diff --git a/.gitignore b/.gitignore
index 42fa0d5626a9..f4c0b091dcf4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,7 +22,6 @@
 *.lst
 *.symtypes
 *.order
-modules.builtin
 *.elf
 *.bin
 *.gz
@@ -33,6 +32,8 @@ modules.builtin
 *.lzo
 *.patch
 *.gcno
+modules.builtin
+Module.symvers
 
 #
 # Top-level generic files
@@ -44,7 +45,6 @@ modules.builtin
 /vmlinuz
 /System.map
 /Module.markers
-/Module.symvers
 
 #
 # Debian directory (make deb-pkg)
diff --git a/CREDITS b/CREDITS
index c322dcfb926d..ce275b6f4873 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1377,6 +1377,9 @@ S: 17 rue Danton
 S: F - 94270 Le Kremlin-Bicêtre
 S: France
 
+N: Jack Hammer
+D: IBM ServeRAID RAID (ips) driver maintenance
+
 N: Greg Hankins
 E: gregh@cc.gatech.edu
 D: fixed keyboard driver to separate LED and locking status
@@ -1687,6 +1690,10 @@ S: Reading
 S: RG6 2NU
 S: United Kingdom
 
+N: Dave Jeffery
+E: dhjeffery@gmail.com
+D: SCSI hacks and IBM ServeRAID RAID driver maintenance
+
 N: Jakub Jelinek
 E: jakub@redhat.com
 W: http://sunsite.mff.cuni.cz/~jj
diff --git a/Documentation/ABI/testing/sysfs-class-bdi b/Documentation/ABI/testing/sysfs-class-bdi
index d773d5697cf5..3187a18af6da 100644
--- a/Documentation/ABI/testing/sysfs-class-bdi
+++ b/Documentation/ABI/testing/sysfs-class-bdi
@@ -53,3 +53,11 @@ stable_pages_required (read-only)
 
 	If set, the backing device requires that all pages comprising a write
 	request must not be changed until writeout is complete.
+
+strictlimit (read-write)
+
+	Forces per-BDI checks for the share of given device in the write-back
+	cache even before the global background dirty limit is reached. This
+	is useful in situations where the global limit is much higher than
+	affordable for given relatively slow (or untrusted) device. Turning
+	strictlimit on has no visible effect if max_ratio is equal to 100%.
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-thingm b/Documentation/ABI/testing/sysfs-driver-hid-thingm
deleted file mode 100644
index abcffeedd20a..000000000000
--- a/Documentation/ABI/testing/sysfs-driver-hid-thingm
+++ /dev/null
@@ -1,23 +0,0 @@
-What:		/sys/class/leds/blink1::<serial>/rgb
-Date:		January 2013
-Contact:	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
-Description:	The ThingM blink1 is an USB RGB LED. The color notation is
-		3-byte hexadecimal. Read this attribute to get the last set
-		color. Write the 24-bit hexadecimal color to change the current
-		LED color. The default color is full white (0xFFFFFF).
-		For instance, set the color to green with: echo 00FF00 > rgb
-
-What:		/sys/class/leds/blink1::<serial>/fade
-Date:		January 2013
-Contact:	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
-Description:	This attribute allows to set a fade time in milliseconds for
-		the next color change. Read the attribute to know the current
-		fade time. The default value is set to 0 (no fade time). For
-		instance, set a fade time of 2 seconds with: echo 2000 > fade
-
-What:		/sys/class/leds/blink1::<serial>/play
-Date:		January 2013
-Contact:	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
-Description:	This attribute is used to play/pause the light patterns. Write 1
-		to start playing, 0 to stop. Reading this attribute returns the
-		current playing status.
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index f5170082bdb3..cc63f30de166 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -276,7 +276,7 @@ X!Isound/sound_firmware.c
      </para>
 
      <sect1><title>Frame Buffer Memory</title>
-!Edrivers/video/fbmem.c
+!Edrivers/video/fbdev/core/fbmem.c
      </sect1>
 <!--
      <sect1><title>Frame Buffer Console</title>
@@ -284,7 +284,7 @@ X!Edrivers/video/console/fbcon.c
      </sect1>
 -->
      <sect1><title>Frame Buffer Colormap</title>
-!Edrivers/video/fbcmap.c
+!Edrivers/video/fbdev/core/fbcmap.c
      </sect1>
 <!-- FIXME:
   drivers/video/fbgen.c has no docs, which stuffs up the sgml.  Comment
@@ -294,11 +294,11 @@ X!Idrivers/video/fbgen.c
      </sect1>
 KAO -->
      <sect1><title>Frame Buffer Video Mode Database</title>
-!Idrivers/video/modedb.c
-!Edrivers/video/modedb.c
+!Idrivers/video/fbdev/core/modedb.c
+!Edrivers/video/fbdev/core/modedb.c
      </sect1>
      <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
-!Edrivers/video/macmodes.c
+!Edrivers/video/fbdev/macmodes.c
      </sect1>
      <sect1><title>Frame Buffer Fonts</title>
         <para>
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 2a8e89e13e45..7e9abb8a276b 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -132,6 +132,20 @@ Example:
 	platform_set_drvdata(), but left the variable "dev" unused,
 	delete it.
 
+If your patch fixes a bug in a specific commit, e.g. you found an issue using
+git-bisect, please use the 'Fixes:' tag with the first 12 characters of the
+SHA-1 ID, and the one line summary.
+Example:
+
+	Fixes: e21d2170f366 ("video: remove unnecessary platform_set_drvdata()")
+
+The following git-config settings can be used to add a pretty format for
+outputting the above style in the git log or git show commands
+
+	[core]
+		abbrev = 12
+	[pretty]
+		fixes = Fixes: %h (\"%s\")
 
 3) Separate your changes.
 
@@ -443,7 +457,7 @@ person it names.  This tag documents that potentially interested parties
 have been included in the discussion
 
 
-14) Using Reported-by:, Tested-by:, Reviewed-by: and Suggested-by:
+14) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes:
 
 If this patch fixes a problem reported by somebody else, consider adding a
 Reported-by: tag to credit the reporter for their contribution.  Please
@@ -498,6 +512,12 @@ idea was not posted in a public forum. That said, if we diligently credit our
 idea reporters, they will, hopefully, be inspired to help us again in the
 future.
 
+A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
+is used to make it easy to determine where a bug originated, which can help
+review a bug fix. This tag also assists the stable kernel team in determining
+which stable kernel versions should receive your fix. This is the preferred
+method for indicating a bug fixed by the patch. See #2 above for more details.
+
 
 15) The canonical patch format
 
diff --git a/Documentation/arm/Marvell/README b/Documentation/arm/Marvell/README
index 963ec445e15a..2cce5401e323 100644
--- a/Documentation/arm/Marvell/README
+++ b/Documentation/arm/Marvell/README
@@ -234,6 +234,11 @@ Berlin family (Digital Entertainment)
 		Core:		Marvell PJ4B (ARMv7), Tauros3 L2CC
 		Homepage:	http://www.marvell.com/digital-entertainment/armada-1500/
 		Product Brief:	http://www.marvell.com/digital-entertainment/armada-1500/assets/Marvell-ARMADA-1500-Product-Brief.pdf
+	88DE3114, Armada 1500 Pro
+		Design name:	BG2-Q
+		Core:		Quad Core ARM Cortex-A9, PL310 L2CC
+		Homepage:	http://www.marvell.com/digital-entertainment/armada-1500-pro/
+		Product Brief:	http://www.marvell.com/digital-entertainment/armada-1500-pro/assets/Marvell_ARMADA_1500_PRO-01_product_brief.pdf
 	88DE????
 		Design name:	BG3
 		Core:		ARM Cortex-A15, CA15 integrated L2CC
diff --git a/Documentation/devicetree/bindings/arm/marvell,berlin.txt b/Documentation/devicetree/bindings/arm/marvell,berlin.txt
index 737afa5f8148..0677003e1476 100644
--- a/Documentation/devicetree/bindings/arm/marvell,berlin.txt
+++ b/Documentation/devicetree/bindings/arm/marvell,berlin.txt
@@ -12,6 +12,7 @@ SoC and board used. Currently known SoC compatibles are:
     "marvell,berlin2"      for Marvell Armada 1500 (BG2, 88DE3100),
     "marvell,berlin2cd"    for Marvell Armada 1500-mini (BG2CD, 88DE3005)
     "marvell,berlin2ct"    for Marvell Armada ? (BG2CT, 88DE????)
+    "marvell,berlin2q"     for Marvell Armada 1500-pro (BG2Q, 88DE3114)
     "marvell,berlin3"      for Marvell Armada ? (BG3, 88DE????)
 
 * Example:
diff --git a/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt b/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt
new file mode 100644
index 000000000000..925ecbf6e7b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt
@@ -0,0 +1,97 @@
+Marvell Kirkwood SoC Family Device Tree Bindings
+------------------------------------------------
+
+Boards with a SoC of the Marvell Kirkwook family, eg 88f6281
+
+* Required root node properties:
+compatible: must contain "marvell,kirkwood"
+
+In addition, the above compatible shall be extended with the specific
+SoC. Currently known SoC compatibles are:
+
+"marvell,kirkwood-88f6192"
+"marvell,kirkwood-88f6281"
+"marvell,kirkwood-88f6282"
+"marvell,kirkwood-88f6283"
+"marvell,kirkwood-88f6702"
+"marvell,kirkwood-98DX4122"
+
+And in addition, the compatible shall be extended with the specific
+board. Currently known boards are:
+
+"buffalo,lschlv2"
+"buffalo,lsxhl"
+"buffalo,lsxl"
+"dlink,dns-320"
+"dlink,dns-320-a1"
+"dlink,dns-325"
+"dlink,dns-325-a1"
+"dlink,dns-kirkwood"
+"excito,b3"
+"globalscale,dreamplug-003-ds2001"
+"globalscale,guruplug"
+"globalscale,guruplug-server-plus"
+"globalscale,sheevaplug"
+"globalscale,sheevaplug"
+"globalscale,sheevaplug-esata"
+"globalscale,sheevaplug-esata-rev13"
+"iom,iconnect"
+"iom,iconnect-1.1"
+"iom,ix2-200"
+"keymile,km_kirkwood"
+"lacie,cloudbox"
+"lacie,inetspace_v2"
+"lacie,laplug"
+"lacie,netspace_lite_v2"
+"lacie,netspace_max_v2"
+"lacie,netspace_mini_v2"
+"lacie,netspace_v2"
+"marvell,db-88f6281-bp"
+"marvell,db-88f6282-bp"
+"marvell,mv88f6281gtw-ge"
+"marvell,rd88f6281"
+"marvell,rd88f6281"
+"marvell,rd88f6281-a0"
+"marvell,rd88f6281-a1"
+"mpl,cec4"
+"mpl,cec4-10"
+"netgear,readynas"
+"netgear,readynas"
+"netgear,readynas-duo-v2"
+"netgear,readynas-nv+-v2"
+"plathome,openblocks-a6"
+"plathome,openblocks-a7"
+"raidsonic,ib-nas6210"
+"raidsonic,ib-nas6210-b"
+"raidsonic,ib-nas6220"
+"raidsonic,ib-nas6220-b"
+"raidsonic,ib-nas62x0"
+"seagate,dockstar"
+"seagate,goflexnet"
+"synology,ds109"
+"synology,ds110jv10"
+"synology,ds110jv20"
+"synology,ds110jv30"
+"synology,ds111"
+"synology,ds209"
+"synology,ds210jv10"
+"synology,ds210jv20"
+"synology,ds212"
+"synology,ds212jv10"
+"synology,ds212jv20"
+"synology,ds212pv10"
+"synology,ds409"
+"synology,ds409slim"
+"synology,ds410j"
+"synology,ds411"
+"synology,ds411j"
+"synology,ds411slim"
+"synology,ds413jv10"
+"synology,rs212"
+"synology,rs409"
+"synology,rs411"
+"synology,rs812"
+"usi,topkick"
+"usi,topkick-1281P2"
+"zyxel,nsa310"
+"zyxel,nsa310a"
diff --git a/Documentation/devicetree/bindings/clock/imx25-clock.txt b/Documentation/devicetree/bindings/clock/imx25-clock.txt
index db4f2f05c4d0..ceaf31346d5c 100644
--- a/Documentation/devicetree/bindings/clock/imx25-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx25-clock.txt
@@ -139,6 +139,9 @@ clocks and IDs.
 	uart5_ipg		124
 	reserved		125
 	wdt_ipg			126
+	cko_div			127
+	cko_sel			128
+	clo			129
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 71724d026ffa..bef86e57c388 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -13,8 +13,22 @@ ad,ad7414		SMBus/I2C Digital Temperature Sensor in 6-Pin SOT with SMBus Alert an
 ad,adm9240		ADM9240:  Complete System Hardware Monitor for uProcessor-Based Systems
 adi,adt7461		+/-1C TDM Extended Temp Range I.C
 adt7461			+/-1C TDM Extended Temp Range I.C
+adi,adt7473		+/-1C TDM Extended Temp Range I.C
+adi,adt7475		+/-1C TDM Extended Temp Range I.C
+adi,adt7476		+/-1C TDM Extended Temp Range I.C
+adi,adt7490		+/-1C TDM Extended Temp Range I.C
 at,24c08		i2c serial eeprom  (24cxx)
+atmel,24c00		i2c serial eeprom  (24cxx)
+atmel,24c01		i2c serial eeprom  (24cxx)
 atmel,24c02		i2c serial eeprom  (24cxx)
+atmel,24c04		i2c serial eeprom  (24cxx)
+atmel,24c16		i2c serial eeprom  (24cxx)
+atmel,24c32		i2c serial eeprom  (24cxx)
+atmel,24c64		i2c serial eeprom  (24cxx)
+atmel,24c128		i2c serial eeprom  (24cxx)
+atmel,24c256		i2c serial eeprom  (24cxx)
+atmel,24c512		i2c serial eeprom  (24cxx)
+atmel,24c1024		i2c serial eeprom  (24cxx)
 atmel,at97sc3204t	i2c trusted platform module (TPM)
 capella,cm32181		CM32181: Ambient Light Sensor
 catalyst,24c32		i2c serial eeprom
@@ -46,8 +60,10 @@ maxim,ds1050		5 Bit Programmable, Pulse-Width Modulator
 maxim,max1237		Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
 maxim,max6625		9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
 mc,rv3029c2		Real Time Clock Module with I2C-Bus
+national,lm63		Temperature sensor with integrated fan control
 national,lm75		I2C TEMP SENSOR
 national,lm80		Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
+national,lm85		Temperature sensor with integrated fan control
 national,lm92		±0.33°C Accurate, 12-Bit + Sign Temperature Sensor and Thermal Window Comparator with Two-Wire Interface
 nuvoton,npct501		i2c trusted platform module (TPM)
 nxp,pca9556		Octal SMBus and I2C registered interface
diff --git a/Documentation/devicetree/bindings/leds/leds-pwm.txt b/Documentation/devicetree/bindings/leds/leds-pwm.txt
index 7297107cf832..6c6583c35f2f 100644
--- a/Documentation/devicetree/bindings/leds/leds-pwm.txt
+++ b/Documentation/devicetree/bindings/leds/leds-pwm.txt
@@ -13,6 +13,8 @@ LED sub-node properties:
   For the pwms and pwm-names property please refer to:
   Documentation/devicetree/bindings/pwm/pwm.txt
 - max-brightness : Maximum brightness possible for the LED
+- active-low : (optional) For PWMs where the LED is wired to supply
+  rather than ground.
 - label :  (optional)
   see Documentation/devicetree/bindings/leds/common.txt
 - linux,default-trigger :  (optional)
diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt b/Documentation/devicetree/bindings/mfd/s2mps11.txt
index 802e839b0829..d81ba30c0d8b 100644
--- a/Documentation/devicetree/bindings/mfd/s2mps11.txt
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -56,6 +56,20 @@ for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
 Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
 BUCK[3, 4], and BUCK[7, 8, 10]
 
+On S2MPS14 the LDO10, LDO11 and LDO12 can be configured to external control
+over GPIO. To turn this feature on this property must be added to the regulator
+sub-node:
+	- samsung,ext-control-gpios: GPIO specifier for one GPIO
+		controlling this regulator (enable/disable);
+Example:
+	LDO12 {
+		regulator-name = "V_EMMC_2.8V";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		samsung,ext-control-gpios = <&gpk0 2 0>;
+	};
+
+
 The regulator constraints inside the regulator nodes use the standard regulator
 bindings which are documented elsewhere.
 
diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt
index 9ecd43d8792c..3fc360523bc9 100644
--- a/Documentation/devicetree/bindings/net/ethernet.txt
+++ b/Documentation/devicetree/bindings/net/ethernet.txt
@@ -10,7 +10,7 @@ The following properties are common to the Ethernet controllers:
 - max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than
   the maximum frame size (there's contradiction in ePAPR).
 - phy-mode: string, operation mode of the PHY interface; supported values are
-  "mii", "gmii", "sgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id",
+  "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id",
   "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto
   standard property;
 - phy-connection-type: the same as "phy-mode" property but described in ePAPR;
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt
index c119debe6bab..67a5db95f189 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt
@@ -119,7 +119,7 @@ Optional Properties (for HDMI pins):
 Example:
 // pin controller node
 pinctrl@35004800 {
-	compatible = "brcmbcm11351-pinctrl";
+	compatible = "brcm,bcm11351-pinctrl";
 	reg = <0x35004800 0x430>;
 
 	// pin configuration node
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
new file mode 100644
index 000000000000..7181f925acaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
@@ -0,0 +1,88 @@
+Qualcomm APQ8064 TLMM block
+
+Required properties:
+- compatible: "qcom,apq8064-pinctrl"
+- reg: Should be the base address and length of the TLMM block.
+- interrupts: Should be the parent IRQ of the TLMM block.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells: Should be two.
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells : Should be two.
+                The first cell is the gpio pin number and the
+                second cell is used for optional parameters.
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Qualcomm's pin configuration nodes act as a container for an abitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+ pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength,
+ output-low, output-high.
+
+Non-empty subnodes must specify the 'pins' property.
+
+Valid values for pins are:
+  gpio0-gpio89
+
+Valid values for function are:
+  cam_mclk, codec_mic_i2s, codec_spkr_i2s, gsbi1, gsbi2, gsbi3, gsbi4,
+  gsbi4_cam_i2c, gsbi5, gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6,
+  gsbi6_spi_cs1, gsbi6_spi_cs2, gsbi6_spi_cs3, gsbi7, gsbi7_spi_cs1,
+  gsbi7_spi_cs2, gsbi7_spi_cs3, gsbi_cam_i2c, hdmi, mi2s, riva_bt, riva_fm,
+  riva_wlan, sdc2, sdc4, slimbus, spkr_i2s, tsif1, tsif2, usb2_hsic,
+
+Example:
+
+	msmgpio: pinctrl@800000 {
+		compatible = "qcom,apq8064-pinctrl";
+		reg = <0x800000 0x4000>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupts = <0 32 0x4>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&gsbi5_uart_default>;
+
+		gsbi5_uart_default: gsbi5_uart_default {
+			mux {
+				pins = "gpio51", "gpio52";
+				function = "gsbi5";
+			};
+
+			tx {
+				pins = "gpio51";
+				drive-strength = <4>;
+				bias-disable;
+			};
+
+			rx {
+				pins = "gpio52";
+				drive-strength = <2>;
+				bias-pull-up;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/rtc/xgene-rtc.txt b/Documentation/devicetree/bindings/rtc/xgene-rtc.txt
new file mode 100644
index 000000000000..fd195c358446
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/xgene-rtc.txt
@@ -0,0 +1,28 @@
+* APM X-Gene Real Time Clock
+
+RTC controller for the APM X-Gene Real Time Clock
+
+Required properties:
+- compatible : Should be "apm,xgene-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: IRQ line for the RTC.
+- #clock-cells: Should be 1.
+- clocks: Reference to the clock entry.
+
+Example:
+
+rtcclk: rtcclk {
+	compatible = "fixed-clock";
+	#clock-cells = <1>;
+	clock-frequency = <100000000>;
+	clock-output-names = "rtcclk";
+};
+
+rtc: rtc@10510000 {
+	compatible = "apm,xgene-rtc";
+	reg = <0x0 0x10510000 0x0 0x400>;
+	interrupts = <0x0 0x46 0x4>;
+	#clock-cells = <1>;
+	clocks = <&rtcclk 0>;
+};
diff --git a/Documentation/devicetree/bindings/serial/efm32-uart.txt b/Documentation/devicetree/bindings/serial/efm32-uart.txt
index 1984bdfbd545..3ca01336b837 100644
--- a/Documentation/devicetree/bindings/serial/efm32-uart.txt
+++ b/Documentation/devicetree/bindings/serial/efm32-uart.txt
@@ -1,7 +1,7 @@
 * Energymicro efm32 UART
 
 Required properties:
-- compatible : Should be "efm32,uart"
+- compatible : Should be "energymicro,efm32-uart"
 - reg : Address and length of the register set
 - interrupts : Should contain uart interrupt
 
@@ -13,7 +13,7 @@ Optional properties:
 Example:
 
 uart@0x4000c400 {
-	compatible = "efm32,uart";
+	compatible = "energymicro,efm32-uart";
 	reg = <0x4000c400 0x400>;
 	interrupts = <15>;
 	efm32,location = <0>;
diff --git a/Documentation/devicetree/bindings/sound/ak5386.txt b/Documentation/devicetree/bindings/sound/ak5386.txt
index dc3914fe6ce8..ec3df3abba0c 100644
--- a/Documentation/devicetree/bindings/sound/ak5386.txt
+++ b/Documentation/devicetree/bindings/sound/ak5386.txt
@@ -10,10 +10,14 @@ Optional properties:
 
   - reset-gpio : a GPIO spec for the reset/power down pin.
 		 If specified, it will be deasserted at probe time.
+  - va-supply : a regulator spec, providing 5.0V
+  - vd-supply : a regulator spec, providing 3.3V
 
 Example:
 
 spdif: ak5386@0 {
 	compatible = "asahi-kasei,ak5386";
 	reset-gpio = <&gpio0 23>;
+	va-supply = <&vdd_5v0_reg>;
+	vd-supply = <&vdd_3v3_reg>;
 };
diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt
index 98611a6761c0..0f4e23828190 100644
--- a/Documentation/devicetree/bindings/sound/fsl-sai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt
@@ -7,10 +7,11 @@ codec/DSP interfaces.
 
 
 Required properties:
-- compatible: Compatible list, contains "fsl,vf610-sai".
+- compatible: Compatible list, contains "fsl,vf610-sai" or "fsl,imx6sx-sai".
 - reg: Offset and length of the register set for the device.
 - clocks: Must contain an entry for each entry in clock-names.
-- clock-names : Must include the "sai" entry.
+- clock-names : Must include the "bus" for register access and "mclk1" "mclk2"
+  "mclk3" for bit clock and frame clock providing.
 - dmas : Generic dma devicetree binding as described in
   Documentation/devicetree/bindings/dma/dma.txt.
 - dma-names : Two dmas have to be defined, "tx" and "rx".
@@ -30,8 +31,10 @@ sai2: sai@40031000 {
 	      reg = <0x40031000 0x1000>;
 	      pinctrl-names = "default";
 	      pinctrl-0 = <&pinctrl_sai2_1>;
-	      clocks = <&clks VF610_CLK_SAI2>;
-	      clock-names = "sai";
+	      clocks = <&clks VF610_CLK_PLATFORM_BUS>,
+		     <&clks VF610_CLK_SAI2>,
+		     <&clks 0>, <&clks 0>;
+	      clock-names = "bus", "mclk1", "mclk2", "mclk3";
 	      dma-names = "tx", "rx";
 	      dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
 		   <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt
index 068a1141b06f..bac4d9ac1edc 100644
--- a/Documentation/devicetree/bindings/sound/rt5640.txt
+++ b/Documentation/devicetree/bindings/sound/rt5640.txt
@@ -1,10 +1,10 @@
-RT5640 audio CODEC
+RT5640/RT5639 audio CODEC
 
 This device supports I2C only.
 
 Required properties:
 
-- compatible : "realtek,rt5640".
+- compatible : One of "realtek,rt5640" or "realtek,rt5639".
 
 - reg : The I2C address of the device.
 
@@ -18,7 +18,7 @@ Optional properties:
 
 - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
 
-Pins on the device (for linking into audio routes):
+Pins on the device (for linking into audio routes) for RT5639/RT5640:
 
   * DMIC1
   * DMIC2
@@ -31,13 +31,16 @@ Pins on the device (for linking into audio routes):
   * HPOR
   * LOUTL
   * LOUTR
-  * MONOP
-  * MONON
   * SPOLP
   * SPOLN
   * SPORP
   * SPORN
 
+Additional pins on the device for RT5640:
+
+  * MONOP
+  * MONON
+
 Example:
 
 rt5640 {
diff --git a/Documentation/devicetree/bindings/sound/st,sta350.txt b/Documentation/devicetree/bindings/sound/st,sta350.txt
new file mode 100644
index 000000000000..950188891abd
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,sta350.txt
@@ -0,0 +1,107 @@
+STA350 audio CODEC
+
+The driver for this device only supports I2C.
+
+Required properties:
+
+  - compatible: "st,sta350"
+  - reg: the I2C address of the device for I2C
+  - reset-gpios: a GPIO spec for the reset pin. If specified, it will be
+		 deasserted before communication to the codec starts.
+
+  - power-down-gpios: a GPIO spec for the power down pin. If specified,
+		      it will be deasserted before communication to the codec
+		      starts.
+
+  - vdd-dig-supply: regulator spec, providing 3.3V
+  - vdd-pll-supply: regulator spec, providing 3.3V
+  - vcc-supply: regulator spec, providing 5V - 26V
+
+Optional properties:
+
+  -  st,output-conf: number, Selects the output configuration:
+	0: 2-channel (full-bridge) power, 2-channel data-out
+	1: 2 (half-bridge). 1 (full-bridge) on-board power
+	2: 2 Channel (Full-Bridge) Power, 1 Channel FFX
+	3: 1 Channel Mono-Parallel
+	If parameter is missing, mode 0 will be enabled.
+
+  -  st,ch1-output-mapping: Channel 1 output mapping
+  -  st,ch2-output-mapping: Channel 2 output mapping
+  -  st,ch3-output-mapping: Channel 3 output mapping
+	0: Channel 1
+	1: Channel 2
+	2: Channel 3
+	If parameter is missing, channel 1 is choosen.
+
+  -  st,thermal-warning-recover:
+	If present, thermal warning recovery is enabled.
+
+  -  st,thermal-warning-adjustment:
+	If present, thermal warning adjustment is enabled.
+
+  -  st,fault-detect-recovery:
+	If present, then fault recovery will be enabled.
+
+  -  st,ffx-power-output-mode: string
+	The FFX power output mode selects how the FFX output timing is
+	configured. Must be one of these values:
+	  -  "drop-compensation"
+	  -  "tapered-compensation"
+	  -  "full-power-mode"
+	  -  "variable-drop-compensation" (default)
+
+  -  st,drop-compensation-ns: number
+	Only required for "st,ffx-power-output-mode" ==
+	"variable-drop-compensation".
+	Specifies the drop compensation in nanoseconds.
+	The value must be in the range of 0..300, and only
+	multiples of 20 are allowed. Default is 140ns.
+
+  -  st,overcurrent-warning-adjustment:
+	If present, overcurrent warning adjustment is enabled.
+
+  -  st,max-power-use-mpcc:
+	If present, then MPCC bits are used for MPC coefficients,
+	otherwise standard MPC coefficients are used.
+
+  -  st,max-power-corr:
+	If present, power bridge correction for THD reduction near maximum
+	power output is enabled.
+
+  -  st,am-reduction-mode:
+	If present, FFX mode runs in AM reduction mode, otherwise normal
+	FFX mode is used.
+
+  -  st,odd-pwm-speed-mode:
+	If present, PWM speed mode run on odd speed mode (341.3 kHz) on all
+	channels. If not present, normal PWM spped mode (384 kHz) will be used.
+
+  -  st,distortion-compensation:
+	If present, distortion compensation variable uses DCC coefficient.
+	If not present, preset DC coefficient is used.
+
+  -  st,invalid-input-detect-mute:
+	If not present, automatic invalid input detect mute is enabled.
+
+
+
+Example:
+
+codec: sta350@38 {
+	compatible = "st,sta350";
+	reg = <0x1c>;
+	reset-gpios = <&gpio1 19 0>;
+	power-down-gpios = <&gpio1 16 0>;
+	st,output-conf = <0x3>;			// set output to 2-channel
+						// (full-bridge) power,
+						// 2-channel data-out
+	st,ch1-output-mapping = <0>;		// set channel 1 output ch 1
+	st,ch2-output-mapping = <0>;		// set channel 2 output ch 1
+	st,ch3-output-mapping = <0>;		// set channel 3 output ch 1
+	st,max-power-correction;		// enables power bridge
+						// correction for THD reduction
+						// near maximum power output
+	st,invalid-input-detect-mute;		// mute if no valid digital
+						// audio signal is provided.
+};
diff --git a/Documentation/devicetree/bindings/spi/fsl-spi.txt b/Documentation/devicetree/bindings/spi/fsl-spi.txt
index b032dd76e9d2..a2331372068c 100644
--- a/Documentation/devicetree/bindings/spi/fsl-spi.txt
+++ b/Documentation/devicetree/bindings/spi/fsl-spi.txt
@@ -42,6 +42,10 @@ Required properties:
 - interrupts : should contain eSPI interrupt, the device has one interrupt.
 - fsl,espi-num-chipselects : the number of the chipselect signals.
 
+Optional properties:
+- fsl,csbef: chip select assertion time in bits before frame starts
+- fsl,csaft: chip select negation time in bits after frame ends
+
 Example:
 	spi@110000 {
 		#address-cells = <1>;
@@ -51,4 +55,6 @@ Example:
 		interrupts = <53 0x2>;
 		interrupt-parent = <&mpic>;
 		fsl,espi-num-chipselects = <4>;
+		fsl,csbef = <1>;
+		fsl,csaft = <1>;
 	};
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index e5a4d1b4acfe..22d57404fdc3 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -55,6 +55,8 @@ contain the following properties.
     		chip select active high
 - spi-3wire       - (optional) Empty property indicating device requires
     		    3-wire mode.
+- spi-lsb-first   - (optional) Empty property indicating device requires
+		LSB first mode.
 - spi-tx-bus-width - (optional) The bus width(number of data wires) that
                       used for MOSI. Defaults to 1 if not present.
 - spi-rx-bus-width - (optional) The bus width(number of data wires) that
diff --git a/Documentation/devicetree/bindings/spi/spi-cadence.txt b/Documentation/devicetree/bindings/spi/spi-cadence.txt
new file mode 100644
index 000000000000..94f09141a4f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-cadence.txt
@@ -0,0 +1,31 @@
+Cadence SPI controller Device Tree Bindings
+-------------------------------------------
+
+Required properties:
+- compatible		: Should be "cdns,spi-r1p6" or "xlnx,zynq-spi-r1p6".
+- reg			: Physical base address and size of SPI registers map.
+- interrupts		: Property with a value describing the interrupt
+			  number.
+- interrupt-parent	: Must be core interrupt controller
+- clock-names		: List of input clock names - "ref_clk", "pclk"
+			  (See clock bindings for details).
+- clocks		: Clock phandles (see clock bindings for details).
+
+Optional properties:
+- num-cs		: Number of chip selects used.
+			  If a decoder is used, this will be the number of
+			  chip selects after the decoder.
+- is-decoded-cs		: Flag to indicate whether decoder is used or not.
+
+Example:
+
+	spi@e0007000 {
+		compatible = "xlnx,zynq-spi-r1p6";
+		clock-names = "ref_clk", "pclk";
+		clocks = <&clkc 26>, <&clkc 35>;
+		interrupt-parent = <&intc>;
+		interrupts = <0 49 4>;
+		num-cs = <4>;
+		is-decoded-cs = <0>;
+		reg = <0xe0007000 0x1000>;
+	} ;
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0f01c9bf19c8..285500407a43 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -22,6 +22,7 @@ auo	AU Optronics Corporation
 avago	Avago Technologies
 bosch	Bosch Sensortec GmbH
 brcm	Broadcom Corporation
+buffalo	Buffalo, Inc.
 calxeda	Calxeda
 capella	Capella Microsystems, Inc
 cavium	Cavium, Inc.
@@ -33,15 +34,18 @@ cortina	Cortina Systems, Inc.
 crystalfontz	Crystalfontz America, Inc.
 dallas	Maxim Integrated Products (formerly Dallas Semiconductor)
 davicom	DAVICOM Semiconductor, Inc.
-dlink	D-Link Systems, Inc.
 denx	Denx Software Engineering
+digi	Digi International Inc.
+dlink	D-Link Corporation
 dmo	Data Modul AG
+ebv	EBV Elektronik
 edt	Emerging Display Technologies
 emmicro	EM Microelectronic
 epfl	Ecole Polytechnique Fédérale de Lausanne
 epson	Seiko Epson Corp.
 est	ESTeem Wireless Modems
 eukrea  Eukréa Electromatique
+excito	Excito
 fsl	Freescale Semiconductor
 GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
@@ -53,13 +57,17 @@ haoyu	Haoyu Microelectronic Co. Ltd.
 hisilicon	Hisilicon Limited.
 honeywell	Honeywell
 hp	Hewlett Packard
+i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
+iom	Iomega Corporation
 img	Imagination Technologies Ltd.
 intel	Intel Corporation
 intercontrol	Inter Control Group
+isee	ISEE 2007 S.L.
 isl	Intersil
 karo	Ka-Ro electronics GmbH
+keymile	Keymile GmbH
 lacie	LaCie
 lantiq	Lantiq Semiconductor
 lg	LG Corporation
@@ -70,9 +78,12 @@ maxim	Maxim Integrated Products
 microchip	Microchip Technology Inc.
 mosaixtech	Mosaix Technologies, Inc.
 moxa	Moxa
+mpl	MPL AG
+mxicy	Macronix International Co., Ltd.
 national	National Semiconductor
 neonode		Neonode Inc.
 netgear	NETGEAR
+newhaven	Newhaven Display International
 nintendo	Nintendo
 nokia	Nokia
 nvidia	NVIDIA
@@ -82,10 +93,12 @@ opencores	OpenCores.org
 panasonic	Panasonic Corporation
 phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
+plathome	Plat'Home Co., Ltd.
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
 qnap	QNAP Systems, Inc.
+raidsonic	RaidSonic Technology GmbH
 ralink	Mediatek/Ralink Technology Corp.
 ramtron	Ramtron International
 realtek Realtek Semiconductor Corp.
@@ -95,6 +108,7 @@ rockchip	Fuzhou Rockchip Electronics Co., Ltd
 samsung	Samsung Semiconductor
 sbs	Smart Battery System
 schindler	Schindler
+seagate	Seagate Technology PLC
 sil	Silicon Image
 silabs	Silicon Laboratories
 simtek
@@ -109,8 +123,10 @@ stericsson	ST-Ericsson
 synology	Synology, Inc.
 ti	Texas Instruments
 tlm	Trusted Logic Mobility
+toradex	Toradex AG
 toshiba	Toshiba Corporation
 toumaz	Toumaz
+usi	Universal Scientifc Industrial Co., Ltd.
 v3	V3 Semiconductor
 via	VIA Technologies, Inc.
 voipac	Voipac Technologies s.r.o.
@@ -119,3 +135,4 @@ wlf	Wolfson Microelectronics
 wm	Wondermedia Technologies, Inc.
 xes	Extreme Engineering Solutions (X-ES)
 xlnx	Xilinx
+zyxel	ZyXEL Communications Corp.
diff --git a/Documentation/email-clients.txt b/Documentation/email-clients.txt
index e9f5daccbd02..4e30ebaa9e5b 100644
--- a/Documentation/email-clients.txt
+++ b/Documentation/email-clients.txt
@@ -201,20 +201,15 @@ To beat some sense out of the internal editor, do this:
 
 - Edit your Thunderbird config settings so that it won't use format=flowed.
   Go to "edit->preferences->advanced->config editor" to bring up the
-  thunderbird's registry editor, and set "mailnews.send_plaintext_flowed" to
-  "false".
+  thunderbird's registry editor.
 
-- Disable HTML Format: Set "mail.identity.id1.compose_html" to "false".
+- Set "mailnews.send_plaintext_flowed" to "false"
 
-- Enable "preformat" mode: Set "editor.quotesPreformatted" to "true".
+- Set "mailnews.wraplength" from "72" to "0"
 
-- Enable UTF8: Set "prefs.converted-to-utf8" to "true".
+- "View" > "Message Body As" > "Plain Text"
 
-- Install the "toggle wordwrap" extension.  Download the file from:
-    https://addons.mozilla.org/thunderbird/addon/2351/
-  Then go to "tools->add ons", select "install" at the bottom of the screen,
-  and browse to where you saved the .xul file.  This adds an "Enable
-  Wordwrap" entry under the Options menu of the message composer.
+- "View" > "Character Encoding" > "Unicode (UTF-8)"
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 TkRat (GUI)
diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt
index 4a93e98b290a..5cf57b368dc6 100644
--- a/Documentation/filesystems/vfat.txt
+++ b/Documentation/filesystems/vfat.txt
@@ -175,6 +175,16 @@ nfs=stale_rw|nostale_ro
 
 <bool>: 0,1,yes,no,true,false
 
+LIMITATION
+---------------------------------------------------------------------
+* The fallocated region of file is discarded at umount/evict time
+  when using fallocate with FALLOC_FL_KEEP_SIZE.
+  So, User should assume that fallocated region can be discarded at
+  last close if there is memory pressure resulting in eviction of
+  the inode from the memory. As a result, for any dependency on
+  the fallocated region, user should make sure to recheck fallocate
+  after reopening the file.
+
 TODO
 ----------------------------------------------------------------------
 * Need to get rid of the raw scanning stuff.  Instead, always use
diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
index f73cc7b5dc85..fa9a0a8b3734 100644
--- a/Documentation/gpio/driver.txt
+++ b/Documentation/gpio/driver.txt
@@ -73,6 +73,65 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using
 the header <linux/irq.h>. So basically such a driver is utilizing two sub-
 systems simultaneously: gpio and irq.
 
+GPIO irqchips usually fall in one of two categories:
+
+* CHAINED GPIO irqchips: these are usually the type that is embedded on
+  an SoC. This means that there is a fast IRQ handler for the GPIOs that
+  gets called in a chain from the parent IRQ handler, most typically the
+  system interrupt controller. This means the GPIO irqchip is registered
+  using irq_set_chained_handler() or the corresponding
+  gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
+  handler will be called immediately from the parent irqchip, while
+  holding the IRQs disabled. The GPIO irqchip will then end up calling
+  something like this sequence in its interrupt handler:
+
+  static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+      chained_irq_enter(...);
+      generic_handle_irq(...);
+      chained_irq_exit(...);
+
+  Chained GPIO irqchips typically can NOT set the .can_sleep flag on
+  struct gpio_chip, as everything happens directly in the callbacks.
+
+* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any
+  other GPIO irqchip residing on the other side of a sleeping bus. Of course
+  such drivers that need slow bus traffic to read out IRQ status and similar,
+  traffic which may in turn incur other IRQs to happen, cannot be handled
+  in a quick IRQ handler with IRQs disabled. Instead they need to spawn a
+  thread and then mask the parent IRQ line until the interrupt is handled
+  by the driver. The hallmark of this driver is to call something like
+  this in its interrupt handler:
+
+  static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+      ...
+      handle_nested_irq(irq);
+
+  The hallmark of threaded GPIO irqchips is that they set the .can_sleep
+  flag on struct gpio_chip to true, indicating that this chip may sleep
+  when accessing the GPIOs.
+
+To help out in handling the set-up and management of GPIO irqchips and the
+associated irqdomain and resource allocation callbacks, the gpiolib has
+some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
+symbol:
+
+* gpiochip_irqchip_add(): adds an irqchip to a gpiochip. It will pass
+  the struct gpio_chip* for the chip to all IRQ callbacks, so the callbacks
+  need to embed the gpio_chip in its state container and obtain a pointer
+  to the container using container_of().
+  (See Documentation/driver-model/design-patterns.txt)
+
+* gpiochip_set_chained_irqchip(): sets up a chained irq handler for a
+  gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
+  data. (Notice handler data, since the irqchip data is likely used by the
+  parent irqchip!) This is for the chained type of chip.
+
+To use the helpers please keep the following in mind:
+
+- Make sure to assign all relevant members of the struct gpio_chip so that
+  the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
+  properly.
+
 It is legal for any IRQ consumer to request an IRQ from any irqchip no matter
 if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
 irq_chip are orthogonal, and offering their services independent of each
diff --git a/Documentation/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO
index 0091a8215ac1..b61885c35ce1 100644
--- a/Documentation/ja_JP/HOWTO
+++ b/Documentation/ja_JP/HOWTO
@@ -315,7 +315,7 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー
 もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が
 最新の安定版カーネルです。
 
-3.x.y は "stable" チーム <stable@kernel.org> でメンテされており、必
+3.x.y は "stable" チーム <stable@vger.kernel.org> でメンテされており、必
 要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
 た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
 の場合はこれに対してだいたいの場合、すぐにリリースがされます。
diff --git a/Documentation/ja_JP/stable_kernel_rules.txt b/Documentation/ja_JP/stable_kernel_rules.txt
index 14265837c4ce..9dbda9b5d21e 100644
--- a/Documentation/ja_JP/stable_kernel_rules.txt
+++ b/Documentation/ja_JP/stable_kernel_rules.txt
@@ -50,16 +50,16 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt
 
 -stable ツリーにパッチを送付する手続き-
 
- - 上記の規則に従っているかを確認した後に、stable@kernel.org にパッチ
+ - 上記の規則に従っているかを確認した後に、stable@vger.kernel.org にパッチ
    を送る。
  - 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合
    には NAK を受け取る。この反応は開発者たちのスケジュールによって、数
    日かかる場合がある。
  - もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの
    メンテナーによるレビューのために -stable キューに追加される。
- - パッチに stable@kernel.org のアドレスが付加されているときには、それ
+ - パッチに stable@vger.kernel.org のアドレスが付加されているときには、それ
    が Linus のツリーに入る時に自動的に stable チームに email される。
- - セキュリティパッチはこのエイリアス (stable@kernel.org) に送られるべ
+ - セキュリティパッチはこのエイリアス (stable@vger.kernel.org) に送られるべ
    きではなく、代わりに security@kernel.org のアドレスに送られる。
 
 レビューサイクル-
diff --git a/Documentation/java.txt b/Documentation/java.txt
index e6a723281547..418020584ccc 100644
--- a/Documentation/java.txt
+++ b/Documentation/java.txt
@@ -188,6 +188,9 @@ shift
 #define CP_METHODREF 10
 #define CP_INTERFACEMETHODREF 11
 #define CP_NAMEANDTYPE 12
+#define CP_METHODHANDLE 15
+#define CP_METHODTYPE 16
+#define CP_INVOKEDYNAMIC 18
 
 /* Define some commonly used error messages */
 
@@ -242,14 +245,19 @@ void skip_constant(FILE *classfile, u_int16_t *cur)
 		break;
 	case CP_CLASS:
 	case CP_STRING:
+	case CP_METHODTYPE:
 		seekerr = fseek(classfile, 2, SEEK_CUR);
 		break;
+	case CP_METHODHANDLE:
+		seekerr = fseek(classfile, 3, SEEK_CUR);
+		break;
 	case CP_INTEGER:
 	case CP_FLOAT:
 	case CP_FIELDREF:
 	case CP_METHODREF:
 	case CP_INTERFACEMETHODREF:
 	case CP_NAMEANDTYPE:
+	case CP_INVOKEDYNAMIC:
 		seekerr = fseek(classfile, 4, SEEK_CUR);
 		break;
 	case CP_LONG:
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 03e50b4883a8..7ec22955857d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -804,13 +804,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	dhash_entries=	[KNL]
 			Set number of hash buckets for dentry cache.
 
-	digi=		[HW,SERIAL]
-			IO parameters + enable/disable command.
-
-	digiepca=	[HW,SERIAL]
-			See drivers/char/README.epca and
-			Documentation/serial/digiepca.txt.
-
 	disable=	[IPV6]
 			See Documentation/networking/ipv6.txt.
 
@@ -1294,6 +1287,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			for working out where the kernel is dying during
 			startup.
 
+	initcall_blacklist=  [KNL] Do not execute a comma-separated list of
+			initcall functions.  Useful for debugging built-in
+			modules and initcalls.
+
 	initrd=		[BOOT] Specify the location of the initial ramdisk
 
 	inport.irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver
@@ -2939,9 +2936,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	rhash_entries=	[KNL,NET]
 			Set number of hash buckets for route cache
 
-	riscom8=	[HW,SERIAL]
-			Format: <io_board1>[,<io_board2>[,...<io_boardN>]]
-
 	ro		[KNL] Mount root device read-only on boot
 
 	root=		[KNL] Root filesystem
@@ -3083,9 +3077,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
 			See Documentation/laptops/sonypi.txt
 
-	specialix=	[HW,SERIAL] Specialix multi-serial port adapter
-			See Documentation/serial/specialix.txt.
-
 	spia_io_base=	[HW,MTD]
 	spia_fio_base=
 	spia_pedr=
diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
index 79699c200766..62261c04060a 100644
--- a/Documentation/leds/leds-class.txt
+++ b/Documentation/leds/leds-class.txt
@@ -2,9 +2,6 @@
 LED handling under Linux
 ========================
 
-If you're reading this and thinking about keyboard leds, these are
-handled by the input subsystem and the led class is *not* needed.
-
 In its simplest form, the LED class just allows control of LEDs from
 userspace. LEDs appear in /sys/class/leds/. The maximum brightness of the
 LED is defined in max_brightness file. The brightness file will set the brightness
diff --git a/Documentation/lto-build b/Documentation/lto-build
new file mode 100644
index 000000000000..5dcce1e9cc25
--- /dev/null
+++ b/Documentation/lto-build
@@ -0,0 +1,173 @@
+Link time optimization (LTO) for the Linux kernel
+
+This is an experimental feature.
+
+Link Time Optimization allows the compiler to optimize the complete program
+instead of just each file.  LTO requires at least gcc 4.8 (but
+works more efficiently with 4.9+) LTO requires Linux binutils (the normal FSF
+releases used in many distributions do not work at the moment)
+
+The compiler can inline functions between files and do various other global
+optimizations, like specializing functions for common parameters,
+determing when global variables are clobbered, making functions pure/const,
+propagating constants globally, removing unneeded data and others.
+
+It will also drop unused functions which can make the kernel
+image smaller in some circumstances, in particular for small kernel
+configurations.
+
+For small monolithic kernels it can throw away unused code very effectively
+(especially when modules are disabled) and usually shrinks
+the code size.
+
+Build time and memory consumption at build time will increase, depending
+on the size of the largest binary. Modular kernels are less affected.
+With LTO incremental builds are less incremental, as always the whole
+binary needs to be re-optimized (but not re-parsed)
+
+Oops can be somewhat more difficult to read, due to the more aggressive
+inlining.
+
+Normal "reasonable" builds work with less than 4GB of RAM, but very large
+configurations like allyesconfig may need more memory. The actual
+memory needed depends on the available memory (gcc sizes its garbage
+collector pools based on that or on the ulimit -m limits) and
+the compiler version.
+
+gcc 4.9+ has much better build performance and less memory consumption
+
+- A few kernel features are currently incompatible with LTO, in particular
+function tracing, because they require special compiler flags for
+specific files, which is not supported in LTO right now.
+- Jobserver control for -j does not work correctly for the final
+LTO phase due to some problems with the kernel's pipe code.
+The makefiles hard codes -j<number of online cpus> for the final
+LTO phase to work around for this
+
+Configuration:
+- Enable CONFIG_LTO_MENU and then disable CONFIG_LTO_DISABLE.
+This is mainly to not have allyesconfig default to LTO.
+- FUNCTION_TRACER, STACK_TRACER, FUNCTION_GRAPH_TRACER, KALLSYMS_ALL, GCOV
+have to disabled because they are currently incompatible with LTO.
+- MODVERSIONS have to be disabled (may work with 4.9+)
+
+Requirements:
+- Enough memory: 4GB for a standard build, more for allyesconfig
+The peak memory usage happens single threaded (when lto-wpa merges types),
+so dialing back -j options will not help much.
+
+A 32bit compiler is unlikely to work due to the memory requirements.
+You can however build a kernel targeted at 32bit on a 64bit host.
+
+Example build procedure:
+
+Simplified procedure for distributions that have gcc 4.8, but not
+the Linux binutils (for example openSUSE 13.1 or FC20):
+
+The LTO builds requires gcc-nm/gcc-ar. Some distributions ship
+those in separate packages, which may need to be explicitely installed.
+
+- Get the latest Linux binutils from
+http://www.kernel.org/pub/linux/devel/binutils/
+and unpack it.
+
+We install it in a separate directory to not overwrite the system binutils.
+
+# replace VERSION with respective version numbers
+
+cd binutils*
+# don't forget the --enable-plugins!
+./configure --prefix=/opt/binutils-VERSION --enable-plugins
+make -j $(getconf _NPROCESSORS_ONLN) && sudo make install
+
+Fix up the kernel configuration to allow LTO:
+
+<start with a suitable kernel configuration>
+./source/scripts/config --disable function_tracer \
+			--disable function_graph_tracer \
+			--disable stack_tracer --enable lto_menu \
+                        --disable lto_disable \
+			--disable gcov \
+			--disable kallsyms_all \
+			--disable modversions
+make oldconfig
+
+Then you can build with
+
+# The COMPILER_PATH is needed to let gcc use the new binutils
+# as the LTO plugin linker
+# if you installed gcc in a separate directory like below also
+# add it to the PATH line below before the regular $PATH
+# The COMPILER_PATH setting is only needed if the gcc was not built
+# with --with-plugin-ld pointing to the Linux binutils ld
+# The AR/NM setting works around a Makefile bug
+COMPILER_PATH=/opt/binutils-VERSION/bin PATH=$COMPILER_PATH:$PATH \
+make -j$(getconf _NPROCESSORS_ONLN) AR=gcc-ar NM=gcc-nm
+
+If you don't have gcc 4.8+ as system compiler you would also need
+to install that compiler. In this case I recommend getting
+a gcc 4.9+ snapshot from http://gcc.gnu.org (or release when available),
+as it builds much faster for LTO than 4.8.
+
+Here's an example build procedure:
+
+Assuming gcc is unpacked in gcc-VERSION
+
+cd gcc-VERSION
+./contrib/download_preqrequisites
+cd ..
+
+mkdir obj-gcc
+# please don't skip this cd. the build will not work correctly in the
+# source dir, you have to use the separate object dir
+cd obj-gcc
+../gcc-VERSION/configure --prefix=/opt/gcc-VERSION --enable-lto \
+--with-plugin-ld=/opt/binutils-VERSION/bin/ld
+--disable-nls --enable-languages=c,c++ \
+--disable-libstdcxx-pch
+make -j$(getconf _NPROCESSORS_ONLN)
+sudo make install-no-fixedincludes
+
+FAQs:
+
+Q: I get a section type attribute conflict
+A: Usually because of someone doing
+const __initdata (should be const __initconst) or const __read_mostly
+(should be just const). Check both symbols reported by gcc.
+
+Q: I see lots of undefined symbols for memcmp etc.
+A: Usually because NM=gcc-nm AR=gcc-ar are missing.
+The Makefile tries to set those automatically, but it doesn't always
+work. Better to set it manually on the make command line.
+
+Q: It's quite slow / uses too much memory.
+A: Consider a gcc 4.9 snapshot/release (not released yet)
+The main problem in 4.8 is the type merging in the single threaded WPA pass,
+which has been improved considerably in 4.9 by running it distributed.
+
+Q: It's still slow
+A: It'll always be somewhat slower than non LTO sorry.
+
+Q: What's up with .XXXXX numeric post fixes
+A: This is due LTO turning (near) all symbols to static
+Use gcc 4.9, it avoids them in most cases. They are also filtered out
+in kallsyms.
+
+References:
+
+Presentation on Kernel LTO
+(note, performance numbers/details outdated.  In particular gcc 4.9 fixed
+most of the build time problems):
+http://halobates.de/kernel-lto.pdf
+
+Generic gcc LTO:
+http://www.ucw.cz/~hubicka/slides/labs2013.pdf
+http://www.hipeac.net/system/files/barcelona.pdf
+
+Somewhat outdated too:
+http://gcc.gnu.org/projects/lto/lto.pdf
+http://gcc.gnu.org/projects/lto/whopr.pdf
+
+Happy Link-Time-Optimizing!
+
+Andi Kleen
diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
index 76d80a64bbe1..4c8e142db2ef 100644
--- a/Documentation/magic-number.txt
+++ b/Documentation/magic-number.txt
@@ -63,8 +63,6 @@ Magic Name            Number      Structure            File
 PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
 CMAGIC                0x0111      user              include/linux/a.out.h
 MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
-RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
-SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
 HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
 APM_BIOS_MAGIC        0x4101      apm_user          arch/x86/kernel/apm_32.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
@@ -82,7 +80,6 @@ STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
 X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
 SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
 AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
-ESP_MAGIC             0x53ee      esp_struct        drivers/char/esp.h
 TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
 MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
 TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
@@ -94,13 +91,10 @@ USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
 RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
 USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
 CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
-A2232_MAGIC           0x000a2232  gs_port           drivers/char/ser_a2232.h
 RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
 LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
 GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
 RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
-RIO_MAGIC             0x12345678  gs_port           drivers/char/rio/rio_linux.c
-SX_MAGIC              0x12345678  gs_port           drivers/char/sx.h
 NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
 RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
 BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
@@ -116,7 +110,6 @@ ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
 CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
 ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
 SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
-STLI_BOARDMAGIC       0x4bc6c825  stlibrd           include/linux/istallion.h
 CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
 SLAB_C_MAGIC          0x4f17a36d  kmem_cache        mm/slab.c
 COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
@@ -127,10 +120,8 @@ SCC_MAGIC             0x52696368  gs_port           drivers/char/scc.h
 SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
 GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
 RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
-STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
 EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
 HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
-EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
 PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
 KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
 I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
@@ -142,17 +133,14 @@ SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
 LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
 OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
 M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
-STL_PANELMAGIC        0x7ef621a1  stlpanel          include/linux/stallion.h
 VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
 KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
 PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
 NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
-STL_BOARDMAGIC        0xa2267f52  stlbrd            include/linux/stallion.h
 ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
 SCI_MAGIC             0xbabeface  gs_port           drivers/char/sh-sci.h
 CODA_MAGIC            0xC0DAC0DA  coda_file_info    fs/coda/coda_fs_i.h
 DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
-STLI_PORTMAGIC        0xe671c7a1  stliport          include/linux/istallion.h
 YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
 CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
 QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 6f4eb322ffaf..94459b42e0ab 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -184,6 +184,12 @@ dentry names:
 	equivalent of %s dentry->d_name.name we used to use, %pd<n> prints
 	n last components.  %pD does the same thing for struct file.
 
+task_struct comm name:
+
+        %pT
+
+        For printing task_struct->comm.
+
 struct va_format:
 
 	%pV
diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX
index f9c6b5ed03e7..8021a9f29fc5 100644
--- a/Documentation/serial/00-INDEX
+++ b/Documentation/serial/00-INDEX
@@ -2,23 +2,15 @@
 	- this file.
 README.cycladesZ
 	- info on Cyclades-Z firmware loading.
-digiepca.txt
-	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
 driver
 	- intro to the low level serial driver.
 moxa-smartio
 	- file with info on installing/using Moxa multiport serial driver.
 n_gsm.txt
 	- GSM 0710 tty multiplexer howto.
-riscom8.txt
-	- notes on using the RISCom/8 multi-port serial driver.
 rocket.txt
 	- info on the Comtrol RocketPort multiport serial driver.
 serial-rs485.txt
 	- info about RS485 structures and support in the kernel.
-specialix.txt
-	- info on hardware/driver for specialix IO8+ multiport serial card.
-sx.txt
-	- info on the Specialix SX/SI multiport serial driver.
 tty.txt
 	- guide to the locking policies of the tty layer.
diff --git a/Documentation/serial/digiepca.txt b/Documentation/serial/digiepca.txt
deleted file mode 100644
index f2560e22f2c9..000000000000
--- a/Documentation/serial/digiepca.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-NOTE:  This driver is obsolete.  Digi provides a 2.6 driver (dgdm) at
-http://www.digi.com for PCI cards.  They no longer maintain this driver,
-and have no 2.6 driver for ISA cards.
-
-This driver requires a number of user-space tools.  They can be acquired from
-http://www.digi.com, but only works with 2.4 kernels.
-
-
-The Digi Intl. epca driver. 
-----------------------------
-The Digi Intl. epca driver for Linux supports the following boards:
-
-Digi PC/Xem, PC/Xr, PC/Xe, PC/Xi, PC/Xeve 
-Digi EISA/Xem, PCI/Xem, PCI/Xr 
-
-Limitations:
-------------
-Currently the driver only autoprobes for supported PCI boards. 
-
-The Linux MAKEDEV command does not support generating the Digiboard
-Devices.  Users executing digiConfig to setup EISA and PC series cards
-will have their device nodes automatically constructed (cud?? for ~CLOCAL,
-and ttyD?? for CLOCAL).  Users wishing to boot their board from the LILO
-prompt, or those users booting PCI cards may use buildDIGI to construct 
-the necessary nodes. 
-
-Notes:
-------
-This driver may be configured via LILO.  For users who have already configured
-their driver using digiConfig, configuring from LILO will override previous 
-settings.  Multiple boards may be configured by issuing multiple LILO command 
-lines.  For examples see the bottom of this document.
-
-Device names start at 0 and continue up.  Beware of this as previous Digi 
-drivers started device names with 1.
-
-PCI boards are auto-detected and configured by the driver.  PCI boards will
-be allocated device numbers (internally) beginning with the lowest PCI slot
-first.  In other words a PCI card in slot 3 will always have higher device
-nodes than a PCI card in slot 1. 
-
-LILO config examples:
----------------------
-Using LILO's APPEND command, a string of comma separated identifiers or 
-integers can be used to configure supported boards.  The six values in order 
-are:
-
-   Enable/Disable this card or Override,
-   Type of card: PC/Xe (AccelePort) (0), PC/Xeve (1), PC/Xem or PC/Xr (2), 
-                 EISA/Xem (3), PC/64Xe (4), PC/Xi (5), 
-   Enable/Disable alternate pin arrangement,
-   Number of ports on this card,
-   I/O Port where card is configured (in HEX if using string identifiers),
-   Base of memory window (in HEX if using string identifiers), 
-
-NOTE : PCI boards are auto-detected and configured.  Do not attempt to 
-configure PCI boards with the LILO append command.  If you wish to override
-previous configuration data (As set by digiConfig), but you do not wish to
-configure any specific card (Example if there are PCI cards in the system) 
-the following override command will accomplish this:
--> append="digi=2"
-
-Samples:
-   append="digiepca=E,PC/Xe,D,16,200,D0000"
-                  or
-   append="digi=1,0,0,16,512,851968"
-
-Supporting Tools:
------------------
-Supporting tools include digiDload, digiConfig, buildPCI, and ditty.  See
-drivers/char/README.epca for more details.  Note,
-this driver REQUIRES that digiDload be executed prior to it being used. 
-Failure to do this will result in an ENODEV error.
-
-Documentation:
---------------
-Complete documentation for this product may be found in the tool package. 
-
-Sources of information and support:
------------------------------------
-Digi Intl. support site for this product:
-
-->  http://www.digi.com
-
-Acknowledgments:
-----------------
-Much of this work (And even text) was derived from a similar document 
-supporting the original public domain DigiBoard driver Copyright (C)
-1994,1995 Troy De Jongh.  Many thanks to Christoph Lameter 
-(christoph@lameter.com) and Mike McLagan (mike.mclagan@linux.org) who authored 
-and contributed to the original document. 
-
-Changelog:
-----------
-10-29-04:	Update status of driver, remove dead links in document
-		James Nelson <james4765@gmail.com>
-
-2000 (?)	Original Document
diff --git a/Documentation/serial/riscom8.txt b/Documentation/serial/riscom8.txt
deleted file mode 100644
index 14f61fdad7ca..000000000000
--- a/Documentation/serial/riscom8.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-* NOTE - this is an unmaintained driver.  The original author cannot be located.
-
-SDL Communications is now SBS Technologies, and does not have any
-information on these ancient ISA cards on their website.
-
-James Nelson <james4765@gmail.com> - 12-12-2004
-
-	This is the README for RISCom/8 multi-port serial driver
-	(C) 1994-1996 D.Gorodchanin
-	See file LICENSE for terms and conditions.
-
-NOTE: English is not my native language. 
-      I'm sorry for any mistakes in this text.
-
-Misc. notes for RISCom/8 serial driver, in no particular order :)
-
-1) This driver can support up to 4 boards at time.
-   Use string "riscom8=0xXXX,0xXXX,0xXXX,0xXXX" at LILO prompt, for
-   setting I/O base addresses for boards. If you compile driver
-   as module use modprobe options "iobase=0xXXX iobase1=0xXXX iobase2=..."
-
-2) The driver partially supports famous 'setserial' program, you can use almost
-   any of its options, excluding port & irq settings.
-
-3) There are some misc. defines at the beginning of riscom8.c, please read the 
-   comments and try to change some of them in case of problems.
-
-4) I consider the current state of the driver as BETA.
-
-5) SDL Communications WWW page is http://www.sdlcomm.com.
-
-6) You can use the MAKEDEV program to create RISCom/8 /dev/ttyL* entries.
-
-7) Minor numbers for first board are 0-7, for second 8-15, etc.
-
-22 Apr 1996.
diff --git a/Documentation/serial/specialix.txt b/Documentation/serial/specialix.txt
deleted file mode 100644
index 6eb6f3a3331c..000000000000
--- a/Documentation/serial/specialix.txt
+++ /dev/null
@@ -1,383 +0,0 @@
-
-      specialix.txt  -- specialix IO8+ multiport serial driver readme.
-
-
-
-      Copyright (C) 1997  Roger Wolff (R.E.Wolff@BitWizard.nl)
-
-      Specialix pays for the development and support of this driver.
-      Please DO contact io8-linux@specialix.co.uk if you require
-      support.
-
-      This driver was developed in the BitWizard linux device
-      driver service. If you require a linux device driver for your
-      product, please contact devices@BitWizard.nl for a quote.
-
-      This code is firmly based on the riscom/8 serial driver,
-      written by Dmitry Gorodchanin. The specialix IO8+ card
-      programming information was obtained from the CL-CD1865 Data
-      Book, and Specialix document number 6200059: IO8+ Hardware
-      Functional Specification, augmented by document number 6200088:
-      Merak Hardware Functional Specification. (IO8+/PCI is also 
-      called Merak)
-
-
-      This program is free software; you can redistribute it and/or
-      modify it under the terms of the GNU General Public License as
-      published by the Free Software Foundation; either version 2 of
-      the License, or (at your option) any later version.
-
-      This program is distributed in the hope that it will be
-      useful, but WITHOUT ANY WARRANTY; without even the implied
-      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-      PURPOSE.  See the GNU General Public License for more details.
-
-      You should have received a copy of the GNU General Public
-      License along with this program; if not, write to the Free
-      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
-      USA.
-
-
-Intro
-=====
-
- 
-This file contains some random information, that I like to have online
-instead of in a manual that can get lost. Ever misplace your Linux
-kernel sources?  And the manual of one of the boards in your computer?
-
-
-Addresses and interrupts
-========================
-
-Address dip switch settings:
-The dip switch sets bits 2-9 of the IO address. 
-
-       9 8 7 6 5 4 3 2 
-     +-----------------+
-   0 | X   X X X X X X |
-     |                 |    =   IoBase = 0x100 
-   1 |   X             |
-     +-----------------+          ------ RS232 connectors ---->
-         
-         |    |    |
-       edge connector
-         |    |    |
-         V    V    V
-
-Base address 0x100 caused a conflict in one of my computers once.  I
-haven't the foggiest why. My Specialix card is now at 0x180.  My
-other computer runs just fine with the Specialix card at 0x100....
-The card occupies 4 addresses, but actually only two are really used.
-
-The PCI version doesn't have any dip switches. The BIOS assigns
-an IO address. 
-
-The driver now still autoprobes at 0x100, 0x180, 0x250 and 0x260.  If
-that causes trouble for you, please report that. I'll remove
-autoprobing then.
-
-The driver will tell the card what IRQ to use, so you don't have to
-change any jumpers to change the IRQ. Just use a command line
-argument (irq=xx) to the insmod program to set the interrupt.
-
-The BIOS assigns the IRQ on the PCI version. You have no say in what
-IRQ to use in that case. 
-
-If your specialix cards are not at the default locations, you can use
-the kernel command line argument "specialix=io0,irq0,io1,irq1...".
-Here "io0" is the io address for the first card, and "irq0" is the
-irq line that the first card should use. And so on. 
-
-Examples. 
-
-You use the driver as a module and have three cards at 0x100, 0x250
-and 0x180. And some way or another you want them detected in that
-order. Moreover irq 12 is taken (e.g. by your PS/2 mouse).
-
-  insmod specialix.o iobase=0x100,0x250,0x180 irq=9,11,15
-
-The same three cards, but now in the kernel would require you to
-add 
-
-   specialix=0x100,9,0x250,11,0x180,15
-
-to the command line. This would become 
-
-   append="specialix=0x100,9,0x250,11,0x180,15" 
-
-in your /etc/lilo.conf file if you use lilo. 
-
-The Specialix driver is slightly odd: It allows you to have the second
-or third card detected without having a first card. This has
-advantages and disadvantages. A slot that isn't filled by an ISA card,
-might be filled if a PCI card is detected. Thus if you have an ISA
-card at 0x250 and a PCI card, you would get:
-
-sx0: specialix IO8+ Board at 0x100 not found.
-sx1: specialix IO8+ Board at 0x180 not found.
-sx2: specialix IO8+ board detected at 0x250, IRQ 12, CD1865 Rev. B.
-sx3: specialix IO8+ Board at 0x260 not found.
-sx0: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
-
-This would happen if you don't give any probe hints to the driver. 
-If you would specify:
-
-   specialix=0x250,11
-
-you'd get the following messages:
-
-sx0: specialix IO8+ board detected at 0x250, IRQ 11, CD1865 Rev. B.
-sx1: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
-
-ISA probing is aborted after the IO address you gave is exhausted, and
-the PCI card is now detected as the second card. The ISA card is now
-also forced to IRQ11....
-
-
-Baud rates
-==========
-
-The rev 1.2 and below boards use a CL-CD1864. These chips can only 
-do 64kbit. The rev 1.3 and newer boards use a CL-CD1865. These chips
-are officially capable of 115k2.
-
-The Specialix card uses a 25MHz crystal (in times two mode, which in
-fact is a divided by two mode). This is not enough to reach the rated
-115k2 on all ports at the same time. With this clock rate you can only
-do 37% of this rate. This means that at 115k2 on all ports you are
-going to lose characters (The chip cannot handle that many incoming
-bits at this clock rate.) (Yes, you read that correctly: there is a
-limit to the number of -=bits=- per second that the chip can handle.)
-
-If you near the "limit" you will first start to see a graceful
-degradation in that the chip cannot keep the transmitter busy at all
-times. However with a central clock this slow, you can also get it to
-miss incoming characters. The driver will print a warning message when
-you are outside the official specs. The messages usually show up in
-the file /var/log/messages .
-
-The specialix card cannot reliably do 115k2. If you use it, you have
-to do "extensive testing" (*) to verify if it actually works.
-
-When "mgetty" communicates with my modem at 115k2 it reports:
-got: +++[0d]ATQ0V1H0[0d][0d][8a]O[cb][0d][8a]
-                            ^^^^ ^^^^    ^^^^ 
-
-The three characters that have the "^^^" under them have suffered a
-bit error in the highest bit. In conclusion: I've tested it, and found
-that it simply DOESN'T work for me. I also suspect that this is also
-caused by the baud rate being just a little bit out of tune. 
-
-I upgraded the crystal to 66Mhz on one of my Specialix cards. Works
-great! Contact me for details. (Voids warranty, requires a steady hand
-and more such restrictions....)
-
-
-(*) Cirrus logic CD1864 databook, page 40.
-
-
-Cables for the Specialix IO8+
-=============================
-
-The pinout of the connectors on the IO8+ is:
-
-     pin    short    direction    long name
-            name
-    Pin 1   DCD      input        Data Carrier Detect
-    Pin 2   RXD      input        Receive
-    Pin 3   DTR/RTS  output       Data Terminal Ready/Ready To Send
-    Pin 4   GND      -            Ground
-    Pin 5   TXD      output       Transmit
-    Pin 6   CTS      input        Clear To Send
-        
-    
-             -- 6  5  4  3  2  1 --
-             |                    |
-             |                    |
-             |                    |
-             |                    |
-             +-----          -----+
-                  |__________|
-                      clip
-    
-    Front view of an RJ12 connector. Cable moves "into" the paper.
-    (the plug is ready to plug into your mouth this way...)
-
-    
-    NULL cable. I don't know who is going to use these except for
-    testing purposes, but I tested the cards with this cable. (It 
-    took quite a while to figure out, so I'm not going to delete
-    it. So there! :-)
-    
-    
-    This end goes               This end needs
-    straight into the           some twists in
-    RJ12 plug.                  the wiring.
-       IO8+ RJ12                   IO8+ RJ12
-        1  DCD       white          -
-        -             -             1 DCD
-        2  RXD       black          5 TXD
-        3  DTR/RTS   red            6 CTS
-        4  GND       green          4 GND
-        5  TXD       yellow         2 RXD
-        6  CTS       blue           3 DTR/RTS
-    
-
-    Same NULL cable, but now sorted on the second column.
- 
-        1  DCD       white          -
-        -             -             1 DCD
-        5  TXD       yellow         2 RXD
-        6  CTS       blue           3 DTR/RTS
-        4  GND       green          4 GND
-        2  RXD       black          5 TXD
-        3  DTR/RTS   red            6 CTS
-    
-    
-    
-    This is a modem cable usable for hardware handshaking:
-        RJ12                        DB25           DB9
-        1   DCD      white          8 DCD          1 DCD
-        2   RXD      black          3 RXD          2 RXD
-        3   DTR/RTS  red            4 RTS          7 RTS
-        4   GND      green          7 GND          5 GND
-        5   TXD      yellow         2 TXD          3 TXD
-        6   CTS      blue           5 CTS          8 CTS
-                            +----   6 DSR          6 DSR
-                            +----  20 DTR          4 DTR
-
-    This is a modem cable usable for software handshaking:
-    It allows you to reset the modem using the DTR ioctls.
-    I (REW) have never tested this, "but xxxxxxxxxxxxx
-    says that it works." If you test this, please
-    tell me and I'll fill in your name on the xxx's.
-
-        RJ12                        DB25           DB9
-        1   DCD      white          8 DCD          1 DCD
-        2   RXD      black          3 RXD          2 RXD
-        3   DTR/RTS  red           20 DTR          4 DTR
-        4   GND      green          7 GND          5 GND
-        5   TXD      yellow         2 TXD          3 TXD
-        6   CTS      blue           5 CTS          8 CTS
-                            +----   6 DSR          6 DSR
-                            +----   4 RTS          7 RTS
-
-   I bought a 6 wire flat cable. It was colored as indicated.
-   Check that yours is the same before you trust me on this.
-   
- 
-Hardware handshaking issues.
-============================
-
-The driver can be told to operate in two different ways. The default
-behaviour is specialix.sx_rtscts = 0 where the pin behaves as DTR when
-hardware handshaking is off. It behaves as the RTS hardware
-handshaking signal when hardware handshaking is selected.
-
-When you use this, you have to use the appropriate cable. The
-cable will either be compatible with hardware handshaking or with
-software handshaking. So switching on the fly is not really an
-option.
-
-I actually prefer to use the "specialix.sx_rtscts=1" option.
-This makes the DTR/RTS pin always an RTS pin, and ioctls to
-change DTR are always ignored. I have a cable that is configured
-for this. 
-
-
-Ports and devices
-=================
-
-Port 0 is the one furthest from the card-edge connector.
-
-Devices:
-
-You should make the devices as follows:
-
-bash
-cd /dev
-for i in  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 \
-         16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-do
-  echo -n "$i "
-  mknod /dev/ttyW$i c 75 $i
-  mknod /dev/cuw$i c 76 $i
-done
-echo ""
-
-If your system doesn't come with these devices preinstalled, bug your
-linux-vendor about this. They have had ample time to get this
-implemented by now.
-
-You cannot have more than 4 boards in one computer. The card only
-supports 4 different interrupts. If you really want this, contact me
-about this and I'll give you a few tips (requires soldering iron)....
-
-If you have enough PCI slots, you can probably use more than 4 PCI
-versions of the card though.... 
-
-The PCI version of the card cannot adhere to the mechanical part of
-the PCI spec because the 8 serial connectors are simply too large. If
-it doesn't fit in your computer, bring back the card.
-
-
-------------------------------------------------------------------------
-
-
-  Fixed bugs and restrictions:
-       - During initialization, interrupts are blindly turned on.
-            Having a shadow variable would cause an extra memory
-            access on every IO instruction. 
-       - The interrupt (on the card) should be disabled when we
-         don't allocate the Linux end of the interrupt. This allows 
-         a different driver/card to use it while all ports are not in
-         use..... (a la standard serial port)
-       == An extra _off variant of the sx_in and sx_out macros are
-          now available. They don't set the interrupt enable bit.
-          These are used during initialization. Normal operation uses
-          the old variant which enables the interrupt line.
-       - RTS/DTR issue needs to be implemented according to 
-         specialix' spec.
-            I kind of like the "determinism" of the current 
-            implementation. Compile time flag?
-       == Ok. Compile time flag! Default is how Specialix likes it.
-       == Now a config time flag! Gets saved in your config file. Neat!
-       - Can you set the IO address from the lilo command line?
-            If you need this, bug me about it, I'll make it. 
-       == Hah! No bugging needed. Fixed! :-)
-       - Cirrus logic hasn't gotten back to me yet why the CD1865 can
-            and the CD1864 can't do 115k2. I suspect that this is
-            because the CD1864 is not rated for 33MHz operation.
-            Therefore the CD1864 versions of the card can't do 115k2 on 
-            all ports just like the CD1865 versions. The driver does
-            not block 115k2 on CD1864 cards. 
-        == I called the Cirrus Logic representative here in Holland.
-           The CD1864 databook is identical to the CD1865 databook, 
-           except for an extra warning at the end. Similar Bit errors
-           have been observed in testing at 115k2 on both an 1865 and
-           a 1864 chip. I see no reason why I would prohibit 115k2 on
-           1864 chips and not do it on 1865 chips. Actually there is
-           reason to prohibit it on BOTH chips. I print a warning.
-           If you use 115k2, you're on your own. 
-       - A spiky CD may send spurious HUPs. Also in CLOCAL???
-         -- A fix for this turned out to be counter productive. 
-            Different fix? Current behaviour is acceptable?
-         -- Maybe the current implementation is correct. If anybody
-            gets bitten by this, please report, and it will get fixed.
-
-         -- Testing revealed that when in CLOCAL, the problem doesn't
-            occur. As warned for in the CD1865 manual, the chip may
-            send modem intr's on a spike. We could filter those out,
-            but that would be a cludge anyway (You'd still risk getting
-            a spurious HUP when two spikes occur.).....
- 
-
-
-  Bugs & restrictions:
-       - This is a difficult card to autoprobe.
-            You have to WRITE to the address register to even 
-            read-probe a CD186x register. Disable autodetection?
-         -- Specialix: any suggestions?
-
-
diff --git a/Documentation/serial/sx.txt b/Documentation/serial/sx.txt
deleted file mode 100644
index cb4efa0fb5cc..000000000000
--- a/Documentation/serial/sx.txt
+++ /dev/null
@@ -1,294 +0,0 @@
-
-      sx.txt  -- specialix SX/SI multiport serial driver readme.
-
-
-
-      Copyright (C) 1997  Roger Wolff (R.E.Wolff@BitWizard.nl)
-
-      Specialix pays for the development and support of this driver.
-      Please DO contact support@specialix.co.uk if you require
-      support.
-
-      This driver was developed in the BitWizard linux device
-      driver service. If you require a linux device driver for your
-      product, please contact devices@BitWizard.nl for a quote.
-
-      (History)
-      There used to be an SI driver by Simon Allan. This is a complete 
-      rewrite  from scratch. Just a few lines-of-code have been snatched.
-
-      (Sources)
-      Specialix document number 6210028: SX Host Card and Download Code
-      Software Functional Specification.
-
-      (Copying)
-      This program is free software; you can redistribute it and/or
-      modify it under the terms of the GNU General Public License as
-      published by the Free Software Foundation; either version 2 of
-      the License, or (at your option) any later version.
-
-      This program is distributed in the hope that it will be
-      useful, but WITHOUT ANY WARRANTY; without even the implied
-      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-      PURPOSE.  See the GNU General Public License for more details.
-
-      You should have received a copy of the GNU General Public
-      License along with this program; if not, write to the Free
-      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
-      USA.
-      
-      (Addendum)
-      I'd appreciate it that if you have fixes, that you send them
-      to me first. 
-
-
-Introduction
-============
-
-This file contains some random information, that I like to have online
-instead of in a manual that can get lost. Ever misplace your Linux
-kernel sources?  And the manual of one of the boards in your computer?
-
-
-Theory of operation
-===================
-
-An important thing to know is that the driver itself doesn't have the
-firmware for the card. This means that you need the separate package
-"sx_firmware". For now you can get the source at
-
-	ftp://ftp.bitwizard.nl/specialix/sx_firmware_<version>.tgz
-
-The firmware load needs a "misc" device, so you'll need to enable the
-"Support for user misc device modules" in your kernel configuration.
-The misc device needs to be called "/dev/specialix_sxctl". It needs
-misc major 10, and minor number 167 (assigned by HPA). The section
-on creating device files below also creates this device. 
-
-After loading the sx.o module into your kernel, the driver will report
-the number of cards detected, but because it doesn't have any
-firmware, it will not be able to determine the number of ports. Only
-when you then run "sx_firmware" will the firmware be downloaded and
-the rest of the driver initialized. At that time the sx_firmware
-program will report the number of ports installed.
-
-In contrast with many other multi port serial cards, some of the data
-structures are only allocated when the card knows the number of ports
-that are connected. This means we won't waste memory for 120 port
-descriptor structures when you only have 8 ports. If you experience
-problems due to this, please report them: I haven't seen any.
-
-
-Interrupts
-==========
-
-A multi port serial card, would generate a horrendous amount of
-interrupts if it would interrupt the CPU for every received
-character. Even more than 10 years ago, the trick not to use
-interrupts but to poll the serial cards was invented.
-
-The SX card allow us to do this two ways. First the card limits its
-own interrupt rate to a rate that won't overwhelm the CPU. Secondly,
-we could forget about the cards interrupt completely and use the
-internal timer for this purpose.
-
-Polling the card can take up to a few percent of your CPU. Using the
-interrupts would be better if you have most of the ports idle. Using
-timer-based polling is better if your card almost always has work to
-do. You save the separate interrupt in that case.
-
-In any case, it doesn't really matter all that much. 
-
-The most common problem with interrupts is that for ISA cards in a PCI
-system the BIOS has to be told to configure that interrupt as "legacy
-ISA". Otherwise the card can pull on the interrupt line all it wants
-but the CPU won't see this.
-
-If you can't get the interrupt to work, remember that polling mode is
-more efficient (provided you actually use the card intensively).
-
-
-Allowed Configurations
-======================
-
-Some configurations are disallowed. Even though at a glance they might
-seem to work, they are known to lockup the bus between the host card
-and the device concentrators. You should respect the drivers decision
-not to support certain configurations. It's there for a reason.
-
-Warning: Seriously technical stuff ahead. Executive summary: Don't use
-SX cards except configured at a 64k boundary. Skip the next paragraph.
-
-The SX cards can theoretically be placed at a 32k boundary. So for
-instance you can put an SX card at 0xc8000-0xd7fff. This is not a
-"recommended configuration". ISA cards have to tell the bus controller
-how they like their timing. Due to timing issues they have to do this
-based on which 64k window the address falls into. This means that the
-32k window below and above the SX card have to use exactly the same
-timing as the SX card. That reportedly works for other SX cards. But
-you're still left with two useless 32k windows that should not be used
-by anybody else.
-
-
-Configuring the driver
-======================
-
-PCI cards are always detected. The driver auto-probes for ISA cards at
-some sensible addresses. Please report if the auto-probe causes trouble
-in your system, or when a card isn't detected.
-
-I'm afraid I haven't implemented "kernel command line parameters" yet.
-This means that if the default doesn't work for you, you shouldn't use
-the compiled-into-the-kernel version of the driver. Use a module
-instead.  If you convince me that you need this, I'll make it for
-you. Deal?
-
-I'm afraid that the module parameters are a bit clumsy. If you have a
-better idea, please tell me.
-
-You can specify several parameters:
-
-	sx_poll: number of jiffies between timer-based polls.
-
-		Set this to "0" to disable timer based polls. 
-                Initialization of cards without a working interrupt
-                will fail.
-
-		Set this to "1" if you want a polling driver. 
-		(on Intel: 100 polls per second). If you don't use
-                fast baud rates, you might consider a value like "5". 
-                (If you don't know how to do the math, use 1).
-
-	sx_slowpoll: Number of jiffies between timer-based polls. 
- 		Set this to "100" to poll once a second. 
-		This should get the card out of a stall if the driver
-                ever misses an interrupt. I've never seen this happen,
-                and if it does, that's a bug. Tell me. 
-
-	sx_maxints: Number of interrupts to request from the card. 
-		The card normally limits interrupts to about 100 per
-		second to offload the host CPU. You can increase this
-		number to reduce latency on the card a little.
-		Note that if you give a very high number you can overload
-		your CPU as well as the CPU on the host card. This setting 
-		is inaccurate and not recommended for SI cards (But it 
-		works). 
-
-	sx_irqmask: The mask of allowable IRQs to use. I suggest you set 
-		this to 0 (disable IRQs all together) and use polling if 
-		the assignment of IRQs becomes problematic. This is defined
-		as the sum of (1 << irq) 's that you want to allow. So 
-		sx_irqmask of 8 (1 << 3) specifies that only irq 3 may
-		be used by the SX driver. If you want to specify to the 
-		driver: "Either irq 11 or 12 is ok for you to use", then
-		specify (1 << 11) | (1 << 12) = 0x1800 . 
-
-	sx_debug: You can enable different sorts of debug traces with this. 
-		At "-1" all debugging traces are active. You'll get several
-		times more debugging output than you'll get characters 
-		transmitted. 
-
-
-Baud rates
-==========
-
-Theoretically new SXDCs should be capable of more than 460k
-baud. However the line drivers usually give up before that.  Also the
-CPU on the card may not be able to handle 8 channels going at full
-blast at that speed. Moreover, the buffers are not large enough to
-allow operation with 100 interrupts per second. You'll have to realize
-that the card has a 256 byte buffer, so you'll have to increase the
-number of interrupts per second if you have more than 256*100 bytes
-per second to transmit.  If you do any performance testing in this
-area, I'd be glad to hear from you...
-
-(Psst Linux users..... I think the Linux driver is more efficient than
-the driver for other OSes. If you can and want to benchmark them
-against each other, be my guest, and report your findings...... :-)
-
-
-Ports and devices
-=================
-
-Port 0 is the top connector on the module closest to the host
-card. Oh, the ports on the SXDCs and TAs are labelled from 1 to 8
-instead of from 0 to 7, as they are numbered by linux. I'm stubborn in
-this: I know for sure that I wouldn't be able to calculate which port
-is which anymore if I would change that....
-
-
-Devices:
-
-You should make the device files as follows:
-
-#!/bin/sh
-# (I recommend that you cut-and-paste this into a file and run that)
-cd /dev
-t=0
-mknod specialix_sxctl c 10 167
-while [ $t -lt 64 ]
-  do 
-  echo -n "$t "
-  mknod ttyX$t c 32 $t
-  mknod cux$t  c 33 $t
-  t=`expr $t + 1`
-done
-echo ""
-rm /etc/psdevtab
-ps > /dev/null
-
-
-This creates 64 devices. If you have more, increase the constant on
-the line with "while". The devices start at 0, as is customary on
-Linux. Specialix seems to like starting the numbering at 1. 
-
-If your system doesn't come with these devices pre-installed, bug your
-linux-vendor about this. They should have these devices
-"pre-installed" before the new millennium. The "ps" stuff at the end
-is to "tell" ps that the new devices exist.
-
-Officially the maximum number of cards per computer is 4. This driver
-however supports as many cards in one machine as you want. You'll run
-out of interrupts after a few, but you can switch to polled operation
-then. At about 256 ports (More than 8 cards), we run out of minor
-device numbers. Sorry. I suggest you buy a second computer.... (Or
-switch to RIO).
-
-------------------------------------------------------------------------
-
-
-  Fixed bugs and restrictions:
-	- Hangup processing.  
-	  -- Done.
-
-	- the write path in generic_serial (lockup / oops). 
-	  -- Done (Ugly: not the way I want it. Copied from serial.c).
-
-        - write buffer isn't flushed at close.
-	  -- Done. I still seem to lose a few chars at close. 
-	     Sorry. I think that this is a firmware issue. (-> Specialix)
-
-	- drain hardware before  changing termios
-	- Change debug on the fly. 
-	- ISA free irq -1. (no firmware loaded).
-	- adding c8000 as a probe address. Added warning. 
-	- Add a RAMtest for the RAM on the card.c
-        - Crash when opening a port "way" of the number of allowed ports. 
-          (for example opening port 60 when there are only 24 ports attached)
-	- Sometimes the use-count strays a bit. After a few hours of
-          testing the use count is sometimes "3". If you are not like
-          me and can remember what you did to get it that way, I'd
-          appreciate an Email. Possibly fixed. Tell me if anyone still
-          sees this.
-	- TAs don't work right if you don't connect all the modem control
-	  signals. SXDCs do. T225 firmware problem -> Specialix. 
-	  (Mostly fixed now, I think. Tell me if you encounter this!)
-
-  Bugs & restrictions:
-
-	- Arbitrary baud rates. Requires firmware update. (-> Specialix)
-
-	- Low latency (mostly firmware, -> Specialix)
-
-
-
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index b0714d8f678a..cbc2f03056bd 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree:
    the stable tree without anything else needing to be done by the author
    or subsystem maintainer.
  - If the patch requires other patches as prerequisites which can be
-   cherry-picked than this can be specified in the following format in
+   cherry-picked, then this can be specified in the following format in
    the sign-off area:
 
      Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle
diff --git a/Documentation/zh_CN/HOWTO b/Documentation/zh_CN/HOWTO
index 6c914aa87e71..54ea24ff63c7 100644
--- a/Documentation/zh_CN/HOWTO
+++ b/Documentation/zh_CN/HOWTO
@@ -237,7 +237,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循
 如果没有2.6.x.y版本内核存在，那么最新的2.6.x版本内核就相当于是当前的稳定
 版内核。
 
-2.6.x.y版本由“稳定版”小组（邮件地址<stable@kernel.org>）维护，一般隔周发
+2.6.x.y版本由“稳定版”小组（邮件地址<stable@vger.kernel.org>）维护，一般隔周发
 布新版本。
 
 内核源码中的Documentation/stable_kernel_rules.txt文件具体描述了可被稳定
diff --git a/Documentation/zh_CN/io_ordering.txt b/Documentation/zh_CN/io_ordering.txt
new file mode 100644
index 000000000000..e592daf4e014
--- /dev/null
+++ b/Documentation/zh_CN/io_ordering.txt
@@ -0,0 +1,67 @@
+Chinese translated version of Documentation/io_orderings.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Chinese maintainer: Lin Yongting <linyongting@gmail.com>
+---------------------------------------------------------------------
+Documentation/io_ordering.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 林永听 Lin Yongting <linyongting@gmail.com>
+中文版翻译者： 林永听 Lin Yongting <linyongting@gmail.com>
+中文版校译者： 林永听 Lin Yongting <linyongting@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+
+在某些平台上，所谓的内存映射I/O是弱顺序。在这些平台上，驱动开发者有责任
+保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
+设备寄存器或桥寄存器，触发IO芯片清刷未处理的写操作到达设备后才处理读操作，
+而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
+这也可以保证后面的写操作只在前面的写操作之后到达设备（这非常类似于内存
+屏障操作，mb()，不过仅适用于I/O）。
+
+假设一个设备驱动程的具体例子：
+
+        ...
+CPU A:  spin_lock_irqsave(&dev_lock, flags)
+CPU A:  val = readl(my_status);
+CPU A:  ...
+CPU A:  writel(newval, ring_ptr);
+CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
+        ...
+CPU B:  spin_lock_irqsave(&dev_lock, flags)
+CPU B:  val = readl(my_status);
+CPU B:  ...
+CPU B:  writel(newval2, ring_ptr);
+CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
+        ...
+
+上述例子中，设备可能会先接收到newval2的值，然后接收到newval的值，问题就
+发生了。不过很容易通过下面方法来修复：
+
+        ...
+CPU A:  spin_lock_irqsave(&dev_lock, flags)
+CPU A:  val = readl(my_status);
+CPU A:  ...
+CPU A:  writel(newval, ring_ptr);
+CPU A:  (void)readl(safe_register); /* 配置寄存器？*/
+CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
+        ...
+CPU B:  spin_lock_irqsave(&dev_lock, flags)
+CPU B:  val = readl(my_status);
+CPU B:  ...
+CPU B:  writel(newval2, ring_ptr);
+CPU B:  (void)readl(safe_register); /* 配置寄存器？*/
+CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
+
+在解决方案中，读取safe_register寄存器，触发IO芯片清刷未处理的写操作，
+再处理后面的读操作，防止引发数据不一致问题。
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt
index 2ebe539f5450..dfb72a5c63e9 100644
--- a/Documentation/zh_CN/magic-number.txt
+++ b/Documentation/zh_CN/magic-number.txt
@@ -63,8 +63,6 @@ struct tty_ldisc {
 PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
 CMAGIC                0x0111      user              include/linux/a.out.h
 MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
-RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
-SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
 HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
 APM_BIOS_MAGIC        0x4101      apm_user          arch/x86/kernel/apm_32.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
@@ -82,7 +80,6 @@ STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
 X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
 SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
 AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
-ESP_MAGIC             0x53ee      esp_struct        drivers/char/esp.h
 TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
 MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
 TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
@@ -94,13 +91,10 @@ USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
 RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
 USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
 CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
-A2232_MAGIC           0x000a2232  gs_port           drivers/char/ser_a2232.h
 RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
 LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
 GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
 RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
-RIO_MAGIC             0x12345678  gs_port           drivers/char/rio/rio_linux.c
-SX_MAGIC              0x12345678  gs_port           drivers/char/sx.h
 NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
 RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
 BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
@@ -116,7 +110,6 @@ ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
 CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
 ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
 SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
-STLI_BOARDMAGIC       0x4bc6c825  stlibrd           include/linux/istallion.h
 CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
 SLAB_C_MAGIC          0x4f17a36d  kmem_cache        mm/slab.c
 COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
@@ -127,10 +120,8 @@ SCC_MAGIC             0x52696368  gs_port           drivers/char/scc.h
 SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
 GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
 RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
-STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
 EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
 HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
-EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
 PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
 KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
 I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
@@ -142,17 +133,14 @@ SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
 LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
 OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
 M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
-STL_PANELMAGIC        0x7ef621a1  stlpanel          include/linux/stallion.h
 VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
 KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
 PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
 NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
-STL_BOARDMAGIC        0xa2267f52  stlbrd            include/linux/stallion.h
 ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
 SCI_MAGIC             0xbabeface  gs_port           drivers/char/sh-sci.h
 CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
 DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
-STLI_PORTMAGIC        0xe671c7a1  stliport          include/linux/istallion.h
 YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
 CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
 QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
diff --git a/Documentation/zh_CN/stable_kernel_rules.txt b/Documentation/zh_CN/stable_kernel_rules.txt
index b5b9b0ab02fd..26ea5ed7cd9c 100644
--- a/Documentation/zh_CN/stable_kernel_rules.txt
+++ b/Documentation/zh_CN/stable_kernel_rules.txt
@@ -42,7 +42,7 @@ Documentation/stable_kernel_rules.txt 的中文翻译
 
 向稳定版代码树提交补丁的过程：
 
-  - 在确认了补丁符合以上的规则后，将补丁发送到stable@kernel.org。
+  - 在确认了补丁符合以上的规则后，将补丁发送到stable@vger.kernel.org。
   - 如果补丁被接受到队列里，发送者会收到一个ACK回复，如果没有被接受，收
     到的是NAK回复。回复需要几天的时间，这取决于开发者的时间安排。
   - 被接受的补丁会被加到稳定版本队列里，等待其他开发者的审查。
diff --git a/MAINTAINERS b/MAINTAINERS
index 6dc67b1fdb50..3152dd74be22 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4384,10 +4384,7 @@ F:	drivers/scsi/ibmvscsi/
 X:	drivers/scsi/ibmvscsi/ibmvstgt.c
 
 IBM ServeRAID RAID DRIVER
-P:	Jack Hammer
-M:	Dave Jeffery <ipslinux@adaptec.com>
-W:	http://www.developer.ibm.com/welcome/netfinity/serveraid.html
-S:	Supported
+S:	Orphan
 F:	drivers/scsi/ips.*
 
 ICH LPC AND GPIO DRIVER
@@ -6404,6 +6401,7 @@ F:	drivers/usb/*/*omap*
 F:	arch/arm/*omap*/usb*
 
 OMAP GPIO DRIVER
+M:	Javier Martinez Canillas <javier@dowhile0.org>
 M:	Santosh Shilimkar <santosh.shilimkar@ti.com>
 M:	Kevin Hilman <khilman@deeprootsystems.com>
 L:	linux-omap@vger.kernel.org
@@ -6782,7 +6780,7 @@ PERFORMANCE EVENTS SUBSYSTEM
 M:	Peter Zijlstra <a.p.zijlstra@chello.nl>
 M:	Paul Mackerras <paulus@samba.org>
 M:	Ingo Molnar <mingo@redhat.com>
-M:	Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
+M:	Arnaldo Carvalho de Melo <acme@kernel.org>
 L:	linux-kernel@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
 S:	Supported
@@ -9098,6 +9096,9 @@ F:	arch/um/os-Linux/drivers/
 
 TURBOCHANNEL SUBSYSTEM
 M:	"Maciej W. Rozycki" <macro@linux-mips.org>
+M:	Ralf Baechle <ralf@linux-mips.org>
+L:	linux-mips@linux-mips.org
+Q:	http://patchwork.linux-mips.org/project/linux-mips/list/
 S:	Maintained
 F:	drivers/tc/
 F:	include/linux/tc.h
diff --git a/Makefile b/Makefile
index 60ccbfe750a2..ab2a73f1a8b0 100644
--- a/Makefile
+++ b/Makefile
@@ -105,10 +105,6 @@ ifeq ("$(origin O)", "command line")
   KBUILD_OUTPUT := $(O)
 endif
 
-ifeq ("$(origin W)", "command line")
-  export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W)
-endif
-
 # That's our default target when none is given on the command line
 PHONY := _all
 _all:
@@ -349,9 +345,14 @@ include $(srctree)/scripts/Kbuild.include
 
 AS		= $(CROSS_COMPILE)as
 LD		= $(CROSS_COMPILE)ld
+LDFINAL	= $(LD)
 CC		= $(CROSS_COMPILE)gcc
 CPP		= $(CC) -E
+ifdef CONFIG_LTO
+AR		= $(CROSS_COMPILE)gcc-ar
+else
 AR		= $(CROSS_COMPILE)ar
+endif
 NM		= $(CROSS_COMPILE)nm
 STRIP		= $(CROSS_COMPILE)strip
 OBJCOPY		= $(CROSS_COMPILE)objcopy
@@ -410,7 +411,7 @@ KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(S
 
 export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
 export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP
+export CPP AR NM STRIP OBJCOPY OBJDUMP LDFINAL
 export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE
 export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
@@ -421,6 +422,17 @@ export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
 export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
 export KBUILD_ARFLAGS
 
+ifdef CONFIG_LTO
+# LTO gcc creates a lot of files in TMPDIR, and with /tmp as tmpfs
+# it's easy to drive the machine OOM. Use the object directory
+# instead.
+ifndef TMPDIR
+TMPDIR ?= $(objtree)
+export TMPDIR
+$(info setting TMPDIR=$(objtree) for LTO build)
+endif
+endif
+
 # When compiling out-of-tree modules, put MODVERDIR in the module
 # tree rather than in the kernel tree. The kernel tree might
 # even be read-only.
@@ -731,6 +743,9 @@ ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
 	KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
 endif
 
+include $(srctree)/scripts/Makefile.extrawarn
+include ${srctree}/scripts/Makefile.lto
+
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
 KBUILD_CPPFLAGS += $(KCPPFLAGS)
 KBUILD_AFLAGS += $(KAFLAGS)
diff --git a/Next/SHA1s b/Next/SHA1s
new file mode 100644
index 000000000000..1d3bd1bdfe81
--- /dev/null
+++ b/Next/SHA1s
@@ -0,0 +1,217 @@
+Name		SHA1
+----		----
+origin		6ca2a88ad820af56535ed1e6936e0490cb6ec6dc
+fixes		b0031f227e47919797dc0e1c1990f3ef151ff0cc
+kbuild-current	38dbfb59d1175ef458d006556061adeaa8751b72
+arc-current	0409726a81f22f0b95571afa6bb1669b8a441ee4
+arm-current	c9d347e0277696c80496161cbef47393b850a0aa
+m68k-current	50be9eba831da114e1979726f4119d342698e651
+metag-fixes	0414855fdc4a40da05221fc6062cccbc0c30f169
+powerpc-merge	cc4f265ad9a37bdb1846c45eebe454c382f31d67
+sparc		455c6fdbd219161bd09b1165f11699d6d73de11c
+net		0acf07d240a84069c4a6651e6030cf35d30c7159
+ipsec		a32452366b7250c42e96a18ffc3ad8db9e0ca3c2
+sound-current	8dc9abb93dde94e7f2bc719032fe16f5713df05c
+pci-current	f5d3352b2751f8de7e06e23a04ac0b4c474075e9
+wireless	f8d2b9209ad648a8e9aa973d32fb64aa2ab01d00
+driver-core.current	98b0f811aade1b7c6e7806c86aa0befd5919d65f
+tty.current	1e7da0530423a232747d64c2113ace55b01e5754
+usb.current	94d72f008909610710bb1841d665eeeb010a0be1
+staging.current	33c84bc14c25074ac14644cf7db75a57e9abaf1a
+char-misc.current	03367ef5ea811475187a0732aada068919e14d61
+input-current	692d96552c9a86a919fe6b5b82288a6c77c015a5
+md-current	d47648fcf0611812286f68131b40251c6fa54f5e
+crypto-current	eb4a5346e777784f1b5ae9fd0c29b96344bdc3ae
+ide		5b40dd30bbfaa7fcba0cd945a4852a146c552ea7
+dwmw2		5950f0803ca9d396ab79b7fe6789351f96e1d8d5
+devicetree-current	1f42e5dd5065963979bb53daadf5d4f1e71f0c5f
+rr-fixes	7122c3e9154b5d9a7422f68f02d8acf050fad2b0
+mfd-fixes	73beb63d290f961c299526852884846b0d868840
+vfio-fixes	239a87020b263fe7e70adc5803cb157955023d3c
+drm-intel-fixes	b6842feb63a23a6a988f4e1ffb93408d8ff6931e
+asm-generic	fb9de7ebc3a2eb7ddb83c92e288447a0c313bced
+arc		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+arm		98f07013149d4be18ff16cfc5b43218f3a70afd6
+arm-kvm-cpuresume	91a3f6af430d81c5f855f3f1ff0f3715e064f342
+arm-perf	c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+arm-soc		2bf73dd61a84cdf27e49f48e08739af6ba70ace1
+bcm2835		fa389e220254c69ffae0d403eac4146171062d08
+berlin		e49c50df1e18481f8c62f0e7ee44c1c39f9b77b1
+cortex-m	f0d7515372ff0ea53fd66099533d3c8e0464cbbf
+ep93xx		bfb0709fd17b13498d99592bbe12c91130e35a55
+imx-mxs		1e9dfe21eca865ecc67ae3b4a00383738e115074
+ixp4xx		19f949f52599ba7c3f67a5897ac6be14bfcb1200
+keystone	47fc77cc704ea0ff839f8240894ed8e0be398adf
+msm		81cf1e061d001fab44dbaa85fc4fbfb6da6713a1
+mvebu		6412d6635b676c8fc862f5c71bc1eb3be9ddf7b6
+renesas		47a0013abaeefa18b442eceb150553f114ce44c8
+samsung		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+tegra		628d56b42d351f2a4820bd8d89921c87ec4b4a9d
+arm64		ebf81a938dade3b450eb11c57fa744cfac4b523f
+blackfin	c4a2c58d20953ff1080f50f705cdd952f6d301b2
+c6x		ae72758f1dd93bd367dc7719702f24a9bfb3bad9
+cris		cd065a010a97e3c330d1ded9af551664c9689b19
+hexagon		a9a44fdf329668125042055c569656aa83d8cccb
+ia64		e32634f5d57f1dce88624b70a6d625915f6ea09e
+m68k		50be9eba831da114e1979726f4119d342698e651
+m68knommu	2bf0787b4b42e61c3a366446b6b24cdfd6165028
+metag		2aca46ce1b5c4b7d76566de72b16640ec674c008
+microblaze	a66a626538af65cbfc611e2b2fce500ed3f24518
+mips		0c61dd849d8cf9b8eea3557bc4ac7558cecaa437
+openrisc	548dafe880ad84d0accc0a5596c26e3348b103e1
+parisc		6c700d71f7faecb540b3fa4303edb5323a2768c1
+parisc-hd	ab3e55b119c9653b19ea4edffb86f04db867ac98
+powerpc		cd427485357c0c4b99f69719251baacf25946e11
+mpc5xxx		bc75059422338197ce487d338ac9c898761e1e61
+galak		9e2ecdbba3b0745f9ed454ab86961e3ccf9dc224
+s390		4c0fda1613464d7a0f769713088807fa302e1843
+sparc-next	049ffa8ab33a63b3bff672d1a0ee6a35ad253fe8
+tile		5eb0bdf84433eb7b7ad4ba92a80aac57ad4b46ea
+uml		989e59fa41c5464ab77bf0bf82f32f721430544e
+unicore32	c284464658acab50c67ff65ff3dc9215a0231ad2
+xtensa		cfe8255f0afcf5d2d1dbfa093223cafe38773fa7
+btrfs		00fdf13a2e9f313a044288aa59d3b8ec29ff904a
+ceph		a30be7cb2ccb995ad5e67fd4b548f11fe37fc8b1
+cifs		a5a64da8c4e584450bb1485463ce343316426e22
+configfs	b930c26416c4ea6855726fd977145ccea9afbdda
+ecryptfs	9e78d14a9f641c0476f733f6fc559ba5cac6f52b
+ext3		01d8885785a60ae8f4c37b0ed75bdc96d0fc6a44
+ext4		dd346d66aa92865e01b2511eff937f3e9a3af613
+f2fs		350ca07320d4fb28e9ac2ad792dbb6c8853ee759
+fscache		fe02fb3ec10932ce07406b1581e28326181fc9d8
+fuse		f3846266f593595632a07242fcbc6c24bc2ade68
+gfs2		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+jfs		24e4a0f3de21ad715c9235367e241554c64b9adb
+logfs		339466142b3f58fe0ee4dea7e8c5f3d33099e89c
+nfs		1f2edbe3fe2111a59fcd1bb3b9725066bc9ed686
+nfsd		06f9cc12caa862f5bc86ebdb4f77568a4bef0167
+omfs		976d167615b64e14bc1491ca51d424e2ba9a5e84
+squashfs	6d565409503f4e1f74ac30de14e8c91a2b826cd8
+v9fs		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+ubifs		d56030ac25d383218045c5d87e98e0494d6af3ad
+xfs		330033d697ed8d296fa52b5303db9d802ad901cc
+file-private-locks	f1c6bb2cb8b81013e8979806f8e15e3d53efb96d
+vfs		527d1511310a89650000081869260394e20c7013
+pci		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+hid		12e5706a47c23cdd84c351e59da01ef9e33737f3
+i2c		9e897e13bd46fa03485468609741974259a8c573
+jdelvare-hwmon	455c6fdbd219161bd09b1165f11699d6d73de11c
+hwmon-staging	046f3ea7c6af596a8d913154687c5e457410046e
+v4l-dvb		b40dfe97cc3a171f036c9e3a9fcb5831c502da1e
+kbuild		de71647f7af0cd00b50265498a21b4376955797d
+kconfig		95edca5c523c4b404dd60baa0a1bea0e4c38fd72
+libata		73ff0e9080ed7e5fd0d03b5b8cd12529fb6c58fc
+pm		19ce7f3f31103d7a5b0e93ba9de3ebb4b9d66701
+idle		23a299cd93781a190cdca0d7d16034837b7dfd86
+apm		158204397034f088bfd505eeee281f7072da1c24
+cpupowerutils	f16603386b38c28979f4df1cafdc2fe73fa87d37
+thermal		9477165ec525d47abb1cb6523698e0cd89d65ddb
+ieee1394	0ca49345b6f489e95f8d6edeb0b092e257475b2a
+dlm		075f01775f53640af4a2ca3ed8cbc71de6e37582
+swiotlb		0cb637bff80d5ba2b916bb19f19ffd59cd4079fd
+slave-dma	8edc51c197b8f409bef7b21755254e6f3ce7ed23
+dmaengine	b9bf6d2e84b736eeed2cf0f387771c7793a1c465
+net-next	cd6362befe4cc7bf589a5236d2a780af2d47bcc9
+ipsec-next	cd6362befe4cc7bf589a5236d2a780af2d47bcc9
+wireless-next	321d03c86732e45f5f33ad0db5b68e2e1364acb9
+bluetooth	899704633969526114ae63fa72a3f0a8d7ea5dab
+infiniband	5ae2866f5264fd51ac2ff6c95d02156a7c1f073c
+mtd		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+l2-mtd		6189cccbe8d16d0ef175bd0dca18e3824ca01174
+crypto		f51f593b3eb194d01d8980316e6bb1f7d72f567a
+drm		c39b06951f1dc2e384650288676c5b7dcc0ec92c
+drm-intel	c79057922ed6c2c6df1214e6ab4414fea1b23db2
+drm-tegra	3d1c1474386e3714c05beef07abe3142e0dd822d
+sound		00d90154404ae6218730068d25bf2faad3186631
+sound-asoc	df9a50e93aa5ff53e54ce04b7487c2aa07c041f3
+modules		22c9bcad859d5c969289b3b37084a96c621f8f2c
+virtio		fc4324b4597c4eb8907207e82f9a6acec84dd335
+input		e2c3ecf0ea8e87c5209371af7da107ebc47a5639
+input-mt	5e01dc7b26d9f24f39abace5da98ccbd6a5ceb52
+block		926912e06e3b9cf2bbc2596d1a7ad19f69fe304e
+device-mapper	ec052772958d3102fd8bab838a5d88f224973a0c
+embedded	4744b43431e8613f920c5cba88346756f53c5165
+firmware	6e03a201bbe8137487f340d26aa662110e324b20
+pcmcia		80af9e6d7ae633309cc5bca96aee6a45117e7c98
+mmc		c67480173f72e883235dd0ad09d90156c8f87600
+kgdb		6bedf31c25dd93c4f70a28e9ab94a239a5fb592c
+slab		34bf6ef94a835a8f1d8abd3e7d38c6c08d205867
+uclinux		6dbe51c251a327e012439c4772097a13df43c5b8
+md		e2f23b606b94f28a8febd5aa715df697d80b018e
+mfd		90b128ed1557c2f523995a379a53e5105891ecf8
+mfd-lj		2d28ca731b9bb6262f7711241628c7844b0cf7dc
+battery		ac323d8d807060f7c95a685a9fe861e7b6300993
+fbdev		718b90ac4c21c81f42b6db062ca0867f3cac7648
+viafb		838ac785d521e091bd8b5f6a2b545166f5f32b77
+omap_dss2	d754589d80447da9ed23426d3861e33df43dbda7
+regulator	053ed78e189f97212fa3533b1424d82d1718b606
+security	fab71a90eddaf4d5f654fdd0ea7c46315c8da4a4
+selinux		6d32c850621b0be75777b9102b14f6268bbd9f0f
+lblnet		d8ec26d7f8287f5788a494f56e8814210f0e64be
+watchdog	c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+iommu		e172b81222548b856ecbe59b305d2cb733d512c4
+dwmw2-iommu	5ae0566a0fffa09a77ac5996e3854fe91cd87167
+vfio		4379d2ae152860e023b42257fd60b5e235047f63
+osd		f1f6630b53e702648a248fecd881f3df5968a31a
+jc_docs		5c050fb96380a87a85aad9084b68fdcd2b84c193
+trivial		c800bcd5f53fd9455fc6c68f1a34306e5aa4f79a
+audit		4daa06f4d8b05ebbff7f18ddfdb43e8449ca4190
+fsnotify	1ca39ab9d21ac93f94b9e3eb364ea9a5cf2aba06
+devicetree	d88cf7d7b4240b8df170ba105e414e476fb51cce
+dt-rh		e7a62df8e8b4a5ecbbf4339b5b3671ae6582e50a
+spi		5db6f05a77a00968e345e9a6ddda6050870f0d16
+tip		7b8bfcc693cf7b039201f020c0d5faa52ae01f2b
+clockevents	09e15176ded1faa7bd685b3b5b1213cf0240566e
+edac		49856dc973cd95d85ac1cab6c70410d8331e5c04
+edac-amd	c045ebdf6079b79ac4b4dd16ff37f93ae0bd5190
+ftrace		17a280ea8111c66791c18c0353b7986aafcb24fe
+rcu		765a3f4fed708ae429ee095914a7897acb3a65bd
+uprobes		0326f5a94ddea33fa331b2519f4172f4fb387baa
+kvm		0f689a33ad17845363acdc6d52783befd6ad116c
+kvm-arm		b73117c49364551ff789db7c424a115ac5b77850
+kvm-ppc		7227fc0666606b0df2c0d2966a7f4859b01bdf74
+oprofile	6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae
+fw-nohz		74876a98a87a115254b3a66a14b27320b7f0acaa
+xen-tip		0a25e113b480694a0af716f33d2edd243b6a8764
+percpu		4abee313c9a8fc8ce0c8276e5c6a5c57ab410a7f
+workqueues	77f300b198f93328c26191b52655ce1b62e202cf
+drivers-x86	7a70906e55bf3b78a10f749cebb6ab0b4026b76e
+chrome-platform	2b8454a75b90d7cd1ac325a0baba77244733354f
+sysctl		4e474a00d7ff746ed177ddae14fa8b2d4bad7a00
+regmap		b94f4fe06dd8d3f6d17950cffcc53695b5f2c07d
+hsi		43139a61fc68f4b0af7327a0e63f340a7c81c69a
+leds		95d33e9fcc7eec018bd19c196315c4c788399499
+driver-core	c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+tty		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+usb		c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+usb-gadget	c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+staging		dff222670ebebf1a7f147a23ccb5fc0312f2ae7e
+char-misc	c9eaa447e77efe77b7fa4c953bd62de8297fd6c5
+cgroup		49957f8e2a43035a97d05bddefa394492a969c0d
+scsi		b908a5a97b7f6355d2b1028f92c796f822df5aa8
+target-updates	b076808051f2c80d38e03fb2f1294f525c7a446d
+target-merge	b28a960c42fcd9cfc987441fa6d1c1a471f0f9ed
+writeback	f9b0e058cbd04ada76b13afffa7e1df830543c24
+hwspinlock	8b37fcfc9b3400b647748783a2cafff67793e0ad
+pinctrl		cc17609e18558931eb5823a1d64151fdc705004f
+vhost		d3d665a654a35c47463d2aa6353bac3ce293f4f5
+remoteproc	bd88acba5f9809af48f66267bb16024b9e33cf2b
+rpmsg		397944df3290ddc46dcc6a08cd71fb560700431b
+gpio		da150898c98287d36a05edec6910cb2a04550f95
+dma-mapping	68efd7d2fb32c2606f1da318b6a851d933813f27
+pwm		2ae69a460413615c82381b240df3800a909100d3
+dma-buf		dcb99fd9b08cfe1afe426af4d8d3cbc429190f15
+userns		3efe1ac78e996da8e141b86667cc15758aad4366
+ktest		62183dcac539a14ed0a820b8392db353d72a7d7e
+signal		20b4fb485227404329e41ad15588afad3df23050
+clk		31c2c4b8e9115844858bbf0d441fde46545528fd
+random		7b878d4b48c4e04b936918bb83836a107ba453b3
+lzo-update	42b775abafafdf811ef300e869a4e1480ef1cf95
+arm64-hugepages	af07484863e0c20796081e57093886c22dc16705
+aio		e02ba72aabfade4c9cd6e3263e9b57bf890ad25c
+llvmlinux	40e9963e622cf28ecef258e3dddb04457b65681c
+powernv-cpuidle	0888839c5b62c44a55ac9d28acc273ba663c65ea
+rd-docs		596d80c7ceb61b28e2583ffbac69460c61435167
+akpm-current	7b5f689823ab9b3bbb07aa4a57ea9aa9db6f09c5
+akpm-current	7b5f689823ab9b3bbb07aa4a57ea9aa9db6f09c5
+akpm		4c3d768413b4c96a9001e8e6b0a545dc72ad572c
diff --git a/Next/Trees b/Next/Trees
new file mode 100644
index 000000000000..a795417b26f5
--- /dev/null
+++ b/Next/Trees
@@ -0,0 +1,218 @@
+Trees included into this release:
+
+Name		Type	URL
+----		----	---
+origin		git	git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git#master
+fixes		git	git://git.kernel.org/pub/scm/linux/kernel/git/sfr/next-fixes.git#master
+kbuild-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#rc-fixes
+arc-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git#for-curr
+arm-current	git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#fixes
+m68k-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-linus
+metag-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag.git#fixes
+powerpc-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#merge
+sparc		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git#master
+net		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git#master
+ipsec		git	git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git#master
+sound-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-linus
+pci-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#for-linus
+wireless	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git#master
+driver-core.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-linus
+tty.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-linus
+usb.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-linus
+staging.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-linus
+char-misc.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-linus
+input-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#for-linus
+md-current	git	git://neil.brown.name/md#for-linus
+crypto-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git#master
+ide		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide.git#master
+dwmw2		git	git://git.infradead.org/users/dwmw2/random-2.6.git#master
+devicetree-current	git	git://git.secretlab.ca/git/linux-2.6#devicetree/merge
+rr-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#fixes
+mfd-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git#master
+vfio-fixes	git	git://github.com/awilliam/linux-vfio.git#for-linus
+drm-intel-fixes	git	git://anongit.freedesktop.org/drm-intel#for-linux-next-fixes
+asm-generic	git	git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git#master
+arc		git	git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git#for-next
+arm		git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#for-next
+arm-kvm-cpuresume	git	git://linux-arm.org/linux-2.6-lp.git#arm-kvm-cpuresume
+arm-perf	git	git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git#for-next/perf
+arm-soc		git	git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git#for-next
+bcm2835		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git#for-next
+berlin		git	git://github.com/shesselba/linux-berlin.git#berlin/for-next
+cortex-m	git	git://git.pengutronix.de/git/ukl/linux.git#for-next
+ep93xx		git	git://github.com/RyanMallon/linux-ep93xx.git#ep93xx-for-next
+imx-mxs		git	git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git#for-next
+ixp4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux.git#next
+keystone	git	git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git#next
+msm		git	git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git#for-next
+mvebu		git	git://git.infradead.org/linux-mvebu.git#for-next
+renesas		git	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git#next
+samsung		git	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git#for-next
+tegra		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git#for-next
+arm64		git	git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux#for-next/core
+blackfin	git	http://git.kernel.org/pub/scm/linux/kernel/git/realmz6/blackfin-linux.git#for-linus
+c6x		git	git://linux-c6x.org/git/projects/linux-c6x-upstreaming.git#for-linux-next
+cris		git	git://www.jni.nu/cris.git#for-next
+hexagon		git	git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel.git#linux-next
+ia64		git	git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git#next
+m68k		git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-next
+m68knommu	git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu.git#for-next
+metag		git	git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag.git#for-next
+microblaze	git	git://git.monstr.eu/linux-2.6-microblaze.git#next
+mips		git	git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git#mips-for-linux-next
+openrisc	git	git://openrisc.net/jonas/linux#for-upstream
+parisc		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git#for-next
+parisc-hd	git	git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git#for-next
+powerpc		git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#next
+mpc5xxx		git	git://git.denx.de/linux-2.6-agust.git#next
+galak		git	git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git#next
+s390		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#features
+sparc-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git#master
+tile		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git#master
+uml		git	git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml.git#next
+unicore32	git	git://github.com/gxt/linux.git#unicore32
+xtensa		git	git://github.com/czankel/xtensa-linux.git#for_next
+btrfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git#next
+ceph		git	git://github.com/ceph/ceph-client.git#master
+cifs		git	git://git.samba.org/sfrench/cifs-2.6.git#for-next
+configfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/configfs.git#linux-next
+ecryptfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git#next
+ext3		git	git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs.git#for_next
+ext4		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git#dev
+f2fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git#dev
+fscache		git	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git#fscache
+fuse		git	git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git#for-next
+gfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git#master
+jfs		git	git://github.com/kleikamp/linux-shaggy.git#jfs-next
+logfs		git	git://github.com/prasad-joshi/logfs_upstream.git#master
+nfs		git	git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git#linux-next
+nfsd		git	git://git.linux-nfs.org/~bfields/linux.git#nfsd-next
+omfs		git	git://github.com/bcopeland/omfs.git#for-next
+squashfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next.git#master
+v9fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git#for-next
+ubifs		git	git://git.infradead.org/ubifs-2.6.git#linux-next
+xfs		git	git://oss.sgi.com/xfs/xfs.git#for-next
+file-private-locks	git	git://git.samba.org/jlayton/linux.git#linux-next
+vfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6.git#for-next
+pci		git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#next
+hid		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git#for-next
+i2c		git	git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git#i2c/for-next
+jdelvare-hwmon	quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-hwmon/
+hwmon-staging	git	git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git#hwmon-next
+v4l-dvb		git	git://linuxtv.org/mchehab/media-next.git#master
+kbuild		git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#for-next
+kconfig		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-kconfig.git#for-next
+libata		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git#for-next
+pm		git	git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git#linux-next
+idle		git	git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git#next
+apm		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git#for-next
+cpupowerutils	git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/cpupowerutils.git#master
+thermal		git	git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git#next
+ieee1394	git	git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git#for-next
+dlm		git	git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git#next
+swiotlb		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb.git#linux-next
+slave-dma	git	git://git.infradead.org/users/vkoul/slave-dma.git#next
+dmaengine	git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/dmaengine.git#next
+net-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git#master
+ipsec-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git#master
+wireless-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git#master
+bluetooth	git	git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git#master
+infiniband	git	git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git#for-next
+mtd		git	git://git.infradead.org/mtd-2.6.git#master
+l2-mtd		git	git://git.infradead.org/users/dedekind/l2-mtd-2.6.git#master
+crypto		git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git#master
+drm		git	git://people.freedesktop.org/~airlied/linux.git#drm-next
+drm-intel	git	git://anongit.freedesktop.org/drm-intel#for-linux-next
+drm-tegra	git	git://anongit.freedesktop.org/tegra/linux.git#drm/for-next
+sound		git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-next
+sound-asoc	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git#for-next
+modules		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#modules-next
+virtio		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#virtio-next
+input		git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#next
+input-mt	git	git://github.com/rydberg/linux.git#for-next
+block		git	git://git.kernel.dk/linux-block.git#for-next
+device-mapper	git	git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git#for-next
+embedded	git	git://git.infradead.org/embedded-2.6.git#master
+firmware	git	git://git.infradead.org/users/dwmw2/firmware-2.6.git#master
+pcmcia		git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia.git#master
+mmc		git	git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git#mmc-next
+kgdb		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb.git#kgdb-next
+slab		git	git://github.com/penberg/linux.git#for-next
+uclinux		git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/uclinux.git#for-next
+md		git	git://neil.brown.name/md#for-next
+mfd		git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git#master
+mfd-lj		git	git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git#for-mfd-next
+battery		git	git://git.infradead.org/battery-2.6.git#master
+fbdev		git	git://git.kernel.org/pub/scm/linux/kernel/git/plagnioj/linux-fbdev.git#for-next
+viafb		git	git://github.com/schandinat/linux-2.6.git#viafb-next
+omap_dss2	git	git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git#for-next
+regulator	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git#for-next
+security	git	git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git#next
+selinux		git	git://git.infradead.org/users/pcmoore/selinux#next
+lblnet		git	git://git.infradead.org/users/pcmoore/lblnet#next
+watchdog	git	git://www.linux-watchdog.org/linux-watchdog-next.git#master
+iommu		git	git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git#next
+dwmw2-iommu	git	git://git.infradead.org/iommu-2.6.git#master
+vfio		git	git://github.com/awilliam/linux-vfio.git#next
+osd		git	git://git.open-osd.org/linux-open-osd.git#linux-next
+jc_docs		git	git://git.lwn.net/linux-2.6.git#docs-next
+trivial		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git#for-next
+audit		git	git://git.infradead.org/users/eparis/audit.git#master
+fsnotify	git	git://git.infradead.org/users/eparis/notify.git#for-next
+devicetree	git	git://git.secretlab.ca/git/linux-2.6#devicetree/next
+dt-rh		git	git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git#for-next
+spi		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git#for-next
+tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git#auto-latest
+clockevents	git	git://git.linaro.org/people/daniel.lezcano/linux.git#clockevents/next
+edac		git	git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git#linux_next
+edac-amd	git	git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git#for-next
+ftrace		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git#for-next
+rcu		git	git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git#rcu/next
+uprobes		git	git://github.com/srikard/linux.git#for-next
+kvm		git	git://git.kernel.org/pub/scm/virt/kvm/kvm.git#linux-next
+kvm-arm		git	git://github.com/columbia/linux-kvm-arm.git#kvm-arm-next
+kvm-ppc		git	git://github.com/agraf/linux-2.6.git#kvm-ppc-next
+oprofile	git	git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile.git#for-next
+fw-nohz		git	git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks.git#nohz/next
+xen-tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git#linux-next
+percpu		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git#for-next
+workqueues	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git#for-next
+drivers-x86	git	git://cavan.codon.org.uk/platform-drivers-x86.git#linux-next
+chrome-platform	git	git://git.kernel.org/pub/scm/linux/kernel/git/olof/chrome-platform.git#for-next
+sysctl		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl.git#master
+regmap		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git#for-next
+hsi		git	git://gitorious.org/kernel-hsi/kernel-hsi.git#for-next
+leds		git	git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git#for-next
+driver-core	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-next
+tty		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-next
+usb		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-next
+usb-gadget	git	git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git#next
+staging		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-next
+char-misc	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-next
+cgroup		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git#for-next
+scsi		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git#for-next
+target-updates	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next
+target-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next-merge
+writeback	git	git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux.git#writeback-for-next
+hwspinlock	git	git://github.com/ohadbc/hwspinlock-next.git#linux-next
+pinctrl		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git#for-next
+vhost		git	git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git#linux-next
+remoteproc	git	git://git.kernel.org/pub/scm/linux/kernel/git/ohad/remoteproc.git#for-next
+rpmsg		git	git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg.git#for-next
+gpio		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git#for-next
+dma-mapping	git	git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git#dma-mapping-next
+pwm		git	git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git#for-next
+dma-buf		git	git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git#for-next
+userns		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git#for-next
+ktest		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-ktest.git#for-next
+signal		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal.git#for-next
+clk		git	git://git.linaro.org/people/mturquette/linux.git#clk-next
+random		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random.git#dev
+lzo-update	git	git://github.com/markus-oberhumer/linux.git#lzo-update
+arm64-hugepages	git	git://git.linaro.org/people/stevecapper/linux.git#for-next/hugepages
+aio		git	git://git.kvack.org/~bcrl/aio-next.git#master
+llvmlinux	git	git://git.linuxfoundation.org/llvmlinux/kernel.git#for-next
+powernv-cpuidle	git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#powernv-cpuidle
+rd-docs		quilt	http://www.infradead.org/~rdunlap/Doc/patches/
+akpm-current	mmotm	http://www.ozlabs.org/~akpm/mmotm/
+akpm		mmotm	http://www.ozlabs.org/~akpm/mmotm/
diff --git a/Next/merge.log b/Next/merge.log
new file mode 100644
index 000000000000..31a4d507efda
--- /dev/null
+++ b/Next/merge.log
@@ -0,0 +1,3404 @@
+$ date
+Thursday 17 April  11:11:49 EST 2014
+$ git checkout master
+Already on 'master'
+$ git reset --hard stable
+HEAD is now at 55101e2d6ce1 Merge git://git.kernel.org/pub/scm/virt/kvm/kvm
+Merging origin/master (6ca2a88ad820 Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip)
+$ git merge origin/master
+Updating 55101e2d6ce1..6ca2a88ad820
+Fast-forward
+ .../bindings/pinctrl/brcm,bcm11351-pinctrl.txt     |    2 +-
+ MAINTAINERS                                        |    2 +-
+ arch/arm/configs/bcm_defconfig                     |    2 +-
+ arch/ia64/kernel/head.S                            |    2 +-
+ arch/ia64/kernel/ivt.S                             |    2 +-
+ arch/ia64/kvm/vmm_ivt.S                            |    2 +-
+ arch/s390/include/asm/sigp.h                       |   19 +
+ arch/s390/include/asm/smp.h                        |   13 +-
+ arch/s390/include/uapi/asm/unistd.h                |    3 +-
+ arch/s390/kernel/compat_wrapper.c                  |    3 +-
+ arch/s390/kernel/dumpstack.c                       |    8 +-
+ arch/s390/kernel/ptrace.c                          |    2 +-
+ arch/s390/kernel/setup.c                           |   32 +
+ arch/s390/kernel/smp.c                             |   15 -
+ arch/s390/kernel/syscalls.S                        |    1 +
+ arch/s390/lib/uaccess.c                            |    5 +-
+ arch/s390/mm/fault.c                               |  140 +-
+ arch/x86/Makefile                                  |    4 +-
+ arch/x86/kernel/cpu/perf_event_intel_rapl.c        |   33 +-
+ arch/x86/kernel/early-quirks.c                     |    2 +-
+ arch/x86/kernel/reboot.c                           |   72 +-
+ arch/x86/syscalls/Makefile                         |    2 +
+ arch/x86/syscalls/syscall_32.tbl                   |    1 +
+ arch/x86/tools/Makefile                            |    2 +
+ drivers/irqchip/irq-vic.c                          |    6 +
+ drivers/net/ethernet/broadcom/bnx2.c               |    2 +-
+ drivers/net/ethernet/cadence/Kconfig               |    6 +-
+ drivers/net/ethernet/chelsio/cxgb4/l2t.c           |    4 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c         |    2 +-
+ drivers/net/ethernet/emulex/benet/be.h             |    1 +
+ drivers/net/ethernet/emulex/benet/be_main.c        |   17 +-
+ drivers/net/ethernet/marvell/mvneta.c              |   41 +-
+ drivers/net/ethernet/mellanox/mlx4/main.c          |  181 +--
+ drivers/net/ethernet/mellanox/mlx4/mlx4.h          |    1 +
+ .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c  |   21 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c    |    3 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c    |    2 -
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   33 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c   |   10 +
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c  |   31 +-
+ drivers/net/ieee802154/at86rf230.c                 |   10 +-
+ drivers/net/vxlan.c                                |    4 +-
+ drivers/net/wan/cosa.c                             |    4 -
+ drivers/pinctrl/Kconfig                            |    8 +-
+ drivers/pinctrl/Makefile                           |    2 +-
+ drivers/pinctrl/pinctrl-bcm281xx.c                 | 1461 ++++++++++++++++++++
+ drivers/pinctrl/pinctrl-capri.c                    | 1454 -------------------
+ drivers/pinctrl/pinctrl-msm.c                      |    6 +-
+ drivers/pinctrl/pinctrl-msm.h                      |    1 +
+ drivers/pinctrl/pinctrl-nomadik.c                  |    1 -
+ drivers/pinctrl/pinctrl-rockchip.c                 |   48 +-
+ drivers/s390/char/sclp.c                           |    2 +-
+ drivers/s390/char/sclp_cmd.c                       |    2 +-
+ drivers/s390/char/sclp_vt220.c                     |   14 +-
+ drivers/video/Kconfig                              |    2 +
+ drivers/video/bf54x-lq043fb.c                      |    2 +-
+ drivers/video/da8xx-fb.c                           |   10 +-
+ drivers/video/omap2/dss/dispc.c                    |   67 +-
+ drivers/video/omap2/dss/dsi.c                      |   20 +
+ drivers/video/omap2/dss/dss.c                      |    4 +-
+ drivers/video/omap2/dss/dss.h                      |    6 -
+ drivers/video/omap2/dss/hdmi_common.c              |    8 +-
+ include/linux/filter.h                             |    1 -
+ include/linux/netfilter/nf_conntrack_proto_gre.h   |    1 -
+ include/linux/reboot.h                             |   14 +-
+ include/net/dst.h                                  |   14 +-
+ include/net/inet6_connection_sock.h                |    2 +-
+ include/net/inet_connection_sock.h                 |    2 +-
+ include/net/ip.h                                   |   13 +-
+ include/net/ip6_route.h                            |    5 +
+ include/net/ip_tunnels.h                           |    2 +-
+ include/net/ipv6.h                                 |    2 +-
+ include/net/netfilter/nf_tables_core.h             |   10 +
+ include/net/sctp/structs.h                         |   14 +-
+ include/net/xfrm.h                                 |    6 +-
+ kernel/locking/mutex-debug.c                       |   19 +-
+ kernel/seccomp.c                                   |   17 +-
+ net/core/dev.c                                     |    2 +-
+ net/core/dst.c                                     |   15 +-
+ net/core/filter.c                                  |    9 +-
+ net/dccp/output.c                                  |    2 +-
+ net/decnet/dn_route.c                              |   16 +-
+ net/ipv4/ip_output.c                               |   16 +-
+ net/ipv4/ip_tunnel.c                               |    2 +-
+ net/ipv4/ip_tunnel_core.c                          |    4 +-
+ net/ipv4/ping.c                                    |   15 +-
+ net/ipv4/route.c                                   |    6 +-
+ net/ipv4/tcp_output.c                              |    2 +-
+ net/ipv4/xfrm4_output.c                            |    2 +-
+ net/ipv6/inet6_connection_sock.c                   |    3 +-
+ net/ipv6/ip6_gre.c                                 |   10 +
+ net/ipv6/ip6_output.c                              |    2 +-
+ net/ipv6/route.c                                   |   19 +-
+ net/ipv6/sit.c                                     |    5 +-
+ net/ipv6/xfrm6_output.c                            |    2 +-
+ net/l2tp/l2tp_core.c                               |    4 +-
+ net/l2tp/l2tp_ip.c                                 |    2 +-
+ net/netfilter/nf_conntrack_core.c                  |    1 +
+ net/netfilter/nf_conntrack_pptp.c                  |   20 +-
+ net/netfilter/nf_conntrack_proto_gre.c             |    3 +-
+ net/netfilter/nf_tables_core.c                     |    3 +-
+ net/netfilter/nft_cmp.c                            |    2 +-
+ net/openvswitch/vport-gre.c                        |    2 +-
+ net/sctp/associola.c                               |   82 +-
+ net/sctp/protocol.c                                |    2 +-
+ net/sctp/sm_statefuns.c                            |    2 +-
+ net/sctp/socket.c                                  |    6 +
+ net/sctp/ulpevent.c                                |    8 +-
+ net/xfrm/xfrm_policy.c                             |    2 +-
+ tools/lib/lockdep/Makefile                         |   15 +-
+ tools/lib/lockdep/uinclude/linux/lockdep.h         |    3 +
+ tools/lib/traceevent/event-parse.c                 |  109 +-
+ tools/perf/Documentation/perf-bench.txt            |   22 +
+ tools/perf/Documentation/perf-top.txt              |    1 -
+ tools/perf/Makefile.perf                           |    4 +-
+ tools/perf/bench/numa.c                            |    4 +
+ tools/perf/builtin-stat.c                          |   11 +-
+ tools/perf/config/Makefile                         |    7 +-
+ tools/perf/tests/code-reading.c                    |    1 +
+ tools/perf/util/probe-finder.c                     |   15 +-
+ 120 files changed, 2503 insertions(+), 1948 deletions(-)
+ create mode 100644 drivers/pinctrl/pinctrl-bcm281xx.c
+ delete mode 100644 drivers/pinctrl/pinctrl-capri.c
+Merging fixes/master (b0031f227e47 Merge tag 's2mps11-build' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator)
+$ git merge fixes/master
+Already up-to-date.
+Merging kbuild-current/rc-fixes (38dbfb59d117 Linus 3.14-rc1)
+$ git merge kbuild-current/rc-fixes
+Already up-to-date.
+Merging arc-current/for-curr (0409726a81f2 ARC: fix mmuv2 warning)
+$ git merge arc-current/for-curr
+Merge made by the 'recursive' strategy.
+ arch/arc/include/asm/irq.h       |  2 --
+ arch/arc/kernel/irq.c            | 18 ------------------
+ arch/arc/mm/cache_arc700.c       |  4 ++++
+ arch/arc/plat-arcfpga/Makefile   |  2 +-
+ arch/arc/plat-arcfpga/platform.c |  4 ++--
+ arch/arc/plat-arcfpga/smp.c      | 18 ++++++++++++++++++
+ 6 files changed, 25 insertions(+), 23 deletions(-)
+Merging arm-current/fixes (c9d347e02776 ARM: 8009/1: dcscb.c: remove call to outer_flush_all())
+$ git merge arm-current/fixes
+Already up-to-date.
+Merging m68k-current/for-linus (50be9eba831d m68k: Update defconfigs for v3.14-rc1)
+$ git merge m68k-current/for-linus
+Already up-to-date.
+Merging metag-fixes/fixes (0414855fdc4a Linux 3.14-rc5)
+$ git merge metag-fixes/fixes
+Already up-to-date.
+Merging powerpc-merge/merge (cc4f265ad9a3 powerpc/powernv Adapt opal-elog and opal-dump to new sysfs_remove_file_self)
+$ git merge powerpc-merge/merge
+Already up-to-date.
+Merging sparc/master (455c6fdbd219 Linux 3.14)
+$ git merge sparc/master
+Already up-to-date.
+Merging net/master (0acf07d240a8 seccomp: fix memory leak on filter attach)
+$ git merge net/master
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/net/ethernet.txt |  2 +-
+ drivers/isdn/icn/icn.c                             | 11 ++--
+ drivers/net/ethernet/marvell/mvneta.c              | 73 ++++++++++------------
+ drivers/net/ethernet/mellanox/mlx4/en_cq.c         |  1 -
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c     |  6 +-
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h       |  1 -
+ drivers/net/ethernet/sfc/ef10.c                    | 12 +++-
+ drivers/net/ethernet/sfc/efx.c                     | 19 +++++-
+ drivers/net/ethernet/sfc/enum.h                    | 23 ++++---
+ drivers/net/ethernet/sfc/falcon.c                  |  4 ++
+ drivers/net/ethernet/sfc/farch.c                   | 22 +++++++
+ drivers/net/ethernet/sfc/mcdi.c                    | 55 ++++++++++++----
+ drivers/net/ethernet/sfc/mcdi.h                    | 13 ++++
+ drivers/net/ethernet/sfc/net_driver.h              |  4 ++
+ drivers/net/ethernet/sfc/nic.h                     |  1 +
+ drivers/net/ethernet/sfc/siena.c                   |  2 +
+ drivers/net/phy/mdio-gpio.c                        | 68 +++++++++++++-------
+ include/linux/mdio-gpio.h                          |  5 ++
+ include/linux/phy.h                                |  3 +
+ include/net/flow.h                                 | 10 ++-
+ include/net/net_namespace.h                        |  9 +--
+ kernel/seccomp.c                                   |  2 +
+ net/ipv4/fib_frontend.c                            |  2 +-
+ net/ipv4/fib_semantics.c                           |  1 +
+ net/ipv4/ip_tunnel.c                               | 15 +++--
+ net/ipv4/ipmr.c                                    |  2 +-
+ net/ipv4/netfilter/ipt_rpfilter.c                  |  5 +-
+ net/ipv4/route.c                                   |  3 +-
+ net/ipv6/ip6_tunnel.c                              |  8 +--
+ net/ipv6/ip6mr.c                                   |  2 +-
+ net/ipv6/sit.c                                     | 17 ++---
+ net/socket.c                                       |  4 +-
+ 32 files changed, 264 insertions(+), 141 deletions(-)
+Merging ipsec/master (a32452366b72 vti4: Don't count header length twice.)
+$ git merge ipsec/master
+Recorded preimage for 'net/ipv4/ip_vti.c'
+Auto-merging net/ipv6/xfrm6_output.c
+Auto-merging net/ipv4/xfrm4_output.c
+Auto-merging net/ipv4/ip_vti.c
+CONFLICT (content): Merge conflict in net/ipv4/ip_vti.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'net/ipv4/ip_vti.c'.
+[master 09f4582d3e5c] Merge remote-tracking branch 'ipsec/master'
+$ git diff -M --stat --summary HEAD^..
+ net/ipv4/ip_vti.c       |  1 -
+ net/ipv4/xfrm4_output.c | 32 ++++++++++++++++++--------------
+ net/ipv6/xfrm6_output.c | 22 +++++++++++++---------
+ 3 files changed, 31 insertions(+), 24 deletions(-)
+Merging sound-current/for-linus (8dc9abb93dde ALSA: hda/realtek - Add headset Mic support for Dell machine)
+$ git merge sound-current/for-linus
+Merge made by the 'recursive' strategy.
+ sound/isa/es18xx.c            | 10 +++++-----
+ sound/pci/hda/patch_realtek.c |  5 +++++
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+Merging pci-current/for-linus (f5d3352b2751 PCI: tegra: Use new OF interrupt mapping when possible)
+$ git merge pci-current/for-linus
+Merge made by the 'recursive' strategy.
+ arch/powerpc/kernel/pci_64.c       | 10 ++++++----
+ drivers/pci/host/pci-rcar-gen2.c   |  8 +++++++-
+ drivers/pci/host/pci-tegra.c       |  7 ++++++-
+ drivers/pci/host/pcie-designware.c | 20 +++++++++++++-------
+ 4 files changed, 32 insertions(+), 13 deletions(-)
+Merging wireless/master (f8d2b9209ad6 mwifiex: fix hung task on command timeout)
+$ git merge wireless/master
+Merge made by the 'recursive' strategy.
+ drivers/net/wireless/cw1200/debug.c         |   2 +
+ drivers/net/wireless/iwlwifi/iwl-7000.c     |   5 +-
+ drivers/net/wireless/iwlwifi/mvm/coex.c     |  18 +-
+ drivers/net/wireless/iwlwifi/mvm/mac80211.c |   1 +
+ drivers/net/wireless/iwlwifi/mvm/rs.c       | 261 ++++++++++++++++++----------
+ drivers/net/wireless/iwlwifi/mvm/rs.h       |  14 +-
+ drivers/net/wireless/iwlwifi/mvm/sf.c       |   3 +-
+ drivers/net/wireless/iwlwifi/pcie/drv.c     |   2 +
+ drivers/net/wireless/mwifiex/main.c         |  12 +-
+ drivers/net/wireless/mwifiex/sta_ioctl.c    |   7 +-
+ drivers/net/wireless/rsi/rsi_91x_core.c     |   2 +-
+ drivers/net/wireless/rsi/rsi_91x_mgmt.c     |  21 +--
+ drivers/net/wireless/ti/wl18xx/event.h      |  20 +++
+ drivers/net/wireless/ti/wlcore/event.c      |   5 +
+ net/mac80211/chan.c                         |  11 +-
+ net/mac80211/main.c                         |   4 +-
+ net/mac80211/offchannel.c                   |   1 +
+ net/mac80211/status.c                       |   1 +
+ 18 files changed, 258 insertions(+), 132 deletions(-)
+Merging driver-core.current/driver-core-linus (98b0f811aade Documentation: Update stable address in Chinese and Japanese translations)
+$ git merge driver-core.current/driver-core-linus
+Merge made by the 'recursive' strategy.
+ Documentation/ja_JP/HOWTO                   |  2 +-
+ Documentation/ja_JP/stable_kernel_rules.txt |  6 +-
+ Documentation/stable_kernel_rules.txt       |  2 +-
+ Documentation/zh_CN/HOWTO                   |  2 +-
+ Documentation/zh_CN/io_ordering.txt         | 67 +++++++++++++++++++++
+ Documentation/zh_CN/stable_kernel_rules.txt |  2 +-
+ drivers/base/core.c                         | 33 -----------
+ drivers/base/topology.c                     |  3 +-
+ fs/kernfs/inode.c                           | 14 +++--
+ fs/super.c                                  |  5 +-
+ fs/sysfs/file.c                             | 92 -----------------------------
+ include/linux/device.h                      | 11 +---
+ include/linux/sysfs.h                       |  9 ---
+ 13 files changed, 90 insertions(+), 158 deletions(-)
+ create mode 100644 Documentation/zh_CN/io_ordering.txt
+Merging tty.current/tty-linus (1e7da0530423 serial: amba-pl011: fix regression, causing an Oops on rmmod)
+$ git merge tty.current/tty-linus
+Removing Documentation/serial/sx.txt
+Removing Documentation/serial/specialix.txt
+Removing Documentation/serial/riscom8.txt
+Removing Documentation/serial/digiepca.txt
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/serial/efm32-uart.txt      |   4 +-
+ Documentation/kernel-parameters.txt                |  13 -
+ Documentation/magic-number.txt                     |  12 -
+ Documentation/serial/00-INDEX                      |   8 -
+ Documentation/serial/digiepca.txt                  |  98 ------
+ Documentation/serial/riscom8.txt                   |  36 --
+ Documentation/serial/specialix.txt                 | 383 ---------------------
+ Documentation/serial/sx.txt                        | 294 ----------------
+ Documentation/zh_CN/magic-number.txt               |  12 -
+ drivers/char/Kconfig                               |   2 +-
+ drivers/char/pcmcia/Kconfig                        |   2 +-
+ drivers/char/ttyprintk.c                           |  15 +-
+ drivers/tty/serial/8250/8250_core.c                |   3 +-
+ drivers/tty/serial/Kconfig                         |   1 +
+ drivers/tty/serial/amba-pl011.c                    |   8 +-
+ drivers/tty/serial/clps711x.c                      |  20 +-
+ drivers/tty/serial/efm32-uart.c                    |   3 +
+ drivers/tty/serial/omap-serial.c                   |  30 +-
+ drivers/tty/serial/serial_core.c                   |   5 +-
+ drivers/tty/serial/st-asc.c                        |   4 +-
+ drivers/tty/tty_io.c                               |   4 +-
+ firmware/WHENCE                                    |  10 -
+ 22 files changed, 58 insertions(+), 909 deletions(-)
+ delete mode 100644 Documentation/serial/digiepca.txt
+ delete mode 100644 Documentation/serial/riscom8.txt
+ delete mode 100644 Documentation/serial/specialix.txt
+ delete mode 100644 Documentation/serial/sx.txt
+Merging usb.current/usb-linus (94d72f008909 uas: fix deadlocky memory allocations)
+$ git merge usb.current/usb-linus
+Merge made by the 'recursive' strategy.
+ drivers/usb/class/cdc-acm.c       | 34 +++++++++++++++++++++++++---------
+ drivers/usb/core/hcd-pci.c        |  2 +-
+ drivers/usb/host/ehci-exynos.c    |  2 ++
+ drivers/usb/host/ehci-platform.c  |  2 ++
+ drivers/usb/host/ehci-tegra.c     | 23 +++++++++++++++++++++++
+ drivers/usb/host/ohci-jz4740.c    |  6 +++---
+ drivers/usb/serial/cp210x.c       |  1 +
+ drivers/usb/serial/ftdi_sio.c     | 33 +++++++++++++++++++++++++++++++++
+ drivers/usb/serial/ftdi_sio_ids.h | 37 +++++++++++++++++++++++++++++++++++++
+ drivers/usb/serial/option.c       |  2 ++
+ drivers/usb/serial/pl2303.c       |  3 +++
+ drivers/usb/serial/pl2303.h       |  5 ++++-
+ drivers/usb/serial/sierra.c       |  1 -
+ drivers/usb/serial/usb_wwan.c     |  9 +++------
+ drivers/usb/storage/uas.c         | 13 +++++++------
+ drivers/usb/usb-common.c          |  2 +-
+ drivers/uwb/drp.c                 |  5 ++++-
+ 17 files changed, 151 insertions(+), 29 deletions(-)
+Merging staging.current/staging-linus (33c84bc14c25 staging: r8188eu: Fix case where ethtype was never obtained and always be checked against 0)
+$ git merge staging.current/staging-linus
+Removing drivers/staging/rtl8187se/r8185b_init.c
+Removing drivers/staging/rtl8187se/r8180_wx.h
+Removing drivers/staging/rtl8187se/r8180_wx.c
+Removing drivers/staging/rtl8187se/r8180_rtl8225z2.c
+Removing drivers/staging/rtl8187se/r8180_rtl8225.h
+Removing drivers/staging/rtl8187se/r8180_hw.h
+Removing drivers/staging/rtl8187se/r8180_dm.h
+Removing drivers/staging/rtl8187se/r8180_dm.c
+Removing drivers/staging/rtl8187se/r8180_core.c
+Removing drivers/staging/rtl8187se/r8180_93cx6.h
+Removing drivers/staging/rtl8187se/r8180.h
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+Removing drivers/staging/rtl8187se/ieee80211/ieee80211.h
+Removing drivers/staging/rtl8187se/ieee80211/dot11d.h
+Removing drivers/staging/rtl8187se/ieee80211/dot11d.c
+Removing drivers/staging/rtl8187se/TODO
+Removing drivers/staging/rtl8187se/Module.symvers
+Removing drivers/staging/rtl8187se/Makefile
+Removing drivers/staging/rtl8187se/Kconfig
+Merge made by the 'recursive' strategy.
+ drivers/staging/Kconfig                            |    2 -
+ drivers/staging/Makefile                           |    1 -
+ drivers/staging/comedi/comedi_buf.c                |   37 +-
+ drivers/staging/comedi/comedi_fops.c               |   18 +-
+ drivers/staging/comedi/comedi_internal.h           |    2 +
+ drivers/staging/goldfish/goldfish_audio.c          |    1 +
+ drivers/staging/gs_fpgaboot/Makefile               |    2 -
+ drivers/staging/gs_fpgaboot/gs_fpgaboot.c          |    1 -
+ drivers/staging/rtl8187se/Kconfig                  |   10 -
+ drivers/staging/rtl8187se/Makefile                 |   38 -
+ drivers/staging/rtl8187se/Module.symvers           |    0
+ drivers/staging/rtl8187se/TODO                     |   13 -
+ drivers/staging/rtl8187se/ieee80211/dot11d.c       |  189 -
+ drivers/staging/rtl8187se/ieee80211/dot11d.h       |   71 -
+ drivers/staging/rtl8187se/ieee80211/ieee80211.h    | 1496 --------
+ .../staging/rtl8187se/ieee80211/ieee80211_crypt.c  |  240 --
+ .../staging/rtl8187se/ieee80211/ieee80211_crypt.h  |   86 -
+ .../rtl8187se/ieee80211/ieee80211_crypt_ccmp.c     |  455 ---
+ .../rtl8187se/ieee80211/ieee80211_crypt_tkip.c     |  740 ----
+ .../rtl8187se/ieee80211/ieee80211_crypt_wep.c      |  277 --
+ .../staging/rtl8187se/ieee80211/ieee80211_module.c |  203 --
+ drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c | 1486 --------
+ .../rtl8187se/ieee80211/ieee80211_softmac.c        | 2711 --------------
+ .../rtl8187se/ieee80211/ieee80211_softmac_wx.c     |  567 ---
+ drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c |  591 ---
+ drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c |  713 ----
+ drivers/staging/rtl8187se/r8180.h                  |  640 ----
+ drivers/staging/rtl8187se/r8180_93cx6.h            |   54 -
+ drivers/staging/rtl8187se/r8180_core.c             | 3775 --------------------
+ drivers/staging/rtl8187se/r8180_dm.c               | 1139 ------
+ drivers/staging/rtl8187se/r8180_dm.h               |   23 -
+ drivers/staging/rtl8187se/r8180_hw.h               |  588 ---
+ drivers/staging/rtl8187se/r8180_rtl8225.h          |   34 -
+ drivers/staging/rtl8187se/r8180_rtl8225z2.c        |  811 -----
+ drivers/staging/rtl8187se/r8180_wx.c               | 1409 --------
+ drivers/staging/rtl8187se/r8180_wx.h               |   21 -
+ drivers/staging/rtl8187se/r8185b_init.c            | 1464 --------
+ drivers/staging/rtl8188eu/core/rtw_recv.c          |   19 +-
+ drivers/staging/rtl8188eu/os_dep/ioctl_linux.c     |   74 +-
+ drivers/staging/rtl8712/rtl871x_recv.c             |   13 +-
+ drivers/staging/rtl8723au/core/rtw_ieee80211.c     |   46 +-
+ drivers/staging/rtl8723au/core/rtw_mlme_ext.c      |    2 +-
+ drivers/staging/rtl8723au/core/rtw_p2p.c           |    4 +-
+ drivers/staging/rtl8723au/core/rtw_wlan_util.c     |    4 +-
+ drivers/staging/rtl8821ae/base.c                   |   10 +-
+ drivers/staging/speakup/main.c                     |   18 +-
+ drivers/staging/unisys/uislib/uislib.c             |    4 +-
+ drivers/staging/unisys/visorchipset/visorchipset.h |    4 +-
+ .../unisys/visorchipset/visorchipset_main.c        |    8 +-
+ .../usbip/userspace/libsrc/usbip_host_driver.c     |    7 +-
+ drivers/staging/usbip/vhci_sysfs.c                 |    2 +-
+ drivers/staging/vme/devices/vme_user.c             |    9 +-
+ 52 files changed, 154 insertions(+), 19978 deletions(-)
+ delete mode 100644 drivers/staging/rtl8187se/Kconfig
+ delete mode 100644 drivers/staging/rtl8187se/Makefile
+ delete mode 100644 drivers/staging/rtl8187se/Module.symvers
+ delete mode 100644 drivers/staging/rtl8187se/TODO
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/dot11d.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/dot11d.h
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211.h
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+ delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+ delete mode 100644 drivers/staging/rtl8187se/r8180.h
+ delete mode 100644 drivers/staging/rtl8187se/r8180_93cx6.h
+ delete mode 100644 drivers/staging/rtl8187se/r8180_core.c
+ delete mode 100644 drivers/staging/rtl8187se/r8180_dm.c
+ delete mode 100644 drivers/staging/rtl8187se/r8180_dm.h
+ delete mode 100644 drivers/staging/rtl8187se/r8180_hw.h
+ delete mode 100644 drivers/staging/rtl8187se/r8180_rtl8225.h
+ delete mode 100644 drivers/staging/rtl8187se/r8180_rtl8225z2.c
+ delete mode 100644 drivers/staging/rtl8187se/r8180_wx.c
+ delete mode 100644 drivers/staging/rtl8187se/r8180_wx.h
+ delete mode 100644 drivers/staging/rtl8187se/r8185b_init.c
+Merging char-misc.current/char-misc-linus (03367ef5ea81 Drivers: hv: vmbus: Negotiate version 3.0 when running on ws2012r2 hosts)
+$ git merge char-misc.current/char-misc-linus
+Merge made by the 'recursive' strategy.
+ drivers/hv/connection.c             |   5 +-
+ drivers/mcb/mcb-parse.c             |   1 +
+ drivers/misc/Kconfig                |   4 +-
+ drivers/misc/genwqe/card_base.h     |  58 ++++++++----
+ drivers/misc/genwqe/card_ddcb.c     |   6 +-
+ drivers/misc/genwqe/card_dev.c      |  44 ++++------
+ drivers/misc/genwqe/card_utils.c    | 170 +++++++++++++++++++++++++++---------
+ drivers/misc/genwqe/genwqe_driver.h |   2 +-
+ drivers/misc/mei/hw-me-regs.h       |   5 ++
+ drivers/misc/mei/interrupt.c        |   3 +-
+ drivers/misc/mei/main.c             |   3 +-
+ drivers/misc/mei/pci-me.c           |  30 +++++--
+ drivers/vme/bridges/vme_tsi148.c    |  22 +++--
+ drivers/w1/w1.c                     |  32 ++-----
+ drivers/w1/w1_netlink.c             |  44 ++++++----
+ include/linux/hyperv.h              |   4 +-
+ include/uapi/linux/hyperv.h         |   1 +
+ tools/hv/hv_fcopy_daemon.c          |   4 +-
+ 18 files changed, 280 insertions(+), 158 deletions(-)
+Merging input-current/for-linus (692d96552c9a Merge branch 'next' into for-linus)
+$ git merge input-current/for-linus
+Already up-to-date.
+Merging md-current/for-linus (d47648fcf061 raid5: avoid finding "discard" stripe)
+$ git merge md-current/for-linus
+Already up-to-date.
+Merging crypto-current/master (eb4a5346e777 hwrng: bcm2835 - fix oops when rng h/w is accessed during registration)
+$ git merge crypto-current/master
+Already up-to-date.
+Merging ide/master (5b40dd30bbfa ide: Fix SC1200 dependencies)
+$ git merge ide/master
+Merge made by the 'recursive' strategy.
+ drivers/ide/Kconfig     | 5 ++++-
+ drivers/ide/ide-probe.c | 8 +++++---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+Merging dwmw2/master (5950f0803ca9 pcmcia: remove RPX board stuff)
+$ git merge dwmw2/master
+Already up-to-date.
+Merging devicetree-current/devicetree/merge (1f42e5dd5065 of: Add self test for of_match_node())
+$ git merge devicetree-current/devicetree/merge
+Already up-to-date.
+Merging rr-fixes/fixes (7122c3e9154b scripts/link-vmlinux.sh: only filter kernel symbols for arm)
+$ git merge rr-fixes/fixes
+Already up-to-date.
+Merging mfd-fixes/master (73beb63d290f mfd: rtsx_pcr: Disable interrupts before cancelling delayed works)
+$ git merge mfd-fixes/master
+Already up-to-date.
+Merging vfio-fixes/for-linus (239a87020b26 Merge branch 'for-joerg/arm-smmu/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into for-linus)
+$ git merge vfio-fixes/for-linus
+Already up-to-date.
+Merging drm-intel-fixes/for-linux-next-fixes (b6842feb63a2 drm/i915: Allow user modes to exceed DVI 165MHz limit)
+$ git merge drm-intel-fixes/for-linux-next-fixes
+Merge made by the 'recursive' strategy.
+ drivers/gpu/drm/drm_mm.c                   |   2 -
+ drivers/gpu/drm/i915/i915_drv.h            |   9 +-
+ drivers/gpu/drm/i915/i915_gem.c            |   2 +-
+ drivers/gpu/drm/i915/i915_gem_context.c    | 218 ++++++++++++-----------------
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c |   2 +-
+ drivers/gpu/drm/i915/intel_bios.c          |  10 ++
+ drivers/gpu/drm/i915/intel_bios.h          |   3 +
+ drivers/gpu/drm/i915/intel_hdmi.c          |   9 +-
+ drivers/gpu/drm/i915/intel_panel.c         |   5 +
+ drivers/gpu/drm/i915/intel_pm.c            |  10 ++
+ 10 files changed, 127 insertions(+), 143 deletions(-)
+Merging asm-generic/master (fb9de7ebc3a2 xtensa: Use generic asm/mmu.h for nommu)
+$ git merge asm-generic/master
+Already up-to-date.
+Merging arc/for-next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge arc/for-next
+Already up-to-date.
+Merging arm/for-next (98f07013149d Merge branch 'devel-stable' into for-next)
+$ git merge arm/for-next
+Already up-to-date.
+Merging arm-kvm-cpuresume/arm-kvm-cpuresume (91a3f6af430d arm: kernel: sleep: restore HYP mode configuration in cpu_resume)
+$ git merge arm-kvm-cpuresume/arm-kvm-cpuresume
+Auto-merging arch/arm/include/asm/assembler.h
+Merge made by the 'recursive' strategy.
+ arch/arm/include/asm/assembler.h | 2 +-
+ arch/arm/kernel/sleep.S          | 5 ++++-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+Merging arm-perf/for-next/perf (c9eaa447e77e Linux 3.15-rc1)
+$ git merge arm-perf/for-next/perf
+Already up-to-date.
+Merging arm-soc/for-next (2bf73dd61a84 Merge tag 'tags/cleanup2-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc)
+$ git merge arm-soc/for-next
+Already up-to-date.
+Merging bcm2835/for-next (fa389e220254 Linux 3.14-rc6)
+$ git merge bcm2835/for-next
+Already up-to-date.
+Merging berlin/berlin/for-next (e49c50df1e18 Merge branch 'berlin/dt' into berlin/for-next)
+$ git merge berlin/berlin/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/arm/Marvell/README                   |   5 +
+ .../devicetree/bindings/arm/marvell,berlin.txt     |   1 +
+ arch/arm/boot/dts/Makefile                         |   3 +-
+ arch/arm/boot/dts/berlin2.dtsi                     |  10 +
+ arch/arm/boot/dts/berlin2q-marvell-dmp.dts         |  28 ++
+ arch/arm/boot/dts/berlin2q.dtsi                    | 336 +++++++++++++++++++++
+ arch/arm/mach-berlin/Kconfig                       |   8 +
+ 7 files changed, 390 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+ create mode 100644 arch/arm/boot/dts/berlin2q.dtsi
+Merging cortex-m/for-next (f0d7515372ff ARM: v7m: add trivial suspend support)
+$ git merge cortex-m/for-next
+Already up-to-date.
+Merging ep93xx/ep93xx-for-next (bfb0709fd17b Merge branch 'ep93xx-fixes' into ep93xx-for-next)
+$ git merge ep93xx/ep93xx-for-next
+Merge made by the 'recursive' strategy.
+Merging imx-mxs/for-next (1e9dfe21eca8 Merge branch 'imx/dt' into for-next)
+$ git merge imx-mxs/for-next
+Removing arch/arm/mach-imx/mach-mx51_babbage.c
+Auto-merging arch/arm/boot/dts/Makefile
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/clock/imx25-clock.txt      |   3 +
+ .../devicetree/bindings/vendor-prefixes.txt        |   1 +
+ arch/arm/Kconfig.debug                             |   9 +
+ arch/arm/boot/dts/Makefile                         |   3 +
+ .../boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts  |  13 +
+ arch/arm/boot/dts/imx25-pdk.dts                    | 217 ++++++++++-
+ arch/arm/boot/dts/imx25.dtsi                       |  40 +-
+ arch/arm/boot/dts/imx27-apf27.dts                  |   1 +
+ arch/arm/boot/dts/imx27-pdk.dts                    |  48 ++-
+ arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts     |  77 +++-
+ arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi    |  20 +-
+ arch/arm/boot/dts/imx27.dtsi                       |   2 +
+ arch/arm/boot/dts/imx28-duckbill.dts               |  12 +-
+ arch/arm/boot/dts/imx28.dtsi                       |   1 +
+ arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi       |  15 +
+ .../boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts  |  22 ++
+ arch/arm/boot/dts/imx35-pdk.dts                    |  67 ++++
+ arch/arm/boot/dts/imx35.dtsi                       |  25 +-
+ arch/arm/boot/dts/imx50.dtsi                       |   5 +
+ arch/arm/boot/dts/imx51-babbage.dts                |  62 +++
+ arch/arm/boot/dts/imx51-digi-connectcore-jsk.dts   | 108 ++++++
+ arch/arm/boot/dts/imx51-digi-connectcore-som.dtsi  | 379 ++++++++++++++++++
+ arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi       |  11 +
+ .../boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts  |  58 +++
+ arch/arm/boot/dts/imx51.dtsi                       |   5 +
+ arch/arm/boot/dts/imx53-m53evk.dts                 |  23 +-
+ arch/arm/boot/dts/imx53-qsb-common.dtsi            |   3 +-
+ arch/arm/boot/dts/imx53-tx53-x03x.dts              |  11 +-
+ arch/arm/boot/dts/imx53.dtsi                       |   9 +-
+ arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts            |  48 ++-
+ arch/arm/boot/dts/imx6q-gw5400-a.dts               |   3 -
+ arch/arm/boot/dts/imx6qdl-gw52xx.dtsi              |   3 -
+ arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi     |  22 +-
+ arch/arm/boot/dts/imx6qdl-sabresd.dtsi             |  19 +
+ arch/arm/boot/dts/imx6qdl.dtsi                     |  14 +-
+ arch/arm/boot/dts/imx6sl-evk.dts                   |   1 +
+ arch/arm/boot/dts/imx6sl.dtsi                      |   5 +-
+ arch/arm/boot/dts/vf610-colibri.dts                | 123 ++++++
+ arch/arm/boot/dts/vf610-twr.dts                    |  38 ++
+ arch/arm/boot/dts/vf610.dtsi                       |  28 +-
+ arch/arm/configs/imx_v4_v5_defconfig               |   6 +
+ arch/arm/configs/imx_v6_v7_defconfig               |  10 +-
+ arch/arm/configs/mxs_defconfig                     |   5 +-
+ arch/arm/include/debug/vf.S                        |  15 +-
+ arch/arm/mach-imx/Kconfig                          |  15 -
+ arch/arm/mach-imx/Makefile                         |   1 -
+ arch/arm/mach-imx/clk-imx25.c                      |  24 +-
+ arch/arm/mach-imx/clk-imx51-imx53.c                |  20 +-
+ arch/arm/mach-imx/clk-imx6q.c                      |  12 +-
+ arch/arm/mach-imx/clk-imx6sl.c                     |   6 +-
+ arch/arm/mach-imx/common.h                         |   2 +
+ arch/arm/mach-imx/mach-mx21ads.c                   | 173 +++++----
+ arch/arm/mach-imx/mach-mx51_babbage.c              | 428 ---------------------
+ arch/arm/mach-imx/time.c                           |  15 +
+ 54 files changed, 1628 insertions(+), 658 deletions(-)
+ create mode 100644 arch/arm/boot/dts/imx35-pdk.dts
+ create mode 100644 arch/arm/boot/dts/imx51-digi-connectcore-jsk.dts
+ create mode 100644 arch/arm/boot/dts/imx51-digi-connectcore-som.dtsi
+ create mode 100644 arch/arm/boot/dts/vf610-colibri.dts
+ delete mode 100644 arch/arm/mach-imx/mach-mx51_babbage.c
+Merging ixp4xx/next (19f949f52599 Linux 3.8)
+$ git merge ixp4xx/next
+Already up-to-date.
+Merging keystone/next (47fc77cc704e Merge branch 'for_3.15/fixes' into next)
+$ git merge keystone/next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging msm/for-next (81cf1e061d00 ARM: msm: Rename msm devicetrees to have standard 'qcom' prefix)
+$ git merge msm/for-next
+Already up-to-date.
+Merging mvebu/for-next (6412d6635b67 Merge branch 'mvebu/dt-fixes-non-critical' into for-next)
+$ git merge mvebu/for-next
+Resolved 'arch/arm/boot/dts/Makefile' using previous resolution.
+Auto-merging arch/arm/boot/dts/Makefile
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 2d1726721171] Merge remote-tracking branch 'mvebu/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/boot/dts/Makefile                     | 5 ++++-
+ arch/arm/boot/dts/armada-370-xp.dtsi           | 1 +
+ arch/arm/boot/dts/armada-38x.dtsi              | 1 +
+ arch/arm/boot/dts/kirkwood-b3.dts              | 2 +-
+ arch/arm/boot/dts/kirkwood-cloudbox.dts        | 2 +-
+ arch/arm/boot/dts/kirkwood-dreamplug.dts       | 2 +-
+ arch/arm/boot/dts/kirkwood-laplug.dts          | 2 +-
+ arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts | 2 +-
+ arch/arm/boot/dts/kirkwood-ns2-common.dtsi     | 4 ++--
+ arch/arm/boot/dts/kirkwood-nsa310.dts          | 2 +-
+ arch/arm/boot/dts/kirkwood-nsa310a.dts         | 2 +-
+ arch/arm/boot/dts/kirkwood-openblocks_a6.dts   | 2 +-
+ arch/arm/boot/dts/kirkwood-openblocks_a7.dts   | 2 +-
+ 13 files changed, 17 insertions(+), 12 deletions(-)
+Merging renesas/next (47a0013abaee Merge branches 'heads/next', 'heads/boards-for-v3.16' and 'heads/dt-for-v3.16' into devel)
+$ git merge renesas/next
+Removing arch/arm/mach-shmobile/include/mach/emev2.h
+Removing arch/arm/mach-shmobile/clock-emev2.c
+Auto-merging arch/arm/boot/dts/Makefile
+Merge made by the 'recursive' strategy.
+ arch/arm/boot/dts/Makefile                         |   3 +-
+ .../boot/dts/r8a7740-armadillo800eva-reference.dts |  27 ++-
+ arch/arm/boot/dts/r8a7740.dtsi                     |   9 +-
+ arch/arm/boot/dts/r8a7778-bockw-reference.dts      |  14 ++
+ arch/arm/boot/dts/r8a7778.dtsi                     |  18 +-
+ arch/arm/boot/dts/r8a7779.dtsi                     |  18 +-
+ arch/arm/boot/dts/r8a7790-lager.dts                |  67 +++++-
+ arch/arm/boot/dts/r8a7790.dtsi                     | 122 +++++++++--
+ arch/arm/boot/dts/r8a7791-koelsch.dts              |  84 ++++++--
+ arch/arm/boot/dts/r8a7791.dtsi                     | 109 ++++++++--
+ arch/arm/boot/dts/sh73a0-kzm9g-reference.dts       |  15 +-
+ arch/arm/boot/dts/sh73a0.dtsi                      |   1 -
+ arch/arm/configs/shmobile_defconfig                |  14 ++
+ arch/arm/mach-shmobile/Kconfig                     |  17 +-
+ arch/arm/mach-shmobile/Makefile                    |   3 +-
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |   1 +
+ arch/arm/mach-shmobile/board-bockw.c               |  63 ++++--
+ arch/arm/mach-shmobile/board-koelsch-reference.c   |  86 ++++----
+ arch/arm/mach-shmobile/board-koelsch.c             |   2 +-
+ arch/arm/mach-shmobile/board-lager-reference.c     |  79 ++++---
+ arch/arm/mach-shmobile/board-lager.c               |  33 +--
+ arch/arm/mach-shmobile/clock-emev2.c               | 231 ---------------------
+ arch/arm/mach-shmobile/clock-r8a7778.c             |  22 +-
+ arch/arm/mach-shmobile/clock-r8a7790.c             |  32 ++-
+ arch/arm/mach-shmobile/clock-r8a7791.c             |  23 +-
+ arch/arm/mach-shmobile/clock.c                     |  28 +++
+ arch/arm/mach-shmobile/include/mach/clock.h        |  16 ++
+ arch/arm/mach-shmobile/include/mach/common.h       |   1 +
+ arch/arm/mach-shmobile/include/mach/emev2.h        |   9 -
+ arch/arm/mach-shmobile/setup-emev2.c               |  11 +-
+ arch/arm/mach-shmobile/setup-r8a7790.c             |  12 +-
+ arch/arm/mach-shmobile/setup-r8a7791.c             |   2 +-
+ arch/arm/mach-shmobile/setup-rcar-gen2.c           |  16 +-
+ arch/arm/mach-shmobile/smp-emev2.c                 |   1 -
+ arch/arm/mach-shmobile/smp-r8a7791.c               |  15 +-
+ arch/arm/mach-shmobile/timer.c                     |  28 +++
+ include/dt-bindings/clock/r8a7790-clock.h          |   7 +-
+ include/dt-bindings/clock/r8a7791-clock.h          |   5 +-
+ 38 files changed, 714 insertions(+), 530 deletions(-)
+ delete mode 100644 arch/arm/mach-shmobile/clock-emev2.c
+ delete mode 100644 arch/arm/mach-shmobile/include/mach/emev2.h
+Merging samsung/for-next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge samsung/for-next
+Already up-to-date.
+Merging tegra/for-next (628d56b42d35 Merge branch for-3.16/defconfig into for-next)
+$ git merge tegra/for-next
+Auto-merging arch/arm/boot/dts/Makefile
+Merge made by the 'recursive' strategy.
+ arch/arm/boot/dts/Makefile                |    1 +
+ arch/arm/boot/dts/tegra124-jetson-tk1.dts | 1791 +++++++++++++++++++++++++++++
+ arch/arm/boot/dts/tegra124-venice2.dts    |    4 +-
+ arch/arm/configs/tegra_defconfig          |    1 +
+ 4 files changed, 1796 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/tegra124-jetson-tk1.dts
+Merging arm64/for-next/core (ebf81a938dad arm64: Fix DMA range invalidation for cache line unaligned buffers)
+$ git merge arm64/for-next/core
+Already up-to-date.
+Merging blackfin/for-linus (c4a2c58d2095 blackfin: cleanup board files)
+$ git merge blackfin/for-linus
+Already up-to-date.
+Merging c6x/for-linux-next (ae72758f1dd9 c6x: fix build failure caused by cache.h)
+$ git merge c6x/for-linux-next
+Already up-to-date.
+Merging cris/for-next (cd065a010a97 CRISv10: Readd missing header)
+$ git merge cris/for-next
+Already up-to-date.
+Merging hexagon/linux-next (a9a44fdf3296 Hexagon: update CR year for elf.h)
+$ git merge hexagon/linux-next
+Already up-to-date.
+Merging ia64/next (e32634f5d57f pstore: Fix memory leak when decompress using big_oops_buf)
+$ git merge ia64/next
+Already up-to-date.
+Merging m68k/for-next (50be9eba831d m68k: Update defconfigs for v3.14-rc1)
+$ git merge m68k/for-next
+Already up-to-date.
+Merging m68knommu/for-next (2bf0787b4b42 m68k: fix a compiler warning when building for DragonBall)
+$ git merge m68knommu/for-next
+Merge made by the 'recursive' strategy.
+ arch/m68k/kernel/setup_no.c         | 13 ++++++-------
+ arch/m68k/platform/68000/m68EZ328.c |  3 ++-
+ arch/m68k/platform/68000/m68VZ328.c |  1 +
+ 3 files changed, 9 insertions(+), 8 deletions(-)
+Merging metag/for-next (2aca46ce1b5c sched: remove unused SCHED_INIT_NODE)
+$ git merge metag/for-next
+Already up-to-date.
+Merging microblaze/next (a66a626538af microblaze: Use asm-generic/io.h)
+$ git merge microblaze/next
+Already up-to-date.
+Merging mips/mips-for-linux-next (0c61dd849d8c Merge branch '3.15-fixes' into mips-for-linux-next)
+$ git merge mips/mips-for-linux-next
+Removing arch/mips/include/asm/rm9k-ocd.h
+Removing arch/mips/dec/prom/call_o32.S
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                           |   3 +
+ arch/mips/dec/ecc-berr.c              |   1 +
+ arch/mips/dec/kn02xa-berr.c           |   1 +
+ arch/mips/dec/prom/Makefile           |   1 -
+ arch/mips/dec/prom/call_o32.S         |  89 --------
+ arch/mips/fw/lib/call_o32.S           |  57 +++--
+ arch/mips/fw/sni/sniprom.c            |   3 +-
+ arch/mips/include/asm/branch.h        |  12 +
+ arch/mips/include/asm/dec/prom.h      |  48 ++--
+ arch/mips/include/asm/rm9k-ocd.h      |  56 -----
+ arch/mips/include/uapi/asm/bitfield.h |  29 +++
+ arch/mips/include/uapi/asm/inst.h     | 414 ++++++++++++++++------------------
+ arch/mips/kernel/proc.c               |   9 +-
+ arch/mips/lib/csum_partial.S          |   9 +
+ arch/mips/lib/delay.c                 |  14 +-
+ arch/mips/lib/strncpy_user.S          |  13 +-
+ arch/mips/loongson/Kconfig            |   1 -
+ arch/mips/loongson/lemote-2f/clock.c  |   5 +-
+ arch/mips/math-emu/Makefile           |   2 +
+ arch/mips/math-emu/cp1emu.c           | 185 ++++++---------
+ arch/mips/math-emu/dp_add.c           |   2 +-
+ arch/mips/math-emu/dp_cmp.c           |   2 +-
+ arch/mips/math-emu/dp_div.c           |   2 +-
+ arch/mips/math-emu/dp_fint.c          |   4 +-
+ arch/mips/math-emu/dp_flong.c         |   4 +-
+ arch/mips/math-emu/dp_frexp.c         |   2 +-
+ arch/mips/math-emu/dp_fsp.c           |   2 +-
+ arch/mips/math-emu/dp_logb.c          |   2 +-
+ arch/mips/math-emu/dp_modf.c          |   2 +-
+ arch/mips/math-emu/dp_mul.c           |   2 +-
+ arch/mips/math-emu/dp_scalb.c         |   4 +-
+ arch/mips/math-emu/dp_simple.c        |  10 +-
+ arch/mips/math-emu/dp_sqrt.c          |   4 +-
+ arch/mips/math-emu/dp_sub.c           |   2 +-
+ arch/mips/math-emu/dp_tint.c          |   7 +-
+ arch/mips/math-emu/dp_tlong.c         |   6 +-
+ arch/mips/math-emu/dsemul.c           |  26 +--
+ arch/mips/math-emu/ieee754.c          |   9 +-
+ arch/mips/math-emu/ieee754.h          | 267 ++++++++++------------
+ arch/mips/math-emu/ieee754d.c         |   7 +-
+ arch/mips/math-emu/ieee754dp.c        |  19 +-
+ arch/mips/math-emu/ieee754dp.h        |  43 ++--
+ arch/mips/math-emu/ieee754int.h       | 146 ++++++------
+ arch/mips/math-emu/ieee754m.c         |  12 +-
+ arch/mips/math-emu/ieee754sp.c        |  22 +-
+ arch/mips/math-emu/ieee754sp.h        |  58 ++---
+ arch/mips/math-emu/ieee754xcpt.c      |   5 +-
+ arch/mips/math-emu/kernel_linkage.c   |   7 +-
+ arch/mips/math-emu/me-debugfs.c       |  62 +++++
+ arch/mips/math-emu/sp_add.c           |   2 +-
+ arch/mips/math-emu/sp_cmp.c           |   2 +-
+ arch/mips/math-emu/sp_div.c           |   2 +-
+ arch/mips/math-emu/sp_fdp.c           |   4 +-
+ arch/mips/math-emu/sp_fint.c          |   4 +-
+ arch/mips/math-emu/sp_flong.c         |   4 +-
+ arch/mips/math-emu/sp_frexp.c         |   2 +-
+ arch/mips/math-emu/sp_logb.c          |   2 +-
+ arch/mips/math-emu/sp_modf.c          |   2 +-
+ arch/mips/math-emu/sp_mul.c           |   2 +-
+ arch/mips/math-emu/sp_scalb.c         |   4 +-
+ arch/mips/math-emu/sp_simple.c        |  10 +-
+ arch/mips/math-emu/sp_sqrt.c          |   2 +-
+ arch/mips/math-emu/sp_sub.c           |   2 +-
+ arch/mips/math-emu/sp_tint.c          |   7 +-
+ arch/mips/math-emu/sp_tlong.c         |   6 +-
+ drivers/cpufreq/loongson2_cpufreq.c   |   4 +-
+ 66 files changed, 807 insertions(+), 946 deletions(-)
+ delete mode 100644 arch/mips/dec/prom/call_o32.S
+ delete mode 100644 arch/mips/include/asm/rm9k-ocd.h
+ create mode 100644 arch/mips/include/uapi/asm/bitfield.h
+ create mode 100644 arch/mips/math-emu/me-debugfs.c
+Merging openrisc/for-upstream (548dafe880ad openrisc: Use get_signal() signal_setup_done())
+$ git merge openrisc/for-upstream
+Already up-to-date.
+Merging parisc/for-next (6c700d71f7fa [PARISC] hpux: Remove obsolete regs parameter from do_execve() in hpux_execve())
+$ git merge parisc/for-next
+Already up-to-date.
+Merging parisc-hd/for-next (ab3e55b119c9 parisc: fix epoll_pwait syscall on compat kernel)
+$ git merge parisc-hd/for-next
+Merge made by the 'recursive' strategy.
+ arch/parisc/include/asm/shmparam.h |  5 ++---
+ arch/parisc/kernel/cache.c         |  3 ++-
+ arch/parisc/kernel/sys_parisc.c    | 14 +++++++-------
+ arch/parisc/kernel/syscall_table.S |  2 +-
+ arch/parisc/lib/memcpy.c           |  2 +-
+ arch/parisc/mm/fault.c             |  2 +-
+ 6 files changed, 14 insertions(+), 14 deletions(-)
+Merging powerpc/next (cd427485357c Merge remote-tracking branch 'scott/next' into next)
+$ git merge powerpc/next
+Already up-to-date.
+Merging mpc5xxx/next (bc7505942233 powerpc/512x: dts: add MPC5125 clock specs)
+$ git merge mpc5xxx/next
+Already up-to-date.
+Merging galak/next (9e2ecdbba3b0 powerpc/fsl-booke: add the reg prop for pci bridge device node for T4/B4)
+$ git merge galak/next
+Already up-to-date.
+Merging s390/features (4c0fda161346 s390/cmma: remove "cmma disable" code in case of dump again)
+$ git merge s390/features
+Auto-merging arch/s390/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/s390/Kconfig                      |  13 +-
+ arch/s390/include/asm/lowcore.h        |   5 +-
+ arch/s390/include/asm/setup.h          |  16 +-
+ arch/s390/include/asm/spinlock.h       | 134 ++++++----
+ arch/s390/include/asm/spinlock_types.h |  23 +-
+ arch/s390/kernel/crash_dump.c          |  83 +++---
+ arch/s390/kernel/early.c               |   6 +
+ arch/s390/kernel/head31.S              |   1 -
+ arch/s390/kernel/setup.c               | 455 ++++++++++++---------------------
+ arch/s390/kernel/smp.c                 |   3 +
+ arch/s390/kernel/topology.c            |   4 +-
+ arch/s390/lib/spinlock.c               | 147 ++++++++---
+ arch/s390/mm/mem_detect.c              | 130 +++-------
+ arch/s390/mm/page-states.c             |  10 -
+ arch/s390/mm/vmem.c                    |  30 +--
+ drivers/s390/char/zcore.c              |  44 +---
+ include/linux/memblock.h               |  79 +++++-
+ mm/Kconfig                             |   3 +
+ mm/memblock.c                          | 205 ++++++++++-----
+ 19 files changed, 714 insertions(+), 677 deletions(-)
+Merging sparc-next/master (049ffa8ab33a Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux)
+$ git merge sparc-next/master
+Already up-to-date.
+Merging tile/master (5eb0bdf84433 arch/tile: remove unused variable 'devcap')
+$ git merge tile/master
+Already up-to-date.
+Merging uml/next (989e59fa41c5 um: Include generic barrier.h)
+$ git merge uml/next
+Resolved 'arch/um/include/asm/Kbuild' using previous resolution.
+Removing arch/x86/um/shared/sysdep/skas_ptrace.h
+Removing arch/um/sys-ppc/shared/sysdep/skas_ptrace.h
+Removing arch/um/sys-ia64/sysdep/skas_ptrace.h
+Removing arch/um/include/shared/skas_ptrace.h
+Removing arch/um/include/shared/skas/proc_mm.h
+Auto-merging arch/um/include/asm/Kbuild
+CONFLICT (content): Merge conflict in arch/um/include/asm/Kbuild
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master b9933913e5e8] Merge remote-tracking branch 'uml/next'
+$ git diff -M --stat --summary HEAD^..
+ arch/um/include/shared/os.h                 |   2 -
+ arch/um/include/shared/skas/proc_mm.h       |  44 ------
+ arch/um/include/shared/skas/skas.h          |   3 -
+ arch/um/include/shared/skas_ptrace.h        |  14 --
+ arch/um/kernel/ptrace.c                     |  32 ----
+ arch/um/kernel/reboot.c                     |  35 ++---
+ arch/um/kernel/skas/mmu.c                   |  68 +++------
+ arch/um/kernel/skas/process.c               |  27 ----
+ arch/um/kernel/trap.c                       |   2 +-
+ arch/um/kernel/um_arch.c                    |  10 --
+ arch/um/os-Linux/process.c                  |  16 --
+ arch/um/os-Linux/skas/mem.c                 | 100 ++----------
+ arch/um/os-Linux/skas/process.c             | 200 ++++++------------------
+ arch/um/os-Linux/start_up.c                 | 154 -------------------
+ arch/um/sys-ia64/sysdep/skas_ptrace.h       |  22 ---
+ arch/um/sys-ppc/shared/sysdep/skas_ptrace.h |  22 ---
+ arch/x86/um/ldt.c                           | 227 ++++++----------------------
+ arch/x86/um/shared/sysdep/faultinfo_32.h    |   3 -
+ arch/x86/um/shared/sysdep/faultinfo_64.h    |   3 -
+ arch/x86/um/shared/sysdep/skas_ptrace.h     |  22 ---
+ 20 files changed, 148 insertions(+), 858 deletions(-)
+ delete mode 100644 arch/um/include/shared/skas/proc_mm.h
+ delete mode 100644 arch/um/include/shared/skas_ptrace.h
+ delete mode 100644 arch/um/sys-ia64/sysdep/skas_ptrace.h
+ delete mode 100644 arch/um/sys-ppc/shared/sysdep/skas_ptrace.h
+ delete mode 100644 arch/x86/um/shared/sysdep/skas_ptrace.h
+Merging unicore32/unicore32 (c284464658ac arch/unicore32: remove CONFIG_EXPERIMENTAL)
+$ git merge unicore32/unicore32
+Already up-to-date.
+Merging xtensa/for_next (cfe8255f0afc xtensa: xt2000: drop redundant sysmem initialization)
+$ git merge xtensa/for_next
+Auto-merging arch/xtensa/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/xtensa/Kconfig                         |  19 ++
+ arch/xtensa/boot/dts/kc705.dts              |  11 +
+ arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi |  28 +++
+ arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi  |  48 ++---
+ arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi   |  32 +--
+ arch/xtensa/boot/dts/xtfpga.dtsi            |  37 ++--
+ arch/xtensa/include/asm/bootparam.h         |  13 +-
+ arch/xtensa/include/asm/fixmap.h            |  58 ++++++
+ arch/xtensa/include/asm/highmem.h           |  45 ++++-
+ arch/xtensa/include/asm/pgtable.h           |   4 +
+ arch/xtensa/include/asm/sysmem.h            |  38 ++++
+ arch/xtensa/include/asm/tlbflush.h          |  11 +-
+ arch/xtensa/kernel/setup.c                  |  46 +----
+ arch/xtensa/kernel/smp.c                    |  15 ++
+ arch/xtensa/kernel/xtensa_ksyms.c           |   7 +
+ arch/xtensa/mm/Makefile                     |   1 +
+ arch/xtensa/mm/cache.c                      |   7 +-
+ arch/xtensa/mm/highmem.c                    |  72 +++++++
+ arch/xtensa/mm/init.c                       | 299 +++++++++++++++++++++++-----
+ arch/xtensa/mm/mmu.c                        |  36 ++++
+ arch/xtensa/mm/tlb.c                        |  15 ++
+ arch/xtensa/platforms/xt2000/setup.c        |  12 +-
+ scripts/sortextable.c                       |   5 +
+ 23 files changed, 694 insertions(+), 165 deletions(-)
+ create mode 100644 arch/xtensa/boot/dts/kc705.dts
+ create mode 100644 arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
+ create mode 100644 arch/xtensa/include/asm/fixmap.h
+ create mode 100644 arch/xtensa/include/asm/sysmem.h
+ create mode 100644 arch/xtensa/mm/highmem.c
+Merging btrfs/next (00fdf13a2e9f Btrfs: fix a crash of clone with inline extents's split)
+$ git merge btrfs/next
+Already up-to-date.
+Merging ceph/master (a30be7cb2ccb ceph: skip invalid dentry during dcache readdir)
+$ git merge ceph/master
+Already up-to-date.
+Merging cifs/for-next (a5a64da8c4e5 fs: cifs: remove unused variable.)
+$ git merge cifs/for-next
+Auto-merging fs/cifs/file.c
+Auto-merging fs/cifs/cifsfs.c
+Merge made by the 'recursive' strategy.
+ fs/cifs/cifsfs.c    | 14 +++++++++-
+ fs/cifs/cifsglob.h  |  8 ++++++
+ fs/cifs/cifsproto.h |  3 +++
+ fs/cifs/cifssmb.c   |  3 +++
+ fs/cifs/file.c      | 31 +++++++++++++++++++---
+ fs/cifs/misc.c      | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++--
+ fs/cifs/smb1ops.c   | 11 ++++++++
+ fs/cifs/smb2misc.c  | 18 ++++++++++---
+ fs/cifs/smb2ops.c   | 14 ++++++++++
+ fs/cifs/smb2pdu.c   |  2 --
+ 10 files changed, 167 insertions(+), 11 deletions(-)
+Merging configfs/linux-next (b930c26416c4 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs)
+$ git merge configfs/linux-next
+Already up-to-date.
+Merging ecryptfs/next (9e78d14a9f64 Use %pd in eCryptFS)
+$ git merge ecryptfs/next
+Auto-merging fs/ecryptfs/inode.c
+Merge made by the 'recursive' strategy.
+ fs/ecryptfs/file.c  |  4 ++--
+ fs/ecryptfs/inode.c | 12 ++++++------
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+Merging ext3/for_next (01d8885785a6 reiserfs: fix race in readdir)
+$ git merge ext3/for_next
+Already up-to-date.
+Merging ext4/dev (dd346d66aa92 i386: add renameat2 syscall)
+$ git merge ext4/dev
+Auto-merging fs/xfs/xfs_file.c
+Auto-merging fs/open.c
+Auto-merging fs/ext4/file.c
+Auto-merging fs/ceph/file.c
+Merge made by the 'recursive' strategy.
+ fs/ceph/file.c              |   3 -
+ fs/ext4/balloc.c            |   2 +-
+ fs/ext4/ext4.h              |  43 ++----
+ fs/ext4/ext4_extents.h      |  22 ++--
+ fs/ext4/extents.c           | 309 +++++++++++++++++++++++++-------------------
+ fs/ext4/extents_status.c    |   4 +-
+ fs/ext4/file.c              | 152 +++++++++++-----------
+ fs/ext4/inode.c             | 118 +++++++++--------
+ fs/ext4/mballoc.c           |  18 ++-
+ fs/ext4/move_extent.c       |  38 +++---
+ fs/ext4/namei.c             |   3 +-
+ fs/ext4/page-io.c           |   5 +-
+ fs/ext4/super.c             |  54 ++++----
+ fs/ext4/xattr.c             |  23 +++-
+ fs/open.c                   |  21 ++-
+ fs/xfs/xfs_file.c           |  10 +-
+ include/trace/events/ext4.h |  18 +--
+ 17 files changed, 449 insertions(+), 394 deletions(-)
+Merging f2fs/dev (350ca07320d4 f2fs: remove costly dirty_dir_inode operations)
+$ git merge f2fs/dev
+Merge made by the 'recursive' strategy.
+ fs/f2fs/checkpoint.c | 63 +++++++++++++++++-----------------------------------
+ fs/f2fs/data.c       | 10 +++------
+ fs/f2fs/f2fs.h       |  4 +++-
+ fs/f2fs/inline.c     | 13 ++++++-----
+ fs/f2fs/node.c       |  5 +----
+ fs/f2fs/recovery.c   | 18 ++++++++-------
+ fs/f2fs/segment.c    | 25 +++++++++++++++------
+ fs/f2fs/super.c      |  4 ++--
+ 8 files changed, 64 insertions(+), 78 deletions(-)
+Merging fscache/fscache (fe02fb3ec109 FS-Cache: Handle removal of unadded object to the fscache_object_list rb tree)
+$ git merge fscache/fscache
+Merge made by the 'recursive' strategy.
+Merging fuse/for-next (f3846266f593 fuse: fix "uninitialized variable" warning)
+$ git merge fuse/for-next
+Already up-to-date.
+Merging gfs2/master (c9eaa447e77e Linux 3.15-rc1)
+$ git merge gfs2/master
+Already up-to-date.
+Merging jfs/jfs-next (24e4a0f3de21 fs/jfs/jfs_inode.c: atomically set inode->i_flags)
+$ git merge jfs/jfs-next
+Merge made by the 'recursive' strategy.
+ fs/jfs/jfs_inode.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+Merging logfs/master (339466142b3f Fix the call to BUG() caused by no free segment found)
+$ git merge logfs/master
+Auto-merging fs/logfs/super.c
+Merge made by the 'recursive' strategy.
+ fs/logfs/dev_mtd.c | 2 +-
+ fs/logfs/super.c   | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+Merging nfs/linux-next (1f2edbe3fe21 NFS: Don't ignore suid/sgid bit changes after a successful write)
+$ git merge nfs/linux-next
+Merge made by the 'recursive' strategy.
+ fs/nfs/getroot.c |  3 ++-
+ fs/nfs/inode.c   | 26 +++++++++++++++++---------
+ fs/nfs/write.c   | 35 +++++++++++++++++++++++++++++++++--
+ 3 files changed, 52 insertions(+), 12 deletions(-)
+Merging nfsd/nfsd-next (06f9cc12caa8 nfsd4: don't create unnecessary mask acl)
+$ git merge nfsd/nfsd-next
+Already up-to-date.
+Merging omfs/for-next (976d167615b6 Linux 3.1-rc9)
+$ git merge omfs/for-next
+Already up-to-date.
+Merging squashfs/master (6d565409503f Squashfs: fix failure to unlock pages on decompress error)
+$ git merge squashfs/master
+Already up-to-date.
+Merging v9fs/for-next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge v9fs/for-next
+Already up-to-date.
+Merging ubifs/linux-next (d56030ac25d3 UBI: block: Remove __initdata from ubiblock_param_ops)
+$ git merge ubifs/linux-next
+Already up-to-date.
+Merging xfs/for-next (330033d697ed xfs: fix tmpfile/selinux deadlock and initialize security)
+$ git merge xfs/for-next
+Auto-merging fs/xfs/xfs_file.c
+Merge made by the 'recursive' strategy.
+ fs/xfs/xfs_aops.c      | 51 ++++++++++++++++++++++++++++++++++++++++++------
+ fs/xfs/xfs_bmap.c      | 17 ++++++++++------
+ fs/xfs/xfs_bmap_util.c | 13 ++++++++++++-
+ fs/xfs/xfs_buf.c       | 16 +++++++++++----
+ fs/xfs/xfs_file.c      |  2 +-
+ fs/xfs/xfs_inode.c     |  5 +++--
+ fs/xfs/xfs_inode.h     |  2 +-
+ fs/xfs/xfs_iops.c      | 20 ++++++++++++++++---
+ fs/xfs/xfs_log.c       | 53 +++++++++++++++++++++++++++++++++++++++++---------
+ fs/xfs/xfs_trace.h     |  1 +
+ 10 files changed, 147 insertions(+), 33 deletions(-)
+Merging file-private-locks/linux-next (f1c6bb2cb8b8 locks: allow __break_lease to sleep even when break_time is 0)
+$ git merge file-private-locks/linux-next
+Merge made by the 'recursive' strategy.
+ fs/locks.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+Merging vfs/for-next (527d1511310a Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc)
+$ git merge vfs/for-next
+Already up-to-date.
+Merging pci/next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge pci/next
+Already up-to-date.
+Merging hid/for-next (12e5706a47c2 Merge branch 'for-3.16/rmi4' into for-next)
+$ git merge hid/for-next
+Auto-merging drivers/leds/Kconfig
+Removing Documentation/ABI/testing/sysfs-driver-hid-thingm
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-driver-hid-thingm |  23 -
+ drivers/hid/Kconfig                               |   8 +
+ drivers/hid/Makefile                              |   1 +
+ drivers/hid/hid-core.c                            |   2 +
+ drivers/hid/hid-rmi.c                             | 888 ++++++++++++++++++++++
+ drivers/hid/hid-thingm.c                          | 361 +++++----
+ drivers/leds/Kconfig                              |   2 +
+ include/linux/hid.h                               |   2 +
+ 8 files changed, 1104 insertions(+), 183 deletions(-)
+ delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-thingm
+ create mode 100644 drivers/hid/hid-rmi.c
+Merging i2c/i2c/for-next (9e897e13bd46 Merge branch 'for-linus' of git://git.open-osd.org/linux-open-osd)
+$ git merge i2c/i2c/for-next
+Already up-to-date.
+Merging jdelvare-hwmon/master (455c6fdbd219 Linux 3.14)
+$ git merge jdelvare-hwmon/master
+Already up-to-date.
+Merging hwmon-staging/hwmon-next (046f3ea7c6af hwmon: (lm77) Drop FSF mailing address)
+$ git merge hwmon-staging/hwmon-next
+Merge made by the 'recursive' strategy.
+ drivers/hwmon/lm70.c   |  62 ++++-------------
+ drivers/hwmon/lm77.c   | 177 ++++++++++++++++++++++---------------------------
+ drivers/hwmon/tmp102.c |  62 ++++++++---------
+ drivers/hwmon/tmp421.c |  47 +++++--------
+ 4 files changed, 138 insertions(+), 210 deletions(-)
+Merging v4l-dvb/master (b40dfe97cc3a Merge branch 'v4l_for_linus' into to_next)
+$ git merge v4l-dvb/master
+Merge made by the 'recursive' strategy.
+ drivers/media/i2c/s5c73m3/s5c73m3-core.c         |  2 +-
+ drivers/media/platform/davinci/vpbe_display.c    | 16 +++++++-
+ drivers/media/platform/davinci/vpfe_capture.c    |  2 +
+ drivers/media/platform/davinci/vpif_capture.c    | 34 +++++++++++------
+ drivers/media/platform/davinci/vpif_display.c    | 35 +++++++++++------
+ drivers/media/platform/exynos4-is/fimc-core.c    |  2 +-
+ drivers/media/usb/dvb-usb-v2/Makefile            |  1 -
+ drivers/media/usb/dvb-usb-v2/rtl28xxu.c          | 48 +++++++++++++++++++++---
+ drivers/media/usb/gspca/sonixb.c                 |  2 -
+ drivers/staging/media/davinci_vpfe/vpfe_video.c  | 13 ++++++-
+ drivers/staging/media/sn9c102/sn9c102_devtable.h |  2 -
+ 11 files changed, 119 insertions(+), 38 deletions(-)
+Merging kbuild/for-next (de71647f7af0 Merge branch 'kbuild/kbuild' into kbuild/for-next)
+$ git merge kbuild/for-next
+Merge made by the 'recursive' strategy.
+ .gitignore                 |   4 +-
+ Documentation/lto-build    | 173 +++++++++++++++++++++++++++++++++++++++++++++
+ Makefile                   |  25 +++++--
+ arch/x86/Kconfig           |   2 +-
+ init/Kconfig               |  73 +++++++++++++++++++
+ kernel/gcov/Kconfig        |   2 +-
+ lib/Kconfig.debug          |   2 +-
+ scripts/Makefile.build     |  61 ----------------
+ scripts/Makefile.extrawarn |  67 ++++++++++++++++++
+ scripts/Makefile.lto       |  84 ++++++++++++++++++++++
+ scripts/Makefile.modpost   |   7 +-
+ scripts/link-vmlinux.sh    |   2 +-
+ scripts/tags.sh            |   6 +-
+ 13 files changed, 431 insertions(+), 77 deletions(-)
+ create mode 100644 Documentation/lto-build
+ create mode 100644 scripts/Makefile.extrawarn
+ create mode 100644 scripts/Makefile.lto
+Merging kconfig/for-next (95edca5c523c localmodconfig: Add config depends by default settings)
+$ git merge kconfig/for-next
+Already up-to-date.
+Merging libata/for-next (73ff0e9080ed Merge branch 'for-3.15-fixes' into for-next)
+$ git merge libata/for-next
+Merge made by the 'recursive' strategy.
+ drivers/ata/Kconfig           |  5 ++---
+ drivers/ata/ahci.c            | 12 ++++-------
+ drivers/ata/libata-core.c     |  6 ++++--
+ drivers/ata/pata_arasan_cf.c  |  7 ++++--
+ drivers/ata/pata_at91.c       | 11 +++++-----
+ drivers/ata/pata_octeon_cf.c  | 50 +++++++++++++++----------------------------
+ drivers/ata/pata_samsung_cf.c | 10 ++++++---
+ 7 files changed, 45 insertions(+), 56 deletions(-)
+Merging pm/linux-next (19ce7f3f3110 Merge branch 'acpi-config')
+$ git merge pm/linux-next
+Already up-to-date.
+Merging idle/next (23a299cd9378 Merge branches 'turbostat' and 'intel_idle' into release)
+$ git merge idle/next
+Already up-to-date.
+Merging apm/for-next (158204397034 apm-emulation: add hibernation APM events to support suspend2disk)
+$ git merge apm/for-next
+Already up-to-date.
+Merging cpupowerutils/master (f16603386b38 cpupower tools: add install target to the debug tools' makefiles)
+$ git merge cpupowerutils/master
+Already up-to-date.
+Merging thermal/next (9477165ec525 thermal: rcar-thermal: update thermal zone only when temperature changes)
+$ git merge thermal/next
+Already up-to-date.
+Merging ieee1394/for-next (0ca49345b6f4 firewire: ohci: fix probe failure with Agere/LSI controllers)
+$ git merge ieee1394/for-next
+Already up-to-date.
+Merging dlm/next (075f01775f53 dlm: use INFO for recovery messages)
+$ git merge dlm/next
+Already up-to-date.
+Merging swiotlb/linux-next (0cb637bff80d swiotlb: Don't DoS us with 'swiotlb buffer is full' (v2))
+$ git merge swiotlb/linux-next
+Already up-to-date.
+Merging slave-dma/next (8edc51c197b8 dma: fix eDMA driver as a subsys_initcall)
+$ git merge slave-dma/next
+Merge made by the 'recursive' strategy.
+ drivers/dma/Kconfig            |  2 +-
+ drivers/dma/edma.c             |  6 ++++--
+ drivers/dma/fsl-edma.c         | 12 +++++++++++-
+ drivers/dma/sirf-dma.c         |  2 +-
+ drivers/media/platform/Kconfig |  2 +-
+ 5 files changed, 18 insertions(+), 6 deletions(-)
+Merging dmaengine/next (b9bf6d2e84b7 dma: mv_xor: Flush descriptors before activating a channel)
+$ git merge dmaengine/next
+Auto-merging include/linux/dmaengine.h
+Auto-merging drivers/dma/dmaengine.c
+Merge made by the 'recursive' strategy.
+ drivers/dma/dmaengine.c   |  2 ++
+ drivers/dma/ioat/dca.c    | 13 +++----
+ drivers/dma/ioat/dma.c    |  2 +-
+ drivers/dma/ioat/dma_v3.c |  6 ++--
+ drivers/dma/mv_xor.c      | 88 +++++++++++++++++++++++++++++++++++------------
+ include/linux/dmaengine.h |  1 +
+ 6 files changed, 80 insertions(+), 32 deletions(-)
+Merging net-next/master (cd6362befe4c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next)
+$ git merge net-next/master
+Already up-to-date.
+Merging ipsec-next/master (cd6362befe4c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next)
+$ git merge ipsec-next/master
+Already up-to-date.
+Merging wireless-next/master (321d03c86732 Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild)
+$ git merge wireless-next/master
+Already up-to-date.
+Merging bluetooth/master (899704633969 Bluetooth: Fix redundant encryption request for reauthentication)
+$ git merge bluetooth/master
+Merge made by the 'recursive' strategy.
+ drivers/bluetooth/btmrvl_drv.h   |   2 +
+ drivers/bluetooth/btmrvl_main.c  |  17 +++
+ drivers/bluetooth/btmrvl_sdio.c  | 103 ++++++++++++----
+ drivers/bluetooth/btmrvl_sdio.h  |   3 +
+ include/net/bluetooth/hci.h      |   1 +
+ include/net/bluetooth/hci_core.h |  13 +-
+ net/bluetooth/hci_conn.c         |  90 ++++++++++++--
+ net/bluetooth/hci_core.c         |  20 ++--
+ net/bluetooth/hci_event.c        | 252 +++++++++++++++++++++++++++++----------
+ net/bluetooth/lib.c              |   1 +
+ net/bluetooth/mgmt.c             |  36 +++---
+ 11 files changed, 416 insertions(+), 122 deletions(-)
+Merging infiniband/for-next (5ae2866f5264 Merge branches 'cxgb4', 'misc', 'mlx5' and 'qib' into for-next)
+$ git merge infiniband/for-next
+Merge made by the 'recursive' strategy.
+ drivers/infiniband/hw/cxgb4/cm.c         | 89 ++++++++++++++++++++------------
+ drivers/infiniband/hw/cxgb4/cq.c         | 24 ++++-----
+ drivers/infiniband/hw/cxgb4/device.c     | 41 ++++++++++++---
+ drivers/infiniband/hw/cxgb4/iw_cxgb4.h   |  2 +
+ drivers/infiniband/hw/cxgb4/mem.c        |  6 ++-
+ drivers/infiniband/hw/cxgb4/provider.c   |  2 +-
+ drivers/infiniband/hw/cxgb4/qp.c         | 70 +++++++++++++++----------
+ drivers/infiniband/hw/cxgb4/resource.c   | 10 ++--
+ drivers/infiniband/hw/cxgb4/t4.h         | 72 ++++++++++++++++++++++++--
+ drivers/infiniband/hw/mlx5/main.c        |  2 +
+ drivers/infiniband/hw/mlx5/qp.c          | 12 +++++
+ drivers/infiniband/hw/mthca/mthca_main.c |  8 +--
+ drivers/infiniband/hw/qib/qib_pcie.c     | 55 ++++++++++----------
+ include/linux/mlx5/device.h              |  1 +
+ include/linux/mlx5/qp.h                  |  1 +
+ 15 files changed, 270 insertions(+), 125 deletions(-)
+Merging mtd/master (c9eaa447e77e Linux 3.15-rc1)
+$ git merge mtd/master
+Already up-to-date.
+Merging l2-mtd/master (6189cccbe8d1 mtd: gpmi: add gpmi_devdata{} to simplify the code)
+$ git merge l2-mtd/master
+Merge made by the 'recursive' strategy.
+ drivers/mtd/mtd_blkdevs.c              |  6 ++++
+ drivers/mtd/nand/davinci_nand.c        |  6 ++++
+ drivers/mtd/nand/gpmi-nand/gpmi-lib.c  |  5 +---
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 53 ++++++++++++++++++----------------
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.h | 28 +++++++++++-------
+ drivers/mtd/nand/nand_base.c           |  3 +-
+ drivers/mtd/nand/nand_ecc.c            |  2 +-
+ drivers/mtd/nand/omap2.c               |  2 +-
+ 8 files changed, 61 insertions(+), 44 deletions(-)
+Merging crypto/master (f51f593b3eb1 crypto: omap-des - handle error of pm_runtime_get_sync)
+$ git merge crypto/master
+Recorded preimage for 'drivers/char/hw_random/Kconfig'
+CONFLICT (rename/delete): drivers/crypto/bfin_crc.h deleted in HEAD and renamed in crypto/master. Version crypto/master of drivers/crypto/bfin_crc.h left in tree.
+Removing drivers/char/hw_random/picoxcell-rng.c
+Auto-merging drivers/char/hw_random/Kconfig
+CONFLICT (content): Merge conflict in drivers/char/hw_random/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'drivers/char/hw_random/Kconfig'.
+[master 37c6149f0de5] Merge remote-tracking branch 'crypto/master'
+$ git diff -M --stat --summary HEAD^..
+ arch/x86/crypto/ghash-clmulni-intel_asm.S  |   4 +-
+ arch/x86/crypto/ghash-clmulni-intel_glue.c |  12 +-
+ crypto/testmgr.h                           | 775 ++++++++++++++++++++++++++++-
+ drivers/char/hw_random/Kconfig             | 103 ++--
+ drivers/char/hw_random/Makefile            |   1 -
+ drivers/char/hw_random/picoxcell-rng.c     | 181 -------
+ drivers/crypto/bfin_crc.c                  | 103 ++--
+ drivers/crypto/bfin_crc.h                  | 125 +++++
+ drivers/crypto/ccp/ccp-pci.c               |   7 +-
+ drivers/crypto/nx/nx-842.c                 |   4 +-
+ drivers/crypto/omap-des.c                  |  33 +-
+ 11 files changed, 1036 insertions(+), 312 deletions(-)
+ delete mode 100644 drivers/char/hw_random/picoxcell-rng.c
+ create mode 100644 drivers/crypto/bfin_crc.h
+Merging drm/drm-next (c39b06951f1d DRM: armada: fix corruption while loading cursors)
+$ git merge drm/drm-next
+Already up-to-date.
+Merging drm-intel/for-linux-next (c79057922ed6 drm/i915: Remove vblank wait from haswell_write_eld)
+$ git merge drm-intel/for-linux-next
+Resolved 'drivers/gpu/drm/i915/i915_gem_context.c' using previous resolution.
+Auto-merging drivers/gpu/drm/i915/intel_pm.c
+Auto-merging drivers/gpu/drm/i915/intel_panel.c
+Auto-merging drivers/gpu/drm/i915/intel_hdmi.c
+Auto-merging drivers/gpu/drm/i915/intel_bios.h
+Auto-merging drivers/gpu/drm/i915/intel_bios.c
+Auto-merging drivers/gpu/drm/i915/i915_gem_execbuffer.c
+Auto-merging drivers/gpu/drm/i915/i915_gem_context.c
+CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/i915_gem_context.c
+Auto-merging drivers/gpu/drm/i915/i915_gem.c
+Auto-merging drivers/gpu/drm/i915/i915_drv.h
+Auto-merging drivers/gpu/drm/i915/Kconfig
+Auto-merging drivers/gpu/drm/drm_cache.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master bc5524d06a9e] Merge remote-tracking branch 'drm-intel/for-linux-next'
+$ git diff -M --stat --summary HEAD^..
+ drivers/gpu/drm/drm_cache.c                |   4 +-
+ drivers/gpu/drm/i915/Kconfig               |   2 +-
+ drivers/gpu/drm/i915/dvo_ch7xxx.c          |   2 +-
+ drivers/gpu/drm/i915/dvo_ivch.c            |   2 +-
+ drivers/gpu/drm/i915/dvo_ns2501.c          |  24 +-
+ drivers/gpu/drm/i915/dvo_sil164.c          |   2 +-
+ drivers/gpu/drm/i915/dvo_tfp410.c          |   2 +-
+ drivers/gpu/drm/i915/i915_cmd_parser.c     | 616 +++++++++++++++++++++++++----
+ drivers/gpu/drm/i915/i915_debugfs.c        |  25 +-
+ drivers/gpu/drm/i915/i915_dma.c            |   3 +
+ drivers/gpu/drm/i915/i915_drv.c            |  53 ++-
+ drivers/gpu/drm/i915/i915_drv.h            | 265 +++----------
+ drivers/gpu/drm/i915/i915_gem.c            |   5 +-
+ drivers/gpu/drm/i915/i915_gem_context.c    |  18 +-
+ drivers/gpu/drm/i915/i915_gem_dmabuf.c     |   6 +-
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c |   3 +-
+ drivers/gpu/drm/i915/i915_gem_gtt.c        |  75 +---
+ drivers/gpu/drm/i915/i915_gem_gtt.h        | 283 +++++++++++++
+ drivers/gpu/drm/i915/i915_gpu_error.c      |  23 +-
+ drivers/gpu/drm/i915/i915_irq.c            | 504 +++++++++++------------
+ drivers/gpu/drm/i915/i915_params.c         |   8 +-
+ drivers/gpu/drm/i915/i915_reg.h            | 117 +++++-
+ drivers/gpu/drm/i915/intel_bios.c          | 242 +++++++++++-
+ drivers/gpu/drm/i915/intel_bios.h          |  60 +++
+ drivers/gpu/drm/i915/intel_display.c       | 283 ++++++-------
+ drivers/gpu/drm/i915/intel_dp.c            | 197 ++++++++-
+ drivers/gpu/drm/i915/intel_drv.h           |  35 +-
+ drivers/gpu/drm/i915/intel_dsi.c           | 125 ++++--
+ drivers/gpu/drm/i915/intel_dsi.h           |   4 +-
+ drivers/gpu/drm/i915/intel_dsi_cmd.c       |   4 +-
+ drivers/gpu/drm/i915/intel_dsi_cmd.h       |   5 +-
+ drivers/gpu/drm/i915/intel_hdmi.c          |  38 +-
+ drivers/gpu/drm/i915/intel_lvds.c          |   7 -
+ drivers/gpu/drm/i915/intel_panel.c         |   8 +-
+ drivers/gpu/drm/i915/intel_pm.c            | 219 ++++++----
+ drivers/gpu/drm/i915/intel_ringbuffer.c    |  75 ++--
+ drivers/gpu/drm/i915/intel_ringbuffer.h    |   5 +-
+ drivers/gpu/drm/i915/intel_sdvo.c          |   4 +-
+ drivers/gpu/drm/i915/intel_sideband.c      |   8 +
+ drivers/gpu/drm/i915/intel_uncore.c        |  24 +-
+ include/drm/drmP.h                         |   2 +-
+ include/uapi/drm/i915_drm.h                |   1 +
+ 42 files changed, 2354 insertions(+), 1034 deletions(-)
+ create mode 100644 drivers/gpu/drm/i915/i915_gem_gtt.h
+Merging drm-tegra/drm/for-next (3d1c1474386e drm/tegra: Use standard GPL v2 license text)
+$ git merge drm-tegra/drm/for-next
+Merge made by the 'recursive' strategy.
+Merging sound/for-next (00d90154404a ALSA: pcm: 'BUG:' message unnecessarily triggers kerneloops)
+$ git merge sound/for-next
+Merge made by the 'recursive' strategy.
+ include/sound/atmel-ac97c.h |   2 -
+ sound/atmel/ac97c.c         |  15 +-
+ sound/core/pcm_lib.c        |   2 +-
+ sound/usb/Kconfig           |  13 ++
+ sound/usb/Makefile          |   2 +-
+ sound/usb/bcd2000/Makefile  |   3 +
+ sound/usb/bcd2000/bcd2000.c | 461 ++++++++++++++++++++++++++++++++++++++++++++
+ 7 files changed, 481 insertions(+), 17 deletions(-)
+ create mode 100644 sound/usb/bcd2000/Makefile
+ create mode 100644 sound/usb/bcd2000/bcd2000.c
+Merging sound-asoc/for-next (df9a50e93aa5 Merge remote-tracking branches 'asoc/topic/rt5640', 'asoc/topic/sirf', 'asoc/topic/sta350' and 'asoc/topic/tmp-of' into asoc-next)
+$ git merge sound-asoc/for-next
+Removing sound/soc/sirf/sirf-audio-port.h
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/sound/ak5386.txt |    4 +
+ .../devicetree/bindings/sound/fsl-sai.txt          |   11 +-
+ Documentation/devicetree/bindings/sound/rt5640.txt |   13 +-
+ .../devicetree/bindings/sound/st,sta350.txt        |  107 ++
+ include/linux/of.h                                 |    5 +
+ include/sound/rt5640.h                             |    4 +
+ include/sound/soc-dapm.h                           |   12 -
+ include/sound/soc.h                                |   68 +-
+ include/sound/sta350.h                             |   52 +
+ sound/soc/codecs/88pm860x-codec.c                  |   20 +-
+ sound/soc/codecs/Kconfig                           |   11 +-
+ sound/soc/codecs/Makefile                          |    4 +
+ sound/soc/codecs/ab8500-codec.c                    |   12 +-
+ sound/soc/codecs/adau1373.c                        |    7 +-
+ sound/soc/codecs/adav80x.c                         |   12 +-
+ sound/soc/codecs/ak4641.c                          |    4 +-
+ sound/soc/codecs/ak5386.c                          |   50 +
+ sound/soc/codecs/alc5623.c                         |    2 +-
+ sound/soc/codecs/arizona.h                         |    4 +-
+ sound/soc/codecs/cq93vc.c                          |   10 +-
+ sound/soc/codecs/cs4270.c                          |    2 +-
+ sound/soc/codecs/cs4271.c                          |    4 +-
+ sound/soc/codecs/cs42l51-i2c.c                     |   59 +
+ sound/soc/codecs/cs42l51.c                         |   79 +-
+ sound/soc/codecs/cs42l51.h                         |    5 +
+ sound/soc/codecs/da7210.c                          |    4 +-
+ sound/soc/codecs/da7213.c                          |    4 +-
+ sound/soc/codecs/da732x.c                          |    4 +-
+ sound/soc/codecs/da9055.c                          |    2 +-
+ sound/soc/codecs/hdmi.c                            |    1 +
+ sound/soc/codecs/lm4857.c                          |    4 +-
+ sound/soc/codecs/max9768.c                         |    4 +-
+ sound/soc/codecs/max98088.c                        |   12 +-
+ sound/soc/codecs/max98090.c                        |   10 +-
+ sound/soc/codecs/max98095.c                        |   16 +-
+ sound/soc/codecs/mc13783.c                         |   22 +-
+ sound/soc/codecs/pcm1681.c                         |    4 +-
+ sound/soc/codecs/pcm512x.c                         |    4 +-
+ sound/soc/codecs/rt5631.c                          |    4 +-
+ sound/soc/codecs/rt5640.c                          |  417 ++++---
+ sound/soc/codecs/rt5640.h                          |    6 +-
+ sound/soc/codecs/sgtl5000.c                        |    4 +-
+ sound/soc/codecs/si476x.c                          |   14 +-
+ sound/soc/codecs/sirf-audio-codec.c                |   74 +-
+ sound/soc/codecs/sirf-audio-codec.h                |   50 +
+ sound/soc/codecs/sta32x.c                          |    4 +-
+ sound/soc/codecs/sta350.c                          | 1266 ++++++++++++++++++++
+ sound/soc/codecs/sta350.h                          |  228 ++++
+ sound/soc/codecs/tas5086.c                         |    4 +-
+ sound/soc/codecs/tlv320aic23-i2c.c                 |    1 +
+ sound/soc/codecs/tlv320aic23.c                     |    4 +-
+ sound/soc/codecs/tlv320aic31xx.c                   |    1 +
+ sound/soc/codecs/tlv320aic3x.c                     |    9 +-
+ sound/soc/codecs/tlv320dac33.c                     |    4 +-
+ sound/soc/codecs/tpa6130a2.c                       |    1 +
+ sound/soc/codecs/twl4030.c                         |   10 +-
+ sound/soc/codecs/twl6040.c                         |    8 +-
+ sound/soc/codecs/wl1273.c                          |   12 +-
+ sound/soc/codecs/wm2000.c                          |    8 +-
+ sound/soc/codecs/wm2200.c                          |    4 +-
+ sound/soc/codecs/wm5100.c                          |    4 +-
+ sound/soc/codecs/wm5102.c                          |   26 +-
+ sound/soc/codecs/wm5110.c                          |   35 +-
+ sound/soc/codecs/wm8350.c                          |   14 +-
+ sound/soc/codecs/wm8400.c                          |   12 +-
+ sound/soc/codecs/wm8580.c                          |    2 +-
+ sound/soc/codecs/wm8731.c                          |    4 +-
+ sound/soc/codecs/wm8753.c                          |    4 +-
+ sound/soc/codecs/wm8804.c                          |    4 +-
+ sound/soc/codecs/wm8903.c                          |    4 +-
+ sound/soc/codecs/wm8904.c                          |   14 +-
+ sound/soc/codecs/wm8955.c                          |    4 +-
+ sound/soc/codecs/wm8958-dsp2.c                     |   32 +-
+ sound/soc/codecs/wm8960.c                          |    4 +-
+ sound/soc/codecs/wm8962.c                          |    8 +-
+ sound/soc/codecs/wm8983.c                          |    4 +-
+ sound/soc/codecs/wm8985.c                          |    4 +-
+ sound/soc/codecs/wm8988.c                          |    8 +-
+ sound/soc/codecs/wm8990.c                          |    2 +-
+ sound/soc/codecs/wm8991.c                          |    2 +-
+ sound/soc/codecs/wm8994.c                          |   32 +-
+ sound/soc/codecs/wm8995.c                          |   10 +-
+ sound/soc/codecs/wm8996.c                          |    4 +-
+ sound/soc/codecs/wm8997.c                          |   25 +-
+ sound/soc/codecs/wm9081.c                          |    4 +-
+ sound/soc/codecs/wm_adsp.c                         |    4 +-
+ sound/soc/codecs/wm_hubs.c                         |    2 +-
+ sound/soc/davinci/davinci-mcasp.c                  |  217 ++--
+ sound/soc/davinci/davinci-mcasp.h                  |    1 +
+ sound/soc/davinci/davinci-pcm.h                    |   10 +
+ sound/soc/fsl/Kconfig                              |   57 +-
+ sound/soc/fsl/fsl_esai.c                           |    9 +-
+ sound/soc/fsl/fsl_sai.c                            |  255 ++--
+ sound/soc/fsl/fsl_sai.h                            |   16 +
+ sound/soc/fsl/fsl_spdif.c                          |    9 +-
+ sound/soc/fsl/fsl_ssi.c                            |  150 +--
+ sound/soc/intel/sst-firmware.c                     |    4 +-
+ sound/soc/intel/sst-haswell-ipc.c                  |    3 +-
+ sound/soc/intel/sst-haswell-pcm.c                  |    8 +-
+ sound/soc/omap/ams-delta.c                         |   64 +-
+ sound/soc/omap/omap3pandora.c                      |   31 +-
+ sound/soc/omap/rx51.c                              |   47 +-
+ sound/soc/sh/rcar/src.c                            |    4 +-
+ sound/soc/sh/rcar/ssi.c                            |    4 +-
+ sound/soc/sirf/sirf-audio-port.c                   |  107 --
+ sound/soc/sirf/sirf-audio-port.h                   |   62 -
+ sound/soc/soc-cache.c                              |    2 -
+ sound/soc/soc-core.c                               |  541 ++++-----
+ sound/soc/soc-io.c                                 |  153 ++-
+ 109 files changed, 3354 insertions(+), 1457 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/sound/st,sta350.txt
+ create mode 100644 include/sound/sta350.h
+ create mode 100644 sound/soc/codecs/cs42l51-i2c.c
+ create mode 100644 sound/soc/codecs/sta350.c
+ create mode 100644 sound/soc/codecs/sta350.h
+ delete mode 100644 sound/soc/sirf/sirf-audio-port.h
+Merging modules/modules-next (22c9bcad859d staging: fix up speakup kobject mode)
+$ git merge modules/modules-next
+Already up-to-date.
+Merging virtio/virtio-next (fc4324b4597c virtio-blk: base queue-depth on virtqueue ringsize or module param)
+$ git merge virtio/virtio-next
+Already up-to-date.
+Merging input/next (e2c3ecf0ea8e Input: edt-ft5x06 - add a missing condition)
+$ git merge input/next
+Already up-to-date.
+Merging input-mt/for-next (5e01dc7b26d9 Linux 3.12)
+$ git merge input-mt/for-next
+Already up-to-date.
+Merging block/for-next (926912e06e3b Merge branch 'for-3.16/drivers' into for-next)
+$ git merge block/for-next
+Auto-merging drivers/mtd/mtd_blkdevs.c
+Merge made by the 'recursive' strategy.
+ block/blk-core.c             |  45 ++--
+ block/blk-flush.c            |  26 +--
+ block/blk-map.c              |   3 -
+ block/blk-mq-cpumap.c        |   6 +-
+ block/blk-mq-sysfs.c         |   8 +-
+ block/blk-mq-tag.c           |  14 --
+ block/blk-mq-tag.h           |  19 +-
+ block/blk-mq.c               | 494 +++++++++++++++++++++++++------------------
+ block/blk-mq.h               |   8 +-
+ block/blk-timeout.c          |  15 +-
+ block/bsg.c                  |   2 +-
+ block/cfq-iosched.c          |   2 +-
+ drivers/block/amiflop.c      |   2 +-
+ drivers/block/ataflop.c      |   2 +-
+ drivers/block/floppy.c       |  18 +-
+ drivers/block/hd.c           |  10 +-
+ drivers/block/mg_disk.c      |  12 +-
+ drivers/block/null_blk.c     |  96 +++++----
+ drivers/block/paride/pcd.c   |   2 +-
+ drivers/block/paride/pd.c    |   4 +-
+ drivers/block/paride/pf.c    |   4 +-
+ drivers/block/skd_main.c     |   5 +-
+ drivers/block/swim.c         |   2 +-
+ drivers/block/swim3.c        |   6 +-
+ drivers/block/virtio_blk.c   |  73 ++++---
+ drivers/block/xen-blkfront.c |   4 +-
+ drivers/block/xsysace.c      |   4 +-
+ drivers/block/z2ram.c        |   6 +-
+ drivers/cdrom/gdrom.c        |   2 +-
+ drivers/ide/ide-disk.c       |   5 +-
+ drivers/md/dm.c              |   1 -
+ drivers/mtd/mtd_blkdevs.c    |   3 +-
+ drivers/mtd/ubi/block.c      |   2 +-
+ drivers/sbus/char/jsflash.c  |   2 +-
+ drivers/scsi/scsi_lib.c      |   5 +-
+ drivers/scsi/sd.c            |  10 +-
+ include/linux/blk-mq.h       |  59 +++---
+ include/linux/blkdev.h       |  21 +-
+ 38 files changed, 568 insertions(+), 434 deletions(-)
+Merging device-mapper/for-next (ec052772958d Merge branch 'for-3.15' into for-next)
+$ git merge device-mapper/for-next
+Auto-merging fs/bio.c
+Merge made by the 'recursive' strategy.
+ drivers/md/dm-crypt.c  | 427 +++++++++++++++++++++++++------------------------
+ drivers/md/dm-thin.c   |  75 ++++++++-
+ drivers/md/dm-verity.c |  15 +-
+ fs/bio.c               |   3 +-
+ 4 files changed, 297 insertions(+), 223 deletions(-)
+Merging embedded/master (4744b43431e8 embedded: fix vc_translate operator precedence)
+$ git merge embedded/master
+Already up-to-date.
+Merging firmware/master (6e03a201bbe8 firmware: speed up request_firmware(), v3)
+$ git merge firmware/master
+Already up-to-date.
+Merging pcmcia/master (80af9e6d7ae6 pcmcia at91_cf: fix raw gpio number usage)
+$ git merge pcmcia/master
+Already up-to-date.
+Merging mmc/mmc-next (c67480173f72 mmc: sdhci-acpi: Intel SDIO has broken card detect)
+$ git merge mmc/mmc-next
+Already up-to-date.
+Merging kgdb/kgdb-next (6bedf31c25dd kdb: Remove unhandled ssb command)
+$ git merge kgdb/kgdb-next
+Merge made by the 'recursive' strategy.
+Merging slab/for-next (34bf6ef94a83 mm: slab/slub: use page->list consistently instead of page->lru)
+$ git merge slab/for-next
+Already up-to-date.
+Merging uclinux/for-next (6dbe51c251a3 Linux 3.9-rc1)
+$ git merge uclinux/for-next
+Already up-to-date.
+Merging md/for-next (e2f23b606b94 md: avoid oops on unload if some process is in poll or select.)
+$ git merge md/for-next
+Already up-to-date.
+Merging mfd/master (90b128ed1557 Merge tag 'mfd-lee-3.13-3' of git://git.linaro.org/people/ljones/mfd)
+$ git merge mfd/master
+Already up-to-date.
+Merging mfd-lj/for-mfd-next (2d28ca731b9b mfd: wm5110: Correct default for HEADPHONE_DETECT_1)
+$ git merge mfd-lj/for-mfd-next
+Already up-to-date.
+Merging battery/master (ac323d8d8070 power: max17040: Fix NULL pointer dereference when there is no platform_data)
+$ git merge battery/master
+Already up-to-date.
+Merging fbdev/for-next (718b90ac4c21 video: xilinxfb: Simplify error path)
+$ git merge fbdev/for-next
+Already up-to-date.
+Merging viafb/viafb-next (838ac785d521 viafb: avoid refresh and mode lookup in set_par)
+$ git merge viafb/viafb-next
+Already up-to-date.
+Merging omap_dss2/for-next (d754589d8044 OMAPDSS: add missing __init for dss_init_ports)
+$ git merge omap_dss2/for-next
+Recorded preimage for 'drivers/video/Kconfig'
+Resolved 'drivers/video/Makefile' using previous resolution.
+Removing drivers/video/omap2/Kconfig
+Auto-merging drivers/video/fbdev/wmt_ge_rops.c
+CONFLICT (rename/delete): drivers/video/fbdev/sgivwfb.c deleted in HEAD and renamed in omap_dss2/for-next. Version omap_dss2/for-next of drivers/video/fbdev/sgivwfb.c left in tree.
+Auto-merging drivers/video/fbdev/mmp/Kconfig
+Auto-merging drivers/video/fbdev/core/fbmon.c
+Auto-merging drivers/video/fbdev/core/fb_ddc.c
+Auto-merging drivers/video/fbdev/aty/mach64_cursor.c
+Auto-merging drivers/video/Makefile
+CONFLICT (content): Merge conflict in drivers/video/Makefile
+Auto-merging drivers/video/Kconfig
+CONFLICT (content): Merge conflict in drivers/video/Kconfig
+CONFLICT (rename/rename): Rename "drivers/video/exynos/exynos_dp_reg.h"->"drivers/gpu/drm/exynos/exynos_dp_reg.h" in branch "HEAD" rename "drivers/video/exynos/exynos_dp_reg.h"->"drivers/video/fbdev/exynos/exynos_dp_reg.h" in "omap_dss2/for-next"
+CONFLICT (rename/rename): Rename "drivers/video/exynos/exynos_dp_reg.c"->"drivers/gpu/drm/exynos/exynos_dp_reg.c" in branch "HEAD" rename "drivers/video/exynos/exynos_dp_reg.c"->"drivers/video/fbdev/exynos/exynos_dp_reg.c" in "omap_dss2/for-next"
+CONFLICT (rename/rename): Rename "drivers/video/exynos/exynos_dp_core.h"->"drivers/gpu/drm/exynos/exynos_dp_core.h" in branch "HEAD" rename "drivers/video/exynos/exynos_dp_core.h"->"drivers/video/fbdev/exynos/exynos_dp_core.h" in "omap_dss2/for-next"
+CONFLICT (rename/rename): Rename "drivers/video/exynos/exynos_dp_core.c"->"drivers/gpu/drm/exynos/exynos_dp_core.c" in branch "HEAD" rename "drivers/video/exynos/exynos_dp_core.c"->"drivers/video/fbdev/exynos/exynos_dp_core.c" in "omap_dss2/for-next"
+Auto-merging drivers/Makefile
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f drivers/video/fbdev/exynos/exynos_dp_core.c drivers/video/fbdev/exynos/exynos_dp_core.h drivers/video/fbdev/exynos/exynos_dp_reg.c drivers/video/fbdev/exynos/exynos_dp_reg.h drivers/video/exynos/exynos_dp_core.c drivers/video/exynos/exynos_dp_core.h drivers/video/exynos/exynos_dp_reg.c drivers/video/exynos/exynos_dp_reg.h
+drivers/video/exynos/exynos_dp_core.c: needs merge
+drivers/video/exynos/exynos_dp_core.h: needs merge
+drivers/video/exynos/exynos_dp_reg.c: needs merge
+drivers/video/exynos/exynos_dp_reg.h: needs merge
+drivers/video/fbdev/exynos/exynos_dp_core.c: needs merge
+drivers/video/fbdev/exynos/exynos_dp_core.h: needs merge
+drivers/video/fbdev/exynos/exynos_dp_reg.c: needs merge
+drivers/video/fbdev/exynos/exynos_dp_reg.h: needs merge
+rm 'drivers/video/exynos/exynos_dp_core.c'
+rm 'drivers/video/exynos/exynos_dp_core.h'
+rm 'drivers/video/exynos/exynos_dp_reg.c'
+rm 'drivers/video/exynos/exynos_dp_reg.h'
+rm 'drivers/video/fbdev/exynos/exynos_dp_core.c'
+rm 'drivers/video/fbdev/exynos/exynos_dp_core.h'
+rm 'drivers/video/fbdev/exynos/exynos_dp_reg.c'
+rm 'drivers/video/fbdev/exynos/exynos_dp_reg.h'
+$ git rm -f drivers/video/fbdev/sgivwfb.c
+drivers/video/fbdev/sgivwfb.c: needs merge
+rm 'drivers/video/fbdev/sgivwfb.c'
+$ git commit -v -a
+Recorded resolution for 'drivers/video/Kconfig'.
+[master a27f49932d0b] Merge remote-tracking branch 'omap_dss2/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/DocBook/device-drivers.tmpl          |   10 +-
+ drivers/Makefile                                   |    4 +-
+ drivers/staging/xgifb/vb_def.h                     |    2 +-
+ drivers/staging/xgifb/vb_struct.h                  |    2 +-
+ drivers/staging/xgifb/vgatypes.h                   |    4 +-
+ drivers/video/Kconfig                              | 2480 +------------------
+ drivers/video/Makefile                             |  166 +-
+ drivers/video/console/sticon.c                     |    2 +-
+ drivers/video/console/sticore.c                    |    2 +-
+ drivers/video/{ => fbdev}/68328fb.c                |    0
+ drivers/video/fbdev/Kconfig                        | 2481 ++++++++++++++++++++
+ drivers/video/fbdev/Makefile                       |  153 ++
+ drivers/video/{ => fbdev}/acornfb.c                |    0
+ drivers/video/{ => fbdev}/acornfb.h                |    0
+ drivers/video/{ => fbdev}/amba-clcd.c              |    0
+ drivers/video/{ => fbdev}/amifb.c                  |    0
+ drivers/video/{ => fbdev}/arcfb.c                  |    0
+ drivers/video/{ => fbdev}/arkfb.c                  |    0
+ drivers/video/{ => fbdev}/asiliantfb.c             |    0
+ drivers/video/{ => fbdev}/atafb.c                  |    0
+ drivers/video/{ => fbdev}/atafb.h                  |    0
+ drivers/video/{ => fbdev}/atafb_iplan2p2.c         |    0
+ drivers/video/{ => fbdev}/atafb_iplan2p4.c         |    0
+ drivers/video/{ => fbdev}/atafb_iplan2p8.c         |    0
+ drivers/video/{ => fbdev}/atafb_mfb.c              |    0
+ drivers/video/{ => fbdev}/atafb_utils.h            |    0
+ drivers/video/{ => fbdev}/atmel_lcdfb.c            |    0
+ drivers/video/{ => fbdev}/aty/Makefile             |    0
+ drivers/video/{ => fbdev}/aty/ati_ids.h            |    0
+ drivers/video/{ => fbdev}/aty/aty128fb.c           |    0
+ drivers/video/{ => fbdev}/aty/atyfb.h              |    0
+ drivers/video/{ => fbdev}/aty/atyfb_base.c         |    0
+ drivers/video/{ => fbdev}/aty/mach64_accel.c       |    0
+ drivers/video/{ => fbdev}/aty/mach64_ct.c          |    0
+ drivers/video/{ => fbdev}/aty/mach64_cursor.c      |    2 +-
+ drivers/video/{ => fbdev}/aty/mach64_gx.c          |    0
+ drivers/video/{ => fbdev}/aty/radeon_accel.c       |    0
+ drivers/video/{ => fbdev}/aty/radeon_backlight.c   |    0
+ drivers/video/{ => fbdev}/aty/radeon_base.c        |    0
+ drivers/video/{ => fbdev}/aty/radeon_i2c.c         |    0
+ drivers/video/{ => fbdev}/aty/radeon_monitor.c     |    0
+ drivers/video/{ => fbdev}/aty/radeon_pm.c          |    0
+ drivers/video/{ => fbdev}/aty/radeonfb.h           |    0
+ drivers/video/{ => fbdev}/au1100fb.c               |    0
+ drivers/video/{ => fbdev}/au1100fb.h               |    0
+ drivers/video/{ => fbdev}/au1200fb.c               |    0
+ drivers/video/{ => fbdev}/au1200fb.h               |    0
+ drivers/video/{ => fbdev}/auo_k1900fb.c            |    0
+ drivers/video/{ => fbdev}/auo_k1901fb.c            |    0
+ drivers/video/{ => fbdev}/auo_k190x.c              |    0
+ drivers/video/{ => fbdev}/auo_k190x.h              |    0
+ drivers/video/{ => fbdev}/bf537-lq035.c            |    0
+ drivers/video/{ => fbdev}/bf54x-lq043fb.c          |    0
+ drivers/video/{ => fbdev}/bfin-lq035q1-fb.c        |    0
+ drivers/video/{ => fbdev}/bfin-t350mcqb-fb.c       |    0
+ drivers/video/{ => fbdev}/bfin_adv7393fb.c         |    0
+ drivers/video/{ => fbdev}/bfin_adv7393fb.h         |    0
+ drivers/video/{ => fbdev}/broadsheetfb.c           |    0
+ drivers/video/{ => fbdev}/bt431.h                  |    0
+ drivers/video/{ => fbdev}/bt455.h                  |    0
+ drivers/video/{ => fbdev}/bw2.c                    |    0
+ drivers/video/{ => fbdev}/c2p.h                    |    0
+ drivers/video/{ => fbdev}/c2p_core.h               |    0
+ drivers/video/{ => fbdev}/c2p_iplan2.c             |    0
+ drivers/video/{ => fbdev}/c2p_planar.c             |    0
+ drivers/video/{ => fbdev}/carminefb.c              |    0
+ drivers/video/{ => fbdev}/carminefb.h              |    0
+ drivers/video/{ => fbdev}/carminefb_regs.h         |    0
+ drivers/video/{ => fbdev}/cg14.c                   |    0
+ drivers/video/{ => fbdev}/cg3.c                    |    0
+ drivers/video/{ => fbdev}/cg6.c                    |    0
+ drivers/video/{ => fbdev}/chipsfb.c                |    0
+ drivers/video/{ => fbdev}/cirrusfb.c               |    0
+ drivers/video/{ => fbdev}/clps711xfb.c             |    0
+ drivers/video/{ => fbdev}/cobalt_lcdfb.c           |    0
+ drivers/video/{ => fbdev}/controlfb.c              |    0
+ drivers/video/{ => fbdev}/controlfb.h              |    0
+ drivers/video/fbdev/core/Makefile                  |   16 +
+ drivers/video/{ => fbdev/core}/cfbcopyarea.c       |    0
+ drivers/video/{ => fbdev/core}/cfbfillrect.c       |    0
+ drivers/video/{ => fbdev/core}/cfbimgblt.c         |    0
+ drivers/video/{ => fbdev/core}/fb_ddc.c            |    2 +-
+ drivers/video/{ => fbdev/core}/fb_defio.c          |    0
+ drivers/video/{ => fbdev/core}/fb_draw.h           |    0
+ drivers/video/{ => fbdev/core}/fb_notify.c         |    0
+ drivers/video/{ => fbdev/core}/fb_sys_fops.c       |    0
+ drivers/video/{ => fbdev/core}/fbcmap.c            |    0
+ drivers/video/{ => fbdev/core}/fbcvt.c             |    0
+ drivers/video/{ => fbdev/core}/fbmem.c             |    0
+ drivers/video/{ => fbdev/core}/fbmon.c             |    2 +-
+ drivers/video/{ => fbdev/core}/fbsysfs.c           |    0
+ drivers/video/{ => fbdev/core}/modedb.c            |    0
+ drivers/video/{ => fbdev/core}/svgalib.c           |    0
+ drivers/video/{ => fbdev/core}/syscopyarea.c       |    0
+ drivers/video/{ => fbdev/core}/sysfillrect.c       |    0
+ drivers/video/{ => fbdev/core}/sysimgblt.c         |    0
+ drivers/video/{ => fbdev}/cyber2000fb.c            |    0
+ drivers/video/{ => fbdev}/cyber2000fb.h            |    0
+ drivers/video/{ => fbdev}/da8xx-fb.c               |    0
+ drivers/video/{ => fbdev}/dnfb.c                   |    0
+ drivers/video/{ => fbdev}/edid.h                   |    0
+ drivers/video/{ => fbdev}/efifb.c                  |    0
+ drivers/video/{ => fbdev}/ep93xx-fb.c              |    0
+ drivers/video/{ => fbdev}/exynos/Kconfig           |    0
+ drivers/video/{ => fbdev}/exynos/Makefile          |    0
+ drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi.c |    0
+ .../{ => fbdev}/exynos/exynos_mipi_dsi_common.c    |    0
+ .../{ => fbdev}/exynos/exynos_mipi_dsi_common.h    |    0
+ .../{ => fbdev}/exynos/exynos_mipi_dsi_lowlevel.c  |    0
+ .../{ => fbdev}/exynos/exynos_mipi_dsi_lowlevel.h  |    0
+ .../{ => fbdev}/exynos/exynos_mipi_dsi_regs.h      |    0
+ drivers/video/{ => fbdev}/exynos/s6e8ax0.c         |    0
+ drivers/video/{ => fbdev}/fb-puv3.c                |    0
+ drivers/video/{ => fbdev}/ffb.c                    |    0
+ drivers/video/{ => fbdev}/fm2fb.c                  |    0
+ drivers/video/{ => fbdev}/fsl-diu-fb.c             |    0
+ drivers/video/{ => fbdev}/g364fb.c                 |    0
+ drivers/video/{ => fbdev}/gbefb.c                  |    0
+ drivers/video/{ => fbdev}/geode/Kconfig            |    0
+ drivers/video/{ => fbdev}/geode/Makefile           |    0
+ drivers/video/{ => fbdev}/geode/display_gx.c       |    0
+ drivers/video/{ => fbdev}/geode/display_gx1.c      |    0
+ drivers/video/{ => fbdev}/geode/display_gx1.h      |    0
+ drivers/video/{ => fbdev}/geode/geodefb.h          |    0
+ drivers/video/{ => fbdev}/geode/gx1fb_core.c       |    0
+ drivers/video/{ => fbdev}/geode/gxfb.h             |    0
+ drivers/video/{ => fbdev}/geode/gxfb_core.c        |    0
+ drivers/video/{ => fbdev}/geode/lxfb.h             |    0
+ drivers/video/{ => fbdev}/geode/lxfb_core.c        |    0
+ drivers/video/{ => fbdev}/geode/lxfb_ops.c         |    0
+ drivers/video/{ => fbdev}/geode/suspend_gx.c       |    0
+ drivers/video/{ => fbdev}/geode/video_cs5530.c     |    0
+ drivers/video/{ => fbdev}/geode/video_cs5530.h     |    0
+ drivers/video/{ => fbdev}/geode/video_gx.c         |    0
+ drivers/video/{ => fbdev}/goldfishfb.c             |    0
+ drivers/video/{ => fbdev}/grvga.c                  |    0
+ drivers/video/{ => fbdev}/gxt4500.c                |    0
+ drivers/video/{ => fbdev}/hecubafb.c               |    0
+ drivers/video/{ => fbdev}/hgafb.c                  |    0
+ drivers/video/{ => fbdev}/hitfb.c                  |    0
+ drivers/video/{ => fbdev}/hpfb.c                   |    0
+ drivers/video/{ => fbdev}/hyperv_fb.c              |    0
+ drivers/video/{ => fbdev}/i740_reg.h               |    0
+ drivers/video/{ => fbdev}/i740fb.c                 |    0
+ drivers/video/{ => fbdev}/i810/Makefile            |    0
+ drivers/video/{ => fbdev}/i810/i810-i2c.c          |    0
+ drivers/video/{ => fbdev}/i810/i810.h              |    0
+ drivers/video/{ => fbdev}/i810/i810_accel.c        |    0
+ drivers/video/{ => fbdev}/i810/i810_dvt.c          |    0
+ drivers/video/{ => fbdev}/i810/i810_gtf.c          |    0
+ drivers/video/{ => fbdev}/i810/i810_main.c         |    0
+ drivers/video/{ => fbdev}/i810/i810_main.h         |    0
+ drivers/video/{ => fbdev}/i810/i810_regs.h         |    0
+ drivers/video/{ => fbdev}/igafb.c                  |    0
+ drivers/video/{ => fbdev}/imsttfb.c                |    0
+ drivers/video/{ => fbdev}/imxfb.c                  |    0
+ drivers/video/{ => fbdev}/intelfb/Makefile         |    0
+ drivers/video/{ => fbdev}/intelfb/intelfb.h        |    0
+ drivers/video/{ => fbdev}/intelfb/intelfb_i2c.c    |    0
+ drivers/video/{ => fbdev}/intelfb/intelfbdrv.c     |    0
+ drivers/video/{ => fbdev}/intelfb/intelfbhw.c      |    0
+ drivers/video/{ => fbdev}/intelfb/intelfbhw.h      |    0
+ drivers/video/{ => fbdev}/jz4740_fb.c              |    0
+ drivers/video/{ => fbdev}/kyro/Makefile            |    0
+ drivers/video/{ => fbdev}/kyro/STG4000InitDevice.c |    0
+ drivers/video/{ => fbdev}/kyro/STG4000Interface.h  |    0
+ .../video/{ => fbdev}/kyro/STG4000OverlayDevice.c  |    0
+ drivers/video/{ => fbdev}/kyro/STG4000Ramdac.c     |    0
+ drivers/video/{ => fbdev}/kyro/STG4000Reg.h        |    0
+ drivers/video/{ => fbdev}/kyro/STG4000VTG.c        |    0
+ drivers/video/{ => fbdev}/kyro/fbdev.c             |    0
+ drivers/video/{ => fbdev}/leo.c                    |    0
+ drivers/video/{ => fbdev}/macfb.c                  |    0
+ drivers/video/{ => fbdev}/macmodes.c               |    0
+ drivers/video/{ => fbdev}/macmodes.h               |    0
+ drivers/video/{ => fbdev}/matrox/Makefile          |    0
+ drivers/video/{ => fbdev}/matrox/g450_pll.c        |    0
+ drivers/video/{ => fbdev}/matrox/g450_pll.h        |    0
+ drivers/video/{ => fbdev}/matrox/i2c-matroxfb.c    |    0
+ .../video/{ => fbdev}/matrox/matroxfb_DAC1064.c    |    0
+ .../video/{ => fbdev}/matrox/matroxfb_DAC1064.h    |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_Ti3026.c |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_Ti3026.h |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_accel.c  |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_accel.h  |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_base.c   |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_base.h   |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_crtc2.c  |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_crtc2.h  |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_g450.c   |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_g450.h   |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_maven.c  |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_maven.h  |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_misc.c   |    0
+ drivers/video/{ => fbdev}/matrox/matroxfb_misc.h   |    0
+ drivers/video/{ => fbdev}/maxinefb.c               |    0
+ drivers/video/{ => fbdev}/mb862xx/Makefile         |    0
+ drivers/video/{ => fbdev}/mb862xx/mb862xx-i2c.c    |    0
+ drivers/video/{ => fbdev}/mb862xx/mb862xx_reg.h    |    0
+ drivers/video/{ => fbdev}/mb862xx/mb862xxfb.h      |    0
+ .../video/{ => fbdev}/mb862xx/mb862xxfb_accel.c    |    0
+ .../video/{ => fbdev}/mb862xx/mb862xxfb_accel.h    |    0
+ drivers/video/{ => fbdev}/mb862xx/mb862xxfbdrv.c   |    0
+ drivers/video/{ => fbdev}/mbx/Makefile             |    0
+ drivers/video/{ => fbdev}/mbx/mbxdebugfs.c         |    0
+ drivers/video/{ => fbdev}/mbx/mbxfb.c              |    0
+ drivers/video/{ => fbdev}/mbx/reg_bits.h           |    0
+ drivers/video/{ => fbdev}/mbx/regs.h               |    0
+ drivers/video/{ => fbdev}/metronomefb.c            |    0
+ drivers/video/{ => fbdev}/mmp/Kconfig              |    6 +-
+ drivers/video/{ => fbdev}/mmp/Makefile             |    0
+ drivers/video/{ => fbdev}/mmp/core.c               |    0
+ drivers/video/{ => fbdev}/mmp/fb/Kconfig           |    0
+ drivers/video/{ => fbdev}/mmp/fb/Makefile          |    0
+ drivers/video/{ => fbdev}/mmp/fb/mmpfb.c           |    0
+ drivers/video/{ => fbdev}/mmp/fb/mmpfb.h           |    0
+ drivers/video/{ => fbdev}/mmp/hw/Kconfig           |    0
+ drivers/video/{ => fbdev}/mmp/hw/Makefile          |    0
+ drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.c        |    0
+ drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.h        |    0
+ drivers/video/{ => fbdev}/mmp/hw/mmp_spi.c         |    0
+ drivers/video/{ => fbdev}/mmp/panel/Kconfig        |    0
+ drivers/video/{ => fbdev}/mmp/panel/Makefile       |    0
+ .../video/{ => fbdev}/mmp/panel/tpo_tj032md01bw.c  |    0
+ drivers/video/{ => fbdev}/msm/Makefile             |    0
+ drivers/video/{ => fbdev}/msm/mddi.c               |    0
+ drivers/video/{ => fbdev}/msm/mddi_client_dummy.c  |    0
+ .../video/{ => fbdev}/msm/mddi_client_nt35399.c    |    0
+ .../video/{ => fbdev}/msm/mddi_client_toshiba.c    |    0
+ drivers/video/{ => fbdev}/msm/mddi_hw.h            |    0
+ drivers/video/{ => fbdev}/msm/mdp.c                |    0
+ drivers/video/{ => fbdev}/msm/mdp_csc_table.h      |    0
+ drivers/video/{ => fbdev}/msm/mdp_hw.h             |    0
+ drivers/video/{ => fbdev}/msm/mdp_ppp.c            |    0
+ drivers/video/{ => fbdev}/msm/mdp_scale_tables.c   |    0
+ drivers/video/{ => fbdev}/msm/mdp_scale_tables.h   |    0
+ drivers/video/{ => fbdev}/msm/msm_fb.c             |    0
+ drivers/video/{ => fbdev}/mx3fb.c                  |    0
+ drivers/video/{ => fbdev}/mxsfb.c                  |    0
+ drivers/video/{ => fbdev}/n411.c                   |    0
+ drivers/video/{ => fbdev}/neofb.c                  |    0
+ drivers/video/{ => fbdev}/nuc900fb.c               |    0
+ drivers/video/{ => fbdev}/nuc900fb.h               |    0
+ drivers/video/{ => fbdev}/nvidia/Makefile          |    0
+ drivers/video/{ => fbdev}/nvidia/nv_accel.c        |    0
+ drivers/video/{ => fbdev}/nvidia/nv_backlight.c    |    0
+ drivers/video/{ => fbdev}/nvidia/nv_dma.h          |    0
+ drivers/video/{ => fbdev}/nvidia/nv_hw.c           |    0
+ drivers/video/{ => fbdev}/nvidia/nv_i2c.c          |    0
+ drivers/video/{ => fbdev}/nvidia/nv_local.h        |    0
+ drivers/video/{ => fbdev}/nvidia/nv_of.c           |    0
+ drivers/video/{ => fbdev}/nvidia/nv_proto.h        |    0
+ drivers/video/{ => fbdev}/nvidia/nv_setup.c        |    0
+ drivers/video/{ => fbdev}/nvidia/nv_type.h         |    0
+ drivers/video/{ => fbdev}/nvidia/nvidia.c          |    0
+ drivers/video/{ => fbdev}/ocfb.c                   |    0
+ drivers/video/{ => fbdev}/offb.c                   |    0
+ drivers/video/{ => fbdev}/omap/Kconfig             |    0
+ drivers/video/{ => fbdev}/omap/Makefile            |    0
+ drivers/video/{ => fbdev}/omap/hwa742.c            |    0
+ drivers/video/{ => fbdev}/omap/lcd_ams_delta.c     |    0
+ drivers/video/{ => fbdev}/omap/lcd_h3.c            |    0
+ drivers/video/{ => fbdev}/omap/lcd_htcherald.c     |    0
+ drivers/video/{ => fbdev}/omap/lcd_inn1510.c       |    0
+ drivers/video/{ => fbdev}/omap/lcd_inn1610.c       |    0
+ drivers/video/{ => fbdev}/omap/lcd_mipid.c         |    0
+ drivers/video/{ => fbdev}/omap/lcd_osk.c           |    0
+ drivers/video/{ => fbdev}/omap/lcd_palmte.c        |    0
+ drivers/video/{ => fbdev}/omap/lcd_palmtt.c        |    0
+ drivers/video/{ => fbdev}/omap/lcd_palmz71.c       |    0
+ drivers/video/{ => fbdev}/omap/lcdc.c              |    0
+ drivers/video/{ => fbdev}/omap/lcdc.h              |    0
+ drivers/video/{ => fbdev}/omap/omapfb.h            |    0
+ drivers/video/{ => fbdev}/omap/omapfb_main.c       |    0
+ drivers/video/{ => fbdev}/omap/sossi.c             |    0
+ drivers/video/fbdev/omap2/Kconfig                  |   10 +
+ drivers/video/{ => fbdev}/omap2/Makefile           |    0
+ .../video/{ => fbdev}/omap2/displays-new/Kconfig   |    0
+ .../video/{ => fbdev}/omap2/displays-new/Makefile  |    0
+ .../omap2/displays-new/connector-analog-tv.c       |    0
+ .../{ => fbdev}/omap2/displays-new/connector-dvi.c |    0
+ .../omap2/displays-new/connector-hdmi.c            |    0
+ .../omap2/displays-new/encoder-tfp410.c            |    0
+ .../omap2/displays-new/encoder-tpd12s015.c         |    0
+ .../{ => fbdev}/omap2/displays-new/panel-dpi.c     |    0
+ .../{ => fbdev}/omap2/displays-new/panel-dsi-cm.c  |    0
+ .../omap2/displays-new/panel-lgphilips-lb035q02.c  |    0
+ .../omap2/displays-new/panel-nec-nl8048hl11.c      |    0
+ .../omap2/displays-new/panel-sharp-ls037v7dw01.c   |    0
+ .../omap2/displays-new/panel-sony-acx565akm.c      |    0
+ .../omap2/displays-new/panel-tpo-td028ttec1.c      |    0
+ .../omap2/displays-new/panel-tpo-td043mtea1.c      |    0
+ drivers/video/{ => fbdev}/omap2/dss/Kconfig        |    0
+ drivers/video/{ => fbdev}/omap2/dss/Makefile       |    0
+ drivers/video/{ => fbdev}/omap2/dss/apply.c        |    0
+ drivers/video/{ => fbdev}/omap2/dss/core.c         |    0
+ drivers/video/{ => fbdev}/omap2/dss/dispc-compat.c |    0
+ drivers/video/{ => fbdev}/omap2/dss/dispc-compat.h |    0
+ drivers/video/{ => fbdev}/omap2/dss/dispc.c        |    0
+ drivers/video/{ => fbdev}/omap2/dss/dispc.h        |    0
+ drivers/video/{ => fbdev}/omap2/dss/dispc_coefs.c  |    0
+ .../video/{ => fbdev}/omap2/dss/display-sysfs.c    |    0
+ drivers/video/{ => fbdev}/omap2/dss/display.c      |    0
+ drivers/video/{ => fbdev}/omap2/dss/dpi.c          |    0
+ drivers/video/{ => fbdev}/omap2/dss/dsi.c          |    0
+ drivers/video/{ => fbdev}/omap2/dss/dss-of.c       |    0
+ drivers/video/{ => fbdev}/omap2/dss/dss.c          |    0
+ drivers/video/{ => fbdev}/omap2/dss/dss.h          |    0
+ drivers/video/{ => fbdev}/omap2/dss/dss_features.c |    0
+ drivers/video/{ => fbdev}/omap2/dss/dss_features.h |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi.h         |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi4.c        |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi4_core.c   |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi4_core.h   |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi_common.c  |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi_phy.c     |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi_pll.c     |    0
+ drivers/video/{ => fbdev}/omap2/dss/hdmi_wp.c      |    0
+ .../video/{ => fbdev}/omap2/dss/manager-sysfs.c    |    0
+ drivers/video/{ => fbdev}/omap2/dss/manager.c      |    0
+ drivers/video/{ => fbdev}/omap2/dss/output.c       |    0
+ .../video/{ => fbdev}/omap2/dss/overlay-sysfs.c    |    0
+ drivers/video/{ => fbdev}/omap2/dss/overlay.c      |    0
+ drivers/video/{ => fbdev}/omap2/dss/rfbi.c         |    0
+ drivers/video/{ => fbdev}/omap2/dss/sdi.c          |    0
+ drivers/video/{ => fbdev}/omap2/dss/venc.c         |    0
+ drivers/video/{ => fbdev}/omap2/dss/venc_panel.c   |    0
+ drivers/video/{ => fbdev}/omap2/omapfb/Kconfig     |    0
+ drivers/video/{ => fbdev}/omap2/omapfb/Makefile    |    0
+ .../video/{ => fbdev}/omap2/omapfb/omapfb-ioctl.c  |    0
+ .../video/{ => fbdev}/omap2/omapfb/omapfb-main.c   |    0
+ .../video/{ => fbdev}/omap2/omapfb/omapfb-sysfs.c  |    0
+ drivers/video/{ => fbdev}/omap2/omapfb/omapfb.h    |    0
+ drivers/video/{ => fbdev}/omap2/vrfb.c             |    0
+ drivers/video/{ => fbdev}/p9100.c                  |    0
+ drivers/video/{ => fbdev}/platinumfb.c             |    0
+ drivers/video/{ => fbdev}/platinumfb.h             |    0
+ drivers/video/{ => fbdev}/pm2fb.c                  |    0
+ drivers/video/{ => fbdev}/pm3fb.c                  |    0
+ drivers/video/{ => fbdev}/pmag-aa-fb.c             |    0
+ drivers/video/{ => fbdev}/pmag-ba-fb.c             |    0
+ drivers/video/{ => fbdev}/pmagb-b-fb.c             |    0
+ drivers/video/{ => fbdev}/ps3fb.c                  |    0
+ drivers/video/{ => fbdev}/pvr2fb.c                 |    0
+ drivers/video/{ => fbdev}/pxa168fb.c               |    0
+ drivers/video/{ => fbdev}/pxa168fb.h               |    0
+ drivers/video/{ => fbdev}/pxa3xx-gcu.c             |    0
+ drivers/video/{ => fbdev}/pxa3xx-gcu.h             |    0
+ drivers/video/{ => fbdev}/pxafb.c                  |    0
+ drivers/video/{ => fbdev}/pxafb.h                  |    0
+ drivers/video/{ => fbdev}/q40fb.c                  |    0
+ drivers/video/{ => fbdev}/riva/Makefile            |    0
+ drivers/video/{ => fbdev}/riva/fbdev.c             |    0
+ drivers/video/{ => fbdev}/riva/nv_driver.c         |    0
+ drivers/video/{ => fbdev}/riva/nv_type.h           |    0
+ drivers/video/{ => fbdev}/riva/nvreg.h             |    0
+ drivers/video/{ => fbdev}/riva/riva_hw.c           |    0
+ drivers/video/{ => fbdev}/riva/riva_hw.h           |    0
+ drivers/video/{ => fbdev}/riva/riva_tbl.h          |    0
+ drivers/video/{ => fbdev}/riva/rivafb-i2c.c        |    0
+ drivers/video/{ => fbdev}/riva/rivafb.h            |    0
+ drivers/video/{ => fbdev}/s1d13xxxfb.c             |    0
+ drivers/video/{ => fbdev}/s3c-fb.c                 |    0
+ drivers/video/{ => fbdev}/s3c2410fb.c              |    0
+ drivers/video/{ => fbdev}/s3c2410fb.h              |    0
+ drivers/video/{ => fbdev}/s3fb.c                   |    0
+ drivers/video/{ => fbdev}/sa1100fb.c               |    0
+ drivers/video/{ => fbdev}/sa1100fb.h               |    0
+ drivers/video/{ => fbdev}/savage/Makefile          |    0
+ drivers/video/{ => fbdev}/savage/savagefb-i2c.c    |    0
+ drivers/video/{ => fbdev}/savage/savagefb.h        |    0
+ drivers/video/{ => fbdev}/savage/savagefb_accel.c  |    0
+ drivers/video/{ => fbdev}/savage/savagefb_driver.c |    0
+ drivers/video/{ => fbdev}/sbuslib.c                |    0
+ drivers/video/{ => fbdev}/sbuslib.h                |    0
+ drivers/video/{ => fbdev}/sh7760fb.c               |    0
+ drivers/video/{ => fbdev}/sh_mipi_dsi.c            |    0
+ drivers/video/{ => fbdev}/sh_mobile_hdmi.c         |    0
+ drivers/video/{ => fbdev}/sh_mobile_lcdcfb.c       |    0
+ drivers/video/{ => fbdev}/sh_mobile_lcdcfb.h       |    0
+ drivers/video/{ => fbdev}/sh_mobile_meram.c        |    0
+ drivers/video/{ => fbdev}/simplefb.c               |    0
+ drivers/video/{ => fbdev}/sis/300vtbl.h            |    0
+ drivers/video/{ => fbdev}/sis/310vtbl.h            |    0
+ drivers/video/{ => fbdev}/sis/Makefile             |    0
+ drivers/video/{ => fbdev}/sis/init.c               |    0
+ drivers/video/{ => fbdev}/sis/init.h               |    0
+ drivers/video/{ => fbdev}/sis/init301.c            |    0
+ drivers/video/{ => fbdev}/sis/init301.h            |    0
+ drivers/video/{ => fbdev}/sis/initdef.h            |    0
+ drivers/video/{ => fbdev}/sis/initextlfb.c         |    0
+ drivers/video/{ => fbdev}/sis/oem300.h             |    0
+ drivers/video/{ => fbdev}/sis/oem310.h             |    0
+ drivers/video/{ => fbdev}/sis/sis.h                |    0
+ drivers/video/{ => fbdev}/sis/sis_accel.c          |    0
+ drivers/video/{ => fbdev}/sis/sis_accel.h          |    0
+ drivers/video/{ => fbdev}/sis/sis_main.c           |    0
+ drivers/video/{ => fbdev}/sis/sis_main.h           |    0
+ drivers/video/{ => fbdev}/sis/vgatypes.h           |    0
+ drivers/video/{ => fbdev}/sis/vstruct.h            |    0
+ drivers/video/{ => fbdev}/skeletonfb.c             |    0
+ drivers/video/{ => fbdev}/sm501fb.c                |    0
+ drivers/video/{ => fbdev}/smscufx.c                |    0
+ drivers/video/{ => fbdev}/ssd1307fb.c              |    0
+ drivers/video/{ => fbdev}/sstfb.c                  |    0
+ drivers/video/{ => fbdev}/sticore.h                |    0
+ drivers/video/{ => fbdev}/stifb.c                  |    0
+ drivers/video/{ => fbdev}/sunxvr1000.c             |    0
+ drivers/video/{ => fbdev}/sunxvr2500.c             |    0
+ drivers/video/{ => fbdev}/sunxvr500.c              |    0
+ drivers/video/{ => fbdev}/tcx.c                    |    0
+ drivers/video/{ => fbdev}/tdfxfb.c                 |    0
+ drivers/video/{ => fbdev}/tgafb.c                  |    0
+ drivers/video/{ => fbdev}/tmiofb.c                 |    0
+ drivers/video/{ => fbdev}/tridentfb.c              |    0
+ drivers/video/{ => fbdev}/udlfb.c                  |    0
+ drivers/video/{ => fbdev}/uvesafb.c                |    0
+ drivers/video/{ => fbdev}/valkyriefb.c             |    0
+ drivers/video/{ => fbdev}/valkyriefb.h             |    0
+ drivers/video/{ => fbdev}/vermilion/Makefile       |    0
+ drivers/video/{ => fbdev}/vermilion/cr_pll.c       |    0
+ drivers/video/{ => fbdev}/vermilion/vermilion.c    |    0
+ drivers/video/{ => fbdev}/vermilion/vermilion.h    |    0
+ drivers/video/{ => fbdev}/vesafb.c                 |    0
+ drivers/video/{ => fbdev}/vfb.c                    |    0
+ drivers/video/{ => fbdev}/vga16fb.c                |    0
+ drivers/video/{ => fbdev}/via/Makefile             |    0
+ drivers/video/{ => fbdev}/via/accel.c              |    0
+ drivers/video/{ => fbdev}/via/accel.h              |    0
+ drivers/video/{ => fbdev}/via/chip.h               |    0
+ drivers/video/{ => fbdev}/via/debug.h              |    0
+ drivers/video/{ => fbdev}/via/dvi.c                |    0
+ drivers/video/{ => fbdev}/via/dvi.h                |    0
+ drivers/video/{ => fbdev}/via/global.c             |    0
+ drivers/video/{ => fbdev}/via/global.h             |    0
+ drivers/video/{ => fbdev}/via/hw.c                 |    0
+ drivers/video/{ => fbdev}/via/hw.h                 |    0
+ drivers/video/{ => fbdev}/via/ioctl.c              |    0
+ drivers/video/{ => fbdev}/via/ioctl.h              |    0
+ drivers/video/{ => fbdev}/via/lcd.c                |    0
+ drivers/video/{ => fbdev}/via/lcd.h                |    0
+ drivers/video/{ => fbdev}/via/share.h              |    0
+ drivers/video/{ => fbdev}/via/tblDPASetting.c      |    0
+ drivers/video/{ => fbdev}/via/tblDPASetting.h      |    0
+ drivers/video/{ => fbdev}/via/via-core.c           |    0
+ drivers/video/{ => fbdev}/via/via-gpio.c           |    0
+ drivers/video/{ => fbdev}/via/via_aux.c            |    0
+ drivers/video/{ => fbdev}/via/via_aux.h            |    0
+ drivers/video/{ => fbdev}/via/via_aux_ch7301.c     |    0
+ drivers/video/{ => fbdev}/via/via_aux_edid.c       |    0
+ drivers/video/{ => fbdev}/via/via_aux_sii164.c     |    0
+ drivers/video/{ => fbdev}/via/via_aux_vt1621.c     |    0
+ drivers/video/{ => fbdev}/via/via_aux_vt1622.c     |    0
+ drivers/video/{ => fbdev}/via/via_aux_vt1625.c     |    0
+ drivers/video/{ => fbdev}/via/via_aux_vt1631.c     |    0
+ drivers/video/{ => fbdev}/via/via_aux_vt1632.c     |    0
+ drivers/video/{ => fbdev}/via/via_aux_vt1636.c     |    0
+ drivers/video/{ => fbdev}/via/via_clock.c          |    0
+ drivers/video/{ => fbdev}/via/via_clock.h          |    0
+ drivers/video/{ => fbdev}/via/via_i2c.c            |    0
+ drivers/video/{ => fbdev}/via/via_modesetting.c    |    0
+ drivers/video/{ => fbdev}/via/via_modesetting.h    |    0
+ drivers/video/{ => fbdev}/via/via_utility.c        |    0
+ drivers/video/{ => fbdev}/via/via_utility.h        |    0
+ drivers/video/{ => fbdev}/via/viafbdev.c           |    0
+ drivers/video/{ => fbdev}/via/viafbdev.h           |    0
+ drivers/video/{ => fbdev}/via/viamode.c            |    0
+ drivers/video/{ => fbdev}/via/viamode.h            |    0
+ drivers/video/{ => fbdev}/via/vt1636.c             |    0
+ drivers/video/{ => fbdev}/via/vt1636.h             |    0
+ drivers/video/{ => fbdev}/vt8500lcdfb.c            |    0
+ drivers/video/{ => fbdev}/vt8500lcdfb.h            |    0
+ drivers/video/{ => fbdev}/vt8623fb.c               |    0
+ drivers/video/{ => fbdev}/w100fb.c                 |    0
+ drivers/video/{ => fbdev}/w100fb.h                 |    0
+ drivers/video/{ => fbdev}/wm8505fb.c               |    0
+ drivers/video/{ => fbdev}/wm8505fb_regs.h          |    0
+ drivers/video/{ => fbdev}/wmt_ge_rops.c            |    2 +-
+ drivers/video/{ => fbdev}/wmt_ge_rops.h            |    0
+ drivers/video/{ => fbdev}/xen-fbfront.c            |    0
+ drivers/video/{ => fbdev}/xilinxfb.c               |    0
+ drivers/video/omap2/Kconfig                        |   10 -
+ 482 files changed, 2690 insertions(+), 2666 deletions(-)
+ rename drivers/video/{ => fbdev}/68328fb.c (100%)
+ create mode 100644 drivers/video/fbdev/Kconfig
+ create mode 100644 drivers/video/fbdev/Makefile
+ rename drivers/video/{ => fbdev}/acornfb.c (100%)
+ rename drivers/video/{ => fbdev}/acornfb.h (100%)
+ rename drivers/video/{ => fbdev}/amba-clcd.c (100%)
+ rename drivers/video/{ => fbdev}/amifb.c (100%)
+ rename drivers/video/{ => fbdev}/arcfb.c (100%)
+ rename drivers/video/{ => fbdev}/arkfb.c (100%)
+ rename drivers/video/{ => fbdev}/asiliantfb.c (100%)
+ rename drivers/video/{ => fbdev}/atafb.c (100%)
+ rename drivers/video/{ => fbdev}/atafb.h (100%)
+ rename drivers/video/{ => fbdev}/atafb_iplan2p2.c (100%)
+ rename drivers/video/{ => fbdev}/atafb_iplan2p4.c (100%)
+ rename drivers/video/{ => fbdev}/atafb_iplan2p8.c (100%)
+ rename drivers/video/{ => fbdev}/atafb_mfb.c (100%)
+ rename drivers/video/{ => fbdev}/atafb_utils.h (100%)
+ rename drivers/video/{ => fbdev}/atmel_lcdfb.c (100%)
+ rename drivers/video/{ => fbdev}/aty/Makefile (100%)
+ rename drivers/video/{ => fbdev}/aty/ati_ids.h (100%)
+ rename drivers/video/{ => fbdev}/aty/aty128fb.c (100%)
+ rename drivers/video/{ => fbdev}/aty/atyfb.h (100%)
+ rename drivers/video/{ => fbdev}/aty/atyfb_base.c (100%)
+ rename drivers/video/{ => fbdev}/aty/mach64_accel.c (100%)
+ rename drivers/video/{ => fbdev}/aty/mach64_ct.c (100%)
+ rename drivers/video/{ => fbdev}/aty/mach64_cursor.c (99%)
+ rename drivers/video/{ => fbdev}/aty/mach64_gx.c (100%)
+ rename drivers/video/{ => fbdev}/aty/radeon_accel.c (100%)
+ rename drivers/video/{ => fbdev}/aty/radeon_backlight.c (100%)
+ rename drivers/video/{ => fbdev}/aty/radeon_base.c (100%)
+ rename drivers/video/{ => fbdev}/aty/radeon_i2c.c (100%)
+ rename drivers/video/{ => fbdev}/aty/radeon_monitor.c (100%)
+ rename drivers/video/{ => fbdev}/aty/radeon_pm.c (100%)
+ rename drivers/video/{ => fbdev}/aty/radeonfb.h (100%)
+ rename drivers/video/{ => fbdev}/au1100fb.c (100%)
+ rename drivers/video/{ => fbdev}/au1100fb.h (100%)
+ rename drivers/video/{ => fbdev}/au1200fb.c (100%)
+ rename drivers/video/{ => fbdev}/au1200fb.h (100%)
+ rename drivers/video/{ => fbdev}/auo_k1900fb.c (100%)
+ rename drivers/video/{ => fbdev}/auo_k1901fb.c (100%)
+ rename drivers/video/{ => fbdev}/auo_k190x.c (100%)
+ rename drivers/video/{ => fbdev}/auo_k190x.h (100%)
+ rename drivers/video/{ => fbdev}/bf537-lq035.c (100%)
+ rename drivers/video/{ => fbdev}/bf54x-lq043fb.c (100%)
+ rename drivers/video/{ => fbdev}/bfin-lq035q1-fb.c (100%)
+ rename drivers/video/{ => fbdev}/bfin-t350mcqb-fb.c (100%)
+ rename drivers/video/{ => fbdev}/bfin_adv7393fb.c (100%)
+ rename drivers/video/{ => fbdev}/bfin_adv7393fb.h (100%)
+ rename drivers/video/{ => fbdev}/broadsheetfb.c (100%)
+ rename drivers/video/{ => fbdev}/bt431.h (100%)
+ rename drivers/video/{ => fbdev}/bt455.h (100%)
+ rename drivers/video/{ => fbdev}/bw2.c (100%)
+ rename drivers/video/{ => fbdev}/c2p.h (100%)
+ rename drivers/video/{ => fbdev}/c2p_core.h (100%)
+ rename drivers/video/{ => fbdev}/c2p_iplan2.c (100%)
+ rename drivers/video/{ => fbdev}/c2p_planar.c (100%)
+ rename drivers/video/{ => fbdev}/carminefb.c (100%)
+ rename drivers/video/{ => fbdev}/carminefb.h (100%)
+ rename drivers/video/{ => fbdev}/carminefb_regs.h (100%)
+ rename drivers/video/{ => fbdev}/cg14.c (100%)
+ rename drivers/video/{ => fbdev}/cg3.c (100%)
+ rename drivers/video/{ => fbdev}/cg6.c (100%)
+ rename drivers/video/{ => fbdev}/chipsfb.c (100%)
+ rename drivers/video/{ => fbdev}/cirrusfb.c (100%)
+ rename drivers/video/{ => fbdev}/clps711xfb.c (100%)
+ rename drivers/video/{ => fbdev}/cobalt_lcdfb.c (100%)
+ rename drivers/video/{ => fbdev}/controlfb.c (100%)
+ rename drivers/video/{ => fbdev}/controlfb.h (100%)
+ create mode 100644 drivers/video/fbdev/core/Makefile
+ rename drivers/video/{ => fbdev/core}/cfbcopyarea.c (100%)
+ rename drivers/video/{ => fbdev/core}/cfbfillrect.c (100%)
+ rename drivers/video/{ => fbdev/core}/cfbimgblt.c (100%)
+ rename drivers/video/{ => fbdev/core}/fb_ddc.c (99%)
+ rename drivers/video/{ => fbdev/core}/fb_defio.c (100%)
+ rename drivers/video/{ => fbdev/core}/fb_draw.h (100%)
+ rename drivers/video/{ => fbdev/core}/fb_notify.c (100%)
+ rename drivers/video/{ => fbdev/core}/fb_sys_fops.c (100%)
+ rename drivers/video/{ => fbdev/core}/fbcmap.c (100%)
+ rename drivers/video/{ => fbdev/core}/fbcvt.c (100%)
+ rename drivers/video/{ => fbdev/core}/fbmem.c (100%)
+ rename drivers/video/{ => fbdev/core}/fbmon.c (99%)
+ rename drivers/video/{ => fbdev/core}/fbsysfs.c (100%)
+ rename drivers/video/{ => fbdev/core}/modedb.c (100%)
+ rename drivers/video/{ => fbdev/core}/svgalib.c (100%)
+ rename drivers/video/{ => fbdev/core}/syscopyarea.c (100%)
+ rename drivers/video/{ => fbdev/core}/sysfillrect.c (100%)
+ rename drivers/video/{ => fbdev/core}/sysimgblt.c (100%)
+ rename drivers/video/{ => fbdev}/cyber2000fb.c (100%)
+ rename drivers/video/{ => fbdev}/cyber2000fb.h (100%)
+ rename drivers/video/{ => fbdev}/da8xx-fb.c (100%)
+ rename drivers/video/{ => fbdev}/dnfb.c (100%)
+ rename drivers/video/{ => fbdev}/edid.h (100%)
+ rename drivers/video/{ => fbdev}/efifb.c (100%)
+ rename drivers/video/{ => fbdev}/ep93xx-fb.c (100%)
+ rename drivers/video/{ => fbdev}/exynos/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/exynos/Makefile (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi.c (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_common.c (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_common.h (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_lowlevel.c (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_lowlevel.h (100%)
+ rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_regs.h (100%)
+ rename drivers/video/{ => fbdev}/exynos/s6e8ax0.c (100%)
+ rename drivers/video/{ => fbdev}/fb-puv3.c (100%)
+ rename drivers/video/{ => fbdev}/ffb.c (100%)
+ rename drivers/video/{ => fbdev}/fm2fb.c (100%)
+ rename drivers/video/{ => fbdev}/fsl-diu-fb.c (100%)
+ rename drivers/video/{ => fbdev}/g364fb.c (100%)
+ rename drivers/video/{ => fbdev}/gbefb.c (100%)
+ rename drivers/video/{ => fbdev}/geode/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/geode/Makefile (100%)
+ rename drivers/video/{ => fbdev}/geode/display_gx.c (100%)
+ rename drivers/video/{ => fbdev}/geode/display_gx1.c (100%)
+ rename drivers/video/{ => fbdev}/geode/display_gx1.h (100%)
+ rename drivers/video/{ => fbdev}/geode/geodefb.h (100%)
+ rename drivers/video/{ => fbdev}/geode/gx1fb_core.c (100%)
+ rename drivers/video/{ => fbdev}/geode/gxfb.h (100%)
+ rename drivers/video/{ => fbdev}/geode/gxfb_core.c (100%)
+ rename drivers/video/{ => fbdev}/geode/lxfb.h (100%)
+ rename drivers/video/{ => fbdev}/geode/lxfb_core.c (100%)
+ rename drivers/video/{ => fbdev}/geode/lxfb_ops.c (100%)
+ rename drivers/video/{ => fbdev}/geode/suspend_gx.c (100%)
+ rename drivers/video/{ => fbdev}/geode/video_cs5530.c (100%)
+ rename drivers/video/{ => fbdev}/geode/video_cs5530.h (100%)
+ rename drivers/video/{ => fbdev}/geode/video_gx.c (100%)
+ rename drivers/video/{ => fbdev}/goldfishfb.c (100%)
+ rename drivers/video/{ => fbdev}/grvga.c (100%)
+ rename drivers/video/{ => fbdev}/gxt4500.c (100%)
+ rename drivers/video/{ => fbdev}/hecubafb.c (100%)
+ rename drivers/video/{ => fbdev}/hgafb.c (100%)
+ rename drivers/video/{ => fbdev}/hitfb.c (100%)
+ rename drivers/video/{ => fbdev}/hpfb.c (100%)
+ rename drivers/video/{ => fbdev}/hyperv_fb.c (100%)
+ rename drivers/video/{ => fbdev}/i740_reg.h (100%)
+ rename drivers/video/{ => fbdev}/i740fb.c (100%)
+ rename drivers/video/{ => fbdev}/i810/Makefile (100%)
+ rename drivers/video/{ => fbdev}/i810/i810-i2c.c (100%)
+ rename drivers/video/{ => fbdev}/i810/i810.h (100%)
+ rename drivers/video/{ => fbdev}/i810/i810_accel.c (100%)
+ rename drivers/video/{ => fbdev}/i810/i810_dvt.c (100%)
+ rename drivers/video/{ => fbdev}/i810/i810_gtf.c (100%)
+ rename drivers/video/{ => fbdev}/i810/i810_main.c (100%)
+ rename drivers/video/{ => fbdev}/i810/i810_main.h (100%)
+ rename drivers/video/{ => fbdev}/i810/i810_regs.h (100%)
+ rename drivers/video/{ => fbdev}/igafb.c (100%)
+ rename drivers/video/{ => fbdev}/imsttfb.c (100%)
+ rename drivers/video/{ => fbdev}/imxfb.c (100%)
+ rename drivers/video/{ => fbdev}/intelfb/Makefile (100%)
+ rename drivers/video/{ => fbdev}/intelfb/intelfb.h (100%)
+ rename drivers/video/{ => fbdev}/intelfb/intelfb_i2c.c (100%)
+ rename drivers/video/{ => fbdev}/intelfb/intelfbdrv.c (100%)
+ rename drivers/video/{ => fbdev}/intelfb/intelfbhw.c (100%)
+ rename drivers/video/{ => fbdev}/intelfb/intelfbhw.h (100%)
+ rename drivers/video/{ => fbdev}/jz4740_fb.c (100%)
+ rename drivers/video/{ => fbdev}/kyro/Makefile (100%)
+ rename drivers/video/{ => fbdev}/kyro/STG4000InitDevice.c (100%)
+ rename drivers/video/{ => fbdev}/kyro/STG4000Interface.h (100%)
+ rename drivers/video/{ => fbdev}/kyro/STG4000OverlayDevice.c (100%)
+ rename drivers/video/{ => fbdev}/kyro/STG4000Ramdac.c (100%)
+ rename drivers/video/{ => fbdev}/kyro/STG4000Reg.h (100%)
+ rename drivers/video/{ => fbdev}/kyro/STG4000VTG.c (100%)
+ rename drivers/video/{ => fbdev}/kyro/fbdev.c (100%)
+ rename drivers/video/{ => fbdev}/leo.c (100%)
+ rename drivers/video/{ => fbdev}/macfb.c (100%)
+ rename drivers/video/{ => fbdev}/macmodes.c (100%)
+ rename drivers/video/{ => fbdev}/macmodes.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/Makefile (100%)
+ rename drivers/video/{ => fbdev}/matrox/g450_pll.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/g450_pll.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/i2c-matroxfb.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_DAC1064.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_DAC1064.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_Ti3026.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_Ti3026.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_accel.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_accel.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_base.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_base.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_crtc2.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_crtc2.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_g450.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_g450.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_maven.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_maven.h (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_misc.c (100%)
+ rename drivers/video/{ => fbdev}/matrox/matroxfb_misc.h (100%)
+ rename drivers/video/{ => fbdev}/maxinefb.c (100%)
+ rename drivers/video/{ => fbdev}/mb862xx/Makefile (100%)
+ rename drivers/video/{ => fbdev}/mb862xx/mb862xx-i2c.c (100%)
+ rename drivers/video/{ => fbdev}/mb862xx/mb862xx_reg.h (100%)
+ rename drivers/video/{ => fbdev}/mb862xx/mb862xxfb.h (100%)
+ rename drivers/video/{ => fbdev}/mb862xx/mb862xxfb_accel.c (100%)
+ rename drivers/video/{ => fbdev}/mb862xx/mb862xxfb_accel.h (100%)
+ rename drivers/video/{ => fbdev}/mb862xx/mb862xxfbdrv.c (100%)
+ rename drivers/video/{ => fbdev}/mbx/Makefile (100%)
+ rename drivers/video/{ => fbdev}/mbx/mbxdebugfs.c (100%)
+ rename drivers/video/{ => fbdev}/mbx/mbxfb.c (100%)
+ rename drivers/video/{ => fbdev}/mbx/reg_bits.h (100%)
+ rename drivers/video/{ => fbdev}/mbx/regs.h (100%)
+ rename drivers/video/{ => fbdev}/metronomefb.c (100%)
+ rename drivers/video/{ => fbdev}/mmp/Kconfig (61%)
+ rename drivers/video/{ => fbdev}/mmp/Makefile (100%)
+ rename drivers/video/{ => fbdev}/mmp/core.c (100%)
+ rename drivers/video/{ => fbdev}/mmp/fb/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/mmp/fb/Makefile (100%)
+ rename drivers/video/{ => fbdev}/mmp/fb/mmpfb.c (100%)
+ rename drivers/video/{ => fbdev}/mmp/fb/mmpfb.h (100%)
+ rename drivers/video/{ => fbdev}/mmp/hw/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/mmp/hw/Makefile (100%)
+ rename drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.c (100%)
+ rename drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.h (100%)
+ rename drivers/video/{ => fbdev}/mmp/hw/mmp_spi.c (100%)
+ rename drivers/video/{ => fbdev}/mmp/panel/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/mmp/panel/Makefile (100%)
+ rename drivers/video/{ => fbdev}/mmp/panel/tpo_tj032md01bw.c (100%)
+ rename drivers/video/{ => fbdev}/msm/Makefile (100%)
+ rename drivers/video/{ => fbdev}/msm/mddi.c (100%)
+ rename drivers/video/{ => fbdev}/msm/mddi_client_dummy.c (100%)
+ rename drivers/video/{ => fbdev}/msm/mddi_client_nt35399.c (100%)
+ rename drivers/video/{ => fbdev}/msm/mddi_client_toshiba.c (100%)
+ rename drivers/video/{ => fbdev}/msm/mddi_hw.h (100%)
+ rename drivers/video/{ => fbdev}/msm/mdp.c (100%)
+ rename drivers/video/{ => fbdev}/msm/mdp_csc_table.h (100%)
+ rename drivers/video/{ => fbdev}/msm/mdp_hw.h (100%)
+ rename drivers/video/{ => fbdev}/msm/mdp_ppp.c (100%)
+ rename drivers/video/{ => fbdev}/msm/mdp_scale_tables.c (100%)
+ rename drivers/video/{ => fbdev}/msm/mdp_scale_tables.h (100%)
+ rename drivers/video/{ => fbdev}/msm/msm_fb.c (100%)
+ rename drivers/video/{ => fbdev}/mx3fb.c (100%)
+ rename drivers/video/{ => fbdev}/mxsfb.c (100%)
+ rename drivers/video/{ => fbdev}/n411.c (100%)
+ rename drivers/video/{ => fbdev}/neofb.c (100%)
+ rename drivers/video/{ => fbdev}/nuc900fb.c (100%)
+ rename drivers/video/{ => fbdev}/nuc900fb.h (100%)
+ rename drivers/video/{ => fbdev}/nvidia/Makefile (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_accel.c (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_backlight.c (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_dma.h (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_hw.c (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_i2c.c (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_local.h (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_of.c (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_proto.h (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_setup.c (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nv_type.h (100%)
+ rename drivers/video/{ => fbdev}/nvidia/nvidia.c (100%)
+ rename drivers/video/{ => fbdev}/ocfb.c (100%)
+ rename drivers/video/{ => fbdev}/offb.c (100%)
+ rename drivers/video/{ => fbdev}/omap/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/omap/Makefile (100%)
+ rename drivers/video/{ => fbdev}/omap/hwa742.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_ams_delta.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_h3.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_htcherald.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_inn1510.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_inn1610.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_mipid.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_osk.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_palmte.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_palmtt.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcd_palmz71.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcdc.c (100%)
+ rename drivers/video/{ => fbdev}/omap/lcdc.h (100%)
+ rename drivers/video/{ => fbdev}/omap/omapfb.h (100%)
+ rename drivers/video/{ => fbdev}/omap/omapfb_main.c (100%)
+ rename drivers/video/{ => fbdev}/omap/sossi.c (100%)
+ create mode 100644 drivers/video/fbdev/omap2/Kconfig
+ rename drivers/video/{ => fbdev}/omap2/Makefile (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/Makefile (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/connector-analog-tv.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/connector-dvi.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/connector-hdmi.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/encoder-tfp410.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/encoder-tpd12s015.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-dpi.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-dsi-cm.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-lgphilips-lb035q02.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-nec-nl8048hl11.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-sharp-ls037v7dw01.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-sony-acx565akm.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-tpo-td028ttec1.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/displays-new/panel-tpo-td043mtea1.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/Makefile (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/apply.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/core.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dispc-compat.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dispc-compat.h (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dispc.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dispc.h (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dispc_coefs.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/display-sysfs.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/display.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dpi.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dsi.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dss-of.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dss.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dss.h (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dss_features.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/dss_features.h (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi.h (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi4.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi4_core.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi4_core.h (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi_common.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi_phy.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi_pll.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/hdmi_wp.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/manager-sysfs.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/manager.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/output.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/overlay-sysfs.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/overlay.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/rfbi.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/sdi.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/venc.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/dss/venc_panel.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/omapfb/Kconfig (100%)
+ rename drivers/video/{ => fbdev}/omap2/omapfb/Makefile (100%)
+ rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb-ioctl.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb-main.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb-sysfs.c (100%)
+ rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb.h (100%)
+ rename drivers/video/{ => fbdev}/omap2/vrfb.c (100%)
+ rename drivers/video/{ => fbdev}/p9100.c (100%)
+ rename drivers/video/{ => fbdev}/platinumfb.c (100%)
+ rename drivers/video/{ => fbdev}/platinumfb.h (100%)
+ rename drivers/video/{ => fbdev}/pm2fb.c (100%)
+ rename drivers/video/{ => fbdev}/pm3fb.c (100%)
+ rename drivers/video/{ => fbdev}/pmag-aa-fb.c (100%)
+ rename drivers/video/{ => fbdev}/pmag-ba-fb.c (100%)
+ rename drivers/video/{ => fbdev}/pmagb-b-fb.c (100%)
+ rename drivers/video/{ => fbdev}/ps3fb.c (100%)
+ rename drivers/video/{ => fbdev}/pvr2fb.c (100%)
+ rename drivers/video/{ => fbdev}/pxa168fb.c (100%)
+ rename drivers/video/{ => fbdev}/pxa168fb.h (100%)
+ rename drivers/video/{ => fbdev}/pxa3xx-gcu.c (100%)
+ rename drivers/video/{ => fbdev}/pxa3xx-gcu.h (100%)
+ rename drivers/video/{ => fbdev}/pxafb.c (100%)
+ rename drivers/video/{ => fbdev}/pxafb.h (100%)
+ rename drivers/video/{ => fbdev}/q40fb.c (100%)
+ rename drivers/video/{ => fbdev}/riva/Makefile (100%)
+ rename drivers/video/{ => fbdev}/riva/fbdev.c (100%)
+ rename drivers/video/{ => fbdev}/riva/nv_driver.c (100%)
+ rename drivers/video/{ => fbdev}/riva/nv_type.h (100%)
+ rename drivers/video/{ => fbdev}/riva/nvreg.h (100%)
+ rename drivers/video/{ => fbdev}/riva/riva_hw.c (100%)
+ rename drivers/video/{ => fbdev}/riva/riva_hw.h (100%)
+ rename drivers/video/{ => fbdev}/riva/riva_tbl.h (100%)
+ rename drivers/video/{ => fbdev}/riva/rivafb-i2c.c (100%)
+ rename drivers/video/{ => fbdev}/riva/rivafb.h (100%)
+ rename drivers/video/{ => fbdev}/s1d13xxxfb.c (100%)
+ rename drivers/video/{ => fbdev}/s3c-fb.c (100%)
+ rename drivers/video/{ => fbdev}/s3c2410fb.c (100%)
+ rename drivers/video/{ => fbdev}/s3c2410fb.h (100%)
+ rename drivers/video/{ => fbdev}/s3fb.c (100%)
+ rename drivers/video/{ => fbdev}/sa1100fb.c (100%)
+ rename drivers/video/{ => fbdev}/sa1100fb.h (100%)
+ rename drivers/video/{ => fbdev}/savage/Makefile (100%)
+ rename drivers/video/{ => fbdev}/savage/savagefb-i2c.c (100%)
+ rename drivers/video/{ => fbdev}/savage/savagefb.h (100%)
+ rename drivers/video/{ => fbdev}/savage/savagefb_accel.c (100%)
+ rename drivers/video/{ => fbdev}/savage/savagefb_driver.c (100%)
+ rename drivers/video/{ => fbdev}/sbuslib.c (100%)
+ rename drivers/video/{ => fbdev}/sbuslib.h (100%)
+ rename drivers/video/{ => fbdev}/sh7760fb.c (100%)
+ rename drivers/video/{ => fbdev}/sh_mipi_dsi.c (100%)
+ rename drivers/video/{ => fbdev}/sh_mobile_hdmi.c (100%)
+ rename drivers/video/{ => fbdev}/sh_mobile_lcdcfb.c (100%)
+ rename drivers/video/{ => fbdev}/sh_mobile_lcdcfb.h (100%)
+ rename drivers/video/{ => fbdev}/sh_mobile_meram.c (100%)
+ rename drivers/video/{ => fbdev}/simplefb.c (100%)
+ rename drivers/video/{ => fbdev}/sis/300vtbl.h (100%)
+ rename drivers/video/{ => fbdev}/sis/310vtbl.h (100%)
+ rename drivers/video/{ => fbdev}/sis/Makefile (100%)
+ rename drivers/video/{ => fbdev}/sis/init.c (100%)
+ rename drivers/video/{ => fbdev}/sis/init.h (100%)
+ rename drivers/video/{ => fbdev}/sis/init301.c (100%)
+ rename drivers/video/{ => fbdev}/sis/init301.h (100%)
+ rename drivers/video/{ => fbdev}/sis/initdef.h (100%)
+ rename drivers/video/{ => fbdev}/sis/initextlfb.c (100%)
+ rename drivers/video/{ => fbdev}/sis/oem300.h (100%)
+ rename drivers/video/{ => fbdev}/sis/oem310.h (100%)
+ rename drivers/video/{ => fbdev}/sis/sis.h (100%)
+ rename drivers/video/{ => fbdev}/sis/sis_accel.c (100%)
+ rename drivers/video/{ => fbdev}/sis/sis_accel.h (100%)
+ rename drivers/video/{ => fbdev}/sis/sis_main.c (100%)
+ rename drivers/video/{ => fbdev}/sis/sis_main.h (100%)
+ rename drivers/video/{ => fbdev}/sis/vgatypes.h (100%)
+ rename drivers/video/{ => fbdev}/sis/vstruct.h (100%)
+ rename drivers/video/{ => fbdev}/skeletonfb.c (100%)
+ rename drivers/video/{ => fbdev}/sm501fb.c (100%)
+ rename drivers/video/{ => fbdev}/smscufx.c (100%)
+ rename drivers/video/{ => fbdev}/ssd1307fb.c (100%)
+ rename drivers/video/{ => fbdev}/sstfb.c (100%)
+ rename drivers/video/{ => fbdev}/sticore.h (100%)
+ rename drivers/video/{ => fbdev}/stifb.c (100%)
+ rename drivers/video/{ => fbdev}/sunxvr1000.c (100%)
+ rename drivers/video/{ => fbdev}/sunxvr2500.c (100%)
+ rename drivers/video/{ => fbdev}/sunxvr500.c (100%)
+ rename drivers/video/{ => fbdev}/tcx.c (100%)
+ rename drivers/video/{ => fbdev}/tdfxfb.c (100%)
+ rename drivers/video/{ => fbdev}/tgafb.c (100%)
+ rename drivers/video/{ => fbdev}/tmiofb.c (100%)
+ rename drivers/video/{ => fbdev}/tridentfb.c (100%)
+ rename drivers/video/{ => fbdev}/udlfb.c (100%)
+ rename drivers/video/{ => fbdev}/uvesafb.c (100%)
+ rename drivers/video/{ => fbdev}/valkyriefb.c (100%)
+ rename drivers/video/{ => fbdev}/valkyriefb.h (100%)
+ rename drivers/video/{ => fbdev}/vermilion/Makefile (100%)
+ rename drivers/video/{ => fbdev}/vermilion/cr_pll.c (100%)
+ rename drivers/video/{ => fbdev}/vermilion/vermilion.c (100%)
+ rename drivers/video/{ => fbdev}/vermilion/vermilion.h (100%)
+ rename drivers/video/{ => fbdev}/vesafb.c (100%)
+ rename drivers/video/{ => fbdev}/vfb.c (100%)
+ rename drivers/video/{ => fbdev}/vga16fb.c (100%)
+ rename drivers/video/{ => fbdev}/via/Makefile (100%)
+ rename drivers/video/{ => fbdev}/via/accel.c (100%)
+ rename drivers/video/{ => fbdev}/via/accel.h (100%)
+ rename drivers/video/{ => fbdev}/via/chip.h (100%)
+ rename drivers/video/{ => fbdev}/via/debug.h (100%)
+ rename drivers/video/{ => fbdev}/via/dvi.c (100%)
+ rename drivers/video/{ => fbdev}/via/dvi.h (100%)
+ rename drivers/video/{ => fbdev}/via/global.c (100%)
+ rename drivers/video/{ => fbdev}/via/global.h (100%)
+ rename drivers/video/{ => fbdev}/via/hw.c (100%)
+ rename drivers/video/{ => fbdev}/via/hw.h (100%)
+ rename drivers/video/{ => fbdev}/via/ioctl.c (100%)
+ rename drivers/video/{ => fbdev}/via/ioctl.h (100%)
+ rename drivers/video/{ => fbdev}/via/lcd.c (100%)
+ rename drivers/video/{ => fbdev}/via/lcd.h (100%)
+ rename drivers/video/{ => fbdev}/via/share.h (100%)
+ rename drivers/video/{ => fbdev}/via/tblDPASetting.c (100%)
+ rename drivers/video/{ => fbdev}/via/tblDPASetting.h (100%)
+ rename drivers/video/{ => fbdev}/via/via-core.c (100%)
+ rename drivers/video/{ => fbdev}/via/via-gpio.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux.h (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_ch7301.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_edid.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_sii164.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_vt1621.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_vt1622.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_vt1625.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_vt1631.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_vt1632.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_aux_vt1636.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_clock.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_clock.h (100%)
+ rename drivers/video/{ => fbdev}/via/via_i2c.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_modesetting.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_modesetting.h (100%)
+ rename drivers/video/{ => fbdev}/via/via_utility.c (100%)
+ rename drivers/video/{ => fbdev}/via/via_utility.h (100%)
+ rename drivers/video/{ => fbdev}/via/viafbdev.c (100%)
+ rename drivers/video/{ => fbdev}/via/viafbdev.h (100%)
+ rename drivers/video/{ => fbdev}/via/viamode.c (100%)
+ rename drivers/video/{ => fbdev}/via/viamode.h (100%)
+ rename drivers/video/{ => fbdev}/via/vt1636.c (100%)
+ rename drivers/video/{ => fbdev}/via/vt1636.h (100%)
+ rename drivers/video/{ => fbdev}/vt8500lcdfb.c (100%)
+ rename drivers/video/{ => fbdev}/vt8500lcdfb.h (100%)
+ rename drivers/video/{ => fbdev}/vt8623fb.c (100%)
+ rename drivers/video/{ => fbdev}/w100fb.c (100%)
+ rename drivers/video/{ => fbdev}/w100fb.h (100%)
+ rename drivers/video/{ => fbdev}/wm8505fb.c (100%)
+ rename drivers/video/{ => fbdev}/wm8505fb_regs.h (100%)
+ rename drivers/video/{ => fbdev}/wmt_ge_rops.c (99%)
+ rename drivers/video/{ => fbdev}/wmt_ge_rops.h (100%)
+ rename drivers/video/{ => fbdev}/xen-fbfront.c (100%)
+ rename drivers/video/{ => fbdev}/xilinxfb.c (100%)
+ delete mode 100644 drivers/video/omap2/Kconfig
+$ git am -3 ../patches/0001-video-fbdev-fix-up-fro-removal-of-SGI-Visual-Worksta.patch
+Applying: video: fbdev: fix up fro removal of SGI Visual Workstation
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/video/fbdev/Kconfig
+M	drivers/video/fbdev/Makefile
+$ git add -A .
+$ git commit -v -a --amend
+[master 466a7c428695] Merge remote-tracking branch 'omap_dss2/for-next'
+$ git am -3 ../patches/0001-video-imxfb-Select-LCD_CLASS_DEVICE-unconditionally-.patch
+Applying: video: imxfb: Select LCD_CLASS_DEVICE unconditionally - fix
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/video/fbdev/Kconfig
+$ git add -A .
+$ git commit -v -a --amend
+[master df3568bed10a] Merge remote-tracking branch 'omap_dss2/for-next'
+Merging regulator/for-next (053ed78e189f Merge remote-tracking branches 'regulator/topic/axp20', 'regulator/topic/of', 'regulator/topic/pbias', 'regulator/topic/s2mps11' and 'regulator/topic/s5m8767' into regulator-next)
+$ git merge regulator/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/mfd/s2mps11.txt |  14 ++
+ drivers/regulator/Kconfig                         |   7 +
+ drivers/regulator/Makefile                        |   1 +
+ drivers/regulator/axp20x-regulator.c              | 285 ++++++++++++++++++++++
+ drivers/regulator/core.c                          |   3 +-
+ drivers/regulator/of_regulator.c                  |  26 +-
+ drivers/regulator/pbias-regulator.c               |  89 ++-----
+ drivers/regulator/s2mps11.c                       |  98 +++++++-
+ drivers/regulator/s5m8767.c                       |  17 +-
+ include/linux/mfd/samsung/s2mps14.h               |   2 +
+ include/linux/regulator/of_regulator.h            |   7 +
+ 11 files changed, 451 insertions(+), 98 deletions(-)
+ create mode 100644 drivers/regulator/axp20x-regulator.c
+Merging security/next (fab71a90edda security: Convert use of typedef ctl_table to struct ctl_table)
+$ git merge security/next
+Auto-merging security/selinux/hooks.c
+Auto-merging security/security.c
+Auto-merging include/linux/security.h
+Merge made by the 'recursive' strategy.
+ include/linux/key.h        | 11 +++++++++++
+ include/linux/security.h   |  6 +++---
+ security/capability.c      |  2 +-
+ security/keys/internal.h   | 11 +----------
+ security/keys/key.c        |  6 +++---
+ security/keys/keyctl.c     | 44 ++++++++++++++++++++++----------------------
+ security/keys/keyring.c    |  8 ++++----
+ security/keys/permission.c |  4 ++--
+ security/keys/persistent.c |  4 ++--
+ security/keys/proc.c       |  2 +-
+ security/keys/sysctl.c     |  2 +-
+ security/security.c        |  2 +-
+ security/selinux/hooks.c   |  2 +-
+ security/smack/smack_lsm.c |  9 +++++++--
+ 14 files changed, 60 insertions(+), 53 deletions(-)
+Merging selinux/next (6d32c850621b Merge tag 'v3.14' into next)
+$ git merge selinux/next
+Merge made by the 'recursive' strategy.
+Merging lblnet/next (d8ec26d7f828 Linux 3.13)
+$ git merge lblnet/next
+Already up-to-date.
+Merging watchdog/master (c9eaa447e77e Linux 3.15-rc1)
+$ git merge watchdog/master
+Already up-to-date.
+Merging iommu/next (e172b8122254 Merge branches 'iommu/fixes', 'arm/smmu', 'x86/amd', 'arm/omap', 'arm/shmobile' and 'x86/vt-d' into next)
+$ git merge iommu/next
+Already up-to-date.
+Merging dwmw2-iommu/master (5ae0566a0fff iommu/vt-d: fix bug in matching PCI devices with DRHD/RMRR descriptors)
+$ git merge dwmw2-iommu/master
+Merge made by the 'recursive' strategy.
+ drivers/iommu/dmar.c        |  3 ++-
+ drivers/iommu/intel-iommu.c | 10 +++++++---
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+Merging vfio/next (4379d2ae1528 vfio: always select ANON_INODES)
+$ git merge vfio/next
+Already up-to-date.
+Merging osd/linux-next (f1f6630b53e7 MAINTAINERS: Update email address for bhalevy)
+$ git merge osd/linux-next
+Already up-to-date.
+Merging jc_docs/docs-next (5c050fb96380 docs: update the development process document)
+$ git merge jc_docs/docs-next
+Already up-to-date.
+Merging trivial/for-next (c800bcd5f53f sparse: fix comment)
+$ git merge trivial/for-next
+Already up-to-date.
+Merging audit/master (4daa06f4d8b0 syscall.h: fix doc text for syscall_get_arch())
+$ git merge audit/master
+Resolved 'arch/mips/include/asm/syscall.h' using previous resolution.
+Resolved 'arch/x86/Kconfig' using previous resolution.
+Resolved 'kernel/audit.c' using previous resolution.
+Auto-merging kernel/audit.c
+CONFLICT (content): Merge conflict in kernel/audit.c
+Auto-merging arch/x86/Kconfig
+CONFLICT (content): Merge conflict in arch/x86/Kconfig
+Auto-merging arch/mips/include/asm/syscall.h
+CONFLICT (content): Merge conflict in arch/mips/include/asm/syscall.h
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 81a2874ea686] Merge remote-tracking branch 'audit/master'
+$ git diff -M --stat --summary HEAD^..
+ include/asm-generic/syscall.h |  2 +-
+ include/uapi/linux/audit.h    | 13 -------------
+ 2 files changed, 1 insertion(+), 14 deletions(-)
+Merging fsnotify/for-next (1ca39ab9d21a inotify: automatically restart syscalls)
+$ git merge fsnotify/for-next
+Already up-to-date.
+Merging devicetree/devicetree/next (d88cf7d7b424 Merge remote-tracking branch 'robh/for-next' into devicetree/next)
+$ git merge devicetree/devicetree/next
+Already up-to-date.
+Merging dt-rh/for-next (e7a62df8e8b4 of: Clean up of_update_property)
+$ git merge dt-rh/for-next
+Auto-merging Documentation/devicetree/bindings/vendor-prefixes.txt
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/arm/marvell,kirkwood.txt   | 97 ++++++++++++++++++++++
+ .../devicetree/bindings/i2c/trivial-devices.txt    | 16 ++++
+ .../devicetree/bindings/vendor-prefixes.txt        | 18 +++-
+ drivers/of/base.c                                  | 10 +--
+ drivers/of/fdt.c                                   |  2 +-
+ 5 files changed, 134 insertions(+), 9 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/marvell,kirkwood.txt
+Merging spi/for-next (5db6f05a77a0 Merge remote-tracking branches 'spi/topic/s3c24xx', 'spi/topic/sirf' and 'spi/topic/workqueue' into spi-next)
+$ git merge spi/for-next
+Auto-merging include/linux/spi/adi_spi3.h
+Auto-merging drivers/spi/spi-adi-v3.c
+Auto-merging arch/arm/mach-shmobile/clock-r8a7778.c
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/spi/fsl-spi.txt  |   6 +
+ Documentation/devicetree/bindings/spi/spi-bus.txt  |   2 +
+ .../devicetree/bindings/spi/spi-cadence.txt        |  31 +
+ arch/arm/mach-shmobile/clock-r8a7778.c             |   2 +-
+ arch/blackfin/mach-bf609/boards/ezkit.c            |  22 +-
+ arch/blackfin/mach-bf609/clock.c                   |   7 +
+ drivers/spi/Kconfig                                |  11 +-
+ drivers/spi/Makefile                               |   3 +-
+ drivers/spi/{spi-bfin-v3.c => spi-adi-v3.c}        | 433 ++++++-------
+ drivers/spi/spi-ath79.c                            |   1 -
+ drivers/spi/spi-atmel.c                            |   4 +-
+ drivers/spi/spi-bcm63xx-hsspi.c                    |   1 -
+ drivers/spi/spi-bcm63xx.c                          |   1 -
+ drivers/spi/spi-bfin5xx.c                          |   1 +
+ drivers/spi/spi-cadence.c                          | 673 +++++++++++++++++++++
+ drivers/spi/spi-falcon.c                           |   1 -
+ drivers/spi/spi-fsl-espi.c                         |  36 +-
+ drivers/spi/spi-fsl-lib.c                          |   6 -
+ drivers/spi/spi-fsl-lib.h                          |   1 -
+ drivers/spi/spi-fsl-spi.c                          |   2 +-
+ drivers/spi/spi-nuc900.c                           |   1 -
+ drivers/spi/spi-omap-uwire.c                       |   1 -
+ drivers/spi/spi-pxa2xx.c                           |   1 -
+ drivers/spi/spi-s3c24xx.c                          |  11 +-
+ drivers/spi/spi-s3c64xx.c                          |   1 -
+ drivers/spi/spi-sh-hspi.c                          |   4 +-
+ drivers/spi/spi-sh-sci.c                           |   1 -
+ drivers/spi/spi-sirf.c                             | 268 ++++----
+ drivers/spi/spi-sun4i.c                            |   1 -
+ drivers/spi/spi-sun6i.c                            |   1 -
+ drivers/spi/spi.c                                  |   4 +-
+ .../bfin_spi3.h => include/linux/spi/adi_spi3.h    |  20 +-
+ 32 files changed, 1177 insertions(+), 381 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-cadence.txt
+ rename drivers/spi/{spi-bfin-v3.c => spi-adi-v3.c} (60%)
+ create mode 100644 drivers/spi/spi-cadence.c
+ rename arch/blackfin/include/asm/bfin_spi3.h => include/linux/spi/adi_spi3.h (97%)
+Merging tip/auto-latest (7b8bfcc693cf Merge branch 'x86/vdso')
+$ git merge tip/auto-latest
+Merge made by the 'recursive' strategy.
+ arch/x86/include/asm/hw_irq.h      |  4 ++--
+ arch/x86/include/asm/uv/uv_hub.h   | 12 +----------
+ arch/x86/include/asm/uv/uv_mmrs.h  | 42 +++++++++++++++++++++++++++++++++++++-
+ arch/x86/kernel/apic/x2apic_uv_x.c | 26 ++++++++++++++++++-----
+ arch/x86/kernel/cpu/mshyperv.c     |  9 --------
+ arch/x86/kernel/i8259.c            | 20 +++++++++++++++++-
+ arch/x86/mm/pgtable.c              | 21 ++++++++++++-------
+ arch/x86/realmode/rm/Makefile      |  3 ++-
+ arch/x86/vdso/vdso-layout.lds.S    | 19 ++++++++---------
+ drivers/misc/sgi-gru/grufile.c     | 11 +++++++---
+ include/linux/compiler-intel.h     |  3 ---
+ include/linux/smp.h                | 11 ++++++++++
+ include/linux/tick.h               |  2 ++
+ kernel/sched/core.c                |  5 +----
+ kernel/sched/fair.c                | 13 ++++++------
+ kernel/sched/sched.h               | 11 +++++++++-
+ kernel/smp.c                       | 42 ++++++++++++++++++++++++++++++++++++++
+ kernel/time/tick-common.c          |  2 +-
+ kernel/time/tick-sched.c           | 26 ++++++++++++++++++++++-
+ 19 files changed, 215 insertions(+), 67 deletions(-)
+Merging clockevents/clockevents/next (09e15176ded1 clocksource: exynos_mct: silence a static checker warning)
+$ git merge clockevents/clockevents/next
+Already up-to-date.
+Merging edac/linux_next (49856dc973cd sb_edac: mark MCE messages as KERN_DEBUG)
+$ git merge edac/linux_next
+Already up-to-date.
+Merging edac-amd/for-next (c045ebdf6079 Merge branch 'edac-for-3.15' into for-next)
+$ git merge edac-amd/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging ftrace/for-next (17a280ea8111 tracing: Add missing function triggers dump and cpudump to README)
+$ git merge ftrace/for-next
+Already up-to-date.
+Merging rcu/rcu/next (765a3f4fed70 rcu: Provide grace-period piggybacking API)
+$ git merge rcu/rcu/next
+Already up-to-date.
+Merging uprobes/for-next (0326f5a94dde uprobes/core: Handle breakpoint and singlestep exceptions)
+$ git merge uprobes/for-next
+Already up-to-date.
+Merging kvm/linux-next (0f689a33ad17 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux)
+$ git merge kvm/linux-next
+Already up-to-date.
+Merging kvm-arm/kvm-arm-next (b73117c49364 Merge branch 'kvm-ppc-next' of git://github.com/agraf/linux-2.6 into kvm-queue)
+$ git merge kvm-arm/kvm-arm-next
+Already up-to-date.
+Merging kvm-ppc/kvm-ppc-next (7227fc066660 Merge branch 'kvm-ppchv-next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc into kvm-next)
+$ git merge kvm-ppc/kvm-ppc-next
+Already up-to-date.
+Merging oprofile/for-next (6ce4eac1f600 Linux 3.13-rc1)
+$ git merge oprofile/for-next
+Already up-to-date.
+Merging fw-nohz/nohz/next (74876a98a87a printk: Wake up klogd using irq_work)
+$ git merge fw-nohz/nohz/next
+Already up-to-date.
+Merging xen-tip/linux-next (0a25e113b480 Merge branch 'devel/for-linus-3.15' into linux-next)
+$ git merge xen-tip/linux-next
+Merge made by the 'recursive' strategy.
+ drivers/xen/xen-acpi-processor.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+Merging percpu/for-next (4abee313c9a8 Merge branch 'for-3.16' into for-next)
+$ git merge percpu/for-next
+Merge made by the 'recursive' strategy.
+ include/linux/percpu.h | 2 +-
+ mm/percpu.c            | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+Merging workqueues/for-next (77f300b198f9 workqueue: fix bugs in wq_update_unbound_numa() failure path)
+$ git merge workqueues/for-next
+Merge made by the 'recursive' strategy.
+ kernel/workqueue.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+Merging drivers-x86/linux-next (7a70906e55bf alienware-wmi: cover some scenarios where memory allocations would fail)
+$ git merge drivers-x86/linux-next
+Merge made by the 'recursive' strategy.
+Merging chrome-platform/for-next (2b8454a75b90 platform/chrome: unregister platform driver/device when module exit)
+$ git merge chrome-platform/for-next
+Already up-to-date.
+Merging sysctl/master (4e474a00d7ff sysctl: protect poll() in entries that may go away)
+$ git merge sysctl/master
+Already up-to-date.
+Merging regmap/for-next (b94f4fe06dd8 Merge remote-tracking branches 'regmap/topic/le', 'regmap/topic/mmio' and 'regmap/topic/rbtree' into regmap-next)
+$ git merge regmap/for-next
+Merge made by the 'recursive' strategy.
+ drivers/base/regmap/regcache-rbtree.c |  8 +++---
+ drivers/base/regmap/regmap-mmio.c     | 29 +++++++++++++++----
+ drivers/base/regmap/regmap.c          | 52 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 80 insertions(+), 9 deletions(-)
+Merging hsi/for-next (43139a61fc68 HSI: hsi_char: Update ioctl-number.txt)
+$ git merge hsi/for-next
+Already up-to-date.
+Merging leds/for-next (95d33e9fcc7e leds: leds-pwm: add DT support for LEDs wired to supply)
+$ git merge leds/for-next
+Removing include/linux/platform_data/leds-pca9685.h
+Removing drivers/leds/leds-pca9685.c
+Auto-merging drivers/leds/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/leds/leds-pwm.txt          |   2 +
+ drivers/leds/Kconfig                               |  10 -
+ drivers/leds/Makefile                              |   1 -
+ drivers/leds/dell-led.c                            | 171 ++++++++++++++++-
+ drivers/leds/leds-pca9685.c                        | 213 ---------------------
+ drivers/leds/leds-pwm.c                            | 144 +++++++-------
+ include/linux/dell-led.h                           |  10 +
+ include/linux/platform_data/leds-pca9685.h         |  35 ----
+ 8 files changed, 246 insertions(+), 340 deletions(-)
+ delete mode 100644 drivers/leds/leds-pca9685.c
+ create mode 100644 include/linux/dell-led.h
+ delete mode 100644 include/linux/platform_data/leds-pca9685.h
+Merging driver-core/driver-core-next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge driver-core/driver-core-next
+Already up-to-date.
+Merging tty/tty-next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge tty/tty-next
+Already up-to-date.
+Merging usb/usb-next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge usb/usb-next
+Already up-to-date.
+Merging usb-gadget/next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge usb-gadget/next
+Already up-to-date.
+Merging staging/staging-next (dff222670ebe staging: rtl8723au: Make _rtw_free_network23() static)
+$ git merge staging/staging-next
+Recorded preimage for 'drivers/staging/rtl8723au/core/rtw_ieee80211.c'
+Recorded preimage for 'drivers/staging/rtl8723au/core/rtw_mlme_ext.c'
+Recorded preimage for 'drivers/staging/rtl8723au/core/rtw_wlan_util.c'
+Removing drivers/staging/rtl8723au/include/rtw_p2p.h
+Removing drivers/staging/rtl8723au/include/ethernet.h
+Auto-merging drivers/staging/rtl8723au/core/rtw_wlan_util.c
+CONFLICT (content): Merge conflict in drivers/staging/rtl8723au/core/rtw_wlan_util.c
+CONFLICT (modify/delete): drivers/staging/rtl8723au/core/rtw_p2p.c deleted in staging/staging-next and modified in HEAD. Version HEAD of drivers/staging/rtl8723au/core/rtw_p2p.c left in tree.
+Auto-merging drivers/staging/rtl8723au/core/rtw_mlme_ext.c
+CONFLICT (content): Merge conflict in drivers/staging/rtl8723au/core/rtw_mlme_ext.c
+Auto-merging drivers/staging/rtl8723au/core/rtw_ieee80211.c
+CONFLICT (content): Merge conflict in drivers/staging/rtl8723au/core/rtw_ieee80211.c
+Auto-merging drivers/staging/comedi/comedi_fops.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f drivers/staging/rtl8723au/core/rtw_p2p.c
+drivers/staging/rtl8723au/core/rtw_p2p.c: needs merge
+rm 'drivers/staging/rtl8723au/core/rtw_p2p.c'
+$ git commit -v -a
+Recorded resolution for 'drivers/staging/rtl8723au/core/rtw_ieee80211.c'.
+Recorded resolution for 'drivers/staging/rtl8723au/core/rtw_mlme_ext.c'.
+Recorded resolution for 'drivers/staging/rtl8723au/core/rtw_wlan_util.c'.
+[master d2084840d8e4] Merge remote-tracking branch 'staging/staging-next'
+$ git diff -M --stat --summary HEAD^..
+ drivers/staging/bcm/CmHost.c                       |   50 +-
+ drivers/staging/bcm/Qos.c                          |  174 +-
+ drivers/staging/bcm/hostmibs.c                     |   51 +-
+ drivers/staging/comedi/comedi_fops.c               |    9 +-
+ drivers/staging/comedi/drivers.c                   |    1 +
+ drivers/staging/comedi/drivers/addi_apci_1032.c    |    2 +-
+ drivers/staging/comedi/drivers/addi_apci_1500.c    |    2 +-
+ drivers/staging/comedi/drivers/addi_apci_1564.c    |    2 +-
+ drivers/staging/comedi/drivers/addi_apci_2032.c    |    2 +-
+ drivers/staging/comedi/drivers/addi_apci_3120.c    |    2 +-
+ drivers/staging/comedi/drivers/adl_pci9118.c       |    6 +-
+ drivers/staging/comedi/drivers/das6402.c           |    2 +-
+ drivers/staging/comedi/drivers/pcl812.c            |    3 +-
+ drivers/staging/comedi/drivers/s626.c              |   36 +-
+ drivers/staging/dgap/dgap.c                        |  191 +-
+ drivers/staging/dgap/dgap.h                        |  423 +-
+ drivers/staging/iio/light/tsl2583.c                |   38 +-
+ .../staging/iio/trigger/iio-trig-periodic-rtc.c    |    3 +-
+ drivers/staging/rtl8188eu/include/xmit_osdep.h     |    4 -
+ drivers/staging/rtl8188eu/os_dep/os_intfs.c        |    6 +-
+ drivers/staging/rtl8188eu/os_dep/usb_intf.c        |   29 -
+ drivers/staging/rtl8723au/Kconfig                  |    8 -
+ drivers/staging/rtl8723au/Makefile                 |    1 -
+ drivers/staging/rtl8723au/core/rtw_ap.c            |  196 +-
+ drivers/staging/rtl8723au/core/rtw_cmd.c           |   76 +-
+ drivers/staging/rtl8723au/core/rtw_ieee80211.c     |  732 +--
+ drivers/staging/rtl8723au/core/rtw_ioctl_set.c     |   17 +-
+ drivers/staging/rtl8723au/core/rtw_mlme.c          | 1362 ++---
+ drivers/staging/rtl8723au/core/rtw_mlme_ext.c      | 5835 +++++---------------
+ drivers/staging/rtl8723au/core/rtw_p2p.c           | 4001 --------------
+ drivers/staging/rtl8723au/core/rtw_pwrctrl.c       |   78 +-
+ drivers/staging/rtl8723au/core/rtw_recv.c          |   40 +-
+ drivers/staging/rtl8723au/core/rtw_sreset.c        |   22 +-
+ drivers/staging/rtl8723au/core/rtw_wlan_util.c     |  454 +-
+ drivers/staging/rtl8723au/core/rtw_xmit.c          |  177 +-
+ drivers/staging/rtl8723au/hal/hal_com.c            |  111 +-
+ drivers/staging/rtl8723au/hal/hal_intf.c           |   12 -
+ .../staging/rtl8723au/hal/rtl8723a_bt-coexist.c    |   18 +-
+ drivers/staging/rtl8723au/hal/rtl8723a_cmd.c       |   91 +-
+ drivers/staging/rtl8723au/hal/rtl8723a_dm.c        |   11 +-
+ drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c  |  303 +-
+ drivers/staging/rtl8723au/hal/rtl8723au_recv.c     |   11 +-
+ drivers/staging/rtl8723au/hal/usb_halinit.c        |   53 +-
+ drivers/staging/rtl8723au/include/drv_types.h      |   26 -
+ drivers/staging/rtl8723au/include/ethernet.h       |   22 -
+ drivers/staging/rtl8723au/include/hal_com.h        |   13 +-
+ drivers/staging/rtl8723au/include/hal_intf.h       |   90 +-
+ drivers/staging/rtl8723au/include/ieee80211.h      |  148 +-
+ drivers/staging/rtl8723au/include/mlme_osdep.h     |    4 -
+ drivers/staging/rtl8723au/include/osdep_service.h  |   21 -
+ drivers/staging/rtl8723au/include/recv_osdep.h     |    9 -
+ drivers/staging/rtl8723au/include/rtl8723a_cmd.h   |    4 -
+ drivers/staging/rtl8723au/include/rtl8723a_hal.h   |   15 -
+ drivers/staging/rtl8723au/include/rtw_ap.h         |    2 -
+ drivers/staging/rtl8723au/include/rtw_cmd.h        |    3 -
+ drivers/staging/rtl8723au/include/rtw_mlme.h       |  131 -
+ drivers/staging/rtl8723au/include/rtw_mlme_ext.h   |   54 +-
+ drivers/staging/rtl8723au/include/rtw_p2p.h        |  158 -
+ drivers/staging/rtl8723au/include/rtw_security.h   |   17 -
+ drivers/staging/rtl8723au/include/wifi.h           |  219 +-
+ drivers/staging/rtl8723au/include/xmit_osdep.h     |   19 -
+ drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c  |  981 +---
+ drivers/staging/rtl8723au/os_dep/mlme_linux.c      |  105 -
+ drivers/staging/rtl8723au/os_dep/os_intfs.c        |   63 +-
+ drivers/staging/rtl8723au/os_dep/osdep_service.c   |   11 -
+ drivers/staging/rtl8723au/os_dep/recv_linux.c      |   58 -
+ drivers/staging/rtl8723au/os_dep/usb_intf.c        |   28 +-
+ drivers/staging/rtl8723au/os_dep/xmit_linux.c      |   41 -
+ drivers/staging/rtl8821ae/rtl8821ae/hw.h           |   35 +-
+ 69 files changed, 3042 insertions(+), 13880 deletions(-)
+ delete mode 100644 drivers/staging/rtl8723au/core/rtw_p2p.c
+ delete mode 100644 drivers/staging/rtl8723au/include/ethernet.h
+ delete mode 100644 drivers/staging/rtl8723au/include/rtw_p2p.h
+Merging char-misc/char-misc-next (c9eaa447e77e Linux 3.15-rc1)
+$ git merge char-misc/char-misc-next
+Already up-to-date.
+Merging cgroup/for-next (49957f8e2a43 cgroup: newly created dirs and files should be owned by the creator)
+$ git merge cgroup/for-next
+Already up-to-date.
+Merging scsi/for-next (b908a5a97b7f [SCSI] hpsa: fix NULL dereference in hpsa_put_ctlr_into_performant_mode())
+$ git merge scsi/for-next
+Merge made by the 'recursive' strategy.
+ drivers/scsi/hpsa.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+Merging target-updates/for-next (b076808051f2 ib_srpt: Use correct ib_sg_dma primitives)
+$ git merge target-updates/for-next
+Already up-to-date.
+Merging target-merge/for-next-merge (b28a960c42fc Linux 3.14-rc2)
+$ git merge target-merge/for-next-merge
+Already up-to-date.
+Merging writeback/writeback-for-next (f9b0e058cbd0 writeback: Fix data corruption on NFS)
+$ git merge writeback/writeback-for-next
+Already up-to-date.
+Merging hwspinlock/linux-next (8b37fcfc9b34 hwspinlock: add MAINTAINERS entries)
+$ git merge hwspinlock/linux-next
+Already up-to-date.
+Merging pinctrl/for-next (cc17609e1855 Merge branch 'devel' into for-next)
+$ git merge pinctrl/for-next
+Merge made by the 'recursive' strategy.
+ .../bindings/pinctrl/qcom,apq8064-pinctrl.txt      |  88 ++++
+ drivers/pinctrl/Kconfig                            |  11 +-
+ drivers/pinctrl/Makefile                           |   1 +
+ drivers/pinctrl/pinctrl-adi2.c                     |   2 +-
+ drivers/pinctrl/pinctrl-apq8064.c                  | 566 +++++++++++++++++++++
+ drivers/pinctrl/pinctrl-lantiq.h                   |   1 +
+ drivers/pinctrl/pinctrl-msm.c                      |   4 +-
+ drivers/pinctrl/pinctrl-msm.h                      |   3 +-
+ drivers/pinctrl/pinctrl-msm8x74.c                  |   3 +-
+ drivers/pinctrl/pinctrl-st.c                       | 130 ++---
+ drivers/pinctrl/sh-pfc/pfc-r8a7791.c               |  37 +-
+ 11 files changed, 733 insertions(+), 113 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
+ create mode 100644 drivers/pinctrl/pinctrl-apq8064.c
+Merging vhost/linux-next (d3d665a654a3 vhost-scsi: whitespace tweak)
+$ git merge vhost/linux-next
+Already up-to-date.
+Merging remoteproc/for-next (bd88acba5f98 remoteproc/ste_modem: staticize local symbols)
+$ git merge remoteproc/for-next
+Already up-to-date.
+Merging rpmsg/for-next (397944df3290 rpmsg: fix kconfig dependencies for VIRTIO)
+$ git merge rpmsg/for-next
+Already up-to-date.
+Merging gpio/for-next (da150898c982 Merge branch 'devel' into for-next)
+$ git merge gpio/for-next
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/gpio/driver.txt |  59 +++++++++++++++++
+ MAINTAINERS                   |   1 +
+ drivers/gpio/Kconfig          |  11 +++-
+ drivers/gpio/Makefile         |   2 +-
+ drivers/gpio/gpio-dwapb.c     |   3 -
+ drivers/gpio/gpio-omap.c      | 128 ++++++++++++++++++------------------
+ drivers/gpio/gpio-tc3589x.c   | 148 +++++++++---------------------------------
+ drivers/gpio/gpio-zevio.c     |   2 +-
+ drivers/gpio/gpiolib-acpi.c   |  12 +++-
+ drivers/gpio/gpiolib.c        |  14 +++-
+ include/linux/gpio/driver.h   |   5 +-
+ include/linux/mfd/tc3589x.h   |   1 -
+ 12 files changed, 193 insertions(+), 193 deletions(-)
+Merging dma-mapping/dma-mapping-next (68efd7d2fb32 arm: dma-mapping: remove order parameter from arm_iommu_create_mapping())
+$ git merge dma-mapping/dma-mapping-next
+Already up-to-date.
+Merging pwm/for-next (2ae69a460413 pwm: pxa: Constify OF match table)
+$ git merge pwm/for-next
+Already up-to-date.
+Merging dma-buf/for-next (dcb99fd9b08c Linux 3.14-rc7)
+$ git merge dma-buf/for-next
+Already up-to-date.
+Merging userns/for-next (3efe1ac78e99 vfs: Block intuitively in the case of BSD accounting files)
+$ git merge userns/for-next
+Recorded preimage for 'fs/namespace.c'
+Resolved 'fs/dcache.c' using previous resolution.
+Resolved 'fs/namei.c' using previous resolution.
+Auto-merging include/linux/dcache.h
+Auto-merging fs/proc/fd.c
+Auto-merging fs/proc/base.c
+Auto-merging fs/nfs/dir.c
+Auto-merging fs/namespace.c
+CONFLICT (content): Merge conflict in fs/namespace.c
+Auto-merging fs/namei.c
+CONFLICT (content): Merge conflict in fs/namei.c
+Auto-merging fs/mount.h
+Auto-merging fs/kernfs/dir.c
+Auto-merging fs/fuse/dir.c
+Auto-merging fs/dcache.c
+CONFLICT (content): Merge conflict in fs/dcache.c
+Auto-merging fs/ceph/dir.c
+Auto-merging fs/btrfs/ioctl.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'fs/namespace.c'.
+[master d90734d818ac] Merge remote-tracking branch 'userns/for-next'
+$ git diff -M --stat --summary HEAD^..
+ fs/afs/dir.c           |   5 --
+ fs/btrfs/ioctl.c       |   5 +-
+ fs/ceph/dir.c          |   1 -
+ fs/cifs/readdir.c      |   6 +--
+ fs/dcache.c            | 140 ++++++++++++++++++-------------------------------
+ fs/fuse/dir.c          |   7 +--
+ fs/gfs2/dentry.c       |   3 --
+ fs/kernfs/dir.c        |  11 ----
+ fs/mount.h             |  22 ++++++++
+ fs/namei.c             |  22 ++++----
+ fs/namespace.c         | 130 +++++++++++++++++++++++++++++++++++++++++----
+ fs/nfs/dir.c           |   7 +--
+ fs/proc/base.c         |  10 +---
+ fs/proc/fd.c           |   2 -
+ include/linux/dcache.h |   3 +-
+ kernel/acct.c          |  25 +++++++--
+ 16 files changed, 231 insertions(+), 168 deletions(-)
+$ git reset --hard HEAD^
+HEAD is now at 12f81a13da6d Merge remote-tracking branch 'gpio/for-next'
+Merging ktest/for-next (62183dcac539 ktest: Set CLOSE_CONSOLE_SIGNAL in the kvm.conf)
+$ git merge ktest/for-next
+Already up-to-date.
+Merging signal/for-next (20b4fb485227 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs)
+$ git merge signal/for-next
+Already up-to-date.
+Merging clk/clk-next (31c2c4b8e911 clk: bcm281xx: don't use unnamed structs or unions)
+$ git merge clk/clk-next
+Merge made by the 'recursive' strategy.
+ drivers/clk/bcm/clk-kona-setup.c | 33 +++++++++++----------
+ drivers/clk/bcm/clk-kona.c       | 64 +++++++++++++++++++++-------------------
+ drivers/clk/bcm/clk-kona.h       | 28 +++++++++---------
+ 3 files changed, 64 insertions(+), 61 deletions(-)
+Merging random/dev (7b878d4b48c4 random: Add arch_has_random[_seed]())
+$ git merge random/dev
+Already up-to-date.
+Merging lzo-update/lzo-update (42b775abafaf lib/lzo: huge LZO decompression speedup on ARM by using unaligned access)
+$ git merge lzo-update/lzo-update
+Merge made by the 'recursive' strategy.
+ lib/lzo/lzo1x_decompress_safe.c | 4 ++++
+ lib/lzo/lzodefs.h               | 6 ++++++
+ 2 files changed, 10 insertions(+)
+Merging arm64-hugepages/for-next/hugepages (af07484863e0 ARM64: mm: THP support.)
+$ git merge arm64-hugepages/for-next/hugepages
+Already up-to-date.
+Merging aio/master (e02ba72aabfa aio: block io_destroy() until all context requests are completed)
+$ git merge aio/master
+Merge made by the 'recursive' strategy.
+ fs/aio.c | 36 ++++++++++++++++++++++++++++++++----
+ 1 file changed, 32 insertions(+), 4 deletions(-)
+Merging llvmlinux/for-next (40e9963e622c Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip)
+$ git merge llvmlinux/for-next
+Already up-to-date.
+Merging powernv-cpuidle/powernv-cpuidle (0888839c5b62 cpuidle/powernv: Parse device tree to setup idle states)
+$ git merge powernv-cpuidle/powernv-cpuidle
+Already up-to-date.
+Merging rd-docs/master (596d80c7ceb6 The sample wrapper currently fails on some Java 7 .class files.  This updates the wrapper to properly handle those files.)
+$ git merge rd-docs/master
+Merge made by the 'recursive' strategy.
+ Documentation/email-clients.txt | 15 +++++----------
+ Documentation/java.txt          |  8 ++++++++
+ 2 files changed, 13 insertions(+), 10 deletions(-)
+Merging akpm-current/current (7b5f689823ab lib/scatterlist: clean up useless architecture versions of scatterlist.h)
+$ git merge --no-ff akpm-current/current
+Auto-merging lib/Kconfig.debug
+Auto-merging init/Kconfig
+Auto-merging drivers/leds/Kconfig
+Removing arch/x86/include/asm/scatterlist.h
+Auto-merging arch/x86/Kconfig
+Removing arch/sparc/include/asm/scatterlist.h
+Removing arch/score/include/asm/scatterlist.h
+Removing arch/s390/include/asm/scatterlist.h
+Auto-merging arch/s390/Kconfig
+Removing arch/powerpc/include/asm/scatterlist.h
+Removing arch/mn10300/include/asm/scatterlist.h
+Removing arch/microblaze/include/asm/scatterlist.h
+Removing arch/m32r/include/asm/scatterlist.h
+Removing arch/ia64/include/asm/scatterlist.h
+Removing arch/frv/include/asm/scatterlist.h
+Removing arch/cris/include/asm/scatterlist.h
+Removing arch/arm/include/asm/scatterlist.h
+Removing arch/alpha/include/asm/scatterlist.h
+Auto-merging MAINTAINERS
+Auto-merging Documentation/kernel-parameters.txt
+Merge made by the 'recursive' strategy.
+ CREDITS                                            |   7 +
+ Documentation/SubmittingPatches                    |  22 +-
+ .../devicetree/bindings/rtc/xgene-rtc.txt          |  28 ++
+ Documentation/filesystems/vfat.txt                 |  10 +
+ Documentation/kernel-parameters.txt                |   4 +
+ Documentation/leds/leds-class.txt                  |   3 -
+ Documentation/printk-formats.txt                   |   6 +
+ MAINTAINERS                                        |   5 +-
+ arch/alpha/include/asm/Kbuild                      |   1 +
+ arch/alpha/include/asm/scatterlist.h               |   6 -
+ arch/arm/Kconfig                                   |   1 +
+ arch/arm/include/asm/Kbuild                        |   1 +
+ arch/arm/include/asm/fixmap.h                      |  29 +-
+ arch/arm/include/asm/scatterlist.h                 |  12 -
+ arch/arm/mm/init.c                                 |   2 +-
+ arch/arm64/Kconfig                                 |   1 +
+ arch/arm64/boot/dts/apm-storm.dtsi                 |  21 ++
+ arch/cris/include/asm/Kbuild                       |   1 +
+ arch/cris/include/asm/scatterlist.h                |   6 -
+ arch/frv/include/asm/Kbuild                        |   1 +
+ arch/frv/include/asm/scatterlist.h                 |   6 -
+ arch/ia64/Kconfig                                  |   1 +
+ arch/ia64/include/asm/Kbuild                       |   1 +
+ arch/ia64/include/asm/scatterlist.h                |   7 -
+ arch/m32r/include/asm/Kbuild                       |   1 +
+ arch/m32r/include/asm/scatterlist.h                |   6 -
+ arch/m68k/include/asm/signal.h                     |   9 -
+ arch/microblaze/include/asm/Kbuild                 |   1 +
+ arch/microblaze/include/asm/scatterlist.h          |   1 -
+ arch/mips/mm/cache.c                               |   4 +-
+ arch/mn10300/include/asm/Kbuild                    |   1 +
+ arch/mn10300/include/asm/scatterlist.h             |  16 -
+ arch/powerpc/Kconfig                               |   1 +
+ arch/powerpc/include/asm/Kbuild                    |   1 +
+ arch/powerpc/include/asm/pgtable.h                 |  11 +
+ arch/powerpc/include/asm/scatterlist.h             |  17 -
+ arch/powerpc/mm/dma-noncoherent.c                  |   1 +
+ arch/powerpc/mm/subpage-prot.c                     |   6 +-
+ arch/powerpc/platforms/44x/warp.c                  |   1 +
+ arch/powerpc/platforms/52xx/efika.c                |   1 +
+ arch/powerpc/platforms/amigaone/setup.c            |   1 +
+ arch/s390/Kconfig                                  |   1 +
+ arch/s390/include/asm/Kbuild                       |   1 +
+ arch/s390/include/asm/scatterlist.h                |   3 -
+ arch/score/include/asm/Kbuild                      |   1 +
+ arch/score/include/asm/scatterlist.h               |   6 -
+ arch/sparc/Kconfig                                 |   1 +
+ arch/sparc/include/asm/Kbuild                      |   1 +
+ arch/sparc/include/asm/scatterlist.h               |   8 -
+ arch/um/include/asm/Kbuild                         |   1 +
+ arch/x86/Kconfig                                   |   3 +-
+ arch/x86/include/asm/Kbuild                        |   3 +-
+ arch/x86/include/asm/pgtable.h                     |  14 +-
+ arch/x86/include/asm/pgtable_64.h                  |   8 +
+ arch/x86/include/asm/pgtable_types.h               |  66 ++--
+ arch/x86/include/asm/scatterlist.h                 |   8 -
+ arch/x86/include/asm/signal.h                      |   6 -
+ arch/x86/mm/pageattr-test.c                        |   2 +-
+ block/genhd.c                                      |   2 +-
+ drivers/input/Kconfig                              |   9 +
+ drivers/input/Makefile                             |   3 +
+ drivers/input/input.c                              |   6 +
+ drivers/input/leds.c                               | 249 ++++++++++++++
+ drivers/input/misc/da9055_onkey.c                  |   1 -
+ drivers/leds/Kconfig                               |   3 -
+ drivers/misc/ti-st/st_core.c                       |   2 +-
+ drivers/net/irda/donauboe.c                        |  15 +-
+ drivers/pps/pps.c                                  |  57 ++--
+ drivers/rtc/Kconfig                                |   9 +
+ drivers/rtc/Makefile                               |   1 +
+ drivers/rtc/interface.c                            |  15 +-
+ drivers/rtc/rtc-xgene.c                            | 278 +++++++++++++++
+ drivers/tty/Kconfig                                |   4 +
+ drivers/tty/vt/keyboard.c                          | 110 ++++--
+ drivers/video/backlight/backlight.c                |   2 -
+ fs/befs/linuxvfs.c                                 |   5 +-
+ fs/binfmt_elf.c                                    |  21 +-
+ fs/fat/cache.c                                     |  70 +++-
+ fs/fat/fat.h                                       |   6 +-
+ fs/fat/file.c                                      |  78 ++++-
+ fs/fat/inode.c                                     |  87 ++++-
+ fs/hfsplus/catalog.c                               |  89 +++--
+ fs/hfsplus/dir.c                                   |  11 +-
+ fs/hfsplus/hfsplus_fs.h                            |   4 +-
+ fs/hfsplus/super.c                                 |   4 +-
+ fs/jffs2/background.c                              |  12 +-
+ fs/mpage.c                                         |  23 +-
+ fs/ntfs/compress.c                                 |   2 +-
+ fs/ntfs/super.c                                    |   4 +-
+ fs/ntfs/sysctl.c                                   |   2 +-
+ fs/ocfs2/cluster/tcp.c                             |  33 +-
+ fs/ocfs2/dlm/dlmdebug.c                            |   2 +-
+ fs/ocfs2/dlm/dlmlock.c                             |   2 +-
+ fs/ocfs2/dlm/dlmmaster.c                           |  20 +-
+ fs/ocfs2/namei.c                                   | 123 ++++++-
+ fs/ocfs2/stackglue.c                               |   2 +-
+ fs/ocfs2/super.c                                   |   8 +-
+ fs/ocfs2/uptodate.c                                |   2 +-
+ fs/proc/task_mmu.c                                 | 287 +++++++---------
+ include/asm-generic/pgtable.h                      |  35 +-
+ include/linux/crc64_ecma.h                         |  56 +++
+ include/linux/gfp.h                                |  10 +-
+ include/linux/hugetlb.h                            |   7 -
+ include/linux/hugetlb_inline.h                     |   7 +
+ include/linux/input.h                              |  21 ++
+ include/linux/memcontrol.h                         |  17 +-
+ include/linux/mm.h                                 |  24 +-
+ include/linux/pagemap.h                            |  28 ++
+ include/linux/scatterlist.h                        |   2 +-
+ include/linux/sched.h                              |   3 -
+ include/linux/signal.h                             |  21 +-
+ include/linux/slab.h                               |  11 +-
+ include/linux/string.h                             |   1 +
+ include/linux/swapops.h                            |   2 +-
+ include/linux/thread_info.h                        |   2 -
+ include/linux/vm_event_item.h                      |   4 +
+ include/linux/vmstat.h                             |   6 +
+ include/linux/wait.h                               |  14 +-
+ include/scsi/scsi.h                                |   2 +-
+ include/trace/events/gfpflags.h                    |   1 -
+ init/Kconfig                                       |  24 +-
+ init/main.c                                        |  72 +++-
+ ipc/msg.c                                          |   9 +-
+ ipc/sem.c                                          |  10 +-
+ ipc/shm.c                                          |  10 +-
+ ipc/util.c                                         |   8 +-
+ ipc/util.h                                         |   2 +-
+ kernel/exit.c                                      |  39 ---
+ kernel/fork.c                                      |   6 +-
+ kernel/kmod.c                                      |   5 +-
+ kernel/signal.c                                    |  90 +++--
+ kernel/time/sched_clock.c                          |   4 +
+ kernel/watchdog.c                                  |  10 +-
+ lib/Kconfig                                        |  14 +
+ lib/Kconfig.debug                                  |  13 +-
+ lib/Makefile                                       |   1 +
+ lib/crc64_ecma.c                                   | 341 +++++++++++++++++++
+ lib/scatterlist.c                                  |   4 +-
+ lib/string.c                                       |   8 +-
+ lib/vsprintf.c                                     |  20 +-
+ lib/xz/Kconfig                                     |  24 +-
+ mm/compaction.c                                    |  17 +-
+ mm/fremap.c                                        |   7 +-
+ mm/huge_memory.c                                   |   2 +-
+ mm/hugetlb.c                                       |   2 +
+ mm/memcontrol.c                                    |  86 ++---
+ mm/memory-failure.c                                |   6 +-
+ mm/memory.c                                        |  25 +-
+ mm/mempolicy.c                                     | 259 ++++++--------
+ mm/page_alloc.c                                    |  56 +--
+ mm/pagewalk.c                                      | 375 +++++++++++++--------
+ mm/rmap.c                                          |  14 +-
+ mm/slab.c                                          |   7 +-
+ mm/slab.h                                          |  29 ++
+ mm/slab_common.c                                   |  19 +-
+ mm/slub.c                                          |  30 +-
+ mm/util.c                                          |  30 ++
+ mm/vmacache.c                                      |  19 +-
+ mm/vmscan.c                                        |  68 ++--
+ mm/vmstat.c                                        |   4 +
+ scripts/checkpatch.pl                              |  40 ++-
+ usr/Kconfig                                        |  77 -----
+ 162 files changed, 2942 insertions(+), 1275 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/rtc/xgene-rtc.txt
+ delete mode 100644 arch/alpha/include/asm/scatterlist.h
+ delete mode 100644 arch/arm/include/asm/scatterlist.h
+ delete mode 100644 arch/cris/include/asm/scatterlist.h
+ delete mode 100644 arch/frv/include/asm/scatterlist.h
+ delete mode 100644 arch/ia64/include/asm/scatterlist.h
+ delete mode 100644 arch/m32r/include/asm/scatterlist.h
+ delete mode 100644 arch/microblaze/include/asm/scatterlist.h
+ delete mode 100644 arch/mn10300/include/asm/scatterlist.h
+ delete mode 100644 arch/powerpc/include/asm/scatterlist.h
+ delete mode 100644 arch/s390/include/asm/scatterlist.h
+ delete mode 100644 arch/score/include/asm/scatterlist.h
+ delete mode 100644 arch/sparc/include/asm/scatterlist.h
+ delete mode 100644 arch/x86/include/asm/scatterlist.h
+ create mode 100644 drivers/input/leds.c
+ create mode 100644 drivers/rtc/rtc-xgene.c
+ create mode 100644 include/linux/crc64_ecma.h
+ create mode 100644 lib/crc64_ecma.c
+$ git am -3 ../patches/0001-Revert-x86-define-_PAGE_NUMA-by-reusing-software-bit.patch
+Applying: Revert "x86: define _PAGE_NUMA by reusing software bits on the PMD and PTE levels -fix"
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/powerpc/include/asm/pgtable.h
+$ git add -A .
+$ git commit -v -a --amend
+[master 02f07c3ccc07] Merge branch 'akpm-current/current'
+$ git am -3 ../patches/0002-Revert-x86-define-_PAGE_NUMA-by-reusing-software-bit.patch
+Applying: Revert "x86: define _PAGE_NUMA by reusing software bits on the PMD and PTE levels"
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/powerpc/include/asm/pgtable.h
+M	arch/x86/include/asm/pgtable.h
+M	arch/x86/include/asm/pgtable_64.h
+M	arch/x86/include/asm/pgtable_types.h
+M	arch/x86/mm/pageattr-test.c
+M	include/asm-generic/pgtable.h
+M	include/linux/swapops.h
+M	mm/memory.c
+$ git add -A .
+$ git commit -v -a --amend
+[master 50e056db0177] Merge branch 'akpm-current/current'
+$ git clone -s -l -n -q . ../rebase-tmp
+$ cd ../rebase-tmp
+$ git checkout -b akpm remotes/origin/akpm/master
+Switched to a new branch 'akpm'
+$ git rebase --onto master remotes/origin/akpm/master-base
+First, rewinding head to replay your work on top of it...
+Applying: drivers/gpio/gpio-zevio.c: fix build
+Applying: drivers/w1/w1_int.c: call put_device if device_register fails
+Applying: arm: move arm_dma_limit to setup_dma_zone
+Applying: ufs: sb mutex merge + mutex_destroy
+Applying: mm: add strictlimit knob
+$ cd ../next
+$ git fetch -f ../rebase-tmp akpm:akpm/master
+From ../rebase-tmp
+ + fa3cfb65368e...4c3d768413b4 akpm       -> akpm/master  (forced update)
+$ rm -rf ../rebase-tmp
+Merging akpm/master (4c3d768413b4 mm: add strictlimit knob)
+$ git merge --no-ff akpm/master
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-class-bdi |  8 +++++++
+ arch/arm/mm/init.c                        |  6 ++++--
+ arch/arm/mm/mm.h                          |  2 --
+ drivers/gpio/gpio-zevio.c                 |  4 ++++
+ drivers/w1/w1_int.c                       |  5 ++---
+ fs/ufs/balloc.c                           | 30 +++++++++++++-------------
+ fs/ufs/ialloc.c                           | 17 +++++++--------
+ fs/ufs/super.c                            | 28 +++++++++----------------
+ fs/ufs/ufs.h                              |  1 -
+ mm/backing-dev.c                          | 35 +++++++++++++++++++++++++++++++
+ 10 files changed, 86 insertions(+), 50 deletions(-)
diff --git a/Next/quilt-import.log b/Next/quilt-import.log
new file mode 100644
index 000000000000..55d907fe9732
--- /dev/null
+++ b/Next/quilt-import.log
@@ -0,0 +1,4 @@
+Importing jdelvare-hwmon based on 3.14
+Unchanged quilt series jdelvare-hwmon
+Importing rd-docs based on 3.14
+Unchanged quilt series rd-docs
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 96e54bed5088..e858aa0ad8af 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -6,4 +6,5 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff --git a/arch/alpha/include/asm/scatterlist.h b/arch/alpha/include/asm/scatterlist.h
deleted file mode 100644
index 017d7471c3c4..000000000000
--- a/arch/alpha/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ALPHA_SCATTERLIST_H
-#define _ALPHA_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(_ALPHA_SCATTERLIST_H) */
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index 291a70db68b8..781f57f25bd8 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -19,8 +19,6 @@
 #include <asm-generic/irq.h>
 
 extern void arc_init_IRQ(void);
-extern int get_hw_config_num_irq(void);
-
 void arc_local_timer_setup(unsigned int cpu);
 
 #endif
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index a4b141ee9a6a..7d653c0d0773 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -150,24 +150,6 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 	set_irq_regs(old_regs);
 }
 
-int get_hw_config_num_irq(void)
-{
-	uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR);
-
-	switch (val & 0x03) {
-	case 0:
-		return 16;
-	case 1:
-		return 32;
-	case 2:
-		return 8;
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
 /*
  * arch_local_irq_enable - Enable interrupts.
  *
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
index 89edf7961a2f..23c3832e6d9f 100644
--- a/arch/arc/mm/cache_arc700.c
+++ b/arch/arc/mm/cache_arc700.c
@@ -253,12 +253,16 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr,
 
 	if (cacheop == OP_INV_IC) {
 		aux_cmd = ARC_REG_IC_IVIL;
+#if (CONFIG_ARC_MMU_VER > 2)
 		aux_tag = ARC_REG_IC_PTAG;
+#endif
 	}
 	else {
 		/* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
 		aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
+#if (CONFIG_ARC_MMU_VER > 2)
 		aux_tag = ARC_REG_DC_PTAG;
+#endif
 	}
 
 	/* Ensure we properly floor/ceil the non-line aligned/sized requests
diff --git a/arch/arc/plat-arcfpga/Makefile b/arch/arc/plat-arcfpga/Makefile
index a44e22ebc1b7..4d1bddc34b5b 100644
--- a/arch/arc/plat-arcfpga/Makefile
+++ b/arch/arc/plat-arcfpga/Makefile
@@ -9,4 +9,4 @@
 KBUILD_CFLAGS	+= -Iarch/arc/plat-arcfpga/include
 
 obj-y := platform.o irq.o
-obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_ISS_SMP_EXTN)		+= smp.o
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
index 19b76b61f44b..213394a15cd2 100644
--- a/arch/arc/plat-arcfpga/platform.c
+++ b/arch/arc/plat-arcfpga/platform.c
@@ -169,7 +169,7 @@ static void __init plat_fpga_early_init(void)
 
 	arc_fpga_serial_init();
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_ISS_SMP_EXTN
 	iss_model_init_early_smp();
 #endif
 }
@@ -211,7 +211,7 @@ MACHINE_START(ANGEL4, "angel4")
 	.init_early	= plat_fpga_early_init,
 	.init_machine	= plat_fpga_populate_dev,
 	.init_irq	= plat_fpga_init_IRQ,
-#ifdef CONFIG_SMP
+#ifdef CONFIG_ISS_SMP_EXTN
 	.init_smp	= iss_model_init_smp,
 #endif
 MACHINE_END
diff --git a/arch/arc/plat-arcfpga/smp.c b/arch/arc/plat-arcfpga/smp.c
index 8a12741f5f7a..92bad9122077 100644
--- a/arch/arc/plat-arcfpga/smp.c
+++ b/arch/arc/plat-arcfpga/smp.c
@@ -42,6 +42,24 @@ static void iss_model_smp_wakeup_cpu(int cpu, unsigned long pc)
 
 }
 
+static inline int get_hw_config_num_irq(void)
+{
+	uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR);
+
+	switch (val & 0x03) {
+	case 0:
+		return 16;
+	case 1:
+		return 32;
+	case 2:
+		return 8;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
 /*
  * Any SMP specific init any CPU does when it comes up.
  * Here we setup the CPU to enable Inter-Processor-Interrupts
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ab438cb5af55..8e9286af440a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -83,6 +83,7 @@ config ARM
 	  <http://www.arm.linux.org.uk/>.
 
 config ARM_HAS_SG_CHAIN
+	select ARCH_HAS_SG_CHAIN
 	bool
 
 config NEED_SG_DMA_LENGTH
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 4a2fc0bf6fc9..7289853ab6fb 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -942,6 +942,15 @@ config DEBUG_IMX_UART_PORT
 	  Choose UART port on which kernel low-level debug messages
 	  should be output.
 
+config DEBUG_VF_UART_PORT
+	int "Vybrid Debug UART Port Selection" if DEBUG_VF_UART
+	default 1
+	range 0 3
+	depends on SOC_VF610
+	help
+	  Choose UART port on which kernel low-level debug messages
+	  should be output.
+
 config DEBUG_TEGRA_UART
 	bool
 	depends on ARCH_TEGRA
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 35c146f31e46..145699cb3819 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -57,7 +57,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
 dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb
 dtb-$(CONFIG_ARCH_BERLIN) += \
 	berlin2-sony-nsz-gs7.dtb	\
-	berlin2cd-google-chromecast.dtb
+	berlin2cd-google-chromecast.dtb	\
+	berlin2q-marvell-dmp.dtb
 dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
 	da850-evm.dtb
 dtb-$(CONFIG_ARCH_EFM32) += efm32gg-dk3750.dtb
@@ -143,10 +144,12 @@ kirkwood := \
 	kirkwood-ts419-6281.dtb \
 	kirkwood-ts419-6282.dtb
 dtb-$(CONFIG_ARCH_KIRKWOOD) += $(kirkwood)
-dtb-$(CONFIG_MACH_KIRKWOOD) += $(kirkwood)
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
 dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
+dtb-$(CONFIG_ARCH_MSM) += qcom-msm8660-surf.dtb \
+	qcom-msm8960-cdp.dtb \
+	qcom-apq8074-dragonboard.dtb
 dtb-$(CONFIG_ARCH_MXC) += \
 	imx25-eukrea-mbimxsd25-baseboard.dtb \
 	imx25-karo-tx25.dtb \
@@ -158,10 +161,12 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx27-phytec-phycard-s-rdk.dtb \
 	imx31-bug.dtb \
 	imx35-eukrea-mbimxsd35-baseboard.dtb \
+	imx35-pdk.dtb \
 	imx50-evk.dtb \
 	imx51-apf51.dtb \
 	imx51-apf51dev.dtb \
 	imx51-babbage.dtb \
+	imx51-digi-connectcore-jsk.dtb \
 	imx51-eukrea-mbimxsd51-baseboard.dtb \
 	imx53-ard.dtb \
 	imx53-m53evk.dtb \
@@ -204,6 +209,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
 	imx6q-udoo.dtb \
 	imx6q-wandboard.dtb \
 	imx6sl-evk.dtb \
+	vf610-colibri.dtb \
 	vf610-cosmic.dtb \
 	vf610-twr.dtb
 dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
@@ -304,8 +310,7 @@ dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
 dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
 dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \
 	s3c6410-smdk6410.dtb
-dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += emev2-kzm9d.dtb \
-	r7s72100-genmai.dtb \
+dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += r7s72100-genmai.dtb \
 	r7s72100-genmai-reference.dtb \
 	r8a7740-armadillo800eva.dtb \
 	r8a7778-bockw.dtb \
@@ -368,6 +373,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
 	tegra30-cardhu-a02.dtb \
 	tegra30-cardhu-a04.dtb \
 	tegra114-dalmore.dtb \
+	tegra124-jetson-tk1.dtb \
 	tegra124-venice2.dtb
 dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \
 	versatile-pb.dtb
@@ -408,6 +414,7 @@ dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
 	dove-d2plug.dtb \
 	dove-d3plug.dtb \
 	dove-dove-db.dtb
+dtb-$(CONFIG_MACH_KIRKWOOD) += $(kirkwood)
 
 targets += dtbs dtbs_install
 targets += $(dtb-y)
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index bbb40f62037d..bb77970c0b12 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -230,6 +230,7 @@
 				#size-cells = <0>;
 				compatible = "marvell,orion-mdio";
 				reg = <0x72004 0x4>;
+				clocks = <&gateclk 4>;
 			};
 
 			eth1: ethernet@74000 {
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index a064f59da02d..ca8813bb99ba 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -336,6 +336,7 @@
 				#size-cells = <0>;
 				compatible = "marvell,orion-mdio";
 				reg = <0x72004 0x4>;
+				clocks = <&gateclk 4>;
 			};
 
 			coredivclk: clock@e4250 {
diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi
index 56a1af2f1052..4d85312dc17a 100644
--- a/arch/arm/boot/dts/berlin2.dtsi
+++ b/arch/arm/boot/dts/berlin2.dtsi
@@ -72,6 +72,11 @@
 			cache-level = <2>;
 		};
 
+		scu: snoop-control-unit@ad0000 {
+			compatible = "arm,cortex-a9-scu";
+			reg = <0xad0000 0x58>;
+		};
+
 		gic: interrupt-controller@ad1000 {
 			compatible = "arm,cortex-a9-gic";
 			reg = <0xad1000 0x1000>, <0xad0100 0x0100>;
@@ -176,6 +181,11 @@
 			};
 		};
 
+		generic-regs@ea0184 {
+			compatible = "marvell,berlin-generic-regs", "syscon";
+			reg = <0xea0184 0x10>;
+		};
+
 		apb@fc0000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
new file mode 100644
index 000000000000..2da9c41e29d8
--- /dev/null
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 Antoine Ténart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+#include "berlin2q.dtsi"
+
+/ {
+	model = "Marvell BG2-Q DMP";
+	compatible = "marvell,berlin2q-dmp", "marvell,berlin2q", "marvell,berlin";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000>;
+	};
+
+	choosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
new file mode 100644
index 000000000000..52c7d644e492
--- /dev/null
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2014 Antoine Ténart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
+
+/ {
+	model = "Marvell Armada 1500 pro (BG2-Q) SoC";
+	compatible = "marvell,berlin2q", "marvell,berlin";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			next-level-cache = <&l2>;
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			next-level-cache = <&l2>;
+			reg = <1>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			next-level-cache = <&l2>;
+			reg = <2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			next-level-cache = <&l2>;
+			reg = <3>;
+		};
+	};
+
+	smclk: sysmgr-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+
+	cfgclk: config-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+	};
+
+	cpuclk: cpu-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1200000000>;
+	};
+
+	twdclk: twdclk {
+		compatible = "fixed-factor-clock";
+		#clock-cells = <0>;
+		clocks = <&cpuclk>;
+		clock-mult = <1>;
+		clock-div = <3>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ranges = <0 0xf7000000 0x1000000>;
+		interrupt-parent = <&gic>;
+
+		l2: l2-cache-controller@ac0000 {
+			compatible = "arm,pl310-cache";
+			reg = <0xac0000 0x1000>;
+			cache-level = <2>;
+		};
+
+		scu: snoop-control-unit@ad0000 {
+			compatible = "arm,cortex-a9-scu";
+			reg = <0xad0000 0x58>;
+		};
+
+		local-timer@ad0600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0xad0600 0x20>;
+			clocks = <&twdclk>;
+			interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		gic: interrupt-controller@ad1000 {
+			compatible = "arm,cortex-a9-gic";
+			reg = <0xad1000 0x1000>, <0xad0100 0x100>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		apb@e80000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			ranges = <0 0xe80000 0x10000>;
+			interrupt-parent = <&aic>;
+
+			gpio0: gpio@0400 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x0400 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				porta: gpio-port@0 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					snps,nr-gpios = <32>;
+					reg = <0>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					interrupts = <0>;
+				};
+			};
+
+			gpio1: gpio@0800 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x0800 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				portb: gpio-port@1 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					snps,nr-gpios = <32>;
+					reg = <0>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					interrupts = <1>;
+				};
+			};
+
+			gpio2: gpio@0c00 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x0c00 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				portc: gpio-port@2 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					snps,nr-gpios = <32>;
+					reg = <0>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					interrupts = <2>;
+				};
+			};
+
+			gpio3: gpio@1000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x1000 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				portd: gpio-port@3 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					snps,nr-gpios = <32>;
+					reg = <0>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					interrupts = <3>;
+				};
+			};
+
+			timer0: timer@2c00 {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c00 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				interrupts = <8>;
+			};
+
+			timer1: timer@2c14 {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c14 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				status = "disabled";
+			};
+
+			timer2: timer@2c28 {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c28 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				status = "disabled";
+			};
+
+			timer3: timer@2c3c {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c3c 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				status = "disabled";
+			};
+
+			timer4: timer@2c50 {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c50 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				status = "disabled";
+			};
+
+			timer5: timer@2c64 {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c64 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				status = "disabled";
+			};
+
+			timer6: timer@2c78 {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c78 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				status = "disabled";
+			};
+
+			timer7: timer@2c8c {
+				compatible = "snps,dw-apb-timer";
+				reg = <0x2c8c 0x14>;
+				clocks = <&cfgclk>;
+				clock-names = "timer";
+				status = "disabled";
+			};
+
+			aic: interrupt-controller@3800 {
+				compatible = "snps,dw-apb-ictl";
+				reg = <0x3800 0x30>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			gpio4: gpio@5000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x5000 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				porte: gpio-port@4 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					snps,nr-gpios = <32>;
+					reg = <0>;
+				};
+			};
+
+			gpio5: gpio@c000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0xc000 0x400>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				portf: gpio-port@5 {
+					compatible = "snps,dw-apb-gpio-port";
+					gpio-controller;
+					#gpio-cells = <2>;
+					snps,nr-gpios = <32>;
+					reg = <0>;
+				};
+			};
+		};
+
+		generic-regs@ea0110 {
+			compatible = "marvell,berlin-generic-regs", "syscon";
+			reg = <0xea0110 0x10>;
+		};
+
+		apb@fc0000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			ranges = <0 0xfc0000 0x10000>;
+			interrupt-parent = <&sic>;
+
+			uart0: uart@9000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x9000 0x100>;
+				interrupt-parent = <&sic>;
+				interrupts = <8>;
+				clocks = <&smclk>;
+				reg-shift = <2>;
+				status = "disabled";
+			};
+
+			uart1: uart@a000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0xa000 0x100>;
+				interrupt-parent = <&sic>;
+				interrupts = <9>;
+				clocks = <&smclk>;
+				reg-shift = <2>;
+				status = "disabled";
+			};
+
+			sic: interrupt-controller@e000 {
+				compatible = "snps,dw-apb-ictl";
+				reg = <0xe000 0x30>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
index 62fb3da50bdb..ad12da38fc92 100644
--- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
@@ -172,3 +172,16 @@
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
+
+&usbhost1 {
+	phy_type = "serial";
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbotg {
+	phy_type = "utmi";
+	dr_mode = "otg";
+	external-vbus-divider;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts
index f607ce520eda..c608942b8a3b 100644
--- a/arch/arm/boot/dts/imx25-pdk.dts
+++ b/arch/arm/boot/dts/imx25-pdk.dts
@@ -10,6 +10,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/input/input.h>
 #include "imx25.dtsi"
 
 / {
@@ -19,18 +20,232 @@
 	memory {
 		reg = <0x80000000 0x4000000>;
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_fec_3v3: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "fec-3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio2 3 0>;
+			enable-active-high;
+		};
+
+		reg_2p5v: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+		};
+
+		reg_3p3v: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+		};
+
+		reg_can_3v3: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "can-3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio4 6 0>;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx25-pdk-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx25-pdk-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <4>;
+	};
 };
 
-&uart1 {
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1>;
+	xceiver-supply = <&reg_can_3v3>;
+	status = "okay";
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	cd-gpios = <&gpio2 1 0>;
+	wp-gpios = <&gpio2 0 0>;
 	status = "okay";
 };
 
 &fec {
 	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	phy-supply = <&reg_fec_3v3>;
+	phy-reset-gpios = <&gpio4 8 0>;
 	status = "okay";
 };
 
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 129>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
+&iomuxc {
+	imx25-pdk {
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX25_PAD_RW__AUD4_TXFS			0xe0
+				MX25_PAD_OE__AUD4_TXC			0xe0
+				MX25_PAD_EB0__AUD4_TXD			0xe0
+				MX25_PAD_EB1__AUD4_RXD			0xe0
+			>;
+		};
+
+		pinctrl_can1: can1grp {
+			fsl,pins = <
+				MX25_PAD_GPIO_A__CAN1_TX		0x0
+				MX25_PAD_GPIO_B__CAN1_RX		0x0
+				MX25_PAD_D14__GPIO_4_6 			0x80000000
+			>;
+		};
+
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX25_PAD_SD1_CMD__SD1_CMD		0x80000000
+				MX25_PAD_SD1_CLK__SD1_CLK		0x80000000
+				MX25_PAD_SD1_DATA0__SD1_DATA0		0x80000000
+				MX25_PAD_SD1_DATA1__SD1_DATA1		0x80000000
+				MX25_PAD_SD1_DATA2__SD1_DATA2		0x80000000
+				MX25_PAD_SD1_DATA3__SD1_DATA3		0x80000000
+				MX25_PAD_A14__GPIO_2_0			0x80000000
+				MX25_PAD_A15__GPIO_2_1			0x80000000
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX25_PAD_FEC_MDC__FEC_MDC		0x80000000
+				MX25_PAD_FEC_MDIO__FEC_MDIO		0x400001e0
+				MX25_PAD_FEC_TDATA0__FEC_TDATA0		0x80000000
+				MX25_PAD_FEC_TDATA1__FEC_TDATA1		0x80000000
+				MX25_PAD_FEC_TX_EN__FEC_TX_EN		0x80000000
+				MX25_PAD_FEC_RDATA0__FEC_RDATA0		0x80000000
+				MX25_PAD_FEC_RDATA1__FEC_RDATA1		0x80000000
+				MX25_PAD_FEC_RX_DV__FEC_RX_DV		0x80000000
+				MX25_PAD_FEC_TX_CLK__FEC_TX_CLK		0x1c0
+				MX25_PAD_A17__GPIO_2_3			0x80000000
+				MX25_PAD_D12__GPIO_4_8			0x80000000
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX25_PAD_I2C1_CLK__I2C1_CLK		0x80000000
+				MX25_PAD_I2C1_DAT__I2C1_DAT		0x80000000
+			>;
+		};
+
+		pinctrl_kpp: kppgrp {
+			fsl,pins = <
+				MX25_PAD_KPP_ROW0__KPP_ROW0	0x80000000
+				MX25_PAD_KPP_ROW1__KPP_ROW1	0x80000000
+				MX25_PAD_KPP_ROW2__KPP_ROW2	0x80000000
+				MX25_PAD_KPP_ROW3__KPP_ROW3	0x80000000
+				MX25_PAD_KPP_COL0__KPP_COL0	0x80000000
+				MX25_PAD_KPP_COL1__KPP_COL1	0x80000000
+				MX25_PAD_KPP_COL2__KPP_COL2	0x80000000
+				MX25_PAD_KPP_COL3__KPP_COL3	0x80000000
+			>;
+		};
+
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX25_PAD_UART1_RTS__UART1_RTS		0xe0
+				MX25_PAD_UART1_CTS__UART1_CTS		0xe0
+				MX25_PAD_UART1_TXD__UART1_TXD		0x80000000
+				MX25_PAD_UART1_RXD__UART1_RXD		0xc0
+			>;
+		};
+	};
+};
+
 &nfc {
 	nand-on-flash-bbt;
 	status = "okay";
 };
+
+&kpp {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_kpp>;
+	linux,keymap = <
+			MATRIX_KEY(0x0, 0x0, KEY_UP)
+			MATRIX_KEY(0x0, 0x1, KEY_DOWN)
+			MATRIX_KEY(0x0, 0x2, KEY_VOLUMEDOWN)
+			MATRIX_KEY(0x0, 0x3, KEY_HOME)
+			MATRIX_KEY(0x1, 0x0, KEY_RIGHT)
+			MATRIX_KEY(0x1, 0x1, KEY_LEFT)
+			MATRIX_KEY(0x1, 0x2, KEY_ENTER)
+			MATRIX_KEY(0x1, 0x3, KEY_VOLUMEUP)
+			MATRIX_KEY(0x2, 0x0, KEY_F6)
+			MATRIX_KEY(0x2, 0x1, KEY_F8)
+			MATRIX_KEY(0x2, 0x2, KEY_F9)
+			MATRIX_KEY(0x2, 0x3, KEY_F10)
+			MATRIX_KEY(0x3, 0x0, KEY_F1)
+			MATRIX_KEY(0x3, 0x1, KEY_F2)
+			MATRIX_KEY(0x3, 0x2, KEY_F3)
+			MATRIX_KEY(0x3, 0x2, KEY_POWER)
+	>;
+	status = "okay";
+};
+
+&ssi1 {
+	codec-handle = <&codec>;
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usbhost1 {
+	phy_type = "serial";
+	dr_mode = "host";
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
index 32f760e24898..563e168c88a0 100644
--- a/arch/arm/boot/dts/imx25.dtsi
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -14,6 +14,7 @@
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -56,6 +57,7 @@
 
 		osc {
 			compatible = "fsl,imx-osc", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24000000>;
 		};
 	};
@@ -164,9 +166,10 @@
 				status = "disabled";
 			};
 
-			kpp@43fa8000 {
+			kpp: kpp@43fa8000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
+				compatible = "fsl,imx25-kpp", "fsl,imx21-kpp";
 				reg = <0x43fa8000 0x4000>;
 				clocks = <&clks 102>;
 				clock-names = "";
@@ -481,23 +484,13 @@
 				clocks = <&clks 99>;
 			};
 
-			usbphy1: usbphy@1 {
-				compatible = "nop-usbphy";
-				status = "disabled";
-			};
-
-			usbphy2: usbphy@2 {
-				compatible = "nop-usbphy";
-				status = "disabled";
-			};
-
 			usbotg: usb@53ff4000 {
 				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
 				reg = <0x53ff4000 0x0200>;
 				interrupts = <37>;
-				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
-				clock-names = "ipg", "ahb", "per";
+				clocks = <&clks 70>;
 				fsl,usbmisc = <&usbmisc 0>;
+				fsl,usbphy = <&usbphy0>;
 				status = "disabled";
 			};
 
@@ -505,9 +498,9 @@
 				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
 				reg = <0x53ff4400 0x0200>;
 				interrupts = <35>;
-				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
-				clock-names = "ipg", "ahb", "per";
+				clocks = <&clks 70>;
 				fsl,usbmisc = <&usbmisc 1>;
+				fsl,usbphy = <&usbphy1>;
 				status = "disabled";
 			};
 
@@ -517,7 +510,6 @@
 				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
 				clock-names = "ipg", "ahb", "per";
 				reg = <0x53ff4600 0x00f>;
-				status = "disabled";
 			};
 
 			dryice@53ffc000 {
@@ -549,4 +541,20 @@
 			};
 		};
 	};
+
+	usbphy {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usbphy0: usb-phy@0 {
+			reg = <0>;
+			compatible = "usb-nop-xceiv";
+		};
+
+		usbphy1: usb-phy@1 {
+			reg = <1>;
+			compatible = "usb-nop-xceiv";
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
index 09f57b39e3ef..73aae4f5e539 100644
--- a/arch/arm/boot/dts/imx27-apf27.dts
+++ b/arch/arm/boot/dts/imx27-apf27.dts
@@ -29,6 +29,7 @@
 
 		osc26m {
 			compatible = "fsl,imx-osc26m", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <0>;
 		};
 	};
diff --git a/arch/arm/boot/dts/imx27-pdk.dts b/arch/arm/boot/dts/imx27-pdk.dts
index 5ce89aa275df..430b72b5bdb8 100644
--- a/arch/arm/boot/dts/imx27-pdk.dts
+++ b/arch/arm/boot/dts/imx27-pdk.dts
@@ -17,15 +17,57 @@
 	compatible = "fsl,imx27-pdk", "fsl,imx27";
 
 	memory {
-		reg = <0x0 0x0>;
+		reg = <0xa0000000 0x08000000>;
 	};
 };
 
+
+&fec {
+	phy-mode = "mii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	status = "okay";
+};
+
 &uart1 {
 	fsl,uart-has-rtscts;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
 	status = "okay";
 };
 
-&fec {
-	status = "okay";
+&iomuxc {
+	imx27-pdk {
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX27_PAD_SD3_CMD__FEC_TXD0 0x0
+				MX27_PAD_SD3_CLK__FEC_TXD1 0x0
+				MX27_PAD_ATA_DATA0__FEC_TXD2 0x0
+				MX27_PAD_ATA_DATA1__FEC_TXD3 0x0
+				MX27_PAD_ATA_DATA2__FEC_RX_ER 0x0
+				MX27_PAD_ATA_DATA3__FEC_RXD1 0x0
+				MX27_PAD_ATA_DATA4__FEC_RXD2 0x0
+				MX27_PAD_ATA_DATA5__FEC_RXD3 0x0
+				MX27_PAD_ATA_DATA6__FEC_MDIO 0x0
+				MX27_PAD_ATA_DATA7__FEC_MDC 0x0
+				MX27_PAD_ATA_DATA8__FEC_CRS 0x0
+				MX27_PAD_ATA_DATA9__FEC_TX_CLK 0x0
+				MX27_PAD_ATA_DATA10__FEC_RXD0 0x0
+				MX27_PAD_ATA_DATA11__FEC_RX_DV 0x0
+				MX27_PAD_ATA_DATA12__FEC_RX_CLK 0x0
+				MX27_PAD_ATA_DATA13__FEC_COL 0x0
+				MX27_PAD_ATA_DATA14__FEC_TX_ER 0x0
+				MX27_PAD_ATA_DATA15__FEC_TX_EN 0x0
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX27_PAD_UART1_TXD__UART1_TXD 0x0
+				MX27_PAD_UART1_RXD__UART1_RXD 0x0
+				MX27_PAD_UART1_CTS__UART1_CTS 0x0
+				MX27_PAD_UART1_RTS__UART1_RTS 0x0
+			>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
index df3b2e731835..8b4181b72596 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
@@ -12,14 +12,51 @@
 / {
 	model = "Phytec pcm970";
 	compatible = "phytec,imx27-pcm970", "phytec,imx27-pcm038", "fsl,imx27";
+
+	display0: LQ035Q7 {
+		model = "Sharp-LQ035Q7";
+		native-mode = <&timing0>;
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xf00080c0>;
+
+		display-timings {
+			timing0: 240x320 {
+				clock-frequency = <5500000>;
+				hactive = <240>;
+				vactive = <320>;
+				hback-porch = <5>;
+				hsync-len = <7>;
+				hfront-porch = <16>;
+				vback-porch = <7>;
+				vsync-len = <1>;
+				vfront-porch = <9>;
+				pixelclk-active = <1>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+				de-active = <0>;
+			};
+		};
+	};
 };
 
 &cspi1 {
+	pinctrl-0 = <&pinctrl_cspi1>, <&pinctrl_cspi1cs1>;
 	fsl,spi-num-chipselects = <2>;
 	cs-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>,
 		   <&gpio4 27 GPIO_ACTIVE_LOW>;
 };
 
+&fb {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_imxfb1>;
+	display = <&display0>;
+	lcd-supply = <&reg_5v0>;
+	fsl,dmacr = <0x00020010>;
+	fsl,lscr1 = <0x00120300>;
+	fsl,lpccr = <0x00a903ff>;
+	status = "okay";
+};
+
 &i2c1 {
 	clock-frequency = <400000>;
 	pinctrl-names = "default";
@@ -36,6 +73,44 @@
 
 &iomuxc {
 	imx27_phycore_rdk {
+		pinctrl_cspi1cs1: cspi1cs1grp {
+			fsl,pins = <
+				MX27_PAD_CSPI1_SS1__GPIO4_27 0x0
+			>;
+		};
+
+		pinctrl_imxfb1: imxfbgrp {
+			fsl,pins = <
+				MX27_PAD_LD0__LD0 0x0
+				MX27_PAD_LD1__LD1 0x0
+				MX27_PAD_LD2__LD2 0x0
+				MX27_PAD_LD3__LD3 0x0
+				MX27_PAD_LD4__LD4 0x0
+				MX27_PAD_LD5__LD5 0x0
+				MX27_PAD_LD6__LD6 0x0
+				MX27_PAD_LD7__LD7 0x0
+				MX27_PAD_LD8__LD8 0x0
+				MX27_PAD_LD9__LD9 0x0
+				MX27_PAD_LD10__LD10 0x0
+				MX27_PAD_LD11__LD11 0x0
+				MX27_PAD_LD12__LD12 0x0
+				MX27_PAD_LD13__LD13 0x0
+				MX27_PAD_LD14__LD14 0x0
+				MX27_PAD_LD15__LD15 0x0
+				MX27_PAD_LD16__LD16 0x0
+				MX27_PAD_LD17__LD17 0x0
+				MX27_PAD_CLS__CLS 0x0
+				MX27_PAD_CONTRAST__CONTRAST 0x0
+				MX27_PAD_LSCLK__LSCLK 0x0
+				MX27_PAD_OE_ACD__OE_ACD 0x0
+				MX27_PAD_PS__PS 0x0
+				MX27_PAD_REV__REV 0x0
+				MX27_PAD_SPL_SPR__SPL_SPR 0x0
+				MX27_PAD_HSYNC__HSYNC 0x0
+				MX27_PAD_VSYNC__VSYNC 0x0
+			>;
+		};
+
 		pinctrl_i2c1: i2c1grp {
 			/* Add pullup to DATA line */
 			fsl,pins = <
@@ -205,7 +280,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_weim>;
 
-	can@d4000000 {
+	can@4,0 {
 		compatible = "nxp,sja1000";
 		reg = <4 0x00000000 0x00000100>;
 		interrupt-parent = <&gpio5>;
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
index cefaa6994623..d7ed63c51c6c 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
@@ -251,6 +251,15 @@
 			>;
 		};
 
+		pinctrl_ssi1: ssi1grp {
+			fsl,pins = <
+				MX27_PAD_SSI1_FS__SSI1_FS 0x0
+				MX27_PAD_SSI1_RXDAT__SSI1_RXDAT 0x0
+				MX27_PAD_SSI1_TXDAT__SSI1_TXDAT 0x0
+				MX27_PAD_SSI1_CLK__SSI1_CLK 0x0
+			>;
+		};
+
 		pinctrl_usbotg: usbotggrp {
 			fsl,pins = <
 				MX27_PAD_USBOTG_CLK__USBOTG_CLK 0x0
@@ -279,6 +288,13 @@
 	status = "okay";
 };
 
+&ssi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ssi1>;
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
 &usbotg {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usbotg>;
@@ -295,7 +311,7 @@
 &weim {
 	status = "okay";
 
-	nor: nor@c0000000 {
+	nor: nor@0,0 {
 		compatible = "cfi-flash";
 		reg = <0 0x00000000 0x02000000>;
 		bank-width = <2>;
@@ -305,7 +321,7 @@
 		#size-cells = <1>;
 	};
 
-	sram: sram@c8000000 {
+	sram: sram@1,0 {
 		compatible = "mtd-ram";
 		reg = <1 0x00000000 0x00800000>;
 		bank-width = <2>;
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 6279e0b4f768..00cf66c1b8f3 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -16,6 +16,7 @@
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -48,6 +49,7 @@
 
 		osc26m {
 			compatible = "fsl,imx-osc26m", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <26000000>;
 		};
 	};
diff --git a/arch/arm/boot/dts/imx28-duckbill.dts b/arch/arm/boot/dts/imx28-duckbill.dts
index 5f326c1c1850..ce1a7effba37 100644
--- a/arch/arm/boot/dts/imx28-duckbill.dts
+++ b/arch/arm/boot/dts/imx28-duckbill.dts
@@ -25,9 +25,9 @@
 			ssp0: ssp@80010000 {
 				compatible = "fsl,imx28-mmc";
 				pinctrl-names = "default";
-				pinctrl-0 = <&mmc0_8bit_pins_a
+				pinctrl-0 = <&mmc0_4bit_pins_a
 					&mmc0_cd_cfg &mmc0_sck_cfg>;
-				bus-width = <8>;
+				bus-width = <4>;
 				vmmc-supply = <&reg_3p3v>;
 				status = "okay";
 			};
@@ -39,7 +39,7 @@
 				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						MX28_PAD_ENET0_RX_CLK__GPIO_4_13 /* PHY Reset */
+						MX28_PAD_SSP0_DATA7__GPIO_2_7 /* PHY Reset */
 					>;
 					fsl,drive-strength = <MXS_DRIVE_4mA>;
 					fsl,voltage = <MXS_VOLTAGE_HIGH>;
@@ -82,7 +82,7 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&mac0_pins_a>;
 			phy-supply = <&reg_3p3v>;
-			phy-reset-gpios = <&gpio4 13 0>;
+			phy-reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
 			phy-reset-duration = <100>;
 			status = "okay";
 		};
@@ -110,12 +110,12 @@
 
 		status {
 			label = "duckbill:green:status";
-			gpios = <&gpio3 5 0>;
+			gpios = <&gpio3 5 GPIO_ACTIVE_HIGH>;
 		};
 
 		failure {
 			label = "duckbill:red:status";
-			gpios = <&gpio3 4 0>;
+			gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 90a579532b8b..a95cc5358ff4 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -9,6 +9,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <dt-bindings/gpio/gpio.h>
 #include "skeleton.dtsi"
 #include "imx28-pinfunc.h"
 
diff --git a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
index 906ae937b013..9c2b715ab8bf 100644
--- a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
+++ b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
@@ -37,6 +37,17 @@
 		compatible = "nxp,pcf8563";
 		reg = <0x51>;
 	};
+
+	tsc2007: tsc2007@48 {
+		compatible = "ti,tsc2007";
+		gpios = <&gpio3 2 0>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <0x2 0x8>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tsc2007_1>;
+		reg = <0x48>;
+		ti,x-plate-ohms = <180>;
+	};
 };
 
 &iomuxc {
@@ -70,6 +81,10 @@
 				MX35_PAD_I2C1_DAT__I2C1_SDA		0x80000000
 			>;
 		};
+
+		pinctrl_tsc2007_1: tsc2007grp-1 {
+			fsl,pins = <MX35_PAD_ATA_DA2__GPIO3_2 0x80000000>;
+		};
 	};
 };
 
diff --git a/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts b/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
index 1bdec21f4533..f04ae91eea89 100644
--- a/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
+++ b/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
@@ -46,6 +46,14 @@
 			linux,default-trigger = "heartbeat";
 		};
 	};
+
+	sound {
+		compatible = "eukrea,asoc-tlv320";
+		eukrea,model = "imx35-eukrea-tlv320aic23";
+		ssi-controller = <&ssi1>;
+		fsl,mux-int-port = <1>;
+		fsl,mux-ext-port = <4>;
+	};
 };
 
 &audmux {
@@ -124,6 +132,7 @@
 };
 
 &ssi1 {
+	codec-handle = <&tlv320aic23>;
 	fsl,mode = "i2s-slave";
 	status = "okay";
 };
@@ -141,3 +150,16 @@
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
+
+&usbhost1 {
+	phy_type = "serial";
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbotg {
+	phy_type = "utmi";
+	dr_mode = "otg";
+	external-vbus-divider;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx35-pdk.dts b/arch/arm/boot/dts/imx35-pdk.dts
new file mode 100644
index 000000000000..db69ff085e27
--- /dev/null
+++ b/arch/arm/boot/dts/imx35-pdk.dts
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx35.dtsi"
+
+/ {
+	model = "Freescale i.MX35 Product Development Kit";
+	compatible = "fsl,imx35-pdk", "fsl,imx35";
+
+	memory {
+		reg = <0x80000000 0x8000000>;
+	};
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	status = "okay";
+};
+
+&iomuxc {
+	imx35-pdk {
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,pins = <
+				MX35_PAD_SD1_CMD__ESDHC1_CMD		0x80000000
+				MX35_PAD_SD1_CLK__ESDHC1_CLK		0x80000000
+				MX35_PAD_SD1_DATA0__ESDHC1_DAT0		0x80000000
+				MX35_PAD_SD1_DATA1__ESDHC1_DAT1		0x80000000
+				MX35_PAD_SD1_DATA2__ESDHC1_DAT2		0x80000000
+				MX35_PAD_SD1_DATA3__ESDHC1_DAT3		0x80000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX35_PAD_TXD1__UART1_TXD_MUX		0x1c5
+				MX35_PAD_RXD1__UART1_RXD_MUX		0x1c5
+				MX35_PAD_CTS1__UART1_CTS		0x1c5
+				MX35_PAD_RTS1__UART1_RTS		0x1c5
+			>;
+		};
+	};
+};
+
+&nfc {
+	nand-bus-width = <16>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi
index 88b218f8f810..4759abb49436 100644
--- a/arch/arm/boot/dts/imx35.dtsi
+++ b/arch/arm/boot/dts/imx35.dtsi
@@ -13,6 +13,7 @@
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -295,9 +296,9 @@
 				compatible = "fsl,imx35-usb", "fsl,imx27-usb";
 				reg = <0x53ff4000 0x0200>;
 				interrupts = <37>;
-				clocks = <&clks 9>, <&clks 73>, <&clks 28>;
-				clock-names = "ipg", "ahb", "per";
+				clocks = <&clks 73>;
 				fsl,usbmisc = <&usbmisc 0>;
+				fsl,usbphy = <&usbphy0>;
 				status = "disabled";
 			};
 
@@ -305,9 +306,9 @@
 				compatible = "fsl,imx35-usb", "fsl,imx27-usb";
 				reg = <0x53ff4400 0x0200>;
 				interrupts = <35>;
-				clocks = <&clks 9>, <&clks 73>, <&clks 28>;
-				clock-names = "ipg", "ahb", "per";
+				clocks = <&clks 73>;
 				fsl,usbmisc = <&usbmisc 1>;
+				fsl,usbphy = <&usbphy1>;
 				status = "disabled";
 			};
 
@@ -356,4 +357,20 @@
 			};
 		};
 	};
+
+	usbphy {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usbphy0: usb-phy@0 {
+			reg = <0>;
+			compatible = "usb-nop-xceiv";
+		};
+
+		usbphy1: usb-phy@1 {
+			reg = <1>;
+			compatible = "usb-nop-xceiv";
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi
index 0c75fe3deb35..6a201cf54366 100644
--- a/arch/arm/boot/dts/imx50.dtsi
+++ b/arch/arm/boot/dts/imx50.dtsi
@@ -17,6 +17,7 @@
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -53,21 +54,25 @@
 
 		ckil {
 			compatible = "fsl,imx-ckil", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <32768>;
 		};
 
 		ckih1 {
 			compatible = "fsl,imx-ckih1", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <22579200>;
 		};
 
 		ckih2 {
 			compatible = "fsl,imx-ckih2", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <0>;
 		};
 
 		osc {
 			compatible = "fsl,imx-osc", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24000000>;
 		};
 	};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index 9e9deb244b76..2dda06be52a9 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -129,6 +129,35 @@
 			gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
 		};
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb_vbus: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "usb_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio2 5 0>;
+			enable-active-high;
+		};
+	};
+
+	usbphy {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "simple-bus";
+
+		usbh1phy: usbh1phy@0 {
+			compatible = "usb-nop-xceiv";
+			reg = <0>;
+			clocks = <&clks 0>;
+			clock-names = "main_clk";
+		};
+	};
 };
 
 &esdhc1 {
@@ -479,6 +508,23 @@
 				MX51_PAD_EIM_D24__UART3_CTS		0x1c5
 			>;
 		};
+
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX51_PAD_USBH1_CLK__USBH1_CLK		0x80000000
+				MX51_PAD_USBH1_DIR__USBH1_DIR		0x80000000
+				MX51_PAD_USBH1_NXT__USBH1_NXT		0x80000000
+				MX51_PAD_USBH1_DATA0__USBH1_DATA0	0x80000000
+				MX51_PAD_USBH1_DATA1__USBH1_DATA1	0x80000000
+				MX51_PAD_USBH1_DATA2__USBH1_DATA2	0x80000000
+				MX51_PAD_USBH1_DATA3__USBH1_DATA3	0x80000000
+				MX51_PAD_USBH1_DATA4__USBH1_DATA4	0x80000000
+				MX51_PAD_USBH1_DATA5__USBH1_DATA5	0x80000000
+				MX51_PAD_USBH1_DATA6__USBH1_DATA6	0x80000000
+				MX51_PAD_USBH1_DATA7__USBH1_DATA7	0x80000000
+				MX51_PAD_EIM_D21__GPIO2_5		0x80000000
+			>;
+		};
 	};
 };
 
@@ -547,3 +593,19 @@
 		>;
 	status = "okay";
 };
+
+&usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	vbus-supply = <&reg_usb_vbus>;
+	fsl,usbphy = <&usbh1phy>;
+	phy_type = "ulpi";
+	status = "okay";
+};
+
+&usbotg {
+	dr_mode = "otg";
+	disable-over-current;
+	phy_type = "utmi_wide";
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx51-digi-connectcore-jsk.dts b/arch/arm/boot/dts/imx51-digi-connectcore-jsk.dts
new file mode 100644
index 000000000000..1db517d3d497
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-digi-connectcore-jsk.dts
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx51-digi-connectcore-som.dtsi"
+
+/ {
+	model = "Digi ConnectCore CC(W)-MX51 JSK";
+	compatible = "digi,connectcore-ccxmx51-jsk",
+		     "digi,connectcore-ccxmx51-som", "fsl,imx51";
+
+	chosen {
+		linux,stdout-path = &uart1;
+	};
+};
+
+&owire {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_owire>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&usbotg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	dr_mode = "host";
+	phy_type = "ulpi";
+	disable-over-current;
+	status = "okay";
+};
+
+&iomuxc {
+	imx51-digi-connectcore-jsk {
+		pinctrl_owire: owiregrp {
+			fsl,pins = <
+				MX51_PAD_OWIRE_LINE__OWIRE_LINE		0x40000000
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX51_PAD_UART1_RXD__UART1_RXD		0x1c5
+				MX51_PAD_UART1_TXD__UART1_TXD		0x1c5
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX51_PAD_UART2_RXD__UART2_RXD		0x1c5
+				MX51_PAD_UART2_TXD__UART2_TXD		0x1c5
+			>;
+		};
+
+		pinctrl_uart3: uart3grp {
+			fsl,pins = <
+				MX51_PAD_UART3_RXD__UART3_RXD		0x1c5
+				MX51_PAD_UART3_TXD__UART3_TXD		0x1c5
+			>;
+		};
+
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX51_PAD_USBH1_DATA0__USBH1_DATA0	0x1e5
+				MX51_PAD_USBH1_DATA1__USBH1_DATA1	0x1e5
+				MX51_PAD_USBH1_DATA2__USBH1_DATA2	0x1e5
+				MX51_PAD_USBH1_DATA3__USBH1_DATA3	0x1e5
+				MX51_PAD_USBH1_DATA4__USBH1_DATA4	0x1e5
+				MX51_PAD_USBH1_DATA5__USBH1_DATA5	0x1e5
+				MX51_PAD_USBH1_DATA6__USBH1_DATA6	0x1e5
+				MX51_PAD_USBH1_DATA7__USBH1_DATA7	0x1e5
+				MX51_PAD_USBH1_CLK__USBH1_CLK		0x1e5
+				MX51_PAD_USBH1_DIR__USBH1_DIR		0x1e5
+				MX51_PAD_USBH1_NXT__USBH1_NXT		0x1e5
+				MX51_PAD_USBH1_STP__USBH1_STP		0x1e5
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx51-digi-connectcore-som.dtsi b/arch/arm/boot/dts/imx51-digi-connectcore-som.dtsi
new file mode 100644
index 000000000000..7787f46cc5b5
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-digi-connectcore-som.dtsi
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx51.dtsi"
+
+/ {
+	model = "Digi ConnectCore CC(W)-MX51";
+	compatible = "digi,connectcore-ccxmx51-som", "fsl,imx51";
+
+	memory {
+		reg = <0x90000000 0x08000000>;
+	};
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+
+	pmic: mc13892@0 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_mc13892>;
+		compatible = "fsl,mc13892";
+		spi-max-frequency = <16000000>;
+		spi-cs-high;
+		reg = <0>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+		fsl,mc13xxx-uses-rtc;
+
+		regulators {
+			sw1_reg: sw1 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <1225000>;
+				regulator-max-microvolt = <1225000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3_reg: sw3 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			swbst_reg: swbst { };
+
+			viohi_reg: viohi {
+				regulator-always-on;
+			};
+
+			vpll_reg: vpll {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vdig_reg: vdig {
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-always-on;
+			};
+
+			vsd_reg: vsd {
+				regulator-min-microvolt = <3150000>;
+				regulator-max-microvolt = <3150000>;
+				regulator-always-on;
+			};
+
+			vusb2_reg: vusb2 {
+				regulator-min-microvolt = <2600000>;
+				regulator-max-microvolt = <2600000>;
+				regulator-always-on;
+			};
+
+			vvideo_reg: vvideo {
+				regulator-min-microvolt = <2775000>;
+				regulator-max-microvolt = <2775000>;
+				regulator-always-on;
+			};
+
+			vaudio_reg: vaudio {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+
+			vcam_reg: vcam {
+				regulator-min-microvolt = <2750000>;
+				regulator-max-microvolt = <2750000>;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <3150000>;
+				regulator-max-microvolt = <3150000>;
+				regulator-always-on;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vusb_reg: vusb {
+				regulator-always-on;
+			};
+
+			gpo1_reg: gpo1 { };
+
+			gpo2_reg: gpo2 { };
+
+			gpo3_reg: gpo3 { };
+
+			gpo4_reg: gpo4 { };
+
+			pwgt2spi_reg: pwgt2spi {
+				regulator-always-on;
+			};
+
+			vcoincell_reg: vcoincell {
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&esdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc2>;
+	cap-sdio-irq;
+	enable-sdio-wakeup;
+	keep-power-in-suspend;
+	max-frequency = <50000000>;
+	no-1-8-v;
+	non-removable;
+	vmmc-supply = <&gpo4_reg>;
+	status = "okay";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	phy-mode = "mii";
+	phy-supply = <&gpo3_reg>;
+	/* Pins shared with LCD2, keep status disabled */
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	mma7455l@1d {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_mma7455l>;
+		compatible = "fsl,mma7455l";
+		reg = <0x1d>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <7 IRQ_TYPE_LEVEL_HIGH>, <6 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nfc>;
+	nand-bus-width = <8>;
+	nand-ecc-mode = "hw";
+	nand-on-flash-bbt;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	status = "okay";
+};
+
+&usbotg {
+	phy_type = "utmi_wide";
+	disable-over-current;
+	/* Device role is not known, keep status disabled */
+};
+
+&weim {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_weim>;
+	status = "okay";
+
+	lan9221: lan9221@5,0 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lan9221>;
+		compatible = "smsc,lan9221", "smsc,lan9115";
+		reg = <5 0x00000000 0x1000>;
+		fsl,weim-cs-timing = <
+			0x00420081 0x00000000
+			0x32260000 0x00000000
+			0x72080f00 0x00000000
+		>;
+		clocks = <&clks IMX5_CLK_DUMMY>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+		phy-mode = "mii";
+		reg-io-width = <2>;
+		smsc,irq-push-pull;
+		vdd33a-supply = <&gpo2_reg>;
+		vddvario-supply = <&gpo2_reg>;
+	};
+};
+
+&iomuxc {
+	imx51-digi-connectcore-som {
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX51_PAD_CSPI1_MISO__ECSPI1_MISO	0x185
+				MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	0x185
+				MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	0x185
+				MX51_PAD_CSPI1_SS0__GPIO4_24		0x85 /* CS0 */
+			>;
+		};
+
+		pinctrl_esdhc2: esdhc2grp {
+			fsl,pins = <
+				MX51_PAD_SD2_CMD__SD2_CMD		0x400020d5
+				MX51_PAD_SD2_CLK__SD2_CLK		0x20d5
+				MX51_PAD_SD2_DATA0__SD2_DATA0		0x20d5
+				MX51_PAD_SD2_DATA1__SD2_DATA1		0x20d5
+				MX51_PAD_SD2_DATA2__SD2_DATA2		0x20d5
+				MX51_PAD_SD2_DATA3__SD2_DATA3		0x20d5
+			>;
+		};
+
+		pinctrl_fec: fecgrp {
+			fsl,pins = <
+				MX51_PAD_DI_GP3__FEC_TX_ER		0x80000000
+				MX51_PAD_DI2_PIN4__FEC_CRS		0x80000000
+				MX51_PAD_DI2_PIN2__FEC_MDC		0x80000000
+				MX51_PAD_DI2_PIN3__FEC_MDIO		0x80000000
+				MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	0x80000000
+				MX51_PAD_DI_GP4__FEC_RDATA2		0x80000000
+				MX51_PAD_DISP2_DAT0__FEC_RDATA3		0x80000000
+				MX51_PAD_DISP2_DAT1__FEC_RX_ER		0x80000000
+				MX51_PAD_DISP2_DAT6__FEC_TDATA1		0x80000000
+				MX51_PAD_DISP2_DAT7__FEC_TDATA2		0x80000000
+				MX51_PAD_DISP2_DAT8__FEC_TDATA3		0x80000000
+				MX51_PAD_DISP2_DAT9__FEC_TX_EN		0x80000000
+				MX51_PAD_DISP2_DAT10__FEC_COL		0x80000000
+				MX51_PAD_DISP2_DAT11__FEC_RX_CLK	0x80000000
+				MX51_PAD_DISP2_DAT12__FEC_RX_DV		0x80000000
+				MX51_PAD_DISP2_DAT13__FEC_TX_CLK	0x80000000
+				MX51_PAD_DISP2_DAT14__FEC_RDATA0	0x80000000
+				MX51_PAD_DISP2_DAT15__FEC_TDATA0	0x80000000
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX51_PAD_GPIO1_2__I2C2_SCL		0x400001ed
+				MX51_PAD_GPIO1_3__I2C2_SDA		0x400001ed
+			>;
+		};
+
+		pinctrl_nfc: nfcgrp {
+			fsl,pins = <
+				MX51_PAD_NANDF_D0__NANDF_D0		0x80000000
+				MX51_PAD_NANDF_D1__NANDF_D1		0x80000000
+				MX51_PAD_NANDF_D2__NANDF_D2		0x80000000
+				MX51_PAD_NANDF_D3__NANDF_D3		0x80000000
+				MX51_PAD_NANDF_D4__NANDF_D4		0x80000000
+				MX51_PAD_NANDF_D5__NANDF_D5		0x80000000
+				MX51_PAD_NANDF_D6__NANDF_D6		0x80000000
+				MX51_PAD_NANDF_D7__NANDF_D7		0x80000000
+				MX51_PAD_NANDF_ALE__NANDF_ALE		0x80000000
+				MX51_PAD_NANDF_CLE__NANDF_CLE		0x80000000
+				MX51_PAD_NANDF_RE_B__NANDF_RE_B		0x80000000
+				MX51_PAD_NANDF_WE_B__NANDF_WE_B		0x80000000
+				MX51_PAD_NANDF_WP_B__NANDF_WP_B		0x80000000
+				MX51_PAD_NANDF_CS0__NANDF_CS0		0x80000000
+				MX51_PAD_NANDF_RB0__NANDF_RB0		0x80000000
+			>;
+		};
+
+		pinctrl_lan9221: lan9221grp {
+			fsl,pins = <
+				MX51_PAD_GPIO1_9__GPIO1_9		0xe5 /* IRQ */
+			>;
+		};
+
+		pinctrl_mc13892: mc13892grp {
+			fsl,pins = <
+				MX51_PAD_GPIO1_5__GPIO1_5		0xe5 /* IRQ */
+			>;
+		};
+
+		pinctrl_mma7455l: mma7455lgrp {
+			fsl,pins = <
+				MX51_PAD_GPIO1_7__GPIO1_7		0xe5 /* IRQ1 */
+				MX51_PAD_GPIO1_6__GPIO1_6		0xe5 /* IRQ2 */
+			>;
+		};
+
+		pinctrl_weim: weimgrp {
+			fsl,pins = <
+				MX51_PAD_EIM_DA0__EIM_DA0		0x80000000
+				MX51_PAD_EIM_DA1__EIM_DA1		0x80000000
+				MX51_PAD_EIM_DA2__EIM_DA2		0x80000000
+				MX51_PAD_EIM_DA3__EIM_DA3		0x80000000
+				MX51_PAD_EIM_DA4__EIM_DA4		0x80000000
+				MX51_PAD_EIM_DA5__EIM_DA5		0x80000000
+				MX51_PAD_EIM_DA6__EIM_DA6		0x80000000
+				MX51_PAD_EIM_DA7__EIM_DA7		0x80000000
+				MX51_PAD_EIM_DA8__EIM_DA8		0x80000000
+				MX51_PAD_EIM_DA9__EIM_DA9		0x80000000
+				MX51_PAD_EIM_DA10__EIM_DA10		0x80000000
+				MX51_PAD_EIM_DA11__EIM_DA11		0x80000000
+				MX51_PAD_EIM_DA12__EIM_DA12		0x80000000
+				MX51_PAD_EIM_DA13__EIM_DA13		0x80000000
+				MX51_PAD_EIM_DA14__EIM_DA14		0x80000000
+				MX51_PAD_EIM_DA15__EIM_DA15		0x80000000
+				MX51_PAD_EIM_A16__EIM_A16		0x80000000
+				MX51_PAD_EIM_A17__EIM_A17		0x80000000
+				MX51_PAD_EIM_A18__EIM_A18		0x80000000
+				MX51_PAD_EIM_A19__EIM_A19		0x80000000
+				MX51_PAD_EIM_A20__EIM_A20		0x80000000
+				MX51_PAD_EIM_A21__EIM_A21		0x80000000
+				MX51_PAD_EIM_A22__EIM_A22		0x80000000
+				MX51_PAD_EIM_A23__EIM_A23		0x80000000
+				MX51_PAD_EIM_A24__EIM_A24		0x80000000
+				MX51_PAD_EIM_A25__EIM_A25		0x80000000
+				MX51_PAD_EIM_A26__EIM_A26		0x80000000
+				MX51_PAD_EIM_A27__EIM_A27		0x80000000
+				MX51_PAD_EIM_D16__EIM_D16		0x80000000
+				MX51_PAD_EIM_D17__EIM_D17		0x80000000
+				MX51_PAD_EIM_D18__EIM_D18		0x80000000
+				MX51_PAD_EIM_D19__EIM_D19		0x80000000
+				MX51_PAD_EIM_D20__EIM_D20		0x80000000
+				MX51_PAD_EIM_D21__EIM_D21		0x80000000
+				MX51_PAD_EIM_D22__EIM_D22		0x80000000
+				MX51_PAD_EIM_D23__EIM_D23		0x80000000
+				MX51_PAD_EIM_D24__EIM_D24		0x80000000
+				MX51_PAD_EIM_D25__EIM_D25		0x80000000
+				MX51_PAD_EIM_D26__EIM_D26		0x80000000
+				MX51_PAD_EIM_D27__EIM_D27		0x80000000
+				MX51_PAD_EIM_D28__EIM_D28		0x80000000
+				MX51_PAD_EIM_D29__EIM_D29		0x80000000
+				MX51_PAD_EIM_D30__EIM_D30		0x80000000
+				MX51_PAD_EIM_D31__EIM_D31		0x80000000
+				MX51_PAD_EIM_OE__EIM_OE			0x80000000
+				MX51_PAD_EIM_DTACK__EIM_DTACK		0x80000000
+				MX51_PAD_EIM_LBA__EIM_LBA		0x80000000
+				MX51_PAD_EIM_CS5__EIM_CS5		0x80000000 /* CS5 */
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi b/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
index 9b3acf6e4282..63164266af83 100644
--- a/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
+++ b/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
@@ -42,6 +42,17 @@
 		compatible = "nxp,pcf8563";
 		reg = <0x51>;
 	};
+
+	tsc2007: tsc2007@49 {
+		compatible = "ti,tsc2007";
+		gpios = <&gpio4 0 1>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <0x0 0x8>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tsc2007_1>;
+		reg = <0x49>;
+		ti,x-plate-ohms = <180>;
+	};
 };
 
 &iomuxc {
diff --git a/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts b/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
index 5cec4f322096..8b1098ebaf79 100644
--- a/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
+++ b/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
@@ -57,6 +57,20 @@
 		fsl,mux-int-port = <2>;
 		fsl,mux-ext-port = <3>;
 	};
+
+	usbphy {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "simple-bus";
+
+		usbh1phy: usbh1phy@0 {
+			compatible = "usb-nop-xceiv";
+			reg = <0>;
+			clocks = <&clks IMX5_CLK_USB_PHY_GATE>;
+			clock-names = "main_clk";
+			clock-frequency = <19200000>;
+		};
+	};
 };
 
 &audmux {
@@ -151,6 +165,29 @@
 				MX51_PAD_CSI1_D9__GPIO3_13 0x1f5
 			>;
 		};
+
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX51_PAD_USBH1_CLK__USBH1_CLK     0x1e5
+				MX51_PAD_USBH1_DIR__USBH1_DIR     0x1e5
+				MX51_PAD_USBH1_NXT__USBH1_NXT     0x1e5
+				MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x1e5
+				MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x1e5
+				MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x1e5
+				MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x1e5
+				MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x1e5
+				MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x1e5
+				MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x1e5
+				MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x1e5
+				MX51_PAD_USBH1_STP__USBH1_STP     0x1e5
+			>;
+		};
+
+		pinctrl_usbh1_vbus: usbh1-vbusgrp {
+			fsl,pins = <
+				MX51_PAD_EIM_CS3__GPIO2_28 0x1f5
+			>;
+		};
 	};
 };
 
@@ -173,3 +210,24 @@
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
+
+&usbh1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	fsl,usbphy = <&usbh1phy>;
+	dr_mode = "host";
+	phy_type = "ulpi";
+	status = "okay";
+};
+
+&usbotg {
+	dr_mode = "otg";
+	phy_type = "utmi_wide";
+	status = "okay";
+};
+
+&usbphy0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1_vbus>;
+	reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 5f8216d08f6b..51b86700cd88 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -19,6 +19,7 @@
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -50,21 +51,25 @@
 
 		ckil {
 			compatible = "fsl,imx-ckil", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <32768>;
 		};
 
 		ckih1 {
 			compatible = "fsl,imx-ckih1", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <0>;
 		};
 
 		ckih2 {
 			compatible = "fsl,imx-ckih2", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <0>;
 		};
 
 		osc {
 			compatible = "fsl,imx-osc", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24000000>;
 		};
 	};
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index f6d3ac3e5587..d5d146a8b149 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -17,7 +17,8 @@
 	compatible = "denx,imx53-m53evk", "fsl,imx53";
 
 	memory {
-		reg = <0x70000000 0x20000000>;
+		reg = <0x70000000 0x20000000>,
+		      <0xb0000000 0x20000000>;
 	};
 
 	soc {
@@ -193,17 +194,17 @@
 		irq-trigger = <0x1>;
 
 		stmpe_touchscreen {
-			compatible = "stmpe,ts";
+			compatible = "st,stmpe-ts";
 			reg = <0>;
-			ts,sample-time = <4>;
-			ts,mod-12b = <1>;
-			ts,ref-sel = <0>;
-			ts,adc-freq = <1>;
-			ts,ave-ctrl = <3>;
-			ts,touch-det-delay = <3>;
-			ts,settling = <4>;
-			ts,fraction-z = <7>;
-			ts,i-drive = <1>;
+			st,sample-time = <4>;
+			st,mod-12b = <1>;
+			st,ref-sel = <0>;
+			st,adc-freq = <1>;
+			st,ave-ctrl = <3>;
+			st,touch-det-delay = <3>;
+			st,settling = <4>;
+			st,fraction-z = <7>;
+			st,i-drive = <1>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/imx53-qsb-common.dtsi
index 3f825a6813da..ede04fa4161f 100644
--- a/arch/arm/boot/dts/imx53-qsb-common.dtsi
+++ b/arch/arm/boot/dts/imx53-qsb-common.dtsi
@@ -14,7 +14,8 @@
 
 / {
 	memory {
-		reg = <0x70000000 0x40000000>;
+		reg = <0x70000000 0x20000000>,
+		      <0xb0000000 0x20000000>;
 	};
 
 	display0: display@di0 {
diff --git a/arch/arm/boot/dts/imx53-tx53-x03x.dts b/arch/arm/boot/dts/imx53-tx53-x03x.dts
index 0217dde3b36b..3b73e81dc3f0 100644
--- a/arch/arm/boot/dts/imx53-tx53-x03x.dts
+++ b/arch/arm/boot/dts/imx53-tx53-x03x.dts
@@ -25,12 +25,17 @@
 	soc {
 		display: display@di0 {
 			compatible = "fsl,imx-parallel-display";
-			crtcs = <&ipu 0>;
 			interface-pix-fmt = "rgb24";
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_rgb24_vga1>;
 			status = "okay";
 
+			port {
+				display0_in: endpoint {
+					remote-endpoint = <&ipu_di0_disp0>;
+				};
+			};
+
 			display-timings {
 				VGA {
 					clock-frequency = <25200000>;
@@ -293,6 +298,10 @@
 	};
 };
 
+&ipu_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
 &kpp {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_kpp>;
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index b57ab57740f6..375e66fad578 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -18,6 +18,7 @@
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -70,21 +71,25 @@
 
 		ckil {
 			compatible = "fsl,imx-ckil", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <32768>;
 		};
 
 		ckih1 {
 			compatible = "fsl,imx-ckih1", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <22579200>;
 		};
 
 		ckih2 {
 			compatible = "fsl,imx-ckih2", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <0>;
 		};
 
 		osc {
 			compatible = "fsl,imx-osc", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24000000>;
 		};
 	};
@@ -430,7 +435,7 @@
 
 					port {
 						lvds1_in: endpoint {
-							remote-endpoint = <&ipu_di0_lvds0>;
+							remote-endpoint = <&ipu_di1_lvds1>;
 						};
 					};
 				};
@@ -722,8 +727,8 @@
 				clocks = <&clks IMX5_CLK_VPU_GATE>,
 				         <&clks IMX5_CLK_VPU_GATE>;
 				clock-names = "per", "ahb";
+				resets = <&src 1>;
 				iram = <&ocram>;
-				status = "disabled";
 			};
 		};
 
diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
index a63bbb3d46bb..e4ae38fd0269 100644
--- a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
+++ b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
@@ -19,7 +19,10 @@
 	compatible = "dmo,imx6q-edmqmx6", "fsl,imx6q";
 
 	aliases {
-		gpio7 = &stmpe_gpio;
+		gpio7 = &stmpe_gpio1;
+		gpio8 = &stmpe_gpio2;
+		stmpe-i2c0 = &stmpe1;
+		stmpe-i2c1 = &stmpe2;
 	};
 
 	memory {
@@ -40,13 +43,15 @@
 			regulator-always-on;
 		};
 
-		reg_usb_otg_vbus: regulator@1 {
+		reg_usb_otg_switch: regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
-			regulator-name = "usb_otg_vbus";
+			regulator-name = "usb_otg_switch";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			gpio = <&gpio7 12 0>;
+			regulator-boot-on;
+			regulator-always-on;
 		};
 
 		reg_usb_host1: regulator@2 {
@@ -65,23 +70,23 @@
 
 		led-blue {
 			label = "blue";
-			gpios = <&stmpe_gpio 8 GPIO_ACTIVE_HIGH>;
+			gpios = <&stmpe_gpio1 8 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 
 		led-green {
 			label = "green";
-			gpios = <&stmpe_gpio 9 GPIO_ACTIVE_HIGH>;
+			gpios = <&stmpe_gpio1 9 GPIO_ACTIVE_HIGH>;
 		};
 
 		led-pink {
 			label = "pink";
-			gpios = <&stmpe_gpio 10 GPIO_ACTIVE_HIGH>;
+			gpios = <&stmpe_gpio1 10 GPIO_ACTIVE_HIGH>;
 		};
 
 		led-red {
 			label = "red";
-			gpios = <&stmpe_gpio 11 GPIO_ACTIVE_HIGH>;
+			gpios = <&stmpe_gpio1 11 GPIO_ACTIVE_HIGH>;
 		};
 	};
 };
@@ -99,7 +104,8 @@
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_i2c2
-		     &pinctrl_stmpe>;
+		     &pinctrl_stmpe1
+		     &pinctrl_stmpe2>;
 	status = "okay";
 
 	pmic: pfuze100@08 {
@@ -205,13 +211,25 @@
 		};
 	};
 
-	stmpe: stmpe1601@40 {
+	stmpe1: stmpe1601@40 {
 		compatible = "st,stmpe1601";
 		reg = <0x40>;
 		interrupts = <30 0>;
 		interrupt-parent = <&gpio3>;
 
-		stmpe_gpio: stmpe_gpio {
+		stmpe_gpio1: stmpe_gpio {
+			#gpio-cells = <2>;
+			compatible = "st,stmpe-gpio";
+		};
+	};
+
+	stmpe2: stmpe1601@44 {
+		compatible = "st,stmpe1601";
+		reg = <0x44>;
+		interrupts = <2 0>;
+		interrupt-parent = <&gpio5>;
+
+		stmpe_gpio2: stmpe_gpio {
 			#gpio-cells = <2>;
 			compatible = "st,stmpe-gpio";
 		};
@@ -273,10 +291,14 @@
 			>;
 		};
 
-		pinctrl_stmpe: stmpegrp {
+		pinctrl_stmpe1: stmpe1grp {
 			fsl,pins = <MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x80000000>;
 		};
 
+		pinctrl_stmpe2: stmpe2grp {
+			fsl,pins = <MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000>;
+		};
+
 		pinctrl_uart1: uart1grp {
 			fsl,pins = <
 				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
@@ -293,7 +315,7 @@
 
 		pinctrl_usbotg: usbotggrp {
 			fsl,pins = <
-				MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x17059
 			>;
 		};
 
@@ -344,11 +366,11 @@
 &usbh1 {
 	vbus-supply = <&reg_usb_host1>;
 	disable-over-current;
+	dr_mode = "host";
 	status = "okay";
 };
 
 &usbotg {
-	vbus-supply = <&reg_usb_otg_vbus>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usbotg>;
 	disable-over-current;
diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/imx6q-gw5400-a.dts
index 902f98310481..e51bb3f0fd56 100644
--- a/arch/arm/boot/dts/imx6q-gw5400-a.dts
+++ b/arch/arm/boot/dts/imx6q-gw5400-a.dts
@@ -487,9 +487,6 @@
 
 &ldb {
 	status = "okay";
-	lvds-channel@0 {
-		crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
-	};
 };
 
 &pcie {
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index 8e99c9a9bc76..035d3a85c318 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -436,9 +436,6 @@
 
 &ldb {
 	status = "okay";
-	lvds-channel@0 {
-		crtcs = <&ipu1 0>, <&ipu1 1>;
-	};
 };
 
 &pcie {
diff --git a/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi b/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
index a3cb2fff8f61..d16066608e21 100644
--- a/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
@@ -26,25 +26,25 @@
 				/* GPIO16 -> AR8035 25MHz */
 				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0xc0000000
 				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x80000000
-				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
-				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
-				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
-				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
-				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b030
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b030
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b030
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b030
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b030
 				/* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
 				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x0a0b1
 				/* AR8035 pin strapping: IO voltage: pull up */
-				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b030
 				/* AR8035 pin strapping: PHYADDR#0: pull down */
-				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x130b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x13030
 				/* AR8035 pin strapping: PHYADDR#1: pull down */
-				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x130b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x13030
 				/* AR8035 pin strapping: MODE#1: pull up */
-				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
 				/* AR8035 pin strapping: MODE#3: pull up */
-				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
 				/* AR8035 pin strapping: MODE#0: pull down */
-				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x130b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x13030
 
 				/*
 				 * As the RMII pins are also connected to RGMII
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 0d816d3be4b6..7a88d9ae8daa 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -105,6 +105,17 @@
 		default-brightness-level = <7>;
 		status = "okay";
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+
+		red {
+		        gpios = <&gpio1 2 0>;
+		        default-state = "on";
+		};
+	};
 };
 
 &audmux {
@@ -422,6 +433,14 @@
 			>;
 		};
 	};
+
+	gpio_leds {
+		pinctrl_gpio_leds: gpioledsgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
+			>;
+		};
+	};
 };
 
 &ldb {
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 55cb926fa3f7..02a6afca7530 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -10,10 +10,13 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
 #include "skeleton.dtsi"
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		can0 = &can1;
 		can1 = &can2;
 		gpio0 = &gpio1;
@@ -46,8 +49,6 @@
 	intc: interrupt-controller@00a01000 {
 		compatible = "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
-		#address-cells = <1>;
-		#size-cells = <1>;
 		interrupt-controller;
 		reg = <0x00a01000 0x1000>,
 		      <0x00a00100 0x100>;
@@ -59,16 +60,19 @@
 
 		ckil {
 			compatible = "fsl,imx-ckil", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <32768>;
 		};
 
 		ckih1 {
 			compatible = "fsl,imx-ckih1", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <0>;
 		};
 
 		osc {
 			compatible = "fsl,imx-osc", "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24000000>;
 		};
 	};
@@ -138,6 +142,12 @@
 				  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
 			num-lanes = <1>;
 			interrupts = <0 123 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 0x7>;
+			interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+			                <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+			                <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+			                <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
 			clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
 			status = "disabled";
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 864d8dfb51ca..a8d9a93fab85 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -282,6 +282,7 @@
 				MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO	0x100b1
 				MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI	0x100b1
 				MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK	0x100b1
+				MX6SL_PAD_ECSPI1_SS0__GPIO4_IO11	0x80000000
 			>;
 		};
 
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 3cb4941afeef..2d4e5285f3f3 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -14,6 +14,7 @@
 
 / {
 	aliases {
+		ethernet0 = &fec;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
@@ -68,8 +69,6 @@
 	intc: interrupt-controller@00a01000 {
 		compatible = "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
-		#address-cells = <1>;
-		#size-cells = <1>;
 		interrupt-controller;
 		reg = <0x00a01000 0x1000>,
 		      <0x00a00100 0x100>;
@@ -81,11 +80,13 @@
 
 		ckil {
 			compatible = "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <32768>;
 		};
 
 		osc {
 			compatible = "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24000000>;
 		};
 	};
diff --git a/arch/arm/boot/dts/kirkwood-b3.dts b/arch/arm/boot/dts/kirkwood-b3.dts
index 40791053106b..6becedebaa4e 100644
--- a/arch/arm/boot/dts/kirkwood-b3.dts
+++ b/arch/arm/boot/dts/kirkwood-b3.dts
@@ -75,7 +75,7 @@
 			m25p16@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "m25p16";
+				compatible = "st,m25p16";
 				reg = <0>;
 				spi-max-frequency = <40000000>;
 				mode = <0>;
diff --git a/arch/arm/boot/dts/kirkwood-cloudbox.dts b/arch/arm/boot/dts/kirkwood-cloudbox.dts
index 0e06fd3cee4d..3b62aeeaa3a2 100644
--- a/arch/arm/boot/dts/kirkwood-cloudbox.dts
+++ b/arch/arm/boot/dts/kirkwood-cloudbox.dts
@@ -46,7 +46,7 @@
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "mx25l4005a";
+				compatible = "mxicy,mx25l4005a";
 				reg = <0>;
 				spi-max-frequency = <20000000>;
 				mode = <0>;
diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts
index ef3463e0ae19..28b3ee369778 100644
--- a/arch/arm/boot/dts/kirkwood-dreamplug.dts
+++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts
@@ -43,7 +43,7 @@
 			m25p40@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "mx25l1606e";
+				compatible = "mxicy,mx25l1606e";
 				reg = <0>;
 				spi-max-frequency = <50000000>;
 				mode = <0>;
diff --git a/arch/arm/boot/dts/kirkwood-laplug.dts b/arch/arm/boot/dts/kirkwood-laplug.dts
index c9e82eff9bf2..6761ffa2c4ab 100644
--- a/arch/arm/boot/dts/kirkwood-laplug.dts
+++ b/arch/arm/boot/dts/kirkwood-laplug.dts
@@ -48,7 +48,7 @@
 			status = "okay";
 
 			eeprom@50 {
-				compatible = "at,24c04";
+				compatible = "atmel,24c04";
 				pagesize = <16>;
 				reg = <0x50>;
 			};
diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
index 2cb0dc529165..32c6fb4a1162 100644
--- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
+++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
@@ -56,7 +56,7 @@
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "mx25l12805d";
+				compatible = "mxicy,mx25l12805d";
 				reg = <0>;
 				spi-max-frequency = <50000000>;
 				mode = <0>;
diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
index 743152f31a81..e6e5ec4fe6b9 100644
--- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
@@ -32,7 +32,7 @@
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "mx25l4005a";
+				compatible = "mxicy,mx25l4005a";
 				reg = <0>;
 				spi-max-frequency = <20000000>;
 				mode = <0>;
@@ -50,7 +50,7 @@
 			status = "okay";
 
 			eeprom@50 {
-				compatible = "at,24c04";
+				compatible = "atmel,24c04";
 				pagesize = <16>;
 				reg = <0x50>;
 			};
diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts
index 03fa24cf3344..0a07af9d8e58 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa310.dts
@@ -104,7 +104,7 @@
 			status = "okay";
 
 			adt7476: adt7476a@2e {
-				compatible = "adt7476";
+				compatible = "adi,adt7476";
 				reg = <0x2e>;
 			};
 		};
diff --git a/arch/arm/boot/dts/kirkwood-nsa310a.dts b/arch/arm/boot/dts/kirkwood-nsa310a.dts
index a5e779452867..27ca6a79c48a 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310a.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa310a.dts
@@ -94,7 +94,7 @@
 			status = "okay";
 
 			lm85: lm85@2e {
-				compatible = "lm85";
+				compatible = "national,lm85";
 				reg = <0x2e>;
 			};
 		};
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
index b88da9392c32..0650beafc1de 100644
--- a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
@@ -40,7 +40,7 @@
 			pinctrl-names = "default";
 
 			s35390a: s35390a@30 {
-				compatible = "s35390a";
+				compatible = "sii,s35390a";
 				reg = <0x30>;
 			};
 		};
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
index b2f7cae06839..38520a287514 100644
--- a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
@@ -52,7 +52,7 @@
 			pinctrl-names = "default";
 
 			s24c02: s24c02@50 {
-				compatible = "24c02";
+				compatible = "atmel,24c02";
 				reg = <0x50>;
 			};
 		};
diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
index 95a849bf921f..0cb235a450b9 100644
--- a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
@@ -11,6 +11,7 @@
 /dts-v1/;
 #include "r8a7740.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pwm/pwm.h>
 
@@ -77,26 +78,26 @@
 
 		power-key {
 			gpios = <&pfc 99 GPIO_ACTIVE_LOW>;
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			label = "SW3";
 			gpio-key,wakeup;
 		};
 
 		back-key {
 			gpios = <&pfc 100 GPIO_ACTIVE_LOW>;
-			linux,code = <158>;
+			linux,code = <KEY_BACK>;
 			label = "SW4";
 		};
 
 		menu-key {
 			gpios = <&pfc 97 GPIO_ACTIVE_LOW>;
-			linux,code = <139>;
+			linux,code = <KEY_MENU>;
 			label = "SW5";
 		};
 
 		home-key {
 			gpios = <&pfc 98 GPIO_ACTIVE_LOW>;
-			linux,code = <102>;
+			linux,code = <KEY_HOME>;
 			label = "SW6";
 		};
 	};
@@ -117,6 +118,16 @@
 		};
 	};
 
+	i2c2: i2c@2 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		gpios = <&pfc 208 GPIO_ACTIVE_HIGH /* sda */
+			 &pfc 91 GPIO_ACTIVE_HIGH /* scl */
+			>;
+		i2c-gpio,delay-us = <5>;
+	};
+
 	backlight {
 		compatible = "pwm-backlight";
 		pwms = <&tpu 2 33333 PWM_POLARITY_INVERTED>;
@@ -166,6 +177,14 @@
 	};
 };
 
+&i2c2 {
+	status = "okay";
+	rtc@30 {
+		compatible = "seiko,s35390a";
+		reg = <0x30>;
+	};
+};
+
 &pfc {
 	pinctrl-0 = <&scifa1_pins>;
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 8280884bfa59..3834b94dc02a 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -28,7 +28,6 @@
 	gic: interrupt-controller@c2800000 {
 		compatible = "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
-		#address-cells = <1>;
 		interrupt-controller;
 		reg = <0xc2800000 0x1000>,
 		      <0xc2000000 0x1000>;
@@ -126,7 +125,7 @@
 	i2c0: i2c@fff20000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		compatible = "renesas,rmobile-iic";
+		compatible = "renesas,iic-r8a7740", "renesas,rmobile-iic";
 		reg = <0xfff20000 0x425>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 201 IRQ_TYPE_LEVEL_HIGH
@@ -139,7 +138,7 @@
 	i2c1: i2c@e6c20000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		compatible = "renesas,rmobile-iic";
+		compatible = "renesas,iic-r8a7740", "renesas,rmobile-iic";
 		reg = <0xe6c20000 0x425>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH
@@ -174,7 +173,7 @@
 	};
 
 	mmcif0: mmc@e6bd0000 {
-		compatible = "renesas,sh-mmcif";
+		compatible = "renesas,mmcif-r8a7740", "renesas,sh-mmcif";
 		reg = <0xe6bd0000 0x100>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH
@@ -220,7 +219,7 @@
 
 	sh_fsi2: sound@fe1f0000 {
 		#sound-dai-cells = <1>;
-		compatible = "renesas,sh_fsi2";
+		compatible = "renesas,fsi2-r8a7740", "renesas,sh_fsi2";
 		reg = <0xfe1f0000 0x400>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 9 0x4>;
diff --git a/arch/arm/boot/dts/r8a7778-bockw-reference.dts b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
index 06cda19dac6a..f76f6ec01e19 100644
--- a/arch/arm/boot/dts/r8a7778-bockw-reference.dts
+++ b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
@@ -109,4 +109,18 @@
 	pinctrl-0 = <&hspi0_pins>;
 	pinctrl-names = "default";
 	status = "okay";
+
+	flash: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,s25fl008k";
+		reg = <0>;
+		spi-max-frequency = <104000000>;
+		m25p,fast-read;
+
+		partition@0 {
+			label = "data(spi)";
+			reg = <0x00000000 0x00100000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index 85c5b3b99f5e..3c6fab5c9702 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -204,26 +204,32 @@
 	};
 
 	hspi0: spi@fffc7000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
 		reg = <0xfffc7000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi1: spi@fffc8000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
 		reg = <0xfffc8000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi2: spi@fffc6000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7778", "renesas,hspi";
 		reg = <0xfffc6000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 };
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index d0561d4c7c46..8b1a336ee401 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -256,26 +256,32 @@
 	};
 
 	hspi0: spi@fffc7000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
 		reg = <0xfffc7000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi1: spi@fffc8000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
 		reg = <0xfffc8000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	hspi2: spi@fffc6000 {
-		compatible = "renesas,hspi";
+		compatible = "renesas,hspi-r8a7779", "renesas,hspi";
 		reg = <0xfffc6000 0x18>;
-		interrupt-controller = <&gic>;
+		interrupt-parent = <&gic>;
 		interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
 		status = "disabled";
 	};
 };
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 6e99eb2df076..86d676f62942 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -12,6 +12,7 @@
 /dts-v1/;
 #include "r8a7790.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 
 / {
 	model = "Lager";
@@ -36,6 +37,39 @@
 		#size-cells = <1>;
 	};
 
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		button@1 {
+			linux,code = <KEY_1>;
+			label = "SW2-1";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+			gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+		};
+		button@2 {
+			linux,code = <KEY_2>;
+			label = "SW2-2";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+			gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
+		};
+		button@3 {
+			linux,code = <KEY_3>;
+			label = "SW2-3";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+			gpios = <&gpio1 26 GPIO_ACTIVE_LOW>;
+		};
+		button@4 {
+			linux,code = <KEY_4>;
+			label = "SW2-4";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+			gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
+		};
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		led6 {
@@ -141,12 +175,12 @@
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,gpios = "sdhi0_data4", "sdhi0_ctrl";
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
 		renesas,function = "sdhi0";
 	};
 
 	sdhi2_pins: sd2 {
-		renesas,gpios = "sdhi2_data4", "sdhi2_ctrl";
+		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
 		renesas,function = "sdhi2";
 	};
 
@@ -155,10 +189,16 @@
 		renesas,function = "mmc1";
 	};
 
-	qspi_pins: spi {
+	qspi_pins: spi0 {
 		renesas,groups = "qspi_ctrl", "qspi_data4";
 		renesas,function = "qspi";
 	};
+
+	msiof1_pins: spi2 {
+		renesas,groups = "msiof1_clk", "msiof1_sync", "msiof1_rx",
+				 "msiof1_tx";
+		renesas,function = "msiof1";
+	};
 };
 
 &ether {
@@ -173,6 +213,7 @@
 		reg = <1>;
 		interrupt-parent = <&irqc0>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		micrel,led-mode = <1>;
 	};
 };
 
@@ -190,7 +231,7 @@
 	status = "okay";
 };
 
-&spi {
+&qspi {
 	pinctrl-0 = <&qspi_pins>;
 	pinctrl-names = "default";
 
@@ -202,6 +243,8 @@
 		compatible = "spansion,s25fl512s";
 		reg = <0>;
 		spi-max-frequency = <30000000>;
+		spi-tx-bus-width = <4>;
+		spi-rx-bus-width = <4>;
 		m25p,fast-read;
 
 		partition@0 {
@@ -221,6 +264,22 @@
 	};
 };
 
+&msiof1 {
+	pinctrl-0 = <&msiof1_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	pmic: pmic@0 {
+		compatible = "renesas,r2a11302ft";
+		reg = <0>;
+		spi-max-frequency = <6000000>;
+		spi-cpol;
+		spi-cpha;
+	};
+
+};
+
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 618e5b537eaf..d38d70339149 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -24,6 +24,15 @@
 		i2c1 = &i2c1;
 		i2c2 = &i2c2;
 		i2c3 = &i2c3;
+		i2c4 = &iic0;
+		i2c5 = &iic1;
+		i2c6 = &iic2;
+		i2c7 = &iic3;
+		spi0 = &qspi;
+		spi1 = &msiof0;
+		spi2 = &msiof1;
+		spi3 = &msiof2;
+		spi4 = &msiof3;
 	};
 
 	cpus {
@@ -231,6 +240,46 @@
 		status = "disabled";
 	};
 
+	iic0: i2c@e6500000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,iic-r8a7790", "renesas,rmobile-iic";
+		reg = <0 0xe6500000 0 0x425>;
+		interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
+		status = "disabled";
+	};
+
+	iic1: i2c@e6510000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,iic-r8a7790", "renesas,rmobile-iic";
+		reg = <0 0xe6510000 0 0x425>;
+		interrupts = <0 175 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_IIC1>;
+		status = "disabled";
+	};
+
+	iic2: i2c@e6520000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,iic-r8a7790", "renesas,rmobile-iic";
+		reg = <0 0xe6520000 0 0x425>;
+		interrupts = <0 176 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_IIC2>;
+		status = "disabled";
+	};
+
+	iic3: i2c@e60b0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,iic-r8a7790", "renesas,rmobile-iic";
+		reg = <0 0xe60b0000 0 0x425>;
+		interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7790_CLK_IICDVFS>;
+		status = "disabled";
+	};
+
 	mmcif0: mmcif@ee200000 {
 		compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
 		reg = <0 0xee200000 0 0x80>;
@@ -673,7 +722,7 @@
 			renesas,clock-indices = <
 				R8A7790_CLK_TMU1 R8A7790_CLK_TMU3 R8A7790_CLK_TMU2
 				R8A7790_CLK_CMT0 R8A7790_CLK_TMU0 R8A7790_CLK_VSP1_DU1
-				R8A7790_CLK_VSP1_DU0 R8A7790_CLK_VSP1_RT R8A7790_CLK_VSP1_SY
+				R8A7790_CLK_VSP1_DU0 R8A7790_CLK_VSP1_R R8A7790_CLK_VSP1_S
 			>;
 			clock-output-names =
 				"tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1",
@@ -697,18 +746,19 @@
 		mstp3_clks: mstp3_clks@e615013c {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
-			clocks = <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, <&sd2_clk>,
-				 <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>,
-				 <&mmc0_clk>, <&rclk_clk>;
+			clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&sd3_clk>,
+				 <&sd2_clk>, <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, <&mmc0_clk>,
+				 <&hp_clk>, <&hp_clk>, <&rclk_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
-				R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
-				R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0
-				R8A7790_CLK_MMCIF0 R8A7790_CLK_CMT1
+				R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
+				R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0
+				R8A7790_CLK_IIC0 R8A7790_CLK_IIC1 R8A7790_CLK_CMT1
 			>;
 			clock-output-names =
-				"tpu0", "mmcif1", "sdhi3", "sdhi2",
-				"sdhi1", "sdhi0", "mmcif0", "cmt1";
+				"iic2", "tpu0", "mmcif1", "sdhi3",
+				"sdhi2", "sdhi1", "sdhi0", "mmcif0",
+				"iic0", "iic1", "cmt1";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -752,20 +802,20 @@
 		mstp9_clks: mstp9_clks@e6150994 {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>;
-			clocks = <&p_clk>, <&p_clk>, <&cpg_clocks R8A7790_CLK_QSPI>,
-				 <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>;
+			clocks = <&p_clk>, <&p_clk>, <&cpg_clocks R8A7790_CLK_QSPI>, <&cp_clk>,
+				 <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
-				R8A7790_CLK_RCAN1 R8A7790_CLK_RCAN0 R8A7790_CLK_QSPI_MOD
-				R8A7790_CLK_I2C3 R8A7790_CLK_I2C2 R8A7790_CLK_I2C1
-				R8A7790_CLK_I2C0
+				R8A7790_CLK_RCAN1 R8A7790_CLK_RCAN0 R8A7790_CLK_QSPI_MOD R8A7790_CLK_IICDVFS
+				R8A7790_CLK_I2C3 R8A7790_CLK_I2C2 R8A7790_CLK_I2C1 R8A7790_CLK_I2C0
 			>;
 			clock-output-names =
-				"rcan1", "rcan0", "qspi_mod", "i2c3", "i2c2", "i2c1", "i2c0";
+				"rcan1", "rcan0", "qspi_mod", "iic3",
+				"i2c3", "i2c2", "i2c1", "i2c0";
 		};
 	};
 
-	spi: spi@e6b10000 {
+	qspi: spi@e6b10000 {
 		compatible = "renesas,qspi-r8a7790", "renesas,qspi";
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
@@ -775,4 +825,44 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	msiof0: spi@e6e20000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6e20000 0 0x0064>;
+		interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof1: spi@e6e10000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6e10000 0 0x0064>;
+		interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof2: spi@e6e00000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6e00000 0 0x0064>;
+		interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof3: spi@e6c90000 {
+		compatible = "renesas,msiof-r8a7790";
+		reg = <0 0xe6c90000 0 0x0064>;
+		interrupts = <0 159 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index bdd73e6657b2..0d69813def85 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 #include "r8a7791.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 
 / {
 	model = "Koelsch";
@@ -40,51 +41,79 @@
 	gpio-keys {
 		compatible = "gpio-keys";
 
+		key-1 {
+			gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_1>;
+			label = "SW2-1";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-2 {
+			gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_2>;
+			label = "SW2-2";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-3 {
+			gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_3>;
+			label = "SW2-3";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
+		key-4 {
+			gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_4>;
+			label = "SW2-4";
+			gpio-key,wakeup;
+			debounce-interval = <20>;
+		};
 		key-a {
 			gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
-			linux,code = <30>;
+			linux,code = <KEY_A>;
 			label = "SW30";
 			gpio-key,wakeup;
 			debounce-interval = <20>;
 		};
 		key-b {
 			gpios = <&gpio7 1 GPIO_ACTIVE_LOW>;
-			linux,code = <48>;
+			linux,code = <KEY_B>;
 			label = "SW31";
 			gpio-key,wakeup;
 			debounce-interval = <20>;
 		};
 		key-c {
 			gpios = <&gpio7 2 GPIO_ACTIVE_LOW>;
-			linux,code = <46>;
+			linux,code = <KEY_C>;
 			label = "SW32";
 			gpio-key,wakeup;
 			debounce-interval = <20>;
 		};
 		key-d {
 			gpios = <&gpio7 3 GPIO_ACTIVE_LOW>;
-			linux,code = <32>;
+			linux,code = <KEY_D>;
 			label = "SW33";
 			gpio-key,wakeup;
 			debounce-interval = <20>;
 		};
 		key-e {
 			gpios = <&gpio7 4 GPIO_ACTIVE_LOW>;
-			linux,code = <18>;
+			linux,code = <KEY_E>;
 			label = "SW34";
 			gpio-key,wakeup;
 			debounce-interval = <20>;
 		};
 		key-f {
 			gpios = <&gpio7 5 GPIO_ACTIVE_LOW>;
-			linux,code = <33>;
+			linux,code = <KEY_F>;
 			label = "SW35";
 			gpio-key,wakeup;
 			debounce-interval = <20>;
 		};
 		key-g {
 			gpios = <&gpio7 6 GPIO_ACTIVE_LOW>;
-			linux,code = <34>;
+			linux,code = <KEY_G>;
 			label = "SW36";
 			gpio-key,wakeup;
 			debounce-interval = <20>;
@@ -195,11 +224,16 @@
 	};
 };
 
+&i2c6 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
 &pfc {
 	pinctrl-0 = <&du_pins &scif0_pins &scif1_pins>;
 	pinctrl-names = "default";
 
-	i2c2_pins: i2c {
+	i2c2_pins: i2c2 {
 		renesas,groups = "i2c2";
 		renesas,function = "i2c2";
 	};
@@ -230,24 +264,30 @@
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,gpios = "sdhi0_data4", "sdhi0_ctrl";
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
 		renesas,function = "sdhi0";
 	};
 
 	sdhi1_pins: sd1 {
-		renesas,gpios = "sdhi1_data4", "sdhi1_ctrl";
+		renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
 		renesas,function = "sdhi1";
 	};
 
 	sdhi2_pins: sd2 {
-		renesas,gpios = "sdhi2_data4", "sdhi2_ctrl";
+		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
 		renesas,function = "sdhi2";
 	};
 
-	qspi_pins: spi {
+	qspi_pins: spi0 {
 		renesas,groups = "qspi_ctrl", "qspi_data4";
 		renesas,function = "qspi";
 	};
+
+	msiof0_pins: spi1 {
+		renesas,groups = "msiof0_clk", "msiof0_sync", "msiof0_rx",
+				 "msiof0_tx";
+		renesas,function = "msiof0";
+	};
 };
 
 &ether {
@@ -262,6 +302,7 @@
 		reg = <1>;
 		interrupt-parent = <&irqc0>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		micrel,led-mode = <1>;
 	};
 };
 
@@ -301,7 +342,7 @@
 	status = "okay";
 };
 
-&spi {
+&qspi {
 	pinctrl-0 = <&qspi_pins>;
 	pinctrl-names = "default";
 
@@ -313,6 +354,8 @@
 		compatible = "spansion,s25fl512s";
 		reg = <0>;
 		spi-max-frequency = <30000000>;
+		spi-tx-bus-width = <4>;
+		spi-rx-bus-width = <4>;
 		m25p,fast-read;
 
 		partition@0 {
@@ -331,3 +374,18 @@
 		};
 	};
 };
+
+&msiof0 {
+	pinctrl-0 = <&msiof0_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	pmic: pmic@0 {
+		compatible = "renesas,r2a11302ft";
+		reg = <0>;
+		spi-max-frequency = <6000000>;
+		spi-cpol;
+		spi-cpha;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 46181708e59c..44f03444ef74 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -27,6 +27,13 @@
 		i2c3 = &i2c3;
 		i2c4 = &i2c4;
 		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
+		i2c8 = &i2c8;
+		spi0 = &qspi;
+		spi1 = &msiof0;
+		spi2 = &msiof1;
+		spi3 = &msiof2;
 	};
 
 	cpus {
@@ -37,14 +44,14 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0>;
-			clock-frequency = <1300000000>;
+			clock-frequency = <1500000000>;
 		};
 
 		cpu1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <1>;
-			clock-frequency = <1300000000>;
+			clock-frequency = <1500000000>;
 		};
 	};
 
@@ -180,6 +187,7 @@
 			     <0 17 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	/* The memory map in the User's Manual maps the cores to bus numbers */
 	i2c0: i2c@e6508000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -231,6 +239,7 @@
 	};
 
 	i2c5: i2c@e6528000 {
+		/* doesn't need pinmux */
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "renesas,i2c-r8a7791";
@@ -240,6 +249,37 @@
 		status = "disabled";
 	};
 
+	i2c6: i2c@e60b0000 {
+		/* doesn't need pinmux */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,iic-r8a7791", "renesas,rmobile-iic";
+		reg = <0 0xe60b0000 0 0x425>;
+		interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7791_CLK_IICDVFS>;
+		status = "disabled";
+	};
+
+	i2c7: i2c@e6500000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,iic-r8a7791", "renesas,rmobile-iic";
+		reg = <0 0xe6500000 0 0x425>;
+		interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_IIC0>;
+		status = "disabled";
+	};
+
+	i2c8: i2c@e6510000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,iic-r8a7791", "renesas,rmobile-iic";
+		reg = <0 0xe6510000 0 0x425>;
+		interrupts = <0 175 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_IIC1>;
+		status = "disabled";
+	};
+
 	pfc: pfc@e6060000 {
 		compatible = "renesas,pfc-r8a7791";
 		reg = <0 0xe6060000 0 0x250>;
@@ -688,7 +728,7 @@
 			renesas,clock-indices = <
 				R8A7791_CLK_TMU1 R8A7791_CLK_TMU3 R8A7791_CLK_TMU2
 				R8A7791_CLK_CMT0 R8A7791_CLK_TMU0 R8A7791_CLK_VSP1_DU1
-				R8A7791_CLK_VSP1_DU0 R8A7791_CLK_VSP1_SY
+				R8A7791_CLK_VSP1_DU0 R8A7791_CLK_VSP1_S
 			>;
 			clock-output-names =
 				"tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1",
@@ -712,15 +752,16 @@
 		mstp3_clks: mstp3_clks@e615013c {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
-			clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>,
-				<&cpg_clocks R8A7791_CLK_SD0>, <&mmc0_clk>, <&rclk_clk>;
+			clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7791_CLK_SD0>,
+				 <&mmc0_clk>, <&hp_clk>, <&hp_clk>, <&rclk_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
-				R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1
-				R8A7791_CLK_SDHI0 R8A7791_CLK_MMCIF0 R8A7791_CLK_CMT1
+				R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1 R8A7791_CLK_SDHI0
+				R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_IIC1 R8A7791_CLK_CMT1
 			>;
 			clock-output-names =
-				"tpu0", "sdhi2", "sdhi1", "sdhi0", "mmcif0", "cmt1";
+				"tpu0", "sdhi2", "sdhi1", "sdhi0",
+				"mmcif0", "i2c7", "i2c8", "cmt1";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -733,19 +774,19 @@
 		mstp7_clks: mstp7_clks@e615014c {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
-			clocks = <&mp_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
+			clocks = <&mp_clk>,  <&mp_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
 				 <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
 				 <&zx_clk>, <&zx_clk>, <&zx_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
-				R8A7791_CLK_HSUSB R8A7791_CLK_HSCIF2 R8A7791_CLK_SCIF5
+				R8A7791_CLK_EHCI R8A7791_CLK_HSUSB R8A7791_CLK_HSCIF2 R8A7791_CLK_SCIF5
 				R8A7791_CLK_SCIF4 R8A7791_CLK_HSCIF1 R8A7791_CLK_HSCIF0
 				R8A7791_CLK_SCIF3 R8A7791_CLK_SCIF2 R8A7791_CLK_SCIF1
 				R8A7791_CLK_SCIF0 R8A7791_CLK_DU1 R8A7791_CLK_DU0
 				R8A7791_CLK_LVDS0
 			>;
 			clock-output-names =
-				"hsusb", "hscif2", "scif5", "scif4", "hscif1", "hscif0",
+				"ehci", "hsusb", "hscif2", "scif5", "scif4", "hscif1", "hscif0",
 				"scif3", "scif2", "scif1", "scif0", "du1", "du0", "lvds0";
 		};
 		mstp8_clks: mstp8_clks@e6150990 {
@@ -764,17 +805,17 @@
 		mstp9_clks: mstp9_clks@e6150994 {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>;
-			clocks = <&p_clk>, <&p_clk>, <&cpg_clocks R8A7791_CLK_QSPI>,
-				 <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
-				 <&p_clk>;
+			clocks = <&p_clk>, <&p_clk>, <&cpg_clocks R8A7791_CLK_QSPI>, <&hp_clk>,
+				 <&cp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>,
+				 <&hp_clk>, <&hp_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
-				R8A7791_CLK_RCAN1 R8A7791_CLK_RCAN0 R8A7791_CLK_QSPI_MOD
-				R8A7791_CLK_I2C5 R8A7791_CLK_I2C4 R8A7791_CLK_I2C3
-				R8A7791_CLK_I2C2 R8A7791_CLK_I2C1 R8A7791_CLK_I2C0
+				R8A7791_CLK_RCAN1 R8A7791_CLK_RCAN0 R8A7791_CLK_QSPI_MOD R8A7791_CLK_I2C5
+				R8A7791_CLK_IICDVFS R8A7791_CLK_I2C4 R8A7791_CLK_I2C3 R8A7791_CLK_I2C2
+				R8A7791_CLK_I2C1 R8A7791_CLK_I2C0
 			>;
 			clock-output-names =
-				"rcan1", "rcan0", "qspi_mod", "i2c5", "i2c4", "i2c3",
+				"rcan1", "rcan0", "qspi_mod", "i2c5", "i2c6", "i2c4", "i2c3",
 				"i2c2", "i2c1", "i2c0";
 		};
 		mstp11_clks: mstp11_clks@e615099c {
@@ -789,7 +830,7 @@
 		};
 	};
 
-	spi: spi@e6b10000 {
+	qspi: spi@e6b10000 {
 		compatible = "renesas,qspi-r8a7791", "renesas,qspi";
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
@@ -799,4 +840,34 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	msiof0: spi@e6e20000 {
+		compatible = "renesas,msiof-r8a7791";
+		reg = <0 0xe6e20000 0 0x0064>;
+		interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof1: spi@e6e10000 {
+		compatible = "renesas,msiof-r8a7791";
+		reg = <0 0xe6e10000 0 0x0064>;
+		interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_MSIOF1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	msiof2: spi@e6e00000 {
+		compatible = "renesas,msiof-r8a7791";
+		reg = <0 0xe6e00000 0 0x0064>;
+		interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks R8A7791_CLK_MSIOF2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
index eb8886b535e4..a99171c8a782 100644
--- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
+++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 #include "sh73a0.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
@@ -112,43 +113,43 @@
 
 		back-key {
 			gpios = <&pcf8575 8 GPIO_ACTIVE_LOW>;
-			linux,code = <158>;
+			linux,code = <KEY_BACK>;
 			label = "SW3";
 		};
 
 		right-key {
 			gpios = <&pcf8575 9 GPIO_ACTIVE_LOW>;
-			linux,code = <106>;
+			linux,code = <KEY_RIGHT>;
 			label = "SW2-R";
 		};
 
 		left-key {
 			gpios = <&pcf8575 10 GPIO_ACTIVE_LOW>;
-			linux,code = <105>;
+			linux,code = <KEY_LEFT>;
 			label = "SW2-L";
 		};
 
 		enter-key {
 			gpios = <&pcf8575 11 GPIO_ACTIVE_LOW>;
-			linux,code = <28>;
+			linux,code = <KEY_ENTER>;
 			label = "SW2-P";
 		};
 
 		up-key {
 			gpios = <&pcf8575 12 GPIO_ACTIVE_LOW>;
-			linux,code = <103>;
+			linux,code = <KEY_UP>;
 			label = "SW2-U";
 		};
 
 		down-key {
 			gpios = <&pcf8575 13 GPIO_ACTIVE_LOW>;
-			linux,code = <108>;
+			linux,code = <KEY_DOWN>;
 			label = "SW2-D";
 		};
 
 		home-key {
 			gpios = <&pcf8575 14 GPIO_ACTIVE_LOW>;
-			linux,code = <102>;
+			linux,code = <KEY_HOME>;
 			label = "SW1";
 		};
 	};
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index b7bd3b9a6753..5ecf552e1c00 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -34,7 +34,6 @@
 	gic: interrupt-controller@f0001000 {
 		compatible = "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
-		#address-cells = <1>;
 		interrupt-controller;
 		reg = <0xf0001000 0x1000>,
 		      <0xf0000100 0x100>;
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
new file mode 100644
index 000000000000..dd3076d94727
--- /dev/null
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -0,0 +1,1791 @@
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "tegra124.dtsi"
+
+/ {
+	model = "NVIDIA Tegra124 Jetson TK1";
+	compatible = "nvidia,jetson-tk1", "nvidia,tegra124";
+
+	aliases {
+		rtc0 = "/i2c@0,7000d000/pmic@40";
+		rtc1 = "/rtc@0,7000e000";
+	};
+
+	memory {
+		reg = <0x0 0x80000000 0x0 0x80000000>;
+	};
+
+	pinmux: pinmux@0,70000868 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&state_default>;
+
+		state_default: pinmux {
+			clk_32k_out_pa0 {
+				nvidia,pins = "clk_32k_out_pa0";
+				nvidia,function = "soc";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			uart3_cts_n_pa1 {
+				nvidia,pins = "uart3_cts_n_pa1";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap2_fs_pa2 {
+				nvidia,pins = "dap2_fs_pa2";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap2_sclk_pa3 {
+				nvidia,pins = "dap2_sclk_pa3";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap2_din_pa4 {
+				nvidia,pins = "dap2_din_pa4";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap2_dout_pa5 {
+				nvidia,pins = "dap2_dout_pa5";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_clk_pa6 {
+				nvidia,pins = "sdmmc3_clk_pa6";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_cmd_pa7 {
+				nvidia,pins = "sdmmc3_cmd_pa7";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pb0 {
+				nvidia,pins = "pb0";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pb1 {
+				nvidia,pins = "pb1";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_dat3_pb4 {
+				nvidia,pins = "sdmmc3_dat3_pb4";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_dat2_pb5 {
+				nvidia,pins = "sdmmc3_dat2_pb5";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_dat1_pb6 {
+				nvidia,pins = "sdmmc3_dat1_pb6";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_dat0_pb7 {
+				nvidia,pins = "sdmmc3_dat0_pb7";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			uart3_rts_n_pc0 {
+				nvidia,pins = "uart3_rts_n_pc0";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			uart2_txd_pc2 {
+				nvidia,pins = "uart2_txd_pc2";
+				nvidia,function = "irda";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			uart2_rxd_pc3 {
+				nvidia,pins = "uart2_rxd_pc3";
+				nvidia,function = "irda";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			gen1_i2c_scl_pc4 {
+				nvidia,pins = "gen1_i2c_scl_pc4";
+				nvidia,function = "i2c1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			gen1_i2c_sda_pc5 {
+				nvidia,pins = "gen1_i2c_sda_pc5";
+				nvidia,function = "i2c1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			pc7 {
+				nvidia,pins = "pc7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pg0 {
+				nvidia,pins = "pg0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pg1 {
+				nvidia,pins = "pg1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pg2 {
+				nvidia,pins = "pg2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pg3 {
+				nvidia,pins = "pg3";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pg4 {
+				nvidia,pins = "pg4";
+				nvidia,function = "spi4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pg5 {
+				nvidia,pins = "pg5";
+				nvidia,function = "spi4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pg6 {
+				nvidia,pins = "pg6";
+				nvidia,function = "spi4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pg7 {
+				nvidia,pins = "pg7";
+				nvidia,function = "spi4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ph0 {
+				nvidia,pins = "ph0";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ph1 {
+				nvidia,pins = "ph1";
+				nvidia,function = "pwm1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ph2 {
+				nvidia,pins = "ph2";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ph3 {
+				nvidia,pins = "ph3";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ph4 {
+				nvidia,pins = "ph4";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ph5 {
+				nvidia,pins = "ph5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ph6 {
+				nvidia,pins = "ph6";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ph7 {
+				nvidia,pins = "ph7";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pi0 {
+				nvidia,pins = "pi0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pi1 {
+				nvidia,pins = "pi1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pi2 {
+				nvidia,pins = "pi2";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pi3 {
+				nvidia,pins = "pi3";
+				nvidia,function = "spi4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pi4 {
+				nvidia,pins = "pi4";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pi5 {
+				nvidia,pins = "pi5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pi6 {
+				nvidia,pins = "pi6";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pi7 {
+				nvidia,pins = "pi7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pj0 {
+				nvidia,pins = "pj0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pj2 {
+				nvidia,pins = "pj2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			uart2_cts_n_pj5 {
+				nvidia,pins = "uart2_cts_n_pj5";
+				nvidia,function = "uartb";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			uart2_rts_n_pj6 {
+				nvidia,pins = "uart2_rts_n_pj6";
+				nvidia,function = "uartb";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pj7 {
+				nvidia,pins = "pj7";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pk0 {
+				nvidia,pins = "pk0";
+				nvidia,function = "soc";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pk1 {
+				nvidia,pins = "pk1";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pk2 {
+				nvidia,pins = "pk2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pk3 {
+				nvidia,pins = "pk3";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pk4 {
+				nvidia,pins = "pk4";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			spdif_out_pk5 {
+				nvidia,pins = "spdif_out_pk5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			spdif_in_pk6 {
+				nvidia,pins = "spdif_in_pk6";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pk7 {
+				nvidia,pins = "pk7";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap1_fs_pn0 {
+				nvidia,pins = "dap1_fs_pn0";
+				nvidia,function = "i2s0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap1_din_pn1 {
+				nvidia,pins = "dap1_din_pn1";
+				nvidia,function = "i2s0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap1_dout_pn2 {
+				nvidia,pins = "dap1_dout_pn2";
+				nvidia,function = "sata";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap1_sclk_pn3 {
+				nvidia,pins = "dap1_sclk_pn3";
+				nvidia,function = "i2s0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			usb_vbus_en0_pn4 {
+				nvidia,pins = "usb_vbus_en0_pn4";
+				nvidia,function = "usb";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			usb_vbus_en1_pn5 {
+				nvidia,pins = "usb_vbus_en1_pn5";
+				nvidia,function = "usb";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			hdmi_int_pn7 {
+				nvidia,pins = "hdmi_int_pn7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+			};
+			ulpi_data7_po0 {
+				nvidia,pins = "ulpi_data7_po0";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ulpi_data0_po1 {
+				nvidia,pins = "ulpi_data0_po1";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ulpi_data1_po2 {
+				nvidia,pins = "ulpi_data1_po2";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ulpi_data2_po3 {
+				nvidia,pins = "ulpi_data2_po3";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ulpi_data3_po4 {
+				nvidia,pins = "ulpi_data3_po4";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ulpi_data4_po5 {
+				nvidia,pins = "ulpi_data4_po5";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ulpi_data5_po6 {
+				nvidia,pins = "ulpi_data5_po6";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ulpi_data6_po7 {
+				nvidia,pins = "ulpi_data6_po7";
+				nvidia,function = "ulpi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap3_fs_pp0 {
+				nvidia,pins = "dap3_fs_pp0";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap3_din_pp1 {
+				nvidia,pins = "dap3_din_pp1";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap3_dout_pp2 {
+				nvidia,pins = "dap3_dout_pp2";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap3_sclk_pp3 {
+				nvidia,pins = "dap3_sclk_pp3";
+				nvidia,function = "rsvd3";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap4_fs_pp4 {
+				nvidia,pins = "dap4_fs_pp4";
+				nvidia,function = "i2s3";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap4_din_pp5 {
+				nvidia,pins = "dap4_din_pp5";
+				nvidia,function = "i2s3";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap4_dout_pp6 {
+				nvidia,pins = "dap4_dout_pp6";
+				nvidia,function = "i2s3";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap4_sclk_pp7 {
+				nvidia,pins = "dap4_sclk_pp7";
+				nvidia,function = "i2s3";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_col0_pq0 {
+				nvidia,pins = "kb_col0_pq0";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_col1_pq1 {
+				nvidia,pins = "kb_col1_pq1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_col2_pq2 {
+				nvidia,pins = "kb_col2_pq2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_col3_pq3 {
+				nvidia,pins = "kb_col3_pq3";
+				nvidia,function = "kbc";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_col4_pq4 {
+				nvidia,pins = "kb_col4_pq4";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_col5_pq5 {
+				nvidia,pins = "kb_col5_pq5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_col6_pq6 {
+				nvidia,pins = "kb_col6_pq6";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_col7_pq7 {
+				nvidia,pins = "kb_col7_pq7";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row0_pr0 {
+				nvidia,pins = "kb_row0_pr0";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row1_pr1 {
+				nvidia,pins = "kb_row1_pr1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row2_pr2 {
+				nvidia,pins = "kb_row2_pr2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row3_pr3 {
+				nvidia,pins = "kb_row3_pr3";
+				nvidia,function = "sys";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row4_pr4 {
+				nvidia,pins = "kb_row4_pr4";
+				nvidia,function = "rsvd3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row5_pr5 {
+				nvidia,pins = "kb_row5_pr5";
+				nvidia,function = "rsvd3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row6_pr6 {
+				nvidia,pins = "kb_row6_pr6";
+				nvidia,function = "displaya_alt";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row7_pr7 {
+				nvidia,pins = "kb_row7_pr7";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row8_ps0 {
+				nvidia,pins = "kb_row8_ps0";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row9_ps1 {
+				nvidia,pins = "kb_row9_ps1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row10_ps2 {
+				nvidia,pins = "kb_row10_ps2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row11_ps3 {
+				nvidia,pins = "kb_row11_ps3";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row12_ps4 {
+				nvidia,pins = "kb_row12_ps4";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row13_ps5 {
+				nvidia,pins = "kb_row13_ps5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row14_ps6 {
+				nvidia,pins = "kb_row14_ps6";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row15_ps7 {
+				nvidia,pins = "kb_row15_ps7";
+				nvidia,function = "soc";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			kb_row16_pt0 {
+				nvidia,pins = "kb_row16_pt0";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			kb_row17_pt1 {
+				nvidia,pins = "kb_row17_pt1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			gen2_i2c_scl_pt5 {
+				nvidia,pins = "gen2_i2c_scl_pt5";
+				nvidia,function = "i2c2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			gen2_i2c_sda_pt6 {
+				nvidia,pins = "gen2_i2c_sda_pt6";
+				nvidia,function = "i2c2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_cmd_pt7 {
+				nvidia,pins = "sdmmc4_cmd_pt7";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pu0 {
+				nvidia,pins = "pu0";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pu1 {
+				nvidia,pins = "pu1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pu2 {
+				nvidia,pins = "pu2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pu3 {
+				nvidia,pins = "pu3";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pu4 {
+				nvidia,pins = "pu4";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pu5 {
+				nvidia,pins = "pu5";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pu6 {
+				nvidia,pins = "pu6";
+				nvidia,function = "rsvd3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pv0 {
+				nvidia,pins = "pv0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pv1 {
+				nvidia,pins = "pv1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_cd_n_pv2 {
+				nvidia,pins = "sdmmc3_cd_n_pv2";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc1_wp_n_pv3 {
+				nvidia,pins = "sdmmc1_wp_n_pv3";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ddc_scl_pv4 {
+				nvidia,pins = "ddc_scl_pv4";
+				nvidia,function = "i2c4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+			};
+			ddc_sda_pv5 {
+				nvidia,pins = "ddc_sda_pv5";
+				nvidia,function = "i2c4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+			};
+			gpio_w2_aud_pw2 {
+				nvidia,pins = "gpio_w2_aud_pw2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			gpio_w3_aud_pw3 {
+				nvidia,pins = "gpio_w3_aud_pw3";
+				nvidia,function = "spi6";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dap_mclk1_pw4 {
+				nvidia,pins = "dap_mclk1_pw4";
+				nvidia,function = "extperiph1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			clk2_out_pw5 {
+				nvidia,pins = "clk2_out_pw5";
+				nvidia,function = "extperiph2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			uart3_txd_pw6 {
+				nvidia,pins = "uart3_txd_pw6";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			uart3_rxd_pw7 {
+				nvidia,pins = "uart3_rxd_pw7";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dvfs_pwm_px0 {
+				nvidia,pins = "dvfs_pwm_px0";
+				nvidia,function = "cldvfs";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			gpio_x1_aud_px1 {
+				nvidia,pins = "gpio_x1_aud_px1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dvfs_clk_px2 {
+				nvidia,pins = "dvfs_clk_px2";
+				nvidia,function = "cldvfs";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			gpio_x3_aud_px3 {
+				nvidia,pins = "gpio_x3_aud_px3";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			gpio_x4_aud_px4 {
+				nvidia,pins = "gpio_x4_aud_px4";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			gpio_x5_aud_px5 {
+				nvidia,pins = "gpio_x5_aud_px5";
+				nvidia,function = "rsvd4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			gpio_x6_aud_px6 {
+				nvidia,pins = "gpio_x6_aud_px6";
+				nvidia,function = "gmi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			gpio_x7_aud_px7 {
+				nvidia,pins = "gpio_x7_aud_px7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ulpi_clk_py0 {
+				nvidia,pins = "ulpi_clk_py0";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ulpi_dir_py1 {
+				nvidia,pins = "ulpi_dir_py1";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			ulpi_nxt_py2 {
+				nvidia,pins = "ulpi_nxt_py2";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			ulpi_stp_py3 {
+				nvidia,pins = "ulpi_stp_py3";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_dat3_py4 {
+				nvidia,pins = "sdmmc1_dat3_py4";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc1_dat2_py5 {
+				nvidia,pins = "sdmmc1_dat2_py5";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc1_dat1_py6 {
+				nvidia,pins = "sdmmc1_dat1_py6";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc1_dat0_py7 {
+				nvidia,pins = "sdmmc1_dat0_py7";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc1_clk_pz0 {
+				nvidia,pins = "sdmmc1_clk_pz0";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc1_cmd_pz1 {
+				nvidia,pins = "sdmmc1_cmd_pz1";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pwr_i2c_scl_pz6 {
+				nvidia,pins = "pwr_i2c_scl_pz6";
+				nvidia,function = "i2cpwr";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			pwr_i2c_sda_pz7 {
+				nvidia,pins = "pwr_i2c_sda_pz7";
+				nvidia,function = "i2cpwr";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat0_paa0 {
+				nvidia,pins = "sdmmc4_dat0_paa0";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat1_paa1 {
+				nvidia,pins = "sdmmc4_dat1_paa1";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat2_paa2 {
+				nvidia,pins = "sdmmc4_dat2_paa2";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat3_paa3 {
+				nvidia,pins = "sdmmc4_dat3_paa3";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat4_paa4 {
+				nvidia,pins = "sdmmc4_dat4_paa4";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat5_paa5 {
+				nvidia,pins = "sdmmc4_dat5_paa5";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat6_paa6 {
+				nvidia,pins = "sdmmc4_dat6_paa6";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_dat7_paa7 {
+				nvidia,pins = "sdmmc4_dat7_paa7";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pbb0 {
+				nvidia,pins = "pbb0";
+				nvidia,function = "vimclk2_alt";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			cam_i2c_scl_pbb1 {
+				nvidia,pins = "cam_i2c_scl_pbb1";
+				nvidia,function = "i2c3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			cam_i2c_sda_pbb2 {
+				nvidia,pins = "cam_i2c_sda_pbb2";
+				nvidia,function = "i2c3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			pbb3 {
+				nvidia,pins = "pbb3";
+				nvidia,function = "vgp3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pbb4 {
+				nvidia,pins = "pbb4";
+				nvidia,function = "vgp4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pbb5 {
+				nvidia,pins = "pbb5";
+				nvidia,function = "rsvd3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pbb6 {
+				nvidia,pins = "pbb6";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pbb7 {
+				nvidia,pins = "pbb7";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			cam_mclk_pcc0 {
+				nvidia,pins = "cam_mclk_pcc0";
+				nvidia,function = "vi_alt3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pcc1 {
+				nvidia,pins = "pcc1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			pcc2 {
+				nvidia,pins = "pcc2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc4_clk_pcc4 {
+				nvidia,pins = "sdmmc4_clk_pcc4";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			clk2_req_pcc5 {
+				nvidia,pins = "clk2_req_pcc5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			clk3_out_pee0 {
+				nvidia,pins = "clk3_out_pee0";
+				nvidia,function = "extperiph3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			clk3_req_pee1 {
+				nvidia,pins = "clk3_req_pee1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap_mclk1_req_pee2 {
+				nvidia,pins = "dap_mclk1_req_pee2";
+				nvidia,function = "sata";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			hdmi_cec_pee3 {
+				nvidia,pins = "hdmi_cec_pee3";
+				nvidia,function = "cec";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_clk_lb_out_pee4 {
+				nvidia,pins = "sdmmc3_clk_lb_out_pee4";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			sdmmc3_clk_lb_in_pee5 {
+				nvidia,pins = "sdmmc3_clk_lb_in_pee5";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			dp_hpd_pff0 {
+				nvidia,pins = "dp_hpd_pff0";
+				nvidia,function = "dp";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			usb_vbus_en2_pff1 {
+				nvidia,pins = "usb_vbus_en2_pff1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pff2 {
+				nvidia,pins = "pff2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			core_pwr_req {
+				nvidia,pins = "core_pwr_req";
+				nvidia,function = "pwron";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			cpu_pwr_req {
+				nvidia,pins = "cpu_pwr_req";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			pwr_int_n {
+				nvidia,pins = "pwr_int_n";
+				nvidia,function = "pmi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			reset_out_n {
+				nvidia,pins = "reset_out_n";
+				nvidia,function = "reset_out_n";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			owr {
+				nvidia,pins = "owr";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+			};
+			clk_32k_in {
+				nvidia,pins = "clk_32k_in";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+			};
+			jtag_rtck {
+				nvidia,pins = "jtag_rtck";
+				nvidia,function = "rtck";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+		};
+	};
+
+	/* DB9 serial port */
+	serial@0,70006300 {
+		status = "okay";
+	};
+
+	/* Expansion GEN1_I2C_*, mini-PCIe I2C, on-board components */
+	i2c@0,7000c000 {
+		status = "okay";
+		clock-frequency = <100000>;
+
+		rt5640: audio-codec@1c {
+			compatible = "realtek,rt5640";
+			reg = <0x1c>;
+			interrupt-parent = <&gpio>;
+			interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
+			realtek,ldo1-en-gpios =
+				<&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_HIGH>;
+		};
+
+		temperature-sensor@4c {
+			compatible = "ti,tmp451";
+			reg = <0x4c>;
+			interrupt-parent = <&gpio>;
+			interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
+		};
+
+		eeprom@56 {
+			compatible = "atmel,24c02";
+			reg = <0x56>;
+			pagesize = <8>;
+		};
+	};
+
+	/* Expansion GEN2_I2C_* */
+	i2c@0,7000c400 {
+		status = "okay";
+		clock-frequency = <100000>;
+	};
+
+	/* Expansion CAM_I2C_* */
+	i2c@0,7000c500 {
+		status = "okay";
+		clock-frequency = <100000>;
+	};
+
+	/* HDMI DDC */
+	i2c@0,7000c700 {
+		status = "okay";
+		clock-frequency = <100000>;
+	};
+
+	/* Expansion PWR_I2C_*, on-board components */
+	i2c@0,7000d000 {
+		status = "okay";
+		clock-frequency = <400000>;
+
+		pmic: pmic@40 {
+			compatible = "ams,as3722";
+			reg = <0x40>;
+			interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+
+			ams,system-power-controller;
+
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&as3722_default>;
+
+			as3722_default: pinmux {
+				gpio0 {
+					pins = "gpio0";
+					function = "gpio";
+					bias-pull-down;
+				};
+
+				gpio1_2_4_7 {
+					pins = "gpio1", "gpio2", "gpio4", "gpio7";
+					function = "gpio";
+					bias-pull-up;
+				};
+
+				gpio3_5_6 {
+					pins = "gpio3", "gpio5", "gpio6";
+					bias-high-impedance;
+				};
+			};
+
+			regulators {
+				vsup-sd2-supply = <&vdd_5v0_sys>;
+				vsup-sd3-supply = <&vdd_5v0_sys>;
+				vsup-sd4-supply = <&vdd_5v0_sys>;
+				vsup-sd5-supply = <&vdd_5v0_sys>;
+				vin-ldo0-supply = <&vdd_1v35_lp0>;
+				vin-ldo1-6-supply = <&vdd_3v3_run>;
+				vin-ldo2-5-7-supply = <&vddio_1v8>;
+				vin-ldo3-4-supply = <&vdd_3v3_sys>;
+				vin-ldo9-10-supply = <&vdd_5v0_sys>;
+				vin-ldo11-supply = <&vdd_3v3_run>;
+
+				sd0 {
+					regulator-name = "+VDD_CPU_AP";
+					regulator-min-microvolt = <700000>;
+					regulator-max-microvolt = <1400000>;
+					regulator-min-microamp = <3500000>;
+					regulator-max-microamp = <3500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					ams,external-control = <2>;
+				};
+
+				sd1 {
+					regulator-name = "+VDD_CORE";
+					regulator-min-microvolt = <700000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-min-microamp = <2500000>;
+					regulator-max-microamp = <2500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					ams,external-control = <1>;
+				};
+
+				vdd_1v35_lp0: sd2 {
+					regulator-name = "+1.35V_LP0(sd2)";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				sd3 {
+					regulator-name = "+1.35V_LP0(sd3)";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				sd4 {
+					regulator-name = "+1.05V_RUN";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				vddio_1v8: sd5 {
+					regulator-name = "+1.8V_VDDIO";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				sd6 {
+					regulator-name = "+VDD_GPU_AP";
+					regulator-min-microvolt = <650000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-min-microamp = <3500000>;
+					regulator-max-microamp = <3500000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo0 {
+					regulator-name = "+1.05V_RUN_AVDD";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					regulator-boot-on;
+					regulator-always-on;
+					ams,external-control = <1>;
+				};
+
+				ldo1 {
+					regulator-name = "+1.8V_RUN_CAM";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo2 {
+					regulator-name = "+1.2V_GEN_AVDD";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo3 {
+					regulator-name = "+1.05V_LP0_VDD_RTC";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-boot-on;
+					regulator-always-on;
+					ams,enable-tracking;
+				};
+
+				ldo4 {
+					regulator-name = "+2.8V_RUN_CAM";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo5 {
+					regulator-name = "+1.2V_RUN_CAM_FRONT";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				vddio_sdmmc3: ldo6 {
+					regulator-name = "+VDDIO_SDMMC3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo7 {
+					regulator-name = "+1.05V_RUN_CAM_REAR";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				ldo9 {
+					regulator-name = "+3.3V_RUN_TOUCH";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo10 {
+					regulator-name = "+2.8V_RUN_CAM_AF";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo11 {
+					regulator-name = "+1.8V_RUN_VPP_FUSE";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+			};
+		};
+	};
+
+	/* Expansion TS_SPI_* */
+	spi@0,7000d400 {
+		status = "okay";
+	};
+
+	/* Internal SPI */
+	spi@0,7000da00 {
+		status = "okay";
+		spi-max-frequency = <25000000>;
+		spi-flash@0 {
+			compatible = "winbond,w25q32dw";
+			reg = <0>;
+			spi-max-frequency = <20000000>;
+		};
+	};
+
+	pmc@0,7000e400 {
+		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <1>;
+		nvidia,cpu-pwr-good-time = <500>;
+		nvidia,cpu-pwr-off-time = <300>;
+		nvidia,core-pwr-good-time = <641 3845>;
+		nvidia,core-pwr-off-time = <61036>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
+	};
+
+	/* SD card */
+	sdhci@0,700b0400 {
+		status = "okay";
+		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
+		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
+		bus-width = <4>;
+		vqmmc-supply = <&vddio_sdmmc3>;
+	};
+
+	/* eMMC */
+	sdhci@0,700b0600 {
+		status = "okay";
+		bus-width = <8>;
+	};
+
+	ahub@0,70300000 {
+		i2s@0,70301100 {
+			status = "okay";
+		};
+	};
+
+	/* mini-PCIe USB */
+	usb@0,7d004000 {
+		status = "okay";
+	};
+
+	usb-phy@0,7d004000 {
+		status = "okay";
+	};
+
+	/* USB A connector */
+	usb@0,7d008000 {
+		status = "okay";
+	};
+
+	usb-phy@0,7d008000 {
+		status = "okay";
+		vbus-supply = <&vdd_usb3_vbus>;
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			debounce-interval = <10>;
+			gpio-key,wakeup;
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_mux: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "+VDD_MUX";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
+			regulator-always-on;
+			regulator-boot-on;
+		};
+
+		vdd_5v0_sys: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "+5V_SYS";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			vin-supply = <&vdd_mux>;
+		};
+
+		vdd_3v3_sys: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "+3.3V_SYS";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			vin-supply = <&vdd_mux>;
+		};
+
+		vdd_3v3_run: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "+3.3V_RUN";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_3v3_sys>;
+		};
+
+		vdd_3v3_hdmi: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "+3.3V_AVDD_HDMI_AP_GATED";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			vin-supply = <&vdd_3v3_run>;
+		};
+
+		vdd_usb1_vbus: regulator@7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "+USB0_VBUS_SW";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_sys>;
+		};
+
+		vdd_usb3_vbus: regulator@8 {
+			compatible = "regulator-fixed";
+			reg = <8>;
+			regulator-name = "+5V_USB_HS";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_sys>;
+		};
+
+		vdd_3v3_lp0: regulator@10 {
+			compatible = "regulator-fixed";
+			reg = <10>;
+			regulator-name = "+3.3V_LP0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&pmic 2 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_3v3_sys>;
+		};
+	};
+
+	sound {
+		compatible = "nvidia,tegra-audio-rt5640-jetson-tk1",
+			     "nvidia,tegra-audio-rt5640";
+		nvidia,model = "NVIDIA Tegra Jetson TK1";
+
+		nvidia,audio-routing =
+			"Headphones", "HPOR",
+			"Headphones", "HPOL",
+			"Mic Jack", "MICBIAS1",
+			"IN2P", "Mic Jack";
+
+		nvidia,i2s-controller = <&tegra_i2s1>;
+		nvidia,audio-codec = <&rt5640>;
+
+		nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_LOW>;
+
+		clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
+			 <&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
+			 <&tegra_car TEGRA124_CLK_EXTERN1>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
+	};
+};
diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index c17283c04598..6770e2bdf226 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -933,7 +933,7 @@
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
 		status = "okay";
 		bus-width = <4>;
-		vmmc-supply = <&vddio_sdmmc3>;
+		vqmmc-supply = <&vddio_sdmmc3>;
 	};
 
 	sdhci@0,700b0600 {
@@ -1060,6 +1060,8 @@
 			regulator-name = "+3.3V_RUN";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
 			gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
 			enable-active-high;
 			vin-supply = <&vdd_3v3_sys>;
diff --git a/arch/arm/boot/dts/vf610-colibri.dts b/arch/arm/boot/dts/vf610-colibri.dts
new file mode 100644
index 000000000000..aecc7dbc65e8
--- /dev/null
+++ b/arch/arm/boot/dts/vf610-colibri.dts
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/dts-v1/;
+#include "vf610.dtsi"
+
+/ {
+	model = "Toradex Colibri VF61 COM";
+	compatible = "toradex,vf610-colibri", "fsl,vf610";
+
+	chosen {
+		bootargs = "console=ttyLP0,115200";
+	};
+
+	memory {
+		reg = <0x80000000 0x10000000>;
+	};
+
+	clocks {
+		enet_ext {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+		};
+	};
+
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&fec1 {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1>;
+	status = "okay";
+};
+
+&L2 {
+	arm,data-latency = <2 1 2>;
+	arm,tag-latency = <3 2 3>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&iomuxc {
+	vf610-colibri {
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,fsl,pins = <
+				VF610_PAD_PTA24__ESDHC1_CLK	0x31ef
+				VF610_PAD_PTA25__ESDHC1_CMD	0x31ef
+				VF610_PAD_PTA26__ESDHC1_DAT0	0x31ef
+				VF610_PAD_PTA27__ESDHC1_DAT1	0x31ef
+				VF610_PAD_PTA28__ESDHC1_DATA2	0x31ef
+				VF610_PAD_PTA29__ESDHC1_DAT3	0x31ef
+				VF610_PAD_PTB20__GPIO_42	0x219d
+			>;
+		};
+
+		pinctrl_fec1: fec1grp {
+			fsl,pins = <
+				VF610_PAD_PTC9__ENET_RMII1_MDC		0x30d2
+				VF610_PAD_PTC10__ENET_RMII1_MDIO	0x30d3
+				VF610_PAD_PTC11__ENET_RMII1_CRS		0x30d1
+				VF610_PAD_PTC12__ENET_RMII_RXD1		0x30d1
+				VF610_PAD_PTC13__ENET_RMII1_RXD0	0x30d1
+				VF610_PAD_PTC14__ENET_RMII1_RXER	0x30d1
+				VF610_PAD_PTC15__ENET_RMII1_TXD1	0x30d2
+				VF610_PAD_PTC16__ENET_RMII1_TXD0	0x30d2
+				VF610_PAD_PTC17__ENET_RMII1_TXEN	0x30d2
+			>;
+		};
+
+		pinctrl_uart0: uart0grp {
+			fsl,pins = <
+				VF610_PAD_PTB10__UART0_TX		0x21a2
+				VF610_PAD_PTB11__UART0_RX		0x21a1
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				VF610_PAD_PTB4__UART1_TX		0x21a2
+				VF610_PAD_PTB5__UART1_RX		0x21a1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				VF610_PAD_PTD0__UART2_TX		0x21a2
+				VF610_PAD_PTD1__UART2_RX		0x21a1
+				VF610_PAD_PTD2__UART2_RTS		0x21a2
+				VF610_PAD_PTD3__UART2_CTS		0x21a1
+			>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 7dd1d6ede525..11d733406c7e 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -25,11 +25,13 @@
 	clocks {
 		audio_ext {
 			compatible = "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24576000>;
 		};
 
 		enet_ext {
 			compatible = "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <50000000>;
 		};
 	};
@@ -111,6 +113,13 @@
 	};
 };
 
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	bus-width = <4>;
+	status = "okay";
+};
+
 &fec0 {
 	phy-mode = "rmii";
 	pinctrl-names = "default";
@@ -158,6 +167,18 @@
 			>;
 		};
 
+		pinctrl_esdhc1: esdhc1grp {
+			fsl,fsl,pins = <
+				VF610_PAD_PTA24__ESDHC1_CLK	0x31ef
+				VF610_PAD_PTA25__ESDHC1_CMD	0x31ef
+				VF610_PAD_PTA26__ESDHC1_DAT0	0x31ef
+				VF610_PAD_PTA27__ESDHC1_DAT1	0x31ef
+				VF610_PAD_PTA28__ESDHC1_DATA2	0x31ef
+				VF610_PAD_PTA29__ESDHC1_DAT3	0x31ef
+				VF610_PAD_PTA7__GPIO_134	0x219d
+			>;
+		};
+
 		pinctrl_fec0: fec0grp {
 			fsl,pins = <
 				VF610_PAD_PTA6__RMII_CLKIN		0x30d1
@@ -194,6 +215,17 @@
 			>;
 		};
 
+		pinctrl_pwm0: pwm0grp {
+			fsl,pins = <
+				VF610_PAD_PTB0__FTM0_CH0		0x1582
+				VF610_PAD_PTB1__FTM0_CH1		0x1582
+				VF610_PAD_PTB2__FTM0_CH2		0x1582
+				VF610_PAD_PTB3__FTM0_CH3		0x1582
+				VF610_PAD_PTB6__FTM0_CH6		0x1582
+				VF610_PAD_PTB7__FTM0_CH7		0x1582
+			>;
+		};
+
 		pinctrl_sai2: sai2grp {
 			fsl,pins = <
 				VF610_PAD_PTA16__SAI2_TX_BCLK		0x02ed
@@ -215,6 +247,12 @@
 	};
 };
 
+&pwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm0>;
+	status = "okay";
+};
+
 &sai2 {
 	#sound-dai-cells = <0>;
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 804873367669..73355ddc5186 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -45,11 +45,13 @@
 
 		sxosc {
 			compatible = "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <32768>;
 		};
 
 		fxosc {
 			compatible = "fixed-clock";
+			#clock-cells = <0>;
 			clock-frequency = <24000000>;
 		};
 	};
@@ -72,8 +74,6 @@
 			intc: interrupt-controller@40002000 {
 				compatible = "arm,cortex-a9-gic";
 				#interrupt-cells = <3>;
-				#address-cells = <1>;
-				#size-cells = <1>;
 				interrupt-controller;
 				reg = <0x40003000 0x1000>,
 				      <0x40002100 0x100>;
@@ -183,6 +183,19 @@
 				clock-names = "pit";
 			};
 
+			pwm0: pwm@40038000 {
+				compatible = "fsl,vf610-ftm-pwm";
+				#pwm-cells = <3>;
+				reg = <0x40038000 0x1000>;
+				clock-names = "ftm_sys", "ftm_ext",
+					      "ftm_fix", "ftm_cnt_clk_en";
+				clocks = <&clks VF610_CLK_FTM0>,
+					<&clks VF610_CLK_FTM0_EXT_SEL>,
+					<&clks VF610_CLK_FTM0_FIX_SEL>,
+					<&clks VF610_CLK_FTM0_EXT_FIX_EN>;
+				status = "disabled";
+			};
+
 			adc0: adc@4003b000 {
 				compatible = "fsl,vf610-adc";
 				reg = <0x4003b000 0x1000>;
@@ -347,6 +360,17 @@
 				status = "disabled";
 			};
 
+			esdhc1: esdhc@400b2000 {
+				compatible = "fsl,imx53-esdhc";
+				reg = <0x400b2000 0x4000>;
+				interrupts = <0 28 0x04>;
+				clocks = <&clks VF610_CLK_IPG_BUS>,
+					<&clks VF610_CLK_PLATFORM_BUS>,
+					<&clks VF610_CLK_ESDHC1>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
 			fec0: ethernet@400d0000 {
 				compatible = "fsl,mvf600-fec";
 				reg = <0x400d0000 0x1000>;
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
index 01004640ee4d..3df3f3a79ef4 100644
--- a/arch/arm/configs/bcm_defconfig
+++ b/arch/arm/configs/bcm_defconfig
@@ -132,7 +132,7 @@ CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
 CONFIG_XZ_DEC=y
 CONFIG_AVERAGE=y
-CONFIG_PINCTRL_CAPRI=y
+CONFIG_PINCTRL_BCM281XX=y
 CONFIG_WATCHDOG=y
 CONFIG_BCM_KONA_WDT=y
 CONFIG_BCM_KONA_WDT_DEBUG=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index f1aeb7d72712..ec9b36580952 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -80,6 +80,7 @@ CONFIG_MTD_UBI=y
 CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
 CONFIG_ATA=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_PATA_IMX=y
 CONFIG_NETDEVICES=y
 CONFIG_CS89x0=y
@@ -153,6 +154,11 @@ CONFIG_USB_HID=m
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_NOP_USB_XCEIV=y
 CONFIG_MMC=y
 CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_MMC_SDHCI=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 09e974392fa1..0e0052831d60 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -46,7 +46,11 @@ CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
+CONFIG_CMA=y
 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_ARM_IMX6Q_CPUFREQ=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_BINFMT_MISC=m
@@ -72,6 +76,7 @@ CONFIG_RFKILL_INPUT=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
+CONFIG_DMA_CMA=y
 CONFIG_IMX_WEIM=y
 CONFIG_CONNECTOR=y
 CONFIG_MTD=y
@@ -183,6 +188,7 @@ CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_CODA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_DRM=y
+CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
@@ -209,8 +215,10 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_OTG_FSM=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_MXS_PHY=y
+CONFIG_USB_ULPI=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_USB_MASS_STORAGE=m
@@ -245,7 +253,7 @@ CONFIG_DRM_IMX_TVE=y
 CONFIG_DRM_IMX_LDB=y
 CONFIG_DRM_IMX_IPUV3_CORE=y
 CONFIG_DRM_IMX_IPUV3=y
-CONFIG_COMMON_CLK_DEBUG=y
+CONFIG_DRM_IMX_HDMI=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PWM=y
 CONFIG_PWM_IMX=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 6150108e15de..40e87c412419 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -26,7 +26,6 @@ CONFIG_ARCH_MXS=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
-CONFIG_FPE_NWFPE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -51,7 +50,6 @@ CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_M25P80=y
-# CONFIG_M25PXX_USE_FAST_READ is not set
 CONFIG_MTD_SST25L=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_GPMI_NAND=y
@@ -138,7 +136,6 @@ CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
 CONFIG_STAGING=y
 CONFIG_MXS_LRADC=y
-CONFIG_COMMON_CLK_DEBUG=y
 CONFIG_IIO=y
 CONFIG_IIO_SYSFS_TRIGGER=y
 CONFIG_PWM=y
@@ -180,7 +177,7 @@ CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_STRICT_DEVMEM=y
 CONFIG_DEBUG_USER=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
+CONFIG_CRYPTO_DEV_MXS_DCP=y
 CONFIG_CRC_ITU_T=m
 CONFIG_CRC7=m
 CONFIG_FONTS=y
diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
index 83b07258a385..6d6437cbbc52 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -25,6 +25,7 @@ CONFIG_SCHED_MC=y
 CONFIG_HAVE_ARM_ARCH_TIMER=y
 CONFIG_NR_CPUS=8
 CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -43,6 +44,7 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_M25P80=y
+CONFIG_EEPROM_AT24=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 CONFIG_SATA_RCAR=y
@@ -75,9 +77,11 @@ CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=20
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 CONFIG_I2C_GPIO=y
+CONFIG_I2C_SH_MOBILE=y
 CONFIG_I2C_RCAR=y
 CONFIG_SPI=y
 CONFIG_SPI_RSPI=y
+CONFIG_SPI_SH_MSIOF=y
 CONFIG_GPIO_EM=y
 CONFIG_GPIO_RCAR=y
 # CONFIG_HWMON is not set
@@ -88,10 +92,14 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_PLATFORM=y
 CONFIG_VIDEO_RCAR_VIN=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_RENESAS_VSP1=y
 # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
 CONFIG_VIDEO_ADV7180=y
 CONFIG_DRM=y
@@ -100,7 +108,13 @@ CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_RCAR=y
+CONFIG_USB=y
 CONFIG_USB_RCAR_GEN2_PHY=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_RENESAS_USBHS=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_RENESAS_USBHS_UDC=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
 CONFIG_MMC_SH_MMCIF=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 2926281368ab..d9f4a730f399 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -97,6 +97,7 @@ CONFIG_AD525X_DPOT_I2C=y
 CONFIG_ICS932S401=y
 CONFIG_APDS9802ALS=y
 CONFIG_ISL29003=y
+CONFIG_EEPROM_AT24=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 23e728ecf8ab..2d95820276fd 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -21,6 +21,7 @@ generic-y += parport.h
 generic-y += poll.h
 generic-y += preempt.h
 generic-y += resource.h
+generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += sembuf.h
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b974184f9941..57f0584e8d97 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -312,7 +312,7 @@
  * you cannot return to the original mode.
  */
 .macro safe_svcmode_maskall reg:req
-#if __LINUX_ARM_ARCH__ >= 6
+#if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M)
 	mrs	\reg , cpsr
 	eor	\reg, \reg, #HYP_MODE
 	tst	\reg, #MODE_MASK
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index bbae919bceb4..68ea615c2a28 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -14,28 +14,15 @@
  */
 
 #define FIXADDR_START		0xfff00000UL
-#define FIXADDR_TOP		0xfffe0000UL
-#define FIXADDR_SIZE		(FIXADDR_TOP - FIXADDR_START)
+#define FIXADDR_END		0xfffe0000UL
+#define FIXADDR_TOP		(FIXADDR_END - PAGE_SIZE)
 
-#define FIX_KMAP_BEGIN		0
-#define FIX_KMAP_END		(FIXADDR_SIZE >> PAGE_SHIFT)
+enum fixed_addresses {
+	FIX_KMAP_BEGIN,
+	FIX_KMAP_END = (FIXADDR_TOP - FIXADDR_START) >> PAGE_SHIFT,
+	__end_of_fixed_addresses
+};
 
-#define __fix_to_virt(x)	(FIXADDR_START + ((x) << PAGE_SHIFT))
-#define __virt_to_fix(x)	(((x) - FIXADDR_START) >> PAGE_SHIFT)
-
-extern void __this_fixmap_does_not_exist(void);
-
-static inline unsigned long fix_to_virt(const unsigned int idx)
-{
-	if (idx >= FIX_KMAP_END)
-		__this_fixmap_does_not_exist();
-	return __fix_to_virt(idx);
-}
-
-static inline unsigned int virt_to_fix(const unsigned long vaddr)
-{
-	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
-	return __virt_to_fix(vaddr);
-}
+#include <asm-generic/fixmap.h>
 
 #endif
diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h
deleted file mode 100644
index cefdb8f898a1..000000000000
--- a/arch/arm/include/asm/scatterlist.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASMARM_SCATTERLIST_H
-#define _ASMARM_SCATTERLIST_H
-
-#ifdef CONFIG_ARM_HAS_SG_CHAIN
-#define ARCH_HAS_SG_CHAIN
-#endif
-
-#include <asm/memory.h>
-#include <asm/types.h>
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASMARM_SCATTERLIST_H */
diff --git a/arch/arm/include/debug/vf.S b/arch/arm/include/debug/vf.S
index ba12cc44b2cb..b88933849a17 100644
--- a/arch/arm/include/debug/vf.S
+++ b/arch/arm/include/debug/vf.S
@@ -7,9 +7,20 @@
  *
  */
 
+#define VF_UART0_BASE_ADDR	0x40027000
+#define VF_UART1_BASE_ADDR	0x40028000
+#define VF_UART2_BASE_ADDR	0x40029000
+#define VF_UART3_BASE_ADDR	0x4002a000
+#define VF_UART_BASE_ADDR(n)	VF_UART##n##_BASE_ADDR
+#define VF_UART_BASE(n)		VF_UART_BASE_ADDR(n)
+#define VF_UART_PHYSICAL_BASE	VF_UART_BASE(CONFIG_DEBUG_VF_UART_PORT)
+
+#define VF_UART_VIRTUAL_BASE	0xfe000000
+
 	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =0x40028000	@ physical
-	ldr	\rv, =0xfe028000	@ virtual
+	ldr	\rp, =VF_UART_PHYSICAL_BASE 	@ physical
+	and	\rv, \rp, #0xffffff		@ offset within 16MB section
+	add	\rv, \rv, #VF_UART_VIRTUAL_BASE
 	.endm
 
 	.macro	senduart, rd, rx
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index b907d9b790ab..1b880db2a033 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -127,6 +127,10 @@ ENDPROC(cpu_resume_after_mmu)
 	.align
 ENTRY(cpu_resume)
 ARM_BE8(setend be)			@ ensure we are in BE mode
+#ifdef CONFIG_ARM_VIRT_EXT
+	bl	__hyp_stub_install_secondary
+#endif
+	safe_svcmode_maskall r1
 	mov	r1, #0
 	ALT_SMP(mrc p15, 0, r0, c0, c0, 5)
 	ALT_UP_B(1f)
@@ -144,7 +148,6 @@ ARM_BE8(setend be)			@ ensure we are in BE mode
 	ldr	r0, [r0, #SLEEP_SAVE_SP_PHYS]
 	ldr	r0, [r0, r1, lsl #2]
 
-	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
 	@ load phys pgd, stack, resume fn
   ARM(	ldmia	r0!, {r1, sp, pc}	)
 THUMB(	ldmia	r0!, {r1, r2, r3}	)
diff --git a/arch/arm/mach-berlin/Kconfig b/arch/arm/mach-berlin/Kconfig
index b0cb0722acd2..1168c8f096ae 100644
--- a/arch/arm/mach-berlin/Kconfig
+++ b/arch/arm/mach-berlin/Kconfig
@@ -1,5 +1,6 @@
 config ARCH_BERLIN
 	bool "Marvell Berlin SoCs" if ARCH_MULTI_V7
+	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
 	select GENERIC_IRQ_CHIP
 	select DW_APB_ICTL
@@ -20,6 +21,13 @@ config MACH_BERLIN_BG2CD
 	select CACHE_L2X0
 	select HAVE_ARM_TWD if SMP
 
+config MACH_BERLIN_BG2Q
+	bool "Marvell Armada 1500 Pro (BG2-Q)"
+	select CACHE_L2X0
+	select CPU_V7
+	select HAVE_ARM_TWD if SMP
+	select HAVE_SMP
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 5740296dc429..d56eb1a001d8 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -711,21 +711,6 @@ config MACH_IMX51_DT
 	  Include support for Freescale i.MX51 based platforms
 	  using the device tree for discovery
 
-config MACH_MX51_BABBAGE
-	bool "Support MX51 BABBAGE platforms"
-	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_EHCI
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select SOC_IMX51
-	help
-	  Include support for MX51 Babbage platform, also known as MX51EVK in
-	  u-boot. This includes specific configurations for the board and its
-	  peripherals.
-
 config MACH_EUKREA_CPUIMX51SD
 	bool "Support Eukrea CPUIMX51SD module"
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f4ed83032dd0..8dd377be88a6 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -109,7 +109,6 @@ endif
 obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
 
 # i.MX5 based machines
-obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o
 
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index dc36e6c2f1da..ae578c096ad8 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -62,6 +62,10 @@ static struct clk_onecell_data clk_data;
 
 static const char *cpu_sel_clks[] = { "mpll", "mpll_cpu_3_4", };
 static const char *per_sel_clks[] = { "ahb", "upll", };
+static const char *cko_sel_clks[] = { "dummy", "osc", "cpu", "ahb",
+				      "ipg", "dummy", "dummy", "dummy",
+				      "dummy", "dummy", "per0", "per2",
+				      "per13", "per14", "usbotg_ahb", "dummy",};
 
 enum mx25_clks {
 	dummy, osc, mpll, upll, mpll_cpu_3_4, cpu_sel, cpu, ahb, usb_div, ipg,
@@ -82,7 +86,7 @@ enum mx25_clks {
 	pwm2_ipg, pwm3_ipg, pwm4_ipg, rngb_ipg, reserved16, scc_ipg, sdma_ipg,
 	sim1_ipg, sim2_ipg, slcdc_ipg, spba_ipg, ssi1_ipg, ssi2_ipg, tsc_ipg,
 	uart1_ipg, uart2_ipg, uart3_ipg, uart4_ipg, uart5_ipg, reserved17,
-	wdt_ipg, clk_max
+	wdt_ipg, cko_div, cko_sel, cko, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -117,6 +121,9 @@ static int __init __mx25_clocks_init(unsigned long osc_rate)
 	clk[per13_sel] = imx_clk_mux("per13_sel", ccm(CCM_MCR), 13, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
 	clk[per14_sel] = imx_clk_mux("per14_sel", ccm(CCM_MCR), 14, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
 	clk[per15_sel] = imx_clk_mux("per15_sel", ccm(CCM_MCR), 15, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks));
+	clk[cko_div] = imx_clk_divider("cko_div", "cko_sel", ccm(CCM_MCR), 24, 6);
+	clk[cko_sel] = imx_clk_mux("cko_sel", ccm(CCM_MCR), 20, 4, cko_sel_clks, ARRAY_SIZE(cko_sel_clks));
+	clk[cko] = imx_clk_gate("cko", "cko_div", ccm(CCM_MCR),  30);
 	clk[per0] = imx_clk_divider("per0", "per0_sel", ccm(CCM_PCDR0), 0, 6);
 	clk[per1] = imx_clk_divider("per1", "per1_sel", ccm(CCM_PCDR0), 8, 6);
 	clk[per2] = imx_clk_divider("per2", "per2_sel", ccm(CCM_PCDR0), 16, 6);
@@ -230,6 +237,12 @@ static int __init __mx25_clocks_init(unsigned long osc_rate)
 	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
 	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
 
+	/*
+	 * Let's initially set up CLKO parent as ipg, since this configuration
+	 * is used on some imx25 board designs to clock the audio codec.
+	 */
+	clk_set_parent(clk[cko_sel], clk[ipg]);
+
 	return 0;
 }
 
@@ -304,8 +317,6 @@ int __init mx25_clocks_init(void)
 int __init mx25_clocks_init_dt(void)
 {
 	struct device_node *np;
-	void __iomem *base;
-	int irq;
 	unsigned long osc_rate = 24000000;
 
 	/* retrieve the freqency of fixed clocks from device tree */
@@ -325,12 +336,7 @@ int __init mx25_clocks_init_dt(void)
 
 	__mx25_clocks_init(osc_rate);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt");
-	base = of_iomap(np, 0);
-	WARN_ON(!base);
-	irq = irq_of_parse_and_map(np, 0);
-
-	mxc_timer_init(base, irq);
+	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt"));
 
 	return 0;
 }
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 568ef0a4de84..21d2b111c83d 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -322,9 +322,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 
 static void __init mx50_clocks_init(struct device_node *np)
 {
-	void __iomem *base;
 	unsigned long r;
-	int i, irq;
+	int i;
 
 	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
 	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
@@ -372,11 +371,7 @@ static void __init mx50_clocks_init(struct device_node *np)
 	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
 	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx50-gpt");
-	base = of_iomap(np, 0);
-	WARN_ON(!base);
-	irq = irq_of_parse_and_map(np, 0);
-	mxc_timer_init(base, irq);
+	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx50-gpt"));
 }
 CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
 
@@ -436,7 +431,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 
 	clk_register_clkdev(clk[IMX5_CLK_HSI2C_GATE], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[IMX5_CLK_MX51_MIPI], "mipi_hsp", NULL);
-	clk_register_clkdev(clk[IMX5_CLK_VPU_GATE], NULL, "imx51-vpu.0");
 	clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx27-fec.0");
 	clk_register_clkdev(clk[IMX5_CLK_USB_PHY_GATE], "phy", "mxc-ehci.0");
 	clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx51.0");
@@ -492,9 +486,8 @@ CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init_dt);
 
 static void __init mx53_clocks_init(struct device_node *np)
 {
-	int i, irq;
+	int i;
 	unsigned long r;
-	void __iomem *base;
 
 	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
 	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
@@ -561,7 +554,6 @@ static void __init mx53_clocks_init(struct device_node *np)
 
 	mx5_clocks_common_init(0, 0, 0, 0);
 
-	clk_register_clkdev(clk[IMX5_CLK_VPU_GATE], NULL, "imx53-vpu.0");
 	clk_register_clkdev(clk[IMX5_CLK_I2C3_GATE], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx25-fec.0");
 	clk_register_clkdev(clk[IMX5_CLK_USB_PHY1_GATE], "usb_phy1", "mxc-ehci.0");
@@ -592,10 +584,6 @@ static void __init mx53_clocks_init(struct device_node *np)
 	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
 	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt");
-	base = of_iomap(np, 0);
-	WARN_ON(!base);
-	irq = irq_of_parse_and_map(np, 0);
-	mxc_timer_init(base, irq);
+	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt"));
 }
 CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index b0e7f9d2c245..20ad0d14e6bf 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -144,7 +144,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 {
 	struct device_node *np;
 	void __iomem *base;
-	int i, irq;
+	int i;
 	int ret;
 
 	clk[dummy] = imx_clk_fixed("dummy", 0);
@@ -208,8 +208,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	 * the "output_enable" bit as a gate, even though it's really just
 	 * enabling clock output.
 	 */
-	clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "dummy", base + 0x160, 10);
-	clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "dummy", base + 0x160, 11);
+	clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "lvds1_sel", base + 0x160, 10);
+	clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "lvds2_sel", base + 0x160, 11);
 
 	/*                                name              parent_name        reg       idx */
 	clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
@@ -480,10 +480,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	/* Set initial power mode */
 	imx6q_set_lpm(WAIT_CLOCKED);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
-	base = of_iomap(np, 0);
-	WARN_ON(!base);
-	irq = irq_of_parse_and_map(np, 0);
-	mxc_timer_init(base, irq);
+	mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"));
 }
 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index f7073c0782fb..21cf06cebade 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -169,7 +169,6 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 {
 	struct device_node *np;
 	void __iomem *base;
-	int irq;
 	int i;
 	int ret;
 
@@ -385,9 +384,6 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	imx6q_set_lpm(WAIT_CLOCKED);
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt");
-	base = of_iomap(np, 0);
-	WARN_ON(!base);
-	irq = irq_of_parse_and_map(np, 0);
-	mxc_timer_init(base, irq);
+	mxc_timer_init_dt(np);
 }
 CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index b5241ea76706..4facd01d1c75 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -17,6 +17,7 @@ struct irq_data;
 struct platform_device;
 struct pt_regs;
 struct clk;
+struct device_node;
 enum mxc_cpu_pwr_mode;
 
 void mx1_map_io(void);
@@ -56,6 +57,7 @@ void imx51_init_late(void);
 void imx53_init_late(void);
 void epit_timer_init(void __iomem *base, int irq);
 void mxc_timer_init(void __iomem *, int);
+void mxc_timer_init_dt(struct device_node *);
 int mx1_clocks_init(unsigned long fref);
 int mx21_clocks_init(unsigned long lref, unsigned long fref);
 int mx25_clocks_init(void);
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index a06aa4dc37fc..30c30fdae53f 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -17,51 +17,46 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
+#include <linux/basic_mmio_gpio.h>
 #include <linux/gpio.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
 
 #include "common.h"
 #include "devices-imx21.h"
 #include "hardware.h"
 #include "iomux-mx21.h"
 
-/*
- * Memory-mapped I/O on MX21ADS base board
- */
-#define MX21ADS_MMIO_BASE_ADDR   0xf5000000
-#define MX21ADS_MMIO_SIZE        0xc00000
-
-#define MX21ADS_REG_ADDR(offset)    (void __force __iomem *) \
-		(MX21ADS_MMIO_BASE_ADDR + (offset))
+#define MX21ADS_CS8900A_REG		(MX21_CS1_BASE_ADDR + 0x000000)
+#define MX21ADS_ST16C255_IOBASE_REG	(MX21_CS1_BASE_ADDR + 0x200000)
+#define MX21ADS_VERSION_REG		(MX21_CS1_BASE_ADDR + 0x400000)
+#define MX21ADS_IO_REG			(MX21_CS1_BASE_ADDR + 0x800000)
 
-#define MX21ADS_CS8900A_MMIO_SIZE   0x200000
-#define MX21ADS_CS8900A_IRQ_GPIO    IMX_GPIO_NR(5, 11)
-#define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000)
-#define MX21ADS_VERSION_REG         MX21ADS_REG_ADDR(0x400000)
-#define MX21ADS_IO_REG              MX21ADS_REG_ADDR(0x800000)
+#define MX21ADS_MMC_CD			IMX_GPIO_NR(4, 25)
+#define MX21ADS_CS8900A_IRQ_GPIO	IMX_GPIO_NR(5, 11)
+#define MX21ADS_MMGPIO_BASE		(6 * 32)
 
 /* MX21ADS_IO_REG bit definitions */
-#define MX21ADS_IO_SD_WP        0x0001 /* read */
-#define MX21ADS_IO_TP6          0x0001 /* write */
-#define MX21ADS_IO_SW_SEL       0x0002 /* read */
-#define MX21ADS_IO_TP7          0x0002 /* write */
-#define MX21ADS_IO_RESET_E_UART 0x0004
-#define MX21ADS_IO_RESET_BASE   0x0008
-#define MX21ADS_IO_CSI_CTL2     0x0010
-#define MX21ADS_IO_CSI_CTL1     0x0020
-#define MX21ADS_IO_CSI_CTL0     0x0040
-#define MX21ADS_IO_UART1_EN     0x0080
-#define MX21ADS_IO_UART4_EN     0x0100
-#define MX21ADS_IO_LCDON        0x0200
-#define MX21ADS_IO_IRDA_EN      0x0400
-#define MX21ADS_IO_IRDA_FIR_SEL 0x0800
-#define MX21ADS_IO_IRDA_MD0_B   0x1000
-#define MX21ADS_IO_IRDA_MD1     0x2000
-#define MX21ADS_IO_LED4_ON      0x4000
-#define MX21ADS_IO_LED3_ON      0x8000
+#define MX21ADS_IO_SD_WP		(MX21ADS_MMGPIO_BASE + 0)
+#define MX21ADS_IO_TP6			(MX21ADS_IO_SD_WP)
+#define MX21ADS_IO_SW_SEL		(MX21ADS_MMGPIO_BASE + 1)
+#define MX21ADS_IO_TP7			(MX21ADS_IO_SW_SEL)
+#define MX21ADS_IO_RESET_E_UART		(MX21ADS_MMGPIO_BASE + 2)
+#define MX21ADS_IO_RESET_BASE		(MX21ADS_MMGPIO_BASE + 3)
+#define MX21ADS_IO_CSI_CTL2		(MX21ADS_MMGPIO_BASE + 4)
+#define MX21ADS_IO_CSI_CTL1		(MX21ADS_MMGPIO_BASE + 5)
+#define MX21ADS_IO_CSI_CTL0		(MX21ADS_MMGPIO_BASE + 6)
+#define MX21ADS_IO_UART1_EN		(MX21ADS_MMGPIO_BASE + 7)
+#define MX21ADS_IO_UART4_EN		(MX21ADS_MMGPIO_BASE + 8)
+#define MX21ADS_IO_LCDON		(MX21ADS_MMGPIO_BASE + 9)
+#define MX21ADS_IO_IRDA_EN		(MX21ADS_MMGPIO_BASE + 10)
+#define MX21ADS_IO_IRDA_FIR_SEL		(MX21ADS_MMGPIO_BASE + 11)
+#define MX21ADS_IO_IRDA_MD0_B		(MX21ADS_MMGPIO_BASE + 12)
+#define MX21ADS_IO_IRDA_MD1		(MX21ADS_MMGPIO_BASE + 13)
+#define MX21ADS_IO_LED4_ON		(MX21ADS_MMGPIO_BASE + 14)
+#define MX21ADS_IO_LED3_ON		(MX21ADS_MMGPIO_BASE + 15)
 
 static const int mx21ads_pins[] __initconst = {
 
@@ -143,11 +138,8 @@ static struct physmap_flash_data mx21ads_flash_data = {
 	.width = 4,
 };
 
-static struct resource mx21ads_flash_resource = {
-	.start = MX21_CS0_BASE_ADDR,
-	.end = MX21_CS0_BASE_ADDR + 0x02000000 - 1,
-	.flags = IORESOURCE_MEM,
-};
+static struct resource mx21ads_flash_resource =
+	DEFINE_RES_MEM(MX21_CS0_BASE_ADDR, SZ_32M);
 
 static struct platform_device mx21ads_nor_mtd_device = {
 	.name = "physmap-flash",
@@ -160,7 +152,7 @@ static struct platform_device mx21ads_nor_mtd_device = {
 };
 
 static struct resource mx21ads_cs8900_resources[] __initdata = {
-	DEFINE_RES_MEM(MX21_CS1_BASE_ADDR, MX21ADS_CS8900A_MMIO_SIZE),
+	DEFINE_RES_MEM(MX21ADS_CS8900A_REG, SZ_1K),
 	/* irq number is run-time assigned */
 	DEFINE_RES_IRQ(-1),
 };
@@ -179,24 +171,50 @@ static const struct imxuart_platform_data uart_pdata_rts __initconst = {
 static const struct imxuart_platform_data uart_pdata_norts __initconst = {
 };
 
-static int mx21ads_fb_init(struct platform_device *pdev)
-{
-	u16 tmp;
+static struct resource mx21ads_mmgpio_resource =
+	DEFINE_RES_MEM_NAMED(MX21ADS_IO_REG, SZ_2, "dat");
 
-	tmp = __raw_readw(MX21ADS_IO_REG);
-	tmp |= MX21ADS_IO_LCDON;
-	__raw_writew(tmp, MX21ADS_IO_REG);
-	return 0;
-}
+static struct bgpio_pdata mx21ads_mmgpio_pdata = {
+	.base	= MX21ADS_MMGPIO_BASE,
+	.ngpio	= 16,
+};
 
-static void mx21ads_fb_exit(struct platform_device *pdev)
-{
-	u16 tmp;
+static struct platform_device mx21ads_mmgpio = {
+	.name = "basic-mmio-gpio",
+	.id = PLATFORM_DEVID_AUTO,
+	.resource = &mx21ads_mmgpio_resource,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &mx21ads_mmgpio_pdata,
+	},
+};
 
-	tmp = __raw_readw(MX21ADS_IO_REG);
-	tmp &= ~MX21ADS_IO_LCDON;
-	__raw_writew(tmp, MX21ADS_IO_REG);
-}
+static struct regulator_consumer_supply mx21ads_lcd_regulator_consumer =
+	REGULATOR_SUPPLY("lcd", "imx-fb.0");
+
+static struct regulator_init_data mx21ads_lcd_regulator_init_data = {
+	.constraints = {
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.consumer_supplies	= &mx21ads_lcd_regulator_consumer,
+	.num_consumer_supplies	= 1,
+};
+
+static struct fixed_voltage_config mx21ads_lcd_regulator_pdata = {
+	.supply_name	= "LCD",
+	.microvolts	= 3300000,
+	.gpio		= MX21ADS_IO_LCDON,
+	.enable_high	= 1,
+	.init_data	= &mx21ads_lcd_regulator_init_data,
+};
+
+static struct platform_device mx21ads_lcd_regulator = {
+	.name = "reg-fixed-voltage",
+	.id = PLATFORM_DEVID_AUTO,
+	.dev = {
+		.platform_data = &mx21ads_lcd_regulator_pdata,
+	},
+};
 
 /*
  * Connected is a portrait Sharp-QVGA display
@@ -229,26 +247,30 @@ static const struct imx_fb_platform_data mx21ads_fb_data __initconst = {
 	.pwmr		= 0x00a903ff,
 	.lscr1		= 0x00120300,
 	.dmacr		= 0x00020008,
-
-	.init = mx21ads_fb_init,
-	.exit = mx21ads_fb_exit,
 };
 
 static int mx21ads_sdhc_get_ro(struct device *dev)
 {
-	return (__raw_readw(MX21ADS_IO_REG) & MX21ADS_IO_SD_WP) ? 1 : 0;
+	return gpio_get_value(MX21ADS_IO_SD_WP);
 }
 
 static int mx21ads_sdhc_init(struct device *dev, irq_handler_t detect_irq,
 	void *data)
 {
-	return request_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), detect_irq,
-		IRQF_TRIGGER_FALLING, "mmc-detect", data);
+	int ret;
+
+	ret = gpio_request(MX21ADS_IO_SD_WP, "mmc-ro");
+	if (ret)
+		return ret;
+
+	return request_irq(gpio_to_irq(MX21ADS_MMC_CD), detect_irq,
+			   IRQF_TRIGGER_FALLING, "mmc-detect", data);
 }
 
 static void mx21ads_sdhc_exit(struct device *dev, void *data)
 {
-	free_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), data);
+	free_irq(gpio_to_irq(MX21ADS_MMC_CD), data);
+	gpio_free(MX21ADS_IO_SD_WP);
 }
 
 static const struct imxmmc_platform_data mx21ads_sdhc_pdata __initconst = {
@@ -264,29 +286,9 @@ mx21ads_nand_board_info __initconst = {
 	.hw_ecc = 1,
 };
 
-static struct map_desc mx21ads_io_desc[] __initdata = {
-	/*
-	 * Memory-mapped I/O on MX21ADS Base board:
-	 *   - CS8900A Ethernet controller
-	 *   - ST16C2552CJ UART
-	 *   - CPU and Base board version
-	 *   - Base board I/O register
-	 */
-	{
-		.virtual = MX21ADS_MMIO_BASE_ADDR,
-		.pfn = __phys_to_pfn(MX21_CS1_BASE_ADDR),
-		.length = MX21ADS_MMIO_SIZE,
-		.type = MT_DEVICE,
-	},
-};
-
-static void __init mx21ads_map_io(void)
-{
-	mx21_map_io();
-	iotable_init(mx21ads_io_desc, ARRAY_SIZE(mx21ads_io_desc));
-}
-
 static struct platform_device *platform_devices[] __initdata = {
+	&mx21ads_mmgpio,
+	&mx21ads_lcd_regulator,
 	&mx21ads_nor_mtd_device,
 };
 
@@ -300,12 +302,13 @@ static void __init mx21ads_board_init(void)
 	imx21_add_imx_uart0(&uart_pdata_rts);
 	imx21_add_imx_uart2(&uart_pdata_norts);
 	imx21_add_imx_uart3(&uart_pdata_rts);
-	imx21_add_imx_fb(&mx21ads_fb_data);
 	imx21_add_mxc_mmc(0, &mx21ads_sdhc_pdata);
 	imx21_add_mxc_nand(&mx21ads_nand_board_info);
 
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
+	imx21_add_imx_fb(&mx21ads_fb_data);
+
 	mx21ads_cs8900_resources[1].start =
 			gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO);
 	mx21ads_cs8900_resources[1].end =
@@ -321,7 +324,7 @@ static void __init mx21ads_timer_init(void)
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
-	.map_io = mx21ads_map_io,
+	.map_io		= mx21_map_io,
 	.init_early = imx21_init_early,
 	.init_irq = mx21_init_irq,
 	.handle_irq = imx21_handle_irq,
diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c
deleted file mode 100644
index f3d264a636fa..000000000000
--- a/arch/arm/mach-imx/mach-mx51_babbage.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/input.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "common.h"
-#include "devices-imx51.h"
-#include "hardware.h"
-#include "iomux-mx51.h"
-
-#define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
-#define BABBAGE_USBH1_STP	IMX_GPIO_NR(1, 27)
-#define BABBAGE_USB_PHY_RESET	IMX_GPIO_NR(2, 5)
-#define BABBAGE_FEC_PHY_RESET	IMX_GPIO_NR(2, 14)
-#define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
-#define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
-#define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD2_CD		IMX_GPIO_NR(1, 6)
-#define BABBAGE_SD2_WP		IMX_GPIO_NR(1, 5)
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET			0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN		(1 << 25)
-
-#define	MX51_USB_PLLDIV_12_MHZ		0x00
-#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
-#define	MX51_USB_PLL_DIV_24_MHZ	0x02
-
-static struct gpio_keys_button babbage_buttons[] = {
-	{
-		.gpio		= BABBAGE_POWER_KEY,
-		.code		= BTN_0,
-		.desc		= "PWR",
-		.active_low	= 1,
-		.wakeup		= 1,
-	},
-};
-
-static const struct gpio_keys_platform_data imx_button_data __initconst = {
-	.buttons	= babbage_buttons,
-	.nbuttons	= ARRAY_SIZE(babbage_buttons),
-};
-
-static iomux_v3_cfg_t mx51babbage_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* UART2 */
-	MX51_PAD_UART2_RXD__UART2_RXD,
-	MX51_PAD_UART2_TXD__UART2_TXD,
-
-	/* UART3 */
-	MX51_PAD_EIM_D25__UART3_RXD,
-	MX51_PAD_EIM_D26__UART3_TXD,
-	MX51_PAD_EIM_D27__UART3_RTS,
-	MX51_PAD_EIM_D24__UART3_CTS,
-
-	/* I2C1 */
-	MX51_PAD_EIM_D16__I2C1_SDA,
-	MX51_PAD_EIM_D19__I2C1_SCL,
-
-	/* I2C2 */
-	MX51_PAD_KEY_COL4__I2C2_SCL,
-	MX51_PAD_KEY_COL5__I2C2_SDA,
-
-	/* HSI2C */
-	MX51_PAD_I2C1_CLK__I2C1_CLK,
-	MX51_PAD_I2C1_DAT__I2C1_DAT,
-
-	/* USB HOST1 */
-	MX51_PAD_USBH1_CLK__USBH1_CLK,
-	MX51_PAD_USBH1_DIR__USBH1_DIR,
-	MX51_PAD_USBH1_NXT__USBH1_NXT,
-	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
-	/* USB HUB reset line*/
-	MX51_PAD_GPIO1_7__GPIO1_7,
-
-	/* USB PHY reset line */
-	MX51_PAD_EIM_D21__GPIO2_5,
-
-	/* FEC */
-	MX51_PAD_EIM_EB2__FEC_MDIO,
-	MX51_PAD_EIM_EB3__FEC_RDATA1,
-	MX51_PAD_EIM_CS2__FEC_RDATA2,
-	MX51_PAD_EIM_CS3__FEC_RDATA3,
-	MX51_PAD_EIM_CS4__FEC_RX_ER,
-	MX51_PAD_EIM_CS5__FEC_CRS,
-	MX51_PAD_NANDF_RB2__FEC_COL,
-	MX51_PAD_NANDF_RB3__FEC_RX_CLK,
-	MX51_PAD_NANDF_D9__FEC_RDATA0,
-	MX51_PAD_NANDF_D8__FEC_TDATA0,
-	MX51_PAD_NANDF_CS2__FEC_TX_ER,
-	MX51_PAD_NANDF_CS3__FEC_MDC,
-	MX51_PAD_NANDF_CS4__FEC_TDATA1,
-	MX51_PAD_NANDF_CS5__FEC_TDATA2,
-	MX51_PAD_NANDF_CS6__FEC_TDATA3,
-	MX51_PAD_NANDF_CS7__FEC_TX_EN,
-	MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
-
-	/* FEC PHY reset line */
-	MX51_PAD_EIM_A20__GPIO2_14,
-
-	/* SD 1 */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-	/* CD/WP from controller */
-	MX51_PAD_GPIO1_0__SD1_CD,
-	MX51_PAD_GPIO1_1__SD1_WP,
-
-	/* SD 2 */
-	MX51_PAD_SD2_CMD__SD2_CMD,
-	MX51_PAD_SD2_CLK__SD2_CLK,
-	MX51_PAD_SD2_DATA0__SD2_DATA0,
-	MX51_PAD_SD2_DATA1__SD2_DATA1,
-	MX51_PAD_SD2_DATA2__SD2_DATA2,
-	MX51_PAD_SD2_DATA3__SD2_DATA3,
-	/* CD/WP gpio */
-	MX51_PAD_GPIO1_6__GPIO1_6,
-	MX51_PAD_GPIO1_5__GPIO1_5,
-
-	/* eCSPI1 */
-	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-	MX51_PAD_CSPI1_SS0__GPIO4_24,
-	MX51_PAD_CSPI1_SS1__GPIO4_25,
-
-	/* Audio */
-	MX51_PAD_AUD3_BB_TXD__AUD3_TXD,
-	MX51_PAD_AUD3_BB_RXD__AUD3_RXD,
-	MX51_PAD_AUD3_BB_CK__AUD3_TXC,
-	MX51_PAD_AUD3_BB_FS__AUD3_TXFS,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
-	.bitrate = 400000,
-};
-
-static struct gpio mx51_babbage_usbh1_gpios[] = {
-	{ BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
-	{ BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
-};
-
-static int gpio_usbh1_active(void)
-{
-	iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
-	int ret;
-
-	/* Set USBH1_STP to GPIO and toggle it */
-	mxc_iomux_v3_setup_pad(usbh1stp_gpio);
-	ret = gpio_request_array(mx51_babbage_usbh1_gpios,
-					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
-
-	if (ret) {
-		pr_debug("failed to get USBH1 pins: %d\n", ret);
-		return ret;
-	}
-
-	msleep(100);
-	gpio_set_value(BABBAGE_USBH1_STP, 1);
-	gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
-	gpio_free_array(mx51_babbage_usbh1_gpios,
-					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
-	return 0;
-}
-
-static inline void babbage_usbhub_reset(void)
-{
-	int ret;
-
-	/* Reset USB hub */
-	ret = gpio_request_one(BABBAGE_USB_HUB_RESET,
-					GPIOF_OUT_INIT_LOW, "GPIO1_7");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
-		return;
-	}
-
-	msleep(2);
-	/* Deassert reset */
-	gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
-}
-
-static inline void babbage_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
-					GPIOF_OUT_INIT_LOW, "fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	msleep(1);
-	gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
-}
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_19_2_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* The clock for the USBH1 ULPI port will come externally from the PHY. */
-	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
-	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
-			MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-	.init		= initialize_otg_port,
-	.portsc	= MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
-	.operating_mode	= FSL_USB2_DR_DEVICE,
-	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
-	.init		= initialize_usbh1_port,
-	.portsc	= MXC_EHCI_MODE_ULPI,
-};
-
-static bool otg_mode_host __initdata;
-
-static int __init babbage_otg_mode(char *options)
-{
-	if (!strcmp(options, "host"))
-		otg_mode_host = true;
-	else if (!strcmp(options, "device"))
-		otg_mode_host = false;
-	else
-		pr_info("otg_mode neither \"host\" nor \"device\". "
-			"Defaulting to device\n");
-	return 1;
-}
-__setup("otg_mode=", babbage_otg_mode);
-
-static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
-	{
-		.modalias = "mtd_dataflash",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.mode = SPI_MODE_0,
-		.platform_data = NULL,
-	},
-};
-
-static int mx51_babbage_spi_cs[] = {
-	BABBAGE_ECSPI1_CS0,
-	BABBAGE_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
-	.chipselect     = mx51_babbage_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
-	.cd_type = ESDHC_CD_CONTROLLER,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
-	.cd_gpio = BABBAGE_SD2_CD,
-	.wp_gpio = BABBAGE_SD2_WP,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_GPIO,
-};
-
-void __init imx51_babbage_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
-					 ARRAY_SIZE(mx51babbage_pads));
-}
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_babbage_init(void)
-{
-	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-	iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
-		PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
-
-	imx51_soc_init();
-
-	imx51_babbage_common_init();
-
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, NULL);
-	imx51_add_imx_uart(2, &uart_pdata);
-
-	babbage_fec_reset();
-	imx51_add_fec(NULL);
-
-	/* Set the PAD settings for the pwr key. */
-	mxc_iomux_v3_setup_pad(power_key);
-	imx_add_gpio_keys(&imx_button_data);
-
-	imx51_add_imx_i2c(0, &babbage_i2c_data);
-	imx51_add_imx_i2c(1, &babbage_i2c_data);
-	imx51_add_hsi2c(&babbage_hsi2c_data);
-
-	if (otg_mode_host)
-		imx51_add_mxc_ehci_otg(&dr_utmi_config);
-	else {
-		initialize_otg_port(NULL);
-		imx51_add_fsl_usb2_udc(&usb_pdata);
-	}
-
-	gpio_usbh1_active();
-	imx51_add_mxc_ehci_hs(1, &usbh1_config);
-	/* setback USBH1_STP to be function */
-	mxc_iomux_v3_setup_pad(usbh1stp);
-	babbage_usbhub_reset();
-
-	imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
-	imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
-
-	spi_register_board_info(mx51_babbage_spi_board_info,
-		ARRAY_SIZE(mx51_babbage_spi_board_info));
-	imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
-	imx51_add_imx2_wdt(0);
-}
-
-static void __init mx51_babbage_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
-	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.init_time	= mx51_babbage_timer_init,
-	.init_machine = mx51_babbage_init,
-	.init_late	= imx51_init_late,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 65222ea0df6d..bed081e58262 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -28,6 +28,9 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/sched_clock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 
@@ -328,3 +331,15 @@ void __init mxc_timer_init(void __iomem *base, int irq)
 	/* Make irqs happen */
 	setup_irq(irq, &mxc_timer_irq);
 }
+
+void __init mxc_timer_init_dt(struct device_node *np)
+{
+	void __iomem *base;
+	int irq;
+
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	irq = irq_of_parse_and_map(np, 0);
+
+	mxc_timer_init(base, irq);
+}
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 0f92ba8e7884..037c00622de6 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -108,6 +108,7 @@ config ARCH_R8A7778
 	select SH_CLK_CPG
 	select ARM_GIC
 	select SYS_SUPPORTS_SH_TMU
+	select RENESAS_INTC_IRQPIN
 
 config ARCH_R8A7779
 	bool "R-Car H1 (R8A77790)"
@@ -140,16 +141,6 @@ config ARCH_R8A7791
 	select SYS_SUPPORTS_SH_CMT
 	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 
-config ARCH_EMEV2
-	bool "Emma Mobile EV2"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select ARM_GIC
-	select CPU_V7
-	select MIGHT_HAVE_PCI
-	select USE_OF
-	select AUTO_ZRELADDR
-	select SYS_SUPPORTS_EM_STI
-
 config ARCH_R7S72100
 	bool "RZ/A1H (R7S72100)"
 	select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -205,8 +196,8 @@ config MACH_ARMADILLO800EVA_REFERENCE
 	select SND_SOC_WM8978 if SND_SIMPLE_CARD
 	select USE_OF
 	---help---
-	   Use reference implementation of Aramdillo800 EVA board support
-	   which makes a greater use of device tree at the expense
+	   Use reference implementation of Armadillo800 EVA board support
+	   which makes greater use of device tree at the expense
 	   of not supporting a number of devices.
 
 	   This is intended to aid developers
@@ -216,7 +207,6 @@ config MACH_BOCKW
 	depends on ARCH_R8A7778
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-	select RENESAS_INTC_IRQPIN
 	select SND_SOC_AK4554 if SND_SIMPLE_CARD
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
 	select USE_OF
@@ -225,7 +215,6 @@ config MACH_BOCKW_REFERENCE
 	bool "BOCK-W  - Reference Device Tree Implementation"
 	depends on ARCH_R8A7778
 	select ARCH_REQUIRE_GPIOLIB
-	select RENESAS_INTC_IRQPIN
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select USE_OF
 	---help---
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 4caffc912a81..9c5cd8c53a85 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -21,8 +21,8 @@ obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)	+= setup-r7s72100.o
 
 # Clock objects
-ifndef CONFIG_COMMON_CLK
 obj-y				+= clock.o
+ifndef CONFIG_COMMON_CLK
 obj-$(CONFIG_ARCH_SH7372)	+= clock-sh7372.o
 obj-$(CONFIG_ARCH_SH73A0)	+= clock-sh73a0.o
 obj-$(CONFIG_ARCH_R8A73A4)	+= clock-r8a73a4.o
@@ -31,7 +31,6 @@ obj-$(CONFIG_ARCH_R8A7778)	+= clock-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)	+= clock-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)	+= clock-r8a7790.o
 obj-$(CONFIG_ARCH_R8A7791)	+= clock-r8a7791.o
-obj-$(CONFIG_ARCH_EMEV2)	+= clock-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)	+= clock-r7s72100.o
 endif
 
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 2858f380beae..486063db2a2f 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -992,6 +992,7 @@ static struct asoc_simple_card_info fsi_wm8978_info = {
 	.platform	= "sh_fsi2",
 	.daifmt		= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
 	.cpu_dai = {
+		.fmt	= SND_SOC_DAIFMT_IB_NF,
 		.name	= "fsia-dai",
 	},
 	.codec_dai = {
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index b4122f8cb8d9..f444be2f241e 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -345,24 +345,39 @@ static struct rsnd_ssi_platform_info rsnd_ssi[] = {
 	RSND_SSI_UNUSED, /* SSI 0 */
 	RSND_SSI_UNUSED, /* SSI 1 */
 	RSND_SSI_UNUSED, /* SSI 2 */
-	RSND_SSI_SET(1, HPBDMA_SLAVE_HPBIF3_TX, gic_iid(0x85), RSND_SSI_PLAY),
-	RSND_SSI_SET(2, HPBDMA_SLAVE_HPBIF4_RX, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE),
-	RSND_SSI_SET(0, HPBDMA_SLAVE_HPBIF5_TX, gic_iid(0x86), RSND_SSI_PLAY),
-	RSND_SSI_SET(0, HPBDMA_SLAVE_HPBIF6_RX, gic_iid(0x86), 0),
-	RSND_SSI_SET(3, HPBDMA_SLAVE_HPBIF7_TX, gic_iid(0x86), RSND_SSI_PLAY),
-	RSND_SSI_SET(4, HPBDMA_SLAVE_HPBIF8_RX, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF3_TX, gic_iid(0x85), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF4_RX, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF5_TX, gic_iid(0x86), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF6_RX, gic_iid(0x86), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF7_TX, gic_iid(0x86), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF8_RX, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE),
 };
 
-static struct rsnd_scu_platform_info rsnd_scu[9] = {
-	{ .flags = 0, }, /* SRU 0 */
-	{ .flags = 0, }, /* SRU 1 */
-	{ .flags = 0, }, /* SRU 2 */
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
+static struct rsnd_src_platform_info rsnd_src[9] = {
+	RSND_SRC_UNUSED, /* SRU 0 */
+	RSND_SRC_UNUSED, /* SRU 1 */
+	RSND_SRC_UNUSED, /* SRU 2 */
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+};
+
+static struct rsnd_dai_platform_info rsnd_dai[] = {
+	{
+		.playback = { .ssi = &rsnd_ssi[5], .src = &rsnd_src[5] },
+		.capture  = { .ssi = &rsnd_ssi[6], .src = &rsnd_src[6] },
+	}, {
+		.playback = { .ssi = &rsnd_ssi[3], .src = &rsnd_src[3] },
+	}, {
+		.capture  = { .ssi = &rsnd_ssi[4], .src = &rsnd_src[4] },
+	}, {
+		.playback = { .ssi = &rsnd_ssi[7], .src = &rsnd_src[7] },
+	}, {
+		.capture  = { .ssi = &rsnd_ssi[8], .src = &rsnd_src[8] },
+	},
 };
 
 enum {
@@ -437,8 +452,10 @@ static struct rcar_snd_info rsnd_info = {
 	.flags		= RSND_GEN1,
 	.ssi_info	= rsnd_ssi,
 	.ssi_info_nr	= ARRAY_SIZE(rsnd_ssi),
-	.scu_info	= rsnd_scu,
-	.scu_info_nr	= ARRAY_SIZE(rsnd_scu),
+	.src_info	= rsnd_src,
+	.src_info_nr	= ARRAY_SIZE(rsnd_src),
+	.dai_info	= rsnd_dai,
+	.dai_info_nr	= ARRAY_SIZE(rsnd_dai),
 	.start		= rsnd_start,
 	.stop		= rsnd_stop,
 };
@@ -591,6 +608,7 @@ static void __init bockw_init(void)
 {
 	void __iomem *base;
 	struct clk *clk;
+	struct platform_device *pdev;
 	int i;
 
 	r8a7778_clock_init();
@@ -673,9 +691,6 @@ static void __init bockw_init(void)
 	}
 
 	/* for Audio */
-	clk = clk_get(NULL, "audio_clk_b");
-	clk_set_rate(clk, 24576000);
-	clk_put(clk);
 	rsnd_codec_power(5, 1); /* enable ak4642 */
 
 	platform_device_register_simple(
@@ -684,11 +699,15 @@ static void __init bockw_init(void)
 	platform_device_register_simple(
 		"ak4554-adc-dac", 1, NULL, 0);
 
-	platform_device_register_resndata(
+	pdev = platform_device_register_resndata(
 		&platform_bus, "rcar_sound", -1,
 		rsnd_resources, ARRAY_SIZE(rsnd_resources),
 		&rsnd_info, sizeof(rsnd_info));
 
+	clk = clk_get(&pdev->dev, "clk_b");
+	clk_set_rate(clk, 24576000);
+	clk_put(clk);
+
 	for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
 		struct platform_device_info cardinfo = {
 			.parent         = &platform_bus,
diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index a3fd30242bd8..941f8b394e84 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -19,12 +19,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/rcar-du.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/rcar-gen2.h>
@@ -82,49 +81,50 @@ static void __init koelsch_add_du_device(void)
 	platform_device_register_full(&info);
 }
 
-static void __init koelsch_add_standard_devices(void)
-{
-	/*
-	 * This is a really crude hack to provide clkdev support to the CMT and
-	 * DU devices until they get moved to DT.
-	 */
-	static const struct clk_name {
-		const char *clk;
-		const char *con_id;
-		const char *dev_id;
-	} clk_names[] = {
-		{ "cmt0", NULL, "sh_cmt.0" },
-		{ "scifa0", NULL, "sh-sci.0" },
-		{ "scifa1", NULL, "sh-sci.1" },
-		{ "scifb0", NULL, "sh-sci.2" },
-		{ "scifb1", NULL, "sh-sci.3" },
-		{ "scifb2", NULL, "sh-sci.4" },
-		{ "scifa2", NULL, "sh-sci.5" },
-		{ "scif0", NULL, "sh-sci.6" },
-		{ "scif1", NULL, "sh-sci.7" },
-		{ "scif2", NULL, "sh-sci.8" },
-		{ "scif3", NULL, "sh-sci.9" },
-		{ "scif4", NULL, "sh-sci.10" },
-		{ "scif5", NULL, "sh-sci.11" },
-		{ "scifa3", NULL, "sh-sci.12" },
-		{ "scifa4", NULL, "sh-sci.13" },
-		{ "scifa5", NULL, "sh-sci.14" },
-		{ "du0", "du.0", "rcar-du-r8a7791" },
-		{ "du1", "du.1", "rcar-du-r8a7791" },
-		{ "lvds0", "lvds.0", "rcar-du-r8a7791" },
-	};
-	struct clk *clk;
-	unsigned int i;
+/*
+ * This is a really crude hack to provide clkdev support to platform
+ * devices until they get moved to DT.
+ */
+static const struct clk_name clk_names[] __initconst = {
+	{ "cmt0", NULL, "sh_cmt.0" },
+	{ "scifa0", NULL, "sh-sci.0" },
+	{ "scifa1", NULL, "sh-sci.1" },
+	{ "scifb0", NULL, "sh-sci.2" },
+	{ "scifb1", NULL, "sh-sci.3" },
+	{ "scifb2", NULL, "sh-sci.4" },
+	{ "scifa2", NULL, "sh-sci.5" },
+	{ "scif0", NULL, "sh-sci.6" },
+	{ "scif1", NULL, "sh-sci.7" },
+	{ "scif2", NULL, "sh-sci.8" },
+	{ "scif3", NULL, "sh-sci.9" },
+	{ "scif4", NULL, "sh-sci.10" },
+	{ "scif5", NULL, "sh-sci.11" },
+	{ "scifa3", NULL, "sh-sci.12" },
+	{ "scifa4", NULL, "sh-sci.13" },
+	{ "scifa5", NULL, "sh-sci.14" },
+	{ "du0", "du.0", "rcar-du-r8a7791" },
+	{ "du1", "du.1", "rcar-du-r8a7791" },
+	{ "lvds0", "lvds.0", "rcar-du-r8a7791" },
+};
 
-	for (i = 0; i < ARRAY_SIZE(clk_names); ++i) {
-		clk = clk_get(NULL, clk_names[i].clk);
-		if (!IS_ERR(clk)) {
-			clk_register_clkdev(clk, clk_names[i].con_id,
-					    clk_names[i].dev_id);
-			clk_put(clk);
-		}
-	}
+/*
+ * This is a really crude hack to work around core platform clock issues
+ */
+static const struct clk_name clk_enables[] __initconst = {
+	{ "ether", NULL, "ee700000.ethernet" },
+	{ "i2c2", NULL, "e6530000.i2c" },
+	{ "msiof0", NULL, "e6e20000.spi" },
+	{ "qspi_mod", NULL, "e6b10000.spi" },
+	{ "sdhi0", NULL, "ee100000.sd" },
+	{ "sdhi1", NULL, "ee140000.sd" },
+	{ "sdhi2", NULL, "ee160000.sd" },
+	{ "thermal", NULL, "e61f0000.thermal" },
+};
 
+static void __init koelsch_add_standard_devices(void)
+{
+	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
+	shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
 	r8a7791_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
index 5a034ff405d0..a12a9d3b4b6e 100644
--- a/arch/arm/mach-shmobile/board-koelsch.c
+++ b/arch/arm/mach-shmobile/board-koelsch.c
@@ -216,7 +216,7 @@ static const struct spi_board_info spi_info[] __initconst = {
 	{
 		.modalias	= "m25p80",
 		.platform_data	= &spi_flash_data,
-		.mode		= SPI_MODE_0,
+		.mode		= SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD,
 		.max_speed_hz	= 30000000,
 		.bus_num	= 0,
 		.chip_select	= 0,
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 440aac36d693..1eb48cffb4c5 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -18,12 +18,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/rcar-du.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/rcar-gen2.h>
@@ -86,46 +85,46 @@ static void __init lager_add_du_device(void)
 	platform_device_register_full(&info);
 }
 
-static void __init lager_add_standard_devices(void)
-{
-	/*
-	 * This is a really crude hack to provide clkdev support to platform
-	 * devices until they get moved to DT.
-	 */
-	static const struct clk_name {
-		const char *clk;
-		const char *con_id;
-		const char *dev_id;
-	} clk_names[] = {
-		{ "cmt0", NULL, "sh_cmt.0" },
-		{ "scifa0", NULL, "sh-sci.0" },
-		{ "scifa1", NULL, "sh-sci.1" },
-		{ "scifb0", NULL, "sh-sci.2" },
-		{ "scifb1", NULL, "sh-sci.3" },
-		{ "scifb2", NULL, "sh-sci.4" },
-		{ "scifa2", NULL, "sh-sci.5" },
-		{ "scif0", NULL, "sh-sci.6" },
-		{ "scif1", NULL, "sh-sci.7" },
-		{ "hscif0", NULL, "sh-sci.8" },
-		{ "hscif1", NULL, "sh-sci.9" },
-		{ "du0", "du.0", "rcar-du-r8a7790" },
-		{ "du1", "du.1", "rcar-du-r8a7790" },
-		{ "du2", "du.2", "rcar-du-r8a7790" },
-		{ "lvds0", "lvds.0", "rcar-du-r8a7790" },
-		{ "lvds1", "lvds.1", "rcar-du-r8a7790" },
-	};
-	struct clk *clk;
-	unsigned int i;
+/*
+ * This is a really crude hack to provide clkdev support to platform
+ * devices until they get moved to DT.
+ */
+static const struct clk_name clk_names[] __initconst = {
+	{ "cmt0", NULL, "sh_cmt.0" },
+	{ "scifa0", NULL, "sh-sci.0" },
+	{ "scifa1", NULL, "sh-sci.1" },
+	{ "scifb0", NULL, "sh-sci.2" },
+	{ "scifb1", NULL, "sh-sci.3" },
+	{ "scifb2", NULL, "sh-sci.4" },
+	{ "scifa2", NULL, "sh-sci.5" },
+	{ "scif0", NULL, "sh-sci.6" },
+	{ "scif1", NULL, "sh-sci.7" },
+	{ "hscif0", NULL, "sh-sci.8" },
+	{ "hscif1", NULL, "sh-sci.9" },
+	{ "du0", "du.0", "rcar-du-r8a7790" },
+	{ "du1", "du.1", "rcar-du-r8a7790" },
+	{ "du2", "du.2", "rcar-du-r8a7790" },
+	{ "lvds0", "lvds.0", "rcar-du-r8a7790" },
+	{ "lvds1", "lvds.1", "rcar-du-r8a7790" },
+};
 
-	for (i = 0; i < ARRAY_SIZE(clk_names); ++i) {
-		clk = clk_get(NULL, clk_names[i].clk);
-		if (!IS_ERR(clk)) {
-			clk_register_clkdev(clk, clk_names[i].con_id,
-					    clk_names[i].dev_id);
-			clk_put(clk);
-		}
-	}
+/*
+ * This is a really crude hack to work around core platform clock issues
+ */
+static const struct clk_name clk_enables[] __initconst = {
+	{ "ether", NULL, "ee700000.ethernet" },
+	{ "msiof1", NULL, "e6e10000.spi" },
+	{ "mmcif1", NULL, "ee220000.mmc" },
+	{ "qspi_mod", NULL, "e6b10000.spi" },
+	{ "sdhi0", NULL, "ee100000.sd" },
+	{ "sdhi2", NULL, "ee140000.sd" },
+	{ "thermal", NULL, "e61f0000.thermal" },
+};
 
+static void __init lager_add_standard_devices(void)
+{
+	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
+	shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
 	r8a7790_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index f0104bfe544e..f8b1e05463cc 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -325,12 +325,12 @@ static const struct rspi_plat_data qspi_pdata __initconst = {
 
 static const struct spi_board_info spi_info[] __initconst = {
 	{
-		.modalias               = "m25p80",
-		.platform_data          = &spi_flash_data,
-		.mode                   = SPI_MODE_0,
-		.max_speed_hz           = 30000000,
-		.bus_num                = 0,
-		.chip_select            = 0,
+		.modalias	= "m25p80",
+		.platform_data	= &spi_flash_data,
+		.mode		= SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD,
+		.max_speed_hz	= 30000000,
+		.bus_num	= 0,
+		.chip_select	= 0,
 	},
 };
 
@@ -567,20 +567,27 @@ static struct resource rsnd_resources[] __initdata = {
 };
 
 static struct rsnd_ssi_platform_info rsnd_ssi[] = {
-	RSND_SSI_SET(0, 0, gic_spi(370), RSND_SSI_PLAY),
-	RSND_SSI_SET(0, 0, gic_spi(371), RSND_SSI_CLK_PIN_SHARE),
+	RSND_SSI(0, gic_spi(370), 0),
+	RSND_SSI(0, gic_spi(371), RSND_SSI_CLK_PIN_SHARE),
 };
 
-static struct rsnd_scu_platform_info rsnd_scu[2] = {
+static struct rsnd_src_platform_info rsnd_src[2] = {
 	/* no member at this point */
 };
 
+static struct rsnd_dai_platform_info rsnd_dai = {
+	.playback = { .ssi = &rsnd_ssi[0], },
+	.capture  = { .ssi = &rsnd_ssi[1], },
+};
+
 static struct rcar_snd_info rsnd_info = {
 	.flags		= RSND_GEN2,
 	.ssi_info	= rsnd_ssi,
 	.ssi_info_nr	= ARRAY_SIZE(rsnd_ssi),
-	.scu_info	= rsnd_scu,
-	.scu_info_nr	= ARRAY_SIZE(rsnd_scu),
+	.src_info	= rsnd_src,
+	.src_info_nr	= ARRAY_SIZE(rsnd_src),
+	.dai_info	= &rsnd_dai,
+	.dai_info_nr	= 1,
 };
 
 static struct asoc_simple_card_info rsnd_card_info = {
@@ -588,14 +595,12 @@ static struct asoc_simple_card_info rsnd_card_info = {
 	.card		= "SSI01-AK4643",
 	.codec		= "ak4642-codec.2-0012",
 	.platform	= "rcar_sound",
-	.daifmt		= SND_SOC_DAIFMT_LEFT_J,
+	.daifmt		= SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM,
 	.cpu_dai = {
 		.name	= "rcar_sound",
-		.fmt	= SND_SOC_DAIFMT_CBS_CFS,
 	},
 	.codec_dai = {
 		.name	= "ak4642-hifi",
-		.fmt	= SND_SOC_DAIFMT_CBM_CFM,
 		.sysclk	= 11289600,
 	},
 };
diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
deleted file mode 100644
index 5ac13ba71d54..000000000000
--- a/arch/arm/mach-shmobile/clock-emev2.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Emma Mobile EV2 clock framework support
- *
- * Copyright (C) 2012  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/sh_clk.h>
-#include <linux/clkdev.h>
-#include <mach/common.h>
-
-#define EMEV2_SMU_BASE 0xe0110000
-
-/* EMEV2 SMU registers */
-#define USIAU0_RSTCTRL 0x094
-#define USIBU1_RSTCTRL 0x0ac
-#define USIBU2_RSTCTRL 0x0b0
-#define USIBU3_RSTCTRL 0x0b4
-#define STI_RSTCTRL 0x124
-#define USIAU0GCLKCTRL 0x4a0
-#define USIBU1GCLKCTRL 0x4b8
-#define USIBU2GCLKCTRL 0x4bc
-#define USIBU3GCLKCTRL 0x04c0
-#define STIGCLKCTRL 0x528
-#define USIAU0SCLKDIV 0x61c
-#define USIB2SCLKDIV 0x65c
-#define USIB3SCLKDIV 0x660
-#define STI_CLKSEL 0x688
-
-/* not pretty, but hey */
-static void __iomem *smu_base;
-
-static void emev2_smu_write(unsigned long value, int offs)
-{
-	BUG_ON(!smu_base || (offs >= PAGE_SIZE));
-	iowrite32(value, smu_base + offs);
-}
-
-static struct clk_mapping smu_mapping = {
-	.phys	= EMEV2_SMU_BASE,
-	.len	= PAGE_SIZE,
-};
-
-/* Fixed 32 KHz root clock from C32K pin */
-static struct clk c32k_clk = {
-	.rate           = 32768,
-	.mapping	= &smu_mapping,
-};
-
-/* PLL3 multiplies C32K with 7000 */
-static unsigned long pll3_recalc(struct clk *clk)
-{
-	return clk->parent->rate * 7000;
-}
-
-static struct sh_clk_ops pll3_clk_ops = {
-	.recalc		= pll3_recalc,
-};
-
-static struct clk pll3_clk = {
-	.ops		= &pll3_clk_ops,
-	.parent		= &c32k_clk,
-};
-
-static struct clk *main_clks[] = {
-	&c32k_clk,
-	&pll3_clk,
-};
-
-enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3,
-	SCLKDIV_NR };
-
-#define SCLKDIV(_reg, _shift)			\
-{								\
-	.parent		= &pll3_clk,				\
-	.enable_reg	= IOMEM(EMEV2_SMU_BASE + (_reg)),	\
-	.enable_bit	= _shift,				\
-}
-
-static struct clk sclkdiv_clks[SCLKDIV_NR] = {
-	[SCLKDIV_USIAU0] = SCLKDIV(USIAU0SCLKDIV, 0),
-	[SCLKDIV_USIBU2] = SCLKDIV(USIB2SCLKDIV, 16),
-	[SCLKDIV_USIBU1] = SCLKDIV(USIB2SCLKDIV, 0),
-	[SCLKDIV_USIBU3] = SCLKDIV(USIB3SCLKDIV, 0),
-};
-
-enum { GCLK_USIAU0_SCLK, GCLK_USIBU1_SCLK, GCLK_USIBU2_SCLK, GCLK_USIBU3_SCLK,
-	GCLK_STI_SCLK,
-	GCLK_NR };
-
-#define GCLK_SCLK(_parent, _reg) \
-{								\
-	.parent		= _parent,				\
-	.enable_reg	= IOMEM(EMEV2_SMU_BASE + (_reg)),	\
-	.enable_bit	= 1, /* SCLK_GCC */			\
-}
-
-static struct clk gclk_clks[GCLK_NR] = {
-	[GCLK_USIAU0_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIAU0],
-				       USIAU0GCLKCTRL),
-	[GCLK_USIBU1_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU1],
-				       USIBU1GCLKCTRL),
-	[GCLK_USIBU2_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU2],
-				       USIBU2GCLKCTRL),
-	[GCLK_USIBU3_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU3],
-				       USIBU3GCLKCTRL),
-	[GCLK_STI_SCLK] = GCLK_SCLK(&c32k_clk, STIGCLKCTRL),
-};
-
-static int emev2_gclk_enable(struct clk *clk)
-{
-	iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
-		  clk->mapped_reg);
-	return 0;
-}
-
-static void emev2_gclk_disable(struct clk *clk)
-{
-	iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
-		  clk->mapped_reg);
-}
-
-static struct sh_clk_ops emev2_gclk_clk_ops = {
-	.enable		= emev2_gclk_enable,
-	.disable	= emev2_gclk_disable,
-	.recalc		= followparent_recalc,
-};
-
-static int __init emev2_gclk_register(struct clk *clks, int nr)
-{
-	struct clk *clkp;
-	int ret = 0;
-	int k;
-
-	for (k = 0; !ret && (k < nr); k++) {
-		clkp = clks + k;
-		clkp->ops = &emev2_gclk_clk_ops;
-		ret |= clk_register(clkp);
-	}
-
-	return ret;
-}
-
-static unsigned long emev2_sclkdiv_recalc(struct clk *clk)
-{
-	unsigned int sclk_div;
-
-	sclk_div = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0xff;
-
-	return clk->parent->rate / (sclk_div + 1);
-}
-
-static struct sh_clk_ops emev2_sclkdiv_clk_ops = {
-	.recalc		= emev2_sclkdiv_recalc,
-};
-
-static int __init emev2_sclkdiv_register(struct clk *clks, int nr)
-{
-	struct clk *clkp;
-	int ret = 0;
-	int k;
-
-	for (k = 0; !ret && (k < nr); k++) {
-		clkp = clks + k;
-		clkp->ops = &emev2_sclkdiv_clk_ops;
-		ret |= clk_register(clkp);
-	}
-
-	return ret;
-}
-
-static struct clk_lookup lookups[] = {
-	CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]),
-	CLKDEV_DEV_ID("e1020000.uart", &gclk_clks[GCLK_USIAU0_SCLK]),
-	CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]),
-	CLKDEV_DEV_ID("e1030000.uart", &gclk_clks[GCLK_USIBU1_SCLK]),
-	CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]),
-	CLKDEV_DEV_ID("e1040000.uart", &gclk_clks[GCLK_USIBU2_SCLK]),
-	CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]),
-	CLKDEV_DEV_ID("e1050000.uart", &gclk_clks[GCLK_USIBU3_SCLK]),
-	CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]),
-	CLKDEV_DEV_ID("e0180000.sti", &gclk_clks[GCLK_STI_SCLK]),
-};
-
-void __init emev2_clock_init(void)
-{
-	int k, ret = 0;
-
-	smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
-	BUG_ON(!smu_base);
-
-	/* setup STI timer to run on 32.768 kHz and deassert reset */
-	emev2_smu_write(0, STI_CLKSEL);
-	emev2_smu_write(1, STI_RSTCTRL);
-
-	/* deassert reset for UART0->UART3 */
-	emev2_smu_write(2, USIAU0_RSTCTRL);
-	emev2_smu_write(2, USIBU1_RSTCTRL);
-	emev2_smu_write(2, USIBU2_RSTCTRL);
-	emev2_smu_write(2, USIBU3_RSTCTRL);
-
-	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
-		ret = clk_register(main_clks[k]);
-
-	if (!ret)
-		ret = emev2_sclkdiv_register(sclkdiv_clks, SCLKDIV_NR);
-
-	if (!ret)
-		ret = emev2_gclk_register(gclk_clks, GCLK_NR);
-
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-	if (!ret)
-		shmobile_clk_init();
-	else
-		panic("failed to setup emev2 clocks\n");
-}
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index 2009a9bc6356..6609beb9b9b4 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -170,15 +170,11 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */
 	[MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  9, 0), /* SSI3 */
 	[MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  8, 0), /* SRU */
-	[MSTP007] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  7, 0), /* HSPI */
+	[MSTP007] = SH_CLK_MSTP32(&s_clk, MSTPCR0,  7, 0), /* HSPI */
 };
 
 static struct clk_lookup lookups[] = {
 	/* main */
-	CLKDEV_CON_ID("audio_clk_a",	&audio_clk_a),
-	CLKDEV_CON_ID("audio_clk_b",	&audio_clk_b),
-	CLKDEV_CON_ID("audio_clk_c",	&audio_clk_c),
-	CLKDEV_CON_ID("audio_clk_internal",	&s1_clk),
 	CLKDEV_CON_ID("shyway_clk",	&s_clk),
 	CLKDEV_CON_ID("peripheral_clk",	&p_clk),
 
@@ -234,15 +230,15 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]),
 	CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]),
 	CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]),
-	CLKDEV_ICK_ID("scu.0", "rcar_sound", &mstp_clks[MSTP531]),
-	CLKDEV_ICK_ID("scu.1", "rcar_sound", &mstp_clks[MSTP530]),
-	CLKDEV_ICK_ID("scu.2", "rcar_sound", &mstp_clks[MSTP529]),
-	CLKDEV_ICK_ID("scu.3", "rcar_sound", &mstp_clks[MSTP528]),
-	CLKDEV_ICK_ID("scu.4", "rcar_sound", &mstp_clks[MSTP527]),
-	CLKDEV_ICK_ID("scu.5", "rcar_sound", &mstp_clks[MSTP526]),
-	CLKDEV_ICK_ID("scu.6", "rcar_sound", &mstp_clks[MSTP525]),
-	CLKDEV_ICK_ID("scu.7", "rcar_sound", &mstp_clks[MSTP524]),
-	CLKDEV_ICK_ID("scu.8", "rcar_sound", &mstp_clks[MSTP523]),
+	CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP531]),
+	CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP530]),
+	CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP529]),
+	CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP528]),
+	CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP527]),
+	CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP526]),
+	CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP525]),
+	CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP524]),
+	CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP523]),
 };
 
 void __init r8a7778_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index 3f93503f5b96..a936ae7de083 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -249,10 +249,10 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP1007] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 7, MSTPSR10, 0), /* SSI8 */
 	[MSTP1006] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 6, MSTPSR10, 0), /* SSI9 */
 	[MSTP1005] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 5, MSTPSR10, 0), /* SSI ALL */
-	[MSTP931] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
-	[MSTP930] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
-	[MSTP929] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
-	[MSTP928] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
+	[MSTP931] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
+	[MSTP930] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
+	[MSTP929] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
+	[MSTP928] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
 	[MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */
 	[MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */
 	[MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */
@@ -294,10 +294,6 @@ static struct clk mstp_clks[MSTP_NR] = {
 static struct clk_lookup lookups[] = {
 
 	/* main clocks */
-	CLKDEV_CON_ID("audio_clk_a",	&audio_clk_a),
-	CLKDEV_CON_ID("audio_clk_b",	&audio_clk_b),
-	CLKDEV_CON_ID("audio_clk_c",	&audio_clk_c),
-	CLKDEV_CON_ID("audio_clk_internal",	&m2_clk),
 	CLKDEV_CON_ID("extal",		&extal_clk),
 	CLKDEV_CON_ID("extal_div2",	&extal_div2_clk),
 	CLKDEV_CON_ID("main",		&main_clk),
@@ -381,16 +377,16 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b),
 	CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c),
 	CLKDEV_ICK_ID("clk_i", "rcar_sound", &m2_clk),
-	CLKDEV_ICK_ID("scu.0", "rcar_sound", &mstp_clks[MSTP1031]),
-	CLKDEV_ICK_ID("scu.1", "rcar_sound", &mstp_clks[MSTP1030]),
-	CLKDEV_ICK_ID("scu.2", "rcar_sound", &mstp_clks[MSTP1029]),
-	CLKDEV_ICK_ID("scu.3", "rcar_sound", &mstp_clks[MSTP1028]),
-	CLKDEV_ICK_ID("scu.4", "rcar_sound", &mstp_clks[MSTP1027]),
-	CLKDEV_ICK_ID("scu.5", "rcar_sound", &mstp_clks[MSTP1026]),
-	CLKDEV_ICK_ID("scu.6", "rcar_sound", &mstp_clks[MSTP1025]),
-	CLKDEV_ICK_ID("scu.7", "rcar_sound", &mstp_clks[MSTP1024]),
-	CLKDEV_ICK_ID("scu.8", "rcar_sound", &mstp_clks[MSTP1023]),
-	CLKDEV_ICK_ID("scu.9", "rcar_sound", &mstp_clks[MSTP1022]),
+	CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP1031]),
+	CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP1030]),
+	CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP1029]),
+	CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP1028]),
+	CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP1027]),
+	CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP1026]),
+	CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP1025]),
+	CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP1024]),
+	CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP1023]),
+	CLKDEV_ICK_ID("src.9", "rcar_sound", &mstp_clks[MSTP1022]),
 	CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP1015]),
 	CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP1014]),
 	CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP1013]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
index 701383fe3267..3b26c7eee873 100644
--- a/arch/arm/mach-shmobile/clock-r8a7791.c
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -25,6 +25,7 @@
 #include <linux/clkdev.h>
 #include <mach/clock.h>
 #include <mach/common.h>
+#include <mach/rcar-gen2.h>
 
 /*
  *   MD		EXTAL		PLL0	PLL1	PLL3
@@ -43,8 +44,6 @@
  *	see "p1 / 2" on R8A7791_CLOCK_ROOT() below
  */
 
-#define MD(nr)	(1 << nr)
-
 #define CPG_BASE 0xe6150000
 #define CPG_LEN 0x1000
 
@@ -68,7 +67,6 @@
 #define MSTPSR9		IOMEM(0xe61509a4)
 #define MSTPSR11	IOMEM(0xe61509ac)
 
-#define MODEMR		0xE6160060
 #define SDCKCR		0xE6150074
 #define SD1CKCR		0xE6150078
 #define SD2CKCR		0xE615026c
@@ -190,12 +188,12 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP1108] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 8, MSTPSR11, 0), /* SCIFA5 */
 	[MSTP1107] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 7, MSTPSR11, 0), /* SCIFA4 */
 	[MSTP1106] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 6, MSTPSR11, 0), /* SCIFA3 */
-	[MSTP931] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
-	[MSTP930] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
-	[MSTP929] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
-	[MSTP928] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
-	[MSTP927] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 27, MSTPSR9, 0), /* I2C4 */
-	[MSTP925] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 25, MSTPSR9, 0), /* I2C5 */
+	[MSTP931] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
+	[MSTP930] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
+	[MSTP929] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
+	[MSTP928] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
+	[MSTP927] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 27, MSTPSR9, 0), /* I2C4 */
+	[MSTP925] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 25, MSTPSR9, 0), /* I2C5 */
 	[MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */
 	[MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */
 	[MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */
@@ -295,14 +293,9 @@ static struct clk_lookup lookups[] = {
 
 void __init r8a7791_clock_init(void)
 {
-	void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
-	u32 mode;
+	u32 mode = rcar_gen2_read_mode_pins();
 	int k, ret = 0;
 
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
-
 	switch (mode & (MD(14) | MD(13))) {
 	case 0:
 		R8A7791_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
index ad7df629d995..e7232a0373b9 100644
--- a/arch/arm/mach-shmobile/clock.c
+++ b/arch/arm/mach-shmobile/clock.c
@@ -21,6 +21,32 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+
+#ifdef CONFIG_COMMON_CLK
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <mach/clock.h>
+
+void __init shmobile_clk_workaround(const struct clk_name *clks,
+				    int nr_clks, bool enable)
+{
+	const struct clk_name *clkn;
+	struct clk *clk;
+	unsigned int i;
+
+	for (i = 0; i < nr_clks; ++i) {
+		clkn = clks + i;
+		clk = clk_get(NULL, clkn->clk);
+		if (!IS_ERR(clk)) {
+			clk_register_clkdev(clk, clkn->con_id, clkn->dev_id);
+			if (enable)
+				clk_prepare_enable(clk);
+			clk_put(clk);
+		}
+	}
+}
+
+#else /* CONFIG_COMMON_CLK */
 #include <linux/sh_clk.h>
 #include <linux/export.h>
 #include <mach/clock.h>
@@ -58,3 +84,5 @@ void __clk_put(struct clk *clk)
 {
 }
 EXPORT_SYMBOL(__clk_put);
+
+#endif /* CONFIG_COMMON_CLK */
diff --git a/arch/arm/mach-shmobile/include/mach/clock.h b/arch/arm/mach-shmobile/include/mach/clock.h
index 03e56074928c..9a93cf924b9c 100644
--- a/arch/arm/mach-shmobile/include/mach/clock.h
+++ b/arch/arm/mach-shmobile/include/mach/clock.h
@@ -1,6 +1,21 @@
 #ifndef CLOCK_H
 #define CLOCK_H
 
+#ifdef CONFIG_COMMON_CLK
+/* temporary clock configuration helper for platform devices */
+
+struct clk_name {
+	const char *clk;
+	const char *con_id;
+	const char *dev_id;
+};
+
+void shmobile_clk_workaround(const struct clk_name *clks, int nr_clks,
+			     bool enable);
+
+#else /* CONFIG_COMMON_CLK */
+/* legacy clock implementation */
+
 unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk);
 extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops;
 
@@ -36,4 +51,5 @@ do {			\
 	(p)->div = d;	\
 } while (0)
 
+#endif /* CONFIG_COMMON_CLK */
 #endif
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index cb8e32deb2a3..f7a360edcc35 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -4,6 +4,7 @@
 extern void shmobile_earlytimer_init(void);
 extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
 			 unsigned int mult, unsigned int div);
+extern void shmobile_init_delay(void);
 struct twd_local_timer;
 extern void shmobile_setup_console(void);
 extern void shmobile_boot_vector(void);
diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
deleted file mode 100644
index fcb142a14e07..000000000000
--- a/arch/arm/mach-shmobile/include/mach/emev2.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __ASM_EMEV2_H__
-#define __ASM_EMEV2_H__
-
-extern void emev2_map_io(void);
-extern void emev2_init_delay(void);
-extern void emev2_clock_init(void);
-extern struct smp_operations emev2_smp_ops;
-
-#endif /* __ASM_EMEV2_H__ */
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index c71d667007b8..d953ff6e78a2 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <mach/common.h>
-#include <mach/emev2.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -38,23 +37,19 @@ static struct map_desc emev2_io_desc[] __initdata = {
 #endif
 };
 
-void __init emev2_map_io(void)
+static void __init emev2_map_io(void)
 {
 	iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
 }
 
-void __init emev2_init_delay(void)
+static void __init emev2_init_delay(void)
 {
 	shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
 }
 
 static void __init emev2_add_standard_devices_dt(void)
 {
-#ifdef CONFIG_COMMON_CLK
 	of_clk_init(NULL);
-#else
-	emev2_clock_init();
-#endif
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -63,6 +58,8 @@ static const char *emev2_boards_compat_dt[] __initconst = {
 	NULL,
 };
 
+extern struct smp_operations emev2_smp_ops;
+
 DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
 	.smp		= smp_ops(emev2_smp_ops),
 	.map_io		= emev2_map_io,
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index c4616f0698c6..a901d9ef53f6 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -185,12 +185,6 @@ void __init r8a7790_pinmux_init(void)
 	r8a7790_register_gpio(3);
 	r8a7790_register_gpio(4);
 	r8a7790_register_gpio(5);
-	r8a7790_register_i2c(0);
-	r8a7790_register_i2c(1);
-	r8a7790_register_i2c(2);
-	r8a7790_register_i2c(3);
-	r8a7790_register_audio_dmac(0);
-	r8a7790_register_audio_dmac(1);
 }
 
 #define __R8A7790_SCIF(scif_type, _scscr, index, baseaddr, irq)		\
@@ -308,6 +302,12 @@ void __init r8a7790_add_standard_devices(void)
 	r8a7790_add_dt_devices();
 	r8a7790_register_irqc(0);
 	r8a7790_register_thermal();
+	r8a7790_register_i2c(0);
+	r8a7790_register_i2c(1);
+	r8a7790_register_i2c(2);
+	r8a7790_register_i2c(3);
+	r8a7790_register_audio_dmac(0);
+	r8a7790_register_audio_dmac(1);
 }
 
 void __init r8a7790_init_early(void)
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
index e28404e43860..a7e4966f5e18 100644
--- a/arch/arm/mach-shmobile/setup-r8a7791.c
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -213,7 +213,7 @@ void __init r8a7791_add_standard_devices(void)
 void __init r8a7791_init_early(void)
 {
 #ifndef CONFIG_ARM_ARCH_TIMER
-	shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
+	shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
 #endif
 }
 
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index 10604480f325..542c5a47173f 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -30,12 +30,16 @@
 
 u32 rcar_gen2_read_mode_pins(void)
 {
-	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
-	u32 mode;
-
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
+	static u32 mode;
+	static bool mode_valid;
+
+	if (!mode_valid) {
+		void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+		BUG_ON(!modemr);
+		mode = ioread32(modemr);
+		iounmap(modemr);
+		mode_valid = true;
+	}
 
 	return mode;
 }
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index f2ca92308f75..2dfd748da7f3 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -24,7 +24,6 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <mach/common.h>
-#include <mach/emev2.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 
diff --git a/arch/arm/mach-shmobile/smp-r8a7791.c b/arch/arm/mach-shmobile/smp-r8a7791.c
index 2df5bd190fe4..ec979529f30f 100644
--- a/arch/arm/mach-shmobile/smp-r8a7791.c
+++ b/arch/arm/mach-shmobile/smp-r8a7791.c
@@ -20,6 +20,7 @@
 #include <asm/smp_plat.h>
 #include <mach/common.h>
 #include <mach/r8a7791.h>
+#include <mach/rcar-gen2.h>
 
 #define RST		0xe6160000
 #define CA15BAR		0x0020
@@ -51,9 +52,21 @@ static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
 	iounmap(p);
 }
 
+static int r8a7791_smp_boot_secondary(unsigned int cpu,
+				      struct task_struct *idle)
+{
+	/* Error out when hardware debug mode is enabled */
+	if (rcar_gen2_read_mode_pins() & BIT(21)) {
+		pr_warn("Unable to boot CPU%u when MD21 is set\n", cpu);
+		return -ENOTSUPP;
+	}
+
+	return shmobile_smp_apmu_boot_secondary(cpu, idle);
+}
+
 struct smp_operations r8a7791_smp_ops __initdata = {
 	.smp_prepare_cpus	= r8a7791_smp_prepare_cpus,
-	.smp_boot_secondary	= shmobile_smp_apmu_boot_secondary,
+	.smp_boot_secondary	= r8a7791_smp_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_disable		= shmobile_smp_cpu_disable,
 	.cpu_die		= shmobile_smp_apmu_cpu_die,
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index 62d7052d6f21..ccecde9a3362 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/clocksource.h>
 #include <linux/delay.h>
+#include <linux/of_address.h>
 
 void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
 				 unsigned int mult, unsigned int div)
@@ -39,6 +40,33 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
 		preset_lpj = max_cpu_core_mhz * value;
 }
 
+void __init shmobile_init_delay(void)
+{
+	struct device_node *np, *parent;
+	u32 max_freq, freq;
+
+	max_freq = 0;
+
+	parent = of_find_node_by_path("/cpus");
+	if (parent) {
+		for_each_child_of_node(parent, np) {
+			if (!of_property_read_u32(np, "clock-frequency", &freq))
+				max_freq = max(max_freq, freq);
+		}
+		of_node_put(parent);
+	}
+
+	if (max_freq) {
+		if (of_find_compatible_node(NULL, NULL, "arm,cortex-a8"))
+			shmobile_setup_delay(max_freq, 1, 3);
+		else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9"))
+			shmobile_setup_delay(max_freq, 1, 3);
+		else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a15"))
+			if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
+				shmobile_setup_delay(max_freq, 2, 4);
+	}
+}
+
 static void __init shmobile_late_time_init(void)
 {
 	/*
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 2a77ba8796ae..97c293e1897d 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -153,7 +153,6 @@ EXPORT_SYMBOL(arm_dma_zone_size);
  * allocations.  This must be the smallest DMA mask in the system,
  * so a successful GFP_DMA allocation will always satisfy this.
  */
-phys_addr_t arm_dma_limit;
 unsigned long arm_dma_pfn_limit;
 
 static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
@@ -172,6 +171,8 @@ static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
 void __init setup_dma_zone(const struct machine_desc *mdesc)
 {
 #ifdef CONFIG_ZONE_DMA
+	phys_addr_t arm_dma_limit;
+
 	if (mdesc->dma_zone_size) {
 		arm_dma_zone_size = mdesc->dma_zone_size;
 		arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
@@ -329,7 +330,8 @@ void __init arm_memblock_init(struct meminfo *mi,
 	 * reserve memory for DMA contigouos allocations,
 	 * must come from DMA area inside low memory
 	 */
-	dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit));
+	dma_contiguous_reserve(min((phys_addr_t)arm_dma_pfn_limit << PAGE_SHIFT,
+				   arm_lowmem_limit));
 
 	arm_memblock_steal_permitted = false;
 	memblock_dump_all();
@@ -578,7 +580,7 @@ void __init mem_init(void)
 			MLK(DTCM_OFFSET, (unsigned long) dtcm_end),
 			MLK(ITCM_OFFSET, (unsigned long) itcm_end),
 #endif
-			MLK(FIXADDR_START, FIXADDR_TOP),
+			MLK(FIXADDR_START, FIXADDR_END),
 			MLM(VMALLOC_START, VMALLOC_END),
 			MLM(PAGE_OFFSET, (unsigned long)high_memory),
 #ifdef CONFIG_HIGHMEM
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 7ea641b7aa7d..64a40d63cad5 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -81,10 +81,8 @@ extern __init void add_static_vm_early(struct static_vm *svm);
 #endif
 
 #ifdef CONFIG_ZONE_DMA
-extern phys_addr_t arm_dma_limit;
 extern unsigned long arm_dma_pfn_limit;
 #else
-#define arm_dma_limit ((phys_addr_t)~0)
 #define arm_dma_pfn_limit (~0ul >> PAGE_SHIFT)
 #endif
 
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index e6e4d3749a6e..df24b9323ac6 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
 	def_bool y
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_USE_CMPXCHG_LOCKREF
+	select ARCH_HAS_SG_CHAIN
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
index 93f4b2dd9248..4917f3b81a44 100644
--- a/arch/arm64/boot/dts/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
@@ -257,6 +257,19 @@
 				enable-offset = <0x0>;
 				enable-mask = <0x39>;
 			};
+
+			rtcclk: rtcclk@17000000 {
+				compatible = "apm,xgene-device-clock";
+				#clock-cells = <1>;
+				clocks = <&socplldiv2 0>;
+				reg = <0x0 0x17000000 0x0 0x2000>;
+				reg-names = "csr-reg";
+				csr-offset = <0xc>;
+				csr-mask = <0x2>;
+				enable-offset = <0x10>;
+				enable-mask = <0x2>;
+				clock-output-names = "rtcclk";
+			};
 		};
 
 		serial0: serial@1c020000 {
@@ -339,5 +352,13 @@
 			phys = <&phy3 0>;
 			phy-names = "sata-phy";
 		};
+
+		rtc: rtc@10510000 {
+			compatible = "apm,xgene-rtc";
+			reg = <0x0 0x10510000 0x0 0x400>;
+			interrupts = <0x0 0x46 0x4>;
+			#clock-cells = <1>;
+			clocks = <&rtcclk 0>;
+		};
 	};
 };
diff --git a/arch/blackfin/include/asm/bfin_spi3.h b/arch/blackfin/include/asm/bfin_spi3.h
deleted file mode 100644
index 0957e65a54be..000000000000
--- a/arch/blackfin/include/asm/bfin_spi3.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Analog Devices SPI3 controller driver
- *
- * Copyright (c) 2011 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _SPI_CHANNEL_H_
-#define _SPI_CHANNEL_H_
-
-#include <linux/types.h>
-
-/* SPI_CONTROL */
-#define SPI_CTL_EN                  0x00000001    /* Enable */
-#define SPI_CTL_MSTR                0x00000002    /* Master/Slave */
-#define SPI_CTL_PSSE                0x00000004    /* controls modf error in master mode */
-#define SPI_CTL_ODM                 0x00000008    /* Open Drain Mode */
-#define SPI_CTL_CPHA                0x00000010    /* Clock Phase */
-#define SPI_CTL_CPOL                0x00000020    /* Clock Polarity */
-#define SPI_CTL_ASSEL               0x00000040    /* Slave Select Pin Control */
-#define SPI_CTL_SELST               0x00000080    /* Slave Select Polarity in-between transfers */
-#define SPI_CTL_EMISO               0x00000100    /* Enable MISO */
-#define SPI_CTL_SIZE                0x00000600    /* Word Transfer Size */
-#define SPI_CTL_SIZE08              0x00000000    /* SIZE: 8 bits */
-#define SPI_CTL_SIZE16              0x00000200    /* SIZE: 16 bits */
-#define SPI_CTL_SIZE32              0x00000400    /* SIZE: 32 bits */
-#define SPI_CTL_LSBF                0x00001000    /* LSB First */
-#define SPI_CTL_FCEN                0x00002000    /* Flow-Control Enable */
-#define SPI_CTL_FCCH                0x00004000    /* Flow-Control Channel Selection */
-#define SPI_CTL_FCPL                0x00008000    /* Flow-Control Polarity */
-#define SPI_CTL_FCWM                0x00030000    /* Flow-Control Water-Mark */
-#define SPI_CTL_FIFO0               0x00000000    /* FCWM: TFIFO empty or RFIFO Full */
-#define SPI_CTL_FIFO1               0x00010000    /* FCWM: TFIFO 75% or more empty or RFIFO 75% or more full */
-#define SPI_CTL_FIFO2               0x00020000    /* FCWM: TFIFO 50% or more empty or RFIFO 50% or more full */
-#define SPI_CTL_FMODE               0x00040000    /* Fast-mode Enable */
-#define SPI_CTL_MIOM                0x00300000    /* Multiple I/O Mode */
-#define SPI_CTL_MIO_DIS             0x00000000    /* MIOM: Disable */
-#define SPI_CTL_MIO_DUAL            0x00100000    /* MIOM: Enable DIOM (Dual I/O Mode) */
-#define SPI_CTL_MIO_QUAD            0x00200000    /* MIOM: Enable QUAD (Quad SPI Mode) */
-#define SPI_CTL_SOSI                0x00400000    /* Start on MOSI */
-/* SPI_RX_CONTROL */
-#define SPI_RXCTL_REN               0x00000001    /* Receive Channel Enable */
-#define SPI_RXCTL_RTI               0x00000004    /* Receive Transfer Initiate */
-#define SPI_RXCTL_RWCEN             0x00000008    /* Receive Word Counter Enable */
-#define SPI_RXCTL_RDR               0x00000070    /* Receive Data Request */
-#define SPI_RXCTL_RDR_DIS           0x00000000    /* RDR: Disabled */
-#define SPI_RXCTL_RDR_NE            0x00000010    /* RDR: RFIFO not empty */
-#define SPI_RXCTL_RDR_25            0x00000020    /* RDR: RFIFO 25% full */
-#define SPI_RXCTL_RDR_50            0x00000030    /* RDR: RFIFO 50% full */
-#define SPI_RXCTL_RDR_75            0x00000040    /* RDR: RFIFO 75% full */
-#define SPI_RXCTL_RDR_FULL          0x00000050    /* RDR: RFIFO full */
-#define SPI_RXCTL_RDO               0x00000100    /* Receive Data Over-Run */
-#define SPI_RXCTL_RRWM              0x00003000    /* FIFO Regular Water-Mark */
-#define SPI_RXCTL_RWM_0             0x00000000    /* RRWM: RFIFO Empty */
-#define SPI_RXCTL_RWM_25            0x00001000    /* RRWM: RFIFO 25% full */
-#define SPI_RXCTL_RWM_50            0x00002000    /* RRWM: RFIFO 50% full */
-#define SPI_RXCTL_RWM_75            0x00003000    /* RRWM: RFIFO 75% full */
-#define SPI_RXCTL_RUWM              0x00070000    /* FIFO Urgent Water-Mark */
-#define SPI_RXCTL_UWM_DIS           0x00000000    /* RUWM: Disabled */
-#define SPI_RXCTL_UWM_25            0x00010000    /* RUWM: RFIFO 25% full */
-#define SPI_RXCTL_UWM_50            0x00020000    /* RUWM: RFIFO 50% full */
-#define SPI_RXCTL_UWM_75            0x00030000    /* RUWM: RFIFO 75% full */
-#define SPI_RXCTL_UWM_FULL          0x00040000    /* RUWM: RFIFO full */
-/* SPI_TX_CONTROL */
-#define SPI_TXCTL_TEN               0x00000001    /* Transmit Channel Enable */
-#define SPI_TXCTL_TTI               0x00000004    /* Transmit Transfer Initiate */
-#define SPI_TXCTL_TWCEN             0x00000008    /* Transmit Word Counter Enable */
-#define SPI_TXCTL_TDR               0x00000070    /* Transmit Data Request */
-#define SPI_TXCTL_TDR_DIS           0x00000000    /* TDR: Disabled */
-#define SPI_TXCTL_TDR_NF            0x00000010    /* TDR: TFIFO not full */
-#define SPI_TXCTL_TDR_25            0x00000020    /* TDR: TFIFO 25% empty */
-#define SPI_TXCTL_TDR_50            0x00000030    /* TDR: TFIFO 50% empty */
-#define SPI_TXCTL_TDR_75            0x00000040    /* TDR: TFIFO 75% empty */
-#define SPI_TXCTL_TDR_EMPTY         0x00000050    /* TDR: TFIFO empty */
-#define SPI_TXCTL_TDU               0x00000100    /* Transmit Data Under-Run */
-#define SPI_TXCTL_TRWM              0x00003000    /* FIFO Regular Water-Mark */
-#define SPI_TXCTL_RWM_FULL          0x00000000    /* TRWM: TFIFO full */
-#define SPI_TXCTL_RWM_25            0x00001000    /* TRWM: TFIFO 25% empty */
-#define SPI_TXCTL_RWM_50            0x00002000    /* TRWM: TFIFO 50% empty */
-#define SPI_TXCTL_RWM_75            0x00003000    /* TRWM: TFIFO 75% empty */
-#define SPI_TXCTL_TUWM              0x00070000    /* FIFO Urgent Water-Mark */
-#define SPI_TXCTL_UWM_DIS           0x00000000    /* TUWM: Disabled */
-#define SPI_TXCTL_UWM_25            0x00010000    /* TUWM: TFIFO 25% empty */
-#define SPI_TXCTL_UWM_50            0x00020000    /* TUWM: TFIFO 50% empty */
-#define SPI_TXCTL_UWM_75            0x00030000    /* TUWM: TFIFO 75% empty */
-#define SPI_TXCTL_UWM_EMPTY         0x00040000    /* TUWM: TFIFO empty */
-/* SPI_CLOCK */
-#define SPI_CLK_BAUD                0x0000FFFF    /* Baud Rate */
-/* SPI_DELAY */
-#define SPI_DLY_STOP                0x000000FF    /* Transfer delay time in multiples of SCK period */
-#define SPI_DLY_LEADX               0x00000100    /* Extended (1 SCK) LEAD Control */
-#define SPI_DLY_LAGX                0x00000200    /* Extended (1 SCK) LAG control */
-/* SPI_SSEL */
-#define SPI_SLVSEL_SSE1             0x00000002    /* SPISSEL1 Enable */
-#define SPI_SLVSEL_SSE2             0x00000004    /* SPISSEL2 Enable */
-#define SPI_SLVSEL_SSE3             0x00000008    /* SPISSEL3 Enable */
-#define SPI_SLVSEL_SSE4             0x00000010    /* SPISSEL4 Enable */
-#define SPI_SLVSEL_SSE5             0x00000020    /* SPISSEL5 Enable */
-#define SPI_SLVSEL_SSE6             0x00000040    /* SPISSEL6 Enable */
-#define SPI_SLVSEL_SSE7             0x00000080    /* SPISSEL7 Enable */
-#define SPI_SLVSEL_SSEL1            0x00000200    /* SPISSEL1 Value */
-#define SPI_SLVSEL_SSEL2            0x00000400    /* SPISSEL2 Value */
-#define SPI_SLVSEL_SSEL3            0x00000800    /* SPISSEL3 Value */
-#define SPI_SLVSEL_SSEL4            0x00001000    /* SPISSEL4 Value */
-#define SPI_SLVSEL_SSEL5            0x00002000    /* SPISSEL5 Value */
-#define SPI_SLVSEL_SSEL6            0x00004000    /* SPISSEL6 Value */
-#define SPI_SLVSEL_SSEL7            0x00008000    /* SPISSEL7 Value */
-/* SPI_RWC */
-#define SPI_RWC_VALUE               0x0000FFFF    /* Received Word-Count */
-/* SPI_RWCR */
-#define SPI_RWCR_VALUE              0x0000FFFF    /* Received Word-Count Reload */
-/* SPI_TWC */
-#define SPI_TWC_VALUE               0x0000FFFF    /* Transmitted Word-Count */
-/* SPI_TWCR */
-#define SPI_TWCR_VALUE              0x0000FFFF    /* Transmitted Word-Count Reload */
-/* SPI_IMASK */
-#define SPI_IMSK_RUWM               0x00000002    /* Receive Urgent Water-Mark Interrupt Mask */
-#define SPI_IMSK_TUWM               0x00000004    /* Transmit Urgent Water-Mark Interrupt Mask */
-#define SPI_IMSK_ROM                0x00000010    /* Receive Over-Run Error Interrupt Mask */
-#define SPI_IMSK_TUM                0x00000020    /* Transmit Under-Run Error Interrupt Mask */
-#define SPI_IMSK_TCM                0x00000040    /* Transmit Collision Error Interrupt Mask */
-#define SPI_IMSK_MFM                0x00000080    /* Mode Fault Error Interrupt Mask */
-#define SPI_IMSK_RSM                0x00000100    /* Receive Start Interrupt Mask */
-#define SPI_IMSK_TSM                0x00000200    /* Transmit Start Interrupt Mask */
-#define SPI_IMSK_RFM                0x00000400    /* Receive Finish Interrupt Mask */
-#define SPI_IMSK_TFM                0x00000800    /* Transmit Finish Interrupt Mask */
-/* SPI_IMASKCL */
-#define SPI_IMSK_CLR_RUW            0x00000002    /* Receive Urgent Water-Mark Interrupt Mask */
-#define SPI_IMSK_CLR_TUWM           0x00000004    /* Transmit Urgent Water-Mark Interrupt Mask */
-#define SPI_IMSK_CLR_ROM            0x00000010    /* Receive Over-Run Error Interrupt Mask */
-#define SPI_IMSK_CLR_TUM            0x00000020    /* Transmit Under-Run Error Interrupt Mask */
-#define SPI_IMSK_CLR_TCM            0x00000040    /* Transmit Collision Error Interrupt Mask */
-#define SPI_IMSK_CLR_MFM            0x00000080    /* Mode Fault Error Interrupt Mask */
-#define SPI_IMSK_CLR_RSM            0x00000100    /* Receive Start Interrupt Mask */
-#define SPI_IMSK_CLR_TSM            0x00000200    /* Transmit Start Interrupt Mask */
-#define SPI_IMSK_CLR_RFM            0x00000400    /* Receive Finish Interrupt Mask */
-#define SPI_IMSK_CLR_TFM            0x00000800    /* Transmit Finish Interrupt Mask */
-/* SPI_IMASKST */
-#define SPI_IMSK_SET_RUWM           0x00000002    /* Receive Urgent Water-Mark Interrupt Mask */
-#define SPI_IMSK_SET_TUWM           0x00000004    /* Transmit Urgent Water-Mark Interrupt Mask */
-#define SPI_IMSK_SET_ROM            0x00000010    /* Receive Over-Run Error Interrupt Mask */
-#define SPI_IMSK_SET_TUM            0x00000020    /* Transmit Under-Run Error Interrupt Mask */
-#define SPI_IMSK_SET_TCM            0x00000040    /* Transmit Collision Error Interrupt Mask */
-#define SPI_IMSK_SET_MFM            0x00000080    /* Mode Fault Error Interrupt Mask */
-#define SPI_IMSK_SET_RSM            0x00000100    /* Receive Start Interrupt Mask */
-#define SPI_IMSK_SET_TSM            0x00000200    /* Transmit Start Interrupt Mask */
-#define SPI_IMSK_SET_RFM            0x00000400    /* Receive Finish Interrupt Mask */
-#define SPI_IMSK_SET_TFM            0x00000800    /* Transmit Finish Interrupt Mask */
-/* SPI_STATUS */
-#define SPI_STAT_SPIF               0x00000001    /* SPI Finished */
-#define SPI_STAT_RUWM               0x00000002    /* Receive Urgent Water-Mark Breached */
-#define SPI_STAT_TUWM               0x00000004    /* Transmit Urgent Water-Mark Breached */
-#define SPI_STAT_ROE                0x00000010    /* Receive Over-Run Error Indication */
-#define SPI_STAT_TUE                0x00000020    /* Transmit Under-Run Error Indication */
-#define SPI_STAT_TCE                0x00000040    /* Transmit Collision Error Indication */
-#define SPI_STAT_MODF               0x00000080    /* Mode Fault Error Indication */
-#define SPI_STAT_RS                 0x00000100    /* Receive Start Indication */
-#define SPI_STAT_TS                 0x00000200    /* Transmit Start Indication */
-#define SPI_STAT_RF                 0x00000400    /* Receive Finish Indication */
-#define SPI_STAT_TF                 0x00000800    /* Transmit Finish Indication */
-#define SPI_STAT_RFS                0x00007000    /* SPI_RFIFO status */
-#define SPI_STAT_RFIFO_EMPTY        0x00000000    /* RFS: RFIFO Empty */
-#define SPI_STAT_RFIFO_25           0x00001000    /* RFS: RFIFO 25% Full */
-#define SPI_STAT_RFIFO_50           0x00002000    /* RFS: RFIFO 50% Full */
-#define SPI_STAT_RFIFO_75           0x00003000    /* RFS: RFIFO 75% Full */
-#define SPI_STAT_RFIFO_FULL         0x00004000    /* RFS: RFIFO Full */
-#define SPI_STAT_TFS                0x00070000    /* SPI_TFIFO status */
-#define SPI_STAT_TFIFO_FULL         0x00000000    /* TFS: TFIFO full */
-#define SPI_STAT_TFIFO_25           0x00010000    /* TFS: TFIFO 25% empty */
-#define SPI_STAT_TFIFO_50           0x00020000    /* TFS: TFIFO 50% empty */
-#define SPI_STAT_TFIFO_75           0x00030000    /* TFS: TFIFO 75% empty */
-#define SPI_STAT_TFIFO_EMPTY        0x00040000    /* TFS: TFIFO empty */
-#define SPI_STAT_FCS                0x00100000    /* Flow-Control Stall Indication */
-#define SPI_STAT_RFE                0x00400000    /* SPI_RFIFO Empty */
-#define SPI_STAT_TFF                0x00800000    /* SPI_TFIFO Full */
-/* SPI_ILAT */
-#define SPI_ILAT_RUWMI              0x00000002    /* Receive Urgent Water Mark Interrupt */
-#define SPI_ILAT_TUWMI              0x00000004    /* Transmit Urgent Water Mark Interrupt */
-#define SPI_ILAT_ROI                0x00000010    /* Receive Over-Run Error Indication */
-#define SPI_ILAT_TUI                0x00000020    /* Transmit Under-Run Error Indication */
-#define SPI_ILAT_TCI                0x00000040    /* Transmit Collision Error Indication */
-#define SPI_ILAT_MFI                0x00000080    /* Mode Fault Error Indication */
-#define SPI_ILAT_RSI                0x00000100    /* Receive Start Indication */
-#define SPI_ILAT_TSI                0x00000200    /* Transmit Start Indication */
-#define SPI_ILAT_RFI                0x00000400    /* Receive Finish Indication */
-#define SPI_ILAT_TFI                0x00000800    /* Transmit Finish Indication */
-/* SPI_ILATCL */
-#define SPI_ILAT_CLR_RUWMI          0x00000002    /* Receive Urgent Water Mark Interrupt */
-#define SPI_ILAT_CLR_TUWMI          0x00000004    /* Transmit Urgent Water Mark Interrupt */
-#define SPI_ILAT_CLR_ROI            0x00000010    /* Receive Over-Run Error Indication */
-#define SPI_ILAT_CLR_TUI            0x00000020    /* Transmit Under-Run Error Indication */
-#define SPI_ILAT_CLR_TCI            0x00000040    /* Transmit Collision Error Indication */
-#define SPI_ILAT_CLR_MFI            0x00000080    /* Mode Fault Error Indication */
-#define SPI_ILAT_CLR_RSI            0x00000100    /* Receive Start Indication */
-#define SPI_ILAT_CLR_TSI            0x00000200    /* Transmit Start Indication */
-#define SPI_ILAT_CLR_RFI            0x00000400    /* Receive Finish Indication */
-#define SPI_ILAT_CLR_TFI            0x00000800    /* Transmit Finish Indication */
-
-/*
- * bfin spi3 registers layout
- */
-struct bfin_spi_regs {
-	u32 revid;
-	u32 control;
-	u32 rx_control;
-	u32 tx_control;
-	u32 clock;
-	u32 delay;
-	u32 ssel;
-	u32 rwc;
-	u32 rwcr;
-	u32 twc;
-	u32 twcr;
-	u32 reserved0;
-	u32 emask;
-	u32 emaskcl;
-	u32 emaskst;
-	u32 reserved1;
-	u32 status;
-	u32 elat;
-	u32 elatcl;
-	u32 reserved2;
-	u32 rfifo;
-	u32 reserved3;
-	u32 tfifo;
-};
-
-#define MAX_CTRL_CS          8  /* cs in spi controller */
-
-/* device.platform_data for SSP controller devices */
-struct bfin_spi3_master {
-	u16 num_chipselect;
-	u16 pin_req[7];
-};
-
-/* spi_board_info.controller_data for SPI slave devices,
- * copied to spi_device.platform_data ... mostly for dma tuning
- */
-struct bfin_spi3_chip {
-	u32 control;
-	u16 cs_chg_udelay; /* Some devices require 16-bit delays */
-	u32 tx_dummy_val; /* tx value for rx only transfer */
-	bool enable_dma;
-};
-
-#endif /* _SPI_CHANNEL_H_ */
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c
index 943f7e95ec15..1ba4600de69f 100644
--- a/arch/blackfin/mach-bf609/boards/ezkit.c
+++ b/arch/blackfin/mach-bf609/boards/ezkit.c
@@ -20,7 +20,7 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinconf-generic.h>
 #include <linux/platform_data/pinctrl-adi2.h>
-#include <asm/bfin_spi3.h>
+#include <linux/spi/adi_spi3.h>
 #include <asm/dma.h>
 #include <asm/gpio.h>
 #include <asm/nand.h>
@@ -767,13 +767,13 @@ static struct flash_platform_data bfin_spi_flash_data = {
 	.type = "w25q32",
 };
 
-static struct bfin_spi3_chip spi_flash_chip_info = {
+static struct adi_spi3_chip spi_flash_chip_info = {
 	.enable_dma = true,         /* use dma transfer with this chip*/
 };
 #endif
 
 #if IS_ENABLED(CONFIG_SPI_SPIDEV)
-static struct bfin_spi3_chip spidev_chip_info = {
+static struct adi_spi3_chip spidev_chip_info = {
 	.enable_dma = true,
 };
 #endif
@@ -1736,7 +1736,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 };
-#if IS_ENABLED(CONFIG_SPI_BFIN_V3)
+#if IS_ENABLED(CONFIG_SPI_ADI_V3)
 /* SPI (0) */
 static struct resource bfin_spi0_resource[] = {
 	{
@@ -1777,13 +1777,13 @@ static struct resource bfin_spi1_resource[] = {
 };
 
 /* SPI controller data */
-static struct bfin_spi3_master bf60x_spi_master_info0 = {
+static struct adi_spi3_master bf60x_spi_master_info0 = {
 	.num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
 	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
 };
 
 static struct platform_device bf60x_spi_master0 = {
-	.name = "bfin-spi3",
+	.name = "adi-spi3",
 	.id = 0, /* Bus number */
 	.num_resources = ARRAY_SIZE(bfin_spi0_resource),
 	.resource = bfin_spi0_resource,
@@ -1792,13 +1792,13 @@ static struct platform_device bf60x_spi_master0 = {
 	},
 };
 
-static struct bfin_spi3_master bf60x_spi_master_info1 = {
+static struct adi_spi3_master bf60x_spi_master_info1 = {
 	.num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
 	.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
 };
 
 static struct platform_device bf60x_spi_master1 = {
-	.name = "bfin-spi3",
+	.name = "adi-spi3",
 	.id = 1, /* Bus number */
 	.num_resources = ARRAY_SIZE(bfin_spi1_resource),
 	.resource = bfin_spi1_resource,
@@ -1990,7 +1990,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
 	&bfin_sdh_device,
 #endif
 
-#if IS_ENABLED(CONFIG_SPI_BFIN_V3)
+#if IS_ENABLED(CONFIG_SPI_ADI_V3)
 	&bf60x_spi_master0,
 	&bf60x_spi_master1,
 #endif
@@ -2051,8 +2051,8 @@ static struct pinctrl_map __initdata bfin_pinmux_map[] = {
 	PIN_MAP_MUX_GROUP_DEFAULT("bfin_sir.1",  "pinctrl-adi2.0", NULL, "uart1"),
 	PIN_MAP_MUX_GROUP_DEFAULT("bfin-sdh.0",  "pinctrl-adi2.0", NULL, "rsi0"),
 	PIN_MAP_MUX_GROUP_DEFAULT("stmmaceth.0",  "pinctrl-adi2.0", NULL, "eth0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("bfin-spi3.0",  "pinctrl-adi2.0", NULL, "spi0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("bfin-spi3.1",  "pinctrl-adi2.0", NULL, "spi1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("adi-spi3.0",  "pinctrl-adi2.0", NULL, "spi0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("adi-spi3.1",  "pinctrl-adi2.0", NULL, "spi1"),
 	PIN_MAP_MUX_GROUP_DEFAULT("i2c-bfin-twi.0",  "pinctrl-adi2.0", NULL, "twi0"),
 	PIN_MAP_MUX_GROUP_DEFAULT("i2c-bfin-twi.1",  "pinctrl-adi2.0", NULL, "twi1"),
 	PIN_MAP_MUX_GROUP_DEFAULT("bfin-rotary",  "pinctrl-adi2.0", NULL, "rotary"),
diff --git a/arch/blackfin/mach-bf609/clock.c b/arch/blackfin/mach-bf609/clock.c
index 56200f37cfc8..244fa4ab4c56 100644
--- a/arch/blackfin/mach-bf609/clock.c
+++ b/arch/blackfin/mach-bf609/clock.c
@@ -363,6 +363,12 @@ static struct clk ethclk = {
 	.ops	    = &dummy_clk_ops,
 };
 
+static struct clk spiclk = {
+	.name       = "spi",
+	.parent     = &sclk1,
+	.ops        = &dummy_clk_ops,
+};
+
 static struct clk_lookup bf609_clks[] = {
 	CLK(sys_clkin, NULL, "SYS_CLKIN"),
 	CLK(pll_clk, NULL, "PLLCLK"),
@@ -375,6 +381,7 @@ static struct clk_lookup bf609_clks[] = {
 	CLK(dclk, NULL, "DCLK"),
 	CLK(oclk, NULL, "OCLK"),
 	CLK(ethclk, NULL, "stmmaceth"),
+	CLK(spiclk, NULL, "spi"),
 };
 
 int __init clk_init(void)
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index afff5105909d..31742dfadff9 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -13,6 +13,7 @@ generic-y += linkage.h
 generic-y += mcs_spinlock.h
 generic-y += module.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
diff --git a/arch/cris/include/asm/scatterlist.h b/arch/cris/include/asm/scatterlist.h
deleted file mode 100644
index f11f8f40ec4a..000000000000
--- a/arch/cris/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_CRIS_SCATTERLIST_H
-#define __ASM_CRIS_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(__ASM_CRIS_SCATTERLIST_H) */
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 87b95eb8aee5..5b73921b6e9d 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -5,4 +5,5 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff --git a/arch/frv/include/asm/scatterlist.h b/arch/frv/include/asm/scatterlist.h
deleted file mode 100644
index 0e5eb3018468..000000000000
--- a/arch/frv/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCATTERLIST_H
-#define _ASM_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !_ASM_SCATTERLIST_H */
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 12c3afee0f6f..43e7290fbccf 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -27,6 +27,7 @@ config IA64
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_VIRT_CPU_ACCOUNTING
+	select ARCH_HAS_SG_CHAIN
 	select VIRT_TO_BUS
 	select ARCH_DISCARD_MEMBLOCK
 	select GENERIC_IRQ_PROBE
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 0da4aa2602ae..e8317d2d6c8d 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -5,5 +5,6 @@ generic-y += hash.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += vtime.h
diff --git a/arch/ia64/include/asm/scatterlist.h b/arch/ia64/include/asm/scatterlist.h
deleted file mode 100644
index 08fd93bff1db..000000000000
--- a/arch/ia64/include/asm/scatterlist.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_IA64_SCATTERLIST_H
-#define _ASM_IA64_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_IA64_SCATTERLIST_H */
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index e6f80fcf013b..a4acddad0c78 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -259,7 +259,7 @@ start_ap:
 	 * Switch into virtual mode:
 	 */
 	movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
-		  |IA64_PSR_DI|IA64_PSR_AC)
+		  |IA64_PSR_DI)
 	;;
 	mov cr.ipsr=r16
 	movl r17=1f
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index 689ffcaa284e..18e794a57248 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -58,7 +58,7 @@
 #include <asm/unistd.h>
 #include <asm/errno.h>
 
-#if 1
+#if 0
 # define PSR_DEFAULT_BITS	psr.ac
 #else
 # define PSR_DEFAULT_BITS	0
diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S
index 24018484c6e9..397e34a63e18 100644
--- a/arch/ia64/kvm/vmm_ivt.S
+++ b/arch/ia64/kvm/vmm_ivt.S
@@ -64,7 +64,7 @@
 #include "kvm_minstate.h"
 #include "vti.h"
 
-#if 1
+#if 0
 # define PSR_DEFAULT_BITS   psr.ac
 #else
 # define PSR_DEFAULT_BITS   0
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 67779a74b62d..accc10a3dc78 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -6,4 +6,5 @@ generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += module.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff --git a/arch/m32r/include/asm/scatterlist.h b/arch/m32r/include/asm/scatterlist.h
deleted file mode 100644
index 7370b8b6243e..000000000000
--- a/arch/m32r/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_M32R_SCATTERLIST_H
-#define _ASM_M32R_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_M32R_SCATTERLIST_H */
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
index 214320b50384..8c8ce5e1ee0e 100644
--- a/arch/m68k/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal.h
@@ -60,15 +60,6 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
 	 __const_sigismember(set,sig) :		\
 	 __gen_sigismember(set,sig))
 
-static inline int sigfindinword(unsigned long word)
-{
-	asm ("bfffo %1{#0,#0},%0"
-		: "=d" (word)
-		: "d" (word & -word)
-		: "cc");
-	return word ^ 31;
-}
-
 #endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */
 
 #ifndef __uClinux__
diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c
index 5b16f5d61b44..88c27d94a721 100644
--- a/arch/m68k/kernel/setup_no.c
+++ b/arch/m68k/kernel/setup_no.c
@@ -58,17 +58,16 @@ void (*mach_halt)(void);
 void (*mach_power_off)(void);
 
 #ifdef CONFIG_M68000
-#define CPU_NAME	"MC68000"
-#endif
-#ifdef CONFIG_M68328
+#if defined(CONFIG_M68328)
 #define CPU_NAME	"MC68328"
-#endif
-#ifdef CONFIG_M68EZ328
+#elif defined(CONFIG_M68EZ328)
 #define CPU_NAME	"MC68EZ328"
-#endif
-#ifdef CONFIG_M68VZ328
+#elif defined(CONFIG_M68VZ328)
 #define CPU_NAME	"MC68VZ328"
+#else
+#define CPU_NAME	"MC68000"
 #endif
+#endif /* CONFIG_M68000 */
 #ifdef CONFIG_M68360
 #define CPU_NAME	"MC68360"
 #endif
diff --git a/arch/m68k/platform/68000/m68EZ328.c b/arch/m68k/platform/68000/m68EZ328.c
index 332b5e8605fc..21952906e9e2 100644
--- a/arch/m68k/platform/68000/m68EZ328.c
+++ b/arch/m68k/platform/68000/m68EZ328.c
@@ -69,7 +69,8 @@ void __init config_BSP(char *command, int len)
   if (p) strcpy(p,command);
   else command[0] = 0;
 #endif
- 
+
+  mach_sched_init = hw_timer_init;
   mach_hwclk = m68328_hwclk;
   mach_reset = m68ez328_reset;
 }
diff --git a/arch/m68k/platform/68000/m68VZ328.c b/arch/m68k/platform/68000/m68VZ328.c
index fd6658358af1..0e5e5a10a021 100644
--- a/arch/m68k/platform/68000/m68VZ328.c
+++ b/arch/m68k/platform/68000/m68VZ328.c
@@ -182,6 +182,7 @@ void __init config_BSP(char *command, int size)
 
 	init_hardware(command, size);
 
+	mach_sched_init = hw_timer_init;
 	mach_hwclk = m68328_hwclk;
 	mach_reset = m68vz328_reset;
 }
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c98ed95c0541..2ea655be809d 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -6,5 +6,6 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
diff --git a/arch/microblaze/include/asm/scatterlist.h b/arch/microblaze/include/asm/scatterlist.h
deleted file mode 100644
index 35d786fe93ae..000000000000
--- a/arch/microblaze/include/asm/scatterlist.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/scatterlist.h>
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
index 5abf4e894216..2a66e908f6a9 100644
--- a/arch/mips/dec/ecc-berr.c
+++ b/arch/mips/dec/ecc-berr.c
@@ -21,6 +21,7 @@
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/cpu-type.h>
 #include <asm/irq_regs.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
diff --git a/arch/mips/dec/kn02xa-berr.c b/arch/mips/dec/kn02xa-berr.c
index f434b759e3b9..ec606363b806 100644
--- a/arch/mips/dec/kn02xa-berr.c
+++ b/arch/mips/dec/kn02xa-berr.c
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
+#include <asm/cpu-type.h>
 #include <asm/irq_regs.h>
 #include <asm/ptrace.h>
 #include <asm/traps.h>
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
index 064ae7a76bdc..ae73e42ac20b 100644
--- a/arch/mips/dec/prom/Makefile
+++ b/arch/mips/dec/prom/Makefile
@@ -6,4 +6,3 @@
 lib-y			+= init.o memory.o cmdline.o identify.o console.o
 
 lib-$(CONFIG_32BIT)	+= locore.o
-lib-$(CONFIG_64BIT)	+= call_o32.o
diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S
deleted file mode 100644
index 8c8498159e43..000000000000
--- a/arch/mips/dec/prom/call_o32.S
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *	O32 interface for the 64 (or N32) ABI.
- *
- *	Copyright (C) 2002  Maciej W. Rozycki
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- */
-
-#include <asm/asm.h>
-#include <asm/regdef.h>
-
-/* Maximum number of arguments supported.  Must be even!  */
-#define O32_ARGC	32
-/* Number of static registers we save.  */
-#define O32_STATC	11
-/* Frame size for both of the above.  */
-#define O32_FRAMESZ	(4 * O32_ARGC + SZREG * O32_STATC)
-
-		.text
-
-/*
- * O32 function call dispatcher, for interfacing 32-bit ROM routines.
- *
- * The standard 64 (N32) calling sequence is supported, with a0
- * holding a function pointer, a1-a7 -- its first seven arguments
- * and the stack -- remaining ones (up to O32_ARGC, including a1-a7).
- * Static registers, gp and fp are preserved, v0 holds a result.
- * This code relies on the called o32 function for sp and ra
- * restoration and thus both this dispatcher and the current stack
- * have to be placed in a KSEGx (or KUSEG) address space.  Any
- * pointers passed have to point to addresses within one of these
- * spaces as well.
- */
-NESTED(call_o32, O32_FRAMESZ, ra)
-		REG_SUBU	sp,O32_FRAMESZ
-
-		REG_S		ra,O32_FRAMESZ-1*SZREG(sp)
-		REG_S		fp,O32_FRAMESZ-2*SZREG(sp)
-		REG_S		gp,O32_FRAMESZ-3*SZREG(sp)
-		REG_S		s7,O32_FRAMESZ-4*SZREG(sp)
-		REG_S		s6,O32_FRAMESZ-5*SZREG(sp)
-		REG_S		s5,O32_FRAMESZ-6*SZREG(sp)
-		REG_S		s4,O32_FRAMESZ-7*SZREG(sp)
-		REG_S		s3,O32_FRAMESZ-8*SZREG(sp)
-		REG_S		s2,O32_FRAMESZ-9*SZREG(sp)
-		REG_S		s1,O32_FRAMESZ-10*SZREG(sp)
-		REG_S		s0,O32_FRAMESZ-11*SZREG(sp)
-
-		move		jp,a0
-
-		sll		a0,a1,zero
-		sll		a1,a2,zero
-		sll		a2,a3,zero
-		sll		a3,a4,zero
-		sw		a5,0x10(sp)
-		sw		a6,0x14(sp)
-		sw		a7,0x18(sp)
-
-		PTR_LA		t0,O32_FRAMESZ(sp)
-		PTR_LA		t1,0x1c(sp)
-		li		t2,O32_ARGC-7
-1:
-		lw		t3,(t0)
-		REG_ADDU	t0,SZREG
-		sw		t3,(t1)
-		REG_SUBU	t2,1
-		REG_ADDU	t1,4
-		bnez		t2,1b
-
-		jalr		jp
-
-		REG_L		s0,O32_FRAMESZ-11*SZREG(sp)
-		REG_L		s1,O32_FRAMESZ-10*SZREG(sp)
-		REG_L		s2,O32_FRAMESZ-9*SZREG(sp)
-		REG_L		s3,O32_FRAMESZ-8*SZREG(sp)
-		REG_L		s4,O32_FRAMESZ-7*SZREG(sp)
-		REG_L		s5,O32_FRAMESZ-6*SZREG(sp)
-		REG_L		s6,O32_FRAMESZ-5*SZREG(sp)
-		REG_L		s7,O32_FRAMESZ-4*SZREG(sp)
-		REG_L		gp,O32_FRAMESZ-3*SZREG(sp)
-		REG_L		fp,O32_FRAMESZ-2*SZREG(sp)
-		REG_L		ra,O32_FRAMESZ-1*SZREG(sp)
-
-		REG_ADDU	sp,O32_FRAMESZ
-		jr		ra
-END(call_o32)
diff --git a/arch/mips/fw/lib/call_o32.S b/arch/mips/fw/lib/call_o32.S
index b308b2a0613e..4703fe4dbd9a 100644
--- a/arch/mips/fw/lib/call_o32.S
+++ b/arch/mips/fw/lib/call_o32.S
@@ -1,7 +1,7 @@
 /*
  *	O32 interface for the 64 (or N32) ABI.
  *
- *	Copyright (C) 2002  Maciej W. Rozycki
+ *	Copyright (C) 2002, 2014  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -12,28 +12,37 @@
 #include <asm/asm.h>
 #include <asm/regdef.h>
 
+/* O32 register size.  */
+#define O32_SZREG	4
 /* Maximum number of arguments supported.  Must be even!  */
 #define O32_ARGC	32
-/* Number of static registers we save.	*/
+/* Number of static registers we save.  */
 #define O32_STATC	11
-/* Frame size for static register  */
-#define O32_FRAMESZ	(SZREG * O32_STATC)
-/* Frame size on new stack */
-#define O32_FRAMESZ_NEW (SZREG + 4 * O32_ARGC)
+/* Argument area frame size.  */
+#define O32_ARGSZ	(O32_SZREG * O32_ARGC)
+/* Static register save area frame size.  */
+#define O32_STATSZ	(SZREG * O32_STATC)
+/* Stack pointer register save area frame size.  */
+#define O32_SPSZ	SZREG
+/* Combined area frame size.  */
+#define O32_FRAMESZ	(O32_ARGSZ + O32_SPSZ + O32_STATSZ)
+/* Switched stack frame size.  */
+#define O32_NFRAMESZ	(O32_ARGSZ + O32_SPSZ)
 
 		.text
 
 /*
  * O32 function call dispatcher, for interfacing 32-bit ROM routines.
  *
- * The standard 64 (N32) calling sequence is supported, with a0
- * holding a function pointer, a1 a new stack pointer, a2-a7 -- its
- * first six arguments and the stack -- remaining ones (up to O32_ARGC,
- * including a2-a7). Static registers, gp and fp are preserved, v0 holds
- * a result. This code relies on the called o32 function for sp and ra
- * restoration and this dispatcher has to be placed in a KSEGx (or KUSEG)
- * address space.  Any pointers passed have to point to addresses within
- * one of these spaces as well.
+ * The standard 64 (N32) calling sequence is supported, with a0 holding
+ * a function pointer, a1 a pointer to the new stack to call the
+ * function with or 0 if no stack switching is requested, a2-a7 -- the
+ * function call's first six arguments, and the stack -- the remaining
+ * arguments (up to O32_ARGC, including a2-a7).  Static registers, gp
+ * and fp are preserved, v0 holds the result.  This code relies on the
+ * called o32 function for sp and ra restoration and this dispatcher has
+ * to be placed in a KSEGx (or KUSEG) address space.  Any pointers
+ * passed have to point to addresses within one of these spaces as well.
  */
 NESTED(call_o32, O32_FRAMESZ, ra)
 		REG_SUBU	sp,O32_FRAMESZ
@@ -51,32 +60,36 @@ NESTED(call_o32, O32_FRAMESZ, ra)
 		REG_S		s0,O32_FRAMESZ-11*SZREG(sp)
 
 		move		jp,a0
-		REG_SUBU	s0,a1,O32_FRAMESZ_NEW
-		REG_S		sp,O32_FRAMESZ_NEW-1*SZREG(s0)
+
+		move		fp,sp
+		beqz		a1,0f
+		REG_SUBU	fp,a1,O32_NFRAMESZ
+0:
+		REG_S		sp,O32_NFRAMESZ-1*SZREG(fp)
 
 		sll		a0,a2,zero
 		sll		a1,a3,zero
 		sll		a2,a4,zero
 		sll		a3,a5,zero
-		sw		a6,0x10(s0)
-		sw		a7,0x14(s0)
+		sw		a6,4*O32_SZREG(fp)
+		sw		a7,5*O32_SZREG(fp)
 
 		PTR_LA		t0,O32_FRAMESZ(sp)
-		PTR_LA		t1,0x18(s0)
+		PTR_LA		t1,6*O32_SZREG(fp)
 		li		t2,O32_ARGC-6
 1:
 		lw		t3,(t0)
 		REG_ADDU	t0,SZREG
 		sw		t3,(t1)
 		REG_SUBU	t2,1
-		REG_ADDU	t1,4
+		REG_ADDU	t1,O32_SZREG
 		bnez		t2,1b
 
-		move		sp,s0
+		move		sp,fp
 
 		jalr		jp
 
-		REG_L		sp,O32_FRAMESZ_NEW-1*SZREG(sp)
+		REG_L		sp,O32_NFRAMESZ-1*SZREG(sp)
 
 		REG_L		s0,O32_FRAMESZ-11*SZREG(sp)
 		REG_L		s1,O32_FRAMESZ-10*SZREG(sp)
diff --git a/arch/mips/fw/sni/sniprom.c b/arch/mips/fw/sni/sniprom.c
index 2c2cb182af4e..6aa264b9856a 100644
--- a/arch/mips/fw/sni/sniprom.c
+++ b/arch/mips/fw/sni/sniprom.c
@@ -40,7 +40,8 @@
 
 #ifdef CONFIG_64BIT
 
-static u8 o32_stk[16384];
+/* O32 stack has to be 8-byte aligned. */
+static u64 o32_stk[4096];
 #define O32_STK	  &o32_stk[sizeof(o32_stk)]
 
 #define __PROM_O32(fun, arg) fun arg __asm__(#fun); \
diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h
index e28a3e0eb3cb..d109e34130f5 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_BRANCH_H
 #define _ASM_BRANCH_H
 
+#include <asm/cpu-features.h>
+#include <asm/mipsregs.h>
 #include <asm/ptrace.h>
 #include <asm/inst.h>
 
@@ -24,6 +26,16 @@ static inline int delay_slot(struct pt_regs *regs)
 	return regs->cp0_cause & CAUSEF_BD;
 }
 
+static inline void clear_delay_slot(struct pt_regs *regs)
+{
+	regs->cp0_cause &= ~CAUSEF_BD;
+}
+
+static inline void set_delay_slot(struct pt_regs *regs)
+{
+	regs->cp0_cause |= CAUSEF_BD;
+}
+
 static inline unsigned long exception_epc(struct pt_regs *regs)
 {
 	if (likely(!delay_slot(regs)))
diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h
index c0ead6313845..b59a2103b61a 100644
--- a/arch/mips/include/asm/dec/prom.h
+++ b/arch/mips/include/asm/dec/prom.h
@@ -113,31 +113,31 @@ extern int (*__pmax_close)(int);
 #define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \
 				 __asm__(#fun " = call_o32")
 
-int __DEC_PROM_O32(_rex_bootinit, (int (*)(void)));
-int __DEC_PROM_O32(_rex_bootread, (int (*)(void)));
-int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), memmap *));
+int __DEC_PROM_O32(_rex_bootinit, (int (*)(void), void *));
+int __DEC_PROM_O32(_rex_bootread, (int (*)(void), void *));
+int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), void *, memmap *));
 unsigned long *__DEC_PROM_O32(_rex_slot_address,
-			     (unsigned long *(*)(int), int));
-void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void)));
-int __DEC_PROM_O32(_rex_getsysid, (int (*)(void)));
-void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void)));
-
-int __DEC_PROM_O32(_prom_getchar, (int (*)(void)));
-char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), char *));
-int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), char *, ...));
-
-
-#define rex_bootinit()		_rex_bootinit(__rex_bootinit)
-#define rex_bootread()		_rex_bootread(__rex_bootread)
-#define rex_getbitmap(x)	_rex_getbitmap(__rex_getbitmap, x)
-#define rex_slot_address(x)	_rex_slot_address(__rex_slot_address, x)
-#define rex_gettcinfo()		_rex_gettcinfo(__rex_gettcinfo)
-#define rex_getsysid()		_rex_getsysid(__rex_getsysid)
-#define rex_clear_cache()	_rex_clear_cache(__rex_clear_cache)
-
-#define prom_getchar()		_prom_getchar(__prom_getchar)
-#define prom_getenv(x)		_prom_getenv(__prom_getenv, x)
-#define prom_printf(x...)	_prom_printf(__prom_printf, x)
+			     (unsigned long *(*)(int), void *, int));
+void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void), void *));
+int __DEC_PROM_O32(_rex_getsysid, (int (*)(void), void *));
+void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void), void *));
+
+int __DEC_PROM_O32(_prom_getchar, (int (*)(void), void *));
+char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), void *, char *));
+int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), void *, char *, ...));
+
+
+#define rex_bootinit()		_rex_bootinit(__rex_bootinit, NULL)
+#define rex_bootread()		_rex_bootread(__rex_bootread, NULL)
+#define rex_getbitmap(x)	_rex_getbitmap(__rex_getbitmap, NULL, x)
+#define rex_slot_address(x)	_rex_slot_address(__rex_slot_address, NULL, x)
+#define rex_gettcinfo()		_rex_gettcinfo(__rex_gettcinfo, NULL)
+#define rex_getsysid()		_rex_getsysid(__rex_getsysid, NULL)
+#define rex_clear_cache()	_rex_clear_cache(__rex_clear_cache, NULL)
+
+#define prom_getchar()		_prom_getchar(__prom_getchar, NULL)
+#define prom_getenv(x)		_prom_getenv(__prom_getenv, NULL, x)
+#define prom_printf(x...)	_prom_printf(__prom_printf, NULL, x)
 
 #else /* !CONFIG_64BIT */
 
diff --git a/arch/mips/include/asm/rm9k-ocd.h b/arch/mips/include/asm/rm9k-ocd.h
deleted file mode 100644
index b0b80d9ecf96..000000000000
--- a/arch/mips/include/asm/rm9k-ocd.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#if !defined(_ASM_RM9K_OCD_H)
-#define _ASM_RM9K_OCD_H
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-
-extern volatile void __iomem * const ocd_base;
-extern volatile void __iomem * const titan_base;
-
-#define ocd_addr(__x__)		(ocd_base + (__x__))
-#define titan_addr(__x__)	(titan_base + (__x__))
-#define scram_addr(__x__)	(scram_base + (__x__))
-
-/* OCD register access */
-#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__))
-#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__))
-#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__))
-#define ocd_writel(__val__, __offs__) \
-	__raw_writel((__val__), ocd_addr(__offs__))
-#define ocd_writew(__val__, __offs__) \
-	__raw_writew((__val__), ocd_addr(__offs__))
-#define ocd_writeb(__val__, __offs__) \
-	__raw_writeb((__val__), ocd_addr(__offs__))
-
-/* TITAN register access - 32 bit-wide only */
-#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__))
-#define titan_writel(__val__, __offs__) \
-	__raw_writel((__val__), titan_addr(__offs__))
-
-/* Protect access to shared TITAN registers */
-extern spinlock_t titan_lock;
-extern int titan_irqflags;
-#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags)
-#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags)
-
-#endif	/* !defined(_ASM_RM9K_OCD_H) */
diff --git a/arch/mips/include/uapi/asm/bitfield.h b/arch/mips/include/uapi/asm/bitfield.h
new file mode 100644
index 000000000000..ad9861359cea
--- /dev/null
+++ b/arch/mips/include/uapi/asm/bitfield.h
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __UAPI_ASM_BITFIELD_H
+#define __UAPI_ASM_BITFIELD_H
+
+/*
+ *  * Damn ...  bitfields depend from byteorder :-(
+ *   */
+#ifdef __MIPSEB__
+#define __BITFIELD_FIELD(field, more)					\
+	field;								\
+	more
+
+#elif defined(__MIPSEL__)
+
+#define __BITFIELD_FIELD(field, more)					\
+	more								\
+	field;
+
+#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */
+#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
+#endif
+
+#endif /* __UAPI_ASM_BITFIELD_H */
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index df6e775f3fef..fce8367da245 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -13,6 +13,8 @@
 #ifndef _UAPI_ASM_INST_H
 #define _UAPI_ASM_INST_H
 
+#include <asm/bitfield.h>
+
 /*
  * Major opcodes; before MIPS IV cop1x was called cop3.
  */
@@ -480,131 +482,113 @@ enum MIPS6e_i8_func {
  */
 #define MM_NOP16	0x0c00
 
-/*
- * Damn ...  bitfields depend from byteorder :-(
- */
-#ifdef __MIPSEB__
-#define BITFIELD_FIELD(field, more)					\
-	field;								\
-	more
-
-#elif defined(__MIPSEL__)
-
-#define BITFIELD_FIELD(field, more)					\
-	more								\
-	field;
-
-#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */
-#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
-#endif
-
 struct j_format {
-	BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */
-	BITFIELD_FIELD(unsigned int target : 26,
+	__BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */
+	__BITFIELD_FIELD(unsigned int target : 26,
 	;))
 };
 
 struct i_format {			/* signed immediate format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rs : 5,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(signed int simmediate : 16,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(signed int simmediate : 16,
 	;))))
 };
 
 struct u_format {			/* unsigned immediate format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rs : 5,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int uimmediate : 16,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int uimmediate : 16,
 	;))))
 };
 
 struct c_format {			/* Cache (>= R6000) format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rs : 5,
-	BITFIELD_FIELD(unsigned int c_op : 3,
-	BITFIELD_FIELD(unsigned int cache : 2,
-	BITFIELD_FIELD(unsigned int simmediate : 16,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(unsigned int c_op : 3,
+	__BITFIELD_FIELD(unsigned int cache : 2,
+	__BITFIELD_FIELD(unsigned int simmediate : 16,
 	;)))))
 };
 
 struct r_format {			/* Register format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rs : 5,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int rd : 5,
-	BITFIELD_FIELD(unsigned int re : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int rd : 5,
+	__BITFIELD_FIELD(unsigned int re : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct p_format {		/* Performance counter format (R10000) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rs : 5,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int rd : 5,
-	BITFIELD_FIELD(unsigned int re : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int rd : 5,
+	__BITFIELD_FIELD(unsigned int re : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct f_format {			/* FPU register format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int : 1,
-	BITFIELD_FIELD(unsigned int fmt : 4,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int rd : 5,
-	BITFIELD_FIELD(unsigned int re : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int : 1,
+	__BITFIELD_FIELD(unsigned int fmt : 4,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int rd : 5,
+	__BITFIELD_FIELD(unsigned int re : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;)))))))
 };
 
 struct ma_format {		/* FPU multiply and add format (MIPS IV) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int fr : 5,
-	BITFIELD_FIELD(unsigned int ft : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int func : 4,
-	BITFIELD_FIELD(unsigned int fmt : 2,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int fr : 5,
+	__BITFIELD_FIELD(unsigned int ft : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int func : 4,
+	__BITFIELD_FIELD(unsigned int fmt : 2,
 	;)))))))
 };
 
 struct b_format {			/* BREAK and SYSCALL */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int code : 20,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int code : 20,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;)))
 };
 
 struct ps_format {			/* MIPS-3D / paired single format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rs : 5,
-	BITFIELD_FIELD(unsigned int ft : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(unsigned int ft : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct v_format {				/* MDMX vector format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int sel : 4,
-	BITFIELD_FIELD(unsigned int fmt : 1,
-	BITFIELD_FIELD(unsigned int vt : 5,
-	BITFIELD_FIELD(unsigned int vs : 5,
-	BITFIELD_FIELD(unsigned int vd : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int sel : 4,
+	__BITFIELD_FIELD(unsigned int fmt : 1,
+	__BITFIELD_FIELD(unsigned int vt : 5,
+	__BITFIELD_FIELD(unsigned int vs : 5,
+	__BITFIELD_FIELD(unsigned int vd : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;)))))))
 };
 
 struct spec3_format {   /* SPEC3 */
-	BITFIELD_FIELD(unsigned int opcode:6,
-	BITFIELD_FIELD(unsigned int rs:5,
-	BITFIELD_FIELD(unsigned int rt:5,
-	BITFIELD_FIELD(signed int simmediate:9,
-	BITFIELD_FIELD(unsigned int func:7,
+	__BITFIELD_FIELD(unsigned int opcode:6,
+	__BITFIELD_FIELD(unsigned int rs:5,
+	__BITFIELD_FIELD(unsigned int rt:5,
+	__BITFIELD_FIELD(signed int simmediate:9,
+	__BITFIELD_FIELD(unsigned int func:7,
 	;)))))
 };
 
@@ -616,141 +600,141 @@ struct spec3_format {   /* SPEC3 */
  *	if it is MIPS32 instruction re-encoded for use in the microMIPS ASE.
  */
 struct fb_format {		/* FPU branch format (MIPS32) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int bc : 5,
-	BITFIELD_FIELD(unsigned int cc : 3,
-	BITFIELD_FIELD(unsigned int flag : 2,
-	BITFIELD_FIELD(signed int simmediate : 16,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int bc : 5,
+	__BITFIELD_FIELD(unsigned int cc : 3,
+	__BITFIELD_FIELD(unsigned int flag : 2,
+	__BITFIELD_FIELD(signed int simmediate : 16,
 	;)))))
 };
 
 struct fp0_format {		/* FPU multiply and add format (MIPS32) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int fmt : 5,
-	BITFIELD_FIELD(unsigned int ft : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int fmt : 5,
+	__BITFIELD_FIELD(unsigned int ft : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct mm_fp0_format {		/* FPU multipy and add format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int ft : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int fmt : 3,
-	BITFIELD_FIELD(unsigned int op : 2,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int ft : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int fmt : 3,
+	__BITFIELD_FIELD(unsigned int op : 2,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;)))))))
 };
 
 struct fp1_format {		/* FPU mfc1 and cfc1 format (MIPS32) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int op : 5,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int op : 5,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct mm_fp1_format {		/* FPU mfc1 and cfc1 format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fmt : 2,
-	BITFIELD_FIELD(unsigned int op : 8,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fmt : 2,
+	__BITFIELD_FIELD(unsigned int op : 8,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct mm_fp2_format {		/* FPU movt and movf format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int cc : 3,
-	BITFIELD_FIELD(unsigned int zero : 2,
-	BITFIELD_FIELD(unsigned int fmt : 2,
-	BITFIELD_FIELD(unsigned int op : 3,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int cc : 3,
+	__BITFIELD_FIELD(unsigned int zero : 2,
+	__BITFIELD_FIELD(unsigned int fmt : 2,
+	__BITFIELD_FIELD(unsigned int op : 3,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))))
 };
 
 struct mm_fp3_format {		/* FPU abs and neg format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fmt : 3,
-	BITFIELD_FIELD(unsigned int op : 7,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fmt : 3,
+	__BITFIELD_FIELD(unsigned int op : 7,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct mm_fp4_format {		/* FPU c.cond format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int cc : 3,
-	BITFIELD_FIELD(unsigned int fmt : 3,
-	BITFIELD_FIELD(unsigned int cond : 4,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int cc : 3,
+	__BITFIELD_FIELD(unsigned int fmt : 3,
+	__BITFIELD_FIELD(unsigned int cond : 4,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;)))))))
 };
 
 struct mm_fp5_format {		/* FPU lwxc1 and swxc1 format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int index : 5,
-	BITFIELD_FIELD(unsigned int base : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int op : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int index : 5,
+	__BITFIELD_FIELD(unsigned int base : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int op : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct fp6_format {		/* FPU madd and msub format (MIPS IV) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int fr : 5,
-	BITFIELD_FIELD(unsigned int ft : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int fr : 5,
+	__BITFIELD_FIELD(unsigned int ft : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct mm_fp6_format {		/* FPU madd and msub format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int ft : 5,
-	BITFIELD_FIELD(unsigned int fs : 5,
-	BITFIELD_FIELD(unsigned int fd : 5,
-	BITFIELD_FIELD(unsigned int fr : 5,
-	BITFIELD_FIELD(unsigned int func : 6,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int ft : 5,
+	__BITFIELD_FIELD(unsigned int fs : 5,
+	__BITFIELD_FIELD(unsigned int fd : 5,
+	__BITFIELD_FIELD(unsigned int fr : 5,
+	__BITFIELD_FIELD(unsigned int func : 6,
 	;))))))
 };
 
 struct mm_i_format {		/* Immediate format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(unsigned int rs : 5,
-	BITFIELD_FIELD(signed int simmediate : 16,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(unsigned int rs : 5,
+	__BITFIELD_FIELD(signed int simmediate : 16,
 	;))))
 };
 
 struct mm_m_format {		/* Multi-word load/store format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rd : 5,
-	BITFIELD_FIELD(unsigned int base : 5,
-	BITFIELD_FIELD(unsigned int func : 4,
-	BITFIELD_FIELD(signed int simmediate : 12,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rd : 5,
+	__BITFIELD_FIELD(unsigned int base : 5,
+	__BITFIELD_FIELD(unsigned int func : 4,
+	__BITFIELD_FIELD(signed int simmediate : 12,
 	;)))))
 };
 
 struct mm_x_format {		/* Scaled indexed load format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int index : 5,
-	BITFIELD_FIELD(unsigned int base : 5,
-	BITFIELD_FIELD(unsigned int rd : 5,
-	BITFIELD_FIELD(unsigned int func : 11,
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int index : 5,
+	__BITFIELD_FIELD(unsigned int base : 5,
+	__BITFIELD_FIELD(unsigned int rd : 5,
+	__BITFIELD_FIELD(unsigned int func : 11,
 	;)))))
 };
 
@@ -758,51 +742,51 @@ struct mm_x_format {		/* Scaled indexed load format (microMIPS) */
  * microMIPS instruction formats (16-bit length)
  */
 struct mm_b0_format {		/* Unconditional branch format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(signed int simmediate : 10,
-	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(signed int simmediate : 10,
+	__BITFIELD_FIELD(unsigned int : 16, /* Ignored */
 	;)))
 };
 
 struct mm_b1_format {		/* Conditional branch format (microMIPS) */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rs : 3,
-	BITFIELD_FIELD(signed int simmediate : 7,
-	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rs : 3,
+	__BITFIELD_FIELD(signed int simmediate : 7,
+	__BITFIELD_FIELD(unsigned int : 16, /* Ignored */
 	;))))
 };
 
 struct mm16_m_format {		/* Multi-word load/store format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int func : 4,
-	BITFIELD_FIELD(unsigned int rlist : 2,
-	BITFIELD_FIELD(unsigned int imm : 4,
-	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int func : 4,
+	__BITFIELD_FIELD(unsigned int rlist : 2,
+	__BITFIELD_FIELD(unsigned int imm : 4,
+	__BITFIELD_FIELD(unsigned int : 16, /* Ignored */
 	;)))))
 };
 
 struct mm16_rb_format {		/* Signed immediate format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rt : 3,
-	BITFIELD_FIELD(unsigned int base : 3,
-	BITFIELD_FIELD(signed int simmediate : 4,
-	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rt : 3,
+	__BITFIELD_FIELD(unsigned int base : 3,
+	__BITFIELD_FIELD(signed int simmediate : 4,
+	__BITFIELD_FIELD(unsigned int : 16, /* Ignored */
 	;)))))
 };
 
 struct mm16_r3_format {		/* Load from global pointer format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rt : 3,
-	BITFIELD_FIELD(signed int simmediate : 7,
-	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rt : 3,
+	__BITFIELD_FIELD(signed int simmediate : 7,
+	__BITFIELD_FIELD(unsigned int : 16, /* Ignored */
 	;))))
 };
 
 struct mm16_r5_format {		/* Load/store from stack pointer format */
-	BITFIELD_FIELD(unsigned int opcode : 6,
-	BITFIELD_FIELD(unsigned int rt : 5,
-	BITFIELD_FIELD(signed int simmediate : 5,
-	BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+	__BITFIELD_FIELD(unsigned int opcode : 6,
+	__BITFIELD_FIELD(unsigned int rt : 5,
+	__BITFIELD_FIELD(signed int simmediate : 5,
+	__BITFIELD_FIELD(unsigned int : 16, /* Ignored */
 	;))))
 };
 
@@ -810,57 +794,57 @@ struct mm16_r5_format {		/* Load/store from stack pointer format */
  * MIPS16e instruction formats (16-bit length)
  */
 struct m16e_rr {
-	BITFIELD_FIELD(unsigned int opcode : 5,
-	BITFIELD_FIELD(unsigned int rx : 3,
-	BITFIELD_FIELD(unsigned int nd : 1,
-	BITFIELD_FIELD(unsigned int l : 1,
-	BITFIELD_FIELD(unsigned int ra : 1,
-	BITFIELD_FIELD(unsigned int func : 5,
+	__BITFIELD_FIELD(unsigned int opcode : 5,
+	__BITFIELD_FIELD(unsigned int rx : 3,
+	__BITFIELD_FIELD(unsigned int nd : 1,
+	__BITFIELD_FIELD(unsigned int l : 1,
+	__BITFIELD_FIELD(unsigned int ra : 1,
+	__BITFIELD_FIELD(unsigned int func : 5,
 	;))))))
 };
 
 struct m16e_jal {
-	BITFIELD_FIELD(unsigned int opcode : 5,
-	BITFIELD_FIELD(unsigned int x : 1,
-	BITFIELD_FIELD(unsigned int imm20_16 : 5,
-	BITFIELD_FIELD(signed int imm25_21 : 5,
+	__BITFIELD_FIELD(unsigned int opcode : 5,
+	__BITFIELD_FIELD(unsigned int x : 1,
+	__BITFIELD_FIELD(unsigned int imm20_16 : 5,
+	__BITFIELD_FIELD(signed int imm25_21 : 5,
 	;))))
 };
 
 struct m16e_i64 {
-	BITFIELD_FIELD(unsigned int opcode : 5,
-	BITFIELD_FIELD(unsigned int func : 3,
-	BITFIELD_FIELD(unsigned int imm : 8,
+	__BITFIELD_FIELD(unsigned int opcode : 5,
+	__BITFIELD_FIELD(unsigned int func : 3,
+	__BITFIELD_FIELD(unsigned int imm : 8,
 	;)))
 };
 
 struct m16e_ri64 {
-	BITFIELD_FIELD(unsigned int opcode : 5,
-	BITFIELD_FIELD(unsigned int func : 3,
-	BITFIELD_FIELD(unsigned int ry : 3,
-	BITFIELD_FIELD(unsigned int imm : 5,
+	__BITFIELD_FIELD(unsigned int opcode : 5,
+	__BITFIELD_FIELD(unsigned int func : 3,
+	__BITFIELD_FIELD(unsigned int ry : 3,
+	__BITFIELD_FIELD(unsigned int imm : 5,
 	;))))
 };
 
 struct m16e_ri {
-	BITFIELD_FIELD(unsigned int opcode : 5,
-	BITFIELD_FIELD(unsigned int rx : 3,
-	BITFIELD_FIELD(unsigned int imm : 8,
+	__BITFIELD_FIELD(unsigned int opcode : 5,
+	__BITFIELD_FIELD(unsigned int rx : 3,
+	__BITFIELD_FIELD(unsigned int imm : 8,
 	;)))
 };
 
 struct m16e_rri {
-	BITFIELD_FIELD(unsigned int opcode : 5,
-	BITFIELD_FIELD(unsigned int rx : 3,
-	BITFIELD_FIELD(unsigned int ry : 3,
-	BITFIELD_FIELD(unsigned int imm : 5,
+	__BITFIELD_FIELD(unsigned int opcode : 5,
+	__BITFIELD_FIELD(unsigned int rx : 3,
+	__BITFIELD_FIELD(unsigned int ry : 3,
+	__BITFIELD_FIELD(unsigned int imm : 5,
 	;))))
 };
 
 struct m16e_i8 {
-	BITFIELD_FIELD(unsigned int opcode : 5,
-	BITFIELD_FIELD(unsigned int func : 3,
-	BITFIELD_FIELD(unsigned int imm : 8,
+	__BITFIELD_FIELD(unsigned int opcode : 5,
+	__BITFIELD_FIELD(unsigned int func : 3,
+	__BITFIELD_FIELD(unsigned int imm : 8,
 	;)))
 };
 
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index e40971b51d2f..037a44d962f3 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -124,14 +124,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 	seq_printf(m, "kscratch registers\t: %d\n",
 		      hweight8(cpu_data[n].kscratch_mask));
 	seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
-#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
-	if (cpu_has_mipsmt) {
-		seq_printf(m, "VPE\t\t\t: %d\n", cpu_data[n].vpe_id);
-#if defined(CONFIG_MIPS_MT_SMTC)
-		seq_printf(m, "TC\t\t\t: %d\n", cpu_data[n].tc_id);
-#endif
-	}
-#endif
+
 	sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
 		      cpu_has_vce ? "%u" : "not available");
 	seq_printf(m, fmt, 'D', vced_count);
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index 2e4825e48388..9901237563c5 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -56,14 +56,20 @@
 #define UNIT(unit)  ((unit)*NBYTES)
 
 #define ADDC(sum,reg)						\
+	.set	push;						\
+	.set	noat;						\
 	ADD	sum, reg;					\
 	sltu	v1, sum, reg;					\
 	ADD	sum, v1;					\
+	.set	pop
 
 #define ADDC32(sum,reg)						\
+	.set	push;						\
+	.set	noat;						\
 	addu	sum, reg;					\
 	sltu	v1, sum, reg;					\
 	addu	sum, v1;					\
+	.set	pop
 
 #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)	\
 	LOAD	_t0, (offset + UNIT(0))(src);			\
@@ -710,6 +716,8 @@ LEAF(csum_partial)
 	ADDC(sum, t2)
 .Ldone\@:
 	/* fold checksum */
+	.set	push
+	.set	noat
 #ifdef USE_DOUBLE
 	dsll32	v1, sum, 0
 	daddu	sum, v1
@@ -732,6 +740,7 @@ LEAF(csum_partial)
 	or	sum, sum, t0
 1:
 #endif
+	.set	pop
 	.set reorder
 	ADDC32(sum, psum)
 	jr	ra
diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c
index 44713af15a62..705cfb7c1a74 100644
--- a/arch/mips/lib/delay.c
+++ b/arch/mips/lib/delay.c
@@ -6,7 +6,7 @@
  * Copyright (C) 1994 by Waldorf Electronics
  * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2007  Maciej W. Rozycki
+ * Copyright (C) 2007, 2014 Maciej W. Rozycki
  */
 #include <linux/module.h>
 #include <linux/param.h>
@@ -15,6 +15,12 @@
 #include <asm/compiler.h>
 #include <asm/war.h>
 
+#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
+#define GCC_DADDI_IMM_ASM() "I"
+#else
+#define GCC_DADDI_IMM_ASM() "r"
+#endif
+
 void __delay(unsigned long loops)
 {
 	__asm__ __volatile__ (
@@ -22,13 +28,13 @@ void __delay(unsigned long loops)
 	"	.align	3					\n"
 	"1:	bnez	%0, 1b					\n"
 #if BITS_PER_LONG == 32
-	"	subu	%0, 1					\n"
+	"	subu	%0, %1					\n"
 #else
-	"	dsubu	%0, 1					\n"
+	"	dsubu	%0, %1					\n"
 #endif
 	"	.set	reorder					\n"
 	: "=r" (loops)
-	: "0" (loops));
+	: GCC_DADDI_IMM_ASM() (1), "0" (loops));
 }
 EXPORT_SYMBOL(__delay);
 
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
index d3301cd1e9a5..3c32baf8b494 100644
--- a/arch/mips/lib/strncpy_user.S
+++ b/arch/mips/lib/strncpy_user.S
@@ -35,7 +35,6 @@ LEAF(__strncpy_from_\func\()_asm)
 	bnez		v0, .Lfault\@
 
 FEXPORT(__strncpy_from_\func\()_nocheck_asm)
-	.set		noreorder
 	move		t0, zero
 	move		v1, a1
 .ifeqs "\func","kernel"
@@ -45,21 +44,21 @@ FEXPORT(__strncpy_from_\func\()_nocheck_asm)
 .endif
 	PTR_ADDIU	v1, 1
 	R10KCBARRIER(0(ra))
+	sb		v0, (a0)
 	beqz		v0, 2f
-	 sb		v0, (a0)
 	PTR_ADDIU	t0, 1
+	PTR_ADDIU	a0, 1
 	bne		t0, a2, 1b
-	 PTR_ADDIU	a0, 1
 2:	PTR_ADDU	v0, a1, t0
 	xor		v0, a1
 	bltz		v0, .Lfault\@
-	 nop
+	move		v0, t0
 	jr		ra			# return n
-	 move		v0, t0
 	END(__strncpy_from_\func\()_asm)
 
-.Lfault\@: jr		ra
-	  li		v0, -EFAULT
+.Lfault\@:
+	li		v0, -EFAULT
+	jr		ra
 
 	.section	__ex_table,"a"
 	PTR		1b, .Lfault\@
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 7397be226a06..603d79a95f47 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -64,7 +64,6 @@ config LEMOTE_MACH3A
 	bool "Lemote Loongson 3A family machines"
 	select ARCH_SPARSEMEM_ENABLE
 	select GENERIC_ISA_DMA_SUPPORT_BROKEN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select BOOT_ELF32
 	select BOARD_SCACHE
 	select CSRC_R4K
diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c
index e1f427f4f5f3..67dd94ef28e6 100644
--- a/arch/mips/loongson/lemote-2f/clock.c
+++ b/arch/mips/loongson/lemote-2f/clock.c
@@ -91,6 +91,7 @@ EXPORT_SYMBOL(clk_put);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
+	unsigned int rate_khz = rate / 1000;
 	int ret = 0;
 	int regval;
 	int i;
@@ -111,10 +112,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 		if (loongson2_clockmod_table[i].frequency ==
 		    CPUFREQ_ENTRY_INVALID)
 			continue;
-		if (rate == loongson2_clockmod_table[i].frequency)
+		if (rate_khz == loongson2_clockmod_table[i].frequency)
 			break;
 	}
-	if (rate != loongson2_clockmod_table[i].frequency)
+	if (rate_khz != loongson2_clockmod_table[i].frequency)
 		return -ENOTSUPP;
 
 	clk->rate = rate;
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile
index 121a848a3594..0803970dfc16 100644
--- a/arch/mips/math-emu/Makefile
+++ b/arch/mips/math-emu/Makefile
@@ -9,3 +9,5 @@ obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
 	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
 	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
 	   dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o
+
+obj-$(CONFIG_DEBUG_FS) += me-debugfs.o
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 7b3c9acae689..584e0b805909 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -34,20 +34,19 @@
  * better performance by compiling with -msoft-float!
  */
 #include <linux/sched.h>
-#include <linux/module.h>
 #include <linux/debugfs.h>
+#include <linux/percpu-defs.h>
 #include <linux/perf_event.h>
 
+#include <asm/branch.h>
 #include <asm/inst.h>
-#include <asm/bootinfo.h>
-#include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
-#include <asm/mipsregs.h>
+#include <asm/uaccess.h>
+
+#include <asm/processor.h>
 #include <asm/fpu_emulator.h>
 #include <asm/fpu.h>
-#include <asm/uaccess.h>
-#include <asm/branch.h>
 
 #include "ieee754.h"
 
@@ -68,12 +67,6 @@ static int fpux_emu(struct pt_regs *,
 	struct mips_fpu_struct *, mips_instruction, void *__user *);
 #endif
 
-/* Further private data for which no space exists in mips_fpu_struct */
-
-#ifdef CONFIG_DEBUG_FS
-DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
-#endif
-
 /* Control registers */
 
 #define FPCREG_RID	0	/* $0  = revision id */
@@ -876,14 +869,16 @@ static inline int cop1_64bit(struct pt_regs *xcp)
 #endif
 }
 
-#define SIFROMREG(si, x) do {						\
+#define SIFROMREG(si, x)						\
+do {									\
 	if (cop1_64bit(xcp))						\
 		(si) = get_fpr32(&ctx->fpr[x], 0);			\
 	else								\
 		(si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1);		\
 } while (0)
 
-#define SITOREG(si, x) do {						\
+#define SITOREG(si, x)							\
+do {									\
 	if (cop1_64bit(xcp)) {						\
 		unsigned i;						\
 		set_fpr32(&ctx->fpr[x], 0, si);				\
@@ -896,17 +891,19 @@ static inline int cop1_64bit(struct pt_regs *xcp)
 
 #define SIFROMHREG(si, x)	((si) = get_fpr32(&ctx->fpr[x], 1))
 
-#define SITOHREG(si, x) do {						\
+#define SITOHREG(si, x)							\
+do {									\
 	unsigned i;							\
 	set_fpr32(&ctx->fpr[x], 1, si);					\
 	for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++)		\
 		set_fpr32(&ctx->fpr[x], i, 0);				\
 } while (0)
 
-#define DIFROMREG(di, x) \
+#define DIFROMREG(di, x)						\
 	((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0))
 
-#define DITOREG(di, x) do {						\
+#define DITOREG(di, x)							\
+do {									\
 	unsigned fpr, i;						\
 	fpr = (x) & ~(cop1_64bit(xcp) == 0);				\
 	set_fpr64(&ctx->fpr[fpr], 0, di);				\
@@ -933,17 +930,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	int pc_inc;
 
 	/* XXX NEC Vr54xx bug workaround */
-	if (xcp->cp0_cause & CAUSEF_BD) {
+	if (delay_slot(xcp)) {
 		if (dec_insn.micro_mips_mode) {
 			if (!mm_isBranchInstr(xcp, dec_insn, &contpc))
-				xcp->cp0_cause &= ~CAUSEF_BD;
+				clear_delay_slot(xcp);
 		} else {
 			if (!isBranchInstr(xcp, dec_insn, &contpc))
-				xcp->cp0_cause &= ~CAUSEF_BD;
+				clear_delay_slot(xcp);
 		}
 	}
 
-	if (xcp->cp0_cause & CAUSEF_BD) {
+	if (delay_slot(xcp)) {
 		/*
 		 * The instruction to be emulated is in a branch delay slot
 		 * which means that we have to	emulate the branch instruction
@@ -1178,7 +1175,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		case bc_op:{
 			int likely = 0;
 
-			if (xcp->cp0_cause & CAUSEF_BD)
+			if (delay_slot(xcp))
 				return SIGILL;
 
 #if __mips >= 4
@@ -1201,7 +1198,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 				return SIGILL;
 			}
 
-			xcp->cp0_cause |= CAUSEF_BD;
+			set_delay_slot(xcp);
 			if (cond) {
 				/* branch taken: emulate dslot
 				 * instruction
@@ -1321,7 +1318,7 @@ sigill:
 
 	/* we did it !! */
 	xcp->cp0_epc = contpc;
-	xcp->cp0_cause &= ~CAUSEF_BD;
+	clear_delay_slot(xcp);
 
 	return 0;
 }
@@ -1348,38 +1345,38 @@ static const unsigned char cmptab[8] = {
  * Additional MIPS4 instructions
  */
 
-#define DEF3OP(name, p, f1, f2, f3) \
-static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \
-    ieee754##p t) \
-{ \
-	struct _ieee754_csr ieee754_csr_save; \
-	s = f1(s, t); \
-	ieee754_csr_save = ieee754_csr; \
-	s = f2(s, r); \
-	ieee754_csr_save.cx |= ieee754_csr.cx; \
-	ieee754_csr_save.sx |= ieee754_csr.sx; \
-	s = f3(s); \
-	ieee754_csr.cx |= ieee754_csr_save.cx; \
-	ieee754_csr.sx |= ieee754_csr_save.sx; \
-	return s; \
+#define DEF3OP(name, p, f1, f2, f3)					\
+static union ieee754##p fpemu_##p##_##name(union ieee754##p r,		\
+	union ieee754##p s, union ieee754##p t)				\
+{									\
+	struct _ieee754_csr ieee754_csr_save;				\
+	s = f1(s, t);							\
+	ieee754_csr_save = ieee754_csr;					\
+	s = f2(s, r);							\
+	ieee754_csr_save.cx |= ieee754_csr.cx;				\
+	ieee754_csr_save.sx |= ieee754_csr.sx;				\
+	s = f3(s);							\
+	ieee754_csr.cx |= ieee754_csr_save.cx;				\
+	ieee754_csr.sx |= ieee754_csr_save.sx;				\
+	return s;							\
 }
 
-static ieee754dp fpemu_dp_recip(ieee754dp d)
+static union ieee754dp fpemu_dp_recip(union ieee754dp d)
 {
 	return ieee754dp_div(ieee754dp_one(0), d);
 }
 
-static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+static union ieee754dp fpemu_dp_rsqrt(union ieee754dp d)
 {
 	return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
 }
 
-static ieee754sp fpemu_sp_recip(ieee754sp s)
+static union ieee754sp fpemu_sp_recip(union ieee754sp s)
 {
 	return ieee754sp_div(ieee754sp_one(0), s);
 }
 
-static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+static union ieee754sp fpemu_sp_rsqrt(union ieee754sp s)
 {
 	return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
 }
@@ -1403,8 +1400,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	switch (MIPSInst_FMA_FFMT(ir)) {
 	case s_fmt:{		/* 0 */
 
-		ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
-		ieee754sp fd, fr, fs, ft;
+		union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp);
+		union ieee754sp fd, fr, fs, ft;
 		u32 __user *va;
 		u32 val;
 
@@ -1492,8 +1489,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	}
 
 	case d_fmt:{		/* 1 */
-		ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
-		ieee754dp fd, fr, fs, ft;
+		union ieee754dp(*handler) (union ieee754dp, union ieee754dp, union ieee754dp);
+		union ieee754dp fd, fr, fs, ft;
 		u64 __user *va;
 		u64 val;
 
@@ -1588,8 +1585,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	unsigned rcsr = 0;	/* resulting csr */
 	unsigned cond;
 	union {
-		ieee754dp d;
-		ieee754sp s;
+		union ieee754dp d;
+		union ieee754sp s;
 		int w;
 #ifdef __mips64
 		s64 l;
@@ -1600,8 +1597,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
 	case s_fmt:{		/* 0 */
 		union {
-			ieee754sp(*b) (ieee754sp, ieee754sp);
-			ieee754sp(*u) (ieee754sp);
+			union ieee754sp(*b) (union ieee754sp, union ieee754sp);
+			union ieee754sp(*u) (union ieee754sp);
 		} handler;
 
 		switch (MIPSInst_FUNC(ir)) {
@@ -1666,7 +1663,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 			/* binary op on handler */
 		      scopbop:
 			{
-				ieee754sp fs, ft;
+				union ieee754sp fs, ft;
 
 				SPFROMREG(fs, MIPSInst_FS(ir));
 				SPFROMREG(ft, MIPSInst_FT(ir));
@@ -1676,7 +1673,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 			}
 		      scopuop:
 			{
-				ieee754sp fs;
+				union ieee754sp fs;
 
 				SPFROMREG(fs, MIPSInst_FS(ir));
 				rv.s = (*handler.u) (fs);
@@ -1699,7 +1696,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		case fcvts_op:
 			return SIGILL;	/* not defined */
 		case fcvtd_op:{
-			ieee754sp fs;
+			union ieee754sp fs;
 
 			SPFROMREG(fs, MIPSInst_FS(ir));
 			rv.d = ieee754dp_fsp(fs);
@@ -1707,7 +1704,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 			goto copcsr;
 		}
 		case fcvtw_op:{
-			ieee754sp fs;
+			union ieee754sp fs;
 
 			SPFROMREG(fs, MIPSInst_FS(ir));
 			rv.w = ieee754sp_tint(fs);
@@ -1721,7 +1718,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		case fceil_op:
 		case ffloor_op:{
 			unsigned int oldrm = ieee754_csr.rm;
-			ieee754sp fs;
+			union ieee754sp fs;
 
 			SPFROMREG(fs, MIPSInst_FS(ir));
 			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
@@ -1734,7 +1731,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
 #if defined(__mips64)
 		case fcvtl_op:{
-			ieee754sp fs;
+			union ieee754sp fs;
 
 			SPFROMREG(fs, MIPSInst_FS(ir));
 			rv.l = ieee754sp_tlong(fs);
@@ -1747,7 +1744,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		case fceill_op:
 		case ffloorl_op:{
 			unsigned int oldrm = ieee754_csr.rm;
-			ieee754sp fs;
+			union ieee754sp fs;
 
 			SPFROMREG(fs, MIPSInst_FS(ir));
 			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
@@ -1761,7 +1758,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		default:
 			if (MIPSInst_FUNC(ir) >= fcmp_op) {
 				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
-				ieee754sp fs, ft;
+				union ieee754sp fs, ft;
 
 				SPFROMREG(fs, MIPSInst_FS(ir));
 				SPFROMREG(ft, MIPSInst_FT(ir));
@@ -1785,8 +1782,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
 	case d_fmt:{
 		union {
-			ieee754dp(*b) (ieee754dp, ieee754dp);
-			ieee754dp(*u) (ieee754dp);
+			union ieee754dp(*b) (union ieee754dp, union ieee754dp);
+			union ieee754dp(*u) (union ieee754dp);
 		} handler;
 
 		switch (MIPSInst_FUNC(ir)) {
@@ -1852,7 +1849,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
 			/* binary op on handler */
 		      dcopbop:{
-				ieee754dp fs, ft;
+				union ieee754dp fs, ft;
 
 				DPFROMREG(fs, MIPSInst_FS(ir));
 				DPFROMREG(ft, MIPSInst_FT(ir));
@@ -1861,7 +1858,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 				goto copcsr;
 			}
 		      dcopuop:{
-				ieee754dp fs;
+				union ieee754dp fs;
 
 				DPFROMREG(fs, MIPSInst_FS(ir));
 				rv.d = (*handler.u) (fs);
@@ -1870,7 +1867,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
 			/* unary conv ops */
 		case fcvts_op:{
-			ieee754dp fs;
+			union ieee754dp fs;
 
 			DPFROMREG(fs, MIPSInst_FS(ir));
 			rv.s = ieee754sp_fdp(fs);
@@ -1881,7 +1878,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 			return SIGILL;	/* not defined */
 
 		case fcvtw_op:{
-			ieee754dp fs;
+			union ieee754dp fs;
 
 			DPFROMREG(fs, MIPSInst_FS(ir));
 			rv.w = ieee754dp_tint(fs);	/* wrong */
@@ -1895,7 +1892,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		case fceil_op:
 		case ffloor_op:{
 			unsigned int oldrm = ieee754_csr.rm;
-			ieee754dp fs;
+			union ieee754dp fs;
 
 			DPFROMREG(fs, MIPSInst_FS(ir));
 			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
@@ -1908,7 +1905,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
 #if defined(__mips64)
 		case fcvtl_op:{
-			ieee754dp fs;
+			union ieee754dp fs;
 
 			DPFROMREG(fs, MIPSInst_FS(ir));
 			rv.l = ieee754dp_tlong(fs);
@@ -1921,7 +1918,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		case fceill_op:
 		case ffloorl_op:{
 			unsigned int oldrm = ieee754_csr.rm;
-			ieee754dp fs;
+			union ieee754dp fs;
 
 			DPFROMREG(fs, MIPSInst_FS(ir));
 			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
@@ -1935,7 +1932,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 		default:
 			if (MIPSInst_FUNC(ir) >= fcmp_op) {
 				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
-				ieee754dp fs, ft;
+				union ieee754dp fs, ft;
 
 				DPFROMREG(fs, MIPSInst_FS(ir));
 				DPFROMREG(ft, MIPSInst_FT(ir));
@@ -1960,7 +1957,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	}
 
 	case w_fmt:{
-		ieee754sp fs;
+		union ieee754sp fs;
 
 		switch (MIPSInst_FUNC(ir)) {
 		case fcvts_op:
@@ -2160,53 +2157,3 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
 	return sig;
 }
-
-#ifdef CONFIG_DEBUG_FS
-
-static int fpuemu_stat_get(void *data, u64 *val)
-{
-	int cpu;
-	unsigned long sum = 0;
-	for_each_online_cpu(cpu) {
-		struct mips_fpu_emulator_stats *ps;
-		local_t *pv;
-		ps = &per_cpu(fpuemustats, cpu);
-		pv = (void *)ps + (unsigned long)data;
-		sum += local_read(pv);
-	}
-	*val = sum;
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
-
-extern struct dentry *mips_debugfs_dir;
-static int __init debugfs_fpuemu(void)
-{
-	struct dentry *d, *dir;
-
-	if (!mips_debugfs_dir)
-		return -ENODEV;
-	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
-	if (!dir)
-		return -ENOMEM;
-
-#define FPU_STAT_CREATE(M)						\
-	do {								\
-		d = debugfs_create_file(#M , S_IRUGO, dir,		\
-			(void *)offsetof(struct mips_fpu_emulator_stats, M), \
-			&fops_fpuemu_stat);				\
-		if (!d)							\
-			return -ENOMEM;					\
-	} while (0)
-
-	FPU_STAT_CREATE(emulated);
-	FPU_STAT_CREATE(loads);
-	FPU_STAT_CREATE(stores);
-	FPU_STAT_CREATE(cp1ops);
-	FPU_STAT_CREATE(cp1xops);
-	FPU_STAT_CREATE(errors);
-
-	return 0;
-}
-__initcall(debugfs_fpuemu);
-#endif
diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c
index c57c8adc42c4..b5aac129e9f1 100644
--- a/arch/mips/math-emu/dp_add.c
+++ b/arch/mips/math-emu/dp_add.c
@@ -27,7 +27,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y)
 {
 	COMPXDP;
 	COMPYDP;
diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c
index 0f32486b0ed9..a3b4984d2e83 100644
--- a/arch/mips/math-emu/dp_cmp.c
+++ b/arch/mips/math-emu/dp_cmp.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig)
+int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig)
 {
 	COMPXDP;
 	COMPYDP;
diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c
index a1bce1b7c09c..30cc7fa3ce37 100644
--- a/arch/mips/math-emu/dp_div.c
+++ b/arch/mips/math-emu/dp_div.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y)
 {
 	COMPXDP;
 	COMPYDP;
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c
index 88571288c9e0..60ed6ec7ddc7 100644
--- a/arch/mips/math-emu/dp_fint.c
+++ b/arch/mips/math-emu/dp_fint.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_fint(int x)
+union ieee754dp ieee754dp_fint(int x)
 {
 	u64 xm;
 	int xe;
@@ -70,7 +70,7 @@ ieee754dp ieee754dp_fint(int x)
 #endif
 }
 
-ieee754dp ieee754dp_funs(unsigned int u)
+union ieee754dp ieee754dp_funs(unsigned int u)
 {
 	if ((int) u < 0)
 		return ieee754dp_add(ieee754dp_1e31(),
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c
index 14fc01ec742d..2418f9d03055 100644
--- a/arch/mips/math-emu/dp_flong.c
+++ b/arch/mips/math-emu/dp_flong.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_flong(s64 x)
+union ieee754dp ieee754dp_flong(s64 x)
 {
 	u64 xm;
 	int xe;
@@ -68,7 +68,7 @@ ieee754dp ieee754dp_flong(s64 x)
 	DPNORMRET1(xs, xe, xm, "dp_flong", x);
 }
 
-ieee754dp ieee754dp_fulong(u64 u)
+union ieee754dp ieee754dp_fulong(u64 u)
 {
 	if ((s64) u < 0)
 		return ieee754dp_add(ieee754dp_1e63(),
diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c
index cb15a5eaecbb..6ab7df958362 100644
--- a/arch/mips/math-emu/dp_frexp.c
+++ b/arch/mips/math-emu/dp_frexp.c
@@ -28,7 +28,7 @@
 
 /* close to ieeep754dp_logb
 */
-ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
+union ieee754dp ieee754dp_frexp(union ieee754dp x, int *eptr)
 {
 	COMPXDP;
 	CLEARCX;
diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c
index daed6834dc15..d69cb1ad3f60 100644
--- a/arch/mips/math-emu/dp_fsp.c
+++ b/arch/mips/math-emu/dp_fsp.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_fsp(ieee754sp x)
+union ieee754dp ieee754dp_fsp(union ieee754sp x)
 {
 	COMPXSP;
 
diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c
index 151127e59f5c..80116e2f331f 100644
--- a/arch/mips/math-emu/dp_logb.c
+++ b/arch/mips/math-emu/dp_logb.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_logb(ieee754dp x)
+union ieee754dp ieee754dp_logb(union ieee754dp x)
 {
 	COMPXDP;
 
diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c
index b01f9cf6d402..cbc1386cdfca 100644
--- a/arch/mips/math-emu/dp_modf.c
+++ b/arch/mips/math-emu/dp_modf.c
@@ -28,7 +28,7 @@
 
 /* modf function is always exact for a finite number
 */
-ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp *ip)
+union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp *ip)
 {
 	COMPXDP;
 
diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c
index 09175f461920..c4cad69c377e 100644
--- a/arch/mips/math-emu/dp_mul.c
+++ b/arch/mips/math-emu/dp_mul.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)
 {
 	COMPXDP;
 	COMPYDP;
diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c
index 6f5df438dda8..4f8b65622942 100644
--- a/arch/mips/math-emu/dp_scalb.c
+++ b/arch/mips/math-emu/dp_scalb.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_scalb(ieee754dp x, int n)
+union ieee754dp ieee754dp_scalb(union ieee754dp x, int n)
 {
 	COMPXDP;
 
@@ -51,7 +51,7 @@ ieee754dp ieee754dp_scalb(ieee754dp x, int n)
 }
 
 
-ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
+union ieee754dp ieee754dp_ldexp(union ieee754dp x, int n)
 {
 	return ieee754dp_scalb(x, n);
 }
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
index 79ce2673a714..b341cc83eeb0 100644
--- a/arch/mips/math-emu/dp_simple.c
+++ b/arch/mips/math-emu/dp_simple.c
@@ -26,12 +26,12 @@
 
 #include "ieee754dp.h"
 
-int ieee754dp_finite(ieee754dp x)
+int ieee754dp_finite(union ieee754dp x)
 {
 	return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
 }
 
-ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y)
 {
 	CLEARCX;
 	DPSIGN(x) = DPSIGN(y);
@@ -39,7 +39,7 @@ ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
 }
 
 
-ieee754dp ieee754dp_neg(ieee754dp x)
+union ieee754dp ieee754dp_neg(union ieee754dp x)
 {
 	COMPXDP;
 
@@ -55,7 +55,7 @@ ieee754dp ieee754dp_neg(ieee754dp x)
 	DPSIGN(x) ^= 1;
 
 	if (xc == IEEE754_CLASS_SNAN) {
-		ieee754dp y = ieee754dp_indef();
+		union ieee754dp y = ieee754dp_indef();
 		SETCX(IEEE754_INVALID_OPERATION);
 		DPSIGN(y) = DPSIGN(x);
 		return ieee754dp_nanxcpt(y, "neg");
@@ -65,7 +65,7 @@ ieee754dp ieee754dp_neg(ieee754dp x)
 }
 
 
-ieee754dp ieee754dp_abs(ieee754dp x)
+union ieee754dp ieee754dp_abs(union ieee754dp x)
 {
 	COMPXDP;
 
diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c
index b874d60a942b..cee9f3c2700d 100644
--- a/arch/mips/math-emu/dp_sqrt.c
+++ b/arch/mips/math-emu/dp_sqrt.c
@@ -34,10 +34,10 @@ static const unsigned table[] = {
 	1742, 661, 130
 };
 
-ieee754dp ieee754dp_sqrt(ieee754dp x)
+union ieee754dp ieee754dp_sqrt(union ieee754dp x)
 {
 	struct _ieee754_csr oldcsr;
-	ieee754dp y, z, t;
+	union ieee754dp y, z, t;
 	unsigned scalx, yh;
 	COMPXDP;
 
diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c
index 91e0a4b5cbc7..1e8f19ae6cd5 100644
--- a/arch/mips/math-emu/dp_sub.c
+++ b/arch/mips/math-emu/dp_sub.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)
 {
 	COMPXDP;
 	COMPYDP;
diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c
index 0ebe8598b94a..e6bc33fd61a9 100644
--- a/arch/mips/math-emu/dp_tint.c
+++ b/arch/mips/math-emu/dp_tint.c
@@ -24,10 +24,9 @@
  */
 
 
-#include <linux/kernel.h>
 #include "ieee754dp.h"
 
-int ieee754dp_tint(ieee754dp x)
+int ieee754dp_tint(union ieee754dp x)
 {
 	COMPXDP;
 
@@ -109,9 +108,9 @@ int ieee754dp_tint(ieee754dp x)
 }
 
 
-unsigned int ieee754dp_tuns(ieee754dp x)
+unsigned int ieee754dp_tuns(union ieee754dp x)
 {
-	ieee754dp hb = ieee754dp_1e31();
+	union ieee754dp hb = ieee754dp_1e31();
 
 	/* what if x < 0 ?? */
 	if (ieee754dp_lt(x, hb))
diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c
index 133ce2ba0012..3366399eebe8 100644
--- a/arch/mips/math-emu/dp_tlong.c
+++ b/arch/mips/math-emu/dp_tlong.c
@@ -26,7 +26,7 @@
 
 #include "ieee754dp.h"
 
-s64 ieee754dp_tlong(ieee754dp x)
+s64 ieee754dp_tlong(union ieee754dp x)
 {
 	COMPXDP;
 
@@ -112,9 +112,9 @@ s64 ieee754dp_tlong(ieee754dp x)
 }
 
 
-u64 ieee754dp_tulong(ieee754dp x)
+u64 ieee754dp_tulong(union ieee754dp x)
 {
-	ieee754dp hb = ieee754dp_1e63();
+	union ieee754dp hb = ieee754dp_1e63();
 
 	/* what if x < 0 ?? */
 	if (ieee754dp_lt(x, hb))
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index 7ea622ab8dad..c6e879c59a7f 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -1,30 +1,12 @@
-#include <linux/compiler.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
-#include <linux/smp.h>
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/byteorder.h>
-#include <asm/cpu.h>
-#include <asm/inst.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
 #include <asm/branch.h>
-#include <asm/mipsregs.h>
 #include <asm/cacheflush.h>
-
 #include <asm/fpu_emulator.h>
+#include <asm/inst.h>
+#include <asm/mipsregs.h>
+#include <asm/uaccess.h>
 
 #include "ieee754.h"
 
-/* Strap kernel emulator for full MIPS IV emulation */
-
-#ifdef __mips
-#undef __mips
-#endif
-#define __mips 4
-
 /*
  * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
  * we have to emulate the instruction in a COP1 branch delay slot.  Do
@@ -59,7 +41,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 		(ir == 0)) {
 		/* NOP is easy */
 		regs->cp0_epc = cpc;
-		regs->cp0_cause &= ~CAUSEF_BD;
+		clear_delay_slot(regs);
 		return 0;
 	}
 #ifdef DSEMUL_TRACE
diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c
index 0015cf1989da..141f0cb40df4 100644
--- a/arch/mips/math-emu/ieee754.c
+++ b/arch/mips/math-emu/ieee754.c
@@ -28,6 +28,7 @@
  * ########################################################################
  */
 
+#include <linux/compiler.h>
 
 #include "ieee754int.h"
 #include "ieee754sp.h"
@@ -55,7 +56,7 @@
 #define DPSTR(s, b, mh, ml) {s, b, mh, ml}
 #endif
 
-const struct ieee754dp_konst __ieee754dp_spcvals[] = {
+const struct ieee754dp_const __ieee754dp_spcvals[] = {
 	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero   */
 	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero   */
 	DPSTR(0, DP_EBIAS, 0, 0),	/* + 1.0   */
@@ -75,7 +76,7 @@ const struct ieee754dp_konst __ieee754dp_spcvals[] = {
 	DPSTR(0, 63 + DP_EBIAS, 0, 0),	/* + 1.0e63 */
 };
 
-const struct ieee754sp_konst __ieee754sp_spcvals[] = {
+const struct ieee754sp_const __ieee754sp_spcvals[] = {
 	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0),	/* + zero   */
 	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0),	/* - zero   */
 	SPSTR(0, SP_EBIAS, 0),	/* + 1.0   */
@@ -96,7 +97,7 @@ const struct ieee754sp_konst __ieee754sp_spcvals[] = {
 };
 
 
-int ieee754si_xcpt(int r, const char *op, ...)
+int __cold ieee754si_xcpt(int r, const char *op, ...)
 {
 	struct ieee754xctx ax;
 
@@ -111,7 +112,7 @@ int ieee754si_xcpt(int r, const char *op, ...)
 	return ax.rv.si;
 }
 
-s64 ieee754di_xcpt(s64 r, const char *op, ...)
+s64 __cold ieee754di_xcpt(s64 r, const char *op, ...)
 {
 	struct ieee754xctx ax;
 
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
index 22796e012060..05705fa785c3 100644
--- a/arch/mips/math-emu/ieee754.h
+++ b/arch/mips/math-emu/ieee754.h
@@ -24,9 +24,11 @@
 #ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H
 #define __ARCH_MIPS_MATH_EMU_IEEE754_H
 
+#include <linux/compiler.h>
 #include <asm/byteorder.h>
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <asm/bitfield.h>
 
 /*
  * Not very pretty, but the Linux kernel's normal va_list definition
@@ -36,163 +38,133 @@
 #include <stdarg.h>
 #endif
 
-#ifdef __LITTLE_ENDIAN
-struct ieee754dp_konst {
-	unsigned mantlo:32;
-	unsigned manthi:20;
-	unsigned bexp:11;
-	unsigned sign:1;
-};
-struct ieee754sp_konst {
-	unsigned mant:23;
-	unsigned bexp:8;
-	unsigned sign:1;
+struct ieee754dp_const {
+	__BITFIELD_FIELD(unsigned sign:1,
+	__BITFIELD_FIELD(unsigned bexp:11,
+	__BITFIELD_FIELD(unsigned manthi:20,
+	__BITFIELD_FIELD(unsigned mantlo:32,
+	;))))
 };
 
-typedef union _ieee754dp {
-	struct ieee754dp_konst oparts;
+union ieee754dp {
+	struct ieee754dp_const oparts;
 	struct {
-		u64 mant:52;
-		unsigned int bexp:11;
-		unsigned int sign:1;
-	} parts;
-	u64 bits;
-	double d;
-} ieee754dp;
-
-typedef union _ieee754sp {
-	struct ieee754sp_konst parts;
-	float f;
-	u32 bits;
-} ieee754sp;
-#endif
-
-#ifdef __BIG_ENDIAN
-struct ieee754dp_konst {
-	unsigned sign:1;
-	unsigned bexp:11;
-	unsigned manthi:20;
-	unsigned mantlo:32;
-};
-
-typedef union _ieee754dp {
-	struct ieee754dp_konst oparts;
-	struct {
-		unsigned int sign:1;
-		unsigned int bexp:11;
-		u64 mant:52;
+		__BITFIELD_FIELD(unsigned int sign:1,
+		__BITFIELD_FIELD(unsigned int bexp:11,
+		__BITFIELD_FIELD(u64 mant:52,
+		;)))
 	} parts;
 	double d;
 	u64 bits;
-} ieee754dp;
+};
 
-struct ieee754sp_konst {
-	unsigned sign:1;
-	unsigned bexp:8;
-	unsigned mant:23;
+struct ieee754sp_const {
+	__BITFIELD_FIELD(unsigned sign:1,
+	__BITFIELD_FIELD(unsigned bexp:8,
+	__BITFIELD_FIELD(unsigned mant:23,
+	;)))
 };
 
-typedef union _ieee754sp {
-	struct ieee754sp_konst parts;
+union ieee754sp {
+	struct ieee754sp_const parts;
 	float f;
 	u32 bits;
-} ieee754sp;
-#endif
+};
 
 /*
  * single precision (often aka float)
 */
-int ieee754sp_finite(ieee754sp x);
-int ieee754sp_class(ieee754sp x);
+int ieee754sp_finite(union ieee754sp x);
+int ieee754sp_class(union ieee754sp x);
 
-ieee754sp ieee754sp_abs(ieee754sp x);
-ieee754sp ieee754sp_neg(ieee754sp x);
-ieee754sp ieee754sp_scalb(ieee754sp x, int);
-ieee754sp ieee754sp_logb(ieee754sp x);
+union ieee754sp ieee754sp_abs(union ieee754sp x);
+union ieee754sp ieee754sp_neg(union ieee754sp x);
+union ieee754sp ieee754sp_scalb(union ieee754sp x, int);
+union ieee754sp ieee754sp_logb(union ieee754sp x);
 
 /* x with sign of y */
-ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
+union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y);
 
-ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
-ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
-ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
-ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
+union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y);
 
-ieee754sp ieee754sp_fint(int x);
-ieee754sp ieee754sp_funs(unsigned x);
-ieee754sp ieee754sp_flong(s64 x);
-ieee754sp ieee754sp_fulong(u64 x);
-ieee754sp ieee754sp_fdp(ieee754dp x);
+union ieee754sp ieee754sp_fint(int x);
+union ieee754sp ieee754sp_funs(unsigned x);
+union ieee754sp ieee754sp_flong(s64 x);
+union ieee754sp ieee754sp_fulong(u64 x);
+union ieee754sp ieee754sp_fdp(union ieee754dp x);
 
-int ieee754sp_tint(ieee754sp x);
-unsigned int ieee754sp_tuns(ieee754sp x);
-s64 ieee754sp_tlong(ieee754sp x);
-u64 ieee754sp_tulong(ieee754sp x);
+int ieee754sp_tint(union ieee754sp x);
+unsigned int ieee754sp_tuns(union ieee754sp x);
+s64 ieee754sp_tlong(union ieee754sp x);
+u64 ieee754sp_tulong(union ieee754sp x);
 
-int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig);
+int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cop, int sig);
 /*
  * basic sp math
  */
-ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
-ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
-ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp * ip);
+union ieee754sp ieee754sp_frexp(union ieee754sp x, int *exp);
+union ieee754sp ieee754sp_ldexp(union ieee754sp x, int exp);
 
-ieee754sp ieee754sp_ceil(ieee754sp x);
-ieee754sp ieee754sp_floor(ieee754sp x);
-ieee754sp ieee754sp_trunc(ieee754sp x);
+union ieee754sp ieee754sp_ceil(union ieee754sp x);
+union ieee754sp ieee754sp_floor(union ieee754sp x);
+union ieee754sp ieee754sp_trunc(union ieee754sp x);
 
-ieee754sp ieee754sp_sqrt(ieee754sp x);
+union ieee754sp ieee754sp_sqrt(union ieee754sp x);
 
 /*
  * double precision (often aka double)
 */
-int ieee754dp_finite(ieee754dp x);
-int ieee754dp_class(ieee754dp x);
+int ieee754dp_finite(union ieee754dp x);
+int ieee754dp_class(union ieee754dp x);
 
 /* x with sign of y */
-ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y);
 
-ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
-ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
-ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
-ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y);
 
-ieee754dp ieee754dp_abs(ieee754dp x);
-ieee754dp ieee754dp_neg(ieee754dp x);
-ieee754dp ieee754dp_scalb(ieee754dp x, int);
+union ieee754dp ieee754dp_abs(union ieee754dp x);
+union ieee754dp ieee754dp_neg(union ieee754dp x);
+union ieee754dp ieee754dp_scalb(union ieee754dp x, int);
 
 /* return exponent as integer in floating point format
  */
-ieee754dp ieee754dp_logb(ieee754dp x);
+union ieee754dp ieee754dp_logb(union ieee754dp x);
 
-ieee754dp ieee754dp_fint(int x);
-ieee754dp ieee754dp_funs(unsigned x);
-ieee754dp ieee754dp_flong(s64 x);
-ieee754dp ieee754dp_fulong(u64 x);
-ieee754dp ieee754dp_fsp(ieee754sp x);
+union ieee754dp ieee754dp_fint(int x);
+union ieee754dp ieee754dp_funs(unsigned x);
+union ieee754dp ieee754dp_flong(s64 x);
+union ieee754dp ieee754dp_fulong(u64 x);
+union ieee754dp ieee754dp_fsp(union ieee754sp x);
 
-ieee754dp ieee754dp_ceil(ieee754dp x);
-ieee754dp ieee754dp_floor(ieee754dp x);
-ieee754dp ieee754dp_trunc(ieee754dp x);
+union ieee754dp ieee754dp_ceil(union ieee754dp x);
+union ieee754dp ieee754dp_floor(union ieee754dp x);
+union ieee754dp ieee754dp_trunc(union ieee754dp x);
 
-int ieee754dp_tint(ieee754dp x);
-unsigned int ieee754dp_tuns(ieee754dp x);
-s64 ieee754dp_tlong(ieee754dp x);
-u64 ieee754dp_tulong(ieee754dp x);
+int ieee754dp_tint(union ieee754dp x);
+unsigned int ieee754dp_tuns(union ieee754dp x);
+s64 ieee754dp_tlong(union ieee754dp x);
+u64 ieee754dp_tulong(union ieee754dp x);
 
-int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig);
+int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cop, int sig);
 /*
  * basic sp math
  */
-ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
-ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
-ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp * ip);
+union ieee754dp ieee754dp_frexp(union ieee754dp x, int *exp);
+union ieee754dp ieee754dp_ldexp(union ieee754dp x, int exp);
 
-ieee754dp ieee754dp_ceil(ieee754dp x);
-ieee754dp ieee754dp_floor(ieee754dp x);
-ieee754dp ieee754dp_trunc(ieee754dp x);
+union ieee754dp ieee754dp_ceil(union ieee754dp x);
+union ieee754dp ieee754dp_floor(union ieee754dp x);
+union ieee754dp ieee754dp_trunc(union ieee754dp x);
 
-ieee754dp ieee754dp_sqrt(ieee754dp x);
+union ieee754dp ieee754dp_sqrt(union ieee754dp x);
 
 
 
@@ -232,65 +204,65 @@ ieee754dp ieee754dp_sqrt(ieee754dp x);
 
 /* "normal" comparisons
 */
-static inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);
 }
 
-static inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_ne(union ieee754sp x, union ieee754sp y)
 {
 	return ieee754sp_cmp(x, y,
 			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
 }
 
-static inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_lt(union ieee754sp x, union ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CLT, 0);
 }
 
-static inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_le(union ieee754sp x, union ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
 }
 
-static inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_gt(union ieee754sp x, union ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CGT, 0);
 }
 
 
-static inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_ge(union ieee754sp x, union ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
 }
 
-static inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_eq(union ieee754dp x, union ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);
 }
 
-static inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_ne(union ieee754dp x, union ieee754dp y)
 {
 	return ieee754dp_cmp(x, y,
 			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
 }
 
-static inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_lt(union ieee754dp x, union ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CLT, 0);
 }
 
-static inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_le(union ieee754dp x, union ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
 }
 
-static inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_gt(union ieee754dp x, union ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CGT, 0);
 }
 
-static inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_ge(union ieee754dp x, union ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
 }
@@ -299,34 +271,23 @@ static inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
 /*
  * Like strtod
  */
-ieee754dp ieee754dp_fstr(const char *s, char **endp);
-char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
+union ieee754dp ieee754dp_fstr(const char *s, char **endp);
+char *ieee754dp_tstr(union ieee754dp x, int prec, int fmt, int af);
 
 
 /*
  * The control status register
  */
 struct _ieee754_csr {
-#ifdef __BIG_ENDIAN
-	unsigned pad0:7;
-	unsigned nod:1;		/* set 1 for no denormalised numbers */
-	unsigned c:1;		/* condition */
-	unsigned pad1:5;
-	unsigned cx:6;		/* exceptions this operation */
-	unsigned mx:5;		/* exception enable  mask */
-	unsigned sx:5;		/* exceptions total */
-	unsigned rm:2;		/* current rounding mode */
-#endif
-#ifdef __LITTLE_ENDIAN
-	unsigned rm:2;		/* current rounding mode */
-	unsigned sx:5;		/* exceptions total */
-	unsigned mx:5;		/* exception enable  mask */
-	unsigned cx:6;		/* exceptions this operation */
-	unsigned pad1:5;
-	unsigned c:1;		/* condition */
-	unsigned nod:1;		/* set 1 for no denormalised numbers */
-	unsigned pad0:7;
-#endif
+	__BITFIELD_FIELD(unsigned pad0:7,
+	__BITFIELD_FIELD(unsigned nod:1,	/* set 1 for no denormalised numbers */
+	__BITFIELD_FIELD(unsigned c:1,		/* condition */
+	__BITFIELD_FIELD(unsigned pad1:5,
+	__BITFIELD_FIELD(unsigned cx:6,		/* exceptions this operation */
+	__BITFIELD_FIELD(unsigned mx:5,		/* exception enable  mask */
+	__BITFIELD_FIELD(unsigned sx:5,		/* exceptions total */
+	__BITFIELD_FIELD(unsigned rm:2,		/* current rounding mode */
+	;))))))))
 };
 #define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.fcr31))
 
@@ -377,8 +338,8 @@ static inline int ieee754_sxtest(unsigned n)
 }
 
 /* debugging */
-ieee754sp ieee754sp_dump(char *s, ieee754sp x);
-ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+union ieee754sp ieee754sp_dump(char *s, union ieee754sp x);
+union ieee754dp ieee754dp_dump(char *s, union ieee754dp x);
 
 #define IEEE754_SPCVAL_PZERO	0
 #define IEEE754_SPCVAL_NZERO	1
@@ -398,10 +359,10 @@ ieee754dp ieee754dp_dump(char *s, ieee754dp x);
 #define IEEE754_SPCVAL_P1E31	15	/* + 1.0e31 */
 #define IEEE754_SPCVAL_P1E63	16	/* + 1.0e63 */
 
-extern const struct ieee754dp_konst __ieee754dp_spcvals[];
-extern const struct ieee754sp_konst __ieee754sp_spcvals[];
-#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
-#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+extern const struct ieee754dp_const __ieee754dp_spcvals[];
+extern const struct ieee754sp_const __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const union ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const union ieee754sp *)__ieee754sp_spcvals)
 
 /*
  * Return infinity with given sign
@@ -443,8 +404,8 @@ struct ieee754xctx {
 	const char *op;		/* operation name */
 	int rt;			/* result type */
 	union {
-		ieee754sp sp;	/* single precision */
-		ieee754dp dp;	/* double precision */
+		union ieee754sp sp;	/* single precision */
+		union ieee754dp dp;	/* double precision */
 #ifdef IEEE854_XP
 		ieee754xp xp;	/* extended precision */
 #endif
@@ -461,7 +422,7 @@ struct ieee754xctx {
 #define IEEE754_RT_SI	3
 #define IEEE754_RT_DI	4
 
-extern void ieee754_xcpt(struct ieee754xctx *xcp);
+extern void __cold ieee754_xcpt(struct ieee754xctx *xcp);
 
 /* compat */
 #define ieee754dp_fix(x)	ieee754dp_tint(x)
diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c
index 9599bdd32585..6d4dc36a6fdc 100644
--- a/arch/mips/math-emu/ieee754d.c
+++ b/arch/mips/math-emu/ieee754d.c
@@ -25,7 +25,8 @@
  *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
  */
 
-#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/printk.h>
 #include "ieee754.h"
 
 #define DP_EBIAS	1023
@@ -56,7 +57,7 @@
 #define DPBEXP(dp)	(dp.parts.bexp)
 #define DPMANT(dp)	(dp.parts.mant)
 
-ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+union ieee754dp ieee754dp_dump(char *m, union ieee754dp x)
 {
 	int i;
 
@@ -96,7 +97,7 @@ ieee754dp ieee754dp_dump(char *m, ieee754dp x)
 	return x;
 }
 
-ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+union ieee754sp ieee754sp_dump(char *m, union ieee754sp x)
 {
 	int i;
 
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c
index 068e56be8de9..43fb7fefb6cc 100644
--- a/arch/mips/math-emu/ieee754dp.c
+++ b/arch/mips/math-emu/ieee754dp.c
@@ -23,29 +23,30 @@
  * ########################################################################
  */
 
+#include <linux/compiler.h>
 
 #include "ieee754dp.h"
 
-int ieee754dp_class(ieee754dp x)
+int ieee754dp_class(union ieee754dp x)
 {
 	COMPXDP;
 	EXPLODEXDP;
 	return xc;
 }
 
-int ieee754dp_isnan(ieee754dp x)
+int ieee754dp_isnan(union ieee754dp x)
 {
 	return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
 }
 
-int ieee754dp_issnan(ieee754dp x)
+int ieee754dp_issnan(union ieee754dp x)
 {
 	assert(ieee754dp_isnan(x));
 	return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1));
 }
 
 
-ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
+union ieee754dp __cold ieee754dp_xcpt(union ieee754dp r, const char *op, ...)
 {
 	struct ieee754xctx ax;
 	if (!TSTX())
@@ -60,7 +61,7 @@ ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
 	return ax.rv.dp;
 }
 
-ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r, const char *op, ...)
 {
 	struct ieee754xctx ax;
 
@@ -87,7 +88,7 @@ ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
 	return ax.rv.dp;
 }
 
-ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_bestnan(union ieee754dp x, union ieee754dp y)
 {
 	assert(ieee754dp_isnan(x));
 	assert(ieee754dp_isnan(y));
@@ -130,7 +131,7 @@ static u64 get_rounding(int sn, u64 xm)
  * xe is an unbiased exponent
  * xm is 3bit extended precision value.
  */
-ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
+union ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
 {
 	assert(xm);		/* we don't gen exact zeros (probably should) */
 
@@ -150,12 +151,12 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
 			case IEEE754_RZ:
 				return ieee754dp_zero(sn);
 			case IEEE754_RU:    /* toward +Infinity */
-				if(sn == 0)
+				if (sn == 0)
 					return ieee754dp_min(0);
 				else
 					return ieee754dp_zero(1);
 			case IEEE754_RD:    /* toward -Infinity */
-				if(sn == 0)
+				if (sn == 0)
 					return ieee754dp_zero(0);
 				else
 					return ieee754dp_min(1);
diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h
index f139c724c59a..3759f3f35293 100644
--- a/arch/mips/math-emu/ieee754dp.h
+++ b/arch/mips/math-emu/ieee754dp.h
@@ -24,6 +24,7 @@
  * ########################################################################
  */
 
+#include <linux/compiler.h>
 
 #include "ieee754int.h"
 
@@ -31,23 +32,23 @@
 
 /* 3bit extended double precision sticky right shift */
 #define XDPSRS(v,rs)	\
-  ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+	((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
 
 #define XDPSRSX1() \
-  (xe++, (xm = (xm >> 1) | (xm & 1)))
+	(xe++, (xm = (xm >> 1) | (xm & 1)))
 
 #define XDPSRS1(v)	\
-  (((v) >> 1) | ((v) & 1))
+	(((v) >> 1) | ((v) & 1))
 
 /* convert denormal to normalized with extended exponent */
 #define DPDNORMx(m,e) \
-  while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+	while ((m >> DP_MBITS) == 0) { m <<= 1; e--; }
 #define DPDNORMX	DPDNORMx(xm, xe)
 #define DPDNORMY	DPDNORMx(ym, ye)
 
-static inline ieee754dp builddp(int s, int bx, u64 m)
+static inline union ieee754dp builddp(int s, int bx, u64 m)
 {
-	ieee754dp r;
+	union ieee754dp r;
 
 	assert((s) == 0 || (s) == 1);
 	assert((bx) >= DP_EMIN - 1 + DP_EBIAS
@@ -60,23 +61,23 @@ static inline ieee754dp builddp(int s, int bx, u64 m)
 	return r;
 }
 
-extern int ieee754dp_isnan(ieee754dp);
-extern int ieee754dp_issnan(ieee754dp);
-extern int ieee754si_xcpt(int, const char *, ...);
-extern s64 ieee754di_xcpt(s64, const char *, ...);
-extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
-extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
-extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
-extern ieee754dp ieee754dp_format(int, int, u64);
+extern int ieee754dp_isnan(union ieee754dp);
+extern int ieee754dp_issnan(union ieee754dp);
+extern int __cold ieee754si_xcpt(int, const char *, ...);
+extern s64 __cold ieee754di_xcpt(s64, const char *, ...);
+extern union ieee754dp __cold ieee754dp_xcpt(union ieee754dp, const char *, ...);
+extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp, const char *, ...);
+extern union ieee754dp ieee754dp_bestnan(union ieee754dp, union ieee754dp);
+extern union ieee754dp ieee754dp_format(int, int, u64);
 
 
-#define DPNORMRET2(s, e, m, name, a0, a1) \
-{ \
-    ieee754dp V = ieee754dp_format(s, e, m); \
-    if(TSTX()) \
-      return ieee754dp_xcpt(V, name, a0, a1); \
-    else \
-      return V; \
+#define DPNORMRET2(s, e, m, name, a0, a1)				\
+{									\
+	union ieee754dp V = ieee754dp_format(s, e, m);			\
+	if (TSTX())							\
+		return ieee754dp_xcpt(V, name, a0, a1);			\
+	else								\
+		return V;						\
 }
 
 #define DPNORMRET1(s, e, m, name, a0)  DPNORMRET2(s, e, m, name, a0, a0)
diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h
index 4b6c6fb35304..27ed825ad35a 100644
--- a/arch/mips/math-emu/ieee754int.h
+++ b/arch/mips/math-emu/ieee754int.h
@@ -57,105 +57,105 @@
 #define CLPAIR(x, y)	((x)*6+(y))
 
 #define CLEARCX \
-  (ieee754_csr.cx = 0)
+	(ieee754_csr.cx = 0)
 
 #define SETCX(x) \
-  (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x))
+	(ieee754_csr.cx |= (x), ieee754_csr.sx |= (x))
 
 #define SETANDTESTCX(x) \
-  (SETCX(x), ieee754_csr.mx & (x))
+	(SETCX(x), ieee754_csr.mx & (x))
 
 #define TSTX()	\
 	(ieee754_csr.cx & ieee754_csr.mx)
 
 
 #define COMPXSP \
-  unsigned xm; int xe; int xs __maybe_unused; int xc
+	unsigned xm; int xe; int xs __maybe_unused; int xc
 
 #define COMPYSP \
-  unsigned ym; int ye; int ys; int yc
-
-#define EXPLODESP(v, vc, vs, ve, vm) \
-{\
-    vs = SPSIGN(v);\
-    ve = SPBEXP(v);\
-    vm = SPMANT(v);\
-    if(ve == SP_EMAX+1+SP_EBIAS){\
-	if(vm == 0)\
-	  vc = IEEE754_CLASS_INF;\
-	else if(vm & SP_MBIT(SP_MBITS-1)) \
-	  vc = IEEE754_CLASS_SNAN;\
-	else \
-	  vc = IEEE754_CLASS_QNAN;\
-    } else if(ve == SP_EMIN-1+SP_EBIAS) {\
-	if(vm) {\
-	    ve = SP_EMIN;\
-	    vc = IEEE754_CLASS_DNORM;\
-	} else\
-	  vc = IEEE754_CLASS_ZERO;\
-    } else {\
-	ve -= SP_EBIAS;\
-	vm |= SP_HIDDEN_BIT;\
-	vc = IEEE754_CLASS_NORM;\
-    }\
+	unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v, vc, vs, ve, vm)					\
+{									\
+	vs = SPSIGN(v);							\
+	ve = SPBEXP(v);							\
+	vm = SPMANT(v);							\
+	if (ve == SP_EMAX+1+SP_EBIAS) {					\
+		if (vm == 0)						\
+			vc = IEEE754_CLASS_INF;				\
+		else if (vm & SP_MBIT(SP_MBITS-1))			\
+			vc = IEEE754_CLASS_SNAN;			\
+	else								\
+		vc = IEEE754_CLASS_QNAN;				\
+	} else if (ve == SP_EMIN-1+SP_EBIAS) {				\
+		if (vm) {						\
+			ve = SP_EMIN;					\
+			vc = IEEE754_CLASS_DNORM;			\
+		} else							\
+			vc = IEEE754_CLASS_ZERO;			\
+	} else {							\
+		ve -= SP_EBIAS;						\
+		vm |= SP_HIDDEN_BIT;					\
+		vc = IEEE754_CLASS_NORM;				\
+	}								\
 }
 #define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm)
 #define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym)
 
 
 #define COMPXDP \
-u64 xm; int xe; int xs __maybe_unused; int xc
+	u64 xm; int xe; int xs __maybe_unused; int xc
 
 #define COMPYDP \
-u64 ym; int ye; int ys; int yc
-
-#define EXPLODEDP(v, vc, vs, ve, vm) \
-{\
-    vm = DPMANT(v);\
-    vs = DPSIGN(v);\
-    ve = DPBEXP(v);\
-    if(ve == DP_EMAX+1+DP_EBIAS){\
-	if(vm == 0)\
-	  vc = IEEE754_CLASS_INF;\
-	else if(vm & DP_MBIT(DP_MBITS-1)) \
-	  vc = IEEE754_CLASS_SNAN;\
-	else \
-	  vc = IEEE754_CLASS_QNAN;\
-    } else if(ve == DP_EMIN-1+DP_EBIAS) {\
-	if(vm) {\
-	    ve = DP_EMIN;\
-	    vc = IEEE754_CLASS_DNORM;\
-	} else\
-	  vc = IEEE754_CLASS_ZERO;\
-    } else {\
-	ve -= DP_EBIAS;\
-	vm |= DP_HIDDEN_BIT;\
-	vc = IEEE754_CLASS_NORM;\
-    }\
+	u64 ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v, vc, vs, ve, vm)					\
+{									\
+	vm = DPMANT(v);							\
+	vs = DPSIGN(v);							\
+	ve = DPBEXP(v);							\
+	if (ve == DP_EMAX+1+DP_EBIAS) {					\
+		if (vm == 0)						\
+			vc = IEEE754_CLASS_INF;				\
+		else if (vm & DP_MBIT(DP_MBITS-1))			\
+			vc = IEEE754_CLASS_SNAN;			\
+		else							\
+			vc = IEEE754_CLASS_QNAN;			\
+	} else if (ve == DP_EMIN-1+DP_EBIAS) {				\
+		if (vm) {						\
+			ve = DP_EMIN;					\
+			vc = IEEE754_CLASS_DNORM;			\
+	} else								\
+		vc = IEEE754_CLASS_ZERO;				\
+	} else {							\
+		ve -= DP_EBIAS;						\
+		vm |= DP_HIDDEN_BIT;					\
+		vc = IEEE754_CLASS_NORM;				\
+	}								\
 }
 #define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm)
 #define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym)
 
-#define FLUSHDP(v, vc, vs, ve, vm) \
-	if(vc==IEEE754_CLASS_DNORM) {\
-	    if(ieee754_csr.nod) {\
-		SETCX(IEEE754_INEXACT);\
-		vc = IEEE754_CLASS_ZERO;\
-		ve = DP_EMIN-1+DP_EBIAS;\
-		vm = 0;\
-		v = ieee754dp_zero(vs);\
-	    }\
+#define FLUSHDP(v, vc, vs, ve, vm)					\
+	if (vc==IEEE754_CLASS_DNORM) {					\
+		if (ieee754_csr.nod) {					\
+			SETCX(IEEE754_INEXACT);				\
+			vc = IEEE754_CLASS_ZERO;			\
+			ve = DP_EMIN-1+DP_EBIAS;			\
+			vm = 0;						\
+			v = ieee754dp_zero(vs);				\
+		}							\
 	}
 
-#define FLUSHSP(v, vc, vs, ve, vm) \
-	if(vc==IEEE754_CLASS_DNORM) {\
-	    if(ieee754_csr.nod) {\
-		SETCX(IEEE754_INEXACT);\
-		vc = IEEE754_CLASS_ZERO;\
-		ve = SP_EMIN-1+SP_EBIAS;\
-		vm = 0;\
-		v = ieee754sp_zero(vs);\
-	    }\
+#define FLUSHSP(v, vc, vs, ve, vm)					\
+	if (vc==IEEE754_CLASS_DNORM) {					\
+		if (ieee754_csr.nod) {					\
+			SETCX(IEEE754_INEXACT);				\
+			vc = IEEE754_CLASS_ZERO;			\
+			ve = SP_EMIN-1+SP_EBIAS;			\
+			vm = 0;						\
+			v = ieee754sp_zero(vs);				\
+		}							\
 	}
 
 #define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm)
diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c
index 24190f3c9dd6..06224064333b 100644
--- a/arch/mips/math-emu/ieee754m.c
+++ b/arch/mips/math-emu/ieee754m.c
@@ -26,9 +26,9 @@
 
 #include "ieee754.h"
 
-ieee754dp ieee754dp_floor(ieee754dp x)
+union ieee754dp ieee754dp_floor(union ieee754dp x)
 {
-	ieee754dp i;
+	union ieee754dp i;
 
 	if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
 		return ieee754dp_sub(i, ieee754dp_one(0));
@@ -36,9 +36,9 @@ ieee754dp ieee754dp_floor(ieee754dp x)
 		return i;
 }
 
-ieee754dp ieee754dp_ceil(ieee754dp x)
+union ieee754dp ieee754dp_ceil(union ieee754dp x)
 {
-	ieee754dp i;
+	union ieee754dp i;
 
 	if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
 		return ieee754dp_add(i, ieee754dp_one(0));
@@ -46,9 +46,9 @@ ieee754dp ieee754dp_ceil(ieee754dp x)
 		return i;
 }
 
-ieee754dp ieee754dp_trunc(ieee754dp x)
+union ieee754dp ieee754dp_trunc(union ieee754dp x)
 {
-	ieee754dp i;
+	union ieee754dp i;
 
 	(void) ieee754dp_modf(x, &i);
 	return i;
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c
index 15d1e36cfe64..a15d2123e05e 100644
--- a/arch/mips/math-emu/ieee754sp.c
+++ b/arch/mips/math-emu/ieee754sp.c
@@ -23,29 +23,30 @@
  * ########################################################################
  */
 
+#include <linux/compiler.h>
 
 #include "ieee754sp.h"
 
-int ieee754sp_class(ieee754sp x)
+int ieee754sp_class(union ieee754sp x)
 {
 	COMPXSP;
 	EXPLODEXSP;
 	return xc;
 }
 
-int ieee754sp_isnan(ieee754sp x)
+int ieee754sp_isnan(union ieee754sp x)
 {
 	return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
 }
 
-int ieee754sp_issnan(ieee754sp x)
+int ieee754sp_issnan(union ieee754sp x)
 {
 	assert(ieee754sp_isnan(x));
 	return (SPMANT(x) & SP_MBIT(SP_MBITS-1));
 }
 
 
-ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
+union ieee754sp __cold ieee754sp_xcpt(union ieee754sp r, const char *op, ...)
 {
 	struct ieee754xctx ax;
 
@@ -61,7 +62,7 @@ ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
 	return ax.rv.sp;
 }
 
-ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r, const char *op, ...)
 {
 	struct ieee754xctx ax;
 
@@ -88,7 +89,7 @@ ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
 	return ax.rv.sp;
 }
 
-ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_bestnan(union ieee754sp x, union ieee754sp y)
 {
 	assert(ieee754sp_isnan(x));
 	assert(ieee754sp_isnan(y));
@@ -131,7 +132,7 @@ static unsigned get_rounding(int sn, unsigned xm)
  * xe is an unbiased exponent
  * xm is 3bit extended precision value.
  */
-ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
 {
 	assert(xm);		/* we don't gen exact zeros (probably should) */
 
@@ -151,12 +152,12 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
 			case IEEE754_RZ:
 				return ieee754sp_zero(sn);
 			case IEEE754_RU:      /* toward +Infinity */
-				if(sn == 0)
+				if (sn == 0)
 					return ieee754sp_min(0);
 				else
 					return ieee754sp_zero(1);
 			case IEEE754_RD:      /* toward -Infinity */
-				if(sn == 0)
+				if (sn == 0)
 					return ieee754sp_zero(0);
 				else
 					return ieee754sp_min(1);
@@ -173,8 +174,7 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
 			/* Clear grs bits */
 			xm &= ~(SP_MBIT(3) - 1);
 			xe++;
-		}
-		else {
+		} else {
 			/* sticky right shift es bits
 			 */
 			SPXSRSXn(es);
diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h
index 754fd54649b5..f007c47086cb 100644
--- a/arch/mips/math-emu/ieee754sp.h
+++ b/arch/mips/math-emu/ieee754sp.h
@@ -24,35 +24,36 @@
  * ########################################################################
  */
 
+#include <linux/compiler.h>
 
 #include "ieee754int.h"
 
 #define assert(expr) ((void)0)
 
 /* 3bit extended single precision sticky right shift */
-#define SPXSRSXn(rs) \
-  (xe += rs, \
-   xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+#define SPXSRSXn(rs)							\
+	(xe += rs,							\
+	 xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
 
 #define SPXSRSX1() \
-  (xe++, (xm = (xm >> 1) | (xm & 1)))
+	(xe++, (xm = (xm >> 1) | (xm & 1)))
 
-#define SPXSRSYn(rs) \
-   (ye+=rs, \
-    ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+#define SPXSRSYn(rs)								\
+	(ye+=rs,								\
+	 ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
 
 #define SPXSRSY1() \
-   (ye++, (ym = (ym >> 1) | (ym & 1)))
+	(ye++, (ym = (ym >> 1) | (ym & 1)))
 
 /* convert denormal to normalized with extended exponent */
 #define SPDNORMx(m,e) \
-  while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+	while ((m >> SP_MBITS) == 0) { m <<= 1; e--; }
 #define SPDNORMX	SPDNORMx(xm, xe)
 #define SPDNORMY	SPDNORMx(ym, ye)
 
-static inline ieee754sp buildsp(int s, int bx, unsigned m)
+static inline union ieee754sp buildsp(int s, int bx, unsigned m)
 {
-	ieee754sp r;
+	union ieee754sp r;
 
 	assert((s) == 0 || (s) == 1);
 	assert((bx) >= SP_EMIN - 1 + SP_EBIAS
@@ -66,23 +67,24 @@ static inline ieee754sp buildsp(int s, int bx, unsigned m)
 	return r;
 }
 
-extern int ieee754sp_isnan(ieee754sp);
-extern int ieee754sp_issnan(ieee754sp);
-extern int ieee754si_xcpt(int, const char *, ...);
-extern s64 ieee754di_xcpt(s64, const char *, ...);
-extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
-extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
-extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
-extern ieee754sp ieee754sp_format(int, int, unsigned);
-
-
-#define SPNORMRET2(s, e, m, name, a0, a1) \
-{ \
-    ieee754sp V = ieee754sp_format(s, e, m); \
-    if(TSTX()) \
-      return ieee754sp_xcpt(V, name, a0, a1); \
-    else \
-      return V; \
+extern int ieee754sp_isnan(union ieee754sp);
+extern int ieee754sp_issnan(union ieee754sp);
+extern int __cold ieee754si_xcpt(int, const char *, ...);
+extern s64 __cold ieee754di_xcpt(s64, const char *, ...);
+extern union ieee754sp __cold ieee754sp_xcpt(union ieee754sp, const char *, ...);
+extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp, const char *, ...);
+extern union ieee754sp ieee754sp_bestnan(union ieee754sp, union ieee754sp);
+extern union ieee754sp ieee754sp_format(int, int, unsigned);
+
+
+#define SPNORMRET2(s, e, m, name, a0, a1)				\
+{									\
+	union ieee754sp V = ieee754sp_format(s, e, m);			\
+									\
+	if (TSTX())							\
+		return ieee754sp_xcpt(V, name, a0, a1);			\
+	else								\
+		return V;						\
 }
 
 #define SPNORMRET1(s, e, m, name, a0)  SPNORMRET2(s, e, m, name, a0, a0)
diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c
index 967167116ae8..d68408a19570 100644
--- a/arch/mips/math-emu/ieee754xcpt.c
+++ b/arch/mips/math-emu/ieee754xcpt.c
@@ -28,7 +28,8 @@
  *  Copyright (C) 2000 MIPS Technologies, Inc.	All rights reserved.
  *************************************************************************/
 
-#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/printk.h>
 #include "ieee754.h"
 
 /*
@@ -40,7 +41,7 @@ static const char *const rtnames[] = {
 	"sp", "dp", "xp", "si", "di"
 };
 
-void ieee754_xcpt(struct ieee754xctx *xcp)
+void __cold ieee754_xcpt(struct ieee754xctx *xcp)
 {
 	printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n",
 		xcp->op, rtnames[xcp->rt]);
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
index eb58a85b3157..a7959005700b 100644
--- a/arch/mips/math-emu/kernel_linkage.c
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -19,11 +19,8 @@
  * manipulation primitives for the Algorithmics MIPS
  * FPU Emulator
  */
-#include <linux/sched.h>
-#include <asm/processor.h>
-#include <asm/signal.h>
-#include <asm/uaccess.h>
-
+#include <linux/printk.h>
+#include <asm/current.h>
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 
diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c
new file mode 100644
index 000000000000..95ed9f9bd2b0
--- /dev/null
+++ b/arch/mips/math-emu/me-debugfs.c
@@ -0,0 +1,62 @@
+#include <linux/cpumask.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/types.h>
+#include <asm/fpu_emulator.h>
+#include <asm/local.h>
+
+DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+
+static int fpuemu_stat_get(void *data, u64 *val)
+{
+	int cpu;
+	unsigned long sum = 0;
+
+	for_each_online_cpu(cpu) {
+		struct mips_fpu_emulator_stats *ps;
+		local_t *pv;
+
+		ps = &per_cpu(fpuemustats, cpu);
+		pv = (void *)ps + (unsigned long)data;
+		sum += local_read(pv);
+	}
+	*val = sum;
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
+
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_fpuemu(void)
+{
+	struct dentry *d, *dir;
+
+	if (!mips_debugfs_dir)
+		return -ENODEV;
+	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
+	if (!dir)
+		return -ENOMEM;
+
+#define FPU_EMU_STAT_OFFSET(m)						\
+	offsetof(struct mips_fpu_emulator_stats, m)
+
+#define FPU_STAT_CREATE(m)						\
+do {									\
+	d = debugfs_create_file(#m , S_IRUGO, dir,			\
+				(void *)FPU_EMU_STAT_OFFSET(m),		\
+				&fops_fpuemu_stat);			\
+	if (!d)								\
+		return -ENOMEM;						\
+} while (0)
+
+	FPU_STAT_CREATE(emulated);
+	FPU_STAT_CREATE(loads);
+	FPU_STAT_CREATE(stores);
+	FPU_STAT_CREATE(cp1ops);
+	FPU_STAT_CREATE(cp1xops);
+	FPU_STAT_CREATE(errors);
+
+	return 0;
+}
+__initcall(debugfs_fpuemu);
diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c
index c446e64637e2..4938d8f1d4bc 100644
--- a/arch/mips/math-emu/sp_add.c
+++ b/arch/mips/math-emu/sp_add.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
 {
 	COMPXSP;
 	COMPYSP;
diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c
index 716cf37e2465..b98d68617cfe 100644
--- a/arch/mips/math-emu/sp_cmp.c
+++ b/arch/mips/math-emu/sp_cmp.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig)
+int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig)
 {
 	COMPXSP;
 	COMPYSP;
diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c
index d7747928c954..1f62865ffcbd 100644
--- a/arch/mips/math-emu/sp_div.c
+++ b/arch/mips/math-emu/sp_div.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y)
 {
 	COMPXSP;
 	COMPYSP;
diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c
index e1515aae0166..cbefb88a14ef 100644
--- a/arch/mips/math-emu/sp_fdp.c
+++ b/arch/mips/math-emu/sp_fdp.c
@@ -26,10 +26,10 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_fdp(ieee754dp x)
+union ieee754sp ieee754sp_fdp(union ieee754dp x)
 {
 	COMPXDP;
-	ieee754sp nan;
+	union ieee754sp nan;
 
 	EXPLODEXDP;
 
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c
index 9694d6c016cb..7ba2b40348c4 100644
--- a/arch/mips/math-emu/sp_fint.c
+++ b/arch/mips/math-emu/sp_fint.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_fint(int x)
+union ieee754sp ieee754sp_fint(int x)
 {
 	unsigned xm;
 	int xe;
@@ -70,7 +70,7 @@ ieee754sp ieee754sp_fint(int x)
 }
 
 
-ieee754sp ieee754sp_funs(unsigned int u)
+union ieee754sp ieee754sp_funs(unsigned int u)
 {
 	if ((int) u < 0)
 		return ieee754sp_add(ieee754sp_1e31(),
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c
index 16a651f29865..c457a9f8a148 100644
--- a/arch/mips/math-emu/sp_flong.c
+++ b/arch/mips/math-emu/sp_flong.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_flong(s64 x)
+union ieee754sp ieee754sp_flong(s64 x)
 {
 	u64 xm;		/* <--- need 64-bit mantissa temp */
 	int xe;
@@ -69,7 +69,7 @@ ieee754sp ieee754sp_flong(s64 x)
 }
 
 
-ieee754sp ieee754sp_fulong(u64 u)
+union ieee754sp ieee754sp_fulong(u64 u)
 {
 	if ((s64) u < 0)
 		return ieee754sp_add(ieee754sp_1e63(),
diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c
index 5bc993c30044..668252bca513 100644
--- a/arch/mips/math-emu/sp_frexp.c
+++ b/arch/mips/math-emu/sp_frexp.c
@@ -28,7 +28,7 @@
 
 /* close to ieeep754sp_logb
 */
-ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
+union ieee754sp ieee754sp_frexp(union ieee754sp x, int *eptr)
 {
 	COMPXSP;
 	CLEARCX;
diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c
index 9c14e0c75bd2..4dfe5386e89d 100644
--- a/arch/mips/math-emu/sp_logb.c
+++ b/arch/mips/math-emu/sp_logb.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_logb(ieee754sp x)
+union ieee754sp ieee754sp_logb(union ieee754sp x)
 {
 	COMPXSP;
 
diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c
index 25a0fbaa0556..30d53ec1f7eb 100644
--- a/arch/mips/math-emu/sp_modf.c
+++ b/arch/mips/math-emu/sp_modf.c
@@ -28,7 +28,7 @@
 
 /* modf function is always exact for a finite number
 */
-ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp *ip)
+union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp *ip)
 {
 	COMPXSP;
 
diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c
index fa4675cf2aad..c628f3c495dc 100644
--- a/arch/mips/math-emu/sp_mul.c
+++ b/arch/mips/math-emu/sp_mul.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y)
 {
 	COMPXSP;
 	COMPYSP;
diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c
index dd76196984c8..9831d428af6f 100644
--- a/arch/mips/math-emu/sp_scalb.c
+++ b/arch/mips/math-emu/sp_scalb.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_scalb(ieee754sp x, int n)
+union ieee754sp ieee754sp_scalb(union ieee754sp x, int n)
 {
 	COMPXSP;
 
@@ -51,7 +51,7 @@ ieee754sp ieee754sp_scalb(ieee754sp x, int n)
 }
 
 
-ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
+union ieee754sp ieee754sp_ldexp(union ieee754sp x, int n)
 {
 	return ieee754sp_scalb(x, n);
 }
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
index ae4fcfafd853..633c7a54cf1e 100644
--- a/arch/mips/math-emu/sp_simple.c
+++ b/arch/mips/math-emu/sp_simple.c
@@ -26,12 +26,12 @@
 
 #include "ieee754sp.h"
 
-int ieee754sp_finite(ieee754sp x)
+int ieee754sp_finite(union ieee754sp x)
 {
 	return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
 }
 
-ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y)
 {
 	CLEARCX;
 	SPSIGN(x) = SPSIGN(y);
@@ -39,7 +39,7 @@ ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
 }
 
 
-ieee754sp ieee754sp_neg(ieee754sp x)
+union ieee754sp ieee754sp_neg(union ieee754sp x)
 {
 	COMPXSP;
 
@@ -55,7 +55,7 @@ ieee754sp ieee754sp_neg(ieee754sp x)
 	SPSIGN(x) ^= 1;
 
 	if (xc == IEEE754_CLASS_SNAN) {
-		ieee754sp y = ieee754sp_indef();
+		union ieee754sp y = ieee754sp_indef();
 		SETCX(IEEE754_INVALID_OPERATION);
 		SPSIGN(y) = SPSIGN(x);
 		return ieee754sp_nanxcpt(y, "neg");
@@ -65,7 +65,7 @@ ieee754sp ieee754sp_neg(ieee754sp x)
 }
 
 
-ieee754sp ieee754sp_abs(ieee754sp x)
+union ieee754sp ieee754sp_abs(union ieee754sp x)
 {
 	COMPXSP;
 
diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c
index fed20175f5fb..4c60d91961f4 100644
--- a/arch/mips/math-emu/sp_sqrt.c
+++ b/arch/mips/math-emu/sp_sqrt.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_sqrt(ieee754sp x)
+union ieee754sp ieee754sp_sqrt(union ieee754sp x)
 {
 	int ix, s, q, m, t, i;
 	unsigned int r;
diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c
index e595c6f3d0bb..ed67acfb114f 100644
--- a/arch/mips/math-emu/sp_sub.c
+++ b/arch/mips/math-emu/sp_sub.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
 {
 	COMPXSP;
 	COMPYSP;
diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c
index 0fe9acc7716e..a69dfe5dda3a 100644
--- a/arch/mips/math-emu/sp_tint.c
+++ b/arch/mips/math-emu/sp_tint.c
@@ -24,10 +24,9 @@
  */
 
 
-#include <linux/kernel.h>
 #include "ieee754sp.h"
 
-int ieee754sp_tint(ieee754sp x)
+int ieee754sp_tint(union ieee754sp x)
 {
 	COMPXSP;
 
@@ -113,9 +112,9 @@ int ieee754sp_tint(ieee754sp x)
 }
 
 
-unsigned int ieee754sp_tuns(ieee754sp x)
+unsigned int ieee754sp_tuns(union ieee754sp x)
 {
-	ieee754sp hb = ieee754sp_1e31();
+	union ieee754sp hb = ieee754sp_1e31();
 
 	/* what if x < 0 ?? */
 	if (ieee754sp_lt(x, hb))
diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c
index d0ca6e22be29..da412d38d5ef 100644
--- a/arch/mips/math-emu/sp_tlong.c
+++ b/arch/mips/math-emu/sp_tlong.c
@@ -26,7 +26,7 @@
 
 #include "ieee754sp.h"
 
-s64 ieee754sp_tlong(ieee754sp x)
+s64 ieee754sp_tlong(union ieee754sp x)
 {
 	COMPXDP;		/* <-- need 64-bit mantissa tmp */
 
@@ -108,9 +108,9 @@ s64 ieee754sp_tlong(ieee754sp x)
 }
 
 
-u64 ieee754sp_tulong(ieee754sp x)
+u64 ieee754sp_tulong(union ieee754sp x)
 {
-	ieee754sp hb = ieee754sp_1e63();
+	union ieee754sp hb = ieee754sp_1e63();
 
 	/* what if x < 0 ?? */
 	if (ieee754sp_lt(x, hb))
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index e422b38d3113..9e67cdea3c74 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -29,15 +29,15 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
 	unsigned long pfn);
 void (*flush_icache_range)(unsigned long start, unsigned long end);
+EXPORT_SYMBOL_GPL(flush_icache_range);
 void (*local_flush_icache_range)(unsigned long start, unsigned long end);
 
 void (*__flush_cache_vmap)(void);
 void (*__flush_cache_vunmap)(void);
 
 void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
-void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
-
 EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
+void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 654d5ba6e310..ecbd6676bd33 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -6,4 +6,5 @@ generic-y += exec.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff --git a/arch/mn10300/include/asm/scatterlist.h b/arch/mn10300/include/asm/scatterlist.h
deleted file mode 100644
index 7baa4006008a..000000000000
--- a/arch/mn10300/include/asm/scatterlist.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* MN10300 Scatterlist definitions
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_SCATTERLIST_H
-#define _ASM_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_SCATTERLIST_H */
diff --git a/arch/parisc/include/asm/shmparam.h b/arch/parisc/include/asm/shmparam.h
index 628ddc22faa8..afe1300ab667 100644
--- a/arch/parisc/include/asm/shmparam.h
+++ b/arch/parisc/include/asm/shmparam.h
@@ -1,8 +1,7 @@
 #ifndef _ASMPARISC_SHMPARAM_H
 #define _ASMPARISC_SHMPARAM_H
 
-#define __ARCH_FORCE_SHMLBA 	1
-
-#define SHMLBA 0x00400000   /* attach addr needs to be 4 Mb aligned */
+#define SHMLBA	   PAGE_SIZE	/* attach addr a multiple of this */
+#define SHM_COLOUR 0x00400000	/* shared mappings colouring */
 
 #endif /* _ASMPARISC_SHMPARAM_H */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index a6ffc775a9f8..f6448c7c62b5 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -323,7 +323,8 @@ void flush_dcache_page(struct page *page)
 		 * specifically accesses it, of course) */
 
 		flush_tlb_page(mpnt, addr);
-		if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
+		if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))
+				      != (addr & (SHM_COLOUR - 1))) {
 			__flush_cache_page(mpnt, addr, page_to_phys(page));
 			if (old_addr)
 				printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? (char *)mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index b7cadc4a06cd..31ffa9b55322 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -45,7 +45,7 @@
 
 static int get_offset(unsigned int last_mmap)
 {
-	return (last_mmap & (SHMLBA-1)) >> PAGE_SHIFT;
+	return (last_mmap & (SHM_COLOUR-1)) >> PAGE_SHIFT;
 }
 
 static unsigned long shared_align_offset(unsigned int last_mmap,
@@ -57,8 +57,8 @@ static unsigned long shared_align_offset(unsigned int last_mmap,
 static inline unsigned long COLOR_ALIGN(unsigned long addr,
 			 unsigned int last_mmap, unsigned long pgoff)
 {
-	unsigned long base = (addr+SHMLBA-1) & ~(SHMLBA-1);
-	unsigned long off  = (SHMLBA-1) &
+	unsigned long base = (addr+SHM_COLOUR-1) & ~(SHM_COLOUR-1);
+	unsigned long off  = (SHM_COLOUR-1) &
 		(shared_align_offset(last_mmap, pgoff) << PAGE_SHIFT);
 
 	return base + off;
@@ -101,7 +101,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	if (flags & MAP_FIXED) {
 		if ((flags & MAP_SHARED) && last_mmap &&
 		    (addr - shared_align_offset(last_mmap, pgoff))
-				& (SHMLBA - 1))
+				& (SHM_COLOUR - 1))
 			return -EINVAL;
 		goto found_addr;
 	}
@@ -122,7 +122,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.length = len;
 	info.low_limit = mm->mmap_legacy_base;
 	info.high_limit = mmap_upper_limit();
-	info.align_mask = last_mmap ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
 	info.align_offset = shared_align_offset(last_mmap, pgoff);
 	addr = vm_unmapped_area(&info);
 
@@ -161,7 +161,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	if (flags & MAP_FIXED) {
 		if ((flags & MAP_SHARED) && last_mmap &&
 		    (addr - shared_align_offset(last_mmap, pgoff))
-			& (SHMLBA - 1))
+			& (SHM_COLOUR - 1))
 			return -EINVAL;
 		goto found_addr;
 	}
@@ -182,7 +182,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.length = len;
 	info.low_limit = PAGE_SIZE;
 	info.high_limit = mm->mmap_base;
-	info.align_mask = last_mmap ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
 	info.align_offset = shared_align_offset(last_mmap, pgoff);
 	addr = vm_unmapped_area(&info);
 	if (!(addr & ~PAGE_MASK))
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 80e5dd248934..83ead0ea127d 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -392,7 +392,7 @@
 	ENTRY_COMP(vmsplice)
 	ENTRY_COMP(move_pages)		/* 295 */
 	ENTRY_SAME(getcpu)
-	ENTRY_SAME(epoll_pwait)
+	ENTRY_COMP(epoll_pwait)
 	ENTRY_COMP(statfs64)
 	ENTRY_COMP(fstatfs64)
 	ENTRY_COMP(kexec_load)		/* 300 */
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index 413dc1769299..b2b441b32341 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -470,7 +470,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
 		return 0;
 
 	/* if a load or store fault occured we can get the faulty addr */
-	d = &__get_cpu_var(exception_data);
+	d = this_cpu_ptr(&exception_data);
 	fault_addr = d->fault_addr;
 
 	/* error in load or store? */
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 9d08c71a967e..747550762f3c 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -151,7 +151,7 @@ int fixup_exception(struct pt_regs *regs)
 	fix = search_exception_tables(regs->iaoq[0]);
 	if (fix) {
 		struct exception_data *d;
-		d = &__get_cpu_var(exception_data);
+		d = this_cpu_ptr(&exception_data);
 		d->fault_ip = regs->iaoq[0];
 		d->fault_space = regs->isr;
 		d->fault_addr = regs->ior;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index e0998997943b..caece570d0b4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -111,6 +111,7 @@ config PPC
 	select HAVE_DMA_API_DEBUG
 	select HAVE_OPROFILE
 	select HAVE_DEBUG_KMEMLEAK
+	select ARCH_HAS_SG_CHAIN
 	select GENERIC_ATOMIC64 if PPC32
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select HAVE_PERF_EVENTS
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 3fb1bc432f4f..7f23f162ce9c 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -4,5 +4,6 @@ generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += vtime.h
diff --git a/arch/powerpc/include/asm/scatterlist.h b/arch/powerpc/include/asm/scatterlist.h
deleted file mode 100644
index de1f620bd5c9..000000000000
--- a/arch/powerpc/include/asm/scatterlist.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_POWERPC_SCATTERLIST_H
-#define _ASM_POWERPC_SCATTERLIST_H
-/*
- * Copyright (C) 2001 PPC64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/dma.h>
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_POWERPC_SCATTERLIST_H */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 2a4779091a58..155013da27e0 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -208,7 +208,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 			  unsigned long in_devfn)
 {
 	struct pci_controller* hose;
-	struct pci_bus *bus = NULL;
+	struct pci_bus *tmp_bus, *bus = NULL;
 	struct device_node *hose_node;
 
 	/* Argh ! Please forgive me for that hack, but that's the
@@ -229,10 +229,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 	 * used on pre-domains setup. We return the first match
 	 */
 
-	list_for_each_entry(bus, &pci_root_buses, node) {
-		if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
+	list_for_each_entry(tmp_bus, &pci_root_buses, node) {
+		if (in_bus >= tmp_bus->number &&
+		    in_bus <= tmp_bus->busn_res.end) {
+			bus = tmp_bus;
 			break;
-		bus = NULL;
+		}
 	}
 	if (bus == NULL || bus->dev.of_node == NULL)
 		return -ENODEV;
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c
index 7b6c10750179..d85e86aac7fb 100644
--- a/arch/powerpc/mm/dma-noncoherent.c
+++ b/arch/powerpc/mm/dma-noncoherent.c
@@ -33,6 +33,7 @@
 #include <linux/export.h>
 
 #include <asm/tlbflush.h>
+#include <asm/dma.h>
 
 #include "mmu_decl.h"
 
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c
index 6c0b1f5f8d2c..fa9fb5b4c66c 100644
--- a/arch/powerpc/mm/subpage-prot.c
+++ b/arch/powerpc/mm/subpage-prot.c
@@ -134,7 +134,7 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len)
 static int subpage_walk_pmd_entry(pmd_t *pmd, unsigned long addr,
 				  unsigned long end, struct mm_walk *walk)
 {
-	struct vm_area_struct *vma = walk->private;
+	struct vm_area_struct *vma = walk->vma;
 	split_huge_page_pmd(vma, addr, pmd);
 	return 0;
 }
@@ -163,9 +163,7 @@ static void subpage_mark_vma_nohuge(struct mm_struct *mm, unsigned long addr,
 		if (vma->vm_start >= (addr + len))
 			break;
 		vma->vm_flags |= VM_NOHUGEPAGE;
-		subpage_proto_walk.private = vma;
-		walk_page_range(vma->vm_start, vma->vm_end,
-				&subpage_proto_walk);
+		walk_page_vma(vma, &subpage_proto_walk);
 		vma = vma->vm_next;
 	}
 }
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
index 534574a97ec9..3a104284b338 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -25,6 +25,7 @@
 #include <asm/time.h>
 #include <asm/uic.h>
 #include <asm/ppc4xx.h>
+#include <asm/dma.h>
 
 
 static __initdata struct of_device_id warp_of_bus[] = {
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 18c104820198..47d66794cf3e 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -13,6 +13,7 @@
 #include <generated/utsrelease.h>
 #include <linux/pci.h>
 #include <linux/of.h>
+#include <asm/dma.h>
 #include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
index 03aabc0e16ac..2fe12046279e 100644
--- a/arch/powerpc/platforms/amigaone/setup.c
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -24,6 +24,7 @@
 #include <asm/i8259.h>
 #include <asm/time.h>
 #include <asm/udbg.h>
+#include <asm/dma.h>
 
 extern void __flush_disable_L1(void);
 
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index d68fe34799b0..6a71a6435629 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -60,7 +60,6 @@ config PCI_QUIRKS
 
 config S390
 	def_bool y
-	select ARCH_DISCARD_MEMBLOCK
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
@@ -130,6 +129,7 @@ config S390
 	select HAVE_KVM if 64BIT
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
+	select HAVE_MEMBLOCK_PHYS_MAP
 	select HAVE_MOD_ARCH_SPECIFIC
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
@@ -139,12 +139,14 @@ config S390
 	select HAVE_VIRT_CPU_ACCOUNTING
 	select KTIME_SCALAR if 32BIT
 	select MODULES_USE_ELF_RELA
+	select NO_BOOTMEM
 	select OLD_SIGACTION
 	select OLD_SIGSUSPEND3
 	select SYSCTL_EXCEPTION_TRACE
 	select TTY
 	select VIRT_CPU_ACCOUNTING
 	select VIRT_TO_BUS
+	select ARCH_HAS_SG_CHAIN
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
@@ -329,6 +331,16 @@ config SYSVIPC_COMPAT
 config KEYS_COMPAT
 	def_bool y if COMPAT && KEYS
 
+config S390_TICKET_SPINLOCK
+	bool "Use ticket spinlocks"
+	depends on S390 && SMP
+	default n
+	help
+	  This enables support for ticket spinlocks. Ticket spinlocks
+	  are more fair by means that waiting CPUs will get the lock
+	  in the order they tried to obtain it.
+	  The tradeoff is more complex code that could impact performance.
+
 config SMP
 	def_bool y
 	prompt "Symmetric multi-processing support"
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 57892a8a9055..b3fea0722ff1 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -4,4 +4,5 @@ generic-y += clkdev.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index bbf8141408cd..3b476eb92f20 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -139,7 +139,7 @@ struct _lowcore {
 	__u32	percpu_offset;			/* 0x02f0 */
 	__u32	machine_flags;			/* 0x02f4 */
 	__u32	ftrace_func;			/* 0x02f8 */
-	__u8	pad_0x02fc[0x0300-0x02fc];	/* 0x02fc */
+	__u32	spinlock_lockval;		/* 0x02fc */
 
 	/* Interrupt response block */
 	__u8	irb[64];			/* 0x0300 */
@@ -285,7 +285,8 @@ struct _lowcore {
 	__u64	machine_flags;			/* 0x0388 */
 	__u64	ftrace_func;			/* 0x0390 */
 	__u64	gmap;				/* 0x0398 */
-	__u8	pad_0x03a0[0x0400-0x03a0];	/* 0x03a0 */
+	__u32	spinlock_lockval;		/* 0x03a0 */
+	__u8	pad_0x03a0[0x0400-0x03a4];	/* 0x03a4 */
 
 	/* Interrupt response block. */
 	__u8	irb[64];			/* 0x0400 */
diff --git a/arch/s390/include/asm/scatterlist.h b/arch/s390/include/asm/scatterlist.h
deleted file mode 100644
index 6d45ef6c12a7..000000000000
--- a/arch/s390/include/asm/scatterlist.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index b31b22dba948..089a49814c50 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -9,7 +9,6 @@
 
 
 #define PARMAREA		0x10400
-#define MEMORY_CHUNKS		256
 
 #ifndef __ASSEMBLY__
 
@@ -31,22 +30,11 @@
 #endif /* CONFIG_64BIT */
 #define COMMAND_LINE      ((char *)            (0x10480))
 
-#define CHUNK_READ_WRITE 0
-#define CHUNK_READ_ONLY  1
-
-struct mem_chunk {
-	unsigned long addr;
-	unsigned long size;
-	int type;
-};
-
-extern struct mem_chunk memory_chunk[];
 extern int memory_end_set;
 extern unsigned long memory_end;
+extern unsigned long max_physmem_end;
 
-void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize);
-void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
-		     unsigned long size);
+extern void detect_memory_memblock(void);
 
 /*
  * Machine features detected in head.S
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h
index d091aa1aaf11..bf9c823d4020 100644
--- a/arch/s390/include/asm/sigp.h
+++ b/arch/s390/include/asm/sigp.h
@@ -31,4 +31,23 @@
 #define SIGP_STATUS_INCORRECT_STATE	0x00000200UL
 #define SIGP_STATUS_NOT_RUNNING		0x00000400UL
 
+#ifndef __ASSEMBLY__
+
+static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
+{
+	register unsigned int reg1 asm ("1") = parm;
+	int cc;
+
+	asm volatile(
+		"	sigp	%1,%2,0(%3)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
+	if (status && cc == 1)
+		*status = reg1;
+	return cc;
+}
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __S390_ASM_SIGP_H */
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index 160779394096..21703f85b48d 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -7,6 +7,8 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
+#include <asm/sigp.h>
+
 #ifdef CONFIG_SMP
 
 #include <asm/lowcore.h>
@@ -50,9 +52,18 @@ static inline int smp_store_status(int cpu) { return 0; }
 static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
 static inline void smp_yield(void) { }
-static inline void smp_stop_cpu(void) { }
 static inline void smp_fill_possible_mask(void) { }
 
+static inline void smp_stop_cpu(void)
+{
+	u16 pcpu = stap();
+
+	for (;;) {
+		__pcpu_sigp(pcpu, SIGP_STOP, 0, NULL);
+		cpu_relax();
+	}
+}
+
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index 83e5d216105e..84faa13aa7ae 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -1,7 +1,8 @@
 /*
  *  S390 version
- *    Copyright IBM Corp. 1999
+ *    Copyright IBM Corp. 1999, 2014
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *		 Philipp Hachtmann (phacht@linux.vnet.ibm.com)
  *
  *  Derived from "include/asm-i386/spinlock.h"
  */
@@ -11,80 +12,121 @@
 
 #include <linux/smp.h>
 
+#define SPINLOCK_LOCKVAL (S390_lowcore.spinlock_lockval)
+
 extern int spin_retry;
 
 static inline int
-_raw_compare_and_swap(volatile unsigned int *lock,
-		      unsigned int old, unsigned int new)
+_raw_compare_and_swap(unsigned int *lock, unsigned int old, unsigned int new)
 {
+	unsigned int old_expected = old;
+
 	asm volatile(
 		"	cs	%0,%3,%1"
 		: "=d" (old), "=Q" (*lock)
 		: "0" (old), "d" (new), "Q" (*lock)
 		: "cc", "memory" );
-	return old;
+	return old == old_expected;
 }
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
  *
- * We make no fairness assumptions. They have a cost.
- *
  * (the type definitions are in asm/spinlock_types.h)
  */
 
-#define arch_spin_is_locked(x) ((x)->owner_cpu != 0)
-#define arch_spin_unlock_wait(lock) \
-	do { while (arch_spin_is_locked(lock)) \
-		 arch_spin_relax(lock); } while (0)
+void arch_spin_lock_wait(arch_spinlock_t *);
+int arch_spin_trylock_retry(arch_spinlock_t *);
+void arch_spin_relax(arch_spinlock_t *);
+
+#ifdef CONFIG_S390_TICKET_SPINLOCK
+
+void arch_spin_unlock_slow(arch_spinlock_t *lp);
+
+static inline u32 arch_spin_lockval(u32 cpu)
+{
+	arch_spinlock_t new;
+
+	new.tickets.owner = ~cpu;
+	new.tickets.head = 0;
+	new.tickets.tail = 0;
+	return new.lock;
+}
+
+static inline void arch_spin_lock_wait_flags(arch_spinlock_t *lp,
+					     unsigned long flags)
+{
+	arch_spin_lock_wait(lp);
+}
+
+#else /* CONFIG_S390_TICKET_SPINLOCK */
+
+void arch_spin_lock_wait_flags(arch_spinlock_t *, unsigned long flags);
+
+static inline u32 arch_spin_lockval(int cpu)
+{
+	return ~cpu;
+}
+
+static inline void arch_spin_unlock_slow(arch_spinlock_t *lp)
+{
+}
 
-extern void arch_spin_lock_wait(arch_spinlock_t *);
-extern void arch_spin_lock_wait_flags(arch_spinlock_t *, unsigned long flags);
-extern int arch_spin_trylock_retry(arch_spinlock_t *);
-extern void arch_spin_relax(arch_spinlock_t *lock);
+#endif /* CONFIG_S390_TICKET_SPINLOCK */
 
 static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
 {
-	return lock.owner_cpu == 0;
+	return lock.lock == 0;
 }
 
-static inline void arch_spin_lock(arch_spinlock_t *lp)
+static inline int arch_spin_is_locked(arch_spinlock_t *lp)
 {
-	int old;
+	return ACCESS_ONCE(lp->lock) != 0;
+}
 
-	old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
-	if (likely(old == 0))
-		return;
-	arch_spin_lock_wait(lp);
+static inline int arch_spin_trylock_once(arch_spinlock_t *lp)
+{
+	return _raw_compare_and_swap(&lp->lock, 0, SPINLOCK_LOCKVAL);
 }
 
-static inline void arch_spin_lock_flags(arch_spinlock_t *lp,
-					 unsigned long flags)
+static inline int arch_spin_tryrelease_once(arch_spinlock_t *lp)
 {
-	int old;
+	return _raw_compare_and_swap(&lp->lock, SPINLOCK_LOCKVAL, 0);
+}
 
-	old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
-	if (likely(old == 0))
-		return;
-	arch_spin_lock_wait_flags(lp, flags);
+static inline void arch_spin_lock(arch_spinlock_t *lp)
+{
+	if (unlikely(!arch_spin_trylock_once(lp)))
+		arch_spin_lock_wait(lp);
 }
 
-static inline int arch_spin_trylock(arch_spinlock_t *lp)
+static inline void arch_spin_lock_flags(arch_spinlock_t *lp,
+					unsigned long flags)
 {
-	int old;
+	if (unlikely(!arch_spin_trylock_once(lp)))
+		arch_spin_lock_wait_flags(lp, flags);
+}
 
-	old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
-	if (likely(old == 0))
-		return 1;
-	return arch_spin_trylock_retry(lp);
+static inline int arch_spin_trylock(arch_spinlock_t *lp)
+{
+	if (unlikely(!arch_spin_trylock_once(lp)))
+		return arch_spin_trylock_retry(lp);
+	return 1;
 }
 
 static inline void arch_spin_unlock(arch_spinlock_t *lp)
 {
-	_raw_compare_and_swap(&lp->owner_cpu, lp->owner_cpu, 0);
+	if (unlikely(!arch_spin_tryrelease_once(lp)))
+		arch_spin_unlock_slow(lp);
 }
-		
+
+static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
+{
+	while (arch_spin_is_locked(lock))
+		arch_spin_relax(lock);
+}
+
 /*
  * Read-write spinlocks, allowing multiple readers
  * but only one writer.
@@ -119,7 +161,7 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 {
 	unsigned int old;
 	old = rw->lock & 0x7fffffffU;
-	if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old)
+	if (!_raw_compare_and_swap(&rw->lock, old, old + 1))
 		_raw_read_lock_wait(rw);
 }
 
@@ -127,30 +169,28 @@ static inline void arch_read_lock_flags(arch_rwlock_t *rw, unsigned long flags)
 {
 	unsigned int old;
 	old = rw->lock & 0x7fffffffU;
-	if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old)
+	if (!_raw_compare_and_swap(&rw->lock, old, old + 1))
 		_raw_read_lock_wait_flags(rw, flags);
 }
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
 {
-	unsigned int old, cmp;
+	unsigned int old;
 
-	old = rw->lock;
 	do {
-		cmp = old;
-		old = _raw_compare_and_swap(&rw->lock, old, old - 1);
-	} while (cmp != old);
+		old = ACCESS_ONCE(rw->lock);
+	} while (!_raw_compare_and_swap(&rw->lock, old, old - 1));
 }
 
 static inline void arch_write_lock(arch_rwlock_t *rw)
 {
-	if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
+	if (unlikely(!_raw_compare_and_swap(&rw->lock, 0, 0x80000000)))
 		_raw_write_lock_wait(rw);
 }
 
 static inline void arch_write_lock_flags(arch_rwlock_t *rw, unsigned long flags)
 {
-	if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
+	if (unlikely(!_raw_compare_and_swap(&rw->lock, 0, 0x80000000)))
 		_raw_write_lock_wait_flags(rw, flags);
 }
 
@@ -163,14 +203,14 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
 	unsigned int old;
 	old = rw->lock & 0x7fffffffU;
-	if (likely(_raw_compare_and_swap(&rw->lock, old, old + 1) == old))
+	if (likely(_raw_compare_and_swap(&rw->lock, old, old + 1)))
 		return 1;
 	return _raw_read_trylock_retry(rw);
 }
 
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
-	if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0))
+	if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000)))
 		return 1;
 	return _raw_write_trylock_retry(rw);
 }
diff --git a/arch/s390/include/asm/spinlock_types.h b/arch/s390/include/asm/spinlock_types.h
index 9c76656a0af0..472e12254a51 100644
--- a/arch/s390/include/asm/spinlock_types.h
+++ b/arch/s390/include/asm/spinlock_types.h
@@ -5,14 +5,31 @@
 # error "please don't include this file directly"
 #endif
 
+#ifdef CONFIG_S390_TICKET_SPINLOCK
+
+typedef struct arch_spinlock {
+	union {
+		unsigned int lock;
+		struct __raw_tickets {
+			u16 owner;
+			u8 tail;
+			u8 head;
+		} tickets;
+	};
+} arch_spinlock_t;
+
+#else /* CONFIG_S390_TICKET_SPINLOCK */
+
 typedef struct {
-	volatile unsigned int owner_cpu;
+	unsigned int lock;
 } __attribute__ ((aligned (4))) arch_spinlock_t;
 
-#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+#endif /* CONFIG_S390_TICKET_SPINLOCK */
+
+#define __ARCH_SPIN_LOCK_UNLOCKED { .lock = 0, }
 
 typedef struct {
-	volatile unsigned int lock;
+	unsigned int lock;
 } arch_rwlock_t;
 
 #define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h
index 5eb5c9ddb120..3802d2d3a18d 100644
--- a/arch/s390/include/uapi/asm/unistd.h
+++ b/arch/s390/include/uapi/asm/unistd.h
@@ -282,7 +282,8 @@
 #define __NR_finit_module	344
 #define __NR_sched_setattr	345
 #define __NR_sched_getattr	346
-#define NR_syscalls 345
+#define __NR_renameat2		347
+#define NR_syscalls 348
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
index 824c39dfddfc..45cdb37aa6f8 100644
--- a/arch/s390/kernel/compat_wrapper.c
+++ b/arch/s390/kernel/compat_wrapper.c
@@ -1,5 +1,5 @@
 /*
- *  Compat sytem call wrappers.
+ *  Compat system call wrappers.
  *
  *    Copyright IBM Corp. 2014
  */
@@ -213,3 +213,4 @@ COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, i
 COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
 COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
 COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
+COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index d7658c4b2ed5..a3b9150e6802 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 #include <linux/elf.h>
+#include <linux/memblock.h>
 #include <asm/os_info.h>
 #include <asm/elf.h>
 #include <asm/ipl.h>
@@ -22,6 +23,24 @@
 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
 #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
 
+static struct memblock_region oldmem_region;
+
+static struct memblock_type oldmem_type = {
+	.cnt = 1,
+	.max = 1,
+	.total_size = 0,
+	.regions = &oldmem_region,
+};
+
+#define for_each_dump_mem_range(i, nid, p_start, p_end, p_nid)		\
+	for (i = 0, __next_mem_range(&i, nid, &memblock.physmem,	\
+				     &oldmem_type, p_start,		\
+				     p_end, p_nid);			\
+	     i != (u64)ULLONG_MAX;					\
+	     __next_mem_range(&i, nid, &memblock.physmem,		\
+			      &oldmem_type,				\
+			      p_start, p_end, p_nid))
+
 struct dump_save_areas dump_save_areas;
 
 /*
@@ -264,19 +283,6 @@ static void *kzalloc_panic(int len)
 }
 
 /*
- * Get memory layout and create hole for oldmem
- */
-static struct mem_chunk *get_memory_layout(void)
-{
-	struct mem_chunk *chunk_array;
-
-	chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
-	detect_memory_layout(chunk_array, 0);
-	create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE);
-	return chunk_array;
-}
-
-/*
  * Initialize ELF note
  */
 static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len,
@@ -490,52 +496,33 @@ static int get_cpu_cnt(void)
  */
 static int get_mem_chunk_cnt(void)
 {
-	struct mem_chunk *chunk_array, *mem_chunk;
-	int i, cnt = 0;
+	int cnt = 0;
+	u64 idx;
 
-	chunk_array = get_memory_layout();
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		mem_chunk = &chunk_array[i];
-		if (chunk_array[i].type != CHUNK_READ_WRITE &&
-		    chunk_array[i].type != CHUNK_READ_ONLY)
-			continue;
-		if (mem_chunk->size == 0)
-			continue;
+	for_each_dump_mem_range(idx, NUMA_NO_NODE, NULL, NULL, NULL)
 		cnt++;
-	}
-	kfree(chunk_array);
 	return cnt;
 }
 
 /*
  * Initialize ELF loads (new kernel)
  */
-static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
+static void loads_init(Elf64_Phdr *phdr, u64 loads_offset)
 {
-	struct mem_chunk *chunk_array, *mem_chunk;
-	int i;
+	phys_addr_t start, end;
+	u64 idx;
 
-	chunk_array = get_memory_layout();
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		mem_chunk = &chunk_array[i];
-		if (mem_chunk->size == 0)
-			continue;
-		if (chunk_array[i].type != CHUNK_READ_WRITE &&
-		    chunk_array[i].type != CHUNK_READ_ONLY)
-			continue;
-		else
-			phdr->p_filesz = mem_chunk->size;
+	for_each_dump_mem_range(idx, NUMA_NO_NODE, &start, &end, NULL) {
+		phdr->p_filesz = end - start;
 		phdr->p_type = PT_LOAD;
-		phdr->p_offset = mem_chunk->addr;
-		phdr->p_vaddr = mem_chunk->addr;
-		phdr->p_paddr = mem_chunk->addr;
-		phdr->p_memsz = mem_chunk->size;
+		phdr->p_offset = start;
+		phdr->p_vaddr = start;
+		phdr->p_paddr = start;
+		phdr->p_memsz = end - start;
 		phdr->p_flags = PF_R | PF_W | PF_X;
 		phdr->p_align = PAGE_SIZE;
 		phdr++;
 	}
-	kfree(chunk_array);
-	return i;
 }
 
 /*
@@ -584,6 +571,14 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
 	/* If we cannot get HSA size for zfcpdump return error */
 	if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp_get_hsa_size())
 		return -ENODEV;
+
+	/* For kdump, exclude previous crashkernel memory */
+	if (OLDMEM_BASE) {
+		oldmem_region.base = OLDMEM_BASE;
+		oldmem_region.size = OLDMEM_SIZE;
+		oldmem_type.total_size = OLDMEM_SIZE;
+	}
+
 	mem_chunk_cnt = get_mem_chunk_cnt();
 
 	alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index e6af9406987c..acb412442e5e 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -144,10 +144,10 @@ void show_registers(struct pt_regs *regs)
 	char *mode;
 
 	mode = user_mode(regs) ? "User" : "Krnl";
-	printk("%s PSW : %p %p (%pSR)\n",
-	       mode, (void *) regs->psw.mask,
-	       (void *) regs->psw.addr,
-	       (void *) regs->psw.addr);
+	printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
+	if (!user_mode(regs))
+		printk(" (%pSR)", (void *)regs->psw.addr);
+	printk("\n");
 	printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
 	       "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
 	       mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index a734f3585ceb..0dff972a169c 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -258,13 +258,19 @@ static __init void setup_topology(void)
 static void early_pgm_check_handler(void)
 {
 	const struct exception_table_entry *fixup;
+	unsigned long cr0, cr0_new;
 	unsigned long addr;
 
 	addr = S390_lowcore.program_old_psw.addr;
 	fixup = search_exception_tables(addr & PSW_ADDR_INSN);
 	if (!fixup)
 		disabled_wait(0);
+	/* Disable low address protection before storing into lowcore. */
+	__ctl_store(cr0, 0, 0);
+	cr0_new = cr0 & ~(1UL << 28);
+	__ctl_load(cr0_new, 0, 0);
 	S390_lowcore.program_old_psw.addr = extable_fixup(fixup)|PSW_ADDR_AMODE;
+	__ctl_load(cr0, 0, 0);
 }
 
 static noinline __init void setup_lowcore_early(void)
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 9a99856df1c9..6dbe80983a24 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -59,7 +59,6 @@ ENTRY(startup_continue)
 	.long	0			# cr13: home space segment table
 	.long	0xc0000000		# cr14: machine check handling off
 	.long	0			# cr15: linkage stack operations
-.Lmchunk:.long	memory_chunk
 .Lbss_bgn:  .long __bss_start
 .Lbss_end:  .long _end
 .Lparmaddr: .long PARMAREA
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 4ac8fafec95f..1c82619eb4f7 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -64,7 +64,7 @@ void update_cr_regs(struct task_struct *task)
 		if (task->thread.per_flags & PER_FLAG_NO_TE)
 			cr_new &= ~(1UL << 55);
 		if (cr_new != cr)
-			__ctl_load(cr, 0, 0);
+			__ctl_load(cr_new, 0, 0);
 		/* Set or clear transaction execution TDC bits 62 and 63. */
 		__ctl_store(cr, 2, 2);
 		cr_new = cr & ~3UL;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index f70f2489fa5f..7c5b05fa2194 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -78,10 +78,9 @@ EXPORT_SYMBOL(console_irq);
 unsigned long elf_hwcap = 0;
 char elf_platform[ELF_PLATFORM_SIZE];
 
-struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
-
 int __initdata memory_end_set;
 unsigned long __initdata memory_end;
+unsigned long __initdata max_physmem_end;
 
 unsigned long VMALLOC_START;
 EXPORT_SYMBOL(VMALLOC_START);
@@ -273,6 +272,7 @@ EXPORT_SYMBOL_GPL(pm_power_off);
 static int __init early_parse_mem(char *p)
 {
 	memory_end = memparse(p, &p);
+	memory_end &= PAGE_MASK;
 	memory_end_set = 1;
 	return 0;
 }
@@ -373,6 +373,10 @@ static void __init setup_lowcore(void)
 	mem_assign_absolute(S390_lowcore.restart_source, lc->restart_source);
 	mem_assign_absolute(S390_lowcore.restart_psw, lc->restart_psw);
 
+#ifdef CONFIG_SMP
+	lc->spinlock_lockval = arch_spin_lockval(0);
+#endif
+
 	set_prefix((u32)(unsigned long) lc);
 	lowcore_ptr[0] = lc;
 }
@@ -401,7 +405,8 @@ static struct resource __initdata *standard_resources[] = {
 static void __init setup_resources(void)
 {
 	struct resource *res, *std_res, *sub_res;
-	int i, j;
+	struct memblock_region *reg;
+	int j;
 
 	code_resource.start = (unsigned long) &_text;
 	code_resource.end = (unsigned long) &_etext - 1;
@@ -410,24 +415,13 @@ static void __init setup_resources(void)
 	bss_resource.start = (unsigned long) &__bss_start;
 	bss_resource.end = (unsigned long) &__bss_stop - 1;
 
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		if (!memory_chunk[i].size)
-			continue;
+	for_each_memblock(memory, reg) {
 		res = alloc_bootmem_low(sizeof(*res));
 		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
-		switch (memory_chunk[i].type) {
-		case CHUNK_READ_WRITE:
-			res->name = "System RAM";
-			break;
-		case CHUNK_READ_ONLY:
-			res->name = "System ROM";
-			res->flags |= IORESOURCE_READONLY;
-			break;
-		default:
-			res->name = "reserved";
-		}
-		res->start = memory_chunk[i].addr;
-		res->end = res->start + memory_chunk[i].size - 1;
+
+		res->name = "System RAM";
+		res->start = reg->base;
+		res->end = reg->base + reg->size - 1;
 		request_resource(&iomem_resource, res);
 
 		for (j = 0; j < ARRAY_SIZE(standard_resources); j++) {
@@ -451,48 +445,11 @@ static void __init setup_resources(void)
 static void __init setup_memory_end(void)
 {
 	unsigned long vmax, vmalloc_size, tmp;
-	unsigned long real_memory_size = 0;
-	int i;
-
-
-#ifdef CONFIG_ZFCPDUMP
-	if (ipl_info.type == IPL_TYPE_FCP_DUMP &&
-	    !OLDMEM_BASE && sclp_get_hsa_size()) {
-		memory_end = sclp_get_hsa_size();
-		memory_end_set = 1;
-	}
-#endif
-	memory_end &= PAGE_MASK;
-
-	/*
-	 * Make sure all chunks are MAX_ORDER aligned so we don't need the
-	 * extra checks that HOLES_IN_ZONE would require.
-	 */
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		unsigned long start, end;
-		struct mem_chunk *chunk;
-		unsigned long align;
-
-		chunk = &memory_chunk[i];
-		if (!chunk->size)
-			continue;
-		align = 1UL << (MAX_ORDER + PAGE_SHIFT - 1);
-		start = (chunk->addr + align - 1) & ~(align - 1);
-		end = (chunk->addr + chunk->size) & ~(align - 1);
-		if (start >= end)
-			memset(chunk, 0, sizeof(*chunk));
-		else {
-			chunk->addr = start;
-			chunk->size = end - start;
-		}
-		real_memory_size = max(real_memory_size,
-				       chunk->addr + chunk->size);
-	}
 
 	/* Choose kernel address space layout: 2, 3, or 4 levels. */
 #ifdef CONFIG_64BIT
 	vmalloc_size = VMALLOC_END ?: (128UL << 30) - MODULES_LEN;
-	tmp = (memory_end ?: real_memory_size) / PAGE_SIZE;
+	tmp = (memory_end ?: max_physmem_end) / PAGE_SIZE;
 	tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size;
 	if (tmp <= (1UL << 42))
 		vmax = 1UL << 42;	/* 3-level kernel page table */
@@ -520,21 +477,11 @@ static void __init setup_memory_end(void)
 	vmemmap = (struct page *) tmp;
 
 	/* Take care that memory_end is set and <= vmemmap */
-	memory_end = min(memory_end ?: real_memory_size, tmp);
-
-	/* Fixup memory chunk array to fit into 0..memory_end */
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		struct mem_chunk *chunk = &memory_chunk[i];
+	memory_end = min(memory_end ?: max_physmem_end, tmp);
+	max_pfn = max_low_pfn = PFN_DOWN(memory_end);
+	memblock_remove(memory_end, ULONG_MAX);
 
-		if (!chunk->size)
-			continue;
-		if (chunk->addr >= memory_end) {
-			memset(chunk, 0, sizeof(*chunk));
-			continue;
-		}
-		if (chunk->addr + chunk->size > memory_end)
-			chunk->size = memory_end - chunk->addr;
-	}
+	pr_notice("Max memory size: %luMB\n", memory_end >> 20);
 }
 
 static void __init setup_vmcoreinfo(void)
@@ -545,89 +492,6 @@ static void __init setup_vmcoreinfo(void)
 #ifdef CONFIG_CRASH_DUMP
 
 /*
- * Find suitable location for crashkernel memory
- */
-static unsigned long __init find_crash_base(unsigned long crash_size,
-					    char **msg)
-{
-	unsigned long crash_base;
-	struct mem_chunk *chunk;
-	int i;
-
-	if (memory_chunk[0].size < crash_size) {
-		*msg = "first memory chunk must be at least crashkernel size";
-		return 0;
-	}
-	if (OLDMEM_BASE && crash_size == OLDMEM_SIZE)
-		return OLDMEM_BASE;
-
-	for (i = MEMORY_CHUNKS - 1; i >= 0; i--) {
-		chunk = &memory_chunk[i];
-		if (chunk->size == 0)
-			continue;
-		if (chunk->type != CHUNK_READ_WRITE)
-			continue;
-		if (chunk->size < crash_size)
-			continue;
-		crash_base = (chunk->addr + chunk->size) - crash_size;
-		if (crash_base < crash_size)
-			continue;
-		if (crash_base < sclp_get_hsa_size())
-			continue;
-		if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE)
-			continue;
-		return crash_base;
-	}
-	*msg = "no suitable area found";
-	return 0;
-}
-
-/*
- * Check if crash_base and crash_size is valid
- */
-static int __init verify_crash_base(unsigned long crash_base,
-				    unsigned long crash_size,
-				    char **msg)
-{
-	struct mem_chunk *chunk;
-	int i;
-
-	/*
-	 * Because we do the swap to zero, we must have at least 'crash_size'
-	 * bytes free space before crash_base
-	 */
-	if (crash_size > crash_base) {
-		*msg = "crashkernel offset must be greater than size";
-		return -EINVAL;
-	}
-
-	/* First memory chunk must be at least crash_size */
-	if (memory_chunk[0].size < crash_size) {
-		*msg = "first memory chunk must be at least crashkernel size";
-		return -EINVAL;
-	}
-	/* Check if we fit into the respective memory chunk */
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		chunk = &memory_chunk[i];
-		if (chunk->size == 0)
-			continue;
-		if (crash_base < chunk->addr)
-			continue;
-		if (crash_base >= chunk->addr + chunk->size)
-			continue;
-		/* we have found the memory chunk */
-		if (crash_base + crash_size > chunk->addr + chunk->size) {
-			*msg = "selected memory chunk is too small for "
-				"crashkernel memory";
-			return -EINVAL;
-		}
-		return 0;
-	}
-	*msg = "invalid memory range specified";
-	return -EINVAL;
-}
-
-/*
  * When kdump is enabled, we have to ensure that no memory from
  * the area [0 - crashkernel memory size] and
  * [crashk_res.start - crashk_res.end] is set offline.
@@ -653,23 +517,44 @@ static struct notifier_block kdump_mem_nb = {
 #endif
 
 /*
+ * Make sure that the area behind memory_end is protected
+ */
+static void reserve_memory_end(void)
+{
+#ifdef CONFIG_ZFCPDUMP
+	if (ipl_info.type == IPL_TYPE_FCP_DUMP &&
+	    !OLDMEM_BASE && sclp_get_hsa_size()) {
+		memory_end = sclp_get_hsa_size();
+		memory_end &= PAGE_MASK;
+		memory_end_set = 1;
+	}
+#endif
+	if (!memory_end_set)
+		return;
+	memblock_reserve(memory_end, ULONG_MAX);
+}
+
+/*
  * Make sure that oldmem, where the dump is stored, is protected
  */
 static void reserve_oldmem(void)
 {
 #ifdef CONFIG_CRASH_DUMP
-	unsigned long real_size = 0;
-	int i;
-
-	if (!OLDMEM_BASE)
-		return;
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		struct mem_chunk *chunk = &memory_chunk[i];
+	if (OLDMEM_BASE)
+		/* Forget all memory above the running kdump system */
+		memblock_reserve(OLDMEM_SIZE, (phys_addr_t)ULONG_MAX);
+#endif
+}
 
-		real_size = max(real_size, chunk->addr + chunk->size);
-	}
-	create_mem_hole(memory_chunk, OLDMEM_BASE, OLDMEM_SIZE);
-	create_mem_hole(memory_chunk, OLDMEM_SIZE, real_size - OLDMEM_SIZE);
+/*
+ * Make sure that oldmem, where the dump is stored, is protected
+ */
+static void remove_oldmem(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+	if (OLDMEM_BASE)
+		/* Forget all memory above the running kdump system */
+		memblock_remove(OLDMEM_SIZE, (phys_addr_t)ULONG_MAX);
 #endif
 }
 
@@ -680,167 +565,132 @@ static void __init reserve_crashkernel(void)
 {
 #ifdef CONFIG_CRASH_DUMP
 	unsigned long long crash_base, crash_size;
-	char *msg = NULL;
+	phys_addr_t low, high;
 	int rc;
 
 	rc = parse_crashkernel(boot_command_line, memory_end, &crash_size,
 			       &crash_base);
-	if (rc || crash_size == 0)
-		return;
+
 	crash_base = ALIGN(crash_base, KEXEC_CRASH_MEM_ALIGN);
 	crash_size = ALIGN(crash_size, KEXEC_CRASH_MEM_ALIGN);
-	if (register_memory_notifier(&kdump_mem_nb))
+	if (rc || crash_size == 0)
 		return;
-	if (!crash_base)
-		crash_base = find_crash_base(crash_size, &msg);
-	if (!crash_base) {
-		pr_info("crashkernel reservation failed: %s\n", msg);
-		unregister_memory_notifier(&kdump_mem_nb);
+
+	if (memblock.memory.regions[0].size < crash_size) {
+		pr_info("crashkernel reservation failed: %s\n",
+			"first memory chunk must be at least crashkernel size");
 		return;
 	}
-	if (verify_crash_base(crash_base, crash_size, &msg)) {
-		pr_info("crashkernel reservation failed: %s\n", msg);
-		unregister_memory_notifier(&kdump_mem_nb);
+
+	low = crash_base ?: OLDMEM_BASE;
+	high = low + crash_size;
+	if (low >= OLDMEM_BASE && high <= OLDMEM_BASE + OLDMEM_SIZE) {
+		/* The crashkernel fits into OLDMEM, reuse OLDMEM */
+		crash_base = low;
+	} else {
+		/* Find suitable area in free memory */
+		low = max_t(unsigned long, crash_size, sclp_get_hsa_size());
+		high = crash_base ? crash_base + crash_size : ULONG_MAX;
+
+		if (crash_base && crash_base < low) {
+			pr_info("crashkernel reservation failed: %s\n",
+				"crash_base too low");
+			return;
+		}
+		low = crash_base ?: low;
+		crash_base = memblock_find_in_range(low, high, crash_size,
+						    KEXEC_CRASH_MEM_ALIGN);
+	}
+
+	if (!crash_base) {
+		pr_info("crashkernel reservation failed: %s\n",
+			"no suitable area found");
 		return;
 	}
+
+	if (register_memory_notifier(&kdump_mem_nb))
+		return;
+
 	if (!OLDMEM_BASE && MACHINE_IS_VM)
 		diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));
 	crashk_res.start = crash_base;
 	crashk_res.end = crash_base + crash_size - 1;
 	insert_resource(&iomem_resource, &crashk_res);
-	create_mem_hole(memory_chunk, crash_base, crash_size);
+	memblock_remove(crash_base, crash_size);
 	pr_info("Reserving %lluMB of memory at %lluMB "
 		"for crashkernel (System RAM: %luMB)\n",
-		crash_size >> 20, crash_base >> 20, memory_end >> 20);
+		crash_size >> 20, crash_base >> 20,
+		(unsigned long)memblock.memory.total_size >> 20);
 	os_info_crashkernel_add(crash_base, crash_size);
 #endif
 }
 
-static void __init setup_memory(void)
+/*
+ * Reserve the initrd from being used by memblock
+ */
+static void __init reserve_initrd(void)
 {
-        unsigned long bootmap_size;
-	unsigned long start_pfn, end_pfn;
-	int i;
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_start = INITRD_START;
+	initrd_end = initrd_start + INITRD_SIZE;
+	memblock_reserve(INITRD_START, INITRD_SIZE);
+#endif
+}
 
-	/*
-	 * partially used pages are not usable - thus
-	 * we are rounding upwards:
-	 */
+/*
+ * Check for initrd being in usable memory
+ */
+static void __init check_initrd(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (INITRD_START && INITRD_SIZE &&
+	    !memblock_is_region_memory(INITRD_START, INITRD_SIZE)) {
+		pr_err("initrd does not fit memory.\n");
+		memblock_free(INITRD_START, INITRD_SIZE);
+		initrd_start = initrd_end = 0;
+	}
+#endif
+}
+
+/*
+ * Reserve all kernel text
+ */
+static void __init reserve_kernel(void)
+{
+	unsigned long start_pfn;
 	start_pfn = PFN_UP(__pa(&_end));
-	end_pfn = max_pfn = PFN_DOWN(memory_end);
 
-#ifdef CONFIG_BLK_DEV_INITRD
 	/*
-	 * Move the initrd in case the bitmap of the bootmem allocater
-	 * would overwrite it.
+	 * Reserve memory used for lowcore/command line/kernel image.
 	 */
+	memblock_reserve(0, (unsigned long)_ehead);
+	memblock_reserve((unsigned long)_stext, PFN_PHYS(start_pfn)
+			 - (unsigned long)_stext);
+}
 
-	if (INITRD_START && INITRD_SIZE) {
-		unsigned long bmap_size;
-		unsigned long start;
-
-		bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1);
-		bmap_size = PFN_PHYS(bmap_size);
-
-		if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) {
-			start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE;
-
+static void __init reserve_elfcorehdr(void)
+{
 #ifdef CONFIG_CRASH_DUMP
-			if (OLDMEM_BASE) {
-				/* Move initrd behind kdump oldmem */
-				if (start + INITRD_SIZE > OLDMEM_BASE &&
-				    start < OLDMEM_BASE + OLDMEM_SIZE)
-					start = OLDMEM_BASE + OLDMEM_SIZE;
-			}
-#endif
-			if (start + INITRD_SIZE > memory_end) {
-				pr_err("initrd extends beyond end of "
-				       "memory (0x%08lx > 0x%08lx) "
-				       "disabling initrd\n",
-				       start + INITRD_SIZE, memory_end);
-				INITRD_START = INITRD_SIZE = 0;
-			} else {
-				pr_info("Moving initrd (0x%08lx -> "
-					"0x%08lx, size: %ld)\n",
-					INITRD_START, start, INITRD_SIZE);
-				memmove((void *) start, (void *) INITRD_START,
-					INITRD_SIZE);
-				INITRD_START = start;
-			}
-		}
-	}
+	if (is_kdump_kernel())
+		memblock_reserve(elfcorehdr_addr - OLDMEM_BASE,
+				 PAGE_ALIGN(elfcorehdr_size));
 #endif
+}
 
-	/*
-	 * Initialize the boot-time allocator
-	 */
-	bootmap_size = init_bootmem(start_pfn, end_pfn);
+static void __init setup_memory(void)
+{
+	struct memblock_region *reg;
 
 	/*
-	 * Register RAM areas with the bootmem allocator.
+	 * Init storage key for present memory
 	 */
-
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		unsigned long start_chunk, end_chunk, pfn;
-
-		if (!memory_chunk[i].size)
-			continue;
-		start_chunk = PFN_DOWN(memory_chunk[i].addr);
-		end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
-		end_chunk = min(end_chunk, end_pfn);
-		if (start_chunk >= end_chunk)
-			continue;
-		memblock_add_node(PFN_PHYS(start_chunk),
-				  PFN_PHYS(end_chunk - start_chunk), 0);
-		pfn = max(start_chunk, start_pfn);
-		storage_key_init_range(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
+	for_each_memblock(memory, reg) {
+		storage_key_init_range(reg->base, reg->base + reg->size);
 	}
-
 	psw_set_key(PAGE_DEFAULT_KEY);
 
-	free_bootmem_with_active_regions(0, max_pfn);
-
-	/*
-	 * Reserve memory used for lowcore/command line/kernel image.
-	 */
-	reserve_bootmem(0, (unsigned long)_ehead, BOOTMEM_DEFAULT);
-	reserve_bootmem((unsigned long)_stext,
-			PFN_PHYS(start_pfn) - (unsigned long)_stext,
-			BOOTMEM_DEFAULT);
-	/*
-	 * Reserve the bootmem bitmap itself as well. We do this in two
-	 * steps (first step was init_bootmem()) because this catches
-	 * the (very unlikely) case of us accidentally initializing the
-	 * bootmem allocator with an invalid RAM area.
-	 */
-	reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size,
-			BOOTMEM_DEFAULT);
-
-#ifdef CONFIG_CRASH_DUMP
-	if (crashk_res.start)
-		reserve_bootmem(crashk_res.start,
-				crashk_res.end - crashk_res.start + 1,
-				BOOTMEM_DEFAULT);
-	if (is_kdump_kernel())
-		reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
-				PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (INITRD_START && INITRD_SIZE) {
-		if (INITRD_START + INITRD_SIZE <= memory_end) {
-			reserve_bootmem(INITRD_START, INITRD_SIZE,
-					BOOTMEM_DEFAULT);
-			initrd_start = INITRD_START;
-			initrd_end = initrd_start + INITRD_SIZE;
-		} else {
-			pr_err("initrd extends beyond end of "
-			       "memory (0x%08lx > 0x%08lx) "
-			       "disabling initrd\n",
-			       initrd_start + INITRD_SIZE, memory_end);
-			initrd_start = initrd_end = 0;
-		}
-	}
-#endif
+	/* Only cosmetics */
+	memblock_enforce_memory_limit(memblock_end_of_DRAM());
 }
 
 /*
@@ -989,23 +839,46 @@ void __init setup_arch(char **cmdline_p)
 
         ROOT_DEV = Root_RAM0;
 
+	/* Is init_mm really needed? */
 	init_mm.start_code = PAGE_OFFSET;
 	init_mm.end_code = (unsigned long) &_etext;
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
 	parse_early_param();
-	detect_memory_layout(memory_chunk, memory_end);
 	os_info_init();
 	setup_ipl();
+
+	/* Do some memory reservations *before* memory is added to memblock */
+	reserve_memory_end();
 	reserve_oldmem();
+	reserve_kernel();
+	reserve_initrd();
+	reserve_elfcorehdr();
+	memblock_allow_resize();
+
+	/* Get information about *all* installed memory */
+	detect_memory_memblock();
+
+	remove_oldmem();
+
+	/*
+	 * Make sure all chunks are MAX_ORDER aligned so we don't need the
+	 * extra checks that HOLES_IN_ZONE would require.
+	 *
+	 * Is this still required?
+	 */
+	memblock_trim_memory(1UL << (MAX_ORDER - 1 + PAGE_SHIFT));
+
 	setup_memory_end();
-	reserve_crashkernel();
 	setup_memory();
+
+	check_initrd();
+	reserve_crashkernel();
+
 	setup_resources();
 	setup_vmcoreinfo();
 	setup_lowcore();
-
 	smp_fill_possible_mask();
         cpu_init();
 	s390_init_cpu_topology();
@@ -1027,3 +900,35 @@ void __init setup_arch(char **cmdline_p)
 	/* Setup zfcpdump support */
 	setup_zfcpdump();
 }
+
+#ifdef CONFIG_32BIT
+static int no_removal_warning __initdata;
+
+static int __init parse_no_removal_warning(char *str)
+{
+	no_removal_warning = 1;
+	return 0;
+}
+__setup("no_removal_warning", parse_no_removal_warning);
+
+static int __init removal_warning(void)
+{
+	if (no_removal_warning)
+		return 0;
+	printk(KERN_ALERT "\n\n");
+	printk(KERN_CONT "Warning - you are using a 31 bit kernel!\n\n");
+	printk(KERN_CONT "We plan to remove 31 bit kernel support from the kernel sources in March 2015.\n");
+	printk(KERN_CONT "Currently we assume that nobody is using the 31 bit kernel on old 31 bit\n");
+	printk(KERN_CONT "hardware anymore. If you think that the code should not be removed and also\n");
+	printk(KERN_CONT "future versions of the Linux kernel should be able to run in 31 bit mode\n");
+	printk(KERN_CONT "please let us know. Please write to:\n");
+	printk(KERN_CONT "linux390@de.ibm.com (mail address) and/or\n");
+	printk(KERN_CONT "linux-s390@vger.kernel.org (mailing list).\n\n");
+	printk(KERN_CONT "Thank you!\n\n");
+	printk(KERN_CONT "If this kernel runs on a 64 bit machine you may consider using a 64 bit kernel.\n");
+	printk(KERN_CONT "This message can be disabled with the \"no_removal_warning\" kernel parameter.\n");
+	schedule_timeout_uninterruptible(300 * HZ);
+	return 0;
+}
+early_initcall(removal_warning);
+#endif
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 512ce1cde2a4..1f0b474041c4 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -82,21 +82,6 @@ DEFINE_MUTEX(smp_cpu_state_mutex);
 /*
  * Signal processor helper functions.
  */
-static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
-{
-	register unsigned int reg1 asm ("1") = parm;
-	int cc;
-
-	asm volatile(
-		"	sigp	%1,%2,0(%3)\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
-	if (status && cc == 1)
-		*status = reg1;
-	return cc;
-}
-
 static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
 {
 	int cc;
@@ -185,6 +170,7 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
 	lc->panic_stack = pcpu->panic_stack + PAGE_SIZE
 		- STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
 	lc->cpu_nr = cpu;
+	lc->spinlock_lockval = arch_spin_lockval(cpu);
 #ifndef CONFIG_64BIT
 	if (MACHINE_HAS_IEEE) {
 		lc->extended_save_area_addr = get_zeroed_page(GFP_KERNEL);
@@ -241,6 +227,7 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
 	cpumask_set_cpu(cpu, mm_cpumask(&init_mm));
 	atomic_inc(&init_mm.context.attach_count);
 	lc->cpu_nr = cpu;
+	lc->spinlock_lockval = arch_spin_lockval(cpu);
 	lc->percpu_offset = __per_cpu_offset[cpu];
 	lc->kernel_asce = S390_lowcore.kernel_asce;
 	lc->machine_flags = S390_lowcore.machine_flags;
@@ -824,6 +811,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
 void __init smp_setup_processor_id(void)
 {
 	S390_lowcore.cpu_nr = 0;
+	S390_lowcore.spinlock_lockval = arch_spin_lockval(0);
 }
 
 /*
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 542ef488bac1..fe5cdf29a001 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -355,3 +355,4 @@ SYSCALL(sys_kcmp,sys_kcmp,compat_sys_kcmp)
 SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module)
 SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */
 SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr)
+SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 6298fed11ced..fa3b8cdaadac 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -333,7 +333,9 @@ static void __init alloc_masks(struct sysinfo_15_1_x *info,
 		nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
 	nr_masks = max(nr_masks, 1);
 	for (i = 0; i < nr_masks; i++) {
-		mask->next = alloc_bootmem(sizeof(struct mask_info));
+		mask->next = alloc_bootmem_align(
+			roundup_pow_of_two(sizeof(struct mask_info)),
+			roundup_pow_of_two(sizeof(struct mask_info)));
 		mask = mask->next;
 	}
 }
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index f709983f41f8..0946b99fe6c3 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -1,8 +1,9 @@
 /*
  *    Out of line spinlock code.
  *
- *    Copyright IBM Corp. 2004, 2006
+ *    Copyright IBM Corp. 2004, 2014
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *		 Philipp Hachtmann (phacht@linux.vnet.ibm.com)
  */
 
 #include <linux/types.h>
@@ -24,29 +25,111 @@ static int __init spin_retry_setup(char *str)
 }
 __setup("spin_retry=", spin_retry_setup);
 
+#ifdef CONFIG_S390_TICKET_SPINLOCK
+
+void arch_spin_lock_wait(arch_spinlock_t *lp)
+{
+	arch_spinlock_t cur, new;
+	int cpu, owner, count;
+	u8 ticket = 0;
+
+	cpu = smp_processor_id();
+	count = spin_retry;
+	while (1) {
+		new.lock = cur.lock = ACCESS_ONCE(lp->lock);
+		if (new.lock == 0) {
+			/* The lock is free with no waiter, try to get it. */
+			new.tickets.owner = (u16) ~cpu;
+		} else if (!ticket) {
+			/* Try to get a ticket. */
+			new.tickets.tail = (u8)(new.tickets.tail + 1) ? : 1;
+			if (new.tickets.tail == new.tickets.head)
+				/* Overflow, can't get a ticket. */
+				new.tickets.tail = cur.tickets.tail;
+		} else if (new.tickets.head == ticket)
+			new.tickets.owner = (u16) ~cpu;
+		/* Do the atomic update. */
+		if (cur.lock != new.lock &&
+		    _raw_compare_and_swap(&lp->lock, cur.lock, new.lock)) {
+			/* Update successful. */
+			if (new.tickets.owner == (u16) ~cpu)
+				return;		/* Got the lock. */
+			ticket = new.tickets.tail; /* Got a ticket. */
+			count = 0;
+		}
+		/* Lock could not be acquired yet. */
+		if (count--)
+			continue;
+		count = spin_retry;
+		owner = cur.tickets.owner;
+		if (ticket) {
+			if (owner && smp_vcpu_scheduled(~owner)) {
+				if (MACHINE_IS_LPAR)
+					continue;
+			} else
+				count = 0;
+		}
+		/* Yield the cpu. */
+		if (owner)
+			smp_yield_cpu(~owner);
+		else
+			smp_yield();
+	}
+}
+EXPORT_SYMBOL(arch_spin_lock_wait);
+
+void arch_spin_unlock_slow(arch_spinlock_t *lp)
+{
+	arch_spinlock_t cur, new;
+
+	do {
+		cur.lock = ACCESS_ONCE(lp->lock);
+		new.lock = 0;
+		if (cur.tickets.head != cur.tickets.tail) {
+			new.tickets.tail = cur.tickets.tail;
+			new.tickets.head = (u8)(cur.tickets.head + 1) ? : 1;
+			new.tickets.owner = 0;
+		}
+	} while (!_raw_compare_and_swap(&lp->lock, cur.lock, new.lock));
+}
+EXPORT_SYMBOL(arch_spin_unlock_slow);
+
+void arch_spin_relax(arch_spinlock_t *lp)
+{
+	unsigned int cpu = lp->tickets.owner;
+
+	if (cpu != 0) {
+		if (MACHINE_IS_VM || MACHINE_IS_KVM ||
+		    !smp_vcpu_scheduled(~cpu))
+			smp_yield_cpu(~cpu);
+	}
+}
+EXPORT_SYMBOL(arch_spin_relax);
+
+#else /* CONFIG_S390_TICKET_SPINLOCK */
+
 void arch_spin_lock_wait(arch_spinlock_t *lp)
 {
 	int count = spin_retry;
-	unsigned int cpu = ~smp_processor_id();
+	unsigned int cpu = SPINLOCK_LOCKVAL;
 	unsigned int owner;
 
 	while (1) {
-		owner = lp->owner_cpu;
+		owner = lp->lock;
 		if (!owner || smp_vcpu_scheduled(~owner)) {
 			for (count = spin_retry; count > 0; count--) {
 				if (arch_spin_is_locked(lp))
 					continue;
-				if (_raw_compare_and_swap(&lp->owner_cpu, 0,
-							  cpu) == 0)
+				if (_raw_compare_and_swap(&lp->lock, 0, cpu))
 					return;
 			}
 			if (MACHINE_IS_LPAR)
 				continue;
 		}
-		owner = lp->owner_cpu;
+		owner = lp->lock;
 		if (owner)
 			smp_yield_cpu(~owner);
-		if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
+		if (_raw_compare_and_swap(&lp->lock, 0, cpu))
 			return;
 	}
 }
@@ -55,62 +138,62 @@ EXPORT_SYMBOL(arch_spin_lock_wait);
 void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
 {
 	int count = spin_retry;
-	unsigned int cpu = ~smp_processor_id();
+	unsigned int cpu = SPINLOCK_LOCKVAL;
 	unsigned int owner;
 
 	local_irq_restore(flags);
 	while (1) {
-		owner = lp->owner_cpu;
+		owner = lp->lock;
 		if (!owner || smp_vcpu_scheduled(~owner)) {
 			for (count = spin_retry; count > 0; count--) {
 				if (arch_spin_is_locked(lp))
 					continue;
 				local_irq_disable();
-				if (_raw_compare_and_swap(&lp->owner_cpu, 0,
-							  cpu) == 0)
+				if (_raw_compare_and_swap(&lp->lock, 0, cpu))
 					return;
 				local_irq_restore(flags);
 			}
 			if (MACHINE_IS_LPAR)
 				continue;
 		}
-		owner = lp->owner_cpu;
+		owner = lp->lock;
 		if (owner)
 			smp_yield_cpu(~owner);
 		local_irq_disable();
-		if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
+		if (_raw_compare_and_swap(&lp->lock, 0, cpu))
 			return;
 		local_irq_restore(flags);
 	}
 }
 EXPORT_SYMBOL(arch_spin_lock_wait_flags);
 
+void arch_spin_relax(arch_spinlock_t *lp)
+{
+	unsigned int cpu = lp->lock;
+	if (cpu != 0) {
+		if (MACHINE_IS_VM || MACHINE_IS_KVM ||
+		    !smp_vcpu_scheduled(~cpu))
+			smp_yield_cpu(~cpu);
+	}
+}
+EXPORT_SYMBOL(arch_spin_relax);
+
+#endif /* CONFIG_S390_TICKET_SPINLOCK */
+
 int arch_spin_trylock_retry(arch_spinlock_t *lp)
 {
-	unsigned int cpu = ~smp_processor_id();
 	int count;
 
 	for (count = spin_retry; count > 0; count--) {
 		if (arch_spin_is_locked(lp))
 			continue;
-		if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
+		if (arch_spin_trylock_once(lp))
 			return 1;
 	}
 	return 0;
 }
 EXPORT_SYMBOL(arch_spin_trylock_retry);
 
-void arch_spin_relax(arch_spinlock_t *lock)
-{
-	unsigned int cpu = lock->owner_cpu;
-	if (cpu != 0) {
-		if (MACHINE_IS_VM || MACHINE_IS_KVM ||
-		    !smp_vcpu_scheduled(~cpu))
-			smp_yield_cpu(~cpu);
-	}
-}
-EXPORT_SYMBOL(arch_spin_relax);
-
 void _raw_read_lock_wait(arch_rwlock_t *rw)
 {
 	unsigned int old;
@@ -124,7 +207,7 @@ void _raw_read_lock_wait(arch_rwlock_t *rw)
 		if (!arch_read_can_lock(rw))
 			continue;
 		old = rw->lock & 0x7fffffffU;
-		if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
+		if (_raw_compare_and_swap(&rw->lock, old, old + 1))
 			return;
 	}
 }
@@ -145,7 +228,7 @@ void _raw_read_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags)
 			continue;
 		old = rw->lock & 0x7fffffffU;
 		local_irq_disable();
-		if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
+		if (_raw_compare_and_swap(&rw->lock, old, old + 1))
 			return;
 	}
 }
@@ -160,7 +243,7 @@ int _raw_read_trylock_retry(arch_rwlock_t *rw)
 		if (!arch_read_can_lock(rw))
 			continue;
 		old = rw->lock & 0x7fffffffU;
-		if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
+		if (_raw_compare_and_swap(&rw->lock, old, old + 1))
 			return 1;
 	}
 	return 0;
@@ -178,7 +261,7 @@ void _raw_write_lock_wait(arch_rwlock_t *rw)
 		}
 		if (!arch_write_can_lock(rw))
 			continue;
-		if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
+		if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000))
 			return;
 	}
 }
@@ -197,7 +280,7 @@ void _raw_write_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags)
 		if (!arch_write_can_lock(rw))
 			continue;
 		local_irq_disable();
-		if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
+		if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000))
 			return;
 	}
 }
@@ -210,7 +293,7 @@ int _raw_write_trylock_retry(arch_rwlock_t *rw)
 	while (count-- > 0) {
 		if (!arch_write_can_lock(rw))
 			continue;
-		if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
+		if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000))
 			return 1;
 	}
 	return 0;
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index 23f866b4c7f1..7416efe8eae4 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -338,9 +338,6 @@ static inline unsigned long strnlen_user_srst(const char __user *src,
 	register unsigned long reg0 asm("0") = 0;
 	unsigned long tmp1, tmp2;
 
-	if (unlikely(!size))
-		return 0;
-	update_primary_asce(current);
 	asm volatile(
 		"   la    %2,0(%1)\n"
 		"   la    %3,0(%0,%1)\n"
@@ -359,6 +356,8 @@ static inline unsigned long strnlen_user_srst(const char __user *src,
 
 unsigned long __strnlen_user(const char __user *src, unsigned long size)
 {
+	if (unlikely(!size))
+		return 0;
 	update_primary_asce(current);
 	return strnlen_user_srst(src, size);
 }
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 19f623f1f21c..2f51a998a67e 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -126,6 +126,133 @@ static inline int user_space_fault(struct pt_regs *regs)
 	return 0;
 }
 
+static int bad_address(void *p)
+{
+	unsigned long dummy;
+
+	return probe_kernel_address((unsigned long *)p, dummy);
+}
+
+#ifdef CONFIG_64BIT
+static void dump_pagetable(unsigned long asce, unsigned long address)
+{
+	unsigned long *table = __va(asce & PAGE_MASK);
+
+	pr_alert("AS:%016lx ", asce);
+	switch (asce & _ASCE_TYPE_MASK) {
+	case _ASCE_TYPE_REGION1:
+		table = table + ((address >> 53) & 0x7ff);
+		if (bad_address(table))
+			goto bad;
+		pr_cont("R1:%016lx ", *table);
+		if (*table & _REGION_ENTRY_INVALID)
+			goto out;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		/* fallthrough */
+	case _ASCE_TYPE_REGION2:
+		table = table + ((address >> 42) & 0x7ff);
+		if (bad_address(table))
+			goto bad;
+		pr_cont("R2:%016lx ", *table);
+		if (*table & _REGION_ENTRY_INVALID)
+			goto out;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		/* fallthrough */
+	case _ASCE_TYPE_REGION3:
+		table = table + ((address >> 31) & 0x7ff);
+		if (bad_address(table))
+			goto bad;
+		pr_cont("R3:%016lx ", *table);
+		if (*table & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE))
+			goto out;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		/* fallthrough */
+	case _ASCE_TYPE_SEGMENT:
+		table = table + ((address >> 20) & 0x7ff);
+		if (bad_address(table))
+			goto bad;
+		pr_cont(KERN_CONT "S:%016lx ", *table);
+		if (*table & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE))
+			goto out;
+		table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+	}
+	table = table + ((address >> 12) & 0xff);
+	if (bad_address(table))
+		goto bad;
+	pr_cont("P:%016lx ", *table);
+out:
+	pr_cont("\n");
+	return;
+bad:
+	pr_cont("BAD\n");
+}
+
+#else /* CONFIG_64BIT */
+
+static void dump_pagetable(unsigned long asce, unsigned long address)
+{
+	unsigned long *table = __va(asce & PAGE_MASK);
+
+	pr_alert("AS:%08lx ", asce);
+	table = table + ((address >> 20) & 0x7ff);
+	if (bad_address(table))
+		goto bad;
+	pr_cont("S:%08lx ", *table);
+	if (*table & _SEGMENT_ENTRY_INVALID)
+		goto out;
+	table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+	table = table + ((address >> 12) & 0xff);
+	if (bad_address(table))
+		goto bad;
+	pr_cont("P:%08lx ", *table);
+out:
+	pr_cont("\n");
+	return;
+bad:
+	pr_cont("BAD\n");
+}
+
+#endif /* CONFIG_64BIT */
+
+static void dump_fault_info(struct pt_regs *regs)
+{
+	unsigned long asce;
+
+	pr_alert("Fault in ");
+	switch (regs->int_parm_long & 3) {
+	case 3:
+		pr_cont("home space ");
+		break;
+	case 2:
+		pr_cont("secondary space ");
+		break;
+	case 1:
+		pr_cont("access register ");
+		break;
+	case 0:
+		pr_cont("primary space ");
+		break;
+	}
+	pr_cont("mode while using ");
+	if (!user_space_fault(regs)) {
+		asce = S390_lowcore.kernel_asce;
+		pr_cont("kernel ");
+	}
+#ifdef CONFIG_PGSTE
+	else if ((current->flags & PF_VCPU) && S390_lowcore.gmap) {
+		struct gmap *gmap = (struct gmap *)S390_lowcore.gmap;
+		asce = gmap->asce;
+		pr_cont("gmap ");
+	}
+#endif
+	else {
+		asce = S390_lowcore.user_asce;
+		pr_cont("user ");
+	}
+	pr_cont("ASCE.\n");
+	dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK);
+}
+
 static inline void report_user_fault(struct pt_regs *regs, long signr)
 {
 	if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
@@ -138,8 +265,9 @@ static inline void report_user_fault(struct pt_regs *regs, long signr)
 	       regs->int_code);
 	print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN);
 	printk(KERN_CONT "\n");
-	printk(KERN_ALERT "failing address: %lX\n",
-	       regs->int_parm_long & __FAIL_ADDR_MASK);
+	printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
+	       regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
+	dump_fault_info(regs);
 	show_regs(regs);
 }
 
@@ -177,11 +305,13 @@ static noinline void do_no_context(struct pt_regs *regs)
 	address = regs->int_parm_long & __FAIL_ADDR_MASK;
 	if (!user_space_fault(regs))
 		printk(KERN_ALERT "Unable to handle kernel pointer dereference"
-		       " at virtual kernel address %p\n", (void *)address);
+		       " in virtual kernel address space\n");
 	else
 		printk(KERN_ALERT "Unable to handle kernel paging request"
-		       " at virtual user address %p\n", (void *)address);
-
+		       " in virtual user address space\n");
+	printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
+	       regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
+	dump_fault_info(regs);
 	die(regs, "Oops");
 	do_exit(SIGKILL);
 }
diff --git a/arch/s390/mm/mem_detect.c b/arch/s390/mm/mem_detect.c
index cca388253a39..5535cfe0ee11 100644
--- a/arch/s390/mm/mem_detect.c
+++ b/arch/s390/mm/mem_detect.c
@@ -6,130 +6,60 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/memblock.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <asm/ipl.h>
 #include <asm/sclp.h>
 #include <asm/setup.h>
 
 #define ADDR2G (1ULL << 31)
 
-static void find_memory_chunks(struct mem_chunk chunk[], unsigned long maxsize)
+#define CHUNK_READ_WRITE 0
+#define CHUNK_READ_ONLY  1
+
+static inline void memblock_physmem_add(phys_addr_t start, phys_addr_t size)
+{
+	memblock_add_range(&memblock.memory, start, size, 0, 0);
+	memblock_add_range(&memblock.physmem, start, size, 0, 0);
+}
+
+void __init detect_memory_memblock(void)
 {
 	unsigned long long memsize, rnmax, rzm;
-	unsigned long addr = 0, size;
-	int i = 0, type;
+	unsigned long addr, size;
+	int type;
 
 	rzm = sclp_get_rzm();
 	rnmax = sclp_get_rnmax();
 	memsize = rzm * rnmax;
 	if (!rzm)
 		rzm = 1ULL << 17;
-	if (sizeof(long) == 4) {
+	if (IS_ENABLED(CONFIG_32BIT)) {
 		rzm = min(ADDR2G, rzm);
-		memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
+		memsize = min(ADDR2G, memsize);
 	}
-	if (maxsize)
-		memsize = memsize ? min((unsigned long)memsize, maxsize) : maxsize;
+	max_physmem_end = memsize;
+	addr = 0;
+	/* keep memblock lists close to the kernel */
+	memblock_set_bottom_up(true);
 	do {
 		size = 0;
 		type = tprot(addr);
 		do {
 			size += rzm;
-			if (memsize && addr + size >= memsize)
+			if (max_physmem_end && addr + size >= max_physmem_end)
 				break;
 		} while (type == tprot(addr + size));
 		if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
-			if (memsize && (addr + size > memsize))
-				size = memsize - addr;
-			chunk[i].addr = addr;
-			chunk[i].size = size;
-			chunk[i].type = type;
-			i++;
+			if (max_physmem_end && (addr + size > max_physmem_end))
+				size = max_physmem_end - addr;
+			memblock_physmem_add(addr, size);
 		}
 		addr += size;
-	} while (addr < memsize && i < MEMORY_CHUNKS);
-}
-
-/**
- * detect_memory_layout - fill mem_chunk array with memory layout data
- * @chunk: mem_chunk array to be filled
- * @maxsize: maximum address where memory detection should stop
- *
- * Fills the passed in memory chunk array with the memory layout of the
- * machine. The array must have a size of at least MEMORY_CHUNKS and will
- * be fully initialized afterwards.
- * If the maxsize paramater has a value > 0 memory detection will stop at
- * that address. It is guaranteed that all chunks have an ending address
- * that is smaller than maxsize.
- * If maxsize is 0 all memory will be detected.
- */
-void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize)
-{
-	unsigned long flags, flags_dat, cr0;
-
-	memset(chunk, 0, MEMORY_CHUNKS * sizeof(struct mem_chunk));
-	/*
-	 * Disable IRQs, DAT and low address protection so tprot does the
-	 * right thing and we don't get scheduled away with low address
-	 * protection disabled.
-	 */
-	local_irq_save(flags);
-	flags_dat = __arch_local_irq_stnsm(0xfb);
-	/*
-	 * In case DAT was enabled, make sure chunk doesn't reside in vmalloc
-	 * space. We have disabled DAT and any access to vmalloc area will
-	 * cause an exception.
-	 * If DAT was disabled we are called from early ipl code.
-	 */
-	if (test_bit(5, &flags_dat)) {
-		if (WARN_ON_ONCE(is_vmalloc_or_module_addr(chunk)))
-			goto out;
-	}
-	__ctl_store(cr0, 0, 0);
-	__ctl_clear_bit(0, 28);
-	find_memory_chunks(chunk, maxsize);
-	__ctl_load(cr0, 0, 0);
-out:
-	__arch_local_irq_ssm(flags_dat);
-	local_irq_restore(flags);
-}
-EXPORT_SYMBOL(detect_memory_layout);
-
-/*
- * Create memory hole with given address and size.
- */
-void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
-		     unsigned long size)
-{
-	int i;
-
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		struct mem_chunk *chunk = &mem_chunk[i];
-
-		if (chunk->size == 0)
-			continue;
-		if (addr > chunk->addr + chunk->size)
-			continue;
-		if (addr + size <= chunk->addr)
-			continue;
-		/* Split */
-		if ((addr > chunk->addr) &&
-		    (addr + size < chunk->addr + chunk->size)) {
-			struct mem_chunk *new = chunk + 1;
-
-			memmove(new, chunk, (MEMORY_CHUNKS-i-1) * sizeof(*new));
-			new->addr = addr + size;
-			new->size = chunk->addr + chunk->size - new->addr;
-			chunk->size = addr - chunk->addr;
-			continue;
-		} else if ((addr <= chunk->addr) &&
-			   (addr + size >= chunk->addr + chunk->size)) {
-			memmove(chunk, chunk + 1, (MEMORY_CHUNKS-i-1) * sizeof(*chunk));
-			memset(&mem_chunk[MEMORY_CHUNKS-1], 0, sizeof(*chunk));
-		} else if (addr + size < chunk->addr + chunk->size) {
-			chunk->size =  chunk->addr + chunk->size - addr - size;
-			chunk->addr = addr + size;
-		} else if (addr > chunk->addr) {
-			chunk->size = addr - chunk->addr;
-		}
-	}
+	} while (addr < max_physmem_end);
+	memblock_set_bottom_up(false);
+	if (!max_physmem_end)
+		max_physmem_end = memblock_end_of_DRAM();
 }
diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c
index 27c50f4d90cb..a90d45e9dfb0 100644
--- a/arch/s390/mm/page-states.c
+++ b/arch/s390/mm/page-states.c
@@ -12,8 +12,6 @@
 #include <linux/mm.h>
 #include <linux/gfp.h>
 #include <linux/init.h>
-#include <asm/setup.h>
-#include <asm/ipl.h>
 
 #define ESSA_SET_STABLE		1
 #define ESSA_SET_UNUSED		2
@@ -43,14 +41,6 @@ void __init cmma_init(void)
 
 	if (!cmma_flag)
 		return;
-	/*
-	 * Disable CMM for dump, otherwise  the tprot based memory
-	 * detection can fail because of unstable pages.
-	 */
-	if (OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP) {
-		cmma_flag = 0;
-		return;
-	}
 	asm volatile(
 		"       .insn rrf,0xb9ab0000,%1,%1,0,0\n"
 		"0:     la      %0,0\n"
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 72b04de18283..fe9012a49aa5 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -10,6 +10,7 @@
 #include <linux/list.h>
 #include <linux/hugetlb.h>
 #include <linux/slab.h>
+#include <linux/memblock.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
@@ -66,7 +67,8 @@ static pte_t __ref *vmem_pte_alloc(unsigned long address)
 	if (slab_is_available())
 		pte = (pte_t *) page_table_alloc(&init_mm, address);
 	else
-		pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
+		pte = alloc_bootmem_align(PTRS_PER_PTE * sizeof(pte_t),
+					  PTRS_PER_PTE * sizeof(pte_t));
 	if (!pte)
 		return NULL;
 	clear_table((unsigned long *) pte, _PAGE_INVALID,
@@ -371,16 +373,14 @@ out:
 void __init vmem_map_init(void)
 {
 	unsigned long ro_start, ro_end;
-	unsigned long start, end;
-	int i;
+	struct memblock_region *reg;
+	phys_addr_t start, end;
 
 	ro_start = PFN_ALIGN((unsigned long)&_stext);
 	ro_end = (unsigned long)&_eshared & PAGE_MASK;
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		if (!memory_chunk[i].size)
-			continue;
-		start = memory_chunk[i].addr;
-		end = memory_chunk[i].addr + memory_chunk[i].size;
+	for_each_memblock(memory, reg) {
+		start = reg->base;
+		end = reg->base + reg->size - 1;
 		if (start >= ro_end || end <= ro_start)
 			vmem_add_mem(start, end - start, 0);
 		else if (start >= ro_start && end <= ro_end)
@@ -400,23 +400,21 @@ void __init vmem_map_init(void)
 }
 
 /*
- * Convert memory chunk array to a memory segment list so there is a single
- * list that contains both r/w memory and shared memory segments.
+ * Convert memblock.memory  to a memory segment list so there is a single
+ * list that contains all memory segments.
  */
 static int __init vmem_convert_memory_chunk(void)
 {
+	struct memblock_region *reg;
 	struct memory_segment *seg;
-	int i;
 
 	mutex_lock(&vmem_mutex);
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		if (!memory_chunk[i].size)
-			continue;
+	for_each_memblock(memory, reg) {
 		seg = kzalloc(sizeof(*seg), GFP_KERNEL);
 		if (!seg)
 			panic("Out of memory...\n");
-		seg->start = memory_chunk[i].addr;
-		seg->size = memory_chunk[i].size;
+		seg->start = reg->base;
+		seg->size = reg->size;
 		insert_memory_segment(seg);
 	}
 	mutex_unlock(&vmem_mutex);
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 2f947aba4bd4..aad209199f7e 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -8,5 +8,6 @@ generic-y += cputime.h
 generic-y += hash.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += trace_clock.h
 generic-y += xor.h
diff --git a/arch/score/include/asm/scatterlist.h b/arch/score/include/asm/scatterlist.h
deleted file mode 100644
index 9f533b8362c7..000000000000
--- a/arch/score/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCORE_SCATTERLIST_H
-#define _ASM_SCORE_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_SCORE_SCATTERLIST_H */
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 29f2e988c56a..e1ea0ff154d7 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -42,6 +42,7 @@ config SPARC
 	select MODULES_USE_ELF_RELA
 	select ODD_RT_SIGACTION
 	select OLD_SIGSUSPEND
+	select ARCH_HAS_SG_CHAIN
 
 config SPARC32
 	def_bool !64BIT
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index a45821818003..cdd1b447bb6c 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -15,6 +15,7 @@ generic-y += mcs_spinlock.h
 generic-y += module.h
 generic-y += mutex.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
diff --git a/arch/sparc/include/asm/scatterlist.h b/arch/sparc/include/asm/scatterlist.h
deleted file mode 100644
index 92bb638313f8..000000000000
--- a/arch/sparc/include/asm/scatterlist.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _SPARC_SCATTERLIST_H
-#define _SPARC_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* !(_SPARC_SCATTERLIST_H) */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index a5e4b6068213..7bd64aa2e94a 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -21,6 +21,7 @@ generic-y += param.h
 generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += switch_to.h
 generic-y += topology.h
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 75298d3358e7..8a37fb235ff2 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -173,7 +173,6 @@ extern unsigned long long os_makedev(unsigned major, unsigned minor);
 
 /* start_up.c */
 extern void os_early_checks(void);
-extern void can_do_skas(void);
 extern void os_check_bugs(void);
 extern void check_host_supports_tls(int *supports_tls, int *tls_min);
 
@@ -186,7 +185,6 @@ extern int os_process_parent(int pid);
 extern void os_stop_process(int pid);
 extern void os_kill_process(int pid, int reap_child);
 extern void os_kill_ptraced_process(int pid, int reap_child);
-extern long os_ptrace_ldt(long pid, long addr, long data);
 
 extern int os_getpid(void);
 extern int os_getpgrp(void);
diff --git a/arch/um/include/shared/skas/proc_mm.h b/arch/um/include/shared/skas/proc_mm.h
deleted file mode 100644
index 902809209603..000000000000
--- a/arch/um/include/shared/skas/proc_mm.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_PROC_MM_H
-#define __SKAS_PROC_MM_H
-
-#define MM_MMAP 54
-#define MM_MUNMAP 55
-#define MM_MPROTECT 56
-#define MM_COPY_SEGMENTS 57
-
-struct mm_mmap {
-	unsigned long addr;
-	unsigned long len;
-	unsigned long prot;
-	unsigned long flags;
-	unsigned long fd;
-	unsigned long offset;
-};
-
-struct mm_munmap {
-	unsigned long addr;
-	unsigned long len;
-};
-
-struct mm_mprotect {
-	unsigned long addr;
-	unsigned long len;
-	unsigned int prot;
-};
-
-struct proc_mm_op {
-	int op;
-	union {
-		struct mm_mmap mmap;
-		struct mm_munmap munmap;
-	        struct mm_mprotect mprotect;
-		int copy_segments;
-	} u;
-};
-
-#endif
diff --git a/arch/um/include/shared/skas/skas.h b/arch/um/include/shared/skas/skas.h
index c45df961c874..911f3c45ad1f 100644
--- a/arch/um/include/shared/skas/skas.h
+++ b/arch/um/include/shared/skas/skas.h
@@ -9,13 +9,10 @@
 #include <sysdep/ptrace.h>
 
 extern int userspace_pid[];
-extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
-extern int skas_needs_stub;
 
 extern int user_thread(unsigned long stack, int flags);
 extern void new_thread_handler(void);
 extern void handle_syscall(struct uml_pt_regs *regs);
-extern int new_mm(unsigned long stack);
 extern long execute_syscall_skas(void *r);
 extern unsigned long current_stub_stack(void);
 
diff --git a/arch/um/include/shared/skas_ptrace.h b/arch/um/include/shared/skas_ptrace.h
deleted file mode 100644
index 630a9c92b93c..000000000000
--- a/arch/um/include/shared/skas_ptrace.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_PTRACE_H
-#define __SKAS_PTRACE_H
-
-#define PTRACE_FAULTINFO 52
-#define PTRACE_SWITCH_MM 55
-
-#include <sysdep/skas_ptrace.h>
-
-#endif
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 694d551c8899..8c06a4a7ad18 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -8,9 +8,6 @@
 #include <linux/sched.h>
 #include <linux/tracehook.h>
 #include <asm/uaccess.h>
-#include <skas_ptrace.h>
-
-
 
 void user_enable_single_step(struct task_struct *child)
 {
@@ -104,35 +101,6 @@ long arch_ptrace(struct task_struct *child, long request,
 		ret = ptrace_set_thread_area(child, addr, vp);
 		break;
 
-	case PTRACE_FAULTINFO: {
-		/*
-		 * Take the info from thread->arch->faultinfo,
-		 * but transfer max. sizeof(struct ptrace_faultinfo).
-		 * On i386, ptrace_faultinfo is smaller!
-		 */
-		ret = copy_to_user(p, &child->thread.arch.faultinfo,
-				   sizeof(struct ptrace_faultinfo)) ?
-			-EIO : 0;
-		break;
-	}
-
-#ifdef PTRACE_LDT
-	case PTRACE_LDT: {
-		struct ptrace_ldt ldt;
-
-		if (copy_from_user(&ldt, p, sizeof(ldt))) {
-			ret = -EIO;
-			break;
-		}
-
-		/*
-		 * This one is confusing, so just punt and return -EIO for
-		 * now
-		 */
-		ret = -EIO;
-		break;
-	}
-#endif
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		if (ret == -EIO)
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index ced8903921ae..9bdf67a092a5 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -15,28 +15,21 @@ void (*pm_power_off)(void);
 
 static void kill_off_processes(void)
 {
-	if (proc_mm)
-		/*
-		 * FIXME: need to loop over userspace_pids
-		 */
-		os_kill_ptraced_process(userspace_pid[0], 1);
-	else {
-		struct task_struct *p;
-		int pid;
-
-		read_lock(&tasklist_lock);
-		for_each_process(p) {
-			struct task_struct *t;
-
-			t = find_lock_task_mm(p);
-			if (!t)
-				continue;
-			pid = t->mm->context.id.u.pid;
-			task_unlock(t);
-			os_kill_ptraced_process(pid, 1);
-		}
-		read_unlock(&tasklist_lock);
+	struct task_struct *p;
+	int pid;
+
+	read_lock(&tasklist_lock);
+	for_each_process(p) {
+		struct task_struct *t;
+
+		t = find_lock_task_mm(p);
+		if (!t)
+			continue;
+		pid = t->mm->context.id.u.pid;
+		task_unlock(t);
+		os_kill_ptraced_process(pid, 1);
 	}
+	read_unlock(&tasklist_lock);
 }
 
 void uml_cleanup(void)
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 007d5503f49b..94abdcc1d6ad 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -54,35 +54,22 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
 	unsigned long stack = 0;
 	int ret = -ENOMEM;
 
-	if (skas_needs_stub) {
-		stack = get_zeroed_page(GFP_KERNEL);
-		if (stack == 0)
-			goto out;
-	}
+	stack = get_zeroed_page(GFP_KERNEL);
+	if (stack == 0)
+		goto out;
 
 	to_mm->id.stack = stack;
 	if (current->mm != NULL && current->mm != &init_mm)
 		from_mm = &current->mm->context;
 
-	if (proc_mm) {
-		ret = new_mm(stack);
-		if (ret < 0) {
-			printk(KERN_ERR "init_new_context_skas - "
-			       "new_mm failed, errno = %d\n", ret);
-			goto out_free;
-		}
-		to_mm->id.u.mm_fd = ret;
-	}
-	else {
-		if (from_mm)
-			to_mm->id.u.pid = copy_context_skas0(stack,
-							     from_mm->id.u.pid);
-		else to_mm->id.u.pid = start_userspace(stack);
-
-		if (to_mm->id.u.pid < 0) {
-			ret = to_mm->id.u.pid;
-			goto out_free;
-		}
+	if (from_mm)
+		to_mm->id.u.pid = copy_context_skas0(stack,
+						     from_mm->id.u.pid);
+	else to_mm->id.u.pid = start_userspace(stack);
+
+	if (to_mm->id.u.pid < 0) {
+		ret = to_mm->id.u.pid;
+		goto out_free;
 	}
 
 	ret = init_new_ldt(to_mm, from_mm);
@@ -105,9 +92,6 @@ void uml_setup_stubs(struct mm_struct *mm)
 {
 	int err, ret;
 
-	if (!skas_needs_stub)
-		return;
-
 	ret = init_stub_pte(mm, STUB_CODE,
 			    (unsigned long) &__syscall_stub_start);
 	if (ret)
@@ -154,25 +138,19 @@ void destroy_context(struct mm_struct *mm)
 {
 	struct mm_context *mmu = &mm->context;
 
-	if (proc_mm)
-		os_close_file(mmu->id.u.mm_fd);
-	else {
-		/*
-		 * If init_new_context wasn't called, this will be
-		 * zero, resulting in a kill(0), which will result in the
-		 * whole UML suddenly dying.  Also, cover negative and
-		 * 1 cases, since they shouldn't happen either.
-		 */
-		if (mmu->id.u.pid < 2) {
-			printk(KERN_ERR "corrupt mm_context - pid = %d\n",
-			       mmu->id.u.pid);
-			return;
-		}
-		os_kill_ptraced_process(mmu->id.u.pid, 1);
+	/*
+	 * If init_new_context wasn't called, this will be
+	 * zero, resulting in a kill(0), which will result in the
+	 * whole UML suddenly dying.  Also, cover negative and
+	 * 1 cases, since they shouldn't happen either.
+	 */
+	if (mmu->id.u.pid < 2) {
+		printk(KERN_ERR "corrupt mm_context - pid = %d\n",
+		       mmu->id.u.pid);
+		return;
 	}
+	os_kill_ptraced_process(mmu->id.u.pid, 1);
 
-	if (skas_needs_stub)
-		free_page(mmu->id.stack);
-
+	free_page(mmu->id.stack);
 	free_ldt(mmu);
 }
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 4da11b3c8ddb..082955d694f3 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -10,25 +10,6 @@
 #include <os.h>
 #include <skas.h>
 
-int new_mm(unsigned long stack)
-{
-	int fd, err;
-
-	fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
-	if (fd < 0)
-		return fd;
-
-	if (skas_needs_stub) {
-		err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
-		if (err) {
-			os_close_file(fd);
-			return err;
-		}
-	}
-
-	return fd;
-}
-
 extern void start_kernel(void);
 
 static int __init start_kernel_proc(void *unused)
@@ -55,14 +36,6 @@ int __init start_uml(void)
 {
 	stack_protections((unsigned long) &cpu0_irqstack);
 	set_sigstack(cpu0_irqstack, THREAD_SIZE);
-	if (proc_mm) {
-		userspace_pid[0] = start_userspace(0);
-		if (userspace_pid[0] < 0) {
-			printf("start_uml - start_userspace returned %d\n",
-			       userspace_pid[0]);
-			exit(1);
-		}
-	}
 
 	init_new_thread_signals();
 
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 974b87474a99..4a6235b758e6 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -218,7 +218,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
 		panic("Segfault with no mm");
 	}
 
-	if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
+	if (SEGV_IS_FIXABLE(&fi))
 		err = handle_page_fault(address, ip, is_write, is_user,
 					&si.si_code);
 	else {
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 016adf0985d5..6043c767d378 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -268,7 +268,6 @@ int __init linux_main(int argc, char **argv)
 	unsigned long stack;
 	unsigned int i;
 	int add;
-	char * mode;
 
 	for (i = 1; i < argc; i++) {
 		if ((i == 1) && (argv[i][0] == ' '))
@@ -291,15 +290,6 @@ int __init linux_main(int argc, char **argv)
 	/* OS sanity checks that need to happen before the kernel runs */
 	os_early_checks();
 
-	can_do_skas();
-
-	if (proc_mm && ptrace_faultinfo)
-		mode = "SKAS3";
-	else
-		mode = "SKAS0";
-
-	printf("UML running in %s mode\n", mode);
-
 	brk_start = (unsigned long) sbrk(0);
 
 	/*
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 33496fe2bb52..8408aba915b2 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -16,7 +16,6 @@
 #include <init.h>
 #include <longjmp.h>
 #include <os.h>
-#include <skas_ptrace.h>
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -102,21 +101,6 @@ void os_kill_process(int pid, int reap_child)
 		CATCH_EINTR(waitpid(pid, NULL, __WALL));
 }
 
-/* This is here uniquely to have access to the userspace errno, i.e. the one
- * used by ptrace in case of error.
- */
-
-long os_ptrace_ldt(long pid, long addr, long data)
-{
-	int ret;
-
-	ret = ptrace(PTRACE_LDT, pid, addr, data);
-
-	if (ret < 0)
-		return -errno;
-	return ret;
-}
-
 /* Kill off a ptraced child by all means available.  kill it normally first,
  * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from
  * which it can't exit directly.
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 689b18db798f..e7f8c945a573 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -12,7 +12,6 @@
 #include <as-layout.h>
 #include <mm_id.h>
 #include <os.h>
-#include <proc_mm.h>
 #include <ptrace_user.h>
 #include <registers.h>
 #include <skas.h>
@@ -46,8 +45,6 @@ static int __init init_syscall_regs(void)
 
 __initcall(init_syscall_regs);
 
-extern int proc_mm;
-
 static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
 {
 	int n, i;
@@ -56,10 +53,6 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
 	unsigned long * syscall;
 	int err, pid = mm_idp->u.pid;
 
-	if (proc_mm)
-		/* FIXME: Need to look up userspace_pid by cpu */
-		pid = userspace_pid[0];
-
 	n = ptrace_setregs(pid, syscall_regs);
 	if (n < 0) {
 		printk(UM_KERN_ERR "Registers - \n");
@@ -178,38 +171,12 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot,
 	int phys_fd, unsigned long long offset, int done, void **data)
 {
 	int ret;
+	unsigned long args[] = { virt, len, prot,
+				 MAP_SHARED | MAP_FIXED, phys_fd,
+				 MMAP_OFFSET(offset) };
 
-	if (proc_mm) {
-		struct proc_mm_op map;
-		int fd = mm_idp->u.mm_fd;
-
-		map = ((struct proc_mm_op) { .op	= MM_MMAP,
-				       .u		=
-				       { .mmap	=
-					 { .addr	= virt,
-					   .len	= len,
-					   .prot	= prot,
-					   .flags	= MAP_SHARED |
-					   MAP_FIXED,
-					   .fd	= phys_fd,
-					   .offset= offset
-					 } } } );
-		CATCH_EINTR(ret = write(fd, &map, sizeof(map)));
-		if (ret != sizeof(map)) {
-			ret = -errno;
-			printk(UM_KERN_ERR "map : /proc/mm map failed, "
-			       "err = %d\n", -ret);
-		}
-		else ret = 0;
-	}
-	else {
-		unsigned long args[] = { virt, len, prot,
-					 MAP_SHARED | MAP_FIXED, phys_fd,
-					 MMAP_OFFSET(offset) };
-
-		ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
-				       data, done);
-	}
+	ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
+			       data, done);
 
 	return ret;
 }
@@ -218,32 +185,11 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
 	  int done, void **data)
 {
 	int ret;
+	unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
+				 0 };
 
-	if (proc_mm) {
-		struct proc_mm_op unmap;
-		int fd = mm_idp->u.mm_fd;
-
-		unmap = ((struct proc_mm_op) { .op	= MM_MUNMAP,
-					 .u	=
-					 { .munmap	=
-					   { .addr	=
-					     (unsigned long) addr,
-					     .len		= len } } } );
-		CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap)));
-		if (ret != sizeof(unmap)) {
-			ret = -errno;
-			printk(UM_KERN_ERR "unmap - proc_mm write returned "
-			       "%d\n", ret);
-		}
-		else ret = 0;
-	}
-	else {
-		unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
-					 0 };
-
-		ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
-				       data, done);
-	}
+	ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
+			       data, done);
 
 	return ret;
 }
@@ -251,33 +197,11 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
 int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
 	    unsigned int prot, int done, void **data)
 {
-	struct proc_mm_op protect;
 	int ret;
+	unsigned long args[] = { addr, len, prot, 0, 0, 0 };
 
-	if (proc_mm) {
-		int fd = mm_idp->u.mm_fd;
-
-		protect = ((struct proc_mm_op) { .op	= MM_MPROTECT,
-					   .u	=
-					   { .mprotect	=
-					     { .addr	=
-					       (unsigned long) addr,
-					       .len	= len,
-					       .prot	= prot } } } );
-
-		CATCH_EINTR(ret = write(fd, &protect, sizeof(protect)));
-		if (ret != sizeof(protect)) {
-			ret = -errno;
-			printk(UM_KERN_ERR "protect failed, err = %d", -ret);
-		}
-		else ret = 0;
-	}
-	else {
-		unsigned long args[] = { addr, len, prot, 0, 0, 0 };
-
-		ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
-				       data, done);
-	}
+	ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
+			       data, done);
 
 	return ret;
 }
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index d531879a4617..452c214d86bf 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -16,11 +16,9 @@
 #include <kern_util.h>
 #include <mem.h>
 #include <os.h>
-#include <proc_mm.h>
 #include <ptrace_user.h>
 #include <registers.h>
 #include <skas.h>
-#include <skas_ptrace.h>
 #include <sysdep/stub.h>
 
 int is_skas_winch(int pid, int fd, void *data)
@@ -96,50 +94,33 @@ extern unsigned long current_stub_stack(void);
 static void get_skas_faultinfo(int pid, struct faultinfo *fi)
 {
 	int err;
+	unsigned long fpregs[FP_SIZE];
 
-	if (ptrace_faultinfo) {
-		err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
-		if (err) {
-			printk(UM_KERN_ERR "get_skas_faultinfo - "
-			       "PTRACE_FAULTINFO failed, errno = %d\n", errno);
-			fatal_sigsegv();
-		}
-
-		/* Special handling for i386, which has different structs */
-		if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
-			memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
-			       sizeof(struct faultinfo) -
-			       sizeof(struct ptrace_faultinfo));
+	err = get_fp_registers(pid, fpregs);
+	if (err < 0) {
+		printk(UM_KERN_ERR "save_fp_registers returned %d\n",
+		       err);
+		fatal_sigsegv();
 	}
-	else {
-		unsigned long fpregs[FP_SIZE];
-
-		err = get_fp_registers(pid, fpregs);
-		if (err < 0) {
-			printk(UM_KERN_ERR "save_fp_registers returned %d\n",
-			       err);
-			fatal_sigsegv();
-		}
-		err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
-		if (err) {
-			printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
-			       "errno = %d\n", pid, errno);
-			fatal_sigsegv();
-		}
-		wait_stub_done(pid);
+	err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
+	if (err) {
+		printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
+		       "errno = %d\n", pid, errno);
+		fatal_sigsegv();
+	}
+	wait_stub_done(pid);
 
-		/*
-		 * faultinfo is prepared by the stub-segv-handler at start of
-		 * the stub stack page. We just have to copy it.
-		 */
-		memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
+	/*
+	 * faultinfo is prepared by the stub-segv-handler at start of
+	 * the stub stack page. We just have to copy it.
+	 */
+	memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
 
-		err = put_fp_registers(pid, fpregs);
-		if (err < 0) {
-			printk(UM_KERN_ERR "put_fp_registers returned %d\n",
-			       err);
-			fatal_sigsegv();
-		}
+	err = put_fp_registers(pid, fpregs);
+	if (err < 0) {
+		printk(UM_KERN_ERR "put_fp_registers returned %d\n",
+		       err);
+		fatal_sigsegv();
 	}
 }
 
@@ -203,7 +184,8 @@ extern int __syscall_stub_start;
 static int userspace_tramp(void *stack)
 {
 	void *addr;
-	int err;
+	int err, fd;
+	unsigned long long offset;
 
 	ptrace(PTRACE_TRACEME, 0, 0, 0);
 
@@ -216,36 +198,32 @@ static int userspace_tramp(void *stack)
 		exit(1);
 	}
 
-	if (!proc_mm) {
-		/*
-		 * This has a pte, but it can't be mapped in with the usual
-		 * tlb_flush mechanism because this is part of that mechanism
-		 */
-		int fd;
-		unsigned long long offset;
-		fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
-		addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
-			      PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
+	/*
+	 * This has a pte, but it can't be mapped in with the usual
+	 * tlb_flush mechanism because this is part of that mechanism
+	 */
+	fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
+	addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
+		      PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
+	if (addr == MAP_FAILED) {
+		printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "
+		       "errno = %d\n", STUB_CODE, errno);
+		exit(1);
+	}
+
+	if (stack != NULL) {
+		fd = phys_mapping(to_phys(stack), &offset);
+		addr = mmap((void *) STUB_DATA,
+			    UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
+			    MAP_FIXED | MAP_SHARED, fd, offset);
 		if (addr == MAP_FAILED) {
-			printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "
-			       "errno = %d\n", STUB_CODE, errno);
+			printk(UM_KERN_ERR "mapping segfault stack "
+			       "at 0x%lx failed, errno = %d\n",
+			       STUB_DATA, errno);
 			exit(1);
 		}
-
-		if (stack != NULL) {
-			fd = phys_mapping(to_phys(stack), &offset);
-			addr = mmap((void *) STUB_DATA,
-				    UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
-				    MAP_FIXED | MAP_SHARED, fd, offset);
-			if (addr == MAP_FAILED) {
-				printk(UM_KERN_ERR "mapping segfault stack "
-				       "at 0x%lx failed, errno = %d\n",
-				       STUB_DATA, errno);
-				exit(1);
-			}
-		}
 	}
-	if (!ptrace_faultinfo && (stack != NULL)) {
+	if (stack != NULL) {
 		struct sigaction sa;
 
 		unsigned long v = STUB_CODE +
@@ -291,11 +269,7 @@ int start_userspace(unsigned long stub_stack)
 
 	sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
 
-	flags = CLONE_FILES;
-	if (proc_mm)
-		flags |= CLONE_VM;
-	else
-		flags |= SIGCHLD;
+	flags = CLONE_FILES | SIGCHLD;
 
 	pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
 	if (pid < 0) {
@@ -418,8 +392,7 @@ void userspace(struct uml_pt_regs *regs)
 
 			switch (sig) {
 			case SIGSEGV:
-				if (PTRACE_FULL_FAULTINFO ||
-				    !ptrace_faultinfo) {
+				if (PTRACE_FULL_FAULTINFO) {
 					get_skas_faultinfo(pid,
 							   &regs->faultinfo);
 					(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
@@ -576,67 +549,6 @@ int copy_context_skas0(unsigned long new_stack, int pid)
 	return err;
 }
 
-/*
- * This is used only, if stub pages are needed, while proc_mm is
- * available. Opening /proc/mm creates a new mm_context, which lacks
- * the stub-pages. Thus, we map them using /proc/mm-fd
- */
-int map_stub_pages(int fd, unsigned long code, unsigned long data,
-		   unsigned long stack)
-{
-	struct proc_mm_op mmop;
-	int n;
-	unsigned long long code_offset;
-	int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start),
-				   &code_offset);
-
-	mmop = ((struct proc_mm_op) { .op        = MM_MMAP,
-				      .u         =
-				      { .mmap    =
-					{ .addr    = code,
-					  .len     = UM_KERN_PAGE_SIZE,
-					  .prot    = PROT_EXEC,
-					  .flags   = MAP_FIXED | MAP_PRIVATE,
-					  .fd      = code_fd,
-					  .offset  = code_offset
-	} } });
-	CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
-	if (n != sizeof(mmop)) {
-		n = errno;
-		printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
-		       "offset = %llx\n", code, code_fd,
-		       (unsigned long long) code_offset);
-		printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
-		       "failed, err = %d\n", n);
-		return -n;
-	}
-
-	if (stack) {
-		unsigned long long map_offset;
-		int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);
-		mmop = ((struct proc_mm_op)
-				{ .op        = MM_MMAP,
-				  .u         =
-				  { .mmap    =
-				    { .addr    = data,
-				      .len     = UM_KERN_PAGE_SIZE,
-				      .prot    = PROT_READ | PROT_WRITE,
-				      .flags   = MAP_FIXED | MAP_SHARED,
-				      .fd      = map_fd,
-				      .offset  = map_offset
-		} } });
-		CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
-		if (n != sizeof(mmop)) {
-			n = errno;
-			printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
-			       "data failed, err = %d\n", n);
-			return -n;
-		}
-	}
-
-	return 0;
-}
-
 void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
 {
 	(*buf)[0].JB_IP = (unsigned long) handler;
@@ -733,17 +645,5 @@ void reboot_skas(void)
 
 void __switch_mm(struct mm_id *mm_idp)
 {
-	int err;
-
-	/* FIXME: need cpu pid in __switch_mm */
-	if (proc_mm) {
-		err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
-			     mm_idp->u.mm_fd);
-		if (err) {
-			printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
-			       "failed, errno = %d\n", errno);
-			fatal_sigsegv();
-		}
-	}
-	else userspace_pid[0] = mm_idp->u.pid;
+	userspace_pid[0] = mm_idp->u.pid;
 }
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 337518c5042a..47f1ff056a54 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -24,7 +24,6 @@
 #include <ptrace_user.h>
 #include <registers.h>
 #include <skas.h>
-#include <skas_ptrace.h>
 
 static void ptrace_child(void)
 {
@@ -143,44 +142,6 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit)
 }
 
 /* Changed only during early boot */
-int ptrace_faultinfo;
-static int disable_ptrace_faultinfo;
-
-int ptrace_ldt;
-static int disable_ptrace_ldt;
-
-int proc_mm;
-static int disable_proc_mm;
-
-int have_switch_mm;
-static int disable_switch_mm;
-
-int skas_needs_stub;
-
-static int __init skas0_cmd_param(char *str, int* add)
-{
-	disable_ptrace_faultinfo = 1;
-	disable_ptrace_ldt = 1;
-	disable_proc_mm = 1;
-	disable_switch_mm = 1;
-
-	return 0;
-}
-
-/* The two __uml_setup would conflict, without this stupid alias. */
-
-static int __init mode_skas0_cmd_param(char *str, int* add)
-	__attribute__((alias("skas0_cmd_param")));
-
-__uml_setup("skas0", skas0_cmd_param,
-"skas0\n"
-"    Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n");
-
-__uml_setup("mode=skas0", mode_skas0_cmd_param,
-"mode=skas0\n"
-"    Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n");
-
-/* Changed only during early boot */
 static int force_sysemu_disabled = 0;
 
 static int __init nosysemu_cmd_param(char *str, int* add)
@@ -376,121 +337,6 @@ void __init os_early_checks(void)
 	stop_ptraced_child(pid, 1, 1);
 }
 
-static int __init noprocmm_cmd_param(char *str, int* add)
-{
-	disable_proc_mm = 1;
-	return 0;
-}
-
-__uml_setup("noprocmm", noprocmm_cmd_param,
-"noprocmm\n"
-"    Turns off usage of /proc/mm, even if host supports it.\n"
-"    To support /proc/mm, the host needs to be patched using\n"
-"    the current skas3 patch.\n\n");
-
-static int __init noptracefaultinfo_cmd_param(char *str, int* add)
-{
-	disable_ptrace_faultinfo = 1;
-	return 0;
-}
-
-__uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param,
-"noptracefaultinfo\n"
-"    Turns off usage of PTRACE_FAULTINFO, even if host supports\n"
-"    it. To support PTRACE_FAULTINFO, the host needs to be patched\n"
-"    using the current skas3 patch.\n\n");
-
-static int __init noptraceldt_cmd_param(char *str, int* add)
-{
-	disable_ptrace_ldt = 1;
-	return 0;
-}
-
-__uml_setup("noptraceldt", noptraceldt_cmd_param,
-"noptraceldt\n"
-"    Turns off usage of PTRACE_LDT, even if host supports it.\n"
-"    To support PTRACE_LDT, the host needs to be patched using\n"
-"    the current skas3 patch.\n\n");
-
-static inline void check_skas3_ptrace_faultinfo(void)
-{
-	struct ptrace_faultinfo fi;
-	int pid, n;
-
-	non_fatal("  - PTRACE_FAULTINFO...");
-	pid = start_ptraced_child();
-
-	n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
-	if (n < 0) {
-		if (errno == EIO)
-			non_fatal("not found\n");
-		else
-			perror("not found");
-	} else if (disable_ptrace_faultinfo)
-		non_fatal("found but disabled on command line\n");
-	else {
-		ptrace_faultinfo = 1;
-		non_fatal("found\n");
-	}
-
-	stop_ptraced_child(pid, 1, 1);
-}
-
-static inline void check_skas3_ptrace_ldt(void)
-{
-#ifdef PTRACE_LDT
-	int pid, n;
-	unsigned char ldtbuf[40];
-	struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
-		.func = 2, /* read default ldt */
-		.ptr = ldtbuf,
-		.bytecount = sizeof(ldtbuf)};
-
-	non_fatal("  - PTRACE_LDT...");
-	pid = start_ptraced_child();
-
-	n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
-	if (n < 0) {
-		if (errno == EIO)
-			non_fatal("not found\n");
-		else
-			perror("not found");
-	} else if (disable_ptrace_ldt)
-		non_fatal("found, but use is disabled\n");
-	else {
-		ptrace_ldt = 1;
-		non_fatal("found\n");
-	}
-
-	stop_ptraced_child(pid, 1, 1);
-#endif
-}
-
-static inline void check_skas3_proc_mm(void)
-{
-	non_fatal("  - /proc/mm...");
-	if (access("/proc/mm", W_OK) < 0)
-		perror("not found");
-	else if (disable_proc_mm)
-		non_fatal("found but disabled on command line\n");
-	else {
-		proc_mm = 1;
-		non_fatal("found\n");
-	}
-}
-
-void can_do_skas(void)
-{
-	non_fatal("Checking for the skas3 patch in the host:\n");
-
-	check_skas3_proc_mm();
-	check_skas3_ptrace_faultinfo();
-	check_skas3_ptrace_ldt();
-
-	if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
-		skas_needs_stub = 1;
-}
-
 int __init parse_iomem(char *str, int *add)
 {
 	struct iomem_region *new;
diff --git a/arch/um/sys-ia64/sysdep/skas_ptrace.h b/arch/um/sys-ia64/sysdep/skas_ptrace.h
deleted file mode 100644
index 25a38e715702..000000000000
--- a/arch/um/sys-ia64/sysdep/skas_ptrace.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_IA64_SKAS_PTRACE_H
-#define __SYSDEP_IA64_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff --git a/arch/um/sys-ppc/shared/sysdep/skas_ptrace.h b/arch/um/sys-ppc/shared/sysdep/skas_ptrace.h
deleted file mode 100644
index d9fbbac10de0..000000000000
--- a/arch/um/sys-ppc/shared/sysdep/skas_ptrace.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_PPC_SKAS_PTRACE_H
-#define __SYSDEP_PPC_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 25d2c6f7325e..376e4f7def27 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -26,7 +26,7 @@ config X86
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select HAVE_AOUT if X86_32
 	select HAVE_UNSTABLE_SCHED_CLOCK
-	select ARCH_SUPPORTS_NUMA_BALANCING
+	select ARCH_SUPPORTS_NUMA_BALANCING if X86_64
 	select ARCH_SUPPORTS_INT128 if X86_64
 	select ARCH_WANTS_PROT_NUMA_PROT_NONE
 	select HAVE_IDE
@@ -96,6 +96,7 @@ config X86
 	select IRQ_FORCED_THREADING
 	select HAVE_BPF_JIT if X86_64
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+	select ARCH_HAS_SG_CHAIN
 	select CLKEVT_I8253
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_IOMAP
@@ -533,7 +534,7 @@ config X86_32_IRIS
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
-	prompt "Single-depth WCHAN output"
+	prompt "Single-depth WCHAN output" if !LTO && !FRAME_POINTER
 	depends on X86
 	---help---
 	  Calculate simpler /proc/<PID>/wchan values. If this option
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 602f57e590b5..d1b7c377a234 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -250,8 +250,8 @@ archclean:
 PHONY += kvmconfig
 kvmconfig:
 	$(if $(wildcard $(objtree)/.config),, $(error You need an existing .config for this target))
-	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m -O $(objtree) $(objtree)/.config arch/x86/configs/kvm_guest.config
-	$(Q)yes "" | $(MAKE) oldconfig
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m -O $(objtree) $(objtree)/.config $(srctree)/arch/x86/configs/kvm_guest.config
+	$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
 
 define archhelp
   echo  '* bzImage      - Compressed kernel image (arch/x86/boot/bzImage)'
diff --git a/arch/x86/crypto/ghash-clmulni-intel_asm.S b/arch/x86/crypto/ghash-clmulni-intel_asm.S
index 185fad49d86f..5d1e0075ac24 100644
--- a/arch/x86/crypto/ghash-clmulni-intel_asm.S
+++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S
@@ -92,7 +92,7 @@ __clmul_gf128mul_ble:
 	ret
 ENDPROC(__clmul_gf128mul_ble)
 
-/* void clmul_ghash_mul(char *dst, const be128 *shash) */
+/* void clmul_ghash_mul(char *dst, const u128 *shash) */
 ENTRY(clmul_ghash_mul)
 	movups (%rdi), DATA
 	movups (%rsi), SHASH
@@ -106,7 +106,7 @@ ENDPROC(clmul_ghash_mul)
 
 /*
  * void clmul_ghash_update(char *dst, const char *src, unsigned int srclen,
- *			   const be128 *shash);
+ *			   const u128 *shash);
  */
 ENTRY(clmul_ghash_update)
 	cmp $16, %rdx
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c
index d785cf2c529c..88bb7ba8b175 100644
--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c
+++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c
@@ -25,17 +25,17 @@
 #define GHASH_BLOCK_SIZE	16
 #define GHASH_DIGEST_SIZE	16
 
-void clmul_ghash_mul(char *dst, const be128 *shash);
+void clmul_ghash_mul(char *dst, const u128 *shash);
 
 void clmul_ghash_update(char *dst, const char *src, unsigned int srclen,
-			const be128 *shash);
+			const u128 *shash);
 
 struct ghash_async_ctx {
 	struct cryptd_ahash *cryptd_tfm;
 };
 
 struct ghash_ctx {
-	be128 shash;
+	u128 shash;
 };
 
 struct ghash_desc_ctx {
@@ -68,11 +68,11 @@ static int ghash_setkey(struct crypto_shash *tfm,
 	a = be64_to_cpu(x->a);
 	b = be64_to_cpu(x->b);
 
-	ctx->shash.a = (__be64)((b << 1) | (a >> 63));
-	ctx->shash.b = (__be64)((a << 1) | (b >> 63));
+	ctx->shash.a = (b << 1) | (a >> 63);
+	ctx->shash.b = (a << 1) | (b >> 63);
 
 	if (a >> 63)
-		ctx->shash.b ^= cpu_to_be64(0xc2);
+		ctx->shash.b ^= ((u64)0xc2) << 56;
 
 	return 0;
 }
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 3ca9762e1649..3bf000fab0ae 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -5,6 +5,7 @@ genhdr-y += unistd_64.h
 genhdr-y += unistd_x32.h
 
 generic-y += clkdev.h
-generic-y += early_ioremap.h
 generic-y += cputime.h
+generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
+generic-y += scatterlist.h
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index a307b7530e54..4615906d83df 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -190,8 +190,8 @@ extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void);
 #define trace_interrupt interrupt
 #endif
 
-#define VECTOR_UNDEFINED	-1
-#define VECTOR_RETRIGGERED	-2
+#define VECTOR_UNDEFINED	(-1)
+#define VECTOR_RETRIGGERED	(-2)
 
 typedef int vector_irq_t[NR_VECTORS];
 DECLARE_PER_CPU(vector_irq_t, vector_irq);
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index fcaf9c961265..7de069afb382 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -60,7 +60,7 @@
 			  | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE     \
 			  | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_PCIDE \
 			  | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \
-			  | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
+			  | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE | X86_CR4_SMAP))
 
 #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
 
diff --git a/arch/x86/include/asm/scatterlist.h b/arch/x86/include/asm/scatterlist.h
deleted file mode 100644
index 4240878b9d76..000000000000
--- a/arch/x86/include/asm/scatterlist.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _ASM_X86_SCATTERLIST_H
-#define _ASM_X86_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_X86_SCATTERLIST_H */
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h
index 35e67a457182..31eab867e6d3 100644
--- a/arch/x86/include/asm/signal.h
+++ b/arch/x86/include/asm/signal.h
@@ -92,12 +92,6 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
 	 ? __const_sigismember((set), (sig))	\
 	 : __gen_sigismember((set), (sig)))
 
-static inline int sigfindinword(unsigned long word)
-{
-	asm("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
-	return word;
-}
-
 struct pt_regs;
 
 #else /* __i386__ */
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index a30836c8ac4d..c63e925fd6b7 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -5,7 +5,7 @@
  *
  * SGI UV architectural definitions
  *
- * Copyright (C) 2007-2013 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_X86_UV_UV_HUB_H
@@ -204,16 +204,6 @@ static inline int is_uvx_hub(void)
 	return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
 }
 
-static inline int is_uv2_1_hub(void)
-{
-	return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE;
-}
-
-static inline int is_uv2_2_hub(void)
-{
-	return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE + 1;
-}
-
 union uvh_apicid {
     unsigned long       v;
     struct uvh_apicid_s {
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h
index e42249bcf7e1..ddd8db6b6e70 100644
--- a/arch/x86/include/asm/uv/uv_mmrs.h
+++ b/arch/x86/include/asm/uv/uv_mmrs.h
@@ -5,7 +5,7 @@
  *
  * SGI UV MMR definitions
  *
- * Copyright (C) 2007-2013 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_X86_UV_UV_MMRS_H
@@ -2803,6 +2803,46 @@ union uv1h_lb_target_physical_apic_id_mask_u {
 };
 
 /* ========================================================================= */
+/*                          UV3H_GR0_GAM_GR_CONFIG                           */
+/* ========================================================================= */
+#define UV3H_GR0_GAM_GR_CONFIG				0xc00028UL
+
+#define UV3H_GR0_GAM_GR_CONFIG_M_SKT_SHFT		0
+#define UV3H_GR0_GAM_GR_CONFIG_SUBSPACE_SHFT		10
+#define UV3H_GR0_GAM_GR_CONFIG_M_SKT_MASK		0x000000000000003fUL
+#define UV3H_GR0_GAM_GR_CONFIG_SUBSPACE_MASK		0x0000000000000400UL
+
+union uv3h_gr0_gam_gr_config_u {
+	unsigned long	v;
+	struct uv3h_gr0_gam_gr_config_s {
+		unsigned long	m_skt:6;			/* RW */
+		unsigned long	undef_6_9:4;			/* Undefined */
+		unsigned long	subspace:1;			/* RW */
+		unsigned long	reserved:53;
+	} s3;
+};
+
+/* ========================================================================= */
+/*                          UV3H_GR1_GAM_GR_CONFIG                           */
+/* ========================================================================= */
+#define UV3H_GR1_GAM_GR_CONFIG				0x1000028UL
+
+#define UV3H_GR1_GAM_GR_CONFIG_M_SKT_SHFT		0
+#define UV3H_GR1_GAM_GR_CONFIG_SUBSPACE_SHFT		10
+#define UV3H_GR1_GAM_GR_CONFIG_M_SKT_MASK		0x000000000000003fUL
+#define UV3H_GR1_GAM_GR_CONFIG_SUBSPACE_MASK		0x0000000000000400UL
+
+union uv3h_gr1_gam_gr_config_u {
+	unsigned long	v;
+	struct uv3h_gr1_gam_gr_config_s {
+		unsigned long	m_skt:6;			/* RW */
+		unsigned long	undef_6_9:4;			/* Undefined */
+		unsigned long	subspace:1;			/* RW */
+		unsigned long	reserved:53;
+	} s3;
+};
+
+/* ========================================================================= */
 /*                   UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR                   */
 /* ========================================================================= */
 #define UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR		0x1603000UL
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 7834389ba5be..293b41df54ef 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -5,7 +5,7 @@
  *
  * SGI UV APIC functions (note: not an Intel compatible APIC)
  *
- * Copyright (C) 2007-2013 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved.
  */
 #include <linux/cpumask.h>
 #include <linux/hardirq.h>
@@ -440,6 +440,20 @@ static __initdata struct redir_addr redir_addrs[] = {
 	{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR, UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR},
 };
 
+static unsigned char get_n_lshift(int m_val)
+{
+	union uv3h_gr0_gam_gr_config_u m_gr_config;
+
+	if (is_uv1_hub())
+		return m_val;
+
+	if (is_uv2_hub())
+		return m_val == 40 ? 40 : 39;
+
+	m_gr_config.v = uv_read_local_mmr(UV3H_GR0_GAM_GR_CONFIG);
+	return m_gr_config.s3.m_skt;
+}
+
 static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
 {
 	union uvh_rh_gam_alias210_overlay_config_2_mmr_u alias;
@@ -849,6 +863,7 @@ void __init uv_system_init(void)
 	int gnode_extra, min_pnode = 999999, max_pnode = -1;
 	unsigned long mmr_base, present, paddr;
 	unsigned short pnode_mask;
+	unsigned char n_lshift;
 	char *hub = (is_uv1_hub() ? "UV1" :
 		    (is_uv2_hub() ? "UV2" :
 				    "UV3"));
@@ -860,6 +875,7 @@ void __init uv_system_init(void)
 	m_val = m_n_config.s.m_skt;
 	n_val = m_n_config.s.n_skt;
 	pnode_mask = (1 << n_val) - 1;
+	n_lshift = get_n_lshift(m_val);
 	mmr_base =
 	    uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
 	    ~UV_MMR_ENABLE;
@@ -867,8 +883,9 @@ void __init uv_system_init(void)
 	node_id.v = uv_read_local_mmr(UVH_NODE_ID);
 	gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1;
 	gnode_upper = ((unsigned long)gnode_extra  << m_val);
-	pr_info("UV: N:%d M:%d pnode_mask:0x%x gnode_upper/extra:0x%lx/0x%x\n",
-			n_val, m_val, pnode_mask, gnode_upper, gnode_extra);
+	pr_info("UV: N:%d M:%d pnode_mask:0x%x gnode_upper/extra:0x%lx/0x%x n_lshift 0x%x\n",
+			n_val, m_val, pnode_mask, gnode_upper, gnode_extra,
+			n_lshift);
 
 	pr_info("UV: global MMR base 0x%lx\n", mmr_base);
 
@@ -935,8 +952,7 @@ void __init uv_system_init(void)
 		uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
 
 		uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
-		uv_cpu_hub_info(cpu)->n_lshift = is_uv2_1_hub() ?
-				(m_val == 40 ? 40 : 39) : m_val;
+		uv_cpu_hub_info(cpu)->n_lshift = n_lshift;
 
 		pnode = uv_apicid_to_pnode(apicid);
 		blade = boot_pnode_to_blade(pnode);
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 76f98fe5b35c..a450373e8e91 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -132,15 +132,6 @@ static void __init ms_hyperv_init_platform(void)
 		lapic_timer_frequency = hv_lapic_frequency;
 		printk(KERN_INFO "HyperV: LAPIC Timer Frequency: %#x\n",
 				lapic_timer_frequency);
-
-		/*
-		 * On Hyper-V, when we are booting off an EFI firmware stack,
-		 * we do not have many legacy devices including PIC, PIT etc.
-		 */
-		if (efi_enabled(EFI_BOOT)) {
-			printk(KERN_INFO "HyperV: Using null_legacy_pic\n");
-			legacy_pic = &null_legacy_pic;
-		}
 	}
 #endif
 
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
index 059218ed5208..4b9a9e9466bd 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
@@ -59,7 +59,7 @@
 #define INTEL_RAPL_PKG		0x2	/* pseudo-encoding */
 #define RAPL_IDX_RAM_NRG_STAT	2	/* DRAM */
 #define INTEL_RAPL_RAM		0x3	/* pseudo-encoding */
-#define RAPL_IDX_PP1_NRG_STAT	3	/* DRAM */
+#define RAPL_IDX_PP1_NRG_STAT	3	/* gpu */
 #define INTEL_RAPL_PP1		0x4	/* pseudo-encoding */
 
 /* Clients have PP0, PKG */
@@ -72,6 +72,12 @@
 			 1<<RAPL_IDX_PKG_NRG_STAT|\
 			 1<<RAPL_IDX_RAM_NRG_STAT)
 
+/* Servers have PP0, PKG, RAM, PP1 */
+#define RAPL_IDX_HSW	(1<<RAPL_IDX_PP0_NRG_STAT|\
+			 1<<RAPL_IDX_PKG_NRG_STAT|\
+			 1<<RAPL_IDX_RAM_NRG_STAT|\
+			 1<<RAPL_IDX_PP1_NRG_STAT)
+
 /*
  * event code: LSB 8 bits, passed in attr->config
  * any other bit is reserved
@@ -425,6 +431,24 @@ static struct attribute *rapl_events_cln_attr[] = {
 	NULL,
 };
 
+static struct attribute *rapl_events_hsw_attr[] = {
+	EVENT_PTR(rapl_cores),
+	EVENT_PTR(rapl_pkg),
+	EVENT_PTR(rapl_gpu),
+	EVENT_PTR(rapl_ram),
+
+	EVENT_PTR(rapl_cores_unit),
+	EVENT_PTR(rapl_pkg_unit),
+	EVENT_PTR(rapl_gpu_unit),
+	EVENT_PTR(rapl_ram_unit),
+
+	EVENT_PTR(rapl_cores_scale),
+	EVENT_PTR(rapl_pkg_scale),
+	EVENT_PTR(rapl_gpu_scale),
+	EVENT_PTR(rapl_ram_scale),
+	NULL,
+};
+
 static struct attribute_group rapl_pmu_events_group = {
 	.name = "events",
 	.attrs = NULL, /* patched at runtime */
@@ -631,11 +655,14 @@ static int __init rapl_pmu_init(void)
 	switch (boot_cpu_data.x86_model) {
 	case 42: /* Sandy Bridge */
 	case 58: /* Ivy Bridge */
-	case 60: /* Haswell */
-	case 69: /* Haswell-Celeron */
 		rapl_cntr_mask = RAPL_IDX_CLN;
 		rapl_pmu_events_group.attrs = rapl_events_cln_attr;
 		break;
+	case 60: /* Haswell */
+	case 69: /* Haswell-Celeron */
+		rapl_cntr_mask = RAPL_IDX_HSW;
+		rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
+		break;
 	case 45: /* Sandy Bridge-EP */
 	case 62: /* IvyTown */
 		rapl_cntr_mask = RAPL_IDX_SRV;
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index b0cc3809723d..6e2537c32190 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -240,7 +240,7 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s
 	return base;
 }
 
-#define KB(x)	((x) * 1024)
+#define KB(x)	((x) * 1024UL)
 #define MB(x)	(KB (KB (x)))
 #define GB(x)	(MB (KB (x)))
 
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 2e977b5d61dd..8af817105e29 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -299,13 +299,31 @@ static void unmask_8259A(void)
 static void init_8259A(int auto_eoi)
 {
 	unsigned long flags;
+	unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
+	unsigned char new_val;
 
 	i8259A_auto_eoi = auto_eoi;
 
 	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
-	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
+	/*
+	 * Check to see if we have a PIC.
+	 * Mask all except the cascade and read
+	 * back the value we just wrote. If we don't
+	 * have a PIC, we will read 0xff as opposed to the
+	 * value we wrote.
+	 */
 	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-2 */
+	outb(probe_val, PIC_MASTER_IMR);
+	new_val = inb(PIC_MASTER_IMR);
+	if (new_val != probe_val) {
+		printk(KERN_INFO "Using NULL legacy PIC\n");
+		legacy_pic = &null_legacy_pic;
+		raw_spin_unlock_irqrestore(&i8259A_lock, flags);
+		return;
+	}
+
+	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
 
 	/*
 	 * outb_pic - this has to work on a wide range of PC hardware.
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 654b46574b91..3399d3a99730 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -114,8 +114,8 @@ EXPORT_SYMBOL(machine_real_restart);
  */
 static int __init set_pci_reboot(const struct dmi_system_id *d)
 {
-	if (reboot_type != BOOT_CF9) {
-		reboot_type = BOOT_CF9;
+	if (reboot_type != BOOT_CF9_FORCE) {
+		reboot_type = BOOT_CF9_FORCE;
 		pr_info("%s series board detected. Selecting %s-method for reboots.\n",
 			d->ident, "PCI");
 	}
@@ -458,20 +458,23 @@ void __attribute__((weak)) mach_reboot_fixups(void)
 }
 
 /*
- * Windows compatible x86 hardware expects the following on reboot:
+ * To the best of our knowledge Windows compatible x86 hardware expects
+ * the following on reboot:
  *
  * 1) If the FADT has the ACPI reboot register flag set, try it
  * 2) If still alive, write to the keyboard controller
  * 3) If still alive, write to the ACPI reboot register again
  * 4) If still alive, write to the keyboard controller again
  * 5) If still alive, call the EFI runtime service to reboot
- * 6) If still alive, write to the PCI IO port 0xCF9 to reboot
- * 7) If still alive, inform BIOS to do a proper reboot
+ * 6) If no EFI runtime service, call the BIOS to do a reboot
  *
- * If the machine is still alive at this stage, it gives up. We default to
- * following the same pattern, except that if we're still alive after (7) we'll
- * try to force a triple fault and then cycle between hitting the keyboard
- * controller and doing that
+ * We default to following the same pattern. We also have
+ * two other reboot methods: 'triple fault' and 'PCI', which
+ * can be triggered via the reboot= kernel boot option or
+ * via quirks.
+ *
+ * This means that this function can never return, it can misbehave
+ * by not rebooting properly and hanging.
  */
 static void native_machine_emergency_restart(void)
 {
@@ -492,6 +495,11 @@ static void native_machine_emergency_restart(void)
 	for (;;) {
 		/* Could also try the reset bit in the Hammer NB */
 		switch (reboot_type) {
+		case BOOT_ACPI:
+			acpi_reboot();
+			reboot_type = BOOT_KBD;
+			break;
+
 		case BOOT_KBD:
 			mach_reboot_fixups(); /* For board specific fixups */
 
@@ -509,43 +517,29 @@ static void native_machine_emergency_restart(void)
 			}
 			break;
 
-		case BOOT_TRIPLE:
-			load_idt(&no_idt);
-			__asm__ __volatile__("int3");
-
-			/* We're probably dead after this, but... */
-			reboot_type = BOOT_KBD;
-			break;
-
-		case BOOT_BIOS:
-			machine_real_restart(MRR_BIOS);
-
-			/* We're probably dead after this, but... */
-			reboot_type = BOOT_TRIPLE;
-			break;
-
-		case BOOT_ACPI:
-			acpi_reboot();
-			reboot_type = BOOT_KBD;
-			break;
-
 		case BOOT_EFI:
 			if (efi_enabled(EFI_RUNTIME_SERVICES))
 				efi.reset_system(reboot_mode == REBOOT_WARM ?
 						 EFI_RESET_WARM :
 						 EFI_RESET_COLD,
 						 EFI_SUCCESS, 0, NULL);
-			reboot_type = BOOT_CF9_COND;
+			reboot_type = BOOT_BIOS;
+			break;
+
+		case BOOT_BIOS:
+			machine_real_restart(MRR_BIOS);
+
+			/* We're probably dead after this, but... */
+			reboot_type = BOOT_CF9_SAFE;
 			break;
 
-		case BOOT_CF9:
+		case BOOT_CF9_FORCE:
 			port_cf9_safe = true;
 			/* Fall through */
 
-		case BOOT_CF9_COND:
+		case BOOT_CF9_SAFE:
 			if (port_cf9_safe) {
-				u8 reboot_code = reboot_mode == REBOOT_WARM ?
-					0x06 : 0x0E;
+				u8 reboot_code = reboot_mode == REBOOT_WARM ?  0x06 : 0x0E;
 				u8 cf9 = inb(0xcf9) & ~reboot_code;
 				outb(cf9|2, 0xcf9); /* Request hard reset */
 				udelay(50);
@@ -553,7 +547,15 @@ static void native_machine_emergency_restart(void)
 				outb(cf9|reboot_code, 0xcf9);
 				udelay(50);
 			}
-			reboot_type = BOOT_BIOS;
+			reboot_type = BOOT_TRIPLE;
+			break;
+
+		case BOOT_TRIPLE:
+			load_idt(&no_idt);
+			__asm__ __volatile__("int3");
+
+			/* We're probably dead after this, but... */
+			reboot_type = BOOT_KBD;
 			break;
 		}
 	}
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index bea60671ef8a..f47a104a749c 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -308,7 +308,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 	const u32 kvm_supported_word9_x86_features =
 		F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) |
 		F(BMI2) | F(ERMS) | f_invpcid | F(RTM) | f_mpx | F(RDSEED) |
-		F(ADX);
+		F(ADX) | F(SMAP);
 
 	/* all calls to cpuid_count() should be made on the same cpu */
 	get_cpu();
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index a2a1bb7ed8c1..eeecbed26ac7 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -48,6 +48,14 @@ static inline bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu)
 	return best && (best->ebx & bit(X86_FEATURE_SMEP));
 }
 
+static inline bool guest_cpuid_has_smap(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 7, 0);
+	return best && (best->ebx & bit(X86_FEATURE_SMAP));
+}
+
 static inline bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index f5704d9e5ddc..813d31038b93 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3601,20 +3601,27 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
 	}
 }
 
-static void update_permission_bitmask(struct kvm_vcpu *vcpu,
+void update_permission_bitmask(struct kvm_vcpu *vcpu,
 		struct kvm_mmu *mmu, bool ept)
 {
 	unsigned bit, byte, pfec;
 	u8 map;
-	bool fault, x, w, u, wf, uf, ff, smep;
+	bool fault, x, w, u, wf, uf, ff, smapf, cr4_smap, cr4_smep, smap = 0;
 
-	smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
+	cr4_smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
+	cr4_smap = kvm_read_cr4_bits(vcpu, X86_CR4_SMAP);
 	for (byte = 0; byte < ARRAY_SIZE(mmu->permissions); ++byte) {
 		pfec = byte << 1;
 		map = 0;
 		wf = pfec & PFERR_WRITE_MASK;
 		uf = pfec & PFERR_USER_MASK;
 		ff = pfec & PFERR_FETCH_MASK;
+		/*
+		 * PFERR_RSVD_MASK bit is set in PFEC if the access is not
+		 * subject to SMAP restrictions, and cleared otherwise. The
+		 * bit is only meaningful if the SMAP bit is set in CR4.
+		 */
+		smapf = !(pfec & PFERR_RSVD_MASK);
 		for (bit = 0; bit < 8; ++bit) {
 			x = bit & ACC_EXEC_MASK;
 			w = bit & ACC_WRITE_MASK;
@@ -3626,12 +3633,33 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
 				/* Allow supervisor writes if !cr0.wp */
 				w |= !is_write_protection(vcpu) && !uf;
 				/* Disallow supervisor fetches of user code if cr4.smep */
-				x &= !(smep && u && !uf);
+				x &= !(cr4_smep && u && !uf);
+
+				/*
+				 * SMAP:kernel-mode data accesses from user-mode
+				 * mappings should fault. A fault is considered
+				 * as a SMAP violation if all of the following
+				 * conditions are ture:
+				 *   - X86_CR4_SMAP is set in CR4
+				 *   - An user page is accessed
+				 *   - Page fault in kernel mode
+				 *   - if CPL = 3 or X86_EFLAGS_AC is clear
+				 *
+				 *   Here, we cover the first three conditions.
+				 *   The fourth is computed dynamically in
+				 *   permission_fault() and is in smapf.
+				 *
+				 *   Also, SMAP does not affect instruction
+				 *   fetches, add the !ff check here to make it
+				 *   clearer.
+				 */
+				smap = cr4_smap && u && !uf && !ff;
 			} else
 				/* Not really needed: no U/S accesses on ept  */
 				u = 1;
 
-			fault = (ff && !x) || (uf && !u) || (wf && !w);
+			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
+				(smapf && smap);
 			map |= fault << bit;
 		}
 		mmu->permissions[byte] = map;
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 292615274358..3842e70bdb7c 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -44,11 +44,17 @@
 #define PT_DIRECTORY_LEVEL 2
 #define PT_PAGE_TABLE_LEVEL 1
 
-#define PFERR_PRESENT_MASK (1U << 0)
-#define PFERR_WRITE_MASK (1U << 1)
-#define PFERR_USER_MASK (1U << 2)
-#define PFERR_RSVD_MASK (1U << 3)
-#define PFERR_FETCH_MASK (1U << 4)
+#define PFERR_PRESENT_BIT 0
+#define PFERR_WRITE_BIT 1
+#define PFERR_USER_BIT 2
+#define PFERR_RSVD_BIT 3
+#define PFERR_FETCH_BIT 4
+
+#define PFERR_PRESENT_MASK (1U << PFERR_PRESENT_BIT)
+#define PFERR_WRITE_MASK (1U << PFERR_WRITE_BIT)
+#define PFERR_USER_MASK (1U << PFERR_USER_BIT)
+#define PFERR_RSVD_MASK (1U << PFERR_RSVD_BIT)
+#define PFERR_FETCH_MASK (1U << PFERR_FETCH_BIT)
 
 int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
 void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask);
@@ -73,6 +79,8 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct);
 void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
 void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context,
 		bool execonly);
+void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+		bool ept);
 
 static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
 {
@@ -110,10 +118,30 @@ static inline bool is_write_protection(struct kvm_vcpu *vcpu)
  * Will a fault with a given page-fault error code (pfec) cause a permission
  * fault with the given access (in ACC_* format)?
  */
-static inline bool permission_fault(struct kvm_mmu *mmu, unsigned pte_access,
-				    unsigned pfec)
+static inline bool permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+				    unsigned pte_access, unsigned pfec)
 {
-	return (mmu->permissions[pfec >> 1] >> pte_access) & 1;
+	int cpl = kvm_x86_ops->get_cpl(vcpu);
+	unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
+
+	/*
+	 * If CPL < 3, SMAP prevention are disabled if EFLAGS.AC = 1.
+	 *
+	 * If CPL = 3, SMAP applies to all supervisor-mode data accesses
+	 * (these are implicit supervisor accesses) regardless of the value
+	 * of EFLAGS.AC.
+	 *
+	 * This computes (cpl < 3) && (rflags & X86_EFLAGS_AC), leaving
+	 * the result in X86_EFLAGS_AC. We then insert it in place of
+	 * the PFERR_RSVD_MASK bit; this bit will always be zero in pfec,
+	 * but it will be one in index if SMAP checks are being overridden.
+	 * It is important to keep this branchless.
+	 */
+	unsigned long smap = (cpl - 3) & (rflags & X86_EFLAGS_AC);
+	int index = (pfec >> 1) +
+		    (smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1));
+
+	return (mmu->permissions[index] >> pte_access) & 1;
 }
 
 void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index b1e6c1bf68d3..123efd3ec29f 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -353,7 +353,7 @@ retry_walk:
 		walker->ptes[walker->level - 1] = pte;
 	} while (!is_last_gpte(mmu, walker->level, pte));
 
-	if (unlikely(permission_fault(mmu, pte_access, access))) {
+	if (unlikely(permission_fault(vcpu, mmu, pte_access, access))) {
 		errcode |= PFERR_PRESENT_MASK;
 		goto error;
 	}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1320e0f8e611..1f68c5831924 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3484,13 +3484,14 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 			hw_cr4 &= ~X86_CR4_PAE;
 			hw_cr4 |= X86_CR4_PSE;
 			/*
-			 * SMEP is disabled if CPU is in non-paging mode in
-			 * hardware. However KVM always uses paging mode to
+			 * SMEP/SMAP is disabled if CPU is in non-paging mode
+			 * in hardware. However KVM always uses paging mode to
 			 * emulate guest non-paging mode with TDP.
-			 * To emulate this behavior, SMEP needs to be manually
-			 * disabled when guest switches to non-paging mode.
+			 * To emulate this behavior, SMEP/SMAP needs to be
+			 * manually disabled when guest switches to non-paging
+			 * mode.
 			 */
-			hw_cr4 &= ~X86_CR4_SMEP;
+			hw_cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP);
 		} else if (!(cr4 & X86_CR4_PAE)) {
 			hw_cr4 &= ~X86_CR4_PAE;
 		}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9d1b5cd4d34c..8b8fc0b792ba 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -652,6 +652,9 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 	if (!guest_cpuid_has_smep(vcpu) && (cr4 & X86_CR4_SMEP))
 		return 1;
 
+	if (!guest_cpuid_has_smap(vcpu) && (cr4 & X86_CR4_SMAP))
+		return 1;
+
 	if (!guest_cpuid_has_fsgsbase(vcpu) && (cr4 & X86_CR4_FSGSBASE))
 		return 1;
 
@@ -680,6 +683,9 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 	    (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE)))
 		kvm_mmu_reset_context(vcpu);
 
+	if ((cr4 ^ old_cr4) & X86_CR4_SMAP)
+		update_permission_bitmask(vcpu, vcpu->arch.walk_mmu, false);
+
 	if ((cr4 ^ old_cr4) & X86_CR4_OSXSAVE)
 		kvm_update_cpuid(vcpu);
 
@@ -1117,7 +1123,6 @@ static inline u64 get_kernel_ns(void)
 {
 	struct timespec ts;
 
-	WARN_ON(preemptible());
 	ktime_get_ts(&ts);
 	monotonic_to_bootbased(&ts);
 	return timespec_to_ns(&ts);
@@ -4164,7 +4169,8 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
 		| (write ? PFERR_WRITE_MASK : 0);
 
 	if (vcpu_match_mmio_gva(vcpu, gva)
-	    && !permission_fault(vcpu->arch.walk_mmu, vcpu->arch.access, access)) {
+	    && !permission_fault(vcpu, vcpu->arch.walk_mmu,
+				 vcpu->arch.access, access)) {
 		*gpa = vcpu->arch.mmio_gfn << PAGE_SHIFT |
 					(gva & (PAGE_SIZE - 1));
 		trace_vcpu_match_mmio(gva, *gpa, write, false);
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index c96314abd144..0004ac72dbdd 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -399,13 +399,20 @@ int pmdp_test_and_clear_young(struct vm_area_struct *vma,
 int ptep_clear_flush_young(struct vm_area_struct *vma,
 			   unsigned long address, pte_t *ptep)
 {
-	int young;
-
-	young = ptep_test_and_clear_young(vma, address, ptep);
-	if (young)
-		flush_tlb_page(vma, address);
-
-	return young;
+	/*
+	 * On x86 CPUs, clearing the accessed bit without a TLB flush
+	 * doesn't cause data corruption. [ It could cause incorrect
+	 * page aging and the (mistaken) reclaim of hot pages, but the
+	 * chance of that should be relatively low. ]
+	 *
+	 * So as a performance optimization don't flush the TLB when
+	 * clearing the accessed bit, it will eventually be flushed by
+	 * a context switch or a VM operation anyway. [ In the rare
+	 * event of it not getting flushed for a long time the delay
+	 * shouldn't really matter because there's no real memory
+	 * pressure for swapout to react to. ]
+	 */
+	return ptep_test_and_clear_young(vma, address, ptep);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
index 3497f14e4dea..7c0d7be176a5 100644
--- a/arch/x86/realmode/rm/Makefile
+++ b/arch/x86/realmode/rm/Makefile
@@ -52,8 +52,9 @@ $(obj)/realmode.elf: $(obj)/realmode.lds $(REALMODE_OBJS) FORCE
 OBJCOPYFLAGS_realmode.bin := -O binary
 
 targets += realmode.bin
-$(obj)/realmode.bin: $(obj)/realmode.elf $(obj)/realmode.relocs
+$(obj)/realmode.bin: $(obj)/realmode.elf $(obj)/realmode.relocs FORCE
 	$(call if_changed,objcopy)
+	@:
 
 quiet_cmd_relocs = RELOCS  $@
       cmd_relocs = arch/x86/tools/relocs --realmode $< > $@
diff --git a/arch/x86/syscalls/Makefile b/arch/x86/syscalls/Makefile
index f325af26107c..3323c2745248 100644
--- a/arch/x86/syscalls/Makefile
+++ b/arch/x86/syscalls/Makefile
@@ -54,5 +54,7 @@ syshdr-$(CONFIG_X86_64)		+= syscalls_64.h
 
 targets	+= $(uapisyshdr-y) $(syshdr-y)
 
+PHONY += all
 all: $(addprefix $(uapi)/,$(uapisyshdr-y))
 all: $(addprefix $(out)/,$(syshdr-y))
+	@:
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index 96bc506ac6de..d6b867921612 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -359,3 +359,4 @@
 350	i386	finit_module		sys_finit_module
 351	i386	sched_setattr		sys_sched_setattr
 352	i386	sched_getattr		sys_sched_getattr
+353	i386	renameat2		sys_renameat2
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile
index e8120346903b..604a37efd4d5 100644
--- a/arch/x86/tools/Makefile
+++ b/arch/x86/tools/Makefile
@@ -40,4 +40,6 @@ $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/ina
 HOST_EXTRACFLAGS += -I$(srctree)/tools/include
 hostprogs-y	+= relocs
 relocs-objs     := relocs_32.o relocs_64.o relocs_common.o
+PHONY += relocs
 relocs: $(obj)/relocs
+	@:
diff --git a/arch/x86/um/ldt.c b/arch/x86/um/ldt.c
index 8e08176f0bcb..5c0b711d2433 100644
--- a/arch/x86/um/ldt.c
+++ b/arch/x86/um/ldt.c
@@ -8,9 +8,7 @@
 #include <linux/slab.h>
 #include <asm/unistd.h>
 #include <os.h>
-#include <proc_mm.h>
 #include <skas.h>
-#include <skas_ptrace.h>
 #include <sysdep/tls.h>
 
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
@@ -19,105 +17,20 @@ static long write_ldt_entry(struct mm_id *mm_idp, int func,
 		     struct user_desc *desc, void **addr, int done)
 {
 	long res;
-
-	if (proc_mm) {
-		/*
-		 * This is a special handling for the case, that the mm to
-		 * modify isn't current->active_mm.
-		 * If this is called directly by modify_ldt,
-		 *     (current->active_mm->context.skas.u == mm_idp)
-		 * will be true. So no call to __switch_mm(mm_idp) is done.
-		 * If this is called in case of init_new_ldt or PTRACE_LDT,
-		 * mm_idp won't belong to current->active_mm, but child->mm.
-		 * So we need to switch child's mm into our userspace, then
-		 * later switch back.
-		 *
-		 * Note: I'm unsure: should interrupts be disabled here?
-		 */
-		if (!current->active_mm || current->active_mm == &init_mm ||
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(mm_idp);
-	}
-
-	if (ptrace_ldt) {
-		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
-			.func = func,
-			.ptr = desc,
-			.bytecount = sizeof(*desc)};
-		u32 cpu;
-		int pid;
-
-		if (!proc_mm)
-			pid = mm_idp->u.pid;
-		else {
-			cpu = get_cpu();
-			pid = userspace_pid[cpu];
-		}
-
-		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
-
-		if (proc_mm)
-			put_cpu();
-	}
-	else {
-		void *stub_addr;
-		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
-					(sizeof(*desc) + sizeof(long) - 1) &
-					    ~(sizeof(long) - 1),
-					addr, &stub_addr);
-		if (!res) {
-			unsigned long args[] = { func,
-						 (unsigned long)stub_addr,
-						 sizeof(*desc),
-						 0, 0, 0 };
-			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
-					       0, addr, done);
-		}
+	void *stub_addr;
+	res = syscall_stub_data(mm_idp, (unsigned long *)desc,
+				(sizeof(*desc) + sizeof(long) - 1) &
+				    ~(sizeof(long) - 1),
+				addr, &stub_addr);
+	if (!res) {
+		unsigned long args[] = { func,
+					 (unsigned long)stub_addr,
+					 sizeof(*desc),
+					 0, 0, 0 };
+		res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
+				       0, addr, done);
 	}
 
-	if (proc_mm) {
-		/*
-		 * This is the second part of special handling, that makes
-		 * PTRACE_LDT possible to implement.
-		 */
-		if (current->active_mm && current->active_mm != &init_mm &&
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(&current->active_mm->context.id);
-	}
-
-	return res;
-}
-
-static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
-{
-	int res, n;
-	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
-			.func = 0,
-			.bytecount = bytecount,
-			.ptr = kmalloc(bytecount, GFP_KERNEL)};
-	u32 cpu;
-
-	if (ptrace_ldt.ptr == NULL)
-		return -ENOMEM;
-
-	/*
-	 * This is called from sys_modify_ldt only, so userspace_pid gives
-	 * us the right number
-	 */
-
-	cpu = get_cpu();
-	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
-	put_cpu();
-	if (res < 0)
-		goto out;
-
-	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
-	if (n != 0)
-		res = -EFAULT;
-
-  out:
-	kfree(ptrace_ldt.ptr);
-
 	return res;
 }
 
@@ -145,9 +58,6 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
 	err = bytecount;
 
-	if (ptrace_ldt)
-		return read_ldt_from_host(ptr, bytecount);
-
 	mutex_lock(&ldt->lock);
 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
 		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
@@ -229,17 +139,11 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
 			goto out;
 	}
 
-	if (!ptrace_ldt)
-		mutex_lock(&ldt->lock);
+	mutex_lock(&ldt->lock);
 
 	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
 	if (err)
 		goto out_unlock;
-	else if (ptrace_ldt) {
-		/* With PTRACE_LDT available, this is used as a flag only */
-		ldt->entry_count = 1;
-		goto out;
-	}
 
 	if (ldt_info.entry_number >= ldt->entry_count &&
 	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
@@ -393,91 +297,56 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
 	int i;
 	long page, err=0;
 	void *addr = NULL;
-	struct proc_mm_op copy;
 
 
-	if (!ptrace_ldt)
-		mutex_init(&new_mm->arch.ldt.lock);
+	mutex_init(&new_mm->arch.ldt.lock);
 
 	if (!from_mm) {
 		memset(&desc, 0, sizeof(desc));
 		/*
-		 * We have to initialize a clean ldt.
+		 * Now we try to retrieve info about the ldt, we
+		 * inherited from the host. All ldt-entries found
+		 * will be reset in the following loop
 		 */
-		if (proc_mm) {
-			/*
-			 * If the new mm was created using proc_mm, host's
-			 * default-ldt currently is assigned, which normally
-			 * contains the call-gates for lcall7 and lcall27.
-			 * To remove these gates, we simply write an empty
-			 * entry as number 0 to the host.
-			 */
-			err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
-		}
-		else{
-			/*
-			 * Now we try to retrieve info about the ldt, we
-			 * inherited from the host. All ldt-entries found
-			 * will be reset in the following loop
-			 */
-			ldt_get_host_info();
-			for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
-				desc.entry_number = *num_p;
-				err = write_ldt_entry(&new_mm->id, 1, &desc,
-						      &addr, *(num_p + 1) == -1);
-				if (err)
-					break;
-			}
+		ldt_get_host_info();
+		for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
+			desc.entry_number = *num_p;
+			err = write_ldt_entry(&new_mm->id, 1, &desc,
+					      &addr, *(num_p + 1) == -1);
+			if (err)
+				break;
 		}
 		new_mm->arch.ldt.entry_count = 0;
 
 		goto out;
 	}
 
-	if (proc_mm) {
-		/*
-		 * We have a valid from_mm, so we now have to copy the LDT of
-		 * from_mm to new_mm, because using proc_mm an new mm with
-		 * an empty/default LDT was created in new_mm()
-		 */
-		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
-					      .u 	=
-					      { .copy_segments =
-							from_mm->id.u.mm_fd } } );
-		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
-		if (i != sizeof(copy))
-			printk(KERN_ERR "new_mm : /proc/mm copy_segments "
-			       "failed, err = %d\n", -i);
-	}
-
-	if (!ptrace_ldt) {
-		/*
-		 * Our local LDT is used to supply the data for
-		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
-		 * i.e., we have to use the stub for modify_ldt, which
-		 * can't handle the big read buffer of up to 64kB.
-		 */
-		mutex_lock(&from_mm->arch.ldt.lock);
-		if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
-			memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
-			       sizeof(new_mm->arch.ldt.u.entries));
-		else {
-			i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
-			while (i-->0) {
-				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
-				if (!page) {
-					err = -ENOMEM;
-					break;
-				}
-				new_mm->arch.ldt.u.pages[i] =
-					(struct ldt_entry *) page;
-				memcpy(new_mm->arch.ldt.u.pages[i],
-				       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
+	/*
+	 * Our local LDT is used to supply the data for
+	 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
+	 * i.e., we have to use the stub for modify_ldt, which
+	 * can't handle the big read buffer of up to 64kB.
+	 */
+	mutex_lock(&from_mm->arch.ldt.lock);
+	if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
+		memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
+		       sizeof(new_mm->arch.ldt.u.entries));
+	else {
+		i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+		while (i-->0) {
+			page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+			if (!page) {
+				err = -ENOMEM;
+				break;
 			}
+			new_mm->arch.ldt.u.pages[i] =
+				(struct ldt_entry *) page;
+			memcpy(new_mm->arch.ldt.u.pages[i],
+			       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
 		}
-		new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
-		mutex_unlock(&from_mm->arch.ldt.lock);
 	}
+	new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
+	mutex_unlock(&from_mm->arch.ldt.lock);
 
     out:
 	return err;
@@ -488,7 +357,7 @@ void free_ldt(struct mm_context *mm)
 {
 	int i;
 
-	if (!ptrace_ldt && mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
+	if (mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
 		i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
 		while (i-- > 0)
 			free_page((long) mm->arch.ldt.u.pages[i]);
diff --git a/arch/x86/um/shared/sysdep/faultinfo_32.h b/arch/x86/um/shared/sysdep/faultinfo_32.h
index a26086b8a800..b6f2437ec29c 100644
--- a/arch/x86/um/shared/sysdep/faultinfo_32.h
+++ b/arch/x86/um/shared/sysdep/faultinfo_32.h
@@ -27,9 +27,6 @@ struct faultinfo {
 /* This is Page Fault */
 #define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
 
-/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
-#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
-
 #define PTRACE_FULL_FAULTINFO 0
 
 #endif
diff --git a/arch/x86/um/shared/sysdep/faultinfo_64.h b/arch/x86/um/shared/sysdep/faultinfo_64.h
index f811cbe15d62..ee88f88974ea 100644
--- a/arch/x86/um/shared/sysdep/faultinfo_64.h
+++ b/arch/x86/um/shared/sysdep/faultinfo_64.h
@@ -27,9 +27,6 @@ struct faultinfo {
 /* This is Page Fault */
 #define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
 
-/* No broken SKAS API, which doesn't pass trap_no, here. */
-#define SEGV_MAYBE_FIXABLE(fi)	0
-
 #define PTRACE_FULL_FAULTINFO 1
 
 #endif
diff --git a/arch/x86/um/shared/sysdep/skas_ptrace.h b/arch/x86/um/shared/sysdep/skas_ptrace.h
deleted file mode 100644
index 453febe98993..000000000000
--- a/arch/x86/um/shared/sysdep/skas_ptrace.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_SKAS_PTRACE_H
-#define __SYSDEP_X86_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 2e263f367b13..9df017ab2285 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -9,12 +9,9 @@ SECTIONS
 #ifdef BUILD_VDSO32
 #include <asm/vdso32.h>
 
-	.hpet_sect : {
-		hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
-	} :text :hpet_sect
+	hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
 
-	.vvar_sect : {
-		vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
+	vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
 
 	/* Place all vvars at the offsets in asm/vvar.h. */
 #define EMIT_VVAR(name, offset) vvar_ ## name = vvar + offset;
@@ -22,7 +19,6 @@ SECTIONS
 #include <asm/vvar.h>
 #undef __VVAR_KERNEL_LDS
 #undef EMIT_VVAR
-	} :text :vvar_sect
 #endif
 	. = SIZEOF_HEADERS;
 
@@ -61,7 +57,12 @@ SECTIONS
 	 */
 	. = ALIGN(0x100);
 
-	.text		: { *(.text*) }			:text	=0x90909090
+	.text		: { *(.text*) }			:text	=0x90909090,
+
+	/*
+	 * The comma above works around a bug in gold:
+	 * https://sourceware.org/bugzilla/show_bug.cgi?id=16804
+	 */
 
 	/DISCARD/ : {
 		*(.discard)
@@ -84,8 +85,4 @@ PHDRS
 	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
 	note		PT_NOTE		FLAGS(4);		/* PF_R */
 	eh_frame_hdr	PT_GNU_EH_FRAME;
-#ifdef BUILD_VDSO32
-	vvar_sect	PT_NULL		FLAGS(4);		/* PF_R */
-	hpet_sect	PT_NULL		FLAGS(4);		/* PF_R */
-#endif
 }
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 02d6d29a63c1..2d7fed21e2ee 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -14,6 +14,7 @@ config XTENSA
 	select GENERIC_PCI_IOMAP
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select BUILDTIME_EXTABLE_SORT
 	select CLONE_BACKWARDS
 	select IRQ_DOMAIN
 	select HAVE_OPROFILE
@@ -189,6 +190,24 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
 
 	  If in doubt, say Y.
 
+config HIGHMEM
+	bool "High Memory Support"
+	help
+	  Linux can use the full amount of RAM in the system by
+	  default. However, the default MMUv2 setup only maps the
+	  lowermost 128 MB of memory linearly to the areas starting
+	  at 0xd0000000 (cached) and 0xd8000000 (uncached).
+	  When there are more than 128 MB memory in the system not
+	  all of it can be "permanently mapped" by the kernel.
+	  The physical memory that's not permanently mapped is called
+	  "high memory".
+
+	  If you are compiling a kernel which will never run on a
+	  machine with more than 128 MB total physical RAM, answer
+	  N here.
+
+	  If unsure, say Y.
+
 endmenu
 
 config XTENSA_CALIBRATE_CCOUNT
diff --git a/arch/xtensa/boot/dts/kc705.dts b/arch/xtensa/boot/dts/kc705.dts
new file mode 100644
index 000000000000..742a347be67a
--- /dev/null
+++ b/arch/xtensa/boot/dts/kc705.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-128m.dtsi"
+
+/ {
+	compatible = "cdns,xtensa-kc705";
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;
+	};
+};
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
new file mode 100644
index 000000000000..d3a88e029873
--- /dev/null
+++ b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
@@ -0,0 +1,28 @@
+/ {
+	soc {
+		flash: flash@00000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x00000000 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			partition@0x0 {
+				label = "data";
+				reg = <0x00000000 0x06000000>;
+			};
+			partition@0x6000000 {
+				label = "boot loader area";
+				reg = <0x06000000 0x00800000>;
+			};
+			partition@0x6800000 {
+				label = "kernel image";
+				reg = <0x06800000 0x017e0000>;
+			};
+			partition@0x7fe0000 {
+				label = "boot environment";
+				reg = <0x07fe0000 0x00020000>;
+			};
+		};
+        };
+};
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
index e5703c7beeb6..1d97203c18e7 100644
--- a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
+++ b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
@@ -1,26 +1,28 @@
 / {
-	flash: flash@f8000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "cfi-flash";
-		reg = <0xf8000000 0x01000000>;
-		bank-width = <2>;
-		device-width = <2>;
-		partition@0x0 {
-			label = "boot loader area";
-			reg = <0x00000000 0x00400000>;
+	soc {
+		flash: flash@08000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x08000000 0x01000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			partition@0x0 {
+				label = "boot loader area";
+				reg = <0x00000000 0x00400000>;
+			};
+			partition@0x400000 {
+				label = "kernel image";
+				reg = <0x00400000 0x00600000>;
+			};
+			partition@0xa00000 {
+				label = "data";
+				reg = <0x00a00000 0x005e0000>;
+			};
+			partition@0xfe0000 {
+				label = "boot environment";
+				reg = <0x00fe0000 0x00020000>;
+			};
 		};
-		partition@0x400000 {
-			label = "kernel image";
-			reg = <0x00400000 0x00600000>;
-		};
-		partition@0xa00000 {
-			label = "data";
-			reg = <0x00a00000 0x005e0000>;
-		};
-		partition@0xfe0000 {
-			label = "boot environment";
-			reg = <0x00fe0000 0x00020000>;
-		};
-        };
+	};
 };
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
index 6f9c10d6b689..d1c621ca8be1 100644
--- a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
+++ b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
@@ -1,18 +1,20 @@
 / {
-	flash: flash@f8000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "cfi-flash";
-		reg = <0xf8000000 0x00400000>;
-		bank-width = <2>;
-		device-width = <2>;
-		partition@0x0 {
-			label = "boot loader area";
-			reg = <0x00000000 0x003f0000>;
+	soc {
+		flash: flash@08000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x08000000 0x00400000>;
+			bank-width = <2>;
+			device-width = <2>;
+			partition@0x0 {
+				label = "boot loader area";
+				reg = <0x00000000 0x003f0000>;
+			};
+			partition@0x3f0000 {
+				label = "boot environment";
+				reg = <0x003f0000 0x00010000>;
+			};
 		};
-		partition@0x3f0000 {
-			label = "boot environment";
-			reg = <0x003f0000 0x00010000>;
-		};
-        };
+	};
 };
diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi
index e7370b11348e..dec9178840f6 100644
--- a/arch/xtensa/boot/dts/xtfpga.dtsi
+++ b/arch/xtensa/boot/dts/xtfpga.dtsi
@@ -42,21 +42,28 @@
 		};
 	};
 
-	serial0: serial@fd050020 {
-		device_type = "serial";
-		compatible = "ns16550a";
-		no-loopback-test;
-		reg = <0xfd050020 0x20>;
-		reg-shift = <2>;
-		interrupts = <0 1>; /* external irq 0 */
-		clocks = <&osc>;
-	};
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf0000000 0x10000000>;
 
-	enet0: ethoc@fd030000 {
-		compatible = "opencores,ethoc";
-		reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
-		interrupts = <1 1>; /* external irq 1 */
-		local-mac-address = [00 50 c2 13 6f 00];
-		clocks = <&osc>;
+		serial0: serial@0d050020 {
+			device_type = "serial";
+			compatible = "ns16550a";
+			no-loopback-test;
+			reg = <0x0d050020 0x20>;
+			reg-shift = <2>;
+			interrupts = <0 1>; /* external irq 0 */
+			clocks = <&osc>;
+		};
+
+		enet0: ethoc@0d030000 {
+			compatible = "opencores,ethoc";
+			reg = <0x0d030000 0x4000 0x0d800000 0x4000>;
+			interrupts = <1 1>; /* external irq 1 */
+			local-mac-address = [00 50 c2 13 6f 00];
+			clocks = <&osc>;
+		};
 	};
 };
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h
index 23392c5630ce..892aab399ac8 100644
--- a/arch/xtensa/include/asm/bootparam.h
+++ b/arch/xtensa/include/asm/bootparam.h
@@ -37,23 +37,14 @@ typedef struct bp_tag {
 	unsigned long data[0];	/* data */
 } bp_tag_t;
 
-typedef struct meminfo {
+struct bp_meminfo {
 	unsigned long type;
 	unsigned long start;
 	unsigned long end;
-} meminfo_t;
-
-#define SYSMEM_BANKS_MAX 5
+};
 
 #define MEMORY_TYPE_CONVENTIONAL	0x1000
 #define MEMORY_TYPE_NONE		0x2000
 
-typedef struct sysmem_info {
-	int nr_banks;
-	meminfo_t bank[SYSMEM_BANKS_MAX];
-} sysmem_info_t;
-
-extern sysmem_info_t sysmem;
-
 #endif
 #endif
diff --git a/arch/xtensa/include/asm/fixmap.h b/arch/xtensa/include/asm/fixmap.h
new file mode 100644
index 000000000000..9f6c33d0428a
--- /dev/null
+++ b/arch/xtensa/include/asm/fixmap.h
@@ -0,0 +1,58 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Ingo Molnar
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+#include <asm/pgtable.h>
+#ifdef CONFIG_HIGHMEM
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#endif
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process. We allocate these special  addresses
+ * from the end of the consistent memory region backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * these 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages. (or larger if used with an increment
+ * higher than 1) use fixmap_set(idx,phys) to associate
+ * physical memory with fixmap indices.
+ */
+enum fixed_addresses {
+#ifdef CONFIG_HIGHMEM
+	/* reserved pte's for temporary kernel mappings */
+	FIX_KMAP_BEGIN,
+	FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
+#endif
+	__end_of_fixed_addresses
+};
+
+#define FIXADDR_TOP     (VMALLOC_START - PAGE_SIZE)
+#define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START	((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK)
+
+#include <asm-generic/fixmap.h>
+
+#define kmap_get_fixmap_pte(vaddr) \
+	pte_offset_kernel( \
+		pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), \
+		(vaddr) \
+	)
+
+#endif
diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h
index 80be15124697..2653ef5d55f1 100644
--- a/arch/xtensa/include/asm/highmem.h
+++ b/arch/xtensa/include/asm/highmem.h
@@ -6,11 +6,54 @@
  * this archive for more details.
  *
  * Copyright (C) 2003 - 2005 Tensilica Inc.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
  */
 
 #ifndef _XTENSA_HIGHMEM_H
 #define _XTENSA_HIGHMEM_H
 
-extern void flush_cache_kmaps(void);
+#include <asm/cacheflush.h>
+#include <asm/fixmap.h>
+#include <asm/kmap_types.h>
+#include <asm/pgtable.h>
+
+#define PKMAP_BASE		(FIXADDR_START - PMD_SIZE)
+#define LAST_PKMAP		PTRS_PER_PTE
+#define LAST_PKMAP_MASK		(LAST_PKMAP - 1)
+#define PKMAP_NR(virt)		(((virt) - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)		(PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define kmap_prot		PAGE_KERNEL
+
+extern pte_t *pkmap_page_table;
+
+void *kmap_high(struct page *page);
+void kunmap_high(struct page *page);
+
+static inline void *kmap(struct page *page)
+{
+	BUG_ON(in_interrupt());
+	if (!PageHighMem(page))
+		return page_address(page);
+	return kmap_high(page);
+}
+
+static inline void kunmap(struct page *page)
+{
+	BUG_ON(in_interrupt());
+	if (!PageHighMem(page))
+		return;
+	kunmap_high(page);
+}
+
+static inline void flush_cache_kmaps(void)
+{
+	flush_cache_all();
+}
+
+void *kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+
+void kmap_init(void);
 
 #endif
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h
index 216446295ada..4b0ca35a93b1 100644
--- a/arch/xtensa/include/asm/pgtable.h
+++ b/arch/xtensa/include/asm/pgtable.h
@@ -310,6 +310,10 @@ set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
 	update_pte(ptep, pteval);
 }
 
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+	update_pte(ptep, pteval);
+}
 
 static inline void
 set_pmd(pmd_t *pmdp, pmd_t pmdval)
diff --git a/arch/xtensa/include/asm/sysmem.h b/arch/xtensa/include/asm/sysmem.h
new file mode 100644
index 000000000000..c015c5c8e3f7
--- /dev/null
+++ b/arch/xtensa/include/asm/sysmem.h
@@ -0,0 +1,38 @@
+/*
+ * sysmem-related prototypes.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ */
+
+#ifndef _XTENSA_SYSMEM_H
+#define _XTENSA_SYSMEM_H
+
+#define SYSMEM_BANKS_MAX 31
+
+struct meminfo {
+	unsigned long start;
+	unsigned long end;
+};
+
+/*
+ * Bank array is sorted by .start.
+ * Banks don't overlap and there's at least one page gap
+ * between adjacent bank entries.
+ */
+struct sysmem_info {
+	int nr_banks;
+	struct meminfo bank[SYSMEM_BANKS_MAX];
+};
+
+extern struct sysmem_info sysmem;
+
+int add_sysmem_bank(unsigned long start, unsigned long end);
+int mem_reserve(unsigned long, unsigned long, int);
+void bootmem_init(void);
+void zones_init(void);
+
+#endif /* _XTENSA_SYSMEM_H */
diff --git a/arch/xtensa/include/asm/tlbflush.h b/arch/xtensa/include/asm/tlbflush.h
index fc34274ce41b..06875feb27c2 100644
--- a/arch/xtensa/include/asm/tlbflush.h
+++ b/arch/xtensa/include/asm/tlbflush.h
@@ -36,6 +36,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma,
 		unsigned long page);
 void local_flush_tlb_range(struct vm_area_struct *vma,
 		unsigned long start, unsigned long end);
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
 
 #ifdef CONFIG_SMP
 
@@ -44,12 +45,7 @@ void flush_tlb_mm(struct mm_struct *);
 void flush_tlb_page(struct vm_area_struct *, unsigned long);
 void flush_tlb_range(struct vm_area_struct *, unsigned long,
 		unsigned long);
-
-static inline void flush_tlb_kernel_range(unsigned long start,
-		unsigned long end)
-{
-	flush_tlb_all();
-}
+void flush_tlb_kernel_range(unsigned long start, unsigned long end);
 
 #else /* !CONFIG_SMP */
 
@@ -58,7 +54,8 @@ static inline void flush_tlb_kernel_range(unsigned long start,
 #define flush_tlb_page(vma, page)	   local_flush_tlb_page(vma, page)
 #define flush_tlb_range(vma, vmaddr, end)  local_flush_tlb_range(vma, vmaddr, \
 								 end)
-#define flush_tlb_kernel_range(start, end) local_flush_tlb_all()
+#define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \
+									end)
 
 #endif /* CONFIG_SMP */
 
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 84fe931bb60e..9757bb74e532 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -50,6 +50,7 @@
 #include <asm/param.h>
 #include <asm/traps.h>
 #include <asm/smp.h>
+#include <asm/sysmem.h>
 
 #include <platform/hardware.h>
 
@@ -88,12 +89,6 @@ static char __initdata command_line[COMMAND_LINE_SIZE];
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 #endif
 
-sysmem_info_t __initdata sysmem;
-
-extern int mem_reserve(unsigned long, unsigned long, int);
-extern void bootmem_init(void);
-extern void zones_init(void);
-
 /*
  * Boot parameter parsing.
  *
@@ -113,31 +108,14 @@ typedef struct tagtable {
 
 /* parse current tag */
 
-static int __init add_sysmem_bank(unsigned long type, unsigned long start,
-		unsigned long end)
-{
-	if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
-		printk(KERN_WARNING
-				"Ignoring memory bank 0x%08lx size %ldKB\n",
-				start, end - start);
-		return -EINVAL;
-	}
-	sysmem.bank[sysmem.nr_banks].type  = type;
-	sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(start);
-	sysmem.bank[sysmem.nr_banks].end   = end & PAGE_MASK;
-	sysmem.nr_banks++;
-
-	return 0;
-}
-
 static int __init parse_tag_mem(const bp_tag_t *tag)
 {
-	meminfo_t *mi = (meminfo_t *)(tag->data);
+	struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
 
 	if (mi->type != MEMORY_TYPE_CONVENTIONAL)
 		return -1;
 
-	return add_sysmem_bank(mi->type, mi->start, mi->end);
+	return add_sysmem_bank(mi->start, mi->end);
 }
 
 __tagtable(BP_TAG_MEMORY, parse_tag_mem);
@@ -146,8 +124,8 @@ __tagtable(BP_TAG_MEMORY, parse_tag_mem);
 
 static int __init parse_tag_initrd(const bp_tag_t* tag)
 {
-	meminfo_t* mi;
-	mi = (meminfo_t*)(tag->data);
+	struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
+
 	initrd_start = (unsigned long)__va(mi->start);
 	initrd_end = (unsigned long)__va(mi->end);
 
@@ -255,7 +233,7 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 		return;
 
 	size &= PAGE_MASK;
-	add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size);
+	add_sysmem_bank(base, base + size);
 }
 
 void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
@@ -292,8 +270,6 @@ device_initcall(xtensa_device_probe);
 
 void __init init_arch(bp_tag_t *bp_start)
 {
-	sysmem.nr_banks = 0;
-
 	/* Parse boot parameters */
 
 	if (bp_start)
@@ -304,10 +280,9 @@ void __init init_arch(bp_tag_t *bp_start)
 #endif
 
 	if (sysmem.nr_banks == 0) {
-		sysmem.nr_banks = 1;
-		sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
-		sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
-				     + PLATFORM_DEFAULT_MEM_SIZE;
+		add_sysmem_bank(PLATFORM_DEFAULT_MEM_START,
+				PLATFORM_DEFAULT_MEM_START +
+				PLATFORM_DEFAULT_MEM_SIZE);
 	}
 
 #ifdef CONFIG_CMDLINE_BOOL
@@ -487,7 +462,7 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start < initrd_end) {
 		initrd_is_mapped = mem_reserve(__pa(initrd_start),
-					       __pa(initrd_end), 0);
+					       __pa(initrd_end), 0) == 0;
 		initrd_below_start_ok = 1;
 	} else {
 		initrd_start = 0;
@@ -532,6 +507,7 @@ void __init setup_arch(char **cmdline_p)
 		    __pa(&_Level6InterruptVector_text_end), 0);
 #endif
 
+	parse_early_param();
 	bootmem_init();
 
 	unflatten_and_copy_device_tree();
diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c
index aa8bd8717927..40b5a3771fb0 100644
--- a/arch/xtensa/kernel/smp.c
+++ b/arch/xtensa/kernel/smp.c
@@ -496,6 +496,21 @@ void flush_tlb_range(struct vm_area_struct *vma,
 	on_each_cpu(ipi_flush_tlb_range, &fd, 1);
 }
 
+static void ipi_flush_tlb_kernel_range(void *arg)
+{
+	struct flush_data *fd = arg;
+	local_flush_tlb_kernel_range(fd->addr1, fd->addr2);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	struct flush_data fd = {
+		.addr1 = start,
+		.addr2 = end,
+	};
+	on_each_cpu(ipi_flush_tlb_kernel_range, &fd, 1);
+}
+
 /* Cache flush functions */
 
 static void ipi_flush_cache_all(void *arg)
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 80b33ed51f31..4d2872fd9bb5 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -20,6 +20,7 @@
 #include <linux/in6.h>
 
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 #include <asm/checksum.h>
 #include <asm/dma.h>
 #include <asm/io.h>
@@ -105,6 +106,7 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
  * Architecture-specific symbols
  */
 EXPORT_SYMBOL(__xtensa_copy_user);
+EXPORT_SYMBOL(__invalidate_icache_range);
 
 /*
  * Kernel hacking ...
@@ -127,3 +129,8 @@ EXPORT_SYMBOL(common_exception_return);
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
 #endif
+
+EXPORT_SYMBOL(__invalidate_dcache_range);
+#if XCHAL_DCACHE_IS_WRITEBACK
+EXPORT_SYMBOL(__flush_dcache_range);
+#endif
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile
index f0b646d2f843..f54f78e24d7b 100644
--- a/arch/xtensa/mm/Makefile
+++ b/arch/xtensa/mm/Makefile
@@ -4,3 +4,4 @@
 
 obj-y			:= init.o cache.o misc.o
 obj-$(CONFIG_MMU)	+= fault.o mmu.o tlb.o
+obj-$(CONFIG_HIGHMEM)	+= highmem.o
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c
index ba4c47f291b1..63cbb867dadd 100644
--- a/arch/xtensa/mm/cache.c
+++ b/arch/xtensa/mm/cache.c
@@ -59,6 +59,10 @@
  *
  */
 
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM)
+#error "HIGHMEM is not supported on cores with aliasing cache."
+#endif
+
 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
 /*
@@ -179,10 +183,11 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
 #else
 	if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)
 	    && (vma->vm_flags & VM_EXEC) != 0) {
-	    	unsigned long paddr = (unsigned long) page_address(page);
+		unsigned long paddr = (unsigned long)kmap_atomic(page);
 		__flush_dcache_page(paddr);
 		__invalidate_icache_page(paddr);
 		set_bit(PG_arch_1, &page->flags);
+		kunmap_atomic((void *)paddr);
 	}
 #endif
 }
diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c
new file mode 100644
index 000000000000..17a8c0d6fd17
--- /dev/null
+++ b/arch/xtensa/mm/highmem.c
@@ -0,0 +1,72 @@
+/*
+ * High memory support for Xtensa architecture
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2014 Cadence Design Systems Inc.
+ */
+
+#include <linux/export.h>
+#include <linux/highmem.h>
+#include <asm/tlbflush.h>
+
+static pte_t *kmap_pte;
+
+void *kmap_atomic(struct page *page)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+	int type;
+
+	pagefault_disable();
+	if (!PageHighMem(page))
+		return page_address(page);
+
+	type = kmap_atomic_idx_push();
+	idx = type + KM_TYPE_NR * smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+	BUG_ON(!pte_none(*(kmap_pte - idx)));
+#endif
+	set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC));
+
+	return (void *)vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic);
+
+void __kunmap_atomic(void *kvaddr)
+{
+	int idx, type;
+
+	if (kvaddr >= (void *)FIXADDR_START &&
+	    kvaddr < (void *)FIXADDR_TOP) {
+		type = kmap_atomic_idx();
+		idx = type + KM_TYPE_NR * smp_processor_id();
+
+		/*
+		 * Force other mappings to Oops if they'll try to access this
+		 * pte without first remap it.  Keeping stale mappings around
+		 * is a bad idea also, in case the page changes cacheability
+		 * attributes or becomes a protected page in a hypervisor.
+		 */
+		pte_clear(&init_mm, kvaddr, kmap_pte - idx);
+		local_flush_tlb_kernel_range((unsigned long)kvaddr,
+					     (unsigned long)kvaddr + PAGE_SIZE);
+
+		kmap_atomic_idx_pop();
+	}
+
+	pagefault_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
+
+void __init kmap_init(void)
+{
+	unsigned long kmap_vstart;
+
+	/* cache the first kmap pte */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+}
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index aff108df92d3..4224256bb215 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -8,6 +8,7 @@
  * for more details.
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
  *
  * Chris Zankel	<chris@zankel.net>
  * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
@@ -19,6 +20,7 @@
 #include <linux/errno.h>
 #include <linux/bootmem.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 #include <linux/swap.h>
 #include <linux/mman.h>
 #include <linux/nodemask.h>
@@ -27,11 +29,133 @@
 #include <asm/bootparam.h>
 #include <asm/page.h>
 #include <asm/sections.h>
+#include <asm/sysmem.h>
+
+struct sysmem_info sysmem __initdata;
+
+static void __init sysmem_dump(void)
+{
+	unsigned i;
+
+	pr_debug("Sysmem:\n");
+	for (i = 0; i < sysmem.nr_banks; ++i)
+		pr_debug("  0x%08lx - 0x%08lx (%ldK)\n",
+			 sysmem.bank[i].start, sysmem.bank[i].end,
+			 (sysmem.bank[i].end - sysmem.bank[i].start) >> 10);
+}
+
+/*
+ * Find bank with maximal .start such that bank.start <= start
+ */
+static inline struct meminfo * __init find_bank(unsigned long start)
+{
+	unsigned i;
+	struct meminfo *it = NULL;
+
+	for (i = 0; i < sysmem.nr_banks; ++i)
+		if (sysmem.bank[i].start <= start)
+			it = sysmem.bank + i;
+		else
+			break;
+	return it;
+}
+
+/*
+ * Move all memory banks starting at 'from' to a new place at 'to',
+ * adjust nr_banks accordingly.
+ * Both 'from' and 'to' must be inside the sysmem.bank.
+ *
+ * Returns: 0 (success), -ENOMEM (not enough space in the sysmem.bank).
+ */
+static int __init move_banks(struct meminfo *to, struct meminfo *from)
+{
+	unsigned n = sysmem.nr_banks - (from - sysmem.bank);
+
+	if (to > from && to - from + sysmem.nr_banks > SYSMEM_BANKS_MAX)
+		return -ENOMEM;
+	if (to != from)
+		memmove(to, from, n * sizeof(struct meminfo));
+	sysmem.nr_banks += to - from;
+	return 0;
+}
+
+/*
+ * Add new bank to sysmem. Resulting sysmem is the union of bytes of the
+ * original sysmem and the new bank.
+ *
+ * Returns: 0 (success), < 0 (error)
+ */
+int __init add_sysmem_bank(unsigned long start, unsigned long end)
+{
+	unsigned i;
+	struct meminfo *it = NULL;
+	unsigned long sz;
+	unsigned long bank_sz = 0;
+
+	if (start == end ||
+	    (start < end) != (PAGE_ALIGN(start) < (end & PAGE_MASK))) {
+		pr_warn("Ignoring small memory bank 0x%08lx size: %ld bytes\n",
+			start, end - start);
+		return -EINVAL;
+	}
+
+	start = PAGE_ALIGN(start);
+	end &= PAGE_MASK;
+	sz = end - start;
+
+	it = find_bank(start);
+
+	if (it)
+		bank_sz = it->end - it->start;
+
+	if (it && bank_sz >= start - it->start) {
+		if (end - it->start > bank_sz)
+			it->end = end;
+		else
+			return 0;
+	} else {
+		if (!it)
+			it = sysmem.bank;
+		else
+			++it;
+
+		if (it - sysmem.bank < sysmem.nr_banks &&
+		    it->start - start <= sz) {
+			it->start = start;
+			if (it->end - it->start < sz)
+				it->end = end;
+			else
+				return 0;
+		} else {
+			if (move_banks(it + 1, it) < 0) {
+				pr_warn("Ignoring memory bank 0x%08lx size %ld bytes\n",
+					start, end - start);
+				return -EINVAL;
+			}
+			it->start = start;
+			it->end = end;
+			return 0;
+		}
+	}
+	sz = it->end - it->start;
+	for (i = it + 1 - sysmem.bank; i < sysmem.nr_banks; ++i)
+		if (sysmem.bank[i].start - it->start <= sz) {
+			if (sz < sysmem.bank[i].end - it->start)
+				it->end = sysmem.bank[i].end;
+		} else {
+			break;
+		}
+
+	move_banks(it + 1, sysmem.bank + i);
+	return 0;
+}
 
 /*
  * mem_reserve(start, end, must_exist)
  *
  * Reserve some memory from the memory pool.
+ * If must_exist is set and a part of the region being reserved does not exist
+ * memory map is not altered.
  *
  * Parameters:
  *  start	Start of region,
@@ -39,53 +163,69 @@
  *  must_exist	Must exist in memory pool.
  *
  * Returns:
- *  0 (memory area couldn't be mapped)
- * -1 (success)
+ *  0 (success)
+ *  < 0 (error)
  */
 
 int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
 {
-	int i;
-
-	if (start == end)
-		return 0;
+	struct meminfo *it;
+	struct meminfo *rm = NULL;
+	unsigned long sz;
+	unsigned long bank_sz = 0;
 
 	start = start & PAGE_MASK;
 	end = PAGE_ALIGN(end);
+	sz = end - start;
+	if (!sz)
+		return -EINVAL;
 
-	for (i = 0; i < sysmem.nr_banks; i++)
-		if (start < sysmem.bank[i].end
-		    && end >= sysmem.bank[i].start)
-			break;
+	it = find_bank(start);
+
+	if (it)
+		bank_sz = it->end - it->start;
 
-	if (i == sysmem.nr_banks) {
-		if (must_exist)
-			printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) "
-				"not in any region!\n", start, end);
-		return 0;
+	if ((!it || end - it->start > bank_sz) && must_exist) {
+		pr_warn("mem_reserve: [0x%0lx, 0x%0lx) not in any region!\n",
+			start, end);
+		return -EINVAL;
 	}
 
-	if (start > sysmem.bank[i].start) {
-		if (end < sysmem.bank[i].end) {
-			/* split entry */
-			if (sysmem.nr_banks >= SYSMEM_BANKS_MAX)
-				panic("meminfo overflow\n");
-			sysmem.bank[sysmem.nr_banks].start = end;
-			sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end;
-			sysmem.nr_banks++;
+	if (it && start - it->start < bank_sz) {
+		if (start == it->start) {
+			if (end - it->start < bank_sz) {
+				it->start = end;
+				return 0;
+			} else {
+				rm = it;
+			}
+		} else {
+			it->end = start;
+			if (end - it->start < bank_sz)
+				return add_sysmem_bank(end,
+						       it->start + bank_sz);
+			++it;
 		}
-		sysmem.bank[i].end = start;
+	}
 
-	} else if (end < sysmem.bank[i].end) {
-		sysmem.bank[i].start = end;
+	if (!it)
+		it = sysmem.bank;
 
-	} else {
-		/* remove entry */
-		sysmem.nr_banks--;
-		sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
-		sysmem.bank[i].end   = sysmem.bank[sysmem.nr_banks].end;
+	for (; it < sysmem.bank + sysmem.nr_banks; ++it) {
+		if (it->end - start <= sz) {
+			if (!rm)
+				rm = it;
+		} else {
+			if (it->start - start < sz)
+				it->start = end;
+			break;
+		}
 	}
-	return -1;
+
+	if (rm)
+		move_banks(rm, it);
+
+	return 0;
 }
 
 
@@ -99,6 +239,7 @@ void __init bootmem_init(void)
 	unsigned long bootmap_start, bootmap_size;
 	int i;
 
+	sysmem_dump();
 	max_low_pfn = max_pfn = 0;
 	min_low_pfn = ~0;
 
@@ -156,19 +297,13 @@ void __init bootmem_init(void)
 
 void __init zones_init(void)
 {
-	unsigned long zones_size[MAX_NR_ZONES];
-	int i;
-
 	/* All pages are DMA-able, so we put them all in the DMA zone. */
-
-	zones_size[ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET;
-	for (i = 1; i < MAX_NR_ZONES; i++)
-		zones_size[i] = 0;
-
+	unsigned long zones_size[MAX_NR_ZONES] = {
+		[ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET,
 #ifdef CONFIG_HIGHMEM
-	zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
+		[ZONE_HIGHMEM] = max_pfn - max_low_pfn,
 #endif
-
+	};
 	free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL);
 }
 
@@ -178,16 +313,38 @@ void __init zones_init(void)
 
 void __init mem_init(void)
 {
-	max_mapnr = max_low_pfn - ARCH_PFN_OFFSET;
-	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
-
 #ifdef CONFIG_HIGHMEM
-#error HIGHGMEM not implemented in init.c
+	unsigned long tmp;
+
+	reset_all_zones_managed_pages();
+	for (tmp = max_low_pfn; tmp < max_pfn; tmp++)
+		free_highmem_page(pfn_to_page(tmp));
 #endif
 
+	max_mapnr = max_pfn - ARCH_PFN_OFFSET;
+	high_memory = (void *)__va(max_low_pfn << PAGE_SHIFT);
+
 	free_all_bootmem();
 
 	mem_init_print_info(NULL);
+	pr_info("virtual kernel memory layout:\n"
+#ifdef CONFIG_HIGHMEM
+		"    pkmap   : 0x%08lx - 0x%08lx  (%5lu kB)\n"
+		"    fixmap  : 0x%08lx - 0x%08lx  (%5lu kB)\n"
+#endif
+		"    vmalloc : 0x%08x - 0x%08x  (%5u MB)\n"
+		"    lowmem  : 0x%08x - 0x%08lx  (%5lu MB)\n",
+#ifdef CONFIG_HIGHMEM
+		PKMAP_BASE, PKMAP_BASE + LAST_PKMAP * PAGE_SIZE,
+		(LAST_PKMAP*PAGE_SIZE) >> 10,
+		FIXADDR_START, FIXADDR_TOP,
+		(FIXADDR_TOP - FIXADDR_START) >> 10,
+#endif
+		VMALLOC_START, VMALLOC_END,
+		(VMALLOC_END - VMALLOC_START) >> 20,
+		PAGE_OFFSET, PAGE_OFFSET +
+		(max_low_pfn - min_low_pfn) * PAGE_SIZE,
+		((max_low_pfn - min_low_pfn) * PAGE_SIZE) >> 20);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -204,3 +361,53 @@ void free_initmem(void)
 {
 	free_initmem_default(-1);
 }
+
+static void __init parse_memmap_one(char *p)
+{
+	char *oldp;
+	unsigned long start_at, mem_size;
+
+	if (!p)
+		return;
+
+	oldp = p;
+	mem_size = memparse(p, &p);
+	if (p == oldp)
+		return;
+
+	switch (*p) {
+	case '@':
+		start_at = memparse(p + 1, &p);
+		add_sysmem_bank(start_at, start_at + mem_size);
+		break;
+
+	case '$':
+		start_at = memparse(p + 1, &p);
+		mem_reserve(start_at, start_at + mem_size, 0);
+		break;
+
+	case 0:
+		mem_reserve(mem_size, 0, 0);
+		break;
+
+	default:
+		pr_warn("Unrecognized memmap syntax: %s\n", p);
+		break;
+	}
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+	while (str) {
+		char *k = strchr(str, ',');
+
+		if (k)
+			*k++ = 0;
+
+		parse_memmap_one(str);
+		str = k;
+	}
+
+	return 0;
+}
+early_param("memmap", parse_memmap_opt);
diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c
index 861203e958da..3429b483d9f8 100644
--- a/arch/xtensa/mm/mmu.c
+++ b/arch/xtensa/mm/mmu.c
@@ -3,6 +3,7 @@
  *
  * Extracted from init.c
  */
+#include <linux/bootmem.h>
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/string.h>
@@ -16,9 +17,44 @@
 #include <asm/initialize_mmu.h>
 #include <asm/io.h>
 
+#if defined(CONFIG_HIGHMEM)
+static void * __init init_pmd(unsigned long vaddr)
+{
+	pgd_t *pgd = pgd_offset_k(vaddr);
+	pmd_t *pmd = pmd_offset(pgd, vaddr);
+
+	if (pmd_none(*pmd)) {
+		unsigned i;
+		pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE);
+
+		for (i = 0; i < 1024; i++)
+			pte_clear(NULL, 0, pte + i);
+
+		set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK));
+		BUG_ON(pte != pte_offset_kernel(pmd, 0));
+		pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n",
+			 __func__, vaddr, pmd, pte);
+		return pte;
+	} else {
+		return pte_offset_kernel(pmd, 0);
+	}
+}
+
+static void __init fixedrange_init(void)
+{
+	BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE);
+	init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK);
+}
+#endif
+
 void __init paging_init(void)
 {
 	memset(swapper_pg_dir, 0, PAGE_SIZE);
+#ifdef CONFIG_HIGHMEM
+	fixedrange_init();
+	pkmap_page_table = init_pmd(PKMAP_BASE);
+	kmap_init();
+#endif
 }
 
 /*
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
index ade623826788..5ece856c5725 100644
--- a/arch/xtensa/mm/tlb.c
+++ b/arch/xtensa/mm/tlb.c
@@ -149,6 +149,21 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 	local_irq_restore(flags);
 }
 
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	if (end > start && start >= TASK_SIZE && end <= PAGE_OFFSET &&
+	    end - start < _TLB_ENTRIES << PAGE_SHIFT) {
+		start &= PAGE_MASK;
+		while (start < end) {
+			invalidate_itlb_mapping(start);
+			invalidate_dtlb_mapping(start);
+			start += PAGE_SIZE;
+		}
+	} else {
+		local_flush_tlb_all();
+	}
+}
+
 #ifdef CONFIG_DEBUG_TLB_SANITY
 
 static unsigned get_pte_for_vaddr(unsigned vaddr)
diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c
index f9bc87966290..b90555cb8089 100644
--- a/arch/xtensa/platforms/xt2000/setup.c
+++ b/arch/xtensa/platforms/xt2000/setup.c
@@ -92,18 +92,8 @@ void __init platform_setup(char** cmdline)
 
 /* early initialization */
 
-extern sysmem_info_t __initdata sysmem;
-
-void platform_init(bp_tag_t* first)
+void __init platform_init(bp_tag_t *first)
 {
-	/* Set default memory block if not provided by the bootloader. */
-
-	if (sysmem.nr_banks == 0) {
-		sysmem.nr_banks = 1;
-		sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
-		sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
-				     + PLATFORM_DEFAULT_MEM_SIZE;
-	}
 }
 
 /* Heartbeat. Let the LED blink. */
diff --git a/block/blk-core.c b/block/blk-core.c
index a0e3096c4bb5..c4269701cb4f 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -146,8 +146,8 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
 	printk(KERN_INFO "  sector %llu, nr/cnr %u/%u\n",
 	       (unsigned long long)blk_rq_pos(rq),
 	       blk_rq_sectors(rq), blk_rq_cur_sectors(rq));
-	printk(KERN_INFO "  bio %p, biotail %p, buffer %p, len %u\n",
-	       rq->bio, rq->biotail, rq->buffer, blk_rq_bytes(rq));
+	printk(KERN_INFO "  bio %p, biotail %p, len %u\n",
+	       rq->bio, rq->biotail, blk_rq_bytes(rq));
 
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		printk(KERN_INFO "  cdb: ");
@@ -251,8 +251,10 @@ void blk_sync_queue(struct request_queue *q)
 		struct blk_mq_hw_ctx *hctx;
 		int i;
 
-		queue_for_each_hw_ctx(q, hctx, i)
-			cancel_delayed_work_sync(&hctx->delayed_work);
+		queue_for_each_hw_ctx(q, hctx, i) {
+			cancel_delayed_work_sync(&hctx->run_work);
+			cancel_delayed_work_sync(&hctx->delay_work);
+		}
 	} else {
 		cancel_delayed_work_sync(&q->delay_work);
 	}
@@ -1360,7 +1362,6 @@ void blk_add_request_payload(struct request *rq, struct page *page,
 
 	rq->__data_len = rq->resid_len = len;
 	rq->nr_phys_segments = 1;
-	rq->buffer = bio_data(bio);
 }
 EXPORT_SYMBOL_GPL(blk_add_request_payload);
 
@@ -1402,12 +1403,6 @@ bool bio_attempt_front_merge(struct request_queue *q, struct request *req,
 	bio->bi_next = req->bio;
 	req->bio = bio;
 
-	/*
-	 * may not be valid. if the low level driver said
-	 * it didn't need a bounce buffer then it better
-	 * not touch req->buffer either...
-	 */
-	req->buffer = bio_data(bio);
 	req->__sector = bio->bi_iter.bi_sector;
 	req->__data_len += bio->bi_iter.bi_size;
 	req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
@@ -1654,7 +1649,7 @@ static int __init fail_make_request_debugfs(void)
 	struct dentry *dir = fault_create_debugfs_attr("fail_make_request",
 						NULL, &fail_make_request);
 
-	return IS_ERR(dir) ? PTR_ERR(dir) : 0;
+	return PTR_ERR_OR_ZERO(dir);
 }
 
 late_initcall(fail_make_request_debugfs);
@@ -2434,7 +2429,6 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 	}
 
 	req->__data_len -= total_bytes;
-	req->buffer = bio_data(req->bio);
 
 	/* update sector only for requests with clear definition of sector */
 	if (req->cmd_type == REQ_TYPE_FS)
@@ -2503,7 +2497,7 @@ EXPORT_SYMBOL_GPL(blk_unprep_request);
 /*
  * queue lock must be held
  */
-static void blk_finish_request(struct request *req, int error)
+void blk_finish_request(struct request *req, int error)
 {
 	if (blk_rq_tagged(req))
 		blk_queue_end_tag(req->q, req);
@@ -2529,6 +2523,7 @@ static void blk_finish_request(struct request *req, int error)
 		__blk_put_request(req->q, req);
 	}
 }
+EXPORT_SYMBOL(blk_finish_request);
 
 /**
  * blk_end_bidi_request - Complete a bidi request
@@ -2752,10 +2747,9 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
 	/* Bit 0 (R/W) is identical in rq->cmd_flags and bio->bi_rw */
 	rq->cmd_flags |= bio->bi_rw & REQ_WRITE;
 
-	if (bio_has_data(bio)) {
+	if (bio_has_data(bio))
 		rq->nr_phys_segments = bio_phys_segments(q, bio);
-		rq->buffer = bio_data(bio);
-	}
+
 	rq->__data_len = bio->bi_iter.bi_size;
 	rq->bio = rq->biotail = bio;
 
@@ -2831,7 +2825,7 @@ EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);
 
 /*
  * Copy attributes of the original request to the clone request.
- * The actual data parts (e.g. ->cmd, ->buffer, ->sense) are not copied.
+ * The actual data parts (e.g. ->cmd, ->sense) are not copied.
  */
 static void __blk_rq_prep_clone(struct request *dst, struct request *src)
 {
@@ -2857,7 +2851,7 @@ static void __blk_rq_prep_clone(struct request *dst, struct request *src)
  *
  * Description:
  *     Clones bios in @rq_src to @rq, and copies attributes of @rq_src to @rq.
- *     The actual data parts of @rq_src (e.g. ->cmd, ->buffer, ->sense)
+ *     The actual data parts of @rq_src (e.g. ->cmd, ->sense)
  *     are not copied, and copying such parts is the caller's responsibility.
  *     Also, pages which the original bios are pointing to are not copied
  *     and the cloned bios just point same pages.
@@ -2904,19 +2898,26 @@ free_and_out:
 }
 EXPORT_SYMBOL_GPL(blk_rq_prep_clone);
 
-int kblockd_schedule_work(struct request_queue *q, struct work_struct *work)
+int kblockd_schedule_work(struct work_struct *work)
 {
 	return queue_work(kblockd_workqueue, work);
 }
 EXPORT_SYMBOL(kblockd_schedule_work);
 
-int kblockd_schedule_delayed_work(struct request_queue *q,
-			struct delayed_work *dwork, unsigned long delay)
+int kblockd_schedule_delayed_work(struct delayed_work *dwork,
+				  unsigned long delay)
 {
 	return queue_delayed_work(kblockd_workqueue, dwork, delay);
 }
 EXPORT_SYMBOL(kblockd_schedule_delayed_work);
 
+int kblockd_schedule_delayed_work_on(int cpu, struct delayed_work *dwork,
+				     unsigned long delay)
+{
+	return queue_delayed_work_on(cpu, kblockd_workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(kblockd_schedule_delayed_work_on);
+
 #define PLUG_MAGIC	0x91827364
 
 /**
diff --git a/block/blk-flush.c b/block/blk-flush.c
index 43e6b4755e9a..ec7a224d6733 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -134,7 +134,7 @@ static void mq_flush_run(struct work_struct *work)
 {
 	struct request *rq;
 
-	rq = container_of(work, struct request, mq_flush_work);
+	rq = container_of(work, struct request, requeue_work);
 
 	memset(&rq->csd, 0, sizeof(rq->csd));
 	blk_mq_insert_request(rq, false, true, false);
@@ -143,8 +143,8 @@ static void mq_flush_run(struct work_struct *work)
 static bool blk_flush_queue_rq(struct request *rq, bool add_front)
 {
 	if (rq->q->mq_ops) {
-		INIT_WORK(&rq->mq_flush_work, mq_flush_run);
-		kblockd_schedule_work(rq->q, &rq->mq_flush_work);
+		INIT_WORK(&rq->requeue_work, mq_flush_run);
+		kblockd_schedule_work(&rq->requeue_work);
 		return false;
 	} else {
 		if (add_front)
@@ -306,23 +306,9 @@ static bool blk_kick_flush(struct request_queue *q)
 	 */
 	q->flush_pending_idx ^= 1;
 
-	if (q->mq_ops) {
-		struct blk_mq_ctx *ctx = first_rq->mq_ctx;
-		struct blk_mq_hw_ctx *hctx = q->mq_ops->map_queue(q, ctx->cpu);
-
-		blk_mq_rq_init(hctx, q->flush_rq);
-		q->flush_rq->mq_ctx = ctx;
-
-		/*
-		 * Reuse the tag value from the fist waiting request,
-		 * with blk-mq the tag is generated during request
-		 * allocation and drivers can rely on it being inside
-		 * the range they asked for.
-		 */
-		q->flush_rq->tag = first_rq->tag;
-	} else {
-		blk_rq_init(q, q->flush_rq);
-	}
+	blk_rq_init(q, q->flush_rq);
+	if (q->mq_ops)
+		blk_mq_clone_flush_request(q->flush_rq, first_rq);
 
 	q->flush_rq->cmd_type = REQ_TYPE_FS;
 	q->flush_rq->cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ;
diff --git a/block/blk-map.c b/block/blk-map.c
index f7b22bc21518..f890d4345b0c 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -155,7 +155,6 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
 	if (!bio_flagged(bio, BIO_USER_MAPPED))
 		rq->cmd_flags |= REQ_COPY_USER;
 
-	rq->buffer = NULL;
 	return 0;
 unmap_rq:
 	blk_rq_unmap_user(bio);
@@ -238,7 +237,6 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
 	blk_queue_bounce(q, &bio);
 	bio_get(bio);
 	blk_rq_bio_prep(q, rq, bio);
-	rq->buffer = NULL;
 	return 0;
 }
 EXPORT_SYMBOL(blk_rq_map_user_iov);
@@ -325,7 +323,6 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
 	}
 
 	blk_queue_bounce(q, &rq->bio);
-	rq->buffer = NULL;
 	return 0;
 }
 EXPORT_SYMBOL(blk_rq_map_kern);
diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c
index 097921329619..5d0f93cf358c 100644
--- a/block/blk-mq-cpumap.c
+++ b/block/blk-mq-cpumap.c
@@ -80,17 +80,17 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)
 	return 0;
 }
 
-unsigned int *blk_mq_make_queue_map(struct blk_mq_reg *reg)
+unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set)
 {
 	unsigned int *map;
 
 	/* If cpus are offline, map them to first hctx */
 	map = kzalloc_node(sizeof(*map) * num_possible_cpus(), GFP_KERNEL,
-				reg->numa_node);
+				set->numa_node);
 	if (!map)
 		return NULL;
 
-	if (!blk_mq_update_queue_map(map, reg->nr_hw_queues))
+	if (!blk_mq_update_queue_map(map, set->nr_hw_queues))
 		return map;
 
 	kfree(map);
diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index b0ba264b0522..9176a6984857 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -246,16 +246,12 @@ static ssize_t blk_mq_hw_sysfs_tags_show(struct blk_mq_hw_ctx *hctx, char *page)
 
 static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
 {
-	unsigned int i, queue_num, first = 1;
+	unsigned int i, first = 1;
 	ssize_t ret = 0;
 
 	blk_mq_disable_hotplug();
 
-	for_each_online_cpu(i) {
-		queue_num = hctx->queue->mq_map[i];
-		if (queue_num != hctx->queue_num)
-			continue;
-
+	for_each_cpu(i, hctx->cpumask) {
 		if (first)
 			ret += sprintf(ret + page, "%u", i);
 		else
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index 83ae96c51a27..7a799c46c32d 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -1,25 +1,11 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/percpu_ida.h>
 
 #include <linux/blk-mq.h>
 #include "blk.h"
 #include "blk-mq.h"
 #include "blk-mq-tag.h"
 
-/*
- * Per tagged queue (tag address space) map
- */
-struct blk_mq_tags {
-	unsigned int nr_tags;
-	unsigned int nr_reserved_tags;
-	unsigned int nr_batch_move;
-	unsigned int nr_max_cache;
-
-	struct percpu_ida free_tags;
-	struct percpu_ida reserved_tags;
-};
-
 void blk_mq_wait_for_tags(struct blk_mq_tags *tags)
 {
 	int tag = blk_mq_get_tag(tags, __GFP_WAIT, false);
diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h
index 947ba2c6148e..b602e3fa66ea 100644
--- a/block/blk-mq-tag.h
+++ b/block/blk-mq-tag.h
@@ -1,7 +1,24 @@
 #ifndef INT_BLK_MQ_TAG_H
 #define INT_BLK_MQ_TAG_H
 
-struct blk_mq_tags;
+#include <linux/percpu_ida.h>
+
+/*
+ * Tag address space map.
+ */
+struct blk_mq_tags {
+	unsigned int nr_tags;
+	unsigned int nr_reserved_tags;
+	unsigned int nr_batch_move;
+	unsigned int nr_max_cache;
+
+	struct percpu_ida free_tags;
+	struct percpu_ida reserved_tags;
+
+	struct request **rqs;
+	struct list_head page_list;
+};
+
 
 extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int reserved_tags, int node);
 extern void blk_mq_free_tags(struct blk_mq_tags *tags);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 1d2a9bdbee57..ee225cc312b8 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -81,7 +81,8 @@ static struct request *__blk_mq_alloc_request(struct blk_mq_hw_ctx *hctx,
 
 	tag = blk_mq_get_tag(hctx->tags, gfp, reserved);
 	if (tag != BLK_MQ_TAG_FAIL) {
-		rq = hctx->rqs[tag];
+		rq = hctx->tags->rqs[tag];
+		blk_rq_init(hctx->queue, rq);
 		rq->tag = tag;
 
 		return rq;
@@ -209,11 +210,14 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q,
 			break;
 		}
 
-		blk_mq_put_ctx(ctx);
-		if (!(gfp & __GFP_WAIT))
+		if (gfp & __GFP_WAIT) {
+			__blk_mq_run_hw_queue(hctx);
+			blk_mq_put_ctx(ctx);
+		} else {
+			blk_mq_put_ctx(ctx);
 			break;
+		}
 
-		__blk_mq_run_hw_queue(hctx);
 		blk_mq_wait_for_tags(hctx->tags);
 	} while (1);
 
@@ -248,26 +252,13 @@ struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw,
 }
 EXPORT_SYMBOL(blk_mq_alloc_reserved_request);
 
-/*
- * Re-init and set pdu, if we have it
- */
-void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq)
-{
-	blk_rq_init(hctx->queue, rq);
-
-	if (hctx->cmd_size)
-		rq->special = blk_mq_rq_to_pdu(rq);
-}
-
 static void __blk_mq_free_request(struct blk_mq_hw_ctx *hctx,
 				  struct blk_mq_ctx *ctx, struct request *rq)
 {
 	const int tag = rq->tag;
 	struct request_queue *q = rq->q;
 
-	blk_mq_rq_init(hctx, rq);
 	blk_mq_put_tag(hctx->tags, tag);
-
 	blk_mq_queue_exit(q);
 }
 
@@ -283,20 +274,47 @@ void blk_mq_free_request(struct request *rq)
 	__blk_mq_free_request(hctx, ctx, rq);
 }
 
-bool blk_mq_end_io_partial(struct request *rq, int error, unsigned int nr_bytes)
+/*
+ * Clone all relevant state from a request that has been put on hold in
+ * the flush state machine into the preallocated flush request that hangs
+ * off the request queue.
+ *
+ * For a driver the flush request should be invisible, that's why we are
+ * impersonating the original request here.
+ */
+void blk_mq_clone_flush_request(struct request *flush_rq,
+		struct request *orig_rq)
 {
-	if (blk_update_request(rq, error, blk_rq_bytes(rq)))
-		return true;
+	struct blk_mq_hw_ctx *hctx =
+		orig_rq->q->mq_ops->map_queue(orig_rq->q, orig_rq->mq_ctx->cpu);
 
+	flush_rq->mq_ctx = orig_rq->mq_ctx;
+	flush_rq->tag = orig_rq->tag;
+	memcpy(blk_mq_rq_to_pdu(flush_rq), blk_mq_rq_to_pdu(orig_rq),
+		hctx->cmd_size);
+}
+
+inline void __blk_mq_end_io(struct request *rq, int error)
+{
 	blk_account_io_done(rq);
 
-	if (rq->end_io)
+	if (rq->end_io) {
 		rq->end_io(rq, error);
-	else
+	} else {
+		if (unlikely(blk_bidi_rq(rq)))
+			blk_mq_free_request(rq->next_rq);
 		blk_mq_free_request(rq);
-	return false;
+	}
+}
+EXPORT_SYMBOL(__blk_mq_end_io);
+
+void blk_mq_end_io(struct request *rq, int error)
+{
+	if (blk_update_request(rq, error, blk_rq_bytes(rq)))
+		BUG();
+	__blk_mq_end_io(rq, error);
 }
-EXPORT_SYMBOL(blk_mq_end_io_partial);
+EXPORT_SYMBOL(blk_mq_end_io);
 
 static void __blk_mq_complete_request_remote(void *data)
 {
@@ -350,6 +368,10 @@ static void blk_mq_start_request(struct request *rq, bool last)
 
 	trace_block_rq_issue(q, rq);
 
+	rq->resid_len = blk_rq_bytes(rq);
+	if (unlikely(blk_bidi_rq(rq)))
+		rq->next_rq->resid_len = blk_rq_bytes(rq->next_rq);
+
 	/*
 	 * Just mark start time and set the started bit. Due to memory
 	 * ordering, we know we'll see the correct deadline as long as
@@ -378,7 +400,7 @@ static void blk_mq_start_request(struct request *rq, bool last)
 		rq->cmd_flags |= REQ_END;
 }
 
-static void blk_mq_requeue_request(struct request *rq)
+static void __blk_mq_requeue_request(struct request *rq)
 {
 	struct request_queue *q = rq->q;
 
@@ -391,6 +413,26 @@ static void blk_mq_requeue_request(struct request *rq)
 		rq->nr_phys_segments--;
 }
 
+void blk_mq_requeue_request(struct request *rq)
+{
+	struct request_queue *q = rq->q;
+
+	__blk_mq_requeue_request(rq);
+	blk_clear_rq_complete(rq);
+
+	trace_block_rq_requeue(q, rq);
+
+	BUG_ON(blk_queued_rq(rq));
+	blk_mq_insert_request(rq, true, true, false);
+}
+EXPORT_SYMBOL(blk_mq_requeue_request);
+
+struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag)
+{
+	return tags->rqs[tag];
+}
+EXPORT_SYMBOL(blk_mq_tag_to_rq);
+
 struct blk_mq_timeout_data {
 	struct blk_mq_hw_ctx *hctx;
 	unsigned long *next;
@@ -412,12 +454,13 @@ static void blk_mq_timeout_check(void *__data, unsigned long *free_tags)
 	do {
 		struct request *rq;
 
-		tag = find_next_zero_bit(free_tags, hctx->queue_depth, tag);
-		if (tag >= hctx->queue_depth)
+		tag = find_next_zero_bit(free_tags, hctx->tags->nr_tags, tag);
+		if (tag >= hctx->tags->nr_tags)
 			break;
 
-		rq = hctx->rqs[tag++];
-
+		rq = blk_mq_tag_to_rq(hctx->tags, tag++);
+		if (rq->q != hctx->queue)
+			continue;
 		if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags))
 			continue;
 
@@ -514,6 +557,8 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
 	LIST_HEAD(rq_list);
 	int bit, queued;
 
+	WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask));
+
 	if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
 		return;
 
@@ -571,7 +616,7 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
 			 * time
 			 */
 			list_add(&rq->queuelist, &rq_list);
-			blk_mq_requeue_request(rq);
+			__blk_mq_requeue_request(rq);
 			break;
 		default:
 			pr_err("blk-mq: bad return on queue: %d\n", ret);
@@ -606,12 +651,21 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
 	if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
 		return;
 
-	if (!async)
+	if (!async && cpumask_test_cpu(smp_processor_id(), hctx->cpumask))
 		__blk_mq_run_hw_queue(hctx);
+	else if (hctx->queue->nr_hw_queues == 1)
+		kblockd_schedule_delayed_work(&hctx->run_work, 0);
 	else {
-		struct request_queue *q = hctx->queue;
+		unsigned int cpu;
 
-		kblockd_schedule_delayed_work(q, &hctx->delayed_work, 0);
+		/*
+		 * It'd be great if the workqueue API had a way to pass
+		 * in a mask and had some smarts for more clever placement
+		 * than the first CPU. Or we could round-robin here. For now,
+		 * just queue on the first CPU.
+		 */
+		cpu = cpumask_first(hctx->cpumask);
+		kblockd_schedule_delayed_work_on(cpu, &hctx->run_work, 0);
 	}
 }
 
@@ -626,14 +680,17 @@ void blk_mq_run_queues(struct request_queue *q, bool async)
 		    test_bit(BLK_MQ_S_STOPPED, &hctx->state))
 			continue;
 
+		preempt_disable();
 		blk_mq_run_hw_queue(hctx, async);
+		preempt_enable();
 	}
 }
 EXPORT_SYMBOL(blk_mq_run_queues);
 
 void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx)
 {
-	cancel_delayed_work(&hctx->delayed_work);
+	cancel_delayed_work(&hctx->run_work);
+	cancel_delayed_work(&hctx->delay_work);
 	set_bit(BLK_MQ_S_STOPPED, &hctx->state);
 }
 EXPORT_SYMBOL(blk_mq_stop_hw_queue);
@@ -651,11 +708,25 @@ EXPORT_SYMBOL(blk_mq_stop_hw_queues);
 void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx)
 {
 	clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
+
+	preempt_disable();
 	__blk_mq_run_hw_queue(hctx);
+	preempt_enable();
 }
 EXPORT_SYMBOL(blk_mq_start_hw_queue);
 
-void blk_mq_start_stopped_hw_queues(struct request_queue *q)
+void blk_mq_start_hw_queues(struct request_queue *q)
+{
+	struct blk_mq_hw_ctx *hctx;
+	int i;
+
+	queue_for_each_hw_ctx(q, hctx, i)
+		blk_mq_start_hw_queue(hctx);
+}
+EXPORT_SYMBOL(blk_mq_start_hw_queues);
+
+
+void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async)
 {
 	struct blk_mq_hw_ctx *hctx;
 	int i;
@@ -665,19 +736,53 @@ void blk_mq_start_stopped_hw_queues(struct request_queue *q)
 			continue;
 
 		clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
-		blk_mq_run_hw_queue(hctx, true);
+		preempt_disable();
+		blk_mq_run_hw_queue(hctx, async);
+		preempt_enable();
 	}
 }
 EXPORT_SYMBOL(blk_mq_start_stopped_hw_queues);
 
-static void blk_mq_work_fn(struct work_struct *work)
+static void blk_mq_run_work_fn(struct work_struct *work)
 {
 	struct blk_mq_hw_ctx *hctx;
 
-	hctx = container_of(work, struct blk_mq_hw_ctx, delayed_work.work);
+	hctx = container_of(work, struct blk_mq_hw_ctx, run_work.work);
+
 	__blk_mq_run_hw_queue(hctx);
 }
 
+static void blk_mq_delay_work_fn(struct work_struct *work)
+{
+	struct blk_mq_hw_ctx *hctx;
+
+	hctx = container_of(work, struct blk_mq_hw_ctx, delay_work.work);
+
+	if (test_and_clear_bit(BLK_MQ_S_STOPPED, &hctx->state))
+		__blk_mq_run_hw_queue(hctx);
+}
+
+void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
+{
+	unsigned long tmo = msecs_to_jiffies(msecs);
+
+	if (hctx->queue->nr_hw_queues == 1)
+		kblockd_schedule_delayed_work(&hctx->delay_work, tmo);
+	else {
+		unsigned int cpu;
+
+		/*
+		 * It'd be great if the workqueue API had a way to pass
+		 * in a mask and had some smarts for more clever placement
+		 * than the first CPU. Or we could round-robin here. For now,
+		 * just queue on the first CPU.
+		 */
+		cpu = cpumask_first(hctx->cpumask);
+		kblockd_schedule_delayed_work_on(cpu, &hctx->delay_work, tmo);
+	}
+}
+EXPORT_SYMBOL(blk_mq_delay_queue);
+
 static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx,
 				    struct request *rq, bool at_head)
 {
@@ -719,10 +824,10 @@ void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
 		spin_unlock(&ctx->lock);
 	}
 
-	blk_mq_put_ctx(current_ctx);
-
 	if (run_queue)
 		blk_mq_run_hw_queue(hctx, async);
+
+	blk_mq_put_ctx(current_ctx);
 }
 
 static void blk_mq_insert_requests(struct request_queue *q,
@@ -758,9 +863,8 @@ static void blk_mq_insert_requests(struct request_queue *q,
 	}
 	spin_unlock(&ctx->lock);
 
-	blk_mq_put_ctx(current_ctx);
-
 	blk_mq_run_hw_queue(hctx, from_schedule);
+	blk_mq_put_ctx(current_ctx);
 }
 
 static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b)
@@ -879,7 +983,6 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
 	if (unlikely(is_flush_fua)) {
 		blk_mq_bio_to_request(rq, bio);
-		blk_mq_put_ctx(ctx);
 		blk_insert_flush(rq);
 		goto run_queue;
 	}
@@ -917,7 +1020,6 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
 	}
 
 	spin_unlock(&ctx->lock);
-	blk_mq_put_ctx(ctx);
 
 	/*
 	 * For a SYNC request, send it to the hardware immediately. For an
@@ -926,6 +1028,7 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
 	 */
 run_queue:
 	blk_mq_run_hw_queue(hctx, !is_sync || is_flush_fua);
+	blk_mq_put_ctx(ctx);
 }
 
 /*
@@ -937,11 +1040,11 @@ struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q, const int cpu)
 }
 EXPORT_SYMBOL(blk_mq_map_queue);
 
-struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_reg *reg,
+struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *set,
 						   unsigned int hctx_index)
 {
 	return kmalloc_node(sizeof(struct blk_mq_hw_ctx),
-				GFP_KERNEL | __GFP_ZERO, reg->numa_node);
+				GFP_KERNEL | __GFP_ZERO, set->numa_node);
 }
 EXPORT_SYMBOL(blk_mq_alloc_single_hw_queue);
 
@@ -993,90 +1096,36 @@ static void blk_mq_hctx_notify(void *data, unsigned long action,
 	blk_mq_hctx_mark_pending(hctx, ctx);
 
 	spin_unlock(&ctx->lock);
-	blk_mq_put_ctx(ctx);
 
 	blk_mq_run_hw_queue(hctx, true);
+	blk_mq_put_ctx(ctx);
 }
 
-static int blk_mq_init_hw_commands(struct blk_mq_hw_ctx *hctx,
-				   int (*init)(void *, struct blk_mq_hw_ctx *,
-					struct request *, unsigned int),
-				   void *data)
-{
-	unsigned int i;
-	int ret = 0;
-
-	for (i = 0; i < hctx->queue_depth; i++) {
-		struct request *rq = hctx->rqs[i];
-
-		ret = init(data, hctx, rq, i);
-		if (ret)
-			break;
-	}
-
-	return ret;
-}
-
-int blk_mq_init_commands(struct request_queue *q,
-			 int (*init)(void *, struct blk_mq_hw_ctx *,
-					struct request *, unsigned int),
-			 void *data)
-{
-	struct blk_mq_hw_ctx *hctx;
-	unsigned int i;
-	int ret = 0;
-
-	queue_for_each_hw_ctx(q, hctx, i) {
-		ret = blk_mq_init_hw_commands(hctx, init, data);
-		if (ret)
-			break;
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(blk_mq_init_commands);
-
-static void blk_mq_free_hw_commands(struct blk_mq_hw_ctx *hctx,
-				    void (*free)(void *, struct blk_mq_hw_ctx *,
-					struct request *, unsigned int),
-				    void *data)
+static void blk_mq_free_rq_map(struct blk_mq_tag_set *set,
+		struct blk_mq_tags *tags, unsigned int hctx_idx)
 {
-	unsigned int i;
+	struct page *page;
 
-	for (i = 0; i < hctx->queue_depth; i++) {
-		struct request *rq = hctx->rqs[i];
+	if (tags->rqs && set->ops->exit_request) {
+		int i;
 
-		free(data, hctx, rq, i);
+		for (i = 0; i < tags->nr_tags; i++) {
+			if (!tags->rqs[i])
+				continue;
+			set->ops->exit_request(set->driver_data, tags->rqs[i],
+						hctx_idx, i);
+		}
 	}
-}
-
-void blk_mq_free_commands(struct request_queue *q,
-			  void (*free)(void *, struct blk_mq_hw_ctx *,
-					struct request *, unsigned int),
-			  void *data)
-{
-	struct blk_mq_hw_ctx *hctx;
-	unsigned int i;
-
-	queue_for_each_hw_ctx(q, hctx, i)
-		blk_mq_free_hw_commands(hctx, free, data);
-}
-EXPORT_SYMBOL(blk_mq_free_commands);
-
-static void blk_mq_free_rq_map(struct blk_mq_hw_ctx *hctx)
-{
-	struct page *page;
 
-	while (!list_empty(&hctx->page_list)) {
-		page = list_first_entry(&hctx->page_list, struct page, lru);
+	while (!list_empty(&tags->page_list)) {
+		page = list_first_entry(&tags->page_list, struct page, lru);
 		list_del_init(&page->lru);
 		__free_pages(page, page->private);
 	}
 
-	kfree(hctx->rqs);
+	kfree(tags->rqs);
 
-	if (hctx->tags)
-		blk_mq_free_tags(hctx->tags);
+	blk_mq_free_tags(tags);
 }
 
 static size_t order_to_size(unsigned int order)
@@ -1089,28 +1138,36 @@ static size_t order_to_size(unsigned int order)
 	return ret;
 }
 
-static int blk_mq_init_rq_map(struct blk_mq_hw_ctx *hctx,
-			      unsigned int reserved_tags, int node)
+static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
+		unsigned int hctx_idx)
 {
+	struct blk_mq_tags *tags;
 	unsigned int i, j, entries_per_page, max_order = 4;
 	size_t rq_size, left;
 
-	INIT_LIST_HEAD(&hctx->page_list);
+	tags = blk_mq_init_tags(set->queue_depth, set->reserved_tags,
+				set->numa_node);
+	if (!tags)
+		return NULL;
 
-	hctx->rqs = kmalloc_node(hctx->queue_depth * sizeof(struct request *),
-					GFP_KERNEL, node);
-	if (!hctx->rqs)
-		return -ENOMEM;
+	INIT_LIST_HEAD(&tags->page_list);
+
+	tags->rqs = kmalloc_node(set->queue_depth * sizeof(struct request *),
+					GFP_KERNEL, set->numa_node);
+	if (!tags->rqs) {
+		blk_mq_free_tags(tags);
+		return NULL;
+	}
 
 	/*
 	 * rq_size is the size of the request plus driver payload, rounded
 	 * to the cacheline size
 	 */
-	rq_size = round_up(sizeof(struct request) + hctx->cmd_size,
+	rq_size = round_up(sizeof(struct request) + set->cmd_size,
 				cache_line_size());
-	left = rq_size * hctx->queue_depth;
+	left = rq_size * set->queue_depth;
 
-	for (i = 0; i < hctx->queue_depth;) {
+	for (i = 0; i < set->queue_depth; ) {
 		int this_order = max_order;
 		struct page *page;
 		int to_do;
@@ -1120,7 +1177,8 @@ static int blk_mq_init_rq_map(struct blk_mq_hw_ctx *hctx,
 			this_order--;
 
 		do {
-			page = alloc_pages_node(node, GFP_KERNEL, this_order);
+			page = alloc_pages_node(set->numa_node, GFP_KERNEL,
+						this_order);
 			if (page)
 				break;
 			if (!this_order--)
@@ -1130,43 +1188,39 @@ static int blk_mq_init_rq_map(struct blk_mq_hw_ctx *hctx,
 		} while (1);
 
 		if (!page)
-			break;
+			goto fail;
 
 		page->private = this_order;
-		list_add_tail(&page->lru, &hctx->page_list);
+		list_add_tail(&page->lru, &tags->page_list);
 
 		p = page_address(page);
 		entries_per_page = order_to_size(this_order) / rq_size;
-		to_do = min(entries_per_page, hctx->queue_depth - i);
+		to_do = min(entries_per_page, set->queue_depth - i);
 		left -= to_do * rq_size;
 		for (j = 0; j < to_do; j++) {
-			hctx->rqs[i] = p;
-			blk_mq_rq_init(hctx, hctx->rqs[i]);
+			tags->rqs[i] = p;
+			if (set->ops->init_request) {
+				if (set->ops->init_request(set->driver_data,
+						tags->rqs[i], hctx_idx, i,
+						set->numa_node))
+					goto fail;
+			}
+
 			p += rq_size;
 			i++;
 		}
 	}
 
-	if (i < (reserved_tags + BLK_MQ_TAG_MIN))
-		goto err_rq_map;
-	else if (i != hctx->queue_depth) {
-		hctx->queue_depth = i;
-		pr_warn("%s: queue depth set to %u because of low memory\n",
-					__func__, i);
-	}
-
-	hctx->tags = blk_mq_init_tags(hctx->queue_depth, reserved_tags, node);
-	if (!hctx->tags) {
-err_rq_map:
-		blk_mq_free_rq_map(hctx);
-		return -ENOMEM;
-	}
+	return tags;
 
-	return 0;
+fail:
+	pr_warn("%s: failed to allocate requests\n", __func__);
+	blk_mq_free_rq_map(set, tags, hctx_idx);
+	return NULL;
 }
 
 static int blk_mq_init_hw_queues(struct request_queue *q,
-				 struct blk_mq_reg *reg, void *driver_data)
+		struct blk_mq_tag_set *set)
 {
 	struct blk_mq_hw_ctx *hctx;
 	unsigned int i, j;
@@ -1180,23 +1234,22 @@ static int blk_mq_init_hw_queues(struct request_queue *q,
 
 		node = hctx->numa_node;
 		if (node == NUMA_NO_NODE)
-			node = hctx->numa_node = reg->numa_node;
+			node = hctx->numa_node = set->numa_node;
 
-		INIT_DELAYED_WORK(&hctx->delayed_work, blk_mq_work_fn);
+		INIT_DELAYED_WORK(&hctx->run_work, blk_mq_run_work_fn);
+		INIT_DELAYED_WORK(&hctx->delay_work, blk_mq_delay_work_fn);
 		spin_lock_init(&hctx->lock);
 		INIT_LIST_HEAD(&hctx->dispatch);
 		hctx->queue = q;
 		hctx->queue_num = i;
-		hctx->flags = reg->flags;
-		hctx->queue_depth = reg->queue_depth;
-		hctx->cmd_size = reg->cmd_size;
+		hctx->flags = set->flags;
+		hctx->cmd_size = set->cmd_size;
 
 		blk_mq_init_cpu_notifier(&hctx->cpu_notifier,
 						blk_mq_hctx_notify, hctx);
 		blk_mq_register_cpu_notifier(&hctx->cpu_notifier);
 
-		if (blk_mq_init_rq_map(hctx, reg->reserved_tags, node))
-			break;
+		hctx->tags = set->tags[i];
 
 		/*
 		 * Allocate space for all possible cpus to avoid allocation in
@@ -1216,8 +1269,8 @@ static int blk_mq_init_hw_queues(struct request_queue *q,
 		hctx->nr_ctx_map = num_maps;
 		hctx->nr_ctx = 0;
 
-		if (reg->ops->init_hctx &&
-		    reg->ops->init_hctx(hctx, driver_data, i))
+		if (set->ops->init_hctx &&
+		    set->ops->init_hctx(hctx, set->driver_data, i))
 			break;
 	}
 
@@ -1231,11 +1284,10 @@ static int blk_mq_init_hw_queues(struct request_queue *q,
 		if (i == j)
 			break;
 
-		if (reg->ops->exit_hctx)
-			reg->ops->exit_hctx(hctx, j);
+		if (set->ops->exit_hctx)
+			set->ops->exit_hctx(hctx, j);
 
 		blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier);
-		blk_mq_free_rq_map(hctx);
 		kfree(hctx->ctxs);
 	}
 
@@ -1258,12 +1310,13 @@ static void blk_mq_init_cpu_queues(struct request_queue *q,
 		__ctx->queue = q;
 
 		/* If the cpu isn't online, the cpu is mapped to first hctx */
-		hctx = q->mq_ops->map_queue(q, i);
-		hctx->nr_ctx++;
-
 		if (!cpu_online(i))
 			continue;
 
+		hctx = q->mq_ops->map_queue(q, i);
+		cpumask_set_cpu(i, hctx->cpumask);
+		hctx->nr_ctx++;
+
 		/*
 		 * Set local node, IFF we have more than one hw queue. If
 		 * not, we remain on the home node of the device
@@ -1280,6 +1333,7 @@ static void blk_mq_map_swqueue(struct request_queue *q)
 	struct blk_mq_ctx *ctx;
 
 	queue_for_each_hw_ctx(q, hctx, i) {
+		cpumask_clear(hctx->cpumask);
 		hctx->nr_ctx = 0;
 	}
 
@@ -1288,59 +1342,50 @@ static void blk_mq_map_swqueue(struct request_queue *q)
 	 */
 	queue_for_each_ctx(q, ctx, i) {
 		/* If the cpu isn't online, the cpu is mapped to first hctx */
+		if (!cpu_online(i))
+			continue;
+
 		hctx = q->mq_ops->map_queue(q, i);
+		cpumask_set_cpu(i, hctx->cpumask);
 		ctx->index_hw = hctx->nr_ctx;
 		hctx->ctxs[hctx->nr_ctx++] = ctx;
 	}
 }
 
-struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg,
-					void *driver_data)
+struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
 {
 	struct blk_mq_hw_ctx **hctxs;
 	struct blk_mq_ctx *ctx;
 	struct request_queue *q;
 	int i;
 
-	if (!reg->nr_hw_queues ||
-	    !reg->ops->queue_rq || !reg->ops->map_queue ||
-	    !reg->ops->alloc_hctx || !reg->ops->free_hctx)
-		return ERR_PTR(-EINVAL);
-
-	if (!reg->queue_depth)
-		reg->queue_depth = BLK_MQ_MAX_DEPTH;
-	else if (reg->queue_depth > BLK_MQ_MAX_DEPTH) {
-		pr_err("blk-mq: queuedepth too large (%u)\n", reg->queue_depth);
-		reg->queue_depth = BLK_MQ_MAX_DEPTH;
-	}
-
-	if (reg->queue_depth < (reg->reserved_tags + BLK_MQ_TAG_MIN))
-		return ERR_PTR(-EINVAL);
-
 	ctx = alloc_percpu(struct blk_mq_ctx);
 	if (!ctx)
 		return ERR_PTR(-ENOMEM);
 
-	hctxs = kmalloc_node(reg->nr_hw_queues * sizeof(*hctxs), GFP_KERNEL,
-			reg->numa_node);
+	hctxs = kmalloc_node(set->nr_hw_queues * sizeof(*hctxs), GFP_KERNEL,
+			set->numa_node);
 
 	if (!hctxs)
 		goto err_percpu;
 
-	for (i = 0; i < reg->nr_hw_queues; i++) {
-		hctxs[i] = reg->ops->alloc_hctx(reg, i);
+	for (i = 0; i < set->nr_hw_queues; i++) {
+		hctxs[i] = set->ops->alloc_hctx(set, i);
 		if (!hctxs[i])
 			goto err_hctxs;
 
+		if (!zalloc_cpumask_var(&hctxs[i]->cpumask, GFP_KERNEL))
+			goto err_hctxs;
+
 		hctxs[i]->numa_node = NUMA_NO_NODE;
 		hctxs[i]->queue_num = i;
 	}
 
-	q = blk_alloc_queue_node(GFP_KERNEL, reg->numa_node);
+	q = blk_alloc_queue_node(GFP_KERNEL, set->numa_node);
 	if (!q)
 		goto err_hctxs;
 
-	q->mq_map = blk_mq_make_queue_map(reg);
+	q->mq_map = blk_mq_make_queue_map(set);
 	if (!q->mq_map)
 		goto err_map;
 
@@ -1348,33 +1393,34 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg,
 	blk_queue_rq_timeout(q, 30000);
 
 	q->nr_queues = nr_cpu_ids;
-	q->nr_hw_queues = reg->nr_hw_queues;
+	q->nr_hw_queues = set->nr_hw_queues;
 
 	q->queue_ctx = ctx;
 	q->queue_hw_ctx = hctxs;
 
-	q->mq_ops = reg->ops;
+	q->mq_ops = set->ops;
 	q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;
 
 	q->sg_reserved_size = INT_MAX;
 
 	blk_queue_make_request(q, blk_mq_make_request);
-	blk_queue_rq_timed_out(q, reg->ops->timeout);
-	if (reg->timeout)
-		blk_queue_rq_timeout(q, reg->timeout);
+	blk_queue_rq_timed_out(q, set->ops->timeout);
+	if (set->timeout)
+		blk_queue_rq_timeout(q, set->timeout);
 
-	if (reg->ops->complete)
-		blk_queue_softirq_done(q, reg->ops->complete);
+	if (set->ops->complete)
+		blk_queue_softirq_done(q, set->ops->complete);
 
 	blk_mq_init_flush(q);
-	blk_mq_init_cpu_queues(q, reg->nr_hw_queues);
+	blk_mq_init_cpu_queues(q, set->nr_hw_queues);
 
-	q->flush_rq = kzalloc(round_up(sizeof(struct request) + reg->cmd_size,
-				cache_line_size()), GFP_KERNEL);
+	q->flush_rq = kzalloc(round_up(sizeof(struct request) +
+				set->cmd_size, cache_line_size()),
+				GFP_KERNEL);
 	if (!q->flush_rq)
 		goto err_hw;
 
-	if (blk_mq_init_hw_queues(q, reg, driver_data))
+	if (blk_mq_init_hw_queues(q, set))
 		goto err_flush_rq;
 
 	blk_mq_map_swqueue(q);
@@ -1392,10 +1438,11 @@ err_hw:
 err_map:
 	blk_cleanup_queue(q);
 err_hctxs:
-	for (i = 0; i < reg->nr_hw_queues; i++) {
+	for (i = 0; i < set->nr_hw_queues; i++) {
 		if (!hctxs[i])
 			break;
-		reg->ops->free_hctx(hctxs[i], i);
+		free_cpumask_var(hctxs[i]->cpumask);
+		set->ops->free_hctx(hctxs[i], i);
 	}
 	kfree(hctxs);
 err_percpu:
@@ -1412,10 +1459,10 @@ void blk_mq_free_queue(struct request_queue *q)
 	queue_for_each_hw_ctx(q, hctx, i) {
 		kfree(hctx->ctx_map);
 		kfree(hctx->ctxs);
-		blk_mq_free_rq_map(hctx);
 		blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier);
 		if (q->mq_ops->exit_hctx)
 			q->mq_ops->exit_hctx(hctx, i);
+		free_cpumask_var(hctx->cpumask);
 		q->mq_ops->free_hctx(hctx, i);
 	}
 
@@ -1472,6 +1519,53 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
 	return NOTIFY_OK;
 }
 
+int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
+{
+	int i;
+
+	if (!set->nr_hw_queues)
+		return -EINVAL;
+	if (!set->queue_depth || set->queue_depth > BLK_MQ_MAX_DEPTH)
+		return -EINVAL;
+	if (set->queue_depth < set->reserved_tags + BLK_MQ_TAG_MIN)
+		return -EINVAL;
+
+	if (!set->nr_hw_queues ||
+	    !set->ops->queue_rq || !set->ops->map_queue ||
+	    !set->ops->alloc_hctx || !set->ops->free_hctx)
+		return -EINVAL;
+
+
+	set->tags = kmalloc_node(set->nr_hw_queues * sizeof(struct blk_mq_tags),
+				 GFP_KERNEL, set->numa_node);
+	if (!set->tags)
+		goto out;
+
+	for (i = 0; i < set->nr_hw_queues; i++) {
+		set->tags[i] = blk_mq_init_rq_map(set, i);
+		if (!set->tags[i])
+			goto out_unwind;
+	}
+
+	return 0;
+
+out_unwind:
+	while (--i >= 0)
+		blk_mq_free_rq_map(set, set->tags[i], i);
+out:
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(blk_mq_alloc_tag_set);
+
+void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
+{
+	int i;
+
+	for (i = 0; i < set->nr_hw_queues; i++)
+		blk_mq_free_rq_map(set, set->tags[i], i);
+}
+EXPORT_SYMBOL(blk_mq_free_tag_set);
+
 void blk_mq_disable_hotplug(void)
 {
 	mutex_lock(&all_q_mutex);
diff --git a/block/blk-mq.h b/block/blk-mq.h
index ebbe6bac9d61..5fa14f19f752 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -1,6 +1,8 @@
 #ifndef INT_BLK_MQ_H
 #define INT_BLK_MQ_H
 
+struct blk_mq_tag_set;
+
 struct blk_mq_ctx {
 	struct {
 		spinlock_t		lock;
@@ -27,7 +29,8 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
 void blk_mq_init_flush(struct request_queue *q);
 void blk_mq_drain_queue(struct request_queue *q);
 void blk_mq_free_queue(struct request_queue *q);
-void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq);
+void blk_mq_clone_flush_request(struct request *flush_rq,
+		struct request *orig_rq);
 
 /*
  * CPU hotplug helpers
@@ -45,8 +48,7 @@ void blk_mq_disable_hotplug(void);
 /*
  * CPU -> queue mappings
  */
-struct blk_mq_reg;
-extern unsigned int *blk_mq_make_queue_map(struct blk_mq_reg *reg);
+extern unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set);
 extern int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues);
 
 void blk_mq_add_timer(struct request *rq);
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index d96f7061c6fd..a09e8af8186c 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -199,8 +199,19 @@ void __blk_add_timer(struct request *req, struct list_head *timeout_list)
 	expiry = round_jiffies_up(req->deadline);
 
 	if (!timer_pending(&q->timeout) ||
-	    time_before(expiry, q->timeout.expires))
-		mod_timer(&q->timeout, expiry);
+	    time_before(expiry, q->timeout.expires)) {
+		unsigned long diff = q->timeout.expires - expiry;
+
+		/*
+		 * Due to added timer slack to group timers, the timer
+		 * will often be a little in front of what we asked for.
+		 * So apply some tolerance here too, otherwise we keep
+		 * modifying the timer because expires for value X
+		 * will be X + something.
+		 */
+		if (diff >= HZ / 2)
+			mod_timer(&q->timeout, expiry);
+	}
 
 }
 
diff --git a/block/bsg.c b/block/bsg.c
index 420a5a9f1b23..e5214c148096 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -1008,7 +1008,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
 	/*
 	 * we need a proper transport to send commands, not a stacked device
 	 */
-	if (!q->request_fn)
+	if (!queue_is_rq_based(q))
 		return 0;
 
 	bcd = &q->bsg_dev;
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index e0985f1955e7..5063a0bd831a 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -908,7 +908,7 @@ static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
 {
 	if (cfqd->busy_queues) {
 		cfq_log(cfqd, "schedule dispatch");
-		kblockd_schedule_work(cfqd->queue, &cfqd->unplug_work);
+		kblockd_schedule_work(&cfqd->unplug_work);
 	}
 }
 
diff --git a/block/genhd.c b/block/genhd.c
index 791f41943132..7bd4372e8b6f 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -849,7 +849,7 @@ static int show_partition(struct seq_file *seqf, void *v)
 	char buf[BDEVNAME_SIZE];
 
 	/* Don't show non-partitionable removeable devices or empty devices */
-	if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
+	if (!get_capacity(sgp) || (!(disk_max_parts(sgp) > 1) &&
 				   (sgp->flags & GENHD_FL_REMOVABLE)))
 		return 0;
 	if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 3db83dbba1d9..3c95bda11d51 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -487,10 +487,15 @@ static struct hash_testvec crct10dif_tv_template[] = {
  * SHA1 test vectors  from from FIPS PUB 180-1
  * Long vector from CAVS 5.0
  */
-#define SHA1_TEST_VECTORS	3
+#define SHA1_TEST_VECTORS	6
 
 static struct hash_testvec sha1_tv_template[] = {
 	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55"
+			  "\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09",
+	}, {
 		.plaintext = "abc",
 		.psize	= 3,
 		.digest	= "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e"
@@ -529,6 +534,144 @@ static struct hash_testvec sha1_tv_template[] = {
 			  "\x45\x9c\x02\xb6\x9b\x4a\xa8\xf5\x82\x17",
 		.np	= 4,
 		.tap	= { 63, 64, 31, 5 }
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+		.psize	= 64,
+		.digest = "\xc8\x71\xf6\x9a\x63\xcc\xa9\x84\x84\x82"
+			  "\x64\xe7\x79\x95\x5d\xd7\x19\x41\x7c\x91",
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\xb8\xe3\x54\xed\xc5\xfc\xef\xa4"
+			     "\x55\x73\x4a\x81\x99\xe4\x47\x2a"
+			     "\x30\xd6\xc9\x85",
 	}
 };
 
@@ -536,10 +679,17 @@ static struct hash_testvec sha1_tv_template[] = {
 /*
  * SHA224 test vectors from from FIPS PUB 180-2
  */
-#define SHA224_TEST_VECTORS     2
+#define SHA224_TEST_VECTORS     5
 
 static struct hash_testvec sha224_tv_template[] = {
 	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= "\xd1\x4a\x02\x8c\x2a\x3a\x2b\xc9"
+			  "\x47\x61\x02\xbb\x28\x82\x34\xc4"
+			  "\x15\xa2\xb0\x1f\x82\x8e\xa6\x2a"
+			  "\xc5\xb3\xe4\x2f",
+	}, {
 		.plaintext = "abc",
 		.psize  = 3,
 		.digest = "\x23\x09\x7D\x22\x34\x05\xD8\x22"
@@ -556,16 +706,164 @@ static struct hash_testvec sha224_tv_template[] = {
 			  "\x52\x52\x25\x25",
 		.np     = 2,
 		.tap    = { 28, 28 }
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+		.psize	= 64,
+		.digest = "\xc4\xdb\x2b\x3a\x58\xc3\x99\x01"
+			  "\x42\xfd\x10\x92\xaa\x4e\x04\x08"
+			  "\x58\xbb\xbb\xe8\xf8\x14\xa7\x0c"
+			  "\xef\x3b\xcb\x0e",
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\x98\x43\x07\x63\x75\xe0\xa7\x1c"
+			     "\x78\xb1\x8b\xfd\x04\xf5\x2d\x91"
+			     "\x20\x48\xa4\x28\xff\x55\xb1\xd3"
+			     "\xe6\xf9\x4f\xcc",
 	}
 };
 
 /*
  * SHA256 test vectors from from NIST
  */
-#define SHA256_TEST_VECTORS	2
+#define SHA256_TEST_VECTORS	5
 
 static struct hash_testvec sha256_tv_template[] = {
 	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14"
+			  "\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24"
+			  "\x27\xae\x41\xe4\x64\x9b\x93\x4c"
+			  "\xa4\x95\x99\x1b\x78\x52\xb8\x55",
+	}, {
 		.plaintext = "abc",
 		.psize	= 3,
 		.digest	= "\xba\x78\x16\xbf\x8f\x01\xcf\xea"
@@ -581,16 +879,166 @@ static struct hash_testvec sha256_tv_template[] = {
 			  "\xf6\xec\xed\xd4\x19\xdb\x06\xc1",
 		.np	= 2,
 		.tap	= { 28, 28 }
-	},
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+		.psize	= 64,
+		.digest = "\xb5\xfe\xad\x56\x7d\xff\xcb\xa4"
+			  "\x2c\x32\x29\x32\x19\xbb\xfb\xfa"
+			  "\xd6\xff\x94\xa3\x72\x91\x85\x66"
+			  "\x3b\xa7\x87\x77\x58\xa3\x40\x3a",
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\xc5\xce\x0c\xca\x01\x4f\x53\x3a"
+			     "\x32\x32\x17\xcc\xd4\x6a\x71\xa9"
+			     "\xf3\xed\x50\x10\x64\x8e\x06\xbe"
+			     "\x9b\x4a\xa6\xbb\x05\x89\x59\x51",
+	}
 };
 
 /*
  * SHA384 test vectors from from NIST and kerneli
  */
-#define SHA384_TEST_VECTORS	4
+#define SHA384_TEST_VECTORS	6
 
 static struct hash_testvec sha384_tv_template[] = {
 	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= "\x38\xb0\x60\xa7\x51\xac\x96\x38"
+			  "\x4c\xd9\x32\x7e\xb1\xb1\xe3\x6a"
+			  "\x21\xfd\xb7\x11\x14\xbe\x07\x43"
+			  "\x4c\x0c\xc7\xbf\x63\xf6\xe1\xda"
+			  "\x27\x4e\xde\xbf\xe7\x6f\x65\xfb"
+			  "\xd5\x1a\xd2\xf1\x48\x98\xb9\x5b",
+	}, {
 		.plaintext= "abc",
 		.psize	= 3,
 		.digest	= "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b"
@@ -630,16 +1078,163 @@ static struct hash_testvec sha384_tv_template[] = {
 			  "\xc9\x38\xe2\xd1\x99\xe8\xbe\xa4",
 		.np	= 4,
 		.tap	= { 26, 26, 26, 26 }
-	},
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\x4d\x97\x23\xc8\xea\x7a\x7c\x15"
+			     "\xb8\xff\x97\x9c\xf5\x13\x4f\x31"
+			     "\xde\x67\xf7\x24\x73\xcd\x70\x1c"
+			     "\x03\x4a\xba\x8a\x87\x49\xfe\xdc"
+			     "\x75\x29\x62\x83\xae\x3f\x17\xab"
+			     "\xfd\x10\x4d\x8e\x17\x1c\x1f\xca",
+	}
 };
 
 /*
  * SHA512 test vectors from from NIST and kerneli
  */
-#define SHA512_TEST_VECTORS	4
+#define SHA512_TEST_VECTORS	6
 
 static struct hash_testvec sha512_tv_template[] = {
 	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd"
+			  "\xf1\x54\x28\x50\xd6\x6d\x80\x07"
+			  "\xd6\x20\xe4\x05\x0b\x57\x15\xdc"
+			  "\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
+			  "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0"
+			  "\xff\x83\x18\xd2\x87\x7e\xec\x2f"
+			  "\x63\xb9\x31\xbd\x47\x41\x7a\x81"
+			  "\xa5\x38\x32\x7a\xf9\x27\xda\x3e",
+	}, {
 		.plaintext = "abc",
 		.psize	= 3,
 		.digest	= "\xdd\xaf\x35\xa1\x93\x61\x7a\xba"
@@ -687,7 +1282,145 @@ static struct hash_testvec sha512_tv_template[] = {
 			  "\xed\xb4\x19\x87\x23\x28\x50\xc9",
 		.np	= 4,
 		.tap	= { 26, 26, 26, 26 }
-	},
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\x76\xc9\xd4\x91\x7a\x5f\x0f\xaa"
+			     "\x13\x39\xf3\x01\x7a\xfa\xe5\x41"
+			     "\x5f\x0b\xf8\xeb\x32\xfc\xbf\xb0"
+			     "\xfa\x8c\xcd\x17\x83\xe2\xfa\xeb"
+			     "\x1c\x19\xde\xe2\x75\xdc\x34\x64"
+			     "\x5f\x35\x9c\x61\x2f\x10\xf9\xec"
+			     "\x59\xca\x9d\xcc\x25\x0c\x43\xba"
+			     "\x85\xa8\xf8\xfe\xb5\x24\xb2\xee",
+	}
 };
 
 
@@ -12844,7 +13577,7 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
 #define AES_GCM_4106_DEC_TEST_VECTORS 7
 #define AES_GCM_4543_ENC_TEST_VECTORS 1
 #define AES_GCM_4543_DEC_TEST_VECTORS 2
-#define AES_CCM_ENC_TEST_VECTORS 7
+#define AES_CCM_ENC_TEST_VECTORS 8
 #define AES_CCM_DEC_TEST_VECTORS 7
 #define AES_CCM_4309_ENC_TEST_VECTORS 7
 #define AES_CCM_4309_DEC_TEST_VECTORS 10
@@ -18746,7 +19479,29 @@ static struct aead_testvec aes_ccm_enc_tv_template[] = {
 			  "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6"
 			  "\xba",
 		.rlen	= 33,
-	},
+	}, {
+		/*
+		 * This is the same vector as aes_ccm_rfc4309_enc_tv_template[0]
+		 * below but rewritten to use the ccm algorithm directly.
+		 */
+		.key	= "\x83\xac\x54\x66\xc2\xeb\xe5\x05"
+			  "\x2e\x01\xd1\xfc\x5d\x82\x66\x2e",
+		.klen	= 16,
+		.iv	= "\x03\x96\xac\x59\x30\x07\xa1\xe2\xa2\xc7\x55\x24\0\0\0\0",
+		.alen	= 0,
+		.input	= "\x19\xc8\x81\xf6\xe9\x86\xff\x93"
+			  "\x0b\x78\x67\xe5\xbb\xb7\xfc\x6e"
+			  "\x83\x77\xb3\xa6\x0c\x8c\x9f\x9c"
+			  "\x35\x2e\xad\xe0\x62\xf9\x91\xa1",
+		.ilen	= 32,
+		.result	= "\xab\x6f\xe1\x69\x1d\x19\x99\xa8"
+			  "\x92\xa0\xc4\x6f\x7e\xe2\x8b\xb1"
+			  "\x70\xbb\x8c\xa6\x4c\x6e\x97\x8a"
+			  "\x57\x2b\xbe\x5d\x98\xa6\xb1\x32"
+			  "\xda\x24\xea\xd9\xa1\x39\x98\xfd"
+			  "\xa4\xbe\xd9\xf2\x1a\x6d\x22\xa8",
+		.rlen	= 48,
+	}
 };
 
 static struct aead_testvec aes_ccm_dec_tv_template[] = {
diff --git a/drivers/Makefile b/drivers/Makefile
index e3ced91b1784..d05d81b19b50 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -53,8 +53,8 @@ obj-y				+= gpu/
 obj-$(CONFIG_CONNECTOR)		+= connector/
 
 # i810fb and intelfb depend on char/agp/
-obj-$(CONFIG_FB_I810)           += video/i810/
-obj-$(CONFIG_FB_INTEL)          += video/intelfb/
+obj-$(CONFIG_FB_I810)           += video/fbdev/i810/
+obj-$(CONFIG_FB_INTEL)          += video/fbdev/intelfb/
 
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-y				+= base/ block/ misc/ mfd/ nfc/
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 20e03a7eb8b4..c2706047337f 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -116,7 +116,7 @@ config AHCI_ST
 
 config AHCI_IMX
 	tristate "Freescale i.MX AHCI SATA support"
-	depends on MFD_SYSCON
+	depends on MFD_SYSCON && (ARCH_MXC || COMPILE_TEST)
 	help
 	  This option enables support for the Freescale i.MX SoC's
 	  onboard AHCI SATA.
@@ -134,8 +134,7 @@ config AHCI_SUNXI
 
 config AHCI_XGENE
 	tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
-	depends on ARM64 || COMPILE_TEST
-	select PHY_XGENE
+	depends on PHY_XGENE
 	help
 	 This option enables support for APM X-Gene SoC SATA host controller.
 
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 5a0bf8ed649b..e45b18ee04c3 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1232,18 +1232,14 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
 		return rc;
 
 	for (i = 0; i < host->n_ports; i++) {
-		const char* desc;
 		struct ahci_port_priv *pp = host->ports[i]->private_data;
 
 		/* pp is NULL for dummy ports */
 		if (pp)
-			desc = pp->irq_desc;
-		else
-			desc = dev_driver_string(host->dev);
-
-		rc = devm_request_threaded_irq(host->dev,
-			irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
-			desc, host->ports[i]);
+			rc = devm_request_threaded_irq(host->dev,
+						       irq + i, ahci_hw_interrupt,
+						       ahci_thread_fn, IRQF_SHARED,
+						       pp->irq_desc, host->ports[i]);
 		if (rc)
 			goto out_free_irqs;
 	}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c19734d96d7e..0e4d8b5db7eb 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4224,8 +4224,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 	{ "PIONEER DVD-RW  DVR-216D",	NULL,	ATA_HORKAGE_NOSETXFER },
 
 	/* devices that don't properly handle queued TRIM commands */
-	{ "Micron_M500*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
-	{ "Crucial_CT???M500SSD*",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM, },
+	{ "Micron_M500*",		"MU0[1-4]*",	ATA_HORKAGE_NO_NCQ_TRIM, },
+	{ "Crucial_CT???M500SSD*",	"MU0[1-4]*",	ATA_HORKAGE_NO_NCQ_TRIM, },
+	{ "Micron_M550*",		NULL,		ATA_HORKAGE_NO_NCQ_TRIM, },
+	{ "Crucial_CT???M550SSD*",	NULL,		ATA_HORKAGE_NO_NCQ_TRIM, },
 
 	/*
 	 * Some WD SATA-I drives spin up and down erratically when the link
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index 6fac524c2f50..4edb1a81f63f 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -898,9 +898,12 @@ static int arasan_cf_probe(struct platform_device *pdev)
 
 	cf_card_detect(acdev, 0);
 
-	return ata_host_activate(host, acdev->irq, irq_handler, 0,
-			&arasan_cf_sht);
+	ret = ata_host_activate(host, acdev->irq, irq_handler, 0,
+				&arasan_cf_sht);
+	if (!ret)
+		return 0;
 
+	cf_exit(acdev);
 free_clk:
 	clk_put(acdev->clk);
 	return ret;
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index e9c87274a781..8a66f23af4c4 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -407,12 +407,13 @@ static int pata_at91_probe(struct platform_device *pdev)
 
 	host->private_data = info;
 
-	return ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
-			gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
-			irq_flags, &pata_at91_sht);
+	ret = ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
+				gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
+				irq_flags, &pata_at91_sht);
+	if (ret)
+		goto err_put;
 
-	if (!ret)
-		return 0;
+	return 0;
 
 err_put:
 	clk_put(info->mck);
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index 83c4ddb1bc7f..2a97d3a531ec 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -865,7 +865,7 @@ static int octeon_cf_probe(struct platform_device *pdev)
 	if (node == NULL)
 		return -EINVAL;
 
-	cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL);
+	cf_port = devm_kzalloc(&pdev->dev, sizeof(*cf_port), GFP_KERNEL);
 	if (!cf_port)
 		return -ENOMEM;
 
@@ -881,10 +881,9 @@ static int octeon_cf_probe(struct platform_device *pdev)
 	n_size = of_n_size_cells(node);
 
 	reg_prop = of_find_property(node, "reg", &reg_len);
-	if (!reg_prop || reg_len < sizeof(__be32)) {
-		rv = -EINVAL;
-		goto free_cf_port;
-	}
+	if (!reg_prop || reg_len < sizeof(__be32))
+		return -EINVAL;
+
 	cs_num = reg_prop->value;
 	cf_port->cs0 = be32_to_cpup(cs_num);
 
@@ -901,16 +900,13 @@ static int octeon_cf_probe(struct platform_device *pdev)
 				res_dma = platform_get_resource(dma_dev, IORESOURCE_MEM, 0);
 				if (!res_dma) {
 					of_node_put(dma_node);
-					rv = -EINVAL;
-					goto free_cf_port;
+					return -EINVAL;
 				}
 				cf_port->dma_base = (u64)devm_ioremap_nocache(&pdev->dev, res_dma->start,
 									 resource_size(res_dma));
-
 				if (!cf_port->dma_base) {
 					of_node_put(dma_node);
-					rv = -EINVAL;
-					goto free_cf_port;
+					return -EINVAL;
 				}
 
 				irq_handler = octeon_cf_interrupt;
@@ -921,41 +917,34 @@ static int octeon_cf_probe(struct platform_device *pdev)
 			of_node_put(dma_node);
 		}
 		res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (!res_cs1) {
-			rv = -EINVAL;
-			goto free_cf_port;
-		}
+		if (!res_cs1)
+			return -EINVAL;
+
 		cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,
 					   resource_size(res_cs1));
-
 		if (!cs1)
-			goto free_cf_port;
+			return rv;
+
+		if (reg_len < (n_addr + n_size + 1) * sizeof(__be32))
+			return -EINVAL;
 
-		if (reg_len < (n_addr + n_size + 1) * sizeof(__be32)) {
-			rv = -EINVAL;
-			goto free_cf_port;
-		}
 		cs_num += n_addr + n_size;
 		cf_port->cs1 = be32_to_cpup(cs_num);
 	}
 
 	res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	if (!res_cs0) {
-		rv = -EINVAL;
-		goto free_cf_port;
-	}
+	if (!res_cs0)
+		return -EINVAL;
 
 	cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start,
 				   resource_size(res_cs0));
-
 	if (!cs0)
-		goto free_cf_port;
+		return rv;
 
 	/* allocate host */
 	host = ata_host_alloc(&pdev->dev, 1);
 	if (!host)
-		goto free_cf_port;
+		return rv;
 
 	ap = host->ports[0];
 	ap->private_data = cf_port;
@@ -1020,17 +1009,12 @@ static int octeon_cf_probe(struct platform_device *pdev)
 
 	ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);
 
-
 	dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n",
 		 is_16bit ? 16 : 8,
 		 cf_port->is_true_ide ? ", True IDE" : "");
 
 	return ata_host_activate(host, irq, irq_handler,
 				 IRQF_SHARED, &octeon_cf_sht);
-
-free_cf_port:
-	kfree(cf_port);
-	return rv;
 }
 
 static void octeon_cf_shutdown(struct device *dev)
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index a79566d05666..0610e78c8a2a 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -594,9 +594,13 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, host);
 
-	return ata_host_activate(host, info->irq,
-			info->irq ? pata_s3c_irq : NULL,
-			0, &pata_s3c_sht);
+	ret = ata_host_activate(host, info->irq,
+				info->irq ? pata_s3c_irq : NULL,
+				0, &pata_s3c_sht);
+	if (ret)
+		goto stop_clk;
+
+	return 0;
 
 stop_clk:
 	clk_disable(info->clk);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 0dd65281cc65..20da3ad1696b 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(device_remove_bin_file);
 
-/**
- * device_schedule_callback_owner - helper to schedule a callback for a device
- * @dev: device.
- * @func: callback function to invoke later.
- * @owner: module owning the callback routine
- *
- * Attribute methods must not unregister themselves or their parent device
- * (which would amount to the same thing).  Attempts to do so will deadlock,
- * since unregistration is mutually exclusive with driver callbacks.
- *
- * Instead methods can call this routine, which will attempt to allocate
- * and schedule a workqueue request to call back @func with @dev as its
- * argument in the workqueue's process context.  @dev will be pinned until
- * @func returns.
- *
- * This routine is usually called via the inline device_schedule_callback(),
- * which automatically sets @owner to THIS_MODULE.
- *
- * Returns 0 if the request was submitted, -ENOMEM if storage could not
- * be allocated, -ENODEV if a reference to @owner isn't available.
- *
- * NOTE: This routine won't work if CONFIG_SYSFS isn't set!  It uses an
- * underlying sysfs routine (since it is intended for use by attribute
- * methods), and if sysfs isn't available you'll get nothing but -ENOSYS.
- */
-int device_schedule_callback_owner(struct device *dev,
-		void (*func)(struct device *), struct module *owner)
-{
-	return sysfs_schedule_callback(&dev->kobj,
-			(void (*)(void *)) func, dev, owner);
-}
-EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
-
 static void klist_children_get(struct klist_node *n)
 {
 	struct device_private *p = to_device_private_parent(n);
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 930cad4e5df8..6a7e4fa12854 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -23,16 +23,16 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
 static int regcache_rbtree_exit(struct regmap *map);
 
 struct regcache_rbtree_node {
-	/* the actual rbtree node holding this block */
-	struct rb_node node;
-	/* base register handled by this block */
-	unsigned int base_reg;
 	/* block of adjacent registers */
 	void *block;
 	/* Which registers are present */
 	long *cache_present;
+	/* base register handled by this block */
+	unsigned int base_reg;
 	/* number of registers available in the block */
 	unsigned int blklen;
+	/* the actual rbtree node holding this block */
+	struct rb_node node;
 } __attribute__ ((packed));
 
 struct regcache_rbtree_ctx {
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 1e03e7f8bacb..dff32c6b2474 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -66,12 +66,31 @@ static inline void regmap_mmio_count_check(size_t count)
 	BUG_ON(count % 2 != 0);
 }
 
+static inline unsigned int
+regmap_mmio_get_offset(const void *reg, size_t reg_size)
+{
+	switch (reg_size) {
+	case 1:
+		return *(u8 *)reg;
+	case 2:
+		return *(u16 *)reg;
+	case 4:
+		return *(u32 *)reg;
+#ifdef CONFIG_64BIT
+	case 8:
+		return *(u64 *)reg;
+#endif
+	default:
+		BUG();
+	}
+}
+
 static int regmap_mmio_gather_write(void *context,
 				    const void *reg, size_t reg_size,
 				    const void *val, size_t val_size)
 {
 	struct regmap_mmio_context *ctx = context;
-	u32 offset;
+	unsigned int offset;
 	int ret;
 
 	regmap_mmio_regsize_check(reg_size);
@@ -82,7 +101,7 @@ static int regmap_mmio_gather_write(void *context,
 			return ret;
 	}
 
-	offset = *(u32 *)reg;
+	offset = regmap_mmio_get_offset(reg, reg_size);
 
 	while (val_size) {
 		switch (ctx->val_bytes) {
@@ -118,7 +137,7 @@ static int regmap_mmio_gather_write(void *context,
 static int regmap_mmio_write(void *context, const void *data, size_t count)
 {
 	struct regmap_mmio_context *ctx = context;
-	u32 offset = ctx->reg_bytes + ctx->pad_bytes;
+	unsigned int offset = ctx->reg_bytes + ctx->pad_bytes;
 
 	regmap_mmio_count_check(count);
 
@@ -131,7 +150,7 @@ static int regmap_mmio_read(void *context,
 			    void *val, size_t val_size)
 {
 	struct regmap_mmio_context *ctx = context;
-	u32 offset;
+	unsigned int offset;
 	int ret;
 
 	regmap_mmio_regsize_check(reg_size);
@@ -142,7 +161,7 @@ static int regmap_mmio_read(void *context,
 			return ret;
 	}
 
-	offset = *(u32 *)reg;
+	offset = regmap_mmio_get_offset(reg, reg_size);
 
 	while (val_size) {
 		switch (ctx->val_bytes) {
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 63e30ef096e2..a1beffb4b066 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -192,6 +192,13 @@ static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
 	b[0] = cpu_to_be16(val << shift);
 }
 
+static void regmap_format_16_le(void *buf, unsigned int val, unsigned int shift)
+{
+	__le16 *b = buf;
+
+	b[0] = cpu_to_le16(val << shift);
+}
+
 static void regmap_format_16_native(void *buf, unsigned int val,
 				    unsigned int shift)
 {
@@ -216,6 +223,13 @@ static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
 	b[0] = cpu_to_be32(val << shift);
 }
 
+static void regmap_format_32_le(void *buf, unsigned int val, unsigned int shift)
+{
+	__le32 *b = buf;
+
+	b[0] = cpu_to_le32(val << shift);
+}
+
 static void regmap_format_32_native(void *buf, unsigned int val,
 				    unsigned int shift)
 {
@@ -240,6 +254,13 @@ static unsigned int regmap_parse_16_be(const void *buf)
 	return be16_to_cpu(b[0]);
 }
 
+static unsigned int regmap_parse_16_le(const void *buf)
+{
+	const __le16 *b = buf;
+
+	return le16_to_cpu(b[0]);
+}
+
 static void regmap_parse_16_be_inplace(void *buf)
 {
 	__be16 *b = buf;
@@ -247,6 +268,13 @@ static void regmap_parse_16_be_inplace(void *buf)
 	b[0] = be16_to_cpu(b[0]);
 }
 
+static void regmap_parse_16_le_inplace(void *buf)
+{
+	__le16 *b = buf;
+
+	b[0] = le16_to_cpu(b[0]);
+}
+
 static unsigned int regmap_parse_16_native(const void *buf)
 {
 	return *(u16 *)buf;
@@ -269,6 +297,13 @@ static unsigned int regmap_parse_32_be(const void *buf)
 	return be32_to_cpu(b[0]);
 }
 
+static unsigned int regmap_parse_32_le(const void *buf)
+{
+	const __le32 *b = buf;
+
+	return le32_to_cpu(b[0]);
+}
+
 static void regmap_parse_32_be_inplace(void *buf)
 {
 	__be32 *b = buf;
@@ -276,6 +311,13 @@ static void regmap_parse_32_be_inplace(void *buf)
 	b[0] = be32_to_cpu(b[0]);
 }
 
+static void regmap_parse_32_le_inplace(void *buf)
+{
+	__le32 *b = buf;
+
+	b[0] = le32_to_cpu(b[0]);
+}
+
 static unsigned int regmap_parse_32_native(const void *buf)
 {
 	return *(u32 *)buf;
@@ -608,6 +650,11 @@ struct regmap *regmap_init(struct device *dev,
 			map->format.parse_val = regmap_parse_16_be;
 			map->format.parse_inplace = regmap_parse_16_be_inplace;
 			break;
+		case REGMAP_ENDIAN_LITTLE:
+			map->format.format_val = regmap_format_16_le;
+			map->format.parse_val = regmap_parse_16_le;
+			map->format.parse_inplace = regmap_parse_16_le_inplace;
+			break;
 		case REGMAP_ENDIAN_NATIVE:
 			map->format.format_val = regmap_format_16_native;
 			map->format.parse_val = regmap_parse_16_native;
@@ -629,6 +676,11 @@ struct regmap *regmap_init(struct device *dev,
 			map->format.parse_val = regmap_parse_32_be;
 			map->format.parse_inplace = regmap_parse_32_be_inplace;
 			break;
+		case REGMAP_ENDIAN_LITTLE:
+			map->format.format_val = regmap_format_32_le;
+			map->format.parse_val = regmap_parse_32_le;
+			map->format.parse_inplace = regmap_parse_32_le_inplace;
+			break;
 		case REGMAP_ENDIAN_NATIVE:
 			map->format.format_val = regmap_format_32_native;
 			map->format.parse_val = regmap_parse_32_native;
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index bbcbd3c43926..be7c1fb7c0c9 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -39,8 +39,7 @@
 static ssize_t show_##name(struct device *dev,			\
 		struct device_attribute *attr, char *buf)	\
 {								\
-	unsigned int cpu = dev->id;				\
-	return sprintf(buf, "%d\n", topology_##name(cpu));	\
+	return sprintf(buf, "%d\n", topology_##name(dev->id));	\
 }
 
 #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 748dea4f34dc..758da2287d9a 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1406,7 +1406,7 @@ next_segment:
 
 		track = block / (floppy->dtype->sects * floppy->type->sect_mult);
 		sector = block % (floppy->dtype->sects * floppy->type->sect_mult);
-		data = rq->buffer + 512 * cnt;
+		data = bio_data(rq->bio) + 512 * cnt;
 #ifdef DEBUG
 		printk("access to track %d, sector %d, with buffer at "
 		       "0x%08lx\n", track, sector, data);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 96b629e1f0c9..7e8a55f8917c 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1484,7 +1484,7 @@ repeat:
 	ReqCnt = 0;
 	ReqCmd = rq_data_dir(fd_request);
 	ReqBlock = blk_rq_pos(fd_request);
-	ReqBuffer = fd_request->buffer;
+	ReqBuffer = bio_data(fd_request->bio);
 	setup_req_params( drive );
 	do_fd_action( drive );
 
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 8f5565bf34cd..5f69c910c3ac 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -2351,7 +2351,7 @@ static void rw_interrupt(void)
 	}
 
 	if (CT(COMMAND) != FD_READ ||
-	    raw_cmd->kernel_data == current_req->buffer) {
+	    raw_cmd->kernel_data == bio_data(current_req->bio)) {
 		/* transfer directly from buffer */
 		cont->done(1);
 	} else if (CT(COMMAND) == FD_READ) {
@@ -2640,7 +2640,7 @@ static int make_raw_rw_request(void)
 		raw_cmd->flags &= ~FD_RAW_WRITE;
 		raw_cmd->flags |= FD_RAW_READ;
 		COMMAND = FM_MODE(_floppy, FD_READ);
-	} else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
+	} else if ((unsigned long)bio_data(current_req->bio) < MAX_DMA_ADDRESS) {
 		unsigned long dma_limit;
 		int direct, indirect;
 
@@ -2654,13 +2654,13 @@ static int make_raw_rw_request(void)
 		 */
 		max_size = buffer_chain_size();
 		dma_limit = (MAX_DMA_ADDRESS -
-			     ((unsigned long)current_req->buffer)) >> 9;
+			     ((unsigned long)bio_data(current_req->bio))) >> 9;
 		if ((unsigned long)max_size > dma_limit)
 			max_size = dma_limit;
 		/* 64 kb boundaries */
-		if (CROSS_64KB(current_req->buffer, max_size << 9))
+		if (CROSS_64KB(bio_data(current_req->bio), max_size << 9))
 			max_size = (K_64 -
-				    ((unsigned long)current_req->buffer) %
+				    ((unsigned long)bio_data(current_req->bio)) %
 				    K_64) >> 9;
 		direct = transfer_size(ssize, max_sector, max_size) - fsector_t;
 		/*
@@ -2677,7 +2677,7 @@ static int make_raw_rw_request(void)
 		       (DP->read_track & (1 << DRS->probed_format)))))) {
 			max_size = blk_rq_sectors(current_req);
 		} else {
-			raw_cmd->kernel_data = current_req->buffer;
+			raw_cmd->kernel_data = bio_data(current_req->bio);
 			raw_cmd->length = current_count_sectors << 9;
 			if (raw_cmd->length == 0) {
 				DPRINT("%s: zero dma transfer attempted\n", __func__);
@@ -2731,7 +2731,7 @@ static int make_raw_rw_request(void)
 	raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
 	raw_cmd->length <<= 9;
 	if ((raw_cmd->length < current_count_sectors << 9) ||
-	    (raw_cmd->kernel_data != current_req->buffer &&
+	    (raw_cmd->kernel_data != bio_data(current_req->bio) &&
 	     CT(COMMAND) == FD_WRITE &&
 	     (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
 	      aligned_sector_t < buffer_min)) ||
@@ -2739,7 +2739,7 @@ static int make_raw_rw_request(void)
 	    raw_cmd->length <= 0 || current_count_sectors <= 0) {
 		DPRINT("fractionary current count b=%lx s=%lx\n",
 		       raw_cmd->length, current_count_sectors);
-		if (raw_cmd->kernel_data != current_req->buffer)
+		if (raw_cmd->kernel_data != bio_data(current_req->bio))
 			pr_info("addr=%d, length=%ld\n",
 				(int)((raw_cmd->kernel_data -
 				       floppy_track_buffer) >> 9),
@@ -2756,7 +2756,7 @@ static int make_raw_rw_request(void)
 		return 0;
 	}
 
-	if (raw_cmd->kernel_data != current_req->buffer) {
+	if (raw_cmd->kernel_data != bio_data(current_req->bio)) {
 		if (raw_cmd->kernel_data < floppy_track_buffer ||
 		    current_count_sectors < 0 ||
 		    raw_cmd->length < 0 ||
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index bf397bf108b7..8a290c08262f 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -464,11 +464,11 @@ static void read_intr(void)
 
 ok_to_read:
 	req = hd_req;
-	insw(HD_DATA, req->buffer, 256);
+	insw(HD_DATA, bio_data(req->bio), 256);
 #ifdef DEBUG
 	printk("%s: read: sector %ld, remaining = %u, buffer=%p\n",
 	       req->rq_disk->disk_name, blk_rq_pos(req) + 1,
-	       blk_rq_sectors(req) - 1, req->buffer+512);
+	       blk_rq_sectors(req) - 1, bio_data(req->bio)+512);
 #endif
 	if (hd_end_request(0, 512)) {
 		SET_HANDLER(&read_intr);
@@ -505,7 +505,7 @@ static void write_intr(void)
 ok_to_write:
 	if (hd_end_request(0, 512)) {
 		SET_HANDLER(&write_intr);
-		outsw(HD_DATA, req->buffer, 256);
+		outsw(HD_DATA, bio_data(req->bio), 256);
 		return;
 	}
 
@@ -624,7 +624,7 @@ repeat:
 	printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
 		req->rq_disk->disk_name,
 		req_data_dir(req) == READ ? "read" : "writ",
-		cyl, head, sec, nsect, req->buffer);
+		cyl, head, sec, nsect, bio_data(req->bio));
 #endif
 	if (req->cmd_type == REQ_TYPE_FS) {
 		switch (rq_data_dir(req)) {
@@ -643,7 +643,7 @@ repeat:
 				bad_rw_intr();
 				goto repeat;
 			}
-			outsw(HD_DATA, req->buffer, 256);
+			outsw(HD_DATA, bio_data(req->bio), 256);
 			break;
 		default:
 			printk("unknown hd-command\n");
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c
index eb59b1241366..e352cac707e8 100644
--- a/drivers/block/mg_disk.c
+++ b/drivers/block/mg_disk.c
@@ -479,7 +479,7 @@ static unsigned int mg_out(struct mg_host *host,
 
 static void mg_read_one(struct mg_host *host, struct request *req)
 {
-	u16 *buff = (u16 *)req->buffer;
+	u16 *buff = (u16 *)bio_data(req->bio);
 	u32 i;
 
 	for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
@@ -496,7 +496,7 @@ static void mg_read(struct request *req)
 		mg_bad_rw_intr(host);
 
 	MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
-	       blk_rq_sectors(req), blk_rq_pos(req), req->buffer);
+	       blk_rq_sectors(req), blk_rq_pos(req), bio_data(req->bio));
 
 	do {
 		if (mg_wait(host, ATA_DRQ,
@@ -514,7 +514,7 @@ static void mg_read(struct request *req)
 
 static void mg_write_one(struct mg_host *host, struct request *req)
 {
-	u16 *buff = (u16 *)req->buffer;
+	u16 *buff = (u16 *)bio_data(req->bio);
 	u32 i;
 
 	for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
@@ -534,7 +534,7 @@ static void mg_write(struct request *req)
 	}
 
 	MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
-	       rem, blk_rq_pos(req), req->buffer);
+	       rem, blk_rq_pos(req), bio_data(req->bio));
 
 	if (mg_wait(host, ATA_DRQ,
 		    MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
@@ -585,7 +585,7 @@ ok_to_read:
 	mg_read_one(host, req);
 
 	MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
-	       blk_rq_pos(req), blk_rq_sectors(req) - 1, req->buffer);
+	       blk_rq_pos(req), blk_rq_sectors(req) - 1, bio_data(req->bio));
 
 	/* send read confirm */
 	outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
@@ -624,7 +624,7 @@ ok_to_write:
 		/* write 1 sector and set handler if remains */
 		mg_write_one(host, req);
 		MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
-		       blk_rq_pos(req), blk_rq_sectors(req), req->buffer);
+		       blk_rq_pos(req), blk_rq_sectors(req), bio_data(req->bio));
 		host->mg_do_intr = mg_write_intr;
 		mod_timer(&host->timer, jiffies + 3 * HZ);
 	}
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index 091b9ea14feb..8e7e3a0b0d24 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -32,6 +32,7 @@ struct nullb {
 	unsigned int index;
 	struct request_queue *q;
 	struct gendisk *disk;
+	struct blk_mq_tag_set tag_set;
 	struct hrtimer timer;
 	unsigned int queue_depth;
 	spinlock_t lock;
@@ -226,7 +227,7 @@ static void null_cmd_end_timer(struct nullb_cmd *cmd)
 
 static void null_softirq_done_fn(struct request *rq)
 {
-	end_cmd(rq->special);
+	end_cmd(blk_mq_rq_to_pdu(rq));
 }
 
 static inline void null_handle_cmd(struct nullb_cmd *cmd)
@@ -311,7 +312,7 @@ static void null_request_fn(struct request_queue *q)
 
 static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq)
 {
-	struct nullb_cmd *cmd = rq->special;
+	struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq);
 
 	cmd->rq = rq;
 	cmd->nq = hctx->driver_data;
@@ -320,10 +321,11 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq)
 	return BLK_MQ_RQ_QUEUE_OK;
 }
 
-static struct blk_mq_hw_ctx *null_alloc_hctx(struct blk_mq_reg *reg, unsigned int hctx_index)
+static struct blk_mq_hw_ctx *null_alloc_hctx(struct blk_mq_tag_set *set,
+		unsigned int hctx_index)
 {
-	int b_size = DIV_ROUND_UP(reg->nr_hw_queues, nr_online_nodes);
-	int tip = (reg->nr_hw_queues % nr_online_nodes);
+	int b_size = DIV_ROUND_UP(set->nr_hw_queues, nr_online_nodes);
+	int tip = (set->nr_hw_queues % nr_online_nodes);
 	int node = 0, i, n;
 
 	/*
@@ -338,7 +340,7 @@ static struct blk_mq_hw_ctx *null_alloc_hctx(struct blk_mq_reg *reg, unsigned in
 
 			tip--;
 			if (!tip)
-				b_size = reg->nr_hw_queues / nr_online_nodes;
+				b_size = set->nr_hw_queues / nr_online_nodes;
 		}
 	}
 
@@ -387,13 +389,17 @@ static struct blk_mq_ops null_mq_ops = {
 	.map_queue      = blk_mq_map_queue,
 	.init_hctx	= null_init_hctx,
 	.complete	= null_softirq_done_fn,
+	.alloc_hctx	= blk_mq_alloc_single_hw_queue,
+	.free_hctx	= blk_mq_free_single_hw_queue,
 };
 
-static struct blk_mq_reg null_mq_reg = {
-	.ops		= &null_mq_ops,
-	.queue_depth	= 64,
-	.cmd_size	= sizeof(struct nullb_cmd),
-	.flags		= BLK_MQ_F_SHOULD_MERGE,
+static struct blk_mq_ops null_mq_ops_pernode = {
+	.queue_rq       = null_queue_rq,
+	.map_queue      = blk_mq_map_queue,
+	.init_hctx	= null_init_hctx,
+	.complete	= null_softirq_done_fn,
+	.alloc_hctx	= null_alloc_hctx,
+	.free_hctx	= null_free_hctx,
 };
 
 static void null_del_dev(struct nullb *nullb)
@@ -402,6 +408,8 @@ static void null_del_dev(struct nullb *nullb)
 
 	del_gendisk(nullb->disk);
 	blk_cleanup_queue(nullb->q);
+	if (queue_mode == NULL_Q_MQ)
+		blk_mq_free_tag_set(&nullb->tag_set);
 	put_disk(nullb->disk);
 	kfree(nullb);
 }
@@ -506,7 +514,7 @@ static int null_add_dev(void)
 
 	nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, home_node);
 	if (!nullb)
-		return -ENOMEM;
+		goto out;
 
 	spin_lock_init(&nullb->lock);
 
@@ -514,49 +522,47 @@ static int null_add_dev(void)
 		submit_queues = nr_online_nodes;
 
 	if (setup_queues(nullb))
-		goto err;
+		goto out_free_nullb;
 
 	if (queue_mode == NULL_Q_MQ) {
-		null_mq_reg.numa_node = home_node;
-		null_mq_reg.queue_depth = hw_queue_depth;
-		null_mq_reg.nr_hw_queues = submit_queues;
-
-		if (use_per_node_hctx) {
-			null_mq_reg.ops->alloc_hctx = null_alloc_hctx;
-			null_mq_reg.ops->free_hctx = null_free_hctx;
-		} else {
-			null_mq_reg.ops->alloc_hctx = blk_mq_alloc_single_hw_queue;
-			null_mq_reg.ops->free_hctx = blk_mq_free_single_hw_queue;
-		}
-
-		nullb->q = blk_mq_init_queue(&null_mq_reg, nullb);
+		if (use_per_node_hctx)
+			nullb->tag_set.ops = &null_mq_ops_pernode;
+		else
+			nullb->tag_set.ops = &null_mq_ops;
+		nullb->tag_set.nr_hw_queues = submit_queues;
+		nullb->tag_set.queue_depth = hw_queue_depth;
+		nullb->tag_set.numa_node = home_node;
+		nullb->tag_set.cmd_size	= sizeof(struct nullb_cmd);
+		nullb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
+		nullb->tag_set.driver_data = nullb;
+
+		if (blk_mq_alloc_tag_set(&nullb->tag_set))
+			goto out_cleanup_queues;
+
+		nullb->q = blk_mq_init_queue(&nullb->tag_set);
+		if (!nullb->q)
+			goto out_cleanup_tags;
 	} else if (queue_mode == NULL_Q_BIO) {
 		nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
+		if (!nullb->q)
+			goto out_cleanup_queues;
 		blk_queue_make_request(nullb->q, null_queue_bio);
 		init_driver_queues(nullb);
 	} else {
 		nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
+		if (!nullb->q)
+			goto out_cleanup_queues;
 		blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
-		if (nullb->q)
-			blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
+		blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
 		init_driver_queues(nullb);
 	}
 
-	if (!nullb->q)
-		goto queue_fail;
-
 	nullb->q->queuedata = nullb;
 	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q);
 
 	disk = nullb->disk = alloc_disk_node(1, home_node);
-	if (!disk) {
-queue_fail:
-		blk_cleanup_queue(nullb->q);
-		cleanup_queues(nullb);
-err:
-		kfree(nullb);
-		return -ENOMEM;
-	}
+	if (!disk)
+		goto out_cleanup_blk_queue;
 
 	mutex_lock(&lock);
 	list_add_tail(&nullb->list, &nullb_list);
@@ -579,6 +585,18 @@ err:
 	sprintf(disk->disk_name, "nullb%d", nullb->index);
 	add_disk(disk);
 	return 0;
+
+out_cleanup_blk_queue:
+	blk_cleanup_queue(nullb->q);
+out_cleanup_tags:
+	if (queue_mode == NULL_Q_MQ)
+		blk_mq_free_tag_set(&nullb->tag_set);
+out_cleanup_queues:
+	cleanup_queues(nullb);
+out_free_nullb:
+	kfree(nullb);
+out:
+	return -ENOMEM;
 }
 
 static int __init null_init(void)
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index e76bdc074dbe..719cb1bc1640 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -747,7 +747,7 @@ static void do_pcd_request(struct request_queue * q)
 			pcd_current = cd;
 			pcd_sector = blk_rq_pos(pcd_req);
 			pcd_count = blk_rq_cur_sectors(pcd_req);
-			pcd_buf = pcd_req->buffer;
+			pcd_buf = bio_data(pcd_req->bio);
 			pcd_busy = 1;
 			ps_set_intr(do_pcd_read, NULL, 0, nice);
 			return;
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 19ad8f0c83ef..fea7e76a00de 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -454,7 +454,7 @@ static enum action do_pd_io_start(void)
 		if (pd_block + pd_count > get_capacity(pd_req->rq_disk))
 			return Fail;
 		pd_run = blk_rq_sectors(pd_req);
-		pd_buf = pd_req->buffer;
+		pd_buf = bio_data(pd_req->bio);
 		pd_retries = 0;
 		if (pd_cmd == READ)
 			return do_pd_read_start();
@@ -485,7 +485,7 @@ static int pd_next_buf(void)
 	spin_lock_irqsave(&pd_lock, saved_flags);
 	__blk_end_request_cur(pd_req, 0);
 	pd_count = blk_rq_cur_sectors(pd_req);
-	pd_buf = pd_req->buffer;
+	pd_buf = bio_data(pd_req->bio);
 	spin_unlock_irqrestore(&pd_lock, saved_flags);
 	return 0;
 }
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index f5c86d523ba0..9a15fd3c9349 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -795,7 +795,7 @@ repeat:
 	}
 
 	pf_cmd = rq_data_dir(pf_req);
-	pf_buf = pf_req->buffer;
+	pf_buf = bio_data(pf_req->bio);
 	pf_retries = 0;
 
 	pf_busy = 1;
@@ -827,7 +827,7 @@ static int pf_next_buf(void)
 		if (!pf_req)
 			return 1;
 		pf_count = blk_rq_cur_sectors(pf_req);
-		pf_buf = pf_req->buffer;
+		pf_buf = bio_data(pf_req->bio);
 	}
 	return 0;
 }
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
index a69dd93d1bd5..36bcedfd930c 100644
--- a/drivers/block/skd_main.c
+++ b/drivers/block/skd_main.c
@@ -563,7 +563,6 @@ skd_prep_discard_cdb(struct skd_scsi_request *scsi_req,
 
 	req = skreq->req;
 	blk_add_request_payload(req, page, len);
-	req->buffer = buf;
 }
 
 static void skd_request_fn_not_online(struct request_queue *q);
@@ -856,10 +855,10 @@ static void skd_end_request(struct skd_device *skdev,
 
 	if ((io_flags & REQ_DISCARD) &&
 		(skreq->discard_page == 1)) {
+		struct bio *bio = req->bio;
 		pr_debug("%s:%s:%d, free the page!",
 			 skdev->name, __func__, __LINE__);
-		free_page((unsigned long)req->buffer);
-		req->buffer = NULL;
+		__free_page(bio->bi_io_vec->bv_page);
 	}
 
 	if (unlikely(error)) {
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index b02d53a399f3..6b44bbe528b7 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -549,7 +549,7 @@ static void redo_fd_request(struct request_queue *q)
 		case READ:
 			err = floppy_read_sectors(fs, blk_rq_pos(req),
 						  blk_rq_cur_sectors(req),
-						  req->buffer);
+						  bio_data(req->bio));
 			break;
 		}
 	done:
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index c74f7b56e7c4..523ee8fd4c15 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -342,7 +342,7 @@ static void start_request(struct floppy_state *fs)
 		swim3_dbg("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n",
 			  req->rq_disk->disk_name, req->cmd,
 			  (long)blk_rq_pos(req), blk_rq_sectors(req),
-			  req->buffer);
+			  bio_data(req->bio));
 		swim3_dbg("           errors=%d current_nr_sectors=%u\n",
 			  req->errors, blk_rq_cur_sectors(req));
 #endif
@@ -479,11 +479,11 @@ static inline void setup_transfer(struct floppy_state *fs)
 		/* Set up 3 dma commands: write preamble, data, postamble */
 		init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble));
 		++cp;
-		init_dma(cp, OUTPUT_MORE, req->buffer, 512);
+		init_dma(cp, OUTPUT_MORE, bio_data(req->bio), 512);
 		++cp;
 		init_dma(cp, OUTPUT_LAST, write_postamble, sizeof(write_postamble));
 	} else {
-		init_dma(cp, INPUT_LAST, req->buffer, n * 512);
+		init_dma(cp, INPUT_LAST, bio_data(req->bio), n * 512);
 	}
 	++cp;
 	out_le16(&cp->command, DBDMA_STOP);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 6d8a87f252de..7a51f065edcd 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -30,6 +30,9 @@ struct virtio_blk
 	/* The disk structure for the kernel. */
 	struct gendisk *disk;
 
+	/* Block layer tags. */
+	struct blk_mq_tag_set tag_set;
+
 	/* Process context for config space updates */
 	struct work_struct config_work;
 
@@ -112,7 +115,7 @@ static int __virtblk_add_req(struct virtqueue *vq,
 
 static inline void virtblk_request_done(struct request *req)
 {
-	struct virtblk_req *vbr = req->special;
+	struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
 	int error = virtblk_result(vbr);
 
 	if (req->cmd_type == REQ_TYPE_BLOCK_PC) {
@@ -148,13 +151,13 @@ static void virtblk_done(struct virtqueue *vq)
 
 	/* In case queue is stopped waiting for more buffers. */
 	if (req_done)
-		blk_mq_start_stopped_hw_queues(vblk->disk->queue);
+		blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
 }
 
 static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
 {
 	struct virtio_blk *vblk = hctx->queue->queuedata;
-	struct virtblk_req *vbr = req->special;
+	struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
 	unsigned long flags;
 	unsigned int num;
 	const bool last = (req->cmd_flags & REQ_END) != 0;
@@ -480,32 +483,28 @@ static const struct device_attribute dev_attr_cache_type_rw =
 	__ATTR(cache_type, S_IRUGO|S_IWUSR,
 	       virtblk_cache_type_show, virtblk_cache_type_store);
 
+static int virtblk_init_request(void *data, struct request *rq,
+		unsigned int hctx_idx, unsigned int request_idx,
+		unsigned int numa_node)
+{
+	struct virtio_blk *vblk = data;
+	struct virtblk_req *vbr = blk_mq_rq_to_pdu(rq);
+
+	sg_init_table(vbr->sg, vblk->sg_elems);
+	return 0;
+}
+
 static struct blk_mq_ops virtio_mq_ops = {
 	.queue_rq	= virtio_queue_rq,
 	.map_queue	= blk_mq_map_queue,
 	.alloc_hctx	= blk_mq_alloc_single_hw_queue,
 	.free_hctx	= blk_mq_free_single_hw_queue,
 	.complete	= virtblk_request_done,
+	.init_request	= virtblk_init_request,
 };
 
-static struct blk_mq_reg virtio_mq_reg = {
-	.ops		= &virtio_mq_ops,
-	.nr_hw_queues	= 1,
-	.queue_depth	= 0, /* Set in virtblk_probe */
-	.numa_node	= NUMA_NO_NODE,
-	.flags		= BLK_MQ_F_SHOULD_MERGE,
-};
-module_param_named(queue_depth, virtio_mq_reg.queue_depth, uint, 0444);
-
-static int virtblk_init_vbr(void *data, struct blk_mq_hw_ctx *hctx,
-			     struct request *rq, unsigned int nr)
-{
-	struct virtio_blk *vblk = data;
-	struct virtblk_req *vbr = rq->special;
-
-	sg_init_table(vbr->sg, vblk->sg_elems);
-	return 0;
-}
+static unsigned int virtblk_queue_depth;
+module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
 
 static int virtblk_probe(struct virtio_device *vdev)
 {
@@ -561,24 +560,34 @@ static int virtblk_probe(struct virtio_device *vdev)
 	}
 
 	/* Default queue sizing is to fill the ring. */
-	if (!virtio_mq_reg.queue_depth) {
-		virtio_mq_reg.queue_depth = vblk->vq->num_free;
+	if (!virtblk_queue_depth) {
+		virtblk_queue_depth = vblk->vq->num_free;
 		/* ... but without indirect descs, we use 2 descs per req */
 		if (!virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC))
-			virtio_mq_reg.queue_depth /= 2;
+			virtblk_queue_depth /= 2;
 	}
-	virtio_mq_reg.cmd_size =
+
+	memset(&vblk->tag_set, 0, sizeof(vblk->tag_set));
+	vblk->tag_set.ops = &virtio_mq_ops;
+	vblk->tag_set.nr_hw_queues = 1;
+	vblk->tag_set.queue_depth = virtblk_queue_depth;
+	vblk->tag_set.numa_node = NUMA_NO_NODE;
+	vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
+	vblk->tag_set.cmd_size =
 		sizeof(struct virtblk_req) +
 		sizeof(struct scatterlist) * sg_elems;
+	vblk->tag_set.driver_data = vblk;
 
-	q = vblk->disk->queue = blk_mq_init_queue(&virtio_mq_reg, vblk);
+	err = blk_mq_alloc_tag_set(&vblk->tag_set);
+	if (err)
+		goto out_put_disk;
+
+	q = vblk->disk->queue = blk_mq_init_queue(&vblk->tag_set);
 	if (!q) {
 		err = -ENOMEM;
-		goto out_put_disk;
+		goto out_free_tags;
 	}
 
-	blk_mq_init_commands(q, virtblk_init_vbr, vblk);
-
 	q->queuedata = vblk;
 
 	virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
@@ -679,6 +688,8 @@ static int virtblk_probe(struct virtio_device *vdev)
 out_del_disk:
 	del_gendisk(vblk->disk);
 	blk_cleanup_queue(vblk->disk->queue);
+out_free_tags:
+	blk_mq_free_tag_set(&vblk->tag_set);
 out_put_disk:
 	put_disk(vblk->disk);
 out_free_vq:
@@ -705,6 +716,8 @@ static void virtblk_remove(struct virtio_device *vdev)
 	del_gendisk(vblk->disk);
 	blk_cleanup_queue(vblk->disk->queue);
 
+	blk_mq_free_tag_set(&vblk->tag_set);
+
 	/* Stop all the virtqueues. */
 	vdev->config->reset(vdev);
 
@@ -749,7 +762,7 @@ static int virtblk_restore(struct virtio_device *vdev)
 	vblk->config_enable = true;
 	ret = init_vq(vdev->priv);
 	if (!ret)
-		blk_mq_start_stopped_hw_queues(vblk->disk->queue);
+		blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
 
 	return ret;
 }
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index efe1b4761735..283a30e88287 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -612,10 +612,10 @@ static void do_blkif_request(struct request_queue *rq)
 		}
 
 		pr_debug("do_blk_req %p: cmd %p, sec %lx, "
-			 "(%u/%u) buffer:%p [%s]\n",
+			 "(%u/%u) [%s]\n",
 			 req, req->cmd, (unsigned long)blk_rq_pos(req),
 			 blk_rq_cur_sectors(req), blk_rq_sectors(req),
-			 req->buffer, rq_data_dir(req) ? "write" : "read");
+			 rq_data_dir(req) ? "write" : "read");
 
 		if (blkif_queue_request(req)) {
 			blk_requeue_request(rq, req);
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 1393b8871a28..ab3ea62e5dfc 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -661,7 +661,7 @@ static void ace_fsm_dostate(struct ace_device *ace)
 			rq_data_dir(req));
 
 		ace->req = req;
-		ace->data_ptr = req->buffer;
+		ace->data_ptr = bio_data(req->bio);
 		ace->data_count = blk_rq_cur_sectors(req) * ACE_BUF_PER_SECTOR;
 		ace_out32(ace, ACE_MPULBA, blk_rq_pos(req) & 0x0FFFFFFF);
 
@@ -733,7 +733,7 @@ static void ace_fsm_dostate(struct ace_device *ace)
 			 *      blk_rq_sectors(ace->req),
 			 *      blk_rq_cur_sectors(ace->req));
 			 */
-			ace->data_ptr = ace->req->buffer;
+			ace->data_ptr = bio_data(ace->req->bio);
 			ace->data_count = blk_rq_cur_sectors(ace->req) * 16;
 			ace_fsm_yieldirq(ace);
 			break;
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 27de5046708a..968f9e52effa 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -87,13 +87,15 @@ static void do_z2_request(struct request_queue *q)
 		while (len) {
 			unsigned long addr = start & Z2RAM_CHUNKMASK;
 			unsigned long size = Z2RAM_CHUNKSIZE - addr;
+			void *buffer = bio_data(req->bio);
+
 			if (len < size)
 				size = len;
 			addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ];
 			if (rq_data_dir(req) == READ)
-				memcpy(req->buffer, (char *)addr, size);
+				memcpy(buffer, (char *)addr, size);
 			else
-				memcpy((char *)addr, req->buffer, size);
+				memcpy((char *)addr, buffer, size);
 			start += size;
 			len -= size;
 		}
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 7399303d7d99..199ff492da26 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -59,6 +59,8 @@ struct btmrvl_device {
 };
 
 struct btmrvl_adapter {
+	void *hw_regs_buf;
+	u8 *hw_regs;
 	u32 int_count;
 	struct sk_buff_head tx_queue;
 	u8 psmode;
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 2c4997ce2484..5c0b9444b5e1 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -24,6 +24,7 @@
 #include <net/bluetooth/hci_core.h>
 
 #include "btmrvl_drv.h"
+#include "btmrvl_sdio.h"
 
 #define VERSION "1.0"
 
@@ -337,10 +338,25 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
 
 static void btmrvl_init_adapter(struct btmrvl_private *priv)
 {
+	int buf_size;
+
 	skb_queue_head_init(&priv->adapter->tx_queue);
 
 	priv->adapter->ps_state = PS_AWAKE;
 
+	buf_size = ALIGN_SZ(SDIO_BLOCK_SIZE, BTSDIO_DMA_ALIGN);
+	priv->adapter->hw_regs_buf = kzalloc(buf_size, GFP_KERNEL);
+	if (!priv->adapter->hw_regs_buf) {
+		priv->adapter->hw_regs = NULL;
+		BT_ERR("Unable to allocate buffer for hw_regs.");
+	} else {
+		priv->adapter->hw_regs =
+			(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf,
+					 BTSDIO_DMA_ALIGN);
+		BT_DBG("hw_regs_buf=%p hw_regs=%p",
+		       priv->adapter->hw_regs_buf, priv->adapter->hw_regs);
+	}
+
 	init_waitqueue_head(&priv->adapter->cmd_wait_q);
 }
 
@@ -348,6 +364,7 @@ static void btmrvl_free_adapter(struct btmrvl_private *priv)
 {
 	skb_queue_purge(&priv->adapter->tx_queue);
 
+	kfree(priv->adapter->hw_regs_buf);
 	kfree(priv->adapter);
 
 	priv->adapter = NULL;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 1b52c9f5230d..9dedca516ff5 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -64,6 +64,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
 	.io_port_0 = 0x00,
 	.io_port_1 = 0x01,
 	.io_port_2 = 0x02,
+	.int_read_to_clear = false,
 };
 static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
 	.cfg = 0x00,
@@ -80,6 +81,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
 	.io_port_0 = 0x78,
 	.io_port_1 = 0x79,
 	.io_port_2 = 0x7a,
+	.int_read_to_clear = false,
 };
 
 static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
@@ -97,6 +99,9 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
 	.io_port_0 = 0xd8,
 	.io_port_1 = 0xd9,
 	.io_port_2 = 0xda,
+	.int_read_to_clear = true,
+	.host_int_rsr = 0x01,
+	.card_misc_cfg = 0xcc,
 };
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
@@ -667,46 +672,78 @@ static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
 	return 0;
 }
 
-static void btmrvl_sdio_interrupt(struct sdio_func *func)
+static int btmrvl_sdio_read_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
 {
-	struct btmrvl_private *priv;
-	struct btmrvl_sdio_card *card;
-	ulong flags;
-	u8 ireg = 0;
+	struct btmrvl_adapter *adapter = card->priv->adapter;
 	int ret;
 
-	card = sdio_get_drvdata(func);
-	if (!card || !card->priv) {
-		BT_ERR("sbi_interrupt(%p) card or priv is "
-				"NULL, card=%p\n", func, card);
-		return;
+	ret = sdio_readsb(card->func, adapter->hw_regs, 0, SDIO_BLOCK_SIZE);
+	if (ret) {
+		BT_ERR("sdio_readsb: read int hw_regs failed: %d", ret);
+		return ret;
 	}
 
-	priv = card->priv;
+	*ireg = adapter->hw_regs[card->reg->host_intstatus];
+	BT_DBG("hw_regs[%#x]=%#x", card->reg->host_intstatus, *ireg);
+
+	return 0;
+}
 
-	ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
+static int btmrvl_sdio_write_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
+{
+	int ret;
+
+	*ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
 	if (ret) {
-		BT_ERR("sdio_readb: read int status register failed");
-		return;
+		BT_ERR("sdio_readb: read int status failed: %d", ret);
+		return ret;
 	}
 
-	if (ireg != 0) {
+	if (*ireg) {
 		/*
 		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
 		 * Clear the interrupt status register and re-enable the
 		 * interrupt.
 		 */
-		BT_DBG("ireg = 0x%x", ireg);
+		BT_DBG("int_status = 0x%x", *ireg);
 
-		sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
-					UP_LD_HOST_INT_STATUS),
-				card->reg->host_intstatus, &ret);
+		sdio_writeb(card->func, ~(*ireg) & (DN_LD_HOST_INT_STATUS |
+						    UP_LD_HOST_INT_STATUS),
+			    card->reg->host_intstatus, &ret);
 		if (ret) {
-			BT_ERR("sdio_writeb: clear int status register failed");
-			return;
+			BT_ERR("sdio_writeb: clear int status failed: %d", ret);
+			return ret;
 		}
 	}
 
+	return 0;
+}
+
+static void btmrvl_sdio_interrupt(struct sdio_func *func)
+{
+	struct btmrvl_private *priv;
+	struct btmrvl_sdio_card *card;
+	ulong flags;
+	u8 ireg = 0;
+	int ret;
+
+	card = sdio_get_drvdata(func);
+	if (!card || !card->priv) {
+		BT_ERR("sbi_interrupt(%p) card or priv is "
+				"NULL, card=%p\n", func, card);
+		return;
+	}
+
+	priv = card->priv;
+
+	if (card->reg->int_read_to_clear)
+		ret = btmrvl_sdio_read_to_clear(card, &ireg);
+	else
+		ret = btmrvl_sdio_write_to_clear(card, &ireg);
+
+	if (ret)
+		return;
+
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	sdio_ireg |= ireg;
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -777,6 +814,30 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 
 	BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport);
 
+	if (card->reg->int_read_to_clear) {
+		reg = sdio_readb(func, card->reg->host_int_rsr, &ret);
+		if (ret < 0) {
+			ret = -EIO;
+			goto release_irq;
+		}
+		sdio_writeb(func, reg | 0x3f, card->reg->host_int_rsr, &ret);
+		if (ret < 0) {
+			ret = -EIO;
+			goto release_irq;
+		}
+
+		reg = sdio_readb(func, card->reg->card_misc_cfg, &ret);
+		if (ret < 0) {
+			ret = -EIO;
+			goto release_irq;
+		}
+		sdio_writeb(func, reg | 0x10, card->reg->card_misc_cfg, &ret);
+		if (ret < 0) {
+			ret = -EIO;
+			goto release_irq;
+		}
+	}
+
 	sdio_set_drvdata(func, card);
 
 	sdio_release_host(func);
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 43d35a609ca9..d4dd3b0fa53d 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -78,6 +78,9 @@ struct btmrvl_sdio_card_reg {
 	u8 io_port_0;
 	u8 io_port_1;
 	u8 io_port_2;
+	bool int_read_to_clear;
+	u8 host_int_rsr;
+	u8 card_misc_cfg;
 };
 
 struct btmrvl_sdio_card {
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 51e75ad96422..584bc3126403 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -602,7 +602,7 @@ static void gdrom_readdisk_dma(struct work_struct *work)
 		spin_unlock(&gdrom_lock);
 		block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET;
 		block_cnt = blk_rq_sectors(req)/GD_TO_BLK;
-		__raw_writel(virt_to_phys(req->buffer), GDROM_DMA_STARTADDR_REG);
+		__raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG);
 		__raw_writel(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG);
 		__raw_writel(1, GDROM_DMA_DIRECTION_REG);
 		__raw_writel(1, GDROM_DMA_ENABLE_REG);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index fbae63e3d304..6e9f74a5c095 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -40,7 +40,7 @@ config SGI_MBCS
 source "drivers/tty/serial/Kconfig"
 
 config TTY_PRINTK
-	bool "TTY driver to output user messages via printk"
+	tristate "TTY driver to output user messages via printk"
 	depends on EXPERT && TTY
 	default n
 	---help---
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 244759bbd7b7..ac6c0f3e2eb2 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -2,7 +2,7 @@
 # Hardware Random Number Generator (RNG) configuration
 #
 
-config HW_RANDOM
+menuconfig HW_RANDOM
 	tristate "Hardware Random Number Generator Core support"
 	default m
 	---help---
@@ -20,9 +20,11 @@ config HW_RANDOM
 
 	  If unsure, say Y.
 
+if HW_RANDOM
+
 config HW_RANDOM_TIMERIOMEM
 	tristate "Timer IOMEM HW Random Number Generator support"
-	depends on HW_RANDOM && HAS_IOMEM
+	depends on HAS_IOMEM
 	---help---
 	  This driver provides kernel-side support for a generic Random
 	  Number Generator used by reading a 'dumb' iomem address that
@@ -36,7 +38,7 @@ config HW_RANDOM_TIMERIOMEM
 
 config HW_RANDOM_INTEL
 	tristate "Intel HW Random Number Generator support"
-	depends on HW_RANDOM && (X86 || IA64) && PCI
+	depends on (X86 || IA64) && PCI
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -49,7 +51,7 @@ config HW_RANDOM_INTEL
 
 config HW_RANDOM_AMD
 	tristate "AMD HW Random Number Generator support"
-	depends on HW_RANDOM && (X86 || PPC_MAPLE) && PCI
+	depends on (X86 || PPC_MAPLE) && PCI
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -62,8 +64,8 @@ config HW_RANDOM_AMD
 
 config HW_RANDOM_ATMEL
 	tristate "Atmel Random Number Generator support"
-	depends on HW_RANDOM && HAVE_CLK
-	default (HW_RANDOM && ARCH_AT91)
+	depends on ARCH_AT91 && HAVE_CLK
+	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
 	  Generator hardware found on Atmel AT91 devices.
@@ -75,7 +77,7 @@ config HW_RANDOM_ATMEL
 
 config HW_RANDOM_BCM63XX
 	tristate "Broadcom BCM63xx Random Number Generator support"
-	depends on HW_RANDOM && BCM63XX
+	depends on BCM63XX
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -88,7 +90,7 @@ config HW_RANDOM_BCM63XX
 
 config HW_RANDOM_BCM2835
 	tristate "Broadcom BCM2835 Random Number Generator support"
-	depends on HW_RANDOM && ARCH_BCM2835
+	depends on ARCH_BCM2835
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -101,7 +103,7 @@ config HW_RANDOM_BCM2835
 
 config HW_RANDOM_GEODE
 	tristate "AMD Geode HW Random Number Generator support"
-	depends on HW_RANDOM && X86_32 && PCI
+	depends on X86_32 && PCI
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -114,7 +116,7 @@ config HW_RANDOM_GEODE
 
 config HW_RANDOM_N2RNG
 	tristate "Niagara2 Random Number Generator support"
-	depends on HW_RANDOM && SPARC64
+	depends on SPARC64
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -127,7 +129,7 @@ config HW_RANDOM_N2RNG
 
 config HW_RANDOM_VIA
 	tristate "VIA HW Random Number Generator support"
-	depends on HW_RANDOM && X86
+	depends on X86
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -140,7 +142,7 @@ config HW_RANDOM_VIA
 
 config HW_RANDOM_IXP4XX
 	tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
-	depends on HW_RANDOM && ARCH_IXP4XX
+	depends on ARCH_IXP4XX
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Pseudo-Random
@@ -153,7 +155,7 @@ config HW_RANDOM_IXP4XX
 
 config HW_RANDOM_OMAP
 	tristate "OMAP Random Number Generator support"
-	depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP2PLUS)
+	depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS
 	default HW_RANDOM
  	---help---
  	  This driver provides kernel-side support for the Random Number
@@ -167,7 +169,7 @@ config HW_RANDOM_OMAP
 
 config HW_RANDOM_OMAP3_ROM
 	tristate "OMAP3 ROM Random Number Generator support"
-	depends on HW_RANDOM && ARCH_OMAP3
+	depends on ARCH_OMAP3
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -180,7 +182,7 @@ config HW_RANDOM_OMAP3_ROM
 
 config HW_RANDOM_OCTEON
 	tristate "Octeon Random Number Generator support"
-	depends on HW_RANDOM && CAVIUM_OCTEON_SOC
+	depends on CAVIUM_OCTEON_SOC
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -193,7 +195,7 @@ config HW_RANDOM_OCTEON
 
 config HW_RANDOM_PASEMI
 	tristate "PA Semi HW Random Number Generator support"
-	depends on HW_RANDOM && PPC_PASEMI
+	depends on PPC_PASEMI
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -206,7 +208,7 @@ config HW_RANDOM_PASEMI
 
 config HW_RANDOM_VIRTIO
 	tristate "VirtIO Random Number Generator support"
-	depends on HW_RANDOM && VIRTIO
+	depends on VIRTIO
 	---help---
 	  This driver provides kernel-side support for the virtual Random Number
 	  Generator hardware.
@@ -216,7 +218,7 @@ config HW_RANDOM_VIRTIO
 
 config HW_RANDOM_TX4939
 	tristate "TX4939 Random Number Generator support"
-	depends on HW_RANDOM && SOC_TX4939
+	depends on SOC_TX4939
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -229,7 +231,8 @@ config HW_RANDOM_TX4939
 
 config HW_RANDOM_MXC_RNGA
 	tristate "Freescale i.MX RNGA Random Number Generator"
-	depends on HW_RANDOM && ARCH_HAS_RNGA
+	depends on ARCH_HAS_RNGA
+	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
 	  Generator hardware found on Freescale i.MX processors.
@@ -241,7 +244,8 @@ config HW_RANDOM_MXC_RNGA
 
 config HW_RANDOM_NOMADIK
 	tristate "ST-Ericsson Nomadik Random Number Generator support"
-	depends on HW_RANDOM && ARCH_NOMADIK
+	depends on ARCH_NOMADIK
+	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
 	  Generator hardware found on ST-Ericsson SoCs (8815 and 8500).
@@ -251,21 +255,10 @@ config HW_RANDOM_NOMADIK
 
 	  If unsure, say Y.
 
-config HW_RANDOM_PICOXCELL
-	tristate "Picochip picoXcell true random number generator support"
-	depends on HW_RANDOM && ARCH_PICOXCELL && PICOXCELL_PC3X3
-	---help---
-	  This driver provides kernel-side support for the Random Number
-	  Generator hardware found on Picochip PC3x3 and later devices.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called picoxcell-rng.
-
-	  If unsure, say Y.
-
 config HW_RANDOM_PPC4XX
 	tristate "PowerPC 4xx generic true random number generator support"
-	depends on HW_RANDOM && PPC && 4xx
+	depends on PPC && 4xx
+	default HW_RANDOM
 	---help---
 	 This driver provides the kernel-side support for the TRNG hardware
 	 found in the security function of some PowerPC 4xx SoCs.
@@ -275,24 +268,9 @@ config HW_RANDOM_PPC4XX
 
 	 If unsure, say N.
 
-config UML_RANDOM
-	depends on UML
-	tristate "Hardware random number generator"
-	help
-	  This option enables UML's "hardware" random number generator.  It
-	  attaches itself to the host's /dev/random, supplying as much entropy
-	  as the host has, rather than the small amount the UML gets from its
-	  own drivers.  It registers itself as a standard hardware random number
-	  generator, major 10, minor 183, and the canonical device name is
-	  /dev/hwrng.
-	  The way to make use of this is to install the rng-tools package
-	  (check your distro, or download from
-	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
-	  /dev/hwrng and injects the entropy into /dev/random.
-
 config HW_RANDOM_PSERIES
 	tristate "pSeries HW Random Number Generator support"
-	depends on HW_RANDOM && PPC64 && IBMVIO
+	depends on PPC64 && IBMVIO
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -305,7 +283,7 @@ config HW_RANDOM_PSERIES
 
 config HW_RANDOM_POWERNV
 	tristate "PowerNV Random Number Generator support"
-	depends on HW_RANDOM && PPC_POWERNV
+	depends on PPC_POWERNV
 	default HW_RANDOM
 	---help---
 	  This is the driver for Random Number Generator hardware found
@@ -318,7 +296,8 @@ config HW_RANDOM_POWERNV
 
 config HW_RANDOM_EXYNOS
 	tristate "EXYNOS HW random number generator support"
-	depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK
+	depends on ARCH_EXYNOS
+	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
 	  Generator hardware found on EXYNOS SOCs.
@@ -330,7 +309,7 @@ config HW_RANDOM_EXYNOS
 
 config HW_RANDOM_TPM
 	tristate "TPM HW Random Number Generator support"
-	depends on HW_RANDOM && TCG_TPM
+	depends on TCG_TPM
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -343,7 +322,8 @@ config HW_RANDOM_TPM
 
 config HW_RANDOM_MSM
 	tristate "Qualcomm SoCs Random Number Generator support"
-	depends on HW_RANDOM && ARCH_QCOM
+	depends on ARCH_QCOM
+	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
 	  Generator hardware found on Qualcomm SoCs.
@@ -352,3 +332,20 @@ config HW_RANDOM_MSM
 	  module will be called msm-rng.
 
 	  If unsure, say Y.
+
+endif # HW_RANDOM
+
+config UML_RANDOM
+	depends on UML
+	tristate "Hardware random number generator"
+	help
+	  This option enables UML's "hardware" random number generator.  It
+	  attaches itself to the host's /dev/random, supplying as much entropy
+	  as the host has, rather than the small amount the UML gets from its
+	  own drivers.  It registers itself as a standard hardware random number
+	  generator, major 10, minor 183, and the canonical device name is
+	  /dev/hwrng.
+	  The way to make use of this is to install the rng-tools package
+	  (check your distro, or download from
+	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
+	  /dev/hwrng and injects the entropy into /dev/random.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 3ae7755a52e7..199ed283e149 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
 obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
 obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
 obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
-obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
 obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
 obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index 8c3b255e629a..e900961cdd2e 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -61,18 +61,18 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
 	}
 	bcm2835_rng_ops.priv = (unsigned long)rng_base;
 
+	/* set warm-up count & enable */
+	__raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
+	__raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
+
 	/* register driver */
 	err = hwrng_register(&bcm2835_rng_ops);
 	if (err) {
 		dev_err(dev, "hwrng registration failed\n");
 		iounmap(rng_base);
-	} else {
+	} else
 		dev_info(dev, "hwrng registered\n");
 
-		/* set warm-up count & enable */
-		__raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
-		__raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
-	}
 	return err;
 }
 
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
deleted file mode 100644
index eab5448ad56f..000000000000
--- a/drivers/char/hw_random/picoxcell-rng.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * All enquiries to support@picochip.com
- */
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/hw_random.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#define DATA_REG_OFFSET		0x0200
-#define CSR_REG_OFFSET		0x0278
-#define CSR_OUT_EMPTY_MASK	(1 << 24)
-#define CSR_FAULT_MASK		(1 << 1)
-#define TRNG_BLOCK_RESET_MASK	(1 << 0)
-#define TAI_REG_OFFSET		0x0380
-
-/*
- * The maximum amount of time in microseconds to spend waiting for data if the
- * core wants us to wait.  The TRNG should generate 32 bits every 320ns so a
- * timeout of 20us seems reasonable.  The TRNG does builtin tests of the data
- * for randomness so we can't always assume there is data present.
- */
-#define PICO_TRNG_TIMEOUT		20
-
-static void __iomem *rng_base;
-static struct clk *rng_clk;
-static struct device *rng_dev;
-
-static inline u32 picoxcell_trng_read_csr(void)
-{
-	return __raw_readl(rng_base + CSR_REG_OFFSET);
-}
-
-static inline bool picoxcell_trng_is_empty(void)
-{
-	return picoxcell_trng_read_csr() & CSR_OUT_EMPTY_MASK;
-}
-
-/*
- * Take the random number generator out of reset and make sure the interrupts
- * are masked. We shouldn't need to get large amounts of random bytes so just
- * poll the status register. The hardware generates 32 bits every 320ns so we
- * shouldn't have to wait long enough to warrant waiting for an IRQ.
- */
-static void picoxcell_trng_start(void)
-{
-	__raw_writel(0, rng_base + TAI_REG_OFFSET);
-	__raw_writel(0, rng_base + CSR_REG_OFFSET);
-}
-
-static void picoxcell_trng_reset(void)
-{
-	__raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + CSR_REG_OFFSET);
-	__raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + TAI_REG_OFFSET);
-	picoxcell_trng_start();
-}
-
-/*
- * Get some random data from the random number generator. The hw_random core
- * layer provides us with locking.
- */
-static int picoxcell_trng_read(struct hwrng *rng, void *buf, size_t max,
-			       bool wait)
-{
-	int i;
-
-	/* Wait for some data to become available. */
-	for (i = 0; i < PICO_TRNG_TIMEOUT && picoxcell_trng_is_empty(); ++i) {
-		if (!wait)
-			return 0;
-
-		udelay(1);
-	}
-
-	if (picoxcell_trng_read_csr() & CSR_FAULT_MASK) {
-		dev_err(rng_dev, "fault detected, resetting TRNG\n");
-		picoxcell_trng_reset();
-		return -EIO;
-	}
-
-	if (i == PICO_TRNG_TIMEOUT)
-		return 0;
-
-	*(u32 *)buf = __raw_readl(rng_base + DATA_REG_OFFSET);
-	return sizeof(u32);
-}
-
-static struct hwrng picoxcell_trng = {
-	.name		= "picoxcell",
-	.read		= picoxcell_trng_read,
-};
-
-static int picoxcell_trng_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	rng_base = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(rng_base))
-		return PTR_ERR(rng_base);
-
-	rng_clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(rng_clk)) {
-		dev_warn(&pdev->dev, "no clk\n");
-		return PTR_ERR(rng_clk);
-	}
-
-	ret = clk_enable(rng_clk);
-	if (ret) {
-		dev_warn(&pdev->dev, "unable to enable clk\n");
-		return ret;
-	}
-
-	picoxcell_trng_start();
-	ret = hwrng_register(&picoxcell_trng);
-	if (ret)
-		goto err_register;
-
-	rng_dev = &pdev->dev;
-	dev_info(&pdev->dev, "pixoxcell random number generator active\n");
-
-	return 0;
-
-err_register:
-	clk_disable(rng_clk);
-	return ret;
-}
-
-static int picoxcell_trng_remove(struct platform_device *pdev)
-{
-	hwrng_unregister(&picoxcell_trng);
-	clk_disable(rng_clk);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int picoxcell_trng_suspend(struct device *dev)
-{
-	clk_disable(rng_clk);
-
-	return 0;
-}
-
-static int picoxcell_trng_resume(struct device *dev)
-{
-	return clk_enable(rng_clk);
-}
-
-static const struct dev_pm_ops picoxcell_trng_pm_ops = {
-	.suspend	= picoxcell_trng_suspend,
-	.resume		= picoxcell_trng_resume,
-};
-#endif /* CONFIG_PM */
-
-static struct platform_driver picoxcell_trng_driver = {
-	.probe		= picoxcell_trng_probe,
-	.remove		= picoxcell_trng_remove,
-	.driver		= {
-		.name	= "picoxcell-trng",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &picoxcell_trng_pm_ops,
-#endif /* CONFIG_PM */
-	},
-};
-
-module_platform_driver(picoxcell_trng_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jamie Iles");
-MODULE_DESCRIPTION("Picochip picoXcell TRNG driver");
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig
index b27f5342fe76..8d3dfb0c8a26 100644
--- a/drivers/char/pcmcia/Kconfig
+++ b/drivers/char/pcmcia/Kconfig
@@ -15,7 +15,7 @@ config SYNCLINK_CS
 
 	  This driver may be built as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called synclinkmp.  If you want to do that, say M
+	  The module will be called synclink_cs.  If you want to do that, say M
 	  here.
 
 config CARDMAN_4000
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index daea84c41743..a15ce4ef39cd 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -17,7 +17,7 @@
 #include <linux/device.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
-#include <linux/export.h>
+#include <linux/module.h>
 
 struct ttyprintk_port {
 	struct tty_port port;
@@ -210,10 +210,19 @@ static int __init ttyprintk_init(void)
 	return 0;
 
 error:
-	tty_unregister_driver(ttyprintk_driver);
 	put_tty_driver(ttyprintk_driver);
 	tty_port_destroy(&tpk_port.port);
-	ttyprintk_driver = NULL;
 	return ret;
 }
+
+static void __exit ttyprintk_exit(void)
+{
+	tty_unregister_driver(ttyprintk_driver);
+	put_tty_driver(ttyprintk_driver);
+	tty_port_destroy(&tpk_port.port);
+}
+
 device_initcall(ttyprintk_init);
+module_exit(ttyprintk_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c
index c7607feb18dd..54a06526f64f 100644
--- a/drivers/clk/bcm/clk-kona-setup.c
+++ b/drivers/clk/bcm/clk-kona-setup.c
@@ -27,7 +27,7 @@ LIST_HEAD(ccu_list);	/* The list of set up CCUs */
 
 static bool clk_requires_trigger(struct kona_clk *bcm_clk)
 {
-	struct peri_clk_data *peri = bcm_clk->peri;
+	struct peri_clk_data *peri = bcm_clk->u.peri;
 	struct bcm_clk_sel *sel;
 	struct bcm_clk_div *div;
 
@@ -63,7 +63,7 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
 	u32 limit;
 
 	BUG_ON(bcm_clk->type != bcm_clk_peri);
-	peri = bcm_clk->peri;
+	peri = bcm_clk->u.peri;
 	name = bcm_clk->name;
 	range = bcm_clk->ccu->range;
 
@@ -81,19 +81,19 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
 
 	div = &peri->div;
 	if (divider_exists(div)) {
-		if (div->offset > limit) {
+		if (div->u.s.offset > limit) {
 			pr_err("%s: bad divider offset for %s (%u > %u)\n",
-				__func__, name, div->offset, limit);
+				__func__, name, div->u.s.offset, limit);
 			return false;
 		}
 	}
 
 	div = &peri->pre_div;
 	if (divider_exists(div)) {
-		if (div->offset > limit) {
+		if (div->u.s.offset > limit) {
 			pr_err("%s: bad pre-divider offset for %s "
 					"(%u > %u)\n",
-				__func__, name, div->offset, limit);
+				__func__, name, div->u.s.offset, limit);
 			return false;
 		}
 	}
@@ -249,21 +249,22 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name,
 {
 	if (divider_is_fixed(div)) {
 		/* Any fixed divider value but 0 is OK */
-		if (div->fixed == 0) {
+		if (div->u.fixed == 0) {
 			pr_err("%s: bad %s fixed value 0 for %s\n", __func__,
 				field_name, clock_name);
 			return false;
 		}
 		return true;
 	}
-	if (!bitfield_valid(div->shift, div->width, field_name, clock_name))
+	if (!bitfield_valid(div->u.s.shift, div->u.s.width,
+				field_name, clock_name))
 		return false;
 
 	if (divider_has_fraction(div))
-		if (div->frac_width > div->width) {
+		if (div->u.s.frac_width > div->u.s.width) {
 			pr_warn("%s: bad %s fraction width for %s (%u > %u)\n",
 				__func__, field_name, clock_name,
-				div->frac_width, div->width);
+				div->u.s.frac_width, div->u.s.width);
 			return false;
 		}
 
@@ -278,7 +279,7 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name,
  */
 static bool kona_dividers_valid(struct kona_clk *bcm_clk)
 {
-	struct peri_clk_data *peri = bcm_clk->peri;
+	struct peri_clk_data *peri = bcm_clk->u.peri;
 	struct bcm_clk_div *div;
 	struct bcm_clk_div *pre_div;
 	u32 limit;
@@ -295,7 +296,7 @@ static bool kona_dividers_valid(struct kona_clk *bcm_clk)
 
 	limit = BITS_PER_BYTE * sizeof(u32);
 
-	return div->frac_width + pre_div->frac_width <= limit;
+	return div->u.s.frac_width + pre_div->u.s.frac_width <= limit;
 }
 
 
@@ -328,7 +329,7 @@ peri_clk_data_valid(struct kona_clk *bcm_clk)
 	if (!peri_clk_data_offsets_valid(bcm_clk))
 		return false;
 
-	peri = bcm_clk->peri;
+	peri = bcm_clk->u.peri;
 	name = bcm_clk->name;
 	gate = &peri->gate;
 	if (gate_exists(gate) && !gate_valid(gate, "gate", name))
@@ -588,12 +589,12 @@ static void bcm_clk_teardown(struct kona_clk *bcm_clk)
 {
 	switch (bcm_clk->type) {
 	case bcm_clk_peri:
-		peri_clk_teardown(bcm_clk->data, &bcm_clk->init_data);
+		peri_clk_teardown(bcm_clk->u.data, &bcm_clk->init_data);
 		break;
 	default:
 		break;
 	}
-	bcm_clk->data = NULL;
+	bcm_clk->u.data = NULL;
 	bcm_clk->type = bcm_clk_none;
 }
 
@@ -644,7 +645,7 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name,
 		break;
 	}
 	bcm_clk->type = type;
-	bcm_clk->data = data;
+	bcm_clk->u.data = data;
 
 	/* Make sure everything makes sense before we set it up */
 	if (!kona_clk_valid(bcm_clk)) {
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index e3d339e08309..db11a87449f2 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -61,7 +61,7 @@ u64 do_div_round_closest(u64 dividend, unsigned long divisor)
 /* Convert a divider into the scaled divisor value it represents. */
 static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div)
 {
-	return (u64)reg_div + ((u64)1 << div->frac_width);
+	return (u64)reg_div + ((u64)1 << div->u.s.frac_width);
 }
 
 /*
@@ -77,7 +77,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths)
 	BUG_ON(billionths >= BILLION);
 
 	combined = (u64)div_value * BILLION + billionths;
-	combined <<= div->frac_width;
+	combined <<= div->u.s.frac_width;
 
 	return do_div_round_closest(combined, BILLION);
 }
@@ -87,7 +87,7 @@ static inline u64
 scaled_div_min(struct bcm_clk_div *div)
 {
 	if (divider_is_fixed(div))
-		return (u64)div->fixed;
+		return (u64)div->u.fixed;
 
 	return scaled_div_value(div, 0);
 }
@@ -98,9 +98,9 @@ u64 scaled_div_max(struct bcm_clk_div *div)
 	u32 reg_div;
 
 	if (divider_is_fixed(div))
-		return (u64)div->fixed;
+		return (u64)div->u.fixed;
 
-	reg_div = ((u32)1 << div->width) - 1;
+	reg_div = ((u32)1 << div->u.s.width) - 1;
 
 	return scaled_div_value(div, reg_div);
 }
@@ -115,7 +115,7 @@ divider(struct bcm_clk_div *div, u64 scaled_div)
 	BUG_ON(scaled_div < scaled_div_min(div));
 	BUG_ON(scaled_div > scaled_div_max(div));
 
-	return (u32)(scaled_div - ((u64)1 << div->frac_width));
+	return (u32)(scaled_div - ((u64)1 << div->u.s.frac_width));
 }
 
 /* Return a rate scaled for use when dividing by a scaled divisor. */
@@ -125,7 +125,7 @@ scale_rate(struct bcm_clk_div *div, u32 rate)
 	if (divider_is_fixed(div))
 		return (u64)rate;
 
-	return (u64)rate << div->frac_width;
+	return (u64)rate << div->u.s.frac_width;
 }
 
 /* CCU access */
@@ -398,14 +398,14 @@ static u64 divider_read_scaled(struct ccu_data *ccu, struct bcm_clk_div *div)
 	u32 reg_div;
 
 	if (divider_is_fixed(div))
-		return (u64)div->fixed;
+		return (u64)div->u.fixed;
 
 	flags = ccu_lock(ccu);
-	reg_val = __ccu_read(ccu, div->offset);
+	reg_val = __ccu_read(ccu, div->u.s.offset);
 	ccu_unlock(ccu, flags);
 
 	/* Extract the full divider field from the register value */
-	reg_div = bitfield_extract(reg_val, div->shift, div->width);
+	reg_div = bitfield_extract(reg_val, div->u.s.shift, div->u.s.width);
 
 	/* Return the scaled divisor value it represents */
 	return scaled_div_value(div, reg_div);
@@ -433,16 +433,17 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
 	 * state was defined in the device tree, we just find out
 	 * what its current value is rather than updating it.
 	 */
-	if (div->scaled_div == BAD_SCALED_DIV_VALUE) {
-		reg_val = __ccu_read(ccu, div->offset);
-		reg_div = bitfield_extract(reg_val, div->shift, div->width);
-		div->scaled_div = scaled_div_value(div, reg_div);
+	if (div->u.s.scaled_div == BAD_SCALED_DIV_VALUE) {
+		reg_val = __ccu_read(ccu, div->u.s.offset);
+		reg_div = bitfield_extract(reg_val, div->u.s.shift,
+						div->u.s.width);
+		div->u.s.scaled_div = scaled_div_value(div, reg_div);
 
 		return 0;
 	}
 
 	/* Convert the scaled divisor to the value we need to record */
-	reg_div = divider(div, div->scaled_div);
+	reg_div = divider(div, div->u.s.scaled_div);
 
 	/* Clock needs to be enabled before changing the rate */
 	enabled = __is_clk_gate_enabled(ccu, gate);
@@ -452,9 +453,10 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
 	}
 
 	/* Replace the divider value and record the result */
-	reg_val = __ccu_read(ccu, div->offset);
-	reg_val = bitfield_replace(reg_val, div->shift, div->width, reg_div);
-	__ccu_write(ccu, div->offset, reg_val);
+	reg_val = __ccu_read(ccu, div->u.s.offset);
+	reg_val = bitfield_replace(reg_val, div->u.s.shift, div->u.s.width,
+					reg_div);
+	__ccu_write(ccu, div->u.s.offset, reg_val);
 
 	/* If the trigger fails we still want to disable the gate */
 	if (!__clk_trigger(ccu, trig))
@@ -490,11 +492,11 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
 
 	BUG_ON(divider_is_fixed(div));
 
-	previous = div->scaled_div;
+	previous = div->u.s.scaled_div;
 	if (previous == scaled_div)
 		return 0;	/* No change */
 
-	div->scaled_div = scaled_div;
+	div->u.s.scaled_div = scaled_div;
 
 	flags = ccu_lock(ccu);
 	__ccu_write_enable(ccu);
@@ -505,7 +507,7 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
 	ccu_unlock(ccu, flags);
 
 	if (ret)
-		div->scaled_div = previous;		/* Revert the change */
+		div->u.s.scaled_div = previous;		/* Revert the change */
 
 	return ret;
 
@@ -802,7 +804,7 @@ static int selector_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
 static int kona_peri_clk_enable(struct clk_hw *hw)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
+	struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
 
 	return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true);
 }
@@ -810,7 +812,7 @@ static int kona_peri_clk_enable(struct clk_hw *hw)
 static void kona_peri_clk_disable(struct clk_hw *hw)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
+	struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
 
 	(void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false);
 }
@@ -818,7 +820,7 @@ static void kona_peri_clk_disable(struct clk_hw *hw)
 static int kona_peri_clk_is_enabled(struct clk_hw *hw)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
+	struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
 
 	return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0;
 }
@@ -827,7 +829,7 @@ static unsigned long kona_peri_clk_recalc_rate(struct clk_hw *hw,
 			unsigned long parent_rate)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct peri_clk_data *data = bcm_clk->peri;
+	struct peri_clk_data *data = bcm_clk->u.peri;
 
 	return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div,
 				parent_rate);
@@ -837,20 +839,20 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 			unsigned long *parent_rate)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct bcm_clk_div *div = &bcm_clk->peri->div;
+	struct bcm_clk_div *div = &bcm_clk->u.peri->div;
 
 	if (!divider_exists(div))
 		return __clk_get_rate(hw->clk);
 
 	/* Quietly avoid a zero rate */
-	return round_rate(bcm_clk->ccu, div, &bcm_clk->peri->pre_div,
+	return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div,
 				rate ? rate : 1, *parent_rate, NULL);
 }
 
 static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct peri_clk_data *data = bcm_clk->peri;
+	struct peri_clk_data *data = bcm_clk->u.peri;
 	struct bcm_clk_sel *sel = &data->sel;
 	struct bcm_clk_trig *trig;
 	int ret;
@@ -884,7 +886,7 @@ static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
 static u8 kona_peri_clk_get_parent(struct clk_hw *hw)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct peri_clk_data *data = bcm_clk->peri;
+	struct peri_clk_data *data = bcm_clk->u.peri;
 	u8 index;
 
 	index = selector_read_index(bcm_clk->ccu, &data->sel);
@@ -897,7 +899,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 			unsigned long parent_rate)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
-	struct peri_clk_data *data = bcm_clk->peri;
+	struct peri_clk_data *data = bcm_clk->u.peri;
 	struct bcm_clk_div *div = &data->div;
 	u64 scaled_div = 0;
 	int ret;
@@ -958,7 +960,7 @@ struct clk_ops kona_peri_clk_ops = {
 static bool __peri_clk_init(struct kona_clk *bcm_clk)
 {
 	struct ccu_data *ccu = bcm_clk->ccu;
-	struct peri_clk_data *peri = bcm_clk->peri;
+	struct peri_clk_data *peri = bcm_clk->u.peri;
 	const char *name = bcm_clk->name;
 	struct bcm_clk_trig *trig;
 
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h
index 5e139adc3dc5..dee690951bb6 100644
--- a/drivers/clk/bcm/clk-kona.h
+++ b/drivers/clk/bcm/clk-kona.h
@@ -57,7 +57,7 @@
 #define divider_exists(div)		FLAG_TEST(div, DIV, EXISTS)
 #define divider_is_fixed(div)		FLAG_TEST(div, DIV, FIXED)
 #define divider_has_fraction(div)	(!divider_is_fixed(div) && \
-						(div)->frac_width > 0)
+						(div)->u.s.frac_width > 0)
 
 #define selector_exists(sel)		((sel)->width != 0)
 #define trigger_exists(trig)		FLAG_TEST(trig, TRIG, EXISTS)
@@ -244,9 +244,9 @@ struct bcm_clk_div {
 			u32 frac_width;	/* field fraction width */
 
 			u64 scaled_div;	/* scaled divider value */
-		};
+		} s;
 		u32 fixed;	/* non-zero fixed divider value */
-	};
+	} u;
 	u32 flags;		/* BCM_CLK_DIV_FLAGS_* below */
 };
 
@@ -263,28 +263,28 @@ struct bcm_clk_div {
 /* A fixed (non-zero) divider */
 #define FIXED_DIVIDER(_value)						\
 	{								\
-		.fixed = (_value),					\
+		.u.fixed = (_value),					\
 		.flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED),		\
 	}
 
 /* A divider with an integral divisor */
 #define DIVIDER(_offset, _shift, _width)				\
 	{								\
-		.offset = (_offset),					\
-		.shift = (_shift),					\
-		.width = (_width),					\
-		.scaled_div = BAD_SCALED_DIV_VALUE,			\
+		.u.s.offset = (_offset),				\
+		.u.s.shift = (_shift),					\
+		.u.s.width = (_width),					\
+		.u.s.scaled_div = BAD_SCALED_DIV_VALUE,			\
 		.flags = FLAG(DIV, EXISTS),				\
 	}
 
 /* A divider whose divisor has an integer and fractional part */
 #define FRAC_DIVIDER(_offset, _shift, _width, _frac_width)		\
 	{								\
-		.offset = (_offset),					\
-		.shift = (_shift),					\
-		.width = (_width),					\
-		.frac_width = (_frac_width),				\
-		.scaled_div = BAD_SCALED_DIV_VALUE,			\
+		.u.s.offset = (_offset),				\
+		.u.s.shift = (_shift),					\
+		.u.s.width = (_width),					\
+		.u.s.frac_width = (_frac_width),			\
+		.u.s.scaled_div = BAD_SCALED_DIV_VALUE,			\
 		.flags = FLAG(DIV, EXISTS),				\
 	}
 
@@ -380,7 +380,7 @@ struct kona_clk {
 	union {
 		void *data;
 		struct peri_clk_data *peri;
-	};
+	} u;
 };
 #define to_kona_clk(_hw) \
 	container_of(_hw, struct kona_clk, hw)
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index f0bc31f5db27..d4add8621944 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -62,7 +62,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
 	set_cpus_allowed_ptr(current, &cpus_allowed);
 
 	/* setting the cpu frequency */
-	clk_set_rate(policy->clk, freq);
+	clk_set_rate(policy->clk, freq * 1000);
 
 	return 0;
 }
@@ -92,7 +92,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	     i++)
 		loongson2_clockmod_table[i].frequency = (rate * i) / 8;
 
-	ret = clk_set_rate(cpuclk, rate);
+	ret = clk_set_rate(cpuclk, rate * 1000);
 	if (ret) {
 		clk_put(cpuclk);
 		return ret;
diff --git a/drivers/crypto/bfin_crc.c b/drivers/crypto/bfin_crc.c
index c9ff298e6d26..b099e33cb073 100644
--- a/drivers/crypto/bfin_crc.c
+++ b/drivers/crypto/bfin_crc.c
@@ -29,10 +29,11 @@
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
 
-#include <asm/blackfin.h>
-#include <asm/bfin_crc.h>
 #include <asm/dma.h>
 #include <asm/portmux.h>
+#include <asm/io.h>
+
+#include "bfin_crc.h"
 
 #define CRC_CCRYPTO_QUEUE_LENGTH	5
 
@@ -54,12 +55,13 @@ struct bfin_crypto_crc {
 	int			irq;
 	int			dma_ch;
 	u32			poly;
-	volatile struct crc_register *regs;
+	struct crc_register	*regs;
 
 	struct ahash_request	*req; /* current request in operation */
 	struct dma_desc_array	*sg_cpu; /* virt addr of sg dma descriptors */
 	dma_addr_t		sg_dma; /* phy addr of sg dma descriptors */
 	u8			*sg_mid_buf;
+	dma_addr_t		sg_mid_dma; /* phy addr of sg mid buffer */
 
 	struct tasklet_struct	done_task;
 	struct crypto_queue	queue; /* waiting requests */
@@ -132,13 +134,13 @@ static struct scatterlist *sg_get(struct scatterlist *sg_list, unsigned int nent
 
 static int bfin_crypto_crc_init_hw(struct bfin_crypto_crc *crc, u32 key)
 {
-	crc->regs->datacntrld = 0;
-	crc->regs->control = MODE_CALC_CRC << OPMODE_OFFSET;
-	crc->regs->curresult = key;
+	writel(0, &crc->regs->datacntrld);
+	writel(MODE_CALC_CRC << OPMODE_OFFSET, &crc->regs->control);
+	writel(key, &crc->regs->curresult);
 
 	/* setup CRC interrupts */
-	crc->regs->status = CMPERRI | DCNTEXPI;
-	crc->regs->intrenset = CMPERRI | DCNTEXPI;
+	writel(CMPERRI | DCNTEXPI, &crc->regs->status);
+	writel(CMPERRI | DCNTEXPI, &crc->regs->intrenset);
 
 	return 0;
 }
@@ -194,7 +196,6 @@ static void bfin_crypto_crc_config_dma(struct bfin_crypto_crc *crc)
 	dma_map_sg(crc->dev, ctx->sg, ctx->sg_nents, DMA_TO_DEVICE);
 
 	for_each_sg(ctx->sg, sg, ctx->sg_nents, j) {
-		dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 | DMAEN | PSIZE_32;
 		dma_addr = sg_dma_address(sg);
 		/* deduce extra bytes in last sg */
 		if (sg_is_last(sg))
@@ -207,12 +208,29 @@ static void bfin_crypto_crc_config_dma(struct bfin_crypto_crc *crc)
 			   bytes in current sg buffer. Move addr of current
 			   sg and deduce the length of current sg.
 			 */
-			memcpy(crc->sg_mid_buf +((i-1) << 2) + mid_dma_count,
-				(void *)dma_addr,
+			memcpy(crc->sg_mid_buf +(i << 2) + mid_dma_count,
+				sg_virt(sg),
 				CHKSUM_DIGEST_SIZE - mid_dma_count);
 			dma_addr += CHKSUM_DIGEST_SIZE - mid_dma_count;
 			dma_count -= CHKSUM_DIGEST_SIZE - mid_dma_count;
+
+			dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 |
+				DMAEN | PSIZE_32 | WDSIZE_32;
+
+			/* setup new dma descriptor for next middle dma */
+			crc->sg_cpu[i].start_addr = crc->sg_mid_dma + (i << 2);
+			crc->sg_cpu[i].cfg = dma_config;
+			crc->sg_cpu[i].x_count = 1;
+			crc->sg_cpu[i].x_modify = CHKSUM_DIGEST_SIZE;
+			dev_dbg(crc->dev, "%d: crc_dma: start_addr:0x%lx, "
+				"cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n",
+				i, crc->sg_cpu[i].start_addr,
+				crc->sg_cpu[i].cfg, crc->sg_cpu[i].x_count,
+				crc->sg_cpu[i].x_modify);
+			i++;
 		}
+
+		dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 | DMAEN | PSIZE_32;
 		/* chop current sg dma len to multiple of 32 bits */
 		mid_dma_count = dma_count % 4;
 		dma_count &= ~0x3;
@@ -243,24 +261,9 @@ static void bfin_crypto_crc_config_dma(struct bfin_crypto_crc *crc)
 
 		if (mid_dma_count) {
 			/* copy extra bytes to next middle dma buffer */
-			dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 |
-				DMAEN | PSIZE_32 | WDSIZE_32;
 			memcpy(crc->sg_mid_buf + (i << 2),
-				(void *)(dma_addr + (dma_count << 2)),
+				(u8*)sg_virt(sg) + (dma_count << 2),
 				mid_dma_count);
-			/* setup new dma descriptor for next middle dma */
-			crc->sg_cpu[i].start_addr = dma_map_single(crc->dev,
-					crc->sg_mid_buf + (i << 2),
-					CHKSUM_DIGEST_SIZE, DMA_TO_DEVICE);
-			crc->sg_cpu[i].cfg = dma_config;
-			crc->sg_cpu[i].x_count = 1;
-			crc->sg_cpu[i].x_modify = CHKSUM_DIGEST_SIZE;
-			dev_dbg(crc->dev, "%d: crc_dma: start_addr:0x%lx, "
-				"cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n",
-				i, crc->sg_cpu[i].start_addr,
-				crc->sg_cpu[i].cfg, crc->sg_cpu[i].x_count,
-				crc->sg_cpu[i].x_modify);
-			i++;
 		}
 	}
 
@@ -303,6 +306,7 @@ static int bfin_crypto_crc_handle_queue(struct bfin_crypto_crc *crc,
 	int nsg, i, j;
 	unsigned int nextlen;
 	unsigned long flags;
+	u32 reg;
 
 	spin_lock_irqsave(&crc->lock, flags);
 	if (req)
@@ -402,13 +406,14 @@ finish_update:
 		ctx->sg_buflen += CHKSUM_DIGEST_SIZE;
 
 	/* set CRC data count before start DMA */
-	crc->regs->datacnt = ctx->sg_buflen >> 2;
+	writel(ctx->sg_buflen >> 2, &crc->regs->datacnt);
 
 	/* setup and enable CRC DMA */
 	bfin_crypto_crc_config_dma(crc);
 
 	/* finally kick off CRC operation */
-	crc->regs->control |= BLKEN;
+	reg = readl(&crc->regs->control);
+	writel(reg | BLKEN, &crc->regs->control);
 
 	return -EINPROGRESS;
 }
@@ -529,14 +534,17 @@ static void bfin_crypto_crc_done_task(unsigned long data)
 static irqreturn_t bfin_crypto_crc_handler(int irq, void *dev_id)
 {
 	struct bfin_crypto_crc *crc = dev_id;
+	u32 reg;
 
-	if (crc->regs->status & DCNTEXP) {
-		crc->regs->status = DCNTEXP;
+	if (readl(&crc->regs->status) & DCNTEXP) {
+		writel(DCNTEXP, &crc->regs->status);
 
 		/* prepare results */
-		put_unaligned_le32(crc->regs->result, crc->req->result);
+		put_unaligned_le32(readl(&crc->regs->result),
+			crc->req->result);
 
-		crc->regs->control &= ~BLKEN;
+		reg = readl(&crc->regs->control);
+		writel(reg & ~BLKEN, &crc->regs->control);
 		crc->busy = 0;
 
 		if (crc->req->base.complete)
@@ -560,7 +568,7 @@ static int bfin_crypto_crc_suspend(struct platform_device *pdev, pm_message_t st
 	struct bfin_crypto_crc *crc = platform_get_drvdata(pdev);
 	int i = 100000;
 
-	while ((crc->regs->control & BLKEN) && --i)
+	while ((readl(&crc->regs->control) & BLKEN) && --i)
 		cpu_relax();
 
 	if (i == 0)
@@ -647,29 +655,32 @@ static int bfin_crypto_crc_probe(struct platform_device *pdev)
 	 * 1 last + 1 next dma descriptors
 	 */
 	crc->sg_mid_buf = (u8 *)(crc->sg_cpu + ((CRC_MAX_DMA_DESC + 1) << 1));
+	crc->sg_mid_dma = crc->sg_dma + sizeof(struct dma_desc_array)
+			* ((CRC_MAX_DMA_DESC + 1) << 1);
 
-	crc->regs->control = 0;
-	crc->regs->poly = crc->poly = (u32)pdev->dev.platform_data;
+	writel(0, &crc->regs->control);
+	crc->poly = (u32)pdev->dev.platform_data;
+	writel(crc->poly, &crc->regs->poly);
 
-	while (!(crc->regs->status & LUTDONE) && (--timeout) > 0)
+	while (!(readl(&crc->regs->status) & LUTDONE) && (--timeout) > 0)
 		cpu_relax();
 
 	if (timeout == 0)
 		dev_info(&pdev->dev, "init crc poly timeout\n");
 
+	platform_set_drvdata(pdev, crc);
+
 	spin_lock(&crc_list.lock);
 	list_add(&crc->list, &crc_list.dev_list);
 	spin_unlock(&crc_list.lock);
 
-	platform_set_drvdata(pdev, crc);
-
-	ret = crypto_register_ahash(&algs);
-	if (ret) {
-		spin_lock(&crc_list.lock);
-		list_del(&crc->list);
-		spin_unlock(&crc_list.lock);
-		dev_err(&pdev->dev, "Cann't register crypto ahash device\n");
-		goto out_error_dma;
+	if (list_is_singular(&crc_list.dev_list)) {
+		ret = crypto_register_ahash(&algs);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Can't register crypto ahash device\n");
+			goto out_error_dma;
+		}
 	}
 
 	dev_info(&pdev->dev, "initialized\n");
diff --git a/drivers/crypto/bfin_crc.h b/drivers/crypto/bfin_crc.h
new file mode 100644
index 000000000000..75cef4dc85a1
--- /dev/null
+++ b/drivers/crypto/bfin_crc.h
@@ -0,0 +1,125 @@
+/*
+ * bfin_crc.h - interface to Blackfin CRC controllers
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_CRC_H__
+#define __BFIN_CRC_H__
+
+/* Function driver which use hardware crc must initialize the structure */
+struct crc_info {
+	/* Input data address */
+	unsigned char *in_addr;
+	/* Output data address */
+	unsigned char *out_addr;
+	/* Input or output bytes */
+	unsigned long datasize;
+	union {
+	/* CRC to compare with that of input buffer */
+	unsigned long crc_compare;
+	/* Value to compare with input data */
+	unsigned long val_verify;
+	/* Value to fill */
+	unsigned long val_fill;
+	};
+	/* Value to program the 32b CRC Polynomial */
+	unsigned long crc_poly;
+	union {
+	/* CRC calculated from the input data */
+	unsigned long crc_result;
+	/* First failed position to verify input data */
+	unsigned long pos_verify;
+	};
+	/* CRC mirror flags */
+	unsigned int bitmirr:1;
+	unsigned int bytmirr:1;
+	unsigned int w16swp:1;
+	unsigned int fdsel:1;
+	unsigned int rsltmirr:1;
+	unsigned int polymirr:1;
+	unsigned int cmpmirr:1;
+};
+
+/* Userspace interface */
+#define CRC_IOC_MAGIC		'C'
+#define CRC_IOC_CALC_CRC	_IOWR('C', 0x01, unsigned int)
+#define CRC_IOC_MEMCPY_CRC	_IOWR('C', 0x02, unsigned int)
+#define CRC_IOC_VERIFY_VAL	_IOWR('C', 0x03, unsigned int)
+#define CRC_IOC_FILL_VAL	_IOWR('C', 0x04, unsigned int)
+
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/miscdevice.h>
+
+struct crc_register {
+	u32 control;
+	u32 datacnt;
+	u32 datacntrld;
+	u32 __pad_1[2];
+	u32 compare;
+	u32 fillval;
+	u32 datafifo;
+	u32 intren;
+	u32 intrenset;
+	u32 intrenclr;
+	u32 poly;
+	u32 __pad_2[4];
+	u32 status;
+	u32 datacntcap;
+	u32 __pad_3;
+	u32 result;
+	u32 curresult;
+	u32 __pad_4[3];
+	u32 revid;
+};
+
+/* CRC_STATUS Masks */
+#define CMPERR			0x00000002	/* Compare error */
+#define DCNTEXP			0x00000010	/* datacnt register expired */
+#define IBR			0x00010000	/* Input buffer ready */
+#define OBR			0x00020000	/* Output buffer ready */
+#define IRR			0x00040000	/* Immediate result readt */
+#define LUTDONE			0x00080000	/* Look-up table generation done */
+#define FSTAT			0x00700000	/* FIFO status */
+#define MAX_FIFO		4		/* Max fifo size */
+
+/* CRC_CONTROL Masks */
+#define BLKEN			0x00000001	/* Block enable */
+#define OPMODE			0x000000F0	/* Operation mode */
+#define OPMODE_OFFSET		4		/* Operation mode mask offset*/
+#define MODE_DMACPY_CRC		1		/* MTM CRC compute and compare */
+#define MODE_DATA_FILL		2		/* MTM data fill */
+#define MODE_CALC_CRC		3		/* MSM CRC compute and compare */
+#define MODE_DATA_VERIFY	4		/* MSM data verify */
+#define AUTOCLRZ		0x00000100	/* Auto clear to zero */
+#define AUTOCLRF		0x00000200	/* Auto clear to one */
+#define OBRSTALL		0x00001000	/* Stall on output buffer ready */
+#define IRRSTALL		0x00002000	/* Stall on immediate result ready */
+#define BITMIRR			0x00010000	/* Mirror bits within each byte of 32-bit input data */
+#define BITMIRR_OFFSET		16		/* Mirror bits offset */
+#define BYTMIRR			0x00020000	/* Mirror bytes of 32-bit input data */
+#define BYTMIRR_OFFSET		17		/* Mirror bytes offset */
+#define W16SWP			0x00040000	/* Mirror uppper and lower 16-bit word of 32-bit input data */
+#define W16SWP_OFFSET		18		/* Mirror 16-bit word offset */
+#define FDSEL			0x00080000	/* FIFO is written after input data is mirrored */
+#define FDSEL_OFFSET		19		/* Mirror FIFO offset */
+#define RSLTMIRR		0x00100000	/* CRC result registers are mirrored. */
+#define RSLTMIRR_OFFSET		20		/* Mirror CRC result offset. */
+#define POLYMIRR		0x00200000	/* CRC poly register is mirrored. */
+#define POLYMIRR_OFFSET		21		/* Mirror CRC poly offset. */
+#define CMPMIRR			0x00400000	/* CRC compare register is mirrored. */
+#define CMPMIRR_OFFSET		22		/* Mirror CRC compare offset. */
+
+/* CRC_INTREN Masks */
+#define CMPERRI 		0x02		/* CRC_ERROR_INTR */
+#define DCNTEXPI 		0x10		/* CRC_STATUS_INTR */
+
+#endif
+
+#endif
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index 93319f9db753..0d746236df5e 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -48,12 +48,11 @@ static int ccp_get_msix_irqs(struct ccp_device *ccp)
 	for (v = 0; v < ARRAY_SIZE(msix_entry); v++)
 		msix_entry[v].entry = v;
 
-	while ((ret = pci_enable_msix(pdev, msix_entry, v)) > 0)
-		v = ret;
-	if (ret)
+	ret = pci_enable_msix_range(pdev, msix_entry, 1, v);
+	if (ret < 0)
 		return ret;
 
-	ccp_pci->msix_count = v;
+	ccp_pci->msix_count = ret;
 	for (v = 0; v < ccp_pci->msix_count; v++) {
 		/* Set the interrupt names and request the irqs */
 		snprintf(ccp_pci->msix[v].name, name_len, "ccp-%u", v);
diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c
index 1e5481d88a26..c4fcbf47475f 100644
--- a/drivers/crypto/nx/nx-842.c
+++ b/drivers/crypto/nx/nx-842.c
@@ -1234,7 +1234,7 @@ static int __exit nx842_remove(struct vio_dev *viodev)
 	old_devdata = rcu_dereference_check(devdata,
 			lockdep_is_held(&devdata_mutex));
 	of_reconfig_notifier_unregister(&nx842_of_nb);
-	rcu_assign_pointer(devdata, NULL);
+	RCU_INIT_POINTER(devdata, NULL);
 	spin_unlock_irqrestore(&devdata_mutex, flags);
 	synchronize_rcu();
 	dev_set_drvdata(&viodev->dev, NULL);
@@ -1285,7 +1285,7 @@ static void __exit nx842_exit(void)
 	spin_lock_irqsave(&devdata_mutex, flags);
 	old_devdata = rcu_dereference_check(devdata,
 			lockdep_is_held(&devdata_mutex));
-	rcu_assign_pointer(devdata, NULL);
+	RCU_INIT_POINTER(devdata, NULL);
 	spin_unlock_irqrestore(&devdata_mutex, flags);
 	synchronize_rcu();
 	if (old_devdata)
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index ec5f13162b73..b8bc84be8741 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -223,12 +223,19 @@ static void omap_des_write_n(struct omap_des_dev *dd, u32 offset,
 
 static int omap_des_hw_init(struct omap_des_dev *dd)
 {
+	int err;
+
 	/*
 	 * clocks are enabled when request starts and disabled when finished.
 	 * It may be long delays between requests.
 	 * Device might go to off mode to save power.
 	 */
-	pm_runtime_get_sync(dd->dev);
+	err = pm_runtime_get_sync(dd->dev);
+	if (err < 0) {
+		pm_runtime_put_noidle(dd->dev);
+		dev_err(dd->dev, "%s: failed to get_sync(%d)\n", __func__, err);
+		return err;
+	}
 
 	if (!(dd->flags & FLAGS_INIT)) {
 		dd->flags |= FLAGS_INIT;
@@ -1074,16 +1081,20 @@ static int omap_des_probe(struct platform_device *pdev)
 	if (err)
 		goto err_res;
 
-	dd->io_base = devm_request_and_ioremap(dev, res);
-	if (!dd->io_base) {
-		dev_err(dev, "can't ioremap\n");
-		err = -ENOMEM;
+	dd->io_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(dd->io_base)) {
+		err = PTR_ERR(dd->io_base);
 		goto err_res;
 	}
 	dd->phys_base = res->start;
 
 	pm_runtime_enable(dev);
-	pm_runtime_get_sync(dev);
+	err = pm_runtime_get_sync(dev);
+	if (err < 0) {
+		pm_runtime_put_noidle(dev);
+		dev_err(dd->dev, "%s: failed to get_sync(%d)\n", __func__, err);
+		goto err_get;
+	}
 
 	omap_des_dma_stop(dd);
 
@@ -1148,6 +1159,7 @@ err_algs:
 err_irq:
 	tasklet_kill(&dd->done_task);
 	tasklet_kill(&dd->queue_task);
+err_get:
 	pm_runtime_disable(dev);
 err_res:
 	dd = NULL;
@@ -1191,7 +1203,14 @@ static int omap_des_suspend(struct device *dev)
 
 static int omap_des_resume(struct device *dev)
 {
-	pm_runtime_get_sync(dev);
+	int err;
+
+	err = pm_runtime_get_sync(dev);
+	if (err < 0) {
+		pm_runtime_put_noidle(dev);
+		dev_err(dev, "%s: failed to get_sync(%d)\n", __func__, err);
+		return err;
+	}
 	return 0;
 }
 #endif
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index ba06d1d2f99e..5c5863842de9 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -197,7 +197,7 @@ config AMCC_PPC440SPE_ADMA
 
 config TIMB_DMA
 	tristate "Timberdale FPGA DMA support"
-	depends on MFD_TIMBERDALE || HAS_IOMEM
+	depends on MFD_TIMBERDALE
 	select DMA_ENGINE
 	help
 	  Enable support for the Timberdale FPGA DMA engine.
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index a886713937fd..d5d30ed863ce 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -1009,6 +1009,7 @@ static void dmaengine_unmap(struct kref *kref)
 		dma_unmap_page(dev, unmap->addr[i], unmap->len,
 			       DMA_BIDIRECTIONAL);
 	}
+	cnt = unmap->map_cnt;
 	mempool_free(unmap, __get_unmap_pool(cnt)->pool);
 }
 
@@ -1074,6 +1075,7 @@ dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags)
 	memset(unmap, 0, sizeof(*unmap));
 	kref_init(&unmap->kref);
 	unmap->dev = dev;
+	unmap->map_cnt = nr;
 
 	return unmap;
 }
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index cd04eb7b182e..926360c2db6a 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -182,11 +182,13 @@ static void edma_execute(struct edma_chan *echan)
 				  echan->ecc->dummy_slot);
 	}
 
-	edma_resume(echan->ch_num);
-
 	if (edesc->processed <= MAX_NR_SG) {
 		dev_dbg(dev, "first transfer starting %d\n", echan->ch_num);
 		edma_start(echan->ch_num);
+	} else {
+		dev_dbg(dev, "chan: %d: completed %d elements, resuming\n",
+			echan->ch_num, edesc->processed);
+		edma_resume(echan->ch_num);
 	}
 
 	/*
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 381e793184ba..b396a7fb53ab 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -968,7 +968,17 @@ static struct platform_driver fsl_edma_driver = {
 	.remove		= fsl_edma_remove,
 };
 
-module_platform_driver(fsl_edma_driver);
+static int __init fsl_edma_init(void)
+{
+	return platform_driver_register(&fsl_edma_driver);
+}
+subsys_initcall(fsl_edma_init);
+
+static void __exit fsl_edma_exit(void)
+{
+	platform_driver_unregister(&fsl_edma_driver);
+}
+module_exit(fsl_edma_exit);
 
 MODULE_ALIAS("platform:fsl-edma");
 MODULE_DESCRIPTION("Freescale eDMA engine driver");
diff --git a/drivers/dma/ioat/dca.c b/drivers/dma/ioat/dca.c
index 9e84d5bc9307..3b55bb8d969a 100644
--- a/drivers/dma/ioat/dca.c
+++ b/drivers/dma/ioat/dca.c
@@ -35,6 +35,7 @@
 
 #include "dma.h"
 #include "registers.h"
+#include "dma_v2.h"
 
 /*
  * Bit 7 of a tag map entry is the "valid" bit, if it is set then bits 0:6
@@ -147,7 +148,7 @@ static int ioat_dca_add_requester(struct dca_provider *dca, struct device *dev)
 	u16 id;
 
 	/* This implementation only supports PCI-Express */
-	if (dev->bus != &pci_bus_type)
+	if (!dev_is_pci(dev))
 		return -ENODEV;
 	pdev = to_pci_dev(dev);
 	id = dcaid_from_pcidev(pdev);
@@ -179,7 +180,7 @@ static int ioat_dca_remove_requester(struct dca_provider *dca,
 	int i;
 
 	/* This implementation only supports PCI-Express */
-	if (dev->bus != &pci_bus_type)
+	if (!dev_is_pci(dev))
 		return -ENODEV;
 	pdev = to_pci_dev(dev);
 
@@ -320,7 +321,7 @@ static int ioat2_dca_add_requester(struct dca_provider *dca, struct device *dev)
 	u16 global_req_table;
 
 	/* This implementation only supports PCI-Express */
-	if (dev->bus != &pci_bus_type)
+	if (!dev_is_pci(dev))
 		return -ENODEV;
 	pdev = to_pci_dev(dev);
 	id = dcaid_from_pcidev(pdev);
@@ -354,7 +355,7 @@ static int ioat2_dca_remove_requester(struct dca_provider *dca,
 	u16 global_req_table;
 
 	/* This implementation only supports PCI-Express */
-	if (dev->bus != &pci_bus_type)
+	if (!dev_is_pci(dev))
 		return -ENODEV;
 	pdev = to_pci_dev(dev);
 
@@ -496,7 +497,7 @@ static int ioat3_dca_add_requester(struct dca_provider *dca, struct device *dev)
 	u16 global_req_table;
 
 	/* This implementation only supports PCI-Express */
-	if (dev->bus != &pci_bus_type)
+	if (!dev_is_pci(dev))
 		return -ENODEV;
 	pdev = to_pci_dev(dev);
 	id = dcaid_from_pcidev(pdev);
@@ -530,7 +531,7 @@ static int ioat3_dca_remove_requester(struct dca_provider *dca,
 	u16 global_req_table;
 
 	/* This implementation only supports PCI-Express */
-	if (dev->bus != &pci_bus_type)
+	if (!dev_is_pci(dev))
 		return -ENODEV;
 	pdev = to_pci_dev(dev);
 
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 4e3549a16132..b76c1485933b 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -947,7 +947,7 @@ msix:
 	for (i = 0; i < msixcnt; i++)
 		device->msix_entries[i].entry = i;
 
-	err = pci_enable_msix(pdev, device->msix_entries, msixcnt);
+	err = pci_enable_msix_exact(pdev, device->msix_entries, msixcnt);
 	if (err)
 		goto msi;
 
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index b9b38a1cf92f..85971d6e9646 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -740,7 +740,7 @@ ioat3_prep_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
 	return __ioat3_prep_xor_lock(chan, NULL, dest, src, src_cnt, len, flags);
 }
 
-struct dma_async_tx_descriptor *
+static struct dma_async_tx_descriptor *
 ioat3_prep_xor_val(struct dma_chan *chan, dma_addr_t *src,
 		    unsigned int src_cnt, size_t len,
 		    enum sum_check_flags *result, unsigned long flags)
@@ -1091,7 +1091,7 @@ ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
 	}
 }
 
-struct dma_async_tx_descriptor *
+static struct dma_async_tx_descriptor *
 ioat3_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
 		  unsigned int src_cnt, const unsigned char *scf, size_t len,
 		  enum sum_check_flags *pqres, unsigned long flags)
@@ -1133,7 +1133,7 @@ ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,
 				     flags);
 }
 
-struct dma_async_tx_descriptor *
+static struct dma_async_tx_descriptor *
 ioat3_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src,
 		     unsigned int src_cnt, size_t len,
 		     enum sum_check_flags *result, unsigned long flags)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 766b68ed505c..7938272f2edf 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -191,12 +191,10 @@ static void mv_set_mode(struct mv_xor_chan *chan,
 
 static void mv_chan_activate(struct mv_xor_chan *chan)
 {
-	u32 activation;
-
 	dev_dbg(mv_chan_to_devp(chan), " activate chan.\n");
-	activation = readl_relaxed(XOR_ACTIVATION(chan));
-	activation |= 0x1;
-	writel_relaxed(activation, XOR_ACTIVATION(chan));
+
+	/* writel ensures all descriptors are flushed before activation */
+	writel(BIT(0), XOR_ACTIVATION(chan));
 }
 
 static char mv_chan_is_busy(struct mv_xor_chan *chan)
@@ -312,7 +310,8 @@ mv_xor_clean_slot(struct mv_xor_desc_slot *desc,
 	return 0;
 }
 
-static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
+/* This function must be called with the mv_xor_chan spinlock held */
+static void mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
 {
 	struct mv_xor_desc_slot *iter, *_iter;
 	dma_cookie_t cookie = 0;
@@ -368,18 +367,13 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
 		mv_chan->dmachan.completed_cookie = cookie;
 }
 
-static void
-mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
-{
-	spin_lock_bh(&mv_chan->lock);
-	__mv_xor_slot_cleanup(mv_chan);
-	spin_unlock_bh(&mv_chan->lock);
-}
-
 static void mv_xor_tasklet(unsigned long data)
 {
 	struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
+
+	spin_lock_bh(&chan->lock);
 	mv_xor_slot_cleanup(chan);
+	spin_unlock_bh(&chan->lock);
 }
 
 static struct mv_xor_desc_slot *
@@ -658,9 +652,10 @@ static void mv_xor_free_chan_resources(struct dma_chan *chan)
 	struct mv_xor_desc_slot *iter, *_iter;
 	int in_use_descs = 0;
 
+	spin_lock_bh(&mv_chan->lock);
+
 	mv_xor_slot_cleanup(mv_chan);
 
-	spin_lock_bh(&mv_chan->lock);
 	list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
 					chain_node) {
 		in_use_descs++;
@@ -702,11 +697,12 @@ static enum dma_status mv_xor_status(struct dma_chan *chan,
 	enum dma_status ret;
 
 	ret = dma_cookie_status(chan, cookie, txstate);
-	if (ret == DMA_COMPLETE) {
-		mv_xor_clean_completed_slots(mv_chan);
+	if (ret == DMA_COMPLETE)
 		return ret;
-	}
+
+	spin_lock_bh(&mv_chan->lock);
 	mv_xor_slot_cleanup(mv_chan);
+	spin_unlock_bh(&mv_chan->lock);
 
 	return dma_cookie_status(chan, cookie, txstate);
 }
@@ -784,7 +780,7 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
 
 static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
 {
-	int i;
+	int i, ret;
 	void *src, *dest;
 	dma_addr_t src_dma, dest_dma;
 	struct dma_chan *dma_chan;
@@ -821,19 +817,44 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
 
 	src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0,
 				 PAGE_SIZE, DMA_TO_DEVICE);
-	unmap->to_cnt = 1;
 	unmap->addr[0] = src_dma;
 
+	ret = dma_mapping_error(dma_chan->device->dev, src_dma);
+	if (ret) {
+		err = -ENOMEM;
+		goto free_resources;
+	}
+	unmap->to_cnt = 1;
+
 	dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0,
 				  PAGE_SIZE, DMA_FROM_DEVICE);
-	unmap->from_cnt = 1;
 	unmap->addr[1] = dest_dma;
 
+	ret = dma_mapping_error(dma_chan->device->dev, dest_dma);
+	if (ret) {
+		err = -ENOMEM;
+		goto free_resources;
+	}
+	unmap->from_cnt = 1;
 	unmap->len = PAGE_SIZE;
 
 	tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
 				    PAGE_SIZE, 0);
+	if (!tx) {
+		dev_err(dma_chan->device->dev,
+			"Self-test cannot prepare operation, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
 	cookie = mv_xor_tx_submit(tx);
+	if (dma_submit_error(cookie)) {
+		dev_err(dma_chan->device->dev,
+			"Self-test submit error, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
 	mv_xor_issue_pending(dma_chan);
 	async_tx_ack(tx);
 	msleep(1);
@@ -868,7 +889,7 @@ out:
 static int
 mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
 {
-	int i, src_idx;
+	int i, src_idx, ret;
 	struct page *dest;
 	struct page *xor_srcs[MV_XOR_NUM_SRC_TEST];
 	dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
@@ -931,19 +952,42 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
 		unmap->addr[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
 					      0, PAGE_SIZE, DMA_TO_DEVICE);
 		dma_srcs[i] = unmap->addr[i];
+		ret = dma_mapping_error(dma_chan->device->dev, unmap->addr[i]);
+		if (ret) {
+			err = -ENOMEM;
+			goto free_resources;
+		}
 		unmap->to_cnt++;
 	}
 
 	unmap->addr[src_count] = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
 				      DMA_FROM_DEVICE);
 	dest_dma = unmap->addr[src_count];
+	ret = dma_mapping_error(dma_chan->device->dev, unmap->addr[src_count]);
+	if (ret) {
+		err = -ENOMEM;
+		goto free_resources;
+	}
 	unmap->from_cnt = 1;
 	unmap->len = PAGE_SIZE;
 
 	tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
 				 src_count, PAGE_SIZE, 0);
+	if (!tx) {
+		dev_err(dma_chan->device->dev,
+			"Self-test cannot prepare operation, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
 
 	cookie = mv_xor_tx_submit(tx);
+	if (dma_submit_error(cookie)) {
+		dev_err(dma_chan->device->dev,
+			"Self-test submit error, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
 	mv_xor_issue_pending(dma_chan);
 	async_tx_ack(tx);
 	msleep(8);
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index a1bd8298d55f..03f7820fa333 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -666,7 +666,7 @@ static struct dma_chan *of_dma_sirfsoc_xlate(struct of_phandle_args *dma_spec,
 	struct sirfsoc_dma *sdma = ofdma->of_dma_data;
 	unsigned int request = dma_spec->args[0];
 
-	if (request > SIRFSOC_DMA_CHANNELS)
+	if (request >= SIRFSOC_DMA_CHANNELS)
 		return NULL;
 
 	return dma_get_slave_channel(&sdma->channels[request].chan);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a86c49a605c6..c58b828e882f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -243,6 +243,14 @@ config GPIO_OCTEON
 	  Say yes here to support the on-chip GPIO lines on the OCTEON
 	  family of SOCs.
 
+config GPIO_OMAP
+	bool "TI OMAP GPIO support"
+	default y if ARCH_OMAP
+	depends on ARM && ARCH_OMAP
+	select GPIOLIB_IRQCHIP
+	help
+	  Say yes here to enable GPIO support for TI OMAP SoCs.
+
 config GPIO_PL061
 	bool "PrimeCell PL061 GPIO support"
 	depends on ARM_AMBA
@@ -579,6 +587,7 @@ config GPIO_STP_XWAY
 config GPIO_TC3589X
 	bool "TC3589X GPIOs"
 	depends on MFD_TC3589X
+	select GPIOLIB_IRQCHIP
 	help
 	  This enables support for the GPIOs found on the TC3589X
 	  I/O Expander.
@@ -739,7 +748,7 @@ config GPIO_SODAVILLE
 
 config GPIO_TIMBERDALE
 	bool "Support for timberdale GPIO IP"
-	depends on MFD_TIMBERDALE && HAS_IOMEM
+	depends on MFD_TIMBERDALE
 	---help---
 	Add support for the GPIO IP in the timberdale FPGA.
 
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 6309aff1d806..d10f6a9d875a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -58,7 +58,7 @@ obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o
 obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o
 obj-$(CONFIG_GPIO_OCTEON)	+= gpio-octeon.o
-obj-$(CONFIG_ARCH_OMAP)		+= gpio-omap.o
+obj-$(CONFIG_GPIO_OMAP)		+= gpio-omap.o
 obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index ed5711f77e2d..4d25a06bb45e 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -260,9 +260,6 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
 	ct->regs.ack = GPIO_PORTA_EOI;
 	ct->regs.mask = GPIO_INTMASK;
 
-	irq_setup_generic_chip(irq_gc, IRQ_MSK(port->bgc.gc.ngpio),
-			IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
-
 	irq_set_chained_handler(irq, dwapb_irq_handler);
 	irq_set_handler_data(irq, gpio);
 
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 19b886c21b1d..8cc9e91e7e4e 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -24,7 +24,6 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/irqdomain.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
@@ -52,7 +51,6 @@ struct gpio_bank {
 	struct list_head node;
 	void __iomem *base;
 	u16 irq;
-	struct irq_domain *domain;
 	u32 non_wakeup_gpios;
 	u32 enabled_non_wakeup_gpios;
 	struct gpio_regs context;
@@ -95,11 +93,10 @@ static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
 	return bank->chip.base + gpio_irq;
 }
 
-static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)
 {
-	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
-
-	return irq_find_mapping(bank->domain, offset);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+	return container_of(chip, struct gpio_bank, chip);
 }
 
 static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
@@ -479,7 +476,7 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
 
 static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_bank *bank = _irq_data_get_bank(d);
 	unsigned gpio = 0;
 	int retval;
 	unsigned long flags;
@@ -514,14 +511,6 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
 		return -EINVAL;
 	}
 
-	retval = gpio_lock_as_irq(&bank->chip, offset);
-	if (retval) {
-		dev_err(bank->dev, "unable to lock offset %d for IRQ\n",
-			offset);
-		spin_unlock_irqrestore(&bank->lock, flags);
-		return retval;
-	}
-
 	bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
@@ -664,7 +653,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_bank *bank = _irq_data_get_bank(d);
 	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 
 	return _set_gpio_wakeup(bank, gpio, enable);
@@ -732,11 +721,12 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	unsigned int bit;
 	struct gpio_bank *bank;
 	int unmasked = 0;
-	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	struct gpio_chip *chip = irq_get_handler_data(irq);
 
-	chained_irq_enter(chip, desc);
+	chained_irq_enter(irqchip, desc);
 
-	bank = irq_get_handler_data(irq);
+	bank = container_of(chip, struct gpio_bank, chip);
 	isr_reg = bank->base + bank->regs->irqstatus;
 	pm_runtime_get_sync(bank->dev);
 
@@ -764,7 +754,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 		configured, we could unmask GPIO bank interrupt immediately */
 		if (!level_mask && !unmasked) {
 			unmasked = 1;
-			chained_irq_exit(chip, desc);
+			chained_irq_exit(irqchip, desc);
 		}
 
 		if (!isr)
@@ -784,7 +774,8 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 			if (bank->toggle_mask & (1 << bit))
 				_toggle_gpio_edge_triggering(bank, bit);
 
-			generic_handle_irq(irq_find_mapping(bank->domain, bit));
+			generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
+							    bit));
 		}
 	}
 	/* if bank has any level sensitive GPIO pin interrupt
@@ -793,13 +784,13 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	interrupt */
 exit:
 	if (!unmasked)
-		chained_irq_exit(chip, desc);
+		chained_irq_exit(irqchip, desc);
 	pm_runtime_put(bank->dev);
 }
 
 static void gpio_irq_shutdown(struct irq_data *d)
 {
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_bank *bank = _irq_data_get_bank(d);
 	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 	unsigned long flags;
 	unsigned offset = GPIO_INDEX(bank, gpio);
@@ -821,7 +812,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
 
 static void gpio_ack_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_bank *bank = _irq_data_get_bank(d);
 	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 
 	_clear_gpio_irqstatus(bank, gpio);
@@ -829,7 +820,7 @@ static void gpio_ack_irq(struct irq_data *d)
 
 static void gpio_mask_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_bank *bank = _irq_data_get_bank(d);
 	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 	unsigned long flags;
 
@@ -841,7 +832,7 @@ static void gpio_mask_irq(struct irq_data *d)
 
 static void gpio_unmask_irq(struct irq_data *d)
 {
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_bank *bank = _irq_data_get_bank(d);
 	unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 	unsigned int irq_mask = GPIO_BIT(bank, gpio);
 	u32 trigger = irqd_get_trigger_type(d);
@@ -1081,10 +1072,12 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static void omap_gpio_chip_init(struct gpio_bank *bank)
+static int omap_gpio_chip_init(struct gpio_bank *bank)
 {
 	int j;
 	static int gpio;
+	int irq_base = 0;
+	int ret;
 
 	/*
 	 * REVISIT eventually switch from OMAP-specific gpio structs
@@ -1097,7 +1090,6 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
 	bank->chip.direction_output = gpio_output;
 	bank->chip.set_debounce = gpio_debounce;
 	bank->chip.set = gpio_set;
-	bank->chip.to_irq = omap_gpio_to_irq;
 	if (bank->is_mpuio) {
 		bank->chip.label = "mpuio";
 		if (bank->regs->wkup_en)
@@ -1110,22 +1102,48 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
 	}
 	bank->chip.ngpio = bank->width;
 
-	gpiochip_add(&bank->chip);
+	ret = gpiochip_add(&bank->chip);
+	if (ret) {
+		dev_err(bank->dev, "Could not register gpio chip %d\n", ret);
+		return ret;
+	}
+
+#ifdef CONFIG_ARCH_OMAP1
+	/*
+	 * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
+	 * irq_alloc_descs() since a base IRQ offset will no longer be needed.
+	 */
+	irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
+	if (irq_base < 0) {
+		dev_err(bank->dev, "Couldn't allocate IRQ numbers\n");
+		return -ENODEV;
+	}
+#endif
+
+	ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip,
+				   irq_base, gpio_irq_handler,
+				   IRQ_TYPE_NONE);
+
+	if (ret) {
+		dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret);
+		ret = gpiochip_remove(&bank->chip);
+		return -ENODEV;
+	}
+
+	gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip,
+				     bank->irq, gpio_irq_handler);
 
 	for (j = 0; j < bank->width; j++) {
-		int irq = irq_create_mapping(bank->domain, j);
+		int irq = irq_find_mapping(bank->chip.irqdomain, j);
 		irq_set_lockdep_class(irq, &gpio_lock_class);
-		irq_set_chip_data(irq, bank);
 		if (bank->is_mpuio) {
 			omap_mpuio_alloc_gc(bank, irq, bank->width);
-		} else {
-			irq_set_chip_and_handler(irq, &gpio_irq_chip,
-						 handle_simple_irq);
-			set_irq_flags(irq, IRQF_VALID);
+			irq_set_chip_and_handler(irq, NULL, NULL);
+			set_irq_flags(irq, 0);
 		}
 	}
-	irq_set_chained_handler(bank->irq, gpio_irq_handler);
-	irq_set_handler_data(bank->irq, bank);
+
+	return 0;
 }
 
 static const struct of_device_id omap_gpio_match[];
@@ -1138,9 +1156,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 	const struct omap_gpio_platform_data *pdata;
 	struct resource *res;
 	struct gpio_bank *bank;
-#ifdef CONFIG_ARCH_OMAP1
-	int irq_base;
-#endif
+	int ret;
 
 	match = of_match_device(of_match_ptr(omap_gpio_match), dev);
 
@@ -1162,6 +1178,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 
 	bank->irq = res->start;
 	bank->dev = dev;
+	bank->chip.dev = dev;
 	bank->dbck_flag = pdata->dbck_flag;
 	bank->stride = pdata->bank_stride;
 	bank->width = pdata->bank_width;
@@ -1182,29 +1199,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
 				pdata->get_context_loss_count;
 	}
 
-#ifdef CONFIG_ARCH_OMAP1
-	/*
-	 * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
-	 * irq_alloc_descs() and irq_domain_add_legacy() and just use a
-	 * linear IRQ domain mapping for all OMAP platforms.
-	 */
-	irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
-	if (irq_base < 0) {
-		dev_err(dev, "Couldn't allocate IRQ numbers\n");
-		return -ENODEV;
-	}
-
-	bank->domain = irq_domain_add_legacy(node, bank->width, irq_base,
-					     0, &irq_domain_simple_ops, NULL);
-#else
-	bank->domain = irq_domain_add_linear(node, bank->width,
-					     &irq_domain_simple_ops, NULL);
-#endif
-	if (!bank->domain) {
-		dev_err(dev, "Couldn't register an IRQ domain\n");
-		return -ENODEV;
-	}
-
 	if (bank->regs->set_dataout && bank->regs->clr_dataout)
 		bank->set_dataout = _set_gpio_dataout_reg;
 	else
@@ -1216,7 +1210,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	bank->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(bank->base)) {
-		irq_domain_remove(bank->domain);
+		irq_domain_remove(bank->chip.irqdomain);
 		return PTR_ERR(bank->base);
 	}
 
@@ -1230,7 +1224,11 @@ static int omap_gpio_probe(struct platform_device *pdev)
 		mpuio_init(bank);
 
 	omap_gpio_mod_init(bank);
-	omap_gpio_chip_init(bank);
+
+	ret = omap_gpio_chip_init(bank);
+	if (ret)
+		return ret;
+
 	omap_gpio_show_rev(bank);
 
 	pm_runtime_put(bank->dev);
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 1019320984d7..51f7cbd9ff71 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -12,8 +12,6 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/tc3589x.h>
 
@@ -31,10 +29,6 @@ struct tc3589x_gpio {
 	struct tc3589x *tc3589x;
 	struct device *dev;
 	struct mutex irq_lock;
-	struct irq_domain *domain;
-
-	int irq_base;
-
 	/* Caches of interrupt control registers for bus_lock */
 	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
 	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
@@ -95,30 +89,6 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
 	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
 }
 
-/**
- * tc3589x_gpio_irq_get_irq(): Map a hardware IRQ on a chip to a Linux IRQ
- *
- * @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
- * @irq: index of the hardware interrupt requested in the chip IRQs
- *
- * Useful for drivers to request their own IRQs.
- */
-static int tc3589x_gpio_irq_get_irq(struct tc3589x_gpio *tc3589x_gpio,
-				     int hwirq)
-{
-	if (!tc3589x_gpio)
-		return -EINVAL;
-
-	return irq_create_mapping(tc3589x_gpio->domain, hwirq);
-}
-
-static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-
-	return tc3589x_gpio_irq_get_irq(tc3589x_gpio, offset);
-}
-
 static struct gpio_chip template_chip = {
 	.label			= "tc3589x",
 	.owner			= THIS_MODULE,
@@ -126,13 +96,13 @@ static struct gpio_chip template_chip = {
 	.get			= tc3589x_gpio_get,
 	.direction_output	= tc3589x_gpio_direction_output,
 	.set			= tc3589x_gpio_set,
-	.to_irq			= tc3589x_gpio_to_irq,
 	.can_sleep		= true,
 };
 
 static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
@@ -159,14 +129,16 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 
 static void tc3589x_gpio_irq_lock(struct irq_data *d)
 {
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
 
 	mutex_lock(&tc3589x_gpio->irq_lock);
 }
 
 static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
 {
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
 	static const u8 regmap[] = {
 		[REG_IBE]	= TC3589x_GPIOIBE0,
@@ -194,7 +166,8 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
 
 static void tc3589x_gpio_irq_mask(struct irq_data *d)
 {
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
@@ -204,7 +177,8 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
 
 static void tc3589x_gpio_irq_unmask(struct irq_data *d)
 {
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
@@ -242,7 +216,8 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = i * 8 + bit;
-			int irq = tc3589x_gpio_irq_get_irq(tc3589x_gpio, line);
+			int irq = irq_find_mapping(tc3589x_gpio->chip.irqdomain,
+						   line);
 
 			handle_nested_irq(irq);
 			stat &= ~(1 << bit);
@@ -254,61 +229,6 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-				irq_hw_number_t hwirq)
-{
-	struct tc3589x *tc3589x_gpio = d->host_data;
-
-	irq_set_chip_data(irq, tc3589x_gpio);
-	irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
-				handle_simple_irq);
-	irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, IRQF_VALID);
-#else
-	irq_set_noprobe(irq);
-#endif
-
-	return 0;
-}
-
-static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
-{
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, 0);
-#endif
-	irq_set_chip_and_handler(irq, NULL, NULL);
-	irq_set_chip_data(irq, NULL);
-}
-
-static struct irq_domain_ops tc3589x_irq_ops = {
-	.map    = tc3589x_gpio_irq_map,
-	.unmap  = tc3589x_gpio_irq_unmap,
-	.xlate  = irq_domain_xlate_twocell,
-};
-
-static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
-				struct device_node *np)
-{
-	int base = tc3589x_gpio->irq_base;
-
-	/*
-	 * If this results in a linear domain, irq_create_mapping() will
-	 * take care of allocating IRQ descriptors at runtime. When a base
-	 * is provided, the IRQ descriptors will be allocated when the
-	 * domain is instantiated.
-	 */
-	tc3589x_gpio->domain = irq_domain_add_simple(np,
-			tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
-			tc3589x_gpio);
-	if (!tc3589x_gpio->domain) {
-		dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
-		return -ENOSYS;
-	}
-
-	return 0;
-}
-
 static int tc3589x_gpio_probe(struct platform_device *pdev)
 {
 	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
@@ -329,7 +249,8 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return irq;
 
-	tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
+	tc3589x_gpio = devm_kzalloc(&pdev->dev, sizeof(struct tc3589x_gpio),
+				    GFP_KERNEL);
 	if (!tc3589x_gpio)
 		return -ENOMEM;
 
@@ -347,30 +268,36 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
 	tc3589x_gpio->chip.of_node = np;
 #endif
 
-	tc3589x_gpio->irq_base = tc3589x->irq_base ?
-		tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0;
-
 	/* Bring the GPIO module out of reset */
 	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
 			       TC3589x_RSTCTRL_GPIRST, 0);
 	if (ret < 0)
-		goto out_free;
-
-	ret = tc3589x_gpio_irq_init(tc3589x_gpio, np);
-	if (ret)
-		goto out_free;
+		return ret;
 
-	ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
-				   "tc3589x-gpio", tc3589x_gpio);
+	ret = devm_request_threaded_irq(&pdev->dev,
+					irq, NULL, tc3589x_gpio_irq,
+					IRQF_ONESHOT, "tc3589x-gpio",
+					tc3589x_gpio);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-		goto out_free;
+		return ret;
 	}
 
 	ret = gpiochip_add(&tc3589x_gpio->chip);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-		goto out_freeirq;
+		return ret;
+	}
+
+	ret =  gpiochip_irqchip_add(&tc3589x_gpio->chip,
+				    &tc3589x_gpio_irq_chip,
+				    0,
+				    handle_simple_irq,
+				    IRQ_TYPE_NONE);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"could not connect irqchip to gpiochip\n");
+		return ret;
 	}
 
 	if (pdata && pdata->setup)
@@ -379,12 +306,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, tc3589x_gpio);
 
 	return 0;
-
-out_freeirq:
-	free_irq(irq, tc3589x_gpio);
-out_free:
-	kfree(tc3589x_gpio);
-	return ret;
 }
 
 static int tc3589x_gpio_remove(struct platform_device *pdev)
@@ -392,7 +313,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
 	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
 	struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
-	int irq = platform_get_irq(pdev, 0);
 	int ret;
 
 	if (pdata && pdata->remove)
@@ -405,10 +325,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
 		return ret;
 	}
 
-	free_irq(irq, tc3589x_gpio);
-
-	kfree(tc3589x_gpio);
-
 	return 0;
 }
 
diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c
index 9bf5034b6cdb..b4d7fa6251b0 100644
--- a/drivers/gpio/gpio-zevio.c
+++ b/drivers/gpio/gpio-zevio.c
@@ -18,6 +18,10 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 
+#ifndef IOMEM
+#define IOMEM(x)    ((void __force __iomem *)(x))
+#endif
+
 /*
  * Memory layout:
  * This chip has four gpio sections, each controls 8 GPIOs.
@@ -209,7 +213,7 @@ static struct platform_driver zevio_gpio_driver = {
 	.driver		= {
 		.name	= "gpio-zevio",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(zevio_gpio_of_match),
+		.of_match_table = zevio_gpio_of_match,
 	},
 	.probe		= zevio_gpio_probe,
 };
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index bf0f8b476696..401add28933f 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -233,7 +233,7 @@ static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
 {
 	struct gpio_chip *chip = acpi_gpio->chip;
 
-	if (!chip->dev || !chip->to_irq)
+	if (!chip->to_irq)
 		return;
 
 	INIT_LIST_HEAD(&acpi_gpio->events);
@@ -253,7 +253,7 @@ static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
 	struct acpi_gpio_event *event, *ep;
 	struct gpio_chip *chip = acpi_gpio->chip;
 
-	if (!chip->dev || !chip->to_irq)
+	if (!chip->to_irq)
 		return;
 
 	list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
@@ -451,7 +451,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
 		if (function == ACPI_WRITE)
 			gpiod_set_raw_value(desc, !!((1 << i) & *value));
 		else
-			*value |= gpiod_get_raw_value(desc) << i;
+			*value |= (u64)gpiod_get_raw_value(desc) << i;
 	}
 
 out:
@@ -501,6 +501,9 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
 	acpi_handle handle;
 	acpi_status status;
 
+	if (!chip || !chip->dev)
+		return;
+
 	handle = ACPI_HANDLE(chip->dev);
 	if (!handle)
 		return;
@@ -531,6 +534,9 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
 	acpi_handle handle;
 	acpi_status status;
 
+	if (!chip || !chip->dev)
+		return;
+
 	handle = ACPI_HANDLE(chip->dev);
 	if (!handle)
 		return;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 761013f8b82f..c12fe9dfd2db 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1363,6 +1363,11 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 				  int parent_irq,
 				  irq_flow_handler_t parent_handler)
 {
+	if (gpiochip->can_sleep) {
+		chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
+		return;
+	}
+
 	irq_set_chained_handler(parent_irq, parent_handler);
 	/*
 	 * The parent irqchip is already using the chip_data for this
@@ -1387,8 +1392,11 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 {
 	struct gpio_chip *chip = d->host_data;
 
-	irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
 	irq_set_chip_data(irq, chip);
+	irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
+	/* Chips that can sleep need nested thread handlers */
+	if (chip->can_sleep)
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 	set_irq_flags(irq, IRQF_VALID);
 #else
@@ -1401,9 +1409,13 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 
 static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
 {
+	struct gpio_chip *chip = d->host_data;
+
 #ifdef CONFIG_ARM
 	set_irq_flags(irq, 0);
 #endif
+	if (chip->can_sleep)
+		irq_set_nested_thread(irq, 0);
 	irq_set_chip_and_handler(irq, NULL, NULL);
 	irq_set_chip_data(irq, NULL);
 }
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 534cb89b160d..ae251b8abd0e 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -131,11 +131,11 @@ drm_clflush_sg(struct sg_table *st)
 EXPORT_SYMBOL(drm_clflush_sg);
 
 void
-drm_clflush_virt_range(char *addr, unsigned long length)
+drm_clflush_virt_range(void *addr, unsigned long length)
 {
 #if defined(CONFIG_X86)
 	if (cpu_has_clflush) {
-		char *end = addr + length;
+		void *end = addr + length;
 		mb();
 		for (; addr < end; addr += boot_cpu_data.x86_clflush_size)
 			clflush(addr);
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 71e2d3fcd6ee..04a209e2b66d 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -207,8 +207,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
 		return 0;
 	}
 
-	WARN(1, "no hole found for node 0x%lx + 0x%lx\n",
-	     node->start, node->size);
 	return -ENOSPC;
 }
 EXPORT_SYMBOL(drm_mm_reserve_node);
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index bea2d67196fb..e4e3c01b8cbc 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -71,7 +71,7 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT
 
 config DRM_I915_UMS
 	bool "Enable userspace modesetting on Intel hardware (DEPRECATED)"
-	depends on DRM_I915
+	depends on DRM_I915 && BROKEN
 	default n
 	help
 	  Choose this option if you still need userspace modesetting.
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index a0f5bdd69491..80449f475960 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -160,7 +160,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 	if (i2c_transfer(adapter, msgs, 2) == 2) {
 		*ch = in_buf[0];
 		return true;
-	};
+	}
 
 	if (!ch7xxx->quiet) {
 		DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index 0f1865d7d4d8..0f2587ff347c 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -195,7 +195,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
 	if (i2c_transfer(adapter, msgs, 3) == 3) {
 		*data = (in_buf[1] << 8) | in_buf[0];
 		return true;
-	};
+	}
 
 	if (!priv->quiet) {
 		DRM_DEBUG_KMS("Unable to read register 0x%02x from "
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c
index 8155ded79079..74f2af7c2d3e 100644
--- a/drivers/gpu/drm/i915/dvo_ns2501.c
+++ b/drivers/gpu/drm/i915/dvo_ns2501.c
@@ -121,7 +121,7 @@ static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
 	if (i2c_transfer(adapter, msgs, 2) == 2) {
 		*ch = in_buf[0];
 		return true;
-	};
+	}
 
 	if (!ns->quiet) {
 		DRM_DEBUG_KMS
@@ -233,9 +233,8 @@ static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
 					      struct drm_display_mode *mode)
 {
 	DRM_DEBUG_KMS
-	    ("%s: is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
-	     __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
-	     mode->vtotal);
+	    ("is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
+	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
 
 	/*
 	 * Currently, these are all the modes I have data from.
@@ -261,9 +260,8 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
 	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
 
 	DRM_DEBUG_KMS
-	    ("%s: set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
-	     __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
-	     mode->vtotal);
+	    ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
+	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
 
 	/*
 	 * Where do I find the native resolution for which scaling is not required???
@@ -277,8 +275,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
 		if (mode->hdisplay == 800 && mode->vdisplay == 600) {
 			/* mode 277 */
 			ns->reg_8_shadow &= ~NS2501_8_BPAS;
-			DRM_DEBUG_KMS("%s: switching to 800x600\n",
-				      __FUNCTION__);
+			DRM_DEBUG_KMS("switching to 800x600\n");
 
 			/*
 			 * No, I do not know where this data comes from.
@@ -341,8 +338,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
 
 		} else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
 			/* mode 274 */
-			DRM_DEBUG_KMS("%s: switching to 640x480\n",
-				      __FUNCTION__);
+			DRM_DEBUG_KMS("switching to 640x480\n");
 			/*
 			 * No, I do not know where this data comes from.
 			 * It is just what the video bios left in the DVO, so
@@ -406,8 +402,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
 
 		} else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
 			/* mode 280 */
-			DRM_DEBUG_KMS("%s: switching to 1024x768\n",
-				      __FUNCTION__);
+			DRM_DEBUG_KMS("switching to 1024x768\n");
 			/*
 			 * This might or might not work, actually. I'm silently
 			 * assuming here that the native panel resolution is
@@ -458,8 +453,7 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
 	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
 	unsigned char ch;
 
-	DRM_DEBUG_KMS("%s: Trying set the dpms of the DVO to %i\n",
-		      __FUNCTION__, enable);
+	DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable);
 
 	ch = ns->reg_8_shadow;
 
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index 7b3e9e936200..fa0114967076 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -93,7 +93,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 	if (i2c_transfer(adapter, msgs, 2) == 2) {
 		*ch = in_buf[0];
 		return true;
-	};
+	}
 
 	if (!sil->quiet) {
 		DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index 12ea4b164692..7853719a0e81 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -118,7 +118,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 	if (i2c_transfer(adapter, msgs, 2) == 2) {
 		*ch = in_buf[0];
 		return true;
-	};
+	}
 
 	if (!tfp->quiet) {
 		DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 4cf6d020d513..9bac0979a294 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -86,6 +86,367 @@
  * general bitmasking mechanism.
  */
 
+#define STD_MI_OPCODE_MASK  0xFF800000
+#define STD_3D_OPCODE_MASK  0xFFFF0000
+#define STD_2D_OPCODE_MASK  0xFFC00000
+#define STD_MFX_OPCODE_MASK 0xFFFF0000
+
+#define CMD(op, opm, f, lm, fl, ...)				\
+	{							\
+		.flags = (fl) | ((f) ? CMD_DESC_FIXED : 0),	\
+		.cmd = { (op), (opm) }, 			\
+		.length = { (lm) },				\
+		__VA_ARGS__					\
+	}
+
+/* Convenience macros to compress the tables */
+#define SMI STD_MI_OPCODE_MASK
+#define S3D STD_3D_OPCODE_MASK
+#define S2D STD_2D_OPCODE_MASK
+#define SMFX STD_MFX_OPCODE_MASK
+#define F true
+#define S CMD_DESC_SKIP
+#define R CMD_DESC_REJECT
+#define W CMD_DESC_REGISTER
+#define B CMD_DESC_BITMASK
+#define M CMD_DESC_MASTER
+
+/*            Command                          Mask   Fixed Len   Action
+	      ---------------------------------------------------------- */
+static const struct drm_i915_cmd_descriptor common_cmds[] = {
+	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
+	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      R  ),
+	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      M  ),
+	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
+	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
+	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
+	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   W,
+	      .reg = { .offset = 1, .mask = 0x007FFFFC }               ),
+	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   W | B,
+	      .reg = { .offset = 1, .mask = 0x007FFFFC },
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   W | B,
+	      .reg = { .offset = 1, .mask = 0x007FFFFC },
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
+};
+
+static const struct drm_i915_cmd_descriptor render_cmds[] = {
+	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
+	CMD(  MI_PREDICATE,                     SMI,    F,  1,      S  ),
+	CMD(  MI_TOPOLOGY_FILTER,               SMI,    F,  1,      S  ),
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_REPORT_PERF_COUNT,             SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 1,
+			.mask = MI_REPORT_PERF_COUNT_GGTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  GFX_OP_3DSTATE_VF_STATISTICS,     S3D,    F,  1,      S  ),
+	CMD(  PIPELINE_SELECT,                  S3D,    F,  1,      S  ),
+	CMD(  MEDIA_VFE_STATE,			S3D,   !F,  0xFFFF, B,
+	      .bits = {{
+			.offset = 2,
+			.mask = MEDIA_VFE_STATE_MMIO_ACCESS_MASK,
+			.expected = 0,
+	      }},						       ),
+	CMD(  GPGPU_OBJECT,                     S3D,   !F,  0xFF,   S  ),
+	CMD(  GPGPU_WALKER,                     S3D,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_SO_DECL_LIST,      S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_PIPE_CONTROL(5),           S3D,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 1,
+			.mask = (PIPE_CONTROL_MMIO_WRITE | PIPE_CONTROL_NOTIFY),
+			.expected = 0,
+	      },
+	      {
+			.offset = 1,
+		        .mask = (PIPE_CONTROL_GLOBAL_GTT_IVB |
+				 PIPE_CONTROL_STORE_DATA_INDEX),
+			.expected = 0,
+			.condition_offset = 1,
+			.condition_mask = PIPE_CONTROL_POST_SYNC_OP_MASK,
+	      }},						       ),
+};
+
+static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
+	CMD(  MI_SET_PREDICATE,                 SMI,    F,  1,      S  ),
+	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
+	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
+	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
+	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   M  ),
+	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_URB_MEM,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_URB_MEM,                 SMI,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_VS,  S3D,   !F,  0x7FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_PS,  S3D,   !F,  0x7FF,  S  ),
+
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS,  S3D,   !F,  0x1FF,  S  ),
+};
+
+static const struct drm_i915_cmd_descriptor video_cmds[] = {
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_FLUSH_DW_NOTIFY,
+			.expected = 0,
+	      },
+	      {
+			.offset = 1,
+			.mask = MI_FLUSH_DW_USE_GTT,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      },
+	      {
+			.offset = 0,
+			.mask = MI_FLUSH_DW_STORE_INDEX,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      }},						       ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	/*
+	 * MFX_WAIT doesn't fit the way we handle length for most commands.
+	 * It has a length field but it uses a non-standard length bias.
+	 * It is always 1 dword though, so just treat it as fixed length.
+	 */
+	CMD(  MFX_WAIT,                         SMFX,   F,  1,      S  ),
+};
+
+static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_FLUSH_DW_NOTIFY,
+			.expected = 0,
+	      },
+	      {
+			.offset = 1,
+			.mask = MI_FLUSH_DW_USE_GTT,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      },
+	      {
+			.offset = 0,
+			.mask = MI_FLUSH_DW_STORE_INDEX,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      }},						       ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+};
+
+static const struct drm_i915_cmd_descriptor blt_cmds[] = {
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_FLUSH_DW_NOTIFY,
+			.expected = 0,
+	      },
+	      {
+			.offset = 1,
+			.mask = MI_FLUSH_DW_USE_GTT,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      },
+	      {
+			.offset = 0,
+			.mask = MI_FLUSH_DW_STORE_INDEX,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      }},						       ),
+	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
+	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
+};
+
+static const struct drm_i915_cmd_descriptor hsw_blt_cmds[] = {
+	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   M  ),
+	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
+};
+
+#undef CMD
+#undef SMI
+#undef S3D
+#undef S2D
+#undef SMFX
+#undef F
+#undef S
+#undef R
+#undef W
+#undef B
+#undef M
+
+static const struct drm_i915_cmd_table gen7_render_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ render_cmds, ARRAY_SIZE(render_cmds) },
+};
+
+static const struct drm_i915_cmd_table hsw_render_ring_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ render_cmds, ARRAY_SIZE(render_cmds) },
+	{ hsw_render_cmds, ARRAY_SIZE(hsw_render_cmds) },
+};
+
+static const struct drm_i915_cmd_table gen7_video_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ video_cmds, ARRAY_SIZE(video_cmds) },
+};
+
+static const struct drm_i915_cmd_table hsw_vebox_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ vecs_cmds, ARRAY_SIZE(vecs_cmds) },
+};
+
+static const struct drm_i915_cmd_table gen7_blt_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
+};
+
+static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
+	{ hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) },
+};
+
+/*
+ * Register whitelists, sorted by increasing register offset.
+ *
+ * Some registers that userspace accesses are 64 bits. The register
+ * access commands only allow 32-bit accesses. Hence, we have to include
+ * entries for both halves of the 64-bit registers.
+ */
+
+/* Convenience macro for adding 64-bit registers */
+#define REG64(addr) (addr), (addr + sizeof(u32))
+
+static const u32 gen7_render_regs[] = {
+	REG64(HS_INVOCATION_COUNT),
+	REG64(DS_INVOCATION_COUNT),
+	REG64(IA_VERTICES_COUNT),
+	REG64(IA_PRIMITIVES_COUNT),
+	REG64(VS_INVOCATION_COUNT),
+	REG64(GS_INVOCATION_COUNT),
+	REG64(GS_PRIMITIVES_COUNT),
+	REG64(CL_INVOCATION_COUNT),
+	REG64(CL_PRIMITIVES_COUNT),
+	REG64(PS_INVOCATION_COUNT),
+	REG64(PS_DEPTH_COUNT),
+	OACONTROL, /* Only allowed for LRI and SRM. See below. */
+	GEN7_3DPRIM_END_OFFSET,
+	GEN7_3DPRIM_START_VERTEX,
+	GEN7_3DPRIM_VERTEX_COUNT,
+	GEN7_3DPRIM_INSTANCE_COUNT,
+	GEN7_3DPRIM_START_INSTANCE,
+	GEN7_3DPRIM_BASE_VERTEX,
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)),
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)),
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)),
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(3)),
+	REG64(GEN7_SO_PRIM_STORAGE_NEEDED(0)),
+	REG64(GEN7_SO_PRIM_STORAGE_NEEDED(1)),
+	REG64(GEN7_SO_PRIM_STORAGE_NEEDED(2)),
+	REG64(GEN7_SO_PRIM_STORAGE_NEEDED(3)),
+	GEN7_SO_WRITE_OFFSET(0),
+	GEN7_SO_WRITE_OFFSET(1),
+	GEN7_SO_WRITE_OFFSET(2),
+	GEN7_SO_WRITE_OFFSET(3),
+};
+
+static const u32 gen7_blt_regs[] = {
+	BCS_SWCTRL,
+};
+
+static const u32 ivb_master_regs[] = {
+	FORCEWAKE_MT,
+	DERRMR,
+	GEN7_PIPE_DE_LOAD_SL(PIPE_A),
+	GEN7_PIPE_DE_LOAD_SL(PIPE_B),
+	GEN7_PIPE_DE_LOAD_SL(PIPE_C),
+};
+
+static const u32 hsw_master_regs[] = {
+	FORCEWAKE_MT,
+	DERRMR,
+};
+
+#undef REG64
+
 static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
 {
 	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
@@ -137,12 +498,13 @@ static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header)
 	return 0;
 }
 
-static void validate_cmds_sorted(struct intel_ring_buffer *ring)
+static bool validate_cmds_sorted(struct intel_ring_buffer *ring)
 {
 	int i;
+	bool ret = true;
 
 	if (!ring->cmd_tables || ring->cmd_table_count == 0)
-		return;
+		return true;
 
 	for (i = 0; i < ring->cmd_table_count; i++) {
 		const struct drm_i915_cmd_table *table = &ring->cmd_tables[i];
@@ -154,35 +516,45 @@ static void validate_cmds_sorted(struct intel_ring_buffer *ring)
 				&table->table[i];
 			u32 curr = desc->cmd.value & desc->cmd.mask;
 
-			if (curr < previous)
+			if (curr < previous) {
 				DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
 					  ring->id, i, j, curr, previous);
+				ret = false;
+			}
 
 			previous = curr;
 		}
 	}
+
+	return ret;
 }
 
-static void check_sorted(int ring_id, const u32 *reg_table, int reg_count)
+static bool check_sorted(int ring_id, const u32 *reg_table, int reg_count)
 {
 	int i;
 	u32 previous = 0;
+	bool ret = true;
 
 	for (i = 0; i < reg_count; i++) {
 		u32 curr = reg_table[i];
 
-		if (curr < previous)
+		if (curr < previous) {
 			DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
 				  ring_id, i, curr, previous);
+			ret = false;
+		}
 
 		previous = curr;
 	}
+
+	return ret;
 }
 
-static void validate_regs_sorted(struct intel_ring_buffer *ring)
+static bool validate_regs_sorted(struct intel_ring_buffer *ring)
 {
-	check_sorted(ring->id, ring->reg_table, ring->reg_count);
-	check_sorted(ring->id, ring->master_reg_table, ring->master_reg_count);
+	return check_sorted(ring->id, ring->reg_table, ring->reg_count) &&
+		check_sorted(ring->id, ring->master_reg_table,
+			     ring->master_reg_count);
 }
 
 /**
@@ -200,15 +572,58 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 
 	switch (ring->id) {
 	case RCS:
+		if (IS_HASWELL(ring->dev)) {
+			ring->cmd_tables = hsw_render_ring_cmds;
+			ring->cmd_table_count =
+				ARRAY_SIZE(hsw_render_ring_cmds);
+		} else {
+			ring->cmd_tables = gen7_render_cmds;
+			ring->cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
+		}
+
+		ring->reg_table = gen7_render_regs;
+		ring->reg_count = ARRAY_SIZE(gen7_render_regs);
+
+		if (IS_HASWELL(ring->dev)) {
+			ring->master_reg_table = hsw_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+		} else {
+			ring->master_reg_table = ivb_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+		}
+
 		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
 		break;
 	case VCS:
+		ring->cmd_tables = gen7_video_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
 		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
 	case BCS:
+		if (IS_HASWELL(ring->dev)) {
+			ring->cmd_tables = hsw_blt_ring_cmds;
+			ring->cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmds);
+		} else {
+			ring->cmd_tables = gen7_blt_cmds;
+			ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
+		}
+
+		ring->reg_table = gen7_blt_regs;
+		ring->reg_count = ARRAY_SIZE(gen7_blt_regs);
+
+		if (IS_HASWELL(ring->dev)) {
+			ring->master_reg_table = hsw_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+		} else {
+			ring->master_reg_table = ivb_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+		}
+
 		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 		break;
 	case VECS:
+		ring->cmd_tables = hsw_vebox_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
 		/* VECS can use the same length_mask function as VCS */
 		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
@@ -218,8 +633,8 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 		BUG();
 	}
 
-	validate_cmds_sorted(ring);
-	validate_regs_sorted(ring);
+	BUG_ON(!validate_cmds_sorted(ring));
+	BUG_ON(!validate_regs_sorted(ring));
 }
 
 static const struct drm_i915_cmd_descriptor*
@@ -331,13 +746,111 @@ finish:
  */
 bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
 {
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+
 	/* No command tables indicates a platform without parsing */
 	if (!ring->cmd_tables)
 		return false;
 
+	/*
+	 * XXX: VLV is Gen7 and therefore has cmd_tables, but has PPGTT
+	 * disabled. That will cause all of the parser's PPGTT checks to
+	 * fail. For now, disable parsing when PPGTT is off.
+	 */
+	if (!dev_priv->mm.aliasing_ppgtt)
+		return false;
+
 	return (i915.enable_cmd_parser == 1);
 }
 
+static bool check_cmd(const struct intel_ring_buffer *ring,
+		      const struct drm_i915_cmd_descriptor *desc,
+		      const u32 *cmd,
+		      const bool is_master,
+		      bool *oacontrol_set)
+{
+	if (desc->flags & CMD_DESC_REJECT) {
+		DRM_DEBUG_DRIVER("CMD: Rejected command: 0x%08X\n", *cmd);
+		return false;
+	}
+
+	if ((desc->flags & CMD_DESC_MASTER) && !is_master) {
+		DRM_DEBUG_DRIVER("CMD: Rejected master-only command: 0x%08X\n",
+				 *cmd);
+		return false;
+	}
+
+	if (desc->flags & CMD_DESC_REGISTER) {
+		u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
+
+		/*
+		 * OACONTROL requires some special handling for writes. We
+		 * want to make sure that any batch which enables OA also
+		 * disables it before the end of the batch. The goal is to
+		 * prevent one process from snooping on the perf data from
+		 * another process. To do that, we need to check the value
+		 * that will be written to the register. Hence, limit
+		 * OACONTROL writes to only MI_LOAD_REGISTER_IMM commands.
+		 */
+		if (reg_addr == OACONTROL) {
+			if (desc->cmd.value == MI_LOAD_REGISTER_MEM)
+				return false;
+
+			if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1))
+				*oacontrol_set = (cmd[2] != 0);
+		}
+
+		if (!valid_reg(ring->reg_table,
+			       ring->reg_count, reg_addr)) {
+			if (!is_master ||
+			    !valid_reg(ring->master_reg_table,
+				       ring->master_reg_count,
+				       reg_addr)) {
+				DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
+						 reg_addr,
+						 *cmd,
+						 ring->id);
+				return false;
+			}
+		}
+	}
+
+	if (desc->flags & CMD_DESC_BITMASK) {
+		int i;
+
+		for (i = 0; i < MAX_CMD_DESC_BITMASKS; i++) {
+			u32 dword;
+
+			if (desc->bits[i].mask == 0)
+				break;
+
+			if (desc->bits[i].condition_mask != 0) {
+				u32 offset =
+					desc->bits[i].condition_offset;
+				u32 condition = cmd[offset] &
+					desc->bits[i].condition_mask;
+
+				if (condition == 0)
+					continue;
+			}
+
+			dword = cmd[desc->bits[i].offset] &
+				desc->bits[i].mask;
+
+			if (dword != desc->bits[i].expected) {
+				DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X for bitmask 0x%08X (exp=0x%08X act=0x%08X) (ring=%d)\n",
+						 *cmd,
+						 desc->bits[i].mask,
+						 desc->bits[i].expected,
+						 dword, ring->id);
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
 #define LENGTH_BIAS 2
 
 /**
@@ -361,6 +874,7 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
 	u32 *cmd, *batch_base, *batch_end;
 	struct drm_i915_cmd_descriptor default_desc = { 0 };
 	int needs_clflush = 0;
+	bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */
 
 	ret = i915_gem_obj_prepare_shmem_read(batch_obj, &needs_clflush);
 	if (ret) {
@@ -402,7 +916,7 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
 			length = ((*cmd & desc->length.mask) + LENGTH_BIAS);
 
 		if ((batch_end - cmd) < length) {
-			DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%td\n",
+			DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%u batchlen=%td\n",
 					 *cmd,
 					 length,
 					 (unsigned long)(batch_end - cmd));
@@ -410,68 +924,19 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
 			break;
 		}
 
-		if (desc->flags & CMD_DESC_REJECT) {
-			DRM_DEBUG_DRIVER("CMD: Rejected command: 0x%08X\n", *cmd);
-			ret = -EINVAL;
-			break;
-		}
-
-		if ((desc->flags & CMD_DESC_MASTER) && !is_master) {
-			DRM_DEBUG_DRIVER("CMD: Rejected master-only command: 0x%08X\n",
-					 *cmd);
+		if (!check_cmd(ring, desc, cmd, is_master, &oacontrol_set)) {
 			ret = -EINVAL;
 			break;
 		}
 
-		if (desc->flags & CMD_DESC_REGISTER) {
-			u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
-
-			if (!valid_reg(ring->reg_table,
-				       ring->reg_count, reg_addr)) {
-				if (!is_master ||
-				    !valid_reg(ring->master_reg_table,
-					       ring->master_reg_count,
-					       reg_addr)) {
-					DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
-							 reg_addr,
-							 *cmd,
-							 ring->id);
-					ret = -EINVAL;
-					break;
-				}
-			}
-		}
-
-		if (desc->flags & CMD_DESC_BITMASK) {
-			int i;
-
-			for (i = 0; i < MAX_CMD_DESC_BITMASKS; i++) {
-				u32 dword;
-
-				if (desc->bits[i].mask == 0)
-					break;
-
-				dword = cmd[desc->bits[i].offset] &
-					desc->bits[i].mask;
-
-				if (dword != desc->bits[i].expected) {
-					DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X for bitmask 0x%08X (exp=0x%08X act=0x%08X) (ring=%d)\n",
-							 *cmd,
-							 desc->bits[i].mask,
-							 desc->bits[i].expected,
-							 dword, ring->id);
-					ret = -EINVAL;
-					break;
-				}
-			}
-
-			if (ret)
-				break;
-		}
-
 		cmd += length;
 	}
 
+	if (oacontrol_set) {
+		DRM_DEBUG_DRIVER("CMD: batch set OACONTROL but did not clear it\n");
+		ret = -EINVAL;
+	}
+
 	if (cmd >= batch_end) {
 		DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n");
 		ret = -EINVAL;
@@ -483,3 +948,22 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
 
 	return ret;
 }
+
+/**
+ * i915_cmd_parser_get_version() - get the cmd parser version number
+ *
+ * The cmd parser maintains a simple increasing integer version number suitable
+ * for passing to userspace clients to determine what operations are permitted.
+ *
+ * Return: the current version number of the cmd parser
+ */
+int i915_cmd_parser_get_version(void)
+{
+	/*
+	 * Command parser version history
+	 *
+	 * 1. Initial version. Checks batches and reports violations, but leaves
+	 *    hardware parsing enabled (so does not allow new use cases).
+	 */
+	return 1;
+}
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 195fe5bc0aac..1e83ae45041c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -966,7 +966,7 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
 	return 0;
 }
 
-static int i915_cur_delayinfo(struct seq_file *m, void *unused)
+static int i915_frequency_info(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
@@ -991,6 +991,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
 		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		u32 rpmodectl, rpinclimit, rpdeclimit;
 		u32 rpstat, cagf, reqf;
 		u32 rpupei, rpcurup, rpprevup;
 		u32 rpdownei, rpcurdown, rpprevdown;
@@ -1011,6 +1012,10 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 			reqf >>= 25;
 		reqf *= GT_FREQUENCY_MULTIPLIER;
 
+		rpmodectl = I915_READ(GEN6_RP_CONTROL);
+		rpinclimit = I915_READ(GEN6_RP_UP_THRESHOLD);
+		rpdeclimit = I915_READ(GEN6_RP_DOWN_THRESHOLD);
+
 		rpstat = I915_READ(GEN6_RPSTAT1);
 		rpupei = I915_READ(GEN6_RP_CUR_UP_EI);
 		rpcurup = I915_READ(GEN6_RP_CUR_UP);
@@ -1027,14 +1032,23 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 		gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 		mutex_unlock(&dev->struct_mutex);
 
+		seq_printf(m, "PM IER=0x%08x IMR=0x%08x ISR=0x%08x IIR=0x%08x, MASK=0x%08x\n",
+			   I915_READ(GEN6_PMIER),
+			   I915_READ(GEN6_PMIMR),
+			   I915_READ(GEN6_PMISR),
+			   I915_READ(GEN6_PMIIR),
+			   I915_READ(GEN6_PMINTRMSK));
 		seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
-		seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat);
 		seq_printf(m, "Render p-state ratio: %d\n",
 			   (gt_perf_status & 0xff00) >> 8);
 		seq_printf(m, "Render p-state VID: %d\n",
 			   gt_perf_status & 0xff);
 		seq_printf(m, "Render p-state limit: %d\n",
 			   rp_state_limits & 0xff);
+		seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat);
+		seq_printf(m, "RPMODECTL: 0x%08x\n", rpmodectl);
+		seq_printf(m, "RPINCLIMIT: 0x%08x\n", rpinclimit);
+		seq_printf(m, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
 		seq_printf(m, "RPNSWREQ: %dMHz\n", reqf);
 		seq_printf(m, "CAGF: %dMHz\n", cagf);
 		seq_printf(m, "RP CUR UP EI: %dus\n", rpupei &
@@ -1816,8 +1830,7 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 			u64 pdp = I915_READ(ring->mmio_base + offset + 4);
 			pdp <<= 32;
 			pdp |= I915_READ(ring->mmio_base + offset);
-			for (i = 0; i < 4; i++)
-				seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp);
+			seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp);
 		}
 	}
 }
@@ -2044,7 +2057,7 @@ static int i915_pc8_status(struct seq_file *m, void *unused)
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!IS_HASWELL(dev)) {
+	if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
 		seq_puts(m, "not supported\n");
 		return 0;
 	}
@@ -3774,7 +3787,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
 	{"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS},
 	{"i915_rstdby_delays", i915_rstdby_delays, 0},
-	{"i915_cur_delayinfo", i915_cur_delayinfo, 0},
+	{"i915_frequency_info", i915_frequency_info, 0},
 	{"i915_delayfreq_table", i915_delayfreq_table, 0},
 	{"i915_inttoext_table", i915_inttoext_table, 0},
 	{"i915_drpc_info", i915_drpc_info, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 96177eec0a0e..0b38f88c35f0 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1017,6 +1017,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_EXEC_HANDLE_LUT:
 		value = 1;
 		break;
+	case I915_PARAM_CMD_PARSER_VERSION:
+		value = i915_cmd_parser_get_version();
+		break;
 	default:
 		DRM_DEBUG("Unknown parameter %d\n", param->param);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 82f4d1f47d3b..5d8250f7145d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -891,7 +891,36 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 }
 
-static int i915_runtime_suspend(struct device *device)
+static void snb_runtime_suspend(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	intel_runtime_pm_disable_interrupts(dev);
+}
+
+static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
+{
+	hsw_enable_pc8(dev_priv);
+}
+
+static void snb_runtime_resume(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	intel_runtime_pm_restore_interrupts(dev);
+	intel_init_pch_refclk(dev);
+	i915_gem_init_swizzling(dev);
+	mutex_lock(&dev_priv->rps.hw_lock);
+	gen6_update_ring_freq(dev);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
+static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
+{
+	hsw_disable_pc8(dev_priv);
+}
+
+static int intel_runtime_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct drm_device *dev = pci_get_drvdata(pdev);
@@ -902,8 +931,12 @@ static int i915_runtime_suspend(struct device *device)
 
 	DRM_DEBUG_KMS("Suspending device\n");
 
-	if (HAS_PC8(dev))
-		hsw_enable_pc8(dev_priv);
+	if (IS_GEN6(dev))
+		snb_runtime_suspend(dev_priv);
+	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+		hsw_runtime_suspend(dev_priv);
+	else
+		WARN_ON(1);
 
 	i915_gem_release_all_mmaps(dev_priv);
 
@@ -923,7 +956,7 @@ static int i915_runtime_suspend(struct device *device)
 	return 0;
 }
 
-static int i915_runtime_resume(struct device *device)
+static int intel_runtime_resume(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct drm_device *dev = pci_get_drvdata(pdev);
@@ -936,8 +969,12 @@ static int i915_runtime_resume(struct device *device)
 	intel_opregion_notify_adapter(dev, PCI_D0);
 	dev_priv->pm.suspended = false;
 
-	if (HAS_PC8(dev))
-		hsw_disable_pc8(dev_priv);
+	if (IS_GEN6(dev))
+		snb_runtime_resume(dev_priv);
+	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+		hsw_runtime_resume(dev_priv);
+	else
+		WARN_ON(1);
 
 	DRM_DEBUG_KMS("Device resumed\n");
 	return 0;
@@ -954,8 +991,8 @@ static const struct dev_pm_ops i915_pm_ops = {
 	.poweroff = i915_pm_poweroff,
 	.restore_early = i915_pm_resume_early,
 	.restore = i915_pm_resume,
-	.runtime_suspend = i915_runtime_suspend,
-	.runtime_resume = i915_runtime_resume,
+	.runtime_suspend = intel_runtime_suspend,
+	.runtime_resume = intel_runtime_resume,
 };
 
 static const struct vm_operations_struct i915_gem_vm_ops = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0905cd915589..7d6acb401fd9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -35,6 +35,7 @@
 #include "i915_reg.h"
 #include "intel_bios.h"
 #include "intel_ringbuffer.h"
+#include "i915_gem_gtt.h"
 #include <linux/io-mapping.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
@@ -358,7 +359,7 @@ struct drm_i915_error_state {
 		u64 bbaddr;
 		u64 acthd;
 		u32 fault_reg;
-		u32 faddr;
+		u64 faddr;
 		u32 rc_psmi; /* sleep state */
 		u32 semaphore_mboxes[I915_NUM_RINGS - 1];
 
@@ -572,168 +573,6 @@ enum i915_cache_level {
 	I915_CACHE_WT, /* hsw:gt3e WriteThrough for scanouts */
 };
 
-typedef uint32_t gen6_gtt_pte_t;
-
-/**
- * A VMA represents a GEM BO that is bound into an address space. Therefore, a
- * VMA's presence cannot be guaranteed before binding, or after unbinding the
- * object into/from the address space.
- *
- * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
- * will always be <= an objects lifetime. So object refcounting should cover us.
- */
-struct i915_vma {
-	struct drm_mm_node node;
-	struct drm_i915_gem_object *obj;
-	struct i915_address_space *vm;
-
-	/** This object's place on the active/inactive lists */
-	struct list_head mm_list;
-
-	struct list_head vma_link; /* Link in the object's VMA list */
-
-	/** This vma's place in the batchbuffer or on the eviction list */
-	struct list_head exec_list;
-
-	/**
-	 * Used for performing relocations during execbuffer insertion.
-	 */
-	struct hlist_node exec_node;
-	unsigned long exec_handle;
-	struct drm_i915_gem_exec_object2 *exec_entry;
-
-	/**
-	 * How many users have pinned this object in GTT space. The following
-	 * users can each hold at most one reference: pwrite/pread, pin_ioctl
-	 * (via user_pin_count), execbuffer (objects are not allowed multiple
-	 * times for the same batchbuffer), and the framebuffer code. When
-	 * switching/pageflipping, the framebuffer code has at most two buffers
-	 * pinned per crtc.
-	 *
-	 * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
-	 * bits with absolutely no headroom. So use 4 bits. */
-	unsigned int pin_count:4;
-#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
-
-	/** Unmap an object from an address space. This usually consists of
-	 * setting the valid PTE entries to a reserved scratch page. */
-	void (*unbind_vma)(struct i915_vma *vma);
-	/* Map an object into an address space with the given cache flags. */
-#define GLOBAL_BIND (1<<0)
-	void (*bind_vma)(struct i915_vma *vma,
-			 enum i915_cache_level cache_level,
-			 u32 flags);
-};
-
-struct i915_address_space {
-	struct drm_mm mm;
-	struct drm_device *dev;
-	struct list_head global_link;
-	unsigned long start;		/* Start offset always 0 for dri2 */
-	size_t total;		/* size addr space maps (ex. 2GB for ggtt) */
-
-	struct {
-		dma_addr_t addr;
-		struct page *page;
-	} scratch;
-
-	/**
-	 * List of objects currently involved in rendering.
-	 *
-	 * Includes buffers having the contents of their GPU caches
-	 * flushed, not necessarily primitives.  last_rendering_seqno
-	 * represents when the rendering involved will be completed.
-	 *
-	 * A reference is held on the buffer while on this list.
-	 */
-	struct list_head active_list;
-
-	/**
-	 * LRU list of objects which are not in the ringbuffer and
-	 * are ready to unbind, but are still in the GTT.
-	 *
-	 * last_rendering_seqno is 0 while an object is in this list.
-	 *
-	 * A reference is not held on the buffer while on this list,
-	 * as merely being GTT-bound shouldn't prevent its being
-	 * freed, and we'll pull it off the list in the free path.
-	 */
-	struct list_head inactive_list;
-
-	/* FIXME: Need a more generic return type */
-	gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
-				     enum i915_cache_level level,
-				     bool valid); /* Create a valid PTE */
-	void (*clear_range)(struct i915_address_space *vm,
-			    uint64_t start,
-			    uint64_t length,
-			    bool use_scratch);
-	void (*insert_entries)(struct i915_address_space *vm,
-			       struct sg_table *st,
-			       uint64_t start,
-			       enum i915_cache_level cache_level);
-	void (*cleanup)(struct i915_address_space *vm);
-};
-
-/* The Graphics Translation Table is the way in which GEN hardware translates a
- * Graphics Virtual Address into a Physical Address. In addition to the normal
- * collateral associated with any va->pa translations GEN hardware also has a
- * portion of the GTT which can be mapped by the CPU and remain both coherent
- * and correct (in cases like swizzling). That region is referred to as GMADR in
- * the spec.
- */
-struct i915_gtt {
-	struct i915_address_space base;
-	size_t stolen_size;		/* Total size of stolen memory */
-
-	unsigned long mappable_end;	/* End offset that we can CPU map */
-	struct io_mapping *mappable;	/* Mapping to our CPU mappable region */
-	phys_addr_t mappable_base;	/* PA of our GMADR */
-
-	/** "Graphics Stolen Memory" holds the global PTEs */
-	void __iomem *gsm;
-
-	bool do_idle_maps;
-
-	int mtrr;
-
-	/* global gtt ops */
-	int (*gtt_probe)(struct drm_device *dev, size_t *gtt_total,
-			  size_t *stolen, phys_addr_t *mappable_base,
-			  unsigned long *mappable_end);
-};
-#define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
-
-#define GEN8_LEGACY_PDPS 4
-struct i915_hw_ppgtt {
-	struct i915_address_space base;
-	struct kref ref;
-	struct drm_mm_node node;
-	unsigned num_pd_entries;
-	unsigned num_pd_pages; /* gen8+ */
-	union {
-		struct page **pt_pages;
-		struct page **gen8_pt_pages[GEN8_LEGACY_PDPS];
-	};
-	struct page *pd_pages;
-	union {
-		uint32_t pd_offset;
-		dma_addr_t pd_dma_addr[GEN8_LEGACY_PDPS];
-	};
-	union {
-		dma_addr_t *pt_dma_addr;
-		dma_addr_t *gen8_pt_dma_addr[4];
-	};
-
-	struct i915_hw_context *ctx;
-
-	int (*enable)(struct i915_hw_ppgtt *ppgtt);
-	int (*switch_mm)(struct i915_hw_ppgtt *ppgtt,
-			 struct intel_ring_buffer *ring,
-			 bool synchronous);
-	void (*debug_dump)(struct i915_hw_ppgtt *ppgtt, struct seq_file *m);
-};
-
 struct i915_ctx_hang_stats {
 	/* This context had batch pending when hang was declared */
 	unsigned batch_pending;
@@ -794,6 +633,10 @@ struct i915_fbc {
 	} no_fbc_reason;
 };
 
+struct i915_drrs {
+	struct intel_connector *connector;
+};
+
 struct i915_psr {
 	bool sink_support;
 	bool source_ok;
@@ -1260,8 +1103,12 @@ struct i915_gpu_error {
 	 */
 	wait_queue_head_t reset_queue;
 
-	/* For gpu hang simulation. */
-	unsigned int stop_rings;
+	/* Userspace knobs for gpu hang simulation;
+	 * combines both a ring mask, and extra flags
+	 */
+	u32 stop_rings;
+#define I915_STOP_RING_ALLOW_BAN       (1 << 31)
+#define I915_STOP_RING_ALLOW_WARN      (1 << 30)
 
 	/* For missed irq/seqno simulation. */
 	unsigned int test_irq_rings;
@@ -1281,6 +1128,12 @@ struct ddi_vbt_port_info {
 	uint8_t supports_dp:1;
 };
 
+enum drrs_support_type {
+	DRRS_NOT_SUPPORTED = 0,
+	STATIC_DRRS_SUPPORT = 1,
+	SEAMLESS_DRRS_SUPPORT = 2
+};
+
 struct intel_vbt_data {
 	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
 	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
@@ -1296,6 +1149,8 @@ struct intel_vbt_data {
 	int lvds_ssc_freq;
 	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
 
+	enum drrs_support_type drrs_type;
+
 	/* eDP */
 	int edp_rate;
 	int edp_lanes;
@@ -1308,12 +1163,19 @@ struct intel_vbt_data {
 
 	struct {
 		u16 pwm_freq_hz;
+		bool present;
 		bool active_low_pwm;
 	} backlight;
 
 	/* MIPI DSI */
 	struct {
 		u16 panel_id;
+		struct mipi_config *config;
+		struct mipi_pps_data *pps;
+		u8 seq_version;
+		u32 size;
+		u8 *data;
+		u8 *sequence[MIPI_SEQ_MAX];
 	} dsi;
 
 	int crt_ddc_pin;
@@ -1365,23 +1227,13 @@ struct ilk_wm_values {
  * goes back to false exactly before we reenable the IRQs. We use this variable
  * to check if someone is trying to enable/disable IRQs while they're supposed
  * to be disabled. This shouldn't happen and we'll print some error messages in
- * case it happens, but if it actually happens we'll also update the variables
- * inside struct regsave so when we restore the IRQs they will contain the
- * latest expected values.
+ * case it happens.
  *
  * For more, read the Documentation/power/runtime_pm.txt.
  */
 struct i915_runtime_pm {
 	bool suspended;
 	bool irqs_disabled;
-
-	struct {
-		uint32_t deimr;
-		uint32_t sdeimr;
-		uint32_t gtimr;
-		uint32_t gtier;
-		uint32_t gen6_pmimr;
-	} regsave;
 };
 
 enum intel_pipe_crc_source {
@@ -1414,7 +1266,7 @@ struct intel_pipe_crc {
 	wait_queue_head_t wq;
 };
 
-typedef struct drm_i915_private {
+struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
 
@@ -1483,6 +1335,7 @@ typedef struct drm_i915_private {
 	struct timer_list hotplug_reenable_timer;
 
 	struct i915_fbc fbc;
+	struct i915_drrs drrs;
 	struct intel_opregion opregion;
 	struct intel_vbt_data vbt;
 
@@ -1500,6 +1353,7 @@ typedef struct drm_i915_private {
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
 	unsigned int fsb_freq, mem_freq, is_ddr3;
+	unsigned int vlv_cdclk_freq;
 
 	/**
 	 * wq - Driver workqueue for GEM.
@@ -1523,7 +1377,7 @@ typedef struct drm_i915_private {
 	struct mutex modeset_restore_lock;
 
 	struct list_head vm_list; /* Global list of all address spaces */
-	struct i915_gtt gtt; /* VMA representing the global address space */
+	struct i915_gtt gtt; /* VM representing the global address space */
 
 	struct i915_gem_mm mm;
 
@@ -1619,7 +1473,7 @@ typedef struct drm_i915_private {
 	struct i915_dri1_state dri1;
 	/* Old ums support infrastructure, same warning applies. */
 	struct i915_ums_state ums;
-} drm_i915_private_t;
+};
 
 static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
 {
@@ -1893,11 +1747,17 @@ struct drm_i915_cmd_descriptor {
 	 * the expected value, the parser rejects it. Only valid if flags has
 	 * the CMD_DESC_BITMASK bit set. Only entries where mask is non-zero
 	 * are valid.
+	 *
+	 * If the check specifies a non-zero condition_mask then the parser
+	 * only performs the check when the bits specified by condition_mask
+	 * are non-zero.
 	 */
 	struct {
 		u32 offset;
 		u32 mask;
 		u32 expected;
+		u32 condition_offset;
+		u32 condition_mask;
 	} bits[MAX_CMD_DESC_BITMASKS];
 };
 
@@ -1939,8 +1799,9 @@ struct drm_i915_cmd_table {
 				 (dev)->pdev->device == 0x0106 || \
 				 (dev)->pdev->device == 0x010A)
 #define IS_VALLEYVIEW(dev)	(INTEL_INFO(dev)->is_valleyview)
+#define IS_CHERRYVIEW(dev)	(INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
 #define IS_HASWELL(dev)	(INTEL_INFO(dev)->is_haswell)
-#define IS_BROADWELL(dev)	(INTEL_INFO(dev)->gen == 8)
+#define IS_BROADWELL(dev)	(!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
 #define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)
 #define IS_HSW_EARLY_SDV(dev)	(IS_HASWELL(dev) && \
 				 ((dev)->pdev->device & 0xFF00) == 0x0C00)
@@ -2021,8 +1882,8 @@ struct drm_i915_cmd_table {
 #define HAS_DDI(dev)		(INTEL_INFO(dev)->has_ddi)
 #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
-#define HAS_PC8(dev)		(IS_HASWELL(dev)) /* XXX HSW:ULX */
-#define HAS_RUNTIME_PM(dev)	(IS_HASWELL(dev))
+#define HAS_RUNTIME_PM(dev)	(IS_GEN6(dev) || IS_HASWELL(dev) || \
+				 IS_BROADWELL(dev))
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
@@ -2079,6 +1940,7 @@ struct i915_params {
 	bool prefault_disable;
 	bool reset;
 	bool disable_display;
+	bool disable_vtd_wa;
 };
 extern struct i915_params i915 __read_mostly;
 
@@ -2301,6 +2163,18 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
 	return ((atomic_read(&error->reset_counter) & ~I915_WEDGED) + 1) / 2;
 }
 
+static inline bool i915_stop_ring_allow_ban(struct drm_i915_private *dev_priv)
+{
+	return dev_priv->gpu_error.stop_rings == 0 ||
+		dev_priv->gpu_error.stop_rings & I915_STOP_RING_ALLOW_BAN;
+}
+
+static inline bool i915_stop_ring_allow_warn(struct drm_i915_private *dev_priv)
+{
+	return dev_priv->gpu_error.stop_rings == 0 ||
+		dev_priv->gpu_error.stop_rings & I915_STOP_RING_ALLOW_WARN;
+}
+
 void i915_gem_reset(struct drm_device *dev);
 bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
 int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
@@ -2431,20 +2305,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
 int i915_gem_context_enable(struct drm_i915_private *dev_priv);
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 int i915_switch_context(struct intel_ring_buffer *ring,
-			struct drm_file *file, struct i915_hw_context *to);
+			struct i915_hw_context *to);
 struct i915_hw_context *
 i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
 void i915_gem_context_free(struct kref *ctx_ref);
 static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
 {
-	if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
-		kref_get(&ctx->ref);
+	kref_get(&ctx->ref);
 }
 
 static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
 {
-	if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
-		kref_put(&ctx->ref, i915_gem_context_free);
+	kref_put(&ctx->ref, i915_gem_context_free);
 }
 
 static inline bool i915_gem_context_is_default(const struct i915_hw_context *c)
@@ -2467,23 +2339,12 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
 int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
 int i915_gem_evict_everything(struct drm_device *dev);
 
-/* i915_gem_gtt.c */
-void i915_check_and_clear_faults(struct drm_device *dev);
-void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
-void i915_gem_restore_gtt_mappings(struct drm_device *dev);
-int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
-void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
-void i915_gem_init_global_gtt(struct drm_device *dev);
-void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start,
-			       unsigned long mappable_end, unsigned long end);
-int i915_gem_gtt_init(struct drm_device *dev);
+/* belongs in i915_gem_gtt.h */
 static inline void i915_gem_chipset_flush(struct drm_device *dev)
 {
 	if (INTEL_INFO(dev)->gen < 6)
 		intel_gtt_chipset_flush();
 }
-int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
-bool intel_enable_ppgtt(struct drm_device *dev, bool full);
 
 /* i915_gem_stolen.c */
 int i915_gem_init_stolen(struct drm_device *dev);
@@ -2551,6 +2412,7 @@ void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone);
 const char *i915_cache_level_str(int type);
 
 /* i915_cmd_parser.c */
+int i915_cmd_parser_get_version(void);
 void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring);
 bool i915_needs_cmd_parser(struct intel_ring_buffer *ring);
 int i915_parse_cmds(struct intel_ring_buffer *ring,
@@ -2702,20 +2564,6 @@ void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val);
 int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
 
-void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
-void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
-
-#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
-	(((reg) >= 0x2000 && (reg) < 0x4000) ||\
-	((reg) >= 0x5000 && (reg) < 0x8000) ||\
-	((reg) >= 0xB000 && (reg) < 0x12000) ||\
-	((reg) >= 0x2E000 && (reg) < 0x30000))
-
-#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
-	(((reg) >= 0x12000 && (reg) < 0x14000) ||\
-	((reg) >= 0x22000 && (reg) < 0x24000) ||\
-	((reg) >= 0x30000 && (reg) < 0x40000))
-
 #define FORCEWAKE_RENDER	(1 << 0)
 #define FORCEWAKE_MEDIA		(1 << 1)
 #define FORCEWAKE_ALL		(FORCEWAKE_RENDER | FORCEWAKE_MEDIA)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6370a761d137..8f5ffab15894 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2277,8 +2277,9 @@ static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
 		if (!i915_gem_context_is_default(ctx)) {
 			DRM_DEBUG("context hanging too fast, banning!\n");
 			return true;
-		} else if (dev_priv->gpu_error.stop_rings == 0) {
-			DRM_ERROR("gpu hanging too fast, banning!\n");
+		} else if (i915_stop_ring_allow_ban(dev_priv)) {
+			if (i915_stop_ring_allow_warn(dev_priv))
+				DRM_ERROR("gpu hanging too fast, banning!\n");
 			return true;
 		}
 	}
@@ -2790,7 +2791,7 @@ int i915_gpu_idle(struct drm_device *dev)
 
 	/* Flush everything onto the inactive list. */
 	for_each_ring(ring, dev_priv, i) {
-		ret = i915_switch_context(ring, NULL, ring->default_context);
+		ret = i915_switch_context(ring, ring->default_context);
 		if (ret)
 			return ret;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 6043062ffce7..f77b4c126465 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -96,9 +96,6 @@
 #define GEN6_CONTEXT_ALIGN (64<<10)
 #define GEN7_CONTEXT_ALIGN 4096
 
-static int do_switch(struct intel_ring_buffer *ring,
-		     struct i915_hw_context *to);
-
 static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
 {
 	struct drm_device *dev = ppgtt->base.dev;
@@ -185,13 +182,15 @@ void i915_gem_context_free(struct kref *ctx_ref)
 						   typeof(*ctx), ref);
 	struct i915_hw_ppgtt *ppgtt = NULL;
 
-	/* We refcount even the aliasing PPGTT to keep the code symmetric */
-	if (USES_PPGTT(ctx->obj->base.dev))
-		ppgtt = ctx_to_ppgtt(ctx);
+	if (ctx->obj) {
+		/* We refcount even the aliasing PPGTT to keep the code symmetric */
+		if (USES_PPGTT(ctx->obj->base.dev))
+			ppgtt = ctx_to_ppgtt(ctx);
 
-	/* XXX: Free up the object before tearing down the address space, in
-	 * case we're bound in the PPGTT */
-	drm_gem_object_unreference(&ctx->obj->base);
+		/* XXX: Free up the object before tearing down the address space, in
+		 * case we're bound in the PPGTT */
+		drm_gem_object_unreference(&ctx->obj->base);
+	}
 
 	if (ppgtt)
 		kref_put(&ppgtt->ref, ppgtt_release);
@@ -232,32 +231,40 @@ __create_hw_context(struct drm_device *dev,
 		return ERR_PTR(-ENOMEM);
 
 	kref_init(&ctx->ref);
-	ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
-	INIT_LIST_HEAD(&ctx->link);
-	if (ctx->obj == NULL) {
-		kfree(ctx);
-		DRM_DEBUG_DRIVER("Context object allocated failed\n");
-		return ERR_PTR(-ENOMEM);
-	}
+	list_add_tail(&ctx->link, &dev_priv->context_list);
 
-	if (INTEL_INFO(dev)->gen >= 7) {
-		ret = i915_gem_object_set_cache_level(ctx->obj,
-						      I915_CACHE_L3_LLC);
-		/* Failure shouldn't ever happen this early */
-		if (WARN_ON(ret))
+	if (dev_priv->hw_context_size) {
+		ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
+		if (ctx->obj == NULL) {
+			ret = -ENOMEM;
 			goto err_out;
-	}
+		}
 
-	list_add_tail(&ctx->link, &dev_priv->context_list);
+		/*
+		 * Try to make the context utilize L3 as well as LLC.
+		 *
+		 * On VLV we don't have L3 controls in the PTEs so we
+		 * shouldn't touch the cache level, especially as that
+		 * would make the object snooped which might have a
+		 * negative performance impact.
+		 */
+		if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
+			ret = i915_gem_object_set_cache_level(ctx->obj,
+							      I915_CACHE_L3_LLC);
+			/* Failure shouldn't ever happen this early */
+			if (WARN_ON(ret))
+				goto err_out;
+		}
+	}
 
 	/* Default context will never have a file_priv */
-	if (file_priv == NULL)
-		return ctx;
-
-	ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0,
-			GFP_KERNEL);
-	if (ret < 0)
-		goto err_out;
+	if (file_priv != NULL) {
+		ret = idr_alloc(&file_priv->context_idr, ctx,
+				DEFAULT_CONTEXT_ID, 0, GFP_KERNEL);
+		if (ret < 0)
+			goto err_out;
+	} else
+		ret = DEFAULT_CONTEXT_ID;
 
 	ctx->file_priv = file_priv;
 	ctx->id = ret;
@@ -294,7 +301,7 @@ i915_gem_create_context(struct drm_device *dev,
 	if (IS_ERR(ctx))
 		return ctx;
 
-	if (is_global_default_ctx) {
+	if (is_global_default_ctx && ctx->obj) {
 		/* We may need to do things with the shrinker which
 		 * require us to immediately switch back to the default
 		 * context. This can cause a problem as pinning the
@@ -342,7 +349,7 @@ i915_gem_create_context(struct drm_device *dev,
 	return ctx;
 
 err_unpin:
-	if (is_global_default_ctx)
+	if (is_global_default_ctx && ctx->obj)
 		i915_gem_object_ggtt_unpin(ctx->obj);
 err_destroy:
 	i915_gem_context_unreference(ctx);
@@ -352,32 +359,22 @@ err_destroy:
 void i915_gem_context_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ring_buffer *ring;
 	int i;
 
-	if (!HAS_HW_CONTEXTS(dev))
-		return;
-
 	/* Prevent the hardware from restoring the last context (which hung) on
 	 * the next switch */
 	for (i = 0; i < I915_NUM_RINGS; i++) {
-		struct i915_hw_context *dctx;
-		if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
-			continue;
+		struct intel_ring_buffer *ring = &dev_priv->ring[i];
+		struct i915_hw_context *dctx = ring->default_context;
 
 		/* Do a fake switch to the default context */
-		ring = &dev_priv->ring[i];
-		dctx = ring->default_context;
-		if (WARN_ON(!dctx))
+		if (ring->last_context == dctx)
 			continue;
 
 		if (!ring->last_context)
 			continue;
 
-		if (ring->last_context == dctx)
-			continue;
-
-		if (i == RCS) {
+		if (dctx->obj && i == RCS) {
 			WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
 						      get_context_alignment(dev), 0));
 			/* Fake a finish/inactive */
@@ -394,44 +391,35 @@ void i915_gem_context_reset(struct drm_device *dev)
 int i915_gem_context_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ring_buffer *ring;
+	struct i915_hw_context *ctx;
 	int i;
 
-	if (!HAS_HW_CONTEXTS(dev))
-		return 0;
-
 	/* Init should only be called once per module load. Eventually the
 	 * restriction on the context_disabled check can be loosened. */
 	if (WARN_ON(dev_priv->ring[RCS].default_context))
 		return 0;
 
-	dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
-
-	if (dev_priv->hw_context_size > (1<<20)) {
-		DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
-		return -E2BIG;
+	if (HAS_HW_CONTEXTS(dev)) {
+		dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
+		if (dev_priv->hw_context_size > (1<<20)) {
+			DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
+					 dev_priv->hw_context_size);
+			dev_priv->hw_context_size = 0;
+		}
 	}
 
-	dev_priv->ring[RCS].default_context =
-		i915_gem_create_context(dev, NULL, USES_PPGTT(dev));
-
-	if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) {
-		DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n",
-				 PTR_ERR(dev_priv->ring[RCS].default_context));
-		return PTR_ERR(dev_priv->ring[RCS].default_context);
+	ctx = i915_gem_create_context(dev, NULL, USES_PPGTT(dev));
+	if (IS_ERR(ctx)) {
+		DRM_ERROR("Failed to create default global context (error %ld)\n",
+			  PTR_ERR(ctx));
+		return PTR_ERR(ctx);
 	}
 
-	for (i = RCS + 1; i < I915_NUM_RINGS; i++) {
-		if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
-			continue;
-
-		ring = &dev_priv->ring[i];
-
-		/* NB: RCS will hold a ref for all rings */
-		ring->default_context = dev_priv->ring[RCS].default_context;
-	}
+	/* NB: RCS will hold a ref for all rings */
+	for (i = 0; i < I915_NUM_RINGS; i++)
+		dev_priv->ring[i].default_context = ctx;
 
-	DRM_DEBUG_DRIVER("HW context support initialized\n");
+	DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->hw_context_size ? "HW" : "fake");
 	return 0;
 }
 
@@ -441,33 +429,30 @@ void i915_gem_context_fini(struct drm_device *dev)
 	struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
 	int i;
 
-	if (!HAS_HW_CONTEXTS(dev))
-		return;
-
-	/* The only known way to stop the gpu from accessing the hw context is
-	 * to reset it. Do this as the very last operation to avoid confusing
-	 * other code, leading to spurious errors. */
-	intel_gpu_reset(dev);
-
-	/* When default context is created and switched to, base object refcount
-	 * will be 2 (+1 from object creation and +1 from do_switch()).
-	 * i915_gem_context_fini() will be called after gpu_idle() has switched
-	 * to default context. So we need to unreference the base object once
-	 * to offset the do_switch part, so that i915_gem_context_unreference()
-	 * can then free the base object correctly. */
-	WARN_ON(!dev_priv->ring[RCS].last_context);
-	if (dev_priv->ring[RCS].last_context == dctx) {
-		/* Fake switch to NULL context */
-		WARN_ON(dctx->obj->active);
-		i915_gem_object_ggtt_unpin(dctx->obj);
-		i915_gem_context_unreference(dctx);
-		dev_priv->ring[RCS].last_context = NULL;
+	if (dctx->obj) {
+		/* The only known way to stop the gpu from accessing the hw context is
+		 * to reset it. Do this as the very last operation to avoid confusing
+		 * other code, leading to spurious errors. */
+		intel_gpu_reset(dev);
+
+		/* When default context is created and switched to, base object refcount
+		 * will be 2 (+1 from object creation and +1 from do_switch()).
+		 * i915_gem_context_fini() will be called after gpu_idle() has switched
+		 * to default context. So we need to unreference the base object once
+		 * to offset the do_switch part, so that i915_gem_context_unreference()
+		 * can then free the base object correctly. */
+		WARN_ON(!dev_priv->ring[RCS].last_context);
+		if (dev_priv->ring[RCS].last_context == dctx) {
+			/* Fake switch to NULL context */
+			WARN_ON(dctx->obj->active);
+			i915_gem_object_ggtt_unpin(dctx->obj);
+			i915_gem_context_unreference(dctx);
+			dev_priv->ring[RCS].last_context = NULL;
+		}
 	}
 
 	for (i = 0; i < I915_NUM_RINGS; i++) {
 		struct intel_ring_buffer *ring = &dev_priv->ring[i];
-		if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
-			continue;
 
 		if (ring->last_context)
 			i915_gem_context_unreference(ring->last_context);
@@ -478,7 +463,6 @@ void i915_gem_context_fini(struct drm_device *dev)
 
 	i915_gem_object_ggtt_unpin(dctx->obj);
 	i915_gem_context_unreference(dctx);
-	dev_priv->mm.aliasing_ppgtt = NULL;
 }
 
 int i915_gem_context_enable(struct drm_i915_private *dev_priv)
@@ -486,9 +470,6 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
 	struct intel_ring_buffer *ring;
 	int ret, i;
 
-	if (!HAS_HW_CONTEXTS(dev_priv->dev))
-		return 0;
-
 	/* This is the only place the aliasing PPGTT gets enabled, which means
 	 * it has to happen before we bail on reset */
 	if (dev_priv->mm.aliasing_ppgtt) {
@@ -503,7 +484,7 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
 	BUG_ON(!dev_priv->ring[RCS].default_context);
 
 	for_each_ring(ring, dev_priv, i) {
-		ret = do_switch(ring, ring->default_context);
+		ret = i915_switch_context(ring, ring->default_context);
 		if (ret)
 			return ret;
 	}
@@ -526,19 +507,6 @@ static int context_idr_cleanup(int id, void *p, void *data)
 int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_i915_file_private *file_priv = file->driver_priv;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (!HAS_HW_CONTEXTS(dev)) {
-		/* Cheat for hang stats */
-		file_priv->private_default_ctx =
-			kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL);
-
-		if (file_priv->private_default_ctx == NULL)
-			return -ENOMEM;
-
-		file_priv->private_default_ctx->vm = &dev_priv->gtt.base;
-		return 0;
-	}
 
 	idr_init(&file_priv->context_idr);
 
@@ -559,14 +527,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_i915_file_private *file_priv = file->driver_priv;
 
-	if (!HAS_HW_CONTEXTS(dev)) {
-		kfree(file_priv->private_default_ctx);
-		return;
-	}
-
 	idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
-	i915_gem_context_unreference(file_priv->private_default_ctx);
 	idr_destroy(&file_priv->context_idr);
+
+	i915_gem_context_unreference(file_priv->private_default_ctx);
 }
 
 struct i915_hw_context *
@@ -574,9 +538,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
 {
 	struct i915_hw_context *ctx;
 
-	if (!HAS_HW_CONTEXTS(file_priv->dev_priv->dev))
-		return file_priv->private_default_ctx;
-
 	ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id);
 	if (!ctx)
 		return ERR_PTR(-ENOENT);
@@ -596,7 +557,7 @@ mi_set_context(struct intel_ring_buffer *ring,
 	 * explicitly, so we rely on the value at ring init, stored in
 	 * itlb_before_ctx_switch.
 	 */
-	if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) {
+	if (IS_GEN6(ring->dev)) {
 		ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0);
 		if (ret)
 			return ret;
@@ -606,8 +567,8 @@ mi_set_context(struct intel_ring_buffer *ring,
 	if (ret)
 		return ret;
 
-	/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw */
-	if (IS_GEN7(ring->dev))
+	/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw */
+	if (INTEL_INFO(ring->dev)->gen >= 7)
 		intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 	else
 		intel_ring_emit(ring, MI_NOOP);
@@ -625,7 +586,7 @@ mi_set_context(struct intel_ring_buffer *ring,
 	 */
 	intel_ring_emit(ring, MI_NOOP);
 
-	if (IS_GEN7(ring->dev))
+	if (INTEL_INFO(ring->dev)->gen >= 7)
 		intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
 	else
 		intel_ring_emit(ring, MI_NOOP);
@@ -758,7 +719,6 @@ unpin_out:
 /**
  * i915_switch_context() - perform a GPU context switch.
  * @ring: ring for which we'll execute the context switch
- * @file_priv: file_priv associated with the context, may be NULL
  * @to: the context to switch to
  *
  * The context life cycle is simple. The context refcount is incremented and
@@ -767,24 +727,30 @@ unpin_out:
  * object while letting the normal object tracking destroy the backing BO.
  */
 int i915_switch_context(struct intel_ring_buffer *ring,
-			struct drm_file *file,
 			struct i915_hw_context *to)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
-	BUG_ON(file && to == NULL);
-
-	/* We have the fake context */
-	if (!HAS_HW_CONTEXTS(ring->dev)) {
-		ring->last_context = to;
+	if (to->obj == NULL) { /* We have the fake context */
+		if (to != ring->last_context) {
+			i915_gem_context_reference(to);
+			if (ring->last_context)
+				i915_gem_context_unreference(ring->last_context);
+			ring->last_context = to;
+		}
 		return 0;
 	}
 
 	return do_switch(ring, to);
 }
 
+static bool hw_context_enabled(struct drm_device *dev)
+{
+	return to_i915(dev)->hw_context_size;
+}
+
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 				  struct drm_file *file)
 {
@@ -793,7 +759,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 	struct i915_hw_context *ctx;
 	int ret;
 
-	if (!HAS_HW_CONTEXTS(dev))
+	if (!hw_context_enabled(dev))
 		return -ENODEV;
 
 	ret = i915_mutex_lock_interruptible(dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 9bb533e0d762..321102a8374b 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -161,12 +161,8 @@ static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
 	struct drm_device *dev = obj->base.dev;
-	int ret;
-
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return;
 
+	mutex_lock(&dev->struct_mutex);
 	if (--obj->vmapping_count == 0) {
 		vunmap(obj->dma_buf_vmapping);
 		obj->dma_buf_vmapping = NULL;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 7447160155a3..0ec8621eb4f8 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1132,7 +1132,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		mutex_unlock(&dev->struct_mutex);
 		ret = PTR_ERR(ctx);
 		goto pre_mutex_err;
-	} 
+	}
 
 	i915_gem_context_reference(ctx);
 
@@ -1142,6 +1142,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	eb = eb_create(args);
 	if (eb == NULL) {
+		i915_gem_context_unreference(ctx);
 		mutex_unlock(&dev->struct_mutex);
 		ret = -ENOMEM;
 		goto pre_mutex_err;
@@ -1221,7 +1222,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		goto err;
 
-	ret = i915_switch_context(ring, file, ctx);
+	ret = i915_switch_context(ring, ctx);
 	if (ret)
 		goto err;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index ab5e93c30aa2..0d514ff9b94c 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -50,64 +50,11 @@ bool intel_enable_ppgtt(struct drm_device *dev, bool full)
 
 	/* Full ppgtt disabled by default for now due to issues. */
 	if (full)
-		return false; /* HAS_PPGTT(dev) */
+		return HAS_PPGTT(dev) && (i915.enable_ppgtt == 2);
 	else
 		return HAS_ALIASING_PPGTT(dev);
 }
 
-#define GEN6_PPGTT_PD_ENTRIES 512
-#define I915_PPGTT_PT_ENTRIES (PAGE_SIZE / sizeof(gen6_gtt_pte_t))
-typedef uint64_t gen8_gtt_pte_t;
-typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
-
-/* PPGTT stuff */
-#define GEN6_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0xff0))
-#define HSW_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0x7f0))
-
-#define GEN6_PDE_VALID			(1 << 0)
-/* gen6+ has bit 11-4 for physical addr bit 39-32 */
-#define GEN6_PDE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
-
-#define GEN6_PTE_VALID			(1 << 0)
-#define GEN6_PTE_UNCACHED		(1 << 1)
-#define HSW_PTE_UNCACHED		(0)
-#define GEN6_PTE_CACHE_LLC		(2 << 1)
-#define GEN7_PTE_CACHE_L3_LLC		(3 << 1)
-#define GEN6_PTE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
-#define HSW_PTE_ADDR_ENCODE(addr)	HSW_GTT_ADDR_ENCODE(addr)
-
-/* Cacheability Control is a 4-bit value. The low three bits are stored in *
- * bits 3:1 of the PTE, while the fourth bit is stored in bit 11 of the PTE.
- */
-#define HSW_CACHEABILITY_CONTROL(bits)	((((bits) & 0x7) << 1) | \
-					 (((bits) & 0x8) << (11 - 3)))
-#define HSW_WB_LLC_AGE3			HSW_CACHEABILITY_CONTROL(0x2)
-#define HSW_WB_LLC_AGE0			HSW_CACHEABILITY_CONTROL(0x3)
-#define HSW_WB_ELLC_LLC_AGE0		HSW_CACHEABILITY_CONTROL(0xb)
-#define HSW_WB_ELLC_LLC_AGE3		HSW_CACHEABILITY_CONTROL(0x8)
-#define HSW_WT_ELLC_LLC_AGE0		HSW_CACHEABILITY_CONTROL(0x6)
-#define HSW_WT_ELLC_LLC_AGE3		HSW_CACHEABILITY_CONTROL(0x7)
-
-#define GEN8_PTES_PER_PAGE		(PAGE_SIZE / sizeof(gen8_gtt_pte_t))
-#define GEN8_PDES_PER_PAGE		(PAGE_SIZE / sizeof(gen8_ppgtt_pde_t))
-
-/* GEN8 legacy style addressis defined as a 3 level page table:
- * 31:30 | 29:21 | 20:12 |  11:0
- * PDPE  |  PDE  |  PTE  | offset
- * The difference as compared to normal x86 3 level page table is the PDPEs are
- * programmed via register.
- */
-#define GEN8_PDPE_SHIFT			30
-#define GEN8_PDPE_MASK			0x3
-#define GEN8_PDE_SHIFT			21
-#define GEN8_PDE_MASK			0x1ff
-#define GEN8_PTE_SHIFT			12
-#define GEN8_PTE_MASK			0x1ff
-
-#define PPAT_UNCACHED_INDEX		(_PAGE_PWT | _PAGE_PCD)
-#define PPAT_CACHED_PDE_INDEX		0 /* WB LLC */
-#define PPAT_CACHED_INDEX		_PAGE_PAT /* WB LLCeLLC */
-#define PPAT_DISPLAY_ELLC_INDEX		_PAGE_PCD /* WT eLLC */
 
 static void ppgtt_bind_vma(struct i915_vma *vma,
 			   enum i915_cache_level cache_level,
@@ -187,9 +134,6 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
 	return pte;
 }
 
-#define BYT_PTE_WRITEABLE		(1 << 1)
-#define BYT_PTE_SNOOPED_BY_CPU_CACHES	(1 << 2)
-
 static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
 				     enum i915_cache_level level,
 				     bool valid)
@@ -1057,8 +1001,6 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 
 static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
 {
-#define GEN6_PD_ALIGN (PAGE_SIZE * 16)
-#define GEN6_PD_SIZE (GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE)
 	struct drm_device *dev = ppgtt->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	bool retried = false;
@@ -1848,17 +1790,6 @@ static int ggtt_probe_common(struct drm_device *dev,
  * writing this data shouldn't be harmful even in those cases. */
 static void gen8_setup_private_ppat(struct drm_i915_private *dev_priv)
 {
-#define GEN8_PPAT_UC		(0<<0)
-#define GEN8_PPAT_WC		(1<<0)
-#define GEN8_PPAT_WT		(2<<0)
-#define GEN8_PPAT_WB		(3<<0)
-#define GEN8_PPAT_ELLC_OVERRIDE	(0<<2)
-/* FIXME(BDW): Bspec is completely confused about cache control bits. */
-#define GEN8_PPAT_LLC		(1<<2)
-#define GEN8_PPAT_LLCELLC	(2<<2)
-#define GEN8_PPAT_LLCeLLC	(3<<2)
-#define GEN8_PPAT_AGE(x)	(x<<4)
-#define GEN8_PPAT(i, x) ((uint64_t) (x) << ((i) * 8))
 	uint64_t pat;
 
 	pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC)     | /* for normal objects, no eLLC */
@@ -2031,6 +1962,10 @@ int i915_gem_gtt_init(struct drm_device *dev)
 		 gtt->base.total >> 20);
 	DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20);
 	DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20);
+#ifdef CONFIG_INTEL_IOMMU
+	if (intel_iommu_gfx_mapped)
+		DRM_INFO("VT-d active for gfx access\n");
+#endif
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
new file mode 100644
index 000000000000..b5e8ac0f5ce4
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Please try to maintain the following order within this file unless it makes
+ * sense to do otherwise. From top to bottom:
+ * 1. typedefs
+ * 2. #defines, and macros
+ * 3. structure definitions
+ * 4. function prototypes
+ *
+ * Within each section, please try to order by generation in ascending order,
+ * from top to bottom (ie. gen6 on the top, gen8 on the bottom).
+ */
+
+#ifndef __I915_GEM_GTT_H__
+#define __I915_GEM_GTT_H__
+
+typedef uint32_t gen6_gtt_pte_t;
+typedef uint64_t gen8_gtt_pte_t;
+typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
+
+#define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
+
+#define I915_PPGTT_PT_ENTRIES		(PAGE_SIZE / sizeof(gen6_gtt_pte_t))
+/* gen6-hsw has bit 11-4 for physical addr bit 39-32 */
+#define GEN6_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0xff0))
+#define GEN6_PTE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
+#define GEN6_PDE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
+#define GEN6_PTE_CACHE_LLC		(2 << 1)
+#define GEN6_PTE_UNCACHED		(1 << 1)
+#define GEN6_PTE_VALID			(1 << 0)
+
+#define GEN6_PPGTT_PD_ENTRIES		512
+#define GEN6_PD_SIZE			(GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE)
+#define GEN6_PD_ALIGN			(PAGE_SIZE * 16)
+#define GEN6_PDE_VALID			(1 << 0)
+
+#define GEN7_PTE_CACHE_L3_LLC		(3 << 1)
+
+#define BYT_PTE_SNOOPED_BY_CPU_CACHES	(1 << 2)
+#define BYT_PTE_WRITEABLE		(1 << 1)
+
+/* Cacheability Control is a 4-bit value. The low three bits are stored in bits
+ * 3:1 of the PTE, while the fourth bit is stored in bit 11 of the PTE.
+ */
+#define HSW_CACHEABILITY_CONTROL(bits)	((((bits) & 0x7) << 1) | \
+					 (((bits) & 0x8) << (11 - 3)))
+#define HSW_WB_LLC_AGE3			HSW_CACHEABILITY_CONTROL(0x2)
+#define HSW_WB_LLC_AGE0			HSW_CACHEABILITY_CONTROL(0x3)
+#define HSW_WB_ELLC_LLC_AGE3		HSW_CACHEABILITY_CONTROL(0x8)
+#define HSW_WB_ELLC_LLC_AGE0		HSW_CACHEABILITY_CONTROL(0xb)
+#define HSW_WT_ELLC_LLC_AGE3		HSW_CACHEABILITY_CONTROL(0x7)
+#define HSW_WT_ELLC_LLC_AGE0		HSW_CACHEABILITY_CONTROL(0x6)
+#define HSW_PTE_UNCACHED		(0)
+#define HSW_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0x7f0))
+#define HSW_PTE_ADDR_ENCODE(addr)	HSW_GTT_ADDR_ENCODE(addr)
+
+/* GEN8 legacy style address is defined as a 3 level page table:
+ * 31:30 | 29:21 | 20:12 |  11:0
+ * PDPE  |  PDE  |  PTE  | offset
+ * The difference as compared to normal x86 3 level page table is the PDPEs are
+ * programmed via register.
+ */
+#define GEN8_PDPE_SHIFT			30
+#define GEN8_PDPE_MASK			0x3
+#define GEN8_PDE_SHIFT			21
+#define GEN8_PDE_MASK			0x1ff
+#define GEN8_PTE_SHIFT			12
+#define GEN8_PTE_MASK			0x1ff
+#define GEN8_LEGACY_PDPS		4
+#define GEN8_PTES_PER_PAGE		(PAGE_SIZE / sizeof(gen8_gtt_pte_t))
+#define GEN8_PDES_PER_PAGE		(PAGE_SIZE / sizeof(gen8_ppgtt_pde_t))
+
+#define PPAT_UNCACHED_INDEX		(_PAGE_PWT | _PAGE_PCD)
+#define PPAT_CACHED_PDE_INDEX		0 /* WB LLC */
+#define PPAT_CACHED_INDEX		_PAGE_PAT /* WB LLCeLLC */
+#define PPAT_DISPLAY_ELLC_INDEX		_PAGE_PCD /* WT eLLC */
+
+#define GEN8_PPAT_AGE(x)		(x<<4)
+#define GEN8_PPAT_LLCeLLC		(3<<2)
+#define GEN8_PPAT_LLCELLC		(2<<2)
+#define GEN8_PPAT_LLC			(1<<2)
+#define GEN8_PPAT_WB			(3<<0)
+#define GEN8_PPAT_WT			(2<<0)
+#define GEN8_PPAT_WC			(1<<0)
+#define GEN8_PPAT_UC			(0<<0)
+#define GEN8_PPAT_ELLC_OVERRIDE		(0<<2)
+#define GEN8_PPAT(i, x)			((uint64_t) (x) << ((i) * 8))
+
+enum i915_cache_level;
+/**
+ * A VMA represents a GEM BO that is bound into an address space. Therefore, a
+ * VMA's presence cannot be guaranteed before binding, or after unbinding the
+ * object into/from the address space.
+ *
+ * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
+ * will always be <= an objects lifetime. So object refcounting should cover us.
+ */
+struct i915_vma {
+	struct drm_mm_node node;
+	struct drm_i915_gem_object *obj;
+	struct i915_address_space *vm;
+
+	/** This object's place on the active/inactive lists */
+	struct list_head mm_list;
+
+	struct list_head vma_link; /* Link in the object's VMA list */
+
+	/** This vma's place in the batchbuffer or on the eviction list */
+	struct list_head exec_list;
+
+	/**
+	 * Used for performing relocations during execbuffer insertion.
+	 */
+	struct hlist_node exec_node;
+	unsigned long exec_handle;
+	struct drm_i915_gem_exec_object2 *exec_entry;
+
+	/**
+	 * How many users have pinned this object in GTT space. The following
+	 * users can each hold at most one reference: pwrite/pread, pin_ioctl
+	 * (via user_pin_count), execbuffer (objects are not allowed multiple
+	 * times for the same batchbuffer), and the framebuffer code. When
+	 * switching/pageflipping, the framebuffer code has at most two buffers
+	 * pinned per crtc.
+	 *
+	 * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
+	 * bits with absolutely no headroom. So use 4 bits. */
+	unsigned int pin_count:4;
+#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
+
+	/** Unmap an object from an address space. This usually consists of
+	 * setting the valid PTE entries to a reserved scratch page. */
+	void (*unbind_vma)(struct i915_vma *vma);
+	/* Map an object into an address space with the given cache flags. */
+#define GLOBAL_BIND (1<<0)
+	void (*bind_vma)(struct i915_vma *vma,
+			 enum i915_cache_level cache_level,
+			 u32 flags);
+};
+
+struct i915_address_space {
+	struct drm_mm mm;
+	struct drm_device *dev;
+	struct list_head global_link;
+	unsigned long start;		/* Start offset always 0 for dri2 */
+	size_t total;		/* size addr space maps (ex. 2GB for ggtt) */
+
+	struct {
+		dma_addr_t addr;
+		struct page *page;
+	} scratch;
+
+	/**
+	 * List of objects currently involved in rendering.
+	 *
+	 * Includes buffers having the contents of their GPU caches
+	 * flushed, not necessarily primitives.  last_rendering_seqno
+	 * represents when the rendering involved will be completed.
+	 *
+	 * A reference is held on the buffer while on this list.
+	 */
+	struct list_head active_list;
+
+	/**
+	 * LRU list of objects which are not in the ringbuffer and
+	 * are ready to unbind, but are still in the GTT.
+	 *
+	 * last_rendering_seqno is 0 while an object is in this list.
+	 *
+	 * A reference is not held on the buffer while on this list,
+	 * as merely being GTT-bound shouldn't prevent its being
+	 * freed, and we'll pull it off the list in the free path.
+	 */
+	struct list_head inactive_list;
+
+	/* FIXME: Need a more generic return type */
+	gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
+				     enum i915_cache_level level,
+				     bool valid); /* Create a valid PTE */
+	void (*clear_range)(struct i915_address_space *vm,
+			    uint64_t start,
+			    uint64_t length,
+			    bool use_scratch);
+	void (*insert_entries)(struct i915_address_space *vm,
+			       struct sg_table *st,
+			       uint64_t start,
+			       enum i915_cache_level cache_level);
+	void (*cleanup)(struct i915_address_space *vm);
+};
+
+/* The Graphics Translation Table is the way in which GEN hardware translates a
+ * Graphics Virtual Address into a Physical Address. In addition to the normal
+ * collateral associated with any va->pa translations GEN hardware also has a
+ * portion of the GTT which can be mapped by the CPU and remain both coherent
+ * and correct (in cases like swizzling). That region is referred to as GMADR in
+ * the spec.
+ */
+struct i915_gtt {
+	struct i915_address_space base;
+	size_t stolen_size;		/* Total size of stolen memory */
+
+	unsigned long mappable_end;	/* End offset that we can CPU map */
+	struct io_mapping *mappable;	/* Mapping to our CPU mappable region */
+	phys_addr_t mappable_base;	/* PA of our GMADR */
+
+	/** "Graphics Stolen Memory" holds the global PTEs */
+	void __iomem *gsm;
+
+	bool do_idle_maps;
+
+	int mtrr;
+
+	/* global gtt ops */
+	int (*gtt_probe)(struct drm_device *dev, size_t *gtt_total,
+			  size_t *stolen, phys_addr_t *mappable_base,
+			  unsigned long *mappable_end);
+};
+
+struct i915_hw_ppgtt {
+	struct i915_address_space base;
+	struct kref ref;
+	struct drm_mm_node node;
+	unsigned num_pd_entries;
+	unsigned num_pd_pages; /* gen8+ */
+	union {
+		struct page **pt_pages;
+		struct page **gen8_pt_pages[GEN8_LEGACY_PDPS];
+	};
+	struct page *pd_pages;
+	union {
+		uint32_t pd_offset;
+		dma_addr_t pd_dma_addr[GEN8_LEGACY_PDPS];
+	};
+	union {
+		dma_addr_t *pt_dma_addr;
+		dma_addr_t *gen8_pt_dma_addr[4];
+	};
+
+	struct i915_hw_context *ctx;
+
+	int (*enable)(struct i915_hw_ppgtt *ppgtt);
+	int (*switch_mm)(struct i915_hw_ppgtt *ppgtt,
+			 struct intel_ring_buffer *ring,
+			 bool synchronous);
+	void (*debug_dump)(struct i915_hw_ppgtt *ppgtt, struct seq_file *m);
+};
+
+int i915_gem_gtt_init(struct drm_device *dev);
+void i915_gem_init_global_gtt(struct drm_device *dev);
+void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start,
+			       unsigned long mappable_end, unsigned long end);
+
+bool intel_enable_ppgtt(struct drm_device *dev, bool full);
+int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
+
+void i915_check_and_clear_faults(struct drm_device *dev);
+void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
+void i915_gem_restore_gtt_mappings(struct drm_device *dev);
+
+int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
+void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
+
+#endif
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 12f1d43b2d68..4865ade71f29 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -257,7 +257,8 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
 		err_printf(m, "  INSTPS: 0x%08x\n", ring->instps);
 	}
 	err_printf(m, "  INSTPM: 0x%08x\n", ring->instpm);
-	err_printf(m, "  FADDR: 0x%08x\n", ring->faddr);
+	err_printf(m, "  FADDR: 0x%08x %08x\n", upper_32_bits(ring->faddr),
+		   lower_32_bits(ring->faddr));
 	if (INTEL_INFO(dev)->gen >= 6) {
 		err_printf(m, "  RC PSMI: 0x%08x\n", ring->rc_psmi);
 		err_printf(m, "  FAULT_REG: 0x%08x\n", ring->fault_reg);
@@ -452,16 +453,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 			err_printf(m, "%s --- HW Context = 0x%08x\n",
 				   dev_priv->ring[i].name,
 				   obj->gtt_offset);
-			offset = 0;
-			for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
-				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
-					   offset,
-					   obj->pages[0][elt],
-					   obj->pages[0][elt+1],
-					   obj->pages[0][elt+2],
-					   obj->pages[0][elt+3]);
-					offset += 16;
-			}
+			print_error_obj(m, obj);
 		}
 	}
 
@@ -781,8 +773,10 @@ static void i915_record_ring_state(struct drm_device *dev,
 		ering->instdone = I915_READ(RING_INSTDONE(ring->mmio_base));
 		ering->instps = I915_READ(RING_INSTPS(ring->mmio_base));
 		ering->bbaddr = I915_READ(RING_BBADDR(ring->mmio_base));
-		if (INTEL_INFO(dev)->gen >= 8)
+		if (INTEL_INFO(dev)->gen >= 8) {
+			ering->faddr |= (u64) I915_READ(RING_DMA_FADD_UDW(ring->mmio_base)) << 32;
 			ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
+		}
 		ering->bbstate = I915_READ(RING_BBSTATE(ring->mmio_base));
 	} else {
 		ering->faddr = I915_READ(DMA_FADD_I8XX);
@@ -875,10 +869,7 @@ static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) {
-			ering->ctx = i915_error_object_create_sized(dev_priv,
-								    obj,
-								    &dev_priv->gtt.base,
-								    1);
+			ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
 			break;
 		}
 	}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7753249b3a95..7a4d3ae807df 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -80,17 +80,64 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
 	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
 };
 
+/* IIR can theoretically queue up two events. Be paranoid. */
+#define GEN8_IRQ_RESET_NDX(type, which) do { \
+	I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
+	POSTING_READ(GEN8_##type##_IMR(which)); \
+	I915_WRITE(GEN8_##type##_IER(which), 0); \
+	I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
+	POSTING_READ(GEN8_##type##_IIR(which)); \
+	I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
+	POSTING_READ(GEN8_##type##_IIR(which)); \
+} while (0)
+
+#define GEN5_IRQ_RESET(type) do { \
+	I915_WRITE(type##IMR, 0xffffffff); \
+	POSTING_READ(type##IMR); \
+	I915_WRITE(type##IER, 0); \
+	I915_WRITE(type##IIR, 0xffffffff); \
+	POSTING_READ(type##IIR); \
+	I915_WRITE(type##IIR, 0xffffffff); \
+	POSTING_READ(type##IIR); \
+} while (0)
+
+/*
+ * We should clear IMR at preinstall/uninstall, and just check at postinstall.
+ */
+#define GEN5_ASSERT_IIR_IS_ZERO(reg) do { \
+	u32 val = I915_READ(reg); \
+	if (val) { \
+		WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", \
+		     (reg), val); \
+		I915_WRITE((reg), 0xffffffff); \
+		POSTING_READ(reg); \
+		I915_WRITE((reg), 0xffffffff); \
+		POSTING_READ(reg); \
+	} \
+} while (0)
+
+#define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \
+	GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \
+	I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
+	I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \
+	POSTING_READ(GEN8_##type##_IER(which)); \
+} while (0)
+
+#define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \
+	GEN5_ASSERT_IIR_IS_ZERO(type##IIR); \
+	I915_WRITE(type##IMR, (imr_val)); \
+	I915_WRITE(type##IER, (ier_val)); \
+	POSTING_READ(type##IER); \
+} while (0)
+
 /* For display hotplug interrupt */
 static void
 ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (dev_priv->pm.irqs_disabled) {
-		WARN(1, "IRQs disabled\n");
-		dev_priv->pm.regsave.deimr &= ~mask;
+	if (WARN_ON(dev_priv->pm.irqs_disabled))
 		return;
-	}
 
 	if ((dev_priv->irq_mask & mask) != 0) {
 		dev_priv->irq_mask &= ~mask;
@@ -104,11 +151,8 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (dev_priv->pm.irqs_disabled) {
-		WARN(1, "IRQs disabled\n");
-		dev_priv->pm.regsave.deimr |= mask;
+	if (WARN_ON(dev_priv->pm.irqs_disabled))
 		return;
-	}
 
 	if ((dev_priv->irq_mask & mask) != mask) {
 		dev_priv->irq_mask |= mask;
@@ -129,13 +173,8 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
 {
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (dev_priv->pm.irqs_disabled) {
-		WARN(1, "IRQs disabled\n");
-		dev_priv->pm.regsave.gtimr &= ~interrupt_mask;
-		dev_priv->pm.regsave.gtimr |= (~enabled_irq_mask &
-						interrupt_mask);
+	if (WARN_ON(dev_priv->pm.irqs_disabled))
 		return;
-	}
 
 	dev_priv->gt_irq_mask &= ~interrupt_mask;
 	dev_priv->gt_irq_mask |= (~enabled_irq_mask & interrupt_mask);
@@ -167,13 +206,8 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (dev_priv->pm.irqs_disabled) {
-		WARN(1, "IRQs disabled\n");
-		dev_priv->pm.regsave.gen6_pmimr &= ~interrupt_mask;
-		dev_priv->pm.regsave.gen6_pmimr |= (~enabled_irq_mask &
-						     interrupt_mask);
+	if (WARN_ON(dev_priv->pm.irqs_disabled))
 		return;
-	}
 
 	new_val = dev_priv->pm_irq_mask;
 	new_val &= ~interrupt_mask;
@@ -313,14 +347,8 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (dev_priv->pm.irqs_disabled &&
-	    (interrupt_mask & SDE_HOTPLUG_MASK_CPT)) {
-		WARN(1, "IRQs disabled\n");
-		dev_priv->pm.regsave.sdeimr &= ~interrupt_mask;
-		dev_priv->pm.regsave.sdeimr |= (~enabled_irq_mask &
-						 interrupt_mask);
+	if (WARN_ON(dev_priv->pm.irqs_disabled))
 		return;
-	}
 
 	I915_WRITE(SDEIMR, sdeimr);
 	POSTING_READ(SDEIMR);
@@ -503,8 +531,10 @@ __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
-	                 status_mask & ~PIPESTAT_INT_STATUS_MASK))
+	if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+		      status_mask & ~PIPESTAT_INT_STATUS_MASK,
+		      "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
+		      pipe_name(pipe), enable_mask, status_mask))
 		return;
 
 	if ((pipestat & enable_mask) == enable_mask)
@@ -527,8 +557,10 @@ __i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
-	                 status_mask & ~PIPESTAT_INT_STATUS_MASK))
+	if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+		      status_mask & ~PIPESTAT_INT_STATUS_MASK,
+		      "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
+		      pipe_name(pipe), enable_mask, status_mask))
 		return;
 
 	if ((pipestat & enable_mask) == 0)
@@ -1609,6 +1641,33 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
 		gmbus_irq_handler(dev);
 }
 
+static void i9xx_hpd_irq_handler(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+
+	if (IS_G4X(dev)) {
+		u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
+
+		intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_g4x);
+	} else {
+		u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
+
+		intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
+	}
+
+	if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&
+	    hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+		dp_aux_irq_handler(dev);
+
+	I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+	/*
+	 * Make sure hotplug status is cleared before we clear IIR, or else we
+	 * may miss hotplug events.
+	 */
+	POSTING_READ(PORT_HOTPLUG_STAT);
+}
+
 static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -1631,19 +1690,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 		valleyview_pipestat_irq_handler(dev, iir);
 
 		/* Consume port.  Then clear IIR or we'll miss events */
-		if (iir & I915_DISPLAY_PORT_INTERRUPT) {
-			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
-			u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
-
-			intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
-
-			if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
-				dp_aux_irq_handler(dev);
-
-			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-			I915_READ(PORT_HOTPLUG_STAT);
-		}
-
+		if (iir & I915_DISPLAY_PORT_INTERRUPT)
+			i9xx_hpd_irq_handler(dev);
 
 		if (pm_iir)
 			gen6_rps_irq_handler(dev_priv, pm_iir);
@@ -2012,7 +2060,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
 		if (pipe_iir & GEN8_PIPE_VBLANK)
 			drm_handle_vblank(dev, pipe);
 
-		if (pipe_iir & GEN8_PIPE_FLIP_DONE) {
+		if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
 			intel_prepare_page_flip(dev, pipe);
 			intel_finish_page_flip_plane(dev, pipe);
 		}
@@ -2501,6 +2549,56 @@ ring_idle(struct intel_ring_buffer *ring, u32 seqno)
 		i915_seqno_passed(seqno, ring_last_seqno(ring)));
 }
 
+static bool
+ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
+{
+	if (INTEL_INFO(dev)->gen >= 8) {
+		/*
+		 * FIXME: gen8 semaphore support - currently we don't emit
+		 * semaphores on bdw anyway, but this needs to be addressed when
+		 * we merge that code.
+		 */
+		return false;
+	} else {
+		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
+		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
+				 MI_SEMAPHORE_REGISTER);
+	}
+}
+
+static struct intel_ring_buffer *
+semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
+{
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct intel_ring_buffer *signaller;
+	int i;
+
+	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
+		/*
+		 * FIXME: gen8 semaphore support - currently we don't emit
+		 * semaphores on bdw anyway, but this needs to be addressed when
+		 * we merge that code.
+		 */
+		return NULL;
+	} else {
+		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
+
+		for_each_ring(signaller, dev_priv, i) {
+			if(ring == signaller)
+				continue;
+
+			if (sync_bits ==
+			    signaller->semaphore_register[ring->id])
+				return signaller;
+		}
+	}
+
+	DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x\n",
+		  ring->id, ipehr);
+
+	return NULL;
+}
+
 static struct intel_ring_buffer *
 semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 {
@@ -2509,8 +2607,7 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 	int i;
 
 	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
-	if ((ipehr & ~(0x3 << 16)) !=
-	    (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | MI_SEMAPHORE_REGISTER))
+	if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
 		return NULL;
 
 	/*
@@ -2542,7 +2639,7 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 		return NULL;
 
 	*seqno = ioread32(ring->virtual_start + head + 4) + 1;
-	return &dev_priv->ring[(ring->id + (((ipehr >> 17) & 1) + 1)) % 3];
+	return semaphore_wait_to_signaller_ring(ring, ipehr);
 }
 
 static int semaphore_passed(struct intel_ring_buffer *ring)
@@ -2749,57 +2846,68 @@ void i915_queue_hangcheck(struct drm_device *dev)
 		  round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
 }
 
-static void ibx_irq_preinstall(struct drm_device *dev)
+static void ibx_irq_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (HAS_PCH_NOP(dev))
 		return;
 
-	/* south display irq */
-	I915_WRITE(SDEIMR, 0xffffffff);
-	/*
-	 * SDEIER is also touched by the interrupt handler to work around missed
-	 * PCH interrupts. Hence we can't update it after the interrupt handler
-	 * is enabled - instead we unconditionally enable all PCH interrupt
-	 * sources here, but then only unmask them as needed with SDEIMR.
-	 */
+	GEN5_IRQ_RESET(SDE);
+
+	if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
+		I915_WRITE(SERR_INT, 0xffffffff);
+}
+
+/*
+ * SDEIER is also touched by the interrupt handler to work around missed PCH
+ * interrupts. Hence we can't update it after the interrupt handler is enabled -
+ * instead we unconditionally enable all PCH interrupt sources here, but then
+ * only unmask them as needed with SDEIMR.
+ *
+ * This function needs to be called before interrupts are enabled.
+ */
+static void ibx_irq_pre_postinstall(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (HAS_PCH_NOP(dev))
+		return;
+
+	WARN_ON(I915_READ(SDEIER) != 0);
 	I915_WRITE(SDEIER, 0xffffffff);
 	POSTING_READ(SDEIER);
 }
 
-static void gen5_gt_irq_preinstall(struct drm_device *dev)
+static void gen5_gt_irq_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	/* and GT */
-	I915_WRITE(GTIMR, 0xffffffff);
-	I915_WRITE(GTIER, 0x0);
-	POSTING_READ(GTIER);
-
-	if (INTEL_INFO(dev)->gen >= 6) {
-		/* and PM */
-		I915_WRITE(GEN6_PMIMR, 0xffffffff);
-		I915_WRITE(GEN6_PMIER, 0x0);
-		POSTING_READ(GEN6_PMIER);
-	}
+	GEN5_IRQ_RESET(GT);
+	if (INTEL_INFO(dev)->gen >= 6)
+		GEN5_IRQ_RESET(GEN6_PM);
 }
 
 /* drm_dma.h hooks
 */
-static void ironlake_irq_preinstall(struct drm_device *dev)
+static void ironlake_irq_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	I915_WRITE(HWSTAM, 0xeffe);
+	I915_WRITE(HWSTAM, 0xffffffff);
 
-	I915_WRITE(DEIMR, 0xffffffff);
-	I915_WRITE(DEIER, 0x0);
-	POSTING_READ(DEIER);
+	GEN5_IRQ_RESET(DE);
+	if (IS_GEN7(dev))
+		I915_WRITE(GEN7_ERR_INT, 0xffffffff);
 
-	gen5_gt_irq_preinstall(dev);
+	gen5_gt_irq_reset(dev);
+
+	ibx_irq_reset(dev);
+}
 
-	ibx_irq_preinstall(dev);
+static void ironlake_irq_preinstall(struct drm_device *dev)
+{
+	ironlake_irq_reset(dev);
 }
 
 static void valleyview_irq_preinstall(struct drm_device *dev)
@@ -2817,7 +2925,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
 
-	gen5_gt_irq_preinstall(dev);
+	gen5_gt_irq_reset(dev);
 
 	I915_WRITE(DPINVGTT, 0xff);
 
@@ -2831,7 +2939,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
 	POSTING_READ(VLV_IER);
 }
 
-static void gen8_irq_preinstall(struct drm_device *dev)
+static void gen8_irq_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
@@ -2839,43 +2947,24 @@ static void gen8_irq_preinstall(struct drm_device *dev)
 	I915_WRITE(GEN8_MASTER_IRQ, 0);
 	POSTING_READ(GEN8_MASTER_IRQ);
 
-	/* IIR can theoretically queue up two events. Be paranoid */
-#define GEN8_IRQ_INIT_NDX(type, which) do { \
-		I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
-		POSTING_READ(GEN8_##type##_IMR(which)); \
-		I915_WRITE(GEN8_##type##_IER(which), 0); \
-		I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
-		POSTING_READ(GEN8_##type##_IIR(which)); \
-		I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
-	} while (0)
-
-#define GEN8_IRQ_INIT(type) do { \
-		I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \
-		POSTING_READ(GEN8_##type##_IMR); \
-		I915_WRITE(GEN8_##type##_IER, 0); \
-		I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
-		POSTING_READ(GEN8_##type##_IIR); \
-		I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
-	} while (0)
-
-	GEN8_IRQ_INIT_NDX(GT, 0);
-	GEN8_IRQ_INIT_NDX(GT, 1);
-	GEN8_IRQ_INIT_NDX(GT, 2);
-	GEN8_IRQ_INIT_NDX(GT, 3);
+	GEN8_IRQ_RESET_NDX(GT, 0);
+	GEN8_IRQ_RESET_NDX(GT, 1);
+	GEN8_IRQ_RESET_NDX(GT, 2);
+	GEN8_IRQ_RESET_NDX(GT, 3);
 
-	for_each_pipe(pipe) {
-		GEN8_IRQ_INIT_NDX(DE_PIPE, pipe);
-	}
+	for_each_pipe(pipe)
+		GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
 
-	GEN8_IRQ_INIT(DE_PORT);
-	GEN8_IRQ_INIT(DE_MISC);
-	GEN8_IRQ_INIT(PCU);
-#undef GEN8_IRQ_INIT
-#undef GEN8_IRQ_INIT_NDX
+	GEN5_IRQ_RESET(GEN8_DE_PORT_);
+	GEN5_IRQ_RESET(GEN8_DE_MISC_);
+	GEN5_IRQ_RESET(GEN8_PCU_);
 
-	POSTING_READ(GEN8_PCU_IIR);
+	ibx_irq_reset(dev);
+}
 
-	ibx_irq_preinstall(dev);
+static void gen8_irq_preinstall(struct drm_device *dev)
+{
+	gen8_irq_reset(dev);
 }
 
 static void ibx_hpd_irq_setup(struct drm_device *dev)
@@ -2921,15 +3010,12 @@ static void ibx_irq_postinstall(struct drm_device *dev)
 	if (HAS_PCH_NOP(dev))
 		return;
 
-	if (HAS_PCH_IBX(dev)) {
+	if (HAS_PCH_IBX(dev))
 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
-	} else {
+	else
 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
 
-		I915_WRITE(SERR_INT, I915_READ(SERR_INT));
-	}
-
-	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
+	GEN5_ASSERT_IIR_IS_ZERO(SDEIIR);
 	I915_WRITE(SDEIMR, ~mask);
 }
 
@@ -2955,10 +3041,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
 		gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
 	}
 
-	I915_WRITE(GTIIR, I915_READ(GTIIR));
-	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-	I915_WRITE(GTIER, gt_irqs);
-	POSTING_READ(GTIER);
+	GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs);
 
 	if (INTEL_INFO(dev)->gen >= 6) {
 		pm_irqs |= dev_priv->pm_rps_events;
@@ -2967,10 +3050,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
 			pm_irqs |= PM_VEBOX_USER_INTERRUPT;
 
 		dev_priv->pm_irq_mask = 0xffffffff;
-		I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
-		I915_WRITE(GEN6_PMIMR, dev_priv->pm_irq_mask);
-		I915_WRITE(GEN6_PMIER, pm_irqs);
-		POSTING_READ(GEN6_PMIER);
+		GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_irq_mask, pm_irqs);
 	}
 }
 
@@ -2987,8 +3067,6 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 				DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB);
 		extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
 			      DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB);
-
-		I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
 	} else {
 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
 				DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
@@ -3001,11 +3079,11 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 
 	dev_priv->irq_mask = ~display_mask;
 
-	/* should always can generate irq */
-	I915_WRITE(DEIIR, I915_READ(DEIIR));
-	I915_WRITE(DEIMR, dev_priv->irq_mask);
-	I915_WRITE(DEIER, display_mask | extra_mask);
-	POSTING_READ(DEIER);
+	I915_WRITE(HWSTAM, 0xeffe);
+
+	ibx_irq_pre_postinstall(dev);
+
+	GEN5_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask);
 
 	gen5_gt_irq_postinstall(dev);
 
@@ -3165,21 +3243,14 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
 		GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT
 		};
 
-	for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++) {
-		u32 tmp = I915_READ(GEN8_GT_IIR(i));
-		if (tmp)
-			DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n",
-				  i, tmp);
-		I915_WRITE(GEN8_GT_IMR(i), ~gt_interrupts[i]);
-		I915_WRITE(GEN8_GT_IER(i), gt_interrupts[i]);
-	}
-	POSTING_READ(GEN8_GT_IER(0));
+	for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++)
+		GEN8_IRQ_INIT_NDX(GT, i, ~gt_interrupts[i], gt_interrupts[i]);
 }
 
 static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
-	uint32_t de_pipe_masked = GEN8_PIPE_FLIP_DONE |
+	uint32_t de_pipe_masked = GEN8_PIPE_PRIMARY_FLIP_DONE |
 		GEN8_PIPE_CDCLK_CRC_DONE |
 		GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
 	uint32_t de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
@@ -3189,25 +3260,19 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 	dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked;
 	dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
 
-	for_each_pipe(pipe) {
-		u32 tmp = I915_READ(GEN8_DE_PIPE_IIR(pipe));
-		if (tmp)
-			DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n",
-				  pipe, tmp);
-		I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
-		I915_WRITE(GEN8_DE_PIPE_IER(pipe), de_pipe_enables);
-	}
-	POSTING_READ(GEN8_DE_PIPE_ISR(0));
+	for_each_pipe(pipe)
+		GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, dev_priv->de_irq_mask[pipe],
+				  de_pipe_enables);
 
-	I915_WRITE(GEN8_DE_PORT_IMR, ~GEN8_AUX_CHANNEL_A);
-	I915_WRITE(GEN8_DE_PORT_IER, GEN8_AUX_CHANNEL_A);
-	POSTING_READ(GEN8_DE_PORT_IER);
+	GEN5_IRQ_INIT(GEN8_DE_PORT_, ~GEN8_AUX_CHANNEL_A, GEN8_AUX_CHANNEL_A);
 }
 
 static int gen8_irq_postinstall(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	ibx_irq_pre_postinstall(dev);
+
 	gen8_gt_irq_postinstall(dev_priv);
 	gen8_de_irq_postinstall(dev_priv);
 
@@ -3222,41 +3287,13 @@ static int gen8_irq_postinstall(struct drm_device *dev)
 static void gen8_irq_uninstall(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipe;
 
 	if (!dev_priv)
 		return;
 
-	I915_WRITE(GEN8_MASTER_IRQ, 0);
-
-#define GEN8_IRQ_FINI_NDX(type, which) do { \
-		I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
-		I915_WRITE(GEN8_##type##_IER(which), 0); \
-		I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
-	} while (0)
-
-#define GEN8_IRQ_FINI(type) do { \
-		I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \
-		I915_WRITE(GEN8_##type##_IER, 0); \
-		I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
-	} while (0)
-
-	GEN8_IRQ_FINI_NDX(GT, 0);
-	GEN8_IRQ_FINI_NDX(GT, 1);
-	GEN8_IRQ_FINI_NDX(GT, 2);
-	GEN8_IRQ_FINI_NDX(GT, 3);
-
-	for_each_pipe(pipe) {
-		GEN8_IRQ_FINI_NDX(DE_PIPE, pipe);
-	}
-
-	GEN8_IRQ_FINI(DE_PORT);
-	GEN8_IRQ_FINI(DE_MISC);
-	GEN8_IRQ_FINI(PCU);
-#undef GEN8_IRQ_FINI
-#undef GEN8_IRQ_FINI_NDX
+	intel_hpd_irq_uninstall(dev_priv);
 
-	POSTING_READ(GEN8_PCU_IIR);
+	gen8_irq_reset(dev);
 }
 
 static void valleyview_irq_uninstall(struct drm_device *dev)
@@ -3299,26 +3336,7 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
 
 	intel_hpd_irq_uninstall(dev_priv);
 
-	I915_WRITE(HWSTAM, 0xffffffff);
-
-	I915_WRITE(DEIMR, 0xffffffff);
-	I915_WRITE(DEIER, 0x0);
-	I915_WRITE(DEIIR, I915_READ(DEIIR));
-	if (IS_GEN7(dev))
-		I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
-
-	I915_WRITE(GTIMR, 0xffffffff);
-	I915_WRITE(GTIER, 0x0);
-	I915_WRITE(GTIIR, I915_READ(GTIIR));
-
-	if (HAS_PCH_NOP(dev))
-		return;
-
-	I915_WRITE(SDEIMR, 0xffffffff);
-	I915_WRITE(SDEIER, 0x0);
-	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
-	if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
-		I915_WRITE(SERR_INT, I915_READ(SERR_INT));
+	ironlake_irq_reset(dev);
 }
 
 static void i8xx_irq_preinstall(struct drm_device * dev)
@@ -3626,16 +3644,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 			break;
 
 		/* Consume port.  Then clear IIR or we'll miss events */
-		if ((I915_HAS_HOTPLUG(dev)) &&
-		    (iir & I915_DISPLAY_PORT_INTERRUPT)) {
-			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
-			u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
-
-			intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
-
-			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-			POSTING_READ(PORT_HOTPLUG_STAT);
-		}
+		if (I915_HAS_HOTPLUG(dev) &&
+		    iir & I915_DISPLAY_PORT_INTERRUPT)
+			i9xx_hpd_irq_handler(dev);
 
 		I915_WRITE(IIR, iir & ~flip_mask);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
@@ -3869,22 +3880,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 		ret = IRQ_HANDLED;
 
 		/* Consume port.  Then clear IIR or we'll miss events */
-		if (iir & I915_DISPLAY_PORT_INTERRUPT) {
-			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
-			u32 hotplug_trigger = hotplug_status & (IS_G4X(dev) ?
-								  HOTPLUG_INT_STATUS_G4X :
-								  HOTPLUG_INT_STATUS_I915);
-
-			intel_hpd_irq_handler(dev, hotplug_trigger,
-					      IS_G4X(dev) ? hpd_status_g4x : hpd_status_i915);
-
-			if (IS_G4X(dev) &&
-			    (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X))
-				dp_aux_irq_handler(dev);
-
-			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-			I915_READ(PORT_HOTPLUG_STAT);
-		}
+		if (iir & I915_DISPLAY_PORT_INTERRUPT)
+			i9xx_hpd_irq_handler(dev);
 
 		I915_WRITE(IIR, iir & ~flip_mask);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
@@ -4111,57 +4108,20 @@ void intel_hpd_init(struct drm_device *dev)
 }
 
 /* Disable interrupts so we can allow runtime PM. */
-void hsw_runtime_pm_disable_interrupts(struct drm_device *dev)
+void intel_runtime_pm_disable_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long irqflags;
-
-	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-
-	dev_priv->pm.regsave.deimr = I915_READ(DEIMR);
-	dev_priv->pm.regsave.sdeimr = I915_READ(SDEIMR);
-	dev_priv->pm.regsave.gtimr = I915_READ(GTIMR);
-	dev_priv->pm.regsave.gtier = I915_READ(GTIER);
-	dev_priv->pm.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
-
-	ironlake_disable_display_irq(dev_priv, 0xffffffff);
-	ibx_disable_display_interrupt(dev_priv, 0xffffffff);
-	ilk_disable_gt_irq(dev_priv, 0xffffffff);
-	snb_disable_pm_irq(dev_priv, 0xffffffff);
 
+	dev->driver->irq_uninstall(dev);
 	dev_priv->pm.irqs_disabled = true;
-
-	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
 /* Restore interrupts so we can recover from runtime PM. */
-void hsw_runtime_pm_restore_interrupts(struct drm_device *dev)
+void intel_runtime_pm_restore_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long irqflags;
-	uint32_t val;
-
-	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-
-	val = I915_READ(DEIMR);
-	WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
-
-	val = I915_READ(SDEIMR);
-	WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
-
-	val = I915_READ(GTIMR);
-	WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
-
-	val = I915_READ(GEN6_PMIMR);
-	WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
 
 	dev_priv->pm.irqs_disabled = false;
-
-	ironlake_enable_display_irq(dev_priv, ~dev_priv->pm.regsave.deimr);
-	ibx_enable_display_interrupt(dev_priv, ~dev_priv->pm.regsave.sdeimr);
-	ilk_enable_gt_irq(dev_priv, ~dev_priv->pm.regsave.gtimr);
-	snb_enable_pm_irq(dev_priv, ~dev_priv->pm.regsave.gen6_pmimr);
-	I915_WRITE(GTIER, dev_priv->pm.regsave.gtier);
-
-	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+	dev->driver->irq_preinstall(dev);
+	dev->driver->irq_postinstall(dev);
 }
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d1d7980f0e01..d05a2afa17dc 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -46,7 +46,8 @@ struct i915_params i915 __read_mostly = {
 	.reset = true,
 	.invert_brightness = 0,
 	.disable_display = 0,
-	.enable_cmd_parser = 0,
+	.enable_cmd_parser = 1,
+	.disable_vtd_wa = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -149,6 +150,9 @@ MODULE_PARM_DESC(invert_brightness,
 module_param_named(disable_display, i915.disable_display, bool, 0600);
 MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
 
+module_param_named(disable_vtd_wa, i915.disable_vtd_wa, bool, 0600);
+MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)");
+
 module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
 MODULE_PARM_DESC(enable_cmd_parser,
-		 "Enable command parsing (1=enabled, 0=disabled [default])");
+		 "Enable command parsing (1=enabled [default], 0=disabled)");
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 9f5b18d9d885..8f845556503e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -190,6 +190,8 @@
  * Memory interface instructions used by the kernel
  */
 #define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
+/* Many MI commands use bit 22 of the header dword for GGTT vs PPGTT */
+#define  MI_GLOBAL_GTT    (1<<22)
 
 #define MI_NOOP			MI_INSTR(0, 0)
 #define MI_USER_INTERRUPT	MI_INSTR(0x02, 0)
@@ -244,7 +246,8 @@
 #define   MI_SEMAPHORE_SYNC_BVE	    (0<<16) /* VECS wait for BCS  (VEBSYNC) */
 #define   MI_SEMAPHORE_SYNC_VVE	    (1<<16) /* VECS wait for VCS  (VEVSYNC) */
 #define   MI_SEMAPHORE_SYNC_RVE	    (2<<16) /* VECS wait for RCS  (VERSYNC) */
-#define   MI_SEMAPHORE_SYNC_INVALID  (3<<16)
+#define   MI_SEMAPHORE_SYNC_INVALID (3<<16)
+#define   MI_SEMAPHORE_SYNC_MASK    (3<<16)
 #define MI_SET_CONTEXT		MI_INSTR(0x18, 0)
 #define   MI_MM_SPACE_GTT		(1<<8)
 #define   MI_MM_SPACE_PHYSICAL		(0<<8)
@@ -262,13 +265,16 @@
  * - One can actually load arbitrary many arbitrary registers: Simply issue x
  *   address/value pairs. Don't overdue it, though, x <= 2^4 must hold!
  */
-#define MI_LOAD_REGISTER_IMM(x)	MI_INSTR(0x22, 2*x-1)
-#define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1)
+#define MI_LOAD_REGISTER_IMM(x)	MI_INSTR(0x22, 2*(x)-1)
+#define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*(x)-1)
+#define MI_STORE_REGISTER_MEM_GEN8(x) MI_INSTR(0x24, 3*(x)-1)
 #define   MI_SRM_LRM_GLOBAL_GTT		(1<<22)
 #define MI_FLUSH_DW		MI_INSTR(0x26, 1) /* for GEN6 */
 #define   MI_FLUSH_DW_STORE_INDEX	(1<<21)
 #define   MI_INVALIDATE_TLB		(1<<18)
 #define   MI_FLUSH_DW_OP_STOREDW	(1<<14)
+#define   MI_FLUSH_DW_OP_MASK		(3<<14)
+#define   MI_FLUSH_DW_NOTIFY		(1<<8)
 #define   MI_INVALIDATE_BSD		(1<<7)
 #define   MI_FLUSH_DW_USE_GTT		(1<<2)
 #define   MI_FLUSH_DW_USE_PPGTT		(0<<2)
@@ -330,9 +336,12 @@
 #define   DISPLAY_PLANE_B           (1<<20)
 #define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
 #define   PIPE_CONTROL_GLOBAL_GTT_IVB			(1<<24) /* gen7+ */
+#define   PIPE_CONTROL_MMIO_WRITE			(1<<23)
+#define   PIPE_CONTROL_STORE_DATA_INDEX			(1<<21)
 #define   PIPE_CONTROL_CS_STALL				(1<<20)
 #define   PIPE_CONTROL_TLB_INVALIDATE			(1<<18)
 #define   PIPE_CONTROL_QW_WRITE				(1<<14)
+#define   PIPE_CONTROL_POST_SYNC_OP_MASK                (3<<14)
 #define   PIPE_CONTROL_DEPTH_STALL			(1<<13)
 #define   PIPE_CONTROL_WRITE_FLUSH			(1<<12)
 #define   PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH	(1<<12) /* gen6+ */
@@ -347,6 +356,94 @@
 #define   PIPE_CONTROL_DEPTH_CACHE_FLUSH		(1<<0)
 #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
 
+/*
+ * Commands used only by the command parser
+ */
+#define MI_SET_PREDICATE        MI_INSTR(0x01, 0)
+#define MI_ARB_CHECK            MI_INSTR(0x05, 0)
+#define MI_RS_CONTROL           MI_INSTR(0x06, 0)
+#define MI_URB_ATOMIC_ALLOC     MI_INSTR(0x09, 0)
+#define MI_PREDICATE            MI_INSTR(0x0C, 0)
+#define MI_RS_CONTEXT           MI_INSTR(0x0F, 0)
+#define MI_TOPOLOGY_FILTER      MI_INSTR(0x0D, 0)
+#define MI_LOAD_SCAN_LINES_EXCL MI_INSTR(0x13, 0)
+#define MI_URB_CLEAR            MI_INSTR(0x19, 0)
+#define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
+#define MI_CLFLUSH              MI_INSTR(0x27, 0)
+#define MI_REPORT_PERF_COUNT    MI_INSTR(0x28, 0)
+#define   MI_REPORT_PERF_COUNT_GGTT (1<<0)
+#define MI_LOAD_REGISTER_MEM    MI_INSTR(0x29, 0)
+#define MI_LOAD_REGISTER_REG    MI_INSTR(0x2A, 0)
+#define MI_RS_STORE_DATA_IMM    MI_INSTR(0x2B, 0)
+#define MI_LOAD_URB_MEM         MI_INSTR(0x2C, 0)
+#define MI_STORE_URB_MEM        MI_INSTR(0x2D, 0)
+#define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0)
+
+#define PIPELINE_SELECT                ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16))
+#define GFX_OP_3DSTATE_VF_STATISTICS   ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16))
+#define MEDIA_VFE_STATE                ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<16))
+#define  MEDIA_VFE_STATE_MMIO_ACCESS_MASK (0x18)
+#define GPGPU_OBJECT                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
+#define GPGPU_WALKER                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
+#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16))
+#define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16))
+#define GFX_OP_3DSTATE_SO_DECL_LIST \
+	((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16))
+
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16))
+
+#define MFX_WAIT  ((0x3<<29)|(0x1<<27)|(0x0<<16))
+
+#define COLOR_BLT     ((0x2<<29)|(0x40<<22))
+#define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))
+
+/*
+ * Registers used only by the command parser
+ */
+#define BCS_SWCTRL 0x22200
+
+#define HS_INVOCATION_COUNT 0x2300
+#define DS_INVOCATION_COUNT 0x2308
+#define IA_VERTICES_COUNT   0x2310
+#define IA_PRIMITIVES_COUNT 0x2318
+#define VS_INVOCATION_COUNT 0x2320
+#define GS_INVOCATION_COUNT 0x2328
+#define GS_PRIMITIVES_COUNT 0x2330
+#define CL_INVOCATION_COUNT 0x2338
+#define CL_PRIMITIVES_COUNT 0x2340
+#define PS_INVOCATION_COUNT 0x2348
+#define PS_DEPTH_COUNT      0x2350
+
+/* There are the 4 64-bit counter registers, one for each stream output */
+#define GEN7_SO_NUM_PRIMS_WRITTEN(n) (0x5200 + (n) * 8)
+
+#define GEN7_SO_PRIM_STORAGE_NEEDED(n)  (0x5240 + (n) * 8)
+
+#define GEN7_3DPRIM_END_OFFSET          0x2420
+#define GEN7_3DPRIM_START_VERTEX        0x2430
+#define GEN7_3DPRIM_VERTEX_COUNT        0x2434
+#define GEN7_3DPRIM_INSTANCE_COUNT      0x2438
+#define GEN7_3DPRIM_START_INSTANCE      0x243C
+#define GEN7_3DPRIM_BASE_VERTEX         0x2440
+
+#define OACONTROL 0x2360
+
+#define _GEN7_PIPEA_DE_LOAD_SL	0x70068
+#define _GEN7_PIPEB_DE_LOAD_SL	0x71068
+#define GEN7_PIPE_DE_LOAD_SL(pipe) _PIPE(pipe, \
+					 _GEN7_PIPEA_DE_LOAD_SL, \
+					 _GEN7_PIPEB_DE_LOAD_SL)
 
 /*
  * Reset registers
@@ -748,6 +845,7 @@ enum punit_power_well {
 #define RING_INSTDONE(base)	((base)+0x6c)
 #define RING_INSTPS(base)	((base)+0x70)
 #define RING_DMA_FADD(base)	((base)+0x78)
+#define RING_DMA_FADD_UDW(base)	((base)+0x60) /* gen8+ */
 #define RING_INSTPM(base)	((base)+0xc0)
 #define RING_MI_MODE(base)	((base)+0x9c)
 #define INSTPS		0x02070 /* 965+ only */
@@ -827,6 +925,7 @@ enum punit_power_well {
 # define MI_FLUSH_ENABLE				(1 << 12)
 # define ASYNC_FLIP_PERF_DISABLE			(1 << 14)
 # define MODE_IDLE					(1 << 9)
+# define STOP_RING					(1 << 8)
 
 #define GEN6_GT_MODE	0x20d0
 #define GEN7_GT_MODE	0x7008
@@ -841,7 +940,7 @@ enum punit_power_well {
 #define GFX_MODE_GEN7	0x0229c
 #define RING_MODE_GEN7(ring)	((ring)->mmio_base+0x29c)
 #define   GFX_RUN_LIST_ENABLE		(1<<15)
-#define   GFX_TLB_INVALIDATE_ALWAYS	(1<<13)
+#define   GFX_TLB_INVALIDATE_EXPLICIT	(1<<13)
 #define   GFX_SURFACE_FAULT_ENABLE	(1<<12)
 #define   GFX_REPLAY_MODE		(1<<11)
 #define   GFX_PSMI_GRANULARITY		(1<<10)
@@ -972,6 +1071,7 @@ enum punit_power_well {
 #define   ECO_FLIP_DONE		(1<<0)
 
 #define CACHE_MODE_0_GEN7	0x7000 /* IVB+ */
+#define RC_OP_FLUSH_ENABLE (1<<0)
 #define   HIZ_RAW_STALL_OPT_DISABLE (1<<2)
 #define CACHE_MODE_1		0x7004 /* IVB+ */
 #define   PIXEL_SUBSPAN_COLLECT_OPT_DISABLE	(1<<6)
@@ -3257,6 +3357,7 @@ enum punit_power_well {
 #define   PIPECONF_INTERLACED_DBL_ILK		(4 << 21) /* ilk/snb only */
 #define   PIPECONF_PFIT_PF_INTERLACED_DBL_ILK	(5 << 21) /* ilk/snb only */
 #define   PIPECONF_INTERLACE_MODE_MASK		(7 << 21)
+#define   PIPECONF_EDP_RR_MODE_SWITCH		(1 << 20)
 #define   PIPECONF_CXSR_DOWNCLOCK	(1<<16)
 #define   PIPECONF_COLOR_RANGE_SELECT	(1 << 13)
 #define   PIPECONF_BPC_MASK	(0x7 << 5)
@@ -3534,9 +3635,9 @@ enum punit_power_well {
 #define   PIPE_PIXEL_MASK         0x00ffffff
 #define   PIPE_PIXEL_SHIFT        0
 /* GM45+ just has to be different */
-#define _PIPEA_FRMCOUNT_GM45	(dev_priv->info.display_mmio_offset + 0x70040)
-#define _PIPEA_FLIPCOUNT_GM45	(dev_priv->info.display_mmio_offset + 0x70044)
-#define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45)
+#define _PIPEA_FRMCOUNT_GM45	0x70040
+#define _PIPEA_FLIPCOUNT_GM45	0x70044
+#define PIPE_FRMCOUNT_GM45(pipe) _PIPE2(pipe, _PIPEA_FRMCOUNT_GM45)
 
 /* Cursor A & B regs */
 #define _CURACNTR		(dev_priv->info.display_mmio_offset + 0x70080)
@@ -4119,7 +4220,7 @@ enum punit_power_well {
 #define  GEN8_PIPE_SPRITE_FAULT		(1 << 9)
 #define  GEN8_PIPE_PRIMARY_FAULT	(1 << 8)
 #define  GEN8_PIPE_SPRITE_FLIP_DONE	(1 << 5)
-#define  GEN8_PIPE_FLIP_DONE		(1 << 4)
+#define  GEN8_PIPE_PRIMARY_FLIP_DONE	(1 << 4)
 #define  GEN8_PIPE_SCAN_LINE_EVENT	(1 << 2)
 #define  GEN8_PIPE_VSYNC		(1 << 1)
 #define  GEN8_PIPE_VBLANK		(1 << 0)
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 4867f4cc0938..fba9efd09e87 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -206,7 +206,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 	const struct lvds_dvo_timing *panel_dvo_timing;
 	const struct lvds_fp_timing *fp_timing;
 	struct drm_display_mode *panel_fixed_mode;
-	int i, downclock;
+	int i, downclock, drrs_mode;
 
 	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
@@ -218,6 +218,28 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 
 	panel_type = lvds_options->panel_type;
 
+	drrs_mode = (lvds_options->dps_panel_type_bits
+				>> (panel_type * 2)) & MODE_MASK;
+	/*
+	 * VBT has static DRRS = 0 and seamless DRRS = 2.
+	 * The below piece of code is required to adjust vbt.drrs_type
+	 * to match the enum drrs_support_type.
+	 */
+	switch (drrs_mode) {
+	case 0:
+		dev_priv->vbt.drrs_type = STATIC_DRRS_SUPPORT;
+		DRM_DEBUG_KMS("DRRS supported mode is static\n");
+		break;
+	case 2:
+		dev_priv->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT;
+		DRM_DEBUG_KMS("DRRS supported mode is seamless\n");
+		break;
+	default:
+		dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
+		DRM_DEBUG_KMS("DRRS not supported (VBT input)\n");
+		break;
+	}
+
 	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
 	if (!lvds_lfp_data)
 		return;
@@ -287,6 +309,9 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 	const struct bdb_lfp_backlight_data *backlight_data;
 	const struct bdb_lfp_backlight_data_entry *entry;
 
+	/* Err to enabling backlight if no backlight block. */
+	dev_priv->vbt.backlight.present = true;
+
 	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
 	if (!backlight_data)
 		return;
@@ -299,6 +324,13 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 
 	entry = &backlight_data->data[panel_type];
 
+	dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
+	if (!dev_priv->vbt.backlight.present) {
+		DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n",
+			      entry->type);
+		return;
+	}
+
 	dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
 	dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
 	DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
@@ -516,6 +548,16 @@ parse_driver_features(struct drm_i915_private *dev_priv,
 
 	if (driver->dual_frequency)
 		dev_priv->render_reclock_avail = true;
+
+	DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled);
+	/*
+	 * If DRRS is not supported, drrs_type has to be set to 0.
+	 * This is because, VBT is configured in such a way that
+	 * static DRRS is 0 and DRRS not supported is represented by
+	 * driver->drrs_enabled=false
+	 */
+	if (!driver->drrs_enabled)
+		dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
 }
 
 static void
@@ -594,19 +636,217 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 	}
 }
 
+static u8 *goto_next_sequence(u8 *data, int *size)
+{
+	u16 len;
+	int tmp = *size;
+
+	if (--tmp < 0)
+		return NULL;
+
+	/* goto first element */
+	data++;
+	while (1) {
+		switch (*data) {
+		case MIPI_SEQ_ELEM_SEND_PKT:
+			/*
+			 * skip by this element payload size
+			 * skip elem id, command flag and data type
+			 */
+			tmp -= 5;
+			if (tmp < 0)
+				return NULL;
+
+			data += 3;
+			len = *((u16 *)data);
+
+			tmp -= len;
+			if (tmp < 0)
+				return NULL;
+
+			/* skip by len */
+			data = data + 2 + len;
+			break;
+		case MIPI_SEQ_ELEM_DELAY:
+			/* skip by elem id, and delay is 4 bytes */
+			tmp -= 5;
+			if (tmp < 0)
+				return NULL;
+
+			data += 5;
+			break;
+		case MIPI_SEQ_ELEM_GPIO:
+			tmp -= 3;
+			if (tmp < 0)
+				return NULL;
+
+			data += 3;
+			break;
+		default:
+			DRM_ERROR("Unknown element\n");
+			return NULL;
+		}
+
+		/* end of sequence ? */
+		if (*data == 0)
+			break;
+	}
+
+	/* goto next sequence or end of block byte */
+	if (--tmp < 0)
+		return NULL;
+
+	data++;
+
+	/* update amount of data left for the sequence block to be parsed */
+	*size = tmp;
+	return data;
+}
+
 static void
 parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 {
-	struct bdb_mipi *mipi;
+	struct bdb_mipi_config *start;
+	struct bdb_mipi_sequence *sequence;
+	struct mipi_config *config;
+	struct mipi_pps_data *pps;
+	u8 *data, *seq_data;
+	int i, panel_id, seq_size;
+	u16 block_size;
+
+	/* Initialize this to undefined indicating no generic MIPI support */
+	dev_priv->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID;
+
+	/* Block #40 is already parsed and panel_fixed_mode is
+	 * stored in dev_priv->lfp_lvds_vbt_mode
+	 * resuse this when needed
+	 */
 
-	mipi = find_section(bdb, BDB_MIPI_CONFIG);
-	if (!mipi) {
-		DRM_DEBUG_KMS("No MIPI BDB found");
+	/* Parse #52 for panel index used from panel_type already
+	 * parsed
+	 */
+	start = find_section(bdb, BDB_MIPI_CONFIG);
+	if (!start) {
+		DRM_DEBUG_KMS("No MIPI config BDB found");
 		return;
 	}
 
-	/* XXX: add more info */
+	DRM_DEBUG_DRIVER("Found MIPI Config block, panel index = %d\n",
+								panel_type);
+
+	/*
+	 * get hold of the correct configuration block and pps data as per
+	 * the panel_type as index
+	 */
+	config = &start->config[panel_type];
+	pps = &start->pps[panel_type];
+
+	/* store as of now full data. Trim when we realise all is not needed */
+	dev_priv->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL);
+	if (!dev_priv->vbt.dsi.config)
+		return;
+
+	dev_priv->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL);
+	if (!dev_priv->vbt.dsi.pps) {
+		kfree(dev_priv->vbt.dsi.config);
+		return;
+	}
+
+	/* We have mandatory mipi config blocks. Initialize as generic panel */
 	dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
+
+	/* Check if we have sequence block as well */
+	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
+	if (!sequence) {
+		DRM_DEBUG_KMS("No MIPI Sequence found, parsing complete\n");
+		return;
+	}
+
+	DRM_DEBUG_DRIVER("Found MIPI sequence block\n");
+
+	block_size = get_blocksize(sequence);
+
+	/*
+	 * parse the sequence block for individual sequences
+	 */
+	dev_priv->vbt.dsi.seq_version = sequence->version;
+
+	seq_data = &sequence->data[0];
+
+	/*
+	 * sequence block is variable length and hence we need to parse and
+	 * get the sequence data for specific panel id
+	 */
+	for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) {
+		panel_id = *seq_data;
+		seq_size = *((u16 *) (seq_data + 1));
+		if (panel_id == panel_type)
+			break;
+
+		/* skip the sequence including seq header of 3 bytes */
+		seq_data = seq_data + 3 + seq_size;
+		if ((seq_data - &sequence->data[0]) > block_size) {
+			DRM_ERROR("Sequence start is beyond sequence block size, corrupted sequence block\n");
+			return;
+		}
+	}
+
+	if (i == MAX_MIPI_CONFIGURATIONS) {
+		DRM_ERROR("Sequence block detected but no valid configuration\n");
+		return;
+	}
+
+	/* check if found sequence is completely within the sequence block
+	 * just being paranoid */
+	if (seq_size > block_size) {
+		DRM_ERROR("Corrupted sequence/size, bailing out\n");
+		return;
+	}
+
+	/* skip the panel id(1 byte) and seq size(2 bytes) */
+	dev_priv->vbt.dsi.data = kmemdup(seq_data + 3, seq_size, GFP_KERNEL);
+	if (!dev_priv->vbt.dsi.data)
+		return;
+
+	/*
+	 * loop into the sequence data and split into multiple sequneces
+	 * There are only 5 types of sequences as of now
+	 */
+	data = dev_priv->vbt.dsi.data;
+	dev_priv->vbt.dsi.size = seq_size;
+
+	/* two consecutive 0x00 indicate end of all sequences */
+	while (1) {
+		int seq_id = *data;
+		if (MIPI_SEQ_MAX > seq_id && seq_id > MIPI_SEQ_UNDEFINED) {
+			dev_priv->vbt.dsi.sequence[seq_id] = data;
+			DRM_DEBUG_DRIVER("Found mipi sequence - %d\n", seq_id);
+		} else {
+			DRM_ERROR("undefined sequence\n");
+			goto err;
+		}
+
+		/* partial parsing to skip elements */
+		data = goto_next_sequence(data, &seq_size);
+
+		if (data == NULL) {
+			DRM_ERROR("Sequence elements going beyond block itself. Sequence block parsing failed\n");
+			goto err;
+		}
+
+		if (*data == 0)
+			break; /* end of sequence reached */
+	}
+
+	DRM_DEBUG_DRIVER("MIPI related vbt parsing complete\n");
+	return;
+err:
+	kfree(dev_priv->vbt.dsi.data);
+	dev_priv->vbt.dsi.data = NULL;
+
+	/* error during parsing so set all pointers to null
+	 * because of partial parsing */
+	memset(dev_priv->vbt.dsi.sequence, 0, MIPI_SEQ_MAX);
 }
 
 static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 83b7629e4367..6009debebaaf 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -282,6 +282,9 @@ struct bdb_general_definitions {
 	union child_device_config devices[0];
 } __packed;
 
+/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
+#define MODE_MASK		0x3
+
 struct bdb_lvds_options {
 	u8 panel_type;
 	u8 rsvd1;
@@ -294,6 +297,18 @@ struct bdb_lvds_options {
 	u8 lvds_edid:1;
 	u8 rsvd2:1;
 	u8 rsvd4;
+	/* LVDS Panel channel bits stored here */
+	u32 lvds_panel_channel_bits;
+	/* LVDS SSC (Spread Spectrum Clock) bits stored here. */
+	u16 ssc_bits;
+	u16 ssc_freq;
+	u16 ssc_ddt;
+	/* Panel color depth defined here */
+	u16 panel_color_depth;
+	/* LVDS panel type bits stored here */
+	u32 dps_panel_type_bits;
+	/* LVDS backlight control type bits stored here */
+	u32 blt_control_type_bits;
 } __packed;
 
 /* LFP pointer table contains entries to the struct below */
@@ -374,6 +389,9 @@ struct bdb_lvds_lfp_data {
 	struct bdb_lvds_lfp_data_entry data[16];
 } __packed;
 
+#define BDB_BACKLIGHT_TYPE_NONE	0
+#define BDB_BACKLIGHT_TYPE_PWM	2
+
 struct bdb_lfp_backlight_data_entry {
 	u8 type:2;
 	u8 active_low_pwm:1;
@@ -479,6 +497,20 @@ struct bdb_driver_features {
 
 	u8 hdmi_termination;
 	u8 custom_vbt_version;
+	/* Driver features data block */
+	u16 rmpm_enabled:1;
+	u16 s2ddt_enabled:1;
+	u16 dpst_enabled:1;
+	u16 bltclt_enabled:1;
+	u16 adb_enabled:1;
+	u16 drrs_enabled:1;
+	u16 grs_enabled:1;
+	u16 gpmt_enabled:1;
+	u16 tbt_enabled:1;
+	u16 psr_enabled:1;
+	u16 ips_enabled:1;
+	u16 reserved3:4;
+	u16 pc_feature_valid:1;
 } __packed;
 
 #define EDP_18BPP	0
@@ -867,4 +899,35 @@ struct bdb_mipi_sequence {
 	u8 data[0];
 };
 
+/* MIPI Sequnece Block definitions */
+enum mipi_seq {
+	MIPI_SEQ_UNDEFINED = 0,
+	MIPI_SEQ_ASSERT_RESET,
+	MIPI_SEQ_INIT_OTP,
+	MIPI_SEQ_DISPLAY_ON,
+	MIPI_SEQ_DISPLAY_OFF,
+	MIPI_SEQ_DEASSERT_RESET,
+	MIPI_SEQ_MAX
+};
+
+enum mipi_seq_element {
+	MIPI_SEQ_ELEM_UNDEFINED = 0,
+	MIPI_SEQ_ELEM_SEND_PKT,
+	MIPI_SEQ_ELEM_DELAY,
+	MIPI_SEQ_ELEM_GPIO,
+	MIPI_SEQ_ELEM_STATUS,
+	MIPI_SEQ_ELEM_MAX
+};
+
+enum mipi_gpio_pin_index {
+	MIPI_GPIO_UNDEFINED = 0,
+	MIPI_GPIO_PANEL_ENABLE,
+	MIPI_GPIO_BL_ENABLE,
+	MIPI_GPIO_PWM_ENABLE,
+	MIPI_GPIO_RESET_N,
+	MIPI_GPIO_PWR_DOWN_R,
+	MIPI_GPIO_STDBY_RST_N,
+	MIPI_GPIO_MAX
+};
+
 #endif /* _I830_BIOS_H_ */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dae976f51d83..420070b08ac4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -765,7 +765,7 @@ static void g4x_wait_for_vblank(struct drm_device *dev, int pipe)
 	frame = I915_READ(frame_reg);
 
 	if (wait_for(I915_READ_NOTRACE(frame_reg) != frame, 50))
-		DRM_DEBUG_KMS("vblank wait timed out\n");
+		WARN(1, "vblank wait timed out\n");
 }
 
 /**
@@ -1804,16 +1804,6 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
 
 	I915_WRITE(reg, val | PIPECONF_ENABLE);
 	POSTING_READ(reg);
-
-	/*
-	 * There's no guarantee the pipe will really start running now. It
-	 * depends on the Gen, the output type and the relative order between
-	 * pipe and plane enabling. Avoid waiting on HSW+ since it's not
-	 * necessary.
-	 * TODO: audit the previous gens.
-	 */
-	if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
-		intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
 /**
@@ -2166,15 +2156,6 @@ static int i9xx_update_primary_plane(struct drm_crtc *crtc,
 	u32 dspcntr;
 	u32 reg;
 
-	switch (plane) {
-	case 0:
-	case 1:
-		break;
-	default:
-		DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane));
-		return -EINVAL;
-	}
-
 	intel_fb = to_intel_framebuffer(fb);
 	obj = intel_fb->obj;
 
@@ -2267,16 +2248,6 @@ static int ironlake_update_primary_plane(struct drm_crtc *crtc,
 	u32 dspcntr;
 	u32 reg;
 
-	switch (plane) {
-	case 0:
-	case 1:
-	case 2:
-		break;
-	default:
-		DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane));
-		return -EINVAL;
-	}
-
 	intel_fb = to_intel_framebuffer(fb);
 	obj = intel_fb->obj;
 
@@ -3602,10 +3573,13 @@ void hsw_disable_ips(struct intel_crtc *crtc)
 		return;
 
 	assert_plane_enabled(dev_priv, crtc->plane);
-	if (IS_BROADWELL(crtc->base.dev)) {
+	if (IS_BROADWELL(dev)) {
 		mutex_lock(&dev_priv->rps.hw_lock);
 		WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
 		mutex_unlock(&dev_priv->rps.hw_lock);
+		/* wait for pcode to finish disabling IPS, which may take up to 42ms */
+		if (wait_for((I915_READ(IPS_CTL) & IPS_ENABLE) == 0, 42))
+			DRM_ERROR("Timed out waiting for IPS disable\n");
 	} else {
 		I915_WRITE(IPS_CTL, 0);
 		POSTING_READ(IPS_CTL);
@@ -3662,6 +3636,46 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
 		hsw_enable_ips(intel_crtc);
 }
 
+static void ilk_crtc_enable_planes(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+
+	intel_enable_primary_hw_plane(dev_priv, plane, pipe);
+	intel_enable_planes(crtc);
+	intel_crtc_update_cursor(crtc, true);
+
+	hsw_enable_ips(intel_crtc);
+
+	mutex_lock(&dev->struct_mutex);
+	intel_update_fbc(dev);
+	mutex_unlock(&dev->struct_mutex);
+}
+
+static void ilk_crtc_disable_planes(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+
+	intel_crtc_wait_for_pending_flips(crtc);
+	drm_vblank_off(dev, pipe);
+
+	if (dev_priv->fbc.plane == plane)
+		intel_disable_fbc(dev);
+
+	hsw_disable_ips(intel_crtc);
+
+	intel_crtc_update_cursor(crtc, false);
+	intel_disable_planes(crtc);
+	intel_disable_primary_hw_plane(dev_priv, plane, pipe);
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3669,7 +3683,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
 
 	WARN_ON(!crtc->enabled);
 
@@ -3705,23 +3718,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
-	intel_enable_primary_hw_plane(dev_priv, plane, pipe);
-	intel_enable_planes(crtc);
-	intel_crtc_update_cursor(crtc, true);
 
 	if (intel_crtc->config.has_pch_encoder)
 		ironlake_pch_enable(crtc);
 
-	mutex_lock(&dev->struct_mutex);
-	intel_update_fbc(dev);
-	mutex_unlock(&dev->struct_mutex);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 
 	if (HAS_PCH_CPT(dev))
 		cpt_verify_modeset(dev, intel_crtc->pipe);
 
+	ilk_crtc_enable_planes(crtc);
+
 	/*
 	 * There seems to be a race in PCH platform hw (at least on some
 	 * outputs) where an enabled pipe still completes any pageflip right
@@ -3739,47 +3747,6 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
 	return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
 }
 
-static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
-
-	intel_enable_primary_hw_plane(dev_priv, plane, pipe);
-	intel_enable_planes(crtc);
-	intel_crtc_update_cursor(crtc, true);
-
-	hsw_enable_ips(intel_crtc);
-
-	mutex_lock(&dev->struct_mutex);
-	intel_update_fbc(dev);
-	mutex_unlock(&dev->struct_mutex);
-}
-
-static void haswell_crtc_disable_planes(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
-
-	intel_crtc_wait_for_pending_flips(crtc);
-	drm_vblank_off(dev, pipe);
-
-	/* FBC must be disabled before disabling the plane on HSW. */
-	if (dev_priv->fbc.plane == plane)
-		intel_disable_fbc(dev);
-
-	hsw_disable_ips(intel_crtc);
-
-	intel_crtc_update_cursor(crtc, false);
-	intel_disable_planes(crtc);
-	intel_disable_primary_hw_plane(dev_priv, plane, pipe);
-}
-
 /*
  * This implements the workaround described in the "notes" section of the mode
  * set sequence documentation. When going from no pipes or single pipe to
@@ -3862,7 +3829,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	/* If we change the relative order between pipe/planes enabling, we need
 	 * to change the workaround. */
 	haswell_mode_set_planes_workaround(intel_crtc);
-	haswell_crtc_enable_planes(crtc);
+	ilk_crtc_enable_planes(crtc);
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@ -3887,26 +3854,16 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
 	u32 reg, temp;
 
-
 	if (!intel_crtc->active)
 		return;
 
+	ilk_crtc_disable_planes(crtc);
+
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->disable(encoder);
 
-	intel_crtc_wait_for_pending_flips(crtc);
-	drm_vblank_off(dev, pipe);
-
-	if (dev_priv->fbc.plane == plane)
-		intel_disable_fbc(dev);
-
-	intel_crtc_update_cursor(crtc, false);
-	intel_disable_planes(crtc);
-	intel_disable_primary_hw_plane(dev_priv, plane, pipe);
-
 	if (intel_crtc->config.has_pch_encoder)
 		intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
 
@@ -3965,7 +3922,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	if (!intel_crtc->active)
 		return;
 
-	haswell_crtc_disable_planes(crtc);
+	ilk_crtc_disable_planes(crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
 		intel_opregion_notify_encoder(encoder, false);
@@ -4207,6 +4164,9 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 val, cmd;
 
+	WARN_ON(valleyview_cur_cdclk(dev_priv) != dev_priv->vlv_cdclk_freq);
+	dev_priv->vlv_cdclk_freq = cdclk;
+
 	if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
 		cmd = 2;
 	else if (cdclk == 266)
@@ -4261,7 +4221,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
 	intel_i2c_reset(dev);
 }
 
-static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
+int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
 {
 	int cur_cdclk, vco;
 	int divider;
@@ -4282,10 +4242,6 @@ static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
 static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
 				 int max_pixclk)
 {
-	int cur_cdclk;
-
-	cur_cdclk = valleyview_cur_cdclk(dev_priv);
-
 	/*
 	 * Really only a few cases to deal with, as only 4 CDclks are supported:
 	 *   200MHz
@@ -4327,9 +4283,9 @@ static void valleyview_modeset_global_pipes(struct drm_device *dev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc;
 	int max_pixclk = intel_mode_max_pixclk(dev_priv);
-	int cur_cdclk = valleyview_cur_cdclk(dev_priv);
 
-	if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk)
+	if (valleyview_calc_cdclk(dev_priv, max_pixclk) ==
+	    dev_priv->vlv_cdclk_freq)
 		return;
 
 	/* disable/enable all currently active pipes while we change cdclk */
@@ -4343,10 +4299,9 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int max_pixclk = intel_mode_max_pixclk(dev_priv);
-	int cur_cdclk = valleyview_cur_cdclk(dev_priv);
 	int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
 
-	if (req_cdclk != cur_cdclk)
+	if (req_cdclk != dev_priv->vlv_cdclk_freq)
 		valleyview_set_cdclk(dev, req_cdclk);
 	modeset_update_crtc_power_domains(dev);
 }
@@ -4387,7 +4342,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
 	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
+
 	intel_enable_primary_hw_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	intel_crtc_update_cursor(crtc, true);
@@ -4426,7 +4383,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
 	intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
+
 	intel_enable_primary_hw_plane(dev_priv, plane, pipe);
 	intel_enable_planes(crtc);
 	/* The fixup needs to happen before cursor is enabled */
@@ -5245,9 +5204,6 @@ static void vlv_update_pll(struct intel_crtc *crtc)
 		<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
 	crtc->config.dpll_hw_state.dpll_md = dpll_md;
 
-	if (crtc->config.has_dp_encoder)
-		intel_dp_set_m_n(crtc);
-
 	mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -5325,9 +5281,6 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
 			<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
 		crtc->config.dpll_hw_state.dpll_md = dpll_md;
 	}
-
-	if (crtc->config.has_dp_encoder)
-		intel_dp_set_m_n(crtc);
 }
 
 static void i8xx_update_pll(struct intel_crtc *crtc,
@@ -5656,6 +5609,9 @@ skip_dpll:
 			dspcntr |= DISPPLANE_SEL_PIPE_B;
 	}
 
+	if (intel_crtc->config.has_dp_encoder)
+		intel_dp_set_m_n(intel_crtc);
+
 	intel_set_pipe_timings(intel_crtc);
 
 	/* pipesrc and dspsize control the size that is scaled from,
@@ -6880,8 +6836,6 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = dev_priv->dev;
 	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
 	struct intel_crtc *crtc;
-	unsigned long irqflags;
-	uint32_t val;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
 		WARN(crtc->active, "CRTC for pipe %c enabled\n",
@@ -6902,14 +6856,29 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 	     "Utility pin enabled\n");
 	WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n");
 
-	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	val = I915_READ(DEIMR);
-	WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,
-	     "Unexpected DEIMR bits enabled: 0x%x\n", val);
-	val = I915_READ(SDEIMR);
-	WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
-	     "Unexpected SDEIMR bits enabled: 0x%x\n", val);
-	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+	/*
+	 * In theory we can still leave IRQs enabled, as long as only the HPD
+	 * interrupts remain enabled. We used to check for that, but since it's
+	 * gen-specific and since we only disable LCPLL after we fully disable
+	 * the interrupts, the check below should be enough.
+	 */
+	WARN(!dev_priv->pm.irqs_disabled, "IRQs enabled\n");
+}
+
+static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	if (IS_HASWELL(dev)) {
+		mutex_lock(&dev_priv->rps.hw_lock);
+		if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
+					    val))
+			DRM_ERROR("Failed to disable D_COMP\n");
+		mutex_unlock(&dev_priv->rps.hw_lock);
+	} else {
+		I915_WRITE(D_COMP, val);
+	}
+	POSTING_READ(D_COMP);
 }
 
 /*
@@ -6949,11 +6918,7 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
 
 	val = I915_READ(D_COMP);
 	val |= D_COMP_COMP_DISABLE;
-	mutex_lock(&dev_priv->rps.hw_lock);
-	if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val))
-		DRM_ERROR("Failed to disable D_COMP\n");
-	mutex_unlock(&dev_priv->rps.hw_lock);
-	POSTING_READ(D_COMP);
+	hsw_write_dcomp(dev_priv, val);
 	ndelay(100);
 
 	if (wait_for((I915_READ(D_COMP) & D_COMP_RCOMP_IN_PROGRESS) == 0, 1))
@@ -7008,11 +6973,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 	val = I915_READ(D_COMP);
 	val |= D_COMP_COMP_FORCE;
 	val &= ~D_COMP_COMP_DISABLE;
-	mutex_lock(&dev_priv->rps.hw_lock);
-	if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val))
-		DRM_ERROR("Failed to enable D_COMP\n");
-	mutex_unlock(&dev_priv->rps.hw_lock);
-	POSTING_READ(D_COMP);
+	hsw_write_dcomp(dev_priv, val);
 
 	val = I915_READ(LCPLL_CTL);
 	val &= ~LCPLL_PLL_DISABLE;
@@ -7066,8 +7027,6 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = dev_priv->dev;
 	uint32_t val;
 
-	WARN_ON(!HAS_PC8(dev));
-
 	DRM_DEBUG_KMS("Enabling package C8+\n");
 
 	if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
@@ -7077,7 +7036,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 	}
 
 	lpt_disable_clkout_dp(dev);
-	hsw_runtime_pm_disable_interrupts(dev);
+	intel_runtime_pm_disable_interrupts(dev);
 	hsw_disable_lcpll(dev_priv, true, true);
 }
 
@@ -7086,12 +7045,10 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = dev_priv->dev;
 	uint32_t val;
 
-	WARN_ON(!HAS_PC8(dev));
-
 	DRM_DEBUG_KMS("Disabling package C8+\n");
 
 	hsw_restore_lcpll(dev_priv);
-	hsw_runtime_pm_restore_interrupts(dev);
+	intel_runtime_pm_restore_interrupts(dev);
 	lpt_init_pch_refclk(dev);
 
 	if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
@@ -7107,6 +7064,11 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
+static void snb_modeset_global_resources(struct drm_device *dev)
+{
+	modeset_update_crtc_power_domains(dev);
+}
+
 static void haswell_modeset_global_resources(struct drm_device *dev)
 {
 	modeset_update_crtc_power_domains(dev);
@@ -7374,7 +7336,6 @@ static void haswell_write_eld(struct drm_connector *connector,
 {
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	uint8_t *eld = connector->eld;
-	struct drm_device *dev = crtc->dev;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t eldv;
 	uint32_t i;
@@ -7387,17 +7348,14 @@ static void haswell_write_eld(struct drm_connector *connector,
 	int aud_config = HSW_AUD_CFG(pipe);
 	int aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD;
 
-
-	DRM_DEBUG_DRIVER("HDMI: Haswell Audio initialize....\n");
-
 	/* Audio output enable */
 	DRM_DEBUG_DRIVER("HDMI audio: enable codec\n");
 	tmp = I915_READ(aud_cntrl_st2);
 	tmp |= (AUDIO_OUTPUT_ENABLE_A << (pipe * 4));
 	I915_WRITE(aud_cntrl_st2, tmp);
+	POSTING_READ(aud_cntrl_st2);
 
-	/* Wait for 1 vertical blank */
-	intel_wait_for_vblank(dev, pipe);
+	assert_pipe_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
 
 	/* Set ELD valid state */
 	tmp = I915_READ(aud_cntrl_st2);
@@ -8836,8 +8794,16 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
 	}
 
 	len = 4;
-	if (ring->id == RCS)
+	if (ring->id == RCS) {
 		len += 6;
+		/*
+		 * On Gen 8, SRM is now taking an extra dword to accommodate
+		 * 48bits addresses, and we need a NOOP for the batch size to
+		 * stay even.
+		 */
+		if (IS_GEN8(dev))
+			len += 2;
+	}
 
 	/*
 	 * BSpec MI_DISPLAY_FLIP for IVB:
@@ -8872,10 +8838,18 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
 		intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
 					DERRMR_PIPEB_PRI_FLIP_DONE |
 					DERRMR_PIPEC_PRI_FLIP_DONE));
-		intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) |
-				MI_SRM_LRM_GLOBAL_GTT);
+		if (IS_GEN8(dev))
+			intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8(1) |
+					      MI_SRM_LRM_GLOBAL_GTT);
+		else
+			intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) |
+					      MI_SRM_LRM_GLOBAL_GTT);
 		intel_ring_emit(ring, DERRMR);
 		intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
+		if (IS_GEN8(dev)) {
+			intel_ring_emit(ring, 0);
+			intel_ring_emit(ring, MI_NOOP);
+		}
 	}
 
 	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
@@ -10567,16 +10541,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
 	drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
 
-	if (IS_GEN2(dev)) {
-		intel_crtc->max_cursor_width = GEN2_CURSOR_WIDTH;
-		intel_crtc->max_cursor_height = GEN2_CURSOR_HEIGHT;
-	} else {
-		intel_crtc->max_cursor_width = CURSOR_WIDTH;
-		intel_crtc->max_cursor_height = CURSOR_HEIGHT;
-	}
-	dev->mode_config.cursor_width = intel_crtc->max_cursor_width;
-	dev->mode_config.cursor_height = intel_crtc->max_cursor_height;
-
 	drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
 	for (i = 0; i < 256; i++) {
 		intel_crtc->lut_r[i] = i;
@@ -11077,6 +11041,8 @@ static void intel_init_display(struct drm_device *dev)
 		} else if (IS_GEN6(dev)) {
 			dev_priv->display.fdi_link_train = gen6_fdi_link_train;
 			dev_priv->display.write_eld = ironlake_write_eld;
+			dev_priv->display.modeset_global_resources =
+				snb_modeset_global_resources;
 		} else if (IS_IVYBRIDGE(dev)) {
 			/* FIXME: detect B0+ stepping and use auto training */
 			dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
@@ -11327,6 +11293,15 @@ void intel_modeset_init(struct drm_device *dev)
 		dev->mode_config.max_width = 8192;
 		dev->mode_config.max_height = 8192;
 	}
+
+	if (IS_GEN2(dev)) {
+		dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH;
+		dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT;
+	} else {
+		dev->mode_config.cursor_width = MAX_CURSOR_WIDTH;
+		dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT;
+	}
+
 	dev->mode_config.fb_base = dev_priv->gtt.mappable_base;
 
 	DRM_DEBUG_KMS("%d display pipe%s available.\n",
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a0dad1a2f819..b50b170dc2e8 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
 	}
 }
 
+static void
+intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum transcoder transcoder = crtc->config.cpu_transcoder;
+
+	I915_WRITE(PIPE_DATA_M2(transcoder),
+		TU_SIZE(m_n->tu) | m_n->gmch_m);
+	I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
+	I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
+	I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
+}
+
 bool
 intel_dp_compute_config(struct intel_encoder *encoder,
 			struct intel_crtc_config *pipe_config)
@@ -841,6 +855,14 @@ found:
 			       pipe_config->port_clock,
 			       &pipe_config->dp_m_n);
 
+	if (intel_connector->panel.downclock_mode != NULL &&
+		intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
+			intel_link_compute_m_n(bpp, lane_count,
+				intel_connector->panel.downclock_mode->clock,
+				pipe_config->port_clock,
+				&pipe_config->dp_m2_n2);
+	}
+
 	intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
 
 	return true;
@@ -1043,7 +1065,10 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
 	u32 pp;
 	u32 pp_stat_reg, pp_ctrl_reg;
 	bool need_to_disable = !intel_dp->want_panel_vdd;
@@ -1056,7 +1081,8 @@ static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
 	if (edp_have_panel_vdd(intel_dp))
 		return need_to_disable;
 
-	intel_runtime_pm_get(dev_priv);
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_get(dev_priv, power_domain);
 
 	DRM_DEBUG_KMS("Turning eDP VDD on\n");
 
@@ -1103,6 +1129,11 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
 	if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
+		struct intel_digital_port *intel_dig_port =
+						dp_to_dig_port(intel_dp);
+		struct intel_encoder *intel_encoder = &intel_dig_port->base;
+		enum intel_display_power_domain power_domain;
+
 		DRM_DEBUG_KMS("Turning eDP VDD off\n");
 
 		pp = ironlake_get_pp_control(intel_dp);
@@ -1121,7 +1152,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 		if ((pp & POWER_TARGET_ON) == 0)
 			intel_dp->last_power_cycle = jiffies;
 
-		intel_runtime_pm_put(dev_priv);
+		power_domain = intel_display_port_power_domain(intel_encoder);
+		intel_display_power_put(dev_priv, power_domain);
 	}
 }
 
@@ -1205,8 +1237,11 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
 {
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
 	u32 pp;
 	u32 pp_ctrl_reg;
 
@@ -1236,7 +1271,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 	wait_panel_off(intel_dp);
 
 	/* We got a reference when we enabled the VDD. */
-	intel_runtime_pm_put(dev_priv);
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_put(dev_priv, power_domain);
 }
 
 void intel_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1777,17 +1813,23 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 		intel_dp_link_down(intel_dp);
 }
 
-static void intel_post_disable_dp(struct intel_encoder *encoder)
+static void g4x_post_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	enum port port = dp_to_dig_port(intel_dp)->port;
-	struct drm_device *dev = encoder->base.dev;
 
-	if (port == PORT_A || IS_VALLEYVIEW(dev)) {
-		intel_dp_link_down(intel_dp);
-		if (!IS_VALLEYVIEW(dev))
-			ironlake_edp_pll_off(intel_dp);
-	}
+	if (port != PORT_A)
+		return;
+
+	intel_dp_link_down(intel_dp);
+	ironlake_edp_pll_off(intel_dp);
+}
+
+static void vlv_post_disable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+	intel_dp_link_down(intel_dp);
 }
 
 static void intel_enable_dp(struct intel_encoder *encoder)
@@ -3612,6 +3654,130 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 		      I915_READ(pp_div_reg));
 }
 
+void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+	struct intel_crtc_config *config = NULL;
+	struct intel_crtc *intel_crtc = NULL;
+	struct intel_connector *intel_connector = dev_priv->drrs.connector;
+	u32 reg, val;
+	enum edp_drrs_refresh_rate_type index = DRRS_HIGH_RR;
+
+	if (refresh_rate <= 0) {
+		DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n");
+		return;
+	}
+
+	if (intel_connector == NULL) {
+		DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
+		return;
+	}
+
+	if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
+		DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
+		return;
+	}
+
+	encoder = intel_attached_encoder(&intel_connector->base);
+	intel_dp = enc_to_intel_dp(&encoder->base);
+	intel_crtc = encoder->new_crtc;
+
+	if (!intel_crtc) {
+		DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
+		return;
+	}
+
+	config = &intel_crtc->config;
+
+	if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
+		DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
+		return;
+	}
+
+	if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
+		index = DRRS_LOW_RR;
+
+	if (index == intel_dp->drrs_state.refresh_rate_type) {
+		DRM_DEBUG_KMS(
+			"DRRS requested for previously set RR...ignoring\n");
+		return;
+	}
+
+	if (!intel_crtc->active) {
+		DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n");
+		return;
+	}
+
+	if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) {
+		reg = PIPECONF(intel_crtc->config.cpu_transcoder);
+		val = I915_READ(reg);
+		if (index > DRRS_HIGH_RR) {
+			val |= PIPECONF_EDP_RR_MODE_SWITCH;
+			intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
+		} else {
+			val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
+		}
+		I915_WRITE(reg, val);
+	}
+
+	/*
+	 * mutex taken to ensure that there is no race between differnt
+	 * drrs calls trying to update refresh rate. This scenario may occur
+	 * in future when idleness detection based DRRS in kernel and
+	 * possible calls from user space to set differnt RR are made.
+	 */
+
+	mutex_lock(&intel_dp->drrs_state.mutex);
+
+	intel_dp->drrs_state.refresh_rate_type = index;
+
+	mutex_unlock(&intel_dp->drrs_state.mutex);
+
+	DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
+}
+
+static struct drm_display_mode *
+intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
+			struct intel_connector *intel_connector,
+			struct drm_display_mode *fixed_mode)
+{
+	struct drm_connector *connector = &intel_connector->base;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *downclock_mode = NULL;
+
+	if (INTEL_INFO(dev)->gen <= 6) {
+		DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
+		return NULL;
+	}
+
+	if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
+		DRM_INFO("VBT doesn't support DRRS\n");
+		return NULL;
+	}
+
+	downclock_mode = intel_find_panel_downclock
+					(dev, fixed_mode, connector);
+
+	if (!downclock_mode) {
+		DRM_INFO("DRRS not supported\n");
+		return NULL;
+	}
+
+	dev_priv->drrs.connector = intel_connector;
+
+	mutex_init(&intel_dp->drrs_state.mutex);
+
+	intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
+
+	intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
+	DRM_INFO("seamless DRRS supported for eDP panel.\n");
+	return downclock_mode;
+}
+
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 				     struct intel_connector *intel_connector,
 				     struct edp_power_seq *power_seq)
@@ -3621,10 +3787,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_display_mode *fixed_mode = NULL;
+	struct drm_display_mode *downclock_mode = NULL;
 	bool has_dpcd;
 	struct drm_display_mode *scan;
 	struct edid *edid;
 
+	intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
+
 	if (!is_edp(intel_dp))
 		return true;
 
@@ -3667,6 +3836,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	list_for_each_entry(scan, &connector->probed_modes, head) {
 		if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
 			fixed_mode = drm_mode_duplicate(dev, scan);
+			downclock_mode = intel_dp_drrs_init(
+						intel_dig_port,
+						intel_connector, fixed_mode);
 			break;
 		}
 	}
@@ -3680,7 +3852,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 	mutex_unlock(&dev->mode_config.mutex);
 
-	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
 	intel_panel_setup_backlight(connector);
 
 	return true;
@@ -3831,16 +4003,17 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	intel_encoder->compute_config = intel_dp_compute_config;
 	intel_encoder->mode_set = intel_dp_mode_set;
 	intel_encoder->disable = intel_disable_dp;
-	intel_encoder->post_disable = intel_post_disable_dp;
 	intel_encoder->get_hw_state = intel_dp_get_hw_state;
 	intel_encoder->get_config = intel_dp_get_config;
 	if (IS_VALLEYVIEW(dev)) {
 		intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
 		intel_encoder->pre_enable = vlv_pre_enable_dp;
 		intel_encoder->enable = vlv_enable_dp;
+		intel_encoder->post_disable = vlv_post_disable_dp;
 	} else {
 		intel_encoder->pre_enable = g4x_pre_enable_dp;
 		intel_encoder->enable = g4x_enable_dp;
+		intel_encoder->post_disable = g4x_post_disable_dp;
 	}
 
 	intel_dig_port->port = port;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0542de982260..c551472b892e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -81,8 +81,8 @@
 /* Maximum cursor sizes */
 #define GEN2_CURSOR_WIDTH 64
 #define GEN2_CURSOR_HEIGHT 64
-#define CURSOR_WIDTH 256
-#define CURSOR_HEIGHT 256
+#define MAX_CURSOR_WIDTH 256
+#define MAX_CURSOR_HEIGHT 256
 
 #define INTEL_I2C_BUS_DVO 1
 #define INTEL_I2C_BUS_SDVO 2
@@ -305,6 +305,9 @@ struct intel_crtc_config {
 	int pipe_bpp;
 	struct intel_link_m_n dp_m_n;
 
+	/* m2_n2 for eDP downclock */
+	struct intel_link_m_n dp_m2_n2;
+
 	/*
 	 * Frequence the dpll for the port should run at. Differs from the
 	 * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
@@ -342,6 +345,9 @@ struct intel_pipe_wm {
 	struct intel_wm_level wm[5];
 	uint32_t linetime;
 	bool fbc_wm_enabled;
+	bool pipe_enabled;
+	bool sprites_enabled;
+	bool sprites_scaled;
 };
 
 struct intel_crtc {
@@ -373,7 +379,6 @@ struct intel_crtc {
 	uint32_t cursor_addr;
 	int16_t cursor_x, cursor_y;
 	int16_t cursor_width, cursor_height;
-	int16_t max_cursor_width, max_cursor_height;
 	bool cursor_visible;
 
 	struct intel_plane_config plane_config;
@@ -483,6 +488,17 @@ struct intel_hdmi {
 
 #define DP_MAX_DOWNSTREAM_PORTS		0x10
 
+/**
+ * HIGH_RR is the highest eDP panel refresh rate read from EDID
+ * LOW_RR is the lowest eDP panel refresh rate found from EDID
+ * parsing for same resolution.
+ */
+enum edp_drrs_refresh_rate_type {
+	DRRS_HIGH_RR,
+	DRRS_LOW_RR,
+	DRRS_MAX_RR, /* RR count */
+};
+
 struct intel_dp {
 	uint32_t output_reg;
 	uint32_t aux_ch_ctl_reg;
@@ -521,6 +537,12 @@ struct intel_dp {
 				     bool has_aux_irq,
 				     int send_bytes,
 				     uint32_t aux_clock_divider);
+	struct {
+		enum drrs_support_type type;
+		enum edp_drrs_refresh_rate_type refresh_rate_type;
+		struct mutex mutex;
+	} drrs_state;
+
 };
 
 struct intel_digital_port {
@@ -628,8 +650,8 @@ void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void hsw_runtime_pm_disable_interrupts(struct drm_device *dev);
-void hsw_runtime_pm_restore_interrupts(struct drm_device *dev);
+void intel_runtime_pm_disable_interrupts(struct drm_device *dev);
+void intel_runtime_pm_restore_interrupts(struct drm_device *dev);
 
 
 /* intel_crt.c */
@@ -665,6 +687,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
 const char *intel_output_name(int output);
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
 int intel_pch_rawclk(struct drm_device *dev);
+int valleyview_cur_cdclk(struct drm_i915_private *dev_priv);
 void intel_mark_busy(struct drm_device *dev);
 void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
 			struct intel_ring_buffer *ring);
@@ -773,7 +796,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
 void intel_edp_psr_enable(struct intel_dp *intel_dp);
 void intel_edp_psr_disable(struct intel_dp *intel_dp);
 void intel_edp_psr_update(struct drm_device *dev);
-
+void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
 
 /* intel_dsi.c */
 bool intel_dsi_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 33656647f8bc..4e271c768fd0 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -110,6 +110,15 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
 
 	DRM_DEBUG_KMS("\n");
 
+	mutex_lock(&dev_priv->dpio_lock);
+	/* program rcomp for compliance, reduce from 50 ohms to 45 ohms
+	 * needed everytime after power gate */
+	vlv_flisdsi_write(dev_priv, 0x04, 0x0004);
+	mutex_unlock(&dev_priv->dpio_lock);
+
+	/* bandgap reset is needed after everytime we do power gate */
+	band_gap_reset(dev_priv);
+
 	val = I915_READ(MIPI_PORT_CTRL(pipe));
 	I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD);
 	usleep_range(1000, 1500);
@@ -122,21 +131,6 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
 	I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
 	usleep_range(2000, 2500);
 }
-static void intel_dsi_pre_enable(struct intel_encoder *encoder)
-{
-	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-
-	DRM_DEBUG_KMS("\n");
-
-	if (intel_dsi->dev.dev_ops->panel_reset)
-		intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);
-
-	/* put device in ready state */
-	intel_dsi_device_ready(encoder);
-
-	if (intel_dsi->dev.dev_ops->send_otp_cmds)
-		intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
-}
 
 static void intel_dsi_enable(struct intel_encoder *encoder)
 {
@@ -153,18 +147,63 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
 		I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4);
 	else {
 		msleep(20); /* XXX */
-		dpi_send_cmd(intel_dsi, TURN_ON);
+		dpi_send_cmd(intel_dsi, TURN_ON, DPI_LP_MODE_EN);
 		msleep(100);
 
+		if (intel_dsi->dev.dev_ops->enable)
+			intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+
 		/* assert ip_tg_enable signal */
 		temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
 		temp = temp | intel_dsi->port_bits;
 		I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE);
 		POSTING_READ(MIPI_PORT_CTRL(pipe));
 	}
+}
+
+static void intel_dsi_pre_enable(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	u32 tmp;
+
+	DRM_DEBUG_KMS("\n");
 
-	if (intel_dsi->dev.dev_ops->enable)
-		intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+	/* Disable DPOunit clock gating, can stall pipe
+	 * and we need DPLL REFA always enabled */
+	tmp = I915_READ(DPLL(pipe));
+	tmp |= DPLL_REFA_CLK_ENABLE_VLV;
+	I915_WRITE(DPLL(pipe), tmp);
+
+	tmp = I915_READ(DSPCLK_GATE_D);
+	tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
+	I915_WRITE(DSPCLK_GATE_D, tmp);
+
+	/* put device in ready state */
+	intel_dsi_device_ready(encoder);
+
+	if (intel_dsi->dev.dev_ops->panel_reset)
+		intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);
+
+	if (intel_dsi->dev.dev_ops->send_otp_cmds)
+		intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
+
+	/* Enable port in pre-enable phase itself because as per hw team
+	 * recommendation, port should be enabled befor plane & pipe */
+	intel_dsi_enable(encoder);
+}
+
+static void intel_dsi_enable_nop(struct intel_encoder *encoder)
+{
+	DRM_DEBUG_KMS("\n");
+
+	/* for DSI port enable has to be done before pipe
+	 * and plane enable, so port enable is done in
+	 * pre_enable phase itself unlike other encoders
+	 */
 }
 
 static void intel_dsi_disable(struct intel_encoder *encoder)
@@ -179,7 +218,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
 	DRM_DEBUG_KMS("\n");
 
 	if (is_vid_mode(intel_dsi)) {
-		dpi_send_cmd(intel_dsi, SHUTDOWN);
+		/* Send Shutdown command to the panel in LP mode */
+		dpi_send_cmd(intel_dsi, SHUTDOWN, DPI_LP_MODE_EN);
 		msleep(10);
 
 		/* de-assert ip_tg_enable signal */
@@ -190,6 +230,23 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
 		msleep(2);
 	}
 
+	/* Panel commands can be sent when clock is in LP11 */
+	I915_WRITE(MIPI_DEVICE_READY(pipe), 0x0);
+
+	temp = I915_READ(MIPI_CTRL(pipe));
+	temp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
+	I915_WRITE(MIPI_CTRL(pipe), temp |
+			intel_dsi->escape_clk_div <<
+			ESCAPE_CLOCK_DIVIDER_SHIFT);
+
+	I915_WRITE(MIPI_EOT_DISABLE(pipe), CLOCKSTOP);
+
+	temp = I915_READ(MIPI_DSI_FUNC_PRG(pipe));
+	temp &= ~VID_MODE_FORMAT_MASK;
+	I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), temp);
+
+	I915_WRITE(MIPI_DEVICE_READY(pipe), 0x1);
+
 	/* if disable packets are sent before sending shutdown packet then in
 	 * some next enable sequence send turn on packet error is observed */
 	if (intel_dsi->dev.dev_ops->disable)
@@ -227,14 +284,21 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
 
 	vlv_disable_dsi_pll(encoder);
 }
+
 static void intel_dsi_post_disable(struct intel_encoder *encoder)
 {
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	u32 val;
 
 	DRM_DEBUG_KMS("\n");
 
 	intel_dsi_clear_device_ready(encoder);
 
+	val = I915_READ(DSPCLK_GATE_D);
+	val &= ~DPOUNIT_CLOCK_GATE_DISABLE;
+	I915_WRITE(DSPCLK_GATE_D, val);
+
 	if (intel_dsi->dev.dev_ops->disable_panel_power)
 		intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev);
 }
@@ -379,9 +443,6 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
 
 	DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
 
-	/* XXX: Location of the call */
-	band_gap_reset(dev_priv);
-
 	/* escape clock divider, 20MHz, shared for A and C. device ready must be
 	 * off when doing this! txclkesc? */
 	tmp = I915_READ(MIPI_CTRL(0));
@@ -452,10 +513,17 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
 	/* dphy stuff */
 
 	/* in terms of low power clock */
-	I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(ESCAPE_CLOCK_DIVIDER_1, 100));
+	I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(intel_dsi->escape_clk_div, 100));
+
+	val = 0;
+	if (intel_dsi->eotp_pkt == 0)
+		val |= EOT_DISABLE;
+
+	if (intel_dsi->clock_stop)
+		val |= CLOCKSTOP;
 
 	/* recovery disables */
-	I915_WRITE(MIPI_EOT_DISABLE(pipe), intel_dsi->eot_disable);
+	I915_WRITE(MIPI_EOT_DISABLE(pipe), val);
 
 	/* in terms of txbyteclkhs. actual high to low switch +
 	 * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK.
@@ -484,9 +552,14 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
 		   intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);
 
 	if (is_vid_mode(intel_dsi))
+		/* Some panels might have resolution which is not a multiple of
+		 * 64 like 1366 x 768. Enable RANDOM resolution support for such
+		 * panels by default */
 		I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
 				intel_dsi->video_frmt_cfg_bits |
-				intel_dsi->video_mode_format);
+				intel_dsi->video_mode_format |
+				IP_TG_CONFIG |
+				RANDOM_DPI_DISPLAY_RESOLUTION);
 }
 
 static enum drm_connector_status
@@ -594,7 +667,7 @@ bool intel_dsi_init(struct drm_device *dev)
 	intel_encoder->compute_config = intel_dsi_compute_config;
 	intel_encoder->pre_pll_enable = intel_dsi_pre_pll_enable;
 	intel_encoder->pre_enable = intel_dsi_pre_enable;
-	intel_encoder->enable = intel_dsi_enable;
+	intel_encoder->enable = intel_dsi_enable_nop;
 	intel_encoder->mode_set = intel_dsi_mode_set;
 	intel_encoder->disable = intel_dsi_disable;
 	intel_encoder->post_disable = intel_dsi_post_disable;
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index b4a27cec882f..550714c7860e 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -95,8 +95,10 @@ struct intel_dsi {
 	u32 video_mode_format;
 
 	/* eot for MIPI_EOT_DISABLE register */
-	u32 eot_disable;
+	u8 eotp_pkt;
+	u8 clock_stop;
 
+	u8 escape_clk_div;
 	u32 port_bits;
 	u32 bw_timer;
 	u32 dphy_reg;
diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.c b/drivers/gpu/drm/i915/intel_dsi_cmd.c
index 7c40f981d2c7..3eeb21b9fddf 100644
--- a/drivers/gpu/drm/i915/intel_dsi_cmd.c
+++ b/drivers/gpu/drm/i915/intel_dsi_cmd.c
@@ -389,7 +389,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel,
  *
  * XXX: commands with data in MIPI_DPI_DATA?
  */
-int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd)
+int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs)
 {
 	struct drm_encoder *encoder = &intel_dsi->base.base;
 	struct drm_device *dev = encoder->dev;
@@ -399,7 +399,7 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd)
 	u32 mask;
 
 	/* XXX: pipe, hs */
-	if (intel_dsi->hs)
+	if (hs)
 		cmd &= ~DPI_LP_MODE;
 	else
 		cmd |= DPI_LP_MODE;
diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.h b/drivers/gpu/drm/i915/intel_dsi_cmd.h
index 54c8a234a2e0..9a18cbfa5460 100644
--- a/drivers/gpu/drm/i915/intel_dsi_cmd.h
+++ b/drivers/gpu/drm/i915/intel_dsi_cmd.h
@@ -33,6 +33,9 @@
 #include "intel_drv.h"
 #include "intel_dsi.h"
 
+#define DPI_LP_MODE_EN	false
+#define DPI_HS_MODE_EN	true
+
 void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable);
 
 int dsi_vc_dcs_write(struct intel_dsi *intel_dsi, int channel,
@@ -47,7 +50,7 @@ int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd,
 int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel,
 			u8 *reqdata, int reqlen, u8 *buf, int buflen);
 
-int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd);
+int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs);
 
 /* XXX: questionable write helpers */
 static inline int dsi_vc_dcs_write_0(struct intel_dsi *intel_dsi,
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b0413e190625..b606162cc17c 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -557,10 +557,12 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
 			       struct drm_display_mode *adjusted_mode)
 {
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
 	u32 val = I915_READ(reg);
+	u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
 
 	assert_hdmi_port_disabled(intel_hdmi);
 
@@ -576,9 +578,19 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
 		return;
 	}
 
+	if (port != (val & VIDEO_DIP_PORT_MASK)) {
+		if (val & VIDEO_DIP_ENABLE) {
+			val &= ~VIDEO_DIP_ENABLE;
+			I915_WRITE(reg, val);
+			POSTING_READ(reg);
+		}
+		val &= ~VIDEO_DIP_PORT_MASK;
+		val |= port;
+	}
+
 	val |= VIDEO_DIP_ENABLE;
-	val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
-		 VIDEO_DIP_ENABLE_GCP);
+	val &= ~(VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_ENABLE_VENDOR |
+		 VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP);
 
 	I915_WRITE(reg, val);
 	POSTING_READ(reg);
@@ -638,8 +650,8 @@ static void intel_hdmi_mode_set(struct intel_encoder *encoder)
 	else
 		hdmi_val |= SDVO_COLOR_FORMAT_8bpc;
 
-	/* Required on CPT */
-	if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
+	if (intel_hdmi->has_hdmi_sink &&
+	    (HAS_PCH_CPT(dev) || IS_VALLEYVIEW(dev)))
 		hdmi_val |= HDMI_MODE_SELECT_HDMI;
 
 	if (intel_hdmi->has_audio) {
@@ -657,8 +669,6 @@ static void intel_hdmi_mode_set(struct intel_encoder *encoder)
 
 	I915_WRITE(intel_hdmi->hdmi_reg, hdmi_val);
 	POSTING_READ(intel_hdmi->hdmi_reg);
-
-	intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
 }
 
 static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
@@ -821,11 +831,11 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
 	}
 }
 
-static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
+static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit)
 {
 	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
 
-	if (!hdmi->has_hdmi_sink || IS_G4X(dev))
+	if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev))
 		return 165000;
 	else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8)
 		return 300000;
@@ -837,7 +847,8 @@ static enum drm_mode_status
 intel_hdmi_mode_valid(struct drm_connector *connector,
 		      struct drm_display_mode *mode)
 {
-	if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector)))
+	if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector),
+					       true))
 		return MODE_CLOCK_HIGH;
 	if (mode->clock < 20000)
 		return MODE_CLOCK_LOW;
@@ -879,7 +890,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 	int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2;
-	int portclock_limit = hdmi_portclock_limit(intel_hdmi);
+	int portclock_limit = hdmi_portclock_limit(intel_hdmi, false);
 	int desired_bpp;
 
 	if (intel_hdmi->color_range_auto) {
@@ -1103,13 +1114,26 @@ done:
 	return 0;
 }
 
+static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
+{
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	struct drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
+
+	intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
+}
+
 static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
 {
 	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct intel_hdmi *intel_hdmi = &dport->hdmi;
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc =
 		to_intel_crtc(encoder->base.crtc);
+	struct drm_display_mode *adjusted_mode =
+		&intel_crtc->config.adjusted_mode;
 	enum dpio_channel port = vlv_dport_to_channel(dport);
 	int pipe = intel_crtc->pipe;
 	u32 val;
@@ -1143,6 +1167,8 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
 	mutex_unlock(&dev_priv->dpio_lock);
 
+	intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
+
 	intel_enable_hdmi(encoder);
 
 	vlv_wait_port_ready(dev_priv, dport);
@@ -1338,6 +1364,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 		intel_encoder->enable = vlv_enable_hdmi;
 		intel_encoder->post_disable = vlv_hdmi_post_disable;
 	} else {
+		intel_encoder->pre_enable = intel_hdmi_pre_enable;
 		intel_encoder->enable = intel_enable_hdmi;
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index f1ecf916474a..1b1541dfb440 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -111,13 +111,6 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
 
 	pipe_config->adjusted_mode.flags |= flags;
 
-	/* gen2/3 store dither state in pfit control, needs to match */
-	if (INTEL_INFO(dev)->gen < 4) {
-		tmp = I915_READ(PFIT_CONTROL);
-
-		pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
-	}
-
 	dotclock = pipe_config->port_clock;
 
 	if (HAS_PCH_SPLIT(dev_priv->dev))
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index cb058408c70e..44ad415e3706 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -308,16 +308,16 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
 		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
 				 PFIT_FILTER_FUZZY);
 
+	/* Make sure pre-965 set dither correctly for 18bpp panels. */
+	if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
+		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+
 out:
 	if ((pfit_control & PFIT_ENABLE) == 0) {
 		pfit_control = 0;
 		pfit_pgm_ratios = 0;
 	}
 
-	/* Make sure pre-965 set dither correctly for 18bpp panels. */
-	if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
-		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-
 	pipe_config->gmch_pfit.control = pfit_control;
 	pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
 	pipe_config->gmch_pfit.lvds_border_bits = border;
@@ -1065,6 +1065,11 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
 	unsigned long flags;
 	int ret;
 
+	if (!dev_priv->vbt.backlight.present) {
+		DRM_DEBUG_KMS("native backlight control not available per VBT\n");
+		return 0;
+	}
+
 	/* set level and max in panel struct */
 	spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 	ret = dev_priv->display.setup_backlight(intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 5874716774a7..75c1c766b507 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1545,6 +1545,16 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
 
 	DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
 
+	if (IS_I915GM(dev) && enabled) {
+		struct intel_framebuffer *fb;
+
+		fb = to_intel_framebuffer(enabled->primary->fb);
+
+		/* self-refresh seems busted with untiled */
+		if (fb->obj->tiling_mode == I915_TILING_NONE)
+			enabled = NULL;
+	}
+
 	/*
 	 * Overlay gets an aggressive default since video jitter is bad.
 	 */
@@ -1821,6 +1831,40 @@ static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
 		return 512;
 }
 
+static unsigned int ilk_plane_wm_reg_max(const struct drm_device *dev,
+					 int level, bool is_sprite)
+{
+	if (INTEL_INFO(dev)->gen >= 8)
+		/* BDW primary/sprite plane watermarks */
+		return level == 0 ? 255 : 2047;
+	else if (INTEL_INFO(dev)->gen >= 7)
+		/* IVB/HSW primary/sprite plane watermarks */
+		return level == 0 ? 127 : 1023;
+	else if (!is_sprite)
+		/* ILK/SNB primary plane watermarks */
+		return level == 0 ? 127 : 511;
+	else
+		/* ILK/SNB sprite plane watermarks */
+		return level == 0 ? 63 : 255;
+}
+
+static unsigned int ilk_cursor_wm_reg_max(const struct drm_device *dev,
+					  int level)
+{
+	if (INTEL_INFO(dev)->gen >= 7)
+		return level == 0 ? 63 : 255;
+	else
+		return level == 0 ? 31 : 63;
+}
+
+static unsigned int ilk_fbc_wm_reg_max(const struct drm_device *dev)
+{
+	if (INTEL_INFO(dev)->gen >= 8)
+		return 31;
+	else
+		return 15;
+}
+
 /* Calculate the maximum primary/sprite plane watermark */
 static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 				     int level,
@@ -1829,7 +1873,6 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 				     bool is_sprite)
 {
 	unsigned int fifo_size = ilk_display_fifo_size(dev);
-	unsigned int max;
 
 	/* if sprites aren't enabled, sprites get nothing */
 	if (is_sprite && !config->sprites_enabled)
@@ -1860,19 +1903,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 	}
 
 	/* clamp to max that the registers can hold */
-	if (INTEL_INFO(dev)->gen >= 8)
-		max = level == 0 ? 255 : 2047;
-	else if (INTEL_INFO(dev)->gen >= 7)
-		/* IVB/HSW primary/sprite plane watermarks */
-		max = level == 0 ? 127 : 1023;
-	else if (!is_sprite)
-		/* ILK/SNB primary plane watermarks */
-		max = level == 0 ? 127 : 511;
-	else
-		/* ILK/SNB sprite plane watermarks */
-		max = level == 0 ? 63 : 255;
-
-	return min(fifo_size, max);
+	return min(fifo_size, ilk_plane_wm_reg_max(dev, level, is_sprite));
 }
 
 /* Calculate the maximum cursor plane watermark */
@@ -1885,20 +1916,7 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
 		return 64;
 
 	/* otherwise just report max that registers can hold */
-	if (INTEL_INFO(dev)->gen >= 7)
-		return level == 0 ? 63 : 255;
-	else
-		return level == 0 ? 31 : 63;
-}
-
-/* Calculate the maximum FBC watermark */
-static unsigned int ilk_fbc_wm_max(const struct drm_device *dev)
-{
-	/* max that registers can hold */
-	if (INTEL_INFO(dev)->gen >= 8)
-		return 31;
-	else
-		return 15;
+	return ilk_cursor_wm_reg_max(dev, level);
 }
 
 static void ilk_compute_wm_maximums(const struct drm_device *dev,
@@ -1910,7 +1928,7 @@ static void ilk_compute_wm_maximums(const struct drm_device *dev,
 	max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
 	max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
 	max->cur = ilk_cursor_wm_max(dev, level, config);
-	max->fbc = ilk_fbc_wm_max(dev);
+	max->fbc = ilk_fbc_wm_reg_max(dev);
 }
 
 static bool ilk_validate_wm_level(int level,
@@ -2105,38 +2123,52 @@ static void ilk_setup_wm_latency(struct drm_device *dev)
 }
 
 static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
-				      struct ilk_pipe_wm_parameters *p,
-				      struct intel_wm_config *config)
+				      struct ilk_pipe_wm_parameters *p)
 {
 	struct drm_device *dev = crtc->dev;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum pipe pipe = intel_crtc->pipe;
 	struct drm_plane *plane;
 
-	p->active = intel_crtc_active(crtc);
-	if (p->active) {
-		p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
-		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
-		p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
-		p->cur.bytes_per_pixel = 4;
-		p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
-		p->cur.horiz_pixels = intel_crtc->cursor_width;
-		/* TODO: for now, assume primary and cursor planes are always enabled. */
-		p->pri.enabled = true;
-		p->cur.enabled = true;
-	}
+	if (!intel_crtc_active(crtc))
+		return;
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		config->num_pipes_active += intel_crtc_active(crtc);
+	p->active = true;
+	p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
+	p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
+	p->pri.bytes_per_pixel = crtc->primary->fb->bits_per_pixel / 8;
+	p->cur.bytes_per_pixel = 4;
+	p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
+	p->cur.horiz_pixels = intel_crtc->cursor_width;
+	/* TODO: for now, assume primary and cursor planes are always enabled. */
+	p->pri.enabled = true;
+	p->cur.enabled = true;
 
 	drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
 		struct intel_plane *intel_plane = to_intel_plane(plane);
 
-		if (intel_plane->pipe == pipe)
+		if (intel_plane->pipe == pipe) {
 			p->spr = intel_plane->wm;
+			break;
+		}
+	}
+}
+
+static void ilk_compute_wm_config(struct drm_device *dev,
+				  struct intel_wm_config *config)
+{
+	struct intel_crtc *intel_crtc;
+
+	/* Compute the currently _active_ config */
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		const struct intel_pipe_wm *wm = &intel_crtc->wm.active;
+
+		if (!wm->pipe_enabled)
+			continue;
 
-		config->sprites_enabled |= intel_plane->wm.enabled;
-		config->sprites_scaled |= intel_plane->wm.scaled;
+		config->sprites_enabled |= wm->sprites_enabled;
+		config->sprites_scaled |= wm->sprites_scaled;
+		config->num_pipes_active++;
 	}
 }
 
@@ -2159,6 +2191,10 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	/* LP0 watermarks always use 1/2 DDB partitioning */
 	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
 
+	pipe_wm->pipe_enabled = params->active;
+	pipe_wm->sprites_enabled = params->spr.enabled;
+	pipe_wm->sprites_scaled = params->spr.scaled;
+
 	/* ILK/SNB: LP2+ watermarks only w/o sprites */
 	if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled)
 		max_level = 1;
@@ -2188,8 +2224,11 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 	const struct intel_crtc *intel_crtc;
 
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
-		const struct intel_wm_level *wm =
-			&intel_crtc->wm.active.wm[level];
+		const struct intel_pipe_wm *active = &intel_crtc->wm.active;
+		const struct intel_wm_level *wm = &active->wm[level];
+
+		if (!active->pipe_enabled)
+			continue;
 
 		if (!wm->enable)
 			return;
@@ -2548,7 +2587,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
 	struct intel_wm_config config = {};
 
-	ilk_compute_wm_parameters(crtc, &params, &config);
+	ilk_compute_wm_parameters(crtc, &params);
 
 	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
 
@@ -2557,6 +2596,8 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 
 	intel_crtc->wm.active = pipe_wm;
 
+	ilk_compute_wm_config(dev, &config);
+
 	ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
 	ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
 
@@ -2623,7 +2664,9 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
-	if (intel_crtc_active(crtc)) {
+	active->pipe_enabled = intel_crtc_active(crtc);
+
+	if (active->pipe_enabled) {
 		u32 tmp = hw->wm_pipe[pipe];
 
 		/*
@@ -2664,8 +2707,10 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
 	hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
 
 	hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
-	hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
-	hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
+	if (INTEL_INFO(dev)->gen >= 7) {
+		hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
+		hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
+	}
 
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
@@ -3041,7 +3086,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 	if (val != dev_priv->rps.cur_freq) {
 		gen6_set_rps_thresholds(dev_priv, val);
 
-		if (IS_HASWELL(dev))
+		if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 			I915_WRITE(GEN6_RPNSWREQ,
 				   HSW_FREQUENCY(val));
 		else
@@ -3242,6 +3287,27 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev)
 	spin_unlock_irq(&dev_priv->irq_lock);
 }
 
+static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_cap)
+{
+	/* All of these values are in units of 50MHz */
+	dev_priv->rps.cur_freq		= 0;
+	/* static values from HW: RP0 < RPe < RP1 < RPn (min_freq) */
+	dev_priv->rps.rp1_freq		= (rp_state_cap >>  8) & 0xff;
+	dev_priv->rps.rp0_freq		= (rp_state_cap >>  0) & 0xff;
+	dev_priv->rps.min_freq		= (rp_state_cap >> 16) & 0xff;
+	/* XXX: only BYT has a special efficient freq */
+	dev_priv->rps.efficient_freq	= dev_priv->rps.rp1_freq;
+	/* hw_max = RP0 until we check for overclocking */
+	dev_priv->rps.max_freq		= dev_priv->rps.rp0_freq;
+
+	/* Preserve min/max settings in case of re-init */
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
+
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
+}
+
 static void gen8_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3260,6 +3326,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* 2b: Program RC6 thresholds.*/
 	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
@@ -3279,8 +3346,10 @@ static void gen8_enable_rps(struct drm_device *dev)
 				    rc6_mask);
 
 	/* 4 Program defaults and thresholds for RPS*/
-	I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
-	I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(12)); /* Request 600 MHz */
+	I915_WRITE(GEN6_RPNSWREQ,
+		   HSW_FREQUENCY(dev_priv->rps.rp1_freq));
+	I915_WRITE(GEN6_RC_VIDEO_FREQ,
+		   HSW_FREQUENCY(dev_priv->rps.rp1_freq));
 	/* NB: Docs say 1s, and 1000000 - which aren't equivalent */
 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */
 
@@ -3346,23 +3415,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
-	/* All of these values are in units of 50MHz */
-	dev_priv->rps.cur_freq		= 0;
-	/* static values from HW: RP0 < RPe < RP1 < RPn (min_freq) */
-	dev_priv->rps.rp1_freq		= (rp_state_cap >>  8) & 0xff;
-	dev_priv->rps.rp0_freq		= (rp_state_cap >>  0) & 0xff;
-	dev_priv->rps.min_freq		= (rp_state_cap >> 16) & 0xff;
-	/* XXX: only BYT has a special efficient freq */
-	dev_priv->rps.efficient_freq	= dev_priv->rps.rp1_freq;
-	/* hw_max = RP0 until we check for overclocking */
-	dev_priv->rps.max_freq		= dev_priv->rps.rp0_freq;
-
-	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_freq_softlimit == 0)
-		dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
-
-	if (dev_priv->rps.min_freq_softlimit == 0)
-		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
+	parse_rp_state_cap(dev_priv, rp_state_cap);
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -4616,6 +4669,9 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(CACHE_MODE_0,
 		   _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
 
+	/* WaDisable_RenderCache_OperationalFlush:ilk */
+	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
+
 	g4x_disable_trickle_feed(dev);
 
 	ibx_init_clock_gating(dev);
@@ -4691,6 +4747,9 @@ static void gen6_init_clock_gating(struct drm_device *dev)
 		I915_WRITE(GEN6_GT_MODE,
 			   _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE));
 
+	/* WaDisable_RenderCache_OperationalFlush:snb */
+	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
+
 	/*
 	 * BSpec recoomends 8x4 when MSAA is used,
 	 * however in practice 16x4 seems fastest.
@@ -4930,6 +4989,9 @@ static void haswell_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(GEN7_FF_THREAD_MODE,
 		   I915_READ(GEN7_FF_THREAD_MODE) & ~GEN7_FF_VS_REF_CNT_FFME);
 
+	/* WaDisable_RenderCache_OperationalFlush:hsw */
+	I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
+
 	/* enable HiZ Raw Stall Optimization */
 	I915_WRITE(CACHE_MODE_0_GEN7,
 		   _MASKED_BIT_DISABLE(HIZ_RAW_STALL_OPT_DISABLE));
@@ -4982,6 +5044,9 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 		I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
 			   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
 
+	/* WaDisable_RenderCache_OperationalFlush:ivb */
+	I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
+
 	/* Apply the WaDisableRHWOOptimizationForRenderHang:ivb workaround. */
 	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
 		   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
@@ -5076,6 +5141,10 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 	}
 	DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
+	dev_priv->vlv_cdclk_freq = valleyview_cur_cdclk(dev_priv);
+	DRM_DEBUG_DRIVER("Current CD clock rate: %d MHz",
+			 dev_priv->vlv_cdclk_freq);
+
 	I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
 
 	/* WaDisableEarlyCull:vlv */
@@ -5093,6 +5162,9 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 		   _MASKED_BIT_ENABLE(GEN7_MAX_PS_THREAD_DEP |
 				      GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
 
+	/* WaDisable_RenderCache_OperationalFlush:vlv */
+	I915_WRITE(CACHE_MODE_0_GEN7, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
+
 	/* WaForceL3Serialization:vlv */
 	I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
 		   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
@@ -5162,6 +5234,9 @@ static void g4x_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(CACHE_MODE_0,
 		   _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
 
+	/* WaDisable_RenderCache_OperationalFlush:g4x */
+	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
+
 	g4x_disable_trickle_feed(dev);
 }
 
@@ -5176,6 +5251,9 @@ static void crestline_init_clock_gating(struct drm_device *dev)
 	I915_WRITE16(DEUC, 0);
 	I915_WRITE(MI_ARB_STATE,
 		   _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
+
+	/* WaDisable_RenderCache_OperationalFlush:gen4 */
+	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
 static void broadwater_init_clock_gating(struct drm_device *dev)
@@ -5190,6 +5268,9 @@ static void broadwater_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(RENCLK_GATE_D2, 0);
 	I915_WRITE(MI_ARB_STATE,
 		   _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
+
+	/* WaDisable_RenderCache_OperationalFlush:gen4 */
+	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
 static void gen3_init_clock_gating(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6bc68bdcf433..eb3dd26b94de 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -41,12 +41,16 @@ static inline int ring_space(struct intel_ring_buffer *ring)
 	return space;
 }
 
-void __intel_ring_advance(struct intel_ring_buffer *ring)
+static bool intel_ring_stopped(struct intel_ring_buffer *ring)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring);
+}
 
+void __intel_ring_advance(struct intel_ring_buffer *ring)
+{
 	ring->tail &= ring->size - 1;
-	if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring))
+	if (intel_ring_stopped(ring))
 		return;
 	ring->write_tail(ring, ring->tail);
 }
@@ -437,32 +441,41 @@ static void ring_setup_phys_status_page(struct intel_ring_buffer *ring)
 	I915_WRITE(HWS_PGA, addr);
 }
 
-static int init_ring_common(struct intel_ring_buffer *ring)
+static bool stop_ring(struct intel_ring_buffer *ring)
 {
-	struct drm_device *dev = ring->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj = ring->obj;
-	int ret = 0;
-	u32 head;
+	struct drm_i915_private *dev_priv = to_i915(ring->dev);
 
-	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+	if (!IS_GEN2(ring->dev)) {
+		I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
+		if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
+			DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
+			return false;
+		}
+	}
 
-	/* Stop the ring if it's running. */
 	I915_WRITE_CTL(ring, 0);
 	I915_WRITE_HEAD(ring, 0);
 	ring->write_tail(ring, 0);
-	if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000))
-		DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
 
-	if (I915_NEED_GFX_HWS(dev))
-		intel_ring_setup_status_page(ring);
-	else
-		ring_setup_phys_status_page(ring);
+	if (!IS_GEN2(ring->dev)) {
+		(void)I915_READ_CTL(ring);
+		I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
+	}
 
-	head = I915_READ_HEAD(ring) & HEAD_ADDR;
+	return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0;
+}
 
-	/* G45 ring initialization fails to reset head to zero */
-	if (head != 0) {
+static int init_ring_common(struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj = ring->obj;
+	int ret = 0;
+
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+
+	if (!stop_ring(ring)) {
+		/* G45 ring initialization often fails to reset head to zero */
 		DRM_DEBUG_KMS("%s head not reset to zero "
 			      "ctl %08x head %08x tail %08x start %08x\n",
 			      ring->name,
@@ -471,9 +484,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
 			      I915_READ_TAIL(ring),
 			      I915_READ_START(ring));
 
-		I915_WRITE_HEAD(ring, 0);
-
-		if (I915_READ_HEAD(ring) & HEAD_ADDR) {
+		if (!stop_ring(ring)) {
 			DRM_ERROR("failed to set %s head to zero "
 				  "ctl %08x head %08x tail %08x start %08x\n",
 				  ring->name,
@@ -481,9 +492,16 @@ static int init_ring_common(struct intel_ring_buffer *ring)
 				  I915_READ_HEAD(ring),
 				  I915_READ_TAIL(ring),
 				  I915_READ_START(ring));
+			ret = -EIO;
+			goto out;
 		}
 	}
 
+	if (I915_NEED_GFX_HWS(dev))
+		intel_ring_setup_status_page(ring);
+	else
+		ring_setup_phys_status_page(ring);
+
 	/* Initialize the ring. This must happen _after_ we've cleared the ring
 	 * registers with the above sequence (the readback of the HEAD registers
 	 * also enforces ordering), otherwise the hw might lose the new ring
@@ -587,13 +605,15 @@ static int init_render_ring(struct intel_ring_buffer *ring)
 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
 
 	/* Required for the hardware to program scanline values for waiting */
+	/* WaEnableFlushTlbInvalidationMode:snb */
 	if (INTEL_INFO(dev)->gen == 6)
 		I915_WRITE(GFX_MODE,
-			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS));
+			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT));
 
+	/* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */
 	if (IS_GEN7(dev))
 		I915_WRITE(GFX_MODE_GEN7,
-			   _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
+			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) |
 			   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
 
 	if (INTEL_INFO(dev)->gen >= 5) {
@@ -610,13 +630,6 @@ static int init_render_ring(struct intel_ring_buffer *ring)
 		 */
 		I915_WRITE(CACHE_MODE_0,
 			   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
-
-		/* This is not explicitly set for GEN6, so read the register.
-		 * see intel_ring_mi_set_context() for why we care.
-		 * TODO: consider explicitly setting the bit for GEN5
-		 */
-		ring->itlb_before_ctx_switch =
-			!!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS);
 	}
 
 	if (INTEL_INFO(dev)->gen >= 6)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 270a6a973438..413cdc74ed53 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -34,6 +34,7 @@ struct  intel_hw_status_page {
 #define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val)
 
 #define I915_READ_MODE(ring) I915_READ(RING_MI_MODE((ring)->mmio_base))
+#define I915_WRITE_MODE(ring, val) I915_WRITE(RING_MI_MODE((ring)->mmio_base), val)
 
 enum intel_ring_hangcheck_action {
 	HANGCHECK_IDLE = 0,
@@ -152,10 +153,6 @@ struct  intel_ring_buffer {
 
 	wait_queue_head_t irq_queue;
 
-	/**
-	 * Do an explicit TLB flush before MI_SET_CONTEXT
-	 */
-	bool itlb_before_ctx_switch;
 	struct i915_hw_context *default_context;
 	struct i915_hw_context *last_context;
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d27155adf5db..46be00d66df3 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2424,8 +2424,8 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 	if (ret < 0)
 		goto err1;
 
-	ret = sysfs_create_link(&encoder->ddc.dev.kobj,
-				&drm_connector->kdev->kobj,
+	ret = sysfs_create_link(&drm_connector->kdev->kobj,
+				&encoder->ddc.dev.kobj,
 				encoder->ddc.dev.kobj.name);
 	if (ret < 0)
 		goto err2;
diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c
index 0954f132726e..b1a5514e695a 100644
--- a/drivers/gpu/drm/i915/intel_sideband.c
+++ b/drivers/gpu/drm/i915/intel_sideband.c
@@ -182,6 +182,14 @@ u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg)
 
 	vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
 			DPIO_OPCODE_REG_READ, reg, &val);
+
+	/*
+	 * FIXME: There might be some registers where all 1's is a valid value,
+	 * so ideally we should check the register offset instead...
+	 */
+	WARN(val == 0xffffffff, "DPIO read pipe %c reg 0x%x == 0x%x\n",
+	     pipe_name(pipe), reg, val);
+
 	return val;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index f729dc71d5be..2a72bab106d5 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -253,8 +253,7 @@ static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
 
 }
 
-void vlv_force_wake_get(struct drm_i915_private *dev_priv,
-						int fw_engine)
+static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
 {
 	unsigned long irqflags;
 
@@ -273,8 +272,7 @@ void vlv_force_wake_get(struct drm_i915_private *dev_priv,
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-void vlv_force_wake_put(struct drm_i915_private *dev_priv,
-						int fw_engine)
+static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 {
 	unsigned long irqflags;
 
@@ -486,6 +484,17 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv)
 #define NEEDS_FORCE_WAKE(dev_priv, reg) \
 	 ((reg) < 0x40000 && (reg) != FORCEWAKE)
 
+#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
+	(((reg) >= 0x2000 && (reg) < 0x4000) ||\
+	((reg) >= 0x5000 && (reg) < 0x8000) ||\
+	((reg) >= 0xB000 && (reg) < 0x12000) ||\
+	((reg) >= 0x2E000 && (reg) < 0x30000))
+
+#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
+	(((reg) >= 0x12000 && (reg) < 0x14000) ||\
+	((reg) >= 0x22000 && (reg) < 0x24000) ||\
+	((reg) >= 0x30000 && (reg) < 0x40000))
+
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)
 {
@@ -852,12 +861,15 @@ void intel_uncore_fini(struct drm_device *dev)
 	intel_uncore_forcewake_reset(dev, false);
 }
 
+#define GEN_RANGE(l, h) GENMASK(h, l)
+
 static const struct register_whitelist {
 	uint64_t offset;
 	uint32_t size;
-	uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
+	/* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
+	uint32_t gen_bitmask;
 } whitelist[] = {
-	{ RING_TIMESTAMP(RENDER_RING_BASE), 8, 0x1F0 },
+	{ RING_TIMESTAMP(RENDER_RING_BASE), 8, GEN_RANGE(4, 8) },
 };
 
 int i915_reg_read_ioctl(struct drm_device *dev,
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 7af9d0b5dea1..762f15d6ed88 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -657,6 +657,14 @@ config HID_SUNPLUS
 	---help---
 	Support for Sunplus wireless desktop.
 
+config HID_RMI
+	tristate "Synaptics RMI4 device support"
+	depends on HID
+	---help---
+	Support for Synaptics RMI4 touchpads.
+	Say Y here if you have a Synaptics RMI4 touchpads over i2c-hid or usbhid
+	and want support for its special functionalities.
+
 config HID_GREENASIA
 	tristate "GreenAsia (Product ID 0x12) game controller support"
 	depends on HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index fc712dde02a4..a6fa6baf368e 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -97,6 +97,7 @@ obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o hid-roccat-common.o \
 	hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
 	hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
 	hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-ryos.o hid-roccat-savu.o
+obj-$(CONFIG_HID_RMI)		+= hid-rmi.o
 obj-$(CONFIG_HID_SAITEK)	+= hid-saitek.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9e8064205bc7..f05255d92de7 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1882,6 +1882,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
new file mode 100644
index 000000000000..7da9509894de
--- /dev/null
+++ b/drivers/hid/hid-rmi.c
@@ -0,0 +1,888 @@
+/*
+ *  Copyright (c) 2013 Andrew Duggan <aduggan@synaptics.com>
+ *  Copyright (c) 2013 Synaptics Incorporated
+ *  Copyright (c) 2014 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ *  Copyright (c) 2014 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include "hid-ids.h"
+
+#define RMI_MOUSE_REPORT_ID		0x01 /* Mouse emulation Report */
+#define RMI_WRITE_REPORT_ID		0x09 /* Output Report */
+#define RMI_READ_ADDR_REPORT_ID		0x0a /* Output Report */
+#define RMI_READ_DATA_REPORT_ID		0x0b /* Input Report */
+#define RMI_ATTN_REPORT_ID		0x0c /* Input Report */
+#define RMI_SET_RMI_MODE_REPORT_ID	0x0f /* Feature Report */
+
+/* flags */
+#define RMI_READ_REQUEST_PENDING	BIT(0)
+#define RMI_READ_DATA_PENDING		BIT(1)
+#define RMI_STARTED			BIT(2)
+
+enum rmi_mode_type {
+	RMI_MODE_OFF			= 0,
+	RMI_MODE_ATTN_REPORTS		= 1,
+	RMI_MODE_NO_PACKED_ATTN_REPORTS	= 2,
+};
+
+struct rmi_function {
+	unsigned page;			/* page of the function */
+	u16 query_base_addr;		/* base address for queries */
+	u16 command_base_addr;		/* base address for commands */
+	u16 control_base_addr;		/* base address for controls */
+	u16 data_base_addr;		/* base address for datas */
+	unsigned int interrupt_base;	/* cross-function interrupt number
+					 * (uniq in the device)*/
+	unsigned int interrupt_count;	/* number of interrupts */
+	unsigned int report_size;	/* size of a report */
+	unsigned long irq_mask;		/* mask of the interrupts
+					 * (to be applied against ATTN IRQ) */
+};
+
+/**
+ * struct rmi_data - stores information for hid communication
+ *
+ * @page_mutex: Locks current page to avoid changing pages in unexpected ways.
+ * @page: Keeps track of the current virtual page
+ *
+ * @wait: Used for waiting for read data
+ *
+ * @writeReport: output buffer when writing RMI registers
+ * @readReport: input buffer when reading RMI registers
+ *
+ * @input_report_size: size of an input report (advertised by HID)
+ * @output_report_size: size of an output report (advertised by HID)
+ *
+ * @flags: flags for the current device (started, reading, etc...)
+ *
+ * @f11: placeholder of internal RMI function F11 description
+ * @f30: placeholder of internal RMI function F30 description
+ *
+ * @max_fingers: maximum finger count reported by the device
+ * @max_x: maximum x value reported by the device
+ * @max_y: maximum y value reported by the device
+ *
+ * @gpio_led_count: count of GPIOs + LEDs reported by F30
+ * @button_count: actual physical buttons count
+ * @button_mask: button mask used to decode GPIO ATTN reports
+ * @button_state_mask: pull state of the buttons
+ *
+ * @input: pointer to the kernel input device
+ *
+ * @reset_work: worker which will be called in case of a mouse report
+ * @hdev: pointer to the struct hid_device
+ */
+struct rmi_data {
+	struct mutex page_mutex;
+	int page;
+
+	wait_queue_head_t wait;
+
+	u8 *writeReport;
+	u8 *readReport;
+
+	int input_report_size;
+	int output_report_size;
+
+	unsigned long flags;
+
+	struct rmi_function f11;
+	struct rmi_function f30;
+
+	unsigned int max_fingers;
+	unsigned int max_x;
+	unsigned int max_y;
+	unsigned int x_size_mm;
+	unsigned int y_size_mm;
+
+	unsigned int gpio_led_count;
+	unsigned int button_count;
+	unsigned long button_mask;
+	unsigned long button_state_mask;
+
+	struct input_dev *input;
+
+	struct work_struct reset_work;
+	struct hid_device *hdev;
+};
+
+#define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
+
+static int rmi_write_report(struct hid_device *hdev, u8 *report, int len);
+
+/**
+ * rmi_set_page - Set RMI page
+ * @hdev: The pointer to the hid_device struct
+ * @page: The new page address.
+ *
+ * RMI devices have 16-bit addressing, but some of the physical
+ * implementations (like SMBus) only have 8-bit addressing. So RMI implements
+ * a page address at 0xff of every page so we can reliable page addresses
+ * every 256 registers.
+ *
+ * The page_mutex lock must be held when this function is entered.
+ *
+ * Returns zero on success, non-zero on failure.
+ */
+static int rmi_set_page(struct hid_device *hdev, u8 page)
+{
+	struct rmi_data *data = hid_get_drvdata(hdev);
+	int retval;
+
+	data->writeReport[0] = RMI_WRITE_REPORT_ID;
+	data->writeReport[1] = 1;
+	data->writeReport[2] = 0xFF;
+	data->writeReport[4] = page;
+
+	retval = rmi_write_report(hdev, data->writeReport,
+			data->output_report_size);
+	if (retval != data->output_report_size) {
+		dev_err(&hdev->dev,
+			"%s: set page failed: %d.", __func__, retval);
+		return retval;
+	}
+
+	data->page = page;
+	return 0;
+}
+
+static int rmi_set_mode(struct hid_device *hdev, u8 mode)
+{
+	int ret;
+	u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode};
+
+	ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, txbuf,
+			sizeof(txbuf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+	if (ret < 0) {
+		dev_err(&hdev->dev, "unable to set rmi mode to %d (%d)\n", mode,
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rmi_write_report(struct hid_device *hdev, u8 *report, int len)
+{
+	int ret;
+
+	ret = hid_hw_output_report(hdev, (void *)report, len);
+	if (ret < 0) {
+		dev_err(&hdev->dev, "failed to write hid report (%d)\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int rmi_read_block(struct hid_device *hdev, u16 addr, void *buf,
+		const int len)
+{
+	struct rmi_data *data = hid_get_drvdata(hdev);
+	int ret;
+	int bytes_read;
+	int bytes_needed;
+	int retries;
+	int read_input_count;
+
+	mutex_lock(&data->page_mutex);
+
+	if (RMI_PAGE(addr) != data->page) {
+		ret = rmi_set_page(hdev, RMI_PAGE(addr));
+		if (ret < 0)
+			goto exit;
+	}
+
+	for (retries = 5; retries > 0; retries--) {
+		data->writeReport[0] = RMI_READ_ADDR_REPORT_ID;
+		data->writeReport[1] = 0; /* old 1 byte read count */
+		data->writeReport[2] = addr & 0xFF;
+		data->writeReport[3] = (addr >> 8) & 0xFF;
+		data->writeReport[4] = len  & 0xFF;
+		data->writeReport[5] = (len >> 8) & 0xFF;
+
+		set_bit(RMI_READ_REQUEST_PENDING, &data->flags);
+
+		ret = rmi_write_report(hdev, data->writeReport,
+						data->output_report_size);
+		if (ret != data->output_report_size) {
+			clear_bit(RMI_READ_REQUEST_PENDING, &data->flags);
+			dev_err(&hdev->dev,
+				"failed to write request output report (%d)\n",
+				ret);
+			goto exit;
+		}
+
+		bytes_read = 0;
+		bytes_needed = len;
+		while (bytes_read < len) {
+			if (!wait_event_timeout(data->wait,
+				test_bit(RMI_READ_DATA_PENDING, &data->flags),
+					msecs_to_jiffies(1000))) {
+				hid_warn(hdev, "%s: timeout elapsed\n",
+					 __func__);
+				ret = -EAGAIN;
+				break;
+			}
+
+			read_input_count = data->readReport[1];
+			memcpy(buf + bytes_read, &data->readReport[2],
+				read_input_count < bytes_needed ?
+					read_input_count : bytes_needed);
+
+			bytes_read += read_input_count;
+			bytes_needed -= read_input_count;
+			clear_bit(RMI_READ_DATA_PENDING, &data->flags);
+		}
+
+		if (ret >= 0) {
+			ret = 0;
+			break;
+		}
+	}
+
+exit:
+	clear_bit(RMI_READ_REQUEST_PENDING, &data->flags);
+	mutex_unlock(&data->page_mutex);
+	return ret;
+}
+
+static inline int rmi_read(struct hid_device *hdev, u16 addr, void *buf)
+{
+	return rmi_read_block(hdev, addr, buf, 1);
+}
+
+static void rmi_f11_process_touch(struct rmi_data *hdata, int slot,
+		u8 finger_state, u8 *touch_data)
+{
+	int x, y, wx, wy;
+	int wide, major, minor;
+	int z;
+
+	input_mt_slot(hdata->input, slot);
+	input_mt_report_slot_state(hdata->input, MT_TOOL_FINGER,
+			finger_state == 0x01);
+	if (finger_state == 0x01) {
+		x = (touch_data[0] << 4) | (touch_data[2] & 0x07);
+		y = (touch_data[1] << 4) | (touch_data[2] >> 4);
+		wx = touch_data[3] & 0x07;
+		wy = touch_data[3] >> 4;
+		wide = (wx > wy);
+		major = max(wx, wy);
+		minor = min(wx, wy);
+		z = touch_data[4];
+
+		/* y is inverted */
+		y = hdata->max_y - y;
+
+		input_event(hdata->input, EV_ABS, ABS_MT_POSITION_X, x);
+		input_event(hdata->input, EV_ABS, ABS_MT_POSITION_Y, y);
+		input_event(hdata->input, EV_ABS, ABS_MT_ORIENTATION, wide);
+		input_event(hdata->input, EV_ABS, ABS_MT_PRESSURE, z);
+		input_event(hdata->input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+		input_event(hdata->input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
+	}
+}
+
+static void rmi_reset_work(struct work_struct *work)
+{
+	struct rmi_data *hdata = container_of(work, struct rmi_data,
+						reset_work);
+
+	/* switch the device to RMI if we receive a generic mouse report */
+	rmi_set_mode(hdata->hdev, RMI_MODE_ATTN_REPORTS);
+}
+
+static inline int rmi_schedule_reset(struct hid_device *hdev)
+{
+	struct rmi_data *hdata = hid_get_drvdata(hdev);
+	return schedule_work(&hdata->reset_work);
+}
+
+static int rmi_f11_input_event(struct hid_device *hdev, u8 irq, u8 *data,
+		int size)
+{
+	struct rmi_data *hdata = hid_get_drvdata(hdev);
+	int offset;
+	int i;
+
+	if (size < hdata->f11.report_size)
+		return 0;
+
+	if (!(irq & hdata->f11.irq_mask))
+		return 0;
+
+	offset = (hdata->max_fingers >> 2) + 1;
+	for (i = 0; i < hdata->max_fingers; i++) {
+		int fs_byte_position = i >> 2;
+		int fs_bit_position = (i & 0x3) << 1;
+		int finger_state = (data[fs_byte_position] >> fs_bit_position) &
+					0x03;
+
+		rmi_f11_process_touch(hdata, i, finger_state,
+				&data[offset + 5 * i]);
+	}
+	input_mt_sync_frame(hdata->input);
+	input_sync(hdata->input);
+	return hdata->f11.report_size;
+}
+
+static int rmi_f30_input_event(struct hid_device *hdev, u8 irq, u8 *data,
+		int size)
+{
+	struct rmi_data *hdata = hid_get_drvdata(hdev);
+	int i;
+	int button = 0;
+	bool value;
+
+	if (!(irq & hdata->f30.irq_mask))
+		return 0;
+
+	for (i = 0; i < hdata->gpio_led_count; i++) {
+		if (test_bit(i, &hdata->button_mask)) {
+			value = (data[i / 8] >> (i & 0x07)) & BIT(0);
+			if (test_bit(i, &hdata->button_state_mask))
+				value = !value;
+			input_event(hdata->input, EV_KEY, BTN_LEFT + button++,
+					value);
+		}
+	}
+	return hdata->f30.report_size;
+}
+
+static int rmi_input_event(struct hid_device *hdev, u8 *data, int size)
+{
+	struct rmi_data *hdata = hid_get_drvdata(hdev);
+	unsigned long irq_mask = 0;
+	unsigned index = 2;
+
+	if (!(test_bit(RMI_STARTED, &hdata->flags)))
+		return 0;
+
+	irq_mask |= hdata->f11.irq_mask;
+	irq_mask |= hdata->f30.irq_mask;
+
+	if (data[1] & ~irq_mask)
+		hid_warn(hdev, "unknown intr source:%02lx %s:%d\n",
+			data[1] & ~irq_mask, __FILE__, __LINE__);
+
+	if (hdata->f11.interrupt_base < hdata->f30.interrupt_base) {
+		index += rmi_f11_input_event(hdev, data[1], &data[index],
+				size - index);
+		index += rmi_f30_input_event(hdev, data[1], &data[index],
+				size - index);
+	} else {
+		index += rmi_f30_input_event(hdev, data[1], &data[index],
+				size - index);
+		index += rmi_f11_input_event(hdev, data[1], &data[index],
+				size - index);
+	}
+
+	return 1;
+}
+
+static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size)
+{
+	struct rmi_data *hdata = hid_get_drvdata(hdev);
+
+	if (!test_bit(RMI_READ_REQUEST_PENDING, &hdata->flags)) {
+		hid_err(hdev, "no read request pending\n");
+		return 0;
+	}
+
+	memcpy(hdata->readReport, data, size < hdata->input_report_size ?
+			size : hdata->input_report_size);
+	set_bit(RMI_READ_DATA_PENDING, &hdata->flags);
+	wake_up(&hdata->wait);
+
+	return 1;
+}
+
+static int rmi_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *data, int size)
+{
+	switch (data[0]) {
+	case RMI_READ_DATA_REPORT_ID:
+		return rmi_read_data_event(hdev, data, size);
+	case RMI_ATTN_REPORT_ID:
+		return rmi_input_event(hdev, data, size);
+	case RMI_MOUSE_REPORT_ID:
+		rmi_schedule_reset(hdev);
+		break;
+	}
+
+	return 0;
+}
+
+static int rmi_post_reset(struct hid_device *hdev)
+{
+	return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+}
+
+static int rmi_post_resume(struct hid_device *hdev)
+{
+	return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+}
+
+#define RMI4_MAX_PAGE 0xff
+#define RMI4_PAGE_SIZE 0x0100
+
+#define PDT_START_SCAN_LOCATION 0x00e9
+#define PDT_END_SCAN_LOCATION	0x0005
+#define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff)
+
+struct pdt_entry {
+	u8 query_base_addr:8;
+	u8 command_base_addr:8;
+	u8 control_base_addr:8;
+	u8 data_base_addr:8;
+	u8 interrupt_source_count:3;
+	u8 bits3and4:2;
+	u8 function_version:2;
+	u8 bit7:1;
+	u8 function_number:8;
+} __attribute__((__packed__));
+
+static inline unsigned long rmi_gen_mask(unsigned irq_base, unsigned irq_count)
+{
+	return GENMASK(irq_count + irq_base - 1, irq_base);
+}
+
+static void rmi_register_function(struct rmi_data *data,
+	struct pdt_entry *pdt_entry, int page, unsigned interrupt_count)
+{
+	struct rmi_function *f = NULL;
+	u16 page_base = page << 8;
+
+	switch (pdt_entry->function_number) {
+	case 0x11:
+		f = &data->f11;
+		break;
+	case 0x30:
+		f = &data->f30;
+		break;
+	}
+
+	if (f) {
+		f->page = page;
+		f->query_base_addr = page_base | pdt_entry->query_base_addr;
+		f->command_base_addr = page_base | pdt_entry->command_base_addr;
+		f->control_base_addr = page_base | pdt_entry->control_base_addr;
+		f->data_base_addr = page_base | pdt_entry->data_base_addr;
+		f->interrupt_base = interrupt_count;
+		f->interrupt_count = pdt_entry->interrupt_source_count;
+		f->irq_mask = rmi_gen_mask(f->interrupt_base,
+						f->interrupt_count);
+	}
+}
+
+static int rmi_scan_pdt(struct hid_device *hdev)
+{
+	struct rmi_data *data = hid_get_drvdata(hdev);
+	struct pdt_entry entry;
+	int page;
+	bool page_has_function;
+	int i;
+	int retval;
+	int interrupt = 0;
+	u16 page_start, pdt_start , pdt_end;
+
+	hid_info(hdev, "Scanning PDT...\n");
+
+	for (page = 0; (page <= RMI4_MAX_PAGE); page++) {
+		page_start = RMI4_PAGE_SIZE * page;
+		pdt_start = page_start + PDT_START_SCAN_LOCATION;
+		pdt_end = page_start + PDT_END_SCAN_LOCATION;
+
+		page_has_function = false;
+		for (i = pdt_start; i >= pdt_end; i -= sizeof(entry)) {
+			retval = rmi_read_block(hdev, i, &entry, sizeof(entry));
+			if (retval) {
+				hid_err(hdev,
+					"Read of PDT entry at %#06x failed.\n",
+					i);
+				goto error_exit;
+			}
+
+			if (RMI4_END_OF_PDT(entry.function_number))
+				break;
+
+			page_has_function = true;
+
+			hid_info(hdev, "Found F%02X on page %#04x\n",
+					entry.function_number, page);
+
+			rmi_register_function(data, &entry, page, interrupt);
+			interrupt += entry.interrupt_source_count;
+		}
+
+		if (!page_has_function)
+			break;
+	}
+
+	hid_info(hdev, "%s: Done with PDT scan.\n", __func__);
+	retval = 0;
+
+error_exit:
+	return retval;
+}
+
+static int rmi_populate_f11(struct hid_device *hdev)
+{
+	struct rmi_data *data = hid_get_drvdata(hdev);
+	u8 buf[20];
+	int ret;
+	bool has_query12;
+	bool has_physical_props;
+	unsigned x_size, y_size;
+
+	if (!data->f11.query_base_addr) {
+		hid_err(hdev, "No 2D sensor found, giving up.\n");
+		return -ENODEV;
+	}
+
+	/* query 0 contains some useful information */
+	ret = rmi_read(hdev, data->f11.query_base_addr, buf);
+	if (ret) {
+		hid_err(hdev, "can not get query 0: %d.\n", ret);
+		return ret;
+	}
+	has_query12 = !!(buf[0] & BIT(5));
+
+	/* query 1 to get the max number of fingers */
+	ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf);
+	if (ret) {
+		hid_err(hdev, "can not get NumberOfFingers: %d.\n", ret);
+		return ret;
+	}
+	data->max_fingers = (buf[0] & 0x07) + 1;
+	if (data->max_fingers > 5)
+		data->max_fingers = 10;
+
+	data->f11.report_size = data->max_fingers * 5 +
+				DIV_ROUND_UP(data->max_fingers, 4);
+
+	if (!(buf[0] & BIT(4))) {
+		hid_err(hdev, "No absolute events, giving up.\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * query 12 to know if the physical properties are reported
+	 * (query 12 is at offset 10 for HID devices)
+	 */
+	if (has_query12) {
+		ret = rmi_read(hdev, data->f11.query_base_addr + 10, buf);
+		if (ret) {
+			hid_err(hdev, "can not get query 12: %d.\n", ret);
+			return ret;
+		}
+		has_physical_props = !!(buf[0] & BIT(5));
+
+		if (has_physical_props) {
+			ret = rmi_read_block(hdev,
+					data->f11.query_base_addr + 11, buf, 4);
+			if (ret) {
+				hid_err(hdev, "can not read query 15-18: %d.\n",
+					ret);
+				return ret;
+			}
+
+			x_size = buf[0] | (buf[1] << 8);
+			y_size = buf[2] | (buf[3] << 8);
+
+			data->x_size_mm = DIV_ROUND_CLOSEST(x_size, 10);
+			data->y_size_mm = DIV_ROUND_CLOSEST(y_size, 10);
+
+			hid_info(hdev, "%s: size in mm: %d x %d\n",
+				 __func__, data->x_size_mm, data->y_size_mm);
+		}
+	}
+
+	/* retrieve the ctrl registers */
+	ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 20);
+	if (ret) {
+		hid_err(hdev, "can not read ctrl block of size 20: %d.\n", ret);
+		return ret;
+	}
+
+	data->max_x = buf[6] | (buf[7] << 8);
+	data->max_y = buf[8] | (buf[9] << 8);
+
+	return 0;
+}
+
+static int rmi_populate_f30(struct hid_device *hdev)
+{
+	struct rmi_data *data = hid_get_drvdata(hdev);
+	u8 buf[20];
+	int ret;
+	bool has_gpio, has_led;
+	unsigned bytes_per_ctrl;
+	u8 ctrl2_addr;
+	int ctrl2_3_length;
+	int i;
+
+	/* function F30 is for physical buttons */
+	if (!data->f30.query_base_addr) {
+		hid_err(hdev, "No GPIO/LEDs found, giving up.\n");
+		return -ENODEV;
+	}
+
+	ret = rmi_read_block(hdev, data->f30.query_base_addr, buf, 2);
+	if (ret) {
+		hid_err(hdev, "can not get F30 query registers: %d.\n", ret);
+		return ret;
+	}
+
+	has_gpio = !!(buf[0] & BIT(3));
+	has_led = !!(buf[0] & BIT(2));
+	data->gpio_led_count = buf[1] & 0x1f;
+
+	/* retrieve ctrl 2 & 3 registers */
+	bytes_per_ctrl = (data->gpio_led_count + 7) / 8;
+	/* Ctrl0 is present only if both has_gpio and has_led are set*/
+	ctrl2_addr = (has_gpio && has_led) ? bytes_per_ctrl : 0;
+	/* Ctrl1 is always be present */
+	ctrl2_addr += bytes_per_ctrl;
+	ctrl2_3_length = 2 * bytes_per_ctrl;
+
+	data->f30.report_size = bytes_per_ctrl;
+
+	ret = rmi_read_block(hdev, data->f30.control_base_addr + ctrl2_addr,
+				buf, ctrl2_3_length);
+	if (ret) {
+		hid_err(hdev, "can not read ctrl 2&3 block of size %d: %d.\n",
+			ctrl2_3_length, ret);
+		return ret;
+	}
+
+	for (i = 0; i < data->gpio_led_count; i++) {
+		int byte_position = i >> 3;
+		int bit_position = i & 0x07;
+		u8 dir_byte = buf[byte_position];
+		u8 data_byte = buf[byte_position + bytes_per_ctrl];
+		bool dir = (dir_byte >> bit_position) & BIT(0);
+		bool dat = (data_byte >> bit_position) & BIT(0);
+
+		if (dir == 0) {
+			/* input mode */
+			if (dat) {
+				/* actual buttons have pull up resistor */
+				data->button_count++;
+				set_bit(i, &data->button_mask);
+				set_bit(i, &data->button_state_mask);
+			}
+		}
+
+	}
+
+	return 0;
+}
+
+static int rmi_populate(struct hid_device *hdev)
+{
+	int ret;
+
+	ret = rmi_scan_pdt(hdev);
+	if (ret) {
+		hid_err(hdev, "PDT scan failed with code %d.\n", ret);
+		return ret;
+	}
+
+	ret = rmi_populate_f11(hdev);
+	if (ret) {
+		hid_err(hdev, "Error while initializing F11 (%d).\n", ret);
+		return ret;
+	}
+
+	ret = rmi_populate_f30(hdev);
+	if (ret)
+		hid_warn(hdev, "Error while initializing F30 (%d).\n", ret);
+
+	return 0;
+}
+
+static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
+{
+	struct rmi_data *data = hid_get_drvdata(hdev);
+	struct input_dev *input = hi->input;
+	int ret;
+	int res_x, res_y, i;
+
+	data->input = input;
+
+	hid_dbg(hdev, "Opening low level driver\n");
+	ret = hid_hw_open(hdev);
+	if (ret)
+		return;
+
+	/* Allow incoming hid reports */
+	hid_device_io_start(hdev);
+
+	ret = rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+	if (ret < 0) {
+		dev_err(&hdev->dev, "failed to set rmi mode\n");
+		goto exit;
+	}
+
+	ret = rmi_set_page(hdev, 0);
+	if (ret < 0) {
+		dev_err(&hdev->dev, "failed to set page select to 0.\n");
+		goto exit;
+	}
+
+	ret = rmi_populate(hdev);
+	if (ret)
+		goto exit;
+
+	__set_bit(EV_ABS, input->evbit);
+	input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->max_x, 0, 0);
+	input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->max_y, 0, 0);
+
+	if (data->x_size_mm && data->x_size_mm) {
+		res_x = (data->max_x - 1) / data->x_size_mm;
+		res_y = (data->max_y - 1) / data->x_size_mm;
+
+		input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
+		input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
+	}
+
+	input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+	input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0);
+	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
+	input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
+
+	input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
+
+	if (data->button_count) {
+		__set_bit(EV_KEY, input->evbit);
+		for (i = 0; i < data->button_count; i++)
+			__set_bit(BTN_LEFT + i, input->keybit);
+
+		if (data->button_count == 1)
+			__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+	}
+
+	set_bit(RMI_STARTED, &data->flags);
+
+exit:
+	hid_device_io_stop(hdev);
+	hid_hw_close(hdev);
+}
+
+static int rmi_input_mapping(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	/* we want to make HID ignore the advertised HID collection */
+	return -1;
+}
+
+static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	struct rmi_data *data = NULL;
+	int ret;
+	size_t alloc_size;
+
+	data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	INIT_WORK(&data->reset_work, rmi_reset_work);
+	data->hdev = hdev;
+
+	hid_set_drvdata(hdev, data);
+
+	hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		return ret;
+	}
+
+	data->input_report_size = (hdev->report_enum[HID_INPUT_REPORT]
+		.report_id_hash[RMI_ATTN_REPORT_ID]->size >> 3)
+		+ 1 /* report id */;
+	data->output_report_size = (hdev->report_enum[HID_OUTPUT_REPORT]
+		.report_id_hash[RMI_WRITE_REPORT_ID]->size >> 3)
+		+ 1 /* report id */;
+
+	alloc_size = data->output_report_size + data->input_report_size;
+
+	data->writeReport = devm_kzalloc(&hdev->dev, alloc_size, GFP_KERNEL);
+	if (!data->writeReport) {
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	data->readReport = data->writeReport + data->output_report_size;
+
+	init_waitqueue_head(&data->wait);
+
+	mutex_init(&data->page_mutex);
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		return ret;
+	}
+
+	if (!test_bit(RMI_STARTED, &data->flags)) {
+		hid_hw_stop(hdev);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void rmi_remove(struct hid_device *hdev)
+{
+	struct rmi_data *hdata = hid_get_drvdata(hdev);
+
+	clear_bit(RMI_STARTED, &hdata->flags);
+
+	hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id rmi_id[] = {
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, rmi_id);
+
+static struct hid_driver rmi_driver = {
+	.name = "hid-rmi",
+	.id_table		= rmi_id,
+	.probe			= rmi_probe,
+	.remove			= rmi_remove,
+	.raw_event		= rmi_raw_event,
+	.input_mapping		= rmi_input_mapping,
+	.input_configured	= rmi_input_configured,
+#ifdef CONFIG_PM
+	.resume			= rmi_post_resume,
+	.reset_resume		= rmi_post_reset,
+#endif
+};
+
+module_hid_driver(rmi_driver);
+
+MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>");
+MODULE_DESCRIPTION("RMI HID driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
index a97c78845f7b..31de890d14cf 100644
--- a/drivers/hid/hid-thingm.c
+++ b/drivers/hid/hid-thingm.c
@@ -1,7 +1,7 @@
 /*
  * ThingM blink(1) USB RGB LED driver
  *
- * Copyright 2013 Savoir-faire Linux Inc.
+ * Copyright 2013-2014 Savoir-faire Linux Inc.
  *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -10,244 +10,285 @@
  */
 
 #include <linux/hid.h>
+#include <linux/hidraw.h>
 #include <linux/leds.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include "hid-ids.h"
 
-#define BLINK1_CMD_SIZE		9
+#define REPORT_ID	1
+#define REPORT_SIZE	9
 
-#define blink1_rgb_to_r(rgb)	((rgb & 0xFF0000) >> 16)
-#define blink1_rgb_to_g(rgb)	((rgb & 0x00FF00) >> 8)
-#define blink1_rgb_to_b(rgb)	((rgb & 0x0000FF) >> 0)
+/* Firmware major number of supported devices */
+#define THINGM_MAJOR_MK1	'1'
+#define THINGM_MAJOR_MK2	'2'
 
-/**
- * struct blink1_data - blink(1) device specific data
- * @hdev:		HID device.
- * @led_cdev:		LED class instance.
- * @rgb:		8-bit per channel RGB notation.
- * @fade:		fade time in hundredths of a second.
- * @brightness:		brightness coefficient.
- * @play:		play/pause in-memory patterns.
- */
-struct blink1_data {
+struct thingm_fwinfo {
+	char major;
+	unsigned numrgb;
+	unsigned first;
+};
+
+const struct thingm_fwinfo thingm_fwinfo[] = {
+	{
+		.major = THINGM_MAJOR_MK1,
+		.numrgb = 1,
+		.first = 0,
+	}, {
+		.major = THINGM_MAJOR_MK2,
+		.numrgb = 2,
+		.first = 1,
+	}
+};
+
+/* A red, green or blue channel, part of an RGB chip */
+struct thingm_led {
+	struct thingm_rgb *rgb;
+	struct led_classdev ldev;
+	char name[32];
+};
+
+/* Basically a WS2812 5050 RGB LED chip */
+struct thingm_rgb {
+	struct thingm_device *tdev;
+	struct thingm_led red;
+	struct thingm_led green;
+	struct thingm_led blue;
+	struct work_struct work;
+	u8 num;
+};
+
+struct thingm_device {
 	struct hid_device *hdev;
-	struct led_classdev led_cdev;
-	u32 rgb;
-	u16 fade;
-	u8 brightness;
-	bool play;
+	struct {
+		char major;
+		char minor;
+	} version;
+	const struct thingm_fwinfo *fwinfo;
+	struct mutex lock;
+	struct thingm_rgb *rgb;
 };
 
-static int blink1_send_command(struct blink1_data *data,
-		u8 buf[BLINK1_CMD_SIZE])
+static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
 {
 	int ret;
 
-	hid_dbg(data->hdev, "command: %d%c%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
+	hid_dbg(tdev->hdev, "-> %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
 			buf[0], buf[1], buf[2], buf[3], buf[4],
 			buf[5], buf[6], buf[7], buf[8]);
 
-	ret = hid_hw_raw_request(data->hdev, buf[0], buf, BLINK1_CMD_SIZE,
-				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+	ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
+			HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 
 	return ret < 0 ? ret : 0;
 }
 
-static int blink1_update_color(struct blink1_data *data)
+static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
 {
-	u8 buf[BLINK1_CMD_SIZE] = { 1, 'n', 0, 0, 0, 0, 0, 0, 0 };
-
-	if (data->brightness) {
-		unsigned int coef = DIV_ROUND_CLOSEST(255, data->brightness);
+	int ret;
 
-		buf[2] = DIV_ROUND_CLOSEST(blink1_rgb_to_r(data->rgb), coef);
-		buf[3] = DIV_ROUND_CLOSEST(blink1_rgb_to_g(data->rgb), coef);
-		buf[4] = DIV_ROUND_CLOSEST(blink1_rgb_to_b(data->rgb), coef);
-	}
+	ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
+			HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+	if (ret < 0)
+		return ret;
 
-	if (data->fade) {
-		buf[1] = 'c';
-		buf[5] = (data->fade & 0xFF00) >> 8;
-		buf[6] = (data->fade & 0x00FF);
-	}
+	hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
+			buf[0], buf[1], buf[2], buf[3], buf[4],
+			buf[5], buf[6], buf[7], buf[8]);
 
-	return blink1_send_command(data, buf);
+	return 0;
 }
 
-static void blink1_led_set(struct led_classdev *led_cdev,
-		enum led_brightness brightness)
+static int thingm_version(struct thingm_device *tdev)
 {
-	struct blink1_data *data = dev_get_drvdata(led_cdev->dev->parent);
+	u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 };
+	int err;
 
-	data->brightness = brightness;
-	if (blink1_update_color(data))
-		hid_err(data->hdev, "failed to update color\n");
-}
+	err = thingm_send(tdev, buf);
+	if (err)
+		return err;
 
-static enum led_brightness blink1_led_get(struct led_classdev *led_cdev)
-{
-	struct blink1_data *data = dev_get_drvdata(led_cdev->dev->parent);
+	err = thingm_recv(tdev, buf);
+	if (err)
+		return err;
 
-	return data->brightness;
+	tdev->version.major = buf[3];
+	tdev->version.minor = buf[4];
+
+	return 0;
 }
 
-static ssize_t blink1_show_rgb(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static int thingm_write_color(struct thingm_rgb *rgb)
 {
-	struct blink1_data *data = dev_get_drvdata(dev->parent);
+	u8 buf[REPORT_SIZE] = { REPORT_ID, 'c', 0, 0, 0, 0, 0, rgb->num, 0 };
 
-	return sprintf(buf, "%.6X\n", data->rgb);
+	buf[2] = rgb->red.ldev.brightness;
+	buf[3] = rgb->green.ldev.brightness;
+	buf[4] = rgb->blue.ldev.brightness;
+
+	return thingm_send(rgb->tdev, buf);
 }
 
-static ssize_t blink1_store_rgb(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static void thingm_work(struct work_struct *work)
 {
-	struct blink1_data *data = dev_get_drvdata(dev->parent);
-	long unsigned int rgb;
-	int ret;
+	struct thingm_rgb *rgb = container_of(work, struct thingm_rgb, work);
 
-	ret = kstrtoul(buf, 16, &rgb);
-	if (ret)
-		return ret;
-
-	/* RGB triplet notation is 24-bit hexadecimal */
-	if (rgb > 0xFFFFFF)
-		return -EINVAL;
+	mutex_lock(&rgb->tdev->lock);
 
-	data->rgb = rgb;
-	ret = blink1_update_color(data);
+	if (thingm_write_color(rgb))
+		hid_err(rgb->tdev->hdev, "failed to write color\n");
 
-	return ret ? ret : count;
+	mutex_unlock(&rgb->tdev->lock);
 }
 
-static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR, blink1_show_rgb, blink1_store_rgb);
-
-static ssize_t blink1_show_fade(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static void thingm_led_set(struct led_classdev *ldev,
+		enum led_brightness brightness)
 {
-	struct blink1_data *data = dev_get_drvdata(dev->parent);
+	struct thingm_led *led = container_of(ldev, struct thingm_led, ldev);
 
-	return sprintf(buf, "%d\n", data->fade * 10);
+	/* the ledclass has already stored the brightness value */
+	schedule_work(&led->rgb->work);
 }
 
-static ssize_t blink1_store_fade(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static int thingm_init_rgb(struct thingm_rgb *rgb)
 {
-	struct blink1_data *data = dev_get_drvdata(dev->parent);
-	long unsigned int fade;
-	int ret;
+	const int minor = ((struct hidraw *) rgb->tdev->hdev->hidraw)->minor;
+	int err;
+
+	/* Register the red diode */
+	snprintf(rgb->red.name, sizeof(rgb->red.name),
+			"thingm%d:red:led%d", minor, rgb->num);
+	rgb->red.ldev.name = rgb->red.name;
+	rgb->red.ldev.max_brightness = 255;
+	rgb->red.ldev.brightness_set = thingm_led_set;
+	rgb->red.rgb = rgb;
+
+	err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->red.ldev);
+	if (err)
+		return err;
+
+	/* Register the green diode */
+	snprintf(rgb->green.name, sizeof(rgb->green.name),
+			"thingm%d:green:led%d", minor, rgb->num);
+	rgb->green.ldev.name = rgb->green.name;
+	rgb->green.ldev.max_brightness = 255;
+	rgb->green.ldev.brightness_set = thingm_led_set;
+	rgb->green.rgb = rgb;
+
+	err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->green.ldev);
+	if (err)
+		goto unregister_red;
+
+	/* Register the blue diode */
+	snprintf(rgb->blue.name, sizeof(rgb->blue.name),
+			"thingm%d:blue:led%d", minor, rgb->num);
+	rgb->blue.ldev.name = rgb->blue.name;
+	rgb->blue.ldev.max_brightness = 255;
+	rgb->blue.ldev.brightness_set = thingm_led_set;
+	rgb->blue.rgb = rgb;
+
+	err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->blue.ldev);
+	if (err)
+		goto unregister_green;
+
+	INIT_WORK(&rgb->work, thingm_work);
 
-	ret = kstrtoul(buf, 10, &fade);
-	if (ret)
-		return ret;
+	return 0;
 
-	/* blink(1) accepts 16-bit fade time, number of 10ms ticks */
-	fade = DIV_ROUND_CLOSEST(fade, 10);
-	if (fade > 65535)
-		return -EINVAL;
+unregister_green:
+	led_classdev_unregister(&rgb->green.ldev);
 
-	data->fade = fade;
+unregister_red:
+	led_classdev_unregister(&rgb->red.ldev);
 
-	return count;
+	return err;
 }
 
-static DEVICE_ATTR(fade, S_IRUGO | S_IWUSR,
-		blink1_show_fade, blink1_store_fade);
-
-static ssize_t blink1_show_play(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static void thingm_remove_rgb(struct thingm_rgb *rgb)
 {
-	struct blink1_data *data = dev_get_drvdata(dev->parent);
-
-	return sprintf(buf, "%d\n", data->play);
+	flush_work(&rgb->work);
+	led_classdev_unregister(&rgb->red.ldev);
+	led_classdev_unregister(&rgb->green.ldev);
+	led_classdev_unregister(&rgb->blue.ldev);
 }
 
-static ssize_t blink1_store_play(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-	struct blink1_data *data = dev_get_drvdata(dev->parent);
-	u8 cmd[BLINK1_CMD_SIZE] = { 1, 'p', 0, 0, 0, 0, 0, 0, 0 };
-	long unsigned int play;
-	int ret;
+	struct thingm_device *tdev;
+	int i, err;
 
-	ret = kstrtoul(buf, 10, &play);
-	if (ret)
-		return ret;
+	tdev = devm_kzalloc(&hdev->dev, sizeof(struct thingm_device),
+			GFP_KERNEL);
+	if (!tdev)
+		return -ENOMEM;
 
-	data->play = !!play;
-	cmd[2] = data->play;
-	ret = blink1_send_command(data, cmd);
+	tdev->hdev = hdev;
+	hid_set_drvdata(hdev, tdev);
 
-	return ret ? ret : count;
-}
-
-static DEVICE_ATTR(play, S_IRUGO | S_IWUSR,
-		blink1_show_play, blink1_store_play);
+	err = hid_parse(hdev);
+	if (err)
+		goto error;
 
-static const struct attribute_group blink1_sysfs_group = {
-	.attrs = (struct attribute *[]) {
-		&dev_attr_rgb.attr,
-		&dev_attr_fade.attr,
-		&dev_attr_play.attr,
-		NULL
-	},
-};
+	err = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+	if (err)
+		goto error;
 
-static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	struct blink1_data *data;
-	struct led_classdev *led;
-	char led_name[13];
-	int ret;
+	mutex_init(&tdev->lock);
 
-	data = devm_kzalloc(&hdev->dev, sizeof(struct blink1_data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
+	err = thingm_version(tdev);
+	if (err)
+		goto stop;
 
-	hid_set_drvdata(hdev, data);
-	data->hdev = hdev;
-	data->rgb = 0xFFFFFF; /* set a default white color */
+	hid_dbg(hdev, "firmware version: %c.%c\n",
+			tdev->version.major, tdev->version.minor);
 
-	ret = hid_parse(hdev);
-	if (ret)
-		goto error;
+	for (i = 0; i < ARRAY_SIZE(thingm_fwinfo) && !tdev->fwinfo; ++i)
+		if (thingm_fwinfo[i].major == tdev->version.major)
+			tdev->fwinfo = &thingm_fwinfo[i];
 
-	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
-	if (ret)
-		goto error;
+	if (!tdev->fwinfo) {
+		hid_err(hdev, "unsupported firmware %c\n", tdev->version.major);
+		goto stop;
+	}
 
-	/* blink(1) serial numbers range is 0x1A001000 to 0x1A002FFF */
-	led = &data->led_cdev;
-	snprintf(led_name, sizeof(led_name), "blink1::%s", hdev->uniq + 4);
-	led->name = led_name;
-	led->brightness_set = blink1_led_set;
-	led->brightness_get = blink1_led_get;
-	ret = led_classdev_register(&hdev->dev, led);
-	if (ret)
+	tdev->rgb = devm_kzalloc(&hdev->dev,
+			sizeof(struct thingm_rgb) * tdev->fwinfo->numrgb,
+			GFP_KERNEL);
+	if (!tdev->rgb) {
+		err = -ENOMEM;
 		goto stop;
+	}
 
-	ret = sysfs_create_group(&led->dev->kobj, &blink1_sysfs_group);
-	if (ret)
-		goto remove_led;
+	for (i = 0; i < tdev->fwinfo->numrgb; ++i) {
+		struct thingm_rgb *rgb = tdev->rgb + i;
+
+		rgb->tdev = tdev;
+		rgb->num = tdev->fwinfo->first + i;
+		err = thingm_init_rgb(rgb);
+		if (err) {
+			while (--i >= 0)
+				thingm_remove_rgb(tdev->rgb + i);
+			goto stop;
+		}
+	}
 
 	return 0;
-
-remove_led:
-	led_classdev_unregister(led);
 stop:
 	hid_hw_stop(hdev);
 error:
-	return ret;
+	return err;
 }
 
 static void thingm_remove(struct hid_device *hdev)
 {
-	struct blink1_data *data = hid_get_drvdata(hdev);
-	struct led_classdev *led = &data->led_cdev;
+	struct thingm_device *tdev = hid_get_drvdata(hdev);
+	int i;
+
+	for (i = 0; i < tdev->fwinfo->numrgb; ++i)
+		thingm_remove_rgb(tdev->rgb + i);
 
-	sysfs_remove_group(&led->dev->kobj, &blink1_sysfs_group);
-	led_classdev_unregister(led);
 	hid_hw_stop(hdev);
 }
 
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index f2d7bf90c9fe..2e7801af466e 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -55,6 +55,9 @@ static __u32 vmbus_get_next_version(__u32 current_version)
 	case (VERSION_WIN8):
 		return VERSION_WIN7;
 
+	case (VERSION_WIN8_1):
+		return VERSION_WIN8;
+
 	case (VERSION_WS2008):
 	default:
 		return VERSION_INVAL;
@@ -77,7 +80,7 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
 	msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
 	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
 	msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
-	if (version == VERSION_WIN8)
+	if (version == VERSION_WIN8_1)
 		msg->target_vcpu = hv_context.vp_index[smp_processor_id()];
 
 	/*
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 505a59e100b0..97204dce162d 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -47,7 +47,7 @@
 #define LM70_CHIP_LM74		3	/* NS LM74 */
 
 struct lm70 {
-	struct device *hwmon_dev;
+	struct spi_device *spi;
 	struct mutex lock;
 	unsigned int chip;
 };
@@ -56,11 +56,11 @@ struct lm70 {
 static ssize_t lm70_sense_temp(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct spi_device *spi = to_spi_device(dev);
+	struct lm70 *p_lm70 = dev_get_drvdata(dev);
+	struct spi_device *spi = p_lm70->spi;
 	int status, val = 0;
 	u8 rxbuf[2];
 	s16 raw = 0;
-	struct lm70 *p_lm70 = spi_get_drvdata(spi);
 
 	if (mutex_lock_interruptible(&p_lm70->lock))
 		return -ERESTARTSYS;
@@ -121,21 +121,20 @@ out:
 
 static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL);
 
-static ssize_t lm70_show_name(struct device *dev, struct device_attribute
-			      *devattr, char *buf)
-{
-	return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
-}
+static struct attribute *lm70_attrs[] = {
+	&dev_attr_temp1_input.attr,
+	NULL
+};
 
-static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL);
+ATTRIBUTE_GROUPS(lm70);
 
 /*----------------------------------------------------------------------*/
 
 static int lm70_probe(struct spi_device *spi)
 {
 	int chip = spi_get_device_id(spi)->driver_data;
+	struct device *hwmon_dev;
 	struct lm70 *p_lm70;
-	int status;
 
 	/* signaling is SPI_MODE_0 */
 	if (spi->mode & (SPI_CPOL | SPI_CPHA))
@@ -149,46 +148,14 @@ static int lm70_probe(struct spi_device *spi)
 
 	mutex_init(&p_lm70->lock);
 	p_lm70->chip = chip;
+	p_lm70->spi = spi;
 
-	spi_set_drvdata(spi, p_lm70);
-
-	status = device_create_file(&spi->dev, &dev_attr_temp1_input);
-	if (status)
-		goto out_dev_create_temp_file_failed;
-	status = device_create_file(&spi->dev, &dev_attr_name);
-	if (status)
-		goto out_dev_create_file_failed;
-
-	/* sysfs hook */
-	p_lm70->hwmon_dev = hwmon_device_register(&spi->dev);
-	if (IS_ERR(p_lm70->hwmon_dev)) {
-		dev_dbg(&spi->dev, "hwmon_device_register failed.\n");
-		status = PTR_ERR(p_lm70->hwmon_dev);
-		goto out_dev_reg_failed;
-	}
-
-	return 0;
-
-out_dev_reg_failed:
-	device_remove_file(&spi->dev, &dev_attr_name);
-out_dev_create_file_failed:
-	device_remove_file(&spi->dev, &dev_attr_temp1_input);
-out_dev_create_temp_file_failed:
-	return status;
+	hwmon_dev = devm_hwmon_device_register_with_groups(&spi->dev,
+							   spi->modalias,
+							   p_lm70, lm70_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static int lm70_remove(struct spi_device *spi)
-{
-	struct lm70 *p_lm70 = spi_get_drvdata(spi);
-
-	hwmon_device_unregister(p_lm70->hwmon_dev);
-	device_remove_file(&spi->dev, &dev_attr_temp1_input);
-	device_remove_file(&spi->dev, &dev_attr_name);
-
-	return 0;
-}
-
-
 static const struct spi_device_id lm70_ids[] = {
 	{ "lm70",   LM70_CHIP_LM70 },
 	{ "tmp121", LM70_CHIP_TMP121 },
@@ -205,7 +172,6 @@ static struct spi_driver lm70_driver = {
 	},
 	.id_table = lm70_ids,
 	.probe	= lm70_probe,
-	.remove	= lm70_remove,
 };
 
 module_spi_driver(lm70_driver);
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 502771c06fd9..4cd8a513c47b 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -19,10 +19,6 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/module.h>
@@ -61,36 +57,6 @@ struct lm77_data {
 	u8			alarms;
 };
 
-static int lm77_probe(struct i2c_client *client,
-		      const struct i2c_device_id *id);
-static int lm77_detect(struct i2c_client *client, struct i2c_board_info *info);
-static void lm77_init_client(struct i2c_client *client);
-static int lm77_remove(struct i2c_client *client);
-static u16 lm77_read_value(struct i2c_client *client, u8 reg);
-static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value);
-
-static struct lm77_data *lm77_update_device(struct device *dev);
-
-
-static const struct i2c_device_id lm77_id[] = {
-	{ "lm77", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, lm77_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver lm77_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "lm77",
-	},
-	.probe		= lm77_probe,
-	.remove		= lm77_remove,
-	.id_table	= lm77_id,
-	.detect		= lm77_detect,
-	.address_list	= normal_i2c,
-};
-
 /* straight from the datasheet */
 #define LM77_TEMP_MIN (-55000)
 #define LM77_TEMP_MAX 125000
@@ -110,6 +76,62 @@ static inline int LM77_TEMP_FROM_REG(s16 reg)
 	return (reg / 8) * 500;
 }
 
+/*
+ * All registers are word-sized, except for the configuration register.
+ * The LM77 uses the high-byte first convention.
+ */
+static u16 lm77_read_value(struct i2c_client *client, u8 reg)
+{
+	if (reg == LM77_REG_CONF)
+		return i2c_smbus_read_byte_data(client, reg);
+	else
+		return i2c_smbus_read_word_swapped(client, reg);
+}
+
+static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+	if (reg == LM77_REG_CONF)
+		return i2c_smbus_write_byte_data(client, reg, value);
+	else
+		return i2c_smbus_write_word_swapped(client, reg, value);
+}
+
+static struct lm77_data *lm77_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm77_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		dev_dbg(&client->dev, "Starting lm77 update\n");
+		data->temp_input =
+			LM77_TEMP_FROM_REG(lm77_read_value(client,
+							   LM77_REG_TEMP));
+		data->temp_hyst =
+			LM77_TEMP_FROM_REG(lm77_read_value(client,
+							   LM77_REG_TEMP_HYST));
+		data->temp_crit =
+			LM77_TEMP_FROM_REG(lm77_read_value(client,
+							   LM77_REG_TEMP_CRIT));
+		data->temp_min =
+			LM77_TEMP_FROM_REG(lm77_read_value(client,
+							   LM77_REG_TEMP_MIN));
+		data->temp_max =
+			LM77_TEMP_FROM_REG(lm77_read_value(client,
+							   LM77_REG_TEMP_MAX));
+		data->alarms =
+			lm77_read_value(client, LM77_REG_TEMP) & 0x0007;
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
 /* sysfs stuff */
 
 /* read routines for temperature limits */
@@ -337,6 +359,14 @@ static int lm77_detect(struct i2c_client *client, struct i2c_board_info *info)
 	return 0;
 }
 
+static void lm77_init_client(struct i2c_client *client)
+{
+	/* Initialize the LM77 chip - turn off shutdown mode */
+	int conf = lm77_read_value(client, LM77_REG_CONF);
+	if (conf & 1)
+		lm77_write_value(client, LM77_REG_CONF, conf & 0xfe);
+}
+
 static int lm77_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
@@ -379,69 +409,24 @@ static int lm77_remove(struct i2c_client *client)
 	return 0;
 }
 
-/*
- * All registers are word-sized, except for the configuration register.
- * The LM77 uses the high-byte first convention.
- */
-static u16 lm77_read_value(struct i2c_client *client, u8 reg)
-{
-	if (reg == LM77_REG_CONF)
-		return i2c_smbus_read_byte_data(client, reg);
-	else
-		return i2c_smbus_read_word_swapped(client, reg);
-}
-
-static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-	if (reg == LM77_REG_CONF)
-		return i2c_smbus_write_byte_data(client, reg, value);
-	else
-		return i2c_smbus_write_word_swapped(client, reg, value);
-}
-
-static void lm77_init_client(struct i2c_client *client)
-{
-	/* Initialize the LM77 chip - turn off shutdown mode */
-	int conf = lm77_read_value(client, LM77_REG_CONF);
-	if (conf & 1)
-		lm77_write_value(client, LM77_REG_CONF, conf & 0xfe);
-}
-
-static struct lm77_data *lm77_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm77_data *data = i2c_get_clientdata(client);
-
-	mutex_lock(&data->update_lock);
-
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-	    || !data->valid) {
-		dev_dbg(&client->dev, "Starting lm77 update\n");
-		data->temp_input =
-			LM77_TEMP_FROM_REG(lm77_read_value(client,
-							   LM77_REG_TEMP));
-		data->temp_hyst =
-			LM77_TEMP_FROM_REG(lm77_read_value(client,
-							   LM77_REG_TEMP_HYST));
-		data->temp_crit =
-			LM77_TEMP_FROM_REG(lm77_read_value(client,
-							   LM77_REG_TEMP_CRIT));
-		data->temp_min =
-			LM77_TEMP_FROM_REG(lm77_read_value(client,
-							   LM77_REG_TEMP_MIN));
-		data->temp_max =
-			LM77_TEMP_FROM_REG(lm77_read_value(client,
-							   LM77_REG_TEMP_MAX));
-		data->alarms =
-			lm77_read_value(client, LM77_REG_TEMP) & 0x0007;
-		data->last_updated = jiffies;
-		data->valid = 1;
-	}
-
-	mutex_unlock(&data->update_lock);
+static const struct i2c_device_id lm77_id[] = {
+	{ "lm77", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lm77_id);
 
-	return data;
-}
+/* This is the driver that will be inserted */
+static struct i2c_driver lm77_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "lm77",
+	},
+	.probe		= lm77_probe,
+	.remove		= lm77_remove,
+	.id_table	= lm77_id,
+	.detect		= lm77_detect,
+	.address_list	= normal_i2c,
+};
 
 module_i2c_driver(lm77_driver);
 
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 6748b4583e7b..51719956cc03 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -51,6 +51,7 @@
 #define	TMP102_THIGH_REG		0x03
 
 struct tmp102 {
+	struct i2c_client *client;
 	struct device *hwmon_dev;
 	struct thermal_zone_device *tz;
 	struct mutex lock;
@@ -77,9 +78,10 @@ static const u8 tmp102_reg[] = {
 	TMP102_THIGH_REG,
 };
 
-static struct tmp102 *tmp102_update_device(struct i2c_client *client)
+static struct tmp102 *tmp102_update_device(struct device *dev)
 {
-	struct tmp102 *tmp102 = i2c_get_clientdata(client);
+	struct tmp102 *tmp102 = dev_get_drvdata(dev);
+	struct i2c_client *client = tmp102->client;
 
 	mutex_lock(&tmp102->lock);
 	if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
@@ -98,7 +100,7 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
 
 static int tmp102_read_temp(void *dev, long *temp)
 {
-	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
+	struct tmp102 *tmp102 = tmp102_update_device(dev);
 
 	*temp = tmp102->temp[0];
 
@@ -110,7 +112,7 @@ static ssize_t tmp102_show_temp(struct device *dev,
 				char *buf)
 {
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
-	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
+	struct tmp102 *tmp102 = tmp102_update_device(dev);
 
 	return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
 }
@@ -120,8 +122,8 @@ static ssize_t tmp102_set_temp(struct device *dev,
 			       const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct tmp102 *tmp102 = i2c_get_clientdata(client);
+	struct tmp102 *tmp102 = dev_get_drvdata(dev);
+	struct i2c_client *client = tmp102->client;
 	long val;
 	int status;
 
@@ -145,16 +147,13 @@ static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp,
 static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
 			  tmp102_set_temp, 2);
 
-static struct attribute *tmp102_attributes[] = {
+static struct attribute *tmp102_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	NULL
 };
-
-static const struct attribute_group tmp102_attr_group = {
-	.attrs = tmp102_attributes,
-};
+ATTRIBUTE_GROUPS(tmp102);
 
 #define TMP102_CONFIG  (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
 #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
@@ -162,72 +161,68 @@ static const struct attribute_group tmp102_attr_group = {
 static int tmp102_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct tmp102 *tmp102;
 	int status;
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_WORD_DATA)) {
-		dev_err(&client->dev,
+		dev_err(dev,
 			"adapter doesn't support SMBus word transactions\n");
 		return -ENODEV;
 	}
 
-	tmp102 = devm_kzalloc(&client->dev, sizeof(*tmp102), GFP_KERNEL);
+	tmp102 = devm_kzalloc(dev, sizeof(*tmp102), GFP_KERNEL);
 	if (!tmp102)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, tmp102);
+	tmp102->client = client;
 
 	status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (status < 0) {
-		dev_err(&client->dev, "error reading config register\n");
+		dev_err(dev, "error reading config register\n");
 		return status;
 	}
 	tmp102->config_orig = status;
 	status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
 					      TMP102_CONFIG);
 	if (status < 0) {
-		dev_err(&client->dev, "error writing config register\n");
+		dev_err(dev, "error writing config register\n");
 		goto fail_restore_config;
 	}
 	status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (status < 0) {
-		dev_err(&client->dev, "error reading config register\n");
+		dev_err(dev, "error reading config register\n");
 		goto fail_restore_config;
 	}
 	status &= ~TMP102_CONFIG_RD_ONLY;
 	if (status != TMP102_CONFIG) {
-		dev_err(&client->dev, "config settings did not stick\n");
+		dev_err(dev, "config settings did not stick\n");
 		status = -ENODEV;
 		goto fail_restore_config;
 	}
 	tmp102->last_update = jiffies - HZ;
 	mutex_init(&tmp102->lock);
 
-	status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group);
-	if (status) {
-		dev_dbg(&client->dev, "could not create sysfs files\n");
+	hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+						      tmp102, tmp102_groups);
+	if (IS_ERR(hwmon_dev)) {
+		dev_dbg(dev, "unable to register hwmon device\n");
+		status = PTR_ERR(hwmon_dev);
 		goto fail_restore_config;
 	}
-	tmp102->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(tmp102->hwmon_dev)) {
-		dev_dbg(&client->dev, "unable to register hwmon device\n");
-		status = PTR_ERR(tmp102->hwmon_dev);
-		goto fail_remove_sysfs;
-	}
-
-	tmp102->tz = thermal_zone_of_sensor_register(&client->dev, 0,
-						     &client->dev,
+	tmp102->hwmon_dev = hwmon_dev;
+	tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
 						     tmp102_read_temp, NULL);
 	if (IS_ERR(tmp102->tz))
 		tmp102->tz = NULL;
 
-	dev_info(&client->dev, "initialized\n");
+	dev_info(dev, "initialized\n");
 
 	return 0;
 
-fail_remove_sysfs:
-	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 fail_restore_config:
 	i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
 				     tmp102->config_orig);
@@ -238,9 +233,8 @@ static int tmp102_remove(struct i2c_client *client)
 {
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
-	thermal_zone_of_sensor_unregister(&client->dev, tmp102->tz);
+	thermal_zone_of_sensor_unregister(tmp102->hwmon_dev, tmp102->tz);
 	hwmon_device_unregister(tmp102->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 
 	/* Stop monitoring if device was stopped originally */
 	if (tmp102->config_orig & TMP102_CONF_SD) {
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index ae26b06fa819..7bab7a9bedc6 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -69,7 +69,7 @@ static const struct i2c_device_id tmp421_id[] = {
 MODULE_DEVICE_TABLE(i2c, tmp421_id);
 
 struct tmp421_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid;
 	unsigned long last_updated;
@@ -99,8 +99,8 @@ static int temp_from_u16(u16 reg)
 
 static struct tmp421_data *tmp421_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct tmp421_data *data = i2c_get_clientdata(client);
+	struct tmp421_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -198,6 +198,11 @@ static const struct attribute_group tmp421_group = {
 	.is_visible = tmp421_is_visible,
 };
 
+static const struct attribute_group *tmp421_groups[] = {
+	&tmp421_group,
+	NULL
+};
+
 static int tmp421_init_client(struct i2c_client *client)
 {
 	int config, config_orig;
@@ -264,47 +269,26 @@ static int tmp421_detect(struct i2c_client *client,
 static int tmp421_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct tmp421_data *data;
 	int err;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct tmp421_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct tmp421_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 	data->channels = id->driver_data;
+	data->client = client;
 
 	err = tmp421_init_client(client);
 	if (err)
 		return err;
 
-	err = sysfs_create_group(&client->dev.kobj, &tmp421_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		data->hwmon_dev = NULL;
-		goto exit_remove;
-	}
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &tmp421_group);
-	return err;
-}
-
-static int tmp421_remove(struct i2c_client *client)
-{
-	struct tmp421_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &tmp421_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, tmp421_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static struct i2c_driver tmp421_driver = {
@@ -313,7 +297,6 @@ static struct i2c_driver tmp421_driver = {
 		.name	= "tmp421",
 	},
 	.probe = tmp421_probe,
-	.remove = tmp421_remove,
 	.id_table = tmp421_id,
 	.detect = tmp421_detect,
 	.address_list = normal_i2c,
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 8fb46aab2d87..a04c49f2a011 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -416,6 +416,7 @@ config BLK_DEV_CY82C693
 
 config BLK_DEV_CS5520
 	tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)"
+	depends on X86_32 || COMPILE_TEST
 	select BLK_DEV_IDEDMA_PCI
 	help
 	  Include support for PIO tuning and virtual DMA on the Cyrix MediaGX
@@ -426,6 +427,7 @@ config BLK_DEV_CS5520
 
 config BLK_DEV_CS5530
 	tristate "Cyrix/National Semiconductor CS5530 MediaGX chipset support"
+	depends on X86_32 || COMPILE_TEST
 	select BLK_DEV_IDEDMA_PCI
 	help
 	  Include support for UDMA on the Cyrix MediaGX 5530 chipset. This
@@ -435,7 +437,7 @@ config BLK_DEV_CS5530
 
 config BLK_DEV_CS5535
 	tristate "AMD CS5535 chipset support"
-	depends on X86 && !X86_64
+	depends on X86_32
 	select BLK_DEV_IDEDMA_PCI
 	help
 	  Include support for UDMA on the NSC/AMD CS5535 companion chipset.
@@ -486,6 +488,7 @@ config BLK_DEV_JMICRON
 
 config BLK_DEV_SC1200
 	tristate "National SCx200 chipset support"
+	depends on X86_32 || COMPILE_TEST
 	select BLK_DEV_IDEDMA_PCI
 	help
 	  This driver adds support for the on-board IDE controller on the
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 16f69be820c7..ee880382e3bc 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -188,10 +188,9 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
 
 	ledtrig_ide_activity();
 
-	pr_debug("%s: %sing: block=%llu, sectors=%u, buffer=0x%08lx\n",
+	pr_debug("%s: %sing: block=%llu, sectors=%u\n",
 		 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
-		 (unsigned long long)block, blk_rq_sectors(rq),
-		 (unsigned long)rq->buffer);
+		 (unsigned long long)block, blk_rq_sectors(rq));
 
 	if (hwif->rw_disk)
 		hwif->rw_disk(drive, rq);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 2a744a91370e..a3d3b1733c49 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -853,8 +853,9 @@ static int init_irq (ide_hwif_t *hwif)
 	if (irq_handler == NULL)
 		irq_handler = ide_intr;
 
-	if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
-		goto out_up;
+	if (!host->get_lock)
+		if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
+			goto out_up;
 
 #if !defined(__mc68000__)
 	printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
@@ -1533,7 +1534,8 @@ static void ide_unregister(ide_hwif_t *hwif)
 
 	ide_proc_unregister_port(hwif);
 
-	free_irq(hwif->irq, hwif);
+	if (!hwif->host->get_lock)
+		free_irq(hwif->irq, hwif);
 
 	device_unregister(hwif->portdev);
 	device_unregister(&hwif->gendev);
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 02436d5d0dab..185452abf32c 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -173,12 +173,15 @@ static void start_ep_timer(struct c4iw_ep *ep)
 	add_timer(&ep->timer);
 }
 
-static void stop_ep_timer(struct c4iw_ep *ep)
+static int stop_ep_timer(struct c4iw_ep *ep)
 {
 	PDBG("%s ep %p stopping\n", __func__, ep);
 	del_timer_sync(&ep->timer);
-	if (!test_and_set_bit(TIMEOUT, &ep->com.flags))
+	if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
 		c4iw_put_ep(&ep->com);
+		return 0;
+	}
+	return 1;
 }
 
 static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb,
@@ -1165,12 +1168,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 
 	/*
-	 * Stop mpa timer.  If it expired, then the state has
-	 * changed and we bail since ep_timeout already aborted
-	 * the connection.
+	 * Stop mpa timer.  If it expired, then
+	 * we ignore the MPA reply.  process_timeout()
+	 * will abort the connection.
 	 */
-	stop_ep_timer(ep);
-	if (ep->com.state != MPA_REQ_SENT)
+	if (stop_ep_timer(ep))
 		return;
 
 	/*
@@ -1375,15 +1377,12 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 
-	if (ep->com.state != MPA_REQ_WAIT)
-		return;
-
 	/*
 	 * If we get more than the supported amount of private data
 	 * then we must fail this connection.
 	 */
 	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
@@ -1413,13 +1412,13 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 	if (mpa->revision > mpa_rev) {
 		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
 		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
 
 	if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) {
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
@@ -1430,7 +1429,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 	 * Fail if there's too much private data.
 	 */
 	if (plen > MPA_MAX_PRIVATE_DATA) {
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
@@ -1439,7 +1438,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 	 * If plen does not account for pkt size
 	 */
 	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
@@ -1496,18 +1495,24 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
 	     ep->mpa_attr.p2p_type);
 
-	__state_set(&ep->com, MPA_REQ_RCVD);
-	stop_ep_timer(ep);
-
-	/* drive upcall */
-	mutex_lock(&ep->parent_ep->com.mutex);
-	if (ep->parent_ep->com.state != DEAD) {
-		if (connect_request_upcall(ep))
+	/*
+	 * If the endpoint timer already expired, then we ignore
+	 * the start request.  process_timeout() will abort
+	 * the connection.
+	 */
+	if (!stop_ep_timer(ep)) {
+		__state_set(&ep->com, MPA_REQ_RCVD);
+
+		/* drive upcall */
+		mutex_lock(&ep->parent_ep->com.mutex);
+		if (ep->parent_ep->com.state != DEAD) {
+			if (connect_request_upcall(ep))
+				abort_connection(ep, skb, GFP_KERNEL);
+		} else {
 			abort_connection(ep, skb, GFP_KERNEL);
-	} else {
-		abort_connection(ep, skb, GFP_KERNEL);
+		}
+		mutex_unlock(&ep->parent_ep->com.mutex);
 	}
-	mutex_unlock(&ep->parent_ep->com.mutex);
 	return;
 }
 
@@ -2265,7 +2270,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
 		disconnect = 0;
 		break;
 	case MORIBUND:
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		if (ep->com.cm_id && ep->com.qp) {
 			attrs.next_state = C4IW_QP_STATE_IDLE;
 			c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
@@ -2325,10 +2330,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 	case CONNECTING:
 		break;
 	case MPA_REQ_WAIT:
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		break;
 	case MPA_REQ_SENT:
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1))
 			connect_reply_upcall(ep, -ECONNRESET);
 		else {
@@ -2433,7 +2438,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
 		__state_set(&ep->com, MORIBUND);
 		break;
 	case MORIBUND:
-		stop_ep_timer(ep);
+		(void)stop_ep_timer(ep);
 		if ((ep->com.cm_id) && (ep->com.qp)) {
 			attrs.next_state = C4IW_QP_STATE_IDLE;
 			c4iw_modify_qp(ep->com.qp->rhp,
@@ -3028,7 +3033,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
 		if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) {
 			close = 1;
 			if (abrupt) {
-				stop_ep_timer(ep);
+				(void)stop_ep_timer(ep);
 				ep->com.state = ABORTING;
 			} else
 				ep->com.state = MORIBUND;
@@ -3462,6 +3467,16 @@ static void process_timeout(struct c4iw_ep *ep)
 		__state_set(&ep->com, ABORTING);
 		close_complete_upcall(ep, -ETIMEDOUT);
 		break;
+	case ABORTING:
+	case DEAD:
+
+		/*
+		 * These states are expected if the ep timed out at the same
+		 * time as another thread was calling stop_ep_timer().
+		 * So we silently do nothing for these states.
+		 */
+		abort = 0;
+		break;
 	default:
 		WARN(1, "%s unexpected state ep %p tid %u state %u\n",
 			__func__, ep, ep->hwtid, ep->com.state);
@@ -3483,6 +3498,8 @@ static void process_timedout_eps(void)
 
 		tmp = timeout_list.next;
 		list_del(tmp);
+		tmp->next = NULL;
+		tmp->prev = NULL;
 		spin_unlock_irq(&timeout_lock);
 		ep = list_entry(tmp, struct c4iw_ep, entry);
 		process_timeout(ep);
@@ -3499,6 +3516,7 @@ static void process_work(struct work_struct *work)
 	unsigned int opcode;
 	int ret;
 
+	process_timedout_eps();
 	while ((skb = skb_dequeue(&rxq))) {
 		rpl = cplhdr(skb);
 		dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *)));
@@ -3508,8 +3526,8 @@ static void process_work(struct work_struct *work)
 		ret = work_handlers[opcode](dev, skb);
 		if (!ret)
 			kfree_skb(skb);
+		process_timedout_eps();
 	}
-	process_timedout_eps();
 }
 
 static DECLARE_WORK(skb_work, process_work);
@@ -3521,8 +3539,13 @@ static void ep_timeout(unsigned long arg)
 
 	spin_lock(&timeout_lock);
 	if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
-		list_add_tail(&ep->entry, &timeout_list);
-		kickit = 1;
+		/*
+		 * Only insert if it is not already on the list.
+		 */
+		if (!ep->entry.next) {
+			list_add_tail(&ep->entry, &timeout_list);
+			kickit = 1;
+		}
 	}
 	spin_unlock(&timeout_lock);
 	if (kickit)
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index ce468e542428..cfaa56ada189 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -235,27 +235,21 @@ int c4iw_flush_sq(struct c4iw_qp *qhp)
 	struct t4_cq *cq = &chp->cq;
 	int idx;
 	struct t4_swsqe *swsqe;
-	int error = (qhp->attr.state != C4IW_QP_STATE_CLOSING &&
-			qhp->attr.state != C4IW_QP_STATE_IDLE);
 
 	if (wq->sq.flush_cidx == -1)
 		wq->sq.flush_cidx = wq->sq.cidx;
 	idx = wq->sq.flush_cidx;
 	BUG_ON(idx >= wq->sq.size);
 	while (idx != wq->sq.pidx) {
-		if (error) {
-			swsqe = &wq->sq.sw_sq[idx];
-			BUG_ON(swsqe->flushed);
-			swsqe->flushed = 1;
-			insert_sq_cqe(wq, cq, swsqe);
-			if (wq->sq.oldest_read == swsqe) {
-				BUG_ON(swsqe->opcode != FW_RI_READ_REQ);
-				advance_oldest_read(wq);
-			}
-			flushed++;
-		} else {
-			t4_sq_consume(wq);
+		swsqe = &wq->sq.sw_sq[idx];
+		BUG_ON(swsqe->flushed);
+		swsqe->flushed = 1;
+		insert_sq_cqe(wq, cq, swsqe);
+		if (wq->sq.oldest_read == swsqe) {
+			BUG_ON(swsqe->opcode != FW_RI_READ_REQ);
+			advance_oldest_read(wq);
 		}
+		flushed++;
 		if (++idx == wq->sq.size)
 			idx = 0;
 	}
@@ -678,7 +672,7 @@ skip_cqe:
 static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
 {
 	struct c4iw_qp *qhp = NULL;
-	struct t4_cqe cqe = {0, 0}, *rd_cqe;
+	struct t4_cqe uninitialized_var(cqe), *rd_cqe;
 	struct t4_wq *wq;
 	u32 credit = 0;
 	u8 cqe_flushed;
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 9489a388376c..f4fa50a609e2 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -682,7 +682,10 @@ static void c4iw_dealloc(struct uld_ctx *ctx)
 	idr_destroy(&ctx->dev->hwtid_idr);
 	idr_destroy(&ctx->dev->stid_idr);
 	idr_destroy(&ctx->dev->atid_idr);
-	iounmap(ctx->dev->rdev.oc_mw_kva);
+	if (ctx->dev->rdev.bar2_kva)
+		iounmap(ctx->dev->rdev.bar2_kva);
+	if (ctx->dev->rdev.oc_mw_kva)
+		iounmap(ctx->dev->rdev.oc_mw_kva);
 	ib_dealloc_device(&ctx->dev->ibdev);
 	ctx->dev = NULL;
 }
@@ -722,11 +725,31 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
 	}
 	devp->rdev.lldi = *infop;
 
-	devp->rdev.oc_mw_pa = pci_resource_start(devp->rdev.lldi.pdev, 2) +
-		(pci_resource_len(devp->rdev.lldi.pdev, 2) -
-		 roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size));
-	devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa,
-					       devp->rdev.lldi.vr->ocq.size);
+	/*
+	 * For T5 devices, we map all of BAR2 with WC.
+	 * For T4 devices with onchip qp mem, we map only that part
+	 * of BAR2 with WC.
+	 */
+	devp->rdev.bar2_pa = pci_resource_start(devp->rdev.lldi.pdev, 2);
+	if (is_t5(devp->rdev.lldi.adapter_type)) {
+		devp->rdev.bar2_kva = ioremap_wc(devp->rdev.bar2_pa,
+			pci_resource_len(devp->rdev.lldi.pdev, 2));
+		if (!devp->rdev.bar2_kva) {
+			pr_err(MOD "Unable to ioremap BAR2\n");
+			return ERR_PTR(-EINVAL);
+		}
+	} else if (ocqp_supported(infop)) {
+		devp->rdev.oc_mw_pa =
+			pci_resource_start(devp->rdev.lldi.pdev, 2) +
+			pci_resource_len(devp->rdev.lldi.pdev, 2) -
+			roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size);
+		devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa,
+			devp->rdev.lldi.vr->ocq.size);
+		if (!devp->rdev.oc_mw_kva) {
+			pr_err(MOD "Unable to ioremap onchip mem\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
 
 	PDBG(KERN_INFO MOD "ocq memory: "
 	       "hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n",
@@ -1003,9 +1026,11 @@ static int enable_qp_db(int id, void *p, void *data)
 static void resume_rc_qp(struct c4iw_qp *qp)
 {
 	spin_lock(&qp->lock);
-	t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc);
+	t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc,
+		      is_t5(qp->rhp->rdev.lldi.adapter_type), NULL);
 	qp->wq.sq.wq_pidx_inc = 0;
-	t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc);
+	t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc,
+		      is_t5(qp->rhp->rdev.lldi.adapter_type), NULL);
 	qp->wq.rq.wq_pidx_inc = 0;
 	spin_unlock(&qp->lock);
 }
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index e872203c5424..7b8c5806a09d 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -149,6 +149,8 @@ struct c4iw_rdev {
 	struct gen_pool *ocqp_pool;
 	u32 flags;
 	struct cxgb4_lld_info lldi;
+	unsigned long bar2_pa;
+	void __iomem *bar2_kva;
 	unsigned long oc_mw_pa;
 	void __iomem *oc_mw_kva;
 	struct c4iw_stats stats;
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index f9ca072a99ed..ec7a2988a703 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -259,8 +259,12 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
 
 	if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
 		stag_idx = c4iw_get_resource(&rdev->resource.tpt_table);
-		if (!stag_idx)
+		if (!stag_idx) {
+			mutex_lock(&rdev->stats.lock);
+			rdev->stats.stag.fail++;
+			mutex_unlock(&rdev->stats.lock);
 			return -ENOMEM;
+		}
 		mutex_lock(&rdev->stats.lock);
 		rdev->stats.stag.cur += 32;
 		if (rdev->stats.stag.cur > rdev->stats.stag.max)
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 79429256023a..a94a3e12c349 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -328,7 +328,7 @@ static int c4iw_query_device(struct ib_device *ibdev,
 	props->max_mr = c4iw_num_stags(&dev->rdev);
 	props->max_pd = T4_MAX_NUM_PD;
 	props->local_ca_ack_delay = 0;
-	props->max_fast_reg_page_list_len = T4_MAX_FR_DEPTH;
+	props->max_fast_reg_page_list_len = t4_max_fr_depth(use_dsgl);
 
 	return 0;
 }
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index cb76eb5eee1f..7b5114cb486f 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -212,13 +212,23 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 
 	wq->db = rdev->lldi.db_reg;
 	wq->gts = rdev->lldi.gts_reg;
-	if (user) {
-		wq->sq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) +
-					(wq->sq.qid << rdev->qpshift);
-		wq->sq.udb &= PAGE_MASK;
-		wq->rq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) +
-					(wq->rq.qid << rdev->qpshift);
-		wq->rq.udb &= PAGE_MASK;
+	if (user || is_t5(rdev->lldi.adapter_type)) {
+		u32 off;
+
+		off = (wq->sq.qid << rdev->qpshift) & PAGE_MASK;
+		if (user) {
+			wq->sq.udb = (u64 __iomem *)(rdev->bar2_pa + off);
+		} else {
+			off += 128 * (wq->sq.qid & rdev->qpmask) + 8;
+			wq->sq.udb = (u64 __iomem *)(rdev->bar2_kva + off);
+		}
+		off = (wq->rq.qid << rdev->qpshift) & PAGE_MASK;
+		if (user) {
+			wq->rq.udb = (u64 __iomem *)(rdev->bar2_pa + off);
+		} else {
+			off += 128 * (wq->rq.qid & rdev->qpmask) + 8;
+			wq->rq.udb = (u64 __iomem *)(rdev->bar2_kva + off);
+		}
 	}
 	wq->rdev = rdev;
 	wq->rq.msn = 1;
@@ -299,9 +309,10 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 	if (ret)
 		goto free_dma;
 
-	PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%llx rqudb 0x%llx\n",
+	PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%lx rqudb 0x%lx\n",
 	     __func__, wq->sq.qid, wq->rq.qid, wq->db,
-	     (unsigned long long)wq->sq.udb, (unsigned long long)wq->rq.udb);
+	     (__force unsigned long) wq->sq.udb,
+	     (__force unsigned long) wq->rq.udb);
 
 	return 0;
 free_dma:
@@ -425,6 +436,8 @@ static int build_rdma_send(struct t4_sq *sq, union t4_wr *wqe,
 	default:
 		return -EINVAL;
 	}
+	wqe->send.r3 = 0;
+	wqe->send.r4 = 0;
 
 	plen = 0;
 	if (wr->num_sge) {
@@ -555,7 +568,8 @@ static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
 	int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32);
 	int rem;
 
-	if (wr->wr.fast_reg.page_list_len > T4_MAX_FR_DEPTH)
+	if (wr->wr.fast_reg.page_list_len >
+	    t4_max_fr_depth(use_dsgl))
 		return -EINVAL;
 
 	wqe->fr.qpbinde_to_dcacpu = 0;
@@ -650,9 +664,10 @@ static int ring_kernel_sq_db(struct c4iw_qp *qhp, u16 inc)
 
 	spin_lock_irqsave(&qhp->rhp->lock, flags);
 	spin_lock(&qhp->lock);
-	if (qhp->rhp->db_state == NORMAL) {
-		t4_ring_sq_db(&qhp->wq, inc);
-	} else {
+	if (qhp->rhp->db_state == NORMAL)
+		t4_ring_sq_db(&qhp->wq, inc,
+			      is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
+	else {
 		add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
 		qhp->wq.sq.wq_pidx_inc += inc;
 	}
@@ -667,9 +682,10 @@ static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc)
 
 	spin_lock_irqsave(&qhp->rhp->lock, flags);
 	spin_lock(&qhp->lock);
-	if (qhp->rhp->db_state == NORMAL) {
-		t4_ring_rq_db(&qhp->wq, inc);
-	} else {
+	if (qhp->rhp->db_state == NORMAL)
+		t4_ring_rq_db(&qhp->wq, inc,
+			      is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
+	else {
 		add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
 		qhp->wq.rq.wq_pidx_inc += inc;
 	}
@@ -686,7 +702,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 	enum fw_wr_opcodes fw_opcode = 0;
 	enum fw_ri_wr_flags fw_flags;
 	struct c4iw_qp *qhp;
-	union t4_wr *wqe;
+	union t4_wr *wqe = NULL;
 	u32 num_wrs;
 	struct t4_swsqe *swsqe;
 	unsigned long flag;
@@ -792,7 +808,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
 	}
 	if (!qhp->rhp->rdev.status_page->db_off) {
-		t4_ring_sq_db(&qhp->wq, idx);
+		t4_ring_sq_db(&qhp->wq, idx,
+			      is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
 		spin_unlock_irqrestore(&qhp->lock, flag);
 	} else {
 		spin_unlock_irqrestore(&qhp->lock, flag);
@@ -806,7 +823,7 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 {
 	int err = 0;
 	struct c4iw_qp *qhp;
-	union t4_recv_wr *wqe;
+	union t4_recv_wr *wqe = NULL;
 	u32 num_wrs;
 	u8 len16 = 0;
 	unsigned long flag;
@@ -858,7 +875,8 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 		num_wrs--;
 	}
 	if (!qhp->rhp->rdev.status_page->db_off) {
-		t4_ring_rq_db(&qhp->wq, idx);
+		t4_ring_rq_db(&qhp->wq, idx,
+			      is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
 		spin_unlock_irqrestore(&qhp->lock, flag);
 	} else {
 		spin_unlock_irqrestore(&qhp->lock, flag);
@@ -1352,6 +1370,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 		switch (attrs->next_state) {
 		case C4IW_QP_STATE_CLOSING:
 			BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
+			t4_set_wq_in_error(&qhp->wq);
 			set_state(qhp, C4IW_QP_STATE_CLOSING);
 			ep = qhp->ep;
 			if (!internal) {
@@ -1359,18 +1378,18 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 				disconnect = 1;
 				c4iw_get_ep(&qhp->ep->com);
 			}
-			t4_set_wq_in_error(&qhp->wq);
 			ret = rdma_fini(rhp, qhp, ep);
 			if (ret)
 				goto err;
 			break;
 		case C4IW_QP_STATE_TERMINATE:
+			t4_set_wq_in_error(&qhp->wq);
 			set_state(qhp, C4IW_QP_STATE_TERMINATE);
 			qhp->attr.layer_etype = attrs->layer_etype;
 			qhp->attr.ecode = attrs->ecode;
-			t4_set_wq_in_error(&qhp->wq);
 			ep = qhp->ep;
 			disconnect = 1;
+			c4iw_get_ep(&qhp->ep->com);
 			if (!internal)
 				terminate = 1;
 			else {
@@ -1378,11 +1397,10 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 				if (ret)
 					goto err;
 			}
-			c4iw_get_ep(&qhp->ep->com);
 			break;
 		case C4IW_QP_STATE_ERROR:
-			set_state(qhp, C4IW_QP_STATE_ERROR);
 			t4_set_wq_in_error(&qhp->wq);
+			set_state(qhp, C4IW_QP_STATE_ERROR);
 			if (!internal) {
 				abort = 1;
 				disconnect = 1;
@@ -1677,11 +1695,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
 		mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize);
 		insert_mmap(ucontext, mm2);
 		mm3->key = uresp.sq_db_gts_key;
-		mm3->addr = qhp->wq.sq.udb;
+		mm3->addr = (__force unsigned long) qhp->wq.sq.udb;
 		mm3->len = PAGE_SIZE;
 		insert_mmap(ucontext, mm3);
 		mm4->key = uresp.rq_db_gts_key;
-		mm4->addr = qhp->wq.rq.udb;
+		mm4->addr = (__force unsigned long) qhp->wq.rq.udb;
 		mm4->len = PAGE_SIZE;
 		insert_mmap(ucontext, mm4);
 		if (mm5) {
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index cdef4d7fb6d8..67df71a7012e 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -179,8 +179,12 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
 		kfree(entry);
 	} else {
 		qid = c4iw_get_resource(&rdev->resource.qid_table);
-		if (!qid)
+		if (!qid) {
+			mutex_lock(&rdev->stats.lock);
+			rdev->stats.qid.fail++;
+			mutex_unlock(&rdev->stats.lock);
 			goto out;
+		}
 		mutex_lock(&rdev->stats.lock);
 		rdev->stats.qid.cur += rdev->qpmask + 1;
 		mutex_unlock(&rdev->stats.lock);
@@ -322,8 +326,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
 	unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6);
 	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
 	if (!addr)
-		printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
-		       pci_name(rdev->lldi.pdev));
+		pr_warn_ratelimited(MOD "%s: Out of RQT memory\n",
+				    pci_name(rdev->lldi.pdev));
 	mutex_lock(&rdev->stats.lock);
 	if (addr) {
 		rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index eeca8b1e6376..2178f3198410 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -84,7 +84,14 @@ struct t4_status_page {
 			sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge))
 #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \
 			sizeof(struct fw_ri_immd)) & ~31UL)
-#define T4_MAX_FR_DEPTH (1024 / sizeof(u64))
+#define T4_MAX_FR_IMMD_DEPTH (T4_MAX_FR_IMMD / sizeof(u64))
+#define T4_MAX_FR_DSGL 1024
+#define T4_MAX_FR_DSGL_DEPTH (T4_MAX_FR_DSGL / sizeof(u64))
+
+static inline int t4_max_fr_depth(int use_dsgl)
+{
+	return use_dsgl ? T4_MAX_FR_DSGL_DEPTH : T4_MAX_FR_IMMD_DEPTH;
+}
 
 #define T4_RQ_NUM_SLOTS 2
 #define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS)
@@ -292,7 +299,7 @@ struct t4_sq {
 	unsigned long phys_addr;
 	struct t4_swsqe *sw_sq;
 	struct t4_swsqe *oldest_read;
-	u64 udb;
+	u64 __iomem *udb;
 	size_t memsize;
 	u32 qid;
 	u16 in_use;
@@ -314,7 +321,7 @@ struct t4_rq {
 	dma_addr_t dma_addr;
 	DEFINE_DMA_UNMAP_ADDR(mapping);
 	struct t4_swrqe *sw_rq;
-	u64 udb;
+	u64 __iomem *udb;
 	size_t memsize;
 	u32 qid;
 	u32 msn;
@@ -435,15 +442,67 @@ static inline u16 t4_sq_wq_size(struct t4_wq *wq)
 		return wq->sq.size * T4_SQ_NUM_SLOTS;
 }
 
-static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc)
+/* This function copies 64 byte coalesced work request to memory
+ * mapped BAR2 space. For coalesced WRs, the SGE fetches data
+ * from the FIFO instead of from Host.
+ */
+static inline void pio_copy(u64 __iomem *dst, u64 *src)
+{
+	int count = 8;
+
+	while (count) {
+		writeq(*src, dst);
+		src++;
+		dst++;
+		count--;
+	}
+}
+
+static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5,
+				 union t4_wr *wqe)
 {
+
+	/* Flush host queue memory writes. */
 	wmb();
+	if (t5) {
+		if (inc == 1 && wqe) {
+			PDBG("%s: WC wq->sq.pidx = %d\n",
+			     __func__, wq->sq.pidx);
+			pio_copy(wq->sq.udb + 7, (void *)wqe);
+		} else {
+			PDBG("%s: DB wq->sq.pidx = %d\n",
+			     __func__, wq->sq.pidx);
+			writel(PIDX_T5(inc), wq->sq.udb);
+		}
+
+		/* Flush user doorbell area writes. */
+		wmb();
+		return;
+	}
 	writel(QID(wq->sq.qid) | PIDX(inc), wq->db);
 }
 
-static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc)
+static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5,
+				 union t4_recv_wr *wqe)
 {
+
+	/* Flush host queue memory writes. */
 	wmb();
+	if (t5) {
+		if (inc == 1 && wqe) {
+			PDBG("%s: WC wq->rq.pidx = %d\n",
+			     __func__, wq->rq.pidx);
+			pio_copy(wq->rq.udb + 7, (void *)wqe);
+		} else {
+			PDBG("%s: DB wq->rq.pidx = %d\n",
+			     __func__, wq->rq.pidx);
+			writel(PIDX_T5(inc), wq->rq.udb);
+		}
+
+		/* Flush user doorbell area writes. */
+		wmb();
+		return;
+	}
 	writel(QID(wq->rq.qid) | PIDX(inc), wq->db);
 }
 
@@ -568,6 +627,9 @@ static inline int t4_next_hw_cqe(struct t4_cq *cq, struct t4_cqe **cqe)
 		printk(KERN_ERR MOD "cq overflow cqid %u\n", cq->cqid);
 		BUG_ON(1);
 	} else if (t4_valid_cqe(cq, &cq->queue[cq->cidx])) {
+
+		/* Ensure CQE is flushed to memory */
+		rmb();
 		*cqe = &cq->queue[cq->cidx];
 		ret = 0;
 	} else
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index fa6dc870adae..364d4b6937f5 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -282,6 +282,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
 		props->sig_guard_cap = IB_GUARD_T10DIF_CRC |
 				       IB_GUARD_T10DIF_CSUM;
 	}
+	if (flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)
+		props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
 
 	props->vendor_id	   = be32_to_cpup((__be32 *)(out_mad->data + 36)) &
 		0xffffff;
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index ae788d27b93f..dc930ed21eca 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -807,6 +807,15 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 	spin_lock_init(&qp->sq.lock);
 	spin_lock_init(&qp->rq.lock);
 
+	if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
+		if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) {
+			mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
+			return -EINVAL;
+		} else {
+			qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK;
+		}
+	}
+
 	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
 		qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE;
 
@@ -878,6 +887,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 	if (qp->wq_sig)
 		in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_ENABLE_SIG);
 
+	if (qp->flags & MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK)
+		in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_BLOCK_MCAST);
+
 	if (qp->scat_cqe && is_connected(init_attr->qp_type)) {
 		int rcqe_sz;
 		int scqe_sz;
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 87897b95666d..ded76c101dde 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -858,13 +858,9 @@ static int mthca_enable_msi_x(struct mthca_dev *mdev)
 	entries[1].entry = 1;
 	entries[2].entry = 2;
 
-	err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries));
-	if (err) {
-		if (err > 0)
-			mthca_info(mdev, "Only %d MSI-X vectors available, "
-				   "not using MSI-X\n", err);
+	err = pci_enable_msix_exact(mdev->pdev, entries, ARRAY_SIZE(entries));
+	if (err)
 		return err;
-	}
 
 	mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector;
 	mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector;
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index c8d9c4ab142b..61a0046efb76 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -197,46 +197,47 @@ static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt,
 			   struct qib_msix_entry *qib_msix_entry)
 {
 	int ret;
-	u32 tabsize = 0;
-	u16 msix_flags;
+	int nvec = *msixcnt;
 	struct msix_entry *msix_entry;
 	int i;
 
+	ret = pci_msix_vec_count(dd->pcidev);
+	if (ret < 0)
+		goto do_intx;
+
+	nvec = min(nvec, ret);
+
 	/* We can't pass qib_msix_entry array to qib_msix_setup
 	 * so use a dummy msix_entry array and copy the allocated
 	 * irq back to the qib_msix_entry array. */
-	msix_entry = kmalloc(*msixcnt * sizeof(*msix_entry), GFP_KERNEL);
-	if (!msix_entry) {
-		ret = -ENOMEM;
+	msix_entry = kmalloc(nvec * sizeof(*msix_entry), GFP_KERNEL);
+	if (!msix_entry)
 		goto do_intx;
-	}
-	for (i = 0; i < *msixcnt; i++)
+
+	for (i = 0; i < nvec; i++)
 		msix_entry[i] = qib_msix_entry[i].msix;
 
-	pci_read_config_word(dd->pcidev, pos + PCI_MSIX_FLAGS, &msix_flags);
-	tabsize = 1 + (msix_flags & PCI_MSIX_FLAGS_QSIZE);
-	if (tabsize > *msixcnt)
-		tabsize = *msixcnt;
-	ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize);
-	if (ret > 0) {
-		tabsize = ret;
-		ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize);
-	}
-do_intx:
-	if (ret) {
-		qib_dev_err(dd,
-			"pci_enable_msix %d vectors failed: %d, falling back to INTx\n",
-			tabsize, ret);
-		tabsize = 0;
-	}
-	for (i = 0; i < tabsize; i++)
+	ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec);
+	if (ret < 0)
+		goto free_msix_entry;
+	else
+		nvec = ret;
+
+	for (i = 0; i < nvec; i++)
 		qib_msix_entry[i].msix = msix_entry[i];
+
 	kfree(msix_entry);
-	*msixcnt = tabsize;
+	*msixcnt = nvec;
+	return;
 
-	if (ret)
-		qib_enable_intx(dd->pcidev);
+free_msix_entry:
+	kfree(msix_entry);
 
+do_intx:
+	qib_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, "
+			"falling back to INTx\n", nvec, ret);
+	*msixcnt = 0;
+	qib_enable_intx(dd->pcidev);
 }
 
 /**
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index a11ff74a5127..9eac8de9e8b7 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -178,6 +178,15 @@ comment "Input Device Drivers"
 
 source "drivers/input/keyboard/Kconfig"
 
+config INPUT_LEDS
+	bool "LED Support"
+	depends on LEDS_CLASS = INPUT || LEDS_CLASS = y
+	select LEDS_TRIGGERS
+	default y
+	help
+	  This option enables support for LEDs on keyboards managed
+	  by the input layer.
+
 source "drivers/input/mouse/Kconfig"
 
 source "drivers/input/joystick/Kconfig"
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 5ca3f631497f..2ab5f3336da5 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -6,6 +6,9 @@
 
 obj-$(CONFIG_INPUT)		+= input-core.o
 input-core-y := input.o input-compat.o input-mt.o ff-core.o
+ifeq ($(CONFIG_INPUT_LEDS),y)
+input-core-y += leds.o
+endif
 
 obj-$(CONFIG_INPUT_FF_MEMLESS)	+= ff-memless.o
 obj-$(CONFIG_INPUT_POLLDEV)	+= input-polldev.o
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 1c4c0db05550..3b9284b18e70 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -708,6 +708,9 @@ static void input_disconnect_device(struct input_dev *dev)
 		handle->open = 0;
 
 	spin_unlock_irq(&dev->event_lock);
+
+	if (is_event_supported(EV_LED, dev->evbit, EV_MAX))
+		input_led_disconnect(dev);
 }
 
 /**
@@ -2134,6 +2137,9 @@ int input_register_device(struct input_dev *dev)
 
 	list_add_tail(&dev->node, &input_dev_list);
 
+	if (is_event_supported(EV_LED, dev->evbit, EV_MAX))
+		input_led_connect(dev);
+
 	list_for_each_entry(handler, &input_handler_list, node)
 		input_attach_handler(dev, handler);
 
diff --git a/drivers/input/leds.c b/drivers/input/leds.c
new file mode 100644
index 000000000000..985fa7ebeec7
--- /dev/null
+++ b/drivers/input/leds.c
@@ -0,0 +1,249 @@
+/*
+ * LED support for the input layer
+ *
+ * Copyright 2010-2014 Samuel Thibault <samuel.thibault@ens-lyon.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+
+/*
+ * Keyboard LEDs are propagated by default like the following example:
+ *
+ * VT keyboard numlock trigger
+ * -> vt::numl VT LED
+ * -> vt-numl VT trigger
+ * -> per-device inputX::numl LED
+ *
+ * Userland can however choose the trigger for the vt::numl LED, or
+ * independently choose the trigger for any inputx::numl LED.
+ *
+ *
+ * VT LED classes and triggers are registered on-demand according to
+ * existing LED devices
+ */
+
+/* Handler for VT LEDs, just triggers the corresponding VT trigger. */
+static void vt_led_set(struct led_classdev *cdev,
+			  enum led_brightness brightness);
+static struct led_classdev vt_leds[LED_CNT] = {
+#define DEFINE_INPUT_LED(vt_led, nam, deftrig) \
+	[vt_led] = { \
+		.name = "vt::"nam, \
+		.max_brightness = 1, \
+		.brightness_set = vt_led_set, \
+		.default_trigger = deftrig, \
+	}
+/* Default triggers for the VT LEDs just correspond to the legacy
+ * usage. */
+	DEFINE_INPUT_LED(LED_NUML, "numl", "kbd-numlock"),
+	DEFINE_INPUT_LED(LED_CAPSL, "capsl", "kbd-capslock"),
+	DEFINE_INPUT_LED(LED_SCROLLL, "scrolll", "kbd-scrollock"),
+	DEFINE_INPUT_LED(LED_COMPOSE, "compose", NULL),
+	DEFINE_INPUT_LED(LED_KANA, "kana", "kbd-kanalock"),
+	DEFINE_INPUT_LED(LED_SLEEP, "sleep", NULL),
+	DEFINE_INPUT_LED(LED_SUSPEND, "suspend", NULL),
+	DEFINE_INPUT_LED(LED_MUTE, "mute", NULL),
+	DEFINE_INPUT_LED(LED_MISC, "misc", NULL),
+	DEFINE_INPUT_LED(LED_MAIL, "mail", NULL),
+	DEFINE_INPUT_LED(LED_CHARGING, "charging", NULL),
+};
+static const char *const vt_led_names[LED_CNT] = {
+	[LED_NUML] = "numl",
+	[LED_CAPSL] = "capsl",
+	[LED_SCROLLL] = "scrolll",
+	[LED_COMPOSE] = "compose",
+	[LED_KANA] = "kana",
+	[LED_SLEEP] = "sleep",
+	[LED_SUSPEND] = "suspend",
+	[LED_MUTE] = "mute",
+	[LED_MISC] = "misc",
+	[LED_MAIL] = "mail",
+	[LED_CHARGING] = "charging",
+};
+/* Handler for hotplug initialization */
+static void vt_led_trigger_activate(struct led_classdev *cdev);
+/* VT triggers */
+static struct led_trigger vt_led_triggers[LED_CNT] = {
+#define DEFINE_INPUT_LED_TRIGGER(vt_led, nam) \
+	[vt_led] = { \
+		.name = "vt-"nam, \
+		.activate = vt_led_trigger_activate, \
+	}
+	DEFINE_INPUT_LED_TRIGGER(LED_NUML, "numl"),
+	DEFINE_INPUT_LED_TRIGGER(LED_CAPSL, "capsl"),
+	DEFINE_INPUT_LED_TRIGGER(LED_SCROLLL, "scrolll"),
+	DEFINE_INPUT_LED_TRIGGER(LED_COMPOSE, "compose"),
+	DEFINE_INPUT_LED_TRIGGER(LED_KANA, "kana"),
+	DEFINE_INPUT_LED_TRIGGER(LED_SLEEP, "sleep"),
+	DEFINE_INPUT_LED_TRIGGER(LED_SUSPEND, "suspend"),
+	DEFINE_INPUT_LED_TRIGGER(LED_MUTE, "mute"),
+	DEFINE_INPUT_LED_TRIGGER(LED_MISC, "misc"),
+	DEFINE_INPUT_LED_TRIGGER(LED_MAIL, "mail"),
+	DEFINE_INPUT_LED_TRIGGER(LED_CHARGING, "charging"),
+};
+
+/* Lock for registration coherency */
+static DEFINE_MUTEX(vt_led_registered_lock);
+
+/* Which VT LED classes and triggers are registered */
+static unsigned long vt_led_registered[BITS_TO_LONGS(LED_CNT)];
+
+/* Number of input devices having each LED */
+static int vt_led_references[LED_CNT];
+
+/* VT LED state change, tell the VT trigger.  */
+static void vt_led_set(struct led_classdev *cdev,
+			  enum led_brightness brightness)
+{
+	int led = cdev - vt_leds;
+
+	led_trigger_event(&vt_led_triggers[led], !!brightness);
+}
+
+/* LED state change for some keyboard, notify that keyboard.  */
+static void perdevice_input_led_set(struct led_classdev *cdev,
+			  enum led_brightness brightness)
+{
+	struct input_dev *dev;
+	struct led_classdev *leds;
+	int led;
+
+	dev = cdev->dev->platform_data;
+	if (!dev)
+		/* Still initializing */
+		return;
+	leds = dev->leds;
+	led = cdev - leds;
+
+	input_event(dev, EV_LED, led, !!brightness);
+	input_event(dev, EV_SYN, SYN_REPORT, 0);
+}
+
+/* Keyboard hotplug, initialize its LED status */
+static void vt_led_trigger_activate(struct led_classdev *cdev)
+{
+	struct led_trigger *trigger = cdev->trigger;
+	int led = trigger - vt_led_triggers;
+
+	if (cdev->brightness_set)
+		cdev->brightness_set(cdev, vt_leds[led].brightness);
+}
+
+/* Free led stuff from input device, used at abortion and disconnection.  */
+static void input_led_delete(struct input_dev *dev)
+{
+	if (dev) {
+		struct led_classdev *leds = dev->leds;
+		if (leds) {
+			int i;
+			for (i = 0; i < LED_CNT; i++)
+				kfree(leds[i].name);
+			kfree(leds);
+			dev->leds = NULL;
+		}
+	}
+}
+
+/* A new input device with potential LEDs to connect.  */
+int input_led_connect(struct input_dev *dev)
+{
+	int i, error = 0;
+	struct led_classdev *leds;
+
+	dev->leds = leds = kcalloc(LED_CNT, sizeof(*leds), GFP_KERNEL);
+	if (!dev->leds)
+		return -ENOMEM;
+
+	/* lazily register missing VT LEDs */
+	mutex_lock(&vt_led_registered_lock);
+	for (i = 0; i < LED_CNT; i++)
+		if (vt_leds[i].name && test_bit(i, dev->ledbit)) {
+			if (!vt_led_references[i]) {
+				led_trigger_register(&vt_led_triggers[i]);
+				/* This keyboard is first to have led i,
+				 * try to register it */
+				if (!led_classdev_register(NULL, &vt_leds[i]))
+					vt_led_references[i] = 1;
+				else
+					led_trigger_unregister(&vt_led_triggers[i]);
+			} else
+				vt_led_references[i]++;
+		}
+	mutex_unlock(&vt_led_registered_lock);
+
+	/* and register this device's LEDs */
+	for (i = 0; i < LED_CNT; i++)
+		if (vt_leds[i].name && test_bit(i, dev->ledbit)) {
+			leds[i].name = kasprintf(GFP_KERNEL, "%s::%s",
+						dev_name(&dev->dev),
+						vt_led_names[i]);
+			if (!leds[i].name) {
+				error = -ENOMEM;
+				goto err;
+			}
+			leds[i].max_brightness = 1;
+			leds[i].brightness_set = perdevice_input_led_set;
+			leds[i].default_trigger = vt_led_triggers[i].name;
+		}
+
+	/* No issue so far, we can register for real.  */
+	for (i = 0; i < LED_CNT; i++)
+		if (leds[i].name) {
+			led_classdev_register(&dev->dev, &leds[i]);
+			leds[i].dev->platform_data = dev;
+			perdevice_input_led_set(&leds[i],
+					vt_leds[i].brightness);
+		}
+
+	return 0;
+
+err:
+	input_led_delete(dev);
+	return error;
+}
+
+/*
+ * Disconnected input device. Clean it, and deregister now-useless VT LEDs
+ * and triggers.
+ */
+void input_led_disconnect(struct input_dev *dev)
+{
+	int i;
+	struct led_classdev *leds = dev->leds;
+
+	for (i = 0; i < LED_CNT; i++)
+		if (leds[i].name)
+			led_classdev_unregister(&leds[i]);
+
+	input_led_delete(dev);
+
+	mutex_lock(&vt_led_registered_lock);
+	for (i = 0; i < LED_CNT; i++) {
+		if (!vt_leds[i].name || !test_bit(i, dev->ledbit))
+			continue;
+
+		vt_led_references[i]--;
+		if (vt_led_references[i]) {
+			/* Still some devices needing it */
+			continue;
+		}
+
+		led_classdev_unregister(&vt_leds[i]);
+		led_trigger_unregister(&vt_led_triggers[i]);
+		clear_bit(i, vt_led_registered);
+	}
+	mutex_unlock(&vt_led_registered_lock);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("User LED support for input layer");
+MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>");
diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
index 4b11ede34950..4765799fef74 100644
--- a/drivers/input/misc/da9055_onkey.c
+++ b/drivers/input/misc/da9055_onkey.c
@@ -109,7 +109,6 @@ static int da9055_onkey_probe(struct platform_device *pdev)
 
 	INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work);
 
-	irq = regmap_irq_get_virq(da9055->irq_data, irq);
 	err = request_threaded_irq(irq, NULL, da9055_onkey_irq,
 				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 				   "ONKEY", onkey);
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index f445c10df8df..39f8b717fe84 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -152,7 +152,8 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event)
 	info->seg = pci_domain_nr(dev->bus);
 	info->level = level;
 	if (event == BUS_NOTIFY_ADD_DEVICE) {
-		for (tmp = dev, level--; tmp; tmp = tmp->bus->self) {
+		for (tmp = dev; tmp; tmp = tmp->bus->self) {
+			level--;
 			info->path[level].device = PCI_SLOT(tmp->devfn);
 			info->path[level].function = PCI_FUNC(tmp->devfn);
 			if (pci_is_root_bus(tmp->bus))
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 69fa7da5e48b..f256ffc02e29 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1009,11 +1009,13 @@ static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
 	if (level == 1)
 		return freelist;
 
-	for (pte = page_address(pg); !first_pte_in_page(pte); pte++) {
+	pte = page_address(pg);
+	do {
 		if (dma_pte_present(pte) && !dma_pte_superpage(pte))
 			freelist = dma_pte_list_pagetables(domain, level - 1,
 							   pte, freelist);
-	}
+		pte++;
+	} while (!first_pte_in_page(pte));
 
 	return freelist;
 }
@@ -2235,7 +2237,9 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
 				bridge_devfn = dev_tmp->devfn;
 			}
 			spin_lock_irqsave(&device_domain_lock, flags);
-			info = dmar_search_domain_by_dev_info(segment, bus, devfn);
+			info = dmar_search_domain_by_dev_info(segment,
+							      bridge_bus,
+							      bridge_devfn);
 			if (info) {
 				iommu = info->iommu;
 				domain = info->domain;
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 37dab0b472cd..7d35287f9e90 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -228,12 +229,17 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
 static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc)
 {
 	u32 stat, hwirq;
+	struct irq_chip *host_chip = irq_desc_get_chip(desc);
 	struct vic_device *vic = irq_desc_get_handler_data(desc);
 
+	chained_irq_enter(host_chip, desc);
+
 	while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
 		hwirq = ffs(stat) - 1;
 		generic_handle_irq(irq_find_mapping(vic->domain, hwirq));
 	}
+
+	chained_irq_exit(host_chip, desc);
 }
 
 /*
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 53d487f0c79d..6a7447c304ac 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1155,7 +1155,7 @@ icn_command(isdn_ctrl *c, icn_card *card)
 	ulong a;
 	ulong flags;
 	int i;
-	char cbuf[60];
+	char cbuf[80];
 	isdn_ctrl cmd;
 	icn_cdef cdef;
 	char __user *arg;
@@ -1309,7 +1309,6 @@ icn_command(isdn_ctrl *c, icn_card *card)
 			break;
 		if ((c->arg & 255) < ICN_BCH) {
 			char *p;
-			char dial[50];
 			char dcode[4];
 
 			a = c->arg;
@@ -1321,10 +1320,10 @@ icn_command(isdn_ctrl *c, icn_card *card)
 			} else
 				/* Normal Dial */
 				strcpy(dcode, "CAL");
-			strcpy(dial, p);
-			sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
-				dcode, dial, c->parm.setup.si1,
-				c->parm.setup.si2, c->parm.setup.eazmsn);
+			snprintf(cbuf, sizeof(cbuf),
+				 "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
+				 dcode, p, c->parm.setup.si1,
+				 c->parm.setup.si2, c->parm.setup.eazmsn);
 			i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
 		}
 		break;
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 6de9dfbf61c1..7e55a85c303a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -11,9 +11,6 @@ menuconfig NEW_LEDS
 	  Say Y to enable Linux LED support.  This allows control of supported
 	  LEDs from both userspace and optionally, by kernel events (triggers).
 
-	  This is not related to standard keyboard LEDs which are controlled
-	  via the input system.
-
 if NEW_LEDS
 
 config LEDS_CLASS
@@ -300,16 +297,6 @@ config LEDS_PCA963X
 	  LED driver chip accessed via the I2C bus. Supported
 	  devices include PCA9633 and PCA9634
 
-config LEDS_PCA9685
-	tristate "LED support for PCA9685 I2C chip"
-	depends on LEDS_CLASS
-	depends on I2C
-	help
-	  This option enables support for LEDs connected to the PCA9685
-	  LED driver chip accessed via the I2C bus.
-	  The PCA9685 offers 12-bit PWM (4095 levels of brightness) on
-	  16 individual channels.
-
 config LEDS_WM831X_STATUS
 	tristate "LED support for status LEDs on WM831x PMICs"
 	depends on LEDS_CLASS
@@ -479,6 +466,8 @@ config LEDS_OT200
 	  This option enables support for the LEDs on the Bachmann OT200.
 	  Say Y to enable LEDs on the Bachmann OT200.
 
+comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)"
+
 config LEDS_BLINKM
 	tristate "LED support for the BlinkM I2C RGB LED"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 3cd76dbd9be2..8979b0b2c85e 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_LEDS_OT200)		+= leds-ot200.o
 obj-$(CONFIG_LEDS_FSG)			+= leds-fsg.o
 obj-$(CONFIG_LEDS_PCA955X)		+= leds-pca955x.o
 obj-$(CONFIG_LEDS_PCA963X)		+= leds-pca963x.o
-obj-$(CONFIG_LEDS_PCA9685)		+= leds-pca9685.o
 obj-$(CONFIG_LEDS_DA903X)		+= leds-da903x.o
 obj-$(CONFIG_LEDS_DA9052)		+= leds-da9052.o
 obj-$(CONFIG_LEDS_WM831X_STATUS)	+= leds-wm831x-status.o
diff --git a/drivers/leds/dell-led.c b/drivers/leds/dell-led.c
index e5c57389efd6..c36acaf566a6 100644
--- a/drivers/leds/dell-led.c
+++ b/drivers/leds/dell-led.c
@@ -15,12 +15,15 @@
 #include <linux/leds.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/dmi.h>
+#include <linux/dell-led.h>
 
 MODULE_AUTHOR("Louis Davis/Jim Dailey");
 MODULE_DESCRIPTION("Dell LED Control Driver");
 MODULE_LICENSE("GPL");
 
 #define DELL_LED_BIOS_GUID "F6E4FE6E-909D-47cb-8BAB-C9F6F2F8D396"
+#define DELL_APP_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
 MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID);
 
 /* Error Result Codes: */
@@ -39,6 +42,149 @@ MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID);
 #define CMD_LED_OFF	17
 #define CMD_LED_BLINK	18
 
+struct app_wmi_args {
+	u16 class;
+	u16 selector;
+	u32 arg1;
+	u32 arg2;
+	u32 arg3;
+	u32 arg4;
+	u32 res1;
+	u32 res2;
+	u32 res3;
+	u32 res4;
+	char dummy[92];
+};
+
+#define GLOBAL_MIC_MUTE_ENABLE	0x364
+#define GLOBAL_MIC_MUTE_DISABLE	0x365
+
+struct dell_bios_data_token {
+	u16 tokenid;
+	u16 location;
+	u16 value;
+};
+
+struct __attribute__ ((__packed__)) dell_bios_calling_interface {
+	struct	dmi_header header;
+	u16	cmd_io_addr;
+	u8	cmd_io_code;
+	u32	supported_cmds;
+	struct	dell_bios_data_token damap[];
+};
+
+static struct dell_bios_data_token dell_mic_tokens[2];
+
+static int dell_wmi_perform_query(struct app_wmi_args *args)
+{
+	struct app_wmi_args *bios_return;
+	union acpi_object *obj;
+	struct acpi_buffer input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	acpi_status status;
+	u32 rc = -EINVAL;
+
+	input.length = 128;
+	input.pointer = args;
+
+	status = wmi_evaluate_method(DELL_APP_GUID, 0, 1, &input, &output);
+	if (!ACPI_SUCCESS(status))
+		goto err_out0;
+
+	obj = output.pointer;
+	if (!obj)
+		goto err_out0;
+
+	if (obj->type != ACPI_TYPE_BUFFER)
+		goto err_out1;
+
+	bios_return = (struct app_wmi_args *)obj->buffer.pointer;
+	rc = bios_return->res1;
+	if (rc)
+		goto err_out1;
+
+	memcpy(args, bios_return, sizeof(struct app_wmi_args));
+	rc = 0;
+
+ err_out1:
+	kfree(obj);
+ err_out0:
+	return rc;
+}
+
+static void __init find_micmute_tokens(const struct dmi_header *dm, void *dummy)
+{
+	struct dell_bios_calling_interface *calling_interface;
+	struct dell_bios_data_token *token;
+	int token_size = sizeof(struct dell_bios_data_token);
+	int i = 0;
+
+	if (dm->type == 0xda && dm->length > 17) {
+		calling_interface = container_of(dm,
+				struct dell_bios_calling_interface, header);
+
+		token = &calling_interface->damap[i];
+		while (token->tokenid != 0xffff) {
+			if (token->tokenid == GLOBAL_MIC_MUTE_DISABLE)
+				memcpy(&dell_mic_tokens[0], token, token_size);
+			else if (token->tokenid == GLOBAL_MIC_MUTE_ENABLE)
+				memcpy(&dell_mic_tokens[1], token, token_size);
+
+			i++;
+			token = &calling_interface->damap[i];
+		}
+	}
+}
+
+static int dell_micmute_led_set(int state)
+{
+	struct app_wmi_args args;
+	struct dell_bios_data_token *token;
+
+	if (!wmi_has_guid(DELL_APP_GUID))
+		return -ENODEV;
+
+	if (state == 0 || state == 1)
+		token = &dell_mic_tokens[state];
+	else
+		return -EINVAL;
+
+	memset(&args, 0, sizeof(struct app_wmi_args));
+
+	args.class = 1;
+	args.arg1 = token->location;
+	args.arg2 = token->value;
+
+	dell_wmi_perform_query(&args);
+
+	return state;
+}
+
+int dell_app_wmi_led_set(int whichled, int on)
+{
+	int state = 0;
+
+	switch (whichled) {
+	case DELL_LED_MICMUTE:
+		state = dell_micmute_led_set(on);
+		break;
+	default:
+		pr_warn("led type %x is not supported\n", whichled);
+		break;
+	}
+
+	return state;
+}
+EXPORT_SYMBOL_GPL(dell_app_wmi_led_set);
+
+static int __init dell_micmute_led_init(void)
+{
+	memset(dell_mic_tokens, 0, sizeof(struct dell_bios_data_token) * 2);
+	dmi_walk(find_micmute_tokens, NULL);
+
+	return 0;
+}
+
 struct bios_args {
 	unsigned char length;
 	unsigned char result_code;
@@ -181,21 +327,32 @@ static int __init dell_led_init(void)
 {
 	int error = 0;
 
-	if (!wmi_has_guid(DELL_LED_BIOS_GUID))
+	if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID))
 		return -ENODEV;
 
-	error = led_off();
-	if (error != 0)
-		return -ENODEV;
+	if (wmi_has_guid(DELL_APP_GUID))
+		error = dell_micmute_led_init();
 
-	return led_classdev_register(NULL, &dell_led);
+	if (wmi_has_guid(DELL_LED_BIOS_GUID)) {
+		error = led_off();
+		if (error != 0)
+			return -ENODEV;
+
+		error = led_classdev_register(NULL, &dell_led);
+	}
+
+	return error;
 }
 
 static void __exit dell_led_exit(void)
 {
-	led_classdev_unregister(&dell_led);
+	int error = 0;
 
-	led_off();
+	if (wmi_has_guid(DELL_LED_BIOS_GUID)) {
+		error = led_off();
+		if (error == 0)
+			led_classdev_unregister(&dell_led);
+	}
 }
 
 module_init(dell_led_init);
diff --git a/drivers/leds/leds-pca9685.c b/drivers/leds/leds-pca9685.c
deleted file mode 100644
index 6e1ef3a9d6ef..000000000000
--- a/drivers/leds/leds-pca9685.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2013 Maximilian Güntner <maximilian.guentner@gmail.com>
- *
- * This file is subject to the terms and conditions of version 2 of
- * the GNU General Public License.  See the file COPYING in the main
- * directory of this archive for more details.
- *
- * Based on leds-pca963x.c driver by
- * Peter Meerwald <p.meerwald@bct-electronic.com>
- *
- * Driver for the NXP PCA9685 12-Bit PWM LED driver chip.
- *
- */
-
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/leds.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/workqueue.h>
-
-#include <linux/platform_data/leds-pca9685.h>
-
-/* Register Addresses */
-#define PCA9685_MODE1 0x00
-#define PCA9685_MODE2 0x01
-#define PCA9685_LED0_ON_L 0x06
-#define PCA9685_ALL_LED_ON_L 0xFA
-
-/* MODE1 Register */
-#define PCA9685_ALLCALL 0x00
-#define PCA9685_SLEEP   0x04
-#define PCA9685_AI      0x05
-
-/* MODE2 Register */
-#define PCA9685_INVRT   0x04
-#define PCA9685_OUTDRV  0x02
-
-static const struct i2c_device_id pca9685_id[] = {
-	{ "pca9685", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, pca9685_id);
-
-struct pca9685_led {
-	struct i2c_client *client;
-	struct work_struct work;
-	u16 brightness;
-	struct led_classdev led_cdev;
-	int led_num; /* 0-15 */
-	char name[32];
-};
-
-static void pca9685_write_msg(struct i2c_client *client, u8 *buf, u8 len)
-{
-	struct i2c_msg msg = {
-		.addr = client->addr,
-		.flags = 0x00,
-		.len = len,
-		.buf = buf
-	};
-	i2c_transfer(client->adapter, &msg, 1);
-}
-
-static void pca9685_all_off(struct i2c_client *client)
-{
-	u8 i2c_buffer[5] = {PCA9685_ALL_LED_ON_L, 0x00, 0x00, 0x00, 0x10};
-	pca9685_write_msg(client, i2c_buffer, 5);
-}
-
-static void pca9685_led_work(struct work_struct *work)
-{
-	struct pca9685_led *pca9685;
-	u8 i2c_buffer[5];
-
-	pca9685 = container_of(work, struct pca9685_led, work);
-	i2c_buffer[0] = PCA9685_LED0_ON_L + 4 * pca9685->led_num;
-	/*
-	 * 4095 is the maximum brightness, so we set the ON time to 0x1000
-	 * which disables the PWM generator for that LED
-	 */
-	if (pca9685->brightness == 4095)
-		*((__le16 *)(i2c_buffer+1)) = cpu_to_le16(0x1000);
-	else
-		*((__le16 *)(i2c_buffer+1)) = 0x0000;
-
-	if (pca9685->brightness == 0)
-		*((__le16 *)(i2c_buffer+3)) = cpu_to_le16(0x1000);
-	else if (pca9685->brightness == 4095)
-		*((__le16 *)(i2c_buffer+3)) = 0x0000;
-	else
-		*((__le16 *)(i2c_buffer+3)) = cpu_to_le16(pca9685->brightness);
-
-	pca9685_write_msg(pca9685->client, i2c_buffer, 5);
-}
-
-static void pca9685_led_set(struct led_classdev *led_cdev,
-		enum led_brightness value)
-{
-	struct pca9685_led *pca9685;
-	pca9685 = container_of(led_cdev, struct pca9685_led, led_cdev);
-	pca9685->brightness = value;
-
-	schedule_work(&pca9685->work);
-}
-
-static int pca9685_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
-{
-	struct pca9685_led *pca9685;
-	struct pca9685_platform_data *pdata;
-	int err;
-	u8 i;
-
-	pdata = dev_get_platdata(&client->dev);
-	if (pdata) {
-		if (pdata->leds.num_leds < 1 || pdata->leds.num_leds > 15) {
-			dev_err(&client->dev, "board info must claim 1-16 LEDs");
-			return -EINVAL;
-		}
-	}
-
-	pca9685 = devm_kzalloc(&client->dev, 16 * sizeof(*pca9685), GFP_KERNEL);
-	if (!pca9685)
-		return -ENOMEM;
-
-	i2c_set_clientdata(client, pca9685);
-	pca9685_all_off(client);
-
-	for (i = 0; i < 16; i++) {
-		pca9685[i].client = client;
-		pca9685[i].led_num = i;
-		pca9685[i].name[0] = '\0';
-		if (pdata && i < pdata->leds.num_leds) {
-			if (pdata->leds.leds[i].name)
-				strncpy(pca9685[i].name,
-					pdata->leds.leds[i].name,
-					sizeof(pca9685[i].name)-1);
-			if (pdata->leds.leds[i].default_trigger)
-				pca9685[i].led_cdev.default_trigger =
-					pdata->leds.leds[i].default_trigger;
-		}
-		if (strlen(pca9685[i].name) == 0) {
-			/*
-			 * Write adapter and address to the name as well.
-			 * Otherwise multiple chips attached to one host would
-			 * not work.
-			 */
-			snprintf(pca9685[i].name, sizeof(pca9685[i].name),
-					"pca9685:%d:x%.2x:%d",
-					client->adapter->nr, client->addr, i);
-		}
-		pca9685[i].led_cdev.name = pca9685[i].name;
-		pca9685[i].led_cdev.max_brightness = 0xfff;
-		pca9685[i].led_cdev.brightness_set = pca9685_led_set;
-
-		INIT_WORK(&pca9685[i].work, pca9685_led_work);
-		err = led_classdev_register(&client->dev, &pca9685[i].led_cdev);
-		if (err < 0)
-			goto exit;
-	}
-
-	if (pdata)
-		i2c_smbus_write_byte_data(client, PCA9685_MODE2,
-			pdata->outdrv << PCA9685_OUTDRV |
-			pdata->inverted << PCA9685_INVRT);
-	else
-		i2c_smbus_write_byte_data(client, PCA9685_MODE2,
-			PCA9685_TOTEM_POLE << PCA9685_OUTDRV);
-	/* Enable Auto-Increment, enable oscillator, ALLCALL/SUBADDR disabled */
-	i2c_smbus_write_byte_data(client, PCA9685_MODE1, BIT(PCA9685_AI));
-
-	return 0;
-
-exit:
-	while (i--) {
-		led_classdev_unregister(&pca9685[i].led_cdev);
-		cancel_work_sync(&pca9685[i].work);
-	}
-	return err;
-}
-
-static int pca9685_remove(struct i2c_client *client)
-{
-	struct pca9685_led *pca9685 = i2c_get_clientdata(client);
-	u8 i;
-
-	for (i = 0; i < 16; i++) {
-		led_classdev_unregister(&pca9685[i].led_cdev);
-		cancel_work_sync(&pca9685[i].work);
-	}
-	pca9685_all_off(client);
-	return 0;
-}
-
-static struct i2c_driver pca9685_driver = {
-	.driver = {
-		.name = "leds-pca9685",
-		.owner = THIS_MODULE,
-	},
-	.probe = pca9685_probe,
-	.remove = pca9685_remove,
-	.id_table = pca9685_id,
-};
-
-module_i2c_driver(pca9685_driver);
-
-MODULE_AUTHOR("Maximilian Güntner <maximilian.guentner@gmail.com>");
-MODULE_DESCRIPTION("PCA9685 LED Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 7d0aaed1e23a..f5cf1b0f2748 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -69,6 +69,10 @@ static void led_pwm_set(struct led_classdev *led_cdev,
 
 	duty *= brightness;
 	do_div(duty, max);
+
+	if (led_dat->active_low)
+		duty = led_dat->period - duty;
+
 	led_dat->duty = duty;
 
 	if (led_dat->can_sleep)
@@ -92,55 +96,75 @@ static void led_pwm_cleanup(struct led_pwm_priv *priv)
 	}
 }
 
-static int led_pwm_create_of(struct platform_device *pdev,
-			     struct led_pwm_priv *priv)
+static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
+		       struct led_pwm *led, struct device_node *child)
 {
-	struct device_node *child;
+	struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
 	int ret;
 
-	for_each_child_of_node(pdev->dev.of_node, child) {
-		struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
+	led_data->active_low = led->active_low;
+	led_data->period = led->pwm_period_ns;
+	led_data->cdev.name = led->name;
+	led_data->cdev.default_trigger = led->default_trigger;
+	led_data->cdev.brightness_set = led_pwm_set;
+	led_data->cdev.brightness = LED_OFF;
+	led_data->cdev.max_brightness = led->max_brightness;
+	led_data->cdev.flags = LED_CORE_SUSPENDRESUME;
+
+	if (child)
+		led_data->pwm = devm_of_pwm_get(dev, child, NULL);
+	else
+		led_data->pwm = devm_pwm_get(dev, led->name);
+	if (IS_ERR(led_data->pwm)) {
+		ret = PTR_ERR(led_data->pwm);
+		dev_err(dev, "unable to request PWM for %s: %d\n",
+			led->name, ret);
+		return ret;
+	}
 
-		led_dat->cdev.name = of_get_property(child, "label",
-						     NULL) ? : child->name;
+	if (child)
+		led_data->period = pwm_get_period(led_data->pwm);
 
-		led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL);
-		if (IS_ERR(led_dat->pwm)) {
-			dev_err(&pdev->dev, "unable to request PWM for %s\n",
-				led_dat->cdev.name);
-			ret = PTR_ERR(led_dat->pwm);
-			goto err;
-		}
-		/* Get the period from PWM core when n*/
-		led_dat->period = pwm_get_period(led_dat->pwm);
+	led_data->can_sleep = pwm_can_sleep(led_data->pwm);
+	if (led_data->can_sleep)
+		INIT_WORK(&led_data->work, led_pwm_work);
 
-		led_dat->cdev.default_trigger = of_get_property(child,
-						"linux,default-trigger", NULL);
-		of_property_read_u32(child, "max-brightness",
-				     &led_dat->cdev.max_brightness);
+	ret = led_classdev_register(dev, &led_data->cdev);
+	if (ret == 0) {
+		priv->num_leds++;
+	} else {
+		dev_err(dev, "failed to register PWM led for %s: %d\n",
+			led->name, ret);
+	}
 
-		led_dat->cdev.brightness_set = led_pwm_set;
-		led_dat->cdev.brightness = LED_OFF;
-		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+	return ret;
+}
 
-		led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
-		if (led_dat->can_sleep)
-			INIT_WORK(&led_dat->work, led_pwm_work);
+static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv)
+{
+	struct device_node *child;
+	struct led_pwm led;
+	int ret = 0;
 
-		ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "failed to register for %s\n",
-				led_dat->cdev.name);
+	memset(&led, 0, sizeof(led));
+
+	for_each_child_of_node(dev->of_node, child) {
+		led.name = of_get_property(child, "label", NULL) ? :
+			   child->name;
+
+		led.default_trigger = of_get_property(child,
+						"linux,default-trigger", NULL);
+		led.active_low = of_property_read_bool(child, "active-low");
+		of_property_read_u32(child, "max-brightness",
+				     &led.max_brightness);
+
+		ret = led_pwm_add(dev, priv, &led, child);
+		if (ret) {
 			of_node_put(child);
-			goto err;
+			break;
 		}
-		priv->num_leds++;
 	}
 
-	return 0;
-err:
-	led_pwm_cleanup(priv);
-
 	return ret;
 }
 
@@ -166,51 +190,23 @@ static int led_pwm_probe(struct platform_device *pdev)
 
 	if (pdata) {
 		for (i = 0; i < count; i++) {
-			struct led_pwm *cur_led = &pdata->leds[i];
-			struct led_pwm_data *led_dat = &priv->leds[i];
-
-			led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
-			if (IS_ERR(led_dat->pwm)) {
-				ret = PTR_ERR(led_dat->pwm);
-				dev_err(&pdev->dev,
-					"unable to request PWM for %s\n",
-					cur_led->name);
-				goto err;
-			}
-
-			led_dat->cdev.name = cur_led->name;
-			led_dat->cdev.default_trigger = cur_led->default_trigger;
-			led_dat->active_low = cur_led->active_low;
-			led_dat->period = cur_led->pwm_period_ns;
-			led_dat->cdev.brightness_set = led_pwm_set;
-			led_dat->cdev.brightness = LED_OFF;
-			led_dat->cdev.max_brightness = cur_led->max_brightness;
-			led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
-
-			led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
-			if (led_dat->can_sleep)
-				INIT_WORK(&led_dat->work, led_pwm_work);
-
-			ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
-			if (ret < 0)
-				goto err;
+			ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i],
+					  NULL);
+			if (ret)
+				break;
 		}
-		priv->num_leds = count;
 	} else {
-		ret = led_pwm_create_of(pdev, priv);
-		if (ret)
-			return ret;
+		ret = led_pwm_create_of(&pdev->dev, priv);
+	}
+
+	if (ret) {
+		led_pwm_cleanup(priv);
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, priv);
 
 	return 0;
-
-err:
-	priv->num_leds = i;
-	led_pwm_cleanup(priv);
-
-	return ret;
 }
 
 static int led_pwm_remove(struct platform_device *pdev)
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index d1278b5f3028..004926955263 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -141,6 +141,7 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase,
 		default:
 			pr_err("Invalid chameleon descriptor type 0x%x\n",
 				dtype);
+			kfree(header);
 			return -EINVAL;
 		}
 		num_cells++;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 784695d22fde..53cbfdf0d870 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -18,10 +18,11 @@
 #include <linux/slab.h>
 #include <linux/crypto.h>
 #include <linux/workqueue.h>
+#include <linux/kthread.h>
 #include <linux/backing-dev.h>
-#include <linux/percpu.h>
 #include <linux/atomic.h>
 #include <linux/scatterlist.h>
+#include <linux/rbtree.h>
 #include <asm/page.h>
 #include <asm/unaligned.h>
 #include <crypto/hash.h>
@@ -43,6 +44,7 @@ struct convert_context {
 	struct bvec_iter iter_out;
 	sector_t cc_sector;
 	atomic_t cc_pending;
+	struct ablkcipher_request *req;
 };
 
 /*
@@ -58,8 +60,9 @@ struct dm_crypt_io {
 	atomic_t io_pending;
 	int error;
 	sector_t sector;
-	struct dm_crypt_io *base_io;
-};
+
+	struct rb_node rb_node;
+} CRYPTO_MINALIGN_ATTR;
 
 struct dm_crypt_request {
 	struct convert_context *ctx;
@@ -111,15 +114,7 @@ struct iv_tcw_private {
 enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID };
 
 /*
- * Duplicated per-CPU state for cipher.
- */
-struct crypt_cpu {
-	struct ablkcipher_request *req;
-};
-
-/*
- * The fields in here must be read only after initialization,
- * changing state should be in crypt_cpu.
+ * The fields in here must be read only after initialization.
  */
 struct crypt_config {
 	struct dm_dev *dev;
@@ -129,14 +124,18 @@ struct crypt_config {
 	 * pool for per bio private data, crypto requests and
 	 * encryption requeusts/buffer pages
 	 */
-	mempool_t *io_pool;
 	mempool_t *req_pool;
 	mempool_t *page_pool;
 	struct bio_set *bs;
+	struct mutex bio_alloc_lock;
 
 	struct workqueue_struct *io_queue;
 	struct workqueue_struct *crypt_queue;
 
+	struct task_struct *write_thread;
+	wait_queue_head_t write_thread_wait;
+	struct rb_root write_tree;
+
 	char *cipher;
 	char *cipher_string;
 
@@ -150,12 +149,6 @@ struct crypt_config {
 	sector_t iv_offset;
 	unsigned int iv_size;
 
-	/*
-	 * Duplicated per cpu state. Access through
-	 * per_cpu_ptr() only.
-	 */
-	struct crypt_cpu __percpu *cpu;
-
 	/* ESSIV: struct crypto_cipher *essiv_tfm */
 	void *iv_private;
 	struct crypto_ablkcipher **tfms;
@@ -176,6 +169,8 @@ struct crypt_config {
 	 */
 	unsigned int dmreq_start;
 
+	unsigned int per_bio_data_size;
+
 	unsigned long flags;
 	unsigned int key_size;
 	unsigned int key_parts;      /* independent parts in key buffer */
@@ -184,19 +179,11 @@ struct crypt_config {
 };
 
 #define MIN_IOS        16
-#define MIN_POOL_PAGES 32
-
-static struct kmem_cache *_crypt_io_pool;
 
 static void clone_init(struct dm_crypt_io *, struct bio *);
 static void kcryptd_queue_crypt(struct dm_crypt_io *io);
 static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq);
 
-static struct crypt_cpu *this_crypt_config(struct crypt_config *cc)
-{
-	return this_cpu_ptr(cc->cpu);
-}
-
 /*
  * Use this to access cipher attributes that are the same for each CPU.
  */
@@ -903,16 +890,23 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
 static void crypt_alloc_req(struct crypt_config *cc,
 			    struct convert_context *ctx)
 {
-	struct crypt_cpu *this_cc = this_crypt_config(cc);
 	unsigned key_index = ctx->cc_sector & (cc->tfms_count - 1);
 
-	if (!this_cc->req)
-		this_cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
+	if (!ctx->req)
+		ctx->req = mempool_alloc(cc->req_pool, GFP_NOIO);
 
-	ablkcipher_request_set_tfm(this_cc->req, cc->tfms[key_index]);
-	ablkcipher_request_set_callback(this_cc->req,
+	ablkcipher_request_set_tfm(ctx->req, cc->tfms[key_index]);
+	ablkcipher_request_set_callback(ctx->req,
 	    CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
-	    kcryptd_async_done, dmreq_of_req(cc, this_cc->req));
+	    kcryptd_async_done, dmreq_of_req(cc, ctx->req));
+}
+
+static void crypt_free_req(struct crypt_config *cc,
+			   struct ablkcipher_request *req, struct bio *base_bio)
+{
+	struct dm_crypt_io *io = dm_per_bio_data(base_bio, cc->per_bio_data_size);
+	if ((struct ablkcipher_request *)(io + 1) != req)
+		mempool_free(req, cc->req_pool);
 }
 
 /*
@@ -921,7 +915,6 @@ static void crypt_alloc_req(struct crypt_config *cc,
 static int crypt_convert(struct crypt_config *cc,
 			 struct convert_context *ctx)
 {
-	struct crypt_cpu *this_cc = this_crypt_config(cc);
 	int r;
 
 	atomic_set(&ctx->cc_pending, 1);
@@ -932,7 +925,7 @@ static int crypt_convert(struct crypt_config *cc,
 
 		atomic_inc(&ctx->cc_pending);
 
-		r = crypt_convert_block(cc, ctx, this_cc->req);
+		r = crypt_convert_block(cc, ctx, ctx->req);
 
 		switch (r) {
 		/* async */
@@ -941,7 +934,7 @@ static int crypt_convert(struct crypt_config *cc,
 			reinit_completion(&ctx->restart);
 			/* fall through*/
 		case -EINPROGRESS:
-			this_cc->req = NULL;
+			ctx->req = NULL;
 			ctx->cc_sector++;
 			continue;
 
@@ -962,57 +955,71 @@ static int crypt_convert(struct crypt_config *cc,
 	return 0;
 }
 
+static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone);
+
 /*
  * Generate a new unfragmented bio with the given size
  * This should never violate the device limitations
- * May return a smaller bio when running out of pages, indicated by
- * *out_of_pages set to 1.
+ *
+ * This function may be called concurrently. If we allocate from the mempool
+ * concurrently, there is a possibility of deadlock. For example, if we have
+ * mempool of 256 pages, two processes, each wanting 256, pages allocate from
+ * the mempool concurrently, it may deadlock in a situation where both processes
+ * have allocated 128 pages and the mempool is exhausted.
+ *
+ * In order to avoid this scenario we allocate the pages under a mutex.
+ *
+ * In order to not degrade performance with excessive locking, we try
+ * non-blocking allocation without a mutex first and if it fails, we fallback
+ * to a blocking allocation with a mutex.
  */
-static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size,
-				      unsigned *out_of_pages)
+static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
 {
 	struct crypt_config *cc = io->cc;
 	struct bio *clone;
 	unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
-	unsigned i, len;
+	gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM;
+	unsigned i, len, remaining_size;
 	struct page *page;
+	struct bio_vec *bvec;
+
+retry:
+	if (unlikely(gfp_mask & __GFP_WAIT))
+		mutex_lock(&cc->bio_alloc_lock);
 
 	clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
 	if (!clone)
-		return NULL;
+		goto return_clone;
 
 	clone_init(io, clone);
-	*out_of_pages = 0;
+
+	remaining_size = size;
 
 	for (i = 0; i < nr_iovecs; i++) {
 		page = mempool_alloc(cc->page_pool, gfp_mask);
 		if (!page) {
-			*out_of_pages = 1;
-			break;
+			BUG_ON(gfp_mask & __GFP_WAIT);
+			crypt_free_buffer_pages(cc, clone);
+			bio_put(clone);
+			gfp_mask |= __GFP_WAIT;
+			goto retry;
 		}
 
-		/*
-		 * If additional pages cannot be allocated without waiting,
-		 * return a partially-allocated bio.  The caller will then try
-		 * to allocate more bios while submitting this partial bio.
-		 */
-		gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+		len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size;
 
-		len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+		bvec = &clone->bi_io_vec[clone->bi_vcnt++];
+		bvec->bv_page = page;
+		bvec->bv_len = len;
+		bvec->bv_offset = 0;
 
-		if (!bio_add_page(clone, page, len, 0)) {
-			mempool_free(page, cc->page_pool);
-			break;
-		}
+		clone->bi_iter.bi_size += len;
 
-		size -= len;
+		remaining_size -= len;
 	}
 
-	if (!clone->bi_iter.bi_size) {
-		bio_put(clone);
-		return NULL;
-	}
+return_clone:
+	if (unlikely(gfp_mask & __GFP_WAIT))
+		mutex_unlock(&cc->bio_alloc_lock);
 
 	return clone;
 }
@@ -1029,20 +1036,15 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
 	}
 }
 
-static struct dm_crypt_io *crypt_io_alloc(struct crypt_config *cc,
-					  struct bio *bio, sector_t sector)
+static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc,
+			  struct bio *bio, sector_t sector)
 {
-	struct dm_crypt_io *io;
-
-	io = mempool_alloc(cc->io_pool, GFP_NOIO);
 	io->cc = cc;
 	io->base_bio = bio;
 	io->sector = sector;
 	io->error = 0;
-	io->base_io = NULL;
+	io->ctx.req = NULL;
 	atomic_set(&io->io_pending, 0);
-
-	return io;
 }
 
 static void crypt_inc_pending(struct dm_crypt_io *io)
@@ -1053,27 +1055,20 @@ static void crypt_inc_pending(struct dm_crypt_io *io)
 /*
  * One of the bios was finished. Check for completion of
  * the whole request and correctly clean up the buffer.
- * If base_io is set, wait for the last fragment to complete.
  */
 static void crypt_dec_pending(struct dm_crypt_io *io)
 {
 	struct crypt_config *cc = io->cc;
 	struct bio *base_bio = io->base_bio;
-	struct dm_crypt_io *base_io = io->base_io;
 	int error = io->error;
 
 	if (!atomic_dec_and_test(&io->io_pending))
 		return;
 
-	mempool_free(io, cc->io_pool);
+	if (io->ctx.req)
+		crypt_free_req(cc, io->ctx.req, base_bio);
 
-	if (likely(!base_io))
-		bio_endio(base_bio, error);
-	else {
-		if (error && !base_io->error)
-			base_io->error = error;
-		crypt_dec_pending(base_io);
-	}
+	bio_endio(base_bio, error);
 }
 
 /*
@@ -1155,37 +1150,97 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
 	return 0;
 }
 
+static void kcryptd_io_read_work(struct work_struct *work)
+{
+	struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
+
+	crypt_inc_pending(io);
+	if (kcryptd_io_read(io, GFP_NOIO))
+		io->error = -ENOMEM;
+	crypt_dec_pending(io);
+}
+
+static void kcryptd_queue_read(struct dm_crypt_io *io)
+{
+	struct crypt_config *cc = io->cc;
+
+	INIT_WORK(&io->work, kcryptd_io_read_work);
+	queue_work(cc->io_queue, &io->work);
+}
+
 static void kcryptd_io_write(struct dm_crypt_io *io)
 {
 	struct bio *clone = io->ctx.bio_out;
+
 	generic_make_request(clone);
 }
 
-static void kcryptd_io(struct work_struct *work)
+#define crypt_io_from_node(node) rb_entry((node), struct dm_crypt_io, rb_node)
+
+static int dmcrypt_write(void *data)
 {
-	struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
+	struct crypt_config *cc = data;
+	struct dm_crypt_io *io;
 
-	if (bio_data_dir(io->base_bio) == READ) {
-		crypt_inc_pending(io);
-		if (kcryptd_io_read(io, GFP_NOIO))
-			io->error = -ENOMEM;
-		crypt_dec_pending(io);
-	} else
-		kcryptd_io_write(io);
-}
+	while (1) {
+		struct rb_root write_tree;
+		struct blk_plug plug;
 
-static void kcryptd_queue_io(struct dm_crypt_io *io)
-{
-	struct crypt_config *cc = io->cc;
+		DECLARE_WAITQUEUE(wait, current);
 
-	INIT_WORK(&io->work, kcryptd_io);
-	queue_work(cc->io_queue, &io->work);
+		spin_lock_irq(&cc->write_thread_wait.lock);
+continue_locked:
+
+		if (!RB_EMPTY_ROOT(&cc->write_tree))
+			goto pop_from_list;
+
+		__set_current_state(TASK_INTERRUPTIBLE);
+		__add_wait_queue(&cc->write_thread_wait, &wait);
+
+		spin_unlock_irq(&cc->write_thread_wait.lock);
+
+		if (unlikely(kthread_should_stop())) {
+			set_task_state(current, TASK_RUNNING);
+			remove_wait_queue(&cc->write_thread_wait, &wait);
+			break;
+		}
+
+		schedule();
+
+		set_task_state(current, TASK_RUNNING);
+		spin_lock_irq(&cc->write_thread_wait.lock);
+		__remove_wait_queue(&cc->write_thread_wait, &wait);
+		goto continue_locked;
+
+pop_from_list:
+		write_tree = cc->write_tree;
+		cc->write_tree = RB_ROOT;
+		spin_unlock_irq(&cc->write_thread_wait.lock);
+
+		BUG_ON(rb_parent(write_tree.rb_node));
+
+		/*
+		 * Note: we cannot walk the tree here with rb_next because
+		 * the structures may be freed when kcryptd_io_write is called.
+		 */
+		blk_start_plug(&plug);
+		do {
+			io = crypt_io_from_node(rb_first(&write_tree));
+			rb_erase(&io->rb_node, &write_tree);
+			kcryptd_io_write(io);
+		} while (!RB_EMPTY_ROOT(&write_tree));
+		blk_finish_plug(&plug);
+	}
+	return 0;
 }
 
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io)
 {
 	struct bio *clone = io->ctx.bio_out;
 	struct crypt_config *cc = io->cc;
+	unsigned long flags;
+	sector_t sector;
+	struct rb_node **rbp, *parent;
 
 	if (unlikely(io->error < 0)) {
 		crypt_free_buffer_pages(cc, clone);
@@ -1199,20 +1254,30 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
 
 	clone->bi_iter.bi_sector = cc->start + io->sector;
 
-	if (async)
-		kcryptd_queue_io(io);
-	else
-		generic_make_request(clone);
+	spin_lock_irqsave(&cc->write_thread_wait.lock, flags);
+	rbp = &cc->write_tree.rb_node;
+	parent = NULL;
+	sector = io->sector;
+	while (*rbp) {
+		parent = *rbp;
+
+		if (sector < crypt_io_from_node(parent)->sector)
+			rbp = &(*rbp)->rb_left;
+		else
+			rbp = &(*rbp)->rb_right;
+	}
+	rb_link_node(&io->rb_node, parent, rbp);
+	rb_insert_color(&io->rb_node, &cc->write_tree);
+
+	wake_up_locked(&cc->write_thread_wait);
+	spin_unlock_irqrestore(&cc->write_thread_wait.lock, flags);
 }
 
 static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
 {
 	struct crypt_config *cc = io->cc;
 	struct bio *clone;
-	struct dm_crypt_io *new_io;
 	int crypt_finished;
-	unsigned out_of_pages = 0;
-	unsigned remaining = io->base_bio->bi_iter.bi_size;
 	sector_t sector = io->sector;
 	int r;
 
@@ -1222,80 +1287,30 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
 	crypt_inc_pending(io);
 	crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, sector);
 
-	/*
-	 * The allocated buffers can be smaller than the whole bio,
-	 * so repeat the whole process until all the data can be handled.
-	 */
-	while (remaining) {
-		clone = crypt_alloc_buffer(io, remaining, &out_of_pages);
-		if (unlikely(!clone)) {
-			io->error = -ENOMEM;
-			break;
-		}
-
-		io->ctx.bio_out = clone;
-		io->ctx.iter_out = clone->bi_iter;
-
-		remaining -= clone->bi_iter.bi_size;
-		sector += bio_sectors(clone);
-
-		crypt_inc_pending(io);
-
-		r = crypt_convert(cc, &io->ctx);
-		if (r < 0)
-			io->error = -EIO;
-
-		crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending);
-
-		/* Encryption was already finished, submit io now */
-		if (crypt_finished) {
-			kcryptd_crypt_write_io_submit(io, 0);
-
-			/*
-			 * If there was an error, do not try next fragments.
-			 * For async, error is processed in async handler.
-			 */
-			if (unlikely(r < 0))
-				break;
+	clone = crypt_alloc_buffer(io, io->base_bio->bi_iter.bi_size);
+	if (unlikely(!clone)) {
+		io->error = -EIO;
+		goto dec;
+	}
 
-			io->sector = sector;
-		}
+	io->ctx.bio_out = clone;
+	io->ctx.iter_out = clone->bi_iter;
 
-		/*
-		 * Out of memory -> run queues
-		 * But don't wait if split was due to the io size restriction
-		 */
-		if (unlikely(out_of_pages))
-			congestion_wait(BLK_RW_ASYNC, HZ/100);
+	sector += bio_sectors(clone);
 
-		/*
-		 * With async crypto it is unsafe to share the crypto context
-		 * between fragments, so switch to a new dm_crypt_io structure.
-		 */
-		if (unlikely(!crypt_finished && remaining)) {
-			new_io = crypt_io_alloc(io->cc, io->base_bio,
-						sector);
-			crypt_inc_pending(new_io);
-			crypt_convert_init(cc, &new_io->ctx, NULL,
-					   io->base_bio, sector);
-			new_io->ctx.iter_in = io->ctx.iter_in;
-
-			/*
-			 * Fragments after the first use the base_io
-			 * pending count.
-			 */
-			if (!io->base_io)
-				new_io->base_io = io;
-			else {
-				new_io->base_io = io->base_io;
-				crypt_inc_pending(io->base_io);
-				crypt_dec_pending(io);
-			}
+	crypt_inc_pending(io);
+	r = crypt_convert(cc, &io->ctx);
+	if (r)
+		io->error = -EIO;
+	crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending);
 
-			io = new_io;
-		}
+	/* Encryption was already finished, submit io now */
+	if (crypt_finished) {
+		kcryptd_crypt_write_io_submit(io);
+		io->sector = sector;
 	}
 
+dec:
 	crypt_dec_pending(io);
 }
 
@@ -1343,7 +1358,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
 	if (error < 0)
 		io->error = -EIO;
 
-	mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
+	crypt_free_req(cc, req_of_dmreq(cc, dmreq), io->base_bio);
 
 	if (!atomic_dec_and_test(&ctx->cc_pending))
 		return;
@@ -1351,7 +1366,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
 	if (bio_data_dir(io->base_bio) == READ)
 		kcryptd_crypt_read_done(io);
 	else
-		kcryptd_crypt_write_io_submit(io, 1);
+		kcryptd_crypt_write_io_submit(io);
 }
 
 static void kcryptd_crypt(struct work_struct *work)
@@ -1492,26 +1507,20 @@ static int crypt_wipe_key(struct crypt_config *cc)
 static void crypt_dtr(struct dm_target *ti)
 {
 	struct crypt_config *cc = ti->private;
-	struct crypt_cpu *cpu_cc;
-	int cpu;
 
 	ti->private = NULL;
 
 	if (!cc)
 		return;
 
+	if (cc->write_thread)
+		kthread_stop(cc->write_thread);
+
 	if (cc->io_queue)
 		destroy_workqueue(cc->io_queue);
 	if (cc->crypt_queue)
 		destroy_workqueue(cc->crypt_queue);
 
-	if (cc->cpu)
-		for_each_possible_cpu(cpu) {
-			cpu_cc = per_cpu_ptr(cc->cpu, cpu);
-			if (cpu_cc->req)
-				mempool_free(cpu_cc->req, cc->req_pool);
-		}
-
 	crypt_free_tfms(cc);
 
 	if (cc->bs)
@@ -1521,8 +1530,6 @@ static void crypt_dtr(struct dm_target *ti)
 		mempool_destroy(cc->page_pool);
 	if (cc->req_pool)
 		mempool_destroy(cc->req_pool);
-	if (cc->io_pool)
-		mempool_destroy(cc->io_pool);
 
 	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
 		cc->iv_gen_ops->dtr(cc);
@@ -1530,9 +1537,6 @@ static void crypt_dtr(struct dm_target *ti)
 	if (cc->dev)
 		dm_put_device(ti, cc->dev);
 
-	if (cc->cpu)
-		free_percpu(cc->cpu);
-
 	kzfree(cc->cipher);
 	kzfree(cc->cipher_string);
 
@@ -1588,13 +1592,6 @@ static int crypt_ctr_cipher(struct dm_target *ti,
 	if (tmp)
 		DMWARN("Ignoring unexpected additional cipher options");
 
-	cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)),
-				 __alignof__(struct crypt_cpu));
-	if (!cc->cpu) {
-		ti->error = "Cannot allocate per cpu state";
-		goto bad_mem;
-	}
-
 	/*
 	 * For compatibility with the original dm-crypt mapping format, if
 	 * only the cipher name is supplied, use cbc-plain.
@@ -1745,19 +1742,13 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	if (ret < 0)
 		goto bad;
 
-	ret = -ENOMEM;
-	cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool);
-	if (!cc->io_pool) {
-		ti->error = "Cannot allocate crypt io mempool";
-		goto bad;
-	}
-
 	cc->dmreq_start = sizeof(struct ablkcipher_request);
 	cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc));
 	cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment());
 	cc->dmreq_start += crypto_ablkcipher_alignmask(any_tfm(cc)) &
 			   ~(crypto_tfm_ctx_alignment() - 1);
 
+	ret = -ENOMEM;
 	cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start +
 			sizeof(struct dm_crypt_request) + cc->iv_size);
 	if (!cc->req_pool) {
@@ -1765,7 +1756,11 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 		goto bad;
 	}
 
-	cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
+	cc->per_bio_data_size = ti->per_bio_data_size =
+				sizeof(struct dm_crypt_io) + cc->dmreq_start +
+				sizeof(struct dm_crypt_request) + cc->iv_size;
+
+	cc->page_pool = mempool_create_page_pool(BIO_MAX_PAGES, 0);
 	if (!cc->page_pool) {
 		ti->error = "Cannot allocate page mempool";
 		goto bad;
@@ -1777,6 +1772,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 		goto bad;
 	}
 
+	mutex_init(&cc->bio_alloc_lock);
+
 	ret = -EINVAL;
 	if (sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) {
 		ti->error = "Invalid iv_offset sector";
@@ -1827,12 +1824,24 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	}
 
 	cc->crypt_queue = alloc_workqueue("kcryptd",
-					  WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 1);
+					  WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus());
 	if (!cc->crypt_queue) {
 		ti->error = "Couldn't create kcryptd queue";
 		goto bad;
 	}
 
+	init_waitqueue_head(&cc->write_thread_wait);
+	cc->write_tree = RB_ROOT;
+
+	cc->write_thread = kthread_create(dmcrypt_write, cc, "dmcrypt_write");
+	if (IS_ERR(cc->write_thread)) {
+		ret = PTR_ERR(cc->write_thread);
+		cc->write_thread = NULL;
+		ti->error = "Couldn't spawn write thread";
+		goto bad;
+	}
+	wake_up_process(cc->write_thread);
+
 	ti->num_flush_bios = 1;
 	ti->discard_zeroes_data_unsupported = true;
 
@@ -1861,11 +1870,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
 		return DM_MAPIO_REMAPPED;
 	}
 
-	io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
+	io = dm_per_bio_data(bio, cc->per_bio_data_size);
+	crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
+	io->ctx.req = (struct ablkcipher_request *)(io + 1);
 
 	if (bio_data_dir(io->base_bio) == READ) {
 		if (kcryptd_io_read(io, GFP_NOWAIT))
-			kcryptd_queue_io(io);
+			kcryptd_queue_read(io);
 	} else
 		kcryptd_queue_crypt(io);
 
@@ -2011,14 +2022,9 @@ static int __init dm_crypt_init(void)
 {
 	int r;
 
-	_crypt_io_pool = KMEM_CACHE(dm_crypt_io, 0);
-	if (!_crypt_io_pool)
-		return -ENOMEM;
-
 	r = dm_register_target(&crypt_target);
 	if (r < 0) {
 		DMERR("register failed %d", r);
-		kmem_cache_destroy(_crypt_io_pool);
 	}
 
 	return r;
@@ -2027,7 +2033,6 @@ static int __init dm_crypt_init(void)
 static void __exit dm_crypt_exit(void)
 {
 	dm_unregister_target(&crypt_target);
-	kmem_cache_destroy(_crypt_io_pool);
 }
 
 module_init(dm_crypt_init);
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 53728be84dee..28fc282b61b2 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -232,6 +232,13 @@ struct thin_c {
 	struct bio_list deferred_bio_list;
 	struct bio_list retry_on_resume_list;
 	struct rb_root sort_bio_list; /* sorted list of deferred bios */
+
+	/*
+	 * Ensures the thin is not destroyed until the worker has finished
+	 * iterating the active_thins list.
+	 */
+	atomic_t refcount;
+	struct completion can_destroy;
 };
 
 /*----------------------------------------------------------------*/
@@ -1486,6 +1493,45 @@ static void process_thin_deferred_bios(struct thin_c *tc)
 	blk_finish_plug(&plug);
 }
 
+static void thin_get(struct thin_c *tc);
+static void thin_put(struct thin_c *tc);
+
+/*
+ * We can't hold rcu_read_lock() around code that can block.  So we
+ * find a thin with the rcu lock held; bump a refcount; then drop
+ * the lock.
+ */
+static struct thin_c *get_first_thin(struct pool *pool)
+{
+	struct thin_c *tc = NULL;
+
+	rcu_read_lock();
+	if (!list_empty(&pool->active_thins)) {
+		tc = list_entry_rcu(pool->active_thins.next, struct thin_c, list);
+		thin_get(tc);
+	}
+	rcu_read_unlock();
+
+	return tc;
+}
+
+static struct thin_c *get_next_thin(struct pool *pool, struct thin_c *tc)
+{
+	struct thin_c *old_tc = tc;
+
+	rcu_read_lock();
+	list_for_each_entry_continue_rcu(tc, &pool->active_thins, list) {
+		thin_get(tc);
+		thin_put(old_tc);
+		rcu_read_unlock();
+		return tc;
+	}
+	thin_put(old_tc);
+	rcu_read_unlock();
+
+	return NULL;
+}
+
 static void process_deferred_bios(struct pool *pool)
 {
 	unsigned long flags;
@@ -1493,10 +1539,11 @@ static void process_deferred_bios(struct pool *pool)
 	struct bio_list bios;
 	struct thin_c *tc;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(tc, &pool->active_thins, list)
+	tc = get_first_thin(pool);
+	while (tc) {
 		process_thin_deferred_bios(tc);
-	rcu_read_unlock();
+		tc = get_next_thin(pool, tc);
+	}
 
 	/*
 	 * If there are any deferred flush bios, we must commit
@@ -3061,11 +3108,25 @@ static struct target_type pool_target = {
 /*----------------------------------------------------------------
  * Thin target methods
  *--------------------------------------------------------------*/
+static void thin_get(struct thin_c *tc)
+{
+	atomic_inc(&tc->refcount);
+}
+
+static void thin_put(struct thin_c *tc)
+{
+	if (atomic_dec_and_test(&tc->refcount))
+		complete(&tc->can_destroy);
+}
+
 static void thin_dtr(struct dm_target *ti)
 {
 	struct thin_c *tc = ti->private;
 	unsigned long flags;
 
+	thin_put(tc);
+	wait_for_completion(&tc->can_destroy);
+
 	spin_lock_irqsave(&tc->pool->lock, flags);
 	list_del_rcu(&tc->list);
 	spin_unlock_irqrestore(&tc->pool->lock, flags);
@@ -3101,6 +3162,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 	struct thin_c *tc;
 	struct dm_dev *pool_dev, *origin_dev;
 	struct mapped_device *pool_md;
+	unsigned long flags;
 
 	mutex_lock(&dm_thin_pool_table.mutex);
 
@@ -3191,9 +3253,12 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
 	mutex_unlock(&dm_thin_pool_table.mutex);
 
-	spin_lock(&tc->pool->lock);
+	atomic_set(&tc->refcount, 1);
+	init_completion(&tc->can_destroy);
+
+	spin_lock_irqsave(&tc->pool->lock, flags);
 	list_add_tail_rcu(&tc->list, &tc->pool->active_thins);
-	spin_unlock(&tc->pool->lock);
+	spin_unlock_irqrestore(&tc->pool->lock, flags);
 	/*
 	 * This synchronize_rcu() call is needed here otherwise we risk a
 	 * wake_worker() call finding no bios to process (because the newly
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index 796007a5e0e1..7a7bab8947ae 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -330,15 +330,17 @@ test_block_hash:
 				return r;
 			}
 		}
-
 		todo = 1 << v->data_dev_block_bits;
-		while (io->iter.bi_size) {
+		do {
 			u8 *page;
+			unsigned len;
 			struct bio_vec bv = bio_iter_iovec(bio, io->iter);
 
 			page = kmap_atomic(bv.bv_page);
-			r = crypto_shash_update(desc, page + bv.bv_offset,
-						bv.bv_len);
+			len = bv.bv_len;
+			if (likely(len >= todo))
+				len = todo;
+			r = crypto_shash_update(desc, page + bv.bv_offset, len);
 			kunmap_atomic(page);
 
 			if (r < 0) {
@@ -346,8 +348,9 @@ test_block_hash:
 				return r;
 			}
 
-			bio_advance_iter(bio, &io->iter, bv.bv_len);
-		}
+			bio_advance_iter(bio, &io->iter, len);
+			todo -= len;
+		} while (todo);
 
 		if (!v->version) {
 			r = crypto_shash_update(desc, v->salt, v->salt_size);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 455e64916498..6a71bc7c9133 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1544,7 +1544,6 @@ static int setup_clone(struct request *clone, struct request *rq,
 	clone->cmd = rq->cmd;
 	clone->cmd_len = rq->cmd_len;
 	clone->sense = rq->sense;
-	clone->buffer = rq->buffer;
 	clone->end_io = end_clone_request;
 	clone->end_io_data = tio;
 
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index a4459301b5f8..ee0f57e01b56 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -1616,7 +1616,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state)
 	if (ret < 0)
 		return -EINVAL;
 
-	node_ep = v4l2_of_get_next_endpoint(node, NULL);
+	node_ep = of_graph_get_next_endpoint(node, NULL);
 	if (!node_ep) {
 		dev_warn(dev, "no endpoint defined for node: %s\n",
 						node->full_name);
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index c137abfa0c54..20f1655e6d75 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -56,7 +56,7 @@ config VIDEO_VIU
 
 config VIDEO_TIMBERDALE
 	tristate "Support for timberdale Video In/LogiWIN"
-	depends on VIDEO_V4L2 && I2C && DMADEVICES
+	depends on MFD_TIMBERDALE && VIDEO_V4L2 && I2C && DMADEVICES
 	select DMA_ENGINE
 	select TIMB_DMA
 	select VIDEO_ADV7180
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index b4f12d00be05..656708252962 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -372,18 +372,32 @@ static int vpbe_stop_streaming(struct vb2_queue *vq)
 {
 	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
 	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_display *disp = fh->disp_dev;
+	unsigned long flags;
 
 	if (!vb2_is_streaming(vq))
 		return 0;
 
 	/* release all active buffers */
+	spin_lock_irqsave(&disp->dma_queue_lock, flags);
+	if (layer->cur_frm == layer->next_frm) {
+		vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_ERROR);
+	} else {
+		if (layer->cur_frm != NULL)
+			vb2_buffer_done(&layer->cur_frm->vb,
+					VB2_BUF_STATE_ERROR);
+		if (layer->next_frm != NULL)
+			vb2_buffer_done(&layer->next_frm->vb,
+					VB2_BUF_STATE_ERROR);
+	}
+
 	while (!list_empty(&layer->dma_queue)) {
 		layer->next_frm = list_entry(layer->dma_queue.next,
 						struct vpbe_disp_buffer, list);
 		list_del(&layer->next_frm->list);
 		vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR);
 	}
-
+	spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
 	return 0;
 }
 
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index d762246eabf5..0379cb9f9a9c 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -734,6 +734,8 @@ static int vpfe_release(struct file *file)
 		}
 		vpfe_dev->io_usrs = 0;
 		vpfe_dev->numbuffers = config_params.numbuffers;
+		videobuf_stop(&vpfe_dev->buffer_queue);
+		videobuf_mmap_free(&vpfe_dev->buffer_queue);
 	}
 
 	/* Decrement device usrs counter */
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 756da78bac23..8dea0b84a3ad 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -358,8 +358,31 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
+	/* Disable channel as per its device type and channel id */
+	if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
+		enable_channel0(0);
+		channel0_intr_enable(0);
+	}
+	if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
+		(2 == common->started)) {
+		enable_channel1(0);
+		channel1_intr_enable(0);
+	}
+	common->started = 0;
+
 	/* release all active buffers */
 	spin_lock_irqsave(&common->irqlock, flags);
+	if (common->cur_frm == common->next_frm) {
+		vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+	} else {
+		if (common->cur_frm != NULL)
+			vb2_buffer_done(&common->cur_frm->vb,
+					VB2_BUF_STATE_ERROR);
+		if (common->next_frm != NULL)
+			vb2_buffer_done(&common->next_frm->vb,
+					VB2_BUF_STATE_ERROR);
+	}
+
 	while (!list_empty(&common->dma_queue)) {
 		common->next_frm = list_entry(common->dma_queue.next,
 						struct vpif_cap_buffer, list);
@@ -933,17 +956,6 @@ static int vpif_release(struct file *filep)
 	if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
 		/* Reset io_usrs member of channel object */
 		common->io_usrs = 0;
-		/* Disable channel as per its device type and channel id */
-		if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
-			enable_channel0(0);
-			channel0_intr_enable(0);
-		}
-		if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
-		    (2 == common->started)) {
-			enable_channel1(0);
-			channel1_intr_enable(0);
-		}
-		common->started = 0;
 		/* Free buffers allocated */
 		vb2_queue_release(&common->buffer_queue);
 		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 0ac841e35aa4..aed41edd0501 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -320,8 +320,31 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
+	/* Disable channel */
+	if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
+		enable_channel2(0);
+		channel2_intr_enable(0);
+	}
+	if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
+		(2 == common->started)) {
+		enable_channel3(0);
+		channel3_intr_enable(0);
+	}
+	common->started = 0;
+
 	/* release all active buffers */
 	spin_lock_irqsave(&common->irqlock, flags);
+	if (common->cur_frm == common->next_frm) {
+		vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+	} else {
+		if (common->cur_frm != NULL)
+			vb2_buffer_done(&common->cur_frm->vb,
+					VB2_BUF_STATE_ERROR);
+		if (common->next_frm != NULL)
+			vb2_buffer_done(&common->next_frm->vb,
+					VB2_BUF_STATE_ERROR);
+	}
+
 	while (!list_empty(&common->dma_queue)) {
 		common->next_frm = list_entry(common->dma_queue.next,
 						struct vpif_disp_buffer, list);
@@ -773,18 +796,6 @@ static int vpif_release(struct file *filep)
 	if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
 		/* Reset io_usrs member of channel object */
 		common->io_usrs = 0;
-		/* Disable channel */
-		if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
-			enable_channel2(0);
-			channel2_intr_enable(0);
-		}
-		if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
-		    (2 == common->started)) {
-			enable_channel3(0);
-			channel3_intr_enable(0);
-		}
-		common->started = 0;
-
 		/* Free buffers allocated */
 		vb2_queue_release(&common->buffer_queue);
 		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index da2fc86cc524..25dbf5b05a96 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -122,7 +122,7 @@ static struct fimc_fmt fimc_formats[] = {
 	}, {
 		.name		= "YUV 4:2:2 planar, Y/Cb/Cr",
 		.fourcc		= V4L2_PIX_FMT_YUV422P,
-		.depth		= { 12 },
+		.depth		= { 16 },
 		.color		= FIMC_FMT_YCBYCR422,
 		.memplanes	= 1,
 		.colplanes	= 3,
diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile
index 7407b8338ccf..bc38f03394cd 100644
--- a/drivers/media/usb/dvb-usb-v2/Makefile
+++ b/drivers/media/usb/dvb-usb-v2/Makefile
@@ -41,4 +41,3 @@ ccflags-y += -I$(srctree)/drivers/media/dvb-core
 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
 ccflags-y += -I$(srctree)/drivers/media/tuners
 ccflags-y += -I$(srctree)/drivers/media/common
-ccflags-y += -I$(srctree)/drivers/staging/media/rtl2832u_sdr
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 61d196e8b3ab..dcbd392e6efc 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -24,7 +24,6 @@
 
 #include "rtl2830.h"
 #include "rtl2832.h"
-#include "rtl2832_sdr.h"
 
 #include "qt1010.h"
 #include "mt2060.h"
@@ -36,6 +35,45 @@
 #include "tua9001.h"
 #include "r820t.h"
 
+/*
+ * RTL2832_SDR module is in staging. That logic is added in order to avoid any
+ * hard dependency to drivers/staging/ directory as we want compile mainline
+ * driver even whole staging directory is missing.
+ */
+#include <media/v4l2-subdev.h>
+
+#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
+struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+	struct v4l2_subdev *sd);
+#else
+static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+	struct v4l2_subdev *sd)
+{
+	return NULL;
+}
+#endif
+
+#ifdef CONFIG_MEDIA_ATTACH
+#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
+	void *__r = NULL; \
+	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+	if (__a) { \
+		__r = (void *) __a(ARGS); \
+		if (__r == NULL) \
+			symbol_put(FUNCTION); \
+	} \
+	__r; \
+})
+
+#else
+#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
+	FUNCTION(ARGS); \
+})
+
+#endif
+
 static int rtl28xxu_disable_rc;
 module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644);
 MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller");
@@ -908,7 +946,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
 
 		/* attach SDR */
-		dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
 				&rtl28xxu_rtl2832_fc0012_config, NULL);
 		break;
 	case TUNER_RTL2832_FC0013:
@@ -920,7 +958,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
 
 		/* attach SDR */
-		dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
 				&rtl28xxu_rtl2832_fc0013_config, NULL);
 		break;
 	case TUNER_RTL2832_E4000: {
@@ -951,7 +989,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 			i2c_set_adapdata(i2c_adap_internal, d);
 
 			/* attach SDR */
-			dvb_attach(rtl2832_sdr_attach, adap->fe[0],
+			dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0],
 					i2c_adap_internal,
 					&rtl28xxu_rtl2832_e4000_config, sd);
 		}
@@ -982,7 +1020,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
 
 		/* attach SDR */
-		dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
 				&rtl28xxu_rtl2832_r820t_config, NULL);
 		break;
 	case TUNER_RTL2832_R828D:
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index 7277dbd2afcd..ecbcb39feb71 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -1430,10 +1430,8 @@ static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
 	{USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
 	{USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
-#if !IS_ENABLED(CONFIG_USB_SN9C102)
 	{USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
 	{USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
-#endif
 	{USB_DEVICE(0x0c45, 0x6027), SB(OV7630, 101)}, /* Genius Eye 310 */
 	{USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
 	{USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1cb74085e410..8baff0effc7d 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -300,8 +300,8 @@ config SGI_GRU_DEBUG
 	depends on SGI_GRU
 	default n
 	---help---
-	This option enables addition debugging code for the SGI GRU driver. If
-	you are unsure, say N.
+	This option enables additional debugging code for the SGI GRU driver.
+	If you are unsure, say N.
 
 config APDS9802ALS
 	tristate "Medfield Avago APDS9802 ALS Sensor module"
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h
index 5e4dbd21f89a..0e608a288603 100644
--- a/drivers/misc/genwqe/card_base.h
+++ b/drivers/misc/genwqe/card_base.h
@@ -337,6 +337,44 @@ enum genwqe_requ_state {
 };
 
 /**
+ * struct genwqe_sgl - Scatter gather list describing user-space memory
+ * @sgl:            scatter gather list needs to be 128 byte aligned
+ * @sgl_dma_addr:   dma address of sgl
+ * @sgl_size:       size of area used for sgl
+ * @user_addr:      user-space address of memory area
+ * @user_size:      size of user-space memory area
+ * @page:           buffer for partial pages if needed
+ * @page_dma_addr:  dma address partial pages
+ */
+struct genwqe_sgl {
+	dma_addr_t sgl_dma_addr;
+	struct sg_entry *sgl;
+	size_t sgl_size;	/* size of sgl */
+
+	void __user *user_addr; /* user-space base-address */
+	size_t user_size;       /* size of memory area */
+
+	unsigned long nr_pages;
+	unsigned long fpage_offs;
+	size_t fpage_size;
+	size_t lpage_size;
+
+	void *fpage;
+	dma_addr_t fpage_dma_addr;
+
+	void *lpage;
+	dma_addr_t lpage_dma_addr;
+};
+
+int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+			  void __user *user_addr, size_t user_size);
+
+int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+		     dma_addr_t *dma_list);
+
+int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl);
+
+/**
  * struct ddcb_requ - Kernel internal representation of the DDCB request
  * @cmd:          User space representation of the DDCB execution request
  */
@@ -347,9 +385,7 @@ struct ddcb_requ {
 	struct ddcb_queue *queue;	  /* associated queue */
 
 	struct dma_mapping  dma_mappings[DDCB_FIXUPS];
-	struct sg_entry     *sgl[DDCB_FIXUPS];
-	dma_addr_t	    sgl_dma_addr[DDCB_FIXUPS];
-	size_t		    sgl_size[DDCB_FIXUPS];
+	struct genwqe_sgl sgls[DDCB_FIXUPS];
 
 	/* kernel/user shared content */
 	struct genwqe_ddcb_cmd cmd;	/* ddcb_no for this request */
@@ -453,22 +489,6 @@ int  genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m,
 int  genwqe_user_vunmap(struct genwqe_dev *cd, struct dma_mapping *m,
 			struct ddcb_requ *req);
 
-struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages,
-				 dma_addr_t *dma_addr, size_t *sgl_size);
-
-void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list,
-		    dma_addr_t dma_addr, size_t size);
-
-int genwqe_setup_sgl(struct genwqe_dev *cd,
-		    unsigned long offs,
-		    unsigned long size,
-		    struct sg_entry *sgl, /* genwqe sgl */
-		    dma_addr_t dma_addr, size_t sgl_size,
-		    dma_addr_t *dma_list, int page_offs, int num_pages);
-
-int genwqe_check_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list,
-		     int size);
-
 static inline bool dma_mapping_used(struct dma_mapping *m)
 {
 	if (!m)
diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c
index 6f1acc0ccf88..c8046db2d5a2 100644
--- a/drivers/misc/genwqe/card_ddcb.c
+++ b/drivers/misc/genwqe/card_ddcb.c
@@ -305,6 +305,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue,
 			break;
 
 		new = (old | DDCB_NEXT_BE32);
+
+		wmb();
 		icrc_hsi_shi = cmpxchg(&prev_ddcb->icrc_hsi_shi_32, old, new);
 
 		if (icrc_hsi_shi == old)
@@ -314,6 +316,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue,
 	/* Queue must be re-started by updating QUEUE_OFFSET */
 	ddcb_mark_tapped(pddcb);
 	num = (u64)ddcb_no << 8;
+
+	wmb();
 	__genwqe_writeq(cd, queue->IO_QUEUE_OFFSET, num); /* start queue */
 
 	return RET_DDCB_TAPPED;
@@ -1306,7 +1310,7 @@ static int queue_wake_up_all(struct genwqe_dev *cd)
  */
 int genwqe_finish_queue(struct genwqe_dev *cd)
 {
-	int i, rc, in_flight;
+	int i, rc = 0, in_flight;
 	int waitmax = genwqe_ddcb_software_timeout;
 	struct pci_dev *pci_dev = cd->pci_dev;
 	struct ddcb_queue *queue = &cd->queue;
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 2c2c9cc75231..1d2f163a1906 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -531,7 +531,9 @@ static int do_flash_update(struct genwqe_file *cfile,
 	case '1':
 		cmdopts = 0x1C;
 		break;		/* download/erase_first/part_1 */
-	case 'v':		/* cmdopts = 0x0c (VPD) */
+	case 'v':
+		cmdopts = 0x0C;
+		break;		/* download/erase_first/vpd */
 	default:
 		return -EINVAL;
 	}
@@ -665,6 +667,8 @@ static int do_flash_read(struct genwqe_file *cfile,
 		cmdopts = 0x1A;
 		break;		/* upload/part_1 */
 	case 'v':
+		cmdopts = 0x0A;
+		break;		/* upload/vpd */
 	default:
 		return -EINVAL;
 	}
@@ -836,15 +840,8 @@ static int ddcb_cmd_cleanup(struct genwqe_file *cfile, struct ddcb_requ *req)
 			__genwqe_del_mapping(cfile, dma_map);
 			genwqe_user_vunmap(cd, dma_map, req);
 		}
-		if (req->sgl[i] != NULL) {
-			genwqe_free_sgl(cd, req->sgl[i],
-				       req->sgl_dma_addr[i],
-				       req->sgl_size[i]);
-			req->sgl[i] = NULL;
-			req->sgl_dma_addr[i] = 0x0;
-			req->sgl_size[i] = 0;
-		}
-
+		if (req->sgls[i].sgl != NULL)
+			genwqe_free_sync_sgl(cd, &req->sgls[i]);
 	}
 	return 0;
 }
@@ -913,7 +910,7 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req)
 
 		case ATS_TYPE_SGL_RDWR:
 		case ATS_TYPE_SGL_RD: {
-			int page_offs, nr_pages, offs;
+			int page_offs;
 
 			u_addr = be64_to_cpu(*((__be64 *)
 					       &cmd->asiv[asiv_offs]));
@@ -951,27 +948,18 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req)
 				page_offs = 0;
 			}
 
-			offs = offset_in_page(u_addr);
-			nr_pages = DIV_ROUND_UP(offs + u_size, PAGE_SIZE);
-
 			/* create genwqe style scatter gather list */
-			req->sgl[i] = genwqe_alloc_sgl(cd, m->nr_pages,
-						      &req->sgl_dma_addr[i],
-						      &req->sgl_size[i]);
-			if (req->sgl[i] == NULL) {
-				rc = -ENOMEM;
+			rc = genwqe_alloc_sync_sgl(cd, &req->sgls[i],
+						   (void __user *)u_addr,
+						   u_size);
+			if (rc != 0)
 				goto err_out;
-			}
-			genwqe_setup_sgl(cd, offs, u_size,
-					req->sgl[i],
-					req->sgl_dma_addr[i],
-					req->sgl_size[i],
-					m->dma_list,
-					page_offs,
-					nr_pages);
+
+			genwqe_setup_sgl(cd, &req->sgls[i],
+					 &m->dma_list[page_offs]);
 
 			*((__be64 *)&cmd->asiv[asiv_offs]) =
-				cpu_to_be64(req->sgl_dma_addr[i]);
+				cpu_to_be64(req->sgls[i].sgl_dma_addr);
 
 			break;
 		}
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index 6b1a6ef9f1a8..d049d271699c 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -275,67 +275,107 @@ static int genwqe_sgl_size(int num_pages)
 	return roundup(len, PAGE_SIZE);
 }
 
-struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages,
-				  dma_addr_t *dma_addr, size_t *sgl_size)
+/**
+ * genwqe_alloc_sync_sgl() - Allocate memory for sgl and overlapping pages
+ *
+ * Allocates memory for sgl and overlapping pages. Pages which might
+ * overlap other user-space memory blocks are being cached for DMAs,
+ * such that we do not run into syncronization issues. Data is copied
+ * from user-space into the cached pages.
+ */
+int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+			  void __user *user_addr, size_t user_size)
 {
+	int rc;
 	struct pci_dev *pci_dev = cd->pci_dev;
-	struct sg_entry *sgl;
 
-	*sgl_size = genwqe_sgl_size(num_pages);
-	if (get_order(*sgl_size) > MAX_ORDER) {
+	sgl->fpage_offs = offset_in_page((unsigned long)user_addr);
+	sgl->fpage_size = min_t(size_t, PAGE_SIZE-sgl->fpage_offs, user_size);
+	sgl->nr_pages = DIV_ROUND_UP(sgl->fpage_offs + user_size, PAGE_SIZE);
+	sgl->lpage_size = (user_size - sgl->fpage_size) % PAGE_SIZE;
+
+	dev_dbg(&pci_dev->dev, "[%s] uaddr=%p usize=%8ld nr_pages=%ld "
+		"fpage_offs=%lx fpage_size=%ld lpage_size=%ld\n",
+		__func__, user_addr, user_size, sgl->nr_pages,
+		sgl->fpage_offs, sgl->fpage_size, sgl->lpage_size);
+
+	sgl->user_addr = user_addr;
+	sgl->user_size = user_size;
+	sgl->sgl_size = genwqe_sgl_size(sgl->nr_pages);
+
+	if (get_order(sgl->sgl_size) > MAX_ORDER) {
 		dev_err(&pci_dev->dev,
 			"[%s] err: too much memory requested!\n", __func__);
-		return NULL;
+		return -ENOMEM;
 	}
 
-	sgl = __genwqe_alloc_consistent(cd, *sgl_size, dma_addr);
-	if (sgl == NULL) {
+	sgl->sgl = __genwqe_alloc_consistent(cd, sgl->sgl_size,
+					     &sgl->sgl_dma_addr);
+	if (sgl->sgl == NULL) {
 		dev_err(&pci_dev->dev,
 			"[%s] err: no memory available!\n", __func__);
-		return NULL;
+		return -ENOMEM;
 	}
 
-	return sgl;
+	/* Only use buffering on incomplete pages */
+	if ((sgl->fpage_size != 0) && (sgl->fpage_size != PAGE_SIZE)) {
+		sgl->fpage = __genwqe_alloc_consistent(cd, PAGE_SIZE,
+						       &sgl->fpage_dma_addr);
+		if (sgl->fpage == NULL)
+			goto err_out;
+
+		/* Sync with user memory */
+		if (copy_from_user(sgl->fpage + sgl->fpage_offs,
+				   user_addr, sgl->fpage_size)) {
+			rc = -EFAULT;
+			goto err_out;
+		}
+	}
+	if (sgl->lpage_size != 0) {
+		sgl->lpage = __genwqe_alloc_consistent(cd, PAGE_SIZE,
+						       &sgl->lpage_dma_addr);
+		if (sgl->lpage == NULL)
+			goto err_out1;
+
+		/* Sync with user memory */
+		if (copy_from_user(sgl->lpage, user_addr + user_size -
+				   sgl->lpage_size, sgl->lpage_size)) {
+			rc = -EFAULT;
+			goto err_out1;
+		}
+	}
+	return 0;
+
+ err_out1:
+	__genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage,
+				 sgl->fpage_dma_addr);
+ err_out:
+	__genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl,
+				 sgl->sgl_dma_addr);
+	return -ENOMEM;
 }
 
-int genwqe_setup_sgl(struct genwqe_dev *cd,
-		     unsigned long offs,
-		     unsigned long size,
-		     struct sg_entry *sgl,
-		     dma_addr_t dma_addr, size_t sgl_size,
-		     dma_addr_t *dma_list, int page_offs, int num_pages)
+int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+		     dma_addr_t *dma_list)
 {
 	int i = 0, j = 0, p;
 	unsigned long dma_offs, map_offs;
-	struct pci_dev *pci_dev = cd->pci_dev;
 	dma_addr_t prev_daddr = 0;
 	struct sg_entry *s, *last_s = NULL;
-
-	/* sanity checks */
-	if (offs > PAGE_SIZE) {
-		dev_err(&pci_dev->dev,
-			"[%s] too large start offs %08lx\n", __func__, offs);
-		return -EFAULT;
-	}
-	if (sgl_size < genwqe_sgl_size(num_pages)) {
-		dev_err(&pci_dev->dev,
-			"[%s] sgl_size too small %08lx for %d pages\n",
-			__func__, sgl_size, num_pages);
-		return -EFAULT;
-	}
+	size_t size = sgl->user_size;
 
 	dma_offs = 128;		/* next block if needed/dma_offset */
-	map_offs = offs;	/* offset in first page */
+	map_offs = sgl->fpage_offs; /* offset in first page */
 
-	s = &sgl[0];		/* first set of 8 entries */
+	s = &sgl->sgl[0];	/* first set of 8 entries */
 	p = 0;			/* page */
-	while (p < num_pages) {
+	while (p < sgl->nr_pages) {
 		dma_addr_t daddr;
 		unsigned int size_to_map;
 
 		/* always write the chaining entry, cleanup is done later */
 		j = 0;
-		s[j].target_addr = cpu_to_be64(dma_addr + dma_offs);
+		s[j].target_addr = cpu_to_be64(sgl->sgl_dma_addr + dma_offs);
 		s[j].len	 = cpu_to_be32(128);
 		s[j].flags	 = cpu_to_be32(SG_CHAINED);
 		j++;
@@ -343,7 +383,17 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
 		while (j < 8) {
 			/* DMA mapping for requested page, offs, size */
 			size_to_map = min(size, PAGE_SIZE - map_offs);
-			daddr = dma_list[page_offs + p] + map_offs;
+
+			if ((p == 0) && (sgl->fpage != NULL)) {
+				daddr = sgl->fpage_dma_addr + map_offs;
+
+			} else if ((p == sgl->nr_pages - 1) &&
+				   (sgl->lpage != NULL)) {
+				daddr = sgl->lpage_dma_addr;
+			} else {
+				daddr = dma_list[p] + map_offs;
+			}
+
 			size -= size_to_map;
 			map_offs = 0;
 
@@ -358,7 +408,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
 							  size_to_map);
 
 				p++; /* process next page */
-				if (p == num_pages)
+				if (p == sgl->nr_pages)
 					goto fixup;  /* nothing to do */
 
 				prev_daddr = daddr + size_to_map;
@@ -374,7 +424,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
 			j++;
 
 			p++;	/* process next page */
-			if (p == num_pages)
+			if (p == sgl->nr_pages)
 				goto fixup;  /* nothing to do */
 		}
 		dma_offs += 128;
@@ -395,10 +445,50 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
 	return 0;
 }
 
-void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list,
-		    dma_addr_t dma_addr, size_t size)
+/**
+ * genwqe_free_sync_sgl() - Free memory for sgl and overlapping pages
+ *
+ * After the DMA transfer has been completed we free the memory for
+ * the sgl and the cached pages. Data is being transfered from cached
+ * pages into user-space buffers.
+ */
+int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl)
 {
-	__genwqe_free_consistent(cd, size, sg_list, dma_addr);
+	int rc;
+	struct pci_dev *pci_dev = cd->pci_dev;
+
+	if (sgl->fpage) {
+		if (copy_to_user(sgl->user_addr, sgl->fpage + sgl->fpage_offs,
+				 sgl->fpage_size)) {
+			dev_err(&pci_dev->dev, "[%s] err: copying fpage!\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		__genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage,
+					 sgl->fpage_dma_addr);
+		sgl->fpage = NULL;
+		sgl->fpage_dma_addr = 0;
+	}
+	if (sgl->lpage) {
+		if (copy_to_user(sgl->user_addr + sgl->user_size -
+				 sgl->lpage_size, sgl->lpage,
+				 sgl->lpage_size)) {
+			dev_err(&pci_dev->dev, "[%s] err: copying lpage!\n",
+				__func__);
+			rc = -EFAULT;
+		}
+		__genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage,
+					 sgl->lpage_dma_addr);
+		sgl->lpage = NULL;
+		sgl->lpage_dma_addr = 0;
+	}
+	__genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl,
+				 sgl->sgl_dma_addr);
+
+	sgl->sgl = NULL;
+	sgl->sgl_dma_addr = 0x0;
+	sgl->sgl_size = 0;
+	return rc;
 }
 
 /**
diff --git a/drivers/misc/genwqe/genwqe_driver.h b/drivers/misc/genwqe/genwqe_driver.h
index 46e916b36c70..cd5263163a6e 100644
--- a/drivers/misc/genwqe/genwqe_driver.h
+++ b/drivers/misc/genwqe/genwqe_driver.h
@@ -36,7 +36,7 @@
 #include <asm/byteorder.h>
 #include <linux/genwqe/genwqe_card.h>
 
-#define DRV_VERS_STRING		"2.0.0"
+#define DRV_VERS_STRING		"2.0.15"
 
 /*
  * Static minor number assignement, until we decide/implement
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 66f411a6e8ea..cabc04383685 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -115,6 +115,11 @@
 #define MEI_DEV_ID_LPT_HR     0x8CBA  /* Lynx Point H Refresh */
 
 #define MEI_DEV_ID_WPT_LP     0x9CBA  /* Wildcat Point LP */
+
+/* Host Firmware Status Registers in PCI Config Space */
+#define PCI_CFG_HFS_1         0x40
+#define PCI_CFG_HFS_2         0x48
+
 /*
  * MEI HW Section
  */
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 29b5af8efb71..4e3cba6da3f5 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -455,8 +455,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 
 		cl->status = 0;
 		list_del(&cb->list);
-		if (MEI_WRITING == cl->writing_state &&
-		    cb->fop_type == MEI_FOP_WRITE &&
+		if (cb->fop_type == MEI_FOP_WRITE &&
 		    cl != &dev->iamthif_cl) {
 			cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
 			cl->writing_state = MEI_WRITE_COMPLETE;
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index b35594dbf52f..147413145c97 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -644,8 +644,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 		goto out;
 	}
 
-	if (MEI_WRITE_COMPLETE == cl->writing_state)
-		mask |= (POLLIN | POLLRDNORM);
+	mask |= (POLLIN | POLLRDNORM);
 
 out:
 	mutex_unlock(&dev->device_lock);
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1c8fd3a3e135..95889e2e31ff 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -97,15 +97,31 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
 	u32 reg;
-	if (ent->device == MEI_DEV_ID_PBG_1) {
-		pci_read_config_dword(pdev, 0x48, &reg);
-		/* make sure that bit 9 is up and bit 10 is down */
-		if ((reg & 0x600) == 0x200) {
-			dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
-			return false;
-		}
+	/* Cougar Point || Patsburg */
+	if (ent->device == MEI_DEV_ID_CPT_1 ||
+	    ent->device == MEI_DEV_ID_PBG_1) {
+		pci_read_config_dword(pdev, PCI_CFG_HFS_2, &reg);
+		/* make sure that bit 9 (NM) is up and bit 10 (DM) is down */
+		if ((reg & 0x600) == 0x200)
+			goto no_mei;
 	}
+
+	/* Lynx Point */
+	if (ent->device == MEI_DEV_ID_LPT_H  ||
+	    ent->device == MEI_DEV_ID_LPT_W  ||
+	    ent->device == MEI_DEV_ID_LPT_HR) {
+		/* Read ME FW Status check for SPS Firmware */
+		pci_read_config_dword(pdev, PCI_CFG_HFS_1, &reg);
+		/* if bits [19:16] = 15, running SPS Firmware */
+		if ((reg & 0xf0000) == 0xf0000)
+			goto no_mei;
+	}
+
 	return true;
+
+no_mei:
+	dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
+	return false;
 }
 /**
  * mei_probe - Device Initialization Routine
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index 0535d1e0bc78..104a05f6b738 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -6,7 +6,7 @@
  * This file supports the user system call for file open, close, mmap, etc.
  * This also incudes the driver initialization code.
  *
- *  Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ *  Copyright (c) 2008-2014 Silicon Graphics, Inc.  All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -58,6 +58,11 @@ static int max_user_cbrs, max_user_dsr_bytes;
 
 static struct miscdevice gru_miscdev;
 
+static int gru_supported(void)
+{
+	return is_uv_system() &&
+		(uv_hub_info->hub_revision < UV3_HUB_REVISION_BASE);
+}
 
 /*
  * gru_vma_close
@@ -518,7 +523,7 @@ static int __init gru_init(void)
 {
 	int ret;
 
-	if (!is_uv_system() || (is_uvx_hub() && !is_uv2_hub()))
+	if (!gru_supported())
 		return 0;
 
 #if defined CONFIG_IA64
@@ -573,7 +578,7 @@ exit0:
 
 static void __exit gru_exit(void)
 {
-	if (!is_uv_system())
+	if (!gru_supported())
 		return;
 
 	gru_teardown_tlb_irqs();
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 1972d57aadb3..e7fbc08a0627 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -342,7 +342,7 @@ void st_int_recv(void *disc_data,
 			/* Unknow packet? */
 		default:
 			type = *ptr;
-			if (st_gdata->list[type] == NULL) {
+			if (type >= ST_MAX_CHANNELS || st_gdata->list[type] == NULL) {
 				pr_err("chip/interface misbehavior dropping"
 					" frame starting with 0x%02x", type);
 				goto done;
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 0b2ccb68c0d0..43e30992a369 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -82,12 +82,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
 
 	block = blk_rq_pos(req) << 9 >> tr->blkshift;
 	nsect = blk_rq_cur_bytes(req) >> tr->blkshift;
-
-	buf = req->buffer;
+	buf = bio_data(req->bio);
 
 	if (req->cmd_type != REQ_TYPE_FS)
 		return -EIO;
 
+	if (req->cmd_flags & REQ_FLUSH)
+		return tr->flush(dev);
+
 	if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
 	    get_capacity(req->rq_disk))
 		return -EIO;
@@ -408,6 +410,9 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 	if (!new->rq)
 		goto error3;
 
+	if (tr->flush)
+		blk_queue_flush(new->rq, REQ_FLUSH);
+
 	new->rq->queuedata = new;
 	blk_queue_logical_block_size(new->rq, tr->blksize);
 
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 4615d79fc93f..b922c8efcf40 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -523,6 +523,7 @@ static struct nand_ecclayout hwecc4_2048 = {
 #if defined(CONFIG_OF)
 static const struct of_device_id davinci_nand_of_match[] = {
 	{.compatible = "ti,davinci-nand", },
+	{.compatible = "ti,keystone-nand", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
@@ -581,6 +582,11 @@ static struct davinci_nand_pdata
 		    of_property_read_bool(pdev->dev.of_node,
 			"ti,davinci-nand-use-bbt"))
 			pdata->bbt_options = NAND_BBT_USE_FLASH;
+
+		if (of_device_is_compatible(pdev->dev.of_node,
+					    "ti,keystone-nand")) {
+			pdata->options |= NAND_NO_SUBPAGE_WRITE;
+		}
 	}
 
 	return dev_get_platdata(&pdev->dev);
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index dd1df605a1d6..ec4db2a359e5 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -861,7 +861,7 @@ static void gpmi_compute_edo_timing(struct gpmi_nand_data *this,
 	struct resources *r = &this->resources;
 	unsigned long rate = clk_get_rate(r->clock[0]);
 	int mode = this->timing_mode;
-	int dll_threshold = 16; /* in ns */
+	int dll_threshold = this->devdata->max_chain_delay;
 	unsigned long delay;
 	unsigned long clk_period;
 	int t_rea;
@@ -886,9 +886,6 @@ static void gpmi_compute_edo_timing(struct gpmi_nand_data *this,
 	/* [3] for GPMI_HW_GPMI_CTRL1 */
 	hw->wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
 
-	if (GPMI_IS_MX6Q(this))
-		dll_threshold = 12;
-
 	/*
 	 * Enlarge 10 times for the numerator and denominator in {3}.
 	 * This make us to get more accurate result.
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index bb77f750e75a..e88d64e1e963 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -53,6 +53,24 @@ static struct nand_ecclayout gpmi_hw_ecclayout = {
 	.oobfree = { {.offset = 0, .length = 0} }
 };
 
+static const struct gpmi_devdata gpmi_devdata_imx23 = {
+	.type = IS_MX23,
+	.bch_max_ecc_strength = 20,
+	.max_chain_delay = 16,
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx28 = {
+	.type = IS_MX28,
+	.bch_max_ecc_strength = 20,
+	.max_chain_delay = 16,
+};
+
+static const struct gpmi_devdata gpmi_devdata_imx6q = {
+	.type = IS_MX6Q,
+	.bch_max_ecc_strength = 40,
+	.max_chain_delay = 12,
+};
+
 static irqreturn_t bch_irq(int irq, void *cookie)
 {
 	struct gpmi_nand_data *this = cookie;
@@ -102,14 +120,8 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
 		/* The mx23/mx28 only support the GF13. */
 		if (geo->gf_len == 14)
 			return false;
-
-		if (geo->ecc_strength > MXS_ECC_STRENGTH_MAX)
-			return false;
-	} else if (GPMI_IS_MX6Q(this)) {
-		if (geo->ecc_strength > MX6_ECC_STRENGTH_MAX)
-			return false;
 	}
-	return true;
+	return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
 }
 
 /*
@@ -270,8 +282,7 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
 			"We can not support this nand chip."
 			" Its required ecc strength(%d) is beyond our"
 			" capability(%d).\n", geo->ecc_strength,
-			(GPMI_IS_MX6Q(this) ? MX6_ECC_STRENGTH_MAX
-					: MXS_ECC_STRENGTH_MAX));
+			this->devdata->bch_max_ecc_strength);
 		return -EINVAL;
 	}
 
@@ -1740,23 +1751,16 @@ err_out:
 	return ret;
 }
 
-static const struct platform_device_id gpmi_ids[] = {
-	{ .name = "imx23-gpmi-nand", .driver_data = IS_MX23, },
-	{ .name = "imx28-gpmi-nand", .driver_data = IS_MX28, },
-	{ .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, },
-	{}
-};
-
 static const struct of_device_id gpmi_nand_id_table[] = {
 	{
 		.compatible = "fsl,imx23-gpmi-nand",
-		.data = (void *)&gpmi_ids[IS_MX23],
+		.data = (void *)&gpmi_devdata_imx23,
 	}, {
 		.compatible = "fsl,imx28-gpmi-nand",
-		.data = (void *)&gpmi_ids[IS_MX28],
+		.data = (void *)&gpmi_devdata_imx28,
 	}, {
 		.compatible = "fsl,imx6q-gpmi-nand",
-		.data = (void *)&gpmi_ids[IS_MX6Q],
+		.data = (void *)&gpmi_devdata_imx6q,
 	}, {}
 };
 MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
@@ -1767,18 +1771,18 @@ static int gpmi_nand_probe(struct platform_device *pdev)
 	const struct of_device_id *of_id;
 	int ret;
 
+	this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
+	if (!this)
+		return -ENOMEM;
+
 	of_id = of_match_device(gpmi_nand_id_table, &pdev->dev);
 	if (of_id) {
-		pdev->id_entry = of_id->data;
+		this->devdata = of_id->data;
 	} else {
 		dev_err(&pdev->dev, "Failed to find the right device id.\n");
 		return -ENODEV;
 	}
 
-	this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
-	if (!this)
-		return -ENOMEM;
-
 	platform_set_drvdata(pdev, this);
 	this->pdev  = pdev;
 	this->dev   = &pdev->dev;
@@ -1823,7 +1827,6 @@ static struct platform_driver gpmi_nand_driver = {
 	},
 	.probe   = gpmi_nand_probe,
 	.remove  = gpmi_nand_remove,
-	.id_table = gpmi_ids,
 };
 module_platform_driver(gpmi_nand_driver);
 
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 4c801fa18725..7904e8329b67 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -119,11 +119,24 @@ struct nand_timing {
 	int8_t  tRHOH_in_ns;
 };
 
+enum gpmi_type {
+	IS_MX23,
+	IS_MX28,
+	IS_MX6Q
+};
+
+struct gpmi_devdata {
+	enum gpmi_type type;
+	int bch_max_ecc_strength;
+	int max_chain_delay; /* See the async EDO mode */
+};
+
 struct gpmi_nand_data {
 	/* flags */
 #define GPMI_ASYNC_EDO_ENABLED	(1 << 0)
 #define GPMI_TIMING_INIT_OK	(1 << 1)
 	int			flags;
+	const struct gpmi_devdata *devdata;
 
 	/* System Interface */
 	struct device		*dev;
@@ -281,15 +294,8 @@ extern int gpmi_read_page(struct gpmi_nand_data *,
 #define STATUS_ERASED		0xff
 #define STATUS_UNCORRECTABLE	0xfe
 
-/* BCH's bit correction capability. */
-#define MXS_ECC_STRENGTH_MAX	20	/* mx23 and mx28 */
-#define MX6_ECC_STRENGTH_MAX	40
-
-/* Use the platform_id to distinguish different Archs. */
-#define IS_MX23			0x0
-#define IS_MX28			0x1
-#define IS_MX6Q			0x2
-#define GPMI_IS_MX23(x)		((x)->pdev->id_entry->driver_data == IS_MX23)
-#define GPMI_IS_MX28(x)		((x)->pdev->id_entry->driver_data == IS_MX28)
-#define GPMI_IS_MX6Q(x)		((x)->pdev->id_entry->driver_data == IS_MX6Q)
+/* Use the devdata to distinguish different Archs. */
+#define GPMI_IS_MX23(x)		((x)->devdata->type == IS_MX23)
+#define GPMI_IS_MX28(x)		((x)->devdata->type == IS_MX28)
+#define GPMI_IS_MX6Q(x)		((x)->devdata->type == IS_MX6Q)
 #endif
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9d01c4df838c..b8eabde8dbdc 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1204,8 +1204,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 	 * ecc.pos. Let's make sure that there are no gaps in ECC positions.
 	 */
 	for (i = 0; i < eccfrag_len - 1; i++) {
-		if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
-			eccpos[i + start_step * chip->ecc.bytes + 1]) {
+		if (eccpos[i + index] + 1 != eccpos[i + index + 1]) {
 			gaps = 1;
 			break;
 		}
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 053c9a2d47c3..97c4c0216c90 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -506,7 +506,7 @@ int __nand_correct_data(unsigned char *buf,
 	if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
 		return 1;	/* error in ECC data; no action needed */
 
-	pr_err("%s: uncorrectable ECC error", __func__);
+	pr_err("%s: uncorrectable ECC error\n", __func__);
 	return -1;
 }
 EXPORT_SYMBOL(__nand_correct_data);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 1ff49b80bdaf..1b800bcda5a4 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1237,6 +1237,7 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
 	return 0;
 }
 
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
 /**
  * erased_sector_bitflips - count bit flips
  * @data:	data sector buffer
@@ -1276,7 +1277,6 @@ static int erased_sector_bitflips(u_char *data, u_char *oob,
 	return flip_bits;
 }
 
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
 /**
  * omap_elm_correct_data - corrects page data area in case error reported
  * @mtd:	MTD device structure
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 7ff473c871a9..ee774ba3728d 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -253,7 +253,7 @@ static int do_ubiblock_request(struct ubiblock *dev, struct request *req)
 	 * flash access anyway.
 	 */
 	mutex_lock(&dev->dev_mutex);
-	ret = ubiblock_read(dev, req->buffer, sec, len);
+	ret = ubiblock_read(dev, bio_data(req->bio), sec, len);
 	mutex_unlock(&dev->dev_mutex);
 
 	return ret;
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index a8efb18e42fa..0ab83708b6a1 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8627,6 +8627,7 @@ bnx2_remove_one(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int
 bnx2_suspend(struct device *device)
 {
@@ -8665,7 +8666,6 @@ bnx2_resume(struct device *device)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static SIMPLE_DEV_PM_OPS(bnx2_pm_ops, bnx2_suspend, bnx2_resume);
 #define BNX2_PM_OPS (&bnx2_pm_ops)
 
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index 751d5c7b312d..7e49c43b7af3 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -4,7 +4,7 @@
 
 config NET_CADENCE
 	bool "Cadence devices"
-	depends on HAS_IOMEM
+	depends on HAS_IOMEM && (ARM || AVR32 || COMPILE_TEST)
 	default y
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y.
@@ -22,7 +22,7 @@ if NET_CADENCE
 
 config ARM_AT91_ETHER
 	tristate "AT91RM9200 Ethernet support"
-	depends on HAS_DMA
+	depends on HAS_DMA && (ARCH_AT91RM9200 || COMPILE_TEST)
 	select MACB
 	---help---
 	  If you wish to compile a kernel for the AT91RM9200 and enable
@@ -30,7 +30,7 @@ config ARM_AT91_ETHER
 
 config MACB
 	tristate "Cadence MACB/GEM support"
-	depends on HAS_DMA
+	depends on HAS_DMA && (PLATFORM_AT32AP || ARCH_AT91 || ARCH_PICOXCELL || ARCH_ZYNQ || COMPILE_TEST)
 	select PHYLIB
 	---help---
 	  The Cadence MACB ethernet interface is found on many Atmel AT32 and
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index 81e8402a74b4..8a96572fdde0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -154,7 +154,7 @@ static int write_l2e(struct adapter *adap, struct l2t_entry *e, int sync)
 	req->params = htons(L2T_W_PORT(e->lport) | L2T_W_NOREPLY(!sync));
 	req->l2t_idx = htons(e->idx);
 	req->vlan = htons(e->vlan);
-	if (e->neigh)
+	if (e->neigh && !(e->neigh->dev->flags & IFF_LOOPBACK))
 		memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac));
 	memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
 
@@ -394,6 +394,8 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
 	if (e) {
 		spin_lock(&e->lock);          /* avoid race with t4_l2t_free */
 		e->state = L2T_STATE_RESOLVING;
+		if (neigh->dev->flags & IFF_LOOPBACK)
+			memcpy(e->dmac, physdev->dev_addr, sizeof(e->dmac));
 		memcpy(e->addr, addr, addr_len);
 		e->ifindex = ifidx;
 		e->hash = hash;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index fb2fe65903c2..bba67681aeaa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -682,7 +682,7 @@ enum {
 	SF_RD_ID        = 0x9f,       /* read ID */
 	SF_ERASE_SECTOR = 0xd8,       /* erase sector */
 
-	FW_MAX_SIZE = 512 * 1024,
+	FW_MAX_SIZE = 16 * SF_SEC_SIZE,
 };
 
 /**
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 8ccaa2520dc3..97db5a7179df 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -374,6 +374,7 @@ enum vf_state {
 #define BE_FLAGS_NAPI_ENABLED			(1 << 9)
 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD		(1 << 11)
 #define BE_FLAGS_VXLAN_OFFLOADS			(1 << 12)
+#define BE_FLAGS_SETUP_DONE			(1 << 13)
 
 #define BE_UC_PMAC_COUNT			30
 #define BE_VF_UC_PMAC_COUNT			2
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 3e6df47b6973..a18645407d21 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2033,11 +2033,13 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
 	bool dummy_wrb;
 	int i, pending_txqs;
 
-	/* Wait for a max of 200ms for all the tx-completions to arrive. */
+	/* Stop polling for compls when HW has been silent for 10ms */
 	do {
 		pending_txqs = adapter->num_tx_qs;
 
 		for_all_tx_queues(adapter, txo, i) {
+			cmpl = 0;
+			num_wrbs = 0;
 			txq = &txo->q;
 			while ((txcp = be_tx_compl_get(&txo->cq))) {
 				end_idx =
@@ -2050,14 +2052,13 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
 			if (cmpl) {
 				be_cq_notify(adapter, txo->cq.id, false, cmpl);
 				atomic_sub(num_wrbs, &txq->used);
-				cmpl = 0;
-				num_wrbs = 0;
+				timeo = 0;
 			}
 			if (atomic_read(&txq->used) == 0)
 				pending_txqs--;
 		}
 
-		if (pending_txqs == 0 || ++timeo > 200)
+		if (pending_txqs == 0 || ++timeo > 10 || be_hw_error(adapter))
 			break;
 
 		mdelay(1);
@@ -2725,6 +2726,12 @@ static int be_close(struct net_device *netdev)
 	struct be_eq_obj *eqo;
 	int i;
 
+	/* This protection is needed as be_close() may be called even when the
+	 * adapter is in cleared state (after eeh perm failure)
+	 */
+	if (!(adapter->flags & BE_FLAGS_SETUP_DONE))
+		return 0;
+
 	be_roce_dev_close(adapter);
 
 	if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
@@ -3055,6 +3062,7 @@ static int be_clear(struct be_adapter *adapter)
 	be_clear_queues(adapter);
 
 	be_msix_disable(adapter);
+	adapter->flags &= ~BE_FLAGS_SETUP_DONE;
 	return 0;
 }
 
@@ -3559,6 +3567,7 @@ static int be_setup(struct be_adapter *adapter)
 		adapter->phy.fc_autoneg = 1;
 
 	be_schedule_worker(adapter);
+	adapter->flags |= BE_FLAGS_SETUP_DONE;
 	return 0;
 err:
 	be_clear(adapter);
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index d04b1c3c9b85..14786c8bf99e 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -91,7 +91,7 @@
 #define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
 #define MVNETA_SERDES_CFG			 0x24A0
 #define      MVNETA_SGMII_SERDES_PROTO		 0x0cc7
-#define      MVNETA_RGMII_SERDES_PROTO		 0x0667
+#define      MVNETA_QSGMII_SERDES_PROTO		 0x0667
 #define MVNETA_TYPE_PRIO                         0x24bc
 #define      MVNETA_FORCE_UNI                    BIT(21)
 #define MVNETA_TXQ_CMD_1                         0x24e4
@@ -2721,29 +2721,44 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp,
 }
 
 /* Power up the port */
-static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
+static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
 {
-	u32 val;
+	u32 ctrl;
 
 	/* MAC Cause register should be cleared */
 	mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
 
-	if (phy_mode == PHY_INTERFACE_MODE_SGMII)
-		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
-	else
-		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_RGMII_SERDES_PROTO);
+	ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
 
-	val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
-
-	val |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+	/* Even though it might look weird, when we're configured in
+	 * SGMII or QSGMII mode, the RGMII bit needs to be set.
+	 */
+	switch(phy_mode) {
+	case PHY_INTERFACE_MODE_QSGMII:
+		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
+		ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+		break;
+	case PHY_INTERFACE_MODE_SGMII:
+		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
+		ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		ctrl |= MVNETA_GMAC2_PORT_RGMII;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	/* Cancel Port Reset */
-	val &= ~MVNETA_GMAC2_PORT_RESET;
-	mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+	ctrl &= ~MVNETA_GMAC2_PORT_RESET;
+	mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl);
 
 	while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) &
 		MVNETA_GMAC2_PORT_RESET) != 0)
 		continue;
+
+	return 0;
 }
 
 /* Device initialization routine */
@@ -2854,7 +2869,12 @@ static int mvneta_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "can't init eth hal\n");
 		goto err_free_stats;
 	}
-	mvneta_port_power_up(pp, phy_mode);
+
+	err = mvneta_port_power_up(pp, phy_mode);
+	if (err < 0) {
+		dev_err(&pdev->dev, "can't power up port\n");
+		goto err_deinit;
+	}
 
 	dram_target_info = mv_mbus_dram_info();
 	if (dram_target_info)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index 70e95324a97d..c2cd8d31bcad 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -66,7 +66,6 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
 
 	cq->ring = ring;
 	cq->is_tx = mode;
-	spin_lock_init(&cq->lock);
 
 	/* Allocate HW buffers on provided NUMA node.
 	 * dev->numa_node is used in mtt range allocation flow.
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index f085c2df5e69..7e4b1720c3d1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1304,15 +1304,11 @@ static void mlx4_en_netpoll(struct net_device *dev)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_cq *cq;
-	unsigned long flags;
 	int i;
 
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		cq = priv->rx_cq[i];
-		spin_lock_irqsave(&cq->lock, flags);
-		napi_synchronize(&cq->napi);
-		mlx4_en_process_rx_cq(dev, cq, 0);
-		spin_unlock_irqrestore(&cq->lock, flags);
+		napi_schedule(&cq->napi);
 	}
 }
 #endif
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index f0ae95f66ceb..cef267e24f9c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -2301,13 +2301,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
 	/* Allow large DMA segments, up to the firmware limit of 1 GB */
 	dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		err = -ENOMEM;
-		goto err_release_regions;
-	}
-
-	dev       = &priv->dev;
+	dev       = pci_get_drvdata(pdev);
+	priv      = mlx4_priv(dev);
 	dev->pdev = pdev;
 	INIT_LIST_HEAD(&priv->ctx_list);
 	spin_lock_init(&priv->ctx_lock);
@@ -2374,10 +2369,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
 			} else {
 				atomic_inc(&pf_loading);
 				err = pci_enable_sriov(pdev, total_vfs);
-				atomic_dec(&pf_loading);
 				if (err) {
 					mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n",
 						 err);
+					atomic_dec(&pf_loading);
 					err = 0;
 				} else {
 					mlx4_warn(dev, "Running in master mode\n");
@@ -2535,8 +2530,10 @@ slave_start:
 	mlx4_sense_init(dev);
 	mlx4_start_sense(dev);
 
-	priv->pci_dev_data = pci_dev_data;
-	pci_set_drvdata(pdev, dev);
+	priv->removed = 0;
+
+	if (mlx4_is_master(dev) && dev->num_vfs)
+		atomic_dec(&pf_loading);
 
 	return 0;
 
@@ -2588,6 +2585,9 @@ err_rel_own:
 	if (!mlx4_is_slave(dev))
 		mlx4_free_ownership(dev);
 
+	if (mlx4_is_master(dev) && dev->num_vfs)
+		atomic_dec(&pf_loading);
+
 	kfree(priv->dev.dev_vfs);
 
 err_free_dev:
@@ -2604,85 +2604,110 @@ err_disable_pdev:
 
 static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+	struct mlx4_priv *priv;
+	struct mlx4_dev *dev;
+
 	printk_once(KERN_INFO "%s", mlx4_version);
 
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev       = &priv->dev;
+	pci_set_drvdata(pdev, dev);
+	priv->pci_dev_data = id->driver_data;
+
 	return __mlx4_init_one(pdev, id->driver_data);
 }
 
-static void mlx4_remove_one(struct pci_dev *pdev)
+static void __mlx4_remove_one(struct pci_dev *pdev)
 {
 	struct mlx4_dev  *dev  = pci_get_drvdata(pdev);
 	struct mlx4_priv *priv = mlx4_priv(dev);
+	int               pci_dev_data;
 	int p;
 
-	if (dev) {
-		/* in SRIOV it is not allowed to unload the pf's
-		 * driver while there are alive vf's */
-		if (mlx4_is_master(dev)) {
-			if (mlx4_how_many_lives_vf(dev))
-				printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
-		}
-		mlx4_stop_sense(dev);
-		mlx4_unregister_device(dev);
+	if (priv->removed)
+		return;
 
-		for (p = 1; p <= dev->caps.num_ports; p++) {
-			mlx4_cleanup_port_info(&priv->port[p]);
-			mlx4_CLOSE_PORT(dev, p);
-		}
+	pci_dev_data = priv->pci_dev_data;
 
-		if (mlx4_is_master(dev))
-			mlx4_free_resource_tracker(dev,
-						   RES_TR_FREE_SLAVES_ONLY);
-
-		mlx4_cleanup_counters_table(dev);
-		mlx4_cleanup_qp_table(dev);
-		mlx4_cleanup_srq_table(dev);
-		mlx4_cleanup_cq_table(dev);
-		mlx4_cmd_use_polling(dev);
-		mlx4_cleanup_eq_table(dev);
-		mlx4_cleanup_mcg_table(dev);
-		mlx4_cleanup_mr_table(dev);
-		mlx4_cleanup_xrcd_table(dev);
-		mlx4_cleanup_pd_table(dev);
+	/* in SRIOV it is not allowed to unload the pf's
+	 * driver while there are alive vf's */
+	if (mlx4_is_master(dev) && mlx4_how_many_lives_vf(dev))
+		printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
+	mlx4_stop_sense(dev);
+	mlx4_unregister_device(dev);
 
-		if (mlx4_is_master(dev))
-			mlx4_free_resource_tracker(dev,
-						   RES_TR_FREE_STRUCTS_ONLY);
-
-		iounmap(priv->kar);
-		mlx4_uar_free(dev, &priv->driver_uar);
-		mlx4_cleanup_uar_table(dev);
-		if (!mlx4_is_slave(dev))
-			mlx4_clear_steering(dev);
-		mlx4_free_eq_table(dev);
-		if (mlx4_is_master(dev))
-			mlx4_multi_func_cleanup(dev);
-		mlx4_close_hca(dev);
-		if (mlx4_is_slave(dev))
-			mlx4_multi_func_cleanup(dev);
-		mlx4_cmd_cleanup(dev);
-
-		if (dev->flags & MLX4_FLAG_MSI_X)
-			pci_disable_msix(pdev);
-		if (dev->flags & MLX4_FLAG_SRIOV) {
-			mlx4_warn(dev, "Disabling SR-IOV\n");
-			pci_disable_sriov(pdev);
-		}
+	for (p = 1; p <= dev->caps.num_ports; p++) {
+		mlx4_cleanup_port_info(&priv->port[p]);
+		mlx4_CLOSE_PORT(dev, p);
+	}
 
-		if (!mlx4_is_slave(dev))
-			mlx4_free_ownership(dev);
+	if (mlx4_is_master(dev))
+		mlx4_free_resource_tracker(dev,
+					   RES_TR_FREE_SLAVES_ONLY);
 
-		kfree(dev->caps.qp0_tunnel);
-		kfree(dev->caps.qp0_proxy);
-		kfree(dev->caps.qp1_tunnel);
-		kfree(dev->caps.qp1_proxy);
-		kfree(dev->dev_vfs);
+	mlx4_cleanup_counters_table(dev);
+	mlx4_cleanup_qp_table(dev);
+	mlx4_cleanup_srq_table(dev);
+	mlx4_cleanup_cq_table(dev);
+	mlx4_cmd_use_polling(dev);
+	mlx4_cleanup_eq_table(dev);
+	mlx4_cleanup_mcg_table(dev);
+	mlx4_cleanup_mr_table(dev);
+	mlx4_cleanup_xrcd_table(dev);
+	mlx4_cleanup_pd_table(dev);
 
-		kfree(priv);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-		pci_set_drvdata(pdev, NULL);
+	if (mlx4_is_master(dev))
+		mlx4_free_resource_tracker(dev,
+					   RES_TR_FREE_STRUCTS_ONLY);
+
+	iounmap(priv->kar);
+	mlx4_uar_free(dev, &priv->driver_uar);
+	mlx4_cleanup_uar_table(dev);
+	if (!mlx4_is_slave(dev))
+		mlx4_clear_steering(dev);
+	mlx4_free_eq_table(dev);
+	if (mlx4_is_master(dev))
+		mlx4_multi_func_cleanup(dev);
+	mlx4_close_hca(dev);
+	if (mlx4_is_slave(dev))
+		mlx4_multi_func_cleanup(dev);
+	mlx4_cmd_cleanup(dev);
+
+	if (dev->flags & MLX4_FLAG_MSI_X)
+		pci_disable_msix(pdev);
+	if (dev->flags & MLX4_FLAG_SRIOV) {
+		mlx4_warn(dev, "Disabling SR-IOV\n");
+		pci_disable_sriov(pdev);
+		dev->num_vfs = 0;
 	}
+
+	if (!mlx4_is_slave(dev))
+		mlx4_free_ownership(dev);
+
+	kfree(dev->caps.qp0_tunnel);
+	kfree(dev->caps.qp0_proxy);
+	kfree(dev->caps.qp1_tunnel);
+	kfree(dev->caps.qp1_proxy);
+	kfree(dev->dev_vfs);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	memset(priv, 0, sizeof(*priv));
+	priv->pci_dev_data = pci_dev_data;
+	priv->removed = 1;
+}
+
+static void mlx4_remove_one(struct pci_dev *pdev)
+{
+	struct mlx4_dev  *dev  = pci_get_drvdata(pdev);
+	struct mlx4_priv *priv = mlx4_priv(dev);
+
+	__mlx4_remove_one(pdev);
+	kfree(priv);
+	pci_set_drvdata(pdev, NULL);
 }
 
 int mlx4_restart_one(struct pci_dev *pdev)
@@ -2692,7 +2717,7 @@ int mlx4_restart_one(struct pci_dev *pdev)
 	int		  pci_dev_data;
 
 	pci_dev_data = priv->pci_dev_data;
-	mlx4_remove_one(pdev);
+	__mlx4_remove_one(pdev);
 	return __mlx4_init_one(pdev, pci_dev_data);
 }
 
@@ -2747,7 +2772,7 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table);
 static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
 					      pci_channel_state_t state)
 {
-	mlx4_remove_one(pdev);
+	__mlx4_remove_one(pdev);
 
 	return state == pci_channel_io_perm_failure ?
 		PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
@@ -2755,11 +2780,11 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
 
 static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
 {
-	const struct pci_device_id *id;
-	int ret;
+	struct mlx4_dev	 *dev  = pci_get_drvdata(pdev);
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int               ret;
 
-	id = pci_match_id(mlx4_pci_table, pdev);
-	ret = __mlx4_init_one(pdev, id->driver_data);
+	ret = __mlx4_init_one(pdev, priv->pci_dev_data);
 
 	return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index cf8be41abb36..f9c465101963 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -800,6 +800,7 @@ struct mlx4_priv {
 	spinlock_t		ctx_lock;
 
 	int			pci_dev_data;
+	int                     removed;
 
 	struct list_head        pgdir_list;
 	struct mutex            pgdir_mutex;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 7a733c287744..04d9b6fe3e80 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -319,7 +319,6 @@ struct mlx4_en_cq {
 	struct mlx4_cq          mcq;
 	struct mlx4_hwq_resources wqres;
 	int                     ring;
-	spinlock_t              lock;
 	struct net_device      *dev;
 	struct napi_struct	napi;
 	int size;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index b48737dcd3c5..ba20c721ee97 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -2139,8 +2139,6 @@ static int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
 	ahw->max_mac_filters = nic_info.max_mac_filters;
 	ahw->max_mtu = nic_info.max_mtu;
 
-	adapter->max_tx_rings = ahw->max_tx_ques;
-	adapter->max_sds_rings = ahw->max_rx_ques;
 	/* eSwitch capability indicates vNIC mode.
 	 * vNIC and SRIOV are mutually exclusive operational modes.
 	 * If SR-IOV capability is detected, SR-IOV physical function
@@ -2161,6 +2159,7 @@ static int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
 int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	u16 max_sds_rings, max_tx_rings;
 	int ret;
 
 	ret = qlcnic_83xx_get_nic_configuration(adapter);
@@ -2173,18 +2172,21 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
 		if (qlcnic_83xx_config_vnic_opmode(adapter))
 			return -EIO;
 
-		adapter->max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;
-		adapter->max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;
+		max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;
+		max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;
 	} else if (ret == QLC_83XX_DEFAULT_OPMODE) {
 		ahw->nic_mode = QLCNIC_DEFAULT_MODE;
 		adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
 		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
-		adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
-		adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
+		max_sds_rings = QLCNIC_MAX_SDS_RINGS;
+		max_tx_rings = QLCNIC_MAX_TX_RINGS;
 	} else {
 		return -EIO;
 	}
 
+	adapter->max_sds_rings = min(ahw->max_rx_ques, max_sds_rings);
+	adapter->max_tx_rings = min(ahw->max_tx_ques, max_tx_rings);
+
 	return 0;
 }
 
@@ -2348,15 +2350,16 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
 		goto disable_intr;
 	}
 
+	INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
+
 	err = qlcnic_83xx_setup_mbx_intr(adapter);
 	if (err)
 		goto disable_mbx_intr;
 
 	qlcnic_83xx_clear_function_resources(adapter);
-
-	INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
-
+	qlcnic_dcb_enable(adapter->dcb);
 	qlcnic_83xx_initialize_nic(adapter, 1);
+	qlcnic_dcb_get_info(adapter->dcb);
 
 	/* Configure default, SR-IOV or Virtual NIC mode of operation */
 	err = qlcnic_83xx_configure_opmode(adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 64dcbf33d8f0..c1e11f5715b0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -883,8 +883,6 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
 		npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
 		npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
 		npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
-		adapter->max_tx_rings = npar_info->max_tx_ques;
-		adapter->max_sds_rings = npar_info->max_rx_ques;
 	}
 
 	qlcnic_free_mbx_args(&cmd);
@@ -1356,6 +1354,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
 			arg2 &= ~BIT_3;
 		break;
 	case QLCNIC_ADD_VLAN:
+			arg1 &= ~(0x0ffff << 16);
 			arg1 |= (BIT_2 | BIT_5);
 			arg1 |= (esw_cfg->vlan_id << 16);
 			break;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
index 7d4f54912bad..a51fe18f09a8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
@@ -330,8 +330,6 @@ static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
 		goto out_free_cfg;
 	}
 
-	qlcnic_dcb_get_info(dcb);
-
 	return 0;
 out_free_cfg:
 	kfree(dcb->cfg);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 309d05640883..dbf75393f758 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -670,7 +670,7 @@ int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *adapter)
 	else
 		num_msix += adapter->drv_tx_rings;
 
-	if (adapter->drv_rss_rings  > 0)
+	if (adapter->drv_rss_rings > 0)
 		num_msix += adapter->drv_rss_rings;
 	else
 		num_msix += adapter->drv_sds_rings;
@@ -686,19 +686,15 @@ int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *adapter)
 			return -ENOMEM;
 	}
 
-restore:
 	for (vector = 0; vector < num_msix; vector++)
 		adapter->msix_entries[vector].entry = vector;
 
+restore:
 	err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
-	if (err == 0) {
-		adapter->ahw->num_msix = num_msix;
-		if (adapter->drv_tss_rings > 0)
-			adapter->drv_tx_rings = adapter->drv_tss_rings;
+	if (err > 0) {
+		if (!adapter->drv_tss_rings && !adapter->drv_rss_rings)
+			return -ENOSPC;
 
-		if (adapter->drv_rss_rings > 0)
-			adapter->drv_sds_rings = adapter->drv_rss_rings;
-	} else {
 		netdev_info(adapter->netdev,
 			    "Unable to allocate %d MSI-X vectors, Available vectors %d\n",
 			    num_msix, err);
@@ -716,12 +712,20 @@ restore:
 			    "Restoring %d Tx, %d SDS rings for total %d vectors.\n",
 			    adapter->drv_tx_rings, adapter->drv_sds_rings,
 			    num_msix);
-		goto restore;
 
-		err = -EIO;
+		goto restore;
+	} else if (err < 0) {
+		return err;
 	}
 
-	return err;
+	adapter->ahw->num_msix = num_msix;
+	if (adapter->drv_tss_rings > 0)
+		adapter->drv_tx_rings = adapter->drv_tss_rings;
+
+	if (adapter->drv_rss_rings > 0)
+		adapter->drv_sds_rings = adapter->drv_rss_rings;
+
+	return 0;
 }
 
 int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
@@ -2528,8 +2532,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_free_hw;
 	}
 
-	qlcnic_dcb_enable(adapter->dcb);
-
 	if (qlcnic_read_mac_addr(adapter))
 		dev_warn(&pdev->dev, "failed to read mac addr\n");
 
@@ -2549,7 +2551,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			 "Device does not support MSI interrupts\n");
 
 	if (qlcnic_82xx_check(adapter)) {
+		qlcnic_dcb_enable(adapter->dcb);
+		qlcnic_dcb_get_info(adapter->dcb);
 		err = qlcnic_setup_intr(adapter);
+
 		if (err) {
 			dev_err(&pdev->dev, "Failed to setup interrupt\n");
 			goto err_out_disable_msi;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
index 14f748cbf0de..280137991544 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
@@ -461,6 +461,16 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 
+	if (pci_vfs_assigned(adapter->pdev)) {
+		netdev_err(adapter->netdev,
+			   "SR-IOV VFs belonging to port %d are assigned to VMs. SR-IOV can not be disabled on this port\n",
+			   adapter->portnum);
+		netdev_info(adapter->netdev,
+			    "Please detach SR-IOV VFs belonging to port %d from VMs, and then try to disable SR-IOV on this port\n",
+			    adapter->portnum);
+		return -EPERM;
+	}
+
 	rtnl_lock();
 	if (netif_running(netdev))
 		__qlcnic_down(adapter, netdev);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 448d156c3d08..cd346e27f2e1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -354,7 +354,7 @@ int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
 {
 	int i;
 
-	for (i = 0; i < adapter->ahw->max_vnic_func; i++) {
+	for (i = 0; i < adapter->ahw->total_nic_func; i++) {
 		if (adapter->npars[i].pci_func == pci_func)
 			return i;
 	}
@@ -720,6 +720,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
 	struct qlcnic_npar_func_cfg *np_cfg;
 	struct qlcnic_info nic_info;
+	u8 pci_func;
 	int i, ret;
 	u32 count;
 
@@ -729,26 +730,28 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
 
 	count = size / sizeof(struct qlcnic_npar_func_cfg);
 	for (i = 0; i < adapter->ahw->total_nic_func; i++) {
-		if (qlcnic_is_valid_nic_func(adapter, i) < 0)
-			continue;
 		if (adapter->npars[i].pci_func >= count) {
 			dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n",
 				__func__, adapter->ahw->total_nic_func, count);
 			continue;
 		}
-		ret = qlcnic_get_nic_info(adapter, &nic_info, i);
-		if (ret)
-			return ret;
 		if (!adapter->npars[i].eswitch_status)
 			continue;
-		np_cfg[i].pci_func = i;
-		np_cfg[i].op_mode = (u8)nic_info.op_mode;
-		np_cfg[i].port_num = nic_info.phys_port;
-		np_cfg[i].fw_capab = nic_info.capabilities;
-		np_cfg[i].min_bw = nic_info.min_tx_bw;
-		np_cfg[i].max_bw = nic_info.max_tx_bw;
-		np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
-		np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
+		pci_func = adapter->npars[i].pci_func;
+		if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
+			continue;
+		ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
+		if (ret)
+			return ret;
+
+		np_cfg[pci_func].pci_func = pci_func;
+		np_cfg[pci_func].op_mode = (u8)nic_info.op_mode;
+		np_cfg[pci_func].port_num = nic_info.phys_port;
+		np_cfg[pci_func].fw_capab = nic_info.capabilities;
+		np_cfg[pci_func].min_bw = nic_info.min_tx_bw;
+		np_cfg[pci_func].max_bw = nic_info.max_tx_bw;
+		np_cfg[pci_func].max_tx_queues = nic_info.max_tx_ques;
+		np_cfg[pci_func].max_rx_queues = nic_info.max_rx_ques;
 	}
 	return size;
 }
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 21c20ea0dad0..b5ed30a39144 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -738,8 +738,11 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type)
 	/* If it was a port reset, trigger reallocation of MC resources.
 	 * Note that on an MC reset nothing needs to be done now because we'll
 	 * detect the MC reset later and handle it then.
+	 * For an FLR, we never get an MC reset event, but the MC has reset all
+	 * resources assigned to us, so we have to trigger reallocation now.
 	 */
-	if (reset_type == RESET_TYPE_ALL && !rc)
+	if ((reset_type == RESET_TYPE_ALL ||
+	     reset_type == RESET_TYPE_MCDI_TIMEOUT) && !rc)
 		efx_ef10_reset_mc_allocations(efx);
 	return rc;
 }
@@ -2141,6 +2144,11 @@ static int efx_ef10_fini_dmaq(struct efx_nic *efx)
 	return 0;
 }
 
+static void efx_ef10_prepare_flr(struct efx_nic *efx)
+{
+	atomic_set(&efx->active_queues, 0);
+}
+
 static bool efx_ef10_filter_equal(const struct efx_filter_spec *left,
 				  const struct efx_filter_spec *right)
 {
@@ -3603,6 +3611,8 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
 	.probe_port = efx_mcdi_port_probe,
 	.remove_port = efx_mcdi_port_remove,
 	.fini_dmaq = efx_ef10_fini_dmaq,
+	.prepare_flr = efx_ef10_prepare_flr,
+	.finish_flr = efx_port_dummy_op_void,
 	.describe_stats = efx_ef10_describe_stats,
 	.update_stats = efx_ef10_update_stats,
 	.start_stats = efx_mcdi_mac_start_stats,
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 57b971e5e6b2..63d595fd3cc5 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -76,6 +76,7 @@ const char *const efx_reset_type_names[] = {
 	[RESET_TYPE_RECOVER_OR_ALL]     = "RECOVER_OR_ALL",
 	[RESET_TYPE_WORLD]              = "WORLD",
 	[RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE",
+	[RESET_TYPE_MC_BIST]		= "MC_BIST",
 	[RESET_TYPE_DISABLE]            = "DISABLE",
 	[RESET_TYPE_TX_WATCHDOG]        = "TX_WATCHDOG",
 	[RESET_TYPE_INT_ERROR]          = "INT_ERROR",
@@ -83,7 +84,7 @@ const char *const efx_reset_type_names[] = {
 	[RESET_TYPE_DMA_ERROR]          = "DMA_ERROR",
 	[RESET_TYPE_TX_SKIP]            = "TX_SKIP",
 	[RESET_TYPE_MC_FAILURE]         = "MC_FAILURE",
-	[RESET_TYPE_MC_BIST]		= "MC_BIST",
+	[RESET_TYPE_MCDI_TIMEOUT]	= "MCDI_TIMEOUT (FLR)",
 };
 
 /* Reset workqueue. If any NIC has a hardware failure then a reset will be
@@ -1739,7 +1740,8 @@ static void efx_start_all(struct efx_nic *efx)
 
 	/* Check that it is appropriate to restart the interface. All
 	 * of these flags are safe to read under just the rtnl lock */
-	if (efx->port_enabled || !netif_running(efx->net_dev))
+	if (efx->port_enabled || !netif_running(efx->net_dev) ||
+	    efx->reset_pending)
 		return;
 
 	efx_start_port(efx);
@@ -2334,6 +2336,9 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
 {
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
+	if (method == RESET_TYPE_MCDI_TIMEOUT)
+		efx->type->prepare_flr(efx);
+
 	efx_stop_all(efx);
 	efx_disable_interrupts(efx);
 
@@ -2354,6 +2359,10 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
 
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
+	if (method == RESET_TYPE_MCDI_TIMEOUT)
+		efx->type->finish_flr(efx);
+
+	/* Ensure that SRAM is initialised even if we're disabling the device */
 	rc = efx->type->init(efx);
 	if (rc) {
 		netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n");
@@ -2417,7 +2426,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
 	/* Clear flags for the scopes we covered.  We assume the NIC and
 	 * driver are now quiescent so that there is no race here.
 	 */
-	efx->reset_pending &= -(1 << (method + 1));
+	if (method < RESET_TYPE_MAX_METHOD)
+		efx->reset_pending &= -(1 << (method + 1));
+	else /* it doesn't fit into the well-ordered scope hierarchy */
+		__clear_bit(method, &efx->reset_pending);
 
 	/* Reinitialise bus-mastering, which may have been turned off before
 	 * the reset was scheduled. This is still appropriate, even in the
@@ -2546,6 +2558,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
 	case RESET_TYPE_DISABLE:
 	case RESET_TYPE_RECOVER_OR_DISABLE:
 	case RESET_TYPE_MC_BIST:
+	case RESET_TYPE_MCDI_TIMEOUT:
 		method = type;
 		netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
 			  RESET_TYPE(method));
diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h
index 75ef7ef6450b..d1dbb5fb31bb 100644
--- a/drivers/net/ethernet/sfc/enum.h
+++ b/drivers/net/ethernet/sfc/enum.h
@@ -143,6 +143,7 @@ enum efx_loopback_mode {
  * @RESET_TYPE_WORLD: Reset as much as possible
  * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if
  * unsuccessful.
+ * @RESET_TYPE_MC_BIST: MC entering BIST mode.
  * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled
  * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
  * @RESET_TYPE_INT_ERROR: reset due to internal error
@@ -150,14 +151,16 @@ enum efx_loopback_mode {
  * @RESET_TYPE_DMA_ERROR: DMA error
  * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors
  * @RESET_TYPE_MC_FAILURE: MC reboot/assertion
+ * @RESET_TYPE_MCDI_TIMEOUT: MCDI timeout.
  */
 enum reset_type {
-	RESET_TYPE_INVISIBLE = 0,
-	RESET_TYPE_RECOVER_OR_ALL = 1,
-	RESET_TYPE_ALL = 2,
-	RESET_TYPE_WORLD = 3,
-	RESET_TYPE_RECOVER_OR_DISABLE = 4,
-	RESET_TYPE_DISABLE = 5,
+	RESET_TYPE_INVISIBLE,
+	RESET_TYPE_RECOVER_OR_ALL,
+	RESET_TYPE_ALL,
+	RESET_TYPE_WORLD,
+	RESET_TYPE_RECOVER_OR_DISABLE,
+	RESET_TYPE_MC_BIST,
+	RESET_TYPE_DISABLE,
 	RESET_TYPE_MAX_METHOD,
 	RESET_TYPE_TX_WATCHDOG,
 	RESET_TYPE_INT_ERROR,
@@ -165,7 +168,13 @@ enum reset_type {
 	RESET_TYPE_DMA_ERROR,
 	RESET_TYPE_TX_SKIP,
 	RESET_TYPE_MC_FAILURE,
-	RESET_TYPE_MC_BIST,
+	/* RESET_TYPE_MCDI_TIMEOUT is actually a method, not just a reason, but
+	 * it doesn't fit the scope hierarchy (not well-ordered by inclusion).
+	 * We encode this by having its enum value be greater than
+	 * RESET_TYPE_MAX_METHOD. This also prevents issuing it with
+	 * efx_ioctl_reset.
+	 */
+	RESET_TYPE_MCDI_TIMEOUT,
 	RESET_TYPE_MAX,
 };
 
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 8ec20b713cc6..fae25a418647 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2696,6 +2696,8 @@ const struct efx_nic_type falcon_a1_nic_type = {
 	.fini_dmaq = efx_farch_fini_dmaq,
 	.prepare_flush = falcon_prepare_flush,
 	.finish_flush = efx_port_dummy_op_void,
+	.prepare_flr = efx_port_dummy_op_void,
+	.finish_flr = efx_farch_finish_flr,
 	.describe_stats = falcon_describe_nic_stats,
 	.update_stats = falcon_update_nic_stats,
 	.start_stats = falcon_start_nic_stats,
@@ -2790,6 +2792,8 @@ const struct efx_nic_type falcon_b0_nic_type = {
 	.fini_dmaq = efx_farch_fini_dmaq,
 	.prepare_flush = falcon_prepare_flush,
 	.finish_flush = efx_port_dummy_op_void,
+	.prepare_flr = efx_port_dummy_op_void,
+	.finish_flr = efx_farch_finish_flr,
 	.describe_stats = falcon_describe_nic_stats,
 	.update_stats = falcon_update_nic_stats,
 	.start_stats = falcon_start_nic_stats,
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index a08761360cdf..0537381cd2f6 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -741,6 +741,28 @@ int efx_farch_fini_dmaq(struct efx_nic *efx)
 	return rc;
 }
 
+/* Reset queue and flush accounting after FLR
+ *
+ * One possible cause of FLR recovery is that DMA may be failing (eg. if bus
+ * mastering was disabled), in which case we don't receive (RXQ) flush
+ * completion events.  This means that efx->rxq_flush_outstanding remained at 4
+ * after the FLR; also, efx->active_queues was non-zero (as no flush completion
+ * events were received, and we didn't go through efx_check_tx_flush_complete())
+ * If we don't fix this up, on the next call to efx_realloc_channels() we won't
+ * flush any RX queues because efx->rxq_flush_outstanding is at the limit of 4
+ * for batched flush requests; and the efx->active_queues gets messed up because
+ * we keep incrementing for the newly initialised queues, but it never went to
+ * zero previously.  Then we get a timeout every time we try to restart the
+ * queues, as it doesn't go back to zero when we should be flushing the queues.
+ */
+void efx_farch_finish_flr(struct efx_nic *efx)
+{
+	atomic_set(&efx->rxq_flush_pending, 0);
+	atomic_set(&efx->rxq_flush_outstanding, 0);
+	atomic_set(&efx->active_queues, 0);
+}
+
+
 /**************************************************************************
  *
  * Event queue processing
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 7bd4b14bf3b3..5239cf9bdc56 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -52,12 +52,7 @@ static void efx_mcdi_timeout_async(unsigned long context);
 static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
 			       bool *was_attached_out);
 static bool efx_mcdi_poll_once(struct efx_nic *efx);
-
-static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
-{
-	EFX_BUG_ON_PARANOID(!efx->mcdi);
-	return &efx->mcdi->iface;
-}
+static void efx_mcdi_abandon(struct efx_nic *efx);
 
 int efx_mcdi_init(struct efx_nic *efx)
 {
@@ -558,6 +553,8 @@ static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
 			rc = 0;
 		}
 
+		efx_mcdi_abandon(efx);
+
 		/* Close the race with efx_mcdi_ev_cpl() executing just too late
 		 * and completing a request we've just cancelled, by ensuring
 		 * that the seqno check therein fails.
@@ -672,6 +669,9 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
 	if (efx->mc_bist_for_other_fn)
 		return -ENETDOWN;
 
+	if (mcdi->mode == MCDI_MODE_FAIL)
+		return -ENETDOWN;
+
 	efx_mcdi_acquire_sync(mcdi);
 	efx_mcdi_send_request(efx, cmd, inbuf, inlen);
 	return 0;
@@ -812,7 +812,11 @@ void efx_mcdi_mode_poll(struct efx_nic *efx)
 		return;
 
 	mcdi = efx_mcdi(efx);
-	if (mcdi->mode == MCDI_MODE_POLL)
+	/* If already in polling mode, nothing to do.
+	 * If in fail-fast state, don't switch to polled completion.
+	 * FLR recovery will do that later.
+	 */
+	if (mcdi->mode == MCDI_MODE_POLL || mcdi->mode == MCDI_MODE_FAIL)
 		return;
 
 	/* We can switch from event completion to polled completion, because
@@ -841,8 +845,8 @@ void efx_mcdi_flush_async(struct efx_nic *efx)
 
 	mcdi = efx_mcdi(efx);
 
-	/* We must be in polling mode so no more requests can be queued */
-	BUG_ON(mcdi->mode != MCDI_MODE_POLL);
+	/* We must be in poll or fail mode so no more requests can be queued */
+	BUG_ON(mcdi->mode == MCDI_MODE_EVENTS);
 
 	del_timer_sync(&mcdi->async_timer);
 
@@ -875,8 +879,11 @@ void efx_mcdi_mode_event(struct efx_nic *efx)
 		return;
 
 	mcdi = efx_mcdi(efx);
-
-	if (mcdi->mode == MCDI_MODE_EVENTS)
+	/* If already in event completion mode, nothing to do.
+	 * If in fail-fast state, don't switch to event completion.  FLR
+	 * recovery will do that later.
+	 */
+	if (mcdi->mode == MCDI_MODE_EVENTS || mcdi->mode == MCDI_MODE_FAIL)
 		return;
 
 	/* We can't switch from polled to event completion in the middle of a
@@ -966,6 +973,19 @@ static void efx_mcdi_ev_bist(struct efx_nic *efx)
 	spin_unlock(&mcdi->iface_lock);
 }
 
+/* MCDI timeouts seen, so make all MCDI calls fail-fast and issue an FLR to try
+ * to recover.
+ */
+static void efx_mcdi_abandon(struct efx_nic *efx)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+	if (xchg(&mcdi->mode, MCDI_MODE_FAIL) == MCDI_MODE_FAIL)
+		return; /* it had already been done */
+	netif_dbg(efx, hw, efx->net_dev, "MCDI is timing out; trying to recover\n");
+	efx_schedule_reset(efx, RESET_TYPE_MCDI_TIMEOUT);
+}
+
 /* Called from  falcon_process_eventq for MCDI events */
 void efx_mcdi_process_event(struct efx_channel *channel,
 			    efx_qword_t *event)
@@ -1512,6 +1532,19 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
 {
 	int rc;
 
+	/* If MCDI is down, we can't handle_assertion */
+	if (method == RESET_TYPE_MCDI_TIMEOUT) {
+		rc = pci_reset_function(efx->pci_dev);
+		if (rc)
+			return rc;
+		/* Re-enable polled MCDI completion */
+		if (efx->mcdi) {
+			struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+			mcdi->mode = MCDI_MODE_POLL;
+		}
+		return 0;
+	}
+
 	/* Recover from a failed assertion pre-reset */
 	rc = efx_mcdi_handle_assertion(efx);
 	if (rc)
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 52931aebf3c3..56465f7465a2 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -28,9 +28,16 @@ enum efx_mcdi_state {
 	MCDI_STATE_COMPLETED,
 };
 
+/**
+ * enum efx_mcdi_mode - MCDI transaction mode
+ * @MCDI_MODE_POLL: poll for MCDI completion, until timeout
+ * @MCDI_MODE_EVENTS: wait for an mcdi_event.  On timeout, poll once
+ * @MCDI_MODE_FAIL: we think MCDI is dead, so fail-fast all calls
+ */
 enum efx_mcdi_mode {
 	MCDI_MODE_POLL,
 	MCDI_MODE_EVENTS,
+	MCDI_MODE_FAIL,
 };
 
 /**
@@ -104,6 +111,12 @@ struct efx_mcdi_data {
 	u32 fn_flags;
 };
 
+static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
+{
+	EFX_BUG_ON_PARANOID(!efx->mcdi);
+	return &efx->mcdi->iface;
+}
+
 #ifdef CONFIG_SFC_MCDI_MON
 static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
 {
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 8a400a0595eb..5bdae8ed7c57 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -972,6 +972,8 @@ struct efx_mtd_partition {
  *	(for Falcon architecture)
  * @finish_flush: Clean up after flushing the DMA queues (for Falcon
  *	architecture)
+ * @prepare_flr: Prepare for an FLR
+ * @finish_flr: Clean up after an FLR
  * @describe_stats: Describe statistics for ethtool
  * @update_stats: Update statistics not provided by event handling.
  *	Either argument may be %NULL.
@@ -1100,6 +1102,8 @@ struct efx_nic_type {
 	int (*fini_dmaq)(struct efx_nic *efx);
 	void (*prepare_flush)(struct efx_nic *efx);
 	void (*finish_flush)(struct efx_nic *efx);
+	void (*prepare_flr)(struct efx_nic *efx);
+	void (*finish_flr)(struct efx_nic *efx);
 	size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
 	size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
 			       struct rtnl_link_stats64 *core_stats);
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index a001fae1a8d7..d3ad8ed8d901 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -757,6 +757,7 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
 int efx_nic_flush_queues(struct efx_nic *efx);
 void siena_prepare_flush(struct efx_nic *efx);
 int efx_farch_fini_dmaq(struct efx_nic *efx);
+void efx_farch_finish_flr(struct efx_nic *efx);
 void siena_finish_flush(struct efx_nic *efx);
 void falcon_start_nic_stats(struct efx_nic *efx);
 void falcon_stop_nic_stats(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 23f3a6f7737a..50ffefed492c 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -921,6 +921,8 @@ const struct efx_nic_type siena_a0_nic_type = {
 	.fini_dmaq = efx_farch_fini_dmaq,
 	.prepare_flush = siena_prepare_flush,
 	.finish_flush = siena_finish_flush,
+	.prepare_flr = efx_port_dummy_op_void,
+	.finish_flr = efx_farch_finish_flr,
 	.describe_stats = siena_describe_nic_stats,
 	.update_stats = siena_update_nic_stats,
 	.start_stats = efx_mcdi_mac_start_stats,
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 430bb0db9bc4..e36f194673a4 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -365,7 +365,7 @@ __at86rf230_read_subreg(struct at86rf230_local *lp,
 	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
 
 	if (status == 0)
-		*data = buf[1];
+		*data = (buf[1] & mask) >> shift;
 
 	return status;
 }
@@ -1025,14 +1025,6 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 		return -EINVAL;
 	}
 
-	rc = at86rf230_read_subreg(lp, SR_AVDD_OK, &status);
-	if (rc)
-		return rc;
-	if (!status) {
-		dev_err(&lp->spi->dev, "AVDD error\n");
-		return -EINVAL;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 768dfe9a9315..6d3e2093bf7f 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1755,17 +1755,4 @@ static struct pci_driver donauboe_pci_driver = {
 	.resume		= toshoboe_wakeup 
 };
 
-static int __init
-donauboe_init (void)
-{
-  return pci_register_driver(&donauboe_pci_driver);
-}
-
-static void __exit
-donauboe_cleanup (void)
-{
-  pci_unregister_driver(&donauboe_pci_driver);
-}
-
-module_init(donauboe_init);
-module_exit(donauboe_cleanup);
+module_pci_driver(donauboe_pci_driver);
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index e701433bf52f..9c4defdec67b 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -32,29 +32,39 @@
 
 struct mdio_gpio_info {
 	struct mdiobb_ctrl ctrl;
-	int mdc, mdio;
+	int mdc, mdio, mdo;
+	int mdc_active_low, mdio_active_low, mdo_active_low;
 };
 
 static void *mdio_gpio_of_get_data(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct mdio_gpio_platform_data *pdata;
+	enum of_gpio_flags flags;
 	int ret;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return NULL;
 
-	ret = of_get_gpio(np, 0);
+	ret = of_get_gpio_flags(np, 0, &flags);
 	if (ret < 0)
 		return NULL;
 
 	pdata->mdc = ret;
+	pdata->mdc_active_low = flags & OF_GPIO_ACTIVE_LOW;
 
-	ret = of_get_gpio(np, 1);
+	ret = of_get_gpio_flags(np, 1, &flags);
 	if (ret < 0)
 		return NULL;
 	pdata->mdio = ret;
+	pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+	ret = of_get_gpio_flags(np, 2, &flags);
+	if (ret > 0) {
+		pdata->mdo = ret;
+		pdata->mdo_active_low = flags & OF_GPIO_ACTIVE_LOW;
+	}
 
 	return pdata;
 }
@@ -64,8 +74,19 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
 	struct mdio_gpio_info *bitbang =
 		container_of(ctrl, struct mdio_gpio_info, ctrl);
 
+	if (bitbang->mdo) {
+		/* Separate output pin. Always set its value to high
+		 * when changing direction. If direction is input,
+		 * assume the pin serves as pull-up. If direction is
+		 * output, the default value is high.
+		 */
+		gpio_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low);
+		return;
+	}
+
 	if (dir)
-		gpio_direction_output(bitbang->mdio, 1);
+		gpio_direction_output(bitbang->mdio,
+				      1 ^ bitbang->mdio_active_low);
 	else
 		gpio_direction_input(bitbang->mdio);
 }
@@ -75,7 +96,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
 	struct mdio_gpio_info *bitbang =
 		container_of(ctrl, struct mdio_gpio_info, ctrl);
 
-	return gpio_get_value(bitbang->mdio);
+	return gpio_get_value(bitbang->mdio) ^ bitbang->mdio_active_low;
 }
 
 static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -83,7 +104,10 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
 	struct mdio_gpio_info *bitbang =
 		container_of(ctrl, struct mdio_gpio_info, ctrl);
 
-	gpio_set_value(bitbang->mdio, what);
+	if (bitbang->mdo)
+		gpio_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low);
+	else
+		gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low);
 }
 
 static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -91,7 +115,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
 	struct mdio_gpio_info *bitbang =
 		container_of(ctrl, struct mdio_gpio_info, ctrl);
 
-	gpio_set_value(bitbang->mdc, what);
+	gpio_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low);
 }
 
 static struct mdiobb_ops mdio_gpio_ops = {
@@ -110,18 +134,22 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
 	struct mdio_gpio_info *bitbang;
 	int i;
 
-	bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
+	bitbang = devm_kzalloc(dev, sizeof(*bitbang), GFP_KERNEL);
 	if (!bitbang)
 		goto out;
 
 	bitbang->ctrl.ops = &mdio_gpio_ops;
 	bitbang->ctrl.reset = pdata->reset;
 	bitbang->mdc = pdata->mdc;
+	bitbang->mdc_active_low = pdata->mdc_active_low;
 	bitbang->mdio = pdata->mdio;
+	bitbang->mdio_active_low = pdata->mdio_active_low;
+	bitbang->mdo = pdata->mdo;
+	bitbang->mdo_active_low = pdata->mdo_active_low;
 
 	new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
 	if (!new_bus)
-		goto out_free_bitbang;
+		goto out;
 
 	new_bus->name = "GPIO Bitbanged MDIO",
 
@@ -138,11 +166,18 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
 
 	snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id);
 
-	if (gpio_request(bitbang->mdc, "mdc"))
+	if (devm_gpio_request(dev, bitbang->mdc, "mdc"))
+		goto out_free_bus;
+
+	if (devm_gpio_request(dev, bitbang->mdio, "mdio"))
 		goto out_free_bus;
 
-	if (gpio_request(bitbang->mdio, "mdio"))
-		goto out_free_mdc;
+	if (bitbang->mdo) {
+		if (devm_gpio_request(dev, bitbang->mdo, "mdo"))
+			goto out_free_bus;
+		gpio_direction_output(bitbang->mdo, 1);
+		gpio_direction_input(bitbang->mdio);
+	}
 
 	gpio_direction_output(bitbang->mdc, 0);
 
@@ -150,12 +185,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
 
 	return new_bus;
 
-out_free_mdc:
-	gpio_free(bitbang->mdc);
 out_free_bus:
 	free_mdio_bitbang(new_bus);
-out_free_bitbang:
-	kfree(bitbang);
 out:
 	return NULL;
 }
@@ -163,13 +194,8 @@ out:
 static void mdio_gpio_bus_deinit(struct device *dev)
 {
 	struct mii_bus *bus = dev_get_drvdata(dev);
-	struct mdio_gpio_info *bitbang = bus->priv;
 
-	dev_set_drvdata(dev, NULL);
-	gpio_free(bitbang->mdio);
-	gpio_free(bitbang->mdc);
 	free_mdio_bitbang(bus);
-	kfree(bitbang);
 }
 
 static void mdio_gpio_bus_destroy(struct device *dev)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index c55e316373a1..82355d5d155a 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1755,8 +1755,8 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
 	if (err)
 		return err;
 
-	return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df,
-			     false);
+	return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP,
+			     tos, ttl, df, false);
 }
 EXPORT_SYMBOL_GPL(vxlan_xmit_skb);
 
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 84734a805092..83c39e2858bf 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -1521,11 +1521,7 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring)
 	cosa_putstatus(cosa, 0);
 	cosa_getdata8(cosa);
 	cosa_putstatus(cosa, SR_RST);
-#ifdef MODULE
 	msleep(500);
-#else
-	udelay(5*100000);
-#endif
 	/* Disable all IRQs from the card */
 	cosa_putstatus(cosa, 0);
 
diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c
index e323b4d54338..34f97c31eecf 100644
--- a/drivers/net/wireless/cw1200/debug.c
+++ b/drivers/net/wireless/cw1200/debug.c
@@ -41,6 +41,8 @@ static const char * const cw1200_debug_link_id[] = {
 	"REQ",
 	"SOFT",
 	"HARD",
+	"RESET",
+	"RESET_REMAP",
 };
 
 static const char *cw1200_debug_mode(int mode)
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index 003a546571d4..4c2d4ef28b22 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -67,8 +67,8 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX	8
-#define IWL3160_UCODE_API_MAX	8
+#define IWL7260_UCODE_API_MAX	9
+#define IWL3160_UCODE_API_MAX	9
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK	8
@@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = {
 
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
+MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index 685f7e8e6943..fa858d548d13 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -190,7 +190,7 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
 		cpu_to_le32(0xcc00aaaa),
 		cpu_to_le32(0x0000aaaa),
 		cpu_to_le32(0xc0004000),
-		cpu_to_le32(0x00000000),
+		cpu_to_le32(0x00004000),
 		cpu_to_le32(0xf0005000),
 		cpu_to_le32(0xf0005000),
 	},
@@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
 		/* Tx Tx disabled */
 		cpu_to_le32(0xaaaaaaaa),
 		cpu_to_le32(0xaaaaaaaa),
-		cpu_to_le32(0xaaaaaaaa),
+		cpu_to_le32(0xeeaaaaaa),
 		cpu_to_le32(0xaaaaaaaa),
 		cpu_to_le32(0xcc00ff28),
 		cpu_to_le32(0x0000aaaa),
 		cpu_to_le32(0xcc00aaaa),
 		cpu_to_le32(0x0000aaaa),
-		cpu_to_le32(0xC0004000),
-		cpu_to_le32(0xC0004000),
-		cpu_to_le32(0xF0005000),
-		cpu_to_le32(0xF0005000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xc0004000),
+		cpu_to_le32(0xf0005000),
+		cpu_to_le32(0xf0005000),
 	},
 };
 
@@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	u32 ant_isolation = le32_to_cpup((void *)pkt->data);
 	u8 __maybe_unused lower_bound, upper_bound;
+	int ret;
 	u8 lut;
 
 	struct iwl_bt_coex_cmd *bt_cmd;
@@ -1318,5 +1319,8 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
 	memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
 	       sizeof(bt_cmd->bt4_corun_lut40));
 
-	return 0;
+	ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+	kfree(bt_cmd);
+	return ret;
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 4dd9ff43b8b6..f0cebf12c7b8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 		 */
 		iwl_mvm_remove_time_event(mvm, mvmvif,
 					  &mvmvif->time_event_data);
+		iwl_mvm_sf_update(mvm, vif, false);
 		WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC));
 	} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
 			      BSS_CHANGED_QOS)) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 568abd61b14f..9f52c5b3f0ec 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -59,7 +59,7 @@
 /* max allowed rate miss before sync LQ cmd */
 #define IWL_MISSED_RATE_MAX		15
 #define RS_STAY_IN_COLUMN_TIMEOUT       (5*HZ)
-
+#define RS_IDLE_TIMEOUT                 (5*HZ)
 
 static u8 rs_ht_to_legacy[] = {
 	[IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX,
@@ -142,7 +142,7 @@ enum rs_column_mode {
 	RS_MIMO2,
 };
 
-#define MAX_NEXT_COLUMNS 5
+#define MAX_NEXT_COLUMNS 7
 #define MAX_COLUMN_CHECKS 3
 
 typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm,
@@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_LEGACY_ANT_B,
 			RS_COLUMN_SISO_ANT_A,
 			RS_COLUMN_SISO_ANT_B,
-			RS_COLUMN_MIMO2,
-			RS_COLUMN_MIMO2_SGI,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 	},
 	[RS_COLUMN_LEGACY_ANT_B] = {
@@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_LEGACY_ANT_A,
 			RS_COLUMN_SISO_ANT_A,
 			RS_COLUMN_SISO_ANT_B,
-			RS_COLUMN_MIMO2,
-			RS_COLUMN_MIMO2_SGI,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 	},
 	[RS_COLUMN_SISO_ANT_A] = {
@@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_MIMO2,
 			RS_COLUMN_SISO_ANT_A_SGI,
 			RS_COLUMN_SISO_ANT_B_SGI,
-			RS_COLUMN_MIMO2_SGI,
+			RS_COLUMN_LEGACY_ANT_A,
+			RS_COLUMN_LEGACY_ANT_B,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_MIMO2,
 			RS_COLUMN_SISO_ANT_B_SGI,
 			RS_COLUMN_SISO_ANT_A_SGI,
-			RS_COLUMN_MIMO2_SGI,
+			RS_COLUMN_LEGACY_ANT_A,
+			RS_COLUMN_LEGACY_ANT_B,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_A,
 			RS_COLUMN_SISO_ANT_B,
 			RS_COLUMN_MIMO2,
+			RS_COLUMN_LEGACY_ANT_A,
+			RS_COLUMN_LEGACY_ANT_B,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_B,
 			RS_COLUMN_SISO_ANT_A,
 			RS_COLUMN_MIMO2,
+			RS_COLUMN_LEGACY_ANT_A,
+			RS_COLUMN_LEGACY_ANT_B,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_A_SGI,
 			RS_COLUMN_SISO_ANT_B_SGI,
 			RS_COLUMN_MIMO2_SGI,
+			RS_COLUMN_LEGACY_ANT_A,
+			RS_COLUMN_LEGACY_ANT_B,
 		},
 		.checks = {
 			rs_mimo_allow,
@@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_A,
 			RS_COLUMN_SISO_ANT_B,
 			RS_COLUMN_MIMO2,
+			RS_COLUMN_LEGACY_ANT_A,
+			RS_COLUMN_LEGACY_ANT_B,
 		},
 		.checks = {
 			rs_mimo_allow,
@@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
 	window->average_tpt = IWL_INVALID_VALUE;
 }
 
-static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl)
+static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm,
+					    struct iwl_scale_tbl_info *tbl)
 {
 	int i;
 
+	IWL_DEBUG_RATE(mvm, "Clearing up window stats\n");
 	for (i = 0; i < IWL_RATE_COUNT; i++)
 		rs_rate_scale_clear_window(&tbl->win[i]);
 }
@@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
 		return;
 	}
 
+#ifdef CPTCFG_MAC80211_DEBUGFS
+	/* Disable last tx check if we are debugging with fixed rate */
+	if (lq_sta->dbg_fixed_rate) {
+		IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
+		return;
+	}
+#endif
 	if (!ieee80211_is_data(hdr->frame_control) ||
 	    info->flags & IEEE80211_TX_CTL_NO_ACK)
 		return;
@@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
 			mac_index++;
 	}
 
+	if (time_after(jiffies,
+		       (unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) {
+		int tid;
+		IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
+		for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+			ieee80211_stop_tx_ba_session(sta, tid);
+
+		iwl_mvm_rs_rate_init(mvm, sta, sband->band, false);
+		return;
+	}
+	lq_sta->last_tx = jiffies;
+
 	/* Here we actually compare this rate to the latest LQ command */
 	if ((mac_index < 0) ||
 	    (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
@@ -1186,9 +1223,26 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy,
 	lq_sta->visited_columns = 0;
 }
 
+static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta,
+				   const struct rs_tx_column *column)
+{
+	switch (column->mode) {
+	case RS_LEGACY:
+		return lq_sta->max_legacy_rate_idx;
+	case RS_SISO:
+		return lq_sta->max_siso_rate_idx;
+	case RS_MIMO2:
+		return lq_sta->max_mimo2_rate_idx;
+	default:
+		WARN_ON_ONCE(1);
+	}
+
+	return lq_sta->max_legacy_rate_idx;
+}
+
 static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,
-				      const struct rs_tx_column *column,
-				      u32 bw)
+					    const struct rs_tx_column *column,
+					    u32 bw)
 {
 	/* Used to choose among HT tables */
 	const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT];
@@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
 
 				IWL_DEBUG_RATE(mvm,
 					       "LQ: stay in table clear win\n");
-				rs_rate_scale_clear_tbl_windows(tbl);
+				rs_rate_scale_clear_tbl_windows(mvm, tbl);
 			}
 		}
 
@@ -1446,8 +1500,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
 		 * bitmaps and stats in active table (this will become the new
 		 * "search" table). */
 		if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) {
-			IWL_DEBUG_RATE(mvm, "Clearing up window stats\n");
-			rs_rate_scale_clear_tbl_windows(tbl);
+			rs_rate_scale_clear_tbl_windows(mvm, tbl);
 		}
 	}
 }
@@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
 					 struct ieee80211_sta *sta,
 					 struct iwl_scale_tbl_info *tbl)
 {
-	int i, j, n;
+	int i, j, max_rate;
 	enum rs_column next_col_id;
 	const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column];
 	const struct rs_tx_column *next_col;
 	allow_column_func_t allow_func;
 	u8 valid_ants = mvm->fw->valid_tx_ant;
 	const u16 *expected_tpt_tbl;
-	s32 tpt, max_expected_tpt;
+	u16 tpt, max_expected_tpt;
 
 	for (i = 0; i < MAX_NEXT_COLUMNS; i++) {
 		next_col_id = curr_col->next_columns[i];
@@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
 		if (WARN_ON_ONCE(!expected_tpt_tbl))
 			continue;
 
-		max_expected_tpt = 0;
-		for (n = 0; n < IWL_RATE_COUNT; n++)
-			if (expected_tpt_tbl[n] > max_expected_tpt)
-				max_expected_tpt = expected_tpt_tbl[n];
+		max_rate = rs_get_max_allowed_rate(lq_sta, next_col);
+		if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID))
+			continue;
 
+		max_expected_tpt = expected_tpt_tbl[max_rate];
 		if (tpt >= max_expected_tpt) {
 			IWL_DEBUG_RATE(mvm,
 				       "Skip column %d: can't beat current TPT. Max expected %d current %d\n",
@@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
 			continue;
 		}
 
+		IWL_DEBUG_RATE(mvm,
+			       "Found potential column %d. Max expected %d current %d\n",
+			       next_col_id, max_expected_tpt, tpt);
 		break;
 	}
 
 	if (i == MAX_NEXT_COLUMNS)
 		return RS_COLUMN_INVALID;
 
-	IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id);
-
 	return next_col_id;
 }
 
@@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
 {
 	enum rs_action action = RS_ACTION_STAY;
 
-	/* Too many failures, decrease rate */
 	if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
 		IWL_DEBUG_RATE(mvm,
-			       "decrease rate because of low SR\n");
-		action = RS_ACTION_DOWNSCALE;
-	/* No throughput measured yet for adjacent rates; try increase. */
-	} else if ((low_tpt == IWL_INVALID_VALUE) &&
-		   (high_tpt == IWL_INVALID_VALUE)) {
-		if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) {
-			IWL_DEBUG_RATE(mvm,
-				       "Good SR and no high rate measurement. "
-				       "Increase rate\n");
-			action = RS_ACTION_UPSCALE;
-		} else if (low != IWL_RATE_INVALID) {
-			IWL_DEBUG_RATE(mvm,
-				       "Remain in current rate\n");
-			action = RS_ACTION_STAY;
-		}
+			       "Decrease rate because of low SR\n");
+		return RS_ACTION_DOWNSCALE;
 	}
 
-	/* Both adjacent throughputs are measured, but neither one has better
-	 * throughput; we're using the best rate, don't change it!
-	 */
-	else if ((low_tpt != IWL_INVALID_VALUE) &&
-		 (high_tpt != IWL_INVALID_VALUE) &&
-		 (low_tpt < current_tpt) &&
-		 (high_tpt < current_tpt)) {
+	if ((low_tpt == IWL_INVALID_VALUE) &&
+	    (high_tpt == IWL_INVALID_VALUE) &&
+	    (high != IWL_RATE_INVALID)) {
 		IWL_DEBUG_RATE(mvm,
-			       "Both high and low are worse. "
-			       "Maintain rate\n");
-		action = RS_ACTION_STAY;
+			       "No data about high/low rates. Increase rate\n");
+		return RS_ACTION_UPSCALE;
 	}
 
-	/* At least one adjacent rate's throughput is measured,
-	 * and may have better performance.
-	 */
-	else {
-		/* Higher adjacent rate's throughput is measured */
-		if (high_tpt != IWL_INVALID_VALUE) {
-			/* Higher rate has better throughput */
-			if (high_tpt > current_tpt &&
-			    sr >= IWL_RATE_INCREASE_TH) {
-				IWL_DEBUG_RATE(mvm,
-					       "Higher rate is better and good "
-					       "SR. Increate rate\n");
-				action = RS_ACTION_UPSCALE;
-			} else {
-				IWL_DEBUG_RATE(mvm,
-					       "Higher rate isn't better OR "
-					       "no good SR. Maintain rate\n");
-				action = RS_ACTION_STAY;
-			}
+	if ((high_tpt == IWL_INVALID_VALUE) &&
+	    (high != IWL_RATE_INVALID) &&
+	    (low_tpt != IWL_INVALID_VALUE) &&
+	    (low_tpt < current_tpt)) {
+		IWL_DEBUG_RATE(mvm,
+			       "No data about high rate and low rate is worse. Increase rate\n");
+		return RS_ACTION_UPSCALE;
+	}
 
-		/* Lower adjacent rate's throughput is measured */
-		} else if (low_tpt != IWL_INVALID_VALUE) {
-			/* Lower rate has better throughput */
-			if (low_tpt > current_tpt) {
-				IWL_DEBUG_RATE(mvm,
-					       "Lower rate is better. "
-					       "Decrease rate\n");
-				action = RS_ACTION_DOWNSCALE;
-			} else if (sr >= IWL_RATE_INCREASE_TH) {
-				IWL_DEBUG_RATE(mvm,
-					       "Lower rate isn't better and "
-					       "good SR. Increase rate\n");
-				action = RS_ACTION_UPSCALE;
-			}
-		}
+	if ((high_tpt != IWL_INVALID_VALUE) &&
+	    (high_tpt > current_tpt)) {
+		IWL_DEBUG_RATE(mvm,
+			       "Higher rate is better. Increate rate\n");
+		return RS_ACTION_UPSCALE;
 	}
 
-	/* Sanity check; asked for decrease, but success rate or throughput
-	 * has been good at old rate.  Don't change it.
-	 */
-	if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) &&
-	    ((sr > IWL_RATE_HIGH_TH) ||
-	     (current_tpt > (100 * tbl->expected_tpt[low])))) {
+	if ((low_tpt != IWL_INVALID_VALUE) &&
+	    (high_tpt != IWL_INVALID_VALUE) &&
+	    (low_tpt < current_tpt) &&
+	    (high_tpt < current_tpt)) {
+		IWL_DEBUG_RATE(mvm,
+			       "Both high and low are worse. Maintain rate\n");
+		return RS_ACTION_STAY;
+	}
+
+	if ((low_tpt != IWL_INVALID_VALUE) &&
+	    (low_tpt > current_tpt)) {
+		IWL_DEBUG_RATE(mvm,
+			       "Lower rate is better\n");
+		action = RS_ACTION_DOWNSCALE;
+		goto out;
+	}
+
+	if ((low_tpt == IWL_INVALID_VALUE) &&
+	    (low != IWL_RATE_INVALID)) {
 		IWL_DEBUG_RATE(mvm,
-			       "Sanity check failed. Maintain rate\n");
-		action = RS_ACTION_STAY;
+			       "No data about lower rate\n");
+		action = RS_ACTION_DOWNSCALE;
+		goto out;
+	}
+
+	IWL_DEBUG_RATE(mvm, "Maintain rate\n");
+
+out:
+	if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) {
+		if (sr >= RS_SR_NO_DECREASE) {
+			IWL_DEBUG_RATE(mvm,
+				       "SR is above NO DECREASE. Avoid downscale\n");
+			action = RS_ACTION_STAY;
+		} else if (current_tpt > (100 * tbl->expected_tpt[low])) {
+			IWL_DEBUG_RATE(mvm,
+				       "Current TPT is higher than max expected in low rate. Avoid downscale\n");
+			action = RS_ACTION_STAY;
+		} else {
+			IWL_DEBUG_RATE(mvm, "Decrease rate\n");
+		}
 	}
 
 	return action;
@@ -1792,6 +1837,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
 			       "Aggregation changed: prev %d current %d. Update expected TPT table\n",
 			       prev_agg, lq_sta->is_agg);
 		rs_set_expected_tpt_table(lq_sta, tbl);
+		rs_rate_scale_clear_tbl_windows(mvm, tbl);
 	}
 
 	/* current tx rate */
@@ -2021,7 +2067,7 @@ lq_update:
 		if (lq_sta->search_better_tbl) {
 			/* Access the "search" table, clear its history. */
 			tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-			rs_rate_scale_clear_tbl_windows(tbl);
+			rs_rate_scale_clear_tbl_windows(mvm, tbl);
 
 			/* Use new "search" start rate */
 			index = tbl->rate.index;
@@ -2042,8 +2088,18 @@ lq_update:
 		 * stay with best antenna legacy modulation for a while
 		 * before next round of mode comparisons. */
 		tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
-		if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) {
+		if (is_legacy(&tbl1->rate)) {
 			IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n");
+
+			if (tid != IWL_MAX_TID_COUNT) {
+				tid_data = &sta_priv->tid_data[tid];
+				if (tid_data->state != IWL_AGG_OFF) {
+					IWL_DEBUG_RATE(mvm,
+						       "Stop aggregation on tid %d\n",
+						       tid);
+					ieee80211_stop_tx_ba_session(sta, tid);
+				}
+			}
 			rs_set_stay_in_table(mvm, 1, lq_sta);
 		} else {
 		/* If we're in an HT mode, and all 3 mode switch actions
@@ -2342,9 +2398,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 	lq_sta->lq.sta_id = sta_priv->sta_id;
 
 	for (j = 0; j < LQ_SIZE; j++)
-		rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]);
+		rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]);
 
 	lq_sta->flush_timer = 0;
+	lq_sta->last_tx = jiffies;
 
 	IWL_DEBUG_RATE(mvm,
 		       "LQ: *** rate scale station global init for station %d ***\n",
@@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 		lq_sta->is_vht = true;
 	}
 
-	IWL_DEBUG_RATE(mvm,
-		       "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n",
+	lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
+						    BITS_PER_LONG);
+	lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
+						  BITS_PER_LONG);
+	lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate,
+						   BITS_PER_LONG);
+
+	IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n",
+		       lq_sta->active_legacy_rate,
 		       lq_sta->active_siso_rate,
 		       lq_sta->active_mimo2_rate,
 		       lq_sta->is_vht);
+	IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
+		       lq_sta->max_legacy_rate_idx,
+		       lq_sta->max_siso_rate_idx,
+		       lq_sta->max_mimo2_rate_idx);
 
 	/* These values will be overridden later */
 	lq_sta->lq.single_stream_ant_msk =
@@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
 	if (is_siso(&rate)) {
 		num_rates = RS_SECONDARY_SISO_NUM_RATES;
 		num_retries = RS_SECONDARY_SISO_RETRIES;
+		lq_cmd->mimo_delim = index;
 	} else if (is_legacy(&rate)) {
 		num_rates = RS_SECONDARY_LEGACY_NUM_RATES;
 		num_retries = RS_LEGACY_RETRIES_PER_RATE;
@@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 		return -ENOMEM;
 
 	desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id);
-	desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n",
+	desc += sprintf(buff+desc, "failed=%d success=%d rate=0%lX\n",
 			lq_sta->total_failed, lq_sta->total_success,
 			lq_sta->active_legacy_rate);
 	desc += sprintf(buff+desc, "fixed rate 0x%X\n",
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index 3332b396011e..0acfac96a56c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -156,6 +156,7 @@ enum {
 #define IWL_RATE_HIGH_TH		10880	/*  85% */
 #define IWL_RATE_INCREASE_TH		6400	/*  50% */
 #define RS_SR_FORCE_DECREASE		1920	/*  15% */
+#define RS_SR_NO_DECREASE		10880	/*  85% */
 
 #define LINK_QUAL_AGG_TIME_LIMIT_DEF	(4000) /* 4 milliseconds */
 #define LINK_QUAL_AGG_TIME_LIMIT_MAX	(8000)
@@ -310,13 +311,20 @@ struct iwl_lq_sta {
 	u32 visited_columns;    /* Bitmask marking which Tx columns were
 				 * explored during a search cycle
 				 */
+	u64 last_tx;
 	bool is_vht;
 	enum ieee80211_band band;
 
 	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
-	u16 active_legacy_rate;
-	u16 active_siso_rate;
-	u16 active_mimo2_rate;
+	unsigned long active_legacy_rate;
+	unsigned long active_siso_rate;
+	unsigned long active_mimo2_rate;
+
+	/* Highest rate per Tx mode */
+	u8 max_legacy_rate_idx;
+	u8 max_siso_rate_idx;
+	u8 max_mimo2_rate_idx;
+
 	s8 max_rate_idx;     /* Max rate set by user */
 	u8 missed_rate_counter;
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c
index 8401627c0030..88809b2d1654 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sf.c
@@ -274,7 +274,8 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
 				return -EINVAL;
 			if (changed_vif->type != NL80211_IFTYPE_STATION) {
 				new_state = SF_UNINIT;
-			} else if (changed_vif->bss_conf.assoc) {
+			} else if (changed_vif->bss_conf.assoc &&
+				   changed_vif->bss_conf.dtim_period) {
 				mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
 				sta_id = mvmvif->ap_sta_id;
 				new_state = SF_FULL_ON;
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index edb015c99049..3d1d57f9f5bc 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -373,12 +373,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 	{IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)},
 	{IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
+	{IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)},
 	{IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 77db0886c6e2..9c771b3e9918 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -292,6 +292,12 @@ process_start:
 			while ((skb = skb_dequeue(&adapter->usb_rx_data_q)))
 				mwifiex_handle_rx_packet(adapter, skb);
 
+		/* Check for event */
+		if (adapter->event_received) {
+			adapter->event_received = false;
+			mwifiex_process_event(adapter);
+		}
+
 		/* Check for Cmd Resp */
 		if (adapter->cmd_resp_received) {
 			adapter->cmd_resp_received = false;
@@ -304,12 +310,6 @@ process_start:
 			}
 		}
 
-		/* Check for event */
-		if (adapter->event_received) {
-			adapter->event_received = false;
-			mwifiex_process_event(adapter);
-		}
-
 		/* Check if we need to confirm Sleep Request
 		   received previously */
 		if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 894270611f2c..536c14aa71f3 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -60,9 +60,10 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
 	int status;
 
 	/* Wait for completion */
-	status = wait_event_interruptible(adapter->cmd_wait_q.wait,
-					  *(cmd_queued->condition));
-	if (status) {
+	status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait,
+						  *(cmd_queued->condition),
+						  (12 * HZ));
+	if (status <= 0) {
 		dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status);
 		mwifiex_cancel_all_pending_cmd(adapter);
 		return status;
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 1a8d32138593..cf61d6e3eaa7 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -88,7 +88,7 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
 	bool recontend_queue = false;
 	u32 q_len = 0;
 	u8 q_num = INVALID_QUEUE;
-	u8 ii, min = 0;
+	u8 ii = 0, min = 0;
 
 	if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {
 		if (!common->mgmt_q_block)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 73694295648f..1b28cda6ca88 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -841,16 +841,6 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
 	rsi_dbg(MGMT_TX_ZONE,
 		"%s: Sending scan req frame\n", __func__);
 
-	skb = dev_alloc_skb(FRAME_DESC_SZ);
-	if (!skb) {
-		rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	memset(skb->data, 0, FRAME_DESC_SZ);
-	mgmt_frame = (struct rsi_mac_frame *)skb->data;
-
 	if (common->band == IEEE80211_BAND_5GHZ) {
 		if ((channel >= 36) && (channel <= 64))
 			channel = ((channel - 32) / 4);
@@ -868,6 +858,16 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
 		}
 	}
 
+	skb = dev_alloc_skb(FRAME_DESC_SZ);
+	if (!skb) {
+		rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	memset(skb->data, 0, FRAME_DESC_SZ);
+	mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
 	mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
 	mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST);
 	mgmt_frame->desc_word[4] = cpu_to_le16(channel);
@@ -966,6 +966,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
 	if (!selected_rates) {
 		rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",
 			__func__);
+		dev_kfree_skb(skb);
 		return -ENOMEM;
 	}
 
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
index 398f3d2c0a6c..a76e98eb8372 100644
--- a/drivers/net/wireless/ti/wl18xx/event.h
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -68,6 +68,26 @@ struct wl18xx_event_mailbox {
 
 	/* bitmap of inactive stations (by HLID) */
 	__le32 inactive_sta_bitmap;
+
+	/* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */
+	u8 rx_ba_role_id;
+	u8 rx_ba_link_id;
+	u8 rx_ba_win_size;
+	u8 padding;
+
+	/* smart config */
+	u8 sc_ssid_len;
+	u8 sc_pwd_len;
+	u8 sc_token_len;
+	u8 padding1;
+	u8 sc_ssid[32];
+	u8 sc_pwd[32];
+	u8 sc_token[32];
+
+	/* smart config sync channel */
+	u8 sc_sync_channel;
+	u8 sc_sync_band;
+	u8 padding2[2];
 } __packed;
 
 int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 1f9a36031b06..16d10281798d 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -158,6 +158,11 @@ EXPORT_SYMBOL_GPL(wlcore_event_channel_switch);
 
 void wlcore_event_dummy_packet(struct wl1271 *wl)
 {
+	if (wl->plt) {
+		wl1271_info("Got DUMMY_PACKET event in PLT mode.  FW bug, ignoring.");
+		return;
+	}
+
 	wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
 	wl1271_tx_dummy_packet(wl);
 }
diff --git a/drivers/of/base.c b/drivers/of/base.c
index f72d19b7e5d2..6d4ee22708c9 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1828,17 +1828,13 @@ int of_update_property(struct device_node *np, struct property *newprop)
 		next = &(*next)->next;
 	}
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
-	if (rc)
-		return rc;
+	if (!found)
+		return -ENODEV;
 
 	/* Update the sysfs attribute */
-	if (oldprop)
-		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
+	sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
 	__of_add_property_sysfs(np, newprop);
 
-	if (!found)
-		return -ENODEV;
-
 	return 0;
 }
 
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index fa16a912a927..7a2ef7bb8022 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -491,7 +491,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
  * in /reserved-memory matches the values supported by the current implementation,
  * also check if ranges property has been provided
  */
-static int __reserved_mem_check_root(unsigned long node)
+static int __init __reserved_mem_check_root(unsigned long node)
 {
 	__be32 *prop;
 
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index fd3e3ab56509..4fe349dcaf59 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_pci.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -180,8 +181,13 @@ static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	struct pci_sys_data *sys = dev->bus->sysdata;
 	struct rcar_pci_priv *priv = sys->private_data;
+	int irq;
+
+	irq = of_irq_parse_and_map_pci(dev, slot, pin);
+	if (!irq)
+		irq = priv->irq;
 
-	return priv->irq;
+	return irq;
 }
 
 #ifdef CONFIG_PCI_DEBUG
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 330f7e3a32dd..083cf37ca047 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -639,10 +639,15 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
 	struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata);
+	int irq;
 
 	tegra_cpuidle_pcie_irqs_in_use();
 
-	return pcie->irq;
+	irq = of_irq_parse_and_map_pci(pdev, slot, pin);
+	if (!irq)
+		irq = pcie->irq;
+
+	return irq;
 }
 
 static void tegra_pcie_add_bus(struct pci_bus *bus)
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 509a29d84509..c4e373294476 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/msi.h>
 #include <linux/of_address.h>
+#include <linux/of_pci.h>
 #include <linux/pci.h>
 #include <linux/pci_regs.h>
 #include <linux/types.h>
@@ -490,7 +491,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 	dw_pci.nr_controllers = 1;
 	dw_pci.private_data = (void **)&pp;
 
-	pci_common_init(&dw_pci);
+	pci_common_init_dev(pp->dev, &dw_pci);
 	pci_assign_unassigned_resources();
 #ifdef CONFIG_PCI_DOMAINS
 	dw_pci.domain++;
@@ -520,13 +521,13 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
 	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
 			  PCIE_ATU_VIEWPORT);
 	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1);
-	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
 	dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE);
 	dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE);
 	dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1,
 			  PCIE_ATU_LIMIT);
 	dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
 	dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
+	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
 }
 
 static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
@@ -535,7 +536,6 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
 	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
 			  PCIE_ATU_VIEWPORT);
 	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
-	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
 	dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE);
 	dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE);
 	dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1,
@@ -543,6 +543,7 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
 	dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET);
 	dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr),
 			  PCIE_ATU_UPPER_TARGET);
+	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
 }
 
 static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
@@ -551,7 +552,6 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
 	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
 			  PCIE_ATU_VIEWPORT);
 	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
-	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
 	dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE);
 	dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE);
 	dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1,
@@ -559,6 +559,7 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
 	dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET);
 	dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr),
 			  PCIE_ATU_UPPER_TARGET);
+	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
 }
 
 static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
@@ -723,7 +724,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 
 	if (pp) {
 		pp->root_bus_nr = sys->busnr;
-		bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops,
+		bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
 					sys, &sys->resources);
 	} else {
 		bus = NULL;
@@ -736,8 +737,13 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
+	int irq;
+
+	irq = of_irq_parse_and_map_pci(dev, slot, pin);
+	if (!irq)
+		irq = pp->irq;
 
-	return pp->irq;
+	return irq;
 }
 
 static void dw_pcie_add_bus(struct pci_bus *bus)
@@ -764,7 +770,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	u32 membase;
 	u32 memlimit;
 
-	/* set the number of lines as 4 */
+	/* set the number of lanes */
 	dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val);
 	val &= ~PORT_LINK_MODE_MASK;
 	switch (pp->lanes) {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index e49324032611..fbd7eda7e946 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -104,16 +104,16 @@ config PINCTRL_BCM2835
 	select PINMUX
 	select PINCONF
 
-config PINCTRL_CAPRI
-	bool "Broadcom Capri pinctrl driver"
+config PINCTRL_BCM281XX
+	bool "Broadcom BCM281xx pinctrl driver"
 	depends on OF
 	select PINMUX
 	select PINCONF
 	select GENERIC_PINCONF
 	select REGMAP_MMIO
 	help
-	  Say Y here to support Broadcom Capri pinctrl driver, which is used for
-	  the BCM281xx SoC family, including BCM11130, BCM11140, BCM11351,
+	  Say Y here to support Broadcom BCM281xx pinctrl driver, which is used
+	  for the BCM281xx SoC family, including BCM11130, BCM11140, BCM11351,
 	  BCM28145, and BCM28155 SoCs.  This driver requires the pinctrl
 	  framework.  GPIO is provided by a separate GPIO driver.
 
@@ -222,9 +222,17 @@ config PINCTRL_MSM
 	select PINCONF
 	select GENERIC_PINCONF
 
+config PINCTRL_APQ8064
+	tristate "Qualcomm APQ8064 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
+
 config PINCTRL_MSM8X74
 	tristate "Qualcomm 8x74 pin controller driver"
-	depends on GPIOLIB && OF
+	depends on GPIOLIB && OF && (ARCH_QCOM || COMPILE_TEST)
 	select PINCTRL_MSM
 	help
 	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -281,6 +289,7 @@ config PINCTRL_ST
 	depends on OF
 	select PINMUX
 	select PINCONF
+	select GPIOLIB_IRQCHIP
 
 config PINCTRL_TEGRA
 	bool
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 4b835880cf80..c43fb9884086 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_PINCTRL_BF60x)	+= pinctrl-adi2-bf60x.o
 obj-$(CONFIG_PINCTRL_AT91)	+= pinctrl-at91.o
 obj-$(CONFIG_PINCTRL_BCM2835)	+= pinctrl-bcm2835.o
 obj-$(CONFIG_PINCTRL_BAYTRAIL)	+= pinctrl-baytrail.o
-obj-$(CONFIG_PINCTRL_CAPRI)	+= pinctrl-capri.o
+obj-$(CONFIG_PINCTRL_BCM281XX)	+= pinctrl-bcm281xx.o
 obj-$(CONFIG_PINCTRL_IMX)	+= pinctrl-imx.o
 obj-$(CONFIG_PINCTRL_IMX1_CORE)	+= pinctrl-imx1-core.o
 obj-$(CONFIG_PINCTRL_IMX27)	+= pinctrl-imx27.o
@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_IMX23)	+= pinctrl-imx23.o
 obj-$(CONFIG_PINCTRL_IMX25)	+= pinctrl-imx25.o
 obj-$(CONFIG_PINCTRL_IMX28)	+= pinctrl-imx28.o
 obj-$(CONFIG_PINCTRL_MSM)	+= pinctrl-msm.o
+obj-$(CONFIG_PINCTRL_APQ8064)	+= pinctrl-apq8064.o
 obj-$(CONFIG_PINCTRL_MSM8X74)	+= pinctrl-msm8x74.o
 obj-$(CONFIG_PINCTRL_NOMADIK)	+= pinctrl-nomadik.o
 obj-$(CONFIG_PINCTRL_STN8815)	+= pinctrl-nomadik-stn8815.o
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index 0cc0eec83396..5c44feb54ebb 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -927,7 +927,7 @@ static int adi_gpio_irq_map(struct irq_domain *d, unsigned int irq,
 	return 0;
 }
 
-const struct irq_domain_ops adi_gpio_irq_domain_ops = {
+static const struct irq_domain_ops adi_gpio_irq_domain_ops = {
 	.map = adi_gpio_irq_map,
 	.xlate = irq_domain_xlate_onecell,
 };
diff --git a/drivers/pinctrl/pinctrl-apq8064.c b/drivers/pinctrl/pinctrl-apq8064.c
new file mode 100644
index 000000000000..7c2a8baaea80
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-apq8064.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2014, Sony Mobile Communications AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc apq8064_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+};
+
+#define DECLARE_APQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_APQ_GPIO_PINS(0);
+DECLARE_APQ_GPIO_PINS(1);
+DECLARE_APQ_GPIO_PINS(2);
+DECLARE_APQ_GPIO_PINS(3);
+DECLARE_APQ_GPIO_PINS(4);
+DECLARE_APQ_GPIO_PINS(5);
+DECLARE_APQ_GPIO_PINS(6);
+DECLARE_APQ_GPIO_PINS(7);
+DECLARE_APQ_GPIO_PINS(8);
+DECLARE_APQ_GPIO_PINS(9);
+DECLARE_APQ_GPIO_PINS(10);
+DECLARE_APQ_GPIO_PINS(11);
+DECLARE_APQ_GPIO_PINS(12);
+DECLARE_APQ_GPIO_PINS(13);
+DECLARE_APQ_GPIO_PINS(14);
+DECLARE_APQ_GPIO_PINS(15);
+DECLARE_APQ_GPIO_PINS(16);
+DECLARE_APQ_GPIO_PINS(17);
+DECLARE_APQ_GPIO_PINS(18);
+DECLARE_APQ_GPIO_PINS(19);
+DECLARE_APQ_GPIO_PINS(20);
+DECLARE_APQ_GPIO_PINS(21);
+DECLARE_APQ_GPIO_PINS(22);
+DECLARE_APQ_GPIO_PINS(23);
+DECLARE_APQ_GPIO_PINS(24);
+DECLARE_APQ_GPIO_PINS(25);
+DECLARE_APQ_GPIO_PINS(26);
+DECLARE_APQ_GPIO_PINS(27);
+DECLARE_APQ_GPIO_PINS(28);
+DECLARE_APQ_GPIO_PINS(29);
+DECLARE_APQ_GPIO_PINS(30);
+DECLARE_APQ_GPIO_PINS(31);
+DECLARE_APQ_GPIO_PINS(32);
+DECLARE_APQ_GPIO_PINS(33);
+DECLARE_APQ_GPIO_PINS(34);
+DECLARE_APQ_GPIO_PINS(35);
+DECLARE_APQ_GPIO_PINS(36);
+DECLARE_APQ_GPIO_PINS(37);
+DECLARE_APQ_GPIO_PINS(38);
+DECLARE_APQ_GPIO_PINS(39);
+DECLARE_APQ_GPIO_PINS(40);
+DECLARE_APQ_GPIO_PINS(41);
+DECLARE_APQ_GPIO_PINS(42);
+DECLARE_APQ_GPIO_PINS(43);
+DECLARE_APQ_GPIO_PINS(44);
+DECLARE_APQ_GPIO_PINS(45);
+DECLARE_APQ_GPIO_PINS(46);
+DECLARE_APQ_GPIO_PINS(47);
+DECLARE_APQ_GPIO_PINS(48);
+DECLARE_APQ_GPIO_PINS(49);
+DECLARE_APQ_GPIO_PINS(50);
+DECLARE_APQ_GPIO_PINS(51);
+DECLARE_APQ_GPIO_PINS(52);
+DECLARE_APQ_GPIO_PINS(53);
+DECLARE_APQ_GPIO_PINS(54);
+DECLARE_APQ_GPIO_PINS(55);
+DECLARE_APQ_GPIO_PINS(56);
+DECLARE_APQ_GPIO_PINS(57);
+DECLARE_APQ_GPIO_PINS(58);
+DECLARE_APQ_GPIO_PINS(59);
+DECLARE_APQ_GPIO_PINS(60);
+DECLARE_APQ_GPIO_PINS(61);
+DECLARE_APQ_GPIO_PINS(62);
+DECLARE_APQ_GPIO_PINS(63);
+DECLARE_APQ_GPIO_PINS(64);
+DECLARE_APQ_GPIO_PINS(65);
+DECLARE_APQ_GPIO_PINS(66);
+DECLARE_APQ_GPIO_PINS(67);
+DECLARE_APQ_GPIO_PINS(68);
+DECLARE_APQ_GPIO_PINS(69);
+DECLARE_APQ_GPIO_PINS(70);
+DECLARE_APQ_GPIO_PINS(71);
+DECLARE_APQ_GPIO_PINS(72);
+DECLARE_APQ_GPIO_PINS(73);
+DECLARE_APQ_GPIO_PINS(74);
+DECLARE_APQ_GPIO_PINS(75);
+DECLARE_APQ_GPIO_PINS(76);
+DECLARE_APQ_GPIO_PINS(77);
+DECLARE_APQ_GPIO_PINS(78);
+DECLARE_APQ_GPIO_PINS(79);
+DECLARE_APQ_GPIO_PINS(80);
+DECLARE_APQ_GPIO_PINS(81);
+DECLARE_APQ_GPIO_PINS(82);
+DECLARE_APQ_GPIO_PINS(83);
+DECLARE_APQ_GPIO_PINS(84);
+DECLARE_APQ_GPIO_PINS(85);
+DECLARE_APQ_GPIO_PINS(86);
+DECLARE_APQ_GPIO_PINS(87);
+DECLARE_APQ_GPIO_PINS(88);
+DECLARE_APQ_GPIO_PINS(89);
+
+#define FUNCTION(fname)					\
+	[APQ_MUX_##fname] = {				\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
+	{						\
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			APQ_MUX_NA, /* gpio mode */	\
+			APQ_MUX_##f1,			\
+			APQ_MUX_##f2,			\
+			APQ_MUX_##f3,			\
+			APQ_MUX_##f4,			\
+			APQ_MUX_##f5,			\
+			APQ_MUX_##f6,			\
+			APQ_MUX_##f7,			\
+			APQ_MUX_##f8,			\
+			APQ_MUX_##f9,			\
+			APQ_MUX_##f10,			\
+		},					\
+		.nfuncs = 11,				\
+		.ctl_reg = 0x1000 + 0x10 * id,		\
+		.io_reg = 0x1004 + 0x10 * id,		\
+		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
+		.intr_status_reg = 0x100c + 0x10 * id,	\
+		.intr_target_reg = 0x400 + 0x4 * id,	\
+		.mux_bit = 2,				\
+		.pull_bit = 0,				\
+		.drv_bit = 6,				\
+		.oe_bit = 9,				\
+		.in_bit = 0,				\
+		.out_bit = 1,				\
+		.intr_enable_bit = 0,			\
+		.intr_status_bit = 0,			\
+		.intr_ack_high = 1,			\
+		.intr_target_bit = 0,			\
+		.intr_raw_status_bit = 3,		\
+		.intr_polarity_bit = 1,			\
+		.intr_detection_bit = 2,		\
+		.intr_detection_width = 1,		\
+	}
+
+enum apq8064_functions {
+	APQ_MUX_cam_mclk,
+	APQ_MUX_codec_mic_i2s,
+	APQ_MUX_codec_spkr_i2s,
+	APQ_MUX_gsbi1,
+	APQ_MUX_gsbi2,
+	APQ_MUX_gsbi3,
+	APQ_MUX_gsbi4,
+	APQ_MUX_gsbi4_cam_i2c,
+	APQ_MUX_gsbi5,
+	APQ_MUX_gsbi5_spi_cs1,
+	APQ_MUX_gsbi5_spi_cs2,
+	APQ_MUX_gsbi5_spi_cs3,
+	APQ_MUX_gsbi6,
+	APQ_MUX_gsbi6_spi_cs1,
+	APQ_MUX_gsbi6_spi_cs2,
+	APQ_MUX_gsbi6_spi_cs3,
+	APQ_MUX_gsbi7,
+	APQ_MUX_gsbi7_spi_cs1,
+	APQ_MUX_gsbi7_spi_cs2,
+	APQ_MUX_gsbi7_spi_cs3,
+	APQ_MUX_gsbi_cam_i2c,
+	APQ_MUX_hdmi,
+	APQ_MUX_mi2s,
+	APQ_MUX_riva_bt,
+	APQ_MUX_riva_fm,
+	APQ_MUX_riva_wlan,
+	APQ_MUX_sdc2,
+	APQ_MUX_sdc4,
+	APQ_MUX_slimbus,
+	APQ_MUX_spkr_i2s,
+	APQ_MUX_tsif1,
+	APQ_MUX_tsif2,
+	APQ_MUX_usb2_hsic,
+	APQ_MUX_NA,
+};
+
+static const char * const cam_mclk_groups[] = {
+	"gpio4" "gpio5"
+};
+static const char * const codec_mic_i2s_groups[] = {
+	"gpio34", "gpio35", "gpio36", "gpio37", "gpio38"
+};
+static const char * const codec_spkr_i2s_groups[] = {
+	"gpio39", "gpio40", "gpio41", "gpio42"
+};
+static const char * const gsbi1_groups[] = {
+	"gpio18", "gpio19", "gpio20", "gpio21"
+};
+static const char * const gsbi2_groups[] = {
+	"gpio22", "gpio23", "gpio24", "gpio25"
+};
+static const char * const gsbi3_groups[] = {
+	"gpio6", "gpio7", "gpio8", "gpio9"
+};
+static const char * const gsbi4_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13"
+};
+static const char * const gsbi4_cam_i2c_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13"
+};
+static const char * const gsbi5_groups[] = {
+	"gpio51", "gpio52", "gpio53", "gpio54"
+};
+static const char * const gsbi5_spi_cs1_groups[] = {
+	"gpio47"
+};
+static const char * const gsbi5_spi_cs2_groups[] = {
+	"gpio31"
+};
+static const char * const gsbi5_spi_cs3_groups[] = {
+	"gpio32"
+};
+static const char * const gsbi6_groups[] = {
+	"gpio14", "gpio15", "gpio16", "gpio17"
+};
+static const char * const gsbi6_spi_cs1_groups[] = {
+	"gpio47"
+};
+static const char * const gsbi6_spi_cs2_groups[] = {
+	"gpio31"
+};
+static const char * const gsbi6_spi_cs3_groups[] = {
+	"gpio32"
+};
+static const char * const gsbi7_groups[] = {
+	"gpio82", "gpio83", "gpio84", "gpio85"
+};
+static const char * const gsbi7_spi_cs1_groups[] = {
+	"gpio47"
+};
+static const char * const gsbi7_spi_cs2_groups[] = {
+	"gpio31"
+};
+static const char * const gsbi7_spi_cs3_groups[] = {
+	"gpio32"
+};
+static const char * const gsbi_cam_i2c_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio13"
+};
+static const char * const hdmi_groups[] = {
+	"gpio69", "gpio70", "gpio71", "gpio72"
+};
+static const char * const mi2s_groups[] = {
+	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33"
+};
+static const char * const riva_bt_groups[] = {
+	"gpio16", "gpio17"
+};
+static const char * const riva_fm_groups[] = {
+	"gpio14", "gpio15"
+};
+static const char * const riva_wlan_groups[] = {
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+static const char * const sdc2_groups[] = {
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62"
+};
+static const char * const sdc4_groups[] = {
+	"gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+static const char * const slimbus_groups[] = {
+	"gpio40", "gpio41"
+};
+static const char * const spkr_i2s_groups[] = {
+	"gpio47", "gpio48", "gpio49", "gpio50"
+};
+static const char * const tsif1_groups[] = {
+	"gpio55", "gpio56", "gpio57"
+};
+static const char * const tsif2_groups[] = {
+	"gpio58", "gpio59", "gpio60"
+};
+static const char * const usb2_hsic_groups[] = {
+	"gpio88", "gpio89"
+};
+
+static const struct msm_function apq8064_functions[] = {
+	FUNCTION(cam_mclk),
+	FUNCTION(codec_mic_i2s),
+	FUNCTION(codec_spkr_i2s),
+	FUNCTION(gsbi1),
+	FUNCTION(gsbi2),
+	FUNCTION(gsbi3),
+	FUNCTION(gsbi4),
+	FUNCTION(gsbi4_cam_i2c),
+	FUNCTION(gsbi5),
+	FUNCTION(gsbi5_spi_cs1),
+	FUNCTION(gsbi5_spi_cs2),
+	FUNCTION(gsbi5_spi_cs3),
+	FUNCTION(gsbi6),
+	FUNCTION(gsbi6_spi_cs1),
+	FUNCTION(gsbi6_spi_cs2),
+	FUNCTION(gsbi6_spi_cs3),
+	FUNCTION(gsbi7),
+	FUNCTION(gsbi7_spi_cs1),
+	FUNCTION(gsbi7_spi_cs2),
+	FUNCTION(gsbi7_spi_cs3),
+	FUNCTION(gsbi_cam_i2c),
+	FUNCTION(hdmi),
+	FUNCTION(mi2s),
+	FUNCTION(riva_bt),
+	FUNCTION(riva_fm),
+	FUNCTION(riva_wlan),
+	FUNCTION(sdc2),
+	FUNCTION(sdc4),
+	FUNCTION(slimbus),
+	FUNCTION(spkr_i2s),
+	FUNCTION(tsif1),
+	FUNCTION(tsif2),
+	FUNCTION(usb2_hsic),
+};
+
+static const struct msm_pingroup apq8064_groups[] = {
+	PINGROUP(0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(4, NA, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(5, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(6, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(7, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(8, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(9, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(10, gsbi4, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c, NA),
+	PINGROUP(11, gsbi4, NA, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c),
+	PINGROUP(12, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA),
+	PINGROUP(13, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA),
+	PINGROUP(14, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(15, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(17, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(18, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(19, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(20, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(21, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(22, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(23, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(24, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(25, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(27, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(28, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(29, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(30, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(31, mi2s, NA, gsbi5_spi_cs2, gsbi6_spi_cs2, gsbi7_spi_cs2, NA, NA, NA, NA, NA),
+	PINGROUP(32, mi2s, NA, NA, NA, NA, gsbi5_spi_cs3, gsbi6_spi_cs3, gsbi7_spi_cs3, NA, NA),
+	PINGROUP(33, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(34, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(35, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(36, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(37, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(38, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(39, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(40, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(41, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(42, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(47, spkr_i2s, gsbi5_spi_cs1, gsbi6_spi_cs1, gsbi7_spi_cs1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(48, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(49, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(50, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(51, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(52, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(53, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(54, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(55, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(56, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(57, tsif1, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(58, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(59, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(60, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(63, NA, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(64, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(65, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(66, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(67, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(68, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(69, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(70, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(75, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(76, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(77, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(79, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(82, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(84, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(85, NA, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(88, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(89, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+};
+
+#define NUM_GPIO_PINGROUPS 90
+
+static const struct msm_pinctrl_soc_data apq8064_pinctrl = {
+	.pins = apq8064_pins,
+	.npins = ARRAY_SIZE(apq8064_pins),
+	.functions = apq8064_functions,
+	.nfunctions = ARRAY_SIZE(apq8064_functions),
+	.groups = apq8064_groups,
+	.ngroups = ARRAY_SIZE(apq8064_groups),
+	.ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int apq8064_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &apq8064_pinctrl);
+}
+
+static const struct of_device_id apq8064_pinctrl_of_match[] = {
+	{ .compatible = "qcom,apq8064-pinctrl", },
+	{ },
+};
+
+static struct platform_driver apq8064_pinctrl_driver = {
+	.driver = {
+		.name = "apq8064-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = apq8064_pinctrl_of_match,
+	},
+	.probe = apq8064_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init apq8064_pinctrl_init(void)
+{
+	return platform_driver_register(&apq8064_pinctrl_driver);
+}
+arch_initcall(apq8064_pinctrl_init);
+
+static void __exit apq8064_pinctrl_exit(void)
+{
+	platform_driver_unregister(&apq8064_pinctrl_driver);
+}
+module_exit(apq8064_pinctrl_exit);
+
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
+MODULE_DESCRIPTION("Qualcomm APQ8064 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, apq8064_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-bcm281xx.c b/drivers/pinctrl/pinctrl-bcm281xx.c
new file mode 100644
index 000000000000..3bed792b2c03
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-bcm281xx.c
@@ -0,0 +1,1461 @@
+/*
+ * Copyright (C) 2013 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include "core.h"
+#include "pinctrl-utils.h"
+
+/* BCM281XX Pin Control Registers Definitions */
+
+/* Function Select bits are the same for all pin control registers */
+#define BCM281XX_PIN_REG_F_SEL_MASK		0x0700
+#define BCM281XX_PIN_REG_F_SEL_SHIFT		8
+
+/* Standard pin register */
+#define BCM281XX_STD_PIN_REG_DRV_STR_MASK	0x0007
+#define BCM281XX_STD_PIN_REG_DRV_STR_SHIFT	0
+#define BCM281XX_STD_PIN_REG_INPUT_DIS_MASK	0x0008
+#define BCM281XX_STD_PIN_REG_INPUT_DIS_SHIFT	3
+#define BCM281XX_STD_PIN_REG_SLEW_MASK		0x0010
+#define BCM281XX_STD_PIN_REG_SLEW_SHIFT		4
+#define BCM281XX_STD_PIN_REG_PULL_UP_MASK	0x0020
+#define BCM281XX_STD_PIN_REG_PULL_UP_SHIFT	5
+#define BCM281XX_STD_PIN_REG_PULL_DN_MASK	0x0040
+#define BCM281XX_STD_PIN_REG_PULL_DN_SHIFT	6
+#define BCM281XX_STD_PIN_REG_HYST_MASK		0x0080
+#define BCM281XX_STD_PIN_REG_HYST_SHIFT		7
+
+/* I2C pin register */
+#define BCM281XX_I2C_PIN_REG_INPUT_DIS_MASK	0x0004
+#define BCM281XX_I2C_PIN_REG_INPUT_DIS_SHIFT	2
+#define BCM281XX_I2C_PIN_REG_SLEW_MASK		0x0008
+#define BCM281XX_I2C_PIN_REG_SLEW_SHIFT		3
+#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_MASK	0x0070
+#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_SHIFT	4
+
+/* HDMI pin register */
+#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_MASK	0x0008
+#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_SHIFT	3
+#define BCM281XX_HDMI_PIN_REG_MODE_MASK		0x0010
+#define BCM281XX_HDMI_PIN_REG_MODE_SHIFT	4
+
+/**
+ * bcm281xx_pin_type - types of pin register
+ */
+enum bcm281xx_pin_type {
+	BCM281XX_PIN_TYPE_UNKNOWN = 0,
+	BCM281XX_PIN_TYPE_STD,
+	BCM281XX_PIN_TYPE_I2C,
+	BCM281XX_PIN_TYPE_HDMI,
+};
+
+static enum bcm281xx_pin_type std_pin = BCM281XX_PIN_TYPE_STD;
+static enum bcm281xx_pin_type i2c_pin = BCM281XX_PIN_TYPE_I2C;
+static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI;
+
+/**
+ * bcm281xx_pin_function- define pin function
+ */
+struct bcm281xx_pin_function {
+	const char *name;
+	const char * const *groups;
+	const unsigned ngroups;
+};
+
+/**
+ * bcm281xx_pinctrl_data - Broadcom-specific pinctrl data
+ * @reg_base - base of pinctrl registers
+ */
+struct bcm281xx_pinctrl_data {
+	void __iomem *reg_base;
+
+	/* List of all pins */
+	const struct pinctrl_pin_desc *pins;
+	const unsigned npins;
+
+	const struct bcm281xx_pin_function *functions;
+	const unsigned nfunctions;
+
+	struct regmap *regmap;
+};
+
+/*
+ * Pin number definition.  The order here must be the same as defined in the
+ * PADCTRLREG block in the RDB.
+ */
+#define BCM281XX_PIN_ADCSYNC		0
+#define BCM281XX_PIN_BAT_RM		1
+#define BCM281XX_PIN_BSC1_SCL		2
+#define BCM281XX_PIN_BSC1_SDA		3
+#define BCM281XX_PIN_BSC2_SCL		4
+#define BCM281XX_PIN_BSC2_SDA		5
+#define BCM281XX_PIN_CLASSGPWR		6
+#define BCM281XX_PIN_CLK_CX8		7
+#define BCM281XX_PIN_CLKOUT_0		8
+#define BCM281XX_PIN_CLKOUT_1		9
+#define BCM281XX_PIN_CLKOUT_2		10
+#define BCM281XX_PIN_CLKOUT_3		11
+#define BCM281XX_PIN_CLKREQ_IN_0	12
+#define BCM281XX_PIN_CLKREQ_IN_1	13
+#define BCM281XX_PIN_CWS_SYS_REQ1	14
+#define BCM281XX_PIN_CWS_SYS_REQ2	15
+#define BCM281XX_PIN_CWS_SYS_REQ3	16
+#define BCM281XX_PIN_DIGMIC1_CLK	17
+#define BCM281XX_PIN_DIGMIC1_DQ		18
+#define BCM281XX_PIN_DIGMIC2_CLK	19
+#define BCM281XX_PIN_DIGMIC2_DQ		20
+#define BCM281XX_PIN_GPEN13		21
+#define BCM281XX_PIN_GPEN14		22
+#define BCM281XX_PIN_GPEN15		23
+#define BCM281XX_PIN_GPIO00		24
+#define BCM281XX_PIN_GPIO01		25
+#define BCM281XX_PIN_GPIO02		26
+#define BCM281XX_PIN_GPIO03		27
+#define BCM281XX_PIN_GPIO04		28
+#define BCM281XX_PIN_GPIO05		29
+#define BCM281XX_PIN_GPIO06		30
+#define BCM281XX_PIN_GPIO07		31
+#define BCM281XX_PIN_GPIO08		32
+#define BCM281XX_PIN_GPIO09		33
+#define BCM281XX_PIN_GPIO10		34
+#define BCM281XX_PIN_GPIO11		35
+#define BCM281XX_PIN_GPIO12		36
+#define BCM281XX_PIN_GPIO13		37
+#define BCM281XX_PIN_GPIO14		38
+#define BCM281XX_PIN_GPS_PABLANK	39
+#define BCM281XX_PIN_GPS_TMARK		40
+#define BCM281XX_PIN_HDMI_SCL		41
+#define BCM281XX_PIN_HDMI_SDA		42
+#define BCM281XX_PIN_IC_DM		43
+#define BCM281XX_PIN_IC_DP		44
+#define BCM281XX_PIN_KP_COL_IP_0	45
+#define BCM281XX_PIN_KP_COL_IP_1	46
+#define BCM281XX_PIN_KP_COL_IP_2	47
+#define BCM281XX_PIN_KP_COL_IP_3	48
+#define BCM281XX_PIN_KP_ROW_OP_0	49
+#define BCM281XX_PIN_KP_ROW_OP_1	50
+#define BCM281XX_PIN_KP_ROW_OP_2	51
+#define BCM281XX_PIN_KP_ROW_OP_3	52
+#define BCM281XX_PIN_LCD_B_0		53
+#define BCM281XX_PIN_LCD_B_1		54
+#define BCM281XX_PIN_LCD_B_2		55
+#define BCM281XX_PIN_LCD_B_3		56
+#define BCM281XX_PIN_LCD_B_4		57
+#define BCM281XX_PIN_LCD_B_5		58
+#define BCM281XX_PIN_LCD_B_6		59
+#define BCM281XX_PIN_LCD_B_7		60
+#define BCM281XX_PIN_LCD_G_0		61
+#define BCM281XX_PIN_LCD_G_1		62
+#define BCM281XX_PIN_LCD_G_2		63
+#define BCM281XX_PIN_LCD_G_3		64
+#define BCM281XX_PIN_LCD_G_4		65
+#define BCM281XX_PIN_LCD_G_5		66
+#define BCM281XX_PIN_LCD_G_6		67
+#define BCM281XX_PIN_LCD_G_7		68
+#define BCM281XX_PIN_LCD_HSYNC		69
+#define BCM281XX_PIN_LCD_OE		70
+#define BCM281XX_PIN_LCD_PCLK		71
+#define BCM281XX_PIN_LCD_R_0		72
+#define BCM281XX_PIN_LCD_R_1		73
+#define BCM281XX_PIN_LCD_R_2		74
+#define BCM281XX_PIN_LCD_R_3		75
+#define BCM281XX_PIN_LCD_R_4		76
+#define BCM281XX_PIN_LCD_R_5		77
+#define BCM281XX_PIN_LCD_R_6		78
+#define BCM281XX_PIN_LCD_R_7		79
+#define BCM281XX_PIN_LCD_VSYNC		80
+#define BCM281XX_PIN_MDMGPIO0		81
+#define BCM281XX_PIN_MDMGPIO1		82
+#define BCM281XX_PIN_MDMGPIO2		83
+#define BCM281XX_PIN_MDMGPIO3		84
+#define BCM281XX_PIN_MDMGPIO4		85
+#define BCM281XX_PIN_MDMGPIO5		86
+#define BCM281XX_PIN_MDMGPIO6		87
+#define BCM281XX_PIN_MDMGPIO7		88
+#define BCM281XX_PIN_MDMGPIO8		89
+#define BCM281XX_PIN_MPHI_DATA_0	90
+#define BCM281XX_PIN_MPHI_DATA_1	91
+#define BCM281XX_PIN_MPHI_DATA_2	92
+#define BCM281XX_PIN_MPHI_DATA_3	93
+#define BCM281XX_PIN_MPHI_DATA_4	94
+#define BCM281XX_PIN_MPHI_DATA_5	95
+#define BCM281XX_PIN_MPHI_DATA_6	96
+#define BCM281XX_PIN_MPHI_DATA_7	97
+#define BCM281XX_PIN_MPHI_DATA_8	98
+#define BCM281XX_PIN_MPHI_DATA_9	99
+#define BCM281XX_PIN_MPHI_DATA_10	100
+#define BCM281XX_PIN_MPHI_DATA_11	101
+#define BCM281XX_PIN_MPHI_DATA_12	102
+#define BCM281XX_PIN_MPHI_DATA_13	103
+#define BCM281XX_PIN_MPHI_DATA_14	104
+#define BCM281XX_PIN_MPHI_DATA_15	105
+#define BCM281XX_PIN_MPHI_HA0		106
+#define BCM281XX_PIN_MPHI_HAT0		107
+#define BCM281XX_PIN_MPHI_HAT1		108
+#define BCM281XX_PIN_MPHI_HCE0_N	109
+#define BCM281XX_PIN_MPHI_HCE1_N	110
+#define BCM281XX_PIN_MPHI_HRD_N		111
+#define BCM281XX_PIN_MPHI_HWR_N		112
+#define BCM281XX_PIN_MPHI_RUN0		113
+#define BCM281XX_PIN_MPHI_RUN1		114
+#define BCM281XX_PIN_MTX_SCAN_CLK	115
+#define BCM281XX_PIN_MTX_SCAN_DATA	116
+#define BCM281XX_PIN_NAND_AD_0		117
+#define BCM281XX_PIN_NAND_AD_1		118
+#define BCM281XX_PIN_NAND_AD_2		119
+#define BCM281XX_PIN_NAND_AD_3		120
+#define BCM281XX_PIN_NAND_AD_4		121
+#define BCM281XX_PIN_NAND_AD_5		122
+#define BCM281XX_PIN_NAND_AD_6		123
+#define BCM281XX_PIN_NAND_AD_7		124
+#define BCM281XX_PIN_NAND_ALE		125
+#define BCM281XX_PIN_NAND_CEN_0		126
+#define BCM281XX_PIN_NAND_CEN_1		127
+#define BCM281XX_PIN_NAND_CLE		128
+#define BCM281XX_PIN_NAND_OEN		129
+#define BCM281XX_PIN_NAND_RDY_0		130
+#define BCM281XX_PIN_NAND_RDY_1		131
+#define BCM281XX_PIN_NAND_WEN		132
+#define BCM281XX_PIN_NAND_WP		133
+#define BCM281XX_PIN_PC1		134
+#define BCM281XX_PIN_PC2		135
+#define BCM281XX_PIN_PMU_INT		136
+#define BCM281XX_PIN_PMU_SCL		137
+#define BCM281XX_PIN_PMU_SDA		138
+#define BCM281XX_PIN_RFST2G_MTSLOTEN3G	139
+#define BCM281XX_PIN_RGMII_0_RX_CTL	140
+#define BCM281XX_PIN_RGMII_0_RXC	141
+#define BCM281XX_PIN_RGMII_0_RXD_0	142
+#define BCM281XX_PIN_RGMII_0_RXD_1	143
+#define BCM281XX_PIN_RGMII_0_RXD_2	144
+#define BCM281XX_PIN_RGMII_0_RXD_3	145
+#define BCM281XX_PIN_RGMII_0_TX_CTL	146
+#define BCM281XX_PIN_RGMII_0_TXC	147
+#define BCM281XX_PIN_RGMII_0_TXD_0	148
+#define BCM281XX_PIN_RGMII_0_TXD_1	149
+#define BCM281XX_PIN_RGMII_0_TXD_2	150
+#define BCM281XX_PIN_RGMII_0_TXD_3	151
+#define BCM281XX_PIN_RGMII_1_RX_CTL	152
+#define BCM281XX_PIN_RGMII_1_RXC	153
+#define BCM281XX_PIN_RGMII_1_RXD_0	154
+#define BCM281XX_PIN_RGMII_1_RXD_1	155
+#define BCM281XX_PIN_RGMII_1_RXD_2	156
+#define BCM281XX_PIN_RGMII_1_RXD_3	157
+#define BCM281XX_PIN_RGMII_1_TX_CTL	158
+#define BCM281XX_PIN_RGMII_1_TXC	159
+#define BCM281XX_PIN_RGMII_1_TXD_0	160
+#define BCM281XX_PIN_RGMII_1_TXD_1	161
+#define BCM281XX_PIN_RGMII_1_TXD_2	162
+#define BCM281XX_PIN_RGMII_1_TXD_3	163
+#define BCM281XX_PIN_RGMII_GPIO_0	164
+#define BCM281XX_PIN_RGMII_GPIO_1	165
+#define BCM281XX_PIN_RGMII_GPIO_2	166
+#define BCM281XX_PIN_RGMII_GPIO_3	167
+#define BCM281XX_PIN_RTXDATA2G_TXDATA3G1	168
+#define BCM281XX_PIN_RTXEN2G_TXDATA3G2	169
+#define BCM281XX_PIN_RXDATA3G0		170
+#define BCM281XX_PIN_RXDATA3G1		171
+#define BCM281XX_PIN_RXDATA3G2		172
+#define BCM281XX_PIN_SDIO1_CLK		173
+#define BCM281XX_PIN_SDIO1_CMD		174
+#define BCM281XX_PIN_SDIO1_DATA_0	175
+#define BCM281XX_PIN_SDIO1_DATA_1	176
+#define BCM281XX_PIN_SDIO1_DATA_2	177
+#define BCM281XX_PIN_SDIO1_DATA_3	178
+#define BCM281XX_PIN_SDIO4_CLK		179
+#define BCM281XX_PIN_SDIO4_CMD		180
+#define BCM281XX_PIN_SDIO4_DATA_0	181
+#define BCM281XX_PIN_SDIO4_DATA_1	182
+#define BCM281XX_PIN_SDIO4_DATA_2	183
+#define BCM281XX_PIN_SDIO4_DATA_3	184
+#define BCM281XX_PIN_SIM_CLK		185
+#define BCM281XX_PIN_SIM_DATA		186
+#define BCM281XX_PIN_SIM_DET		187
+#define BCM281XX_PIN_SIM_RESETN		188
+#define BCM281XX_PIN_SIM2_CLK		189
+#define BCM281XX_PIN_SIM2_DATA		190
+#define BCM281XX_PIN_SIM2_DET		191
+#define BCM281XX_PIN_SIM2_RESETN	192
+#define BCM281XX_PIN_SRI_C		193
+#define BCM281XX_PIN_SRI_D		194
+#define BCM281XX_PIN_SRI_E		195
+#define BCM281XX_PIN_SSP_EXTCLK		196
+#define BCM281XX_PIN_SSP0_CLK		197
+#define BCM281XX_PIN_SSP0_FS		198
+#define BCM281XX_PIN_SSP0_RXD		199
+#define BCM281XX_PIN_SSP0_TXD		200
+#define BCM281XX_PIN_SSP2_CLK		201
+#define BCM281XX_PIN_SSP2_FS_0		202
+#define BCM281XX_PIN_SSP2_FS_1		203
+#define BCM281XX_PIN_SSP2_FS_2		204
+#define BCM281XX_PIN_SSP2_FS_3		205
+#define BCM281XX_PIN_SSP2_RXD_0		206
+#define BCM281XX_PIN_SSP2_RXD_1		207
+#define BCM281XX_PIN_SSP2_TXD_0		208
+#define BCM281XX_PIN_SSP2_TXD_1		209
+#define BCM281XX_PIN_SSP3_CLK		210
+#define BCM281XX_PIN_SSP3_FS		211
+#define BCM281XX_PIN_SSP3_RXD		212
+#define BCM281XX_PIN_SSP3_TXD		213
+#define BCM281XX_PIN_SSP4_CLK		214
+#define BCM281XX_PIN_SSP4_FS		215
+#define BCM281XX_PIN_SSP4_RXD		216
+#define BCM281XX_PIN_SSP4_TXD		217
+#define BCM281XX_PIN_SSP5_CLK		218
+#define BCM281XX_PIN_SSP5_FS		219
+#define BCM281XX_PIN_SSP5_RXD		220
+#define BCM281XX_PIN_SSP5_TXD		221
+#define BCM281XX_PIN_SSP6_CLK		222
+#define BCM281XX_PIN_SSP6_FS		223
+#define BCM281XX_PIN_SSP6_RXD		224
+#define BCM281XX_PIN_SSP6_TXD		225
+#define BCM281XX_PIN_STAT_1		226
+#define BCM281XX_PIN_STAT_2		227
+#define BCM281XX_PIN_SYSCLKEN		228
+#define BCM281XX_PIN_TRACECLK		229
+#define BCM281XX_PIN_TRACEDT00		230
+#define BCM281XX_PIN_TRACEDT01		231
+#define BCM281XX_PIN_TRACEDT02		232
+#define BCM281XX_PIN_TRACEDT03		233
+#define BCM281XX_PIN_TRACEDT04		234
+#define BCM281XX_PIN_TRACEDT05		235
+#define BCM281XX_PIN_TRACEDT06		236
+#define BCM281XX_PIN_TRACEDT07		237
+#define BCM281XX_PIN_TRACEDT08		238
+#define BCM281XX_PIN_TRACEDT09		239
+#define BCM281XX_PIN_TRACEDT10		240
+#define BCM281XX_PIN_TRACEDT11		241
+#define BCM281XX_PIN_TRACEDT12		242
+#define BCM281XX_PIN_TRACEDT13		243
+#define BCM281XX_PIN_TRACEDT14		244
+#define BCM281XX_PIN_TRACEDT15		245
+#define BCM281XX_PIN_TXDATA3G0		246
+#define BCM281XX_PIN_TXPWRIND		247
+#define BCM281XX_PIN_UARTB1_UCTS	248
+#define BCM281XX_PIN_UARTB1_URTS	249
+#define BCM281XX_PIN_UARTB1_URXD	250
+#define BCM281XX_PIN_UARTB1_UTXD	251
+#define BCM281XX_PIN_UARTB2_URXD	252
+#define BCM281XX_PIN_UARTB2_UTXD	253
+#define BCM281XX_PIN_UARTB3_UCTS	254
+#define BCM281XX_PIN_UARTB3_URTS	255
+#define BCM281XX_PIN_UARTB3_URXD	256
+#define BCM281XX_PIN_UARTB3_UTXD	257
+#define BCM281XX_PIN_UARTB4_UCTS	258
+#define BCM281XX_PIN_UARTB4_URTS	259
+#define BCM281XX_PIN_UARTB4_URXD	260
+#define BCM281XX_PIN_UARTB4_UTXD	261
+#define BCM281XX_PIN_VC_CAM1_SCL	262
+#define BCM281XX_PIN_VC_CAM1_SDA	263
+#define BCM281XX_PIN_VC_CAM2_SCL	264
+#define BCM281XX_PIN_VC_CAM2_SDA	265
+#define BCM281XX_PIN_VC_CAM3_SCL	266
+#define BCM281XX_PIN_VC_CAM3_SDA	267
+
+#define BCM281XX_PIN_DESC(a, b, c) \
+	{ .number = a, .name = b, .drv_data = &c##_pin }
+
+/*
+ * Pin description definition.  The order here must be the same as defined in
+ * the PADCTRLREG block in the RDB, since the pin number is used as an index
+ * into this array.
+ */
+static const struct pinctrl_pin_desc bcm281xx_pinctrl_pins[] = {
+	BCM281XX_PIN_DESC(BCM281XX_PIN_ADCSYNC, "adcsync", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_BAT_RM, "bat_rm", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SCL, "bsc1_scl", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SDA, "bsc1_sda", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SCL, "bsc2_scl", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SDA, "bsc2_sda", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLASSGPWR, "classgpwr", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLK_CX8, "clk_cx8", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_0, "clkout_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_1, "clkout_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_2, "clkout_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_3, "clkout_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_0, "clkreq_in_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_1, "clkreq_in_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ1, "cws_sys_req1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ2, "cws_sys_req2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ3, "cws_sys_req3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_CLK, "digmic1_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_DQ, "digmic1_dq", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_CLK, "digmic2_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_DQ, "digmic2_dq", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN13, "gpen13", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN14, "gpen14", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN15, "gpen15", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO00, "gpio00", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO01, "gpio01", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO02, "gpio02", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO03, "gpio03", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO04, "gpio04", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO05, "gpio05", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO06, "gpio06", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO07, "gpio07", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO08, "gpio08", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO09, "gpio09", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO10, "gpio10", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO11, "gpio11", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO12, "gpio12", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO13, "gpio13", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO14, "gpio14", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_PABLANK, "gps_pablank", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_TMARK, "gps_tmark", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SCL, "hdmi_scl", hdmi),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SDA, "hdmi_sda", hdmi),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DM, "ic_dm", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DP, "ic_dp", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_0, "kp_col_ip_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_1, "kp_col_ip_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_2, "kp_col_ip_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_3, "kp_col_ip_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_0, "kp_row_op_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_1, "kp_row_op_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_2, "kp_row_op_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_3, "kp_row_op_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_0, "lcd_b_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_1, "lcd_b_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_2, "lcd_b_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_3, "lcd_b_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_4, "lcd_b_4", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_5, "lcd_b_5", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_6, "lcd_b_6", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_7, "lcd_b_7", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_0, "lcd_g_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_1, "lcd_g_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_2, "lcd_g_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_3, "lcd_g_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_4, "lcd_g_4", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_5, "lcd_g_5", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_6, "lcd_g_6", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_7, "lcd_g_7", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_HSYNC, "lcd_hsync", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_OE, "lcd_oe", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_PCLK, "lcd_pclk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_0, "lcd_r_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_1, "lcd_r_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_2, "lcd_r_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_3, "lcd_r_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_4, "lcd_r_4", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_5, "lcd_r_5", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_6, "lcd_r_6", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_7, "lcd_r_7", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_VSYNC, "lcd_vsync", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO0, "mdmgpio0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO1, "mdmgpio1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO2, "mdmgpio2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO3, "mdmgpio3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO4, "mdmgpio4", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO5, "mdmgpio5", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO6, "mdmgpio6", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO7, "mdmgpio7", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO8, "mdmgpio8", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_0, "mphi_data_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_1, "mphi_data_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_2, "mphi_data_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_3, "mphi_data_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_4, "mphi_data_4", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_5, "mphi_data_5", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_6, "mphi_data_6", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_7, "mphi_data_7", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_8, "mphi_data_8", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_9, "mphi_data_9", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_10, "mphi_data_10", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_11, "mphi_data_11", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_12, "mphi_data_12", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_13, "mphi_data_13", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_14, "mphi_data_14", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_15, "mphi_data_15", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HA0, "mphi_ha0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT0, "mphi_hat0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT1, "mphi_hat1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE0_N, "mphi_hce0_n", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE1_N, "mphi_hce1_n", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HRD_N, "mphi_hrd_n", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HWR_N, "mphi_hwr_n", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN0, "mphi_run0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN1, "mphi_run1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_CLK, "mtx_scan_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_DATA, "mtx_scan_data", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_0, "nand_ad_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_1, "nand_ad_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_2, "nand_ad_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_3, "nand_ad_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_4, "nand_ad_4", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_5, "nand_ad_5", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_6, "nand_ad_6", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_7, "nand_ad_7", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_ALE, "nand_ale", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_0, "nand_cen_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_1, "nand_cen_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CLE, "nand_cle", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_OEN, "nand_oen", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_0, "nand_rdy_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_1, "nand_rdy_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WEN, "nand_wen", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WP, "nand_wp", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_PC1, "pc1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_PC2, "pc2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_INT, "pmu_int", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SCL, "pmu_scl", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SDA, "pmu_sda", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RFST2G_MTSLOTEN3G, "rfst2g_mtsloten3g",
+		std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RX_CTL, "rgmii_0_rx_ctl", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXC, "rgmii_0_rxc", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_0, "rgmii_0_rxd_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_1, "rgmii_0_rxd_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_2, "rgmii_0_rxd_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_3, "rgmii_0_rxd_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TX_CTL, "rgmii_0_tx_ctl", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXC, "rgmii_0_txc", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_0, "rgmii_0_txd_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_1, "rgmii_0_txd_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_2, "rgmii_0_txd_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_3, "rgmii_0_txd_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RX_CTL, "rgmii_1_rx_ctl", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXC, "rgmii_1_rxc", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_0, "rgmii_1_rxd_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_1, "rgmii_1_rxd_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_2, "rgmii_1_rxd_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_3, "rgmii_1_rxd_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TX_CTL, "rgmii_1_tx_ctl", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXC, "rgmii_1_txc", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_0, "rgmii_1_txd_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_1, "rgmii_1_txd_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_2, "rgmii_1_txd_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_3, "rgmii_1_txd_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_0, "rgmii_gpio_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_1, "rgmii_gpio_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_2, "rgmii_gpio_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_3, "rgmii_gpio_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RTXDATA2G_TXDATA3G1,
+		"rtxdata2g_txdata3g1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RTXEN2G_TXDATA3G2, "rtxen2g_txdata3g2",
+		std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G0, "rxdata3g0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G1, "rxdata3g1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G2, "rxdata3g2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CLK, "sdio1_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CMD, "sdio1_cmd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_0, "sdio1_data_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_1, "sdio1_data_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_2, "sdio1_data_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_3, "sdio1_data_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CLK, "sdio4_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CMD, "sdio4_cmd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_0, "sdio4_data_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_1, "sdio4_data_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_2, "sdio4_data_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_3, "sdio4_data_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_CLK, "sim_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DATA, "sim_data", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DET, "sim_det", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_RESETN, "sim_resetn", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_CLK, "sim2_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DATA, "sim2_data", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DET, "sim2_det", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_RESETN, "sim2_resetn", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_C, "sri_c", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_D, "sri_d", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_E, "sri_e", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP_EXTCLK, "ssp_extclk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_CLK, "ssp0_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_FS, "ssp0_fs", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_RXD, "ssp0_rxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_TXD, "ssp0_txd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_CLK, "ssp2_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_0, "ssp2_fs_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_1, "ssp2_fs_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_2, "ssp2_fs_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_3, "ssp2_fs_3", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_0, "ssp2_rxd_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_1, "ssp2_rxd_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_0, "ssp2_txd_0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_1, "ssp2_txd_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_CLK, "ssp3_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_FS, "ssp3_fs", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_RXD, "ssp3_rxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_TXD, "ssp3_txd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_CLK, "ssp4_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_FS, "ssp4_fs", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_RXD, "ssp4_rxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_TXD, "ssp4_txd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_CLK, "ssp5_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_FS, "ssp5_fs", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_RXD, "ssp5_rxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_TXD, "ssp5_txd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_CLK, "ssp6_clk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_FS, "ssp6_fs", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_RXD, "ssp6_rxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_TXD, "ssp6_txd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_1, "stat_1", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_2, "stat_2", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_SYSCLKEN, "sysclken", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACECLK, "traceclk", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT00, "tracedt00", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT01, "tracedt01", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT02, "tracedt02", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT03, "tracedt03", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT04, "tracedt04", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT05, "tracedt05", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT06, "tracedt06", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT07, "tracedt07", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT08, "tracedt08", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT09, "tracedt09", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT10, "tracedt10", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT11, "tracedt11", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT12, "tracedt12", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT13, "tracedt13", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT14, "tracedt14", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT15, "tracedt15", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TXDATA3G0, "txdata3g0", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_TXPWRIND, "txpwrind", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UCTS, "uartb1_ucts", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URTS, "uartb1_urts", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URXD, "uartb1_urxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UTXD, "uartb1_utxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_URXD, "uartb2_urxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_UTXD, "uartb2_utxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UCTS, "uartb3_ucts", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URTS, "uartb3_urts", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URXD, "uartb3_urxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UTXD, "uartb3_utxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UCTS, "uartb4_ucts", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URTS, "uartb4_urts", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URXD, "uartb4_urxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UTXD, "uartb4_utxd", std),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SCL, "vc_cam1_scl", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SDA, "vc_cam1_sda", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SCL, "vc_cam2_scl", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SDA, "vc_cam2_sda", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SCL, "vc_cam3_scl", i2c),
+	BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SDA, "vc_cam3_sda", i2c),
+};
+
+static const char * const bcm281xx_alt_groups[] = {
+	"adcsync",
+	"bat_rm",
+	"bsc1_scl",
+	"bsc1_sda",
+	"bsc2_scl",
+	"bsc2_sda",
+	"classgpwr",
+	"clk_cx8",
+	"clkout_0",
+	"clkout_1",
+	"clkout_2",
+	"clkout_3",
+	"clkreq_in_0",
+	"clkreq_in_1",
+	"cws_sys_req1",
+	"cws_sys_req2",
+	"cws_sys_req3",
+	"digmic1_clk",
+	"digmic1_dq",
+	"digmic2_clk",
+	"digmic2_dq",
+	"gpen13",
+	"gpen14",
+	"gpen15",
+	"gpio00",
+	"gpio01",
+	"gpio02",
+	"gpio03",
+	"gpio04",
+	"gpio05",
+	"gpio06",
+	"gpio07",
+	"gpio08",
+	"gpio09",
+	"gpio10",
+	"gpio11",
+	"gpio12",
+	"gpio13",
+	"gpio14",
+	"gps_pablank",
+	"gps_tmark",
+	"hdmi_scl",
+	"hdmi_sda",
+	"ic_dm",
+	"ic_dp",
+	"kp_col_ip_0",
+	"kp_col_ip_1",
+	"kp_col_ip_2",
+	"kp_col_ip_3",
+	"kp_row_op_0",
+	"kp_row_op_1",
+	"kp_row_op_2",
+	"kp_row_op_3",
+	"lcd_b_0",
+	"lcd_b_1",
+	"lcd_b_2",
+	"lcd_b_3",
+	"lcd_b_4",
+	"lcd_b_5",
+	"lcd_b_6",
+	"lcd_b_7",
+	"lcd_g_0",
+	"lcd_g_1",
+	"lcd_g_2",
+	"lcd_g_3",
+	"lcd_g_4",
+	"lcd_g_5",
+	"lcd_g_6",
+	"lcd_g_7",
+	"lcd_hsync",
+	"lcd_oe",
+	"lcd_pclk",
+	"lcd_r_0",
+	"lcd_r_1",
+	"lcd_r_2",
+	"lcd_r_3",
+	"lcd_r_4",
+	"lcd_r_5",
+	"lcd_r_6",
+	"lcd_r_7",
+	"lcd_vsync",
+	"mdmgpio0",
+	"mdmgpio1",
+	"mdmgpio2",
+	"mdmgpio3",
+	"mdmgpio4",
+	"mdmgpio5",
+	"mdmgpio6",
+	"mdmgpio7",
+	"mdmgpio8",
+	"mphi_data_0",
+	"mphi_data_1",
+	"mphi_data_2",
+	"mphi_data_3",
+	"mphi_data_4",
+	"mphi_data_5",
+	"mphi_data_6",
+	"mphi_data_7",
+	"mphi_data_8",
+	"mphi_data_9",
+	"mphi_data_10",
+	"mphi_data_11",
+	"mphi_data_12",
+	"mphi_data_13",
+	"mphi_data_14",
+	"mphi_data_15",
+	"mphi_ha0",
+	"mphi_hat0",
+	"mphi_hat1",
+	"mphi_hce0_n",
+	"mphi_hce1_n",
+	"mphi_hrd_n",
+	"mphi_hwr_n",
+	"mphi_run0",
+	"mphi_run1",
+	"mtx_scan_clk",
+	"mtx_scan_data",
+	"nand_ad_0",
+	"nand_ad_1",
+	"nand_ad_2",
+	"nand_ad_3",
+	"nand_ad_4",
+	"nand_ad_5",
+	"nand_ad_6",
+	"nand_ad_7",
+	"nand_ale",
+	"nand_cen_0",
+	"nand_cen_1",
+	"nand_cle",
+	"nand_oen",
+	"nand_rdy_0",
+	"nand_rdy_1",
+	"nand_wen",
+	"nand_wp",
+	"pc1",
+	"pc2",
+	"pmu_int",
+	"pmu_scl",
+	"pmu_sda",
+	"rfst2g_mtsloten3g",
+	"rgmii_0_rx_ctl",
+	"rgmii_0_rxc",
+	"rgmii_0_rxd_0",
+	"rgmii_0_rxd_1",
+	"rgmii_0_rxd_2",
+	"rgmii_0_rxd_3",
+	"rgmii_0_tx_ctl",
+	"rgmii_0_txc",
+	"rgmii_0_txd_0",
+	"rgmii_0_txd_1",
+	"rgmii_0_txd_2",
+	"rgmii_0_txd_3",
+	"rgmii_1_rx_ctl",
+	"rgmii_1_rxc",
+	"rgmii_1_rxd_0",
+	"rgmii_1_rxd_1",
+	"rgmii_1_rxd_2",
+	"rgmii_1_rxd_3",
+	"rgmii_1_tx_ctl",
+	"rgmii_1_txc",
+	"rgmii_1_txd_0",
+	"rgmii_1_txd_1",
+	"rgmii_1_txd_2",
+	"rgmii_1_txd_3",
+	"rgmii_gpio_0",
+	"rgmii_gpio_1",
+	"rgmii_gpio_2",
+	"rgmii_gpio_3",
+	"rtxdata2g_txdata3g1",
+	"rtxen2g_txdata3g2",
+	"rxdata3g0",
+	"rxdata3g1",
+	"rxdata3g2",
+	"sdio1_clk",
+	"sdio1_cmd",
+	"sdio1_data_0",
+	"sdio1_data_1",
+	"sdio1_data_2",
+	"sdio1_data_3",
+	"sdio4_clk",
+	"sdio4_cmd",
+	"sdio4_data_0",
+	"sdio4_data_1",
+	"sdio4_data_2",
+	"sdio4_data_3",
+	"sim_clk",
+	"sim_data",
+	"sim_det",
+	"sim_resetn",
+	"sim2_clk",
+	"sim2_data",
+	"sim2_det",
+	"sim2_resetn",
+	"sri_c",
+	"sri_d",
+	"sri_e",
+	"ssp_extclk",
+	"ssp0_clk",
+	"ssp0_fs",
+	"ssp0_rxd",
+	"ssp0_txd",
+	"ssp2_clk",
+	"ssp2_fs_0",
+	"ssp2_fs_1",
+	"ssp2_fs_2",
+	"ssp2_fs_3",
+	"ssp2_rxd_0",
+	"ssp2_rxd_1",
+	"ssp2_txd_0",
+	"ssp2_txd_1",
+	"ssp3_clk",
+	"ssp3_fs",
+	"ssp3_rxd",
+	"ssp3_txd",
+	"ssp4_clk",
+	"ssp4_fs",
+	"ssp4_rxd",
+	"ssp4_txd",
+	"ssp5_clk",
+	"ssp5_fs",
+	"ssp5_rxd",
+	"ssp5_txd",
+	"ssp6_clk",
+	"ssp6_fs",
+	"ssp6_rxd",
+	"ssp6_txd",
+	"stat_1",
+	"stat_2",
+	"sysclken",
+	"traceclk",
+	"tracedt00",
+	"tracedt01",
+	"tracedt02",
+	"tracedt03",
+	"tracedt04",
+	"tracedt05",
+	"tracedt06",
+	"tracedt07",
+	"tracedt08",
+	"tracedt09",
+	"tracedt10",
+	"tracedt11",
+	"tracedt12",
+	"tracedt13",
+	"tracedt14",
+	"tracedt15",
+	"txdata3g0",
+	"txpwrind",
+	"uartb1_ucts",
+	"uartb1_urts",
+	"uartb1_urxd",
+	"uartb1_utxd",
+	"uartb2_urxd",
+	"uartb2_utxd",
+	"uartb3_ucts",
+	"uartb3_urts",
+	"uartb3_urxd",
+	"uartb3_utxd",
+	"uartb4_ucts",
+	"uartb4_urts",
+	"uartb4_urxd",
+	"uartb4_utxd",
+	"vc_cam1_scl",
+	"vc_cam1_sda",
+	"vc_cam2_scl",
+	"vc_cam2_sda",
+	"vc_cam3_scl",
+	"vc_cam3_sda",
+};
+
+/* Every pin can implement all ALT1-ALT4 functions */
+#define BCM281XX_PIN_FUNCTION(fcn_name)			\
+{							\
+	.name = #fcn_name,				\
+	.groups = bcm281xx_alt_groups,			\
+	.ngroups = ARRAY_SIZE(bcm281xx_alt_groups),	\
+}
+
+static const struct bcm281xx_pin_function bcm281xx_functions[] = {
+	BCM281XX_PIN_FUNCTION(alt1),
+	BCM281XX_PIN_FUNCTION(alt2),
+	BCM281XX_PIN_FUNCTION(alt3),
+	BCM281XX_PIN_FUNCTION(alt4),
+};
+
+static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
+	.pins = bcm281xx_pinctrl_pins,
+	.npins = ARRAY_SIZE(bcm281xx_pinctrl_pins),
+	.functions = bcm281xx_functions,
+	.nfunctions = ARRAY_SIZE(bcm281xx_functions),
+};
+
+static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
+						  unsigned pin)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	if (pin >= pdata->npins)
+		return BCM281XX_PIN_TYPE_UNKNOWN;
+
+	return *(enum bcm281xx_pin_type *)(pdata->pins[pin].drv_data);
+}
+
+#define BCM281XX_PIN_SHIFT(type, param) \
+	(BCM281XX_ ## type ## _PIN_REG_ ## param ## _SHIFT)
+
+#define BCM281XX_PIN_MASK(type, param) \
+	(BCM281XX_ ## type ## _PIN_REG_ ## param ## _MASK)
+
+/*
+ * This helper function is used to build up the value and mask used to write to
+ * a pin register, but does not actually write to the register.
+ */
+static inline void bcm281xx_pin_update(u32 *reg_val, u32 *reg_mask,
+				       u32 param_val, u32 param_shift,
+				       u32 param_mask)
+{
+	*reg_val &= ~param_mask;
+	*reg_val |= (param_val << param_shift) & param_mask;
+	*reg_mask |= param_mask;
+}
+
+static struct regmap_config bcm281xx_pinctrl_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = BCM281XX_PIN_VC_CAM3_SDA,
+};
+
+static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	return pdata->npins;
+}
+
+static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+						   unsigned group)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	return pdata->pins[group].name;
+}
+
+static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+					   unsigned group,
+					   const unsigned **pins,
+					   unsigned *num_pins)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = &pdata->pins[group].number;
+	*num_pins = 1;
+
+	return 0;
+}
+
+static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+					  struct seq_file *s,
+					  unsigned offset)
+{
+	seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static struct pinctrl_ops bcm281xx_pinctrl_ops = {
+	.get_groups_count = bcm281xx_pinctrl_get_groups_count,
+	.get_group_name = bcm281xx_pinctrl_get_group_name,
+	.get_group_pins = bcm281xx_pinctrl_get_group_pins,
+	.pin_dbg_show = bcm281xx_pinctrl_pin_dbg_show,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+	.dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	return pdata->nfunctions;
+}
+
+static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
+						 unsigned function)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	return pdata->functions[function].name;
+}
+
+static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
+					   unsigned function,
+					   const char * const **groups,
+					   unsigned * const num_groups)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pdata->functions[function].groups;
+	*num_groups = pdata->functions[function].ngroups;
+
+	return 0;
+}
+
+static int bcm281xx_pinmux_enable(struct pinctrl_dev *pctldev,
+				  unsigned function,
+				  unsigned group)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	const struct bcm281xx_pin_function *f = &pdata->functions[function];
+	u32 offset = 4 * pdata->pins[group].number;
+	int rc = 0;
+
+	dev_dbg(pctldev->dev,
+		"%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
+		__func__, f->name, function, pdata->pins[group].name,
+		pdata->pins[group].number, offset);
+
+	rc = regmap_update_bits(pdata->regmap, offset,
+		BCM281XX_PIN_REG_F_SEL_MASK,
+		function << BCM281XX_PIN_REG_F_SEL_SHIFT);
+	if (rc)
+		dev_err(pctldev->dev,
+			"Error updating register for pin %s (%d).\n",
+			pdata->pins[group].name, pdata->pins[group].number);
+
+	return rc;
+}
+
+static struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = {
+	.get_functions_count = bcm281xx_pinctrl_get_fcns_count,
+	.get_function_name = bcm281xx_pinctrl_get_fcn_name,
+	.get_function_groups = bcm281xx_pinctrl_get_fcn_groups,
+	.enable = bcm281xx_pinmux_enable,
+};
+
+static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
+					   unsigned pin,
+					   unsigned long *config)
+{
+	return -ENOTSUPP;
+}
+
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
+				   unsigned pin,
+				   unsigned long *configs,
+				   unsigned num_configs,
+				   u32 *val,
+				   u32 *mask)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	int i;
+	enum pin_config_param param;
+	u16 arg;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			arg = (arg >= 1 ? 1 : 0);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(STD, HYST),
+				BCM281XX_PIN_MASK(STD, HYST));
+			break;
+		/*
+		 * The pin bias can only be one of pull-up, pull-down, or
+		 * disable.  The user does not need to specify a value for the
+		 * property, and the default value from pinconf-generic is
+		 * ignored.
+		 */
+		case PIN_CONFIG_BIAS_DISABLE:
+			bcm281xx_pin_update(val, mask, 0,
+				BCM281XX_PIN_SHIFT(STD, PULL_UP),
+				BCM281XX_PIN_MASK(STD, PULL_UP));
+			bcm281xx_pin_update(val, mask, 0,
+				BCM281XX_PIN_SHIFT(STD, PULL_DN),
+				BCM281XX_PIN_MASK(STD, PULL_DN));
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_UP:
+			bcm281xx_pin_update(val, mask, 1,
+				BCM281XX_PIN_SHIFT(STD, PULL_UP),
+				BCM281XX_PIN_MASK(STD, PULL_UP));
+			bcm281xx_pin_update(val, mask, 0,
+				BCM281XX_PIN_SHIFT(STD, PULL_DN),
+				BCM281XX_PIN_MASK(STD, PULL_DN));
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			bcm281xx_pin_update(val, mask, 0,
+				BCM281XX_PIN_SHIFT(STD, PULL_UP),
+				BCM281XX_PIN_MASK(STD, PULL_UP));
+			bcm281xx_pin_update(val, mask, 1,
+				BCM281XX_PIN_SHIFT(STD, PULL_DN),
+				BCM281XX_PIN_MASK(STD, PULL_DN));
+			break;
+
+		case PIN_CONFIG_SLEW_RATE:
+			arg = (arg >= 1 ? 1 : 0);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(STD, SLEW),
+				BCM281XX_PIN_MASK(STD, SLEW));
+			break;
+
+		case PIN_CONFIG_INPUT_ENABLE:
+			/* inversed since register is for input _disable_ */
+			arg = (arg >= 1 ? 0 : 1);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(STD, INPUT_DIS),
+				BCM281XX_PIN_MASK(STD, INPUT_DIS));
+			break;
+
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			/* Valid range is 2-16 mA, even numbers only */
+			if ((arg < 2) || (arg > 16) || (arg % 2)) {
+				dev_err(pctldev->dev,
+					"Invalid Drive Strength value (%d) for "
+					"pin %s (%d). Valid values are "
+					"(2..16) mA, even numbers only.\n",
+					arg, pdata->pins[pin].name, pin);
+				return -EINVAL;
+			}
+			bcm281xx_pin_update(val, mask, (arg/2)-1,
+				BCM281XX_PIN_SHIFT(STD, DRV_STR),
+				BCM281XX_PIN_MASK(STD, DRV_STR));
+			break;
+
+		default:
+			dev_err(pctldev->dev,
+				"Unrecognized pin config %d for pin %s (%d).\n",
+				param, pdata->pins[pin].name, pin);
+			return -EINVAL;
+
+		} /* switch config */
+	} /* for each config */
+
+	return 0;
+}
+
+/*
+ * The pull-up strength for an I2C pin is represented by bits 4-6 in the
+ * register with the following mapping:
+ *   0b000: No pull-up
+ *   0b001: 1200 Ohm
+ *   0b010: 1800 Ohm
+ *   0b011: 720 Ohm
+ *   0b100: 2700 Ohm
+ *   0b101: 831 Ohm
+ *   0b110: 1080 Ohm
+ *   0b111: 568 Ohm
+ * This array maps pull-up strength in Ohms to register values (1+index).
+ */
+static const u16 bcm281xx_pullup_map[] = {
+	1200, 1800, 720, 2700, 831, 1080, 568
+};
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
+				   unsigned pin,
+				   unsigned long *configs,
+				   unsigned num_configs,
+				   u32 *val,
+				   u32 *mask)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	int i, j;
+	enum pin_config_param param;
+	u16 arg;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_PULL_UP:
+			for (j = 0; j < ARRAY_SIZE(bcm281xx_pullup_map); j++)
+				if (bcm281xx_pullup_map[j] == arg)
+					break;
+
+			if (j == ARRAY_SIZE(bcm281xx_pullup_map)) {
+				dev_err(pctldev->dev,
+					"Invalid pull-up value (%d) for pin %s "
+					"(%d). Valid values are 568, 720, 831, "
+					"1080, 1200, 1800, 2700 Ohms.\n",
+					arg, pdata->pins[pin].name, pin);
+				return -EINVAL;
+			}
+
+			bcm281xx_pin_update(val, mask, j+1,
+				BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
+				BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
+			break;
+
+		case PIN_CONFIG_BIAS_DISABLE:
+			bcm281xx_pin_update(val, mask, 0,
+				BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
+				BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
+			break;
+
+		case PIN_CONFIG_SLEW_RATE:
+			arg = (arg >= 1 ? 1 : 0);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(I2C, SLEW),
+				BCM281XX_PIN_MASK(I2C, SLEW));
+			break;
+
+		case PIN_CONFIG_INPUT_ENABLE:
+			/* inversed since register is for input _disable_ */
+			arg = (arg >= 1 ? 0 : 1);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(I2C, INPUT_DIS),
+				BCM281XX_PIN_MASK(I2C, INPUT_DIS));
+			break;
+
+		default:
+			dev_err(pctldev->dev,
+				"Unrecognized pin config %d for pin %s (%d).\n",
+				param, pdata->pins[pin].name, pin);
+			return -EINVAL;
+
+		} /* switch config */
+	} /* for each config */
+
+	return 0;
+}
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
+				    unsigned pin,
+				    unsigned long *configs,
+				    unsigned num_configs,
+				    u32 *val,
+				    u32 *mask)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	int i;
+	enum pin_config_param param;
+	u16 arg;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_SLEW_RATE:
+			arg = (arg >= 1 ? 1 : 0);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(HDMI, MODE),
+				BCM281XX_PIN_MASK(HDMI, MODE));
+			break;
+
+		case PIN_CONFIG_INPUT_ENABLE:
+			/* inversed since register is for input _disable_ */
+			arg = (arg >= 1 ? 0 : 1);
+			bcm281xx_pin_update(val, mask, arg,
+				BCM281XX_PIN_SHIFT(HDMI, INPUT_DIS),
+				BCM281XX_PIN_MASK(HDMI, INPUT_DIS));
+			break;
+
+		default:
+			dev_err(pctldev->dev,
+				"Unrecognized pin config %d for pin %s (%d).\n",
+				param, pdata->pins[pin].name, pin);
+			return -EINVAL;
+
+		} /* switch config */
+	} /* for each config */
+
+	return 0;
+}
+
+static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
+					   unsigned pin,
+					   unsigned long *configs,
+					   unsigned num_configs)
+{
+	struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	enum bcm281xx_pin_type pin_type;
+	u32 offset = 4 * pin;
+	u32 cfg_val, cfg_mask;
+	int rc;
+
+	cfg_val = 0;
+	cfg_mask = 0;
+	pin_type = pin_type_get(pctldev, pin);
+
+	/* Different pins have different configuration options */
+	switch (pin_type) {
+	case BCM281XX_PIN_TYPE_STD:
+		rc = bcm281xx_std_pin_update(pctldev, pin, configs,
+			num_configs, &cfg_val, &cfg_mask);
+		break;
+
+	case BCM281XX_PIN_TYPE_I2C:
+		rc = bcm281xx_i2c_pin_update(pctldev, pin, configs,
+			num_configs, &cfg_val, &cfg_mask);
+		break;
+
+	case BCM281XX_PIN_TYPE_HDMI:
+		rc = bcm281xx_hdmi_pin_update(pctldev, pin, configs,
+			num_configs, &cfg_val, &cfg_mask);
+		break;
+
+	default:
+		dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
+			pdata->pins[pin].name, pin);
+		return -EINVAL;
+
+	} /* switch pin type */
+
+	if (rc)
+		return rc;
+
+	dev_dbg(pctldev->dev,
+		"%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
+		__func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
+
+	rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
+	if (rc) {
+		dev_err(pctldev->dev,
+			"Error updating register for pin %s (%d).\n",
+			pdata->pins[pin].name, pin);
+		return rc;
+	}
+
+	return 0;
+}
+
+static struct pinconf_ops bcm281xx_pinctrl_pinconf_ops = {
+	.pin_config_get = bcm281xx_pinctrl_pin_config_get,
+	.pin_config_set = bcm281xx_pinctrl_pin_config_set,
+};
+
+static struct pinctrl_desc bcm281xx_pinctrl_desc = {
+	/* name, pins, npins members initialized in probe function */
+	.pctlops = &bcm281xx_pinctrl_ops,
+	.pmxops = &bcm281xx_pinctrl_pinmux_ops,
+	.confops = &bcm281xx_pinctrl_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
+{
+	struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
+	struct resource *res;
+	struct pinctrl_dev *pctl;
+
+	/* So far We can assume there is only 1 bank of registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Missing MEM resource\n");
+		return -ENODEV;
+	}
+
+	pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pdata->reg_base)) {
+		dev_err(&pdev->dev, "Failed to ioremap MEM resource\n");
+		return -ENODEV;
+	}
+
+	/* Initialize the dynamic part of pinctrl_desc */
+	pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
+		&bcm281xx_pinctrl_regmap_config);
+	if (IS_ERR(pdata->regmap)) {
+		dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
+		return -ENODEV;
+	}
+
+	bcm281xx_pinctrl_desc.name = dev_name(&pdev->dev);
+	bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
+	bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
+
+	pctl = pinctrl_register(&bcm281xx_pinctrl_desc,
+				&pdev->dev,
+				pdata);
+	if (!pctl) {
+		dev_err(&pdev->dev, "Failed to register pinctrl\n");
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, pdata);
+
+	return 0;
+}
+
+static struct of_device_id bcm281xx_pinctrl_of_match[] = {
+	{ .compatible = "brcm,bcm11351-pinctrl", },
+	{ },
+};
+
+static struct platform_driver bcm281xx_pinctrl_driver = {
+	.driver = {
+		.name = "bcm281xx-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = bcm281xx_pinctrl_of_match,
+	},
+};
+
+module_platform_driver_probe(bcm281xx_pinctrl_driver, bcm281xx_pinctrl_probe);
+
+MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
+MODULE_AUTHOR("Sherman Yin <syin@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom BCM281xx pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-capri.c b/drivers/pinctrl/pinctrl-capri.c
deleted file mode 100644
index eb2500212147..000000000000
--- a/drivers/pinctrl/pinctrl-capri.c
+++ /dev/null
@@ -1,1454 +0,0 @@
-/*
- * Copyright (C) 2013 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-#include "core.h"
-#include "pinctrl-utils.h"
-
-/* Capri Pin Control Registers Definitions */
-
-/* Function Select bits are the same for all pin control registers */
-#define CAPRI_PIN_REG_F_SEL_MASK		0x0700
-#define CAPRI_PIN_REG_F_SEL_SHIFT		8
-
-/* Standard pin register */
-#define CAPRI_STD_PIN_REG_DRV_STR_MASK		0x0007
-#define CAPRI_STD_PIN_REG_DRV_STR_SHIFT		0
-#define CAPRI_STD_PIN_REG_INPUT_DIS_MASK	0x0008
-#define CAPRI_STD_PIN_REG_INPUT_DIS_SHIFT	3
-#define CAPRI_STD_PIN_REG_SLEW_MASK		0x0010
-#define CAPRI_STD_PIN_REG_SLEW_SHIFT		4
-#define CAPRI_STD_PIN_REG_PULL_UP_MASK		0x0020
-#define CAPRI_STD_PIN_REG_PULL_UP_SHIFT		5
-#define CAPRI_STD_PIN_REG_PULL_DN_MASK		0x0040
-#define CAPRI_STD_PIN_REG_PULL_DN_SHIFT		6
-#define CAPRI_STD_PIN_REG_HYST_MASK		0x0080
-#define CAPRI_STD_PIN_REG_HYST_SHIFT		7
-
-/* I2C pin register */
-#define CAPRI_I2C_PIN_REG_INPUT_DIS_MASK	0x0004
-#define CAPRI_I2C_PIN_REG_INPUT_DIS_SHIFT	2
-#define CAPRI_I2C_PIN_REG_SLEW_MASK		0x0008
-#define CAPRI_I2C_PIN_REG_SLEW_SHIFT		3
-#define CAPRI_I2C_PIN_REG_PULL_UP_STR_MASK	0x0070
-#define CAPRI_I2C_PIN_REG_PULL_UP_STR_SHIFT	4
-
-/* HDMI pin register */
-#define CAPRI_HDMI_PIN_REG_INPUT_DIS_MASK	0x0008
-#define CAPRI_HDMI_PIN_REG_INPUT_DIS_SHIFT	3
-#define CAPRI_HDMI_PIN_REG_MODE_MASK		0x0010
-#define CAPRI_HDMI_PIN_REG_MODE_SHIFT		4
-
-/**
- * capri_pin_type - types of pin register
- */
-enum capri_pin_type {
-	CAPRI_PIN_TYPE_UNKNOWN = 0,
-	CAPRI_PIN_TYPE_STD,
-	CAPRI_PIN_TYPE_I2C,
-	CAPRI_PIN_TYPE_HDMI,
-};
-
-static enum capri_pin_type std_pin = CAPRI_PIN_TYPE_STD;
-static enum capri_pin_type i2c_pin = CAPRI_PIN_TYPE_I2C;
-static enum capri_pin_type hdmi_pin = CAPRI_PIN_TYPE_HDMI;
-
-/**
- * capri_pin_function- define pin function
- */
-struct capri_pin_function {
-	const char *name;
-	const char * const *groups;
-	const unsigned ngroups;
-};
-
-/**
- * capri_pinctrl_data - Broadcom-specific pinctrl data
- * @reg_base - base of pinctrl registers
- */
-struct capri_pinctrl_data {
-	void __iomem *reg_base;
-
-	/* List of all pins */
-	const struct pinctrl_pin_desc *pins;
-	const unsigned npins;
-
-	const struct capri_pin_function *functions;
-	const unsigned nfunctions;
-
-	struct regmap *regmap;
-};
-
-/*
- * Pin number definition.  The order here must be the same as defined in the
- * PADCTRLREG block in the RDB.
- */
-#define CAPRI_PIN_ADCSYNC		0
-#define CAPRI_PIN_BAT_RM		1
-#define CAPRI_PIN_BSC1_SCL		2
-#define CAPRI_PIN_BSC1_SDA		3
-#define CAPRI_PIN_BSC2_SCL		4
-#define CAPRI_PIN_BSC2_SDA		5
-#define CAPRI_PIN_CLASSGPWR		6
-#define CAPRI_PIN_CLK_CX8		7
-#define CAPRI_PIN_CLKOUT_0		8
-#define CAPRI_PIN_CLKOUT_1		9
-#define CAPRI_PIN_CLKOUT_2		10
-#define CAPRI_PIN_CLKOUT_3		11
-#define CAPRI_PIN_CLKREQ_IN_0		12
-#define CAPRI_PIN_CLKREQ_IN_1		13
-#define CAPRI_PIN_CWS_SYS_REQ1		14
-#define CAPRI_PIN_CWS_SYS_REQ2		15
-#define CAPRI_PIN_CWS_SYS_REQ3		16
-#define CAPRI_PIN_DIGMIC1_CLK		17
-#define CAPRI_PIN_DIGMIC1_DQ		18
-#define CAPRI_PIN_DIGMIC2_CLK		19
-#define CAPRI_PIN_DIGMIC2_DQ		20
-#define CAPRI_PIN_GPEN13		21
-#define CAPRI_PIN_GPEN14		22
-#define CAPRI_PIN_GPEN15		23
-#define CAPRI_PIN_GPIO00		24
-#define CAPRI_PIN_GPIO01		25
-#define CAPRI_PIN_GPIO02		26
-#define CAPRI_PIN_GPIO03		27
-#define CAPRI_PIN_GPIO04		28
-#define CAPRI_PIN_GPIO05		29
-#define CAPRI_PIN_GPIO06		30
-#define CAPRI_PIN_GPIO07		31
-#define CAPRI_PIN_GPIO08		32
-#define CAPRI_PIN_GPIO09		33
-#define CAPRI_PIN_GPIO10		34
-#define CAPRI_PIN_GPIO11		35
-#define CAPRI_PIN_GPIO12		36
-#define CAPRI_PIN_GPIO13		37
-#define CAPRI_PIN_GPIO14		38
-#define CAPRI_PIN_GPS_PABLANK		39
-#define CAPRI_PIN_GPS_TMARK		40
-#define CAPRI_PIN_HDMI_SCL		41
-#define CAPRI_PIN_HDMI_SDA		42
-#define CAPRI_PIN_IC_DM			43
-#define CAPRI_PIN_IC_DP			44
-#define CAPRI_PIN_KP_COL_IP_0		45
-#define CAPRI_PIN_KP_COL_IP_1		46
-#define CAPRI_PIN_KP_COL_IP_2		47
-#define CAPRI_PIN_KP_COL_IP_3		48
-#define CAPRI_PIN_KP_ROW_OP_0		49
-#define CAPRI_PIN_KP_ROW_OP_1		50
-#define CAPRI_PIN_KP_ROW_OP_2		51
-#define CAPRI_PIN_KP_ROW_OP_3		52
-#define CAPRI_PIN_LCD_B_0		53
-#define CAPRI_PIN_LCD_B_1		54
-#define CAPRI_PIN_LCD_B_2		55
-#define CAPRI_PIN_LCD_B_3		56
-#define CAPRI_PIN_LCD_B_4		57
-#define CAPRI_PIN_LCD_B_5		58
-#define CAPRI_PIN_LCD_B_6		59
-#define CAPRI_PIN_LCD_B_7		60
-#define CAPRI_PIN_LCD_G_0		61
-#define CAPRI_PIN_LCD_G_1		62
-#define CAPRI_PIN_LCD_G_2		63
-#define CAPRI_PIN_LCD_G_3		64
-#define CAPRI_PIN_LCD_G_4		65
-#define CAPRI_PIN_LCD_G_5		66
-#define CAPRI_PIN_LCD_G_6		67
-#define CAPRI_PIN_LCD_G_7		68
-#define CAPRI_PIN_LCD_HSYNC		69
-#define CAPRI_PIN_LCD_OE		70
-#define CAPRI_PIN_LCD_PCLK		71
-#define CAPRI_PIN_LCD_R_0		72
-#define CAPRI_PIN_LCD_R_1		73
-#define CAPRI_PIN_LCD_R_2		74
-#define CAPRI_PIN_LCD_R_3		75
-#define CAPRI_PIN_LCD_R_4		76
-#define CAPRI_PIN_LCD_R_5		77
-#define CAPRI_PIN_LCD_R_6		78
-#define CAPRI_PIN_LCD_R_7		79
-#define CAPRI_PIN_LCD_VSYNC		80
-#define CAPRI_PIN_MDMGPIO0		81
-#define CAPRI_PIN_MDMGPIO1		82
-#define CAPRI_PIN_MDMGPIO2		83
-#define CAPRI_PIN_MDMGPIO3		84
-#define CAPRI_PIN_MDMGPIO4		85
-#define CAPRI_PIN_MDMGPIO5		86
-#define CAPRI_PIN_MDMGPIO6		87
-#define CAPRI_PIN_MDMGPIO7		88
-#define CAPRI_PIN_MDMGPIO8		89
-#define CAPRI_PIN_MPHI_DATA_0		90
-#define CAPRI_PIN_MPHI_DATA_1		91
-#define CAPRI_PIN_MPHI_DATA_2		92
-#define CAPRI_PIN_MPHI_DATA_3		93
-#define CAPRI_PIN_MPHI_DATA_4		94
-#define CAPRI_PIN_MPHI_DATA_5		95
-#define CAPRI_PIN_MPHI_DATA_6		96
-#define CAPRI_PIN_MPHI_DATA_7		97
-#define CAPRI_PIN_MPHI_DATA_8		98
-#define CAPRI_PIN_MPHI_DATA_9		99
-#define CAPRI_PIN_MPHI_DATA_10		100
-#define CAPRI_PIN_MPHI_DATA_11		101
-#define CAPRI_PIN_MPHI_DATA_12		102
-#define CAPRI_PIN_MPHI_DATA_13		103
-#define CAPRI_PIN_MPHI_DATA_14		104
-#define CAPRI_PIN_MPHI_DATA_15		105
-#define CAPRI_PIN_MPHI_HA0		106
-#define CAPRI_PIN_MPHI_HAT0		107
-#define CAPRI_PIN_MPHI_HAT1		108
-#define CAPRI_PIN_MPHI_HCE0_N		109
-#define CAPRI_PIN_MPHI_HCE1_N		110
-#define CAPRI_PIN_MPHI_HRD_N		111
-#define CAPRI_PIN_MPHI_HWR_N		112
-#define CAPRI_PIN_MPHI_RUN0		113
-#define CAPRI_PIN_MPHI_RUN1		114
-#define CAPRI_PIN_MTX_SCAN_CLK		115
-#define CAPRI_PIN_MTX_SCAN_DATA		116
-#define CAPRI_PIN_NAND_AD_0		117
-#define CAPRI_PIN_NAND_AD_1		118
-#define CAPRI_PIN_NAND_AD_2		119
-#define CAPRI_PIN_NAND_AD_3		120
-#define CAPRI_PIN_NAND_AD_4		121
-#define CAPRI_PIN_NAND_AD_5		122
-#define CAPRI_PIN_NAND_AD_6		123
-#define CAPRI_PIN_NAND_AD_7		124
-#define CAPRI_PIN_NAND_ALE		125
-#define CAPRI_PIN_NAND_CEN_0		126
-#define CAPRI_PIN_NAND_CEN_1		127
-#define CAPRI_PIN_NAND_CLE		128
-#define CAPRI_PIN_NAND_OEN		129
-#define CAPRI_PIN_NAND_RDY_0		130
-#define CAPRI_PIN_NAND_RDY_1		131
-#define CAPRI_PIN_NAND_WEN		132
-#define CAPRI_PIN_NAND_WP		133
-#define CAPRI_PIN_PC1			134
-#define CAPRI_PIN_PC2			135
-#define CAPRI_PIN_PMU_INT		136
-#define CAPRI_PIN_PMU_SCL		137
-#define CAPRI_PIN_PMU_SDA		138
-#define CAPRI_PIN_RFST2G_MTSLOTEN3G	139
-#define CAPRI_PIN_RGMII_0_RX_CTL	140
-#define CAPRI_PIN_RGMII_0_RXC		141
-#define CAPRI_PIN_RGMII_0_RXD_0		142
-#define CAPRI_PIN_RGMII_0_RXD_1		143
-#define CAPRI_PIN_RGMII_0_RXD_2		144
-#define CAPRI_PIN_RGMII_0_RXD_3		145
-#define CAPRI_PIN_RGMII_0_TX_CTL	146
-#define CAPRI_PIN_RGMII_0_TXC		147
-#define CAPRI_PIN_RGMII_0_TXD_0		148
-#define CAPRI_PIN_RGMII_0_TXD_1		149
-#define CAPRI_PIN_RGMII_0_TXD_2		150
-#define CAPRI_PIN_RGMII_0_TXD_3		151
-#define CAPRI_PIN_RGMII_1_RX_CTL	152
-#define CAPRI_PIN_RGMII_1_RXC		153
-#define CAPRI_PIN_RGMII_1_RXD_0		154
-#define CAPRI_PIN_RGMII_1_RXD_1		155
-#define CAPRI_PIN_RGMII_1_RXD_2		156
-#define CAPRI_PIN_RGMII_1_RXD_3		157
-#define CAPRI_PIN_RGMII_1_TX_CTL	158
-#define CAPRI_PIN_RGMII_1_TXC		159
-#define CAPRI_PIN_RGMII_1_TXD_0		160
-#define CAPRI_PIN_RGMII_1_TXD_1		161
-#define CAPRI_PIN_RGMII_1_TXD_2		162
-#define CAPRI_PIN_RGMII_1_TXD_3		163
-#define CAPRI_PIN_RGMII_GPIO_0		164
-#define CAPRI_PIN_RGMII_GPIO_1		165
-#define CAPRI_PIN_RGMII_GPIO_2		166
-#define CAPRI_PIN_RGMII_GPIO_3		167
-#define CAPRI_PIN_RTXDATA2G_TXDATA3G1	168
-#define CAPRI_PIN_RTXEN2G_TXDATA3G2	169
-#define CAPRI_PIN_RXDATA3G0		170
-#define CAPRI_PIN_RXDATA3G1		171
-#define CAPRI_PIN_RXDATA3G2		172
-#define CAPRI_PIN_SDIO1_CLK		173
-#define CAPRI_PIN_SDIO1_CMD		174
-#define CAPRI_PIN_SDIO1_DATA_0		175
-#define CAPRI_PIN_SDIO1_DATA_1		176
-#define CAPRI_PIN_SDIO1_DATA_2		177
-#define CAPRI_PIN_SDIO1_DATA_3		178
-#define CAPRI_PIN_SDIO4_CLK		179
-#define CAPRI_PIN_SDIO4_CMD		180
-#define CAPRI_PIN_SDIO4_DATA_0		181
-#define CAPRI_PIN_SDIO4_DATA_1		182
-#define CAPRI_PIN_SDIO4_DATA_2		183
-#define CAPRI_PIN_SDIO4_DATA_3		184
-#define CAPRI_PIN_SIM_CLK		185
-#define CAPRI_PIN_SIM_DATA		186
-#define CAPRI_PIN_SIM_DET		187
-#define CAPRI_PIN_SIM_RESETN		188
-#define CAPRI_PIN_SIM2_CLK		189
-#define CAPRI_PIN_SIM2_DATA		190
-#define CAPRI_PIN_SIM2_DET		191
-#define CAPRI_PIN_SIM2_RESETN		192
-#define CAPRI_PIN_SRI_C			193
-#define CAPRI_PIN_SRI_D			194
-#define CAPRI_PIN_SRI_E			195
-#define CAPRI_PIN_SSP_EXTCLK		196
-#define CAPRI_PIN_SSP0_CLK		197
-#define CAPRI_PIN_SSP0_FS		198
-#define CAPRI_PIN_SSP0_RXD		199
-#define CAPRI_PIN_SSP0_TXD		200
-#define CAPRI_PIN_SSP2_CLK		201
-#define CAPRI_PIN_SSP2_FS_0		202
-#define CAPRI_PIN_SSP2_FS_1		203
-#define CAPRI_PIN_SSP2_FS_2		204
-#define CAPRI_PIN_SSP2_FS_3		205
-#define CAPRI_PIN_SSP2_RXD_0		206
-#define CAPRI_PIN_SSP2_RXD_1		207
-#define CAPRI_PIN_SSP2_TXD_0		208
-#define CAPRI_PIN_SSP2_TXD_1		209
-#define CAPRI_PIN_SSP3_CLK		210
-#define CAPRI_PIN_SSP3_FS		211
-#define CAPRI_PIN_SSP3_RXD		212
-#define CAPRI_PIN_SSP3_TXD		213
-#define CAPRI_PIN_SSP4_CLK		214
-#define CAPRI_PIN_SSP4_FS		215
-#define CAPRI_PIN_SSP4_RXD		216
-#define CAPRI_PIN_SSP4_TXD		217
-#define CAPRI_PIN_SSP5_CLK		218
-#define CAPRI_PIN_SSP5_FS		219
-#define CAPRI_PIN_SSP5_RXD		220
-#define CAPRI_PIN_SSP5_TXD		221
-#define CAPRI_PIN_SSP6_CLK		222
-#define CAPRI_PIN_SSP6_FS		223
-#define CAPRI_PIN_SSP6_RXD		224
-#define CAPRI_PIN_SSP6_TXD		225
-#define CAPRI_PIN_STAT_1		226
-#define CAPRI_PIN_STAT_2		227
-#define CAPRI_PIN_SYSCLKEN		228
-#define CAPRI_PIN_TRACECLK		229
-#define CAPRI_PIN_TRACEDT00		230
-#define CAPRI_PIN_TRACEDT01		231
-#define CAPRI_PIN_TRACEDT02		232
-#define CAPRI_PIN_TRACEDT03		233
-#define CAPRI_PIN_TRACEDT04		234
-#define CAPRI_PIN_TRACEDT05		235
-#define CAPRI_PIN_TRACEDT06		236
-#define CAPRI_PIN_TRACEDT07		237
-#define CAPRI_PIN_TRACEDT08		238
-#define CAPRI_PIN_TRACEDT09		239
-#define CAPRI_PIN_TRACEDT10		240
-#define CAPRI_PIN_TRACEDT11		241
-#define CAPRI_PIN_TRACEDT12		242
-#define CAPRI_PIN_TRACEDT13		243
-#define CAPRI_PIN_TRACEDT14		244
-#define CAPRI_PIN_TRACEDT15		245
-#define CAPRI_PIN_TXDATA3G0		246
-#define CAPRI_PIN_TXPWRIND		247
-#define CAPRI_PIN_UARTB1_UCTS		248
-#define CAPRI_PIN_UARTB1_URTS		249
-#define CAPRI_PIN_UARTB1_URXD		250
-#define CAPRI_PIN_UARTB1_UTXD		251
-#define CAPRI_PIN_UARTB2_URXD		252
-#define CAPRI_PIN_UARTB2_UTXD		253
-#define CAPRI_PIN_UARTB3_UCTS		254
-#define CAPRI_PIN_UARTB3_URTS		255
-#define CAPRI_PIN_UARTB3_URXD		256
-#define CAPRI_PIN_UARTB3_UTXD		257
-#define CAPRI_PIN_UARTB4_UCTS		258
-#define CAPRI_PIN_UARTB4_URTS		259
-#define CAPRI_PIN_UARTB4_URXD		260
-#define CAPRI_PIN_UARTB4_UTXD		261
-#define CAPRI_PIN_VC_CAM1_SCL		262
-#define CAPRI_PIN_VC_CAM1_SDA		263
-#define CAPRI_PIN_VC_CAM2_SCL		264
-#define CAPRI_PIN_VC_CAM2_SDA		265
-#define CAPRI_PIN_VC_CAM3_SCL		266
-#define CAPRI_PIN_VC_CAM3_SDA		267
-
-#define CAPRI_PIN_DESC(a, b, c) \
-	{ .number = a, .name = b, .drv_data = &c##_pin }
-
-/*
- * Pin description definition.  The order here must be the same as defined in
- * the PADCTRLREG block in the RDB, since the pin number is used as an index
- * into this array.
- */
-static const struct pinctrl_pin_desc capri_pinctrl_pins[] = {
-	CAPRI_PIN_DESC(CAPRI_PIN_ADCSYNC, "adcsync", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_BAT_RM, "bat_rm", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_BSC1_SCL, "bsc1_scl", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_BSC1_SDA, "bsc1_sda", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_BSC2_SCL, "bsc2_scl", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_BSC2_SDA, "bsc2_sda", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLASSGPWR, "classgpwr", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLK_CX8, "clk_cx8", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_0, "clkout_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_1, "clkout_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_2, "clkout_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_3, "clkout_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLKREQ_IN_0, "clkreq_in_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CLKREQ_IN_1, "clkreq_in_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CWS_SYS_REQ1, "cws_sys_req1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CWS_SYS_REQ2, "cws_sys_req2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_CWS_SYS_REQ3, "cws_sys_req3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC1_CLK, "digmic1_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC1_DQ, "digmic1_dq", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC2_CLK, "digmic2_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC2_DQ, "digmic2_dq", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPEN13, "gpen13", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPEN14, "gpen14", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPEN15, "gpen15", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO00, "gpio00", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO01, "gpio01", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO02, "gpio02", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO03, "gpio03", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO04, "gpio04", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO05, "gpio05", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO06, "gpio06", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO07, "gpio07", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO08, "gpio08", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO09, "gpio09", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO10, "gpio10", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO11, "gpio11", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO12, "gpio12", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO13, "gpio13", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPIO14, "gpio14", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPS_PABLANK, "gps_pablank", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_GPS_TMARK, "gps_tmark", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_HDMI_SCL, "hdmi_scl", hdmi),
-	CAPRI_PIN_DESC(CAPRI_PIN_HDMI_SDA, "hdmi_sda", hdmi),
-	CAPRI_PIN_DESC(CAPRI_PIN_IC_DM, "ic_dm", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_IC_DP, "ic_dp", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_0, "kp_col_ip_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_1, "kp_col_ip_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_2, "kp_col_ip_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_3, "kp_col_ip_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_0, "kp_row_op_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_1, "kp_row_op_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_2, "kp_row_op_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_3, "kp_row_op_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_0, "lcd_b_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_1, "lcd_b_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_2, "lcd_b_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_3, "lcd_b_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_4, "lcd_b_4", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_5, "lcd_b_5", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_6, "lcd_b_6", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_7, "lcd_b_7", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_0, "lcd_g_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_1, "lcd_g_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_2, "lcd_g_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_3, "lcd_g_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_4, "lcd_g_4", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_5, "lcd_g_5", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_6, "lcd_g_6", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_7, "lcd_g_7", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_HSYNC, "lcd_hsync", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_OE, "lcd_oe", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_PCLK, "lcd_pclk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_0, "lcd_r_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_1, "lcd_r_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_2, "lcd_r_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_3, "lcd_r_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_4, "lcd_r_4", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_5, "lcd_r_5", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_6, "lcd_r_6", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_7, "lcd_r_7", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_LCD_VSYNC, "lcd_vsync", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO0, "mdmgpio0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO1, "mdmgpio1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO2, "mdmgpio2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO3, "mdmgpio3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO4, "mdmgpio4", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO5, "mdmgpio5", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO6, "mdmgpio6", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO7, "mdmgpio7", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO8, "mdmgpio8", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_0, "mphi_data_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_1, "mphi_data_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_2, "mphi_data_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_3, "mphi_data_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_4, "mphi_data_4", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_5, "mphi_data_5", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_6, "mphi_data_6", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_7, "mphi_data_7", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_8, "mphi_data_8", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_9, "mphi_data_9", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_10, "mphi_data_10", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_11, "mphi_data_11", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_12, "mphi_data_12", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_13, "mphi_data_13", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_14, "mphi_data_14", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_15, "mphi_data_15", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HA0, "mphi_ha0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HAT0, "mphi_hat0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HAT1, "mphi_hat1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HCE0_N, "mphi_hce0_n", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HCE1_N, "mphi_hce1_n", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HRD_N, "mphi_hrd_n", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HWR_N, "mphi_hwr_n", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_RUN0, "mphi_run0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MPHI_RUN1, "mphi_run1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MTX_SCAN_CLK, "mtx_scan_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_MTX_SCAN_DATA, "mtx_scan_data", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_0, "nand_ad_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_1, "nand_ad_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_2, "nand_ad_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_3, "nand_ad_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_4, "nand_ad_4", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_5, "nand_ad_5", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_6, "nand_ad_6", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_7, "nand_ad_7", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_ALE, "nand_ale", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_CEN_0, "nand_cen_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_CEN_1, "nand_cen_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_CLE, "nand_cle", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_OEN, "nand_oen", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_RDY_0, "nand_rdy_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_RDY_1, "nand_rdy_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_WEN, "nand_wen", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_NAND_WP, "nand_wp", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_PC1, "pc1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_PC2, "pc2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_PMU_INT, "pmu_int", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_PMU_SCL, "pmu_scl", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_PMU_SDA, "pmu_sda", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_RFST2G_MTSLOTEN3G, "rfst2g_mtsloten3g", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RX_CTL, "rgmii_0_rx_ctl", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXC, "rgmii_0_rxc", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_0, "rgmii_0_rxd_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_1, "rgmii_0_rxd_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_2, "rgmii_0_rxd_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_3, "rgmii_0_rxd_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TX_CTL, "rgmii_0_tx_ctl", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXC, "rgmii_0_txc", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_0, "rgmii_0_txd_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_1, "rgmii_0_txd_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_2, "rgmii_0_txd_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_3, "rgmii_0_txd_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RX_CTL, "rgmii_1_rx_ctl", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXC, "rgmii_1_rxc", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_0, "rgmii_1_rxd_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_1, "rgmii_1_rxd_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_2, "rgmii_1_rxd_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_3, "rgmii_1_rxd_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TX_CTL, "rgmii_1_tx_ctl", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXC, "rgmii_1_txc", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_0, "rgmii_1_txd_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_1, "rgmii_1_txd_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_2, "rgmii_1_txd_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_3, "rgmii_1_txd_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_0, "rgmii_gpio_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_1, "rgmii_gpio_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_2, "rgmii_gpio_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_3, "rgmii_gpio_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RTXDATA2G_TXDATA3G1, "rtxdata2g_txdata3g1",
-		std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RTXEN2G_TXDATA3G2, "rtxen2g_txdata3g2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RXDATA3G0, "rxdata3g0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RXDATA3G1, "rxdata3g1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_RXDATA3G2, "rxdata3g2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_CLK, "sdio1_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_CMD, "sdio1_cmd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_0, "sdio1_data_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_1, "sdio1_data_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_2, "sdio1_data_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_3, "sdio1_data_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_CLK, "sdio4_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_CMD, "sdio4_cmd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_0, "sdio4_data_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_1, "sdio4_data_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_2, "sdio4_data_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_3, "sdio4_data_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM_CLK, "sim_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM_DATA, "sim_data", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM_DET, "sim_det", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM_RESETN, "sim_resetn", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM2_CLK, "sim2_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM2_DATA, "sim2_data", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM2_DET, "sim2_det", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SIM2_RESETN, "sim2_resetn", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SRI_C, "sri_c", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SRI_D, "sri_d", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SRI_E, "sri_e", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP_EXTCLK, "ssp_extclk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP0_CLK, "ssp0_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP0_FS, "ssp0_fs", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP0_RXD, "ssp0_rxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP0_TXD, "ssp0_txd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_CLK, "ssp2_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_0, "ssp2_fs_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_1, "ssp2_fs_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_2, "ssp2_fs_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_3, "ssp2_fs_3", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_RXD_0, "ssp2_rxd_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_RXD_1, "ssp2_rxd_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_TXD_0, "ssp2_txd_0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP2_TXD_1, "ssp2_txd_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP3_CLK, "ssp3_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP3_FS, "ssp3_fs", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP3_RXD, "ssp3_rxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP3_TXD, "ssp3_txd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP4_CLK, "ssp4_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP4_FS, "ssp4_fs", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP4_RXD, "ssp4_rxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP4_TXD, "ssp4_txd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP5_CLK, "ssp5_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP5_FS, "ssp5_fs", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP5_RXD, "ssp5_rxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP5_TXD, "ssp5_txd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP6_CLK, "ssp6_clk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP6_FS, "ssp6_fs", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP6_RXD, "ssp6_rxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SSP6_TXD, "ssp6_txd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_STAT_1, "stat_1", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_STAT_2, "stat_2", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_SYSCLKEN, "sysclken", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACECLK, "traceclk", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT00, "tracedt00", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT01, "tracedt01", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT02, "tracedt02", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT03, "tracedt03", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT04, "tracedt04", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT05, "tracedt05", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT06, "tracedt06", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT07, "tracedt07", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT08, "tracedt08", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT09, "tracedt09", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT10, "tracedt10", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT11, "tracedt11", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT12, "tracedt12", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT13, "tracedt13", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT14, "tracedt14", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT15, "tracedt15", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TXDATA3G0, "txdata3g0", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_TXPWRIND, "txpwrind", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_UCTS, "uartb1_ucts", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_URTS, "uartb1_urts", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_URXD, "uartb1_urxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_UTXD, "uartb1_utxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB2_URXD, "uartb2_urxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB2_UTXD, "uartb2_utxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_UCTS, "uartb3_ucts", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_URTS, "uartb3_urts", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_URXD, "uartb3_urxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_UTXD, "uartb3_utxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_UCTS, "uartb4_ucts", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_URTS, "uartb4_urts", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_URXD, "uartb4_urxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_UTXD, "uartb4_utxd", std),
-	CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM1_SCL, "vc_cam1_scl", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM1_SDA, "vc_cam1_sda", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM2_SCL, "vc_cam2_scl", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM2_SDA, "vc_cam2_sda", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM3_SCL, "vc_cam3_scl", i2c),
-	CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM3_SDA, "vc_cam3_sda", i2c),
-};
-
-static const char * const capri_alt_groups[] = {
-	"adcsync",
-	"bat_rm",
-	"bsc1_scl",
-	"bsc1_sda",
-	"bsc2_scl",
-	"bsc2_sda",
-	"classgpwr",
-	"clk_cx8",
-	"clkout_0",
-	"clkout_1",
-	"clkout_2",
-	"clkout_3",
-	"clkreq_in_0",
-	"clkreq_in_1",
-	"cws_sys_req1",
-	"cws_sys_req2",
-	"cws_sys_req3",
-	"digmic1_clk",
-	"digmic1_dq",
-	"digmic2_clk",
-	"digmic2_dq",
-	"gpen13",
-	"gpen14",
-	"gpen15",
-	"gpio00",
-	"gpio01",
-	"gpio02",
-	"gpio03",
-	"gpio04",
-	"gpio05",
-	"gpio06",
-	"gpio07",
-	"gpio08",
-	"gpio09",
-	"gpio10",
-	"gpio11",
-	"gpio12",
-	"gpio13",
-	"gpio14",
-	"gps_pablank",
-	"gps_tmark",
-	"hdmi_scl",
-	"hdmi_sda",
-	"ic_dm",
-	"ic_dp",
-	"kp_col_ip_0",
-	"kp_col_ip_1",
-	"kp_col_ip_2",
-	"kp_col_ip_3",
-	"kp_row_op_0",
-	"kp_row_op_1",
-	"kp_row_op_2",
-	"kp_row_op_3",
-	"lcd_b_0",
-	"lcd_b_1",
-	"lcd_b_2",
-	"lcd_b_3",
-	"lcd_b_4",
-	"lcd_b_5",
-	"lcd_b_6",
-	"lcd_b_7",
-	"lcd_g_0",
-	"lcd_g_1",
-	"lcd_g_2",
-	"lcd_g_3",
-	"lcd_g_4",
-	"lcd_g_5",
-	"lcd_g_6",
-	"lcd_g_7",
-	"lcd_hsync",
-	"lcd_oe",
-	"lcd_pclk",
-	"lcd_r_0",
-	"lcd_r_1",
-	"lcd_r_2",
-	"lcd_r_3",
-	"lcd_r_4",
-	"lcd_r_5",
-	"lcd_r_6",
-	"lcd_r_7",
-	"lcd_vsync",
-	"mdmgpio0",
-	"mdmgpio1",
-	"mdmgpio2",
-	"mdmgpio3",
-	"mdmgpio4",
-	"mdmgpio5",
-	"mdmgpio6",
-	"mdmgpio7",
-	"mdmgpio8",
-	"mphi_data_0",
-	"mphi_data_1",
-	"mphi_data_2",
-	"mphi_data_3",
-	"mphi_data_4",
-	"mphi_data_5",
-	"mphi_data_6",
-	"mphi_data_7",
-	"mphi_data_8",
-	"mphi_data_9",
-	"mphi_data_10",
-	"mphi_data_11",
-	"mphi_data_12",
-	"mphi_data_13",
-	"mphi_data_14",
-	"mphi_data_15",
-	"mphi_ha0",
-	"mphi_hat0",
-	"mphi_hat1",
-	"mphi_hce0_n",
-	"mphi_hce1_n",
-	"mphi_hrd_n",
-	"mphi_hwr_n",
-	"mphi_run0",
-	"mphi_run1",
-	"mtx_scan_clk",
-	"mtx_scan_data",
-	"nand_ad_0",
-	"nand_ad_1",
-	"nand_ad_2",
-	"nand_ad_3",
-	"nand_ad_4",
-	"nand_ad_5",
-	"nand_ad_6",
-	"nand_ad_7",
-	"nand_ale",
-	"nand_cen_0",
-	"nand_cen_1",
-	"nand_cle",
-	"nand_oen",
-	"nand_rdy_0",
-	"nand_rdy_1",
-	"nand_wen",
-	"nand_wp",
-	"pc1",
-	"pc2",
-	"pmu_int",
-	"pmu_scl",
-	"pmu_sda",
-	"rfst2g_mtsloten3g",
-	"rgmii_0_rx_ctl",
-	"rgmii_0_rxc",
-	"rgmii_0_rxd_0",
-	"rgmii_0_rxd_1",
-	"rgmii_0_rxd_2",
-	"rgmii_0_rxd_3",
-	"rgmii_0_tx_ctl",
-	"rgmii_0_txc",
-	"rgmii_0_txd_0",
-	"rgmii_0_txd_1",
-	"rgmii_0_txd_2",
-	"rgmii_0_txd_3",
-	"rgmii_1_rx_ctl",
-	"rgmii_1_rxc",
-	"rgmii_1_rxd_0",
-	"rgmii_1_rxd_1",
-	"rgmii_1_rxd_2",
-	"rgmii_1_rxd_3",
-	"rgmii_1_tx_ctl",
-	"rgmii_1_txc",
-	"rgmii_1_txd_0",
-	"rgmii_1_txd_1",
-	"rgmii_1_txd_2",
-	"rgmii_1_txd_3",
-	"rgmii_gpio_0",
-	"rgmii_gpio_1",
-	"rgmii_gpio_2",
-	"rgmii_gpio_3",
-	"rtxdata2g_txdata3g1",
-	"rtxen2g_txdata3g2",
-	"rxdata3g0",
-	"rxdata3g1",
-	"rxdata3g2",
-	"sdio1_clk",
-	"sdio1_cmd",
-	"sdio1_data_0",
-	"sdio1_data_1",
-	"sdio1_data_2",
-	"sdio1_data_3",
-	"sdio4_clk",
-	"sdio4_cmd",
-	"sdio4_data_0",
-	"sdio4_data_1",
-	"sdio4_data_2",
-	"sdio4_data_3",
-	"sim_clk",
-	"sim_data",
-	"sim_det",
-	"sim_resetn",
-	"sim2_clk",
-	"sim2_data",
-	"sim2_det",
-	"sim2_resetn",
-	"sri_c",
-	"sri_d",
-	"sri_e",
-	"ssp_extclk",
-	"ssp0_clk",
-	"ssp0_fs",
-	"ssp0_rxd",
-	"ssp0_txd",
-	"ssp2_clk",
-	"ssp2_fs_0",
-	"ssp2_fs_1",
-	"ssp2_fs_2",
-	"ssp2_fs_3",
-	"ssp2_rxd_0",
-	"ssp2_rxd_1",
-	"ssp2_txd_0",
-	"ssp2_txd_1",
-	"ssp3_clk",
-	"ssp3_fs",
-	"ssp3_rxd",
-	"ssp3_txd",
-	"ssp4_clk",
-	"ssp4_fs",
-	"ssp4_rxd",
-	"ssp4_txd",
-	"ssp5_clk",
-	"ssp5_fs",
-	"ssp5_rxd",
-	"ssp5_txd",
-	"ssp6_clk",
-	"ssp6_fs",
-	"ssp6_rxd",
-	"ssp6_txd",
-	"stat_1",
-	"stat_2",
-	"sysclken",
-	"traceclk",
-	"tracedt00",
-	"tracedt01",
-	"tracedt02",
-	"tracedt03",
-	"tracedt04",
-	"tracedt05",
-	"tracedt06",
-	"tracedt07",
-	"tracedt08",
-	"tracedt09",
-	"tracedt10",
-	"tracedt11",
-	"tracedt12",
-	"tracedt13",
-	"tracedt14",
-	"tracedt15",
-	"txdata3g0",
-	"txpwrind",
-	"uartb1_ucts",
-	"uartb1_urts",
-	"uartb1_urxd",
-	"uartb1_utxd",
-	"uartb2_urxd",
-	"uartb2_utxd",
-	"uartb3_ucts",
-	"uartb3_urts",
-	"uartb3_urxd",
-	"uartb3_utxd",
-	"uartb4_ucts",
-	"uartb4_urts",
-	"uartb4_urxd",
-	"uartb4_utxd",
-	"vc_cam1_scl",
-	"vc_cam1_sda",
-	"vc_cam2_scl",
-	"vc_cam2_sda",
-	"vc_cam3_scl",
-	"vc_cam3_sda",
-};
-
-/* Every pin can implement all ALT1-ALT4 functions */
-#define CAPRI_PIN_FUNCTION(fcn_name)			\
-{							\
-	.name = #fcn_name,				\
-	.groups = capri_alt_groups,			\
-	.ngroups = ARRAY_SIZE(capri_alt_groups),	\
-}
-
-static const struct capri_pin_function capri_functions[] = {
-	CAPRI_PIN_FUNCTION(alt1),
-	CAPRI_PIN_FUNCTION(alt2),
-	CAPRI_PIN_FUNCTION(alt3),
-	CAPRI_PIN_FUNCTION(alt4),
-};
-
-static struct capri_pinctrl_data capri_pinctrl = {
-	.pins = capri_pinctrl_pins,
-	.npins = ARRAY_SIZE(capri_pinctrl_pins),
-	.functions = capri_functions,
-	.nfunctions = ARRAY_SIZE(capri_functions),
-};
-
-static inline enum capri_pin_type pin_type_get(struct pinctrl_dev *pctldev,
-					       unsigned pin)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-	if (pin >= pdata->npins)
-		return CAPRI_PIN_TYPE_UNKNOWN;
-
-	return *(enum capri_pin_type *)(pdata->pins[pin].drv_data);
-}
-
-#define CAPRI_PIN_SHIFT(type, param) \
-	(CAPRI_ ## type ## _PIN_REG_ ## param ## _SHIFT)
-
-#define CAPRI_PIN_MASK(type, param) \
-	(CAPRI_ ## type ## _PIN_REG_ ## param ## _MASK)
-
-/*
- * This helper function is used to build up the value and mask used to write to
- * a pin register, but does not actually write to the register.
- */
-static inline void capri_pin_update(u32 *reg_val, u32 *reg_mask, u32 param_val,
-				    u32 param_shift, u32 param_mask)
-{
-	*reg_val &= ~param_mask;
-	*reg_val |= (param_val << param_shift) & param_mask;
-	*reg_mask |= param_mask;
-}
-
-static struct regmap_config capri_pinctrl_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.max_register = CAPRI_PIN_VC_CAM3_SDA,
-};
-
-static int capri_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-	return pdata->npins;
-}
-
-static const char *capri_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
-						unsigned group)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-	return pdata->pins[group].name;
-}
-
-static int capri_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
-					unsigned group,
-					const unsigned **pins,
-					unsigned *num_pins)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-	*pins = &pdata->pins[group].number;
-	*num_pins = 1;
-
-	return 0;
-}
-
-static void capri_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
-				       struct seq_file *s,
-				       unsigned offset)
-{
-	seq_printf(s, " %s", dev_name(pctldev->dev));
-}
-
-static struct pinctrl_ops capri_pinctrl_ops = {
-	.get_groups_count = capri_pinctrl_get_groups_count,
-	.get_group_name = capri_pinctrl_get_group_name,
-	.get_group_pins = capri_pinctrl_get_group_pins,
-	.pin_dbg_show = capri_pinctrl_pin_dbg_show,
-	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
-};
-
-static int capri_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-	return pdata->nfunctions;
-}
-
-static const char *capri_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
-					      unsigned function)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-	return pdata->functions[function].name;
-}
-
-static int capri_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
-					unsigned function,
-					const char * const **groups,
-					unsigned * const num_groups)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-	*groups = pdata->functions[function].groups;
-	*num_groups = pdata->functions[function].ngroups;
-
-	return 0;
-}
-
-static int capri_pinmux_enable(struct pinctrl_dev *pctldev,
-			       unsigned function,
-			       unsigned group)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-	const struct capri_pin_function *f = &pdata->functions[function];
-	u32 offset = 4 * pdata->pins[group].number;
-	int rc = 0;
-
-	dev_dbg(pctldev->dev,
-		"%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
-		__func__, f->name, function, pdata->pins[group].name,
-		pdata->pins[group].number, offset);
-
-	rc = regmap_update_bits(pdata->regmap, offset, CAPRI_PIN_REG_F_SEL_MASK,
-			function << CAPRI_PIN_REG_F_SEL_SHIFT);
-	if (rc)
-		dev_err(pctldev->dev,
-			"Error updating register for pin %s (%d).\n",
-			pdata->pins[group].name, pdata->pins[group].number);
-
-	return rc;
-}
-
-static struct pinmux_ops capri_pinctrl_pinmux_ops = {
-	.get_functions_count = capri_pinctrl_get_fcns_count,
-	.get_function_name = capri_pinctrl_get_fcn_name,
-	.get_function_groups = capri_pinctrl_get_fcn_groups,
-	.enable = capri_pinmux_enable,
-};
-
-static int capri_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
-					unsigned pin,
-					unsigned long *config)
-{
-	return -ENOTSUPP;
-}
-
-
-/* Goes through the configs and update register val/mask */
-static int capri_std_pin_update(struct pinctrl_dev *pctldev,
-				unsigned pin,
-				unsigned long *configs,
-				unsigned num_configs,
-				u32 *val,
-				u32 *mask)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-	int i;
-	enum pin_config_param param;
-	u16 arg;
-
-	for (i = 0; i < num_configs; i++) {
-		param = pinconf_to_config_param(configs[i]);
-		arg = pinconf_to_config_argument(configs[i]);
-
-		switch (param) {
-		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
-			arg = (arg >= 1 ? 1 : 0);
-			capri_pin_update(val, mask, arg,
-					CAPRI_PIN_SHIFT(STD, HYST),
-					CAPRI_PIN_MASK(STD, HYST));
-			break;
-		/*
-		 * The pin bias can only be one of pull-up, pull-down, or
-		 * disable.  The user does not need to specify a value for the
-		 * property, and the default value from pinconf-generic is
-		 * ignored.
-		 */
-		case PIN_CONFIG_BIAS_DISABLE:
-			capri_pin_update(val, mask, 0,
-					CAPRI_PIN_SHIFT(STD, PULL_UP),
-					CAPRI_PIN_MASK(STD, PULL_UP));
-			capri_pin_update(val, mask, 0,
-					CAPRI_PIN_SHIFT(STD, PULL_DN),
-					CAPRI_PIN_MASK(STD, PULL_DN));
-			break;
-
-		case PIN_CONFIG_BIAS_PULL_UP:
-			capri_pin_update(val, mask, 1,
-					CAPRI_PIN_SHIFT(STD, PULL_UP),
-					CAPRI_PIN_MASK(STD, PULL_UP));
-			capri_pin_update(val, mask, 0,
-					CAPRI_PIN_SHIFT(STD, PULL_DN),
-					CAPRI_PIN_MASK(STD, PULL_DN));
-			break;
-
-		case PIN_CONFIG_BIAS_PULL_DOWN:
-			capri_pin_update(val, mask, 0,
-					CAPRI_PIN_SHIFT(STD, PULL_UP),
-					CAPRI_PIN_MASK(STD, PULL_UP));
-			capri_pin_update(val, mask, 1,
-					CAPRI_PIN_SHIFT(STD, PULL_DN),
-					CAPRI_PIN_MASK(STD, PULL_DN));
-			break;
-
-		case PIN_CONFIG_SLEW_RATE:
-			arg = (arg >= 1 ? 1 : 0);
-			capri_pin_update(val, mask, arg,
-					CAPRI_PIN_SHIFT(STD, SLEW),
-					CAPRI_PIN_MASK(STD, SLEW));
-			break;
-
-		case PIN_CONFIG_INPUT_ENABLE:
-			/* inversed since register is for input _disable_ */
-			arg = (arg >= 1 ? 0 : 1);
-			capri_pin_update(val, mask, arg,
-					CAPRI_PIN_SHIFT(STD, INPUT_DIS),
-					CAPRI_PIN_MASK(STD, INPUT_DIS));
-			break;
-
-		case PIN_CONFIG_DRIVE_STRENGTH:
-			/* Valid range is 2-16 mA, even numbers only */
-			if ((arg < 2) || (arg > 16) || (arg % 2)) {
-				dev_err(pctldev->dev,
-					"Invalid Drive Strength value (%d) for "
-					"pin %s (%d). Valid values are "
-					"(2..16) mA, even numbers only.\n",
-					arg, pdata->pins[pin].name, pin);
-				return -EINVAL;
-			}
-			capri_pin_update(val, mask, (arg/2)-1,
-					CAPRI_PIN_SHIFT(STD, DRV_STR),
-					CAPRI_PIN_MASK(STD, DRV_STR));
-			break;
-
-		default:
-			dev_err(pctldev->dev,
-				"Unrecognized pin config %d for pin %s (%d).\n",
-				param, pdata->pins[pin].name, pin);
-			return -EINVAL;
-
-		} /* switch config */
-	} /* for each config */
-
-	return 0;
-}
-
-/*
- * The pull-up strength for an I2C pin is represented by bits 4-6 in the
- * register with the following mapping:
- *   0b000: No pull-up
- *   0b001: 1200 Ohm
- *   0b010: 1800 Ohm
- *   0b011: 720 Ohm
- *   0b100: 2700 Ohm
- *   0b101: 831 Ohm
- *   0b110: 1080 Ohm
- *   0b111: 568 Ohm
- * This array maps pull-up strength in Ohms to register values (1+index).
- */
-static const u16 capri_pullup_map[] = {1200, 1800, 720, 2700, 831, 1080, 568};
-
-/* Goes through the configs and update register val/mask */
-static int capri_i2c_pin_update(struct pinctrl_dev *pctldev,
-				unsigned pin,
-				unsigned long *configs,
-				unsigned num_configs,
-				u32 *val,
-				u32 *mask)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-	int i, j;
-	enum pin_config_param param;
-	u16 arg;
-
-	for (i = 0; i < num_configs; i++) {
-		param = pinconf_to_config_param(configs[i]);
-		arg = pinconf_to_config_argument(configs[i]);
-
-		switch (param) {
-		case PIN_CONFIG_BIAS_PULL_UP:
-			for (j = 0; j < ARRAY_SIZE(capri_pullup_map); j++)
-				if (capri_pullup_map[j] == arg)
-					break;
-
-			if (j == ARRAY_SIZE(capri_pullup_map)) {
-				dev_err(pctldev->dev,
-					"Invalid pull-up value (%d) for pin %s "
-					"(%d). Valid values are 568, 720, 831, "
-					"1080, 1200, 1800, 2700 Ohms.\n",
-					arg, pdata->pins[pin].name, pin);
-				return -EINVAL;
-			}
-
-			capri_pin_update(val, mask, j+1,
-					CAPRI_PIN_SHIFT(I2C, PULL_UP_STR),
-					CAPRI_PIN_MASK(I2C, PULL_UP_STR));
-			break;
-
-		case PIN_CONFIG_BIAS_DISABLE:
-			capri_pin_update(val, mask, 0,
-					CAPRI_PIN_SHIFT(I2C, PULL_UP_STR),
-					CAPRI_PIN_MASK(I2C, PULL_UP_STR));
-			break;
-
-		case PIN_CONFIG_SLEW_RATE:
-			arg = (arg >= 1 ? 1 : 0);
-			capri_pin_update(val, mask, arg,
-					CAPRI_PIN_SHIFT(I2C, SLEW),
-					CAPRI_PIN_MASK(I2C, SLEW));
-			break;
-
-		case PIN_CONFIG_INPUT_ENABLE:
-			/* inversed since register is for input _disable_ */
-			arg = (arg >= 1 ? 0 : 1);
-			capri_pin_update(val, mask, arg,
-					CAPRI_PIN_SHIFT(I2C, INPUT_DIS),
-					CAPRI_PIN_MASK(I2C, INPUT_DIS));
-			break;
-
-		default:
-			dev_err(pctldev->dev,
-				"Unrecognized pin config %d for pin %s (%d).\n",
-				param, pdata->pins[pin].name, pin);
-			return -EINVAL;
-
-		} /* switch config */
-	} /* for each config */
-
-	return 0;
-}
-
-/* Goes through the configs and update register val/mask */
-static int capri_hdmi_pin_update(struct pinctrl_dev *pctldev,
-				 unsigned pin,
-				 unsigned long *configs,
-				 unsigned num_configs,
-				 u32 *val,
-				 u32 *mask)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-	int i;
-	enum pin_config_param param;
-	u16 arg;
-
-	for (i = 0; i < num_configs; i++) {
-		param = pinconf_to_config_param(configs[i]);
-		arg = pinconf_to_config_argument(configs[i]);
-
-		switch (param) {
-		case PIN_CONFIG_SLEW_RATE:
-			arg = (arg >= 1 ? 1 : 0);
-			capri_pin_update(val, mask, arg,
-					CAPRI_PIN_SHIFT(HDMI, MODE),
-					CAPRI_PIN_MASK(HDMI, MODE));
-			break;
-
-		case PIN_CONFIG_INPUT_ENABLE:
-			/* inversed since register is for input _disable_ */
-			arg = (arg >= 1 ? 0 : 1);
-			capri_pin_update(val, mask, arg,
-					CAPRI_PIN_SHIFT(HDMI, INPUT_DIS),
-					CAPRI_PIN_MASK(HDMI, INPUT_DIS));
-			break;
-
-		default:
-			dev_err(pctldev->dev,
-				"Unrecognized pin config %d for pin %s (%d).\n",
-				param, pdata->pins[pin].name, pin);
-			return -EINVAL;
-
-		} /* switch config */
-	} /* for each config */
-
-	return 0;
-}
-
-static int capri_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
-					unsigned pin,
-					unsigned long *configs,
-					unsigned num_configs)
-{
-	struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-	enum capri_pin_type pin_type;
-	u32 offset = 4 * pin;
-	u32 cfg_val, cfg_mask;
-	int rc;
-
-	cfg_val = 0;
-	cfg_mask = 0;
-	pin_type = pin_type_get(pctldev, pin);
-
-	/* Different pins have different configuration options */
-	switch (pin_type) {
-	case CAPRI_PIN_TYPE_STD:
-		rc = capri_std_pin_update(pctldev, pin, configs, num_configs,
-			&cfg_val, &cfg_mask);
-		break;
-
-	case CAPRI_PIN_TYPE_I2C:
-		rc = capri_i2c_pin_update(pctldev, pin, configs, num_configs,
-			&cfg_val, &cfg_mask);
-		break;
-
-	case CAPRI_PIN_TYPE_HDMI:
-		rc = capri_hdmi_pin_update(pctldev, pin, configs, num_configs,
-			&cfg_val, &cfg_mask);
-		break;
-
-	default:
-		dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
-			pdata->pins[pin].name, pin);
-		return -EINVAL;
-
-	} /* switch pin type */
-
-	if (rc)
-		return rc;
-
-	dev_dbg(pctldev->dev,
-		"%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
-		__func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
-
-	rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
-	if (rc) {
-		dev_err(pctldev->dev,
-			"Error updating register for pin %s (%d).\n",
-			pdata->pins[pin].name, pin);
-		return rc;
-	}
-
-	return 0;
-}
-
-static struct pinconf_ops capri_pinctrl_pinconf_ops = {
-	.pin_config_get = capri_pinctrl_pin_config_get,
-	.pin_config_set = capri_pinctrl_pin_config_set,
-};
-
-static struct pinctrl_desc capri_pinctrl_desc = {
-	/* name, pins, npins members initialized in probe function */
-	.pctlops = &capri_pinctrl_ops,
-	.pmxops = &capri_pinctrl_pinmux_ops,
-	.confops = &capri_pinctrl_pinconf_ops,
-	.owner = THIS_MODULE,
-};
-
-int __init capri_pinctrl_probe(struct platform_device *pdev)
-{
-	struct capri_pinctrl_data *pdata = &capri_pinctrl;
-	struct resource *res;
-	struct pinctrl_dev *pctl;
-
-	/* So far We can assume there is only 1 bank of registers */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "Missing MEM resource\n");
-		return -ENODEV;
-	}
-
-	pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(pdata->reg_base)) {
-		dev_err(&pdev->dev, "Failed to ioremap MEM resource\n");
-		return -ENODEV;
-	}
-
-	/* Initialize the dynamic part of pinctrl_desc */
-	pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
-		&capri_pinctrl_regmap_config);
-	if (IS_ERR(pdata->regmap)) {
-		dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
-		return -ENODEV;
-	}
-
-	capri_pinctrl_desc.name = dev_name(&pdev->dev);
-	capri_pinctrl_desc.pins = capri_pinctrl.pins;
-	capri_pinctrl_desc.npins = capri_pinctrl.npins;
-
-	pctl = pinctrl_register(&capri_pinctrl_desc,
-				&pdev->dev,
-				pdata);
-	if (!pctl) {
-		dev_err(&pdev->dev, "Failed to register pinctrl\n");
-		return -ENODEV;
-	}
-
-	platform_set_drvdata(pdev, pdata);
-
-	return 0;
-}
-
-static struct of_device_id capri_pinctrl_of_match[] = {
-	{ .compatible = "brcm,bcm11351-pinctrl", },
-	{ },
-};
-
-static struct platform_driver capri_pinctrl_driver = {
-	.driver = {
-		.name = "bcm-capri-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = capri_pinctrl_of_match,
-	},
-};
-
-module_platform_driver_probe(capri_pinctrl_driver, capri_pinctrl_probe);
-
-MODULE_AUTHOR("Sherman Yin <syin@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom Capri pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h
index 6d07f0238532..c7cfad5527d7 100644
--- a/drivers/pinctrl/pinctrl-lantiq.h
+++ b/drivers/pinctrl/pinctrl-lantiq.h
@@ -10,6 +10,7 @@
  */
 
 #ifndef __PINCTRL_LANTIQ_H
+#define __PINCTRL_LANTIQ_H
 
 #include <linux/clkdev.h>
 #include <linux/pinctrl/pinctrl.h>
diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c
index 38d579b47f31..5fa9341cc589 100644
--- a/drivers/pinctrl/pinctrl-msm.c
+++ b/drivers/pinctrl/pinctrl-msm.c
@@ -145,12 +145,12 @@ static int msm_pinmux_enable(struct pinctrl_dev *pctldev,
 	if (WARN_ON(g->mux_bit < 0))
 		return -EINVAL;
 
-	for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
+	for (i = 0; i < g->nfuncs; i++) {
 		if (g->funcs[i] == function)
 			break;
 	}
 
-	if (WARN_ON(i == ARRAY_SIZE(g->funcs)))
+	if (WARN_ON(i == g->nfuncs))
 		return -EINVAL;
 
 	spin_lock_irqsave(&pctrl->lock, flags);
@@ -665,7 +665,10 @@ static void msm_gpio_irq_ack(struct irq_data *d)
 	spin_lock_irqsave(&pctrl->lock, flags);
 
 	val = readl(pctrl->regs + g->intr_status_reg);
-	val &= ~BIT(g->intr_status_bit);
+	if (g->intr_ack_high)
+		val |= BIT(g->intr_status_bit);
+	else
+		val &= ~BIT(g->intr_status_bit);
 	writel(val, pctrl->regs + g->intr_status_reg);
 
 	if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
@@ -744,6 +747,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 			break;
 		case IRQ_TYPE_EDGE_BOTH:
 			val |= BIT(g->intr_detection_bit);
+			val |= BIT(g->intr_polarity_bit);
 			break;
 		case IRQ_TYPE_LEVEL_LOW:
 			break;
diff --git a/drivers/pinctrl/pinctrl-msm.h b/drivers/pinctrl/pinctrl-msm.h
index 8fbe9fb19f36..7b2a227a590a 100644
--- a/drivers/pinctrl/pinctrl-msm.h
+++ b/drivers/pinctrl/pinctrl-msm.h
@@ -65,7 +65,8 @@ struct msm_pingroup {
 	const unsigned *pins;
 	unsigned npins;
 
-	unsigned funcs[8];
+	unsigned *funcs;
+	unsigned nfuncs;
 
 	s16 ctl_reg;
 	s16 io_reg;
@@ -84,6 +85,7 @@ struct msm_pingroup {
 
 	unsigned intr_enable_bit:5;
 	unsigned intr_status_bit:5;
+	unsigned intr_ack_high:1;
 
 	unsigned intr_target_bit:5;
 	unsigned intr_raw_status_bit:5;
diff --git a/drivers/pinctrl/pinctrl-msm8x74.c b/drivers/pinctrl/pinctrl-msm8x74.c
index dde5529807aa..57766d56e257 100644
--- a/drivers/pinctrl/pinctrl-msm8x74.c
+++ b/drivers/pinctrl/pinctrl-msm8x74.c
@@ -341,7 +341,7 @@ static const unsigned int sdc2_data_pins[] = { 151 };
 		.name = "gpio" #id,			\
 		.pins = gpio##id##_pins,		\
 		.npins = ARRAY_SIZE(gpio##id##_pins),	\
-		.funcs = {				\
+		.funcs = (int[]){			\
 			MSM_MUX_NA, /* gpio mode */	\
 			MSM_MUX_##f1,			\
 			MSM_MUX_##f2,			\
@@ -351,6 +351,7 @@ static const unsigned int sdc2_data_pins[] = { 151 };
 			MSM_MUX_##f6,			\
 			MSM_MUX_##f7			\
 		},					\
+		.nfuncs = 8,				\
 		.ctl_reg = 0x1000 + 0x10 * id,		\
 		.io_reg = 0x1004 + 0x10 * id,		\
 		.intr_cfg_reg = 0x1008 + 0x10 * id,	\
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 208341fd57d2..8f6f16ef73f3 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -877,7 +877,6 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
 	u32 status;
 
-	pr_err("PLONK IRQ %d\n", irq);
 	clk_enable(nmk_chip->clk);
 	status = readl(nmk_chip->addr + NMK_GPIO_IS);
 	clk_disable(nmk_chip->clk);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 46dddc159286..96c60d230c13 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -342,7 +342,7 @@ static const struct pinctrl_ops rockchip_pctrl_ops = {
  * @pin: pin to change
  * @mux: new mux function to set
  */
-static void rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 	void __iomem *reg = info->reg_base + info->ctrl->mux_offset;
@@ -350,6 +350,20 @@ static void rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
 	u8 bit;
 	u32 data;
 
+	/*
+	 * The first 16 pins of rk3188_bank0 are always gpios and do not have
+	 * a mux register at all.
+	 */
+	if (bank->bank_type == RK3188_BANK0 && pin < 16) {
+		if (mux != RK_FUNC_GPIO) {
+			dev_err(info->dev,
+				"pin %d only supports a gpio mux\n", pin);
+			return -ENOTSUPP;
+		} else {
+			return 0;
+		}
+	}
+
 	dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n",
 						bank->bank_num, pin, mux);
 
@@ -365,6 +379,8 @@ static void rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
 	writel(data, reg);
 
 	spin_unlock_irqrestore(&bank->slock, flags);
+
+	return 0;
 }
 
 #define RK2928_PULL_OFFSET		0x118
@@ -560,7 +576,7 @@ static int rockchip_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
 	const unsigned int *pins = info->groups[group].pins;
 	const struct rockchip_pin_config *data = info->groups[group].data;
 	struct rockchip_pin_bank *bank;
-	int cnt;
+	int cnt, ret = 0;
 
 	dev_dbg(info->dev, "enable function %s group %s\n",
 		info->functions[selector].name, info->groups[group].name);
@@ -571,8 +587,18 @@ static int rockchip_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
 	 */
 	for (cnt = 0; cnt < info->groups[group].npins; cnt++) {
 		bank = pin_to_bank(info, pins[cnt]);
-		rockchip_set_mux(bank, pins[cnt] - bank->pin_base,
-				 data[cnt].func);
+		ret = rockchip_set_mux(bank, pins[cnt] - bank->pin_base,
+				       data[cnt].func);
+		if (ret)
+			break;
+	}
+
+	if (ret) {
+		/* revert the already done pin settings */
+		for (cnt--; cnt >= 0; cnt--)
+			rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0);
+
+		return ret;
 	}
 
 	return 0;
@@ -607,7 +633,7 @@ static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
 	struct rockchip_pin_bank *bank;
 	struct gpio_chip *chip;
-	int pin;
+	int pin, ret;
 	u32 data;
 
 	chip = range->gc;
@@ -617,7 +643,9 @@ static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
 	dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n",
 		 offset, range->name, pin, input ? "input" : "output");
 
-	rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
+	ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
+	if (ret < 0)
+		return ret;
 
 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
 	/* set bit to 1 for output, 0 for input */
@@ -1144,9 +1172,13 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
 	u32 polarity;
 	u32 level;
 	u32 data;
+	int ret;
 
 	/* make sure the pin is configured as gpio input */
-	rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
+	ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
+	if (ret < 0)
+		return ret;
+
 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
 	data &= ~mask;
 	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
@@ -1534,7 +1566,7 @@ static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
 		.nr_banks		= ARRAY_SIZE(rk3188_pin_banks),
 		.label			= "RK3188-GPIO",
 		.type			= RK3188,
-		.mux_offset		= 0x68,
+		.mux_offset		= 0x60,
 		.pull_calc_reg		= rk3188_calc_pull_reg_and_bit,
 };
 
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index bd725b0a4341..1bd6363bc95e 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -13,10 +13,6 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdesc.h>
-#include <linux/irqdomain.h>
-#include <linux/irqchip/chained_irq.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_gpio.h>
@@ -242,13 +238,13 @@ struct st_pio_control {
 };
 
 struct st_pctl_data {
-	enum st_retime_style rt_style;
-	unsigned int	*input_delays;
-	int		ninput_delays;
-	unsigned int	*output_delays;
-	int		noutput_delays;
+	const enum st_retime_style	rt_style;
+	const unsigned int		*input_delays;
+	const int			ninput_delays;
+	const unsigned int		*output_delays;
+	const int			noutput_delays;
 	/* register offset information */
-	int alt, oe, pu, od, rt;
+	const int alt, oe, pu, od, rt;
 };
 
 struct st_pinconf {
@@ -321,7 +317,6 @@ struct st_gpio_bank {
 	struct pinctrl_gpio_range	range;
 	void __iomem			*base;
 	struct st_pio_control		pc;
-	struct	irq_domain		*domain;
 	unsigned long			irq_edge_conf;
 	spinlock_t                      lock;
 };
@@ -342,15 +337,15 @@ struct st_pinctrl {
 
 /* SOC specific data */
 /* STiH415 data */
-static unsigned int stih415_input_delays[] = {0, 500, 1000, 1500};
-static unsigned int stih415_output_delays[] = {0, 1000, 2000, 3000};
+static const unsigned int stih415_input_delays[] = {0, 500, 1000, 1500};
+static const unsigned int stih415_output_delays[] = {0, 1000, 2000, 3000};
 
 #define STIH415_PCTRL_COMMON_DATA				\
 	.rt_style	= st_retime_style_packed,		\
 	.input_delays	= stih415_input_delays,			\
-	.ninput_delays	= 4,					\
+	.ninput_delays	= ARRAY_SIZE(stih415_input_delays),	\
 	.output_delays = stih415_output_delays,			\
-	.noutput_delays = 4
+	.noutput_delays = ARRAY_SIZE(stih415_output_delays)
 
 static const struct st_pctl_data  stih415_sbc_data = {
 	STIH415_PCTRL_COMMON_DATA,
@@ -378,8 +373,8 @@ static const struct st_pctl_data  stih415_right_data = {
 };
 
 /* STiH416 data */
-static unsigned int stih416_delays[] = {0, 300, 500, 750, 1000, 1250, 1500,
-			1750, 2000, 2250, 2500, 2750, 3000, 3250 };
+static const unsigned int stih416_delays[] = {0, 300, 500, 750, 1000, 1250,
+			1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250 };
 
 static const struct st_pctl_data  stih416_data = {
 	.rt_style	= st_retime_style_dedicated,
@@ -468,7 +463,7 @@ static void st_pctl_set_function(struct st_pio_control *pc,
 static unsigned long st_pinconf_delay_to_bit(unsigned int delay,
 	const struct st_pctl_data *data, unsigned long config)
 {
-	unsigned int *delay_times;
+	const unsigned int *delay_times;
 	int num_delay_times, i, closest_index = -1;
 	unsigned int closest_divergence = UINT_MAX;
 
@@ -501,7 +496,7 @@ static unsigned long st_pinconf_delay_to_bit(unsigned int delay,
 static unsigned long st_pinconf_bit_to_delay(unsigned int index,
 	const struct st_pctl_data *data, unsigned long output)
 {
-	unsigned int *delay_times;
+	const unsigned int *delay_times;
 	int num_delay_times;
 
 	if (output) {
@@ -1285,58 +1280,26 @@ static int st_pctl_parse_functions(struct device_node *np,
 	return 0;
 }
 
-static int st_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct st_gpio_bank *bank = gpio_chip_to_bank(chip);
-	int irq = -ENXIO;
-
-	if (offset < chip->ngpio)
-		irq = irq_find_mapping(bank->domain, offset);
-
-	dev_info(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
-				chip->label, offset + chip->base, irq);
-	return irq;
-}
-
 static void st_gpio_irq_mask(struct irq_data *d)
 {
-	struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
 
 	writel(BIT(d->hwirq), bank->base + REG_PIO_CLR_PMASK);
 }
 
 static void st_gpio_irq_unmask(struct irq_data *d)
 {
-	struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
 
 	writel(BIT(d->hwirq), bank->base + REG_PIO_SET_PMASK);
 }
 
-static unsigned int st_gpio_irq_startup(struct irq_data *d)
-{
-	struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-	if (gpio_lock_as_irq(&bank->gpio_chip, d->hwirq))
-		dev_err(bank->gpio_chip.dev,
-			"unable to lock HW IRQ %lu for IRQ\n",
-			d->hwirq);
-
-	st_gpio_irq_unmask(d);
-
-	return 0;
-}
-
-static void st_gpio_irq_shutdown(struct irq_data *d)
-{
-	struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-	st_gpio_irq_mask(d);
-	gpio_unlock_as_irq(&bank->gpio_chip, d->hwirq);
-}
-
 static int st_gpio_irq_set_type(struct irq_data *d, unsigned type)
 {
-	struct st_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
 	unsigned long flags;
 	int comp, pin = d->hwirq;
 	u32 val;
@@ -1440,7 +1403,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
 					continue;
 			}
 
-			generic_handle_irq(irq_find_mapping(bank->domain, n));
+			generic_handle_irq(irq_find_mapping(bank->gpio_chip.irqdomain, n));
 		}
 	}
 }
@@ -1449,7 +1412,8 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
 	/* interrupt dedicated per bank */
 	struct irq_chip *chip = irq_get_chip(irq);
-	struct st_gpio_bank *bank = irq_get_handler_data(irq);
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
 
 	chained_irq_enter(chip, desc);
 	__gpio_irq_handler(bank);
@@ -1483,7 +1447,6 @@ static struct gpio_chip st_gpio_template = {
 	.ngpio			= ST_GPIO_PINS_PER_BANK,
 	.of_gpio_n_cells	= 1,
 	.of_xlate		= st_gpio_xlate,
-	.to_irq			= st_gpio_to_irq,
 };
 
 static struct irq_chip st_gpio_irqchip = {
@@ -1491,26 +1454,6 @@ static struct irq_chip st_gpio_irqchip = {
 	.irq_mask	= st_gpio_irq_mask,
 	.irq_unmask	= st_gpio_irq_unmask,
 	.irq_set_type	= st_gpio_irq_set_type,
-	.irq_startup	= st_gpio_irq_startup,
-	.irq_shutdown	= st_gpio_irq_shutdown,
-};
-
-static int st_gpio_irq_domain_map(struct irq_domain *h,
-			unsigned int virq, irq_hw_number_t hw)
-{
-	struct st_gpio_bank *bank = h->host_data;
-
-	irq_set_chip(virq, &st_gpio_irqchip);
-	irq_set_handler(virq, handle_simple_irq);
-	set_irq_flags(virq, IRQF_VALID);
-	irq_set_chip_data(virq, bank);
-
-	return 0;
-}
-
-static struct irq_domain_ops st_gpio_irq_ops = {
-	.map	= st_gpio_irq_domain_map,
-	.xlate	= irq_domain_xlate_twocell,
 };
 
 static int st_gpiolib_register_bank(struct st_pinctrl *info,
@@ -1521,7 +1464,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
 	struct device *dev = info->dev;
 	int bank_num = of_alias_get_id(np, "gpio");
 	struct resource res, irq_res;
-	int gpio_irq = 0, err, i;
+	int gpio_irq = 0, err;
 
 	if (of_address_to_resource(np, 0, &res))
 		return -ENODEV;
@@ -1534,6 +1477,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
 	bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK;
 	bank->gpio_chip.ngpio = ST_GPIO_PINS_PER_BANK;
 	bank->gpio_chip.of_node = np;
+	bank->gpio_chip.dev = dev;
 	spin_lock_init(&bank->lock);
 
 	of_property_read_string(np, "st,bank-name", &range->name);
@@ -1571,26 +1515,18 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
 
 	if (of_irq_to_resource(np, 0, &irq_res)) {
 		gpio_irq = irq_res.start;
-		irq_set_chained_handler(gpio_irq, st_gpio_irq_handler);
-		irq_set_handler_data(gpio_irq, bank);
+		gpiochip_set_chained_irqchip(&bank->gpio_chip, &st_gpio_irqchip,
+					     gpio_irq, st_gpio_irq_handler);
 	}
 
 	if (info->irqmux_base > 0 || gpio_irq > 0) {
-		/* Setup IRQ domain */
-		bank->domain  = irq_domain_add_linear(np,
-						ST_GPIO_PINS_PER_BANK,
-						&st_gpio_irq_ops, bank);
-		if (!bank->domain) {
-			dev_err(dev, "Failed to add irq domain for %s\n",
-				np->full_name);
-		} else  {
-			for (i = 0; i < ST_GPIO_PINS_PER_BANK; i++) {
-				if (irq_create_mapping(bank->domain, i) < 0)
-					dev_err(dev,
-						"Failed to map IRQ %i\n", i);
-			}
+		err = gpiochip_irqchip_add(&bank->gpio_chip, &st_gpio_irqchip,
+					   0, handle_simple_irq,
+					   IRQ_TYPE_LEVEL_LOW);
+		if (err) {
+			dev_info(dev, "could not add irqchip\n");
+			return err;
 		}
-
 	} else {
 		dev_info(dev, "No IRQ support for %s bank\n", np->full_name);
 	}
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 5186d70c49d4..56f62dc6e666 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -1733,19 +1733,32 @@ static const unsigned int du_clk_out_1_mux[] = {
 	DU1_DOTCLKOUT1_MARK
 };
 static const unsigned int du_sync_pins[] = {
-	/* EXVSYNC/VSYNC, EXHSYNC/HSYNC, EXDISP/EXODDF/EXCDE */
-	RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 27),
+	/* EXVSYNC/VSYNC, EXHSYNC/HSYNC */
+	RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 27),
 };
 static const unsigned int du_sync_mux[] = {
-	DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK,
 	DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK
 };
-static const unsigned int du_cde_disp_pins[] = {
-	/* CDE DISP */
-	RCAR_GP_PIN(3, 31), RCAR_GP_PIN(3, 30),
+static const unsigned int du_oddf_pins[] = {
+	/* EXDISP/EXODDF/EXCDE */
+	RCAR_GP_PIN(3, 29),
+};
+static const unsigned int du_oddf_mux[] = {
+	DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK,
+};
+static const unsigned int du_cde_pins[] = {
+	/* CDE */
+	RCAR_GP_PIN(3, 31),
+};
+static const unsigned int du_cde_mux[] = {
+	DU1_CDE_MARK,
+};
+static const unsigned int du_disp_pins[] = {
+	/* DISP */
+	RCAR_GP_PIN(3, 30),
 };
-static const unsigned int du_cde_disp_mux[] = {
-	DU1_CDE_MARK, DU1_DISP_MARK
+static const unsigned int du_disp_mux[] = {
+	DU1_DISP_MARK,
 };
 static const unsigned int du0_clk_in_pins[] = {
 	/* CLKIN */
@@ -3555,7 +3568,9 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(du_clk_out_0),
 	SH_PFC_PIN_GROUP(du_clk_out_1),
 	SH_PFC_PIN_GROUP(du_sync),
-	SH_PFC_PIN_GROUP(du_cde_disp),
+	SH_PFC_PIN_GROUP(du_oddf),
+	SH_PFC_PIN_GROUP(du_cde),
+	SH_PFC_PIN_GROUP(du_disp),
 	SH_PFC_PIN_GROUP(du0_clk_in),
 	SH_PFC_PIN_GROUP(du1_clk_in),
 	SH_PFC_PIN_GROUP(du1_clk_in_b),
@@ -3804,7 +3819,9 @@ static const char * const du_groups[] = {
 	"du_clk_out_0",
 	"du_clk_out_1",
 	"du_sync",
-	"du_cde_disp",
+	"du_oddf",
+	"du_cde",
+	"du_disp",
 };
 
 static const char * const du0_groups[] = {
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 2f07cd615665..983f50c4b7b4 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -152,35 +152,38 @@ static long pps_cdev_ioctl(struct file *file,
 		if (err)
 			return -EFAULT;
 
-		ev = pps->last_ev;
-
-		/* Manage the timeout */
-		if (fdata.timeout.flags & PPS_TIME_INVALID)
-			err = wait_event_interruptible(pps->queue,
-					ev != pps->last_ev);
-		else {
-			unsigned long ticks;
-
-			dev_dbg(pps->dev, "timeout %lld.%09d\n",
-					(long long) fdata.timeout.sec,
-					fdata.timeout.nsec);
-			ticks = fdata.timeout.sec * HZ;
-			ticks += fdata.timeout.nsec / (NSEC_PER_SEC / HZ);
-
-			if (ticks != 0) {
-				err = wait_event_interruptible_timeout(
-						pps->queue,
-						ev != pps->last_ev,
-						ticks);
-				if (err == 0)
-					return -ETIMEDOUT;
+		if (!(file->f_flags & O_NONBLOCK)) {
+			ev = pps->last_ev;
+
+			/* Manage the timeout */
+			if (fdata.timeout.flags & PPS_TIME_INVALID)
+				err = wait_event_interruptible(pps->queue,
+						ev != pps->last_ev);
+			else {
+				unsigned long ticks;
+
+				dev_dbg(pps->dev, "timeout %lld.%09d\n",
+						(long long) fdata.timeout.sec,
+						fdata.timeout.nsec);
+				ticks = fdata.timeout.sec * HZ;
+				ticks += fdata.timeout.nsec /
+					(NSEC_PER_SEC / HZ);
+
+				if (ticks != 0) {
+					err = wait_event_interruptible_timeout(
+							pps->queue,
+							ev != pps->last_ev,
+							ticks);
+					if (err == 0)
+						return -ETIMEDOUT;
+				}
 			}
-		}
 
-		/* Check for pending signals */
-		if (err == -ERESTARTSYS) {
-			dev_dbg(pps->dev, "pending signal caught\n");
-			return -EINTR;
+			/* Check for pending signals */
+			if (err == -ERESTARTSYS) {
+				dev_dbg(pps->dev, "pending signal caught\n");
+				return -EINTR;
+			}
 		}
 
 		/* Return the fetched timestamp */
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 903eb37f047a..65e5d7d1b35a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -139,6 +139,13 @@ config REGULATOR_AS3722
 	  AS3722 PMIC. This will enable support for all the software
 	  controllable DCDC/LDO regulators.
 
+config REGULATOR_AXP20X
+	tristate "X-POWERS AXP20X PMIC Regulators"
+	depends on MFD_AXP20X
+	help
+	  This driver provides support for the voltage regulators on the
+	  AXP20X PMIC.
+
 config REGULATOR_BCM590XX
 	tristate "Broadcom BCM590xx PMU Regulators"
 	depends on MFD_BCM590XX
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 12ef277a48b4..c14696b290c0 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
new file mode 100644
index 000000000000..78a29e60f53a
--- /dev/null
+++ b/drivers/regulator/axp20x-regulator.c
@@ -0,0 +1,285 @@
+/*
+ * AXP20x regulators driver.
+ *
+ * Copyright (C) 2013 Carlo Caione <carlo@caione.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define AXP20X_IO_ENABLED		0x03
+#define AXP20X_IO_DISABLED		0x07
+
+#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
+#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
+
+#define AXP20X_FREQ_DCDC_MASK		0x0f
+
+#define AXP20X_DESC_IO(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg,   \
+		       _emask, _enable_val, _disable_val)			\
+	[AXP20X_##_id] = {							\
+		.name		= #_id,						\
+		.supply_name	= (_supply),					\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= AXP20X_##_id,					\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.enable_val	= (_enable_val),				\
+		.disable_val	= (_disable_val),				\
+		.ops		= &axp20x_ops,					\
+	}
+
+#define AXP20X_DESC(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg,	\
+		    _emask) 							\
+	[AXP20X_##_id] = {							\
+		.name		= #_id,						\
+		.supply_name	= (_supply),					\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= AXP20X_##_id,					\
+		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_min) * 1000,				\
+		.uV_step	= (_step) * 1000,				\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.ops		= &axp20x_ops,					\
+	}
+
+#define AXP20X_DESC_FIXED(_id, _supply, _volt)					\
+	[AXP20X_##_id] = {							\
+		.name		= #_id,						\
+		.supply_name	= (_supply),					\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= AXP20X_##_id,					\
+		.n_voltages	= 1,						\
+		.owner		= THIS_MODULE,					\
+		.min_uV		= (_volt) * 1000,				\
+		.ops		= &axp20x_ops_fixed				\
+	}
+
+#define AXP20X_DESC_TABLE(_id, _supply, _table, _vreg, _vmask, _ereg, _emask)	\
+	[AXP20X_##_id] = {							\
+		.name		= #_id,						\
+		.supply_name	= (_supply),					\
+		.type		= REGULATOR_VOLTAGE,				\
+		.id		= AXP20X_##_id,					\
+		.n_voltages	= ARRAY_SIZE(_table),				\
+		.owner		= THIS_MODULE,					\
+		.vsel_reg	= (_vreg),					\
+		.vsel_mask	= (_vmask),					\
+		.enable_reg	= (_ereg),					\
+		.enable_mask	= (_emask),					\
+		.volt_table	= (_table),					\
+		.ops		= &axp20x_ops_table,				\
+	}
+
+static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000,
+					1700000, 1800000, 1900000, 2000000, 2500000,
+					2700000, 2800000, 3000000, 3100000, 3200000,
+					3300000 };
+
+static struct regulator_ops axp20x_ops_fixed = {
+	.list_voltage		= regulator_list_voltage_linear,
+};
+
+static struct regulator_ops axp20x_ops_table = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_table,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+
+static struct regulator_ops axp20x_ops = {
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+};
+
+static const struct regulator_desc axp20x_regulators[] = {
+	AXP20X_DESC(DCDC2, "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f,
+		    AXP20X_PWR_OUT_CTRL, 0x10),
+	AXP20X_DESC(DCDC3, "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT, 0x7f,
+		    AXP20X_PWR_OUT_CTRL, 0x02),
+	AXP20X_DESC_FIXED(LDO1, "acin", 1300),
+	AXP20X_DESC(LDO2, "ldo24in", 1800, 3300, 100, AXP20X_LDO24_V_OUT, 0xf0,
+		    AXP20X_PWR_OUT_CTRL, 0x04),
+	AXP20X_DESC(LDO3, "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f,
+		    AXP20X_PWR_OUT_CTRL, 0x40),
+	AXP20X_DESC_TABLE(LDO4, "ldo24in", axp20x_ldo4_data, AXP20X_LDO24_V_OUT, 0x0f,
+			  AXP20X_PWR_OUT_CTRL, 0x08),
+	AXP20X_DESC_IO(LDO5, "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0,
+		       AXP20X_GPIO0_CTRL, 0x07, AXP20X_IO_ENABLED,
+		       AXP20X_IO_DISABLED),
+};
+
+#define AXP_MATCH(_name, _id) \
+	[AXP20X_##_id] = { \
+		.name		= #_name, \
+		.driver_data	= (void *) &axp20x_regulators[AXP20X_##_id], \
+	}
+
+static struct of_regulator_match axp20x_matches[] = {
+	AXP_MATCH(dcdc2, DCDC2),
+	AXP_MATCH(dcdc3, DCDC3),
+	AXP_MATCH(ldo1, LDO1),
+	AXP_MATCH(ldo2, LDO2),
+	AXP_MATCH(ldo3, LDO3),
+	AXP_MATCH(ldo4, LDO4),
+	AXP_MATCH(ldo5, LDO5),
+};
+
+static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
+{
+	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+
+	if (dcdcfreq < 750) {
+		dcdcfreq = 750;
+		dev_warn(&pdev->dev, "DCDC frequency too low. Set to 750kHz\n");
+	}
+
+	if (dcdcfreq > 1875) {
+		dcdcfreq = 1875;
+		dev_warn(&pdev->dev, "DCDC frequency too high. Set to 1875kHz\n");
+	}
+
+	dcdcfreq = (dcdcfreq - 750) / 75;
+
+	return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
+				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
+}
+
+static int axp20x_regulator_parse_dt(struct platform_device *pdev)
+{
+	struct device_node *np, *regulators;
+	int ret;
+	u32 dcdcfreq;
+
+	np = of_node_get(pdev->dev.parent->of_node);
+	if (!np)
+		return 0;
+
+	regulators = of_find_node_by_name(np, "regulators");
+	if (!regulators) {
+		dev_warn(&pdev->dev, "regulators node not found\n");
+	} else {
+		ret = of_regulator_match(&pdev->dev, regulators, axp20x_matches,
+					 ARRAY_SIZE(axp20x_matches));
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
+			return ret;
+		}
+
+		dcdcfreq = 1500;
+		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
+		ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret);
+			return ret;
+		}
+
+		of_node_put(regulators);
+	}
+
+	return 0;
+}
+
+static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
+{
+	unsigned int mask = AXP20X_WORKMODE_DCDC2_MASK;
+
+	if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
+		return -EINVAL;
+
+	if (id == AXP20X_DCDC3)
+		mask = AXP20X_WORKMODE_DCDC3_MASK;
+
+	workmode <<= ffs(mask) - 1;
+
+	return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
+}
+
+static int axp20x_regulator_probe(struct platform_device *pdev)
+{
+	struct regulator_dev *rdev;
+	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+	struct regulator_config config = { };
+	struct regulator_init_data *init_data;
+	int ret, i;
+	u32 workmode;
+
+	ret = axp20x_regulator_parse_dt(pdev);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
+		init_data = axp20x_matches[i].init_data;
+
+		config.dev = &pdev->dev;
+		config.init_data = init_data;
+		config.regmap = axp20x->regmap;
+		config.of_node = axp20x_matches[i].of_node;
+
+		rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i],
+					       &config);
+		if (IS_ERR(rdev)) {
+			dev_err(&pdev->dev, "Failed to register %s\n",
+				axp20x_regulators[i].name);
+
+			return PTR_ERR(rdev);
+		}
+
+		ret = of_property_read_u32(axp20x_matches[i].of_node, "x-powers,dcdc-workmode",
+					   &workmode);
+		if (!ret) {
+			if (axp20x_set_dcdc_workmode(rdev, i, workmode))
+				dev_err(&pdev->dev, "Failed to set workmode on %s\n",
+					axp20x_regulators[i].name);
+		}
+	}
+
+	return 0;
+}
+
+static struct platform_driver axp20x_regulator_driver = {
+	.probe	= axp20x_regulator_probe,
+	.driver	= {
+		.name		= "axp20x-regulator",
+		.owner		= THIS_MODULE,
+	},
+};
+
+module_platform_driver(axp20x_regulator_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9a09f3cdbabb..b97ffd2365d3 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3447,7 +3447,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
 
 	/* register with sysfs */
 	rdev->dev.class = &regulator_class;
-	rdev->dev.of_node = config->of_node;
+	rdev->dev.of_node = of_node_get(config->of_node);
 	rdev->dev.parent = dev;
 	dev_set_name(&rdev->dev, "regulator.%d",
 		     atomic_inc_return(&regulator_no) - 1);
@@ -3589,6 +3589,7 @@ void regulator_unregister(struct regulator_dev *rdev)
 	list_del(&rdev->list);
 	kfree(rdev->constraints);
 	regulator_ena_gpio_free(rdev);
+	of_node_put(rdev->dev.of_node);
 	device_unregister(&rdev->dev);
 	mutex_unlock(&regulator_list_mutex);
 }
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index ea4f36f2cbe2..188e0cb10d03 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -119,7 +119,8 @@ EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
  * regulator. The data parsed from a child node will be matched to a regulator
  * based on either the deprecated property regulator-compatible if present,
  * or otherwise the child node's name. Note that the match table is modified
- * in place.
+ * in place and an additional of_node reference is taken for each matched
+ * regulator.
  *
  * Returns the number of matches found or a negative error code on failure.
  */
@@ -162,7 +163,7 @@ int of_regulator_match(struct device *dev, struct device_node *node,
 					child->name);
 				return -EINVAL;
 			}
-			match->of_node = child;
+			match->of_node = of_node_get(child);
 			count++;
 			break;
 		}
@@ -171,3 +172,24 @@ int of_regulator_match(struct device *dev, struct device_node *node,
 	return count;
 }
 EXPORT_SYMBOL_GPL(of_regulator_match);
+
+/**
+ * of_regulator_put_match - put the of_node references from an
+ *                          of_regulator_match structure
+ * @matches: match table for the regulators
+ * @num_matches: number of entries in match table
+ *
+ * This function goes through a match table and calls of_node_put on each
+ * of_node.
+ */
+int of_regulator_put_match(struct of_regulator_match *matches,
+			   unsigned int num_matches)
+{
+	int i;
+
+	for (i = 0; i < num_matches; i++)
+		of_node_put(matches[i].of_node);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_regulator_put_match);
diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c
index ded3b3574209..708ddbb83e29 100644
--- a/drivers/regulator/pbias-regulator.c
+++ b/drivers/regulator/pbias-regulator.c
@@ -38,85 +38,24 @@ struct pbias_reg_info {
 struct pbias_regulator_data {
 	struct regulator_desc desc;
 	void __iomem *pbias_addr;
-	unsigned int pbias_reg;
 	struct regulator_dev *dev;
 	struct regmap *syscon;
 	const struct pbias_reg_info *info;
 	int voltage;
 };
 
-static int pbias_regulator_set_voltage(struct regulator_dev *dev,
-			int min_uV, int max_uV, unsigned *selector)
-{
-	struct pbias_regulator_data *data = rdev_get_drvdata(dev);
-	const struct pbias_reg_info *info = data->info;
-	int ret, vmode;
-
-	if (min_uV <= 1800000)
-		vmode = 0;
-	else if (min_uV > 1800000)
-		vmode = info->vmode;
-
-	ret = regmap_update_bits(data->syscon, data->pbias_reg,
-						info->vmode, vmode);
-
-	return ret;
-}
-
-static int pbias_regulator_get_voltage(struct regulator_dev *rdev)
-{
-	struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
-	const struct pbias_reg_info *info = data->info;
-	int value, voltage;
-
-	regmap_read(data->syscon, data->pbias_reg, &value);
-	value &= info->vmode;
-
-	voltage = value ? 3000000 : 1800000;
-
-	return voltage;
-}
-
-static int pbias_regulator_enable(struct regulator_dev *rdev)
-{
-	struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
-	const struct pbias_reg_info *info = data->info;
-	int ret;
-
-	ret = regmap_update_bits(data->syscon, data->pbias_reg,
-					info->enable_mask, info->enable);
-
-	return ret;
-}
-
-static int pbias_regulator_disable(struct regulator_dev *rdev)
-{
-	struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
-	const struct pbias_reg_info *info = data->info;
-	int ret;
-
-	ret = regmap_update_bits(data->syscon, data->pbias_reg,
-						info->enable_mask, 0);
-	return ret;
-}
-
-static int pbias_regulator_is_enable(struct regulator_dev *rdev)
-{
-	struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
-	const struct pbias_reg_info *info = data->info;
-	int value;
-
-	regmap_read(data->syscon, data->pbias_reg, &value);
-
-	return (value & info->enable_mask) == info->enable_mask;
-}
+static const unsigned int pbias_volt_table[] = {
+	1800000,
+	3000000
+};
 
 static struct regulator_ops pbias_regulator_voltage_ops = {
-	.set_voltage	= pbias_regulator_set_voltage,
-	.get_voltage	= pbias_regulator_get_voltage,
-	.enable		= pbias_regulator_enable,
-	.disable	= pbias_regulator_disable,
-	.is_enabled	= pbias_regulator_is_enable,
+	.list_voltage = regulator_list_voltage_table,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
 };
 
 static const struct pbias_reg_info pbias_mmc_omap2430 = {
@@ -192,6 +131,7 @@ static int pbias_regulator_probe(struct platform_device *pdev)
 	if (IS_ERR(syscon))
 		return PTR_ERR(syscon);
 
+	cfg.regmap = syscon;
 	cfg.dev = &pdev->dev;
 
 	for (idx = 0; idx < PBIAS_NUM_REGS && data_idx < count; idx++) {
@@ -207,15 +147,20 @@ static int pbias_regulator_probe(struct platform_device *pdev)
 		if (!res)
 			return -EINVAL;
 
-		drvdata[data_idx].pbias_reg = res->start;
 		drvdata[data_idx].syscon = syscon;
 		drvdata[data_idx].info = info;
 		drvdata[data_idx].desc.name = info->name;
 		drvdata[data_idx].desc.owner = THIS_MODULE;
 		drvdata[data_idx].desc.type = REGULATOR_VOLTAGE;
 		drvdata[data_idx].desc.ops = &pbias_regulator_voltage_ops;
+		drvdata[data_idx].desc.volt_table = pbias_volt_table;
 		drvdata[data_idx].desc.n_voltages = 2;
 		drvdata[data_idx].desc.enable_time = info->enable_time;
+		drvdata[data_idx].desc.vsel_reg = res->start;
+		drvdata[data_idx].desc.vsel_mask = info->vmode;
+		drvdata[data_idx].desc.enable_reg = res->start;
+		drvdata[data_idx].desc.enable_mask = info->enable_mask;
+		drvdata[data_idx].desc.enable_val = info->enable;
 
 		cfg.init_data = pbias_matches[idx].init_data;
 		cfg.driver_data = &drvdata[data_idx];
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index e713c162fbd4..6dad0aa74a47 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -27,6 +27,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
+#include <linux/of_gpio.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps14.h>
@@ -44,6 +45,8 @@ struct s2mps11_info {
 	 * was enabled.
 	 */
 	unsigned int s2mps14_suspend_state:30;
+	/* Array of size rdev_num with GPIO-s for external sleep control */
+	int *ext_control_gpio;
 };
 
 static int get_ramp_delay(int ramp_delay)
@@ -409,6 +412,8 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
 
 	if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
 		val = S2MPS14_ENABLE_SUSPEND;
+	else if (s2mps11->ext_control_gpio[rdev_get_id(rdev)])
+		val = S2MPS14_ENABLE_EXT_CONTROL;
 	else
 		val = rdev->desc->enable_mask;
 
@@ -565,12 +570,63 @@ static const struct regulator_desc s2mps14_regulators[] = {
 	regulator_desc_s2mps14_buck1235(5),
 };
 
+static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
+		struct regulator_dev *rdev)
+{
+	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+			rdev->desc->enable_mask, S2MPS14_ENABLE_EXT_CONTROL);
+}
+
+static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
+		struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
+{
+	int *gpio = s2mps11->ext_control_gpio;
+	unsigned int i;
+	unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11,
+		S2MPS14_LDO12 };
+
+	for (i = 0; i < ARRAY_SIZE(valid_regulators); i++) {
+		unsigned int reg = valid_regulators[i];
+
+		if (!rdata[reg].init_data || !rdata[reg].of_node)
+			continue;
+
+		gpio[reg] = of_get_named_gpio(rdata[reg].of_node,
+				"samsung,ext-control-gpios", 0);
+		if (!gpio_is_valid(gpio[reg]))
+			gpio[reg] = 0;
+		else
+			dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n",
+					gpio[reg], reg, rdata[reg].name);
+	}
+}
+
+static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
+		struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
+		enum sec_device_type dev_type)
+{
+	struct device_node *reg_np;
+
+	reg_np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
+	if (!reg_np) {
+		dev_err(&pdev->dev, "could not find regulators sub-node\n");
+		return -EINVAL;
+	}
+
+	of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
+	if (dev_type == S2MPS14X)
+		s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
+
+	of_node_put(reg_np);
+
+	return 0;
+}
+
 static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-	struct sec_platform_data *pdata = iodev->pdata;
+	struct sec_platform_data *pdata = NULL;
 	struct of_regulator_match *rdata = NULL;
-	struct device_node *reg_np = NULL;
 	struct regulator_config config = { };
 	struct s2mps11_info *s2mps11;
 	int i, ret = 0;
@@ -597,8 +653,15 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 		return -EINVAL;
 	};
 
+	s2mps11->ext_control_gpio = devm_kzalloc(&pdev->dev,
+			sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
+			GFP_KERNEL);
+	if (!s2mps11->ext_control_gpio)
+		return -ENOMEM;
+
 	if (!iodev->dev->of_node) {
-		if (pdata) {
+		if (iodev->pdata) {
+			pdata = iodev->pdata;
 			goto common_reg;
 		} else {
 			dev_err(pdev->dev.parent,
@@ -614,15 +677,9 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 	for (i = 0; i < s2mps11->rdev_num; i++)
 		rdata[i].name = regulators[i].name;
 
-	reg_np = of_get_child_by_name(iodev->dev->of_node, "regulators");
-	if (!reg_np) {
-		dev_err(&pdev->dev, "could not find regulators sub-node\n");
-		ret = -EINVAL;
+	ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type);
+	if (ret)
 		goto out;
-	}
-
-	of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
-	of_node_put(reg_np);
 
 common_reg:
 	platform_set_drvdata(pdev, s2mps11);
@@ -633,7 +690,7 @@ common_reg:
 	for (i = 0; i < s2mps11->rdev_num; i++) {
 		struct regulator_dev *regulator;
 
-		if (!reg_np) {
+		if (pdata) {
 			config.init_data = pdata->regulators[i].initdata;
 			config.of_node = pdata->regulators[i].reg_node;
 		} else {
@@ -641,6 +698,12 @@ common_reg:
 			config.of_node = rdata[i].of_node;
 		}
 
+		if (s2mps11->ext_control_gpio[i]) {
+			config.ena_gpio = s2mps11->ext_control_gpio[i];
+			config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+		} else
+			config.ena_gpio = config.ena_gpio_flags = 0;
+
 		regulator = devm_regulator_register(&pdev->dev,
 						&regulators[i], &config);
 		if (IS_ERR(regulator)) {
@@ -649,6 +712,17 @@ common_reg:
 				i);
 			goto out;
 		}
+
+		if (s2mps11->ext_control_gpio[i]) {
+			ret = s2mps14_pmic_enable_ext_control(s2mps11,
+					regulator);
+			if (ret < 0) {
+				dev_err(&pdev->dev,
+						"failed to enable GPIO control over %s: %d\n",
+						regulator->desc->name, ret);
+				goto out;
+			}
+		}
 	}
 
 out:
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 92f19a005dc3..5daa06626f16 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -28,7 +28,6 @@ struct s5m8767_info {
 	struct device *dev;
 	struct sec_pmic_dev *iodev;
 	int num_regulators;
-	struct regulator_dev **rdev;
 	struct sec_opmode_data *opmode;
 
 	int ramp_delay;
@@ -695,7 +694,6 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct sec_platform_data *pdata = iodev->pdata;
 	struct regulator_config config = { };
-	struct regulator_dev **rdev;
 	struct s5m8767_info *s5m8767;
 	int i, ret, size, buck_init;
 
@@ -737,11 +735,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2);
-	s5m8767->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
-	if (!s5m8767->rdev)
-		return -ENOMEM;
 
-	rdev = s5m8767->rdev;
 	s5m8767->dev = &pdev->dev;
 	s5m8767->iodev = iodev;
 	s5m8767->num_regulators = pdata->num_regulators;
@@ -938,6 +932,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
 		const struct sec_voltage_desc *desc;
 		int id = pdata->regulators[i].id;
 		int enable_reg, enable_val;
+		struct regulator_dev *rdev;
 
 		desc = reg_voltage_map[id];
 		if (desc) {
@@ -969,21 +964,21 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
 			s5m8767_regulator_config_ext_control(s5m8767,
 					&pdata->regulators[i], &config);
 
-		rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
+		rdev = devm_regulator_register(&pdev->dev, &regulators[id],
 						  &config);
-		if (IS_ERR(rdev[i])) {
-			ret = PTR_ERR(rdev[i]);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
 			dev_err(s5m8767->dev, "regulator init failed for %d\n",
 					id);
 			return ret;
 		}
 
 		if (pdata->regulators[i].ext_control_gpio) {
-			ret = s5m8767_enable_ext_control(s5m8767, rdev[i]);
+			ret = s5m8767_enable_ext_control(s5m8767, rdev);
 			if (ret < 0) {
 				dev_err(s5m8767->dev,
 						"failed to enable gpio control over %s: %d\n",
-						rdev[i]->desc->name, ret);
+						rdev->desc->name, ret);
 				return ret;
 			}
 		}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2e565f8e5165..ac4fa56280cd 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1327,6 +1327,15 @@ config RTC_DRV_MOXART
 	   This driver can also be built as a module. If so, the module
 	   will be called rtc-moxart
 
+config RTC_DRV_XGENE
+	tristate "APM X-Gene RTC"
+	help
+	  If you say yes here you get support for the APM X-Gene SoC real time
+	  clock.
+
+	  This driver can also be built as a module, if so, the module
+	  will be called "rtc-xgene".
+
 comment "HID Sensor RTC drivers"
 
 config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 40a09915c8f6..4545b4a88f30 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -135,5 +135,6 @@ obj-$(CONFIG_RTC_DRV_VT8500)	+= rtc-vt8500.o
 obj-$(CONFIG_RTC_DRV_WM831X)	+= rtc-wm831x.o
 obj-$(CONFIG_RTC_DRV_WM8350)	+= rtc-wm8350.o
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
+obj-$(CONFIG_RTC_DRV_XGENE)	+= rtc-xgene.o
 obj-$(CONFIG_RTC_DRV_SIRFSOC)	+= rtc-sirfsoc.o
 obj-$(CONFIG_RTC_DRV_MOXART)	+= rtc-moxart.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index c2eff6082363..13f93fa7fa80 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -292,7 +292,9 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
 		do {
 			alarm->time.tm_year++;
-		} while (rtc_valid_tm(&alarm->time) != 0);
+		} while (alarm->time.tm_mon == 1
+			&& is_leap_year(alarm->time.tm_year + 1900)
+			&& rtc_valid_tm(&alarm->time) != 0);
 		break;
 
 	default:
@@ -300,7 +302,16 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 	}
 
 done:
-	return 0;
+	err = rtc_valid_tm(&alarm->time);
+
+	if (err) {
+		dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n",
+			alarm->time.tm_year + 1900, alarm->time.tm_mon + 1,
+			alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min,
+			alarm->time.tm_sec);
+	}
+
+	return err;
 }
 
 int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c
new file mode 100644
index 000000000000..14129cc85bdb
--- /dev/null
+++ b/drivers/rtc/rtc-xgene.c
@@ -0,0 +1,278 @@
+/*
+ * APM X-Gene SoC Real Time Clock Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Author: Rameshwar Prasad Sahu <rsahu@apm.com>
+ *         Loc Ho <lho@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+
+/* RTC CSR Registers */
+#define RTC_CCVR		0x00
+#define RTC_CMR			0x04
+#define RTC_CLR			0x08
+#define RTC_CCR			0x0C
+#define  RTC_CCR_IE		BIT(0)
+#define  RTC_CCR_MASK		BIT(1)
+#define  RTC_CCR_EN		BIT(2)
+#define  RTC_CCR_WEN		BIT(3)
+#define RTC_STAT		0x10
+#define  RTC_STAT_BIT		BIT(0)
+#define RTC_RSTAT		0x14
+#define RTC_EOI			0x18
+#define RTC_VER			0x1C
+
+struct xgene_rtc_dev {
+	struct rtc_device *rtc;
+	struct device *dev;
+	unsigned long alarm_time;
+	void __iomem *csr_base;
+	struct clk *clk;
+	unsigned int irq_wake;
+};
+
+static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
+
+	rtc_time_to_tm(readl(pdata->csr_base + RTC_CCVR), tm);
+	return rtc_valid_tm(tm);
+}
+
+static int xgene_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+	struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
+
+	/*
+	 * NOTE: After the following write, the RTC_CCVR is only reflected
+	 *       after the update cycle of 1 seconds.
+	 */
+	writel((u32) secs, pdata->csr_base + RTC_CLR);
+	readl(pdata->csr_base + RTC_CLR); /* Force a barrier */
+
+	return 0;
+}
+
+static int xgene_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
+
+	rtc_time_to_tm(pdata->alarm_time, &alrm->time);
+	alrm->enabled = readl(pdata->csr_base + RTC_CCR) & RTC_CCR_IE;
+
+	return 0;
+}
+
+static int xgene_rtc_alarm_irq_enable(struct device *dev, u32 enabled)
+{
+	struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
+	u32 ccr;
+
+	ccr = readl(pdata->csr_base + RTC_CCR);
+	if (enabled) {
+		ccr &= ~RTC_CCR_MASK;
+		ccr |= RTC_CCR_IE;
+	} else {
+		ccr &= ~RTC_CCR_IE;
+		ccr |= RTC_CCR_MASK;
+	}
+	writel(ccr, pdata->csr_base + RTC_CCR);
+
+	return 0;
+}
+
+static int xgene_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
+	unsigned long rtc_time;
+	unsigned long alarm_time;
+
+	rtc_time = readl(pdata->csr_base + RTC_CCVR);
+	rtc_tm_to_time(&alrm->time, &alarm_time);
+
+	pdata->alarm_time = alarm_time;
+	writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR);
+
+	xgene_rtc_alarm_irq_enable(dev, alrm->enabled);
+
+	return 0;
+}
+
+static const struct rtc_class_ops xgene_rtc_ops = {
+	.read_time	= xgene_rtc_read_time,
+	.set_mmss	= xgene_rtc_set_mmss,
+	.read_alarm	= xgene_rtc_read_alarm,
+	.set_alarm	= xgene_rtc_set_alarm,
+	.alarm_irq_enable = xgene_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t xgene_rtc_interrupt(int irq, void *id)
+{
+	struct xgene_rtc_dev *pdata = (struct xgene_rtc_dev *) id;
+
+	/* Check if interrupt asserted */
+	if (!(readl(pdata->csr_base + RTC_STAT) & RTC_STAT_BIT))
+		return IRQ_NONE;
+
+	/* Clear interrupt */
+	readl(pdata->csr_base + RTC_EOI);
+
+	rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF);
+
+	return IRQ_HANDLED;
+}
+
+static int xgene_rtc_probe(struct platform_device *pdev)
+{
+	struct xgene_rtc_dev *pdata;
+	struct resource *res;
+	int ret;
+	int irq;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, pdata);
+	pdata->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pdata->csr_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pdata->csr_base))
+		return PTR_ERR(pdata->csr_base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No IRQ resource\n");
+		return irq;
+	}
+	ret = devm_request_irq(&pdev->dev, irq, xgene_rtc_interrupt, 0,
+			       dev_name(&pdev->dev), pdata);
+	if (ret) {
+		dev_err(&pdev->dev, "Could not request IRQ\n");
+		return ret;
+	}
+
+	pdata->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pdata->clk)) {
+		dev_err(&pdev->dev, "Couldn't get the clock for RTC\n");
+		return -ENODEV;
+	}
+	clk_prepare_enable(pdata->clk);
+
+	/* Turn on the clock and the crystal */
+	writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR);
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+					 &xgene_rtc_ops, THIS_MODULE);
+	if (IS_ERR(pdata->rtc)) {
+		clk_disable_unprepare(pdata->clk);
+		return PTR_ERR(pdata->rtc);
+	}
+
+	/* HW does not support update faster than 1 seconds */
+	pdata->rtc->uie_unsupported = 1;
+
+	return 0;
+}
+
+static int xgene_rtc_remove(struct platform_device *pdev)
+{
+	struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
+
+	xgene_rtc_alarm_irq_enable(&pdev->dev, 0);
+	device_init_wakeup(&pdev->dev, 0);
+	clk_disable_unprepare(pdata->clk);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int xgene_rtc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
+	int irq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (device_may_wakeup(&pdev->dev)) {
+		if (!enable_irq_wake(irq))
+			pdata->irq_wake = 1;
+	} else {
+		xgene_rtc_alarm_irq_enable(dev, 0);
+		clk_disable(pdata->clk);
+	}
+
+	return 0;
+}
+
+static int xgene_rtc_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
+	int irq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (device_may_wakeup(&pdev->dev)) {
+		if (pdata->irq_wake) {
+			disable_irq_wake(irq);
+			pdata->irq_wake = 0;
+		}
+	} else {
+		clk_enable(pdata->clk);
+		xgene_rtc_alarm_irq_enable(dev, 1);
+	}
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(xgene_rtc_pm_ops, xgene_rtc_suspend, xgene_rtc_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id xgene_rtc_of_match[] = {
+	{.compatible = "apm,xgene-rtc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xgene_rtc_of_match);
+#endif
+
+static struct platform_driver xgene_rtc_driver = {
+	.probe		= xgene_rtc_probe,
+	.remove		= xgene_rtc_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "xgene-rtc",
+		.pm = &xgene_rtc_pm_ops,
+		.of_match_table	= of_match_ptr(xgene_rtc_of_match),
+	},
+};
+
+module_platform_driver(xgene_rtc_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC RTC driver");
+MODULE_AUTHOR("Rameshwar Sahu <rsahu@apm.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 1990285296c6..c316051d9bda 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -1252,7 +1252,7 @@ static __init int sclp_initcall(void)
 		return rc;
 
 	sclp_pdev = platform_device_register_simple("sclp", -1, NULL, 0);
-	rc = PTR_RET(sclp_pdev);
+	rc = PTR_ERR_OR_ZERO(sclp_pdev);
 	if (rc)
 		goto fail_platform_driver_unregister;
 
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 6e8f90f84e49..6e14999f9e8f 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -515,7 +515,7 @@ static int __init sclp_detect_standby_memory(void)
 	if (rc)
 		goto out;
 	sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0);
-	rc = PTR_RET(sclp_pdev);
+	rc = PTR_ERR_OR_ZERO(sclp_pdev);
 	if (rc)
 		goto out_driver;
 	sclp_add_standby_memory();
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 4eed38cd0af6..cd9c91909596 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -97,13 +97,16 @@ static void sclp_vt220_pm_event_fn(struct sclp_register *reg,
 static int __sclp_vt220_emit(struct sclp_vt220_request *request);
 static void sclp_vt220_emit_current(void);
 
-/* Registration structure for our interest in SCLP event buffers */
+/* Registration structure for SCLP output event buffers */
 static struct sclp_register sclp_vt220_register = {
 	.send_mask		= EVTYP_VT220MSG_MASK,
+	.pm_event_fn		= sclp_vt220_pm_event_fn,
+};
+
+/* Registration structure for SCLP input event buffers */
+static struct sclp_register sclp_vt220_register_input = {
 	.receive_mask		= EVTYP_VT220MSG_MASK,
-	.state_change_fn	= NULL,
 	.receiver_fn		= sclp_vt220_receiver_fn,
-	.pm_event_fn		= sclp_vt220_pm_event_fn,
 };
 
 
@@ -715,9 +718,14 @@ static int __init sclp_vt220_tty_init(void)
 	rc = tty_register_driver(driver);
 	if (rc)
 		goto out_init;
+	rc = sclp_register(&sclp_vt220_register_input);
+	if (rc)
+		goto out_reg;
 	sclp_vt220_driver = driver;
 	return 0;
 
+out_reg:
+	tty_unregister_driver(driver);
 out_init:
 	__sclp_vt220_cleanup();
 out_driver:
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 3d8e4d63f514..1884653e4472 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -17,6 +17,8 @@
 #include <linux/miscdevice.h>
 #include <linux/debugfs.h>
 #include <linux/module.h>
+#include <linux/memblock.h>
+
 #include <asm/asm-offsets.h>
 #include <asm/ipl.h>
 #include <asm/sclp.h>
@@ -411,33 +413,24 @@ static ssize_t zcore_memmap_read(struct file *filp, char __user *buf,
 				 size_t count, loff_t *ppos)
 {
 	return simple_read_from_buffer(buf, count, ppos, filp->private_data,
-				       MEMORY_CHUNKS * CHUNK_INFO_SIZE);
+				       memblock.memory.cnt * CHUNK_INFO_SIZE);
 }
 
 static int zcore_memmap_open(struct inode *inode, struct file *filp)
 {
-	int i;
+	struct memblock_region *reg;
 	char *buf;
-	struct mem_chunk *chunk_array;
+	int i = 0;
 
-	chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
-			      GFP_KERNEL);
-	if (!chunk_array)
-		return -ENOMEM;
-	detect_memory_layout(chunk_array, 0);
-	buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
+	buf = kzalloc(memblock.memory.cnt * CHUNK_INFO_SIZE, GFP_KERNEL);
 	if (!buf) {
-		kfree(chunk_array);
 		return -ENOMEM;
 	}
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		sprintf(buf + (i * CHUNK_INFO_SIZE), "%016llx %016llx ",
-			(unsigned long long) chunk_array[i].addr,
-			(unsigned long long) chunk_array[i].size);
-		if (chunk_array[i].size == 0)
-			break;
+	for_each_memblock(memory, reg) {
+		sprintf(buf + (i++ * CHUNK_INFO_SIZE), "%016llx %016llx ",
+			(unsigned long long) reg->base,
+			(unsigned long long) reg->size);
 	}
-	kfree(chunk_array);
 	filp->private_data = buf;
 	return nonseekable_open(inode, filp);
 }
@@ -593,21 +586,12 @@ static int __init check_sdias(void)
 
 static int __init get_mem_info(unsigned long *mem, unsigned long *end)
 {
-	int i;
-	struct mem_chunk *chunk_array;
+	struct memblock_region *reg;
 
-	chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
-			      GFP_KERNEL);
-	if (!chunk_array)
-		return -ENOMEM;
-	detect_memory_layout(chunk_array, 0);
-	for (i = 0; i < MEMORY_CHUNKS; i++) {
-		if (chunk_array[i].size == 0)
-			break;
-		*mem += chunk_array[i].size;
-		*end = max(*end, chunk_array[i].addr + chunk_array[i].size);
+	for_each_memblock(memory, reg) {
+		*mem += reg->size;
+		*end = max_t(unsigned long, *end, reg->base + reg->size);
 	}
-	kfree(chunk_array);
 	return 0;
 }
 
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 4ccb5d869389..a40ee1e37486 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -207,7 +207,7 @@ static void jsfd_do_request(struct request_queue *q)
 			goto end;
 		}
 
-		jsfd_read(req->buffer, jdp->dbase + offset, len);
+		jsfd_read(bio_data(req->bio), jdp->dbase + offset, len);
 		err = 0;
 	end:
 		if (!__blk_end_request_cur(req, err))
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 8cf4a0c69baf..9a6e4a2cd072 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -7463,6 +7463,10 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
 	if (hpsa_simple_mode)
 		return;
 
+	trans_support = readl(&(h->cfgtable->TransportSupport));
+	if (!(trans_support & PERFORMANT_MODE))
+		return;
+
 	/* Check for I/O accelerator mode support */
 	if (trans_support & CFGTBL_Trans_io_accel1) {
 		transMethod |= CFGTBL_Trans_io_accel1 |
@@ -7479,10 +7483,6 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
 	}
 
 	/* TODO, check that this next line h->nreply_queues is correct */
-	trans_support = readl(&(h->cfgtable->TransportSupport));
-	if (!(trans_support & PERFORMANT_MODE))
-		return;
-
 	h->nreply_queues = h->msix_vector > 0 ? h->msix_vector : 1;
 	hpsa_get_max_perf_mode_cmds(h);
 	/* Performant mode ring buffer and supporting data structures */
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 65a123d9c676..3cc82d3dec78 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -139,7 +139,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
 	 */
 	spin_lock_irqsave(q->queue_lock, flags);
 	blk_requeue_request(q, cmd->request);
-	kblockd_schedule_work(q, &device->requeue_work);
+	kblockd_schedule_work(&device->requeue_work);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -1018,8 +1018,6 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
 		return BLKPREP_DEFER;
 	}
 
-	req->buffer = NULL;
-
 	/* 
 	 * Next, walk the list, and fill in the addresses and sizes of
 	 * each segment.
@@ -1156,7 +1154,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		BUG_ON(blk_rq_bytes(req));
 
 		memset(&cmd->sdb, 0, sizeof(cmd->sdb));
-		req->buffer = NULL;
 	}
 
 	cmd->cmd_len = req->cmd_len;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index efcbcd182863..06d154d20faa 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -739,14 +739,11 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 
 	blk_add_request_payload(rq, page, len);
 	ret = scsi_setup_blk_pc_cmnd(sdp, rq);
-	rq->buffer = page_address(page);
 	rq->__data_len = nr_bytes;
 
 out:
-	if (ret != BLKPREP_OK) {
+	if (ret != BLKPREP_OK)
 		__free_page(page);
-		rq->buffer = NULL;
-	}
 	return ret;
 }
 
@@ -843,8 +840,9 @@ static void sd_unprep_fn(struct request_queue *q, struct request *rq)
 	struct scsi_cmnd *SCpnt = rq->special;
 
 	if (rq->cmd_flags & REQ_DISCARD) {
-		free_page((unsigned long)rq->buffer);
-		rq->buffer = NULL;
+		struct bio *bio = rq->bio;
+
+		__free_page(bio->bi_io_vec->bv_page);
 	}
 	if (SCpnt->cmnd != rq->cmd) {
 		mempool_free(SCpnt->cmnd, sd_cdb_pool);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 60f2b41c7310..016557d5284d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -91,8 +91,8 @@ config SPI_BFIN5XX
 	help
 	  This is the SPI controller master driver for Blackfin 5xx processor.
 
-config SPI_BFIN_V3
-	tristate "SPI controller v3 for Blackfin"
+config SPI_ADI_V3
+	tristate "SPI controller v3 for ADI"
 	depends on BF60x
 	help
 	  This is the SPI controller v3 master driver
@@ -148,6 +148,13 @@ config SPI_BUTTERFLY
 	  inexpensive battery powered microcontroller evaluation board.
 	  This same cable can be used to flash new firmware.
 
+config SPI_CADENCE
+	tristate "Cadence SPI controller"
+	depends on ARM
+	help
+	  This selects the Cadence SPI controller master driver
+	  used by Xilinx Zynq.
+
 config SPI_CLPS711X
 	tristate "CLPS711X host SPI controller"
 	depends on ARCH_CLPS711X || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index bd792669e563..929c9f5eac01 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,10 +18,11 @@ obj-$(CONFIG_SPI_BCM2835)		+= spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)		+= spi-bcm63xx.o
 obj-$(CONFIG_SPI_BCM63XX_HSSPI)		+= spi-bcm63xx-hsspi.o
 obj-$(CONFIG_SPI_BFIN5XX)		+= spi-bfin5xx.o
-obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o
+obj-$(CONFIG_SPI_ADI_V3)                += spi-adi-v3.o
 obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o
 obj-$(CONFIG_SPI_BITBANG)		+= spi-bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi-butterfly.o
+obj-$(CONFIG_SPI_CADENCE)		+= spi-cadence.o
 obj-$(CONFIG_SPI_CLPS711X)		+= spi-clps711x.o
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= spi-coldfire-qspi.o
 obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
diff --git a/drivers/spi/spi-adi-v3.c b/drivers/spi/spi-adi-v3.c
new file mode 100644
index 000000000000..dcb2287c7f8a
--- /dev/null
+++ b/drivers/spi/spi-adi-v3.c
@@ -0,0 +1,986 @@
+/*
+ * Analog Devices SPI3 controller driver
+ *
+ * Copyright (c) 2014 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/adi_spi3.h>
+#include <linux/types.h>
+
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+enum adi_spi_state {
+	START_STATE,
+	RUNNING_STATE,
+	DONE_STATE,
+	ERROR_STATE
+};
+
+struct adi_spi_master;
+
+struct adi_spi_transfer_ops {
+	void (*write) (struct adi_spi_master *);
+	void (*read) (struct adi_spi_master *);
+	void (*duplex) (struct adi_spi_master *);
+};
+
+/* runtime info for spi master */
+struct adi_spi_master {
+	/* SPI framework hookup */
+	struct spi_master *master;
+
+	/* Regs base of SPI controller */
+	struct adi_spi_regs __iomem *regs;
+
+	/* Pin request list */
+	u16 *pin_req;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message *cur_msg;
+	struct spi_transfer *cur_transfer;
+	struct adi_spi_device *cur_chip;
+	unsigned transfer_len;
+
+	/* transfer buffer */
+	void *tx;
+	void *tx_end;
+	void *rx;
+	void *rx_end;
+
+	/* dma info */
+	unsigned int tx_dma;
+	unsigned int rx_dma;
+	dma_addr_t tx_dma_addr;
+	dma_addr_t rx_dma_addr;
+	unsigned long dummy_buffer; /* used in unidirectional transfer */
+	unsigned long tx_dma_size;
+	unsigned long rx_dma_size;
+	int tx_num;
+	int rx_num;
+
+	/* store register value for suspend/resume */
+	u32 control;
+	u32 ssel;
+
+	unsigned long sclk;
+	enum adi_spi_state state;
+
+	const struct adi_spi_transfer_ops *ops;
+};
+
+struct adi_spi_device {
+	u32 control;
+	u32 clock;
+	u32 ssel;
+
+	u8 cs;
+	u16 cs_chg_udelay; /* Some devices require > 255usec delay */
+	u32 cs_gpio;
+	u32 tx_dummy_val; /* tx value for rx only transfer */
+	bool enable_dma;
+	const struct adi_spi_transfer_ops *ops;
+};
+
+static void adi_spi_enable(struct adi_spi_master *drv_data)
+{
+	u32 ctl;
+
+	ctl = ioread32(&drv_data->regs->control);
+	ctl |= SPI_CTL_EN;
+	iowrite32(ctl, &drv_data->regs->control);
+}
+
+static void adi_spi_disable(struct adi_spi_master *drv_data)
+{
+	u32 ctl;
+
+	ctl = ioread32(&drv_data->regs->control);
+	ctl &= ~SPI_CTL_EN;
+	iowrite32(ctl, &drv_data->regs->control);
+}
+
+/* Caculate the SPI_CLOCK register value based on input HZ */
+static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)
+{
+	u32 spi_clock = sclk / speed_hz;
+
+	if (spi_clock)
+		spi_clock--;
+	return spi_clock;
+}
+
+static int adi_spi_flush(struct adi_spi_master *drv_data)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	/* wait for stop and clear stat */
+	while (!(ioread32(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit)
+		cpu_relax();
+
+	iowrite32(0xFFFFFFFF, &drv_data->regs->status);
+
+	return limit;
+}
+
+/* Chip select operation functions for cs_change flag */
+static void adi_spi_cs_active(struct adi_spi_master *drv_data, struct adi_spi_device *chip)
+{
+	if (likely(chip->cs < MAX_CTRL_CS)) {
+		u32 reg;
+		reg = ioread32(&drv_data->regs->ssel);
+		reg &= ~chip->ssel;
+		iowrite32(reg, &drv_data->regs->ssel);
+	} else {
+		gpio_set_value(chip->cs_gpio, 0);
+	}
+}
+
+static void adi_spi_cs_deactive(struct adi_spi_master *drv_data,
+				struct adi_spi_device *chip)
+{
+	if (likely(chip->cs < MAX_CTRL_CS)) {
+		u32 reg;
+		reg = ioread32(&drv_data->regs->ssel);
+		reg |= chip->ssel;
+		iowrite32(reg, &drv_data->regs->ssel);
+	} else {
+		gpio_set_value(chip->cs_gpio, 1);
+	}
+
+	/* Move delay here for consistency */
+	if (chip->cs_chg_udelay)
+		udelay(chip->cs_chg_udelay);
+}
+
+/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
+static inline void adi_spi_cs_enable(struct adi_spi_master *drv_data,
+					struct adi_spi_device *chip)
+{
+	if (chip->cs < MAX_CTRL_CS) {
+		u32 reg;
+		reg = ioread32(&drv_data->regs->ssel);
+		reg |= chip->ssel >> 8;
+		iowrite32(reg, &drv_data->regs->ssel);
+	}
+}
+
+static inline void adi_spi_cs_disable(struct adi_spi_master *drv_data,
+					struct adi_spi_device *chip)
+{
+	if (chip->cs < MAX_CTRL_CS) {
+		u32 reg;
+		reg = ioread32(&drv_data->regs->ssel);
+		reg &= ~(chip->ssel >> 8);
+		iowrite32(reg, &drv_data->regs->ssel);
+	}
+}
+
+/* stop controller and re-config current chip*/
+static void adi_spi_restore_state(struct adi_spi_master *drv_data)
+{
+	struct adi_spi_device *chip = drv_data->cur_chip;
+
+	/* Clear status and disable clock */
+	iowrite32(0xFFFFFFFF, &drv_data->regs->status);
+	iowrite32(0x0, &drv_data->regs->rx_control);
+	iowrite32(0x0, &drv_data->regs->tx_control);
+	adi_spi_disable(drv_data);
+
+	/* Load the registers */
+	iowrite32(chip->control, &drv_data->regs->control);
+	iowrite32(chip->clock, &drv_data->regs->clock);
+
+	adi_spi_enable(drv_data);
+	drv_data->tx_num = drv_data->rx_num = 0;
+	/* we always choose tx transfer initiate */
+	iowrite32(SPI_RXCTL_REN, &drv_data->regs->rx_control);
+	iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &drv_data->regs->tx_control);
+	adi_spi_cs_active(drv_data, chip);
+}
+
+/* discard invalid rx data and empty rfifo */
+static inline void dummy_read(struct adi_spi_master *drv_data)
+{
+	while (!(ioread32(&drv_data->regs->status) & SPI_STAT_RFE))
+		ioread32(&drv_data->regs->rfifo);
+}
+
+static void adi_spi_u8_write(struct adi_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->tx < drv_data->tx_end) {
+		iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo);
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		ioread32(&drv_data->regs->rfifo);
+	}
+}
+
+static void adi_spi_u8_read(struct adi_spi_master *drv_data)
+{
+	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		iowrite32(tx_val, &drv_data->regs->tfifo);
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo);
+	}
+}
+
+static void adi_spi_u8_duplex(struct adi_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo);
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo);
+	}
+}
+
+static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u8 = {
+	.write  = adi_spi_u8_write,
+	.read   = adi_spi_u8_read,
+	.duplex = adi_spi_u8_duplex,
+};
+
+static void adi_spi_u16_write(struct adi_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->tx < drv_data->tx_end) {
+		iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo);
+		drv_data->tx += 2;
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		ioread32(&drv_data->regs->rfifo);
+	}
+}
+
+static void adi_spi_u16_read(struct adi_spi_master *drv_data)
+{
+	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		iowrite32(tx_val, &drv_data->regs->tfifo);
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
+		drv_data->rx += 2;
+	}
+}
+
+static void adi_spi_u16_duplex(struct adi_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo);
+		drv_data->tx += 2;
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
+		drv_data->rx += 2;
+	}
+}
+
+static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u16 = {
+	.write  = adi_spi_u16_write,
+	.read   = adi_spi_u16_read,
+	.duplex = adi_spi_u16_duplex,
+};
+
+static void adi_spi_u32_write(struct adi_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->tx < drv_data->tx_end) {
+		iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo);
+		drv_data->tx += 4;
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		ioread32(&drv_data->regs->rfifo);
+	}
+}
+
+static void adi_spi_u32_read(struct adi_spi_master *drv_data)
+{
+	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		iowrite32(tx_val, &drv_data->regs->tfifo);
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
+		drv_data->rx += 4;
+	}
+}
+
+static void adi_spi_u32_duplex(struct adi_spi_master *drv_data)
+{
+	dummy_read(drv_data);
+	while (drv_data->rx < drv_data->rx_end) {
+		iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo);
+		drv_data->tx += 4;
+		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
+			cpu_relax();
+		*(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
+		drv_data->rx += 4;
+	}
+}
+
+static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u32 = {
+	.write  = adi_spi_u32_write,
+	.read   = adi_spi_u32_read,
+	.duplex = adi_spi_u32_duplex,
+};
+
+
+/* test if there is more transfer to be done */
+static void adi_spi_next_transfer(struct adi_spi_master *drv)
+{
+	struct spi_message *msg = drv->cur_msg;
+	struct spi_transfer *t = drv->cur_transfer;
+
+	/* Move to next transfer */
+	if (t->transfer_list.next != &msg->transfers) {
+		drv->cur_transfer = list_entry(t->transfer_list.next,
+			       struct spi_transfer, transfer_list);
+		drv->state = RUNNING_STATE;
+	} else {
+		drv->state = DONE_STATE;
+		drv->cur_transfer = NULL;
+	}
+}
+
+static void adi_spi_giveback(struct adi_spi_master *drv_data)
+{
+	struct adi_spi_device *chip = drv_data->cur_chip;
+
+	adi_spi_cs_deactive(drv_data, chip);
+	spi_finalize_current_message(drv_data->master);
+}
+
+static int adi_spi_setup_transfer(struct adi_spi_master *drv)
+{
+	struct spi_transfer *t = drv->cur_transfer;
+	u32 cr, cr_width;
+
+	if (t->tx_buf) {
+		drv->tx = (void *)t->tx_buf;
+		drv->tx_end = drv->tx + t->len;
+	} else {
+		drv->tx = NULL;
+	}
+
+	if (t->rx_buf) {
+		drv->rx = t->rx_buf;
+		drv->rx_end = drv->rx + t->len;
+	} else {
+		drv->rx = NULL;
+	}
+
+	drv->transfer_len = t->len;
+
+	/* bits per word setup */
+	switch (t->bits_per_word) {
+	case 8:
+		cr_width = SPI_CTL_SIZE08;
+		drv->ops = &adi_spi_transfer_ops_u8;
+		break;
+	case 16:
+		cr_width = SPI_CTL_SIZE16;
+		drv->ops = &adi_spi_transfer_ops_u16;
+		break;
+	case 32:
+		cr_width = SPI_CTL_SIZE32;
+		drv->ops = &adi_spi_transfer_ops_u32;
+		break;
+	default:
+		return -EINVAL;
+	}
+	cr = ioread32(&drv->regs->control) & ~SPI_CTL_SIZE;
+	cr |= cr_width;
+	iowrite32(cr, &drv->regs->control);
+
+	/* speed setup */
+	iowrite32(hz_to_spi_clock(drv->sclk, t->speed_hz), &drv->regs->clock);
+	return 0;
+}
+
+static int adi_spi_dma_xfer(struct adi_spi_master *drv_data)
+{
+	struct spi_transfer *t = drv_data->cur_transfer;
+	struct spi_message *msg = drv_data->cur_msg;
+	struct adi_spi_device *chip = drv_data->cur_chip;
+	u32 dma_config;
+	unsigned long word_count, word_size;
+	void *tx_buf, *rx_buf;
+
+	switch (t->bits_per_word) {
+	case 8:
+		dma_config = WDSIZE_8 | PSIZE_8;
+		word_count = drv_data->transfer_len;
+		word_size = 1;
+		break;
+	case 16:
+		dma_config = WDSIZE_16 | PSIZE_16;
+		word_count = drv_data->transfer_len / 2;
+		word_size = 2;
+		break;
+	default:
+		dma_config = WDSIZE_32 | PSIZE_32;
+		word_count = drv_data->transfer_len / 4;
+		word_size = 4;
+		break;
+	}
+
+	if (!drv_data->rx) {
+		tx_buf = drv_data->tx;
+		rx_buf = &drv_data->dummy_buffer;
+		drv_data->tx_dma_size = drv_data->transfer_len;
+		drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer);
+		set_dma_x_modify(drv_data->tx_dma, word_size);
+		set_dma_x_modify(drv_data->rx_dma, 0);
+	} else if (!drv_data->tx) {
+		drv_data->dummy_buffer = chip->tx_dummy_val;
+		tx_buf = &drv_data->dummy_buffer;
+		rx_buf = drv_data->rx;
+		drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer);
+		drv_data->rx_dma_size = drv_data->transfer_len;
+		set_dma_x_modify(drv_data->tx_dma, 0);
+		set_dma_x_modify(drv_data->rx_dma, word_size);
+	} else {
+		tx_buf = drv_data->tx;
+		rx_buf = drv_data->rx;
+		drv_data->tx_dma_size = drv_data->rx_dma_size
+					= drv_data->transfer_len;
+		set_dma_x_modify(drv_data->tx_dma, word_size);
+		set_dma_x_modify(drv_data->rx_dma, word_size);
+	}
+
+	drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev,
+				(void *)tx_buf,
+				drv_data->tx_dma_size,
+				DMA_TO_DEVICE);
+	if (dma_mapping_error(&msg->spi->dev,
+				drv_data->tx_dma_addr))
+		return -ENOMEM;
+
+	drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev,
+				(void *)rx_buf,
+				drv_data->rx_dma_size,
+				DMA_FROM_DEVICE);
+	if (dma_mapping_error(&msg->spi->dev,
+				drv_data->rx_dma_addr)) {
+		dma_unmap_single(&msg->spi->dev,
+				drv_data->tx_dma_addr,
+				drv_data->tx_dma_size,
+				DMA_TO_DEVICE);
+		return -ENOMEM;
+	}
+
+	dummy_read(drv_data);
+	set_dma_x_count(drv_data->tx_dma, word_count);
+	set_dma_x_count(drv_data->rx_dma, word_count);
+	set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr);
+	set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr);
+	dma_config |= DMAFLOW_STOP | RESTART | DI_EN;
+	set_dma_config(drv_data->tx_dma, dma_config);
+	set_dma_config(drv_data->rx_dma, dma_config | WNR);
+	enable_dma(drv_data->tx_dma);
+	enable_dma(drv_data->rx_dma);
+
+	iowrite32(SPI_RXCTL_REN | SPI_RXCTL_RDR_NE,
+			&drv_data->regs->rx_control);
+	iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF,
+			&drv_data->regs->tx_control);
+
+	return 0;
+}
+
+static int adi_spi_pio_xfer(struct adi_spi_master *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+
+	if (!drv_data->rx) {
+		/* write only half duplex */
+		drv_data->ops->write(drv_data);
+		if (drv_data->tx != drv_data->tx_end)
+			return -EIO;
+	} else if (!drv_data->tx) {
+		/* read only half duplex */
+		drv_data->ops->read(drv_data);
+		if (drv_data->rx != drv_data->rx_end)
+			return -EIO;
+	} else {
+		/* full duplex mode */
+		drv_data->ops->duplex(drv_data);
+		if (drv_data->tx != drv_data->tx_end)
+			return -EIO;
+	}
+
+	if (!adi_spi_flush(drv_data))
+		return -EIO;
+	msg->actual_length += drv_data->transfer_len;
+	tasklet_schedule(&drv_data->pump_transfers);
+	return 0;
+}
+
+static void adi_spi_pump_transfers(unsigned long data)
+{
+	struct adi_spi_master *drv_data = (struct adi_spi_master *)data;
+	struct spi_message *msg = NULL;
+	struct spi_transfer *t = NULL;
+	struct adi_spi_device *chip = NULL;
+	int ret;
+
+	/* Get current state information */
+	msg = drv_data->cur_msg;
+	t = drv_data->cur_transfer;
+	chip = drv_data->cur_chip;
+
+	/* Handle for abort */
+	if (drv_data->state == ERROR_STATE) {
+		msg->status = -EIO;
+		adi_spi_giveback(drv_data);
+		return;
+	}
+
+	if (drv_data->state == RUNNING_STATE) {
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+		if (t->cs_change)
+			adi_spi_cs_deactive(drv_data, chip);
+		adi_spi_next_transfer(drv_data);
+		t = drv_data->cur_transfer;
+	}
+	/* Handle end of message */
+	if (drv_data->state == DONE_STATE) {
+		msg->status = 0;
+		adi_spi_giveback(drv_data);
+		return;
+	}
+
+	if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) {
+		/* Schedule next transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+		return;
+	}
+
+	ret = adi_spi_setup_transfer(drv_data);
+	if (ret) {
+		msg->status = ret;
+		adi_spi_giveback(drv_data);
+	}
+
+	iowrite32(0xFFFFFFFF, &drv_data->regs->status);
+	adi_spi_cs_active(drv_data, chip);
+	drv_data->state = RUNNING_STATE;
+
+	if (chip->enable_dma)
+		ret = adi_spi_dma_xfer(drv_data);
+	else
+		ret = adi_spi_pio_xfer(drv_data);
+	if (ret) {
+		msg->status = ret;
+		adi_spi_giveback(drv_data);
+	}
+}
+
+static int adi_spi_transfer_one_message(struct spi_master *master,
+					struct spi_message *m)
+{
+	struct adi_spi_master *drv_data = spi_master_get_devdata(master);
+
+	drv_data->cur_msg = m;
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+	adi_spi_restore_state(drv_data);
+
+	drv_data->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+					    struct spi_transfer, transfer_list);
+
+	tasklet_schedule(&drv_data->pump_transfers);
+	return 0;
+}
+
+#define MAX_SPI_SSEL	7
+
+static const u16 ssel[][MAX_SPI_SSEL] = {
+	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
+	P_SPI0_SSEL4, P_SPI0_SSEL5,
+	P_SPI0_SSEL6, P_SPI0_SSEL7},
+
+	{P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
+	P_SPI1_SSEL4, P_SPI1_SSEL5,
+	P_SPI1_SSEL6, P_SPI1_SSEL7},
+
+	{P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
+	P_SPI2_SSEL4, P_SPI2_SSEL5,
+	P_SPI2_SSEL6, P_SPI2_SSEL7},
+};
+
+static int adi_spi_setup(struct spi_device *spi)
+{
+	struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master);
+	struct adi_spi_device *chip = spi_get_ctldata(spi);
+	u32 ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;
+	int ret = -EINVAL;
+
+	if (!chip) {
+		struct adi_spi3_chip *chip_info = spi->controller_data;
+
+		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev, "can not allocate chip data\n");
+			return -ENOMEM;
+		}
+		if (chip_info) {
+			if (chip_info->control & ~ctl_reg) {
+				dev_err(&spi->dev,
+					"do not set bits that the SPI framework manages\n");
+				goto error;
+			}
+			chip->control = chip_info->control;
+			chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+			chip->tx_dummy_val = chip_info->tx_dummy_val;
+			chip->enable_dma = chip_info->enable_dma;
+		}
+		chip->cs = spi->chip_select;
+
+		if (chip->cs < MAX_CTRL_CS) {
+			chip->ssel = (1 << chip->cs) << 8;
+			ret = peripheral_request(ssel[spi->master->bus_num]
+					[chip->cs-1], dev_name(&spi->dev));
+			if (ret) {
+				dev_err(&spi->dev, "peripheral_request() error\n");
+				goto error;
+			}
+		} else {
+			chip->cs_gpio = chip->cs - MAX_CTRL_CS;
+			ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH,
+						dev_name(&spi->dev));
+			if (ret) {
+				dev_err(&spi->dev, "gpio_request_one() error\n");
+				goto error;
+			}
+		}
+		spi_set_ctldata(spi, chip);
+	}
+
+	/* force a default base state */
+	chip->control &= ctl_reg;
+
+	if (spi->mode & SPI_CPOL)
+		chip->control |= SPI_CTL_CPOL;
+	if (spi->mode & SPI_CPHA)
+		chip->control |= SPI_CTL_CPHA;
+	if (spi->mode & SPI_LSB_FIRST)
+		chip->control |= SPI_CTL_LSBF;
+	chip->control |= SPI_CTL_MSTR;
+	/* we choose software to controll cs */
+	chip->control &= ~SPI_CTL_ASSEL;
+
+	chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz);
+
+	adi_spi_cs_enable(drv_data, chip);
+	adi_spi_cs_deactive(drv_data, chip);
+
+	return 0;
+error:
+	if (chip) {
+		kfree(chip);
+		spi_set_ctldata(spi, NULL);
+	}
+
+	return ret;
+}
+
+static void adi_spi_cleanup(struct spi_device *spi)
+{
+	struct adi_spi_device *chip = spi_get_ctldata(spi);
+	struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master);
+
+	if (!chip)
+		return;
+
+	if (chip->cs < MAX_CTRL_CS) {
+		peripheral_free(ssel[spi->master->bus_num]
+					[chip->cs-1]);
+		adi_spi_cs_disable(drv_data, chip);
+	} else {
+		gpio_free(chip->cs_gpio);
+	}
+
+	kfree(chip);
+	spi_set_ctldata(spi, NULL);
+}
+
+static irqreturn_t adi_spi_tx_dma_isr(int irq, void *dev_id)
+{
+	struct adi_spi_master *drv_data = dev_id;
+	u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma);
+	u32 tx_ctl;
+
+	clear_dma_irqstat(drv_data->tx_dma);
+	if (dma_stat & DMA_DONE) {
+		drv_data->tx_num++;
+	} else {
+		dev_err(&drv_data->master->dev,
+				"spi tx dma error: %d\n", dma_stat);
+		if (drv_data->tx)
+			drv_data->state = ERROR_STATE;
+	}
+	tx_ctl = ioread32(&drv_data->regs->tx_control);
+	tx_ctl &= ~SPI_TXCTL_TDR_NF;
+	iowrite32(tx_ctl, &drv_data->regs->tx_control);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t adi_spi_rx_dma_isr(int irq, void *dev_id)
+{
+	struct adi_spi_master *drv_data = dev_id;
+	struct spi_message *msg = drv_data->cur_msg;
+	u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma);
+
+	clear_dma_irqstat(drv_data->rx_dma);
+	if (dma_stat & DMA_DONE) {
+		drv_data->rx_num++;
+		/* we may fail on tx dma */
+		if (drv_data->state != ERROR_STATE)
+			msg->actual_length += drv_data->transfer_len;
+	} else {
+		drv_data->state = ERROR_STATE;
+		dev_err(&drv_data->master->dev,
+				"spi rx dma error: %d\n", dma_stat);
+	}
+	iowrite32(0, &drv_data->regs->tx_control);
+	iowrite32(0, &drv_data->regs->rx_control);
+	if (drv_data->rx_num != drv_data->tx_num)
+		dev_dbg(&drv_data->master->dev,
+				"dma interrupt missing: tx=%d,rx=%d\n",
+				drv_data->tx_num, drv_data->rx_num);
+	tasklet_schedule(&drv_data->pump_transfers);
+	return IRQ_HANDLED;
+}
+
+static int adi_spi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct adi_spi3_master *info = dev_get_platdata(dev);
+	struct spi_master *master;
+	struct adi_spi_master *drv_data;
+	struct resource *mem, *res;
+	unsigned int tx_dma, rx_dma;
+	struct clk *sclk;
+	int ret;
+
+	if (!info) {
+		dev_err(dev, "platform data missing!\n");
+		return -ENODEV;
+	}
+
+	sclk = devm_clk_get(dev, "spi");
+	if (IS_ERR(sclk)) {
+		dev_err(dev, "can not get spi clock\n");
+		return PTR_ERR(sclk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!res) {
+		dev_err(dev, "can not get tx dma resource\n");
+		return -ENXIO;
+	}
+	tx_dma = res->start;
+
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!res) {
+		dev_err(dev, "can not get rx dma resource\n");
+		return -ENXIO;
+	}
+	rx_dma = res->start;
+
+	/* allocate master with space for drv_data */
+	master = spi_alloc_master(dev, sizeof(*drv_data));
+	if (!master) {
+		dev_err(dev, "can not alloc spi_master\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, master);
+
+	/* the mode bits supported by this driver */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = info->num_chipselect;
+	master->cleanup = adi_spi_cleanup;
+	master->setup = adi_spi_setup;
+	master->transfer_one_message = adi_spi_transfer_one_message;
+	master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
+				     SPI_BPW_MASK(8);
+
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->tx_dma = tx_dma;
+	drv_data->rx_dma = rx_dma;
+	drv_data->pin_req = info->pin_req;
+	drv_data->sclk = clk_get_rate(sclk);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	drv_data->regs = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(drv_data->regs)) {
+		ret = PTR_ERR(drv_data->regs);
+		goto err_put_master;
+	}
+
+	/* request tx and rx dma */
+	ret = request_dma(tx_dma, "SPI_TX_DMA");
+	if (ret) {
+		dev_err(dev, "can not request SPI TX DMA channel\n");
+		goto err_put_master;
+	}
+	set_dma_callback(tx_dma, adi_spi_tx_dma_isr, drv_data);
+
+	ret = request_dma(rx_dma, "SPI_RX_DMA");
+	if (ret) {
+		dev_err(dev, "can not request SPI RX DMA channel\n");
+		goto err_free_tx_dma;
+	}
+	set_dma_callback(drv_data->rx_dma, adi_spi_rx_dma_isr, drv_data);
+
+	/* request CLK, MOSI and MISO */
+	ret = peripheral_request_list(drv_data->pin_req, "adi-spi3");
+	if (ret < 0) {
+		dev_err(dev, "can not request spi pins\n");
+		goto err_free_rx_dma;
+	}
+
+	iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control);
+	iowrite32(0x0000FE00, &drv_data->regs->ssel);
+	iowrite32(0x0, &drv_data->regs->delay);
+
+	tasklet_init(&drv_data->pump_transfers,
+			adi_spi_pump_transfers, (unsigned long)drv_data);
+	/* register with the SPI framework */
+	ret = devm_spi_register_master(dev, master);
+	if (ret) {
+		dev_err(dev, "can not  register spi master\n");
+		goto err_free_peripheral;
+	}
+
+	return ret;
+
+err_free_peripheral:
+	peripheral_free_list(drv_data->pin_req);
+err_free_rx_dma:
+	free_dma(rx_dma);
+err_free_tx_dma:
+	free_dma(tx_dma);
+err_put_master:
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int adi_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct adi_spi_master *drv_data = spi_master_get_devdata(master);
+
+	adi_spi_disable(drv_data);
+	peripheral_free_list(drv_data->pin_req);
+	free_dma(drv_data->rx_dma);
+	free_dma(drv_data->tx_dma);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int adi_spi_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct adi_spi_master *drv_data = spi_master_get_devdata(master);
+
+	spi_master_suspend(master);
+
+	drv_data->control = ioread32(&drv_data->regs->control);
+	drv_data->ssel = ioread32(&drv_data->regs->ssel);
+
+	iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control);
+	iowrite32(0x0000FE00, &drv_data->regs->ssel);
+	dma_disable_irq(drv_data->rx_dma);
+	dma_disable_irq(drv_data->tx_dma);
+
+	return 0;
+}
+
+static int adi_spi_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct adi_spi_master *drv_data = spi_master_get_devdata(master);
+	int ret = 0;
+
+	/* bootrom may modify spi and dma status when resume in spi boot mode */
+	disable_dma(drv_data->rx_dma);
+
+	dma_enable_irq(drv_data->rx_dma);
+	dma_enable_irq(drv_data->tx_dma);
+	iowrite32(drv_data->control, &drv_data->regs->control);
+	iowrite32(drv_data->ssel, &drv_data->regs->ssel);
+
+	ret = spi_master_resume(master);
+	if (ret) {
+		free_dma(drv_data->rx_dma);
+		free_dma(drv_data->tx_dma);
+	}
+
+	return ret;
+}
+#endif
+static const struct dev_pm_ops adi_spi_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(adi_spi_suspend, adi_spi_resume)
+};
+
+MODULE_ALIAS("platform:adi-spi3");
+static struct platform_driver adi_spi_driver = {
+	.driver	= {
+		.name	= "adi-spi3",
+		.owner	= THIS_MODULE,
+		.pm     = &adi_spi_pm_ops,
+	},
+	.remove		= adi_spi_remove,
+};
+
+module_platform_driver_probe(adi_spi_driver, adi_spi_probe);
+
+MODULE_DESCRIPTION("Analog Devices SPI3 controller driver");
+MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 3898b0b9ee77..058db0fe8dc7 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/spi/spi.h>
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 8005f9869481..485e6cce94bf 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -224,7 +224,7 @@ struct atmel_spi {
 	struct platform_device	*pdev;
 
 	struct spi_transfer	*current_transfer;
-	unsigned long		current_remaining_bytes;
+	int			current_remaining_bytes;
 	int			done_status;
 
 	struct completion	xfer_completion;
@@ -1110,6 +1110,8 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 				atmel_spi_next_xfer_pio(master, xfer);
 			} else {
 				as->current_remaining_bytes -= len;
+				if (as->current_remaining_bytes < 0)
+					as->current_remaining_bytes = 0;
 			}
 		} else {
 			atmel_spi_next_xfer_pio(master, xfer);
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index 5a211e98383b..86f5a98aa7a2 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -18,7 +18,6 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/spi/spi.h>
-#include <linux/workqueue.h>
 #include <linux/mutex.h>
 
 #define HSSPI_GLOBAL_CTRL_REG			0x0
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 0250fa721cea..8510400e7867 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -29,7 +29,6 @@
 #include <linux/spi/spi.h>
 #include <linux/completion.h>
 #include <linux/err.h>
-#include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
 
 #include <bcm63xx_dev_spi.h>
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c
deleted file mode 100644
index 4089d0e0d84e..000000000000
--- a/drivers/spi/spi-bfin-v3.c
+++ /dev/null
@@ -1,965 +0,0 @@
-/*
- * Analog Devices SPI3 controller driver
- *
- * Copyright (c) 2013 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/types.h>
-
-#include <asm/bfin_spi3.h>
-#include <asm/cacheflush.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-
-enum bfin_spi_state {
-	START_STATE,
-	RUNNING_STATE,
-	DONE_STATE,
-	ERROR_STATE
-};
-
-struct bfin_spi_master;
-
-struct bfin_spi_transfer_ops {
-	void (*write) (struct bfin_spi_master *);
-	void (*read) (struct bfin_spi_master *);
-	void (*duplex) (struct bfin_spi_master *);
-};
-
-/* runtime info for spi master */
-struct bfin_spi_master {
-	/* SPI framework hookup */
-	struct spi_master *master;
-
-	/* Regs base of SPI controller */
-	struct bfin_spi_regs __iomem *regs;
-
-	/* Pin request list */
-	u16 *pin_req;
-
-	/* Message Transfer pump */
-	struct tasklet_struct pump_transfers;
-
-	/* Current message transfer state info */
-	struct spi_message *cur_msg;
-	struct spi_transfer *cur_transfer;
-	struct bfin_spi_device *cur_chip;
-	unsigned transfer_len;
-
-	/* transfer buffer */
-	void *tx;
-	void *tx_end;
-	void *rx;
-	void *rx_end;
-
-	/* dma info */
-	unsigned int tx_dma;
-	unsigned int rx_dma;
-	dma_addr_t tx_dma_addr;
-	dma_addr_t rx_dma_addr;
-	unsigned long dummy_buffer; /* used in unidirectional transfer */
-	unsigned long tx_dma_size;
-	unsigned long rx_dma_size;
-	int tx_num;
-	int rx_num;
-
-	/* store register value for suspend/resume */
-	u32 control;
-	u32 ssel;
-
-	unsigned long sclk;
-	enum bfin_spi_state state;
-
-	const struct bfin_spi_transfer_ops *ops;
-};
-
-struct bfin_spi_device {
-	u32 control;
-	u32 clock;
-	u32 ssel;
-
-	u8 cs;
-	u16 cs_chg_udelay; /* Some devices require > 255usec delay */
-	u32 cs_gpio;
-	u32 tx_dummy_val; /* tx value for rx only transfer */
-	bool enable_dma;
-	const struct bfin_spi_transfer_ops *ops;
-};
-
-static void bfin_spi_enable(struct bfin_spi_master *drv_data)
-{
-	bfin_write_or(&drv_data->regs->control, SPI_CTL_EN);
-}
-
-static void bfin_spi_disable(struct bfin_spi_master *drv_data)
-{
-	bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN);
-}
-
-/* Caculate the SPI_CLOCK register value based on input HZ */
-static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)
-{
-	u32 spi_clock = sclk / speed_hz;
-
-	if (spi_clock)
-		spi_clock--;
-	return spi_clock;
-}
-
-static int bfin_spi_flush(struct bfin_spi_master *drv_data)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	/* wait for stop and clear stat */
-	while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit)
-		cpu_relax();
-
-	bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
-
-	return limit;
-}
-
-/* Chip select operation functions for cs_change flag */
-static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip)
-{
-	if (likely(chip->cs < MAX_CTRL_CS))
-		bfin_write_and(&drv_data->regs->ssel, ~chip->ssel);
-	else
-		gpio_set_value(chip->cs_gpio, 0);
-}
-
-static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data,
-				struct bfin_spi_device *chip)
-{
-	if (likely(chip->cs < MAX_CTRL_CS))
-		bfin_write_or(&drv_data->regs->ssel, chip->ssel);
-	else
-		gpio_set_value(chip->cs_gpio, 1);
-
-	/* Move delay here for consistency */
-	if (chip->cs_chg_udelay)
-		udelay(chip->cs_chg_udelay);
-}
-
-/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
-static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data,
-					struct bfin_spi_device *chip)
-{
-	if (chip->cs < MAX_CTRL_CS)
-		bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8);
-}
-
-static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data,
-					struct bfin_spi_device *chip)
-{
-	if (chip->cs < MAX_CTRL_CS)
-		bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8));
-}
-
-/* stop controller and re-config current chip*/
-static void bfin_spi_restore_state(struct bfin_spi_master *drv_data)
-{
-	struct bfin_spi_device *chip = drv_data->cur_chip;
-
-	/* Clear status and disable clock */
-	bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
-	bfin_write(&drv_data->regs->rx_control, 0x0);
-	bfin_write(&drv_data->regs->tx_control, 0x0);
-	bfin_spi_disable(drv_data);
-
-	SSYNC();
-
-	/* Load the registers */
-	bfin_write(&drv_data->regs->control, chip->control);
-	bfin_write(&drv_data->regs->clock, chip->clock);
-
-	bfin_spi_enable(drv_data);
-	drv_data->tx_num = drv_data->rx_num = 0;
-	/* we always choose tx transfer initiate */
-	bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN);
-	bfin_write(&drv_data->regs->tx_control,
-			SPI_TXCTL_TEN | SPI_TXCTL_TTI);
-	bfin_spi_cs_active(drv_data, chip);
-}
-
-/* discard invalid rx data and empty rfifo */
-static inline void dummy_read(struct bfin_spi_master *drv_data)
-{
-	while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE))
-		bfin_read(&drv_data->regs->rfifo);
-}
-
-static void bfin_spi_u8_write(struct bfin_spi_master *drv_data)
-{
-	dummy_read(drv_data);
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		bfin_read(&drv_data->regs->rfifo);
-	}
-}
-
-static void bfin_spi_u8_read(struct bfin_spi_master *drv_data)
-{
-	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
-
-	dummy_read(drv_data);
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tfifo, tx_val);
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
-	}
-}
-
-static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data)
-{
-	dummy_read(drv_data);
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
-	}
-}
-
-static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
-	.write  = bfin_spi_u8_write,
-	.read   = bfin_spi_u8_read,
-	.duplex = bfin_spi_u8_duplex,
-};
-
-static void bfin_spi_u16_write(struct bfin_spi_master *drv_data)
-{
-	dummy_read(drv_data);
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
-		drv_data->tx += 2;
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		bfin_read(&drv_data->regs->rfifo);
-	}
-}
-
-static void bfin_spi_u16_read(struct bfin_spi_master *drv_data)
-{
-	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
-
-	dummy_read(drv_data);
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tfifo, tx_val);
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
-		drv_data->rx += 2;
-	}
-}
-
-static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data)
-{
-	dummy_read(drv_data);
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
-		drv_data->tx += 2;
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
-		drv_data->rx += 2;
-	}
-}
-
-static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
-	.write  = bfin_spi_u16_write,
-	.read   = bfin_spi_u16_read,
-	.duplex = bfin_spi_u16_duplex,
-};
-
-static void bfin_spi_u32_write(struct bfin_spi_master *drv_data)
-{
-	dummy_read(drv_data);
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
-		drv_data->tx += 4;
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		bfin_read(&drv_data->regs->rfifo);
-	}
-}
-
-static void bfin_spi_u32_read(struct bfin_spi_master *drv_data)
-{
-	u32 tx_val = drv_data->cur_chip->tx_dummy_val;
-
-	dummy_read(drv_data);
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tfifo, tx_val);
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
-		drv_data->rx += 4;
-	}
-}
-
-static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data)
-{
-	dummy_read(drv_data);
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
-		drv_data->tx += 4;
-		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
-			cpu_relax();
-		*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
-		drv_data->rx += 4;
-	}
-}
-
-static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = {
-	.write  = bfin_spi_u32_write,
-	.read   = bfin_spi_u32_read,
-	.duplex = bfin_spi_u32_duplex,
-};
-
-
-/* test if there is more transfer to be done */
-static void bfin_spi_next_transfer(struct bfin_spi_master *drv)
-{
-	struct spi_message *msg = drv->cur_msg;
-	struct spi_transfer *t = drv->cur_transfer;
-
-	/* Move to next transfer */
-	if (t->transfer_list.next != &msg->transfers) {
-		drv->cur_transfer = list_entry(t->transfer_list.next,
-			       struct spi_transfer, transfer_list);
-		drv->state = RUNNING_STATE;
-	} else {
-		drv->state = DONE_STATE;
-		drv->cur_transfer = NULL;
-	}
-}
-
-static void bfin_spi_giveback(struct bfin_spi_master *drv_data)
-{
-	struct bfin_spi_device *chip = drv_data->cur_chip;
-
-	bfin_spi_cs_deactive(drv_data, chip);
-	spi_finalize_current_message(drv_data->master);
-}
-
-static int bfin_spi_setup_transfer(struct bfin_spi_master *drv)
-{
-	struct spi_transfer *t = drv->cur_transfer;
-	u32 cr, cr_width;
-
-	if (t->tx_buf) {
-		drv->tx = (void *)t->tx_buf;
-		drv->tx_end = drv->tx + t->len;
-	} else {
-		drv->tx = NULL;
-	}
-
-	if (t->rx_buf) {
-		drv->rx = t->rx_buf;
-		drv->rx_end = drv->rx + t->len;
-	} else {
-		drv->rx = NULL;
-	}
-
-	drv->transfer_len = t->len;
-
-	/* bits per word setup */
-	switch (t->bits_per_word) {
-	case 8:
-		cr_width = SPI_CTL_SIZE08;
-		drv->ops = &bfin_bfin_spi_transfer_ops_u8;
-		break;
-	case 16:
-		cr_width = SPI_CTL_SIZE16;
-		drv->ops = &bfin_bfin_spi_transfer_ops_u16;
-		break;
-	case 32:
-		cr_width = SPI_CTL_SIZE32;
-		drv->ops = &bfin_bfin_spi_transfer_ops_u32;
-		break;
-	default:
-		return -EINVAL;
-	}
-	cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE;
-	cr |= cr_width;
-	bfin_write(&drv->regs->control, cr);
-
-	/* speed setup */
-	bfin_write(&drv->regs->clock,
-			hz_to_spi_clock(drv->sclk, t->speed_hz));
-	return 0;
-}
-
-static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data)
-{
-	struct spi_transfer *t = drv_data->cur_transfer;
-	struct spi_message *msg = drv_data->cur_msg;
-	struct bfin_spi_device *chip = drv_data->cur_chip;
-	u32 dma_config;
-	unsigned long word_count, word_size;
-	void *tx_buf, *rx_buf;
-
-	switch (t->bits_per_word) {
-	case 8:
-		dma_config = WDSIZE_8 | PSIZE_8;
-		word_count = drv_data->transfer_len;
-		word_size = 1;
-		break;
-	case 16:
-		dma_config = WDSIZE_16 | PSIZE_16;
-		word_count = drv_data->transfer_len / 2;
-		word_size = 2;
-		break;
-	default:
-		dma_config = WDSIZE_32 | PSIZE_32;
-		word_count = drv_data->transfer_len / 4;
-		word_size = 4;
-		break;
-	}
-
-	if (!drv_data->rx) {
-		tx_buf = drv_data->tx;
-		rx_buf = &drv_data->dummy_buffer;
-		drv_data->tx_dma_size = drv_data->transfer_len;
-		drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer);
-		set_dma_x_modify(drv_data->tx_dma, word_size);
-		set_dma_x_modify(drv_data->rx_dma, 0);
-	} else if (!drv_data->tx) {
-		drv_data->dummy_buffer = chip->tx_dummy_val;
-		tx_buf = &drv_data->dummy_buffer;
-		rx_buf = drv_data->rx;
-		drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer);
-		drv_data->rx_dma_size = drv_data->transfer_len;
-		set_dma_x_modify(drv_data->tx_dma, 0);
-		set_dma_x_modify(drv_data->rx_dma, word_size);
-	} else {
-		tx_buf = drv_data->tx;
-		rx_buf = drv_data->rx;
-		drv_data->tx_dma_size = drv_data->rx_dma_size
-					= drv_data->transfer_len;
-		set_dma_x_modify(drv_data->tx_dma, word_size);
-		set_dma_x_modify(drv_data->rx_dma, word_size);
-	}
-
-	drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev,
-				(void *)tx_buf,
-				drv_data->tx_dma_size,
-				DMA_TO_DEVICE);
-	if (dma_mapping_error(&msg->spi->dev,
-				drv_data->tx_dma_addr))
-		return -ENOMEM;
-
-	drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev,
-				(void *)rx_buf,
-				drv_data->rx_dma_size,
-				DMA_FROM_DEVICE);
-	if (dma_mapping_error(&msg->spi->dev,
-				drv_data->rx_dma_addr)) {
-		dma_unmap_single(&msg->spi->dev,
-				drv_data->tx_dma_addr,
-				drv_data->tx_dma_size,
-				DMA_TO_DEVICE);
-		return -ENOMEM;
-	}
-
-	dummy_read(drv_data);
-	set_dma_x_count(drv_data->tx_dma, word_count);
-	set_dma_x_count(drv_data->rx_dma, word_count);
-	set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr);
-	set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr);
-	dma_config |= DMAFLOW_STOP | RESTART | DI_EN;
-	set_dma_config(drv_data->tx_dma, dma_config);
-	set_dma_config(drv_data->rx_dma, dma_config | WNR);
-	enable_dma(drv_data->tx_dma);
-	enable_dma(drv_data->rx_dma);
-	SSYNC();
-
-	bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE);
-	SSYNC();
-	bfin_write(&drv_data->regs->tx_control,
-			SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF);
-
-	return 0;
-}
-
-static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data)
-{
-	struct spi_message *msg = drv_data->cur_msg;
-
-	if (!drv_data->rx) {
-		/* write only half duplex */
-		drv_data->ops->write(drv_data);
-		if (drv_data->tx != drv_data->tx_end)
-			return -EIO;
-	} else if (!drv_data->tx) {
-		/* read only half duplex */
-		drv_data->ops->read(drv_data);
-		if (drv_data->rx != drv_data->rx_end)
-			return -EIO;
-	} else {
-		/* full duplex mode */
-		drv_data->ops->duplex(drv_data);
-		if (drv_data->tx != drv_data->tx_end)
-			return -EIO;
-	}
-
-	if (!bfin_spi_flush(drv_data))
-		return -EIO;
-	msg->actual_length += drv_data->transfer_len;
-	tasklet_schedule(&drv_data->pump_transfers);
-	return 0;
-}
-
-static void bfin_spi_pump_transfers(unsigned long data)
-{
-	struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data;
-	struct spi_message *msg = NULL;
-	struct spi_transfer *t = NULL;
-	struct bfin_spi_device *chip = NULL;
-	int ret;
-
-	/* Get current state information */
-	msg = drv_data->cur_msg;
-	t = drv_data->cur_transfer;
-	chip = drv_data->cur_chip;
-
-	/* Handle for abort */
-	if (drv_data->state == ERROR_STATE) {
-		msg->status = -EIO;
-		bfin_spi_giveback(drv_data);
-		return;
-	}
-
-	if (drv_data->state == RUNNING_STATE) {
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-		if (t->cs_change)
-			bfin_spi_cs_deactive(drv_data, chip);
-		bfin_spi_next_transfer(drv_data);
-		t = drv_data->cur_transfer;
-	}
-	/* Handle end of message */
-	if (drv_data->state == DONE_STATE) {
-		msg->status = 0;
-		bfin_spi_giveback(drv_data);
-		return;
-	}
-
-	if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) {
-		/* Schedule next transfer tasklet */
-		tasklet_schedule(&drv_data->pump_transfers);
-		return;
-	}
-
-	ret = bfin_spi_setup_transfer(drv_data);
-	if (ret) {
-		msg->status = ret;
-		bfin_spi_giveback(drv_data);
-	}
-
-	bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
-	bfin_spi_cs_active(drv_data, chip);
-	drv_data->state = RUNNING_STATE;
-
-	if (chip->enable_dma)
-		ret = bfin_spi_dma_xfer(drv_data);
-	else
-		ret = bfin_spi_pio_xfer(drv_data);
-	if (ret) {
-		msg->status = ret;
-		bfin_spi_giveback(drv_data);
-	}
-}
-
-static int bfin_spi_transfer_one_message(struct spi_master *master,
-					struct spi_message *m)
-{
-	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
-
-	drv_data->cur_msg = m;
-	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-	bfin_spi_restore_state(drv_data);
-
-	drv_data->state = START_STATE;
-	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
-					    struct spi_transfer, transfer_list);
-
-	tasklet_schedule(&drv_data->pump_transfers);
-	return 0;
-}
-
-#define MAX_SPI_SSEL	7
-
-static const u16 ssel[][MAX_SPI_SSEL] = {
-	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
-	P_SPI0_SSEL4, P_SPI0_SSEL5,
-	P_SPI0_SSEL6, P_SPI0_SSEL7},
-
-	{P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
-	P_SPI1_SSEL4, P_SPI1_SSEL5,
-	P_SPI1_SSEL6, P_SPI1_SSEL7},
-
-	{P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
-	P_SPI2_SSEL4, P_SPI2_SSEL5,
-	P_SPI2_SSEL6, P_SPI2_SSEL7},
-};
-
-static int bfin_spi_setup(struct spi_device *spi)
-{
-	struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
-	struct bfin_spi_device *chip = spi_get_ctldata(spi);
-	u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;
-	int ret = -EINVAL;
-
-	if (!chip) {
-		struct bfin_spi3_chip *chip_info = spi->controller_data;
-
-		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-		if (!chip) {
-			dev_err(&spi->dev, "can not allocate chip data\n");
-			return -ENOMEM;
-		}
-		if (chip_info) {
-			if (chip_info->control & ~bfin_ctl_reg) {
-				dev_err(&spi->dev,
-					"do not set bits that the SPI framework manages\n");
-				goto error;
-			}
-			chip->control = chip_info->control;
-			chip->cs_chg_udelay = chip_info->cs_chg_udelay;
-			chip->tx_dummy_val = chip_info->tx_dummy_val;
-			chip->enable_dma = chip_info->enable_dma;
-		}
-		chip->cs = spi->chip_select;
-		if (chip->cs < MAX_CTRL_CS) {
-			chip->ssel = (1 << chip->cs) << 8;
-			ret = peripheral_request(ssel[spi->master->bus_num]
-					[chip->cs-1], dev_name(&spi->dev));
-			if (ret) {
-				dev_err(&spi->dev, "peripheral_request() error\n");
-				goto error;
-			}
-		} else {
-			chip->cs_gpio = chip->cs - MAX_CTRL_CS;
-			ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH,
-						dev_name(&spi->dev));
-			if (ret) {
-				dev_err(&spi->dev, "gpio_request_one() error\n");
-				goto error;
-			}
-		}
-		spi_set_ctldata(spi, chip);
-	}
-
-	/* force a default base state */
-	chip->control &= bfin_ctl_reg;
-
-	if (spi->mode & SPI_CPOL)
-		chip->control |= SPI_CTL_CPOL;
-	if (spi->mode & SPI_CPHA)
-		chip->control |= SPI_CTL_CPHA;
-	if (spi->mode & SPI_LSB_FIRST)
-		chip->control |= SPI_CTL_LSBF;
-	chip->control |= SPI_CTL_MSTR;
-	/* we choose software to controll cs */
-	chip->control &= ~SPI_CTL_ASSEL;
-
-	chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz);
-
-	bfin_spi_cs_enable(drv_data, chip);
-	bfin_spi_cs_deactive(drv_data, chip);
-
-	return 0;
-error:
-	if (chip) {
-		kfree(chip);
-		spi_set_ctldata(spi, NULL);
-	}
-
-	return ret;
-}
-
-static void bfin_spi_cleanup(struct spi_device *spi)
-{
-	struct bfin_spi_device *chip = spi_get_ctldata(spi);
-	struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
-
-	if (!chip)
-		return;
-
-	if (chip->cs < MAX_CTRL_CS) {
-		peripheral_free(ssel[spi->master->bus_num]
-					[chip->cs-1]);
-		bfin_spi_cs_disable(drv_data, chip);
-	} else {
-		gpio_free(chip->cs_gpio);
-	}
-
-	kfree(chip);
-	spi_set_ctldata(spi, NULL);
-}
-
-static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)
-{
-	struct bfin_spi_master *drv_data = dev_id;
-	u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma);
-
-	clear_dma_irqstat(drv_data->tx_dma);
-	if (dma_stat & DMA_DONE) {
-		drv_data->tx_num++;
-	} else {
-		dev_err(&drv_data->master->dev,
-				"spi tx dma error: %d\n", dma_stat);
-		if (drv_data->tx)
-			drv_data->state = ERROR_STATE;
-	}
-	bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)
-{
-	struct bfin_spi_master *drv_data = dev_id;
-	struct spi_message *msg = drv_data->cur_msg;
-	u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma);
-
-	clear_dma_irqstat(drv_data->rx_dma);
-	if (dma_stat & DMA_DONE) {
-		drv_data->rx_num++;
-		/* we may fail on tx dma */
-		if (drv_data->state != ERROR_STATE)
-			msg->actual_length += drv_data->transfer_len;
-	} else {
-		drv_data->state = ERROR_STATE;
-		dev_err(&drv_data->master->dev,
-				"spi rx dma error: %d\n", dma_stat);
-	}
-	bfin_write(&drv_data->regs->tx_control, 0);
-	bfin_write(&drv_data->regs->rx_control, 0);
-	if (drv_data->rx_num != drv_data->tx_num)
-		dev_dbg(&drv_data->master->dev,
-				"dma interrupt missing: tx=%d,rx=%d\n",
-				drv_data->tx_num, drv_data->rx_num);
-	tasklet_schedule(&drv_data->pump_transfers);
-	return IRQ_HANDLED;
-}
-
-static int bfin_spi_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct bfin_spi3_master *info = dev_get_platdata(dev);
-	struct spi_master *master;
-	struct bfin_spi_master *drv_data;
-	struct resource *mem, *res;
-	unsigned int tx_dma, rx_dma;
-	unsigned long sclk;
-	int ret;
-
-	if (!info) {
-		dev_err(dev, "platform data missing!\n");
-		return -ENODEV;
-	}
-
-	sclk = get_sclk1();
-	if (!sclk) {
-		dev_err(dev, "can not get sclk1\n");
-		return -ENXIO;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!res) {
-		dev_err(dev, "can not get tx dma resource\n");
-		return -ENXIO;
-	}
-	tx_dma = res->start;
-
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!res) {
-		dev_err(dev, "can not get rx dma resource\n");
-		return -ENXIO;
-	}
-	rx_dma = res->start;
-
-	/* allocate master with space for drv_data */
-	master = spi_alloc_master(dev, sizeof(*drv_data));
-	if (!master) {
-		dev_err(dev, "can not alloc spi_master\n");
-		return -ENOMEM;
-	}
-	platform_set_drvdata(pdev, master);
-
-	/* the mode bits supported by this driver */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
-
-	master->bus_num = pdev->id;
-	master->num_chipselect = info->num_chipselect;
-	master->cleanup = bfin_spi_cleanup;
-	master->setup = bfin_spi_setup;
-	master->transfer_one_message = bfin_spi_transfer_one_message;
-	master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
-				     SPI_BPW_MASK(8);
-
-	drv_data = spi_master_get_devdata(master);
-	drv_data->master = master;
-	drv_data->tx_dma = tx_dma;
-	drv_data->rx_dma = rx_dma;
-	drv_data->pin_req = info->pin_req;
-	drv_data->sclk = sclk;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	drv_data->regs = devm_ioremap_resource(dev, mem);
-	if (IS_ERR(drv_data->regs)) {
-		ret = PTR_ERR(drv_data->regs);
-		goto err_put_master;
-	}
-
-	/* request tx and rx dma */
-	ret = request_dma(tx_dma, "SPI_TX_DMA");
-	if (ret) {
-		dev_err(dev, "can not request SPI TX DMA channel\n");
-		goto err_put_master;
-	}
-	set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data);
-
-	ret = request_dma(rx_dma, "SPI_RX_DMA");
-	if (ret) {
-		dev_err(dev, "can not request SPI RX DMA channel\n");
-		goto err_free_tx_dma;
-	}
-	set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data);
-
-	/* request CLK, MOSI and MISO */
-	ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3");
-	if (ret < 0) {
-		dev_err(dev, "can not request spi pins\n");
-		goto err_free_rx_dma;
-	}
-
-	bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
-	bfin_write(&drv_data->regs->ssel, 0x0000FE00);
-	bfin_write(&drv_data->regs->delay, 0x0);
-
-	tasklet_init(&drv_data->pump_transfers,
-			bfin_spi_pump_transfers, (unsigned long)drv_data);
-	/* register with the SPI framework */
-	ret = devm_spi_register_master(dev, master);
-	if (ret) {
-		dev_err(dev, "can not  register spi master\n");
-		goto err_free_peripheral;
-	}
-
-	return ret;
-
-err_free_peripheral:
-	peripheral_free_list(drv_data->pin_req);
-err_free_rx_dma:
-	free_dma(rx_dma);
-err_free_tx_dma:
-	free_dma(tx_dma);
-err_put_master:
-	spi_master_put(master);
-
-	return ret;
-}
-
-static int bfin_spi_remove(struct platform_device *pdev)
-{
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
-
-	bfin_spi_disable(drv_data);
-
-	peripheral_free_list(drv_data->pin_req);
-	free_dma(drv_data->rx_dma);
-	free_dma(drv_data->tx_dma);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_spi_suspend(struct device *dev)
-{
-	struct spi_master *master = dev_get_drvdata(dev);
-	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
-
-	spi_master_suspend(master);
-
-	drv_data->control = bfin_read(&drv_data->regs->control);
-	drv_data->ssel = bfin_read(&drv_data->regs->ssel);
-
-	bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
-	bfin_write(&drv_data->regs->ssel, 0x0000FE00);
-	dma_disable_irq(drv_data->rx_dma);
-	dma_disable_irq(drv_data->tx_dma);
-
-	return 0;
-}
-
-static int bfin_spi_resume(struct device *dev)
-{
-	struct spi_master *master = dev_get_drvdata(dev);
-	struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
-	int ret = 0;
-
-	/* bootrom may modify spi and dma status when resume in spi boot mode */
-	disable_dma(drv_data->rx_dma);
-
-	dma_enable_irq(drv_data->rx_dma);
-	dma_enable_irq(drv_data->tx_dma);
-	bfin_write(&drv_data->regs->control, drv_data->control);
-	bfin_write(&drv_data->regs->ssel, drv_data->ssel);
-
-	ret = spi_master_resume(master);
-	if (ret) {
-		free_dma(drv_data->rx_dma);
-		free_dma(drv_data->tx_dma);
-	}
-
-	return ret;
-}
-#endif
-static const struct dev_pm_ops bfin_spi_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume)
-};
-
-MODULE_ALIAS("platform:bfin-spi3");
-static struct platform_driver bfin_spi_driver = {
-	.driver	= {
-		.name	= "bfin-spi3",
-		.owner	= THIS_MODULE,
-		.pm     = &bfin_spi_pm_ops,
-	},
-	.remove		= bfin_spi_remove,
-};
-
-module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe);
-
-MODULE_DESCRIPTION("Analog Devices SPI3 controller driver");
-MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index 55e57c3eb9bd..ebf720b88a2a 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
new file mode 100644
index 000000000000..bb758978465d
--- /dev/null
+++ b/drivers/spi/spi-cadence.c
@@ -0,0 +1,673 @@
+/*
+ * Cadence SPI controller driver (master mode only)
+ *
+ * Copyright (C) 2008 - 2014 Xilinx, Inc.
+ *
+ * based on Blackfin On-Chip SPI Driver (spi_bfin5xx.c)
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+/* Name of this driver */
+#define CDNS_SPI_NAME		"cdns-spi"
+
+/* Register offset definitions */
+#define CDNS_SPI_CR_OFFSET	0x00 /* Configuration  Register, RW */
+#define CDNS_SPI_ISR_OFFSET	0x04 /* Interrupt Status Register, RO */
+#define CDNS_SPI_IER_OFFSET	0x08 /* Interrupt Enable Register, WO */
+#define CDNS_SPI_IDR_OFFSET	0x0c /* Interrupt Disable Register, WO */
+#define CDNS_SPI_IMR_OFFSET	0x10 /* Interrupt Enabled Mask Register, RO */
+#define CDNS_SPI_ER_OFFSET	0x14 /* Enable/Disable Register, RW */
+#define CDNS_SPI_DR_OFFSET	0x18 /* Delay Register, RW */
+#define CDNS_SPI_TXD_OFFSET	0x1C /* Data Transmit Register, WO */
+#define CDNS_SPI_RXD_OFFSET	0x20 /* Data Receive Register, RO */
+#define CDNS_SPI_SICR_OFFSET	0x24 /* Slave Idle Count Register, RW */
+#define CDNS_SPI_THLD_OFFSET	0x28 /* Transmit FIFO Watermark Register,RW */
+
+/*
+ * SPI Configuration Register bit Masks
+ *
+ * This register contains various control bits that affect the operation
+ * of the SPI controller
+ */
+#define CDNS_SPI_CR_MANSTRT_MASK	0x00010000 /* Manual TX Start */
+#define CDNS_SPI_CR_CPHA_MASK		0x00000004 /* Clock Phase Control */
+#define CDNS_SPI_CR_CPOL_MASK		0x00000002 /* Clock Polarity Control */
+#define CDNS_SPI_CR_SSCTRL_MASK		0x00003C00 /* Slave Select Mask */
+#define CDNS_SPI_CR_BAUD_DIV_MASK	0x00000038 /* Baud Rate Divisor Mask */
+#define CDNS_SPI_CR_MSTREN_MASK		0x00000001 /* Master Enable Mask */
+#define CDNS_SPI_CR_MANSTRTEN_MASK	0x00008000 /* Manual TX Enable Mask */
+#define CDNS_SPI_CR_SSFORCE_MASK	0x00004000 /* Manual SS Enable Mask */
+#define CDNS_SPI_CR_BAUD_DIV_4_MASK	0x00000008 /* Default Baud Div Mask */
+#define CDNS_SPI_CR_DEFAULT_MASK	(CDNS_SPI_CR_MSTREN_MASK | \
+					CDNS_SPI_CR_SSCTRL_MASK | \
+					CDNS_SPI_CR_SSFORCE_MASK | \
+					CDNS_SPI_CR_BAUD_DIV_4_MASK)
+
+/*
+ * SPI Configuration Register - Baud rate and slave select
+ *
+ * These are the values used in the calculation of baud rate divisor and
+ * setting the slave select.
+ */
+
+#define CDNS_SPI_BAUD_DIV_MAX		7 /* Baud rate divisor maximum */
+#define CDNS_SPI_BAUD_DIV_MIN		1 /* Baud rate divisor minimum */
+#define CDNS_SPI_BAUD_DIV_SHIFT		3 /* Baud rate divisor shift in CR */
+#define CDNS_SPI_SS_SHIFT		10 /* Slave Select field shift in CR */
+#define CDNS_SPI_SS0			0x1 /* Slave Select zero */
+
+/*
+ * SPI Interrupt Registers bit Masks
+ *
+ * All the four interrupt registers (Status/Mask/Enable/Disable) have the same
+ * bit definitions.
+ */
+#define CDNS_SPI_IXR_TXOW_MASK	0x00000004 /* SPI TX FIFO Overwater */
+#define CDNS_SPI_IXR_MODF_MASK	0x00000002 /* SPI Mode Fault */
+#define CDNS_SPI_IXR_RXNEMTY_MASK 0x00000010 /* SPI RX FIFO Not Empty */
+#define CDNS_SPI_IXR_DEFAULT_MASK	(CDNS_SPI_IXR_TXOW_MASK | \
+					CDNS_SPI_IXR_MODF_MASK)
+#define CDNS_SPI_IXR_TXFULL_MASK	0x00000008 /* SPI TX Full */
+#define CDNS_SPI_IXR_ALL_MASK	0x0000007F /* SPI all interrupts */
+
+/*
+ * SPI Enable Register bit Masks
+ *
+ * This register is used to enable or disable the SPI controller
+ */
+#define CDNS_SPI_ER_ENABLE_MASK	0x00000001 /* SPI Enable Bit Mask */
+#define CDNS_SPI_ER_DISABLE_MASK	0x0 /* SPI Disable Bit Mask */
+
+/* SPI FIFO depth in bytes */
+#define CDNS_SPI_FIFO_DEPTH	128
+
+/* Default number of chip select lines */
+#define CDNS_SPI_DEFAULT_NUM_CS		4
+
+/**
+ * struct cdns_spi - This definition defines spi driver instance
+ * @regs:		Virtual address of the SPI controller registers
+ * @ref_clk:		Pointer to the peripheral clock
+ * @pclk:		Pointer to the APB clock
+ * @speed_hz:		Current SPI bus clock speed in Hz
+ * @txbuf:		Pointer	to the TX buffer
+ * @rxbuf:		Pointer to the RX buffer
+ * @tx_bytes:		Number of bytes left to transfer
+ * @rx_bytes:		Number of bytes requested
+ * @dev_busy:		Device busy flag
+ * @is_decoded_cs:	Flag for decoder property set or not
+ */
+struct cdns_spi {
+	void __iomem *regs;
+	struct clk *ref_clk;
+	struct clk *pclk;
+	u32 speed_hz;
+	const u8 *txbuf;
+	u8 *rxbuf;
+	int tx_bytes;
+	int rx_bytes;
+	u8 dev_busy;
+	u32 is_decoded_cs;
+};
+
+/* Macros for the SPI controller read/write */
+static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
+{
+	return readl_relaxed(xspi->regs + offset);
+}
+
+static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val)
+{
+	writel_relaxed(val, xspi->regs + offset);
+}
+
+/**
+ * cdns_spi_init_hw - Initialize the hardware and configure the SPI controller
+ * @xspi:	Pointer to the cdns_spi structure
+ *
+ * On reset the SPI controller is configured to be in master mode, baud rate
+ * divisor is set to 4, threshold value for TX FIFO not full interrupt is set
+ * to 1 and size of the word to be transferred as 8 bit.
+ * This function initializes the SPI controller to disable and clear all the
+ * interrupts, enable manual slave select and manual start, deselect all the
+ * chip select lines, and enable the SPI controller.
+ */
+static void cdns_spi_init_hw(struct cdns_spi *xspi)
+{
+	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
+		       CDNS_SPI_ER_DISABLE_MASK);
+	cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET,
+		       CDNS_SPI_IXR_ALL_MASK);
+
+	/* Clear the RX FIFO */
+	while (cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET) &
+	       CDNS_SPI_IXR_RXNEMTY_MASK)
+		cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET);
+
+	cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET,
+		       CDNS_SPI_IXR_ALL_MASK);
+	cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET,
+		       CDNS_SPI_CR_DEFAULT_MASK);
+	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
+		       CDNS_SPI_ER_ENABLE_MASK);
+}
+
+/**
+ * cdns_spi_chipselect - Select or deselect the chip select line
+ * @spi:	Pointer to the spi_device structure
+ * @is_on:	Select(0) or deselect (1) the chip select line
+ */
+static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
+{
+	struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
+	u32 ctrl_reg;
+
+	ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
+
+	if (is_high) {
+		/* Deselect the slave */
+		ctrl_reg |= CDNS_SPI_CR_SSCTRL_MASK;
+	} else {
+		/* Select the slave */
+		ctrl_reg &= ~CDNS_SPI_CR_SSCTRL_MASK;
+		if (!(xspi->is_decoded_cs))
+			ctrl_reg |= ((~(CDNS_SPI_SS0 << spi->chip_select)) <<
+				     CDNS_SPI_SS_SHIFT) &
+				     CDNS_SPI_CR_SSCTRL_MASK;
+		else
+			ctrl_reg |= (spi->chip_select << CDNS_SPI_SS_SHIFT) &
+				     CDNS_SPI_CR_SSCTRL_MASK;
+	}
+
+	cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
+}
+
+/**
+ * cdns_spi_config_clock_mode - Sets clock polarity and phase
+ * @spi:	Pointer to the spi_device structure
+ *
+ * Sets the requested clock polarity and phase.
+ */
+static void cdns_spi_config_clock_mode(struct spi_device *spi)
+{
+	struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
+	u32 ctrl_reg;
+
+	ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
+
+	/* Set the SPI clock phase and clock polarity */
+	ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK);
+	if (spi->mode & SPI_CPHA)
+		ctrl_reg |= CDNS_SPI_CR_CPHA_MASK;
+	if (spi->mode & SPI_CPOL)
+		ctrl_reg |= CDNS_SPI_CR_CPOL_MASK;
+
+	cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
+}
+
+/**
+ * cdns_spi_config_clock_freq - Sets clock frequency
+ * @spi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provides
+ *		information about next transfer setup parameters
+ *
+ * Sets the requested clock frequency.
+ * Note: If the requested frequency is not an exact match with what can be
+ * obtained using the prescalar value the driver sets the clock frequency which
+ * is lower than the requested frequency (maximum lower) for the transfer. If
+ * the requested frequency is higher or lower than that is supported by the SPI
+ * controller the driver will set the highest or lowest frequency supported by
+ * controller.
+ */
+static void cdns_spi_config_clock_freq(struct spi_device *spi,
+				  struct spi_transfer *transfer)
+{
+	struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
+	u32 ctrl_reg, baud_rate_val;
+	unsigned long frequency;
+
+	frequency = clk_get_rate(xspi->ref_clk);
+
+	ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
+
+	/* Set the clock frequency */
+	if (xspi->speed_hz != transfer->speed_hz) {
+		/* first valid value is 1 */
+		baud_rate_val = CDNS_SPI_BAUD_DIV_MIN;
+		while ((baud_rate_val < CDNS_SPI_BAUD_DIV_MAX) &&
+		       (frequency / (2 << baud_rate_val)) > transfer->speed_hz)
+			baud_rate_val++;
+
+		ctrl_reg &= ~CDNS_SPI_CR_BAUD_DIV_MASK;
+		ctrl_reg |= baud_rate_val << CDNS_SPI_BAUD_DIV_SHIFT;
+
+		xspi->speed_hz = frequency / (2 << baud_rate_val);
+	}
+	cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
+}
+
+/**
+ * cdns_spi_setup_transfer - Configure SPI controller for specified transfer
+ * @spi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provides
+ *		information about next transfer setup parameters
+ *
+ * Sets the operational mode of SPI controller for the next SPI transfer and
+ * sets the requested clock frequency.
+ *
+ * Return:	Always 0
+ */
+static int cdns_spi_setup_transfer(struct spi_device *spi,
+				   struct spi_transfer *transfer)
+{
+	struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
+
+	cdns_spi_config_clock_freq(spi, transfer);
+
+	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u clock speed\n",
+		__func__, spi->mode, spi->bits_per_word,
+		xspi->speed_hz);
+
+	return 0;
+}
+
+/**
+ * cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
+ * @xspi:	Pointer to the cdns_spi structure
+ */
+static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
+{
+	unsigned long trans_cnt = 0;
+
+	while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) &&
+	       (xspi->tx_bytes > 0)) {
+		if (xspi->txbuf)
+			cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET,
+				       *xspi->txbuf++);
+		else
+			cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, 0);
+
+		xspi->tx_bytes--;
+		trans_cnt++;
+	}
+}
+
+/**
+ * cdns_spi_irq - Interrupt service routine of the SPI controller
+ * @irq:	IRQ number
+ * @dev_id:	Pointer to the xspi structure
+ *
+ * This function handles TX empty and Mode Fault interrupts only.
+ * On TX empty interrupt this function reads the received data from RX FIFO and
+ * fills the TX FIFO if there is any data remaining to be transferred.
+ * On Mode Fault interrupt this function indicates that transfer is completed,
+ * the SPI subsystem will identify the error as the remaining bytes to be
+ * transferred is non-zero.
+ *
+ * Return:	IRQ_HANDLED when handled; IRQ_NONE otherwise.
+ */
+static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
+{
+	struct spi_master *master = dev_id;
+	struct cdns_spi *xspi = spi_master_get_devdata(master);
+	u32 intr_status, status;
+
+	status = IRQ_NONE;
+	intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET);
+	cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, intr_status);
+
+	if (intr_status & CDNS_SPI_IXR_MODF_MASK) {
+		/* Indicate that transfer is completed, the SPI subsystem will
+		 * identify the error as the remaining bytes to be
+		 * transferred is non-zero
+		 */
+		cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET,
+			       CDNS_SPI_IXR_DEFAULT_MASK);
+		spi_finalize_current_transfer(master);
+		status = IRQ_HANDLED;
+	} else if (intr_status & CDNS_SPI_IXR_TXOW_MASK) {
+		unsigned long trans_cnt;
+
+		trans_cnt = xspi->rx_bytes - xspi->tx_bytes;
+
+		/* Read out the data from the RX FIFO */
+		while (trans_cnt) {
+			u8 data;
+
+			data = cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET);
+			if (xspi->rxbuf)
+				*xspi->rxbuf++ = data;
+
+			xspi->rx_bytes--;
+			trans_cnt--;
+		}
+
+		if (xspi->tx_bytes) {
+			/* There is more data to send */
+			cdns_spi_fill_tx_fifo(xspi);
+		} else {
+			/* Transfer is completed */
+			cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET,
+				       CDNS_SPI_IXR_DEFAULT_MASK);
+			spi_finalize_current_transfer(master);
+		}
+		status = IRQ_HANDLED;
+	}
+
+	return status;
+}
+
+/**
+ * cdns_transfer_one - Initiates the SPI transfer
+ * @master:	Pointer to spi_master structure
+ * @spi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provides
+ *		information about next transfer parameters
+ *
+ * This function fills the TX FIFO, starts the SPI transfer and
+ * returns a positive transfer count so that core will wait for completion.
+ *
+ * Return:	Number of bytes transferred in the last transfer
+ */
+static int cdns_transfer_one(struct spi_master *master,
+			     struct spi_device *spi,
+			     struct spi_transfer *transfer)
+{
+	struct cdns_spi *xspi = spi_master_get_devdata(master);
+
+	xspi->txbuf = transfer->tx_buf;
+	xspi->rxbuf = transfer->rx_buf;
+	xspi->tx_bytes = transfer->len;
+	xspi->rx_bytes = transfer->len;
+
+	cdns_spi_setup_transfer(spi, transfer);
+
+	cdns_spi_fill_tx_fifo(xspi);
+
+	cdns_spi_write(xspi, CDNS_SPI_IER_OFFSET,
+		       CDNS_SPI_IXR_DEFAULT_MASK);
+	return transfer->len;
+}
+
+/**
+ * cdns_prepare_transfer_hardware - Prepares hardware for transfer.
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ *
+ * This function enables SPI master controller.
+ *
+ * Return:	0 always
+ */
+static int cdns_prepare_transfer_hardware(struct spi_master *master)
+{
+	struct cdns_spi *xspi = spi_master_get_devdata(master);
+
+	cdns_spi_config_clock_mode(master->cur_msg->spi);
+
+	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
+		       CDNS_SPI_ER_ENABLE_MASK);
+
+	return 0;
+}
+
+/**
+ * cdns_unprepare_transfer_hardware - Relaxes hardware after transfer
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ *
+ * This function disables the SPI master controller.
+ *
+ * Return:	0 always
+ */
+static int cdns_unprepare_transfer_hardware(struct spi_master *master)
+{
+	struct cdns_spi *xspi = spi_master_get_devdata(master);
+
+	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
+		       CDNS_SPI_ER_DISABLE_MASK);
+
+	return 0;
+}
+
+/**
+ * cdns_spi_probe - Probe method for the SPI driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function initializes the driver data structures and the hardware.
+ *
+ * Return:	0 on success and error value on error
+ */
+static int cdns_spi_probe(struct platform_device *pdev)
+{
+	int ret = 0, irq;
+	struct spi_master *master;
+	struct cdns_spi *xspi;
+	struct resource *res;
+	u32 num_cs;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*xspi));
+	if (master == NULL)
+		return -ENOMEM;
+
+	xspi = spi_master_get_devdata(master);
+	master->dev.of_node = pdev->dev.of_node;
+	platform_set_drvdata(pdev, master);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xspi->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(xspi->regs)) {
+		ret = PTR_ERR(xspi->regs);
+		goto remove_master;
+	}
+
+	xspi->pclk = devm_clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(xspi->pclk)) {
+		dev_err(&pdev->dev, "pclk clock not found.\n");
+		ret = PTR_ERR(xspi->pclk);
+		goto remove_master;
+	}
+
+	xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+	if (IS_ERR(xspi->ref_clk)) {
+		dev_err(&pdev->dev, "ref_clk clock not found.\n");
+		ret = PTR_ERR(xspi->ref_clk);
+		goto remove_master;
+	}
+
+	ret = clk_prepare_enable(xspi->pclk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable APB clock.\n");
+		goto remove_master;
+	}
+
+	ret = clk_prepare_enable(xspi->ref_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable device clock.\n");
+		goto clk_dis_apb;
+	}
+
+	/* SPI controller initializations */
+	cdns_spi_init_hw(xspi);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		ret = -ENXIO;
+		dev_err(&pdev->dev, "irq number is invalid\n");
+		goto remove_master;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq,
+			       0, pdev->name, master);
+	if (ret != 0) {
+		ret = -ENXIO;
+		dev_err(&pdev->dev, "request_irq failed\n");
+		goto remove_master;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
+
+	if (ret < 0)
+		master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
+	else
+		master->num_chipselect = num_cs;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "is-decoded-cs",
+				   &xspi->is_decoded_cs);
+
+	if (ret < 0)
+		xspi->is_decoded_cs = 0;
+
+	master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
+	master->transfer_one = cdns_transfer_one;
+	master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
+	master->set_cs = cdns_spi_chipselect;
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+
+	/* Set to default valid value */
+	master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4;
+	xspi->speed_hz = master->max_speed_hz;
+
+	master->bits_per_word_mask = SPI_BPW_MASK(8);
+
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(&pdev->dev, "spi_register_master failed\n");
+		goto clk_dis_all;
+	}
+
+	return ret;
+
+clk_dis_all:
+	clk_disable_unprepare(xspi->ref_clk);
+clk_dis_apb:
+	clk_disable_unprepare(xspi->pclk);
+remove_master:
+	spi_master_put(master);
+	return ret;
+}
+
+/**
+ * cdns_spi_remove - Remove method for the SPI driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees all resources allocated to
+ * the device.
+ *
+ * Return:	0 on success and error value on error
+ */
+static int cdns_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct cdns_spi *xspi = spi_master_get_devdata(master);
+
+	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
+		       CDNS_SPI_ER_DISABLE_MASK);
+
+	clk_disable_unprepare(xspi->ref_clk);
+	clk_disable_unprepare(xspi->pclk);
+
+	spi_unregister_master(master);
+
+	return 0;
+}
+
+/**
+ * cdns_spi_suspend - Suspend method for the SPI driver
+ * @dev:	Address of the platform_device structure
+ *
+ * This function disables the SPI controller and
+ * changes the driver state to "suspend"
+ *
+ * Return:	Always 0
+ */
+static int __maybe_unused cdns_spi_suspend(struct device *dev)
+{
+	struct platform_device *pdev = container_of(dev,
+			struct platform_device, dev);
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct cdns_spi *xspi = spi_master_get_devdata(master);
+
+	spi_master_suspend(master);
+
+	clk_disable_unprepare(xspi->ref_clk);
+
+	clk_disable_unprepare(xspi->pclk);
+
+	return 0;
+}
+
+/**
+ * cdns_spi_resume - Resume method for the SPI driver
+ * @dev:	Address of the platform_device structure
+ *
+ * This function changes the driver state to "ready"
+ *
+ * Return:	0 on success and error value on error
+ */
+static int __maybe_unused cdns_spi_resume(struct device *dev)
+{
+	struct platform_device *pdev = container_of(dev,
+			struct platform_device, dev);
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct cdns_spi *xspi = spi_master_get_devdata(master);
+	int ret = 0;
+
+	ret = clk_prepare_enable(xspi->pclk);
+	if (ret) {
+		dev_err(dev, "Cannot enable APB clock.\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(xspi->ref_clk);
+	if (ret) {
+		dev_err(dev, "Cannot enable device clock.\n");
+		clk_disable(xspi->pclk);
+		return ret;
+	}
+	spi_master_resume(master);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend,
+			 cdns_spi_resume);
+
+static struct of_device_id cdns_spi_of_match[] = {
+	{ .compatible = "xlnx,zynq-spi-r1p6" },
+	{ .compatible = "cdns,spi-r1p6" },
+	{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, cdns_spi_of_match);
+
+/* cdns_spi_driver - This structure defines the SPI subsystem platform driver */
+static struct platform_driver cdns_spi_driver = {
+	.probe	= cdns_spi_probe,
+	.remove	= cdns_spi_remove,
+	.driver = {
+		.name = CDNS_SPI_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = cdns_spi_of_match,
+		.pm = &cdns_spi_dev_pm_ops,
+	},
+};
+
+module_platform_driver(cdns_spi_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Cadence SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c
index 09965f069a1c..ba441ad9a007 100644
--- a/drivers/spi/spi-falcon.c
+++ b/drivers/spi/spi-falcon.c
@@ -11,7 +11,6 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/delay.h>
-#include <linux/workqueue.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index e767f5831b9c..3936062c4915 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -458,7 +458,7 @@ static int fsl_espi_setup(struct spi_device *spi)
 		return -EINVAL;
 
 	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);
 		if (!cs)
 			return -ENOMEM;
 		spi->controller_state = cs;
@@ -586,8 +586,10 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
 	struct spi_master *master;
 	struct mpc8xxx_spi *mpc8xxx_spi;
 	struct fsl_espi_reg *reg_base;
-	u32 regval;
-	int i, ret = 0;
+	struct device_node *nc;
+	const __be32 *prop;
+	u32 regval, csmode;
+	int i, len, ret = 0;
 
 	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
 	if (!master) {
@@ -634,8 +636,32 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
 	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
 
 	/* Init eSPI CS mode register */
-	for (i = 0; i < pdata->max_chipselect; i++)
-		mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+	for_each_available_child_of_node(master->dev.of_node, nc) {
+		/* get chip select */
+		prop = of_get_property(nc, "reg", &len);
+		if (!prop || len < sizeof(*prop))
+			continue;
+		i = be32_to_cpup(prop);
+		if (i < 0 || i >= pdata->max_chipselect)
+			continue;
+
+		csmode = CSMODE_INIT_VAL;
+		/* check if CSBEF is set in device tree */
+		prop = of_get_property(nc, "fsl,csbef", &len);
+		if (prop && len >= sizeof(*prop)) {
+			csmode &= ~(CSMODE_BEF(0xf));
+			csmode |= CSMODE_BEF(be32_to_cpup(prop));
+		}
+		/* check if CSAFT is set in device tree */
+		prop = of_get_property(nc, "fsl,csaft", &len);
+		if (prop && len >= sizeof(*prop)) {
+			csmode &= ~(CSMODE_AFT(0xf));
+			csmode |= CSMODE_AFT(be32_to_cpup(prop));
+		}
+		mpc8xxx_spi_write_reg(&reg_base->csmode[i], csmode);
+
+		dev_info(dev, "cs=%d, init_csmode=0x%x\n", i, csmode);
+	}
 
 	/* Enable SPI interface */
 	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c
index e5d45fca3551..95212ea96c8d 100644
--- a/drivers/spi/spi-fsl-lib.c
+++ b/drivers/spi/spi-fsl-lib.c
@@ -99,11 +99,6 @@ int mpc8xxx_spi_transfer(struct spi_device *spi,
 	return 0;
 }
 
-void mpc8xxx_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
 const char *mpc8xxx_spi_strmode(unsigned int flags)
 {
 	if (flags & SPI_QE_CPU_MODE) {
@@ -134,7 +129,6 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
 			| SPI_LSB_FIRST | SPI_LOOP;
 
 	master->transfer = mpc8xxx_spi_transfer;
-	master->cleanup = mpc8xxx_spi_cleanup;
 	master->dev.of_node = dev->of_node;
 
 	mpc8xxx_spi = spi_master_get_devdata(master);
diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
index 52db6936778e..2fcbfd01d109 100644
--- a/drivers/spi/spi-fsl-lib.h
+++ b/drivers/spi/spi-fsl-lib.h
@@ -124,7 +124,6 @@ extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
 extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
 		struct spi_transfer *t, unsigned int len);
 extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
-extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
 extern const char *mpc8xxx_spi_strmode(unsigned int flags);
 extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
 		unsigned int irq);
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index b3e7775034db..98ccd231bf00 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -431,7 +431,7 @@ static int fsl_spi_setup(struct spi_device *spi)
 		return -EINVAL;
 
 	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);
 		if (!cs)
 			return -ENOMEM;
 		spi->controller_state = cs;
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
index 16e30de650b0..73e91d5a43df 100644
--- a/drivers/spi/spi-nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -10,7 +10,6 @@
 
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c
index be2a2e108e2f..0f5a0aa3b871 100644
--- a/drivers/spi/spi-omap-uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -37,7 +37,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
-#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
 #include <linux/clk.h>
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 41185d0557fa..d0fc8e06bf43 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -27,7 +27,6 @@
 #include <linux/platform_device.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/spi/spi.h>
-#include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index bed23384dfab..bd85181ef129 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -10,7 +10,6 @@
 */
 
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -183,7 +182,9 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
 
 	/* allocate settings on the first call */
 	if (!cs) {
-		cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
+		cs = devm_kzalloc(&spi->dev,
+				  sizeof(struct s3c24xx_spi_devstate),
+				  GFP_KERNEL);
 		if (!cs) {
 			dev_err(&spi->dev, "no memory for controller state\n");
 			return -ENOMEM;
@@ -209,11 +210,6 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
 	return 0;
 }
 
-static void s3c24xx_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
 static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
 {
 	return hw->tx ? hw->tx[count] : 0;
@@ -543,7 +539,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
 	hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;
 
 	hw->master->setup  = s3c24xx_spi_setup;
-	hw->master->cleanup = s3c24xx_spi_cleanup;
 
 	dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
 
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index f19cd97855e8..153b4bec21c1 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -19,7 +19,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 9009456bdf4d..c8e795ef2e13 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -244,9 +244,9 @@ static int hspi_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	clk = clk_get(NULL, "shyway_clk");
+	clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "shyway_clk is required\n");
+		dev_err(&pdev->dev, "couldn't get clock\n");
 		ret = -EINVAL;
 		goto error0;
 	}
diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c
index 8b44b71f5024..1f56ef651d1a 100644
--- a/drivers/spi/spi-sh-sci.c
+++ b/drivers/spi/spi-sh-sci.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 #include <linux/platform_device.h>
 
 #include <linux/spi/spi.h>
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index 1a77ad52812f..2d238990115c 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -287,8 +288,8 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
 				sspi->left_rx_word)
 			sspi->rx_word(sspi);
 
-	if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY
-			| SIRFSOC_SPI_TXFIFO_THD_REACH))
+	if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY |
+			SIRFSOC_SPI_TXFIFO_THD_REACH))
 		while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
 				& SIRFSOC_SPI_FIFO_FULL)) &&
 				sspi->left_tx_word)
@@ -309,59 +310,51 @@ static void spi_sirfsoc_dma_fini_callback(void *data)
 	complete(dma_complete);
 }
 
-static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
+static int spi_sirfsoc_cmd_transfer(struct spi_device *spi,
+	struct spi_transfer *t)
 {
 	struct sirfsoc_spi *sspi;
 	int timeout = t->len * 10;
-	sspi = spi_master_get_devdata(spi->master);
-
-	sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage;
-	sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage;
-	sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width;
-	reinit_completion(&sspi->rx_done);
-	reinit_completion(&sspi->tx_done);
-
-	writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
+	u32 cmd;
 
-	/*
-	 * fill tx_buf into command register and wait for its completion
-	 */
-	if (sspi->tx_by_cmd) {
-		u32 cmd;
-		memcpy(&cmd, sspi->tx, t->len);
-
-		if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST))
-			cmd = cpu_to_be32(cmd) >>
-				((SIRFSOC_MAX_CMD_BYTES - t->len) * 8);
-		if (sspi->word_width == 2 && t->len == 4 &&
-				(!(spi->mode & SPI_LSB_FIRST)))
-			cmd = ((cmd & 0xffff) << 16) | (cmd >> 16);
-
-		writel(cmd, sspi->base + SIRFSOC_SPI_CMD);
-		writel(SIRFSOC_SPI_FRM_END_INT_EN,
-			sspi->base + SIRFSOC_SPI_INT_EN);
-		writel(SIRFSOC_SPI_CMD_TX_EN,
-			sspi->base + SIRFSOC_SPI_TX_RX_EN);
+	sspi = spi_master_get_devdata(spi->master);
+	memcpy(&cmd, sspi->tx, t->len);
+	if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST))
+		cmd = cpu_to_be32(cmd) >>
+			((SIRFSOC_MAX_CMD_BYTES - t->len) * 8);
+	if (sspi->word_width == 2 && t->len == 4 &&
+			(!(spi->mode & SPI_LSB_FIRST)))
+		cmd = ((cmd & 0xffff) << 16) | (cmd >> 16);
+	writel(cmd, sspi->base + SIRFSOC_SPI_CMD);
+	writel(SIRFSOC_SPI_FRM_END_INT_EN,
+		sspi->base + SIRFSOC_SPI_INT_EN);
+	writel(SIRFSOC_SPI_CMD_TX_EN,
+		sspi->base + SIRFSOC_SPI_TX_RX_EN);
+	if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
+		dev_err(&spi->dev, "cmd transfer timeout\n");
+		return 0;
+	}
 
-		if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
-			dev_err(&spi->dev, "transfer timeout\n");
-			return 0;
-		}
+	return t->len;
+}
 
-		return t->len;
-	}
+static void spi_sirfsoc_dma_transfer(struct spi_device *spi,
+	struct spi_transfer *t)
+{
+	struct sirfsoc_spi *sspi;
+	struct dma_async_tx_descriptor *rx_desc, *tx_desc;
+	int timeout = t->len * 10;
 
-	if (sspi->left_tx_word == 1) {
-		writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
-			SIRFSOC_SPI_ENA_AUTO_CLR,
-			sspi->base + SIRFSOC_SPI_CTRL);
-		writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
-		writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
-	} else if ((sspi->left_tx_word > 1) && (sspi->left_tx_word <
-				SIRFSOC_SPI_DAT_FRM_LEN_MAX)) {
+	sspi = spi_master_get_devdata(spi->master);
+	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
+	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
+	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
+	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
+	writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
+	writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
+	if (sspi->left_tx_word < SIRFSOC_SPI_DAT_FRM_LEN_MAX) {
 		writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
-				SIRFSOC_SPI_MUL_DAT_MODE |
-				SIRFSOC_SPI_ENA_AUTO_CLR,
+			SIRFSOC_SPI_ENA_AUTO_CLR | SIRFSOC_SPI_MUL_DAT_MODE,
 			sspi->base + SIRFSOC_SPI_CTRL);
 		writel(sspi->left_tx_word - 1,
 				sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
@@ -373,76 +366,109 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
 		writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
 		writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
 	}
-
-	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
-	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
-	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
-	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
-
-	if (IS_DMA_VALID(t)) {
-		struct dma_async_tx_descriptor *rx_desc, *tx_desc;
-
-		sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len, DMA_FROM_DEVICE);
-		rx_desc = dmaengine_prep_slave_single(sspi->rx_chan,
-			sspi->dst_start, t->len, DMA_DEV_TO_MEM,
-			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-		rx_desc->callback = spi_sirfsoc_dma_fini_callback;
-		rx_desc->callback_param = &sspi->rx_done;
-
-		sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len, DMA_TO_DEVICE);
-		tx_desc = dmaengine_prep_slave_single(sspi->tx_chan,
-			sspi->src_start, t->len, DMA_MEM_TO_DEV,
-			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-		tx_desc->callback = spi_sirfsoc_dma_fini_callback;
-		tx_desc->callback_param = &sspi->tx_done;
-
-		dmaengine_submit(tx_desc);
-		dmaengine_submit(rx_desc);
-		dma_async_issue_pending(sspi->tx_chan);
-		dma_async_issue_pending(sspi->rx_chan);
-	} else {
-		/* Send the first word to trigger the whole tx/rx process */
-		sspi->tx_word(sspi);
-
-		writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
-			SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN |
-			SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN |
-			SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN);
-	}
-
-	writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN);
-
-	if (!IS_DMA_VALID(t)) { /* for PIO */
-		if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0)
-			dev_err(&spi->dev, "transfer timeout\n");
-	} else if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {
+	sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len,
+					(t->tx_buf != t->rx_buf) ?
+					DMA_FROM_DEVICE : DMA_BIDIRECTIONAL);
+	rx_desc = dmaengine_prep_slave_single(sspi->rx_chan,
+		sspi->dst_start, t->len, DMA_DEV_TO_MEM,
+		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	rx_desc->callback = spi_sirfsoc_dma_fini_callback;
+	rx_desc->callback_param = &sspi->rx_done;
+
+	sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len,
+					(t->tx_buf != t->rx_buf) ?
+					DMA_TO_DEVICE : DMA_BIDIRECTIONAL);
+	tx_desc = dmaengine_prep_slave_single(sspi->tx_chan,
+		sspi->src_start, t->len, DMA_MEM_TO_DEV,
+		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	tx_desc->callback = spi_sirfsoc_dma_fini_callback;
+	tx_desc->callback_param = &sspi->tx_done;
+
+	dmaengine_submit(tx_desc);
+	dmaengine_submit(rx_desc);
+	dma_async_issue_pending(sspi->tx_chan);
+	dma_async_issue_pending(sspi->rx_chan);
+	writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
+			sspi->base + SIRFSOC_SPI_TX_RX_EN);
+	if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {
 		dev_err(&spi->dev, "transfer timeout\n");
 		dmaengine_terminate_all(sspi->rx_chan);
 	} else
 		sspi->left_rx_word = 0;
-
 	/*
 	 * we only wait tx-done event if transferring by DMA. for PIO,
 	 * we get rx data by writing tx data, so if rx is done, tx has
 	 * done earlier
 	 */
-	if (IS_DMA_VALID(t)) {
-		if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
-			dev_err(&spi->dev, "transfer timeout\n");
-			dmaengine_terminate_all(sspi->tx_chan);
-		}
+	if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
+		dev_err(&spi->dev, "transfer timeout\n");
+		dmaengine_terminate_all(sspi->tx_chan);
 	}
+	dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE);
+	dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE);
+	/* TX, RX FIFO stop */
+	writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
+	writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
+	if (sspi->left_tx_word >= SIRFSOC_SPI_DAT_FRM_LEN_MAX)
+		writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN);
+}
 
-	if (IS_DMA_VALID(t)) {
-		dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE);
-		dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE);
-	}
+static void spi_sirfsoc_pio_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct sirfsoc_spi *sspi;
+	int timeout = t->len * 10;
 
-	/* TX, RX FIFO stop */
+	sspi = spi_master_get_devdata(spi->master);
+	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
+	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
+	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
+	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
+	writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
+	writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
+	writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | SIRFSOC_SPI_MUL_DAT_MODE |
+		SIRFSOC_SPI_ENA_AUTO_CLR, sspi->base + SIRFSOC_SPI_CTRL);
+	writel(sspi->left_tx_word - 1,
+			sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
+	writel(sspi->left_rx_word - 1,
+			sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
+	sspi->tx_word(sspi);
+	writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
+		SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_RXFIFO_THD_INT_EN |
+		SIRFSOC_SPI_TXFIFO_THD_INT_EN | SIRFSOC_SPI_FRM_END_INT_EN|
+		SIRFSOC_SPI_RXFIFO_FULL_INT_EN,
+		sspi->base + SIRFSOC_SPI_INT_EN);
+	writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
+			sspi->base + SIRFSOC_SPI_TX_RX_EN);
+	if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0)
+		dev_err(&spi->dev, "transfer timeout\n");
 	writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
 	writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
 	writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN);
 	writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
+}
+
+static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct sirfsoc_spi *sspi;
+	sspi = spi_master_get_devdata(spi->master);
+
+	sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage;
+	sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage;
+	sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width;
+	reinit_completion(&sspi->rx_done);
+	reinit_completion(&sspi->tx_done);
+	/*
+	 * in the transfer, if transfer data using command register with rx_buf
+	 * null, just fill command data into command register and wait for its
+	 * completion.
+	 */
+	if (sspi->tx_by_cmd)
+		spi_sirfsoc_cmd_transfer(spi, t);
+	else if (IS_DMA_VALID(t))
+		spi_sirfsoc_dma_transfer(spi, t);
+	else
+		spi_sirfsoc_pio_transfer(spi, t);
 
 	return t->len - sspi->left_rx_word * sspi->word_width;
 }
@@ -470,7 +496,16 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
 		writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
 	} else {
 		int gpio = sspi->chipselect[spi->chip_select];
-		gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+		switch (value) {
+		case BITBANG_CS_ACTIVE:
+			gpio_direction_output(gpio,
+					spi->mode & SPI_CS_HIGH ? 1 : 0);
+			break;
+		case BITBANG_CS_INACTIVE:
+			gpio_direction_output(gpio,
+					spi->mode & SPI_CS_HIGH ? 0 : 1);
+			break;
+		}
 	}
 }
 
@@ -503,7 +538,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 		break;
 	case 12:
 	case 16:
-		regval |= (bits_per_word ==  12) ? SIRFSOC_SPI_TRAN_DAT_FORMAT_12 :
+		regval |= (bits_per_word ==  12) ?
+			SIRFSOC_SPI_TRAN_DAT_FORMAT_12 :
 			SIRFSOC_SPI_TRAN_DAT_FORMAT_16;
 		sspi->rx_word = spi_sirfsoc_rx_word_u16;
 		sspi->tx_word = spi_sirfsoc_tx_word_u16;
@@ -531,8 +567,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 		regval |= SIRFSOC_SPI_CLK_IDLE_STAT;
 
 	/*
-	 * Data should be driven at least 1/2 cycle before the fetch edge to make
-	 * sure that data gets stable at the fetch edge.
+	 * Data should be driven at least 1/2 cycle before the fetch edge
+	 * to make sure that data gets stable at the fetch edge.
 	 */
 	if (((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA)) ||
 	    (!(spi->mode & SPI_CPOL) && !(spi->mode & SPI_CPHA)))
@@ -559,16 +595,24 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 		regval &= ~SIRFSOC_SPI_CMD_MODE;
 		sspi->tx_by_cmd = false;
 	}
+	/*
+	 * set spi controller in RISC chipselect mode, we are controlling CS by
+	 * software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE.
+	 */
+	regval |= SIRFSOC_SPI_CS_IO_MODE;
 	writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
 
 	if (IS_DMA_VALID(t)) {
 		/* Enable DMA mode for RX, TX */
 		writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
-		writel(SIRFSOC_SPI_RX_DMA_FLUSH, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
+		writel(SIRFSOC_SPI_RX_DMA_FLUSH,
+			sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
 	} else {
 		/* Enable IO mode for RX, TX */
-		writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
-		writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
+		writel(SIRFSOC_SPI_IO_MODE_SEL,
+			sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
+		writel(SIRFSOC_SPI_IO_MODE_SEL,
+			sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
 	}
 
 	return 0;
@@ -598,7 +642,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
 		goto err_cs;
 	}
 
-	master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs);
+	master = spi_alloc_master(&pdev->dev,
+			sizeof(*sspi) + sizeof(int) * num_cs);
 	if (!master) {
 		dev_err(&pdev->dev, "Unable to allocate SPI master\n");
 		return -ENOMEM;
@@ -794,8 +839,7 @@ static struct platform_driver spi_sirfsoc_driver = {
 	.remove = spi_sirfsoc_remove,
 };
 module_platform_driver(spi_sirfsoc_driver);
-
 MODULE_DESCRIPTION("SiRF SoC SPI master driver");
-MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>, "
-		"Barry Song <Baohua.Song@csr.com>");
+MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>");
+MODULE_AUTHOR("Barry Song <Baohua.Song@csr.com>");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index d266a8702067..85204c93f3d3 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-#include <linux/workqueue.h>
 
 #include <linux/spi/spi.h>
 
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index b3e3498a7e6f..bd24093f4038 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -20,7 +20,6 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
-#include <linux/workqueue.h>
 
 #include <linux/spi/spi.h>
 
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 4eb9bf02996c..38ba75ab393f 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -775,7 +775,7 @@ static int spi_transfer_one_message(struct spi_master *master,
 		if (ret > 0) {
 			ret = 0;
 			ms = xfer->len * 8 * 1000 / xfer->speed_hz;
-			ms += 10; /* some tolerance */
+			ms += ms + 100; /* some tolerance */
 
 			ms = wait_for_completion_timeout(&master->xfer_completion,
 							 msecs_to_jiffies(ms));
@@ -1234,6 +1234,8 @@ static void of_register_spi_devices(struct spi_master *master)
 			spi->mode |= SPI_CS_HIGH;
 		if (of_find_property(nc, "spi-3wire", NULL))
 			spi->mode |= SPI_3WIRE;
+		if (of_find_property(nc, "spi-lsb-first", NULL))
+			spi->mode |= SPI_LSB_FIRST;
 
 		/* Device DUAL/QUAD mode */
 		if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index ea5efb426f75..22365f140bec 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -40,8 +40,6 @@ source "drivers/staging/olpc_dcon/Kconfig"
 
 source "drivers/staging/panel/Kconfig"
 
-source "drivers/staging/rtl8187se/Kconfig"
-
 source "drivers/staging/rtl8192u/Kconfig"
 
 source "drivers/staging/rtl8192e/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 86e020c2ad0d..fbe84ed2d048 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB)	+= wlan-ng/
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_FB_OLPC_DCON)	+= olpc_dcon/
 obj-$(CONFIG_PANEL)		+= panel/
-obj-$(CONFIG_R8187SE)		+= rtl8187se/
 obj-$(CONFIG_RTL8192U)		+= rtl8192u/
 obj-$(CONFIG_RTL8192E)		+= rtl8192e/
 obj-$(CONFIG_R8712U)		+= rtl8712/
diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c
index 632f81a7c63f..4564c63f908c 100644
--- a/drivers/staging/bcm/CmHost.c
+++ b/drivers/staging/bcm/CmHost.c
@@ -460,42 +460,30 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "CopyToAdapter : u8CSSpecification : %X\n", psfLocalSet->u8CSSpecification);
 	switch (psfLocalSet->u8CSSpecification) {
 	case eCSPacketIPV4:
-	{
 		Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS;
 		break;
-	}
 	case eCSPacketIPV6:
-	{
 		Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS;
 		break;
-	}
 	case eCS802_3PacketEthernet:
 	case eCS802_1QPacketVLAN:
-	{
 		Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3;
 		break;
-	}
 	case eCSPacketIPV4Over802_1QVLAN:
 	case eCSPacketIPV4Over802_3Ethernet:
-	{
 		Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS;
 		Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3;
 		break;
-	}
 	case eCSPacketIPV6Over802_1QVLAN:
 	case eCSPacketIPV6Over802_3Ethernet:
-	{
 		Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS;
 		Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3;
 		break;
-	}
 	default:
-	{
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Error in value of CS Classification.. setting default to IP CS\n");
 		Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS;
 		break;
 	}
-	}
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "CopyToAdapter : Queue No : %X ETH CS Support :  %X  , IP CS Support : %X\n",
 			uiSearchRuleIndex,
@@ -542,32 +530,23 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 		} else if (ucDsxType == DSC_ACK) {
 			switch (psfCSType->u8ClassfierDSCAction) {
 			case 0: /* DSC Add Classifier */
-			{
 				eClassifierAction = eAddClassifier;
-			}
-			break;
+				break;
 			case 1: /* DSC Replace Classifier */
-			{
 				eClassifierAction = eReplaceClassifier;
-			}
-			break;
+				break;
 			case 2: /* DSC Delete Classifier */
-			{
 				eClassifierAction = eDeleteClassifier;
-			}
-			break;
+				break;
 			default:
-			{
 				eClassifierAction = eInvalidClassifierAction;
 			}
-			}
 		}
 
 		u16PacketClassificationRuleIndex = ntohs(psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex);
 
 		switch (eClassifierAction) {
 		case eAddClassifier:
-		{
 			/* Get a Free Classifier Index From Classifier table for this SF to add the Classifier */
 			/* Contained in this message */
 			nClassifierIndex = SearchClsid(Adapter, ulSFID, u16PacketClassificationRuleIndex);
@@ -587,10 +566,8 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 						"CopyToAdapter: Error The Specified Classifier Already Exists and attempted To Add Classifier with Same PCRI : 0x%x\n",
 						u16PacketClassificationRuleIndex);
 			}
-		}
-		break;
+			break;
 		case eReplaceClassifier:
-		{
 			/* Get the Classifier Index From Classifier table for this SF and replace existing  Classifier */
 			/* with the new classifier Contained in this message */
 			nClassifierIndex = SearchClsid(Adapter, ulSFID, u16PacketClassificationRuleIndex);
@@ -601,10 +578,8 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 			}
 			/* Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. */
 			CopyClassifierRuleToSF(Adapter, psfCSType, uiSearchRuleIndex, nClassifierIndex);
-		}
-		break;
+			break;
 		case eDeleteClassifier:
-		{
 			/* Get the Classifier Index From Classifier table for this SF and replace existing  Classifier */
 			/* with the new classifier Contained in this message */
 			nClassifierIndex = SearchClsid(Adapter, ulSFID, u16PacketClassificationRuleIndex);
@@ -616,14 +591,11 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 
 			/* Delete This classifier */
 			DeleteClassifierRuleFromSF(Adapter, uiSearchRuleIndex, nClassifierIndex);
-		}
-		break;
+			break;
 		default:
-		{
 			/* Invalid Action for classifier */
 			break;
 		}
-		}
 	}
 
 	/* Repeat parsing Classification Entries to process PHS Rules */
@@ -633,35 +605,28 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 
 		switch (psfCSType->u8PhsDSCAction) {
 		case eDeleteAllPHSRules:
-		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Deleting All PHS Rules For VCID: 0x%X\n", uVCID);
 
 			/* Delete All the PHS rules for this Service flow */
 			PhsDeleteSFRules(&Adapter->stBCMPhsContext, uVCID);
 			break;
-		}
 		case eDeletePHSRule:
-		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "PHS DSC Action = Delete PHS Rule\n");
 
 			if (psfCSType->cPhsRule.u8PHSI)
 				PhsDeletePHSRule(&Adapter->stBCMPhsContext, uVCID, psfCSType->cCPacketClassificationRule.u8AssociatedPHSI);
 
 			break;
-		}
 		default:
-		{
 			if (ucDsxType == DSC_ACK) {
 				/* BCM_DEBUG_PRINT(CONN_MSG,("Invalid PHS DSC Action For DSC\n",psfCSType->cPhsRule.u8PHSI)); */
 				break; /* FOr DSC ACK Case PHS DSC Action must be in valid set */
 			}
-		}
 		/* Proceed To Add PHS rule for DSA_ACK case even if PHS DSC action is unspecified */
 		/* No Break Here . Intentionally! */
 
 		case eAddPHSRule:
 		case eSetPHSRule:
-		{
 			if (psfCSType->cPhsRule.u8PHSI)	{
 				/* Apply This PHS Rule to all classifiers whose Associated PHSI Match */
 				unsigned int uiClassifierIndex = 0;
@@ -738,8 +703,7 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 						sPhsRule.u8PHSI);
 				}
 			}
-		}
-		break;
+			break;
 		}
 	}
 
diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c
index 4f315835ddfc..09e548aef812 100644
--- a/drivers/staging/bcm/Qos.c
+++ b/drivers/staging/bcm/Qos.c
@@ -33,14 +33,11 @@ static bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULO
 	ulSrcIP = ntohl(ulSrcIP);
 	if (0 == pstClassifierRule->ucIPSourceAddressLength)
 		return TRUE;
-	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength); ucLoopIndex++)
-	{
+	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength); ucLoopIndex++) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]);
 		if ((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP) ==
 				(pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]))
-		{
 			return TRUE;
-		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched");
 	return false;
@@ -68,13 +65,10 @@ static bool MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, UL
 		return TRUE;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x  ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]);
 
-	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength); ucLoopIndex++)
-	{
+	for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength); ucLoopIndex++) {
 		if ((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP) ==
 				(pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex]))
-		{
 			return TRUE;
-		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched");
 	return false;
@@ -99,9 +93,8 @@ static bool MatchTos(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucType
 		return TRUE;
 
 	if (((pstClassifierRule->ucTosMask & ucTypeOfService) <= pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService) >= pstClassifierRule->ucTosLow))
-	{
 		return TRUE;
-	}
+
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched");
 	return false;
 }
@@ -123,13 +116,10 @@ bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucProtoc
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 	if (0 == pstClassifierRule->ucProtocolLength)
 		return TRUE;
-	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucProtocolLength; ucLoopIndex++)
-	{
+	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucProtocolLength; ucLoopIndex++) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X", ucProtocol, pstClassifierRule->ucProtocol[ucLoopIndex]);
 		if (pstClassifierRule->ucProtocol[ucLoopIndex] == ucProtocol)
-		{
 			return TRUE;
-		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched");
 	return false;
@@ -155,13 +145,10 @@ bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushSrcPo
 
 	if (0 == pstClassifierRule->ucSrcPortRangeLength)
 		return TRUE;
-	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength; ucLoopIndex++)
-	{
+	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength; ucLoopIndex++) {
 		if (ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] &&
 			ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex])
-		{
 			return TRUE;
-		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ", ushSrcPort);
 	return false;
@@ -186,15 +173,12 @@ bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushDest
 	if (0 == pstClassifierRule->ucDestPortRangeLength)
 		return TRUE;
 
-	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucDestPortRangeLength; ucLoopIndex++)
-	{
+	for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucDestPortRangeLength; ucLoopIndex++) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X   0x%X  0x%X", ushDestPort, pstClassifierRule->usDestPortRangeLo[ucLoopIndex], pstClassifierRule->usDestPortRangeHi[ucLoopIndex]);
 
 		if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] &&
 			ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex])
-		{
 			return TRUE;
-		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched", ushDestPort);
 	return false;
@@ -273,21 +257,13 @@ static USHORT	IpVersion4(struct bcm_mini_adapter *Adapter,
 		bClassificationSucceed = TRUE;
 	} while (0);
 
-	if (TRUE == bClassificationSucceed)
-	{
+	if (TRUE == bClassificationSucceed) {
 		INT iMatchedSFQueueIndex = 0;
 		iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
 		if (iMatchedSFQueueIndex >= NO_OF_QUEUES)
-		{
 			bClassificationSucceed = false;
-		}
-		else
-		{
-			if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
-			{
-				bClassificationSucceed = false;
-			}
-		}
+		else if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
+			bClassificationSucceed = false;
 	}
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <==========");
@@ -299,8 +275,7 @@ VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter)
 {
 	UINT iIndex = 0;
 
-	for (iIndex = 0; iIndex < HiPriority; iIndex++)
-	{
+	for (iIndex = 0; iIndex < HiPriority; iIndex++) {
 		if (!Adapter->PackInfo[iIndex].bValid)
 			continue;
 
@@ -334,10 +309,10 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
 
 	spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock);
 
-	while (1)
+	while (1) {
 //	while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost >
-//		SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
-	{
+//		SF_MAX_ALLOWED_PACKETS_TO_BACKUP) {
+
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x",
 		Adapter->PackInfo[iIndex].uiCurrentBytesOnHost,
 		Adapter->PackInfo[iIndex].uiMaxBucketSize);
@@ -350,8 +325,7 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex)
 			((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb)+SKB_CB_LATENCY_OFFSET))/HZ) <= Adapter->PackInfo[iIndex].uiMaxLatency))
 			break;
 
-		if (PacketToDrop)
-		{
+		if (PacketToDrop) {
 			if (netif_msg_tx_err(Adapter))
 				pr_info(PFX "%s: tx queue %d overlimit\n",
 					Adapter->dev->name, iIndex);
@@ -394,20 +368,16 @@ VOID flush_all_queues(struct bcm_mini_adapter *Adapter)
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>");
 
 //	down(&Adapter->data_packet_queue_lock);
-	for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++)
-	{
+	for (iQIndex = LowPriority; iQIndex < HiPriority; iQIndex++) {
 		struct net_device_stats *netstats = &Adapter->dev->stats;
 
 		spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
-		while (Adapter->PackInfo[iQIndex].FirstTxQueue)
-		{
+		while (Adapter->PackInfo[iQIndex].FirstTxQueue) {
 			PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
-			if (PacketToDrop)
-			{
+			if (PacketToDrop) {
 				uiTotalPacketLength = PacketToDrop->len;
 				netstats->tx_dropped++;
-			}
-			else
+			} else
 				uiTotalPacketLength = 0;
 
 			DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue,
@@ -455,58 +425,42 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
 	*((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET) = 0;
 	EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo);
 
-	switch (stEthCsPktInfo.eNwpktEthFrameType)
-	{
+	switch (stEthCsPktInfo.eNwpktEthFrameType) {
 		case eEth802LLCFrame:
-		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLCFrame\n");
 			pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_frame);
 			break;
-		}
-
 		case eEth802LLCSNAPFrame:
-		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLC SNAP Frame\n");
 			pIpHeader = pvEThPayload + sizeof(struct bcm_eth_llc_snap_frame);
 			break;
-		}
 		case eEth802QVLANFrame:
-		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802.1Q VLANFrame\n");
 			pIpHeader = pvEThPayload + sizeof(struct bcm_eth_q_frame);
 			break;
-		}
 		case eEthOtherFrame:
-		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : ETH Other Frame\n");
 			pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
 			break;
-		}
 		default:
-		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Unrecognized ETH Frame\n");
 			pIpHeader = pvEThPayload + sizeof(struct bcm_ethernet2_frame);
 			break;
-		}
 	}
 
-	if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet)
-	{
+	if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) {
 		usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET);
 		if ((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment)
 			bFragmentedPkt = TRUE;
 
-		if (bFragmentedPkt)
-		{
+		if (bFragmentedPkt) {
 				//Fragmented  Packet. Get Frag Classifier Entry.
 			pstClassifierRule = GetFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
-			if (pstClassifierRule)
-			{
+			if (pstClassifierRule) {
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "It is next Fragmented pkt");
 					bClassificationSucceed = TRUE;
 			}
-			if (!(ntohs(pIpHeader->frag_off) & IP_MF))
-			{
+			if (!(ntohs(pIpHeader->frag_off) & IP_MF)) {
 				//Fragmented Last packet . Remove Frag Classifier Entry
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "This is the last fragmented Pkt");
 				DelFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr);
@@ -514,23 +468,19 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
 		}
 	}
 
-	for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--)
-	{
+	for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) {
 		if (bClassificationSucceed)
 			break;
 		//Iterate through all classifiers which are already in order of priority
 		//to classify the packet until match found
-		do
-		{
-			if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed)
-			{
+		do {
+			if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed) {
 				bClassificationSucceed = false;
 				break;
 			}
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex);
 
-			if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection)
-			{
+			if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) {
 				bClassificationSucceed = false;//cannot be processed for classification.
 				break;						// it is a down link connection
 			}
@@ -543,11 +493,9 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
 				break;
 			}
 
-			if (Adapter->PackInfo[uiSfIndex].bEthCSSupport)
-			{
+			if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) {
 
-				if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType)
-				{
+				if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) {
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
 					bClassificationSucceed = false;
 					break;
@@ -558,17 +506,12 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n", pstClassifierRule->uiClassifierRuleIndex, Adapter->PackInfo[uiSfIndex].ulSFID);
 				bClassificationSucceed = EThCSClassifyPkt(Adapter, skb, &stEthCsPktInfo, pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport);
 
-				if (!bClassificationSucceed)
-				{
+				if (!bClassificationSucceed) {
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ClassifyPacket : Ethernet CS Classification Failed\n");
 					break;
 				}
-			}
-
-			else // No ETH Supported on this SF
-			{
-				if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType)
-				{
+			} else {	// No ETH Supported on this SF
+				if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) {
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
 					bClassificationSucceed = false;
 					break;
@@ -577,11 +520,9 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
 
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Proceeding to IP CS Clasification");
 
-			if (Adapter->PackInfo[uiSfIndex].bIPCSSupport)
-			{
+			if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) {
 
-				if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket)
-				{
+				if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) {
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet\n");
 					bClassificationSucceed = false;
 					break;
@@ -598,31 +539,26 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb)
 		} while (0);
 	}
 
-	if (bClassificationSucceed == TRUE)
-	{
+	if (bClassificationSucceed == TRUE) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu", pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID);
 
 		//Store The matched Classifier in SKB
 		*((UINT32*)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex;
-		if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len))
-		{
+		if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len)) {
 			 IpHeaderLength   = pIpHeader->ihl;
 			 pTcpHeader = (struct bcm_tcp_header *)(((PUCHAR)pIpHeader)+(IpHeaderLength*4));
 			 TcpHeaderLength  = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength);
 
 			if ((pTcpHeader->ucFlags & TCP_ACK) &&
 			   (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4)))
-			{
 				*((UINT32*) (skb->cb) + SKB_CB_TCPACK_OFFSET) = TCP_ACK;
-			}
 		}
 
 		usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is	=%d", usIndex);
 
 		//If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt.
-		if (bFragmentedPkt && (usCurrFragment == 0))
-		{
+		if (bFragmentedPkt && (usCurrFragment == 0)) {
 			//First Fragment of Fragmented Packet. Create Frag CLS Entry
 			struct bcm_fragmented_packet_info stFragPktInfo;
 			stFragPktInfo.bUsed = TRUE;
@@ -649,8 +585,7 @@ static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRul
 	if (pstClassifierRule->ucEthCSSrcMACLen == 0)
 		return TRUE;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s\n", __FUNCTION__);
-	for (i = 0; i < MAC_ADDRESS_SIZE; i++)
-	{
+	for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSSrcMAC[i], pstClassifierRule->au8EThCSSrcMACMask[i]);
 		if ((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i]) !=
 			(Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
@@ -666,8 +601,7 @@ static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRu
 	if (pstClassifierRule->ucEthCSDestMACLen == 0)
 		return TRUE;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s\n", __FUNCTION__);
-	for (i = 0; i < MAC_ADDRESS_SIZE; i++)
-	{
+	for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSDestMAC[i], pstClassifierRule->au8EThCSDestMACMask[i]);
 		if ((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i]) !=
 			(Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
@@ -684,8 +618,7 @@ static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,
 		return TRUE;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s SrcEtherType:%x CLS EtherType[0]:%x\n", __FUNCTION__, pstEthCsPktInfo->usEtherType, pstClassifierRule->au8EthCSEtherType[0]);
-	if (pstClassifierRule->au8EthCSEtherType[0] == 1)
-	{
+	if (pstClassifierRule->au8EthCSEtherType[0] == 1) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS EtherType[1]:%x EtherType[2]:%x\n", __FUNCTION__, pstClassifierRule->au8EthCSEtherType[1], pstClassifierRule->au8EthCSEtherType[2]);
 
 		if (memcmp(&pstEthCsPktInfo->usEtherType, &pstClassifierRule->au8EthCSEtherType[1], 2) == 0)
@@ -694,8 +627,7 @@ static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,
 			return false;
 	}
 
-	if (pstClassifierRule->au8EthCSEtherType[0] == 2)
-	{
+	if (pstClassifierRule->au8EthCSEtherType[0] == 2) {
 		if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
 			return false;
 
@@ -721,8 +653,7 @@ static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, s
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS UserPrio:%x CLS VLANID:%x\n", __FUNCTION__, ntohs(*((USHORT *)pstClassifierRule->usUserPriority)), pstClassifierRule->usVLANID);
 
 	/* In case FW didn't receive the TLV, the priority field should be ignored */
-	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID))
-	{
+	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID)) {
 		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
 				return false;
 
@@ -739,8 +670,7 @@ static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, s
 
 	bClassificationSucceed = false;
 
-	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID))
-	{
+	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID)) {
 		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
 				return false;
 
@@ -800,32 +730,24 @@ static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload
 	USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype);
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype);
-	if (u16Etype > 0x5dc)
-	{
+	if (u16Etype > 0x5dc) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame\n");
 		//ETH2 Frame
-		if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN)
-		{
+		if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN) {
 			//802.1Q VLAN Header
 			pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame;
 			u16Etype = ((struct bcm_eth_q_frame *)pvEthPayload)->EthType;
 			//((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority
-		}
-		else
-		{
+		} else {
 			pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame;
 			u16Etype = ntohs(u16Etype);
 		}
-
-	}
-	else
-	{
+	} else {
 		//802.2 LLC
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame\n");
 		pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame;
 		pstEthCsPktInfo->ucDSAP = ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP;
-		if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA)
-		{
+		if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) {
 			//SNAP Frame
 			pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame;
 			u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType;
diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c
index 39ace5510c43..42d9004e357d 100644
--- a/drivers/staging/bcm/hostmibs.c
+++ b/drivers/staging/bcm/hostmibs.c
@@ -9,37 +9,40 @@
 
 #include "headers.h"
 
-INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_mibs *pstHostMibs)
+INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter,
+		       struct bcm_host_stats_mibs *pstHostMibs)
 {
 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
 	struct bcm_phs_rule *pstPhsRule = NULL;
 	struct bcm_phs_classifier_table *pstClassifierTable = NULL;
 	struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
-	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *) &Adapter->stBCMPhsContext;
-
-	UINT nClassifierIndex = 0, nPhsTableIndex = 0, nSfIndex = 0, uiIndex = 0;
+	struct bcm_phs_extension *pDeviceExtension = &Adapter->stBCMPhsContext;
+	UINT nClassifierIndex = 0;
+	UINT nPhsTableIndex = 0;
+	UINT nSfIndex = 0;
+	UINT uiIndex = 0;
 
 	if (pDeviceExtension == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, HOST_MIBS, DBG_LVL_ALL, "Invalid Device Extension\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, HOST_MIBS,
+				DBG_LVL_ALL, "Invalid Device Extension\n");
 		return STATUS_FAILURE;
 	}
 
 	/* Copy the classifier Table */
-	for (nClassifierIndex = 0; nClassifierIndex < MAX_CLASSIFIERS; nClassifierIndex++) {
+	for (nClassifierIndex = 0; nClassifierIndex < MAX_CLASSIFIERS;
+							nClassifierIndex++) {
 		if (Adapter->astClassifierTable[nClassifierIndex].bUsed == TRUE)
-			memcpy((PVOID) &pstHostMibs->
-			       astClassifierTable[nClassifierIndex],
-			       (PVOID) &Adapter->
-			       astClassifierTable[nClassifierIndex],
+			memcpy(&pstHostMibs->astClassifierTable[nClassifierIndex],
+			       &Adapter->astClassifierTable[nClassifierIndex],
 			       sizeof(struct bcm_mibs_classifier_rule));
 	}
 
 	/* Copy the SF Table */
 	for (nSfIndex = 0; nSfIndex < NO_OF_QUEUES; nSfIndex++) {
 		if (Adapter->PackInfo[nSfIndex].bValid) {
-			memcpy((PVOID) &pstHostMibs->astSFtable[nSfIndex],
-			       (PVOID) &Adapter->PackInfo[nSfIndex],
-				sizeof(struct bcm_mibs_table));
+			memcpy(&pstHostMibs->astSFtable[nSfIndex],
+			       &Adapter->PackInfo[nSfIndex],
+			       sizeof(struct bcm_mibs_table));
 		} else {
 			/* If index in not valid,
 			 * don't process this for the PHS table.
@@ -68,9 +71,9 @@ INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_m
 				pstHostMibs->astPhsRulesTable[nPhsTableIndex].
 				    ulSFID = Adapter->PackInfo[nSfIndex].ulSFID;
 
-				memcpy(&pstHostMibs->
-				       astPhsRulesTable[nPhsTableIndex].u8PHSI,
-				       &pstPhsRule->u8PHSI, sizeof(struct bcm_phs_rule));
+				memcpy(&pstHostMibs->astPhsRulesTable[nPhsTableIndex].u8PHSI,
+				       &pstPhsRule->u8PHSI,
+				       sizeof(struct bcm_phs_rule));
 				nPhsTableIndex++;
 
 			}
@@ -82,26 +85,32 @@ INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_m
 	/* Copy other Host Statistics parameters */
 	pstHostMibs->stHostInfo.GoodTransmits = Adapter->dev->stats.tx_packets;
 	pstHostMibs->stHostInfo.GoodReceives = Adapter->dev->stats.rx_packets;
-	pstHostMibs->stHostInfo.CurrNumFreeDesc = atomic_read(&Adapter->CurrNumFreeTxDesc);
+	pstHostMibs->stHostInfo.CurrNumFreeDesc =
+				atomic_read(&Adapter->CurrNumFreeTxDesc);
 	pstHostMibs->stHostInfo.BEBucketSize = Adapter->BEBucketSize;
 	pstHostMibs->stHostInfo.rtPSBucketSize = Adapter->rtPSBucketSize;
 	pstHostMibs->stHostInfo.TimerActive = Adapter->TimerActive;
 	pstHostMibs->stHostInfo.u32TotalDSD = Adapter->u32TotalDSD;
 
-	memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist, Adapter->aTxPktSizeHist, sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
-	memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist, Adapter->aRxPktSizeHist, sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
+	memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist, Adapter->aTxPktSizeHist,
+	       sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
+	memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist, Adapter->aRxPktSizeHist,
+	       sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES);
 
 	return STATUS_SUCCESS;
 }
 
-VOID GetDroppedAppCntrlPktMibs(struct bcm_host_stats_mibs *pstHostMibs, struct bcm_tarang_data *pTarang)
+VOID GetDroppedAppCntrlPktMibs(struct bcm_host_stats_mibs *pstHostMibs,
+			       struct bcm_tarang_data *pTarang)
 {
 	memcpy(&(pstHostMibs->stDroppedAppCntrlMsgs),
 	       &(pTarang->stDroppedAppCntrlMsgs),
 	       sizeof(struct bcm_mibs_dropped_cntrl_msg));
 }
 
-VOID CopyMIBSExtendedSFParameters(struct bcm_mini_adapter *Adapter, struct bcm_connect_mgr_params *psfLocalSet, UINT uiSearchRuleIndex)
+VOID CopyMIBSExtendedSFParameters(struct bcm_mini_adapter *Adapter,
+				  struct bcm_connect_mgr_params *psfLocalSet,
+				  UINT uiSearchRuleIndex)
 {
 	struct bcm_mibs_parameters *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable;
 
diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
index 924fce977985..257595016161 100644
--- a/drivers/staging/comedi/comedi_buf.c
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -61,6 +61,8 @@ static void __comedi_buf_free(struct comedi_device *dev,
 			      struct comedi_subdevice *s)
 {
 	struct comedi_async *async = s->async;
+	struct comedi_buf_map *bm;
+	unsigned long flags;
 
 	if (async->prealloc_buf) {
 		vunmap(async->prealloc_buf);
@@ -68,8 +70,11 @@ static void __comedi_buf_free(struct comedi_device *dev,
 		async->prealloc_bufsz = 0;
 	}
 
-	comedi_buf_map_put(async->buf_map);
+	spin_lock_irqsave(&s->spin_lock, flags);
+	bm = async->buf_map;
 	async->buf_map = NULL;
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+	comedi_buf_map_put(bm);
 }
 
 static void __comedi_buf_alloc(struct comedi_device *dev,
@@ -80,6 +85,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
 	struct page **pages = NULL;
 	struct comedi_buf_map *bm;
 	struct comedi_buf_page *buf;
+	unsigned long flags;
 	unsigned i;
 
 	if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
@@ -92,8 +98,10 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
 	if (!bm)
 		return;
 
-	async->buf_map = bm;
 	kref_init(&bm->refcount);
+	spin_lock_irqsave(&s->spin_lock, flags);
+	async->buf_map = bm;
+	spin_unlock_irqrestore(&s->spin_lock, flags);
 	bm->dma_dir = s->async_dma_dir;
 	if (bm->dma_dir != DMA_NONE)
 		/* Need ref to hardware device to free buffer later. */
@@ -127,7 +135,9 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
 
 		pages[i] = virt_to_page(buf->virt_addr);
 	}
+	spin_lock_irqsave(&s->spin_lock, flags);
 	bm->n_pages = i;
+	spin_unlock_irqrestore(&s->spin_lock, flags);
 
 	/* vmap the prealloc_buf if all the pages were allocated */
 	if (i == n_pages)
@@ -150,6 +160,29 @@ int comedi_buf_map_put(struct comedi_buf_map *bm)
 	return 1;
 }
 
+/* returns s->async->buf_map and increments its kref refcount */
+struct comedi_buf_map *
+comedi_buf_map_from_subdev_get(struct comedi_subdevice *s)
+{
+	struct comedi_async *async = s->async;
+	struct comedi_buf_map *bm = NULL;
+	unsigned long flags;
+
+	if (!async)
+		return NULL;
+
+	spin_lock_irqsave(&s->spin_lock, flags);
+	bm = async->buf_map;
+	/* only want it if buffer pages allocated */
+	if (bm && bm->n_pages)
+		comedi_buf_map_get(bm);
+	else
+		bm = NULL;
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+
+	return bm;
+}
+
 bool comedi_buf_is_mmapped(struct comedi_async *async)
 {
 	struct comedi_buf_map *bm = async->buf_map;
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index ea6dc36d753b..70545e670dd0 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1435,13 +1435,15 @@ static int __comedi_get_user_cmd(struct comedi_device *dev,
 	s = &dev->subdevices[cmd->subdev];
 
 	if (s->type == COMEDI_SUBD_UNUSED) {
-		dev_dbg(dev->class_dev, "%d not valid subdevice\n", cmd->subdev);
+		dev_dbg(dev->class_dev, "%d not valid subdevice\n",
+			cmd->subdev);
 		return -EIO;
 	}
 
 	if (!s->do_cmd || !s->do_cmdtest || !s->async) {
 		dev_dbg(dev->class_dev,
-			"subdevice %d does not support commands\n", cmd->subdev);
+			"subdevice %d does not support commands\n",
+			cmd->subdev);
 		return -EIO;
 	}
 
@@ -1597,7 +1599,6 @@ static int do_cmdtest_ioctl(struct comedi_device *dev,
 {
 	struct comedi_cmd cmd;
 	struct comedi_subdevice *s;
-	unsigned int *chanlist = NULL;
 	unsigned int __user *user_chanlist;
 	int ret;
 
@@ -1626,8 +1627,6 @@ static int do_cmdtest_ioctl(struct comedi_device *dev,
 		ret = -EFAULT;
 	}
 
-	kfree(chanlist);
-
 	return ret;
 }
 
@@ -1926,14 +1925,21 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
 	struct comedi_device *dev = file->private_data;
 	struct comedi_subdevice *s;
 	struct comedi_async *async;
-	struct comedi_buf_map *bm;
+	struct comedi_buf_map *bm = NULL;
 	unsigned long start = vma->vm_start;
 	unsigned long size;
 	int n_pages;
 	int i;
 	int retval;
 
-	mutex_lock(&dev->mutex);
+	/*
+	 * 'trylock' avoids circular dependency with current->mm->mmap_sem
+	 * and down-reading &dev->attach_lock should normally succeed without
+	 * contention unless the device is in the process of being attached
+	 * or detached.
+	 */
+	if (!down_read_trylock(&dev->attach_lock))
+		return -EAGAIN;
 
 	if (!dev->attached) {
 		dev_dbg(dev->class_dev, "no driver attached\n");
@@ -1973,7 +1979,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
 	}
 
 	n_pages = size >> PAGE_SHIFT;
-	bm = async->buf_map;
+
+	/* get reference to current buf map (if any) */
+	bm = comedi_buf_map_from_subdev_get(s);
 	if (!bm || n_pages > bm->n_pages) {
 		retval = -EINVAL;
 		goto done;
@@ -1997,7 +2005,8 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
 
 	retval = 0;
 done:
-	mutex_unlock(&dev->mutex);
+	up_read(&dev->attach_lock);
+	comedi_buf_map_put(bm);	/* put reference to buf map - okay if NULL */
 	return retval;
 }
 
diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h
index 9a746570f161..a492f2d2436e 100644
--- a/drivers/staging/comedi/comedi_internal.h
+++ b/drivers/staging/comedi/comedi_internal.h
@@ -19,6 +19,8 @@ void comedi_buf_reset(struct comedi_async *async);
 bool comedi_buf_is_mmapped(struct comedi_async *async);
 void comedi_buf_map_get(struct comedi_buf_map *bm);
 int comedi_buf_map_put(struct comedi_buf_map *bm);
+struct comedi_buf_map *comedi_buf_map_from_subdev_get(
+		struct comedi_subdevice *s);
 unsigned int comedi_buf_write_n_allocated(struct comedi_async *async);
 void comedi_device_cancel_all(struct comedi_device *dev);
 
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index ab0e8ed47291..cb5d21411a0c 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -258,6 +258,7 @@ static int insn_rw_emulate_bits(struct comedi_device *dev,
 	const unsigned base_bitfield_channel =
 	    (chan < channels_per_bitfield) ? 0 : chan;
 	unsigned int new_data[2];
+
 	memset(new_data, 0, sizeof(new_data));
 	memset(&new_insn, 0, sizeof(new_insn));
 	new_insn.insn = INSN_BITS;
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index 0daa0ea63b5e..d6a5424654fc 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -379,5 +379,5 @@ static struct pci_driver apci1032_pci_driver = {
 module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("ADDI-DATA APCI-1032, 32 channel DI boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index bd8e08ca14c0..eab75eb26478 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -72,5 +72,5 @@ static struct pci_driver apci1500_pci_driver = {
 module_comedi_pci_driver(apci1500_driver, apci1500_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("ADDI-DATA APCI-1500, 16 channel DI / 16 channel DO boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 27aa9ae1bdd9..11aa0bd5d7b1 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -70,5 +70,5 @@ static struct pci_driver apci1564_pci_driver = {
 module_comedi_pci_driver(apci1564_driver, apci1564_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("ADDI-DATA APCI-1564, 32 channel DI / 32 channel DO boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index c9b933cb5987..feefc7a5ca9a 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -374,5 +374,5 @@ static struct pci_driver apci2032_pci_driver = {
 module_comedi_pci_driver(apci2032_driver, apci2032_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("ADDI-DATA APCI-2032, 32 channel DO boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index 57ee6e5c7635..0cfb12fa1cbc 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -246,5 +246,5 @@ static struct pci_driver apci3120_pci_driver = {
 module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 3cfa1756fa6a..b6abef6ceab7 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -96,7 +96,7 @@ Configuration options:
 				 * correct channel number on every 12 bit sample
 				 */
 
-#define IORANGE_9118 	64	/* I hope */
+#define IORANGE_9118	64	/* I hope */
 #define PCI9118_CHANLEN	255	/*
 				 * len of chanlist, some source say 256,
 				 * but reality looks like 255 :-(
@@ -383,7 +383,7 @@ struct pci9118_private {
 						 * users(0-AI, 1-AO, 2-DI, 3-DO)
 						 */
 	unsigned int cnt0_divisor;		/* actual CNT0 divisor */
-	void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *,
+	void (*int_ai_func)(struct comedi_device *, struct comedi_subdevice *,
 		unsigned short,
 		unsigned int,
 		unsigned short);	/*
@@ -1045,7 +1045,7 @@ static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
 		move_block_from_dma(dev, s,
 				    devpriv->dmabuf_virt[devpriv->dma_actbuf],
 				    samplesinbuf);
-		m = m - sampls;		/* m= how many samples was transferred */
+		m = m - sampls;		/* m=how many samples was transferred */
 	}
 
 	if (!devpriv->ai_neverending) {
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index e0cfb6cb547b..d18eea6c01aa 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -125,7 +125,7 @@ struct das6402_boardinfo {
 	unsigned int maxdata;
 };
 
-struct das6402_boardinfo das6402_boards[] = {
+static struct das6402_boardinfo das6402_boards[] = {
 	{
 		.name		= "das6402-12",
 		.maxdata	= 0x0fff,
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 160eac8083db..5cc01fe45cf2 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -811,8 +811,9 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 				devpriv->ai_dma = 0;
 				break;
 			}
-	} else
+	} else {
 		devpriv->ai_dma = 0;
+	}
 
 	devpriv->ai_act_scan = 0;
 	devpriv->ai_poll_ptr = 0;
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 95fadf343f27..6da43de51eb3 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -295,10 +295,24 @@ static void s626_debi_replace(struct comedi_device *dev, unsigned int addr,
 
 /* **************  EEPROM ACCESS FUNCTIONS  ************** */
 
-static uint32_t s626_i2c_handshake(struct comedi_device *dev, uint32_t val)
+static int s626_i2c_handshake_eoc(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned long context)
+{
+	bool status;
+
+	status = s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
+	if (status)
+		return 0;
+	return -EBUSY;
+}
+
+static int s626_i2c_handshake(struct comedi_device *dev, uint32_t val)
 {
 	struct s626_private *devpriv = dev->private;
 	unsigned int ctrl;
+	int ret;
 
 	/* Write I2C command to I2C Transfer Control shadow register */
 	writel(val, devpriv->mmio + S626_P_I2CCTRL);
@@ -308,8 +322,9 @@ static uint32_t s626_i2c_handshake(struct comedi_device *dev, uint32_t val)
 	 * wait for upload confirmation.
 	 */
 	s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
-	while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2))
-		;
+	ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
+	if (ret)
+		return ret;
 
 	/* Wait until I2C bus transfer is finished or an error occurs */
 	do {
@@ -2029,8 +2044,9 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 	/* Wait for the data to arrive in FB BUFFER 1 register. */
 
 	/* Wait for ADC done */
-	while (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_GPIO2))
-		;
+	ret = comedi_timeout(dev, s, insn, s626_ai_eoc, 0);
+	if (ret)
+		return ret;
 
 	/* Fetch ADC data from audio interface's input shift register. */
 
@@ -2681,8 +2697,9 @@ static int s626_initialize(struct comedi_device *dev)
 	writel(S626_I2C_CLKSEL | S626_I2C_ABORT,
 	       devpriv->mmio + S626_P_I2CSTAT);
 	s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
-	while (!(readl(devpriv->mmio + S626_P_MC2) & S626_MC2_UPLD_IIC))
-		;
+	ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
+	if (ret)
+		return ret;
 
 	/*
 	 * Per SAA7146 data sheet, write to STATUS
@@ -2691,8 +2708,9 @@ static int s626_initialize(struct comedi_device *dev)
 	for (i = 0; i < 2; i++) {
 		writel(S626_I2C_CLKSEL, devpriv->mmio + S626_P_I2CSTAT);
 		s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
-		while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2))
-			;
+		ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
+		if (ret)
+			return ret;
 	}
 
 	/*
diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c
index a5fc3c75ed4e..3c9278a224e2 100644
--- a/drivers/staging/dgap/dgap.c
+++ b/drivers/staging/dgap/dgap.c
@@ -12,21 +12,6 @@
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *	NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *	This is shared code between Digi's CVS archive and the
- *	Linux Kernel sources.
- *	Changing the source just for reformatting needlessly breaks
- *	our CVS diff history.
- *
- *	Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *	Thank you.
- *
  */
 
 /*
@@ -78,21 +63,11 @@
 
 #include "dgap.h"
 
-#define init_MUTEX(sem)         sema_init(sem, 1)
-#define DECLARE_MUTEX(name)     \
-	struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Digi International, http://www.digi.com");
 MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line");
 MODULE_SUPPORTED_DEVICE("dgap");
 
-/**************************************************************************
- *
- * protos for this file
- *
- */
-
 static int dgap_start(void);
 static void dgap_init_globals(void);
 static int dgap_found_board(struct pci_dev *pdev, int id);
@@ -105,7 +80,6 @@ static int dgap_probe1(struct pci_dev *pdev, int card_type);
 static int dgap_do_remap(struct board_t *brd);
 static irqreturn_t dgap_intr(int irq, void *voidbrd);
 
-/* Our function prototypes */
 static int dgap_tty_open(struct tty_struct *tty, struct file *file);
 static void dgap_tty_close(struct tty_struct *tty, struct file *file);
 static int dgap_block_til_ready(struct tty_struct *tty, struct file *file,
@@ -161,9 +135,9 @@ static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds);
 static int dgap_event(struct board_t *bd);
 
 static void dgap_poll_tasklet(unsigned long data);
-static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1,
-			uchar byte2, uint ncmds);
-static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds);
+static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1,
+			u8 byte2, uint ncmds);
+static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds);
 static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
 static int dgap_param(struct tty_struct *tty);
 static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf,
@@ -210,22 +184,21 @@ static uint dgap_config_get_useintr(struct board_t *bd);
 static uint dgap_config_get_altpin(struct board_t *bd);
 
 static int dgap_ms_sleep(ulong ms);
-static void dgap_do_bios_load(struct board_t *brd, const uchar *ubios, int len);
-static void dgap_do_fep_load(struct board_t *brd, const uchar *ufep, int len);
+static void dgap_do_bios_load(struct board_t *brd, const u8 *ubios, int len);
+static void dgap_do_fep_load(struct board_t *brd, const u8 *ufep, int len);
 #ifdef DIGI_CONCENTRATORS_SUPPORTED
-static void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len);
+static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len);
 #endif
 static int dgap_after_config_loaded(int board);
 static int dgap_finalize_board_init(struct board_t *brd);
 
 static void dgap_get_vpd(struct board_t *brd);
 static void dgap_do_reset_board(struct board_t *brd);
-static int dgap_do_wait_for_bios(struct board_t *brd);
-static int dgap_do_wait_for_fep(struct board_t *brd);
+static int dgap_test_bios(struct board_t *brd);
+static int dgap_test_fep(struct board_t *brd);
 static int dgap_tty_register_ports(struct board_t *brd);
 static int dgap_firmware_load(struct pci_dev *pdev, int card_type);
 
-/* Driver unload function */
 static void dgap_cleanup_module(void);
 
 module_exit(dgap_cleanup_module);
@@ -237,22 +210,14 @@ static const struct file_operations DgapBoardFops = {
 	.owner	= THIS_MODULE,
 };
 
-/*
- * Globals
- */
 static uint dgap_NumBoards;
 static struct board_t *dgap_Board[MAXBOARDS];
 static ulong dgap_poll_counter;
 static char *dgap_config_buf;
 static int dgap_driver_state = DRIVER_INITIALIZED;
-DEFINE_SPINLOCK(dgap_dl_lock);
 static wait_queue_head_t dgap_dl_wait;
-static int dgap_dl_action;
 static int dgap_poll_tick = 20;	/* Poll interval - 20 ms */
 
-/*
- * Static vars.
- */
 static struct class *dgap_class;
 
 static struct board_t *dgap_BoardsByMajor[256];
@@ -310,7 +275,7 @@ MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
  */
 struct board_id {
 	uint config_type;
-	uchar *name;
+	u8 *name;
 	uint maxports;
 	uint dpatype;
 };
@@ -342,10 +307,10 @@ static struct pci_driver dgap_driver = {
 };
 
 struct firmware_info {
-	uchar *conf_name;       /* dgap.conf */
-	uchar *bios_name;	/* BIOS filename */
-	uchar *fep_name;	/* FEP  filename */
-	uchar *con_name;	/* Concentrator filename  FIXME*/
+	u8 *conf_name;       /* dgap.conf */
+	u8 *bios_name;	/* BIOS filename */
+	u8 *fep_name;	/* FEP  filename */
+	u8 *con_name;	/* Concentrator filename  FIXME*/
 	int num;                /* sequence number */
 };
 
@@ -655,8 +620,6 @@ static void dgap_cleanup_module(void)
 	class_destroy(dgap_class);
 	unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
 
-	kfree(dgap_config_buf);
-
 	for (i = 0; i < dgap_NumBoards; ++i) {
 		dgap_remove_ports_sysfiles(dgap_Board[i]);
 		dgap_tty_uninit(dgap_Board[i]);
@@ -819,9 +782,8 @@ static int dgap_found_board(struct pci_dev *pdev, int id)
 	if (i)
 		brd->state = BOARD_FAILED;
 
-	pr_info("dgap: board %d: %s (rev %d), irq %ld, %s\n",
-		dgap_NumBoards, brd->name, brd->rev, brd->irq,
-		brd->state ? "NOT READY\0" : "READY\0");
+	pr_info("dgap: board %d: %s (rev %d), irq %ld\n",
+		dgap_NumBoards, brd->name, brd->rev, brd->irq);
 
 	return 0;
 }
@@ -863,7 +825,7 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
 	dgap_get_vpd(brd);
 	dgap_do_reset_board(brd);
 
-	if (fw_info[card_type].conf_name) {
+	if ((fw_info[card_type].conf_name) && !dgap_config_buf) {
 		ret = request_firmware(&fw, fw_info[card_type].conf_name,
 					 &pdev->dev);
 		if (ret) {
@@ -871,20 +833,22 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
 				fw_info[card_type].conf_name);
 			return ret;
 		}
+
+		dgap_config_buf = kmalloc(fw->size + 1, GFP_KERNEL);
 		if (!dgap_config_buf) {
-			dgap_config_buf = kmalloc(fw->size + 1, GFP_ATOMIC);
-			if (!dgap_config_buf) {
-				release_firmware(fw);
-				return -ENOMEM;
-			}
+			release_firmware(fw);
+			return -ENOMEM;
 		}
 
 		memcpy(dgap_config_buf, fw->data, fw->size);
 		release_firmware(fw);
 		dgap_config_buf[fw->size + 1] = '\0';
 
-		if (dgap_parsefile(&dgap_config_buf, TRUE) != 0)
+		if (dgap_parsefile(&dgap_config_buf, TRUE) != 0) {
+			kfree(dgap_config_buf);
 			return -EINVAL;
+		}
+		kfree(dgap_config_buf);
 	}
 
 	ret = dgap_after_config_loaded(brd->boardnum);
@@ -926,8 +890,9 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
 		release_firmware(fw);
 
 		/* Wait for BIOS to test board... */
-		if (!dgap_do_wait_for_bios(brd))
-			return -ENXIO;
+		ret = dgap_test_bios(brd);
+		if (ret)
+			return ret;
 	}
 
 	if (fw_info[card_type].fep_name) {
@@ -942,8 +907,9 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
 		release_firmware(fw);
 
 		/* Wait for FEP to load on board... */
-		if (!dgap_do_wait_for_fep(brd))
-			return -ENXIO;
+		ret = dgap_test_fep(brd);
+		if (ret)
+			return ret;
 	}
 
 #ifdef DIGI_CONCENTRATORS_SUPPORTED
@@ -1197,7 +1163,6 @@ static void dgap_init_globals(void)
 	init_timer(&dgap_poll_timer);
 
 	init_waitqueue_head(&dgap_dl_wait);
-	dgap_dl_action = 0;
 }
 
 /************************************************************************
@@ -1328,8 +1293,8 @@ static int dgap_tty_init(struct board_t *brd)
 	int i;
 	int tlw;
 	uint true_count = 0;
-	uchar *vaddr;
-	uchar modem = 0;
+	u8 *vaddr;
+	u8 modem = 0;
 	struct channel_t *ch;
 	struct bs_t *bs;
 	struct cm_t *cm;
@@ -1540,8 +1505,8 @@ static void dgap_tty_uninit(struct board_t *brd)
  * dgap_sniff - Dump data out to the "sniff" buffer if the
  * proc sniff file is opened...
  */
-static void dgap_sniff_nowait_nolock(struct channel_t *ch, uchar *text,
-				     uchar *buf, int len)
+static void dgap_sniff_nowait_nolock(struct channel_t *ch, u8 *text,
+				     u8 *buf, int len)
 {
 	struct timeval tv;
 	int n;
@@ -1675,8 +1640,8 @@ static void dgap_input(struct channel_t *ch)
 	int flip_len;
 	int len = 0;
 	int n = 0;
-	uchar *buf;
-	uchar tmpchar;
+	u8 *buf;
+	u8 tmpchar;
 	int s = 0;
 
 	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
@@ -2445,7 +2410,7 @@ static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
 	struct channel_t *ch = NULL;
 	struct un_t *un = NULL;
 	struct bs_t *bs = NULL;
-	uchar tbusy;
+	u8 tbusy;
 	uint chars = 0;
 	u16 thead, ttail, tmask, chead, ctail;
 	ulong   lock_flags = 0;
@@ -2878,8 +2843,8 @@ static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
 		n -= remain;
 		vaddr = ch->ch_taddr + head;
 
-		memcpy_toio(vaddr, (uchar *) buf, remain);
-		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *) buf,
+		memcpy_toio(vaddr, (u8 *) buf, remain);
+		dgap_sniff_nowait_nolock(ch, "USER WRITE", (u8 *) buf,
 					remain);
 
 		head = ch->ch_tstart;
@@ -2894,8 +2859,8 @@ static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
 		vaddr = ch->ch_taddr + head;
 		remain = n;
 
-		memcpy_toio(vaddr, (uchar *) buf, remain);
-		dgap_sniff_nowait_nolock(ch, "USER WRITE", (uchar *)buf,
+		memcpy_toio(vaddr, (u8 *) buf, remain);
+		dgap_sniff_nowait_nolock(ch, "USER WRITE", (u8 *)buf,
 					remain);
 
 		head += remain;
@@ -2950,7 +2915,7 @@ static int dgap_tty_tiocmget(struct tty_struct *tty)
 	struct channel_t *ch;
 	struct un_t *un;
 	int result = -EIO;
-	uchar mstat = 0;
+	u8 mstat = 0;
 	ulong lock_flags;
 
 	if (!tty || tty->magic != TTY_MAGIC)
@@ -3176,7 +3141,7 @@ static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
 static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
 {
 	int result = 0;
-	uchar mstat = 0;
+	u8 mstat = 0;
 	ulong lock_flags;
 	int rc = 0;
 
@@ -4336,9 +4301,9 @@ static int dgap_tty_register_ports(struct board_t *brd)
  * Copies the BIOS code from the user to the board,
  * and starts the BIOS running.
  */
-static void dgap_do_bios_load(struct board_t *brd, const uchar *ubios, int len)
+static void dgap_do_bios_load(struct board_t *brd, const u8 *ubios, int len)
 {
-	uchar *addr;
+	u8 *addr;
 	uint offset;
 	int i;
 
@@ -4369,16 +4334,15 @@ static void dgap_do_bios_load(struct board_t *brd, const uchar *ubios, int len)
 /*
  * Checks to see if the BIOS completed running on the card.
  */
-static int dgap_do_wait_for_bios(struct board_t *brd)
+static int dgap_test_bios(struct board_t *brd)
 {
-	uchar *addr;
+	u8 *addr;
 	u16 word;
 	u16 err1;
 	u16 err2;
-	int ret = 0;
 
 	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return ret;
+		return -EINVAL;
 
 	addr = brd->re_map_membase;
 	word = readw(addr + POSTAREA);
@@ -4392,7 +4356,7 @@ static int dgap_do_wait_for_bios(struct board_t *brd)
 	while (brd->wait_for_bios < 1000) {
 		/* Check to see if BIOS thinks board is good. (GD). */
 		if (word == *(u16 *) "GD")
-			return 1;
+			return 0;
 		msleep_interruptible(10);
 		brd->wait_for_bios++;
 		word = readw(addr + POSTAREA);
@@ -4406,16 +4370,16 @@ static int dgap_do_wait_for_bios(struct board_t *brd)
 	brd->state = BOARD_FAILED;
 	brd->dpastatus = BD_NOBIOS;
 
-	return ret;
+	return -EIO;
 }
 
 /*
  * Copies the FEP code from the user to the board,
  * and starts the FEP running.
  */
-static void dgap_do_fep_load(struct board_t *brd, const uchar *ufep, int len)
+static void dgap_do_fep_load(struct board_t *brd, const u8 *ufep, int len)
 {
-	uchar *addr;
+	u8 *addr;
 	uint offset;
 
 	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
@@ -4434,8 +4398,8 @@ static void dgap_do_fep_load(struct board_t *brd, const uchar *ufep, int len)
 	 * it its config string describing how the concentrators look.
 	 */
 	if ((brd->type == PCX) || (brd->type == PEPC)) {
-		uchar string[100];
-		uchar *config, *xconfig;
+		u8 string[100];
+		u8 *config, *xconfig;
 		int i = 0;
 
 		xconfig = dgap_create_config_string(brd, string);
@@ -4457,16 +4421,15 @@ static void dgap_do_fep_load(struct board_t *brd, const uchar *ufep, int len)
 /*
  * Waits for the FEP to report thats its ready for us to use.
  */
-static int dgap_do_wait_for_fep(struct board_t *brd)
+static int dgap_test_fep(struct board_t *brd)
 {
-	uchar *addr;
+	u8 *addr;
 	u16 word;
 	u16 err1;
 	u16 err2;
-	int ret = 0;
 
 	if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
-		return ret;
+		return -EINVAL;
 
 	addr = brd->re_map_membase;
 	word = readw(addr + FEPSTAT);
@@ -4486,7 +4449,7 @@ static int dgap_do_wait_for_fep(struct board_t *brd)
 			if (word == *(u16 *) "5A")
 				brd->bd_flags |= BD_FEP5PLUS;
 
-			return 1;
+			return 0;
 		}
 		msleep_interruptible(10);
 		brd->wait_for_fep++;
@@ -4501,7 +4464,7 @@ static int dgap_do_wait_for_fep(struct board_t *brd)
 	brd->state = BOARD_FAILED;
 	brd->dpastatus = BD_NOFEP;
 
-	return ret;
+	return -EIO;
 }
 
 /*
@@ -4509,7 +4472,7 @@ static int dgap_do_wait_for_fep(struct board_t *brd)
  */
 static void dgap_do_reset_board(struct board_t *brd)
 {
-	uchar check;
+	u8 check;
 	u32 check1;
 	u32 check2;
 	int i = 0;
@@ -4557,7 +4520,7 @@ static void dgap_do_reset_board(struct board_t *brd)
 /*
  * Sends a concentrator image into the FEP5 board.
  */
-static void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
+static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len)
 {
 	char *vaddr;
 	u16 offset = 0;
@@ -4590,8 +4553,8 @@ static void dgap_get_vpd(struct board_t *brd)
 	u16 vpd_offset;
 	u16 image_length;
 	u16 i;
-	uchar byte1;
-	uchar byte2;
+	u8 byte1;
+	u8 byte2;
 
 	/*
 	 * Poke the magic number at the PCI Rom Address location.
@@ -4770,8 +4733,8 @@ out:
  *                        in the cmd buffer before returning.
  *
  *=======================================================================*/
-static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1,
-			uchar byte2, uint ncmds)
+static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1,
+			u8 byte2, uint ncmds)
 {
 	char		*vaddr = NULL;
 	struct cm_t	*cm_addr = NULL;
@@ -4813,7 +4776,7 @@ static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1,
 	 * Put the data in the circular command buffer.
 	 */
 	writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
-	writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
+	writeb((u8) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
 	writeb(byte1, (char *) (vaddr + head + CMDSTART + 2));
 	writeb(byte2, (char *) (vaddr + head + CMDSTART + 3));
 
@@ -4856,7 +4819,7 @@ static void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1,
  *                        in the cmd buffer before returning.
  *
  *=======================================================================*/
-static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
+static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds)
 {
 	char		*vaddr = NULL;
 	struct cm_t	*cm_addr = NULL;
@@ -4897,7 +4860,7 @@ static void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds)
 	 * Put the data in the circular command buffer.
 	 */
 	writeb(cmd, (char *) (vaddr + head + CMDSTART + 0));
-	writeb((uchar) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
+	writeb((u8) ch->ch_portnum, (char *) (vaddr + head + CMDSTART + 1));
 	writew((u16) word, (char *) (vaddr + head + CMDSTART + 2));
 
 	head = (head + 4) & (CMDMAX - CMDSTART - 4);
@@ -4981,9 +4944,9 @@ static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
 	 */
 
 	/* Write an FF to tell the FEP that we want an extended command */
-	writeb((uchar) 0xff, (char *) (vaddr + head + CMDSTART + 0));
+	writeb((u8) 0xff, (char *) (vaddr + head + CMDSTART + 0));
 
-	writeb((uchar) ch->ch_portnum, (uchar *) (vaddr + head + CMDSTART + 1));
+	writeb((u8) ch->ch_portnum, (u8 *) (vaddr + head + CMDSTART + 1));
 	writew((u16) cmd, (char *) (vaddr + head + CMDSTART + 2));
 
 	/*
@@ -5088,7 +5051,7 @@ static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
  */
 static uint dgap_get_custom_baud(struct channel_t *ch)
 {
-	uchar *vaddr;
+	u8 *vaddr;
 	ulong offset = 0;
 	uint value = 0;
 
@@ -5160,8 +5123,8 @@ static int dgap_param(struct tty_struct *tty)
 	u16	head;
 	u16	cflag;
 	u16	iflag;
-	uchar	mval;
-	uchar	hflow;
+	u8	mval;
+	u8	hflow;
 
 	if (!tty || tty->magic != TTY_MAGIC)
 		return -ENXIO;
@@ -5427,7 +5390,7 @@ static int dgap_param(struct tty_struct *tty)
 		ch->ch_hflow = hflow;
 
 		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SHFLOW, (uchar) hflow, 0xff, 0);
+		dgap_cmdb(ch, SHFLOW, (u8) hflow, 0xff, 0);
 	}
 
 
@@ -5455,7 +5418,7 @@ static int dgap_param(struct tty_struct *tty)
 		ch->ch_mostat = mval;
 
 		/* Okay to have channel and board locks held calling this */
-		dgap_cmdb(ch, SMODEM, (uchar) mval, D_RTS(ch)|D_DTR(ch), 0);
+		dgap_cmdb(ch, SMODEM, (u8) mval, D_RTS(ch)|D_DTR(ch), 0);
 	}
 
 	/*
@@ -5609,8 +5572,8 @@ static int dgap_event(struct board_t *bd)
 	ulong		lock_flags;
 	ulong		lock_flags2;
 	struct bs_t	*bs;
-	uchar		*event;
-	uchar		*vaddr = NULL;
+	u8		*event;
+	u8		*vaddr = NULL;
 	struct ev_t	*eaddr = NULL;
 	uint		head;
 	uint		tail;
diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h
index 6b8f5f858327..b23570bd183d 100644
--- a/drivers/staging/dgap/dgap.h
+++ b/drivers/staging/dgap/dgap.h
@@ -39,9 +39,6 @@
 # define FALSE 0
 #endif
 
-/* Required for our shared headers! */
-typedef unsigned char		uchar;
-
 #if !defined(TTY_FLIPBUF_SIZE)
 # define TTY_FLIPBUF_SIZE 512
 #endif
@@ -61,7 +58,7 @@ typedef unsigned char		uchar;
 
 /*
  * defines from dgap_pci.h
- */ 
+ */
 #define PCIMAX 32			/* maximum number of PCI boards */
 
 #define DIGI_VID		0x114F
@@ -186,7 +183,7 @@ typedef unsigned char		uchar;
 			ECHOCTL | ECHOKE | IEXTEN)
 
 #ifndef _POSIX_VDISABLE
-#define   _POSIX_VDISABLE '\0'
+#define _POSIX_VDISABLE ('\0')
 #endif
 
 #define SNIFF_MAX	65536		/* Sniff buffer size (2^n) */
@@ -207,9 +204,11 @@ typedef unsigned char		uchar;
 #define EVSTART         0x0800L         /* Start of event buffer        */
 #define EVMAX           0x0c00L         /* End of event buffer          */
 #define FEP5_PLUS       0x0E40          /* ASCII '5' and ASCII 'A' is here  */
-#define ECS_SEG         0x0E44          /* Segment of the extended channel structure */
-#define LINE_SPEED      0x10            /* Offset into ECS_SEG for line speed   */
-                                        /* if the fep has extended capabilities */
+#define ECS_SEG         0x0E44          /* Segment of the extended      */
+					/* channel structure            */
+#define LINE_SPEED      0x10            /* Offset into ECS_SEG for line */
+					/* speed if the fep has extended */
+					/* capabilities                 */
 
 /* BIOS MAGIC SPOTS */
 #define ERROR           0x0C14L		/* BIOS error code              */
@@ -247,12 +246,12 @@ typedef unsigned char		uchar;
 
 #define FEPTIMEOUT 200000
 
-#define ENABLE_INTR		0x0e04		/* Enable interrupts flag */
-#define FEPPOLL_MIN		1		/* minimum of 1 millisecond */
-#define FEPPOLL_MAX		20		/* maximum of 20 milliseconds */
-#define FEPPOLL			0x0c26		/* Fep event poll interval */
+#define ENABLE_INTR	0x0e04		/* Enable interrupts flag */
+#define FEPPOLL_MIN	1		/* minimum of 1 millisecond */
+#define FEPPOLL_MAX	20		/* maximum of 20 milliseconds */
+#define FEPPOLL		0x0c26		/* Fep event poll interval */
 
-#define	IALTPIN			0x0080		/* Input flag to swap DSR <-> DCD */
+#define	IALTPIN		0x0080		/* Input flag to swap DSR <-> DCD */
 
 /************************************************************************
  * FEP supported functions
@@ -280,14 +279,12 @@ typedef unsigned char		uchar;
 #define SPINTFC		0xfc		/* Reserved			*/
 #define SCOMMODE	0xfd		/* Set RS232/422 mode		*/
 
-
 /************************************************************************
  *	Modes for SCOMMODE
  ************************************************************************/
 #define MODE_232	0x00
 #define MODE_422	0x01
 
-
 /************************************************************************
  *      Event flags.
  ************************************************************************/
@@ -362,13 +359,13 @@ typedef unsigned char		uchar;
 #define MC8E8K  36
 
 #define AVANFS	42	/* start of Avanstar family definitions */
-#define A8P 	42
+#define A8P	42
 #define A16P	43
 #define AVANFE	43	/* end of Avanstar family definitions */
 
-#define DA2000FS	44	/* start of AccelePort 2000 family definitions */
-#define DA22 		44 /* AccelePort 2002 */
-#define DA24 		45 /* AccelePort 2004 */
+#define DA2000FS	44 /* start of AccelePort 2000 family definitions */
+#define DA22		44 /* AccelePort 2002 */
+#define DA24		45 /* AccelePort 2004 */
 #define DA28		46 /* AccelePort 2008 */
 #define DA216		47 /* AccelePort 2016 */
 #define DAR4		48 /* AccelePort RAS 4 port */
@@ -492,8 +489,6 @@ enum {
 	REQUESTED_CONCENTRATOR
 };
 
-
-
 /*
  * Modem line constants are defined as macros because DSR and
  * DCD are swapable using the ditty altpin option.
@@ -505,14 +500,12 @@ enum {
 #define D_RI(ch)        DM_RI           /* Ring indicator       */
 #define D_DTR(ch)       DM_DTR          /* Data terminal ready  */
 
-
 /*************************************************************************
  *
  * Structures and closely related defines.
  *
  *************************************************************************/
 
-
 /*
  * A structure to hold a statistics counter.  We also
  * compute moving averages for this counter.
@@ -524,7 +517,6 @@ struct macounter {
 	ulong		ema;	/* Exponential moving average */
 };
 
-
 /************************************************************************
  * Device flag definitions for bd_flags.
  ************************************************************************/
@@ -546,11 +538,11 @@ struct board_t {
 	u16		device;		/* PCI device ID */
 	u16		subvendor;	/* PCI subsystem vendor ID */
 	u16		subdevice;	/* PCI subsystem device ID */
-	uchar		rev;		/* PCI revision ID */
+	u8		rev;		/* PCI revision ID */
 	uint		pci_bus;	/* PCI bus value */
 	uint		pci_slot;	/* PCI slot value */
 	u16		maxports;	/* MAX ports this board can handle */
-	uchar		vpd[VPDSIZE];	/* VPD of board, if found */
+	u8		vpd[VPDSIZE];	/* VPD of board, if found */
 	u32		bd_flags;	/* Board flags */
 
 	spinlock_t	bd_lock;	/* Used to protect board */
@@ -571,20 +563,22 @@ struct board_t {
 	ulong		irq;		/* Interrupt request number */
 	ulong		intr_count;	/* Count of interrupts */
 	u32		intr_used;	/* Non-zero if using interrupts */
-	u32		intr_running;	/* Non-zero if FEP knows its doing interrupts */
+	u32		intr_running;	/* Non-zero if FEP knows its doing */
+					/* interrupts */
 
 	ulong		port;		/* Start of base io port of the card */
 	ulong		port_end;	/* End of base io port of the card */
 	ulong		membase;	/* Start of base memory of the card */
 	ulong		membase_end;	/* End of base memory of the card */
 
-	uchar 		*re_map_port;	/* Remapped io port of the card */
-	uchar		*re_map_membase;/* Remapped memory of the card */
+	u8		*re_map_port;	/* Remapped io port of the card */
+	u8		*re_map_membase;/* Remapped memory of the card */
 
-	uchar		runwait;	/* # Processes waiting for FEP  */
-	uchar		inhibit_poller; /* Tells  the poller to leave us alone */
+	u8		runwait;	/* # Processes waiting for FEP  */
+	u8		inhibit_poller; /* Tells the poller to leave us alone */
 
-	struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
+	struct channel_t *channels[MAXPORTS]; /* array of pointers to our */
+					      /* channels.                */
 
 	struct tty_driver	*SerialDriver;
 	struct tty_port *SerialPorts;
@@ -599,20 +593,23 @@ struct board_t {
 	u32		dgap_Serial_Major;
 	u32		dgap_TransparentPrint_Major;
 
-	struct bs_t	*bd_bs;			/* Base structure pointer       */
+	struct bs_t	*bd_bs;		/* Base structure pointer         */
 
-	char	*flipbuf;		/* Our flip buffer, alloced if board is found */
-	char	*flipflagbuf;		/* Our flip flag buffer, alloced if board is found */
+	char	*flipbuf;		/* Our flip buffer, alloced if    */
+					/* board is found                 */
+	char	*flipflagbuf;		/* Our flip flag buffer, alloced  */
+					/* if board is found              */
 
-	u16		dpatype;	/* The board "type", as defined by DPA */
-	u16		dpastatus;	/* The board "status", as defined by DPA */
-	wait_queue_head_t kme_wait;	/* Needed for DPA support */
+	u16		dpatype;	/* The board "type", as defined   */
+					/* by DPA                         */
+	u16		dpastatus;	/* The board "status", as defined */
+					/* by DPA                         */
+	wait_queue_head_t kme_wait;	/* Needed for DPA support         */
 
-	u32		conc_dl_status;	/* Status of any pending conc download */
+	u32		conc_dl_status;	/* Status of any pending conc     */
+					/* download                       */
 };
 
-
-
 /************************************************************************
  * Unit flag definitions for un_flags.
  ************************************************************************/
@@ -650,7 +647,6 @@ struct un_t {
 	struct device *un_sysfs;
 };
 
-
 /************************************************************************
  * Device flag definitions for ch_flags.
  ************************************************************************/
@@ -677,7 +673,6 @@ struct un_t {
 #define SNIFF_WAIT_DATA	0x2
 #define SNIFF_WAIT_SPACE 0x4
 
-
 /************************************************************************
  ***	Definitions for Digi ditty(1) command.
  ************************************************************************/
@@ -689,8 +684,8 @@ struct un_t {
 
 #if !defined(TIOCMODG)
 
-#define	TIOCMODG	(('d'<<8) | 250)		/* get modem ctrl state	*/
-#define	TIOCMODS	(('d'<<8) | 251)		/* set modem ctrl state	*/
+#define	TIOCMODG	(('d'<<8) | 250)	/* get modem ctrl state	*/
+#define	TIOCMODS	(('d'<<8) | 251)	/* set modem ctrl state	*/
 
 #ifndef TIOCM_LE
 #define		TIOCM_LE	0x01		/* line enable		*/
@@ -709,16 +704,15 @@ struct un_t {
 #endif
 
 #if !defined(TIOCMSET)
-#define	TIOCMSET	(('d'<<8) | 252)		/* set modem ctrl state	*/
-#define	TIOCMGET	(('d'<<8) | 253)		/* set modem ctrl state	*/
+#define	TIOCMSET	(('d'<<8) | 252)	/* set modem ctrl state	*/
+#define	TIOCMGET	(('d'<<8) | 253)	/* set modem ctrl state	*/
 #endif
 
 #if !defined(TIOCMBIC)
-#define	TIOCMBIC	(('d'<<8) | 254)		/* set modem ctrl state */
-#define	TIOCMBIS	(('d'<<8) | 255)		/* set modem ctrl state */
+#define	TIOCMBIC	(('d'<<8) | 254)	/* set modem ctrl state */
+#define	TIOCMBIS	(('d'<<8) | 255)	/* set modem ctrl state */
 #endif
 
-
 #if !defined(TIOCSDTR)
 #define	TIOCSDTR	(('e'<<8) | 0)		/* set DTR		*/
 #define	TIOCCDTR	(('e'<<8) | 1)		/* clear DTR		*/
@@ -737,26 +731,25 @@ struct un_t {
 						/* Adapter Memory	*/
 
 #define	DIGI_GETFLOW	(('e'<<8) | 99)		/* Get startc/stopc flow */
-						/* control characters 	 */
-#define	DIGI_SETFLOW	(('e'<<8) | 100)		/* Set startc/stopc flow */
+						/* control characters    */
+#define	DIGI_SETFLOW	(('e'<<8) | 100)	/* Set startc/stopc flow */
 						/* control characters	 */
-#define	DIGI_GETAFLOW	(('e'<<8) | 101)		/* Get Aux. startc/stopc */
-						/* flow control chars 	 */
-#define	DIGI_SETAFLOW	(('e'<<8) | 102)		/* Set Aux. startc/stopc */
+#define	DIGI_GETAFLOW	(('e'<<8) | 101)	/* Get Aux. startc/stopc */
+						/* flow control chars    */
+#define	DIGI_SETAFLOW	(('e'<<8) | 102)	/* Set Aux. startc/stopc */
 						/* flow control chars	 */
 
-#define DIGI_GEDELAY	(('d'<<8) | 246)		/* Get edelay */
-#define DIGI_SEDELAY	(('d'<<8) | 247)		/* Set edelay */
+#define DIGI_GEDELAY	(('d'<<8) | 246)	/* Get edelay */
+#define DIGI_SEDELAY	(('d'<<8) | 247)	/* Set edelay */
 
 struct	digiflow_t {
-	unsigned char	startc;				/* flow cntl start char	*/
-	unsigned char	stopc;				/* flow cntl stop char	*/
+	unsigned char	startc;			/* flow cntl start char	*/
+	unsigned char	stopc;			/* flow cntl stop char	*/
 };
 
-
 #ifdef	FLOW_2200
-#define	F2200_GETA	(('e'<<8) | 104)		/* Get 2x36 flow cntl flags */
-#define	F2200_SETAW	(('e'<<8) | 105)		/* Set 2x36 flow cntl flags */
+#define	F2200_GETA	(('e'<<8) | 104)	/* Get 2x36 flow cntl flags */
+#define	F2200_SETAW	(('e'<<8) | 105)	/* Set 2x36 flow cntl flags */
 #define		F2200_MASK	0x03		/* 2200 flow cntl bit mask  */
 #define		FCNTL_2200	0x01		/* 2x36 terminal flow cntl  */
 #define		PCNTL_2200	0x02		/* 2x36 printer flow cntl   */
@@ -830,59 +823,6 @@ struct rw_t {
 	unsigned char	rw_data[128];	/* Data to read/write		*/
 };
 
-/***********************************************************************
- * Shrink Buffer and Board Information definitions and structures.
-
- ************************************************************************/
-			/* Board type return codes */
-#define	PCXI_TYPE 1     /* Board type at the designated port is a PC/Xi */
-#define PCXM_TYPE 2     /* Board type at the designated port is a PC/Xm */
-#define	PCXE_TYPE 3     /* Board type at the designated port is a PC/Xe */
-#define	MCXI_TYPE 4     /* Board type at the designated port is a MC/Xi */
-#define COMXI_TYPE 5     /* Board type at the designated port is a COM/Xi */
-
-			 /* Non-Zero Result codes. */
-#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
-#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
-#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
-#define RESULT_TOOSML  4 /* Too small an area to shrink.  */
-#define RESULT_NOCHAN  5 /* Channel structure for the board was not found */
-
-struct shrink_buf_struct {
-	unsigned long	shrink_buf_vaddr;	/* Virtual address of board */
-	unsigned long	shrink_buf_phys;	/* Physical address of board */
-	unsigned long	shrink_buf_bseg;	/* Amount of board memory */
-	unsigned long	shrink_buf_hseg;	/* '186 Beginning of Dual-Port */
-
-	unsigned long	shrink_buf_lseg;	/* '186 Beginning of freed memory						*/
-	unsigned long	shrink_buf_mseg;	/* Linear address from start of
-						   dual-port were freed memory
-						   begins, host viewpoint. */
-
-	unsigned long	shrink_buf_bdparam;	/* Parameter for xxmemon and
-						   xxmemoff */
-
-	unsigned long	shrink_buf_reserva;	/* Reserved */
-	unsigned long	shrink_buf_reservb;	/* Reserved */
-	unsigned long	shrink_buf_reservc;	/* Reserved */
-	unsigned long	shrink_buf_reservd;	/* Reserved */
-
-	unsigned char	shrink_buf_result;	/* Reason for call failing
-						   Zero is Good return */
-	unsigned char	shrink_buf_init;	/* Non-Zero if it caused an
-						   xxinit call. */
-
-	unsigned char	shrink_buf_anports;	/* Number of async ports  */
-	unsigned char	shrink_buf_snports; 	/* Number of sync  ports */
-	unsigned char	shrink_buf_type;	/* Board type 1 = PC/Xi,
-							      2 = PC/Xm,
-							      3 = PC/Xe
-							      4 = MC/Xi
-							      5 = COMX/i */
-	unsigned char	shrink_buf_card;	/* Card number */
-
-};
-
 /************************************************************************
  * Structure to get driver status information
  ************************************************************************/
@@ -892,7 +832,7 @@ struct digi_dinfo {
 	char		dinfo_version[16];	/* driver version       */
 };
 
-#define	DIGI_GETDD	(('d'<<8) | 248)		/* get driver info      */
+#define	DIGI_GETDD	(('d'<<8) | 248)	/* get driver info      */
 
 /************************************************************************
  * Structure used with ioctl commands for per-board information
@@ -912,7 +852,7 @@ struct digi_info {
 	char		info_reserved[7];	/* for future expansion    */
 };
 
-#define	DIGI_GETBD	(('d'<<8) | 249)		/* get board info          */
+#define	DIGI_GETBD	(('d'<<8) | 249)	/* get board info          */
 
 struct digi_stat {
 	unsigned int	info_chan;		/* Channel number (0 based)  */
@@ -927,7 +867,7 @@ struct digi_stat {
 	unsigned long	info_reserved[8];	/* for future expansion    */
 };
 
-#define	DIGI_GETSTAT	(('d'<<8) | 244)		/* get board info          */
+#define	DIGI_GETSTAT	(('d'<<8) | 244)	/* get board info          */
 /************************************************************************
  *
  * Structure used with ioctl commands for per-channel information
@@ -936,9 +876,9 @@ struct digi_stat {
 struct digi_ch {
 	unsigned long	info_bdnum;		/* Board number (0 based)  */
 	unsigned long	info_channel;		/* Channel index number    */
-	unsigned long	info_ch_cflag;		/* Channel cflag   	   */
-	unsigned long	info_ch_iflag;		/* Channel iflag   	   */
-	unsigned long	info_ch_oflag;		/* Channel oflag   	   */
+	unsigned long	info_ch_cflag;		/* Channel cflag           */
+	unsigned long	info_ch_iflag;		/* Channel iflag           */
+	unsigned long	info_ch_oflag;		/* Channel oflag           */
 	unsigned long	info_chsize;		/* Channel structure size  */
 	unsigned long	info_sleep_stat;	/* sleep status		   */
 	dev_t		info_dev;		/* device number	   */
@@ -970,7 +910,7 @@ struct digi_cmd {
 #define INFO_CH_WLOW	0x0020
 #define INFO_XXBUF_BUSY 0x0040
 
-#define	DIGI_GETCH	(('d'<<8) | 245)		/* get board info          */
+#define	DIGI_GETCH	(('d'<<8) | 245)	/* get board info          */
 
 /* Board type definitions */
 
@@ -1015,12 +955,13 @@ struct digi_cmd {
 #define BD_TRIBOOT	0x8
 #define	BD_BADKME	0x80
 
-#define DIGI_LOOPBACK	      (('d'<<8) | 252)		/* Enable/disable UART internal loopback */
-#define DIGI_SPOLL            (('d'<<8) | 254)		/* change poller rate   */
+#define DIGI_LOOPBACK	(('d'<<8) | 252)	/* Enable/disable UART  */
+						/* internal loopback    */
+#define DIGI_SPOLL	(('d'<<8) | 254)	/* change poller rate   */
 
-#define DIGI_SETCUSTOMBAUD	_IOW('e', 106, int)	/* Set integer baud rate */
-#define DIGI_GETCUSTOMBAUD	_IOR('e', 107, int)	/* Get integer baud rate */
-#define DIGI_RESET_PORT		(('e'<<8) | 93)		/* Reset port		*/
+#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int)	/* Set integer baud rate */
+#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int)	/* Get integer baud rate */
+#define DIGI_RESET_PORT	   (('e'<<8) | 93)	/* Reset port		 */
 
 /************************************************************************
  * Channel information structure.
@@ -1041,14 +982,14 @@ struct channel_t {
 	wait_queue_head_t ch_flags_wait;
 
 	u32	pscan_state;
-	uchar	pscan_savechar;
+	u8	pscan_savechar;
 
 	u32 ch_portnum;			/* Port number, 0 offset.	*/
 	u32 ch_open_count;		/* open count			*/
 	u32	ch_flags;		/* Channel flags                */
 
-
-	u32	ch_close_delay;		/* How long we should drop RTS/DTR for */
+	u32	ch_close_delay;		/* How long we should drop      */
+					/* RTS/DTR for                  */
 
 	u32	ch_cpstime;		/* Time for CPS calculations    */
 
@@ -1057,7 +998,7 @@ struct channel_t {
 	tcflag_t ch_c_oflag;		/* channel oflags               */
 	tcflag_t ch_c_lflag;		/* channel lflags               */
 
-	u16  ch_fepiflag;            /* FEP tty iflags               */
+	u16  ch_fepiflag;		/* FEP tty iflags               */
 	u16  ch_fepcflag;		/* FEP tty cflags               */
 	u16  ch_fepoflag;		/* FEP tty oflags               */
 	u16  ch_wopen;			/* Waiting for open process cnt */
@@ -1071,33 +1012,33 @@ struct channel_t {
 
 	u16  ch_cook;			/* Output character mask        */
 
-	uchar   ch_card;		/* Card channel is on           */
-	uchar   ch_stopc;		/* Stop character               */
-	uchar   ch_startc;		/* Start character              */
-
-	uchar   ch_mostat;		/* FEP output modem status      */
-	uchar   ch_mistat;		/* FEP input modem status       */
-	uchar   ch_mforce;		/* Modem values to be forced    */
-	uchar   ch_mval;		/* Force values                 */
-	uchar   ch_fepstopc;		/* FEP stop character           */
-	uchar   ch_fepstartc;		/* FEP start character          */
-
-	uchar   ch_astopc;		/* Auxiliary Stop character     */
-	uchar   ch_astartc;		/* Auxiliary Start character    */
-	uchar   ch_fepastopc;		/* Auxiliary FEP stop char      */
-	uchar   ch_fepastartc;		/* Auxiliary FEP start char     */
-
-	uchar   ch_hflow;		/* FEP hardware handshake       */
-	uchar   ch_dsr;			/* stores real dsr value        */
-	uchar   ch_cd;			/* stores real cd value         */
-	uchar   ch_tx_win;		/* channel tx buffer window     */
-	uchar   ch_rx_win;		/* channel rx buffer window     */
+	u8   ch_card;			/* Card channel is on           */
+	u8   ch_stopc;			/* Stop character               */
+	u8   ch_startc;			/* Start character              */
+
+	u8   ch_mostat;			/* FEP output modem status      */
+	u8   ch_mistat;			/* FEP input modem status       */
+	u8   ch_mforce;			/* Modem values to be forced    */
+	u8   ch_mval;			/* Force values                 */
+	u8   ch_fepstopc;		/* FEP stop character           */
+	u8   ch_fepstartc;		/* FEP start character          */
+
+	u8   ch_astopc;			/* Auxiliary Stop character     */
+	u8   ch_astartc;		/* Auxiliary Start character    */
+	u8   ch_fepastopc;		/* Auxiliary FEP stop char      */
+	u8   ch_fepastartc;		/* Auxiliary FEP start char     */
+
+	u8   ch_hflow;			/* FEP hardware handshake       */
+	u8   ch_dsr;			/* stores real dsr value        */
+	u8   ch_cd;			/* stores real cd value         */
+	u8   ch_tx_win;			/* channel tx buffer window     */
+	u8   ch_rx_win;			/* channel rx buffer window     */
 	uint	ch_custom_speed;	/* Custom baud, if set		*/
-	uint	ch_baud_info;		/* Current baud info for /proc output	*/
-	ulong	ch_rxcount;		/* total of data received so far	*/
-	ulong	ch_txcount;		/* total of data transmitted so far	*/
-	ulong	ch_err_parity;		/* Count of parity errors on channel	*/
-	ulong	ch_err_frame;		/* Count of framing errors on channel	*/
+	uint	ch_baud_info;		/* Current baud info for /proc output */
+	ulong	ch_rxcount;		/* total of data received so far      */
+	ulong	ch_txcount;		/* total of data transmitted so far   */
+	ulong	ch_err_parity;		/* Count of parity errors on channel  */
+	ulong	ch_err_frame;		/* Count of framing errors on channel */
 	ulong	ch_err_break;		/* Count of breaks on channel	*/
 	ulong	ch_err_overrun;		/* Count of overruns on channel	*/
 
@@ -1112,34 +1053,34 @@ struct channel_t {
  * Command structure definition.
  ************************************************************************/
 struct cm_t {
-	volatile unsigned short cm_head;	/* Command buffer head offset	*/
-	volatile unsigned short cm_tail;	/* Command buffer tail offset	*/
-	volatile unsigned short cm_start;	/* start offset of buffer	*/
-	volatile unsigned short cm_max;		/* last offset of buffer	*/
+	unsigned short cm_head;		/* Command buffer head offset */
+	unsigned short cm_tail;		/* Command buffer tail offset */
+	unsigned short cm_start;	/* start offset of buffer     */
+	unsigned short cm_max;		/* last offset of buffer      */
 };
 
 /************************************************************************
  * Event structure definition.
  ************************************************************************/
 struct ev_t {
-	volatile unsigned short ev_head;	/* Command buffer head offset	*/
-	volatile unsigned short ev_tail;	/* Command buffer tail offset	*/
-	volatile unsigned short ev_start;	/* start offset of buffer	*/
-	volatile unsigned short ev_max;		/* last offset of buffer	*/
+	unsigned short ev_head;		/* Command buffer head offset */
+	unsigned short ev_tail;		/* Command buffer tail offset */
+	unsigned short ev_start;	/* start offset of buffer     */
+	unsigned short ev_max;		/* last offset of buffer      */
 };
 
 /************************************************************************
  * Download buffer structure.
  ************************************************************************/
 struct downld_t {
-	uchar	dl_type;		/* Header                       */
-	uchar	dl_seq;			/* Download sequence            */
+	u8	dl_type;		/* Header                       */
+	u8	dl_seq;			/* Download sequence            */
 	ushort	dl_srev;		/* Software revision number     */
 	ushort	dl_lrev;		/* Low revision number          */
 	ushort	dl_hrev;		/* High revision number         */
 	ushort	dl_seg;			/* Start segment address        */
 	ushort	dl_size;		/* Number of bytes to download  */
-	uchar	dl_data[1024];		/* Download data                */
+	u8	dl_data[1024];		/* Download data                */
 };
 
 /************************************************************************
@@ -1152,70 +1093,74 @@ struct downld_t {
  *        U = unknown (may be changed w/o notice)                       *
  ************************************************************************/
 struct bs_t {
-	volatile unsigned short  tp_jmp;	/* Transmit poll jump		 */
-	volatile unsigned short  tc_jmp;	/* Cooked procedure jump	 */
-	volatile unsigned short  ri_jmp;	/* Not currently used		 */
-	volatile unsigned short  rp_jmp;	/* Receive poll jump		 */
-
-	volatile unsigned short  tx_seg;	/* W  Tx segment	 */
-	volatile unsigned short  tx_head;	/* W  Tx buffer head offset	*/
-	volatile unsigned short  tx_tail;	/* R  Tx buffer tail offset	*/
-	volatile unsigned short  tx_max;	/* W  Tx buffer size - 1	 */
-
-	volatile unsigned short  rx_seg;	/* W  Rx segment		*/
-	volatile unsigned short  rx_head;	/* W  Rx buffer head offset	*/
-	volatile unsigned short  rx_tail;	/* R  Rx buffer tail offset	*/
-	volatile unsigned short  rx_max;	/* W  Rx buffer size - 1	 */
-
-	volatile unsigned short  tx_lw;		/* W  Tx buffer low water mark  */
-	volatile unsigned short  rx_lw;		/* W  Rx buffer low water mark  */
-	volatile unsigned short  rx_hw;		/* W  Rx buffer high water mark */
-	volatile unsigned short  incr;		/* W  Increment to next channel */
-
-	volatile unsigned short  fepdev;	/* U  SCC device base address    */
-	volatile unsigned short  edelay;	/* W  Exception delay            */
-	volatile unsigned short  blen;		/* W  Break length              */
-	volatile unsigned short  btime;		/* U  Break complete time       */
-
-	volatile unsigned short  iflag;		/* C  UNIX input flags          */
-	volatile unsigned short  oflag;		/* C  UNIX output flags         */
-	volatile unsigned short  cflag;		/* C  UNIX control flags        */
-	volatile unsigned short  wfill[13];	/* U  Reserved for expansion    */
-
-	volatile unsigned char   num;		/* U  Channel number            */
-	volatile unsigned char   ract;		/* U  Receiver active counter   */
-	volatile unsigned char   bstat;		/* U  Break status bits         */
-	volatile unsigned char   tbusy;		/* W  Transmit busy             */
-	volatile unsigned char   iempty;	/* W  Transmit empty event enable */
-	volatile unsigned char   ilow;		/* W  Transmit low-water event enable */
-	volatile unsigned char   idata;		/* W  Receive data interrupt enable */
-	volatile unsigned char   eflag;		/* U  Host event flags          */
-
-	volatile unsigned char   tflag;		/* U  Transmit flags            */
-	volatile unsigned char   rflag;		/* U  Receive flags             */
-	volatile unsigned char   xmask;		/* U  Transmit ready flags      */
-	volatile unsigned char   xval;		/* U  Transmit ready value      */
-	volatile unsigned char   m_stat;	/* RC Modem status bits          */
-	volatile unsigned char   m_change;	/* U  Modem bits which changed  */
-	volatile unsigned char   m_int;		/* W  Modem interrupt enable bits */
-	volatile unsigned char   m_last;	/* U  Last modem status         */
-
-	volatile unsigned char   mtran;		/* C   Unreported modem trans   */
-	volatile unsigned char   orun;		/* C   Buffer overrun occurred  */
-	volatile unsigned char   astartc;	/* W   Auxiliary Xon char       */
-	volatile unsigned char   astopc;	/* W   Auxiliary Xoff char      */
-	volatile unsigned char   startc;	/* W   Xon character             */
-	volatile unsigned char   stopc;		/* W   Xoff character           */
-	volatile unsigned char   vnextc;	/* W   Vnext character           */
-	volatile unsigned char   hflow;		/* C   Software flow control    */
-	
-	volatile unsigned char   fillc;		/* U   Delay Fill character     */
-	volatile unsigned char   ochar;		/* U   Saved output character   */
-	volatile unsigned char   omask;		/* U   Output character mask    */
-
-	volatile unsigned char   bfill[13];	/* U   Reserved for expansion   */
-
-	volatile unsigned char   scc[16];	/* U   SCC registers            */
+	unsigned short  tp_jmp;		/* Transmit poll jump	 */
+	unsigned short  tc_jmp;		/* Cooked procedure jump */
+	unsigned short  ri_jmp;		/* Not currently used	 */
+	unsigned short  rp_jmp;		/* Receive poll jump	 */
+
+	unsigned short  tx_seg;		/* W Tx segment	 */
+	unsigned short  tx_head;	/* W Tx buffer head offset */
+	unsigned short  tx_tail;	/* R Tx buffer tail offset */
+	unsigned short  tx_max;		/* W Tx buffer size - 1    */
+
+	unsigned short  rx_seg;		/* W Rx segment	    */
+	unsigned short  rx_head;	/* W Rx buffer head offset */
+	unsigned short  rx_tail;	/* R Rx buffer tail offset */
+	unsigned short  rx_max;		/* W Rx buffer size - 1    */
+
+	unsigned short  tx_lw;		/* W Tx buffer low water mark */
+	unsigned short  rx_lw;		/* W Rx buffer low water mark */
+	unsigned short  rx_hw;		/* W Rx buffer high water mark*/
+	unsigned short  incr;		/* W Increment to next channel*/
+
+	unsigned short  fepdev;		/* U SCC device base address  */
+	unsigned short  edelay;		/* W Exception delay          */
+	unsigned short  blen;		/* W Break length             */
+	unsigned short  btime;		/* U Break complete time      */
+
+	unsigned short  iflag;		/* C UNIX input flags         */
+	unsigned short  oflag;		/* C UNIX output flags        */
+	unsigned short  cflag;		/* C UNIX control flags       */
+	unsigned short  wfill[13];	/* U Reserved for expansion   */
+
+	unsigned char   num;		/* U Channel number           */
+	unsigned char   ract;		/* U Receiver active counter  */
+	unsigned char   bstat;		/* U Break status bits        */
+	unsigned char   tbusy;		/* W Transmit busy            */
+	unsigned char   iempty;		/* W Transmit empty event     */
+					/* enable                     */
+	unsigned char   ilow;		/* W Transmit low-water event */
+					/* enable                     */
+	unsigned char   idata;		/* W Receive data interrupt   */
+					/* enable                     */
+	unsigned char   eflag;		/* U Host event flags         */
+
+	unsigned char   tflag;		/* U Transmit flags           */
+	unsigned char   rflag;		/* U Receive flags            */
+	unsigned char   xmask;		/* U Transmit ready flags     */
+	unsigned char   xval;		/* U Transmit ready value     */
+	unsigned char   m_stat;		/* RC Modem status bits       */
+	unsigned char   m_change;	/* U Modem bits which changed */
+	unsigned char   m_int;		/* W Modem interrupt enable   */
+					/* bits                       */
+	unsigned char   m_last;		/* U Last modem status        */
+
+	unsigned char   mtran;		/* C Unreported modem trans   */
+	unsigned char   orun;		/* C Buffer overrun occurred  */
+	unsigned char   astartc;	/* W Auxiliary Xon char       */
+	unsigned char   astopc;		/* W Auxiliary Xoff char      */
+	unsigned char   startc;		/* W Xon character            */
+	unsigned char   stopc;		/* W Xoff character           */
+	unsigned char   vnextc;		/* W Vnext character          */
+	unsigned char   hflow;		/* C Software flow control    */
+
+	unsigned char   fillc;		/* U Delay Fill character     */
+	unsigned char   ochar;		/* U Saved output character   */
+	unsigned char   omask;		/* U Output character mask    */
+
+	unsigned char   bfill[13];	/* U Reserved for expansion   */
+
+	unsigned char   scc[16];	/* U SCC registers            */
 };
 
 struct cnode {
@@ -1225,7 +1170,7 @@ struct cnode {
 
 	union {
 		struct {
-			char  type;	/* Board Type 		*/
+			char  type;	/* Board Type           */
 			long  port;	/* I/O Address		*/
 			char  *portstr; /* I/O Address in string */
 			long  addr;	/* Memory Address	*/
@@ -1294,29 +1239,17 @@ struct cnode {
 		} module;
 
 		char *ttyname;
-
 		char *cuname;
-
 		char *printname;
-
 		long majornumber;
-
 		long altpin;
-
 		long ttysize;
-
 		long chsize;
-
 		long bssize;
-
 		long unsize;
-
 		long f2size;
-
 		long vpixsize;
-
 		long useintr;
 	} u;
 };
-
 #endif
diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c
index f96dcec740ae..7ac2602242f1 100644
--- a/drivers/staging/goldfish/goldfish_audio.c
+++ b/drivers/staging/goldfish/goldfish_audio.c
@@ -334,6 +334,7 @@ static int goldfish_audio_probe(struct platform_device *pdev)
 	return 0;
 
 err_misc_register_failed:
+	free_irq(data->irq, data);
 err_request_irq_failed:
 	dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE,
 					data->buffer_virt, data->buffer_phys);
diff --git a/drivers/staging/gs_fpgaboot/Makefile b/drivers/staging/gs_fpgaboot/Makefile
index 34cb606e0e3d..d2f0211ba540 100644
--- a/drivers/staging/gs_fpgaboot/Makefile
+++ b/drivers/staging/gs_fpgaboot/Makefile
@@ -1,4 +1,2 @@
 gs_fpga-y	+= gs_fpgaboot.o io.o
 obj-$(CONFIG_GS_FPGABOOT)	+= gs_fpga.o
-
-ccflags-$(CONFIG_GS_FPGA_DEBUG)	:= -DDEBUG
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
index 89bc84d833e6..7506900c9b8d 100644
--- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
+++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
@@ -373,7 +373,6 @@ static int __init gs_fpgaboot_init(void)
 	r = -1;
 
 	pr_info("FPGA DOWNLOAD --->\n");
-	pr_info("built at %s UTC\n", __TIMESTAMP__);
 
 	pr_info("FPGA image file name: %s\n", file);
 
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index 0a60def92735..fa9649879662 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -165,8 +165,9 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len)
 		/* select register to write */
 		ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | reg));
 		if (ret < 0) {
-			dev_err(&client->dev, "taos_i2c_read failed to write"
-				" register %x\n", reg);
+			dev_err(&client->dev,
+				"taos_i2c_read failed to write register %x\n",
+				reg);
 			return ret;
 		}
 		/* read the data */
@@ -211,7 +212,7 @@ static int taos_get_lux(struct iio_dev *indio_dev)
 	if (chip->taos_chip_status != TSL258X_CHIP_WORKING) {
 		/* device is not enabled */
 		dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n");
-		ret = -EBUSY ;
+		ret = -EBUSY;
 		goto out_unlock;
 	}
 
@@ -231,8 +232,9 @@ static int taos_get_lux(struct iio_dev *indio_dev)
 		int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i);
 		ret = taos_i2c_read(chip->client, reg, &buf[i], 1);
 		if (ret < 0) {
-			dev_err(&chip->client->dev, "taos_get_lux failed to read"
-				" register %x\n", reg);
+			dev_err(&chip->client->dev,
+				"taos_get_lux failed to read register %x\n",
+				reg);
 			goto out_unlock;
 		}
 	}
@@ -449,7 +451,7 @@ static int taos_chip_on(struct iio_dev *indio_dev)
 		}
 	}
 
-	msleep(3);
+	usleep_range(3000, 3500);
 	/* NOW enable the ADC
 	 * initialize the desired mode of operation */
 	utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL;
@@ -809,9 +811,7 @@ static int taos_probe(struct i2c_client *clientp,
 
 	if (!i2c_check_functionality(clientp->adapter,
 		I2C_FUNC_SMBUS_BYTE_DATA)) {
-		dev_err(&clientp->dev,
-			"taos_probe() - i2c smbus byte data "
-			"functions unsupported\n");
+		dev_err(&clientp->dev, "taos_probe() - i2c smbus byte data func unsupported\n");
 		return -EOPNOTSUPP;
 	}
 
@@ -830,30 +830,32 @@ static int taos_probe(struct i2c_client *clientp,
 		ret = i2c_smbus_write_byte(clientp,
 				(TSL258X_CMD_REG | (TSL258X_CNTRL + i)));
 		if (ret < 0) {
-			dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd "
-				"reg failed in taos_probe(), err = %d\n", ret);
+			dev_err(&clientp->dev,
+				"i2c_smbus_write_byte to cmd reg failed in taos_probe(), err = %d\n",
+				ret);
 			return ret;
 		}
 		ret = i2c_smbus_read_byte(clientp);
 		if (ret < 0) {
-			dev_err(&clientp->dev, "i2c_smbus_read_byte from "
-				"reg failed in taos_probe(), err = %d\n", ret);
-
+			dev_err(&clientp->dev,
+				"i2c_smbus_read_byte from reg failed in taos_probe(), err = %d\n",
+				ret);
 			return ret;
 		}
 		buf[i] = ret;
 	}
 
 	if (!taos_tsl258x_device(buf)) {
-		dev_info(&clientp->dev, "i2c device found but does not match "
-			"expected id in taos_probe()\n");
+		dev_info(&clientp->dev,
+			"i2c device found but does not match expected id in taos_probe()\n");
 		return -EINVAL;
 	}
 
 	ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL));
 	if (ret < 0) {
-		dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg "
-			"failed in taos_probe(), err = %d\n", ret);
+		dev_err(&clientp->dev,
+			"i2c_smbus_write_byte() to cmd reg failed in taos_probe(), err = %d\n",
+			ret);
 		return ret;
 	}
 
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 48a6afa84088..38ecb4bb6e4c 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -33,7 +33,8 @@ static int iio_trig_periodic_rtc_set_state(struct iio_trigger *trig, bool state)
 	struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
 	if (trig_info->frequency == 0)
 		return -EINVAL;
-	printk(KERN_INFO "trigger frequency is %d\n", trig_info->frequency);
+	dev_info(&trig_info->rtc->dev, "trigger frequency is %d\n",
+			trig_info->frequency);
 	return rtc_irq_set_state(trig_info->rtc, &trig_info->task, state);
 }
 
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 8c101cbbee97..acc8184c46cd 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -1247,9 +1247,18 @@ static int vpfe_stop_streaming(struct vb2_queue *vq)
 	struct vpfe_fh *fh = vb2_get_drv_priv(vq);
 	struct vpfe_video_device *video = fh->video;
 
-	if (!vb2_is_streaming(vq))
-		return 0;
 	/* release all active buffers */
+	if (video->cur_frm == video->next_frm) {
+		vb2_buffer_done(&video->cur_frm->vb, VB2_BUF_STATE_ERROR);
+	} else {
+		if (video->cur_frm != NULL)
+			vb2_buffer_done(&video->cur_frm->vb,
+					VB2_BUF_STATE_ERROR);
+		if (video->next_frm != NULL)
+			vb2_buffer_done(&video->next_frm->vb,
+					VB2_BUF_STATE_ERROR);
+	}
+
 	while (!list_empty(&video->dma_queue)) {
 		video->next_frm = list_entry(video->dma_queue.next,
 						struct vpfe_cap_buffer, list);
diff --git a/drivers/staging/media/sn9c102/sn9c102_devtable.h b/drivers/staging/media/sn9c102/sn9c102_devtable.h
index b3d2cc729657..4ba569258498 100644
--- a/drivers/staging/media/sn9c102/sn9c102_devtable.h
+++ b/drivers/staging/media/sn9c102/sn9c102_devtable.h
@@ -48,10 +48,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
 	{ SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
 /*	{ SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
-#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig
deleted file mode 100644
index ff8d41ebca36..000000000000
--- a/drivers/staging/rtl8187se/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config R8187SE
-	tristate "RealTek RTL8187SE Wireless LAN NIC driver"
-	depends on PCI && WLAN
-	depends on m
-	select WIRELESS_EXT
-	select WEXT_PRIV
-	select EEPROM_93CX6
-	select CRYPTO
-	---help---
-	  If built as a module, it will be called r8187se.ko.
diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile
deleted file mode 100644
index 91d1aa2830c9..000000000000
--- a/drivers/staging/rtl8187se/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-
-#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y
-#ccflags-y += -std=gnu89
-#ccflags-y += -O2
-#CC            = gcc
-
-ccflags-y := -DSW_ANTE
-ccflags-y += -DTX_TRACK
-ccflags-y += -DHIGH_POWER
-ccflags-y += -DSW_DIG
-ccflags-y += -DRATE_ADAPT
-
-#enable it for legacy power save, disable it for leisure power save
-ccflags-y += -DENABLE_LPS
-
-
-#ccflags-y := -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
-
-r8187se-y :=			\
-		r8180_core.o		\
-		r8180_wx.o		\
-		r8180_rtl8225z2.o	\
-		r8185b_init.o		\
-		r8180_dm.o		\
-		ieee80211/dot11d.o			\
-		ieee80211/ieee80211_softmac.o		\
-		ieee80211/ieee80211_rx.o		\
-		ieee80211/ieee80211_tx.o		\
-		ieee80211/ieee80211_wx.o		\
-		ieee80211/ieee80211_module.o		\
-		ieee80211/ieee80211_softmac_wx.o	\
-		ieee80211/ieee80211_crypt.o		\
-		ieee80211/ieee80211_crypt_tkip.o	\
-		ieee80211/ieee80211_crypt_ccmp.o	\
-		ieee80211/ieee80211_crypt_wep.o
-
-obj-$(CONFIG_R8187SE)	+= r8187se.o
-
diff --git a/drivers/staging/rtl8187se/Module.symvers b/drivers/staging/rtl8187se/Module.symvers
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/drivers/staging/rtl8187se/TODO b/drivers/staging/rtl8187se/TODO
deleted file mode 100644
index 704949a9da0d..000000000000
--- a/drivers/staging/rtl8187se/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-TODO:
-- prepare private ieee80211 stack for merge with rtl8192su's version:
-  - add hwsec_active flag to struct ieee80211_device
-  - add bHwSec flag to cb_desc structure
-- switch to use shared "librtl" instead of private ieee80211 stack
-- switch to use LIB80211
-- switch to use MAC80211
-- use kernel coding style
-- checkpatch.pl fixes
-- sparse fixes
-- integrate with drivers/net/wireless/rtl818x
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com>.
diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c
deleted file mode 100644
index 4483c2c0307c..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/dot11d.c
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "dot11d.h"
-
-void Dot11d_Init(struct ieee80211_device *ieee)
-{
-	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
-
-	pDot11dInfo->bEnabled = 0;
-
-	pDot11dInfo->State = DOT11D_STATE_NONE;
-	pDot11dInfo->CountryIeLen = 0;
-	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
-	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
-	RESET_CIE_WATCHDOG(ieee);
-
-	netdev_info(ieee->dev, "Dot11d_Init()\n");
-}
-
-/* Reset to the state as we are just entering a regulatory domain. */
-void Dot11d_Reset(struct ieee80211_device *ieee)
-{
-	u32 i;
-	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
-
-	/* Clear old channel map */
-	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
-	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
-	/* Set new channel map */
-	for (i = 1; i <= 11; i++)
-		(pDot11dInfo->channel_map)[i] = 1;
-
-	for (i = 12; i <= 14; i++)
-		(pDot11dInfo->channel_map)[i] = 2;
-
-	pDot11dInfo->State = DOT11D_STATE_NONE;
-	pDot11dInfo->CountryIeLen = 0;
-	RESET_CIE_WATCHDOG(ieee);
-}
-
-/*
- * Description:
- *	Update country IE from Beacon or Probe Response and configure PHY for
- *	operation in the regulatory domain.
- *
- * TODO:
- *	Configure Tx power.
- *
- * Assumption:
- *	1. IS_DOT11D_ENABLE() is TRUE.
- *	2. Input IE is an valid one.
- */
-void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
-			    u16 CoutryIeLen, u8 *pCoutryIe)
-{
-	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
-	u8 i, j, NumTriples, MaxChnlNum;
-	u8 index, MaxTxPowerInDbm;
-	PCHNL_TXPOWER_TRIPLE pTriple;
-
-	if ((CoutryIeLen - 3)%3 != 0) {
-		netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
-		Dot11d_Reset(dev);
-		return;
-	}
-
-	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
-	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
-	MaxChnlNum = 0;
-	NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */
-	pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
-	for (i = 0; i < NumTriples; i++) {
-		if (MaxChnlNum >= pTriple->FirstChnl) {
-			/*
-			 * It is not in a monotonically increasing order,
-			 * so stop processing.
-			 */
-			netdev_info(dev->dev,
-				    "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
-			Dot11d_Reset(dev);
-			return;
-		}
-		if (MAX_CHANNEL_NUMBER <
-		    (pTriple->FirstChnl + pTriple->NumChnls)) {
-			/*
-			 * It is not a valid set of channel id,
-			 * so stop processing
-			 */
-			netdev_info(dev->dev,
-				    "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
-			Dot11d_Reset(dev);
-			return;
-		}
-
-		for (j = 0; j < pTriple->NumChnls; j++) {
-			index = pTriple->FirstChnl + j;
-			pDot11dInfo->channel_map[index] = 1;
-			MaxTxPowerInDbm = pTriple->MaxTxPowerInDbm;
-			pDot11dInfo->MaxTxPwrDbmList[index] = MaxTxPowerInDbm;
-			MaxChnlNum = pTriple->FirstChnl + j;
-		}
-
-		pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3);
-	}
-#if 1
-	netdev_info(dev->dev, "Channel List:");
-	for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
-		if (pDot11dInfo->channel_map[i] > 0)
-			netdev_info(dev->dev, " %d", i);
-	netdev_info(dev->dev, "\n");
-#endif
-
-	UPDATE_CIE_SRC(dev, pTaddr);
-
-	pDot11dInfo->CountryIeLen = CoutryIeLen;
-	memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
-	pDot11dInfo->State = DOT11D_STATE_LEARNED;
-}
-
-u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel)
-{
-	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
-	u8 MaxTxPwrInDbm = 255;
-
-	if (MAX_CHANNEL_NUMBER < Channel) {
-		netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
-		return MaxTxPwrInDbm;
-	}
-	if (pDot11dInfo->channel_map[Channel])
-		MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
-
-	return MaxTxPwrInDbm;
-}
-
-
-void DOT11D_ScanComplete(struct ieee80211_device *dev)
-{
-	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
-
-	switch (pDot11dInfo->State) {
-	case DOT11D_STATE_LEARNED:
-		pDot11dInfo->State = DOT11D_STATE_DONE;
-		break;
-
-	case DOT11D_STATE_DONE:
-		if (GET_CIE_WATCHDOG(dev) == 0) {
-			/* Reset country IE if previous one is gone. */
-			Dot11d_Reset(dev);
-		}
-		break;
-	case DOT11D_STATE_NONE:
-		break;
-	}
-}
-
-int IsLegalChannel(struct ieee80211_device *dev, u8 channel)
-{
-	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
-
-	if (MAX_CHANNEL_NUMBER < channel) {
-		netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
-		return 0;
-	}
-	if (pDot11dInfo->channel_map[channel] > 0)
-		return 1;
-	return 0;
-}
-
-int ToLegalChannel(struct ieee80211_device *dev, u8 channel)
-{
-	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
-	u8 default_chn = 0;
-	u32 i = 0;
-
-	for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
-		if (pDot11dInfo->channel_map[i] > 0) {
-			default_chn = i;
-			break;
-		}
-	}
-
-	if (MAX_CHANNEL_NUMBER < channel) {
-		netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
-		return default_chn;
-	}
-
-	if (pDot11dInfo->channel_map[channel] > 0)
-		return channel;
-
-	return default_chn;
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.h b/drivers/staging/rtl8187se/ieee80211/dot11d.h
deleted file mode 100644
index f996691307bf..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/dot11d.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef __INC_DOT11D_H
-#define __INC_DOT11D_H
-
-#include "ieee80211.h"
-
-/* #define ENABLE_DOT11D */
-
-/* #define DOT11D_MAX_CHNL_NUM 83 */
-
-typedef struct _CHNL_TXPOWER_TRIPLE {
-	u8 FirstChnl;
-	u8  NumChnls;
-	u8  MaxTxPowerInDbm;
-} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
-
-typedef enum _DOT11D_STATE {
-	DOT11D_STATE_NONE = 0,
-	DOT11D_STATE_LEARNED,
-	DOT11D_STATE_DONE,
-} DOT11D_STATE;
-
-typedef struct _RT_DOT11D_INFO {
-	/* DECLARE_RT_OBJECT(RT_DOT12D_INFO); */
-
-	bool bEnabled; /* dot11MultiDomainCapabilityEnabled */
-
-	u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */
-	u8  CountryIeBuf[MAX_IE_LEN];
-	u8  CountryIeSrcAddr[6]; /* Source AP of the country IE. */
-	u8  CountryIeWatchdog;
-
-	u8  channel_map[MAX_CHANNEL_NUMBER+1];  /* !!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */
-	/* u8  ChnlListLen; // #Bytes valid in ChnlList[]. */
-	/* u8  ChnlList[DOT11D_MAX_CHNL_NUM]; */
-	u8  MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
-
-	DOT11D_STATE State;
-} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
-
-#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1:0)
-#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
-#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
-
-#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
-#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
-
-#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-
-#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
-	(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
-	FALSE : \
-	(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
-
-#define CIE_WATCHDOG_TH 1
-#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
-#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
-#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
-
-#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
-
-void Dot11d_Init(struct ieee80211_device *dev);
-void Dot11d_Reset(struct ieee80211_device *dev);
-void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
-			    u16 CoutryIeLen, u8 *pCoutryIe);
-u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel);
-void DOT11D_ScanComplete(struct ieee80211_device *dev);
-int IsLegalChannel(struct ieee80211_device *dev, u8 channel);
-int ToLegalChannel(struct ieee80211_device *dev, u8 channel);
-
-#endif /*  #ifndef __INC_DOT11D_H */
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
deleted file mode 100644
index d1763b7b8f27..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ /dev/null
@@ -1,1496 +0,0 @@
-/*
- * Merged with mainline ieee80211.h in Aug 2004.  Original ieee802_11
- * remains copyright by the original authors
- *
- * Portions of the merged code are based on Host AP (software wireless
- * LAN access point) driver for Intersil Prism2/2.5/3.
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * Adaption to a generic IEEE 802.11 stack by James Ketrenos
- * <jketreno@linux.intel.com>
- * Copyright (c) 2004, Intel Corporation
- *
- * Modified for Realtek's wi-fi cards by Andrea Merello
- * <andrea.merello@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-#ifndef IEEE80211_H
-#define IEEE80211_H
-#include <linux/if_ether.h> /* ETH_ALEN */
-#include <linux/kernel.h>   /* ARRAY_SIZE */
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/semaphore.h>
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <linux/interrupt.h>
-
-#define KEY_TYPE_NA		0x0
-#define KEY_TYPE_WEP40 		0x1
-#define KEY_TYPE_TKIP		0x2
-#define KEY_TYPE_CCMP		0x4
-#define KEY_TYPE_WEP104		0x5
-
-#define aSifsTime					10
-
-#define MGMT_QUEUE_NUM 5
-
-
-#define IEEE_CMD_SET_WPA_PARAM			1
-#define	IEEE_CMD_SET_WPA_IE			2
-#define IEEE_CMD_SET_ENCRYPTION			3
-#define IEEE_CMD_MLME				4
-
-#define IEEE_PARAM_WPA_ENABLED			1
-#define IEEE_PARAM_TKIP_COUNTERMEASURES		2
-#define IEEE_PARAM_DROP_UNENCRYPTED		3
-#define IEEE_PARAM_PRIVACY_INVOKED		4
-#define IEEE_PARAM_AUTH_ALGS			5
-#define IEEE_PARAM_IEEE_802_1X			6
-//It should consistent with the driver_XXX.c
-//   David, 2006.9.26
-#define IEEE_PARAM_WPAX_SELECT			7
-//Added for notify the encryption type selection
-//   David, 2006.9.26
-#define IEEE_PROTO_WPA				1
-#define IEEE_PROTO_RSN				2
-//Added for notify the encryption type selection
-//   David, 2006.9.26
-#define IEEE_WPAX_USEGROUP			0
-#define IEEE_WPAX_WEP40				1
-#define IEEE_WPAX_TKIP				2
-#define IEEE_WPAX_WRAP   			3
-#define IEEE_WPAX_CCMP				4
-#define IEEE_WPAX_WEP104			5
-
-#define IEEE_KEY_MGMT_IEEE8021X			1
-#define IEEE_KEY_MGMT_PSK			2
-
-
-
-#define IEEE_MLME_STA_DEAUTH			1
-#define IEEE_MLME_STA_DISASSOC			2
-
-
-#define IEEE_CRYPT_ERR_UNKNOWN_ALG		2
-#define IEEE_CRYPT_ERR_UNKNOWN_ADDR		3
-#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED		4
-#define IEEE_CRYPT_ERR_KEY_SET_FAILED		5
-#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED		6
-#define IEEE_CRYPT_ERR_CARD_CONF_FAILED		7
-
-
-#define	IEEE_CRYPT_ALG_NAME_LEN			16
-
-extern int ieee80211_crypto_tkip_init(void);
-extern void ieee80211_crypto_tkip_exit(void);
-
-//by amy for ps
-typedef struct ieee_param {
-	u32 cmd;
-	u8 sta_addr[ETH_ALEN];
-        union {
-		struct {
-			u8 name;
-			u32 value;
-		} wpa_param;
-		struct {
-			u32 len;
-			u8 reserved[32];
-			u8 data[0];
-		} wpa_ie;
-	        struct{
-			int command;
-    			int reason_code;
-		} mlme;
-		struct {
-			u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
-			u8 set_tx;
-			u32 err;
-			u8 idx;
-			u8 seq[8]; /* sequence counter (set: RX, get: TX) */
-			u16 key_len;
-			u8 key[0];
-		} crypt;
-
-	} u;
-}ieee_param;
-
-
-#define MSECS(t) msecs_to_jiffies(t)
-#define msleep_interruptible_rtl  msleep_interruptible
-
-#define IEEE80211_DATA_LEN		2304
-/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
-   6.2.1.1.2.
-
-   The figure in section 7.1.2 suggests a body size of up to 2312
-   bytes is allowed, which is a bit confusing, I suspect this
-   represents the 2304 bytes of real data, plus a possible 8 bytes of
-   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
-
-#define IEEE80211_3ADDR_LEN 24
-#define IEEE80211_4ADDR_LEN 30
-#define IEEE80211_FCS_LEN    4
-#define IEEE80211_HLEN			IEEE80211_4ADDR_LEN
-#define IEEE80211_FRAME_LEN		(IEEE80211_DATA_LEN + IEEE80211_HLEN)
-#define IEEE80211_MGMT_HDR_LEN 24
-#define IEEE80211_DATA_HDR3_LEN 24
-#define IEEE80211_DATA_HDR4_LEN 30
-
-#define MIN_FRAG_THRESHOLD     256U
-#define	MAX_FRAG_THRESHOLD     2346U
-
-/* Frame control field constants */
-#define IEEE80211_FCTL_DSTODS		0x0300 //added by david
-#define IEEE80211_FCTL_WEP		0x4000
-
-/* debug macros */
-
-#ifdef CONFIG_IEEE80211_DEBUG
-extern u32 ieee80211_debug_level;
-#define IEEE80211_DEBUG(level, fmt, args...) \
-do { if (ieee80211_debug_level & (level)) \
-  printk(KERN_DEBUG "ieee80211: %c %s " fmt, \
-         in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
-#else
-#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
-#endif	/* CONFIG_IEEE80211_DEBUG */
-
-/*
- * To use the debug system;
- *
- * If you are defining a new debug classification, simply add it to the #define
- * list here in the form of:
- *
- * #define IEEE80211_DL_xxxx VALUE
- *
- * shifting value to the left one bit from the previous entry.  xxxx should be
- * the name of the classification (for example, WEP)
- *
- * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your
- * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want
- * to send output to that classification.
- *
- * To add your debug level to the list of levels seen when you perform
- *
- * % cat /proc/net/ipw/debug_level
- *
- * you simply need to add your entry to the ipw_debug_levels array.
- *
- * If you do not see debug_level in /proc/net/ipw then you do not have
- * CONFIG_IEEE80211_DEBUG defined in your kernel configuration
- *
- */
-
-#define IEEE80211_DL_INFO          (1<<0)
-#define IEEE80211_DL_WX            (1<<1)
-#define IEEE80211_DL_SCAN          (1<<2)
-#define IEEE80211_DL_STATE         (1<<3)
-#define IEEE80211_DL_MGMT          (1<<4)
-#define IEEE80211_DL_FRAG          (1<<5)
-#define IEEE80211_DL_EAP           (1<<6)
-#define IEEE80211_DL_DROP          (1<<7)
-
-#define IEEE80211_DL_TX            (1<<8)
-#define IEEE80211_DL_RX            (1<<9)
-
-#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
-#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
-#define IEEE80211_DEBUG_INFO(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a)
-
-#define IEEE80211_DEBUG_WX(f, a...)     IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a)
-#define IEEE80211_DEBUG_SCAN(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a)
-//#define IEEE_DEBUG_SCAN  IEEE80211_WARNING
-#define IEEE80211_DEBUG_STATE(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
-#define IEEE80211_DEBUG_MGMT(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
-#define IEEE80211_DEBUG_FRAG(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
-#define IEEE80211_DEBUG_EAP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
-#define IEEE80211_DEBUG_DROP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
-#define IEEE80211_DEBUG_TX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
-#define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
-#include <linux/netdevice.h>
-#include <linux/if_arp.h> /* ARPHRD_ETHER */
-
-#ifndef WIRELESS_SPY
-#define WIRELESS_SPY		// enable iwspy support
-#endif
-#include <net/iw_handler.h>	// new driver API
-
-#ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
-
-#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
-
-#ifndef ETH_P_80211_RAW
-#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
-#endif
-
-/* IEEE 802.11 defines */
-
-#define P80211_OUI_LEN 3
-
-struct ieee80211_snap_hdr {
-
-        u8    dsap;   /* always 0xAA */
-        u8    ssap;   /* always 0xAA */
-        u8    ctrl;   /* always 0x03 */
-        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
-
-} __attribute__ ((packed));
-
-#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
-
-#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
-
-#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
-#define WLAN_GET_SEQ_SEQ(seq)  ((seq) & IEEE80211_SCTL_SEQ)
-
-#define WLAN_CAPABILITY_BSS (1<<0)
-#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
-
-#define IEEE80211_STATMASK_SIGNAL (1<<0)
-#define IEEE80211_STATMASK_RSSI (1<<1)
-#define IEEE80211_STATMASK_NOISE (1<<2)
-#define IEEE80211_STATMASK_RATE (1<<3)
-#define IEEE80211_STATMASK_WEMASK 0x7
-
-
-#define IEEE80211_CCK_MODULATION    (1<<0)
-#define IEEE80211_OFDM_MODULATION   (1<<1)
-
-#define IEEE80211_24GHZ_BAND     (1<<0)
-#define IEEE80211_52GHZ_BAND     (1<<1)
-
-#define IEEE80211_CCK_RATE_LEN  		4
-#define IEEE80211_CCK_RATE_1MB		        0x02
-#define IEEE80211_CCK_RATE_2MB		        0x04
-#define IEEE80211_CCK_RATE_5MB		        0x0B
-#define IEEE80211_CCK_RATE_11MB		        0x16
-#define IEEE80211_OFDM_RATE_LEN 		8
-#define IEEE80211_OFDM_RATE_6MB		        0x0C
-#define IEEE80211_OFDM_RATE_9MB		        0x12
-#define IEEE80211_OFDM_RATE_12MB		0x18
-#define IEEE80211_OFDM_RATE_18MB		0x24
-#define IEEE80211_OFDM_RATE_24MB		0x30
-#define IEEE80211_OFDM_RATE_36MB		0x48
-#define IEEE80211_OFDM_RATE_48MB		0x60
-#define IEEE80211_OFDM_RATE_54MB		0x6C
-#define IEEE80211_BASIC_RATE_MASK		0x80
-
-#define IEEE80211_CCK_RATE_1MB_MASK		(1<<0)
-#define IEEE80211_CCK_RATE_2MB_MASK		(1<<1)
-#define IEEE80211_CCK_RATE_5MB_MASK		(1<<2)
-#define IEEE80211_CCK_RATE_11MB_MASK		(1<<3)
-#define IEEE80211_OFDM_RATE_6MB_MASK		(1<<4)
-#define IEEE80211_OFDM_RATE_9MB_MASK		(1<<5)
-#define IEEE80211_OFDM_RATE_12MB_MASK		(1<<6)
-#define IEEE80211_OFDM_RATE_18MB_MASK		(1<<7)
-#define IEEE80211_OFDM_RATE_24MB_MASK		(1<<8)
-#define IEEE80211_OFDM_RATE_36MB_MASK		(1<<9)
-#define IEEE80211_OFDM_RATE_48MB_MASK		(1<<10)
-#define IEEE80211_OFDM_RATE_54MB_MASK		(1<<11)
-
-#define IEEE80211_CCK_RATES_MASK	        0x0000000F
-#define IEEE80211_CCK_BASIC_RATES_MASK	(IEEE80211_CCK_RATE_1MB_MASK | \
-	IEEE80211_CCK_RATE_2MB_MASK)
-#define IEEE80211_CCK_DEFAULT_RATES_MASK	(IEEE80211_CCK_BASIC_RATES_MASK | \
-        IEEE80211_CCK_RATE_5MB_MASK | \
-        IEEE80211_CCK_RATE_11MB_MASK)
-
-#define IEEE80211_OFDM_RATES_MASK		0x00000FF0
-#define IEEE80211_OFDM_BASIC_RATES_MASK	(IEEE80211_OFDM_RATE_6MB_MASK | \
-	IEEE80211_OFDM_RATE_12MB_MASK | \
-	IEEE80211_OFDM_RATE_24MB_MASK)
-#define IEEE80211_OFDM_DEFAULT_RATES_MASK	(IEEE80211_OFDM_BASIC_RATES_MASK | \
-	IEEE80211_OFDM_RATE_9MB_MASK  | \
-	IEEE80211_OFDM_RATE_18MB_MASK | \
-	IEEE80211_OFDM_RATE_36MB_MASK | \
-	IEEE80211_OFDM_RATE_48MB_MASK | \
-	IEEE80211_OFDM_RATE_54MB_MASK)
-#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
-                                IEEE80211_CCK_DEFAULT_RATES_MASK)
-
-#define IEEE80211_NUM_OFDM_RATES	    8
-#define IEEE80211_NUM_CCK_RATES	            4
-#define IEEE80211_OFDM_SHIFT_MASK_A         4
-
-/* this is stolen and modified from the madwifi driver*/
-#define IEEE80211_FC0_TYPE_MASK		0x0c
-#define IEEE80211_FC0_TYPE_DATA		0x08
-#define IEEE80211_FC0_SUBTYPE_MASK	0xB0
-#define IEEE80211_FC0_SUBTYPE_QOS	0x80
-
-#define IEEE80211_QOS_HAS_SEQ(fc) \
-	(((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \
-	 (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
-
-/* this is stolen from ipw2200 driver */
-#define IEEE_IBSS_MAC_HASH_SIZE 31
-struct ieee_ibss_seq {
-	u8 mac[ETH_ALEN];
-	u16 seq_num[17];
-	u16 frag_num[17];
-	unsigned long packet_time[17];
-	struct list_head list;
-};
-
-/* NOTE: This data is for statistical purposes; not all hardware provides this
- *       information for frames received.  Not setting these will not cause
- *       any adverse affects. */
-struct ieee80211_rx_stats {
-	u32 mac_time[2];
-	u8 signalstrength;
-	s8 rssi;
-	u8 signal;
-	u8 noise;
-	u16 rate; /* in 100 kbps */
-	u8 received_channel;
-	u8 control;
-	u8 mask;
-	u8 freq;
-	u16 len;
-	u8 nic_type;
-};
-
-/* IEEE 802.11 requires that STA supports concurrent reception of at least
- * three fragmented frames. This define can be increased to support more
- * concurrent frames, but it should be noted that each entry can consume about
- * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
-#define IEEE80211_FRAG_CACHE_LEN 4
-
-struct ieee80211_frag_entry {
-	unsigned long first_frag_time;
-	unsigned int seq;
-	unsigned int last_frag;
-	struct sk_buff *skb;
-	u8 src_addr[ETH_ALEN];
-	u8 dst_addr[ETH_ALEN];
-};
-
-struct ieee80211_stats {
-	unsigned int tx_unicast_frames;
-	unsigned int tx_multicast_frames;
-	unsigned int tx_fragments;
-	unsigned int tx_unicast_octets;
-	unsigned int tx_multicast_octets;
-	unsigned int tx_deferred_transmissions;
-	unsigned int tx_single_retry_frames;
-	unsigned int tx_multiple_retry_frames;
-	unsigned int tx_retry_limit_exceeded;
-	unsigned int tx_discards;
-	unsigned int rx_unicast_frames;
-	unsigned int rx_multicast_frames;
-	unsigned int rx_fragments;
-	unsigned int rx_unicast_octets;
-	unsigned int rx_multicast_octets;
-	unsigned int rx_fcs_errors;
-	unsigned int rx_discards_no_buffer;
-	unsigned int tx_discards_wrong_sa;
-	unsigned int rx_discards_undecryptable;
-	unsigned int rx_message_in_msg_fragments;
-	unsigned int rx_message_in_bad_msg_fragments;
-};
-
-struct ieee80211_device;
-
-#include "ieee80211_crypt.h"
-
-#define SEC_KEY_1         (1<<0)
-#define SEC_KEY_2         (1<<1)
-#define SEC_KEY_3         (1<<2)
-#define SEC_KEY_4         (1<<3)
-#define SEC_ACTIVE_KEY    (1<<4)
-#define SEC_AUTH_MODE     (1<<5)
-#define SEC_UNICAST_GROUP (1<<6)
-#define SEC_LEVEL         (1<<7)
-#define SEC_ENABLED       (1<<8)
-
-#define SEC_LEVEL_0      0 /* None */
-#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
-#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
-#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
-#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
-
-#define WEP_KEYS 4
-#define WEP_KEY_LEN 13
-
-#define WEP_KEY_LEN_MODIF 32
-
-struct ieee80211_security {
-	u16 active_key:2,
-            enabled:1,
-	    auth_mode:2,
-            auth_algo:4,
-            unicast_uses_group:1;
-	u8 key_sizes[WEP_KEYS];
-	u8 keys[WEP_KEYS][WEP_KEY_LEN_MODIF];
-	u8 level;
-	u16 flags;
-} __attribute__ ((packed));
-
-
-/*
-
- 802.11 data frame from AP
-
-      ,-------------------------------------------------------------------.
-Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
-      |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
-      |      | tion | (BSSID) |         |         | ence |  data   |      |
-      `-------------------------------------------------------------------'
-
-Total: 28-2340 bytes
-
-*/
-
-/* Management Frame Information Element Types */
-enum {
-	MFIE_TYPE_SSID = 0,
-	MFIE_TYPE_RATES = 1,
-	MFIE_TYPE_FH_SET = 2,
-	MFIE_TYPE_DS_SET = 3,
-	MFIE_TYPE_CF_SET = 4,
-	MFIE_TYPE_TIM = 5,
-	MFIE_TYPE_IBSS_SET = 6,
-	MFIE_TYPE_COUNTRY = 7,
-	MFIE_TYPE_CHALLENGE = 16,
-	MFIE_TYPE_ERP = 42,
-	MFIE_TYPE_RSN = 48,
-	MFIE_TYPE_RATES_EX = 50,
-	MFIE_TYPE_GENERIC = 221,
-};
-
-struct ieee80211_header_data {
-	__le16 frame_ctl;
-	u16 duration_id;
-	u8 addr1[6];
-	u8 addr2[6];
-	u8 addr3[6];
-	u16 seq_ctrl;
-};
-
-struct ieee80211_hdr_4addr {
-	__le16 frame_ctl;
-	u16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_3addrqos {
-	u16 frame_ctl;
-	u16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
-	u16 qos_ctl;
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_4addrqos {
-	u16 frame_ctl;
-	u16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-	u16 qos_ctl;
-} __attribute__ ((packed));
-
-struct ieee80211_info_element_hdr {
-	u8 id;
-	u8 len;
-} __attribute__ ((packed));
-
-struct ieee80211_info_element {
-	u8 id;
-	u8 len;
-	u8 data[0];
-} __attribute__ ((packed));
-
-struct ieee80211_authentication {
-	struct ieee80211_header_data header;
-	u16 algorithm;
-	u16 transaction;
-	u16 status;
-	//struct ieee80211_info_element_hdr info_element;
-} __attribute__ ((packed));
-
-struct ieee80211_disassoc_frame {
-	struct ieee80211_hdr_3addr header;
-	u16    reasoncode;
-} __attribute__ ((packed));
-
-struct ieee80211_probe_request {
-	struct ieee80211_header_data header;
-	/* struct ieee80211_info_element info_element; */
-} __attribute__ ((packed));
-
-struct ieee80211_probe_response {
-	struct ieee80211_header_data header;
-	u32 time_stamp[2];
-	u16 beacon_interval;
-	u16 capability;
-	struct ieee80211_info_element info_element;
-} __attribute__ ((packed));
-
-struct ieee80211_assoc_request_frame {
-	struct ieee80211_hdr_3addr header;
-	u16 capability;
-	u16 listen_interval;
-	//u8 current_ap[ETH_ALEN];
-	struct ieee80211_info_element_hdr info_element;
-} __attribute__ ((packed));
-
-struct ieee80211_assoc_response_frame {
-	struct ieee80211_hdr_3addr header;
-	u16 capability;
-	u16 status;
-	u16 aid;
-	struct ieee80211_info_element info_element; /* supported rates */
-} __attribute__ ((packed));
-
-struct ieee80211_txb {
-	u8 nr_frags;
-	u8 encrypted;
-	u16 reserved;
-	u16 frag_size;
-	u16 payload_size;
-	struct sk_buff *fragments[0];
-};
-
-/* SWEEP TABLE ENTRIES NUMBER */
-#define MAX_SWEEP_TAB_ENTRIES			42
-#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET	7
-
-/* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
- * only use 8, and then use extended rates for the remaining supported
- * rates.  Other APs, however, stick all of their supported rates on the
- * main rates information element... */
-#define MAX_RATES_LENGTH			((u8)12)
-#define MAX_RATES_EX_LENGTH			((u8)16)
-
-#define MAX_NETWORK_COUNT			128
-
-#define MAX_CHANNEL_NUMBER			165
-
-#define IEEE80211_SOFTMAC_SCAN_TIME		100 /* (HZ / 2) */
-#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME	(HZ * 2)
-
-#define CRC_LENGTH	4U
-
-#define MAX_WPA_IE_LEN	64
-
-#define NETWORK_EMPTY_ESSID	(1 << 0)
-#define NETWORK_HAS_OFDM	(1 << 1)
-#define NETWORK_HAS_CCK		(1 << 2)
-
-struct ieee80211_wmm_ac_param {
-	u8 ac_aci_acm_aifsn;
-	u8 ac_ecwmin_ecwmax;
-	u16 ac_txop_limit;
-};
-
-struct ieee80211_wmm_ts_info {
-	u8 ac_dir_tid;
-	u8 ac_up_psb;
-	u8 reserved;
-} __attribute__ ((packed));
-
-struct ieee80211_wmm_tspec_elem {
-	struct ieee80211_wmm_ts_info ts_info;
-	u16 norm_msdu_size;
-	u16 max_msdu_size;
-	u32 min_serv_inter;
-	u32 max_serv_inter;
-	u32 inact_inter;
-	u32 suspen_inter;
-	u32 serv_start_time;
-	u32 min_data_rate;
-	u32 mean_data_rate;
-	u32 peak_data_rate;
-	u32 max_burst_size;
-	u32 delay_bound;
-	u32 min_phy_rate;
-	u16 surp_band_allow;
-	u16 medium_time;
-}__attribute__((packed));
-
-enum eap_type {
-	EAP_PACKET = 0,
-	EAPOL_START,
-	EAPOL_LOGOFF,
-	EAPOL_KEY,
-	EAPOL_ENCAP_ASF_ALERT
-};
-
-static const char *eap_types[] = {
-	[EAP_PACKET]		= "EAP-Packet",
-	[EAPOL_START]		= "EAPOL-Start",
-	[EAPOL_LOGOFF]		= "EAPOL-Logoff",
-	[EAPOL_KEY]		= "EAPOL-Key",
-	[EAPOL_ENCAP_ASF_ALERT]	= "EAPOL-Encap-ASF-Alert"
-};
-
-static inline const char *eap_get_type(int type)
-{
-	return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
-}
-
-struct eapol {
-	u8 snap[6];
-	u16 ethertype;
-	u8 version;
-	u8 type;
-	u16 length;
-} __attribute__ ((packed));
-
-struct ieee80211_softmac_stats {
-	unsigned int rx_ass_ok;
-	unsigned int rx_ass_err;
-	unsigned int rx_probe_rq;
-	unsigned int tx_probe_rs;
-	unsigned int tx_beacons;
-	unsigned int rx_auth_rq;
-	unsigned int rx_auth_rs_ok;
-	unsigned int rx_auth_rs_err;
-	unsigned int tx_auth_rq;
-	unsigned int no_auth_rs;
-	unsigned int no_ass_rs;
-	unsigned int tx_ass_rq;
-	unsigned int rx_ass_rq;
-	unsigned int tx_probe_rq;
-	unsigned int reassoc;
-	unsigned int swtxstop;
-	unsigned int swtxawake;
-};
-
-#define BEACON_PROBE_SSID_ID_POSITION 12
-
-/*
- * These are the data types that can make up management packets
- *
-	u16 auth_algorithm;
-	u16 auth_sequence;
-	u16 beacon_interval;
-	u16 capability;
-	u8 current_ap[ETH_ALEN];
-	u16 listen_interval;
-	struct {
-		u16 association_id:14, reserved:2;
-	} __attribute__ ((packed));
-	u32 time_stamp[2];
-	u16 reason;
-	u16 status;
-*/
-
-#define IEEE80211_DEFAULT_TX_ESSID "Penguin"
-#define IEEE80211_DEFAULT_BASIC_RATE 10
-
-enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
-#define MAX_SP_Len  (WMM_all_frame << 4)
-#define IEEE80211_QOS_TID 0x0f
-#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5)
-
-#define MAX_IE_LEN						0xFF //+YJ,080625
-
-struct rtl8187se_channel_list {
-	u8	channel[MAX_CHANNEL_NUMBER + 1];
-	u8	len;
-};
-
-//by amy for ps
-#define IEEE80211_WATCH_DOG_TIME    2000
-//by amy for ps
-//by amy for antenna
-#define ANTENNA_DIVERSITY_TIMER_PERIOD		1000 // 1000 m
-//by amy for antenna
-
-#define IEEE80211_DTIM_MBCAST 4
-#define IEEE80211_DTIM_UCAST 2
-#define IEEE80211_DTIM_VALID 1
-#define IEEE80211_DTIM_INVALID 0
-
-#define IEEE80211_PS_DISABLED 0
-#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST
-#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST
-#define IEEE80211_PS_ENABLE   IEEE80211_DTIM_VALID
-//added by David for QoS 2006/6/30
-//#define WMM_Hang_8187
-#ifdef WMM_Hang_8187
-#undef WMM_Hang_8187
-#endif
-
-#define WME_AC_BE   0x00
-#define WME_AC_BK   0x01
-#define WME_AC_VI   0x02
-#define WME_AC_VO   0x03
-#define WME_ACI_MASK 0x03
-#define WME_AIFSN_MASK 0x03
-#define WME_AC_PRAM_LEN 16
-
-//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
-//#define UP2AC(up)	((up<3) ? ((up==0)?1:0) : (up>>1))
-#define UP2AC(up) (		   \
-	((up) < 1) ? WME_AC_BE : \
-	((up) < 3) ? WME_AC_BK : \
-	((up) < 4) ? WME_AC_BE : \
-	((up) < 6) ? WME_AC_VI : \
-	WME_AC_VO)
-//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue
-#define AC2UP(_ac)	(       \
-	((_ac) == WME_AC_VO) ? 6 : \
-	((_ac) == WME_AC_VI) ? 5 : \
-	((_ac) == WME_AC_BK) ? 1 : \
-	0)
-
-#define	ETHER_ADDR_LEN		6	/* length of an Ethernet address */
-struct	ether_header {
-	u8 ether_dhost[ETHER_ADDR_LEN];
-	u8 ether_shost[ETHER_ADDR_LEN];
-	u16 ether_type;
-} __attribute__((packed));
-
-#ifndef ETHERTYPE_PAE
-#define	ETHERTYPE_PAE	0x888e		/* EAPOL PAE/802.1x */
-#endif
-#ifndef ETHERTYPE_IP
-#define	ETHERTYPE_IP	0x0800		/* IP protocol */
-#endif
-
-struct ieee80211_network {
-	/* These entries are used to identify a unique network */
-	u8 bssid[ETH_ALEN];
-	u8 channel;
-	/* Ensure null-terminated for any debug msgs */
-	u8 ssid[IW_ESSID_MAX_SIZE + 1];
-	u8 ssid_len;
-
-	/* These are network statistics */
-	struct ieee80211_rx_stats stats;
-	u16 capability;
-	u8 rates[MAX_RATES_LENGTH];
-	u8 rates_len;
-	u8 rates_ex[MAX_RATES_EX_LENGTH];
-	u8 rates_ex_len;
-	unsigned long last_scanned;
-	u8 mode;
-	u8 flags;
-	u32 last_associate;
-	u32 time_stamp[2];
-	u16 beacon_interval;
-	u16 listen_interval;
-	u16 atim_window;
-	u8 wpa_ie[MAX_WPA_IE_LEN];
-	size_t wpa_ie_len;
-	u8 rsn_ie[MAX_WPA_IE_LEN];
-	size_t rsn_ie_len;
-	u8 dtim_period;
-	u8 dtim_data;
-	u32 last_dtim_sta_time[2];
-	struct list_head list;
-	//appeded for QoS
-	u8 wmm_info;
-	struct ieee80211_wmm_ac_param wmm_param[4];
-	u8 QoS_Enable;
-	u8 SignalStrength;
-//by amy 080312
-	u8 HighestOperaRate;
-//by amy 080312
-	u8 Turbo_Enable;//enable turbo mode, added by thomas
-	u16 CountryIeLen;
-	u8 CountryIeBuf[MAX_IE_LEN];
-};
-
-enum ieee80211_state {
-
-	/* the card is not linked at all */
-	IEEE80211_NOLINK = 0,
-
-	/* IEEE80211_ASSOCIATING* are for BSS client mode
-	 * the driver shall not perform RX filtering unless
-	 * the state is LINKED.
-	 * The driver shall just check for the state LINKED and
-	 * defaults to NOLINK for ALL the other states (including
-	 * LINKED_SCANNING)
-	 */
-
-	/* the association procedure will start (wq scheduling)*/
-	IEEE80211_ASSOCIATING,
-	IEEE80211_ASSOCIATING_RETRY,
-
-	/* the association procedure is sending AUTH request*/
-	IEEE80211_ASSOCIATING_AUTHENTICATING,
-
-	/* the association procedure has successfully authenticated
-	 * and is sending association request
-	 */
-	IEEE80211_ASSOCIATING_AUTHENTICATED,
-
-	/* the link is ok. the card associated to a BSS or linked
-	 * to a ibss cell or acting as an AP and creating the bss
-	 */
-	IEEE80211_LINKED,
-
-	/* same as LINKED, but the driver shall apply RX filter
-	 * rules as we are in NO_LINK mode. As the card is still
-	 * logically linked, but it is doing a syncro site survey
-	 * then it will be back to LINKED state.
-	 */
-	IEEE80211_LINKED_SCANNING,
-
-};
-
-#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
-#define DEFAULT_FTS 2346
-
-#define CFG_IEEE80211_RESERVE_FCS (1<<0)
-#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
-
-typedef struct tx_pending_t{
-	int frag;
-	struct ieee80211_txb *txb;
-}tx_pending_t;
-
-enum {
-	COUNTRY_CODE_FCC = 0,
-	COUNTRY_CODE_IC = 1,
-	COUNTRY_CODE_ETSI = 2,
-	COUNTRY_CODE_SPAIN = 3,
-	COUNTRY_CODE_FRANCE = 4,
-	COUNTRY_CODE_MKK = 5,
-	COUNTRY_CODE_MKK1 = 6,
-	COUNTRY_CODE_ISRAEL = 7,
-	COUNTRY_CODE_TELEC = 8,
-	COUNTRY_CODE_GLOBAL_DOMAIN = 9,
-	COUNTRY_CODE_WORLD_WIDE_13_INDEX = 10
-};
-
-struct ieee80211_device {
-	struct net_device *dev;
-
-	/* Bookkeeping structures */
-	struct net_device_stats stats;
-	struct ieee80211_stats ieee_stats;
-	struct ieee80211_softmac_stats softmac_stats;
-
-	/* Probe / Beacon management */
-	struct list_head network_free_list;
-	struct list_head network_list;
-	struct ieee80211_network *networks;
-	int scans;
-	int scan_age;
-
-	int iw_mode; /* operating mode (IW_MODE_*) */
-
-	spinlock_t lock;
-	spinlock_t wpax_suitlist_lock;
-
-	int tx_headroom; /* Set to size of any additional room needed at front
-			  * of allocated Tx SKBs */
-	u32 config;
-
-	/* WEP and other encryption related settings at the device level */
-	int open_wep; /* Set to 1 to allow unencrypted frames */
-
-	int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
-				 * WEP key changes */
-
-	/* If the host performs {en,de}cryption, then set to 1 */
-	int host_encrypt;
-	int host_decrypt;
-	int ieee802_1x; /* is IEEE 802.1X used */
-
-	/* WPA data */
-	int wpa_enabled;
-	int drop_unencrypted;
-	int tkip_countermeasures;
-	int privacy_invoked;
-	size_t wpa_ie_len;
-	u8 *wpa_ie;
-
-	u8 ap_mac_addr[6];
-	u16 pairwise_key_type;
-	u16 broadcast_key_type;
-
-	struct list_head crypt_deinit_list;
-	struct ieee80211_crypt_data *crypt[WEP_KEYS];
-	int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
-	struct timer_list crypt_deinit_timer;
-
-	int bcrx_sta_key; /* use individual keys to override default keys even
-			   * with RX of broad/multicast frames */
-
-	/* Fragmentation structures */
-	/* each stream contains an entry */
-	struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN];
-	unsigned int frag_next_idx[17];
-	u16 fts; /* Fragmentation Threshold */
-
-	/* This stores infos for the current network.
-	 * Either the network we are associated in INFRASTRUCTURE
-	 * or the network that we are creating in MASTER mode.
-	 * ad-hoc is a mixture ;-).
-	 * Note that in infrastructure mode, even when not associated,
-	 * fields bssid and essid may be valid (if wpa_set and essid_set
-	 * are true) as thy carry the value set by the user via iwconfig
-	 */
-	struct ieee80211_network current_network;
-
-
-	enum ieee80211_state state;
-
-	int short_slot;
-	int mode;       /* A, B, G */
-	int modulation; /* CCK, OFDM */
-	int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
-	int abg_true;   /* ABG flag              */
-
-	/* used for forcing the ibss workqueue to terminate
-	 * without wait for the syncro scan to terminate
-	 */
-	short sync_scan_hurryup;
-
-	void * pDot11dInfo;
-	bool bGlobalDomain;
-
-	// For Liteon Ch12~13 passive scan
-	u8	MinPassiveChnlNum;
-	u8	IbssStartChnl;
-
-	int rate;       /* current rate */
-	int basic_rate;
-	//FIXME: please callback, see if redundant with softmac_features
-	short active_scan;
-
-	/* this contains flags for selectively enable softmac support */
-	u16 softmac_features;
-
-	/* if the sequence control field is not filled by HW */
-	u16 seq_ctrl[5];
-
-	/* association procedure transaction sequence number */
-	u16 associate_seq;
-
-	/* AID for RTXed association responses */
-	u16 assoc_id;
-
-	/* power save mode related*/
-	short ps;
-	short sta_sleep;
-	int ps_timeout;
-	struct tasklet_struct ps_task;
-	u32 ps_th;
-	u32 ps_tl;
-
-	short raw_tx;
-	/* used if IEEE_SOFTMAC_TX_QUEUE is set */
-	short queue_stop;
-	short scanning;
-	short proto_started;
-
-	struct semaphore wx_sem;
-	struct semaphore scan_sem;
-
-	spinlock_t mgmt_tx_lock;
-	spinlock_t beacon_lock;
-
-	short beacon_txing;
-
-	short wap_set;
-	short ssid_set;
-
-	u8  wpax_type_set;    //{added by David, 2006.9.28}
-	u32 wpax_type_notify; //{added by David, 2006.9.26}
-
-	/* QoS related flag */
-	char init_wmmparam_flag;
-
-	/* for discarding duplicated packets in IBSS */
-	struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE];
-
-	/* for discarding duplicated packets in BSS */
-	u16 last_rxseq_num[17]; /* rx seq previous per-tid */
-	u16 last_rxfrag_num[17];/* tx frag previous per-tid */
-	unsigned long last_packet_time[17];
-
-	/* for PS mode */
-	unsigned long last_rx_ps_time;
-
-	/* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
-	struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
-	int mgmt_queue_head;
-	int mgmt_queue_tail;
-
-
-	/* used if IEEE_SOFTMAC_TX_QUEUE is set */
-	struct  tx_pending_t tx_pending;
-
-	/* used if IEEE_SOFTMAC_ASSOCIATE is set */
-	struct timer_list associate_timer;
-
-	/* used if IEEE_SOFTMAC_BEACONS is set */
-	struct timer_list beacon_timer;
-
-	struct work_struct associate_complete_wq;
-//	struct work_struct associate_retry_wq;
-	struct work_struct associate_procedure_wq;
-//	struct work_struct softmac_scan_wq;
-	struct work_struct wx_sync_scan_wq;
-	struct work_struct wmm_param_update_wq;
-	struct work_struct ps_request_tx_ack_wq;//for ps
-//	struct work_struct hw_wakeup_wq;
-//	struct work_struct hw_sleep_wq;
-//	struct work_struct watch_dog_wq;
-	bool bInactivePs;
-	bool actscanning;
-	bool beinretry;
-	u16 ListenInterval;
-	unsigned long NumRxDataInPeriod; //YJ,add,080828
-	unsigned long NumRxBcnInPeriod;  //YJ,add,080828
-	unsigned long NumRxOkTotal;
-	unsigned long NumRxUnicast;//YJ,add,080828,for keep alive
-	bool bHwRadioOff;
-        struct delayed_work softmac_scan_wq;
-        struct delayed_work associate_retry_wq;
-	struct delayed_work hw_wakeup_wq;
-	struct delayed_work hw_sleep_wq;//+by amy 080324
-	struct delayed_work watch_dog_wq;
-	struct delayed_work sw_antenna_wq;
-	struct delayed_work  start_ibss_wq;
-//by amy for rate adaptive 080312
-    struct delayed_work rate_adapter_wq;
-//by amy for rate adaptive
-	struct delayed_work hw_dig_wq;
-	struct delayed_work tx_pw_wq;
-
-//Added for RF power on power off by lizhaoming 080512
-	struct delayed_work GPIOChangeRFWorkItem;
-
-	struct workqueue_struct *wq;
-
-	/* Callback functions */
-	void (*set_security)(struct net_device *dev,
-			     struct ieee80211_security *sec);
-
-	/* Used to TX data frame by using txb structs.
-	 * this is not used if in the softmac_features
-	 * is set the flag IEEE_SOFTMAC_TX_QUEUE
-	 */
-	int (*hard_start_xmit)(struct ieee80211_txb *txb,
-			       struct net_device *dev);
-
-	int (*reset_port)(struct net_device *dev);
-
-	/* Softmac-generated frames (management) are TXed via this
-	 * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
-	 * not set. As some cards may have different HW queues that
-	 * one might want to use for data and management frames
-	 * the option to have two callbacks might be useful.
-	 * This function can't sleep.
-	 */
-	int (*softmac_hard_start_xmit)(struct sk_buff *skb,
-			       struct net_device *dev);
-
-	/* used instead of hard_start_xmit (not softmac_hard_start_xmit)
-	 * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
-	 * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
-	 * then also management frames are sent via this callback.
-	 * This function can't sleep.
-	 */
-	void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
-			       struct net_device *dev,int rate);
-
-	/* stops the HW queue for DATA frames. Useful to avoid
-	 * waste time to TX data frame when we are reassociating
-	 * This function can sleep.
-	 */
-	void (*data_hard_stop)(struct net_device *dev);
-
-	/* OK this is complementar to data_poll_hard_stop */
-	void (*data_hard_resume)(struct net_device *dev);
-
-	/* ask to the driver to retune the radio .
-	 * This function can sleep. the driver should ensure
-	 * the radio has been switched before return.
-	 */
-	void (*set_chan)(struct net_device *dev,short ch);
-
-	/* These are not used if the ieee stack takes care of
-	 * scanning (IEEE_SOFTMAC_SCAN feature set).
-	 * In this case only the set_chan is used.
-	 *
-	 * The syncro version is similar to the start_scan but
-	 * does not return until all channels has been scanned.
-	 * this is called in user context and should sleep,
-	 * it is called in a work_queue when switching to ad-hoc mode
-	 * or in behalf of iwlist scan when the card is associated
-	 * and root user ask for a scan.
-	 * the function stop_scan should stop both the syncro and
-	 * background scanning and can sleep.
-	 * The function start_scan should initiate the background
-	 * scanning and can't sleep.
-	 */
-	void (*scan_syncro)(struct net_device *dev);
-	void (*start_scan)(struct net_device *dev);
-	void (*stop_scan)(struct net_device *dev);
-
-	/* indicate the driver that the link state is changed
-	 * for example it may indicate the card is associated now.
-	 * Driver might be interested in this to apply RX filter
-	 * rules or simply light the LINK led
-	 */
-	void (*link_change)(struct net_device *dev);
-
-	/* these two function indicates to the HW when to start
-	 * and stop to send beacons. This is used when the
-	 * IEEE_SOFTMAC_BEACONS is not set. For now the
-	 * stop_send_bacons is NOT guaranteed to be called only
-	 * after start_send_beacons.
-	 */
-	void (*start_send_beacons) (struct net_device *dev);
-	void (*stop_send_beacons) (struct net_device *dev);
-
-	/* power save mode related */
-	void (*sta_wake_up) (struct net_device *dev);
-	void (*ps_request_tx_ack) (struct net_device *dev);
-	void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl);
-	short (*ps_is_queue_empty) (struct net_device *dev);
-
-	/* QoS related */
-	//void (*wmm_param_update) (struct net_device *dev, u8 *ac_param);
-	//void (*wmm_param_update) (struct ieee80211_device *ieee);
-
-	/* This must be the last item so that it points to the data
-	 * allocated beyond this structure by alloc_ieee80211 */
-	u8 priv[0];
-};
-
-#define IEEE_A            (1<<0)
-#define IEEE_B            (1<<1)
-#define IEEE_G            (1<<2)
-#define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
-
-/* Generate a 802.11 header */
-
-/* Uses the channel change callback directly
- * instead of [start/stop] scan callbacks
- */
-#define IEEE_SOFTMAC_SCAN (1<<2)
-
-/* Perform authentication and association handshake */
-#define IEEE_SOFTMAC_ASSOCIATE (1<<3)
-
-/* Generate probe requests */
-#define IEEE_SOFTMAC_PROBERQ (1<<4)
-
-/* Generate response to probe requests */
-#define IEEE_SOFTMAC_PROBERS (1<<5)
-
-/* The ieee802.11 stack will manages the netif queue
- * wake/stop for the driver, taking care of 802.11
- * fragmentation. See softmac.c for details. */
-#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
-
-/* Uses only the softmac_data_hard_start_xmit
- * even for TX management frames.
- */
-#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8)
-
-/* Generate beacons.  The stack will enqueue beacons
- * to the card
- */
-#define IEEE_SOFTMAC_BEACONS (1<<6)
-
-
-
-static inline void *ieee80211_priv(struct net_device *dev)
-{
-	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
-}
-
-static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
-{
-	/* Single white space is for Linksys APs */
-	if (essid_len == 1 && essid[0] == ' ')
-		return 1;
-
-	/* Otherwise, if the entire essid is 0, we assume it is hidden */
-	while (essid_len) {
-		essid_len--;
-		if (essid[essid_len] != '\0')
-			return 0;
-	}
-
-	return 1;
-}
-
-static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
-					  int mode)
-{
-	/*
-	 * It is possible for both access points and our device to support
-	 * combinations of modes, so as long as there is one valid combination
-	 * of ap/device supported modes, then return success
-	 *
-	 */
-	if ((mode & IEEE_A) &&
-	    (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
-	    (ieee->freq_band & IEEE80211_52GHZ_BAND))
-		return 1;
-
-	if ((mode & IEEE_G) &&
-	    (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
-	    (ieee->freq_band & IEEE80211_24GHZ_BAND))
-		return 1;
-
-	if ((mode & IEEE_B) &&
-	    (ieee->modulation & IEEE80211_CCK_MODULATION) &&
-	    (ieee->freq_band & IEEE80211_24GHZ_BAND))
-		return 1;
-
-	return 0;
-}
-
-static inline int ieee80211_get_hdrlen(u16 fc)
-{
-	int hdrlen = 24;
-
-	switch (WLAN_FC_GET_TYPE(fc)) {
-	case IEEE80211_FTYPE_DATA:
-		if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
-			hdrlen = 30; /* Addr4 */
-		if(IEEE80211_QOS_HAS_SEQ(fc))
-			hdrlen += 2; /* QOS ctrl*/
-		break;
-	case IEEE80211_FTYPE_CTL:
-		switch (WLAN_FC_GET_STYPE(fc)) {
-		case IEEE80211_STYPE_CTS:
-		case IEEE80211_STYPE_ACK:
-			hdrlen = 10;
-			break;
-		default:
-			hdrlen = 16;
-			break;
-		}
-		break;
-	}
-
-	return hdrlen;
-}
-
-
-
-/* ieee80211.c */
-extern void free_ieee80211(struct net_device *dev);
-extern struct net_device *alloc_ieee80211(int sizeof_priv);
-
-extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
-
-/* ieee80211_tx.c */
-
-extern int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
-				      struct sk_buff *frag, int hdr_len);
-
-extern int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void ieee80211_txb_free(struct ieee80211_txb *);
-
-
-/* ieee80211_rx.c */
-extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
-			    struct ieee80211_rx_stats *rx_stats);
-extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-			     struct ieee80211_hdr_4addr *header,
-			     struct ieee80211_rx_stats *stats);
-
-/* ieee80211_wx.c */
-extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
-				   struct iw_request_info *info,
-				   union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
-				   struct iw_request_info *info,
-				   union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
-				       struct iw_request_info *info,
-				       union iwreq_data *wrqu, char *extra);
-int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
-			  struct iw_request_info *info,
-			  struct iw_param *data, char *extra);
-int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
-			  struct iw_request_info *info,
-			  union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
-/* ieee80211_softmac.c */
-extern short ieee80211_is_54g(const struct ieee80211_network *net);
-extern short ieee80211_is_shortslot(const struct ieee80211_network *net);
-extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee,
-				      struct sk_buff *skb,
-				      struct ieee80211_rx_stats *rx_stats,
-				      u16 type, u16 stype);
-extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee,
-				      struct ieee80211_network *net);
-
-extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb,
-				   struct ieee80211_device *ieee);
-extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_master_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_ibss(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_init(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_free(struct ieee80211_device *ieee);
-extern void ieee80211_associate_abort(struct ieee80211_device *ieee);
-extern void ieee80211_disassociate(struct ieee80211_device *ieee);
-extern void ieee80211_stop_scan(struct ieee80211_device *ieee);
-extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
-extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
-extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
-extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee,
-					  struct iw_point *p);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
-extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta,
-			       u8 asRsn);
-extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee);
-
-//Add for RF power on power off by lizhaoming 080512
-extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta,
-			       u8 asRsn);
-
-/* ieee80211_crypt_ccmp&tkip&wep.c */
-extern void ieee80211_tkip_null(void);
-extern void ieee80211_wep_null(void);
-extern void ieee80211_ccmp_null(void);
-/* ieee80211_softmac_wx.c */
-
-extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *ext);
-
-extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
-				struct iw_request_info *info,
-				union iwreq_data *awrq,
-				char *extra);
-
-extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee,
-				  struct iw_request_info *a,
-				  union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee,
-				 struct iw_request_info *a,
-				 union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
-				 struct iw_request_info *a,
-				 union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
-				  struct iw_request_info *a,
-				  union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee,
-				 struct iw_request_info *a,
-				 union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee,
-				 struct iw_request_info *a,
-				 union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
-				 struct iw_request_info *a,
-				 union iwreq_data *wrqu, char *b);
-
-extern void ieee80211_wx_sync_scan_wq(struct work_struct *work);
-
-extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
-				  struct iw_request_info *info,
-				  union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_name(struct ieee80211_device *ieee,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_set_power(struct ieee80211_device *ieee,
-				  struct iw_request_info *info,
-				  union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_power(struct ieee80211_device *ieee,
-				  struct iw_request_info *info,
-				  union iwreq_data *wrqu, char *extra);
-
-extern void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee);
-
-extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
-					     short pwr);
-
-extern const long ieee80211_wlan_frequencies[];
-
-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
-{
-	ieee->scans++;
-}
-
-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
-{
-	return ieee->scans;
-}
-
-static inline const char *escape_essid(const char *essid, u8 essid_len) {
-	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-	const char *s = essid;
-	char *d = escaped;
-
-	if (ieee80211_is_empty_essid(essid, essid_len)) {
-		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-		return escaped;
-	}
-
-	essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
-	while (essid_len--) {
-		if (*s == '\0') {
-			*d++ = '\\';
-			*d++ = '0';
-			s++;
-		} else {
-			*d++ = *s++;
-		}
-	}
-	*d = '\0';
-	return escaped;
-}
-#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
deleted file mode 100644
index 101f0c0cdb0a..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Host AP crypto routines
- *
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-//#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-
-#include "ieee80211.h"
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("HostAP crypto");
-MODULE_LICENSE("GPL");
-
-struct ieee80211_crypto_alg {
-	struct list_head list;
-	struct ieee80211_crypto_ops *ops;
-};
-
-
-struct ieee80211_crypto {
-	struct list_head algs;
-	spinlock_t lock;
-};
-
-static struct ieee80211_crypto *hcrypt;
-
-void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
-{
-	struct list_head *ptr, *n;
-	struct ieee80211_crypt_data *entry;
-
-	for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
-	     ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
-		entry = list_entry(ptr, struct ieee80211_crypt_data, list);
-
-		if (atomic_read(&entry->refcnt) != 0 && !force)
-			continue;
-
-		list_del(ptr);
-
-		if (entry->ops)
-			entry->ops->deinit(entry->priv);
-		kfree(entry);
-	}
-}
-
-void ieee80211_crypt_deinit_handler(unsigned long data)
-{
-	struct ieee80211_device *ieee = (struct ieee80211_device *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-	ieee80211_crypt_deinit_entries(ieee, 0);
-	if (!list_empty(&ieee->crypt_deinit_list)) {
-		pr_debug("entries remaining in delayed crypt deletion list\n");
-		ieee->crypt_deinit_timer.expires = jiffies + HZ;
-		add_timer(&ieee->crypt_deinit_timer);
-	}
-	spin_unlock_irqrestore(&ieee->lock, flags);
-
-}
-
-void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
-				    struct ieee80211_crypt_data **crypt)
-{
-	struct ieee80211_crypt_data *tmp;
-	unsigned long flags;
-
-	if (*crypt == NULL)
-		return;
-
-	tmp = *crypt;
-	*crypt = NULL;
-
-	/* must not run ops->deinit() while there may be pending encrypt or
-	 * decrypt operations. Use a list of delayed deinits to avoid needing
-	 * locking. */
-
-	spin_lock_irqsave(&ieee->lock, flags);
-	list_add(&tmp->list, &ieee->crypt_deinit_list);
-	if (!timer_pending(&ieee->crypt_deinit_timer)) {
-		ieee->crypt_deinit_timer.expires = jiffies + HZ;
-		add_timer(&ieee->crypt_deinit_timer);
-	}
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
-{
-	unsigned long flags;
-	struct ieee80211_crypto_alg *alg;
-
-	if (hcrypt == NULL)
-		return -1;
-
-	alg = kzalloc(sizeof(*alg), GFP_KERNEL);
-	if (alg == NULL)
-		return -ENOMEM;
-
-	alg->ops = ops;
-
-	spin_lock_irqsave(&hcrypt->lock, flags);
-	list_add(&alg->list, &hcrypt->algs);
-	spin_unlock_irqrestore(&hcrypt->lock, flags);
-
-	pr_debug("registered algorithm '%s'\n", ops->name);
-
-	return 0;
-}
-
-int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
-{
-	unsigned long flags;
-	struct list_head *ptr;
-	struct ieee80211_crypto_alg *del_alg = NULL;
-
-	if (hcrypt == NULL)
-		return -1;
-
-	spin_lock_irqsave(&hcrypt->lock, flags);
-	for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
-		struct ieee80211_crypto_alg *alg =
-			(struct ieee80211_crypto_alg *) ptr;
-		if (alg->ops == ops) {
-			list_del(&alg->list);
-			del_alg = alg;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&hcrypt->lock, flags);
-
-	if (del_alg) {
-		pr_debug("unregistered algorithm '%s'\n", ops->name);
-		kfree(del_alg);
-	}
-
-	return del_alg ? 0 : -1;
-}
-
-
-struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
-{
-	unsigned long flags;
-	struct list_head *ptr;
-	struct ieee80211_crypto_alg *found_alg = NULL;
-
-	if (hcrypt == NULL)
-		return NULL;
-
-	spin_lock_irqsave(&hcrypt->lock, flags);
-	for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
-		struct ieee80211_crypto_alg *alg =
-			(struct ieee80211_crypto_alg *) ptr;
-		if (strcmp(alg->ops->name, name) == 0) {
-			found_alg = alg;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&hcrypt->lock, flags);
-
-	if (found_alg)
-		return found_alg->ops;
-	else
-		return NULL;
-}
-
-
-static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
-static void ieee80211_crypt_null_deinit(void *priv) {}
-
-static struct ieee80211_crypto_ops ieee80211_crypt_null = {
-	.name			= "NULL",
-	.init			= ieee80211_crypt_null_init,
-	.deinit			= ieee80211_crypt_null_deinit,
-	.encrypt_mpdu		= NULL,
-	.decrypt_mpdu		= NULL,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= NULL,
-	.get_key		= NULL,
-	.extra_prefix_len	= 0,
-	.extra_postfix_len	= 0,
-	.owner			= THIS_MODULE,
-};
-
-
-int ieee80211_crypto_init(void)
-{
-	int ret = -ENOMEM;
-
-	hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
-	if (!hcrypt)
-		goto out;
-
-	INIT_LIST_HEAD(&hcrypt->algs);
-	spin_lock_init(&hcrypt->lock);
-
-	ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
-	if (ret < 0) {
-		kfree(hcrypt);
-		hcrypt = NULL;
-	}
-out:
-	return ret;
-}
-
-
-void ieee80211_crypto_deinit(void)
-{
-	struct list_head *ptr, *n;
-	struct ieee80211_crypto_alg *alg = NULL;
-
-	if (hcrypt == NULL)
-		return;
-
-	list_for_each_safe(ptr, n, &hcrypt->algs) {
-		alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
-		if (alg) {
-			list_del(ptr);
-			pr_debug("unregistered algorithm '%s' (deinit)\n",
-				 alg->ops->name);
-			kfree(alg);
-		}
-	}
-	kfree(hcrypt);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
deleted file mode 100644
index 0b4ea431982d..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Original code based on Host AP (software wireless LAN access point) driver
- * for Intersil Prism2/2.5/3.
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * Adaption to a generic IEEE 802.11 stack by James Ketrenos
- * <jketreno@linux.intel.com>
- *
- * Copyright (c) 2004, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-/*
- * This file defines the interface to the ieee80211 crypto module.
- */
-#ifndef IEEE80211_CRYPT_H
-#define IEEE80211_CRYPT_H
-
-#include <linux/skbuff.h>
-
-struct ieee80211_crypto_ops {
-	const char *name;
-
-	/* init new crypto context (e.g., allocate private data space,
-	 * select IV, etc.); returns NULL on failure or pointer to allocated
-	 * private data on success */
-	void * (*init)(int keyidx);
-
-	/* deinitialize crypto context and free allocated private data */
-	void (*deinit)(void *priv);
-
-	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
-	 * value from decrypt_mpdu is passed as the keyidx value for
-	 * decrypt_msdu. skb must have enough head and tail room for the
-	 * encryption; if not, error will be returned; these functions are
-	 * called for all MPDUs (i.e., fragments).
-	 */
-	int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-
-	/* These functions are called for full MSDUs, i.e. full frames.
-	 * These can be NULL if full MSDU operations are not needed. */
-	int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
-			    void *priv);
-
-	int (*set_key)(void *key, int len, u8 *seq, void *priv);
-	int (*get_key)(void *key, int len, u8 *seq, void *priv);
-
-	/* procfs handler for printing out key information and possible
-	 * statistics */
-	char * (*print_stats)(char *p, void *priv);
-
-	/* maximum number of bytes added by encryption; encrypt buf is
-	 * allocated with extra_prefix_len bytes, copy of in_buf, and
-	 * extra_postfix_len; encrypt need not use all this space, but
-	 * the result must start at the beginning of the buffer and correct
-	 * length must be returned */
-	int extra_prefix_len, extra_postfix_len;
-
-	struct module *owner;
-};
-
-struct ieee80211_crypt_data {
-	struct list_head list; /* delayed deletion list */
-	struct ieee80211_crypto_ops *ops;
-	void *priv;
-	atomic_t refcnt;
-};
-
-int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
-int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
-struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
-void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
-void ieee80211_crypt_deinit_handler(unsigned long);
-void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
-				    struct ieee80211_crypt_data **crypt);
-
-#endif
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
deleted file mode 100644
index 4fe253818630..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
- *
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/if_ether.h>
-#include <linux/if_arp.h>
-#include <linux/string.h>
-#include <linux/wireless.h>
-
-#include "ieee80211.h"
-
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("Host AP crypt: CCMP");
-MODULE_LICENSE("GPL");
-
-
-#define AES_BLOCK_LEN 16
-#define CCMP_HDR_LEN 8
-#define CCMP_MIC_LEN 8
-#define CCMP_TK_LEN 16
-#define CCMP_PN_LEN 6
-
-struct ieee80211_ccmp_data {
-	u8 key[CCMP_TK_LEN];
-	int key_set;
-
-	u8 tx_pn[CCMP_PN_LEN];
-	u8 rx_pn[CCMP_PN_LEN];
-
-	u32 dot11RSNAStatsCCMPFormatErrors;
-	u32 dot11RSNAStatsCCMPReplays;
-	u32 dot11RSNAStatsCCMPDecryptErrors;
-
-	int key_idx;
-
-	struct crypto_tfm *tfm;
-
-	/* scratch buffers for virt_to_page() (crypto API) */
-	u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
-		tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
-	u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
-};
-
-static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
-				const u8 pt[16], u8 ct[16])
-{
-	crypto_cipher_encrypt_one((void *)tfm, ct, pt);
-}
-
-static void *ieee80211_ccmp_init(int key_idx)
-{
-	struct ieee80211_ccmp_data *priv;
-
-	priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
-	if (priv == NULL)
-		goto fail;
-	priv->key_idx = key_idx;
-
-	priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->tfm)) {
-		pr_debug("could not allocate crypto API aes\n");
-		priv->tfm = NULL;
-		goto fail;
-	}
-
-	return priv;
-
-fail:
-	if (priv) {
-		if (priv->tfm)
-			crypto_free_cipher((void *)priv->tfm);
-		kfree(priv);
-	}
-
-	return NULL;
-}
-
-
-static void ieee80211_ccmp_deinit(void *priv)
-{
-	struct ieee80211_ccmp_data *_priv = priv;
-
-	if (_priv && _priv->tfm)
-		crypto_free_cipher((void *)_priv->tfm);
-	kfree(priv);
-}
-
-
-static inline void xor_block(u8 *b, u8 *a, size_t len)
-{
-	int i;
-	for (i = 0; i < len; i++)
-		b[i] ^= a[i];
-}
-
-static void ccmp_init_blocks(struct crypto_tfm *tfm,
-			     struct ieee80211_hdr_4addr *hdr,
-			     u8 *pn, size_t dlen, u8 *b0, u8 *auth,
-			     u8 *s0)
-{
-	u8 *pos, qc = 0;
-	size_t aad_len;
-	u16 fc;
-	int a4_included, qc_included;
-	u8 aad[2 * AES_BLOCK_LEN];
-
-	fc = le16_to_cpu(hdr->frame_ctl);
-	a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
-		       (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
-	/*
-	qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
-		       (WLAN_FC_GET_STYPE(fc) & 0x08));
-	*/
-	qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
-		       (WLAN_FC_GET_STYPE(fc) & 0x80));
-	aad_len = 22;
-	if (a4_included)
-		aad_len += 6;
-	if (qc_included) {
-		pos = (u8 *) &hdr->addr4;
-		if (a4_included)
-			pos += 6;
-		qc = *pos & 0x0f;
-		aad_len += 2;
-	}
-	/* CCM Initial Block:
-	 * Flag (Include authentication header, M=3 (8-octet MIC),
-	 *       L=1 (2-octet Dlen))
-	 * Nonce: 0x00 | A2 | PN
-	 * Dlen */
-	b0[0] = 0x59;
-	b0[1] = qc;
-	memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
-	memcpy(b0 + 8, pn, CCMP_PN_LEN);
-	b0[14] = (dlen >> 8) & 0xff;
-	b0[15] = dlen & 0xff;
-
-	/* AAD:
-	 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
-	 * A1 | A2 | A3
-	 * SC with bits 4..15 (seq#) masked to zero
-	 * A4 (if present)
-	 * QC (if present)
-	 */
-	pos = (u8 *) hdr;
-	aad[0] = 0; /* aad_len >> 8 */
-	aad[1] = aad_len & 0xff;
-	aad[2] = pos[0] & 0x8f;
-	aad[3] = pos[1] & 0xc7;
-	memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
-	pos = (u8 *) &hdr->seq_ctl;
-	aad[22] = pos[0] & 0x0f;
-	aad[23] = 0; /* all bits masked */
-	memset(aad + 24, 0, 8);
-	if (a4_included)
-		memcpy(aad + 24, hdr->addr4, ETH_ALEN);
-	if (qc_included) {
-		aad[a4_included ? 30 : 24] = qc;
-		/* rest of QC masked */
-	}
-
-	/* Start with the first block and AAD */
-	ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
-	xor_block(auth, aad, AES_BLOCK_LEN);
-	ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
-	xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
-	ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
-	b0[0] &= 0x07;
-	b0[14] = b0[15] = 0;
-	ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
-}
-
-static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
-	struct ieee80211_ccmp_data *key = priv;
-	int data_len, i;
-	u8 *pos;
-	struct ieee80211_hdr_4addr *hdr;
-	int blocks, last, len;
-	u8 *mic;
-	u8 *b0 = key->tx_b0;
-	u8 *b = key->tx_b;
-	u8 *e = key->tx_e;
-	u8 *s0 = key->tx_s0;
-
-	if (skb_headroom(skb) < CCMP_HDR_LEN ||
-	    skb_tailroom(skb) < CCMP_MIC_LEN ||
-	    skb->len < hdr_len)
-		return -1;
-
-	data_len = skb->len - hdr_len;
-	pos = skb_push(skb, CCMP_HDR_LEN);
-	memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
-	pos += hdr_len;
-
-	i = CCMP_PN_LEN - 1;
-	while (i >= 0) {
-		key->tx_pn[i]++;
-		if (key->tx_pn[i] != 0)
-			break;
-		i--;
-	}
-
-	*pos++ = key->tx_pn[5];
-	*pos++ = key->tx_pn[4];
-	*pos++ = 0;
-	*pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
-	*pos++ = key->tx_pn[3];
-	*pos++ = key->tx_pn[2];
-	*pos++ = key->tx_pn[1];
-	*pos++ = key->tx_pn[0];
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	mic = skb_put(skb, CCMP_MIC_LEN);
-
-	ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
-
-	blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
-	last = data_len % AES_BLOCK_LEN;
-
-	for (i = 1; i <= blocks; i++) {
-		len = (i == blocks && last) ? last : AES_BLOCK_LEN;
-		/* Authentication */
-		xor_block(b, pos, len);
-		ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
-		/* Encryption, with counter */
-		b0[14] = (i >> 8) & 0xff;
-		b0[15] = i & 0xff;
-		ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
-		xor_block(pos, e, len);
-		pos += len;
-	}
-
-	for (i = 0; i < CCMP_MIC_LEN; i++)
-		mic[i] = b[i] ^ s0[i];
-
-	return 0;
-}
-
-
-static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
-	struct ieee80211_ccmp_data *key = priv;
-	u8 keyidx, *pos;
-	struct ieee80211_hdr_4addr *hdr;
-	u8 pn[6];
-	size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
-	u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
-	u8 *b0 = key->rx_b0;
-	u8 *b = key->rx_b;
-	u8 *a = key->rx_a;
-	int i, blocks, last, len;
-
-	if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
-		key->dot11RSNAStatsCCMPFormatErrors++;
-		return -1;
-	}
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	pos = skb->data + hdr_len;
-	keyidx = pos[3];
-	if (!(keyidx & (1 << 5))) {
-		if (net_ratelimit()) {
-			pr_debug("received packet without ExtIV flag from %pM\n",
-				 hdr->addr2);
-		}
-		key->dot11RSNAStatsCCMPFormatErrors++;
-		return -2;
-	}
-	keyidx >>= 6;
-	if (key->key_idx != keyidx) {
-		pr_debug("RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
-			 key->key_idx, keyidx, priv);
-		return -6;
-	}
-	if (!key->key_set) {
-		if (net_ratelimit()) {
-			pr_debug("received packet from %pM with keyid=%d that does not have a configured key\n",
-				 hdr->addr2, keyidx);
-		}
-		return -3;
-	}
-
-	pn[0] = pos[7];
-	pn[1] = pos[6];
-	pn[2] = pos[5];
-	pn[3] = pos[4];
-	pn[4] = pos[1];
-	pn[5] = pos[0];
-	pos += 8;
-
-	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
-		if (net_ratelimit()) {
-			pr_debug("replay detected: STA=%pM previous PN %pm received PN %pm\n",
-				 hdr->addr2, key->rx_pn, pn);
-		}
-		key->dot11RSNAStatsCCMPReplays++;
-		return -4;
-	}
-
-	ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
-	xor_block(mic, b, CCMP_MIC_LEN);
-
-	blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
-	last = data_len % AES_BLOCK_LEN;
-
-	for (i = 1; i <= blocks; i++) {
-		len = (i == blocks && last) ? last : AES_BLOCK_LEN;
-		/* Decrypt, with counter */
-		b0[14] = (i >> 8) & 0xff;
-		b0[15] = i & 0xff;
-		ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
-		xor_block(pos, b, len);
-		/* Authentication */
-		xor_block(a, pos, len);
-		ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
-		pos += len;
-	}
-
-	if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
-		if (net_ratelimit())
-			pr_debug("decrypt failed: STA=%pM\n", hdr->addr2);
-
-		key->dot11RSNAStatsCCMPDecryptErrors++;
-		return -5;
-	}
-
-	memcpy(key->rx_pn, pn, CCMP_PN_LEN);
-
-	/* Remove hdr and MIC */
-	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
-	skb_pull(skb, CCMP_HDR_LEN);
-	skb_trim(skb, skb->len - CCMP_MIC_LEN);
-
-	return keyidx;
-}
-
-
-static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
-{
-	struct ieee80211_ccmp_data *data = priv;
-	int keyidx;
-	struct crypto_tfm *tfm = data->tfm;
-
-	keyidx = data->key_idx;
-	memset(data, 0, sizeof(*data));
-	data->key_idx = keyidx;
-	data->tfm = tfm;
-	if (len == CCMP_TK_LEN) {
-		memcpy(data->key, key, CCMP_TK_LEN);
-		data->key_set = 1;
-		if (seq) {
-			data->rx_pn[0] = seq[5];
-			data->rx_pn[1] = seq[4];
-			data->rx_pn[2] = seq[3];
-			data->rx_pn[3] = seq[2];
-			data->rx_pn[4] = seq[1];
-			data->rx_pn[5] = seq[0];
-		}
-		crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN);
-	} else if (len == 0)
-		data->key_set = 0;
-	else
-		return -1;
-
-	return 0;
-}
-
-
-static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
-{
-	struct ieee80211_ccmp_data *data = priv;
-
-	if (len < CCMP_TK_LEN)
-		return -1;
-
-	if (!data->key_set)
-		return 0;
-	memcpy(key, data->key, CCMP_TK_LEN);
-
-	if (seq) {
-		seq[0] = data->tx_pn[5];
-		seq[1] = data->tx_pn[4];
-		seq[2] = data->tx_pn[3];
-		seq[3] = data->tx_pn[2];
-		seq[4] = data->tx_pn[1];
-		seq[5] = data->tx_pn[0];
-	}
-
-	return CCMP_TK_LEN;
-}
-
-
-static char *ieee80211_ccmp_print_stats(char *p, void *priv)
-{
-	struct ieee80211_ccmp_data *ccmp = priv;
-	p += sprintf(p,
-		     "key[%d] alg=CCMP key_set=%d tx_pn=%pm rx_pn=%pm format_errors=%d replays=%d decrypt_errors=%d\n",
-		     ccmp->key_idx, ccmp->key_set,
-		     ccmp->tx_pn, ccmp->rx_pn,
-		     ccmp->dot11RSNAStatsCCMPFormatErrors,
-		     ccmp->dot11RSNAStatsCCMPReplays,
-		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
-
-	return p;
-}
-
-void ieee80211_ccmp_null(void)
-{
-	return;
-}
-static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
-	.name			= "CCMP",
-	.init			= ieee80211_ccmp_init,
-	.deinit			= ieee80211_ccmp_deinit,
-	.encrypt_mpdu		= ieee80211_ccmp_encrypt,
-	.decrypt_mpdu		= ieee80211_ccmp_decrypt,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= ieee80211_ccmp_set_key,
-	.get_key		= ieee80211_ccmp_get_key,
-	.print_stats		= ieee80211_ccmp_print_stats,
-	.extra_prefix_len	= CCMP_HDR_LEN,
-	.extra_postfix_len	= CCMP_MIC_LEN,
-	.owner			= THIS_MODULE,
-};
-
-
-int ieee80211_crypto_ccmp_init(void)
-{
-	return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
-}
-
-
-void ieee80211_crypto_ccmp_exit(void)
-{
-	ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
deleted file mode 100644
index 6c1acc5dfba7..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
- *
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/if_ether.h>
-#include <linux/if_arp.h>
-#include <asm/string.h>
-
-#include "ieee80211.h"
-
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
-#include <linux/crc32.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("Host AP crypt: TKIP");
-MODULE_LICENSE("GPL");
-
-
-struct ieee80211_tkip_data {
-#define TKIP_KEY_LEN 32
-	u8 key[TKIP_KEY_LEN];
-	int key_set;
-
-	u32 tx_iv32;
-	u16 tx_iv16;
-	u16 tx_ttak[5];
-	int tx_phase1_done;
-
-	u32 rx_iv32;
-	u16 rx_iv16;
-	u16 rx_ttak[5];
-	int rx_phase1_done;
-	u32 rx_iv32_new;
-	u16 rx_iv16_new;
-
-	u32 dot11RSNAStatsTKIPReplays;
-	u32 dot11RSNAStatsTKIPICVErrors;
-	u32 dot11RSNAStatsTKIPLocalMICFailures;
-
-	int key_idx;
-
-	struct crypto_blkcipher *rx_tfm_arc4;
-	struct crypto_hash *rx_tfm_michael;
-	struct crypto_blkcipher *tx_tfm_arc4;
-	struct crypto_hash *tx_tfm_michael;
-	struct crypto_tfm *tfm_arc4;
-	struct crypto_tfm *tfm_michael;
-
-	/* scratch buffers for virt_to_page() (crypto API) */
-	u8 rx_hdr[16], tx_hdr[16];
-};
-
-static void *ieee80211_tkip_init(int key_idx)
-{
-	struct ieee80211_tkip_data *priv;
-
-	priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
-	if (priv == NULL)
-		goto fail;
-	priv->key_idx = key_idx;
-
-	priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
-						CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->tx_tfm_arc4)) {
-		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
-		       "crypto API arc4\n");
-		priv->tx_tfm_arc4 = NULL;
-		goto fail;
-	}
-
-	priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
-						 CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->tx_tfm_michael)) {
-		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
-		       "crypto API michael_mic\n");
-		priv->tx_tfm_michael = NULL;
-		goto fail;
-	}
-
-	priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
-						CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->rx_tfm_arc4)) {
-		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
-		       "crypto API arc4\n");
-		priv->rx_tfm_arc4 = NULL;
-		goto fail;
-	}
-
-	priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
-						 CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->rx_tfm_michael)) {
-		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
-		       "crypto API michael_mic\n");
-		priv->rx_tfm_michael = NULL;
-		goto fail;
-	}
-
-	return priv;
-
-fail:
-	if (priv) {
-		if (priv->tx_tfm_michael)
-			crypto_free_hash(priv->tx_tfm_michael);
-		if (priv->tx_tfm_arc4)
-			crypto_free_blkcipher(priv->tx_tfm_arc4);
-		if (priv->rx_tfm_michael)
-			crypto_free_hash(priv->rx_tfm_michael);
-		if (priv->rx_tfm_arc4)
-			crypto_free_blkcipher(priv->rx_tfm_arc4);
-		kfree(priv);
-	}
-
-	return NULL;
-}
-
-
-static void ieee80211_tkip_deinit(void *priv)
-{
-	struct ieee80211_tkip_data *_priv = priv;
-
-	if (_priv) {
-		if (_priv->tx_tfm_michael)
-			crypto_free_hash(_priv->tx_tfm_michael);
-		if (_priv->tx_tfm_arc4)
-			crypto_free_blkcipher(_priv->tx_tfm_arc4);
-		if (_priv->rx_tfm_michael)
-			crypto_free_hash(_priv->rx_tfm_michael);
-		if (_priv->rx_tfm_arc4)
-			crypto_free_blkcipher(_priv->rx_tfm_arc4);
-	}
-	kfree(priv);
-}
-
-
-static inline u16 RotR1(u16 val)
-{
-	return (val >> 1) | (val << 15);
-}
-
-
-static inline u8 Lo8(u16 val)
-{
-	return val & 0xff;
-}
-
-
-static inline u8 Hi8(u16 val)
-{
-	return val >> 8;
-}
-
-
-static inline u16 Lo16(u32 val)
-{
-	return val & 0xffff;
-}
-
-
-static inline u16 Hi16(u32 val)
-{
-	return val >> 16;
-}
-
-
-static inline u16 Mk16(u8 hi, u8 lo)
-{
-	return lo | (((u16) hi) << 8);
-}
-
-
-static inline u16 Mk16_le(u16 *v)
-{
-	return le16_to_cpu(*v);
-}
-
-
-static const u16 Sbox[256] = {
-	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
-	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
-	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
-	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
-	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
-	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
-	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
-	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
-	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
-	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
-	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
-	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
-	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
-	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
-	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
-	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
-	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
-	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
-	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
-	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
-	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
-	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
-	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
-	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
-	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
-	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
-	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
-	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
-	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
-	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
-	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
-	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
-};
-
-
-static inline u16 _S_(u16 v)
-{
-	u16 t = Sbox[Hi8(v)];
-	return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
-}
-
-#define PHASE1_LOOP_COUNT 8
-
-static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
-{
-	int i, j;
-
-	/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
-	TTAK[0] = Lo16(IV32);
-	TTAK[1] = Hi16(IV32);
-	TTAK[2] = Mk16(TA[1], TA[0]);
-	TTAK[3] = Mk16(TA[3], TA[2]);
-	TTAK[4] = Mk16(TA[5], TA[4]);
-
-	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
-		j = 2 * (i & 1);
-		TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
-		TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
-		TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
-		TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
-		TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
-	}
-}
-
-
-static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
-			       u16 IV16)
-{
-	/* Make temporary area overlap WEP seed so that the final copy can be
-	 * avoided on little endian hosts. */
-	u16 *PPK = (u16 *) &WEPSeed[4];
-
-	/* Step 1 - make copy of TTAK and bring in TSC */
-	PPK[0] = TTAK[0];
-	PPK[1] = TTAK[1];
-	PPK[2] = TTAK[2];
-	PPK[3] = TTAK[3];
-	PPK[4] = TTAK[4];
-	PPK[5] = TTAK[4] + IV16;
-
-	/* Step 2 - 96-bit bijective mixing using S-box */
-	PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
-	PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
-	PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
-	PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
-	PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
-	PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
-
-	PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
-	PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
-	PPK[2] += RotR1(PPK[1]);
-	PPK[3] += RotR1(PPK[2]);
-	PPK[4] += RotR1(PPK[3]);
-	PPK[5] += RotR1(PPK[4]);
-
-	/* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
-	 * WEPSeed[0..2] is transmitted as WEP IV */
-	WEPSeed[0] = Hi8(IV16);
-	WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
-	WEPSeed[2] = Lo8(IV16);
-	WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
-
-#ifdef __BIG_ENDIAN
-	{
-		int i;
-		for (i = 0; i < 6; i++)
-			PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
-	}
-#endif
-}
-
-static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
-	struct ieee80211_tkip_data *tkey = priv;
-	struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
-	int len;
-	u8  *pos;
-	struct ieee80211_hdr_4addr *hdr;
-	u8 rc4key[16], *icv;
-	u32 crc;
-	struct scatterlist sg;
-	int ret;
-
-	ret = 0;
-	if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
-	    skb->len < hdr_len)
-		return -1;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
-	if (!tkey->tx_phase1_done) {
-		tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
-				   tkey->tx_iv32);
-		tkey->tx_phase1_done = 1;
-	}
-	tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
-
-	len = skb->len - hdr_len;
-	pos = skb_push(skb, 8);
-	memmove(pos, pos + 8, hdr_len);
-	pos += hdr_len;
-
-	*pos++ = rc4key[0];
-	*pos++ = rc4key[1];
-	*pos++ = rc4key[2];
-	*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
-	*pos++ = tkey->tx_iv32 & 0xff;
-	*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
-	*pos++ = (tkey->tx_iv32 >> 16) & 0xff;
-	*pos++ = (tkey->tx_iv32 >> 24) & 0xff;
-
-	icv = skb_put(skb, 4);
-	crc = ~crc32_le(~0, pos, len);
-	icv[0] = crc;
-	icv[1] = crc >> 8;
-	icv[2] = crc >> 16;
-	icv[3] = crc >> 24;
-	crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
-	sg_init_one(&sg, pos, len + 4);
-	ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
-
-	tkey->tx_iv16++;
-	if (tkey->tx_iv16 == 0) {
-		tkey->tx_phase1_done = 0;
-		tkey->tx_iv32++;
-	}
-	   return ret;
-}
-
-static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
-	struct ieee80211_tkip_data *tkey = priv;
-	struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
-	u8 keyidx, *pos;
-	u32 iv32;
-	u16 iv16;
-	struct ieee80211_hdr_4addr *hdr;
-	u8 icv[4];
-	u32 crc;
-	struct scatterlist sg;
-	u8 rc4key[16];
-	int plen;
-
-	if (skb->len < hdr_len + 8 + 4)
-		return -1;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	pos = skb->data + hdr_len;
-	keyidx = pos[3];
-	if (!(keyidx & (1 << 5))) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: received packet without ExtIV"
-			       " flag from %pM\n", hdr->addr2);
-		}
-		return -2;
-	}
-	keyidx >>= 6;
-	if (tkey->key_idx != keyidx) {
-		printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
-		       "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
-		return -6;
-	}
-	if (!tkey->key_set) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: received packet from %pM"
-			       " with keyid=%d that does not have a configured"
-			       " key\n", hdr->addr2, keyidx);
-		}
-		return -3;
-	}
-	iv16 = (pos[0] << 8) | pos[2];
-	iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
-	pos += 8;
-
-	if (iv32 < tkey->rx_iv32 ||
-	    (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
-			       " previous TSC %08x%04x received TSC "
-			       "%08x%04x\n", hdr->addr2,
-			       tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
-		}
-		tkey->dot11RSNAStatsTKIPReplays++;
-		return -4;
-	}
-
-	if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
-		tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
-		tkey->rx_phase1_done = 1;
-	}
-	tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
-
-	plen = skb->len - hdr_len - 12;
-	crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
-	sg_init_one(&sg, pos, plen + 4);
-	if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG ": TKIP: failed to decrypt "
-			       "received packet from %pM\n",
-			       hdr->addr2);
-		}
-		return -7;
-	}
-
-	crc = ~crc32_le(~0, pos, plen);
-	icv[0] = crc;
-	icv[1] = crc >> 8;
-	icv[2] = crc >> 16;
-	icv[3] = crc >> 24;
-	if (memcmp(icv, pos + plen, 4) != 0) {
-		if (iv32 != tkey->rx_iv32) {
-			/* Previously cached Phase1 result was already lost, so
-			 * it needs to be recalculated for the next packet. */
-			tkey->rx_phase1_done = 0;
-		}
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: ICV error detected: STA="
-			       "%pM\n", hdr->addr2);
-		}
-		tkey->dot11RSNAStatsTKIPICVErrors++;
-		return -5;
-	}
-
-	/* Update real counters only after Michael MIC verification has
-	 * completed */
-	tkey->rx_iv32_new = iv32;
-	tkey->rx_iv16_new = iv16;
-
-	/* Remove IV and ICV */
-	memmove(skb->data + 8, skb->data, hdr_len);
-	skb_pull(skb, 8);
-	skb_trim(skb, skb->len - 4);
-
-	return keyidx;
-}
-
-static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr,
-			u8 *data, size_t data_len, u8 *mic)
-{
-	struct hash_desc desc;
-	struct scatterlist sg[2];
-
-	if (tfm_michael == NULL) {
-		printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
-		return -1;
-	}
-
-	sg_init_table(sg, 2);
-	sg_set_buf(&sg[0], hdr, 16);
-	sg_set_buf(&sg[1], data, data_len);
-
-	if (crypto_hash_setkey(tfm_michael, key, 8))
-		return -1;
-
-	desc.tfm = tfm_michael;
-	desc.flags = 0;
-	return crypto_hash_digest(&desc, sg, data_len + 16, mic);
-}
-
-static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
-{
-	struct ieee80211_hdr_4addr *hdr11;
-
-	hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
-	switch (le16_to_cpu(hdr11->frame_ctl) &
-		(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
-	case IEEE80211_FCTL_TODS:
-		memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
-		memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
-		break;
-	case IEEE80211_FCTL_FROMDS:
-		memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
-		memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
-		break;
-	case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
-		memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
-		memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
-		break;
-	case 0:
-		memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
-		memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
-		break;
-	}
-
-	hdr[12] = 0; /* priority */
-
-	hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
-}
-
-
-static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
-				     void *priv)
-{
-	struct ieee80211_tkip_data *tkey = priv;
-	u8 *pos;
-	struct ieee80211_hdr_4addr *hdr;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
-	if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
-		printk(KERN_DEBUG "Invalid packet for Michael MIC add "
-		       "(tailroom=%d hdr_len=%d skb->len=%d)\n",
-		       skb_tailroom(skb), hdr_len, skb->len);
-		return -1;
-	}
-
-	michael_mic_hdr(skb, tkey->tx_hdr);
-
-	if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
-		tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
-
-	pos = skb_put(skb, 8);
-
-	if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
-			skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
-		return -1;
-
-	return 0;
-}
-
-static void ieee80211_michael_mic_failure(struct net_device *dev,
-					  struct ieee80211_hdr_4addr *hdr,
-					  int keyidx)
-{
-	union iwreq_data wrqu;
-	struct iw_michaelmicfailure ev;
-
-	/* TODO: needed parameters: count, keyid, key type, TSC */
-	memset(&ev, 0, sizeof(ev));
-	ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
-	if (hdr->addr1[0] & 0x01)
-		ev.flags |= IW_MICFAILURE_GROUP;
-	else
-		ev.flags |= IW_MICFAILURE_PAIRWISE;
-	ev.src_addr.sa_family = ARPHRD_ETHER;
-	memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
-	memset(&wrqu, 0, sizeof(wrqu));
-	wrqu.data.length = sizeof(ev);
-	wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
-}
-
-static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
-					int hdr_len, void *priv)
-{
-	struct ieee80211_tkip_data *tkey = priv;
-	u8 mic[8];
-	struct ieee80211_hdr_4addr *hdr;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
-	if (!tkey->key_set)
-		return -1;
-
-	michael_mic_hdr(skb, tkey->rx_hdr);
-	if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
-		tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
-
-	if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
-			skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
-		return -1;
-
-	if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
-		struct ieee80211_hdr_4addr *hdr;
-		hdr = (struct ieee80211_hdr_4addr *)skb->data;
-		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
-		       "MSDU from %pM keyidx=%d\n",
-		       skb->dev ? skb->dev->name : "N/A", hdr->addr2,
-		       keyidx);
-		if (skb->dev)
-			ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
-		tkey->dot11RSNAStatsTKIPLocalMICFailures++;
-		return -1;
-	}
-
-	/* Update TSC counters for RX now that the packet verification has
-	 * completed. */
-	tkey->rx_iv32 = tkey->rx_iv32_new;
-	tkey->rx_iv16 = tkey->rx_iv16_new;
-
-	skb_trim(skb, skb->len - 8);
-
-	return 0;
-}
-
-
-static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
-{
-	struct ieee80211_tkip_data *tkey = priv;
-	int keyidx;
-	struct crypto_hash *tfm = tkey->tx_tfm_michael;
-	struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
-	struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
-	struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
-
-	keyidx = tkey->key_idx;
-	memset(tkey, 0, sizeof(*tkey));
-	tkey->key_idx = keyidx;
-
-	tkey->tx_tfm_michael = tfm;
-	tkey->tx_tfm_arc4 = tfm2;
-	tkey->rx_tfm_michael = tfm3;
-	tkey->rx_tfm_arc4 = tfm4;
-
-	if (len == TKIP_KEY_LEN) {
-		memcpy(tkey->key, key, TKIP_KEY_LEN);
-		tkey->key_set = 1;
-		tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
-		if (seq) {
-			tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
-				(seq[3] << 8) | seq[2];
-			tkey->rx_iv16 = (seq[1] << 8) | seq[0];
-		}
-	} else if (len == 0)
-		tkey->key_set = 0;
-	else
-		return -1;
-
-	return 0;
-}
-
-
-static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
-{
-	struct ieee80211_tkip_data *tkey = priv;
-
-	if (len < TKIP_KEY_LEN)
-		return -1;
-
-	if (!tkey->key_set)
-		return 0;
-	memcpy(key, tkey->key, TKIP_KEY_LEN);
-
-	if (seq) {
-		/* Return the sequence number of the last transmitted frame. */
-		u16 iv16 = tkey->tx_iv16;
-		u32 iv32 = tkey->tx_iv32;
-		if (iv16 == 0)
-			iv32--;
-		iv16--;
-		seq[0] = tkey->tx_iv16;
-		seq[1] = tkey->tx_iv16 >> 8;
-		seq[2] = tkey->tx_iv32;
-		seq[3] = tkey->tx_iv32 >> 8;
-		seq[4] = tkey->tx_iv32 >> 16;
-		seq[5] = tkey->tx_iv32 >> 24;
-	}
-
-	return TKIP_KEY_LEN;
-}
-
-
-static char *ieee80211_tkip_print_stats(char *p, void *priv)
-{
-	struct ieee80211_tkip_data *tkip = priv;
-	p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
-		     "replays=%d icv_errors=%d local_mic_failures=%d\n",
-		     tkip->key_idx, tkip->key_set,
-		     (tkip->tx_iv32 >> 24) & 0xff,
-		     (tkip->tx_iv32 >> 16) & 0xff,
-		     (tkip->tx_iv32 >> 8) & 0xff,
-		     tkip->tx_iv32 & 0xff,
-		     (tkip->tx_iv16 >> 8) & 0xff,
-		     tkip->tx_iv16 & 0xff,
-		     (tkip->rx_iv32 >> 24) & 0xff,
-		     (tkip->rx_iv32 >> 16) & 0xff,
-		     (tkip->rx_iv32 >> 8) & 0xff,
-		     tkip->rx_iv32 & 0xff,
-		     (tkip->rx_iv16 >> 8) & 0xff,
-		     tkip->rx_iv16 & 0xff,
-		     tkip->dot11RSNAStatsTKIPReplays,
-		     tkip->dot11RSNAStatsTKIPICVErrors,
-		     tkip->dot11RSNAStatsTKIPLocalMICFailures);
-	return p;
-}
-
-
-static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
-	.name			= "TKIP",
-	.init			= ieee80211_tkip_init,
-	.deinit			= ieee80211_tkip_deinit,
-	.encrypt_mpdu		= ieee80211_tkip_encrypt,
-	.decrypt_mpdu		= ieee80211_tkip_decrypt,
-	.encrypt_msdu		= ieee80211_michael_mic_add,
-	.decrypt_msdu		= ieee80211_michael_mic_verify,
-	.set_key		= ieee80211_tkip_set_key,
-	.get_key		= ieee80211_tkip_get_key,
-	.print_stats		= ieee80211_tkip_print_stats,
-	.extra_prefix_len	= 4 + 4, /* IV + ExtIV */
-	.extra_postfix_len	= 8 + 4, /* MIC + ICV */
-	.owner		        = THIS_MODULE,
-};
-
-
-int ieee80211_crypto_tkip_init(void)
-{
-	return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
-}
-
-
-void ieee80211_crypto_tkip_exit(void)
-{
-	ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
-}
-
-
-void ieee80211_tkip_null(void)
-{
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
deleted file mode 100644
index f25367224941..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Host AP crypt: host-based WEP encryption implementation for Host AP driver
- *
- * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/skbuff.h>
-#include <linux/string.h>
-
-#include "ieee80211.h"
-
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
-#include <linux/crc32.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("Host AP crypt: WEP");
-MODULE_LICENSE("GPL");
-
-struct prism2_wep_data {
-	u32 iv;
-#define WEP_KEY_LEN 13
-	u8 key[WEP_KEY_LEN + 1];
-	u8 key_len;
-	u8 key_idx;
-	struct crypto_blkcipher *tx_tfm;
-	struct crypto_blkcipher *rx_tfm;
-};
-
-static void *prism2_wep_init(int keyidx)
-{
-	struct prism2_wep_data *priv;
-
-	priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
-	if (priv == NULL)
-		goto fail;
-	priv->key_idx = keyidx;
-	priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->tx_tfm)) {
-		pr_debug("could not allocate crypto API arc4\n");
-		priv->tx_tfm = NULL;
-		goto fail;
-	}
-	priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->rx_tfm)) {
-		pr_debug("could not allocate crypto API arc4\n");
-		priv->rx_tfm = NULL;
-		goto fail;
-	}
-
-	/* start WEP IV from a random value */
-	get_random_bytes(&priv->iv, 4);
-
-	return priv;
-
-fail:
-	if (priv) {
-		if (priv->tx_tfm)
-			crypto_free_blkcipher(priv->tx_tfm);
-		if (priv->rx_tfm)
-			crypto_free_blkcipher(priv->rx_tfm);
-		kfree(priv);
-	}
-
-	return NULL;
-}
-
-static void prism2_wep_deinit(void *priv)
-{
-	struct prism2_wep_data *_priv = priv;
-
-	if (_priv) {
-		if (_priv->tx_tfm)
-			crypto_free_blkcipher(_priv->tx_tfm);
-		if (_priv->rx_tfm)
-			crypto_free_blkcipher(_priv->rx_tfm);
-	}
-
-	kfree(priv);
-}
-
-/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
- * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
- * so the payload length increases with 8 bytes.
- *
- * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
- */
-static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
-	struct prism2_wep_data *wep = priv;
-	struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
-	u32 klen, len;
-	u8 key[WEP_KEY_LEN + 3];
-	u8 *pos;
-	u32 crc;
-	u8 *icv;
-	struct scatterlist sg;
-
-	if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
-	    skb->len < hdr_len)
-		return -1;
-
-	len = skb->len - hdr_len;
-	pos = skb_push(skb, 4);
-	memmove(pos, pos + 4, hdr_len);
-	pos += hdr_len;
-
-	klen = 3 + wep->key_len;
-
-	wep->iv++;
-
-	/* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
-	 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
-	 * can be used to speedup attacks, so avoid using them. */
-	if ((wep->iv & 0xff00) == 0xff00) {
-		u8 B = (wep->iv >> 16) & 0xff;
-		if (B >= 3 && B < klen)
-			wep->iv += 0x0100;
-	}
-
-	/* Prepend 24-bit IV to RC4 key and TX frame */
-	*pos++ = key[0] = (wep->iv >> 16) & 0xff;
-	*pos++ = key[1] = (wep->iv >> 8) & 0xff;
-	*pos++ = key[2] = wep->iv & 0xff;
-	*pos++ = wep->key_idx << 6;
-
-	/* Copy rest of the WEP key (the secret part) */
-	memcpy(key + 3, wep->key, wep->key_len);
-
-	/* Append little-endian CRC32 and encrypt it to produce ICV */
-	crc = ~crc32_le(~0, pos, len);
-	icv = skb_put(skb, 4);
-	icv[0] = crc;
-	icv[1] = crc >> 8;
-	icv[2] = crc >> 16;
-	icv[3] = crc >> 24;
-
-	crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
-	sg_init_one(&sg, pos, len + 4);
-
-	return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
-}
-
-/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
- * the frame: IV (4 bytes), encrypted payload (including SNAP header),
- * ICV (4 bytes). len includes both IV and ICV.
- *
- * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
- * failure. If frame is OK, IV and ICV will be removed.
- */
-static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
-	struct prism2_wep_data *wep = priv;
-	struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
-	u32 klen, plen;
-	u8 key[WEP_KEY_LEN + 3];
-	u8 keyidx, *pos;
-	u32 crc;
-	u8 icv[4];
-	struct scatterlist sg;
-
-	if (skb->len < hdr_len + 8)
-		return -1;
-
-	pos = skb->data + hdr_len;
-	key[0] = *pos++;
-	key[1] = *pos++;
-	key[2] = *pos++;
-	keyidx = *pos++ >> 6;
-	if (keyidx != wep->key_idx)
-		return -1;
-
-	klen = 3 + wep->key_len;
-
-	/* Copy rest of the WEP key (the secret part) */
-	memcpy(key + 3, wep->key, wep->key_len);
-
-	/* Apply RC4 to data and compute CRC32 over decrypted data */
-	plen = skb->len - hdr_len - 8;
-
-	crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
-	sg_init_one(&sg, pos, plen + 4);
-
-	if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
-		return -7;
-
-	crc = ~crc32_le(~0, pos, plen);
-	icv[0] = crc;
-	icv[1] = crc >> 8;
-	icv[2] = crc >> 16;
-	icv[3] = crc >> 24;
-
-	if (memcmp(icv, pos + plen, 4) != 0) {
-		/* ICV mismatch - drop frame */
-		return -2;
-	}
-
-	/* Remove IV and ICV */
-	memmove(skb->data + 4, skb->data, hdr_len);
-	skb_pull(skb, 4);
-	skb_trim(skb, skb->len - 4);
-	return 0;
-}
-
-static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
-{
-	struct prism2_wep_data *wep = priv;
-
-	if (len < 0 || len > WEP_KEY_LEN)
-		return -1;
-
-	memcpy(wep->key, key, len);
-	wep->key_len = len;
-
-	return 0;
-}
-
-static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
-{
-	struct prism2_wep_data *wep = priv;
-
-	if (len < wep->key_len)
-		return -1;
-
-	memcpy(key, wep->key, wep->key_len);
-
-	return wep->key_len;
-}
-
-static char *prism2_wep_print_stats(char *p, void *priv)
-{
-	struct prism2_wep_data *wep = priv;
-	p += sprintf(p, "key[%d] alg=WEP len=%d\n",
-		     wep->key_idx, wep->key_len);
-	return p;
-}
-
-static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
-	.name			= "WEP",
-	.init			= prism2_wep_init,
-	.deinit			= prism2_wep_deinit,
-	.encrypt_mpdu		= prism2_wep_encrypt,
-	.decrypt_mpdu		= prism2_wep_decrypt,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= prism2_wep_set_key,
-	.get_key		= prism2_wep_get_key,
-	.print_stats		= prism2_wep_print_stats,
-	.extra_prefix_len	= 4, /* IV */
-	.extra_postfix_len	= 4, /* ICV */
-	.owner			= THIS_MODULE,
-};
-
-int ieee80211_crypto_wep_init(void)
-{
-	return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
-}
-
-void ieee80211_crypto_wep_exit(void)
-{
-	ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
-}
-
-void ieee80211_wep_null(void)
-{
-	return;
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
deleted file mode 100644
index 07a1fbb6678e..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*******************************************************************************
-
-  Copyright(c) 2004 Intel Corporation. All rights reserved.
-
-  Portions of this file are based on the WEP enablement code provided by the
-  Host AP project hostap-drivers v0.1.3
-  Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
-  <jkmaline@cc.hut.fi>
-  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of version 2 of the GNU General Public License as
-  published by the Free Software Foundation.
-
-  This program is distributed in the hope that it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-
-  Contact Information:
-  James P. Ketrenos <ipw2100-admin@linux.intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include <linux/compiler.h>
-//#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in6.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/tcp.h>
-#include <linux/types.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-#include <linux/uaccess.h>
-#include <net/arp.h>
-#include <net/net_namespace.h>
-
-#include "ieee80211.h"
-
-MODULE_DESCRIPTION("802.11 data/management/control stack");
-MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
-MODULE_LICENSE("GPL");
-
-#define DRV_NAME "ieee80211"
-
-static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
-{
-	if (ieee->networks)
-		return 0;
-
-	ieee->networks = kcalloc(
-		MAX_NETWORK_COUNT, sizeof(struct ieee80211_network),
-		GFP_KERNEL);
-	if (!ieee->networks)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
-{
-	if (!ieee->networks)
-		return;
-	kfree(ieee->networks);
-	ieee->networks = NULL;
-}
-
-static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
-{
-	int i;
-
-	INIT_LIST_HEAD(&ieee->network_free_list);
-	INIT_LIST_HEAD(&ieee->network_list);
-	for (i = 0; i < MAX_NETWORK_COUNT; i++)
-		list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
-}
-
-
-struct net_device *alloc_ieee80211(int sizeof_priv)
-{
-	struct ieee80211_device *ieee;
-	struct net_device *dev;
-	int i, err;
-
-	IEEE80211_DEBUG_INFO("Initializing...\n");
-
-	dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
-	if (!dev) {
-		IEEE80211_ERROR("Unable to network device.\n");
-		goto failed;
-	}
-	ieee = netdev_priv(dev);
-
-	ieee->dev = dev;
-
-	err = ieee80211_networks_allocate(ieee);
-	if (err) {
-		IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
-				err);
-		goto failed;
-	}
-	ieee80211_networks_initialize(ieee);
-
-	/* Default fragmentation threshold is maximum payload size */
-	ieee->fts = DEFAULT_FTS;
-	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
-	ieee->open_wep = 1;
-
-	/* Default to enabling full open WEP with host based encrypt/decrypt */
-	ieee->host_encrypt = 1;
-	ieee->host_decrypt = 1;
-	ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
-
-	INIT_LIST_HEAD(&ieee->crypt_deinit_list);
-	init_timer(&ieee->crypt_deinit_timer);
-	ieee->crypt_deinit_timer.data = (unsigned long)ieee;
-	ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
-
-	spin_lock_init(&ieee->lock);
-	spin_lock_init(&ieee->wpax_suitlist_lock);
-
-	ieee->wpax_type_set = 0;
-	ieee->wpa_enabled = 0;
-	ieee->tkip_countermeasures = 0;
-	ieee->drop_unencrypted = 0;
-	ieee->privacy_invoked = 0;
-	ieee->ieee802_1x = 1;
-	ieee->raw_tx = 0;
-
-	ieee80211_softmac_init(ieee);
-
-	for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
-		INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
-
-	for (i = 0; i < 17; i++) {
-		ieee->last_rxseq_num[i] = -1;
-		ieee->last_rxfrag_num[i] = -1;
-		ieee->last_packet_time[i] = 0;
-	}
-//These function were added to load crypte module autoly
-	ieee80211_tkip_null();
-	ieee80211_wep_null();
-	ieee80211_ccmp_null();
-	return dev;
-
- failed:
-	if (dev)
-		free_netdev(dev);
-	return NULL;
-}
-
-
-void free_ieee80211(struct net_device *dev)
-{
-	struct ieee80211_device *ieee = netdev_priv(dev);
-
-	int i;
-	struct list_head *p, *q;
-
-
-	ieee80211_softmac_free(ieee);
-	del_timer_sync(&ieee->crypt_deinit_timer);
-	ieee80211_crypt_deinit_entries(ieee, 1);
-
-	for (i = 0; i < WEP_KEYS; i++) {
-		struct ieee80211_crypt_data *crypt = ieee->crypt[i];
-		if (crypt) {
-			if (crypt->ops)
-				crypt->ops->deinit(crypt->priv);
-			kfree(crypt);
-			ieee->crypt[i] = NULL;
-		}
-	}
-
-	ieee80211_networks_free(ieee);
-
-	for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) {
-		list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) {
-			kfree(list_entry(p, struct ieee_ibss_seq, list));
-			list_del(p);
-		}
-	}
-
-
-	free_netdev(dev);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
deleted file mode 100644
index b522b57a2691..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+++ /dev/null
@@ -1,1486 +0,0 @@
-/*
- * Original code based Host AP (software wireless LAN access point) driver
- * for Intersil Prism2/2.5/3 - hostap.o module, common routines
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- * Copyright (c) 2004, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- ******************************************************************************
-
-  Few modifications for Realtek's Wi-Fi drivers by
-  Andrea Merello <andrea.merello@gmail.com>
-
-  A special thanks goes to Realtek for their support !
-
-******************************************************************************/
-
-
-#include <linux/compiler.h>
-//#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in6.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/tcp.h>
-#include <linux/types.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-#include <linux/uaccess.h>
-#include <linux/ctype.h>
-
-#include "ieee80211.h"
-#include "dot11d.h"
-static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
-					struct sk_buff *skb,
-					struct ieee80211_rx_stats *rx_stats)
-{
-	struct ieee80211_hdr_4addr *hdr =
-		(struct ieee80211_hdr_4addr *)skb->data;
-	u16 fc = le16_to_cpu(hdr->frame_ctl);
-
-	skb->dev = ieee->dev;
-	skb_reset_mac_header(skb);
-	skb_pull(skb, ieee80211_get_hdrlen(fc));
-	skb->pkt_type = PACKET_OTHERHOST;
-	skb->protocol = __constant_htons(ETH_P_80211_RAW);
-	memset(skb->cb, 0, sizeof(skb->cb));
-	netif_rx(skb);
-}
-
-
-/* Called only as a tasklet (software IRQ) */
-static struct ieee80211_frag_entry *
-ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
-			  unsigned int frag, u8 tid, u8 *src, u8 *dst)
-{
-	struct ieee80211_frag_entry *entry;
-	int i;
-
-	for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
-		entry = &ieee->frag_cache[tid][i];
-		if (entry->skb != NULL &&
-		    time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
-			IEEE80211_DEBUG_FRAG(
-				"expiring fragment cache entry "
-				"seq=%u last_frag=%u\n",
-				entry->seq, entry->last_frag);
-			dev_kfree_skb_any(entry->skb);
-			entry->skb = NULL;
-		}
-
-		if (entry->skb != NULL && entry->seq == seq &&
-		    (entry->last_frag + 1 == frag || frag == -1) &&
-		    memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
-		    memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
-			return entry;
-	}
-
-	return NULL;
-}
-
-/* Called only as a tasklet (software IRQ) */
-static struct sk_buff *
-ieee80211_frag_cache_get(struct ieee80211_device *ieee,
-			 struct ieee80211_hdr_4addr *hdr)
-{
-	struct sk_buff *skb = NULL;
-	u16 fc = le16_to_cpu(hdr->frame_ctl);
-	u16 sc = le16_to_cpu(hdr->seq_ctl);
-	unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
-	unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
-	struct ieee80211_frag_entry *entry;
-	struct ieee80211_hdr_3addrqos *hdr_3addrqos;
-	struct ieee80211_hdr_4addrqos *hdr_4addrqos;
-	u8 tid;
-
-	if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
-		hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
-		tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
-		tid = UP2AC(tid);
-		tid++;
-	} else if (IEEE80211_QOS_HAS_SEQ(fc)) {
-		hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
-		tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
-		tid = UP2AC(tid);
-		tid++;
-	} else {
-		tid = 0;
-	}
-
-	if (frag == 0) {
-		/* Reserve enough space to fit maximum frame length */
-		skb = dev_alloc_skb(ieee->dev->mtu +
-				    sizeof(struct ieee80211_hdr_4addr) +
-				    8 /* LLC */ +
-				    2 /* alignment */ +
-				    8 /* WEP */ +
-				    ETH_ALEN /* WDS */ +
-				    (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */);
-		if (skb == NULL)
-			return NULL;
-
-		entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
-		ieee->frag_next_idx[tid]++;
-		if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
-			ieee->frag_next_idx[tid] = 0;
-
-		if (entry->skb != NULL)
-			dev_kfree_skb_any(entry->skb);
-
-		entry->first_frag_time = jiffies;
-		entry->seq = seq;
-		entry->last_frag = frag;
-		entry->skb = skb;
-		memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
-		memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
-	} else {
-		/* received a fragment of a frame for which the head fragment
-		 * should have already been received */
-		entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2,
-						  hdr->addr1);
-		if (entry != NULL) {
-			entry->last_frag = frag;
-			skb = entry->skb;
-		}
-	}
-
-	return skb;
-}
-
-
-/* Called only as a tasklet (software IRQ) */
-static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
-					   struct ieee80211_hdr_4addr *hdr)
-{
-	u16 fc = le16_to_cpu(hdr->frame_ctl);
-	u16 sc = le16_to_cpu(hdr->seq_ctl);
-	unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
-	struct ieee80211_frag_entry *entry;
-	struct ieee80211_hdr_3addrqos *hdr_3addrqos;
-	struct ieee80211_hdr_4addrqos *hdr_4addrqos;
-	u8 tid;
-
-	if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
-		hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
-		tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
-		tid = UP2AC(tid);
-		tid++;
-	} else if (IEEE80211_QOS_HAS_SEQ(fc)) {
-		hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
-		tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
-		tid = UP2AC(tid);
-		tid++;
-	} else {
-		tid = 0;
-	}
-
-	entry = ieee80211_frag_cache_find(ieee, seq, -1, tid, hdr->addr2,
-					  hdr->addr1);
-
-	if (entry == NULL) {
-		IEEE80211_DEBUG_FRAG(
-			"could not invalidate fragment cache "
-			"entry (seq=%u)\n", seq);
-		return -1;
-	}
-
-	entry->skb = NULL;
-	return 0;
-}
-
-
-
-/* ieee80211_rx_frame_mgtmt
- *
- * Responsible for handling management control frames
- *
- * Called by ieee80211_rx */
-static inline int
-ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
-			struct ieee80211_rx_stats *rx_stats, u16 type,
-			u16 stype)
-{
-	struct ieee80211_hdr_4addr *hdr;
-
-	// cheat the the hdr type
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
-	/* On the struct stats definition there is written that
-	 * this is not mandatory.... but seems that the probe
-	 * response parser uses it
-	 */
-	rx_stats->len = skb->len;
-	ieee80211_rx_mgt(ieee, (struct ieee80211_hdr_4addr *)skb->data,
-			 rx_stats);
-
-	if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) {
-		dev_kfree_skb_any(skb);
-		return 0;
-	}
-
-	ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
-
-	dev_kfree_skb_any(skb);
-
-	return 0;
-
-}
-
-
-
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-static unsigned char bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-/* No encapsulation header if EtherType < 0x600 (=length) */
-
-/* Called by ieee80211_rx_frame_decrypt */
-static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
-				    struct sk_buff *skb, size_t hdrlen)
-{
-	struct net_device *dev = ieee->dev;
-	u16 fc, ethertype;
-	struct ieee80211_hdr_4addr *hdr;
-	u8 *pos;
-
-	if (skb->len < 24)
-		return 0;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	fc = le16_to_cpu(hdr->frame_ctl);
-
-	/* check that the frame is unicast frame to us */
-	if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
-	    IEEE80211_FCTL_TODS &&
-	    memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
-	    memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
-		/* ToDS frame with own addr BSSID and DA */
-	} else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
-		   IEEE80211_FCTL_FROMDS &&
-		   memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
-		/* FromDS frame with own addr as DA */
-	} else
-		return 0;
-
-	if (skb->len < 24 + 8)
-		return 0;
-
-	/* check for port access entity Ethernet type */
-//	pos = skb->data + 24;
-	pos = skb->data + hdrlen;
-	ethertype = (pos[6] << 8) | pos[7];
-	if (ethertype == ETH_P_PAE)
-		return 1;
-
-	return 0;
-}
-
-/* Called only as a tasklet (software IRQ), by ieee80211_rx */
-static inline int
-ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
-			   struct ieee80211_crypt_data *crypt)
-{
-	struct ieee80211_hdr_4addr *hdr;
-	int res, hdrlen;
-
-	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
-		return 0;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
-
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-	if (ieee->tkip_countermeasures &&
-	    strcmp(crypt->ops->name, "TKIP") == 0) {
-		if (net_ratelimit()) {
-			netdev_dbg(ieee->dev,
-				   "TKIP countermeasures: dropped received packet from %pM\n",
-				   ieee->dev->name, hdr->addr2);
-		}
-		return -1;
-	}
-#endif
-
-	atomic_inc(&crypt->refcnt);
-	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
-	if (res < 0) {
-		IEEE80211_DEBUG_DROP(
-			"decryption failed (SA=%pM"
-			") res=%d\n", hdr->addr2, res);
-		if (res == -2)
-			IEEE80211_DEBUG_DROP("Decryption failed ICV "
-					     "mismatch (key %d)\n",
-					     skb->data[hdrlen + 3] >> 6);
-		ieee->ieee_stats.rx_discards_undecryptable++;
-		return -1;
-	}
-
-	return res;
-}
-
-
-/* Called only as a tasklet (software IRQ), by ieee80211_rx */
-static inline int
-ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
-				struct sk_buff *skb, int keyidx,
-				struct ieee80211_crypt_data *crypt)
-{
-	struct ieee80211_hdr_4addr *hdr;
-	int res, hdrlen;
-
-	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
-		return 0;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
-
-	atomic_inc(&crypt->refcnt);
-	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
-	if (res < 0) {
-		netdev_dbg(ieee->dev,
-			   "MSDU decryption/MIC verification failed (SA=%pM keyidx=%d)\n",
-			   hdr->addr2, keyidx);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/* this function is stolen from ipw2200 driver*/
-#define IEEE_PACKET_RETRY_TIME (5*HZ)
-static int is_duplicate_packet(struct ieee80211_device *ieee,
-			       struct ieee80211_hdr_4addr *header)
-{
-	u16 fc = le16_to_cpu(header->frame_ctl);
-	u16 sc = le16_to_cpu(header->seq_ctl);
-	u16 seq = WLAN_GET_SEQ_SEQ(sc);
-	u16 frag = WLAN_GET_SEQ_FRAG(sc);
-	u16 *last_seq, *last_frag;
-	unsigned long *last_time;
-	struct ieee80211_hdr_3addrqos *hdr_3addrqos;
-	struct ieee80211_hdr_4addrqos *hdr_4addrqos;
-	u8 tid;
-
-	//TO2DS and QoS
-	if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
-		hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
-		tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
-		tid = UP2AC(tid);
-		tid++;
-	} else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
-		hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header;
-		tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
-		tid = UP2AC(tid);
-		tid++;
-	} else { // no QoS
-		tid = 0;
-	}
-	switch (ieee->iw_mode) {
-	case IW_MODE_ADHOC:
-	{
-		struct list_head *p;
-		struct ieee_ibss_seq *entry = NULL;
-		u8 *mac = header->addr2;
-		int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
-
-		list_for_each(p, &ieee->ibss_mac_hash[index]) {
-			entry = list_entry(p, struct ieee_ibss_seq, list);
-			if (!memcmp(entry->mac, mac, ETH_ALEN))
-				break;
-		}
-	//	if (memcmp(entry->mac, mac, ETH_ALEN)){
-		if (p == &ieee->ibss_mac_hash[index]) {
-			entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
-			if (!entry)
-				return 0;
-
-			memcpy(entry->mac, mac, ETH_ALEN);
-			entry->seq_num[tid] = seq;
-			entry->frag_num[tid] = frag;
-			entry->packet_time[tid] = jiffies;
-			list_add(&entry->list, &ieee->ibss_mac_hash[index]);
-			return 0;
-		}
-		last_seq = &entry->seq_num[tid];
-		last_frag = &entry->frag_num[tid];
-		last_time = &entry->packet_time[tid];
-		break;
-	}
-
-	case IW_MODE_INFRA:
-		last_seq = &ieee->last_rxseq_num[tid];
-		last_frag = &ieee->last_rxfrag_num[tid];
-		last_time = &ieee->last_packet_time[tid];
-
-		break;
-	default:
-		return 0;
-	}
-
-//	if(tid != 0) {
-//		printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl);
-//	}
-	if ((*last_seq == seq) &&
-	    time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
-		if (*last_frag == frag) {
-			//printk(KERN_WARNING "[1] go drop!\n");
-			goto drop;
-
-		}
-		if (*last_frag + 1 != frag)
-			/* out-of-order fragment */
-			//printk(KERN_WARNING "[2] go drop!\n");
-			goto drop;
-	} else
-		*last_seq = seq;
-
-	*last_frag = frag;
-	*last_time = jiffies;
-	return 0;
-
-drop:
-//	BUG_ON(!(fc & IEEE80211_FCTL_RETRY));
-//	printk("DUP\n");
-
-	return 1;
-}
-
-
-/* All received frames are sent to this function. @skb contains the frame in
- * IEEE 802.11 format, i.e., in the format it was sent over air.
- * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
-		     struct ieee80211_rx_stats *rx_stats)
-{
-	struct net_device *dev = ieee->dev;
-	//struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct ieee80211_hdr_4addr *hdr;
-
-	size_t hdrlen;
-	u16 fc, type, stype, sc;
-	struct net_device_stats *stats;
-	unsigned int frag;
-	u8 *payload;
-	u16 ethertype;
-	u8 dst[ETH_ALEN];
-	u8 src[ETH_ALEN];
-	u8 bssid[ETH_ALEN];
-	struct ieee80211_crypt_data *crypt = NULL;
-	int keyidx = 0;
-
-	// cheat the the hdr type
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	stats = &ieee->stats;
-
-	if (skb->len < 10) {
-		netdev_info(ieee->dev, "SKB length < 10\n");
-		goto rx_dropped;
-	}
-
-	fc = le16_to_cpu(hdr->frame_ctl);
-	type = WLAN_FC_GET_TYPE(fc);
-	stype = WLAN_FC_GET_STYPE(fc);
-	sc = le16_to_cpu(hdr->seq_ctl);
-
-	frag = WLAN_GET_SEQ_FRAG(sc);
-
-//YJ,add,080828,for keep alive
-	if ((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS) {
-		if (!memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN))
-			ieee->NumRxUnicast++;
-	} else {
-		if (!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN))
-			ieee->NumRxUnicast++;
-	}
-//YJ,add,080828,for keep alive,end
-
-	hdrlen = ieee80211_get_hdrlen(fc);
-
-
-	if (ieee->iw_mode == IW_MODE_MONITOR) {
-		ieee80211_monitor_rx(ieee, skb, rx_stats);
-		stats->rx_packets++;
-		stats->rx_bytes += skb->len;
-		return 1;
-	}
-
-	if (ieee->host_decrypt) {
-		int idx = 0;
-		if (skb->len >= hdrlen + 3)
-			idx = skb->data[hdrlen + 3] >> 6;
-		crypt = ieee->crypt[idx];
-
-		/* allow NULL decrypt to indicate an station specific override
-		 * for default encryption */
-		if (crypt && (crypt->ops == NULL ||
-			      crypt->ops->decrypt_mpdu == NULL))
-			crypt = NULL;
-
-		if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
-			/* This seems to be triggered by some (multicast?)
-			 * frames from other than current BSS, so just drop the
-			 * frames silently instead of filling system log with
-			 * these reports. */
-			IEEE80211_DEBUG_DROP("Decryption failed (not set)"
-					     " (SA=%pM)\n",
-					     hdr->addr2);
-			ieee->ieee_stats.rx_discards_undecryptable++;
-			goto rx_dropped;
-		}
-	}
-
-	if (skb->len < IEEE80211_DATA_HDR3_LEN)
-		goto rx_dropped;
-
-	// if QoS enabled, should check the sequence for each of the AC
-	if (is_duplicate_packet(ieee, hdr))
-		goto rx_dropped;
-
-
-	if (type == IEEE80211_FTYPE_MGMT) {
-		if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
-			goto rx_dropped;
-		else
-			goto rx_exit;
-	}
-
-	/* Data frame - extract src/dst addresses */
-	switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
-	case IEEE80211_FCTL_FROMDS:
-		memcpy(dst, hdr->addr1, ETH_ALEN);
-		memcpy(src, hdr->addr3, ETH_ALEN);
-		memcpy(bssid, hdr->addr2, ETH_ALEN);
-		break;
-	case IEEE80211_FCTL_TODS:
-		memcpy(dst, hdr->addr3, ETH_ALEN);
-		memcpy(src, hdr->addr2, ETH_ALEN);
-		memcpy(bssid, hdr->addr1, ETH_ALEN);
-		break;
-	case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
-		if (skb->len < IEEE80211_DATA_HDR4_LEN)
-			goto rx_dropped;
-		memcpy(dst, hdr->addr3, ETH_ALEN);
-		memcpy(src, hdr->addr4, ETH_ALEN);
-		memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
-		break;
-	case 0:
-		memcpy(dst, hdr->addr1, ETH_ALEN);
-		memcpy(src, hdr->addr2, ETH_ALEN);
-		memcpy(bssid, hdr->addr3, ETH_ALEN);
-		break;
-	}
-
-
-	dev->last_rx = jiffies;
-
-
-	/* Nullfunc frames may have PS-bit set, so they must be passed to
-	 * hostap_handle_sta_rx() before being dropped here. */
-	if (stype != IEEE80211_STYPE_DATA &&
-	    stype != IEEE80211_STYPE_DATA_CFACK &&
-	    stype != IEEE80211_STYPE_DATA_CFPOLL &&
-	    stype != IEEE80211_STYPE_DATA_CFACKPOLL &&
-	    stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
-	    ) {
-		if (stype != IEEE80211_STYPE_NULLFUNC)
-			IEEE80211_DEBUG_DROP(
-				"RX: dropped data frame "
-				"with no data (type=0x%02x, "
-				"subtype=0x%02x, len=%d)\n",
-				type, stype, skb->len);
-		goto rx_dropped;
-	}
-	if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
-		goto rx_dropped;
-
-	ieee->NumRxDataInPeriod++;
-	ieee->NumRxOkTotal++;
-	/* skb: hdr + (possibly fragmented, possibly encrypted) payload */
-
-	if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
-	    (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
-		goto rx_dropped;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
-	/* skb: hdr + (possibly fragmented) plaintext payload */
-	// PR: FIXME: hostap has additional conditions in the "if" below:
-	// ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
-	if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
-		int flen;
-		struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
-		IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
-
-		if (!frag_skb) {
-			IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
-					"Rx cannot get skb from fragment "
-					"cache (morefrag=%d seq=%u frag=%u)\n",
-					(fc & IEEE80211_FCTL_MOREFRAGS) != 0,
-					WLAN_GET_SEQ_SEQ(sc), frag);
-			goto rx_dropped;
-		}
-		flen = skb->len;
-		if (frag != 0)
-			flen -= hdrlen;
-
-		if (frag_skb->tail + flen > frag_skb->end) {
-			netdev_warn(ieee->dev,
-				    "host decrypted and reassembled frame did not fit skb\n");
-			ieee80211_frag_cache_invalidate(ieee, hdr);
-			goto rx_dropped;
-		}
-
-		if (frag == 0) {
-			/* copy first fragment (including full headers) into
-			 * beginning of the fragment cache skb */
-			memcpy(skb_put(frag_skb, flen), skb->data, flen);
-		} else {
-			/* append frame payload to the end of the fragment
-			 * cache skb */
-			memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
-			       flen);
-		}
-		dev_kfree_skb_any(skb);
-		skb = NULL;
-
-		if (fc & IEEE80211_FCTL_MOREFRAGS) {
-			/* more fragments expected - leave the skb in fragment
-			 * cache for now; it will be delivered to upper layers
-			 * after all fragments have been received */
-			goto rx_exit;
-		}
-
-		/* this was the last fragment and the frame will be
-		 * delivered, so remove skb from fragment cache */
-		skb = frag_skb;
-		hdr = (struct ieee80211_hdr_4addr *)skb->data;
-		ieee80211_frag_cache_invalidate(ieee, hdr);
-	}
-
-	/* skb: hdr + (possible reassembled) full MSDU payload; possibly still
-	 * encrypted/authenticated */
-	if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
-	    ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
-		goto rx_dropped;
-
-	hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
-		if (/*ieee->ieee802_1x &&*/
-		    ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
-
-#ifdef CONFIG_IEEE80211_DEBUG
-			/* pass unencrypted EAPOL frames even if encryption is
-			 * configured */
-			struct eapol *eap = (struct eapol *)(skb->data +
-				24);
-			IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
-						eap_get_type(eap->type));
-#endif
-		} else {
-			IEEE80211_DEBUG_DROP(
-				"encryption configured, but RX "
-				"frame not encrypted (SA=%pM)\n",
-				hdr->addr2);
-			goto rx_dropped;
-		}
-	}
-
-#ifdef CONFIG_IEEE80211_DEBUG
-	if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
-	    ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
-			struct eapol *eap = (struct eapol *)(skb->data +
-				24);
-			IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
-						eap_get_type(eap->type));
-	}
-#endif
-
-	if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
-	    !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
-		IEEE80211_DEBUG_DROP(
-			"dropped unencrypted RX data "
-			"frame from %pM"
-			" (drop_unencrypted=1)\n",
-			hdr->addr2);
-		goto rx_dropped;
-	}
-/*
-	if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
-		printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
-	}
-*/
-	/* skb: hdr + (possible reassembled) full plaintext payload */
-	payload = skb->data + hdrlen;
-	ethertype = (payload[6] << 8) | payload[7];
-
-
-	/* convert hdr + possible LLC headers into Ethernet header */
-	if (skb->len - hdrlen >= 8 &&
-	    ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
-	      ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
-	     memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
-		/* remove RFC1042 or Bridge-Tunnel encapsulation and
-		 * replace EtherType */
-		skb_pull(skb, hdrlen + SNAP_SIZE);
-		memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
-		memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
-	} else {
-		u16 len;
-		/* Leave Ethernet header part of hdr and full payload */
-		skb_pull(skb, hdrlen);
-		len = htons(skb->len);
-		memcpy(skb_push(skb, 2), &len, 2);
-		memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
-		memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
-	}
-
-
-	stats->rx_packets++;
-	stats->rx_bytes += skb->len;
-
-	if (skb) {
-		skb->protocol = eth_type_trans(skb, dev);
-		memset(skb->cb, 0, sizeof(skb->cb));
-		skb->dev = dev;
-		skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
-		ieee->last_rx_ps_time = jiffies;
-		netif_rx(skb);
-	}
-
- rx_exit:
-	return 1;
-
- rx_dropped:
-	stats->rx_dropped++;
-
-	/* Returning 0 indicates to caller that we have not handled the SKB--
-	 * so it is still allocated and can be used again by underlying
-	 * hardware as a DMA target */
-	return 0;
-}
-
-#define MGMT_FRAME_FIXED_PART_LENGTH		0x24
-
-static inline int ieee80211_is_ofdm_rate(u8 rate)
-{
-	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
-	case IEEE80211_OFDM_RATE_6MB:
-	case IEEE80211_OFDM_RATE_9MB:
-	case IEEE80211_OFDM_RATE_12MB:
-	case IEEE80211_OFDM_RATE_18MB:
-	case IEEE80211_OFDM_RATE_24MB:
-	case IEEE80211_OFDM_RATE_36MB:
-	case IEEE80211_OFDM_RATE_48MB:
-	case IEEE80211_OFDM_RATE_54MB:
-		return 1;
-	}
-	return 0;
-}
-
-static inline int ieee80211_SignalStrengthTranslate(int CurrSS)
-{
-	int RetSS;
-
-	// Step 1. Scale mapping.
-	if (CurrSS >= 71 && CurrSS <= 100)
-		RetSS = 90 + ((CurrSS - 70) / 3);
-	else if (CurrSS >= 41 && CurrSS <= 70)
-		RetSS = 78 + ((CurrSS - 40) / 3);
-	else if (CurrSS >= 31 && CurrSS <= 40)
-		RetSS = 66 + (CurrSS - 30);
-	else if (CurrSS >= 21 && CurrSS <= 30)
-		RetSS = 54 + (CurrSS - 20);
-	else if (CurrSS >= 5 && CurrSS <= 20)
-		RetSS = 42 + (((CurrSS - 5) * 2) / 3);
-	else if (CurrSS == 4)
-		RetSS = 36;
-	else if (CurrSS == 3)
-		RetSS = 27;
-	else if (CurrSS == 2)
-		RetSS = 18;
-	else if (CurrSS == 1)
-		RetSS = 9;
-	else
-		RetSS = CurrSS;
-
-	//RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
-
-	// Step 2. Smoothing.
-
-	//RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
-
-	return RetSS;
-}
-
-static inline void
-ieee80211_extract_country_ie(struct ieee80211_device *ieee,
-			     struct ieee80211_info_element *info_element,
-			     struct ieee80211_network *network, u8 *addr2)
-{
-	if (IS_DOT11D_ENABLE(ieee)) {
-		if (info_element->len != 0) {
-			memcpy(network->CountryIeBuf, info_element->data, info_element->len);
-			network->CountryIeLen = info_element->len;
-
-			if (!IS_COUNTRY_IE_VALID(ieee))
-				Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
-		}
-
-		//
-		// 070305, rcnjko: I update country IE watch dog here because
-		// some AP (e.g. Cisco 1242) don't include country IE in their
-		// probe response frame.
-		//
-		if (IS_EQUAL_CIE_SRC(ieee, addr2))
-			UPDATE_CIE_WATCHDOG(ieee);
-	}
-
-}
-
-/* SignalStrengthIndex is 0-100 */
-static int ieee80211_TranslateToDbm(unsigned char SignalStrengthIndex)
-{
-	unsigned char SignalPower; // in dBm.
-
-	// Translate to dBm (x=0.5y-95).
-	SignalPower = (int)SignalStrengthIndex * 7 / 10;
-	SignalPower -= 95;
-
-	return SignalPower;
-}
-inline int ieee80211_network_init(
-	struct ieee80211_device *ieee,
-	struct ieee80211_probe_response *beacon,
-	struct ieee80211_network *network,
-	struct ieee80211_rx_stats *stats)
-{
-#ifdef CONFIG_IEEE80211_DEBUG
-	char rates_str[64];
-	char *p;
-#endif
-	struct ieee80211_info_element *info_element;
-	u16 left;
-	u8 i;
-	short offset;
-	u8 curRate = 0, hOpRate = 0, curRate_ex = 0;
-
-	/* Pull out fixed field data */
-	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
-	network->capability = beacon->capability;
-	network->last_scanned = jiffies;
-	network->time_stamp[0] = beacon->time_stamp[0];
-	network->time_stamp[1] = beacon->time_stamp[1];
-	network->beacon_interval = beacon->beacon_interval;
-	/* Where to pull this? beacon->listen_interval;*/
-	network->listen_interval = 0x0A;
-	network->rates_len = network->rates_ex_len = 0;
-	network->last_associate = 0;
-	network->ssid_len = 0;
-	network->flags = 0;
-	network->atim_window = 0;
-	network->QoS_Enable = 0;
-//by amy 080312
-	network->HighestOperaRate = 0;
-//by amy 080312
-	network->Turbo_Enable = 0;
-	network->CountryIeLen = 0;
-	memset(network->CountryIeBuf, 0, MAX_IE_LEN);
-
-	if (stats->freq == IEEE80211_52GHZ_BAND) {
-		/* for A band (No DS info) */
-		network->channel = stats->received_channel;
-	} else
-		network->flags |= NETWORK_HAS_CCK;
-
-	network->wpa_ie_len = 0;
-	network->rsn_ie_len = 0;
-
-	info_element = &beacon->info_element;
-	left = stats->len - ((void *)info_element - (void *)beacon);
-	while (left >= sizeof(struct ieee80211_info_element_hdr)) {
-		if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
-			IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
-					     info_element->len + sizeof(struct ieee80211_info_element),
-					     left);
-			return 1;
-		}
-
-		switch (info_element->id) {
-		case MFIE_TYPE_SSID:
-			if (ieee80211_is_empty_essid(info_element->data,
-						     info_element->len)) {
-				network->flags |= NETWORK_EMPTY_ESSID;
-				break;
-			}
-
-			network->ssid_len = min(info_element->len,
-						(u8)IW_ESSID_MAX_SIZE);
-			memcpy(network->ssid, info_element->data, network->ssid_len);
-			if (network->ssid_len < IW_ESSID_MAX_SIZE)
-				memset(network->ssid + network->ssid_len, 0,
-				       IW_ESSID_MAX_SIZE - network->ssid_len);
-
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
-					     network->ssid, network->ssid_len);
-			break;
-
-		case MFIE_TYPE_RATES:
-#ifdef CONFIG_IEEE80211_DEBUG
-			p = rates_str;
-#endif
-			network->rates_len = min(info_element->len, MAX_RATES_LENGTH);
-			for (i = 0; i < network->rates_len; i++) {
-				network->rates[i] = info_element->data[i];
-				curRate = network->rates[i] & 0x7f;
-				if (hOpRate < curRate)
-					hOpRate = curRate;
-#ifdef CONFIG_IEEE80211_DEBUG
-				p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
-#endif
-				if (ieee80211_is_ofdm_rate(info_element->data[i])) {
-					network->flags |= NETWORK_HAS_OFDM;
-					if (info_element->data[i] &
-					    IEEE80211_BASIC_RATE_MASK)
-						network->flags &=
-							~NETWORK_HAS_CCK;
-				}
-			}
-
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
-					     rates_str, network->rates_len);
-			break;
-
-		case MFIE_TYPE_RATES_EX:
-#ifdef CONFIG_IEEE80211_DEBUG
-			p = rates_str;
-#endif
-			network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH);
-			for (i = 0; i < network->rates_ex_len; i++) {
-				network->rates_ex[i] = info_element->data[i];
-				curRate_ex = network->rates_ex[i] & 0x7f;
-				if (hOpRate < curRate_ex)
-					hOpRate = curRate_ex;
-#ifdef CONFIG_IEEE80211_DEBUG
-				p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
-#endif
-				if (ieee80211_is_ofdm_rate(info_element->data[i])) {
-					network->flags |= NETWORK_HAS_OFDM;
-					if (info_element->data[i] &
-					    IEEE80211_BASIC_RATE_MASK)
-						network->flags &=
-							~NETWORK_HAS_CCK;
-				}
-			}
-
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
-					     rates_str, network->rates_ex_len);
-			break;
-
-		case MFIE_TYPE_DS_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
-					     info_element->data[0]);
-			if (stats->freq == IEEE80211_24GHZ_BAND)
-				network->channel = info_element->data[0];
-			break;
-
-		case MFIE_TYPE_FH_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
-			break;
-
-		case MFIE_TYPE_CF_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
-			break;
-
-		case MFIE_TYPE_TIM:
-
-			if (info_element->len < 4)
-				break;
-
-			network->dtim_period = info_element->data[1];
-
-			if (ieee->state != IEEE80211_LINKED)
-				break;
-
-			network->last_dtim_sta_time[0] = jiffies;
-			network->last_dtim_sta_time[1] = stats->mac_time[1];
-
-			network->dtim_data = IEEE80211_DTIM_VALID;
-
-			if (info_element->data[0] != 0)
-				break;
-
-			if (info_element->data[2] & 1)
-				network->dtim_data |= IEEE80211_DTIM_MBCAST;
-
-			offset = (info_element->data[2] >> 1)*2;
-
-			//printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
-
-			/* add and modified for ps 2008.1.22 */
-			if (ieee->assoc_id < 8*offset ||
-				ieee->assoc_id > 8*(offset + info_element->len - 3)) {
-				break;
-			}
-
-			offset = (ieee->assoc_id/8) - offset;// + ((aid % 8)? 0 : 1) ;
-
-		//	printk("offset:%x data:%x, ucast:%d\n", offset,
-			//	info_element->data[3+offset] ,
-			//	info_element->data[3+offset] & (1<<(ieee->assoc_id%8)));
-
-			if (info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
-				network->dtim_data |= IEEE80211_DTIM_UCAST;
-
-			break;
-
-		case MFIE_TYPE_IBSS_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
-			break;
-
-		case MFIE_TYPE_CHALLENGE:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
-			break;
-
-		case MFIE_TYPE_GENERIC:
-			//nic is 87B
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
-					     info_element->len);
-			if (info_element->len >= 4  &&
-			    info_element->data[0] == 0x00 &&
-			    info_element->data[1] == 0x50 &&
-			    info_element->data[2] == 0xf2 &&
-			    info_element->data[3] == 0x01) {
-				network->wpa_ie_len = min(info_element->len + 2,
-							 MAX_WPA_IE_LEN);
-				memcpy(network->wpa_ie, info_element,
-				       network->wpa_ie_len);
-			}
-
-			if (info_element->len == 7 &&
-			    info_element->data[0] == 0x00 &&
-			    info_element->data[1] == 0xe0 &&
-			    info_element->data[2] == 0x4c &&
-			    info_element->data[3] == 0x01 &&
-			    info_element->data[4] == 0x02) {
-				network->Turbo_Enable = 1;
-			}
-			if (1 == stats->nic_type) //nic 87
-				break;
-
-			if (info_element->len >= 5  &&
-			    info_element->data[0] == 0x00 &&
-			    info_element->data[1] == 0x50 &&
-			    info_element->data[2] == 0xf2 &&
-			    info_element->data[3] == 0x02 &&
-			    info_element->data[4] == 0x00) {
-				//printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]);
-				//WMM Information Element
-				network->wmm_info = info_element->data[6];
-				network->QoS_Enable = 1;
-			}
-
-			if (info_element->len >= 8  &&
-			    info_element->data[0] == 0x00 &&
-			    info_element->data[1] == 0x50 &&
-			    info_element->data[2] == 0xf2 &&
-			    info_element->data[3] == 0x02 &&
-			    info_element->data[4] == 0x01) {
-				// Not care about version at present.
-				//WMM Information Element
-				//printk(KERN_WARNING "wmm info&param updated: %x\n", info_element->data[6]);
-				network->wmm_info = info_element->data[6];
-				//WMM Parameter Element
-				memcpy(network->wmm_param, (u8 *)(info_element->data + 8), (info_element->len - 8));
-				network->QoS_Enable = 1;
-			}
-			break;
-
-		case MFIE_TYPE_RSN:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
-					     info_element->len);
-			network->rsn_ie_len = min(info_element->len + 2,
-						 MAX_WPA_IE_LEN);
-			memcpy(network->rsn_ie, info_element,
-			       network->rsn_ie_len);
-			break;
-		case MFIE_TYPE_COUNTRY:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
-					     info_element->len);
-//			printk("=====>Receive <%s> Country IE\n",network->ssid);
-			ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2);
-			break;
-		default:
-			IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
-					     info_element->id);
-			break;
-		}
-
-		left -= sizeof(struct ieee80211_info_element_hdr) +
-			info_element->len;
-		info_element = (struct ieee80211_info_element *)
-			&info_element->data[info_element->len];
-	}
-//by amy 080312
-	network->HighestOperaRate = hOpRate;
-//by amy 080312
-	network->mode = 0;
-	if (stats->freq == IEEE80211_52GHZ_BAND)
-		network->mode = IEEE_A;
-	else {
-		if (network->flags & NETWORK_HAS_OFDM)
-			network->mode |= IEEE_G;
-		if (network->flags & NETWORK_HAS_CCK)
-			network->mode |= IEEE_B;
-	}
-
-	if (network->mode == 0) {
-		IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
-				     "network.\n",
-				     escape_essid(network->ssid,
-						  network->ssid_len),
-				     network->bssid);
-		return 1;
-	}
-
-	if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
-		network->flags |= NETWORK_EMPTY_ESSID;
-
-	stats->signal = ieee80211_TranslateToDbm(stats->signalstrength);
-	//stats->noise = stats->signal - stats->noise;
-	stats->noise = ieee80211_TranslateToDbm(100 - stats->signalstrength) - 25;
-	memcpy(&network->stats, stats, sizeof(network->stats));
-
-	return 0;
-}
-
-static inline int is_same_network(struct ieee80211_network *src,
-				  struct ieee80211_network *dst,
-				  struct ieee80211_device *ieee)
-{
-	/* A network is only a duplicate if the channel, BSSID, ESSID
-	 * and the capability field (in particular IBSS and BSS) all match.
-	 * We treat all <hidden> with the same BSSID and channel
-	 * as one network */
-	return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&  //YJ,mod,080819,for hidden ap
-		//((src->ssid_len == dst->ssid_len) &&
-		(src->channel == dst->channel) &&
-		!memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
-		(!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap
-		//!memcmp(src->ssid, dst->ssid, src->ssid_len) &&
-		((src->capability & WLAN_CAPABILITY_IBSS) ==
-		(dst->capability & WLAN_CAPABILITY_IBSS)) &&
-		((src->capability & WLAN_CAPABILITY_BSS) ==
-		(dst->capability & WLAN_CAPABILITY_BSS)));
-}
-
-inline void update_network(struct ieee80211_network *dst,
-			   struct ieee80211_network *src)
-{
-	unsigned char quality = src->stats.signalstrength;
-	unsigned char signal = 0;
-	unsigned char noise = 0;
-	if (dst->stats.signalstrength > 0)
-		quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6;
-	signal = ieee80211_TranslateToDbm(quality);
-	//noise = signal - src->stats.noise;
-	if (dst->stats.noise > 0)
-		noise = (dst->stats.noise * 5 + src->stats.noise)/6;
-        //if(strcmp(dst->ssid, "linksys_lzm000") == 0)
-//	printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal);
-	memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
-	dst->stats.signalstrength = quality;
-	dst->stats.signal = signal;
-//	printk("==================>stats.signal is %d\n",dst->stats.signal);
-	dst->stats.noise = noise;
-
-
-	dst->capability = src->capability;
-	memcpy(dst->rates, src->rates, src->rates_len);
-	dst->rates_len = src->rates_len;
-	memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
-	dst->rates_ex_len = src->rates_ex_len;
-	dst->HighestOperaRate = src->HighestOperaRate;
-	//printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel);
-
-	//YJ,add,080819,for hidden ap
-	if (src->ssid_len > 0) {
-		//if(src->ssid_len == 13)
-		//	printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid);
-		memset(dst->ssid, 0, dst->ssid_len);
-		dst->ssid_len = src->ssid_len;
-		memcpy(dst->ssid, src->ssid, src->ssid_len);
-	}
-	//YJ,add,080819,for hidden ap,end
-
-	dst->channel = src->channel;
-	dst->mode = src->mode;
-	dst->flags = src->flags;
-	dst->time_stamp[0] = src->time_stamp[0];
-	dst->time_stamp[1] = src->time_stamp[1];
-
-	dst->beacon_interval = src->beacon_interval;
-	dst->listen_interval = src->listen_interval;
-	dst->atim_window = src->atim_window;
-	dst->dtim_period = src->dtim_period;
-	dst->dtim_data = src->dtim_data;
-	dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
-	dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
-//	printk("update:%s, dtim_period:%x, dtim_data:%x\n", src->ssid, src->dtim_period, src->dtim_data);
-	memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
-	dst->wpa_ie_len = src->wpa_ie_len;
-	memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
-	dst->rsn_ie_len = src->rsn_ie_len;
-
-	dst->last_scanned = jiffies;
-	/* dst->last_associate is not overwritten */
-// disable QoS process now, added by David 2006/7/25
-#if 1
-	dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
-/*
-	if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter
-	  memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN);
-	}
-*/
-	if (src->wmm_param[0].ac_aci_acm_aifsn || \
-	   src->wmm_param[1].ac_aci_acm_aifsn || \
-	   src->wmm_param[2].ac_aci_acm_aifsn || \
-	   src->wmm_param[3].ac_aci_acm_aifsn) {
-		memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
-	}
-	dst->QoS_Enable = src->QoS_Enable;
-#else
-	dst->QoS_Enable = 1;//for Rtl8187 simulation
-#endif
-	dst->SignalStrength = src->SignalStrength;
-	dst->Turbo_Enable = src->Turbo_Enable;
-	dst->CountryIeLen = src->CountryIeLen;
-	memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
-}
-
-
-inline void
-ieee80211_process_probe_response(struct ieee80211_device *ieee,
-				 struct ieee80211_probe_response *beacon,
-				 struct ieee80211_rx_stats *stats)
-{
-	struct ieee80211_network network;
-	struct ieee80211_network *target;
-	struct ieee80211_network *oldest = NULL;
-#ifdef CONFIG_IEEE80211_DEBUG
-	struct ieee80211_info_element *info_element = &beacon->info_element;
-#endif
-	unsigned long flags;
-	short renew;
-	u8 wmm_info;
-	u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON) ? 1 : 0;  //YJ,add,080819,for hidden ap
-
-	memset(&network, 0, sizeof(struct ieee80211_network));
-
-	IEEE80211_DEBUG_SCAN(
-		"'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
-		escape_essid(info_element->data, info_element->len),
-		beacon->header.addr3,
-		(beacon->capability & (1<<0xf)) ? '1' : '0',
-		(beacon->capability & (1<<0xe)) ? '1' : '0',
-		(beacon->capability & (1<<0xd)) ? '1' : '0',
-		(beacon->capability & (1<<0xc)) ? '1' : '0',
-		(beacon->capability & (1<<0xb)) ? '1' : '0',
-		(beacon->capability & (1<<0xa)) ? '1' : '0',
-		(beacon->capability & (1<<0x9)) ? '1' : '0',
-		(beacon->capability & (1<<0x8)) ? '1' : '0',
-		(beacon->capability & (1<<0x7)) ? '1' : '0',
-		(beacon->capability & (1<<0x6)) ? '1' : '0',
-		(beacon->capability & (1<<0x5)) ? '1' : '0',
-		(beacon->capability & (1<<0x4)) ? '1' : '0',
-		(beacon->capability & (1<<0x3)) ? '1' : '0',
-		(beacon->capability & (1<<0x2)) ? '1' : '0',
-		(beacon->capability & (1<<0x1)) ? '1' : '0',
-		(beacon->capability & (1<<0x0)) ? '1' : '0');
-
-	if (ieee80211_network_init(ieee, beacon, &network, stats)) {
-		IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
-				     escape_essid(info_element->data,
-						  info_element->len),
-				     beacon->header.addr3,
-				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
-		return;
-	}
-
-	// For Asus EeePc request,
-	// (1) if wireless adapter receive get any 802.11d country code in AP beacon,
-	//	   wireless adapter should follow the country code.
-	// (2)  If there is no any country code in beacon,
-	//       then wireless adapter should do active scan from ch1~11 and
-	//       passive scan from ch12~14
-	if (ieee->bGlobalDomain) {
-		if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) {
-			// Case 1: Country code
-			if (IS_COUNTRY_IE_VALID(ieee)) {
-				if (!IsLegalChannel(ieee, network.channel)) {
-					printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
-					return;
-				}
-			}
-			// Case 2: No any country code.
-			else {
-				// Filter over channel ch12~14
-				if (network.channel > 11) {
-					printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
-					return;
-				}
-			}
-		} else {
-			// Case 1: Country code
-			if (IS_COUNTRY_IE_VALID(ieee)) {
-				if (!IsLegalChannel(ieee, network.channel)) {
-					printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network.channel);
-					return;
-				}
-			}
-			// Case 2: No any country code.
-			else {
-				// Filter over channel ch12~14
-				if (network.channel > 14) {
-					printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network.channel);
-					return;
-				}
-			}
-		}
-	}
-	/* The network parsed correctly -- so now we scan our known networks
-	 * to see if we can find it in our list.
-	 *
-	 * NOTE:  This search is definitely not optimized.  Once its doing
-	 *        the "right thing" we'll optimize it for efficiency if
-	 *        necessary */
-
-	/* Search for this entry in the list and update it if it is
-	 * already there. */
-
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if (is_same_network(&ieee->current_network, &network, ieee)) {
-		wmm_info = ieee->current_network.wmm_info;
-		//YJ,add,080819,for hidden ap
-		if (is_beacon == 0)
-			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
-		else if (ieee->state == IEEE80211_LINKED)
-			ieee->NumRxBcnInPeriod++;
-		//YJ,add,080819,for hidden ap,end
-		//printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid);
-		update_network(&ieee->current_network, &network);
-	}
-
-	list_for_each_entry(target, &ieee->network_list, list) {
-		if (is_same_network(target, &network, ieee))
-			break;
-		if ((oldest == NULL) ||
-		    (target->last_scanned < oldest->last_scanned))
-			oldest = target;
-	}
-
-	/* If we didn't find a match, then get a new network slot to initialize
-	 * with this beacon's information */
-	if (&target->list == &ieee->network_list) {
-		if (list_empty(&ieee->network_free_list)) {
-			/* If there are no more slots, expire the oldest */
-			list_del(&oldest->list);
-			target = oldest;
-			IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
-					     "network list.\n",
-					     escape_essid(target->ssid,
-							  target->ssid_len),
-					     target->bssid);
-		} else {
-			/* Otherwise just pull from the free list */
-			target = list_entry(ieee->network_free_list.next,
-					    struct ieee80211_network, list);
-			list_del(ieee->network_free_list.next);
-		}
-
-
-#ifdef CONFIG_IEEE80211_DEBUG
-		IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
-				     escape_essid(network.ssid,
-						  network.ssid_len),
-				     network.bssid,
-				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
-#endif
-
-		memcpy(target, &network, sizeof(*target));
-		list_add_tail(&target->list, &ieee->network_list);
-	} else {
-		IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
-				     escape_essid(target->ssid,
-						  target->ssid_len),
-				     target->bssid,
-				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
-
-		/* we have an entry and we are going to update it. But this entry may
-		 * be already expired. In this case we do the same as we found a new
-		 * net and call the new_net handler
-		 */
-		renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
-		//YJ,add,080819,for hidden ap
-		if (is_beacon == 0)
-			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
-		//if(strncmp(network.ssid, "linksys-c",9) == 0)
-		//	printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
-		if (((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
-		    && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
-		    || ((ieee->current_network.ssid_len == network.ssid_len) && (strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK))))
-			renew = 1;
-		//YJ,add,080819,for hidden ap,end
-		update_network(target, &network);
-	}
-
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-		      struct ieee80211_hdr_4addr *header,
-		      struct ieee80211_rx_stats *stats)
-{
-	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
-
-	case IEEE80211_STYPE_BEACON:
-		IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
-		IEEE80211_DEBUG_SCAN("Beacon\n");
-		ieee80211_process_probe_response(
-			ieee, (struct ieee80211_probe_response *)header, stats);
-		break;
-
-	case IEEE80211_STYPE_PROBE_RESP:
-		IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
-		IEEE80211_DEBUG_SCAN("Probe response\n");
-		ieee80211_process_probe_response(
-			ieee, (struct ieee80211_probe_response *)header, stats);
-		break;
-	}
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
deleted file mode 100644
index 03eb164798cd..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ /dev/null
@@ -1,2711 +0,0 @@
-/* IEEE 802.11 SoftMAC layer
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * Mostly extracted from the rtl8180-sa2400 driver for the
- * in-kernel generic ieee802.11 stack.
- *
- * Few lines might be stolen from other part of the ieee80211
- * stack. Copyright who own it's copyright
- *
- * WPA code stolen from the ipw2200 driver.
- * Copyright who own it's copyright.
- *
- * released under the GPL
- */
-
-#include "ieee80211.h"
-
-#include <linux/random.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
-#include <linux/etherdevice.h>
-
-#include "dot11d.h"
-
-short ieee80211_is_54g(const struct ieee80211_network *net)
-{
-	return (net->rates_ex_len > 0) || (net->rates_len > 4);
-}
-
-short ieee80211_is_shortslot(const struct ieee80211_network *net)
-{
-	return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
-}
-
-/* returns the total length needed for placing the RATE MFIE
- * tag and the EXTENDED RATE MFIE tag if needed.
- * It encludes two bytes per tag for the tag itself and its len
- */
-static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
-{
-	unsigned int rate_len = 0;
-
-	if (ieee->modulation & IEEE80211_CCK_MODULATION)
-		rate_len = IEEE80211_CCK_RATE_LEN + 2;
-
-	if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-
-		rate_len += IEEE80211_OFDM_RATE_LEN + 2;
-
-	return rate_len;
-}
-
-/* place the MFIE rate, tag to the memory (double) poised.
- * Then it updates the pointer so that it points after the new MFIE tag added.
- */
-static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
-{
-	u8 *tag = *tag_p;
-
-	if (ieee->modulation & IEEE80211_CCK_MODULATION) {
-		*tag++ = MFIE_TYPE_RATES;
-		*tag++ = 4;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
-	}
-
-	/* We may add an option for custom rates that specific HW might support */
-	*tag_p = tag;
-}
-
-static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
-{
-	u8 *tag = *tag_p;
-
-		if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-		*tag++ = MFIE_TYPE_RATES_EX;
-		*tag++ = 8;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
-		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
-
-	}
-	/* We may add an option for custom rates that specific HW might support */
-	*tag_p = tag;
-}
-
-static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
-{
-	u8 *tag = *tag_p;
-
-	*tag++ = MFIE_TYPE_GENERIC; /* 0 */
-	*tag++ = 7;
-	*tag++ = 0x00;
-	*tag++ = 0x50;
-	*tag++ = 0xf2;
-	*tag++ = 0x02; /* 5 */
-	*tag++ = 0x00;
-	*tag++ = 0x01;
-#ifdef SUPPORT_USPD
-	if (ieee->current_network.wmm_info & 0x80)
-		*tag++ = 0x0f|MAX_SP_Len;
-	else
-		*tag++ = MAX_SP_Len;
-#else
-	*tag++ = MAX_SP_Len;
-#endif
-	*tag_p = tag;
-}
-
-static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p)
-{
-	u8 *tag = *tag_p;
-	*tag++ = MFIE_TYPE_GENERIC; /* 0 */
-	*tag++ = 7;
-	*tag++ = 0x00;
-	*tag++ = 0xe0;
-	*tag++ = 0x4c;
-	*tag++ = 0x01; /* 5 */
-	*tag++ = 0x02;
-	*tag++ = 0x11;
-	*tag++ = 0x00;
-	*tag_p = tag;
-	printk(KERN_ALERT "This is enable turbo mode IE process\n");
-}
-
-static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
-{
-	int nh;
-	nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM;
-
-	ieee->mgmt_queue_head = nh;
-	ieee->mgmt_queue_ring[nh] = skb;
-}
-
-static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
-{
-	struct sk_buff *ret;
-
-	if (ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
-		return NULL;
-
-	ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
-
-	ieee->mgmt_queue_tail =
-		(ieee->mgmt_queue_tail + 1) % MGMT_QUEUE_NUM;
-
-	return ret;
-}
-
-static void init_mgmt_queue(struct ieee80211_device *ieee)
-{
-	ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
-}
-
-void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
-
-inline void softmac_mgmt_xmit(struct sk_buff *skb,
-			      struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-	short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
-	struct ieee80211_hdr_3addr  *header =
-		(struct ieee80211_hdr_3addr  *) skb->data;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	/* called with 2nd param 0, no mgmt lock required */
-	ieee80211_sta_wakeup(ieee, 0);
-
-	if (single) {
-		if (ieee->queue_stop) {
-			enqueue_mgmt(ieee, skb);
-		} else {
-			header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
-
-			if (ieee->seq_ctrl[0] == 0xFFF)
-				ieee->seq_ctrl[0] = 0;
-			else
-				ieee->seq_ctrl[0]++;
-
-			/* avoid watchdog triggers */
-			ieee->dev->trans_start = jiffies;
-			ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
-		}
-
-		spin_unlock_irqrestore(&ieee->lock, flags);
-	} else {
-		spin_unlock_irqrestore(&ieee->lock, flags);
-		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
-
-		header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
-		if (ieee->seq_ctrl[0] == 0xFFF)
-			ieee->seq_ctrl[0] = 0;
-		else
-			ieee->seq_ctrl[0]++;
-
-		/* avoid watchdog triggers */
-		ieee->dev->trans_start = jiffies;
-		ieee->softmac_hard_start_xmit(skb, ieee->dev);
-
-		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
-	}
-}
-
-inline void softmac_ps_mgmt_xmit(struct sk_buff *skb,
-				 struct ieee80211_device *ieee)
-{
-	short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
-	struct ieee80211_hdr_3addr  *header =
-		(struct ieee80211_hdr_3addr  *) skb->data;
-
-	if (single) {
-		header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
-		if (ieee->seq_ctrl[0] == 0xFFF)
-			ieee->seq_ctrl[0] = 0;
-		else
-			ieee->seq_ctrl[0]++;
-
-		/* avoid watchdog triggers */
-		ieee->dev->trans_start = jiffies;
-		ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
-	} else {
-		header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
-		if (ieee->seq_ctrl[0] == 0xFFF)
-			ieee->seq_ctrl[0] = 0;
-		else
-			ieee->seq_ctrl[0]++;
-
-		/* avoid watchdog triggers */
-		ieee->dev->trans_start = jiffies;
-		ieee->softmac_hard_start_xmit(skb, ieee->dev);
-	}
-}
-
-inline struct sk_buff *
-ieee80211_disassociate_skb(struct ieee80211_network *beacon,
-			   struct ieee80211_device *ieee, u8 asRsn)
-{
-	struct sk_buff *skb;
-	struct ieee80211_disassoc_frame *disass;
-
-	skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc_frame));
-	if (!skb)
-		return NULL;
-
-	disass = (struct ieee80211_disassoc_frame *) skb_put(skb, sizeof(struct ieee80211_disassoc_frame));
-	disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
-	disass->header.duration_id = 0;
-
-	memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
-	memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
-
-	disass->reasoncode = asRsn;
-	return skb;
-}
-
-void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn)
-{
-	struct ieee80211_network *beacon = &ieee->current_network;
-	struct sk_buff *skb;
-	skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
-	if (skb)
-		softmac_mgmt_xmit(skb, ieee);
-}
-
-inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
-{
-	unsigned int len, rate_len;
-	u8 *tag;
-	struct sk_buff *skb;
-	struct ieee80211_probe_request *req;
-
-	len = ieee->current_network.ssid_len;
-
-	rate_len = ieee80211_MFIE_rate_len(ieee);
-
-	skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
-			    2 + len + rate_len);
-	if (!skb)
-		return NULL;
-
-	req = (struct ieee80211_probe_request *) skb_put(skb, sizeof(struct ieee80211_probe_request));
-	req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
-	req->header.duration_id = 0; /* FIXME: is this OK ? */
-
-	memset(req->header.addr1, 0xff, ETH_ALEN);
-	memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
-	memset(req->header.addr3, 0xff, ETH_ALEN);
-
-	tag = (u8 *) skb_put(skb, len + 2 + rate_len);
-
-	*tag++ = MFIE_TYPE_SSID;
-	*tag++ = len;
-	memcpy(tag, ieee->current_network.ssid, len);
-	tag += len;
-	ieee80211_MFIE_Brate(ieee, &tag);
-	ieee80211_MFIE_Grate(ieee, &tag);
-
-	return skb;
-}
-
-struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
-
-static void ieee80211_send_beacon(struct ieee80211_device *ieee)
-{
-	struct sk_buff *skb;
-
-	skb = ieee80211_get_beacon_(ieee);
-
-	if (skb) {
-		softmac_mgmt_xmit(skb, ieee);
-		ieee->softmac_stats.tx_beacons++;
-		dev_kfree_skb_any(skb);
-	}
-
-	ieee->beacon_timer.expires = jiffies +
-		(MSECS(ieee->current_network.beacon_interval - 5));
-
-	if (ieee->beacon_txing)
-		add_timer(&ieee->beacon_timer);
-}
-
-
-static void ieee80211_send_beacon_cb(unsigned long _ieee)
-{
-	struct ieee80211_device *ieee =
-		(struct ieee80211_device *) _ieee;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ieee->beacon_lock, flags);
-	ieee80211_send_beacon(ieee);
-	spin_unlock_irqrestore(&ieee->beacon_lock, flags);
-}
-
-static void ieee80211_send_probe(struct ieee80211_device *ieee)
-{
-	struct sk_buff *skb;
-
-	skb = ieee80211_probe_req(ieee);
-	if (skb) {
-		softmac_mgmt_xmit(skb, ieee);
-		ieee->softmac_stats.tx_probe_rq++;
-	}
-}
-
-static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
-{
-	if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) {
-		ieee80211_send_probe(ieee);
-		ieee80211_send_probe(ieee);
-	}
-}
-
-/* this performs syncro scan blocking the caller until all channels
- * in the allowed channel map has been checked.
- */
-static void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
-{
-	short ch = 0;
-	u8 channel_map[MAX_CHANNEL_NUMBER+1];
-	memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
-	down(&ieee->scan_sem);
-
-	while (1) {
-		do {
-			ch++;
-			if (ch > MAX_CHANNEL_NUMBER)
-				goto out; /* scan completed */
-
-		} while (!channel_map[ch]);
-		/* this function can be called in two situations
-		 * 1- We have switched to ad-hoc mode and we are
-		 *    performing a complete syncro scan before conclude
-		 *    there are no interesting cell and to create a
-		 *    new one. In this case the link state is
-		 *    IEEE80211_NOLINK until we found an interesting cell.
-		 *    If so the ieee8021_new_net, called by the RX path
-		 *    will set the state to IEEE80211_LINKED, so we stop
-		 *    scanning
-		 * 2- We are linked and the root uses run iwlist scan.
-		 *    So we switch to IEEE80211_LINKED_SCANNING to remember
-		 *    that we are still logically linked (not interested in
-		 *    new network events, despite for updating the net list,
-		 *    but we are temporarily 'unlinked' as the driver shall
-		 *    not filter RX frames and the channel is changing.
-		 * So the only situation in witch are interested is to check
-		 * if the state become LINKED because of the #1 situation
-		 */
-
-		if (ieee->state == IEEE80211_LINKED)
-			goto out;
-
-		ieee->set_chan(ieee->dev, ch);
-		if (channel_map[ch] == 1)
-			ieee80211_send_probe_requests(ieee);
-
-		/* this prevent excessive time wait when we
-		 * need to wait for a syncro scan to end..
-		 */
-		if (ieee->sync_scan_hurryup)
-			goto out;
-
-		msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME);
-	}
-out:
-	ieee->sync_scan_hurryup = 0;
-	up(&ieee->scan_sem);
-	if (IS_DOT11D_ENABLE(ieee))
-		DOT11D_ScanComplete(ieee);
-}
-
-void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee)
-{
-	int ch;
-	unsigned int watch_dog = 0;
-	u8 channel_map[MAX_CHANNEL_NUMBER+1];
-	memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
-	down(&ieee->scan_sem);
-	ch = ieee->current_network.channel;
-
-	while (1) {
-		/* this function can be called in two situations
-		 * 1- We have switched to ad-hoc mode and we are
-		 *    performing a complete syncro scan before conclude
-		 *    there are no interesting cell and to create a
-		 *    new one. In this case the link state is
-		 *    IEEE80211_NOLINK until we found an interesting cell.
-		 *    If so the ieee8021_new_net, called by the RX path
-		 *    will set the state to IEEE80211_LINKED, so we stop
-		 *    scanning
-		 * 2- We are linked and the root uses run iwlist scan.
-		 *    So we switch to IEEE80211_LINKED_SCANNING to remember
-		 *    that we are still logically linked (not interested in
-		 *    new network events, despite for updating the net list,
-		 *    but we are temporarily 'unlinked' as the driver shall
-		 *    not filter RX frames and the channel is changing.
-		 * So the only situation in witch are interested is to check
-		 * if the state become LINKED because of the #1 situation
-		 */
-		if (ieee->state == IEEE80211_LINKED)
-			goto out;
-
-		if (channel_map[ieee->current_network.channel] > 0)
-			ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
-		if (channel_map[ieee->current_network.channel] == 1)
-			ieee80211_send_probe_requests(ieee);
-
-		msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME);
-
-		do {
-			if (watch_dog++ >= MAX_CHANNEL_NUMBER)
-				goto out; /* scan completed */
-
-			ieee->current_network.channel = (ieee->current_network.channel + 1)%MAX_CHANNEL_NUMBER;
-		} while (!channel_map[ieee->current_network.channel]);
-	}
-out:
-	ieee->actscanning = false;
-	up(&ieee->scan_sem);
-	if (IS_DOT11D_ENABLE(ieee))
-		DOT11D_ScanComplete(ieee);
-}
-
-static void ieee80211_softmac_scan_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
-	static short watchdog;
-	u8 channel_map[MAX_CHANNEL_NUMBER+1];
-	memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
-	down(&ieee->scan_sem);
-
-	do {
-		ieee->current_network.channel =
-			(ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
-		if (watchdog++ > MAX_CHANNEL_NUMBER)
-				goto out; /* no good chans */
-	} while (!channel_map[ieee->current_network.channel]);
-
-	if (ieee->scanning == 0) {
-		printk("error out, scanning = 0\n");
-		goto out;
-	}
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
-	if (channel_map[ieee->current_network.channel] == 1)
-		ieee80211_send_probe_requests(ieee);
-
-	queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
-	up(&ieee->scan_sem);
-	return;
-out:
-	ieee->actscanning = false;
-	watchdog = 0;
-	ieee->scanning = 0;
-	up(&ieee->scan_sem);
-
-	if (IS_DOT11D_ENABLE(ieee))
-		DOT11D_ScanComplete(ieee);
-	return;
-}
-
-static void ieee80211_beacons_start(struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ieee->beacon_lock, flags);
-
-	ieee->beacon_txing = 1;
-	ieee80211_send_beacon(ieee);
-
-	spin_unlock_irqrestore(&ieee->beacon_lock, flags);
-}
-
-static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ieee->beacon_lock, flags);
-
-	ieee->beacon_txing = 0;
-	del_timer_sync(&ieee->beacon_timer);
-
-	spin_unlock_irqrestore(&ieee->beacon_lock, flags);
-}
-
-void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
-{
-	if (ieee->stop_send_beacons)
-		ieee->stop_send_beacons(ieee->dev);
-	if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
-		ieee80211_beacons_stop(ieee);
-}
-
-void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
-{
-	if (ieee->start_send_beacons)
-		ieee->start_send_beacons(ieee->dev);
-	if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
-		ieee80211_beacons_start(ieee);
-}
-
-static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
-{
-	down(&ieee->scan_sem);
-
-	if (ieee->scanning == 1) {
-		ieee->scanning = 0;
-		cancel_delayed_work(&ieee->softmac_scan_wq);
-	}
-
-	up(&ieee->scan_sem);
-}
-
-void ieee80211_stop_scan(struct ieee80211_device *ieee)
-{
-	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
-		ieee80211_softmac_stop_scan(ieee);
-	else
-		ieee->stop_scan(ieee->dev);
-}
-
-/* called with ieee->lock held */
-void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
-{
-	if (IS_DOT11D_ENABLE(ieee)) {
-		if (IS_COUNTRY_IE_VALID(ieee))
-			RESET_CIE_WATCHDOG(ieee);
-	}
-
-	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
-		if (ieee->scanning == 0) {
-			ieee->scanning = 1;
-#if 1
-			queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
-#endif
-		}
-	}else
-		ieee->start_scan(ieee->dev);
-}
-
-/* called with wx_sem held */
-void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
-{
-	if (IS_DOT11D_ENABLE(ieee)) {
-		if (IS_COUNTRY_IE_VALID(ieee))
-			RESET_CIE_WATCHDOG(ieee);
-	}
-	ieee->sync_scan_hurryup = 0;
-
-	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
-		ieee80211_softmac_scan_syncro(ieee);
-	else
-		ieee->scan_syncro(ieee->dev);
-}
-
-inline struct sk_buff *
-ieee80211_authentication_req(struct ieee80211_network *beacon,
-			     struct ieee80211_device *ieee, int challengelen)
-{
-	struct sk_buff *skb;
-	struct ieee80211_authentication *auth;
-
-	skb = dev_alloc_skb(sizeof(struct ieee80211_authentication) + challengelen);
-
-	if (!skb)
-		return NULL;
-
-	auth = (struct ieee80211_authentication *)
-		skb_put(skb, sizeof(struct ieee80211_authentication));
-
-	auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
-	if (challengelen)
-		auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
-
-	auth->header.duration_id = 0x013a; /* FIXME */
-
-	memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
-	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
-
-	auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
-
-	auth->transaction = cpu_to_le16(ieee->associate_seq);
-	ieee->associate_seq++;
-
-	auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
-
-	return skb;
-}
-
-static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee,
-					    u8 *dest)
-{
-	u8 *tag;
-	int beacon_size;
-	struct ieee80211_probe_response *beacon_buf;
-	struct sk_buff *skb;
-	int encrypt;
-	int atim_len, erp_len;
-	struct ieee80211_crypt_data *crypt;
-
-	char *ssid = ieee->current_network.ssid;
-	int ssid_len = ieee->current_network.ssid_len;
-	int rate_len = ieee->current_network.rates_len+2;
-	int rate_ex_len = ieee->current_network.rates_ex_len;
-	int wpa_ie_len = ieee->wpa_ie_len;
-	if (rate_ex_len > 0)
-		rate_ex_len += 2;
-
-	if (ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
-		atim_len = 4;
-	else
-		atim_len = 0;
-
-	if (ieee80211_is_54g(&ieee->current_network))
-		erp_len = 3;
-	else
-		erp_len = 0;
-
-	beacon_size = sizeof(struct ieee80211_probe_response)+
-		ssid_len
-		+3 /* channel */
-		+rate_len
-		+rate_ex_len
-		+atim_len
-		+wpa_ie_len
-		+erp_len;
-
-	skb = dev_alloc_skb(beacon_size);
-
-	if (!skb)
-		return NULL;
-
-	beacon_buf = (struct ieee80211_probe_response *) skb_put(skb, beacon_size);
-
-	memcpy(beacon_buf->header.addr1, dest, ETH_ALEN);
-	memcpy(beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
-
-	beacon_buf->header.duration_id = 0; /* FIXME */
-	beacon_buf->beacon_interval =
-		cpu_to_le16(ieee->current_network.beacon_interval);
-	beacon_buf->capability =
-		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
-
-	if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
-		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
-
-	crypt = ieee->crypt[ieee->tx_keyidx];
-
-	encrypt = ieee->host_encrypt && crypt && crypt->ops &&
-		((0 == strcmp(crypt->ops->name, "WEP")) || wpa_ie_len);
-
-	if (encrypt)
-		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
-
-
-	beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
-
-	beacon_buf->info_element.id = MFIE_TYPE_SSID;
-	beacon_buf->info_element.len = ssid_len;
-
-	tag = (u8 *) beacon_buf->info_element.data;
-
-	memcpy(tag, ssid, ssid_len);
-
-	tag += ssid_len;
-
-	*(tag++) = MFIE_TYPE_RATES;
-	*(tag++) = rate_len - 2;
-	memcpy(tag, ieee->current_network.rates, rate_len-2);
-	tag += rate_len - 2;
-
-	*(tag++) = MFIE_TYPE_DS_SET;
-	*(tag++) = 1;
-	*(tag++) = ieee->current_network.channel;
-
-	if (atim_len) {
-		*(tag++) = MFIE_TYPE_IBSS_SET;
-		*(tag++) = 2;
-		*((u16 *)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
-		tag += 2;
-	}
-
-	if (erp_len) {
-		*(tag++) = MFIE_TYPE_ERP;
-		*(tag++) = 1;
-		*(tag++) = 0;
-	}
-
-	if (rate_ex_len) {
-		*(tag++) = MFIE_TYPE_RATES_EX;
-		*(tag++) = rate_ex_len-2;
-		memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
-		tag += rate_ex_len - 2;
-	}
-
-	if (wpa_ie_len)	{
-		if (ieee->iw_mode == IW_MODE_ADHOC) {
-			/* as Windows will set pairwise key same as the group
-			 * key which is not allowed in Linux, so set this for
-			 * IOT issue.
-			 */
-			memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
-		}
-
-		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
-	}
-	skb->dev = ieee->dev;
-	return skb;
-}
-
-static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
-					    u8 *dest)
-{
-	struct sk_buff *skb;
-	u8 *tag;
-
-	struct ieee80211_crypt_data *crypt;
-	struct ieee80211_assoc_response_frame *assoc;
-	short encrypt;
-
-	unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
-	int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len;
-
-	skb = dev_alloc_skb(len);
-
-	if (!skb)
-		return NULL;
-
-	assoc = (struct ieee80211_assoc_response_frame *)
-		skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
-
-	assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
-	memcpy(assoc->header.addr1, dest, ETH_ALEN);
-	memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
-	assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
-		WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
-
-	if (ieee->short_slot)
-		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
-
-	if (ieee->host_encrypt)
-		crypt = ieee->crypt[ieee->tx_keyidx];
-	else
-		crypt = NULL;
-
-	encrypt = (crypt && crypt->ops);
-
-	if (encrypt)
-		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
-
-	assoc->status = 0;
-	assoc->aid = cpu_to_le16(ieee->assoc_id);
-	if (ieee->assoc_id == 0x2007)
-		ieee->assoc_id = 0;
-	else
-		ieee->assoc_id++;
-
-	tag = (u8 *) skb_put(skb, rate_len);
-
-	ieee80211_MFIE_Brate(ieee, &tag);
-	ieee80211_MFIE_Grate(ieee, &tag);
-
-	return skb;
-}
-
-static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
-					   int status, u8 *dest)
-{
-	struct sk_buff *skb;
-	struct ieee80211_authentication *auth;
-
-	skb = dev_alloc_skb(sizeof(struct ieee80211_authentication)+1);
-
-	if (!skb)
-		return NULL;
-
-	skb->len = sizeof(struct ieee80211_authentication);
-
-	auth = (struct ieee80211_authentication *)skb->data;
-
-	auth->status = cpu_to_le16(status);
-	auth->transaction = cpu_to_le16(2);
-	auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
-
-	memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(auth->header.addr1, dest, ETH_ALEN);
-	auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
-	return skb;
-}
-
-static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee, short pwr)
-{
-	struct sk_buff *skb;
-	struct ieee80211_hdr_3addr *hdr;
-
-	skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
-
-	if (!skb)
-		return NULL;
-
-	hdr = (struct ieee80211_hdr_3addr *)skb_put(skb, sizeof(struct ieee80211_hdr_3addr));
-
-	memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
-	memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
-
-	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
-		IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
-		(pwr ? IEEE80211_FCTL_PM:0));
-
-	return skb;
-}
-
-static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
-{
-	struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
-
-	if (buf) {
-		softmac_mgmt_xmit(buf, ieee);
-		dev_kfree_skb_any(buf);
-	}
-}
-
-static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8 *dest)
-{
-	struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
-
-	if (buf) {
-		softmac_mgmt_xmit(buf, ieee);
-		dev_kfree_skb_any(buf);
-	}
-}
-
-static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
-{
-	struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
-
-	if (buf) {
-		softmac_mgmt_xmit(buf, ieee);
-		dev_kfree_skb_any(buf);
-	}
-}
-
-inline struct sk_buff *
-ieee80211_association_req(struct ieee80211_network *beacon,
-			  struct ieee80211_device *ieee)
-{
-	struct sk_buff *skb;
-
-	struct ieee80211_assoc_request_frame *hdr;
-	u8 *tag;
-	unsigned int wpa_len = beacon->wpa_ie_len;
-#if 1
-	/* for testing purpose */
-	unsigned int rsn_len = beacon->rsn_ie_len;
-#endif
-	unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
-	unsigned int wmm_info_len = beacon->QoS_Enable?9:0;
-	unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
-
-	u8  encry_proto = ieee->wpax_type_notify & 0xff;
-
-	int len = 0;
-
-	/* [0] Notify type of encryption: WPA/WPA2
-	 * [1] pair wise type
-	 * [2] authen type
-	 */
-	if (ieee->wpax_type_set) {
-		if (IEEE_PROTO_WPA == encry_proto) {
-			rsn_len = 0;
-		} else if (IEEE_PROTO_RSN == encry_proto) {
-			wpa_len = 0;
-		}
-	}
-	len = sizeof(struct ieee80211_assoc_request_frame)+
-		+ beacon->ssid_len /* essid tagged val */
-		+ rate_len /* rates tagged val */
-		+ wpa_len
-		+ rsn_len
-		+ wmm_info_len
-		+ turbo_info_len;
-
-	skb = dev_alloc_skb(len);
-
-	if (!skb)
-		return NULL;
-
-	hdr = (struct ieee80211_assoc_request_frame *)
-		skb_put(skb, sizeof(struct ieee80211_assoc_request_frame));
-
-	hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
-	hdr->header.duration_id = 37; /* FIXME */
-	memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
-	memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
-	memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
-	memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN); /* for HW security */
-
-	hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
-	if (beacon->capability & WLAN_CAPABILITY_PRIVACY)
-		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
-	if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
-
-	if (ieee->short_slot)
-		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
-
-	hdr->listen_interval = 0xa; /* FIXME */
-
-	hdr->info_element.id = MFIE_TYPE_SSID;
-
-	hdr->info_element.len = beacon->ssid_len;
-	tag = skb_put(skb, beacon->ssid_len);
-	memcpy(tag, beacon->ssid, beacon->ssid_len);
-
-	tag = skb_put(skb, rate_len);
-
-	ieee80211_MFIE_Brate(ieee, &tag);
-	ieee80211_MFIE_Grate(ieee, &tag);
-
-	/* add rsn==0 condition for ap's mix security mode(wpa+wpa2)
-	 * choose AES encryption as default algorithm while using mixed mode.
-	 */
-
-	tag = skb_put(skb, ieee->wpa_ie_len);
-	memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
-
-	tag = skb_put(skb, wmm_info_len);
-	if (wmm_info_len)
-	  ieee80211_WMM_Info(ieee, &tag);
-
-	tag = skb_put(skb, turbo_info_len);
-	if (turbo_info_len)
-		ieee80211_TURBO_Info(ieee, &tag);
-
-	return skb;
-}
-
-void ieee80211_associate_abort(struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	ieee->associate_seq++;
-
-	/* don't scan, and avoid to have the RX path possibly
-	 * try again to associate. Even do not react to AUTH or
-	 * ASSOC response. Just wait for the retry wq to be scheduled.
-	 * Here we will check if there are good nets to associate
-	 * with, so we retry or just get back to NO_LINK and scanning
-	 */
-	if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING) {
-		IEEE80211_DEBUG_MGMT("Authentication failed\n");
-		ieee->softmac_stats.no_auth_rs++;
-	} else {
-		IEEE80211_DEBUG_MGMT("Association failed\n");
-		ieee->softmac_stats.no_ass_rs++;
-	}
-
-	ieee->state = IEEE80211_ASSOCIATING_RETRY;
-
-	queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
-
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-static void ieee80211_associate_abort_cb(unsigned long dev)
-{
-	ieee80211_associate_abort((struct ieee80211_device *) dev);
-}
-
-static void ieee80211_associate_step1(struct ieee80211_device *ieee)
-{
-	struct ieee80211_network *beacon = &ieee->current_network;
-	struct sk_buff *skb;
-
-	IEEE80211_DEBUG_MGMT("Stopping scan\n");
-	ieee->softmac_stats.tx_auth_rq++;
-	skb = ieee80211_authentication_req(beacon, ieee, 0);
-	if (!skb) {
-		ieee80211_associate_abort(ieee);
-	} else {
-		ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING;
-		IEEE80211_DEBUG_MGMT("Sending authentication request\n");
-		softmac_mgmt_xmit(skb, ieee);
-		/* BUGON when you try to add_timer twice, using mod_timer may
-		 * be better.
-		 */
-		if (!timer_pending(&ieee->associate_timer)) {
-			ieee->associate_timer.expires = jiffies + (HZ / 2);
-			add_timer(&ieee->associate_timer);
-		}
-		/* If call dev_kfree_skb_any,a warning will ocur....
-		 * KERNEL: assertion (!atomic_read(&skb->users)) failed at
-		 * net/core/dev.c (1708)
-		 */
-	}
-}
-
-static void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge,
-				  int chlen)
-{
-	u8 *c;
-	struct sk_buff *skb;
-	struct ieee80211_network *beacon = &ieee->current_network;
-	del_timer_sync(&ieee->associate_timer);
-	ieee->associate_seq++;
-	ieee->softmac_stats.tx_auth_rq++;
-
-	skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
-	if (!skb)
-		ieee80211_associate_abort(ieee);
-	else {
-		c = skb_put(skb, chlen+2);
-		*(c++) = MFIE_TYPE_CHALLENGE;
-		*(c++) = chlen;
-		memcpy(c, challenge, chlen);
-
-		IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
-
-		ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr));
-
-		softmac_mgmt_xmit(skb, ieee);
-		if (!timer_pending(&ieee->associate_timer)) {
-		ieee->associate_timer.expires = jiffies + (HZ / 2);
-		add_timer(&ieee->associate_timer);
-		}
-		dev_kfree_skb_any(skb);
-	}
-	kfree(challenge);
-}
-
-static void ieee80211_associate_step2(struct ieee80211_device *ieee)
-{
-	struct sk_buff *skb;
-	struct ieee80211_network *beacon = &ieee->current_network;
-
-	del_timer_sync(&ieee->associate_timer);
-
-	IEEE80211_DEBUG_MGMT("Sending association request\n");
-	ieee->softmac_stats.tx_ass_rq++;
-	skb = ieee80211_association_req(beacon, ieee);
-	if (!skb)
-		ieee80211_associate_abort(ieee);
-	else {
-		softmac_mgmt_xmit(skb, ieee);
-		if (!timer_pending(&ieee->associate_timer)) {
-		ieee->associate_timer.expires = jiffies + (HZ / 2);
-		add_timer(&ieee->associate_timer);
-		}
-	}
-}
-
-static void ieee80211_associate_complete_wq(struct work_struct *work)
-{
-	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
-
-	printk(KERN_INFO "Associated successfully\n");
-	if (ieee80211_is_54g(&ieee->current_network) &&
-		(ieee->modulation & IEEE80211_OFDM_MODULATION)) {
-		ieee->rate = 540;
-		printk(KERN_INFO"Using G rates\n");
-	} else {
-		ieee->rate = 110;
-		printk(KERN_INFO"Using B rates\n");
-	}
-	ieee->link_change(ieee->dev);
-	notify_wx_assoc_event(ieee);
-	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
-	netif_carrier_on(ieee->dev);
-}
-
-static void ieee80211_associate_complete(struct ieee80211_device *ieee)
-{
-	del_timer_sync(&ieee->associate_timer);
-
-	ieee->state = IEEE80211_LINKED;
-	IEEE80211_DEBUG_MGMT("Successfully associated\n");
-
-	queue_work(ieee->wq, &ieee->associate_complete_wq);
-}
-
-static void ieee80211_associate_procedure_wq(struct work_struct *work)
-{
-	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
-
-	ieee->sync_scan_hurryup = 1;
-	down(&ieee->wx_sem);
-
-	if (ieee->data_hard_stop)
-		ieee->data_hard_stop(ieee->dev);
-
-	ieee80211_stop_scan(ieee);
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
-	ieee->associate_seq = 1;
-	ieee80211_associate_step1(ieee);
-
-	up(&ieee->wx_sem);
-}
-
-inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee,
-				      struct ieee80211_network *net)
-{
-	u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
-	int tmp_ssid_len = 0;
-
-	short apset, ssidset, ssidbroad, apmatch, ssidmatch;
-
-	/* we are interested in new new only if we are not associated
-	 * and we are not associating / authenticating
-	 */
-	if (ieee->state != IEEE80211_NOLINK)
-		return;
-
-	if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
-		return;
-
-	if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
-		return;
-
-	if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
-		/* if the user specified the AP MAC, we need also the essid
-		 * This could be obtained by beacons or, if the network does not
-		 * broadcast it, it can be put manually.
-		 */
-		apset = ieee->wap_set;
-		ssidset = ieee->ssid_set;
-		ssidbroad =  !(net->ssid_len == 0 || net->ssid[0] == '\0');
-		apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN) == 0);
-
-		if (ieee->current_network.ssid_len != net->ssid_len)
-			ssidmatch = 0;
-		else
-			ssidmatch = (0 == strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
-
-		/* if the user set the AP check if match.
-		 * if the network does not broadcast essid we check the user
-		 * supplied ANY essid
-		 * if the network does broadcast and the user does not set essid
-		 * it is OK
-		 * if the network does broadcast and the user did set essid
-		 * chech if essid match
-		 * (apset && apmatch && ((ssidset && ssidbroad && ssidmatch) ||
-		 *  (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) ||
-		 * if the ap is not set, check that the user set the bssid and
-		 * the network does broadcast and that those two bssid matches
-		 * (!apset && ssidset && ssidbroad && ssidmatch)
-		 */
-		if ((apset && apmatch && ((ssidset && ssidbroad && ssidmatch) ||
-		     (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) ||
-		    (!apset && ssidset && ssidbroad && ssidmatch)) {
-			/* if the essid is hidden replace it with the
-			 * essid provided by the user.
-			 */
-			if (!ssidbroad) {
-				strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
-				tmp_ssid_len = ieee->current_network.ssid_len;
-			}
-			memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
-
-			if (!ssidbroad) {
-				strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
-				ieee->current_network.ssid_len = tmp_ssid_len;
-			}
-			printk(KERN_INFO"Linking with %s: channel is %d\n", ieee->current_network.ssid, ieee->current_network.channel);
-
-			if (ieee->iw_mode == IW_MODE_INFRA) {
-				ieee->state = IEEE80211_ASSOCIATING;
-				ieee->beinretry = false;
-				queue_work(ieee->wq, &ieee->associate_procedure_wq);
-			} else {
-				if (ieee80211_is_54g(&ieee->current_network) &&
-						(ieee->modulation & IEEE80211_OFDM_MODULATION)) {
-					ieee->rate = 540;
-					printk(KERN_INFO"Using G rates\n");
-				} else {
-					ieee->rate = 110;
-					printk(KERN_INFO"Using B rates\n");
-				}
-				ieee->state = IEEE80211_LINKED;
-				ieee->beinretry = false;
-			}
-		}
-	}
-}
-
-void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-	struct ieee80211_network *target;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-	list_for_each_entry(target, &ieee->network_list, list) {
-		/* if the state become different that NOLINK means
-		 * we had found what we are searching for
-		 */
-		if (ieee->state != IEEE80211_NOLINK)
-			break;
-
-		if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
-			ieee80211_softmac_new_net(ieee, target);
-	}
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
-{
-	struct ieee80211_authentication *a;
-	u8 *t;
-	if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
-		IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
-		return 0xcafe;
-	}
-	*challenge = NULL;
-	a = (struct ieee80211_authentication *) skb->data;
-	if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
-		t = skb->data + sizeof(struct ieee80211_authentication);
-
-		if (*(t++) == MFIE_TYPE_CHALLENGE) {
-			*chlen = *(t++);
-			*challenge = kmemdup(t, *chlen, GFP_ATOMIC);
-			if (!*challenge)
-				return -ENOMEM;
-		}
-	}
-	return cpu_to_le16(a->status);
-}
-
-static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
-{
-	struct ieee80211_authentication *a;
-
-	if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
-		IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n", skb->len);
-		return -1;
-	}
-	a = (struct ieee80211_authentication *) skb->data;
-
-	memcpy(dest, a->header.addr2, ETH_ALEN);
-
-	if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
-		return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
-
-	return WLAN_STATUS_SUCCESS;
-}
-
-static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb,
-			    u8 *src)
-{
-	u8 *tag;
-	u8 *skbend;
-	u8 *ssid = NULL;
-	u8 ssidlen = 0;
-
-	struct ieee80211_hdr_3addr   *header =
-		(struct ieee80211_hdr_3addr   *) skb->data;
-
-	if (skb->len < sizeof(struct ieee80211_hdr_3addr))
-		return -1; /* corrupted */
-
-	memcpy(src, header->addr2, ETH_ALEN);
-
-	skbend = (u8 *)skb->data + skb->len;
-
-	tag = skb->data + sizeof(struct ieee80211_hdr_3addr);
-
-	while (tag+1 < skbend) {
-		if (*tag == 0) {
-			ssid = tag+2;
-			ssidlen = *(tag+1);
-			break;
-		}
-		tag++; /* point to the len field */
-		tag = tag + *(tag); /* point to the last data byte of the tag */
-		tag++; /* point to the next tag */
-	}
-
-	if (ssidlen == 0)
-		return 1;
-
-	if (!ssid)
-		 return 1; /* ssid not found in tagged param */
-
-	return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
-
-}
-
-static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
-{
-	struct ieee80211_assoc_request_frame *a;
-
-	if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
-		sizeof(struct ieee80211_info_element))) {
-
-		IEEE80211_DEBUG_MGMT("invalid len in auth request:%d\n", skb->len);
-		return -1;
-	}
-
-	a = (struct ieee80211_assoc_request_frame *) skb->data;
-
-	memcpy(dest, a->header.addr2, ETH_ALEN);
-
-	return 0;
-}
-
-static inline u16 assoc_parse(struct sk_buff *skb, int *aid)
-{
-	struct ieee80211_assoc_response_frame *a;
-	if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
-		IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
-		return 0xcafe;
-	}
-
-	a = (struct ieee80211_assoc_response_frame *) skb->data;
-	*aid = le16_to_cpu(a->aid) & 0x3fff;
-	return le16_to_cpu(a->status);
-}
-
-static inline void ieee80211_rx_probe_rq(struct ieee80211_device *ieee,
-					 struct sk_buff *skb)
-{
-	u8 dest[ETH_ALEN];
-
-	ieee->softmac_stats.rx_probe_rq++;
-	if (probe_rq_parse(ieee, skb, dest)) {
-		ieee->softmac_stats.tx_probe_rs++;
-		ieee80211_resp_to_probe(ieee, dest);
-	}
-}
-
-inline void ieee80211_rx_auth_rq(struct ieee80211_device *ieee,
-				 struct sk_buff *skb)
-{
-	u8 dest[ETH_ALEN];
-	int status;
-	ieee->softmac_stats.rx_auth_rq++;
-
-	status = auth_rq_parse(skb, dest);
-	if (status != -1)
-		ieee80211_resp_to_auth(ieee, status, dest);
-}
-
-inline void
-ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
-{
-
-	u8 dest[ETH_ALEN];
-
-	ieee->softmac_stats.rx_ass_rq++;
-	if (assoc_rq_parse(skb, dest) != -1)
-		ieee80211_resp_to_assoc_rq(ieee, dest);
-
-
-	printk(KERN_INFO"New client associated: %pM\n", dest);
-}
-
-void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
-{
-	struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
-
-	if (buf)
-		softmac_ps_mgmt_xmit(buf, ieee);
-}
-
-static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
-			     u32 *time_l)
-{
-	int timeout = 0;
-
-	u8 dtim;
-	dtim = ieee->current_network.dtim_data;
-
-	if (!(dtim & IEEE80211_DTIM_VALID))
-		return 0;
-	else
-		timeout = ieee->current_network.beacon_interval;
-
-	ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
-
-	if (dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST) & ieee->ps))
-		return 2;
-
-	if (!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
-		return 0;
-
-	if (!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
-		return 0;
-
-	if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) &&
-		(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
-		return 0;
-
-	if (time_l) {
-		*time_l = ieee->current_network.last_dtim_sta_time[0]
-			+ MSECS((ieee->current_network.beacon_interval));
-	}
-
-	if (time_h) {
-		*time_h = ieee->current_network.last_dtim_sta_time[1];
-		if (time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
-			*time_h += 1;
-	}
-
-	return 1;
-}
-
-static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
-{
-
-	u32 th, tl;
-	short sleep;
-
-	unsigned long flags, flags2;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if ((ieee->ps == IEEE80211_PS_DISABLED ||
-		ieee->iw_mode != IW_MODE_INFRA ||
-		ieee->state != IEEE80211_LINKED)) {
-
-		/* #warning CHECK_LOCK_HERE */
-		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-
-		ieee80211_sta_wakeup(ieee, 1);
-
-		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
-	}
-
-	sleep = ieee80211_sta_ps_sleep(ieee, &th, &tl);
-	/* 2 wake, 1 sleep, 0 do nothing */
-	if (sleep == 0)
-		goto out;
-
-	if (sleep == 1) {
-		if (ieee->sta_sleep == 1)
-			ieee->enter_sleep_state(ieee->dev, th, tl);
-
-		else if (ieee->sta_sleep == 0) {
-			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-			if (ieee->ps_is_queue_empty(ieee->dev)) {
-				ieee->sta_sleep = 2;
-
-				ieee->ps_request_tx_ack(ieee->dev);
-
-				ieee80211_sta_ps_send_null_frame(ieee, 1);
-
-				ieee->ps_th = th;
-				ieee->ps_tl = tl;
-			}
-			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
-		}
-	} else if (sleep == 2) {
-		/* #warning CHECK_LOCK_HERE */
-		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-
-		ieee80211_sta_wakeup(ieee, 1);
-
-		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
-	}
-out:
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
-{
-	if (ieee->sta_sleep == 0) {
-		if (nl) {
-			ieee->ps_request_tx_ack(ieee->dev);
-			ieee80211_sta_ps_send_null_frame(ieee, 0);
-		}
-		return;
-	}
-
-	if (ieee->sta_sleep == 1)
-		ieee->sta_wake_up(ieee->dev);
-
-	ieee->sta_sleep = 0;
-
-	if (nl) {
-		ieee->ps_request_tx_ack(ieee->dev);
-		ieee80211_sta_ps_send_null_frame(ieee, 0);
-	}
-}
-
-void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
-{
-	unsigned long flags, flags2;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-	if (ieee->sta_sleep == 2) {
-		/* Null frame with PS bit set */
-		if (success) {
-			ieee->sta_sleep = 1;
-			ieee->enter_sleep_state(ieee->dev, ieee->ps_th, ieee->ps_tl);
-		}
-		/* if the card report not success we can't be sure the AP
-		 * has not RXed so we can't assume the AP believe us awake
-		 */
-	} else {
-		if ((ieee->sta_sleep == 0) && !success) {
-			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-			ieee80211_sta_ps_send_null_frame(ieee, 0);
-			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
-		}
-	}
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-inline int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee,
-				      struct sk_buff *skb,
-				      struct ieee80211_rx_stats *rx_stats,
-				      u16 type,	u16 stype)
-{
-	struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
-	u16 errcode;
-	u8 *challenge = NULL;
-	int chlen = 0;
-	int aid = 0;
-	struct ieee80211_assoc_response_frame *assoc_resp;
-	struct ieee80211_info_element *info_element;
-
-	if (!ieee->proto_started)
-		return 0;
-
-	if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
-		ieee->iw_mode == IW_MODE_INFRA &&
-		ieee->state == IEEE80211_LINKED))
-
-		tasklet_schedule(&ieee->ps_task);
-
-	if (WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_PROBE_RESP &&
-		WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_BEACON)
-		ieee->last_rx_ps_time = jiffies;
-
-	switch (WLAN_FC_GET_STYPE(header->frame_control)) {
-		case IEEE80211_STYPE_ASSOC_RESP:
-		case IEEE80211_STYPE_REASSOC_RESP:
-			IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
-					WLAN_FC_GET_STYPE(header->frame_ctl));
-			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
-				ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
-				ieee->iw_mode == IW_MODE_INFRA) {
-				errcode = assoc_parse(skb, &aid);
-				if (0 == errcode) {
-					u16 left;
-
-					ieee->state = IEEE80211_LINKED;
-					ieee->assoc_id = aid;
-					ieee->softmac_stats.rx_ass_ok++;
-					/* card type is 8187 */
-					if (1 == rx_stats->nic_type)
-						goto associate_complete;
-
-					assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
-					info_element = &assoc_resp->info_element;
-					left = skb->len - ((void *)info_element - (void *)assoc_resp);
-
-					while (left >= sizeof(struct ieee80211_info_element_hdr)) {
-						if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
-							printk(KERN_WARNING "[re]associate response error!");
-							return 1;
-						}
-						switch (info_element->id) {
-						  case MFIE_TYPE_GENERIC:
-							IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", info_element->len);
-							if (info_element->len >= 8  &&
-							    info_element->data[0] == 0x00 &&
-							    info_element->data[1] == 0x50 &&
-							    info_element->data[2] == 0xf2 &&
-							    info_element->data[3] == 0x02 &&
-							    info_element->data[4] == 0x01) {
-								/* Not care about version at present.
-								 * WMM Parameter Element.
-								 */
-								memcpy(ieee->current_network.wmm_param, (u8 *)(info_element->data\
-									+ 8), (info_element->len - 8));
-
-								if (((ieee->current_network.wmm_info^info_element->data[6])& \
-										    0x0f) || (!ieee->init_wmmparam_flag)) {
-									/* refresh parameter element for current network
-									 * update the register parameter for hardware.
-									 */
-									ieee->init_wmmparam_flag = 1;
-									queue_work(ieee->wq, &ieee->wmm_param_update_wq);
-								}
-								/* update info_element for current network */
-								ieee->current_network.wmm_info  = info_element->data[6];
-							}
-							break;
-						  default:
-							/* nothing to do at present!!! */
-							break;
-						}
-
-						left -= sizeof(struct ieee80211_info_element_hdr) +
-							info_element->len;
-						info_element = (struct ieee80211_info_element *)
-							&info_element->data[info_element->len];
-					}
-					/* legacy AP, reset the AC_xx_param register */
-					if (!ieee->init_wmmparam_flag) {
-						queue_work(ieee->wq, &ieee->wmm_param_update_wq);
-						ieee->init_wmmparam_flag = 1; /* indicate AC_xx_param upated since last associate */
-					}
-associate_complete:
-					ieee80211_associate_complete(ieee);
-				} else {
-					ieee->softmac_stats.rx_ass_err++;
-					IEEE80211_DEBUG_MGMT(
-						"Association response status code 0x%x\n",
-						errcode);
-					ieee80211_associate_abort(ieee);
-				}
-			}
-			break;
-		case IEEE80211_STYPE_ASSOC_REQ:
-		case IEEE80211_STYPE_REASSOC_REQ:
-			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
-				ieee->iw_mode == IW_MODE_MASTER)
-
-				ieee80211_rx_assoc_rq(ieee, skb);
-			break;
-		case IEEE80211_STYPE_AUTH:
-			if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
-				if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
-				ieee->iw_mode == IW_MODE_INFRA){
-						IEEE80211_DEBUG_MGMT("Received authentication response");
-
-						errcode = auth_parse(skb, &challenge, &chlen);
-						if (0 == errcode) {
-							if (ieee->open_wep || !challenge) {
-								ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
-								ieee->softmac_stats.rx_auth_rs_ok++;
-
-								ieee80211_associate_step2(ieee);
-							} else {
-								ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
-							}
-						} else {
-							ieee->softmac_stats.rx_auth_rs_err++;
-							IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x", errcode);
-							ieee80211_associate_abort(ieee);
-						}
-
-					} else if (ieee->iw_mode == IW_MODE_MASTER) {
-						ieee80211_rx_auth_rq(ieee, skb);
-					}
-				}
-			break;
-		case IEEE80211_STYPE_PROBE_REQ:
-			if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
-				((ieee->iw_mode == IW_MODE_ADHOC ||
-				ieee->iw_mode == IW_MODE_MASTER) &&
-				ieee->state == IEEE80211_LINKED))
-
-				ieee80211_rx_probe_rq(ieee, skb);
-			break;
-		case IEEE80211_STYPE_DISASSOC:
-		case IEEE80211_STYPE_DEAUTH:
-			/* FIXME for now repeat all the association procedure
-			 * both for disassociation and deauthentication
-			 */
-			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
-				(ieee->state == IEEE80211_LINKED) &&
-				(ieee->iw_mode == IW_MODE_INFRA) &&
-				(!memcmp(header->addr2, ieee->current_network.bssid, ETH_ALEN))) {
-				ieee->state = IEEE80211_ASSOCIATING;
-				ieee->softmac_stats.reassoc++;
-
-				queue_work(ieee->wq, &ieee->associate_procedure_wq);
-			}
-			break;
-		default:
-			return -1;
-			break;
-	}
-	return 0;
-}
-
-/* following are for a simpler TX queue management.
- * Instead of using netif_[stop/wake]_queue the driver
- * will uses these two function (plus a reset one), that
- * will internally uses the kernel netif_* and takes
- * care of the ieee802.11 fragmentation.
- * So the driver receives a fragment per time and might
- * call the stop function when it want without take care
- * to have enough room to TX an entire packet.
- * This might be useful if each fragment need it's own
- * descriptor, thus just keep a total free memory > than
- * the max fragmentation threshold is not enough.. If the
- * ieee802.11 stack passed a TXB struct then you needed
- * to keep N free descriptors where
- * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
- * In this way you need just one and the 802.11 stack
- * will take care of buffering fragments and pass them to
- * to the driver later, when it wakes the queue.
- */
-
-void ieee80211_softmac_xmit(struct ieee80211_txb *txb,
-			    struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-	int  i;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	/* called with 2nd parm 0, no tx mgmt lock required */
-	ieee80211_sta_wakeup(ieee, 0);
-
-	for (i = 0; i < txb->nr_frags; i++) {
-		if (ieee->queue_stop) {
-			ieee->tx_pending.txb = txb;
-			ieee->tx_pending.frag = i;
-			goto exit;
-		} else {
-			ieee->softmac_data_hard_start_xmit(
-				txb->fragments[i],
-				ieee->dev, ieee->rate);
-			ieee->stats.tx_packets++;
-			ieee->stats.tx_bytes += txb->fragments[i]->len;
-			ieee->dev->trans_start = jiffies;
-		}
-	}
-
-	ieee80211_txb_free(txb);
-
-	exit:
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-/* called with ieee->lock acquired */
-static void ieee80211_resume_tx(struct ieee80211_device *ieee)
-{
-	int i;
-	for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
-
-		if (ieee->queue_stop) {
-			ieee->tx_pending.frag = i;
-			return;
-		} else {
-			ieee->softmac_data_hard_start_xmit(
-				ieee->tx_pending.txb->fragments[i],
-				ieee->dev, ieee->rate);
-			ieee->stats.tx_packets++;
-			ieee->dev->trans_start = jiffies;
-		}
-	}
-
-	ieee80211_txb_free(ieee->tx_pending.txb);
-	ieee->tx_pending.txb = NULL;
-}
-
-void ieee80211_reset_queue(struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-	init_mgmt_queue(ieee);
-	if (ieee->tx_pending.txb) {
-		ieee80211_txb_free(ieee->tx_pending.txb);
-		ieee->tx_pending.txb = NULL;
-	}
-	ieee->queue_stop = 0;
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-	struct sk_buff *skb;
-	struct ieee80211_hdr_3addr  *header;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-	if (!ieee->queue_stop)
-		goto exit;
-
-	ieee->queue_stop = 0;
-
-	if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
-		while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) {
-			header = (struct ieee80211_hdr_3addr  *) skb->data;
-
-			header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
-			if (ieee->seq_ctrl[0] == 0xFFF)
-				ieee->seq_ctrl[0] = 0;
-			else
-				ieee->seq_ctrl[0]++;
-
-			ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
-			dev_kfree_skb_any(skb);
-		}
-	}
-	if (!ieee->queue_stop && ieee->tx_pending.txb)
-		ieee80211_resume_tx(ieee);
-
-	if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
-		ieee->softmac_stats.swtxawake++;
-		netif_wake_queue(ieee->dev);
-	}
-exit:
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
-{
-	if (!netif_queue_stopped(ieee->dev)) {
-		netif_stop_queue(ieee->dev);
-		ieee->softmac_stats.swtxstop++;
-	}
-	ieee->queue_stop = 1;
-}
-
-inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
-{
-	random_ether_addr(ieee->current_network.bssid);
-}
-
-/* called in user context only */
-void ieee80211_start_master_bss(struct ieee80211_device *ieee)
-{
-	ieee->assoc_id = 1;
-
-	if (ieee->current_network.ssid_len == 0) {
-		strncpy(ieee->current_network.ssid,
-			IEEE80211_DEFAULT_TX_ESSID,
-			IW_ESSID_MAX_SIZE);
-
-		ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
-		ieee->ssid_set = 1;
-	}
-
-	memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
-
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
-	ieee->state = IEEE80211_LINKED;
-	ieee->link_change(ieee->dev);
-	notify_wx_assoc_event(ieee);
-
-	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
-
-	netif_carrier_on(ieee->dev);
-}
-
-static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
-{
-	if (ieee->raw_tx) {
-
-		if (ieee->data_hard_resume)
-			ieee->data_hard_resume(ieee->dev);
-
-		netif_carrier_on(ieee->dev);
-	}
-}
-
-static void ieee80211_start_ibss_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
-
-	/* iwconfig mode ad-hoc will schedule this and return
-	 * on the other hand this will block further iwconfig SET
-	 * operations because of the wx_sem hold.
-	 * Anyway some most set operations set a flag to speed-up
-	 * (abort) this wq (when syncro scanning) before sleeping
-	 * on the semaphore
-	 */
-
-	down(&ieee->wx_sem);
-
-	if (ieee->current_network.ssid_len == 0) {
-		strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
-		ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
-		ieee->ssid_set = 1;
-	}
-
-	/* check if we have this cell in our network list */
-	ieee80211_softmac_check_all_nets(ieee);
-
-	if (ieee->state == IEEE80211_NOLINK)
-		ieee->current_network.channel = 10;
-	/* if not then the state is not linked. Maybe the user switched to
-	 * ad-hoc mode just after being in monitor mode, or just after
-	 * being very few time in managed mode (so the card have had no
-	 * time to scan all the chans..) or we have just run up the iface
-	 * after setting ad-hoc mode. So we have to give another try..
-	 * Here, in ibss mode, should be safe to do this without extra care
-	 * (in bss mode we had to make sure no-one tried to associate when
-	 * we had just checked the ieee->state and we was going to start the
-	 * scan) because in ibss mode the ieee80211_new_net function, when
-	 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
-	 * so, at worst, we waste a bit of time to initiate an unneeded syncro
-	 * scan, that will stop at the first round because it sees the state
-	 * associated.
-	 */
-	if (ieee->state == IEEE80211_NOLINK)
-		ieee80211_start_scan_syncro(ieee);
-
-	/* the network definitively is not here.. create a new cell */
-	if (ieee->state == IEEE80211_NOLINK) {
-		printk("creating new IBSS cell\n");
-		if (!ieee->wap_set)
-			ieee80211_randomize_cell(ieee);
-
-		if (ieee->modulation & IEEE80211_CCK_MODULATION) {
-			ieee->current_network.rates_len = 4;
-
-			ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
-			ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
-			ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
-			ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
-
-		} else
-			ieee->current_network.rates_len = 0;
-
-		if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-			ieee->current_network.rates_ex_len = 8;
-
-			ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
-			ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
-			ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
-			ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
-			ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
-			ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
-			ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
-			ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
-
-			ieee->rate = 540;
-		} else {
-			ieee->current_network.rates_ex_len = 0;
-			ieee->rate = 110;
-		}
-
-		/* By default, WMM function will be disabled in IBSS mode */
-		ieee->current_network.QoS_Enable = 0;
-
-		ieee->current_network.atim_window = 0;
-		ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
-		if (ieee->short_slot)
-			ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
-	}
-
-	ieee->state = IEEE80211_LINKED;
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
-	ieee->link_change(ieee->dev);
-
-	notify_wx_assoc_event(ieee);
-
-	ieee80211_start_send_beacons(ieee);
-	printk(KERN_WARNING "after sending beacon packet!\n");
-
-	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
-
-	netif_carrier_on(ieee->dev);
-
-	up(&ieee->wx_sem);
-}
-
-inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
-{
-	queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 100);
-}
-
-/* this is called only in user context, with wx_sem held */
-void ieee80211_start_bss(struct ieee80211_device *ieee)
-{
-	unsigned long flags;
-	/* Ref: 802.11d 11.1.3.3
-	 * STA shall not start a BSS unless properly formed Beacon frame
-	 * including a Country IE.
-	 */
-	if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
-		if (!ieee->bGlobalDomain)
-			return;
-	}
-	/* check if we have already found the net we are interested in (if any).
-	 * if not (we are disassociated and we are not
-	 * in associating / authenticating phase) start the background scanning.
-	 */
-	ieee80211_softmac_check_all_nets(ieee);
-
-	/* ensure no-one start an associating process (thus setting
-	 * the ieee->state to ieee80211_ASSOCIATING) while we
-	 * have just cheked it and we are going to enable scan.
-	 * The ieee80211_new_net function is always called with
-	 * lock held (from both ieee80211_softmac_check_all_nets and
-	 * the rx path), so we cannot be in the middle of such function
-	 */
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if (ieee->state == IEEE80211_NOLINK) {
-		ieee->actscanning = true;
-		ieee80211_rtl_start_scan(ieee);
-	}
-	spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-/* called only in userspace context */
-void ieee80211_disassociate(struct ieee80211_device *ieee)
-{
-	netif_carrier_off(ieee->dev);
-
-	if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
-			ieee80211_reset_queue(ieee);
-
-	if (ieee->data_hard_stop)
-			ieee->data_hard_stop(ieee->dev);
-
-	if (IS_DOT11D_ENABLE(ieee))
-		Dot11d_Reset(ieee);
-
-	ieee->link_change(ieee->dev);
-	if (ieee->state == IEEE80211_LINKED)
-		notify_wx_assoc_event(ieee);
-	ieee->state = IEEE80211_NOLINK;
-
-}
-static void ieee80211_associate_retry_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
-	unsigned long flags;
-	down(&ieee->wx_sem);
-	if (!ieee->proto_started)
-		goto exit;
-	if (ieee->state != IEEE80211_ASSOCIATING_RETRY)
-		goto exit;
-	/* until we do not set the state to IEEE80211_NOLINK
-	* there are no possibility to have someone else trying
-	* to start an association procedure (we get here with
-	* ieee->state = IEEE80211_ASSOCIATING).
-	* When we set the state to IEEE80211_NOLINK it is possible
-	* that the RX path run an attempt to associate, but
-	* both ieee80211_softmac_check_all_nets and the
-	* RX path works with ieee->lock held so there are no
-	* problems. If we are still disassociated then start a scan.
-	* the lock here is necessary to ensure no one try to start
-	* an association procedure when we have just checked the
-	* state and we are going to start the scan.
-	*/
-	ieee->state = IEEE80211_NOLINK;
-	ieee->beinretry = true;
-	ieee80211_softmac_check_all_nets(ieee);
-
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if (ieee->state == IEEE80211_NOLINK) {
-		ieee->beinretry = false;
-		ieee->actscanning = true;
-		ieee80211_rtl_start_scan(ieee);
-	}
-	if (ieee->state == IEEE80211_NOLINK)
-		notify_wx_assoc_event(ieee);
-	spin_unlock_irqrestore(&ieee->lock, flags);
-
-exit:
-	up(&ieee->wx_sem);
-}
-
-struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
-{
-	u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-	struct sk_buff *skb = NULL;
-	struct ieee80211_probe_response *b;
-
-	skb = ieee80211_probe_resp(ieee, broadcast_addr);
-	if (!skb)
-		return NULL;
-
-	b = (struct ieee80211_probe_response *) skb->data;
-	b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
-
-	return skb;
-}
-
-struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
-{
-	struct sk_buff *skb;
-	struct ieee80211_probe_response *b;
-
-	skb = ieee80211_get_beacon_(ieee);
-	if (!skb)
-		return NULL;
-
-	b = (struct ieee80211_probe_response *) skb->data;
-	b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
-	if (ieee->seq_ctrl[0] == 0xFFF)
-		ieee->seq_ctrl[0] = 0;
-	else
-		ieee->seq_ctrl[0]++;
-
-	return skb;
-}
-
-void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
-{
-	ieee->sync_scan_hurryup = 1;
-	down(&ieee->wx_sem);
-	ieee80211_stop_protocol(ieee);
-	up(&ieee->wx_sem);
-}
-
-void ieee80211_stop_protocol(struct ieee80211_device *ieee)
-{
-	if (!ieee->proto_started)
-		return;
-
-	ieee->proto_started = 0;
-
-	ieee80211_stop_send_beacons(ieee);
-	if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_LINKED))
-		SendDisassociation(ieee, NULL, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
-
-	del_timer_sync(&ieee->associate_timer);
-	cancel_delayed_work(&ieee->associate_retry_wq);
-	cancel_delayed_work(&ieee->start_ibss_wq);
-	ieee80211_stop_scan(ieee);
-
-	ieee80211_disassociate(ieee);
-}
-
-void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
-{
-	ieee->sync_scan_hurryup = 0;
-	down(&ieee->wx_sem);
-	ieee80211_start_protocol(ieee);
-	up(&ieee->wx_sem);
-}
-
-void ieee80211_start_protocol(struct ieee80211_device *ieee)
-{
-	short ch = 0;
-	int i = 0;
-
-	if (ieee->proto_started)
-		return;
-
-	ieee->proto_started = 1;
-
-	if (ieee->current_network.channel == 0) {
-		do {
-			ch++;
-			if (ch > MAX_CHANNEL_NUMBER)
-				return; /* no channel found */
-
-		} while (!GET_DOT11D_INFO(ieee)->channel_map[ch]);
-
-		ieee->current_network.channel = ch;
-	}
-
-	if (ieee->current_network.beacon_interval == 0)
-		ieee->current_network.beacon_interval = 100;
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
-	for (i = 0; i < 17; i++) {
-		ieee->last_rxseq_num[i] = -1;
-		ieee->last_rxfrag_num[i] = -1;
-		ieee->last_packet_time[i] = 0;
-	}
-
-	ieee->init_wmmparam_flag = 0; /* reinitialize AC_xx_PARAM registers. */
-
-	/* if the user set the MAC of the ad-hoc cell and then
-	 * switch to managed mode, shall we  make sure that association
-	 * attempts does not fail just because the user provide the essid
-	 * and the nic is still checking for the AP MAC ??
-	 */
-	switch (ieee->iw_mode) {
-		case IW_MODE_AUTO:
-			ieee->iw_mode = IW_MODE_INFRA;
-			/* not set break here intentionly */
-		case IW_MODE_INFRA:
-			ieee80211_start_bss(ieee);
-			break;
-
-		case IW_MODE_ADHOC:
-			ieee80211_start_ibss(ieee);
-			break;
-
-		case IW_MODE_MASTER:
-			ieee80211_start_master_bss(ieee);
-		break;
-
-		case IW_MODE_MONITOR:
-			ieee80211_start_monitor_mode(ieee);
-			break;
-
-		default:
-			ieee->iw_mode = IW_MODE_INFRA;
-			ieee80211_start_bss(ieee);
-			break;
-	}
-}
-
-#define DRV_NAME  "Ieee80211"
-void ieee80211_softmac_init(struct ieee80211_device *ieee)
-{
-	int i;
-	memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
-
-	ieee->state = IEEE80211_NOLINK;
-	ieee->sync_scan_hurryup = 0;
-	for (i = 0; i < 5; i++)
-		ieee->seq_ctrl[i] = 0;
-
-	ieee->assoc_id = 0;
-	ieee->queue_stop = 0;
-	ieee->scanning = 0;
-	ieee->softmac_features = 0; /* so IEEE2100-like driver are happy */
-	ieee->wap_set = 0;
-	ieee->ssid_set = 0;
-	ieee->proto_started = 0;
-	ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
-	ieee->rate = 3;
-	ieee->ps = IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST;
-	ieee->sta_sleep = 0;
-	ieee->bInactivePs = false;
-	ieee->actscanning = false;
-	ieee->ListenInterval = 2;
-	ieee->NumRxDataInPeriod = 0;
-	ieee->NumRxBcnInPeriod = 0;
-	ieee->NumRxOkTotal = 0;
-	ieee->NumRxUnicast = 0; /* for keep alive */
-	ieee->beinretry = false;
-	ieee->bHwRadioOff = false;
-
-	init_mgmt_queue(ieee);
-
-	ieee->tx_pending.txb = NULL;
-
-	init_timer(&ieee->associate_timer);
-	ieee->associate_timer.data = (unsigned long)ieee;
-	ieee->associate_timer.function = ieee80211_associate_abort_cb;
-
-	init_timer(&ieee->beacon_timer);
-	ieee->beacon_timer.data = (unsigned long) ieee;
-	ieee->beacon_timer.function = ieee80211_send_beacon_cb;
-
-	ieee->wq = create_workqueue(DRV_NAME);
-
-	INIT_DELAYED_WORK(&ieee->start_ibss_wq, (void *) ieee80211_start_ibss_wq);
-	INIT_WORK(&ieee->associate_complete_wq, (void *) ieee80211_associate_complete_wq);
-	INIT_WORK(&ieee->associate_procedure_wq, (void *) ieee80211_associate_procedure_wq);
-	INIT_DELAYED_WORK(&ieee->softmac_scan_wq, (void *) ieee80211_softmac_scan_wq);
-	INIT_DELAYED_WORK(&ieee->associate_retry_wq, (void *) ieee80211_associate_retry_wq);
-	INIT_WORK(&ieee->wx_sync_scan_wq, (void *) ieee80211_wx_sync_scan_wq);
-
-	sema_init(&ieee->wx_sem, 1);
-	sema_init(&ieee->scan_sem, 1);
-
-	spin_lock_init(&ieee->mgmt_tx_lock);
-	spin_lock_init(&ieee->beacon_lock);
-
-	tasklet_init(&ieee->ps_task,
-	     (void(*)(unsigned long)) ieee80211_sta_ps,
-	     (unsigned long)ieee);
-	ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
-}
-
-void ieee80211_softmac_free(struct ieee80211_device *ieee)
-{
-	down(&ieee->wx_sem);
-
-	del_timer_sync(&ieee->associate_timer);
-	cancel_delayed_work(&ieee->associate_retry_wq);
-
-	/* add for RF power on power of */
-	cancel_delayed_work(&ieee->GPIOChangeRFWorkItem);
-
-	destroy_workqueue(ieee->wq);
-	kfree(ieee->pDot11dInfo);
-	up(&ieee->wx_sem);
-}
-
-/* Start of WPA code. This is stolen from the ipw2200 driver  */
-static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
-{
-	/* This is called when wpa_supplicant loads and closes the driver
-	 * interface. */
-	printk("%s WPA\n", value ? "enabling" : "disabling");
-	ieee->wpa_enabled = value;
-	return 0;
-}
-
-static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie,
-			       int wpa_ie_len)
-{
-	/* make sure WPA is enabled */
-	ieee80211_wpa_enable(ieee, 1);
-
-	ieee80211_disassociate(ieee);
-}
-
-static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command,
-			      int reason)
-{
-	int ret = 0;
-
-	switch (command) {
-	case IEEE_MLME_STA_DEAUTH:
-		/* silently ignore */
-		break;
-
-	case IEEE_MLME_STA_DISASSOC:
-		ieee80211_disassociate(ieee);
-		break;
-
-	default:
-		printk("Unknown MLME request: %d\n", command);
-		ret = -EOPNOTSUPP;
-	}
-
-	return ret;
-}
-
-static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
-				    struct ieee_param *param, int plen)
-{
-	u8 *buf;
-
-	if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
-	    (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
-		return -EINVAL;
-
-	if (param->u.wpa_ie.len) {
-		buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
-			      GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		kfree(ieee->wpa_ie);
-		ieee->wpa_ie = buf;
-		ieee->wpa_ie_len = param->u.wpa_ie.len;
-	} else {
-		kfree(ieee->wpa_ie);
-		ieee->wpa_ie = NULL;
-		ieee->wpa_ie_len = 0;
-	}
-
-	ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
-	return 0;
-}
-
-#define AUTH_ALG_OPEN_SYSTEM			0x1
-#define AUTH_ALG_SHARED_KEY			0x2
-
-static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
-{
-	struct ieee80211_security sec = {
-		.flags = SEC_AUTH_MODE,
-	};
-	int ret = 0;
-
-	if (value & AUTH_ALG_SHARED_KEY) {
-		sec.auth_mode = WLAN_AUTH_SHARED_KEY;
-		ieee->open_wep = 0;
-	} else {
-		sec.auth_mode = WLAN_AUTH_OPEN;
-		ieee->open_wep = 1;
-	}
-
-	if (ieee->set_security)
-		ieee->set_security(ieee->dev, &sec);
-	else
-		ret = -EOPNOTSUPP;
-
-	return ret;
-}
-
-static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name,
-				   u32 value)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	switch (name) {
-	case IEEE_PARAM_WPA_ENABLED:
-		ret = ieee80211_wpa_enable(ieee, value);
-		break;
-
-	case IEEE_PARAM_TKIP_COUNTERMEASURES:
-		ieee->tkip_countermeasures = value;
-		break;
-
-	case IEEE_PARAM_DROP_UNENCRYPTED: {
-		/* HACK:
-		 *
-		 * wpa_supplicant calls set_wpa_enabled when the driver
-		 * is loaded and unloaded, regardless of if WPA is being
-		 * used.  No other calls are made which can be used to
-		 * determine if encryption will be used or not prior to
-		 * association being expected.  If encryption is not being
-		 * used, drop_unencrypted is set to false, else true -- we
-		 * can use this to determine if the CAP_PRIVACY_ON bit should
-		 * be set.
-		 */
-		struct ieee80211_security sec = {
-			.flags = SEC_ENABLED,
-			.enabled = value,
-		};
-		ieee->drop_unencrypted = value;
-		/* We only change SEC_LEVEL for open mode. Others
-		 * are set by ipw_wpa_set_encryption.
-		 */
-		if (!value) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_0;
-		} else {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_1;
-		}
-		if (ieee->set_security)
-			ieee->set_security(ieee->dev, &sec);
-		break;
-	}
-
-	case IEEE_PARAM_PRIVACY_INVOKED:
-		ieee->privacy_invoked = value;
-		break;
-	case IEEE_PARAM_AUTH_ALGS:
-		ret = ieee80211_wpa_set_auth_algs(ieee, value);
-		break;
-	case IEEE_PARAM_IEEE_802_1X:
-		ieee->ieee802_1x = value;
-		break;
-	case IEEE_PARAM_WPAX_SELECT:
-		spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
-		ieee->wpax_type_set = 1;
-		ieee->wpax_type_notify = value;
-		spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
-		break;
-	default:
-		printk("Unknown WPA param: %d\n", name);
-		ret = -EOPNOTSUPP;
-	}
-
-	return ret;
-}
-
-/* implementation borrowed from hostap driver */
-
-static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
-					struct ieee_param *param, int param_len)
-{
-	int ret = 0;
-
-	struct ieee80211_crypto_ops *ops;
-	struct ieee80211_crypt_data **crypt;
-
-	struct ieee80211_security sec = {
-		.flags = 0,
-	};
-
-	param->u.crypt.err = 0;
-	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
-	if (param_len !=
-	    (int) ((char *) param->u.crypt.key - (char *) param) +
-	    param->u.crypt.key_len) {
-		printk("Len mismatch %d, %d\n", param_len,
-			       param->u.crypt.key_len);
-		return -EINVAL;
-	}
-	if (is_broadcast_ether_addr(param->sta_addr)) {
-		if (param->u.crypt.idx >= WEP_KEYS)
-			return -EINVAL;
-		crypt = &ieee->crypt[param->u.crypt.idx];
-	} else {
-		return -EINVAL;
-	}
-
-	if (strcmp(param->u.crypt.alg, "none") == 0) {
-		if (crypt) {
-			sec.enabled = 0;
-			/* FIXME FIXME */
-			sec.level = SEC_LEVEL_0;
-			sec.flags |= SEC_ENABLED | SEC_LEVEL;
-			ieee80211_crypt_delayed_deinit(ieee, crypt);
-		}
-		goto done;
-	}
-	sec.enabled = 1;
-	/* FIXME FIXME */
-	sec.flags |= SEC_ENABLED;
-
-	/* IPW HW cannot build TKIP MIC, host decryption still needed. */
-	if (!(ieee->host_encrypt || ieee->host_decrypt) &&
-	    strcmp(param->u.crypt.alg, "TKIP"))
-		goto skip_host_crypt;
-
-	ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
-		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
-		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
-		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-	if (ops == NULL) {
-		printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
-		param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (*crypt == NULL || (*crypt)->ops != ops) {
-		struct ieee80211_crypt_data *new_crypt;
-
-		ieee80211_crypt_delayed_deinit(ieee, crypt);
-
-		new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
-		if (new_crypt == NULL) {
-			ret = -ENOMEM;
-			goto done;
-		}
-		memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
-		new_crypt->ops = ops;
-		if (new_crypt->ops)
-			new_crypt->priv =
-				new_crypt->ops->init(param->u.crypt.idx);
-
-		if (new_crypt->priv == NULL) {
-			kfree(new_crypt);
-			param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
-			ret = -EINVAL;
-			goto done;
-		}
-
-		*crypt = new_crypt;
-	}
-
-	if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
-	    (*crypt)->ops->set_key(param->u.crypt.key,
-				   param->u.crypt.key_len, param->u.crypt.seq,
-				   (*crypt)->priv) < 0) {
-		printk("key setting failed\n");
-		param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
-		ret = -EINVAL;
-		goto done;
-	}
-
- skip_host_crypt:
-	if (param->u.crypt.set_tx) {
-		ieee->tx_keyidx = param->u.crypt.idx;
-		sec.active_key = param->u.crypt.idx;
-		sec.flags |= SEC_ACTIVE_KEY;
-	} else
-		sec.flags &= ~SEC_ACTIVE_KEY;
-
-	if (param->u.crypt.alg != NULL) {
-		memcpy(sec.keys[param->u.crypt.idx],
-		       param->u.crypt.key,
-		       param->u.crypt.key_len);
-		sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
-		sec.flags |= (1 << param->u.crypt.idx);
-
-		if (strcmp(param->u.crypt.alg, "WEP") == 0) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_1;
-		} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_2;
-		} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_3;
-		}
-	}
- done:
-	if (ieee->set_security)
-		ieee->set_security(ieee->dev, &sec);
-
-	/* Do not reset port if card is in Managed mode since resetting will
-	 * generate new IEEE 802.11 authentication which may end up in looping
-	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
-	 * configuration (for example... Prism2), implement the reset_port in
-	 * the callbacks structures used to initialize the 802.11 stack. */
-	if (ieee->reset_on_keychange &&
-	    ieee->iw_mode != IW_MODE_INFRA &&
-	    ieee->reset_port &&
-	    ieee->reset_port(ieee->dev)) {
-		printk("reset_port failed\n");
-		param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
-		return -EINVAL;
-	}
-
-	return ret;
-}
-
-int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee,
-				   struct iw_point *p)
-{
-	struct ieee_param *param;
-	int ret = 0;
-
-	down(&ieee->wx_sem);
-
-	if (p->length < sizeof(struct ieee_param) || !p->pointer) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	param = memdup_user(p->pointer, p->length);
-	if (IS_ERR(param)) {
-		ret = PTR_ERR(param);
-		goto out;
-	}
-
-	switch (param->cmd) {
-	case IEEE_CMD_SET_WPA_PARAM:
-		ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
-					param->u.wpa_param.value);
-		break;
-	case IEEE_CMD_SET_WPA_IE:
-		ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
-		break;
-	case IEEE_CMD_SET_ENCRYPTION:
-		ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
-		break;
-	case IEEE_CMD_MLME:
-		ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
-				   param->u.mlme.reason_code);
-		break;
-	default:
-		printk("Unknown WPA supplicant request: %d\n", param->cmd);
-		ret = -EOPNOTSUPP;
-		break;
-	}
-
-	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
-		ret = -EFAULT;
-
-	kfree(param);
-out:
-	up(&ieee->wx_sem);
-
-	return ret;
-}
-
-void notify_wx_assoc_event(struct ieee80211_device *ieee)
-{
-	union iwreq_data wrqu;
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	if (ieee->state == IEEE80211_LINKED)
-		memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
-	else
-		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
-	wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
deleted file mode 100644
index 46f35644126c..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/* IEEE 802.11 SoftMAC layer
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * Mostly extracted from the rtl8180-sa2400 driver for the
- * in-kernel generic ieee802.11 stack.
- *
- * Some pieces of code might be stolen from ipw2100 driver
- * copyright of who own it's copyright ;-)
- *
- * PS wx handler mostly stolen from hostap, copyright who
- * own it's copyright ;-)
- *
- * released under the GPL
- */
-
-
-#include <linux/etherdevice.h>
-
-#include "ieee80211.h"
-
-/* FIXME: add A freqs */
-
-const long ieee80211_wlan_frequencies[] = {
-	2412, 2417, 2422, 2427,
-	2432, 2437, 2442, 2447,
-	2452, 2457, 2462, 2467,
-	2472, 2484
-};
-
-
-int ieee80211_wx_set_freq(struct ieee80211_device *ieee,
-			  struct iw_request_info *a, union iwreq_data *wrqu,
-			  char *b)
-{
-	int ret;
-	struct iw_freq *fwrq = &wrqu->freq;
-//	printk("in %s\n",__func__);
-	down(&ieee->wx_sem);
-
-	if (ieee->iw_mode == IW_MODE_INFRA) {
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
-	/* if setting by freq convert to channel */
-	if (fwrq->e == 1) {
-		if ((fwrq->m >= (int) 2.412e8 &&
-		     fwrq->m <= (int) 2.487e8)) {
-			int f = fwrq->m / 100000;
-			int c = 0;
-
-			while ((c < 14) && (f != ieee80211_wlan_frequencies[c]))
-				c++;
-
-			/* hack to fall through */
-			fwrq->e = 0;
-			fwrq->m = c + 1;
-		}
-	}
-
-	if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) {
-		ret = -EOPNOTSUPP;
-		goto out;
-
-	} else { /* Set the channel */
-
-
-		ieee->current_network.channel = fwrq->m;
-		ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
-		if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
-			if (ieee->state == IEEE80211_LINKED) {
-				ieee80211_stop_send_beacons(ieee);
-				ieee80211_start_send_beacons(ieee);
-			}
-	}
-
-	ret = 0;
-out:
-	up(&ieee->wx_sem);
-	return ret;
-}
-
-
-int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
-			  struct iw_request_info *a, union iwreq_data *wrqu,
-			  char *b)
-{
-	struct iw_freq *fwrq = &wrqu->freq;
-
-	if (ieee->current_network.channel == 0)
-		return -1;
-
-	fwrq->m = ieee->current_network.channel;
-	fwrq->e = 0;
-
-	return 0;
-}
-
-int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
-			 struct iw_request_info *info, union iwreq_data *wrqu,
-			 char *extra)
-{
-	unsigned long flags;
-
-	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
-
-	if (ieee->iw_mode == IW_MODE_MONITOR)
-		return -1;
-
-	/* We want avoid to give to the user inconsistent infos*/
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if (ieee->state != IEEE80211_LINKED &&
-		ieee->state != IEEE80211_LINKED_SCANNING &&
-		ieee->wap_set == 0)
-
-		memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
-	else
-		memcpy(wrqu->ap_addr.sa_data,
-		       ieee->current_network.bssid, ETH_ALEN);
-
-	spin_unlock_irqrestore(&ieee->lock, flags);
-
-	return 0;
-}
-
-
-int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
-			 struct iw_request_info *info, union iwreq_data *awrq,
-			 char *extra)
-{
-
-	int ret = 0;
-	unsigned long flags;
-
-	short ifup = ieee->proto_started;//dev->flags & IFF_UP;
-	struct sockaddr *temp = (struct sockaddr *)awrq;
-
-	//printk("=======Set WAP:");
-	ieee->sync_scan_hurryup = 1;
-
-	down(&ieee->wx_sem);
-	/* use ifconfig hw ether */
-	if (ieee->iw_mode == IW_MODE_MASTER) {
-		ret = -1;
-		goto out;
-	}
-
-	if (temp->sa_family != ARPHRD_ETHER) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (ifup)
-		ieee80211_stop_protocol(ieee);
-
-	/* just to avoid to give inconsistent infos in the
-	 * get wx method. not really needed otherwise
-	 */
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
-	ieee->wap_set = !is_zero_ether_addr(temp->sa_data);
-	//printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]);
-
-	spin_unlock_irqrestore(&ieee->lock, flags);
-
-	if (ifup)
-		ieee80211_start_protocol(ieee);
-
-out:
-	up(&ieee->wx_sem);
-	return ret;
-}
-
-int ieee80211_wx_get_essid(struct ieee80211_device *ieee,
-			   struct iw_request_info *a, union iwreq_data *wrqu,
-			   char *b)
-{
-	int len, ret = 0;
-	unsigned long flags;
-
-	if (ieee->iw_mode == IW_MODE_MONITOR)
-		return -1;
-
-	/* We want avoid to give to the user inconsistent infos*/
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if (ieee->current_network.ssid[0] == '\0' ||
-		ieee->current_network.ssid_len == 0){
-		ret = -1;
-		goto out;
-	}
-
-	if (ieee->state != IEEE80211_LINKED &&
-		ieee->state != IEEE80211_LINKED_SCANNING &&
-		ieee->ssid_set == 0){
-		ret = -1;
-		goto out;
-	}
-	len = ieee->current_network.ssid_len;
-	wrqu->essid.length = len;
-	strncpy(b, ieee->current_network.ssid, len);
-	wrqu->essid.flags = 1;
-
-out:
-	spin_unlock_irqrestore(&ieee->lock, flags);
-
-	return ret;
-
-}
-
-int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
-			  struct iw_request_info *info, union iwreq_data *wrqu,
-			  char *extra)
-{
-
-	u32 target_rate = wrqu->bitrate.value;
-
-	//added by lizhaoming for auto mode
-	if (target_rate == -1)
-		ieee->rate = 110;
-	else
-		ieee->rate = target_rate/100000;
-
-	//FIXME: we might want to limit rate also in management protocols.
-	return 0;
-}
-
-
-
-int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
-			  struct iw_request_info *info, union iwreq_data *wrqu,
-			  char *extra)
-{
-
-	wrqu->bitrate.value = ieee->rate * 100000;
-
-	return 0;
-}
-
-int ieee80211_wx_set_mode(struct ieee80211_device *ieee,
-			  struct iw_request_info *a, union iwreq_data *wrqu,
-			  char *b)
-{
-
-	ieee->sync_scan_hurryup = 1;
-
-	down(&ieee->wx_sem);
-
-	if (wrqu->mode == ieee->iw_mode)
-		goto out;
-
-	if (wrqu->mode == IW_MODE_MONITOR)
-		ieee->dev->type = ARPHRD_IEEE80211;
-	else
-		ieee->dev->type = ARPHRD_ETHER;
-
-	if (!ieee->proto_started) {
-		ieee->iw_mode = wrqu->mode;
-	} else {
-		ieee80211_stop_protocol(ieee);
-		ieee->iw_mode = wrqu->mode;
-		ieee80211_start_protocol(ieee);
-	}
-
-out:
-	up(&ieee->wx_sem);
-	return 0;
-}
-
-
-void ieee80211_wx_sync_scan_wq(struct work_struct *work)
-{
-	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq);
-	short chan;
-
-	chan = ieee->current_network.channel;
-
-	if (ieee->data_hard_stop)
-		ieee->data_hard_stop(ieee->dev);
-
-	ieee80211_stop_send_beacons(ieee);
-
-	ieee->state = IEEE80211_LINKED_SCANNING;
-	ieee->link_change(ieee->dev);
-
-	ieee80211_start_scan_syncro(ieee);
-
-	ieee->set_chan(ieee->dev, chan);
-
-	ieee->state = IEEE80211_LINKED;
-	ieee->link_change(ieee->dev);
-
-	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
-
-	if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
-		ieee80211_start_send_beacons(ieee);
-
-	//YJ,add,080828, In prevent of lossing ping packet during scanning
-	//ieee80211_sta_ps_send_null_frame(ieee, false);
-	//YJ,add,080828,end
-
-	up(&ieee->wx_sem);
-
-}
-
-int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
-			  struct iw_request_info *a, union iwreq_data *wrqu,
-			  char *b)
-{
-	int ret = 0;
-
-	down(&ieee->wx_sem);
-
-	if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
-		ret = -1;
-		goto out;
-	}
-	//YJ,add,080828
-	//In prevent of lossing ping packet during scanning
-	//ieee80211_sta_ps_send_null_frame(ieee, true);
-	//YJ,add,080828,end
-
-	if (ieee->state == IEEE80211_LINKED) {
-		queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
-		/* intentionally forget to up sem */
-		return 0;
-	}
-
-out:
-	up(&ieee->wx_sem);
-	return ret;
-}
-
-int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
-			   struct iw_request_info *a, union iwreq_data *wrqu,
-			   char *extra)
-{
-
-	int ret = 0, len;
-	short proto_started;
-	unsigned long flags;
-
-	ieee->sync_scan_hurryup = 1;
-
-	down(&ieee->wx_sem);
-
-	proto_started = ieee->proto_started;
-
-	if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
-		ret = -E2BIG;
-		goto out;
-	}
-
-	if (ieee->iw_mode == IW_MODE_MONITOR) {
-		ret = -1;
-		goto out;
-	}
-
-	if (proto_started)
-		ieee80211_stop_protocol(ieee);
-
-	/* this is just to be sure that the GET wx callback
-	 * has consistent infos. not needed otherwise
-	 */
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if (wrqu->essid.flags && wrqu->essid.length) {
-//YJ,modified,080819
-		len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length) : IW_ESSID_MAX_SIZE;
-		memset(ieee->current_network.ssid, 0, ieee->current_network.ssid_len); //YJ,add,080819
-		strncpy(ieee->current_network.ssid, extra, len);
-		ieee->current_network.ssid_len = len;
-		ieee->ssid_set = 1;
-//YJ,modified,080819,end
-
-		//YJ,add,080819,for hidden ap
-		if (len == 0) {
-			memset(ieee->current_network.bssid, 0, ETH_ALEN);
-			ieee->current_network.capability = 0;
-		}
-		//YJ,add,080819,for hidden ap,end
-	} else {
-		ieee->ssid_set = 0;
-		ieee->current_network.ssid[0] = '\0';
-		ieee->current_network.ssid_len = 0;
-	}
-	//printk("==========set essid %s!\n",ieee->current_network.ssid);
-	spin_unlock_irqrestore(&ieee->lock, flags);
-
-	if (proto_started)
-		ieee80211_start_protocol(ieee);
-out:
-	up(&ieee->wx_sem);
-	return ret;
-}
-
-int ieee80211_wx_get_mode(struct ieee80211_device *ieee,
-			  struct iw_request_info *a, union iwreq_data *wrqu,
-			  char *b)
-{
-
-	wrqu->mode = ieee->iw_mode;
-	return 0;
-}
-
-int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
-			   struct iw_request_info *info, union iwreq_data *wrqu,
-			   char *extra)
-{
-
-	int *parms = (int *)extra;
-	int enable = (parms[0] > 0);
-	short prev = ieee->raw_tx;
-
-	down(&ieee->wx_sem);
-
-	if (enable)
-		ieee->raw_tx = 1;
-	else
-		ieee->raw_tx = 0;
-
-	netdev_info(ieee->dev, "raw TX is %s\n",
-		    ieee->raw_tx ? "enabled" : "disabled");
-
-	if (ieee->iw_mode == IW_MODE_MONITOR) {
-		if (prev == 0 && ieee->raw_tx) {
-			if (ieee->data_hard_resume)
-				ieee->data_hard_resume(ieee->dev);
-
-			netif_carrier_on(ieee->dev);
-		}
-
-		if (prev && ieee->raw_tx == 1)
-			netif_carrier_off(ieee->dev);
-	}
-
-	up(&ieee->wx_sem);
-
-	return 0;
-}
-
-int ieee80211_wx_get_name(struct ieee80211_device *ieee,
-			  struct iw_request_info *info, union iwreq_data *wrqu,
-			  char *extra)
-{
-	strlcpy(wrqu->name, "802.11", IFNAMSIZ);
-	if (ieee->modulation & IEEE80211_CCK_MODULATION) {
-		strlcat(wrqu->name, "b", IFNAMSIZ);
-		if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-			strlcat(wrqu->name, "/g", IFNAMSIZ);
-	} else if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-		strlcat(wrqu->name, "g", IFNAMSIZ);
-
-	if ((ieee->state == IEEE80211_LINKED) ||
-		(ieee->state == IEEE80211_LINKED_SCANNING))
-		strlcat(wrqu->name, "  link", IFNAMSIZ);
-	else if (ieee->state != IEEE80211_NOLINK)
-		strlcat(wrqu->name, " .....", IFNAMSIZ);
-
-
-	return 0;
-}
-
-
-/* this is mostly stolen from hostap */
-int ieee80211_wx_set_power(struct ieee80211_device *ieee,
-			   struct iw_request_info *info, union iwreq_data *wrqu,
-			   char *extra)
-{
-	int ret = 0;
-
-	if ((!ieee->sta_wake_up) ||
-	    (!ieee->ps_request_tx_ack) ||
-	    (!ieee->enter_sleep_state) ||
-	    (!ieee->ps_is_queue_empty)) {
-
-		printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
-
-		return -1;
-	}
-
-	down(&ieee->wx_sem);
-
-	if (wrqu->power.disabled) {
-		ieee->ps = IEEE80211_PS_DISABLED;
-
-		goto exit;
-	}
-	switch (wrqu->power.flags & IW_POWER_MODE) {
-	case IW_POWER_UNICAST_R:
-		ieee->ps = IEEE80211_PS_UNICAST;
-
-		break;
-	case IW_POWER_ALL_R:
-		ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST;
-		break;
-
-	case IW_POWER_ON:
-		ieee->ps = IEEE80211_PS_DISABLED;
-		break;
-
-	default:
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	if (wrqu->power.flags & IW_POWER_TIMEOUT) {
-
-		ieee->ps_timeout = wrqu->power.value / 1000;
-		printk("Timeout %d\n", ieee->ps_timeout);
-	}
-
-	if (wrqu->power.flags & IW_POWER_PERIOD) {
-
-		ret = -EOPNOTSUPP;
-		goto exit;
-		//wrq->value / 1024;
-
-	}
-exit:
-	up(&ieee->wx_sem);
-	return ret;
-
-}
-
-/* this is stolen from hostap */
-int ieee80211_wx_get_power(struct ieee80211_device *ieee,
-			   struct iw_request_info *info, union iwreq_data *wrqu,
-			   char *extra)
-{
-	int ret = 0;
-
-	down(&ieee->wx_sem);
-
-	if (ieee->ps == IEEE80211_PS_DISABLED) {
-		wrqu->power.disabled = 1;
-		goto exit;
-	}
-
-	wrqu->power.disabled = 0;
-
-//	if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-		wrqu->power.flags = IW_POWER_TIMEOUT;
-		wrqu->power.value = ieee->ps_timeout * 1000;
-//	} else {
-//		ret = -EOPNOTSUPP;
-//		goto exit;
-		//wrqu->power.flags = IW_POWER_PERIOD;
-		//wrqu->power.value = ieee->current_network.dtim_period *
-		//	ieee->current_network.beacon_interval * 1024;
-//	}
-
-
-	if (ieee->ps & IEEE80211_PS_MBCAST)
-		wrqu->power.flags |= IW_POWER_ALL_R;
-	else
-		wrqu->power.flags |= IW_POWER_UNICAST_R;
-
-exit:
-	up(&ieee->wx_sem);
-	return ret;
-
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
deleted file mode 100644
index 0dc5ae414270..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/******************************************************************************
-
-  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of version 2 of the GNU General Public License as
-  published by the Free Software Foundation.
-
-  This program is distributed in the hope that it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-
-  Contact Information:
-  James P. Ketrenos <ipw2100-admin@linux.intel.com>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-******************************************************************************
-
-  Few modifications for Realtek's Wi-Fi drivers by
-  Andrea Merello <andrea.merello@gmail.com>
-
-  A special thanks goes to Realtek for their support !
-
-******************************************************************************/
-
-#include <linux/compiler.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in6.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/tcp.h>
-#include <linux/types.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-#include <asm/uaccess.h>
-#include <linux/if_vlan.h>
-
-#include "ieee80211.h"
-
-
-/*
-
-
-802.11 Data Frame
-
-
-802.11 frame_contorl for data frames - 2 bytes
-     ,-----------------------------------------------------------------------------------------.
-bits | 0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  a  |  b  |  c  |  d  |  e   |
-     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
-val  | 0  |  0  |  0  |  1  |  x  |  0  |  0  |  0  |  1  |  0  |  x  |  x  |  x  |  x  |  x   |
-     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
-desc | ^-ver-^  |  ^type-^  |  ^-----subtype-----^  | to  |from |more |retry| pwr |more |wep   |
-     |          |           | x=0 data,x=1 data+ack | DS  | DS  |frag |     | mgm |data |      |
-     '-----------------------------------------------------------------------------------------'
-		                                    /\
-                                                    |
-802.11 Data Frame                                   |
-           ,--------- 'ctrl' expands to >-----------'
-          |
-      ,--'---,-------------------------------------------------------------.
-Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
-      |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
-      |      | tion | (BSSID) |         |         | ence |  data   |      |
-      `--------------------------------------------------|         |------'
-Total: 28 non-data bytes                                 `----.----'
-                                                              |
-       .- 'Frame data' expands to <---------------------------'
-       |
-       V
-      ,---------------------------------------------------.
-Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
-      |------|------|---------|----------|------|---------|
-Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
-      | DSAP | SSAP |         |          |      | Packet  |
-      | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
-      `-----------------------------------------|         |
-Total: 8 non-data bytes                         `----.----'
-                                                     |
-       .- 'IP Packet' expands, if WEP enabled, to <--'
-       |
-       V
-      ,-----------------------.
-Bytes |  4  |   0-2296  |  4  |
-      |-----|-----------|-----|
-Desc. | IV  | Encrypted | ICV |
-      |     | IP Packet |     |
-      `-----------------------'
-Total: 8 non-data bytes
-
-
-802.3 Ethernet Data Frame
-
-      ,-----------------------------------------.
-Bytes |   6   |   6   |  2   |  Variable |   4  |
-      |-------|-------|------|-----------|------|
-Desc. | Dest. | Source| Type | IP Packet |  fcs |
-      |  MAC  |  MAC  |      |           |      |
-      `-----------------------------------------'
-Total: 18 non-data bytes
-
-In the event that fragmentation is required, the incoming payload is split into
-N parts of size ieee->fts.  The first fragment contains the SNAP header and the
-remaining packets are just data.
-
-If encryption is enabled, each fragment payload size is reduced by enough space
-to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
-So if you have 1500 bytes of payload with ieee->fts set to 500 without
-encryption it will take 3 frames.  With WEP it will take 4 frames as the
-payload of each frame is reduced to 492 bytes.
-
-* SKB visualization
-*
-*  ,- skb->data
-* |
-* |    ETHERNET HEADER        ,-<-- PAYLOAD
-* |                           |     14 bytes from skb->data
-* |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
-* |                       | | |
-* |,-Dest.--. ,--Src.---. | | |
-* |  6 bytes| | 6 bytes | | | |
-* v         | |         | | | |
-* 0         | v       1 | v | v           2
-* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
-*     ^     | ^         | ^ |
-*     |     | |         | | |
-*     |     | |         | `T' <---- 2 bytes for Type
-*     |     | |         |
-*     |     | '---SNAP--' <-------- 6 bytes for SNAP
-*     |     |
-*     `-IV--' <-------------------- 4 bytes for IV (WEP)
-*
-*      SNAP HEADER
-*
-*/
-
-static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
-static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
-
-static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
-{
-	struct ieee80211_snap_hdr *snap;
-	u8 *oui;
-
-	snap = (struct ieee80211_snap_hdr *)data;
-	snap->dsap = 0xaa;
-	snap->ssap = 0xaa;
-	snap->ctrl = 0x03;
-
-	if (h_proto == 0x8137 || h_proto == 0x80f3)
-		oui = P802_1H_OUI;
-	else
-		oui = RFC1042_OUI;
-	snap->oui[0] = oui[0];
-	snap->oui[1] = oui[1];
-	snap->oui[2] = oui[2];
-
-	*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
-
-	return SNAP_SIZE + sizeof(u16);
-}
-
-int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
-			       struct sk_buff *frag, int hdr_len)
-{
-	struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
-	int res;
-
-	/*
-	 * added to care about null crypt condition, to solve that system hangs
-	 * when shared keys error
-	 */
-	if (!crypt || !crypt->ops)
-		return -1;
-
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-	struct ieee80211_hdr_4addr *header;
-
-	if (ieee->tkip_countermeasures &&
-	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
-		header = (struct ieee80211_hdr_4addr *)frag->data;
-		if (net_ratelimit()) {
-			netdev_dbg(ieee->dev, "TKIP countermeasures: dropped "
-			       "TX packet to %pM\n", header->addr1);
-		}
-		return -1;
-	}
-#endif
-	/*
-	 * To encrypt, frame format is:
-	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes)
-	 *
-	 * PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU
-	 * encryption.
-	 *
-	 * Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
-	 * call both MSDU and MPDU encryption functions from here.
-	 */
-	atomic_inc(&crypt->refcnt);
-	res = 0;
-	if (crypt->ops->encrypt_msdu)
-		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
-	if (res == 0 && crypt->ops->encrypt_mpdu)
-		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
-
-	atomic_dec(&crypt->refcnt);
-	if (res < 0) {
-		netdev_info(ieee->dev, "Encryption failed: len=%d.\n", frag->len);
-		ieee->ieee_stats.tx_discards++;
-		return -1;
-	}
-
-	return 0;
-}
-
-
-void ieee80211_txb_free(struct ieee80211_txb *txb)
-{
-	int i;
-	if (unlikely(!txb))
-		return;
-	for (i = 0; i < txb->nr_frags; i++)
-		if (txb->fragments[i])
-			dev_kfree_skb_any(txb->fragments[i]);
-	kfree(txb);
-}
-
-static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
-						 gfp_t gfp_mask)
-{
-	struct ieee80211_txb *txb;
-	int i;
-	txb = kmalloc(
-		sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
-		gfp_mask);
-	if (!txb)
-		return NULL;
-
-	memset(txb, 0, sizeof(struct ieee80211_txb));
-	txb->nr_frags = nr_frags;
-	txb->frag_size = txb_size;
-
-	for (i = 0; i < nr_frags; i++) {
-		txb->fragments[i] = dev_alloc_skb(txb_size);
-		if (unlikely(!txb->fragments[i])) {
-			i--;
-			break;
-		}
-	}
-	if (unlikely(i != nr_frags)) {
-		while (i >= 0)
-			dev_kfree_skb_any(txb->fragments[i--]);
-		kfree(txb);
-		return NULL;
-	}
-	return txb;
-}
-
-/*
- * Classify the to-be send data packet
- * Need to acquire the sent queue index.
- */
-static int ieee80211_classify(struct sk_buff *skb,
-			      struct ieee80211_network *network)
-{
-	struct ether_header *eh = (struct ether_header *)skb->data;
-	unsigned int wme_UP = 0;
-
-	if (!network->QoS_Enable) {
-		skb->priority = 0;
-		return(wme_UP);
-	}
-
-	if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
-		const struct iphdr *ih = (struct iphdr *)(skb->data +
-		    sizeof(struct ether_header));
-		wme_UP = (ih->tos >> 5)&0x07;
-	} else if (vlan_tx_tag_present(skb)) {/* vtag packet */
-#ifndef VLAN_PRI_SHIFT
-#define VLAN_PRI_SHIFT  13              /* Shift to find VLAN user priority */
-#define VLAN_PRI_MASK   7               /* Mask for user priority bits in VLAN */
-#endif
-		u32 tag = vlan_tx_tag_get(skb);
-		wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
-	} else if (ETH_P_PAE ==  ntohs(((struct ethhdr *)skb->data)->h_proto)) {
-		wme_UP = 7;
-	}
-
-	skb->priority = wme_UP;
-	return(wme_UP);
-}
-
-/* SKBs are added to the ieee->tx_queue. */
-int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ieee80211_device *ieee = netdev_priv(dev);
-	struct ieee80211_txb *txb = NULL;
-	struct ieee80211_hdr_3addrqos *frag_hdr;
-	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
-	unsigned long flags;
-	struct net_device_stats *stats = &ieee->stats;
-	int ether_type, encrypt;
-	int bytes, fc, qos_ctl, hdr_len;
-	struct sk_buff *skb_frag;
-	struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
-		.duration_id = 0,
-		.seq_ctl = 0,
-		.qos_ctl = 0
-	};
-	u8 dest[ETH_ALEN], src[ETH_ALEN];
-
-	struct ieee80211_crypt_data* crypt;
-
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	/*
-	 * If there is no driver handler to take the TXB, don't bother
-	 * creating it...
-	 */
-	if ((!ieee->hard_start_xmit &&
-	     !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) ||
-	    ((!ieee->softmac_data_hard_start_xmit &&
-	      (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
-		netdev_warn(ieee->dev, "No xmit handler.\n");
-		goto success;
-	}
-
-	ieee80211_classify(skb,&ieee->current_network);
-	if (likely(ieee->raw_tx == 0)){
-
-		if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
-			netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
-			goto success;
-		}
-
-		ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
-
-		crypt = ieee->crypt[ieee->tx_keyidx];
-
-		encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
-			ieee->host_encrypt && crypt && crypt->ops;
-
-		if (!encrypt && ieee->ieee802_1x &&
-		ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
-			stats->tx_dropped++;
-			goto success;
-		}
-
-	#ifdef CONFIG_IEEE80211_DEBUG
-		if (crypt && !encrypt && ether_type == ETH_P_PAE) {
-			struct eapol *eap = (struct eapol *)(skb->data +
-				sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
-			IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
-				eap_get_type(eap->type));
-		}
-	#endif
-
-		/* Save source and destination addresses */
-		memcpy(&dest, skb->data, ETH_ALEN);
-		memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
-
-		/* Advance the SKB to the start of the payload */
-		skb_pull(skb, sizeof(struct ethhdr));
-
-		/* Determine total amount of storage required for TXB packets */
-		bytes = skb->len + SNAP_SIZE + sizeof(u16);
-
-		if (ieee->current_network.QoS_Enable) {
-			if (encrypt)
-				fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA |
-					IEEE80211_FCTL_WEP;
-			else
-				fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
-
-		} else {
-			if (encrypt)
-				fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
-					IEEE80211_FCTL_WEP;
-			else
-				fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
-		}
-
-		if (ieee->iw_mode == IW_MODE_INFRA) {
-			fc |= IEEE80211_FCTL_TODS;
-			/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
-			memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
-			memcpy(&header.addr2, &src, ETH_ALEN);
-			memcpy(&header.addr3, &dest, ETH_ALEN);
-		} else if (ieee->iw_mode == IW_MODE_ADHOC) {
-			/*
-			 * not From/To DS: Addr1 = DA, Addr2 = SA,
-			 * Addr3 = BSSID
-			 */
-			memcpy(&header.addr1, dest, ETH_ALEN);
-			memcpy(&header.addr2, src, ETH_ALEN);
-			memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
-		}
-		header.frame_ctl = cpu_to_le16(fc);
-
-		/*
-		 * Determine fragmentation size based on destination (multicast
-		 * and broadcast are not fragmented)
-		 */
-		if (is_multicast_ether_addr(header.addr1)) {
-			frag_size = MAX_FRAG_THRESHOLD;
-			qos_ctl = QOS_CTL_NOTCONTAIN_ACK;
-		} else {
-			/* default:392 */
-			frag_size = ieee->fts;
-			qos_ctl = 0;
-		}
-
-		if (ieee->current_network.QoS_Enable)	{
-			hdr_len = IEEE80211_3ADDR_LEN + 2;
-			/* skb->priority is set in the ieee80211_classify() */
-			qos_ctl |= skb->priority;
-			header.qos_ctl = cpu_to_le16(qos_ctl);
-		} else {
-			hdr_len = IEEE80211_3ADDR_LEN;
-		}
-
-		/*
-		 * Determine amount of payload per fragment.  Regardless of if
-		 * this stack is providing the full 802.11 header, one will
-		 * eventually be affixed to this fragment -- so we must account
-		 * for it when determining the amount of payload space.
-		 */
-		bytes_per_frag = frag_size - hdr_len;
-		if (ieee->config &
-		(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
-			bytes_per_frag -= IEEE80211_FCS_LEN;
-
-		/* Each fragment may need to have room for encryption pre/postfix */
-		if (encrypt)
-			bytes_per_frag -= crypt->ops->extra_prefix_len +
-				crypt->ops->extra_postfix_len;
-
-		/*
-		 * Number of fragments is the total bytes_per_frag /
-		 * payload_per_fragment
-		 */
-		nr_frags = bytes / bytes_per_frag;
-		bytes_last_frag = bytes % bytes_per_frag;
-		if (bytes_last_frag)
-			nr_frags++;
-		else
-			bytes_last_frag = bytes_per_frag;
-
-		/*
-		 * When we allocate the TXB we allocate enough space for the 
-		 * reserve and full fragment bytes (bytes_per_frag doesn't
-		 * include prefix, postfix, header, FCS, etc.)
-		 */
-		txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
-		if (unlikely(!txb)) {
-			netdev_warn(ieee->dev, "Could not allocate TXB\n");
-			goto failed;
-		}
-		txb->encrypted = encrypt;
-		txb->payload_size = bytes;
-
-		for (i = 0; i < nr_frags; i++) {
-			skb_frag = txb->fragments[i];
-			skb_frag->priority = UP2AC(skb->priority);
-			if (encrypt)
-				skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
-
-			frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(
-				skb_frag, hdr_len);
-			memcpy(frag_hdr, &header, hdr_len);
-
-			/*
-			 * If this is not the last fragment, then add the MOREFRAGS
-			 * bit to the frame control
-			 */
-			if (i != nr_frags - 1) {
-				frag_hdr->frame_ctl = cpu_to_le16(
-					fc | IEEE80211_FCTL_MOREFRAGS);
-				bytes = bytes_per_frag;
-
-			} else {
-				/* The last fragment takes the remaining length */
-				bytes = bytes_last_frag;
-			}
-			if (ieee->current_network.QoS_Enable) {
-				/*
-				 * add 1 only indicate to corresponding seq
-				 * number control 2006/7/12
-				 */
-				frag_hdr->seq_ctl = cpu_to_le16(
-					ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
-			} else {
-				frag_hdr->seq_ctl = cpu_to_le16(
-					ieee->seq_ctrl[0]<<4 | i);
-			}
-
-			/* Put a SNAP header on the first fragment */
-			if (i == 0) {
-				ieee80211_put_snap(
-					skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
-					ether_type);
-				bytes -= SNAP_SIZE + sizeof(u16);
-			}
-
-			memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
-
-			/* Advance the SKB... */
-			skb_pull(skb, bytes);
-
-			/*
-			 * Encryption routine will move the header forward in
-			 * order to insert the IV between the header and the
-			 * payload
-			 */
-			if (encrypt)
-				ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
-			if (ieee->config &
-			(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
-				skb_put(skb_frag, 4);
-		}
-		/* Advance sequence number in data frame. */
-		if (ieee->current_network.QoS_Enable) {
-			if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
-				ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
-			else
-				ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
-		} else {
-			if (ieee->seq_ctrl[0] == 0xFFF)
-				ieee->seq_ctrl[0] = 0;
-			else
-				ieee->seq_ctrl[0]++;
-		}
-	} else {
-		if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
-			netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
-			goto success;
-		}
-
-		txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
-		if (!txb) {
-			netdev_warn(ieee->dev, "Could not allocate TXB\n");
-			goto failed;
-		}
-
-		txb->encrypted = 0;
-		txb->payload_size = skb->len;
-		memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len);
-	}
-
- success:
-	spin_unlock_irqrestore(&ieee->lock, flags);
-		dev_kfree_skb_any(skb);
-	if (txb) {
-		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
-			ieee80211_softmac_xmit(txb, ieee);
-		} else {
-			if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
-				stats->tx_packets++;
-				stats->tx_bytes += txb->payload_size;
-				return NETDEV_TX_OK;
-			}
-			ieee80211_txb_free(txb);
-		}
-	}
-
-	return NETDEV_TX_OK;
-
- failed:
-	spin_unlock_irqrestore(&ieee->lock, flags);
-	netif_stop_queue(dev);
-	stats->tx_errors++;
-	return NETDEV_TX_BUSY;
-
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
deleted file mode 100644
index 07c3f715a6f5..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/*
- *  Copyright(c) 2004 Intel Corporation. All rights reserved.
- *
- * Portions of this file are based on the WEP enablement code provided by the
- * Host AP project hostap-drivers v0.1.3
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- */
-
-#include <linux/wireless.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/etherdevice.h>
-
-#include "ieee80211.h"
-static const char *ieee80211_modes[] = {
-	"?", "a", "b", "ab", "g", "ag", "bg", "abg"
-};
-
-#define MAX_CUSTOM_LEN 64
-static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
-					   char *start, char *stop,
-					   struct ieee80211_network *network,
-					   struct iw_request_info *info)
-{
-	char custom[MAX_CUSTOM_LEN];
-	char *p;
-	struct iw_event iwe;
-	int i, j;
-	u8 max_rate, rate;
-
-	/* First entry *MUST* be the AP MAC address */
-	iwe.cmd = SIOCGIWAP;
-	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-	ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid);
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
-
-	/* Remaining entries will be displayed in the order we provide them */
-
-	/* Add the ESSID */
-	iwe.cmd = SIOCGIWESSID;
-	iwe.u.data.flags = 1;
-	if (network->ssid_len == 0) {
-		iwe.u.data.length = sizeof("<hidden>");
-		start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
-	} else {
-		iwe.u.data.length = min_t(u8, network->ssid_len, 32);
-		start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
-	}
-	/* Add the protocol name */
-	iwe.cmd = SIOCGIWNAME;
-	snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
-
-	/* Add mode */
-	iwe.cmd = SIOCGIWMODE;
-	if (network->capability &
-	    (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
-		if (network->capability & WLAN_CAPABILITY_BSS)
-			iwe.u.mode = IW_MODE_MASTER;
-		else
-			iwe.u.mode = IW_MODE_ADHOC;
-
-		start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
-	}
-
-	/* Add frequency/channel */
-	iwe.cmd = SIOCGIWFREQ;
-	iwe.u.freq.m = network->channel;
-	iwe.u.freq.e = 0;
-	iwe.u.freq.i = 0;
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
-
-	/* Add encryption capability */
-	iwe.cmd = SIOCGIWENCODE;
-	if (network->capability & WLAN_CAPABILITY_PRIVACY)
-		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-	else
-		iwe.u.data.flags = IW_ENCODE_DISABLED;
-	iwe.u.data.length = 0;
-	start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
-
-	/* Add basic and extended rates */
-	max_rate = 0;
-	p = custom;
-	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
-	for (i = 0, j = 0; i < network->rates_len; ) {
-		if (j < network->rates_ex_len &&
-		    ((network->rates_ex[j] & 0x7F) <
-		     (network->rates[i] & 0x7F)))
-			rate = network->rates_ex[j++] & 0x7F;
-		else
-			rate = network->rates[i++] & 0x7F;
-		if (rate > max_rate)
-			max_rate = rate;
-		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
-	}
-	for (; j < network->rates_ex_len; j++) {
-		rate = network->rates_ex[j] & 0x7F;
-		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
-		if (rate > max_rate)
-			max_rate = rate;
-	}
-
-	iwe.cmd = SIOCGIWRATE;
-	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-	iwe.u.bitrate.value = max_rate * 500000;
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
-
-	iwe.cmd = IWEVCUSTOM;
-	iwe.u.data.length = p - custom;
-	if (iwe.u.data.length)
-		start = iwe_stream_add_point(info, start, stop, &iwe, custom);
-
-	/* Add quality statistics */
-	/* TODO: Fix these values... */
-	if (network->stats.signal == 0 || network->stats.rssi == 0)
-		netdev_info(ieee->dev, "========>signal:%d, rssi:%d\n",
-			    network->stats.signal, network->stats.rssi);
-	iwe.cmd = IWEVQUAL;
-	iwe.u.qual.qual = network->stats.signalstrength;
-	iwe.u.qual.level = network->stats.signal;
-	iwe.u.qual.noise = network->stats.noise;
-	iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
-	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
-		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
-	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
-		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
-	if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
-		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
-	iwe.u.qual.updated = 7;
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
-
-	iwe.cmd = IWEVCUSTOM;
-	p = custom;
-
-	iwe.u.data.length = p - custom;
-	if (iwe.u.data.length)
-		start = iwe_stream_add_point(info, start, stop, &iwe, custom);
-
-	memset(&iwe, 0, sizeof(iwe));
-	if (network->wpa_ie_len) {
-		char buf[MAX_WPA_IE_LEN];
-		memcpy(buf, network->wpa_ie, network->wpa_ie_len);
-		iwe.cmd = IWEVGENIE;
-		iwe.u.data.length = network->wpa_ie_len;
-		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-	}
-
-	memset(&iwe, 0, sizeof(iwe));
-	if (network->rsn_ie_len) {
-		char buf[MAX_WPA_IE_LEN];
-		memcpy(buf, network->rsn_ie, network->rsn_ie_len);
-		iwe.cmd = IWEVGENIE;
-		iwe.u.data.length = network->rsn_ie_len;
-		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-	}
-
-	/* Add EXTRA: Age to display seconds since last beacon/probe response
-	 * for given network.
-	 */
-	iwe.cmd = IWEVCUSTOM;
-	p = custom;
-	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-		      " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
-	iwe.u.data.length = p - custom;
-	if (iwe.u.data.length)
-		start = iwe_stream_add_point(info, start, stop, &iwe, custom);
-
-	return start;
-}
-
-int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
-			  struct iw_request_info *info,
-			  union iwreq_data *wrqu, char *extra)
-{
-	struct ieee80211_network *network;
-	unsigned long flags;
-	int err = 0;
-	char *ev = extra;
-	char *stop = ev + wrqu->data.length;
-	int i = 0;
-
-	IEEE80211_DEBUG_WX("Getting scan\n");
-	down(&ieee->wx_sem);
-	spin_lock_irqsave(&ieee->lock, flags);
-
-	if (!ieee->bHwRadioOff) {
-		list_for_each_entry(network, &ieee->network_list, list) {
-			i++;
-
-			if ((stop-ev) < 200) {
-				err = -E2BIG;
-				break;
-			}
-			if (ieee->scan_age == 0 ||
-			    time_after(network->last_scanned + ieee->scan_age, jiffies)) {
-				ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
-			} else
-				IEEE80211_DEBUG_SCAN(
-					"Not showing network '%s ("
-					"%pM)' due to age (%lums).\n",
-					escape_essid(network->ssid,
-						     network->ssid_len),
-					network->bssid,
-					(jiffies - network->last_scanned) / (HZ / 100));
-		}
-	}
-	spin_unlock_irqrestore(&ieee->lock, flags);
-	up(&ieee->wx_sem);
-	wrqu->data.length = ev -  extra;
-	wrqu->data.flags = 0;
-	IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
-
-	return err;
-}
-
-int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *keybuf)
-{
-	struct iw_point *erq = &(wrqu->encoding);
-	struct net_device *dev = ieee->dev;
-	struct ieee80211_security sec = {
-		.flags = 0
-	};
-	int i, key, key_provided, len;
-	struct ieee80211_crypt_data **crypt;
-
-	IEEE80211_DEBUG_WX("SET_ENCODE\n");
-
-	key = erq->flags & IW_ENCODE_INDEX;
-	if (key) {
-		if (key > WEP_KEYS)
-			return -EINVAL;
-		key--;
-		key_provided = 1;
-	} else {
-		key_provided = 0;
-		key = ieee->tx_keyidx;
-	}
-
-	IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
-			   "provided" : "default");
-
-	crypt = &ieee->crypt[key];
-
-	if (erq->flags & IW_ENCODE_DISABLED) {
-		if (key_provided && *crypt) {
-			IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
-					   key);
-			ieee80211_crypt_delayed_deinit(ieee, crypt);
-		} else
-			IEEE80211_DEBUG_WX("Disabling encryption.\n");
-
-		/* Check all the keys to see if any are still configured,
-		 * and if no key index was provided, de-init them all.
-		 */
-		for (i = 0; i < WEP_KEYS; i++) {
-			if (ieee->crypt[i] != NULL) {
-				if (key_provided)
-					break;
-				ieee80211_crypt_delayed_deinit(
-					ieee, &ieee->crypt[i]);
-			}
-		}
-
-		if (i == WEP_KEYS) {
-			sec.enabled = 0;
-			sec.level = SEC_LEVEL_0;
-			sec.flags |= SEC_ENABLED | SEC_LEVEL;
-		}
-
-		goto done;
-	}
-
-	sec.enabled = 1;
-	sec.flags |= SEC_ENABLED;
-
-	if (*crypt != NULL && (*crypt)->ops != NULL &&
-	    strcmp((*crypt)->ops->name, "WEP") != 0) {
-		/* changing to use WEP; deinit previously used algorithm
-		 * on this key.
-		 */
-		ieee80211_crypt_delayed_deinit(ieee, crypt);
-	}
-
-	if (*crypt == NULL) {
-		struct ieee80211_crypt_data *new_crypt;
-
-		/* take WEP into use */
-		new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
-				    GFP_KERNEL);
-		if (new_crypt == NULL)
-			return -ENOMEM;
-		new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-		if (!new_crypt->ops)
-			new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-
-		if (new_crypt->ops)
-			new_crypt->priv = new_crypt->ops->init(key);
-
-		if (!new_crypt->ops || !new_crypt->priv) {
-			kfree(new_crypt);
-			new_crypt = NULL;
-
-			netdev_warn(ieee->dev,
-				    "could not initialize WEP: load module ieee80211_crypt_wep\n");
-			return -EOPNOTSUPP;
-		}
-		*crypt = new_crypt;
-	}
-
-	/* If a new key was provided, set it up */
-	if (erq->length > 0) {
-		len = erq->length <= 5 ? 5 : 13;
-		memcpy(sec.keys[key], keybuf, erq->length);
-		if (len > erq->length)
-			memset(sec.keys[key] + erq->length, 0,
-			       len - erq->length);
-		IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
-				   key, escape_essid(sec.keys[key], len),
-				   erq->length, len);
-		sec.key_sizes[key] = len;
-		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
-				       (*crypt)->priv);
-		sec.flags |= (1 << key);
-		/* This ensures a key will be activated if no key is
-		 * explicitly set.
-		 */
-		if (key == sec.active_key)
-			sec.flags |= SEC_ACTIVE_KEY;
-		ieee->tx_keyidx = key;
-	} else {
-		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
-					     NULL, (*crypt)->priv);
-		if (len == 0) {
-			/* Set a default key of all 0 */
-			IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
-					   key);
-			memset(sec.keys[key], 0, 13);
-			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
-					       (*crypt)->priv);
-			sec.key_sizes[key] = 13;
-			sec.flags |= (1 << key);
-		}
-
-		/* No key data - just set the default TX key index */
-		if (key_provided) {
-			IEEE80211_DEBUG_WX(
-				"Setting key %d to default Tx key.\n", key);
-			ieee->tx_keyidx = key;
-			sec.active_key = key;
-			sec.flags |= SEC_ACTIVE_KEY;
-		}
-	}
-
- done:
-	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
-	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
-	sec.flags |= SEC_AUTH_MODE;
-	IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
-			   "OPEN" : "SHARED KEY");
-
-	/* For now we just support WEP, so only set that security level...
-	 * TODO: When WPA is added this is one place that needs to change
-	 */
-	sec.flags |= SEC_LEVEL;
-	sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
-
-	if (ieee->set_security)
-		ieee->set_security(dev, &sec);
-
-	/* Do not reset port if card is in Managed mode since resetting will
-	 * generate new IEEE 802.11 authentication which may end up in looping
-	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
-	 * configuration (for example... Prism2), implement the reset_port in
-	 * the callbacks structures used to initialize the 802.11 stack.
-	 */
-	if (ieee->reset_on_keychange &&
-	    ieee->iw_mode != IW_MODE_INFRA &&
-	    ieee->reset_port && ieee->reset_port(dev)) {
-		netdev_dbg(ieee->dev, "reset_port failed\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *keybuf)
-{
-	struct iw_point *erq = &(wrqu->encoding);
-	int len, key;
-	struct ieee80211_crypt_data *crypt;
-
-	IEEE80211_DEBUG_WX("GET_ENCODE\n");
-
-	if (ieee->iw_mode == IW_MODE_MONITOR)
-		return -1;
-
-	key = erq->flags & IW_ENCODE_INDEX;
-	if (key) {
-		if (key > WEP_KEYS)
-			return -EINVAL;
-		key--;
-	} else
-		key = ieee->tx_keyidx;
-
-	crypt = ieee->crypt[key];
-	erq->flags = key + 1;
-
-	if (crypt == NULL || crypt->ops == NULL) {
-		erq->length = 0;
-		erq->flags |= IW_ENCODE_DISABLED;
-		return 0;
-	}
-
-	if (strcmp(crypt->ops->name, "WEP") != 0) {
-		/* only WEP is supported with wireless extensions, so just
-		 * report that encryption is used.
-		 */
-		erq->length = 0;
-		erq->flags |= IW_ENCODE_ENABLED;
-		return 0;
-	}
-
-	len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
-	erq->length = (len >= 0 ? len : 0);
-
-	erq->flags |= IW_ENCODE_ENABLED;
-
-	if (ieee->open_wep)
-		erq->flags |= IW_ENCODE_OPEN;
-	else
-		erq->flags |= IW_ENCODE_RESTRICTED;
-
-	return 0;
-}
-
-int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	struct net_device *dev = ieee->dev;
-	struct iw_point *encoding = &wrqu->encoding;
-	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-	int i, idx, ret = 0;
-	int group_key = 0;
-	const char *alg;
-	struct ieee80211_crypto_ops *ops;
-	struct ieee80211_crypt_data **crypt;
-
-	struct ieee80211_security sec = {
-		.flags = 0,
-	};
-	idx = encoding->flags & IW_ENCODE_INDEX;
-	if (idx) {
-		if (idx < 1 || idx > WEP_KEYS)
-			return -EINVAL;
-		idx--;
-	} else
-		idx = ieee->tx_keyidx;
-
-	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
-		crypt = &ieee->crypt[idx];
-		group_key = 1;
-	} else {
-		/* some Cisco APs use idx>0 for unicast in dynamic WEP */
-		if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
-			return -EINVAL;
-		if (ieee->iw_mode == IW_MODE_INFRA)
-			crypt = &ieee->crypt[idx];
-		else
-			return -EINVAL;
-	}
-
-	sec.flags |= SEC_ENABLED;
-	if ((encoding->flags & IW_ENCODE_DISABLED) ||
-	    ext->alg == IW_ENCODE_ALG_NONE) {
-		if (*crypt)
-			ieee80211_crypt_delayed_deinit(ieee, crypt);
-
-		for (i = 0; i < WEP_KEYS; i++)
-			if (ieee->crypt[i] != NULL)
-				break;
-
-		if (i == WEP_KEYS) {
-			sec.enabled = 0;
-			sec.level = SEC_LEVEL_0;
-			sec.flags |= SEC_LEVEL;
-		}
-		goto done;
-	}
-
-	sec.enabled = 1;
-
-	switch (ext->alg) {
-	case IW_ENCODE_ALG_WEP:
-		alg = "WEP";
-		break;
-	case IW_ENCODE_ALG_TKIP:
-		alg = "TKIP";
-		break;
-	case IW_ENCODE_ALG_CCMP:
-		alg = "CCMP";
-		break;
-	default:
-		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
-				   dev->name, ext->alg);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	ops = ieee80211_get_crypto_ops(alg);
-	if (ops == NULL)
-		ops = ieee80211_get_crypto_ops(alg);
-	if (ops == NULL) {
-		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
-				   dev->name, ext->alg);
-		netdev_err(ieee->dev, "========>unknown crypto alg %d\n",
-			   ext->alg);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (*crypt == NULL || (*crypt)->ops != ops) {
-		struct ieee80211_crypt_data *new_crypt;
-
-		ieee80211_crypt_delayed_deinit(ieee, crypt);
-
-		new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
-		if (new_crypt == NULL) {
-			ret = -ENOMEM;
-			goto done;
-		}
-		new_crypt->ops = ops;
-		if (new_crypt->ops)
-			new_crypt->priv = new_crypt->ops->init(idx);
-		if (new_crypt->priv == NULL) {
-			kfree(new_crypt);
-			ret = -EINVAL;
-			goto done;
-		}
-		*crypt = new_crypt;
-
-	}
-
-	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
-	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
-				   (*crypt)->priv) < 0) {
-		IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
-		netdev_err(ieee->dev, "key setting failed\n");
-		ret = -EINVAL;
-		goto done;
-	}
-#if 1
-	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
-		ieee->tx_keyidx = idx;
-		sec.active_key = idx;
-		sec.flags |= SEC_ACTIVE_KEY;
-	}
-
-	if (ext->alg != IW_ENCODE_ALG_NONE) {
-		memcpy(sec.keys[idx], ext->key, ext->key_len);
-		sec.key_sizes[idx] = ext->key_len;
-		sec.flags |= (1 << idx);
-		if (ext->alg == IW_ENCODE_ALG_WEP) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_1;
-		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_2;
-		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
-			sec.flags |= SEC_LEVEL;
-			sec.level = SEC_LEVEL_3;
-		}
-		/* Don't set sec level for group keys. */
-		if (group_key)
-			sec.flags &= ~SEC_LEVEL;
-	}
-#endif
-done:
-	if (ieee->set_security)
-		ieee->set_security(ieee->dev, &sec);
-
-	if (ieee->reset_on_keychange &&
-	    ieee->iw_mode != IW_MODE_INFRA &&
-	    ieee->reset_port && ieee->reset_port(dev)) {
-		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
-		return -EINVAL;
-	}
-
-	return ret;
-}
-
-int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
-			  struct iw_request_info *info,
-			  union iwreq_data *wrqu, char *extra)
-{
-	struct iw_mlme *mlme = (struct iw_mlme *) extra;
-#if 1
-	switch (mlme->cmd) {
-	case IW_MLME_DEAUTH:
-	case IW_MLME_DISASSOC:
-		ieee80211_disassociate(ieee);
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-#endif
-	return 0;
-}
-
-int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
-			  struct iw_request_info *info,
-			  struct iw_param *data, char *extra)
-{
-	switch (data->flags & IW_AUTH_INDEX) {
-	case IW_AUTH_WPA_VERSION:
-		/* need to support wpa2 here */
-		break;
-	case IW_AUTH_CIPHER_PAIRWISE:
-	case IW_AUTH_CIPHER_GROUP:
-	case IW_AUTH_KEY_MGMT:
-		/* Host AP driver does not use these parameters and allows
-		 * wpa_supplicant to control them internally.
-		 */
-		break;
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-		ieee->tkip_countermeasures = data->value;
-		break;
-	case IW_AUTH_DROP_UNENCRYPTED:
-		ieee->drop_unencrypted = data->value;
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0;
-		break;
-
-#if 1
-	case IW_AUTH_WPA_ENABLED:
-		ieee->wpa_enabled = (data->value) ? 1 : 0;
-		break;
-
-#endif
-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-		ieee->ieee802_1x = data->value;
-		break;
-	case IW_AUTH_PRIVACY_INVOKED:
-		ieee->privacy_invoked = data->value;
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-#if 1
-int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
-{
-	u8 *buf = NULL;
-
-	if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) {
-		netdev_err(ieee->dev, "return error out, len:%zu\n", len);
-	return -EINVAL;
-	}
-
-	if (len) {
-		if (len != ie[1]+2) {
-			netdev_err(ieee->dev, "len:%zu, ie:%d\n", len, ie[1]);
-			return -EINVAL;
-		}
-		buf = kmemdup(ie, len, GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-		kfree(ieee->wpa_ie);
-		ieee->wpa_ie = buf;
-		ieee->wpa_ie_len = len;
-	} else {
-		kfree(ieee->wpa_ie);
-		ieee->wpa_ie = NULL;
-		ieee->wpa_ie_len = 0;
-	}
-
-	return 0;
-
-}
-#endif
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
deleted file mode 100644
index 9f931dba1d82..000000000000
--- a/drivers/staging/rtl8187se/r8180.h
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * This is part of rtl8180 OpenSource driver.
- * Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
- * Released under the terms of GPL (General Public Licence)
- *
- * Parts of this driver are based on the GPL part of the official realtek driver
- *
- * Parts of this driver are based on the rtl8180 driver skeleton from Patric
- * Schenke & Andres Salomon
- *
- * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
- *
- * We want to thanks the Authors of those projects and the Ndiswrapper project
- * Authors.
- */
-
-#ifndef R8180H
-#define R8180H
-
-#include <linux/interrupt.h>
-
-#define RTL8180_MODULE_NAME "r8180"
-#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
-#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
-#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/rtnetlink.h> /* for rtnl_lock() */
-#include <linux/wireless.h>
-#include <linux/timer.h>
-#include <linux/proc_fs.h> /* Necessary because we use the proc fs. */
-#include <linux/if_arp.h>
-#include "ieee80211/ieee80211.h"
-#include <asm/io.h>
-
-#define EPROM_93c46 0
-#define EPROM_93c56 1
-
-#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
-
-#define DEFAULT_FRAG_THRESHOLD 2342U
-#define MIN_FRAG_THRESHOLD 256U
-#define DEFAULT_RTS_THRESHOLD 2342U
-#define MIN_RTS_THRESHOLD 0U
-#define MAX_RTS_THRESHOLD 2342U
-#define DEFAULT_BEACONINTERVAL 0x64U
-
-#define DEFAULT_RETRY_RTS 7
-#define DEFAULT_RETRY_DATA 7
-
-#define BEACON_QUEUE 6
-
-#define aSifsTime 10
-
-#define sCrcLng 4
-#define sAckCtsLng 112 /* bits in ACK and CTS frames. */
-/* +by amy 080312. */
-#define RATE_ADAPTIVE_TIMER_PERIOD 300
-
-enum wireless_mode {
-	WIRELESS_MODE_UNKNOWN = 0x00,
-	WIRELESS_MODE_A = 0x01,
-	WIRELESS_MODE_B = 0x02,
-	WIRELESS_MODE_G = 0x04,
-	WIRELESS_MODE_AUTO = 0x08,
-};
-
-struct chnl_access_setting {
-	u16 sifs_timer;
-	u16 difs_timer;
-	u16 slot_time_timer;
-	u16 eifs_timer;
-	u16 cwmin_index;
-	u16 cwmax_index;
-};
-
-enum nic_t {
-	NIC_8185 = 1,
-	NIC_8185B
-};
-
-typedef u32 AC_CODING;
-#define AC0_BE	0 /* ACI: 0x00 */ /* Best Effort. */
-#define AC1_BK	1 /* ACI: 0x01 */ /* Background. */
-#define AC2_VI	2 /* ACI: 0x10 */ /* Video. */
-#define AC3_VO	3 /* ACI: 0x11 */ /* Voice. */
-#define AC_MAX	4 /* Max: define total number; Should not to be used as a real
-		   * enum.
-		   */
-
-/*
- * ECWmin/ECWmax field.
- * Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
- */
-typedef union _ECW {
-	u8 charData;
-	struct {
-		u8 ECWmin:4;
-		u8 ECWmax:4;
-	} f;	/* Field */
-} ECW, *PECW;
-
-/*
- * ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
- */
-typedef union _ACI_AIFSN {
-	u8 charData;
-
-	struct {
-		u8 AIFSN:4;
-		u8 ACM:1;
-		u8 ACI:2;
-		u8 Reserved:1;
-	} f;	/* Field */
-} ACI_AIFSN, *PACI_AIFSN;
-
-/*
- * AC Parameters Record Format.
- * Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
- */
-typedef union _AC_PARAM {
-	u32 longData;
-	u8 charData[4];
-
-	struct {
-		ACI_AIFSN AciAifsn;
-		ECW Ecw;
-		u16 TXOPLimit;
-	} f;	/* Field */
-} AC_PARAM, *PAC_PARAM;
-
-struct buffer {
-	struct buffer *next;
-	u32 *buf;
-	dma_addr_t dma;
-};
-
-/* YJ,modified,080828. */
-struct stats {
-	unsigned long txrdu;
-	unsigned long rxrdu;
-	unsigned long rxnolast;
-	unsigned long rxnodata;
-	unsigned long rxnopointer;
-	unsigned long txnperr;
-	unsigned long txresumed;
-	unsigned long rxerr;
-	unsigned long rxoverflow;
-	unsigned long rxint;
-	unsigned long txbkpokint;
-	unsigned long txbepoking;
-	unsigned long txbkperr;
-	unsigned long txbeperr;
-	unsigned long txnpokint;
-	unsigned long txhpokint;
-	unsigned long txhperr;
-	unsigned long ints;
-	unsigned long shints;
-	unsigned long txoverflow;
-	unsigned long rxdmafail;
-	unsigned long txbeacon;
-	unsigned long txbeaconerr;
-	unsigned long txlpokint;
-	unsigned long txlperr;
-	unsigned long txretry; /* retry number tony 20060601 */
-	unsigned long rxcrcerrmin; /* crc error (0-500) */
-	unsigned long rxcrcerrmid; /* crc error (500-1000) */
-	unsigned long rxcrcerrmax; /* crc error (>1000) */
-	unsigned long rxicverr; /* ICV error */
-};
-
-#define MAX_LD_SLOT_NUM 10
-#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */
-#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */
-#define DEFAULT_KEEP_ALIVE_LEVEL 1
-#define DEFAULT_SLOT_NUM 2
-#define POWER_PROFILE_AC 0
-#define POWER_PROFILE_BATTERY 1
-
-struct link_detect_t {
-	u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame.
-					    * CheckForHang_period  to determine
-					    * link status.
-					    */
-	u16 slot_num; /* number of CheckForHang period to determine link status,
-		       * default is 2.
-		       */
-	u16 slot_index;
-	u32 num_tx_ok_in_period; /* number of packet transmitted during
-				  * CheckForHang.
-				  */
-	u32 num_rx_ok_in_period; /* number of packet received during
-				  * CheckForHang.
-				  */
-	u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */
-	u32 last_num_tx_unicast;
-	u32 last_num_rx_unicast;
-
-	bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */
-};
-
-/* YJ,modified,080828,end */
-
-/* by amy for led
- * ==========================================================================
- * LED customization.
- * ==========================================================================
- */
-enum led_strategy_8185 {
-	SW_LED_MODE0,
-	SW_LED_MODE1,
-	HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
-		 * control modes). */
-};
-
-enum rt_rf_power_state {
-	RF_ON,
-	RF_SLEEP,
-	RF_OFF
-};
-
-enum _ReasonCode {
-	unspec_reason = 0x1,
-	auth_not_valid = 0x2,
-	deauth_lv_ss = 0x3,
-	inactivity = 0x4,
-	ap_overload = 0x5,
-	class2_err = 0x6,
-	class3_err = 0x7,
-	disas_lv_ss = 0x8,
-	asoc_not_auth = 0x9,
-
-	/* ----MIC_CHECK */
-	mic_failure = 0xe,
-	/* ----END MIC_CHECK */
-
-	/* Reason code defined in 802.11i D10.0 p.28. */
-	invalid_IE = 0x0d,
-	four_way_tmout = 0x0f,
-	two_way_tmout = 0x10,
-	IE_dismatch = 0x11,
-	invalid_Gcipher	= 0x12,
-	invalid_Pcipher	= 0x13,
-	invalid_AKMP = 0x14,
-	unsup_RSNIEver = 0x15,
-	invalid_RSNIE = 0x16,
-	auth_802_1x_fail = 0x17,
-	ciper_reject = 0x18,
-
-	/* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie,
-	 * 2005-11-15.
-	 */
-	QoS_unspec = 0x20, /* 32 */
-	QAP_bandwidth = 0x21, /* 33 */
-	poor_condition = 0x22, /* 34 */
-	no_facility = 0x23, /* 35 */
-	/* Where is 36??? */
-	req_declined = 0x25, /* 37 */
-	invalid_param = 0x26, /* 38 */
-	req_not_honored = 0x27, /* 39 */
-	TS_not_created = 0x2F, /* 47 */
-	DL_not_allowed = 0x30, /* 48 */
-	dest_not_exist = 0x31, /* 49 */
-	dest_not_QSTA = 0x32, /* 50 */
-};
-
-enum rt_ps_mode {
-	ACTIVE, /* Active/Continuous access. */
-	MAX_PS,	/* Max power save mode. */
-	FAST_PS /* Fast power save mode. */
-};
-
-/* by amy for power save. */
-struct r8180_priv {
-	struct pci_dev *pdev;
-
-	short epromtype;
-	int irq;
-	struct ieee80211_device *ieee80211;
-
-	short plcp_preamble_mode; /* 0:auto 1:short 2:long */
-
-	spinlock_t irq_th_lock;
-	spinlock_t tx_lock;
-	spinlock_t ps_lock;
-	spinlock_t rf_ps_lock;
-
-	u16 irq_mask;
-	short irq_enabled;
-	struct net_device *dev;
-	short chan;
-	short sens;
-	short max_sens;
-	u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */
-	u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */
-	u8 channel_plan;  /* it's the channel plan index. */
-	short up;
-	short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */
-
-	struct timer_list scan_timer;
-	spinlock_t scan_lock;
-	u8 active_probe;
-	struct semaphore wx_sem;
-	short hw_wep;
-
-	short digphy;
-	short antb;
-	short diversity;
-	u32 key0[4];
-	short (*rf_set_sens)(struct net_device *dev, short sens);
-	void (*rf_set_chan)(struct net_device *dev, short ch);
-	void (*rf_close)(struct net_device *dev);
-	void (*rf_init)(struct net_device *dev);
-	void (*rf_sleep)(struct net_device *dev);
-	void (*rf_wakeup)(struct net_device *dev);
-	/* short rate; */
-	short promisc;
-	/* stats */
-	struct stats stats;
-	struct link_detect_t link_detect; /* YJ,add,080828 */
-	struct iw_statistics wstats;
-
-	/* RX stuff. */
-	u32 *rxring;
-	u32 *rxringtail;
-	dma_addr_t rxringdma;
-	struct buffer *rxbuffer;
-	struct buffer *rxbufferhead;
-	int rxringcount;
-	u16 rxbuffersize;
-
-	struct sk_buff *rx_skb;
-
-	short rx_skb_complete;
-
-	u32 rx_prevlen;
-
-	u32 *txmapring;
-	u32 *txbkpring;
-	u32 *txbepring;
-	u32 *txvipring;
-	u32 *txvopring;
-	u32 *txhpring;
-	dma_addr_t txmapringdma;
-	dma_addr_t txbkpringdma;
-	dma_addr_t txbepringdma;
-	dma_addr_t txvipringdma;
-	dma_addr_t txvopringdma;
-	dma_addr_t txhpringdma;
-	u32 *txmapringtail;
-	u32 *txbkpringtail;
-	u32 *txbepringtail;
-	u32 *txvipringtail;
-	u32 *txvopringtail;
-	u32 *txhpringtail;
-	u32 *txmapringhead;
-	u32 *txbkpringhead;
-	u32 *txbepringhead;
-	u32 *txvipringhead;
-	u32 *txvopringhead;
-	u32 *txhpringhead;
-	struct buffer *txmapbufs;
-	struct buffer *txbkpbufs;
-	struct buffer *txbepbufs;
-	struct buffer *txvipbufs;
-	struct buffer *txvopbufs;
-	struct buffer *txhpbufs;
-	struct buffer *txmapbufstail;
-	struct buffer *txbkpbufstail;
-	struct buffer *txbepbufstail;
-	struct buffer *txvipbufstail;
-	struct buffer *txvopbufstail;
-	struct buffer *txhpbufstail;
-
-	int txringcount;
-	int txbuffsize;
-	struct tasklet_struct irq_rx_tasklet;
-	u8 dma_poll_mask;
-
-	/* adhoc/master mode stuff. */
-	u32 *txbeaconringtail;
-	dma_addr_t txbeaconringdma;
-	u32 *txbeaconring;
-	int txbeaconcount;
-	struct buffer *txbeaconbufs;
-	struct buffer *txbeaconbufstail;
-
-	u8 retry_data;
-	u8 retry_rts;
-	u16 rts;
-
-	/* by amy for led. */
-	enum led_strategy_8185 led_strategy;
-	/* by amy for led. */
-
-	/* by amy for power save. */
-	struct timer_list watch_dog_timer;
-	bool bInactivePs;
-	bool bSwRfProcessing;
-	enum rt_rf_power_state eInactivePowerState;
-	enum rt_rf_power_state eRFPowerState;
-	u32 RfOffReason;
-	bool RFChangeInProgress;
-	bool SetRFPowerStateInProgress;
-	u8 RFProgType;
-	bool bLeisurePs;
-	enum rt_ps_mode dot11PowerSaveMode;
-	u8 TxPollingTimes;
-
-	bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will
-			      * keep eAwake until receive data or timeout.
-			      */
-	u8 WaitBufDataBcnCount;
-	u8 WaitBufDataTimeOut;
-
-	/* by amy for power save. */
-	/* by amy for antenna. */
-	u8 EEPROMSwAntennaDiversity;
-	bool EEPROMDefaultAntenna1;
-	u8 RegSwAntennaDiversityMechanism;
-	bool bSwAntennaDiverity;
-	u8 RegDefaultAntenna;
-	bool bDefaultAntenna1;
-	u8 SignalStrength;
-	long Stats_SignalStrength;
-	long LastSignalStrengthInPercent; /* In percentage, used for smoothing,
-					   * e.g. Moving Average.
-					   */
-	u8 SignalQuality; /* in 0-100 index. */
-	long Stats_SignalQuality;
-	long RecvSignalPower; /* in dBm. */
-	long Stats_RecvSignalPower;
-	u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted
-			      * packet. 0: Aux, 1:Main. Added by Roger,
-			      * 2008.01.25.
-			      */
-	u32 AdRxOkCnt;
-	long AdRxSignalStrength;
-	u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */
-	u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */
-	u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx
-			   * signal strength for SW Antenna Diversity.
-			   */
-	u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */
-	u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */
-	long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */
-	long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */
-	bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal
-				   * strength for last time switching antenna.
-				   */
-	long AdRxSsBeforeSwitched; /* Rx signal strength before we switched
-				    * antenna.
-				    */
-	struct timer_list SwAntennaDiversityTimer;
-	/* by amy for antenna {by amy 080312 */
-
-	/* Crystal calibration. Added by Roger, 2007.12.11. */
-
-	bool bXtalCalibration; /* Crystal calibration.*/
-	u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */
-	u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */
-
-	/* Tx power tracking with thermal meter indication.
-	 * Added by Roger, 2007.12.11.
-	 */
-
-	bool bTxPowerTrack; /* Tx Power tracking. */
-	u8 ThermalMeter; /* Thermal meter reference indication. */
-
-	/* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce,
-	 * 2007-02-14.
-	 */
-	bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */
-	bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010,
-				      * by rcnjko.
-				      */
-	u32 FalseAlarmRegValue;
-	u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is
-			      * used in DIG.
-			      */
-	u8 DIG_NumberFallbackVote;
-	u8 DIG_NumberUpgradeVote;
-	/* For HW antenna diversity, added by Roger, 2008.01.30. */
-	u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */
-	u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */
-	bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW
-			     * evaluation.
-			     */
-	/* RF High Power upper/lower threshold. */
-	u8 RegHiPwrUpperTh;
-	u8 RegHiPwrLowerTh;
-	/* RF RSSI High Power upper/lower Threshold. */
-	u8 RegRSSIHiPwrUpperTh;
-	u8 RegRSSIHiPwrLowerTh;
-	/* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ,
-	 * by Bruce, 2007-04-12.
-	 */
-	u8 CurCCKRSSI;
-	bool bCurCCKPkt;
-	/* High Power Mechanism. Added by amy, 080312. */
-	bool bToUpdateTxPwr;
-	long UndecoratedSmoothedSS;
-	long UndecoratedSmoothedRxPower;
-	u8 RSSI;
-	char RxPower;
-	u8 InitialGain;
-	/* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */
-	u32 DozePeriodInPast2Sec;
-	/* Don't access BB/RF under disable PLL situation. */
-	u8 InitialGainBackUp;
-	u8 RegBModeGainStage;
-	/* by amy for rate adaptive */
-	struct timer_list rateadapter_timer;
-	u32 RateAdaptivePeriod;
-	bool bEnhanceTxPwr;
-	bool bUpdateARFR;
-	int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
-			     */
-	u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */
-	u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */
-	unsigned long NumTxOkTotal;
-	u16 LastRetryCnt;
-	u16 LastRetryRate;
-	unsigned long LastTxokCnt;
-	unsigned long LastRxokCnt;
-	u16 CurrRetryCnt;
-	unsigned long LastTxOKBytes;
-	unsigned long NumTxOkBytesTotal;
-	u8 LastFailTxRate;
-	long LastFailTxRateSS;
-	u8 FailTxRateCount;
-	u32 LastTxThroughput;
-	/* for up rate. */
-	unsigned short bTryuping;
-	u8 CurrTxRate; /* the rate before up. */
-	u16 CurrRetryRate;
-	u16 TryupingCount;
-	u8 TryDownCountLowData;
-	u8 TryupingCountNoData;
-
-	u8 CurrentOperaRate;
-	struct work_struct reset_wq;
-	struct work_struct watch_dog_wq;
-	short ack_tx_to_ieee;
-
-	u8 dma_poll_stop_mask;
-
-	u16 ShortRetryLimit;
-	u16 LongRetryLimit;
-	u16 EarlyRxThreshold;
-	u32 TransmitConfig;
-	u32 ReceiveConfig;
-	u32 IntrMask;
-
-	struct chnl_access_setting ChannelAccessSetting;
-};
-
-#define MANAGE_PRIORITY 0
-#define BK_PRIORITY 1
-#define BE_PRIORITY 2
-#define VI_PRIORITY 3
-#define VO_PRIORITY 4
-#define HI_PRIORITY 5
-#define BEACON_PRIORITY 6
-
-#define LOW_PRIORITY VI_PRIORITY
-#define NORM_PRIORITY VO_PRIORITY
-/* AC2Queue mapping. */
-#define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \
-		((_ac) == WME_AC_VI) ? VI_PRIORITY : \
-		((_ac) == WME_AC_BK) ? BK_PRIORITY : \
-		BE_PRIORITY)
-
-short rtl8180_tx(struct net_device *dev, u8 *skbuf, int len, int priority,
-		 bool morefrag, short fragdesc, int rate);
-
-u8 read_nic_byte(struct net_device *dev, int x);
-u32 read_nic_dword(struct net_device *dev, int x);
-u16 read_nic_word(struct net_device *dev, int x);
-void write_nic_byte(struct net_device *dev, int x, u8 y);
-void write_nic_word(struct net_device *dev, int x, u16 y);
-void write_nic_dword(struct net_device *dev, int x, u32 y);
-void force_pci_posting(struct net_device *dev);
-
-void rtl8180_rtx_disable(struct net_device *);
-void rtl8180_set_anaparam(struct net_device *dev, u32 a);
-void rtl8185_set_anaparam2(struct net_device *dev, u32 a);
-void rtl8180_set_hw_wep(struct net_device *dev);
-void rtl8180_no_hw_wep(struct net_device *dev);
-void rtl8180_update_msr(struct net_device *dev);
-void rtl8180_beacon_tx_disable(struct net_device *dev);
-void rtl8180_beacon_rx_disable(struct net_device *dev);
-int rtl8180_down(struct net_device *dev);
-int rtl8180_up(struct net_device *dev);
-void rtl8180_commit(struct net_device *dev);
-void rtl8180_set_chan(struct net_device *dev, short ch);
-void write_phy(struct net_device *dev, u8 adr, u8 data);
-void write_phy_cck(struct net_device *dev, u8 adr, u32 data);
-void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
-void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
-void rtl8185_rf_pins_enable(struct net_device *dev);
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
-int get_curr_tx_free_desc(struct net_device *dev, int priority);
-void UpdateInitialGain(struct net_device *dev);
-bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt,
-			  bool bAntDiversity);
-
-void rtl8185b_adapter_start(struct net_device *dev);
-void rtl8185b_rx_enable(struct net_device *dev);
-void rtl8185b_tx_enable(struct net_device *dev);
-void rtl8180_reset(struct net_device *dev);
-void rtl8185b_irq_enable(struct net_device *dev);
-void fix_rx_fifo(struct net_device *dev);
-void fix_tx_fifo(struct net_device *dev);
-void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch);
-void rtl8180_rate_adapter(struct work_struct *work);
-bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet,
-			 u32 ChangeSource);
-
-#endif
-
-/* fun with the built-in ieee80211 stack... */
-extern int ieee80211_crypto_init(void);
-extern void ieee80211_crypto_deinit(void);
-extern int ieee80211_crypto_tkip_init(void);
-extern void ieee80211_crypto_tkip_exit(void);
-extern int ieee80211_crypto_ccmp_init(void);
-extern void ieee80211_crypto_ccmp_exit(void);
-extern int ieee80211_crypto_wep_init(void);
-extern void ieee80211_crypto_wep_exit(void);
diff --git a/drivers/staging/rtl8187se/r8180_93cx6.h b/drivers/staging/rtl8187se/r8180_93cx6.h
deleted file mode 100644
index b52b5b0610ab..000000000000
--- a/drivers/staging/rtl8187se/r8180_93cx6.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-	This is part of rtl8180 OpenSource driver
-	Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
-	Released under the terms of GPL (General Public Licence)
-
-	Parts of this driver are based on the GPL part of the official realtek driver
-	Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
-	Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
-	We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
-*/
-
-/*This files contains card eeprom (93c46 or 93c56) programming routines*/
-/*memory is addressed by WORDS*/
-
-#include "r8180.h"
-#include "r8180_hw.h"
-
-#define EPROM_DELAY 10
-
-#define EPROM_ANAPARAM_ADDRLWORD 0xd
-#define EPROM_ANAPARAM_ADDRHWORD 0xe
-
-#define RFCHIPID 0x6
-#define	RFCHIPID_INTERSIL 1
-#define	RFCHIPID_RFMD 2
-#define	RFCHIPID_PHILIPS 3
-#define	RFCHIPID_MAXIM 4
-#define	RFCHIPID_GCT 5
-#define RFCHIPID_RTL8225 9
-#define RF_ZEBRA2 11
-#define EPROM_TXPW_BASE 0x05
-#define RF_ZEBRA4 12
-#define RFCHIPID_RTL8255 0xa
-#define RF_PARAM 0x19
-#define RF_PARAM_DIGPHY_SHIFT 0
-#define RF_PARAM_ANTBDEFAULT_SHIFT 1
-#define RF_PARAM_CARRIERSENSE_SHIFT 2
-#define RF_PARAM_CARRIERSENSE_MASK (3<<2)
-#define ENERGY_TRESHOLD 0x17
-#define EPROM_VERSION 0x1E
-#define MAC_ADR 0x7
-
-#define CIS 0x18
-
-#define	EPROM_TXPW_OFDM_CH1_2 0x20
-
-#define	EPROM_TXPW_CH1_2 0x30
-
-#define RTL818X_EEPROM_CMD_READ		(1 << 0)
-#define RTL818X_EEPROM_CMD_WRITE	(1 << 1)
-#define RTL818X_EEPROM_CMD_CK		(1 << 2)
-#define RTL818X_EEPROM_CMD_CS		(1 << 3)
-
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
deleted file mode 100644
index a6022d4e7573..000000000000
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ /dev/null
@@ -1,3775 +0,0 @@
-/*
- * This is part of rtl818x pci OpenSource driver - v 0.1
- * Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
- * Released under the terms of GPL (General Public License)
- *
- * Parts of this driver are based on the GPL part of the official
- * Realtek driver.
- *
- * Parts of this driver are based on the rtl8180 driver skeleton
- * from Patric Schenke & Andres Salomon.
- *
- * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
- *
- * Parts of BB/RF code are derived from David Young rtl8180 netbsd driver.
- *
- * RSSI calc function from 'The Deuce'
- *
- * Some ideas borrowed from the 8139too.c driver included in linux kernel.
- *
- * We (I?) want to thanks the Authors of those projecs and also the
- * Ndiswrapper's project Authors.
- *
- * A big big thanks goes also to Realtek corp. for their help in my attempt to
- * add RTL8185 and RTL8225 support, and to David Young also.
- *
- * Power management interface routines.
- * Written by Mariusz Matuszek.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#undef RX_DONT_PASS_UL
-#undef DUMMY_RX
-
-#include <linux/slab.h>
-#include <linux/syscalls.h>
-#include <linux/eeprom_93cx6.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#include "r8180_hw.h"
-#include "r8180.h"
-#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */
-#include "r8180_93cx6.h"   /* Card EEPROM */
-#include "r8180_wx.h"
-#include "r8180_dm.h"
-
-#include "ieee80211/dot11d.h"
-
-static struct pci_device_id rtl8180_pci_id_tbl[] = {
-	{
-		.vendor = PCI_VENDOR_ID_REALTEK,
-		.device = 0x8199,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-		.driver_data = 0,
-	},
-	{
-		.vendor = 0,
-		.device = 0,
-		.subvendor = 0,
-		.subdevice = 0,
-		.driver_data = 0,
-	}
-};
-
-static char ifname[IFNAMSIZ] = "wlan%d";
-static int hwwep;
-
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
-MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>");
-MODULE_DESCRIPTION("Linux driver for Realtek RTL8187SE WiFi cards");
-
-module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR);
-module_param(hwwep, int, S_IRUGO|S_IWUSR);
-
-MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards");
-
-static int rtl8180_pci_probe(struct pci_dev *pdev,
-			     const struct pci_device_id *id);
-
-static void rtl8180_pci_remove(struct pci_dev *pdev);
-
-static void rtl8180_shutdown(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	if (dev->netdev_ops->ndo_stop)
-		dev->netdev_ops->ndo_stop(dev);
-	pci_disable_device(pdev);
-}
-
-static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-
-	if (!netif_running(dev))
-		goto out_pci_suspend;
-
-	if (dev->netdev_ops->ndo_stop)
-		dev->netdev_ops->ndo_stop(dev);
-
-	netif_device_detach(dev);
-
-out_pci_suspend:
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	return 0;
-}
-
-static int rtl8180_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	int err;
-	u32 val;
-
-	pci_set_power_state(pdev, PCI_D0);
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "pci_enable_device failed on resume\n");
-
-		return err;
-	}
-
-	pci_restore_state(pdev);
-
-	/*
-	 * Suspend/Resume resets the PCI configuration space, so we have to
-	 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
-	 * from interfering with C3 CPU state. pci_restore_state won't help
-	 * here since it only restores the first 64 bytes pci config header.
-	 */
-	pci_read_config_dword(pdev, 0x40, &val);
-	if ((val & 0x0000ff00) != 0)
-		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-	if (!netif_running(dev))
-		goto out;
-
-	if (dev->netdev_ops->ndo_open)
-		dev->netdev_ops->ndo_open(dev);
-
-	netif_device_attach(dev);
-out:
-	return 0;
-}
-
-static struct pci_driver rtl8180_pci_driver = {
-	.name		= RTL8180_MODULE_NAME,
-	.id_table	= rtl8180_pci_id_tbl,
-	.probe		= rtl8180_pci_probe,
-	.remove		= rtl8180_pci_remove,
-	.suspend	= rtl8180_suspend,
-	.resume		= rtl8180_resume,
-	.shutdown	= rtl8180_shutdown,
-};
-
-u8 read_nic_byte(struct net_device *dev, int x)
-{
-	return 0xff&readb((u8 __iomem *)dev->mem_start + x);
-}
-
-u32 read_nic_dword(struct net_device *dev, int x)
-{
-	return readl((u8 __iomem *)dev->mem_start + x);
-}
-
-u16 read_nic_word(struct net_device *dev, int x)
-{
-	return readw((u8 __iomem *)dev->mem_start + x);
-}
-
-void write_nic_byte(struct net_device *dev, int x, u8 y)
-{
-	writeb(y, (u8 __iomem *)dev->mem_start + x);
-	udelay(20);
-}
-
-void write_nic_dword(struct net_device *dev, int x, u32 y)
-{
-	writel(y, (u8 __iomem *)dev->mem_start + x);
-	udelay(20);
-}
-
-void write_nic_word(struct net_device *dev, int x, u16 y)
-{
-	writew(y, (u8 __iomem *)dev->mem_start + x);
-	udelay(20);
-}
-
-inline void force_pci_posting(struct net_device *dev)
-{
-	read_nic_byte(dev, EPROM_CMD);
-	mb();
-}
-
-static irqreturn_t rtl8180_interrupt(int irq, void *netdev);
-void set_nic_rxring(struct net_device *dev);
-void set_nic_txring(struct net_device *dev);
-static struct net_device_stats *rtl8180_stats(struct net_device *dev);
-void rtl8180_commit(struct net_device *dev);
-void rtl8180_start_tx_beacon(struct net_device *dev);
-
-static struct proc_dir_entry *rtl8180_proc;
-
-static int proc_get_registers(struct seq_file *m, void *v)
-{
-	struct net_device *dev = m->private;
-	int i, n, max = 0xff;
-
-	/* This dump the current register page */
-	for (n = 0; n <= max;) {
-		seq_printf(m, "\nD:  %2x > ", n);
-
-		for (i = 0; i < 16 && n <= max; i++, n++)
-			seq_printf(m, "%2x ", read_nic_byte(dev, n));
-	}
-	seq_putc(m, '\n');
-	return 0;
-}
-
-int get_curr_tx_free_desc(struct net_device *dev, int priority);
-
-static int proc_get_stats_hw(struct seq_file *m, void *v)
-{
-	return 0;
-}
-
-static int proc_get_stats_rx(struct seq_file *m, void *v)
-{
-	struct net_device *dev = m->private;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	seq_printf(m,
-		"RX OK: %lu\n"
-		"RX Retry: %lu\n"
-		"RX CRC Error(0-500): %lu\n"
-		"RX CRC Error(500-1000): %lu\n"
-		"RX CRC Error(>1000): %lu\n"
-		"RX ICV Error: %lu\n",
-		priv->stats.rxint,
-		priv->stats.rxerr,
-		priv->stats.rxcrcerrmin,
-		priv->stats.rxcrcerrmid,
-		priv->stats.rxcrcerrmax,
-		priv->stats.rxicverr
-		);
-
-	return 0;
-}
-
-static int proc_get_stats_tx(struct seq_file *m, void *v)
-{
-	struct net_device *dev = m->private;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	unsigned long totalOK;
-
-	totalOK = priv->stats.txnpokint + priv->stats.txhpokint +
-		priv->stats.txlpokint;
-
-	seq_printf(m,
-		"TX OK: %lu\n"
-		"TX Error: %lu\n"
-		"TX Retry: %lu\n"
-		"TX beacon OK: %lu\n"
-		"TX beacon error: %lu\n",
-		totalOK,
-		priv->stats.txnperr+priv->stats.txhperr+priv->stats.txlperr,
-		priv->stats.txretry,
-		priv->stats.txbeacon,
-		priv->stats.txbeaconerr
-	);
-
-	return 0;
-}
-
-static void rtl8180_proc_module_init(void)
-{
-	DMESG("Initializing proc filesystem");
-	rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net);
-}
-
-static void rtl8180_proc_module_remove(void)
-{
-	remove_proc_entry(RTL8180_MODULE_NAME, init_net.proc_net);
-}
-
-static void rtl8180_proc_remove_one(struct net_device *dev)
-{
-	remove_proc_subtree(dev->name, rtl8180_proc);
-}
-
-/*
- * seq_file wrappers for procfile show routines.
- */
-static int rtl8180_proc_open(struct inode *inode, struct file *file)
-{
-	struct net_device *dev = proc_get_parent_data(inode);
-	int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
-
-	return single_open(file, show, dev);
-}
-
-static const struct file_operations rtl8180_proc_fops = {
-	.open		= rtl8180_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * Table of proc files we need to create.
- */
-struct rtl8180_proc_file {
-	char name[12];
-	int (*show)(struct seq_file *, void *);
-};
-
-static const struct rtl8180_proc_file rtl8180_proc_files[] = {
-	{ "stats-hw",	&proc_get_stats_hw },
-	{ "stats-rx",	&proc_get_stats_rx },
-	{ "stats-tx",	&proc_get_stats_tx },
-	{ "registers",	&proc_get_registers },
-	{ "" }
-};
-
-static void rtl8180_proc_init_one(struct net_device *dev)
-{
-	const struct rtl8180_proc_file *f;
-	struct proc_dir_entry *dir;
-
-	dir = proc_mkdir_data(dev->name, 0, rtl8180_proc, dev);
-	if (!dir) {
-		DMESGE("Unable to initialize /proc/net/r8180/%s\n", dev->name);
-		return;
-	}
-
-	for (f = rtl8180_proc_files; f->name[0]; f++) {
-		if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
-				      &rtl8180_proc_fops, f->show)) {
-			DMESGE("Unable to initialize /proc/net/r8180/%s/%s\n",
-			       dev->name, f->name);
-			return;
-		}
-	}
-}
-
-/*
- * FIXME: check if we can use some standard already-existent
- * data type+functions in kernel.
- */
-
-static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma,
-			struct buffer **bufferhead)
-{
-	struct buffer *tmp;
-
-	if (!*buffer) {
-
-		*buffer = kmalloc(sizeof(struct buffer), GFP_KERNEL);
-
-		if (*buffer == NULL) {
-			DMESGE("Failed to kmalloc head of TX/RX struct");
-			return -1;
-		}
-		(*buffer)->next = *buffer;
-		(*buffer)->buf = buf;
-		(*buffer)->dma = dma;
-		if (bufferhead != NULL)
-			(*bufferhead) = (*buffer);
-		return 0;
-	}
-	tmp = *buffer;
-
-	while (tmp->next != (*buffer))
-		tmp = tmp->next;
-	tmp->next = kmalloc(sizeof(struct buffer), GFP_KERNEL);
-	if (tmp->next == NULL) {
-		DMESGE("Failed to kmalloc TX/RX struct");
-		return -1;
-	}
-	tmp->next->buf = buf;
-	tmp->next->dma = dma;
-	tmp->next->next = *buffer;
-
-	return 0;
-}
-
-static void buffer_free(struct net_device *dev, struct buffer **buffer, int len,
-		 short consistent)
-{
-
-	struct buffer *tmp, *next;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct pci_dev *pdev = priv->pdev;
-
-	if (!*buffer)
-		return;
-
-	tmp = *buffer;
-
-	do {
-		next = tmp->next;
-		if (consistent) {
-			pci_free_consistent(pdev, len,
-				    tmp->buf, tmp->dma);
-		} else {
-			pci_unmap_single(pdev, tmp->dma,
-			len, PCI_DMA_FROMDEVICE);
-			kfree(tmp->buf);
-		}
-		kfree(tmp);
-		tmp = next;
-	} while (next != *buffer);
-
-	*buffer = NULL;
-}
-
-int get_curr_tx_free_desc(struct net_device *dev, int priority)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u32 *tail;
-	u32 *head;
-	int ret;
-
-	switch (priority) {
-	case MANAGE_PRIORITY:
-		head = priv->txmapringhead;
-		tail = priv->txmapringtail;
-		break;
-	case BK_PRIORITY:
-		head = priv->txbkpringhead;
-		tail = priv->txbkpringtail;
-		break;
-	case BE_PRIORITY:
-		head = priv->txbepringhead;
-		tail = priv->txbepringtail;
-		break;
-	case VI_PRIORITY:
-		head = priv->txvipringhead;
-		tail = priv->txvipringtail;
-		break;
-	case VO_PRIORITY:
-		head = priv->txvopringhead;
-		tail = priv->txvopringtail;
-		break;
-	case HI_PRIORITY:
-		head = priv->txhpringhead;
-		tail = priv->txhpringtail;
-		break;
-	default:
-		return -1;
-	}
-
-	if (head <= tail)
-		ret = priv->txringcount - (tail - head)/8;
-	else
-		ret = (head - tail)/8;
-
-	if (ret > priv->txringcount)
-		DMESG("BUG");
-
-	return ret;
-}
-
-static short check_nic_enought_desc(struct net_device *dev, int priority)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = netdev_priv(dev);
-	int requiredbyte;
-	int required;
-
-	requiredbyte = priv->ieee80211->fts +
-		sizeof(struct ieee80211_header_data);
-
-	if (ieee->current_network.QoS_Enable)
-		requiredbyte += 2;
-
-	required = requiredbyte / (priv->txbuffsize-4);
-
-	if (requiredbyte % priv->txbuffsize)
-		required++;
-
-	/* for now we keep two free descriptor as a safety boundary
-	 * between the tail and the head
-	 */
-
-	return required + 2 < get_curr_tx_free_desc(dev, priority);
-}
-
-void fix_tx_fifo(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u32 *tmp;
-	int i;
-
-	for (tmp = priv->txmapring, i = 0;
-	     i < priv->txringcount;
-	     tmp += 8, i++) {
-		*tmp = *tmp & ~(1<<31);
-	}
-
-	for (tmp = priv->txbkpring, i = 0;
-	     i < priv->txringcount;
-	     tmp += 8, i++) {
-		*tmp = *tmp & ~(1<<31);
-	}
-
-	for (tmp = priv->txbepring, i = 0;
-	     i < priv->txringcount;
-	     tmp += 8, i++) {
-		*tmp = *tmp & ~(1<<31);
-	}
-	for (tmp = priv->txvipring, i = 0;
-	     i < priv->txringcount;
-	     tmp += 8, i++) {
-		*tmp = *tmp & ~(1<<31);
-	}
-
-	for (tmp = priv->txvopring, i = 0;
-	     i < priv->txringcount;
-	     tmp += 8, i++) {
-		*tmp = *tmp & ~(1<<31);
-	}
-
-	for (tmp = priv->txhpring, i = 0;
-	     i < priv->txringcount;
-	     tmp += 8, i++) {
-		*tmp = *tmp & ~(1<<31);
-	}
-
-	for (tmp = priv->txbeaconring, i = 0;
-	     i < priv->txbeaconcount;
-	     tmp += 8, i++) {
-		*tmp = *tmp & ~(1<<31);
-	}
-
-	priv->txmapringtail = priv->txmapring;
-	priv->txmapringhead = priv->txmapring;
-	priv->txmapbufstail = priv->txmapbufs;
-
-	priv->txbkpringtail = priv->txbkpring;
-	priv->txbkpringhead = priv->txbkpring;
-	priv->txbkpbufstail = priv->txbkpbufs;
-
-	priv->txbepringtail = priv->txbepring;
-	priv->txbepringhead = priv->txbepring;
-	priv->txbepbufstail = priv->txbepbufs;
-
-	priv->txvipringtail = priv->txvipring;
-	priv->txvipringhead = priv->txvipring;
-	priv->txvipbufstail = priv->txvipbufs;
-
-	priv->txvopringtail = priv->txvopring;
-	priv->txvopringhead = priv->txvopring;
-	priv->txvopbufstail = priv->txvopbufs;
-
-	priv->txhpringtail = priv->txhpring;
-	priv->txhpringhead = priv->txhpring;
-	priv->txhpbufstail = priv->txhpbufs;
-
-	priv->txbeaconringtail = priv->txbeaconring;
-	priv->txbeaconbufstail = priv->txbeaconbufs;
-	set_nic_txring(dev);
-
-	ieee80211_reset_queue(priv->ieee80211);
-	priv->ack_tx_to_ieee = 0;
-}
-
-void fix_rx_fifo(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u32 *tmp;
-	struct buffer *rxbuf;
-	u8 rx_desc_size;
-
-	rx_desc_size = 8; /* 4*8 = 32 bytes */
-
-	for (tmp = priv->rxring, rxbuf = priv->rxbufferhead;
-	     (tmp < (priv->rxring)+(priv->rxringcount)*rx_desc_size);
-	     tmp += rx_desc_size, rxbuf = rxbuf->next) {
-		*(tmp+2) = rxbuf->dma;
-		*tmp = *tmp & ~0xfff;
-		*tmp = *tmp | priv->rxbuffersize;
-		*tmp |= (1<<31);
-	}
-
-	priv->rxringtail = priv->rxring;
-	priv->rxbuffer = priv->rxbufferhead;
-	priv->rx_skb_complete = 1;
-	set_nic_rxring(dev);
-}
-
-static void rtl8180_irq_disable(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	write_nic_dword(dev, IMR, 0);
-	force_pci_posting(dev);
-	priv->irq_enabled = 0;
-}
-
-void rtl8180_set_mode(struct net_device *dev, int mode)
-{
-	u8 ecmd;
-
-	ecmd = read_nic_byte(dev, EPROM_CMD);
-	ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
-	ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
-	ecmd = ecmd & ~(1<<EPROM_CS_SHIFT);
-	ecmd = ecmd & ~(1<<EPROM_CK_SHIFT);
-	write_nic_byte(dev, EPROM_CMD, ecmd);
-}
-
-void rtl8180_beacon_tx_enable(struct net_device *dev);
-
-void rtl8180_update_msr(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8 msr;
-	u32 rxconf;
-
-	msr  = read_nic_byte(dev, MSR);
-	msr &= ~MSR_LINK_MASK;
-
-	rxconf = read_nic_dword(dev, RX_CONF);
-
-	if (priv->ieee80211->state == IEEE80211_LINKED)	{
-		if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-			msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
-		else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
-			msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
-		else if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
-			msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
-		else
-			msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
-		rxconf |= (1<<RX_CHECK_BSSID_SHIFT);
-
-	} else {
-		msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
-		rxconf &= ~(1<<RX_CHECK_BSSID_SHIFT);
-	}
-
-	write_nic_byte(dev, MSR, msr);
-	write_nic_dword(dev, RX_CONF, rxconf);
-}
-
-void rtl8180_set_chan(struct net_device *dev, short ch)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	if ((ch > 14) || (ch < 1)) {
-		netdev_err(dev, "In %s: Invalid channel %d\n", __func__, ch);
-		return;
-	}
-
-	priv->chan = ch;
-	priv->rf_set_chan(dev, priv->chan);
-}
-
-void set_nic_txring(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	write_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR, priv->txmapringdma);
-	write_nic_dword(dev, TX_BKPRIORITY_RING_ADDR, priv->txbkpringdma);
-	write_nic_dword(dev, TX_BEPRIORITY_RING_ADDR, priv->txbepringdma);
-	write_nic_dword(dev, TX_VIPRIORITY_RING_ADDR, priv->txvipringdma);
-	write_nic_dword(dev, TX_VOPRIORITY_RING_ADDR, priv->txvopringdma);
-	write_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR, priv->txhpringdma);
-	write_nic_dword(dev, TX_BEACON_RING_ADDR, priv->txbeaconringdma);
-}
-
-void rtl8180_beacon_tx_enable(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_BQ);
-	write_nic_byte(dev, TPPollStop, priv->dma_poll_mask);
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-void rtl8180_beacon_tx_disable(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	priv->dma_poll_stop_mask |= TPPOLLSTOP_BQ;
-	write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-}
-
-void rtl8180_rtx_disable(struct net_device *dev)
-{
-	u8 cmd;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	cmd = read_nic_byte(dev, CMD);
-	write_nic_byte(dev, CMD, cmd &
-		       ~((1<<CMD_RX_ENABLE_SHIFT)|(1<<CMD_TX_ENABLE_SHIFT)));
-	force_pci_posting(dev);
-	mdelay(10);
-
-	if (!priv->rx_skb_complete)
-		dev_kfree_skb_any(priv->rx_skb);
-}
-
-static short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count,
-				int addr)
-{
-	int i;
-	u32 *desc;
-	u32 *tmp;
-	dma_addr_t dma_desc, dma_tmp;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct pci_dev *pdev = priv->pdev;
-	void *buf;
-
-	if ((bufsize & 0xfff) != bufsize) {
-		DMESGE("TX buffer allocation too large");
-		return 0;
-	}
-	desc = (u32 *)pci_alloc_consistent(pdev,
-					  sizeof(u32)*8*count+256, &dma_desc);
-	if (desc == NULL)
-		return -1;
-
-	if (dma_desc & 0xff)
-		/*
-		 * descriptor's buffer must be 256 byte aligned
-		 * we shouldn't be here, since we set DMA mask !
-		 */
-		WARN(1, "DMA buffer is not aligned\n");
-
-	tmp = desc;
-
-	for (i = 0; i < count; i++) {
-		buf = (void *)pci_alloc_consistent(pdev, bufsize, &dma_tmp);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		switch (addr) {
-		case TX_MANAGEPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&priv->txmapbufs,
-				buf, dma_tmp, NULL)) {
-				DMESGE("Unable to allocate mem for buffer NP");
-				return -ENOMEM;
-			}
-			break;
-		case TX_BKPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&priv->txbkpbufs,
-				buf, dma_tmp, NULL)) {
-				DMESGE("Unable to allocate mem for buffer LP");
-				return -ENOMEM;
-			}
-			break;
-		case TX_BEPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&priv->txbepbufs,
-				buf, dma_tmp, NULL)) {
-				DMESGE("Unable to allocate mem for buffer NP");
-				return -ENOMEM;
-			}
-			break;
-		case TX_VIPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&priv->txvipbufs,
-				buf, dma_tmp, NULL)) {
-				DMESGE("Unable to allocate mem for buffer LP");
-				return -ENOMEM;
-			}
-			break;
-		case TX_VOPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&priv->txvopbufs,
-				buf, dma_tmp, NULL)) {
-				DMESGE("Unable to allocate mem for buffer NP");
-				return -ENOMEM;
-			}
-			break;
-		case TX_HIGHPRIORITY_RING_ADDR:
-			if (-1 == buffer_add(&priv->txhpbufs,
-				buf, dma_tmp, NULL)) {
-				DMESGE("Unable to allocate mem for buffer HP");
-				return -ENOMEM;
-			}
-			break;
-		case TX_BEACON_RING_ADDR:
-			if (-1 == buffer_add(&priv->txbeaconbufs,
-				buf, dma_tmp, NULL)) {
-				DMESGE("Unable to allocate mem for buffer BP");
-				return -ENOMEM;
-			}
-			break;
-		}
-		*tmp = *tmp & ~(1<<31); /* descriptor empty, owned by the drv */
-		*(tmp+2) = (u32)dma_tmp;
-		*(tmp+3) = bufsize;
-
-		if (i+1 < count)
-			*(tmp+4) = (u32)dma_desc+((i+1)*8*4);
-		else
-			*(tmp+4) = (u32)dma_desc;
-
-		tmp = tmp+8;
-	}
-
-	switch (addr) {
-	case TX_MANAGEPRIORITY_RING_ADDR:
-		priv->txmapringdma = dma_desc;
-		priv->txmapring = desc;
-		break;
-	case TX_BKPRIORITY_RING_ADDR:
-		priv->txbkpringdma = dma_desc;
-		priv->txbkpring = desc;
-		break;
-	case TX_BEPRIORITY_RING_ADDR:
-		priv->txbepringdma = dma_desc;
-		priv->txbepring = desc;
-		break;
-	case TX_VIPRIORITY_RING_ADDR:
-		priv->txvipringdma = dma_desc;
-		priv->txvipring = desc;
-		break;
-	case TX_VOPRIORITY_RING_ADDR:
-		priv->txvopringdma = dma_desc;
-		priv->txvopring = desc;
-		break;
-	case TX_HIGHPRIORITY_RING_ADDR:
-		priv->txhpringdma = dma_desc;
-		priv->txhpring = desc;
-		break;
-	case TX_BEACON_RING_ADDR:
-		priv->txbeaconringdma = dma_desc;
-		priv->txbeaconring = desc;
-		break;
-
-	}
-
-	return 0;
-}
-
-static void free_tx_desc_rings(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct pci_dev *pdev = priv->pdev;
-	int count = priv->txringcount;
-
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->txmapring, priv->txmapringdma);
-	buffer_free(dev, &(priv->txmapbufs), priv->txbuffsize, 1);
-
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->txbkpring, priv->txbkpringdma);
-	buffer_free(dev, &(priv->txbkpbufs), priv->txbuffsize, 1);
-
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->txbepring, priv->txbepringdma);
-	buffer_free(dev, &(priv->txbepbufs), priv->txbuffsize, 1);
-
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->txvipring, priv->txvipringdma);
-	buffer_free(dev, &(priv->txvipbufs), priv->txbuffsize, 1);
-
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->txvopring, priv->txvopringdma);
-	buffer_free(dev, &(priv->txvopbufs), priv->txbuffsize, 1);
-
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->txhpring, priv->txhpringdma);
-	buffer_free(dev, &(priv->txhpbufs), priv->txbuffsize, 1);
-
-	count = priv->txbeaconcount;
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->txbeaconring, priv->txbeaconringdma);
-	buffer_free(dev, &(priv->txbeaconbufs), priv->txbuffsize, 1);
-}
-
-static void free_rx_desc_ring(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct pci_dev *pdev = priv->pdev;
-	int count = priv->rxringcount;
-
-	pci_free_consistent(pdev, sizeof(u32)*8*count+256,
-			    priv->rxring, priv->rxringdma);
-
-	buffer_free(dev, &(priv->rxbuffer), priv->rxbuffersize, 0);
-}
-
-static short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
-{
-	int i;
-	u32 *desc;
-	u32 *tmp;
-	dma_addr_t dma_desc, dma_tmp;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct pci_dev *pdev = priv->pdev;
-	void *buf;
-	u8 rx_desc_size;
-
-	rx_desc_size = 8; /* 4*8 = 32 bytes */
-
-	if ((bufsize & 0xfff) != bufsize) {
-		DMESGE("RX buffer allocation too large");
-		return -1;
-	}
-
-	desc = (u32 *)pci_alloc_consistent(pdev,
-		sizeof(u32) * rx_desc_size * count + 256, &dma_desc);
-
-	if (dma_desc & 0xff)
-		/*
-		 * descriptor's buffer must be 256 byte aligned
-		 * should never happen since we specify the DMA mask
-		 */
-		WARN(1, "DMA buffer is not aligned\n");
-
-	priv->rxring = desc;
-	priv->rxringdma = dma_desc;
-	tmp = desc;
-
-	for (i = 0; i < count; i++) {
-		buf = kmalloc(bufsize * sizeof(u8), GFP_ATOMIC);
-		if (buf == NULL) {
-			DMESGE("Failed to kmalloc RX buffer");
-			return -1;
-		}
-
-		dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8),
-					 PCI_DMA_FROMDEVICE);
-		if (pci_dma_mapping_error(pdev, dma_tmp))
-			return -1;
-		if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp,
-			   &(priv->rxbufferhead))) {
-			DMESGE("Unable to allocate mem RX buf");
-			return -1;
-		}
-		*tmp = 0; /* zero pads the header of the descriptor */
-		*tmp = *tmp | (bufsize&0xfff);
-		*(tmp+2) = (u32)dma_tmp;
-		*tmp = *tmp | (1<<31); /* descriptor void, owned by the NIC */
-
-		tmp = tmp+rx_desc_size;
-	}
-
-	/* this is the last descriptor */
-	*(tmp - rx_desc_size) = *(tmp - rx_desc_size) | (1 << 30);
-
-	return 0;
-}
-
-
-void set_nic_rxring(struct net_device *dev)
-{
-	u8 pgreg;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	pgreg = read_nic_byte(dev, PGSELECT);
-	write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT));
-
-	write_nic_dword(dev, RXRING_ADDR, priv->rxringdma);
-}
-
-void rtl8180_reset(struct net_device *dev)
-{
-	u8 cr;
-
-	rtl8180_irq_disable(dev);
-
-	cr = read_nic_byte(dev, CMD);
-	cr = cr & 2;
-	cr = cr | (1<<CMD_RST_SHIFT);
-	write_nic_byte(dev, CMD, cr);
-
-	force_pci_posting(dev);
-
-	mdelay(200);
-
-	if (read_nic_byte(dev, CMD) & (1<<CMD_RST_SHIFT))
-		DMESGW("Card reset timeout!");
-	else
-		DMESG("Card successfully reset");
-
-	rtl8180_set_mode(dev, EPROM_CMD_LOAD);
-	force_pci_posting(dev);
-	mdelay(200);
-}
-
-inline u16 ieeerate2rtlrate(int rate)
-{
-	switch (rate) {
-	case 10:
-		return 0;
-	case 20:
-		return 1;
-	case 55:
-		return 2;
-	case 110:
-		return 3;
-	case 60:
-		return 4;
-	case 90:
-		return 5;
-	case 120:
-		return 6;
-	case 180:
-		return 7;
-	case 240:
-		return 8;
-	case 360:
-		return 9;
-	case 480:
-		return 10;
-	case 540:
-		return 11;
-	default:
-		return 3;
-	}
-}
-
-static u16 rtl_rate[] = {10, 20, 55, 110, 60,
-	90, 120, 180, 240, 360, 480, 540, 720};
-
-inline u16 rtl8180_rate2rate(short rate)
-{
-	if (rate > 12)
-		return 10;
-	return rtl_rate[rate];
-}
-
-inline u8 rtl8180_IsWirelessBMode(u16 rate)
-{
-	if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
-		return 1;
-	else
-		return 0;
-}
-
-u16 N_DBPSOfRate(u16 DataRate);
-
-static u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
-		  u8 bShortPreamble)
-{
-	u16	FrameTime;
-	u16	N_DBPS;
-	u16	Ceiling;
-
-	if (rtl8180_IsWirelessBMode(DataRate)) {
-		if (bManagementFrame || !bShortPreamble || DataRate == 10)
-			/* long preamble */
-			FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
-		else
-			/* short preamble */
-			FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
-
-		if ((FrameLength*8 % (DataRate/10)) != 0) /* get the ceilling */
-			FrameTime++;
-	} else {	/* 802.11g DSSS-OFDM PLCP length field calculation. */
-		N_DBPS = N_DBPSOfRate(DataRate);
-		Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
-				+ (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
-		FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
-	}
-	return FrameTime;
-}
-
-u16 N_DBPSOfRate(u16 DataRate)
-{
-	 u16 N_DBPS = 24;
-
-	switch (DataRate) {
-	case 60:
-		N_DBPS = 24;
-		break;
-	case 90:
-		N_DBPS = 36;
-		break;
-	case 120:
-		N_DBPS = 48;
-		break;
-	case 180:
-		N_DBPS = 72;
-		break;
-	case 240:
-		N_DBPS = 96;
-		break;
-	case 360:
-		N_DBPS = 144;
-		break;
-	case 480:
-		N_DBPS = 192;
-		break;
-	case 540:
-		N_DBPS = 216;
-		break;
-	default:
-		break;
-	}
-
-	return N_DBPS;
-}
-
-/*
- * For Netgear case, they want good-looking signal strength.
- */
-static long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
-{
-	long RetSS;
-
-	/* Step 1. Scale mapping. */
-	if (CurrSS >= 71 && CurrSS <= 100)
-		RetSS = 90 + ((CurrSS - 70) / 3);
-	else if (CurrSS >= 41 && CurrSS <= 70)
-		RetSS = 78 + ((CurrSS - 40) / 3);
-	else if (CurrSS >= 31 && CurrSS <= 40)
-		RetSS = 66 + (CurrSS - 30);
-	else if (CurrSS >= 21 && CurrSS <= 30)
-		RetSS = 54 + (CurrSS - 20);
-	else if (CurrSS >= 5 && CurrSS <= 20)
-		RetSS = 42 + (((CurrSS - 5) * 2) / 3);
-	else if (CurrSS == 4)
-		RetSS = 36;
-	else if (CurrSS == 3)
-		RetSS = 27;
-	else if (CurrSS == 2)
-		RetSS = 18;
-	else if (CurrSS == 1)
-		RetSS = 9;
-	else
-		RetSS = CurrSS;
-
-	/* Step 2. Smoothing. */
-	if (LastSS > 0)
-		RetSS = ((LastSS * 5) + (RetSS) + 5) / 6;
-
-	return RetSS;
-}
-
-/*
- * Translate 0-100 signal strength index into dBm.
- */
-static long TranslateToDbm8185(u8 SignalStrengthIndex)
-{
-	long SignalPower;
-
-	/* Translate to dBm (x=0.5y-95). */
-	SignalPower = (long)((SignalStrengthIndex + 1) >> 1);
-	SignalPower -= 95;
-
-	return SignalPower;
-}
-
-/*
- * Perform signal smoothing for dynamic mechanism.
- * This is different with PerformSignalSmoothing8185 in smoothing formula.
- * No dramatic adjustment is applied because dynamic mechanism need some
- * degree of correctness. Ported from 8187B.
- */
-static void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
-						  bool bCckRate)
-{
-	long smoothedSS;
-	long smoothedRx;
-
-	/* Determine the current packet is CCK rate. */
-	priv->bCurCCKPkt = bCckRate;
-
-	smoothedSS = priv->SignalStrength * 10;
-
-	if (priv->UndecoratedSmoothedSS >= 0)
-		smoothedSS = ((priv->UndecoratedSmoothedSS * 5) +
-				smoothedSS) / 6;
-
-	priv->UndecoratedSmoothedSS = smoothedSS;
-
-	smoothedRx = ((priv->UndecoratedSmoothedRxPower * 50) +
-			(priv->RxPower * 11)) / 60;
-
-	priv->UndecoratedSmoothedRxPower = smoothedRx;
-
-	if (bCckRate)
-		priv->CurCCKRSSI = priv->RSSI;
-	else
-		priv->CurCCKRSSI = 0;
-}
-
-
-/*
- * This is rough RX isr handling routine
- */
-static void rtl8180_rx(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct sk_buff *tmp_skb;
-	short first, last;
-	u32 len;
-	int lastlen;
-	unsigned char quality, signal;
-	u8 rate;
-	u32 *tmp, *tmp2;
-	u8 rx_desc_size;
-	u8 padding;
-	char rxpower = 0;
-	u32 RXAGC = 0;
-	long RxAGC_dBm = 0;
-	u8	LNA = 0, BB = 0;
-	u8	LNA_gain[4] = {02, 17, 29, 39};
-	u8  Antenna = 0;
-	struct ieee80211_hdr_4addr *hdr;
-	u16 fc, type;
-	u8 bHwError = 0, bCRC = 0, bICV = 0;
-	bool	bCckRate = false;
-	u8     RSSI = 0;
-	long	SignalStrengthIndex = 0;
-	struct ieee80211_rx_stats stats = {
-		.signal = 0,
-		.noise = -98,
-		.rate = 0,
-		.freq = IEEE80211_24GHZ_BAND,
-	};
-
-	stats.nic_type = NIC_8185B;
-	rx_desc_size = 8;
-
-	if ((*(priv->rxringtail)) & (1<<31)) {
-		/* we have got an RX int, but the descriptor. we are pointing
-		 * is empty.
-		 */
-
-		priv->stats.rxnodata++;
-		priv->ieee80211->stats.rx_errors++;
-
-		tmp2 = NULL;
-		tmp = priv->rxringtail;
-		do {
-			if (tmp == priv->rxring)
-				tmp  = priv->rxring + (priv->rxringcount - 1) *
-					rx_desc_size;
-			else
-				tmp -= rx_desc_size;
-
-			if (!(*tmp & (1<<31)))
-				tmp2 = tmp;
-		} while (tmp != priv->rxring);
-
-		if (tmp2)
-			priv->rxringtail = tmp2;
-	}
-
-	/* while there are filled descriptors */
-	while (!(*(priv->rxringtail) & (1<<31))) {
-		if (*(priv->rxringtail) & (1<<26))
-			DMESGW("RX buffer overflow");
-		if (*(priv->rxringtail) & (1<<12))
-			priv->stats.rxicverr++;
-
-		if (*(priv->rxringtail) & (1<<27)) {
-			priv->stats.rxdmafail++;
-			goto drop;
-		}
-
-		pci_dma_sync_single_for_cpu(priv->pdev,
-				    priv->rxbuffer->dma,
-				    priv->rxbuffersize * sizeof(u8),
-				    PCI_DMA_FROMDEVICE);
-
-		first = *(priv->rxringtail) & (1<<29) ? 1 : 0;
-		if (first)
-			priv->rx_prevlen = 0;
-
-		last = *(priv->rxringtail) & (1<<28) ? 1 : 0;
-		if (last) {
-			lastlen = ((*priv->rxringtail) & 0xfff);
-
-			/* if the last descriptor (that should tell us the total
-			 * packet len) tell us something less than the
-			 * descriptors len we had until now, then there is some
-			 * problem..
-			 * workaround to prevent kernel panic
-			 */
-			if (lastlen < priv->rx_prevlen)
-				len = 0;
-			else
-				len = lastlen-priv->rx_prevlen;
-
-			if (*(priv->rxringtail) & (1<<13)) {
-				if ((*(priv->rxringtail) & 0xfff) < 500)
-					priv->stats.rxcrcerrmin++;
-				else if ((*(priv->rxringtail) & 0x0fff) > 1000)
-					priv->stats.rxcrcerrmax++;
-				else
-					priv->stats.rxcrcerrmid++;
-
-			}
-
-		} else {
-			len = priv->rxbuffersize;
-		}
-
-		if (first && last) {
-			padding = ((*(priv->rxringtail+3))&(0x04000000))>>26;
-		} else if (first) {
-			padding = ((*(priv->rxringtail+3))&(0x04000000))>>26;
-			if (padding)
-				len -= 2;
-		} else {
-			padding = 0;
-		}
-		padding = 0;
-		priv->rx_prevlen += len;
-
-		if (priv->rx_prevlen > MAX_FRAG_THRESHOLD + 100) {
-			/* HW is probably passing several buggy frames without
-			 * FD or LD flag set.
-			 * Throw this garbage away to prevent skb memory
-			 * exhausting
-			 */
-			if (!priv->rx_skb_complete)
-				dev_kfree_skb_any(priv->rx_skb);
-			priv->rx_skb_complete = 1;
-		}
-
-		signal = (unsigned char)((*(priv->rxringtail + 3) &
-			0x00ff0000) >> 16);
-		signal = (signal & 0xfe) >> 1;
-
-		quality = (unsigned char)((*(priv->rxringtail+3)) & (0xff));
-
-		stats.mac_time[0] = *(priv->rxringtail+1);
-		stats.mac_time[1] = *(priv->rxringtail+2);
-
-		rxpower = ((char)((*(priv->rxringtail + 4) &
-			0x00ff0000) >> 16)) / 2 - 42;
-
-		RSSI = ((u8)((*(priv->rxringtail + 3) &
-			0x0000ff00) >> 8)) & 0x7f;
-
-		rate = ((*(priv->rxringtail)) &
-			((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20;
-
-		stats.rate = rtl8180_rate2rate(rate);
-		Antenna = (*(priv->rxringtail + 3) & 0x00008000) == 0 ? 0 : 1;
-		if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
-			RxAGC_dBm = rxpower+1;	/* bias */
-		} else { /* CCK rate. */
-			RxAGC_dBm = signal; /* bit 0 discard */
-
-			LNA = (u8) (RxAGC_dBm & 0x60) >> 5; /* bit 6~ bit 5 */
-			BB  = (u8) (RxAGC_dBm & 0x1F); /* bit 4 ~ bit 0 */
-
-			/* Pin_11b=-(LNA_gain+BB_gain) (dBm) */
-			RxAGC_dBm = -(LNA_gain[LNA] + (BB * 2));
-
-			RxAGC_dBm += 4; /* bias */
-		}
-
-		if (RxAGC_dBm & 0x80) /* absolute value */
-			RXAGC = ~(RxAGC_dBm)+1;
-		bCckRate = rtl8180_IsWirelessBMode(stats.rate);
-		/* Translate RXAGC into 1-100. */
-		if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
-			if (RXAGC > 90)
-				RXAGC = 90;
-			else if (RXAGC < 25)
-				RXAGC = 25;
-			RXAGC = (90-RXAGC)*100/65;
-		} else { /* CCK rate. */
-			if (RXAGC > 95)
-				RXAGC = 95;
-			else if (RXAGC < 30)
-				RXAGC = 30;
-			RXAGC = (95-RXAGC)*100/65;
-		}
-		priv->SignalStrength = (u8)RXAGC;
-		priv->RecvSignalPower = RxAGC_dBm;
-		priv->RxPower = rxpower;
-		priv->RSSI = RSSI;
-		/* SQ translation formula is provided by SD3 DZ. 2006.06.27 */
-		if (quality >= 127)
-			/* 0 causes epc to show signal zero, walk around now */
-			quality = 1;
-		else if (quality < 27)
-			quality = 100;
-		else
-			quality = 127 - quality;
-		priv->SignalQuality = quality;
-
-		stats.signal = (u8) quality;
-
-		stats.signalstrength = RXAGC;
-		if (stats.signalstrength > 100)
-			stats.signalstrength = 100;
-		stats.signalstrength = (stats.signalstrength * 70) / 100 + 30;
-		stats.rssi = priv->wstats.qual.qual = priv->SignalQuality;
-		stats.noise = priv->wstats.qual.noise =
-			100 - priv->wstats.qual.qual;
-		bHwError = (((*(priv->rxringtail)) & (0x00000fff)) == 4080) |
-			   (((*(priv->rxringtail)) & (0x04000000)) != 0) |
-			   (((*(priv->rxringtail)) & (0x08000000)) != 0) |
-			   (((~(*(priv->rxringtail))) & (0x10000000)) != 0) |
-			   (((~(*(priv->rxringtail))) & (0x20000000)) != 0);
-		bCRC = ((*(priv->rxringtail)) & (0x00002000)) >> 13;
-		bICV = ((*(priv->rxringtail)) & (0x00001000)) >> 12;
-		hdr = (struct ieee80211_hdr_4addr *)priv->rxbuffer->buf;
-		    fc = le16_to_cpu(hdr->frame_ctl);
-		type = WLAN_FC_GET_TYPE(fc);
-
-		if (IEEE80211_FTYPE_CTL != type &&
-		    !bHwError && !bCRC && !bICV &&
-		    eqMacAddr(priv->ieee80211->current_network.bssid,
-			fc & IEEE80211_FCTL_TODS ? hdr->addr1 :
-			fc & IEEE80211_FCTL_FROMDS ? hdr->addr2 :
-			hdr->addr3)) {
-
-			/* Perform signal smoothing for dynamic
-			 * mechanism on demand. This is different
-			 * with PerformSignalSmoothing8185 in smoothing
-			 * fomula. No dramatic adjustion is apply
-			 * because dynamic mechanism need some degree
-			 * of correctness. */
-			PerformUndecoratedSignalSmoothing8185(priv, bCckRate);
-
-			/* For good-looking singal strength. */
-			SignalStrengthIndex = NetgearSignalStrengthTranslate(
-				priv->LastSignalStrengthInPercent,
-				priv->SignalStrength);
-
-			priv->LastSignalStrengthInPercent = SignalStrengthIndex;
-			priv->Stats_SignalStrength =
-				TranslateToDbm8185((u8)SignalStrengthIndex);
-
-			/*
-			 * We need more correct power of received packets and
-			 * the "SignalStrength" of RxStats is beautified, so we
-			 * record the correct power here.
-			 */
-
-			priv->Stats_SignalQuality = (long)(
-				priv->Stats_SignalQuality * 5 +
-				(long)priv->SignalQuality + 5) / 6;
-
-			priv->Stats_RecvSignalPower = (long)(
-				priv->Stats_RecvSignalPower * 5 +
-				priv->RecvSignalPower - 1) / 6;
-
-			/*
-			 * Figure out which antenna received the last packet.
-			 * 0: aux, 1: main
-			 */
-			priv->LastRxPktAntenna = Antenna ? 1 : 0;
-			SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
-		}
-
-		if (first) {
-			if (!priv->rx_skb_complete) {
-				/* seems that HW sometimes fails to receive and
-				 * doesn't provide the last descriptor.
-				 */
-				dev_kfree_skb_any(priv->rx_skb);
-				priv->stats.rxnolast++;
-			}
-			priv->rx_skb = dev_alloc_skb(len+2);
-			if (!priv->rx_skb)
-				goto drop;
-
-			priv->rx_skb_complete = 0;
-			priv->rx_skb->dev = dev;
-		} else {
-			/* if we are here we should have already RXed the first
-			 * frame.
-			 * If we get here and the skb is not allocated then
-			 * we have just throw out garbage (skb not allocated)
-			 * and we are still rxing garbage....
-			 */
-			if (!priv->rx_skb_complete) {
-
-				tmp_skb = dev_alloc_skb(
-					priv->rx_skb->len + len + 2);
-
-				if (!tmp_skb)
-					goto drop;
-
-				tmp_skb->dev = dev;
-
-				memcpy(skb_put(tmp_skb, priv->rx_skb->len),
-					priv->rx_skb->data,
-					priv->rx_skb->len);
-
-				dev_kfree_skb_any(priv->rx_skb);
-
-				priv->rx_skb = tmp_skb;
-			}
-		}
-
-		if (!priv->rx_skb_complete) {
-			memcpy(skb_put(priv->rx_skb, len), ((unsigned char *)
-				priv->rxbuffer->buf) + (padding ? 2 : 0), len);
-		}
-
-		if (last && !priv->rx_skb_complete) {
-			if (priv->rx_skb->len > 4)
-				skb_trim(priv->rx_skb, priv->rx_skb->len-4);
-			if (!ieee80211_rtl_rx(priv->ieee80211,
-					 priv->rx_skb, &stats))
-				dev_kfree_skb_any(priv->rx_skb);
-			priv->rx_skb_complete = 1;
-		}
-
-		pci_dma_sync_single_for_device(priv->pdev,
-				    priv->rxbuffer->dma,
-				    priv->rxbuffersize * sizeof(u8),
-				    PCI_DMA_FROMDEVICE);
-
-drop: /* this is used when we have not enough mem */
-		/* restore the descriptor */
-		*(priv->rxringtail+2) = priv->rxbuffer->dma;
-		*(priv->rxringtail) = *(priv->rxringtail) & ~0xfff;
-		*(priv->rxringtail) =
-			*(priv->rxringtail) | priv->rxbuffersize;
-
-		*(priv->rxringtail) =
-			*(priv->rxringtail) | (1<<31);
-
-		priv->rxringtail += rx_desc_size;
-		if (priv->rxringtail >=
-		   (priv->rxring)+(priv->rxringcount)*rx_desc_size)
-			priv->rxringtail = priv->rxring;
-
-		priv->rxbuffer = (priv->rxbuffer->next);
-	}
-}
-
-
-static void rtl8180_dma_kick(struct net_device *dev, int priority)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	write_nic_byte(dev, TX_DMA_POLLING,
-			(1 << (priority + 1)) | priv->dma_poll_mask);
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-	force_pci_posting(dev);
-}
-
-static void rtl8180_data_hard_stop(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	priv->dma_poll_stop_mask |= TPPOLLSTOP_AC_VIQ;
-	write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-static void rtl8180_data_hard_resume(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_AC_VIQ);
-	write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-/*
- * This function TX data frames when the ieee80211 stack requires this.
- * It checks also if we need to stop the ieee tx queue, eventually do it
- */
-static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
-				   int rate)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	int mode;
-	struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *)skb->data;
-	bool morefrag = le16_to_cpu(h->frame_control) & IEEE80211_FCTL_MOREFRAGS;
-	unsigned long flags;
-	int priority;
-
-	mode = priv->ieee80211->iw_mode;
-
-	rate = ieeerate2rtlrate(rate);
-	/*
-	 * This function doesn't require lock because we make sure it's called
-	 * with the tx_lock already acquired.
-	 * This come from the kernel's hard_xmit callback (through the ieee
-	 * stack, or from the try_wake_queue (again through the ieee stack.
-	 */
-	priority = AC2Q(skb->priority);
-	spin_lock_irqsave(&priv->tx_lock, flags);
-
-	if (priv->ieee80211->bHwRadioOff) {
-		spin_unlock_irqrestore(&priv->tx_lock, flags);
-
-		return;
-	}
-
-	if (!check_nic_enought_desc(dev, priority)) {
-		DMESGW("Error: no descriptor left by previous TX (avail %d) ",
-			get_curr_tx_free_desc(dev, priority));
-		ieee80211_rtl_stop_queue(priv->ieee80211);
-	}
-	rtl8180_tx(dev, skb->data, skb->len, priority, morefrag, 0, rate);
-	if (!check_nic_enought_desc(dev, priority))
-		ieee80211_rtl_stop_queue(priv->ieee80211);
-
-	spin_unlock_irqrestore(&priv->tx_lock, flags);
-}
-
-/*
- * This is a rough attempt to TX a frame
- * This is called by the ieee 80211 stack to TX management frames.
- * If the ring is full packets are dropped (for data frame the queue
- * is stopped before this can happen). For this reason it is better
- * if the descriptors are larger than the largest management frame
- * we intend to TX: i'm unsure what the HW does if it will not find
- * the last fragment of a frame because it has been dropped...
- * Since queues for Management and Data frames are different we
- * might use a different lock than tx_lock (for example mgmt_tx_lock)
- */
-/* these function may loop if invoked with 0 descriptors or 0 len buffer */
-static int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	unsigned long flags;
-	int priority;
-
-	priority = MANAGE_PRIORITY;
-
-	spin_lock_irqsave(&priv->tx_lock, flags);
-
-	if (priv->ieee80211->bHwRadioOff) {
-		spin_unlock_irqrestore(&priv->tx_lock, flags);
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	rtl8180_tx(dev, skb->data, skb->len, priority,
-		0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate));
-
-	priv->ieee80211->stats.tx_bytes += skb->len;
-	priv->ieee80211->stats.tx_packets++;
-	spin_unlock_irqrestore(&priv->tx_lock, flags);
-
-	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
-}
-
-static void rtl8180_prepare_beacon(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct sk_buff *skb;
-
-	u16 word  = read_nic_word(dev, BcnItv);
-	word &= ~BcnItv_BcnItv; /* clear Bcn_Itv */
-
-	/* word |= 0x64; */
-	word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval);
-
-	write_nic_word(dev, BcnItv, word);
-
-	skb = ieee80211_get_beacon(priv->ieee80211);
-	if (skb) {
-		rtl8180_tx(dev, skb->data, skb->len, BEACON_PRIORITY,
-			0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate));
-		dev_kfree_skb_any(skb);
-	}
-}
-
-/*
- * This function do the real dirty work: it enqueues a TX command descriptor in
- * the ring buffer, copyes the frame in a TX buffer and kicks the NIC to ensure
- * it does the DMA transfer.
- */
-short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
-		 bool morefrag, short descfrag, int rate)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u32 *tail, *temp_tail;
-	u32 *begin;
-	u32 *buf;
-	int i;
-	int remain;
-	int buflen;
-	int count;
-	struct buffer *buflist;
-	struct ieee80211_hdr_3addr *frag_hdr =
-		(struct ieee80211_hdr_3addr *)txbuf;
-	u8 dest[ETH_ALEN];
-	u8 bUseShortPreamble = 0;
-	u8 bCTSEnable = 0;
-	u8 bRTSEnable = 0;
-	u16 Duration = 0;
-	u16 RtsDur = 0;
-	u16 ThisFrameTime = 0;
-	u16 TxDescDuration = 0;
-	bool ownbit_flag = false;
-
-	switch (priority) {
-	case MANAGE_PRIORITY:
-		tail = priv->txmapringtail;
-		begin = priv->txmapring;
-		buflist = priv->txmapbufstail;
-		count = priv->txringcount;
-		break;
-	case BK_PRIORITY:
-		tail = priv->txbkpringtail;
-		begin = priv->txbkpring;
-		buflist = priv->txbkpbufstail;
-		count = priv->txringcount;
-		break;
-	case BE_PRIORITY:
-		tail = priv->txbepringtail;
-		begin = priv->txbepring;
-		buflist = priv->txbepbufstail;
-		count = priv->txringcount;
-		break;
-	case VI_PRIORITY:
-		tail = priv->txvipringtail;
-		begin = priv->txvipring;
-		buflist = priv->txvipbufstail;
-		count = priv->txringcount;
-		break;
-	case VO_PRIORITY:
-		tail = priv->txvopringtail;
-		begin = priv->txvopring;
-		buflist = priv->txvopbufstail;
-		count = priv->txringcount;
-		break;
-	case HI_PRIORITY:
-		tail = priv->txhpringtail;
-		begin = priv->txhpring;
-		buflist = priv->txhpbufstail;
-		count = priv->txringcount;
-		break;
-	case BEACON_PRIORITY:
-		tail = priv->txbeaconringtail;
-		begin = priv->txbeaconring;
-		buflist = priv->txbeaconbufstail;
-		count = priv->txbeaconcount;
-		break;
-	default:
-		return -1;
-		break;
-	}
-
-	memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
-	if (is_multicast_ether_addr(dest)) {
-		Duration = 0;
-		RtsDur = 0;
-		bRTSEnable = 0;
-		bCTSEnable = 0;
-
-		ThisFrameTime = ComputeTxTime(len + sCrcLng,
-			rtl8180_rate2rate(rate), 0, bUseShortPreamble);
-		TxDescDuration = ThisFrameTime;
-	} else { /* Unicast packet */
-		u16 AckTime;
-
-		/* for Keep alive */
-		priv->NumTxUnicast++;
-
-		/* Figure out ACK rate according to BSS basic rate
-		 * and Tx rate.
-		 * AckCTSLng = 14 use 1M bps send
-		 */
-		AckTime = ComputeTxTime(14, 10, 0, 0);
-
-		if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */
-			u16 RtsTime, CtsTime;
-			bRTSEnable = 1;
-			bCTSEnable = 0;
-
-			/* Rate and time required for RTS. */
-			RtsTime = ComputeTxTime(sAckCtsLng / 8,
-				priv->ieee80211->basic_rate, 0, 0);
-
-			/* Rate and time required for CTS.
-			 * AckCTSLng = 14 use 1M bps send
-			 */
-			CtsTime = ComputeTxTime(14, 10, 0, 0);
-
-			/* Figure out time required to transmit this frame. */
-			ThisFrameTime = ComputeTxTime(len + sCrcLng,
-				rtl8180_rate2rate(rate), 0,
-				bUseShortPreamble);
-
-			/* RTS-CTS-ThisFrame-ACK. */
-			RtsDur = CtsTime + ThisFrameTime +
-				AckTime + 3 * aSifsTime;
-
-			TxDescDuration = RtsTime + RtsDur;
-		} else { /* Normal case. */
-			bCTSEnable = 0;
-			bRTSEnable = 0;
-			RtsDur = 0;
-
-			ThisFrameTime = ComputeTxTime(len + sCrcLng,
-				rtl8180_rate2rate(rate), 0, bUseShortPreamble);
-			TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
-		}
-
-		if (!(le16_to_cpu(frag_hdr->frame_control) & IEEE80211_FCTL_MOREFRAGS)) {
-			/* ThisFrame-ACK. */
-			Duration = aSifsTime + AckTime;
-		} else { /* One or more fragments remained. */
-			u16 NextFragTime;
-
-			/* pretend following packet length = current packet */
-			NextFragTime = ComputeTxTime(len + sCrcLng,
-				rtl8180_rate2rate(rate), 0, bUseShortPreamble);
-
-			/* ThisFrag-ACk-NextFrag-ACK. */
-			Duration = NextFragTime + 3 * aSifsTime + 2 * AckTime;
-		}
-
-	} /* End of Unicast packet */
-
-	frag_hdr->duration_id = Duration;
-
-	buflen = priv->txbuffsize;
-	remain = len;
-	temp_tail = tail;
-
-	while (remain != 0) {
-		mb();
-		if (!buflist) {
-			DMESGE("TX buffer error, cannot TX frames. pri %d.",
-				priority);
-			return -1;
-		}
-		buf = buflist->buf;
-
-		if ((*tail & (1 << 31)) && (priority != BEACON_PRIORITY)) {
-			DMESGW("No more TX desc, returning %x of %x",
-			       remain, len);
-			priv->stats.txrdu++;
-			return remain;
-		}
-
-		*tail = 0; /* zeroes header */
-		*(tail+1) = 0;
-		*(tail+3) = 0;
-		*(tail+5) = 0;
-		*(tail+6) = 0;
-		*(tail+7) = 0;
-
-		/* FIXME: should be triggered by HW encryption parameters.*/
-		*tail |= (1<<15); /* no encrypt */
-
-		if (remain == len && !descfrag) {
-			ownbit_flag = false;
-			*tail = *tail | (1 << 29); /* first segment of packet */
-			*tail = *tail | (len);
-		} else {
-			ownbit_flag = true;
-		}
-
-		for (i = 0; i < buflen && remain > 0; i++, remain--) {
-			/* copy data into descriptor pointed DMAble buffer */
-			((u8 *)buf)[i] = txbuf[i];
-
-			if (remain == 4 && i+4 >= buflen)
-				break;
-			/* ensure the last desc has at least 4 bytes payload */
-		}
-		txbuf = txbuf + i;
-		*(tail+3) = *(tail+3) & ~0xfff;
-		*(tail+3) = *(tail+3) | i; /* buffer length */
-
-		if (bCTSEnable)
-			*tail |= (1<<18);
-
-		if (bRTSEnable) { /* rts enable */
-			/* RTS RATE */
-			*tail |= (ieeerate2rtlrate(
-				priv->ieee80211->basic_rate) << 19);
-
-			*tail |= (1<<23); /* rts enable */
-			*(tail+1) |= (RtsDur&0xffff); /* RTS Duration */
-		}
-		*(tail+3) |= ((TxDescDuration&0xffff)<<16); /* DURATION */
-
-		*(tail + 5) |= (11 << 8); /* retry lim; */
-
-		*tail = *tail | ((rate&0xf) << 24);
-
-		if (morefrag)
-			*tail = (*tail) | (1<<17); /* more fragment */
-		if (!remain)
-			*tail = (*tail) | (1<<28); /* last segment of frame */
-
-		*(tail+5) = *(tail+5)|(2<<27);
-		*(tail+7) = *(tail+7)|(1<<4);
-
-		wmb();
-		if (ownbit_flag)
-			/* descriptor ready to be txed */
-			*tail |= (1 << 31);
-
-		if ((tail - begin)/8 == count-1)
-			tail = begin;
-		else
-			tail = tail+8;
-
-		buflist = buflist->next;
-
-		mb();
-
-		switch (priority) {
-		case MANAGE_PRIORITY:
-			priv->txmapringtail = tail;
-			priv->txmapbufstail = buflist;
-			break;
-		case BK_PRIORITY:
-			priv->txbkpringtail = tail;
-			priv->txbkpbufstail = buflist;
-			break;
-		case BE_PRIORITY:
-			priv->txbepringtail = tail;
-			priv->txbepbufstail = buflist;
-			break;
-		case VI_PRIORITY:
-			priv->txvipringtail = tail;
-			priv->txvipbufstail = buflist;
-			break;
-		case VO_PRIORITY:
-			priv->txvopringtail = tail;
-			priv->txvopbufstail = buflist;
-			break;
-		case HI_PRIORITY:
-			priv->txhpringtail = tail;
-			priv->txhpbufstail = buflist;
-			break;
-		case BEACON_PRIORITY:
-			/*
-			 * The HW seems to be happy with the 1st
-			 * descriptor filled and the 2nd empty...
-			 * So always update descriptor 1 and never
-			 * touch 2nd
-			 */
-			break;
-		}
-	}
-	*temp_tail = *temp_tail | (1<<31); /* descriptor ready to be txed */
-	rtl8180_dma_kick(dev, priority);
-
-	return 0;
-}
-
-void rtl8180_irq_rx_tasklet(struct r8180_priv *priv);
-
-static void rtl8180_link_change(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u16 beacon_interval;
-	struct ieee80211_network *net = &priv->ieee80211->current_network;
-
-	rtl8180_update_msr(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-
-	write_nic_dword(dev, BSSID, ((u32 *)net->bssid)[0]);
-	write_nic_word(dev, BSSID+4, ((u16 *)net->bssid)[2]);
-
-	beacon_interval  = read_nic_word(dev, BEACON_INTERVAL);
-	beacon_interval &= ~BEACON_INTERVAL_MASK;
-	beacon_interval |= net->beacon_interval;
-	write_nic_word(dev, BEACON_INTERVAL, beacon_interval);
-
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-	rtl8180_set_chan(dev, priv->chan);
-}
-
-static void rtl8180_rq_tx_ack(struct net_device *dev)
-{
-
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	write_nic_byte(dev, CONFIG4,
-		read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT);
-	priv->ack_tx_to_ieee = 1;
-}
-
-static short rtl8180_is_tx_queue_empty(struct net_device *dev)
-{
-
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u32 *d;
-
-	for (d = priv->txmapring;
-		d < priv->txmapring + priv->txringcount; d += 8)
-			if (*d & (1<<31))
-				return 0;
-
-	for (d = priv->txbkpring;
-		d < priv->txbkpring + priv->txringcount; d += 8)
-			if (*d & (1<<31))
-				return 0;
-
-	for (d = priv->txbepring;
-		d < priv->txbepring + priv->txringcount; d += 8)
-			if (*d & (1<<31))
-				return 0;
-
-	for (d = priv->txvipring;
-		d < priv->txvipring + priv->txringcount; d += 8)
-			if (*d & (1<<31))
-				return 0;
-
-	for (d = priv->txvopring;
-		d < priv->txvopring + priv->txringcount; d += 8)
-			if (*d & (1<<31))
-				return 0;
-
-	for (d = priv->txhpring;
-		d < priv->txhpring + priv->txringcount; d += 8)
-			if (*d & (1<<31))
-				return 0;
-	return 1;
-}
-
-static void rtl8180_hw_wakeup(struct net_device *dev)
-{
-	unsigned long flags;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	spin_lock_irqsave(&priv->ps_lock, flags);
-	write_nic_byte(dev, CONFIG4,
-		read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT);
-	if (priv->rf_wakeup)
-		priv->rf_wakeup(dev);
-	spin_unlock_irqrestore(&priv->ps_lock, flags);
-}
-
-static void rtl8180_hw_sleep_down(struct net_device *dev)
-{
-	unsigned long flags;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	spin_lock_irqsave(&priv->ps_lock, flags);
-	if (priv->rf_sleep)
-		priv->rf_sleep(dev);
-	spin_unlock_irqrestore(&priv->ps_lock, flags);
-}
-
-static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u32 rb = jiffies;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->ps_lock, flags);
-
-	/*
-	 * Writing HW register with 0 equals to disable
-	 * the timer, that is not really what we want
-	 */
-	tl -= MSECS(4+16+7);
-
-	/*
-	 * If the interval in which we are requested to sleep is too
-	 * short then give up and remain awake
-	 */
-	if (((tl >= rb) && (tl-rb) <= MSECS(MIN_SLEEP_TIME))
-		|| ((rb > tl) && (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
-		spin_unlock_irqrestore(&priv->ps_lock, flags);
-		netdev_warn(dev, "too short to sleep\n");
-		return;
-	}
-
-	{
-		u32 tmp = (tl > rb) ? (tl-rb) : (rb-tl);
-
-		priv->DozePeriodInPast2Sec += jiffies_to_msecs(tmp);
-		/* as tl may be less than rb */
-		queue_delayed_work(priv->ieee80211->wq,
-			&priv->ieee80211->hw_wakeup_wq, tmp);
-	}
-	/*
-	 * If we suspect the TimerInt is gone beyond tl
-	 * while setting it, then give up
-	 */
-
-	if (((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME))) ||
-		((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) {
-		spin_unlock_irqrestore(&priv->ps_lock, flags);
-		return;
-	}
-
-	queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq);
-	spin_unlock_irqrestore(&priv->ps_lock, flags);
-}
-
-static void rtl8180_wmm_single_param_update(struct net_device *dev,
-	u8 mode, AC_CODING eACI, PAC_PARAM param)
-{
-	u8 u1bAIFS;
-	u32 u4bAcParam;
-
-	/* Retrieve parameters to update. */
-	/* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
-	u1bAIFS = param->f.AciAifsn.f.AIFSN * ((mode & IEEE_G) == IEEE_G ?
-		9 : 20) + aSifsTime;
-	u4bAcParam = (((u32)param->f.TXOPLimit << AC_PARAM_TXOP_LIMIT_OFFSET) |
-		((u32)param->f.Ecw.f.ECWmax << AC_PARAM_ECW_MAX_OFFSET) |
-		((u32)param->f.Ecw.f.ECWmin << AC_PARAM_ECW_MIN_OFFSET) |
-		((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
-
-	switch (eACI) {
-	case AC1_BK:
-		write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
-		return;
-	case AC0_BE:
-		write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
-		return;
-	case AC2_VI:
-		write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
-		return;
-	case AC3_VO:
-		write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
-		return;
-	default:
-		pr_warn("SetHwReg8185(): invalid ACI: %d!\n", eACI);
-		return;
-	}
-}
-
-static void rtl8180_wmm_param_update(struct work_struct *work)
-{
-	struct ieee80211_device *ieee = container_of(work,
-		struct ieee80211_device, wmm_param_update_wq);
-	struct net_device *dev = ieee->dev;
-	u8 *ac_param = (u8 *)(ieee->current_network.wmm_param);
-	u8 mode = ieee->current_network.mode;
-	AC_CODING eACI;
-	AC_PARAM AcParam;
-
-	if (!ieee->current_network.QoS_Enable) {
-		/* legacy ac_xx_param update */
-		AcParam.longData = 0;
-		AcParam.f.AciAifsn.f.AIFSN = 2; /* Follow 802.11 DIFS. */
-		AcParam.f.AciAifsn.f.ACM = 0;
-		AcParam.f.Ecw.f.ECWmin = 3; /* Follow 802.11 CWmin. */
-		AcParam.f.Ecw.f.ECWmax = 7; /* Follow 802.11 CWmax. */
-		AcParam.f.TXOPLimit = 0;
-
-		for (eACI = 0; eACI < AC_MAX; eACI++) {
-			AcParam.f.AciAifsn.f.ACI = (u8)eACI;
-
-			rtl8180_wmm_single_param_update(dev, mode, eACI,
-				(PAC_PARAM)&AcParam);
-		}
-		return;
-	}
-
-	for (eACI = 0; eACI < AC_MAX; eACI++) {
-		rtl8180_wmm_single_param_update(dev, mode,
-			((PAC_PARAM)ac_param)->f.AciAifsn.f.ACI,
-			(PAC_PARAM)ac_param);
-
-		ac_param += sizeof(AC_PARAM);
-	}
-}
-
-void rtl8180_restart_wq(struct work_struct *work);
-void rtl8180_watch_dog_wq(struct work_struct *work);
-void rtl8180_hw_wakeup_wq(struct work_struct *work);
-void rtl8180_hw_sleep_wq(struct work_struct *work);
-void rtl8180_sw_antenna_wq(struct work_struct *work);
-void rtl8180_watch_dog(struct net_device *dev);
-
-static void watch_dog_adaptive(unsigned long data)
-{
-	struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
-
-	if (!priv->up) {
-		DMESG("<----watch_dog_adaptive():driver is not up!\n");
-		return;
-	}
-
-	/* Tx High Power Mechanism. */
-	if (CheckHighPower((struct net_device *)data))
-		queue_work(priv->ieee80211->wq,
-			(void *)&priv->ieee80211->tx_pw_wq);
-
-	/* Tx Power Tracking on 87SE. */
-	if (CheckTxPwrTracking((struct net_device *)data))
-		TxPwrTracking87SE((struct net_device *)data);
-
-	/* Perform DIG immediately. */
-	if (CheckDig((struct net_device *)data))
-		queue_work(priv->ieee80211->wq,
-			(void *)&priv->ieee80211->hw_dig_wq);
-
-	rtl8180_watch_dog((struct net_device *)data);
-
-	queue_work(priv->ieee80211->wq,
-		(void *)&priv->ieee80211->GPIOChangeRFWorkItem);
-
-	priv->watch_dog_timer.expires = jiffies +
-		MSECS(IEEE80211_WATCH_DOG_TIME);
-
-	add_timer(&priv->watch_dog_timer);
-}
-
-static struct rtl8187se_channel_list channel_plan_list[] = {
-	/* FCC */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40,
-		44, 48, 52, 56, 60, 64}, 19},
-
-	/* IC */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
-
-	/* ETSI */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
-		44, 48, 52, 56, 60, 64}, 21},
-
-	/* Spain. Change to ETSI. */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
-		44, 48, 52, 56, 60, 64}, 21},
-
-	/* France. Change to ETSI. */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
-		44, 48, 52, 56, 60, 64}, 21},
-
-	/* MKK */
-	{{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9},
-
-	/* MKK1 */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36,
-		40, 44, 48, 52, 56, 60, 64}, 22},
-
-	/* Israel. */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
-		44, 48, 52, 56, 60, 64}, 21},
-
-	/* For 11a , TELEC */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17},
-
-	/* For Global Domain. 1-11 active, 12-14 passive. */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
-
-	/* world wide 13: ch1~ch11 active, ch12~13 passive */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}
-};
-
-static void rtl8180_set_channel_map(u8 channel_plan,
-				    struct ieee80211_device *ieee)
-{
-	int i;
-
-	ieee->MinPassiveChnlNum = MAX_CHANNEL_NUMBER+1;
-	ieee->IbssStartChnl = 0;
-
-	switch (channel_plan) {
-	case COUNTRY_CODE_FCC:
-	case COUNTRY_CODE_IC:
-	case COUNTRY_CODE_ETSI:
-	case COUNTRY_CODE_SPAIN:
-	case COUNTRY_CODE_FRANCE:
-	case COUNTRY_CODE_MKK:
-	case COUNTRY_CODE_MKK1:
-	case COUNTRY_CODE_ISRAEL:
-	case COUNTRY_CODE_TELEC:
-		{
-			Dot11d_Init(ieee);
-			ieee->bGlobalDomain = false;
-			if (channel_plan_list[channel_plan].len != 0) {
-				/* Clear old channel map */
-				memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
-				/* Set new channel map */
-				for (i = 0; i < channel_plan_list[channel_plan].len; i++) {
-					if (channel_plan_list[channel_plan].channel[i] <= 14)
-						GET_DOT11D_INFO(ieee)->channel_map[channel_plan_list[channel_plan].channel[i]] = 1;
-				}
-			}
-			break;
-		}
-	case COUNTRY_CODE_GLOBAL_DOMAIN:
-		{
-			GET_DOT11D_INFO(ieee)->bEnabled = false;
-			Dot11d_Reset(ieee);
-			ieee->bGlobalDomain = true;
-			break;
-		}
-	case COUNTRY_CODE_WORLD_WIDE_13_INDEX:
-		{
-			ieee->MinPassiveChnlNum = 12;
-			ieee->IbssStartChnl = 10;
-			break;
-		}
-	default:
-		{
-			Dot11d_Init(ieee);
-			ieee->bGlobalDomain = false;
-			memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
-			for (i = 1; i <= 14; i++)
-				GET_DOT11D_INFO(ieee)->channel_map[i] = 1;
-			break;
-		}
-	}
-}
-
-void GPIOChangeRFWorkItemCallBack(struct work_struct *work);
-
-static void rtl8180_statistics_init(struct stats *pstats)
-{
-	memset(pstats, 0, sizeof(struct stats));
-}
-
-static void rtl8180_link_detect_init(struct link_detect_t *plink_detect)
-{
-	memset(plink_detect, 0, sizeof(struct link_detect_t));
-	plink_detect->slot_num = DEFAULT_SLOT_NUM;
-}
-
-static void rtl8187se_eeprom_register_read(struct eeprom_93cx6 *eeprom)
-{
-	struct net_device *dev = eeprom->data;
-	u8 reg = read_nic_byte(dev, EPROM_CMD);
-
-	eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
-	eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
-	eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
-	eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
-}
-
-static void rtl8187se_eeprom_register_write(struct eeprom_93cx6 *eeprom)
-{
-	struct net_device *dev = eeprom->data;
-	u8 reg = 2 << 6;
-
-	if (eeprom->reg_data_in)
-		reg |= RTL818X_EEPROM_CMD_WRITE;
-	if (eeprom->reg_data_out)
-		reg |= RTL818X_EEPROM_CMD_READ;
-	if (eeprom->reg_data_clock)
-		reg |= RTL818X_EEPROM_CMD_CK;
-	if (eeprom->reg_chip_select)
-		reg |= RTL818X_EEPROM_CMD_CS;
-
-	write_nic_byte(dev, EPROM_CMD, reg);
-	read_nic_byte(dev, EPROM_CMD);
-	udelay(10);
-}
-
-static short rtl8180_init(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u16 word;
-	u16 usValue;
-	u16 tmpu16;
-	int i, j;
-	struct eeprom_93cx6 eeprom;
-	u16 eeprom_val;
-
-	eeprom.data = dev;
-	eeprom.register_read = rtl8187se_eeprom_register_read;
-	eeprom.register_write = rtl8187se_eeprom_register_write;
-	eeprom.width = PCI_EEPROM_WIDTH_93C46;
-
-	eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val);
-	priv->channel_plan = eeprom_val & 0xFF;
-	if (priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN) {
-		netdev_err(dev, "rtl8180_init: Invalid channel plan! Set to default.\n");
-		priv->channel_plan = 0;
-	}
-
-	DMESG("Channel plan is %d\n", priv->channel_plan);
-	rtl8180_set_channel_map(priv->channel_plan, priv->ieee80211);
-
-	/* FIXME: these constants are placed in a bad pleace. */
-	priv->txbuffsize = 2048;	/* 1024; */
-	priv->txringcount = 32;		/* 32; */
-	priv->rxbuffersize = 2048;	/* 1024; */
-	priv->rxringcount = 64;		/* 32; */
-	priv->txbeaconcount = 2;
-	priv->rx_skb_complete = 1;
-
-	priv->RFChangeInProgress = false;
-	priv->SetRFPowerStateInProgress = false;
-	priv->RFProgType = 0;
-
-	priv->irq_enabled = 0;
-
-	rtl8180_statistics_init(&priv->stats);
-	rtl8180_link_detect_init(&priv->link_detect);
-
-	priv->ack_tx_to_ieee = 0;
-	priv->ieee80211->current_network.beacon_interval =
-		DEFAULT_BEACONINTERVAL;
-	priv->ieee80211->iw_mode = IW_MODE_INFRA;
-	priv->ieee80211->softmac_features  = IEEE_SOFTMAC_SCAN |
-		IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
-		IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE;
-	priv->ieee80211->active_scan = 1;
-	priv->ieee80211->rate = 110; /* 11 mbps */
-	priv->ieee80211->modulation = IEEE80211_CCK_MODULATION;
-	priv->ieee80211->host_encrypt = 1;
-	priv->ieee80211->host_decrypt = 1;
-	priv->ieee80211->sta_wake_up = rtl8180_hw_wakeup;
-	priv->ieee80211->ps_request_tx_ack = rtl8180_rq_tx_ack;
-	priv->ieee80211->enter_sleep_state = rtl8180_hw_sleep;
-	priv->ieee80211->ps_is_queue_empty = rtl8180_is_tx_queue_empty;
-
-	priv->hw_wep = hwwep;
-	priv->dev = dev;
-	priv->retry_rts = DEFAULT_RETRY_RTS;
-	priv->retry_data = DEFAULT_RETRY_DATA;
-	priv->RFChangeInProgress = false;
-	priv->SetRFPowerStateInProgress = false;
-	priv->RFProgType = 0;
-	priv->bInactivePs = true; /* false; */
-	priv->ieee80211->bInactivePs = priv->bInactivePs;
-	priv->bSwRfProcessing = false;
-	priv->eRFPowerState = RF_OFF;
-	priv->RfOffReason = 0;
-	priv->led_strategy = SW_LED_MODE0;
-	priv->TxPollingTimes = 0;
-	priv->bLeisurePs = true;
-	priv->dot11PowerSaveMode = ACTIVE;
-	priv->AdMinCheckPeriod = 5;
-	priv->AdMaxCheckPeriod = 10;
-	priv->AdMaxRxSsThreshold = 30;	/* 60->30 */
-	priv->AdRxSsThreshold = 20;	/* 50->20 */
-	priv->AdCheckPeriod = priv->AdMinCheckPeriod;
-	priv->AdTickCount = 0;
-	priv->AdRxSignalStrength = -1;
-	priv->RegSwAntennaDiversityMechanism = 0;
-	priv->RegDefaultAntenna = 0;
-	priv->SignalStrength = 0;
-	priv->AdRxOkCnt = 0;
-	priv->CurrAntennaIndex = 0;
-	priv->AdRxSsBeforeSwitched = 0;
-	init_timer(&priv->SwAntennaDiversityTimer);
-	priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
-	priv->SwAntennaDiversityTimer.function =
-		(void *)SwAntennaDiversityTimerCallback;
-	priv->bDigMechanism = true;
-	priv->InitialGain = 6;
-	priv->bXtalCalibration = false;
-	priv->XtalCal_Xin = 0;
-	priv->XtalCal_Xout = 0;
-	priv->bTxPowerTrack = false;
-	priv->ThermalMeter = 0;
-	priv->FalseAlarmRegValue = 0;
-	priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm,
-					which is used in DIG. */
-	priv->DIG_NumberFallbackVote = 0;
-	priv->DIG_NumberUpgradeVote = 0;
-	priv->LastSignalStrengthInPercent = 0;
-	priv->Stats_SignalStrength = 0;
-	priv->LastRxPktAntenna = 0;
-	priv->SignalQuality = 0; /* in 0-100 index. */
-	priv->Stats_SignalQuality = 0;
-	priv->RecvSignalPower = 0; /* in dBm. */
-	priv->Stats_RecvSignalPower = 0;
-	priv->AdMainAntennaRxOkCnt = 0;
-	priv->AdAuxAntennaRxOkCnt = 0;
-	priv->bHWAdSwitched = false;
-	priv->bRegHighPowerMechanism = true;
-	priv->RegHiPwrUpperTh = 77;
-	priv->RegHiPwrLowerTh = 75;
-	priv->RegRSSIHiPwrUpperTh = 70;
-	priv->RegRSSIHiPwrLowerTh = 20;
-	priv->bCurCCKPkt = false;
-	priv->UndecoratedSmoothedSS = -1;
-	priv->bToUpdateTxPwr = false;
-	priv->CurCCKRSSI = 0;
-	priv->RxPower = 0;
-	priv->RSSI = 0;
-	priv->NumTxOkTotal = 0;
-	priv->NumTxUnicast = 0;
-	priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL;
-	priv->CurrRetryCnt = 0;
-	priv->LastRetryCnt = 0;
-	priv->LastTxokCnt = 0;
-	priv->LastRxokCnt = 0;
-	priv->LastRetryRate = 0;
-	priv->bTryuping = 0;
-	priv->CurrTxRate = 0;
-	priv->CurrRetryRate = 0;
-	priv->TryupingCount = 0;
-	priv->TryupingCountNoData = 0;
-	priv->TryDownCountLowData = 0;
-	priv->LastTxOKBytes = 0;
-	priv->LastFailTxRate = 0;
-	priv->LastFailTxRateSS = 0;
-	priv->FailTxRateCount = 0;
-	priv->LastTxThroughput = 0;
-	priv->NumTxOkBytesTotal = 0;
-	priv->ForcedDataRate = 0;
-	priv->RegBModeGainStage = 1;
-
-	priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
-	spin_lock_init(&priv->irq_th_lock);
-	spin_lock_init(&priv->tx_lock);
-	spin_lock_init(&priv->ps_lock);
-	spin_lock_init(&priv->rf_ps_lock);
-	sema_init(&priv->wx_sem, 1);
-	INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq);
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,
-			  (void *)rtl8180_hw_wakeup_wq);
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,
-			  (void *)rtl8180_hw_sleep_wq);
-	INIT_WORK(&priv->ieee80211->wmm_param_update_wq,
-		  (void *)rtl8180_wmm_param_update);
-	INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,
-			  (void *)rtl8180_rate_adapter);
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,
-			 (void *)rtl8180_hw_dig_wq);
-	INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,
-			 (void *)rtl8180_tx_pw_wq);
-	INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,
-			 (void *) GPIOChangeRFWorkItemCallBack);
-	tasklet_init(&priv->irq_rx_tasklet,
-		     (void(*)(unsigned long)) rtl8180_irq_rx_tasklet,
-		     (unsigned long)priv);
-
-	init_timer(&priv->watch_dog_timer);
-	priv->watch_dog_timer.data = (unsigned long)dev;
-	priv->watch_dog_timer.function = watch_dog_adaptive;
-
-	init_timer(&priv->rateadapter_timer);
-	priv->rateadapter_timer.data = (unsigned long)dev;
-	priv->rateadapter_timer.function = timer_rate_adaptive;
-	priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
-	priv->bEnhanceTxPwr = false;
-
-	priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit;
-	priv->ieee80211->set_chan = rtl8180_set_chan;
-	priv->ieee80211->link_change = rtl8180_link_change;
-	priv->ieee80211->softmac_data_hard_start_xmit = rtl8180_hard_data_xmit;
-	priv->ieee80211->data_hard_stop = rtl8180_data_hard_stop;
-	priv->ieee80211->data_hard_resume = rtl8180_data_hard_resume;
-
-	priv->ieee80211->init_wmmparam_flag = 0;
-
-	priv->ieee80211->start_send_beacons = rtl8180_start_tx_beacon;
-	priv->ieee80211->stop_send_beacons = rtl8180_beacon_tx_disable;
-	priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
-
-	priv->ShortRetryLimit = 7;
-	priv->LongRetryLimit = 7;
-	priv->EarlyRxThreshold = 7;
-
-	priv->TransmitConfig =	(1<<TCR_DurProcMode_OFFSET) |
-				(7<<TCR_MXDMA_OFFSET) |
-				(priv->ShortRetryLimit<<TCR_SRL_OFFSET) |
-				(priv->LongRetryLimit<<TCR_LRL_OFFSET);
-
-	priv->ReceiveConfig =	RCR_AMF | RCR_ADF | RCR_ACF |
-				RCR_AB | RCR_AM | RCR_APM |
-				(7<<RCR_MXDMA_OFFSET) |
-				(priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) |
-				(priv->EarlyRxThreshold == 7 ?
-					 RCR_ONLYERLPKT : 0);
-
-	priv->IntrMask		= IMR_TMGDOK | IMR_TBDER |
-				  IMR_THPDER | IMR_THPDOK |
-				  IMR_TVODER | IMR_TVODOK |
-				  IMR_TVIDER | IMR_TVIDOK |
-				  IMR_TBEDER | IMR_TBEDOK |
-				  IMR_TBKDER | IMR_TBKDOK |
-				  IMR_RDU |
-				  IMR_RER | IMR_ROK |
-				  IMR_RQoSOK;
-
-	priv->InitialGain = 6;
-
-	DMESG("MAC controller is a RTL8187SE b/g");
-
-	priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION;
-	priv->ieee80211->short_slot = 1;
-
-	eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &usValue);
-	DMESG("usValue is %#hx\n", usValue);
-	/* 3Read AntennaDiversity */
-
-	/* SW Antenna Diversity. */
-	priv->EEPROMSwAntennaDiversity = (usValue & EEPROM_SW_AD_MASK) ==
-		EEPROM_SW_AD_ENABLE;
-
-	/* Default Antenna to use. */
-	priv->EEPROMDefaultAntenna1 = (usValue & EEPROM_DEF_ANT_MASK) ==
-		EEPROM_DEF_ANT_1;
-
-	if (priv->RegSwAntennaDiversityMechanism == 0) /* Auto */
-		/* 0: default from EEPROM. */
-		priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity;
-	else
-		/* 1:disable antenna diversity, 2: enable antenna diversity. */
-		priv->bSwAntennaDiverity =
-			priv->RegSwAntennaDiversityMechanism == 2;
-
-	if (priv->RegDefaultAntenna == 0)
-		/* 0: default from EEPROM. */
-		priv->bDefaultAntenna1 = priv->EEPROMDefaultAntenna1;
-	else
-		/* 1: main, 2: aux. */
-		priv->bDefaultAntenna1 = priv->RegDefaultAntenna == 2;
-
-	priv->plcp_preamble_mode = 2;
-	/* the eeprom type is stored in RCR register bit #6 */
-	if (RCR_9356SEL & read_nic_dword(dev, RCR))
-		priv->epromtype = EPROM_93c56;
-	else
-		priv->epromtype = EPROM_93c46;
-
-	eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)
-			       dev->dev_addr, 3);
-
-	for (i = 1, j = 0; i < 14; i += 2, j++) {
-		eeprom_93cx6_read(&eeprom, EPROM_TXPW_CH1_2 + j, &word);
-		priv->chtxpwr[i] = word & 0xff;
-		priv->chtxpwr[i+1] = (word & 0xff00)>>8;
-	}
-	for (i = 1, j = 0; i < 14; i += 2, j++) {
-		eeprom_93cx6_read(&eeprom, EPROM_TXPW_OFDM_CH1_2 + j, &word);
-		priv->chtxpwr_ofdm[i] = word & 0xff;
-		priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8;
-	}
-
-	/* 3Read crystal calibration and thermal meter indication on 87SE. */
-	eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16);
-
-	/* Crystal calibration for Xin and Xout resp. */
-	priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK;
-	priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK) >> 4;
-	if ((tmpu16 & EEPROM_XTAL_CAL_ENABLE) >> 12)
-		priv->bXtalCalibration = true;
-
-	/* Thermal meter reference indication. */
-	priv->ThermalMeter =  (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK) >> 8);
-	if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13)
-		priv->bTxPowerTrack = true;
-
-	priv->rf_sleep = rtl8225z4_rf_sleep;
-	priv->rf_wakeup = rtl8225z4_rf_wakeup;
-	DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!");
-
-	priv->rf_close = rtl8225z2_rf_close;
-	priv->rf_init = rtl8225z2_rf_init;
-	priv->rf_set_chan = rtl8225z2_rf_set_chan;
-	priv->rf_set_sens = NULL;
-
-	if (0 != alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount))
-		return -ENOMEM;
-
-	if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
-				  TX_MANAGEPRIORITY_RING_ADDR))
-		return -ENOMEM;
-
-	if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
-				 TX_BKPRIORITY_RING_ADDR))
-		return -ENOMEM;
-
-	if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
-				 TX_BEPRIORITY_RING_ADDR))
-		return -ENOMEM;
-
-	if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
-				  TX_VIPRIORITY_RING_ADDR))
-		return -ENOMEM;
-
-	if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
-				  TX_VOPRIORITY_RING_ADDR))
-		return -ENOMEM;
-
-	if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
-				  TX_HIGHPRIORITY_RING_ADDR))
-		return -ENOMEM;
-
-	if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txbeaconcount,
-				  TX_BEACON_RING_ADDR))
-		return -ENOMEM;
-
-	if (request_irq(dev->irq, rtl8180_interrupt,
-		IRQF_SHARED, dev->name, dev)) {
-		DMESGE("Error allocating IRQ %d", dev->irq);
-		return -1;
-	} else {
-		priv->irq = dev->irq;
-		DMESG("IRQ %d", dev->irq);
-	}
-
-	return 0;
-}
-
-void rtl8180_no_hw_wep(struct net_device *dev)
-{
-}
-
-void rtl8180_set_hw_wep(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8 pgreg;
-	u8 security;
-	u32 key0_word4;
-
-	pgreg = read_nic_byte(dev, PGSELECT);
-	write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT));
-
-	key0_word4 = read_nic_dword(dev, KEY0+4+4+4);
-	key0_word4 &= ~0xff;
-	key0_word4 |= priv->key0[3] & 0xff;
-	write_nic_dword(dev, KEY0, (priv->key0[0]));
-	write_nic_dword(dev, KEY0+4, (priv->key0[1]));
-	write_nic_dword(dev, KEY0+4+4, (priv->key0[2]));
-	write_nic_dword(dev, KEY0+4+4+4, (key0_word4));
-
-	security  = read_nic_byte(dev, SECURITY);
-	security |= (1<<SECURITY_WEP_TX_ENABLE_SHIFT);
-	security |= (1<<SECURITY_WEP_RX_ENABLE_SHIFT);
-	security &= ~SECURITY_ENCRYP_MASK;
-	security |= (SECURITY_ENCRYP_104<<SECURITY_ENCRYP_SHIFT);
-
-	write_nic_byte(dev, SECURITY, security);
-
-	DMESG("key %x %x %x %x", read_nic_dword(dev, KEY0+4+4+4),
-	      read_nic_dword(dev, KEY0+4+4), read_nic_dword(dev, KEY0+4),
-	      read_nic_dword(dev, KEY0));
-}
-
-
-void rtl8185_rf_pins_enable(struct net_device *dev)
-{
-	write_nic_word(dev, RFPinsEnable, 0x1fff); /* | tmp); */
-}
-
-void rtl8185_set_anaparam2(struct net_device *dev, u32 a)
-{
-	u8 conf3;
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-
-	conf3 = read_nic_byte(dev, CONFIG3);
-	write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT));
-	write_nic_dword(dev, ANAPARAM2, a);
-
-	conf3 = read_nic_byte(dev, CONFIG3);
-	write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT));
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-void rtl8180_set_anaparam(struct net_device *dev, u32 a)
-{
-	u8 conf3;
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-
-	conf3 = read_nic_byte(dev, CONFIG3);
-	write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT));
-	write_nic_dword(dev, ANAPARAM, a);
-
-	conf3 = read_nic_byte(dev, CONFIG3);
-	write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT));
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-void rtl8185_tx_antenna(struct net_device *dev, u8 ant)
-{
-	write_nic_byte(dev, TX_ANTENNA, ant);
-	force_pci_posting(dev);
-	mdelay(1);
-}
-
-static void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data)
-{
-	u32 phyw;
-
-	adr |= 0x80;
-
-	phyw = ((data<<8) | adr);
-
-	/* Note: we must write 0xff7c after 0x7d-0x7f to write BB register. */
-	write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24));
-	write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16));
-	write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8));
-	write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff)));
-}
-
-inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data)
-{
-	data = data & 0xff;
-	rtl8185_write_phy(dev, adr, data);
-}
-
-void write_phy_cck(struct net_device *dev, u8 adr, u32 data)
-{
-	data = data & 0xff;
-	rtl8185_write_phy(dev, adr, data | 0x10000);
-}
-
-/*
- * This configures registers for beacon tx and enables it via
- * rtl8180_beacon_tx_enable(). rtl8180_beacon_tx_disable() might
- * be used to stop beacon transmission
- */
-void rtl8180_start_tx_beacon(struct net_device *dev)
-{
-	u16 word;
-
-	DMESG("Enabling beacon TX");
-	rtl8180_prepare_beacon(dev);
-	rtl8180_irq_disable(dev);
-	rtl8180_beacon_tx_enable(dev);
-
-	word = read_nic_word(dev, AtimWnd) & ~AtimWnd_AtimWnd;
-	write_nic_word(dev, AtimWnd, word); /* word |= */
-
-	word  = read_nic_word(dev, BintrItv);
-	word &= ~BintrItv_BintrItv;
-	word |= 1000; /* priv->ieee80211->current_network.beacon_interval *
-		       * ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
-		       * FIXME: check if correct ^^ worked with 0x3e8;
-		       */
-	write_nic_word(dev, BintrItv, word);
-
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-	rtl8185b_irq_enable(dev);
-}
-
-static struct net_device_stats *rtl8180_stats(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	return &priv->ieee80211->stats;
-}
-
-/*
- * Change current and default preamble mode.
- */
-static bool MgntActSet_802_11_PowerSaveMode(struct r8180_priv *priv,
-				     enum rt_ps_mode rtPsMode)
-{
-	/* Currently, we do not change power save mode on IBSS mode. */
-	if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-		return false;
-
-	priv->ieee80211->ps = rtPsMode;
-
-	return true;
-}
-
-static void LeisurePSEnter(struct r8180_priv *priv)
-{
-	if (priv->bLeisurePs)
-		if (priv->ieee80211->ps == IEEE80211_PS_DISABLED)
-			/* IEEE80211_PS_ENABLE */
-			MgntActSet_802_11_PowerSaveMode(priv,
-				IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST);
-}
-
-static void LeisurePSLeave(struct r8180_priv *priv)
-{
-	if (priv->bLeisurePs)
-		if (priv->ieee80211->ps != IEEE80211_PS_DISABLED)
-			MgntActSet_802_11_PowerSaveMode(
-				priv, IEEE80211_PS_DISABLED);
-}
-
-void rtl8180_hw_wakeup_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(
-		dwork, struct ieee80211_device, hw_wakeup_wq);
-	struct net_device *dev = ieee->dev;
-
-	rtl8180_hw_wakeup(dev);
-}
-
-void rtl8180_hw_sleep_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(
-		dwork, struct ieee80211_device, hw_sleep_wq);
-	struct net_device *dev = ieee->dev;
-
-	rtl8180_hw_sleep_down(dev);
-}
-
-static void MgntLinkKeepAlive(struct r8180_priv *priv)
-{
-	if (priv->keepAliveLevel == 0)
-		return;
-
-	if (priv->ieee80211->state == IEEE80211_LINKED) {
-		/*
-		 * Keep-Alive.
-		 */
-
-		if ((priv->keepAliveLevel == 2) ||
-			(priv->link_detect.last_num_tx_unicast ==
-				priv->NumTxUnicast &&
-			priv->link_detect.last_num_rx_unicast ==
-				priv->ieee80211->NumRxUnicast)
-			) {
-			priv->link_detect.idle_count++;
-
-			/*
-			 * Send a Keep-Alive packet packet to AP if we had
-			 * been idle for a while.
-			 */
-			if (priv->link_detect.idle_count >=
-				KEEP_ALIVE_INTERVAL /
-				CHECK_FOR_HANG_PERIOD - 1) {
-				priv->link_detect.idle_count = 0;
-				ieee80211_sta_ps_send_null_frame(
-					priv->ieee80211, false);
-			}
-		} else {
-			priv->link_detect.idle_count = 0;
-		}
-		priv->link_detect.last_num_tx_unicast = priv->NumTxUnicast;
-		priv->link_detect.last_num_rx_unicast =
-			priv->ieee80211->NumRxUnicast;
-	}
-}
-
-void rtl8180_watch_dog(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	bool bEnterPS = false;
-	bool bBusyTraffic = false;
-	u32 TotalRxNum = 0;
-	u16 SlotIndex = 0;
-	u16 i = 0;
-	if (priv->ieee80211->actscanning == false) {
-		if ((priv->ieee80211->iw_mode != IW_MODE_ADHOC) &&
-		    (priv->ieee80211->state == IEEE80211_NOLINK) &&
-		    (priv->ieee80211->beinretry == false) &&
-		    (priv->eRFPowerState == RF_ON))
-			IPSEnter(dev);
-	}
-	if ((priv->ieee80211->state == IEEE80211_LINKED) &&
-		(priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
-		SlotIndex = (priv->link_detect.slot_index++) %
-			priv->link_detect.slot_num;
-
-		priv->link_detect.rx_frame_num[SlotIndex] =
-			priv->ieee80211->NumRxDataInPeriod +
-			priv->ieee80211->NumRxBcnInPeriod;
-
-		for (i = 0; i < priv->link_detect.slot_num; i++)
-			TotalRxNum += priv->link_detect.rx_frame_num[i];
-
-		if (TotalRxNum == 0) {
-			priv->ieee80211->state = IEEE80211_ASSOCIATING;
-			queue_work(priv->ieee80211->wq,
-				&priv->ieee80211->associate_procedure_wq);
-		}
-	}
-
-	MgntLinkKeepAlive(priv);
-
-	LeisurePSLeave(priv);
-
-	if (priv->ieee80211->state == IEEE80211_LINKED) {
-		priv->link_detect.num_rx_ok_in_period =
-			priv->ieee80211->NumRxDataInPeriod;
-		if (priv->link_detect.num_rx_ok_in_period > 666 ||
-			priv->link_detect.num_tx_ok_in_period > 666) {
-			bBusyTraffic = true;
-		}
-		if ((priv->link_detect.num_rx_ok_in_period +
-			priv->link_detect.num_tx_ok_in_period > 8)
-			|| (priv->link_detect.num_rx_ok_in_period > 2)) {
-			bEnterPS = false;
-		} else
-			bEnterPS = true;
-
-		if (bEnterPS)
-			LeisurePSEnter(priv);
-		else
-			LeisurePSLeave(priv);
-	} else
-		LeisurePSLeave(priv);
-	priv->link_detect.b_busy_traffic = bBusyTraffic;
-	priv->link_detect.num_rx_ok_in_period = 0;
-	priv->link_detect.num_tx_ok_in_period = 0;
-	priv->ieee80211->NumRxDataInPeriod = 0;
-	priv->ieee80211->NumRxBcnInPeriod = 0;
-}
-
-static int _rtl8180_up(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	priv->up = 1;
-
-	DMESG("Bringing up iface");
-	rtl8185b_adapter_start(dev);
-	rtl8185b_rx_enable(dev);
-	rtl8185b_tx_enable(dev);
-	if (priv->bInactivePs) {
-		if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-			IPSLeave(dev);
-	}
-	timer_rate_adaptive((unsigned long)dev);
-	watch_dog_adaptive((unsigned long)dev);
-	if (priv->bSwAntennaDiverity)
-			SwAntennaDiversityTimerCallback(dev);
-	ieee80211_softmac_start_protocol(priv->ieee80211);
-	return 0;
-}
-
-static int rtl8180_open(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret;
-
-	down(&priv->wx_sem);
-	ret = rtl8180_up(dev);
-	up(&priv->wx_sem);
-	return ret;
-}
-
-int rtl8180_up(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->up == 1)
-		return -1;
-
-	return _rtl8180_up(dev);
-}
-
-static int rtl8180_close(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret;
-
-	down(&priv->wx_sem);
-	ret = rtl8180_down(dev);
-	up(&priv->wx_sem);
-
-	return ret;
-}
-
-int rtl8180_down(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->up == 0)
-		return -1;
-
-	priv->up = 0;
-
-	ieee80211_softmac_stop_protocol(priv->ieee80211);
-	/* FIXME */
-	if (!netif_queue_stopped(dev))
-		netif_stop_queue(dev);
-	rtl8180_rtx_disable(dev);
-	rtl8180_irq_disable(dev);
-	del_timer_sync(&priv->watch_dog_timer);
-	del_timer_sync(&priv->rateadapter_timer);
-	cancel_delayed_work(&priv->ieee80211->rate_adapter_wq);
-	cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
-	cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
-	cancel_delayed_work(&priv->ieee80211->hw_dig_wq);
-	cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
-	del_timer_sync(&priv->SwAntennaDiversityTimer);
-	SetZebraRFPowerState8185(dev, RF_OFF);
-	memset(&priv->ieee80211->current_network,
-		0, sizeof(struct ieee80211_network));
-	priv->ieee80211->state = IEEE80211_NOLINK;
-	return 0;
-}
-
-void rtl8180_restart_wq(struct work_struct *work)
-{
-	struct r8180_priv *priv = container_of(
-		work, struct r8180_priv, reset_wq);
-	struct net_device *dev = priv->dev;
-
-	down(&priv->wx_sem);
-
-	rtl8180_commit(dev);
-
-	up(&priv->wx_sem);
-}
-
-static void rtl8180_restart(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	schedule_work(&priv->reset_wq);
-}
-
-void rtl8180_commit(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->up == 0)
-		return;
-
-	del_timer_sync(&priv->watch_dog_timer);
-	del_timer_sync(&priv->rateadapter_timer);
-	cancel_delayed_work(&priv->ieee80211->rate_adapter_wq);
-	cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
-	cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
-	cancel_delayed_work(&priv->ieee80211->hw_dig_wq);
-	cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
-	del_timer_sync(&priv->SwAntennaDiversityTimer);
-	ieee80211_softmac_stop_protocol(priv->ieee80211);
-	rtl8180_irq_disable(dev);
-	rtl8180_rtx_disable(dev);
-	_rtl8180_up(dev);
-}
-
-static void r8180_set_multicast(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	short promisc;
-
-	promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
-
-	if (promisc != priv->promisc)
-		rtl8180_restart(dev);
-
-	priv->promisc = promisc;
-}
-
-static int r8180_set_mac_adr(struct net_device *dev, void *mac)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct sockaddr *addr = mac;
-
-	down(&priv->wx_sem);
-
-	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-
-	if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
-		memcpy(priv->ieee80211->current_network.bssid,
-			dev->dev_addr, ETH_ALEN);
-
-	if (priv->up) {
-		rtl8180_down(dev);
-		rtl8180_up(dev);
-	}
-
-	up(&priv->wx_sem);
-
-	return 0;
-}
-
-/* based on ipw2200 driver */
-static int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct iwreq *wrq = (struct iwreq *) rq;
-	int ret = -1;
-
-	switch (cmd) {
-	case RTL_IOCTL_WPA_SUPPLICANT:
-		ret = ieee80211_wpa_supplicant_ioctl(
-			priv->ieee80211, &wrq->u.data);
-		return ret;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return -EOPNOTSUPP;
-}
-
-static const struct net_device_ops rtl8180_netdev_ops = {
-	.ndo_open		= rtl8180_open,
-	.ndo_stop		= rtl8180_close,
-	.ndo_get_stats		= rtl8180_stats,
-	.ndo_tx_timeout		= rtl8180_restart,
-	.ndo_do_ioctl		= rtl8180_ioctl,
-	.ndo_set_rx_mode	= r8180_set_multicast,
-	.ndo_set_mac_address	= r8180_set_mac_adr,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_start_xmit		= ieee80211_rtl_xmit,
-};
-
-static int rtl8180_pci_probe(struct pci_dev *pdev,
-			     const struct pci_device_id *id)
-{
-	unsigned long ioaddr = 0;
-	struct net_device *dev = NULL;
-	struct r8180_priv *priv = NULL;
-	u8 unit = 0;
-	int ret = -ENODEV;
-
-	unsigned long pmem_start, pmem_len, pmem_flags;
-
-	DMESG("Configuring chip resources");
-
-	if (pci_enable_device(pdev)) {
-		DMESG("Failed to enable PCI device");
-		return -EIO;
-	}
-
-	pci_set_master(pdev);
-	pci_set_dma_mask(pdev, 0xffffff00ULL);
-	pci_set_consistent_dma_mask(pdev, 0xffffff00ULL);
-	dev = alloc_ieee80211(sizeof(struct r8180_priv));
-	if (!dev) {
-		ret = -ENOMEM;
-		goto fail_free;
-	}
-	priv = ieee80211_priv(dev);
-	priv->ieee80211 = netdev_priv(dev);
-
-	pci_set_drvdata(pdev, dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	priv = ieee80211_priv(dev);
-	priv->pdev = pdev;
-
-	pmem_start = pci_resource_start(pdev, 1);
-	pmem_len = pci_resource_len(pdev, 1);
-	pmem_flags = pci_resource_flags(pdev, 1);
-
-	if (!(pmem_flags & IORESOURCE_MEM)) {
-		DMESG("region #1 not a MMIO resource, aborting");
-		goto fail;
-	}
-
-	if (!request_mem_region(pmem_start, pmem_len, RTL8180_MODULE_NAME)) {
-		DMESG("request_mem_region failed!");
-		goto fail;
-	}
-
-	ioaddr = (unsigned long)ioremap_nocache(pmem_start, pmem_len);
-	if (ioaddr == (unsigned long)NULL) {
-		DMESG("ioremap failed!");
-		goto fail1;
-	}
-
-	dev->mem_start = ioaddr; /* shared mem start */
-	dev->mem_end = ioaddr + pci_resource_len(pdev, 0); /* shared mem end */
-
-	pci_read_config_byte(pdev, 0x05, &unit);
-	pci_write_config_byte(pdev, 0x05, unit & (~0x04));
-
-	dev->irq = pdev->irq;
-	priv->irq = 0;
-
-	dev->netdev_ops = &rtl8180_netdev_ops;
-	dev->wireless_handlers = &r8180_wx_handlers_def;
-
-	dev->type = ARPHRD_ETHER;
-	dev->watchdog_timeo = HZ*3;
-
-	if (dev_alloc_name(dev, ifname) < 0) {
-		DMESG("Oops: devname already taken! Trying wlan%%d...\n");
-		strcpy(ifname, "wlan%d");
-		dev_alloc_name(dev, ifname);
-	}
-
-	if (rtl8180_init(dev) != 0) {
-		DMESG("Initialization failed");
-		goto fail1;
-	}
-
-	netif_carrier_off(dev);
-
-	if (register_netdev(dev))
-		goto fail1;
-
-	rtl8180_proc_init_one(dev);
-
-	DMESG("Driver probe completed\n");
-	return 0;
-fail1:
-	if (dev->mem_start != (unsigned long)NULL) {
-		iounmap((void __iomem *)dev->mem_start);
-		release_mem_region(pci_resource_start(pdev, 1),
-				   pci_resource_len(pdev, 1));
-	}
-fail:
-	if (dev) {
-		if (priv->irq) {
-			free_irq(dev->irq, dev);
-			dev->irq = 0;
-		}
-		free_ieee80211(dev);
-	}
-
-fail_free:
-	pci_disable_device(pdev);
-
-	DMESG("wlan driver load failed\n");
-	return ret;
-}
-
-static void rtl8180_pci_remove(struct pci_dev *pdev)
-{
-	struct r8180_priv *priv;
-	struct net_device *dev = pci_get_drvdata(pdev);
-
-	if (dev) {
-		unregister_netdev(dev);
-
-		priv = ieee80211_priv(dev);
-
-		rtl8180_proc_remove_one(dev);
-		rtl8180_down(dev);
-		priv->rf_close(dev);
-		rtl8180_reset(dev);
-		mdelay(10);
-
-		if (priv->irq) {
-			DMESG("Freeing irq %d", dev->irq);
-			free_irq(dev->irq, dev);
-			priv->irq = 0;
-		}
-
-		free_rx_desc_ring(dev);
-		free_tx_desc_rings(dev);
-
-		if (dev->mem_start != (unsigned long)NULL) {
-			iounmap((void __iomem *)dev->mem_start);
-			release_mem_region(pci_resource_start(pdev, 1),
-					   pci_resource_len(pdev, 1));
-		}
-
-		free_ieee80211(dev);
-	}
-	pci_disable_device(pdev);
-
-	DMESG("wlan driver removed\n");
-}
-
-static int __init rtl8180_pci_module_init(void)
-{
-	int ret;
-
-	ret = ieee80211_crypto_init();
-	if (ret) {
-		pr_err("ieee80211_crypto_init() failed %d\n", ret);
-		return ret;
-	}
-	ret = ieee80211_crypto_tkip_init();
-	if (ret) {
-		pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
-		return ret;
-	}
-	ret = ieee80211_crypto_ccmp_init();
-	if (ret) {
-		pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
-		return ret;
-	}
-	ret = ieee80211_crypto_wep_init();
-	if (ret) {
-		pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
-		return ret;
-	}
-
-	pr_info("\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n");
-	pr_info("Copyright (c) 2004-2005, Andrea Merello\n");
-	DMESG("Initializing module");
-	DMESG("Wireless extensions version %d", WIRELESS_EXT);
-	rtl8180_proc_module_init();
-
-	if (pci_register_driver(&rtl8180_pci_driver)) {
-		DMESG("No device found");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static void __exit rtl8180_pci_module_exit(void)
-{
-	pci_unregister_driver(&rtl8180_pci_driver);
-	rtl8180_proc_module_remove();
-	ieee80211_crypto_tkip_exit();
-	ieee80211_crypto_ccmp_exit();
-	ieee80211_crypto_wep_exit();
-	ieee80211_crypto_deinit();
-	DMESG("Exiting");
-}
-
-static void rtl8180_try_wake_queue(struct net_device *dev, int pri)
-{
-	unsigned long flags;
-	short enough_desc;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	spin_lock_irqsave(&priv->tx_lock, flags);
-	enough_desc = check_nic_enought_desc(dev, pri);
-	spin_unlock_irqrestore(&priv->tx_lock, flags);
-
-	if (enough_desc)
-		ieee80211_rtl_wake_queue(priv->ieee80211);
-}
-
-static void rtl8180_tx_isr(struct net_device *dev, int pri, short error)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u32 *tail; /* tail virtual addr */
-	u32 *head; /* head virtual addr */
-	u32 *begin; /* start of ring virtual addr */
-	u32 *nicv; /* nic pointer virtual addr */
-	u32 nic; /* nic pointer physical addr */
-	u32 nicbegin; /* start of ring physical addr */
-	unsigned long flag;
-	/* physical addr are ok on 32 bits since we set DMA mask */
-	int offs;
-	int j, i;
-	int hd;
-	if (error)
-		priv->stats.txretry++;
-	spin_lock_irqsave(&priv->tx_lock, flag);
-	switch (pri) {
-	case MANAGE_PRIORITY:
-		tail = priv->txmapringtail;
-		begin = priv->txmapring;
-		head = priv->txmapringhead;
-		nic = read_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR);
-		nicbegin = priv->txmapringdma;
-		break;
-	case BK_PRIORITY:
-		tail = priv->txbkpringtail;
-		begin = priv->txbkpring;
-		head = priv->txbkpringhead;
-		nic = read_nic_dword(dev, TX_BKPRIORITY_RING_ADDR);
-		nicbegin = priv->txbkpringdma;
-		break;
-	case BE_PRIORITY:
-		tail = priv->txbepringtail;
-		begin = priv->txbepring;
-		head = priv->txbepringhead;
-		nic = read_nic_dword(dev, TX_BEPRIORITY_RING_ADDR);
-		nicbegin = priv->txbepringdma;
-		break;
-	case VI_PRIORITY:
-		tail = priv->txvipringtail;
-		begin = priv->txvipring;
-		head = priv->txvipringhead;
-		nic = read_nic_dword(dev, TX_VIPRIORITY_RING_ADDR);
-		nicbegin = priv->txvipringdma;
-		break;
-	case VO_PRIORITY:
-		tail = priv->txvopringtail;
-		begin = priv->txvopring;
-		head = priv->txvopringhead;
-		nic = read_nic_dword(dev, TX_VOPRIORITY_RING_ADDR);
-		nicbegin = priv->txvopringdma;
-		break;
-	case HI_PRIORITY:
-		tail = priv->txhpringtail;
-		begin = priv->txhpring;
-		head = priv->txhpringhead;
-		nic = read_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR);
-		nicbegin = priv->txhpringdma;
-		break;
-
-	default:
-		spin_unlock_irqrestore(&priv->tx_lock, flag);
-		return;
-	}
-
-	nicv = (u32 *)((nic - nicbegin) + (u8 *)begin);
-	if ((head <= tail && (nicv > tail || nicv < head)) ||
-		(head > tail && (nicv > tail && nicv < head))) {
-			DMESGW("nic has lost pointer");
-			spin_unlock_irqrestore(&priv->tx_lock, flag);
-			rtl8180_restart(dev);
-			return;
-		}
-
-	/*
-	 * We check all the descriptors between the head and the nic,
-	 * but not the currently pointed by the nic (the next to be txed)
-	 * and the previous of the pointed (might be in process ??)
-	 */
-	offs = (nic - nicbegin);
-	offs = offs / 8 / 4;
-	hd = (head - begin) / 8;
-
-	if (offs >= hd)
-		j = offs - hd;
-	else
-		j = offs + (priv->txringcount-1-hd);
-
-	j -= 2;
-	if (j < 0)
-		j = 0;
-
-	for (i = 0; i < j; i++) {
-		if ((*head) & (1<<31))
-			break;
-		if (((*head)&(0x10000000)) != 0) {
-			priv->CurrRetryCnt += (u16)((*head) & (0x000000ff));
-			if (!error)
-				priv->NumTxOkTotal++;
-		}
-
-		if (!error)
-			priv->NumTxOkBytesTotal += (*(head+3)) & (0x00000fff);
-
-		*head = *head & ~(1<<31);
-
-		if ((head - begin)/8 == priv->txringcount-1)
-			head = begin;
-		else
-			head += 8;
-	}
-
-	/*
-	 * The head has been moved to the last certainly TXed
-	 * (or at least processed by the nic) packet.
-	 * The driver take forcefully owning of all these packets
-	 * If the packet previous of the nic pointer has been
-	 * processed this doesn't matter: it will be checked
-	 * here at the next round. Anyway if no more packet are
-	 * TXed no memory leak occur at all.
-	 */
-
-	switch (pri) {
-	case MANAGE_PRIORITY:
-		priv->txmapringhead = head;
-
-		if (priv->ack_tx_to_ieee) {
-			if (rtl8180_is_tx_queue_empty(dev)) {
-				priv->ack_tx_to_ieee = 0;
-				ieee80211_ps_tx_ack(priv->ieee80211, !error);
-			}
-		}
-		break;
-	case BK_PRIORITY:
-		priv->txbkpringhead = head;
-		break;
-	case BE_PRIORITY:
-		priv->txbepringhead = head;
-		break;
-	case VI_PRIORITY:
-		priv->txvipringhead = head;
-		break;
-	case VO_PRIORITY:
-		priv->txvopringhead = head;
-		break;
-	case HI_PRIORITY:
-		priv->txhpringhead = head;
-		break;
-	}
-
-	spin_unlock_irqrestore(&priv->tx_lock, flag);
-}
-
-static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
-{
-	struct net_device *dev = (struct net_device *) netdev;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	unsigned long flags;
-	u32 inta;
-
-	/* We should return IRQ_NONE, but for now let me keep this */
-	if (priv->irq_enabled == 0)
-		return IRQ_HANDLED;
-
-	spin_lock_irqsave(&priv->irq_th_lock, flags);
-
-	/* ISR: 4bytes */
-	inta = read_nic_dword(dev, ISR);
-	write_nic_dword(dev, ISR, inta); /* reset int situation */
-
-	priv->stats.shints++;
-
-	if (!inta) {
-		spin_unlock_irqrestore(&priv->irq_th_lock, flags);
-		return IRQ_HANDLED;
-	/*
-	 * most probably we can safely return IRQ_NONE,
-	 * but for now is better to avoid problems
-	 */
-	}
-
-	if (inta == 0xffff) {
-		/* HW disappeared */
-		spin_unlock_irqrestore(&priv->irq_th_lock, flags);
-		return IRQ_HANDLED;
-	}
-
-	priv->stats.ints++;
-
-	if (!netif_running(dev)) {
-		spin_unlock_irqrestore(&priv->irq_th_lock, flags);
-		return IRQ_HANDLED;
-	}
-
-	if (inta & ISR_TimeOut)
-		write_nic_dword(dev, TimerInt, 0);
-
-	if (inta & ISR_TBDOK)
-		priv->stats.txbeacon++;
-
-	if (inta & ISR_TBDER)
-		priv->stats.txbeaconerr++;
-
-	if (inta & IMR_TMGDOK)
-		rtl8180_tx_isr(dev, MANAGE_PRIORITY, 0);
-
-	if (inta & ISR_THPDER) {
-		priv->stats.txhperr++;
-		rtl8180_tx_isr(dev, HI_PRIORITY, 1);
-		priv->ieee80211->stats.tx_errors++;
-	}
-
-	if (inta & ISR_THPDOK) { /* High priority tx ok */
-		priv->link_detect.num_tx_ok_in_period++;
-		priv->stats.txhpokint++;
-		rtl8180_tx_isr(dev, HI_PRIORITY, 0);
-	}
-
-	if (inta & ISR_RER)
-		priv->stats.rxerr++;
-
-	if (inta & ISR_TBKDER) { /* corresponding to BK_PRIORITY */
-		priv->stats.txbkperr++;
-		priv->ieee80211->stats.tx_errors++;
-		rtl8180_tx_isr(dev, BK_PRIORITY, 1);
-		rtl8180_try_wake_queue(dev, BK_PRIORITY);
-	}
-
-	if (inta & ISR_TBEDER) { /* corresponding to BE_PRIORITY */
-		priv->stats.txbeperr++;
-		priv->ieee80211->stats.tx_errors++;
-		rtl8180_tx_isr(dev, BE_PRIORITY, 1);
-		rtl8180_try_wake_queue(dev, BE_PRIORITY);
-	}
-	if (inta & ISR_TNPDER) { /* corresponding to VO_PRIORITY */
-		priv->stats.txnperr++;
-		priv->ieee80211->stats.tx_errors++;
-		rtl8180_tx_isr(dev, NORM_PRIORITY, 1);
-		rtl8180_try_wake_queue(dev, NORM_PRIORITY);
-	}
-
-	if (inta & ISR_TLPDER) { /* corresponding to VI_PRIORITY */
-		priv->stats.txlperr++;
-		priv->ieee80211->stats.tx_errors++;
-		rtl8180_tx_isr(dev, LOW_PRIORITY, 1);
-		rtl8180_try_wake_queue(dev, LOW_PRIORITY);
-	}
-
-	if (inta & ISR_ROK) {
-		priv->stats.rxint++;
-		tasklet_schedule(&priv->irq_rx_tasklet);
-	}
-
-	if (inta & ISR_RQoSOK) {
-		priv->stats.rxint++;
-		tasklet_schedule(&priv->irq_rx_tasklet);
-	}
-
-	if (inta & ISR_BcnInt)
-		rtl8180_prepare_beacon(dev);
-
-	if (inta & ISR_RDU) {
-		DMESGW("No RX descriptor available");
-		priv->stats.rxrdu++;
-		tasklet_schedule(&priv->irq_rx_tasklet);
-	}
-
-	if (inta & ISR_RXFOVW) {
-		priv->stats.rxoverflow++;
-		tasklet_schedule(&priv->irq_rx_tasklet);
-	}
-
-	if (inta & ISR_TXFOVW)
-		priv->stats.txoverflow++;
-
-	if (inta & ISR_TNPDOK) { /* Normal priority tx ok */
-		priv->link_detect.num_tx_ok_in_period++;
-		priv->stats.txnpokint++;
-		rtl8180_tx_isr(dev, NORM_PRIORITY, 0);
-		rtl8180_try_wake_queue(dev, NORM_PRIORITY);
-	}
-
-	if (inta & ISR_TLPDOK) { /* Low priority tx ok */
-		priv->link_detect.num_tx_ok_in_period++;
-		priv->stats.txlpokint++;
-		rtl8180_tx_isr(dev, LOW_PRIORITY, 0);
-		rtl8180_try_wake_queue(dev, LOW_PRIORITY);
-	}
-
-	if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */
-		priv->stats.txbkpokint++;
-		priv->link_detect.num_tx_ok_in_period++;
-		rtl8180_tx_isr(dev, BK_PRIORITY, 0);
-		rtl8180_try_wake_queue(dev, BE_PRIORITY);
-	}
-
-	if (inta & ISR_TBEDOK) { /* corresponding to BE_PRIORITY */
-		priv->stats.txbeperr++;
-		priv->link_detect.num_tx_ok_in_period++;
-		rtl8180_tx_isr(dev, BE_PRIORITY, 0);
-		rtl8180_try_wake_queue(dev, BE_PRIORITY);
-	}
-	force_pci_posting(dev);
-	spin_unlock_irqrestore(&priv->irq_th_lock, flags);
-
-	return IRQ_HANDLED;
-}
-
-void rtl8180_irq_rx_tasklet(struct r8180_priv *priv)
-{
-	rtl8180_rx(priv->dev);
-}
-
-void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
-{
-	struct ieee80211_device *ieee = container_of(
-		work, struct ieee80211_device, GPIOChangeRFWorkItem.work);
-	struct net_device *dev = ieee->dev;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8 btPSR;
-	u8 btConfig0;
-	enum rt_rf_power_state eRfPowerStateToSet;
-	bool bActuallySet = false;
-
-	char *argv[3];
-	static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
-	static char *envp[] = {"HOME=/", "TERM=linux",
-		"PATH=/usr/bin:/bin", NULL};
-	static int readf_count;
-
-	readf_count = (readf_count+1)%0xffff;
-	/* We should turn off LED before polling FF51[4]. */
-
-	/* Turn off LED. */
-	btPSR = read_nic_byte(dev, PSR);
-	write_nic_byte(dev, PSR, (btPSR & ~BIT3));
-
-	/* It need to delay 4us suggested */
-	udelay(4);
-
-	/* HW radio On/Off according to the value of FF51[4](config0) */
-	btConfig0 = btPSR = read_nic_byte(dev, CONFIG0);
-
-	eRfPowerStateToSet = (btConfig0 & BIT4) ?  RF_ON : RF_OFF;
-
-	/* Turn LED back on when radio enabled */
-	if (eRfPowerStateToSet == RF_ON)
-		write_nic_byte(dev, PSR, btPSR | BIT3);
-
-	if ((priv->ieee80211->bHwRadioOff == true) &&
-	   (eRfPowerStateToSet == RF_ON)) {
-		priv->ieee80211->bHwRadioOff = false;
-		bActuallySet = true;
-	} else if ((priv->ieee80211->bHwRadioOff == false) &&
-		  (eRfPowerStateToSet == RF_OFF)) {
-		priv->ieee80211->bHwRadioOff = true;
-		bActuallySet = true;
-	}
-
-	if (bActuallySet) {
-		MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
-
-		/* To update the UI status for Power status changed */
-		if (priv->ieee80211->bHwRadioOff == true)
-			argv[1] = "RFOFF";
-		else
-			argv[1] = "RFON";
-		argv[0] = RadioPowerPath;
-		argv[2] = NULL;
-
-		call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC);
-	}
-}
-
-module_init(rtl8180_pci_module_init);
-module_exit(rtl8180_pci_module_exit);
diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c
deleted file mode 100644
index 8c020e064869..000000000000
--- a/drivers/staging/rtl8187se/r8180_dm.c
+++ /dev/null
@@ -1,1139 +0,0 @@
-#include "r8180_dm.h"
-#include "r8180_hw.h"
-#include "r8180_93cx6.h"
-
- /*	Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */
-#define RATE_ADAPTIVE_TIMER_PERIOD      300
-
-bool CheckHighPower(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee80211;
-
-	if (!priv->bRegHighPowerMechanism)
-		return false;
-
-	if (ieee->state == IEEE80211_LINKED_SCANNING)
-		return false;
-
-	return true;
-}
-
-/*
- *	Description:
- *		Update Tx power level if necessary.
- *		See also DoRxHighPower() and SetTxPowerLevel8185() for reference.
- *
- *	Note:
- *		The reason why we udpate Tx power level here instead of DoRxHighPower()
- *		is the number of IO to change Tx power is much more than channel TR switch
- *		and they are related to OFDM and MAC registers.
- *		So, we don't want to update it so frequently in per-Rx packet base.
- */
-static void DoTxHighPower(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u16			HiPwrUpperTh = 0;
-	u16			HiPwrLowerTh = 0;
-	u8			RSSIHiPwrUpperTh;
-	u8			RSSIHiPwrLowerTh;
-	u8			u1bTmp;
-	char			OfdmTxPwrIdx, CckTxPwrIdx;
-
-	HiPwrUpperTh = priv->RegHiPwrUpperTh;
-	HiPwrLowerTh = priv->RegHiPwrLowerTh;
-
-	HiPwrUpperTh = HiPwrUpperTh * 10;
-	HiPwrLowerTh = HiPwrLowerTh * 10;
-	RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh;
-	RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh;
-
-	/* lzm add 080826 */
-	OfdmTxPwrIdx  = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
-	CckTxPwrIdx  = priv->chtxpwr[priv->ieee80211->current_network.channel];
-
-	if ((priv->UndecoratedSmoothedSS > HiPwrUpperTh) ||
-		(priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) {
-		/* Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah */
-
-		priv->bToUpdateTxPwr = true;
-		u1bTmp = read_nic_byte(dev, CCK_TXAGC);
-
-		/* If it never enter High Power. */
-		if (CckTxPwrIdx == u1bTmp) {
-			u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0;  /* 8dbm */
-			write_nic_byte(dev, CCK_TXAGC, u1bTmp);
-
-			u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
-			u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0;  /* 8dbm */
-			write_nic_byte(dev, OFDM_TXAGC, u1bTmp);
-		}
-
-	} else if ((priv->UndecoratedSmoothedSS < HiPwrLowerTh) &&
-		(!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) {
-		if (priv->bToUpdateTxPwr) {
-			priv->bToUpdateTxPwr = false;
-			/* SD3 required. */
-			u1bTmp = read_nic_byte(dev, CCK_TXAGC);
-			if (u1bTmp < CckTxPwrIdx) {
-				write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx);
-			}
-
-			u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
-			if (u1bTmp < OfdmTxPwrIdx) {
-				write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
-			}
-		}
-	}
-}
-
-
-/*
- *	Description:
- *		Callback function of UpdateTxPowerWorkItem.
- *		Because of some event happened, e.g. CCX TPC, High Power Mechanism,
- *		We update Tx power of current channel again.
- */
-void rtl8180_tx_pw_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, tx_pw_wq);
-	struct net_device *dev = ieee->dev;
-
-	DoTxHighPower(dev);
-}
-
-
-/*
- *	Return TRUE if we shall perform DIG Mechanism, FALSE otherwise.
- */
-bool CheckDig(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee80211;
-
-	if (!priv->bDigMechanism)
-		return false;
-
-	if (ieee->state != IEEE80211_LINKED)
-		return false;
-
-	if ((priv->ieee80211->rate / 5) < 36) /* Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. */
-		return false;
-	return true;
-}
-/*
- *	Implementation of DIG for Zebra and Zebra2.
- */
-static void DIG_Zebra(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u16			CCKFalseAlarm, OFDMFalseAlarm;
-	u16			OfdmFA1, OfdmFA2;
-	int			InitialGainStep = 7; /* The number of initial gain stages. */
-	int			LowestGainStage = 4; /* The capable lowest stage of performing dig workitem. */
-	u32			AwakePeriodIn2Sec = 0;
-
-	CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff);
-	OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff);
-	OfdmFA1 =  0x15;
-	OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8;
-
-	/* The number of initial gain steps is different, by Bruce, 2007-04-13. */
-	if (priv->InitialGain == 0) { /* autoDIG */
-		/* Advised from SD3 DZ */
-		priv->InitialGain = 4; /* In 87B, m74dBm means State 4 (m82dBm) */
-	}
-	/* Advised from SD3 DZ */
-	OfdmFA1 = 0x20;
-
-#if 1 /* lzm reserved 080826 */
-	AwakePeriodIn2Sec = (2000 - priv->DozePeriodInPast2Sec);
-	priv->DozePeriodInPast2Sec = 0;
-
-	if (AwakePeriodIn2Sec) {
-		OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000);
-		OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000);
-	} else {
-		;
-	}
-#endif
-
-	InitialGainStep = 8;
-	LowestGainStage = priv->RegBModeGainStage; /* Lowest gain stage. */
-
-	if (OFDMFalseAlarm > OfdmFA1) {
-		if (OFDMFalseAlarm > OfdmFA2) {
-			priv->DIG_NumberFallbackVote++;
-			if (priv->DIG_NumberFallbackVote > 1) {
-				/* serious OFDM  False Alarm, need fallback */
-				if (priv->InitialGain < InitialGainStep) {
-					priv->InitialGainBackUp = priv->InitialGain;
-
-					priv->InitialGain = (priv->InitialGain + 1);
-					UpdateInitialGain(dev);
-				}
-				priv->DIG_NumberFallbackVote = 0;
-				priv->DIG_NumberUpgradeVote = 0;
-			}
-		} else {
-			if (priv->DIG_NumberFallbackVote)
-				priv->DIG_NumberFallbackVote--;
-		}
-		priv->DIG_NumberUpgradeVote = 0;
-	} else {
-		if (priv->DIG_NumberFallbackVote)
-			priv->DIG_NumberFallbackVote--;
-		priv->DIG_NumberUpgradeVote++;
-
-		if (priv->DIG_NumberUpgradeVote > 9) {
-			if (priv->InitialGain > LowestGainStage) { /* In 87B, m78dBm means State 4 (m864dBm) */
-				priv->InitialGainBackUp = priv->InitialGain;
-
-				priv->InitialGain = (priv->InitialGain - 1);
-				UpdateInitialGain(dev);
-			}
-			priv->DIG_NumberFallbackVote = 0;
-			priv->DIG_NumberUpgradeVote = 0;
-		}
-	}
-}
-
-/*
- *	Dispatch DIG implementation according to RF.
- */
-static void DynamicInitGain(struct net_device *dev)
-{
-	DIG_Zebra(dev);
-}
-
-void rtl8180_hw_dig_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_dig_wq);
-	struct net_device *dev = ieee->dev;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	/* Read CCK and OFDM False Alarm. */
-	priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM);
-
-
-	/* Adjust Initial Gain dynamically. */
-	DynamicInitGain(dev);
-
-}
-
-static int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate)
-{
-	u8 rate_len;
-	u8 rate_ex_len;
-	u8                      RateMask = 0x7F;
-	u8                      idx;
-	unsigned short          Found = 0;
-	u8                      NaiveTxRate = TxRate&RateMask;
-
-	rate_len = priv->ieee80211->current_network.rates_len;
-	rate_ex_len = priv->ieee80211->current_network.rates_ex_len;
-	for (idx = 0; idx < rate_len; idx++) {
-		if ((priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate) {
-			Found = 1;
-			goto found_rate;
-		}
-	}
-	for (idx = 0; idx < rate_ex_len; idx++) {
-		if ((priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate) {
-			Found = 1;
-			goto found_rate;
-		}
-	}
-	return Found;
-found_rate:
-	return Found;
-}
-
-/*
- *	Get the Tx rate one degree up form the input rate in the supported rates.
- *	Return the upgrade rate if it is successed, otherwise return the input rate.
- */
-static u8 GetUpgradeTxRate(struct net_device *dev, u8 rate)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8                      UpRate;
-
-	/* Upgrade 1 degree. */
-	switch (rate) {
-	case 108: /* Up to 54Mbps. */
-		UpRate = 108;
-		break;
-
-	case 96: /* Up to 54Mbps. */
-		UpRate = 108;
-		break;
-
-	case 72: /* Up to 48Mbps. */
-		UpRate = 96;
-		break;
-
-	case 48: /* Up to 36Mbps. */
-		UpRate = 72;
-		break;
-
-	case 36: /* Up to 24Mbps. */
-		UpRate = 48;
-		break;
-
-	case 22: /* Up to 18Mbps. */
-		UpRate = 36;
-		break;
-
-	case 11: /* Up to 11Mbps. */
-		UpRate = 22;
-		break;
-
-	case 4: /* Up to 5.5Mbps. */
-		UpRate = 11;
-		break;
-
-	case 2: /* Up to 2Mbps. */
-		UpRate = 4;
-		break;
-
-	default:
-		printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
-		return rate;
-	}
-	/* Check if the rate is valid. */
-	if (IncludedInSupportedRates(priv, UpRate)) {
-		return UpRate;
-	} else {
-		return rate;
-	}
-	return rate;
-}
-/*
- *	Get the Tx rate one degree down form the input rate in the supported rates.
- *	Return the degrade rate if it is successed, otherwise return the input rate.
- */
-
-static u8 GetDegradeTxRate(struct net_device *dev, u8 rate)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8                      DownRate;
-
-	/* Upgrade 1 degree. */
-	switch (rate) {
-	case 108: /* Down to 48Mbps. */
-		DownRate = 96;
-		break;
-
-	case 96: /* Down to 36Mbps. */
-		DownRate = 72;
-		break;
-
-	case 72: /* Down to 24Mbps. */
-		DownRate = 48;
-		break;
-
-	case 48: /* Down to 18Mbps. */
-		DownRate = 36;
-		break;
-
-	case 36: /* Down to 11Mbps. */
-		DownRate = 22;
-		break;
-
-	case 22: /* Down to 5.5Mbps. */
-		DownRate = 11;
-		break;
-
-	case 11: /* Down to 2Mbps. */
-		DownRate = 4;
-		break;
-
-	case 4: /* Down to 1Mbps. */
-		DownRate = 2;
-		break;
-
-	case 2: /* Down to 1Mbps. */
-		DownRate = 2;
-		break;
-
-	default:
-		printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
-		return rate;
-	}
-	/* Check if the rate is valid. */
-	if (IncludedInSupportedRates(priv, DownRate)) {
-		return DownRate;
-	} else {
-		return rate;
-	}
-	return rate;
-}
-/*
- *      Helper function to determine if specified data rate is
- *      CCK rate.
- */
-
-static bool MgntIsCckRate(u16 rate)
-{
-	bool bReturn = false;
-
-	if ((rate <= 22) && (rate != 12) && (rate != 18)) {
-		bReturn = true;
-	}
-
-	return bReturn;
-}
-/*
- *	Description:
- *		Tx Power tracking mechanism routine on 87SE.
- */
-void TxPwrTracking87SE(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u8	tmpu1Byte, CurrentThermal, Idx;
-	char	CckTxPwrIdx, OfdmTxPwrIdx;
-
-	tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL);
-	CurrentThermal = (tmpu1Byte & 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */
-	CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c : CurrentThermal;/* lzm add 080826 */
-
-	if (CurrentThermal != priv->ThermalMeter) {
-		/* Update Tx Power level on each channel. */
-		for (Idx = 1; Idx < 15; Idx++) {
-			CckTxPwrIdx = priv->chtxpwr[Idx];
-			OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx];
-
-			if (CurrentThermal > priv->ThermalMeter) {
-				/* higher thermal meter. */
-				CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
-				OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
-
-				if (CckTxPwrIdx > 35)
-					CckTxPwrIdx = 35; /* Force TxPower to maximal index. */
-				if (OfdmTxPwrIdx > 35)
-					OfdmTxPwrIdx = 35;
-			} else {
-				/* lower thermal meter. */
-				CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
-				OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
-
-				if (CckTxPwrIdx < 0)
-					CckTxPwrIdx = 0;
-				if (OfdmTxPwrIdx < 0)
-					OfdmTxPwrIdx = 0;
-			}
-
-			/* Update TxPower level on CCK and OFDM resp. */
-			priv->chtxpwr[Idx] = CckTxPwrIdx;
-			priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx;
-		}
-
-		/* Update TxPower level immediately. */
-		rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel);
-	}
-	priv->ThermalMeter = CurrentThermal;
-}
-static void StaRateAdaptive87SE(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	unsigned long	CurrTxokCnt;
-	u16		CurrRetryCnt;
-	u16		CurrRetryRate;
-	unsigned long	CurrRxokCnt;
-	bool		bTryUp = false;
-	bool		bTryDown = false;
-	u8		TryUpTh = 1;
-	u8		TryDownTh = 2;
-	u32		TxThroughput;
-	long		CurrSignalStrength;
-	bool		bUpdateInitialGain = false;
-	u8		u1bOfdm = 0, u1bCck = 0;
-	char		OfdmTxPwrIdx, CckTxPwrIdx;
-
-	priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
-
-
-	CurrRetryCnt	= priv->CurrRetryCnt;
-	CurrTxokCnt	= priv->NumTxOkTotal - priv->LastTxokCnt;
-	CurrRxokCnt	= priv->ieee80211->NumRxOkTotal - priv->LastRxokCnt;
-	CurrSignalStrength = priv->Stats_RecvSignalPower;
-	TxThroughput = (u32)(priv->NumTxOkBytesTotal - priv->LastTxOKBytes);
-	priv->LastTxOKBytes = priv->NumTxOkBytesTotal;
-	priv->CurrentOperaRate = priv->ieee80211->rate / 5;
-	/* 2 Compute retry ratio. */
-	if (CurrTxokCnt > 0) {
-		CurrRetryRate = (u16)(CurrRetryCnt * 100 / CurrTxokCnt);
-	} else {
-	/* It may be serious retry. To distinguish serious retry or no packets modified by Bruce */
-		CurrRetryRate = (u16)(CurrRetryCnt * 100 / 1);
-	}
-
-	priv->LastRetryCnt = priv->CurrRetryCnt;
-	priv->LastTxokCnt = priv->NumTxOkTotal;
-	priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal;
-	priv->CurrRetryCnt = 0;
-
-	/* 2No Tx packets, return to init_rate or not? */
-	if (CurrRetryRate == 0 && CurrTxokCnt == 0) {
-		/*
-		 * After 9 (30*300ms) seconds in this condition, we try to raise rate.
-		 */
-		priv->TryupingCountNoData++;
-
-		/* [TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 */
-		if (priv->TryupingCountNoData > 30) {
-			priv->TryupingCountNoData = 0;
-			priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
-			/* Reset Fail Record */
-			priv->LastFailTxRate = 0;
-			priv->LastFailTxRateSS = -200;
-			priv->FailTxRateCount = 0;
-		}
-		goto SetInitialGain;
-	} else {
-		priv->TryupingCountNoData = 0; /*Reset trying up times. */
-	}
-
-
-	/*
-	 * For Netgear case, I comment out the following signal strength estimation,
-	 * which can results in lower rate to transmit when sample is NOT enough (e.g. PING request).
-	 *
-	 * Restructure rate adaptive as the following main stages:
-	 * (1) Add retry threshold in 54M upgrading condition with signal strength.
-	 * (2) Add the mechanism to degrade to CCK rate according to signal strength
-	 *		and retry rate.
-	 * (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated
-	 *		situation, Initial Gain Update is upon on DIG mechanism except CCK rate.
-	 * (4) Add the mechanism of trying to upgrade tx rate.
-	 * (5) Record the information of upping tx rate to avoid trying upping tx rate constantly.
-	 *
-	 */
-
-	/*
-	 * 11Mbps or 36Mbps
-	 * Check more times in these rate(key rates).
-	 */
-	if (priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72)
-		TryUpTh += 9;
-	/*
-	 * Let these rates down more difficult.
-	 */
-	if (MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36)
-		TryDownTh += 1;
-
-	/* 1 Adjust Rate. */
-	if (priv->bTryuping == true) {
-		/* 2 For Test Upgrading mechanism
-		 * Note:
-		 *	Sometimes the throughput is upon on the capability between the AP and NIC,
-		 *	thus the low data rate does not improve the performance.
-		 *	We randomly upgrade the data rate and check if the retry rate is improved.
-		 */
-
-		/* Upgrading rate did not improve the retry rate, fallback to the original rate. */
-		if ((CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) {
-			/*Not necessary raising rate, fall back rate. */
-			bTryDown = true;
-		} else {
-			priv->bTryuping = false;
-		}
-	} else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) {
-		/*
-		 * 2For High Power
-		 *
-		 * Return to highest data rate, if signal strength is good enough.
-		 * SignalStrength threshold(-50dbm) is for RTL8186.
-		 * Revise SignalStrength threshold to -51dbm.
-		 */
-		/* Also need to check retry rate for safety, by Bruce, 2007-06-05. */
-		if (priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate) {
-			bTryUp = true;
-			/* Upgrade Tx Rate directly. */
-			priv->TryupingCount += TryUpTh;
-		}
-
-	} else if (CurrTxokCnt > 9 && CurrTxokCnt < 100 && CurrRetryRate >= 600) {
-		/*
-		 *2 For Serious Retry
-		 *
-		 * Traffic is not busy but our Tx retry is serious.
-		 */
-		bTryDown = true;
-		/* Let Rate Mechanism to degrade tx rate directly. */
-		priv->TryDownCountLowData += TryDownTh;
-	} else if (priv->CurrentOperaRate == 108) {
-		/* 2For 54Mbps */
-		/* Air Link */
-		if ((CurrRetryRate > 26) && (priv->LastRetryRate > 25)) {
-			bTryDown = true;
-		}
-		/* Cable Link */
-		else if ((CurrRetryRate > 17) && (priv->LastRetryRate > 16) && (CurrSignalStrength > -72)) {
-			bTryDown = true;
-		}
-
-		if (bTryDown && (CurrSignalStrength < -75)) /* cable link */
-			priv->TryDownCountLowData += TryDownTh;
-	} else if (priv->CurrentOperaRate == 96) {
-		/* 2For 48Mbps */
-		/* Air Link */
-		if (((CurrRetryRate > 48) && (priv->LastRetryRate > 47))) {
-			bTryDown = true;
-		} else if (((CurrRetryRate > 21) && (priv->LastRetryRate > 20)) && (CurrSignalStrength > -74)) { /* Cable Link */
-			/* Down to rate 36Mbps. */
-			bTryDown = true;
-		} else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
-			bTryDown = true;
-			priv->TryDownCountLowData += TryDownTh;
-		} else if ((CurrRetryRate < 8) && (priv->LastRetryRate < 8)) { /* TO DO: need to consider (RSSI) */
-			bTryUp = true;
-		}
-
-		if (bTryDown && (CurrSignalStrength < -75)) {
-			priv->TryDownCountLowData += TryDownTh;
-		}
-	} else if (priv->CurrentOperaRate == 72) {
-		/* 2For 36Mbps */
-		if ((CurrRetryRate > 43) && (priv->LastRetryRate > 41)) {
-			/* Down to rate 24Mbps. */
-			bTryDown = true;
-		} else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
-			bTryDown = true;
-			priv->TryDownCountLowData += TryDownTh;
-		} else if ((CurrRetryRate < 15) &&  (priv->LastRetryRate < 16)) { /* TO DO: need to consider (RSSI) */
-			bTryUp = true;
-		}
-
-		if (bTryDown && (CurrSignalStrength < -80))
-			priv->TryDownCountLowData += TryDownTh;
-
-	} else if (priv->CurrentOperaRate == 48) {
-		/* 2For 24Mbps */
-		/* Air Link */
-		if (((CurrRetryRate > 63) && (priv->LastRetryRate > 62))) {
-			bTryDown = true;
-		} else if (((CurrRetryRate > 33) && (priv->LastRetryRate > 32)) && (CurrSignalStrength > -82)) { /* Cable Link */
-			bTryDown = true;
-		} else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
-			bTryDown = true;
-			priv->TryDownCountLowData += TryDownTh;
-		} else if ((CurrRetryRate < 20) && (priv->LastRetryRate < 21)) { /* TO DO: need to consider (RSSI) */
-			bTryUp = true;
-		}
-
-		if (bTryDown && (CurrSignalStrength < -82))
-			priv->TryDownCountLowData += TryDownTh;
-
-	} else if (priv->CurrentOperaRate == 36) {
-		if (((CurrRetryRate > 85) && (priv->LastRetryRate > 86))) {
-			bTryDown = true;
-		} else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
-			bTryDown = true;
-			priv->TryDownCountLowData += TryDownTh;
-		} else if ((CurrRetryRate < 22) && (priv->LastRetryRate < 23)) { /* TO DO: need to consider (RSSI) */
-			bTryUp = true;
-		}
-	} else if (priv->CurrentOperaRate == 22) {
-		/* 2For 11Mbps */
-		if (CurrRetryRate > 95) {
-			bTryDown = true;
-		} else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */
-			bTryUp = true;
-		}
-	} else if (priv->CurrentOperaRate == 11) {
-		/* 2For 5.5Mbps */
-		if (CurrRetryRate > 149) {
-			bTryDown = true;
-		} else if ((CurrRetryRate < 60) && (priv->LastRetryRate < 65)) {
-			bTryUp = true;
-		}
-	} else if (priv->CurrentOperaRate == 4) {
-		/* 2For 2 Mbps */
-		if ((CurrRetryRate > 99) && (priv->LastRetryRate > 99)) {
-			bTryDown = true;
-		} else if ((CurrRetryRate < 65) && (priv->LastRetryRate < 70)) {
-			bTryUp = true;
-		}
-	} else if (priv->CurrentOperaRate == 2) {
-		/* 2For 1 Mbps */
-		if ((CurrRetryRate < 70) && (priv->LastRetryRate < 75)) {
-			bTryUp = true;
-		}
-	}
-
-	if (bTryUp && bTryDown)
-		printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
-
-	/* 1 Test Upgrading Tx Rate
-	 * Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC.
-	 * To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate.
-	 */
-	if (!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0)
-		&& priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) {
-		if (jiffies % (CurrRetryRate + 101) == 0) {
-			bTryUp = true;
-			priv->bTryuping = true;
-		}
-	}
-
-	/* 1 Rate Mechanism */
-	if (bTryUp) {
-		priv->TryupingCount++;
-		priv->TryDownCountLowData = 0;
-
-		/*
-		 * Check more times if we need to upgrade indeed.
-		 * Because the largest value of pHalData->TryupingCount is 0xFFFF and
-		 * the largest value of pHalData->FailTxRateCount is 0x14,
-		 * this condition will be satisfied at most every 2 min.
-		 */
-
-		if ((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) ||
-			(CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) {
-			priv->TryupingCount = 0;
-			/*
-			 * When transferring from CCK to OFDM, DIG is an important issue.
-			 */
-			if (priv->CurrentOperaRate == 22)
-				bUpdateInitialGain = true;
-
-			/*
-			 * The difference in throughput between 48Mbps and 36Mbps is 8M.
-			 * So, we must be careful in this rate scale. Isaiah 2008-02-15.
-			 */
-			if (((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) &&
-				(priv->FailTxRateCount > 2))
-				priv->RateAdaptivePeriod = (RATE_ADAPTIVE_TIMER_PERIOD / 2);
-
-			/* (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. */
-			/* (2)If the signal strength is increased, it may be able to upgrade. */
-
-			priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
-
-			if (priv->CurrentOperaRate == 36) {
-				priv->bUpdateARFR = true;
-				write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */
-			} else if (priv->bUpdateARFR) {
-				priv->bUpdateARFR = false;
-				write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */
-			}
-
-			/* Update Fail Tx rate and count. */
-			if (priv->LastFailTxRate != priv->CurrentOperaRate) {
-				priv->LastFailTxRate = priv->CurrentOperaRate;
-				priv->FailTxRateCount = 0;
-				priv->LastFailTxRateSS = -200; /* Set lowest power. */
-			}
-		}
-	} else {
-		if (priv->TryupingCount > 0)
-			priv->TryupingCount--;
-	}
-
-	if (bTryDown) {
-		priv->TryDownCountLowData++;
-		priv->TryupingCount = 0;
-
-		/* Check if Tx rate can be degraded or Test trying upgrading should fallback. */
-		if (priv->TryDownCountLowData > TryDownTh || priv->bTryuping) {
-			priv->TryDownCountLowData = 0;
-			priv->bTryuping = false;
-			/* Update fail information. */
-			if (priv->LastFailTxRate == priv->CurrentOperaRate) {
-				priv->FailTxRateCount++;
-				/* Record the Tx fail rate signal strength. */
-				if (CurrSignalStrength > priv->LastFailTxRateSS)
-					priv->LastFailTxRateSS = CurrSignalStrength;
-			} else {
-				priv->LastFailTxRate = priv->CurrentOperaRate;
-				priv->FailTxRateCount = 1;
-				priv->LastFailTxRateSS = CurrSignalStrength;
-			}
-			priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate);
-
-			/* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */
-			if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72)) {
-				priv->CurrentOperaRate = 72;
-			}
-
-			if (priv->CurrentOperaRate == 36) {
-				priv->bUpdateARFR = true;
-				write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */
-			} else if (priv->bUpdateARFR) {
-				priv->bUpdateARFR = false;
-				write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */
-			}
-
-			/*
-			 * When it is CCK rate, it may need to update initial gain to receive lower power packets.
-			 */
-			if (MgntIsCckRate(priv->CurrentOperaRate)) {
-				bUpdateInitialGain = true;
-			}
-		}
-	} else {
-		if (priv->TryDownCountLowData > 0)
-			priv->TryDownCountLowData--;
-	}
-
-	/*
-	 * Keep the Tx fail rate count to equal to 0x15 at most.
-	 * Reduce the fail count at least to 10 sec if tx rate is tending stable.
-	 */
-	if (priv->FailTxRateCount >= 0x15 ||
-		(!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) {
-		priv->FailTxRateCount--;
-	}
-
-
-	OfdmTxPwrIdx  = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
-	CckTxPwrIdx  = priv->chtxpwr[priv->ieee80211->current_network.channel];
-
-	/* Mac0x9e increase 2 level in 36M~18M situation */
-	if ((priv->CurrentOperaRate < 96) && (priv->CurrentOperaRate > 22)) {
-		u1bCck = read_nic_byte(dev, CCK_TXAGC);
-		u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
-
-		/* case 1: Never enter High power */
-		if (u1bCck == CckTxPwrIdx) {
-			if (u1bOfdm != (OfdmTxPwrIdx + 2)) {
-			priv->bEnhanceTxPwr = true;
-			u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
-			write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
-			}
-		} else if (u1bCck < CckTxPwrIdx) {
-		/* case 2: enter high power */
-			if (!priv->bEnhanceTxPwr) {
-				priv->bEnhanceTxPwr = true;
-				u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
-				write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
-			}
-		}
-	} else if (priv->bEnhanceTxPwr) {  /* 54/48/11/5.5/2/1 */
-		u1bCck = read_nic_byte(dev, CCK_TXAGC);
-		u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
-
-		/* case 1: Never enter High power */
-		if (u1bCck == CckTxPwrIdx) {
-			priv->bEnhanceTxPwr = false;
-			write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
-		}
-		/* case 2: enter high power */
-		else if (u1bCck < CckTxPwrIdx) {
-			priv->bEnhanceTxPwr = false;
-			u1bOfdm = ((u1bOfdm - 2) > 0) ? (u1bOfdm - 2) : 0;
-			write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
-		}
-	}
-
-	/*
-	 * We need update initial gain when we set tx rate "from OFDM to CCK" or
-	 * "from CCK to OFDM".
-	 */
-SetInitialGain:
-	if (bUpdateInitialGain) {
-		if (MgntIsCckRate(priv->CurrentOperaRate)) { /* CCK */
-			if (priv->InitialGain > priv->RegBModeGainStage) {
-				priv->InitialGainBackUp = priv->InitialGain;
-
-				if (CurrSignalStrength < -85) /* Low power, OFDM [0x17] = 26. */
-					/* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */
-					priv->InitialGain = priv->RegBModeGainStage;
-
-				else if (priv->InitialGain > priv->RegBModeGainStage + 1)
-					priv->InitialGain -= 2;
-
-				else
-					priv->InitialGain--;
-
-				printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
-				UpdateInitialGain(dev);
-			}
-		} else { /* OFDM */
-			if (priv->InitialGain < 4) {
-				priv->InitialGainBackUp = priv->InitialGain;
-
-				priv->InitialGain++;
-				printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
-				UpdateInitialGain(dev);
-			}
-		}
-	}
-
-	/* Record the related info */
-	priv->LastRetryRate = CurrRetryRate;
-	priv->LastTxThroughput = TxThroughput;
-	priv->ieee80211->rate = priv->CurrentOperaRate * 5;
-}
-
-void rtl8180_rate_adapter(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, rate_adapter_wq);
-	struct net_device *dev = ieee->dev;
-	StaRateAdaptive87SE(dev);
-}
-void timer_rate_adaptive(unsigned long data)
-{
-	struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
-	if (!priv->up) {
-		return;
-	}
-	if ((priv->ieee80211->iw_mode != IW_MODE_MASTER)
-			&& (priv->ieee80211->state == IEEE80211_LINKED) &&
-			(priv->ForcedDataRate == 0)) {
-		queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq);
-	}
-	priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod);
-	add_timer(&priv->rateadapter_timer);
-}
-
-void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	priv->AdRxOkCnt++;
-
-	if (priv->AdRxSignalStrength != -1) {
-		priv->AdRxSignalStrength = ((priv->AdRxSignalStrength * 7) + (SignalStrength * 3)) / 10;
-	} else { /* Initialization case. */
-		priv->AdRxSignalStrength = SignalStrength;
-	}
-
-	if (priv->LastRxPktAntenna) /* Main antenna. */
-		priv->AdMainAntennaRxOkCnt++;
-	else	 /* Aux antenna. */
-		priv->AdAuxAntennaRxOkCnt++;
-}
- /*	Change Antenna Switch. */
-bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	bool bAntennaSwitched = false;
-
-	switch (u1bAntennaIndex) {
-	case 0:
-		/* Mac register, main antenna */
-		write_nic_byte(dev, ANTSEL, 0x03);
-		/* base band */
-		write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */
-		write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */
-
-		bAntennaSwitched = true;
-		break;
-
-	case 1:
-		/* Mac register, aux antenna */
-		write_nic_byte(dev, ANTSEL, 0x00);
-		/* base band */
-		write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */
-		write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */
-
-		bAntennaSwitched = true;
-
-		break;
-
-	default:
-		printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex);
-		break;
-	}
-
-	if (bAntennaSwitched)
-		priv->CurrAntennaIndex = u1bAntennaIndex;
-
-	return bAntennaSwitched;
-}
- /*	Toggle Antenna switch. */
-bool SwitchAntenna(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	bool		bResult;
-
-	if (priv->CurrAntennaIndex == 0) {
-		bResult = SetAntenna8185(dev, 1);
-	} else {
-		bResult = SetAntenna8185(dev, 0);
-	}
-
-	return bResult;
-}
-/*
- * Engine of SW Antenna Diversity mechanism.
- * Since 8187 has no Tx part information,
- * this implementation is only dependend on Rx part information.
- */
-void SwAntennaDiversity(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	bool   bSwCheckSS = false;
-	if (bSwCheckSS) {
-		priv->AdTickCount++;
-
-		printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n",
-			priv->AdTickCount, priv->AdCheckPeriod);
-		printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n",
-			priv->AdRxSignalStrength, priv->AdRxSsThreshold);
-	}
-
-	/* Case 1. No Link. */
-	if (priv->ieee80211->state != IEEE80211_LINKED) {
-		priv->bAdSwitchedChecking = false;
-		/* I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. */
-		SwitchAntenna(dev);
-
-	  /* Case 2. Linked but no packet receive.d */
-	} else if (priv->AdRxOkCnt == 0) {
-		priv->bAdSwitchedChecking = false;
-		SwitchAntenna(dev);
-
-	  /* Case 3. Evaluate last antenna switch action and undo it if necessary. */
-	} else if (priv->bAdSwitchedChecking == true) {
-		priv->bAdSwitchedChecking = false;
-
-		/* Adjust Rx signal strength threshold. */
-		priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2;
-
-		priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
-					priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;
-		if (priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) {
-		/* Rx signal strength is not improved after we swtiched antenna. => Swich back. */
-			/* Increase Antenna Diversity checking period due to bad decision. */
-			priv->AdCheckPeriod *= 2;
-			/* Increase Antenna Diversity checking period. */
-			if (priv->AdCheckPeriod > priv->AdMaxCheckPeriod)
-				priv->AdCheckPeriod = priv->AdMaxCheckPeriod;
-
-			/* Wrong decision => switch back. */
-			SwitchAntenna(dev);
-		} else {
-		/* Rx Signal Strength is improved. */
-
-			/* Reset Antenna Diversity checking period to its min value. */
-			priv->AdCheckPeriod = priv->AdMinCheckPeriod;
-		}
-
-	}
-	/* Case 4. Evaluate if we shall switch antenna now. */
-	/* Cause Table Speed is very fast in TRC Dell Lab, we check it every time. */
-	else {
-		priv->AdTickCount = 0;
-
-		/*
-		 * <Roger_Notes> We evaluate RxOk counts for each antenna first and than
-		 * evaluate signal strength.
-		 * The following operation can overcome the disability of CCA on both two antennas
-		 * When signal strength was extremely low or high.
-		 * 2008.01.30.
-		 */
-
-		/*
-		 * Evaluate RxOk count from each antenna if we shall switch default antenna now.
-		 */
-		if ((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt)
-			&& (priv->CurrAntennaIndex == 0)) {
-		/* We set Main antenna as default but RxOk count was less than Aux ones. */
-
-			/* Switch to Aux antenna. */
-			SwitchAntenna(dev);
-			priv->bHWAdSwitched = true;
-		} else if ((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt)
-			&& (priv->CurrAntennaIndex == 1)) {
-		/* We set Aux antenna as default but RxOk count was less than Main ones. */
-
-			/* Switch to Main antenna. */
-			SwitchAntenna(dev);
-			priv->bHWAdSwitched = true;
-		} else {
-		/* Default antenna is better. */
-
-			/* Still need to check current signal strength. */
-			priv->bHWAdSwitched = false;
-		}
-		/*
-		 * <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
-		 * didn't change by HW evaluation.
-		 * 2008.02.27.
-		 *
-		 * [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05
-		 * For example, Throughput of aux is better than main antenna(about 10M v.s 2M),
-		 * but AdRxSignalStrength is less than main.
-		 * Our guess is that main antenna have lower throughput and get many change
-		 * to receive more CCK packets(ex.Beacon) which have stronger SignalStrength.
-		 */
-		if ((!priv->bHWAdSwitched) && (bSwCheckSS)) {
-			/* Evaluate Rx signal strength if we shall switch antenna now. */
-			if (priv->AdRxSignalStrength < priv->AdRxSsThreshold) {
-			/* Rx signal strength is weak => Switch Antenna. */
-				priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength;
-				priv->bAdSwitchedChecking = true;
-
-				SwitchAntenna(dev);
-			} else {
-			/* Rx signal strength is OK. */
-				priv->bAdSwitchedChecking = false;
-				/* Increase Rx signal strength threshold if necessary. */
-				if ((priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && /* Signal is much stronger than current threshold */
-					priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) { /* Current threhold is not yet reach upper limit. */
-
-					priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2;
-					priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
-								priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;/* +by amy 080312 */
-				}
-
-				/* Reduce Antenna Diversity checking period if possible. */
-				if (priv->AdCheckPeriod > priv->AdMinCheckPeriod)
-					priv->AdCheckPeriod /= 2;
-			}
-		}
-	}
-	/* Reset antenna diversity Rx related statistics. */
-	priv->AdRxOkCnt = 0;
-	priv->AdMainAntennaRxOkCnt = 0;
-	priv->AdAuxAntennaRxOkCnt = 0;
-}
-
- /*	Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */
-bool CheckTxPwrTracking(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	if (!priv->bTxPowerTrack)
-		return false;
-
-	/* if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah */
-	if (priv->bToUpdateTxPwr)
-		return false;
-
-	return true;
-}
-
-
- /*	Timer callback function of SW Antenna Diversity. */
-void SwAntennaDiversityTimerCallback(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	enum rt_rf_power_state rtState;
-
-	 /* We do NOT need to switch antenna while RF is off. */
-	rtState = priv->eRFPowerState;
-	do {
-		if (rtState == RF_OFF) {
-			break;
-		} else if (rtState == RF_SLEEP) {
-			/* Don't access BB/RF under Disable PLL situation. */
-			break;
-		}
-		SwAntennaDiversity(dev);
-
-	} while (false);
-
-	if (priv->up) {
-		priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD);
-		add_timer(&priv->SwAntennaDiversityTimer);
-	}
-}
-
diff --git a/drivers/staging/rtl8187se/r8180_dm.h b/drivers/staging/rtl8187se/r8180_dm.h
deleted file mode 100644
index cb4046f346ef..000000000000
--- a/drivers/staging/rtl8187se/r8180_dm.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef R8180_DM_H
-#define R8180_DM_H
-
-#include "r8180.h"
-/* #include "r8180_hw.h"	*/
-/* #include "r8180_93cx6.h"	*/
-void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength);
-bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex);
-bool SwitchAntenna(struct net_device *dev);
-void SwAntennaDiversity(struct net_device *dev);
-void SwAntennaDiversityTimerCallback(struct net_device *dev);
-bool CheckDig(struct net_device *dev);
-bool CheckHighPower(struct net_device *dev);
-void rtl8180_hw_dig_wq(struct work_struct *work);
-void rtl8180_tx_pw_wq(struct work_struct *work);
-void rtl8180_rate_adapter(struct work_struct *work);
-void TxPwrTracking87SE(struct net_device *dev);
-bool CheckTxPwrTracking(struct net_device *dev);
-void rtl8180_rate_adapter(struct work_struct *work);
-void timer_rate_adaptive(unsigned long data);
-
-
-#endif
diff --git a/drivers/staging/rtl8187se/r8180_hw.h b/drivers/staging/rtl8187se/r8180_hw.h
deleted file mode 100644
index e59d74f8ecfc..000000000000
--- a/drivers/staging/rtl8187se/r8180_hw.h
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
-	This is part of rtl8180 OpenSource driver.
-	Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
-	Released under the terms of GPL (General Public Licence)
-
-	Parts of this driver are based on the GPL part of the
-	official Realtek driver.
-	Parts of this driver are based on the rtl8180 driver skeleton
-	from Patric Schenke & Andres Salomon.
-	Parts of this driver are based on the Intel Pro Wireless
-	2100 GPL driver.
-
-	We want to tanks the Authors of those projects
-	and the Ndiswrapper project Authors.
-*/
-
-/* Mariusz Matuszek added full registers definition with Realtek's name */
-
-/* this file contains register definitions for the rtl8180 MAC controller */
-#ifndef R8180_HW
-#define R8180_HW
-
-
-#define BIT0	0x00000001
-#define BIT1	0x00000002
-#define BIT2	0x00000004
-#define BIT3	0x00000008
-#define BIT4	0x00000010
-#define BIT5	0x00000020
-#define BIT6	0x00000040
-#define BIT7	0x00000080
-#define BIT9	0x00000200
-#define BIT11	0x00000800
-#define BIT13	0x00002000
-#define BIT15	0x00008000
-#define BIT20	0x00100000
-#define BIT21	0x00200000
-#define BIT22	0x00400000
-#define BIT23	0x00800000
-#define BIT24	0x01000000
-#define BIT25	0x02000000
-#define BIT26	0x04000000
-#define BIT27	0x08000000
-#define BIT28	0x10000000
-#define BIT29	0x20000000
-#define BIT30	0x40000000
-#define BIT31	0x80000000
-
-#define MAX_SLEEP_TIME (10000)
-#define MIN_SLEEP_TIME (50)
-
-#define BB_HOST_BANG_EN (1<<2)
-#define BB_HOST_BANG_CLK (1<<1)
-
-#define MAC0 0
-#define MAC4 4
-
-#define CMD 0x37
-#define CMD_RST_SHIFT 4
-#define CMD_RX_ENABLE_SHIFT 3
-#define CMD_TX_ENABLE_SHIFT 2
-
-#define EPROM_CMD 0x50
-#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4))
-#define EPROM_CMD_OPERATING_MODE_SHIFT 6
-#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
-#define EPROM_CMD_CONFIG 0x3
-#define EPROM_CMD_NORMAL 0
-#define EPROM_CMD_LOAD 1
-#define EPROM_CMD_PROGRAM 2
-#define EPROM_CS_SHIFT 3
-#define EPROM_CK_SHIFT 2
-#define EPROM_W_SHIFT 1
-#define EPROM_R_SHIFT 0
-#define CONFIG2_DMA_POLLING_MODE_SHIFT 3
-
-#define INTA_TXOVERFLOW (1<<15)
-#define INTA_TIMEOUT (1<<14)
-#define INTA_HIPRIORITYDESCERR (1<<9)
-#define INTA_HIPRIORITYDESCOK (1<<8)
-#define INTA_NORMPRIORITYDESCERR (1<<7)
-#define INTA_NORMPRIORITYDESCOK (1<<6)
-#define INTA_RXOVERFLOW (1<<5)
-#define INTA_RXDESCERR (1<<4)
-#define INTA_LOWPRIORITYDESCERR (1<<3)
-#define INTA_LOWPRIORITYDESCOK (1<<2)
-#define INTA_RXOK (1)
-#define INTA_MASK 0x3c
-
-#define RXRING_ADDR 0xe4 /* page 0 */
-#define PGSELECT 0x5e
-#define PGSELECT_PG_SHIFT 0
-#define RX_CONF 0x44
-#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
-(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
-#define RX_CHECK_BSSID_SHIFT 23
-#define ACCEPT_PWR_FRAME_SHIFT 22
-#define ACCEPT_MNG_FRAME_SHIFT 20
-#define ACCEPT_CTL_FRAME_SHIFT 19
-#define ACCEPT_DATA_FRAME_SHIFT 18
-#define ACCEPT_ICVERR_FRAME_SHIFT 12
-#define ACCEPT_CRCERR_FRAME_SHIFT 5
-#define ACCEPT_BCAST_FRAME_SHIFT 3
-#define ACCEPT_MCAST_FRAME_SHIFT 2
-#define ACCEPT_ALLMAC_FRAME_SHIFT 0
-#define ACCEPT_NICMAC_FRAME_SHIFT 1
-
-#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
-#define RX_FIFO_THRESHOLD_SHIFT 13
-#define RX_FIFO_THRESHOLD_NONE 7
-#define RX_AUTORESETPHY_SHIFT 28
-
-#define TX_CONF 0x40
-#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30
-#define TX_LOOPBACK_SHIFT 17
-#define TX_LOOPBACK_NONE 0
-#define TX_LOOPBACK_CONTINUE 3
-#define TX_LOOPBACK_MASK ((1<<17)|(1<<18))
-#define TX_DPRETRY_SHIFT 0
-#define R8180_MAX_RETRY 255
-#define TX_RTSRETRY_SHIFT 8
-#define TX_NOICV_SHIFT 19
-#define TX_NOCRC_SHIFT 16
-#define TX_DMA_POLLING 0xd9
-#define TX_DMA_POLLING_BEACON_SHIFT 7
-#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6
-#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5
-#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4
-#define TX_MANAGEPRIORITY_RING_ADDR 0x0C
-#define TX_BKPRIORITY_RING_ADDR 0x10
-#define TX_BEPRIORITY_RING_ADDR 0x14
-#define TX_VIPRIORITY_RING_ADDR 0x20
-#define TX_VOPRIORITY_RING_ADDR 0x24
-#define TX_HIGHPRIORITY_RING_ADDR 0x28
-#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
-#define MAX_RX_DMA_2048 7
-#define MAX_RX_DMA_1024	6
-#define MAX_RX_DMA_SHIFT 10
-#define INT_TIMEOUT 0x48
-#define CONFIG3_CLKRUN_SHIFT 2
-#define CONFIG3_ANAPARAM_W_SHIFT 6
-#define ANAPARAM 0x54
-#define BEACON_INTERVAL 0x70
-#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \
-(1<<6)|(1<<7)|(1<<8)|(1<<9))
-#define ATIM_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)| \
-(1<<8)|(1<<9))
-#define ATIM 0x72
-#define EPROM_CS_SHIFT 3
-#define EPROM_CK_SHIFT 2
-#define PHY_ADR 0x7c
-#define SECURITY 0x5f /* 1209 this is sth wrong */
-#define SECURITY_WEP_TX_ENABLE_SHIFT 1
-#define SECURITY_WEP_RX_ENABLE_SHIFT 0
-#define SECURITY_ENCRYP_104 1
-#define SECURITY_ENCRYP_SHIFT 4
-#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5))
-#define KEY0 0x90  /* 1209 this is sth wrong */
-#define CONFIG2_ANTENNA_SHIFT 6
-#define TX_BEACON_RING_ADDR 0x4c
-#define CONFIG0_WEP40_SHIFT 7
-#define CONFIG0_WEP104_SHIFT 6
-#define AGCRESET_SHIFT 5
-
-
-
-/*
- * Operational registers offsets in PCI (I/O) space.
- * RealTek names are used.
- */
-
-#define TSFTR 0x0018
-
-#define TLPDA 0x0020
-
-#define BSSID 0x002E
-
-#define CR 0x0037
-
-#define RF_SW_CONFIG	        0x8			/* store data which is transmitted to RF for driver	*/
-#define RF_SW_CFG_SI		BIT1
-#define EIFS			0x2D			/* Extended InterFrame Space Timer, in unit of 4 us.	*/
-
-#define BRSR			0x34			/* Basic rate set										*/
-
-#define IMR 0x006C
-#define ISR 0x003C
-
-#define TCR 0x0040
-
-#define RCR 0x0044
-
-#define TimerInt 0x0048
-
-#define CR9346 0x0050
-
-#define CONFIG0 0x0051
-#define CONFIG2 0x0053
-
-#define MSR 0x0058
-
-#define CONFIG3 0x0059
-#define CONFIG4 0x005A
-	/* SD3 szuyitasi: Mac0x57= CC -> B0 Mac0x60= D1 -> C6	*/
-	/* Mac0x60 = 0x000004C6 power save parameters			*/
-	#define ANAPARM_ASIC_ON    0xB0054D00
-	#define ANAPARM2_ASIC_ON  0x000004C6
-
-	#define ANAPARM_ON ANAPARM_ASIC_ON
-	#define ANAPARM2_ON ANAPARM2_ASIC_ON
-
-#define TESTR 0x005B
-
-#define PSR 0x005E
-
-#define BcnItv 0x0070
-
-#define AtimWnd 0x0072
-
-#define BintrItv 0x0074
-
-#define PhyAddr 0x007C
-#define PhyDataR 0x007E
-
-/* following are for rtl8185 */
-#define RFPinsOutput 0x80
-#define RFPinsEnable 0x82
-#define RF_TIMING 0x8c
-#define RFPinsSelect 0x84
-#define ANAPARAM2 0x60
-#define RF_PARA 0x88
-#define RFPinsInput 0x86
-#define GP_ENABLE 0x90
-#define GPIO 0x91
-#define SW_CONTROL_GPIO 0x400
-#define TX_ANTENNA 0x9f
-#define TX_GAIN_OFDM 0x9e
-#define TX_GAIN_CCK 0x9d
-#define WPA_CONFIG 0xb0
-#define TX_AGC_CTL 0x9c
-#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0
-#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1
-#define TX_AGC_CTL_FEEDBACK_ANT 2
-#define RESP_RATE 0x34
-#define SIFS 0xb4
-#define DIFS 0xb5
-
-#define SLOT 0xb6
-#define CW_CONF 0xbc
-#define CW_CONF_PERPACKET_RETRY_SHIFT 1
-#define CW_CONF_PERPACKET_CW_SHIFT 0
-#define CW_VAL 0xbd
-#define MAX_RESP_RATE_SHIFT 4
-#define MIN_RESP_RATE_SHIFT 0
-#define RATE_FALLBACK 0xbe
-
-#define CONFIG5 0x00D8
-
-#define PHYPR			0xDA			/* 0xDA - 0x0B PHY Parameter Register.	*/
-
-#define FEMR			0x1D4	/* Function Event Mask register	*/
-
-#define FFER 0x00FC
-#define FFER_END 0x00FF
-
-
-
-/*
- * Bitmasks for specific register functions.
- * Names are derived from the register name and function name.
- *
- * <REGISTER>_<FUNCTION>[<bit>]
- *
- * this leads to some awkward names...
- */
-
-#define BRSR_BPLCP  ((1 << 8))
-#define BRSR_MBR    ((1 << 1)|(1 << 0))
-#define BRSR_MBR_8185 ((1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0))
-#define BRSR_MBR0   ((1 << 0))
-#define BRSR_MBR1   ((1 << 1))
-
-#define CR_RST      ((1 << 4))
-#define CR_RE       ((1 << 3))
-#define CR_TE       ((1 << 2))
-#define CR_MulRW    ((1 << 0))
-
-#define IMR_Dot11hInt	((1 << 25))			/*802.11h Measurement Interrupt					*/
-#define IMR_BcnDmaInt	((1 << 24))			/*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt???	*/
-#define IMR_WakeInt		((1 << 23))			/*Wake Up Interrupt								*/
-#define IMR_TXFOVW		((1 << 22))			/*Tx FIFO Overflow Interrupt					*/
-#define IMR_TimeOut1	((1 << 21))			/*Time Out Interrupt 1							*/
-#define IMR_BcnInt		((1 << 20))			/*Beacon Time out Interrupt						*/
-#define IMR_ATIMInt		((1 << 19))			/*ATIM Time Out Interrupt						*/
-#define IMR_TBDER		((1 << 18))			/*Tx Beacon Descriptor Error Interrupt			*/
-#define IMR_TBDOK		((1 << 17))			/*Tx Beacon Descriptor OK Interrupt				*/
-#define IMR_THPDER		((1 << 16))			/*Tx High Priority Descriptor Error Interrupt	*/
-#define IMR_THPDOK		((1 << 15))			/*Tx High Priority Descriptor OK Interrupt		*/
-#define IMR_TVODER		((1 << 14))			/*Tx AC_VO Descriptor Error Interrupt			*/
-#define IMR_TVODOK		((1 << 13))			/*Tx AC_VO Descriptor OK Interrupt				*/
-#define IMR_FOVW		((1 << 12))			/*Rx FIFO Overflow Interrupt					*/
-#define IMR_RDU			((1 << 11))			/*Rx Descriptor Unavailable Interrupt			*/
-#define IMR_TVIDER		((1 << 10))			/*Tx AC_VI Descriptor Error Interrupt			*/
-#define IMR_TVIDOK		((1 << 9))			/*Tx AC_VI Descriptor OK Interrupt				*/
-#define IMR_RER			((1 << 8))			/*Rx Error Interrupt							*/
-#define IMR_ROK			((1 << 7))			/*Receive OK Interrupt							*/
-#define IMR_TBEDER		((1 << 6))			/*Tx AC_BE Descriptor Error Interrupt			*/
-#define IMR_TBEDOK		((1 << 5))			/*Tx AC_BE Descriptor OK Interrupt				*/
-#define IMR_TBKDER		((1 << 4))			/*Tx AC_BK Descriptor Error Interrupt			*/
-#define IMR_TBKDOK		((1 << 3))			/*Tx AC_BK Descriptor OK Interrupt				*/
-#define IMR_RQoSOK		((1 << 2))			/*Rx QoS OK Interrupt							*/
-#define IMR_TimeOut2	((1 << 1))			/*Time Out Interrupt 2							*/
-#define IMR_TimeOut3	((1 << 0))			/*Time Out Interrupt 3							*/
-#define IMR_TMGDOK      ((1 << 30))
-#define ISR_Dot11hInt	((1 << 25))			/*802.11h Measurement Interrupt					*/
-#define ISR_BcnDmaInt	((1 << 24))			/*Beacon DMA Interrupt	*/ /*What differenct between BcnDmaInt and BcnInt???	*/
-#define ISR_WakeInt		((1 << 23))			/*Wake Up Interrupt								*/
-#define ISR_TXFOVW		((1 << 22))			/*Tx FIFO Overflow Interrupt					*/
-#define ISR_TimeOut1	((1 << 21))			/*Time Out Interrupt 1							*/
-#define ISR_BcnInt		((1 << 20))			/*Beacon Time out Interrupt						*/
-#define ISR_ATIMInt		((1 << 19))			/*ATIM Time Out Interrupt						*/
-#define ISR_TBDER		((1 << 18))			/*Tx Beacon Descriptor Error Interrupt			*/
-#define ISR_TBDOK		((1 << 17))			/*Tx Beacon Descriptor OK Interrupt				*/
-#define ISR_THPDER		((1 << 16))			/*Tx High Priority Descriptor Error Interrupt	*/
-#define ISR_THPDOK		((1 << 15))			/*Tx High Priority Descriptor OK Interrupt		*/
-#define ISR_TVODER		((1 << 14))			/*Tx AC_VO Descriptor Error Interrupt			*/
-#define ISR_TVODOK		((1 << 13))			/*Tx AC_VO Descriptor OK Interrupt				*/
-#define ISR_FOVW		((1 << 12))			/*Rx FIFO Overflow Interrupt					*/
-#define ISR_RDU			((1 << 11))			/*Rx Descriptor Unavailable Interrupt			*/
-#define ISR_TVIDER		((1 << 10))			/*Tx AC_VI Descriptor Error Interrupt			*/
-#define ISR_TVIDOK		((1 << 9))			/*Tx AC_VI Descriptor OK Interrupt				*/
-#define ISR_RER			((1 << 8))			/*Rx Error Interrupt							*/
-#define ISR_ROK			((1 << 7))			/*Receive OK Interrupt							*/
-#define ISR_TBEDER		((1 << 6))			/*Tx AC_BE Descriptor Error Interrupt			*/
-#define ISR_TBEDOK		((1 << 5))			/*Tx AC_BE Descriptor OK Interrupt				*/
-#define ISR_TBKDER		((1 << 4))			/*Tx AC_BK Descriptor Error Interrupt			*/
-#define ISR_TBKDOK		((1 << 3))			/*Tx AC_BK Descriptor OK Interrupt				*/
-#define ISR_RQoSOK		((1 << 2))			/*Rx QoS OK Interrupt							*/
-#define ISR_TimeOut2	((1 << 1))			/*Time Out Interrupt 2							*/
-#define ISR_TimeOut3	((1 << 0))			/*Time Out Interrupt 3							*/
-
-/* these definition is used for Tx/Rx test temporarily */
-#define ISR_TLPDER  ISR_TVIDER
-#define ISR_TLPDOK  ISR_TVIDOK
-#define ISR_TNPDER  ISR_TVODER
-#define ISR_TNPDOK  ISR_TVODOK
-#define ISR_TimeOut ISR_TimeOut1
-#define ISR_RXFOVW ISR_FOVW
-
-
-#define HW_VERID_R8180_F 3
-#define HW_VERID_R8180_ABCD 2
-#define HW_VERID_R8185_ABC 4
-#define HW_VERID_R8185_D 5
-#define HW_VERID_R8185B_B 6
-
-#define TCR_CWMIN   ((1 << 31))
-#define TCR_SWSEQ   ((1 << 30))
-#define TCR_HWVERID_MASK ((1 << 27)|(1 << 26)|(1 << 25))
-#define TCR_HWVERID_SHIFT 25
-#define TCR_SAT     ((1 << 24))
-#define TCR_PLCP_LEN TCR_SAT /* rtl8180 */
-#define TCR_MXDMA_MASK   ((1 << 23)|(1 << 22)|(1 << 21))
-#define TCR_MXDMA_1024 6
-#define TCR_MXDMA_2048 7
-#define TCR_MXDMA_SHIFT  21
-#define TCR_DISCW   ((1 << 20))
-#define TCR_ICV     ((1 << 19))
-#define TCR_LBK     ((1 << 18)|(1 << 17))
-#define TCR_LBK1    ((1 << 18))
-#define TCR_LBK0    ((1 << 17))
-#define TCR_CRC     ((1 << 16))
-#define TCR_DPRETRY_MASK   ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8))
-#define TCR_RTSRETRY_MASK   ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7))
-#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 /* rtl8185 */
-
-#define RCR_ONLYERLPKT ((1 << 31))
-#define RCR_CS_SHIFT   29
-#define RCR_CS_MASK    ((1 << 30) | (1 << 29))
-#define RCR_ENMARP     ((1 << 28))
-#define RCR_CBSSID     ((1 << 23))
-#define RCR_APWRMGT    ((1 << 22))
-#define RCR_ADD3       ((1 << 21))
-#define RCR_AMF        ((1 << 20))
-#define RCR_ACF        ((1 << 19))
-#define RCR_ADF        ((1 << 18))
-#define RCR_RXFTH      ((1 << 15)|(1 << 14)|(1 << 13))
-#define RCR_RXFTH2     ((1 << 15))
-#define RCR_RXFTH1     ((1 << 14))
-#define RCR_RXFTH0     ((1 << 13))
-#define RCR_AICV       ((1 << 12))
-#define RCR_MXDMA      ((1 << 10)|(1 << 9)|(1 << 8))
-#define RCR_MXDMA2     ((1 << 10))
-#define RCR_MXDMA1     ((1 << 9))
-#define RCR_MXDMA0     ((1 << 8))
-#define RCR_9356SEL    ((1 << 6))
-#define RCR_ACRC32     ((1 << 5))
-#define RCR_AB         ((1 << 3))
-#define RCR_AM         ((1 << 2))
-#define RCR_APM        ((1 << 1))
-#define RCR_AAP        ((1 << 0))
-
-#define CR9346_EEM     ((1 << 7)|(1 << 6))
-#define CR9346_EEM1    ((1 << 7))
-#define CR9346_EEM0    ((1 << 6))
-#define CR9346_EECS    ((1 << 3))
-#define CR9346_EESK    ((1 << 2))
-#define CR9346_EED1    ((1 << 1))
-#define CR9346_EED0    ((1 << 0))
-
-#define CONFIG3_PARM_En    ((1 << 6))
-#define CONFIG3_FuncRegEn  ((1 << 1))
-
-#define CONFIG4_PWRMGT     ((1 << 5))
-
-#define MSR_LINK_MASK      ((1 << 2)|(1 << 3))
-#define MSR_LINK_MANAGED   2
-#define MSR_LINK_NONE      0
-#define MSR_LINK_SHIFT     2
-#define MSR_LINK_ADHOC     1
-#define MSR_LINK_MASTER    3
-
-#define BcnItv_BcnItv      (0x01FF)
-
-#define AtimWnd_AtimWnd    (0x01FF)
-
-#define BintrItv_BintrItv  (0x01FF)
-
-#define FEMR_INTR    ((1 << 15))
-#define FEMR_WKUP    ((1 << 14))
-#define FEMR_GWAKE   ((1 << 4))
-
-#define FFER_INTR    ((1 << 15))
-#define FFER_GWAKE   ((1 << 4))
-
-/* Three wire mode.					*/
-#define SW_THREE_WIRE			0
-#define HW_THREE_WIRE			2
-/* RTL8187S by amy					*/
-#define HW_THREE_WIRE_PI		5
-#define HW_THREE_WIRE_SI		6
-/* by amy							*/
-#define TCR_LRL_OFFSET		0
-#define TCR_SRL_OFFSET		8
-#define TCR_MXDMA_OFFSET	21
-#define TCR_DISReqQsize_OFFSET		28
-#define TCR_DurProcMode_OFFSET		30
-
-#define RCR_MXDMA_OFFSET				8
-#define RCR_FIFO_OFFSET					13
-
-#define AckTimeOutReg	0x79		/* ACK timeout register, in unit of 4 us. */
-
-#define RFTiming			0x8C
-
-#define TPPollStop		0x93
-
-#define TXAGC_CTL		0x9C			/*< RJ_TODO_8185B> TX_AGC_CONTROL (0x9C seems be removed at 8185B, see p37). */
-#define CCK_TXAGC		0x9D
-#define OFDM_TXAGC		0x9E
-#define ANTSEL			0x9F
-
-#define ACM_CONTROL             0x00BF      /* ACM Control Registe */
-
-#define	IntMig			0xE2			/* Interrupt Migration (0xE2 ~ 0xE3)	*/
-
-#define TID_AC_MAP		0xE8			/* TID to AC Mapping Register			*/
-
-#define ANAPARAM3		0xEE			/* <RJ_TODO_8185B> How to use it?		*/
-
-#define AC_VO_PARAM		0xF0			/* AC_VO Parameters Record				*/
-#define AC_VI_PARAM		0xF4			/* AC_VI Parameters Record				*/
-#define AC_BE_PARAM		0xF8			/* AC_BE Parameters Record				*/
-#define AC_BK_PARAM		0xFC			/* AC_BK Parameters Record				*/
-
-#define GPIOCtrl			0x16B			/*GPIO Control Register.			*/
-#define ARFR			0x1E0	/* Auto Rate Fallback Register (0x1e0 ~ 0x1e2)	*/
-
-#define RFSW_CTRL			0x272	/* 0x272-0x273.								*/
-#define SW_3W_DB0			0x274	/* Software 3-wire data buffer bit 31~0.		*/
-#define SW_3W_DB1			0x278	/* Software 3-wire data buffer bit 63~32.	*/
-#define SW_3W_CMD0			0x27C	/* Software 3-wire Control/Status Register.	*/
-#define SW_3W_CMD1			0x27D	/* Software 3-wire Control/Status Register.	*/
-
-#define PI_DATA_READ		0X360	/* 0x360 - 0x361  Parallel Interface Data Register.	*/
-#define SI_DATA_READ		0x362	/* 0x362 - 0x363  Serial Interface Data Register.	*/
-
-/*
-----------------------------------------------------------------------------
-		8185B TPPollStop bits					(offset 0x93, 1 byte)
-----------------------------------------------------------------------------
-*/
-#define TPPOLLSTOP_BQ			(0x01 << 7)
-#define TPPOLLSTOP_AC_VIQ		(0x01 << 4)
-
-#define MSR_LINK_ENEDCA	   (1<<4)
-
-/*
-----------------------------------------------------------------------------
-		8187B AC_XX_PARAM bits
-----------------------------------------------------------------------------
-*/
-#define AC_PARAM_TXOP_LIMIT_OFFSET		16
-#define AC_PARAM_ECW_MAX_OFFSET			12
-#define AC_PARAM_ECW_MIN_OFFSET			8
-#define AC_PARAM_AIFS_OFFSET			0
-
-/*
-----------------------------------------------------------------------------
-		8187B ACM_CONTROL bits					(Offset 0xBF, 1 Byte)
-----------------------------------------------------------------------------
-*/
-#define VOQ_ACM_EN				(0x01 << 7)	/*BIT7	*/
-#define VIQ_ACM_EN				(0x01 << 6)	/*BIT6	*/
-#define BEQ_ACM_EN				(0x01 << 5)	/*BIT5	*/
-#define ACM_HW_EN				(0x01 << 4)	/*BIT4	*/
-#define VOQ_ACM_CTL				(0x01 << 2)	/*BIT2	*/	/* Set to 1 when AC_VO used time reaches or exceeds the admitted time	*/
-#define VIQ_ACM_CTL				(0x01 << 1)	/*BIT1	*/	/* Set to 1 when AC_VI used time reaches or exceeds the admitted time	*/
-#define BEQ_ACM_CTL				(0x01 << 0)	/*BIT0	*/	/* Set to 1 when AC_BE used time reaches or exceeds the admitted time	*/
-
-
-/*
-----------------------------------------------------------------------------
-		8185B SW_3W_CMD bits					(Offset 0x27C-0x27D, 16bit)
-----------------------------------------------------------------------------
-*/
-#define SW_3W_CMD0_HOLD		((1 << 7))
-#define SW_3W_CMD1_RE		((1 << 0)) /* BIT8		*/
-#define SW_3W_CMD1_WE		((1 << 1)) /* BIT9		*/
-#define SW_3W_CMD1_DONE		((1 << 2)) /* BIT10		*/
-
-#define BB_HOST_BANG_RW		(1 << 3)
-
-/*
-----------------------------------------------------------------------------
-		8185B RATE_FALLBACK_CTL bits			(Offset 0xBE, 8bit)
-----------------------------------------------------------------------------
-*/
-#define RATE_FALLBACK_CTL_ENABLE				((1 << 7))
-#define RATE_FALLBACK_CTL_ENABLE_RTSCTS		((1 << 6))
-/* Auto rate fallback per 2^n retry. */
-#define RATE_FALLBACK_CTL_AUTO_STEP0	0x00
-#define RATE_FALLBACK_CTL_AUTO_STEP1	0x01
-#define RATE_FALLBACK_CTL_AUTO_STEP2	0x02
-#define RATE_FALLBACK_CTL_AUTO_STEP3	0x03
-
-
-#define RTL8225z2_ANAPARAM_OFF	0x55480658
-#define RTL8225z2_ANAPARAM2_OFF	0x72003f70
-/* by amy for power save		*/
-#define RF_CHANGE_BY_HW BIT30
-#define RF_CHANGE_BY_PS BIT29
-#define RF_CHANGE_BY_IPS BIT28
-/* by amy for power save		*/
-/* by amy for antenna			*/
-#define EEPROM_SW_REVD_OFFSET 0x3f
-
-/*  BIT[8-9] is for SW Antenna Diversity.
- *  Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable.
- */
-#define EEPROM_SW_AD_MASK			0x0300
-#define EEPROM_SW_AD_ENABLE			0x0100
-
-/* BIT[10-11] determine if Antenna 1 is the Default Antenna.
- * Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE.
- */
-#define EEPROM_DEF_ANT_MASK			0x0C00
-#define EEPROM_DEF_ANT_1			0x0400
-/*by amy for antenna																				*/
-/* {by amy 080312																					*/
-/* 0x7C, 0x7D Crystal calibration and Tx Power tracking mechanism. Added by Roger. 2007.12.10.		*/
-#define EEPROM_RSV						0x7C
-#define EEPROM_XTAL_CAL_XOUT_MASK	0x0F	/* 0x7C[3:0], Crystal calibration for Xout.				*/
-#define EEPROM_XTAL_CAL_XIN_MASK		0xF0	/* 0x7C[7:4], Crystal calibration for Xin.			*/
-#define EEPROM_THERMAL_METER_MASK	0x0F00	/* 0x7D[3:0], Thermal meter reference level.			*/
-#define EEPROM_XTAL_CAL_ENABLE		0x1000	/* 0x7D[4], Crystal calibration enabled/disabled BIT.	*/
-#define EEPROM_THERMAL_METER_ENABLE	0x2000	/* 0x7D[5], Thermal meter enabled/disabled BIT.			*/
-#define EN_LPF_CAL			0x238	/* Enable LPF Calibration.										*/
-#define PWR_METER_EN		BIT1
-/* <RJ_TODO_8185B> where are false alarm counters in 8185B? */
-#define CCK_FALSE_ALARM		0xD0
-/* by amy 080312} */
-
-/* YJ,add for Country IE, 080630 */
-#define EEPROM_COUNTRY_CODE  0x2E
-/* YJ,add,080630,end */
-
-#endif
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225.h b/drivers/staging/rtl8187se/r8180_rtl8225.h
deleted file mode 100644
index 7df73927b3cc..000000000000
--- a/drivers/staging/rtl8187se/r8180_rtl8225.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This is part of the rtl8180-sa2400 driver released under the GPL (See file
- * COPYING for details).
- *
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * This files contains programming code for the rtl8225 radio frontend.
- *
- * *Many* thanks to Realtek Corp. for their great support!
- */
-
-#include "r8180.h"
-
-#define RTL8225_ANAPARAM_ON  0xa0000b59
-#define RTL8225_ANAPARAM_OFF 0xa00beb59
-#define RTL8225_ANAPARAM2_OFF 0x840dec11
-#define RTL8225_ANAPARAM2_ON  0x860dec11
-#define RTL8225_ANAPARAM_SLEEP 0xa00bab59
-#define RTL8225_ANAPARAM2_SLEEP 0x840dec11
-
-void rtl8225z2_rf_init(struct net_device *dev);
-void rtl8225z2_rf_set_chan(struct net_device *dev, short ch);
-void rtl8225z2_rf_close(struct net_device *dev);
-
-void RF_WriteReg(struct net_device *dev, u8 offset, u16 data);
-u16 RF_ReadReg(struct net_device *dev, u8 offset);
-
-void rtl8180_set_mode(struct net_device *dev, int mode);
-void rtl8180_set_mode(struct net_device *dev, int mode);
-bool SetZebraRFPowerState8185(struct net_device *dev,
-			      enum rt_rf_power_state eRFPowerState);
-void rtl8225z4_rf_sleep(struct net_device *dev);
-void rtl8225z4_rf_wakeup(struct net_device *dev);
-
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
deleted file mode 100644
index 47104fa05c55..000000000000
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/*
- * This is part of the rtl8180-sa2400 driver
- * released under the GPL (See file COPYING for details).
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * This files contains programming code for the rtl8225
- * radio frontend.
- *
- * *Many* thanks to Realtek Corp. for their great support!
- */
-
-#include "r8180_hw.h"
-#include "r8180_rtl8225.h"
-#include "r8180_93cx6.h"
-
-#include "ieee80211/dot11d.h"
-
-static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
-{
-	int i;
-	u16 out, select;
-	u8 bit;
-	u32 bangdata = (data << 4) | (adr & 0xf);
-
-	out = read_nic_word(dev, RFPinsOutput) & 0xfff3;
-
-	write_nic_word(dev, RFPinsEnable,
-		(read_nic_word(dev, RFPinsEnable) | 0x7));
-
-	select = read_nic_word(dev, RFPinsSelect);
-
-	write_nic_word(dev, RFPinsSelect, select | 0x7 |
-		       SW_CONTROL_GPIO);
-
-	force_pci_posting(dev);
-	udelay(10);
-
-	write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
-
-	force_pci_posting(dev);
-	udelay(2);
-
-	write_nic_word(dev, RFPinsOutput, out);
-
-	force_pci_posting(dev);
-	udelay(10);
-
-	for (i = 15; i >= 0; i--) {
-		bit = (bangdata & (1 << i)) >> i;
-
-		write_nic_word(dev, RFPinsOutput, bit | out);
-
-		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
-		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
-
-		i--;
-		bit = (bangdata & (1 << i)) >> i;
-
-		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
-		write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
-
-		write_nic_word(dev, RFPinsOutput, bit | out);
-
-	}
-
-	write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
-
-	force_pci_posting(dev);
-	udelay(10);
-
-	write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
-
-	write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO);
-
-	rtl8185_rf_pins_enable(dev);
-}
-
-static const u8 rtl8225_agc[] = {
-	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
-	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
-	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
-	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
-	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
-	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
-	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
-	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
-	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
-	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
-	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
-	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
-	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-};
-
-static const u32 rtl8225_chan[] = {
-	0,
-	0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
-	0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
-};
-
-static const u8 rtl8225z2_gain_bg[] = {
-	0x23, 0x15, 0xa5, /* -82-1dBm */
-	0x23, 0x15, 0xb5, /* -82-2dBm */
-	0x23, 0x15, 0xc5, /* -82-3dBm */
-	0x33, 0x15, 0xc5, /* -78dBm */
-	0x43, 0x15, 0xc5, /* -74dBm */
-	0x53, 0x15, 0xc5, /* -70dBm */
-	0x63, 0x15, 0xc5, /* -66dBm */
-};
-
-static const u8 rtl8225z2_gain_a[] = {
-	0x13, 0x27, 0x5a, /* -82dBm */
-	0x23, 0x23, 0x58, /* -82dBm */
-	0x33, 0x1f, 0x56, /* -82dBm */
-	0x43, 0x1b, 0x54, /* -78dBm */
-	0x53, 0x17, 0x51, /* -74dBm */
-	0x63, 0x24, 0x4f, /* -70dBm */
-	0x73, 0x0f, 0x4c, /* -66dBm */
-};
-
-static const u16 rtl8225z2_rxgain[] = {
-	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
-	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
-	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
-	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
-	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
-	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
-	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
-	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
-	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
-	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
-	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
-	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb
-
-};
-
-static void rtl8225z2_set_gain(struct net_device *dev, short gain)
-{
-	const u8 *rtl8225_gain;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8 mode = priv->ieee80211->mode;
-
-	if (mode == IEEE_B || mode == IEEE_G)
-		rtl8225_gain = rtl8225z2_gain_bg;
-	else
-		rtl8225_gain = rtl8225z2_gain_a;
-
-	write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]);
-	write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]);
-	write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]);
-	write_phy_ofdm(dev, 0x21, 0x37);
-}
-
-static u32 read_rtl8225(struct net_device *dev, u8 adr)
-{
-	u32 data2Write = ((u32)(adr & 0x1f)) << 27;
-	u32 dataRead;
-	u32 mask;
-	u16 oval, oval2, oval3, tmp;
-	int i;
-	short bit, rw;
-	u8 wLength = 6;
-	u8 rLength = 12;
-	u8 low2high = 0;
-
-	oval = read_nic_word(dev, RFPinsOutput);
-	oval2 = read_nic_word(dev, RFPinsEnable);
-	oval3 = read_nic_word(dev, RFPinsSelect);
-
-	write_nic_word(dev, RFPinsEnable, (oval2|0xf));
-	write_nic_word(dev, RFPinsSelect, (oval3|0xf));
-
-	dataRead = 0;
-
-	oval &= ~0xf;
-
-	write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN);
-	udelay(4);
-
-	write_nic_word(dev, RFPinsOutput, oval);
-	udelay(5);
-
-	rw = 0;
-
-	mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1));
-
-	for (i = 0; i < wLength/2; i++) {
-		bit = ((data2Write&mask) != 0) ? 1 : 0;
-		write_nic_word(dev, RFPinsOutput, bit | oval | rw);
-		udelay(1);
-
-		write_nic_word(dev, RFPinsOutput,
-				bit | oval | BB_HOST_BANG_CLK | rw);
-		udelay(2);
-		write_nic_word(dev, RFPinsOutput,
-				bit | oval | BB_HOST_BANG_CLK | rw);
-		udelay(2);
-
-		mask = (low2high) ? (mask<<1) : (mask>>1);
-
-		if (i == 2) {
-			rw = BB_HOST_BANG_RW;
-			write_nic_word(dev, RFPinsOutput,
-					bit | oval | BB_HOST_BANG_CLK | rw);
-			udelay(2);
-			write_nic_word(dev, RFPinsOutput, bit | oval | rw);
-			udelay(2);
-			break;
-		}
-
-		bit = ((data2Write&mask) != 0) ? 1 : 0;
-
-		write_nic_word(dev, RFPinsOutput,
-				oval | bit | rw | BB_HOST_BANG_CLK);
-		udelay(2);
-		write_nic_word(dev, RFPinsOutput,
-				oval | bit | rw | BB_HOST_BANG_CLK);
-		udelay(2);
-
-		write_nic_word(dev, RFPinsOutput, oval | bit | rw);
-		udelay(1);
-
-		mask = (low2high) ? (mask<<1) : (mask>>1);
-	}
-
-	write_nic_word(dev, RFPinsOutput, rw|oval);
-	udelay(2);
-	mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1));
-
-	/*
-	 * We must set data pin to HW controlled, otherwise RF can't driver it
-	 * and value RF register won't be able to read back properly.
-	 */
-	write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01)));
-
-	for (i = 0; i < rLength; i++) {
-		write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1);
-
-		write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
-		udelay(2);
-		write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
-		udelay(2);
-		write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
-		udelay(2);
-		tmp = read_nic_word(dev, RFPinsInput);
-
-		dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0);
-
-		write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2);
-
-		mask = (low2high) ? (mask<<1) : (mask>>1);
-	}
-
-	write_nic_word(dev, RFPinsOutput,
-			BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval);
-	udelay(2);
-
-	write_nic_word(dev, RFPinsEnable, oval2);
-	write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */
-	write_nic_word(dev, RFPinsOutput, 0x3a0);
-
-	return dataRead;
-}
-
-void rtl8225z2_rf_close(struct net_device *dev)
-{
-	RF_WriteReg(dev, 0x4, 0x1f);
-
-	force_pci_posting(dev);
-	mdelay(1);
-
-	rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF);
-	rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF);
-}
-
-/*
- * Map dBm into Tx power index according to current HW model, for example,
- * RF and PA, and current wireless mode.
- */
-static s8 DbmToTxPwrIdx(struct r8180_priv *priv,
-			enum wireless_mode mode, s32 PowerInDbm)
-{
-	bool bUseDefault = true;
-	s8 TxPwrIdx = 0;
-
-	/*
-	 * OFDM Power in dBm = Index * 0.5 + 0
-	 * CCK Power in dBm = Index * 0.25 + 13
-	 */
-	s32 tmp = 0;
-
-	if (mode == WIRELESS_MODE_G) {
-		bUseDefault = false;
-		tmp = (2 * PowerInDbm);
-
-		if (tmp < 0)
-			TxPwrIdx = 0;
-		else if (tmp > 40) /* 40 means 20 dBm. */
-			TxPwrIdx = 40;
-		else
-			TxPwrIdx = (s8)tmp;
-	} else if (mode == WIRELESS_MODE_B) {
-		bUseDefault = false;
-		tmp = (4 * PowerInDbm) - 52;
-
-		if (tmp < 0)
-			TxPwrIdx = 0;
-		else if (tmp > 28) /* 28 means 20 dBm. */
-			TxPwrIdx = 28;
-		else
-			TxPwrIdx = (s8)tmp;
-	}
-
-	/*
-	 * TRUE if we want to use a default implementation.
-	 * We shall set it to FALSE when we have exact translation formula
-	 * for target IC. 070622, by rcnjko.
-	 */
-	if (bUseDefault) {
-		if (PowerInDbm < 0)
-			TxPwrIdx = 0;
-		else if (PowerInDbm > 35)
-			TxPwrIdx = 35;
-		else
-			TxPwrIdx = (u8)PowerInDbm;
-	}
-
-	return TxPwrIdx;
-}
-
-void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8 max_cck_power_level;
-	u8 max_ofdm_power_level;
-	u8 min_ofdm_power_level;
-	char cck_power_level = (char)(0xff & priv->chtxpwr[ch]);
-	char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]);
-
-	if (IS_DOT11D_ENABLE(priv->ieee80211) &&
-	    IS_DOT11D_STATE_DONE(priv->ieee80211)) {
-		u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch);
-		u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B,
-							MaxTxPwrInDbm);
-		u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G,
-							MaxTxPwrInDbm);
-
-		if (cck_power_level > CckMaxPwrIdx)
-			cck_power_level = CckMaxPwrIdx;
-		if (ofdm_power_level > OfdmMaxPwrIdx)
-			ofdm_power_level = OfdmMaxPwrIdx;
-	}
-
-	max_cck_power_level = 15;
-	max_ofdm_power_level = 25;
-	min_ofdm_power_level = 10;
-
-	if (cck_power_level > 35)
-		cck_power_level = 35;
-
-	write_nic_byte(dev, CCK_TXAGC, cck_power_level);
-	force_pci_posting(dev);
-	mdelay(1);
-
-	if (ofdm_power_level > 35)
-		ofdm_power_level = 35;
-
-	if (priv->up == 0) {
-		write_phy_ofdm(dev, 2, 0x42);
-		write_phy_ofdm(dev, 5, 0x00);
-		write_phy_ofdm(dev, 6, 0x40);
-		write_phy_ofdm(dev, 7, 0x00);
-		write_phy_ofdm(dev, 8, 0x40);
-	}
-
-	write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level);
-
-	if (ofdm_power_level <= 11) {
-		write_phy_ofdm(dev, 0x07, 0x5c);
-		write_phy_ofdm(dev, 0x09, 0x5c);
-	}
-
-	if (ofdm_power_level <= 17) {
-		write_phy_ofdm(dev, 0x07, 0x54);
-		write_phy_ofdm(dev, 0x09, 0x54);
-	} else {
-		write_phy_ofdm(dev, 0x07, 0x50);
-		write_phy_ofdm(dev, 0x09, 0x50);
-	}
-
-	force_pci_posting(dev);
-	mdelay(1);
-}
-
-void rtl8225z2_rf_set_chan(struct net_device *dev, short ch)
-{
-	rtl8225z2_SetTXPowerLevel(dev, ch);
-
-	RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
-
-	if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch])
-		RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
-
-	mdelay(1);
-
-	force_pci_posting(dev);
-	mdelay(10);
-}
-
-static void rtl8225_host_pci_init(struct net_device *dev)
-{
-	write_nic_word(dev, RFPinsOutput, 0x480);
-
-	rtl8185_rf_pins_enable(dev);
-
-	write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO);
-
-	write_nic_byte(dev, GP_ENABLE, 0);
-
-	force_pci_posting(dev);
-	mdelay(200);
-
-	/* bit 6 is for RF on/off detection */
-	write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6)));
-}
-
-void rtl8225z2_rf_init(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int i;
-	short channel = 1;
-	u16 brsr;
-	u32 data;
-
-	priv->chan = channel;
-
-	rtl8225_host_pci_init(dev);
-
-	write_nic_dword(dev, RF_TIMING, 0x000a8008);
-
-	brsr = read_nic_word(dev, BRSR);
-
-	write_nic_word(dev, BRSR, 0xffff);
-
-	write_nic_dword(dev, RF_PARA, 0x100044);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	write_nic_byte(dev, CONFIG3, 0x44);
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-	rtl8185_rf_pins_enable(dev);
-
-	write_rtl8225(dev, 0x0, 0x2bf); mdelay(1);
-	write_rtl8225(dev, 0x1, 0xee0); mdelay(1);
-	write_rtl8225(dev, 0x2, 0x44d); mdelay(1);
-	write_rtl8225(dev, 0x3, 0x441); mdelay(1);
-	write_rtl8225(dev, 0x4, 0x8c3); mdelay(1);
-	write_rtl8225(dev, 0x5, 0xc72); mdelay(1);
-	write_rtl8225(dev, 0x6, 0xe6);  mdelay(1);
-	write_rtl8225(dev, 0x7, rtl8225_chan[channel]);  mdelay(1);
-	write_rtl8225(dev, 0x8, 0x3f);  mdelay(1);
-	write_rtl8225(dev, 0x9, 0x335); mdelay(1);
-	write_rtl8225(dev, 0xa, 0x9d4); mdelay(1);
-	write_rtl8225(dev, 0xb, 0x7bb); mdelay(1);
-	write_rtl8225(dev, 0xc, 0x850); mdelay(1);
-	write_rtl8225(dev, 0xd, 0xcdf); mdelay(1);
-	write_rtl8225(dev, 0xe, 0x2b);  mdelay(1);
-	write_rtl8225(dev, 0xf, 0x114);
-
-	mdelay(100);
-
-	write_rtl8225(dev, 0x0, 0x1b7);
-
-	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
-		write_rtl8225(dev, 0x1, i + 1);
-		write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]);
-	}
-
-	write_rtl8225(dev, 0x3, 0x80);
-	write_rtl8225(dev, 0x5, 0x4);
-
-	write_rtl8225(dev, 0x0, 0xb7);
-
-	write_rtl8225(dev, 0x2, 0xc4d);
-
-	/* FIXME!! rtl8187 we have to check if calibrarion
-	 * is successful and eventually cal. again (repeat
-	 * the two write on reg 2)
-	 */
-	data = read_rtl8225(dev, 6);
-	if (!(data & 0x00000080)) {
-		write_rtl8225(dev, 0x02, 0x0c4d);
-		force_pci_posting(dev); mdelay(200);
-		write_rtl8225(dev, 0x02, 0x044d);
-		force_pci_posting(dev); mdelay(100);
-		data = read_rtl8225(dev, 6);
-		if (!(data & 0x00000080))
-			DMESGW("RF Calibration Failed!!!!\n");
-	}
-
-	mdelay(200);
-
-	write_rtl8225(dev, 0x0, 0x2bf);
-
-	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
-		write_phy_ofdm(dev, 0xb, rtl8225_agc[i]);
-		mdelay(1);
-
-		/* enable writing AGC table */
-		write_phy_ofdm(dev, 0xa, i + 0x80);
-		mdelay(1);
-	}
-
-	force_pci_posting(dev);
-	mdelay(1);
-
-	write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
-	write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
-	write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
-	write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
-	write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
-	write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
-	write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
-	write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
-	write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
-	write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
-	write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1);
-	write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
-	write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
-	write_phy_ofdm(dev, 0x0d, 0x43);
-	write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
-	write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
-	write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
-	write_phy_ofdm(dev, 0x11, 0x07); mdelay(1);
-	write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
-	write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
-	write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
-	write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
-	write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
-	write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
-	write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
-	write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
-	write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
-	write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1);
-	write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
-	write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
-	write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
-	write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
-	write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
-	write_phy_ofdm(dev, 0x21, 0x17); mdelay(1);
-	write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
-	write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */
-	write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
-	write_phy_ofdm(dev, 0x25, 0x00); mdelay(1);
-	write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
-	write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
-
-	rtl8225z2_set_gain(dev, 4);
-
-	write_phy_cck(dev, 0x0, 0x98); mdelay(1);
-	write_phy_cck(dev, 0x3, 0x20); mdelay(1);
-	write_phy_cck(dev, 0x4, 0x7e); mdelay(1);
-	write_phy_cck(dev, 0x5, 0x12); mdelay(1);
-	write_phy_cck(dev, 0x6, 0xfc); mdelay(1);
-	write_phy_cck(dev, 0x7, 0x78); mdelay(1);
-	write_phy_cck(dev, 0x8, 0x2e); mdelay(1);
-	write_phy_cck(dev, 0x10, 0x93); mdelay(1);
-	write_phy_cck(dev, 0x11, 0x88); mdelay(1);
-	write_phy_cck(dev, 0x12, 0x47); mdelay(1);
-	write_phy_cck(dev, 0x13, 0xd0);
-	write_phy_cck(dev, 0x19, 0x00);
-	write_phy_cck(dev, 0x1a, 0xa0);
-	write_phy_cck(dev, 0x1b, 0x08);
-	write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */
-	write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
-	write_phy_cck(dev, 0x42, 0x15); mdelay(1);
-	write_phy_cck(dev, 0x43, 0x18); mdelay(1);
-	write_phy_cck(dev, 0x44, 0x36); mdelay(1);
-	write_phy_cck(dev, 0x45, 0x35); mdelay(1);
-	write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
-	write_phy_cck(dev, 0x47, 0x25); mdelay(1);
-	write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
-	write_phy_cck(dev, 0x49, 0x12); mdelay(1);
-	write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
-	write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
-	write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
-
-	write_nic_byte(dev, 0x5b, 0x0d); mdelay(1);
-
-	rtl8225z2_SetTXPowerLevel(dev, channel);
-
-	/* RX antenna default to A */
-	write_phy_cck(dev, 0x11, 0x9b); mdelay(1);		/* B: 0xDB */
-	write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);		/* B: 0x10 */
-
-	rtl8185_tx_antenna(dev, 0x03);				/* B: 0x00 */
-
-	/* switch to high-speed 3-wire
-	 * last digit. 2 for both cck and ofdm
-	 */
-	write_nic_dword(dev, 0x94, 0x15c00002);
-	rtl8185_rf_pins_enable(dev);
-
-	rtl8225z2_rf_set_chan(dev, priv->chan);
-}
-
-#define MAX_DOZE_WAITING_TIMES_85B		20
-#define MAX_POLLING_24F_TIMES_87SE		10
-#define LPS_MAX_SLEEP_WAITING_TIMES_87SE	5
-
-bool SetZebraRFPowerState8185(struct net_device *dev,
-			      enum rt_rf_power_state eRFPowerState)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8			btCR9346, btConfig3;
-	bool bActionAllowed = true, bTurnOffBB = true;
-	u8			u1bTmp;
-	int			i;
-	bool		bResult = true;
-	u8			QueueID;
-
-	if (priv->SetRFPowerStateInProgress == true)
-		return false;
-
-	priv->SetRFPowerStateInProgress = true;
-
-	btCR9346 = read_nic_byte(dev, CR9346);
-	write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
-
-	btConfig3 = read_nic_byte(dev, CONFIG3);
-	write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En));
-
-	switch (eRFPowerState) {
-	case RF_ON:
-		write_nic_word(dev, 0x37C, 0x00EC);
-
-		/* turn on AFE */
-		write_nic_byte(dev, 0x54, 0x00);
-		write_nic_byte(dev, 0x62, 0x00);
-
-		/* turn on RF */
-		RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
-		RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
-
-		/* turn on RF again */
-		RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
-		RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
-
-		/* turn on BB */
-		write_phy_ofdm(dev, 0x10, 0x40);
-		write_phy_ofdm(dev, 0x12, 0x40);
-
-		/* Avoid power down at init time. */
-		write_nic_byte(dev, CONFIG4, priv->RFProgType);
-
-		u1bTmp = read_nic_byte(dev, 0x24E);
-		write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
-		break;
-	case RF_SLEEP:
-		for (QueueID = 0, i = 0; QueueID < 6;) {
-			if (get_curr_tx_free_desc(dev, QueueID) ==
-							priv->txringcount) {
-				QueueID++;
-				continue;
-			} else {
-				priv->TxPollingTimes++;
-				if (priv->TxPollingTimes >=
-					LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
-					bActionAllowed = false;
-					break;
-				} else
-					udelay(10);
-			}
-		}
-
-		if (bActionAllowed) {
-			/* turn off BB RXIQ matrix to cut off rx signal */
-			write_phy_ofdm(dev, 0x10, 0x00);
-			write_phy_ofdm(dev, 0x12, 0x00);
-
-			/* turn off RF */
-			RF_WriteReg(dev, 0x4, 0x0000);
-			RF_WriteReg(dev, 0x0, 0x0000);
-
-			/* turn off AFE except PLL */
-			write_nic_byte(dev, 0x62, 0xff);
-			write_nic_byte(dev, 0x54, 0xec);
-
-			mdelay(1);
-
-			{
-				int i = 0;
-				while (true) {
-					u8 tmp24F = read_nic_byte(dev, 0x24f);
-
-					if ((tmp24F == 0x01) ||
-							(tmp24F == 0x09)) {
-						bTurnOffBB = true;
-						break;
-					} else {
-						udelay(10);
-						i++;
-						priv->TxPollingTimes++;
-
-						if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
-							bTurnOffBB = false;
-							break;
-						} else
-							udelay(10);
-					}
-				}
-			}
-
-			if (bTurnOffBB) {
-				/* turn off BB */
-				u1bTmp = read_nic_byte(dev, 0x24E);
-				write_nic_byte(dev, 0x24E,
-						(u1bTmp | BIT5 | BIT6));
-
-				/* turn off AFE PLL */
-				write_nic_byte(dev, 0x54, 0xFC);
-				write_nic_word(dev, 0x37C, 0x00FC);
-			}
-		}
-		break;
-	case RF_OFF:
-		for (QueueID = 0, i = 0; QueueID < 6;) {
-			if (get_curr_tx_free_desc(dev, QueueID) ==
-					priv->txringcount) {
-				QueueID++;
-				continue;
-			} else {
-				udelay(10);
-				i++;
-			}
-
-			if (i >= MAX_DOZE_WAITING_TIMES_85B)
-				break;
-		}
-
-		/* turn off BB RXIQ matrix to cut off rx signal */
-		write_phy_ofdm(dev, 0x10, 0x00);
-		write_phy_ofdm(dev, 0x12, 0x00);
-
-		/* turn off RF */
-		RF_WriteReg(dev, 0x4, 0x0000);
-		RF_WriteReg(dev, 0x0, 0x0000);
-
-		/* turn off AFE except PLL */
-		write_nic_byte(dev, 0x62, 0xff);
-		write_nic_byte(dev, 0x54, 0xec);
-
-		mdelay(1);
-
-		{
-			int i = 0;
-
-			while (true) {
-				u8 tmp24F = read_nic_byte(dev, 0x24f);
-
-				if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
-					bTurnOffBB = true;
-					break;
-				} else {
-					bTurnOffBB = false;
-					udelay(10);
-					i++;
-				}
-
-				if (i > MAX_POLLING_24F_TIMES_87SE)
-					break;
-			}
-		}
-
-		if (bTurnOffBB) {
-			/* turn off BB */
-			u1bTmp = read_nic_byte(dev, 0x24E);
-			write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
-
-			/* turn off AFE PLL (80M) */
-			write_nic_byte(dev, 0x54, 0xFC);
-			write_nic_word(dev, 0x37C, 0x00FC);
-		}
-		break;
-	}
-
-	btConfig3 &= ~(CONFIG3_PARM_En);
-	write_nic_byte(dev, CONFIG3, btConfig3);
-
-	btCR9346 &= ~(0xC0);
-	write_nic_byte(dev, CR9346, btCR9346);
-
-	if (bResult && bActionAllowed)
-		priv->eRFPowerState = eRFPowerState;
-
-	priv->SetRFPowerStateInProgress = false;
-
-	return bResult && bActionAllowed;
-}
-
-void rtl8225z4_rf_sleep(struct net_device *dev)
-{
-	MgntActSet_RF_State(dev, RF_SLEEP, RF_CHANGE_BY_PS);
-}
-
-void rtl8225z4_rf_wakeup(struct net_device *dev)
-{
-	MgntActSet_RF_State(dev, RF_ON, RF_CHANGE_BY_PS);
-}
diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
deleted file mode 100644
index b55249170f18..000000000000
--- a/drivers/staging/rtl8187se/r8180_wx.c
+++ /dev/null
@@ -1,1409 +0,0 @@
-/*
-	This file contains wireless extension handlers.
-
-	This is part of rtl8180 OpenSource driver.
-	Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
-	Released under the terms of GPL (General Public Licence)
-
-	Parts of this driver are based on the GPL part
-	of the official realtek driver.
-
-	Parts of this driver are based on the rtl8180 driver skeleton
-	from Patric Schenke & Andres Salomon.
-
-	Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
-
-	We want to thanks the Authors of those projects and the Ndiswrapper
-	project Authors.
-*/
-
-
-#include "r8180.h"
-#include "r8180_hw.h"
-
-#include <net/iw_handler.h>
-#include "ieee80211/dot11d.h"
-
-static u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
-	6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
-
-#define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
-
-static struct rtl8187se_channel_list default_channel_plan[] = {
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19},		/* FCC */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},						/* IC */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},	/* ETSI	*/
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},	/* Spain. Change to ETSI. */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},	/* France. Change to ETSI. */
-	{{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9},						/* MKK */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},	/* MKK1	*/
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},	/* Israel */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17},			/* For 11a , TELEC */
-	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}					/* For Global Domain. 1-11:active scan, 12-14 passive scan.*/	/* +YJ, 080626 */
-};
-static int r8180_wx_get_freq(struct net_device *dev,
-			     struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
-}
-
-
-static int r8180_wx_set_key(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *key)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct iw_point *erq = &(wrqu->encoding);
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	if (erq->length > 0) {
-		u32 *tkey = (u32 *) key;
-		priv->key0[0] = tkey[0];
-		priv->key0[1] = tkey[1];
-		priv->key0[2] = tkey[2];
-		priv->key0[3] = tkey[3] & 0xff;
-		DMESG("Setting wep key to %x %x %x %x",
-		      tkey[0], tkey[1], tkey[2], tkey[3]);
-		rtl8180_set_hw_wep(dev);
-	}
-	return 0;
-}
-
-
-static int r8180_wx_set_beaconinterval(struct net_device *dev,
-				       struct iw_request_info *aa,
-				       union iwreq_data *wrqu, char *b)
-{
-	int *parms = (int *)b;
-	int bi = parms[0];
-
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	DMESG("setting beacon interval to %x", bi);
-
-	priv->ieee80211->current_network.beacon_interval = bi;
-	rtl8180_commit(dev);
-	up(&priv->wx_sem);
-
-	return 0;
-}
-
-
-
-static int r8180_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
-}
-
-
-
-static int r8180_wx_get_rate(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
-}
-
-
-
-static int r8180_wx_set_rate(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	int ret;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-
-	ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-
-
-static int r8180_wx_set_crcmon(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int *parms = (int *)extra;
-	int enable = (parms[0] > 0);
-	short prev = priv->crcmon;
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-
-	if (enable)
-		priv->crcmon = 1;
-	else
-		priv->crcmon = 0;
-
-	DMESG("bad CRC in monitor mode are %s",
-	      priv->crcmon ? "accepted" : "rejected");
-
-	if (prev != priv->crcmon && priv->up)	{
-		rtl8180_down(dev);
-		rtl8180_up(dev);
-	}
-
-	up(&priv->wx_sem);
-
-	return 0;
-}
-
-
-static int r8180_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret;
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	if (priv->bInactivePs)	{
-		if (wrqu->mode == IW_MODE_ADHOC)
-			IPSLeave(dev);
-	}
-	ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
-
-	up(&priv->wx_sem);
-	return ret;
-}
-
-/* YJ,add,080819,for hidden ap */
-struct  iw_range_with_scan_capa	{
-		/* Informative stuff (to choose between different interface) */
-
-		__u32		throughput; /* To give an idea... */
-
-		/* In theory this value should be the maximum benchmarked
-		 * TCP/IP throughput, because with most of these devices the
-		 * bit rate is meaningless (overhead an co) to estimate how
-		 * fast the connection will go and pick the fastest one.
-		 * I suggest people to play with Netperf or any benchmark...
-		 */
-
-		/* NWID (or domain id)	*/
-		__u32           min_nwid; /* Minimal NWID we are able to set */
-		__u32			max_nwid; /* Maximal NWID we are able to set */
-
-		/* Old Frequency (backward compat - moved lower ) */
-		__u16			old_num_channels;
-		__u8			old_num_frequency;
-
-		/* Scan capabilities */
-		__u8			scan_capa;
-};
-/* YJ,add,080819,for hidden ap */
-
-
-static int rtl8180_wx_get_range(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	struct iw_range *range = (struct iw_range *)extra;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u16 val;
-	int i;
-
-	wrqu->data.length = sizeof(*range);
-	memset(range, 0, sizeof(*range));
-
-	/* Let's try to keep this struct in the same order as in
-	 * linux/include/wireless.h
-	 */
-
-	/* TODO: See what values we can set, and remove the ones we can't
-	 * set, or fill them with some default data.
-	 */
-
-	/* ~5 Mb/s real (802.11b) */
-	range->throughput = 5 * 1000 * 1000;
-
-	/* TODO: Not used in 802.11b?	*/
-/*	range->min_nwid; */	/* Minimal NWID we are able to set */
-	/* TODO: Not used in 802.11b?	*/
-/*	range->max_nwid; */	/* Maximal NWID we are able to set */
-
-		/* Old Frequency (backward compat - moved lower ) */
-/*	range->old_num_channels; */
-/*	range->old_num_frequency; */
-/*	range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
-	if (priv->rf_set_sens != NULL)
-		range->sensitivity = priv->max_sens;	/* signal level threshold range */
-
-	range->max_qual.qual = 100;
-	/* TODO: Find real max RSSI and stick here */
-	range->max_qual.level = 0;
-	range->max_qual.noise = -98;
-	range->max_qual.updated = 7; /* Updated all three */
-
-	range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
-	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
-	range->avg_qual.level = 20 + -98;
-	range->avg_qual.noise = 0;
-	range->avg_qual.updated = 7; /* Updated all three */
-
-	range->num_bitrates = RATE_COUNT;
-
-	for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
-		range->bitrate[i] = rtl8180_rates[i];
-
-	range->min_frag = MIN_FRAG_THRESHOLD;
-	range->max_frag = MAX_FRAG_THRESHOLD;
-
-	range->pm_capa = 0;
-
-	range->we_version_compiled = WIRELESS_EXT;
-	range->we_version_source = 16;
-
-		range->num_channels = 14;
-
-	for (i = 0, val = 0; i < 14; i++) {
-
-		/* Include only legal frequencies for some countries */
-		if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
-				range->freq[val].i = i + 1;
-			range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
-			range->freq[val].e = 1;
-			val++;
-		} else {
-			/* FIXME: do we need to set anything for channels */
-			/* we don't use ? */
-		}
-
-		if (val == IW_MAX_FREQUENCIES)
-			break;
-	}
-
-	range->num_frequency = val;
-	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
-						IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-
-	return 0;
-}
-
-
-static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret;
-	struct ieee80211_device *ieee = priv->ieee80211;
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	if (wrqu->data.flags & IW_SCAN_THIS_ESSID)	{
-		struct iw_scan_req *req = (struct iw_scan_req *)b;
-		if (req->essid_len)		{
-			ieee->current_network.ssid_len = req->essid_len;
-			memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
-		}
-	}
-
-	down(&priv->wx_sem);
-	if (priv->up)	{
-		priv->ieee80211->actscanning = true;
-		if (priv->bInactivePs && (priv->ieee80211->state != IEEE80211_LINKED))	{
-			IPSLeave(dev);
-		ieee80211_softmac_ips_scan_syncro(priv->ieee80211);
-			ret = 0;
-		}	else	{
-			/* prevent scan in BusyTraffic */
-			/* FIXME: Need to consider last scan time */
-			if ((priv->link_detect.b_busy_traffic) && (true)) {
-				ret = 0;
-				printk("Now traffic is busy, please try later!\n");
-			}	else
-				/* prevent scan in BusyTraffic,end */
-				ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
-		}
-	}	else
-			ret = -1;
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-
-
-static int r8180_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b)
-{
-
-	int ret;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	down(&priv->wx_sem);
-	if (priv->up)
-		ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
-	else
-		ret = -1;
-
-	up(&priv->wx_sem);
-	return ret;
-}
-
-
-static int r8180_wx_set_essid(struct net_device *dev,
-			      struct iw_request_info *a,
-			      union iwreq_data *wrqu, char *b)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	int ret;
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	if (priv->bInactivePs)
-		IPSLeave(dev);
-
-	ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
-
-	up(&priv->wx_sem);
-	return ret;
-}
-
-
-static int r8180_wx_get_essid(struct net_device *dev,
-			      struct iw_request_info *a,
-			      union iwreq_data *wrqu, char *b)
-{
-	int ret;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	down(&priv->wx_sem);
-
-	ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-
-
-static int r8180_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b)
-{
-	int ret;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-
-	ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
-
-	up(&priv->wx_sem);
-	return ret;
-}
-
-
-static int r8180_wx_get_name(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
-}
-
-static int r8180_wx_set_frag(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	if (wrqu->frag.disabled)
-		priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
-	else {
-		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
-		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
-			return -EINVAL;
-
-		priv->ieee80211->fts = wrqu->frag.value & ~0x1;
-	}
-
-	return 0;
-}
-
-
-static int r8180_wx_get_frag(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	wrqu->frag.value = priv->ieee80211->fts;
-	wrqu->frag.fixed = 0;	/* no auto select */
-	wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
-
-	return 0;
-}
-
-
-static int r8180_wx_set_wap(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *awrq, char *extra)
-{
-	int ret;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-
-	ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
-
-	up(&priv->wx_sem);
-	return ret;
-
-}
-
-
-static int r8180_wx_get_wap(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
-}
-
-
-static int r8180_wx_set_enc(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *key)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret;
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-
-	down(&priv->wx_sem);
-
-	if (priv->hw_wep)
-		ret = r8180_wx_set_key(dev, info, wrqu, key);
-	else	{
-		DMESG("Setting SW wep key");
-		ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
-	}
-
-	up(&priv->wx_sem);
-	return ret;
-}
-
-
-static int r8180_wx_get_enc(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *key)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
-}
-
-
-static int r8180_wx_set_scan_type(struct net_device *dev,
-				  struct iw_request_info *aa,
-				  union	iwreq_data *wrqu, char *p)
-{
-
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int *parms = (int *)p;
-	int mode = parms[0];
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	priv->ieee80211->active_scan = mode;
-
-	return 1;
-}
-
-static int r8180_wx_set_retry(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int err = 0;
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-
-	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
-	    wrqu->retry.disabled)	{
-		err = -EINVAL;
-		goto exit;
-	}
-	if (!(wrqu->retry.flags & IW_RETRY_LIMIT))	{
-		err = -EINVAL;
-		goto exit;
-	}
-
-	if (wrqu->retry.value > R8180_MAX_RETRY)	{
-		err = -EINVAL;
-		goto exit;
-	}
-	if (wrqu->retry.flags & IW_RETRY_MAX) {
-		priv->retry_rts = wrqu->retry.value;
-		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
-
-	}	else {
-		priv->retry_data = wrqu->retry.value;
-		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
-	}
-
-	/* FIXME !
-	 * We might try to write directly the TX config register
-	 * or to restart just the (R)TX process.
-	 * I'm unsure if whole reset is really needed
-	 */
-
-	rtl8180_commit(dev);
-exit:
-	up(&priv->wx_sem);
-
-	return err;
-}
-
-static int r8180_wx_get_retry(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-	wrqu->retry.disabled = 0; /* can't be disabled */
-
-	if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
-	    IW_RETRY_LIFETIME)
-		return -EINVAL;
-
-	if (wrqu->retry.flags & IW_RETRY_MAX) {
-		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-		wrqu->retry.value = priv->retry_rts;
-	} else {
-		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
-		wrqu->retry.value = priv->retry_data;
-	}
-
-	return 0;
-}
-
-static int r8180_wx_get_sens(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	if (priv->rf_set_sens == NULL)
-		return -1; /* we have not this support for this radio */
-	wrqu->sens.value = priv->sens;
-	return 0;
-}
-
-
-static int r8180_wx_set_sens(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	short err = 0;
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	if (priv->rf_set_sens == NULL) {
-		err = -1; /* we have not this support for this radio */
-		goto exit;
-	}
-	if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
-		priv->sens = wrqu->sens.value;
-	else
-		err = -EINVAL;
-
-exit:
-	up(&priv->wx_sem);
-
-	return err;
-}
-
-
-static int r8180_wx_set_rawtx(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret;
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-
-	ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
-
-	up(&priv->wx_sem);
-
-	return ret;
-
-}
-
-static int r8180_wx_get_power(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	int ret;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	down(&priv->wx_sem);
-
-	ret = ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-
-static int r8180_wx_set_power(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	int ret;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	printk("=>>>>>>>>>>=============================>set power:%d, %d!\n", wrqu->power.disabled, wrqu->power.flags);
-	if (wrqu->power.disabled == 0) {
-		wrqu->power.flags |= IW_POWER_ALL_R;
-		wrqu->power.flags |= IW_POWER_TIMEOUT;
-		wrqu->power.value = 1000;
-	}
-
-	ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-
-static int r8180_wx_set_rts(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	if (wrqu->rts.disabled)
-		priv->rts = DEFAULT_RTS_THRESHOLD;
-	else {
-		if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
-		    wrqu->rts.value > MAX_RTS_THRESHOLD)
-			return -EINVAL;
-
-		priv->rts = wrqu->rts.value;
-	}
-
-	return 0;
-}
-static int r8180_wx_get_rts(struct net_device *dev,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-
-	wrqu->rts.value = priv->rts;
-	wrqu->rts.fixed = 0;	/* no auto select */
-	wrqu->rts.disabled = (wrqu->rts.value == 0);
-
-	return 0;
-}
-static int dummy(struct net_device *dev, struct iw_request_info *a,
-		 union iwreq_data *wrqu, char *b)
-{
-	return -1;
-}
-
-static int r8180_wx_get_iwmode(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee;
-	int ret = 0;
-
-
-
-	down(&priv->wx_sem);
-
-	ieee = priv->ieee80211;
-
-	strcpy(extra, "802.11");
-	if (ieee->modulation & IEEE80211_CCK_MODULATION) {
-		strcat(extra, "b");
-		if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-			strcat(extra, "/g");
-	} else if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-		strcat(extra, "g");
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-static int r8180_wx_set_iwmode(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee80211;
-	int *param = (int *)extra;
-	int ret = 0;
-	int modulation = 0, mode = 0;
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-
-	if (*param == 1) {
-		modulation |= IEEE80211_CCK_MODULATION;
-		mode = IEEE_B;
-	printk(KERN_INFO "B mode!\n");
-	} else if (*param == 2) {
-		modulation |= IEEE80211_OFDM_MODULATION;
-		mode = IEEE_G;
-	printk(KERN_INFO "G mode!\n");
-	} else if (*param == 3) {
-		modulation |= IEEE80211_CCK_MODULATION;
-		modulation |= IEEE80211_OFDM_MODULATION;
-		mode = IEEE_B|IEEE_G;
-	printk(KERN_INFO "B/G mode!\n");
-	}
-
-	if (ieee->proto_started) {
-		ieee80211_stop_protocol(ieee);
-		ieee->mode = mode;
-		ieee->modulation = modulation;
-		ieee80211_start_protocol(ieee);
-	} else {
-		ieee->mode = mode;
-		ieee->modulation = modulation;
-	}
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-static int r8180_wx_get_preamble(struct net_device *dev,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-
-	down(&priv->wx_sem);
-
-
-
-	*extra = (char) priv->plcp_preamble_mode;	/* 0:auto 1:short 2:long */
-	up(&priv->wx_sem);
-
-	return 0;
-}
-static int r8180_wx_set_preamble(struct net_device *dev,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret = 0;
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	if (*extra < 0 || *extra > 2)
-		ret = -1;
-	else
-		priv->plcp_preamble_mode = *((short *)extra);
-
-
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-static int r8180_wx_get_siglevel(struct net_device *dev,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret = 0;
-
-
-
-	down(&priv->wx_sem);
-	/* Modify by hikaru 6.5 */
-	*((int *)extra) = priv->wstats.qual.level;/*for interface test ,it should be the priv->wstats.qual.level; */
-
-
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-static int r8180_wx_get_sigqual(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret = 0;
-
-
-
-	down(&priv->wx_sem);
-	/* Modify by hikaru 6.5	*/
-	*((int *)extra) = priv->wstats.qual.qual;/* for interface test ,it should be the priv->wstats.qual.qual; */
-
-
-
-	up(&priv->wx_sem);
-
-	return ret;
-}
-static int r8180_wx_reset_stats(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	down(&priv->wx_sem);
-
-	priv->stats.txrdu = 0;
-	priv->stats.rxrdu = 0;
-	priv->stats.rxnolast = 0;
-	priv->stats.rxnodata = 0;
-	priv->stats.rxnopointer = 0;
-	priv->stats.txnperr = 0;
-	priv->stats.txresumed = 0;
-	priv->stats.rxerr = 0;
-	priv->stats.rxoverflow = 0;
-	priv->stats.rxint = 0;
-
-	priv->stats.txnpokint = 0;
-	priv->stats.txhpokint = 0;
-	priv->stats.txhperr = 0;
-	priv->stats.ints = 0;
-	priv->stats.shints = 0;
-	priv->stats.txoverflow = 0;
-	priv->stats.rxdmafail = 0;
-	priv->stats.txbeacon = 0;
-	priv->stats.txbeaconerr = 0;
-	priv->stats.txlpokint = 0;
-	priv->stats.txlperr = 0;
-	priv->stats.txretry = 0;/* 20060601 */
-	priv->stats.rxcrcerrmin = 0 ;
-	priv->stats.rxcrcerrmid = 0;
-	priv->stats.rxcrcerrmax = 0;
-	priv->stats.rxicverr = 0;
-
-	up(&priv->wx_sem);
-
-	return 0;
-
-}
-static int r8180_wx_radio_on(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-
-	down(&priv->wx_sem);
-	priv->rf_wakeup(dev);
-
-	up(&priv->wx_sem);
-
-	return 0;
-
-}
-
-static int r8180_wx_radio_off(struct net_device *dev,
-			      struct iw_request_info *info,
-			      union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-
-	down(&priv->wx_sem);
-	priv->rf_sleep(dev);
-
-	up(&priv->wx_sem);
-
-	return 0;
-
-}
-static int r8180_wx_get_channelplan(struct net_device *dev,
-				    struct iw_request_info *info,
-				    union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-
-	down(&priv->wx_sem);
-	*extra = priv->channel_plan;
-
-
-
-	up(&priv->wx_sem);
-
-	return 0;
-}
-static int r8180_wx_set_channelplan(struct net_device *dev,
-				    struct iw_request_info *info,
-				    union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int *val = (int *)extra;
-	int i;
-	printk("-----in fun %s\n", __func__);
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	/* unsigned long flags; */
-	down(&priv->wx_sem);
-	if (default_channel_plan[*val].len != 0) {
-		priv->channel_plan = *val;
-		/* Clear old channel map 8 */
-		for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
-			GET_DOT11D_INFO(priv->ieee80211)->channel_map[i] = 0;
-
-		/* Set new channel map */
-		for (i = 1; i <= default_channel_plan[*val].len; i++)
-			GET_DOT11D_INFO(priv->ieee80211)->channel_map[default_channel_plan[*val].channel[i-1]] = 1;
-
-	}
-	up(&priv->wx_sem);
-
-	return 0;
-}
-
-static int r8180_wx_get_version(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	/* struct ieee80211_device *ieee; */
-
-	down(&priv->wx_sem);
-	strcpy(extra, "1020.0808");
-	up(&priv->wx_sem);
-
-	return 0;
-}
-
-/* added by amy 080818 */
-/*receive datarate from user typing valid rate is from 2 to 108 (1 - 54M), if input 0, return to normal rate adaptive. */
-static int r8180_wx_set_forcerate(struct net_device *dev,
-				  struct iw_request_info *info,
-				  union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	u8 forcerate = *extra;
-
-	down(&priv->wx_sem);
-
-	printk("==============>%s(): forcerate is %d\n", __func__, forcerate);
-	if ((forcerate == 2) || (forcerate == 4) || (forcerate == 11) || (forcerate == 22) || (forcerate == 12) ||
-		(forcerate == 18) || (forcerate == 24) || (forcerate == 36) || (forcerate == 48) || (forcerate == 72) ||
-		(forcerate == 96) || (forcerate == 108)) {
-		priv->ForcedDataRate = 1;
-		priv->ieee80211->rate = forcerate * 5;
-	}	else if (forcerate == 0)	{
-		priv->ForcedDataRate = 0;
-		printk("OK! return rate adaptive\n");
-	}	else
-			printk("ERR: wrong rate\n");
-	up(&priv->wx_sem);
-	return 0;
-}
-
-static int r8180_wx_set_enc_ext(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	int ret = 0;
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
-	up(&priv->wx_sem);
-	return ret;
-
-}
-static int r8180_wx_set_auth(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int ret = 0;
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &wrqu->param, extra);
-	up(&priv->wx_sem);
-	return ret;
-}
-
-static int r8180_wx_set_mlme(struct net_device *dev,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-
-	down(&priv->wx_sem);
-#if 1
-	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
-#endif
-	up(&priv->wx_sem);
-	return ret;
-}
-static int r8180_wx_set_gen_ie(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	int ret = 0;
-		struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-	if (priv->ieee80211->bHwRadioOff)
-		return 0;
-
-	down(&priv->wx_sem);
-#if 1
-	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length);
-#endif
-	up(&priv->wx_sem);
-	return ret;
-
-
-}
-
-static const iw_handler r8180_wx_handlers[] =	{
-	IW_HANDLER(SIOCGIWNAME,		r8180_wx_get_name),
-	IW_HANDLER(SIOCSIWNWID,		dummy),
-	IW_HANDLER(SIOCGIWNWID,		dummy),
-	IW_HANDLER(SIOCSIWFREQ,		r8180_wx_set_freq),
-	IW_HANDLER(SIOCGIWFREQ,		r8180_wx_get_freq),
-	IW_HANDLER(SIOCSIWMODE, 	r8180_wx_set_mode),
-	IW_HANDLER(SIOCGIWMODE,		r8180_wx_get_mode),
-	IW_HANDLER(SIOCSIWSENS,		r8180_wx_set_sens),
-	IW_HANDLER(SIOCGIWSENS,		r8180_wx_get_sens),
-	IW_HANDLER(SIOCGIWRANGE,	rtl8180_wx_get_range),
-	IW_HANDLER(SIOCSIWSPY,		dummy),
-	IW_HANDLER(SIOCGIWSPY,		dummy),
-	IW_HANDLER(SIOCSIWAP,		r8180_wx_set_wap),
-	IW_HANDLER(SIOCGIWAP,		r8180_wx_get_wap),
-	IW_HANDLER(SIOCSIWMLME,		r8180_wx_set_mlme),
-	IW_HANDLER(SIOCGIWAPLIST,	dummy),		/* deprecated */
-	IW_HANDLER(SIOCSIWSCAN,		r8180_wx_set_scan),
-	IW_HANDLER(SIOCGIWSCAN,		r8180_wx_get_scan),
-	IW_HANDLER(SIOCSIWESSID,	r8180_wx_set_essid),
-	IW_HANDLER(SIOCGIWESSID,	r8180_wx_get_essid),
-	IW_HANDLER(SIOCSIWNICKN,	dummy),
-	IW_HANDLER(SIOCGIWNICKN,	dummy),
-	IW_HANDLER(SIOCSIWRATE,		r8180_wx_set_rate),
-	IW_HANDLER(SIOCGIWRATE,		r8180_wx_get_rate),
-	IW_HANDLER(SIOCSIWRTS,		r8180_wx_set_rts),
-	IW_HANDLER(SIOCGIWRTS,		r8180_wx_get_rts),
-	IW_HANDLER(SIOCSIWFRAG,		r8180_wx_set_frag),
-	IW_HANDLER(SIOCGIWFRAG,		r8180_wx_get_frag),
-	IW_HANDLER(SIOCSIWTXPOW,	dummy),
-	IW_HANDLER(SIOCGIWTXPOW,	dummy),
-	IW_HANDLER(SIOCSIWRETRY,	r8180_wx_set_retry),
-	IW_HANDLER(SIOCGIWRETRY,	r8180_wx_get_retry),
-	IW_HANDLER(SIOCSIWENCODE,	r8180_wx_set_enc),
-	IW_HANDLER(SIOCGIWENCODE,	r8180_wx_get_enc),
-	IW_HANDLER(SIOCSIWPOWER,	r8180_wx_set_power),
-	IW_HANDLER(SIOCGIWPOWER,	r8180_wx_get_power),
-	IW_HANDLER(SIOCSIWGENIE,	r8180_wx_set_gen_ie),
-	IW_HANDLER(SIOCSIWAUTH,		r8180_wx_set_auth),
-	IW_HANDLER(SIOCSIWENCODEEXT,	r8180_wx_set_enc_ext),
-};
-
-static const struct iw_priv_args r8180_private_args[] = {
-	{
-		SIOCIWFIRSTPRIV + 0x0,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
-	},
-	{	SIOCIWFIRSTPRIV + 0x1,
-		0, 0, "dummy"
-
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x2,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beaconint"
-	},
-	{	SIOCIWFIRSTPRIV + 0x3,
-		0, 0, "dummy"
-
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x4,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
-
-	},
-	{	SIOCIWFIRSTPRIV + 0x5,
-		0, 0, "dummy"
-
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x6,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
-
-	},
-	{	SIOCIWFIRSTPRIV + 0x7,
-		0, 0, "dummy"
-
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x8,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setiwmode"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x9,
-		0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getiwmode"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0xA,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpreamble"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0xB,
-		0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpreamble"
-	},
-	{	SIOCIWFIRSTPRIV + 0xC,
-		0, 0, "dummy"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0xD,
-		0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getrssi"
-	},
-	{	SIOCIWFIRSTPRIV + 0xE,
-		0, 0, "dummy"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0xF,
-		0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getlinkqual"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x10,
-		0, 0, "resetstats"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x11,
-		0, 0, "dummy"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x12,
-		0, 0, "radioon"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x13,
-		0, 0, "radiooff"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x14,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setchannel"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x15,
-		0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x16,
-		0, 0, "dummy"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x17,
-		0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getversion"
-	},
-	{
-		SIOCIWFIRSTPRIV + 0x18,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setrate"
-	},
-};
-
-
-static iw_handler r8180_private_handler[] = {
-	r8180_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
-	dummy,
-	r8180_wx_set_beaconinterval,
-	dummy,
-	/* r8180_wx_set_monitor_type, */
-	r8180_wx_set_scan_type,
-	dummy,
-	r8180_wx_set_rawtx,
-	dummy,
-	r8180_wx_set_iwmode,
-	r8180_wx_get_iwmode,
-	r8180_wx_set_preamble,
-	r8180_wx_get_preamble,
-	dummy,
-	r8180_wx_get_siglevel,
-	dummy,
-	r8180_wx_get_sigqual,
-	r8180_wx_reset_stats,
-	dummy,/* r8180_wx_get_stats */
-	r8180_wx_radio_on,
-	r8180_wx_radio_off,
-	r8180_wx_set_channelplan,
-	r8180_wx_get_channelplan,
-	dummy,
-	r8180_wx_get_version,
-	r8180_wx_set_forcerate,
-};
-
-static inline int is_same_network(struct ieee80211_network *src,
-				  struct ieee80211_network *dst,
-				  struct ieee80211_device *ieee)
-{
-		/* A network is only a duplicate if the channel, BSSID, ESSID
-		 * and the capability field (in particular IBSS and BSS) all match.
-		 * We treat all <hidden> with the same BSSID and channel
-		 * as one network
-		 */
-		if (src->channel != dst->channel)
-			return 0;
-
-		if (memcmp(src->bssid, dst->bssid, ETH_ALEN) != 0)
-			return 0;
-
-		if (ieee->iw_mode != IW_MODE_INFRA) {
-			if (src->ssid_len != dst->ssid_len)
-				return 0;
-			if (memcmp(src->ssid, dst->ssid, src->ssid_len) != 0)
-				return 0;
-		}
-
-		if ((src->capability & WLAN_CAPABILITY_IBSS) !=
-		    (dst->capability & WLAN_CAPABILITY_IBSS))
-			return 0;
-		if ((src->capability & WLAN_CAPABILITY_BSS) !=
-		    (dst->capability & WLAN_CAPABILITY_BSS))
-			return 0;
-
-		return 1;
-}
-
-/* WB modified to show signal to GUI on 18-01-2008 */
-static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee80211;
-	struct iw_statistics *wstats = &priv->wstats;
-	int tmp_level = 0;
-	int tmp_qual = 0;
-	int tmp_noise = 0;
-
-	if (ieee->state < IEEE80211_LINKED)	{
-		wstats->qual.qual = 0;
-		wstats->qual.level = 0;
-		wstats->qual.noise = 0;
-		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-		return wstats;
-	}
-
-	tmp_level = (&ieee->current_network)->stats.signal;
-	tmp_qual = (&ieee->current_network)->stats.signalstrength;
-	tmp_noise = (&ieee->current_network)->stats.noise;
-
-	wstats->qual.level = tmp_level;
-	wstats->qual.qual = tmp_qual;
-	wstats->qual.noise = tmp_noise;
-	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-	return wstats;
-}
-
-struct iw_handler_def  r8180_wx_handlers_def = {
-	.standard = r8180_wx_handlers,
-	.num_standard = ARRAY_SIZE(r8180_wx_handlers),
-	.private = r8180_private_handler,
-	.num_private = ARRAY_SIZE(r8180_private_handler),
-	.num_private_args = sizeof(r8180_private_args) / sizeof(struct iw_priv_args),
-	.get_wireless_stats = r8180_get_wireless_stats,
-	.private_args = (struct iw_priv_args *)r8180_private_args,
-};
-
-
diff --git a/drivers/staging/rtl8187se/r8180_wx.h b/drivers/staging/rtl8187se/r8180_wx.h
deleted file mode 100644
index d471520ac772..000000000000
--- a/drivers/staging/rtl8187se/r8180_wx.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-	This is part of rtl8180 OpenSource driver - v 0.3
-	Copyright (C) Andrea Merello 2004  <andrea.merello@gmail.com>
-	Released under the terms of GPL (General Public Licence)
-
-	Parts of this driver are based on the GPL part of the official realtek driver
-	Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
-	Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
-	We want to thanks the Authors of such projects and the Ndiswrapper project Authors.
-*/
-
-/* this file (will) contains wireless extension handlers*/
-
-#ifndef R8180_WX_H
-#define R8180_WX_H
-#include <linux/wireless.h>
-#include "ieee80211/ieee80211.h"
-extern struct iw_handler_def r8180_wx_handlers_def;
-
-#endif
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
deleted file mode 100644
index cc6f100814f3..000000000000
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ /dev/null
@@ -1,1464 +0,0 @@
-/*
- * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
- *
- * Module Name:
- *	r8185b_init.c
- *
- * Abstract:
- *	Hardware Initialization and Hardware IO for RTL8185B
- *
- * Major Change History:
- *	When		Who				What
- *	----------	---------------		-------------------------------
- *	2006-11-15	Xiong			Created
- *
- * Notes:
- *	This file is ported from RTL8185B Windows driver.
- *
- *
- */
-
-/*--------------------------Include File------------------------------------*/
-#include <linux/spinlock.h>
-#include "r8180_hw.h"
-#include "r8180.h"
-#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */
-#include "r8180_93cx6.h"   /* Card EEPROM */
-#include "r8180_wx.h"
-#include "ieee80211/dot11d.h"
-/* #define CONFIG_RTL8180_IO_MAP */
-#define TC_3W_POLL_MAX_TRY_CNT 5
-
-static u8 MAC_REG_TABLE[][2] =	{
-	/*
-	 * PAGE 0:
-	 * 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in
-	 * HwConfigureRTL8185()
-	 * 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185().
-	 * 0x1F0~0x1F8  set in MacConfig_85BASIC()
-	 */
-	{0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42},
-	{0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03},
-	{0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03},
-	{0x94, 0x0F}, {0x95, 0x32},
-	{0x96, 0x00}, {0x97, 0x07}, {0xb4, 0x22}, {0xdb, 0x00},
-	{0xf0, 0x32}, {0xf1, 0x32}, {0xf2, 0x00}, {0xf3, 0x00}, {0xf4, 0x32},
-	{0xf5, 0x43}, {0xf6, 0x00}, {0xf7, 0x00}, {0xf8, 0x46}, {0xf9, 0xa4},
-	{0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00},
-	{0xff, 0x00},
-
-	/*
-	 * PAGE 1:
-	 * For Flextronics system Logo PCIHCT failure:
-	 * 0x1C4~0x1CD set no-zero value to avoid PCI configuration
-	 * space 0x45[7]=1
-	 */
-	{0x5e, 0x01},
-	{0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24},
-	{0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF},
-	{0x82, 0xFF}, {0x83, 0x03},
-	/* lzm add 080826 */
-	{0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22},
-	/* lzm add 080826 */
-	{0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22},
-	{0xe2, 0x00},
-
-
-	/* PAGE 2: */
-	{0x5e, 0x02},
-	{0x0c, 0x04}, {0x4c, 0x30}, {0x4d, 0x08}, {0x50, 0x05}, {0x51, 0xf5},
-	{0x52, 0x04}, {0x53, 0xa0}, {0x54, 0xff}, {0x55, 0xff}, {0x56, 0xff},
-	{0x57, 0xff}, {0x58, 0x08}, {0x59, 0x08}, {0x5a, 0x08}, {0x5b, 0x08},
-	{0x60, 0x08}, {0x61, 0x08}, {0x62, 0x08}, {0x63, 0x08}, {0x64, 0x2f},
-	{0x8c, 0x3f}, {0x8d, 0x3f}, {0x8e, 0x3f},
-	{0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff},
-	{0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00},
-
-	/* PAGE 0: */
-	{0x5e, 0x00}, {0x9f, 0x03}
-	};
-
-
-static u8  ZEBRA_AGC[] = {
-	0,
-	0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76,
-	0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A,
-	0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x48, 0x47, 0x46, 0x45,
-	0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
-	0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
-	0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x17, 0x18, 0x18,
-	0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
-	0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22,
-	0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
-	0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
-	};
-
-static u32 ZEBRA_RF_RX_GAIN_TABLE[] = {
-	0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
-	0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
-	0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
-	0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
-	0x0183, 0x0163, 0x0143, 0x0123, 0x0103
-	};
-
-static u8 OFDM_CONFIG[]	= {
-	/* OFDM reg0x06[7:0]=0xFF: Enable power saving mode in RX */
-	/* OFDM reg0x3C[4]=1'b1: Enable RX power saving mode */
-	/* ofdm 0x3a = 0x7b ,(original : 0xfb) For ECS shielding room TP test */
-	/* 0x00	*/
-	0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
-	0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
-	/* 0x10	*/
-	0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
-	0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
-	/* 0x20	*/
-	0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
-	0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
-	/* 0x30	*/
-	0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
-	0xD8, 0x3C, 0x7B, 0x10, 0x10
-	};
-
-	/*---------------------------------------------------------------
-	 *	Hardware IO
-	 *	the code is ported from Windows source code
-	 *---------------------------------------------------------------
-	 */
-
-static u8 PlatformIORead1Byte(struct net_device *dev, u32 offset)
-{
-	return read_nic_byte(dev, offset);
-}
-
-static void PlatformIOWrite1Byte(struct net_device *dev, u32 offset, u8 data)
-{
-	write_nic_byte(dev, offset, data);
-	/*
-	 * To make sure write operation is completed,
-	 * 2005.11.09, by rcnjko.
-	 */
-	read_nic_byte(dev, offset);
-}
-
-static void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data)
-{
-	write_nic_word(dev, offset, data);
-	/*
-	 * To make sure write operation is completed,
-	 *  2005.11.09, by rcnjko.
-	 */
-	read_nic_word(dev, offset);
-}
-
-static void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data)
-{
-	if (offset == PhyAddr) {
-		/* For Base Band configuration. */
-		unsigned char	cmdByte;
-		unsigned long	dataBytes;
-		unsigned char	idx;
-		u8		u1bTmp;
-
-		cmdByte = (u8)(data & 0x000000ff);
-		dataBytes = data>>8;
-
-		/*
-		 *	071010, rcnjko:
-		 *	The critical section is only BB read/write race
-		 *	condition. Assumption:
-		 *	1. We assume NO one will access BB at DIRQL, otherwise,
-		 *	system will crash for
-		 *	acquiring the spinlock in such context.
-		 *	2. PlatformIOWrite4Byte() MUST NOT be recursive.
-		 */
-		/* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */
-
-		for (idx = 0; idx < 30; idx++) {
-			/* Make sure command bit is clear before access it. */
-			u1bTmp = PlatformIORead1Byte(dev, PhyAddr);
-			if ((u1bTmp & BIT7) == 0)
-				break;
-			else
-				mdelay(10);
-		}
-
-		for (idx = 0; idx < 3; idx++)
-			PlatformIOWrite1Byte(dev, offset+1+idx,
-					     ((u8 *)&dataBytes)[idx]);
-
-		write_nic_byte(dev, offset, cmdByte);
-
-		/* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */
-	} else {
-		write_nic_dword(dev, offset, data);
-		/*
-		 * To make sure write operation is completed, 2005.11.09,
-		 *  by rcnjko.
-		 */
-		read_nic_dword(dev, offset);
-	}
-}
-
-static void SetOutputEnableOfRfPins(struct net_device *dev)
-{
-	write_nic_word(dev, RFPinsEnable, 0x1bff);
-}
-
-static bool HwHSSIThreeWire(struct net_device *dev,
-			    u8 *pDataBuf,
-			    bool write)
-{
-	u8	TryCnt;
-	u8	u1bTmp;
-
-	/* Check if WE and RE are cleared. */
-	for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
-		u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
-		if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0)
-			break;
-
-		udelay(10);
-	}
-	if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) {
-		netdev_err(dev,
-			   "HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n",
-			   u1bTmp);
-	return false;
-	}
-
-	/* RTL8187S HSSI Read/Write Function */
-	u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
-	u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */
-	write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
-
-	/* jong: HW SI read must set reg84[3]=0. */
-	u1bTmp = read_nic_byte(dev, RFPinsSelect);
-	u1bTmp &= ~BIT3;
-	write_nic_byte(dev, RFPinsSelect, u1bTmp);
-	/*  Fill up data buffer for write operation. */
-
-	/* SI - reg274[3:0] : RF register's Address */
-	if (write)
-		write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
-	else
-		write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
-
-	/* Set up command: WE or RE. */
-	if (write)
-		write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE);
-	else
-		write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE);
-
-
-	/* Check if DONE is set. */
-	for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
-		u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
-		if (u1bTmp & SW_3W_CMD1_DONE)
-			break;
-
-		udelay(10);
-	}
-
-	write_nic_byte(dev, SW_3W_CMD1, 0);
-
-	/* Read back data for read operation. */
-	if (!write) {
-		/* Serial Interface : reg363_362[11:0] */
-		*((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ);
-		*((u16 *)pDataBuf) &= 0x0FFF;
-	}
-
-	return true;
-}
-
-void RF_WriteReg(struct net_device *dev, u8 offset, u16 data)
-{
-	u16 reg = (data << 4) | (offset & 0x0f);
-	HwHSSIThreeWire(dev, (u8 *)&reg, true);
-}
-
-u16 RF_ReadReg(struct net_device *dev, u8 offset)
-{
-	u16 reg = offset & 0x0f;
-	HwHSSIThreeWire(dev, (u8 *)&reg, false);
-	return reg;
-}
-
-static u8 ReadBBPortUchar(struct net_device *dev, u32 addr)
-{
-	PlatformIOWrite4Byte(dev, PhyAddr, addr & 0xffffff7f);
-	return PlatformIORead1Byte(dev, PhyDataR);
-}
-
-/* by Owen on 04/07/14 for writing BB register successfully */
-static void WriteBBPortUchar(struct net_device *dev, u32 Data)
-{
-	PlatformIOWrite4Byte(dev, PhyAddr, Data);
-	ReadBBPortUchar(dev, Data);
-}
-
-/*
- *	Description:
- *	Perform Antenna settings with antenna diversity on 87SE.
- *		Created by Roger, 2008.01.25.
- */
-bool SetAntennaConfig87SE(struct net_device *dev,
-			  u8   DefaultAnt, /* 0: Main, 1: Aux. */
-			  bool bAntDiversity) /* 1:Enable, 0: Disable. */
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	bool   bAntennaSwitched = true;
-	/* 0x00 = disabled, 0x80 = enabled */
-	u8	ant_diversity_offset = 0x00;
-
-	/*
-	 * printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n",
-	 * DefaultAnt, bAntDiversity);
-	 */
-
-	/* Threshold for antenna diversity. */
-	write_phy_cck(dev, 0x0c, 0x09); /* Reg0c : 09 */
-
-	if (bAntDiversity)	/*	Enable Antenna Diversity. */
-		ant_diversity_offset = 0x80;
-
-	if (DefaultAnt == 1) { /* aux Antenna */
-		/* Mac register, aux antenna */
-		write_nic_byte(dev, ANTSEL, 0x00);
-
-		/* Config CCK RX antenna. */
-		write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
-
-		/* Reg01 : 47 | ant_diversity_offset */
-		write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset);
-
-		/* Config OFDM RX antenna. */
-		write_phy_ofdm(dev, 0x0D, 0x54);	/* Reg0d : 54 */
-		/* Reg18 : 32 */
-		write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset);
-	} else { /* main Antenna */
-		/* Mac register, main antenna */
-		write_nic_byte(dev, ANTSEL, 0x03);
-
-		/* Config CCK RX antenna.	*/
-		write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
-		/* Reg01 : 47 */
-		write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset);
-
-		/* Config OFDM RX antenna. */
-		write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */
-		/*Reg18 : 32 */
-		write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset);
-	}
-	priv->CurrAntennaIndex = DefaultAnt; /* Update default settings. */
-	return	bAntennaSwitched;
-}
-/*
- *--------------------------------------------------------------
- *		Hardware Initialization.
- *		the code is ported from Windows source code
- *--------------------------------------------------------------
- */
-
-static void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev)
-{
-
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u32			i;
-	u32	addr, data;
-	u32 u4bRegOffset, u4bRegValue;
-	u16 u4bRF23, u4bRF24;
-	u8			u1b24E;
-	int d_cut = 0;
-
-
-/*
- *===========================================================================
- *	87S_PCIE :: RADIOCFG.TXT
- *===========================================================================
- */
-
-
-	/* Page1 : reg16-reg30 */
-	RF_WriteReg(dev, 0x00, 0x013f);		mdelay(1); /* switch to page1 */
-	u4bRF23 = RF_ReadReg(dev, 0x08);	mdelay(1);
-	u4bRF24 = RF_ReadReg(dev, 0x09);	mdelay(1);
-
-	if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) {
-		d_cut = 1;
-		netdev_info(dev, "card type changed from C- to D-cut\n");
-	}
-
-	/* Page0 : reg0-reg15 */
-
-	RF_WriteReg(dev, 0x00, 0x009f);		mdelay(1);/* 1	*/
-	RF_WriteReg(dev, 0x01, 0x06e0);		mdelay(1);
-	RF_WriteReg(dev, 0x02, 0x004d);		mdelay(1);/* 2	*/
-	RF_WriteReg(dev, 0x03, 0x07f1);		mdelay(1);/* 3	*/
-	RF_WriteReg(dev, 0x04, 0x0975);		mdelay(1);
-	RF_WriteReg(dev, 0x05, 0x0c72);		mdelay(1);
-	RF_WriteReg(dev, 0x06, 0x0ae6);		mdelay(1);
-	RF_WriteReg(dev, 0x07, 0x00ca);		mdelay(1);
-	RF_WriteReg(dev, 0x08, 0x0e1c);		mdelay(1);
-	RF_WriteReg(dev, 0x09, 0x02f0);		mdelay(1);
-	RF_WriteReg(dev, 0x0a, 0x09d0);		mdelay(1);
-	RF_WriteReg(dev, 0x0b, 0x01ba);		mdelay(1);
-	RF_WriteReg(dev, 0x0c, 0x0640);		mdelay(1);
-	RF_WriteReg(dev, 0x0d, 0x08df);		mdelay(1);
-	RF_WriteReg(dev, 0x0e, 0x0020);		mdelay(1);
-	RF_WriteReg(dev, 0x0f, 0x0990);		mdelay(1);
-
-	/*  Page1 : reg16-reg30 */
-	RF_WriteReg(dev, 0x00, 0x013f);		mdelay(1);
-	RF_WriteReg(dev, 0x03, 0x0806);		mdelay(1);
-	RF_WriteReg(dev, 0x04, 0x03a7);		mdelay(1);
-	RF_WriteReg(dev, 0x05, 0x059b);		mdelay(1);
-	RF_WriteReg(dev, 0x06, 0x0081);		mdelay(1);
-	RF_WriteReg(dev, 0x07, 0x01A0);		mdelay(1);
-/*
- * Don't write RF23/RF24 to make a difference between 87S C cut and D cut.
- * asked by SD3 stevenl.
- */
-	RF_WriteReg(dev, 0x0a, 0x0001);		mdelay(1);
-	RF_WriteReg(dev, 0x0b, 0x0418);		mdelay(1);
-
-	if (d_cut) {
-		RF_WriteReg(dev, 0x0c, 0x0fbe);		mdelay(1);
-		RF_WriteReg(dev, 0x0d, 0x0008);		mdelay(1);
-		/* RX LO buffer */
-		RF_WriteReg(dev, 0x0e, 0x0807);		mdelay(1);
-	} else {
-		RF_WriteReg(dev, 0x0c, 0x0fbe);		mdelay(1);
-		RF_WriteReg(dev, 0x0d, 0x0008);		mdelay(1);
-		/* RX LO buffer */
-		RF_WriteReg(dev, 0x0e, 0x0806);		mdelay(1);
-	}
-
-	RF_WriteReg(dev, 0x0f, 0x0acc);		mdelay(1);
-	RF_WriteReg(dev, 0x00, 0x01d7);		mdelay(1); /* 6 */
-	RF_WriteReg(dev, 0x03, 0x0e00);		mdelay(1);
-	RF_WriteReg(dev, 0x04, 0x0e50);		mdelay(1);
-
-	for (i = 0; i <= 36; i++) {
-		RF_WriteReg(dev, 0x01, i);		mdelay(1);
-		RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1);
-	}
-
-	RF_WriteReg(dev, 0x05, 0x0203);		mdelay(1); /* 203, 343 */
-	RF_WriteReg(dev, 0x06, 0x0200);		mdelay(1); /* 400 */
-	/* switch to reg16-reg30, and HSSI disable 137 */
-	RF_WriteReg(dev, 0x00, 0x0137);		mdelay(1);
-	mdelay(10); /* Deay 10 ms. */		/* 0xfd */
-
-	/* Z4 synthesizer loop filter setting, 392 */
-	RF_WriteReg(dev, 0x0d, 0x0008);		mdelay(1);
-	mdelay(10); /* Deay 10 ms. */		/* 0xfd */
-
-	/* switch to reg0-reg15, and HSSI disable */
-	RF_WriteReg(dev, 0x00, 0x0037);		mdelay(1);
-	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
-
-	/* CBC on, Tx Rx disable, High gain */
-	RF_WriteReg(dev, 0x04, 0x0160);		mdelay(1);
-	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
-
-	/* Z4 setted channel 1 */
-	RF_WriteReg(dev, 0x07, 0x0080);		mdelay(1);
-	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
-
-	RF_WriteReg(dev, 0x02, 0x088D);		mdelay(1); /* LC calibration */
-	mdelay(200); /* Deay 200 ms. */		/* 0xfd	*/
-	mdelay(10);  /* Deay 10 ms. */		/* 0xfd	*/
-	mdelay(10);  /* Deay 10 ms. */		/* 0xfd	*/
-
-	/* switch to reg16-reg30 137, and HSSI disable 137 */
-	RF_WriteReg(dev, 0x00, 0x0137);		mdelay(1);
-	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
-
-	RF_WriteReg(dev, 0x07, 0x0000);		mdelay(1);
-	RF_WriteReg(dev, 0x07, 0x0180);		mdelay(1);
-	RF_WriteReg(dev, 0x07, 0x0220);		mdelay(1);
-	RF_WriteReg(dev, 0x07, 0x03E0);		mdelay(1);
-
-	/* DAC calibration off 20070702	*/
-	RF_WriteReg(dev, 0x06, 0x00c1);		mdelay(1);
-	RF_WriteReg(dev, 0x0a, 0x0001);		mdelay(1);
-	/* For crystal calibration, added by Roger, 2007.12.11. */
-	if (priv->bXtalCalibration) { /* reg 30.	*/
-	 /*
-	  *	enable crystal calibration.
-	  *	RF Reg[30], (1)Xin:[12:9], Xout:[8:5],  addr[4:0].
-	  *	(2)PA Pwr delay timer[15:14], default: 2.4us,
-	  *	set BIT15=0
-	  *	(3)RF signal on/off when calibration[13], default: on,
-	  *	set BIT13=0.
-	  *	So we should minus 4 BITs offset.
-	  */
-		RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) |
-			    (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1);
-		netdev_info(dev, "ZEBRA_Config_85BASIC_HardCode(): (%02x)\n",
-		      (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) |
-		       BIT11 | BIT9);
-	} else {
-		/* using default value. Xin=6, Xout=6.	*/
-		RF_WriteReg(dev, 0x0f, 0x0acc);		mdelay(1);
-	}
-	/* switch to reg0-reg15, and HSSI enable */
-	RF_WriteReg(dev, 0x00, 0x00bf);		mdelay(1);
-	/* Rx BB start calibration, 00c//+edward */
-	RF_WriteReg(dev, 0x0d, 0x08df);		mdelay(1);
-	/* temperature meter off */
-	RF_WriteReg(dev, 0x02, 0x004d);		mdelay(1);
-	RF_WriteReg(dev, 0x04, 0x0975);		mdelay(1); /* Rx mode */
-	mdelay(10);	/* Deay 10 ms.*/	/* 0xfe	*/
-	mdelay(10);	/* Deay 10 ms.*/	/* 0xfe	*/
-	mdelay(10);	/* Deay 10 ms.*/	/* 0xfe	*/
-	/* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x00, 0x0197);		mdelay(1);
-	/* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x05, 0x05ab);		mdelay(1);
-	/* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x00, 0x009f);		mdelay(1);
-	/* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x01, 0x0000);		mdelay(1);
-	/* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x02, 0x0000);		mdelay(1);
-	/* power save parameters. */
-	u1b24E = read_nic_byte(dev, 0x24E);
-	write_nic_byte(dev, 0x24E, (u1b24E & (~(BIT5|BIT6))));
-
-	/*======================================================================
-	 *
-	 *======================================================================
-	 * CCKCONF.TXT
-	 *======================================================================
-	 *
-	 *	[POWER SAVE] Power Saving Parameters by jong. 2007-11-27
-	 *	CCK reg0x00[7]=1'b1 :power saving for TX (default)
-	 *	CCK reg0x00[6]=1'b1: power saving for RX (default)
-	 *	CCK reg0x06[4]=1'b1: turn off channel estimation related
-	 *	circuits if not doing channel estimation.
-	 *	CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1
-	 *	CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0
-	 */
-
-	write_phy_cck(dev, 0x00, 0xc8);
-	write_phy_cck(dev, 0x06, 0x1c);
-	write_phy_cck(dev, 0x10, 0x78);
-	write_phy_cck(dev, 0x2e, 0xd0);
-	write_phy_cck(dev, 0x2f, 0x06);
-	write_phy_cck(dev, 0x01, 0x46);
-
-	/* power control */
-	write_nic_byte(dev, CCK_TXAGC, 0x10);
-	write_nic_byte(dev, OFDM_TXAGC, 0x1B);
-	write_nic_byte(dev, ANTSEL, 0x03);
-
-
-
-	/*
-	 *======================================================================
-	 *	AGC.txt
-	 *======================================================================
-	 */
-
-	write_phy_ofdm(dev, 0x00, 0x12);
-
-	for (i = 0; i < 128; i++) {
-
-		data = ZEBRA_AGC[i+1];
-		data = data << 8;
-		data = data | 0x0000008F;
-
-		addr = i + 0x80; /* enable writing AGC table */
-		addr = addr << 8;
-		addr = addr | 0x0000008E;
-
-		WriteBBPortUchar(dev, data);
-		WriteBBPortUchar(dev, addr);
-		WriteBBPortUchar(dev, 0x0000008E);
-	}
-
-	PlatformIOWrite4Byte(dev, PhyAddr, 0x00001080);	/* Annie, 2006-05-05 */
-
-	/*
-	 *======================================================================
-	 *
-	 *======================================================================
-	 * OFDMCONF.TXT
-	 *======================================================================
-	 */
-
-	for (i = 0; i < 60; i++) {
-		u4bRegOffset = i;
-		u4bRegValue = OFDM_CONFIG[i];
-
-		WriteBBPortUchar(dev,
-				(0x00000080 |
-				(u4bRegOffset & 0x7f) |
-				((u4bRegValue & 0xff) << 8)));
-	}
-
-	/*
-	 *======================================================================
-	 * by amy for antenna
-	 *======================================================================
-	 */
-	/*
-	 * Config Sw/Hw  Combinational Antenna Diversity. Added by Roger,
-	 * 2008.02.26.
-	 */
-	SetAntennaConfig87SE(dev, priv->bDefaultAntenna1,
-			     priv->bSwAntennaDiverity);
-}
-
-
-void UpdateInitialGain(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	/* lzm add 080826 */
-	if (priv->eRFPowerState != RF_ON) {
-		/*	Don't access BB/RF under disable PLL situation.
-		 *	RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain -
-		 *	pHalData->eRFPowerState!=RF_ON\n"));
-		 *	Back to the original state
-		 */
-		priv->InitialGain = priv->InitialGainBackUp;
-		return;
-	}
-
-	switch (priv->InitialGain) {
-	case 1: /* m861dBm */
-		write_phy_ofdm(dev, 0x17, 0x26);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
-		break;
-
-	case 2: /* m862dBm */
-		write_phy_ofdm(dev, 0x17, 0x36);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
-		break;
-
-	case 3: /* m863dBm */
-		write_phy_ofdm(dev, 0x17, 0x36);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
-		break;
-
-	case 4: /* m864dBm */
-		write_phy_ofdm(dev, 0x17, 0x46);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
-		break;
-
-	case 5: /* m82dBm */
-		write_phy_ofdm(dev, 0x17, 0x46);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0x96);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
-		break;
-
-	case 6: /* m78dBm */
-		write_phy_ofdm(dev, 0x17, 0x56);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0x96);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
-		break;
-
-	case 7: /* m74dBm */
-		write_phy_ofdm(dev, 0x17, 0x56);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0xa6);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
-		break;
-
-	case 8:
-		write_phy_ofdm(dev, 0x17, 0x66);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0xb6);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
-		break;
-
-	default: /* MP */
-		write_phy_ofdm(dev, 0x17, 0x26);	mdelay(1);
-		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-		write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
-		break;
-	}
-}
-/*
- *	Description:
- *		Tx Power tracking mechanism routine on 87SE.
- *	Created by Roger, 2007.12.11.
- */
-static void InitTxPwrTracking87SE(struct net_device *dev)
-{
-	u32	u4bRfReg;
-
-	u4bRfReg = RF_ReadReg(dev, 0x02);
-
-	/* Enable Thermal meter indication.	*/
-	RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN);		mdelay(1);
-}
-
-static void PhyConfig8185(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-		write_nic_dword(dev, RCR, priv->ReceiveConfig);
-	   priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03;
-	/*  RF config */
-	ZEBRA_Config_85BASIC_HardCode(dev);
-	/* Set default initial gain state to 4, approved by SD3 DZ, by Bruce,
-	 * 2007-06-06.
-	 */
-	if (priv->bDigMechanism) {
-		if (priv->InitialGain == 0)
-			priv->InitialGain = 4;
-	}
-
-	/*
-	 *	Enable thermal meter indication to implement TxPower tracking
-	 *	on 87SE. We initialize thermal meter here to avoid unsuccessful
-	 *	configuration. Added by Roger, 2007.12.11.
-	 */
-	if (priv->bTxPowerTrack)
-		InitTxPwrTracking87SE(dev);
-
-	priv->InitialGainBackUp = priv->InitialGain;
-	UpdateInitialGain(dev);
-
-	return;
-}
-
-static void HwConfigureRTL8185(struct net_device *dev)
-{
-	/*
-	 * RTL8185_TODO: Determine Retrylimit, TxAGC,
-	 * AutoRateFallback control.
-	 */
-	u8 bUNIVERSAL_CONTROL_RL = 0;
-	u8 bUNIVERSAL_CONTROL_AGC = 1;
-	u8 bUNIVERSAL_CONTROL_ANT = 1;
-	u8 bAUTO_RATE_FALLBACK_CTL = 1;
-	u8 val8;
-	write_nic_word(dev, BRSR, 0x0fff);
-	/* Retry limit */
-	val8 = read_nic_byte(dev, CW_CONF);
-
-	if (bUNIVERSAL_CONTROL_RL)
-		val8 = val8 & 0xfd;
-	else
-		val8 = val8 | 0x02;
-
-	write_nic_byte(dev, CW_CONF, val8);
-
-	/* Tx AGC */
-	val8 = read_nic_byte(dev, TXAGC_CTL);
-	if (bUNIVERSAL_CONTROL_AGC) {
-		write_nic_byte(dev, CCK_TXAGC, 128);
-		write_nic_byte(dev, OFDM_TXAGC, 128);
-		val8 = val8 & 0xfe;
-	} else {
-		val8 = val8 | 0x01;
-	}
-
-
-	write_nic_byte(dev, TXAGC_CTL, val8);
-
-	/* Tx Antenna including Feedback control */
-	val8 = read_nic_byte(dev, TXAGC_CTL);
-
-	if (bUNIVERSAL_CONTROL_ANT) {
-		write_nic_byte(dev, ANTSEL, 0x00);
-		val8 = val8 & 0xfd;
-	} else {
-		val8 = val8 & (val8|0x02); /* xiong-2006-11-15 */
-	}
-
-	write_nic_byte(dev, TXAGC_CTL, val8);
-
-	/* Auto Rate fallback control	*/
-	val8 = read_nic_byte(dev, RATE_FALLBACK);
-	val8 &= 0x7c;
-	if (bAUTO_RATE_FALLBACK_CTL) {
-		val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1;
-
-		/* <RJ_TODO_8185B> We shall set up the ARFR according
-		 * to user's setting.
-		 */
-		PlatformIOWrite2Byte(dev, ARFR, 0x0fff); /* set 1M ~ 54Mbps. */
-	}
-	write_nic_byte(dev, RATE_FALLBACK, val8);
-}
-
-static void MacConfig_85BASIC_HardCode(struct net_device *dev)
-{
-	/*
-	 *======================================================================
-	 * MACREG.TXT
-	 *======================================================================
-	 */
-	int nLinesRead = 0;
-	u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0;
-	int i;
-
-	nLinesRead = sizeof(MAC_REG_TABLE)/2;
-
-	for (i = 0; i < nLinesRead; i++) { /* nLinesRead=101 */
-		u4bRegOffset = MAC_REG_TABLE[i][0];
-		u4bRegValue = MAC_REG_TABLE[i][1];
-
-				if (u4bRegOffset == 0x5e)
-					u4bPageIndex = u4bRegValue;
-				else
-					u4bRegOffset |= (u4bPageIndex << 8);
-
-		write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue);
-	}
-	/* ================================================================= */
-}
-
-static void MacConfig_85BASIC(struct net_device *dev)
-{
-
-	u8			u1DA;
-	MacConfig_85BASIC_HardCode(dev);
-
-	/* ================================================================= */
-
-	/* Follow TID_AC_MAP of WMac. */
-	write_nic_word(dev, TID_AC_MAP, 0xfa50);
-
-	/* Interrupt Migration, Jong suggested we use set 0x0000 first,
-	 * 2005.12.14, by rcnjko.
-	 */
-	write_nic_word(dev, IntMig, 0x0000);
-
-	/* Prevent TPC to cause CRC error. Added by Annie, 2006-06-10. */
-	PlatformIOWrite4Byte(dev, 0x1F0, 0x00000000);
-	PlatformIOWrite4Byte(dev, 0x1F4, 0x00000000);
-	PlatformIOWrite1Byte(dev, 0x1F8, 0x00);
-
-	/* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */
-
-	/*
-	 *  power save parameter based on
-	 * "87SE power save parameters 20071127.doc", as follow.
-	 */
-
-	/* Enable DA10 TX power saving */
-	u1DA = read_nic_byte(dev, PHYPR);
-	write_nic_byte(dev, PHYPR, (u1DA | BIT2));
-
-	/* POWER: */
-	write_nic_word(dev, 0x360, 0x1000);
-	write_nic_word(dev, 0x362, 0x1000);
-
-	/* AFE. */
-	write_nic_word(dev, 0x370, 0x0560);
-	write_nic_word(dev, 0x372, 0x0560);
-	write_nic_word(dev, 0x374, 0x0DA4);
-	write_nic_word(dev, 0x376, 0x0DA4);
-	write_nic_word(dev, 0x378, 0x0560);
-	write_nic_word(dev, 0x37A, 0x0560);
-	write_nic_word(dev, 0x37C, 0x00EC);
-	write_nic_word(dev, 0x37E, 0x00EC); /* +edward */
-	write_nic_byte(dev, 0x24E, 0x01);
-}
-
-static u8 GetSupportedWirelessMode8185(struct net_device *dev)
-{
-	return WIRELESS_MODE_B | WIRELESS_MODE_G;
-}
-
-static void
-ActUpdateChannelAccessSetting(struct net_device *dev,
-			      enum wireless_mode mode,
-			      struct chnl_access_setting *chnl_access_setting)
-{
-	AC_CODING	eACI;
-
-	/*
-	 *	<RJ_TODO_8185B>
-	 *	TODO: We still don't know how to set up these registers,
-	 *	just follow WMAC to verify 8185B FPAG.
-	 *
-	 *	<RJ_TODO_8185B>
-	 *	Jong said CWmin/CWmax register are not functional in 8185B,
-	 *	so we shall fill channel access realted register into AC
-	 *	parameter registers,
-	 *	even in nQBss.
-	 */
-
-	/* Suggested by Jong, 2005.12.08. */
-	chnl_access_setting->sifs_timer = 0x22;
-	chnl_access_setting->difs_timer = 0x1C; /* 2006.06.02, by rcnjko. */
-	chnl_access_setting->slot_time_timer = 9; /* 2006.06.02, by rcnjko. */
-	/*
-	 * Suggested by wcchu, it is the default value of EIFS register,
-	 * 2005.12.08.
-	 */
-	chnl_access_setting->eifs_timer = 0x5B;
-	chnl_access_setting->cwmin_index = 3; /* 2006.06.02, by rcnjko. */
-	chnl_access_setting->cwmax_index = 7; /* 2006.06.02, by rcnjko. */
-
-	write_nic_byte(dev, SIFS, chnl_access_setting->sifs_timer);
-	/*
-	 * Rewrited from directly use PlatformEFIOWrite1Byte(),
-	 * by Annie, 2006-03-29.
-	 */
-	write_nic_byte(dev, SLOT, chnl_access_setting->slot_time_timer);
-
-	write_nic_byte(dev, EIFS, chnl_access_setting->eifs_timer);
-
-	/*
-	 * <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS
-	 * register, 2005.12.08.
-	 */
-	write_nic_byte(dev, AckTimeOutReg, 0x5B);
-
-	for (eACI = 0; eACI < AC_MAX; eACI++)
-		write_nic_byte(dev, ACM_CONTROL, 0);
-}
-
-static void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode)
-{
-	struct  r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	struct  ieee80211_device *ieee = priv->ieee80211;
-	u8	btSupportedWirelessMode = GetSupportedWirelessMode8185(dev);
-
-	if ((btWirelessMode & btSupportedWirelessMode) == 0)	{
-		/*
-		 * Don't switch to unsupported wireless mode, 2006.02.15,
-		 * by rcnjko.
-		 */
-		DMESGW("ActSetWirelessMode8185(): WirelessMode(%d) is not supported (%d)!\n",
-			btWirelessMode, btSupportedWirelessMode);
-		return;
-	}
-
-	/* 1. Assign wireless mode to switch if necessary. */
-	if (btWirelessMode == WIRELESS_MODE_AUTO) {
-		if ((btSupportedWirelessMode & WIRELESS_MODE_A)) {
-			btWirelessMode = WIRELESS_MODE_A;
-		} else if (btSupportedWirelessMode & WIRELESS_MODE_G) {
-				btWirelessMode = WIRELESS_MODE_G;
-
-		} else if ((btSupportedWirelessMode & WIRELESS_MODE_B))	{
-				btWirelessMode = WIRELESS_MODE_B;
-		} else {
-			DMESGW("ActSetWirelessMode8185(): No valid wireless mode supported, btSupportedWirelessMode(%x)!!!\n",
-			       btSupportedWirelessMode);
-			btWirelessMode = WIRELESS_MODE_B;
-		}
-	}
-
-	/*
-	 * 2. Swtich band: RF or BB specific actions,
-	 * for example, refresh tables in omc8255, or change initial gain if
-	 * necessary. Nothing to do for Zebra to switch band. Update current
-	 * wireless mode if we switch to specified band successfully.
-	 */
-
-	ieee->mode = (enum wireless_mode)btWirelessMode;
-
-	/* 3. Change related setting. */
-	if (ieee->mode == WIRELESS_MODE_A)
-		DMESG("WIRELESS_MODE_A\n");
-	else if (ieee->mode == WIRELESS_MODE_B)
-		DMESG("WIRELESS_MODE_B\n");
-	else if (ieee->mode == WIRELESS_MODE_G)
-		DMESG("WIRELESS_MODE_G\n");
-
-	ActUpdateChannelAccessSetting(dev, ieee->mode,
-				      &priv->ChannelAccessSetting);
-}
-
-void rtl8185b_irq_enable(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	priv->irq_enabled = 1;
-	write_nic_dword(dev, IMR, priv->IntrMask);
-}
-
-static void MgntDisconnectIBSS(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u8 i;
-
-	for (i = 0; i < 6; i++)
-		priv->ieee80211->current_network.bssid[i] = 0x55;
-
-
-
-	priv->ieee80211->state = IEEE80211_NOLINK;
-	/*
-	 *	Stop Beacon.
-	 *
-	 *	Vista add a Adhoc profile, HW radio off until
-	 *	OID_DOT11_RESET_REQUEST Driver would set MSR=NO_LINK,
-	 *	then HW Radio ON, MgntQueue Stuck. Because Bcn DMA isn't
-	 *	complete, mgnt queue would stuck until Bcn packet send.
-	 *
-	 *	Disable Beacon Queue Own bit, suggested by jong
-	 */
-	ieee80211_stop_send_beacons(priv->ieee80211);
-
-	priv->ieee80211->link_change(dev);
-	notify_wx_assoc_event(priv->ieee80211);
-}
-
-static void MlmeDisassociateRequest(struct net_device *dev, u8 *asSta, u8 asRsn)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u8 i;
-
-	SendDisassociation(priv->ieee80211, asSta, asRsn);
-
-	if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) {
-		/* ShuChen TODO: change media status. */
-
-		for (i = 0; i < 6; i++)
-			priv->ieee80211->current_network.bssid[i] = 0x22;
-
-		ieee80211_disassociate(priv->ieee80211);
-	}
-}
-
-static void MgntDisconnectAP(struct net_device *dev, u8 asRsn)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	/*
-	 * Commented out by rcnjko, 2005.01.27:
-	 * I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
-	 *
-	 *	2004/09/15, kcwu, the key should be cleared, or the new
-	 *	handshaking will not success
-	 *
-	 *	In WPA WPA2 need to Clear all key ... because new key will set
-	 *	after new handshaking. 2004.10.11, by rcnjko.
-	 */
-	MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid,
-				asRsn);
-
-	priv->ieee80211->state = IEEE80211_NOLINK;
-}
-
-static bool MgntDisconnect(struct net_device *dev, u8 asRsn)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	/*
-	 *	Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
-	 */
-
-	if (IS_DOT11D_ENABLE(priv->ieee80211))
-		Dot11d_Reset(priv->ieee80211);
-	/* In adhoc mode, update beacon frame. */
-	if (priv->ieee80211->state == IEEE80211_LINKED)	{
-		if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-			MgntDisconnectIBSS(dev);
-
-		if (priv->ieee80211->iw_mode == IW_MODE_INFRA) {
-			/*
-			 *	We clear key here instead of MgntDisconnectAP()
-			 *	because that MgntActSet_802_11_DISASSOCIATE()
-			 *	is an interface called by OS, e.g.
-			 *	OID_802_11_DISASSOCIATE in Windows while as
-			 *	MgntDisconnectAP() is used to handle
-			 *	disassociation related things to AP, e.g. send
-			 *	Disassoc frame to AP.  2005.01.27, by rcnjko.
-			 */
-			MgntDisconnectAP(dev, asRsn);
-		}
-		/* Indicate Disconnect, 2005.02.23, by rcnjko.	*/
-	}
-	return true;
-}
-/*
- *	Description:
- *		Chang RF Power State.
- *		Note that, only MgntActSet_RF_State() is allowed to set
- *		HW_VAR_RF_STATE.
- *
- *	Assumption:
- *		PASSIVE LEVEL.
- */
-static bool SetRFPowerState(struct net_device *dev,
-			    enum rt_rf_power_state eRFPowerState)
-{
-	struct	r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	bool	bResult = false;
-
-	if (eRFPowerState == priv->eRFPowerState)
-		return bResult;
-
-	bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
-
-	return bResult;
-}
-
-bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet,
-			 u32 ChangeSource)
-{
-	struct	r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	bool	bActionAllowed = false;
-	bool	bConnectBySSID = false;
-	enum rt_rf_power_state rtState;
-	u16	RFWaitCounter = 0;
-	unsigned long flag;
-	/*
-	 *	Prevent the race condition of RF state change. By Bruce,
-	 *	2007-11-28. Only one thread can change the RF state at one time,
-	 *	and others should wait to be executed.
-	 */
-	while (true) {
-		spin_lock_irqsave(&priv->rf_ps_lock, flag);
-		if (priv->RFChangeInProgress) {
-			spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
-			/*  Set RF after the previous action is done.	*/
-			while (priv->RFChangeInProgress) {
-				RFWaitCounter++;
-				udelay(1000); /* 1 ms	*/
-
-				/*
-				 *	Wait too long, return FALSE to avoid
-				 *	to be stuck here.
-				 */
-				if (RFWaitCounter > 1000) { /* 1sec */
-					netdev_info(dev, "MgntActSet_RF_State(): Wait too long to set RF\n");
-					/* TODO: Reset RF state? */
-					return false;
-				}
-			}
-		} else {
-			priv->RFChangeInProgress = true;
-			spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
-			break;
-		}
-	}
-	rtState = priv->eRFPowerState;
-
-	switch (StateToSet) {
-	case RF_ON:
-		/*
-		 *	Turn On RF no matter the IPS setting because we need to
-		 *	update the RF state to Ndis under Vista, or the Windows
-		 *	does not allow the driver to perform site survey any
-		 *	more. By Bruce, 2007-10-02.
-		 */
-		priv->RfOffReason &= (~ChangeSource);
-
-		if (!priv->RfOffReason)	{
-			priv->RfOffReason = 0;
-			bActionAllowed = true;
-
-			if (rtState == RF_OFF &&
-			    ChangeSource >= RF_CHANGE_BY_HW)
-				bConnectBySSID = true;
-		}
-		break;
-
-	case RF_OFF:
-		 /* 070125, rcnjko: we always keep connected in AP mode. */
-
-		if (priv->RfOffReason > RF_CHANGE_BY_IPS) {
-			/*
-			 *	060808, Annie:
-			 *	Disconnect to current BSS when radio off.
-			 *	Asked by QuanTa.
-			 *
-			 *	Calling MgntDisconnect() instead of
-			 *	MgntActSet_802_11_DISASSOCIATE(), because
-			 *	we do NOT need to set ssid to dummy ones.
-			 */
-			MgntDisconnect(dev, disas_lv_ss);
-			/*
-			 *	Clear content of bssDesc[] and bssDesc4Query[]
-			 *	to avoid reporting old bss to UI.
-			 */
-		}
-
-		priv->RfOffReason |= ChangeSource;
-		bActionAllowed = true;
-		break;
-	case RF_SLEEP:
-		priv->RfOffReason |= ChangeSource;
-		bActionAllowed = true;
-		break;
-	default:
-		break;
-	}
-
-	if (bActionAllowed) {
-		/* Config HW to the specified mode. */
-		SetRFPowerState(dev, StateToSet);
-	}
-
-	/* Release RF spinlock	*/
-	spin_lock_irqsave(&priv->rf_ps_lock, flag);
-	priv->RFChangeInProgress = false;
-	spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
-	return bActionAllowed;
-}
-
-static void InactivePowerSave(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	/*
-	 *	This flag "bSwRfProcessing", indicates the status of IPS
-	 *	procedure, should be set if the IPS workitem is really
-	 *	scheduled. The old code, sets this flag before scheduling the
-	 *	IPS workitem and however, at the same time the previous IPS
-	 *	workitem did not end yet, fails to schedule the current
-	 *	workitem. Thus, bSwRfProcessing blocks the IPS procedure of
-	 *	switching RF.
-	 */
-	priv->bSwRfProcessing = true;
-
-	MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS);
-
-	/*
-	 *	To solve CAM values miss in RF OFF, rewrite CAM values after
-	 *	RF ON. By Bruce, 2007-09-20.
-	 */
-
-	priv->bSwRfProcessing = false;
-}
-
-/*
- *	Description:
- *		Enter the inactive power save mode. RF will be off
- */
-void IPSEnter(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	enum rt_rf_power_state rtState;
-	if (priv->bInactivePs) {
-		rtState = priv->eRFPowerState;
-
-		/*
-		 *	Do not enter IPS in the following conditions:
-		 *	(1) RF is already OFF or
-		 *	Sleep (2) bSwRfProcessing (indicates the IPS is still
-		 *	under going) (3) Connected (only disconnected can
-		 *	trigger IPS)(4) IBSS (send Beacon)
-		 *	(5) AP mode (send Beacon)
-		 */
-		if (rtState == RF_ON && !priv->bSwRfProcessing
-			&& (priv->ieee80211->state != IEEE80211_LINKED)) {
-			priv->eInactivePowerState = RF_OFF;
-			InactivePowerSave(dev);
-		}
-	}
-}
-void IPSLeave(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	enum rt_rf_power_state rtState;
-	if (priv->bInactivePs) {
-		rtState = priv->eRFPowerState;
-		if ((rtState == RF_OFF || rtState == RF_SLEEP) &&
-		    !priv->bSwRfProcessing
-		    && priv->RfOffReason <= RF_CHANGE_BY_IPS) {
-			priv->eInactivePowerState = RF_ON;
-			InactivePowerSave(dev);
-		}
-	}
-}
-
-void rtl8185b_adapter_start(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee80211;
-
-	u8 SupportedWirelessMode;
-	u8 InitWirelessMode;
-	u8 bInvalidWirelessMode = 0;
-	u8 tmpu8;
-	u8 btCR9346;
-	u8 TmpU1b;
-	u8 btPSR;
-
-	write_nic_byte(dev, 0x24e, (BIT5|BIT6|BIT0));
-	rtl8180_reset(dev);
-
-	priv->dma_poll_mask = 0;
-	priv->dma_poll_stop_mask = 0;
-
-	HwConfigureRTL8185(dev);
-	write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
-	write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff);
-	/* default network type to 'No Link' */
-	write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3);
-	write_nic_word(dev, BcnItv, 100);
-	write_nic_word(dev, AtimWnd, 2);
-	PlatformIOWrite2Byte(dev, FEMR, 0xFFFF);
-	write_nic_byte(dev, WPA_CONFIG, 0);
-	MacConfig_85BASIC(dev);
-	/* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07,
-	 * by rcnjko.
-	 */
-	/* BT_DEMO_BOARD type */
-	PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a);
-
-	/*
-	 *---------------------------------------------------------------------
-	 *	Set up PHY related.
-	 *---------------------------------------------------------------------
-	 */
-	/* Enable Config3.PARAM_En to revise AnaaParm. */
-	write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */
-	tmpu8 = read_nic_byte(dev, CONFIG3);
-	write_nic_byte(dev, CONFIG3, (tmpu8 | CONFIG3_PARM_En));
-	/* Turn on Analog power. */
-	/* Asked for by William, otherwise, MAC 3-wire can't work,
-	 * 2006.06.27, by rcnjko.
-	 */
-	write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
-	write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
-	write_nic_word(dev, ANAPARAM3, 0x0010);
-
-	write_nic_byte(dev, CONFIG3, tmpu8);
-	write_nic_byte(dev, CR9346, 0x00);
-	/* enable EEM0 and EEM1 in 9346CR */
-	btCR9346 = read_nic_byte(dev, CR9346);
-	write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
-
-	/* B cut use LED1 to control HW RF on/off */
-	TmpU1b = read_nic_byte(dev, CONFIG5);
-	TmpU1b = TmpU1b & ~BIT3;
-	write_nic_byte(dev, CONFIG5, TmpU1b);
-
-	/* disable EEM0 and EEM1 in 9346CR */
-	btCR9346 &= ~(0xC0);
-	write_nic_byte(dev, CR9346, btCR9346);
-
-	/* Enable Led (suggested by Jong) */
-	/* B-cut RF Radio on/off  5e[3]=0 */
-	btPSR = read_nic_byte(dev, PSR);
-	write_nic_byte(dev, PSR, (btPSR | BIT3));
-	/* setup initial timing for RFE. */
-	write_nic_word(dev, RFPinsOutput, 0x0480);
-	SetOutputEnableOfRfPins(dev);
-	write_nic_word(dev, RFPinsSelect, 0x2488);
-
-	/* PHY config. */
-	PhyConfig8185(dev);
-
-	/*
-	 *	We assume RegWirelessMode has already been initialized before,
-	 *	however, we has to validate the wireless mode here and provide a
-	 *	reasonable initialized value if necessary. 2005.01.13,
-	 *	by rcnjko.
-	 */
-	SupportedWirelessMode = GetSupportedWirelessMode8185(dev);
-	if ((ieee->mode != WIRELESS_MODE_B) &&
-		(ieee->mode != WIRELESS_MODE_G) &&
-		(ieee->mode != WIRELESS_MODE_A) &&
-		(ieee->mode != WIRELESS_MODE_AUTO)) {
-		/* It should be one of B, G, A, or AUTO. */
-		bInvalidWirelessMode = 1;
-	} else {
-	/* One of B, G, A, or AUTO. */
-		/* Check if the wireless mode is supported by RF. */
-		if	((ieee->mode != WIRELESS_MODE_AUTO) &&
-			(ieee->mode & SupportedWirelessMode) == 0) {
-			bInvalidWirelessMode = 1;
-		}
-	}
-
-	if (bInvalidWirelessMode || ieee->mode == WIRELESS_MODE_AUTO) {
-		/* Auto or other invalid value. */
-		/* Assigne a wireless mode to initialize. */
-		if ((SupportedWirelessMode & WIRELESS_MODE_A)) {
-			InitWirelessMode = WIRELESS_MODE_A;
-		} else if ((SupportedWirelessMode & WIRELESS_MODE_G)) {
-			InitWirelessMode = WIRELESS_MODE_G;
-		} else if ((SupportedWirelessMode & WIRELESS_MODE_B)) {
-			InitWirelessMode = WIRELESS_MODE_B;
-		} else {
-			DMESGW("InitializeAdapter8185(): No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n",
-				 SupportedWirelessMode);
-			InitWirelessMode = WIRELESS_MODE_B;
-		}
-
-		/* Initialize RegWirelessMode if it is not a valid one.	*/
-		if (bInvalidWirelessMode)
-			ieee->mode = (enum wireless_mode)InitWirelessMode;
-
-	} else {
-	/* One of B, G, A. */
-		InitWirelessMode = ieee->mode;
-	}
-	priv->eRFPowerState = RF_OFF;
-	priv->RfOffReason = 0;
-	{
-		MgntActSet_RF_State(dev, RF_ON, 0);
-	}
-		/*
-		 * If inactive power mode is enabled, disable rf while in
-		 * disconnected state.
-		 */
-	if (priv->bInactivePs)
-		MgntActSet_RF_State(dev , RF_OFF, RF_CHANGE_BY_IPS);
-
-	ActSetWirelessMode8185(dev, (u8)(InitWirelessMode));
-
-	/* ----------------------------------------------------------------- */
-
-	rtl8185b_irq_enable(dev);
-
-	netif_start_queue(dev);
-}
-
-void rtl8185b_rx_enable(struct net_device *dev)
-{
-	u8 cmd;
-	/* for now we accept data, management & ctl frame*/
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-
-	if (dev->flags & IFF_PROMISC)
-		DMESG("NIC in promisc mode");
-
-	if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || dev->flags &
-	    IFF_PROMISC) {
-		priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM);
-		priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP;
-	}
-
-	if (priv->ieee80211->iw_mode == IW_MODE_MONITOR)
-		priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF |
-				      RCR_APWRMGT | RCR_AICV;
-
-
-	if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
-		priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACRC32;
-
-	write_nic_dword(dev, RCR, priv->ReceiveConfig);
-
-	fix_rx_fifo(dev);
-
-	cmd = read_nic_byte(dev, CMD);
-	write_nic_byte(dev, CMD, cmd | (1<<CMD_RX_ENABLE_SHIFT));
-
-}
-
-void rtl8185b_tx_enable(struct net_device *dev)
-{
-	u8 cmd;
-	u8 byte;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	write_nic_dword(dev, TCR, priv->TransmitConfig);
-	byte = read_nic_byte(dev, MSR);
-	byte |= MSR_LINK_ENEDCA;
-	write_nic_byte(dev, MSR, byte);
-
-	fix_tx_fifo(dev);
-
-	cmd = read_nic_byte(dev, CMD);
-	write_nic_byte(dev, CMD, cmd | (1<<CMD_TX_ENABLE_SHIFT));
-}
-
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 636ec553ae83..e305d43ebd06 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -545,20 +545,18 @@ static struct recv_frame *decryptor(struct adapter *padapter,
 static struct recv_frame *portctrl(struct adapter *adapter,
 				   struct recv_frame *precv_frame)
 {
-	u8   *psta_addr = NULL, *ptr;
+	u8   *psta_addr, *ptr;
 	uint  auth_alg;
 	struct recv_frame *pfhdr;
 	struct sta_info *psta;
 	struct sta_priv *pstapriv;
 	struct recv_frame *prtnframe;
-	u16	ether_type = 0;
+	u16	ether_type;
 	u16  eapol_type = 0x888e;/* for Funia BD's WPA issue */
 	struct rx_pkt_attrib *pattrib;
-	__be16 be_tmp;
 
 
 	pstapriv = &adapter->stapriv;
-	psta = rtw_get_stainfo(pstapriv, psta_addr);
 
 	auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
 
@@ -566,24 +564,23 @@ static struct recv_frame *portctrl(struct adapter *adapter,
 	pfhdr = precv_frame;
 	pattrib = &pfhdr->attrib;
 	psta_addr = pattrib->ta;
+	psta = rtw_get_stainfo(pstapriv, psta_addr);
 
 	prtnframe = NULL;
 
 	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n", adapter->securitypriv.dot11AuthAlgrthm));
 
 	if (auth_alg == 2) {
+		/* get ether_type */
+		ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
+		memcpy(&ether_type, ptr, 2);
+		ether_type = ntohs((unsigned short)ether_type);
+
 		if ((psta != NULL) && (psta->ieee8021x_blocked)) {
 			/* blocked */
 			/* only accept EAPOL frame */
 			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked==1\n"));
 
-			prtnframe = precv_frame;
-
-			/* get ether_type */
-			ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE;
-			memcpy(&be_tmp, ptr, 2);
-			ether_type = ntohs(be_tmp);
-
 			if (ether_type == eapol_type) {
 				prtnframe = precv_frame;
 			} else {
diff --git a/drivers/staging/rtl8188eu/include/xmit_osdep.h b/drivers/staging/rtl8188eu/include/xmit_osdep.h
index 2ff622ba24f0..48bc5fca996d 100644
--- a/drivers/staging/rtl8188eu/include/xmit_osdep.h
+++ b/drivers/staging/rtl8188eu/include/xmit_osdep.h
@@ -32,10 +32,6 @@ struct pkt_file {
 	size_t buf_len;
 };
 
-extern int rtw_ht_enable;
-extern int rtw_cbw40_enable;
-extern int rtw_ampdu_enable;/* for enable tx_ampdu */
-
 #define NR_XMITFRAME	256
 
 struct xmit_priv;
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index 2636e7f3dbb8..cf30a08912d1 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -359,7 +359,7 @@ static char *translate_scan(struct adapter *padapter,
 		if (wpa_len > 0) {
 			p = buf;
 			_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
-			p += sprintf(p, "wpa_ie =");
+			p += sprintf(p, "wpa_ie=");
 			for (i = 0; i < wpa_len; i++)
 				p += sprintf(p, "%02x", wpa_ie[i]);
 
@@ -376,7 +376,7 @@ static char *translate_scan(struct adapter *padapter,
 		if (rsn_len > 0) {
 			p = buf;
 			_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
-			p += sprintf(p, "rsn_ie =");
+			p += sprintf(p, "rsn_ie=");
 			for (i = 0; i < rsn_len; i++)
 				p += sprintf(p, "%02x", rsn_ie[i]);
 			_rtw_memset(&iwe, 0, sizeof(iwe));
@@ -2899,7 +2899,7 @@ static int rtw_p2p_get_status(struct net_device *dev,
 	/*	Commented by Albert 2010/10/12 */
 	/*	Because of the output size limitation, I had removed the "Role" information. */
 	/*	About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
-	sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo));
+	sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
 	wrqu->data.length = strlen(extra);
 
 	return ret;
@@ -2918,7 +2918,7 @@ static int rtw_p2p_get_req_cm(struct net_device *dev,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
 
-	sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
+	sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
 	wrqu->data.length = strlen(extra);
 	return ret;
 }
@@ -2935,7 +2935,7 @@ static int rtw_p2p_get_role(struct net_device *dev,
 			pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
 			pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
 
-	sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo));
+	sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
 	wrqu->data.length = strlen(extra);
 	return ret;
 }
@@ -3022,7 +3022,7 @@ static int rtw_p2p_get_op_ch(struct net_device *dev,
 
 	DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
 
-	sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel);
+	sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
 	wrqu->data.length = strlen(extra);
 	return ret;
 }
@@ -3043,7 +3043,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
 	u8 blnMatch = 0;
 	u16	attr_content = 0;
 	uint attr_contentlen = 0;
-	/* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
+	/* 6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
 	u8 attr_content_str[6 + 17] = {0x00};
 
 	/*	Commented by Albert 20110727 */
@@ -3079,7 +3079,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
 				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen);
 				if (attr_contentlen) {
 					attr_content = be16_to_cpu(be_tmp);
-					sprintf(attr_content_str, "\n\nM =%.4d", attr_content);
+					sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
 					blnMatch = 1;
 				}
 			}
@@ -3091,7 +3091,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
 	if (!blnMatch)
-		sprintf(attr_content_str, "\n\nM = 0000");
+		sprintf(attr_content_str, "\n\nM=0000");
 
 	if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
 		return -EFAULT;
@@ -3172,9 +3172,9 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev,
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
 	if (!blnMatch)
-		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL");
+		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=NULL");
 	else
-		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+		snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
 			attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
 
 	if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
@@ -3198,7 +3198,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
 	u8 blnMatch = 0;
 	u8 dev_type[8] = {0x00};
 	uint dev_type_len = 0;
-	u8 dev_type_str[17 + 9] = {0x00};	/*  +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */
+	u8 dev_type_str[17 + 9] = {0x00};	/*  +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
 
 	/*	Commented by Albert 20121209 */
 	/*	The input data is the MAC address which the application wants to know its device type. */
@@ -3239,7 +3239,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
 
 					memcpy(&be_tmp, dev_type, 2);
 					type = be16_to_cpu(be_tmp);
-					sprintf(dev_type_str, "\n\nN =%.2d", type);
+					sprintf(dev_type_str, "\n\nN=%.2d", type);
 					blnMatch = 1;
 				}
 			}
@@ -3252,7 +3252,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
 	if (!blnMatch)
-		sprintf(dev_type_str, "\n\nN = 00");
+		sprintf(dev_type_str, "\n\nN=00");
 
 	if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
 		return -EFAULT;
@@ -3277,7 +3277,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
 	u8 blnMatch = 0;
 	u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
 	uint dev_len = 0;
-	u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00};	/*  +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */
+	u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00};	/*  +5 is for the str "devN=", we have to clear it at wrqu->data.pointer */
 
 	/*	Commented by Albert 20121225 */
 	/*	The input data is the MAC address which the application wants to know its device name. */
@@ -3310,7 +3310,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
 			if (wpsie) {
 				rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
 				if (dev_len) {
-					sprintf(dev_name_str, "\n\nN =%s", dev_name);
+					sprintf(dev_name_str, "\n\nN=%s", dev_name);
 					blnMatch = 1;
 				}
 			}
@@ -3323,7 +3323,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
 	if (!blnMatch)
-		sprintf(dev_name_str, "\n\nN = 0000");
+		sprintf(dev_name_str, "\n\nN=0000");
 
 	if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
 		return -EFAULT;
@@ -3349,7 +3349,7 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
 	u8 attr_content[2] = {0x00};
 
 	u8 inv_proc_str[17 + 8] = {0x00};
-	/*  +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
+	/*  +8 is for the str "InvProc=", we have to clear it at wrqu->data.pointer */
 
 	/*	Commented by Ouden 20121226 */
 	/*	The application wants to know P2P initiation procedure is supported or not. */
@@ -3397,12 +3397,12 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
 	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
 	if (!blnMatch) {
-		sprintf(inv_proc_str, "\nIP =-1");
+		sprintf(inv_proc_str, "\nIP=-1");
 	} else {
 		if (attr_content[0] & 0x20)
-			sprintf(inv_proc_str, "\nIP = 1");
+			sprintf(inv_proc_str, "\nIP=1");
 		else
-			sprintf(inv_proc_str, "\nIP = 0");
+			sprintf(inv_proc_str, "\nIP=0");
 	}
 	if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
 		return -EFAULT;
@@ -3512,7 +3512,7 @@ static int rtw_p2p_invite_req(struct net_device *dev,
 	/*	The input data contains two informations. */
 	/*	1. First information is the P2P device address which you want to send to. */
 	/*	2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
-	/*	Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
+	/*	Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
 	/*	Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
 
 	DBG_88E("[%s] data = %s\n", __func__, extra);
@@ -3805,48 +3805,48 @@ static int rtw_p2p_set(struct net_device *dev,
 
 #ifdef CONFIG_88EU_P2P
 	DBG_88E("[%s] extra = %s\n", __func__, extra);
-	if (!memcmp(extra, "enable =", 7)) {
+	if (!memcmp(extra, "enable=", 7)) {
 		rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
-	} else if (!memcmp(extra, "setDN =", 6)) {
+	} else if (!memcmp(extra, "setDN=", 6)) {
 		wrqu->data.length -= 6;
 		rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
-	} else if (!memcmp(extra, "profilefound =", 13)) {
+	} else if (!memcmp(extra, "profilefound=", 13)) {
 		wrqu->data.length -= 13;
 		rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
-	} else if (!memcmp(extra, "prov_disc =", 10)) {
+	} else if (!memcmp(extra, "prov_disc=", 10)) {
 		wrqu->data.length -= 10;
 		rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
-	} else if (!memcmp(extra, "nego =", 5)) {
+	} else if (!memcmp(extra, "nego=", 5)) {
 		wrqu->data.length -= 5;
 		rtw_p2p_connect(dev, info, wrqu, &extra[5]);
-	} else if (!memcmp(extra, "intent =", 7)) {
+	} else if (!memcmp(extra, "intent=", 7)) {
 		/*	Commented by Albert 2011/03/23 */
 		/*	The wrqu->data.length will include the null character */
 		/*	So, we will decrease 7 + 1 */
 		wrqu->data.length -= 8;
 		rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
-	} else if (!memcmp(extra, "ssid =", 5)) {
+	} else if (!memcmp(extra, "ssid=", 5)) {
 		wrqu->data.length -= 5;
 		rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
-	} else if (!memcmp(extra, "got_wpsinfo =", 12)) {
+	} else if (!memcmp(extra, "got_wpsinfo=", 12)) {
 		wrqu->data.length -= 12;
 		rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
-	} else if (!memcmp(extra, "listen_ch =", 10)) {
+	} else if (!memcmp(extra, "listen_ch=", 10)) {
 		/*	Commented by Albert 2011/05/24 */
 		/*	The wrqu->data.length will include the null character */
 		/*	So, we will decrease (10 + 1) */
 		wrqu->data.length -= 11;
 		rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
-	} else if (!memcmp(extra, "op_ch =", 6)) {
+	} else if (!memcmp(extra, "op_ch=", 6)) {
 		/*	Commented by Albert 2011/05/24 */
 		/*	The wrqu->data.length will include the null character */
 		/*	So, we will decrease (6 + 1) */
 		wrqu->data.length -= 7;
 		rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
-	} else if (!memcmp(extra, "invite =", 7)) {
+	} else if (!memcmp(extra, "invite=", 7)) {
 		wrqu->data.length -= 8;
 		rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
-	} else if (!memcmp(extra, "persistent =", 11)) {
+	} else if (!memcmp(extra, "persistent=", 11)) {
 		wrqu->data.length -= 11;
 		rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
 	}
@@ -3887,7 +3887,7 @@ static int rtw_p2p_get(struct net_device *dev,
 			"group_id", 8)) {
 		rtw_p2p_get_groupid(dev, info, wrqu, extra);
 	} else if (!memcmp((__force const char *)wrqu->data.pointer,
-			"peer_deva_inv", 9)) {
+			"peer_deva_inv", 13)) {
 		/*	Get the P2P device address when receiving the P2P Invitation request frame. */
 		rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
 	} else if (!memcmp((__force const char *)wrqu->data.pointer,
@@ -6920,7 +6920,7 @@ static int rtw_mp_ctx(struct net_device *dev,
 
 	DBG_88E("%s: in =%s\n", __func__, extra);
 
-	countPkTx = strncmp(extra, "count =", 5); /*  strncmp true is 0 */
+	countPkTx = strncmp(extra, "count=", 6); /*  strncmp true is 0 */
 	cotuTx = strncmp(extra, "background", 20);
 	CarrSprTx = strncmp(extra, "background, cs", 20);
 	scTx = strncmp(extra, "background, sc", 20);
@@ -7044,7 +7044,7 @@ static int rtw_mp_arx(struct net_device *dev,
 	DBG_88E("%s: %s\n", __func__, input);
 
 	bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /*  strncmp true is 0 */
-	bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /*  strncmp true is 0 */
+	bStopRx = (strncmp(input, "stop", 4) == 0) ? 1 : 0; /*  strncmp true is 0 */
 	bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /*  strncmp true is 0 */
 
 	if (bStartRx) {
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index b225d1c07210..9edb8e880ae8 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -84,9 +84,9 @@ static int rtw_uapsd_acbe_en;
 static int rtw_uapsd_acvi_en;
 static int rtw_uapsd_acvo_en;
 
-int rtw_ht_enable = 1;
-int rtw_cbw40_enable = 3; /*  0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */
-int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
+static int rtw_ht_enable = 1;
+static int rtw_cbw40_enable = 3; /*  0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */
+static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
 static int rtw_rx_stbc = 1;/*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
 static int rtw_ampdu_amsdu;/*  0: disabled, 1:enabled, 2:auto */
 
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 2e49cd583212..49a4ce44ada6 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -62,10 +62,6 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
 
 MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
 
-static struct specific_device_id specific_device_id_tbl[] = {
-	{}		/* empty table for now */
-};
-
 struct rtw_usb_drv {
 	struct usb_driver usbdrv;
 	int drv_registered;
@@ -360,28 +356,6 @@ static void rtw_dev_unload(struct adapter *padapter)
 	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
 }
 
-static void process_spec_devid(const struct usb_device_id *pdid)
-{
-	u16 vid, pid;
-	u32 flags;
-	int i;
-	int num = sizeof(specific_device_id_tbl) /
-		  sizeof(struct specific_device_id);
-
-	for (i = 0; i < num; i++) {
-		vid = specific_device_id_tbl[i].idVendor;
-		pid = specific_device_id_tbl[i].idProduct;
-		flags = specific_device_id_tbl[i].flags;
-
-		if ((pdid->idVendor == vid) && (pdid->idProduct == pid) &&
-		    (flags&SPEC_DEV_ID_DISABLE_HT)) {
-			rtw_ht_enable = 0;
-			rtw_cbw40_enable = 0;
-			rtw_ampdu_enable = 0;
-		}
-	}
-}
-
 int rtw_hw_suspend(struct adapter *padapter)
 {
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
@@ -781,9 +755,6 @@ static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device
 
 	RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
 
-	/* step 0. */
-	process_spec_devid(pdid);
-
 	/* Initialize dvobj_priv */
 	dvobj = usb_dvobj_init(pusb_intf);
 	if (dvobj == NULL) {
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
index 23ec684b60e1..274c359279ef 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ b/drivers/staging/rtl8712/rtl871x_recv.c
@@ -254,7 +254,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
 	struct sta_info *psta;
 	struct	sta_priv *pstapriv;
 	union recv_frame *prtnframe;
-	u16 ether_type = 0;
+	u16 ether_type;
 
 	pstapriv = &adapter->stapriv;
 	ptr = get_recvframe_data(precv_frame);
@@ -263,15 +263,14 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
 	psta = r8712_get_stainfo(pstapriv, psta_addr);
 	auth_alg = adapter->securitypriv.AuthAlgrthm;
 	if (auth_alg == 2) {
+		/* get ether_type */
+		ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
+		memcpy(&ether_type, ptr, 2);
+		ether_type = ntohs((unsigned short)ether_type);
+
 		if ((psta != NULL) && (psta->ieee8021x_blocked)) {
 			/* blocked
 			 * only accept EAPOL frame */
-			prtnframe = precv_frame;
-			/*get ether_type */
-			ptr = ptr + pfhdr->attrib.hdrlen +
-			      pfhdr->attrib.iv_len + LLC_HEADER_SIZE;
-			memcpy(&ether_type, ptr, 2);
-			ether_type = ntohs((unsigned short)ether_type);
 			if (ether_type == 0x888e)
 				prtnframe = precv_frame;
 			else {
diff --git a/drivers/staging/rtl8723au/Kconfig b/drivers/staging/rtl8723au/Kconfig
index 07fb5e4e50fa..435f3594dabe 100644
--- a/drivers/staging/rtl8723au/Kconfig
+++ b/drivers/staging/rtl8723au/Kconfig
@@ -19,14 +19,6 @@ config 8723AU_AP_MODE
 	will never be used as an AP, or the target system has limited memory,
 	"Y" should be selected.
 
-config 8723AU_P2P
-	bool "Realtek RTL8723AU Peer-to-peer mode"
-	default y
-	---help---
-	This option enables peer-to-peer mode for the r8723au driver. Unless you
-	know that peer-to-peer (P2P) mode will never be used, or the target system has
-	limited memory, "Y" should be selected.
-
 config 8723AU_BT_COEXIST
 	bool "Realtek RTL8723AU BlueTooth Coexistence"
 	default y
diff --git a/drivers/staging/rtl8723au/Makefile b/drivers/staging/rtl8723au/Makefile
index 11c6dd486462..bbf503dd437a 100644
--- a/drivers/staging/rtl8723au/Makefile
+++ b/drivers/staging/rtl8723au/Makefile
@@ -8,7 +8,6 @@ r8723au-y :=				\
 		core/rtw_led.o		\
 		core/rtw_mlme.o		\
 		core/rtw_mlme_ext.o	\
-		core/rtw_p2p.o		\
 		core/rtw_pwrctrl.o	\
 		core/rtw_recv.o		\
 		core/rtw_security.o	\
diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c
index a357e98cb83e..207a19e4dc9f 100644
--- a/drivers/staging/rtl8723au/core/rtw_ap.c
+++ b/drivers/staging/rtl8723au/core/rtw_ap.c
@@ -21,7 +21,6 @@
 
 #ifdef CONFIG_8723AU_AP_MODE
 
-extern unsigned char RTW_WPA_OUI23A[];
 extern unsigned char WMM_OUI23A[];
 extern unsigned char WPS_OUI23A[];
 extern unsigned char P2P_OUI23A[];
@@ -79,7 +78,8 @@ static void update_BCNTIM(struct rtw_adapter *padapter)
 
 	tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
 
-	p = rtw_get_ie23a(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
+	p = rtw_get_ie23a(pie + _FIXED_IE_LENGTH_, WLAN_EID_TIM, &tim_ielen,
+			  pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
 	if (p != NULL && tim_ielen>0) {
 		tim_ielen += 2;
 
@@ -98,12 +98,16 @@ static void update_BCNTIM(struct rtw_adapter *padapter)
 		offset = _FIXED_IE_LENGTH_;
 
 		/* get ssid_ie len */
-		p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
+		p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, WLAN_EID_SSID,
+				  &tmp_len, (pnetwork_mlmeext->IELength -
+					     _BEACON_IE_OFFSET_));
 		if (p != NULL)
 			offset += tmp_len+2;
 
 		/*  get supported rates len */
-		p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
+		p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES,
+				  &tmp_len, (pnetwork_mlmeext->IELength -
+					     _BEACON_IE_OFFSET_));
 		if (p !=  NULL)
 			offset += tmp_len+2;
 
@@ -124,7 +128,7 @@ static void update_BCNTIM(struct rtw_adapter *padapter)
 			memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
 	}
 
-	*dst_ie++= _TIM_IE_;
+	*dst_ie++= WLAN_EID_TIM;
 
 	if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc))
 		tim_ielen = 5;
@@ -248,7 +252,7 @@ void	expire_timeout_chk23a(struct rtw_adapter *padapter)
 
 					/* to update bcn with tim_bitmap for this station */
 					pstapriv->tim_bitmap |= CHKBIT(psta->aid);
-					update_beacon23a(padapter, _TIM_IE_, NULL, false);
+					update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 
 					if (!pmlmeext->active_keep_alive_check)
 						continue;
@@ -374,9 +378,9 @@ void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_l
 			tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f);
 	}
 	/* n mode ra_bitmap */
-	if (psta_ht->ht_option)
-	{
-		rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	if (psta_ht->ht_option) {
+		rf_type = rtl8723a_get_rf_type(padapter);
+
 		if (rf_type == RF_2T2R)
 			limit = 16;/*  2R */
 		else
@@ -523,8 +527,6 @@ static void update_bmc_sta(struct rtw_adapter *padapter)
 		psta->raid = raid;
 		psta->init_rate = init_rate;
 
-		rtw_stassoc_hw_rpt23a(padapter, psta);
-
 		spin_lock_bh(&psta->lock);
 		psta->state = _FW_LINKED;
 		spin_unlock_bh(&psta->lock);
@@ -632,9 +634,8 @@ static void update_hw_ht_param(struct rtw_adapter *padapter)
 
 	min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
-
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+	rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing);
+	rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len);
 
 	/*  Config SM Power Save setting */
 	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
@@ -644,11 +645,10 @@ static void update_hw_ht_param(struct rtw_adapter *padapter)
 
 static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
 {
-	u8 *p;
+	const u8 *p;
 	u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
 	u16 bcn_interval;
 	u32 acparm;
-	int ie_len;
 	struct registry_priv *pregpriv = &padapter->registrypriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct security_priv* psecuritypriv = &padapter->securitypriv;
@@ -657,9 +657,6 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
 	struct HT_info_element *pht_info = NULL;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
 
 	bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
 	cur_channel = pnetwork->Configuration.DSConfig;
@@ -695,27 +692,28 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
 	Set_MSR23a(padapter, _HW_STATE_AP_);
 
 	/* Set BSSID REG */
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
+	hw_var_set_bssid(padapter, pnetwork->MacAddress);
 
 	/* Set EDCA param reg */
 	acparm = 0x002F3217; /*  VO */
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
+	rtl8723a_set_ac_param_vo(padapter, acparm);
 	acparm = 0x005E4317; /*  VI */
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
+	rtl8723a_set_ac_param_vi(padapter, acparm);
 	acparm = 0x005ea42b;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
+	rtl8723a_set_ac_param_be(padapter, acparm);
 	acparm = 0x0000A444; /*  BK */
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
+	rtl8723a_set_ac_param_bk(padapter, acparm);
 
 	/* Set Security */
-	val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+	val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ?
+		0xcc: 0xcf;
+	rtl8723a_set_sec_cfg(padapter, val8);
 
 	/* Beacon Control related register */
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
+	rtl8723a_set_beacon_interval(padapter, bcn_interval);
 
 	UpdateBrateTbl23a(padapter, pnetwork->SupportedRates);
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
+	HalSetBrateCfg23a(padapter, pnetwork->SupportedRates);
 
 	if (!pmlmepriv->cur_network.join_res) {
 		/* setting only at  first time */
@@ -723,21 +721,25 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
 		/* disable dynamic functions, such as high power, DIG */
 
 		/* turn on all dynamic functions */
-		Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
+		rtl8723a_odm_support_ability_set(padapter,
+						 DYNAMIC_ALL_FUNC_ENABLE);
 	}
 	/* set channel, bwmode */
-	p = rtw_get_ie23a((pnetwork->IEs + sizeof(struct ndis_802_11_fixed_ies)),
-			  _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength -
-			  sizeof(struct ndis_802_11_fixed_ies)));
-	if (p && ie_len) {
-		pht_info = (struct HT_info_element *)(p+2);
-
-		if ((pregpriv->cbw40_enable) &&	(pht_info->infos[0] & BIT(2))) {
+	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
+			     pnetwork->IEs +
+			     sizeof(struct ndis_802_11_fixed_ies),
+			     pnetwork->IELength -
+			     sizeof(struct ndis_802_11_fixed_ies));
+	if (p && p[1]) {
+		pht_info = (struct HT_info_element *)(p + 2);
+
+		if (pregpriv->cbw40_enable && pht_info->infos[0] & BIT(2)) {
 			/* switch to the 40M Hz mode */
 			cur_bwmode = HT_CHANNEL_WIDTH_40;
 			switch (pht_info->infos[0] & 0x3) {
 			case 1:
-				/* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; */
+				/* pmlmeext->cur_ch_offset =
+				   HAL_PRIME_CHNL_OFFSET_LOWER; */
 				cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
 				break;
 			case 3:
@@ -769,14 +771,8 @@ static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
 	/* let pnetwork_mlmeext == pnetwork_mlme. */
 	memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
 
-#ifdef CONFIG_8723AU_P2P
-	memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.ssid,
-	       pnetwork->Ssid.ssid_len);
-	pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.ssid_len;
-#endif /* CONFIG_8723AU_P2P */
-
 	if (pmlmeext->bstart_bss) {
-		update_beacon23a(padapter, _TIM_IE_, NULL, false);
+		update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 
 		/* issue beacon frame */
 		if (send_beacon23a(padapter) == _FAIL)
@@ -848,7 +844,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	cap = get_unaligned_le16(ie);
 
 	/* SSID */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_SSID, &ie_len,
 			  (pbss_network->IELength -_BEACON_IE_OFFSET_));
 	if (p && ie_len > 0) {
 		memset(&pbss_network->Ssid, 0, sizeof(struct cfg80211_ssid));
@@ -859,7 +855,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	/* chnnel */
 	channel = 0;
 	pbss_network->Configuration.Length = 0;
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_DS_PARAMS, &ie_len,
 			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p && ie_len > 0)
 		channel = *(p + 2);
@@ -868,7 +864,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 
 	memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
 	/*  get supported rates */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES, &ie_len,
 			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p) {
 		memcpy(supportRate, p+2, ie_len);
@@ -876,7 +872,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	}
 
 	/* get ext_supported rates */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES,
 			  &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
 	if (p) {
 		memcpy(supportRate+supportRateNum, p+2, ie_len);
@@ -889,7 +885,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	rtw_set_supported_rate23a(pbss_network->SupportedRates, network_type);
 
 	/* parsing ERP_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &ie_len,
 			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p && ie_len > 0)
 		ERP_IE_handler23a(padapter, (struct ndis_802_11_var_ies *)p);
@@ -906,7 +902,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	group_cipher = 0; pairwise_cipher = 0;
 	psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
 	psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len,
 			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p && ie_len > 0) {
 		if (rtw_parse_wpa2_ie23a(p, ie_len+2, &group_cipher,
@@ -928,7 +924,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
 	psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
 	for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
-		p = rtw_get_ie23a(p, _SSN_IE_1_, &ie_len,
+		p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
 				  (pbss_network->IELength - _BEACON_IE_OFFSET_ -
 				  (ie_len + 2)));
 		if ((p) && (!memcmp(p+2, OUI1, 4))) {
@@ -956,7 +952,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	pmlmepriv->qospriv.qos_option = 0;
 	if (pregistrypriv->wmm_enable) {
 		for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
-			p = rtw_get_ie23a(p, _VENDOR_SPECIFIC_IE_, &ie_len,
+			p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len,
 					  (pbss_network->IELength -
 					  _BEACON_IE_OFFSET_ - (ie_len + 2)));
 			if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
@@ -978,7 +974,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 		}
 	}
 	/* parsing HT_CAP_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len,
 			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p && ie_len > 0) {
 		u8 rf_type;
@@ -990,7 +986,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 		ht_cap = true;
 		network_type |= WIRELESS_11_24N;
 
-		rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+		rf_type = rtl8723a_get_rf_type(padapter);
 
 		if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
 		    (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
@@ -1010,7 +1006,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf,  int len)
 	}
 
 	/* parsing HT_INFO_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len,
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len,
 			  (pbss_network->IELength - _BEACON_IE_OFFSET_));
 	if (p && ie_len > 0)
 		pHT_info_ie = p;
@@ -1200,7 +1196,7 @@ static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter)
 		return;
 
 	/* parsing ERP_IE */
-	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+	p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, WLAN_EID_ERP_INFO, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
 	if (p && len>0)
 	{
 		struct ndis_802_11_var_ies * pIE = (struct ndis_802_11_var_ies *)p;
@@ -1306,26 +1302,16 @@ static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8*oui)
 {
 	DBG_8723A("%s\n", __func__);
 
-	if (!memcmp(RTW_WPA_OUI23A, oui, 4))
-	{
+	if (!memcmp(RTW_WPA_OUI23A_TYPE, oui, 4))
 		update_bcn_wpa_ie(padapter);
-	}
 	else if (!memcmp(WMM_OUI23A, oui, 4))
-	{
 		update_bcn_wmm_ie(padapter);
-	}
 	else if (!memcmp(WPS_OUI23A, oui, 4))
-	{
 		update_bcn_wps_ie(padapter);
-	}
 	else if (!memcmp(P2P_OUI23A, oui, 4))
-	{
 		update_bcn_p2p_ie(padapter);
-	}
 	else
-	{
 		DBG_8723A("unknown OUI type!\n");
-	}
 }
 
 void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
@@ -1350,50 +1336,37 @@ void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
 
 	switch (ie_id)
 	{
-		case 0xFF:
-
-			update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
-
-			break;
-
-		case _TIM_IE_:
-
-			update_BCNTIM(padapter);
-
-			break;
-
-		case _ERPINFO_IE_:
-
-			update_bcn_erpinfo_ie(padapter);
-
-			break;
-
-		case _HT_CAPABILITY_IE_:
-
-			update_bcn_htcap_ie(padapter);
-
-			break;
-
-		case _RSN_IE_2_:
-
-			update_bcn_rsn_ie(padapter);
-
-			break;
+	case 0xFF:
+		/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
+		update_bcn_fixed_ie(padapter);
+		break;
 
-		case _HT_ADD_INFO_IE_:
+	case WLAN_EID_TIM:
+		update_BCNTIM(padapter);
+		break;
 
-			update_bcn_htinfo_ie(padapter);
+	case WLAN_EID_ERP_INFO:
+		update_bcn_erpinfo_ie(padapter);
+		break;
 
-			break;
+	case WLAN_EID_HT_CAPABILITY:
+		update_bcn_htcap_ie(padapter);
+		break;
 
-		case _VENDOR_SPECIFIC_IE_:
+	case WLAN_EID_RSN:
+		update_bcn_rsn_ie(padapter);
+		break;
 
-			update_bcn_vendor_spec_ie(padapter, oui);
+	case WLAN_EID_HT_OPERATION:
+		update_bcn_htinfo_ie(padapter);
+		break;
 
-			break;
+	case WLAN_EID_VENDOR_SPECIFIC:
+		update_bcn_vendor_spec_ie(padapter, oui);
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 
 	pmlmepriv->update_bcn = true;
@@ -1562,7 +1535,7 @@ void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info
 			if (pmlmepriv->num_sta_non_erp == 1)
 			{
 				beacon_updated = true;
-				update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
+				update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true);
 			}
 		}
 
@@ -1578,7 +1551,7 @@ void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info
 			if (pmlmepriv->num_sta_non_erp == 0)
 			{
 				beacon_updated = true;
-				update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
+				update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true);
 			}
 		}
 
@@ -1669,8 +1642,8 @@ void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info
 
 	if (rtw_ht_operation_update(padapter) > 0)
 	{
-		update_beacon23a(padapter, _HT_CAPABILITY_IE_, NULL, false);
-		update_beacon23a(padapter, _HT_ADD_INFO_IE_, NULL, true);
+		update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false);
+		update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true);
 	}
 
 	/* update associcated stations cap. */
@@ -1705,7 +1678,8 @@ u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info
 		if (pmlmepriv->num_sta_non_erp == 0)
 		{
 			beacon_updated = true;
-			update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
+			update_beacon23a(padapter, WLAN_EID_ERP_INFO,
+					 NULL, true);
 		}
 	}
 
@@ -1737,8 +1711,8 @@ u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info
 
 	if (rtw_ht_operation_update(padapter) > 0)
 	{
-		update_beacon23a(padapter, _HT_CAPABILITY_IE_, NULL, false);
-		update_beacon23a(padapter, _HT_ADD_INFO_IE_, NULL, true);
+		update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false);
+		update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true);
 	}
 
 	/* update associcated stations cap. */
diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c
index 5e3088a01800..cb15ddaae12e 100644
--- a/drivers/staging/rtl8723au/core/rtw_cmd.c
+++ b/drivers/staging/rtl8723au/core/rtw_cmd.c
@@ -19,6 +19,7 @@
 #include <recv_osdep.h>
 #include <cmd_osdep.h>
 #include <mlme_osdep.h>
+#include <rtl8723a_cmd.h>
 
 #ifdef CONFIG_8723AU_BT_COEXIST
 #include <rtl8723a_hal.h>
@@ -526,12 +527,6 @@ u8 rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter,
 	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
 		rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1);
 
-#ifdef CONFIG_8723AU_P2P
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-		p2p_ps_wk_cmd23a(padapter, P2P_PS_SCAN, 1);
-	}
-#endif /* CONFIG_8723AU_P2P */
-
 	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
 	if (!ph2c)
 		return _FAIL;
@@ -1269,8 +1264,7 @@ void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type)
 			mstatus = 1;/* connect */
 			/*  Reset LPS Setting */
 			padapter->pwrctrlpriv.LpsIdleCount = 0;
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
-					     (u8 *)&mstatus);
+			rtl8723a_set_FwJoinBssReport_cmd(padapter, 1);
 #ifdef CONFIG_8723AU_BT_COEXIST
 			BT_WifiMediaStatusNotify(padapter, mstatus);
 #endif
@@ -1284,8 +1278,7 @@ void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type)
 			{
 				LPS_Leave23a(padapter);
 			}
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
-					     (u8 *)&mstatus);
+			rtl8723a_set_FwJoinBssReport_cmd(padapter, 0);
 			break;
 		case LPS_CTRL_SPECIAL_PACKET:
 			pwrpriv->DelayLPSLastTimeStamp = jiffies;
@@ -1355,48 +1348,6 @@ static void power_saving_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
 	 rtw_ps_processor23a(padapter);
 }
 
-#ifdef CONFIG_8723AU_P2P
-u8 p2p_protocol_wk_cmd23a(struct rtw_adapter*padapter, int intCmdType)
-{
-	struct cmd_obj *ph2c;
-	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-	u8 res = _SUCCESS;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-	{
-		return res;
-	}
-
-	ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
-	if (!ph2c) {
-		res = _FAIL;
-		goto exit;
-	}
-
-	pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
-				     GFP_ATOMIC);
-	if (!pdrvextra_cmd_parm) {
-		kfree(ph2c);
-		res = _FAIL;
-		goto exit;
-	}
-
-	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
-	pdrvextra_cmd_parm->type_size = intCmdType; /* As the command tppe. */
-	pdrvextra_cmd_parm->pbuf = NULL;	    /* Must be NULL here */
-
-	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
-				   GEN_CMD_CODE(_Set_Drv_Extra));
-
-	res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
-exit:
-
-	return res;
-}
-#endif /* CONFIG_8723AU_P2P */
-
 u8 rtw_ps_cmd23a(struct rtw_adapter*padapter)
 {
 	struct cmd_obj *ppscmd;
@@ -1443,11 +1394,11 @@ static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter)
 		return;
 
 	if (psta_bmc->sleepq_len == 0) {
-		u8 val = 0;
+		bool val;
 
-		rtw23a_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
+		val = rtl8723a_chk_hi_queue_empty(padapter);
 
-		while(val == false) {
+		while (val == false) {
 			msleep(100);
 
 			cnt++;
@@ -1455,15 +1406,14 @@ static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter)
 			if (cnt>10)
 				break;
 
-			rtw23a_hal_get_hwreg(padapter,
-					     HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
+			val = rtl8723a_chk_hi_queue_empty(padapter);
 		}
 
 		if (cnt <= 10) {
 			pstapriv->tim_bitmap &= ~BIT(0);
 			pstapriv->sta_dz_bitmap &= ~BIT(0);
 
-			update_beacon23a(padapter, _TIM_IE_, NULL, false);
+			update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 		} else /* re check again */
 			rtw_chk_hi_queue_cmd23a(padapter);
 	}
@@ -1636,16 +1586,6 @@ u8 rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
 	case LPS_CTRL_WK_CID:
 		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
 		break;
-#ifdef CONFIG_8723AU_P2P
-	case P2P_PS_WK_CID:
-		p2p_ps_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
-		break;
-	case P2P_PROTO_WK_CID:
-		/*	Commented by Albert 2011/07/01 */
-		/*	I used the type_size as the type command */
-		p2p_protocol_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
-		break;
-#endif /*  CONFIG_8723AU_P2P */
 #ifdef CONFIG_8723AU_AP_MODE
 	case CHECK_HIQ_WK_CID:
 		rtw_chk_hi_queue_hdl(padapter);
diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
index 780631fd3b6d..8f91bdbc2bbf 100644
--- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
@@ -131,7 +131,7 @@ u8 *rtw_set_fixed_ie23a(unsigned char *pbuf, unsigned int len,
 }
 
 /*  rtw_set_ie23a will update frame length */
-u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, u8 *source, uint *frlen)
+u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen)
 {
 
 	*pbuf = (u8)index;
@@ -413,7 +413,7 @@ int rtw_generate_ie23a(struct registry_priv *pregistrypriv)
 	ie += 2;
 
 	/* SSID */
-	ie = rtw_set_ie23a(ie, _SSID_IE_, pdev_network->Ssid.ssid_len,
+	ie = rtw_set_ie23a(ie, WLAN_EID_SSID, pdev_network->Ssid.ssid_len,
 			pdev_network->Ssid.ssid, &sz);
 
 	/* supported rates */
@@ -431,25 +431,25 @@ int rtw_generate_ie23a(struct registry_priv *pregistrypriv)
 	rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates);
 
 	if (rateLen > 8) {
-		ie = rtw_set_ie23a(ie, _SUPPORTEDRATES_IE_, 8,
+		ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, 8,
 				pdev_network->SupportedRates, &sz);
 		/* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
 	} else {
-		ie = rtw_set_ie23a(ie, _SUPPORTEDRATES_IE_, rateLen,
+		ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, rateLen,
 				pdev_network->SupportedRates, &sz);
 	}
 
 	/* DS parameter set */
-	ie = rtw_set_ie23a(ie, _DSSET_IE_, 1,
+	ie = rtw_set_ie23a(ie, WLAN_EID_DS_PARAMS, 1,
 			   (u8 *)&pdev_network->Configuration.DSConfig, &sz);
 
 	/* IBSS Parameter Set */
 
-	ie = rtw_set_ie23a(ie, _IBSS_PARA_IE_, 2,
+	ie = rtw_set_ie23a(ie, WLAN_EID_IBSS_PARAMS, 2,
 			   (u8 *)&pdev_network->Configuration.ATIMWindow, &sz);
 
 	if (rateLen > 8) {
-		ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8),
+		ie = rtw_set_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8),
 				(pdev_network->SupportedRates + 8), &sz);
 	}
 
@@ -460,60 +460,7 @@ int rtw_generate_ie23a(struct registry_priv *pregistrypriv)
 	return sz;
 }
 
-unsigned char *rtw_get_wpa_ie23a(unsigned char *pie, int *wpa_ie_len, int limit)
-{
-	int len;
-	u16 val16;
-	unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
-	u8 *pbuf = pie;
-	int limit_new = limit;
-
-	while(1) {
-		pbuf = rtw_get_ie23a(pbuf, _WPA_IE_ID_, &len, limit_new);
-
-		if (pbuf) {
-			/* check if oui matches... */
-			if (memcmp((pbuf + 2), wpa_oui_type,
-				   sizeof(wpa_oui_type))) {
-				goto check_next_ie;
-			}
-
-			/* check version... */
-			memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16));
-
-			val16 = le16_to_cpu(val16);
-			if (val16 != 0x0001)
-				goto check_next_ie;
-
-			*wpa_ie_len = *(pbuf + 1);
-
-			return pbuf;
-		} else {
-			*wpa_ie_len = 0;
-			return NULL;
-		}
-
-check_next_ie:
-
-		limit_new = limit - (pbuf - pie) - 2 - len;
-
-		if (limit_new <= 0)
-			break;
-
-		pbuf += (2 + len);
-	}
-
-	*wpa_ie_len = 0;
-
-	return NULL;
-}
-
-unsigned char *rtw_get_wpa2_ie23a(unsigned char *pie, int *rsn_ie_len, int limit)
-{
-	return rtw_get_ie23a(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
-}
-
-int rtw_get_wpa_cipher_suite23a(u8 *s)
+int rtw_get_wpa_cipher_suite23a(const u8 *s)
 {
 	if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN))
 		return WPA_CIPHER_NONE;
@@ -529,7 +476,7 @@ int rtw_get_wpa_cipher_suite23a(u8 *s)
 	return 0;
 }
 
-int rtw_get_wpa2_cipher_suite23a(u8 *s)
+int rtw_get_wpa2_cipher_suite23a(const u8 *s)
 {
 	if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN))
 		return WPA_CIPHER_NONE;
@@ -545,19 +492,19 @@ int rtw_get_wpa2_cipher_suite23a(u8 *s)
 	return 0;
 }
 
-int rtw_parse_wpa_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
+int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
 {
 	int i, ret = _SUCCESS;
 	int left, count;
-	u8 *pos;
-	u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
+	const u8 *pos;
 
 	if (wpa_ie_len <= 0) {
 		/* No WPA IE - fail silently */
 		return _FAIL;
 	}
 
-	if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
+	if ((*wpa_ie != WLAN_EID_VENDOR_SPECIFIC) ||
+	    (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
 	    memcmp(wpa_ie + 2, RTW_WPA_OUI23A_TYPE, WPA_SELECTOR_LEN)) {
 		return _FAIL;
 	}
@@ -612,7 +559,7 @@ int rtw_parse_wpa_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pair
 	if (is_8021x) {
 		if (left >= 6) {
 			pos += 2;
-			if (!memcmp(pos, SUITE_1X, 4)) {
+			if (!memcmp(pos, RTW_WPA_OUI23A_TYPE, 4)) {
 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 					 ("%s : there has 802.1x auth\n",
 					  __func__));
@@ -624,12 +571,12 @@ int rtw_parse_wpa_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pair
 	return ret;
 }
 
-int rtw_parse_wpa2_ie23a(u8* rsn_ie, int rsn_ie_len, int *group_cipher,
+int rtw_parse_wpa2_ie23a(const u8* rsn_ie, int rsn_ie_len, int *group_cipher,
 		      int *pairwise_cipher, int *is_8021x)
 {
 	int i, ret = _SUCCESS;
 	int left, count;
-	u8 *pos;
+	const u8 *pos;
 	u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
 
 	if (rsn_ie_len <= 0) {
@@ -705,11 +652,9 @@ int rtw_get_sec_ie23a(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
 		   u8 *wpa_ie, u16 *wpa_len)
 {
 	u8 authmode, sec_idx, i;
-	u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
 	uint cnt;
 
 
-
 	/* Search required WPA or WPA2 IE and copy to sec_ie[ ] */
 
 	cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
@@ -719,8 +664,8 @@ int rtw_get_sec_ie23a(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
 	while(cnt < in_len) {
 		authmode = in_ie[cnt];
 
-		if ((authmode == _WPA_IE_ID_) &&
-		    !memcmp(&in_ie[cnt+2], &wpa_oui[0], 4)) {
+		if ((authmode == WLAN_EID_VENDOR_SPECIFIC) &&
+		    !memcmp(&in_ie[cnt+2], RTW_WPA_OUI23A_TYPE, 4)) {
 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 					 ("\n rtw_get_wpa_ie23a: sec_idx =%d "
 					  "in_ie[cnt+1]+2 =%d\n",
@@ -788,7 +733,8 @@ u8 rtw_is_wps_ie23a(u8 *ie_ptr, uint *wps_ielen)
 
 	eid = ie_ptr[0];
 
-	if ((eid == _WPA_IE_ID_) && !memcmp(&ie_ptr[2], wps_oui, 4)) {
+	if ((eid == WLAN_EID_VENDOR_SPECIFIC) &&
+	    !memcmp(&ie_ptr[2], wps_oui, 4)) {
 		/* DBG_8723A("==> found WPS_IE.....\n"); */
 		*wps_ielen = ie_ptr[1] + 2;
 		match = true;
@@ -824,7 +770,8 @@ u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
 	while (cnt < in_len) {
 		eid = in_ie[cnt];
 
-		if ((eid == _WPA_IE_ID_) && !memcmp(&in_ie[cnt+2], wps_oui, 4)) {
+		if ((eid == WLAN_EID_VENDOR_SPECIFIC) &&
+		    !memcmp(&in_ie[cnt+2], wps_oui, 4)) {
 			wpsie_ptr = &in_ie[cnt];
 
 			if (wps_ie)
@@ -866,7 +813,7 @@ u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
 	if (len_attr)
 		*len_attr = 0;
 
-	if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
+	if ((wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC) ||
 	    memcmp(wps_ie + 2, wps_oui, 4)) {
 		return attr_ptr;
 	}
@@ -937,237 +884,6 @@ u8 *rtw_get_wps_attr_content23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
 	return NULL;
 }
 
-static int
-rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
-				     struct rtw_ieee802_11_elems *elems,
-				     int show_errors)
-{
-	unsigned int oui;
-
-	/* first 3 bytes in vendor specific information element are the IEEE
-	 * OUI of the vendor. The following byte is used a vendor specific
-	 * sub-type. */
-	if (elen < 4) {
-		if (show_errors) {
-			DBG_8723A("short vendor specific "
-				   "information element ignored (len =%lu)\n",
-				   (unsigned long) elen);
-		}
-		return -1;
-	}
-
-	oui = RTW_GET_BE24(pos);
-	switch (oui) {
-	case WLAN_OUI_MICROSOFT:
-		/* Microsoft/Wi-Fi information elements are further typed and
-		 * subtyped */
-		switch (pos[3]) {
-		case 1:
-			/* Microsoft OUI (00:50:F2) with OUI Type 1:
-			 * real WPA information element */
-			elems->wpa_ie = pos;
-			elems->wpa_ie_len = elen;
-			break;
-		case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
-			if (elen < 5) {
-				DBG_8723A("short WME "
-					   "information element ignored "
-					   "(len =%lu)\n",
-					   (unsigned long) elen);
-				return -1;
-			}
-			switch (pos[4]) {
-			case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
-			case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
-				elems->wme = pos;
-				elems->wme_len = elen;
-				break;
-			case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
-				elems->wme_tspec = pos;
-				elems->wme_tspec_len = elen;
-				break;
-			default:
-				DBG_8723A("unknown WME "
-					   "information element ignored "
-					   "(subtype =%d len =%lu)\n",
-					   pos[4], (unsigned long) elen);
-				return -1;
-			}
-			break;
-		case 4:
-			/* Wi-Fi Protected Setup (WPS) IE */
-			elems->wps_ie = pos;
-			elems->wps_ie_len = elen;
-			break;
-		default:
-			DBG_8723A("Unknown Microsoft "
-				   "information element ignored "
-				   "(type =%d len =%lu)\n",
-				   pos[3], (unsigned long) elen);
-			return -1;
-		}
-		break;
-
-	case OUI_BROADCOM:
-		switch (pos[3]) {
-		case VENDOR_HT_CAPAB_OUI_TYPE:
-			elems->vendor_ht_cap = pos;
-			elems->vendor_ht_cap_len = elen;
-			break;
-		default:
-			DBG_8723A("Unknown Broadcom "
-				   "information element ignored "
-				   "(type =%d len =%lu)\n",
-				   pos[3], (unsigned long) elen);
-			return -1;
-		}
-		break;
-
-	default:
-		DBG_8723A("unknown vendor specific information "
-			   "element ignored (vendor OUI %02x:%02x:%02x "
-			   "len =%lu)\n",
-			   pos[0], pos[1], pos[2], (unsigned long) elen);
-		return -1;
-	}
-
-	return 0;
-}
-
-/**
- * ieee802_11_parse_elems - Parse information elements in management frames
- * @start: Pointer to the start of IEs
- * @len: Length of IE buffer in octets
- * @elems: Data structure for parsed elements
- * @show_errors: Whether to show parsing errors in debug log
- * Returns: Parsing result
- */
-enum parse_res rtw_ieee802_11_parse_elems23a(u8 *start, uint len,
-				struct rtw_ieee802_11_elems *elems,
-				int show_errors)
-{
-	uint left = len;
-	u8 *pos = start;
-	int unknown = 0;
-
-	memset(elems, 0, sizeof(*elems));
-
-	while (left >= 2) {
-		u8 id, elen;
-
-		id = *pos++;
-		elen = *pos++;
-		left -= 2;
-
-		if (elen > left) {
-			if (show_errors) {
-				DBG_8723A("IEEE 802.11 element "
-					   "parse failed (id =%d elen =%d "
-					   "left =%lu)\n",
-					   id, elen, (unsigned long) left);
-			}
-			return ParseFailed;
-		}
-
-		switch (id) {
-		case WLAN_EID_SSID:
-			elems->ssid = pos;
-			elems->ssid_len = elen;
-			break;
-		case WLAN_EID_SUPP_RATES:
-			elems->supp_rates = pos;
-			elems->supp_rates_len = elen;
-			break;
-		case WLAN_EID_FH_PARAMS:
-			elems->fh_params = pos;
-			elems->fh_params_len = elen;
-			break;
-		case WLAN_EID_DS_PARAMS:
-			elems->ds_params = pos;
-			elems->ds_params_len = elen;
-			break;
-		case WLAN_EID_CF_PARAMS:
-			elems->cf_params = pos;
-			elems->cf_params_len = elen;
-			break;
-		case WLAN_EID_TIM:
-			elems->tim = pos;
-			elems->tim_len = elen;
-			break;
-		case WLAN_EID_IBSS_PARAMS:
-			elems->ibss_params = pos;
-			elems->ibss_params_len = elen;
-			break;
-		case WLAN_EID_CHALLENGE:
-			elems->challenge = pos;
-			elems->challenge_len = elen;
-			break;
-		case WLAN_EID_ERP_INFO:
-			elems->erp_info = pos;
-			elems->erp_info_len = elen;
-			break;
-		case WLAN_EID_EXT_SUPP_RATES:
-			elems->ext_supp_rates = pos;
-			elems->ext_supp_rates_len = elen;
-			break;
-		case WLAN_EID_VENDOR_SPECIFIC:
-			if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
-								 elems,
-								 show_errors))
-				unknown++;
-			break;
-		case WLAN_EID_RSN:
-			elems->rsn_ie = pos;
-			elems->rsn_ie_len = elen;
-			break;
-		case WLAN_EID_PWR_CAPABILITY:
-			elems->power_cap = pos;
-			elems->power_cap_len = elen;
-			break;
-		case WLAN_EID_SUPPORTED_CHANNELS:
-			elems->supp_channels = pos;
-			elems->supp_channels_len = elen;
-			break;
-		case WLAN_EID_MOBILITY_DOMAIN:
-			elems->mdie = pos;
-			elems->mdie_len = elen;
-			break;
-		case WLAN_EID_FAST_BSS_TRANSITION:
-			elems->ftie = pos;
-			elems->ftie_len = elen;
-			break;
-		case WLAN_EID_TIMEOUT_INTERVAL:
-			elems->timeout_int = pos;
-			elems->timeout_int_len = elen;
-			break;
-		case WLAN_EID_HT_CAPABILITY:
-			elems->ht_capabilities = pos;
-			elems->ht_capabilities_len = elen;
-			break;
-		case WLAN_EID_HT_OPERATION:
-			elems->ht_operation = pos;
-			elems->ht_operation_len = elen;
-			break;
-		default:
-			unknown++;
-			if (!show_errors)
-				break;
-			DBG_8723A("IEEE 802.11 element parse "
-				   "ignored unknown element (id =%d elen =%d)\n",
-				   id, elen);
-			break;
-		}
-
-		left -= elen;
-		pos += elen;
-	}
-
-	if (left)
-		return ParseFailed;
-
-	return unknown ? ParseUnknown : ParseOK;
-}
-
 static u8 key_char2num(u8 ch)
 {
 	if ((ch >= '0') && (ch <= '9'))
@@ -1214,409 +930,26 @@ void rtw_macaddr_cfg23a(u8 *mac_addr)
 		  MAC_ARG(mac_addr));
 }
 
-void dump_ies23a(u8 *buf, u32 buf_len) {
-	u8* pos = (u8*)buf;
-	u8 id, len;
-
-	while (pos-buf <= buf_len) {
-		id = *pos;
-		len = *(pos + 1);
-
-		DBG_8723A("%s ID:%u, LEN:%u\n", __func__, id, len);
-#ifdef CONFIG_8723AU_P2P
-		dump_p2p_ie23a(pos, len);
-#endif
-		dump_wps_ie23a(pos, len);
-
-		pos += (2 + len);
-	}
-}
-
-void dump_wps_ie23a(u8 *ie, u32 ie_len) {
-	u8* pos = (u8*)ie;
-	u16 id;
-	u16 len;
-
-	u8 *wps_ie;
-	uint wps_ielen;
-
-	wps_ie = rtw_get_wps_ie23a(ie, ie_len, NULL, &wps_ielen);
-	if (wps_ie != ie || wps_ielen == 0)
-		return;
-
-	pos+= 6;
-	while (pos-ie < ie_len) {
-		id = get_unaligned_be16(pos);
-		len = get_unaligned_be16(pos + 2);
-
-		DBG_8723A("%s ID:0x%04x, LEN:%u\n", __func__, id, len);
-
-		pos += (4 + len);
-	}
-}
-
-#ifdef CONFIG_8723AU_P2P
-void dump_p2p_ie23a(u8 *ie, u32 ie_len) {
-	u8* pos = (u8*)ie;
-	u8 id;
-	u16 len;
-
-	u8 *p2p_ie;
-	uint p2p_ielen;
-
-	p2p_ie = rtw_get_p2p_ie23a(ie, ie_len, NULL, &p2p_ielen);
-	if (p2p_ie != ie || p2p_ielen == 0)
-		return;
-
-	pos += 6;
-	while (pos-ie < ie_len) {
-		id = *pos;
-		len = get_unaligned_le16(pos+1);
-
-		DBG_8723A("%s ID:%u, LEN:%u\n", __func__, id, len);
-
-		pos+= (3+len);
-	}
-}
-
-/**
- * rtw_get_p2p_ie23a - Search P2P IE from a series of IEs
- * @in_ie: Address of IEs to search
- * @in_len: Length limit from in_ie
- * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the
- *          buf starting from p2p_ie
- * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of
- *             the entire P2P IE
- *
- * Returns: The address of the P2P IE found, or NULL
- */
-u8 *rtw_get_p2p_ie23a(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
-{
-	uint cnt = 0;
-	u8 *p2p_ie_ptr;
-	u8 eid, p2p_oui[4]={0x50, 0x6F, 0x9A, 0x09};
-
-	if (p2p_ielen)
-		*p2p_ielen = 0;
-
-	while (cnt<in_len) {
-		eid = in_ie[cnt];
-		if ((in_len < 0) || (cnt > MAX_IE_SZ)) {
-			dump_stack();
-			return NULL;
-		}
-		if ((eid == _VENDOR_SPECIFIC_IE_) &&
-		    !memcmp(&in_ie[cnt + 2], p2p_oui, 4)) {
-			p2p_ie_ptr = in_ie + cnt;
-
-			if (p2p_ie != NULL) {
-				memcpy(p2p_ie, &in_ie[cnt],
-				       in_ie[cnt + 1] + 2);
-			}
-
-			if (p2p_ielen != NULL) {
-				*p2p_ielen = in_ie[cnt + 1] + 2;
-			}
-
-			return p2p_ie_ptr;
-
-			break;
-		} else {
-			cnt += in_ie[cnt + 1] + 2; /* goto next */
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * rtw_get_p2p_attr23a - Search a specific P2P attribute from a given P2P IE
- * @p2p_ie: Address of P2P IE to search
- * @p2p_ielen: Length limit from p2p_ie
- * @target_attr_id: The attribute ID of P2P attribute to search
- * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will
- *            be copied to the buf starting from buf_attr
- * @len_attr: If not NULL and the P2P attribute is found, will set to the
- *            length of the entire P2P attribute
- *
- * Returns: the address of the specific WPS attribute found, or NULL
- */
-u8 *rtw_get_p2p_attr23a(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
-		     u8 *buf_attr, u32 *len_attr)
-{
-	u8 *attr_ptr = NULL;
-	u8 *target_attr_ptr = NULL;
-	u8 p2p_oui[4]={0x50, 0x6F, 0x9A, 0x09};
-
-	if (len_attr)
-		*len_attr = 0;
-
-	if (!p2p_ie || (p2p_ie[0] != _VENDOR_SPECIFIC_IE_) ||
-	    memcmp(p2p_ie + 2, p2p_oui, 4)) {
-		return attr_ptr;
-	}
-
-	/*  6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
-	attr_ptr = p2p_ie + 6; /* goto first attr */
-
-	while (attr_ptr - p2p_ie < p2p_ielen) {
-		/*  3 = 1(Attribute ID) + 2(Length) */
-		u8 attr_id = *attr_ptr;
-		u16 attr_data_len = get_unaligned_le16(attr_ptr + 1);
-		u16 attr_len = attr_data_len + 3;
-
-		/* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
-		if (attr_id == target_attr_id) {
-			target_attr_ptr = attr_ptr;
-
-			if (buf_attr)
-				memcpy(buf_attr, attr_ptr, attr_len);
-
-			if (len_attr)
-				*len_attr = attr_len;
-
-			break;
-		} else {
-			attr_ptr += attr_len; /* goto next */
-		}
-	}
-
-	return target_attr_ptr;
-}
-
-/**
- * rtw_get_p2p_attr23a_content - Search a specific P2P attribute content from
- * a given P2P IE
- * @p2p_ie: Address of P2P IE to search
- * @p2p_ielen: Length limit from p2p_ie
- * @target_attr_id: The attribute ID of P2P attribute to search
- * @buf_content: If not NULL and the P2P attribute is found, P2P attribute
- *               content will be copied to the buf starting from buf_content
- * @len_content: If not NULL and the P2P attribute is found, will set to the
- *               length of the P2P attribute content
- *
- * Returns: the address of the specific P2P attribute content found, or NULL
- */
-u8 *rtw_get_p2p_attr23a_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
-			     u8 *buf_content, uint *len_content)
-{
-	u8 *attr_ptr;
-	u32 attr_len;
-
-	if (len_content)
-		*len_content = 0;
-
-	attr_ptr = rtw_get_p2p_attr23a(p2p_ie, p2p_ielen, target_attr_id,
-				    NULL, &attr_len);
-
-	if (attr_ptr && attr_len) {
-		if (buf_content)
-			memcpy(buf_content, attr_ptr + 3, attr_len - 3);
-
-		if (len_content)
-			*len_content = attr_len - 3;
-
-		return attr_ptr+3;
-	}
-
-	return NULL;
-}
-
-u32 rtw_set_p2p_attr_content23a(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
-{
-	u32 a_len;
-
-	*pbuf = attr_id;
-
-	/* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */
-	put_unaligned_le16(attr_len, pbuf + 1);
-
-	if (pdata_attr)
-		memcpy(pbuf + 3, pdata_attr, attr_len);
-
-	a_len = attr_len + 3;
-
-	return a_len;
-}
-
-static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id)
-{
-	u8 *target_attr;
-	u32 target_attr_len;
-	uint ielen = ielen_ori;
-
-	while(1) {
-		target_attr = rtw_get_p2p_attr23a(ie, ielen, attr_id, NULL,
-					     &target_attr_len);
-		if (target_attr && target_attr_len) {
-			u8 *next_attr = target_attr+target_attr_len;
-			uint remain_len = ielen-(next_attr-ie);
-			/* dump_ies23a(ie, ielen); */
-
-			memset(target_attr, 0, target_attr_len);
-			memcpy(target_attr, next_attr, remain_len);
-			memset(target_attr+remain_len, 0, target_attr_len);
-			*(ie + 1) -= target_attr_len;
-			ielen -= target_attr_len;
-		} else {
-			/* if (index>0) */
-			/*	dump_ies23a(ie, ielen); */
-			break;
-		}
-	}
-
-	return ielen;
-}
-
-void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_id)
-{
-	u8 *p2p_ie;
-	uint p2p_ielen, p2p_ielen_ori;
-
-	if ((p2p_ie = rtw_get_p2p_ie23a(bss_ex->IEs + _FIXED_IE_LENGTH_,
-				     bss_ex->IELength - _FIXED_IE_LENGTH_,
-				     NULL, &p2p_ielen_ori))) {
-		p2p_ielen = rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id);
-		if (p2p_ielen != p2p_ielen_ori) {
-			u8 *next_ie_ori = p2p_ie+p2p_ielen_ori;
-			u8 *next_ie = p2p_ie+p2p_ielen;
-			uint remain_len;
-			remain_len = bss_ex->IELength-(next_ie_ori-bss_ex->IEs);
-
-			memcpy(next_ie, next_ie_ori, remain_len);
-			memset(next_ie+remain_len, 0, p2p_ielen_ori-p2p_ielen);
-			bss_ex->IELength -= p2p_ielen_ori-p2p_ielen;
-		}
-	}
-}
-
-#endif /* CONFIG_8723AU_P2P */
-
-#ifdef CONFIG_8723AU_P2P
-int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
-{
-	int match;
-	uint cnt = 0;
-	u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
-
-	match = false;
-
-	if (in_len < 0) {
-		return match;
-	}
-
-	while (cnt < in_len)
-	{
-		eid = in_ie[cnt];
-
-		if ((eid == _VENDOR_SPECIFIC_IE_) &&
-		    !memcmp(&in_ie[cnt+2], wfd_oui, 4)) {
-			if (wfd_ie != NULL) {
-				memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-
-			} else {
-				if (wfd_ielen != NULL) {
-					*wfd_ielen = 0;
-				}
-			}
-
-			if (wfd_ielen != NULL) {
-				*wfd_ielen = in_ie[cnt + 1] + 2;
-			}
-
-			cnt += in_ie[cnt + 1] + 2;
-
-			match = true;
-			break;
-		} else {
-			cnt += in_ie[cnt + 1] +2; /* goto next */
-		}
-	}
-
-	if (match == true) {
-		match = cnt;
-	}
-
-	return match;
-}
-
-/*	attr_content: The output buffer, contains the "body field" of
-	WFD attribute. */
-/*	attr_contentlen: The data length of the "body field" of WFD
-	attribute. */
-int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id,
-			     u8 *attr_content, uint *attr_contentlen)
-{
-	int match;
-	uint cnt = 0;
-	u8 attr_id, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
-
-	match = false;
-
-	if ((wfd_ie[0] != _VENDOR_SPECIFIC_IE_) ||
-	    memcmp(wfd_ie + 2, wfd_oui, 4)) {
-		return match;
-	}
-
-	/*	1 (WFD IE) + 1 (Length) + 3 (OUI) + 1 (OUI Type) */
-	cnt = 6;
-	while (cnt < wfd_ielen) {
-		u16 attrlen = get_unaligned_be16(wfd_ie + cnt + 1);
-
-		attr_id = wfd_ie[cnt];
-		if (attr_id == target_attr_id) {
-			/*	3 -> 1 byte for attribute ID field, 2
-				bytes for length field */
-			if (attr_content)
-				memcpy(attr_content, &wfd_ie[cnt + 3], attrlen);
-
-			if (attr_contentlen)
-				*attr_contentlen = attrlen;
-
-			cnt += attrlen + 3;
-
-			match = true;
-			break;
-		} else {
-			cnt += attrlen + 3; /* goto next */
-		}
-	}
-
-	return match;
-}
-#endif /*  CONFIG_8723AU_P2P */
-
-/* Baron adds to avoid FreeBSD warning */
-int ieee80211_is_empty_essid23a(const char *essid, int essid_len)
-{
-	/* Single white space is for Linksys APs */
-	if (essid_len == 1 && essid[0] == ' ')
-		return 1;
-
-	/* Otherwise, if the entire essid is 0, we assume it is hidden */
-	while (essid_len) {
-		essid_len--;
-		if (essid[essid_len] != '\0')
-			return 0;
-	}
-
-	return 1;
-}
-
 static int rtw_get_cipher_info(struct wlan_network *pnetwork)
 {
-	u32 wpa_ielen;
-	unsigned char *pbuf;
+	const u8 *pbuf;
 	int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
 	int ret = _FAIL;
-	int r;
-	pbuf = rtw_get_wpa_ie23a(&pnetwork->network.IEs[12], &wpa_ielen,
-			      pnetwork->network.IELength - 12);
+	int r, offset, plen;
+	char *pie;
+
+	offset = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
+		offsetof(struct ieee80211_mgmt, u);
+	pie = &pnetwork->network.IEs[offset];
+	plen = pnetwork->network.IELength - offset;
 
-	if (pbuf && (wpa_ielen > 0)) {
+	pbuf = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+				       WLAN_OUI_TYPE_MICROSOFT_WPA, pie, plen);
+
+	if (pbuf && pbuf[1] > 0) {
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-			 ("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen));
-		r = rtw_parse_wpa_ie23a(pbuf, wpa_ielen + 2, &group_cipher,
+			 ("rtw_get_cipher_info: wpa_ielen: %d", pbuf[1]));
+		r = rtw_parse_wpa_ie23a(pbuf, pbuf[1] + 2, &group_cipher,
 				     &pairwise_cipher, &is8021x);
 		if (r == _SUCCESS) {
 			pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
@@ -1630,13 +963,12 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork)
 			ret = _SUCCESS;
 		}
 	} else {
-		pbuf = rtw_get_wpa2_ie23a(&pnetwork->network.IEs[12], &wpa_ielen,
-				       pnetwork->network.IELength - 12);
+		pbuf = cfg80211_find_ie(WLAN_EID_RSN, pie, plen);
 
-		if (pbuf && (wpa_ielen > 0)) {
+		if (pbuf && pbuf[1] > 0) {
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 				 ("get RSN IE\n"));
-			r = rtw_parse_wpa2_ie23a(pbuf, wpa_ielen + 2,
+			r = rtw_parse_wpa2_ie23a(pbuf, pbuf[1] + 2,
 					      &group_cipher, &pairwise_cipher,
 					      &is8021x);
 			if (r == _SUCCESS) {
@@ -1712,8 +1044,8 @@ void rtw_get_bcn_info23a(struct wlan_network *pnetwork)
 	/* get bwmode and ch_offset */
 	/* parsing HT_CAP_IE */
 	p = rtw_get_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
-		       _HT_CAPABILITY_IE_, &len,
-		       pnetwork->network.IELength - _FIXED_IE_LENGTH_);
+			  WLAN_EID_HT_CAPABILITY, &len,
+			  pnetwork->network.IELength - _FIXED_IE_LENGTH_);
 	if (p && len > 0) {
 		pht_cap = (struct ieee80211_ht_cap *)(p + 2);
 		pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info;
@@ -1722,7 +1054,7 @@ void rtw_get_bcn_info23a(struct wlan_network *pnetwork)
 	}
 	/* parsing HT_INFO_IE */
 	p = rtw_get_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
-		       _HT_ADD_INFO_IE_, &len,
+		       WLAN_EID_HT_OPERATION, &len,
 		       pnetwork->network.IELength - _FIXED_IE_LENGTH_);
 	if (p && len > 0) {
 		pht_info = (struct HT_info_element *)(p + 2);
diff --git a/drivers/staging/rtl8723au/core/rtw_ioctl_set.c b/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
index 30d7185e5637..fe4926a4ced6 100644
--- a/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
+++ b/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
@@ -54,7 +54,7 @@ u8 rtw_do_join23a(struct rtw_adapter *padapter)
 		/* we try to issue sitesurvey firstly */
 
 		if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false ||
-		    rtw_to_roaming(padapter) > 0) {
+		    padapter->mlmepriv.to_roaming > 0) {
 			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
 				 ("rtw_do_join23a(): site survey if scanned_queue "
 				  "is empty\n."));
@@ -130,7 +130,7 @@ u8 rtw_do_join23a(struct rtw_adapter *padapter)
 				   queue */
 				/* we try to issue sitesurvey firstly */
 				if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==
-				    false || rtw_to_roaming(padapter) > 0) {
+				    false || padapter->mlmepriv.to_roaming > 0){
 					/* DBG_8723A("rtw_do_join23a() when   no "
 					   "desired bss in scanning queue\n");
 					*/
@@ -539,7 +539,7 @@ exit:
 u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter)
 {
 	int i = 0;
-	u8 *p;
+	const u8 *p;
 	u16 rate = 0, max_rate = 0;
 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
@@ -550,16 +550,16 @@ u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter)
 	u8 rf_type = 0;
 	u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
 	u16 mcs_rate = 0;
-	u32 ht_ielen = 0;
 
 	if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
 	    !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
 		return 0;
 
 	if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) {
-		p = rtw_get_ie23a(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
-			       &ht_ielen, pcur_bss->IELength - 12);
-		if (p && ht_ielen > 0) {
+		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
+				     &pcur_bss->IEs[12],
+				     pcur_bss->IELength - 12);
+		if (p && p[1] > 0) {
 			pht_capie = (struct ieee80211_ht_cap *)(p + 2);
 
 			memcpy(&mcs_rate, &pht_capie->mcs, 2);
@@ -577,8 +577,7 @@ u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter)
 			short_GI_20 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_20) ? 1:0;
 			short_GI_40 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_40) ? 1:0;
 
-			rtw23a_hal_get_hwreg(adapter, HW_VAR_RF_TYPE,
-					  (u8 *)(&rf_type));
+			rf_type = rtl8723a_get_rf_type(adapter);
 			max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
 						pregistrypriv->cbw40_enable,
 						short_GI_20, short_GI_40,
diff --git a/drivers/staging/rtl8723au/core/rtw_mlme.c b/drivers/staging/rtl8723au/core/rtw_mlme.c
index 6cee78785bdc..4d21d623070e 100644
--- a/drivers/staging/rtl8723au/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723au/core/rtw_mlme.c
@@ -53,8 +53,11 @@ int _rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
 	pmlmepriv->nic_hdl = padapter;
 
 	pmlmepriv->fw_state = 0;
-	pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
-	pmlmepriv->scan_mode=SCAN_ACTIVE;/*  1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
+	pmlmepriv->cur_network.network.InfrastructureMode =
+		Ndis802_11AutoUnknown;
+	/*  1: active, 0: pasive. Maybe someday we should rename this
+	    varable to "active_mode" (Jeff) */
+	pmlmepriv->scan_mode = SCAN_ACTIVE;
 
 	spin_lock_init(&pmlmepriv->lock);
 	_rtw_init_queue23a(&pmlmepriv->scanned_queue);
@@ -72,11 +75,10 @@ int _rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
 #ifdef CONFIG_8723AU_AP_MODE
 static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
 {
-	if(*ppie)
-	{
+	if (*ppie) {
 		kfree(*ppie);
 		*plen = 0;
-		*ppie=NULL;
+		*ppie = NULL;
 	}
 }
 #endif
@@ -86,30 +88,45 @@ void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
 #ifdef CONFIG_8723AU_AP_MODE
 	kfree(pmlmepriv->assoc_req);
 	kfree(pmlmepriv->assoc_rsp);
-	rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
-
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
-
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_beacon_ie, &pmlmepriv->wfd_beacon_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_req_ie, &pmlmepriv->wfd_probe_req_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_resp_ie, &pmlmepriv->wfd_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_go_probe_resp_ie, &pmlmepriv->wfd_go_probe_resp_ie_len);
-	rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_req_ie, &pmlmepriv->wfd_assoc_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie,
+			      &pmlmepriv->wps_beacon_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie,
+			      &pmlmepriv->wps_probe_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie,
+			      &pmlmepriv->wps_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie,
+			      &pmlmepriv->wps_assoc_resp_ie_len);
+
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie,
+			      &pmlmepriv->p2p_beacon_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie,
+			      &pmlmepriv->p2p_probe_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie,
+			      &pmlmepriv->p2p_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie,
+			      &pmlmepriv->p2p_go_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie,
+			      &pmlmepriv->p2p_assoc_req_ie_len);
+
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_beacon_ie,
+			      &pmlmepriv->wfd_beacon_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_req_ie,
+			      &pmlmepriv->wfd_probe_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_resp_ie,
+			      &pmlmepriv->wfd_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_go_probe_resp_ie,
+			      &pmlmepriv->wfd_go_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_req_ie,
+			      &pmlmepriv->wfd_assoc_req_ie_len);
 #endif
 }
 
-void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
+void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
 {
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+		 ("rtw_free_mlme_priv23a\n"));
 
 	rtw23a_free_mlme_priv_ie_data(pmlmepriv);
-
 }
 
 struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
@@ -129,8 +146,8 @@ struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
 	return pnetwork;
 }
 
-void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
-		       struct wlan_network *pnetwork, u8 isfreeall)
+static void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
+				 struct wlan_network *pnetwork, u8 isfreeall)
 {
 	u32 lifetime = SCANQUEUE_LIFETIME;
 
@@ -150,10 +167,9 @@ void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
 }
 
 void _rtw_free_network23a_nolock23a(struct mlme_priv *pmlmepriv,
-			      struct wlan_network *pnetwork)
+				    struct wlan_network *pnetwork)
 {
-
-	if (pnetwork == NULL)
+	if (!pnetwork)
 		return;
 
 	if (pnetwork->fixed == true)
@@ -165,9 +181,9 @@ void _rtw_free_network23a_nolock23a(struct mlme_priv *pmlmepriv,
 }
 
 /*
-	return the wlan_network with the matching addr
+ return the wlan_network with the matching addr
 
-	Shall be calle under atomic context... to avoid possible racing condition...
+ Shall be calle under atomic context... to avoid possible racing condition...
 */
 struct wlan_network *
 _rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
@@ -194,7 +210,7 @@ _rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
 		plist = plist->next;
         }
 
-	if(plist == phead)
+	if (plist == phead)
 		pnetwork = NULL;
 
 	/* spin_unlock_bh(&scanned_queue->lock); */
@@ -208,7 +224,7 @@ void _rtw_free_network23a_queue23a(struct rtw_adapter *padapter, u8 isfreeall)
 {
 	struct list_head *phead, *plist, *ptmp;
 	struct wlan_network *pnetwork;
-	struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
 
 	spin_lock_bh(&scanned_queue->lock);
@@ -222,20 +238,21 @@ void _rtw_free_network23a_queue23a(struct rtw_adapter *padapter, u8 isfreeall)
 	}
 
 	spin_unlock_bh(&scanned_queue->lock);
-
 }
 
-int rtw_if_up23a(struct rtw_adapter *padapter)	{
-
+int rtw_if_up23a(struct rtw_adapter *padapter)
+{
 	int res;
 
-	if(padapter->bDriverStopped || padapter->bSurpriseRemoved ||
-		(check_fwstate(&padapter->mlmepriv, _FW_LINKED)== false)) {
-		RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
-		res=false;
-	}
-	else
-		res=  true;
+	if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
+	    check_fwstate(&padapter->mlmepriv, _FW_LINKED) == false) {
+		RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+			 ("rtw_if_up23a:bDriverStopped(%d) OR "
+			  "bSurpriseRemoved(%d)", padapter->bDriverStopped,
+			  padapter->bSurpriseRemoved));
+		res = false;
+	} else
+		res =  true;
 
 	return res;
 }
@@ -247,85 +264,127 @@ void rtw_generate_random_ibss23a(u8* pibss)
 	pibss[0] = 0x02;  /* in ad-hoc mode bit1 must set to 1 */
 	pibss[1] = 0x11;
 	pibss[2] = 0x87;
-	pibss[3] = (u8)(curtime & 0xff) ;/* p[0]; */
-	pibss[4] = (u8)((curtime>>8) & 0xff) ;/* p[1]; */
-	pibss[5] = (u8)((curtime>>16) & 0xff) ;/* p[2]; */
+	pibss[3] = curtime & 0xff;/* p[0]; */
+	pibss[4] = (curtime >> 8) & 0xff;/* p[1]; */
+	pibss[5] = (curtime >> 16) & 0xff;/* p[2]; */
 
 	return;
 }
 
-u8 *rtw_get_capability23a_from_ie(u8 *ie)
+void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming)
 {
-	return ie + 8 + 2;
+	if (to_roaming == 0)
+		adapter->mlmepriv.to_join = false;
+	adapter->mlmepriv.to_roaming = to_roaming;
 }
 
-u16 rtw_get_capability23a(struct wlan_bssid_ex *bss)
+static void _rtw_roaming(struct rtw_adapter *padapter,
+			 struct wlan_network *tgt_network)
 {
-	u16	val;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wlan_network *pnetwork;
+	int do_join_r;
 
-	memcpy((u8 *)&val, rtw_get_capability23a_from_ie(bss->IEs), 2);
+	if (tgt_network)
+		pnetwork = tgt_network;
+	else
+		pnetwork = &pmlmepriv->cur_network;
 
-	return le16_to_cpu(val);
+	if (padapter->mlmepriv.to_roaming > 0) {
+		DBG_8723A("roaming from %s("MAC_FMT"), length:%d\n",
+			  pnetwork->network.Ssid.ssid,
+			  MAC_ARG(pnetwork->network.MacAddress),
+			  pnetwork->network.Ssid.ssid_len);
+		memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid,
+		       sizeof(struct cfg80211_ssid));
+
+		pmlmepriv->assoc_by_bssid = false;
+
+		while (1) {
+			do_join_r = rtw_do_join23a(padapter);
+			if (do_join_r == _SUCCESS)
+				break;
+			else {
+				DBG_8723A("roaming do_join return %d\n",
+					  do_join_r);
+				pmlmepriv->to_roaming--;
+
+				if (padapter->mlmepriv.to_roaming > 0)
+					continue;
+				else {
+					DBG_8723A("%s(%d) -to roaming fail, "
+						  "indicate_disconnect\n",
+						  __func__, __LINE__);
+					rtw_indicate_disconnect23a(padapter);
+					break;
+				}
+			}
+		}
+	}
 }
 
-u8 *rtw_get_timestampe_from_ie23a(u8 *ie)
+void rtw23a_roaming(struct rtw_adapter *padapter,
+		    struct wlan_network *tgt_network)
 {
-	return ie + 0;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	spin_lock_bh(&pmlmepriv->lock);
+	_rtw_roaming(padapter, tgt_network);
+	spin_unlock_bh(&pmlmepriv->lock);
 }
 
-u8 *rtw_get_beacon_interval23a_from_ie(u8 *ie)
+u8 *rtw_get_capability23a_from_ie(u8 *ie)
 {
-	return ie + 8;
+	return ie + 8 + 2;
 }
 
-int	rtw_init_mlme_priv23a (struct rtw_adapter *padapter)/* struct	mlme_priv *pmlmepriv) */
+u16 rtw_get_capability23a(struct wlan_bssid_ex *bss)
 {
-	int	res;
+	u16 val;
 
-	res = _rtw_init_mlme_priv23a(padapter);/*  (pmlmepriv); */
+	memcpy(&val, rtw_get_capability23a_from_ie(bss->IEs), 2);
 
-	return res;
+	return le16_to_cpu(val);
 }
 
-void rtw_free_mlme_priv23a (struct mlme_priv *pmlmepriv)
+u8 *rtw_get_beacon_interval23a_from_ie(u8 *ie)
 {
+	return ie + 8;
+}
 
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv23a\n"));
-	_rtw_free_mlme_priv23a(pmlmepriv);
+int rtw_init_mlme_priv23a (struct rtw_adapter *padapter)
+{
+	int	res;
 
+	res = _rtw_init_mlme_priv23a(padapter);
+
+	return res;
 }
 
-void rtw_free_network(struct mlme_priv *pmlmepriv, struct	wlan_network *pnetwork, u8 is_freeall);
-void rtw_free_network(struct mlme_priv *pmlmepriv, struct	wlan_network *pnetwork, u8 is_freeall)/* struct	wlan_network *pnetwork, _queue	*free_queue) */
+void rtw_free_network(struct mlme_priv *pmlmepriv,
+		      struct wlan_network *pnetwork, u8 is_freeall)
 {
-
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
 		 ("rtw_free_network ==> ssid = %s\n\n" ,
 		  pnetwork->network.Ssid.ssid));
 	_rtw_free_network23a(pmlmepriv, pnetwork, is_freeall);
-
 }
 
-void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork);
-void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
+void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
+			     struct wlan_network *pnetwork)
 {
-
-	/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_network ==> ssid = %s\n\n" , pnetwork->network.Ssid.ssid)); */
 	_rtw_free_network23a_nolock23a(pmlmepriv, pnetwork);
-
 }
 
 void rtw_free_network_queue23a(struct rtw_adapter* dev, u8 isfreeall)
 {
-
 	_rtw_free_network23a_queue23a(dev, isfreeall);
-
 }
 
 /*
-	return the wlan_network with the matching addr
+ return the wlan_network with the matching addr
 
-	Shall be calle under atomic context... to avoid possible racing condition...
+ Shall be calle under atomic context... to avoid possible racing condition...
 */
 struct	wlan_network *
 rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
@@ -337,25 +396,20 @@ rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
 	return pnetwork;
 }
 
-int rtw_is_same_ibss23a(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
+int rtw_is_same_ibss23a(struct rtw_adapter *adapter,
+			struct wlan_network *pnetwork)
 {
 	int ret = true;
 	struct security_priv *psecuritypriv = &adapter->securitypriv;
 
-	if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
-		    (pnetwork->network.Privacy == 0))
-	{
+	if (psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_ &&
+	    pnetwork->network.Privacy == 0)
 		ret = false;
-	}
-	else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
-		 (pnetwork->network.Privacy == 1))
-	{
+	else if (psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_ &&
+		 pnetwork->network.Privacy == 1)
 		ret = false;
-	}
 	else
-	{
 		ret = true;
-	}
 
 	return ret;
 }
@@ -363,18 +417,16 @@ int rtw_is_same_ibss23a(struct rtw_adapter *adapter, struct wlan_network *pnetwo
 inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b);
 inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
 {
-	/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("(%s,%d)(%s,%d)\n", */
-	/*		a->Ssid.Ssid, a->Ssid.SsidLength, b->Ssid.Ssid, b->Ssid.SsidLength)); */
 	return (a->Ssid.ssid_len == b->Ssid.ssid_len) &&
 		!memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len);
 }
 
 int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
 {
-	 u16 s_cap, d_cap;
+	u16 s_cap, d_cap;
 
-	memcpy((u8 *)&s_cap, rtw_get_capability23a_from_ie(src->IEs), 2);
-	memcpy((u8 *)&d_cap, rtw_get_capability23a_from_ie(dst->IEs), 2);
+	memcpy(&s_cap, rtw_get_capability23a_from_ie(src->IEs), 2);
+	memcpy(&d_cap, rtw_get_capability23a_from_ie(dst->IEs), 2);
 
 	s_cap = le16_to_cpu(s_cap);
 	d_cap = le16_to_cpu(d_cap);
@@ -389,10 +441,10 @@ int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
 		 (d_cap & WLAN_CAPABILITY_ESS)));
 }
 
-struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
+struct wlan_network *
+rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
 {
 	struct list_head *plist, *phead;
-
 	struct wlan_network *pwlan;
 	struct wlan_network *oldest = NULL;
 
@@ -412,7 +464,7 @@ struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_qu
 }
 
 void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
-	struct rtw_adapter * padapter, bool update_ie)
+		       struct rtw_adapter *padapter, bool update_ie)
 {
 	u8 ss_ori = dst->PhyInfo.SignalStrength;
 	u8 sq_ori = dst->PhyInfo.SignalQuality;
@@ -426,30 +478,35 @@ void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
 	u8 sq_final;
 	long rssi_final;
 
-	DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n",
+	DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, "
+		  "ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n",
 		  __func__, src->Ssid.ssid, src->MacAddress,
 		  src->Configuration.DSConfig, ss_ori, sq_ori, rssi_ori,
 		  ss_smp, sq_smp, rssi_smp
 	);
 
 	/* The rule below is 1/5 for sample value, 4/5 for history value */
-	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
+	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
+	    is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
 		/* Take the recvpriv's value for the connected AP*/
 		ss_final = padapter->recvpriv.signal_strength;
 		sq_final = padapter->recvpriv.signal_qual;
-		/* the rssi value here is undecorated, and will be used for antenna diversity */
+		/* the rssi value here is undecorated, and will be
+		   used for antenna diversity */
 		if (sq_smp != 101) /* from the right channel */
 			rssi_final = (src->Rssi+dst->Rssi*4)/5;
 		else
 			rssi_final = rssi_ori;
-	}
-	else {
+	} else {
 		if (sq_smp != 101) { /* from the right channel */
-			ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
-			sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
-			rssi_final = (src->Rssi+dst->Rssi*4)/5;
+			ss_final = ((u32)src->PhyInfo.SignalStrength +
+				    (u32)dst->PhyInfo.SignalStrength * 4) / 5;
+			sq_final = ((u32)src->PhyInfo.SignalQuality +
+				    (u32)dst->PhyInfo.SignalQuality * 4) / 5;
+			rssi_final = src->Rssi+dst->Rssi * 4 / 5;
 		} else {
-			/* bss info not receving from the right channel, use the original RX signal infos */
+			/* bss info not receving from the right channel, use
+			   the original RX signal infos */
 			ss_final = dst->PhyInfo.SignalStrength;
 			sq_final = dst->PhyInfo.SignalQuality;
 			rssi_final = dst->Rssi;
@@ -458,35 +515,32 @@ void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
 	}
 
 	if (update_ie)
-		memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
+		memcpy(dst, src, get_wlan_bssid_ex_sz(src));
 
 	dst->PhyInfo.SignalStrength = ss_final;
 	dst->PhyInfo.SignalQuality = sq_final;
 	dst->Rssi = rssi_final;
 
-	DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n",
-		  __func__, dst->Ssid.ssid, dst->MacAddress,
+	DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, "
+		  "RawRSSI:%ld\n",  __func__, dst->Ssid.ssid, dst->MacAddress,
 		  dst->PhyInfo.SignalStrength,
 		  dst->PhyInfo.SignalQuality, dst->Rssi);
-
 }
 
-static void update_current_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
+static void update_current_network(struct rtw_adapter *adapter,
+				   struct wlan_bssid_ex *pnetwork)
 {
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
-	if ((check_fwstate(pmlmepriv, _FW_LINKED)== true) && (is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)))
-	{
-		/* RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"Same Network\n"); */
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 
-		/* if(pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
-		{
-			update_network23a(&pmlmepriv->cur_network.network, pnetwork,adapter, true);
-			rtw_update_protection23a(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
-									pmlmepriv->cur_network.network.IELength);
-		}
+	if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+	    is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) {
+		update_network23a(&pmlmepriv->cur_network.network,
+				  pnetwork,adapter, true);
+		rtw_update_protection23a(adapter,
+					 pmlmepriv->cur_network.network.IEs +
+					 sizeof (struct ndis_802_11_fixed_ies),
+					 pmlmepriv->cur_network.network.IELength);
 	}
-
 }
 
 /*
@@ -494,7 +548,8 @@ static void update_current_network(struct rtw_adapter *adapter, struct wlan_bssi
 Caller must hold pmlmepriv->lock first.
 
 */
-void rtw_update_scanned_network23a(struct rtw_adapter *adapter, struct wlan_bssid_ex *target)
+void rtw_update_scanned_network23a(struct rtw_adapter *adapter,
+				   struct wlan_bssid_ex *target)
 {
 	struct list_head *plist, *phead;
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
@@ -561,19 +616,20 @@ void rtw_update_scanned_network23a(struct rtw_adapter *adapter, struct wlan_bssi
 
 		/* target.reserved == 1, means that scanned network is
 		 * a bcn frame. */
-		if ((pnetwork->network.IELength>target->IELength) &&
-		    (target->reserved == 1))
+		if (pnetwork->network.IELength > target->IELength &&
+		    target->reserved == 1)
 			update_ie = false;
 
-		update_network23a(&pnetwork->network, target,adapter, update_ie);
+		update_network23a(&pnetwork->network, target,adapter,
+				  update_ie);
 	}
 
 exit:
 	spin_unlock_bh(&queue->lock);
-
 }
 
-void rtw_add_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
+void rtw_add_network(struct rtw_adapter *adapter,
+		     struct wlan_bssid_ex *pnetwork)
 {
 	update_current_network(adapter, pnetwork);
 	rtw_update_scanned_network23a(adapter, pnetwork);
@@ -585,7 +641,8 @@ void rtw_add_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork
 /*			   (3) WMM */
 /*			   (4) HT */
 /*                      (5) others */
-int rtw_is_desired_network(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
+int rtw_is_desired_network(struct rtw_adapter *adapter,
+			   struct wlan_network *pnetwork)
 {
 	struct security_priv *psecuritypriv = &adapter->securitypriv;
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
@@ -600,31 +657,31 @@ int rtw_is_desired_network(struct rtw_adapter *adapter, struct wlan_network *pne
 	desired_encmode = psecuritypriv->ndisencryptstatus;
 	privacy = pnetwork->network.Privacy;
 
-	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
-	{
-		if (rtw_get_wps_ie23a(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen)!= NULL)
-		{
+	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
+		if (rtw_get_wps_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
+				      pnetwork->network.IELength -
+				      _FIXED_IE_LENGTH_, NULL, &wps_ielen))
 			return true;
-		}
 		else
-		{
 			return false;
-		}
 	}
-	if (adapter->registrypriv.wifi_spec == 1) /* for  correct flow of 8021X  to do.... */
-	{
-		if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
+	if (adapter->registrypriv.wifi_spec == 1) {
+		/* for  correct flow of 8021X  to do.... */
+		if (desired_encmode == Ndis802_11EncryptionDisabled &&
+		    privacy != 0)
 	            bselected = false;
 	}
 
-	if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
-		DBG_8723A("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
+	if (desired_encmode != Ndis802_11EncryptionDisabled &&
+	    privacy == 0) {
+		DBG_8723A("desired_encmode: %d, privacy: %d\n",
+			  desired_encmode, privacy);
 		bselected = false;
 	}
 
-	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
-	{
-		if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
+	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+		if (pnetwork->network.InfrastructureMode !=
+		    pmlmepriv->cur_network.network.InfrastructureMode)
 			bselected = false;
 	}
 
@@ -632,15 +689,14 @@ int rtw_is_desired_network(struct rtw_adapter *adapter, struct wlan_network *pne
 }
 
 /* TODO: Perry : For Power Management */
-void rtw_atimdone_event_callback23a(struct rtw_adapter	*adapter , u8 *pbuf)
+void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 {
-
 	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("receive atimdone_evet\n"));
 
 	return;
 }
 
-void rtw_survey_event_cb23a(struct rtw_adapter	*adapter, u8 *pbuf)
+void rtw_survey_event_cb23a(struct rtw_adapter *adapter, u8 *pbuf)
 {
 	u32 len;
 	struct wlan_bssid_ex *pnetwork;
@@ -648,31 +704,36 @@ void rtw_survey_event_cb23a(struct rtw_adapter	*adapter, u8 *pbuf)
 
 	pnetwork = (struct wlan_bssid_ex *)pbuf;
 
-	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_survey_event_cb23a, ssid=%s\n",  pnetwork->Ssid.ssid));
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+		 ("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
 
 	len = get_wlan_bssid_ex_sz(pnetwork);
-	if(len > (sizeof(struct wlan_bssid_ex)))
-	{
-		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n ****rtw_survey_event_cb23a: return a wrong bss ***\n"));
+	if (len > (sizeof(struct wlan_bssid_ex))) {
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+			 ("\n ****rtw_survey_event_cb23a: return a wrong "
+			  "bss ***\n"));
 		return;
 	}
 
 	spin_lock_bh(&pmlmepriv->lock);
 
 	/*  update IBSS_network 's timestamp */
-	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true)
-	{
-		/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
+	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+		/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+		   "rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
 		if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
 				     pnetwork->MacAddress)) {
-			struct wlan_network* ibss_wlan = NULL;
+			struct wlan_network* ibss_wlan;
 
-			memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
+			memcpy(pmlmepriv->cur_network.network.IEs,
+			       pnetwork->IEs, 8);
 			spin_lock_bh(&pmlmepriv->scanned_queue.lock);
-			ibss_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue,  pnetwork->MacAddress);
-			if (ibss_wlan)
-			{
-				memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
+			ibss_wlan = rtw_find_network23a(
+				&pmlmepriv->scanned_queue,
+				pnetwork->MacAddress);
+			if (ibss_wlan) {
+				memcpy(ibss_wlan->network.IEs,
+				       pnetwork->IEs, 8);
 				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 				goto exit;
 			}
@@ -681,8 +742,7 @@ void rtw_survey_event_cb23a(struct rtw_adapter	*adapter, u8 *pbuf)
 	}
 
 	/*  lock pmlmepriv->lock when you accessing network_q */
-	if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false)
-	{
+	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == false) {
 	        if (pnetwork->Ssid.ssid[0] == 0)
 			pnetwork->Ssid.ssid_len = 0;
 
@@ -696,10 +756,12 @@ exit:
 	return;
 }
 
-void rtw_surveydone_event_callback23a(struct rtw_adapter	*adapter, u8 *pbuf)
+void rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 {
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+	struct wlan_bssid_ex *pdev_network;
+	u8 *pibss;
 
 	spin_lock_bh(&pmlmepriv->lock);
 
@@ -709,47 +771,62 @@ void rtw_surveydone_event_callback23a(struct rtw_adapter	*adapter, u8 *pbuf)
 		pmlmepriv->wps_probe_req_ie = NULL;
 	}
 
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback23a: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+		 ("rtw_surveydone_event_callback23a: fw_state:%x\n\n",
+		  get_fwstate(pmlmepriv)));
 
 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
 		del_timer_sync(&pmlmepriv->scan_to_timer);
 
 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 	} else {
-
-		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
+		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+			 ("nic status =%x, survey done event comes too late!\n",
+			  get_fwstate(pmlmepriv)));
 	}
 
 	rtw_set_signal_stat_timer(&adapter->recvpriv);
 
 	if (pmlmepriv->to_join == true) {
-		if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
+		if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 			if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
 				set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 
-				if (rtw_select_and_join_from_scanned_queue23a(pmlmepriv) == _SUCCESS) {
+				if (rtw_select_and_join_from_scanned_queue23a(
+					    pmlmepriv) == _SUCCESS) {
 					mod_timer(&pmlmepriv->assoc_timer,
 						  jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
 				} else {
-					struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
-					u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
+					pdev_network = &adapter->registrypriv.dev_network;
+					pibss = adapter->registrypriv.dev_network.MacAddress;
 
-					_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+					_clr_fwstate_(pmlmepriv,
+						      _FW_UNDER_SURVEY);
 
-					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
+					RT_TRACE(_module_rtl871x_mlme_c_,
+						 _drv_err_,
+						 ("switching to adhoc "
+						  "master\n"));
 
-					memset(&pdev_network->Ssid, 0, sizeof(struct cfg80211_ssid));
-					memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct cfg80211_ssid));
+					memset(&pdev_network->Ssid, 0,
+					       sizeof(struct cfg80211_ssid));
+					memcpy(&pdev_network->Ssid,
+					       &pmlmepriv->assoc_ssid,
+					       sizeof(struct cfg80211_ssid));
 
-					rtw_update_registrypriv_dev_network23a(adapter);
+					rtw_update_registrypriv_dev_network23a(
+						adapter);
 					rtw_generate_random_ibss23a(pibss);
 
-					pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+					pmlmepriv->fw_state =
+						WIFI_ADHOC_MASTER_STATE;
 
-					if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
-					{
-					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd23a status FAIL\n"));
-					}
+					if (rtw_createbss_cmd23a(adapter) !=
+					    _SUCCESS)
+					RT_TRACE(_module_rtl871x_mlme_c_,
+						 _drv_err_,
+						 ("Error =>rtw_createbss_cmd23a"
+						  " status FAIL\n"));
 
 					pmlmepriv->to_join = false;
 				}
@@ -758,27 +835,32 @@ void rtw_surveydone_event_callback23a(struct rtw_adapter	*adapter, u8 *pbuf)
 			int ret;
 			set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 			pmlmepriv->to_join = false;
-			ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
+			ret = rtw_select_and_join_from_scanned_queue23a(
+				pmlmepriv);
 			if (ret == _SUCCESS) {
 				unsigned long e;
 				e = msecs_to_jiffies(MAX_JOIN_TIMEOUT);
 				mod_timer(&pmlmepriv->assoc_timer, jiffies + e);
-			} else if (ret == 2)/* there is no need to wait for join */
-			{
+			} else if (ret == 2) {/* there is no need to wait */
 				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 				rtw_indicate_connect23a(adapter);
 			} else {
-				DBG_8723A("try_to_join, but select scanning queue fail, to_roaming:%d\n", rtw_to_roaming(adapter));
-				if (rtw_to_roaming(adapter) != 0) {
-					if (--pmlmepriv->to_roaming == 0
-						|| _SUCCESS != rtw_sitesurvey_cmd23a(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)
-					) {
+				DBG_8723A("try_to_join, but select scanning "
+					  "queue fail, to_roaming:%d\n",
+					  adapter->mlmepriv.to_roaming);
+				if (adapter->mlmepriv.to_roaming) {
+					if (--pmlmepriv->to_roaming == 0 ||
+					    rtw_sitesurvey_cmd23a(
+						    adapter,
+						    &pmlmepriv->assoc_ssid, 1,
+						    NULL, 0) != _SUCCESS) {
 						rtw_set_roaming(adapter, 0);
-						rtw_free_assoc_resources23a(adapter, 1);
-						rtw_indicate_disconnect23a(adapter);
-					} else {
+						rtw_free_assoc_resources23a(
+							adapter, 1);
+						rtw_indicate_disconnect23a(
+							adapter);
+					} else
 						pmlmepriv->to_join = true;
-					}
 				}
 				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 			}
@@ -787,18 +869,12 @@ void rtw_surveydone_event_callback23a(struct rtw_adapter	*adapter, u8 *pbuf)
 
 	spin_unlock_bh(&pmlmepriv->lock);
 
-#ifdef CONFIG_8723AU_P2P
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-		p2p_ps_wk_cmd23a(adapter, P2P_PS_SCAN_DONE, 0);
-#endif /*  CONFIG_8723AU_P2P */
-
 	rtw_os_xmit_schedule23a(adapter);
 
-	if(pmlmeext->sitesurvey_res.bss_cnt == 0)
+	if (pmlmeext->sitesurvey_res.bss_cnt == 0)
 		rtw_hal_sreset_reset23a(adapter);
 
 	rtw_cfg80211_surveydone_event_callback(adapter);
-
 }
 
 void rtw_dummy_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf)
@@ -809,7 +885,7 @@ void rtw23a_fwdbg_event_callback(struct rtw_adapter *adapter , u8 *pbuf)
 {
 }
 
-static void free_scanqueue(struct	mlme_priv *pmlmepriv)
+static void free_scanqueue(struct mlme_priv *pmlmepriv)
 {
 	struct wlan_network *pnetwork;
 	struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue;
@@ -827,42 +903,38 @@ static void free_scanqueue(struct	mlme_priv *pmlmepriv)
         }
 
 	spin_unlock_bh(&scan_queue->lock);
-
 }
 
 /*
-*rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
-*/
-void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, int lock_scanned_queue)
+ *rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
+ */
+void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
+				 int lock_scanned_queue)
 {
-	struct wlan_network* pwlan = NULL;
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
-	struct	sta_priv *pstapriv = &adapter->stapriv;
+	struct wlan_network* pwlan;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct sta_priv *pstapriv = &adapter->stapriv;
 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+	struct sta_info* psta;
 
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources23a\n"));
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
-		MAC_ARG(tgt_network->network.MacAddress), tgt_network->network.Ssid.ssid));
-
-	if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE))
-	{
-		struct sta_info* psta;
-
-		psta = rtw_get_stainfo23a(&adapter->stapriv, tgt_network->network.MacAddress);
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+		 ("+rtw_free_assoc_resources23a\n"));
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+		 ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
+		  MAC_ARG(tgt_network->network.MacAddress),
+		  tgt_network->network.Ssid.ssid));
 
-		{
-			spin_lock_bh(&pstapriv->sta_hash_lock);
-			rtw_free_stainfo23a(adapter,  psta);
-		}
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
+		psta = rtw_get_stainfo23a(&adapter->stapriv,
+					  tgt_network->network.MacAddress);
 
+		spin_lock_bh(&pstapriv->sta_hash_lock);
+		rtw_free_stainfo23a(adapter,  psta);
 		spin_unlock_bh(&pstapriv->sta_hash_lock);
-
 	}
 
-	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
-	{
-		struct sta_info* psta;
-
+	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE |
+			  WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
 		rtw_free_all_stainfo23a(adapter);
 
 		psta = rtw_get_bcmc_stainfo23a(adapter);
@@ -873,23 +945,25 @@ void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, int lock_scanned_q
 		rtw_init_bcmc_stainfo23a(adapter);
 	}
 
-	if(lock_scanned_queue)
+	if (lock_scanned_queue)
 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 
-	pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
-	if(pwlan)
+	pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
+				    tgt_network->network.MacAddress);
+	if (pwlan)
 		pwlan->fixed = false;
 	else
-		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_assoc_resources23a : pwlan== NULL\n\n"));
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+			 ("rtw_free_assoc_resources23a : pwlan== NULL\n"));
 
-	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1))
+	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
+	    adapter->stapriv.asoc_sta_count == 1)
 		rtw_free_network_nolock(pmlmepriv, pwlan);
 
-	if(lock_scanned_queue)
+	if (lock_scanned_queue)
 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
 	pmlmepriv->key_mask = 0;
-
 }
 
 /*
@@ -897,46 +971,54 @@ void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, int lock_scanned_q
 */
 void rtw_indicate_connect23a(struct rtw_adapter *padapter)
 {
-	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect23a\n"));
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+		 ("+rtw_indicate_connect23a\n"));
 
 	pmlmepriv->to_join = false;
 
-	if(!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+	if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
 		set_fwstate(pmlmepriv, _FW_LINKED);
 
 		rtw_led_control(padapter, LED_CTL_LINK);
 
-		rtw_os_indicate_connect23a(padapter);
+		rtw_cfg80211_indicate_connect(padapter);
+
+		netif_carrier_on(padapter->pnetdev);
+
+		if (padapter->pid[2] != 0)
+			kill_pid(find_vpid(padapter->pid[2]), SIGALRM, 1);
 	}
 
 	rtw_set_roaming(padapter, 0);
 
 	rtw_set_scan_deny(padapter, 3000);
 
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect23a: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
-
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+		 ("-rtw_indicate_connect23a: fw_state=0x%08x\n",
+		  get_fwstate(pmlmepriv)));
 }
 
 /*
-*rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
-*/
+ *rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
+ */
 void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
 {
 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect23a\n"));
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+		 ("+rtw_indicate_disconnect23a\n"));
 
 	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
 
         /* DBG_8723A("clear wps when %s\n", __func__); */
 
-	if (rtw_to_roaming(padapter) > 0)
+	if (padapter->mlmepriv.to_roaming > 0)
 		_clr_fwstate_(pmlmepriv, _FW_LINKED);
 
 	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
-	    (rtw_to_roaming(padapter) <= 0)) {
+	    padapter->mlmepriv.to_roaming <= 0) {
 		rtw_os_indicate_disconnect23a(padapter);
 
 		/* set ips_deny_time to avoid enter IPS before LPS leave */
@@ -951,17 +1033,7 @@ void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
 
 	}
 
-#ifdef CONFIG_8723AU_P2P
-	p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
-#endif /*  CONFIG_8723AU_P2P */
-
 	rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1);
-
-}
-
-inline void rtw_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted)
-{
-	rtw_os_indicate_scan_done23a(padapter, aborted);
 }
 
 void rtw_scan_abort23a(struct rtw_adapter *adapter)
@@ -974,36 +1046,39 @@ void rtw_scan_abort23a(struct rtw_adapter *adapter)
 	pmlmeext->scan_abort = true;
 	while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
 	       jiffies_to_msecs(jiffies - start) <= 200) {
-
 		if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
 			break;
 
-		DBG_8723A(FUNC_NDEV_FMT"fw_state = _FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
+		DBG_8723A(FUNC_NDEV_FMT "fw_state = _FW_UNDER_SURVEY!\n",
+			  FUNC_NDEV_ARG(adapter->pnetdev));
 		msleep(20);
 	}
 
 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
 		if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
-			DBG_8723A(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
-		rtw_indicate_scan_done23a(adapter, true);
+			DBG_8723A(FUNC_NDEV_FMT "waiting for scan_abort time "
+				  "out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
+		rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev),
+						true);
 	}
 	pmlmeext->scan_abort = false;
 }
 
-static struct sta_info *rtw_joinbss_update_stainfo(struct rtw_adapter *padapter, struct wlan_network *pnetwork)
+static struct sta_info *
+rtw_joinbss_update_stainfo(struct rtw_adapter *padapter,
+			   struct wlan_network *pnetwork)
 {
 	int i;
-	struct sta_info *bmc_sta, *psta = NULL;
+	struct sta_info *bmc_sta, *psta;
 	struct recv_reorder_ctrl *preorder_ctrl;
 	struct sta_priv *pstapriv = &padapter->stapriv;
 
 	psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress);
-	if (psta == NULL) {
-		psta = rtw_alloc_stainfo23a(pstapriv, pnetwork->network.MacAddress);
-	}
+	if (!psta)
+		psta = rtw_alloc_stainfo23a(pstapriv,
+					    pnetwork->network.MacAddress);
 
-	if (psta) /* update ptarget_sta */
-	{
+	if (psta) { /* update ptarget_sta */
 		DBG_8723A("%s\n", __func__);
 
 		psta->aid  = pnetwork->join_res;
@@ -1013,57 +1088,63 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct rtw_adapter *padapter,
 		rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
 
 		/* security related */
-		if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
-		{
+		if (padapter->securitypriv.dot11AuthAlgrthm ==
+		    dot11AuthAlgrthm_8021X) {
 			padapter->securitypriv.binstallGrpkey = false;
 			padapter->securitypriv.busetkipkey = false;
 			padapter->securitypriv.bgrpkey_handshake = false;
 
 			psta->ieee8021x_blocked = true;
-			psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+			psta->dot118021XPrivacy =
+				padapter->securitypriv.dot11PrivacyAlgrthm;
 
-			memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof (union Keytype));
+			memset(&psta->dot118021x_UncstKey, 0,
+			       sizeof (union Keytype));
 
-			memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof (union Keytype));
-			memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof (union Keytype));
+			memset(&psta->dot11tkiprxmickey, 0,
+			       sizeof (union Keytype));
+			memset(&psta->dot11tkiptxmickey, 0,
+			       sizeof (union Keytype));
 
-			memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48));
-			memset((u8 *)&psta->dot11rxpn, 0, sizeof (union pn48));
+			memset(&psta->dot11txpn, 0, sizeof (union pn48));
+			memset(&psta->dot11rxpn, 0, sizeof (union pn48));
 		}
 
 		/*	Commented by Albert 2012/07/21 */
 		/*	When doing the WPS, the wps_ie_len won't equal to 0 */
-		/*	And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted. */
-		if (padapter->securitypriv.wps_ie_len != 0)
-		{
+		/*	And the Wi-Fi driver shouldn't allow the data packet
+			to be tramsmitted. */
+		if (padapter->securitypriv.wps_ie_len != 0) {
 			psta->ieee8021x_blocked = true;
 			padapter->securitypriv.wps_ie_len = 0;
 		}
 
-		/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
-		/* if A-MPDU Rx is enabled, reseting  rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
+		/* for A-MPDU Rx reordering buffer control for bmc_sta &
+		 * sta_info */
+		/* if A-MPDU Rx is enabled, reseting
+		   rx_ordering_ctrl wstart_b(indicate_seq) to default
+		   value = 0xffff */
 		/* todo: check if AP can send A-MPDU packets */
-		for (i = 0; i < 16 ; i++)
-		{
+		for (i = 0; i < 16 ; i++) {
 			/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
 			preorder_ctrl = &psta->recvreorder_ctrl[i];
 			preorder_ctrl->enable = false;
 			preorder_ctrl->indicate_seq = 0xffff;
 			preorder_ctrl->wend_b = 0xffff;
-			preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
+			/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
+			preorder_ctrl->wsize_b = 64;
 		}
 
 		bmc_sta = rtw_get_bcmc_stainfo23a(padapter);
-		if (bmc_sta)
-		{
-			for (i = 0; i < 16 ; i++)
-			{
-				/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
+		if (bmc_sta) {
+			for (i = 0; i < 16 ; i++) {
 				preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
 				preorder_ctrl->enable = false;
 				preorder_ctrl->indicate_seq = 0xffff;
 				preorder_ctrl->wend_b = 0xffff;
-				preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
+				/* max_ampdu_sz; ex. 32(kbytes) ->
+				   wsize_b = 32 */
+				preorder_ctrl->wsize_b = 64;
 			}
 		}
 
@@ -1077,29 +1158,41 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct rtw_adapter *padapter,
 
 /* pnetwork : returns from rtw23a_joinbss_event_cb */
 /* ptarget_wlan: found from scanned_queue */
-static void rtw_joinbss_update_network23a(struct rtw_adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network  *pnetwork)
+static void
+rtw_joinbss_update_network23a(struct rtw_adapter *padapter,
+			      struct wlan_network *ptarget_wlan,
+			      struct wlan_network  *pnetwork)
 {
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wlan_network *cur_network = &pmlmepriv->cur_network;
 
 	DBG_8723A("%s\n", __func__);
 
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nfw_state:%x, BSSID:"MAC_FMT"\n"
-		, get_fwstate(pmlmepriv), MAC_ARG(pnetwork->network.MacAddress)));
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+		 ("\nfw_state:%x, BSSID:"MAC_FMT"\n", get_fwstate(pmlmepriv),
+		  MAC_ARG(pnetwork->network.MacAddress)));
 
 	/*  why not use ptarget_wlan?? */
-	memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
+	memcpy(&cur_network->network, &pnetwork->network,
+	       pnetwork->network.Length);
 	/*  some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
 	cur_network->network.IELength = ptarget_wlan->network.IELength;
-	memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
+	memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0],
+	       MAX_IE_SZ);
 
 	cur_network->aid = pnetwork->join_res;
 
 	rtw_set_signal_stat_timer(&padapter->recvpriv);
-	padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
-	padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
-	/* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
-	padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
+	padapter->recvpriv.signal_strength =
+		ptarget_wlan->network.PhyInfo.SignalStrength;
+	padapter->recvpriv.signal_qual =
+		ptarget_wlan->network.PhyInfo.SignalQuality;
+	/*
+	 * the ptarget_wlan->network.Rssi is raw data, we use
+	 * ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled)
+	 */
+	padapter->recvpriv.rssi = translate_percentage_to_dbm(
+		ptarget_wlan->network.PhyInfo.SignalStrength);
 	DBG_8723A("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u\n",
 		  __func__, padapter->recvpriv.signal_strength,
 		  padapter->recvpriv.rssi, padapter->recvpriv.signal_qual);
@@ -1118,40 +1211,51 @@ static void rtw_joinbss_update_network23a(struct rtw_adapter *padapter, struct w
 		break;
 	default:
 		pmlmepriv->fw_state = WIFI_NULL_STATE;
-		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
+		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+			 ("Invalid network_mode\n"));
 		break;
 	}
 
-	rtw_update_protection23a(padapter, (cur_network->network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
-									(cur_network->network.IELength));
+	rtw_update_protection23a(padapter, cur_network->network.IEs +
+				 sizeof (struct ndis_802_11_fixed_ies),
+				 cur_network->network.IELength);
 
-	rtw_update_ht_cap23a(padapter, cur_network->network.IEs, cur_network->network.IELength);
+	rtw_update_ht_cap23a(padapter, cur_network->network.IEs,
+			     cur_network->network.IELength);
 }
 
-/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
-/* pnetwork : returns from rtw23a_joinbss_event_cb */
-/* ptarget_wlan: found from scanned_queue */
-/* if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if  "ptarget_sta" & "ptarget_wlan" exist. */
-/* if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
-/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan !=NULL). */
+/*
+ * Notes:
+ * the fucntion could be > passive_level (the same context as Rx tasklet)
+ * pnetwork : returns from rtw23a_joinbss_event_cb
+ * ptarget_wlan: found from scanned_queue
+ * if join_res > 0, for (fw_state==WIFI_STATION_STATE),
+ * we check if  "ptarget_sta" & "ptarget_wlan" exist.
+ * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE),
+ * we only check if "ptarget_wlan" exist.
+ * if join_res > 0, update "cur_network->network" from "pnetwork->network"
+ * if (ptarget_wlan !=NULL).
+ */
 
 void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
 {
-	static u8 retry=0;
-	struct sta_info *ptarget_sta= NULL, *pcur_sta = NULL;
-	struct	sta_priv *pstapriv = &adapter->stapriv;
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
-	struct wlan_network	*pnetwork	= (struct wlan_network *)pbuf;
+	struct sta_info *ptarget_sta, *pcur_sta;
+	struct sta_priv *pstapriv = &adapter->stapriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
 	struct wlan_network *cur_network = &pmlmepriv->cur_network;
-	struct wlan_network	*pcur_wlan = NULL, *ptarget_wlan = NULL;
-	unsigned int		the_same_macaddr = false;
+	struct wlan_network *pcur_wlan, *ptarget_wlan = NULL;
+	bool the_same_macaddr;
 
-	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("joinbss event call back received with res=%d\n", pnetwork->join_res));
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+		 ("joinbss event call back received with res=%d\n",
+		  pnetwork->join_res));
 
 	rtw_get_encrypt_decrypt_from_registrypriv23a(adapter);
 
 	if (pmlmepriv->assoc_ssid.ssid_len == 0) {
-		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("@@@@@   joinbss event call back  for Any SSid\n"));
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+			 ("@@@@@   joinbss event call back  for Any SSid\n"));
 	} else {
 		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
 			 ("@@@@@   rtw23a_joinbss_event_cb for SSid:%s\n",
@@ -1165,93 +1269,102 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
 		the_same_macaddr = false;
 
 	pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
-	if(pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
-	{
-		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
+	if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+			 ("\n\n ***joinbss_evt_callback return a wrong bss "
+			  "***\n\n"));
 		return;
 	}
 
 	spin_lock_bh(&pmlmepriv->lock);
 
-	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+		 ("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
 
-	if(pnetwork->join_res > 0)
-	{
+	if (pnetwork->join_res > 0) {
 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
-		retry = 0;
-		if (check_fwstate(pmlmepriv,_FW_UNDER_LINKING))
-		{
+		if (check_fwstate(pmlmepriv,_FW_UNDER_LINKING)) {
 			/* s1. find ptarget_wlan */
-			if(check_fwstate(pmlmepriv, _FW_LINKED))
-			{
-				if(the_same_macaddr == true)
-				{
+			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+				if (the_same_macaddr == true) {
 					ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
-				}
-				else
-				{
+				} else {
 					pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
-					if(pcur_wlan)	pcur_wlan->fixed = false;
+					if (pcur_wlan)
+						pcur_wlan->fixed = false;
 
 					pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
-					if(pcur_sta) {
+					if (pcur_sta) {
 						spin_lock_bh(&pstapriv->sta_hash_lock);
-						rtw_free_stainfo23a(adapter,  pcur_sta);
+						rtw_free_stainfo23a(adapter,
+								    pcur_sta);
 						spin_unlock_bh(&pstapriv->sta_hash_lock);
 					}
 
 					ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
-					if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
-						if(ptarget_wlan)	ptarget_wlan->fixed = true;
+					if (check_fwstate(pmlmepriv,
+							  WIFI_STATION_STATE)) {
+						if (ptarget_wlan)
+							ptarget_wlan->fixed =
+								true;
 					}
 				}
 
-			}
-			else
-			{
-				ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
-				if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
-					if(ptarget_wlan)	ptarget_wlan->fixed = true;
+			} else {
+				ptarget_wlan = rtw_find_network23a(
+					&pmlmepriv->scanned_queue,
+					pnetwork->network.MacAddress);
+				if (check_fwstate(pmlmepriv,
+						  WIFI_STATION_STATE)) {
+					if (ptarget_wlan)
+						ptarget_wlan->fixed = true;
 				}
 			}
 
 			/* s2. update cur_network */
-			if(ptarget_wlan)
-			{
-				rtw_joinbss_update_network23a(adapter, ptarget_wlan, pnetwork);
-			}
-			else
-			{
-				RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't find ptarget_wlan when joinbss_event callback\n"));
+			if (ptarget_wlan)
+				rtw_joinbss_update_network23a(adapter,
+							      ptarget_wlan,
+							      pnetwork);
+			else {
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+					 ("Can't find ptarget_wlan when "
+					  "joinbss_event callback\n"));
 				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 				goto ignore_joinbss_callback;
 			}
 
-			/* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
-			if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
-			{
-				ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
-				if(ptarget_sta==NULL)
-				{
-					RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't update stainfo when joinbss_event callback\n"));
+			/* s3. find ptarget_sta & update ptarget_sta after
+			   update cur_network only for station mode */
+			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+				ptarget_sta = rtw_joinbss_update_stainfo(
+					adapter, pnetwork);
+				if (!ptarget_sta) {
+					RT_TRACE(_module_rtl871x_mlme_c_,
+						 _drv_err_,
+						 ("Can't update stainfo when "
+						  "joinbss_event callback\n"));
 					spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 					goto ignore_joinbss_callback;
 				}
 			}
 
 			/* s4. indicate connect */
-			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
-			{
+			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 				rtw_indicate_connect23a(adapter);
-			} else {
-					/* adhoc mode will rtw_indicate_connect23a when rtw_stassoc_event_callback23a */
-				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
+			else {
+				/* adhoc mode will rtw_indicate_connect23a
+				   when rtw_stassoc_event_callback23a */
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+					 ("adhoc mode, fw_state:%x",
+					  get_fwstate(pmlmepriv)));
 			}
 
 			/* s5. Cancle assoc_timer */
 			del_timer_sync(&pmlmepriv->assoc_timer);
 
-			RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("Cancle assoc_timer\n"));
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+				 ("Cancle assoc_timer\n"));
 		} else {
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
 				 ("rtw23a_joinbss_event_cb err: fw_state:%x",
@@ -1260,20 +1373,19 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
 			goto ignore_joinbss_callback;
 		}
 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
-	} else if(pnetwork->join_res == -4) {
+	} else if (pnetwork->join_res == -4) {
 		rtw_reset_securitypriv23a(adapter);
 		mod_timer(&pmlmepriv->assoc_timer,
 			  jiffies + msecs_to_jiffies(1));
 
 		/* rtw_free_assoc_resources23a(adapter, 1); */
 
-		if((check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
+		if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-				 ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n",
-				 get_fwstate(pmlmepriv)));
+				 ("fail! clear _FW_UNDER_LINKING ^^^fw_state="
+				  "%x\n", get_fwstate(pmlmepriv)));
 			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 		}
-
 	} else {
 		/* if join_res < 0 (join fails), then try again */
 		mod_timer(&pmlmepriv->assoc_timer,
@@ -1288,46 +1400,31 @@ ignore_joinbss_callback:
 
 void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, u8 *pbuf)
 {
-	struct wlan_network	*pnetwork	= (struct wlan_network *)pbuf;
+	struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
 
 	mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
 
 	rtw_os_xmit_schedule23a(adapter);
-
-}
-
-/* FOR AP , AD-HOC mode */
-void rtw_stassoc_hw_rpt23a(struct rtw_adapter *adapter, struct sta_info *psta)
-{
-	u16 media_status;
-
-	if (psta == NULL)	return;
-
-	media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE:1 connect */
-	rtw_hal_set_hwreg23a(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
 }
 
 void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 {
 	struct sta_info *psta;
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-	struct stassoc_event	*pstassoc	= (struct stassoc_event*)pbuf;
+	struct stassoc_event *pstassoc = (struct stassoc_event*)pbuf;
 	struct wlan_network *cur_network = &pmlmepriv->cur_network;
-	struct wlan_network	*ptarget_wlan = NULL;
+	struct wlan_network *ptarget_wlan;
 
-	if(rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
+	if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
 		return;
 
 #ifdef CONFIG_8723AU_AP_MODE
-	if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
-	{
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
 		psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
 		if (psta) {
 			/* bss_cap_update_on_sta_join23a(adapter, psta); */
 			/* sta_info_update23a(adapter, psta); */
 			ap_sta_info_defer_update23a(adapter, psta);
-
-			rtw_stassoc_hw_rpt23a(adapter,psta);
 		}
 		return;
 	}
@@ -1336,13 +1433,19 @@ void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 	psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
 	if (psta != NULL) {
 		/* the sta have been in sta_info_queue => do nothing */
-		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n"));
-		return; /* between drv has received this event before and  fw have not yet to set key to CAM_ENTRY) */
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+			 ("Error: rtw_stassoc_event_callback23a: sta has "
+			  "been in sta_hash_queue\n"));
+		/* between drv has received this event before and
+		   fw have not yet to set key to CAM_ENTRY) */
+		return;
 	}
 
 	psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
-	if (psta == NULL) {
-		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't alloc sta_info when rtw_stassoc_event_callback23a\n"));
+	if (!psta) {
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+			 ("Can't alloc sta_info when "
+			  "rtw_stassoc_event_callback23a\n"));
 		return;
 	}
 
@@ -1352,25 +1455,25 @@ void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 	/* psta->aid = (uint)pstassoc->cam_id; */
 	DBG_8723A("%s\n",__func__);
 	/* for ad-hoc mode */
-	rtw_hal_set_odm_var23a(adapter,HAL_ODM_STA_INFO,psta,true);
+	rtw_hal_set_odm_var23a(adapter, HAL_ODM_STA_INFO, psta, true);
 
-	rtw_stassoc_hw_rpt23a(adapter,psta);
-
-	if(adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
-		psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
+	if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
+		psta->dot118021XPrivacy =
+			adapter->securitypriv.dot11PrivacyAlgrthm;
 
 	psta->ieee8021x_blocked = false;
 
 	spin_lock_bh(&pmlmepriv->lock);
 
-	if ( (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==true ) ||
-		(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==true ) )
-	{
-		if(adapter->stapriv.asoc_sta_count== 2)
-		{
+	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+		if (adapter->stapriv.asoc_sta_count == 2) {
 			spin_lock_bh(&pmlmepriv->scanned_queue.lock);
-			ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
-			if(ptarget_wlan)	ptarget_wlan->fixed = true;
+			ptarget_wlan =
+				rtw_find_network23a(&pmlmepriv->scanned_queue,
+						    cur_network->network.MacAddress);
+			if (ptarget_wlan)
+				ptarget_wlan->fixed = true;
 			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 			/*  a sta + bc/mc_stainfo (not Ibss_stainfo) */
 			rtw_indicate_connect23a(adapter);
@@ -1384,47 +1487,40 @@ void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 
 void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 {
-	int mac_id=-1;
+	int mac_id;
 	struct sta_info *psta;
-	struct wlan_network* pwlan = NULL;
-	struct wlan_bssid_ex    *pdev_network=NULL;
-	u8* pibss = NULL;
-	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
-	struct	stadel_event *pstadel	= (struct stadel_event*)pbuf;
-	struct	sta_priv *pstapriv = &adapter->stapriv;
+	struct wlan_network* pwlan;
+	struct wlan_bssid_ex *pdev_network;
+	u8 *pibss;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct stadel_event *pstadel = (struct stadel_event *)pbuf;
+	struct sta_priv *pstapriv = &adapter->stapriv;
 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 
 	psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
-	if(psta)
+	if (psta)
 		mac_id = psta->mac_id;
 	else
 		mac_id = pstadel->mac_id;
 
-	DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id, MAC_ARG(pstadel->macaddr));
-
-	if(mac_id>=0) {
-		u16 media_status;
-		media_status = (mac_id<<8)|0; /*   MACID|OPMODE:0 means disconnect */
-		/* for STA,AP,ADHOC mode, report disconnect stauts to FW */
-		rtw_hal_set_hwreg23a(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
-	}
+	DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id,
+		  MAC_ARG(pstadel->macaddr));
 
         if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
-        {
 		return;
-        }
 
 	mlmeext_sta_del_event_callback23a(adapter);
 
 	spin_lock_bh(&pmlmepriv->lock);
 
-	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
-	{
-		if (rtw_to_roaming(adapter) > 0)
-			pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */
-		else if (rtw_to_roaming(adapter) == 0)
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+		if (adapter->mlmepriv.to_roaming > 0) {
+			/* this stadel_event is caused by roaming,
+			   decrease to_roaming */
+			pmlmepriv->to_roaming--;
+		} else if (adapter->mlmepriv.to_roaming == 0)
 			rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
-		if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
+		if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK)
 			rtw_set_roaming(adapter, 0); /* don't roam */
 
 		rtw_free_uc_swdec_pending_queue23a(adapter);
@@ -1433,32 +1529,33 @@ void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 		rtw_indicate_disconnect23a(adapter);
 		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 		/*  remove the network entry in scanned_queue */
-		pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+		pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
+					    tgt_network->network.MacAddress);
 		if (pwlan) {
 			pwlan->fixed = false;
 			rtw_free_network_nolock(pmlmepriv, pwlan);
 		}
 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
-		_rtw23a_roaming(adapter, tgt_network);
+		_rtw_roaming(adapter, tgt_network);
 	}
 
 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
-	      check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
-	{
+	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 
 		spin_lock_bh(&pstapriv->sta_hash_lock);
 		rtw_free_stainfo23a(adapter,  psta);
 		spin_unlock_bh(&pstapriv->sta_hash_lock);
 
-		if (adapter->stapriv.asoc_sta_count == 1) /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
-		{
+		/* a sta + bc/mc_stainfo (not Ibss_stainfo) */
+		if (adapter->stapriv.asoc_sta_count == 1) {
 			spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 			/* free old ibss network */
-			/* pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pstadel->macaddr); */
-			pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
-			if (pwlan)
-			{
+			/* pwlan = rtw_find_network23a(
+			   &pmlmepriv->scanned_queue, pstadel->macaddr); */
+			pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue,
+						    tgt_network->network.MacAddress);
+			if (pwlan) {
 				pwlan->fixed = false;
 				rtw_free_network_nolock(pmlmepriv, pwlan);
 			}
@@ -1467,7 +1564,8 @@ void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 			pdev_network = &adapter->registrypriv.dev_network;
 			pibss = adapter->registrypriv.dev_network.MacAddress;
 
-			memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
+			memcpy(pdev_network, &tgt_network->network,
+			       get_wlan_bssid_ex_sz(&tgt_network->network));
 
 			memset(&pdev_network->Ssid, 0,
 			       sizeof(struct cfg80211_ssid));
@@ -1478,32 +1576,28 @@ void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
 
 			rtw_generate_random_ibss23a(pibss);
 
-			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
-			{
+			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 				set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
 				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
 			}
 
-			if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
-			{
-
-				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>stadel_event_callback: rtw_createbss_cmd23a status FAIL***\n "));
-
+			if (rtw_createbss_cmd23a(adapter) != _SUCCESS) {
+				RT_TRACE(_module_rtl871x_ioctl_set_c_,
+					 _drv_err_,
+					 ("***Error =>stadel_event_callback: "
+					  "rtw_createbss_cmd23a status "
+					  "FAIL***\n"));
 			}
-
 		}
-
 	}
 
 	spin_unlock_bh(&pmlmepriv->lock);
-
 }
 
 void rtw_cpwm_event_callback23a(struct rtw_adapter *padapter, u8 *pbuf)
 {
-
-	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("+rtw_cpwm_event_callback23a !!!\n"));
-
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+		 ("+rtw_cpwm_event_callback23a !!!\n"));
 }
 
 /*
@@ -1518,23 +1612,28 @@ void rtw23a_join_to_handler (unsigned long data)
 
 	DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
 
-	if(adapter->bDriverStopped ||adapter->bSurpriseRemoved)
+	if (adapter->bDriverStopped ||adapter->bSurpriseRemoved)
 		return;
 
 	spin_lock_bh(&pmlmepriv->lock);
 
-	if (rtw_to_roaming(adapter) > 0) { /* join timeout caused by roaming */
-		while(1) {
+	if (adapter->mlmepriv.to_roaming > 0) {
+		/* join timeout caused by roaming */
+		while (1) {
 			pmlmepriv->to_roaming--;
-			if (rtw_to_roaming(adapter) != 0) { /* try another */
+			if (adapter->mlmepriv.to_roaming != 0) {
+				/* try another */
 				DBG_8723A("%s try another roaming\n", __func__);
-				if (_SUCCESS!= (do_join_r = rtw_do_join23a(adapter))) {
-					DBG_8723A("%s roaming do_join return %d\n", __func__ , do_join_r);
+				do_join_r = rtw_do_join23a(adapter);
+				if (do_join_r != _SUCCESS) {
+					DBG_8723A("%s roaming do_join return "
+						  "%d\n", __func__ , do_join_r);
 					continue;
 				}
 				break;
 			} else {
-				DBG_8723A("%s We've try roaming but fail\n", __func__);
+				DBG_8723A("%s We've try roaming but fail\n",
+					  __func__);
 				rtw_indicate_disconnect23a(adapter);
 				break;
 			}
@@ -1543,7 +1642,8 @@ void rtw23a_join_to_handler (unsigned long data)
 		rtw_indicate_disconnect23a(adapter);
 		free_scanqueue(pmlmepriv);/*  */
 
-		/* indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED */
+		/* indicate disconnect for the case that join_timeout and
+		   check_fwstate != FW_LINKED */
 		rtw_cfg80211_indicate_disconnect(adapter);
 	}
 
@@ -1560,7 +1660,8 @@ void rtw_scan_timeout_handler23a(unsigned long data)
 	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
 
-	DBG_8723A(FUNC_ADPT_FMT" fw_state =%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
+	DBG_8723A(FUNC_ADPT_FMT" fw_state =%x\n", FUNC_ADPT_ARG(adapter),
+		  get_fwstate(pmlmepriv));
 
 	spin_lock_bh(&pmlmepriv->lock);
 
@@ -1568,7 +1669,7 @@ void rtw_scan_timeout_handler23a(unsigned long data)
 
 	spin_unlock_bh(&pmlmepriv->lock);
 
-	rtw_indicate_scan_done23a(adapter, true);
+	rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true);
 }
 
 static void rtw_auto_scan_handler(struct rtw_adapter *padapter)
@@ -1581,7 +1682,8 @@ static void rtw_auto_scan_handler(struct rtw_adapter *padapter)
 		if (pmlmepriv->scan_interval == 0) {
 			DBG_8723A("%s\n", __func__);
 			rtw_set_802_11_bssid23a_list_scan(padapter, NULL, 0);
-			pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
+			/*  30*2 sec = 60sec */
+			pmlmepriv->scan_interval = SCAN_INTERVAL;
 		}
 	}
 }
@@ -1594,7 +1696,8 @@ void rtw_dynamic_check_timer_handler(unsigned long data)
 	if (adapter->hw_init_completed == false)
 		goto out;
 
-	if ((adapter->bDriverStopped == true)||(adapter->bSurpriseRemoved == true))
+	if (adapter->bDriverStopped == true ||
+	    adapter->bSurpriseRemoved == true)
 		goto out;
 
 	if (adapter->net_closed == true)
@@ -1602,16 +1705,9 @@ void rtw_dynamic_check_timer_handler(unsigned long data)
 
 	rtw_dynamic_chk_wk_cmd23a(adapter);
 
-	if (pregistrypriv->wifi_spec == 1)
-	{
-#ifdef CONFIG_8723AU_P2P
-		struct wifidirect_info *pwdinfo = &adapter->wdinfo;
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-#endif
-		{
-			/* auto site survey */
-			rtw_auto_scan_handler(adapter);
-		}
+	if (pregistrypriv->wifi_spec == 1) {
+		/* auto site survey */
+		rtw_auto_scan_handler(adapter);
 	}
 out:
 	mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
@@ -1628,8 +1724,6 @@ void rtw_clear_scan_deny(struct rtw_adapter *adapter)
 {
 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
 	atomic_set(&mlmepriv->set_scan_deny, 0);
-	if (0)
-	DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
 }
 
 void rtw_set_scan_deny_timer_hdl(unsigned long data)
@@ -1642,12 +1736,9 @@ void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
 {
 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
 
-	if (0)
-	DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
 	atomic_set(&mlmepriv->set_scan_deny, 1);
 	mod_timer(&mlmepriv->set_scan_deny_timer,
 		  jiffies + msecs_to_jiffies(ms));
-
 }
 
 #if defined(IEEE80211_SCAN_RESULT_EXPIRE)
@@ -1657,15 +1748,19 @@ void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
 #endif
 
 /*
-* Select a new join candidate from the original @param candidate and @param competitor
+* Select a new join candidate from the original @param candidate and
+*     @param competitor
 * @return true: candidate is updated
 * @return false: candidate is not updated
 */
-static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
-	, struct wlan_network **candidate, struct wlan_network *competitor)
+static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv,
+				    struct wlan_network **candidate,
+				    struct wlan_network *competitor)
 {
 	int updated = false;
-	struct rtw_adapter *adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
+	struct rtw_adapter *adapter;
+
+	adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
 
 	/* check bssid, if needed */
 	if (pmlmepriv->assoc_by_bssid == true) {
@@ -1684,10 +1779,10 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
 			goto exit;
 	}
 
-	if (rtw_is_desired_network(adapter, competitor)  == false)
+	if (rtw_is_desired_network(adapter, competitor) == false)
 		goto exit;
 
-	if (rtw_to_roaming(adapter) > 0) {
+	if (adapter->mlmepriv.to_roaming > 0) {
 		unsigned int passed;
 
 		passed = jiffies_to_msecs(jiffies - competitor->last_scanned);
@@ -1697,19 +1792,21 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
 			goto exit;
 	}
 
-	if (*candidate == NULL ||(*candidate)->network.Rssi<competitor->network.Rssi) {
+	if (!*candidate ||
+	    (*candidate)->network.Rssi<competitor->network.Rssi) {
 		*candidate = competitor;
 		updated = true;
 	}
 
 	if (updated) {
-		DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s("MAC_FMT") rssi:%d\n",
-			pmlmepriv->assoc_by_bssid,
-			pmlmepriv->assoc_ssid.ssid,
-			rtw_to_roaming(adapter),
-			(*candidate)->network.Ssid.ssid,
-			MAC_ARG((*candidate)->network.MacAddress),
-			(int)(*candidate)->network.Rssi);
+		DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] "
+			  "new candidate: %s("MAC_FMT") rssi:%d\n",
+			  pmlmepriv->assoc_by_bssid,
+			  pmlmepriv->assoc_ssid.ssid,
+			  adapter->mlmepriv.to_roaming,
+			  (*candidate)->network.Ssid.ssid,
+			  MAC_ARG((*candidate)->network.MacAddress),
+			  (int)(*candidate)->network.Rssi);
 	}
 
 exit:
@@ -1732,8 +1829,8 @@ int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
 	struct list_head *phead, *plist, *ptmp;
 	struct rtw_adapter *adapter;
 	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
-	struct	wlan_network	*pnetwork = NULL;
-	struct	wlan_network	*candidate = NULL;
+	struct wlan_network *pnetwork;
+	struct wlan_network *candidate = NULL;
 
 	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 	phead = get_list_head(queue);
@@ -1764,7 +1861,7 @@ int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
 	}
 
 	/*  check for situation of  _FW_LINKED */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
+	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 		DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!!!\n",
 			  __func__);
 
@@ -1782,7 +1879,7 @@ exit:
 }
 
 int rtw_set_auth23a(struct rtw_adapter * adapter,
-		 struct security_priv *psecuritypriv)
+		    struct security_priv *psecuritypriv)
 {
 	struct cmd_obj* pcmd;
 	struct setauth_parm *psetauthparm;
@@ -1825,7 +1922,7 @@ exit:
 }
 
 int rtw_set_key23a(struct rtw_adapter *adapter,
-		struct security_priv *psecuritypriv, int keyid, u8 set_tx)
+		   struct security_priv *psecuritypriv, int keyid, u8 set_tx)
 {
 	u8 keylen;
 	struct cmd_obj *pcmd;
@@ -1850,9 +1947,9 @@ int rtw_set_key23a(struct rtw_adapter *adapter,
 		psetkeyparm->algorithm = (unsigned char)
 			psecuritypriv->dot118021XGrpPrivacy;
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-			 ("\n rtw_set_key23a: psetkeyparm->algorithm = (unsigned "
-			  "char)psecuritypriv->dot118021XGrpPrivacy =%d\n",
-			  psetkeyparm->algorithm));
+			 ("\n rtw_set_key23a: psetkeyparm->algorithm = "
+			  "(unsigned char)psecuritypriv->dot118021XGrpPrivacy "
+			  "=%d\n", psetkeyparm->algorithm));
 	} else {
 		psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
@@ -1897,8 +1994,8 @@ int rtw_set_key23a(struct rtw_adapter *adapter,
 		break;
 	default:
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-			 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = "
-			  "%x (must be 1 or 2 or 4 or 5)\n",
+			 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm"
+			  " = %x (must be 1 or 2 or 4 or 5)\n",
 			  psecuritypriv->dot11PrivacyAlgrthm));
 		res = _FAIL;
 		kfree(pcmd);
@@ -1931,7 +2028,7 @@ int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
 	unsigned int i, j;
 
 	i = 12; /* after the fixed IE */
-	while(i < in_len) {
+	while (i < in_len) {
 		ielength = initial_out_len;
 
 		/* WMM element ID and OUI */
@@ -1982,11 +2079,11 @@ static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid)
 			i++;
 			/* continue; */
 		}
-	} while(i < NUM_PMKID_CACHE);
+	} while (i < NUM_PMKID_CACHE);
 
-	if (i == NUM_PMKID_CACHE) {
+	if (i == NUM_PMKID_CACHE)
 		i = -1;/*  Could not find. */
-	} else {
+	else {
 		/*  There is one Pre-Authentication Key for
 		    the specific BSSID. */
 	}
@@ -2023,8 +2120,9 @@ static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry,
 	}
 	return ie_len;
 }
+
 int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
-			uint in_len)
+			   uint in_len)
 {
 	u8 authmode;
 	uint ielength;
@@ -2035,41 +2133,39 @@ int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
 	uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-		 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n",
-		  ndisauthmode, ndissecuritytype));
+		 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d "
+		  "ndissecuritytype=%d\n", ndisauthmode, ndissecuritytype));
 
 	/* copy fixed ie only */
 	memcpy(out_ie, in_ie, 12);
 	ielength = 12;
-	if ((ndisauthmode==Ndis802_11AuthModeWPA) ||
-	    (ndisauthmode==Ndis802_11AuthModeWPAPSK))
-		authmode=_WPA_IE_ID_;
-	if ((ndisauthmode==Ndis802_11AuthModeWPA2) ||
-	    (ndisauthmode==Ndis802_11AuthModeWPA2PSK))
-		authmode=_WPA2_IE_ID_;
+	if (ndisauthmode == Ndis802_11AuthModeWPA ||
+	    ndisauthmode == Ndis802_11AuthModeWPAPSK)
+		authmode = WLAN_EID_VENDOR_SPECIFIC;
+	if (ndisauthmode == Ndis802_11AuthModeWPA2 ||
+	    ndisauthmode == Ndis802_11AuthModeWPA2PSK)
+		authmode = _WPA2_IE_ID_;
 
 	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
 		memcpy(out_ie + ielength, psecuritypriv->wps_ie,
 		       psecuritypriv->wps_ie_len);
 
 		ielength += psecuritypriv->wps_ie_len;
-	} else if ((authmode==_WPA_IE_ID_) || (authmode==_WPA2_IE_ID_)) {
+	} else if (authmode == WLAN_EID_VENDOR_SPECIFIC ||
+		   authmode == _WPA2_IE_ID_) {
 		/* copy RSN or SSN */
 		memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
 		       psecuritypriv->supplicant_ie[1] + 2);
 		ielength += psecuritypriv->supplicant_ie[1] + 2;
-		rtw_report_sec_ie23a(adapter, authmode,
-				  psecuritypriv->supplicant_ie);
 	}
 
 	iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
-	if (iEntry < 0)	{
+	if (iEntry < 0)
 		return ielength;
-	} else {
-		if (authmode == _WPA2_IE_ID_) {
-			ielength=rtw_append_pmkid(adapter, iEntry,
-						  out_ie, ielength);
-		}
+	else {
+		if (authmode == _WPA2_IE_ID_)
+			ielength = rtw_append_pmkid(adapter, iEntry,
+						    out_ie, ielength);
 	}
 
 	return ielength;
@@ -2162,7 +2258,6 @@ void rtw_update_registrypriv_dev_network23a(struct rtw_adapter* adapter)
 	/* notes: translate IELength & Length after assign the
 	   Length to cmdsz in createbss_cmd(); */
 	/* pdev_network->IELength = cpu_to_le32(sz); */
-
 }
 
 void rtw_get_encrypt_decrypt_from_registrypriv23a(struct rtw_adapter* adapter)
@@ -2193,22 +2288,20 @@ void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
 			threshold = 1;
 		else
 			threshold = 0;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH,
-				  (u8 *)(&threshold));
-	} else {
+	} else
 		threshold = 1;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH,
-				  (u8 *)(&threshold));
-	}
+
+	rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
 }
 
 /* the fucntion is >= passive_level */
 unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
-				   u8 *out_ie, uint in_len, uint *pout_len)
+				      u8 *out_ie, uint in_len, uint *pout_len)
 {
-	u32 ielen, out_len;
+	u32 out_len;
 	int max_rx_ampdu_factor;
-	unsigned char *p, *pframe;
+	unsigned char *pframe;
+	const u8 *p;
 	struct ieee80211_ht_cap ht_capie;
 	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -2217,14 +2310,14 @@ unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
 
 	phtpriv->ht_option = false;
 
-	p = rtw_get_ie23a(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12);
+	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie + 12, in_len -12);
 
-	if (p && ielen > 0) {
+	if (p && p[1] > 0) {
 		u32 rx_packet_offset, max_recvbuf_sz;
 		if (pqospriv->qos_option == 0) {
 			out_len = *pout_len;
 			pframe = rtw_set_ie23a(out_ie + out_len,
-					    _VENDOR_SPECIFIC_IE_,
+					    WLAN_EID_VENDOR_SPECIFIC,
 					    _WMM_IE_Length_, WMM_IE, pout_len);
 
 			pqospriv->qos_option = 1;
@@ -2254,17 +2347,19 @@ unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
 			ht_capie.ampdu_params_info |=
 				(IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
 
-		pframe = rtw_set_ie23a(out_ie + out_len, _HT_CAPABILITY_IE_,
+		pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
 				    sizeof(struct ieee80211_ht_cap),
 				    (unsigned char*)&ht_capie, pout_len);
 
 		phtpriv->ht_option = true;
 
-		p = rtw_get_ie23a(in_ie + 12, _HT_ADD_INFO_IE_, &ielen, in_len-12);
-		if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie + 12,
+				     in_len -12);
+		if (p && (p[1] == sizeof(struct ieee80211_ht_addt_info))) {
 			out_len = *pout_len;
-			pframe = rtw_set_ie23a(out_ie + out_len, _HT_ADD_INFO_IE_,
-					    ielen, p + 2 , pout_len);
+			pframe = rtw_set_ie23a(out_ie + out_len,
+					       WLAN_EID_HT_OPERATION,
+					       p[1], p + 2 , pout_len);
 		}
 	}
 
@@ -2274,18 +2369,14 @@ unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
 /* the fucntion is > passive_level (in critical_section) */
 void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
 {
-	u8 *p, max_ampdu_sz;
-	int len;
-	/* struct sta_info *bmc_sta, *psta; */
+	u8 max_ampdu_sz;
+	const u8 *p;
 	struct ieee80211_ht_cap *pht_capie;
 	struct ieee80211_ht_addt_info *pht_addtinfo;
-	/* struct recv_reorder_ctrl *preorder_ctrl; */
-	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
-	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
-	/* struct recv_priv *precvpriv = &padapter->recvpriv; */
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
-	/* struct wlan_network *pcur_network = &pmlmepriv->cur_network;; */
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
 	if (!phtpriv->ht_option)
@@ -2296,51 +2387,51 @@ void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
 
 	DBG_8723A("+rtw_update_ht_cap23a()\n");
 
+	/* Adjust pie + ie_len for our searches */
+	pie += sizeof (struct ndis_802_11_fixed_ies);
+	ie_len -= sizeof (struct ndis_802_11_fixed_ies);
+
 	/* maybe needs check if ap supports rx ampdu. */
-	if ((phtpriv->ampdu_enable == false) && (pregistrypriv->ampdu_enable == 1)) {
+	if (phtpriv->ampdu_enable == false &&
+	    pregistrypriv->ampdu_enable == 1) {
 		if (pregistrypriv->wifi_spec == 1)
 			phtpriv->ampdu_enable = false;
 		else
 			phtpriv->ampdu_enable = true;
-	} else if (pregistrypriv->ampdu_enable == 2) {
+	} else if (pregistrypriv->ampdu_enable == 2)
 		phtpriv->ampdu_enable = true;
-	}
 
 	/* check Max Rx A-MPDU Size */
-	len = 0;
-	p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies), _HT_CAPABILITY_IE_, &len, ie_len-sizeof (struct ndis_802_11_fixed_ies));
-	if (p && len > 0) {
-		pht_capie = (struct ieee80211_ht_cap *)(p+2);
-		max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR);
-		max_ampdu_sz = 1 << (max_ampdu_sz+3); /*  max_ampdu_sz (kbytes); */
-
-		/* DBG_8723A("rtw_update_ht_cap23a(): max_ampdu_sz =%d\n", max_ampdu_sz); */
-		phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
+	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len);
+
+	if (p && p[1] > 0) {
+		pht_capie = (struct ieee80211_ht_cap *)(p + 2);
+		max_ampdu_sz = pht_capie->ampdu_params_info &
+			IEEE80211_HT_AMPDU_PARM_FACTOR;
+		/*  max_ampdu_sz (kbytes); */
+		max_ampdu_sz = 1 << (max_ampdu_sz + 3);
 
+		phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
 	}
 
-	len = 0;
-	p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies), _HT_ADD_INFO_IE_, &len, ie_len-sizeof (struct ndis_802_11_fixed_ies));
-	if (p && len>0)
-	{
-		pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2);
+	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len);
+	if (p && p[1] > 0) {
+		pht_addtinfo = (struct ieee80211_ht_addt_info *)(p + 2);
 		/* todo: */
 	}
 
 	/* update cur_bwmode & cur_ch_offset */
-	if ((pregistrypriv->cbw40_enable) &&
-		(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1)) &&
-		(pmlmeinfo->HT_info.infos[0] & BIT(2)))
-	{
+	if (pregistrypriv->cbw40_enable &&
+	    pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1) &&
+	    pmlmeinfo->HT_info.infos[0] & BIT(2)) {
 		int i;
-		u8	rf_type;
+		u8 rf_type;
 
-		padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+		rf_type = rtl8723a_get_rf_type(padapter);
 
 		/* update the MCS rates */
-		for (i = 0; i < 16; i++)
-		{
-			if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
+		for (i = 0; i < 16; i++) {
+			if (rf_type == RF_1T1R || rf_type == RF_1T2R)
 				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
 			else
 				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
@@ -2349,24 +2440,26 @@ void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
 		pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
 		switch ((pmlmeinfo->HT_info.infos[0] & 0x3))
 		{
-			case HT_EXTCHNL_OFFSET_UPPER:
-				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
-				break;
+		case HT_EXTCHNL_OFFSET_UPPER:
+			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+			break;
 
-			case HT_EXTCHNL_OFFSET_LOWER:
-				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
-				break;
+		case HT_EXTCHNL_OFFSET_LOWER:
+			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+			break;
 
-			default:
-				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-				break;
+		default:
+			pmlmeext->cur_ch_offset =
+				HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+			break;
 		}
 	}
 
 	/*  */
 	/*  Config SM Power Save setting */
 	/*  */
-	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
+	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &
+			    0x0C) >> 2;
 	if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
 		DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
 
@@ -2376,124 +2469,65 @@ void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
 	pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
 }
 
-void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
+void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter,
+			       struct xmit_frame *pxmitframe)
 {
 	u8 issued;
 	int priority;
-	struct sta_info *psta = NULL;
+	struct sta_info *psta;
 	struct ht_priv	*phtpriv;
 	struct pkt_attrib *pattrib = &pxmitframe->attrib;
 	s32 bmcst = is_multicast_ether_addr(pattrib->ra);
 
-	if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod<100))
+	if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100)
 		return;
 
 	priority = pattrib->priority;
 
 	if (pattrib->psta)
 		psta = pattrib->psta;
-	else
-	{
+	else {
 		DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
 		psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
 	}
 
-	if (psta == NULL)
-	{
+	if (!psta) {
 		DBG_8723A("%s, psta == NUL\n", __func__);
 		return;
 	}
 
-	if (!(psta->state &_FW_LINKED))
-	{
-		DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+	if (!(psta->state &_FW_LINKED)) {
+		DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
+			  __func__, psta->state);
 		return;
 	}
 
 	phtpriv = &psta->htpriv;
 
-	if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true))
-	{
+	if (phtpriv->ht_option == true && phtpriv->ampdu_enable == true) {
 		issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
 		issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
 
-		if (0 == issued)
-		{
-			DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n", priority);
-			psta->htpriv.candidate_tid_bitmap |= CHKBIT((u8)priority);
-			rtw_addbareq_cmd23a(padapter, (u8) priority, pattrib->ra);
-		}
-	}
-}
-
-inline void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming)
-{
-	if (to_roaming == 0)
-		adapter->mlmepriv.to_join = false;
-	adapter->mlmepriv.to_roaming = to_roaming;
-}
-
-inline u8 rtw_to_roaming(struct rtw_adapter *adapter)
-{
-	return adapter->mlmepriv.to_roaming;
-}
-
-void rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
-{
-	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
-
-	spin_lock_bh(&pmlmepriv->lock);
-	_rtw23a_roaming(padapter, tgt_network);
-	spin_unlock_bh(&pmlmepriv->lock);
-}
-void _rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
-{
-	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
-	struct wlan_network *pnetwork;
-	int do_join_r;
-
-	if (tgt_network != NULL)
-		pnetwork = tgt_network;
-	else
-		pnetwork = &pmlmepriv->cur_network;
-
-	if (0 < rtw_to_roaming(padapter)) {
-		DBG_8723A("roaming from %s("MAC_FMT"), length:%d\n",
-			  pnetwork->network.Ssid.ssid,
-			  MAC_ARG(pnetwork->network.MacAddress),
-			  pnetwork->network.Ssid.ssid_len);
-		memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid,
-		       sizeof(struct cfg80211_ssid));
-
-		pmlmepriv->assoc_by_bssid = false;
-
-		while(1) {
-			if (_SUCCESS == (do_join_r = rtw_do_join23a(padapter))) {
-				break;
-			} else {
-				DBG_8723A("roaming do_join return %d\n", do_join_r);
-				pmlmepriv->to_roaming--;
-
-				if (0 < rtw_to_roaming(padapter)) {
-					continue;
-				} else {
-					DBG_8723A("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
-					rtw_indicate_disconnect23a(padapter);
-					break;
-				}
-			}
+		if (issued == 0) {
+			DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n",
+				  priority);
+			psta->htpriv.candidate_tid_bitmap |=
+				CHKBIT((u8)priority);
+			rtw_addbareq_cmd23a(padapter, (u8) priority,
+					    pattrib->ra);
 		}
 	}
 }
 
 int rtw_linked_check(struct rtw_adapter *padapter)
 {
-	if ((check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) ||
-	    (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))) {
+	if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) ||
+	    check_fwstate(&padapter->mlmepriv,
+			  WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
 		if (padapter->stapriv.asoc_sta_count > 2)
 			return true;
 	} else {	/* Station mode */
-		if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true)
+		if (check_fwstate(&padapter->mlmepriv, _FW_LINKED))
 			return true;
 	}
 	return false;
diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
index 4c753639ea5a..68991dca1cbf 100644
--- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
@@ -21,13 +21,34 @@
 #include <wlan_bssdef.h>
 #include <mlme_osdep.h>
 #include <recv_osdep.h>
-#include <ethernet.h>
 #include <linux/ieee80211.h>
 
 #ifdef CONFIG_8723AU_BT_COEXIST
 #include <rtl8723a_hal.h>
 #endif
 
+static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+
+static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+
 static struct mlme_handler mlme_sta_tbl[]={
 	{"OnAssocReq23a",		&OnAssocReq23a},
 	{"OnAssocRsp23a",		&OnAssocRsp23a},
@@ -66,7 +87,6 @@ static u8	null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
 /**************************************************
 OUI definitions for the vendor specific IE
 ***************************************************/
-unsigned char	RTW_WPA_OUI23A[] = {0x00, 0x50, 0xf2, 0x01};
 unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
 unsigned char	WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
 unsigned char	P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
@@ -229,6 +249,17 @@ static struct fwevent wlanevents[] =
 };
 
 
+static void rtw_correct_TSF(struct rtw_adapter *padapter)
+{
+	hw_var_set_correct_tsf(padapter);
+}
+
+static void
+rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt)
+{
+	pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp);
+}
+
 /*
  * Search the @param channel_num in given @param channel_set
  * @ch_set: the given channel set
@@ -388,96 +419,88 @@ static void init_channel_list(struct rtw_adapter *padapter,
 	channel_list->reg_classes = cla;
 }
 
-static u8 init_channel_set(struct rtw_adapter* padapter, u8 ChannelPlan,
-			   struct rt_channel_info *channel_set)
+static u8 init_channel_set(struct rtw_adapter* padapter, u8 cplan,
+			   struct rt_channel_info *c_set)
 {
-	u8	index, chanset_size = 0;
-	u8	b5GBand = false, b2_4GBand = false;
-	u8	Index2G = 0, Index5G = 0;
+	u8 i, ch_size = 0;
+	u8 b5GBand = false, b2_4GBand = false;
+	u8 Index2G = 0, Index5G = 0;
 
-	memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM);
+	memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
 
-	if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX &&
-	    ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
-		DBG_8723A("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
-		return chanset_size;
+	if (cplan >= RT_CHANNEL_DOMAIN_MAX &&
+	    cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
+		DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan);
+		return ch_size;
 	}
 
 	if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
 		b2_4GBand = true;
-		if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
+		if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
 			Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
 		else
-			Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
+			Index2G = RTW_ChannelPlanMap[cplan].Index2G;
 	}
 
 	if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
 		b5GBand = true;
-		if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
+		if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
 			Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
 		else
-			Index5G = RTW_ChannelPlanMap[ChannelPlan].Index5G;
+			Index5G = RTW_ChannelPlanMap[cplan].Index5G;
 	}
 
 	if (b2_4GBand) {
-		for (index = 0; index<RTW_ChannelPlan2G[Index2G].Len; index++) {
-			channel_set[chanset_size].ChannelNum =
-				RTW_ChannelPlan2G[Index2G].Channel[index];
+		for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) {
+			c_set[ch_size].ChannelNum =
+				RTW_ChannelPlan2G[Index2G].Channel[i];
 
-			if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||
+			if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) ||
 			    /* Channel 1~11 is active, and 12~14 is passive */
-			    (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)){
-				if (channel_set[chanset_size].ChannelNum >= 1 &&
-				    channel_set[chanset_size].ChannelNum <= 11)
-					channel_set[chanset_size].ScanType =
-						SCAN_ACTIVE;
-				else if ((channel_set[chanset_size].ChannelNum >= 12 &&
-					  channel_set[chanset_size].ChannelNum  <= 14))
-					channel_set[chanset_size].ScanType =
-						SCAN_PASSIVE;
-			} else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ==
-				   ChannelPlan ||
-				   RT_CHANNEL_DOMAIN_WORLD_WIDE_5G ==
-				   ChannelPlan ||
+			    RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) {
+				if (c_set[ch_size].ChannelNum >= 1 &&
+				    c_set[ch_size].ChannelNum <= 11)
+					c_set[ch_size].ScanType = SCAN_ACTIVE;
+				else if (c_set[ch_size].ChannelNum >= 12 &&
+					 c_set[ch_size].ChannelNum  <= 14)
+					c_set[ch_size].ScanType = SCAN_PASSIVE;
+			} else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan ||
+				   RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan ||
 				   RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
 				/*  channel 12~13, passive scan */
-				if (channel_set[chanset_size].ChannelNum <= 11)
-					channel_set[chanset_size].ScanType =
-						SCAN_ACTIVE;
+				if (c_set[ch_size].ChannelNum <= 11)
+					c_set[ch_size].ScanType = SCAN_ACTIVE;
 				else
-					channel_set[chanset_size].ScanType =
-						SCAN_PASSIVE;
+					c_set[ch_size].ScanType = SCAN_PASSIVE;
 			} else
-				channel_set[chanset_size].ScanType =
-					SCAN_ACTIVE;
+				c_set[ch_size].ScanType = SCAN_ACTIVE;
 
-			chanset_size++;
+			ch_size++;
 		}
 	}
 
 	if (b5GBand) {
-		for (index = 0;index<RTW_ChannelPlan5G[Index5G].Len;index++) {
-			if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 ||
-			    RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) {
-				channel_set[chanset_size].ChannelNum =
-					RTW_ChannelPlan5G[Index5G].Channel[index];
-				if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G ==
-				    ChannelPlan) {
+		for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) {
+			if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 ||
+			    RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) {
+				c_set[ch_size].ChannelNum =
+					RTW_ChannelPlan5G[Index5G].Channel[i];
+				if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) {
 					/* passive scan for all 5G channels */
-					channel_set[chanset_size].ScanType =
+					c_set[ch_size].ScanType =
 						SCAN_PASSIVE;
 				} else
-					channel_set[chanset_size].ScanType =
+					c_set[ch_size].ScanType =
 						SCAN_ACTIVE;
 				DBG_8723A("%s(): channel_set[%d].ChannelNum = "
-					  "%d\n", __func__, chanset_size,
-					  channel_set[chanset_size].ChannelNum);
-				chanset_size++;
+					  "%d\n", __func__, ch_size,
+					  c_set[ch_size].ChannelNum);
+				ch_size++;
 			}
 		}
 	}
 
-	return chanset_size;
+	return ch_size;
 }
 
 int init_mlme_ext_priv23a(struct rtw_adapter* padapter)
@@ -547,28 +570,28 @@ _mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
 void mgt_dispatcher23a(struct rtw_adapter *padapter,
 		    struct recv_frame *precv_frame)
 {
-	int index;
 	struct mlme_handler *ptable;
 #ifdef CONFIG_8723AU_AP_MODE
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 #endif /* CONFIG_8723AU_AP_MODE */
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u16 stype;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
 	struct sta_info *psta;
+	u16 stype;
+	int index;
 
-	if (!ieee80211_is_mgmt(hdr->frame_control))
+	if (!ieee80211_is_mgmt(mgmt->frame_control))
 		return;
 
 	/* receive the frames that ra(a1) is my address or ra(a1) is
 	   bc address. */
-	if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv)) &&
-	    !is_broadcast_ether_addr(hdr->addr1))
+	if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
+	    !is_broadcast_ether_addr(mgmt->da))
 		return;
 
 	ptable = mlme_sta_tbl;
 
-	stype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
+	stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
 	index = stype >> 4;
 
 	if (index > 13) {
@@ -579,10 +602,10 @@ void mgt_dispatcher23a(struct rtw_adapter *padapter,
 	}
 	ptable += index;
 
-	psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2);
+	psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
 
 	if (psta) {
-		if (ieee80211_has_retry(hdr->frame_control)) {
+		if (ieee80211_has_retry(mgmt->frame_control)) {
 			if (precv_frame->attrib.seq_num ==
 			    psta->RxMgmtFrameSeqNum) {
 				/* drop the duplicate management frame */
@@ -623,8 +646,6 @@ void mgt_dispatcher23a(struct rtw_adapter *padapter,
 		break;
 	default:
 		_mgt_dispatcher23a(padapter, ptable, precv_frame);
-		if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
-			rtw_hostapd_mlme_rx23a(padapter, precv_frame);
 		break;
 	}
 #else
@@ -632,186 +653,63 @@ void mgt_dispatcher23a(struct rtw_adapter *padapter,
 #endif
 }
 
-#ifdef CONFIG_8723AU_P2P
-static u32 p2p_listen_state_process(struct rtw_adapter *padapter,
-				    unsigned char *da)
-{
-	bool response = true;
-
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == false ||
-	    padapter->mlmepriv.wps_probe_resp_ie == NULL ||
-	    padapter->mlmepriv.p2p_probe_resp_ie == NULL) {
-		DBG_8723A("DON'T issue_probersp23a_p2p23a: p2p_enabled:%d, "
-			  "wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n",
-			  wdev_to_priv(padapter->rtw_wdev)->p2p_enabled,
-			  padapter->mlmepriv.wps_probe_resp_ie,
-			  padapter->mlmepriv.p2p_probe_resp_ie);
-		response = false;
-	}
-
-	if (response == true)
-		issue_probersp23a_p2p23a(padapter, da);
-
-	return _SUCCESS;
-}
-#endif /* CONFIG_8723AU_P2P */
-
 /****************************************************************************
 
 Following are the callback functions for each subtype of the management frames
 
 *****************************************************************************/
 
-unsigned int OnProbeReq23a(struct rtw_adapter *padapter,
-			   struct recv_frame *precv_frame)
+static int
+OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
-	unsigned int	ielen;
-	unsigned char	*p;
+	const u8 *ie;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur = &pmlmeinfo->network;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
-	uint len = skb->len;
-	u8 is_valid_p2p_probereq = false;
-
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	u8 wifi_test_chk_rate = 1;
-
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
-	    !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
-		/*	mcs_rate = 0 -> CCK 1M rate */
-		/*	mcs_rate = 1 -> CCK 2M rate */
-		/*	mcs_rate = 2 -> CCK 5.5M rate */
-		/*	mcs_rate = 3 -> CCK 11M rate */
-		/*	In the P2P mode, the driver should not support
-			the CCK rate */
-
-		/*	IOT issue: Google Nexus7 use 1M rate to send
-			p2p_probe_req after GO nego completed and Nexus7
-			is client */
-		if (wifi_test_chk_rate == 1) {
-			if ((is_valid_p2p_probereq =
-			     process_probe_req_p2p_ie23a(pwdinfo, pframe,
-							 len)) == true) {
-				if (rtw_p2p_chk_role(pwdinfo,
-						     P2P_ROLE_DEVICE)) {
-					u8 *sa = ieee80211_get_SA(hdr);
-					p2p_listen_state_process(padapter, sa);
-					return _SUCCESS;
-				}
-
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-					goto _continue;
-				}
-			}
-		}
-	}
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
+	int len = skb->len;
 
-_continue:
-#endif /* CONFIG_8723AU_P2P */
-
-	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 		return _SUCCESS;
-	}
 
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
-		check_fwstate(pmlmepriv,
-			      WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
+	if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
+	    !check_fwstate(pmlmepriv,
+			   WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
 		return _SUCCESS;
-	}
 
-	p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) +
-			  _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
-			  len - sizeof(struct ieee80211_hdr_3addr) -
-			  _PROBEREQ_IE_OFFSET_);
+	if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) {
+		printk(KERN_WARNING "%s: Received non probe request frame\n",
+		       __func__);
+		return _FAIL;
+	}
 
-	/* check (wildcard) SSID */
-	if (p) {
-		if (is_valid_p2p_probereq == true) {
-			goto _issue_probersp23a;
-		}
+	len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
 
-		if ((ielen != 0 &&
-		     memcmp((void *)(p+2), cur->Ssid.ssid,
-			    cur->Ssid.ssid_len)) ||
-		    (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) {
-			return _SUCCESS;
-		}
+	ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len);
 
-_issue_probersp23a:
+	/* check (wildcard) SSID */
+	if (!ie)
+		goto out;
 
-		if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
-		    pmlmepriv->cur_network.join_res == true) {
-			/* DBG_8723A("+issue_probersp23a during ap mode\n"); */
-			issue_probersp23a(padapter, ieee80211_get_SA(hdr),
-					  is_valid_p2p_probereq);
-		}
+	if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
+	    (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
+		return _SUCCESS;
 	}
 
+	if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+	    pmlmepriv->cur_network.join_res)
+		issue_probersp23a(padapter, mgmt->sa, false);
+
+out:
 	return _SUCCESS;
 }
 
-unsigned int OnProbeRsp23a(struct rtw_adapter *padapter,
-			   struct recv_frame *precv_frame)
+static int
+OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-#ifdef CONFIG_8723AU_P2P
-	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
-#endif
-
-#ifdef CONFIG_8723AU_P2P
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))	{
-		if (pwdinfo->tx_prov_disc_info.benable == true) {
-			if (ether_addr_equal(pwdinfo->tx_prov_disc_info.peerIFAddr,
-				    hdr->addr2)) {
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-					pwdinfo->tx_prov_disc_info.benable = false;
-					issue_p2p_provision_request23a(padapter,
-								    				pwdinfo->tx_prov_disc_info.ssid.ssid,
-												pwdinfo->tx_prov_disc_info.ssid.ssid_len,
-												pwdinfo->tx_prov_disc_info.peerDevAddr);
-				}
-				else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-				{
-					pwdinfo->tx_prov_disc_info.benable = false;
-					issue_p2p_provision_request23a(padapter,
-												NULL,
-												0,
-												pwdinfo->tx_prov_disc_info.peerDevAddr);
-				}
-			}
-		}
-		return _SUCCESS;
-	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
-		if (pwdinfo->nego_req_info.benable == true) {
-			DBG_8723A("[%s] P2P State is GONEGO ING!\n", __func__);
-			if (ether_addr_equal(pwdinfo->nego_req_info.peerDevAddr,
-					     hdr->addr2)) {
-				pwdinfo->nego_req_info.benable = false;
-				issue_p2p_GO_request23a(padapter, pwdinfo->nego_req_info.peerDevAddr);
-			}
-		}
-	} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
-		if (pwdinfo->invitereq_info.benable == true) {
-			DBG_8723A("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
-			if (ether_addr_equal(
-				    pwdinfo->invitereq_info.peer_macaddr,
-				    hdr->addr2)) {
-				pwdinfo->invitereq_info.benable = false;
-				issue_p2p_invitation_request23a(padapter, pwdinfo->invitereq_info.peer_macaddr);
-			}
-		}
-	}
-#endif
 
 	if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 		report_survey_event23a(padapter, precv_frame);
@@ -821,30 +719,30 @@ unsigned int OnProbeRsp23a(struct rtw_adapter *padapter,
 	return _SUCCESS;
 }
 
-unsigned int OnBeacon23a(struct rtw_adapter *padapter,
-			 struct recv_frame *precv_frame)
+static int
+OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	int cam_idx;
 	struct sta_info	*psta;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct sta_priv	*pstapriv = &padapter->stapriv;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
 	u8 *pframe = skb->data;
-	uint len = skb->len;
+	int pkt_len = skb->len;
 	struct wlan_bssid_ex *pbss;
 	int ret = _SUCCESS;
-	u8 *p = NULL;
+	u8 *p, *pie;
+	int pie_len;
 	u32 ielen = 0;
 
-	p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) +
-			  _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen,
-			  len - sizeof(struct ieee80211_hdr_3addr) -
-			  _BEACON_IE_OFFSET_);
-	if ((p != NULL) && (ielen > 0)) {
-		if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) {
+	pie = mgmt->u.beacon.variable;
+	pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
+	p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len);
+	if (p && ielen > 0) {
+		if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) {
 			/* Invalid value 0x2D is detected in Extended Supported
 			 * Rates (ESR) IE. Try to fix the IE length to avoid
 			 * failed Beacon parsing.
@@ -852,8 +750,8 @@ unsigned int OnBeacon23a(struct rtw_adapter *padapter,
 			DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
 				  "Beacon of BSSID: %pM. Fix the length of "
 				  "ESR IE to avoid failed Beacon parsing.\n",
-				  hdr->addr3);
-			*(p + 1) = ielen - 1;
+				  mgmt->bssid);
+			p[1] = ielen - 1;
 		}
 	}
 
@@ -862,129 +760,130 @@ unsigned int OnBeacon23a(struct rtw_adapter *padapter,
 		return _SUCCESS;
 	}
 
-	if (ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network))){
-		if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
-			/* we should update current network before auth,
-			   or some IE is wrong */
-			pbss = (struct wlan_bssid_ex *)
-				kmalloc(sizeof(struct wlan_bssid_ex),
-					GFP_ATOMIC);
-			if (pbss) {
-				if (collect_bss_info23a(padapter, precv_frame,
-							pbss) == _SUCCESS) {
-					update_network23a(&pmlmepriv->cur_network.network, pbss, padapter, true);
-					rtw_get_bcn_info23a(&pmlmepriv->cur_network);
-				}
-				kfree(pbss);
-			}
+	if (!ether_addr_equal(mgmt->bssid,
+			      get_my_bssid23a(&pmlmeinfo->network)))
+		goto out;
 
-			/* check the vendor of the assoc AP */
-			pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pframe + sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
+	if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
+		/* we should update current network before auth,
+		   or some IE is wrong */
+		pbss = (struct wlan_bssid_ex *)
+			kmalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
+		if (pbss) {
+			if (collect_bss_info23a(padapter, precv_frame, pbss) ==
+			    _SUCCESS) {
+				update_network23a(
+					&pmlmepriv->cur_network.network, pbss,
+					padapter, true);
+				rtw_get_bcn_info23a(&pmlmepriv->cur_network);
+			}
+			kfree(pbss);
+		}
 
-			/* update TSF Value */
-			update_TSF23a(pmlmeext, pframe, len);
+		/* check the vendor of the assoc AP */
+		pmlmeinfo->assoc_AP_vendor =
+			check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len -
+					  offsetof(struct ieee80211_mgmt, u));
 
-			/* start auth */
-			start_clnt_auth23a(padapter);
+		/* update TSF Value */
+		rtw_update_TSF(pmlmeext, mgmt);
 
-			return _SUCCESS;
-		}
+		/* start auth */
+		start_clnt_auth23a(padapter);
 
-		if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) &&
-		    (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
-			psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
-			if (psta) {
-				ret = rtw_check_bcn_info23a(padapter, pframe,
-							    len);
-				if (!ret) {
-					DBG_8723A_LEVEL(_drv_always_,
-							"ap has changed, "
-							"disconnect now\n");
-					receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
-					return _SUCCESS;
-				}
-				/* update WMM, ERP in the beacon */
-				/* todo: the timer is used instead of
-				   the number of the beacon received */
-				if ((sta_rx_pkts(psta) & 0xf) == 0) {
-					/* DBG_8723A("update_bcn_info\n"); */
-					update_beacon23a_info(padapter, pframe,
-							      len, psta);
-				}
+		return _SUCCESS;
+	}
 
-#ifdef CONFIG_8723AU_P2P
-				process_p2p_ps_ie23a(padapter, (pframe + sizeof(struct ieee80211_hdr_3addr)), (len - sizeof(struct ieee80211_hdr_3addr)));
-#endif /* CONFIG_8723AU_P2P */
+	if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) &&
+	    (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
+		psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
+		if (psta) {
+			ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
+			if (!ret) {
+				DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
+						"disconnect now\n");
+				receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
+				return _SUCCESS;
+			}
+			/* update WMM, ERP in the beacon */
+			/* todo: the timer is used instead of
+			   the number of the beacon received */
+			if ((sta_rx_pkts(psta) & 0xf) == 0) {
+				/* DBG_8723A("update_bcn_info\n"); */
+				update_beacon23a_info(padapter, pframe,
+						      pkt_len, psta);
+			}
+		}
+	} else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
+		psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
+		if (psta) {
+			/* update WMM, ERP in the beacon */
+			/* todo: the timer is used instead of the
+			   number of the beacon received */
+			if ((sta_rx_pkts(psta) & 0xf) == 0) {
+				/* DBG_8723A("update_bcn_info\n"); */
+				update_beacon23a_info(padapter, pframe,
+						      pkt_len, psta);
+			}
+		} else {
+			/* allocate a new CAM entry for IBSS station */
+			cam_idx = allocate_fw_sta_entry23a(padapter);
+			if (cam_idx == NUM_STA)
+				goto out;
+
+			/* get supported rate */
+			if (update_sta_support_rate23a(padapter, pie, pie_len,
+						       cam_idx) == _FAIL) {
+				pmlmeinfo->FW_sta_info[cam_idx].status = 0;
+				goto out;
 			}
-		} else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
-			psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
-			if (psta) {
-				/* update WMM, ERP in the beacon */
-				/* todo: the timer is used instead of the
-				   number of the beacon received */
-				if ((sta_rx_pkts(psta) & 0xf) == 0) {
-					/* DBG_8723A("update_bcn_info\n"); */
-					update_beacon23a_info(padapter, pframe,
-							      len, psta);
-				}
-			} else {
-				/* allocate a new CAM entry for IBSS station */
-				cam_idx = allocate_fw_sta_entry23a(padapter);
-				if (cam_idx == NUM_STA)
-					goto _END_ONBEACON_;
-
-				/* get supported rate */
-				if (update_sta_support_rate23a(padapter, (pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_), (len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
-					pmlmeinfo->FW_sta_info[cam_idx].status = 0;
-					goto _END_ONBEACON_;
-				}
 
-				/* update TSF Value */
-				update_TSF23a(pmlmeext, pframe, len);
+			/* update TSF Value */
+			rtw_update_TSF(pmlmeext, mgmt);
 
-				/* report sta add event */
-				report_add_sta_event23a(padapter, hdr->addr2,
-							cam_idx);
-			}
+			/* report sta add event */
+			report_add_sta_event23a(padapter, mgmt->sa,
+						cam_idx);
 		}
 	}
 
-_END_ONBEACON_:
+out:
 
 	return _SUCCESS;
 }
 
-unsigned int OnAuth23a(struct rtw_adapter *padapter,
-		       struct recv_frame *precv_frame)
+static int
+OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_8723AU_AP_MODE
-	unsigned int	auth_mode, seq, ie_len;
-	unsigned char	*sa, *p;
-	u16	algorithm;
-	int	status;
 	static struct sta_info stat;
-	struct	sta_info	*pstat = NULL;
-	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *pstat = NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
-	uint len = skb->len;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
+	u8 *pframe;
+	const u8 *p;
+	unsigned char *sa;
+	u16 auth_mode, seq, algorithm;
+	int status, len = skb->len;
 
-	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
 		return _FAIL;
 
 	DBG_8723A("+OnAuth23a\n");
 
-	sa = hdr->addr2;
+	sa = mgmt->sa;
 
 	auth_mode = psecuritypriv->dot11AuthAlgrthm;
-	seq = cpu_to_le16(*(u16*)((unsigned long)pframe +
-				  sizeof(struct ieee80211_hdr_3addr) + 2));
-	algorithm = cpu_to_le16(*(u16*)((unsigned long)pframe +
-					sizeof(struct ieee80211_hdr_3addr)));
+
+	pframe = mgmt->u.auth.variable;
+	len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable);
+
+	seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
+	algorithm = le16_to_cpu(mgmt->u.auth.auth_alg);
 
 	DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
 
@@ -995,8 +894,8 @@ unsigned int OnAuth23a(struct rtw_adapter *padapter,
 
 	/*  rx a shared-key auth but shared not enabled, or */
 	/*  rx a open-system auth but shared-key is enabled */
-	if ((algorithm > 0 && auth_mode == 0) ||
-	    (algorithm == 0 && auth_mode == 1)) {
+	if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) ||
+	    (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) {
 		DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
 			  "=%d] %02X%02X%02X%02X%02X%02X\n",
 			  algorithm, auth_mode,
@@ -1035,8 +934,7 @@ unsigned int OnAuth23a(struct rtw_adapter *padapter,
 		if (!list_empty(&pstat->asoc_list)) {
 			list_del_init(&pstat->asoc_list);
 			pstapriv->asoc_list_cnt--;
-			if (pstat->expire_to > 0)
-			{
+			if (pstat->expire_to > 0) {
 				/* TODO: STA re_auth within expire_to */
 			}
 		}
@@ -1064,7 +962,7 @@ unsigned int OnAuth23a(struct rtw_adapter *padapter,
 		goto auth_fail;
 	}
 
-	if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
+	if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
 		if (seq == 1) {
 			pstat->state &= ~WIFI_FW_AUTH_NULL;
 			pstat->state |= WIFI_FW_AUTH_SUCCESS;
@@ -1088,22 +986,16 @@ unsigned int OnAuth23a(struct rtw_adapter *padapter,
 			/* checking for challenging txt... */
 			DBG_8723A("checking for challenging txt...\n");
 
-			p = rtw_get_ie23a(pframe +
-					  sizeof(struct ieee80211_hdr_3addr) +
-					  4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_,
-					  (int *)&ie_len, len -
-					  sizeof(struct ieee80211_hdr_3addr) -
-					  _AUTH_IE_OFFSET_ - 4);
-
-			if ((p == NULL) || (ie_len<= 0)) {
+			p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len);
+			if (!p || p[1] <= 0) {
 				DBG_8723A("auth rejected because challenge "
 					  "failure!(1)\n");
 				status = WLAN_STATUS_CHALLENGE_FAIL;
 				goto auth_fail;
 			}
 
-			if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
-				pstat->state &= (~WIFI_FW_AUTH_STATE);
+			if (!memcmp(p + 2, pstat->chg_txt, 128)) {
+				pstat->state &= ~WIFI_FW_AUTH_STATE;
 				pstat->state |= WIFI_FW_AUTH_SUCCESS;
 				/*  challenging txt is correct... */
 				pstat->expire_to =  pstapriv->assoc_to;
@@ -1125,7 +1017,7 @@ unsigned int OnAuth23a(struct rtw_adapter *padapter,
 	/*  Now, we are going to issue_auth23a... */
 	pstat->auth_seq = seq + 1;
 
-	issue_auth23a(padapter, pstat, (unsigned short)WLAN_STATUS_SUCCESS);
+	issue_auth23a(padapter, pstat, WLAN_STATUS_SUCCESS);
 
 	if (pstat->state & WIFI_FW_AUTH_SUCCESS)
 		pstat->auth_seq = 0;
@@ -1148,40 +1040,39 @@ auth_fail:
 	return _FAIL;
 }
 
-unsigned int OnAuth23aClient23a(struct rtw_adapter *padapter,
-				struct recv_frame *precv_frame)
+static int
+OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
-	unsigned int	seq, len, status, algthm, offset;
-	unsigned char	*p;
-	unsigned int	go2asoc = 0;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	unsigned int seq, status, algthm;
+	unsigned int go2asoc = 0;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
-	uint pkt_len = skb->len;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
+	const u8 *p;
+	u8 *pie;
+	int plen = skb->len;
 
 	DBG_8723A("%s\n", __func__);
 
 	/* check A1 matches or not */
-	if (!ether_addr_equal(myid(&padapter->eeprompriv),
-			      ieee80211_get_DA(hdr)))
+	if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
 		return _SUCCESS;
 
 	if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
 		return _SUCCESS;
 
-	offset = ieee80211_has_protected(hdr->frame_control) ? 4: 0;
+	pie = mgmt->u.auth.variable;
+	plen -= offsetof(struct ieee80211_mgmt, u.auth.variable);
 
-	algthm	= le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset));
-	seq	= le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset + 2));
-	status	= le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset + 4));
+	algthm = le16_to_cpu(mgmt->u.auth.auth_alg);
+	seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
+	status = le16_to_cpu(mgmt->u.auth.status_code);
 
-	if (status != 0)
-	{
+	if (status) {
 		DBG_8723A("clnt auth fail, status: %d\n", status);
-		if (status == 13)/*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
-		{
+		/*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
+		if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
 			if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
 				pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
 			else
@@ -1193,53 +1084,39 @@ unsigned int OnAuth23aClient23a(struct rtw_adapter *padapter,
 		goto authclnt_fail;
 	}
 
-	if (seq == 2)
-	{
-		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
-		{
-			 /*  legendary shared system */
-			p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
-				pkt_len - sizeof(struct ieee80211_hdr_3addr) - _AUTH_IE_OFFSET_);
+	if (seq == 2) {
+		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
+			/*  legendary shared system */
+			p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
 
-			if (p == NULL)
-			{
+			if (!p) {
 				/* DBG_8723A("marc: no challenge text?\n"); */
 				goto authclnt_fail;
 			}
 
-			memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
+			memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]);
 			pmlmeinfo->auth_seq = 3;
 			issue_auth23a(padapter, NULL, 0);
 			set_link_timer(pmlmeext, REAUTH_TO);
 
 			return _SUCCESS;
-		}
-		else
-		{
+		} else {
 			/*  open system */
 			go2asoc = 1;
 		}
-	}
-	else if (seq == 4)
-	{
+	} else if (seq == 4) {
 		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
-		{
 			go2asoc = 1;
-		}
 		else
-		{
 			goto authclnt_fail;
-		}
-	}
-	else
-	{
+	} else {
 		/*  this is also illegal */
-		/* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n", seq); */
+		/* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n",
+		   seq); */
 		goto authclnt_fail;
 	}
 
-	if (go2asoc)
-	{
+	if (go2asoc) {
 		DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
 		start_clnt_assoc23a(padapter);
 		return _SUCCESS;
@@ -1252,19 +1129,153 @@ authclnt_fail:
 	return _FAIL;
 }
 
-unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+#ifdef CONFIG_8723AU_AP_MODE
+static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
+{
+	unsigned int oui;
+
+	/* first 3 bytes in vendor specific information element are the IEEE
+	 * OUI of the vendor. The following byte is used a vendor specific
+	 * sub-type. */
+	if (elen < 4) {
+		DBG_8723A("short vendor specific information element "
+			  "ignored (len =%i)\n", elen);
+		return -EINVAL;
+	}
+
+	oui = RTW_GET_BE24(pos);
+	switch (oui) {
+	case WLAN_OUI_MICROSOFT:
+		/* Microsoft/Wi-Fi information elements are further typed and
+		 * subtyped */
+		switch (pos[3]) {
+		case 1:
+			/* Microsoft OUI (00:50:F2) with OUI Type 1:
+			 * real WPA information element */
+			break;
+		case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
+			if (elen < 5) {
+				DBG_8723A("short WME information element "
+					  "ignored (len =%i)\n", elen);
+				return -EINVAL;
+			}
+			switch (pos[4]) {
+			case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
+			case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
+				break;
+			case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
+				break;
+			default:
+				DBG_8723A("unknown WME information element "
+					  "ignored (subtype =%d len =%i)\n",
+					   pos[4], elen);
+				return -EINVAL;
+			}
+			break;
+		case 4:
+			/* Wi-Fi Protected Setup (WPS) IE */
+			break;
+		default:
+			DBG_8723A("Unknown Microsoft information element "
+				  "ignored (type =%d len =%i)\n",
+				  pos[3], elen);
+			return -EINVAL;
+		}
+		break;
+
+	case OUI_BROADCOM:
+		switch (pos[3]) {
+		case VENDOR_HT_CAPAB_OUI_TYPE:
+			break;
+		default:
+			DBG_8723A("Unknown Broadcom information element "
+				  "ignored (type =%d len =%i)\n", pos[3], elen);
+			return -EINVAL;
+		}
+		break;
+
+	default:
+		DBG_8723A("unknown vendor specific information element "
+			  "ignored (vendor OUI %02x:%02x:%02x len =%i)\n",
+			   pos[0], pos[1], pos[2], elen);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rtw_validate_frame_ies(const u8 *start, uint len)
+{
+	const u8 *pos = start;
+	int left = len;
+	int unknown = 0;
+
+	while (left >= 2) {
+		u8 id, elen;
+
+		id = *pos++;
+		elen = *pos++;
+		left -= 2;
+
+		if (elen > left) {
+			DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
+				  "left =%i)\n", __func__, id, elen, left);
+			return -EINVAL;
+		}
+
+		switch (id) {
+		case WLAN_EID_SSID:
+		case WLAN_EID_SUPP_RATES:
+		case WLAN_EID_FH_PARAMS:
+		case WLAN_EID_DS_PARAMS:
+		case WLAN_EID_CF_PARAMS:
+		case WLAN_EID_TIM:
+		case WLAN_EID_IBSS_PARAMS:
+		case WLAN_EID_CHALLENGE:
+		case WLAN_EID_ERP_INFO:
+		case WLAN_EID_EXT_SUPP_RATES:
+		case WLAN_EID_VENDOR_SPECIFIC:
+		if (rtw_validate_vendor_specific_ies(pos, elen))
+			unknown++;
+			break;
+		case WLAN_EID_RSN:
+		case WLAN_EID_PWR_CAPABILITY:
+		case WLAN_EID_SUPPORTED_CHANNELS:
+		case WLAN_EID_MOBILITY_DOMAIN:
+		case WLAN_EID_FAST_BSS_TRANSITION:
+		case WLAN_EID_TIMEOUT_INTERVAL:
+		case WLAN_EID_HT_CAPABILITY:
+		case WLAN_EID_HT_OPERATION:
+		default:
+			unknown++;
+			DBG_8723A("%s IEEE 802.11 ignored unknown element "
+				  "(id =%d elen =%d)\n", __func__, id, elen);
+			break;
+		}
+
+		left -= elen;
+		pos += elen;
+	}
+
+	if (left)
+		return -EINVAL;
+
+	return 0;
+}
+#endif
+
+static int
+OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 #ifdef CONFIG_8723AU_AP_MODE
 	u16 capab_info, listen_interval;
-	struct rtw_ieee802_11_elems elems;
 	struct sta_info	*pstat;
-	unsigned char		reassoc, *p, *pos, *wpa_ie;
+	unsigned char reassoc;
 	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
-	int		i, ie_len, wpa_ie_len, left;
-	unsigned char		supportRate[16];
-	int					supportRateNum;
-	unsigned short		status = WLAN_STATUS_SUCCESS;
-	unsigned short ie_offset;
+	int i, wpa_ie_len, left;
+	unsigned char supportRate[16];
+	int supportRateNum;
+	unsigned short status = WLAN_STATUS_SUCCESS;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
@@ -1272,69 +1283,56 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	struct wlan_bssid_ex *cur = &pmlmeinfo->network;
 	struct sta_priv *pstapriv = &padapter->stapriv;
 	struct sk_buff *skb = precv_frame->pkt;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
+	const u8 *pos, *p, *wpa_ie, *wps_ie;
 	u8 *pframe = skb->data;
 	uint pkt_len = skb->len;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u16 frame_control;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	u8 p2p_status_code = P2P_STATUS_SUCCESS;
-	u8 *p2pie;
-	u32 p2pielen = 0;
-	u8	wfd_ie[ 128 ] = { 0x00 };
-	u32	wfd_ielen = 0;
-#endif /* CONFIG_8723AU_P2P */
+	int r;
 
-	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+	if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
 		return _FAIL;
 
-	frame_control = hdr->frame_control;
-	if (ieee80211_is_assoc_req(frame_control)) {
+	left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
+	if (ieee80211_is_assoc_req(mgmt->frame_control)) {
 		reassoc = 0;
-		ie_offset = _ASOCREQ_IE_OFFSET_;
+		pos = mgmt->u.assoc_req.variable;
+		left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
 	} else { /*  WIFI_REASSOCREQ */
 		reassoc = 1;
-		ie_offset = _REASOCREQ_IE_OFFSET_;
+		pos = mgmt->u.reassoc_req.variable;
+		left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
 	}
 
-	if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) {
-		DBG_8723A("handle_assoc(reassoc =%d) - too short payload (len =%lu)"
-		       "\n", reassoc, (unsigned long)pkt_len);
+	if (left < 0) {
+		DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
+			  "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
 		return _FAIL;
 	}
 
-	pstat = rtw_get_stainfo23a(pstapriv, hdr->addr2);
+	pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
 	if (!pstat) {
 		status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
 		goto asoc_class2_error;
 	}
 
-	capab_info = get_unaligned_le16(pframe + sizeof(struct ieee80211_hdr_3addr));
-	/* capab_info = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr))); */
-	/* listen_interval = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)+2)); */
-	listen_interval = get_unaligned_le16(pframe + sizeof(struct ieee80211_hdr_3addr)+2);
-
-	left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
-	pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
+	/* These two are located at the same offsets whether it's an
+	 * assoc_req or a reassoc_req */
+	capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info);
+	listen_interval =
+		get_unaligned_le16(&mgmt->u.assoc_req.listen_interval);
 
 	DBG_8723A("%s\n", __func__);
 
 	/*  check if this stat has been successfully authenticated/assocated */
-	if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS))
-	{
-		if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS))
-		{
+	if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) {
+		if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) {
 			status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
 			goto asoc_class2_error;
-		}
-		else
-		{
+		} else {
 			pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
 			pstat->state |= WIFI_FW_ASSOC_STATE;
 		}
-	}
-	else
-	{
+	} else {
 		pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
 		pstat->state |= WIFI_FW_ASSOC_STATE;
 	}
@@ -1342,41 +1340,40 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	pstat->capability = capab_info;
 
 	/* now parse all ieee802_11 ie to point to elems */
-	if (rtw_ieee802_11_parse_elems23a(pos, left, &elems, 1) == ParseFailed ||
-	    !elems.ssid) {
+
+	if (rtw_validate_frame_ies(pos, left)) {
 		DBG_8723A("STA " MAC_FMT " sent invalid association request\n",
-		       MAC_ARG(pstat->hwaddr));
+			  MAC_ARG(pstat->hwaddr));
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 		goto OnAssocReq23aFail;
 	}
 
 	/*  now we should check all the fields... */
 	/*  checking SSID */
-	p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _SSID_IE_, &ie_len,
-		pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
-	if (p == NULL)
-	{
-		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
-	}
-
-	if (ie_len == 0) /*  broadcast ssid, however it is not allowed in assocreq */
+	p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
+	if (!p || p[1] == 0) {
+		/*  broadcast ssid, however it is not allowed in assocreq */
+		DBG_8723A("STA " MAC_FMT " sent invalid association request "
+			  "lacking an SSID\n", MAC_ARG(pstat->hwaddr));
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
-	else {
+		goto OnAssocReq23aFail;
+	} else {
 		/*  check if ssid match */
-		if (memcmp((void *)(p+2), cur->Ssid.ssid, cur->Ssid.ssid_len))
+		if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len))
 			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 
-		if (ie_len != cur->Ssid.ssid_len)
+		if (p[1] != cur->Ssid.ssid_len)
 			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 	}
 
-	if (WLAN_STATUS_SUCCESS != status)
+	if (status != WLAN_STATUS_SUCCESS)
 		goto OnAssocReq23aFail;
 
 	/*  check if the supported rate is ok */
-	p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
-	if (p == NULL) {
-		DBG_8723A("Rx a sta assoc-req which supported rate is empty!\n");
+	p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left);
+	if (!p) {
+		DBG_8723A("Rx a sta assoc-req which supported rate is "
+			  "empty!\n");
 		/*  use our own rate set as statoin used */
 		/* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
 		/* supportRateNum = AP_BSSRATE_LEN; */
@@ -1384,17 +1381,14 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 		goto OnAssocReq23aFail;
 	} else {
-		memcpy(supportRate, p+2, ie_len);
-		supportRateNum = ie_len;
-
-		p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
-				pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
-		if (p !=  NULL) {
-
-			if (supportRateNum<= sizeof(supportRate))
-			{
-				memcpy(supportRate+supportRateNum, p+2, ie_len);
-				supportRateNum += ie_len;
+		memcpy(supportRate, p + 2, p[1]);
+		supportRateNum = p[1];
+
+		p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
+		if (!p) {
+			if (supportRateNum <= sizeof(supportRate)) {
+				memcpy(supportRate+supportRateNum, p + 2, p[1]);
+				supportRateNum += p[1];
 			}
 		}
 	}
@@ -1415,90 +1409,97 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	pstat->wpa_pairwise_cipher = 0;
 	pstat->wpa2_pairwise_cipher = 0;
 	memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
-	if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
 
+	wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left);
+	if (!wpa_ie)
+		wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+						 WLAN_OUI_TYPE_MICROSOFT_WPA,
+						 pos, left);
+	if (wpa_ie) {
 		int group_cipher = 0, pairwise_cipher = 0;
 
-		wpa_ie = elems.rsn_ie;
-		wpa_ie_len = elems.rsn_ie_len;
-
-		if (rtw_parse_wpa2_ie23a(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
-			pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
-			pstat->wpa_psk |= BIT(1);
-
-			pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
-			pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
-
-			if (!pstat->wpa2_group_cipher)
-				status = WLAN_REASON_INVALID_GROUP_CIPHER;
-
-			if (!pstat->wpa2_pairwise_cipher)
-				status = WLAN_REASON_INVALID_PAIRWISE_CIPHER;
+		wpa_ie_len = wpa_ie[1];
+		if (psecuritypriv->wpa_psk & BIT(1)) {
+			r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2,
+						 &group_cipher,
+						 &pairwise_cipher, NULL);
+			if (r == _SUCCESS) {
+				pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
+				pstat->wpa_psk |= BIT(1);
+
+				pstat->wpa2_group_cipher = group_cipher &
+					psecuritypriv->wpa2_group_cipher;
+				pstat->wpa2_pairwise_cipher = pairwise_cipher &
+					psecuritypriv->wpa2_pairwise_cipher;
+			} else
+				status = WLAN_STATUS_INVALID_IE;
+		} else if (psecuritypriv->wpa_psk & BIT(0)) {
+			r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2,
+						&group_cipher, &pairwise_cipher,
+						NULL);
+			if (r == _SUCCESS) {
+				pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
+				pstat->wpa_psk |= BIT(0);
+
+				pstat->wpa_group_cipher = group_cipher &
+					psecuritypriv->wpa_group_cipher;
+				pstat->wpa_pairwise_cipher = pairwise_cipher &
+					psecuritypriv->wpa_pairwise_cipher;
+			} else
+				status = WLAN_STATUS_INVALID_IE;
 		} else {
-			status = WLAN_STATUS_INVALID_IE;
+			wpa_ie = NULL;
+			wpa_ie_len = 0;
 		}
-
-	} else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
-
-		int group_cipher = 0, pairwise_cipher = 0;
-
-		wpa_ie = elems.wpa_ie;
-		wpa_ie_len = elems.wpa_ie_len;
-
-		if (rtw_parse_wpa_ie23a(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
-			pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
-			pstat->wpa_psk |= BIT(0);
-
-			pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
-			pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
-
+		if (wpa_ie && status == WLAN_STATUS_SUCCESS) {
 			if (!pstat->wpa_group_cipher)
 				status = WLAN_STATUS_INVALID_GROUP_CIPHER;
 
 			if (!pstat->wpa_pairwise_cipher)
 				status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
-
-		} else {
-			status = WLAN_STATUS_INVALID_IE;
 		}
-
-	} else {
-		wpa_ie = NULL;
-		wpa_ie_len = 0;
 	}
 
-	if (WLAN_STATUS_SUCCESS != status)
+	if (status != WLAN_STATUS_SUCCESS)
 		goto OnAssocReq23aFail;
 
 	pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
-	if (wpa_ie == NULL) {
-		if (elems.wps_ie) {
-			DBG_8723A("STA included WPS IE in "
-				   "(Re)Association Request - assume WPS is "
-				   "used\n");
+
+	wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+					 WLAN_OUI_TYPE_MICROSOFT_WPS,
+					 pos, left);
+
+	if (!wpa_ie) {
+		if (wps_ie) {
+			DBG_8723A("STA included WPS IE in (Re)Association "
+				  "Request - assume WPS is used\n");
 			pstat->flags |= WLAN_STA_WPS;
 		} else {
-			DBG_8723A("STA did not include WPA/RSN IE "
-				   "in (Re)Association Request - possible WPS "
-				   "use\n");
+			DBG_8723A("STA did not include WPA/RSN IE in (Re)"
+				   "Association Request - possible WPS use\n");
 			pstat->flags |= WLAN_STA_MAYBE_WPS;
 		}
 
-		/*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
+		/*  AP support WPA/RSN, and sta is going to do WPS, but AP
+		    is not ready */
 		/*  that the selected registrar of AP is _FLASE */
-		if ((psecuritypriv->wpa_psk > 0) &&
-		    (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
+		if (psecuritypriv->wpa_psk > 0 &&
+		    pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS)) {
 			if (pmlmepriv->wps_beacon_ie) {
 				u8 selected_registrar = 0;
 
-				rtw_get_wps_attr_content23a(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len,
-							 WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
+				rtw_get_wps_attr_content23a(
+					pmlmepriv->wps_beacon_ie,
+					pmlmepriv->wps_beacon_ie_len,
+					WPS_ATTR_SELECTED_REGISTRAR,
+					&selected_registrar, NULL);
 
 				if (!selected_registrar) {
-					DBG_8723A("selected_registrar is false , or AP is not ready to do WPS\n");
+					DBG_8723A("selected_registrar is false,"
+						  "or AP is not ready to do "
+						  "WPS\n");
 
 					status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
-
 					goto OnAssocReq23aFail;
 				}
 			}
@@ -1508,26 +1509,26 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 
 		if (psecuritypriv->wpa_psk == 0) {
 			DBG_8723A("STA " MAC_FMT ": WPA/RSN IE in association "
-			"request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
+			"request, but AP don't support WPA/RSN\n",
+				  MAC_ARG(pstat->hwaddr));
 
 			status = WLAN_STATUS_INVALID_IE;
 
 			goto OnAssocReq23aFail;
 		}
 
-		if (elems.wps_ie) {
-			DBG_8723A("STA included WPS IE in "
-				   "(Re)Association Request - WPS is "
-				   "used\n");
+		if (wps_ie) {
+			DBG_8723A("STA included WPS IE in (Re)Association "
+				  "Request - WPS is used\n");
 			pstat->flags |= WLAN_STA_WPS;
 			copy_len = 0;
 		} else {
-			copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
+			copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
+				sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
 		}
 
-		if (copy_len>0)
-			memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
-
+		if (copy_len > 0)
+			memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
 	}
 
 	/*  check if there is WMM IE & support WWM-PS */
@@ -1539,45 +1540,45 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	pstat->uapsd_vi = 0;
 	pstat->uapsd_be = 0;
 	pstat->uapsd_bk = 0;
-	if (pmlmepriv->qospriv.qos_option)
-	{
-		p = pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset; ie_len = 0;
-		for (;;)
-		{
-			p = rtw_get_ie23a(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
-			if (p != NULL) {
-				if (!memcmp(p+2, WMM_IE, 6)) {
-
+	if (pmlmepriv->qospriv.qos_option) {
+		const u8 *end = pos + left;
+		p = pos;
+
+		for (;;) {
+			left = end - p;
+			p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p, left);
+			if (p) {
+				if (!memcmp(p + 2, WMM_IE, 6)) {
 					pstat->flags |= WLAN_STA_WME;
 
 					pstat->qos_option = 1;
-					pstat->qos_info = *(p+8);
+					pstat->qos_info = *(p + 8);
 
-					pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
+					pstat->max_sp_len =
+						(pstat->qos_info >> 5) & 0x3;
 
-					if ((pstat->qos_info&0xf) != 0xf)
+					if ((pstat->qos_info & 0xf) != 0xf)
 						pstat->has_legacy_ac = true;
 					else
 						pstat->has_legacy_ac = false;
 
-					if (pstat->qos_info&0xf)
-					{
-						if (pstat->qos_info&BIT(0))
+					if (pstat->qos_info & 0xf) {
+						if (pstat->qos_info & BIT(0))
 							pstat->uapsd_vo = BIT(0)|BIT(1);
 						else
 							pstat->uapsd_vo = 0;
 
-						if (pstat->qos_info&BIT(1))
+						if (pstat->qos_info & BIT(1))
 							pstat->uapsd_vi = BIT(0)|BIT(1);
 						else
 							pstat->uapsd_vi = 0;
 
-						if (pstat->qos_info&BIT(2))
+						if (pstat->qos_info & BIT(2))
 							pstat->uapsd_bk = BIT(0)|BIT(1);
 						else
 							pstat->uapsd_bk = 0;
 
-						if (pstat->qos_info&BIT(3))
+						if (pstat->qos_info & BIT(3))
 							pstat->uapsd_be = BIT(0)|BIT(1);
 						else
 							pstat->uapsd_be = 0;
@@ -1586,45 +1587,42 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 
 					break;
 				}
-			}
-			else {
+			} else {
 				break;
 			}
-			p = p + ie_len + 2;
+			p = p + p[1] + 2;
 		}
 	}
 
 	/* save HT capabilities in the sta object */
 	memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
-	if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap))
-	{
+	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left);
+
+	if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) {
 		pstat->flags |= WLAN_STA_HT;
 
 		pstat->flags |= WLAN_STA_WME;
 
-		memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
-
+		memcpy(&pstat->htpriv.ht_cap, p + 2,
+		       sizeof(struct ieee80211_ht_cap));
 	} else
 		pstat->flags &= ~WLAN_STA_HT;
 
-	if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT))
-	{
+	if (pmlmepriv->htpriv.ht_option == false && pstat->flags & WLAN_STA_HT){
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 		goto OnAssocReq23aFail;
 	}
 
-	if ((pstat->flags & WLAN_STA_HT) &&
-		    ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
-		      (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP)))
-	{
-		DBG_8723A("HT: " MAC_FMT " tried to "
-				   "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
+	if (pstat->flags & WLAN_STA_HT &&
+	    (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
+	     pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
+		DBG_8723A("HT: " MAC_FMT " tried to use TKIP with HT "
+			  "association\n", MAC_ARG(pstat->hwaddr));
 
 		/* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
 		/* goto OnAssocReq23aFail; */
 	}
 
-       /*  */
 	pstat->flags |= WLAN_STA_NONERP;
 	for (i = 0; i < pstat->bssratelen; i++) {
 		if ((pstat->bssrateset[i] & 0x7f) > 22) {
@@ -1641,39 +1639,6 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	if (status != WLAN_STATUS_SUCCESS)
 		goto OnAssocReq23aFail;
 
-#ifdef CONFIG_8723AU_P2P
-	pstat->is_p2p_device = false;
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-	{
-		if ((p2pie = rtw_get_p2p_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset, NULL, &p2pielen)))
-		{
-			pstat->is_p2p_device = true;
-			if ((p2p_status_code = (u8)process_assoc_req_p2p_ie23a(pwdinfo, pframe, pkt_len, pstat))>0)
-			{
-				pstat->p2p_status_code = p2p_status_code;
-				status = WLAN_STATUS_CAPS_UNSUPPORTED;
-				goto OnAssocReq23aFail;
-			}
-		}
-#ifdef CONFIG_8723AU_P2P
-		if (rtw_get_wfd_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset, wfd_ie, &wfd_ielen))
-		{
-			u8	attr_content[ 10 ] = { 0x00 };
-			u32	attr_contentlen = 0;
-
-			DBG_8723A("[%s] WFD IE Found!!\n", __func__);
-			rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
-			if (attr_contentlen)
-			{
-				pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
-				DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
-			}
-		}
-#endif
-	}
-	pstat->p2p_status_code = p2p_status_code;
-#endif /* CONFIG_8723AU_P2P */
-
 	/* TODO: identify_proprietary_vendor_ie(); */
 	/*  Realtek proprietary IE */
 	/*  identify if this is Broadcom sta */
@@ -1699,14 +1664,13 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 			status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
 
 			goto OnAssocReq23aFail;
-
 		} else {
 			pstapriv->sta_aid[pstat->aid - 1] = pstat;
 			DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
 		}
 	}
 
-	pstat->state &= (~WIFI_FW_ASSOC_STATE);
+	pstat->state &= ~WIFI_FW_ASSOC_STATE;
 	pstat->state |= WIFI_FW_ASSOC_SUCCESS;
 
 	spin_lock_bh(&pstapriv->auth_list_lock);
@@ -1725,18 +1689,20 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	spin_unlock_bh(&pstapriv->asoc_list_lock);
 
 	/*  now the station is qualified to join our BSS... */
-	if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) &&
-	    (WLAN_STATUS_SUCCESS == status)) {
+	if (pstat && pstat->state & WIFI_FW_ASSOC_SUCCESS &&
+	    status == WLAN_STATUS_SUCCESS) {
 #ifdef CONFIG_8723AU_AP_MODE
 		/* 1 bss_cap_update & sta_info_update23a */
 		bss_cap_update_on_sta_join23a(padapter, pstat);
 		sta_info_update23a(padapter, pstat);
 
 		/* issue assoc rsp before notify station join event. */
-		if (ieee80211_is_assoc_req(frame_control))
-			issue_asocrsp23a(padapter, status, pstat, WIFI_ASSOCRSP);
+		if (ieee80211_is_assoc_req(mgmt->frame_control))
+			issue_asocrsp23a(padapter, status, pstat,
+					 WIFI_ASSOCRSP);
 		else
-			issue_asocrsp23a(padapter, status, pstat, WIFI_REASSOCRSP);
+			issue_asocrsp23a(padapter, status, pstat,
+					 WIFI_REASSOCRSP);
 
 		/* 2 - report to upper layer */
 		DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
@@ -1752,16 +1718,15 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
 asoc_class2_error:
 
 #ifdef CONFIG_8723AU_AP_MODE
-	issue_deauth23a(padapter, hdr->addr2, status);
+	issue_deauth23a(padapter, mgmt->sa, status);
 #endif
-
 	return _FAIL;
 
 OnAssocReq23aFail:
 
 #ifdef CONFIG_8723AU_AP_MODE
 	pstat->aid = 0;
-	if (ieee80211_is_assoc_req(frame_control))
+	if (ieee80211_is_assoc_req(mgmt->frame_control))
 		issue_asocrsp23a(padapter, status, pstat, WIFI_ASSOCRSP);
 	else
 		issue_asocrsp23a(padapter, status, pstat, WIFI_REASSOCRSP);
@@ -1772,25 +1737,24 @@ OnAssocReq23aFail:
 	return _FAIL;
 }
 
-unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+static int
+OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
-	uint i;
-	int res;
-	unsigned short	status;
 	struct ndis_802_11_var_ies *pIE;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
+	int res, i;
+	unsigned short status;
 	u8 *pframe = skb->data;
-	uint pkt_len = skb->len;
+	int pkt_len = skb->len;
 
 	DBG_8723A("%s\n", __func__);
 
 	/* check A1 matches or not */
-	if (!ether_addr_equal(myid(&padapter->eeprompriv),
-			      ieee80211_get_DA(hdr)))
+	if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
 		return _SUCCESS;
 
 	if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
@@ -1802,8 +1766,8 @@ unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	del_timer_sync(&pmlmeext->link_timer);
 
 	/* status */
-	if ((status = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr) + 2))) > 0)
-	{
+	status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
+	if (status > 0)	{
 		DBG_8723A("assoc reject, status code: %d\n", status);
 		pmlmeinfo->state = WIFI_FW_NULL_STATE;
 		res = -4;
@@ -1811,42 +1775,37 @@ unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *prec
 	}
 
 	/* get capabilities */
-	pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)));
+	pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
 
 	/* set slot time */
 	pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
 
 	/* AID */
-	res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr) + 4))&0x3fff);
+	res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
 
 	/* following are moved to join event callback function */
 	/* to handle HT, WMM, rate adaptive, update MAC reg */
 	/* for not to handle the synchronous IO in the tasklet */
-	for (i = (6 + sizeof(struct ieee80211_hdr_3addr)); i < pkt_len;) {
+	for (i = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+	     i < pkt_len;) {
 		pIE = (struct ndis_802_11_var_ies *)(pframe + i);
 
 		switch (pIE->ElementID)
 		{
-		case _VENDOR_SPECIFIC_IE_:
+		case WLAN_EID_VENDOR_SPECIFIC:
 			if (!memcmp(pIE->data, WMM_PARA_OUI23A, 6))/* WMM */
-					WMM_param_handler23a(padapter, pIE);
-#if defined(CONFIG_8723AU_P2P)
-			else if (!memcmp(pIE->data, WFD_OUI23A, 4)) { /* WFD */
-				DBG_8723A("[%s] Found WFD IE\n", __func__);
-				WFD_info_handler(padapter, pIE);
-			}
-#endif
+				WMM_param_handler23a(padapter, pIE);
 			break;
 
-		case _HT_CAPABILITY_IE_:	/* HT caps */
+		case WLAN_EID_HT_CAPABILITY:	/* HT caps */
 			HT_caps_handler23a(padapter, pIE);
 			break;
 
-		case _HT_EXTRA_INFO_IE_:	/* HT info */
+		case WLAN_EID_HT_OPERATION:	/* HT info */
 			HT_info_handler23a(padapter, pIE);
 			break;
 
-		case _ERPINFO_IE_:
+		case WLAN_EID_ERP_INFO:
 			ERP_IE_handler23a(padapter, pIE);
 
 		default:
@@ -1856,7 +1815,7 @@ unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *prec
 		i += (pIE->Length + 2);
 	}
 
-	pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
+	pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
 	pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
 
 	/* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
@@ -1879,32 +1838,21 @@ report_assoc_result:
 	return _SUCCESS;
 }
 
-unsigned int OnDeAuth23a(struct rtw_adapter *padapter,
-			 struct recv_frame *precv_frame)
+static int
+OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
-	unsigned short	reason;
+	unsigned short reason;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
 
-	/* check A3 */
-	if (!ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network)))
+	if (!ether_addr_equal(mgmt->bssid,
+			      get_my_bssid23a(&pmlmeinfo->network)))
 		return _SUCCESS;
 
-#ifdef CONFIG_8723AU_P2P
-	if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
-		mod_timer(&pwdinfo->reset_ch_sitesurvey,
-			  jiffies + msecs_to_jiffies(10));
-	}
-#endif /* CONFIG_8723AU_P2P */
-
-	reason = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)));
+	reason = le16_to_cpu(mgmt->u.deauth.reason_code);
 
 	DBG_8723A("%s Reason code(%d)\n", __func__, reason);
 
@@ -1914,9 +1862,9 @@ unsigned int OnDeAuth23a(struct rtw_adapter *padapter,
 		struct sta_priv *pstapriv = &padapter->stapriv;
 
 		DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
-				"sta:%pM\n", reason, hdr->addr2);
+				"sta:%pM\n", reason, mgmt->sa);
 
-		psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
+		psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
 		if (psta) {
 			u8 updated = 0;
 
@@ -1933,46 +1881,34 @@ unsigned int OnDeAuth23a(struct rtw_adapter *padapter,
 		}
 
 		return _SUCCESS;
-	}
-	else
+	} else
 #endif
 	{
 		DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
-				"sta:%pM\n", reason, hdr->addr3);
+				"sta:%pM\n", reason, mgmt->bssid);
 
-		receive_disconnect23a(padapter, hdr->addr3, reason);
+		receive_disconnect23a(padapter, mgmt->bssid, reason);
 	}
 	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+
 	return _SUCCESS;
 }
 
-unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+static int
+OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	unsigned short	reason;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
 
-	/* check A3 */
-	if (!ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network)))
+	if (!ether_addr_equal(mgmt->bssid,
+			      get_my_bssid23a(&pmlmeinfo->network)))
 		return _SUCCESS;
 
-#ifdef CONFIG_8723AU_P2P
-	if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
-	{
-		mod_timer(&pwdinfo->reset_ch_sitesurvey,
-			  jiffies + msecs_to_jiffies(10));
-	}
-#endif /* CONFIG_8723AU_P2P */
-
-	reason = le16_to_cpu(*(unsigned short *)
-			     (pframe + sizeof(struct ieee80211_hdr_3addr)));
+	reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
 
         DBG_8723A("%s Reason code(%d)\n", __func__, reason);
 
@@ -1982,9 +1918,9 @@ unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *prec
 		struct sta_priv *pstapriv = &padapter->stapriv;
 
 		DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
-				" sta:%pM\n", reason, hdr->addr2);
+				" sta:%pM\n", reason, mgmt->sa);
 
-		psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
+		psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
 		if (psta) {
 			u8 updated = 0;
 
@@ -1993,7 +1929,7 @@ unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *prec
 				list_del_init(&psta->asoc_list);
 				pstapriv->asoc_list_cnt--;
 				updated = ap_free_sta23a(padapter, psta,
-						      false, reason);
+							 false, reason);
 			}
 			spin_unlock_bh(&pstapriv->asoc_list_lock);
 
@@ -2001,57 +1937,59 @@ unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *prec
 		}
 
 		return _SUCCESS;
-	}
-	else
+	} else
 #endif
 	{
 		DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
-				"code(%d) sta:%pM\n", reason, hdr->addr3);
+				"code(%d) sta:%pM\n", reason, mgmt->bssid);
 
-		receive_disconnect23a(padapter, hdr->addr3, reason);
+		receive_disconnect23a(padapter, mgmt->bssid, reason);
 	}
 	pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
 	return _SUCCESS;
 }
 
-unsigned int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+static int
+OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	DBG_8723A("%s\n", __func__);
 	return _SUCCESS;
 }
 
-unsigned int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+static int
+on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _FAIL;
 }
 
-unsigned int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+static int
+OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
 
-unsigned int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+static int
+OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
 
-unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+static int OnAction23a_back23a(struct rtw_adapter *padapter,
+			       struct recv_frame *precv_frame)
 {
 	u8 *addr;
 	struct sta_info *psta = NULL;
 	struct recv_reorder_ctrl *preorder_ctrl;
-	unsigned char		*frame_body;
-	unsigned char		category, action;
-	unsigned short	tid, status, reason_code = 0;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	unsigned char category, action;
+	unsigned short tid, status, capab, params, reason_code = 0;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
 	struct sta_priv *pstapriv = &padapter->stapriv;
 
 	/* check RA matches or not */
-	if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
+	if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
 		return _SUCCESS;
 
 	DBG_8723A("%s\n", __func__);
@@ -2060,24 +1998,24 @@ unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame
 		if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
 			return _SUCCESS;
 
-	addr = hdr->addr2;
+	addr = mgmt->sa;
 	psta = rtw_get_stainfo23a(pstapriv, addr);
 
 	if (!psta)
 		return _SUCCESS;
 
-	frame_body = (unsigned char *)
-		(pframe + sizeof(struct ieee80211_hdr_3addr));
-
-	category = frame_body[0];
+	category = mgmt->u.action.category;
 	if (category == WLAN_CATEGORY_BACK) { /*  representing Block Ack */
 		if (!pmlmeinfo->HT_enable)
 			return _SUCCESS;
-		action = frame_body[1];
+		/* action_code is located in the same place for all
+		   action events, so pick any */
+		action = mgmt->u.action.u.wme_action.action_code;
 		DBG_8723A("%s, action =%d\n", __func__, action);
 		switch (action) {
 		case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
-			memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2],
+			memcpy(&pmlmeinfo->ADDBA_req,
+			       &mgmt->u.action.u.addba_req.dialog_token,
 			       sizeof(struct ADDBA_request));
 			process_addba_req23a(padapter,
 					     (u8 *)&pmlmeinfo->ADDBA_req, addr);
@@ -2091,8 +2029,11 @@ unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame
 			}
 			break;
 		case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
-			status = get_unaligned_le16(&frame_body[3]);
-			tid = ((frame_body[5] >> 2) & 0x7);
+			status = get_unaligned_le16(
+				&mgmt->u.action.u.addba_resp.status);
+			capab = get_unaligned_le16(
+				&mgmt->u.action.u.addba_resp.capab);
+			tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
 			if (status == 0) {	/* successful */
 				DBG_8723A("agg_enable for TID =%d\n", tid);
 				psta->htpriv.agg_enable_bitmap |= 1 << tid;
@@ -2103,22 +2044,21 @@ unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame
 			break;
 
 		case WLAN_ACTION_DELBA: /* DELBA */
-			if ((frame_body[3] & BIT(3)) == 0) {
-				psta->htpriv.agg_enable_bitmap &=
-					~(1 << ((frame_body[3] >> 4) & 0xf));
-				psta->htpriv.candidate_tid_bitmap &=
-					~(1 << ((frame_body[3] >> 4) & 0xf));
-
-				/* reason_code = frame_body[4] | (frame_body[5] << 8); */
-				reason_code = get_unaligned_le16(&frame_body[4]);
-			} else if ((frame_body[3] & BIT(3)) == BIT(3)) {
-				tid = (frame_body[3] >> 4) & 0x0F;
+			params = get_unaligned_le16(
+				&mgmt->u.action.u.delba.params);
+			tid = params >> 12;
 
-				preorder_ctrl =  &psta->recvreorder_ctrl[tid];
+			if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
+				preorder_ctrl = &psta->recvreorder_ctrl[tid];
 				preorder_ctrl->enable = false;
 				preorder_ctrl->indicate_seq = 0xffff;
+			} else {
+				psta->htpriv.agg_enable_bitmap &= ~(1 << tid);
+				psta->htpriv.candidate_tid_bitmap &=
+					~(1 << tid);
 			}
-
+			reason_code = get_unaligned_le16(
+				&mgmt->u.action.u.delba.reason_code);
 			DBG_8723A("%s(): DELBA: %x(%x)\n", __func__,
 				  pmlmeinfo->agg_enable_bitmap, reason_code);
 			/* todo: how to notify the host while receiving
@@ -2131,2930 +2071,166 @@ unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame
 	return _SUCCESS;
 }
 
-#ifdef CONFIG_8723AU_P2P
-
-static int get_reg_classes_full_count(struct p2p_channels channel_list) {
-	int cnt = 0;
-	int i;
-
-	for (i = 0; i < channel_list.reg_classes; i++)
-		cnt += channel_list.reg_class[i].channels;
-
-	return cnt;
-}
-
-void issue_p2p_GO_request23a(struct rtw_adapter *padapter, u8* raddr)
+static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
 {
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8			action = P2P_PUB_ACTION_ACTION;
-	u32			p2poui = cpu_to_be32(P2POUI);
-	u8			oui_subtype = P2P_GO_NEGO_REQ;
-	u8			wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
-	u8			wpsielen = 0, p2pielen = 0;
-	u16			len_channellist_attr = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32					wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		return;
-
-	DBG_8723A("[%s] In\n", __func__);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	ether_addr_copy(pwlanhdr->addr1, raddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pwdinfo->negotiation_dialog_token = 1;	/*Initialize the dialog value*/
-	pframe = rtw_set_fixed_ie23a(pframe, 1,
-				     &pwdinfo->negotiation_dialog_token,
-				     &pattrib->pktlen);
-
-	/*	WPS Section */
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(u32*) (wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	/*	Device Password ID */
-	/*	Type: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-
-	if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
-	{
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
-	}
-	else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
-	{
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
-	}
-	else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
-	{
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
-	}
-
-	wpsielen += 2;
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20110306 */
-	/*	According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. Group Owner Intent */
-	/*	3. Configuration Timeout */
-	/*	4. Listen Channel */
-	/*	5. Extended Listen Timing */
-	/*	6. Intended P2P Interface Address */
-	/*	7. Channel List */
-	/*	8. P2P Device Info */
-	/*	9. Operating Channel */
-
-	/*	P2P Capability */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported)
-	{
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
-	}
-	else
-	{
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
-	}
-
-	/*	Group Owner Intent */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Todo the tie breaker bit. */
-	p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;	/*	2 seconds needed to be the P2P Client */
-
-	/*	Listen Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
-
-	/*	Channel Number */
-	p2pie[p2pielen++] = pwdinfo->listen_channel;	/*	listening channel number */
-
-	/*	Extended Listen Timing ATTR */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Availability Period */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-	p2pielen += 2;
-
-	/*	Availability Interval */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-	p2pielen += 2;
-
-	/*	Intended P2P Interface Address */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-	/*  Length: */
-	/*  Country String(3) */
-	/*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
-	/*  + number of channels in all classes */
-	len_channellist_attr = 3
-	   + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
-	   + get_reg_classes_full_count(pmlmeext->channel_list);
-
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Channel Entry List */
-
-	{
-		int i, j;
-		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+	struct rtw_adapter *adapter = recv_frame->adapter;
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	struct sk_buff *skb = recv_frame->pkt;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 seq_ctrl;
 
-			/*	Number of Channels */
-			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+	seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
+		(recv_frame->attrib.frag_num & 0xf);
 
-			/*	Channel List */
-			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
-				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+	if (ieee80211_has_retry(hdr->frame_control)) {
+		if (token >= 0) {
+			if ((seq_ctrl == mlmeext->action_public_rxseq) &&
+			    (token == mlmeext->action_public_dialog_token)) {
+				DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
+					  "rxseq = 0x%x, token:%d\n",
+					  FUNC_ADPT_ARG(adapter), seq_ctrl,
+					  mlmeext->action_public_rxseq, token);
+				return _FAIL;
+			}
+		} else {
+			if (seq_ctrl == mlmeext->action_public_rxseq) {
+				DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
+					  "rxseq = 0x%x\n",
+					  FUNC_ADPT_ARG(adapter), seq_ctrl,
+					  mlmeext->action_public_rxseq);
+				return _FAIL;
 			}
 		}
 	}
 
-	/*	Device Info */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
-
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	*(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
+	mlmeext->action_public_rxseq = seq_ctrl;
 
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
+	if (token >= 0)
+		mlmeext->action_public_dialog_token = token;
 
-	/*	Device Name */
-	/*	Type: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
+	return _SUCCESS;
+}
 
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
-	p2pielen += 2;
+static unsigned int on_action_public23a_p2p(struct recv_frame *precv_frame)
+{
+	struct sk_buff *skb = precv_frame->pkt;
+	u8 *pframe = skb->data;
+	u8 *frame_body;
+	u8 dialogToken = 0;
 
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name,
-	       pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
+	frame_body = (unsigned char *)
+		(pframe + sizeof(struct ieee80211_hdr_3addr));
 
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
+	dialogToken = frame_body[7];
 
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
+	if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
+		return _FAIL;
 
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
+	return _SUCCESS;
+}
 
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
+static unsigned int on_action_public23a_vendor(struct recv_frame *precv_frame)
+{
+	unsigned int ret = _FAIL;
+	struct sk_buff *skb = precv_frame->pkt;
+	u8 *pframe = skb->data;
+	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
 
-	/*	Operating Class */
-	if (pwdinfo->operating_channel <= 14)
-	{
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x51;
-	}
-	else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48))
-	{
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x73;
-	}
-	else
-	{
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x7c;
+	if (!memcmp(frame_body + 2, P2P_OUI23A, 4)) {
+		ret = on_action_public23a_p2p(precv_frame);
 	}
 
-	/*	Channel Number */
-	p2pie[p2pielen++] = pwdinfo->operating_channel;	/*	operating channel number */
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
+	return ret;
 }
 
-static void issue_p2p_GO_response(struct rtw_adapter *padapter, u8* raddr, u8* frame_body, uint len, u8 result)
+static unsigned int
+on_action_public23a_default(struct recv_frame *precv_frame, u8 action)
 {
+	unsigned int ret = _FAIL;
+	struct sk_buff *skb = precv_frame->pkt;
+	u8 *pframe = skb->data;
+	uint frame_len = skb->len;
+	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
+	u8 token;
+	struct rtw_adapter *adapter = precv_frame->adapter;
+	int cnt = 0;
+	char msg[64];
 
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	u32 p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_GO_NEGO_RESP;
-	u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
-	u8 p2pielen = 0;
-	uint wpsielen = 0;
-	u16 wps_devicepassword_id = 0x0000;
-	uint wps_devicepassword_id_len = 0;
-	u16 len_channellist_attr = 0;
-	int i, j;
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
+	token = frame_body[2];
 
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		return;
+	if (rtw_action_public_decache(precv_frame, token) == _FAIL)
+		goto exit;
 
-	DBG_8723A("[%s] In, result = %d\n", __func__,  result);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
+	cnt += sprintf((msg+cnt), "%s(token:%u)",
+		       action_public_str23a(action), token);
+	rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
 
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+	ret = _SUCCESS;
 
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
+exit:
+	return ret;
+}
 
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
+static int on_action_public23a(struct rtw_adapter *padapter,
+			       struct recv_frame *precv_frame)
+{
+	unsigned int ret = _FAIL;
+	struct sk_buff *skb = precv_frame->pkt;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u8 *pframe = skb->data;
+	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
+	u8 category, action;
 
-	ether_addr_copy(pwlanhdr->addr1, raddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
+	/* check RA matches or not */
+	if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
+		goto exit;
 
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	/*	The Dialog Token of provisioning discovery request frame. */
-	pwdinfo->negotiation_dialog_token = frame_body[7];
-	pframe = rtw_set_fixed_ie23a(pframe, 1,
-				     &pwdinfo->negotiation_dialog_token,
-				     &pattrib->pktlen);
-
-	/*	Commented by Albert 20110328 */
-	/*	Try to get the device password ID from the WPS IE of group
-		negotiation request frame */
-	/*	WiFi Direct test plan 5.1.15 */
-	rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
-			  len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
-	rtw_get_wps_attr_content23a(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID,
-				    (u8 *)&wps_devicepassword_id,
-				    &wps_devicepassword_id_len);
-	wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
-
-	memset(wpsie, 0x00, 255);
-	wpsielen = 0;
-
-	/*	WPS Section */
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(u32*) (wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	/*	Device Password ID */
-	/*	Type: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-	if (wps_devicepassword_id == WPS_DPID_USER_SPEC) {
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
-	} else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
-	} else {
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
-	}
-	wpsielen += 2;
-
-	/*	Commented by Kurt 20120113 */
-	/*	If some device wants to do p2p handshake without sending prov_disc_req */
-	/*	We have to get peer_req_cm from here. */
-	if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
-		if (wps_devicepassword_id == WPS_DPID_USER_SPEC) {
-			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
-		} else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {
-			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
-		} else {
-			memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
-		}
-	}
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
-			       (unsigned char *) wpsie, &pattrib->pktlen);
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20100908 */
-	/*	According to the P2P Specification, the group negoitation
-		response frame should contain 9 P2P attributes */
-	/*	1. Status */
-	/*	2. P2P Capability */
-	/*	3. Group Owner Intent */
-	/*	4. Configuration Timeout */
-	/*	5. Operating Channel */
-	/*	6. Intended P2P Interface Address */
-	/*	7. Channel List */
-	/*	8. Device Info */
-	/*	9. Group ID	(Only GO) */
-
-	/*	ToDo: */
-
-	/*	P2P Status */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_STATUS;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = result;
-
-	/*	P2P Capability */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-		/*	Commented by Albert 2011/03/08 */
-		/*	According to the P2P specification */
-		/*	if the sending device will be client, the P2P
-			Capability should be reserved of group negotation
-			response frame */
-		p2pie[p2pielen++] = 0;
-	} else {
-		/*	Be group owner or meet the error case */
-		p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-	}
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported) {
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN |
-			P2P_GRPCAP_PERSISTENT_GROUP;
-	} else {
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
-	}
-
-	/*	Group Owner Intent */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	if (pwdinfo->peer_intent & 0x01) {
-		/*	Peer's tie breaker bit is 1, our tie breaker
-			bit should be 0 */
-		p2pie[p2pielen++] = (pwdinfo->intent << 1);
-	} else {
-		/* Peer's tie breaker bit is 0, our tie breaker bit
-		   should be 1 */
-		p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
-	}
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;
-	/*	2 seconds needed to be the P2P Client */
-	p2pie[p2pielen++] = 200;
-
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	if (pwdinfo->operating_channel <= 14) {
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x51;
-	} else if ((pwdinfo->operating_channel >= 36) &&
-		   (pwdinfo->operating_channel <= 48)) {
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x73;
-	} else {
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x7c;
-	}
-
-	/*	Channel Number */
-	/*	operating channel number */
-	p2pie[p2pielen++] = pwdinfo->operating_channel;
-
-	/*	Intended P2P Interface Address */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-	/*  Country String(3) */
-	/*  + (Operating Class (1) + Number of Channels(1)) *
-	    Operation Classes (?) */
-	/*  + number of channels in all classes */
-	len_channellist_attr = 3 +
-		(1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
-		get_reg_classes_full_count(pmlmeext->channel_list);
-
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Channel Entry List */
-
-	for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-		/*	Operating Class */
-		p2pie[p2pielen++] =
-			pmlmeext->channel_list.reg_class[j].reg_class;
-
-		/*	Number of Channels */
-		p2pie[p2pielen++] =
-			pmlmeext->channel_list.reg_class[j].channels;
-
-		/*	Channel List */
-		for (i = 0;
-		     i < pmlmeext->channel_list.reg_class[j].channels; i++) {
-			p2pie[p2pielen++] =
-				pmlmeext->channel_list.reg_class[j].channel[i];
-		}
-	}
-
-	/*	Device Info */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) +
-		Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field
-		(2bytes) + WPS Device Name Len field (2bytes) */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
-
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	*(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name,
-	       pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-	{
-		/*	Group ID Attribute */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
-
-		/*	Length: */
-		*(u16*) (p2pie + p2pielen) =
-			cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	p2P Device Address */
-		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
-		p2pielen += ETH_ALEN;
-
-		/*	SSID */
-		memcpy(p2pie + p2pielen, pwdinfo->nego_ssid,
-		       pwdinfo->nego_ssidlen);
-		p2pielen += pwdinfo->nego_ssidlen;
-
-	}
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
-			       (unsigned char *) p2pie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
-}
-
-static void issue_p2p_GO_confirm(struct rtw_adapter *padapter, u8* raddr,
-				 u8 result)
-{
-
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	u32 p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_GO_NEGO_CONF;
-	u8 p2pie[ 255 ] = { 0x00 };
-	u8 p2pielen = 0;
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		return;
-
-	DBG_8723A("[%s] In\n", __func__);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	ether_addr_copy(pwlanhdr->addr1, raddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1,
-				     &pwdinfo->negotiation_dialog_token,
-				  &pattrib->pktlen);
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20110306 */
-	/*	According to the P2P Specification, the group negoitation
-		request frame should contain 5 P2P attributes */
-	/*	1. Status */
-	/*	2. P2P Capability */
-	/*	3. Operating Channel */
-	/*	4. Channel List */
-	/*	5. Group ID	(if this WiFi is GO) */
-
-	/*	P2P Status */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_STATUS;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = result;
-
-	/*	P2P Capability */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported) {
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN |
-			P2P_GRPCAP_PERSISTENT_GROUP;
-	} else {
-		p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
-	}
-
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
-		if (pwdinfo->peer_operating_ch <= 14) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x51;
-		} else if ((pwdinfo->peer_operating_ch >= 36) &&
-			 (pwdinfo->peer_operating_ch <= 48)) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x73;
-		} else {
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x7c;
-		}
-
-		p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
-	} else {
-		if (pwdinfo->operating_channel <= 14) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x51;
-		}
-		else if ((pwdinfo->operating_channel >= 36) &&
-			 (pwdinfo->operating_channel <= 48)) {
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x73;
-		} else {
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x7c;
-		}
-
-		/*	Channel Number */
-		/*	Use the listen channel as the operating channel */
-		p2pie[p2pielen++] = pwdinfo->operating_channel;
-	}
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) =
-		cpu_to_le16(pwdinfo->channel_list_attr_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr,
-	       pwdinfo->channel_list_attr_len);
-	p2pielen += pwdinfo->channel_list_attr_len;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-		/*	Group ID Attribute */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
-
-		/*	Length: */
-		*(u16*) (p2pie + p2pielen) =
-			cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	p2P Device Address */
-		memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
-		p2pielen += ETH_ALEN;
-
-		/*	SSID */
-		memcpy(p2pie + p2pielen, pwdinfo->nego_ssid,
-		       pwdinfo->nego_ssidlen);
-		p2pielen += pwdinfo->nego_ssidlen;
-	}
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
-			       (unsigned char *)p2pie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
-}
-
-void issue_p2p_invitation_request23a(struct rtw_adapter *padapter, u8* raddr)
-{
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	u32 p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_INVIT_REQ;
-	u8 p2pie[ 255 ] = { 0x00 };
-	u8 p2pielen = 0;
-	u8 dialogToken = 3;
-	u16 len_channellist_attr = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-	int i, j;
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	ether_addr_copy(pwlanhdr->addr1, raddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, raddr);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20101011 */
-	/*	According to the P2P Specification, the P2P Invitation
-		request frame should contain 7 P2P attributes */
-	/*	1. Configuration Timeout */
-	/*	2. Invitation Flags */
-	/*	3. Operating Channel	(Only GO) */
-	/*	4. P2P Group BSSID	(Should be included if I am the GO) */
-	/*	5. Channel List */
-	/*	6. P2P Group ID */
-	/*	7. P2P Device Info */
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;
-	/*	2 seconds needed to be the P2P Client */
-	p2pie[p2pielen++] = 200;
-
-	/*	Invitation Flags */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
-
-	/*	Operating Channel */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Operating Class */
-	if (pwdinfo->invitereq_info.operating_ch <= 14)
-		p2pie[p2pielen++] = 0x51;
-	else if ((pwdinfo->invitereq_info.operating_ch >= 36) &&
-		 (pwdinfo->invitereq_info.operating_ch <= 48))
-		p2pie[p2pielen++] = 0x73;
-	else
-		p2pie[p2pielen++] = 0x7c;
-
-	/*	Channel Number */
-	/*	operating channel number */
-	p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;
-
-	if (ether_addr_equal(myid(&padapter->eeprompriv),
-			     pwdinfo->invitereq_info.go_bssid)) {
-		/*	P2P Group BSSID */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
-
-		/*	Length: */
-		*(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	P2P Device Address for GO */
-		memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid,
-		       ETH_ALEN);
-		p2pielen += ETH_ALEN;
-	}
-
-	/*	Channel List */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-	/*	Length: */
-	/*  Country String(3) */
-	/*  + (Operating Class (1) + Number of Channels(1)) *
-	    Operation Classes (?) */
-	/*  + number of channels in all classes */
-	len_channellist_attr = 3 +
-		(1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
-		get_reg_classes_full_count(pmlmeext->channel_list);
-
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Country String */
-	p2pie[p2pielen++] = 'X';
-	p2pie[p2pielen++] = 'X';
-
-	/*	The third byte should be set to 0x04. */
-	/*	Described in the "Operating Channel Attribute" section. */
-	p2pie[p2pielen++] = 0x04;
-
-	/*	Channel Entry List */
-	for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-		/*	Operating Class */
-		p2pie[p2pielen++] =
-			pmlmeext->channel_list.reg_class[j].reg_class;
-
-		/*	Number of Channels */
-		p2pie[p2pielen++] =
-			pmlmeext->channel_list.reg_class[j].channels;
-
-		/*	Channel List */
-		for (i = 0;
-		     i < pmlmeext->channel_list.reg_class[j].channels; i++) {
-			p2pie[p2pielen++] =
-				pmlmeext->channel_list.reg_class[j].channel[i];
-		}
-	}
-
-	/*	P2P Group ID */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) =
-		cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address for GO */
-	memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	SSID */
-	memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid,
-	       pwdinfo->invitereq_info.ssidlen);
-	p2pielen += pwdinfo->invitereq_info.ssidlen;
-
-	/*	Device Info */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) +
-		Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field
-		(2bytes) + WPS Device Name Len field (2bytes) */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-	p2pielen += 2;
-
-	/*	OUI */
-	*(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[p2pielen++] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-	p2pielen += 2;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name,
-	       pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
-			       (unsigned char *) p2pie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
-}
-
-void issue_p2p_invitation_response23a(struct rtw_adapter *padapter, u8 *raddr,
-				      u8 dialogToken, u8 status_code)
-{
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	u32 p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_INVIT_RESP;
-	u8 p2pie[ 255 ] = { 0x00 };
-	u8 p2pielen = 0;
-	u16 len_channellist_attr = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-	int i, j;
-
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	ether_addr_copy(pwlanhdr->addr1, raddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, raddr);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	/*	P2P IE Section. */
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[p2pielen++] = 0x50;
-	p2pie[p2pielen++] = 0x6F;
-	p2pie[p2pielen++] = 0x9A;
-	p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20101005 */
-	/*	According to the P2P Specification, the P2P Invitation
-		response frame should contain 5 P2P attributes */
-	/*	1. Status */
-	/*	2. Configuration Timeout */
-	/*	3. Operating Channel	(Only GO) */
-	/*	4. P2P Group BSSID	(Only GO) */
-	/*	5. Channel List */
-
-	/*	P2P Status */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_STATUS;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
-	/*	Sent the event receiving the P2P Invitation Req frame
-		to DMP UI. */
-	/*	DMP had to compare the MAC address to find out the profile. */
-	/*	So, the WiFi driver will send the
-		P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
-	/*	If the UI found the corresponding profile, the WiFi driver
-		sends the P2P Invitation Req */
-	/*	to NB to rebuild the persistent group. */
-	p2pie[p2pielen++] = status_code;
-
-	/*	Configuration Timeout */
-	/*	Type: */
-	p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
-
-	/*	Length: */
-	*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	2 seconds needed to be the P2P GO */
-	p2pie[p2pielen++] = 200;
-	/*	2 seconds needed to be the P2P Client */
-	p2pie[p2pielen++] = 200;
-
-	if (status_code == P2P_STATUS_SUCCESS) {
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-			/* The P2P Invitation request frame asks this
-			   Wi-Fi device to be the P2P GO */
-			/* In this case, the P2P Invitation response
-			   frame should carry the two more P2P attributes. */
-			/* First one is operating channel attribute. */
-			/* Second one is P2P Group BSSID attribute. */
-
-			/* Operating Channel */
-			/* Type: */
-			p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-			/* Length: */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-			p2pielen += 2;
-
-			/* Value: */
-			/* Country String */
-			p2pie[p2pielen++] = 'X';
-			p2pie[p2pielen++] = 'X';
-
-			/* The third byte should be set to 0x04. */
-			/* Described in the "Operating Channel Attribute"
-			   section. */
-			p2pie[p2pielen++] = 0x04;
-
-			/* Operating Class */
-			/*	Copy from SD7 */
-			p2pie[p2pielen++] = 0x51;
-
-			/* Channel Number */
-			/*	operating channel number */
-			p2pie[p2pielen++] = pwdinfo->operating_channel;
-
-			/*	P2P Group BSSID */
-			/*	Type: */
-			p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
-
-			/*	Length: */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
-			p2pielen += 2;
-
-			/*	Value: */
-			/*	P2P Device Address for GO */
-			memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv),
-			       ETH_ALEN);
-			p2pielen += ETH_ALEN;
-		}
-
-		/*	Channel List */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
-
-		/*	Length: */
-		/*  Country String(3) */
-		/*  + (Operating Class (1) + Number of Channels(1)) *
-		    Operation Classes (?) */
-		/*  + number of channels in all classes */
-		len_channellist_attr = 3 +
-			(1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
-			get_reg_classes_full_count(pmlmeext->channel_list);
-
-		*(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Country String */
-		p2pie[p2pielen++] = 'X';
-		p2pie[p2pielen++] = 'X';
-
-		/* The third byte should be set to 0x04. */
-		/* Described in the "Operating Channel Attribute" section. */
-		p2pie[p2pielen++] = 0x04;
-
-		/*	Channel Entry List */
-		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
-			/*	Operating Class */
-			p2pie[p2pielen++] =
-				pmlmeext->channel_list.reg_class[j].reg_class;
-
-			/*	Number of Channels */
-			p2pie[p2pielen++] =
-				pmlmeext->channel_list.reg_class[j].channels;
-
-			/*	Channel List */
-			for (i = 0;
-			     i < pmlmeext->channel_list.reg_class[j].channels;
-			     i++) {
-				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
-			}
-		}
-	}
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
-			       (unsigned char *)p2pie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
-}
-
-void issue_p2p_provision_request23a(struct rtw_adapter *padapter, u8 *pssid,
-				    u8 ussidlen, u8 *pdev_raddr)
-{
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	u8 dialogToken = 1;
-	u32 p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_PROVISION_DISC_REQ;
-	u8 wpsie[100] = { 0x00 };
-	u8 wpsielen = 0;
-	u32 p2pielen = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		return;
-
-	DBG_8723A("[%s] In\n", __func__);
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	ether_addr_copy(pwlanhdr->addr1, pdev_raddr);
-	ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
-	ether_addr_copy(pwlanhdr->addr3, pdev_raddr);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	p2pielen = build_prov_disc_request_p2p_ie23a(pwdinfo, pframe, pssid,
-						     ussidlen, pdev_raddr);
-
-	pframe += p2pielen;
-	pattrib->pktlen += p2pielen;
-
-	wpsielen = 0;
-	/*	WPS OUI */
-	*(u32*) (wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*	WPS version */
-	/*	Type: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*	Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-	/*	Config Method */
-	/*	Type: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
-	wpsielen += 2;
-
-	/*	Length: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*	Value: */
-	*(u16*) (wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
-	wpsielen += 2;
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
-			       (unsigned char *) wpsie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
-}
-
-static u8 is_matched_in_profilelist(u8 *peermacaddr,
-				    struct profile_info *profileinfo)
-{
-	u8 i, match_result = 0;
-
-	DBG_8723A("[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
-		  peermacaddr[0], peermacaddr[1], peermacaddr[2],
-		  peermacaddr[3], peermacaddr[4], peermacaddr[5]);
-
-	for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
-	       DBG_8723A("[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X "
-			 "%.2X\n", __func__, profileinfo->peermac[0],
-			 profileinfo->peermac[1], profileinfo->peermac[2],
-			 profileinfo->peermac[3], profileinfo->peermac[4],
-			 profileinfo->peermac[5]);
-		if (ether_addr_equal(peermacaddr, profileinfo->peermac)) {
-			match_result = 1;
-			DBG_8723A("[%s] Match!\n", __func__);
-			break;
-		}
-	}
-
-	return match_result;
-}
-
-void issue_probersp23a_p2p23a(struct rtw_adapter *padapter, unsigned char *da)
-{
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
-	unsigned char *mac;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-	u16 beacon_interval = 100;
-	u16 capInfo = 0;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	u8 wpsie[255] = { 0x00 };
-	u32 wpsielen = 0, p2pielen = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-	struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
-		&padapter->cfg80211_wdinfo;
-	struct ieee80211_channel *ieee_ch =
-		&pcfg80211_wdinfo->remain_on_ch_channel;
-	u8 listen_channel =
-		(u8)ieee80211_frequency_to_channel(ieee_ch->center_freq);
-
-	/* DBG_8723A("%s\n", __func__); */
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-	{
-		return;
-	}
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	mac = myid(&padapter->eeprompriv);
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-	ether_addr_copy(pwlanhdr->addr1, da);
-	ether_addr_copy(pwlanhdr->addr2, mac);
-
-	/*	Use the device address for BSSID field. */
-	ether_addr_copy(pwlanhdr->addr3, mac);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(fctrl, WIFI_PROBERSP);
-
-	pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = pattrib->hdrlen;
-	pframe += pattrib->hdrlen;
-
-	/* timestamp will be inserted by hardware */
-	pframe += 8;
-	pattrib->pktlen += 8;
-
-	/*  beacon interval: 2 bytes */
-	memcpy(pframe, (unsigned char *) &beacon_interval, 2);
-	pframe += 2;
-	pattrib->pktlen += 2;
-
-	/*	capability info: 2 bytes */
-	/*	ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of
-		WiFi Direct Spec) */
-	capInfo |= cap_ShortPremble;
-	capInfo |= cap_ShortSlot;
-
-	memcpy(pframe, (unsigned char *) &capInfo, 2);
-	pframe += 2;
-	pattrib->pktlen += 2;
-
-	/*  SSID */
-	pframe = rtw_set_ie23a(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid,
-			       &pattrib->pktlen);
-
-	/*  supported rates... */
-	/*	Use the OFDM rate in the P2P probe response frame.
-		(6(B), 9(B), 12, 18, 24, 36, 48, 54) */
-	pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
-			       pwdinfo->support_rate, &pattrib->pktlen);
-
-	/*  DS parameter set */
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled &&
-	    listen_channel != 0) {
-		pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
-				       &listen_channel, &pattrib->pktlen);
-	} else {
-		pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
-				       &pwdinfo->listen_channel,
-				       &pattrib->pktlen);
-	}
-
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-		if (pmlmepriv->wps_probe_resp_ie &&
-		    pmlmepriv->p2p_probe_resp_ie) {
-			/* WPS IE */
-			memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
-			       pmlmepriv->wps_probe_resp_ie_len);
-			pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
-			pframe += pmlmepriv->wps_probe_resp_ie_len;
-
-			/* P2P IE */
-			memcpy(pframe, pmlmepriv->p2p_probe_resp_ie,
-			       pmlmepriv->p2p_probe_resp_ie_len);
-			pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
-			pframe += pmlmepriv->p2p_probe_resp_ie_len;
-		}
-	} else {
-
-		/*	Todo: WPS IE */
-		/*	Noted by Albert 20100907 */
-		/*	According to the WPS specification, all the WPS
-			attribute is presented by Big Endian. */
-
-		wpsielen = 0;
-		/*	WPS OUI */
-		*(u32*) (wpsie) = cpu_to_be32(WPSOUI);
-		wpsielen += 4;
-
-		/*	WPS version */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-		wpsielen += 2;
-
-		/*	Value: */
-		wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-		/*	WiFi Simple Config State */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-		wpsielen += 2;
-
-		/*	Value: */
-		wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;
-
-		/*	Response Type */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-		wpsielen += 2;
-
-		/*	Value: */
-		wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
-
-		/*	UUID-E */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0010);
-		wpsielen += 2;
-
-		/*	Value: */
-		memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
-		wpsielen += 0x10;
-
-		/*	Manufacturer */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0007);
-		wpsielen += 2;
-
-		/*	Value: */
-		memcpy(wpsie + wpsielen, "Realtek", 7);
-		wpsielen += 7;
-
-		/*	Model Name */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0006);
-		wpsielen += 2;
-
-		/*	Value: */
-		memcpy(wpsie + wpsielen, "8192CU", 6);
-		wpsielen += 6;
-
-		/*	Model Number */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-		wpsielen += 2;
-
-		/*	Value: */
-		wpsie[ wpsielen++ ] = 0x31;		/*	character 1 */
-
-		/*	Serial Number */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
-		wpsielen += 2;
-
-		/*	Value: */
-		memcpy(wpsie + wpsielen, "123456", ETH_ALEN);
-		wpsielen += ETH_ALEN;
-
-		/*	Primary Device Type */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0008);
-		wpsielen += 2;
-
-		/*	Value: */
-		/*	Category ID */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-		wpsielen += 2;
-
-		/*	OUI */
-		*(u32*) (wpsie + wpsielen) = cpu_to_be32(WPSOUI);
-		wpsielen += 4;
-
-		/*	Sub Category ID */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-		wpsielen += 2;
-
-		/*	Device Name */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(pwdinfo->device_name_len);
-		wpsielen += 2;
-
-		/*	Value: */
-		if (pwdinfo->device_name_len) {
-			memcpy(wpsie + wpsielen, pwdinfo->device_name,
-			       pwdinfo->device_name_len);
-			wpsielen += pwdinfo->device_name_len;
-		}
-
-		/*	Config Method */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
-		wpsielen += 2;
-
-		/*	Value: */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(pwdinfo->supported_wps_cm);
-		wpsielen += 2;
-
-		pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
-				       (unsigned char *)wpsie,
-				       &pattrib->pktlen);
-
-		p2pielen = build_probe_resp_p2p_ie23a(pwdinfo, pframe);
-		pframe += p2pielen;
-		pattrib->pktlen += p2pielen;
-	}
-
-#ifdef CONFIG_8723AU_P2P
-	if (pwdinfo->wfd_info->wfd_enable) {
-		wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
-		pframe += wfdielen;
-		pattrib->pktlen += wfdielen;
-	} else if (pmlmepriv->wfd_probe_resp_ie &&
-		 pmlmepriv->wfd_probe_resp_ie_len > 0) {
-		/* WFD IE */
-		memcpy(pframe, pmlmepriv->wfd_probe_resp_ie,
-		       pmlmepriv->wfd_probe_resp_ie_len);
-		pattrib->pktlen += pmlmepriv->wfd_probe_resp_ie_len;
-		pframe += pmlmepriv->wfd_probe_resp_ie_len;
-	}
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
-}
-
-static int _issue23a_probereq_p2p(struct rtw_adapter *padapter, u8 *da,
-				  int wait_ack)
-{
-	int ret = _FAIL;
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
-	unsigned char *mac;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
-	u8 wpsie[255] = {0x00}, p2pie[255] = {0x00};
-	u16 wpsielen = 0, p2pielen = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		goto exit;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	mac = myid(&padapter->eeprompriv);
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	if (da) {
-		ether_addr_copy(pwlanhdr->addr1, da);
-		ether_addr_copy(pwlanhdr->addr3, da);
-	} else {
-		if ((pwdinfo->p2p_info.scan_op_ch_only) ||
-		    (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
-			/*	This two flags will be set when this is
-				only the P2P client mode. */
-			ether_addr_copy(pwlanhdr->addr1,
-					pwdinfo->p2p_peer_interface_addr);
-			ether_addr_copy(pwlanhdr->addr3,
-					pwdinfo->p2p_peer_interface_addr);
-		} else {
-			/*	broadcast probe request frame */
-			ether_addr_copy(pwlanhdr->addr1, bc_addr);
-			ether_addr_copy(pwlanhdr->addr3, bc_addr);
-		}
-	}
-	ether_addr_copy(pwlanhdr->addr2, mac);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_PROBEREQ);
-
-	pframe += sizeof (struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
-		pframe = rtw_set_ie23a(pframe, _SSID_IE_,
-				    pwdinfo->tx_prov_disc_info.ssid.ssid_len,
-				    pwdinfo->tx_prov_disc_info.ssid.ssid,
-				    &pattrib->pktlen);
-	} else {
-		pframe = rtw_set_ie23a(pframe, _SSID_IE_,
-				       P2P_WILDCARD_SSID_LEN,
-				       pwdinfo->p2p_wildcard_ssid,
-				       &pattrib->pktlen);
-	}
-	/*	Use the OFDM rate in the P2P probe request frame.
-		(6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
-	pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
-			       pwdinfo->support_rate, &pattrib->pktlen);
-
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-		if (pmlmepriv->wps_probe_req_ie &&
-		    pmlmepriv->p2p_probe_req_ie) {
-			/* WPS IE */
-			memcpy(pframe, pmlmepriv->wps_probe_req_ie,
-			       pmlmepriv->wps_probe_req_ie_len);
-			pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
-			pframe += pmlmepriv->wps_probe_req_ie_len;
-
-			/* P2P IE */
-			memcpy(pframe, pmlmepriv->p2p_probe_req_ie,
-			       pmlmepriv->p2p_probe_req_ie_len);
-			pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
-			pframe += pmlmepriv->p2p_probe_req_ie_len;
-		}
-	} else {
-
-		/*	WPS IE */
-		/*	Noted by Albert 20110221 */
-		/*	According to the WPS specification, all the WPS
-			attribute is presented by Big Endian. */
-
-		wpsielen = 0;
-		/*	WPS OUI */
-		*(u32*) (wpsie) = cpu_to_be32(WPSOUI);
-		wpsielen += 4;
-
-		/*	WPS version */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
-		wpsielen += 2;
-
-		/*	Value: */
-		wpsie[wpsielen++] = WPS_VERSION_1;	/*	Version 1.0 */
-
-		if (pmlmepriv->wps_probe_req_ie == NULL) {
-			/*	UUID-E */
-			/*	Type: */
-			*(u16*) (wpsie + wpsielen) =
-				cpu_to_be16(WPS_ATTR_UUID_E);
-			wpsielen += 2;
-
-			/*	Length: */
-			*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0010);
-			wpsielen += 2;
-
-			/*	Value: */
-			memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv),
-			       ETH_ALEN);
-			wpsielen += 0x10;
-
-			/*	Config Method */
-			/*	Type: */
-			*(u16*) (wpsie + wpsielen) =
-				cpu_to_be16(WPS_ATTR_CONF_METHOD);
-			wpsielen += 2;
-
-			/*	Length: */
-			*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
-			wpsielen += 2;
-
-			/*	Value: */
-			*(u16*) (wpsie + wpsielen) =
-				cpu_to_be16(pwdinfo->supported_wps_cm);
-			wpsielen += 2;
-		}
-
-		/*	Device Name */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(pwdinfo->device_name_len);
-		wpsielen += 2;
-
-		/*	Value: */
-		memcpy(wpsie + wpsielen, pwdinfo->device_name,
-		       pwdinfo->device_name_len);
-		wpsielen += pwdinfo->device_name_len;
-
-		/*	Primary Device Type */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0008);
-		wpsielen += 2;
-
-		/*	Value: */
-		/*	Category ID */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
-		wpsielen += 2;
-
-		/*	OUI */
-		*(u32*) (wpsie + wpsielen) = cpu_to_be32(WPSOUI);
-		wpsielen += 4;
-
-		/*	Sub Category ID */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
-		wpsielen += 2;
-
-		/*	Device Password ID */
-		/*	Type: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
-		wpsielen += 2;
-
-		/*	Length: */
-		*(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
-		wpsielen += 2;
-
-		/*	Value: */
-		/*	Registrar-specified */
-		*(u16*) (wpsie + wpsielen) =
-			cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
-		wpsielen += 2;
-
-		pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
-				       (unsigned char *)wpsie,
-				       &pattrib->pktlen);
-
-		/*	P2P OUI */
-		p2pielen = 0;
-		p2pie[p2pielen++] = 0x50;
-		p2pie[p2pielen++] = 0x6F;
-		p2pie[p2pielen++] = 0x9A;
-		p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-		/*	Commented by Albert 20110221 */
-		/*	According to the P2P Specification, the probe request
-			frame should contain 5 P2P attributes */
-		/*	1. P2P Capability */
-		/*	2. P2P Device ID if this probe request wants to
-			find the specific P2P device */
-		/*	3. Listen Channel */
-		/*	4. Extended Listen Timing */
-		/*	5. Operating Channel if this WiFi is working as
-			the group owner now */
-
-		/*	P2P Capability */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-		/*	Length: */
-		*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Device Capability Bitmap, 1 byte */
-		p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-		/*	Group Capability Bitmap, 1 byte */
-		if (pwdinfo->persistent_supported)
-			p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP |
-				DMP_P2P_GRPCAP_SUPPORT;
-		else
-			p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
-
-		/*	Listen Channel */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
-
-		/*	Length: */
-		*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Country String */
-		p2pie[p2pielen++] = 'X';
-		p2pie[p2pielen++] = 'X';
-
-		/* The third byte should be set to 0x04. */
-		/* Described in the "Operating Channel Attribute" section. */
-		p2pie[p2pielen++] = 0x04;
-
-		/*	Operating Class */
-		p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
-
-		/*	Channel Number */
-		/*	listen channel */
-		p2pie[p2pielen++] = pwdinfo->listen_channel;
-
-		/*	Extended Listen Timing */
-		/*	Type: */
-		p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
-
-		/*	Length: */
-		*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
-		p2pielen += 2;
-
-		/*	Value: */
-		/*	Availability Period */
-		*(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-		p2pielen += 2;
-
-		/*	Availability Interval */
-		*(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-		p2pielen += 2;
-
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-			/* Operating Channel (if this WiFi is working as
-			   the group owner now) */
-			/* Type: */
-			p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
-
-			/*	Length: */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
-			p2pielen += 2;
-
-			/*	Value: */
-			/*	Country String */
-			p2pie[p2pielen++] = 'X';
-			p2pie[p2pielen++] = 'X';
-
-			/* The third byte should be set to 0x04. */
-			/* Described in the "Operating Channel Attribute"
-			   section. */
-			p2pie[p2pielen++] = 0x04;
-
-			/*	Operating Class */
-			p2pie[p2pielen++] = 0x51;	/*	Copy from SD7 */
-
-			/*	Channel Number */
-			/*	operating channel number */
-			p2pie[p2pielen++] = pwdinfo->operating_channel;
-		}
-
-		pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
-				       (unsigned char *)p2pie,
-				       &pattrib->pktlen);
-
-		if (pmlmepriv->wps_probe_req_ie) {
-			/* WPS IE */
-			memcpy(pframe, pmlmepriv->wps_probe_req_ie,
-			       pmlmepriv->wps_probe_req_ie_len);
-			pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
-			pframe += pmlmepriv->wps_probe_req_ie_len;
-		}
-	}
-
-#ifdef CONFIG_8723AU_P2P
-	if (pwdinfo->wfd_info->wfd_enable) {
-		wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
-		pframe += wfdielen;
-		pattrib->pktlen += wfdielen;
-	} else if (pmlmepriv->wfd_probe_req_ie &&
-		   pmlmepriv->wfd_probe_req_ie_len>0) {
-		/* WFD IE */
-		memcpy(pframe, pmlmepriv->wfd_probe_req_ie,
-		       pmlmepriv->wfd_probe_req_ie_len);
-		pattrib->pktlen += pmlmepriv->wfd_probe_req_ie_len;
-		pframe += pmlmepriv->wfd_probe_req_ie_len;
-	}
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-		 ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
-
-	if (wait_ack) {
-		ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
-	} else {
-		dump_mgntframe23a(padapter, pmgntframe);
-		ret = _SUCCESS;
-	}
-
-exit:
-	return ret;
-}
-
-inline void issue23a_probereq_p2p(struct rtw_adapter *adapter, u8 *da)
-{
-	_issue23a_probereq_p2p(adapter, da, false);
-}
-
-int issue23a_probereq_p2p_ex(struct rtw_adapter *adapter, u8 *da,
-			     int try_cnt, int wait_ms)
-{
-	int ret;
-	int i = 0;
-	unsigned long start = jiffies;
-
-	do {
-		ret = _issue23a_probereq_p2p(adapter, da,
-					     wait_ms > 0 ? true : false);
-
-		i++;
-
-		if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
-			break;
-
-		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
-			msleep(wait_ms);
-
-	} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-
-	if (ret != _FAIL) {
-		ret = _SUCCESS;
-		goto exit;
-	}
-
-	if (try_cnt && wait_ms) {
-		if (da)
-			DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
-				  "in %u ms\n", FUNC_ADPT_ARG(adapter),
-				  MAC_ARG(da), rtw_get_oper_ch23a(adapter),
-				  ret == _SUCCESS?", acked":"", i, try_cnt,
-				  jiffies_to_msecs(jiffies - start));
-		else
-			DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
-				  FUNC_ADPT_ARG(adapter),
-				  rtw_get_oper_ch23a(adapter),
-				  ret == _SUCCESS?", acked":"", i, try_cnt,
-				  jiffies_to_msecs(jiffies - start));
-	}
-exit:
-	return ret;
-}
-
-#endif /* CONFIG_8723AU_P2P */
-
-static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
-{
-	struct rtw_adapter *adapter = recv_frame->adapter;
-	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
-	struct sk_buff *skb = recv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u16 seq_ctrl;
-
-	seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
-		(recv_frame->attrib.frag_num & 0xf);
-
-	if (ieee80211_has_retry(hdr->frame_control)) {
-		if (token >= 0) {
-			if ((seq_ctrl == mlmeext->action_public_rxseq) &&
-			    (token == mlmeext->action_public_dialog_token)) {
-				DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
-					  "rxseq = 0x%x, token:%d\n",
-					  FUNC_ADPT_ARG(adapter), seq_ctrl,
-					  mlmeext->action_public_rxseq, token);
-				return _FAIL;
-			}
-		} else {
-			if (seq_ctrl == mlmeext->action_public_rxseq) {
-				DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
-					  "rxseq = 0x%x\n",
-					  FUNC_ADPT_ARG(adapter), seq_ctrl,
-					  mlmeext->action_public_rxseq);
-				return _FAIL;
-			}
-		}
-	}
-
-	mlmeext->action_public_rxseq = seq_ctrl;
-
-	if (token >= 0)
-		mlmeext->action_public_dialog_token = token;
-
-	return _SUCCESS;
-}
-
-static unsigned int on_action_public23a_p2p(struct recv_frame *precv_frame)
-{
-	struct sk_buff *skb = precv_frame->pkt;
-	u8 *pframe = skb->data;
-	u8 *frame_body;
-	u8 dialogToken = 0;
-#ifdef CONFIG_8723AU_P2P
-	struct rtw_adapter *padapter = precv_frame->adapter;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	uint len = skb->len;
-	u8 *p2p_ie;
-	u32	p2p_ielen;
-	struct	wifidirect_info	*pwdinfo = &padapter->wdinfo;
-	u8	result = P2P_STATUS_SUCCESS;
-#endif /* CONFIG_8723AU_P2P */
-
-	frame_body = (unsigned char *)
-		(pframe + sizeof(struct ieee80211_hdr_3addr));
-
-	dialogToken = frame_body[7];
-
-	if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
-		return _FAIL;
-
-#ifdef CONFIG_8723AU_P2P
-	del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-		rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len);
-	} else {
-		/*	Do nothing if the driver doesn't enable the P2P function. */
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
-			return _SUCCESS;
-
-		len -= sizeof(struct ieee80211_hdr_3addr);
-
-		switch (frame_body[ 6 ])/* OUI Subtype */
-		{
-			case P2P_GO_NEGO_REQ:
-				DBG_8723A("[%s] Got GO Nego Req Frame\n", __func__);
-				memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
-
-				if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
-				{
-					rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-				}
-
-				if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
-				{
-					/*	Commented by Albert 20110526 */
-					/*	In this case, this means the previous nego fail doesn't be reset yet. */
-					del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-					/*	Restore the previous p2p state */
-					rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-					DBG_8723A("[%s] Restore the previous p2p state to %d\n", __func__, rtw_p2p_state(pwdinfo));
-				}
-
-				/*	Commented by Kurt 20110902 */
-				/* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
-				if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
-					rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-
-				/*	Commented by Kurt 20120113 */
-				/*	Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
-				if (is_zero_ether_addr(pwdinfo->rx_prov_disc_info.peerDevAddr))
-					ether_addr_copy(pwdinfo->rx_prov_disc_info.peerDevAddr, hdr->addr2);
-
-				result = process_p2p_group_negotation_req23a(pwdinfo, frame_body, len);
-				issue_p2p_GO_response(padapter, hdr->addr2,
-						      frame_body, len, result);
-
-				/*	Commented by Albert 20110718 */
-				/*	No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
-				mod_timer(&pwdinfo->restore_p2p_state_timer,
-					  jiffies + msecs_to_jiffies(5000));
-				break;
-
-			case P2P_GO_NEGO_RESP:
-				DBG_8723A("[%s] Got GO Nego Resp Frame\n", __func__);
-
-				if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
-				{
-					/*	Commented by Albert 20110425 */
-					/*	The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
-					del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-					pwdinfo->nego_req_info.benable = false;
-					result = process_p2p_group_negotation_resp23a(pwdinfo, frame_body, len);
-					issue_p2p_GO_confirm(pwdinfo->padapter,
-							     hdr->addr2,
-							     result);
-					if (result == P2P_STATUS_SUCCESS) {
-						if (rtw_p2p_role(pwdinfo) ==
-						    P2P_ROLE_CLIENT) {
-							pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
-							pwdinfo->p2p_info.scan_op_ch_only = 1;
-							mod_timer(&pwdinfo->reset_ch_sitesurvey2, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
-						}
-					}
-
-					/*	Reset the dialog token for group negotiation frames. */
-					pwdinfo->negotiation_dialog_token = 1;
-
-					if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
-					{
-						mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(5000));
-					}
-				} else {
-					DBG_8723A("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __func__);
-				}
-
-				break;
-
-			case P2P_GO_NEGO_CONF:
-
-				DBG_8723A("[%s] Got GO Nego Confirm Frame\n", __func__);
-				result = process_p2p_group_negotation_confirm23a(pwdinfo, frame_body, len);
-				if (P2P_STATUS_SUCCESS == result)
-				{
-					if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT)
-					{
-						pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
-						pwdinfo->p2p_info.scan_op_ch_only = 1;
-						mod_timer(&pwdinfo->reset_ch_sitesurvey2, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
-					}
-				}
-				break;
-
-			case P2P_INVIT_REQ:
-				/*	Added by Albert 2010/10/05 */
-				/*	Received the P2P Invite Request frame. */
-
-				DBG_8723A("[%s] Got invite request frame!\n", __func__);
-				if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
-				{
-					/*	Parse the necessary information from the P2P Invitation Request frame. */
-					/*	For example: The MAC address of sending this P2P Invitation Request frame. */
-					u32	attr_contentlen = 0;
-					u8	status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-					struct group_id_info group_id;
-					u8	invitation_flag = 0;
-
-					rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
-					if (attr_contentlen)
-					{
-
-						rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
-						/*	Commented by Albert 20120510 */
-						/*	Copy to the pwdinfo->p2p_peer_interface_addr. */
-						/*	So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
-						/*	#> iwpriv wlan0 p2p_get peer_ifa */
-						/*	After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
-
-						if (attr_contentlen)
-						{
-							DBG_8723A("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
-									pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
-									pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
-									pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
-						}
-
-						if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT)
-						{
-							/*	Re-invoke the persistent group. */
-
-							memset(&group_id, 0x00, sizeof(struct group_id_info));
-							rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8*) &group_id, &attr_contentlen);
-							if (attr_contentlen) {
-								if (ether_addr_equal(group_id.go_device_addr, myid(&padapter->eeprompriv))) {
-									/*	The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
-									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
-									rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-									status_code = P2P_STATUS_SUCCESS;
-								}
-								else
-								{
-									/*	The p2p device sending this p2p invitation request wants to be the persistent GO. */
-									if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ]))
-									{
-										u8 operatingch_info[5] = { 0x00 };
-										if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
-										{
-											if (rtw_ch_set_search_ch23a(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4]))
-											{
-												/*	The operating channel is acceptable for this device. */
-												pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4];
-												pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
-												mod_timer(&pwdinfo->reset_ch_sitesurvey, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
-												rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
-												rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-												status_code = P2P_STATUS_SUCCESS;
-												}
-											else
-											{
-												/*	The operating channel isn't supported by this device. */
-												rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
-												rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-												status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
-												mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(3000));
-											}
-										}
-										else {
-											/*	Commented by Albert 20121130 */
-											/*	Intel will use the different P2P IE to store the operating channel information */
-											/*	Workaround for Intel WiDi 3.5 */
-											rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
-											rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-											status_code = P2P_STATUS_SUCCESS;
-										}
-									}
-									else
-									{
-										rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
-
-										status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
-									}
-								}
-							}
-							else
-							{
-								DBG_8723A("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
-								status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-							}
-						}
-						else
-						{
-							/*	Received the invitation to join a P2P group. */
-
-							memset(&group_id, 0x00, sizeof(struct group_id_info));
-							rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8*) &group_id, &attr_contentlen);
-							if (attr_contentlen)
-							{
-								if (ether_addr_equal(group_id.go_device_addr, myid(&padapter->eeprompriv))) {
-									/*	In this case, the GO can't be myself. */
-									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
-									status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-								}
-								else
-								{
-									/*	The p2p device sending this p2p invitation request wants to join an existing P2P group */
-									/*	Commented by Albert 2012/06/28 */
-									/*	In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
-									/*	The peer device address should be the destination address for the provisioning discovery request. */
-									/*	Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
-									/*	The peer interface address should be the address for WPS mac address */
-									ether_addr_copy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr);
-									rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
-									status_code = P2P_STATUS_SUCCESS;
-								}
-							}
-							else
-							{
-								DBG_8723A("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
-								status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-							}
-						}
-					}
-					else
-					{
-						DBG_8723A("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __func__);
-						status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-					}
-
-					DBG_8723A("[%s] status_code = %d\n", __func__, status_code);
-
-					pwdinfo->inviteresp_info.token = frame_body[ 7 ];
-					issue_p2p_invitation_response23a(padapter, hdr->addr2, pwdinfo->inviteresp_info.token, status_code);
-				}
-				break;
-
-			case P2P_INVIT_RESP:
-			{
-				u8	attr_content = 0x00;
-				u32	attr_contentlen = 0;
-
-				DBG_8723A("[%s] Got invite response frame!\n", __func__);
-				del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-				if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
-				{
-					rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
-
-					if (attr_contentlen == 1)
-					{
-						DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
-						pwdinfo->invitereq_info.benable = false;
-
-						if (attr_content == P2P_STATUS_SUCCESS)
-						{
-							if (ether_addr_equal(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv))) {
-								rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-							}
-							else
-							{
-								rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-							}
-							rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
-						}
-						else
-						{
-							rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-							rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
-						}
-					}
-					else
-					{
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
-					}
-				}
-				else
-				{
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
-				}
-
-				if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL)) {
-					mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(5000));
-				}
-				break;
-			}
-			case P2P_DEVDISC_REQ:
-
-				process_p2p_devdisc_req23a(pwdinfo, pframe, len);
-
-				break;
-
-			case P2P_DEVDISC_RESP:
-
-				process_p2p_devdisc_resp23a(pwdinfo, pframe, len);
-
-				break;
-
-			case P2P_PROVISION_DISC_REQ:
-				DBG_8723A("[%s] Got Provisioning Discovery Request Frame\n", __func__);
-				process_p2p_provdisc_req23a(pwdinfo, pframe, len);
-				ether_addr_copy(pwdinfo->rx_prov_disc_info.peerDevAddr, hdr->addr2);
-
-				/* 20110902 Kurt */
-				/* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
-				if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
-					rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
-				mod_timer(&pwdinfo->restore_p2p_state_timer,
-					  jiffies + msecs_to_jiffies(P2P_PROVISION_TIMEOUT));
-				break;
-
-			case P2P_PROVISION_DISC_RESP:
-				/*	Commented by Albert 20110707 */
-				/*	Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
-				DBG_8723A("[%s] Got Provisioning Discovery Response Frame\n", __func__);
-				/*	Commented by Albert 20110426 */
-				/*	The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
-				del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
-				process_p2p_provdisc_resp23a(pwdinfo, pframe);
-				mod_timer(&pwdinfo->restore_p2p_state_timer,
-					  jiffies + msecs_to_jiffies(P2P_PROVISION_TIMEOUT));
-				break;
-
-		}
-	}
-#endif /* CONFIG_8723AU_P2P */
-
-	return _SUCCESS;
-}
-
-static unsigned int on_action_public23a_vendor(struct recv_frame *precv_frame)
-{
-	unsigned int ret = _FAIL;
-	struct sk_buff *skb = precv_frame->pkt;
-	u8 *pframe = skb->data;
-	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-
-	if (!memcmp(frame_body + 2, P2P_OUI23A, 4)) {
-		ret = on_action_public23a_p2p(precv_frame);
-	}
-
-	return ret;
-}
-
-static unsigned int
-on_action_public23a_default(struct recv_frame *precv_frame, u8 action)
-{
-	unsigned int ret = _FAIL;
-	struct sk_buff *skb = precv_frame->pkt;
-	u8 *pframe = skb->data;
-	uint frame_len = skb->len;
-	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-	u8 token;
-	struct rtw_adapter *adapter = precv_frame->adapter;
-	int cnt = 0;
-	char msg[64];
-
-	token = frame_body[2];
-
-	if (rtw_action_public_decache(precv_frame, token) == _FAIL)
-		goto exit;
-
-	cnt += sprintf((msg+cnt), "%s(token:%u)",
-		       action_public_str23a(action), token);
-	rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
-
-	ret = _SUCCESS;
-
-exit:
-	return ret;
-}
-
-unsigned int on_action_public23a(struct rtw_adapter *padapter,
-				 struct recv_frame *precv_frame)
-{
-	unsigned int ret = _FAIL;
-	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
-	u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-	u8 category, action;
-
-	/* check RA matches or not */
-	if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
-		goto exit;
-
-	category = frame_body[0];
-	if (category != WLAN_CATEGORY_PUBLIC)
-		goto exit;
-
-	action = frame_body[1];
-	switch (action) {
-	case ACT_PUBLIC_VENDOR:
-		ret = on_action_public23a_vendor(precv_frame);
-		break;
-	default:
-		ret = on_action_public23a_default(precv_frame, action);
-		break;
-	}
-
-exit:
-	return ret;
-}
-
-unsigned int OnAction23a_ht(struct rtw_adapter *padapter,
-			    struct recv_frame *precv_frame)
-{
-	return _SUCCESS;
-}
-
-unsigned int OnAction23a_wmm(struct rtw_adapter *padapter,
-			     struct recv_frame *precv_frame)
-{
-	return _SUCCESS;
-}
-
-unsigned int OnAction23a_p2p(struct rtw_adapter *padapter,
-			     struct recv_frame *precv_frame)
-{
-#ifdef CONFIG_8723AU_P2P
-	u8 *frame_body;
-	u8 category, OUI_Subtype, dialogToken = 0;
-	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8 *pframe = skb->data;
-	uint len = skb->len;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	DBG_8723A("%s\n", __func__);
-
-	/* check RA matches or not */
-	if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
-		return _SUCCESS;
-
-	frame_body = (unsigned char *)
-		(pframe + sizeof(struct ieee80211_hdr_3addr));
-
-	category = frame_body[0];
-	if (category != WLAN_CATEGORY_VENDOR_SPECIFIC)
-		return _SUCCESS;
-
-	if (cpu_to_be32(*((u32*) (frame_body + 1))) != P2POUI)
-		return _SUCCESS;
-
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-		rtw_cfg80211_rx_action_p2p(padapter, pframe, len);
-		return _SUCCESS;
-	} else {
-		len -= sizeof(struct ieee80211_hdr_3addr);
-		OUI_Subtype = frame_body[5];
-		dialogToken = frame_body[6];
-
-		switch (OUI_Subtype)
-		{
-		case P2P_NOTICE_OF_ABSENCE:
-			break;
+	category = frame_body[0];
+	if (category != WLAN_CATEGORY_PUBLIC)
+		goto exit;
 
-		case P2P_PRESENCE_REQUEST:
-			process_p2p_presence_req23a(pwdinfo, pframe, len);
-			break;
+	action = frame_body[1];
+	switch (action) {
+	case ACT_PUBLIC_VENDOR:
+		ret = on_action_public23a_vendor(precv_frame);
+		break;
+	default:
+		ret = on_action_public23a_default(precv_frame, action);
+		break;
+	}
 
-		case P2P_PRESENCE_RESPONSE:
-			break;
+exit:
+	return ret;
+}
 
-		case P2P_GO_DISC_REQUEST:
-			break;
+static int
+OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+{
+	return _SUCCESS;
+}
 
-		default:
-			break;
-		}
-	}
-#endif /* CONFIG_8723AU_P2P */
+static int
+OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+{
+	return _SUCCESS;
+}
 
+static int
+OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
+{
 	return _SUCCESS;
 }
 
-unsigned int OnAction23a(struct rtw_adapter *padapter,
-			 struct recv_frame *precv_frame)
+static int
+OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	int i;
-	unsigned char	category;
+	u8 category;
 	struct action_handler *ptable;
-	unsigned char	*frame_body;
 	struct sk_buff *skb = precv_frame->pkt;
-	u8 *pframe = skb->data;
-
-	frame_body = (unsigned char *)
-		(pframe + sizeof(struct ieee80211_hdr_3addr));
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
 
-	category = frame_body[0];
+	category = mgmt->u.action.category;
 
 	for (i = 0;
 	     i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
@@ -5067,8 +2243,7 @@ unsigned int OnAction23a(struct rtw_adapter *padapter,
 	return _SUCCESS;
 }
 
-unsigned int DoReserved23a(struct rtw_adapter *padapter,
-			struct recv_frame *precv_frame)
+int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
 {
 	return _SUCCESS;
 }
@@ -5267,9 +2442,6 @@ void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 	u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
 	u8 *wps_ie;
 	u32 wps_ielen;
 	u8 sr = 0;
@@ -5311,119 +2483,7 @@ void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
 
 	if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
 		/* DBG_8723A("ie len =%d\n", cur_network->IELength); */
-#ifdef CONFIG_8723AU_P2P
-		/*  for P2P : Primary Device Type & Device Name */
-		u32 insert_len = 0;
-		wps_ie = rtw_get_wps_ie23a(cur_network->IEs + _FIXED_IE_LENGTH_,
-					   cur_network->IELength -
-					   _FIXED_IE_LENGTH_, NULL, &wps_ielen);
-
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wps_ie &&
-		    wps_ielen > 0) {
-			uint wps_offset, remainder_ielen;
-			u8 *premainder_ie, *pframe_wscie;
-
-			wps_offset = (uint)(wps_ie - cur_network->IEs);
-
-			premainder_ie = wps_ie + wps_ielen;
-
-			remainder_ielen = cur_network->IELength - wps_offset -
-				wps_ielen;
-
-			if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-				if (pmlmepriv->wps_beacon_ie &&
-				    pmlmepriv->wps_beacon_ie_len>0) {
-					memcpy(pframe, cur_network->IEs,
-					       wps_offset);
-					pframe += wps_offset;
-					pattrib->pktlen += wps_offset;
-
-					memcpy(pframe, pmlmepriv->wps_beacon_ie,
-					       pmlmepriv->wps_beacon_ie_len);
-					pframe += pmlmepriv->wps_beacon_ie_len;
-					pattrib->pktlen +=
-						pmlmepriv->wps_beacon_ie_len;
-
-					/* copy remainder_ie to pframe */
-					memcpy(pframe, premainder_ie,
-					       remainder_ielen);
-					pframe += remainder_ielen;
-					pattrib->pktlen += remainder_ielen;
-				} else {
-					memcpy(pframe, cur_network->IEs,
-					       cur_network->IELength);
-					pframe += cur_network->IELength;
-					pattrib->pktlen +=
-						cur_network->IELength;
-				}
-			} else {
-				pframe_wscie = pframe + wps_offset;
-				memcpy(pframe, cur_network->IEs,
-				       wps_offset + wps_ielen);
-				pframe += (wps_offset + wps_ielen);
-				pattrib->pktlen += (wps_offset + wps_ielen);
-
-				/* now pframe is end of wsc ie, insert Primary
-				   Device Type & Device Name */
-				/*	Primary Device Type */
-				/*	Type: */
-				*(u16*) (pframe + insert_len) =
-					cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
-				insert_len += 2;
-
-				/*	Length: */
-				*(u16*) (pframe + insert_len) =
-					cpu_to_be16(0x0008);
-				insert_len += 2;
-
-				/*	Value: */
-				/*	Category ID */
-				*(u16*) (pframe + insert_len) =
-					cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-				insert_len += 2;
-
-				/*	OUI */
-				*(u32*) (pframe + insert_len) =
-					cpu_to_be32(WPSOUI);
-				insert_len += 4;
-
-				/*	Sub Category ID */
-				*(u16*) (pframe + insert_len) =
-					cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-				insert_len += 2;
-
-				/*	Device Name */
-				/*	Type: */
-				*(u16*) (pframe + insert_len) =
-					cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-				insert_len += 2;
-
-				/*	Length: */
-				*(u16*) (pframe + insert_len) =
-					cpu_to_be16(pwdinfo->device_name_len);
-				insert_len += 2;
-
-				/*	Value: */
-				memcpy(pframe + insert_len,
-				       pwdinfo->device_name,
-				       pwdinfo->device_name_len);
-				insert_len += pwdinfo->device_name_len;
-
-				/* update wsc ie length */
-				*(pframe_wscie+1) = (wps_ielen -2) + insert_len;
-
-				/* pframe move to end */
-				pframe+= insert_len;
-				pattrib->pktlen += insert_len;
-
-				/* copy remainder_ie to pframe */
-				memcpy(pframe, premainder_ie, remainder_ielen);
-				pframe += remainder_ielen;
-				pattrib->pktlen += remainder_ielen;
-			}
-		} else
-#endif /* CONFIG_8723AU_P2P */
-			memcpy(pframe, cur_network->IEs, cur_network->IELength);
+		memcpy(pframe, cur_network->IEs, cur_network->IELength);
 		len_diff = update_hidden_ssid(pframe + _BEACON_IE_OFFSET_,
 					      cur_network->IELength -
 					      _BEACON_IE_OFFSET_,
@@ -5447,36 +2507,6 @@ void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
 		else
 			_clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
 
-#ifdef CONFIG_8723AU_P2P
-		if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-			u32 len;
-			if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-				len = pmlmepriv->p2p_beacon_ie_len;
-				if (pmlmepriv->p2p_beacon_ie && len > 0)
-					memcpy(pframe,
-					       pmlmepriv->p2p_beacon_ie, len);
-			} else
-				len = build_beacon_p2p_ie23a(pwdinfo, pframe);
-
-			pframe += len;
-			pattrib->pktlen += len;
-
-			if (true == pwdinfo->wfd_info->wfd_enable) {
-				len = build_beacon_wfd_ie(pwdinfo, pframe);
-			} else {
-				len = 0;
-				if (pmlmepriv->wfd_beacon_ie &&
-				    pmlmepriv->wfd_beacon_ie_len>0) {
-					len = pmlmepriv->wfd_beacon_ie_len;
-					memcpy(pframe,
-					       pmlmepriv->wfd_beacon_ie, len);
-				}
-			}
-			pframe += len;
-			pattrib->pktlen += len;
-		}
-#endif /* CONFIG_8723AU_P2P */
-
 		goto _issue_bcn;
 	}
 
@@ -5503,17 +2533,18 @@ void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
 	pattrib->pktlen += 2;
 
 	/*  SSID */
-	pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
+	pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
+			       cur_network->Ssid.ssid_len,
 			       cur_network->Ssid.ssid, &pattrib->pktlen);
 
 	/*  supported rates... */
 	rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
-	pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
+	pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
 			       ((rate_len > 8)? 8: rate_len),
 			       cur_network->SupportedRates, &pattrib->pktlen);
 
 	/*  DS parameter set */
-	pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
+	pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
 			       &cur_network->Configuration.DSConfig,
 			       &pattrib->pktlen);
 
@@ -5524,18 +2555,18 @@ void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
 		/*  IBSS Parameter Set... */
 		/* ATIMWindow = cur->Configuration.ATIMWindow; */
 		ATIMWindow = 0;
-		pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
 				       (unsigned char *)&ATIMWindow,
 				       &pattrib->pktlen);
 
 		/* ERP IE */
-		pframe = rtw_set_ie23a(pframe, _ERPINFO_IE_, 1,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
 				       &erpinfo, &pattrib->pktlen);
 	}
 
 	/*  EXTERNDED SUPPORTED RATE */
 	if (rate_len > 8)
-		pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
 				       rate_len - 8,
 				       cur_network->SupportedRates + 8,
 				       &pattrib->pktlen);
@@ -5582,22 +2613,17 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 	int ssid_ielen_diff;
 	u8 buf[MAX_IE_SZ];
 	u8 *ies;
-#endif
-#if defined(CONFIG_8723AU_AP_MODE) || defined(CONFIG_8723AU_P2P)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 #endif
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 	unsigned int rate_len;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
 
 	/* DBG_8723A("%s\n", __func__); */
 
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-	{
+	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
+	if (!pmgntframe) {
 		DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
 		return;
 	}
@@ -5608,7 +2634,7 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
 	pwlanhdr = (struct ieee80211_hdr *)pframe;
 
 	mac = myid(&padapter->eeprompriv);
@@ -5640,8 +2666,7 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 					    &wps_ielen);
 
 		/* inerset & update wps_probe_resp_ie */
-		if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie &&
-		    (wps_ielen > 0)) {
+		if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
 			uint wps_offset, remainder_ielen;
 			u8 *premainder_ie;
 
@@ -5658,14 +2683,14 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 
 			/* to get ie data len */
 			wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];
-			if ((wps_offset+wps_ielen+2)<= MAX_IE_SZ) {
+			if (wps_offset + wps_ielen + 2 <= MAX_IE_SZ) {
 				memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
 				       wps_ielen+2);
 				pframe += wps_ielen+2;
 				pattrib->pktlen += wps_ielen+2;
 			}
 
-			if ((wps_offset+wps_ielen+2+remainder_ielen) <=
+			if (wps_offset + wps_ielen + 2 + remainder_ielen <=
 			    MAX_IE_SZ) {
 				memcpy(pframe, premainder_ie, remainder_ielen);
 				pframe += remainder_ielen;
@@ -5681,9 +2706,9 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 		ies = pmgntframe->buf_addr + TXDESC_OFFSET +
 			sizeof(struct ieee80211_hdr_3addr);
 
-		ssid_ie = rtw_get_ie23a(ies+_FIXED_IE_LENGTH_, _SSID_IE_,
+		ssid_ie = rtw_get_ie23a(ies + _FIXED_IE_LENGTH_, WLAN_EID_SSID,
 					&ssid_ielen,
-					(pframe-ies)-_FIXED_IE_LENGTH_);
+					pframe - ies - _FIXED_IE_LENGTH_);
 
 		ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
 
@@ -5691,20 +2716,19 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 			uint remainder_ielen;
 			u8 *remainder_ie;
 			remainder_ie = ssid_ie + 2;
-			remainder_ielen = (pframe-remainder_ie);
+			remainder_ielen = pframe - remainder_ie;
 
 			DBG_8723A_LEVEL(_drv_warning_, FUNC_ADPT_FMT
 					" remainder_ielen > MAX_IE_SZ\n",
 					FUNC_ADPT_ARG(padapter));
-			if (remainder_ielen > MAX_IE_SZ) {
+			if (remainder_ielen > MAX_IE_SZ)
 				remainder_ielen = MAX_IE_SZ;
-			}
 
 			memcpy(buf, remainder_ie, remainder_ielen);
-			memcpy(remainder_ie+ssid_ielen_diff, buf,
+			memcpy(remainder_ie + ssid_ielen_diff, buf,
 			       remainder_ielen);
-			*(ssid_ie+1) = cur_network->Ssid.ssid_len;
-			memcpy(ssid_ie+2, cur_network->Ssid.ssid,
+			*(ssid_ie + 1) = cur_network->Ssid.ssid_len;
+			memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
 			       cur_network->Ssid.ssid_len);
 
 			pframe += ssid_ielen_diff;
@@ -5737,40 +2761,42 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 		/* below for ad-hoc mode */
 
 		/*  SSID */
-		pframe = rtw_set_ie23a(pframe, _SSID_IE_,
-				    cur_network->Ssid.ssid_len,
-				    cur_network->Ssid.ssid, &pattrib->pktlen);
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
+				       cur_network->Ssid.ssid_len,
+				       cur_network->Ssid.ssid,
+				       &pattrib->pktlen);
 
 		/*  supported rates... */
 		rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
-		pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
 				       ((rate_len > 8)? 8: rate_len),
 				       cur_network->SupportedRates,
 				       &pattrib->pktlen);
 
 		/*  DS parameter set */
-		pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
+				       (unsigned char *)
 				       &cur_network->Configuration.DSConfig,
 				       &pattrib->pktlen);
 
-		if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
+		if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
 			u8 erpinfo = 0;
 			u32 ATIMWindow;
 			/*  IBSS Parameter Set... */
 			/* ATIMWindow = cur->Configuration.ATIMWindow; */
 			ATIMWindow = 0;
-			pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2,
+			pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
 					       (unsigned char *)&ATIMWindow,
 					       &pattrib->pktlen);
 
 			/* ERP IE */
-			pframe = rtw_set_ie23a(pframe, _ERPINFO_IE_, 1,
+			pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
 					       &erpinfo, &pattrib->pktlen);
 		}
 
 		/*  EXTERNDED SUPPORTED RATE */
 		if (rate_len > 8)
-			pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
+			pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
 					       rate_len - 8,
 					       cur_network->SupportedRates + 8,
 					       &pattrib->pktlen);
@@ -5778,38 +2804,6 @@ void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 		/* todo:HT for adhoc */
 	}
 
-#ifdef CONFIG_8723AU_P2P
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
-		u32 len;
-		if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-			/* if pwdinfo->role == P2P_ROLE_DEVICE will call
-			   issue_probersp23a_p2p23a() */
-			len = pmlmepriv->p2p_go_probe_resp_ie_len;
-			if (pmlmepriv->p2p_go_probe_resp_ie && len>0)
-				memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie,
-				       len);
-		} else
-			len = build_probe_resp_p2p_ie23a(pwdinfo, pframe);
-
-		pframe += len;
-		pattrib->pktlen += len;
-
-		if (true == pwdinfo->wfd_info->wfd_enable) {
-			len = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
-		} else {
-			len = 0;
-			if (pmlmepriv->wfd_probe_resp_ie &&
-			    pmlmepriv->wfd_probe_resp_ie_len > 0) {
-				len = pmlmepriv->wfd_probe_resp_ie_len;
-				memcpy(pframe, pmlmepriv->wfd_probe_resp_ie,
-				       len);
-			}
-		}
-		pframe += len;
-		pattrib->pktlen += len;
-	}
-#endif /* CONFIG_8723AU_P2P */
-
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
 	dump_mgntframe23a(padapter, pmgntframe);
@@ -5874,22 +2868,22 @@ static int _issue_probereq23a(struct rtw_adapter *padapter,
 	pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
 
 	if (pssid)
-		pframe = rtw_set_ie23a(pframe, _SSID_IE_, pssid->ssid_len,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
 				       pssid->ssid, &pattrib->pktlen);
 	else
-		pframe = rtw_set_ie23a(pframe, _SSID_IE_, 0, NULL,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
 				       &pattrib->pktlen);
 
 	get_rate_set23a(padapter, bssrate, &bssrate_len);
 
 	if (bssrate_len > 8) {
-		pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
 				       bssrate, &pattrib->pktlen);
-		pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
 				       (bssrate_len - 8), (bssrate + 8),
 				       &pattrib->pktlen);
 	} else {
-		pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
 				       bssrate_len, bssrate, &pattrib->pktlen);
 	}
 
@@ -6045,7 +3039,7 @@ void issue_auth23a(struct rtw_adapter *padapter, struct sta_info *psta,
 		/*  added challenging text... */
 		if ((psta->auth_seq == 2) &&
 		    (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
-			pframe = rtw_set_ie23a(pframe, _CHLGETXT_IE_, 128,
+			pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
 					       psta->chg_txt, &pattrib->pktlen);
 #endif
 	} else {
@@ -6104,7 +3098,7 @@ void issue_auth23a(struct rtw_adapter *padapter, struct sta_info *psta,
 		if ((pmlmeinfo->auth_seq == 3) &&
 		    (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
 		    (use_shared_key == 1)) {
-			pframe = rtw_set_ie23a(pframe, _CHLGETXT_IE_, 128,
+			pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
 					       pmlmeinfo->chg_txt,
 					       &pattrib->pktlen);
 
@@ -6136,22 +3130,20 @@ void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
 	struct xmit_frame *pmgntframe;
 	struct ieee80211_hdr *pwlanhdr;
 	struct pkt_attrib *pattrib;
-	unsigned char *pbuf, *pframe;
+	unsigned char *pframe;
 	unsigned short val;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+	const u8 *p;
 	u8 *ie = pnetwork->IEs;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
 
 	DBG_8723A("%s\n", __func__);
 
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
+	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
+	if (!pmgntframe)
 		return;
 
 	/* update attribute */
@@ -6171,7 +3163,7 @@ void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
 
 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 	pmlmeext->mgnt_seq++;
-	if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
+	if (pkt_type == WIFI_ASSOCRSP || pkt_type == WIFI_REASSOCRSP)
 		SetFrameSubType(pwlanhdr, pkt_type);
 	else
 		return;
@@ -6196,69 +3188,70 @@ void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
 				     &pattrib->pktlen);
 
 	if (pstat->bssratelen <= 8) {
-		pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
 				       pstat->bssratelen, pstat->bssrateset,
 				       &pattrib->pktlen);
 	} else {
-		pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
 				       pstat->bssrateset, &pattrib->pktlen);
-		pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
 				       pstat->bssratelen - 8,
 				       pstat->bssrateset + 8, &pattrib->pktlen);
 	}
 
-	if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
-		uint ie_len = 0;
-
+	if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
 		/* FILL HT CAP INFO IE */
 		/* p = hostapd_eid_ht_capabilities_info(hapd, p); */
-		pbuf = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_,
-				     _HT_CAPABILITY_IE_, &ie_len,
-				     pnetwork->IELength - _BEACON_IE_OFFSET_);
-		if (pbuf && ie_len>0) {
-			memcpy(pframe, pbuf, ie_len + 2);
-			pframe += (ie_len + 2);
-			pattrib->pktlen += (ie_len + 2);
+		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
+				     ie + _BEACON_IE_OFFSET_,
+				     pnetwork->IELength -_BEACON_IE_OFFSET_);
+		if (p && p[1]) {
+			memcpy(pframe, p, p[1] + 2);
+			pframe += (p[1] + 2);
+			pattrib->pktlen += (p[1] + 2);
 		}
 
 		/* FILL HT ADD INFO IE */
 		/* p = hostapd_eid_ht_operation(hapd, p); */
-		pbuf = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_,
-				     &ie_len,
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
+				     ie + _BEACON_IE_OFFSET_,
 				     pnetwork->IELength - _BEACON_IE_OFFSET_);
-		if (pbuf && ie_len > 0) {
-			memcpy(pframe, pbuf, ie_len + 2);
-			pframe += (ie_len + 2);
-			pattrib->pktlen += (ie_len + 2);
+		if (p && p[1] > 0) {
+			memcpy(pframe, p, p[1] + 2);
+			pframe += (p[1] + 2);
+			pattrib->pktlen += (p[1] + 2);
 		}
 	}
 
 	/* FILL WMM IE */
-	if ((pstat->flags & WLAN_STA_WME) && pmlmepriv->qospriv.qos_option) {
-		uint ie_len = 0;
+	if (pstat->flags & WLAN_STA_WME && pmlmepriv->qospriv.qos_option) {
 		unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
 					       0x01, 0x01};
-
-		for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
-			pbuf = rtw_get_ie23a(pbuf, _VENDOR_SPECIFIC_IE_,
-					     &ie_len, (pnetwork->IELength -
-						       _BEACON_IE_OFFSET_ -
-						       (ie_len + 2)));
-			if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
-				memcpy(pframe, pbuf, ie_len + 2);
+		int ie_len = 0;
+
+		for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
+			p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
+					     pnetwork->IELength -
+					     _BEACON_IE_OFFSET_ - (ie_len + 2));
+			if (p)
+				ie_len = p[1];
+			else
+				ie_len = 0;
+			if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
+				memcpy(pframe, p, ie_len + 2);
 				pframe += (ie_len + 2);
 				pattrib->pktlen += (ie_len + 2);
 
 				break;
 			}
 
-			if ((!pbuf) || (ie_len == 0))
+			if (!p || ie_len == 0)
 				break;
 		}
 	}
 
 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
-		pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, 6,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
 				       REALTEK_96B_IE23A, &pattrib->pktlen);
 	}
 
@@ -6272,15 +3265,6 @@ void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
 		pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
 	}
 
-#ifdef CONFIG_8723AU_P2P
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) &&
-	    pwdinfo->wfd_info->wfd_enable) {
-		wfdielen = build_assoc_resp_wfd_ie(pwdinfo, pframe);
-		pframe += wfdielen;
-		pattrib->pktlen += wfdielen;
-	}
-#endif /* CONFIG_8723AU_P2P */
-
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
 	dump_mgntframe23a(padapter, pmgntframe);
@@ -6292,11 +3276,11 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 	int ret = _FAIL;
 	struct xmit_frame *pmgntframe;
 	struct pkt_attrib *pattrib;
-	unsigned char *pframe, *p;
+	unsigned char *pframe;
+	const u8 *p;
 	struct ieee80211_hdr *pwlanhdr;
 	unsigned short *fctrl;
-	unsigned short val16;
-	unsigned int i, j, ie_len, index = 0;
+	unsigned int i, j, index = 0;
 	unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
 	struct ndis_802_11_var_ies *pIE;
 	struct registry_priv *pregpriv = &padapter->registrypriv;
@@ -6304,15 +3288,11 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	int bssrate_len = 0, sta_bssrate_len = 0;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	u8 p2pie[255] = { 0x00 };
-	u16 p2pielen = 0;
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
+	int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
+	u8 * pie;
 
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
+	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
+	if (!pmgntframe)
 		goto exit;
 
 	/* update attribute */
@@ -6321,7 +3301,7 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
 	pwlanhdr = (struct ieee80211_hdr *)pframe;
 
 	fctrl = &pwlanhdr->frame_control;
@@ -6338,21 +3318,20 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
 
 	/* caps */
-	memcpy(pframe, rtw_get_capability23a_from_ie(pmlmeinfo->network.IEs),
-	       2);
+	memcpy(pframe,
+	       rtw_get_capability23a_from_ie(pmlmeinfo->network.IEs), 2);
 
 	pframe += 2;
 	pattrib->pktlen += 2;
 
 	/* listen interval */
 	/* todo: listen interval for power saving */
-	val16 = cpu_to_le16(3);
-	memcpy(pframe, (unsigned char *)&val16, 2);
+	put_unaligned_le16(3, pframe);
 	pframe += 2;
 	pattrib->pktlen += 2;
 
 	/* SSID */
-	pframe = rtw_set_ie23a(pframe, _SSID_IE_,
+	pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
 			       pmlmeinfo->network.Ssid.ssid_len,
 			       pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
 
@@ -6387,7 +3366,7 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 			     Handlink WSG-4000 AP */
 			if ((pmlmeinfo->network.SupportedRates[i] |
 			     IEEE80211_BASIC_RATE_MASK) ==
-			    (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
+			    (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
 				/* DBG_8723A("match i = %d, j =%d\n", i, j); */
 				break;
 			}
@@ -6414,33 +3393,31 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 	}
 
 	if (bssrate_len > 8) {
-		pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
 				       bssrate, &pattrib->pktlen);
-		pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
 				       (bssrate_len - 8), (bssrate + 8),
 				       &pattrib->pktlen);
 	} else
-		pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
 				       bssrate_len, bssrate, &pattrib->pktlen);
 
 	/* RSN */
-	p = rtw_get_ie23a((pmlmeinfo->network.IEs +
-			   sizeof(struct ndis_802_11_fixed_ies)), _RSN_IE_2_,
-			  &ie_len, (pmlmeinfo->network.IELength -
-				    sizeof(struct ndis_802_11_fixed_ies)));
+	pie = pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ies);
+	pie_len = pmlmeinfo->network.IELength -
+		sizeof(struct ndis_802_11_fixed_ies);
+
+	p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
 	if (p)
-		pframe = rtw_set_ie23a(pframe, _RSN_IE_2_, ie_len, (p + 2),
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
 				       &pattrib->pktlen);
 
 	/* HT caps */
 	if (padapter->mlmepriv.htpriv.ht_option == true) {
-		p = rtw_get_ie23a((pmlmeinfo->network.IEs +
-				   sizeof(struct ndis_802_11_fixed_ies)),
-				  _HT_CAPABILITY_IE_, &ie_len,
-				  (pmlmeinfo->network.IELength -
-				   sizeof(struct ndis_802_11_fixed_ies)));
-		if ((p != NULL) && (!(is_ap_in_tkip23a(padapter)))) {
-			memcpy(&pmlmeinfo->HT_caps, (p + 2),
+		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
+
+		if (p && !is_ap_in_tkip23a(padapter)) {
+			memcpy(&pmlmeinfo->HT_caps, p + 2,
 			       sizeof(struct HT_caps_element));
 
 			/* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
@@ -6454,15 +3431,13 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 			pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |=
 				0x000c;
 
-			rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE,
-					     (u8 *)(&rf_type));
+			rf_type = rtl8723a_get_rf_type(padapter);
 			/* switch (pregpriv->rf_config) */
-			switch (rf_type)
-			{
+			switch (rf_type) {
 			case RF_1T1R:
-
+				/* RX STBC One spatial stream */
 				if (pregpriv->rx_stbc)
-					pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
+					pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);
 
 				memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R23A, 16);
 				break;
@@ -6470,18 +3445,17 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 			case RF_2T2R:
 			case RF_1T2R:
 			default:
-
 				/* enable for 2.4/5 GHz */
-				if ((pregpriv->rx_stbc == 0x3) ||
-				    ((pmlmeext->cur_wireless_mode &
-				      WIRELESS_11_24N) &&
+				if (pregpriv->rx_stbc == 0x3 ||
+				    (pmlmeext->cur_wireless_mode &
+				     WIRELESS_11_24N &&
 				     /* enable for 2.4GHz */
-				     (pregpriv->rx_stbc == 0x1)) ||
-				    ((pmlmeext->cur_wireless_mode &
-				      WIRELESS_11_5N) &&
-				     (pregpriv->rx_stbc == 0x2)) ||
+				     pregpriv->rx_stbc == 0x1) ||
+				    (pmlmeext->cur_wireless_mode &
+				     WIRELESS_11_5N &&
+				     pregpriv->rx_stbc == 0x2) ||
 				    /* enable for 5GHz */
-				    (pregpriv->wifi_spec == 1)) {
+				    pregpriv->wifi_spec == 1) {
 					DBG_8723A("declare supporting RX "
 						  "STBC\n");
 					pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
@@ -6500,9 +3474,8 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 			}
 #endif
 
-			pframe = rtw_set_ie23a(pframe, _HT_CAPABILITY_IE_,
-					       ie_len,
-					       (u8 *)&pmlmeinfo->HT_caps,
+			pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
+					       p[1], (u8 *)&pmlmeinfo->HT_caps,
 					       &pattrib->pktlen);
 		}
 	}
@@ -6515,8 +3488,8 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 
 		switch (pIE->ElementID)
 		{
-		case _VENDOR_SPECIFIC_IE_:
-			if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4) ||
+		case WLAN_EID_VENDOR_SPECIFIC:
+			if (!memcmp(pIE->data, RTW_WPA_OUI23A_TYPE, 4) ||
 			    !memcmp(pIE->data, WMM_OUI23A, 4) ||
 			    !memcmp(pIE->data, WPS_OUI23A, 4)) {
 				if (!padapter->registrypriv.wifi_spec) {
@@ -6528,7 +3501,7 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 						pIE->Length = 14;
 				}
 				pframe = rtw_set_ie23a(pframe,
-						       _VENDOR_SPECIFIC_IE_,
+						       WLAN_EID_VENDOR_SPECIFIC,
 						       pIE->Length, pIE->data,
 						       &pattrib->pktlen);
 			}
@@ -6538,198 +3511,13 @@ void issue_assocreq23a(struct rtw_adapter *padapter)
 			break;
 		}
 
-		i += (pIE->Length + 2);
+		i += pIE->Length + 2;
 	}
 
 	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
-		pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, 6,
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
 				       REALTEK_96B_IE23A, &pattrib->pktlen);
 
-#ifdef CONFIG_8723AU_P2P
-
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
-		if (pmlmepriv->p2p_assoc_req_ie &&
-		    pmlmepriv->p2p_assoc_req_ie_len>0) {
-			memcpy(pframe, pmlmepriv->p2p_assoc_req_ie,
-			       pmlmepriv->p2p_assoc_req_ie_len);
-			pframe += pmlmepriv->p2p_assoc_req_ie_len;
-			pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
-		}
-	} else {
-		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
-		    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
-			/*	Should add the P2P IE in the association
-				request frame. */
-			/*	P2P OUI */
-
-			p2pielen = 0;
-			p2pie[p2pielen++] = 0x50;
-			p2pie[p2pielen++] = 0x6F;
-			p2pie[p2pielen++] = 0x9A;
-			p2pie[p2pielen++] = 0x09;	/*	WFA P2P v1.0 */
-
-			/*	Commented by Albert 20101109 */
-			/*	According to the P2P Specification, the
-				association request frame should contain
-				3 P2P attributes */
-			/*	1. P2P Capability */
-			/*	2. Extended Listen Timing */
-			/*	3. Device Info */
-			/*	Commented by Albert 20110516 */
-			/*	4. P2P Interface */
-
-			/*	P2P Capability */
-			/*	Type: */
-			p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-			/*	Length: */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
-			p2pielen += 2;
-
-			/*	Value: */
-			/*	Device Capability Bitmap, 1 byte */
-			p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
-
-			/*	Group Capability Bitmap, 1 byte */
-			if (pwdinfo->persistent_supported)
-				p2pie[p2pielen++] =
-					P2P_GRPCAP_PERSISTENT_GROUP |
-					DMP_P2P_GRPCAP_SUPPORT;
-			else
-				p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
-
-			/*	Extended Listen Timing */
-			/*	Type: */
-			p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
-
-			/*	Length: */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
-			p2pielen += 2;
-
-			/*	Value: */
-			/*	Availability Period */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-			p2pielen += 2;
-
-			/*	Availability Interval */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
-			p2pielen += 2;
-
-			/*	Device Info */
-			/*	Type: */
-			p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-			/*	Length: */
-			/*	21 -> P2P Device Address (6bytes) + Config
-				Methods (2bytes) + Primary Device
-				Type (8bytes) */
-			/*	+ NumofSecondDevType (1byte) + WPS Device
-				Name ID field (2bytes) + WPS Device Name
-				Len field (2bytes) */
-			*(u16*) (p2pie + p2pielen) =
-				cpu_to_le16(21 + pwdinfo->device_name_len);
-			p2pielen += 2;
-
-			/*	Value: */
-			/*	P2P Device Address */
-			memcpy(p2pie + p2pielen,
-			       myid(&padapter->eeprompriv), ETH_ALEN);
-			p2pielen += ETH_ALEN;
-
-			/*	Config Method */
-			/*	This field should be big endian.
-				Noted by P2P specification. */
-			if ((pwdinfo->ui_got_wps_info ==
-			     P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
-			    (pwdinfo->ui_got_wps_info ==
-			     P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
-				*(u16*) (p2pie + p2pielen) =
-					cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
-			else
-				*(u16*) (p2pie + p2pielen) =
-					cpu_to_be16(WPS_CONFIG_METHOD_PBC);
-
-			p2pielen += 2;
-
-			/*	Primary Device Type */
-			/*	Category ID */
-			*(u16*) (p2pie + p2pielen) =
-				cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
-			p2pielen += 2;
-
-			/*	OUI */
-			*(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
-			p2pielen += 4;
-
-			/*	Sub Category ID */
-			*(u16*) (p2pie + p2pielen) =
-				cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
-			p2pielen += 2;
-
-			/*	Number of Secondary Device Types */
-			/*	No Secondary Device Type List */
-			p2pie[p2pielen++] = 0x00;
-
-			/*	Device Name */
-			/*	Type: */
-			*(u16*) (p2pie + p2pielen) =
-				cpu_to_be16(WPS_ATTR_DEVICE_NAME);
-			p2pielen += 2;
-
-			/*	Length: */
-			*(u16*) (p2pie + p2pielen) =
-				cpu_to_be16(pwdinfo->device_name_len);
-			p2pielen += 2;
-
-			/*	Value: */
-			memcpy(p2pie + p2pielen, pwdinfo->device_name,
-			       pwdinfo->device_name_len);
-			p2pielen += pwdinfo->device_name_len;
-
-			/*	P2P Interface */
-			/*	Type: */
-			p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
-
-			/*	Length: */
-			*(u16*) (p2pie + p2pielen) = cpu_to_le16(0x000D);
-			p2pielen += 2;
-
-			/*	Value: */
-			memcpy(p2pie + p2pielen, pwdinfo->device_addr,
-			       ETH_ALEN);	/* P2P Device Address */
-			p2pielen += ETH_ALEN;
-
-			/* P2P Interface Address Count */
-			p2pie[p2pielen++] = 1;
-
-			memcpy(p2pie + p2pielen, pwdinfo->device_addr,
-			       ETH_ALEN);	/* P2P Interface Address List */
-			p2pielen += ETH_ALEN;
-
-			pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_,
-					       p2pielen, (unsigned char *)p2pie,
-					       &pattrib->pktlen);
-
-			/* wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);*/
-			/* pframe += wfdielen; */
-			/* pattrib->pktlen += wfdielen; */
-		}
-	}
-
-	if (true == pwdinfo->wfd_info->wfd_enable) {
-		wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
-		pframe += wfdielen;
-		pattrib->pktlen += wfdielen;
-	} else if (pmlmepriv->wfd_assoc_req_ie != NULL &&
-		   pmlmepriv->wfd_assoc_req_ie_len > 0) {
-		/* WFD IE */
-		memcpy(pframe, pmlmepriv->wfd_assoc_req_ie,
-		       pmlmepriv->wfd_assoc_req_ie_len);
-		pattrib->pktlen += pmlmepriv->wfd_assoc_req_ie_len;
-		pframe += pmlmepriv->wfd_assoc_req_ie_len;
-	}
-#endif /* CONFIG_8723AU_P2P */
-
 	pattrib->last_txcmdsz = pattrib->pktlen;
 	dump_mgntframe23a(padapter, pmgntframe);
 
@@ -6741,8 +3529,7 @@ exit:
 		kfree(pmlmepriv->assoc_req);
 		pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
 		if (pmlmepriv->assoc_req) {
-			memcpy(pmlmepriv->assoc_req, pwlanhdr,
-			       pattrib->pktlen);
+			memcpy(pmlmepriv->assoc_req, pwlanhdr, pattrib->pktlen);
 			pmlmepriv->assoc_req_len = pattrib->pktlen;
 		}
 	} else
@@ -7014,20 +3801,9 @@ static int _issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	int ret = _FAIL;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
 
 	/* DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
 
-#ifdef CONFIG_8723AU_P2P
-	if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) &&
-	    (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
-		mod_timer(&pwdinfo->reset_ch_sitesurvey,
-			  jiffies + msecs_to_jiffies(10));
-	}
-#endif /* CONFIG_8723AU_P2P */
-
 	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
 		goto exit;
 
@@ -7373,24 +4149,26 @@ static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
 {
 	struct list_head *plist, *phead, *ptmp;
 	unsigned char category, action;
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char				*pframe;
-	struct ieee80211_hdr	*pwlanhdr;
-	unsigned short			*fctrl;
-	struct	wlan_network	*pnetwork = NULL;
+	struct xmit_frame *pmgntframe;
+	struct pkt_attrib *pattrib;
+	u8 *pframe;
+	struct ieee80211_hdr *pwlanhdr;
+	unsigned short *fctrl;
+	struct wlan_network *pnetwork;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	struct rtw_queue	*queue	= &pmlmepriv->scanned_queue;
+	struct rtw_queue *queue	= &pmlmepriv->scanned_queue;
 	u8 InfoContent[16] = {0};
 	u8 ICS[8][15];
+	int i;
 
-	if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
+	if (pmlmepriv->num_FortyMHzIntolerant == 0 ||
+	    pmlmepriv->num_sta_no_ht == 0)
 		return;
 
-	if (true == pmlmeinfo->bwmode_updated)
+	if (pmlmeinfo->bwmode_updated)
 		return;
 
 	DBG_8723A("%s\n", __func__);
@@ -7398,10 +4176,9 @@ static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
 	category = WLAN_CATEGORY_PUBLIC;
 	action = ACT_PUBLIC_BSSCOEXIST;
 
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-	{
+	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
+	if (!pmgntframe)
 		return;
-	}
 
 	/* update attribute */
 	pattrib = &pmgntframe->attrib;
@@ -7409,7 +4186,7 @@ static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
 
 	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
 	pwlanhdr = (struct ieee80211_hdr *)pframe;
 
 	fctrl = &pwlanhdr->frame_control;
@@ -7429,85 +4206,74 @@ static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
 	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
 	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
 
-	/*  */
-	if (pmlmepriv->num_FortyMHzIntolerant>0)
-	{
-		u8 iedata = 0;
-
-		iedata |= BIT(2);/* 20 MHz BSS Width Request */
-
-		pframe = rtw_set_ie23a(pframe, EID_BSSCoexistence,  1, &iedata, &pattrib->pktlen);
+	if (pmlmepriv->num_FortyMHzIntolerant > 0) {
+		u8 iedata = BIT(2);/* 20 MHz BSS Width Request */
 
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_BSS_COEX_2040, 1,
+				       &iedata, &pattrib->pktlen);
 	}
 
-	/*  */
-	memset(ICS, 0, sizeof(ICS));
-	if (pmlmepriv->num_sta_no_ht>0)
-	{
-		int i;
+	if (pmlmepriv->num_sta_no_ht <= 0)
+		goto out;
 
-		spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+	memset(ICS, 0, sizeof(ICS));
 
-		phead = get_list_head(queue);
-		plist = phead->next;
+	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 
-		list_for_each_safe(plist, ptmp, phead) {
-			int len;
-			u8 *p;
-			struct wlan_bssid_ex *pbss_network;
+	phead = get_list_head(queue);
+	plist = phead->next;
 
-			pnetwork = container_of(plist, struct wlan_network,
-						list);
+	list_for_each_safe(plist, ptmp, phead) {
+		const u8 *p;
+		struct wlan_bssid_ex *pbss_network;
 
-			pbss_network = &pnetwork->network;
+		pnetwork = container_of(plist, struct wlan_network, list);
 
-			p = rtw_get_ie23a(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
-			if ((p == NULL) || (len == 0))/* non-HT */
-			{
-				if ((pbss_network->Configuration.DSConfig<= 0) || (pbss_network->Configuration.DSConfig>14))
-					continue;
+		pbss_network = &pnetwork->network;
 
-				ICS[0][pbss_network->Configuration.DSConfig]= 1;
+		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
+				     pbss_network->IEs + _FIXED_IE_LENGTH_,
+				     pbss_network->IELength -_FIXED_IE_LENGTH_);
+		if (!p || !p[1]) { /* non-HT */
+			if (pbss_network->Configuration.DSConfig <= 0 ||
+			    pbss_network->Configuration.DSConfig > 14)
+				continue;
 
-				if (ICS[0][0] == 0)
-					ICS[0][0] = 1;
-			}
+			ICS[0][pbss_network->Configuration.DSConfig] = 1;
 
+			if (ICS[0][0] == 0)
+				ICS[0][0] = 1;
 		}
 
-		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+	}
 
-		for (i = 0;i<8;i++)
-		{
-			if (ICS[i][0] == 1)
-			{
-				int j, k = 0;
+	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
-				InfoContent[k] = i;
-				/* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
-				k++;
+	for (i = 0; i < 8;i++) {
+		if (ICS[i][0] == 1) {
+			int j, k = 0;
 
-				for (j = 1;j<= 14;j++)
-				{
-					if (ICS[i][j]== 1)
-					{
-						if (k<16)
-						{
-							InfoContent[k] = j; /* channel number */
-							/* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
-							k++;
-						}
+			InfoContent[k] = i;
+			/* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
+			k++;
+
+			for (j = 1; j <= 14; j++) {
+				if (ICS[i][j] == 1) {
+					if (k < 16) {
+						/* channel number */
+						InfoContent[k] = j;
+						k++;
 					}
 				}
-
-				pframe = rtw_set_ie23a(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen);
-
 			}
 
+			pframe = rtw_set_ie23a(pframe,
+					       EID_BSSIntolerantChlReport, k,
+					       InfoContent, &pattrib->pktlen);
 		}
-
 	}
 
+out:
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
 	dump_mgntframe23a(padapter, pmgntframe);
@@ -7555,21 +4321,21 @@ unsigned int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
 
 unsigned int send_beacon23a(struct rtw_adapter *padapter)
 {
-	u8	bxmitok = false;
+	bool	bxmitok;
 	int	issue = 0;
 	int poll = 0;
 	unsigned long start = jiffies;
 	unsigned int passing_time;
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BCN_VALID, NULL);
+	rtl8723a_bcn_valid(padapter);
 	do {
 		issue_beacon23a(padapter, 100);
 		issue++;
 		do {
 			yield();
-			rtw23a_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
+			bxmitok = rtl8723a_get_bcn_valid(padapter);
 			poll++;
-		} while ((poll%10)!= 0 && false == bxmitok &&
+		} while ((poll % 10) != 0 && bxmitok == false &&
 			 !padapter->bSurpriseRemoved &&
 			 !padapter->bDriverStopped);
 
@@ -7615,46 +4381,22 @@ bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
 
 void site_survey23a(struct rtw_adapter *padapter)
 {
-	unsigned char survey_channel = 0, val8;
+	unsigned char survey_channel = 0;
 	enum rt_scan_type ScanType = SCAN_PASSIVE;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	u32 initialgain = 0;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) ||
-	    (pwdinfo->p2p_info.scan_op_ch_only)) {
-		if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
-			survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
-		else
-			survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
-		ScanType = SCAN_ACTIVE;
-	} else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
-		/* The driver is in the find phase, it should go through the social channel. */
-		int ch_set_idx;
-		survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
-		ch_set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, survey_channel);
-		if (ch_set_idx >= 0)
-			ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
-		else
-			ScanType = SCAN_ACTIVE;
-	} else
-#endif /* CONFIG_8723AU_P2P */
-	{
-		struct rtw_ieee80211_channel *ch;
-		if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
-			ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
-			survey_channel = ch->hw_value;
-			ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ? SCAN_PASSIVE : SCAN_ACTIVE;
-}
+	struct rtw_ieee80211_channel *ch;
+
+	if (pmlmeext->sitesurvey_res.channel_idx <
+	    pmlmeext->sitesurvey_res.ch_num) {
+		ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
+		survey_channel = ch->hw_value;
+		ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
+			SCAN_PASSIVE : SCAN_ACTIVE;
 	}
 
 	if (survey_channel != 0) {
 		/* PAUSE 4-AC Queue when site_survey23a */
-		/* rtw23a_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
-		/* val8 |= 0x0f; */
-		/* rtw_hal_set_hwreg23a(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
 		if (pmlmeext->sitesurvey_res.channel_idx == 0)
 			set_channel_bwmode23a(padapter, survey_channel,
 					      HAL_PRIME_CHNL_OFFSET_DONT_CARE,
@@ -7664,276 +4406,220 @@ void site_survey23a(struct rtw_adapter *padapter)
 
 		if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
 		{
-#ifdef CONFIG_8723AU_P2P
-			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
-				rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
-			)
-			{
-				issue23a_probereq_p2p(padapter, NULL);
-				issue23a_probereq_p2p(padapter, NULL);
-				issue23a_probereq_p2p(padapter, NULL);
-			}
-			else
-#endif /* CONFIG_8723AU_P2P */
-			{
-				int i;
-				for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
-					if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
-						/* todo: to issue two probe req??? */
-						issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
-						/* msleep(SURVEY_TO>>1); */
-						issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
-					}
-				}
-
-				if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+			int i;
+			for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
+				if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
 					/* todo: to issue two probe req??? */
-					issue_probereq23a(padapter, NULL, NULL);
+					issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
 					/* msleep(SURVEY_TO>>1); */
-					issue_probereq23a(padapter, NULL, NULL);
+					issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
 				}
 			}
+
+			if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+				/* todo: to issue two probe req??? */
+				issue_probereq23a(padapter, NULL, NULL);
+				/* msleep(SURVEY_TO>>1); */
+				issue_probereq23a(padapter, NULL, NULL);
+			}
 		}
 
 		set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
 	} else {
-
 		/*	channel number is 0 or this channel is not valid. */
+		pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
 
+		/* switch back to the original channel */
 
-#ifdef CONFIG_8723AU_P2P
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
-		{
-			if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only))
-			{
-				/*	Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
-				/*	This will let the following flow to run the scanning end. */
-				rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
-			}
-		}
-
-		if (rtw_p2p_findphase_ex_is_needed(pwdinfo))
-		{
-			/*	Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
-			set_channel_bwmode23a(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-			rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
-			pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
-
-			initialgain = 0xff; /* restore RX GAIN */
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
-			/* turn on dynamic functions */
-			Restore_DM_Func_Flag23a(padapter);
-			/* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
-
-			mod_timer(&pwdinfo->find_phase_timer, jiffies +
-				  msecs_to_jiffies(pwdinfo->listen_dwell * 100));
-		} else
-#endif /* CONFIG_8723AU_P2P */
-		{
-#ifdef CONFIG_8723AU_P2P
-			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
-				rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-			rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
-#endif /* CONFIG_8723AU_P2P */
-
-			pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
-
-			/* switch back to the original channel */
-
-			set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-
-			/* flush 4-AC Queue after site_survey23a */
-			/* val8 = 0; */
-			/* rtw_hal_set_hwreg23a(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
-
-			/* config MSR */
-			Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
+		set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
+				      pmlmeext->cur_ch_offset,
+				      pmlmeext->cur_bwmode);
 
-			initialgain = 0xff; /* restore RX GAIN */
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
-			/* turn on dynamic functions */
-			Restore_DM_Func_Flag23a(padapter);
-			/* Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
+		/* flush 4-AC Queue after site_survey23a */
+		/* val8 = 0; */
 
-			if (is_client_associated_to_ap23a(padapter) == true)
-			{
-				issue_nulldata23a(padapter, NULL, 0, 3, 500);
+		/* config MSR */
+		Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
 
-			}
+		/* restore RX GAIN */
+		rtl8723a_set_initial_gain(padapter, 0xff);
+		/* turn on dynamic functions */
+		rtl8723a_odm_support_ability_restore(padapter);
 
-			val8 = 0; /* survey done */
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+		if (is_client_associated_to_ap23a(padapter) == true)
+			issue_nulldata23a(padapter, NULL, 0, 3, 500);
 
-			report_surveydone_event23a(padapter);
+		rtl8723a_mlme_sitesurvey(padapter, 0);
 
-			pmlmeext->chan_scan_time = SURVEY_TO;
-			pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
+		report_surveydone_event23a(padapter);
 
-			issue_action_BSSCoexistPacket(padapter);
-			issue_action_BSSCoexistPacket(padapter);
-			issue_action_BSSCoexistPacket(padapter);
+		pmlmeext->chan_scan_time = SURVEY_TO;
+		pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
 
-		}
+		issue_action_BSSCoexistPacket(padapter);
+		issue_action_BSSCoexistPacket(padapter);
+		issue_action_BSSCoexistPacket(padapter);
 	}
 
 	return;
 }
 
 /* collect bss info from Beacon and Probe request/response frames. */
-u8 collect_bss_info23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
+u8 collect_bss_info23a(struct rtw_adapter *padapter,
+		       struct recv_frame *precv_frame,
+		       struct wlan_bssid_ex *bssid)
 {
-	int	i;
-	u32	len;
-	u8	*p;
-	u16	val16;
+	int i, length;
+	const u8 *p;
 	struct sk_buff *skb = precv_frame->pkt;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u8	*pframe = skb->data;
-	u32	packet_len = skb->len;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
+	int packet_len = skb->len;
 	u8 ie_offset;
-	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
-	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+	u16 capab_info;
 
-	len = packet_len - sizeof(struct ieee80211_hdr_3addr);
+	length = packet_len - sizeof(struct ieee80211_hdr_3addr);
 
-	if (len > MAX_IE_SZ)
-	{
+	if (length > MAX_IE_SZ) {
 		/* DBG_8723A("IE too long for survey event\n"); */
 		return _FAIL;
 	}
 
 	memset(bssid, 0, sizeof(struct wlan_bssid_ex));
 
-	if (ieee80211_is_beacon(hdr->frame_control)) {
+	if (ieee80211_is_beacon(mgmt->frame_control)) {
 		bssid->reserved = 1;
-		ie_offset = _BEACON_IE_OFFSET_;
+		ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+		capab_info = mgmt->u.beacon.capab_info;
+	} else  if (ieee80211_is_probe_req(mgmt->frame_control)) {
+		ie_offset = offsetof(struct ieee80211_mgmt,
+				     u.probe_req.variable);
+		bssid->reserved = 2;
+		capab_info = 0;
+	} else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
+		ie_offset = offsetof(struct ieee80211_mgmt,
+				     u.probe_resp.variable);
+		bssid->reserved = 3;
+		capab_info = mgmt->u.probe_resp.capab_info;
 	} else {
-		/*  FIXME : more type */
-		if (ieee80211_is_probe_req(hdr->frame_control)) {
-			ie_offset = _PROBEREQ_IE_OFFSET_;
-			bssid->reserved = 2;
-		} else if (ieee80211_is_probe_resp(hdr->frame_control)) {
-			ie_offset = _PROBERSP_IE_OFFSET_;
-			bssid->reserved = 3;
-		} else {
-			bssid->reserved = 0;
-			ie_offset = _FIXED_IE_LENGTH_;
-		}
+		bssid->reserved = 0;
+		ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+		capab_info = mgmt->u.beacon.capab_info;
 	}
+	ie_offset -= offsetof(struct ieee80211_mgmt, u);
 
-	bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
+	bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + length;
 
 	/* below is to copy the information element */
-	bssid->IELength = len;
-	memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
+	bssid->IELength = length;
+	memcpy(bssid->IEs, &mgmt->u, bssid->IELength);
 
 	/* get the signal strength */
-	bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower; /*  in dBM.raw data */
-	bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
-	bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
+	/*  in dBM.raw data */
+	bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
+	bssid->PhyInfo.SignalQuality =
+		precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
+	bssid->PhyInfo.SignalStrength =
+		precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
 
 	/*  checking SSID */
-	if ((p = rtw_get_ie23a(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset)) == NULL)
-	{
+	p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs + ie_offset,
+			     bssid->IELength - ie_offset);
+
+	if (!p) {
 		DBG_8723A("marc: cannot find SSID for survey event\n");
 		return _FAIL;
 	}
 
-	if (*(p + 1)) {
-		if (len > IEEE80211_MAX_SSID_LEN) {
-			DBG_8723A("%s()-%d: IE too long (%d) for survey "
-				  "event\n", __func__, __LINE__, len);
-			return _FAIL;
-		}
-		memcpy(bssid->Ssid.ssid, (p + 2), *(p + 1));
-		bssid->Ssid.ssid_len = *(p + 1);
-	} else {
-		bssid->Ssid.ssid_len = 0;
+	if (p[1] > IEEE80211_MAX_SSID_LEN) {
+		DBG_8723A("%s()-%d: IE too long (%d) for survey "
+			  "event\n", __func__, __LINE__, p[1]);
+		return _FAIL;
 	}
+	memcpy(bssid->Ssid.ssid, p + 2, p[1]);
+	bssid->Ssid.ssid_len = p[1];
 
 	memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
 
 	/* checking rate info... */
 	i = 0;
-	p = rtw_get_ie23a(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
-	if (p != NULL)
-	{
-		if (len > NDIS_802_11_LENGTH_RATES_EX)
-		{
-			DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+	p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs + ie_offset,
+			     bssid->IELength - ie_offset);
+	if (p) {
+		if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
+			DBG_8723A("%s()-%d: IE too long (%d) for survey "
+				  "event\n", __func__, __LINE__, p[1]);
 			return _FAIL;
 		}
-		memcpy(bssid->SupportedRates, (p + 2), len);
-		i = len;
+		memcpy(bssid->SupportedRates, p + 2, p[1]);
+		i = p[1];
 	}
 
-	p = rtw_get_ie23a(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
-	if (p != NULL)
-	{
-		if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
-		{
-			DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+	p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs + ie_offset,
+			     bssid->IELength - ie_offset);
+	if (p) {
+		if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
+			DBG_8723A("%s()-%d: IE too long (%d) for survey "
+				  "event\n", __func__, __LINE__, p[1]);
 			return _FAIL;
 		}
-		memcpy(bssid->SupportedRates + i, (p + 2), len);
+		memcpy(bssid->SupportedRates + i, p + 2, p[1]);
 	}
 
-	/* todo: */
-	{
-		bssid->NetworkTypeInUse = Ndis802_11OFDM24;
-	}
+	bssid->NetworkTypeInUse = Ndis802_11OFDM24;
 
 	if (bssid->IELength < 12)
 		return _FAIL;
 
 	/*  Checking for DSConfig */
-	p = rtw_get_ie23a(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
+	p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs + ie_offset,
+			     bssid->IELength - ie_offset);
 
 	bssid->Configuration.DSConfig = 0;
 	bssid->Configuration.Length = 0;
 
-	if (p)
-	{
-		bssid->Configuration.DSConfig = *(p + 2);
-	}
-	else
-	{/*  In 5G, some ap do not have DSSET IE */
+	if (p) {
+		bssid->Configuration.DSConfig = p[2];
+	} else {/*  In 5G, some ap do not have DSSET IE */
 		/*  checking HT info for channel */
-		p = rtw_get_ie23a(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
-		if (p)
-		{
-			struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
-			bssid->Configuration.DSConfig = HT_info->primary_channel;
-		}
-		else
-		{ /*  use current channel */
-			bssid->Configuration.DSConfig = rtw_get_oper_ch23a(padapter);
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
+				     bssid->IEs + ie_offset,
+				     bssid->IELength - ie_offset);
+		if (p) {
+			struct HT_info_element *HT_info =
+				(struct HT_info_element *)(p + 2);
+			bssid->Configuration.DSConfig =
+				HT_info->primary_channel;
+		} else { /*  use current channel */
+			bssid->Configuration.DSConfig =
+				rtw_get_oper_ch23a(padapter);
 		}
 	}
 
-	if (ieee80211_is_probe_req(hdr->frame_control)) {
+	if (ieee80211_is_probe_req(mgmt->frame_control)) {
 		/*  FIXME */
 		bssid->InfrastructureMode = Ndis802_11Infrastructure;
-		ether_addr_copy(bssid->MacAddress, hdr->addr2);
+		ether_addr_copy(bssid->MacAddress, mgmt->sa);
 		bssid->Privacy = 1;
 		return _SUCCESS;
 	}
 
-	memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval23a_from_ie(bssid->IEs), 2);
-	bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
-
-	val16 = rtw_get_capability23a(bssid);
+	memcpy(&bssid->Configuration.BeaconPeriod,
+	       rtw_get_beacon_interval23a_from_ie(bssid->IEs), 2);
+	bssid->Configuration.BeaconPeriod =
+		le32_to_cpu(bssid->Configuration.BeaconPeriod);
 
-	if (val16 & BIT(0)) {
+	if (capab_info & BIT(0)) {
 		bssid->InfrastructureMode = Ndis802_11Infrastructure;
-		ether_addr_copy(bssid->MacAddress, hdr->addr2);
+		ether_addr_copy(bssid->MacAddress, mgmt->sa);
 	} else {
 		bssid->InfrastructureMode = Ndis802_11IBSS;
-		ether_addr_copy(bssid->MacAddress, hdr->addr3);
+		ether_addr_copy(bssid->MacAddress, mgmt->bssid);
 	}
 
-	if (val16 & BIT(4))
+	if (capab_info & BIT(4))
 		bssid->Privacy = 1;
 	else
 		bssid->Privacy = 0;
@@ -7941,21 +4627,21 @@ u8 collect_bss_info23a(struct rtw_adapter *padapter, struct recv_frame *precv_fr
 	bssid->Configuration.ATIMWindow = 0;
 
 	/* 20/40 BSS Coexistence check */
-	if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated))
-	{
+	if (pregistrypriv->wifi_spec == 1 &&
+	    pmlmeinfo->bwmode_updated == false) {
 		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-		p = rtw_get_ie23a(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
-		if (p && len > 0) {
-			struct HT_caps_element	*pHT_caps;
-			pHT_caps = (struct HT_caps_element	*)(p + 2);
+		p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
+				     bssid->IEs + ie_offset,
+				     bssid->IELength - ie_offset);
+		if (p && p[1] > 0) {
+			struct HT_caps_element *pHT_caps;
+			pHT_caps = (struct HT_caps_element *)(p + 2);
 
 			if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14))
 				pmlmepriv->num_FortyMHzIntolerant++;
 		} else
-		{
 			pmlmepriv->num_sta_no_ht++;
-		}
 	}
 
 
@@ -7969,8 +4655,6 @@ u8 collect_bss_info23a(struct rtw_adapter *padapter, struct recv_frame *precv_fr
 void start_create_ibss23a(struct rtw_adapter* padapter)
 {
 	unsigned short	caps;
-	u8	val8;
-	u8	join_type;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
@@ -7983,10 +4667,8 @@ void start_create_ibss23a(struct rtw_adapter* padapter)
 	/* udpate capability */
 	caps = rtw_get_capability23a(pnetwork);
 	update_capinfo23a(padapter, caps);
-	if (caps&cap_IBSS)/* adhoc master */
-	{
-		val8 = 0xcf;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+	if (caps&cap_IBSS) {	/* adhoc master */
+		rtl8723a_set_sec_cfg(padapter, 0xcf);
 
 		/* switch channel */
 		/* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
@@ -8008,9 +4690,8 @@ void start_create_ibss23a(struct rtw_adapter* padapter)
 		}
 		else
 		{
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
-			join_type = 0;
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+			hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
+			hw_var_set_mlme_join(padapter, 0);
 
 			report_join_res23a(padapter, 1);
 			pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
@@ -8047,9 +4728,10 @@ void start_clnt_join23a(struct rtw_adapter* padapter)
 
 		Set_MSR23a(padapter, WIFI_FW_STATION_STATE);
 
-		val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
+		val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
+			0xcc: 0xcf;
 
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+		rtl8723a_set_sec_cfg(padapter, val8);
 
 		/* switch channel */
 		/* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
@@ -8062,12 +4744,10 @@ void start_clnt_join23a(struct rtw_adapter* padapter)
 			  msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
 		pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
 	}
-	else if (caps&cap_IBSS) /* adhoc client */
-	{
+	else if (caps&cap_IBSS) {	/* adhoc client */
 		Set_MSR23a(padapter, WIFI_FW_ADHOC_STATE);
 
-		val8 = 0xcf;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+		rtl8723a_set_sec_cfg(padapter, 0xcf);
 
 		/* switch channel */
 		set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
@@ -8158,7 +4838,8 @@ unsigned int receive_disconnect23a(struct rtw_adapter *padapter, unsigned char *
 	return _SUCCESS;
 }
 
-static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *bssid)
+static void process_80211d(struct rtw_adapter *padapter,
+			   struct wlan_bssid_ex *bssid)
 {
 	struct registry_priv *pregistrypriv;
 	struct mlme_ext_priv *pmlmeext;
@@ -8171,10 +4852,8 @@ static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *b
 
 	/*  Adjust channel plan by AP Country IE */
 	if (pregistrypriv->enable80211d &&
-		(!pmlmeext->update_channel_plan_by_ap_done))
-	{
-		u8 *ie, *p;
-		u32 len;
+	    !pmlmeext->update_channel_plan_by_ap_done) {
+		const u8 *ie, *p;
 		struct rt_channel_plan chplan_ap;
 		struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
 		u8 country[4];
@@ -8182,31 +4861,34 @@ static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *b
 		u8 noc; /*  number of channel */
 		u8 j, k;
 
-		ie = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-		if (!ie) return;
-		if (len < 6) return;
+		ie = cfg80211_find_ie(WLAN_EID_COUNTRY,
+				      bssid->IEs + _FIXED_IE_LENGTH_,
+				      bssid->IELength - _FIXED_IE_LENGTH_);
+		if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
+			return;
 
 		ie += 2;
 		p = ie;
-		ie += len;
+		ie += ie[1];
 
-		memset(country, 0, 4);
 		memcpy(country, p, 3);
+		country[3] = '\0';
+
 		p += 3;
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-				("%s: 802.11d country =%s\n", __func__, country));
+			 ("%s: 802.11d country =%s\n", __func__, country));
 
 		i = 0;
-		while ((ie - p) >= 3)
-		{
+		while ((ie - p) >= 3) {
 			fcn = *(p++);
 			noc = *(p++);
 			p++;
 
-			for (j = 0; j < noc; j++)
-			{
-				if (fcn <= 14) channel = fcn + j; /*  2.4 GHz */
-				else channel = fcn + j*4; /*  5 GHz */
+			for (j = 0; j < noc; j++) {
+				if (fcn <= 14)
+					channel = fcn + j; /*  2.4 GHz */
+				else
+					channel = fcn + j * 4; /*  5 GHz */
 
 				chplan_ap.Channel[i++] = channel;
 			}
@@ -8220,45 +4902,55 @@ static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *b
 		i = j = k = 0;
 		if (pregistrypriv->wireless_mode & WIRELESS_11G) {
 			do {
-				if ((i == MAX_CHANNEL_NUM) ||
-					(chplan_sta[i].ChannelNum == 0) ||
-					(chplan_sta[i].ChannelNum > 14))
+				if (i == MAX_CHANNEL_NUM ||
+				    chplan_sta[i].ChannelNum == 0 ||
+				    chplan_sta[i].ChannelNum > 14)
 					break;
 
-				if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
+				if (j == chplan_ap.Len ||
+				    chplan_ap.Channel[j] > 14)
 					break;
 
-				if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
-					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+				if (chplan_sta[i].ChannelNum ==
+				    chplan_ap.Channel[j]) {
+					chplan_new[k].ChannelNum =
+						chplan_ap.Channel[j];
 					chplan_new[k].ScanType = SCAN_ACTIVE;
 					i++;
 					j++;
 					k++;
-				} else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
-					chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-					chplan_new[k].ScanType = SCAN_PASSIVE;
+				} else if (chplan_sta[i].ChannelNum <
+					   chplan_ap.Channel[j]) {
+					chplan_new[k].ChannelNum =
+						chplan_sta[i].ChannelNum;
+					chplan_new[k].ScanType =
+						SCAN_PASSIVE;
 					i++;
 					k++;
-				} else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
-					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
-					chplan_new[k].ScanType = SCAN_ACTIVE;
+				} else if (chplan_sta[i].ChannelNum >
+					   chplan_ap.Channel[j]) {
+					chplan_new[k].ChannelNum =
+						chplan_ap.Channel[j];
+					chplan_new[k].ScanType =
+						SCAN_ACTIVE;
 					j++;
 					k++;
 				}
 			} while (1);
 
 			/*  change AP not support channel to Passive scan */
-			while ((i < MAX_CHANNEL_NUM) &&
-				(chplan_sta[i].ChannelNum != 0) &&
-				(chplan_sta[i].ChannelNum <= 14)) {
-				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+			while (i < MAX_CHANNEL_NUM &&
+			       chplan_sta[i].ChannelNum != 0 &&
+			       chplan_sta[i].ChannelNum <= 14) {
+				chplan_new[k].ChannelNum =
+					chplan_sta[i].ChannelNum;
 				chplan_new[k].ScanType = SCAN_PASSIVE;
 				i++;
 				k++;
 			}
 
 			/*  add channel AP supported */
-			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
+			while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
 				chplan_new[k].ChannelNum = chplan_ap.Channel[j];
 				chplan_new[k].ScanType = SCAN_ACTIVE;
 				j++;
@@ -8266,49 +4958,50 @@ static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *b
 			}
 		} else {
 			/*  keep original STA 2.4G channel plan */
-			while ((i < MAX_CHANNEL_NUM) &&
-				(chplan_sta[i].ChannelNum != 0) &&
-				(chplan_sta[i].ChannelNum <= 14)) {
-				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+			while (i < MAX_CHANNEL_NUM &&
+			       chplan_sta[i].ChannelNum != 0 &&
+			       chplan_sta[i].ChannelNum <= 14) {
+				chplan_new[k].ChannelNum =
+					chplan_sta[i].ChannelNum;
 				chplan_new[k].ScanType = chplan_sta[i].ScanType;
 				i++;
 				k++;
 			}
 
 			/*  skip AP 2.4G channel plan */
-			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
+			while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
 				j++;
-			}
 		}
 
 		if (pregistrypriv->wireless_mode & WIRELESS_11A) {
 			do {
-				if ((i == MAX_CHANNEL_NUM) ||
-				    (chplan_sta[i].ChannelNum == 0))
+				if (i == MAX_CHANNEL_NUM ||
+				    chplan_sta[i].ChannelNum == 0)
 					break;
 
-				if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
+				if (j == chplan_ap.Len ||
+				    chplan_ap.Channel[j] == 0)
 					break;
 
-				if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
-				{
-					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+				if (chplan_sta[i].ChannelNum ==
+				    chplan_ap.Channel[j]) {
+					chplan_new[k].ChannelNum =
+						chplan_ap.Channel[j];
 					chplan_new[k].ScanType = SCAN_ACTIVE;
 					i++;
 					j++;
 					k++;
-				}
-				else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
-				{
-					chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-/*					chplan_new[k].ScanType = chplan_sta[i].ScanType; */
+				} else if (chplan_sta[i].ChannelNum <
+					   chplan_ap.Channel[j]) {
+					chplan_new[k].ChannelNum =
+						chplan_sta[i].ChannelNum;
 					chplan_new[k].ScanType = SCAN_PASSIVE;
 					i++;
 					k++;
-				}
-				else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
-				{
-					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+				} else if (chplan_sta[i].ChannelNum >
+					   chplan_ap.Channel[j]) {
+					chplan_new[k].ChannelNum =
+						chplan_ap.Channel[j];
 					chplan_new[k].ScanType = SCAN_ACTIVE;
 					j++;
 					k++;
@@ -8316,15 +5009,17 @@ static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *b
 			} while (1);
 
 			/*  change AP not support channel to Passive scan */
-			while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
-				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+			while (i < MAX_CHANNEL_NUM &&
+			       chplan_sta[i].ChannelNum != 0) {
+				chplan_new[k].ChannelNum =
+					chplan_sta[i].ChannelNum;
 				chplan_new[k].ScanType = SCAN_PASSIVE;
 				i++;
 				k++;
 			}
 
 			/*  add channel AP supported */
-			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
+			while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
 				chplan_new[k].ChannelNum = chplan_ap.Channel[j];
 				chplan_new[k].ScanType = SCAN_ACTIVE;
 				j++;
@@ -8332,8 +5027,10 @@ static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *b
 			}
 		} else {
 			/*  keep original STA 5G channel plan */
-			while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
-				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+			while (i < MAX_CHANNEL_NUM &&
+			       chplan_sta[i].ChannelNum != 0) {
+				chplan_new[k].ChannelNum =
+					chplan_sta[i].ChannelNum;
 				chplan_new[k].ScanType = chplan_sta[i].ScanType;
 				i++;
 				k++;
@@ -8346,18 +5043,19 @@ static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *b
 	channel = bssid->Configuration.DSConfig;
 	chplan_new = pmlmeext->channel_set;
 	i = 0;
-	while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
-		if (chplan_new[i].ChannelNum == channel)
-		{
+	while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
+		if (chplan_new[i].ChannelNum == channel) {
 			if (chplan_new[i].ScanType == SCAN_PASSIVE) {
-				/* 5G Bnad 2, 3 (DFS) doesn't change to active scan */
+				/* 5G Bnad 2, 3 (DFS) doesn't change
+				   to active scan */
 				if (channel >= 52 && channel <= 144)
 					break;
 
 				chplan_new[i].ScanType = SCAN_ACTIVE;
 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-						 ("%s: change channel %d scan type from passive to active\n",
-						  __func__, channel));
+					 ("%s: change channel %d scan type "
+					  "from passive to active\n",
+					  __func__, channel));
 			}
 			break;
 		}
@@ -8691,17 +5389,14 @@ void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_re
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
 	struct sta_priv		*pstapriv = &padapter->stapriv;
-	u8	join_type;
-	u16 media_status;
 
-	if (join_res < 0)
-	{
-		join_type = 1;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
+	if (join_res < 0) {
+		hw_var_set_mlme_join(padapter, 1);
+		hw_var_set_bssid(padapter, null_addr);
 
 		/* restore to initial setting. */
-		update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
+		update_tx_basic_rate23a(padapter,
+					padapter->registrypriv.wireless_mode);
 
 		goto exit_mlmeext_joinbss_event_callback23a;
 	}
@@ -8719,15 +5414,15 @@ void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_re
 	}
 
 	/* turn on dynamic functions */
-	Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
+	rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
 
 	/*  update IOT-releated issue */
 	update_IOT_info23a(padapter);
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
+	HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
 
 	/* BCN interval */
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
+	rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
 
 	/* udpate capability */
 	update_capinfo23a(padapter, pmlmeinfo->capability);
@@ -8752,18 +5447,13 @@ void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_re
 
 		/* set per sta rate after updating HT cap. */
 		set_sta_rate23a(padapter, psta);
-
-		media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE: 1 means connect */
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
 	}
 
-	join_type = 2;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+	hw_var_set_mlme_join(padapter, 2);
 
-	if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
-	{
+	if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
 		/*  correcting TSF */
-		correct_TSF23a(padapter, pmlmeext);
+		rtw_correct_TSF(padapter);
 
 		/* set_link_timer(pmlmeext, DISCONNECT_TO); */
 	}
@@ -8778,7 +5468,6 @@ void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_
 {
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	u8	join_type;
 
 	DBG_8723A("%s\n", __func__);
 
@@ -8790,11 +5479,8 @@ void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_
 		}
 		else/* adhoc client */
 		{
-			/* update TSF Value */
-			/* update_TSF23a(pmlmeext, pframe, len); */
-
 			/*  correcting TSF */
-			correct_TSF23a(padapter, pmlmeext);
+			rtw_correct_TSF(padapter);
 
 			/* start beacon */
 			if (send_beacon23a(padapter) == _FAIL)
@@ -8810,8 +5496,7 @@ void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_
 
 		}
 
-		join_type = 2;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+		hw_var_set_mlme_join(padapter, 2);
 	}
 
 	pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
@@ -8832,8 +5517,8 @@ void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
 	{
 		/* set_opmode_cmd(padapter, infra_client_with_mlme); */
 
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
+		hw_var_set_mlme_disconnect(padapter);
+		hw_var_set_bssid(padapter, null_addr);
 
 		/* restore to initial setting. */
 		update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
@@ -8919,9 +5604,6 @@ void linked_status_chk23a(struct rtw_adapter *padapter)
 		if ((psta = rtw_get_stainfo23a(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
 		{
 			bool is_p2p_enable = false;
-#ifdef CONFIG_8723AU_P2P
-			is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
-#endif
 
 			if (chk_ap_is_alive(padapter, psta) == false)
 				rx_chk = _FAIL;
@@ -9035,32 +5717,17 @@ static void survey_timer_hdl(unsigned long data)
 	struct sitesurvey_parm *psurveyPara;
 	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif
 
 	/* issue rtw_sitesurvey_cmd23a */
 	if (pmlmeext->sitesurvey_res.state > SCAN_START) {
 		if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
 			pmlmeext->sitesurvey_res.channel_idx++;
 
-		if (pmlmeext->scan_abort == true)
-		{
-#ifdef CONFIG_8723AU_P2P
-			if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
-			{
-				rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
-				pmlmeext->sitesurvey_res.channel_idx = 3;
-				DBG_8723A("%s idx:%d, cnt:%u\n", __func__,
-					  pmlmeext->sitesurvey_res.channel_idx,
-					  pwdinfo->find_phase_state_exchange_cnt);
-			} else
-			#endif
-			{
-				pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
-				DBG_8723A("%s idx:%d\n", __func__,
-					  pmlmeext->sitesurvey_res.channel_idx);
-			}
+		if (pmlmeext->scan_abort == true) {
+			pmlmeext->sitesurvey_res.channel_idx =
+				pmlmeext->sitesurvey_res.ch_num;
+			DBG_8723A("%s idx:%d\n", __func__,
+				  pmlmeext->sitesurvey_res.channel_idx);
 
 			pmlmeext->scan_abort = false;/* reset */
 		}
@@ -9189,27 +5856,19 @@ u8 setopmode_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
 
-	if (psetop->mode == Ndis802_11APMode)
-	{
+	if (psetop->mode == Ndis802_11APMode) {
 		pmlmeinfo->state = WIFI_FW_AP_STATE;
 		type = _HW_STATE_AP_;
-	}
-	else if (psetop->mode == Ndis802_11Infrastructure)
-	{
+	} else if (psetop->mode == Ndis802_11Infrastructure) {
 		pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
 		pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to	STATION_STATE */
 		type = _HW_STATE_STATION_;
-	}
-	else if (psetop->mode == Ndis802_11IBSS)
-	{
+	} else if (psetop->mode == Ndis802_11IBSS)
 		type = _HW_STATE_ADHOC_;
-	}
 	else
-	{
 		type = _HW_STATE_NOLINK_;
-	}
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
+	hw_var_set_opmode(padapter, type);
 	/* Set_NETYPE0_MSR(padapter, type); */
 
 	return H2C_SUCCESS;
@@ -9249,12 +5908,10 @@ u8 createbss_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 		pmlmeinfo->candidate_tid_bitmap = 0;
 
 		/* disable dynamic functions, such as high power, DIG */
-		Save_DM_Func_Flag23a(padapter);
-		Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false);
+		rtl8723a_odm_support_ability_backup(padapter);
 
-		/* config the initial gain under linking, need to write the BB registers */
-		/* initialgain = 0x1E; */
-		/* rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
+		rtl8723a_odm_support_ability_clr(padapter,
+						 DYNAMIC_FUNC_DISABLE);
 
 		/* cancel link timer */
 		del_timer_sync(&pmlmeext->link_timer);
@@ -9275,7 +5932,6 @@ u8 createbss_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 
 u8 join_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 {
-	u8	join_type;
 	struct ndis_802_11_var_ies *	pIE;
 	struct registry_priv	*pregpriv = &padapter->registrypriv;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
@@ -9305,7 +5961,7 @@ u8 join_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 		/* Set_MSR23a(padapter, _HW_STATE_NOLINK_); */
 		Set_MSR23a(padapter, _HW_STATE_STATION_);
 
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+		hw_var_set_mlme_disconnect(padapter);
 	}
 
 	rtw_joinbss_reset23a(padapter);
@@ -9337,16 +5993,16 @@ u8 join_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 
 		switch (pIE->ElementID)
 		{
-		case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
+		case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
 			if (!memcmp(pIE->data, WMM_OUI23A, 4))
 				pmlmeinfo->WMM_enable = 1;
 			break;
 
-		case _HT_CAPABILITY_IE_:	/* Get HT Cap IE. */
+		case WLAN_EID_HT_CAPABILITY:	/* Get HT Cap IE. */
 			pmlmeinfo->HT_caps_enable = 1;
 			break;
 
-		case _HT_EXTRA_INFO_IE_:	/* Get HT Info IE. */
+		case WLAN_EID_HT_OPERATION:	/* Get HT Info IE. */
 			pmlmeinfo->HT_info_enable = 1;
 
 			/* spec case only for cisco's ap because cisco's ap
@@ -9385,19 +6041,9 @@ u8 join_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 
 		i += (pIE->Length + 2);
 	}
-	/* disable dynamic functions, such as high power, DIG */
-	/* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
-
-	/* config the initial gain under linking, need to write the BB
-	   registers */
-	/* initialgain = 0x1E; */
-	/* rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN,
-	   (u8 *)(&initialgain)); */
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID,
-			  pmlmeinfo->network.MacAddress);
-	join_type = 0;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+	hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
+	hw_var_set_mlme_join(padapter, 0);
 
 	/* cancel link timer */
 	del_timer_sync(&pmlmeext->link_timer);
@@ -9413,7 +6059,6 @@ u8 disconnect_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
-	u8	val8;
 
 	if (is_client_associated_to_ap23a(padapter))
 	{
@@ -9424,18 +6069,15 @@ u8 disconnect_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
 
 	/* pmlmeinfo->state = WIFI_FW_NULL_STATE; */
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
+	hw_var_set_mlme_disconnect(padapter);
+	hw_var_set_bssid(padapter, null_addr);
 
 	/* restore to initial setting. */
 	update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
 
-	if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
-	{
-		/* Stop BCN */
-		val8 = 0;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
-	}
+	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
+	    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
+		rtl8723a_set_bcn_func(padapter, 0);	/* Stop BCN */
 
 	/* set MSR to no link state -> infra. mode */
 	Set_MSR23a(padapter, _HW_STATE_STATION_);
@@ -9527,14 +6169,10 @@ u8 sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
 	u8 bdelayscan = false;
-	u8 val8;
 	u32 initialgain;
 	u32 i;
 
 	if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
-		/* for first time sitesurvey_cmd */
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_CHECK_TXBUF, NULL);
-
 		pmlmeext->sitesurvey_res.state = SCAN_START;
 		pmlmeext->sitesurvey_res.bss_cnt = 0;
 		pmlmeext->sitesurvey_res.channel_idx = 0;
@@ -9582,25 +6220,23 @@ u8 sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 	if ((pmlmeext->sitesurvey_res.state == SCAN_START) ||
 	    (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
 		/* disable dynamic functions, such as high power, DIG */
-		Save_DM_Func_Flag23a(padapter);
-		Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false);
+		rtl8723a_odm_support_ability_backup(padapter);
+		rtl8723a_odm_support_ability_clr(padapter,
+						 DYNAMIC_FUNC_DISABLE);
 
 		/* config the initial gain under scaning, need to
 		   write the BB registers */
-		if ((wdev_to_priv(padapter->rtw_wdev))->p2p_enabled == true) {
+		if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
 			initialgain = 0x30;
-		} else
+		else
 			initialgain = 0x1E;
 
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN,
-				  (u8 *)(&initialgain));
+		rtl8723a_set_initial_gain(padapter, initialgain);
 
 		/* set MSR to no link state */
 		Set_MSR23a(padapter, _HW_STATE_NOLINK_);
 
-		val8 = 1; /* under site survey */
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY,
-				  (u8 *)(&val8));
+		rtl8723a_mlme_sitesurvey(padapter, 1);
 
 		pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
 	}
@@ -9641,10 +6277,10 @@ u8 setkey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 
 	DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
 			"keyid:%d\n", pparm->algorithm, pparm->keyid);
-	write_cam23a(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
+	rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
 
 	/* allow multicast packets to driver */
-        padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
+	rtl8723a_on_rcr_am(padapter);
 
 	return H2C_SUCCESS;
 }
@@ -9705,7 +6341,8 @@ u8 set_stakey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 						pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
 						pparm->addr[5], cam_id);
 
-			write_cam23a(padapter, cam_id, ctrl, pparm->addr, pparm->key);
+			rtl8723a_cam_write(padapter, cam_id, ctrl,
+					   pparm->addr, pparm->key);
 
 			return H2C_SUCCESS_RSP;
 
@@ -9728,7 +6365,7 @@ u8 set_stakey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
 
 	ctrl = BIT(15) | ((pparm->algorithm) << 2);
 
-	write_cam23a(padapter, cam_id, ctrl, pparm->addr, pparm->key);
+	rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
 
 	pmlmeinfo->enc_algo = pparm->algorithm;
 
diff --git a/drivers/staging/rtl8723au/core/rtw_p2p.c b/drivers/staging/rtl8723au/core/rtw_p2p.c
deleted file mode 100644
index 27a6cc76973d..000000000000
--- a/drivers/staging/rtl8723au/core/rtw_p2p.c
+++ /dev/null
@@ -1,4001 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- ******************************************************************************/
-#define _RTW_P2P_C_
-
-#include <drv_types.h>
-#include <rtw_p2p.h>
-#include <wifi.h>
-
-#ifdef CONFIG_8723AU_P2P
-
-static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8* ch_list, u8 ch_cnt)
-{
-	int found = 0, i = 0;
-
-	for (i = 0; i < ch_cnt; i++)
-	{
-		if (ch_list[ i ] == desired_ch)
-		{
-			found = 1;
-			break;
-		}
-	}
-	return found;
-}
-
-static int is_any_client_associated(struct rtw_adapter *padapter)
-{
-	return padapter->stapriv.asoc_list_cnt ? true : false;
-}
-
-static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	struct list_head *phead, *plist;
-	u32 len = 0;
-	u16 attr_len = 0;
-	u8 tmplen, *pdata_attr, *pstart, *pcur;
-	struct sta_info *psta;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct sta_priv *pstapriv = &padapter->stapriv;
-
-	DBG_8723A("%s\n", __func__);
-
-	pdata_attr = kzalloc(MAX_P2P_IE_LEN, GFP_ATOMIC);
-
-	pstart = pdata_attr;
-	pcur = pdata_attr;
-
-	spin_lock_bh(&pstapriv->asoc_list_lock);
-	phead = &pstapriv->asoc_list;
-
-	list_for_each(plist, phead) {
-		psta = container_of(plist, struct sta_info, asoc_list);
-
-		if (psta->is_p2p_device)
-		{
-			tmplen = 0;
-
-			pcur++;
-
-			/* P2P device address */
-			memcpy(pcur, psta->dev_addr, ETH_ALEN);
-			pcur += ETH_ALEN;
-
-			/* P2P interface address */
-			memcpy(pcur, psta->hwaddr, ETH_ALEN);
-			pcur += ETH_ALEN;
-
-			*pcur = psta->dev_cap;
-			pcur++;
-
-			/* u16*)(pcur) = cpu_to_be16(psta->config_methods); */
-			put_unaligned_be16(psta->config_methods, pcur);
-			pcur += 2;
-
-			memcpy(pcur, psta->primary_dev_type, 8);
-			pcur += 8;
-
-			*pcur = psta->num_of_secdev_type;
-			pcur++;
-
-			memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type*8);
-			pcur += psta->num_of_secdev_type*8;
-
-			if (psta->dev_name_len>0)
-			{
-				/* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
-				put_unaligned_be16(WPS_ATTR_DEVICE_NAME, pcur);
-				pcur += 2;
-
-				/* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */
-				put_unaligned_be16(psta->dev_name_len, pcur);
-				pcur += 2;
-
-				memcpy(pcur, psta->dev_name, psta->dev_name_len);
-				pcur += psta->dev_name_len;
-			}
-
-			tmplen = (u8)(pcur-pstart);
-
-			*pstart = (tmplen-1);
-
-			attr_len += tmplen;
-
-			/* pstart += tmplen; */
-			pstart = pcur;
-
-		}
-
-	}
-	spin_unlock_bh(&pstapriv->asoc_list_lock);
-
-	if (attr_len>0)
-	{
-		len = rtw_set_p2p_attr_content23a(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
-	}
-
-	kfree(pdata_attr);
-
-	return len;
-}
-
-static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
-{
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
-	u32	p2poui = cpu_to_be32(P2POUI);
-	u8	oui_subtype = P2P_GO_DISC_REQUEST;
-	u8	dialogToken = 0;
-
-	DBG_8723A("[%s]\n", __func__);
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-	{
-		return;
-	}
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	/* Build P2P action frame header */
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	/* there is no IE in this P2P action frame */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-}
-
-static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
-{
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8			action = P2P_PUB_ACTION_ACTION;
-	u32			p2poui = cpu_to_be32(P2POUI);
-	u8			oui_subtype = P2P_DEVDISC_RESP;
-	u8 p2pie[8] = { 0x00 };
-	u32 p2pielen = 0;
-
-	DBG_8723A("[%s]\n", __func__);
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-	{
-		return;
-	}
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	/* Build P2P public action frame header */
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	/* Build P2P IE */
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[ p2pielen++ ] = 0x50;
-	p2pie[ p2pielen++ ] = 0x6F;
-	p2pie[ p2pielen++ ] = 0x9A;
-	p2pie[ p2pielen++ ] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*  P2P_ATTR_STATUS */
-	p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-}
-
-static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8* raddr, u8* frame_body, u16 config_method)
-{
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8			action = P2P_PUB_ACTION_ACTION;
-	u8			dialogToken = frame_body[7];	/*	The Dialog Token of provisioning discovery request frame. */
-	u32			p2poui = cpu_to_be32(P2POUI);
-	u8			oui_subtype = P2P_PROVISION_DISC_RESP;
-	u8			wpsie[ 100 ] = { 0x00 };
-	u8			wpsielen = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32					wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-		return;
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	wpsielen = 0;
-	/*	WPS OUI */
-	/* u32*) (wpsie) = cpu_to_be32(WPSOUI); */
-	put_unaligned_be32(WPSOUI, wpsie);
-	wpsielen += 4;
-
-	/*	Config Method */
-	/*	Type: */
-	/* u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); */
-	put_unaligned_be16(WPS_ATTR_CONF_METHOD, wpsie + wpsielen);
-	wpsielen += 2;
-
-	/*	Length: */
-	/* u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002); */
-	put_unaligned_be16(0x0002, wpsie + wpsielen);
-	wpsielen += 2;
-
-	/*	Value: */
-	/* u16*) (wpsie + wpsielen) = cpu_to_be16(config_method); */
-	put_unaligned_be16(config_method, wpsie + wpsielen);
-	wpsielen += 2;
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-
-	return;
-}
-
-static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
-{
-	struct xmit_frame			*pmgntframe;
-	struct pkt_attrib			*pattrib;
-	unsigned char					*pframe;
-	struct ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
-	u32	p2poui = cpu_to_be32(P2POUI);
-	u8	oui_subtype = P2P_PRESENCE_RESPONSE;
-	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
-	u8 noa_attr_content[32] = { 0x00 };
-	u32 p2pielen = 0;
-
-	DBG_8723A("[%s]\n", __func__);
-
-	if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
-	{
-		return;
-	}
-
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	fctrl = &pwlanhdr->frame_control;
-	*fctrl = 0;
-
-	memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-	memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	/* Build P2P action frame header */
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
-				     &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	/* Add P2P IE header */
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[ p2pielen++ ] = 0x50;
-	p2pie[ p2pielen++ ] = 0x6F;
-	p2pie[ p2pielen++ ] = 0x9A;
-	p2pie[ p2pielen++ ] = 0x09;	/*	WFA P2P v1.0 */
-
-	/* Add Status attribute in P2P IE */
-	p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
-
-	/* Add NoA attribute in P2P IE */
-	noa_attr_content[0] = 0x1;/* index */
-	noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
-
-	/* todo: Notice of Absence Descriptor(s) */
-
-	p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie,
-			       &pattrib->pktlen);
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	dump_mgntframe23a(padapter, pmgntframe);
-}
-
-u32 build_beacon_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
-	u16 capability = 0;
-	u32 len = 0, p2pielen = 0;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[ p2pielen++ ] = 0x50;
-	p2pie[ p2pielen++ ] = 0x6F;
-	p2pie[ p2pielen++ ] = 0x9A;
-	p2pie[ p2pielen++ ] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. P2P Device ID */
-	/*	3. Notice of Absence (NOA) */
-
-	/*	P2P Capability ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	/*	Be able to participate in additional P2P Groups and */
-	/*	support the P2P Invitation Procedure */
-	/*	Group Capability Bitmap, 1 byte */
-	capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY;
-	capability |=  ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
-		capability |= (P2P_GRPCAP_GROUP_FORMATION<<8);
-
-	capability = cpu_to_le16(capability);
-
-	p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8*)&capability);
-
-	/*  P2P Device ID ATTR */
-	p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
-
-	/*  Notice of Absence ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-
-	/* go_add_noa_attr(pwdinfo); */
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
-
-	return len;
-}
-
-#ifdef CONFIG_8723AU_P2P
-u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110812 */
-	/*	According to the WFD Specification, the beacon frame should contain 4 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID */
-	/*	3. Coupled Sink Information */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-
-	if (P2P_ROLE_GO == pwdinfo->role)
-	{
-		if (is_any_client_associated(pwdinfo->padapter))
-		{
-			/*	WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */
-			put_unaligned_be16(pwfd_info->wfd_device_type |
-					   WFD_DEVINFO_WSD, wfdie + wfdielen);
-		}
-		else
-		{
-			/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-			put_unaligned_be16(pwfd_info->wfd_device_type |
-					   WFD_DEVINFO_SESSION_AVAIL |
-					   WFD_DEVINFO_WSD, wfdie + wfdielen);
-		}
-
-	}
-	else
-	{
-		/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-		put_unaligned_be16(pwfd_info->wfd_device_type |
-				   WFD_DEVINFO_SESSION_AVAIL |
-				   WFD_DEVINFO_WSD, wfdie + wfdielen);
-	}
-
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110812 */
-	/*	According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID */
-	/*	3. Coupled Sink Information */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-
-	if (1 == pwdinfo->wfd_tdls_enable)
-	{
-		/*	WFD primary sink + available for WFD session + WiFi TDLS mode + WSC (WFD Service Discovery) */
-		put_unaligned_be16(pwfd_info->wfd_device_type |
-				   WFD_DEVINFO_SESSION_AVAIL |
-				   WFD_DEVINFO_WSD |
-				   WFD_DEVINFO_PC_TDLS, wfdie + wfdielen);
-	}
-	else
-	{
-		/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSC (WFD Service Discovery) */
-		put_unaligned_be16(pwfd_info->wfd_device_type |
-				   WFD_DEVINFO_SESSION_AVAIL |
-				   WFD_DEVINFO_WSD, wfdie + wfdielen);
-	}
-
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110812 */
-	/*	According to the WFD Specification, the probe response frame should contain 4 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID */
-	/*	3. Coupled Sink Information */
-	/*	4. WFD Session Information */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + available for WFD session + WiFi Direct mode */
-
-	if (true == pwdinfo->session_available)
-	{
-		if (P2P_ROLE_GO == pwdinfo->role)
-		{
-			if (is_any_client_associated(pwdinfo->padapter))
-			{
-				if (pwdinfo->wfd_tdls_enable)
-				{
-					/*	TDLS mode + WSD (WFD Service Discovery) */
-					put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
-				}
-				else
-				{
-					/*	WiFi Direct mode + WSD (WFD Service Discovery) */
-					put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
-				}
-			}
-			else
-			{
-				if (pwdinfo->wfd_tdls_enable)
-				{
-					/*	available for WFD session + TDLS mode + WSD (WFD Service Discovery) */
-					put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
-				}
-				else
-				{
-					/*	available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-					put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
-				}
-			}
-		}
-		else
-		{
-			if (pwdinfo->wfd_tdls_enable)
-			{
-				/*	available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-				put_unaligned_be16(pwfd_info->wfd_device_type |
-						   WFD_DEVINFO_SESSION_AVAIL |
-						   WFD_DEVINFO_WSD |
-						   WFD_DEVINFO_PC_TDLS |
-						   WFD_DEVINFO_HDCP_SUPPORT,
-						   wfdie + wfdielen);
-			}
-			else
-			{
-
-				/*	available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-				put_unaligned_be16(pwfd_info->wfd_device_type |
-						   WFD_DEVINFO_SESSION_AVAIL |
-						   WFD_DEVINFO_WSD |
-						   WFD_DEVINFO_HDCP_SUPPORT,
-						   wfdie + wfdielen);
-			}
-		}
-	}
-	else
-	{
-		if (pwdinfo->wfd_tdls_enable)
-		{
-			put_unaligned_be16(pwfd_info->wfd_device_type |
-					   WFD_DEVINFO_WSD |
-					   WFD_DEVINFO_PC_TDLS |
-					   WFD_DEVINFO_HDCP_SUPPORT,
-					   wfdie + wfdielen);
-		}
-		else
-		{
-			put_unaligned_be16(pwfd_info->wfd_device_type |
-					   WFD_DEVINFO_WSD |
-					   WFD_DEVINFO_HDCP_SUPPORT,
-					   wfdie + wfdielen);
-		}
-
-	}
-
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-	{
-		/*	WFD Session Information ATTR */
-		/*	Type: */
-		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
-
-		/*	Length: */
-		/*	Note: In the WFD specification, the size of length field is 2. */
-		put_unaligned_be16(0x0000, wfdie + wfdielen);
-		wfdielen += 2;
-
-		/*	Todo: to add the list of WFD device info descriptor in WFD group. */
-
-	}
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter					*padapter = NULL;
-	struct mlme_priv			*pmlmepriv = NULL;
-	struct wifi_display_info		*pwfd_info = NULL;
-
-	/*	WFD OUI */
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
-	{
-		return 0;
-	}
-
-	padapter = pwdinfo->padapter;
-	pmlmepriv = &padapter->mlmepriv;
-	pwfd_info = padapter->wdinfo.wfd_info;
-
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110812 */
-	/*	According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID */
-	/*	3. Coupled Sink Information */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_SESSION_AVAIL |
-			   WFD_DEVINFO_WSD, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110812 */
-	/*	According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID */
-	/*	3. Coupled Sink Information */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_SESSION_AVAIL |
-			   WFD_DEVINFO_WSD, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110825 */
-	/*	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID (Optional) */
-	/*	3. Local IP Adress (Optional) */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL,
-			   wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110825 */
-	/*	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID (Optional) */
-	/*	3. Local IP Adress (Optional) */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL,
-			   wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110825 */
-	/*	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID (Optional) */
-	/*	3. Local IP Adress (Optional) */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
-	put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD |
-			   WFD_DEVINFO_SESSION_AVAIL, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110825 */
-	/*	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID (Optional) */
-	/*	3. Local IP Adress (Optional) */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
-			   wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	if (P2P_ROLE_GO == pwdinfo->role)
-	{
-		/*	WFD Session Information ATTR */
-		/*	Type: */
-		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
-
-		/*	Length: */
-		/*	Note: In the WFD specification, the size of length field is 2. */
-		put_unaligned_be16(0x0000, wfdie + wfdielen);
-		wfdielen += 2;
-
-		/*	Todo: to add the list of WFD device info descriptor in WFD group. */
-
-	}
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110825 */
-	/*	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID (Optional) */
-	/*	3. Local IP Adress (Optional) */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
-			   wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	if (P2P_ROLE_GO == pwdinfo->role)
-	{
-		/*	WFD Session Information ATTR */
-		/*	Type: */
-		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
-
-		/*	Length: */
-		/*	Note: In the WFD specification, the size of length field is 2. */
-		put_unaligned_be16(0x0000, wfdie + wfdielen);
-		wfdielen += 2;
-
-		/*	Todo: to add the list of WFD device info descriptor in WFD group. */
-
-	}
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110825 */
-	/*	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID (Optional) */
-	/*	3. Local IP Adress (Optional) */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
-			   wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
-	u32 len = 0, wfdielen = 0;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
-
-	/*	WFD OUI */
-	wfdielen = 0;
-	wfdie[ wfdielen++ ] = 0x50;
-	wfdie[ wfdielen++ ] = 0x6F;
-	wfdie[ wfdielen++ ] = 0x9A;
-	wfdie[ wfdielen++ ] = 0x0A;	/*	WFA WFD v1.0 */
-
-	/*	Commented by Albert 20110825 */
-	/*	According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */
-	/*	1. WFD Device Information */
-	/*	2. Associated BSSID (Optional) */
-	/*	3. Local IP Adress (Optional) */
-
-	/*	WFD Device Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value1: */
-	/*	WFD device information */
-	/*	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
-	put_unaligned_be16(pwfd_info->wfd_device_type |
-			   WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
-			   wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value2: */
-	/*	Session Management Control Port */
-	/*	Default TCP port for RTSP messages is 554 */
-	put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value3: */
-	/*	WFD Device Maximum Throughput */
-	/*	300Mbps is the maximum throughput */
-	put_unaligned_be16(300, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Associated BSSID ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0006, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Associated BSSID */
-	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-	{
-		memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
-	}
-	else
-	{
-		memset(wfdie + wfdielen, 0x00, ETH_ALEN);
-	}
-
-	wfdielen += ETH_ALEN;
-
-	/*	Coupled Sink Information ATTR */
-	/*	Type: */
-	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
-
-	/*	Length: */
-	/*	Note: In the WFD specification, the size of length field is 2. */
-	put_unaligned_be16(0x0007, wfdie + wfdielen);
-	wfdielen += 2;
-
-	/*	Value: */
-	/*	Coupled Sink Status bitmap */
-	/*	Not coupled/available for Coupling */
-	wfdie[ wfdielen++ ] = 0;
-	/*   MAC Addr. */
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-	wfdie[ wfdielen++ ] = 0;
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
-
-	return len;
-}
-
-#endif /* CONFIG_8723AU_P2P */
-
-u32 build_probe_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
-	u32 len = 0, p2pielen = 0;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[ p2pielen++ ] = 0x50;
-	p2pie[ p2pielen++ ] = 0x6F;
-	p2pie[ p2pielen++ ] = 0x9A;
-	p2pie[ p2pielen++ ] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20100907 */
-	/*	According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. Extended Listen Timing */
-	/*	3. Notice of Absence (NOA)	(Only GO needs this) */
-	/*	4. Device Info */
-	/*	5. Group Info	(Only GO need this) */
-
-	/*	P2P Capability ATTR */
-	/*	Type: */
-	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
-	put_unaligned_le16(0x0002, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-	{
-		p2pie[ p2pielen ] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
-
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
-			p2pie[ p2pielen ] |= P2P_GRPCAP_GROUP_FORMATION;
-
-		p2pielen++;
-	}
-	else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
-	{
-		/*	Group Capability Bitmap, 1 byte */
-		if (pwdinfo->persistent_supported)
-			p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
-		else
-			p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
-	}
-
-	/*	Extended Listen Timing ATTR */
-	/*	Type: */
-	p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */
-	put_unaligned_le16(0x0004, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Availability Period */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
-	put_unaligned_le16(0xFFFF, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Availability Interval */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
-	put_unaligned_le16(0xFFFF, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*  Notice of Absence ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-	{
-		/* go_add_noa_attr(pwdinfo); */
-	}
-
-	/*	Device Info ATTR */
-	/*	Type: */
-	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
-	put_unaligned_le16(21 + pwdinfo->device_name_len, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */
-	put_unaligned_be16(pwdinfo->supported_wps_cm, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
-	put_unaligned_be16(WPS_PDT_CID_MULIT_MEDIA, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	OUI */
-	/* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
-	put_unaligned_be32(WPSOUI, p2pie + p2pielen);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
-	put_unaligned_be16(WPS_PDT_SCID_MEDIA_SERVER, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[ p2pielen++ ] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
-	put_unaligned_be16(WPS_ATTR_DEVICE_NAME, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
-	put_unaligned_be16(pwdinfo->device_name_len, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	/*  Group Info ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-	{
-		p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
-	}
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
-
-	return len;
-}
-
-u32 build_prov_disc_request_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8* pssid, u8 ussidlen, u8* pdev_raddr)
-{
-	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
-	u32 len = 0, p2pielen = 0;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[ p2pielen++ ] = 0x50;
-	p2pie[ p2pielen++ ] = 0x6F;
-	p2pie[ p2pielen++ ] = 0x9A;
-	p2pie[ p2pielen++ ] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*	Commented by Albert 20110301 */
-	/*	According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
-	/*	1. P2P Capability */
-	/*	2. Device Info */
-	/*	3. Group ID (When joining an operating P2P Group) */
-
-	/*	P2P Capability ATTR */
-	/*	Type: */
-	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
-	put_unaligned_le16(0x0002, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	Device Capability Bitmap, 1 byte */
-	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
-
-	/*	Group Capability Bitmap, 1 byte */
-	if (pwdinfo->persistent_supported)
-		p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
-	else
-		p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
-
-	/*	Device Info ATTR */
-	/*	Type: */
-	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
-
-	/*	Length: */
-	/*	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
-	/*	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
-	/* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
-	put_unaligned_le16(21 + pwdinfo->device_name_len, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Value: */
-	/*	P2P Device Address */
-	memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
-	p2pielen += ETH_ALEN;
-
-	/*	Config Method */
-	/*	This field should be big endian. Noted by P2P specification. */
-	if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
-	{
-		/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */
-		put_unaligned_be16(WPS_CONFIG_METHOD_PBC, p2pie + p2pielen);
-	}
-	else
-	{
-		/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */
-		put_unaligned_be16(WPS_CONFIG_METHOD_DISPLAY, p2pie + p2pielen);
-	}
-
-	p2pielen += 2;
-
-	/*	Primary Device Type */
-	/*	Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
-	put_unaligned_be16(WPS_PDT_CID_MULIT_MEDIA, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	OUI */
-	/* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
-	put_unaligned_be32(WPSOUI, p2pie + p2pielen);
-	p2pielen += 4;
-
-	/*	Sub Category ID */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
-	put_unaligned_be16(WPS_PDT_SCID_MEDIA_SERVER, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Number of Secondary Device Types */
-	p2pie[ p2pielen++ ] = 0x00;	/*	No Secondary Device Type List */
-
-	/*	Device Name */
-	/*	Type: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
-	put_unaligned_be16(WPS_ATTR_DEVICE_NAME, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Length: */
-	/* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
-	put_unaligned_be16(pwdinfo->device_name_len, p2pie + p2pielen);
-	p2pielen += 2;
-
-	/*	Value: */
-	memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
-	p2pielen += pwdinfo->device_name_len;
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
-	{
-		/*	Added by Albert 2011/05/19 */
-		/*	In this case, the pdev_raddr is the device address of the group owner. */
-
-		/*	P2P Group ID ATTR */
-		/*	Type: */
-		p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
-
-		/*	Length: */
-		/* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */
-		put_unaligned_le16(ETH_ALEN + ussidlen, p2pie + p2pielen);
-		p2pielen += 2;
-
-		/*	Value: */
-		memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
-		p2pielen += ETH_ALEN;
-
-		memcpy(p2pie + p2pielen, pssid, ussidlen);
-		p2pielen += ussidlen;
-
-	}
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
-
-	return len;
-}
-
-u32 build_assoc_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
-{
-	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
-	u32 len = 0, p2pielen = 0;
-
-	/*	P2P OUI */
-	p2pielen = 0;
-	p2pie[ p2pielen++ ] = 0x50;
-	p2pie[ p2pielen++ ] = 0x6F;
-	p2pie[ p2pielen++ ] = 0x9A;
-	p2pie[ p2pielen++ ] = 0x09;	/*	WFA P2P v1.0 */
-
-	/*  According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
-	/*	1. Status */
-	/*	2. Extended Listen Timing (optional) */
-
-	/*	Status ATTR */
-	p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
-
-	/*  Extended Listen Timing ATTR */
-	/*	Type: */
-	/*	Length: */
-	/*	Value: */
-
-	pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
-
-	return len;
-}
-
-u32 build_deauth_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
-{
-	u32 len = 0;
-
-	return len;
-}
-
-u32 process_probe_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	u8 *p;
-	u32 ret = false;
-	u8 *p2pie;
-	u32	p2pielen = 0;
-	int ssid_len = 0, rate_cnt = 0;
-
-	p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
-			len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
-
-	if (rate_cnt <= 4)
-	{
-		int i, g_rate = 0;
-
-		for (i = 0; i < rate_cnt; i++)
-		{
-			if (((*(p + 2 + i) & 0xff) != 0x02) &&
-				((*(p + 2 + i) & 0xff) != 0x04) &&
-				((*(p + 2 + i) & 0xff) != 0x0B) &&
-				((*(p + 2 + i) & 0xff) != 0x16))
-			{
-				g_rate = 1;
-			}
-		}
-
-		if (g_rate == 0)
-		{
-			/*	There is no OFDM rate included in SupportedRates IE of this probe request frame */
-			/*	The driver should response this probe request. */
-			return ret;
-		}
-	}
-	else
-	{
-		/*	rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
-		/*	We should proceed the following check for this probe request. */
-	}
-
-	/*	Added comments by Albert 20100906 */
-	/*	There are several items we should check here. */
-	/*	1. This probe request frame must contain the P2P IE. (Done) */
-	/*	2. This probe request frame must contain the wildcard SSID. (Done) */
-	/*	3. Wildcard BSSID. (Todo) */
-	/*	4. Destination Address. (Done in mgt_dispatcher23a function) */
-	/*	5. Requested Device Type in WSC IE. (Todo) */
-	/*	6. Device ID attribute in P2P IE. (Todo) */
-
-	p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
-			len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
-
-	ssid_len &= 0xff;	/*	Just last 1 byte is valid for ssid len of the probe request */
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-	{
-		if ((p2pie = rtw_get_p2p_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_, NULL, &p2pielen)))
-		{
-			if ((p) && !memcmp((void *)(p+2), (void *)pwdinfo->p2p_wildcard_ssid, 7))
-			{
-				/* todo: */
-				/* Check Requested Device Type attributes in WSC IE. */
-				/* Check Device ID attribute in P2P IE */
-
-				ret = true;
-			}
-			else if ((p != NULL) && (ssid_len == 0))
-			{
-				ret = true;
-			}
-		}
-		else
-		{
-			/* non -p2p device */
-		}
-
-	}
-
-	return ret;
-}
-
-u32 process_assoc_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
-{
-	u8 status_code = P2P_STATUS_SUCCESS;
-	u8 *pbuf, *pattr_content = NULL;
-	u32 attr_contentlen = 0;
-	u16 cap_attr = 0;
-	unsigned short ie_offset;
-	u8 * ies;
-	u32 ies_len;
-	u8 * p2p_ie;
-	u32	p2p_ielen = 0;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
-
-	if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-		return P2P_STATUS_FAIL_REQUEST_UNABLE;
-
-	if (ieee80211_is_assoc_req(hdr->frame_control))
-		ie_offset = _ASOCREQ_IE_OFFSET_;
-	else /*  WIFI_REASSOCREQ */
-		ie_offset = _REASOCREQ_IE_OFFSET_;
-
-	ies = pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset;
-	ies_len = len - sizeof(struct ieee80211_hdr_3addr) - ie_offset;
-
-	p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
-
-	if (!p2p_ie)
-	{
-		DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
-		status_code =  P2P_STATUS_FAIL_INVALID_PARAM;
-	}
-	else
-	{
-		DBG_8723A("[%s] P2P IE Found!!\n", __func__);
-	}
-
-	while (p2p_ie)
-	{
-		/* Check P2P Capability ATTR */
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen))
-		{
-			DBG_8723A("[%s] Got P2P Capability Attr!!\n", __func__);
-			cap_attr = le16_to_cpu(cap_attr);
-			psta->dev_cap = cap_attr&0xff;
-		}
-
-		/* Check Extended Listen Timing ATTR */
-
-		/* Check P2P Device Info ATTR */
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint*)&attr_contentlen))
-		{
-			DBG_8723A("[%s] Got P2P DEVICE INFO Attr!!\n", __func__);
-			pattr_content = pbuf = kzalloc(attr_contentlen,
-						       GFP_ATOMIC);
-			if (pattr_content) {
-				u8 num_of_secdev_type;
-				u16 dev_name_len;
-
-				rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, pattr_content, (uint*)&attr_contentlen);
-
-				memcpy(psta->dev_addr,	pattr_content, ETH_ALEN);/* P2P Device Address */
-
-				pattr_content += ETH_ALEN;
-
-				memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */
-				psta->config_methods = be16_to_cpu(psta->config_methods);
-
-				pattr_content += 2;
-
-				memcpy(psta->primary_dev_type, pattr_content, 8);
-
-				pattr_content += 8;
-
-				num_of_secdev_type = *pattr_content;
-				pattr_content += 1;
-
-				if (num_of_secdev_type == 0)
-				{
-					psta->num_of_secdev_type = 0;
-				}
-				else
-				{
-					u32 len;
-
-					psta->num_of_secdev_type = num_of_secdev_type;
-
-					len = (sizeof(psta->secdev_types_list)<(num_of_secdev_type*8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type*8);
-
-					memcpy(psta->secdev_types_list, pattr_content, len);
-
-					pattr_content += (num_of_secdev_type*8);
-				}
-
-				/* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */
-				psta->dev_name_len = 0;
-				if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16*)pattr_content))
-				{
-					dev_name_len = be16_to_cpu(*(u16*)(pattr_content+2));
-
-					psta->dev_name_len = (sizeof(psta->dev_name)<dev_name_len) ? sizeof(psta->dev_name):dev_name_len;
-
-					memcpy(psta->dev_name, pattr_content+4, psta->dev_name_len);
-				}
-
-				kfree(pbuf);
-
-			}
-
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
-
-	}
-
-	return status_code;
-}
-
-u32 process_p2p_devdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
-			    uint len)
-{
-	u8 *frame_body;
-	u8 status, dialogToken;
-	struct sta_info *psta = NULL;
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	struct sta_priv *pstapriv = &padapter->stapriv;
-	u8 *p2p_ie;
-	u32	p2p_ielen = 0;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
-
-	frame_body = (unsigned char *)
-		(pframe + sizeof(struct ieee80211_hdr_3addr));
-
-	dialogToken = frame_body[7];
-	status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
-
-	if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
-				     len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
-				     &p2p_ielen))) {
-		u8 groupid[38] = { 0x00 };
-		u8 dev_addr[ETH_ALEN] = { 0x00 };
-		u32 attr_contentlen = 0;
-
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
-					     P2P_ATTR_GROUP_ID, groupid,
-					     &attr_contentlen)) {
-			if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
-			    !memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN,
-				    pwdinfo->p2p_group_ssid_len)) {
-				attr_contentlen = 0;
-
-				if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
-							     P2P_ATTR_DEVICE_ID,
-							     dev_addr,
-							     &attr_contentlen)) {
-					struct list_head *phead, *plist, *ptmp;
-
-					spin_lock_bh(&pstapriv->asoc_list_lock);
-					phead = &pstapriv->asoc_list;
-
-					list_for_each_safe(plist, ptmp, phead) {
-						psta = container_of(plist, struct sta_info, asoc_list);
-
-						if (psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
-						   !memcmp(psta->dev_addr, dev_addr, ETH_ALEN))
-						{
-							/* spin_unlock_bh(&pstapriv->asoc_list_lock); */
-							/* issue GO Discoverability Request */
-							issue_group_disc_req(pwdinfo, psta->hwaddr);
-							/* spin_lock_bh(&pstapriv->asoc_list_lock); */
-							status = P2P_STATUS_SUCCESS;
-							break;
-						} else {
-							status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-						}
-					}
-					spin_unlock_bh(&pstapriv->asoc_list_lock);
-				} else {
-					status = P2P_STATUS_FAIL_INVALID_PARAM;
-				}
-			} else {
-				status = P2P_STATUS_FAIL_INVALID_PARAM;
-			}
-		}
-	}
-
-	/* issue Device Discoverability Response */
-	issue_p2p_devdisc_resp(pwdinfo, hdr->addr2, status, dialogToken);
-
-	return (status == P2P_STATUS_SUCCESS) ? true:false;
-}
-
-u32 process_p2p_devdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	return true;
-}
-
-u8 process_p2p_provdisc_req23a(struct wifidirect_info *pwdinfo,
-			    u8 *pframe, uint len)
-{
-	u8 *frame_body;
-	u8 *wpsie;
-	u8 *ptr = NULL;
-	uint	wps_ielen = 0, attr_contentlen = 0;
-	u16	uconfig_method = 0;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
-
-	frame_body = (pframe + sizeof(struct ieee80211_hdr_3addr));
-
-	wpsie = rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
-			       len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
-			       &wps_ielen);
-	if (!wpsie)
-		goto out;
-
-	if (!rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD,
-				     (u8 *)&uconfig_method, &attr_contentlen))
-		goto out;
-
-	uconfig_method = be16_to_cpu(uconfig_method);
-	ptr = pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req;
-
-	switch (uconfig_method)
-	{
-	case WPS_CM_DISPLYA:
-		memcpy(ptr, "dis", 3);
-		break;
-
-	case WPS_CM_LABEL:
-		memcpy(ptr, "lab", 3);
-		break;
-
-	case WPS_CM_PUSH_BUTTON:
-		memcpy(ptr, "pbc", 3);
-		break;
-
-	case WPS_CM_KEYPAD:
-		memcpy(ptr, "pad", 3);
-		break;
-	}
-	issue_p2p_provision_resp(pwdinfo, hdr->addr2, frame_body,
-				 uconfig_method);
-
-out:
-	DBG_8723A("[%s] config method = %s\n", __func__, ptr);
-
-	return true;
-}
-
-u8 process_p2p_provdisc_resp23a(struct wifidirect_info *pwdinfo,  u8 *pframe)
-{
-
-	return true;
-}
-
-static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
-{
-	u8 i = 0, j = 0;
-	u8 temp = 0;
-	u8 ch_no = 0;
-	ch_content += 3;
-	ch_cnt -= 3;
-
-	while(ch_cnt > 0)
-	{
-		ch_content += 1;
-		ch_cnt -= 1;
-		temp = *ch_content;
-		for (i = 0 ; i < temp ; i++, j++)
-		{
-			peer_ch_list[j] = *(ch_content + 1 + i);
-		}
-		ch_content += (temp + 1);
-		ch_cnt -= (temp + 1);
-		ch_no += temp ;
-	}
-
-	return ch_no;
-}
-
-static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
-{
-	int	i = 0, j = 0, temp = 0;
-	u8 ch_no = 0;
-
-	for (i = 0; i < peer_ch_num; i++)
-	{
-		for (j = temp; j < pmlmeext->max_chan_nums; j++)
-		{
-			if (*(peer_ch_list + i) == pmlmeext->channel_set[ j ].ChannelNum)
-			{
-				ch_list_inclusioned[ ch_no++ ] = *(peer_ch_list + i);
-				temp = j;
-				break;
-			}
-		}
-	}
-
-	return ch_no;
-}
-
-u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	u8	result = P2P_STATUS_SUCCESS;
-	u32	p2p_ielen = 0, wps_ielen = 0;
-	u8 * ies;
-	u32 ies_len;
-	u8 *p2p_ie;
-	u8 *wpsie;
-	u16		wps_devicepassword_id = 0x0000;
-	uint	wps_devicepassword_id_len = 0;
-#ifdef CONFIG_8723AU_P2P
-	u8	wfd_ie[ 128 ] = { 0x00 };
-	u32	wfd_ielen = 0;
-#endif /*  CONFIG_8723AU_P2P */
-
-	if ((wpsie = rtw_get_wps_ie23a(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)))
-	{
-		/*	Commented by Kurt 20120113 */
-		/*	If some device wants to do p2p handshake without sending prov_disc_req */
-		/*	We have to get peer_req_cm from here. */
-		if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3))
-		{
-			rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
-			wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
-
-			if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
-			{
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
-			}
-			else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
-			{
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
-			}
-			else
-			{
-				memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
-			}
-		}
-	}
-	else
-	{
-		DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-		return result;
-	}
-
-	if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
-	{
-		result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
-		return result;
-	}
-
-	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
-	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
-
-	p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
-
-	if (!p2p_ie)
-	{
-		DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-	}
-
-	while (p2p_ie)
-	{
-		u8	attr_content = 0x00;
-		u32	attr_contentlen = 0;
-		u8	ch_content[50] = { 0x00 };
-		uint	ch_cnt = 0;
-		u8	peer_ch_list[50] = { 0x00 };
-		u8	peer_ch_num = 0;
-		u8	ch_list_inclusioned[50] = { 0x00 };
-		u8	ch_num_inclusioned = 0;
-		u16	cap_attr;
-
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
-
-		/* Check P2P Capability ATTR */
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
-			cap_attr = le16_to_cpu(cap_attr);
-
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
-		{
-			DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
-			pwdinfo->peer_intent = attr_content;	/*	include both intent and tie breaker values. */
-
-			if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
-			{
-				/*	Try to match the tie breaker value */
-				if (pwdinfo->intent == P2P_MAX_INTENT)
-				{
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-					result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
-				}
-				else
-				{
-					if (attr_content & 0x01)
-					{
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-					}
-					else
-					{
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-					}
-				}
-			}
-			else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
-			{
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-			}
-			else
-			{
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-			}
-
-			if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-			{
-				/*	Store the group id information. */
-				memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
-				memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
-			}
-		}
-
-		attr_contentlen = 0;
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
-		{
-			if (attr_contentlen != ETH_ALEN)
-			{
-				memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
-			}
-		}
-
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt))
-		{
-			peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
-			ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
-
-			if (ch_num_inclusioned == 0)
-			{
-				DBG_8723A("[%s] No common channel in channel list!\n", __func__);
-				result = P2P_STATUS_FAIL_NO_COMMON_CH;
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-				break;
-			}
-
-			if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-			{
-				if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
-												ch_list_inclusioned, ch_num_inclusioned))
-				{
-					{
-						u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
-						attr_contentlen = 0;
-
-						if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
-						{
-							peer_operating_ch = operatingch_info[4];
-						}
-
-						if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
-														ch_list_inclusioned, ch_num_inclusioned))
-						{
-							/**
-							 *	Change our operating channel as peer's for compatibility.
-							 */
-							pwdinfo->operating_channel = peer_operating_ch;
-							DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
-						}
-						else
-						{
-							/*  Take first channel of ch_list_inclusioned as operating channel */
-							pwdinfo->operating_channel = ch_list_inclusioned[0];
-							DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
-						}
-					}
-
-				}
-			}
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
-	}
-
-#ifdef CONFIG_8723AU_P2P
-	/*	Added by Albert 20110823 */
-	/*	Try to get the TCP port information when receiving the negotiation request. */
-	if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
-	{
-		u8	attr_content[ 10 ] = { 0x00 };
-		u32	attr_contentlen = 0;
-
-		DBG_8723A("[%s] WFD IE Found!!\n", __func__);
-		rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
-		if (attr_contentlen)
-		{
-			pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
-			DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
-		}
-	}
-#endif /*  CONFIG_8723AU_P2P */
-
-	return result;
-}
-
-u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	struct rtw_adapter *padapter = pwdinfo->padapter;
-	u8	result = P2P_STATUS_SUCCESS;
-	u32	p2p_ielen, wps_ielen;
-	u8 * ies;
-	u32 ies_len;
-	u8 * p2p_ie;
-#ifdef CONFIG_8723AU_P2P
-	u8	wfd_ie[ 128 ] = { 0x00 };
-	u32	wfd_ielen = 0;
-#endif /*  CONFIG_8723AU_P2P */
-
-	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
-	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
-
-	/*	Be able to know which one is the P2P GO and which one is P2P client. */
-
-	if (rtw_get_wps_ie23a(ies, ies_len, NULL, &wps_ielen))
-	{
-
-	}
-	else
-	{
-		DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-	}
-
-	p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
-	if (!p2p_ie)
-	{
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
-	}
-	else
-	{
-
-		u8	attr_content = 0x00;
-		u32	attr_contentlen = 0;
-		u8	operatingch_info[5] = { 0x00 };
-		u8	groupid[ 38 ];
-		u16	cap_attr;
-		u8	peer_ch_list[50] = { 0x00 };
-		u8	peer_ch_num = 0;
-		u8	ch_list_inclusioned[50] = { 0x00 };
-		u8	ch_num_inclusioned = 0;
-
-		while (p2p_ie)	/*	Found the P2P IE. */
-		{
-
-			/* Check P2P Capability ATTR */
-			if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
-				cap_attr = le16_to_cpu(cap_attr);
-
-			rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
-			if (attr_contentlen == 1)
-			{
-				DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
-				if (attr_content == P2P_STATUS_SUCCESS)
-				{
-					/*	Do nothing. */
-				}
-				else
-				{
-					if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content) {
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
-					} else {
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-					}
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-					result = attr_content;
-					break;
-				}
-			}
-
-			/*	Try to get the peer's interface address */
-			attr_contentlen = 0;
-			if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
-			{
-				if (attr_contentlen != ETH_ALEN)
-				{
-					memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
-				}
-			}
-
-			/*	Try to get the peer's intent and tie breaker value. */
-			attr_content = 0x00;
-			attr_contentlen = 0;
-			if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
-			{
-				DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
-				pwdinfo->peer_intent = attr_content;	/*	include both intent and tie breaker values. */
-
-				if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
-				{
-					/*	Try to match the tie breaker value */
-					if (pwdinfo->intent == P2P_MAX_INTENT)
-					{
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-						result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-					}
-					else
-					{
-						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-						rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-						if (attr_content & 0x01)
-						{
-							rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-						}
-						else
-						{
-							rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-						}
-					}
-				}
-				else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
-				{
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-				}
-				else
-				{
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-				}
-
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-				{
-					/*	Store the group id information. */
-					memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
-					memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
-
-				}
-			}
-
-			/*	Try to get the operation channel information */
-
-			attr_contentlen = 0;
-			if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
-			{
-				DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
-				pwdinfo->peer_operating_ch = operatingch_info[4];
-			}
-
-			/*	Try to get the channel list information */
-			if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len))
-			{
-				DBG_8723A("[%s] channel list attribute found, len = %d\n", __func__,  pwdinfo->channel_list_attr_len);
-
-				peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
-				ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
-
-				if (ch_num_inclusioned == 0)
-				{
-					DBG_8723A("[%s] No common channel in channel list!\n", __func__);
-					result = P2P_STATUS_FAIL_NO_COMMON_CH;
-					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-					break;
-				}
-
-				if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
-				{
-					if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
-													ch_list_inclusioned, ch_num_inclusioned))
-					{
-						{
-							u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
-							attr_contentlen = 0;
-
-							if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
-							{
-								peer_operating_ch = operatingch_info[4];
-							}
-
-							if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
-															ch_list_inclusioned, ch_num_inclusioned))
-							{
-								/**
-								 *	Change our operating channel as peer's for compatibility.
-								 */
-								pwdinfo->operating_channel = peer_operating_ch;
-								DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
-							}
-							else
-							{
-								/*  Take first channel of ch_list_inclusioned as operating channel */
-								pwdinfo->operating_channel = ch_list_inclusioned[0];
-								DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
-							}
-						}
-
-					}
-				}
-
-			}
-			else
-			{
-				DBG_8723A("[%s] channel list attribute not found!\n", __func__);
-			}
-
-			/*	Try to get the group id information if peer is GO */
-			attr_contentlen = 0;
-			memset(groupid, 0x00, 38);
-			if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
-			{
-				memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
-				memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
-			}
-
-			/* Get the next P2P IE */
-			p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
-		}
-
-	}
-
-#ifdef CONFIG_8723AU_P2P
-	/*	Added by Albert 20111122 */
-	/*	Try to get the TCP port information when receiving the negotiation response. */
-	if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
-	{
-		u8	attr_content[ 10 ] = { 0x00 };
-		u32	attr_contentlen = 0;
-
-		DBG_8723A("[%s] WFD IE Found!!\n", __func__);
-		rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
-		if (attr_contentlen)
-		{
-			pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
-			DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
-		}
-	}
-#endif /*  CONFIG_8723AU_P2P */
-
-	return result;
-}
-
-u8 process_p2p_group_negotation_confirm23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	u8 * ies;
-	u32 ies_len;
-	u8 * p2p_ie;
-	u32	p2p_ielen = 0;
-	u8	result = P2P_STATUS_SUCCESS;
-	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
-	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
-
-	p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
-	while (p2p_ie)	/*	Found the P2P IE. */
-	{
-		u8	attr_content = 0x00, operatingch_info[5] = { 0x00 };
-		u8	groupid[ 38 ] = { 0x00 };
-		u32	attr_contentlen = 0;
-
-		pwdinfo->negotiation_dialog_token = 1;
-		rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
-		if (attr_contentlen == 1)
-		{
-			DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
-			result = attr_content;
-
-			if (attr_content == P2P_STATUS_SUCCESS)
-			{
-				del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-
-				/*	Commented by Albert 20100911 */
-				/*	Todo: Need to handle the case which both Intents are the same. */
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-				rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-				if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))
-				{
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-				}
-				else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))
-				{
-					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-				}
-				else
-				{
-					/*	Have to compare the Tie Breaker */
-					if (pwdinfo->peer_intent & 0x01)
-					{
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-					}
-					else
-					{
-						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-					}
-				}
-			}
-			else
-			{
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
-				break;
-			}
-		}
-
-		/*	Try to get the group id information */
-		attr_contentlen = 0;
-		memset(groupid, 0x00, 38);
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
-		{
-			DBG_8723A("[%s] Ssid = %s, ssidlen = %zu\n", __func__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
-			memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
-			memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
-		}
-
-		attr_contentlen = 0;
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
-		{
-			DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
-			pwdinfo->peer_operating_ch = operatingch_info[4];
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
-
-	}
-
-	return result;
-}
-
-u8 process_p2p_presence_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
-{
-	u8 *frame_body;
-	u8 dialogToken = 0;
-	u8 status = P2P_STATUS_SUCCESS;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
-
-	frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
-
-	dialogToken = frame_body[6];
-
-	/* todo: check NoA attribute */
-
-	issue_p2p_presence_resp(pwdinfo, hdr->addr2, status, dialogToken);
-
-	return true;
-}
-
-static void find_phase_handler(struct rtw_adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
-	struct cfg80211_ssid ssid;
-	u8					_status = 0;
-
-
-
-	memset((unsigned char*)&ssid, 0, sizeof(struct cfg80211_ssid));
-	memcpy(ssid.ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
-	ssid.ssid_len = P2P_WILDCARD_SSID_LEN;
-
-	rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
-
-	spin_lock_bh(&pmlmepriv->lock);
-	_status = rtw_sitesurvey_cmd23a(padapter, &ssid, 1, NULL, 0);
-	spin_unlock_bh(&pmlmepriv->lock);
-
-
-}
-
-void p2p_concurrent_handler(struct rtw_adapter* padapter);
-
-static void restore_p2p_state_handler(struct rtw_adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-
-	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-
-	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
-		/*	In the P2P client mode, the driver should not switch back to its listen channel */
-		/*	because this P2P client should stay at the operating channel of P2P GO. */
-		set_channel_bwmode23a(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	}
-}
-
-static void pre_tx_invitereq_handler(struct rtw_adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	u8	val8 = 1;
-
-	set_channel_bwmode23a(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-	issue23a_probereq_p2p(padapter, NULL);
-	mod_timer(&pwdinfo->pre_tx_scan_timer,
-		  jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
-
-
-}
-
-static void pre_tx_provdisc_handler(struct rtw_adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	u8	val8 = 1;
-
-
-	set_channel_bwmode23a(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-	issue23a_probereq_p2p(padapter, NULL);
-	mod_timer(&pwdinfo->pre_tx_scan_timer,
-		  jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
-
-
-}
-
-static void pre_tx_negoreq_handler(struct rtw_adapter *padapter)
-{
-	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
-	u8	val8 = 1;
-
-
-	set_channel_bwmode23a(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-	issue23a_probereq_p2p(padapter, NULL);
-	mod_timer(&pwdinfo->pre_tx_scan_timer,
-		  jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
-
-
-}
-
-static void ro_ch_handler(struct rtw_adapter *padapter)
-{
-	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
-	if (pcfg80211_wdinfo->restore_channel != pmlmeext->cur_channel) {
-		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
-			pmlmeext->cur_channel = pcfg80211_wdinfo->restore_channel;
-
-		set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
-				      HAL_PRIME_CHNL_OFFSET_DONT_CARE,
-				      HT_CHANNEL_WIDTH_20);
-	}
-
-	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-
-	pcfg80211_wdinfo->is_ro_ch = false;
-
-	DBG_8723A("cfg80211_remain_on_channel_expired\n");
-
-	rtw_cfg80211_remain_on_channel_expired(padapter,
-		pcfg80211_wdinfo->remain_on_ch_cookie,
-		&pcfg80211_wdinfo->remain_on_ch_channel,
-		pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
-}
-
-static void ro_ch_timer_process (unsigned long data)
-{
-	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-
-	p2p_protocol_wk_cmd23a(adapter, P2P_RO_CH_WK);
-}
-
-#ifdef CONFIG_8723AU_P2P
-void rtw_append_wfd_ie(struct rtw_adapter *padapter, u8 *buf, u32* len)
-{
-	unsigned char	*frame_body;
-	u8 category, action, OUI_Subtype, dialogToken = 0;
-	u32	wfdielen = 0;
-
-	frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
-	category = frame_body[0];
-
-	if (category == WLAN_CATEGORY_PUBLIC) {
-		action = frame_body[1];
-		if (action == ACT_PUBLIC_VENDOR &&
-		    !memcmp(frame_body+2, P2P_OUI23A, 4)) {
-			OUI_Subtype = frame_body[6];
-			dialogToken = frame_body[7];
-			switch (OUI_Subtype)/* OUI Subtype */ {
-			case P2P_GO_NEGO_REQ:
-				wfdielen = build_nego_req_wfd_ie(&padapter->wdinfo, buf + (*len));
-				(*len) += wfdielen;
-				break;
-			case P2P_GO_NEGO_RESP:
-				wfdielen = build_nego_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
-				(*len) += wfdielen;
-				break;
-			case P2P_GO_NEGO_CONF:
-				wfdielen = build_nego_confirm_wfd_ie(&padapter->wdinfo, buf + (*len));
-				(*len) += wfdielen;
-				break;
-			case P2P_INVIT_REQ:
-				wfdielen = build_invitation_req_wfd_ie(&padapter->wdinfo, buf + (*len));
-				(*len) += wfdielen;
-				break;
-			case P2P_INVIT_RESP:
-				wfdielen = build_invitation_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
-				(*len) += wfdielen;
-				break;
-			case P2P_DEVDISC_REQ:
-				break;
-			case P2P_DEVDISC_RESP:
-				break;
-			case P2P_PROVISION_DISC_REQ:
-				wfdielen = build_provdisc_req_wfd_ie(&padapter->wdinfo, buf + (*len));
-				(*len) += wfdielen;
-				break;
-			case P2P_PROVISION_DISC_RESP:
-				wfdielen = build_provdisc_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
-				(*len) += wfdielen;
-				break;
-			default:
-				break;
-			}
-		}
-	} else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC) {
-		OUI_Subtype = frame_body[5];
-		dialogToken = frame_body[6];
-	} else {
-		DBG_8723A("%s, action frame category =%d\n", __func__, category);
-	}
-}
-#endif
-
-int rtw_p2p_check_frames(struct rtw_adapter *padapter, const u8 *buf, u32 len, u8 tx)
-{
-	int is_p2p_frame = (-1);
-	unsigned char	*frame_body;
-	u8 category, action, OUI_Subtype, dialogToken = 0;
-	u8 *p2p_ie = NULL;
-	uint p2p_ielen = 0;
-	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
-
-	frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
-	category = frame_body[0];
-	/* just for check */
-	if (category == WLAN_CATEGORY_PUBLIC)
-	{
-		action = frame_body[1];
-		if (action == ACT_PUBLIC_VENDOR &&
-		    !memcmp(frame_body+2, P2P_OUI23A, 4)) {
-			OUI_Subtype = frame_body[6];
-			dialogToken = frame_body[7];
-			is_p2p_frame = OUI_Subtype;
-			p2p_ie = rtw_get_p2p_ie23a(
-				(u8 *)buf+sizeof(struct ieee80211_hdr_3addr)+_PUBLIC_ACTION_IE_OFFSET_,
-				len-sizeof(struct ieee80211_hdr_3addr)-_PUBLIC_ACTION_IE_OFFSET_,
-				NULL, &p2p_ielen);
-
-			switch (OUI_Subtype) {/* OUI Subtype */
-			u8 *cont;
-			uint cont_len;
-			case P2P_GO_NEGO_REQ:
-				DBG_8723A("RTW_%s:P2P_GO_NEGO_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
-				break;
-			case P2P_GO_NEGO_RESP:
-				cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
-				DBG_8723A("RTW_%s:P2P_GO_NEGO_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
-
-				if (!tx)
-					pwdev_priv->provdisc_req_issued = false;
-				break;
-			case P2P_GO_NEGO_CONF:
-				cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
-				DBG_8723A("RTW_%s:P2P_GO_NEGO_CONF, dialogToken =%d, status:%d\n",
-					  (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
-				break;
-			case P2P_INVIT_REQ:
-			{
-				struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
-				int flags = -1;
-				int op_ch = 0;
-
-				if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len)))
-					flags = *cont;
-				if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
-					op_ch = *(cont+4);
-
-				if (invit_info->token != dialogToken)
-					rtw_wdev_invit_info_init(invit_info);
-
-				invit_info->token = dialogToken;
-				invit_info->flags = (flags ==-1) ? 0x0 : flags;
-				invit_info->req_op_ch = op_ch;
-
-				DBG_8723A("RTW_%s:P2P_INVIT_REQ, dialogToken =%d, flags:0x%02x, op_ch:%d\n",
-					  (tx) ? "Tx" : "Rx", dialogToken, flags, op_ch);
-				break;
-			}
-			case P2P_INVIT_RESP:
-			{
-				struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
-				int status = -1;
-				int op_ch = 0;
-
-				if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
-					status = *cont;
-				if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
-					op_ch = *(cont+4);
-
-				if (invit_info->token != dialogToken) {
-					rtw_wdev_invit_info_init(invit_info);
-				} else {
-					invit_info->token = 0;
-					invit_info->status = (status ==-1) ? 0xff : status;
-					invit_info->rsp_op_ch = op_ch;
-				}
-
-				DBG_8723A("RTW_%s:P2P_INVIT_RESP, dialogToken =%d, status:%d, op_ch:%d\n",
-					  (tx == true)?"Tx":"Rx", dialogToken, status, op_ch);
-				break;
-			}
-			case P2P_DEVDISC_REQ:
-				DBG_8723A("RTW_%s:P2P_DEVDISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
-				break;
-			case P2P_DEVDISC_RESP:
-				cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
-				DBG_8723A("RTW_%s:P2P_DEVDISC_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
-				break;
-			case P2P_PROVISION_DISC_REQ:
-			{
-				size_t frame_body_len = len - sizeof(struct ieee80211_hdr_3addr);
-				u8 *p2p_ie;
-				uint p2p_ielen = 0;
-				uint contentlen = 0;
-
-				DBG_8723A("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
-
-				pwdev_priv->provdisc_req_issued = false;
-
-				p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
-							   frame_body_len - _PUBLIC_ACTION_IE_OFFSET_,
-							   NULL, &p2p_ielen);
-				if (p2p_ie) {
-					if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen))
-						pwdev_priv->provdisc_req_issued = false;/* case: p2p_client join p2p GO */
-					else
-						pwdev_priv->provdisc_req_issued = true;/* case: p2p_devices connection before Nego req. */
-				}
-			}
-				break;
-			case P2P_PROVISION_DISC_RESP:
-				DBG_8723A("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
-				break;
-			default:
-				DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"Tx":"Rx", OUI_Subtype, dialogToken);
-				break;
-			}
-
-		}
-
-	}
-	else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC)
-	{
-		OUI_Subtype = frame_body[5];
-		dialogToken = frame_body[6];
-
-		is_p2p_frame = OUI_Subtype;
-
-		switch (OUI_Subtype) {
-		case P2P_NOTICE_OF_ABSENCE:
-			DBG_8723A("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
-			break;
-		case P2P_PRESENCE_REQUEST:
-			DBG_8723A("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
-			break;
-		case P2P_PRESENCE_RESPONSE:
-			DBG_8723A("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
-			break;
-		case P2P_GO_DISC_REQUEST:
-			DBG_8723A("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
-			break;
-		default:
-			DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"TX":"RX", OUI_Subtype, dialogToken);
-			break;
-		}
-
-	} else {
-		DBG_8723A("RTW_%s:action frame category =%d\n", (tx == true)?"TX":"RX", category);
-	}
-	return is_p2p_frame;
-}
-
-void rtw_init_cfg80211_wifidirect_info(struct rtw_adapter *padapter)
-{
-	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
-
-	memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));
-
-	setup_timer(&pcfg80211_wdinfo->remain_on_ch_timer,
-		    ro_ch_timer_process, (unsigned long)padapter);
-}
-
-void p2p_protocol_wk_hdl23a(struct rtw_adapter *padapter, int intCmdType)
-{
-	switch (intCmdType) {
-	case P2P_FIND_PHASE_WK:
-		find_phase_handler(padapter);
-		break;
-	case P2P_RESTORE_STATE_WK:
-		restore_p2p_state_handler(padapter);
-		break;
-	case P2P_PRE_TX_PROVDISC_PROCESS_WK:
-		pre_tx_provdisc_handler(padapter);
-		break;
-	case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
-		pre_tx_invitereq_handler(padapter);
-		break;
-	case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
-		pre_tx_negoreq_handler(padapter);
-		break;
-	case P2P_RO_CH_WK:
-		ro_ch_handler(padapter);
-		break;
-	}
-}
-
-#ifdef CONFIG_8723AU_P2P
-void process_p2p_ps_ie23a(struct rtw_adapter *padapter, u8 *IEs, u32 IELength)
-{
-	u8 * ies;
-	u32 ies_len;
-	u8 * p2p_ie;
-	u32	p2p_ielen = 0;
-	u8	noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/*  NoA length should be n*(13) + 2 */
-	u32	attr_contentlen = 0;
-
-	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
-	u8	find_p2p = false, find_p2p_ps = false;
-	u8	noa_offset, noa_num, noa_index;
-
-
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-	{
-		return;
-	}
-	if (IELength <= _BEACON_IE_OFFSET_)
-		return;
-
-	ies = IEs + _BEACON_IE_OFFSET_;
-	ies_len = IELength - _BEACON_IE_OFFSET_;
-
-	p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
-
-	while(p2p_ie)
-	{
-		find_p2p = true;
-		/*  Get Notice of Absence IE. */
-		if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen))
-		{
-			find_p2p_ps = true;
-			noa_index = noa_attr[0];
-
-			if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
-				(noa_index != pwdinfo->noa_index))/*  if index change, driver should reconfigure related setting. */
-			{
-				pwdinfo->noa_index = noa_index;
-				pwdinfo->opp_ps = noa_attr[1] >> 7;
-				pwdinfo->ctwindow = noa_attr[1] & 0x7F;
-
-				noa_offset = 2;
-				noa_num = 0;
-				/*  NoA length should be n*(13) + 2 */
-				if (attr_contentlen > 2)
-				{
-					while(noa_offset < attr_contentlen)
-					{
-						/* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
-						pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
-						noa_offset += 1;
-
-						memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
-						noa_offset += 4;
-
-						memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
-						noa_offset += 4;
-
-						memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
-						noa_offset += 4;
-
-						noa_num++;
-					}
-				}
-				pwdinfo->noa_num = noa_num;
-
-				if (pwdinfo->opp_ps == 1)
-				{
-					pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
-					/*  driver should wait LPS for entering CTWindow */
-					if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true)
-					{
-						p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
-					}
-				}
-				else if (pwdinfo->noa_num > 0)
-				{
-					pwdinfo->p2p_ps_mode = P2P_PS_NOA;
-					p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
-				}
-				else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
-				{
-					p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
-				}
-			}
-
-			break; /*  find target, just break. */
-		}
-
-		/* Get the next P2P IE */
-		p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
-
-	}
-
-	if (find_p2p == true)
-	{
-		if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == false))
-		{
-			p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
-		}
-	}
-
-
-}
-
-void p2p_ps_wk_hdl23a(struct rtw_adapter *padapter, u8 p2p_ps_state)
-{
-	struct pwrctrl_priv		*pwrpriv = &padapter->pwrctrlpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-
-
-	/*  Pre action for p2p state */
-	switch (p2p_ps_state)
-	{
-		case P2P_PS_DISABLE:
-			pwdinfo->p2p_ps_state = p2p_ps_state;
-
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
-
-			pwdinfo->noa_index = 0;
-			pwdinfo->ctwindow = 0;
-			pwdinfo->opp_ps = 0;
-			pwdinfo->noa_num = 0;
-			pwdinfo->p2p_ps_mode = P2P_PS_NONE;
-			if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true)
-			{
-				if (pwrpriv->smart_ps == 0)
-				{
-					pwrpriv->smart_ps = 2;
-					rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)&padapter->pwrctrlpriv.pwr_mode);
-				}
-			}
-			break;
-		case P2P_PS_ENABLE:
-			if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
-				pwdinfo->p2p_ps_state = p2p_ps_state;
-
-				if (pwdinfo->ctwindow > 0)
-				{
-					if (pwrpriv->smart_ps != 0)
-					{
-						pwrpriv->smart_ps = 0;
-						DBG_8723A("%s(): Enter CTW, change SmartPS\n", __func__);
-						rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)&padapter->pwrctrlpriv.pwr_mode);
-					}
-				}
-				rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
-			}
-			break;
-		case P2P_PS_SCAN:
-		case P2P_PS_SCAN_DONE:
-		case P2P_PS_ALLSTASLEEP:
-			if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
-				pwdinfo->p2p_ps_state = p2p_ps_state;
-				rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
-			}
-			break;
-		default:
-			break;
-	}
-
-
-}
-
-u8 p2p_ps_wk_cmd23a(struct rtw_adapter*padapter, u8 p2p_ps_state, u8 enqueue)
-{
-	struct cmd_obj	*ph2c;
-	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
-	u8	res = _SUCCESS;
-
-
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return res;
-
-	if (enqueue) {
-		ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
-						 GFP_ATOMIC);
-		if (!ph2c) {
-			res = _FAIL;
-			goto exit;
-		}
-
-		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)
-			kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
-		if (pdrvextra_cmd_parm == NULL) {
-			kfree(ph2c);
-			res = _FAIL;
-			goto exit;
-		}
-
-		pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
-		pdrvextra_cmd_parm->type_size = p2p_ps_state;
-		pdrvextra_cmd_parm->pbuf = NULL;
-
-		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-
-		res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
-	}
-	else
-	{
-		p2p_ps_wk_hdl23a(padapter, p2p_ps_state);
-	}
-
-exit:
-
-
-
-	return res;
-}
-#endif /*  CONFIG_8723AU_P2P */
-
-static void reset_ch_sitesurvey_timer_process(unsigned long data)
-{
-	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct  wifidirect_info *pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	DBG_8723A("[%s] In\n", __func__);
-	/*	Reset the operation channel information */
-	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
-	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
-}
-
-static void reset_ch_sitesurvey_timer_process2(unsigned long data)
-{
-	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct wifidirect_info *pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	DBG_8723A("[%s] In\n", __func__);
-	/*	Reset the operation channel information */
-	pwdinfo->p2p_info.operation_ch[0] = 0;
-	pwdinfo->p2p_info.scan_op_ch_only = 0;
-}
-
-static void restore_p2p_state_timer_process (unsigned long data)
-{
-	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	p2p_protocol_wk_cmd23a(adapter, P2P_RESTORE_STATE_WK);
-}
-
-static void pre_tx_scan_timer_process (unsigned long data)
-{
-	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct wifidirect_info *pwdinfo = &adapter->wdinfo;
-	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	spin_lock_bh(&pmlmepriv->lock);
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
-	{
-		if (true == pwdinfo->tx_prov_disc_info.benable)	/*	the provision discovery request frame is trigger to send or not */
-		{
-			p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
-			/* issue23a_probereq_p2p(adapter, NULL); */
-			/* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */
-		}
-	}
-	else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
-	{
-		if (true == pwdinfo->nego_req_info.benable)
-		{
-			p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
-		}
-	}
-	else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ))
-	{
-		if (true == pwdinfo->invitereq_info.benable)
-		{
-			p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
-		}
-	}
-	else
-	{
-		DBG_8723A("[%s] p2p_state is %d, ignore!!\n", __func__, rtw_p2p_state(pwdinfo));
-	}
-
-	spin_unlock_bh(&pmlmepriv->lock);
-}
-
-static void find_phase_timer_process (unsigned long data)
-{
-	struct rtw_adapter *adapter = (struct rtw_adapter *)data;
-	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
-
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-
-	adapter->wdinfo.find_phase_state_exchange_cnt++;
-
-	p2p_protocol_wk_cmd23a(adapter, P2P_FIND_PHASE_WK);
-}
-
-void reset_global_wifidirect_info23a(struct rtw_adapter *padapter)
-{
-	struct wifidirect_info	*pwdinfo;
-
-	pwdinfo = &padapter->wdinfo;
-	pwdinfo->persistent_supported = 0;
-	pwdinfo->session_available = true;
-	pwdinfo->wfd_tdls_enable = 0;
-	pwdinfo->wfd_tdls_weaksec = 0;
-}
-
-#ifdef CONFIG_8723AU_P2P
-int rtw_init_wifi_display_info(struct rtw_adapter* padapter)
-{
-	int	res = _SUCCESS;
-	struct wifi_display_info *pwfd_info = &padapter->wfd_info;
-
-	/*  Used in P2P and TDLS */
-	pwfd_info->rtsp_ctrlport = 554;
-	pwfd_info->peer_rtsp_ctrlport = 0;	/*	Reset to 0 */
-	pwfd_info->wfd_enable = false;
-	pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
-	pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
-
-	/*  Used in P2P */
-	pwfd_info->peer_session_avail = true;
-	pwfd_info->wfd_pc = false;
-
-	/*  Used in TDLS */
-	memset(pwfd_info->ip_address, 0x00, 4);
-	memset(pwfd_info->peer_ip_address, 0x00, 4);
-	return res;
-}
-#endif /* CONFIG_8723AU_P2P */
-
-void rtw_init_wifidirect_timers23a(struct rtw_adapter* padapter)
-{
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	setup_timer(&pwdinfo->find_phase_timer, find_phase_timer_process,
-		    (unsigned long)padapter);
-	setup_timer(&pwdinfo->restore_p2p_state_timer,
-		    restore_p2p_state_timer_process, (unsigned long)padapter);
-	setup_timer(&pwdinfo->pre_tx_scan_timer, pre_tx_scan_timer_process,
-		    (unsigned long)padapter);
-	setup_timer(&pwdinfo->reset_ch_sitesurvey,
-		    reset_ch_sitesurvey_timer_process, (unsigned long)padapter);
-	setup_timer(&pwdinfo->reset_ch_sitesurvey2,
-		    reset_ch_sitesurvey_timer_process2,
-		    (unsigned long)padapter);
-}
-
-void rtw_init_wifidirect_addrs23a(struct rtw_adapter* padapter, u8 *dev_addr, u8 *iface_addr)
-{
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-
-	/*init device&interface address */
-	if (dev_addr) {
-		memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
-	}
-	if (iface_addr) {
-		memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
-	}
-#endif
-}
-
-void init_wifidirect_info23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
-{
-	struct wifidirect_info	*pwdinfo;
-#ifdef CONFIG_8723AU_P2P
-	struct wifi_display_info	*pwfd_info = &padapter->wfd_info;
-#endif
-
-	pwdinfo = &padapter->wdinfo;
-
-	pwdinfo->padapter = padapter;
-
-	/*	1, 6, 11 are the social channel defined in the WiFi Direct specification. */
-	pwdinfo->social_chan[0] = 1;
-	pwdinfo->social_chan[1] = 6;
-	pwdinfo->social_chan[2] = 11;
-	pwdinfo->social_chan[3] = 0;	/*	channel 0 for scanning ending in site survey function. */
-
-	/*	Use the channel 11 as the listen channel */
-	pwdinfo->listen_channel = 11;
-
-	if (role == P2P_ROLE_DEVICE)
-	{
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
-		pwdinfo->intent = 1;
-		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
-	}
-	else if (role == P2P_ROLE_CLIENT)
-	{
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-		pwdinfo->intent = 1;
-		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-	}
-	else if (role == P2P_ROLE_GO)
-	{
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-		pwdinfo->intent = 15;
-		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
-	}
-
-/*	Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
-	pwdinfo->support_rate[0] = 0x8c;	/*	6(B) */
-	pwdinfo->support_rate[1] = 0x92;	/*	9(B) */
-	pwdinfo->support_rate[2] = 0x18;	/*	12 */
-	pwdinfo->support_rate[3] = 0x24;	/*	18 */
-	pwdinfo->support_rate[4] = 0x30;	/*	24 */
-	pwdinfo->support_rate[5] = 0x48;	/*	36 */
-	pwdinfo->support_rate[6] = 0x60;	/*	48 */
-	pwdinfo->support_rate[7] = 0x6c;	/*	54 */
-
-	memcpy((void*) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
-
-	memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
-	pwdinfo->device_name_len = 0;
-
-	memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
-	pwdinfo->invitereq_info.token = 3;	/*	Token used for P2P invitation request frame. */
-
-	memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
-	pwdinfo->inviteresp_info.token = 0;
-
-	pwdinfo->profileindex = 0;
-	memset(&pwdinfo->profileinfo[ 0 ], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
-
-	rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
-
-	pwdinfo->listen_dwell = (u8) ((jiffies % 3) + 1);
-	/* DBG_8723A("[%s] listen_dwell time is %d00ms\n", __func__, pwdinfo->listen_dwell); */
-
-	memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
-	pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
-
-	memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
-
-	pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
-	pwdinfo->negotiation_dialog_token = 1;
-
-	memset(pwdinfo->nego_ssid, 0x00, IEEE80211_MAX_SSID_LEN);
-	pwdinfo->nego_ssidlen = 0;
-
-	pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
-#ifdef CONFIG_8723AU_P2P
-	pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY  | WPS_CONFIG_METHOD_PBC;
-	pwdinfo->wfd_info = pwfd_info;
-#else
-	pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
-#endif /* CONFIG_8723AU_P2P */
-	pwdinfo->channel_list_attr_len = 0;
-	memset(pwdinfo->channel_list_attr, 0x00, 100);
-
-	memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
-	memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
-	memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
-	pwdinfo->wfd_tdls_enable = 0;
-	memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
-	memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
-
-	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
-	pwdinfo->rx_invitereq_info.operation_ch[1] = 0;	/*	Used to indicate the scan end in site survey function */
-	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
-	pwdinfo->p2p_info.operation_ch[0] = 0;
-	pwdinfo->p2p_info.operation_ch[1] = 0;			/*	Used to indicate the scan end in site survey function */
-	pwdinfo->p2p_info.scan_op_ch_only = 0;
-}
-
-int rtw_p2p_enable23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
-{
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	int ret = _SUCCESS;
-
-	if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT ||
-	    role == P2P_ROLE_GO) {
-		/* leave IPS/Autosuspend */
-		if (_FAIL == rtw_pwr_wakeup(padapter)) {
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/*	Added by Albert 2011/03/22 */
-		/*	In the P2P mode, the driver should not support the b mode. */
-		/*	So, the Tx packet shouldn't use the CCK rate */
-		update_tx_basic_rate23a(padapter, WIRELESS_11AGN);
-
-		/* Enable P2P function */
-		init_wifidirect_info23a(padapter, role);
-
-		rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, true);
-		#ifdef CONFIG_8723AU_P2P
-		rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, true);
-		#endif
-
-	}
-	else if (role == P2P_ROLE_DISABLE)
-	{
-		if (_FAIL == rtw_pwr_wakeup(padapter)) {
-			ret = _FAIL;
-			goto exit;
-		}
-
-		/* Disable P2P function */
-		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		{
-			del_timer_sync(&pwdinfo->find_phase_timer);
-			del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-			del_timer_sync(&pwdinfo->pre_tx_scan_timer);
-			del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
-			del_timer_sync(&pwdinfo->reset_ch_sitesurvey2);
-			reset_ch_sitesurvey_timer_process((unsigned long)padapter);
-			reset_ch_sitesurvey_timer_process2((unsigned long)padapter);
-			rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
-			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
-			memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
-		}
-
-		rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, false);
-		#ifdef CONFIG_8723AU_P2P
-		rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, false);
-		#endif
-
-		/* Restore to initial setting. */
-		update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
-	}
-
-exit:
-	return ret;
-}
-
-#endif /* CONFIG_8723AU_P2P */
diff --git a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
index 8ddd67f194ba..77880547e80f 100644
--- a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
@@ -17,6 +17,7 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <osdep_intf.h>
+#include <rtl8723a_cmd.h>
 
 #ifdef CONFIG_8723AU_BT_COEXIST
 #include <rtl8723a_hal.h>
@@ -108,33 +109,30 @@ static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter)
 	struct rtw_adapter *buddy = adapter->pbuddy_adapter;
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
-	struct wifidirect_info *pwdinfo = &adapter->wdinfo;
 
 	bool ret = false;
 
 	if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies))
 		goto exit;
 
-	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
-		|| check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
-		|| check_fwstate(pmlmepriv, WIFI_AP_STATE)
-		|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
-		|| !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
-	) {
+	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
+	    check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
+	    check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
+	    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)){
 		goto exit;
 	}
 
 	/* consider buddy, if exist */
 	if (buddy) {
 		struct mlme_priv *b_pmlmepriv = &buddy->mlmepriv;
-		struct wifidirect_info *b_pwdinfo = &buddy->wdinfo;
-
-		if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
-			|| check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
-			|| check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
-			|| check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
-			|| !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)
-		) {
+
+		if (check_fwstate(b_pmlmepriv,
+				  WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
+		    check_fwstate(b_pmlmepriv,
+				  WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
+		    check_fwstate(b_pmlmepriv, WIFI_AP_STATE) ||
+		    check_fwstate(b_pmlmepriv,
+				  WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)) {
 			goto exit;
 		}
 	}
@@ -263,7 +261,7 @@ void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv)
 
 	pwrpriv->rpwm = pslv;
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
+	rtl8723a_set_rpwm(padapter, rpwm);
 
 	pwrpriv->tog += 0x80;
 	pwrpriv->cpwm = pslv;
@@ -306,11 +304,6 @@ u8 PS_RDY_CHECK(struct rtw_adapter * padapter)
 void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
 {
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
-
-
 
 	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
 			 ("%s: PowerMode =%d Smart_PS =%d\n",
@@ -333,45 +326,29 @@ void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, u8 smart_ps, u
 	}
 
 	if (ps_mode == PS_MODE_ACTIVE) {
-#ifdef CONFIG_8723AU_P2P
-		if (pwdinfo->opp_ps == 0)
-#endif /* CONFIG_8723AU_P2P */
-		{
-			DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n");
+		DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n");
 
-			pwrpriv->pwr_mode = ps_mode;
-			rtw_set_rpwm23a(padapter, PS_STATE_S4);
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
-			pwrpriv->bFwCurrentInPSMode = false;
-		}
-	}
-	else
-	{
+		pwrpriv->pwr_mode = ps_mode;
+		rtw_set_rpwm23a(padapter, PS_STATE_S4);
+		rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode);
+		pwrpriv->bFwCurrentInPSMode = false;
+	} else {
 		if (PS_RDY_CHECK(padapter)
 #ifdef CONFIG_8723AU_BT_COEXIST
 			|| (BT_1Ant(padapter) == true)
 #endif
-			)
-		{
+			) {
 			DBG_8723A("%s: Enter 802.11 power save\n", __func__);
 
 			pwrpriv->bFwCurrentInPSMode = true;
 			pwrpriv->pwr_mode = ps_mode;
 			pwrpriv->smart_ps = smart_ps;
 			pwrpriv->bcn_ant_mode = bcn_ant_mode;
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
-
-#ifdef CONFIG_8723AU_P2P
-			/*  Set CTWindow after LPS */
-			if (pwdinfo->opp_ps == 1)
-				p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 0);
-#endif /* CONFIG_8723AU_P2P */
+			rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode);
 
 			rtw_set_rpwm23a(padapter, PS_STATE_S2);
 		}
 	}
-
-
 }
 
 /*
@@ -391,12 +368,11 @@ s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms)
 
 	while (1)
 	{
-		rtw23a_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
-		if (true == bAwake)
+		bAwake = rtl8723a_get_fwlps_rf_on(padapter);
+		if (bAwake == true)
 			break;
 
-		if (true == padapter->bSurpriseRemoved)
-		{
+		if (padapter->bSurpriseRemoved == true) {
 			err = -2;
 			DBG_8723A("%s: device surprise removed!!\n", __func__);
 			break;
@@ -469,10 +445,6 @@ void LeaveAllPowerSaveMode23a(struct rtw_adapter *Adapter)
 	/* DBG_8723A("%s.....\n", __func__); */
 	if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
 	{ /* connect */
-#ifdef CONFIG_8723AU_P2P
-		p2p_ps_wk_cmd23a(Adapter, P2P_PS_DISABLE, enqueue);
-#endif /* CONFIG_8723AU_P2P */
-
 		rtw_lps_ctrl_wk_cmd23a(Adapter, LPS_CTRL_LEAVE, enqueue);
 	}
 
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
index 0b2455e4f5b6..644c3a132e59 100644
--- a/drivers/staging/rtl8723au/core/rtw_recv.c
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -19,7 +19,6 @@
 #include <mlme_osdep.h>
 #include <linux/ip.h>
 #include <linux/if_ether.h>
-#include <ethernet.h>
 #include <usb_ops.h>
 #include <linux/ieee80211.h>
 #include <wifi.h>
@@ -80,8 +79,6 @@ int _rtw_init_recv_priv23a(struct recv_priv *precvpriv,
 		list_add_tail(&precvframe->list,
 			      &precvpriv->free_recv_queue.queue);
 
-		res = rtw_os_recv_resource_alloc23a(padapter, precvframe);
-
 		precvframe->adapter = padapter;
 		precvframe++;
 	}
@@ -569,31 +566,35 @@ struct recv_frame *decryptor(struct rtw_adapter *padapter,
 static struct recv_frame *portctrl(struct rtw_adapter *adapter,
 				   struct recv_frame *precv_frame)
 {
-	u8 *psta_addr = NULL, *ptr;
+	u8 *psta_addr, *ptr;
 	uint auth_alg;
 	struct recv_frame *pfhdr;
 	struct sta_info *psta;
 	struct sta_priv *pstapriv ;
 	struct recv_frame *prtnframe;
-	u16 ether_type = 0;
-	u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
+	u16 ether_type;
+	u16 eapol_type = ETH_P_PAE;/* for Funia BD's WPA issue */
 	struct rx_pkt_attrib *pattrib;
 
 	pstapriv = &adapter->stapriv;
-	psta = rtw_get_stainfo23a(pstapriv, psta_addr);
 
 	auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
 
-	ptr = precv_frame->pkt->data;
 	pfhdr = precv_frame;
 	pattrib = &pfhdr->attrib;
 	psta_addr = pattrib->ta;
+	psta = rtw_get_stainfo23a(pstapriv, psta_addr);
 
 	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
 		 ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm ="
 		  "%d\n", adapter->securitypriv.dot11AuthAlgrthm));
 
-	if (auth_alg == 2) {
+	if (auth_alg == dot11AuthAlgrthm_8021X) {
+		/* get ether_type */
+		ptr = pfhdr->pkt->data + pfhdr->attrib.hdrlen;
+
+		ether_type = (ptr[6] << 8) | ptr[7];
+
 		if ((psta != NULL) && (psta->ieee8021x_blocked)) {
 			/* blocked */
 			/* only accept EAPOL frame */
@@ -601,13 +602,6 @@ static struct recv_frame *portctrl(struct rtw_adapter *adapter,
 				 ("########portctrl:psta->ieee8021x_blocked =="
 				  "1\n"));
 
-			prtnframe = precv_frame;
-
-			/* get ether_type */
-			ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
-			memcpy(&ether_type, ptr, 2);
-			ether_type = ntohs((unsigned short)ether_type);
-
 		        if (ether_type == eapol_type) {
 				prtnframe = precv_frame;
 			} else {
@@ -651,9 +645,7 @@ static struct recv_frame *portctrl(struct rtw_adapter *adapter,
 		prtnframe = precv_frame;
 	}
 
-
-
-		return prtnframe;
+	return prtnframe;
 }
 
 int recv_decache(struct recv_frame *precv_frame, u8 bretry,
@@ -1222,8 +1214,8 @@ int validate_recv_ctrl_frame(struct rtw_adapter *padapter,
 
 					/* upate BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
-					update_beacon23a(padapter, _TIM_IE_,
-						      NULL, false);
+					update_beacon23a(padapter, WLAN_EID_TIM,
+							 NULL, false);
 				}
 
 				/* spin_unlock_bh(&psta->sleep_q.lock); */
@@ -1254,8 +1246,8 @@ int validate_recv_ctrl_frame(struct rtw_adapter *padapter,
 
 					/* upate BCN for TIM IE */
 					/* update_BCNTIM(padapter); */
-					update_beacon23a(padapter, _TIM_IE_,
-						      NULL, false);
+					update_beacon23a(padapter, WLAN_EID_TIM,
+							 NULL, false);
 				}
 			}
 		}
@@ -2102,7 +2094,7 @@ int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
 		/* s1. */
 		wlanhdr_to_ethhdr(prframe);
 
-		if ((pattrib->qos!= 1) || (pattrib->eth_type == 0x0806) ||
+		if ((pattrib->qos!= 1) || (pattrib->eth_type == ETH_P_ARP) ||
 		    (pattrib->ack_policy != 0)) {
 			if ((padapter->bDriverStopped == false) &&
 			    (padapter->bSurpriseRemoved == false)) {
diff --git a/drivers/staging/rtl8723au/core/rtw_sreset.c b/drivers/staging/rtl8723au/core/rtw_sreset.c
index 4f7459203390..5bf7beb6d19c 100644
--- a/drivers/staging/rtl8723au/core/rtw_sreset.c
+++ b/drivers/staging/rtl8723au/core/rtw_sreset.c
@@ -99,7 +99,8 @@ static void sreset_restore_security_station(struct rtw_adapter *padapter)
 		val8 = 0xcc;
 	else
 		val8 = 0xcf;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+	rtl8723a_set_sec_cfg(padapter, val8);
 
 	if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
 	    (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
@@ -131,23 +132,16 @@ static void sreset_restore_network_station(struct rtw_adapter *padapter)
 			threshold = 1;
 		else
 			threshold = 0;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
-	} else {
+	} else
 		threshold = 1;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
-	}
 
-	set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+	rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
 
-	/* disable dynamic functions, such as high power, DIG */
-	/* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
+	set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
+			      pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
-
-	{
-		u8	join_type = 0;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-	}
+	hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
+	hw_var_set_mlme_join(padapter, 0);
 
 	Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
 
diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
index 0dfcfbce3b52..8824dd4fb55d 100644
--- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
@@ -283,35 +283,9 @@ void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen)
 	}
 }
 
-void Save_DM_Func_Flag23a(struct rtw_adapter *padapter)
-{
-	u8	bSaveFlag = true;
-
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
-}
-
-void Restore_DM_Func_Flag23a(struct rtw_adapter *padapter)
-{
-	u8	bSaveFlag = false;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
-}
-
-void Switch_DM_Func23a(struct rtw_adapter *padapter, unsigned long mode, u8 enable)
-{
-	if (enable == true)
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
-	else
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
-}
-
-static void Set_NETYPE0_MSR(struct rtw_adapter *padapter, u8 type)
-{
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
-}
-
 void Set_MSR23a(struct rtw_adapter *padapter, u8 type)
 {
-		Set_NETYPE0_MSR(padapter, type);
+	rtl8723a_set_media_status(padapter, type);
 }
 
 inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter)
@@ -483,51 +457,9 @@ unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval)
 		return bcn_interval << 2;
 }
 
-void CAM_empty_entry23a(struct rtw_adapter *Adapter, u8 ucIndex)
-{
-	rtw_hal_set_hwreg23a(Adapter, HW_VAR_CAM_EMPTY_ENTRY, (u8 *)(&ucIndex));
-}
-
 void invalidate_cam_all23a(struct rtw_adapter *padapter)
 {
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
-}
-
-void write_cam23a(struct rtw_adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
-{
-	unsigned int	i, val, addr;
-	int j;
-	u32	cam_val[2];
-
-	addr = entry << 3;
-
-	for (j = 5; j >= 0; j--) {
-		switch (j) {
-		case 0:
-			val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
-			break;
-		case 1:
-			val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
-			break;
-		default:
-			i = (j - 2) << 2;
-			val = (key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24));
-			break;
-		}
-
-		cam_val[0] = val;
-		cam_val[1] = addr + (unsigned int)j;
-
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
-
-		/* rtw_write32(padapter, WCAMI, val); */
-
-		/* cmd = CAM_POLLINIG | CAM_WRITE | (addr + j); */
-		/* rtw_write32(padapter, RWCAM, cmd); */
-
-		/* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val); */
-
-	}
+	rtl8723a_cam_invalid_all(padapter);
 }
 
 void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry)
@@ -536,7 +468,7 @@ void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry)
 
 	unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
-	write_cam23a(padapter, entry, 0, null_sta, null_key);
+	rtl8723a_cam_write(padapter, entry, 0, null_sta, null_key);
 }
 
 int allocate_fw_sta_entry23a(struct rtw_adapter *padapter)
@@ -561,37 +493,11 @@ void flush_all_cam_entry23a(struct rtw_adapter *padapter)
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
+	rtl8723a_cam_invalid_all(padapter);
 
 	memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
 }
 
-#if defined(CONFIG_8723AU_P2P) && defined(CONFIG_8723AU_P2P)
-int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies *	pIE)
-{
-	struct wifidirect_info	*pwdinfo;
-	u8	wfd_ie[128] = {0x00};
-	u32	wfd_ielen = 0;
-
-	pwdinfo = &padapter->wdinfo;
-	if (rtw_get_wfd_ie((u8 *) pIE, pIE->Length, wfd_ie, &wfd_ielen)) {
-		u8	attr_content[ 10 ] = { 0x00 };
-		u32	attr_contentlen = 0;
-
-		DBG_8723A("[%s] Found WFD IE\n", __func__);
-		rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
-		if (attr_contentlen) {
-			pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
-			DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
-			return true;
-		}
-	} else {
-		DBG_8723A("[%s] NO WFD IE\n", __func__);
-	}
-	return _FAIL;
-}
-#endif
-
 int WMM_param_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies *	pIE)
 {
 	/* struct registry_priv	*pregpriv = &padapter->registrypriv; */
@@ -649,22 +555,22 @@ void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
 
 		switch (ACI) {
 		case 0x0:
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
+			rtl8723a_set_ac_param_be(padapter, acParm);
 			acm_mask |= (ACM? BIT(1):0);
 			edca[XMIT_BE_QUEUE] = acParm;
 			break;
 		case 0x1:
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
+			rtl8723a_set_ac_param_bk(padapter, acParm);
 			/* acm_mask |= (ACM? BIT(0):0); */
 			edca[XMIT_BK_QUEUE] = acParm;
 			break;
 		case 0x2:
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
+			rtl8723a_set_ac_param_vi(padapter, acParm);
 			acm_mask |= (ACM? BIT(2):0);
 			edca[XMIT_VI_QUEUE] = acParm;
 			break;
 		case 0x3:
-			rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
+			rtl8723a_set_ac_param_vo(padapter, acParm);
 			acm_mask |= (ACM? BIT(3):0);
 			edca[XMIT_VO_QUEUE] = acParm;
 			break;
@@ -674,7 +580,7 @@ void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
 	}
 
 	if (padapter->registrypriv.acm_method == 1)
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
+		rtl8723a_set_acm_ctrl(padapter, acm_mask);
 	else
 		padapter->mlmepriv.acm_mask = acm_mask;
 
@@ -838,7 +744,7 @@ void HT_caps_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies
 	pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
 	pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps);
 
-	rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	rf_type = rtl8723a_get_rf_type(padapter);
 
 	/* update the MCS rates */
 	for (i = 0; i < 16; i++) {
@@ -896,9 +802,8 @@ void HTOnAssocRsp23a(struct rtw_adapter *padapter)
 
 	min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
-
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+	rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing);
+	rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len);
 }
 
 void ERP_IE_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
@@ -951,116 +856,133 @@ void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
 	}
 }
 
-int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, u8 *pframe, u32 packet_len)
+int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
+			  struct ieee80211_mgmt *mgmt, u32 pkt_len)
 {
-	unsigned int		len;
-	unsigned char		*p;
-	unsigned short	val16;
 	struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
-	u16 wpa_len = 0, rsn_len = 0;
-	u8 encryp_protocol = 0;
+	struct HT_info_element *pht_info;
+	struct ieee80211_ht_cap *pht_cap;
 	struct wlan_bssid_ex *bssid;
-	int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
-	unsigned char *pbuf;
-	u32 wpa_ielen = 0;
-	u32 hidden_ssid = 0;
-	struct HT_info_element *pht_info = NULL;
-	struct ieee80211_ht_cap *pht_cap = NULL;
+	unsigned short val16;
+	u16 wpa_len = 0, rsn_len = 0;
+	u8 encryp_protocol;
+	int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0, r;
 	u32 bcn_channel;
-	unsigned short	ht_cap_info;
-	unsigned char	ht_info_infos_0;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
-	u8 *pbssid = hdr->addr3;
+	unsigned short ht_cap_info;
+	unsigned char ht_info_infos_0;
+	int len, pie_len, ie_offset;
+	const u8 *p;
+	u8 *pie;
 
 	if (is_client_associated_to_ap23a(Adapter) == false)
 		return true;
 
-	len = packet_len - sizeof(struct ieee80211_hdr_3addr);
+	if (unlikely(!ieee80211_is_beacon(mgmt->frame_control))) {
+		printk(KERN_WARNING "%s: received a non beacon frame!\n",
+		       __func__);
+		return false;
+	}
+
+	len = pkt_len - sizeof(struct ieee80211_hdr_3addr);
 
 	if (len > MAX_IE_SZ) {
 		DBG_8723A("%s IE too long for survey event\n", __func__);
 		return _FAIL;
 	}
 
-	if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
-		DBG_8723A("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n" MAC_FMT MAC_FMT,
-				MAC_ARG(pbssid), MAC_ARG(cur_network->network.MacAddress));
+	if (memcmp(cur_network->network.MacAddress, mgmt->bssid, 6)) {
+		DBG_8723A("Oops: rtw_check_network_encrypt linked but recv "
+			  "other bssid bcn\n" MAC_FMT MAC_FMT,
+			  MAC_ARG(mgmt->bssid),
+			  MAC_ARG(cur_network->network.MacAddress));
 		return true;
 	}
 
 	bssid = (struct wlan_bssid_ex *)kzalloc(sizeof(struct wlan_bssid_ex),
 		GFP_ATOMIC);
 
-	if (ieee80211_is_beacon(hdr->frame_control))
-		bssid->reserved = 1;
+	bssid->reserved = 1;
 
 	bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
 
 	/* below is to copy the information element */
 	bssid->IELength = len;
-	memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
+	memcpy(bssid->IEs, &mgmt->u, bssid->IELength);
 
 	/* check bw and channel offset */
 	/* parsing HT_CAP_IE */
-	p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-	if (p && len>0) {
-			pht_cap = (struct ieee80211_ht_cap *)(p + 2);
-			ht_cap_info = pht_cap->cap_info;
+	ie_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable) -
+		offsetof(struct ieee80211_mgmt, u);
+	pie = bssid->IEs + ie_offset;
+	pie_len = pkt_len - ie_offset;
+
+	p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
+	if (p && p[1] > 0) {
+		pht_cap = (struct ieee80211_ht_cap *)(p + 2);
+		ht_cap_info = pht_cap->cap_info;
 	} else {
-			ht_cap_info = 0;
+		pht_cap = NULL;
+		ht_cap_info = 0;
 	}
+
 	/* parsing HT_INFO_IE */
-	p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-	if (p && len>0) {
-			pht_info = (struct HT_info_element *)(p + 2);
-			ht_info_infos_0 = pht_info->infos[0];
+	p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, pie_len);
+	if (p && p[1] > 0) {
+		pht_info = (struct HT_info_element *)(p + 2);
+		ht_info_infos_0 = pht_info->infos[0];
 	} else {
-			ht_info_infos_0 = 0;
+		pht_info = NULL;
+		ht_info_infos_0 = 0;
 	}
+
 	if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
-		((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) {
-			DBG_8723A("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
-							ht_cap_info, ht_info_infos_0);
-			DBG_8723A("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
-							cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
-			DBG_8723A("%s bw mode change, disconnect\n", __func__);
-			/* bcn_info_update */
-			cur_network->BcnInfo.ht_cap_info = ht_cap_info;
-			cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
-			/* to do : need to check that whether modify related register of BB or not */
+	    ((ht_info_infos_0 & 0x03) !=
+	     (cur_network->BcnInfo.ht_info_infos_0 & 0x03))) {
+		DBG_8723A("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n",
+			  __func__, ht_cap_info, ht_info_infos_0);
+		DBG_8723A("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n",
+			  __func__, cur_network->BcnInfo.ht_cap_info,
+			  cur_network->BcnInfo.ht_info_infos_0);
+		DBG_8723A("%s bw mode change, disconnect\n", __func__);
+		/* bcn_info_update */
+		cur_network->BcnInfo.ht_cap_info = ht_cap_info;
+		cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
+		/* to do : need to check that whether modify related
+		   register of BB or not */
 	}
 
 	/* Checking for channel */
-	p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-	if (p) {
-			bcn_channel = *(p + 2);
-	} else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
-			p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-			if (pht_info) {
-					bcn_channel = pht_info->primary_channel;
-			} else { /* we don't find channel IE, so don't check it */
-					DBG_8723A("Oops: %s we don't find channel IE, so don't check it\n", __func__);
-					bcn_channel = Adapter->mlmeextpriv.cur_channel;
-			}
+	p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, pie, pie_len);
+	if (p)
+		bcn_channel = p[2];
+	else {
+		/* In 5G, some ap do not have DSSET IE checking HT
+		   info for channel */
+		p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, pie_len);
+
+		if (pht_info)
+			bcn_channel = pht_info->primary_channel;
+		else { /* we don't find channel IE, so don't check it */
+			DBG_8723A("Oops: %s we don't find channel IE, so don't "
+				  "check it\n", __func__);
+			bcn_channel = Adapter->mlmeextpriv.cur_channel;
+		}
 	}
 	if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
-			DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
-						   bcn_channel, Adapter->mlmeextpriv.cur_channel);
-			goto _mismatch;
+		DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n",
+			  __func__, bcn_channel,
+			  Adapter->mlmeextpriv.cur_channel);
+		goto _mismatch;
 	}
 
 	/* checking SSID */
-	if ((p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_)) == NULL) {
-		DBG_8723A("%s marc: cannot find SSID for survey event\n", __func__);
-		hidden_ssid = true;
-	} else {
-		hidden_ssid = false;
-	}
-
-	if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) {
-		memcpy(bssid->Ssid.ssid, (p + 2), *(p + 1));
-		bssid->Ssid.ssid_len = *(p + 1);
+	p = cfg80211_find_ie(WLAN_EID_SSID, pie, pie_len);
+	if (p && p[1]) {
+		memcpy(bssid->Ssid.ssid, p + 2, p[1]);
+		bssid->Ssid.ssid_len = p[1];
 	} else {
+		DBG_8723A("%s marc: cannot find SSID for survey event\n",
+			  __func__);
 		bssid->Ssid.ssid_len = 0;
 		bssid->Ssid.ssid[0] = '\0';
 	}
@@ -1091,60 +1013,83 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, u8 *pframe, u32 packet_le
 		bssid->Privacy = 0;
 
 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-			("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
-			 __func__, cur_network->network.Privacy, bssid->Privacy));
+		 ("%s(): cur_network->network.Privacy is %d, bssid.Privacy "
+		  "is %d\n", __func__, cur_network->network.Privacy,
+		  bssid->Privacy));
 	if (cur_network->network.Privacy != bssid->Privacy) {
 		DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
 		goto _mismatch;
 	}
 
-	rtw_get_sec_ie23a(bssid->IEs, bssid->IELength, NULL,&rsn_len, NULL,&wpa_len);
+	rtw_get_sec_ie23a(bssid->IEs, bssid->IELength, NULL, &rsn_len, NULL,
+			  &wpa_len);
 
-	if (rsn_len > 0) {
+	if (rsn_len > 0)
 		encryp_protocol = ENCRYP_PROTOCOL_WPA2;
-	} else if (wpa_len > 0) {
+	else if (wpa_len > 0)
 		encryp_protocol = ENCRYP_PROTOCOL_WPA;
-	} else {
+	else {
 		if (bssid->Privacy)
 			encryp_protocol = ENCRYP_PROTOCOL_WEP;
+		else
+			encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
 	}
 
 	if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
-		DBG_8723A("%s(): enctyp is not match , return FAIL\n", __func__);
+		DBG_8723A("%s(): enctyp is not match, return FAIL\n", __func__);
 		goto _mismatch;
 	}
 
-	if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
-		pbuf = rtw_get_wpa_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
-		if (pbuf && (wpa_ielen>0)) {
-			if (_SUCCESS == rtw_parse_wpa_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
+	if (encryp_protocol == ENCRYP_PROTOCOL_WPA ||
+	    encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
+		p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+					    WLAN_OUI_TYPE_MICROSOFT_WPA,
+					    pie, pie_len);
+		if (p && p[1] > 0) {
+			r = rtw_parse_wpa_ie23a(p, p[1] + 2, &group_cipher,
+						&pairwise_cipher, &is_8021x);
+			if (r == _SUCCESS)
 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-						("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
-						 pairwise_cipher, group_cipher, is_8021x));
-			}
+					 ("%s pnetwork->pairwise_cipher: %d, "
+					  "group_cipher is %d, is_8021x is "
+					  "%d\n", __func__, pairwise_cipher,
+					  group_cipher, is_8021x));
 		} else {
-			pbuf = rtw_get_wpa2_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
-
-			if (pbuf && (wpa_ielen>0)) {
-				if (_SUCCESS == rtw_parse_wpa2_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
-					RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-							("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
-							 __func__, pairwise_cipher, group_cipher, is_8021x));
-				}
+			p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
+
+			if (p && p[1] > 0) {
+				r = rtw_parse_wpa2_ie23a(p, p[1] + 2,
+							 &group_cipher,
+							 &pairwise_cipher,
+							 &is_8021x);
+				if (r == _SUCCESS)
+					RT_TRACE(_module_rtl871x_mlme_c_,
+						 _drv_info_,
+						 ("%s pnetwork->pairwise_cipher"
+						  ": %d, pnetwork->group_cipher"
+						  " is %d, is_802x is %d\n",
+						  __func__, pairwise_cipher,
+						  group_cipher, is_8021x));
 			}
 		}
 
 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-				("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher));
-		if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
-			DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__,
-					pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
-					group_cipher, cur_network->BcnInfo.group_cipher);
+			 ("%s cur_network->group_cipher is %d: %d\n", __func__,
+			  cur_network->BcnInfo.group_cipher, group_cipher));
+		if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher ||
+		    group_cipher != cur_network->BcnInfo.group_cipher) {
+			DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher "
+				  "(%x:%x) is not match, return FAIL\n",
+				  __func__, pairwise_cipher,
+				  cur_network->BcnInfo.pairwise_cipher,
+				  group_cipher,
+				  cur_network->BcnInfo.group_cipher);
 			goto _mismatch;
 		}
 
 		if (is_8021x != cur_network->BcnInfo.is_8021x) {
-			DBG_8723A("%s authentication is not match , return FAIL\n", __func__);
+			DBG_8723A("%s authentication is not match, return "
+				  "FAIL\n", __func__);
 			goto _mismatch;
 		}
 	}
@@ -1171,11 +1116,11 @@ void update_beacon23a_info(struct rtw_adapter *padapter, u8 *pframe, uint pkt_le
 		pIE = (struct ndis_802_11_var_ies *)(pframe + (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr)) + i);
 
 		switch (pIE->ElementID) {
-		case _HT_EXTRA_INFO_IE_:	/* HT info */
+		case WLAN_EID_HT_OPERATION:	/* HT info */
 			/* HT_info_handler23a(padapter, pIE); */
 			bwmode_update_check(padapter, pIE);
 			break;
-		case _ERPINFO_IE_:
+		case WLAN_EID_ERP_INFO:
 			ERP_IE_handler23a(padapter, pIE);
 			VCS_update23a(padapter, psta);
 			break;
@@ -1199,11 +1144,11 @@ unsigned int is_ap_in_tkip23a(struct rtw_adapter *padapter)
 			pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
 
 			switch (pIE->ElementID) {
-			case _VENDOR_SPECIFIC_IE_:
-				if ((!memcmp(pIE->data, RTW_WPA_OUI23A, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER23A, 4)))
+			case WLAN_EID_VENDOR_SPECIFIC:
+				if ((!memcmp(pIE->data, RTW_WPA_OUI23A_TYPE, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER23A, 4)))
 					return true;
 				break;
-			case _RSN_IE_2_:
+			case WLAN_EID_RSN:
 				if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER23A, 4))
 					return true;
 				break;
@@ -1230,13 +1175,13 @@ unsigned int should_forbid_n_rate23a(struct rtw_adapter * padapter)
 			pIE = (struct ndis_802_11_var_ies *)(cur_network->IEs + i);
 
 			switch (pIE->ElementID) {
-			case _VENDOR_SPECIFIC_IE_:
-				if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4) &&
+			case WLAN_EID_VENDOR_SPECIFIC:
+				if (!memcmp(pIE->data, RTW_WPA_OUI23A_TYPE, 4) &&
 					((!memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP23A, 4)) ||
 					  (!memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP23A, 4))))
 					return false;
 				break;
-			case _RSN_IE_2_:
+			case WLAN_EID_RSN:
 				if  ((!memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP23A, 4))  ||
 				       (!memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP23A, 4)))
 				return false;
@@ -1265,11 +1210,11 @@ unsigned int is_ap_in_wep23a(struct rtw_adapter *padapter)
 			pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
 
 			switch (pIE->ElementID) {
-			case _VENDOR_SPECIFIC_IE_:
-				if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4))
+			case WLAN_EID_VENDOR_SPECIFIC:
+				if (!memcmp(pIE->data, RTW_WPA_OUI23A_TYPE, 4))
 					return false;
 				break;
-			case _RSN_IE_2_:
+			case WLAN_EID_RSN:
 				return false;
 
 			default:
@@ -1432,15 +1377,6 @@ void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta)
 void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode)
 {
 	unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info*	pwdinfo = &padapter->wdinfo;
-
-	/*	Added by Albert 2011/03/22 */
-	/*	In the P2P mode, the driver should not support the b mode. */
-	/*	So, the Tx packet shouldn't use the CCK rate */
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
-		return;
-#endif /* CONFIG_8723AU_P2P */
 
 	memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
 
@@ -1457,7 +1393,7 @@ void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode)
 	else
 		update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, supported_rates);
+	HalSetBrateCfg23a(padapter, supported_rates);
 }
 
 unsigned char check_assoc_AP23a(u8 *pframe, uint len)
@@ -1473,7 +1409,7 @@ unsigned char check_assoc_AP23a(u8 *pframe, uint len)
 		pIE = (struct ndis_802_11_var_ies *)(pframe + i);
 
 		switch (pIE->ElementID) {
-		case _VENDOR_SPECIFIC_IE_:
+		case WLAN_EID_VENDOR_SPECIFIC:
 			if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
 			    (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
 				DBG_8723A("link to Artheros AP\n");
@@ -1546,15 +1482,15 @@ void update_IOT_info23a(struct rtw_adapter *padapter)
 		pmlmeinfo->turboMode_cts2self = 0;
 		pmlmeinfo->turboMode_rtsen = 1;
 		/* disable high power */
-		Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
-			       false);
+		rtl8723a_odm_support_ability_clr(padapter, (u32)
+						 ~DYNAMIC_BB_DYNAMIC_TXPWR);
 		break;
 	case HT_IOT_PEER_REALTEK:
 		/* rtw_write16(padapter, 0x4cc, 0xffff); */
 		/* rtw_write16(padapter, 0x546, 0x01c0); */
 		/* disable high power */
-		Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
-			       false);
+		rtl8723a_odm_support_ability_clr(padapter, (u32)
+						 ~DYNAMIC_BB_DYNAMIC_TXPWR);
 		break;
 	default:
 		pmlmeinfo->turboMode_cts2self = 0;
@@ -1567,22 +1503,19 @@ void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap)
 {
 	struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
-	bool		ShortPreamble;
 
 	if (updateCap & cShortPreamble) {
 		/*  Short Preamble */
 		if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) {
 			/*  PREAMBLE_LONG or PREAMBLE_AUTO */
-			ShortPreamble = true;
 			pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
-			rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
+			rtl8723a_ack_preamble(Adapter, true);
 		}
 	} else { /*  Long Preamble */
 		if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) {
 			/*  PREAMBLE_SHORT or PREAMBLE_AUTO */
-			ShortPreamble = false;
 			pmlmeinfo->preamble_mode = PREAMBLE_LONG;
-			rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
+			rtl8723a_ack_preamble(Adapter, false);
 		}
 	}
 	if (updateCap & cIBSS) {
@@ -1605,13 +1538,12 @@ void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap)
 			pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
 		}
 	}
-	rtw_hal_set_hwreg23a(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
+	rtl8723a_set_slot_time(Adapter, pmlmeinfo->slotTime);
 }
 
 void update_wireless_mode23a(struct rtw_adapter *padapter)
 {
 	int ratelen, network_type = 0;
-	u32 SIFS_Timer;
 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 	struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
@@ -1640,10 +1572,9 @@ void update_wireless_mode23a(struct rtw_adapter *padapter)
 
 	pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
 
-	SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
-                             /* change this value if having IOT issues. */
-
-	padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS,  (u8 *)&SIFS_Timer);
+	/* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
+	/* change this value if having IOT issues. */
+	rtl8723a_set_resp_sifs(padapter, 0x08, 0x08, 0x0a, 0x0a);
 
 	if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
 		update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
@@ -1664,24 +1595,25 @@ void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id)
 	}
 }
 
-int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
+int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie,
+			       uint var_ie_len, int cam_idx)
 {
-	unsigned int	ie_len;
-	struct ndis_802_11_var_ies *pIE;
-	int	supportRateNum = 0;
+	int supportRateNum = 0;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+	const u8 *p;
 
-	pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
-	if (pIE == NULL)
+	p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pvar_ie, var_ie_len);
+	if (!p)
 		return _FAIL;
 
-	memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
-	supportRateNum = ie_len;
+	memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, p + 2, p[1]);
+	supportRateNum = p[1];
 
-	pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
-	if (pIE)
-		memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
+	p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pvar_ie, var_ie_len);
+	if (p)
+		memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates +
+		       supportRateNum, p + 2, p[1]);
 	return _SUCCESS;
 }
 
@@ -1711,26 +1643,6 @@ void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr
 	}
 }
 
-void update_TSF23a(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
-{
-	u8 *pIE;
-	u32 *pbuf;
-
-	pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
-	pbuf = (u32 *)pIE;
-
-	pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1));
-
-	pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
-
-	pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
-}
-
-void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext)
-{
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_CORRECT_TSF, NULL);
-}
-
 void beacon_timing_control23a(struct rtw_adapter *padapter)
 {
 	rtw_hal_bcn_related_reg_setting23a(padapter);
diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c
index 0f10cfa10d39..e7252d16c989 100644
--- a/drivers/staging/rtl8723au/core/rtw_xmit.c
+++ b/drivers/staging/rtl8723au/core/rtw_xmit.c
@@ -443,21 +443,17 @@ u8 qos_acm23a(u8 acm_mask, u8 priority)
 	return change_priority;
 }
 
-static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
+static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib)
 {
-	struct ethhdr etherhdr;
-	struct iphdr ip_hdr;
+	u8 *pframe = skb->data;
+	struct iphdr *ip_hdr;
 	s32 UserPriority = 0;
 
-	_rtw_open_pktfile23a(ppktfile->pkt, ppktfile);
-	_rtw_pktfile_read23a(ppktfile, (unsigned char*)&etherhdr, ETH_HLEN);
-
 	/*  get UserPriority from IP hdr */
-	if (pattrib->ether_type == 0x0800) {
-		_rtw_pktfile_read23a(ppktfile, (u8*)&ip_hdr, sizeof(ip_hdr));
-/*		UserPriority = (ntohs(ip_hdr.tos) >> 5) & 0x3; */
-		UserPriority = ip_hdr.tos >> 5;
-	} else if (pattrib->ether_type == 0x888e) {
+	if (pattrib->ether_type == ETH_P_IP) {
+		ip_hdr = (struct iphdr *)(pframe + ETH_HLEN);
+		UserPriority = ip_hdr->tos >> 5;
+	} else if (pattrib->ether_type == ETH_P_PAE) {
 		/*  "When priority processing of data frames is supported, */
 		/*  a STA's SME should send EAPOL-Key frames at the highest
 		    priority." */
@@ -470,57 +466,53 @@ static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
 }
 
 static s32 update_attrib(struct rtw_adapter *padapter,
-			 struct sk_buff *pkt, struct pkt_attrib *pattrib)
+			 struct sk_buff *skb, struct pkt_attrib *pattrib)
 {
-	uint i;
-	struct pkt_file pktfile;
 	struct sta_info *psta = NULL;
-	struct ethhdr etherhdr;
-
 	int bmcast;
 	struct sta_priv	*pstapriv = &padapter->stapriv;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct qos_priv	*pqospriv = &pmlmepriv->qospriv;
 	int res = _SUCCESS;
+	struct ethhdr *ehdr = (struct ethhdr *) skb->data;
 
-	_rtw_open_pktfile23a(pkt, &pktfile);
-	i = _rtw_pktfile_read23a(&pktfile, (u8*)&etherhdr, ETH_HLEN);
-
-	pattrib->ether_type = ntohs(etherhdr.h_proto);
+	pattrib->ether_type = ntohs(ehdr->h_proto);
 
-	memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
-	memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
+	ether_addr_copy(pattrib->dst, ehdr->h_dest);
+	ether_addr_copy(pattrib->src, ehdr->h_source);
 
 	pattrib->pctrl = 0;
 
 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
 		(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
-		memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
-		memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+		ether_addr_copy(pattrib->ra, pattrib->dst);
+		ether_addr_copy(pattrib->ta, pattrib->src);
 	}
 	else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
-		memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
-		memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+		ether_addr_copy(pattrib->ra, get_bssid(pmlmepriv));
+		ether_addr_copy(pattrib->ta, pattrib->src);
 	}
 	else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
-		memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
-		memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
+		ether_addr_copy(pattrib->ra, pattrib->dst);
+		ether_addr_copy(pattrib->ta, get_bssid(pmlmepriv));
 	}
 
-	pattrib->pktlen = pktfile.pkt_len;
+	pattrib->pktlen = skb->len - ETH_HLEN;
 
 	if (pattrib->ether_type == ETH_P_IP) {
 		/*  The following is for DHCP and ARP packet, we use cck1M
 		    to tx these packets and let LPS awake some time */
 		/*  to prevent DHCP protocol fail */
-		u8 tmp[24];
-		_rtw_pktfile_read23a(&pktfile, &tmp[0], 24);
 		pattrib->dhcp_pkt = 0;
-		if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */
-			if (ETH_P_IP == pattrib->ether_type) {/*  IP header */
-				if (((tmp[21] == 68) && (tmp[23] == 67)) ||
-				    ((tmp[21] == 67) && (tmp[23] == 68))) {
+		/* MINIMUM_DHCP_PACKET_SIZE) { */
+		if (pattrib->pktlen > 282 + 24) {
+			if (pattrib->ether_type == ETH_P_IP) {/*  IP header */
+				u8 *pframe = skb->data;
+				pframe += ETH_HLEN;
+
+				if ((pframe[21] == 68 && pframe[23] == 67) ||
+				    (pframe[21] == 67 && pframe[23] == 68)) {
 					/*  68 : UDP BOOTP client */
 					/*  67 : UDP BOOTP server */
 					RT_TRACE(_module_rtl871x_xmit_c_,
@@ -532,17 +524,17 @@ static s32 update_attrib(struct rtw_adapter *padapter,
 				}
 			}
 		}
-	} else if (0x888e == pattrib->ether_type) {
+	} else if (pattrib->ether_type == ETH_P_PAE) {
 		DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n");
 	}
 
-	if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) {
+	if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) {
 		rtw_set_scan_deny(padapter, 3000);
 	}
 
 	/*  If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */
-	if ((pattrib->ether_type == 0x0806) ||
-	    (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) {
+	if ((pattrib->ether_type == ETH_P_ARP) ||
+	    (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) {
 		rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
 	}
 
@@ -592,10 +584,10 @@ static s32 update_attrib(struct rtw_adapter *padapter,
 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE |
 			  WIFI_ADHOC_MASTER_STATE)) {
 		if (psta->qos_option)
-			set_qos(&pktfile, pattrib);
+			set_qos(skb, pattrib);
 	} else {
 		if (pqospriv->qos_option) {
-			set_qos(&pktfile, pattrib);
+			set_qos(skb, pattrib);
 
 			if (pmlmepriv->acm_mask != 0) {
 				pattrib->priority = qos_acm23a(pmlmepriv->acm_mask,
@@ -610,7 +602,7 @@ static s32 update_attrib(struct rtw_adapter *padapter,
 
 		pattrib->encrypt = 0;
 
-		if ((pattrib->ether_type != 0x888e) &&
+		if ((pattrib->ether_type != ETH_P_PAE) &&
 		    (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)) {
 			RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
 				 ("\npsta->ieee8021x_blocked == true,  "
@@ -1116,39 +1108,40 @@ This sub-routine will perform all the following:
 6. apply sw-encrypt, if necessary.
 
 */
-s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
+s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb,
 			      struct xmit_frame *pxmitframe)
 {
-	struct pkt_file pktfile;
-	struct sta_info		*psta;
-	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
-	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_info *psta;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	struct pkt_attrib *pattrib = &pxmitframe->attrib;
 	s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
 	u8 *pframe, *mem_start;
 	u8 hw_hdr_offset;
 	u8 *pbuf_start;
-
+	u8 *pdata = skb->data;
+	int data_len = skb->len;
 	s32 bmcst = is_multicast_ether_addr(pattrib->ra);
 	s32 res = _SUCCESS;
 
-	if (pattrib->psta) {
+	if (pattrib->psta)
 		psta = pattrib->psta;
-	} else {
+	else {
 		DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
 		psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
 	}
 
-	if (psta == NULL) {
+	if (!psta) {
 		DBG_8723A("%s, psta == NUL\n", __func__);
 		return _FAIL;
 	}
 
 	if (!(psta->state &_FW_LINKED)) {
-		DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
+			  __func__, psta->state);
 		return _FAIL;
 	}
 
-	if (pxmitframe->buf_addr == NULL) {
+	if (!pxmitframe->buf_addr) {
 		DBG_8723A("==> %s buf_addr == NULL\n", __func__);
 		return _FAIL;
 	}
@@ -1157,7 +1150,7 @@ s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
 
 	hw_hdr_offset = TXDESC_OFFSET;
 
-	mem_start = pbuf_start +	hw_hdr_offset;
+	mem_start = pbuf_start + hw_hdr_offset;
 
 	if (rtw_make_wlanhdr23a(padapter, mem_start, pattrib) == _FAIL) {
 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
@@ -1167,8 +1160,8 @@ s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
 		goto exit;
 	}
 
-	_rtw_open_pktfile23a(pkt, &pktfile);
-	_rtw_pktfile_read23a(&pktfile, NULL, pattrib->pkt_hdrlen);
+	pdata += pattrib->pkt_hdrlen;
+	data_len -= pattrib->pkt_hdrlen;
 
 	frg_inx = 0;
 	frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */
@@ -1187,23 +1180,30 @@ s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
 
 		/* adding icv, if necessary... */
 		if (pattrib->iv_len) {
-			if (psta != NULL) {
+			if (psta) {
 				switch (pattrib->encrypt) {
 				case _WEP40_:
 				case _WEP104_:
-					WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+					WEP_IV(pattrib->iv, psta->dot11txpn,
+					       pattrib->key_idx);
 					break;
 				case _TKIP_:
 					if (bmcst)
-						TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+						TKIP_IV(pattrib->iv,
+							psta->dot11txpn,
+							pattrib->key_idx);
 					else
-						TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+						TKIP_IV(pattrib->iv,
+							psta->dot11txpn, 0);
 					break;
 				case _AES_:
 					if (bmcst)
-						AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+						AES_IV(pattrib->iv,
+						       psta->dot11txpn,
+						       pattrib->key_idx);
 					else
-						AES_IV(pattrib->iv, psta->dot11txpn, 0);
+						AES_IV(pattrib->iv,
+						       psta->dot11txpn, 0);
 					break;
 				}
 			}
@@ -1225,16 +1225,20 @@ s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
 			mpdu_len -= llc_sz;
 		}
 
-		if ((pattrib->icv_len >0) && (pattrib->bswenc))
+		if (pattrib->icv_len > 0 && pattrib->bswenc)
 			mpdu_len -= pattrib->icv_len;
 
-		if (bmcst) {
+		if (bmcst)
 			/*  don't do fragment to broadcat/multicast packets */
-			mem_sz = _rtw_pktfile_read23a(&pktfile, pframe, pattrib->pktlen);
-		} else {
-			mem_sz = _rtw_pktfile_read23a(&pktfile, pframe, mpdu_len);
-		}
+			mem_sz = min_t(s32, data_len, pattrib->pktlen);
+		else
+			mem_sz = min_t(s32, data_len, mpdu_len);
+
+		memcpy(pframe, pdata, mem_sz);
+
 		pframe += mem_sz;
+		pdata += mem_sz;
+		data_len -= mem_sz;
 
 		if ((pattrib->icv_len >0) && (pattrib->bswenc)) {
 			memcpy(pframe, pattrib->icv, pattrib->icv_len);
@@ -1243,7 +1247,7 @@ s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
 
 		frg_inx++;
 
-		if (bmcst || (rtw_endofpktfile23a(&pktfile))) {
+		if (bmcst || data_len <= 0) {
 			pattrib->nr_frags = frg_inx;
 
 			pattrib->last_txcmdsz = pattrib->hdrlen +
@@ -1257,16 +1261,18 @@ s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
 
 			break;
 		} else {
-			RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__));
+			RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+				 ("%s: There're still something in packet!\n",
+				  __func__));
 		}
 
 		mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset;
 		memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
-
 	}
 
 	if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
-		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+			 ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
 		DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
 		res = _FAIL;
 		goto exit;
@@ -1313,11 +1319,10 @@ s32 rtw_put_snap23a(u8 *data, u16 h_proto)
 
 void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len)
 {
-	struct	xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct	registry_priv *pregistrypriv = &padapter->registrypriv;
-	uint	protection;
-	u8	*perp;
-	int	 erp_len;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	uint protection;
+	const u8 *p;
 
 	switch (pxmitpriv->vcs_setting) {
 	case DISABLE_VCS:
@@ -1327,11 +1332,11 @@ void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len)
 		break;
 	case AUTO_VCS:
 	default:
-		perp = rtw_get_ie23a(ie, _ERPINFO_IE_, &erp_len, ie_len);
-		if (perp == NULL) {
+		p = cfg80211_find_ie(WLAN_EID_ERP_INFO, ie, ie_len);
+		if (!p)
 			pxmitpriv->vcs = NONE_VCS;
-		} else {
-			protection = (*(perp + 2)) & BIT(1);
+		else {
+			protection = (*(p + 2)) & BIT(1);
 			if (protection) {
 				if (pregistrypriv->vcs_type == RTS_CTS)
 					pxmitpriv->vcs = RTS_CTS;
@@ -2036,7 +2041,8 @@ int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct x
 
 			/* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
 
-			update_beacon23a(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */
+			/* tx bc/mc packets after upate bcn */
+			update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 
 			/* spin_unlock_bh(&psta->sleep_q.lock); */
 
@@ -2093,7 +2099,8 @@ int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct x
 
 				if (psta->sleepq_len == 1) {
 					/* upate BCN for TIM IE */
-					update_beacon23a(padapter, _TIM_IE_, NULL, false);
+					update_beacon23a(padapter, WLAN_EID_TIM,
+							 NULL, false);
 				}
 			}
 
@@ -2307,7 +2314,7 @@ void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta)
 	}
 
 	if (update_mask)
-		update_beacon23a(padapter, _TIM_IE_, NULL, false);
+		update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 }
 
 void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter,
@@ -2372,7 +2379,7 @@ void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter,
 			pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
 
 			/* upate BCN for TIM IE */
-			update_beacon23a(padapter, _TIM_IE_, NULL, false);
+			update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
 		}
 	}
 	spin_unlock_bh(&pxmitpriv->lock);
diff --git a/drivers/staging/rtl8723au/hal/hal_com.c b/drivers/staging/rtl8723au/hal/hal_com.c
index 0640f3522136..d1701a35bc90 100644
--- a/drivers/staging/rtl8723au/hal/hal_com.c
+++ b/drivers/staging/rtl8723au/hal/hal_com.c
@@ -344,12 +344,6 @@ bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe)
 	return result;
 }
 
-void hal_init_macaddr23a(struct rtw_adapter *adapter)
-{
-	rtw_hal_set_hwreg23a(adapter, HW_VAR_MAC_ADDR,
-			  adapter->eeprompriv.mac_addr);
-}
-
 /*
 * C2H event format:
 * Field	 TRIGGER		CONTENT	   CMD_SEQ	CMD_LEN		 CMD_ID
@@ -676,11 +670,13 @@ void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
 		/* delay_ms(40); */
 		rtw_write32(padapter, WCAMI, ulContent);
 		/* RT_TRACE(COMP_SEC, DBG_LOUD,
-		   ("CAM_empty_entry23a(): WRITE A4: %lx \n", ulContent));*/
+		   ("rtl8723a_cam_empty_entry(): WRITE A4: %lx \n",
+		   ulContent));*/
 		/* delay_ms(40); */
 		rtw_write32(padapter, RWCAM, ulCommand);
 		/* RT_TRACE(COMP_SEC, DBG_LOUD,
-		   ("CAM_empty_entry23a(): WRITE A0: %lx \n", ulCommand));*/
+		   ("rtl8723a_cam_empty_entry(): WRITE A0: %lx \n",
+		   ulCommand));*/
 	}
 }
 
@@ -689,14 +685,37 @@ void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter)
 	rtw_write32(padapter, RWCAM, BIT(31) | BIT(30));
 }
 
-void rtl8723a_cam_write(struct rtw_adapter *padapter, u32 val1, u32 val2)
+void rtl8723a_cam_write(struct rtw_adapter *padapter,
+			u8 entry, u16 ctrl, u8 *mac, u8 *key)
 {
 	u32 cmd;
+	unsigned int i, val, addr;
+	int j;
+
+	addr = entry << 3;
+
+	for (j = 5; j >= 0; j--) {
+		switch (j) {
+		case 0:
+			val = ctrl | (mac[0] << 16) | (mac[1] << 24);
+			break;
+		case 1:
+			val = mac[2] | (mac[3] << 8) |
+				(mac[4] << 16) | (mac[5] << 24);
+			break;
+		default:
+			i = (j - 2) << 2;
+			val = key[i] | (key[i+1] << 8) |
+				(key[i+2] << 16) | (key[i+3] << 24);
+			break;
+		}
 
-	rtw_write32(padapter, WCAMI, val1);
+		rtw_write32(padapter, WCAMI, val);
+		cmd = CAM_POLLINIG | CAM_WRITE | (addr + j);
+		rtw_write32(padapter, RWCAM, cmd);
 
-	cmd = CAM_POLLINIG | CAM_WRITE | val2;
-	rtw_write32(padapter, RWCAM, cmd);
+		/* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/
+	}
 }
 
 void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
@@ -736,14 +755,6 @@ void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
 	}
 }
 
-void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val)
-{
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
-
-	pHalData->bMacPwrCtrlOn = val;
-	DBG_8723A("%s: bMacPwrCtrlOn =%d\n", __func__, pHalData->bMacPwrCtrlOn);
-}
-
 void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
 {
 	/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
@@ -752,9 +763,13 @@ void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
 		   rtw_read8(padapter, REG_TDECTRL + 2) | BIT0);
 }
 
-void rtl8723a_set_tx_pause(struct rtw_adapter *padapter, u8 pause)
+bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter)
 {
-	rtw_write8(padapter, REG_TXPAUSE, pause);
+	bool retval;
+
+	retval = (rtw_read8(padapter, REG_TDECTRL + 2) & BIT0) ? true : false;
+
+	return retval;
 }
 
 void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
@@ -837,23 +852,18 @@ void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
 	}
 }
 
-void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val)
+void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter)
 {
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 
-	pHalData->odmpriv.SupportAbility = val;
+	pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility;
 }
 
-void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter, u8 val)
+void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter)
 {
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 
-	if (val)	/*  save dm flag */
-		pHalData->odmpriv.BK_SupportAbility =
-			pHalData->odmpriv.SupportAbility;
-	else		/*  restore dm flag */
-		pHalData->odmpriv.SupportAbility =
-			pHalData->odmpriv.BK_SupportAbility;
+	pHalData->odmpriv.BK_SupportAbility = pHalData->odmpriv.SupportAbility;
 }
 
 void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
@@ -879,3 +889,42 @@ void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
 {
 	rtw_write8(padapter, REG_USB_HRPWM, val);
 }
+
+u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter)
+{
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
+
+	return pHalData->rf_type;
+}
+
+bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter)
+{
+	bool retval;
+	u32 valRCR;
+
+	/*  When we halt NIC, we should check if FW LPS is leave. */
+
+	if ((padapter->bSurpriseRemoved == true) ||
+	    (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
+		/*  If it is in HW/SW Radio OFF or IPS state, we do
+		    not check Fw LPS Leave, because Fw is unload. */
+		retval = true;
+	} else {
+		valRCR = rtw_read32(padapter, REG_RCR);
+		if (valRCR & 0x00070000)
+			retval = false;
+		else
+			retval = true;
+	}
+
+	return retval;
+}
+
+bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter)
+{
+	u32 hgq;
+
+	hgq = rtw_read32(padapter, REG_HGQ_INFORMATION);
+
+	return ((hgq & 0x0000ff00) == 0) ? true : false;
+}
diff --git a/drivers/staging/rtl8723au/hal/hal_intf.c b/drivers/staging/rtl8723au/hal/hal_intf.c
index de3608b4010a..04cc53424b51 100644
--- a/drivers/staging/rtl8723au/hal/hal_intf.c
+++ b/drivers/staging/rtl8723au/hal/hal_intf.c
@@ -117,18 +117,6 @@ uint rtw_hal_deinit23a(struct rtw_adapter *padapter)
 	return status;
 }
 
-void rtw_hal_set_hwreg23a(struct rtw_adapter *padapter, u8 variable, u8 *val)
-{
-	if (padapter->HalFunc.SetHwRegHandler)
-		padapter->HalFunc.SetHwRegHandler(padapter, variable, val);
-}
-
-void rtw23a_hal_get_hwreg(struct rtw_adapter *padapter, u8 variable, u8 *val)
-{
-	if (padapter->HalFunc.GetHwRegHandler)
-		padapter->HalFunc.GetHwRegHandler(padapter, variable, val);
-}
-
 u8 rtw_hal_set_def_var23a(struct rtw_adapter *padapter, enum hal_def_variable eVariable, void *pValue)
 {
 	if (padapter->HalFunc.SetHalDefVarHandler)
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c
index 9d738d79de4b..69041efe5c36 100644
--- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c
@@ -3944,7 +3944,6 @@ bthci_CmdAMPTestEnd(struct rtw_adapter *padapter,
 	enum hci_status status = HCI_STATUS_SUCCESS;
 	struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
 	struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
-	u8 bFilterOutNonAssociatedBSSID = true;
 
 	if (!pBtHciInfo->bInTestMode) {
 		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status = HCI_STATUS_CMD_DISALLOW\n"));
@@ -3956,7 +3955,7 @@ bthci_CmdAMPTestEnd(struct rtw_adapter *padapter,
 
 	del_timer_sync(&pBTInfo->BTTestSendPacketTimer);
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_CHECK_BSSID, (u8 *)(&bFilterOutNonAssociatedBSSID));
+	rtl8723a_check_bssid(padapter, true);
 
 	/* send command complete event here when all data are received. */
 	{
@@ -4057,8 +4056,7 @@ bthci_CmdAMPTestCommand(struct rtw_adapter *padapter,
 			  jiffies + msecs_to_jiffies(50));
 		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n"));
 	} else if (pBtHciInfo->TestScenario == 0x02) {
-		u8 bFilterOutNonAssociatedBSSID = false;
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_CHECK_BSSID, (u8 *)(&bFilterOutNonAssociatedBSSID));
+		rtl8723a_check_bssid(padapter, false);
 		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n"));
 	}
 
@@ -4677,7 +4675,7 @@ bthci_StateConnected(struct rtw_adapter *padapter,
 		if (padapter->HalFunc.UpdateRAMaskHandler)
 			padapter->HalFunc.UpdateRAMaskHandler(padapter, MAX_FW_SUPPORT_MACID_NUM-1-EntryNum, 0);
 
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, padapter->mlmepriv.cur_network.network.SupportedRates);
+		HalSetBrateCfg23a(padapter, padapter->mlmepriv.cur_network.network.SupportedRates);
 		BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT);
 		break;
 	default:
@@ -11221,7 +11219,9 @@ void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum)
 	pBtAssocEntry->HwCAMIndex = BT_HWCAM_STAR + EntryNum;
 
 	usConfig = CAM_VALID | (CAM_AES << 2);
-	write_cam23a(padapter, pBtAssocEntry->HwCAMIndex, usConfig, pBtAssocEntry->BTRemoteMACAddr, pBtAssocEntry->PTK + TKIP_ENC_KEY_POS);
+	rtl8723a_cam_write(padapter, pBtAssocEntry->HwCAMIndex, usConfig,
+			   pBtAssocEntry->BTRemoteMACAddr,
+			   pBtAssocEntry->PTK + TKIP_ENC_KEY_POS);
 }
 
 void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum)
@@ -11234,8 +11234,10 @@ void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum)
 
 	if (pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex != 0) {
 		/*  ToDo : add New HALBT_RemoveKey function !! */
-		if (pBtAssocEntry->HwCAMIndex >= BT_HWCAM_STAR && pBtAssocEntry->HwCAMIndex < HALF_CAM_ENTRY)
-			CAM_empty_entry23a(padapter, pBtAssocEntry->HwCAMIndex);
+		if (pBtAssocEntry->HwCAMIndex >= BT_HWCAM_STAR &&
+		    pBtAssocEntry->HwCAMIndex < HALF_CAM_ENTRY)
+			rtl8723a_cam_empty_entry(padapter,
+						 pBtAssocEntry->HwCAMIndex);
 		pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex = 0;
 	}
 }
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
index 0b205e1204fc..307963d9e7d0 100644
--- a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
@@ -255,30 +255,36 @@ static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLeng
 	/* below for ad-hoc mode */
 
 	/*  SSID */
-	pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
-			    cur_network->Ssid.ssid, &pktlen);
+	pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
+			       cur_network->Ssid.ssid_len,
+			       cur_network->Ssid.ssid, &pktlen);
 
 	/*  supported rates... */
 	rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
-	pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ?
+	pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ?
 			       8 : rate_len), cur_network->SupportedRates, &pktlen);
 
 	/*  DS parameter set */
-	pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pktlen);
+	pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
+			       &cur_network->Configuration.DSConfig, &pktlen);
 
 	if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
 		u32 ATIMWindow;
 		/*  IBSS Parameter Set... */
 		/* ATIMWindow = cur->Configuration.ATIMWindow; */
 		ATIMWindow = 0;
-		pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
+				       (unsigned char *)(&ATIMWindow), &pktlen);
 	}
 
 	/* todo: ERP IE */
 
 	/*  EXTERNDED SUPPORTED RATE */
 	if (rate_len > 8)
-		pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
+		pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
+				       (rate_len - 8),
+				       (cur_network->SupportedRates + 8),
+				       &pktlen);
 
 	/* todo:HT for adhoc */
 
@@ -770,76 +776,3 @@ void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
 	}
 }
 #endif
-
-#ifdef CONFIG_8723AU_P2P
-void rtl8723a_set_p2p_ps_offload_cmd(struct rtw_adapter *padapter, u8 p2p_ps_state)
-{
-	struct hal_data_8723a	*pHalData = GET_HAL_DATA(padapter);
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	struct P2P_PS_Offload_t	*p2p_ps_offload = &pHalData->p2p_ps_offload;
-	u8 i;
-
-	switch (p2p_ps_state) {
-	case P2P_PS_DISABLE:
-		DBG_8723A("P2P_PS_DISABLE \n");
-		memset(p2p_ps_offload, 0, 1);
-		break;
-	case P2P_PS_ENABLE:
-		DBG_8723A("P2P_PS_ENABLE \n");
-		/*  update CTWindow value. */
-		if (pwdinfo->ctwindow > 0) {
-			p2p_ps_offload->CTWindow_En = 1;
-			rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);
-		}
-
-		/*  hw only support 2 set of NoA */
-		for (i = 0; i < pwdinfo->noa_num; i++) {
-			/*  To control the register setting for which NOA */
-			rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));
-			if (i == 0)
-				p2p_ps_offload->NoA0_En = 1;
-			else
-				p2p_ps_offload->NoA1_En = 1;
-
-			/*  config P2P NoA Descriptor Register */
-			rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
-
-			rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
-
-			rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
-
-			rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
-		}
-
-		if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
-			/*  rst p2p circuit */
-			rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
-
-			p2p_ps_offload->Offload_En = 1;
-
-			if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-				p2p_ps_offload->role = 1;
-				p2p_ps_offload->AllStaSleep = 0;
-			} else {
-				p2p_ps_offload->role = 0;
-			}
-
-			p2p_ps_offload->discovery = 0;
-		}
-		break;
-	case P2P_PS_SCAN:
-		DBG_8723A("P2P_PS_SCAN \n");
-		p2p_ps_offload->discovery = 1;
-		break;
-	case P2P_PS_SCAN_DONE:
-		DBG_8723A("P2P_PS_SCAN_DONE \n");
-		p2p_ps_offload->discovery = 0;
-		pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
-		break;
-	default:
-		break;
-	}
-
-	FillH2CCmd(padapter, P2P_PS_OFFLOAD_EID, 1, (u8 *)p2p_ps_offload);
-}
-#endif /* CONFIG_8723AU_P2P */
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_dm.c b/drivers/staging/rtl8723au/hal/rtl8723a_dm.c
index f204ab1714e7..4ca7b8ec7b38 100644
--- a/drivers/staging/rtl8723au/hal/rtl8723a_dm.c
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_dm.c
@@ -76,7 +76,7 @@ static void dm_CheckPbcGPIO(struct rtw_adapter *padapter)
 			return;
 		}
 
-		rtw_signal_process(padapter->pid[0], SIGUSR1);
+		kill_pid(find_vpid(padapter->pid[0]), SIGUSR1, 1);
 	}
 }
 
@@ -217,14 +217,7 @@ rtl8723a_HalDmWatchDog(
 		goto skip_dm;
 
 	bFwCurrentInPSMode = Adapter->pwrctrlpriv.bFwCurrentInPSMode;
-	rtw23a_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
-
-#ifdef CONFIG_8723AU_P2P
-	/*  Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
-	/*  modifed by thomas. 2011.06.11. */
-	if (Adapter->wdinfo.p2p_ps_mode)
-		bFwPSAwake = false;
-#endif /* CONFIG_8723AU_P2P */
+	bFwPSAwake = rtl8723a_get_fwlps_rf_on(Adapter);
 
 	if ((hw_init_completed) && ((!bFwCurrentInPSMode) && bFwPSAwake)) {
 		/*  Calculate Tx/Rx statistics. */
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
index 0982b0a4ab9b..0a86923e7def 100644
--- a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
@@ -619,6 +619,7 @@ hal_ReadEFuse_WiFi(struct rtw_adapter *padapter,
 	u8 offset, wden;
 	u8 efuseHeader, efuseExtHdr, efuseData;
 	u16 i, total, used;
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 
 	/*  Do NOT excess total size of EFuse table.
 	    Added by Roger, 2008.11.10. */
@@ -696,7 +697,7 @@ hal_ReadEFuse_WiFi(struct rtw_adapter *padapter,
 	EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
 				 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
 	used = eFuse_Addr - 1;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&used);
+	pHalData->EfuseUsedBytes = used;
 
 	kfree(efuseTbl);
 }
@@ -711,6 +712,7 @@ hal_ReadEFuse_BT(struct rtw_adapter *padapter,
 	u8 efuseHeader, efuseExtHdr, efuseData;
 	u8 offset, wden;
 	u16 i, total, used;
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 
 	/*  Do NOT excess total size of EFuse table.
 	    Added by Roger, 2008.11.10. */
@@ -812,7 +814,7 @@ hal_ReadEFuse_BT(struct rtw_adapter *padapter,
 	EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
 				 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
 	used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &used);
+	pHalData->BTEfuseUsedBytes = used;
 
 exit:
 	kfree(efuseTbl);
@@ -834,8 +836,9 @@ hal_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
 	u16 efuse_addr = 0;
 	u8 hoffset = 0, hworden = 0;
 	u8 efuse_data, word_cnts = 0;
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 
-	rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
+	efuse_addr = pHalData->EfuseUsedBytes;
 
 	DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr);
 
@@ -872,7 +875,7 @@ hal_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
 		efuse_addr += (word_cnts * 2) + 1;
 	}
 
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
+	pHalData->EfuseUsedBytes = efuse_addr;
 
 	DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr);
 
@@ -888,8 +891,9 @@ hal_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
 	u8 hoffset = 0, hworden = 0;
 	u8 efuse_data, word_cnts = 0;
 	u16 retU2 = 0;
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 
-	rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &btusedbytes);
+	btusedbytes = pHalData->BTEfuseUsedBytes;
 
 	efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN));
 	startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN));
@@ -954,7 +958,7 @@ hal_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
 	}
 
 	retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&retU2);
+	pHalData->BTEfuseUsedBytes = retU2;
 
 	DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2);
 	return retU2;
@@ -1144,6 +1148,7 @@ static u8
 hal_EfusePartialWriteCheck(struct rtw_adapter *padapter, u8 efuseType,
 			   u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
 {
+	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 	u8 bRet = false;
 	u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
 	u8 efuse_data = 0;
@@ -1154,13 +1159,11 @@ hal_EfusePartialWriteCheck(struct rtw_adapter *padapter, u8 efuseType,
 	EFUSE_GetEfuseDefinition23a(padapter, efuseType,
 				 TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max);
 
-	if (efuseType == EFUSE_WIFI) {
-		rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES,
-				  (u8 *) &startAddr);
-	} else {
-		rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES,
-				  (u8 *) &startAddr);
-	}
+	if (efuseType == EFUSE_WIFI)
+		startAddr = pHalData->EfuseUsedBytes;
+	else
+		startAddr = pHalData->BTEfuseUsedBytes;
+
 	startAddr %= efuse_max;
 
 	while (1) {
@@ -2935,7 +2938,7 @@ void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc,
 	rtl8723a_cal_txdesc_chksum(ptxdesc);
 }
 
-static void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
+void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
 {
 	u8 val8;
 
@@ -2996,7 +2999,7 @@ static void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
 	rtw_write8(padapter, MSR, val8);
 }
 
-static void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
+void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
 {
 	u8 idx = 0;
 	u32 reg_macid;
@@ -3007,7 +3010,7 @@ static void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
 		rtw_write8(padapter, (reg_macid + idx), val[idx]);
 }
 
-static void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
+void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
 {
 	u8 idx = 0;
 	u32 reg_bssid;
@@ -3018,7 +3021,7 @@ static void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
 		rtw_write8(padapter, (reg_bssid + idx), val[idx]);
 }
 
-static void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
+void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
 {
 	u64 tsf;
 	u32 reg_tsftr;
@@ -3028,8 +3031,8 @@ static void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
 	/* tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue %
 	   (pmlmeinfo->bcn_interval*1024)) - 1024; us */
 	tsf = pmlmeext->TSFValue -
-		rtw_modular6423a(pmlmeext->TSFValue,
-			      (pmlmeinfo->bcn_interval * 1024)) - 1024;	/* us */
+		do_div(pmlmeext->TSFValue,
+		       (pmlmeinfo->bcn_interval * 1024)) - 1024;	/* us */
 
 	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
 	    ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
@@ -3055,7 +3058,7 @@ static void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
 		ResumeTxBeacon(padapter);
 }
 
-static void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
+void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
 {
 	/*  reject all data frames */
 	rtw_write16(padapter, REG_RXFLTMAP2, 0);
@@ -3067,7 +3070,7 @@ static void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
 	SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
 }
 
-static void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
+void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
 {
 	u8 RetryLimit = 0x30;
 
@@ -3129,264 +3132,6 @@ static void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
 #endif
 }
 
-void SetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
-{
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
-	u32 *val32 = (u32 *)val;
-
-	switch (variable) {
-	case HW_VAR_MEDIA_STATUS:
-		rtl8723a_set_media_status(padapter, *val);
-		break;
-
-	case HW_VAR_MEDIA_STATUS1:
-		rtl8723a_set_media_status1(padapter, *val);
-		break;
-
-	case HW_VAR_SET_OPMODE:
-		hw_var_set_opmode(padapter, *val);
-		break;
-
-	case HW_VAR_MAC_ADDR:
-		hw_var_set_macaddr(padapter, val);
-		break;
-
-	case HW_VAR_BSSID:
-		hw_var_set_bssid(padapter, val);
-		break;
-
-	case HW_VAR_BASIC_RATE:
-		HalSetBrateCfg23a(padapter, val);
-		break;
-
-	case HW_VAR_TXPAUSE:
-		rtl8723a_set_tx_pause(padapter, *val);
-		break;
-
-	case HW_VAR_BCN_FUNC:
-		rtl8723a_set_bcn_func(padapter, *val);
-		break;
-
-	case HW_VAR_CORRECT_TSF:
-		hw_var_set_correct_tsf(padapter);
-		break;
-
-	case HW_VAR_CHECK_BSSID:
-		rtl8723a_check_bssid(padapter, *val);
-		break;
-
-	case HW_VAR_MLME_DISCONNECT:
-		hw_var_set_mlme_disconnect(padapter);
-		break;
-
-	case HW_VAR_MLME_SITESURVEY:
-		rtl8723a_mlme_sitesurvey(padapter, *val);
-		break;
-
-	case HW_VAR_MLME_JOIN:
-		hw_var_set_mlme_join(padapter, *val);
-		break;
-
-	case HW_VAR_ON_RCR_AM:
-		rtl8723a_on_rcr_am(padapter);
-		break;
-
-	case HW_VAR_OFF_RCR_AM:
-		rtl8723a_off_rcr_am(padapter);
-		break;
-
-	case HW_VAR_BEACON_INTERVAL:
-		rtl8723a_set_beacon_interval(padapter, *((u16 *) val));
-		break;
-
-	case HW_VAR_SLOT_TIME:
-		rtl8723a_set_slot_time(padapter, *val);
-		break;
-
-	case HW_VAR_RESP_SIFS:
-		rtl8723a_set_resp_sifs(padapter, val[0], val[1],
-				       val[2], val[3]);
-		break;
-
-	case HW_VAR_ACK_PREAMBLE:
-		rtl8723a_ack_preamble(padapter, *val);
-		break;
-
-	case HW_VAR_SEC_CFG:
-		rtl8723a_set_sec_cfg(padapter, *val);
-		break;
-
-	case HW_VAR_DM_FLAG:
-		rtl8723a_odm_support_ability_write(padapter, *val32);
-		break;
-	case HW_VAR_DM_FUNC_OP:
-		rtl8723a_odm_support_ability_backup(padapter, *val);
-		break;
-	case HW_VAR_DM_FUNC_SET:
-		rtl8723a_odm_support_ability_set(padapter, *val32);
-		break;
-
-	case HW_VAR_DM_FUNC_CLR:
-		rtl8723a_odm_support_ability_clr(padapter, *val32);
-		break;
-
-	case HW_VAR_CAM_EMPTY_ENTRY:
-		rtl8723a_cam_empty_entry(padapter, *val);
-		break;
-
-	case HW_VAR_CAM_INVALID_ALL:
-		rtl8723a_cam_invalid_all(padapter);
-		break;
-
-	case HW_VAR_CAM_WRITE:
-		rtl8723a_cam_write(padapter, val32[0], val32[1]);
-		break;
-
-	case HW_VAR_AC_PARAM_VO:
-		rtl8723a_set_ac_param_vo(padapter, *val32);
-		break;
-
-	case HW_VAR_AC_PARAM_VI:
-		rtl8723a_set_ac_param_vi(padapter, *val32);
-		break;
-
-	case HW_VAR_AC_PARAM_BE:
-		rtl8723a_set_ac_param_be(padapter, *val32);
-		break;
-
-	case HW_VAR_AC_PARAM_BK:
-		rtl8723a_set_ac_param_bk(padapter, *val32);
-		break;
-
-	case HW_VAR_ACM_CTRL:
-		rtl8723a_set_acm_ctrl(padapter, *val);
-		break;
-
-	case HW_VAR_AMPDU_MIN_SPACE:
-		rtl8723a_set_ampdu_min_space(padapter, *val);
-		break;
-
-	case HW_VAR_AMPDU_FACTOR:
-		rtl8723a_set_ampdu_factor(padapter, *val);
-		break;
-
-	case HW_VAR_RXDMA_AGG_PG_TH:
-		rtl8723a_set_rxdma_agg_pg_th(padapter, *val);
-		break;
-
-	case HW_VAR_H2C_FW_PWRMODE:
-		rtl8723a_set_FwPwrMode_cmd(padapter, *val);
-		break;
-
-	case HW_VAR_H2C_FW_JOINBSSRPT:
-		rtl8723a_set_FwJoinBssReport_cmd(padapter, *val);
-		break;
-
-#ifdef CONFIG_8723AU_P2P
-	case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
-		rtl8723a_set_p2p_ps_offload_cmd(padapter, *val);
-		break;
-#endif /* CONFIG_8723AU_P2P */
-
-	case HW_VAR_INITIAL_GAIN:
-		rtl8723a_set_initial_gain(padapter, *val32);
-		break;
-	case HW_VAR_EFUSE_BYTES:
-		pHalData->EfuseUsedBytes = *((u16 *) val);
-		break;
-	case HW_VAR_EFUSE_BT_BYTES:
-		pHalData->BTEfuseUsedBytes = *((u16 *) val);
-		break;
-	case HW_VAR_FIFO_CLEARN_UP:
-		rtl8723a_fifo_cleanup(padapter);
-		break;
-	case HW_VAR_CHECK_TXBUF:
-		break;
-	case HW_VAR_APFM_ON_MAC:
-		rtl8723a_set_apfm_on_mac(padapter, *val);
-		break;
-
-	case HW_VAR_NAV_UPPER:
-		rtl8723a_set_nav_upper(padapter, *val32);
-		break;
-	case HW_VAR_BCN_VALID:
-		rtl8723a_bcn_valid(padapter);
-		break;
-	default:
-		break;
-	}
-
-}
-
-void GetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
-{
-	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
-
-	switch (variable) {
-	case HW_VAR_BASIC_RATE:
-		*((u16 *) val) = pHalData->BasicRateSet;
-		break;
-
-	case HW_VAR_TXPAUSE:
-		*val = rtw_read8(padapter, REG_TXPAUSE);
-		break;
-
-	case HW_VAR_BCN_VALID:
-		/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
-		val[0] = (BIT0 & rtw_read8(padapter, REG_TDECTRL + 2)) ? true :
-			false;
-		break;
-
-	case HW_VAR_RF_TYPE:
-		*val = pHalData->rf_type;
-		break;
-
-	case HW_VAR_DM_FLAG:
-	{
-		struct dm_odm_t *podmpriv = &pHalData->odmpriv;
-		*((u32 *) val) = podmpriv->SupportAbility;
-	}
-		break;
-
-	case HW_VAR_FWLPS_RF_ON:
-	{
-		/*  When we halt NIC, we should check if FW LPS is leave. */
-		u32 valRCR;
-
-		if ((padapter->bSurpriseRemoved == true) ||
-		    (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
-			/*  If it is in HW/SW Radio OFF or IPS state, we do
-			    not check Fw LPS Leave, because Fw is unload. */
-			*val = true;
-		} else {
-			valRCR = rtw_read32(padapter, REG_RCR);
-			valRCR &= 0x00070000;
-			if (valRCR)
-				*val = false;
-			else
-				*val = true;
-		}
-	}
-		break;
-	case HW_VAR_EFUSE_BYTES:
-		*((u16 *) val) = pHalData->EfuseUsedBytes;
-		break;
-
-	case HW_VAR_EFUSE_BT_BYTES:
-		*((u16 *) val) = pHalData->BTEfuseUsedBytes;
-		break;
-
-	case HW_VAR_APFM_ON_MAC:
-		*val = pHalData->bMacPwrCtrlOn;
-		break;
-	case HW_VAR_CHK_HI_QUEUE_EMPTY:
-		*val =
-		    ((rtw_read32(padapter, REG_HGQ_INFORMATION) & 0x0000ff00) ==
-		     0) ? true : false;
-		break;
-	}
-}
-
 #ifdef CONFIG_8723AU_BT_COEXIST
 
 void rtl8723a_SingleDualAntennaDetection(struct rtw_adapter *padapter)
diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_recv.c b/drivers/staging/rtl8723au/hal/rtl8723au_recv.c
index 213d1936109d..e1f17af78a12 100644
--- a/drivers/staging/rtl8723au/hal/rtl8723au_recv.c
+++ b/drivers/staging/rtl8723au/hal/rtl8723au_recv.c
@@ -19,7 +19,6 @@
 #include <mlme_osdep.h>
 #include <linux/ip.h>
 #include <linux/if_ether.h>
-#include <ethernet.h>
 #include <usb_ops.h>
 #include <wifi.h>
 #include <rtl8723a_hal.h>
@@ -66,8 +65,8 @@ int rtl8723au_init_recv_priv(struct rtw_adapter *padapter)
 	for (i = 0; i < NR_RECVBUFF; i++) {
 		INIT_LIST_HEAD(&precvbuf->list);
 
-		res = rtw_os_recvbuf_resource_alloc23a(padapter, precvbuf);
-		if (res == _FAIL)
+		precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!precvbuf->purb)
 			break;
 
 		precvbuf->adapter = padapter;
@@ -110,7 +109,11 @@ void rtl8723au_free_recv_priv(struct rtw_adapter *padapter)
 	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
 
 	for (i = 0; i < NR_RECVBUFF; i++) {
-		rtw_os_recvbuf_resource_free23a(padapter, precvbuf);
+		usb_free_urb(precvbuf->purb);
+
+		if (precvbuf->pskb)
+			dev_kfree_skb_any(precvbuf->pskb);
+
 		precvbuf++;
 	}
 
diff --git a/drivers/staging/rtl8723au/hal/usb_halinit.c b/drivers/staging/rtl8723au/hal/usb_halinit.c
index e206829d50fa..0a6e343373ff 100644
--- a/drivers/staging/rtl8723au/hal/usb_halinit.c
+++ b/drivers/staging/rtl8723au/hal/usb_halinit.c
@@ -621,7 +621,6 @@ static u32 rtl8723au_hal_init(struct rtw_adapter *Adapter)
 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
 	struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
 	struct registry_priv *pregistrypriv = &Adapter->registrypriv;
-	u32 NavUpper = WiFiNavUpperUs;
 
 	unsigned long init_start_time = jiffies;
 
@@ -779,7 +778,7 @@ static u32 rtl8723au_hal_init(struct rtw_adapter *Adapter)
 	_InitDriverInfoSize(Adapter, DRVINFO_SZ);
 
 	_InitInterrupt(Adapter);
-	hal_init_macaddr23a(Adapter);/* set mac_address */
+	hw_var_set_macaddr(Adapter, Adapter->eeprompriv.mac_addr);
 	_InitNetworkType(Adapter);/* set msr */
 	_InitWMACSetting(Adapter);
 	_InitAdaptiveCtrl(Adapter);
@@ -888,7 +887,7 @@ static u32 rtl8723au_hal_init(struct rtw_adapter *Adapter)
 	rtl8723a_InitHalDm(Adapter);
 
 	HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC31);
-	rtw_hal_set_hwreg23a(Adapter, HW_VAR_NAV_UPPER, (u8 *)&NavUpper);
+	rtl8723a_set_nav_upper(Adapter, WiFiNavUpperUs);
 
 	/*  2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, but we need to fin root cause. */
 	if (((rtw_read32(Adapter, rFPGA0_RFMOD) & 0xFF000000) != 0x83000000)) {
@@ -1497,52 +1496,6 @@ static void ReadAdapterInfo8723AU(struct rtw_adapter *Adapter)
 	_ReadAdapterInfo8723AU(Adapter);
 }
 
-#define GPIO_DEBUG_PORT_NUM 0
-static void rtl8723au_trigger_gpio_0(struct rtw_adapter *padapter)
-{
-	u32 gpioctrl;
-	DBG_8723A("==> trigger_gpio_0...\n");
-	rtw_write16_async(padapter, REG_GPIO_PIN_CTRL, 0);
-	rtw_write8_async(padapter, REG_GPIO_PIN_CTRL+2, 0xFF);
-	gpioctrl = (BIT(GPIO_DEBUG_PORT_NUM) << 24)|
-		(BIT(GPIO_DEBUG_PORT_NUM) << 16);
-	rtw_write32_async(padapter, REG_GPIO_PIN_CTRL, gpioctrl);
-	gpioctrl |= (BIT(GPIO_DEBUG_PORT_NUM)<<8);
-	rtw_write32_async(padapter, REG_GPIO_PIN_CTRL, gpioctrl);
-	DBG_8723A("<=== trigger_gpio_0...\n");
-}
-
-/*
- * If variable not handled here,
- * some variables will be processed in SetHwReg8723A()
- */
-static void SetHwReg8723AU(struct rtw_adapter *Adapter, u8 variable, u8 *val)
-{
-	switch (variable) {
-	case HW_VAR_RXDMA_AGG_PG_TH:
-		break;
-	case HW_VAR_SET_RPWM:
-		rtl8723a_set_rpwm(Adapter, *val);
-		break;
-	case HW_VAR_TRIGGER_GPIO_0:
-		rtl8723au_trigger_gpio_0(Adapter);
-		break;
-	default:
-		SetHwReg8723A(Adapter, variable, val);
-		break;
-	}
-
-}
-
-/*
- * If variable not handled here,
- * some variables will be processed in GetHwReg8723A()
- */
-static void GetHwReg8723AU(struct rtw_adapter *Adapter, u8 variable, u8 *val)
-{
-	GetHwReg8723A(Adapter, variable, val);
-}
-
 /*  */
 /*	Description: */
 /*		Query setting of specified variable. */
@@ -1820,8 +1773,6 @@ int rtl8723au_set_hal_ops(struct rtw_adapter *padapter)
 	pHalFunc->init_default_value = &rtl8723au_init_default_value;
 	pHalFunc->intf_chip_configure = &rtl8723au_interface_configure;
 	pHalFunc->read_adapter_info = &ReadAdapterInfo8723AU;
-	pHalFunc->SetHwRegHandler = &SetHwReg8723AU;
-	pHalFunc->GetHwRegHandler = &GetHwReg8723AU;
 	pHalFunc->GetHalDefVarHandler = &GetHalDefVar8192CUsb;
 	pHalFunc->SetHalDefVarHandler = &SetHalDefVar8192CUsb;
 	pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8192CUsb;
diff --git a/drivers/staging/rtl8723au/include/drv_types.h b/drivers/staging/rtl8723au/include/drv_types.h
index 53eecea48cec..de25e1a5eee8 100644
--- a/drivers/staging/rtl8723au/include/drv_types.h
+++ b/drivers/staging/rtl8723au/include/drv_types.h
@@ -55,7 +55,6 @@ enum _NIC_VERSION {
 #include <rtw_event.h>
 #include <rtw_led.h>
 #include <rtw_mlme_ext.h>
-#include <rtw_p2p.h>
 #include <rtw_ap.h>
 
 #include "ioctl_cfg80211.h"
@@ -258,13 +257,7 @@ struct rtw_adapter {
 	struct	hostapd_priv	*phostapdpriv;
 #endif
 
-	struct cfg80211_wifidirect_info	cfg80211_wdinfo;
 	u32	setband;
-	struct wifidirect_info	wdinfo;
-
-#ifdef CONFIG_8723AU_P2P
-	struct wifi_display_info wfd_info;
-#endif /* CONFIG_8723AU_P2P */
 
 	void *HalData;
 	u32 hal_data_sz;
@@ -316,10 +309,6 @@ struct rtw_adapter {
 	u8 bRxRSSIDisplay;
 	/* The driver will show the desired chan nor when this flag is 1. */
 	u8 bNotifyChannelChange;
-#ifdef CONFIG_8723AU_P2P
-	/* driver will show current P2P status when the  application reads it*/
-	u8 bShowGetP2PState;
-#endif
 	struct rtw_adapter *pbuddy_adapter;
 
 	/* extend to support multi interface */
@@ -327,21 +316,6 @@ struct rtw_adapter {
 	/* IFACE_ID1 is equals to SECONDARY_ADAPTER */
 	u8 iface_id;
 
-#ifdef CONFIG_BR_EXT
-	_lock					br_ext_lock;
-	/* unsigned int			macclone_completed; */
-	struct nat25_network_db_entry	*nethash[NAT25_HASH_SIZE];
-	int				pppoe_connection_in_progress;
-	unsigned char			pppoe_addr[MACADDRLEN];
-	unsigned char			scdb_mac[MACADDRLEN];
-	unsigned char			scdb_ip[4];
-	struct nat25_network_db_entry	*scdb_entry;
-	unsigned char			br_mac[MACADDRLEN];
-	unsigned char			br_ip[4];
-
-	struct br_ext_info		ethBrExtInfo;
-#endif	/*  CONFIG_BR_EXT */
-
 	u8    fix_rate;
 
 	unsigned char     in_cta_test;
diff --git a/drivers/staging/rtl8723au/include/ethernet.h b/drivers/staging/rtl8723au/include/ethernet.h
deleted file mode 100644
index 39fc6df88188..000000000000
--- a/drivers/staging/rtl8723au/include/ethernet.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- *
- ******************************************************************************/
-/*! \file */
-#ifndef __INC_ETHERNET_H
-#define __INC_ETHERNET_H
-
-#define LLC_HEADER_SIZE			6	/*  LLC Header Length */
-
-#endif /*  #ifndef __INC_ETHERNET_H */
diff --git a/drivers/staging/rtl8723au/include/hal_com.h b/drivers/staging/rtl8723au/include/hal_com.h
index 20f983cfc2b7..5f050a346a8a 100644
--- a/drivers/staging/rtl8723au/include/hal_com.h
+++ b/drivers/staging/rtl8723au/include/hal_com.h
@@ -165,8 +165,6 @@ void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS);
 bool
 Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe);
 
-void hal_init_macaddr23a(struct rtw_adapter *adapter);
-
 void c2h_evt_clear23a(struct rtw_adapter *adapter);
 s32 c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf);
 
@@ -185,11 +183,12 @@ void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble);
 void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec);
 void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex);
 void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter);
-void rtl8723a_cam_write(struct rtw_adapter *padapter, u32 val1, u32 val2);
+void rtl8723a_cam_write(struct rtw_adapter *padapter,
+			u8 entry, u16 ctrl, u8 *mac, u8 *key);
 void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter);
 void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val);
 void rtl8723a_bcn_valid(struct rtw_adapter *padapter);
-void rtl8723a_set_tx_pause(struct rtw_adapter *padapter, u8 pause);
+bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter);
 void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval);
 void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
 			    u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2);
@@ -202,10 +201,14 @@ void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper);
 void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain);
 
 void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val);
-void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter, u8 val);
+void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter);
+void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter);
 void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val);
 void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val);
 
 void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val);
+u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter);
+bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter);
+bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter);
 
 #endif /* __HAL_COMMON_H__ */
diff --git a/drivers/staging/rtl8723au/include/hal_intf.h b/drivers/staging/rtl8723au/include/hal_intf.h
index d183f4ba1ecb..89516467f241 100644
--- a/drivers/staging/rtl8723au/include/hal_intf.h
+++ b/drivers/staging/rtl8723au/include/hal_intf.h
@@ -35,78 +35,6 @@ enum _CHIP_TYPE {
 	MAX_CHIP_TYPE
 };
 
-enum HW_VARIABLES {
-	HW_VAR_MEDIA_STATUS,
-	HW_VAR_MEDIA_STATUS1,
-	HW_VAR_SET_OPMODE,
-	HW_VAR_MAC_ADDR,
-	HW_VAR_BSSID,
-	HW_VAR_INIT_RTS_RATE,
-	HW_VAR_BASIC_RATE,
-	HW_VAR_TXPAUSE,
-	HW_VAR_BCN_FUNC,
-	HW_VAR_CORRECT_TSF,
-	HW_VAR_CHECK_BSSID,
-	HW_VAR_MLME_DISCONNECT,
-	HW_VAR_MLME_SITESURVEY,
-	HW_VAR_MLME_JOIN,
-	HW_VAR_ON_RCR_AM,
-	HW_VAR_OFF_RCR_AM,
-	HW_VAR_BEACON_INTERVAL,
-	HW_VAR_SLOT_TIME,
-	HW_VAR_RESP_SIFS,
-	HW_VAR_ACK_PREAMBLE,
-	HW_VAR_SEC_CFG,
-	HW_VAR_BCN_VALID,
-	HW_VAR_RF_TYPE,
-	HW_VAR_DM_FLAG,
-	HW_VAR_DM_FUNC_OP,
-	HW_VAR_DM_FUNC_SET,
-	HW_VAR_DM_FUNC_CLR,
-	HW_VAR_CAM_EMPTY_ENTRY,
-	HW_VAR_CAM_INVALID_ALL,
-	HW_VAR_CAM_WRITE,
-	HW_VAR_CAM_READ,
-	HW_VAR_AC_PARAM_VO,
-	HW_VAR_AC_PARAM_VI,
-	HW_VAR_AC_PARAM_BE,
-	HW_VAR_AC_PARAM_BK,
-	HW_VAR_ACM_CTRL,
-	HW_VAR_AMPDU_MIN_SPACE,
-	HW_VAR_AMPDU_FACTOR,
-	HW_VAR_RXDMA_AGG_PG_TH,
-	HW_VAR_SET_RPWM,
-	HW_VAR_H2C_FW_PWRMODE,
-	HW_VAR_H2C_FW_JOINBSSRPT,
-	HW_VAR_FWLPS_RF_ON,
-	HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
-	HW_VAR_TDLS_WRCR,
-	HW_VAR_TDLS_INIT_CH_SEN,
-	HW_VAR_TDLS_RS_RCR,
-	HW_VAR_TDLS_DONE_CH_SEN,
-	HW_VAR_INITIAL_GAIN,
-	HW_VAR_TRIGGER_GPIO_0,
-	HW_VAR_BT_SET_COEXIST,
-	HW_VAR_BT_ISSUE_DELBA,
-	HW_VAR_CURRENT_ANTENNA,
-	HW_VAR_ANTENNA_DIVERSITY_LINK,
-	HW_VAR_ANTENNA_DIVERSITY_SELECT,
-	HW_VAR_SWITCH_EPHY_WoWLAN,
-	HW_VAR_EFUSE_BYTES,
-	HW_VAR_EFUSE_BT_BYTES,
-	HW_VAR_FIFO_CLEARN_UP,
-	HW_VAR_CHECK_TXBUF,
-	HW_VAR_APFM_ON_MAC, /* Auto FSM to Turn On, include clock, isolation, power control for MAC only */
-	/*  The valid upper nav range for the HW updating, if the true value is larger than the upper range, the HW won't update it. */
-	/*  Unit in microsecond. 0 means disable this function. */
-	HW_VAR_NAV_UPPER,
-	HW_VAR_RPT_TIMER_SETTING,
-	HW_VAR_TX_RPT_MAX_MACID,
-	HW_VAR_H2C_MEDIA_STATUS_RPT,
-	HW_VAR_CHK_HI_QUEUE_EMPTY,
-	HW_VAR_READ_LLT_TAB,
-};
-
 enum hal_def_variable {
 	HAL_DEF_UNDERCORATEDSMOOTHEDPWDB,
 	HAL_DEF_IS_SUPPORT_ANT_DIV,
@@ -175,11 +103,6 @@ struct hal_ops {
 
 	void (*hal_dm_watchdog)(struct rtw_adapter *padapter);
 
-	void (*SetHwRegHandler)(struct rtw_adapter *padapter,
-				u8 variable, u8 *val);
-	void (*GetHwRegHandler)(struct rtw_adapter *padapter,
-				u8 variable, u8 *val);
-
 	u8 (*GetHalDefVarHandler)(struct rtw_adapter *padapter,
 				  enum hal_def_variable eVariable,
 				  void *pValue);
@@ -291,11 +214,6 @@ enum hardware_type {
 };
 
 #define GET_EEPROM_EFUSE_PRIV(adapter) (&adapter->eeprompriv)
-#define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse)
-
-extern int rtw_ht_enable23A;
-extern int rtw_cbw40_enable23A;
-extern int rtw_ampdu_enable23A;/* for enable tx_ampdu */
 
 void rtw_hal_def_value_init23a(struct rtw_adapter *padapter);
 int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal);
@@ -312,8 +230,6 @@ u32 rtw_hal_power_on23a(struct rtw_adapter *padapter);
 uint rtw_hal_init23a(struct rtw_adapter *padapter);
 uint rtw_hal_deinit23a(struct rtw_adapter *padapter);
 void rtw_hal_stop(struct rtw_adapter *padapter);
-void rtw_hal_set_hwreg23a(struct rtw_adapter *padapter, u8 variable, u8 *val);
-void rtw23a_hal_get_hwreg(struct rtw_adapter *padapter, u8 variable, u8 *val);
 
 void rtw_hal_chip_configure23a(struct rtw_adapter *padapter);
 void rtw_hal_read_chip_info23a(struct rtw_adapter *padapter);
@@ -388,5 +304,11 @@ void rtw_hal_reset_security_engine23a(struct rtw_adapter *adapter);
 
 s32 rtw_hal_c2h_handler23a(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt);
 c2h_id_filter rtw_hal_c2h_id_filter_ccx23a(struct rtw_adapter *adapter);
+void hw_var_set_correct_tsf(struct rtw_adapter *padapter);
+void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter);
+void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode);
+void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val);
+void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val);
+void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type);
 
 #endif /* __HAL_INTF_H__ */
diff --git a/drivers/staging/rtl8723au/include/ieee80211.h b/drivers/staging/rtl8723au/include/ieee80211.h
index 28e4ab239fb9..76875f651d82 100644
--- a/drivers/staging/rtl8723au/include/ieee80211.h
+++ b/drivers/staging/rtl8723au/include/ieee80211.h
@@ -298,53 +298,6 @@ struct ieee80211_snap_hdr {
 #define WEP_KEY_LEN 13
 
 
-
-/*
-
- 802.11 data frame from AP
-
-      ,-------------------------------------------------------------------.
-Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
-      |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
-      |      | tion | (BSSID) |         |         | ence |  data   |      |
-      `-------------------------------------------------------------------'
-
-Total: 28-2340 bytes
-
-*/
-
-struct ieee80211_header_data {
-	u16 frame_ctl;
-	u16 duration_id;
-	u8 addr1[6];
-	u8 addr2[6];
-	u8 addr3[6];
-	u16 seq_ctrl;
-};
-
-struct ieee80211_info_element_hdr {
-	u8 id;
-	u8 len;
-} __attribute__ ((packed));
-
-struct ieee80211_info_element {
-	u8 id;
-	u8 len;
-	u8 data[0];
-} __attribute__ ((packed));
-
-
-struct ieee80211_txb {
-	u8 nr_frags;
-	u8 encrypted;
-	u16 reserved;
-	u16 frag_size;
-	u16 payload_size;
-	struct sk_buff *fragments[0];
-};
-
-
 /* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
  * only use 8, and then use extended rates for the remaining supported
  * rates.  Other APs, however, stick all of their supported rates on the
@@ -382,9 +335,6 @@ join_res:
 #define IEEE_G            (1<<2)
 #define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
 
-/* Baron move to ieee80211.c */
-int ieee80211_is_empty_essid23a(const char *essid, int essid_len);
-
 enum _PUBLIC_ACTION{
 	ACT_PUBLIC_BSSCOEXIST = 0, /*  20/40 BSS Coexistence */
 	ACT_PUBLIC_DSE_ENABLE = 1,
@@ -457,68 +407,8 @@ struct rtw_ieee80211_channel {
 	/*, (channel)->orig_mag*/ \
 	/*, (channel)->orig_mpwr*/ \
 
-/* Parsed Information Elements */
-struct rtw_ieee802_11_elems {
-	u8 *ssid;
-	u8 ssid_len;
-	u8 *supp_rates;
-	u8 supp_rates_len;
-	u8 *fh_params;
-	u8 fh_params_len;
-	u8 *ds_params;
-	u8 ds_params_len;
-	u8 *cf_params;
-	u8 cf_params_len;
-	u8 *tim;
-	u8 tim_len;
-	u8 *ibss_params;
-	u8 ibss_params_len;
-	u8 *challenge;
-	u8 challenge_len;
-	u8 *erp_info;
-	u8 erp_info_len;
-	u8 *ext_supp_rates;
-	u8 ext_supp_rates_len;
-	u8 *wpa_ie;
-	u8 wpa_ie_len;
-	u8 *rsn_ie;
-	u8 rsn_ie_len;
-	u8 *wme;
-	u8 wme_len;
-	u8 *wme_tspec;
-	u8 wme_tspec_len;
-	u8 *wps_ie;
-	u8 wps_ie_len;
-	u8 *power_cap;
-	u8 power_cap_len;
-	u8 *supp_channels;
-	u8 supp_channels_len;
-	u8 *mdie;
-	u8 mdie_len;
-	u8 *ftie;
-	u8 ftie_len;
-	u8 *timeout_int;
-	u8 timeout_int_len;
-	u8 *ht_capabilities;
-	u8 ht_capabilities_len;
-	u8 *ht_operation;
-	u8 ht_operation_len;
-	u8 *vendor_ht_cap;
-	u8 vendor_ht_cap_len;
-};
-
-enum parse_res {
-	ParseOK = 0,
-	ParseUnknown = 1,
-	ParseFailed = -1
-};
-
-enum parse_res rtw_ieee802_11_parse_elems23a(u8 *start, uint len,
-				struct rtw_ieee802_11_elems *elems,
-				int show_errors);
-
 u8 *rtw_set_fixed_ie23a(unsigned char *pbuf, unsigned int len, unsigned char *source, unsigned int *frlen);
-u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, u8 *source, uint *frlen);
+u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen);
 
 enum secondary_ch_offset {
 	SCN = 0, /* no secondary channel */
@@ -537,12 +427,10 @@ int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u
 
 void rtw_set_supported_rate23a(u8* SupportedRates, uint mode) ;
 
-unsigned char *rtw_get_wpa_ie23a(unsigned char *pie, int *wpa_ie_len, int limit);
-unsigned char *rtw_get_wpa2_ie23a(unsigned char *pie, int *rsn_ie_len, int limit);
-int rtw_get_wpa_cipher_suite23a(u8 *s);
-int rtw_get_wpa2_cipher_suite23a(u8 *s);
-int rtw_parse_wpa_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
-int rtw_parse_wpa2_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
+int rtw_get_wpa_cipher_suite23a(const u8 *s);
+int rtw_get_wpa2_cipher_suite23a(const u8 *s);
+int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
+int rtw_parse_wpa2_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
 
 int rtw_get_sec_ie23a(u8 *in_ie,uint in_len,u8 *rsn_ie,u16 *rsn_len,u8 *wpa_ie,u16 *wpa_len);
 
@@ -551,32 +439,6 @@ u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
 u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr);
 u8 *rtw_get_wps_attr_content23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content, uint *len_content);
 
-/**
- * for_each_ie - iterate over continuous IEs
- * @ie:
- * @buf:
- * @buf_len:
- */
-#define for_each_ie(ie, buf, buf_len) \
-	for (ie = (void*)buf; (((u8*)ie) - ((u8*)buf) + 1) < buf_len; ie = (void*)(((u8*)ie) + *(((u8*)ie)+1) + 2))
-
-void dump_ies23a(u8 *buf, u32 buf_len);
-void dump_wps_ie23a(u8 *ie, u32 ie_len);
-
-#ifdef CONFIG_8723AU_P2P
-void dump_p2p_ie23a(u8 *ie, u32 ie_len);
-u8 *rtw_get_p2p_ie23a(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen);
-u8 *rtw_get_p2p_attr23a(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_attr, u32 *len_attr);
-u8 *rtw_get_p2p_attr23a_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_content, uint *len_content);
-u32 rtw_set_p2p_attr_content23a(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr);
-void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_id);
-#endif
-
-#ifdef CONFIG_8723AU_P2P
-int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen);
-int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id ,u8 *attr_content, uint *attr_contentlen);
-#endif /*  CONFIG_8723AU_P2P */
-
 uint	rtw_get_rateset_len23a(u8	*rateset);
 
 struct registry_priv;
diff --git a/drivers/staging/rtl8723au/include/mlme_osdep.h b/drivers/staging/rtl8723au/include/mlme_osdep.h
index b7132a9a1378..4bb5525b7a68 100644
--- a/drivers/staging/rtl8723au/include/mlme_osdep.h
+++ b/drivers/staging/rtl8723au/include/mlme_osdep.h
@@ -19,10 +19,6 @@
 #include <drv_types.h>
 
 void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter);
-void rtw_os_indicate_connect23a(struct rtw_adapter *adapter);
-void rtw_os_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted);
-void rtw_report_sec_ie23a(struct rtw_adapter *adapter, u8 authmode, u8 *sec_ie);
-
 void rtw_reset_securitypriv23a(struct rtw_adapter *adapter);
 
 #endif	/* _MLME_OSDEP_H_ */
diff --git a/drivers/staging/rtl8723au/include/osdep_service.h b/drivers/staging/rtl8723au/include/osdep_service.h
index 039bc7285ed0..40445bbafe77 100644
--- a/drivers/staging/rtl8723au/include/osdep_service.h
+++ b/drivers/staging/rtl8723au/include/osdep_service.h
@@ -30,7 +30,6 @@
 #include <linux/kref.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
-#include <linux/circ_buf.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
@@ -40,7 +39,6 @@
 #include <linux/sched.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
-#include <net/iw_handler.h>
 #include <linux/if_arp.h>
 #include <linux/rtnetlink.h>
 #include <linux/delay.h>
@@ -139,7 +137,6 @@ void	_rtw_vmfree(u8 *pbuf, u32 sz);
 
 extern unsigned char REALTEK_96B_IE23A[];
 extern unsigned char MCS_rate_2R23A[16];
-extern unsigned char RTW_WPA_OUI23A[];
 extern unsigned char WPA_TKIP_CIPHER23A[4];
 extern unsigned char RSN_TKIP_CIPHER23A[4];
 
@@ -149,16 +146,6 @@ extern unsigned char	MCS_rate_1R23A[16];
 void	_rtw_init_queue23a(struct rtw_queue *pqueue);
 u32	_rtw_queue_empty23a(struct rtw_queue *pqueue);
 
-static inline u32 bitshift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++)
-		if (((bitmask>>i) &  0x1) == 1) break;
-
-	return i;
-}
-
 void rtw_suspend_lock_init(void);
 void rtw_suspend_lock_uninit(void);
 void rtw_lock_suspend(void);
@@ -174,12 +161,6 @@ void rtw_unlock_suspend(void);
 #define FUNC_ADPT_FMT "%s(%s)"
 #define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name
 
-#define rtw_signal_process(pid, sig) kill_pid(find_vpid((pid)),(sig), 1)
-
-u64 rtw_modular6423a(u64 x, u64 y);
-u64 rtw_division6423a(u64 x, u64 y);
-
-
 /* Macros for handling unaligned memory accesses */
 
 #define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
@@ -199,9 +180,7 @@ bool rtw_cbuf_push23a(struct rtw_cbuf *cbuf, void *buf);
 void *rtw_cbuf_pop23a(struct rtw_cbuf *cbuf);
 struct rtw_cbuf *rtw_cbuf_alloc23a(u32 size);
 void rtw_cbuf_free(struct rtw_cbuf *cbuf);
-int rtw_change_ifname(struct rtw_adapter *padapter, const char *ifname);
 s32 c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter);
-void indicate_wx_scan_complete_event(struct rtw_adapter *padapter);
 u8 rtw_do_join23a(struct rtw_adapter *padapter);
 
 #endif
diff --git a/drivers/staging/rtl8723au/include/recv_osdep.h b/drivers/staging/rtl8723au/include/recv_osdep.h
index 15c94b6168bf..c2d3f1bd5948 100644
--- a/drivers/staging/rtl8723au/include/recv_osdep.h
+++ b/drivers/staging/rtl8723au/include/recv_osdep.h
@@ -23,22 +23,13 @@ void _rtw_free_recv_priv23a (struct recv_priv *precvpriv);
 
 int rtw_recv_entry23a(struct recv_frame *precv_frame);
 int rtw_recv_indicatepkt23a(struct rtw_adapter *adapter, struct recv_frame *precv_frame);
-void rtw_recv_returnpacket(struct net_device *cnxt, struct sk_buff *preturnedpkt);
 
-void rtw_hostapd_mlme_rx23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
 void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup);
 
 int	rtw_init_recv_priv(struct recv_priv *precvpriv, struct rtw_adapter *padapter);
 void rtw_free_recv_priv (struct recv_priv *precvpriv);
 
 int rtw_os_recv_resource_init(struct recv_priv *precvpriv, struct rtw_adapter *padapter);
-int rtw_os_recv_resource_alloc23a(struct rtw_adapter *padapter, struct recv_frame *precvframe);
-void rtw_os_recv_resource_free(struct recv_priv *precvpriv);
-
-int rtw_os_recvbuf_resource_alloc23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf);
-int rtw_os_recvbuf_resource_free23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf);
-
-void rtw_os_read_port23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf);
 
 void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl);
 
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_cmd.h b/drivers/staging/rtl8723au/include/rtl8723a_cmd.h
index 8fccbfc3a45c..09fa72340302 100644
--- a/drivers/staging/rtl8723au/include/rtl8723a_cmd.h
+++ b/drivers/staging/rtl8723au/include/rtl8723a_cmd.h
@@ -151,10 +151,6 @@ u8 rtl8723a_set_rssi_cmd(struct rtw_adapter * padapter, u8 *param);
 u8 rtl8723a_set_raid_cmd(struct rtw_adapter * padapter, u32 mask, u8 arg);
 void rtl8723a_add_rateatid(struct rtw_adapter * padapter, u32 bitmap, u8 arg, u8 rssi_level);
 
-#ifdef CONFIG_8723AU_P2P
-void rtl8723a_set_p2p_ps_offload_cmd(struct rtw_adapter * padapter, u8 p2p_ps_state);
-#endif /* CONFIG_8723AU_P2P */
-
 void CheckFwRsvdPageContent23a(struct rtw_adapter *padapter);
 
 #endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_hal.h b/drivers/staging/rtl8723au/include/rtl8723a_hal.h
index c20248bab717..f6b4b7c7c22d 100644
--- a/drivers/staging/rtl8723au/include/rtl8723a_hal.h
+++ b/drivers/staging/rtl8723au/include/rtl8723a_hal.h
@@ -424,11 +424,6 @@ struct hal_data_8723a {
 
 	bool				bMACFuncEnable;
 
-#ifdef CONFIG_8723AU_P2P
-	struct P2P_PS_Offload_t	p2p_ps_offload;
-#endif
-
-
 	/*  */
 	/*  For USB Interface HAL related */
 	/*  */
@@ -437,14 +432,6 @@ struct hal_data_8723a {
 	/*  Interrupt related register information. */
 	u32	IntArray[2];
 	u32	IntrMask[2];
-
-	/*  */
-	/*  For SDIO Interface HAL related */
-	/*  */
-
-	/*  Auto FSM to Turn On, include clock, isolation, power control for MAC only */
-	u8			bMacPwrCtrlOn;
-
 };
 
 #define GET_HAL_DATA(__pAdapter)	((struct hal_data_8723a *)((__pAdapter)->HalData))
@@ -556,8 +543,6 @@ void Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter, u8 *hwinfo,
 void Hal_InitChannelPlan23a(struct rtw_adapter *padapter);
 
 void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc);
-void SetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val);
-void GetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val);
 #ifdef CONFIG_8723AU_BT_COEXIST
 void rtl8723a_SingleDualAntennaDetection(struct rtw_adapter *padapter);
 #endif
diff --git a/drivers/staging/rtl8723au/include/rtw_ap.h b/drivers/staging/rtl8723au/include/rtw_ap.h
index 76f82d68f633..7bcadff02ef9 100644
--- a/drivers/staging/rtl8723au/include/rtw_ap.h
+++ b/drivers/staging/rtl8723au/include/rtw_ap.h
@@ -22,8 +22,6 @@
 #ifdef CONFIG_8723AU_AP_MODE
 
 /* external function */
-void rtw_indicate_sta_assoc_event23a(struct rtw_adapter *padapter, struct sta_info *psta);
-void rtw_indicate_sta_disassoc_event23a(struct rtw_adapter *padapter, struct sta_info *psta);
 
 void init_mlme_ap_info23a(struct rtw_adapter *padapter);
 void free_mlme_ap_info23a(struct rtw_adapter *padapter);
diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h
index f9caa3e35f57..ba6d572b81b3 100644
--- a/drivers/staging/rtl8723au/include/rtw_cmd.h
+++ b/drivers/staging/rtl8723au/include/rtw_cmd.h
@@ -106,9 +106,6 @@ u32 rtw_init_evt_priv23a (struct evt_priv *pevtpriv);
 void rtw_free_evt_priv23a (struct evt_priv *pevtpriv);
 void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv);
 void rtw_evt_notify_isr(struct evt_priv *pevtpriv);
-#ifdef CONFIG_8723AU_P2P
-u8 p2p_protocol_wk_cmd23a(struct rtw_adapter*padapter, int intCmdType );
-#endif /* CONFIG_8723AU_P2P */
 
 enum rtw_drvextra_cmd_id
 {
diff --git a/drivers/staging/rtl8723au/include/rtw_mlme.h b/drivers/staging/rtl8723au/include/rtw_mlme.h
index 31f96f39b498..3d6f7307e41e 100644
--- a/drivers/staging/rtl8723au/include/rtw_mlme.h
+++ b/drivers/staging/rtl8723au/include/rtw_mlme.h
@@ -148,30 +148,6 @@ struct tx_invite_resp_info {
 	u8	token;	/*	Used to record the dialog token of p2p invitation request frame. */
 };
 
-#ifdef CONFIG_8723AU_P2P
-
-struct wifi_display_info {
-	u16	wfd_enable;		/* Enable/Disable the WFD function. */
-	u16	rtsp_ctrlport;		/* TCP port number at which the this WFD device listens for RTSP messages */
-	u16	peer_rtsp_ctrlport;	/* TCP port number at which the peer WFD device listens for RTSP messages */
-					/* This filed should be filled when receiving the gropu negotiation request */
-
-	u8	peer_session_avail;	/* WFD session is available or not for the peer wfd device. */
-					/* This variable will be set when sending the provisioning discovery request to peer WFD device. */
-					/* And this variable will be reset when it is read by using the iwpriv p2p_get wfd_sa command. */
-	u8	ip_address[4];
-	u8	peer_ip_address[4];
-	u8	wfd_pc;		/* WFD preferred connection */
-				/* 0 -> Prefer to use the P2P for WFD connection on peer side. */
-				/* 1 -> Prefer to use the TDLS for WFD connection on peer side. */
-
-	u8	wfd_device_type;/* WFD Device Type */
-				/* 0 -> WFD Source Device */
-				/* 1 -> WFD Primary Sink Device */
-	enum	SCAN_RESULT_TYPE scan_result_type;	/* Used when P2P is enable. This parameter will impact the scan result. */
-};
-#endif /* CONFIG_8723AU_P2P */
-
 struct tx_provdisc_req_info {
 	u16	wps_config_method_request;	/* Used when sending the provisioning request frame */
 	u16	peer_channel_num[2];		/* The channel number which the receiver stands. */
@@ -203,102 +179,6 @@ struct scan_limit_info {
 	u8	operation_ch[2];	/* Store the operation channel of invitation request frame */
 };
 
-struct cfg80211_wifidirect_info {
-	struct timer_list		remain_on_ch_timer;
-	u8		restore_channel;
-	struct ieee80211_channel	remain_on_ch_channel;
-	enum nl80211_channel_type	remain_on_ch_type;
-	u64	remain_on_ch_cookie;
-	bool is_ro_ch;
-};
-
-struct wifidirect_info {
-	struct rtw_adapter	*padapter;
-	struct timer_list	find_phase_timer;
-	struct timer_list	restore_p2p_state_timer;
-
-	/*	Used to do the scanning. After confirming the peer is availalble, the driver transmits the P2P frame to peer. */
-	struct timer_list	pre_tx_scan_timer;
-	struct timer_list	reset_ch_sitesurvey;
-	struct timer_list	reset_ch_sitesurvey2;	/*	Just for resetting the scan limit function by using p2p nego */
-	struct tx_provdisc_req_info	tx_prov_disc_info;
-	struct rx_provdisc_req_info rx_prov_disc_info;
-	struct tx_invite_req_info	invitereq_info;
-	struct profile_info	profileinfo[P2P_MAX_PERSISTENT_GROUP_NUM];	/*	Store the profile information of persistent group */
-	struct tx_invite_resp_info	inviteresp_info;
-	struct tx_nego_req_info	nego_req_info;
-	struct group_id_info	groupid_info;	/*	Store the group id information when doing the group negotiation handshake. */
-	struct scan_limit_info	rx_invitereq_info;	/*	Used for get the limit scan channel from the Invitation procedure */
-	struct scan_limit_info	p2p_info;		/*	Used for get the limit scan channel from the P2P negotiation handshake */
-#ifdef CONFIG_8723AU_P2P
-	struct wifi_display_info	*wfd_info;
-#endif
-	enum P2P_ROLE	role;
-	enum P2P_STATE	pre_p2p_state;
-	enum P2P_STATE	p2p_state;
-	u8	device_addr[ETH_ALEN];	/*	The device address should be the mac address of this device. */
-	u8	interface_addr[ETH_ALEN];
-	u8	social_chan[4];
-	u8	listen_channel;
-	u8	operating_channel;
-	u8	listen_dwell;		/*	This value should be between 1 and 3 */
-	u8	support_rate[8];
-	u8	p2p_wildcard_ssid[P2P_WILDCARD_SSID_LEN];
-	u8	intent;		/*	should only include the intent value. */
-	u8	p2p_peer_interface_addr[ETH_ALEN];
-	u8	p2p_peer_device_addr[ETH_ALEN];
-	u8	peer_intent;	/*	Included the intent value and tie breaker value. */
-	u8	device_name[WPS_MAX_DEVICE_NAME_LEN];	/*	Device name for displaying on searching device screen */
-	u8	device_name_len;
-	u8	profileindex;	/*	Used to point to the index of profileinfo array */
-	u8	peer_operating_ch;
-	u8	find_phase_state_exchange_cnt;
-	u16	device_password_id_for_nego;	/*	The device password ID for group negotation */
-	u8	negotiation_dialog_token;
-	/*	SSID information for group negotitation */
-	u8 nego_ssid[IEEE80211_MAX_SSID_LEN];
-	u8 nego_ssidlen;
-	u8 p2p_group_ssid[IEEE80211_MAX_SSID_LEN];
-	u8 p2p_group_ssid_len;
-	u8	persistent_supported;	/*	Flag to know the persistent function should be supported or not. */
-					/*	In the Sigma test, the Sigma will provide this enable from the sta_set_p2p CAPI. */
-					/*	0: disable */
-					/*	1: enable */
-	u8	session_available;	/*	Flag to set the WFD session available to enable or disable "by Sigma" */
-					/*	In the Sigma test, the Sigma will disable the session available by using the sta_preset CAPI. */
-					/*	0: disable */
-					/*	1: enable */
-
-	u8	wfd_tdls_enable;	/*	Flag to enable or disable the TDLS by WFD Sigma */
-					/*	0: disable */
-					/*	1: enable */
-	u8	wfd_tdls_weaksec;	/*	Flag to enable or disable the weak security function for TDLS by WFD Sigma */
-				/*	0: disable */
-				/*	In this case, the driver can't issue the tdsl setup request frame. */
-				/*	1: enable */
-				/*	In this case, the driver can issue the tdls setup request frame */
-				/*	even the current security is weak security. */
-
-	enum	P2P_WPSINFO		ui_got_wps_info;			/*	This field will store the WPS value (PIN value or PBC) that UI had got from the user. */
-	u16	supported_wps_cm;			/*	This field describes the WPS config method which this driver supported. */
-														/*	The value should be the combination of config method defined in page104 of WPS v2.0 spec. */
-	uint	channel_list_attr_len;		/*	This field will contain the length of body of P2P Channel List attribute of group negotitation response frame. */
-	u8	channel_list_attr[100];		/*	This field will contain the body of P2P Channel List attribute of group negotitation response frame. */
-														/*	We will use the channel_cnt and channel_list fields when constructing the group negotitation confirm frame. */
-#ifdef CONFIG_8723AU_P2P
-	enum P2P_PS_MODE	p2p_ps_mode; /*  indicate p2p ps mode */
-	enum P2P_PS_STATE	p2p_ps_state; /*  indicate p2p ps state */
-	u8	noa_index; /*  Identifies and instance of Notice of Absence timing. */
-	u8	ctwindow; /*  Client traffic window. A period of time in TU after TBTT. */
-	u8	opp_ps; /*  opportunistic power save. */
-	u8	noa_num; /*  number of NoA descriptor in P2P IE. */
-	u8	noa_count[P2P_MAX_NOA_NUM]; /*  Count for owner, Type of client. */
-	u32	noa_duration[P2P_MAX_NOA_NUM]; /*  Max duration for owner, preferred or min acceptable duration for client. */
-	u32	noa_interval[P2P_MAX_NOA_NUM]; /*  Length of interval for owner, preferred or max acceptable interval of client. */
-	u32	noa_start_time[P2P_MAX_NOA_NUM]; /*  schedule expressed in terms of the lower 4 bytes of the TSF timer. */
-#endif /*  CONFIG_8723AU_P2P */
-};
-
 struct tdls_ss_record {	/* signal strength record */
 	u8	macaddr[ETH_ALEN];
 	u8	RxPWDBAll;
@@ -324,9 +204,6 @@ struct tdls_info {
 	u8	watchdog_count;
 	u8	dev_discovered;		/* WFD_TDLS: for sigma test */
 	u8	enable;
-#ifdef CONFIG_8723AU_P2P
-	struct wifi_display_info		*wfd_info;
-#endif
 };
 
 struct mlme_priv {
@@ -553,7 +430,6 @@ void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
 			      int lock_scanned_queue);
 void rtw_indicate_disconnect23a(struct rtw_adapter *adapter);
 void rtw_indicate_connect23a(struct rtw_adapter *adapter);
-void rtw_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted);
 void rtw_scan_abort23a(struct rtw_adapter *adapter);
 
 int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
@@ -582,8 +458,6 @@ void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv);
 
 struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv);
 
-void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
-		       struct wlan_network *pnetwork, u8 isfreeall);
 void _rtw_free_network23a_nolock23a(struct mlme_priv *pmlmepriv,
 			      struct wlan_network *pnetwork);
 
@@ -596,7 +470,6 @@ int rtw_if_up23a(struct rtw_adapter *padapter);
 int rtw_linked_check(struct rtw_adapter *padapter);
 
 u8 *rtw_get_capability23a_from_ie(u8 *ie);
-u8 *rtw_get_timestampe_from_ie23a(u8 *ie);
 u8 *rtw_get_beacon_interval23a_from_ie(u8 *ie);
 
 
@@ -613,12 +486,8 @@ int rtw_is_same_ibss23a(struct rtw_adapter *adapter,
 		     struct wlan_network *pnetwork);
 int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst);
 
-void _rtw23a_roaming(struct rtw_adapter *adapter,
-		  struct wlan_network *tgt_network);
 void rtw23a_roaming(struct rtw_adapter *adapter,
 		 struct wlan_network *tgt_network);
 void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming);
-u8 rtw_to_roaming(struct rtw_adapter *adapter);
-void rtw_stassoc_hw_rpt23a(struct rtw_adapter *adapter, struct sta_info *psta);
 
 #endif /* __RTL871X_MLME_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h
index 0aaf0d5d8aea..cbea64938c54 100644
--- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h
@@ -89,7 +89,6 @@
 #define		_54M_RATE_	11
 
 
-extern unsigned char RTW_WPA_OUI23A[];
 extern unsigned char WMM_OUI23A[];
 extern unsigned char WPS_OUI23A[];
 extern unsigned char WFD_OUI23A[];
@@ -262,13 +261,13 @@ enum SCAN_STATE {
 
 struct mlme_handler {
 	char *str;
-	unsigned int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+	int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
 };
 
 struct action_handler {
 	unsigned int   num;
 	char* str;
-	unsigned int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
+	int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
 };
 
 struct	ss_res
@@ -474,10 +473,6 @@ void get_rate_set23a(struct rtw_adapter *padapter, unsigned char *pbssrate,
 void UpdateBrateTbl23a(struct rtw_adapter *padapter,u8 *mBratesOS);
 void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen);
 
-void Save_DM_Func_Flag23a(struct rtw_adapter *padapter);
-void Restore_DM_Func_Flag23a(struct rtw_adapter *padapter);
-void Switch_DM_Func23a(struct rtw_adapter *padapter, unsigned long mode, u8 enable);
-
 void Set_MSR23a(struct rtw_adapter *padapter, u8 type);
 
 u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter);
@@ -495,12 +490,9 @@ void SetBWMode23a(struct rtw_adapter *padapter, unsigned short bwmode,
 
 unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval);
 
-void write_cam23a(struct rtw_adapter *padapter, u8 entry, u16 ctrl,
-	       u8 *mac, u8 *key);
 void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry);
 
 void invalidate_cam_all23a(struct rtw_adapter *padapter);
-void CAM_empty_entry23a(struct rtw_adapter *Adapter, u8 ucIndex);
 
 int allocate_fw_sta_entry23a(struct rtw_adapter *padapter);
 void flush_all_cam_entry23a(struct rtw_adapter *padapter);
@@ -526,10 +518,6 @@ unsigned char check_assoc_AP23a(u8 *pframe, uint len);
 
 int WMM_param_handler23a(struct rtw_adapter *padapter,
 		      struct ndis_802_11_var_ies *pIE);
-#ifdef CONFIG_8723AU_P2P
-int WFD_info_handler(struct rtw_adapter *padapter,
-		     struct ndis_802_11_var_ies *pIE);
-#endif
 void WMMOnAssocRsp23a(struct rtw_adapter *padapter);
 
 void HT_caps_handler23a(struct rtw_adapter *padapter,
@@ -544,7 +532,8 @@ void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta);
 
 void update_beacon23a_info(struct rtw_adapter *padapter, u8 *pframe, uint len,
 			struct sta_info *psta);
-int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, u8 *pframe, u32 packet_len);
+int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
+			  struct ieee80211_mgmt *mgmt, u32 packet_len);
 void update_IOT_info23a(struct rtw_adapter *padapter);
 void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap);
 void update_wireless_mode23a(struct rtw_adapter * padapter);
@@ -594,18 +583,6 @@ s32 dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
 s32 dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
 				struct xmit_frame *pmgntframe);
 
-#ifdef CONFIG_8723AU_P2P
-void issue_probersp23a_p2p23a(struct rtw_adapter *padapter, unsigned char *da);
-void issue_p2p_provision_request23a(struct rtw_adapter *padapter, u8 *pssid,
-				 u8 ussidlen, u8* pdev_raddr);
-void issue_p2p_GO_request23a(struct rtw_adapter *padapter, u8* raddr);
-void issue23a_probereq_p2p(struct rtw_adapter *padapter, u8 *da);
-int issue23a_probereq_p2p_ex(struct rtw_adapter *adapter, u8 *da, int try_cnt,
-			  int wait_ms);
-void issue_p2p_invitation_response23a(struct rtw_adapter *padapter, u8* raddr,
-				   u8 dialogToken, u8 success);
-void issue_p2p_invitation_request23a(struct rtw_adapter *padapter, u8* raddr);
-#endif /* CONFIG_8723AU_P2P */
 void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms);
 void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
 		    u8 is_valid_p2p_probereq);
@@ -638,28 +615,6 @@ void start_clnt_auth23a(struct rtw_adapter *padapter);
 void start_clnt_join23a(struct rtw_adapter *padapter);
 void start_create_ibss23a(struct rtw_adapter *padapter);
 
-unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-
-unsigned int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-unsigned int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
-
 
 void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_res);
 void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter);
@@ -680,7 +635,6 @@ int cckratesonly_included23a(unsigned char *rate, int ratelen);
 
 void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr);
 
-void update_TSF23a(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len);
 void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext);
 
 struct cmd_hdl {
diff --git a/drivers/staging/rtl8723au/include/rtw_p2p.h b/drivers/staging/rtl8723au/include/rtw_p2p.h
deleted file mode 100644
index 93fdc658ff4d..000000000000
--- a/drivers/staging/rtl8723au/include/rtw_p2p.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- ******************************************************************************/
-#ifndef __RTW_P2P_H_
-#define __RTW_P2P_H_
-
-#include <drv_types.h>
-
-u32 build_beacon_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_probe_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_prov_disc_request_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf,
-				   u8 *pssid, u8 ussidlen, u8 *pdev_raddr);
-u32 build_assoc_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf,
-			    u8 status_code);
-u32 build_deauth_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf);
-#ifdef CONFIG_8723AU_P2P
-u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf,
-			    u8 tunneled);
-u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
-#endif /* CONFIG_8723AU_P2P */
-
-u32 process_probe_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe,
-			     uint len);
-u32 process_assoc_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe,
-			     uint len, struct sta_info *psta);
-u32 process_p2p_devdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
-			    uint len);
-u32 process_p2p_devdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe,
-			     uint len);
-u8 process_p2p_provdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
-			    uint len);
-u8 process_p2p_provdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe);
-u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo,
-				    u8 *pframe, uint len);
-u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo,
-				     u8 *pframe, uint len);
-u8 process_p2p_group_negotation_confirm23a(struct wifidirect_info *pwdinfo,
-					u8 *pframe, uint len);
-u8 process_p2p_presence_req23a(struct wifidirect_info *pwdinfo,
-			    u8 *pframe, uint len);
-
-void p2p_protocol_wk_hdl23a(struct rtw_adapter *padapter, int cmdtype);
-
-#ifdef CONFIG_8723AU_P2P
-void	process_p2p_ps_ie23a(struct rtw_adapter *padapter, u8 *IEs, u32 IELength);
-void	p2p_ps_wk_hdl23a(struct rtw_adapter *padapter, u8 p2p_ps_state);
-u8 p2p_ps_wk_cmd23a(struct rtw_adapter *padapter, u8 p2p_ps_state, u8 enqueue);
-#endif /*  CONFIG_8723AU_P2P */
-
-void rtw_init_cfg80211_wifidirect_info(struct rtw_adapter *padapter);
-int rtw_p2p_check_frames(struct rtw_adapter *padapter, const u8 *buf,
-			 u32 len, u8 tx);
-void rtw_append_wfd_ie(struct rtw_adapter *padapter, u8 *buf, u32 *len);
-
-void reset_global_wifidirect_info23a(struct rtw_adapter *padapter);
-int rtw_init_wifi_display_info(struct rtw_adapter *padapter);
-void rtw_init_wifidirect_timers23a(struct rtw_adapter *padapter);
-void rtw_init_wifidirect_addrs23a(struct rtw_adapter *padapter, u8 *dev_addr,
-			       u8 *iface_addr);
-void init_wifidirect_info23a(struct rtw_adapter *padapter, enum P2P_ROLE role);
-int rtw_p2p_enable23a(struct rtw_adapter *padapter, enum P2P_ROLE role);
-
-static inline void _rtw_p2p_set_state(struct wifidirect_info *wdinfo,
-				      enum P2P_STATE state)
-{
-	if (wdinfo->p2p_state != state) {
-		/* wdinfo->pre_p2p_state = wdinfo->p2p_state; */
-		wdinfo->p2p_state = state;
-	}
-}
-
-static inline void _rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo,
-					  enum P2P_STATE state)
-{
-	if (wdinfo->pre_p2p_state != state)
-		wdinfo->pre_p2p_state = state;
-}
-
-static inline void _rtw_p2p_set_role(struct wifidirect_info *wdinfo,
-				     enum P2P_ROLE role)
-{
-	if (wdinfo->role != role)
-		wdinfo->role = role;
-}
-
-static inline int _rtw_p2p_state(struct wifidirect_info *wdinfo)
-{
-	return wdinfo->p2p_state;
-}
-
-static inline int _rtw_p2p_pre_state(struct wifidirect_info *wdinfo)
-{
-	return wdinfo->pre_p2p_state;
-}
-
-static inline int _rtw_p2p_role(struct wifidirect_info *wdinfo)
-{
-	return wdinfo->role;
-}
-
-static inline bool _rtw_p2p_chk_state(struct wifidirect_info *wdinfo,
-				      enum P2P_STATE state)
-{
-	return wdinfo->p2p_state == state;
-}
-
-static inline bool _rtw_p2p_chk_role(struct wifidirect_info *wdinfo,
-				     enum P2P_ROLE role)
-{
-	return wdinfo->role == role;
-}
-
-#define rtw_p2p_set_state(wdinfo, state) _rtw_p2p_set_state(wdinfo, state)
-#define rtw_p2p_set_pre_state(wdinfo, state)			\
-	_rtw_p2p_set_pre_state(wdinfo, state)
-#define rtw_p2p_set_role(wdinfo, role) _rtw_p2p_set_role(wdinfo, role)
-
-#define rtw_p2p_state(wdinfo) _rtw_p2p_state(wdinfo)
-#define rtw_p2p_pre_state(wdinfo) _rtw_p2p_pre_state(wdinfo)
-#define rtw_p2p_role(wdinfo) _rtw_p2p_role(wdinfo)
-#define rtw_p2p_chk_state(wdinfo, state) _rtw_p2p_chk_state(wdinfo, state)
-#define rtw_p2p_chk_role(wdinfo, role) _rtw_p2p_chk_role(wdinfo, role)
-
-#define rtw_p2p_findphase_ex_set(wdinfo, value) \
-	((wdinfo)->find_phase_state_exchange_cnt = (value))
-
-/* is this find phase exchange for social channel scan? */
-#define rtw_p2p_findphase_ex_is_social(wdinfo)			\
-	((wdinfo)->find_phase_state_exchange_cnt >=		\
-	 P2P_FINDPHASE_EX_SOCIAL_FIRST)
-
-/* should we need find phase exchange anymore? */
-#define rtw_p2p_findphase_ex_is_needed(wdinfo) \
-	((wdinfo)->find_phase_state_exchange_cnt < P2P_FINDPHASE_EX_MAX && \
-	(wdinfo)->find_phase_state_exchange_cnt != P2P_FINDPHASE_EX_NONE)
-
-#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_security.h b/drivers/staging/rtl8723au/include/rtw_security.h
index 75bbb934a53c..702dd845a3ff 100644
--- a/drivers/staging/rtl8723au/include/rtw_security.h
+++ b/drivers/staging/rtl8723au/include/rtw_security.h
@@ -30,7 +30,6 @@
 
 #define is_wep_enc(alg) (((alg) == _WEP40_) || ((alg) == _WEP104_))
 
-#define _WPA_IE_ID_	0xdd
 #define _WPA2_IE_ID_	0x30
 
 #define SHA256_MAC_LEN 32
@@ -316,22 +315,6 @@ static const unsigned long K[64] = {
 	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
 };
 
-/* Various logical functions */
-#define RORc(x, y) \
-(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
-((unsigned long)(x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
-#define Ch(x, y, z)     (z ^ (x & (y ^ z)))
-#define Maj(x, y, z)    (((x | y) & z) | (x & y))
-#define S(x, n)         RORc((x), (n))
-#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
-#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
-#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
-#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
-#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-#ifndef MIN
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#endif
-
 void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 *key);
 void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b);
 void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbBytes);
diff --git a/drivers/staging/rtl8723au/include/wifi.h b/drivers/staging/rtl8723au/include/wifi.h
index b5034c6ef1dc..57ad44ec0aa8 100644
--- a/drivers/staging/rtl8723au/include/wifi.h
+++ b/drivers/staging/rtl8723au/include/wifi.h
@@ -219,39 +219,8 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
 
 #define _FIXED_IE_LENGTH_		_BEACON_IE_OFFSET_
 
-#define _SSID_IE_			0
-#define _SUPPORTEDRATES_IE_		1
-#define _DSSET_IE_			3
-#define _TIM_IE_			5
-#define _IBSS_PARA_IE_			6
-#define _COUNTRY_IE_			7
-#define _CHLGETXT_IE_			16
-#define _SUPPORTED_CH_IE_		36
-#define _CH_SWTICH_ANNOUNCE_	37	/* Secondary Channel Offset */
-#define _RSN_IE_2_			48
-#define _SSN_IE_1_			221
-#define _ERPINFO_IE_			42
-#define _EXT_SUPPORTEDRATES_IE_		50
-
-#define _HT_CAPABILITY_IE_		45
-#define _FTIE_				55
-#define _TIMEOUT_ITVL_IE_		56
-#define _SRC_IE_			59
-#define _HT_EXTRA_INFO_IE_		61
-#define _HT_ADD_INFO_IE_		61 /* _HT_EXTRA_INFO_IE_ */
-
-
-#define	EID_BSSCoexistence		72 /*  20/40 BSS Coexistence */
-#define	EID_BSSIntolerantChlReport	73
-#define _RIC_Descriptor_IE_		75
-
-#define _LINK_ID_IE_		101
-#define _CH_SWITCH_TIMING_	104
-#define _PTI_BUFFER_STATUS_	106
-#define _EXT_CAP_IE_		127
-#define _VENDOR_SPECIFIC_IE_	221
 
-#define	_RESERVED47_		47
+#define	EID_BSSIntolerantChlReport	73
 
 /* ---------------------------------------------------------------------------
 					Below is the fixed elements...
@@ -490,72 +459,6 @@ struct ADDBA_request {
 #define WPS_ASSOC_STATE_ASSOCIATION_FAILURE	0x03
 #define WPS_ASSOC_STATE_IP_FAILURE		0x04
 
-/*	=====================P2P Section===================== */
-/*	For P2P */
-#define	P2POUI					0x506F9A09
-
-/*	P2P Attribute ID */
-#define	P2P_ATTR_STATUS				0x00
-#define	P2P_ATTR_MINOR_REASON_CODE		0x01
-#define	P2P_ATTR_CAPABILITY			0x02
-#define	P2P_ATTR_DEVICE_ID			0x03
-#define	P2P_ATTR_GO_INTENT			0x04
-#define	P2P_ATTR_CONF_TIMEOUT			0x05
-#define	P2P_ATTR_LISTEN_CH			0x06
-#define	P2P_ATTR_GROUP_BSSID			0x07
-#define	P2P_ATTR_EX_LISTEN_TIMING		0x08
-#define	P2P_ATTR_INTENTED_IF_ADDR		0x09
-#define	P2P_ATTR_MANAGEABILITY			0x0A
-#define	P2P_ATTR_CH_LIST			0x0B
-#define	P2P_ATTR_NOA				0x0C
-#define	P2P_ATTR_DEVICE_INFO			0x0D
-#define	P2P_ATTR_GROUP_INFO			0x0E
-#define	P2P_ATTR_GROUP_ID			0x0F
-#define	P2P_ATTR_INTERFACE			0x10
-#define	P2P_ATTR_OPERATING_CH			0x11
-#define	P2P_ATTR_INVITATION_FLAGS		0x12
-
-/*	Value of Status Attribute */
-#define	P2P_STATUS_SUCCESS			0x00
-#define	P2P_STATUS_FAIL_INFO_UNAVAILABLE	0x01
-#define	P2P_STATUS_FAIL_INCOMPATIBLE_PARAM	0x02
-#define	P2P_STATUS_FAIL_LIMIT_REACHED		0x03
-#define	P2P_STATUS_FAIL_INVALID_PARAM		0x04
-#define	P2P_STATUS_FAIL_REQUEST_UNABLE		0x05
-#define	P2P_STATUS_FAIL_PREVOUS_PROTO_ERR	0x06
-#define	P2P_STATUS_FAIL_NO_COMMON_CH		0x07
-#define	P2P_STATUS_FAIL_UNKNOWN_P2PGROUP	0x08
-#define	P2P_STATUS_FAIL_BOTH_GOINTENT_15	0x09
-#define	P2P_STATUS_FAIL_INCOMPATIBLE_PROVSION	0x0A
-#define	P2P_STATUS_FAIL_USER_REJECT		0x0B
-
-/*	Value of Inviation Flags Attribute */
-#define	P2P_INVITATION_FLAGS_PERSISTENT		BIT(0)
-
-#define	DMP_P2P_DEVCAP_SUPPORT	(P2P_DEVCAP_SERVICE_DISCOVERY | \
-				 P2P_DEVCAP_CLIENT_DISCOVERABILITY | \
-				 P2P_DEVCAP_CONCURRENT_OPERATION | \
-				 P2P_DEVCAP_INVITATION_PROC)
-
-#define	DMP_P2P_GRPCAP_SUPPORT	(P2P_GRPCAP_INTRABSS)
-
-/*	Value of Device Capability Bitmap */
-#define	P2P_DEVCAP_SERVICE_DISCOVERY		BIT(0)
-#define	P2P_DEVCAP_CLIENT_DISCOVERABILITY	BIT(1)
-#define	P2P_DEVCAP_CONCURRENT_OPERATION		BIT(2)
-#define	P2P_DEVCAP_INFRA_MANAGED		BIT(3)
-#define	P2P_DEVCAP_DEVICE_LIMIT			BIT(4)
-#define	P2P_DEVCAP_INVITATION_PROC		BIT(5)
-
-/*	Value of Group Capability Bitmap */
-#define	P2P_GRPCAP_GO				BIT(0)
-#define	P2P_GRPCAP_PERSISTENT_GROUP		BIT(1)
-#define	P2P_GRPCAP_GROUP_LIMIT			BIT(2)
-#define	P2P_GRPCAP_INTRABSS			BIT(3)
-#define	P2P_GRPCAP_CROSS_CONN			BIT(4)
-#define	P2P_GRPCAP_PERSISTENT_RECONN		BIT(5)
-#define	P2P_GRPCAP_GROUP_FORMATION		BIT(6)
-
 /*	P2P Public Action Frame ( Management Frame ) */
 #define	P2P_PUB_ACTION_ACTION			0x09
 
@@ -570,37 +473,6 @@ struct ADDBA_request {
 #define	P2P_PROVISION_DISC_REQ			7
 #define	P2P_PROVISION_DISC_RESP			8
 
-/*	P2P Action Frame Type */
-#define	P2P_NOTICE_OF_ABSENCE			0
-#define	P2P_PRESENCE_REQUEST			1
-#define	P2P_PRESENCE_RESPONSE			2
-#define	P2P_GO_DISC_REQUEST			3
-
-
-#define	P2P_MAX_PERSISTENT_GROUP_NUM		10
-
-#define	P2P_PROVISIONING_SCAN_CNT		3
-
-#define	P2P_WILDCARD_SSID_LEN			7
-
-#define	P2P_FINDPHASE_EX_NONE			0	/*  default value, used when: (1)p2p disabed or (2)p2p enabled but only do 1 scan phase */
-#define	P2P_FINDPHASE_EX_FULL			1	/*  used when p2p enabled and want to do 1 scan phase and P2P_FINDPHASE_EX_MAX-1 find phase */
-#define	P2P_FINDPHASE_EX_SOCIAL_FIRST		(P2P_FINDPHASE_EX_FULL+1)
-#define	P2P_FINDPHASE_EX_MAX					4
-#define	P2P_FINDPHASE_EX_SOCIAL_LAST		P2P_FINDPHASE_EX_MAX
-
-#define	P2P_PROVISION_TIMEOUT			5000	/*5 sec timeout for sending the provision discovery request */
-#define	P2P_CONCURRENT_PROVISION_TIMEOUT	3000	/*3 sec timeout for sending the provision discovery request under concurrent mode */
-#define	P2P_GO_NEGO_TIMEOUT			5000	/*5 sec timeout for receiving the group negotation response */
-#define	P2P_CONCURRENT_GO_NEGO_TIMEOUT		3000	/*3 sec timeout for sending the negotiation request under concurrent mode */
-#define	P2P_TX_PRESCAN_TIMEOUT			100	/*100ms */
-#define	P2P_INVITE_TIMEOUT			5000	/*5 sec timeout for sending the invitation request */
-#define	P2P_CONCURRENT_INVITE_TIMEOUT		3000	/*3 sec timeout for sending the invitation request under concurrent mode */
-#define	P2P_RESET_SCAN_CH			25000	/*25 sec t/o to reset the scan channel ( based on channel plan ) */
-#define	P2P_MAX_INTENT				15
-
-#define	P2P_MAX_NOA_NUM				2
-
 /*	WPS Configuration Method */
 #define	WPS_CM_NONE					0x0000
 #define	WPS_CM_LABEL					0x0004
@@ -615,93 +487,4 @@ struct ADDBA_request {
 #define	WPS_CM_SW_DISPLAY_PIN				0x2008
 #define	WPS_CM_LCD_DISPLAY_PIN				0x4008
 
-enum P2P_ROLE {
-	P2P_ROLE_DISABLE = 0,
-	P2P_ROLE_DEVICE = 1,
-	P2P_ROLE_CLIENT = 2,
-	P2P_ROLE_GO = 3
-};
-
-enum P2P_STATE {
-	P2P_STATE_NONE = 0,			/*P2P disable */
-	P2P_STATE_IDLE = 1,			/*P2P had enabled and do nothing */
-	P2P_STATE_LISTEN = 2,			/*In pure listen state */
-	P2P_STATE_SCAN = 3,			/*In scan phase */
-	P2P_STATE_FIND_PHASE_LISTEN = 4,	/*In the listen state of find phase */
-	P2P_STATE_FIND_PHASE_SEARCH = 5,	/*In the search state of find phase */
-	P2P_STATE_TX_PROVISION_DIS_REQ = 6,	/*In P2P provisioning discovery */
-	P2P_STATE_RX_PROVISION_DIS_RSP = 7,
-	P2P_STATE_RX_PROVISION_DIS_REQ = 8,
-	P2P_STATE_GONEGO_ING = 9,		/*Doing the group owner negoitation handshake */
-	P2P_STATE_GONEGO_OK = 10,		/*finish the group negoitation handshake with success */
-	P2P_STATE_GONEGO_FAIL = 11,		/*finish the group negoitation handshake with failure */
-	P2P_STATE_RECV_INVITE_REQ_MATCH = 12,	/*receiving the P2P Inviation request and match with the profile. */
-	P2P_STATE_PROVISIONING_ING = 13,	/*Doing the P2P WPS */
-	P2P_STATE_PROVISIONING_DONE = 14,	/*Finish the P2P WPS */
-	P2P_STATE_TX_INVITE_REQ = 15,		/*Transmit the P2P Invitation request */
-	P2P_STATE_RX_INVITE_RESP_OK = 16,	/*Receiving the P2P Invitation response */
-	P2P_STATE_RECV_INVITE_REQ_DISMATCH = 17,/*receiving the P2P Inviation request and dismatch with the profile. */
-	P2P_STATE_RECV_INVITE_REQ_GO = 18,	/*receiving the P2P Inviation request and this wifi is GO. */
-	P2P_STATE_RECV_INVITE_REQ_JOIN = 19,	/*receiving the P2P Inviation request to join an existing P2P Group. */
-	P2P_STATE_RX_INVITE_RESP_FAIL = 20,	/*receiving the P2P Inviation response with failure */
-	P2P_STATE_RX_INFOR_NOREADY = 21,	/*receiving p2p negotiation response with information is not available */
-	P2P_STATE_TX_INFOR_NOREADY = 22,	/*sending p2p negotiation response with information is not available */
-};
-
-enum P2P_WPSINFO {
-	P2P_NO_WPSINFO				= 0,
-	P2P_GOT_WPSINFO_PEER_DISPLAY_PIN	= 1,
-	P2P_GOT_WPSINFO_SELF_DISPLAY_PIN	= 2,
-	P2P_GOT_WPSINFO_PBC			= 3,
-};
-
-#define	P2P_PRIVATE_IOCTL_SET_LEN		64
-
-enum P2P_PROTO_WK_ID {
-	P2P_FIND_PHASE_WK = 0,
-	P2P_RESTORE_STATE_WK = 1,
-	P2P_PRE_TX_PROVDISC_PROCESS_WK = 2,
-	P2P_PRE_TX_NEGOREQ_PROCESS_WK = 3,
-	P2P_PRE_TX_INVITEREQ_PROCESS_WK = 4,
-	P2P_AP_P2P_CH_SWITCH_PROCESS_WK = 5,
-	P2P_RO_CH_WK = 6,
-};
-
-#ifdef CONFIG_8723AU_P2P
-enum P2P_PS_STATE {
-	P2P_PS_DISABLE = 0,
-	P2P_PS_ENABLE = 1,
-	P2P_PS_SCAN = 2,
-	P2P_PS_SCAN_DONE = 3,
-	P2P_PS_ALLSTASLEEP = 4, /*  for P2P GO */
-};
-
-enum P2P_PS_MODE {
-	P2P_PS_NONE = 0,
-	P2P_PS_CTWINDOW = 1,
-	P2P_PS_NOA	 = 2,
-	P2P_PS_MIX = 3, /*  CTWindow and NoA */
-};
-#endif /*  CONFIG_8723AU_P2P */
-
-/*	=====================WFD Section===================== */
-/*	For Wi-Fi Display */
-#define	WFD_ATTR_DEVICE_INFO			0x00
-#define	WFD_ATTR_ASSOC_BSSID			0x01
-#define	WFD_ATTR_COUPLED_SINK_INFO	0x06
-#define	WFD_ATTR_LOCAL_IP_ADDR		0x08
-#define	WFD_ATTR_SESSION_INFO		0x09
-#define	WFD_ATTR_ALTER_MAC			0x0a
-
-/*	For WFD Device Information Attribute */
-#define	WFD_DEVINFO_SOURCE					0x0000
-#define	WFD_DEVINFO_PSINK					0x0001
-#define	WFD_DEVINFO_SSINK					0x0002
-#define	WFD_DEVINFO_DUAL					0x0003
-
-#define	WFD_DEVINFO_SESSION_AVAIL			0x0010
-#define	WFD_DEVINFO_WSD						0x0040
-#define	WFD_DEVINFO_PC_TDLS					0x0080
-#define	WFD_DEVINFO_HDCP_SUPPORT			0x0100
-
 #endif /*  _WIFI_H_ */
diff --git a/drivers/staging/rtl8723au/include/xmit_osdep.h b/drivers/staging/rtl8723au/include/xmit_osdep.h
index 0eca53ece75d..2be04c48656c 100644
--- a/drivers/staging/rtl8723au/include/xmit_osdep.h
+++ b/drivers/staging/rtl8723au/include/xmit_osdep.h
@@ -18,24 +18,9 @@
 #include <osdep_service.h>
 #include <drv_types.h>
 
-struct pkt_file {
-	struct sk_buff *pkt;
-	__kernel_size_t pkt_len; /* the remainder length of the open_file */
-	unsigned char *cur_buffer;
-	u8 *buf_start;
-	u8 *cur_addr;
-	__kernel_size_t buf_len;
-};
-
 
 #define NR_XMITFRAME	256
 
-struct xmit_priv;
-struct pkt_attrib;
-struct sta_xmit_priv;
-struct xmit_frame;
-struct xmit_buf;
-
 int rtw_xmit23a_entry23a(struct sk_buff *pkt, struct net_device *pnetdev);
 
 void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter);
@@ -44,10 +29,6 @@ int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter,
 			       struct xmit_buf *pxmitbuf, u32 alloc_sz);
 void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter,
 			       struct xmit_buf *pxmitbuf);
-uint rtw_remainder_len23a(struct pkt_file *pfile);
-void _rtw_open_pktfile23a(struct sk_buff *pkt, struct pkt_file *pfile);
-uint _rtw_pktfile_read23a(struct pkt_file *pfile, u8 *rmem, uint rlen);
-int rtw_endofpktfile23a(struct pkt_file *pfile);
 
 void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt);
 void rtw_os_xmit_complete23a(struct rtw_adapter *padapter,
diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
index 50840b9a11fa..5dbe3f43ab0e 100644
--- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
@@ -263,7 +263,6 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
 	size_t len, bssinf_len = 0;
 	struct ieee80211_hdr *pwlanhdr;
 	unsigned short *fctrl;
-	u8 bc_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
 	struct wireless_dev *wdev = padapter->rtw_wdev;
 	struct wiphy *wiphy = wdev->wiphy;
@@ -289,7 +288,6 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
 
 	notify_channel = ieee80211_get_channel(wiphy, freq);
 
-	/* rtw_get_timestampe_from_ie23a() */
 	notify_timestamp = jiffies_to_msecs(jiffies) * 1000;	/* uSec */
 
 	notify_interval =
@@ -321,7 +319,7 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
 	SetSeqNum(pwlanhdr, 0);
 
 	if (pnetwork->network.reserved == 1) {	/*  WIFI_BEACON */
-		memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+		eth_broadcast_addr(pwlanhdr->addr1);
 		SetFrameSubType(pbuf, WIFI_BEACON);
 	} else {
 		memcpy(pwlanhdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN);
@@ -357,9 +355,6 @@ void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wlan_network *cur_network = &pmlmepriv->cur_network;
 	struct wireless_dev *pwdev = padapter->rtw_wdev;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif
 
 	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
 
@@ -370,18 +365,7 @@ void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 		return;
 
-#ifdef CONFIG_8723AU_P2P
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-		DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state =%d\n",
-			  __func__, rtw_p2p_role(pwdinfo),
-			  rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
-	}
-#endif /* CONFIG_8723AU_P2P */
-
-	if (rtw_to_roaming(padapter) > 0) {
+	if (padapter->mlmepriv.to_roaming > 0) {
 		struct wiphy *wiphy = pwdev->wiphy;
 		struct ieee80211_channel *notify_channel;
 		u32 freq;
@@ -429,9 +413,6 @@ void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
 {
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wireless_dev *pwdev = padapter->rtw_wdev;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif
 
 	DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
 
@@ -442,21 +423,6 @@ void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 		return;
 
-#ifdef CONFIG_8723AU_P2P
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		del_timer_sync(&pwdinfo->find_phase_timer);
-		del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-		del_timer_sync(&pwdinfo->pre_tx_scan_timer);
-
-		rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-
-		DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state =%d\n",
-			  __func__, rtw_p2p_role(pwdinfo),
-			  rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
-	}
-#endif /* CONFIG_8723AU_P2P */
-
 	if (!padapter->mlmepriv.not_indic_disco) {
 		if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
 			cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
@@ -921,11 +887,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev,
 	struct rtw_adapter *padapter = netdev_priv(dev);
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif /* CONFIG_8723AU_P2P */
-
-
 
 	DBG_8723A("%s\n", __func__);
 
@@ -1080,15 +1041,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev,
 					rtw_set_key23a(padapter,
 						    &padapter->securitypriv,
 						    param->u.crypt.idx, 1);
-#ifdef CONFIG_8723AU_P2P
-					if (rtw_p2p_chk_state
-					    (pwdinfo,
-					     P2P_STATE_PROVISIONING_ING)) {
-						rtw_p2p_set_state(pwdinfo,
-								  P2P_STATE_PROVISIONING_DONE);
-					}
-#endif /* CONFIG_8723AU_P2P */
-
 				}
 			}
 
@@ -1147,7 +1099,7 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
 		return -1;
 
 	param->cmd = IEEE_CMD_SET_ENCRYPTION;
-	memset(param->sta_addr, 0xff, ETH_ALEN);
+	eth_broadcast_addr(param->sta_addr);
 
 	switch (params->cipher) {
 	case IW_AUTH_CIPHER_NONE:
@@ -1298,10 +1250,8 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
 		ret = -ENOENT;
 		goto exit;
 	}
-#ifdef CONFIG_DEBUG_CFG80211
 	DBG_8723A(FUNC_NDEV_FMT " mac =" MAC_FMT "\n", FUNC_NDEV_ARG(ndev),
 		  MAC_ARG(mac));
-#endif
 
 	/* for infra./P2PClient mode */
 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
@@ -1352,9 +1302,6 @@ static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
 	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-#endif
 	int ret = 0;
 	u8 change = false;
 
@@ -1386,34 +1333,10 @@ static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
 		networkType = Ndis802_11Infrastructure;
-#ifdef CONFIG_8723AU_P2P
-		if (change && rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
-			del_timer_sync(&pwdinfo->find_phase_timer);
-			del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-			del_timer_sync(&pwdinfo->pre_tx_scan_timer);
-
-			/* it means remove GO and change mode from AP(GO)
-			   to station(P2P DEVICE) */
-			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
-			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-
-			DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state ="
-				  "%d\n", __func__, rtw_p2p_role(pwdinfo),
-				  rtw_p2p_state(pwdinfo),
-				  rtw_p2p_pre_state(pwdinfo));
-		}
-#endif /* CONFIG_8723AU_P2P */
 		break;
 	case NL80211_IFTYPE_P2P_GO:
 	case NL80211_IFTYPE_AP:
 		networkType = Ndis802_11APMode;
-#ifdef CONFIG_8723AU_P2P
-		if (change && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-			/* it means P2P Group created, we will be GO
-			   and change mode from  P2P DEVICE to AP(GO) */
-			rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-		}
-#endif /* CONFIG_8723AU_P2P */
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1438,9 +1361,8 @@ void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
 {
 	spin_lock_bh(&pwdev_priv->scan_req_lock);
 	if (pwdev_priv->scan_request != NULL) {
-#ifdef CONFIG_DEBUG_CFG80211
 		DBG_8723A("%s with scan req\n", __func__);
-#endif
+
 		if (pwdev_priv->scan_request->wiphy !=
 		    pwdev_priv->rtw_wdev->wiphy)
 			DBG_8723A("error wiphy compare\n");
@@ -1449,9 +1371,7 @@ void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
 
 		pwdev_priv->scan_request = NULL;
 	} else {
-#ifdef CONFIG_DEBUG_CFG80211
 		DBG_8723A("%s without scan req\n", __func__);
-#endif
 	}
 	spin_unlock_bh(&pwdev_priv->scan_req_lock);
 }
@@ -1463,10 +1383,6 @@ void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
 	struct rtw_queue *queue = &pmlmepriv->scanned_queue;
 	struct wlan_network *pnetwork;
 
-#ifdef CONFIG_DEBUG_CFG80211
-	DBG_8723A("%s\n", __func__);
-#endif
-
 	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
 
 	phead = get_list_head(queue);
@@ -1495,23 +1411,15 @@ static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
 	int ret = 0;
 	uint wps_ielen = 0;
 	u8 *wps_ie;
-#ifdef CONFIG_8723AU_P2P
-	u32 p2p_ielen = 0;
-	u8 *p2p_ie;
-	u32 wfd_ielen = 0;
-#endif
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-#ifdef CONFIG_DEBUG_CFG80211
 	DBG_8723A("%s, ielen =%d\n", __func__, len);
-#endif
 
 	if (len > 0) {
 		wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
 		if (wps_ie) {
-#ifdef CONFIG_DEBUG_CFG80211
 			DBG_8723A("probe_req_wps_ielen =%d\n", wps_ielen);
-#endif
+
 			if (pmlmepriv->wps_probe_req_ie) {
 				pmlmepriv->wps_probe_req_ie_len = 0;
 				kfree(pmlmepriv->wps_probe_req_ie);
@@ -1528,60 +1436,6 @@ static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
 			memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);
 			pmlmepriv->wps_probe_req_ie_len = wps_ielen;
 		}
-#ifdef CONFIG_8723AU_P2P
-		p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
-		if (p2p_ie) {
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("probe_req_p2p_ielen =%d\n", p2p_ielen);
-#endif
-
-			if (pmlmepriv->p2p_probe_req_ie) {
-				pmlmepriv->p2p_probe_req_ie_len = 0;
-				kfree(pmlmepriv->p2p_probe_req_ie);
-				pmlmepriv->p2p_probe_req_ie = NULL;
-			}
-
-			pmlmepriv->p2p_probe_req_ie =
-				kmalloc(p2p_ielen, GFP_KERNEL);
-			if (pmlmepriv->p2p_probe_req_ie == NULL) {
-				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-					  __func__, __LINE__);
-				return -EINVAL;
-
-			}
-			memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);
-			pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;
-		}
-#endif /* CONFIG_8723AU_P2P */
-
-		/* buf += p2p_ielen; */
-		/* len -= p2p_ielen; */
-
-#ifdef CONFIG_8723AU_P2P
-		if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("probe_req_wfd_ielen =%d\n", wfd_ielen);
-#endif
-
-			if (pmlmepriv->wfd_probe_req_ie) {
-				pmlmepriv->wfd_probe_req_ie_len = 0;
-				kfree(pmlmepriv->wfd_probe_req_ie);
-				pmlmepriv->wfd_probe_req_ie = NULL;
-			}
-
-			pmlmepriv->wfd_probe_req_ie =
-				kmalloc(wfd_ielen, GFP_KERNEL);
-			if (pmlmepriv->wfd_probe_req_ie == NULL) {
-				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-					  __func__, __LINE__);
-				return -EINVAL;
-
-			}
-			rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_req_ie,
-				       &pmlmepriv->wfd_probe_req_ie_len);
-		}
-#endif /* CONFIG_8723AU_P2P */
-
 	}
 
 	return ret;
@@ -1599,25 +1453,16 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy,
 	struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
 	struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
 	struct cfg80211_ssid *ssids = request->ssids;
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	int social_channel = 0;
-#endif /* CONFIG_8723AU_P2P */
 	bool need_indicate_scan_done = false;
 
-#ifdef CONFIG_DEBUG_CFG80211
 	DBG_8723A(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));
-#endif
 
 	spin_lock_bh(&pwdev_priv->scan_req_lock);
 	pwdev_priv->scan_request = request;
 	spin_unlock_bh(&pwdev_priv->scan_req_lock);
 
 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
-
-#ifdef CONFIG_DEBUG_CFG80211
 		DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
-#endif
 		/* need_indicate_scan_done = true; */
 		/* goto check_need_indicate_scan_done; */
 	}
@@ -1626,29 +1471,6 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy,
 		need_indicate_scan_done = true;
 		goto check_need_indicate_scan_done;
 	}
-#ifdef CONFIG_8723AU_P2P
-	if (!memcmp(ssids->ssid, "DIRECT-", 7) &&
-	    rtw_get_p2p_ie23a((u8 *) request->ie, request->ie_len, NULL, NULL)) {
-		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-			rtw_p2p_enable23a(padapter, P2P_ROLE_DEVICE);
-			wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = true;
-		} else {
-			rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
-				  rtw_p2p_role(pwdinfo),
-				  rtw_p2p_state(pwdinfo));
-#endif
-		}
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
-
-		if (request->n_channels == 3 &&
-		    request->channels[0]->hw_value == 1 &&
-		    request->channels[1]->hw_value == 6 &&
-		    request->channels[2]->hw_value == 11)
-			social_channel = 1;
-	}
-#endif /* CONFIG_8723AU_P2P */
 
 	if (request->ie && request->ie_len > 0) {
 		rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
@@ -1674,28 +1496,12 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy,
 		need_indicate_scan_done = true;
 		goto check_need_indicate_scan_done;
 	}
-#ifdef CONFIG_8723AU_P2P
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
-	    !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
-		rtw_free_network_queue23a(padapter, true);
-
-		if (social_channel == 0)
-			rtw_p2p_findphase_ex_set(pwdinfo,
-						 P2P_FINDPHASE_EX_NONE);
-		else
-			rtw_p2p_findphase_ex_set(pwdinfo,
-						 P2P_FINDPHASE_EX_SOCIAL_LAST);
-	}
-#endif /* CONFIG_8723AU_P2P */
 
 	memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
 	/* parsing request ssids, n_ssids */
 	for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
-#ifdef CONFIG_DEBUG_CFG80211
 		DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
 			  ssids[i].ssid_len);
-#endif
 		memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
 		ssid[i].ssid_len = ssids[i].ssid_len;
 	}
@@ -1707,11 +1513,9 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy,
 	if (request->n_channels == 1) {
 		for (i = 0; i < request->n_channels &&
 		     i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
-#ifdef CONFIG_DEBUG_CFG80211
 			DBG_8723A(FUNC_ADPT_FMT CHAN_FMT "\n",
 				  FUNC_ADPT_ARG(padapter),
 				  CHAN_ARG(request->channels[i]));
-#endif
 			ch[i].hw_value = request->channels[i]->hw_value;
 			ch[i].flags = request->channels[i]->flags;
 		}
@@ -1877,13 +1681,10 @@ static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
 static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
 				   size_t ielen)
 {
-	u8 *buf = NULL, *pos = NULL;
+	u8 *buf = NULL;
 	int group_cipher = 0, pairwise_cipher = 0;
 	int ret = 0;
-	int wpa_ielen = 0;
-	int wpa2_ielen = 0;
-	u8 *pwpa, *pwpa2;
-	u8 null_addr[] = { 0, 0, 0, 0, 0, 0 };
+	const u8 *pwpa, *pwpa2;
 	int i;
 
 	if (!pie || !ielen) {
@@ -1910,7 +1711,6 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
 			  buf[i], buf[i + 1],
 			  buf[i + 2], buf[i + 3], buf[i + 4],
 			  buf[i + 5], buf[i + 6], buf[i + 7]);
-	pos = buf;
 	if (ielen < RSN_HEADER_LEN) {
 		RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
 			 ("Ie len too short %d\n", (int)ielen));
@@ -1918,33 +1718,35 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
 		goto exit;
 	}
 
-	pwpa = rtw_get_wpa_ie23a(buf, &wpa_ielen, ielen);
-	if (pwpa && wpa_ielen > 0) {
-		if (rtw_parse_wpa_ie23a(pwpa, wpa_ielen + 2, &group_cipher,
-				     &pairwise_cipher, NULL) == _SUCCESS) {
+	pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+				       WLAN_OUI_TYPE_MICROSOFT_WPA,
+				       buf, ielen);
+	if (pwpa && pwpa[1] > 0) {
+		if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher,
+					&pairwise_cipher, NULL) == _SUCCESS) {
 			padapter->securitypriv.dot11AuthAlgrthm =
 				dot11AuthAlgrthm_8021X;
 			padapter->securitypriv.ndisauthtype =
 				Ndis802_11AuthModeWPAPSK;
-			memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0],
-			       wpa_ielen + 2);
+			memcpy(padapter->securitypriv.supplicant_ie, pwpa,
+			       pwpa[1] + 2);
 
-			DBG_8723A("got wpa_ie, wpa_ielen:%u\n", wpa_ielen);
+			DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]);
 		}
 	}
 
-	pwpa2 = rtw_get_wpa2_ie23a(buf, &wpa2_ielen, ielen);
-	if (pwpa2 && wpa2_ielen > 0) {
-		if (rtw_parse_wpa2_ie23a (pwpa2, wpa2_ielen + 2, &group_cipher,
-				       &pairwise_cipher, NULL) == _SUCCESS) {
+	pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, buf, ielen);
+	if (pwpa2 && pwpa2[1] > 0) {
+		if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher,
+					  &pairwise_cipher, NULL) == _SUCCESS) {
 			padapter->securitypriv.dot11AuthAlgrthm =
 				dot11AuthAlgrthm_8021X;
 			padapter->securitypriv.ndisauthtype =
 				Ndis802_11AuthModeWPA2PSK;
-			memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0],
-			       wpa2_ielen + 2);
+			memcpy(padapter->securitypriv.supplicant_ie, pwpa2,
+			       pwpa2[1] + 2);
 
-			DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen);
+			DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]);
 		}
 	}
 
@@ -2029,75 +1831,13 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
 		}
 	}
 
-#ifdef CONFIG_8723AU_P2P
-	{			/* check p2p_ie for assoc req; */
-		uint p2p_ielen = 0;
-		u8 *p2p_ie;
-		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-		p2p_ie = rtw_get_p2p_ie23a(buf, ielen, NULL, &p2p_ielen);
-		if (p2p_ie) {
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("%s p2p_assoc_req_ielen =%d\n", __func__,
-				  p2p_ielen);
-#endif
-
-			if (pmlmepriv->p2p_assoc_req_ie) {
-				pmlmepriv->p2p_assoc_req_ie_len = 0;
-				kfree(pmlmepriv->p2p_assoc_req_ie);
-				pmlmepriv->p2p_assoc_req_ie = NULL;
-			}
-
-			pmlmepriv->p2p_assoc_req_ie =
-				kmalloc(p2p_ielen, GFP_KERNEL);
-			if (pmlmepriv->p2p_assoc_req_ie == NULL) {
-				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-					  __func__, __LINE__);
-				goto exit;
-			}
-			memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);
-			pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;
-		}
-	}
-#endif /* CONFIG_8723AU_P2P */
-
-#ifdef CONFIG_8723AU_P2P
-	{			/* check wfd_ie for assoc req; */
-		uint wfd_ielen = 0;
-		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-		if (rtw_get_wfd_ie(buf, ielen, NULL, &wfd_ielen)) {
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("%s wfd_assoc_req_ielen =%d\n", __func__,
-				  wfd_ielen);
-#endif
-
-			if (pmlmepriv->wfd_assoc_req_ie) {
-				pmlmepriv->wfd_assoc_req_ie_len = 0;
-				kfree(pmlmepriv->wfd_assoc_req_ie);
-				pmlmepriv->wfd_assoc_req_ie = NULL;
-			}
-
-			pmlmepriv->wfd_assoc_req_ie =
-				kmalloc(wfd_ielen, GFP_KERNEL);
-			if (pmlmepriv->wfd_assoc_req_ie == NULL) {
-				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-					  __func__, __LINE__);
-				goto exit;
-			}
-			rtw_get_wfd_ie(buf, ielen, pmlmepriv->wfd_assoc_req_ie,
-				       &pmlmepriv->wfd_assoc_req_ie_len);
-		}
-	}
-#endif /* CONFIG_8723AU_P2P */
-
 	/* TKIP and AES disallow multicast packets until installing group key */
 	if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ ||
 	    padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ ||
 	    padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
 		/* WPS open need to enable multicast */
 		/* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
-		rtw_hal_set_hwreg23a(padapter, HW_VAR_OFF_RCR_AM, null_addr);
+		rtl8723a_off_rcr_am(padapter);
 
 	RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
 		 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
@@ -2513,8 +2253,7 @@ static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
 		if (!memcmp(psecuritypriv->PMKIDList[index].Bssid,
 			    pmksa->bssid, ETH_ALEN)) {
 			/* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
-			memset(psecuritypriv->PMKIDList[index].Bssid, 0x00,
-			       ETH_ALEN);
+			eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid);
 			memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
 			       WLAN_PMKID_LEN);
 			psecuritypriv->PMKIDList[index].bUsed = false;
@@ -2739,9 +2478,6 @@ static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
 		struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 		u32 len = skb->len;
 		u8 category, action;
-#ifdef CONFIG_8723AU_P2P
-		int type = -1;
-#endif
 
 		if (rtw_action_frame_parse23a(skb->data, len, &category,
 					   &action) == false) {
@@ -2753,19 +2489,12 @@ static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
 
 		DBG_8723A("RTW_Tx:da =" MAC_FMT " via " FUNC_NDEV_FMT "\n",
 			  MAC_ARG(dot11_hdr->addr1), FUNC_NDEV_ARG(ndev));
-#ifdef CONFIG_8723AU_P2P
-		type = rtw_p2p_check_frames(padapter, skb->data, len, true);
-		if (type >= 0)
-			goto dump;
-#endif
 		if (category == WLAN_CATEGORY_PUBLIC)
 			DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
 		else
 			DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category,
 				  action);
-#ifdef CONFIG_8723AU_P2P
-dump:
-#endif
+
 		/* starting alloc mgmt frame to dump it */
 		pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
 		if (pmgntframe == NULL)
@@ -2781,16 +2510,6 @@ dump:
 		pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 
 		memcpy(pframe, skb->data, len);
-#ifdef CONFIG_8723AU_P2P
-		if (type >= 0) {
-			struct wifi_display_info *pwfd_info;
-
-			pwfd_info = padapter->wdinfo.wfd_info;
-
-			if (pwfd_info->wfd_enable)
-				rtw_append_wfd_ie(padapter, pframe, &len);
-		}
-#endif /*  CONFIG_8723AU_P2P */
 		pattrib->pktlen = len;
 
 		/* update seq number */
@@ -2976,10 +2695,6 @@ static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
 	int ret = 0;
 	u8 *pbuf = NULL;
 	uint len, wps_ielen = 0;
-#ifdef CONFIG_8723AU_P2P
-	uint p2p_ielen = 0;
-	u8 got_p2p_ie = false;
-#endif
 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 	/* struct sta_priv *pstapriv = &padapter->stapriv; */
 
@@ -3007,55 +2722,14 @@ static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
 	     &wps_ielen))
 		DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
 
-#ifdef CONFIG_8723AU_P2P
-	/* check p2p ie if inclued */
-	if (rtw_get_p2p_ie23a
-	    (pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL,
-	     &p2p_ielen)) {
-		DBG_8723A("got p2p_ie, len =%d\n", p2p_ielen);
-		got_p2p_ie = true;
-	}
-#endif
-
 	/* pbss_network->IEs will not include p2p_ie, wfd ie */
-	rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_,
-			  P2P_OUI23A, 4);
-	rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_,
-			  WFD_OUI23A, 4);
+	rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_,
+			     WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4);
+	rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_,
+			     WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4);
 
 	if (rtw_check_beacon_data23a(adapter, pbuf, len) == _SUCCESS) {
-#ifdef CONFIG_8723AU_P2P
-		/* check p2p if enable */
-		if (got_p2p_ie == true) {
-			struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
-			struct wifidirect_info *pwdinfo = &adapter->wdinfo;
-
-			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-				DBG_8723A("Enable P2P function for the first "
-					  "time\n");
-				rtw_p2p_enable23a(adapter, P2P_ROLE_GO);
-				wdev_to_priv(adapter->rtw_wdev)->p2p_enabled =
-					true;
-			} else {
-				del_timer_sync(&pwdinfo->find_phase_timer);
-				del_timer_sync(&pwdinfo->
-					       restore_p2p_state_timer);
-				del_timer_sync(&pwdinfo->pre_tx_scan_timer);
-
-				DBG_8723A("enter GO Mode, p2p_ielen =%d\n",
-					  p2p_ielen);
-
-				rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
-				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
-				pwdinfo->intent = 15;
-			}
-
-			pwdinfo->operating_channel = pmlmeext->cur_channel;
-		}
-#endif /* CONFIG_8723AU_P2P */
-
 		ret = 0;
-
 	} else {
 		ret = -EINVAL;
 	}
@@ -3252,9 +2926,6 @@ static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
 void rtw_cfg80211_rx_action_p2p(struct rtw_adapter *padapter, u8 *pmgmt_frame,
 				uint frame_len)
 {
-#ifdef CONFIG_8723AU_P2P
-	int type;
-#endif
 	s32 freq;
 	int channel;
 	u8 category, action;
@@ -3262,17 +2933,9 @@ void rtw_cfg80211_rx_action_p2p(struct rtw_adapter *padapter, u8 *pmgmt_frame,
 	channel = rtw_get_oper_ch23a(padapter);
 
 	DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
-#ifdef CONFIG_8723AU_P2P
-	type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, false);
-	if (type >= 0)
-		goto indicate;
-#endif
 	rtw_action_frame_parse23a(pmgmt_frame, frame_len, &category, &action);
 	DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category, action);
 
-#ifdef CONFIG_8723AU_P2P
-indicate:
-#endif
 	if (channel <= RTW_CH_MAX_2G_CHANNEL)
 		freq = ieee80211_channel_to_frequency(channel,
 						      IEEE80211_BAND_2GHZ);
@@ -3287,9 +2950,6 @@ indicate:
 void rtw_cfg80211_rx_p2p_action_public(struct rtw_adapter *padapter,
 				       u8 *pmgmt_frame, uint frame_len)
 {
-#ifdef CONFIG_8723AU_P2P
-	int type;
-#endif
 	s32 freq;
 	int channel;
 	u8 category, action;
@@ -3297,23 +2957,9 @@ void rtw_cfg80211_rx_p2p_action_public(struct rtw_adapter *padapter,
 	channel = rtw_get_oper_ch23a(padapter);
 
 	DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
-#ifdef CONFIG_8723AU_P2P
-	type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, false);
-	if (type >= 0) {
-		switch (type) {
-		case P2P_GO_NEGO_CONF:
-		case P2P_PROVISION_DISC_RESP:
-			rtw_clear_scan_deny(padapter);
-		}
-		goto indicate;
-	}
-#endif
 	rtw_action_frame_parse23a(pmgmt_frame, frame_len, &category, &action);
 	DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category, action);
 
-#ifdef CONFIG_8723AU_P2P
-indicate:
-#endif
 	if (channel <= RTW_CH_MAX_2G_CHANNEL)
 		freq = ieee80211_channel_to_frequency(channel,
 						      IEEE80211_BAND_2GHZ);
@@ -3353,350 +2999,6 @@ void rtw_cfg80211_rx_action(struct rtw_adapter *adapter, u8 *frame,
 	rtw_cfg80211_rx_mgmt(adapter, freq, 0, frame, frame_len, GFP_ATOMIC);
 }
 
-#ifdef CONFIG_8723AU_P2P
-void rtw_cfg80211_issue_p2p_provision_request23a(struct rtw_adapter *padapter,
-					      const u8 *buf, size_t len)
-{
-	u16 wps_devicepassword_id = 0x0000;
-	uint wps_devicepassword_id_len = 0;
-	u8 wpsie[255] = { 0x00 }, p2p_ie[255] = { 0x00 };
-	uint p2p_ielen = 0;
-	uint wpsielen = 0;
-	u32 devinfo_contentlen = 0;
-	u8 devinfo_content[64] = { 0x00 };
-	u16 capability = 0;
-	uint capability_len = 0;
-
-	unsigned char category = WLAN_CATEGORY_PUBLIC;
-	u8 action = P2P_PUB_ACTION_ACTION;
-	u8 dialogToken = 1;
-	u32 p2poui = cpu_to_be32(P2POUI);
-	u8 oui_subtype = P2P_PROVISION_DISC_REQ;
-	u32 p2pielen = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32 wfdielen = 0;
-#endif /* CONFIG_8723AU_P2P */
-
-	struct xmit_frame *pmgntframe;
-	struct pkt_attrib *pattrib;
-	unsigned char *pframe;
-	struct ieee80211_hdr *pwlanhdr, *hdr;
-	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	u8 *frame_body =
-	    (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
-	size_t frame_body_len = len - sizeof(struct ieee80211_hdr_3addr);
-
-	DBG_8723A("[%s] In\n", __func__);
-
-	hdr = (struct ieee80211_hdr *)buf;
-	/* prepare for building provision_request frame */
-	memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, hdr->addr1, ETH_ALEN);
-	memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, hdr->addr1, ETH_ALEN);
-
-	pwdinfo->tx_prov_disc_info.wps_config_method_request =
-	    WPS_CM_PUSH_BUTTON;
-
-	rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
-		       frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie,
-		       &wpsielen);
-	rtw_get_wps_attr_content23a(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID,
-				    (u8 *)&wps_devicepassword_id,
-				    &wps_devicepassword_id_len);
-	wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
-
-	switch (wps_devicepassword_id) {
-	case WPS_DPID_PIN:
-		pwdinfo->tx_prov_disc_info.wps_config_method_request =
-			WPS_CM_LABEL;
-		break;
-	case WPS_DPID_USER_SPEC:
-		pwdinfo->tx_prov_disc_info.wps_config_method_request =
-			WPS_CM_DISPLYA;
-		break;
-	case WPS_DPID_MACHINE_SPEC:
-		break;
-	case WPS_DPID_REKEY:
-		break;
-	case WPS_DPID_PBC:
-		pwdinfo->tx_prov_disc_info.wps_config_method_request =
-			WPS_CM_PUSH_BUTTON;
-		break;
-	case WPS_DPID_REGISTRAR_SPEC:
-		pwdinfo->tx_prov_disc_info.wps_config_method_request =
-			WPS_CM_KEYPAD;
-		break;
-	default:
-		break;
-	}
-
-	if (rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
-			   frame_body_len - _PUBLIC_ACTION_IE_OFFSET_,
-			   p2p_ie, &p2p_ielen)) {
-		rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
-					 P2P_ATTR_DEVICE_INFO, devinfo_content,
-					 &devinfo_contentlen);
-		rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY,
-					 (u8 *)&capability, &capability_len);
-	}
-
-	/* start to build provision_request frame */
-	memset(wpsie, 0, sizeof(wpsie));
-	memset(p2p_ie, 0, sizeof(p2p_ie));
-	p2p_ielen = 0;
-
-	pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
-	if (pmgntframe == NULL)
-		return;
-	/* update attribute */
-	pattrib = &pmgntframe->attrib;
-	update_mgntframe_attrib23a(padapter, pattrib);
-
-	memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-
-	pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
-	pwlanhdr = (struct ieee80211_hdr *)pframe;
-
-	pwlanhdr->frame_control = 0;
-
-	memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr,
-	       ETH_ALEN);
-	memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
-	memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr,
-	       ETH_ALEN);
-
-	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-	pmlmeext->mgnt_seq++;
-	SetFrameSubType(pframe, WIFI_ACTION);
-
-	pframe += sizeof(struct ieee80211_hdr_3addr);
-	pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
-				  &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
-	pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
-
-	/* build_prov_disc_request_p2p_ie23a */
-	/*      P2P OUI */
-	p2pielen = 0;
-	p2p_ie[p2pielen++] = 0x50;
-	p2p_ie[p2pielen++] = 0x6F;
-	p2p_ie[p2pielen++] = 0x9A;
-	p2p_ie[p2pielen++] = 0x09;	/*      WFA P2P v1.0 */
-
-	/*      Commented by Albert 20110301 */
-	/*      According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
-	/*      1. P2P Capability */
-	/*      2. Device Info */
-	/*      3. Group ID ( When joining an operating P2P Group ) */
-
-	/*      P2P Capability ATTR */
-	/*      Type: */
-	p2p_ie[p2pielen++] = P2P_ATTR_CAPABILITY;
-
-	/*      Length: */
-	put_unaligned_le16(0x0002, p2p_ie + p2pielen);
-	p2pielen += 2;
-
-	/*      Value: */
-	/*      Device Capability Bitmap, 1 byte */
-	/*      Group Capability Bitmap, 1 byte */
-	memcpy(p2p_ie + p2pielen, &capability, 2);
-	p2pielen += 2;
-
-	/*      Device Info ATTR */
-	/*      Type: */
-	p2p_ie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
-
-	/*      Length: */
-	put_unaligned_le16(devinfo_contentlen, p2p_ie + p2pielen);
-	p2pielen += 2;
-
-	/*      Value: */
-	memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);
-	p2pielen += devinfo_contentlen;
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
-			    (unsigned char *)p2p_ie, &p2p_ielen);
-	pattrib->pktlen += p2p_ielen;
-
-	wpsielen = 0;
-	/*      WPS OUI */
-	*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
-	wpsielen += 4;
-
-	/*      WPS version */
-	/*      Type: */
-	*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
-	wpsielen += 2;
-
-	/*      Length: */
-	*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
-	wpsielen += 2;
-
-	/*      Value: */
-	wpsie[wpsielen++] = WPS_VERSION_1;	/*      Version 1.0 */
-
-	/*      Config Method */
-	/*      Type: */
-	*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
-	wpsielen += 2;
-
-	/*      Length: */
-	*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
-	wpsielen += 2;
-
-	/*      Value: */
-	*(u16 *)(wpsie + wpsielen) =
-	    cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
-	wpsielen += 2;
-
-	pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
-			    (unsigned char *)wpsie, &pattrib->pktlen);
-
-#ifdef CONFIG_8723AU_P2P
-	wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
-	pframe += wfdielen;
-	pattrib->pktlen += wfdielen;
-#endif /* CONFIG_8723AU_P2P */
-
-	pattrib->last_txcmdsz = pattrib->pktlen;
-
-	/* dump_mgntframe23a(padapter, pmgntframe); */
-	if (dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe) != _SUCCESS)
-		DBG_8723A("%s, ack to\n", __func__);
-}
-
-static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy,
-					  struct wireless_dev *wdev,
-					  struct ieee80211_channel *channel,
-					  unsigned int duration, u64 *cookie)
-{
-	s32 err = 0;
-	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
-	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
-	    &padapter->cfg80211_wdinfo;
-	u8 remain_ch =
-		(u8) ieee80211_frequency_to_channel(channel->center_freq);
-	u8 ready_on_channel = false;
-
-	DBG_8723A(FUNC_ADPT_FMT " ch:%u duration:%d\n", FUNC_ADPT_ARG(padapter),
-		  remain_ch, duration);
-
-	if (pcfg80211_wdinfo->is_ro_ch == true) {
-		DBG_8723A("%s, cancel ro ch timer\n", __func__);
-
-		del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
-
-#ifdef CONFIG_8723AU_P2P
-		p2p_protocol_wk_hdl23a(padapter, P2P_RO_CH_WK);
-#endif
-	}
-
-	pcfg80211_wdinfo->is_ro_ch = true;
-
-	if (_FAIL == rtw_pwr_wakeup(padapter)) {
-		err = -EFAULT;
-		goto exit;
-	}
-
-	memcpy(&pcfg80211_wdinfo->remain_on_ch_channel, channel,
-	       sizeof(struct ieee80211_channel));
-	pcfg80211_wdinfo->remain_on_ch_cookie = *cookie;
-
-	rtw_scan_abort23a(padapter);
-	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		rtw_p2p_enable23a(padapter, P2P_ROLE_DEVICE);
-		wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = true;
-	} else {
-		rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
-#ifdef CONFIG_DEBUG_CFG80211
-		DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
-			  rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
-#endif
-	}
-
-	rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
-
-	if (duration < 400)
-		duration = duration * 3;	/* extend from exper. */
-
-	pcfg80211_wdinfo->restore_channel = pmlmeext->cur_channel;
-
-	if (rtw_ch_set_search_ch23a(pmlmeext->channel_set, remain_ch) >= 0) {
-		if (remain_ch != pmlmeext->cur_channel) {
-			ready_on_channel = true;
-		}
-	} else {
-		DBG_8723A("%s remain_ch:%u not in channel plan!!!!\n",
-			  __func__, remain_ch);
-	}
-
-	/* call this after other things have been done */
-	if (ready_on_channel == true) {
-		if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
-			pmlmeext->cur_channel = remain_ch;
-
-			set_channel_bwmode23a(padapter, remain_ch,
-					   HAL_PRIME_CHNL_OFFSET_DONT_CARE,
-					   HT_CHANNEL_WIDTH_20);
-		}
-	}
-	DBG_8723A("%s, set ro ch timer, duration =%d\n", __func__, duration);
-	mod_timer(&pcfg80211_wdinfo->remain_on_ch_timer,
-		  jiffies + msecs_to_jiffies(duration));
-
-	rtw_cfg80211_ready_on_channel(padapter, *cookie, channel, channel_type,
-				      duration, GFP_KERNEL);
-
-	pwdinfo->listen_channel = pmlmeext->cur_channel;
-
-exit:
-	if (err)
-		pcfg80211_wdinfo->is_ro_ch = false;
-
-	return err;
-}
-
-static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy,
-						 struct wireless_dev *wdev,
-						 u64 cookie)
-{
-	s32 err = 0;
-	struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
-	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
-	struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
-	    &padapter->cfg80211_wdinfo;
-
-	DBG_8723A(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));
-
-	if (pcfg80211_wdinfo->is_ro_ch == true) {
-		DBG_8723A("%s, cancel ro ch timer\n", __func__);
-		del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
-#ifdef CONFIG_8723AU_P2P
-		p2p_protocol_wk_hdl23a(padapter, P2P_RO_CH_WK);
-#endif
-	}
-
-	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
-#ifdef CONFIG_DEBUG_CFG80211
-	DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
-		  rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
-#endif
-	pcfg80211_wdinfo->is_ro_ch = false;
-
-	return err;
-}
-
-#endif /* CONFIG_8723AU_P2P */
-
 static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
 				 const u8 *buf, size_t len)
 {
@@ -3708,7 +3010,6 @@ static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
 	struct ieee80211_hdr *pwlanhdr;
 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-	/* struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo; */
 
 	if (_FAIL == rtw_pwr_wakeup(padapter)) {
 		ret = -EFAULT;
@@ -3753,39 +3054,21 @@ static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
 	pattrib->seqnum = pmlmeext->mgnt_seq;
 	pmlmeext->mgnt_seq++;
 
-#ifdef CONFIG_8723AU_P2P
-	{
-		struct wifi_display_info *pwfd_info;
-
-		pwfd_info = padapter->wdinfo.wfd_info;
-
-		if (true == pwfd_info->wfd_enable) {
-			rtw_append_wfd_ie(padapter, pframe, &pattrib->pktlen);
-		}
-	}
-#endif /*  CONFIG_8723AU_P2P */
-
 	pattrib->last_txcmdsz = pattrib->pktlen;
 
 	if (dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe) != _SUCCESS) {
 		ack = false;
 		ret = _FAIL;
 
-#ifdef CONFIG_DEBUG_CFG80211
 		DBG_8723A("%s, ack == _FAIL\n", __func__);
-#endif
 	} else {
-#ifdef CONFIG_DEBUG_CFG80211
 		DBG_8723A("%s, ack =%d, ok!\n", __func__, ack);
-#endif
 		ret = _SUCCESS;
 	}
 
 exit:
 
-#ifdef CONFIG_DEBUG_CFG80211
 	DBG_8723A("%s, ret =%d\n", __func__, ret);
-#endif
 
 	return ret;
 }
@@ -3824,10 +3107,8 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	/* cookie generation */
 	*cookie = (unsigned long)buf;
 
-#ifdef CONFIG_DEBUG_CFG80211
 	DBG_8723A(FUNC_ADPT_FMT " len =%zu, ch =%d"
 		  "\n", FUNC_ADPT_ARG(padapter), len, tx_ch);
-#endif /* CONFIG_DEBUG_CFG80211 */
 
 	/* indicate ack before issue frame to avoid racing with rsp frame */
 	rtw_cfg80211_mgmt_tx_status(padapter, *cookie, buf, len, ack,
@@ -3842,20 +3123,12 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 
 	DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
 		  MAC_ARG(hdr->addr1));
-#ifdef CONFIG_8723AU_P2P
-	type = rtw_p2p_check_frames(padapter, buf, len, true);
-	if (type >= 0)
-		goto dump;
-#endif
 	if (category == WLAN_CATEGORY_PUBLIC)
 		DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
 	else
 		DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
 			  category, action);
 
-#ifdef CONFIG_8723AU_P2P
-dump:
-#endif
 	do {
 		dump_cnt++;
 		tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
@@ -3893,12 +3166,6 @@ static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
 					     struct wireless_dev *wdev,
 					     u16 frame_type, bool reg)
 {
-
-#ifdef CONFIG_DEBUG_CFG80211
-	DBG_8723A(FUNC_ADPT_FMT " frame_type:%x, reg:%d\n",
-		  FUNC_ADPT_ARG(adapter), frame_type, reg);
-#endif
-
 	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
 		return;
 
@@ -3911,11 +3178,6 @@ static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf,
 	int ret = 0;
 	uint wps_ielen = 0;
 	u8 *wps_ie;
-#ifdef CONFIG_8723AU_P2P
-	u32 p2p_ielen = 0;
-	u32 wfd_ielen = 0;
-	u8 *p2p_ie;
-#endif
 #ifdef CONFIG_8723AU_AP_MODE
 	u8 wps_oui[8] = { 0x0, 0x50, 0xf2, 0x04 };
 #endif
@@ -3928,9 +3190,7 @@ static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf,
 	if (len > 0) {
 		wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
 		if (wps_ie) {
-#ifdef CONFIG_DEBUG_CFG80211
 			DBG_8723A("bcn_wps_ielen =%d\n", wps_ielen);
-#endif
 
 			if (pmlmepriv->wps_beacon_ie) {
 				pmlmepriv->wps_beacon_ie_len = 0;
@@ -3949,63 +3209,10 @@ static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf,
 			pmlmepriv->wps_beacon_ie_len = wps_ielen;
 
 #ifdef CONFIG_8723AU_AP_MODE
-			update_beacon23a(padapter, _VENDOR_SPECIFIC_IE_, wps_oui,
-				      true);
+			update_beacon23a(padapter, WLAN_EID_VENDOR_SPECIFIC,
+					 wps_oui, true);
 #endif
 		}
-#ifdef CONFIG_8723AU_P2P
-		p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
-		if (p2p_ie) {
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("bcn_p2p_ielen =%d\n", p2p_ielen);
-#endif
-
-			if (pmlmepriv->p2p_beacon_ie) {
-				pmlmepriv->p2p_beacon_ie_len = 0;
-				kfree(pmlmepriv->p2p_beacon_ie);
-				pmlmepriv->p2p_beacon_ie = NULL;
-			}
-
-			pmlmepriv->p2p_beacon_ie =
-				kmalloc(p2p_ielen, GFP_KERNEL);
-			if (pmlmepriv->p2p_beacon_ie == NULL) {
-				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-					  __func__, __LINE__);
-				return -EINVAL;
-			}
-
-			memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);
-			pmlmepriv->p2p_beacon_ie_len = p2p_ielen;
-		}
-#endif /* CONFIG_8723AU_P2P */
-
-		/* buf += p2p_ielen; */
-		/* len -= p2p_ielen; */
-
-#ifdef CONFIG_8723AU_P2P
-		if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("bcn_wfd_ielen =%d\n", wfd_ielen);
-#endif
-
-			if (pmlmepriv->wfd_beacon_ie) {
-				pmlmepriv->wfd_beacon_ie_len = 0;
-				kfree(pmlmepriv->wfd_beacon_ie);
-				pmlmepriv->wfd_beacon_ie = NULL;
-			}
-
-			pmlmepriv->wfd_beacon_ie =
-				kmalloc(wfd_ielen, GFP_KERNEL);
-			if (pmlmepriv->wfd_beacon_ie == NULL) {
-				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-					  __func__, __LINE__);
-				return -EINVAL;
-
-			}
-			rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_beacon_ie,
-				       &pmlmepriv->wfd_beacon_ie_len);
-		}
-#endif /* CONFIG_8723AU_P2P */
 
 		pmlmeext->bstart_bss = true;
 
@@ -4019,11 +3226,6 @@ static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net,
 {
 	struct rtw_adapter *padapter = netdev_priv(net);
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-#ifdef CONFIG_8723AU_P2P
-	u32 p2p_ielen = 0;
-	u8 *p2p_ie;
-	u32 wfd_ielen = 0;
-#endif
 	int ret = 0;
 	uint wps_ielen = 0;
 	u8 *wps_ie;
@@ -4067,104 +3269,6 @@ static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net,
 
 		}
 
-		/* buf += wps_ielen; */
-		/* len -= wps_ielen; */
-
-#ifdef CONFIG_8723AU_P2P
-		p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
-		if (p2p_ie) {
-			u8 is_GO = false;
-			u32 attr_contentlen = 0;
-			u16 cap_attr = 0;
-
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("probe_resp_p2p_ielen =%d\n", p2p_ielen);
-#endif
-
-			/* Check P2P Capability ATTR */
-			if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
-						     P2P_ATTR_CAPABILITY,
-						     (u8 *) &cap_attr,
-						     (uint *) &attr_contentlen)) {
-				u8 grp_cap = 0;
-				/* DBG_8723A( "[%s] Got P2P Capability Attr!!\n", __func__ ); */
-				cap_attr = le16_to_cpu(cap_attr);
-				grp_cap = (u8) ((cap_attr >> 8) & 0xff);
-
-				is_GO = (grp_cap & BIT(0)) ? true : false;
-
-				if (is_GO)
-					DBG_8723A
-					    ("Got P2P Capability Attr, grp_cap"
-					     "= 0x%x, is_GO\n", grp_cap);
-			}
-
-			if (is_GO == false) {
-				if (pmlmepriv->p2p_probe_resp_ie) {
-					pmlmepriv->p2p_probe_resp_ie_len = 0;
-					kfree(pmlmepriv->p2p_probe_resp_ie);
-					pmlmepriv->p2p_probe_resp_ie = NULL;
-				}
-
-				pmlmepriv->p2p_probe_resp_ie =
-				    kmalloc(p2p_ielen, GFP_KERNEL);
-				if (pmlmepriv->p2p_probe_resp_ie == NULL) {
-					DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-						  __func__, __LINE__);
-					return -EINVAL;
-				}
-				memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie,
-				       p2p_ielen);
-				pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;
-			} else {
-				if (pmlmepriv->p2p_go_probe_resp_ie) {
-					pmlmepriv->p2p_go_probe_resp_ie_len = 0;
-					kfree(pmlmepriv->p2p_go_probe_resp_ie);
-					pmlmepriv->p2p_go_probe_resp_ie = NULL;
-				}
-
-				pmlmepriv->p2p_go_probe_resp_ie =
-				    kmalloc(p2p_ielen, GFP_KERNEL);
-				if (pmlmepriv->p2p_go_probe_resp_ie == NULL) {
-					DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-						  __func__, __LINE__);
-					return -EINVAL;
-
-				}
-				memcpy(pmlmepriv->p2p_go_probe_resp_ie,
-				       p2p_ie, p2p_ielen);
-				pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;
-			}
-		}
-#endif /* CONFIG_8723AU_P2P */
-
-		/* buf += p2p_ielen; */
-		/* len -= p2p_ielen; */
-
-#ifdef CONFIG_8723AU_P2P
-		if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
-#ifdef CONFIG_DEBUG_CFG80211
-			DBG_8723A("probe_resp_wfd_ielen =%d\n", wfd_ielen);
-#endif
-
-			if (pmlmepriv->wfd_probe_resp_ie) {
-				pmlmepriv->wfd_probe_resp_ie_len = 0;
-				kfree(pmlmepriv->wfd_probe_resp_ie);
-				pmlmepriv->wfd_probe_resp_ie = NULL;
-			}
-
-			pmlmepriv->wfd_probe_resp_ie =
-			    kmalloc(wfd_ielen, GFP_KERNEL);
-			if (pmlmepriv->wfd_probe_resp_ie == NULL) {
-				DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
-					  __func__, __LINE__);
-				return -EINVAL;
-
-			}
-			rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_resp_ie,
-				       &pmlmepriv->wfd_probe_resp_ie_len);
-		}
-#endif /* CONFIG_8723AU_P2P */
 	}
 
 	return ret;
@@ -4205,19 +3309,10 @@ int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
 {
 	int ret = 0;
 	uint wps_ielen = 0;
-#ifdef CONFIG_8723AU_P2P
-	u32 p2p_ielen = 0;
-#endif
 
-#ifdef CONFIG_DEBUG_CFG80211
 	DBG_8723A("%s, ielen =%d\n", __func__, len);
-#endif
 
-	if ((rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen) && (wps_ielen > 0))
-#ifdef CONFIG_8723AU_P2P
-	    || (rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen) && (p2p_ielen > 0))
-#endif
-	    ) {
+	if (rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen) && (wps_ielen > 0)) {
 		if (net) {
 			switch (type) {
 			case 0x1:	/* BEACON */
@@ -4280,11 +3375,6 @@ static struct cfg80211_ops rtw_cfg80211_ops = {
 	.change_bss = cfg80211_rtw_change_bss,
 #endif /* CONFIG_8723AU_AP_MODE */
 
-#ifdef CONFIG_8723AU_P2P
-	.remain_on_channel = cfg80211_rtw_remain_on_channel,
-	.cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,
-#endif
-
 	.mgmt_tx = cfg80211_rtw_mgmt_tx,
 	.mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
 };
@@ -4348,7 +3438,7 @@ void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
 	struct wireless_dev *pwdev = padapter->rtw_wdev;
 	struct wiphy *wiphy = pwdev->wiphy;
 
-	rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	rf_type = rtl8723a_get_rf_type(padapter);
 
 	DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
 
@@ -4388,9 +3478,6 @@ static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
 #ifdef CONFIG_8723AU_AP_MODE
 	    BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
 #endif
-#if defined(CONFIG_8723AU_P2P)
-	    BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) |
-#endif
 	    0;
 
 #ifdef CONFIG_8723AU_AP_MODE
diff --git a/drivers/staging/rtl8723au/os_dep/mlme_linux.c b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
index b30d4d37556a..c0e79f56d2eb 100644
--- a/drivers/staging/rtl8723au/os_dep/mlme_linux.c
+++ b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
@@ -20,22 +20,6 @@
 #include <mlme_osdep.h>
 #include <rtw_ioctl_set.h>
 
-void rtw_os_indicate_connect23a(struct rtw_adapter *adapter)
-{
-	rtw_cfg80211_indicate_connect(adapter);
-
-	netif_carrier_on(adapter->pnetdev);
-
-	if (adapter->pid[2] != 0)
-		rtw_signal_process(adapter->pid[2], SIGALRM);
-}
-
-void rtw_os_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted)
-{
-	rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
-					aborted);
-}
-
 static struct rt_pmkid_list backupPMKIDList[NUM_PMKID_CACHE];
 
 void rtw_reset_securitypriv23a(struct rtw_adapter *adapter)
@@ -52,9 +36,6 @@ void rtw_reset_securitypriv23a(struct rtw_adapter *adapter)
 		 *  When the countermeasure is trigger, the driver have to
 		 *  disconnect with AP for 60 seconds.
 		 */
-		memset(&backupPMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) *
-		       NUM_PMKID_CACHE);
-
 		memcpy(&backupPMKIDList[0], &adapter->securitypriv.PMKIDList[0],
 		       sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
 		backupPMKIDIndex = adapter->securitypriv.PMKIDIndex;
@@ -99,89 +80,3 @@ void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter)
 
 	rtw_reset_securitypriv23a(adapter);
 }
-
-void rtw_report_sec_ie23a(struct rtw_adapter *adapter, u8 authmode, u8 *sec_ie)
-{
-	uint	len;
-	u8	*buff, *p, i;
-	union iwreq_data wrqu;
-
-	RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
-		 ("+rtw_report_sec_ie23a, authmode =%d\n", authmode));
-
-	buff = NULL;
-	if (authmode == _WPA_IE_ID_) {
-		RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
-			 ("rtw_report_sec_ie23a, authmode =%d\n", authmode));
-
-		buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL);
-		if (!buff)
-			return;
-		p = buff;
-
-		p += sprintf(p, "ASSOCINFO(ReqIEs =");
-
-		len = sec_ie[1]+2;
-		len =  (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
-
-		for (i = 0; i < len; i++)
-			p += sprintf(p, "%02x", sec_ie[i]);
-
-		p += sprintf(p, ")");
-
-		memset(&wrqu, 0, sizeof(wrqu));
-
-		wrqu.data.length = p-buff;
-
-		wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
-				   wrqu.data.length : IW_CUSTOM_MAX;
-
-		kfree(buff);
-	}
-}
-
-#ifdef CONFIG_8723AU_AP_MODE
-void rtw_indicate_sta_assoc_event23a(struct rtw_adapter *padapter,
-				  struct sta_info *psta)
-{
-	struct sta_priv *pstapriv = &padapter->stapriv;
-	union iwreq_data wrqu;
-
-	if (psta == NULL)
-		return;
-
-	if (psta->aid > NUM_STA)
-		return;
-
-	if (pstapriv->sta_aid[psta->aid - 1] != psta)
-		return;
-
-	wrqu.addr.sa_family = ARPHRD_ETHER;
-
-	memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
-
-	DBG_8723A("+rtw_indicate_sta_assoc_event23a\n");
-}
-
-void rtw_indicate_sta_disassoc_event23a(struct rtw_adapter *padapter,
-				     struct sta_info *psta)
-{
-	struct sta_priv *pstapriv = &padapter->stapriv;
-	union iwreq_data wrqu;
-
-	if (psta == NULL)
-		return;
-
-	if (psta->aid > NUM_STA)
-		return;
-
-	if (pstapriv->sta_aid[psta->aid - 1] != psta)
-		return;
-
-	wrqu.addr.sa_family = ARPHRD_ETHER;
-
-	memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
-
-	DBG_8723A("+rtw_indicate_sta_disassoc_event23a\n");
-}
-#endif
diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c
index 57eca7a45672..fd9de2a60bf7 100644
--- a/drivers/staging/rtl8723au/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c
@@ -20,7 +20,6 @@
 #include <recv_osdep.h>
 #include <hal_intf.h>
 #include <rtw_version.h>
-#include <ethernet.h>
 
 #include <usb_osintf.h>
 #include <linux/version.h>
@@ -66,10 +65,10 @@ static int rtw_acm_method;/*  0:By SW 1:By HW. */
 static int rtw_wmm_enable = 1;/*  default is set to enable the wmm. */
 static int rtw_uapsd_enable;
 
-int rtw_ht_enable23A = 1;
+static int rtw_ht_enable = 1;
 /* 0 :diable, bit(0): enable 2.4g, bit(1): enable 5g */
-int rtw_cbw40_enable23A = 3;
-int rtw_ampdu_enable23A = 1;/* for enable tx_ampdu */
+static int rtw_cbw40_enable = 3;
+static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
 /*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable
  * 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
  */
@@ -130,9 +129,9 @@ module_param(rtw_wmm_enable, int, 0644);
 module_param(rtw_vrtl_carrier_sense, int, 0644);
 module_param(rtw_vcs_type, int, 0644);
 module_param(rtw_busy_thresh, int, 0644);
-module_param(rtw_ht_enable23A, int, 0644);
-module_param(rtw_cbw40_enable23A, int, 0644);
-module_param(rtw_ampdu_enable23A, int, 0644);
+module_param(rtw_ht_enable, int, 0644);
+module_param(rtw_cbw40_enable, int, 0644);
+module_param(rtw_ampdu_enable, int, 0644);
 module_param(rtw_rx_stbc, int, 0644);
 module_param(rtw_ampdu_amsdu, int, 0644);
 
@@ -203,9 +202,9 @@ static uint loadparam(struct rtw_adapter *padapter,  struct net_device *pnetdev)
 	 /* UAPSD */
 	registry_par->wmm_enable = (u8)rtw_wmm_enable;
 	registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
-	registry_par->ht_enable = (u8)rtw_ht_enable23A;
-	registry_par->cbw40_enable = (u8)rtw_cbw40_enable23A;
-	registry_par->ampdu_enable = (u8)rtw_ampdu_enable23A;
+	registry_par->ht_enable = (u8)rtw_ht_enable;
+	registry_par->cbw40_enable = (u8)rtw_cbw40_enable;
+	registry_par->ampdu_enable = (u8)rtw_ampdu_enable;
 	registry_par->rx_stbc = (u8)rtw_rx_stbc;
 	registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
 	registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit;
@@ -456,9 +455,6 @@ static u8 rtw_init_default_value(struct rtw_adapter *padapter)
 	padapter->bWritePortCancel = false;
 	padapter->bRxRSSIDisplay = 0;
 	padapter->bNotifyChannelChange = 0;
-#ifdef CONFIG_8723AU_P2P
-	padapter->bShowGetP2PState = 1;
-#endif
 	return ret;
 }
 
@@ -521,17 +517,6 @@ u8 rtw_init_drv_sw23a(struct rtw_adapter *padapter)
 		goto exit;
 	}
 
-#ifdef CONFIG_8723AU_P2P
-	rtw_init_wifidirect_timers23a(padapter);
-	init_wifidirect_info23a(padapter, P2P_ROLE_DISABLE);
-	reset_global_wifidirect_info23a(padapter);
-	rtw_init_cfg80211_wifidirect_info(padapter);
-#ifdef CONFIG_8723AU_P2P
-	if (rtw_init_wifi_display_info(padapter) == _FAIL)
-		RT_TRACE(_module_os_intfs_c_, _drv_err_,
-			 ("\n Can't init init_wifi_display_info\n"));
-#endif
-#endif /* CONFIG_8723AU_P2P */
 
 	if (init_mlme_ext_priv23a(padapter) == _FAIL) {
 		RT_TRACE(_module_os_intfs_c_, _drv_err_,
@@ -600,10 +585,6 @@ void rtw_cancel_all_timer23a(struct rtw_adapter *padapter)
 
 	del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer);
 
-#ifdef CONFIG_8723AU_P2P
-	del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
-#endif /* CONFIG_8723AU_P2P */
-
 	del_timer_sync(&padapter->mlmepriv.set_scan_deny_timer);
 	rtw_clear_scan_deny(padapter);
 	RT_TRACE(_module_os_intfs_c_, _drv_info_,
@@ -616,26 +597,8 @@ void rtw_cancel_all_timer23a(struct rtw_adapter *padapter)
 
 u8 rtw_free_drv_sw23a(struct rtw_adapter *padapter)
 {
-#ifdef CONFIG_8723AU_P2P
-	struct wifidirect_info *pwdinfo;
-#endif
-
 	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("==>rtw_free_drv_sw23a"));
 
-	/* we can call rtw_p2p_enable23a here, but:
-	 *  1. rtw_p2p_enable23a may have IO operation
-	 *  2. rtw_p2p_enable23a is bundled with wext interface
-	 */
-#ifdef CONFIG_8723AU_P2P
-	pwdinfo = &padapter->wdinfo;
-	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
-		del_timer_sync(&pwdinfo->find_phase_timer);
-		del_timer_sync(&pwdinfo->restore_p2p_state_timer);
-		del_timer_sync(&pwdinfo->pre_tx_scan_timer);
-		rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
-	}
-#endif
-
 	free_mlme_ext_priv23a(&padapter->mlmeextpriv);
 
 	rtw_free_cmd_priv23a(&padapter->cmdpriv);
@@ -887,7 +850,7 @@ void rtw_ips_pwr_down23a(struct rtw_adapter *padapter)
 
 void rtw_ips_dev_unload23a(struct rtw_adapter *padapter)
 {
-	rtw_hal_set_hwreg23a(padapter, HW_VAR_FIFO_CLEARN_UP, NULL);
+	rtl8723a_fifo_cleanup(padapter);
 
 	if (padapter->intf_stop)
 		padapter->intf_stop(padapter);
@@ -946,12 +909,6 @@ static int netdev_close(struct net_device *pnetdev)
 		rtw_led_control(padapter, LED_CTL_POWER_OFF);
 	}
 
-#ifdef CONFIG_8723AU_P2P
-	if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
-		wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = false;
-	rtw_p2p_enable23a(padapter, P2P_ROLE_DISABLE);
-#endif /* CONFIG_8723AU_P2P */
-
 	rtw_scan_abort23a(padapter);
 	 /* set this at the end */
 	padapter->rtw_wdev->iftype = NL80211_IFTYPE_MONITOR;
diff --git a/drivers/staging/rtl8723au/os_dep/osdep_service.c b/drivers/staging/rtl8723au/os_dep/osdep_service.c
index 97fc27dce19c..b89e779fa045 100644
--- a/drivers/staging/rtl8723au/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8723au/os_dep/osdep_service.c
@@ -71,17 +71,6 @@ u32 _rtw_queue_empty23a(struct rtw_queue *pqueue)
 		return false;
 }
 
-u64 rtw_modular6423a(u64 x, u64 y)
-{
-	return do_div(x, y);
-}
-
-u64 rtw_division6423a(u64 x, u64 y)
-{
-	do_div(x, y);
-	return x;
-}
-
 /* rtw_cbuf_full23a - test if cbuf is full
  * @cbuf: pointer of struct rtw_cbuf
  *
diff --git a/drivers/staging/rtl8723au/os_dep/recv_linux.c b/drivers/staging/rtl8723au/os_dep/recv_linux.c
index 84402a589f25..528ed9253b14 100644
--- a/drivers/staging/rtl8723au/os_dep/recv_linux.c
+++ b/drivers/staging/rtl8723au/os_dep/recv_linux.c
@@ -21,50 +21,9 @@
 #include <recv_osdep.h>
 
 #include <osdep_intf.h>
-#include <ethernet.h>
 
 #include <usb_ops.h>
 
-/* alloc os related resource in struct recv_frame */
-int rtw_os_recv_resource_alloc23a(struct rtw_adapter *padapter,
-			       struct recv_frame *precvframe)
-{
-	int res = _SUCCESS;
-
-	precvframe->pkt = NULL;
-
-	return res;
-}
-
-/* alloc os related resource in struct recv_buf */
-int rtw_os_recvbuf_resource_alloc23a(struct rtw_adapter *padapter,
-				  struct recv_buf *precvbuf)
-{
-	int res = _SUCCESS;
-
-	precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
-	if (precvbuf->purb == NULL)
-		res = _FAIL;
-
-	precvbuf->pskb = NULL;
-
-	return res;
-}
-
-/* free os related resource in struct recv_buf */
-int rtw_os_recvbuf_resource_free23a(struct rtw_adapter *padapter,
-				 struct recv_buf *precvbuf)
-{
-	int ret = _SUCCESS;
-
-	usb_free_urb(precvbuf->purb);
-
-	if (precvbuf->pskb)
-		dev_kfree_skb_any(precvbuf->pskb);
-
-	return ret;
-}
-
 void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup)
 {
 	enum nl80211_key_type key_type = 0;
@@ -110,11 +69,6 @@ void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup)
 	wrqu.data.length = sizeof(ev);
 }
 
-void rtw_hostapd_mlme_rx23a(struct rtw_adapter *padapter,
-			 struct recv_frame *precv_frame)
-{
-}
-
 int rtw_recv_indicatepkt23a(struct rtw_adapter *padapter,
 			 struct recv_frame *precv_frame)
 {
@@ -205,18 +159,6 @@ _recv_indicatepkt_drop:
 	 return _FAIL;
 }
 
-void rtw_os_read_port23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf)
-{
-	struct recv_priv *precvpriv = &padapter->recvpriv;
-
-	/* free skb in recv_buf */
-	dev_kfree_skb_any(precvbuf->pskb);
-
-	precvbuf->pskb = NULL;
-
-	rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, precvbuf);
-}
-
 void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl)
 {
 	setup_timer(&preorder_ctrl->reordering_ctrl_timer,
diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c
index 612806e0de2e..31ab34601bab 100644
--- a/drivers/staging/rtl8723au/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8723au/os_dep/usb_intf.c
@@ -353,6 +353,7 @@ int rtw_hw_suspend23a(struct rtw_adapter *padapter)
 {
 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 	struct net_device *pnetdev = padapter->pnetdev;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
 	if ((!padapter->bup) || (padapter->bDriverStopped) ||
 	    (padapter->bSurpriseRemoved)) {
@@ -380,20 +381,16 @@ int rtw_hw_suspend23a(struct rtw_adapter *padapter)
 
 		/* s2-2.  indicate disconnect to os */
 		/* rtw_indicate_disconnect23a(padapter); */
-		{
-			struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
-			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
-				_clr_fwstate_(pmlmepriv, _FW_LINKED);
+		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+			_clr_fwstate_(pmlmepriv, _FW_LINKED);
 
-				rtw_led_control(padapter, LED_CTL_NO_LINK);
+			rtw_led_control(padapter, LED_CTL_NO_LINK);
 
-				rtw_os_indicate_disconnect23a(padapter);
+			rtw_os_indicate_disconnect23a(padapter);
 
-				/* donnot enqueue cmd */
-				rtw_lps_ctrl_wk_cmd23a(padapter,
-						    LPS_CTRL_DISCONNECT, 0);
-			}
+			/* donnot enqueue cmd */
+			rtw_lps_ctrl_wk_cmd23a(padapter,
+					       LPS_CTRL_DISCONNECT, 0);
 		}
 		/* s2-3. */
 		rtw_free_assoc_resources23a(padapter, 1);
@@ -509,7 +506,8 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
 	up(&pwrpriv->lock);
 
 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
-		rtw_indicate_scan_done23a(padapter, 1);
+		rtw_cfg80211_indicate_scan_done(
+			wdev_to_priv(padapter->rtw_wdev), true);
 
 	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
 		rtw_indicate_disconnect23a(padapter);
@@ -565,7 +563,7 @@ int rtw_resume_process23a(struct rtw_adapter *padapter)
 
 	if (padapter->pid[1] != 0) {
 		DBG_8723A("pid[1]:%d\n", padapter->pid[1]);
-		rtw_signal_process(padapter->pid[1], SIGUSR2);
+		kill_pid(find_vpid(padapter->pid[1]), SIGUSR2, 1);
 	}
 
 	rtw23a_roaming(padapter, NULL);
@@ -664,10 +662,6 @@ static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
 
 	/*  set mac addr */
 	rtw_macaddr_cfg23a(padapter->eeprompriv.mac_addr);
-#ifdef CONFIG_8723AU_P2P
-	rtw_init_wifidirect_addrs23a(padapter, padapter->eeprompriv.mac_addr,
-				  padapter->eeprompriv.mac_addr);
-#endif
 
 	DBG_8723A("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n",
 		  padapter->bDriverStopped, padapter->bSurpriseRemoved,
diff --git a/drivers/staging/rtl8723au/os_dep/xmit_linux.c b/drivers/staging/rtl8723au/os_dep/xmit_linux.c
index e1c6fc746233..69f88848715a 100644
--- a/drivers/staging/rtl8723au/os_dep/xmit_linux.c
+++ b/drivers/staging/rtl8723au/os_dep/xmit_linux.c
@@ -24,47 +24,6 @@
 #include <xmit_osdep.h>
 #include <osdep_intf.h>
 
-uint rtw_remainder_len23a(struct pkt_file *pfile)
-{
-	return pfile->buf_len - ((unsigned long)(pfile->cur_addr) -
-	       (unsigned long)(pfile->buf_start));
-}
-
-void _rtw_open_pktfile23a(struct sk_buff *pktptr, struct pkt_file *pfile)
-{
-	pfile->pkt = pktptr;
-	pfile->buf_start = pktptr->data;
-	pfile->cur_addr = pktptr->data;
-	pfile->buf_len = pktptr->len;
-	pfile->pkt_len = pktptr->len;
-
-	pfile->cur_buffer = pfile->buf_start;
-}
-
-uint _rtw_pktfile_read23a(struct pkt_file *pfile, u8 *rmem, uint rlen)
-{
-	uint	len = 0;
-
-	len =  rtw_remainder_len23a(pfile);
-	len = (rlen > len) ? len : rlen;
-
-	if (rmem)
-		skb_copy_bits(pfile->pkt, pfile->buf_len-pfile->pkt_len,
-			      rmem, len);
-
-	pfile->cur_addr += len;
-	pfile->pkt_len -= len;
-
-	return len;
-}
-
-int rtw_endofpktfile23a(struct pkt_file *pfile)
-{
-	if (pfile->pkt_len == 0)
-		return true;
-	return false;
-}
-
 int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter,
 			       struct xmit_buf *pxmitbuf, u32 alloc_sz)
 {
diff --git a/drivers/staging/rtl8821ae/base.c b/drivers/staging/rtl8821ae/base.c
index e5073fe24770..a4c9cc437bc6 100644
--- a/drivers/staging/rtl8821ae/base.c
+++ b/drivers/staging/rtl8821ae/base.c
@@ -388,7 +388,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
 
 }
 
-static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
+static int _rtl_init_deferred_work(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
@@ -410,6 +410,9 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 	rtlpriv->works.rtl_wq = create_workqueue(rtlpriv->cfg->name);
 #endif
 /*<delete in kernel end>*/
+	if (!rtlpriv->works.rtl_wq)
+		return -ENOMEM;
+
 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
 			  (void *)rtl_watchdog_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
@@ -421,6 +424,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 	INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq,
 			  (void *)rtl_fwevt_wq_callback);
 
+	return 0;
+
 }
 
 void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
@@ -519,7 +524,8 @@ int rtl_init_core(struct ieee80211_hw *hw)
 	INIT_LIST_HEAD(&rtlpriv->entry_list);
 
 	/* <6> init deferred work */
-	_rtl_init_deferred_work(hw);
+	if (_rtl_init_deferred_work(hw))
+		return 1;
 
 	/* <7> */
 #ifdef VIF_TODO
diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hw.h b/drivers/staging/rtl8821ae/rtl8821ae/hw.h
index 4fb6bf0d1da2..256e514f424a 100644
--- a/drivers/staging/rtl8821ae/rtl8821ae/hw.h
+++ b/drivers/staging/rtl8821ae/rtl8821ae/hw.h
@@ -11,10 +11,6 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
@@ -34,42 +30,43 @@ void rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
 void rtl8821ae_read_eeprom_info(struct ieee80211_hw *hw);
 
 void rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw,
-											 u32 *p_inta, u32 *p_intb);
+				    u32 *p_inta, u32 *p_intb);
 int rtl8821ae_hw_init(struct ieee80211_hw *hw);
 void rtl8821ae_card_disable(struct ieee80211_hw *hw);
 void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw);
 void rtl8821ae_disable_interrupt(struct ieee80211_hw *hw);
-int rtl8821ae_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+int rtl8821ae_set_network_type(struct ieee80211_hw *hw,
+			       enum nl80211_iftype type);
 void rtl8821ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
 void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci);
 void rtl8821ae_set_beacon_related_registers(struct ieee80211_hw *hw);
 void rtl8821ae_set_beacon_interval(struct ieee80211_hw *hw);
 void rtl8821ae_update_interrupt_mask(struct ieee80211_hw *hw,
-												u32 add_msr, u32 rm_msr);
+				     u32 add_msr, u32 rm_msr);
 void rtl8821ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
 void rtl8821ae_update_hal_rate_tbl(struct ieee80211_hw *hw,
-											struct ieee80211_sta *sta,
-											u8 rssi_level);
+				   struct ieee80211_sta *sta,
+				   u8 rssi_level);
 void rtl8821ae_update_channel_access_setting(struct ieee80211_hw *hw);
 bool rtl8821ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
 void rtl8821ae_enable_hw_security_config(struct ieee80211_hw *hw);
 void rtl8821ae_set_key(struct ieee80211_hw *hw, u32 key_index,
-		     				u8 *p_macaddr, bool is_group, u8 enc_algo,
-		     				bool is_wepkey, bool clear_all);
+		       u8 *p_macaddr, bool is_group, u8 enc_algo,
+		       bool is_wepkey, bool clear_all);
 
 void rtl8821ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
-															bool autoload_fail,
-															u8* hwinfo);
+					      bool autoload_fail,
+					      u8 *hwinfo);
 void rtl8812ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
-															bool autoload_fail,
-															u8* hwinfo);
-void rtl8821ae_bt_reg_init(struct ieee80211_hw* hw);
-void rtl8821ae_bt_hw_init(struct ieee80211_hw* hw);
+					      bool autoload_fail,
+					      u8 *hwinfo);
+void rtl8821ae_bt_reg_init(struct ieee80211_hw *hw);
+void rtl8821ae_bt_hw_init(struct ieee80211_hw *hw);
 void rtl8821ae_suspend(struct ieee80211_hw *hw);
 void rtl8821ae_resume(struct ieee80211_hw *hw);
 void rtl8821ae_allow_all_destaddr(struct ieee80211_hw *hw,
-										  bool allow_all_da,
-										  bool write_into_reg);
+				  bool allow_all_da,
+				  bool write_into_reg);
 void _rtl8821ae_stop_tx_beacon(struct ieee80211_hw *hw);
 void _rtl8821ae_resume_tx_beacon(struct ieee80211_hw *hw);
 #endif
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index ef5933b93590..3b6e5358c723 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -1855,8 +1855,9 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
 {
 	static u_char goto_buf[8];
 	static int num;
-	int maxlen, go_pos;
+	int maxlen;
 	char *cp;
+
 	if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
 		goto do_goto;
 	if (type == KT_LATIN && ch == '\n')
@@ -1891,25 +1892,24 @@ oops:
 		spk_special_handler = NULL;
 		return 1;
 	}
-	go_pos = kstrtol(goto_buf, 10, (long *)&cp);
-	goto_pos = (u_long) go_pos;
+
+	goto_pos = simple_strtoul(goto_buf, &cp, 10);
+
 	if (*cp == 'x') {
 		if (*goto_buf < '0')
 			goto_pos += spk_x;
-		else
+		else if (goto_pos > 0)
 			goto_pos--;
-		if (goto_pos < 0)
-			goto_pos = 0;
+
 		if (goto_pos >= vc->vc_cols)
 			goto_pos = vc->vc_cols - 1;
 		goto_x = 1;
 	} else {
 		if (*goto_buf < '0')
 			goto_pos += spk_y;
-		else
+		else if (goto_pos > 0)
 			goto_pos--;
-		if (goto_pos < 0)
-			goto_pos = 0;
+
 		if (goto_pos >= vc->vc_rows)
 			goto_pos = vc->vc_rows - 1;
 		goto_x = 0;
diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c
index 8ea9c46e56ae..3152a2180c45 100644
--- a/drivers/staging/unisys/uislib/uislib.c
+++ b/drivers/staging/unisys/uislib/uislib.c
@@ -381,17 +381,17 @@ create_bus(CONTROLVM_MESSAGE *msg, char *buf)
 		cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
 		cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
 		if (!VirtControlChanFunc) {
-			kfree(bus);
 			LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
 			POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
 					 POSTCODE_SEVERITY_ERR);
+			kfree(bus);
 			return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
 		}
 		if (!VirtControlChanFunc(&cmd)) {
-			kfree(bus);
 			LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
 			POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
 					 POSTCODE_SEVERITY_ERR);
+			kfree(bus);
 			return
 			    CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
 		}
diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h
index d4bf203cdfdf..d95825dc5414 100644
--- a/drivers/staging/unisys/visorchipset/visorchipset.h
+++ b/drivers/staging/unisys/visorchipset/visorchipset.h
@@ -104,9 +104,9 @@ finddevice(struct list_head *list, U32 busNo, U32 devNo)
 
 static inline void delbusdevices(struct list_head *list, U32 busNo)
 {
-	VISORCHIPSET_DEVICE_INFO *p;
+	VISORCHIPSET_DEVICE_INFO *p, *tmp;
 
-	list_for_each_entry(p, list, entry) {
+	list_for_each_entry_safe(p, tmp, list, entry) {
 		if (p->busNo == busNo) {
 			list_del(&p->entry);
 			kfree(p);
diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c
index 257c6e59b460..c475e256e34b 100644
--- a/drivers/staging/unisys/visorchipset/visorchipset_main.c
+++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c
@@ -605,16 +605,16 @@ EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client);
 static void
 cleanup_controlvm_structures(void)
 {
-	VISORCHIPSET_BUS_INFO *bi;
-	VISORCHIPSET_DEVICE_INFO *di;
+	VISORCHIPSET_BUS_INFO *bi, *tmp_bi;
+	VISORCHIPSET_DEVICE_INFO *di, *tmp_di;
 
-	list_for_each_entry(bi, &BusInfoList, entry) {
+	list_for_each_entry_safe(bi, tmp_bi, &BusInfoList, entry) {
 		busInfo_clear(bi);
 		list_del(&bi->entry);
 		kfree(bi);
 	}
 
-	list_for_each_entry(di, &DevInfoList, entry) {
+	list_for_each_entry_safe(di, tmp_di, &DevInfoList, entry) {
 		devInfo_clear(di);
 		list_del(&di->entry);
 		kfree(di);
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
index c5bf60b135b9..92caef7474c7 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
@@ -118,6 +118,7 @@ static int refresh_exported_devices(void)
 	struct udev_list_entry *devices, *dev_list_entry;
 	struct udev_device *dev;
 	const char *path;
+	const char *driver;
 
 	enumerate = udev_enumerate_new(udev_context);
 	udev_enumerate_add_match_subsystem(enumerate, "usb");
@@ -128,10 +129,12 @@ static int refresh_exported_devices(void)
 	udev_list_entry_foreach(dev_list_entry, devices) {
 		path = udev_list_entry_get_name(dev_list_entry);
 		dev = udev_device_new_from_syspath(udev_context, path);
+		if (dev == NULL)
+			continue;
 
 		/* Check whether device uses usbip-host driver. */
-		if (!strcmp(udev_device_get_driver(dev),
-			    USBIP_HOST_DRV_NAME)) {
+		driver = udev_device_get_driver(dev);
+		if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
 			edev = usbip_exported_device_new(path);
 			if (!edev) {
 				dbg("usbip_exported_device_new failed");
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index 47bddcdde0a6..211f43f67ea2 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -184,7 +184,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 	 * @devid: unique device identifier in a remote host
 	 * @speed: usb device speed in a remote host
 	 */
-	if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 1)
+	if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 4)
 		return -EINVAL;
 
 	usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index 792792715673..ffb4eeefdddb 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -776,7 +776,8 @@ static int vme_user_probe(struct vme_dev *vdev)
 		image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
 		if (image[i].kern_buf == NULL) {
 			err = -ENOMEM;
-			goto err_master_buf;
+			vme_master_free(image[i].resource);
+			goto err_master;
 		}
 	}
 
@@ -819,8 +820,6 @@ static int vme_user_probe(struct vme_dev *vdev)
 
 	return 0;
 
-	/* Ensure counter set correcty to destroy all sysfs devices */
-	i = VME_DEVS;
 err_sysfs:
 	while (i > 0) {
 		i--;
@@ -830,12 +829,10 @@ err_sysfs:
 
 	/* Ensure counter set correcty to unalloc all master windows */
 	i = MASTER_MAX + 1;
-err_master_buf:
-	for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++)
-		kfree(image[i].kern_buf);
 err_master:
 	while (i > MASTER_MINOR) {
 		i--;
+		kfree(image[i].kern_buf);
 		vme_master_free(image[i].resource);
 	}
 
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
index 5c739bebd8a5..949f0e5eed8d 100644
--- a/drivers/staging/xgifb/vb_def.h
+++ b/drivers/staging/xgifb/vb_def.h
@@ -1,6 +1,6 @@
 #ifndef _VB_DEF_
 #define _VB_DEF_
-#include "../../video/sis/initdef.h"
+#include "../../video/fbdev/sis/initdef.h"
 
 #define VB_XGI301C      0x0020 /* for 301C */
 
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
index c08ff5b2d6ee..0d27594554ca 100644
--- a/drivers/staging/xgifb/vb_struct.h
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -1,6 +1,6 @@
 #ifndef _VB_STRUCT_
 #define _VB_STRUCT_
-#include "../../video/sis/vstruct.h"
+#include "../../video/fbdev/sis/vstruct.h"
 
 struct XGI_LVDSCRT1HDataStruct {
 	unsigned char Reg[8];
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
index ddf7776c295b..264351441f99 100644
--- a/drivers/staging/xgifb/vgatypes.h
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -2,8 +2,8 @@
 #define _VGATYPES_
 
 #include <linux/fb.h>	/* for struct fb_var_screeninfo for sis.h */
-#include "../../video/sis/vgatypes.h"
-#include "../../video/sis/sis.h"		/* for LCD_TYPE */
+#include "../../video/fbdev/sis/vgatypes.h"
+#include "../../video/fbdev/sis/sis.h"		/* for LCD_TYPE */
 
 #ifndef XGI_VB_CHIP_TYPE
 enum XGI_VB_CHIP_TYPE {
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index b24aa010f68c..65cd80bf9aec 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -13,6 +13,10 @@ config VT
 	bool "Virtual terminal" if EXPERT
 	depends on !S390 && !UML
 	select INPUT
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_TRIGGERS
+	select INPUT_LEDS
 	default y
 	---help---
 	  If you say Y here, you will get support for terminal devices with
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 81f909c2101f..139ab1997e06 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1601,8 +1601,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 		l = l->next;
 
 		if (l == i->head && pass_counter++ > PASS_LIMIT) {
-			/* If we hit this, we're dead. */
-			printk_ratelimited(KERN_ERR
+			pr_debug_ratelimited(
 				"serial8250: too much work for irq%d\n", irq);
 			break;
 		}
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2e6d8ddc4425..5d9b01aa54f4 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1226,6 +1226,7 @@ config SERIAL_BFIN_SPORT3_UART_CTSRTS
 config SERIAL_TIMBERDALE
 	tristate "Support for timberdale UART"
 	select SERIAL_CORE
+	depends on X86_32 || COMPILE_TEST
 	---help---
 	Add support for UART controller on timberdale.
 
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d4eda24aa68b..dacf0a09ab24 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -318,7 +318,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
 			.src_addr = uap->port.mapbase + UART01x_DR,
 			.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
 			.direction = DMA_DEV_TO_MEM,
-			.src_maxburst = uap->fifosize >> 1,
+			.src_maxburst = uap->fifosize >> 2,
 			.device_fc = false,
 		};
 
@@ -2176,6 +2176,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 static int pl011_remove(struct amba_device *dev)
 {
 	struct uart_amba_port *uap = amba_get_drvdata(dev);
+	bool busy = false;
 	int i;
 
 	uart_remove_one_port(&amba_reg, &uap->port);
@@ -2183,9 +2184,12 @@ static int pl011_remove(struct amba_device *dev)
 	for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
 		if (amba_ports[i] == uap)
 			amba_ports[i] = NULL;
+		else if (amba_ports[i])
+			busy = true;
 
 	pl011_dma_remove(uap);
-	uart_unregister_driver(&amba_reg);
+	if (!busy)
+		uart_unregister_driver(&amba_reg);
 	return 0;
 }
 
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 5e6fdb1ea73b..14aaea0d4131 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -368,16 +368,12 @@ static const struct uart_ops uart_clps711x_ops = {
 static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
 {
 	struct clps711x_port *s = dev_get_drvdata(port->dev);
+	u32 sysflg = 0;
 
 	/* Wait for FIFO is not full */
-	while (1) {
-		u32 sysflg = 0;
-
+	do {
 		regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
-		if (!(sysflg & SYSFLG_UTXFF))
-			break;
-		cond_resched();
-	}
+	} while (sysflg & SYSFLG_UTXFF);
 
 	writew(ch, port->membase + UARTDR_OFFSET);
 }
@@ -387,18 +383,14 @@ static void uart_clps711x_console_write(struct console *co, const char *c,
 {
 	struct uart_port *port = clps711x_uart.state[co->index].uart_port;
 	struct clps711x_port *s = dev_get_drvdata(port->dev);
+	u32 sysflg = 0;
 
 	uart_console_write(port, c, n, uart_clps711x_console_putchar);
 
 	/* Wait for transmitter to become empty */
-	while (1) {
-		u32 sysflg = 0;
-
+	do {
 		regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
-		if (!(sysflg & SYSFLG_UBUSY))
-			break;
-		cond_resched();
-	}
+	} while (sysflg & SYSFLG_UBUSY);
 }
 
 static int uart_clps711x_console_setup(struct console *co, char *options)
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index 028582e924a5..c167a710dc39 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -798,6 +798,9 @@ static int efm32_uart_remove(struct platform_device *pdev)
 
 static const struct of_device_id efm32_uart_dt_ids[] = {
 	{
+		.compatible = "energymicro,efm32-uart",
+	}, {
+		/* doesn't follow the "vendor,device" scheme, don't use */
 		.compatible = "efm32,uart",
 	}, {
 		/* sentinel */
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index dd8b1a5458ff..08b6b9419f0d 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -225,14 +225,19 @@ static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up,
 	if (enable)
 		enable_irq(up->wakeirq);
 	else
-		disable_irq(up->wakeirq);
+		disable_irq_nosync(up->wakeirq);
 }
 
 static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
 {
 	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
 
+	if (enable == up->wakeups_enabled)
+		return;
+
 	serial_omap_enable_wakeirq(up, enable);
+	up->wakeups_enabled = enable;
+
 	if (!pdata || !pdata->enable_wakeup)
 		return;
 
@@ -1495,6 +1500,11 @@ static int serial_omap_suspend(struct device *dev)
 	uart_suspend_port(&serial_omap_reg, &up->port);
 	flush_work(&up->qos_work);
 
+	if (device_may_wakeup(dev))
+		serial_omap_enable_wakeup(up, true);
+	else
+		serial_omap_enable_wakeup(up, false);
+
 	return 0;
 }
 
@@ -1502,6 +1512,9 @@ static int serial_omap_resume(struct device *dev)
 {
 	struct uart_omap_port *up = dev_get_drvdata(dev);
 
+	if (device_may_wakeup(dev))
+		serial_omap_enable_wakeup(up, false);
+
 	uart_resume_port(&serial_omap_reg, &up->port);
 
 	return 0;
@@ -1789,6 +1802,7 @@ static int serial_omap_remove(struct platform_device *dev)
 	pm_runtime_disable(up->dev);
 	uart_remove_one_port(&serial_omap_reg, &up->port);
 	pm_qos_remove_request(&up->pm_qos_request);
+	device_init_wakeup(&dev->dev, false);
 
 	return 0;
 }
@@ -1877,17 +1891,7 @@ static int serial_omap_runtime_suspend(struct device *dev)
 
 	up->context_loss_cnt = serial_omap_get_context_loss_count(up);
 
-	if (device_may_wakeup(dev)) {
-		if (!up->wakeups_enabled) {
-			serial_omap_enable_wakeup(up, true);
-			up->wakeups_enabled = true;
-		}
-	} else {
-		if (up->wakeups_enabled) {
-			serial_omap_enable_wakeup(up, false);
-			up->wakeups_enabled = false;
-		}
-	}
+	serial_omap_enable_wakeup(up, true);
 
 	up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
 	schedule_work(&up->qos_work);
@@ -1901,6 +1905,8 @@ static int serial_omap_runtime_resume(struct device *dev)
 
 	int loss_cnt = serial_omap_get_context_loss_count(up);
 
+	serial_omap_enable_wakeup(up, false);
+
 	if (loss_cnt < 0) {
 		dev_dbg(dev, "serial_omap_get_context_loss_count failed : %d\n",
 			loss_cnt);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 2cf5649a6dc0..f26834d262b3 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -89,8 +89,7 @@ static void __uart_start(struct tty_struct *tty)
 	struct uart_state *state = tty->driver_data;
 	struct uart_port *port = state->uart_port;
 
-	if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&
-	    !tty->stopped && !tty->hw_stopped)
+	if (!tty->stopped && !tty->hw_stopped)
 		port->ops->start_tx(port);
 }
 
@@ -1452,6 +1451,8 @@ static void uart_hangup(struct tty_struct *tty)
 		clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
 		spin_unlock_irqrestore(&port->lock, flags);
 		tty_port_tty_set(port, NULL);
+		if (!uart_console(state->uart_port))
+			uart_change_pm(state, UART_PM_STATE_OFF);
 		wake_up_interruptible(&port->open_wait);
 		wake_up_interruptible(&port->delta_msr_wait);
 	}
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index 21e6e84c0df8..dd3a96e07026 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -295,7 +295,7 @@ static void asc_receive_chars(struct uart_port *port)
 			status & ASC_STA_OE) {
 
 			if (c & ASC_RXBUF_FE) {
-				if (c == ASC_RXBUF_FE) {
+				if (c == (ASC_RXBUF_FE | ASC_RXBUF_DUMMY_RX)) {
 					port->icount.brk++;
 					if (uart_handle_break(port))
 						continue;
@@ -325,7 +325,7 @@ static void asc_receive_chars(struct uart_port *port)
 				flag = TTY_FRAME;
 		}
 
-		if (uart_handle_sysrq_char(port, c))
+		if (uart_handle_sysrq_char(port, c & 0xff))
 			continue;
 
 		uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index d3448a90f0f9..34110719fe03 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -878,9 +878,8 @@ void disassociate_ctty(int on_exit)
 	spin_lock_irq(&current->sighand->siglock);
 	put_pid(current->signal->tty_old_pgrp);
 	current->signal->tty_old_pgrp = NULL;
-	spin_unlock_irq(&current->sighand->siglock);
 
-	tty = get_current_tty();
+	tty = tty_kref_get(current->signal->tty);
 	if (tty) {
 		unsigned long flags;
 		spin_lock_irqsave(&tty->ctrl_lock, flags);
@@ -897,6 +896,7 @@ void disassociate_ctty(int on_exit)
 #endif
 	}
 
+	spin_unlock_irq(&current->sighand->siglock);
 	/* Now clear signal->tty under the lock */
 	read_lock(&tasklist_lock);
 	session_clear_tty(task_session(current));
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index d0e3a4497707..d6ecfc9e734f 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -33,6 +33,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/leds.h>
 
 #include <linux/kbd_kern.h>
 #include <linux/kbd_diacr.h>
@@ -130,6 +131,7 @@ static char rep;					/* flag telling character repeat */
 static int shift_state = 0;
 
 static unsigned char ledstate = 0xff;			/* undefined */
+static unsigned char lockstate = 0xff;			/* undefined */
 static unsigned char ledioctl;
 
 /*
@@ -961,6 +963,41 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
 	}
 }
 
+/* We route VT keyboard "leds" through triggers */
+static void kbd_ledstate_trigger_activate(struct led_classdev *cdev);
+
+static struct led_trigger ledtrig_ledstate[] = {
+#define DEFINE_LEDSTATE_TRIGGER(kbd_led, nam) \
+	[kbd_led] = { \
+		.name = nam, \
+		.activate = kbd_ledstate_trigger_activate, \
+	}
+	DEFINE_LEDSTATE_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"),
+	DEFINE_LEDSTATE_TRIGGER(VC_NUMLOCK,   "kbd-numlock"),
+	DEFINE_LEDSTATE_TRIGGER(VC_CAPSLOCK,  "kbd-capslock"),
+	DEFINE_LEDSTATE_TRIGGER(VC_KANALOCK,  "kbd-kanalock"),
+#undef DEFINE_LEDSTATE_TRIGGER
+};
+
+static void kbd_lockstate_trigger_activate(struct led_classdev *cdev);
+
+static struct led_trigger ledtrig_lockstate[] = {
+#define DEFINE_LOCKSTATE_TRIGGER(kbd_led, nam) \
+	[kbd_led] = { \
+		.name = nam, \
+		.activate = kbd_lockstate_trigger_activate, \
+	}
+	DEFINE_LOCKSTATE_TRIGGER(VC_SHIFTLOCK,  "kbd-shiftlock"),
+	DEFINE_LOCKSTATE_TRIGGER(VC_ALTGRLOCK,  "kbd-altgrlock"),
+	DEFINE_LOCKSTATE_TRIGGER(VC_CTRLLOCK,   "kbd-ctrllock"),
+	DEFINE_LOCKSTATE_TRIGGER(VC_ALTLOCK,    "kbd-altlock"),
+	DEFINE_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"),
+	DEFINE_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"),
+	DEFINE_LOCKSTATE_TRIGGER(VC_CTRLLLOCK,  "kbd-ctrlllock"),
+	DEFINE_LOCKSTATE_TRIGGER(VC_CTRLRLOCK,  "kbd-ctrlrlock"),
+#undef DEFINE_LOCKSTATE_TRIGGER
+};
+
 /*
  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
  * or (ii) whatever pattern of lights people want to show using KDSETLED,
@@ -995,18 +1032,25 @@ static inline unsigned char getleds(void)
 	return kbd->ledflagstate;
 }
 
-static int kbd_update_leds_helper(struct input_handle *handle, void *data)
+/* Called on trigger connection, to set initial state */
+static void kbd_ledstate_trigger_activate(struct led_classdev *cdev)
 {
-	unsigned char leds = *(unsigned char *)data;
+	struct led_trigger *trigger = cdev->trigger;
+	int led = trigger - ledtrig_ledstate;
 
-	if (test_bit(EV_LED, handle->dev->evbit)) {
-		input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
-		input_inject_event(handle, EV_LED, LED_NUML,    !!(leds & 0x02));
-		input_inject_event(handle, EV_LED, LED_CAPSL,   !!(leds & 0x04));
-		input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
-	}
+	tasklet_disable(&keyboard_tasklet);
+	led_trigger_event(trigger, ledstate & (1 << led) ? LED_FULL : LED_OFF);
+	tasklet_enable(&keyboard_tasklet);
+}
 
-	return 0;
+static void kbd_lockstate_trigger_activate(struct led_classdev *cdev)
+{
+	struct led_trigger *trigger = cdev->trigger;
+	int led = trigger - ledtrig_lockstate;
+
+	tasklet_disable(&keyboard_tasklet);
+	led_trigger_event(trigger, lockstate & (1 << led) ? LED_FULL : LED_OFF);
+	tasklet_enable(&keyboard_tasklet);
 }
 
 /**
@@ -1095,16 +1139,29 @@ static void kbd_bh(unsigned long dummy)
 {
 	unsigned char leds;
 	unsigned long flags;
-	
+	int i;
+
 	spin_lock_irqsave(&led_lock, flags);
 	leds = getleds();
 	spin_unlock_irqrestore(&led_lock, flags);
 
 	if (leds != ledstate) {
-		input_handler_for_each_handle(&kbd_handler, &leds,
-					      kbd_update_leds_helper);
+		for (i = 0; i < ARRAY_SIZE(ledtrig_ledstate); i++)
+			if ((leds ^ ledstate) & (1 << i))
+				led_trigger_event(&ledtrig_ledstate[i],
+						leds & (1 << i)
+						? LED_FULL : LED_OFF);
 		ledstate = leds;
 	}
+
+	if (kbd->lockstate != lockstate) {
+		for (i = 0; i < ARRAY_SIZE(ledtrig_lockstate); i++)
+			if ((kbd->lockstate ^ lockstate) & (1 << i))
+				led_trigger_event(&ledtrig_lockstate[i],
+						kbd->lockstate & (1 << i)
+						? LED_FULL : LED_OFF);
+		lockstate = kbd->lockstate;
+	}
 }
 
 DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
@@ -1442,20 +1499,6 @@ static void kbd_disconnect(struct input_handle *handle)
 	kfree(handle);
 }
 
-/*
- * Start keyboard handler on the new keyboard by refreshing LED state to
- * match the rest of the system.
- */
-static void kbd_start(struct input_handle *handle)
-{
-	tasklet_disable(&keyboard_tasklet);
-
-	if (ledstate != 0xff)
-		kbd_update_leds_helper(handle, &ledstate);
-
-	tasklet_enable(&keyboard_tasklet);
-}
-
 static const struct input_device_id kbd_ids[] = {
 	{
 		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
@@ -1477,7 +1520,6 @@ static struct input_handler kbd_handler = {
 	.match		= kbd_match,
 	.connect	= kbd_connect,
 	.disconnect	= kbd_disconnect,
-	.start		= kbd_start,
 	.name		= "kbd",
 	.id_table	= kbd_ids,
 };
@@ -1501,6 +1543,20 @@ int __init kbd_init(void)
 	if (error)
 		return error;
 
+	for (i = 0; i < ARRAY_SIZE(ledtrig_ledstate); i++) {
+		error = led_trigger_register(&ledtrig_ledstate[i]);
+		if (error)
+			pr_err("error %d while registering trigger %s\n",
+					error, ledtrig_ledstate[i].name);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ledtrig_lockstate); i++) {
+		error = led_trigger_register(&ledtrig_lockstate[i]);
+		if (error)
+			pr_err("error %d while registering trigger %s\n",
+					error, ledtrig_lockstate[i].name);
+	}
+
 	tasklet_enable(&keyboard_tasklet);
 	tasklet_schedule(&keyboard_tasklet);
 
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 900f7ff805ee..904efb6035b0 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -518,13 +518,16 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
 	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
 		dev_err(&acm->control->dev,
 			"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
+		usb_autopm_put_interface(acm->control);
 		goto error_submit_urb;
 	}
 
 	acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
 	if (acm_set_control(acm, acm->ctrlout) < 0 &&
-	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
+	    (acm->ctrl_caps & USB_CDC_CAP_LINE)) {
+		usb_autopm_put_interface(acm->control);
 		goto error_set_control;
+	}
 
 	usb_autopm_put_interface(acm->control);
 
@@ -549,7 +552,6 @@ error_submit_read_urbs:
 error_set_control:
 	usb_kill_urb(acm->ctrlurb);
 error_submit_urb:
-	usb_autopm_put_interface(acm->control);
 error_get_interface:
 disconnected:
 	mutex_unlock(&acm->mutex);
@@ -1652,13 +1654,27 @@ static const struct usb_device_id acm_ids[] = {
 	},
 	/* Motorola H24 HSPA module: */
 	{ USB_DEVICE(0x22b8, 0x2d91) }, /* modem                                */
-	{ USB_DEVICE(0x22b8, 0x2d92) }, /* modem           + diagnostics        */
-	{ USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port                      */
-	{ USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics        */
-	{ USB_DEVICE(0x22b8, 0x2d96) }, /* modem                         + NMEA */
-	{ USB_DEVICE(0x22b8, 0x2d97) }, /* modem           + diagnostics + NMEA */
-	{ USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port               + NMEA */
-	{ USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */
+	{ USB_DEVICE(0x22b8, 0x2d92),   /* modem           + diagnostics        */
+	.driver_info = NO_UNION_NORMAL, /* handle only modem interface          */
+	},
+	{ USB_DEVICE(0x22b8, 0x2d93),   /* modem + AT port                      */
+	.driver_info = NO_UNION_NORMAL, /* handle only modem interface          */
+	},
+	{ USB_DEVICE(0x22b8, 0x2d95),   /* modem + AT port + diagnostics        */
+	.driver_info = NO_UNION_NORMAL, /* handle only modem interface          */
+	},
+	{ USB_DEVICE(0x22b8, 0x2d96),   /* modem                         + NMEA */
+	.driver_info = NO_UNION_NORMAL, /* handle only modem interface          */
+	},
+	{ USB_DEVICE(0x22b8, 0x2d97),   /* modem           + diagnostics + NMEA */
+	.driver_info = NO_UNION_NORMAL, /* handle only modem interface          */
+	},
+	{ USB_DEVICE(0x22b8, 0x2d99),   /* modem + AT port               + NMEA */
+	.driver_info = NO_UNION_NORMAL, /* handle only modem interface          */
+	},
+	{ USB_DEVICE(0x22b8, 0x2d9a),   /* modem + AT port + diagnostics + NMEA */
+	.driver_info = NO_UNION_NORMAL, /* handle only modem interface          */
+	},
 
 	{ USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
 	.driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index d59d99347d54..1f02e65fe305 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -75,7 +75,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
 				PCI_SLOT(companion->devfn) != slot)
 			continue;
 		companion_hcd = pci_get_drvdata(companion);
-		if (!companion_hcd)
+		if (!companion_hcd || !companion_hcd->self.root_hub)
 			continue;
 		fn(pdev, hcd, companion, companion_hcd);
 	}
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index d1d8c47777c5..7f425acd9be5 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -212,6 +212,8 @@ static int exynos_ehci_suspend(struct device *dev)
 	int rc;
 
 	rc = ehci_suspend(hcd, do_wakeup);
+	if (rc)
+		return rc;
 
 	if (exynos_ehci->otg)
 		exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b3a0e11073aa..c7dd93aad20c 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -303,6 +303,8 @@ static int ehci_platform_suspend(struct device *dev)
 	int ret;
 
 	ret = ehci_suspend(hcd, do_wakeup);
+	if (ret)
+		return ret;
 
 	if (pdata->power_suspend)
 		pdata->power_suspend(pdev);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 27ac6ad53c3d..7ef00ecb0da1 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -509,8 +509,31 @@ static struct platform_driver tegra_ehci_driver = {
 	}
 };
 
+static int tegra_ehci_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+	int txfifothresh;
+
+	retval = ehci_setup(hcd);
+	if (retval)
+		return retval;
+
+	/*
+	 * We should really pull this value out of tegra_ehci_soc_config, but
+	 * to avoid needing access to it, make use of the fact that Tegra20 is
+	 * the only one so far that needs a value of 10, and Tegra20 is the
+	 * only one which doesn't set has_hostpc.
+	 */
+	txfifothresh = ehci->has_hostpc ? 0x10 : 10;
+	ehci_writel(ehci, txfifothresh << 16, &ehci->regs->txfill_tuning);
+
+	return 0;
+}
+
 static const struct ehci_driver_overrides tegra_overrides __initconst = {
 	.extra_priv_size	= sizeof(struct tegra_ehci_hcd),
+	.reset			= tegra_ehci_reset,
 };
 
 static int __init ehci_tegra_init(void)
diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
index af8dc1b92d75..c2c221a332eb 100644
--- a/drivers/usb/host/ohci-jz4740.c
+++ b/drivers/usb/host/ohci-jz4740.c
@@ -82,14 +82,14 @@ static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 	u16 wIndex, char *buf, u16 wLength)
 {
 	struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
-	int ret;
+	int ret = 0;
 
 	switch (typeReq) {
-	case SetHubFeature:
+	case SetPortFeature:
 		if (wValue == USB_PORT_FEAT_POWER)
 			ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true);
 		break;
-	case ClearHubFeature:
+	case ClearPortFeature:
 		if (wValue == USB_PORT_FEAT_POWER)
 			ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false);
 		break;
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 95fa1217afdd..762e4a5f5ae9 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -104,6 +104,7 @@ static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
 	{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
+	{ USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */
 	{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
 	{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
 	{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 44ab12986805..7c6e1dedeb06 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -909,6 +909,39 @@ static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
 	/* Cressi Devices */
 	{ USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) },
+	/* Brainboxes Devices */
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) },
+	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) },
 	{ }					/* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index e599fbfcde5f..993c93df6874 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1326,3 +1326,40 @@
  * Manufacturer: Cressi
  */
 #define FTDI_CRESSI_PID		0x87d0
+
+/*
+ * Brainboxes devices
+ */
+#define BRAINBOXES_VID			0x05d1
+#define BRAINBOXES_VX_001_PID		0x1001 /* VX-001 ExpressCard 1 Port RS232 */
+#define BRAINBOXES_VX_012_PID		0x1002 /* VX-012 ExpressCard 2 Port RS232 */
+#define BRAINBOXES_VX_023_PID		0x1003 /* VX-023 ExpressCard 1 Port RS422/485 */
+#define BRAINBOXES_VX_034_PID		0x1004 /* VX-034 ExpressCard 2 Port RS422/485 */
+#define BRAINBOXES_US_101_PID		0x1011 /* US-101 1xRS232 */
+#define BRAINBOXES_US_324_PID		0x1013 /* US-324 1xRS422/485 1Mbaud */
+#define BRAINBOXES_US_606_1_PID		0x2001 /* US-606 6 Port RS232 Serial Port 1 and 2 */
+#define BRAINBOXES_US_606_2_PID		0x2002 /* US-606 6 Port RS232 Serial Port 3 and 4 */
+#define BRAINBOXES_US_606_3_PID		0x2003 /* US-606 6 Port RS232 Serial Port 4 and 6 */
+#define BRAINBOXES_US_701_1_PID		0x2011 /* US-701 4xRS232 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_701_2_PID		0x2012 /* US-701 4xRS422 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_279_1_PID		0x2021 /* US-279 8xRS422 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_279_2_PID		0x2022 /* US-279 8xRS422 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_279_3_PID		0x2023 /* US-279 8xRS422 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_279_4_PID		0x2024 /* US-279 8xRS422 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_346_1_PID		0x3011 /* US-346 4xRS422/485 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_346_2_PID		0x3012 /* US-346 4xRS422/485 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_257_PID		0x5001 /* US-257 2xRS232 1Mbaud */
+#define BRAINBOXES_US_313_PID		0x6001 /* US-313 2xRS422/485 1Mbaud */
+#define BRAINBOXES_US_357_PID		0x7001 /* US_357 1xRS232/422/485 */
+#define BRAINBOXES_US_842_1_PID		0x8001 /* US-842 8xRS422/485 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_842_2_PID		0x8002 /* US-842 8xRS422/485 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_842_3_PID		0x8003 /* US-842 8xRS422/485 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_842_4_PID		0x8004 /* US-842 8xRS422/485 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_160_1_PID		0x9001 /* US-160 16xRS232 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_160_2_PID		0x9002 /* US-160 16xRS232 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_160_3_PID		0x9003 /* US-160 16xRS232 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_160_4_PID		0x9004 /* US-160 16xRS232 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_160_5_PID		0x9005 /* US-160 16xRS232 1Mbaud Port 9 and 10 */
+#define BRAINBOXES_US_160_6_PID		0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */
+#define BRAINBOXES_US_160_7_PID		0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */
+#define BRAINBOXES_US_160_8_PID		0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 68fc9fe65936..367c7f08b27c 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -243,6 +243,7 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_CC864_DUAL		0x1005
 #define TELIT_PRODUCT_CC864_SINGLE		0x1006
 #define TELIT_PRODUCT_DE910_DUAL		0x1010
+#define TELIT_PRODUCT_UE910_V2			0x1012
 #define TELIT_PRODUCT_LE920			0x1200
 
 /* ZTE PRODUCTS */
@@ -1041,6 +1042,7 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
 		.driver_info = (kernel_ulong_t)&telit_le920_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 2e22fc22c382..b3d5a35c0d4b 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -83,6 +83,9 @@ static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
 	{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
 	{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
+	{ USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) },
+	{ USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) },
+	{ USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) },
 	{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
 	{ USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index c38b8c00c06f..42bc082896ac 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -121,8 +121,11 @@
 #define SUPERIAL_VENDOR_ID	0x5372
 #define SUPERIAL_PRODUCT_ID	0x2303
 
-/* Hewlett-Packard LD220-HP POS Pole Display */
+/* Hewlett-Packard POS Pole Displays */
 #define HP_VENDOR_ID		0x03f0
+#define HP_LD960_PRODUCT_ID	0x0b39
+#define HP_LCM220_PRODUCT_ID	0x3139
+#define HP_LCM960_PRODUCT_ID	0x3239
 #define HP_LD220_PRODUCT_ID	0x3524
 
 /* Cressi Edy (diving computer) PC interface */
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index a9eb6221a815..6b192e602ce0 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -291,7 +291,6 @@ static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x0f3d, 0x68A3), 	/* Airprime/Sierra Wireless Direct IP modems */
 	  .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
 	},
-       { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
 
 	{ }
 };
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 640fe0173236..b078440e822f 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -466,6 +466,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
 	int err;
 	int i;
 
+	if (!port->bulk_in_size || !port->bulk_out_size)
+		return -ENODEV;
+
 	portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
 	if (!portdata)
 		return -ENOMEM;
@@ -473,9 +476,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
 	init_usb_anchor(&portdata->delayed);
 
 	for (i = 0; i < N_IN_URB; i++) {
-		if (!port->bulk_in_size)
-			break;
-
 		buffer = (u8 *)__get_free_page(GFP_KERNEL);
 		if (!buffer)
 			goto bail_out_error;
@@ -489,9 +489,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
 	}
 
 	for (i = 0; i < N_OUT_URB; i++) {
-		if (!port->bulk_out_size)
-			break;
-
 		buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
 		if (!buffer)
 			goto bail_out_error2;
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index a7ac97cc5949..511b22953167 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -137,7 +137,7 @@ static void uas_do_work(struct work_struct *work)
 		if (!(cmdinfo->state & IS_IN_WORK_LIST))
 			continue;
 
-		err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+		err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
 		if (!err)
 			cmdinfo->state &= ~IS_IN_WORK_LIST;
 		else
@@ -803,7 +803,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
 
 	devinfo->running_task = 1;
 	memset(&devinfo->response, 0, sizeof(devinfo->response));
-	sense_urb = uas_submit_sense_urb(cmnd, GFP_NOIO,
+	sense_urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC,
 					 devinfo->use_streams ? tag : 0);
 	if (!sense_urb) {
 		shost_printk(KERN_INFO, shost,
@@ -813,7 +813,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
 		spin_unlock_irqrestore(&devinfo->lock, flags);
 		return FAILED;
 	}
-	if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) {
+	if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) {
 		shost_printk(KERN_INFO, shost,
 			     "%s: %s: submit task mgmt urb failed\n",
 			     __func__, fname);
@@ -1030,7 +1030,7 @@ static int uas_configure_endpoints(struct uas_dev_info *devinfo)
 		devinfo->use_streams = 0;
 	} else {
 		devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1,
-						    3, 256, GFP_KERNEL);
+						    3, 256, GFP_NOIO);
 		if (devinfo->qdepth < 0)
 			return devinfo->qdepth;
 		devinfo->use_streams = 1;
@@ -1047,7 +1047,7 @@ static void uas_free_streams(struct uas_dev_info *devinfo)
 	eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
 	eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
 	eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
-	usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
+	usb_free_streams(devinfo->intf, eps, 3, GFP_NOIO);
 }
 
 static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1096,16 +1096,17 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	if (result)
 		goto free_streams;
 
+	usb_set_intfdata(intf, shost);
 	result = scsi_add_host(shost, &intf->dev);
 	if (result)
 		goto free_streams;
 
 	scsi_scan_host(shost);
-	usb_set_intfdata(intf, shost);
 	return result;
 
 free_streams:
 	uas_free_streams(devinfo);
+	usb_set_intfdata(intf, NULL);
 set_alt0:
 	usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
 	if (shost)
diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c
index d771870a819e..6dfd30a863c7 100644
--- a/drivers/usb/usb-common.c
+++ b/drivers/usb/usb-common.c
@@ -69,7 +69,7 @@ const char *usb_state_string(enum usb_device_state state)
 		[USB_STATE_RECONNECTING] = "reconnecting",
 		[USB_STATE_UNAUTHENTICATED] = "unauthenticated",
 		[USB_STATE_DEFAULT] = "default",
-		[USB_STATE_ADDRESS] = "addresssed",
+		[USB_STATE_ADDRESS] = "addressed",
 		[USB_STATE_CONFIGURED] = "configured",
 		[USB_STATE_SUSPENDED] = "suspended",
 	};
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c
index 16ada8341c46..1a2fd9795367 100644
--- a/drivers/uwb/drp.c
+++ b/drivers/uwb/drp.c
@@ -599,8 +599,11 @@ static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_i
 
 	/* alloc and initialize new uwb_cnflt_alien */
 	cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL);
-	if (!cnflt)
+	if (!cnflt) {
 		dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n");
+		return;
+	}
+
 	INIT_LIST_HEAD(&cnflt->rc_node);
 	init_timer(&cnflt->timer);
 	cnflt->timer.function = uwb_cnflt_timer;
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
deleted file mode 100644
index 552258c8f99d..000000000000
--- a/drivers/video/68328fb.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- *  linux/drivers/video/68328fb.c -- Low level implementation of the
- *                                   mc68x328 LCD frame buffer device
- *
- *	Copyright (C) 2003 Georges Menie
- *
- *  This driver assumes an already configured controller (e.g. from config.c)
- *  Keep the code clean of board specific initialization.
- *
- *  This code has not been tested with colors, colormap management functions
- *  are minimal (no colormap data written to the 68328 registers...)
- *
- *  initial version of this driver:
- *    Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>,
- *                            The Silver Hammer Group, Ltd.
- *
- *  this version is based on :
- *
- *  linux/drivers/video/vfb.c -- Virtual frame buffer device
- *
- *      Copyright (C) 2002 James Simmons
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <asm/uaccess.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-
-#if defined(CONFIG_M68VZ328)
-#include <asm/MC68VZ328.h>
-#elif defined(CONFIG_M68EZ328)
-#include <asm/MC68EZ328.h>
-#elif defined(CONFIG_M68328)
-#include <asm/MC68328.h>
-#else
-#error wrong architecture for the MC68x328 frame buffer device
-#endif
-
-#if defined(CONFIG_FB_68328_INVERT)
-#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO01
-#else
-#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO10
-#endif
-
-static u_long videomemory;
-static u_long videomemorysize;
-
-static struct fb_info fb_info;
-static u32 mc68x328fb_pseudo_palette[16];
-
-static struct fb_var_screeninfo mc68x328fb_default __initdata = {
-	.red =		{ 0, 8, 0 },
-      	.green =	{ 0, 8, 0 },
-      	.blue =		{ 0, 8, 0 },
-      	.activate =	FB_ACTIVATE_TEST,
-      	.height =	-1,
-      	.width =	-1,
-      	.pixclock =	20000,
-      	.left_margin =	64,
-      	.right_margin =	64,
-      	.upper_margin =	32,
-      	.lower_margin =	32,
-      	.hsync_len =	64,
-      	.vsync_len =	2,
-      	.vmode =	FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo mc68x328fb_fix __initdata = {
-	.id =		"68328fb",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	1,
-	.accel =	FB_ACCEL_NONE,
-};
-
-    /*
-     *  Interface used by the world
-     */
-int mc68x328fb_init(void);
-int mc68x328fb_setup(char *);
-
-static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
-			 struct fb_info *info);
-static int mc68x328fb_set_par(struct fb_info *info);
-static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			 u_int transp, struct fb_info *info);
-static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
-			   struct fb_info *info);
-static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
-
-static struct fb_ops mc68x328fb_ops = {
-	.fb_check_var	= mc68x328fb_check_var,
-	.fb_set_par	= mc68x328fb_set_par,
-	.fb_setcolreg	= mc68x328fb_setcolreg,
-	.fb_pan_display	= mc68x328fb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_mmap	= mc68x328fb_mmap,
-};
-
-    /*
-     *  Internal routines
-     */
-
-static u_long get_line_length(int xres_virtual, int bpp)
-{
-	u_long length;
-
-	length = xres_virtual * bpp;
-	length = (length + 31) & ~31;
-	length >>= 3;
-	return (length);
-}
-
-    /*
-     *  Setting the video mode has been split into two parts.
-     *  First part, xxxfb_check_var, must not write anything
-     *  to hardware, it should only verify and adjust var.
-     *  This means it doesn't alter par but it does use hardware
-     *  data from it to check this var. 
-     */
-
-static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
-			 struct fb_info *info)
-{
-	u_long line_length;
-
-	/*
-	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
-	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
-	 */
-
-	if (var->vmode & FB_VMODE_CONUPDATE) {
-		var->vmode |= FB_VMODE_YWRAP;
-		var->xoffset = info->var.xoffset;
-		var->yoffset = info->var.yoffset;
-	}
-
-	/*
-	 *  Some very basic checks
-	 */
-	if (!var->xres)
-		var->xres = 1;
-	if (!var->yres)
-		var->yres = 1;
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-	if (var->bits_per_pixel <= 1)
-		var->bits_per_pixel = 1;
-	else if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel <= 24)
-		var->bits_per_pixel = 24;
-	else if (var->bits_per_pixel <= 32)
-		var->bits_per_pixel = 32;
-	else
-		return -EINVAL;
-
-	if (var->xres_virtual < var->xoffset + var->xres)
-		var->xres_virtual = var->xoffset + var->xres;
-	if (var->yres_virtual < var->yoffset + var->yres)
-		var->yres_virtual = var->yoffset + var->yres;
-
-	/*
-	 *  Memory limit
-	 */
-	line_length =
-	    get_line_length(var->xres_virtual, var->bits_per_pixel);
-	if (line_length * var->yres_virtual > videomemorysize)
-		return -ENOMEM;
-
-	/*
-	 * Now that we checked it we alter var. The reason being is that the video
-	 * mode passed in might not work but slight changes to it might make it 
-	 * work. This way we let the user know what is acceptable.
-	 */
-	switch (var->bits_per_pixel) {
-	case 1:
-		var->red.offset = 0;
-		var->red.length = 1;
-		var->green.offset = 0;
-		var->green.length = 1;
-		var->blue.offset = 0;
-		var->blue.length = 1;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:		/* RGBA 5551 */
-		if (var->transp.length) {
-			var->red.offset = 0;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 5;
-			var->blue.offset = 10;
-			var->blue.length = 5;
-			var->transp.offset = 15;
-			var->transp.length = 1;
-		} else {	/* RGB 565 */
-			var->red.offset = 0;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 6;
-			var->blue.offset = 11;
-			var->blue.length = 5;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-		}
-		break;
-	case 24:		/* RGB 888 */
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 16;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 32:		/* RGBA 8888 */
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 16;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	}
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	return 0;
-}
-
-/* This routine actually sets the video mode. It's in here where we
- * the hardware state info->par and fix which can be affected by the 
- * change in par. For this driver it doesn't do much. 
- */
-static int mc68x328fb_set_par(struct fb_info *info)
-{
-	info->fix.line_length = get_line_length(info->var.xres_virtual,
-						info->var.bits_per_pixel);
-	return 0;
-}
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			 u_int transp, struct fb_info *info)
-{
-	if (regno >= 256)	/* no. of hw registers */
-		return 1;
-	/*
-	 * Program hardware... do anything you want with transp
-	 */
-
-	/* grayscale works only partially under directcolor */
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue =
-		    (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	/* Directcolor:
-	 *   var->{color}.offset contains start of bitfield
-	 *   var->{color}.length contains length of bitfield
-	 *   {hardwarespecific} contains width of RAMDAC
-	 *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
-	 *   RAMDAC[X] is programmed to (red, green, blue)
-	 * 
-	 * Pseudocolor:
-	 *    uses offset = 0 && length = RAMDAC register width.
-	 *    var->{color}.offset is 0
-	 *    var->{color}.length contains width of DAC
-	 *    cmap is not used
-	 *    RAMDAC[X] is programmed to (red, green, blue)
-	 * Truecolor:
-	 *    does not use DAC. Usually 3 are present.
-	 *    var->{color}.offset contains start of bitfield
-	 *    var->{color}.length contains length of bitfield
-	 *    cmap is programmed to (red << red.offset) | (green << green.offset) |
-	 *                      (blue << blue.offset) | (transp << transp.offset)
-	 *    RAMDAC does not exist
-	 */
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		red = CNVT_TOHW(red, info->var.red.length);
-		green = CNVT_TOHW(green, info->var.green.length);
-		blue = CNVT_TOHW(blue, info->var.blue.length);
-		transp = CNVT_TOHW(transp, info->var.transp.length);
-		break;
-	case FB_VISUAL_DIRECTCOLOR:
-		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
-		green = CNVT_TOHW(green, 8);
-		blue = CNVT_TOHW(blue, 8);
-		/* hey, there is bug in transp handling... */
-		transp = CNVT_TOHW(transp, 8);
-		break;
-	}
-#undef CNVT_TOHW
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 v;
-
-		if (regno >= 16)
-			return 1;
-
-		v = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset) |
-		    (transp << info->var.transp.offset);
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			break;
-		case 16:
-			((u32 *) (info->pseudo_palette))[regno] = v;
-			break;
-		case 24:
-		case 32:
-			((u32 *) (info->pseudo_palette))[regno] = v;
-			break;
-		}
-		return 0;
-	}
-	return 0;
-}
-
-    /*
-     *  Pan or Wrap the Display
-     *
-     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-     */
-
-static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
-{
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0
-		    || var->yoffset >= info->var.yres_virtual
-		    || var->xoffset)
-			return -EINVAL;
-	} else {
-		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-		    var->yoffset + info->var.yres > info->var.yres_virtual)
-			return -EINVAL;
-	}
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-	return 0;
-}
-
-    /*
-     *  Most drivers don't need their own mmap function 
-     */
-
-static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-#ifndef MMU
-	/* this is uClinux (no MMU) specific code */
-
-	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
-	vma->vm_start = videomemory;
-
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
-int __init mc68x328fb_setup(char *options)
-{
-#if 0
-	char *this_opt;
-#endif
-
-	if (!options || !*options)
-		return 1;
-#if 0
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strncmp(this_opt, "disable", 7))
-			mc68x328fb_enable = 0;
-	}
-#endif
-	return 1;
-}
-
-    /*
-     *  Initialisation
-     */
-
-int __init mc68x328fb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("68328fb", &option))
-		return -ENODEV;
-	mc68x328fb_setup(option);
-#endif
-	/*
-	 *  initialize the default mode from the LCD controller registers
-	 */
-	mc68x328fb_default.xres = LXMAX;
-	mc68x328fb_default.yres = LYMAX+1;
-	mc68x328fb_default.xres_virtual = mc68x328fb_default.xres;
-	mc68x328fb_default.yres_virtual = mc68x328fb_default.yres;
-	mc68x328fb_default.bits_per_pixel = 1 + (LPICF & 0x01);
-	videomemory = LSSA;
-	videomemorysize = (mc68x328fb_default.xres_virtual+7) / 8 *
-		mc68x328fb_default.yres_virtual * mc68x328fb_default.bits_per_pixel;
-
-	fb_info.screen_base = (void *)videomemory;
-	fb_info.fbops = &mc68x328fb_ops;
-	fb_info.var = mc68x328fb_default;
-	fb_info.fix = mc68x328fb_fix;
-	fb_info.fix.smem_start = videomemory;
-	fb_info.fix.smem_len = videomemorysize;
-	fb_info.fix.line_length =
-		get_line_length(mc68x328fb_default.xres_virtual, mc68x328fb_default.bits_per_pixel);
-	fb_info.fix.visual = (mc68x328fb_default.bits_per_pixel) == 1 ?
-		MC68X328FB_MONO_VISUAL : FB_VISUAL_PSEUDOCOLOR;
-	if (fb_info.var.bits_per_pixel == 1) {
-		fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1;
-		fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0;
-	}
-	fb_info.pseudo_palette = &mc68x328fb_pseudo_palette;
-	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-
-	if (fb_alloc_cmap(&fb_info.cmap, 256, 0))
-		return -ENOMEM;
-
-	if (register_framebuffer(&fb_info) < 0) {
-		fb_dealloc_cmap(&fb_info.cmap);
-		return -EINVAL;
-	}
-
-	fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
-	fb_info(&fb_info, "%dx%dx%d at 0x%08lx\n",
-		mc68x328fb_default.xres_virtual,
-		mc68x328fb_default.yres_virtual,
-		1 << mc68x328fb_default.bits_per_pixel, videomemory);
-
-	return 0;
-}
-
-module_init(mc68x328fb_init);
-
-#ifdef MODULE
-
-static void __exit mc68x328fb_cleanup(void)
-{
-	unregister_framebuffer(&fb_info);
-	fb_dealloc_cmap(&fb_info.cmap);
-}
-
-module_exit(mc68x328fb_cleanup);
-
-MODULE_LICENSE("GPL");
-#endif				/* MODULE */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6c793bc683d9..c7b4f0f927b1 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -21,7 +21,15 @@ source "drivers/gpu/vga/Kconfig"
 
 source "drivers/gpu/host1x/Kconfig"
 
+menu "Direct Rendering Manager"
 source "drivers/gpu/drm/Kconfig"
+endmenu
+
+menu "Frame buffer Devices"
+source "drivers/video/fbdev/Kconfig"
+endmenu
+
+source "drivers/video/backlight/Kconfig"
 
 config VGASTATE
        tristate
@@ -33,2482 +41,14 @@ config VIDEOMODE_HELPERS
 config HDMI
 	bool
 
-menuconfig FB
-	tristate "Support for frame buffer devices"
-	---help---
-	  The frame buffer device provides an abstraction for the graphics
-	  hardware. It represents the frame buffer of some video hardware and
-	  allows application software to access the graphics hardware through
-	  a well-defined interface, so the software doesn't need to know
-	  anything about the low-level (hardware register) stuff.
-
-	  Frame buffer devices work identically across the different
-	  architectures supported by Linux and make the implementation of
-	  application programs easier and more portable; at this point, an X
-	  server exists which uses the frame buffer device exclusively.
-	  On several non-X86 architectures, the frame buffer device is the
-	  only way to use the graphics hardware.
-
-	  The device is accessed through special device nodes, usually located
-	  in the /dev directory, i.e. /dev/fb*.
-
-	  You need an utility program called fbset to make full use of frame
-	  buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
-	  and the Framebuffer-HOWTO at
-	  <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.3.html> for more
-	  information.
-
-	  Say Y here and to the driver for your graphics board below if you
-	  are compiling a kernel for a non-x86 architecture.
-
-	  If you are compiling for the x86 architecture, you can say Y if you
-	  want to play with it, but it is not essential. Please note that
-	  running graphical applications that directly touch the hardware
-	  (e.g. an accelerated X server) and that are not frame buffer
-	  device-aware may cause unexpected results. If unsure, say N.
-
-config FIRMWARE_EDID
-       bool "Enable firmware EDID"
-       depends on FB
-       default n
-       ---help---
-         This enables access to the EDID transferred from the firmware.
-	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
-	 transfers do not work for your driver and if you are using
-	 nvidiafb, i810fb or savagefb.
-
-	 In general, choosing Y for this option is safe.  If you
-	 experience extremely long delays while booting before you get
-	 something on your display, try setting this to N.  Matrox cards in
-	 combination with certain motherboards and monitors are known to
-	 suffer from this problem.
-
-config FB_DDC
-       tristate
-       depends on FB
-       select I2C_ALGOBIT
-       select I2C
-       default n
-
-config FB_BOOT_VESA_SUPPORT
-	bool
-	depends on FB
-	default n
-	---help---
-	  If true, at least one selected framebuffer driver can take advantage
-	  of VESA video modes set at an early boot stage via the vga= parameter.
-
-config FB_CFB_FILLRECT
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Include the cfb_fillrect function for generic software rectangle
-	  filling. This is used by drivers that don't provide their own
-	  (accelerated) version.
-
-config FB_CFB_COPYAREA
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Include the cfb_copyarea function for generic software area copying.
-	  This is used by drivers that don't provide their own (accelerated)
-	  version.
-
-config FB_CFB_IMAGEBLIT
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Include the cfb_imageblit function for generic software image
-	  blitting. This is used by drivers that don't provide their own
-	  (accelerated) version.
-
-config FB_CFB_REV_PIXELS_IN_BYTE
-	bool
-	depends on FB
-	default n
-	---help---
-	  Allow generic frame-buffer functions to work on displays with 1, 2
-	  and 4 bits per pixel depths which has opposite order of pixels in
-	  byte order to bytes in long order.
-
-config FB_SYS_FILLRECT
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Include the sys_fillrect function for generic software rectangle
-	  filling. This is used by drivers that don't provide their own
-	  (accelerated) version and the framebuffer is in system RAM.
-
-config FB_SYS_COPYAREA
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Include the sys_copyarea function for generic software area copying.
-	  This is used by drivers that don't provide their own (accelerated)
-	  version and the framebuffer is in system RAM.
-
-config FB_SYS_IMAGEBLIT
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Include the sys_imageblit function for generic software image
-	  blitting. This is used by drivers that don't provide their own
-	  (accelerated) version and the framebuffer is in system RAM.
-
-menuconfig FB_FOREIGN_ENDIAN
-	bool "Framebuffer foreign endianness support"
-	depends on FB
-	---help---
-	  This menu will let you enable support for the framebuffers with
-	  non-native endianness (e.g. Little-Endian framebuffer on a
-	  Big-Endian machine). Most probably you don't have such hardware,
-	  so it's safe to say "n" here.
-
-choice
-	prompt "Choice endianness support"
-	depends on FB_FOREIGN_ENDIAN
-
-config FB_BOTH_ENDIAN
-	bool "Support for Big- and Little-Endian framebuffers"
-
-config FB_BIG_ENDIAN
-	bool "Support for Big-Endian framebuffers only"
-
-config FB_LITTLE_ENDIAN
-	bool "Support for Little-Endian framebuffers only"
-
-endchoice
-
-config FB_SYS_FOPS
-       tristate
-       depends on FB
-       default n
-
-config FB_DEFERRED_IO
-	bool
-	depends on FB
-
-config FB_HECUBA
-	tristate
-	depends on FB
-	depends on FB_DEFERRED_IO
-
-config FB_SVGALIB
-	tristate
-	depends on FB
-	default n
-	---help---
-	  Common utility functions useful to fbdev drivers of VGA-based
-	  cards.
-
-config FB_MACMODES
-       tristate
-       depends on FB
-       default n
-
-config FB_BACKLIGHT
-	bool
-	depends on FB
-	select BACKLIGHT_LCD_SUPPORT
-	select BACKLIGHT_CLASS_DEVICE
-	default n
-
-config FB_MODE_HELPERS
-        bool "Enable Video Mode Handling Helpers"
-        depends on FB
-	default n
-	---help---
-	  This enables functions for handling video modes using the
-	  Generalized Timing Formula and the EDID parser. A few drivers rely
-          on this feature such as the radeonfb, rivafb, and the i810fb. If
-	  your driver does not take advantage of this feature, choosing Y will
-	  just increase the kernel size by about 5K.
-
-config FB_TILEBLITTING
-       bool "Enable Tile Blitting Support"
-       depends on FB
-       default n
-       ---help---
-         This enables tile blitting.  Tile blitting is a drawing technique
-	 where the screen is divided into rectangular sections (tiles), whereas
-	 the standard blitting divides the screen into pixels. Because the
-	 default drawing element is a tile, drawing functions will be passed
-	 parameters in terms of number of tiles instead of number of pixels.
-	 For example, to draw a single character, instead of using bitmaps,
-	 an index to an array of bitmaps will be used.  To clear or move a
-	 rectangular section of a screen, the rectangle will be described in
-	 terms of number of tiles in the x- and y-axis.
-
-	 This is particularly important to one driver, matroxfb.  If
-	 unsure, say N.
-
-comment "Frame buffer hardware drivers"
-	depends on FB
-
-config FB_GRVGA
-	tristate "Aeroflex Gaisler framebuffer support"
-	depends on FB && SPARC
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
-
-config FB_CIRRUS
-	tristate "Cirrus Logic support"
-	depends on FB && (ZORRO || PCI)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  This enables support for Cirrus Logic GD542x/543x based boards on
-	  Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
-
-	  If you have a PCI-based system, this enables support for these
-	  chips: GD-543x, GD-544x, GD-5480.
-
-	  Please read the file <file:Documentation/fb/cirrusfb.txt>.
-
-	  Say N unless you have such a graphics board or plan to get one
-	  before you next recompile the kernel.
-
-config FB_PM2
-	tristate "Permedia2 support"
-	depends on FB && ((AMIGA && BROKEN) || PCI)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for cards based on
-	  the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
-	  The driver was tested on the following cards:
-		Diamond FireGL 1000 PRO AGP
-		ELSA Gloria Synergy PCI
-		Appian Jeronimo PRO (both heads) PCI
-		3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
-		Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
-		ASK Graphic Blaster Exxtreme AGP
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pm2fb.
-
-config FB_PM2_FIFO_DISCONNECT
-	bool "enable FIFO disconnect feature"
-	depends on FB_PM2 && PCI
-	help
-	  Support the Permedia2 FIFO disconnect feature.
-
-config FB_ARMCLCD
-	tristate "ARM PrimeCell PL110 support"
-	depends on ARM || ARM64 || COMPILE_TEST
-	depends on FB && ARM_AMBA
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This framebuffer device driver is for the ARM PrimeCell PL110
-	  Colour LCD controller.  ARM PrimeCells provide the building
-	  blocks for System on a Chip devices.
-
-	  If you want to compile this as a module (=code which can be
-	  inserted into and removed from the running kernel), say M
-	  here and read <file:Documentation/kbuild/modules.txt>.  The module
-	  will be called amba-clcd.
-
-config FB_ACORN
-	bool "Acorn VIDC support"
-	depends on (FB = y) && ARM && ARCH_ACORN
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Acorn VIDC graphics
-	  hardware found in Acorn RISC PCs and other ARM-based machines.  If
-	  unsure, say N.
-
-config FB_CLPS711X
-	bool "CLPS711X LCD support"
-	depends on (FB = y) && ARM && ARCH_CLPS711X
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  Say Y to enable the Framebuffer driver for the CLPS7111 and
-	  EP7212 processors.
-
-config FB_SA1100
-	bool "SA-1100 LCD support"
-	depends on (FB = y) && ARM && ARCH_SA1100
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is a framebuffer device for the SA-1100 LCD Controller.
-	  See <http://www.linux-fbdev.org/> for information on framebuffer
-	  devices.
-
-	  If you plan to use the LCD display with your SA-1100 system, say
-	  Y here.
-
-config FB_IMX
-	tristate "Freescale i.MX1/21/25/27 LCD support"
-	depends on FB && ARCH_MXC
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MODE_HELPERS
-	select VIDEOMODE_HELPERS
-
-config FB_CYBER2000
-	tristate "CyberPro 2000/2010/5000 support"
-	depends on FB && PCI && (BROKEN || !SPARC64)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This enables support for the Integraphics CyberPro 20x0 and 5000
-	  VGA chips used in the Rebel.com Netwinder and other machines.
-	  Say Y if you have a NetWinder or a graphics card containing this
-	  device, otherwise say N.
-
-config FB_CYBER2000_DDC
-	bool "DDC for CyberPro support"
-	depends on FB_CYBER2000
-	select FB_DDC
-	default y
-	help
-	  Say Y here if you want DDC support for your CyberPro graphics
-	  card. This is only I2C bus support, driver does not use EDID.
-
-config FB_CYBER2000_I2C
-	bool "CyberPro 2000/2010/5000 I2C support"
-	depends on FB_CYBER2000 && I2C && ARCH_NETWINDER
-	select I2C_ALGOBIT
-	help
-	  Enable support for the I2C video decoder interface on the
-	  Integraphics CyberPro 20x0 and 5000 VGA chips.  This is used
-	  on the Netwinder machines for the SAA7111 video capture.
-
-config FB_APOLLO
-	bool
-	depends on (FB = y) && APOLLO
-	default y
-	select FB_CFB_FILLRECT
-	select FB_CFB_IMAGEBLIT
-
-config FB_Q40
-	bool
-	depends on (FB = y) && Q40
-	default y
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-
-config FB_AMIGA
-	tristate "Amiga native chipset support"
-	depends on FB && AMIGA
-	help
-	  This is the frame buffer device driver for the builtin graphics
-	  chipset found in Amigas.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called amifb.
-
-config FB_AMIGA_OCS
-	bool "Amiga OCS chipset support"
-	depends on FB_AMIGA
-	help
-	  This enables support for the original Agnus and Denise video chips,
-	  found in the Amiga 1000 and most A500's and A2000's. If you intend
-	  to run Linux on any of these systems, say Y; otherwise say N.
-
-config FB_AMIGA_ECS
-	bool "Amiga ECS chipset support"
-	depends on FB_AMIGA
-	help
-	  This enables support for the Enhanced Chip Set, found in later
-	  A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If
-	  you intend to run Linux on any of these systems, say Y; otherwise
-	  say N.
-
-config FB_AMIGA_AGA
-	bool "Amiga AGA chipset support"
-	depends on FB_AMIGA
-	help
-	  This enables support for the Advanced Graphics Architecture (also
-	  known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T
-	  and CD32. If you intend to run Linux on any of these systems, say Y;
-	  otherwise say N.
-
-config FB_FM2
-	bool "Amiga FrameMaster II/Rainbow II support"
-	depends on (FB = y) && ZORRO
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Amiga FrameMaster
-	  card from BSC (exhibited 1992 but not shipped as a CBM product).
-
-config FB_ARC
-	tristate "Arc Monochrome LCD board support"
-	depends on FB && X86
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	help
-	  This enables support for the Arc Monochrome LCD board. The board
-	  is based on the KS-108 lcd controller and is typically a matrix
-	  of 2*n chips. This driver was tested with a 128x64 panel. This
-	  driver supports it for use with x86 SBCs through a 16 bit GPIO
-	  interface (8 bit data, 8 bit control). If you anticipate using
-	  this driver, say Y or M; otherwise say N. You must specify the
-	  GPIO IO address to be used for setting control and data.
-
-config FB_ATARI
-	bool "Atari native chipset support"
-	depends on (FB = y) && ATARI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the builtin graphics
-	  chipset found in Ataris.
-
-config FB_OF
-	bool "Open Firmware frame buffer device support"
-	depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MACMODES
-	help
-	  Say Y if you want support with Open Firmware for your graphics
-	  board.
-
-config FB_CONTROL
-	bool "Apple \"control\" display support"
-	depends on (FB = y) && PPC_PMAC && PPC32
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MACMODES
-	help
-	  This driver supports a frame buffer for the graphics adapter in the
-	  Power Macintosh 7300 and others.
-
-config FB_PLATINUM
-	bool "Apple \"platinum\" display support"
-	depends on (FB = y) && PPC_PMAC && PPC32
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MACMODES
-	help
-	  This driver supports a frame buffer for the "platinum" graphics
-	  adapter in some Power Macintoshes.
-
-config FB_VALKYRIE
-	bool "Apple \"valkyrie\" display support"
-	depends on (FB = y) && (MAC || (PPC_PMAC && PPC32))
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MACMODES
-	help
-	  This driver supports a frame buffer for the "valkyrie" graphics
-	  adapter in some Power Macintoshes.
-
-config FB_CT65550
-	bool "Chips 65550 display support"
-	depends on (FB = y) && PPC32 && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Chips & Technologies
-	  65550 graphics chip in PowerBooks.
-
-config FB_ASILIANT
-	bool "Asiliant (Chips) 69000 display support"
-	depends on (FB = y) && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Asiliant 69030 chipset
-
-config FB_IMSTT
-	bool "IMS Twin Turbo display support"
-	depends on (FB = y) && PCI
-	select FB_CFB_IMAGEBLIT
-	select FB_MACMODES if PPC
-	help
-	  The IMS Twin Turbo is a PCI-based frame buffer card bundled with
-	  many Macintosh and compatible computers.
-
-config FB_VGA16
-	tristate "VGA 16-color graphics support"
-	depends on FB && (X86 || PPC)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select VGASTATE
-	select FONT_8x16 if FRAMEBUFFER_CONSOLE
-	help
-	  This is the frame buffer device driver for VGA 16 color graphic
-	  cards. Say Y if you have such a card.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vga16fb.
-
-config FB_BF54X_LQ043
-	tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)"
-	depends on FB && (BF54x) && !BF542
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	 This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
-
-config FB_BFIN_T350MCQB
-	tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)"
-	depends on FB && BLACKFIN
-	select BFIN_GPTIMERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	 This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD
-	 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
-	 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
-
-config FB_BFIN_LQ035Q1
-	tristate "SHARP LQ035Q1DH02 TFT LCD"
-	depends on FB && BLACKFIN && SPI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select BFIN_GPTIMERS
-	help
-	  This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on
-	  the Blackfin Landscape LCD EZ-Extender Card.
-	  This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI
-	  It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called bfin-lq035q1-fb.
-
-config FB_BF537_LQ035
-	tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
-	depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select BFIN_GPTIMERS
-	help
-	  This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
-	  attached to a BF537.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called bf537-lq035.
-
-config FB_BFIN_7393
-	tristate "Blackfin ADV7393 Video encoder"
-	depends on FB && BLACKFIN
-	select I2C
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for a ADV7393 video encoder
-	  attached to a Blackfin on the PPI port.
-	  If your Blackfin board has a ADV7393 select Y.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called bfin_adv7393fb.
-
-choice
-	prompt  "Video mode support"
-	depends on FB_BFIN_7393
-	default NTSC
-
-config NTSC
-	bool 'NTSC 720x480'
-
-config PAL
-	bool 'PAL 720x576'
-
-config NTSC_640x480
-	bool 'NTSC 640x480 (Experimental)'
-
-config PAL_640x480
-	bool 'PAL 640x480 (Experimental)'
-
-config NTSC_YCBCR
-	bool 'NTSC 720x480 YCbCR input'
-
-config PAL_YCBCR
-	bool 'PAL 720x576 YCbCR input'
-
-endchoice
-
-choice
-	prompt  "Size of ADV7393 frame buffer memory Single/Double Size"
-	depends on (FB_BFIN_7393)
-	default ADV7393_1XMEM
-
-config ADV7393_1XMEM
-	bool 'Single'
-
-config ADV7393_2XMEM
-	bool 'Double'
-endchoice
-
-config FB_STI
-	tristate "HP STI frame buffer device support"
-	depends on FB && PARISC
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select STI_CONSOLE
-	select VT
-	default y
-	---help---
-	  STI refers to the HP "Standard Text Interface" which is a set of
-	  BIOS routines contained in a ROM chip in HP PA-RISC based machines.
-	  Enabling this option will implement the linux framebuffer device
-	  using calls to the STI BIOS routines for initialisation.
-	
-	  If you enable this option, you will get a planar framebuffer device
-	  /dev/fb which will work on the most common HP graphic cards of the
-	  NGLE family, including the artist chips (in the 7xx and Bxxx series),
-	  HCRX, HCRX24, CRX, CRX24 and VisEG series.
-
-	  It is safe to enable this option, so you should probably say "Y".
-
-config FB_MAC
-	bool "Generic Macintosh display support"
-	depends on (FB = y) && MAC
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MACMODES
-
-config FB_HP300
-	bool
-	depends on (FB = y) && DIO
-	select FB_CFB_IMAGEBLIT
-	default y
-
-config FB_TGA
-	tristate "TGA/SFB+ framebuffer support"
-	depends on FB && (ALPHA || TC)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select BITREVERSE
-	---help---
-	  This is the frame buffer device driver for generic TGA and SFB+
-	  graphic cards.  These include DEC ZLXp-E1, -E2 and -E3 PCI cards,
-	  also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3
-	  TURBOchannel cards, also known as PMAGD-A, -B and -C.
-
-	  Due to hardware limitations ZLX-E2 and E3 cards are not supported
-	  for DECstation 5000/200 systems.  Additionally due to firmware
-	  limitations these cards may cause troubles with booting DECstation
-	  5000/240 and /260 systems, but are fully supported under Linux if
-	  you manage to get it going. ;-)
-
-	  Say Y if you have one of those.
-
-config FB_UVESA
-	tristate "Userspace VESA VGA graphics support"
-	depends on FB && CONNECTOR
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MODE_HELPERS
-	help
-	  This is the frame buffer driver for generic VBE 2.0 compliant
-	  graphic cards. It can also take advantage of VBE 3.0 features,
-	  such as refresh rate adjustment.
-
-	  This driver generally provides more features than vesafb but
-	  requires a userspace helper application called 'v86d'. See
-	  <file:Documentation/fb/uvesafb.txt> for more information.
-
-	  If unsure, say N.
-
-config FB_VESA
-	bool "VESA VGA graphics support"
-	depends on (FB = y) && X86
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_BOOT_VESA_SUPPORT
-	help
-	  This is the frame buffer device driver for generic VESA 2.0
-	  compliant graphic cards. The older VESA 1.2 cards are not supported.
-	  You will get a boot time penguin logo at no additional cost. Please
-	  read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
-
-config FB_EFI
-	bool "EFI-based Framebuffer Support"
-	depends on (FB = y) && X86 && EFI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the EFI frame buffer device driver. If the firmware on
-	  your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
-	  using the EFI framebuffer as your console.
-
-config FB_N411
-       tristate "N411 Apollo/Hecuba devkit support"
-       depends on FB && X86 && MMU
-       select FB_SYS_FILLRECT
-       select FB_SYS_COPYAREA
-       select FB_SYS_IMAGEBLIT
-       select FB_SYS_FOPS
-       select FB_DEFERRED_IO
-       select FB_HECUBA
-       help
-         This enables support for the Apollo display controller in its
-         Hecuba form using the n411 devkit.
-
-config FB_HGA
-	tristate "Hercules mono graphics support"
-	depends on FB && X86
-	help
-	  Say Y here if you have a Hercules mono graphics card.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called hgafb.
-
-	  As this card technology is at least 25 years old,
-	  most people will answer N here.
-
-config FB_GBE
-	bool "SGI Graphics Backend frame buffer support"
-	depends on (FB = y) && SGI_IP32
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
- 	help
-	  This is the frame buffer device driver for SGI Graphics Backend.
-	  This chip is used in SGI O2 and Visual Workstation 320/540.
-
-config FB_GBE_MEM
-	int "Video memory size in MB"
-	depends on FB_GBE
-	default 4
-	help
-	  This is the amount of memory reserved for the framebuffer,
-	  which can be any value between 1MB and 8MB.
-
-config FB_SBUS
-	bool "SBUS and UPA framebuffers"
-	depends on (FB = y) && SPARC
-	help
-	  Say Y if you want support for SBUS or UPA based frame buffer device.
-
-config FB_BW2
-	bool "BWtwo support"
-	depends on (FB = y) && (SPARC && FB_SBUS)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the BWtwo frame buffer.
-
-config FB_CG3
-	bool "CGthree support"
-	depends on (FB = y) && (SPARC && FB_SBUS)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the CGthree frame buffer.
-
-config FB_CG6
-	bool "CGsix (GX,TurboGX) support"
-	depends on (FB = y) && (SPARC && FB_SBUS)
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the CGsix (GX, TurboGX)
-	  frame buffer.
-
-config FB_FFB
-	bool "Creator/Creator3D/Elite3D support"
-	depends on FB_SBUS && SPARC64
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Creator, Creator3D,
-	  and Elite3D graphics boards.
-
-config FB_TCX
-	bool "TCX (SS4/SS5 only) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the TCX 24/8bit frame
-	  buffer.
-
-config FB_CG14
-	bool "CGfourteen (SX) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the CGfourteen frame
-	  buffer on Desktop SPARCsystems with the SX graphics option.
-
-config FB_P9100
-	bool "P9100 (Sparcbook 3 only) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the P9100 card
-	  supported on Sparcbook 3 machines.
-
-config FB_LEO
-	bool "Leo (ZX) support"
-	depends on FB_SBUS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the SBUS-based Sun ZX
-	  (leo) frame buffer cards.
-
-config FB_IGA
-	bool "IGA 168x display support"
-	depends on (FB = y) && SPARC32
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for the INTERGRAPHICS 1680 and
-	  successor frame buffer cards.
-
-config FB_XVR500
-	bool "Sun XVR-500 3DLABS Wildcat support"
-	depends on (FB = y) && PCI && SPARC64
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for the Sun XVR-500 and similar
-	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
-	  only works on sparc64 systems where the system firmware has
-	  mostly initialized the card already.  It is treated as a
-	  completely dumb framebuffer device.
-
-config FB_XVR2500
-	bool "Sun XVR-2500 3DLABS Wildcat support"
-	depends on (FB = y) && PCI && SPARC64
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for the Sun XVR-2500 and similar
-	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
-	  only works on sparc64 systems where the system firmware has
-	  mostly initialized the card already.  It is treated as a
-	  completely dumb framebuffer device.
-
-config FB_XVR1000
-	bool "Sun XVR-1000 support"
-	depends on (FB = y) && SPARC64
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer device for the Sun XVR-1000 and similar
-	  graphics cards.  The driver only works on sparc64 systems where
-	  the system firmware has mostly initialized the card already.  It
-	  is treated as a completely dumb framebuffer device.
-
-config FB_PVR2
-	tristate "NEC PowerVR 2 display support"
-	depends on FB && SH_DREAMCAST
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Say Y here if you have a PowerVR 2 card in your box.  If you plan to
-	  run linux on your Dreamcast, you will have to say Y here.
-	  This driver may or may not work on other PowerVR 2 cards, but is
-	  totally untested.  Use at your own risk.  If unsure, say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pvr2fb.
-
-	  You can pass several parameters to the driver at boot time or at
-	  module load time.  The parameters look like "video=pvr2:XXX", where
-	  the meaning of XXX can be found at the end of the main source file
-	  (<file:drivers/video/pvr2fb.c>). Please see the file
-	  <file:Documentation/fb/pvr2fb.txt>.
-
-config FB_OPENCORES
-	tristate "OpenCores VGA/LCD core 2.0 framebuffer support"
-	depends on FB && HAS_DMA
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This enables support for the OpenCores VGA/LCD core.
-
-	  The OpenCores VGA/LCD core is typically used together with
-	  softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor
-	  systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs.
-
-	  The source code and specification for the core is available at
-	  <http://opencores.org/project,vga_lcd>
-
-config FB_S1D13XXX
-	tristate "Epson S1D13XXX framebuffer support"
-	depends on FB
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  Support for S1D13XXX framebuffer device family (currently only
-	  working with S1D13806). Product specs at
-	  <http://vdc.epson.com/>
-
-config FB_ATMEL
-	tristate "AT91/AT32 LCD Controller support"
-	depends on FB && HAVE_FB_ATMEL
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MODE_HELPERS
-	select VIDEOMODE_HELPERS
-	help
-	  This enables support for the AT91/AT32 LCD Controller.
-
-config FB_INTSRAM
-	bool "Frame Buffer in internal SRAM"
-	depends on FB_ATMEL && ARCH_AT91SAM9261
-	help
-	  Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
-	  to let frame buffer in external SDRAM.
-
-config FB_ATMEL_STN
-	bool "Use a STN display with AT91/AT32 LCD Controller"
-	depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK)
-	default n
-	help
-	  Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
-	  Controller. Say N if you want to connect a TFT.
-
-	  If unsure, say N.
-
-config FB_NVIDIA
-	tristate "nVidia Framebuffer Support"
-	depends on FB && PCI
-	select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select BITREVERSE
-	select VGASTATE
-	help
-	  This driver supports graphics boards with the nVidia chips, TNT
-	  and newer. For very old chipsets, such as the RIVA128, then use
-	  the rivafb.
-	  Say Y if you have such a graphics board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called nvidiafb.
-
-config FB_NVIDIA_I2C
-       bool "Enable DDC Support"
-       depends on FB_NVIDIA
-       select FB_DDC
-       help
-	  This enables I2C support for nVidia Chipsets.  This is used
-	  only for getting EDID information from the attached display
-	  allowing for robust video mode handling and switching.
-
-	  Because fbdev-2.6 requires that drivers must be able to
-	  independently validate video mode parameters, you should say Y
-	  here.
-
-config FB_NVIDIA_DEBUG
-	bool "Lots of debug output"
-	depends on FB_NVIDIA
-	default n
-	help
-	  Say Y here if you want the nVidia driver to output all sorts
-	  of debugging information to provide to the maintainer when
-	  something goes wrong.
-
-config FB_NVIDIA_BACKLIGHT
-	bool "Support for backlight control"
-	depends on FB_NVIDIA
-	default y
-	help
-	  Say Y here if you want to control the backlight of your display.
-
-config FB_RIVA
-	tristate "nVidia Riva support"
-	depends on FB && PCI
-	select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select BITREVERSE
-	select VGASTATE
-	help
-	  This driver supports graphics boards with the nVidia Riva/Geforce
-	  chips.
-	  Say Y if you have such a graphics board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called rivafb.
-
-config FB_RIVA_I2C
-       bool "Enable DDC Support"
-       depends on FB_RIVA
-       select FB_DDC
-       help
-	  This enables I2C support for nVidia Chipsets.  This is used
-	  only for getting EDID information from the attached display
-	  allowing for robust video mode handling and switching.
-
-	  Because fbdev-2.6 requires that drivers must be able to
-	  independently validate video mode parameters, you should say Y
-	  here.
-
-config FB_RIVA_DEBUG
-	bool "Lots of debug output"
-	depends on FB_RIVA
-	default n
-	help
-	  Say Y here if you want the Riva driver to output all sorts
-	  of debugging information to provide to the maintainer when
-	  something goes wrong.
-
-config FB_RIVA_BACKLIGHT
-	bool "Support for backlight control"
-	depends on FB_RIVA
-	default y
-	help
-	  Say Y here if you want to control the backlight of your display.
-
-config FB_I740
-	tristate "Intel740 support"
-	depends on FB && PCI
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select VGASTATE
-	select FB_DDC
-	help
-	  This driver supports graphics cards based on Intel740 chip.
-
-config FB_I810
-	tristate "Intel 810/815 support"
-	depends on FB && PCI && X86_32 && AGP_INTEL
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select VGASTATE
-	help
-	  This driver supports the on-board graphics built in to the Intel 810 
-          and 815 chipsets.  Say Y if you have and plan to use such a board.
-
-          To compile this driver as a module, choose M here: the
-	  module will be called i810fb.
-
-          For more information, please read 
-	  <file:Documentation/fb/intel810.txt>
-
-config FB_I810_GTF
-	bool "use VESA Generalized Timing Formula"
-	depends on FB_I810
-	help
-	  If you say Y, then the VESA standard, Generalized Timing Formula 
-          or GTF, will be used to calculate the required video timing values
-	  per video mode.  Since the GTF allows nondiscrete timings 
-          (nondiscrete being a range of values as opposed to discrete being a
-          set of values), you'll be able to use any combination of horizontal 
-	  and vertical resolutions, and vertical refresh rates without having
-	  to specify your own timing parameters.  This is especially useful
-	  to maximize the performance of an aging display, or if you just 
-          have a display with nonstandard dimensions. A VESA compliant 
-	  monitor is recommended, but can still work with non-compliant ones.
-	  If you need or want this, then select this option. The timings may 
-	  not be compliant with Intel's recommended values. Use at your own 
-	  risk.
-
-          If you say N, the driver will revert to discrete video timings 
-	  using a set recommended by Intel in their documentation.
-  
-          If unsure, say N.
-
-config FB_I810_I2C
-	bool "Enable DDC Support"
-	depends on FB_I810 && FB_I810_GTF
-	select FB_DDC
-	help
-
-config FB_LE80578
-	tristate "Intel LE80578 (Vermilion) support"
-	depends on FB && PCI && X86
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This driver supports the LE80578 (Vermilion Range) chipset
-
-config FB_CARILLO_RANCH
-	tristate "Intel Carillo Ranch support"
-	depends on FB_LE80578 && FB && PCI && X86
-	help
-	  This driver supports the LE80578 (Carillo Ranch) board
-
-config FB_INTEL
-	tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support"
-	depends on FB && PCI && X86 && AGP_INTEL && EXPERT
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_BOOT_VESA_SUPPORT if FB_INTEL = y
-	depends on !DRM_I915
-	help
-	  This driver supports the on-board graphics built in to the Intel
-          830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
-          Say Y if you have and plan to use such a board.
-
-	  To make FB_INTELFB=Y work you need to say AGP_INTEL=y too.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called intelfb.
-
-	  For more information, please read <file:Documentation/fb/intelfb.txt>
-
-config FB_INTEL_DEBUG
-	bool "Intel driver Debug Messages"
-	depends on FB_INTEL
-	---help---
-	  Say Y here if you want the Intel driver to output all sorts
-	  of debugging information to provide to the maintainer when
-	  something goes wrong.
-
-config FB_INTEL_I2C
-	bool "DDC/I2C for Intel framebuffer support"
-	depends on FB_INTEL
-	select FB_DDC
-	default y
-	help
-	  Say Y here if you want DDC/I2C support for your on-board Intel graphics.
-
-config FB_MATROX
-	tristate "Matrox acceleration"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_TILEBLITTING
-	select FB_MACMODES if PPC_PMAC
-	---help---
-	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
-	  Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
-	  Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
-	  Matrox G400, G450 or G550 card in your box.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called matroxfb.
-
-	  You can pass several parameters to the driver at boot time or at
-	  module load time. The parameters look like "video=matroxfb:XXX", and
-	  are described in <file:Documentation/fb/matroxfb.txt>.
-
-config FB_MATROX_MILLENIUM
-	bool "Millennium I/II support"
-	depends on FB_MATROX
-	help
-	  Say Y here if you have a Matrox Millennium or Matrox Millennium II
-	  video card. If you select "Advanced lowlevel driver options" below,
-	  you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp
-	  packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can
-	  also use font widths different from 8.
-
-config FB_MATROX_MYSTIQUE
-	bool "Mystique support"
-	depends on FB_MATROX
-	help
-	  Say Y here if you have a Matrox Mystique or Matrox Mystique 220
-	  video card. If you select "Advanced lowlevel driver options" below,
-	  you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp
-	  packed pixel and 32 bpp packed pixel. You can also use font widths
-	  different from 8.
-
-config FB_MATROX_G
-	bool "G100/G200/G400/G450/G550 support"
-	depends on FB_MATROX
-	---help---
-	  Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based
-	  video card. If you select "Advanced lowlevel driver options", you
-	  should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
-	  pixel and 32 bpp packed pixel. You can also use font widths
-	  different from 8.
-
-	  If you need support for G400 secondary head, you must say Y to
-	  "Matrox I2C support" and "G400 second head support" right below.
-	  G450/G550 secondary head and digital output are supported without
-	  additional modules.
-
-	  The driver starts in monitor mode. You must use the matroxset tool 
-	  (available at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to 
-	  swap primary and secondary head outputs, or to change output mode.  
-	  Secondary head driver always start in 640x480 resolution and you 
-	  must use fbset to change it.
-
-	  Do not forget that second head supports only 16 and 32 bpp
-	  packed pixels, so it is a good idea to compile them into the kernel
-	  too. You can use only some font widths, as the driver uses generic
-	  painting procedures (the secondary head does not use acceleration
-	  engine).
-
-	  G450/G550 hardware can display TV picture only from secondary CRTC,
-	  and it performs no scaling, so picture must have 525 or 625 lines.
-
-config FB_MATROX_I2C
-	tristate "Matrox I2C support"
-	depends on FB_MATROX
-	select FB_DDC
-	---help---
-	  This drivers creates I2C buses which are needed for accessing the
-	  DDC (I2C) bus present on all Matroxes, an I2C bus which
-	  interconnects Matrox optional devices, like MGA-TVO on G200 and
-	  G400, and the secondary head DDC bus, present on G400 only.
-
-	  You can say Y or M here if you want to experiment with monitor
-	  detection code. You must say Y or M here if you want to use either
-	  second head of G400 or MGA-TVO on G200 or G400.
-
-	  If you compile it as module, it will create a module named
-	  i2c-matroxfb.
-
-config FB_MATROX_MAVEN
-	tristate "G400 second head support"
-	depends on FB_MATROX_G && FB_MATROX_I2C
-	---help---
-	  WARNING !!! This support does not work with G450 !!!
-
-	  Say Y or M here if you want to use a secondary head (meaning two
-	  monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary
-	  head is not compatible with accelerated XFree 3.3.x SVGA servers -
-	  secondary head output is blanked while you are in X. With XFree
-	  3.9.17 preview you can use both heads if you use SVGA over fbdev or
-	  the fbdev driver on first head and the fbdev driver on second head.
-
-	  If you compile it as module, two modules are created,
-	  matroxfb_crtc2 and matroxfb_maven. Matroxfb_maven is needed for
-	  both G200 and G400, matroxfb_crtc2 is needed only by G400. You must
-	  also load i2c-matroxfb to get it to run.
-
-	  The driver starts in monitor mode and you must use the matroxset
-	  tool (available at
-	  <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to switch it to
-	  PAL or NTSC or to swap primary and secondary head outputs.
-	  Secondary head driver also always start in 640x480 resolution, you
-	  must use fbset to change it.
-
-	  Also do not forget that second head supports only 16 and 32 bpp
-	  packed pixels, so it is a good idea to compile them into the kernel
-	  too.  You can use only some font widths, as the driver uses generic
-	  painting procedures (the secondary head does not use acceleration
-	  engine).
-
-config FB_RADEON
-	tristate "ATI Radeon display support"
-	depends on FB && PCI
-	select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MACMODES if PPC_OF
-	help
-	  Choose this option if you want to use an ATI Radeon graphics card as
-	  a framebuffer device.  There are both PCI and AGP versions.  You
-	  don't need to choose this to run the Radeon in plain VGA mode.
-
-	  There is a product page at
-	  http://products.amd.com/en-us/GraphicCardResult.aspx
-
-config FB_RADEON_I2C
-	bool "DDC/I2C for ATI Radeon support"
-	depends on FB_RADEON
-	select FB_DDC
-	default y
-	help
-	  Say Y here if you want DDC/I2C support for your Radeon board. 
-
-config FB_RADEON_BACKLIGHT
-	bool "Support for backlight control"
-	depends on FB_RADEON
-	default y
-	help
-	  Say Y here if you want to control the backlight of your display.
-
-config FB_RADEON_DEBUG
-	bool "Lots of debug output from Radeon driver"
-	depends on FB_RADEON
-	default n
-	help
-	  Say Y here if you want the Radeon driver to output all sorts
-	  of debugging information to provide to the maintainer when
-	  something goes wrong.
-
-config FB_ATY128
-	tristate "ATI Rage128 display support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
-	select FB_MACMODES if PPC_PMAC
-	help
-	  This driver supports graphics boards with the ATI Rage128 chips.
-	  Say Y if you have such a graphics board and read
-	  <file:Documentation/fb/aty128fb.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aty128fb.
-
-config FB_ATY128_BACKLIGHT
-	bool "Support for backlight control"
-	depends on FB_ATY128
-	default y
-	help
-	  Say Y here if you want to control the backlight of your display.
-
-config FB_ATY
-	tristate "ATI Mach64 display support" if PCI || ATARI
-	depends on FB && !SPARC32
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_BACKLIGHT if FB_ATY_BACKLIGHT
-	select FB_MACMODES if PPC
-	help
-	  This driver supports graphics boards with the ATI Mach64 chips.
-	  Say Y if you have such a graphics board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called atyfb.
-
-config FB_ATY_CT
-	bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
-	depends on PCI && FB_ATY
-	default y if SPARC64 && PCI
-	help
-	  Say Y here to support use of ATI's 64-bit Rage boards (or other
-	  boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
-	  framebuffer device.  The ATI product support page for these boards
-	  is at <http://support.ati.com/products/pc/mach64/mach64.html>.
-
-config FB_ATY_GENERIC_LCD
-	bool "Mach64 generic LCD support"
-	depends on FB_ATY_CT
-	help
-	  Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
-	  Rage XC, or Rage XL chipset.
-
-config FB_ATY_GX
-	bool "Mach64 GX support" if PCI
-	depends on FB_ATY
-	default y if ATARI
-	help
-	  Say Y here to support use of the ATI Mach64 Graphics Expression
-	  board (or other boards based on the Mach64 GX chipset) as a
-	  framebuffer device.  The ATI product support page for these boards
-	  is at
-	  <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
-
-config FB_ATY_BACKLIGHT
-	bool "Support for backlight control"
-	depends on FB_ATY
-	default y
-	help
-	  Say Y here if you want to control the backlight of your display.
-
-config FB_S3
-	tristate "S3 Trio/Virge support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_TILEBLITTING
-	select FB_SVGALIB
-	select VGASTATE
-	select FONT_8x16 if FRAMEBUFFER_CONSOLE
-	---help---
-	  Driver for graphics boards with S3 Trio / S3 Virge chip.
-
-config FB_S3_DDC
-	bool "DDC for S3 support"
-	depends on FB_S3
-	select FB_DDC
-	default y
-	help
-	  Say Y here if you want DDC support for your S3 graphics card.
-
-config FB_SAVAGE
-	tristate "S3 Savage support"
-	depends on FB && PCI
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select VGASTATE
-	help
-	  This driver supports notebooks and computers with S3 Savage PCI/AGP
-	  chips.
-
-	  Say Y if you have such a graphics card.
-
-	  To compile this driver as a module, choose M here; the module
-	  will be called savagefb.
-
-config FB_SAVAGE_I2C
-       bool "Enable DDC2 Support"
-       depends on FB_SAVAGE
-       select FB_DDC
-       help
-	  This enables I2C support for S3 Savage Chipsets.  This is used
-	  only for getting EDID information from the attached display
-	  allowing for robust video mode handling and switching.
-
-	  Because fbdev-2.6 requires that drivers must be able to
-	  independently validate video mode parameters, you should say Y
-	  here.
-
-config FB_SAVAGE_ACCEL
-       bool "Enable Console Acceleration"
-       depends on FB_SAVAGE
-       default n
-       help
-          This option will compile in console acceleration support. If
-          the resulting framebuffer console has bothersome glitches, then
-          choose N here.
-
-config FB_SIS
-	tristate "SiS/XGI display support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_BOOT_VESA_SUPPORT if FB_SIS = y
-	help
-	  This is the frame buffer device driver for the SiS 300, 315, 330
-	  and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
-	  Specs available at <http://www.sis.com> and <http://www.xgitech.com>.
-
-	  To compile this driver as a module, choose M here; the module
-	  will be called sisfb.
-
-config FB_SIS_300
-	bool "SiS 300 series support"
-	depends on FB_SIS
-	help
-	  Say Y here to support use of the SiS 300/305, 540, 630 and 730.
-
-config FB_SIS_315
-	bool "SiS 315/330/340 series and XGI support"
-	depends on FB_SIS
-	help
-	  Say Y here to support use of the SiS 315, 330 and 340 series
-	  (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
-	  as XGI V3XT, V5, V8 and Z7.
-
-config FB_VIA
-       tristate "VIA UniChrome (Pro) and Chrome9 display support"
-       depends on FB && PCI && X86
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       select I2C_ALGOBIT
-       select I2C
-       select GPIOLIB
-       help
-	  This is the frame buffer device driver for Graphics chips of VIA
-	  UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
-	  CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
- 	  /P4M900,VX800)
-	  Say Y if you have a VIA UniChrome graphics board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called viafb.
-
-if FB_VIA
-
-config FB_VIA_DIRECT_PROCFS
-	bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
-	depends on FB_VIA
-	default n
-	help
-	  Allow direct hardware access to some output registers via procfs.
-	  This is dangerous but may provide the only chance to get the
-	  correct output device configuration.
-	  Its use is strongly discouraged.
-
-config FB_VIA_X_COMPATIBILITY
-	bool "X server compatibility"
-	depends on FB_VIA
-	default n
-	help
-	  This option reduces the functionality (power saving, ...) of the
-	  framebuffer to avoid negative impact on the OpenChrome X server.
-	  If you use any X server other than fbdev you should enable this
-	  otherwise it should be safe to disable it and allow using all
-	  features.
-
-endif
-
-config FB_NEOMAGIC
-	tristate "NeoMagic display support"
-	depends on FB && PCI
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select VGASTATE
-	help
-	  This driver supports notebooks with NeoMagic PCI chips.
-	  Say Y if you have such a graphics card. 
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called neofb.
-
-config FB_KYRO
-	tristate "IMG Kyro support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
-	  graphics board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called kyrofb.
-
-config FB_3DFX
-	tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
-	depends on FB && PCI
-	select FB_CFB_IMAGEBLIT
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_MODE_HELPERS
-	help
-	  This driver supports graphics boards with the 3Dfx Banshee,
-	  Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
-	  such a graphics board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called tdfxfb.
-
-config FB_3DFX_ACCEL
-	bool "3Dfx Acceleration functions"
-	depends on FB_3DFX
-	---help---
-	This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
-	device driver with acceleration functions.
-
-config FB_3DFX_I2C
-	bool "Enable DDC/I2C support"
-	depends on FB_3DFX
-	select FB_DDC
-	default y
-	help
-	  Say Y here if you want DDC/I2C support for your 3dfx Voodoo3.
-
-config FB_VOODOO1
-	tristate "3Dfx Voodoo Graphics (sst1) support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or 
-	  Voodoo2 (cvg) based graphics card.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sstfb.
-
-	  WARNING: Do not use any application that uses the 3D engine
-	  (namely glide) while using this driver.
-	  Please read the <file:Documentation/fb/sstfb.txt> for supported
-	  options and other important info  support.
-
-config FB_VT8623
-	tristate "VIA VT8623 support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_TILEBLITTING
-	select FB_SVGALIB
-	select VGASTATE
-	select FONT_8x16 if FRAMEBUFFER_CONSOLE
-	---help---
-	  Driver for CastleRock integrated graphics core in the
-	  VIA VT8623 [Apollo CLE266] chipset.
-
-config FB_TRIDENT
-	tristate "Trident/CyberXXX/CyberBlade support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  This is the frame buffer device driver for Trident PCI/AGP chipsets.
-	  Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
-	  and Blade XP.
-	  There are also integrated versions of these chips called CyberXXXX,
-	  CyberImage or CyberBlade. These chips are mostly found in laptops
-	  but also on some motherboards including early VIA EPIA motherboards.
-	  For more information, read <file:Documentation/fb/tridentfb.txt>
-
-	  Say Y if you have such a graphics board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called tridentfb.
-
-config FB_ARK
-	tristate "ARK 2000PV support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_TILEBLITTING
-	select FB_SVGALIB
-	select VGASTATE
-	select FONT_8x16 if FRAMEBUFFER_CONSOLE
-	---help---
-	  Driver for PCI graphics boards with ARK 2000PV chip
-	  and ICS 5342 RAMDAC.
-
-config FB_PM3
-	tristate "Permedia3 support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the 3DLabs Permedia3
-	  chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
-	  similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
-	  and maybe other boards.
-
-config FB_CARMINE
-	tristate "Fujitsu carmine frame buffer support"
-	depends on FB && PCI
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Fujitsu Carmine chip.
-	  The driver provides two independent frame buffer devices.
-
-choice
-	depends on FB_CARMINE
-	prompt "DRAM timing"
-	default FB_CARMINE_DRAM_EVAL
-
-config FB_CARMINE_DRAM_EVAL
-	bool "Eval board timings"
-	help
-	  Use timings which work on the eval card.
-
-config CARMINE_DRAM_CUSTOM
-	bool "Custom board timings"
-	help
-	  Use custom board timings.
-endchoice
-
-config FB_AU1100
-	bool "Au1100 LCD Driver"
-	depends on (FB = y) && MIPS_ALCHEMY
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the framebuffer driver for the AMD Au1100 SOC.  It can drive
-	  various panels and CRTs by passing in kernel cmd line option
-	  au1100fb:panel=<name>.
-
-config FB_AU1200
-	bool "Au1200/Au1300 LCD Driver"
-	depends on (FB = y) && MIPS_ALCHEMY
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	help
-	  This is the framebuffer driver for the Au1200/Au1300 SOCs.
-	  It can drive various panels and CRTs by passing in kernel cmd line
-	  option au1200fb:panel=<name>.
-
-config FB_VT8500
-	bool "VIA VT8500 framebuffer support"
-	depends on (FB = y) && ARM && ARCH_VT8500
-	select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
-	select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
-	select FB_SYS_IMAGEBLIT
-	select FB_MODE_HELPERS
-	select VIDEOMODE_HELPERS
-	help
-	  This is the framebuffer driver for VIA VT8500 integrated LCD
-	  controller.
-
-config FB_WM8505
-	bool "Wondermedia WM8xxx-series frame buffer support"
-	depends on (FB = y) && ARM && ARCH_VT8500
-	select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
-	select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
-	select FB_SYS_IMAGEBLIT
-	select FB_MODE_HELPERS
-	select VIDEOMODE_HELPERS
-	help
-	  This is the framebuffer driver for WonderMedia WM8xxx-series
-	  integrated LCD controller. This driver covers the WM8505, WM8650
-	  and WM8850 SoCs.
-
-config FB_WMT_GE_ROPS
-	bool "VT8500/WM8xxx accelerated raster ops support"
-	depends on (FB = y) && (FB_VT8500 || FB_WM8505)
-	default n
-	help
-	  This adds support for accelerated raster operations on the
-	  VIA VT8500 and Wondermedia 85xx series SoCs.
-
-source "drivers/video/geode/Kconfig"
-
-config FB_HIT
-	tristate "HD64461 Frame Buffer support"
-	depends on FB && HD64461
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This is the frame buffer device driver for the Hitachi HD64461 LCD
-	  frame buffer card.
-
-config FB_PMAG_AA
-	bool "PMAG-AA TURBOchannel framebuffer support"
-	depends on (FB = y) && TC
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
-	help
-	  Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1)
-	  used mainly in the MIPS-based DECstation series.
-
-config FB_PMAG_BA
-	tristate "PMAG-BA TURBOchannel framebuffer support"
-	depends on FB && TC
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
-	help
-	  Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8)
-	  used mainly in the MIPS-based DECstation series.
-
-config FB_PMAGB_B
-	tristate "PMAGB-B TURBOchannel framebuffer support"
-	depends on FB && TC
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
-	help
-	  Support for the PMAGB-B TURBOchannel framebuffer card used mainly
-	  in the MIPS-based DECstation series. The card is currently only
-	  supported in 1280x1024x8 mode.
-
-config FB_MAXINE
-	bool "Maxine (Personal DECstation) onboard framebuffer support"
-	depends on (FB = y) && MACH_DECSTATION
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
-	help
-	  Support for the onboard framebuffer (1024x768x8) in the Personal
-	  DECstation series (Personal DECstation 5000/20, /25, /33, /50,
-	  Codename "Maxine").
-
-config FB_G364
-	bool "G364 frame buffer support"
-	depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700)
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
-	help
-	  The G364 driver is the framebuffer used in MIPS Magnum 4000 and
-	  Olivetti M700-10 systems.
-
-config FB_68328
-	bool "Motorola 68328 native frame buffer support"
-	depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328)
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
-	help
-	  Say Y here if you want to support the built-in frame buffer of
-	  the Motorola 68328 CPU family.
-
-config FB_PXA168
-	tristate "PXA168/910 LCD framebuffer support"
-	depends on FB && (CPU_PXA168 || CPU_PXA910)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for the built-in LCD controller in the Marvell
-	  MMP processor.
-
-config FB_PXA
-	tristate "PXA LCD framebuffer support"
-	depends on FB && ARCH_PXA
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for the built-in LCD controller in the Intel
-	  PXA2x0 processor.
-
-	  This driver is also available as a module ( = code which can be
-	  inserted and removed from the running kernel whenever you want). The
-	  module will be called pxafb. If you want to compile it as a module,
-	  say M here and read <file:Documentation/kbuild/modules.txt>.
-
-	  If unsure, say N.
-
-config FB_PXA_OVERLAY
-	bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer"
-	default n
-	depends on FB_PXA && (PXA27x || PXA3xx)
-
-config FB_PXA_SMARTPANEL
-	bool "PXA Smartpanel LCD support"
-	default n
-	depends on FB_PXA
-
-config FB_PXA_PARAMETERS
-	bool "PXA LCD command line parameters"
-	default n
-	depends on FB_PXA
-	---help---
-	  Enable the use of kernel command line or module parameters
-	  to configure the physical properties of the LCD panel when
-	  using the PXA LCD driver.
-
-	  This option allows you to override the panel parameters
-	  supplied by the platform in order to support multiple
-	  different models of flatpanel. If you will only be using a
-	  single model of flatpanel then you can safely leave this
-	  option disabled.
-
-	  <file:Documentation/fb/pxafb.txt> describes the available parameters.
-
-config PXA3XX_GCU
-	tristate "PXA3xx 2D graphics accelerator driver"
-	depends on FB_PXA
-	help
-	  Kernelspace driver for the 2D graphics controller unit (GCU)
-	  found on PXA3xx processors. There is a counterpart driver in the
-	  DirectFB suite, see http://www.directfb.org/
-
-	  If you compile this as a module, it will be called pxa3xx_gcu.
-
-config FB_MBX
-	tristate "2700G LCD framebuffer support"
-	depends on FB && ARCH_PXA
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Framebuffer driver for the Intel 2700G (Marathon) Graphics
-	  Accelerator
-
-config FB_MBX_DEBUG
-       bool "Enable debugging info via debugfs"
-       depends on FB_MBX && DEBUG_FS
-       default n
-       ---help---
-         Enable this if you want debugging information using the debug
-         filesystem (debugfs)
-
-         If unsure, say N.
-
-config FB_FSL_DIU
-	tristate "Freescale DIU framebuffer support"
-	depends on FB && FSL_SOC
-	select FB_MODE_HELPERS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select PPC_LIB_RHEAP
-	---help---
-	  Framebuffer driver for the Freescale SoC DIU
-
-config FB_W100
-	tristate "W100 frame buffer support"
-	depends on FB && ARCH_PXA
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
-	  It can also drive the w3220 chip found on iPAQ hx4700.
-
-	  This driver is also available as a module ( = code which can be
-	  inserted and removed from the running kernel whenever you want). The
-	  module will be called w100fb. If you want to compile it as a module,
-	  say M here and read <file:Documentation/kbuild/modules.txt>.
-
-	  If unsure, say N.
-
-config FB_SH_MOBILE_LCDC
-	tristate "SuperH Mobile LCDC framebuffer support"
-	depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	select FB_BACKLIGHT
-	select SH_MIPI_DSI if SH_LCD_MIPI_DSI
-	---help---
-	  Frame buffer driver for the on-chip SH-Mobile LCD controller.
-
-config FB_SH_MOBILE_HDMI
-	tristate "SuperH Mobile HDMI controller support"
-	depends on FB_SH_MOBILE_LCDC
-	select FB_MODE_HELPERS
-	select SOUND
-	select SND
-	select SND_SOC
-	---help---
-	  Driver for the on-chip SH-Mobile HDMI controller.
-
-config FB_TMIO
-	tristate "Toshiba Mobile IO FrameBuffer support"
-	depends on FB && MFD_CORE
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for the Toshiba Mobile IO integrated as found
-	  on the Sharp SL-6000 series
-
-	  This driver is also available as a module ( = code which can be
-	  inserted and removed from the running kernel whenever you want). The
-	  module will be called tmiofb. If you want to compile it as a module,
-	  say M here and read <file:Documentation/kbuild/modules.txt>.
-
-	  If unsure, say N.
-
-config FB_TMIO_ACCELL
-	bool "tmiofb acceleration"
-	depends on FB_TMIO
-	default y
-
-config FB_S3C
-	tristate "Samsung S3C framebuffer support"
-	depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \
-		ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for the built-in FB controller in the Samsung
-	  SoC line from the S3C2443 onwards, including the S3C2416, S3C2450,
-	  and the S3C64XX series such as the S3C6400 and S3C6410.
-
-	  These chips all have the same basic framebuffer design with the
-	  actual capabilities depending on the chip. For instance the S3C6400
-	  and S3C6410 support 4 hardware windows whereas the S3C24XX series
-	  currently only have two.
-
-	  Currently the support is only for the S3C6400 and S3C6410 SoCs.
-
-config FB_S3C_DEBUG_REGWRITE
-       bool "Debug register writes"
-       depends on FB_S3C
-       ---help---
-         Show all register writes via pr_debug()
-
-config FB_S3C2410
-	tristate "S3C2410 LCD framebuffer support"
-	depends on FB && ARCH_S3C24XX
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for the built-in LCD controller in the Samsung
-	  S3C2410 processor.
-
-	  This driver is also available as a module ( = code which can be
-	  inserted and removed from the running kernel whenever you want). The
-	  module will be called s3c2410fb. If you want to compile it as a module,
-	  say M here and read <file:Documentation/kbuild/modules.txt>.
-
-	  If unsure, say N.
-config FB_S3C2410_DEBUG
-	bool "S3C2410 lcd debug messages"
-	depends on FB_S3C2410
-	help
-	  Turn on debugging messages. Note that you can set/unset at run time
-	  through sysfs
-
-config FB_NUC900
-        bool "NUC900 LCD framebuffer support"
-        depends on FB && ARCH_W90X900
-        select FB_CFB_FILLRECT
-        select FB_CFB_COPYAREA
-        select FB_CFB_IMAGEBLIT
-        ---help---
-          Frame buffer driver for the built-in LCD controller in the Nuvoton
-          NUC900 processor
-
-config GPM1040A0_320X240
-        bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
-        depends on FB_NUC900
-
-config FB_SM501
-	tristate "Silicon Motion SM501 framebuffer support"
-	depends on FB && MFD_SM501
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for the CRT and LCD controllers in the Silicon
-	  Motion SM501.
-
-	  This driver is also available as a module ( = code which can be
-	  inserted and removed from the running kernel whenever you want). The
-	  module will be called sm501fb. If you want to compile it as a module,
-	  say M here and read <file:Documentation/kbuild/modules.txt>.
-
-	  If unsure, say N.
-
-config FB_SMSCUFX
-	tristate "SMSC UFX6000/7000 USB Framebuffer support"
-	depends on FB && USB
-	select FB_MODE_HELPERS
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	---help---
-	  This is a kernel framebuffer driver for SMSC UFX USB devices.
-	  Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
-	  mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000
-	  (USB 3.0) devices.
-	  To compile as a module, choose M here: the module name is smscufx.
-
-config FB_UDL
-	tristate "Displaylink USB Framebuffer support"
-	depends on FB && USB
-	select FB_MODE_HELPERS
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	---help---
-	  This is a kernel framebuffer driver for DisplayLink USB devices.
-	  Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
-	  mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
-	  To compile as a module, choose M here: the module name is udlfb.
-
-config FB_IBM_GXT4500
-	tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors"
-	depends on FB && PPC
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Say Y here to enable support for the IBM GXT4000P/6000P and
-	  GXT4500P/6500P display adaptor based on Raster Engine RC1000,
-	  found on some IBM System P (pSeries) machines. This driver
-	  doesn't use Geometry Engine GT1000.
-
-config FB_PS3
-	tristate "PS3 GPU framebuffer driver"
-	depends on FB && PS3_PS3AV
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
-	---help---
-	  Include support for the virtual frame buffer in the PS3 platform.
-
-config FB_PS3_DEFAULT_SIZE_M
-	int "PS3 default frame buffer size (in MiB)"
-	depends on FB_PS3
-	default 9
-	---help---
-	  This is the default size (in MiB) of the virtual frame buffer in
-	  the PS3.
-	  The default value can be overridden on the kernel command line
-	  using the "ps3fb" option (e.g. "ps3fb=9M");
-
-config FB_XILINX
-	tristate "Xilinx frame buffer support"
-	depends on FB && (XILINX_VIRTEX || MICROBLAZE || ARCH_ZYNQ)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Include support for the Xilinx ML300/ML403 reference design
-	  framebuffer. ML300 carries a 640*480 LCD display on the board,
-	  ML403 uses a standard DB15 VGA connector.
-
-config FB_GOLDFISH
-	tristate "Goldfish Framebuffer"
-	depends on FB && HAS_DMA
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Framebuffer driver for Goldfish Virtual Platform
-
-config FB_COBALT
-	tristate "Cobalt server LCD frame buffer support"
-	depends on FB && (MIPS_COBALT || MIPS_SEAD3)
-
-config FB_SH7760
-	bool "SH7760/SH7763/SH7720/SH7721 LCDC support"
-	depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
-		|| CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Support for the SH7760/SH7763/SH7720/SH7721 integrated
-	  (D)STN/TFT LCD Controller.
-	  Supports display resolutions up to 1024x1024 pixel, grayscale and
-	  color operation, with depths ranging from 1 bpp to 8 bpp monochrome
-	  and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
-	  panels <= 320 pixel horizontal resolution.
-
-config FB_DA8XX
-	tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support"
-	depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_CFB_REV_PIXELS_IN_BYTE
-	select FB_MODE_HELPERS
-	select VIDEOMODE_HELPERS
-	---help---
-	  This is the frame buffer device driver for the TI LCD controller
-	  found on DA8xx/OMAP-L1xx/AM335x SoCs.
-	  If unsure, say N.
-
-config FB_VIRTUAL
-	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
-	depends on FB
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	---help---
-	  This is a `virtual' frame buffer device. It operates on a chunk of
-	  unswappable kernel memory instead of on the memory of a graphics
-	  board. This means you cannot see any output sent to this frame
-	  buffer device, while it does consume precious memory. The main use
-	  of this frame buffer device is testing and debugging the frame
-	  buffer subsystem. Do NOT enable it for normal systems! To protect
-	  the innocent, it has to be enabled explicitly at boot time using the
-	  kernel option `video=vfb:'.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vfb. In order to load it, you must use
-	  the vfb_enable=1 option.
-
-	  If unsure, say N.
-
-config XEN_FBDEV_FRONTEND
-	tristate "Xen virtual frame buffer support"
-	depends on FB && XEN
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
-	select XEN_XENBUS_FRONTEND
-	default y
-	help
-	  This driver implements the front-end of the Xen virtual
-	  frame buffer driver.  It communicates with a back-end
-	  in another domain.
-
-config FB_METRONOME
-	tristate "E-Ink Metronome/8track controller support"
-	depends on FB
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	help
-	  This driver implements support for the E-Ink Metronome
-	  controller. The pre-release name for this device was 8track
-	  and could also have been called by some vendors as PVI-nnnn.
-
-config FB_MB862XX
-	tristate "Fujitsu MB862xx GDC support"
-	depends on FB
-	depends on PCI || (OF && PPC)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers.
-
-choice
-	prompt "GDC variant"
-	depends on FB_MB862XX
-
-config FB_MB862XX_PCI_GDC
-	bool "Carmine/Coral-P(A) GDC"
-	depends on PCI
-	---help---
-	  This enables framebuffer support for Fujitsu Carmine/Coral-P(A)
-	  PCI graphics controller devices.
-
-config FB_MB862XX_LIME
-	bool "Lime GDC"
-	depends on OF && PPC
-	select FB_FOREIGN_ENDIAN
-	select FB_LITTLE_ENDIAN
-	---help---
-	  Framebuffer support for Fujitsu Lime GDC on host CPU bus.
-
-endchoice
-
-config FB_MB862XX_I2C
-	bool "Support I2C bus on MB862XX GDC"
-	depends on FB_MB862XX && I2C
-	default y
-	help
-	  Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter
-	  driver to support accessing I2C devices on controller's I2C bus.
-	  These are usually some video decoder chips.
-
-config FB_EP93XX
-	tristate "EP93XX frame buffer support"
-	depends on FB && ARCH_EP93XX
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Framebuffer driver for the Cirrus Logic EP93XX series of processors.
-	  This driver is also available as a module. The module will be called
-	  ep93xx-fb.
-
-config FB_PRE_INIT_FB
-	bool "Don't reinitialize, use bootloader's GDC/Display configuration"
-	depends on FB && FB_MB862XX_LIME
-	---help---
-	  Select this option if display contents should be inherited as set by
-	  the bootloader.
-
-config FB_MSM
-	tristate "MSM Framebuffer support"
-	depends on FB && ARCH_MSM
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-
-config FB_MX3
-	tristate "MX3 Framebuffer support"
-	depends on FB && MX3_IPU
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	default y
-	help
-	  This is a framebuffer device for the i.MX31 LCD Controller. So
-	  far only synchronous displays are supported. If you plan to use
-	  an LCD display with your i.MX31 system, say Y here.
-
-config FB_BROADSHEET
-	tristate "E-Ink Broadsheet/Epson S1D13521 controller support"
-	depends on FB
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	help
-	  This driver implements support for the E-Ink Broadsheet
-	  controller. The release name for this device was Epson S1D13521
-	  and could also have been called by other names when coupled with
-	  a bridge adapter.
-
-config FB_AUO_K190X
-	tristate "AUO-K190X EPD controller support"
-	depends on FB
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	help
-	  Provides support for epaper controllers from the K190X series
-	  of AUO. These controllers can be used to drive epaper displays
-	  from Sipix.
-
-	  This option enables the common support, shared by the individual
-	  controller drivers. You will also have to enable the driver
-	  for the controller type used in your device.
-
-config FB_AUO_K1900
-	tristate "AUO-K1900 EPD controller support"
-	depends on FB && FB_AUO_K190X
-	help
-	  This driver implements support for the AUO K1900 epd-controller.
-	  This controller can drive Sipix epaper displays but can only do
-	  serial updates, reducing the number of possible frames per second.
-
-config FB_AUO_K1901
-	tristate "AUO-K1901 EPD controller support"
-	depends on FB && FB_AUO_K190X
-	help
-	  This driver implements support for the AUO K1901 epd-controller.
-	  This controller can drive Sipix epaper displays and supports
-	  concurrent updates, making higher frames per second possible.
-
-config FB_JZ4740
-	tristate "JZ4740 LCD framebuffer support"
-	depends on FB && MACH_JZ4740
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	help
-	  Framebuffer support for the JZ4740 SoC.
-
-config FB_MXS
-	tristate "MXS LCD framebuffer support"
-	depends on FB && ARCH_MXS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	select FB_MODE_HELPERS
-	select VIDEOMODE_HELPERS
-	help
-	  Framebuffer support for the MXS SoC.
-
-config FB_PUV3_UNIGFX
-	tristate "PKUnity v3 Unigfx framebuffer support"
-	depends on FB && UNICORE32 && ARCH_PUV3
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	help
-	  Choose this option if you want to use the Unigfx device as a
-	  framebuffer device. Without the support of PCI & AGP.
-
-config FB_HYPERV
-	tristate "Microsoft Hyper-V Synthetic Video support"
-	depends on FB && HYPERV
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
-
-config FB_SIMPLE
-	bool "Simple framebuffer support"
-	depends on (FB = y)
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  Say Y if you want support for a simple frame-buffer.
-
-	  This driver assumes that the display hardware has been initialized
-	  before the kernel boots, and the kernel will simply render to the
-	  pre-allocated frame buffer surface.
-
-	  Configuration re: surface address, size, and format must be provided
-	  through device tree, or plain old platform data.
-
-source "drivers/video/omap/Kconfig"
-source "drivers/video/omap2/Kconfig"
-source "drivers/video/exynos/Kconfig"
-source "drivers/video/mmp/Kconfig"
-source "drivers/video/backlight/Kconfig"
-
 if VT
 	source "drivers/video/console/Kconfig"
 endif
 
 if FB || SGI_NEWPORT_CONSOLE
 	source "drivers/video/logo/Kconfig"
-endif
 
-config FB_SH_MOBILE_MERAM
-	tristate "SuperH Mobile MERAM read ahead support"
-	depends on (SUPERH || ARCH_SHMOBILE)
-	select GENERIC_ALLOCATOR
-	---help---
-	  Enable MERAM support for the SuperH controller.
-
-	  This will allow for caching of the framebuffer to provide more
-	  reliable access under heavy main memory bus traffic situations.
-	  Up to 4 memory channels can be configured, allowing 4 RGB or
-	  2 YCbCr framebuffers to be configured.
+endif
 
-config FB_SSD1307
-	tristate "Solomon SSD1307 framebuffer support"
-	depends on FB && I2C
-	depends on OF
-	depends on GPIOLIB
-	select FB_SYS_FOPS
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_DEFERRED_IO
-	select PWM
-	help
-	  This driver implements support for the Solomon SSD1307
-	  OLED controller over I2C.
 
 endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 1be26fe10592..9ad3c17d6456 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,175 +1,11 @@
-# Makefile for the Linux video drivers.
-# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net>
-# Rewritten to use lists instead of if-statements.
-
-# Each configuration option enables a list of files.
-
 obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-$(CONFIG_HDMI)                += hdmi.o
-obj-y                             += fb_notify.o
-obj-$(CONFIG_FB)                  += fb.o
-fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
-                                     modedb.o fbcvt.o
-fb-objs                           := $(fb-y)
 
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
 obj-y				  += backlight/
 
-obj-$(CONFIG_EXYNOS_VIDEO)     += exynos/
-
-obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
-obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
-obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
-obj-$(CONFIG_FB_SYS_FILLRECT)  += sysfillrect.o
-obj-$(CONFIG_FB_SYS_COPYAREA)  += syscopyarea.o
-obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
-obj-$(CONFIG_FB_SYS_FOPS)      += fb_sys_fops.o
-obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
-obj-$(CONFIG_FB_MACMODES)      += macmodes.o
-obj-$(CONFIG_FB_DDC)           += fb_ddc.o
-obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
-obj-$(CONFIG_FB_WMT_GE_ROPS)   += wmt_ge_rops.o
-
-# Hardware specific drivers go first
-obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
-obj-$(CONFIG_FB_ARC)              += arcfb.o
-obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
-obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
-obj-$(CONFIG_FB_GRVGA)            += grvga.o
-obj-$(CONFIG_FB_PM2)              += pm2fb.o
-obj-$(CONFIG_FB_PM3)		  += pm3fb.o
-
-obj-$(CONFIG_FB_I740)		  += i740fb.o
-obj-$(CONFIG_FB_MATROX)		  += matrox/
-obj-$(CONFIG_FB_RIVA)		  += riva/
-obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
-obj-$(CONFIG_FB_ATY)		  += aty/ macmodes.o
-obj-$(CONFIG_FB_ATY128)		  += aty/ macmodes.o
-obj-$(CONFIG_FB_RADEON)		  += aty/
-obj-$(CONFIG_FB_SIS)		  += sis/
-obj-$(CONFIG_FB_VIA)		  += via/
-obj-$(CONFIG_FB_KYRO)             += kyro/
-obj-$(CONFIG_FB_SAVAGE)		  += savage/
-obj-$(CONFIG_FB_GEODE)		  += geode/
-obj-$(CONFIG_FB_MBX)		  += mbx/
-obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o
-obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
-obj-$(CONFIG_FB_CONTROL)          += controlfb.o
-obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
-obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
-obj-$(CONFIG_FB_CT65550)          += chipsfb.o
-obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
-obj-$(CONFIG_FB_FM2)              += fm2fb.o
-obj-$(CONFIG_FB_VT8623)           += vt8623fb.o
-obj-$(CONFIG_FB_TRIDENT)          += tridentfb.o
-obj-$(CONFIG_FB_LE80578)          += vermilion/
-obj-$(CONFIG_FB_S3)               += s3fb.o
-obj-$(CONFIG_FB_ARK)              += arkfb.o
-obj-$(CONFIG_FB_STI)              += stifb.o
-obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
-obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
-obj-$(CONFIG_FB_CG3)              += cg3.o sbuslib.o
-obj-$(CONFIG_FB_BW2)              += bw2.o sbuslib.o
-obj-$(CONFIG_FB_CG14)             += cg14.o sbuslib.o
-obj-$(CONFIG_FB_P9100)            += p9100.o sbuslib.o
-obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o
-obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
-obj-$(CONFIG_FB_ACORN)            += acornfb.o
-obj-$(CONFIG_FB_ATARI)            += atafb.o c2p_iplan2.o atafb_mfb.o \
-                                     atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
-obj-$(CONFIG_FB_MAC)              += macfb.o
-obj-$(CONFIG_FB_HECUBA)           += hecubafb.o
-obj-$(CONFIG_FB_N411)             += n411.o
-obj-$(CONFIG_FB_HGA)              += hgafb.o
-obj-$(CONFIG_FB_XVR500)           += sunxvr500.o
-obj-$(CONFIG_FB_XVR2500)          += sunxvr2500.o
-obj-$(CONFIG_FB_XVR1000)          += sunxvr1000.o
-obj-$(CONFIG_FB_IGA)              += igafb.o
-obj-$(CONFIG_FB_APOLLO)           += dnfb.o
-obj-$(CONFIG_FB_Q40)              += q40fb.o
-obj-$(CONFIG_FB_TGA)              += tgafb.o
-obj-$(CONFIG_FB_HP300)            += hpfb.o
-obj-$(CONFIG_FB_G364)             += g364fb.o
-obj-$(CONFIG_FB_EP93XX)		  += ep93xx-fb.o
-obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
-obj-$(CONFIG_FB_HIT)              += hitfb.o
-obj-$(CONFIG_FB_ATMEL)		  += atmel_lcdfb.o
-obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
-obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
-obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o
-obj-$(CONFIG_FB_GOLDFISH)         += goldfishfb.o
-obj-$(CONFIG_FB_68328)            += 68328fb.o
-obj-$(CONFIG_FB_GBE)              += gbefb.o
-obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o
-obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
-obj-$(CONFIG_FB_PXA)		  += pxafb.o
-obj-$(CONFIG_FB_PXA168)		  += pxa168fb.o
-obj-$(CONFIG_PXA3XX_GCU)	  += pxa3xx-gcu.o
-obj-$(CONFIG_MMP_DISP)           += mmp/
-obj-$(CONFIG_FB_W100)		  += w100fb.o
-obj-$(CONFIG_FB_TMIO)		  += tmiofb.o
-obj-$(CONFIG_FB_AU1100)		  += au1100fb.o
-obj-$(CONFIG_FB_AU1200)		  += au1200fb.o
-obj-$(CONFIG_FB_VT8500)		  += vt8500lcdfb.o
-obj-$(CONFIG_FB_WM8505)		  += wm8505fb.o
-obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o
-obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o
-obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o
-obj-$(CONFIG_FB_MAXINE)		  += maxinefb.o
-obj-$(CONFIG_FB_METRONOME)        += metronomefb.o
-obj-$(CONFIG_FB_BROADSHEET)       += broadsheetfb.o
-obj-$(CONFIG_FB_AUO_K190X)	  += auo_k190x.o
-obj-$(CONFIG_FB_AUO_K1900)	  += auo_k1900fb.o
-obj-$(CONFIG_FB_AUO_K1901)	  += auo_k1901fb.o
-obj-$(CONFIG_FB_S1D13XXX)	  += s1d13xxxfb.o
-obj-$(CONFIG_FB_SH7760)		  += sh7760fb.o
-obj-$(CONFIG_FB_IMX)              += imxfb.o
-obj-$(CONFIG_FB_S3C)		  += s3c-fb.o
-obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.o
-obj-$(CONFIG_FB_FSL_DIU)	  += fsl-diu-fb.o
-obj-$(CONFIG_FB_COBALT)           += cobalt_lcdfb.o
-obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
-obj-$(CONFIG_FB_PS3)		  += ps3fb.o
-obj-$(CONFIG_FB_SM501)            += sm501fb.o
-obj-$(CONFIG_FB_UDL)		  += udlfb.o
-obj-$(CONFIG_FB_SMSCUFX)	  += smscufx.o
-obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
-obj-$(CONFIG_SH_MIPI_DSI)	  += sh_mipi_dsi.o
-obj-$(CONFIG_FB_SH_MOBILE_HDMI)	  += sh_mobile_hdmi.o
-obj-$(CONFIG_FB_SH_MOBILE_MERAM)  += sh_mobile_meram.o
-obj-$(CONFIG_FB_SH_MOBILE_LCDC)	  += sh_mobile_lcdcfb.o
-obj-$(CONFIG_FB_OMAP)             += omap/
-obj-y                             += omap2/
-obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
-obj-$(CONFIG_FB_CARMINE)          += carminefb.o
-obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
-obj-$(CONFIG_FB_MSM)              += msm/
-obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
-obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
-obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
-obj-$(CONFIG_FB_HYPERV)		  += hyperv_fb.o
-obj-$(CONFIG_FB_OPENCORES)	  += ocfb.o
-
-# Platform or fallback drivers go here
-obj-$(CONFIG_FB_UVESA)            += uvesafb.o
-obj-$(CONFIG_FB_VESA)             += vesafb.o
-obj-$(CONFIG_FB_EFI)              += efifb.o
-obj-$(CONFIG_FB_VGA16)            += vga16fb.o
-obj-$(CONFIG_FB_OF)               += offb.o
-obj-$(CONFIG_FB_BF537_LQ035)      += bf537-lq035.o
-obj-$(CONFIG_FB_BF54X_LQ043)	  += bf54x-lq043fb.o
-obj-$(CONFIG_FB_BFIN_LQ035Q1)     += bfin-lq035q1-fb.o
-obj-$(CONFIG_FB_BFIN_T350MCQB)	  += bfin-t350mcqb-fb.o
-obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
-obj-$(CONFIG_FB_MX3)		  += mx3fb.o
-obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
-obj-$(CONFIG_FB_MXS)		  += mxsfb.o
-obj-$(CONFIG_FB_SSD1307)	  += ssd1307fb.o
-obj-$(CONFIG_FB_SIMPLE)           += simplefb.o
-
-# the test framebuffer is last
-obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
+obj-y				  += fbdev/
 
 obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
 ifeq ($(CONFIG_OF),y)
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
deleted file mode 100644
index a305caea58ee..000000000000
--- a/drivers/video/acornfb.c
+++ /dev/null
@@ -1,1143 +0,0 @@
-/*
- *  linux/drivers/video/acornfb.c
- *
- *  Copyright (C) 1998-2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Frame buffer code for Acorn platforms
- *
- * NOTE: Most of the modes with X!=640 will disappear shortly.
- * NOTE: Startup setting of HS & VS polarity not supported.
- *       (do we need to support it if we're coming up in 640x480?)
- *
- * FIXME: (things broken by the "new improved" FBCON API)
- *  - Blanking 8bpp displays with VIDC
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/gfp.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/pgtable.h>
-
-#include "acornfb.h"
-
-/*
- * Default resolution.
- * NOTE that it has to be supported in the table towards
- * the end of this file.
- */
-#define DEFAULT_XRES	640
-#define DEFAULT_YRES	480
-#define DEFAULT_BPP	4
-
-/*
- * define this to debug the video mode selection
- */
-#undef DEBUG_MODE_SELECTION
-
-/*
- * Translation from RISC OS monitor types to actual
- * HSYNC and VSYNC frequency ranges.  These are
- * probably not right, but they're the best info I
- * have.  Allow 1% either way on the nominal for TVs.
- */
-#define NR_MONTYPES	6
-static struct fb_monspecs monspecs[NR_MONTYPES] = {
-	{	/* TV		*/
-		.hfmin	= 15469,
-		.hfmax	= 15781,
-		.vfmin	= 49,
-		.vfmax	= 51,
-	}, {	/* Multi Freq	*/
-		.hfmin	= 0,
-		.hfmax	= 99999,
-		.vfmin	= 0,
-		.vfmax	= 199,
-	}, {	/* Hi-res mono	*/
-		.hfmin	= 58608,
-		.hfmax	= 58608,
-		.vfmin	= 64,
-		.vfmax	= 64,
-	}, {	/* VGA		*/
-		.hfmin	= 30000,
-		.hfmax	= 70000,
-		.vfmin	= 60,
-		.vfmax	= 60,
-	}, {	/* SVGA		*/
-		.hfmin	= 30000,
-		.hfmax	= 70000,
-		.vfmin	= 56,
-		.vfmax	= 75,
-	}, {
-		.hfmin	= 30000,
-		.hfmax	= 70000,
-		.vfmin	= 60,
-		.vfmax	= 60,
-	}
-};
-
-static struct fb_info fb_info;
-static struct acornfb_par current_par;
-static struct vidc_timing current_vidc;
-
-extern unsigned int vram_size;	/* set by setup.c */
-
-#ifdef HAS_VIDC20
-#include <mach/acornfb.h>
-
-#define MAX_SIZE	2*1024*1024
-
-/* VIDC20 has a different set of rules from the VIDC:
- *  hcr  : must be multiple of 4
- *  hswr : must be even
- *  hdsr : must be even
- *  hder : must be even
- *  vcr  : >= 2, (interlace, must be odd)
- *  vswr : >= 1
- *  vdsr : >= 1
- *  vder : >= vdsr
- */
-static void acornfb_set_timing(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-	struct vidc_timing vidc;
-	u_int vcr, fsize;
-	u_int ext_ctl, dat_ctl;
-	u_int words_per_line;
-
-	memset(&vidc, 0, sizeof(vidc));
-
-	vidc.h_sync_width	= var->hsync_len - 8;
-	vidc.h_border_start	= vidc.h_sync_width + var->left_margin + 8 - 12;
-	vidc.h_display_start	= vidc.h_border_start + 12 - 18;
-	vidc.h_display_end	= vidc.h_display_start + var->xres;
-	vidc.h_border_end	= vidc.h_display_end + 18 - 12;
-	vidc.h_cycle		= vidc.h_border_end + var->right_margin + 12 - 8;
-	vidc.h_interlace	= vidc.h_cycle / 2;
-	vidc.v_sync_width	= var->vsync_len - 1;
-	vidc.v_border_start	= vidc.v_sync_width + var->upper_margin;
-	vidc.v_display_start	= vidc.v_border_start;
-	vidc.v_display_end	= vidc.v_display_start + var->yres;
-	vidc.v_border_end	= vidc.v_display_end;
-	vidc.control		= acornfb_default_control();
-
-	vcr = var->vsync_len + var->upper_margin + var->yres +
-	      var->lower_margin;
-
-	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-		vidc.v_cycle = (vcr - 3) / 2;
-		vidc.control |= VIDC20_CTRL_INT;
-	} else
-		vidc.v_cycle = vcr - 2;
-
-	switch (var->bits_per_pixel) {
-	case  1: vidc.control |= VIDC20_CTRL_1BPP;	break;
-	case  2: vidc.control |= VIDC20_CTRL_2BPP;	break;
-	case  4: vidc.control |= VIDC20_CTRL_4BPP;	break;
-	default:
-	case  8: vidc.control |= VIDC20_CTRL_8BPP;	break;
-	case 16: vidc.control |= VIDC20_CTRL_16BPP;	break;
-	case 32: vidc.control |= VIDC20_CTRL_32BPP;	break;
-	}
-
-	acornfb_vidc20_find_rates(&vidc, var);
-	fsize = var->vsync_len + var->upper_margin + var->lower_margin - 1;
-
-	if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
-		current_vidc = vidc;
-
-		vidc_writel(VIDC20_CTRL| vidc.control);
-		vidc_writel(0xd0000000 | vidc.pll_ctl);
-		vidc_writel(0x80000000 | vidc.h_cycle);
-		vidc_writel(0x81000000 | vidc.h_sync_width);
-		vidc_writel(0x82000000 | vidc.h_border_start);
-		vidc_writel(0x83000000 | vidc.h_display_start);
-		vidc_writel(0x84000000 | vidc.h_display_end);
-		vidc_writel(0x85000000 | vidc.h_border_end);
-		vidc_writel(0x86000000);
-		vidc_writel(0x87000000 | vidc.h_interlace);
-		vidc_writel(0x90000000 | vidc.v_cycle);
-		vidc_writel(0x91000000 | vidc.v_sync_width);
-		vidc_writel(0x92000000 | vidc.v_border_start);
-		vidc_writel(0x93000000 | vidc.v_display_start);
-		vidc_writel(0x94000000 | vidc.v_display_end);
-		vidc_writel(0x95000000 | vidc.v_border_end);
-		vidc_writel(0x96000000);
-		vidc_writel(0x97000000);
-	}
-
-	iomd_writel(fsize, IOMD_FSIZE);
-
-	ext_ctl = acornfb_default_econtrol();
-
-	if (var->sync & FB_SYNC_COMP_HIGH_ACT) /* should be FB_SYNC_COMP */
-		ext_ctl |= VIDC20_ECTL_HS_NCSYNC | VIDC20_ECTL_VS_NCSYNC;
-	else {
-		if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-			ext_ctl |= VIDC20_ECTL_HS_HSYNC;
-		else
-			ext_ctl |= VIDC20_ECTL_HS_NHSYNC;
-
-		if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-			ext_ctl |= VIDC20_ECTL_VS_VSYNC;
-		else
-			ext_ctl |= VIDC20_ECTL_VS_NVSYNC;
-	}
-
-	vidc_writel(VIDC20_ECTL | ext_ctl);
-
-	words_per_line = var->xres * var->bits_per_pixel / 32;
-
-	if (current_par.using_vram && info->fix.smem_len == 2048*1024)
-		words_per_line /= 2;
-
-	/* RiscPC doesn't use the VIDC's VRAM control. */
-	dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;
-
-	/* The data bus width is dependent on both the type
-	 * and amount of video memory.
-	 *     DRAM	32bit low
-	 * 1MB VRAM	32bit
-	 * 2MB VRAM	64bit
-	 */
-	if (current_par.using_vram && current_par.vram_half_sam == 2048)
-		dat_ctl |= VIDC20_DCTL_BUS_D63_0;
-	else
-		dat_ctl |= VIDC20_DCTL_BUS_D31_0;
-
-	vidc_writel(VIDC20_DCTL | dat_ctl);
-
-#ifdef DEBUG_MODE_SELECTION
-	printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
-	       var->yres, var->bits_per_pixel);
-	printk(KERN_DEBUG " H-cycle          : %d\n", vidc.h_cycle);
-	printk(KERN_DEBUG " H-sync-width     : %d\n", vidc.h_sync_width);
-	printk(KERN_DEBUG " H-border-start   : %d\n", vidc.h_border_start);
-	printk(KERN_DEBUG " H-display-start  : %d\n", vidc.h_display_start);
-	printk(KERN_DEBUG " H-display-end    : %d\n", vidc.h_display_end);
-	printk(KERN_DEBUG " H-border-end     : %d\n", vidc.h_border_end);
-	printk(KERN_DEBUG " H-interlace      : %d\n", vidc.h_interlace);
-	printk(KERN_DEBUG " V-cycle          : %d\n", vidc.v_cycle);
-	printk(KERN_DEBUG " V-sync-width     : %d\n", vidc.v_sync_width);
-	printk(KERN_DEBUG " V-border-start   : %d\n", vidc.v_border_start);
-	printk(KERN_DEBUG " V-display-start  : %d\n", vidc.v_display_start);
-	printk(KERN_DEBUG " V-display-end    : %d\n", vidc.v_display_end);
-	printk(KERN_DEBUG " V-border-end     : %d\n", vidc.v_border_end);
-	printk(KERN_DEBUG " Ext Ctrl  (C)    : 0x%08X\n", ext_ctl);
-	printk(KERN_DEBUG " PLL Ctrl  (D)    : 0x%08X\n", vidc.pll_ctl);
-	printk(KERN_DEBUG " Ctrl      (E)    : 0x%08X\n", vidc.control);
-	printk(KERN_DEBUG " Data Ctrl (F)    : 0x%08X\n", dat_ctl);
-	printk(KERN_DEBUG " Fsize            : 0x%08X\n", fsize);
-#endif
-}
-
-/*
- * We have to take note of the VIDC20's 16-bit palette here.
- * The VIDC20 looks up a 16 bit pixel as follows:
- *
- *   bits   111111
- *          5432109876543210
- *   red            ++++++++  (8 bits,  7 to 0)
- *  green       ++++++++      (8 bits, 11 to 4)
- *   blue   ++++++++          (8 bits, 15 to 8)
- *
- * We use a pixel which looks like:
- *
- *   bits   111111
- *          5432109876543210
- *   red               +++++  (5 bits,  4 to  0)
- *  green         +++++       (5 bits,  9 to  5)
- *   blue    +++++            (5 bits, 14 to 10)
- */
-static int
-acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		  u_int trans, struct fb_info *info)
-{
-	union palette pal;
-
-	if (regno >= current_par.palette_size)
-		return 1;
-
-	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		u32 pseudo_val;
-
-		pseudo_val  = regno << info->var.red.offset;
-		pseudo_val |= regno << info->var.green.offset;
-		pseudo_val |= regno << info->var.blue.offset;
-
-		((u32 *)info->pseudo_palette)[regno] = pseudo_val;
-	}
-
-	pal.p = 0;
-	pal.vidc20.red   = red >> 8;
-	pal.vidc20.green = green >> 8;
-	pal.vidc20.blue  = blue >> 8;
-
-	current_par.palette[regno] = pal;
-
-	if (info->var.bits_per_pixel == 16) {
-		int i;
-
-		pal.p = 0;
-		vidc_writel(0x10000000);
-		for (i = 0; i < 256; i += 1) {
-			pal.vidc20.red   = current_par.palette[ i       & 31].vidc20.red;
-			pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
-			pal.vidc20.blue  = current_par.palette[(i >> 2) & 31].vidc20.blue;
-			vidc_writel(pal.p);
-			/* Palette register pointer auto-increments */
-		}
-	} else {
-		vidc_writel(0x10000000 | regno);
-		vidc_writel(pal.p);
-	}
-
-	return 0;
-}
-#endif
-
-/*
- * Before selecting the timing parameters, adjust
- * the resolution to fit the rules.
- */
-static int
-acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, u_int fontht)
-{
-	u_int font_line_len, sam_size, min_size, size, nr_y;
-
-	/* xres must be even */
-	var->xres = (var->xres + 1) & ~1;
-
-	/*
-	 * We don't allow xres_virtual to differ from xres
-	 */
-	var->xres_virtual = var->xres;
-	var->xoffset = 0;
-
-	if (current_par.using_vram)
-		sam_size = current_par.vram_half_sam * 2;
-	else
-		sam_size = 16;
-
-	/*
-	 * Now, find a value for yres_virtual which allows
-	 * us to do ywrap scrolling.  The value of
-	 * yres_virtual must be such that the end of the
-	 * displayable frame buffer must be aligned with
-	 * the start of a font line.
-	 */
-	font_line_len = var->xres * var->bits_per_pixel * fontht / 8;
-	min_size = var->xres * var->yres * var->bits_per_pixel / 8;
-
-	/*
-	 * If minimum screen size is greater than that we have
-	 * available, reject it.
-	 */
-	if (min_size > info->fix.smem_len)
-		return -EINVAL;
-
-	/* Find int 'y', such that y * fll == s * sam < maxsize
-	 * y = s * sam / fll; s = maxsize / sam
-	 */
-	for (size = info->fix.smem_len;
-	     nr_y = size / font_line_len, min_size <= size;
-	     size -= sam_size) {
-		if (nr_y * font_line_len == size)
-			break;
-	}
-	nr_y *= fontht;
-
-	if (var->accel_flags & FB_ACCELF_TEXT) {
-		if (min_size > size) {
-			/*
-			 * failed, use ypan
-			 */
-			size = info->fix.smem_len;
-			var->yres_virtual = size / (font_line_len / fontht);
-		} else
-			var->yres_virtual = nr_y;
-	} else if (var->yres_virtual > nr_y)
-		var->yres_virtual = nr_y;
-
-	current_par.screen_end = info->fix.smem_start + size;
-
-	/*
-	 * Fix yres & yoffset if needed.
-	 */
-	if (var->yres > var->yres_virtual)
-		var->yres = var->yres_virtual;
-
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset > var->yres_virtual)
-			var->yoffset = var->yres_virtual;
-	} else {
-		if (var->yoffset + var->yres > var->yres_virtual)
-			var->yoffset = var->yres_virtual - var->yres;
-	}
-
-	/* hsync_len must be even */
-	var->hsync_len = (var->hsync_len + 1) & ~1;
-
-#if defined(HAS_VIDC20)
-	/* left_margin must be even */
-	if (var->left_margin & 1) {
-		var->left_margin += 1;
-		var->right_margin -= 1;
-	}
-
-	/* right_margin must be even */
-	if (var->right_margin & 1)
-		var->right_margin += 1;
-#endif
-
-	if (var->vsync_len < 1)
-		var->vsync_len = 1;
-
-	return 0;
-}
-
-static int
-acornfb_validate_timing(struct fb_var_screeninfo *var,
-			struct fb_monspecs *monspecs)
-{
-	unsigned long hs, vs;
-
-	/*
-	 * hs(Hz) = 10^12 / (pixclock * xtotal)
-	 * vs(Hz) = hs(Hz) / ytotal
-	 *
-	 * No need to do long long divisions or anything
-	 * like that if you factor it correctly
-	 */
-	hs = 1953125000 / var->pixclock;
-	hs = hs * 512 /
-	     (var->xres + var->left_margin + var->right_margin + var->hsync_len);
-	vs = hs /
-	     (var->yres + var->upper_margin + var->lower_margin + var->vsync_len);
-
-	return (vs >= monspecs->vfmin && vs <= monspecs->vfmax &&
-		hs >= monspecs->hfmin && hs <= monspecs->hfmax) ? 0 : -EINVAL;
-}
-
-static inline void
-acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
-{
-	u_int off = var->yoffset * info->fix.line_length;
-
-#if defined(HAS_MEMC)
-	memc_write(VDMA_INIT, off >> 2);
-#elif defined(HAS_IOMD)
-	iomd_writel(info->fix.smem_start + off, IOMD_VIDINIT);
-#endif
-}
-
-static int
-acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	u_int fontht;
-	int err;
-
-	/*
-	 * FIXME: Find the font height
-	 */
-	fontht = 8;
-
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	switch (var->bits_per_pixel) {
-	case 1:	case 2:	case 4:	case 8:
-		var->red.offset    = 0;
-		var->red.length    = var->bits_per_pixel;
-		var->green         = var->red;
-		var->blue          = var->red;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-
-#ifdef HAS_VIDC20
-	case 16:
-		var->red.offset    = 0;
-		var->red.length    = 5;
-		var->green.offset  = 5;
-		var->green.length  = 5;
-		var->blue.offset   = 10;
-		var->blue.length   = 5;
-		var->transp.offset = 15;
-		var->transp.length = 1;
-		break;
-
-	case 32:
-		var->red.offset    = 0;
-		var->red.length    = 8;
-		var->green.offset  = 8;
-		var->green.length  = 8;
-		var->blue.offset   = 16;
-		var->blue.length   = 8;
-		var->transp.offset = 24;
-		var->transp.length = 4;
-		break;
-#endif
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * Check to see if the pixel rate is valid.
-	 */
-	if (!acornfb_valid_pixrate(var))
-		return -EINVAL;
-
-	/*
-	 * Validate and adjust the resolution to
-	 * match the video generator hardware.
-	 */
-	err = acornfb_adjust_timing(info, var, fontht);
-	if (err)
-		return err;
-
-	/*
-	 * Validate the timing against the
-	 * monitor hardware.
-	 */
-	return acornfb_validate_timing(var, &info->monspecs);
-}
-
-static int acornfb_set_par(struct fb_info *info)
-{
-	switch (info->var.bits_per_pixel) {
-	case 1:
-		current_par.palette_size = 2;
-		info->fix.visual = FB_VISUAL_MONO10;
-		break;
-	case 2:
-		current_par.palette_size = 4;
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 4:
-		current_par.palette_size = 16;
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 8:
-		current_par.palette_size = VIDC_PALETTE_SIZE;
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-#ifdef HAS_VIDC20
-	case 16:
-		current_par.palette_size = 32;
-		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
-		break;
-	case 32:
-		current_par.palette_size = VIDC_PALETTE_SIZE;
-		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
-		break;
-#endif
-	default:
-		BUG();
-	}
-
-	info->fix.line_length	= (info->var.xres * info->var.bits_per_pixel) / 8;
-
-#if defined(HAS_MEMC)
-	{
-		unsigned long size = info->fix.smem_len - VDMA_XFERSIZE;
-
-		memc_write(VDMA_START, 0);
-		memc_write(VDMA_END, size >> 2);
-	}
-#elif defined(HAS_IOMD)
-	{
-		unsigned long start, size;
-		u_int control;
-
-		start = info->fix.smem_start;
-		size  = current_par.screen_end;
-
-		if (current_par.using_vram) {
-			size -= current_par.vram_half_sam;
-			control = DMA_CR_E | (current_par.vram_half_sam / 256);
-		} else {
-			size -= 16;
-			control = DMA_CR_E | DMA_CR_D | 16;
-		}
-
-		iomd_writel(start,   IOMD_VIDSTART);
-		iomd_writel(size,    IOMD_VIDEND);
-		iomd_writel(control, IOMD_VIDCR);
-	}
-#endif
-
-	acornfb_update_dma(info, &info->var);
-	acornfb_set_timing(info);
-
-	return 0;
-}
-
-static int
-acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	u_int y_bottom = var->yoffset;
-
-	if (!(var->vmode & FB_VMODE_YWRAP))
-		y_bottom += info->var.yres;
-
-	if (y_bottom > info->var.yres_virtual)
-		return -EINVAL;
-
-	acornfb_update_dma(info, var);
-
-	return 0;
-}
-
-static struct fb_ops acornfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= acornfb_check_var,
-	.fb_set_par	= acornfb_set_par,
-	.fb_setcolreg	= acornfb_setcolreg,
-	.fb_pan_display	= acornfb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-/*
- * Everything after here is initialisation!!!
- */
-static struct fb_videomode modedb[] = {
-	{	/* 320x256 @ 50Hz */
-		NULL, 50,  320,  256, 125000,  92,  62,  35, 19,  38, 2,
-		FB_SYNC_COMP_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 640x250 @ 50Hz, 15.6 kHz hsync */
-		NULL, 50,  640,  250,  62500, 185, 123,  38, 21,  76, 3,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 640x256 @ 50Hz, 15.6 kHz hsync */
-		NULL, 50,  640,  256,  62500, 185, 123,  35, 18,  76, 3,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 640x512 @ 50Hz, 26.8 kHz hsync */
-		NULL, 50,  640,  512,  41667, 113,  87,  18,  1,  56, 3,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 640x250 @ 70Hz, 31.5 kHz hsync */
-		NULL, 70,  640,  250,  39722,  48,  16, 109, 88,  96, 2,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 640x256 @ 70Hz, 31.5 kHz hsync */
-		NULL, 70,  640,  256,  39722,  48,  16, 106, 85,  96, 2,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 640x352 @ 70Hz, 31.5 kHz hsync */
-		NULL, 70,  640,  352,  39722,  48,  16,  58, 37,  96, 2,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 640x480 @ 60Hz, 31.5 kHz hsync */
-		NULL, 60,  640,  480,  39722,  48,  16,  32, 11,  96, 2,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 800x600 @ 56Hz, 35.2 kHz hsync */
-		NULL, 56,  800,  600,  27778, 101,  23,  22,  1, 100, 2,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 896x352 @ 60Hz, 21.8 kHz hsync */
-		NULL, 60,  896,  352,  41667,  59,  27,   9,  0, 118, 3,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 1024x 768 @ 60Hz, 48.4 kHz hsync */
-		NULL, 60, 1024,  768,  15385, 160,  24,  29,  3, 136, 6,
-		0,
-		FB_VMODE_NONINTERLACED
-	}, {	/* 1280x1024 @ 60Hz, 63.8 kHz hsync */
-		NULL, 60, 1280, 1024,   9090, 186,  96,  38,  1, 160, 3,
-		0,
-		FB_VMODE_NONINTERLACED
-	}
-};
-
-static struct fb_videomode acornfb_default_mode = {
-	.name =		NULL,
-	.refresh =	60,
-	.xres =		640,
-	.yres =		480,
-	.pixclock =	39722,
-	.left_margin =	56,
-	.right_margin =	16,
-	.upper_margin =	34,
-	.lower_margin =	9,
-	.hsync_len =	88,
-	.vsync_len =	2,
-	.sync =		0,
-	.vmode =	FB_VMODE_NONINTERLACED
-};
-
-static void acornfb_init_fbinfo(void)
-{
-	static int first = 1;
-
-	if (!first)
-		return;
-	first = 0;
-
-	fb_info.fbops		= &acornfb_ops;
-	fb_info.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	fb_info.pseudo_palette	= current_par.pseudo_palette;
-
-	strcpy(fb_info.fix.id, "Acorn");
-	fb_info.fix.type	= FB_TYPE_PACKED_PIXELS;
-	fb_info.fix.type_aux	= 0;
-	fb_info.fix.xpanstep	= 0;
-	fb_info.fix.ypanstep	= 1;
-	fb_info.fix.ywrapstep	= 1;
-	fb_info.fix.line_length	= 0;
-	fb_info.fix.accel	= FB_ACCEL_NONE;
-
-	/*
-	 * setup initial parameters
-	 */
-	memset(&fb_info.var, 0, sizeof(fb_info.var));
-
-#if defined(HAS_VIDC20)
-	fb_info.var.red.length	   = 8;
-	fb_info.var.transp.length  = 4;
-#endif
-	fb_info.var.green	   = fb_info.var.red;
-	fb_info.var.blue	   = fb_info.var.red;
-	fb_info.var.nonstd	   = 0;
-	fb_info.var.activate	   = FB_ACTIVATE_NOW;
-	fb_info.var.height	   = -1;
-	fb_info.var.width	   = -1;
-	fb_info.var.vmode	   = FB_VMODE_NONINTERLACED;
-	fb_info.var.accel_flags	   = FB_ACCELF_TEXT;
-
-	current_par.dram_size	   = 0;
-	current_par.montype	   = -1;
-	current_par.dpms	   = 0;
-}
-
-/*
- * setup acornfb options:
- *
- *  mon:hmin-hmax:vmin-vmax:dpms:width:height
- *	Set monitor parameters:
- *		hmin   = horizontal minimum frequency (Hz)
- *		hmax   = horizontal maximum frequency (Hz)	(optional)
- *		vmin   = vertical minimum frequency (Hz)
- *		vmax   = vertical maximum frequency (Hz)	(optional)
- *		dpms   = DPMS supported?			(optional)
- *		width  = width of picture in mm.		(optional)
- *		height = height of picture in mm.		(optional)
- *
- * montype:type
- *	Set RISC-OS style monitor type:
- *		0 (or tv)	- TV frequency
- *		1 (or multi)	- Multi frequency
- *		2 (or hires)	- Hi-res monochrome
- *		3 (or vga)	- VGA
- *		4 (or svga)	- SVGA
- *		auto, or option missing
- *				- try hardware detect
- *
- * dram:size
- *	Set the amount of DRAM to use for the frame buffer
- *	(even if you have VRAM).
- *	size can optionally be followed by 'M' or 'K' for
- *	MB or KB respectively.
- */
-static void acornfb_parse_mon(char *opt)
-{
-	char *p = opt;
-
-	current_par.montype = -2;
-
-	fb_info.monspecs.hfmin = simple_strtoul(p, &p, 0);
-	if (*p == '-')
-		fb_info.monspecs.hfmax = simple_strtoul(p + 1, &p, 0);
-	else
-		fb_info.monspecs.hfmax = fb_info.monspecs.hfmin;
-
-	if (*p != ':')
-		goto bad;
-
-	fb_info.monspecs.vfmin = simple_strtoul(p + 1, &p, 0);
-	if (*p == '-')
-		fb_info.monspecs.vfmax = simple_strtoul(p + 1, &p, 0);
-	else
-		fb_info.monspecs.vfmax = fb_info.monspecs.vfmin;
-
-	if (*p != ':')
-		goto check_values;
-
-	fb_info.monspecs.dpms = simple_strtoul(p + 1, &p, 0);
-
-	if (*p != ':')
-		goto check_values;
-
-	fb_info.var.width = simple_strtoul(p + 1, &p, 0);
-
-	if (*p != ':')
-		goto check_values;
-
-	fb_info.var.height = simple_strtoul(p + 1, NULL, 0);
-
-check_values:
-	if (fb_info.monspecs.hfmax < fb_info.monspecs.hfmin ||
-	    fb_info.monspecs.vfmax < fb_info.monspecs.vfmin)
-		goto bad;
-	return;
-
-bad:
-	printk(KERN_ERR "Acornfb: bad monitor settings: %s\n", opt);
-	current_par.montype = -1;
-}
-
-static void acornfb_parse_montype(char *opt)
-{
-	current_par.montype = -2;
-
-	if (strncmp(opt, "tv", 2) == 0) {
-		opt += 2;
-		current_par.montype = 0;
-	} else if (strncmp(opt, "multi", 5) == 0) {
-		opt += 5;
-		current_par.montype = 1;
-	} else if (strncmp(opt, "hires", 5) == 0) {
-		opt += 5;
-		current_par.montype = 2;
-	} else if (strncmp(opt, "vga", 3) == 0) {
-		opt += 3;
-		current_par.montype = 3;
-	} else if (strncmp(opt, "svga", 4) == 0) {
-		opt += 4;
-		current_par.montype = 4;
-	} else if (strncmp(opt, "auto", 4) == 0) {
-		opt += 4;
-		current_par.montype = -1;
-	} else if (isdigit(*opt))
-		current_par.montype = simple_strtoul(opt, &opt, 0);
-
-	if (current_par.montype == -2 ||
-	    current_par.montype > NR_MONTYPES) {
-		printk(KERN_ERR "acornfb: unknown monitor type: %s\n",
-			opt);
-		current_par.montype = -1;
-	} else
-	if (opt && *opt) {
-		if (strcmp(opt, ",dpms") == 0)
-			current_par.dpms = 1;
-		else
-			printk(KERN_ERR
-			       "acornfb: unknown monitor option: %s\n",
-			       opt);
-	}
-}
-
-static void acornfb_parse_dram(char *opt)
-{
-	unsigned int size;
-
-	size = simple_strtoul(opt, &opt, 0);
-
-	if (opt) {
-		switch (*opt) {
-		case 'M':
-		case 'm':
-			size *= 1024;
-		case 'K':
-		case 'k':
-			size *= 1024;
-		default:
-			break;
-		}
-	}
-
-	current_par.dram_size = size;
-}
-
-static struct options {
-	char *name;
-	void (*parse)(char *opt);
-} opt_table[] = {
-	{ "mon",     acornfb_parse_mon     },
-	{ "montype", acornfb_parse_montype },
-	{ "dram",    acornfb_parse_dram    },
-	{ NULL, NULL }
-};
-
-static int acornfb_setup(char *options)
-{
-	struct options *optp;
-	char *opt;
-
-	if (!options || !*options)
-		return 0;
-
-	acornfb_init_fbinfo();
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-
-		for (optp = opt_table; optp->name; optp++) {
-			int optlen;
-
-			optlen = strlen(optp->name);
-
-			if (strncmp(opt, optp->name, optlen) == 0 &&
-			    opt[optlen] == ':') {
-				optp->parse(opt + optlen + 1);
-				break;
-			}
-		}
-
-		if (!optp->name)
-			printk(KERN_ERR "acornfb: unknown parameter: %s\n",
-			       opt);
-	}
-	return 0;
-}
-
-/*
- * Detect type of monitor connected
- *  For now, we just assume SVGA
- */
-static int acornfb_detect_monitortype(void)
-{
-	return 4;
-}
-
-/*
- * This enables the unused memory to be freed on older Acorn machines.
- * We are freeing memory on behalf of the architecture initialisation
- * code here.
- */
-static inline void
-free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
-{
-	int mb_freed = 0;
-
-	/*
-	 * Align addresses
-	 */
-	virtual_start = PAGE_ALIGN(virtual_start);
-	virtual_end = PAGE_ALIGN(virtual_end);
-
-	while (virtual_start < virtual_end) {
-		struct page *page;
-
-		/*
-		 * Clear page reserved bit,
-		 * set count to 1, and free
-		 * the page.
-		 */
-		page = virt_to_page(virtual_start);
-		__free_reserved_page(page);
-
-		virtual_start += PAGE_SIZE;
-		mb_freed += PAGE_SIZE / 1024;
-	}
-
-	printk("acornfb: freed %dK memory\n", mb_freed);
-}
-
-static int acornfb_probe(struct platform_device *dev)
-{
-	unsigned long size;
-	u_int h_sync, v_sync;
-	int rc, i;
-	char *option = NULL;
-
-	if (fb_get_options("acornfb", &option))
-		return -ENODEV;
-	acornfb_setup(option);
-
-	acornfb_init_fbinfo();
-
-	current_par.dev = &dev->dev;
-
-	if (current_par.montype == -1)
-		current_par.montype = acornfb_detect_monitortype();
-
-	if (current_par.montype == -1 || current_par.montype > NR_MONTYPES)
-		current_par.montype = 4;
-
-	if (current_par.montype >= 0) {
-		fb_info.monspecs = monspecs[current_par.montype];
-		fb_info.monspecs.dpms = current_par.dpms;
-	}
-
-	/*
-	 * Try to select a suitable default mode
-	 */
-	for (i = 0; i < ARRAY_SIZE(modedb); i++) {
-		unsigned long hs;
-
-		hs = modedb[i].refresh *
-		     (modedb[i].yres + modedb[i].upper_margin +
-		      modedb[i].lower_margin + modedb[i].vsync_len);
-		if (modedb[i].xres == DEFAULT_XRES &&
-		    modedb[i].yres == DEFAULT_YRES &&
-		    modedb[i].refresh >= fb_info.monspecs.vfmin &&
-		    modedb[i].refresh <= fb_info.monspecs.vfmax &&
-		    hs                >= fb_info.monspecs.hfmin &&
-		    hs                <= fb_info.monspecs.hfmax) {
-			acornfb_default_mode = modedb[i];
-			break;
-		}
-	}
-
-	fb_info.screen_base    = (char *)SCREEN_BASE;
-	fb_info.fix.smem_start = SCREEN_START;
-	current_par.using_vram = 0;
-
-	/*
-	 * If vram_size is set, we are using VRAM in
-	 * a Risc PC.  However, if the user has specified
-	 * an amount of DRAM then use that instead.
-	 */
-	if (vram_size && !current_par.dram_size) {
-		size = vram_size;
-		current_par.vram_half_sam = vram_size / 1024;
-		current_par.using_vram = 1;
-	} else if (current_par.dram_size)
-		size = current_par.dram_size;
-	else
-		size = MAX_SIZE;
-
-	/*
-	 * Limit maximum screen size.
-	 */
-	if (size > MAX_SIZE)
-		size = MAX_SIZE;
-
-	size = PAGE_ALIGN(size);
-
-#if defined(HAS_VIDC20)
-	if (!current_par.using_vram) {
-		dma_addr_t handle;
-		void *base;
-
-		/*
-		 * RiscPC needs to allocate the DRAM memory
-		 * for the framebuffer if we are not using
-		 * VRAM.
-		 */
-		base = dma_alloc_writecombine(current_par.dev, size, &handle,
-					      GFP_KERNEL);
-		if (base == NULL) {
-			printk(KERN_ERR "acornfb: unable to allocate screen "
-			       "memory\n");
-			return -ENOMEM;
-		}
-
-		fb_info.screen_base = base;
-		fb_info.fix.smem_start = handle;
-	}
-#endif
-	fb_info.fix.smem_len = size;
-	current_par.palette_size   = VIDC_PALETTE_SIZE;
-
-	/*
-	 * Lookup the timing for this resolution.  If we can't
-	 * find it, then we can't restore it if we change
-	 * the resolution, so we disable this feature.
-	 */
-	do {
-		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
-				 ARRAY_SIZE(modedb),
-				 &acornfb_default_mode, DEFAULT_BPP);
-		/*
-		 * If we found an exact match, all ok.
-		 */
-		if (rc == 1)
-			break;
-
-		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
-				  &acornfb_default_mode, DEFAULT_BPP);
-		/*
-		 * If we found an exact match, all ok.
-		 */
-		if (rc == 1)
-			break;
-
-		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
-				 ARRAY_SIZE(modedb),
-				 &acornfb_default_mode, DEFAULT_BPP);
-		if (rc)
-			break;
-
-		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
-				  &acornfb_default_mode, DEFAULT_BPP);
-	} while (0);
-
-	/*
-	 * If we didn't find an exact match, try the
-	 * generic database.
-	 */
-	if (rc == 0) {
-		printk("Acornfb: no valid mode found\n");
-		return -EINVAL;
-	}
-
-	h_sync = 1953125000 / fb_info.var.pixclock;
-	h_sync = h_sync * 512 / (fb_info.var.xres + fb_info.var.left_margin +
-		 fb_info.var.right_margin + fb_info.var.hsync_len);
-	v_sync = h_sync / (fb_info.var.yres + fb_info.var.upper_margin +
-		 fb_info.var.lower_margin + fb_info.var.vsync_len);
-
-	printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, "
-		"%d.%03dkHz, %dHz\n",
-		fb_info.fix.smem_len / 1024,
-		current_par.using_vram ? 'V' : 'D',
-		VIDC_NAME, fb_info.var.xres, fb_info.var.yres,
-		h_sync / 1000, h_sync % 1000, v_sync);
-
-	printk(KERN_INFO "Acornfb: Monitor: %d.%03d-%d.%03dkHz, %d-%dHz%s\n",
-		fb_info.monspecs.hfmin / 1000, fb_info.monspecs.hfmin % 1000,
-		fb_info.monspecs.hfmax / 1000, fb_info.monspecs.hfmax % 1000,
-		fb_info.monspecs.vfmin, fb_info.monspecs.vfmax,
-		fb_info.monspecs.dpms ? ", DPMS" : "");
-
-	if (fb_set_var(&fb_info, &fb_info.var))
-		printk(KERN_ERR "Acornfb: unable to set display parameters\n");
-
-	if (register_framebuffer(&fb_info) < 0)
-		return -EINVAL;
-	return 0;
-}
-
-static struct platform_driver acornfb_driver = {
-	.probe	= acornfb_probe,
-	.driver	= {
-		.name	= "acornfb",
-	},
-};
-
-static int __init acornfb_init(void)
-{
-	return platform_driver_register(&acornfb_driver);
-}
-
-module_init(acornfb_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/acornfb.h b/drivers/video/acornfb.h
deleted file mode 100644
index 175c8ff3367c..000000000000
--- a/drivers/video/acornfb.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *  linux/drivers/video/acornfb.h
- *
- *  Copyright (C) 1998,1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Frame buffer code for Acorn platforms
- */
-#if defined(HAS_VIDC20)
-#include <asm/hardware/iomd.h>
-#define VIDC_PALETTE_SIZE	256
-#define VIDC_NAME		"VIDC20"
-#endif
-
-#define EXTEND8(x) ((x)|(x)<<8)
-#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
-
-struct vidc20_palette {
-	u_int red:8;
-	u_int green:8;
-	u_int blue:8;
-	u_int ext:4;
-	u_int unused:4;
-};
-
-struct vidc_palette {
-	u_int red:4;
-	u_int green:4;
-	u_int blue:4;
-	u_int trans:1;
-	u_int sbz1:13;
-	u_int reg:4;
-	u_int sbz2:2;
-};
-
-union palette {
-	struct vidc20_palette	vidc20;
-	struct vidc_palette	vidc;
-	u_int	p;
-};
-
-struct acornfb_par {
-	struct device	*dev;
-	unsigned long	screen_end;
-	unsigned int	dram_size;
-	unsigned int	vram_half_sam;
-	unsigned int	palette_size;
-	  signed int	montype;
-	unsigned int	using_vram	: 1;
-	unsigned int	dpms		: 1;
-
-	union palette palette[VIDC_PALETTE_SIZE];
-
-	u32		pseudo_palette[16];
-};
-
-struct vidc_timing {
-	u_int	h_cycle;
-	u_int	h_sync_width;
-	u_int	h_border_start;
-	u_int	h_display_start;
-	u_int	h_display_end;
-	u_int	h_border_end;
-	u_int	h_interlace;
-
-	u_int	v_cycle;
-	u_int	v_sync_width;
-	u_int	v_border_start;
-	u_int	v_display_start;
-	u_int	v_display_end;
-	u_int	v_border_end;
-
-	u_int	control;
-
-	/* VIDC20 only */
-	u_int	pll_ctl;
-};
-
-struct modey_params {
-	u_int	y_res;
-	u_int	u_margin;
-	u_int	b_margin;
-	u_int	vsync_len;
-	u_int	vf;
-};
-
-struct modex_params {
-	u_int	x_res;
-	u_int	l_margin;
-	u_int	r_margin;
-	u_int	hsync_len;
-	u_int	clock;
-	u_int	hf;
-	const struct modey_params *modey;
-};
-
-#ifdef HAS_VIDC20
-/*
- * VIDC20 registers
- */
-#define VIDC20_CTRL		0xe0000000
-#define VIDC20_CTRL_PIX_VCLK	(0 << 0)
-#define VIDC20_CTRL_PIX_HCLK	(1 << 0)
-#define VIDC20_CTRL_PIX_RCLK	(2 << 0)
-#define VIDC20_CTRL_PIX_CK	(0 << 2)
-#define VIDC20_CTRL_PIX_CK2	(1 << 2)
-#define VIDC20_CTRL_PIX_CK3	(2 << 2)
-#define VIDC20_CTRL_PIX_CK4	(3 << 2)
-#define VIDC20_CTRL_PIX_CK5	(4 << 2)
-#define VIDC20_CTRL_PIX_CK6	(5 << 2)
-#define VIDC20_CTRL_PIX_CK7	(6 << 2)
-#define VIDC20_CTRL_PIX_CK8	(7 << 2)
-#define VIDC20_CTRL_1BPP	(0 << 5)
-#define VIDC20_CTRL_2BPP	(1 << 5)
-#define VIDC20_CTRL_4BPP	(2 << 5)
-#define VIDC20_CTRL_8BPP	(3 << 5)
-#define VIDC20_CTRL_16BPP	(4 << 5)
-#define VIDC20_CTRL_32BPP	(6 << 5)
-#define VIDC20_CTRL_FIFO_NS	(0 << 8)
-#define VIDC20_CTRL_FIFO_4	(1 << 8)
-#define VIDC20_CTRL_FIFO_8	(2 << 8)
-#define VIDC20_CTRL_FIFO_12	(3 << 8)
-#define VIDC20_CTRL_FIFO_16	(4 << 8)
-#define VIDC20_CTRL_FIFO_20	(5 << 8)
-#define VIDC20_CTRL_FIFO_24	(6 << 8)
-#define VIDC20_CTRL_FIFO_28	(7 << 8)
-#define VIDC20_CTRL_INT		(1 << 12)
-#define VIDC20_CTRL_DUP		(1 << 13)
-#define VIDC20_CTRL_PDOWN	(1 << 14)
-
-#define VIDC20_ECTL		0xc0000000
-#define VIDC20_ECTL_REG(x)	((x) & 0xf3)
-#define VIDC20_ECTL_ECK		(1 << 2)
-#define VIDC20_ECTL_REDPED	(1 << 8)
-#define VIDC20_ECTL_GREENPED	(1 << 9)
-#define VIDC20_ECTL_BLUEPED	(1 << 10)
-#define VIDC20_ECTL_DAC		(1 << 12)
-#define VIDC20_ECTL_LCDGS	(1 << 13)
-#define VIDC20_ECTL_HRM		(1 << 14)
-
-#define VIDC20_ECTL_HS_MASK	(3 << 16)
-#define VIDC20_ECTL_HS_HSYNC	(0 << 16)
-#define VIDC20_ECTL_HS_NHSYNC	(1 << 16)
-#define VIDC20_ECTL_HS_CSYNC	(2 << 16)
-#define VIDC20_ECTL_HS_NCSYNC	(3 << 16)
-
-#define VIDC20_ECTL_VS_MASK	(3 << 18)
-#define VIDC20_ECTL_VS_VSYNC	(0 << 18)
-#define VIDC20_ECTL_VS_NVSYNC	(1 << 18)
-#define VIDC20_ECTL_VS_CSYNC	(2 << 18)
-#define VIDC20_ECTL_VS_NCSYNC	(3 << 18)
-
-#define VIDC20_DCTL		0xf0000000
-/* 0-9 = number of words in scanline */
-#define VIDC20_DCTL_SNA		(1 << 12)
-#define VIDC20_DCTL_HDIS	(1 << 13)
-#define VIDC20_DCTL_BUS_NS	(0 << 16)
-#define VIDC20_DCTL_BUS_D31_0	(1 << 16)
-#define VIDC20_DCTL_BUS_D63_32	(2 << 16)
-#define VIDC20_DCTL_BUS_D63_0	(3 << 16)
-#define VIDC20_DCTL_VRAM_DIS	(0 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK	(1 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK2	(2 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK4	(3 << 18)
-
-#endif
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
deleted file mode 100644
index 14d6b3793e0a..000000000000
--- a/drivers/video/amba-clcd.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
- *  linux/drivers/video/amba-clcd.c
- *
- * Copyright (C) 2001 ARM Limited, by David A Rusling
- * Updated to 2.5, Deep Blue Solutions Ltd.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- *  ARM PrimeCell PL110 Color LCD Controller
- */
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/list.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-#include <linux/clk.h>
-#include <linux/hardirq.h>
-
-#include <asm/sizes.h>
-
-#define to_clcd(info)	container_of(info, struct clcd_fb, fb)
-
-/* This is limited to 16 characters when displayed by X startup */
-static const char *clcd_name = "CLCD FB";
-
-/*
- * Unfortunately, the enable/disable functions may be called either from
- * process or IRQ context, and we _need_ to delay.  This is _not_ good.
- */
-static inline void clcdfb_sleep(unsigned int ms)
-{
-	if (in_atomic()) {
-		mdelay(ms);
-	} else {
-		msleep(ms);
-	}
-}
-
-static inline void clcdfb_set_start(struct clcd_fb *fb)
-{
-	unsigned long ustart = fb->fb.fix.smem_start;
-	unsigned long lstart;
-
-	ustart += fb->fb.var.yoffset * fb->fb.fix.line_length;
-	lstart = ustart + fb->fb.var.yres * fb->fb.fix.line_length / 2;
-
-	writel(ustart, fb->regs + CLCD_UBAS);
-	writel(lstart, fb->regs + CLCD_LBAS);
-}
-
-static void clcdfb_disable(struct clcd_fb *fb)
-{
-	u32 val;
-
-	if (fb->board->disable)
-		fb->board->disable(fb);
-
-	val = readl(fb->regs + fb->off_cntl);
-	if (val & CNTL_LCDPWR) {
-		val &= ~CNTL_LCDPWR;
-		writel(val, fb->regs + fb->off_cntl);
-
-		clcdfb_sleep(20);
-	}
-	if (val & CNTL_LCDEN) {
-		val &= ~CNTL_LCDEN;
-		writel(val, fb->regs + fb->off_cntl);
-	}
-
-	/*
-	 * Disable CLCD clock source.
-	 */
-	if (fb->clk_enabled) {
-		fb->clk_enabled = false;
-		clk_disable(fb->clk);
-	}
-}
-
-static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
-{
-	/*
-	 * Enable the CLCD clock source.
-	 */
-	if (!fb->clk_enabled) {
-		fb->clk_enabled = true;
-		clk_enable(fb->clk);
-	}
-
-	/*
-	 * Bring up by first enabling..
-	 */
-	cntl |= CNTL_LCDEN;
-	writel(cntl, fb->regs + fb->off_cntl);
-
-	clcdfb_sleep(20);
-
-	/*
-	 * and now apply power.
-	 */
-	cntl |= CNTL_LCDPWR;
-	writel(cntl, fb->regs + fb->off_cntl);
-
-	/*
-	 * finally, enable the interface.
-	 */
-	if (fb->board->enable)
-		fb->board->enable(fb);
-}
-
-static int
-clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
-{
-	u32 caps;
-	int ret = 0;
-
-	if (fb->panel->caps && fb->board->caps)
-		caps = fb->panel->caps & fb->board->caps;
-	else {
-		/* Old way of specifying what can be used */
-		caps = fb->panel->cntl & CNTL_BGR ?
-			CLCD_CAP_BGR : CLCD_CAP_RGB;
-		/* But mask out 444 modes as they weren't supported */
-		caps &= ~CLCD_CAP_444;
-	}
-
-	/* Only TFT panels can do RGB888/BGR888 */
-	if (!(fb->panel->cntl & CNTL_LCDTFT))
-		caps &= ~CLCD_CAP_888;
-
-	memset(&var->transp, 0, sizeof(var->transp));
-
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-		/* If we can't do 5551, reject */
-		caps &= CLCD_CAP_5551;
-		if (!caps) {
-			ret = -EINVAL;
-			break;
-		}
-
-		var->red.length		= var->bits_per_pixel;
-		var->red.offset		= 0;
-		var->green.length	= var->bits_per_pixel;
-		var->green.offset	= 0;
-		var->blue.length	= var->bits_per_pixel;
-		var->blue.offset	= 0;
-		break;
-
-	case 16:
-		/* If we can't do 444, 5551 or 565, reject */
-		if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) {
-			ret = -EINVAL;
-			break;
-		}
-
-		/*
-		 * Green length can be 4, 5 or 6 depending whether
-		 * we're operating in 444, 5551 or 565 mode.
-		 */
-		if (var->green.length == 4 && caps & CLCD_CAP_444)
-			caps &= CLCD_CAP_444;
-		if (var->green.length == 5 && caps & CLCD_CAP_5551)
-			caps &= CLCD_CAP_5551;
-		else if (var->green.length == 6 && caps & CLCD_CAP_565)
-			caps &= CLCD_CAP_565;
-		else {
-			/*
-			 * PL110 officially only supports RGB555,
-			 * but may be wired up to allow RGB565.
-			 */
-			if (caps & CLCD_CAP_565) {
-				var->green.length = 6;
-				caps &= CLCD_CAP_565;
-			} else if (caps & CLCD_CAP_5551) {
-				var->green.length = 5;
-				caps &= CLCD_CAP_5551;
-			} else {
-				var->green.length = 4;
-				caps &= CLCD_CAP_444;
-			}
-		}
-
-		if (var->green.length >= 5) {
-			var->red.length = 5;
-			var->blue.length = 5;
-		} else {
-			var->red.length = 4;
-			var->blue.length = 4;
-		}
-		break;
-	case 32:
-		/* If we can't do 888, reject */
-		caps &= CLCD_CAP_888;
-		if (!caps) {
-			ret = -EINVAL;
-			break;
-		}
-
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	/*
-	 * >= 16bpp displays have separate colour component bitfields
-	 * encoded in the pixel data.  Calculate their position from
-	 * the bitfield length defined above.
-	 */
-	if (ret == 0 && var->bits_per_pixel >= 16) {
-		bool bgr, rgb;
-
-		bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
-		rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
-
-		if (!bgr && !rgb)
-			/*
-			 * The requested format was not possible, try just
-			 * our capabilities.  One of BGR or RGB must be
-			 * supported.
-			 */
-			bgr = caps & CLCD_CAP_BGR;
-
-		if (bgr) {
-			var->blue.offset = 0;
-			var->green.offset = var->blue.offset + var->blue.length;
-			var->red.offset = var->green.offset + var->green.length;
-		} else {
-			var->red.offset = 0;
-			var->green.offset = var->red.offset + var->red.length;
-			var->blue.offset = var->green.offset + var->green.length;
-		}
-	}
-
-	return ret;
-}
-
-static int clcdfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct clcd_fb *fb = to_clcd(info);
-	int ret = -EINVAL;
-
-	if (fb->board->check)
-		ret = fb->board->check(fb, var);
-
-	if (ret == 0 &&
-	    var->xres_virtual * var->bits_per_pixel / 8 *
-	    var->yres_virtual > fb->fb.fix.smem_len)
-		ret = -EINVAL;
-
-	if (ret == 0)
-		ret = clcdfb_set_bitfields(fb, var);
-
-	return ret;
-}
-
-static int clcdfb_set_par(struct fb_info *info)
-{
-	struct clcd_fb *fb = to_clcd(info);
-	struct clcd_regs regs;
-
-	fb->fb.fix.line_length = fb->fb.var.xres_virtual *
-				 fb->fb.var.bits_per_pixel / 8;
-
-	if (fb->fb.var.bits_per_pixel <= 8)
-		fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-
-	fb->board->decode(fb, &regs);
-
-	clcdfb_disable(fb);
-
-	writel(regs.tim0, fb->regs + CLCD_TIM0);
-	writel(regs.tim1, fb->regs + CLCD_TIM1);
-	writel(regs.tim2, fb->regs + CLCD_TIM2);
-	writel(regs.tim3, fb->regs + CLCD_TIM3);
-
-	clcdfb_set_start(fb);
-
-	clk_set_rate(fb->clk, (1000000000 / regs.pixclock) * 1000);
-
-	fb->clcd_cntl = regs.cntl;
-
-	clcdfb_enable(fb, regs.cntl);
-
-#ifdef DEBUG
-	printk(KERN_INFO
-	       "CLCD: Registers set to\n"
-	       "  %08x %08x %08x %08x\n"
-	       "  %08x %08x %08x %08x\n",
-		readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
-		readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
-		readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
-		readl(fb->regs + fb->off_ienb), readl(fb->regs + fb->off_cntl));
-#endif
-
-	return 0;
-}
-
-static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
-{
-	unsigned int mask = (1 << bf->length) - 1;
-
-	return (val >> (16 - bf->length) & mask) << bf->offset;
-}
-
-/*
- *  Set a single color register. The values supplied have a 16 bit
- *  magnitude.  Return != 0 for invalid regno.
- */
-static int
-clcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
-		 unsigned int blue, unsigned int transp, struct fb_info *info)
-{
-	struct clcd_fb *fb = to_clcd(info);
-
-	if (regno < 16)
-		fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
-				  convert_bitfield(blue, &fb->fb.var.blue) |
-				  convert_bitfield(green, &fb->fb.var.green) |
-				  convert_bitfield(red, &fb->fb.var.red);
-
-	if (fb->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
-		int hw_reg = CLCD_PALETTE + ((regno * 2) & ~3);
-		u32 val, mask, newval;
-
-		newval  = (red >> 11)  & 0x001f;
-		newval |= (green >> 6) & 0x03e0;
-		newval |= (blue >> 1)  & 0x7c00;
-
-		/*
-		 * 3.2.11: if we're configured for big endian
-		 * byte order, the palette entries are swapped.
-		 */
-		if (fb->clcd_cntl & CNTL_BEBO)
-			regno ^= 1;
-
-		if (regno & 1) {
-			newval <<= 16;
-			mask = 0x0000ffff;
-		} else {
-			mask = 0xffff0000;
-		}
-
-		val = readl(fb->regs + hw_reg) & mask;
-		writel(val | newval, fb->regs + hw_reg);
-	}
-
-	return regno > 255;
-}
-
-/*
- *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
- *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
- *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
- *  to e.g. a video mode which doesn't support it. Implements VESA suspend
- *  and powerdown modes on hardware that supports disabling hsync/vsync:
- *    blank_mode == 2: suspend vsync
- *    blank_mode == 3: suspend hsync
- *    blank_mode == 4: powerdown
- */
-static int clcdfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct clcd_fb *fb = to_clcd(info);
-
-	if (blank_mode != 0) {
-		clcdfb_disable(fb);
-	} else {
-		clcdfb_enable(fb, fb->clcd_cntl);
-	}
-	return 0;
-}
-
-static int clcdfb_mmap(struct fb_info *info,
-		       struct vm_area_struct *vma)
-{
-	struct clcd_fb *fb = to_clcd(info);
-	unsigned long len, off = vma->vm_pgoff << PAGE_SHIFT;
-	int ret = -EINVAL;
-
-	len = info->fix.smem_len;
-
-	if (off <= len && vma->vm_end - vma->vm_start <= len - off &&
-	    fb->board->mmap)
-		ret = fb->board->mmap(fb, vma);
-
-	return ret;
-}
-
-static struct fb_ops clcdfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= clcdfb_check_var,
-	.fb_set_par	= clcdfb_set_par,
-	.fb_setcolreg	= clcdfb_setcolreg,
-	.fb_blank	= clcdfb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_mmap	= clcdfb_mmap,
-};
-
-static int clcdfb_register(struct clcd_fb *fb)
-{
-	int ret;
-
-	/*
-	 * ARM PL111 always has IENB at 0x1c; it's only PL110
-	 * which is reversed on some platforms.
-	 */
-	if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
-		fb->off_ienb = CLCD_PL111_IENB;
-		fb->off_cntl = CLCD_PL111_CNTL;
-	} else {
-#ifdef CONFIG_ARCH_VERSATILE
-		fb->off_ienb = CLCD_PL111_IENB;
-		fb->off_cntl = CLCD_PL111_CNTL;
-#else
-		fb->off_ienb = CLCD_PL110_IENB;
-		fb->off_cntl = CLCD_PL110_CNTL;
-#endif
-	}
-
-	fb->clk = clk_get(&fb->dev->dev, NULL);
-	if (IS_ERR(fb->clk)) {
-		ret = PTR_ERR(fb->clk);
-		goto out;
-	}
-
-	ret = clk_prepare(fb->clk);
-	if (ret)
-		goto free_clk;
-
-	fb->fb.device		= &fb->dev->dev;
-
-	fb->fb.fix.mmio_start	= fb->dev->res.start;
-	fb->fb.fix.mmio_len	= resource_size(&fb->dev->res);
-
-	fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len);
-	if (!fb->regs) {
-		printk(KERN_ERR "CLCD: unable to remap registers\n");
-		ret = -ENOMEM;
-		goto clk_unprep;
-	}
-
-	fb->fb.fbops		= &clcdfb_ops;
-	fb->fb.flags		= FBINFO_FLAG_DEFAULT;
-	fb->fb.pseudo_palette	= fb->cmap;
-
-	strncpy(fb->fb.fix.id, clcd_name, sizeof(fb->fb.fix.id));
-	fb->fb.fix.type		= FB_TYPE_PACKED_PIXELS;
-	fb->fb.fix.type_aux	= 0;
-	fb->fb.fix.xpanstep	= 0;
-	fb->fb.fix.ypanstep	= 0;
-	fb->fb.fix.ywrapstep	= 0;
-	fb->fb.fix.accel	= FB_ACCEL_NONE;
-
-	fb->fb.var.xres		= fb->panel->mode.xres;
-	fb->fb.var.yres		= fb->panel->mode.yres;
-	fb->fb.var.xres_virtual	= fb->panel->mode.xres;
-	fb->fb.var.yres_virtual	= fb->panel->mode.yres;
-	fb->fb.var.bits_per_pixel = fb->panel->bpp;
-	fb->fb.var.grayscale	= fb->panel->grayscale;
-	fb->fb.var.pixclock	= fb->panel->mode.pixclock;
-	fb->fb.var.left_margin	= fb->panel->mode.left_margin;
-	fb->fb.var.right_margin	= fb->panel->mode.right_margin;
-	fb->fb.var.upper_margin	= fb->panel->mode.upper_margin;
-	fb->fb.var.lower_margin	= fb->panel->mode.lower_margin;
-	fb->fb.var.hsync_len	= fb->panel->mode.hsync_len;
-	fb->fb.var.vsync_len	= fb->panel->mode.vsync_len;
-	fb->fb.var.sync		= fb->panel->mode.sync;
-	fb->fb.var.vmode	= fb->panel->mode.vmode;
-	fb->fb.var.activate	= FB_ACTIVATE_NOW;
-	fb->fb.var.nonstd	= 0;
-	fb->fb.var.height	= fb->panel->height;
-	fb->fb.var.width	= fb->panel->width;
-	fb->fb.var.accel_flags	= 0;
-
-	fb->fb.monspecs.hfmin	= 0;
-	fb->fb.monspecs.hfmax   = 100000;
-	fb->fb.monspecs.vfmin	= 0;
-	fb->fb.monspecs.vfmax	= 400;
-	fb->fb.monspecs.dclkmin = 1000000;
-	fb->fb.monspecs.dclkmax	= 100000000;
-
-	/*
-	 * Make sure that the bitfields are set appropriately.
-	 */
-	clcdfb_set_bitfields(fb, &fb->fb.var);
-
-	/*
-	 * Allocate colourmap.
-	 */
-	ret = fb_alloc_cmap(&fb->fb.cmap, 256, 0);
-	if (ret)
-		goto unmap;
-
-	/*
-	 * Ensure interrupts are disabled.
-	 */
-	writel(0, fb->regs + fb->off_ienb);
-
-	fb_set_var(&fb->fb, &fb->fb.var);
-
-	dev_info(&fb->dev->dev, "%s hardware, %s display\n",
-	         fb->board->name, fb->panel->mode.name);
-
-	ret = register_framebuffer(&fb->fb);
-	if (ret == 0)
-		goto out;
-
-	printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
-
-	fb_dealloc_cmap(&fb->fb.cmap);
- unmap:
-	iounmap(fb->regs);
- clk_unprep:
-	clk_unprepare(fb->clk);
- free_clk:
-	clk_put(fb->clk);
- out:
-	return ret;
-}
-
-static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
-{
-	struct clcd_board *board = dev_get_platdata(&dev->dev);
-	struct clcd_fb *fb;
-	int ret;
-
-	if (!board)
-		return -EINVAL;
-
-	ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
-	if (ret)
-		goto out;
-
-	ret = amba_request_regions(dev, NULL);
-	if (ret) {
-		printk(KERN_ERR "CLCD: unable to reserve regs region\n");
-		goto out;
-	}
-
-	fb = kzalloc(sizeof(struct clcd_fb), GFP_KERNEL);
-	if (!fb) {
-		printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
-		ret = -ENOMEM;
-		goto free_region;
-	}
-
-	fb->dev = dev;
-	fb->board = board;
-
-	dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n",
-		amba_part(dev), amba_rev(dev),
-		(unsigned long long)dev->res.start);
-
-	ret = fb->board->setup(fb);
-	if (ret)
-		goto free_fb;
-
-	ret = clcdfb_register(fb); 
-	if (ret == 0) {
-		amba_set_drvdata(dev, fb);
-		goto out;
-	}
-
-	fb->board->remove(fb);
- free_fb:
-	kfree(fb);
- free_region:
-	amba_release_regions(dev);
- out:
-	return ret;
-}
-
-static int clcdfb_remove(struct amba_device *dev)
-{
-	struct clcd_fb *fb = amba_get_drvdata(dev);
-
-	clcdfb_disable(fb);
-	unregister_framebuffer(&fb->fb);
-	if (fb->fb.cmap.len)
-		fb_dealloc_cmap(&fb->fb.cmap);
-	iounmap(fb->regs);
-	clk_unprepare(fb->clk);
-	clk_put(fb->clk);
-
-	fb->board->remove(fb);
-
-	kfree(fb);
-
-	amba_release_regions(dev);
-
-	return 0;
-}
-
-static struct amba_id clcdfb_id_table[] = {
-	{
-		.id	= 0x00041110,
-		.mask	= 0x000ffffe,
-	},
-	{ 0, 0 },
-};
-
-MODULE_DEVICE_TABLE(amba, clcdfb_id_table);
-
-static struct amba_driver clcd_driver = {
-	.drv 		= {
-		.name	= "clcd-pl11x",
-	},
-	.probe		= clcdfb_probe,
-	.remove		= clcdfb_remove,
-	.id_table	= clcdfb_id_table,
-};
-
-static int __init amba_clcdfb_init(void)
-{
-	if (fb_get_options("ambafb", NULL))
-		return -ENODEV;
-
-	return amba_driver_register(&clcd_driver);
-}
-
-module_init(amba_clcdfb_init);
-
-static void __exit amba_clcdfb_exit(void)
-{
-	amba_driver_unregister(&clcd_driver);
-}
-
-module_exit(amba_clcdfb_exit);
-
-MODULE_DESCRIPTION("ARM PrimeCell PL110 CLCD core driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
deleted file mode 100644
index 518f790ef88a..000000000000
--- a/drivers/video/amifb.c
+++ /dev/null
@@ -1,3792 +0,0 @@
-/*
- * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
- *
- *    Copyright (C) 1995-2003 Geert Uytterhoeven
- *
- *          with work by Roman Zippel
- *
- *
- * This file is based on the Atari frame buffer device (atafb.c):
- *
- *    Copyright (C) 1994 Martin Schaller
- *                       Roman Hodek
- *
- *          with work by Andreas Schwab
- *                       Guenther Kelleter
- *
- * and on the original Amiga console driver (amicon.c):
- *
- *    Copyright (C) 1993 Hamish Macdonald
- *                       Greg Harp
- *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
- *
- *          with work by William Rucklidge (wjr@cs.cornell.edu)
- *                       Geert Uytterhoeven
- *                       Jes Sorensen (jds@kom.auc.dk)
- *
- *
- * History:
- *
- *   - 24 Jul 96: Copper generates now vblank interrupt and
- *                VESA Power Saving Protocol is fully implemented
- *   - 14 Jul 96: Rework and hopefully last ECS bugs fixed
- *   -  7 Mar 96: Hardware sprite support by Roman Zippel
- *   - 18 Feb 96: OCS and ECS support by Roman Zippel
- *                Hardware functions completely rewritten
- *   -  2 Dec 95: AGA version by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-
-#include <asm/irq.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/setup.h>
-
-#include "c2p.h"
-
-
-#define DEBUG
-
-#if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
-#define CONFIG_FB_AMIGA_OCS   /* define at least one fb driver, this will change later */
-#endif
-
-#if !defined(CONFIG_FB_AMIGA_OCS)
-#  define IS_OCS (0)
-#elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
-#  define IS_OCS (chipset == TAG_OCS)
-#else
-#  define CONFIG_FB_AMIGA_OCS_ONLY
-#  define IS_OCS (1)
-#endif
-
-#if !defined(CONFIG_FB_AMIGA_ECS)
-#  define IS_ECS (0)
-#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
-#  define IS_ECS (chipset == TAG_ECS)
-#else
-#  define CONFIG_FB_AMIGA_ECS_ONLY
-#  define IS_ECS (1)
-#endif
-
-#if !defined(CONFIG_FB_AMIGA_AGA)
-#  define IS_AGA (0)
-#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
-#  define IS_AGA (chipset == TAG_AGA)
-#else
-#  define CONFIG_FB_AMIGA_AGA_ONLY
-#  define IS_AGA (1)
-#endif
-
-#ifdef DEBUG
-#  define DPRINTK(fmt, args...)	printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-#else
-#  define DPRINTK(fmt, args...)
-#endif
-
-/*******************************************************************************
-
-
-   Generic video timings
-   ---------------------
-
-   Timings used by the frame buffer interface:
-
-   +----------+---------------------------------------------+----------+-------+
-   |          |                ^                            |          |       |
-   |          |                |upper_margin                |          |       |
-   |          |                v                            |          |       |
-   +----------###############################################----------+-------+
-   |          #                ^                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |   left   #                |                            #  right   | hsync |
-   |  margin  #                |       xres                 #  margin  |  len  |
-   |<-------->#<---------------+--------------------------->#<-------->|<----->|
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |yres                        #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                |                            #          |       |
-   |          #                v                            #          |       |
-   +----------###############################################----------+-------+
-   |          |                ^                            |          |       |
-   |          |                |lower_margin                |          |       |
-   |          |                v                            |          |       |
-   +----------+---------------------------------------------+----------+-------+
-   |          |                ^                            |          |       |
-   |          |                |vsync_len                   |          |       |
-   |          |                v                            |          |       |
-   +----------+---------------------------------------------+----------+-------+
-
-
-   Amiga video timings
-   -------------------
-
-   The Amiga native chipsets uses another timing scheme:
-
-      - hsstrt:   Start of horizontal synchronization pulse
-      - hsstop:   End of horizontal synchronization pulse
-      - htotal:   Last value on the line (i.e. line length = htotal + 1)
-      - vsstrt:   Start of vertical synchronization pulse
-      - vsstop:   End of vertical synchronization pulse
-      - vtotal:   Last line value (i.e. number of lines = vtotal + 1)
-      - hcenter:  Start of vertical retrace for interlace
-
-   You can specify the blanking timings independently. Currently I just set
-   them equal to the respective synchronization values:
-
-      - hbstrt:   Start of horizontal blank
-      - hbstop:   End of horizontal blank
-      - vbstrt:   Start of vertical blank
-      - vbstop:   End of vertical blank
-
-   Horizontal values are in color clock cycles (280 ns), vertical values are in
-   scanlines.
-
-   (0, 0) is somewhere in the upper-left corner :-)
-
-
-   Amiga visible window definitions
-   --------------------------------
-
-   Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
-   make corrections and/or additions.
-
-   Within the above synchronization specifications, the visible window is
-   defined by the following parameters (actual register resolutions may be
-   different; all horizontal values are normalized with respect to the pixel
-   clock):
-
-      - diwstrt_h:   Horizontal start of the visible window
-      - diwstop_h:   Horizontal stop + 1(*) of the visible window
-      - diwstrt_v:   Vertical start of the visible window
-      - diwstop_v:   Vertical stop of the visible window
-      - ddfstrt:     Horizontal start of display DMA
-      - ddfstop:     Horizontal stop of display DMA
-      - hscroll:     Horizontal display output delay
-
-   Sprite positioning:
-
-      - sprstrt_h:   Horizontal start - 4 of sprite
-      - sprstrt_v:   Vertical start of sprite
-
-   (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
-
-   Horizontal values are in dotclock cycles (35 ns), vertical values are in
-   scanlines.
-
-   (0, 0) is somewhere in the upper-left corner :-)
-
-
-   Dependencies (AGA, SHRES (35 ns dotclock))
-   -------------------------------------------
-
-   Since there are much more parameters for the Amiga display than for the
-   frame buffer interface, there must be some dependencies among the Amiga
-   display parameters. Here's what I found out:
-
-      - ddfstrt and ddfstop are best aligned to 64 pixels.
-      - the chipset needs 64 + 4 horizontal pixels after the DMA start before
-	the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
-	to display the first pixel on the line too. Increase diwstrt_h for
-	virtual screen panning.
-      - the display DMA always fetches 64 pixels at a time (fmode = 3).
-      - ddfstop is ddfstrt+#pixels - 64.
-      - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
-	be 1 more than htotal.
-      - hscroll simply adds a delay to the display output. Smooth horizontal
-	panning needs an extra 64 pixels on the left to prefetch the pixels that
-	`fall off' on the left.
-      - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
-	DMA, so it's best to make the DMA start as late as possible.
-      - you really don't want to make ddfstrt < 128, since this will steal DMA
-	cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
-      - I make diwstop_h and diwstop_v as large as possible.
-
-   General dependencies
-   --------------------
-
-      - all values are SHRES pixel (35ns)
-
-		  table 1:fetchstart  table 2:prefetch    table 3:fetchsize
-		  ------------------  ----------------    -----------------
-   Pixclock     # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
-   -------------#------+-----+------#------+-----+------#------+-----+------
-   Bus width 1x #   16 |  32 |  64  #   16 |  32 |  64  #   64 |  64 |  64
-   Bus width 2x #   32 |  64 | 128  #   32 |  64 |  64  #   64 |  64 | 128
-   Bus width 4x #   64 | 128 | 256  #   64 |  64 |  64  #   64 | 128 | 256
-
-      - chipset needs 4 pixels before the first pixel is output
-      - ddfstrt must be aligned to fetchstart (table 1)
-      - chipset needs also prefetch (table 2) to get first pixel data, so
-	ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
-      - for horizontal panning decrease diwstrt_h
-      - the length of a fetchline must be aligned to fetchsize (table 3)
-      - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
-	moved to optimize use of dma (useful for OCS/ECS overscan displays)
-      - ddfstop is ddfstrt + ddfsize - fetchsize
-      - If C= didn't change anything for AGA, then at following positions the
-	dma bus is already used:
-	ddfstrt <  48 -> memory refresh
-		<  96 -> disk dma
-		< 160 -> audio dma
-		< 192 -> sprite 0 dma
-		< 416 -> sprite dma (32 per sprite)
-      - in accordance with the hardware reference manual a hardware stop is at
-	192, but AGA (ECS?) can go below this.
-
-   DMA priorities
-   --------------
-
-   Since there are limits on the earliest start value for display DMA and the
-   display of sprites, I use the following policy on horizontal panning and
-   the hardware cursor:
-
-      - if you want to start display DMA too early, you lose the ability to
-	do smooth horizontal panning (xpanstep 1 -> 64).
-      - if you want to go even further, you lose the hardware cursor too.
-
-   IMHO a hardware cursor is more important for X than horizontal scrolling,
-   so that's my motivation.
-
-
-   Implementation
-   --------------
-
-   ami_decode_var() converts the frame buffer values to the Amiga values. It's
-   just a `straightforward' implementation of the above rules.
-
-
-   Standard VGA timings
-   --------------------
-
-	       xres  yres    left  right  upper  lower    hsync    vsync
-	       ----  ----    ----  -----  -----  -----    -----    -----
-      80x25     720   400      27     45     35     12      108        2
-      80x30     720   480      27     45     30      9      108        2
-
-   These were taken from a XFree86 configuration file, recalculated for a 28 MHz
-   dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
-   generic timings.
-
-   As a comparison, graphics/monitor.h suggests the following:
-
-	       xres  yres    left  right  upper  lower    hsync    vsync
-	       ----  ----    ----  -----  -----  -----    -----    -----
-
-      VGA       640   480      52    112     24     19    112 -      2 +
-      VGA70     640   400      52    112     27     21    112 -      2 -
-
-
-   Sync polarities
-   ---------------
-
-      VSYNC    HSYNC    Vertical size    Vertical total
-      -----    -----    -------------    --------------
-	+        +           Reserved          Reserved
-	+        -                400               414
-	-        +                350               362
-	-        -                480               496
-
-   Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
-
-
-   Broadcast video timings
-   -----------------------
-
-   According to the CCIR and RETMA specifications, we have the following values:
-
-   CCIR -> PAL
-   -----------
-
-      - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
-	736 visible 70 ns pixels per line.
-      - we have 625 scanlines, of which 575 are visible (interlaced); after
-	rounding this becomes 576.
-
-   RETMA -> NTSC
-   -------------
-
-      - a scanline is 63.5 µs long, of which 53.5 µs are visible.  This is about
-	736 visible 70 ns pixels per line.
-      - we have 525 scanlines, of which 485 are visible (interlaced); after
-	rounding this becomes 484.
-
-   Thus if you want a PAL compatible display, you have to do the following:
-
-      - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
-	timings are to be used.
-      - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
-	interlaced, 312 for a non-interlaced and 156 for a doublescanned
-	display.
-      - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
-	SHRES, 908 for a HIRES and 454 for a LORES display.
-      - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
-	left_margin + 2 * hsync_len must be greater or equal.
-      - the upper visible part begins at 48 (interlaced; non-interlaced:24,
-	doublescanned:12), upper_margin + 2 * vsync_len must be greater or
-	equal.
-      - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
-	of 4 scanlines
-
-   The settings for a NTSC compatible display are straightforward.
-
-   Note that in a strict sense the PAL and NTSC standards only define the
-   encoding of the color part (chrominance) of the video signal and don't say
-   anything about horizontal/vertical synchronization nor refresh rates.
-
-
-							    -- Geert --
-
-*******************************************************************************/
-
-
-	/*
-	 * Custom Chipset Definitions
-	 */
-
-#define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
-
-	/*
-	 * BPLCON0 -- Bitplane Control Register 0
-	 */
-
-#define BPC0_HIRES	(0x8000)
-#define BPC0_BPU2	(0x4000) /* Bit plane used count */
-#define BPC0_BPU1	(0x2000)
-#define BPC0_BPU0	(0x1000)
-#define BPC0_HAM	(0x0800) /* HAM mode */
-#define BPC0_DPF	(0x0400) /* Double playfield */
-#define BPC0_COLOR	(0x0200) /* Enable colorburst */
-#define BPC0_GAUD	(0x0100) /* Genlock audio enable */
-#define BPC0_UHRES	(0x0080) /* Ultrahi res enable */
-#define BPC0_SHRES	(0x0040) /* Super hi res mode */
-#define BPC0_BYPASS	(0x0020) /* Bypass LUT - AGA */
-#define BPC0_BPU3	(0x0010) /* AGA */
-#define BPC0_LPEN	(0x0008) /* Light pen enable */
-#define BPC0_LACE	(0x0004) /* Interlace */
-#define BPC0_ERSY	(0x0002) /* External resync */
-#define BPC0_ECSENA	(0x0001) /* ECS enable */
-
-	/*
-	 * BPLCON2 -- Bitplane Control Register 2
-	 */
-
-#define BPC2_ZDBPSEL2	(0x4000) /* Bitplane to be used for ZD - AGA */
-#define BPC2_ZDBPSEL1	(0x2000)
-#define BPC2_ZDBPSEL0	(0x1000)
-#define BPC2_ZDBPEN	(0x0800) /* Enable ZD with ZDBPSELx - AGA */
-#define BPC2_ZDCTEN	(0x0400) /* Enable ZD with palette bit #31 - AGA */
-#define BPC2_KILLEHB	(0x0200) /* Kill EHB mode - AGA */
-#define BPC2_RDRAM	(0x0100) /* Color table accesses read, not write - AGA */
-#define BPC2_SOGEN	(0x0080) /* SOG output pin high - AGA */
-#define BPC2_PF2PRI	(0x0040) /* PF2 priority over PF1 */
-#define BPC2_PF2P2	(0x0020) /* PF2 priority wrt sprites */
-#define BPC2_PF2P1	(0x0010)
-#define BPC2_PF2P0	(0x0008)
-#define BPC2_PF1P2	(0x0004) /* ditto PF1 */
-#define BPC2_PF1P1	(0x0002)
-#define BPC2_PF1P0	(0x0001)
-
-	/*
-	 * BPLCON3 -- Bitplane Control Register 3 (AGA)
-	 */
-
-#define BPC3_BANK2	(0x8000) /* Bits to select color register bank */
-#define BPC3_BANK1	(0x4000)
-#define BPC3_BANK0	(0x2000)
-#define BPC3_PF2OF2	(0x1000) /* Bits for color table offset when PF2 */
-#define BPC3_PF2OF1	(0x0800)
-#define BPC3_PF2OF0	(0x0400)
-#define BPC3_LOCT	(0x0200) /* Color register writes go to low bits */
-#define BPC3_SPRES1	(0x0080) /* Sprite resolution bits */
-#define BPC3_SPRES0	(0x0040)
-#define BPC3_BRDRBLNK	(0x0020) /* Border blanked? */
-#define BPC3_BRDRTRAN	(0x0010) /* Border transparent? */
-#define BPC3_ZDCLKEN	(0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
-#define BPC3_BRDRSPRT	(0x0002) /* Sprites in border? */
-#define BPC3_EXTBLKEN	(0x0001) /* BLANK programmable */
-
-	/*
-	 * BPLCON4 -- Bitplane Control Register 4 (AGA)
-	 */
-
-#define BPC4_BPLAM7	(0x8000) /* bitplane color XOR field */
-#define BPC4_BPLAM6	(0x4000)
-#define BPC4_BPLAM5	(0x2000)
-#define BPC4_BPLAM4	(0x1000)
-#define BPC4_BPLAM3	(0x0800)
-#define BPC4_BPLAM2	(0x0400)
-#define BPC4_BPLAM1	(0x0200)
-#define BPC4_BPLAM0	(0x0100)
-#define BPC4_ESPRM7	(0x0080) /* 4 high bits for even sprite colors */
-#define BPC4_ESPRM6	(0x0040)
-#define BPC4_ESPRM5	(0x0020)
-#define BPC4_ESPRM4	(0x0010)
-#define BPC4_OSPRM7	(0x0008) /* 4 high bits for odd sprite colors */
-#define BPC4_OSPRM6	(0x0004)
-#define BPC4_OSPRM5	(0x0002)
-#define BPC4_OSPRM4	(0x0001)
-
-	/*
-	 * BEAMCON0 -- Beam Control Register
-	 */
-
-#define BMC0_HARDDIS	(0x4000) /* Disable hardware limits */
-#define BMC0_LPENDIS	(0x2000) /* Disable light pen latch */
-#define BMC0_VARVBEN	(0x1000) /* Enable variable vertical blank */
-#define BMC0_LOLDIS	(0x0800) /* Disable long/short line toggle */
-#define BMC0_CSCBEN	(0x0400) /* Composite sync/blank */
-#define BMC0_VARVSYEN	(0x0200) /* Enable variable vertical sync */
-#define BMC0_VARHSYEN	(0x0100) /* Enable variable horizontal sync */
-#define BMC0_VARBEAMEN	(0x0080) /* Enable variable beam counters */
-#define BMC0_DUAL	(0x0040) /* Enable alternate horizontal beam counter */
-#define BMC0_PAL	(0x0020) /* Set decodes for PAL */
-#define BMC0_VARCSYEN	(0x0010) /* Enable variable composite sync */
-#define BMC0_BLANKEN	(0x0008) /* Blank enable (no longer used on AGA) */
-#define BMC0_CSYTRUE	(0x0004) /* CSY polarity */
-#define BMC0_VSYTRUE	(0x0002) /* VSY polarity */
-#define BMC0_HSYTRUE	(0x0001) /* HSY polarity */
-
-
-	/*
-	 * FMODE -- Fetch Mode Control Register (AGA)
-	 */
-
-#define FMODE_SSCAN2	(0x8000) /* Sprite scan-doubling */
-#define FMODE_BSCAN2	(0x4000) /* Use PF2 modulus every other line */
-#define FMODE_SPAGEM	(0x0008) /* Sprite page mode */
-#define FMODE_SPR32	(0x0004) /* Sprite 32 bit fetch */
-#define FMODE_BPAGEM	(0x0002) /* Bitplane page mode */
-#define FMODE_BPL32	(0x0001) /* Bitplane 32 bit fetch */
-
-	/*
-	 * Tags used to indicate a specific Pixel Clock
-	 *
-	 * clk_shift is the shift value to get the timings in 35 ns units
-	 */
-
-enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
-
-	/*
-	 * Tags used to indicate the specific chipset
-	 */
-
-enum { TAG_OCS, TAG_ECS, TAG_AGA };
-
-	/*
-	 * Tags used to indicate the memory bandwidth
-	 */
-
-enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
-
-
-	/*
-	 * Clock Definitions, Maximum Display Depth
-	 *
-	 * These depend on the E-Clock or the Chipset, so they are filled in
-	 * dynamically
-	 */
-
-static u_long pixclock[3];	/* SHRES/HIRES/LORES: index = clk_shift */
-static u_short maxdepth[3];	/* SHRES/HIRES/LORES: index = clk_shift */
-static u_short maxfmode, chipset;
-
-
-	/*
-	 * Broadcast Video Timings
-	 *
-	 * Horizontal values are in 35 ns (SHRES) units
-	 * Vertical values are in interlaced scanlines
-	 */
-
-#define PAL_DIWSTRT_H	(360)	/* PAL Window Limits */
-#define PAL_DIWSTRT_V	(48)
-#define PAL_HTOTAL	(1816)
-#define PAL_VTOTAL	(625)
-
-#define NTSC_DIWSTRT_H	(360)	/* NTSC Window Limits */
-#define NTSC_DIWSTRT_V	(40)
-#define NTSC_HTOTAL	(1816)
-#define NTSC_VTOTAL	(525)
-
-
-	/*
-	 * Various macros
-	 */
-
-#define up2(v)		(((v) + 1) & -2)
-#define down2(v)	((v) & -2)
-#define div2(v)		((v)>>1)
-#define mod2(v)		((v) & 1)
-
-#define up4(v)		(((v) + 3) & -4)
-#define down4(v)	((v) & -4)
-#define mul4(v)		((v) << 2)
-#define div4(v)		((v)>>2)
-#define mod4(v)		((v) & 3)
-
-#define up8(v)		(((v) + 7) & -8)
-#define down8(v)	((v) & -8)
-#define div8(v)		((v)>>3)
-#define mod8(v)		((v) & 7)
-
-#define up16(v)		(((v) + 15) & -16)
-#define down16(v)	((v) & -16)
-#define div16(v)	((v)>>4)
-#define mod16(v)	((v) & 15)
-
-#define up32(v)		(((v) + 31) & -32)
-#define down32(v)	((v) & -32)
-#define div32(v)	((v)>>5)
-#define mod32(v)	((v) & 31)
-
-#define up64(v)		(((v) + 63) & -64)
-#define down64(v)	((v) & -64)
-#define div64(v)	((v)>>6)
-#define mod64(v)	((v) & 63)
-
-#define upx(x, v)	(((v) + (x) - 1) & -(x))
-#define downx(x, v)	((v) & -(x))
-#define modx(x, v)	((v) & ((x) - 1))
-
-/* if x1 is not a constant, this macro won't make real sense :-) */
-#ifdef __mc68000__
-#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
-	"d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
-#else
-/* We know a bit about the numbers, so we can do it this way */
-#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
-	((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
-#endif
-
-#define highw(x)	((u_long)(x)>>16 & 0xffff)
-#define loww(x)		((u_long)(x) & 0xffff)
-
-#define custom		amiga_custom
-
-#define VBlankOn()	custom.intena = IF_SETCLR|IF_COPER
-#define VBlankOff()	custom.intena = IF_COPER
-
-
-	/*
-	 * Chip RAM we reserve for the Frame Buffer
-	 *
-	 * This defines the Maximum Virtual Screen Size
-	 * (Setable per kernel options?)
-	 */
-
-#define VIDEOMEMSIZE_AGA_2M	(1310720) /* AGA (2MB) : max 1280*1024*256  */
-#define VIDEOMEMSIZE_AGA_1M	(786432)  /* AGA (1MB) : max 1024*768*256   */
-#define VIDEOMEMSIZE_ECS_2M	(655360)  /* ECS (2MB) : max 1280*1024*16   */
-#define VIDEOMEMSIZE_ECS_1M	(393216)  /* ECS (1MB) : max 1024*768*16    */
-#define VIDEOMEMSIZE_OCS	(262144)  /* OCS       : max ca. 800*600*16 */
-
-#define SPRITEMEMSIZE		(64 * 64 / 4) /* max 64*64*4 */
-#define DUMMYSPRITEMEMSIZE	(8)
-static u_long spritememory;
-
-#define CHIPRAM_SAFETY_LIMIT	(16384)
-
-static u_long videomemory;
-
-	/*
-	 * This is the earliest allowed start of fetching display data.
-	 * Only if you really want no hardware cursor and audio,
-	 * set this to 128, but let it better at 192
-	 */
-
-static u_long min_fstrt = 192;
-
-#define assignchunk(name, type, ptr, size) \
-{ \
-	(name) = (type)(ptr); \
-	ptr += size; \
-}
-
-
-	/*
-	 * Copper Instructions
-	 */
-
-#define CMOVE(val, reg)		(CUSTOM_OFS(reg) << 16 | (val))
-#define CMOVE2(val, reg)	((CUSTOM_OFS(reg) + 2) << 16 | (val))
-#define CWAIT(x, y)		(((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
-#define CEND			(0xfffffffe)
-
-
-typedef union {
-	u_long l;
-	u_short w[2];
-} copins;
-
-static struct copdisplay {
-	copins *init;
-	copins *wait;
-	copins *list[2][2];
-	copins *rebuild[2];
-} copdisplay;
-
-static u_short currentcop = 0;
-
-	/*
-	 * Hardware Cursor API Definitions
-	 * These used to be in linux/fb.h, but were preliminary and used by
-	 * amifb only anyway
-	 */
-
-#define FBIOGET_FCURSORINFO     0x4607
-#define FBIOGET_VCURSORINFO     0x4608
-#define FBIOPUT_VCURSORINFO     0x4609
-#define FBIOGET_CURSORSTATE     0x460A
-#define FBIOPUT_CURSORSTATE     0x460B
-
-
-struct fb_fix_cursorinfo {
-	__u16 crsr_width;		/* width and height of the cursor in */
-	__u16 crsr_height;		/* pixels (zero if no cursor)	*/
-	__u16 crsr_xsize;		/* cursor size in display pixels */
-	__u16 crsr_ysize;
-	__u16 crsr_color1;		/* colormap entry for cursor color1 */
-	__u16 crsr_color2;		/* colormap entry for cursor color2 */
-};
-
-struct fb_var_cursorinfo {
-	__u16 width;
-	__u16 height;
-	__u16 xspot;
-	__u16 yspot;
-	__u8 data[1];			/* field with [height][width]        */
-};
-
-struct fb_cursorstate {
-	__s16 xoffset;
-	__s16 yoffset;
-	__u16 mode;
-};
-
-#define FB_CURSOR_OFF		0
-#define FB_CURSOR_ON		1
-#define FB_CURSOR_FLASH		2
-
-
-	/*
-	 * Hardware Cursor
-	 */
-
-static int cursorrate = 20;	/* Number of frames/flash toggle */
-static u_short cursorstate = -1;
-static u_short cursormode = FB_CURSOR_OFF;
-
-static u_short *lofsprite, *shfsprite, *dummysprite;
-
-	/*
-	 * Current Video Mode
-	 */
-
-struct amifb_par {
-
-	/* General Values */
-
-	int xres;		/* vmode */
-	int yres;		/* vmode */
-	int vxres;		/* vmode */
-	int vyres;		/* vmode */
-	int xoffset;		/* vmode */
-	int yoffset;		/* vmode */
-	u_short bpp;		/* vmode */
-	u_short clk_shift;	/* vmode */
-	u_short line_shift;	/* vmode */
-	int vmode;		/* vmode */
-	u_short diwstrt_h;	/* vmode */
-	u_short diwstop_h;	/* vmode */
-	u_short diwstrt_v;	/* vmode */
-	u_short diwstop_v;	/* vmode */
-	u_long next_line;	/* modulo for next line */
-	u_long next_plane;	/* modulo for next plane */
-
-	/* Cursor Values */
-
-	struct {
-		short crsr_x;	/* movecursor */
-		short crsr_y;	/* movecursor */
-		short spot_x;
-		short spot_y;
-		u_short height;
-		u_short width;
-		u_short fmode;
-	} crsr;
-
-	/* OCS Hardware Registers */
-
-	u_long bplpt0;		/* vmode, pan (Note: physical address) */
-	u_long bplpt0wrap;	/* vmode, pan (Note: physical address) */
-	u_short ddfstrt;
-	u_short ddfstop;
-	u_short bpl1mod;
-	u_short bpl2mod;
-	u_short bplcon0;	/* vmode */
-	u_short bplcon1;	/* vmode */
-	u_short htotal;		/* vmode */
-	u_short vtotal;		/* vmode */
-
-	/* Additional ECS Hardware Registers */
-
-	u_short bplcon3;	/* vmode */
-	u_short beamcon0;	/* vmode */
-	u_short hsstrt;		/* vmode */
-	u_short hsstop;		/* vmode */
-	u_short hbstrt;		/* vmode */
-	u_short hbstop;		/* vmode */
-	u_short vsstrt;		/* vmode */
-	u_short vsstop;		/* vmode */
-	u_short vbstrt;		/* vmode */
-	u_short vbstop;		/* vmode */
-	u_short hcenter;	/* vmode */
-
-	/* Additional AGA Hardware Registers */
-
-	u_short fmode;		/* vmode */
-};
-
-
-	/*
-	 *  Saved color entry 0 so we can restore it when unblanking
-	 */
-
-static u_char red0, green0, blue0;
-
-
-#if defined(CONFIG_FB_AMIGA_ECS)
-static u_short ecs_palette[32];
-#endif
-
-
-	/*
-	 * Latches for Display Changes during VBlank
-	 */
-
-static u_short do_vmode_full = 0;	/* Change the Video Mode */
-static u_short do_vmode_pan = 0;	/* Update the Video Mode */
-static short do_blank = 0;		/* (Un)Blank the Screen (±1) */
-static u_short do_cursor = 0;		/* Move the Cursor */
-
-
-	/*
-	 * Various Flags
-	 */
-
-static u_short is_blanked = 0;		/* Screen is Blanked */
-static u_short is_lace = 0;		/* Screen is laced */
-
-	/*
-	 * Predefined Video Modes
-	 *
-	 */
-
-static struct fb_videomode ami_modedb[] __initdata = {
-
-	/*
-	 *  AmigaOS Video Modes
-	 *
-	 *  If you change these, make sure to update DEFMODE_* as well!
-	 */
-
-	{
-		/* 640x200, 15 kHz, 60 Hz (NTSC) */
-		"ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
-		FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
-		"ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
-		FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x256, 15 kHz, 50 Hz (PAL) */
-		"pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
-		FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
-		"pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
-		FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x480, 29 kHz, 57 Hz */
-		"multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x960, 29 kHz, 57 Hz interlaced */
-		"multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
-		16,
-		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x200, 15 kHz, 72 Hz */
-		"euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x400, 15 kHz, 72 Hz interlaced */
-		"euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
-		10,
-		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x400, 29 kHz, 68 Hz */
-		"euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x800, 29 kHz, 68 Hz interlaced */
-		"euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
-		16,
-		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 800x300, 23 kHz, 70 Hz */
-		"super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 800x600, 23 kHz, 70 Hz interlaced */
-		"super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
-		14,
-		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x200, 27 kHz, 57 Hz doublescan */
-		"dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
-		0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
-	}, {
-		/* 640x400, 27 kHz, 57 Hz */
-		"dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x800, 27 kHz, 57 Hz interlaced */
-		"dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
-		14,
-		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x256, 27 kHz, 47 Hz doublescan */
-		"dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
-		0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
-	}, {
-		/* 640x512, 27 kHz, 47 Hz */
-		"dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x1024, 27 kHz, 47 Hz interlaced */
-		"dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
-		14,
-		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-	},
-
-	/*
-	 *  VGA Video Modes
-	 */
-
-	{
-		/* 640x480, 31 kHz, 60 Hz (VGA) */
-		"vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x400, 31 kHz, 70 Hz (VGA) */
-		"vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
-		FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
-		FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	},
-
-#if 0
-
-	/*
-	 *  A2024 video modes
-	 *  These modes don't work yet because there's no A2024 driver.
-	 */
-
-	{
-		/* 1024x800, 10 Hz */
-		"a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 1024x800, 15 Hz */
-		"a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}
-#endif
-};
-
-#define NUM_TOTAL_MODES  ARRAY_SIZE(ami_modedb)
-
-static char *mode_option __initdata = NULL;
-static int round_down_bpp = 1;	/* for mode probing */
-
-	/*
-	 * Some default modes
-	 */
-
-
-#define DEFMODE_PAL	    2	/* "pal" for PAL OCS/ECS */
-#define DEFMODE_NTSC	    0	/* "ntsc" for NTSC OCS/ECS */
-#define DEFMODE_AMBER_PAL   3	/* "pal-lace" for flicker fixed PAL (A3000) */
-#define DEFMODE_AMBER_NTSC  1	/* "ntsc-lace" for flicker fixed NTSC (A3000) */
-#define DEFMODE_AGA	    19	/* "vga70" for AGA */
-
-
-static int amifb_ilbm = 0;	/* interleaved or normal bitplanes */
-
-static u32 amifb_hfmin __initdata;	/* monitor hfreq lower limit (Hz) */
-static u32 amifb_hfmax __initdata;	/* monitor hfreq upper limit (Hz) */
-static u16 amifb_vfmin __initdata;	/* monitor vfreq lower limit (Hz) */
-static u16 amifb_vfmax __initdata;	/* monitor vfreq upper limit (Hz) */
-
-
-	/*
-	 * Macros for the conversion from real world values to hardware register
-	 * values
-	 *
-	 * This helps us to keep our attention on the real stuff...
-	 *
-	 * Hardware limits for AGA:
-	 *
-	 *	parameter  min    max  step
-	 *	---------  ---   ----  ----
-	 *	diwstrt_h    0   2047     1
-	 *	diwstrt_v    0   2047     1
-	 *	diwstop_h    0   4095     1
-	 *	diwstop_v    0   4095     1
-	 *
-	 *	ddfstrt      0   2032    16
-	 *	ddfstop      0   2032    16
-	 *
-	 *	htotal       8   2048     8
-	 *	hsstrt       0   2040     8
-	 *	hsstop       0   2040     8
-	 *	vtotal       1   4096     1
-	 *	vsstrt       0   4095     1
-	 *	vsstop       0   4095     1
-	 *	hcenter      0   2040     8
-	 *
-	 *	hbstrt       0   2047     1
-	 *	hbstop       0   2047     1
-	 *	vbstrt       0   4095     1
-	 *	vbstop       0   4095     1
-	 *
-	 * Horizontal values are in 35 ns (SHRES) pixels
-	 * Vertical values are in half scanlines
-	 */
-
-/* bplcon1 (smooth scrolling) */
-
-#define hscroll2hw(hscroll) \
-	(((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
-	 ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
-	 ((hscroll)>>2 & 0x000f))
-
-/* diwstrt/diwstop/diwhigh (visible display window) */
-
-#define diwstrt2hw(diwstrt_h, diwstrt_v) \
-	(((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
-#define diwstop2hw(diwstop_h, diwstop_v) \
-	(((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
-#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
-	(((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
-	 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
-	 ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
-
-/* ddfstrt/ddfstop (display DMA) */
-
-#define ddfstrt2hw(ddfstrt)	div8(ddfstrt)
-#define ddfstop2hw(ddfstop)	div8(ddfstop)
-
-/* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */
-
-#define hsstrt2hw(hsstrt)	(div8(hsstrt))
-#define hsstop2hw(hsstop)	(div8(hsstop))
-#define htotal2hw(htotal)	(div8(htotal) - 1)
-#define vsstrt2hw(vsstrt)	(div2(vsstrt))
-#define vsstop2hw(vsstop)	(div2(vsstop))
-#define vtotal2hw(vtotal)	(div2(vtotal) - 1)
-#define hcenter2hw(htotal)	(div8(htotal))
-
-/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
-
-#define hbstrt2hw(hbstrt)	(((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
-#define hbstop2hw(hbstop)	(((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
-#define vbstrt2hw(vbstrt)	(div2(vbstrt))
-#define vbstop2hw(vbstop)	(div2(vbstop))
-
-/* colour */
-
-#define rgb2hw8_high(red, green, blue) \
-	(((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
-#define rgb2hw8_low(red, green, blue) \
-	(((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
-#define rgb2hw4(red, green, blue) \
-	(((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
-#define rgb2hw2(red, green, blue) \
-	(((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
-
-/* sprpos/sprctl (sprite positioning) */
-
-#define spr2hw_pos(start_v, start_h) \
-	(((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
-#define spr2hw_ctl(start_v, start_h, stop_v) \
-	(((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
-	 ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
-	 ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
-	 ((start_h)>>2 & 0x0001))
-
-/* get current vertical position of beam */
-#define get_vbpos()	((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
-
-	/*
-	 * Copper Initialisation List
-	 */
-
-#define COPINITSIZE (sizeof(copins) * 40)
-
-enum {
-	cip_bplcon0
-};
-
-	/*
-	 * Long Frame/Short Frame Copper List
-	 * Don't change the order, build_copper()/rebuild_copper() rely on this
-	 */
-
-#define COPLISTSIZE (sizeof(copins) * 64)
-
-enum {
-	cop_wait, cop_bplcon0,
-	cop_spr0ptrh, cop_spr0ptrl,
-	cop_diwstrt, cop_diwstop,
-	cop_diwhigh,
-};
-
-	/*
-	 * Pixel modes for Bitplanes and Sprites
-	 */
-
-static u_short bplpixmode[3] = {
-	BPC0_SHRES,			/*  35 ns */
-	BPC0_HIRES,			/*  70 ns */
-	0				/* 140 ns */
-};
-
-static u_short sprpixmode[3] = {
-	BPC3_SPRES1 | BPC3_SPRES0,	/*  35 ns */
-	BPC3_SPRES1,			/*  70 ns */
-	BPC3_SPRES0			/* 140 ns */
-};
-
-	/*
-	 * Fetch modes for Bitplanes and Sprites
-	 */
-
-static u_short bplfetchmode[3] = {
-	0,				/* 1x */
-	FMODE_BPL32,			/* 2x */
-	FMODE_BPAGEM | FMODE_BPL32	/* 4x */
-};
-
-static u_short sprfetchmode[3] = {
-	0,				/* 1x */
-	FMODE_SPR32,			/* 2x */
-	FMODE_SPAGEM | FMODE_SPR32	/* 4x */
-};
-
-
-/* --------------------------- Hardware routines --------------------------- */
-
-	/*
-	 * Get the video params out of `var'. If a value doesn't fit, round
-	 * it up, if it's too big, return -EINVAL.
-	 */
-
-static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
-			  const struct fb_info *info)
-{
-	u_short clk_shift, line_shift;
-	u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
-	u_int htotal, vtotal;
-
-	/*
-	 * Find a matching Pixel Clock
-	 */
-
-	for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
-		if (var->pixclock <= pixclock[clk_shift])
-			break;
-	if (clk_shift > TAG_LORES) {
-		DPRINTK("pixclock too high\n");
-		return -EINVAL;
-	}
-	par->clk_shift = clk_shift;
-
-	/*
-	 * Check the Geometry Values
-	 */
-
-	if ((par->xres = var->xres) < 64)
-		par->xres = 64;
-	if ((par->yres = var->yres) < 64)
-		par->yres = 64;
-	if ((par->vxres = var->xres_virtual) < par->xres)
-		par->vxres = par->xres;
-	if ((par->vyres = var->yres_virtual) < par->yres)
-		par->vyres = par->yres;
-
-	par->bpp = var->bits_per_pixel;
-	if (!var->nonstd) {
-		if (par->bpp < 1)
-			par->bpp = 1;
-		if (par->bpp > maxdepth[clk_shift]) {
-			if (round_down_bpp && maxdepth[clk_shift])
-				par->bpp = maxdepth[clk_shift];
-			else {
-				DPRINTK("invalid bpp\n");
-				return -EINVAL;
-			}
-		}
-	} else if (var->nonstd == FB_NONSTD_HAM) {
-		if (par->bpp < 6)
-			par->bpp = 6;
-		if (par->bpp != 6) {
-			if (par->bpp < 8)
-				par->bpp = 8;
-			if (par->bpp != 8 || !IS_AGA) {
-				DPRINTK("invalid bpp for ham mode\n");
-				return -EINVAL;
-			}
-		}
-	} else {
-		DPRINTK("unknown nonstd mode\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the following
-	 * checks failed and smooth scrolling is not possible
-	 */
-
-	par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
-	switch (par->vmode & FB_VMODE_MASK) {
-	case FB_VMODE_INTERLACED:
-		line_shift = 0;
-		break;
-	case FB_VMODE_NONINTERLACED:
-		line_shift = 1;
-		break;
-	case FB_VMODE_DOUBLE:
-		if (!IS_AGA) {
-			DPRINTK("double mode only possible with aga\n");
-			return -EINVAL;
-		}
-		line_shift = 2;
-		break;
-	default:
-		DPRINTK("unknown video mode\n");
-		return -EINVAL;
-		break;
-	}
-	par->line_shift = line_shift;
-
-	/*
-	 * Vertical and Horizontal Timings
-	 */
-
-	xres_n = par->xres << clk_shift;
-	yres_n = par->yres << line_shift;
-	par->htotal = down8((var->left_margin + par->xres + var->right_margin +
-			     var->hsync_len) << clk_shift);
-	par->vtotal =
-		down2(((var->upper_margin + par->yres + var->lower_margin +
-			var->vsync_len) << line_shift) + 1);
-
-	if (IS_AGA)
-		par->bplcon3 = sprpixmode[clk_shift];
-	else
-		par->bplcon3 = 0;
-	if (var->sync & FB_SYNC_BROADCAST) {
-		par->diwstop_h = par->htotal -
-			((var->right_margin - var->hsync_len) << clk_shift);
-		if (IS_AGA)
-			par->diwstop_h += mod4(var->hsync_len);
-		else
-			par->diwstop_h = down4(par->diwstop_h);
-
-		par->diwstrt_h = par->diwstop_h - xres_n;
-		par->diwstop_v = par->vtotal -
-			((var->lower_margin - var->vsync_len) << line_shift);
-		par->diwstrt_v = par->diwstop_v - yres_n;
-		if (par->diwstop_h >= par->htotal + 8) {
-			DPRINTK("invalid diwstop_h\n");
-			return -EINVAL;
-		}
-		if (par->diwstop_v > par->vtotal) {
-			DPRINTK("invalid diwstop_v\n");
-			return -EINVAL;
-		}
-
-		if (!IS_OCS) {
-			/* Initialize sync with some reasonable values for pwrsave */
-			par->hsstrt = 160;
-			par->hsstop = 320;
-			par->vsstrt = 30;
-			par->vsstop = 34;
-		} else {
-			par->hsstrt = 0;
-			par->hsstop = 0;
-			par->vsstrt = 0;
-			par->vsstop = 0;
-		}
-		if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
-			/* PAL video mode */
-			if (par->htotal != PAL_HTOTAL) {
-				DPRINTK("htotal invalid for pal\n");
-				return -EINVAL;
-			}
-			if (par->diwstrt_h < PAL_DIWSTRT_H) {
-				DPRINTK("diwstrt_h too low for pal\n");
-				return -EINVAL;
-			}
-			if (par->diwstrt_v < PAL_DIWSTRT_V) {
-				DPRINTK("diwstrt_v too low for pal\n");
-				return -EINVAL;
-			}
-			htotal = PAL_HTOTAL>>clk_shift;
-			vtotal = PAL_VTOTAL>>1;
-			if (!IS_OCS) {
-				par->beamcon0 = BMC0_PAL;
-				par->bplcon3 |= BPC3_BRDRBLNK;
-			} else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
-				   AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
-				par->beamcon0 = BMC0_PAL;
-				par->hsstop = 1;
-			} else if (amiga_vblank != 50) {
-				DPRINTK("pal not supported by this chipset\n");
-				return -EINVAL;
-			}
-		} else {
-			/* NTSC video mode
-			 * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
-			 * and NTSC activated, so than better let diwstop_h <= 1812
-			 */
-			if (par->htotal != NTSC_HTOTAL) {
-				DPRINTK("htotal invalid for ntsc\n");
-				return -EINVAL;
-			}
-			if (par->diwstrt_h < NTSC_DIWSTRT_H) {
-				DPRINTK("diwstrt_h too low for ntsc\n");
-				return -EINVAL;
-			}
-			if (par->diwstrt_v < NTSC_DIWSTRT_V) {
-				DPRINTK("diwstrt_v too low for ntsc\n");
-				return -EINVAL;
-			}
-			htotal = NTSC_HTOTAL>>clk_shift;
-			vtotal = NTSC_VTOTAL>>1;
-			if (!IS_OCS) {
-				par->beamcon0 = 0;
-				par->bplcon3 |= BPC3_BRDRBLNK;
-			} else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
-				   AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
-				par->beamcon0 = 0;
-				par->hsstop = 1;
-			} else if (amiga_vblank != 60) {
-				DPRINTK("ntsc not supported by this chipset\n");
-				return -EINVAL;
-			}
-		}
-		if (IS_OCS) {
-			if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
-			    par->diwstrt_v >=  512 || par->diwstop_v <  256) {
-				DPRINTK("invalid position for display on ocs\n");
-				return -EINVAL;
-			}
-		}
-	} else if (!IS_OCS) {
-		/* Programmable video mode */
-		par->hsstrt = var->right_margin << clk_shift;
-		par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
-		par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
-		if (!IS_AGA)
-			par->diwstop_h = down4(par->diwstop_h) - 16;
-		par->diwstrt_h = par->diwstop_h - xres_n;
-		par->hbstop = par->diwstrt_h + 4;
-		par->hbstrt = par->diwstop_h + 4;
-		if (par->hbstrt >= par->htotal + 8)
-			par->hbstrt -= par->htotal;
-		par->hcenter = par->hsstrt + (par->htotal >> 1);
-		par->vsstrt = var->lower_margin << line_shift;
-		par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
-		par->diwstop_v = par->vtotal;
-		if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
-			par->diwstop_v -= 2;
-		par->diwstrt_v = par->diwstop_v - yres_n;
-		par->vbstop = par->diwstrt_v - 2;
-		par->vbstrt = par->diwstop_v - 2;
-		if (par->vtotal > 2048) {
-			DPRINTK("vtotal too high\n");
-			return -EINVAL;
-		}
-		if (par->htotal > 2048) {
-			DPRINTK("htotal too high\n");
-			return -EINVAL;
-		}
-		par->bplcon3 |= BPC3_EXTBLKEN;
-		par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
-				BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
-				BMC0_PAL | BMC0_VARCSYEN;
-		if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-			par->beamcon0 |= BMC0_HSYTRUE;
-		if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-			par->beamcon0 |= BMC0_VSYTRUE;
-		if (var->sync & FB_SYNC_COMP_HIGH_ACT)
-			par->beamcon0 |= BMC0_CSYTRUE;
-		htotal = par->htotal>>clk_shift;
-		vtotal = par->vtotal>>1;
-	} else {
-		DPRINTK("only broadcast modes possible for ocs\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Checking the DMA timing
-	 */
-
-	fconst = 16 << maxfmode << clk_shift;
-
-	/*
-	 * smallest window start value without turn off other dma cycles
-	 * than sprite1-7, unless you change min_fstrt
-	 */
-
-
-	fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
-	fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
-	if (fstrt < min_fstrt) {
-		DPRINTK("fetch start too low\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * smallest window start value where smooth scrolling is possible
-	 */
-
-	fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
-		fsize;
-	if (fstrt < min_fstrt)
-		par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
-	maxfetchstop = down16(par->htotal - 80);
-
-	fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
-	fsize = upx(fconst, xres_n +
-		    modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
-	if (fstrt + fsize > maxfetchstop)
-		par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
-	fsize = upx(fconst, xres_n);
-	if (fstrt + fsize > maxfetchstop) {
-		DPRINTK("fetch stop too high\n");
-		return -EINVAL;
-	}
-
-	if (maxfmode + clk_shift <= 1) {
-		fsize = up64(xres_n + fconst - 1);
-		if (min_fstrt + fsize - 64 > maxfetchstop)
-			par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
-		fsize = up64(xres_n);
-		if (min_fstrt + fsize - 64 > maxfetchstop) {
-			DPRINTK("fetch size too high\n");
-			return -EINVAL;
-		}
-
-		fsize -= 64;
-	} else
-		fsize -= fconst;
-
-	/*
-	 * Check if there is enough time to update the bitplane pointers for ywrap
-	 */
-
-	if (par->htotal - fsize - 64 < par->bpp * 64)
-		par->vmode &= ~FB_VMODE_YWRAP;
-
-	/*
-	 * Bitplane calculations and check the Memory Requirements
-	 */
-
-	if (amifb_ilbm) {
-		par->next_plane = div8(upx(16 << maxfmode, par->vxres));
-		par->next_line = par->bpp * par->next_plane;
-		if (par->next_line * par->vyres > info->fix.smem_len) {
-			DPRINTK("too few video mem\n");
-			return -EINVAL;
-		}
-	} else {
-		par->next_line = div8(upx(16 << maxfmode, par->vxres));
-		par->next_plane = par->vyres * par->next_line;
-		if (par->next_plane * par->bpp > info->fix.smem_len) {
-			DPRINTK("too few video mem\n");
-			return -EINVAL;
-		}
-	}
-
-	/*
-	 * Hardware Register Values
-	 */
-
-	par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
-	if (!IS_OCS)
-		par->bplcon0 |= BPC0_ECSENA;
-	if (par->bpp == 8)
-		par->bplcon0 |= BPC0_BPU3;
-	else
-		par->bplcon0 |= par->bpp << 12;
-	if (var->nonstd == FB_NONSTD_HAM)
-		par->bplcon0 |= BPC0_HAM;
-	if (var->sync & FB_SYNC_EXT)
-		par->bplcon0 |= BPC0_ERSY;
-
-	if (IS_AGA)
-		par->fmode = bplfetchmode[maxfmode];
-
-	switch (par->vmode & FB_VMODE_MASK) {
-	case FB_VMODE_INTERLACED:
-		par->bplcon0 |= BPC0_LACE;
-		break;
-	case FB_VMODE_DOUBLE:
-		if (IS_AGA)
-			par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
-		break;
-	}
-
-	if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
-		par->xoffset = var->xoffset;
-		par->yoffset = var->yoffset;
-		if (par->vmode & FB_VMODE_YWRAP) {
-			if (par->xoffset || par->yoffset < 0 ||
-			    par->yoffset >= par->vyres)
-				par->xoffset = par->yoffset = 0;
-		} else {
-			if (par->xoffset < 0 ||
-			    par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
-			    par->yoffset < 0 || par->yoffset > par->vyres - par->yres)
-				par->xoffset = par->yoffset = 0;
-		}
-	} else
-		par->xoffset = par->yoffset = 0;
-
-	par->crsr.crsr_x = par->crsr.crsr_y = 0;
-	par->crsr.spot_x = par->crsr.spot_y = 0;
-	par->crsr.height = par->crsr.width = 0;
-
-	return 0;
-}
-
-	/*
-	 * Fill the `var' structure based on the values in `par' and maybe
-	 * other values read out of the hardware.
-	 */
-
-static void ami_encode_var(struct fb_var_screeninfo *var,
-			   struct amifb_par *par)
-{
-	u_short clk_shift, line_shift;
-
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-
-	clk_shift = par->clk_shift;
-	line_shift = par->line_shift;
-
-	var->xres = par->xres;
-	var->yres = par->yres;
-	var->xres_virtual = par->vxres;
-	var->yres_virtual = par->vyres;
-	var->xoffset = par->xoffset;
-	var->yoffset = par->yoffset;
-
-	var->bits_per_pixel = par->bpp;
-	var->grayscale = 0;
-
-	var->red.offset = 0;
-	var->red.msb_right = 0;
-	var->red.length = par->bpp;
-	if (par->bplcon0 & BPC0_HAM)
-		var->red.length -= 2;
-	var->blue = var->green = var->red;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-
-	if (par->bplcon0 & BPC0_HAM)
-		var->nonstd = FB_NONSTD_HAM;
-	else
-		var->nonstd = 0;
-	var->activate = 0;
-
-	var->height = -1;
-	var->width = -1;
-
-	var->pixclock = pixclock[clk_shift];
-
-	if (IS_AGA && par->fmode & FMODE_BSCAN2)
-		var->vmode = FB_VMODE_DOUBLE;
-	else if (par->bplcon0 & BPC0_LACE)
-		var->vmode = FB_VMODE_INTERLACED;
-	else
-		var->vmode = FB_VMODE_NONINTERLACED;
-
-	if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
-		var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
-		var->right_margin = par->hsstrt>>clk_shift;
-		var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
-		var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
-		var->lower_margin = par->vsstrt>>line_shift;
-		var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
-		var->sync = 0;
-		if (par->beamcon0 & BMC0_HSYTRUE)
-			var->sync |= FB_SYNC_HOR_HIGH_ACT;
-		if (par->beamcon0 & BMC0_VSYTRUE)
-			var->sync |= FB_SYNC_VERT_HIGH_ACT;
-		if (par->beamcon0 & BMC0_CSYTRUE)
-			var->sync |= FB_SYNC_COMP_HIGH_ACT;
-	} else {
-		var->sync = FB_SYNC_BROADCAST;
-		var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
-		var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
-		var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
-		var->vsync_len = 4>>line_shift;
-		var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
-		var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
-				    var->lower_margin - var->vsync_len;
-	}
-
-	if (par->bplcon0 & BPC0_ERSY)
-		var->sync |= FB_SYNC_EXT;
-	if (par->vmode & FB_VMODE_YWRAP)
-		var->vmode |= FB_VMODE_YWRAP;
-}
-
-
-	/*
-	 * Update hardware
-	 */
-
-static void ami_update_par(struct fb_info *info)
-{
-	struct amifb_par *par = info->par;
-	short clk_shift, vshift, fstrt, fsize, fstop, fconst,  shift, move, mod;
-
-	clk_shift = par->clk_shift;
-
-	if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
-		par->xoffset = upx(16 << maxfmode, par->xoffset);
-
-	fconst = 16 << maxfmode << clk_shift;
-	vshift = modx(16 << maxfmode, par->xoffset);
-	fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
-	fsize = (par->xres + vshift) << clk_shift;
-	shift = modx(fconst, fstrt);
-	move = downx(2 << maxfmode, div8(par->xoffset));
-	if (maxfmode + clk_shift > 1) {
-		fstrt = downx(fconst, fstrt) - 64;
-		fsize = upx(fconst, fsize);
-		fstop = fstrt + fsize - fconst;
-	} else {
-		mod = fstrt = downx(fconst, fstrt) - fconst;
-		fstop = fstrt + upx(fconst, fsize) - 64;
-		fsize = up64(fsize);
-		fstrt = fstop - fsize + 64;
-		if (fstrt < min_fstrt) {
-			fstop += min_fstrt - fstrt;
-			fstrt = min_fstrt;
-		}
-		move = move - div8((mod - fstrt)>>clk_shift);
-	}
-	mod = par->next_line - div8(fsize>>clk_shift);
-	par->ddfstrt = fstrt;
-	par->ddfstop = fstop;
-	par->bplcon1 = hscroll2hw(shift);
-	par->bpl2mod = mod;
-	if (par->bplcon0 & BPC0_LACE)
-		par->bpl2mod += par->next_line;
-	if (IS_AGA && (par->fmode & FMODE_BSCAN2))
-		par->bpl1mod = -div8(fsize>>clk_shift);
-	else
-		par->bpl1mod = par->bpl2mod;
-
-	if (par->yoffset) {
-		par->bplpt0 = info->fix.smem_start +
-			      par->next_line * par->yoffset + move;
-		if (par->vmode & FB_VMODE_YWRAP) {
-			if (par->yoffset > par->vyres - par->yres) {
-				par->bplpt0wrap = info->fix.smem_start + move;
-				if (par->bplcon0 & BPC0_LACE &&
-				    mod2(par->diwstrt_v + par->vyres -
-					 par->yoffset))
-					par->bplpt0wrap += par->next_line;
-			}
-		}
-	} else
-		par->bplpt0 = info->fix.smem_start + move;
-
-	if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
-		par->bplpt0 += par->next_line;
-}
-
-
-	/*
-	 * Pan or Wrap the Display
-	 *
-	 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-	 * in `var'.
-	 */
-
-static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct amifb_par *par = info->par;
-
-	par->xoffset = var->xoffset;
-	par->yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		par->vmode |= FB_VMODE_YWRAP;
-	else
-		par->vmode &= ~FB_VMODE_YWRAP;
-
-	do_vmode_pan = 0;
-	ami_update_par(info);
-	do_vmode_pan = 1;
-}
-
-
-static void ami_update_display(const struct amifb_par *par)
-{
-	custom.bplcon1 = par->bplcon1;
-	custom.bpl1mod = par->bpl1mod;
-	custom.bpl2mod = par->bpl2mod;
-	custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
-	custom.ddfstop = ddfstop2hw(par->ddfstop);
-}
-
-	/*
-	 * Change the video mode (called by VBlank interrupt)
-	 */
-
-static void ami_init_display(const struct amifb_par *par)
-{
-	int i;
-
-	custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
-	custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
-	if (!IS_OCS) {
-		custom.bplcon3 = par->bplcon3;
-		if (IS_AGA)
-			custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
-		if (par->beamcon0 & BMC0_VARBEAMEN) {
-			custom.htotal = htotal2hw(par->htotal);
-			custom.hbstrt = hbstrt2hw(par->hbstrt);
-			custom.hbstop = hbstop2hw(par->hbstop);
-			custom.hsstrt = hsstrt2hw(par->hsstrt);
-			custom.hsstop = hsstop2hw(par->hsstop);
-			custom.hcenter = hcenter2hw(par->hcenter);
-			custom.vtotal = vtotal2hw(par->vtotal);
-			custom.vbstrt = vbstrt2hw(par->vbstrt);
-			custom.vbstop = vbstop2hw(par->vbstop);
-			custom.vsstrt = vsstrt2hw(par->vsstrt);
-			custom.vsstop = vsstop2hw(par->vsstop);
-		}
-	}
-	if (!IS_OCS || par->hsstop)
-		custom.beamcon0 = par->beamcon0;
-	if (IS_AGA)
-		custom.fmode = par->fmode;
-
-	/*
-	 * The minimum period for audio depends on htotal
-	 */
-
-	amiga_audio_min_period = div16(par->htotal);
-
-	is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
-#if 1
-	if (is_lace) {
-		i = custom.vposr >> 15;
-	} else {
-		custom.vposw = custom.vposr | 0x8000;
-		i = 1;
-	}
-#else
-	i = 1;
-	custom.vposw = custom.vposr | 0x8000;
-#endif
-	custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
-}
-
-	/*
-	 * (Un)Blank the screen (called by VBlank interrupt)
-	 */
-
-static void ami_do_blank(const struct amifb_par *par)
-{
-#if defined(CONFIG_FB_AMIGA_AGA)
-	u_short bplcon3 = par->bplcon3;
-#endif
-	u_char red, green, blue;
-
-	if (do_blank > 0) {
-		custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
-		red = green = blue = 0;
-		if (!IS_OCS && do_blank > 1) {
-			switch (do_blank) {
-			case FB_BLANK_VSYNC_SUSPEND:
-				custom.hsstrt = hsstrt2hw(par->hsstrt);
-				custom.hsstop = hsstop2hw(par->hsstop);
-				custom.vsstrt = vsstrt2hw(par->vtotal + 4);
-				custom.vsstop = vsstop2hw(par->vtotal + 4);
-				break;
-			case FB_BLANK_HSYNC_SUSPEND:
-				custom.hsstrt = hsstrt2hw(par->htotal + 16);
-				custom.hsstop = hsstop2hw(par->htotal + 16);
-				custom.vsstrt = vsstrt2hw(par->vsstrt);
-				custom.vsstop = vsstrt2hw(par->vsstop);
-				break;
-			case FB_BLANK_POWERDOWN:
-				custom.hsstrt = hsstrt2hw(par->htotal + 16);
-				custom.hsstop = hsstop2hw(par->htotal + 16);
-				custom.vsstrt = vsstrt2hw(par->vtotal + 4);
-				custom.vsstop = vsstop2hw(par->vtotal + 4);
-				break;
-			}
-			if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
-				custom.htotal = htotal2hw(par->htotal);
-				custom.vtotal = vtotal2hw(par->vtotal);
-				custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
-						  BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
-			}
-		}
-	} else {
-		custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
-		red = red0;
-		green = green0;
-		blue = blue0;
-		if (!IS_OCS) {
-			custom.hsstrt = hsstrt2hw(par->hsstrt);
-			custom.hsstop = hsstop2hw(par->hsstop);
-			custom.vsstrt = vsstrt2hw(par->vsstrt);
-			custom.vsstop = vsstop2hw(par->vsstop);
-			custom.beamcon0 = par->beamcon0;
-		}
-	}
-#if defined(CONFIG_FB_AMIGA_AGA)
-	if (IS_AGA) {
-		custom.bplcon3 = bplcon3;
-		custom.color[0] = rgb2hw8_high(red, green, blue);
-		custom.bplcon3 = bplcon3 | BPC3_LOCT;
-		custom.color[0] = rgb2hw8_low(red, green, blue);
-		custom.bplcon3 = bplcon3;
-	} else
-#endif
-#if defined(CONFIG_FB_AMIGA_ECS)
-	if (par->bplcon0 & BPC0_SHRES) {
-		u_short color, mask;
-		int i;
-
-		mask = 0x3333;
-		color = rgb2hw2(red, green, blue);
-		for (i = 12; i >= 0; i -= 4)
-			custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-		mask <<= 2; color >>= 2;
-		for (i = 3; i >= 0; i--)
-			custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-	} else
-#endif
-		custom.color[0] = rgb2hw4(red, green, blue);
-	is_blanked = do_blank > 0 ? do_blank : 0;
-}
-
-static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
-				  const struct amifb_par *par)
-{
-	fix->crsr_width = fix->crsr_xsize = par->crsr.width;
-	fix->crsr_height = fix->crsr_ysize = par->crsr.height;
-	fix->crsr_color1 = 17;
-	fix->crsr_color2 = 18;
-	return 0;
-}
-
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
-				  u_char __user *data,
-				  const struct amifb_par *par)
-{
-	register u_short *lspr, *sspr;
-#ifdef __mc68000__
-	register u_long datawords asm ("d2");
-#else
-	register u_long datawords;
-#endif
-	register short delta;
-	register u_char color;
-	short height, width, bits, words;
-	int size, alloc;
-
-	size = par->crsr.height * par->crsr.width;
-	alloc = var->height * var->width;
-	var->height = par->crsr.height;
-	var->width = par->crsr.width;
-	var->xspot = par->crsr.spot_x;
-	var->yspot = par->crsr.spot_y;
-	if (size > var->height * var->width)
-		return -ENAMETOOLONG;
-	if (!access_ok(VERIFY_WRITE, data, size))
-		return -EFAULT;
-	delta = 1 << par->crsr.fmode;
-	lspr = lofsprite + (delta << 1);
-	if (par->bplcon0 & BPC0_LACE)
-		sspr = shfsprite + (delta << 1);
-	else
-		sspr = NULL;
-	for (height = (short)var->height - 1; height >= 0; height--) {
-		bits = 0; words = delta; datawords = 0;
-		for (width = (short)var->width - 1; width >= 0; width--) {
-			if (bits == 0) {
-				bits = 16; --words;
-#ifdef __mc68000__
-				asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
-					: "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
-#else
-				datawords = (*(lspr + delta) << 16) | (*lspr++);
-#endif
-			}
-			--bits;
-#ifdef __mc68000__
-			asm volatile (
-				"clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
-				"swap %1 ; lslw #1,%1 ; roxlb #1,%0"
-				: "=d" (color), "=d" (datawords) : "1" (datawords));
-#else
-			color = (((datawords >> 30) & 2)
-				 | ((datawords >> 15) & 1));
-			datawords <<= 1;
-#endif
-			put_user(color, data++);
-		}
-		if (bits > 0) {
-			--words; ++lspr;
-		}
-		while (--words >= 0)
-			++lspr;
-#ifdef __mc68000__
-		asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
-			: "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
-#else
-		lspr += delta;
-		if (sspr) {
-			u_short *tmp = lspr;
-			lspr = sspr;
-			sspr = tmp;
-		}
-#endif
-	}
-	return 0;
-}
-
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
-				  u_char __user *data, struct amifb_par *par)
-{
-	register u_short *lspr, *sspr;
-#ifdef __mc68000__
-	register u_long datawords asm ("d2");
-#else
-	register u_long datawords;
-#endif
-	register short delta;
-	u_short fmode;
-	short height, width, bits, words;
-
-	if (!var->width)
-		return -EINVAL;
-	else if (var->width <= 16)
-		fmode = TAG_FMODE_1;
-	else if (var->width <= 32)
-		fmode = TAG_FMODE_2;
-	else if (var->width <= 64)
-		fmode = TAG_FMODE_4;
-	else
-		return -EINVAL;
-	if (fmode > maxfmode)
-		return -EINVAL;
-	if (!var->height)
-		return -EINVAL;
-	if (!access_ok(VERIFY_READ, data, var->width * var->height))
-		return -EFAULT;
-	delta = 1 << fmode;
-	lofsprite = shfsprite = (u_short *)spritememory;
-	lspr = lofsprite + (delta << 1);
-	if (par->bplcon0 & BPC0_LACE) {
-		if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
-			return -EINVAL;
-		memset(lspr, 0, (var->height + 4) << fmode << 2);
-		shfsprite += ((var->height + 5)&-2) << fmode;
-		sspr = shfsprite + (delta << 1);
-	} else {
-		if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
-			return -EINVAL;
-		memset(lspr, 0, (var->height + 2) << fmode << 2);
-		sspr = NULL;
-	}
-	for (height = (short)var->height - 1; height >= 0; height--) {
-		bits = 16; words = delta; datawords = 0;
-		for (width = (short)var->width - 1; width >= 0; width--) {
-			unsigned long tdata = 0;
-			get_user(tdata, data);
-			data++;
-#ifdef __mc68000__
-			asm volatile (
-				"lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
-				"lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
-				: "=d" (datawords)
-				: "0" (datawords), "d" (tdata));
-#else
-			datawords = ((datawords << 1) & 0xfffefffe);
-			datawords |= tdata & 1;
-			datawords |= (tdata & 2) << (16 - 1);
-#endif
-			if (--bits == 0) {
-				bits = 16; --words;
-#ifdef __mc68000__
-				asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
-					: "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
-#else
-				*(lspr + delta) = (u_short) (datawords >> 16);
-				*lspr++ = (u_short) (datawords & 0xffff);
-#endif
-			}
-		}
-		if (bits < 16) {
-			--words;
-#ifdef __mc68000__
-			asm volatile (
-				"swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
-				"swap %2 ; lslw %4,%2 ; movew %2,%0@+"
-				: "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
-#else
-			*(lspr + delta) = (u_short) (datawords >> (16 + bits));
-			*lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
-#endif
-		}
-		while (--words >= 0) {
-#ifdef __mc68000__
-			asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
-				: "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
-#else
-			*(lspr + delta) = 0;
-			*lspr++ = 0;
-#endif
-		}
-#ifdef __mc68000__
-		asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
-			: "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
-#else
-		lspr += delta;
-		if (sspr) {
-			u_short *tmp = lspr;
-			lspr = sspr;
-			sspr = tmp;
-		}
-#endif
-	}
-	par->crsr.height = var->height;
-	par->crsr.width = var->width;
-	par->crsr.spot_x = var->xspot;
-	par->crsr.spot_y = var->yspot;
-	par->crsr.fmode = fmode;
-	if (IS_AGA) {
-		par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
-		par->fmode |= sprfetchmode[fmode];
-		custom.fmode = par->fmode;
-	}
-	return 0;
-}
-
-static int ami_get_cursorstate(struct fb_cursorstate *state,
-			       const struct amifb_par *par)
-{
-	state->xoffset = par->crsr.crsr_x;
-	state->yoffset = par->crsr.crsr_y;
-	state->mode = cursormode;
-	return 0;
-}
-
-static int ami_set_cursorstate(struct fb_cursorstate *state,
-			       struct amifb_par *par)
-{
-	par->crsr.crsr_x = state->xoffset;
-	par->crsr.crsr_y = state->yoffset;
-	if ((cursormode = state->mode) == FB_CURSOR_OFF)
-		cursorstate = -1;
-	do_cursor = 1;
-	return 0;
-}
-
-static void ami_set_sprite(const struct amifb_par *par)
-{
-	copins *copl, *cops;
-	u_short hs, vs, ve;
-	u_long pl, ps, pt;
-	short mx, my;
-
-	cops = copdisplay.list[currentcop][0];
-	copl = copdisplay.list[currentcop][1];
-	ps = pl = ZTWO_PADDR(dummysprite);
-	mx = par->crsr.crsr_x - par->crsr.spot_x;
-	my = par->crsr.crsr_y - par->crsr.spot_y;
-	if (!(par->vmode & FB_VMODE_YWRAP)) {
-		mx -= par->xoffset;
-		my -= par->yoffset;
-	}
-	if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
-	    mx > -(short)par->crsr.width && mx < par->xres &&
-	    my > -(short)par->crsr.height && my < par->yres) {
-		pl = ZTWO_PADDR(lofsprite);
-		hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
-		vs = par->diwstrt_v + (my << par->line_shift);
-		ve = vs + (par->crsr.height << par->line_shift);
-		if (par->bplcon0 & BPC0_LACE) {
-			ps = ZTWO_PADDR(shfsprite);
-			lofsprite[0] = spr2hw_pos(vs, hs);
-			shfsprite[0] = spr2hw_pos(vs + 1, hs);
-			if (mod2(vs)) {
-				lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
-				shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
-				pt = pl; pl = ps; ps = pt;
-			} else {
-				lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
-				shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
-			}
-		} else {
-			lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
-			lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
-		}
-	}
-	copl[cop_spr0ptrh].w[1] = highw(pl);
-	copl[cop_spr0ptrl].w[1] = loww(pl);
-	if (par->bplcon0 & BPC0_LACE) {
-		cops[cop_spr0ptrh].w[1] = highw(ps);
-		cops[cop_spr0ptrl].w[1] = loww(ps);
-	}
-}
-
-
-	/*
-	 * Initialise the Copper Initialisation List
-	 */
-
-static void __init ami_init_copper(void)
-{
-	copins *cop = copdisplay.init;
-	u_long p;
-	int i;
-
-	if (!IS_OCS) {
-		(cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
-		(cop++)->l = CMOVE(0x0181, diwstrt);
-		(cop++)->l = CMOVE(0x0281, diwstop);
-		(cop++)->l = CMOVE(0x0000, diwhigh);
-	} else
-		(cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
-	p = ZTWO_PADDR(dummysprite);
-	for (i = 0; i < 8; i++) {
-		(cop++)->l = CMOVE(0, spr[i].pos);
-		(cop++)->l = CMOVE(highw(p), sprpt[i]);
-		(cop++)->l = CMOVE2(loww(p), sprpt[i]);
-	}
-
-	(cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
-	copdisplay.wait = cop;
-	(cop++)->l = CEND;
-	(cop++)->l = CMOVE(0, copjmp2);
-	cop->l = CEND;
-
-	custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
-	custom.copjmp1 = 0;
-}
-
-static void ami_reinit_copper(const struct amifb_par *par)
-{
-	copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
-	copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
-}
-
-
-	/*
-	 * Rebuild the Copper List
-	 *
-	 * We only change the things that are not static
-	 */
-
-static void ami_rebuild_copper(const struct amifb_par *par)
-{
-	copins *copl, *cops;
-	u_short line, h_end1, h_end2;
-	short i;
-	u_long p;
-
-	if (IS_AGA && maxfmode + par->clk_shift == 0)
-		h_end1 = par->diwstrt_h - 64;
-	else
-		h_end1 = par->htotal - 32;
-	h_end2 = par->ddfstop + 64;
-
-	ami_set_sprite(par);
-
-	copl = copdisplay.rebuild[1];
-	p = par->bplpt0;
-	if (par->vmode & FB_VMODE_YWRAP) {
-		if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
-			if (par->yoffset > par->vyres - par->yres) {
-				for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
-					(copl++)->l = CMOVE(highw(p), bplpt[i]);
-					(copl++)->l = CMOVE2(loww(p), bplpt[i]);
-				}
-				line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
-				while (line >= 512) {
-					(copl++)->l = CWAIT(h_end1, 510);
-					line -= 512;
-				}
-				if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
-					(copl++)->l = CWAIT(h_end1, line);
-				else
-					(copl++)->l = CWAIT(h_end2, line);
-				p = par->bplpt0wrap;
-			}
-		} else
-			p = par->bplpt0wrap;
-	}
-	for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
-		(copl++)->l = CMOVE(highw(p), bplpt[i]);
-		(copl++)->l = CMOVE2(loww(p), bplpt[i]);
-	}
-	copl->l = CEND;
-
-	if (par->bplcon0 & BPC0_LACE) {
-		cops = copdisplay.rebuild[0];
-		p = par->bplpt0;
-		if (mod2(par->diwstrt_v))
-			p -= par->next_line;
-		else
-			p += par->next_line;
-		if (par->vmode & FB_VMODE_YWRAP) {
-			if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
-				if (par->yoffset > par->vyres - par->yres + 1) {
-					for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
-						(cops++)->l = CMOVE(highw(p), bplpt[i]);
-						(cops++)->l = CMOVE2(loww(p), bplpt[i]);
-					}
-					line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
-					while (line >= 512) {
-						(cops++)->l = CWAIT(h_end1, 510);
-						line -= 512;
-					}
-					if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
-						(cops++)->l = CWAIT(h_end1, line);
-					else
-						(cops++)->l = CWAIT(h_end2, line);
-					p = par->bplpt0wrap;
-					if (mod2(par->diwstrt_v + par->vyres -
-					    par->yoffset))
-						p -= par->next_line;
-					else
-						p += par->next_line;
-				}
-			} else
-				p = par->bplpt0wrap - par->next_line;
-		}
-		for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
-			(cops++)->l = CMOVE(highw(p), bplpt[i]);
-			(cops++)->l = CMOVE2(loww(p), bplpt[i]);
-		}
-		cops->l = CEND;
-	}
-}
-
-
-	/*
-	 * Build the Copper List
-	 */
-
-static void ami_build_copper(struct fb_info *info)
-{
-	struct amifb_par *par = info->par;
-	copins *copl, *cops;
-	u_long p;
-
-	currentcop = 1 - currentcop;
-
-	copl = copdisplay.list[currentcop][1];
-
-	(copl++)->l = CWAIT(0, 10);
-	(copl++)->l = CMOVE(par->bplcon0, bplcon0);
-	(copl++)->l = CMOVE(0, sprpt[0]);
-	(copl++)->l = CMOVE2(0, sprpt[0]);
-
-	if (par->bplcon0 & BPC0_LACE) {
-		cops = copdisplay.list[currentcop][0];
-
-		(cops++)->l = CWAIT(0, 10);
-		(cops++)->l = CMOVE(par->bplcon0, bplcon0);
-		(cops++)->l = CMOVE(0, sprpt[0]);
-		(cops++)->l = CMOVE2(0, sprpt[0]);
-
-		(copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
-		(copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
-		(cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
-		(cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
-		if (!IS_OCS) {
-			(copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
-					    par->diwstop_h, par->diwstop_v + 1), diwhigh);
-			(cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
-					    par->diwstop_h, par->diwstop_v), diwhigh);
-#if 0
-			if (par->beamcon0 & BMC0_VARBEAMEN) {
-				(copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
-				(copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
-				(copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
-				(cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
-				(cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
-				(cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
-			}
-#endif
-		}
-		p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
-		(copl++)->l = CMOVE(highw(p), cop2lc);
-		(copl++)->l = CMOVE2(loww(p), cop2lc);
-		p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
-		(cops++)->l = CMOVE(highw(p), cop2lc);
-		(cops++)->l = CMOVE2(loww(p), cop2lc);
-		copdisplay.rebuild[0] = cops;
-	} else {
-		(copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
-		(copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
-		if (!IS_OCS) {
-			(copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
-					    par->diwstop_h, par->diwstop_v), diwhigh);
-#if 0
-			if (par->beamcon0 & BMC0_VARBEAMEN) {
-				(copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
-				(copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
-				(copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
-			}
-#endif
-		}
-	}
-	copdisplay.rebuild[1] = copl;
-
-	ami_update_par(info);
-	ami_rebuild_copper(info->par);
-}
-
-
-static void __init amifb_setup_mcap(char *spec)
-{
-	char *p;
-	int vmin, vmax, hmin, hmax;
-
-	/* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
-	 * <V*> vertical freq. in Hz
-	 * <H*> horizontal freq. in kHz
-	 */
-
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	vmin = simple_strtoul(p, NULL, 10);
-	if (vmin <= 0)
-		return;
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	vmax = simple_strtoul(p, NULL, 10);
-	if (vmax <= 0 || vmax <= vmin)
-		return;
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	hmin = 1000 * simple_strtoul(p, NULL, 10);
-	if (hmin <= 0)
-		return;
-	if (!(p = strsep(&spec, "")) || !*p)
-		return;
-	hmax = 1000 * simple_strtoul(p, NULL, 10);
-	if (hmax <= 0 || hmax <= hmin)
-		return;
-
-	amifb_hfmin = hmin;
-	amifb_hfmax = hmax;
-	amifb_vfmin = vmin;
-	amifb_vfmax = vmax;
-}
-
-static int __init amifb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			fb_invert_cmaps();
-		} else if (!strcmp(this_opt, "ilbm"))
-			amifb_ilbm = 1;
-		else if (!strncmp(this_opt, "monitorcap:", 11))
-			amifb_setup_mcap(this_opt + 11);
-		else if (!strncmp(this_opt, "fstart:", 7))
-			min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
-		else
-			mode_option = this_opt;
-	}
-
-	if (min_fstrt < 48)
-		min_fstrt = 48;
-
-	return 0;
-}
-
-
-static int amifb_check_var(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
-{
-	int err;
-	struct amifb_par par;
-
-	/* Validate wanted screen parameters */
-	err = ami_decode_var(var, &par, info);
-	if (err)
-		return err;
-
-	/* Encode (possibly rounded) screen parameters */
-	ami_encode_var(var, &par);
-	return 0;
-}
-
-
-static int amifb_set_par(struct fb_info *info)
-{
-	struct amifb_par *par = info->par;
-	int error;
-
-	do_vmode_pan = 0;
-	do_vmode_full = 0;
-
-	/* Decode wanted screen parameters */
-	error = ami_decode_var(&info->var, par, info);
-	if (error)
-		return error;
-
-	/* Set new videomode */
-	ami_build_copper(info);
-
-	/* Set VBlank trigger */
-	do_vmode_full = 1;
-
-	/* Update fix for new screen parameters */
-	if (par->bpp == 1) {
-		info->fix.type = FB_TYPE_PACKED_PIXELS;
-		info->fix.type_aux = 0;
-	} else if (amifb_ilbm) {
-		info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
-		info->fix.type_aux = par->next_line;
-	} else {
-		info->fix.type = FB_TYPE_PLANES;
-		info->fix.type_aux = 0;
-	}
-	info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
-
-	if (par->vmode & FB_VMODE_YWRAP) {
-		info->fix.ywrapstep = 1;
-		info->fix.xpanstep = 0;
-		info->fix.ypanstep = 0;
-		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
-			FBINFO_READS_FAST; /* override SCROLL_REDRAW */
-	} else {
-		info->fix.ywrapstep = 0;
-		if (par->vmode & FB_VMODE_SMOOTH_XPAN)
-			info->fix.xpanstep = 1;
-		else
-			info->fix.xpanstep = 16 << maxfmode;
-		info->fix.ypanstep = 1;
-		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	}
-	return 0;
-}
-
-
-	/*
-	 * Set a single color register. The values supplied are already
-	 * rounded down to the hardware's capabilities (according to the
-	 * entries in the var structure). Return != 0 for invalid regno.
-	 */
-
-static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	const struct amifb_par *par = info->par;
-
-	if (IS_AGA) {
-		if (regno > 255)
-			return 1;
-	} else if (par->bplcon0 & BPC0_SHRES) {
-		if (regno > 3)
-			return 1;
-	} else {
-		if (regno > 31)
-			return 1;
-	}
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	if (!regno) {
-		red0 = red;
-		green0 = green;
-		blue0 = blue;
-	}
-
-	/*
-	 * Update the corresponding Hardware Color Register, unless it's Color
-	 * Register 0 and the screen is blanked.
-	 *
-	 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
-	 * being changed by ami_do_blank() during the VBlank.
-	 */
-
-	if (regno || !is_blanked) {
-#if defined(CONFIG_FB_AMIGA_AGA)
-		if (IS_AGA) {
-			u_short bplcon3 = par->bplcon3;
-			VBlankOff();
-			custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
-			custom.color[regno & 31] = rgb2hw8_high(red, green,
-								blue);
-			custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
-					 BPC3_LOCT;
-			custom.color[regno & 31] = rgb2hw8_low(red, green,
-							       blue);
-			custom.bplcon3 = bplcon3;
-			VBlankOn();
-		} else
-#endif
-#if defined(CONFIG_FB_AMIGA_ECS)
-		if (par->bplcon0 & BPC0_SHRES) {
-			u_short color, mask;
-			int i;
-
-			mask = 0x3333;
-			color = rgb2hw2(red, green, blue);
-			VBlankOff();
-			for (i = regno + 12; i >= (int)regno; i -= 4)
-				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-			mask <<= 2; color >>= 2;
-			regno = down16(regno) + mul4(mod4(regno));
-			for (i = regno + 3; i >= (int)regno; i--)
-				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-			VBlankOn();
-		} else
-#endif
-			custom.color[regno] = rgb2hw4(red, green, blue);
-	}
-	return 0;
-}
-
-
-	/*
-	 * Blank the display.
-	 */
-
-static int amifb_blank(int blank, struct fb_info *info)
-{
-	do_blank = blank ? blank : -1;
-
-	return 0;
-}
-
-
-	/*
-	 * Pan or Wrap the Display
-	 *
-	 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-	 */
-
-static int amifb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 ||
-			var->yoffset >= info->var.yres_virtual || var->xoffset)
-				return -EINVAL;
-	} else {
-		/*
-		 * TODO: There will be problems when xpan!=1, so some columns
-		 * on the right side will never be seen
-		 */
-		if (var->xoffset + info->var.xres >
-		    upx(16 << maxfmode, info->var.xres_virtual) ||
-		    var->yoffset + info->var.yres > info->var.yres_virtual)
-			return -EINVAL;
-	}
-	ami_pan_var(var, info);
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-	return 0;
-}
-
-
-#if BITS_PER_LONG == 32
-#define BYTES_PER_LONG	4
-#define SHIFT_PER_LONG	5
-#elif BITS_PER_LONG == 64
-#define BYTES_PER_LONG	8
-#define SHIFT_PER_LONG	6
-#else
-#define Please update me
-#endif
-
-
-	/*
-	 *  Compose two values, using a bitmask as decision value
-	 *  This is equivalent to (a & mask) | (b & ~mask)
-	 */
-
-static inline unsigned long comp(unsigned long a, unsigned long b,
-				 unsigned long mask)
-{
-	return ((a ^ b) & mask) ^ b;
-}
-
-
-static inline unsigned long xor(unsigned long a, unsigned long b,
-				unsigned long mask)
-{
-	return (a & mask) ^ b;
-}
-
-
-	/*
-	 *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses
-	 */
-
-static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
-		   int src_idx, u32 n)
-{
-	unsigned long first, last;
-	int shift = dst_idx - src_idx, left, right;
-	unsigned long d0, d1;
-	int m;
-
-	if (!n)
-		return;
-
-	shift = dst_idx - src_idx;
-	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
-	if (!shift) {
-		// Same alignment for source and dest
-
-		if (dst_idx + n <= BITS_PER_LONG) {
-			// Single word
-			if (last)
-				first &= last;
-			*dst = comp(*src, *dst, first);
-		} else {
-			// Multiple destination words
-			// Leading bits
-			if (first) {
-				*dst = comp(*src, *dst, first);
-				dst++;
-				src++;
-				n -= BITS_PER_LONG - dst_idx;
-			}
-
-			// Main chunk
-			n /= BITS_PER_LONG;
-			while (n >= 8) {
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				n -= 8;
-			}
-			while (n--)
-				*dst++ = *src++;
-
-			// Trailing bits
-			if (last)
-				*dst = comp(*src, *dst, last);
-		}
-	} else {
-		// Different alignment for source and dest
-
-		right = shift & (BITS_PER_LONG - 1);
-		left = -shift & (BITS_PER_LONG - 1);
-
-		if (dst_idx + n <= BITS_PER_LONG) {
-			// Single destination word
-			if (last)
-				first &= last;
-			if (shift > 0) {
-				// Single source word
-				*dst = comp(*src >> right, *dst, first);
-			} else if (src_idx + n <= BITS_PER_LONG) {
-				// Single source word
-				*dst = comp(*src << left, *dst, first);
-			} else {
-				// 2 source words
-				d0 = *src++;
-				d1 = *src;
-				*dst = comp(d0 << left | d1 >> right, *dst,
-					    first);
-			}
-		} else {
-			// Multiple destination words
-			d0 = *src++;
-			// Leading bits
-			if (shift > 0) {
-				// Single source word
-				*dst = comp(d0 >> right, *dst, first);
-				dst++;
-				n -= BITS_PER_LONG - dst_idx;
-			} else {
-				// 2 source words
-				d1 = *src++;
-				*dst = comp(d0 << left | d1 >> right, *dst,
-					    first);
-				d0 = d1;
-				dst++;
-				n -= BITS_PER_LONG - dst_idx;
-			}
-
-			// Main chunk
-			m = n % BITS_PER_LONG;
-			n /= BITS_PER_LONG;
-			while (n >= 4) {
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				n -= 4;
-			}
-			while (n--) {
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-			}
-
-			// Trailing bits
-			if (last) {
-				if (m <= right) {
-					// Single source word
-					*dst = comp(d0 << left, *dst, last);
-				} else {
-					// 2 source words
-					d1 = *src;
-					*dst = comp(d0 << left | d1 >> right,
-						    *dst, last);
-				}
-			}
-		}
-	}
-}
-
-
-	/*
-	 *  Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
-	 */
-
-static void bitcpy_rev(unsigned long *dst, int dst_idx,
-		       const unsigned long *src, int src_idx, u32 n)
-{
-	unsigned long first, last;
-	int shift = dst_idx - src_idx, left, right;
-	unsigned long d0, d1;
-	int m;
-
-	if (!n)
-		return;
-
-	dst += (n - 1) / BITS_PER_LONG;
-	src += (n - 1) / BITS_PER_LONG;
-	if ((n - 1) % BITS_PER_LONG) {
-		dst_idx += (n - 1) % BITS_PER_LONG;
-		dst += dst_idx >> SHIFT_PER_LONG;
-		dst_idx &= BITS_PER_LONG - 1;
-		src_idx += (n - 1) % BITS_PER_LONG;
-		src += src_idx >> SHIFT_PER_LONG;
-		src_idx &= BITS_PER_LONG - 1;
-	}
-
-	shift = dst_idx - src_idx;
-	first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
-	last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
-
-	if (!shift) {
-		// Same alignment for source and dest
-
-		if ((unsigned long)dst_idx + 1 >= n) {
-			// Single word
-			if (last)
-				first &= last;
-			*dst = comp(*src, *dst, first);
-		} else {
-			// Multiple destination words
-			// Leading bits
-			if (first) {
-				*dst = comp(*src, *dst, first);
-				dst--;
-				src--;
-				n -= dst_idx + 1;
-			}
-
-			// Main chunk
-			n /= BITS_PER_LONG;
-			while (n >= 8) {
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				n -= 8;
-			}
-			while (n--)
-				*dst-- = *src--;
-
-			// Trailing bits
-			if (last)
-				*dst = comp(*src, *dst, last);
-		}
-	} else {
-		// Different alignment for source and dest
-
-		right = shift & (BITS_PER_LONG - 1);
-		left = -shift & (BITS_PER_LONG - 1);
-
-		if ((unsigned long)dst_idx + 1 >= n) {
-			// Single destination word
-			if (last)
-				first &= last;
-			if (shift < 0) {
-				// Single source word
-				*dst = comp(*src << left, *dst, first);
-			} else if (1 + (unsigned long)src_idx >= n) {
-				// Single source word
-				*dst = comp(*src >> right, *dst, first);
-			} else {
-				// 2 source words
-				d0 = *src--;
-				d1 = *src;
-				*dst = comp(d0 >> right | d1 << left, *dst,
-					    first);
-			}
-		} else {
-			// Multiple destination words
-			d0 = *src--;
-			// Leading bits
-			if (shift < 0) {
-				// Single source word
-				*dst = comp(d0 << left, *dst, first);
-				dst--;
-				n -= dst_idx + 1;
-			} else {
-				// 2 source words
-				d1 = *src--;
-				*dst = comp(d0 >> right | d1 << left, *dst,
-					    first);
-				d0 = d1;
-				dst--;
-				n -= dst_idx + 1;
-			}
-
-			// Main chunk
-			m = n % BITS_PER_LONG;
-			n /= BITS_PER_LONG;
-			while (n >= 4) {
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				n -= 4;
-			}
-			while (n--) {
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-			}
-
-			// Trailing bits
-			if (last) {
-				if (m <= left) {
-					// Single source word
-					*dst = comp(d0 >> right, *dst, last);
-				} else {
-					// 2 source words
-					d1 = *src;
-					*dst = comp(d0 >> right | d1 << left,
-						    *dst, last);
-				}
-			}
-		}
-	}
-}
-
-
-	/*
-	 *  Unaligned forward inverting bit copy using 32-bit or 64-bit memory
-	 *  accesses
-	 */
-
-static void bitcpy_not(unsigned long *dst, int dst_idx,
-		       const unsigned long *src, int src_idx, u32 n)
-{
-	unsigned long first, last;
-	int shift = dst_idx - src_idx, left, right;
-	unsigned long d0, d1;
-	int m;
-
-	if (!n)
-		return;
-
-	shift = dst_idx - src_idx;
-	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
-	if (!shift) {
-		// Same alignment for source and dest
-
-		if (dst_idx + n <= BITS_PER_LONG) {
-			// Single word
-			if (last)
-				first &= last;
-			*dst = comp(~*src, *dst, first);
-		} else {
-			// Multiple destination words
-			// Leading bits
-			if (first) {
-				*dst = comp(~*src, *dst, first);
-				dst++;
-				src++;
-				n -= BITS_PER_LONG - dst_idx;
-			}
-
-			// Main chunk
-			n /= BITS_PER_LONG;
-			while (n >= 8) {
-				*dst++ = ~*src++;
-				*dst++ = ~*src++;
-				*dst++ = ~*src++;
-				*dst++ = ~*src++;
-				*dst++ = ~*src++;
-				*dst++ = ~*src++;
-				*dst++ = ~*src++;
-				*dst++ = ~*src++;
-				n -= 8;
-			}
-			while (n--)
-				*dst++ = ~*src++;
-
-			// Trailing bits
-			if (last)
-				*dst = comp(~*src, *dst, last);
-		}
-	} else {
-		// Different alignment for source and dest
-
-		right = shift & (BITS_PER_LONG - 1);
-		left = -shift & (BITS_PER_LONG - 1);
-
-		if (dst_idx + n <= BITS_PER_LONG) {
-			// Single destination word
-			if (last)
-				first &= last;
-			if (shift > 0) {
-				// Single source word
-				*dst = comp(~*src >> right, *dst, first);
-			} else if (src_idx + n <= BITS_PER_LONG) {
-				// Single source word
-				*dst = comp(~*src << left, *dst, first);
-			} else {
-				// 2 source words
-				d0 = ~*src++;
-				d1 = ~*src;
-				*dst = comp(d0 << left | d1 >> right, *dst,
-					    first);
-			}
-		} else {
-			// Multiple destination words
-			d0 = ~*src++;
-			// Leading bits
-			if (shift > 0) {
-				// Single source word
-				*dst = comp(d0 >> right, *dst, first);
-				dst++;
-				n -= BITS_PER_LONG - dst_idx;
-			} else {
-				// 2 source words
-				d1 = ~*src++;
-				*dst = comp(d0 << left | d1 >> right, *dst,
-					    first);
-				d0 = d1;
-				dst++;
-				n -= BITS_PER_LONG - dst_idx;
-			}
-
-			// Main chunk
-			m = n % BITS_PER_LONG;
-			n /= BITS_PER_LONG;
-			while (n >= 4) {
-				d1 = ~*src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = ~*src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = ~*src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = ~*src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				n -= 4;
-			}
-			while (n--) {
-				d1 = ~*src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-			}
-
-			// Trailing bits
-			if (last) {
-				if (m <= right) {
-					// Single source word
-					*dst = comp(d0 << left, *dst, last);
-				} else {
-					// 2 source words
-					d1 = ~*src;
-					*dst = comp(d0 << left | d1 >> right,
-						    *dst, last);
-				}
-			}
-		}
-	}
-}
-
-
-	/*
-	 *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
-	 */
-
-static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
-{
-	unsigned long val = pat;
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-#if BITS_PER_LONG == 64
-	val |= val << 32;
-#endif
-
-	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
-	if (dst_idx + n <= BITS_PER_LONG) {
-		// Single word
-		if (last)
-			first &= last;
-		*dst = comp(val, *dst, first);
-	} else {
-		// Multiple destination words
-		// Leading bits
-		if (first) {
-			*dst = comp(val, *dst, first);
-			dst++;
-			n -= BITS_PER_LONG - dst_idx;
-		}
-
-		// Main chunk
-		n /= BITS_PER_LONG;
-		while (n >= 8) {
-			*dst++ = val;
-			*dst++ = val;
-			*dst++ = val;
-			*dst++ = val;
-			*dst++ = val;
-			*dst++ = val;
-			*dst++ = val;
-			*dst++ = val;
-			n -= 8;
-		}
-		while (n--)
-			*dst++ = val;
-
-		// Trailing bits
-		if (last)
-			*dst = comp(val, *dst, last);
-	}
-}
-
-
-	/*
-	 *  Unaligned 32-bit pattern xor using 32/64-bit memory accesses
-	 */
-
-static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
-{
-	unsigned long val = pat;
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-#if BITS_PER_LONG == 64
-	val |= val << 32;
-#endif
-
-	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
-	if (dst_idx + n <= BITS_PER_LONG) {
-		// Single word
-		if (last)
-			first &= last;
-		*dst = xor(val, *dst, first);
-	} else {
-		// Multiple destination words
-		// Leading bits
-		if (first) {
-			*dst = xor(val, *dst, first);
-			dst++;
-			n -= BITS_PER_LONG - dst_idx;
-		}
-
-		// Main chunk
-		n /= BITS_PER_LONG;
-		while (n >= 4) {
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			n -= 4;
-		}
-		while (n--)
-			*dst++ ^= val;
-
-		// Trailing bits
-		if (last)
-			*dst = xor(val, *dst, last);
-	}
-}
-
-static inline void fill_one_line(int bpp, unsigned long next_plane,
-				 unsigned long *dst, int dst_idx, u32 n,
-				 u32 color)
-{
-	while (1) {
-		dst += dst_idx >> SHIFT_PER_LONG;
-		dst_idx &= (BITS_PER_LONG - 1);
-		bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
-		if (!--bpp)
-			break;
-		color >>= 1;
-		dst_idx += next_plane * 8;
-	}
-}
-
-static inline void xor_one_line(int bpp, unsigned long next_plane,
-				unsigned long *dst, int dst_idx, u32 n,
-				u32 color)
-{
-	while (color) {
-		dst += dst_idx >> SHIFT_PER_LONG;
-		dst_idx &= (BITS_PER_LONG - 1);
-		bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
-		if (!--bpp)
-			break;
-		color >>= 1;
-		dst_idx += next_plane * 8;
-	}
-}
-
-
-static void amifb_fillrect(struct fb_info *info,
-			   const struct fb_fillrect *rect)
-{
-	struct amifb_par *par = info->par;
-	int dst_idx, x2, y2;
-	unsigned long *dst;
-	u32 width, height;
-
-	if (!rect->width || !rect->height)
-		return;
-
-	/*
-	 * We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly.
-	 * */
-	x2 = rect->dx + rect->width;
-	y2 = rect->dy + rect->height;
-	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
-	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	width = x2 - rect->dx;
-	height = y2 - rect->dy;
-
-	dst = (unsigned long *)
-		((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
-	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
-	dst_idx += rect->dy * par->next_line * 8 + rect->dx;
-	while (height--) {
-		switch (rect->rop) {
-		case ROP_COPY:
-			fill_one_line(info->var.bits_per_pixel,
-				      par->next_plane, dst, dst_idx, width,
-				      rect->color);
-			break;
-
-		case ROP_XOR:
-			xor_one_line(info->var.bits_per_pixel, par->next_plane,
-				     dst, dst_idx, width, rect->color);
-			break;
-		}
-		dst_idx += par->next_line * 8;
-	}
-}
-
-static inline void copy_one_line(int bpp, unsigned long next_plane,
-				 unsigned long *dst, int dst_idx,
-				 unsigned long *src, int src_idx, u32 n)
-{
-	while (1) {
-		dst += dst_idx >> SHIFT_PER_LONG;
-		dst_idx &= (BITS_PER_LONG - 1);
-		src += src_idx >> SHIFT_PER_LONG;
-		src_idx &= (BITS_PER_LONG - 1);
-		bitcpy(dst, dst_idx, src, src_idx, n);
-		if (!--bpp)
-			break;
-		dst_idx += next_plane * 8;
-		src_idx += next_plane * 8;
-	}
-}
-
-static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
-				     unsigned long *dst, int dst_idx,
-				     unsigned long *src, int src_idx, u32 n)
-{
-	while (1) {
-		dst += dst_idx >> SHIFT_PER_LONG;
-		dst_idx &= (BITS_PER_LONG - 1);
-		src += src_idx >> SHIFT_PER_LONG;
-		src_idx &= (BITS_PER_LONG - 1);
-		bitcpy_rev(dst, dst_idx, src, src_idx, n);
-		if (!--bpp)
-			break;
-		dst_idx += next_plane * 8;
-		src_idx += next_plane * 8;
-	}
-}
-
-
-static void amifb_copyarea(struct fb_info *info,
-			   const struct fb_copyarea *area)
-{
-	struct amifb_par *par = info->par;
-	int x2, y2;
-	u32 dx, dy, sx, sy, width, height;
-	unsigned long *dst, *src;
-	int dst_idx, src_idx;
-	int rev_copy = 0;
-
-	/* clip the destination */
-	x2 = area->dx + area->width;
-	y2 = area->dy + area->height;
-	dx = area->dx > 0 ? area->dx : 0;
-	dy = area->dy > 0 ? area->dy : 0;
-	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
-	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	width = x2 - dx;
-	height = y2 - dy;
-
-	if (area->sx + dx < area->dx || area->sy + dy < area->dy)
-		return;
-
-	/* update sx,sy */
-	sx = area->sx + (dx - area->dx);
-	sy = area->sy + (dy - area->dy);
-
-	/* the source must be completely inside the virtual screen */
-	if (sx + width > info->var.xres_virtual ||
-			sy + height > info->var.yres_virtual)
-		return;
-
-	if (dy > sy || (dy == sy && dx > sx)) {
-		dy += height;
-		sy += height;
-		rev_copy = 1;
-	}
-	dst = (unsigned long *)
-		((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
-	src = dst;
-	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
-	src_idx = dst_idx;
-	dst_idx += dy * par->next_line * 8 + dx;
-	src_idx += sy * par->next_line * 8 + sx;
-	if (rev_copy) {
-		while (height--) {
-			dst_idx -= par->next_line * 8;
-			src_idx -= par->next_line * 8;
-			copy_one_line_rev(info->var.bits_per_pixel,
-					  par->next_plane, dst, dst_idx, src,
-					  src_idx, width);
-		}
-	} else {
-		while (height--) {
-			copy_one_line(info->var.bits_per_pixel,
-				      par->next_plane, dst, dst_idx, src,
-				      src_idx, width);
-			dst_idx += par->next_line * 8;
-			src_idx += par->next_line * 8;
-		}
-	}
-}
-
-
-static inline void expand_one_line(int bpp, unsigned long next_plane,
-				   unsigned long *dst, int dst_idx, u32 n,
-				   const u8 *data, u32 bgcolor, u32 fgcolor)
-{
-	const unsigned long *src;
-	int src_idx;
-
-	while (1) {
-		dst += dst_idx >> SHIFT_PER_LONG;
-		dst_idx &= (BITS_PER_LONG - 1);
-		if ((bgcolor ^ fgcolor) & 1) {
-			src = (unsigned long *)
-				((unsigned long)data & ~(BYTES_PER_LONG - 1));
-			src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
-			if (fgcolor & 1)
-				bitcpy(dst, dst_idx, src, src_idx, n);
-			else
-				bitcpy_not(dst, dst_idx, src, src_idx, n);
-			/* set or clear */
-		} else
-			bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
-		if (!--bpp)
-			break;
-		bgcolor >>= 1;
-		fgcolor >>= 1;
-		dst_idx += next_plane * 8;
-	}
-}
-
-
-static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct amifb_par *par = info->par;
-	int x2, y2;
-	unsigned long *dst;
-	int dst_idx;
-	const char *src;
-	u32 dx, dy, width, height, pitch;
-
-	/*
-	 * We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly like we are
-	 * doing here.
-	 */
-	x2 = image->dx + image->width;
-	y2 = image->dy + image->height;
-	dx = image->dx;
-	dy = image->dy;
-	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
-	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	width  = x2 - dx;
-	height = y2 - dy;
-
-	if (image->depth == 1) {
-		dst = (unsigned long *)
-			((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
-		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
-		dst_idx += dy * par->next_line * 8 + dx;
-		src = image->data;
-		pitch = (image->width + 7) / 8;
-		while (height--) {
-			expand_one_line(info->var.bits_per_pixel,
-					par->next_plane, dst, dst_idx, width,
-					src, image->bg_color,
-					image->fg_color);
-			dst_idx += par->next_line * 8;
-			src += pitch;
-		}
-	} else {
-		c2p_planar(info->screen_base, image->data, dx, dy, width,
-			   height, par->next_line, par->next_plane,
-			   image->width, info->var.bits_per_pixel);
-	}
-}
-
-
-	/*
-	 * Amiga Frame Buffer Specific ioctls
-	 */
-
-static int amifb_ioctl(struct fb_info *info,
-		       unsigned int cmd, unsigned long arg)
-{
-	union {
-		struct fb_fix_cursorinfo fix;
-		struct fb_var_cursorinfo var;
-		struct fb_cursorstate state;
-	} crsr;
-	void __user *argp = (void __user *)arg;
-	int i;
-
-	switch (cmd) {
-	case FBIOGET_FCURSORINFO:
-		i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
-		if (i)
-			return i;
-		return copy_to_user(argp, &crsr.fix,
-				    sizeof(crsr.fix)) ? -EFAULT : 0;
-
-	case FBIOGET_VCURSORINFO:
-		i = ami_get_var_cursorinfo(&crsr.var,
-			((struct fb_var_cursorinfo __user *)arg)->data,
-			info->par);
-		if (i)
-			return i;
-		return copy_to_user(argp, &crsr.var,
-				    sizeof(crsr.var)) ? -EFAULT : 0;
-
-	case FBIOPUT_VCURSORINFO:
-		if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
-			return -EFAULT;
-		return ami_set_var_cursorinfo(&crsr.var,
-			((struct fb_var_cursorinfo __user *)arg)->data,
-			info->par);
-
-	case FBIOGET_CURSORSTATE:
-		i = ami_get_cursorstate(&crsr.state, info->par);
-		if (i)
-			return i;
-		return copy_to_user(argp, &crsr.state,
-				    sizeof(crsr.state)) ? -EFAULT : 0;
-
-	case FBIOPUT_CURSORSTATE:
-		if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
-			return -EFAULT;
-		return ami_set_cursorstate(&crsr.state, info->par);
-	}
-	return -EINVAL;
-}
-
-
-	/*
-	 * Flash the cursor (called by VBlank interrupt)
-	 */
-
-static int flash_cursor(void)
-{
-	static int cursorcount = 1;
-
-	if (cursormode == FB_CURSOR_FLASH) {
-		if (!--cursorcount) {
-			cursorstate = -cursorstate;
-			cursorcount = cursorrate;
-			if (!is_blanked)
-				return 1;
-		}
-	}
-	return 0;
-}
-
-	/*
-	 * VBlank Display Interrupt
-	 */
-
-static irqreturn_t amifb_interrupt(int irq, void *dev_id)
-{
-	struct amifb_par *par = dev_id;
-
-	if (do_vmode_pan || do_vmode_full)
-		ami_update_display(par);
-
-	if (do_vmode_full)
-		ami_init_display(par);
-
-	if (do_vmode_pan) {
-		flash_cursor();
-		ami_rebuild_copper(par);
-		do_cursor = do_vmode_pan = 0;
-	} else if (do_cursor) {
-		flash_cursor();
-		ami_set_sprite(par);
-		do_cursor = 0;
-	} else {
-		if (flash_cursor())
-			ami_set_sprite(par);
-	}
-
-	if (do_blank) {
-		ami_do_blank(par);
-		do_blank = 0;
-	}
-
-	if (do_vmode_full) {
-		ami_reinit_copper(par);
-		do_vmode_full = 0;
-	}
-	return IRQ_HANDLED;
-}
-
-
-static struct fb_ops amifb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= amifb_check_var,
-	.fb_set_par	= amifb_set_par,
-	.fb_setcolreg	= amifb_setcolreg,
-	.fb_blank	= amifb_blank,
-	.fb_pan_display	= amifb_pan_display,
-	.fb_fillrect	= amifb_fillrect,
-	.fb_copyarea	= amifb_copyarea,
-	.fb_imageblit	= amifb_imageblit,
-	.fb_ioctl	= amifb_ioctl,
-};
-
-
-	/*
-	 * Allocate, Clear and Align a Block of Chip Memory
-	 */
-
-static void *aligned_chipptr;
-
-static inline u_long __init chipalloc(u_long size)
-{
-	aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
-	if (!aligned_chipptr) {
-		pr_err("amifb: No Chip RAM for frame buffer");
-		return 0;
-	}
-	memset(aligned_chipptr, 0, size);
-	return (u_long)aligned_chipptr;
-}
-
-static inline void chipfree(void)
-{
-	if (aligned_chipptr)
-		amiga_chip_free(aligned_chipptr);
-}
-
-
-	/*
-	 * Initialisation
-	 */
-
-static int __init amifb_probe(struct platform_device *pdev)
-{
-	struct fb_info *info;
-	int tag, i, err = 0;
-	u_long chipptr;
-	u_int defmode;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("amifb", &option)) {
-		amifb_video_off();
-		return -ENODEV;
-	}
-	amifb_setup(option);
-#endif
-	custom.dmacon = DMAF_ALL | DMAF_MASTER;
-
-	info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
-	if (!info) {
-		dev_err(&pdev->dev, "framebuffer_alloc failed\n");
-		return -ENOMEM;
-	}
-
-	strcpy(info->fix.id, "Amiga ");
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	info->fix.accel = FB_ACCEL_AMIGABLITT;
-
-	switch (amiga_chipset) {
-#ifdef CONFIG_FB_AMIGA_OCS
-	case CS_OCS:
-		strcat(info->fix.id, "OCS");
-default_chipset:
-		chipset = TAG_OCS;
-		maxdepth[TAG_SHRES] = 0;	/* OCS means no SHRES */
-		maxdepth[TAG_HIRES] = 4;
-		maxdepth[TAG_LORES] = 6;
-		maxfmode = TAG_FMODE_1;
-		defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
-		info->fix.smem_len = VIDEOMEMSIZE_OCS;
-		break;
-#endif /* CONFIG_FB_AMIGA_OCS */
-
-#ifdef CONFIG_FB_AMIGA_ECS
-	case CS_ECS:
-		strcat(info->fix.id, "ECS");
-		chipset = TAG_ECS;
-		maxdepth[TAG_SHRES] = 2;
-		maxdepth[TAG_HIRES] = 4;
-		maxdepth[TAG_LORES] = 6;
-		maxfmode = TAG_FMODE_1;
-		if (AMIGAHW_PRESENT(AMBER_FF))
-			defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
-						     : DEFMODE_AMBER_NTSC;
-		else
-			defmode = amiga_vblank == 50 ? DEFMODE_PAL
-						     : DEFMODE_NTSC;
-		if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
-		    VIDEOMEMSIZE_ECS_2M)
-			info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
-		else
-			info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
-		break;
-#endif /* CONFIG_FB_AMIGA_ECS */
-
-#ifdef CONFIG_FB_AMIGA_AGA
-	case CS_AGA:
-		strcat(info->fix.id, "AGA");
-		chipset = TAG_AGA;
-		maxdepth[TAG_SHRES] = 8;
-		maxdepth[TAG_HIRES] = 8;
-		maxdepth[TAG_LORES] = 8;
-		maxfmode = TAG_FMODE_4;
-		defmode = DEFMODE_AGA;
-		if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
-		    VIDEOMEMSIZE_AGA_2M)
-			info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
-		else
-			info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
-		break;
-#endif /* CONFIG_FB_AMIGA_AGA */
-
-	default:
-#ifdef CONFIG_FB_AMIGA_OCS
-		printk("Unknown graphics chipset, defaulting to OCS\n");
-		strcat(info->fix.id, "Unknown");
-		goto default_chipset;
-#else /* CONFIG_FB_AMIGA_OCS */
-		err = -ENODEV;
-		goto release;
-#endif /* CONFIG_FB_AMIGA_OCS */
-		break;
-	}
-
-	/*
-	 * Calculate the Pixel Clock Values for this Machine
-	 */
-
-	{
-	u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
-
-	pixclock[TAG_SHRES] = (tmp + 4) / 8;	/* SHRES:  35 ns / 28 MHz */
-	pixclock[TAG_HIRES] = (tmp + 2) / 4;	/* HIRES:  70 ns / 14 MHz */
-	pixclock[TAG_LORES] = (tmp + 1) / 2;	/* LORES: 140 ns /  7 MHz */
-	}
-
-	/*
-	 * Replace the Tag Values with the Real Pixel Clock Values
-	 */
-
-	for (i = 0; i < NUM_TOTAL_MODES; i++) {
-		struct fb_videomode *mode = &ami_modedb[i];
-		tag = mode->pixclock;
-		if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
-			mode->pixclock = pixclock[tag];
-		}
-	}
-
-	if (amifb_hfmin) {
-		info->monspecs.hfmin = amifb_hfmin;
-		info->monspecs.hfmax = amifb_hfmax;
-		info->monspecs.vfmin = amifb_vfmin;
-		info->monspecs.vfmax = amifb_vfmax;
-	} else {
-		/*
-		 *  These are for a typical Amiga monitor (e.g. A1960)
-		 */
-		info->monspecs.hfmin = 15000;
-		info->monspecs.hfmax = 38000;
-		info->monspecs.vfmin = 49;
-		info->monspecs.vfmax = 90;
-	}
-
-	info->fbops = &amifb_ops;
-	info->flags = FBINFO_DEFAULT;
-	info->device = &pdev->dev;
-
-	if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
-			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
-		err = -EINVAL;
-		goto release;
-	}
-
-	fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
-				 &info->modelist);
-
-	round_down_bpp = 0;
-	chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
-			    DUMMYSPRITEMEMSIZE + COPINITSIZE +
-			    4 * COPLISTSIZE);
-	if (!chipptr) {
-		err = -ENOMEM;
-		goto release;
-	}
-
-	assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
-	assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
-	assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
-	assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
-	assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
-	assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
-	assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
-	assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
-
-	/*
-	 * access the videomem with writethrough cache
-	 */
-	info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
-	videomemory = (u_long)ioremap_writethrough(info->fix.smem_start,
-						   info->fix.smem_len);
-	if (!videomemory) {
-		dev_warn(&pdev->dev,
-			 "Unable to map videomem cached writethrough\n");
-		info->screen_base = ZTWO_VADDR(info->fix.smem_start);
-	} else
-		info->screen_base = (char *)videomemory;
-
-	memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
-
-	/*
-	 * Make sure the Copper has something to do
-	 */
-	ami_init_copper();
-
-	/*
-	 * Enable Display DMA
-	 */
-	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
-			DMAF_BLITTER | DMAF_SPRITE;
-
-	err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
-			  "fb vertb handler", info->par);
-	if (err)
-		goto disable_dma;
-
-	err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
-	if (err)
-		goto free_irq;
-
-	dev_set_drvdata(&pdev->dev, info);
-
-	err = register_framebuffer(info);
-	if (err)
-		goto unset_drvdata;
-
-	fb_info(info, "%s frame buffer device, using %dK of video memory\n",
-		info->fix.id, info->fix.smem_len>>10);
-
-	return 0;
-
-unset_drvdata:
-	fb_dealloc_cmap(&info->cmap);
-free_irq:
-	free_irq(IRQ_AMIGA_COPPER, info->par);
-disable_dma:
-	custom.dmacon = DMAF_ALL | DMAF_MASTER;
-	if (videomemory)
-		iounmap((void *)videomemory);
-	chipfree();
-release:
-	framebuffer_release(info);
-	return err;
-}
-
-
-static int __exit amifb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = dev_get_drvdata(&pdev->dev);
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-	free_irq(IRQ_AMIGA_COPPER, info->par);
-	custom.dmacon = DMAF_ALL | DMAF_MASTER;
-	if (videomemory)
-		iounmap((void *)videomemory);
-	chipfree();
-	framebuffer_release(info);
-	amifb_video_off();
-	return 0;
-}
-
-static struct platform_driver amifb_driver = {
-	.remove = __exit_p(amifb_remove),
-	.driver   = {
-		.name	= "amiga-video",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver_probe(amifb_driver, amifb_probe);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
deleted file mode 100644
index 1b0b233b8b39..000000000000
--- a/drivers/video/arcfb.c
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
- *
- * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This driver was written to be used with the Arc LCD board. Arc uses a
- * set of KS108 chips that control individual 64x64 LCD matrices. The board
- * can be paneled in a variety of setups such as 2x1=128x64, 4x4=256x256 and
- * so on. The interface between the board and the host is TTL based GPIO. The
- * GPIO requirements are 8 writable data lines and 4+n lines for control. On a
- * GPIO-less system, the board can be tested by connecting the respective sigs
- * up to a parallel port connector. The driver requires the IO addresses for
- * data and control GPIO at load time. It is unable to probe for the
- * existence of the LCD so it must be told at load time whether it should
- * be enabled or not.
- *
- * Todo:
- * - testing with 4x4
- * - testing with interrupt hw
- *
- * General notes:
- * - User must set tuhold. It's in microseconds. According to the 108 spec,
- *   the hold time is supposed to be at least 1 microsecond.
- * - User must set num_cols=x num_rows=y, eg: x=2 means 128
- * - User must set arcfb_enable=1 to enable it
- * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/arcfb.h>
-#include <linux/platform_device.h>
-
-#include <linux/uaccess.h>
-
-#define floor8(a) (a&(~0x07))
-#define floorXres(a,xres) (a&(~(xres - 1)))
-#define iceil8(a) (((int)((a+7)/8))*8)
-#define ceil64(a) (a|0x3F)
-#define ceilXres(a,xres) (a|(xres - 1))
-
-/* ks108 chipset specific defines and code */
-
-#define KS_SET_DPY_START_LINE 	0xC0
-#define KS_SET_PAGE_NUM 	0xB8
-#define KS_SET_X 		0x40
-#define KS_CEHI 		0x01
-#define KS_CELO 		0x00
-#define KS_SEL_CMD 		0x08
-#define KS_SEL_DATA 		0x00
-#define KS_DPY_ON 		0x3F
-#define KS_DPY_OFF 		0x3E
-#define KS_INTACK 		0x40
-#define KS_CLRINT		0x02
-
-struct arcfb_par {
-	unsigned long dio_addr;
-	unsigned long cio_addr;
-	unsigned long c2io_addr;
-	atomic_t ref_count;
-	unsigned char cslut[9];
-	struct fb_info *info;
-	unsigned int irq;
-	spinlock_t lock;
-};
-
-static struct fb_fix_screeninfo arcfb_fix = {
-	.id =		"arcfb",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_MONO01,
-	.xpanstep =	0,
-	.ypanstep =	1,
-	.ywrapstep =	0,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo arcfb_var = {
-	.xres		= 128,
-	.yres		= 64,
-	.xres_virtual	= 128,
-	.yres_virtual	= 64,
-	.bits_per_pixel	= 1,
-	.nonstd		= 1,
-};
-
-static unsigned long num_cols;
-static unsigned long num_rows;
-static unsigned long dio_addr;
-static unsigned long cio_addr;
-static unsigned long c2io_addr;
-static unsigned long splashval;
-static unsigned long tuhold;
-static unsigned int nosplash;
-static unsigned int arcfb_enable;
-static unsigned int irq;
-
-static DECLARE_WAIT_QUEUE_HEAD(arcfb_waitq);
-
-static void ks108_writeb_ctl(struct arcfb_par *par,
-				unsigned int chipindex, unsigned char value)
-{
-	unsigned char chipselval = par->cslut[chipindex];
-
-	outb(chipselval|KS_CEHI|KS_SEL_CMD, par->cio_addr);
-	outb(value, par->dio_addr);
-	udelay(tuhold);
-	outb(chipselval|KS_CELO|KS_SEL_CMD, par->cio_addr);
-}
-
-static void ks108_writeb_mainctl(struct arcfb_par *par, unsigned char value)
-{
-
-	outb(value, par->cio_addr);
-	udelay(tuhold);
-}
-
-static unsigned char ks108_readb_ctl2(struct arcfb_par *par)
-{
-	return inb(par->c2io_addr);
-}
-
-static void ks108_writeb_data(struct arcfb_par *par,
-				unsigned int chipindex, unsigned char value)
-{
-	unsigned char chipselval = par->cslut[chipindex];
-
-	outb(chipselval|KS_CEHI|KS_SEL_DATA, par->cio_addr);
-	outb(value, par->dio_addr);
-	udelay(tuhold);
-	outb(chipselval|KS_CELO|KS_SEL_DATA, par->cio_addr);
-}
-
-static void ks108_set_start_line(struct arcfb_par *par,
-				unsigned int chipindex, unsigned char y)
-{
-	ks108_writeb_ctl(par, chipindex, KS_SET_DPY_START_LINE|y);
-}
-
-static void ks108_set_yaddr(struct arcfb_par *par,
-				unsigned int chipindex, unsigned char y)
-{
-	ks108_writeb_ctl(par, chipindex, KS_SET_PAGE_NUM|y);
-}
-
-static void ks108_set_xaddr(struct arcfb_par *par,
-				unsigned int chipindex, unsigned char x)
-{
-	ks108_writeb_ctl(par, chipindex, KS_SET_X|x);
-}
-
-static void ks108_clear_lcd(struct arcfb_par *par, unsigned int chipindex)
-{
-	int i,j;
-
-	for (i = 0; i <= 8; i++) {
-		ks108_set_yaddr(par, chipindex, i);
-		ks108_set_xaddr(par, chipindex, 0);
-		for (j = 0; j < 64; j++) {
-			ks108_writeb_data(par, chipindex,
-				(unsigned char) splashval);
-		}
-	}
-}
-
-/* main arcfb functions */
-
-static int arcfb_open(struct fb_info *info, int user)
-{
-	struct arcfb_par *par = info->par;
-
-	atomic_inc(&par->ref_count);
-	return 0;
-}
-
-static int arcfb_release(struct fb_info *info, int user)
-{
-	struct arcfb_par *par = info->par;
-	int count = atomic_read(&par->ref_count);
-
-	if (!count)
-		return -EINVAL;
-	atomic_dec(&par->ref_count);
-	return 0;
-}
-
-static int arcfb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	int i;
-	struct arcfb_par *par = info->par;
-
-	if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 64)
-		&& (info->var.yres <= 64)) {
-		for (i = 0; i < num_cols; i++) {
-			ks108_set_start_line(par, i, var->yoffset);
-		}
-		info->var.yoffset = var->yoffset;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static irqreturn_t arcfb_interrupt(int vec, void *dev_instance)
-{
-	struct fb_info *info = dev_instance;
-	unsigned char ctl2status;
-	struct arcfb_par *par = info->par;
-
-	ctl2status = ks108_readb_ctl2(par);
-
-	if (!(ctl2status & KS_INTACK)) /* not arc generated interrupt */
-		return IRQ_NONE;
-
-	ks108_writeb_mainctl(par, KS_CLRINT);
-
-	spin_lock(&par->lock);
-        if (waitqueue_active(&arcfb_waitq)) {
-                wake_up(&arcfb_waitq);
-        }
-	spin_unlock(&par->lock);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * here we handle a specific page on the lcd. the complexity comes from
- * the fact that the fb is laidout in 8xX vertical columns. we extract
- * each write of 8 vertical pixels. then we shift out as we move along
- * X. That's what rightshift does. bitmask selects the desired input bit.
- */
-static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
-		unsigned int left, unsigned int right, unsigned int distance)
-{
-	unsigned char *src;
-	unsigned int xindex, yindex, chipindex, linesize;
-	int i;
-	unsigned char val;
-	unsigned char bitmask, rightshift;
-
-	xindex = left >> 6;
-	yindex = upper >> 6;
-	chipindex = (xindex + (yindex*num_cols));
-
-	ks108_set_yaddr(par, chipindex, upper/8);
-
-	linesize = par->info->var.xres/8;
-	src = (unsigned char __force *) par->info->screen_base + (left/8) +
-		(upper * linesize);
-	ks108_set_xaddr(par, chipindex, left);
-
-	bitmask=1;
-	rightshift=0;
-	while (left <= right) {
-		val = 0;
-		for (i = 0; i < 8; i++) {
-			if ( i > rightshift) {
-				val |= (*(src + (i*linesize)) & bitmask)
-						<< (i - rightshift);
-			} else {
-				val |= (*(src + (i*linesize)) & bitmask)
-						 >> (rightshift - i);
-			}
-		}
-		ks108_writeb_data(par, chipindex, val);
-		left++;
-		if (bitmask == 0x80) {
-			bitmask = 1;
-			src++;
-			rightshift=0;
-		} else {
-			bitmask <<= 1;
-			rightshift++;
-		}
-	}
-}
-
-/*
- * here we handle the entire vertical page of the update. we write across
- * lcd chips. update_page uses the upper/left values to decide which
- * chip to select for the right. upper is needed for setting the page
- * desired for the write.
- */
-static void arcfb_lcd_update_vert(struct arcfb_par *par, unsigned int top,
-		unsigned int bottom, unsigned int left, unsigned int right)
-{
-	unsigned int distance, upper, lower;
-
-	distance = (bottom - top) + 1;
-	upper = top;
-	lower = top + 7;
-
-	while (distance > 0) {
-		distance -= 8;
-		arcfb_lcd_update_page(par, upper, left, right, 8);
-		upper = lower + 1;
-		lower = upper + 7;
-	}
-}
-
-/*
- * here we handle horizontal blocks for the update. update_vert will
- * handle spaning multiple pages. we break out each horizontal
- * block in to individual blocks no taller than 64 pixels.
- */
-static void arcfb_lcd_update_horiz(struct arcfb_par *par, unsigned int left,
-			unsigned int right, unsigned int top, unsigned int h)
-{
-	unsigned int distance, upper, lower;
-
-	distance = h;
-	upper = floor8(top);
-	lower = min(upper + distance - 1, ceil64(upper));
-
-	while (distance > 0) {
-		distance -= ((lower - upper) + 1 );
-		arcfb_lcd_update_vert(par, upper, lower, left, right);
-		upper = lower + 1;
-		lower = min(upper + distance - 1, ceil64(upper));
-	}
-}
-
-/*
- * here we start the process of splitting out the fb update into
- * individual blocks of pixels. we end up splitting into 64x64 blocks
- * and finally down to 64x8 pages.
- */
-static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
-			unsigned int dy, unsigned int w, unsigned int h)
-{
-	unsigned int left, right, distance, y;
-
-	/* align the request first */
-	y = floor8(dy);
-	h += dy - y;
-	h = iceil8(h);
-
-	distance = w;
-	left = dx;
-	right = min(left + w - 1, ceil64(left));
-
-	while (distance > 0) {
-		arcfb_lcd_update_horiz(par, left, right, y, h);
-		distance -= ((right - left) + 1);
-		left = right + 1;
-		right = min(left + distance - 1, ceil64(left));
-	}
-}
-
-static void arcfb_fillrect(struct fb_info *info,
-			   const struct fb_fillrect *rect)
-{
-	struct arcfb_par *par = info->par;
-
-	sys_fillrect(info, rect);
-
-	/* update the physical lcd */
-	arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
-}
-
-static void arcfb_copyarea(struct fb_info *info,
-			   const struct fb_copyarea *area)
-{
-	struct arcfb_par *par = info->par;
-
-	sys_copyarea(info, area);
-
-	/* update the physical lcd */
-	arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
-}
-
-static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct arcfb_par *par = info->par;
-
-	sys_imageblit(info, image);
-
-	/* update the physical lcd */
-	arcfb_lcd_update(par, image->dx, image->dy, image->width,
-				image->height);
-}
-
-static int arcfb_ioctl(struct fb_info *info,
-			  unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	struct arcfb_par *par = info->par;
-	unsigned long flags;
-
-	switch (cmd) {
-		case FBIO_WAITEVENT:
-		{
-			DEFINE_WAIT(wait);
-			/* illegal to wait on arc if no irq will occur */
-			if (!par->irq)
-				return -EINVAL;
-
-			/* wait until the Arc has generated an interrupt
-			 * which will wake us up */
-			spin_lock_irqsave(&par->lock, flags);
-			prepare_to_wait(&arcfb_waitq, &wait,
-					TASK_INTERRUPTIBLE);
-			spin_unlock_irqrestore(&par->lock, flags);
-			schedule();
-			finish_wait(&arcfb_waitq, &wait);
-		}
-		case FBIO_GETCONTROL2:
-		{
-			unsigned char ctl2;
-
-			ctl2 = ks108_readb_ctl2(info->par);
-			if (copy_to_user(argp, &ctl2, sizeof(ctl2)))
-				return -EFAULT;
-			return 0;
-		}
-		default:
-			return -EINVAL;
-	}
-}
-
-/*
- * this is the access path from userspace. they can seek and write to
- * the fb. it's inefficient for them to do anything less than 64*8
- * writes since we update the lcd in each write() anyway.
- */
-static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
-			   size_t count, loff_t *ppos)
-{
-	/* modded from epson 1355 */
-
-	unsigned long p;
-	int err=-EINVAL;
-	unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
-	struct arcfb_par *par;
-	unsigned int xres;
-
-	p = *ppos;
-	par = info->par;
-	xres = info->var.xres;
-	fbmemlength = (xres * info->var.yres)/8;
-
-	if (p > fbmemlength)
-		return -ENOSPC;
-
-	err = 0;
-	if ((count + p) > fbmemlength) {
-		count = fbmemlength - p;
-		err = -ENOSPC;
-	}
-
-	if (count) {
-		char *base_addr;
-
-		base_addr = (char __force *)info->screen_base;
-		count -= copy_from_user(base_addr + p, buf, count);
-		*ppos += count;
-		err = -EFAULT;
-	}
-
-
-	bitppos = p*8;
-	startpos = floorXres(bitppos, xres);
-	endpos = ceilXres((bitppos + (count*8)), xres);
-	bitcount = endpos - startpos;
-
-	x = startpos % xres;
-	y = startpos / xres;
-	w = xres;
-	h = bitcount / xres;
-	arcfb_lcd_update(par, x, y, w, h);
-
-	if (count)
-		return count;
-	return err;
-}
-
-static struct fb_ops arcfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= arcfb_open,
-	.fb_read        = fb_sys_read,
-	.fb_write	= arcfb_write,
-	.fb_release	= arcfb_release,
-	.fb_pan_display	= arcfb_pan_display,
-	.fb_fillrect	= arcfb_fillrect,
-	.fb_copyarea	= arcfb_copyarea,
-	.fb_imageblit	= arcfb_imageblit,
-	.fb_ioctl 	= arcfb_ioctl,
-};
-
-static int arcfb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	int retval = -ENOMEM;
-	int videomemorysize;
-	unsigned char *videomemory;
-	struct arcfb_par *par;
-	int i;
-
-	videomemorysize = (((64*64)*num_cols)*num_rows)/8;
-
-	/* We need a flat backing store for the Arc's
-	   less-flat actual paged framebuffer */
-	videomemory = vzalloc(videomemorysize);
-	if (!videomemory)
-		return retval;
-
-	info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
-	if (!info)
-		goto err;
-
-	info->screen_base = (char __iomem *)videomemory;
-	info->fbops = &arcfb_ops;
-
-	info->var = arcfb_var;
-	info->fix = arcfb_fix;
-	par = info->par;
-	par->info = info;
-
-	if (!dio_addr || !cio_addr || !c2io_addr) {
-		printk(KERN_WARNING "no IO addresses supplied\n");
-		goto err1;
-	}
-	par->dio_addr = dio_addr;
-	par->cio_addr = cio_addr;
-	par->c2io_addr = c2io_addr;
-	par->cslut[0] = 0x00;
-	par->cslut[1] = 0x06;
-	info->flags = FBINFO_FLAG_DEFAULT;
-	spin_lock_init(&par->lock);
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err1;
-	platform_set_drvdata(dev, info);
-	if (irq) {
-		par->irq = irq;
-		if (request_irq(par->irq, &arcfb_interrupt, IRQF_SHARED,
-				"arcfb", info)) {
-			printk(KERN_INFO
-				"arcfb: Failed req IRQ %d\n", par->irq);
-			retval = -EBUSY;
-			goto err1;
-		}
-	}
-	fb_info(info, "Arc frame buffer device, using %dK of video memory\n",
-		videomemorysize >> 10);
-
-	/* this inits the lcd but doesn't clear dirty pixels */
-	for (i = 0; i < num_cols * num_rows; i++) {
-		ks108_writeb_ctl(par, i, KS_DPY_OFF);
-		ks108_set_start_line(par, i, 0);
-		ks108_set_yaddr(par, i, 0);
-		ks108_set_xaddr(par, i, 0);
-		ks108_writeb_ctl(par, i, KS_DPY_ON);
-	}
-
-	/* if we were told to splash the screen, we just clear it */
-	if (!nosplash) {
-		for (i = 0; i < num_cols * num_rows; i++) {
-			fb_info(info, "splashing lcd %d\n", i);
-			ks108_set_start_line(par, i, 0);
-			ks108_clear_lcd(par, i);
-		}
-	}
-
-	return 0;
-err1:
-	framebuffer_release(info);
-err:
-	vfree(videomemory);
-	return retval;
-}
-
-static int arcfb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		unregister_framebuffer(info);
-		vfree((void __force *)info->screen_base);
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-static struct platform_driver arcfb_driver = {
-	.probe	= arcfb_probe,
-	.remove = arcfb_remove,
-	.driver	= {
-		.name	= "arcfb",
-	},
-};
-
-static struct platform_device *arcfb_device;
-
-static int __init arcfb_init(void)
-{
-	int ret;
-
-	if (!arcfb_enable)
-		return -ENXIO;
-
-	ret = platform_driver_register(&arcfb_driver);
-	if (!ret) {
-		arcfb_device = platform_device_alloc("arcfb", 0);
-		if (arcfb_device) {
-			ret = platform_device_add(arcfb_device);
-		} else {
-			ret = -ENOMEM;
-		}
-		if (ret) {
-			platform_device_put(arcfb_device);
-			platform_driver_unregister(&arcfb_driver);
-		}
-	}
-	return ret;
-
-}
-
-static void __exit arcfb_exit(void)
-{
-	platform_device_unregister(arcfb_device);
-	platform_driver_unregister(&arcfb_driver);
-}
-
-module_param(num_cols, ulong, 0);
-MODULE_PARM_DESC(num_cols, "Num horiz panels, eg: 2 = 128 bit wide");
-module_param(num_rows, ulong, 0);
-MODULE_PARM_DESC(num_rows, "Num vert panels, eg: 1 = 64 bit high");
-module_param(nosplash, uint, 0);
-MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
-module_param(arcfb_enable, uint, 0);
-MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
-module_param(dio_addr, ulong, 0);
-MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
-module_param(cio_addr, ulong, 0);
-MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
-module_param(c2io_addr, ulong, 0);
-MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
-module_param(splashval, ulong, 0);
-MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
-module_param(tuhold, ulong, 0);
-MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
-module_param(irq, uint, 0);
-MODULE_PARM_DESC(irq, "IRQ for the Arc board");
-
-module_init(arcfb_init);
-module_exit(arcfb_exit);
-
-MODULE_DESCRIPTION("fbdev driver for Arc monochrome LCD board");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
deleted file mode 100644
index adc4ea2cc5a0..000000000000
--- a/drivers/video/arkfb.c
+++ /dev/null
@@ -1,1231 +0,0 @@
-/*
- *  linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV
- *  with ICS 5342 dac (it is easy to add support for different dacs).
- *
- *  Copyright (c) 2007 Ondrej Zajicek <santiago@crfreenet.org>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- *
- *  Code is based on s3fb
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/svga.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
-#include <video/vga.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-struct arkfb_info {
-	int mclk_freq;
-	int mtrr_reg;
-
-	struct dac_info *dac;
-	struct vgastate state;
-	struct mutex open_lock;
-	unsigned int ref_count;
-	u32 pseudo_palette[16];
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-
-static const struct svga_fb_format arkfb_formats[] = {
-	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 8},
-	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
-	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
-		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
-	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 8},
-	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
-	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
-	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 8, 8},
-	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 2},
-	SVGA_FORMAT_END
-};
-
-
-/* CRT timing register sets */
-
-static const struct vga_regset ark_h_total_regs[]        = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END};
-static const struct vga_regset ark_h_display_regs[]      = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END};
-static const struct vga_regset ark_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END};
-static const struct vga_regset ark_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7	}, VGA_REGSET_END};
-static const struct vga_regset ark_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END};
-static const struct vga_regset ark_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
-
-static const struct vga_regset ark_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END};
-static const struct vga_regset ark_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END};
-static const struct vga_regset ark_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END};
-// const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 6}, VGA_REGSET_END};
-static const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
-static const struct vga_regset ark_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END};
-static const struct vga_regset ark_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
-
-static const struct vga_regset ark_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
-static const struct vga_regset ark_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
-static const struct vga_regset ark_offset_regs[]         = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
-
-static const struct svga_timing_regs ark_timing_regs     = {
-	ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs,
-	ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs,
-	ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs,
-	ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs,
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* Module parameters */
-
-static char *mode_option = "640x480-8@60";
-
-#ifdef CONFIG_MTRR
-static int mtrr = 1;
-#endif
-
-MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
-
-module_param(mode_option, charp, 0444);
-MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
-module_param_named(mode, mode_option, charp, 0444);
-MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
-
-#ifdef CONFIG_MTRR
-module_param(mtrr, int, 0444);
-MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
-#endif
-
-static int threshold = 4;
-
-module_param(threshold, int, 0644);
-MODULE_PARM_DESC(threshold, "FIFO threshold");
-
-
-/* ------------------------------------------------------------------------- */
-
-
-static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
-{
-	const u8 *font = map->data;
-	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
-	int i, c;
-
-	if ((map->width != 8) || (map->height != 16) ||
-	    (map->depth != 1) || (map->length != 256)) {
-		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
-		       map->width, map->height, map->depth, map->length);
-		return;
-	}
-
-	fb += 2;
-	for (c = 0; c < map->length; c++) {
-		for (i = 0; i < map->height; i++) {
-			fb_writeb(font[i], &fb[i * 4]);
-			fb_writeb(font[i], &fb[i * 4 + (128 * 8)]);
-		}
-		fb += 128;
-
-		if ((c % 8) == 7)
-			fb += 128*8;
-
-		font += map->height;
-	}
-}
-
-static void arkfb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
-{
-	struct arkfb_info *par = info->par;
-
-	svga_tilecursor(par->state.vgabase, info, cursor);
-}
-
-static struct fb_tile_ops arkfb_tile_ops = {
-	.fb_settile	= arkfb_settile,
-	.fb_tilecopy	= svga_tilecopy,
-	.fb_tilefill    = svga_tilefill,
-	.fb_tileblit    = svga_tileblit,
-	.fb_tilecursor  = arkfb_tilecursor,
-	.fb_get_tilemax = svga_get_tilemax,
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* image data is MSB-first, fb structure is MSB-first too */
-static inline u32 expand_color(u32 c)
-{
-	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
-}
-
-/* arkfb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
-static void arkfb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	u32 fg = expand_color(image->fg_color);
-	u32 bg = expand_color(image->bg_color);
-	const u8 *src1, *src;
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	u32 val;
-	int x, y;
-
-	src1 = image->data;
-	dst1 = info->screen_base + (image->dy * info->fix.line_length)
-		 + ((image->dx / 8) * 4);
-
-	for (y = 0; y < image->height; y++) {
-		src = src1;
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < image->width; x += 8) {
-			val = *(src++) * 0x01010101;
-			val = (val & fg) | (~val & bg);
-			fb_writel(val, dst++);
-		}
-		src1 += image->width / 8;
-		dst1 += info->fix.line_length;
-	}
-
-}
-
-/* arkfb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
-static void arkfb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	u32 fg = expand_color(rect->color);
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	int x, y;
-
-	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
-		 + ((rect->dx / 8) * 4);
-
-	for (y = 0; y < rect->height; y++) {
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < rect->width; x += 8) {
-			fb_writel(fg, dst++);
-		}
-		dst1 += info->fix.line_length;
-	}
-
-}
-
-
-/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
-static inline u32 expand_pixel(u32 c)
-{
-	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
-		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
-}
-
-/* arkfb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
-static void arkfb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	u32 fg = image->fg_color * 0x11111111;
-	u32 bg = image->bg_color * 0x11111111;
-	const u8 *src1, *src;
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	u32 val;
-	int x, y;
-
-	src1 = image->data;
-	dst1 = info->screen_base + (image->dy * info->fix.line_length)
-		 + ((image->dx / 8) * 4);
-
-	for (y = 0; y < image->height; y++) {
-		src = src1;
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < image->width; x += 8) {
-			val = expand_pixel(*(src++));
-			val = (val & fg) | (~val & bg);
-			fb_writel(val, dst++);
-		}
-		src1 += image->width / 8;
-		dst1 += info->fix.line_length;
-	}
-
-}
-
-static void arkfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
-	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
-		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
-			arkfb_iplan_imageblit(info, image);
-		else
-			arkfb_cfb4_imageblit(info, image);
-	} else
-		cfb_imageblit(info, image);
-}
-
-static void arkfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	if ((info->var.bits_per_pixel == 4)
-	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
-	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
-		arkfb_iplan_fillrect(info, rect);
-	 else
-		cfb_fillrect(info, rect);
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-enum
-{
-	DAC_PSEUDO8_8,
-	DAC_RGB1555_8,
-	DAC_RGB0565_8,
-	DAC_RGB0888_8,
-	DAC_RGB8888_8,
-	DAC_PSEUDO8_16,
-	DAC_RGB1555_16,
-	DAC_RGB0565_16,
-	DAC_RGB0888_16,
-	DAC_RGB8888_16,
-	DAC_MAX
-};
-
-struct dac_ops {
-	int (*dac_get_mode)(struct dac_info *info);
-	int (*dac_set_mode)(struct dac_info *info, int mode);
-	int (*dac_get_freq)(struct dac_info *info, int channel);
-	int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq);
-	void (*dac_release)(struct dac_info *info);
-};
-
-typedef void (*dac_read_regs_t)(void *data, u8 *code, int count);
-typedef void (*dac_write_regs_t)(void *data, u8 *code, int count);
-
-struct dac_info
-{
-	struct dac_ops *dacops;
-	dac_read_regs_t dac_read_regs;
-	dac_write_regs_t dac_write_regs;
-	void *data;
-};
-
-
-static inline u8 dac_read_reg(struct dac_info *info, u8 reg)
-{
-	u8 code[2] = {reg, 0};
-	info->dac_read_regs(info->data, code, 1);
-	return code[1];
-}
-
-static inline void dac_read_regs(struct dac_info *info, u8 *code, int count)
-{
-	info->dac_read_regs(info->data, code, count);
-}
-
-static inline void dac_write_reg(struct dac_info *info, u8 reg, u8 val)
-{
-	u8 code[2] = {reg, val};
-	info->dac_write_regs(info->data, code, 1);
-}
-
-static inline void dac_write_regs(struct dac_info *info, u8 *code, int count)
-{
-	info->dac_write_regs(info->data, code, count);
-}
-
-static inline int dac_set_mode(struct dac_info *info, int mode)
-{
-	return info->dacops->dac_set_mode(info, mode);
-}
-
-static inline int dac_set_freq(struct dac_info *info, int channel, u32 freq)
-{
-	return info->dacops->dac_set_freq(info, channel, freq);
-}
-
-static inline void dac_release(struct dac_info *info)
-{
-	info->dacops->dac_release(info);
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* ICS5342 DAC */
-
-struct ics5342_info
-{
-	struct dac_info dac;
-	u8 mode;
-};
-
-#define DAC_PAR(info) ((struct ics5342_info *) info)
-
-/* LSB is set to distinguish unused slots */
-static const u8 ics5342_mode_table[DAC_MAX] = {
-	[DAC_PSEUDO8_8]  = 0x01, [DAC_RGB1555_8]  = 0x21, [DAC_RGB0565_8]  = 0x61,
-	[DAC_RGB0888_8]  = 0x41, [DAC_PSEUDO8_16] = 0x11, [DAC_RGB1555_16] = 0x31,
-	[DAC_RGB0565_16] = 0x51, [DAC_RGB0888_16] = 0x91, [DAC_RGB8888_16] = 0x71
-};
-
-static int ics5342_set_mode(struct dac_info *info, int mode)
-{
-	u8 code;
-
-	if (mode >= DAC_MAX)
-		return -EINVAL;
-
-	code = ics5342_mode_table[mode];
-
-	if (! code)
-		return -EINVAL;
-
-	dac_write_reg(info, 6, code & 0xF0);
-	DAC_PAR(info)->mode = mode;
-
-	return 0;
-}
-
-static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3,
-	60000, 250000, 14318};
-
-/* pd4 - allow only posdivider 4 (r=2) */
-static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2,
-	60000, 335000, 14318};
-
-/* 270 MHz should be upper bound for VCO clock according to specs,
-   but that is too restrictive in pd4 case */
-
-static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq)
-{
-	u16 m, n, r;
-
-	/* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */
-	int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16)
-				  ? &ics5342_pll_pd4 : &ics5342_pll,
-				  freq, &m, &n, &r, 0);
-
-	if (rv < 0) {
-		return -EINVAL;
-	} else {
-		u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)};
-		dac_write_regs(info, code, 3);
-		return 0;
-	}
-}
-
-static void ics5342_release(struct dac_info *info)
-{
-	ics5342_set_mode(info, DAC_PSEUDO8_8);
-	kfree(info);
-}
-
-static struct dac_ops ics5342_ops = {
-	.dac_set_mode	= ics5342_set_mode,
-	.dac_set_freq	= ics5342_set_freq,
-	.dac_release	= ics5342_release
-};
-
-
-static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data)
-{
-	struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL);
-
-	if (! info)
-		return NULL;
-
-	info->dacops = &ics5342_ops;
-	info->dac_read_regs = drr;
-	info->dac_write_regs = dwr;
-	info->data = data;
-	DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */
-	return info;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};
-
-static void ark_dac_read_regs(void *data, u8 *code, int count)
-{
-	struct fb_info *info = data;
-	struct arkfb_info *par;
-	u8 regval;
-
-	par = info->par;
-	regval = vga_rseq(par->state.vgabase, 0x1C);
-	while (count != 0)
-	{
-		vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
-		code[1] = vga_r(par->state.vgabase, dac_regs[code[0] & 3]);
-		count--;
-		code += 2;
-	}
-
-	vga_wseq(par->state.vgabase, 0x1C, regval);
-}
-
-static void ark_dac_write_regs(void *data, u8 *code, int count)
-{
-	struct fb_info *info = data;
-	struct arkfb_info *par;
-	u8 regval;
-
-	par = info->par;
-	regval = vga_rseq(par->state.vgabase, 0x1C);
-	while (count != 0)
-	{
-		vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
-		vga_w(par->state.vgabase, dac_regs[code[0] & 3], code[1]);
-		count--;
-		code += 2;
-	}
-
-	vga_wseq(par->state.vgabase, 0x1C, regval);
-}
-
-
-static void ark_set_pixclock(struct fb_info *info, u32 pixclock)
-{
-	struct arkfb_info *par = info->par;
-	u8 regval;
-
-	int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
-	if (rv < 0) {
-		fb_err(info, "cannot set requested pixclock, keeping old value\n");
-		return;
-	}
-
-	/* Set VGA misc register  */
-	regval = vga_r(par->state.vgabase, VGA_MIS_R);
-	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
-}
-
-
-/* Open framebuffer */
-
-static int arkfb_open(struct fb_info *info, int user)
-{
-	struct arkfb_info *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	if (par->ref_count == 0) {
-		void __iomem *vgabase = par->state.vgabase;
-
-		memset(&(par->state), 0, sizeof(struct vgastate));
-		par->state.vgabase = vgabase;
-		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
-		par->state.num_crtc = 0x60;
-		par->state.num_seq = 0x30;
-		save_vga(&(par->state));
-	}
-
-	par->ref_count++;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-/* Close framebuffer */
-
-static int arkfb_release(struct fb_info *info, int user)
-{
-	struct arkfb_info *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	if (par->ref_count == 0) {
-		mutex_unlock(&(par->open_lock));
-		return -EINVAL;
-	}
-
-	if (par->ref_count == 1) {
-		restore_vga(&(par->state));
-		dac_set_mode(par->dac, DAC_PSEUDO8_8);
-	}
-
-	par->ref_count--;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-/* Validate passed in var */
-
-static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int rv, mem, step;
-
-	/* Find appropriate format */
-	rv = svga_match_format (arkfb_formats, var, NULL);
-	if (rv < 0)
-	{
-		fb_err(info, "unsupported mode requested\n");
-		return rv;
-	}
-
-	/* Do not allow to have real resoulution larger than virtual */
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-
-	/* Round up xres_virtual to have proper alignment of lines */
-	step = arkfb_formats[rv].xresstep - 1;
-	var->xres_virtual = (var->xres_virtual+step) & ~step;
-
-
-	/* Check whether have enough memory */
-	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
-	if (mem > info->screen_size)
-	{
-		fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n",
-		       mem >> 10, (unsigned int) (info->screen_size >> 10));
-		return -EINVAL;
-	}
-
-	rv = svga_check_timings (&ark_timing_regs, var, info->node);
-	if (rv < 0)
-	{
-		fb_err(info, "invalid timings requested\n");
-		return rv;
-	}
-
-	/* Interlaced mode is broken */
-	if (var->vmode & FB_VMODE_INTERLACED)
-		return -EINVAL;
-
-	return 0;
-}
-
-/* Set video mode from par */
-
-static int arkfb_set_par(struct fb_info *info)
-{
-	struct arkfb_info *par = info->par;
-	u32 value, mode, hmul, hdiv, offset_value, screen_size;
-	u32 bpp = info->var.bits_per_pixel;
-	u8 regval;
-
-	if (bpp != 0) {
-		info->fix.ypanstep = 1;
-		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
-
-		info->flags &= ~FBINFO_MISC_TILEBLITTING;
-		info->tileops = NULL;
-
-		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
-		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
-		info->pixmap.blit_y = ~(u32)0;
-
-		offset_value = (info->var.xres_virtual * bpp) / 64;
-		screen_size = info->var.yres_virtual * info->fix.line_length;
-	} else {
-		info->fix.ypanstep = 16;
-		info->fix.line_length = 0;
-
-		info->flags |= FBINFO_MISC_TILEBLITTING;
-		info->tileops = &arkfb_tile_ops;
-
-		/* supports 8x16 tiles only */
-		info->pixmap.blit_x = 1 << (8 - 1);
-		info->pixmap.blit_y = 1 << (16 - 1);
-
-		offset_value = info->var.xres_virtual / 16;
-		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
-	}
-
-	info->var.xoffset = 0;
-	info->var.yoffset = 0;
-	info->var.activate = FB_ACTIVATE_NOW;
-
-	/* Unlock registers */
-	svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
-
-	/* Blank screen and turn off sync */
-	svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-	svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
-
-	/* Set default values */
-	svga_set_default_gfx_regs(par->state.vgabase);
-	svga_set_default_atc_regs(par->state.vgabase);
-	svga_set_default_seq_regs(par->state.vgabase);
-	svga_set_default_crt_regs(par->state.vgabase);
-	svga_wcrt_multi(par->state.vgabase, ark_line_compare_regs, 0xFFFFFFFF);
-	svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, 0);
-
-	/* ARK specific initialization */
-	svga_wseq_mask(par->state.vgabase, 0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */
-	svga_wseq_mask(par->state.vgabase, 0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */
-
-	vga_wseq(par->state.vgabase, 0x13, info->fix.smem_start >> 16);
-	vga_wseq(par->state.vgabase, 0x14, info->fix.smem_start >> 24);
-	vga_wseq(par->state.vgabase, 0x15, 0);
-	vga_wseq(par->state.vgabase, 0x16, 0);
-
-	/* Set the FIFO threshold register */
-	/* It is fascinating way to store 5-bit value in 8-bit register */
-	regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;
-	vga_wseq(par->state.vgabase, 0x18, regval);
-
-	/* Set the offset register */
-	fb_dbg(info, "offset register       : %d\n", offset_value);
-	svga_wcrt_multi(par->state.vgabase, ark_offset_regs, offset_value);
-
-	/* fix for hi-res textmode */
-	svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08);
-
-	if (info->var.vmode & FB_VMODE_DOUBLE)
-		svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
-	else
-		svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
-
-	if (info->var.vmode & FB_VMODE_INTERLACED)
-		svga_wcrt_mask(par->state.vgabase, 0x44, 0x04, 0x04);
-	else
-		svga_wcrt_mask(par->state.vgabase, 0x44, 0x00, 0x04);
-
-	hmul = 1;
-	hdiv = 1;
-	mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix));
-
-	/* Set mode-specific register values */
-	switch (mode) {
-	case 0:
-		fb_dbg(info, "text mode\n");
-		svga_set_textmode_vga_regs(par->state.vgabase);
-
-		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
-		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
-		dac_set_mode(par->dac, DAC_PSEUDO8_8);
-
-		break;
-	case 1:
-		fb_dbg(info, "4 bit pseudocolor\n");
-		vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
-
-		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
-		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
-		dac_set_mode(par->dac, DAC_PSEUDO8_8);
-		break;
-	case 2:
-		fb_dbg(info, "4 bit pseudocolor, planar\n");
-
-		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
-		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
-		dac_set_mode(par->dac, DAC_PSEUDO8_8);
-		break;
-	case 3:
-		fb_dbg(info, "8 bit pseudocolor\n");
-
-		vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode */
-
-		if (info->var.pixclock > 20000) {
-			fb_dbg(info, "not using multiplex\n");
-			svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
-			dac_set_mode(par->dac, DAC_PSEUDO8_8);
-		} else {
-			fb_dbg(info, "using multiplex\n");
-			svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
-			dac_set_mode(par->dac, DAC_PSEUDO8_16);
-			hdiv = 2;
-		}
-		break;
-	case 4:
-		fb_dbg(info, "5/5/5 truecolor\n");
-
-		vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
-		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
-		dac_set_mode(par->dac, DAC_RGB1555_16);
-		break;
-	case 5:
-		fb_dbg(info, "5/6/5 truecolor\n");
-
-		vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
-		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
-		dac_set_mode(par->dac, DAC_RGB0565_16);
-		break;
-	case 6:
-		fb_dbg(info, "8/8/8 truecolor\n");
-
-		vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode ??? */
-		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
-		dac_set_mode(par->dac, DAC_RGB0888_16);
-		hmul = 3;
-		hdiv = 2;
-		break;
-	case 7:
-		fb_dbg(info, "8/8/8/8 truecolor\n");
-
-		vga_wseq(par->state.vgabase, 0x11, 0x1E); /* 32bpp accel mode */
-		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
-		dac_set_mode(par->dac, DAC_RGB8888_16);
-		hmul = 2;
-		break;
-	default:
-		fb_err(info, "unsupported mode - bug\n");
-		return -EINVAL;
-	}
-
-	ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
-	svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv,
-			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
-			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
-			  hmul, info->node);
-
-	/* Set interlaced mode start/end register */
-	value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
-	value = ((value * hmul / hdiv) / 8) - 5;
-	vga_wcrt(par->state.vgabase, 0x42, (value + 1) / 2);
-
-	memset_io(info->screen_base, 0x00, screen_size);
-	/* Device and screen back on */
-	svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
-	svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
-
-	return 0;
-}
-
-/* Set a colour register */
-
-static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-				u_int transp, struct fb_info *fb)
-{
-	switch (fb->var.bits_per_pixel) {
-	case 0:
-	case 4:
-		if (regno >= 16)
-			return -EINVAL;
-
-		if ((fb->var.bits_per_pixel == 4) &&
-		    (fb->var.nonstd == 0)) {
-			outb(0xF0, VGA_PEL_MSK);
-			outb(regno*16, VGA_PEL_IW);
-		} else {
-			outb(0x0F, VGA_PEL_MSK);
-			outb(regno, VGA_PEL_IW);
-		}
-		outb(red >> 10, VGA_PEL_D);
-		outb(green >> 10, VGA_PEL_D);
-		outb(blue >> 10, VGA_PEL_D);
-		break;
-	case 8:
-		if (regno >= 256)
-			return -EINVAL;
-
-		outb(0xFF, VGA_PEL_MSK);
-		outb(regno, VGA_PEL_IW);
-		outb(red >> 10, VGA_PEL_D);
-		outb(green >> 10, VGA_PEL_D);
-		outb(blue >> 10, VGA_PEL_D);
-		break;
-	case 16:
-		if (regno >= 16)
-			return 0;
-
-		if (fb->var.green.length == 5)
-			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
-				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
-		else if (fb->var.green.length == 6)
-			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
-				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-		else
-			return -EINVAL;
-		break;
-	case 24:
-	case 32:
-		if (regno >= 16)
-			return 0;
-
-		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
-			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* Set the display blanking state */
-
-static int arkfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct arkfb_info *par = info->par;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		fb_dbg(info, "unblank\n");
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
-		svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
-		break;
-	case FB_BLANK_NORMAL:
-		fb_dbg(info, "blank\n");
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
-		break;
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_VSYNC_SUSPEND:
-		fb_dbg(info, "sync down\n");
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
-		break;
-	}
-	return 0;
-}
-
-
-/* Pan the display */
-
-static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct arkfb_info *par = info->par;
-	unsigned int offset;
-
-	/* Calculate the offset */
-	if (info->var.bits_per_pixel == 0) {
-		offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
-		       + (var->xoffset / 2);
-		offset = offset >> 2;
-	} else {
-		offset = (var->yoffset * info->fix.line_length) +
-			 (var->xoffset * info->var.bits_per_pixel / 8);
-		offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3);
-	}
-
-	/* Set the offset */
-	svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, offset);
-
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* Frame buffer operations */
-
-static struct fb_ops arkfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= arkfb_open,
-	.fb_release	= arkfb_release,
-	.fb_check_var	= arkfb_check_var,
-	.fb_set_par	= arkfb_set_par,
-	.fb_setcolreg	= arkfb_setcolreg,
-	.fb_blank	= arkfb_blank,
-	.fb_pan_display	= arkfb_pan_display,
-	.fb_fillrect	= arkfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= arkfb_imageblit,
-	.fb_get_caps    = svga_get_caps,
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* PCI probe */
-static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct pci_bus_region bus_reg;
-	struct resource vga_res;
-	struct fb_info *info;
-	struct arkfb_info *par;
-	int rc;
-	u8 regval;
-
-	/* Ignore secondary VGA device because there is no VGA arbitration */
-	if (! svga_primary_device(dev)) {
-		dev_info(&(dev->dev), "ignoring secondary device\n");
-		return -ENODEV;
-	}
-
-	/* Allocate and fill driver data structure */
-	info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev));
-	if (! info) {
-		dev_err(&(dev->dev), "cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	mutex_init(&par->open_lock);
-
-	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
-	info->fbops = &arkfb_ops;
-
-	/* Prepare PCI device */
-	rc = pci_enable_device(dev);
-	if (rc < 0) {
-		dev_err(info->device, "cannot enable PCI device\n");
-		goto err_enable_device;
-	}
-
-	rc = pci_request_regions(dev, "arkfb");
-	if (rc < 0) {
-		dev_err(info->device, "cannot reserve framebuffer region\n");
-		goto err_request_regions;
-	}
-
-	par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
-	if (! par->dac) {
-		rc = -ENOMEM;
-		dev_err(info->device, "RAMDAC initialization failed\n");
-		goto err_dac;
-	}
-
-	info->fix.smem_start = pci_resource_start(dev, 0);
-	info->fix.smem_len = pci_resource_len(dev, 0);
-
-	/* Map physical IO memory address into kernel space */
-	info->screen_base = pci_iomap(dev, 0, 0);
-	if (! info->screen_base) {
-		rc = -ENOMEM;
-		dev_err(info->device, "iomap for framebuffer failed\n");
-		goto err_iomap;
-	}
-
-	bus_reg.start = 0;
-	bus_reg.end = 64 * 1024;
-
-	vga_res.flags = IORESOURCE_IO;
-
-	pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
-
-	par->state.vgabase = (void __iomem *) vga_res.start;
-
-	/* FIXME get memsize */
-	regval = vga_rseq(par->state.vgabase, 0x10);
-	info->screen_size = (1 << (regval >> 6)) << 20;
-	info->fix.smem_len = info->screen_size;
-
-	strcpy(info->fix.id, "ARK 2000PV");
-	info->fix.mmio_start = 0;
-	info->fix.mmio_len = 0;
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	info->fix.ypanstep = 0;
-	info->fix.accel = FB_ACCEL_NONE;
-	info->pseudo_palette = (void*) (par->pseudo_palette);
-
-	/* Prepare startup mode */
-	rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
-	if (! ((rc == 1) || (rc == 2))) {
-		rc = -EINVAL;
-		dev_err(info->device, "mode %s not found\n", mode_option);
-		goto err_find_mode;
-	}
-
-	rc = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (rc < 0) {
-		dev_err(info->device, "cannot allocate colormap\n");
-		goto err_alloc_cmap;
-	}
-
-	rc = register_framebuffer(info);
-	if (rc < 0) {
-		dev_err(info->device, "cannot register framebuffer\n");
-		goto err_reg_fb;
-	}
-
-	fb_info(info, "%s on %s, %d MB RAM\n",
-		info->fix.id, pci_name(dev), info->fix.smem_len >> 20);
-
-	/* Record a reference to the driver data */
-	pci_set_drvdata(dev, info);
-
-#ifdef CONFIG_MTRR
-	if (mtrr) {
-		par->mtrr_reg = -1;
-		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-	}
-#endif
-
-	return 0;
-
-	/* Error handling */
-err_reg_fb:
-	fb_dealloc_cmap(&info->cmap);
-err_alloc_cmap:
-err_find_mode:
-	pci_iounmap(dev, info->screen_base);
-err_iomap:
-	dac_release(par->dac);
-err_dac:
-	pci_release_regions(dev);
-err_request_regions:
-/*	pci_disable_device(dev); */
-err_enable_device:
-	framebuffer_release(info);
-	return rc;
-}
-
-/* PCI remove */
-
-static void ark_pci_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-
-	if (info) {
-		struct arkfb_info *par = info->par;
-
-#ifdef CONFIG_MTRR
-		if (par->mtrr_reg >= 0) {
-			mtrr_del(par->mtrr_reg, 0, 0);
-			par->mtrr_reg = -1;
-		}
-#endif
-
-		dac_release(par->dac);
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-
-		pci_iounmap(dev, info->screen_base);
-		pci_release_regions(dev);
-/*		pci_disable_device(dev); */
-
-		framebuffer_release(info);
-	}
-}
-
-
-#ifdef CONFIG_PM
-/* PCI suspend */
-
-static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct arkfb_info *par = info->par;
-
-	dev_info(info->device, "suspend\n");
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
-		mutex_unlock(&(par->open_lock));
-		console_unlock();
-		return 0;
-	}
-
-	fb_set_suspend(info, 1);
-
-	pci_save_state(dev);
-	pci_disable_device(dev);
-	pci_set_power_state(dev, pci_choose_state(dev, state));
-
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-
-	return 0;
-}
-
-
-/* PCI resume */
-
-static int ark_pci_resume (struct pci_dev* dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct arkfb_info *par = info->par;
-
-	dev_info(info->device, "resume\n");
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	if (par->ref_count == 0)
-		goto fail;
-
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
-
-	if (pci_enable_device(dev))
-		goto fail;
-
-	pci_set_master(dev);
-
-	arkfb_set_par(info);
-	fb_set_suspend(info, 0);
-
-fail:
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-	return 0;
-}
-#else
-#define ark_pci_suspend NULL
-#define ark_pci_resume NULL
-#endif /* CONFIG_PM */
-
-/* List of boards that we are trying to support */
-
-static struct pci_device_id ark_devices[] = {
-	{PCI_DEVICE(0xEDD8, 0xA099)},
-	{0, 0, 0, 0, 0, 0, 0}
-};
-
-
-MODULE_DEVICE_TABLE(pci, ark_devices);
-
-static struct pci_driver arkfb_pci_driver = {
-	.name		= "arkfb",
-	.id_table	= ark_devices,
-	.probe		= ark_pci_probe,
-	.remove		= ark_pci_remove,
-	.suspend	= ark_pci_suspend,
-	.resume		= ark_pci_resume,
-};
-
-/* Cleanup */
-
-static void __exit arkfb_cleanup(void)
-{
-	pr_debug("arkfb: cleaning up\n");
-	pci_unregister_driver(&arkfb_pci_driver);
-}
-
-/* Driver Initialisation */
-
-static int __init arkfb_init(void)
-{
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("arkfb", &option))
-		return -ENODEV;
-
-	if (option && *option)
-		mode_option = option;
-#endif
-
-	pr_debug("arkfb: initializing\n");
-	return pci_register_driver(&arkfb_pci_driver);
-}
-
-module_init(arkfb_init);
-module_exit(arkfb_cleanup);
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
deleted file mode 100644
index 7e8ddf00ccc2..000000000000
--- a/drivers/video/asiliantfb.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * drivers/video/asiliantfb.c
- *  frame buffer driver for Asiliant 69000 chip
- *  Copyright (C) 2001-2003 Saito.K & Jeanne
- *
- *  from driver/video/chipsfb.c and,
- *
- *  drivers/video/asiliantfb.c -- frame buffer device for
- *  Asiliant 69030 chip (formerly Intel, formerly Chips & Technologies)
- *  Author: apc@agelectronics.co.uk
- *  Copyright (C) 2000 AG Electronics
- *  Note: the data sheets don't seem to be available from Asiliant.
- *  They are available by searching developer.intel.com, but are not otherwise
- *  linked to.
- *
- *  This driver should be portable with minimal effort to the 69000 display
- *  chip, and to the twin-display mode of the 69030.
- *  Contains code from Thomas Hhenleitner <th@visuelle-maschinen.de> (thanks)
- *
- *  Derived from the CT65550 driver chipsfb.c:
- *  Copyright (C) 1998 Paul Mackerras
- *  ...which was derived from the Powermac "chips" driver:
- *  Copyright (C) 1997 Fabio Riccardi.
- *  And from the frame buffer device for Open Firmware-initialized devices:
- *  Copyright (C) 1997 Geert Uytterhoeven.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-/* Built in clock of the 69030 */
-static const unsigned Fref = 14318180;
-
-#define mmio_base (p->screen_base + 0x400000)
-
-#define mm_write_ind(num, val, ap, dp)	do { \
-	writeb((num), mmio_base + (ap)); writeb((val), mmio_base + (dp)); \
-} while (0)
-
-static void mm_write_xr(struct fb_info *p, u8 reg, u8 data)
-{
-	mm_write_ind(reg, data, 0x7ac, 0x7ad);
-}
-#define write_xr(num, val)	mm_write_xr(p, num, val)
-
-static void mm_write_fr(struct fb_info *p, u8 reg, u8 data)
-{
-	mm_write_ind(reg, data, 0x7a0, 0x7a1);
-}
-#define write_fr(num, val)	mm_write_fr(p, num, val)
-
-static void mm_write_cr(struct fb_info *p, u8 reg, u8 data)
-{
-	mm_write_ind(reg, data, 0x7a8, 0x7a9);
-}
-#define write_cr(num, val)	mm_write_cr(p, num, val)
-
-static void mm_write_gr(struct fb_info *p, u8 reg, u8 data)
-{
-	mm_write_ind(reg, data, 0x79c, 0x79d);
-}
-#define write_gr(num, val)	mm_write_gr(p, num, val)
-
-static void mm_write_sr(struct fb_info *p, u8 reg, u8 data)
-{
-	mm_write_ind(reg, data, 0x788, 0x789);
-}
-#define write_sr(num, val)	mm_write_sr(p, num, val)
-
-static void mm_write_ar(struct fb_info *p, u8 reg, u8 data)
-{
-	readb(mmio_base + 0x7b4);
-	mm_write_ind(reg, data, 0x780, 0x780);
-}
-#define write_ar(num, val)	mm_write_ar(p, num, val)
-
-static int asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
-static int asiliantfb_check_var(struct fb_var_screeninfo *var,
-				struct fb_info *info);
-static int asiliantfb_set_par(struct fb_info *info);
-static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-				u_int transp, struct fb_info *info);
-
-static struct fb_ops asiliantfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= asiliantfb_check_var,
-	.fb_set_par	= asiliantfb_set_par,
-	.fb_setcolreg	= asiliantfb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-/* Calculate the ratios for the dot clocks without using a single long long
- * value */
-static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dclk2_div)
-{
-	unsigned pixclock = *ppixclock;
-	unsigned Ftarget = 1000000 * (1000000 / pixclock);
-	unsigned n;
-	unsigned best_error = 0xffffffff;
-	unsigned best_m = 0xffffffff,
-	         best_n = 0xffffffff;
-	unsigned ratio;
-	unsigned remainder;
-	unsigned char divisor = 0;
-
-	/* Calculate the frequency required. This is hard enough. */
-	ratio = 1000000 / pixclock;
-	remainder = 1000000 % pixclock;
-	Ftarget = 1000000 * ratio + (1000000 * remainder) / pixclock;
-
-	while (Ftarget < 100000000) {
-		divisor += 0x10;
-		Ftarget <<= 1;
-	}
-
-	ratio = Ftarget / Fref;
-	remainder = Ftarget % Fref;
-
-	/* This expresses the constraint that 150kHz <= Fref/n <= 5Mhz,
-	 * together with 3 <= n <= 257. */
-	for (n = 3; n <= 257; n++) {
-		unsigned m = n * ratio + (n * remainder) / Fref;
-
-		/* 3 <= m <= 257 */
-		if (m >= 3 && m <= 257) {
-			unsigned new_error = Ftarget * n >= Fref * m ?
-					       ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n));
-			if (new_error < best_error) {
-				best_n = n;
-				best_m = m;
-				best_error = new_error;
-			}
-		}
-		/* But if VLD = 4, then 4m <= 1028 */
-		else if (m <= 1028) {
-			/* remember there are still only 8-bits of precision in m, so
-			 * avoid over-optimistic error calculations */
-			unsigned new_error = Ftarget * n >= Fref * (m & ~3) ?
-					       ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n));
-			if (new_error < best_error) {
-				best_n = n;
-				best_m = m;
-				best_error = new_error;
-			}
-		}
-	}
-	if (best_m > 257)
-		best_m >>= 2;	/* divide m by 4, and leave VCO loop divide at 4 */
-	else
-		divisor |= 4;	/* or set VCO loop divide to 1 */
-	*dclk2_m = best_m - 2;
-	*dclk2_n = best_n - 2;
-	*dclk2_div = divisor;
-	*ppixclock = pixclock;
-	return;
-}
-
-static void asiliant_set_timing(struct fb_info *p)
-{
-	unsigned hd = p->var.xres / 8;
-	unsigned hs = (p->var.xres + p->var.right_margin) / 8;
-       	unsigned he = (p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
-	unsigned ht = (p->var.left_margin + p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
-	unsigned vd = p->var.yres;
-	unsigned vs = p->var.yres + p->var.lower_margin;
-	unsigned ve = p->var.yres + p->var.lower_margin + p->var.vsync_len;
-	unsigned vt = p->var.upper_margin + p->var.yres + p->var.lower_margin + p->var.vsync_len;
-	unsigned wd = (p->var.xres_virtual * ((p->var.bits_per_pixel+7)/8)) / 8;
-
-	if ((p->var.xres == 640) && (p->var.yres == 480) && (p->var.pixclock == 39722)) {
-	  write_fr(0x01, 0x02);  /* LCD */
-	} else {
-	  write_fr(0x01, 0x01);  /* CRT */
-	}
-
-	write_cr(0x11, (ve - 1) & 0x0f);
-	write_cr(0x00, (ht - 5) & 0xff);
-	write_cr(0x01, hd - 1);
-	write_cr(0x02, hd);
-	write_cr(0x03, ((ht - 1) & 0x1f) | 0x80);
-	write_cr(0x04, hs);
-	write_cr(0x05, (((ht - 1) & 0x20) <<2) | (he & 0x1f));
-	write_cr(0x3c, (ht - 1) & 0xc0);
-	write_cr(0x06, (vt - 2) & 0xff);
-	write_cr(0x30, (vt - 2) >> 8);
-	write_cr(0x07, 0x00);
-	write_cr(0x08, 0x00);
-	write_cr(0x09, 0x00);
-	write_cr(0x10, (vs - 1) & 0xff);
-	write_cr(0x32, ((vs - 1) >> 8) & 0xf);
-	write_cr(0x11, ((ve - 1) & 0x0f) | 0x80);
-	write_cr(0x12, (vd - 1) & 0xff);
-	write_cr(0x31, ((vd - 1) & 0xf00) >> 8);
-	write_cr(0x13, wd & 0xff);
-	write_cr(0x41, (wd & 0xf00) >> 8);
-	write_cr(0x15, (vs - 1) & 0xff);
-	write_cr(0x33, ((vs - 1) >> 8) & 0xf);
-	write_cr(0x38, ((ht - 5) & 0x100) >> 8);
-	write_cr(0x16, (vt - 1) & 0xff);
-	write_cr(0x18, 0x00);
-
-	if (p->var.xres == 640) {
-	  writeb(0xc7, mmio_base + 0x784);	/* set misc output reg */
-	} else {
-	  writeb(0x07, mmio_base + 0x784);	/* set misc output reg */
-	}
-}
-
-static int asiliantfb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *p)
-{
-	unsigned long Ftarget, ratio, remainder;
-
-	ratio = 1000000 / var->pixclock;
-	remainder = 1000000 % var->pixclock;
-	Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock;
-
-	/* First check the constraint that the maximum post-VCO divisor is 32,
-	 * and the maximum Fvco is 220MHz */
-	if (Ftarget > 220000000 || Ftarget < 3125000) {
-		printk(KERN_ERR "asiliantfb dotclock must be between 3.125 and 220MHz\n");
-		return -ENXIO;
-	}
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-
-	if (var->bits_per_pixel == 24) {
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = var->blue.length = var->green.length = 8;
-	} else if (var->bits_per_pixel == 16) {
-		switch (var->red.offset) {
-			case 11:
-				var->green.length = 6;
-				break;
-			case 10:
-				var->green.length = 5;
-				break;
-			default:
-				return -EINVAL;
-		}
-		var->green.offset = 5;
-		var->blue.offset = 0;
-		var->red.length = var->blue.length = 5;
-	} else if (var->bits_per_pixel == 8) {
-		var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 8;
-	}
-	return 0;
-}
-
-static int asiliantfb_set_par(struct fb_info *p)
-{
-	u8 dclk2_m;		/* Holds m-2 value for register */
-	u8 dclk2_n;		/* Holds n-2 value for register */
-	u8 dclk2_div;		/* Holds divisor bitmask */
-
-	/* Set pixclock */
-	asiliant_calc_dclk2(&p->var.pixclock, &dclk2_m, &dclk2_n, &dclk2_div);
-
-	/* Set color depth */
-	if (p->var.bits_per_pixel == 24) {
-		write_xr(0x81, 0x16);	/* 24 bit packed color mode */
-		write_xr(0x82, 0x00);	/* Disable palettes */
-		write_xr(0x20, 0x20);	/* 24 bit blitter mode */
-	} else if (p->var.bits_per_pixel == 16) {
-		if (p->var.red.offset == 11)
-			write_xr(0x81, 0x15);	/* 16 bit color mode */
-		else
-			write_xr(0x81, 0x14);	/* 15 bit color mode */
-		write_xr(0x82, 0x00);	/* Disable palettes */
-		write_xr(0x20, 0x10);	/* 16 bit blitter mode */
-	} else if (p->var.bits_per_pixel == 8) {
-		write_xr(0x0a, 0x02);	/* Linear */
-		write_xr(0x81, 0x12);	/* 8 bit color mode */
-		write_xr(0x82, 0x00);	/* Graphics gamma enable */
-		write_xr(0x20, 0x00);	/* 8 bit blitter mode */
-	}
-	p->fix.line_length = p->var.xres * (p->var.bits_per_pixel >> 3);
-	p->fix.visual = (p->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	write_xr(0xc4, dclk2_m);
-	write_xr(0xc5, dclk2_n);
-	write_xr(0xc7, dclk2_div);
-	/* Set up the CR registers */
-	asiliant_set_timing(p);
-	return 0;
-}
-
-static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *p)
-{
-	if (regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-        /* Set hardware palete */
-	writeb(regno, mmio_base + 0x790);
-	udelay(1);
-	writeb(red, mmio_base + 0x791);
-	writeb(green, mmio_base + 0x791);
-	writeb(blue, mmio_base + 0x791);
-
-	if (regno < 16) {
-		switch(p->var.red.offset) {
-		case 10: /* RGB 555 */
-			((u32 *)(p->pseudo_palette))[regno] =
-				((red & 0xf8) << 7) |
-				((green & 0xf8) << 2) |
-				((blue & 0xf8) >> 3);
-			break;
-		case 11: /* RGB 565 */
-			((u32 *)(p->pseudo_palette))[regno] =
-				((red & 0xf8) << 8) |
-				((green & 0xfc) << 3) |
-				((blue & 0xf8) >> 3);
-			break;
-		case 16: /* RGB 888 */
-			((u32 *)(p->pseudo_palette))[regno] =
-				(red << 16)  |
-				(green << 8) |
-				(blue);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-struct chips_init_reg {
-	unsigned char addr;
-	unsigned char data;
-};
-
-static struct chips_init_reg chips_init_sr[] =
-{
-	{0x00, 0x03},		/* Reset register */
-	{0x01, 0x01},		/* Clocking mode */
-	{0x02, 0x0f},		/* Plane mask */
-	{0x04, 0x0e}		/* Memory mode */
-};
-
-static struct chips_init_reg chips_init_gr[] =
-{
-        {0x03, 0x00},		/* Data rotate */
-	{0x05, 0x00},		/* Graphics mode */
-	{0x06, 0x01},		/* Miscellaneous */
-	{0x08, 0x00}		/* Bit mask */
-};
-
-static struct chips_init_reg chips_init_ar[] =
-{
-	{0x10, 0x01},		/* Mode control */
-	{0x11, 0x00},		/* Overscan */
-	{0x12, 0x0f},		/* Memory plane enable */
-	{0x13, 0x00}		/* Horizontal pixel panning */
-};
-
-static struct chips_init_reg chips_init_cr[] =
-{
-	{0x0c, 0x00},		/* Start address high */
-	{0x0d, 0x00},		/* Start address low */
-	{0x40, 0x00},		/* Extended Start Address */
-	{0x41, 0x00},		/* Extended Start Address */
-	{0x14, 0x00},		/* Underline location */
-	{0x17, 0xe3},		/* CRT mode control */
-	{0x70, 0x00}		/* Interlace control */
-};
-
-
-static struct chips_init_reg chips_init_fr[] =
-{
-	{0x01, 0x02},
-	{0x03, 0x08},
-	{0x08, 0xcc},
-	{0x0a, 0x08},
-	{0x18, 0x00},
-	{0x1e, 0x80},
-	{0x40, 0x83},
-	{0x41, 0x00},
-	{0x48, 0x13},
-	{0x4d, 0x60},
-	{0x4e, 0x0f},
-
-	{0x0b, 0x01},
-
-	{0x21, 0x51},
-	{0x22, 0x1d},
-	{0x23, 0x5f},
-	{0x20, 0x4f},
-	{0x34, 0x00},
-	{0x24, 0x51},
-	{0x25, 0x00},
-	{0x27, 0x0b},
-	{0x26, 0x00},
-	{0x37, 0x80},
-	{0x33, 0x0b},
-	{0x35, 0x11},
-	{0x36, 0x02},
-	{0x31, 0xea},
-	{0x32, 0x0c},
-	{0x30, 0xdf},
-	{0x10, 0x0c},
-	{0x11, 0xe0},
-	{0x12, 0x50},
-	{0x13, 0x00},
-	{0x16, 0x03},
-	{0x17, 0xbd},
-	{0x1a, 0x00},
-};
-
-
-static struct chips_init_reg chips_init_xr[] =
-{
-	{0xce, 0x00},		/* set default memory clock */
-	{0xcc, 200 },	        /* MCLK ratio M */
-	{0xcd, 18  },	        /* MCLK ratio N */
-	{0xce, 0x90},		/* MCLK divisor = 2 */
-
-	{0xc4, 209 },
-	{0xc5, 118 },
-	{0xc7, 32  },
-	{0xcf, 0x06},
-	{0x09, 0x01},		/* IO Control - CRT controller extensions */
-	{0x0a, 0x02},		/* Frame buffer mapping */
-	{0x0b, 0x01},		/* PCI burst write */
-	{0x40, 0x03},		/* Memory access control */
-	{0x80, 0x82},		/* Pixel pipeline configuration 0 */
-	{0x81, 0x12},		/* Pixel pipeline configuration 1 */
-	{0x82, 0x08},		/* Pixel pipeline configuration 2 */
-
-	{0xd0, 0x0f},
-	{0xd1, 0x01},
-};
-
-static void chips_hw_init(struct fb_info *p)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
-		write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
-	write_xr(0x81, 0x12);
-	write_xr(0x82, 0x08);
-	write_xr(0x20, 0x00);
-	for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
-		write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
-	for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
-		write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
-	for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
-		write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
-	/* Enable video output in attribute index register */
-	writeb(0x20, mmio_base + 0x780);
-	for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
-		write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
-	for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
-		write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
-}
-
-static struct fb_fix_screeninfo asiliantfb_fix = {
-	.id =		"Asiliant 69000",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.accel =	FB_ACCEL_NONE,
-	.line_length =	640,
-	.smem_len =	0x200000,	/* 2MB */
-};
-
-static struct fb_var_screeninfo asiliantfb_var = {
-	.xres 		= 640,
-	.yres 		= 480,
-	.xres_virtual 	= 640,
-	.yres_virtual 	= 480,
-	.bits_per_pixel = 8,
-	.red 		= { .length = 8 },
-	.green 		= { .length = 8 },
-	.blue 		= { .length = 8 },
-	.height 	= -1,
-	.width 		= -1,
-	.vmode 		= FB_VMODE_NONINTERLACED,
-	.pixclock 	= 39722,
-	.left_margin 	= 48,
-	.right_margin 	= 16,
-	.upper_margin 	= 33,
-	.lower_margin 	= 10,
-	.hsync_len 	= 96,
-	.vsync_len 	= 2,
-};
-
-static int init_asiliant(struct fb_info *p, unsigned long addr)
-{
-	int err;
-
-	p->fix			= asiliantfb_fix;
-	p->fix.smem_start	= addr;
-	p->var			= asiliantfb_var;
-	p->fbops		= &asiliantfb_ops;
-	p->flags		= FBINFO_DEFAULT;
-
-	err = fb_alloc_cmap(&p->cmap, 256, 0);
-	if (err) {
-		printk(KERN_ERR "C&T 69000 fb failed to alloc cmap memory\n");
-		return err;
-	}
-
-	err = register_framebuffer(p);
-	if (err < 0) {
-		printk(KERN_ERR "C&T 69000 framebuffer failed to register\n");
-		fb_dealloc_cmap(&p->cmap);
-		return err;
-	}
-
-	fb_info(p, "Asiliant 69000 frame buffer (%dK RAM detected)\n",
-		p->fix.smem_len / 1024);
-
-	writeb(0xff, mmio_base + 0x78c);
-	chips_hw_init(p);
-	return 0;
-}
-
-static int asiliantfb_pci_init(struct pci_dev *dp,
-			       const struct pci_device_id *ent)
-{
-	unsigned long addr, size;
-	struct fb_info *p;
-	int err;
-
-	if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
-		return -ENODEV;
-	addr = pci_resource_start(dp, 0);
-	size = pci_resource_len(dp, 0);
-	if (addr == 0)
-		return -ENODEV;
-	if (!request_mem_region(addr, size, "asiliantfb"))
-		return -EBUSY;
-
-	p = framebuffer_alloc(sizeof(u32) * 16, &dp->dev);
-	if (!p)	{
-		release_mem_region(addr, size);
-		return -ENOMEM;
-	}
-	p->pseudo_palette = p->par;
-	p->par = NULL;
-
-	p->screen_base = ioremap(addr, 0x800000);
-	if (p->screen_base == NULL) {
-		release_mem_region(addr, size);
-		framebuffer_release(p);
-		return -ENOMEM;
-	}
-
-	pci_write_config_dword(dp, 4, 0x02800083);
-	writeb(3, p->screen_base + 0x400784);
-
-	err = init_asiliant(p, addr);
-	if (err) {
-		iounmap(p->screen_base);
-		release_mem_region(addr, size);
-		framebuffer_release(p);
-		return err;
-	}
-
-	pci_set_drvdata(dp, p);
-	return 0;
-}
-
-static void asiliantfb_remove(struct pci_dev *dp)
-{
-	struct fb_info *p = pci_get_drvdata(dp);
-
-	unregister_framebuffer(p);
-	fb_dealloc_cmap(&p->cmap);
-	iounmap(p->screen_base);
-	release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0));
-	framebuffer_release(p);
-}
-
-static struct pci_device_id asiliantfb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000, PCI_ANY_ID, PCI_ANY_ID },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, asiliantfb_pci_tbl);
-
-static struct pci_driver asiliantfb_driver = {
-	.name =		"asiliantfb",
-	.id_table =	asiliantfb_pci_tbl,
-	.probe =	asiliantfb_pci_init,
-	.remove =	asiliantfb_remove,
-};
-
-static int __init asiliantfb_init(void)
-{
-	if (fb_get_options("asiliantfb", NULL))
-		return -ENODEV;
-
-	return pci_register_driver(&asiliantfb_driver);
-}
-
-module_init(asiliantfb_init);
-
-static void __exit asiliantfb_exit(void)
-{
-	pci_unregister_driver(&asiliantfb_driver);
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
deleted file mode 100644
index e21d1f58554c..000000000000
--- a/drivers/video/atafb.c
+++ /dev/null
@@ -1,3266 +0,0 @@
-/*
- * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
- *
- *  Copyright (C) 1994 Martin Schaller & Roman Hodek
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- * History:
- *   - 03 Jan 95: Original version by Martin Schaller: The TT driver and
- *                all the device independent stuff
- *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
- *                and wrote the Falcon, ST(E), and External drivers
- *                based on the original TT driver.
- *   - 07 May 95: Martin: Added colormap operations for the external driver
- *   - 21 May 95: Martin: Added support for overscan
- *		  Andreas: some bug fixes for this
- *   -    Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
- *                Programmable Falcon video modes
- *                (thanks to Christian Cartus for documentation
- *                of VIDEL registers).
- *   - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
- *                on minor 24...31. "user0" may be set on commandline by
- *                "R<x>;<y>;<depth>". (Makes sense only on Falcon)
- *                Video mode switch on Falcon now done at next VBL interrupt
- *                to avoid the annoying right shift of the screen.
- *   - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
- *                The external-part is legacy, therefore hardware-specific
- *                functions like panning/hardwarescrolling/blanking isn't
- *				  supported.
- *   - 29 Sep 97: Juergen: added Romans suggestion for pan_display
- *				  (var->xoffset was changed even if no set_screen_base avail.)
- *	 - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
- *				  we know how to set the colors
- *				  ext_*palette: read from ext_colors (former MV300_colors)
- *							    write to ext_colors and RAMDAC
- *
- * To do:
- *   - For the Falcon it is not possible to set random video modes on
- *     SM124 and SC/TV, only the bootup resolution is supported.
- *
- */
-
-#define ATAFB_TT
-#define ATAFB_STE
-#define ATAFB_EXT
-#define ATAFB_FALCON
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <linux/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_stram.h>
-
-#include <linux/fb.h>
-#include <asm/atarikb.h>
-
-#include "c2p.h"
-#include "atafb.h"
-
-#define SWITCH_ACIA 0x01		/* modes for switch on OverScan */
-#define SWITCH_SND6 0x40
-#define SWITCH_SND7 0x80
-#define SWITCH_NONE 0x00
-
-
-#define up(x, r) (((x) + (r) - 1) & ~((r)-1))
-
-	/*
-	 * Interface to the world
-	 */
-
-static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
-static int atafb_set_par(struct fb_info *info);
-static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
-			   unsigned int blue, unsigned int transp,
-			   struct fb_info *info);
-static int atafb_blank(int blank, struct fb_info *info);
-static int atafb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info);
-static void atafb_fillrect(struct fb_info *info,
-			   const struct fb_fillrect *rect);
-static void atafb_copyarea(struct fb_info *info,
-			   const struct fb_copyarea *region);
-static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
-static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
-		       unsigned long arg);
-
-
-static int default_par;		/* default resolution (0=none) */
-
-static unsigned long default_mem_req;
-
-static int hwscroll = -1;
-
-static int use_hwscroll = 1;
-
-static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
-static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
-static int ovsc_offset, ovsc_addlen;
-
-	/*
-	 * Hardware parameters for current mode
-	 */
-
-static struct atafb_par {
-	void *screen_base;
-	int yres_virtual;
-	u_long next_line;
-#if defined ATAFB_TT || defined ATAFB_STE
-	union {
-		struct {
-			int mode;
-			int sync;
-		} tt, st;
-#endif
-#ifdef ATAFB_FALCON
-		struct falcon_hw {
-			/* Here are fields for storing a video mode, as direct
-			 * parameters for the hardware.
-			 */
-			short sync;
-			short line_width;
-			short line_offset;
-			short st_shift;
-			short f_shift;
-			short vid_control;
-			short vid_mode;
-			short xoffset;
-			short hht, hbb, hbe, hdb, hde, hss;
-			short vft, vbb, vbe, vdb, vde, vss;
-			/* auxiliary information */
-			short mono;
-			short ste_mode;
-			short bpp;
-			u32 pseudo_palette[16];
-		} falcon;
-#endif
-		/* Nothing needed for external mode */
-	} hw;
-} current_par;
-
-/* Don't calculate an own resolution, and thus don't change the one found when
- * booting (currently used for the Falcon to keep settings for internal video
- * hardware extensions (e.g. ScreenBlaster)  */
-static int DontCalcRes = 0;
-
-#ifdef ATAFB_FALCON
-#define HHT hw.falcon.hht
-#define HBB hw.falcon.hbb
-#define HBE hw.falcon.hbe
-#define HDB hw.falcon.hdb
-#define HDE hw.falcon.hde
-#define HSS hw.falcon.hss
-#define VFT hw.falcon.vft
-#define VBB hw.falcon.vbb
-#define VBE hw.falcon.vbe
-#define VDB hw.falcon.vdb
-#define VDE hw.falcon.vde
-#define VSS hw.falcon.vss
-#define VCO_CLOCK25		0x04
-#define VCO_CSYPOS		0x10
-#define VCO_VSYPOS		0x20
-#define VCO_HSYPOS		0x40
-#define VCO_SHORTOFFS	0x100
-#define VMO_DOUBLE		0x01
-#define VMO_INTER		0x02
-#define VMO_PREMASK		0x0c
-#endif
-
-static struct fb_info fb_info = {
-	.fix = {
-		.id	= "Atari ",
-		.visual	= FB_VISUAL_PSEUDOCOLOR,
-		.accel	= FB_ACCEL_NONE,
-	}
-};
-
-static void *screen_base;	/* base address of screen */
-static void *real_screen_base;	/* (only for Overscan) */
-
-static int screen_len;
-
-static int current_par_valid;
-
-static int mono_moni;
-
-
-#ifdef ATAFB_EXT
-
-/* external video handling */
-static unsigned int external_xres;
-static unsigned int external_xres_virtual;
-static unsigned int external_yres;
-
-/*
- * not needed - atafb will never support panning/hardwarescroll with external
- * static unsigned int external_yres_virtual;
- */
-static unsigned int external_depth;
-static int external_pmode;
-static void *external_addr;
-static unsigned long external_len;
-static unsigned long external_vgaiobase;
-static unsigned int external_bitspercol = 6;
-
-/*
- * JOE <joe@amber.dinoco.de>:
- * added card type for external driver, is only needed for
- * colormap handling.
- */
-enum cardtype { IS_VGA, IS_MV300 };
-static enum cardtype external_card_type = IS_VGA;
-
-/*
- * The MV300 mixes the color registers. So we need an array of munged
- * indices in order to access the correct reg.
- */
-static int MV300_reg_1bit[2] = {
-	0, 1
-};
-static int MV300_reg_4bit[16] = {
-	0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
-};
-static int MV300_reg_8bit[256] = {
-	0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
-	8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
-	4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
-	12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
-	2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
-	10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
-	6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
-	14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
-	1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
-	9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
-	5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
-	13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
-	3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
-	11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
-	7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
-	15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
-};
-
-static int *MV300_reg = MV300_reg_8bit;
-#endif /* ATAFB_EXT */
-
-
-static int inverse;
-
-extern int fontheight_8x8;
-extern int fontwidth_8x8;
-extern unsigned char fontdata_8x8[];
-
-extern int fontheight_8x16;
-extern int fontwidth_8x16;
-extern unsigned char fontdata_8x16[];
-
-/*
- * struct fb_ops {
- *	* open/release and usage marking
- *	struct module *owner;
- *	int (*fb_open)(struct fb_info *info, int user);
- *	int (*fb_release)(struct fb_info *info, int user);
- *
- *	* For framebuffers with strange non linear layouts or that do not
- *	* work with normal memory mapped access
- *	ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
- *	ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
- *
- *	* checks var and eventually tweaks it to something supported,
- *	* DOES NOT MODIFY PAR *
- *	int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
- *
- *	* set the video mode according to info->var *
- *	int (*fb_set_par)(struct fb_info *info);
- *
- *	* set color register *
- *	int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
- *			    unsigned int blue, unsigned int transp, struct fb_info *info);
- *
- *	* set color registers in batch *
- *	int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
- *
- *	* blank display *
- *	int (*fb_blank)(int blank, struct fb_info *info);
- *
- *	* pan display *
- *	int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
- *
- *	*** The meat of the drawing engine ***
- *	* Draws a rectangle *
- *	void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
- *	* Copy data from area to another *
- *	void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
- *	* Draws a image to the display *
- *	void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
- *
- *	* Draws cursor *
- *	int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
- *
- *	* Rotates the display *
- *	void (*fb_rotate)(struct fb_info *info, int angle);
- *
- *	* wait for blit idle, optional *
- *	int (*fb_sync)(struct fb_info *info);
- *
- *	* perform fb specific ioctl (optional) *
- *	int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
- *			unsigned long arg);
- *
- *	* Handle 32bit compat ioctl (optional) *
- *	int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
- *			unsigned long arg);
- *
- *	* perform fb specific mmap *
- *	int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
- * } ;
- */
-
-
-/* ++roman: This structure abstracts from the underlying hardware (ST(e),
- * TT, or Falcon.
- *
- * int (*detect)(void)
- *   This function should detect the current video mode settings and
- *   store them in atafb_predefined[0] for later reference by the
- *   user. Return the index+1 of an equivalent predefined mode or 0
- *   if there is no such.
- *
- * int (*encode_fix)(struct fb_fix_screeninfo *fix,
- *                   struct atafb_par *par)
- *   This function should fill in the 'fix' structure based on the
- *   values in the 'par' structure.
- * !!! Obsolete, perhaps !!!
- *
- * int (*decode_var)(struct fb_var_screeninfo *var,
- *                   struct atafb_par *par)
- *   Get the video params out of 'var'. If a value doesn't fit, round
- *   it up, if it's too big, return EINVAL.
- *   Round up in the following order: bits_per_pixel, xres, yres,
- *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
- *   horizontal timing, vertical timing.
- *
- * int (*encode_var)(struct fb_var_screeninfo *var,
- *                   struct atafb_par *par);
- *   Fill the 'var' structure based on the values in 'par' and maybe
- *   other values read out of the hardware.
- *
- * void (*get_par)(struct atafb_par *par)
- *   Fill the hardware's 'par' structure.
- *   !!! Used only by detect() !!!
- *
- * void (*set_par)(struct atafb_par *par)
- *   Set the hardware according to 'par'.
- *
- * void (*set_screen_base)(void *s_base)
- *   Set the base address of the displayed frame buffer. Only called
- *   if yres_virtual > yres or xres_virtual > xres.
- *
- * int (*blank)(int blank_mode)
- *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
- *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
- *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
- *   doesn't support it. Implements VESA suspend and powerdown modes on
- *   hardware that supports disabling hsync/vsync:
- *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
- */
-
-static struct fb_hwswitch {
-	int (*detect)(void);
-	int (*encode_fix)(struct fb_fix_screeninfo *fix,
-			  struct atafb_par *par);
-	int (*decode_var)(struct fb_var_screeninfo *var,
-			  struct atafb_par *par);
-	int (*encode_var)(struct fb_var_screeninfo *var,
-			  struct atafb_par *par);
-	void (*get_par)(struct atafb_par *par);
-	void (*set_par)(struct atafb_par *par);
-	void (*set_screen_base)(void *s_base);
-	int (*blank)(int blank_mode);
-	int (*pan_display)(struct fb_var_screeninfo *var,
-			   struct fb_info *info);
-} *fbhw;
-
-static char *autodetect_names[] = { "autodetect", NULL };
-static char *stlow_names[] = { "stlow", NULL };
-static char *stmid_names[] = { "stmid", "default5", NULL };
-static char *sthigh_names[] = { "sthigh", "default4", NULL };
-static char *ttlow_names[] = { "ttlow", NULL };
-static char *ttmid_names[] = { "ttmid", "default1", NULL };
-static char *tthigh_names[] = { "tthigh", "default2", NULL };
-static char *vga2_names[] = { "vga2", NULL };
-static char *vga4_names[] = { "vga4", NULL };
-static char *vga16_names[] = { "vga16", "default3", NULL };
-static char *vga256_names[] = { "vga256", NULL };
-static char *falh2_names[] = { "falh2", NULL };
-static char *falh16_names[] = { "falh16", NULL };
-
-static char **fb_var_names[] = {
-	autodetect_names,
-	stlow_names,
-	stmid_names,
-	sthigh_names,
-	ttlow_names,
-	ttmid_names,
-	tthigh_names,
-	vga2_names,
-	vga4_names,
-	vga16_names,
-	vga256_names,
-	falh2_names,
-	falh16_names,
-	NULL
-};
-
-static struct fb_var_screeninfo atafb_predefined[] = {
-	/*
-	 * yres_virtual == 0 means use hw-scrolling if possible, else yres
-	 */
-	{ /* autodetect */
-	  0, 0, 0, 0, 0, 0, 0, 0,		/* xres-grayscale */
-	  {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},	/* red green blue tran*/
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* st low */
-	  320, 200, 320, 0, 0, 0, 4, 0,
-	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* st mid */
-	  640, 200, 640, 0, 0, 0, 2, 0,
-	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* st high */
-	  640, 400, 640, 0, 0, 0, 1, 0,
-	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* tt low */
-	  320, 480, 320, 0, 0, 0, 8, 0,
-	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* tt mid */
-	  640, 480, 640, 0, 0, 0, 4, 0,
-	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* tt high */
-	  1280, 960, 1280, 0, 0, 0, 1, 0,
-	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* vga2 */
-	  640, 480, 640, 0, 0, 0, 1, 0,
-	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* vga4 */
-	  640, 480, 640, 0, 0, 0, 2, 0,
-	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* vga16 */
-	  640, 480, 640, 0, 0, 0, 4, 0,
-	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* vga256 */
-	  640, 480, 640, 0, 0, 0, 8, 0,
-	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* falh2 */
-	  896, 608, 896, 0, 0, 0, 1, 0,
-	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ /* falh16 */
-	  896, 608, 896, 0, 0, 0, 4, 0,
-	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-
-static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
-
-static struct fb_videomode atafb_modedb[] __initdata = {
-	/*
-	 *  Atari Video Modes
-	 *
-	 *  If you change these, make sure to update DEFMODE_* as well!
-	 */
-
-	/*
-	 *  ST/TT Video Modes
-	 */
-
-	{
-		/* 320x200, 15 kHz, 60 Hz (ST low) */
-		"st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x200, 15 kHz, 60 Hz (ST medium) */
-		"st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
-		"st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 320x480, 15 kHz, 60 Hz (TT low) */
-		"tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x480, 29 kHz, 57 Hz (TT medium) */
-		"tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 1280x960, 29 kHz, 60 Hz (TT high) */
-		"tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	},
-
-	/*
-	 *  VGA Video Modes
-	 */
-
-	{
-		/* 640x480, 31 kHz, 60 Hz (VGA) */
-		"vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	}, {
-		/* 640x400, 31 kHz, 70 Hz (VGA) */
-		"vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
-		FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	},
-
-	/*
-	 *  Falcon HiRes Video Modes
-	 */
-
-	{
-		/* 896x608, 31 kHz, 60 Hz (Falcon High) */
-		"falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
-		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
-	},
-};
-
-#define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
-
-static char *mode_option __initdata = NULL;
-
- /* default modes */
-
-#define DEFMODE_TT	5		/* "tt-high" for TT */
-#define DEFMODE_F30	7		/* "vga70" for Falcon */
-#define DEFMODE_STE	2		/* "st-high" for ST/E */
-#define DEFMODE_EXT	6		/* "vga" for external */
-
-
-static int get_video_mode(char *vname)
-{
-	char ***name_list;
-	char **name;
-	int i;
-
-	name_list = fb_var_names;
-	for (i = 0; i < num_atafb_predefined; i++) {
-		name = *name_list++;
-		if (!name || !*name)
-			break;
-		while (*name) {
-			if (!strcmp(vname, *name))
-				return i + 1;
-			name++;
-		}
-	}
-	return 0;
-}
-
-
-
-/* ------------------- TT specific functions ---------------------- */
-
-#ifdef ATAFB_TT
-
-static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
-{
-	int mode;
-
-	strcpy(fix->id, "Atari Builtin");
-	fix->smem_start = (unsigned long)real_screen_base;
-	fix->smem_len = screen_len;
-	fix->type = FB_TYPE_INTERLEAVED_PLANES;
-	fix->type_aux = 2;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
-	if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->type_aux = 0;
-		if (mode == TT_SHIFTER_TTHIGH)
-			fix->visual = FB_VISUAL_MONO01;
-	}
-	fix->xpanstep = 0;
-	fix->ypanstep = 1;
-	fix->ywrapstep = 0;
-	fix->line_length = par->next_line;
-	fix->accel = FB_ACCEL_ATARIBLITT;
-	return 0;
-}
-
-static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
-	int xres = var->xres;
-	int yres = var->yres;
-	int bpp = var->bits_per_pixel;
-	int linelen;
-	int yres_virtual = var->yres_virtual;
-
-	if (mono_moni) {
-		if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
-			return -EINVAL;
-		par->hw.tt.mode = TT_SHIFTER_TTHIGH;
-		xres = sttt_xres * 2;
-		yres = tt_yres * 2;
-		bpp = 1;
-	} else {
-		if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
-			return -EINVAL;
-		if (bpp > 4) {
-			if (xres > sttt_xres / 2 || yres > tt_yres)
-				return -EINVAL;
-			par->hw.tt.mode = TT_SHIFTER_TTLOW;
-			xres = sttt_xres / 2;
-			yres = tt_yres;
-			bpp = 8;
-		} else if (bpp > 2) {
-			if (xres > sttt_xres || yres > tt_yres)
-				return -EINVAL;
-			if (xres > sttt_xres / 2 || yres > st_yres / 2) {
-				par->hw.tt.mode = TT_SHIFTER_TTMID;
-				xres = sttt_xres;
-				yres = tt_yres;
-				bpp = 4;
-			} else {
-				par->hw.tt.mode = TT_SHIFTER_STLOW;
-				xres = sttt_xres / 2;
-				yres = st_yres / 2;
-				bpp = 4;
-			}
-		} else if (bpp > 1) {
-			if (xres > sttt_xres || yres > st_yres / 2)
-				return -EINVAL;
-			par->hw.tt.mode = TT_SHIFTER_STMID;
-			xres = sttt_xres;
-			yres = st_yres / 2;
-			bpp = 2;
-		} else if (var->xres > sttt_xres || var->yres > st_yres) {
-			return -EINVAL;
-		} else {
-			par->hw.tt.mode = TT_SHIFTER_STHIGH;
-			xres = sttt_xres;
-			yres = st_yres;
-			bpp = 1;
-		}
-	}
-	if (yres_virtual <= 0)
-		yres_virtual = 0;
-	else if (yres_virtual < yres)
-		yres_virtual = yres;
-	if (var->sync & FB_SYNC_EXT)
-		par->hw.tt.sync = 0;
-	else
-		par->hw.tt.sync = 1;
-	linelen = xres * bpp / 8;
-	if (yres_virtual * linelen > screen_len && screen_len)
-		return -EINVAL;
-	if (yres * linelen > screen_len && screen_len)
-		return -EINVAL;
-	if (var->yoffset + yres > yres_virtual && yres_virtual)
-		return -EINVAL;
-	par->yres_virtual = yres_virtual;
-	par->screen_base = screen_base + var->yoffset * linelen;
-	par->next_line = linelen;
-	return 0;
-}
-
-static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
-	int linelen;
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->red.offset = 0;
-	var->red.length = 4;
-	var->red.msb_right = 0;
-	var->grayscale = 0;
-
-	var->pixclock = 31041;
-	var->left_margin = 120;		/* these may be incorrect */
-	var->right_margin = 100;
-	var->upper_margin = 8;
-	var->lower_margin = 16;
-	var->hsync_len = 140;
-	var->vsync_len = 30;
-
-	var->height = -1;
-	var->width = -1;
-
-	if (par->hw.tt.sync & 1)
-		var->sync = 0;
-	else
-		var->sync = FB_SYNC_EXT;
-
-	switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
-	case TT_SHIFTER_STLOW:
-		var->xres = sttt_xres / 2;
-		var->xres_virtual = sttt_xres_virtual / 2;
-		var->yres = st_yres / 2;
-		var->bits_per_pixel = 4;
-		break;
-	case TT_SHIFTER_STMID:
-		var->xres = sttt_xres;
-		var->xres_virtual = sttt_xres_virtual;
-		var->yres = st_yres / 2;
-		var->bits_per_pixel = 2;
-		break;
-	case TT_SHIFTER_STHIGH:
-		var->xres = sttt_xres;
-		var->xres_virtual = sttt_xres_virtual;
-		var->yres = st_yres;
-		var->bits_per_pixel = 1;
-		break;
-	case TT_SHIFTER_TTLOW:
-		var->xres = sttt_xres / 2;
-		var->xres_virtual = sttt_xres_virtual / 2;
-		var->yres = tt_yres;
-		var->bits_per_pixel = 8;
-		break;
-	case TT_SHIFTER_TTMID:
-		var->xres = sttt_xres;
-		var->xres_virtual = sttt_xres_virtual;
-		var->yres = tt_yres;
-		var->bits_per_pixel = 4;
-		break;
-	case TT_SHIFTER_TTHIGH:
-		var->red.length = 0;
-		var->xres = sttt_xres * 2;
-		var->xres_virtual = sttt_xres_virtual * 2;
-		var->yres = tt_yres * 2;
-		var->bits_per_pixel = 1;
-		break;
-	}
-	var->blue = var->green = var->red;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-	linelen = var->xres_virtual * var->bits_per_pixel / 8;
-	if (!use_hwscroll)
-		var->yres_virtual = var->yres;
-	else if (screen_len) {
-		if (par->yres_virtual)
-			var->yres_virtual = par->yres_virtual;
-		else
-			/* yres_virtual == 0 means use maximum */
-			var->yres_virtual = screen_len / linelen;
-	} else {
-		if (hwscroll < 0)
-			var->yres_virtual = 2 * var->yres;
-		else
-			var->yres_virtual = var->yres + hwscroll * 16;
-	}
-	var->xoffset = 0;
-	if (screen_base)
-		var->yoffset = (par->screen_base - screen_base) / linelen;
-	else
-		var->yoffset = 0;
-	var->nonstd = 0;
-	var->activate = 0;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	return 0;
-}
-
-static void tt_get_par(struct atafb_par *par)
-{
-	unsigned long addr;
-	par->hw.tt.mode = shifter_tt.tt_shiftmode;
-	par->hw.tt.sync = shifter.syncmode;
-	addr = ((shifter.bas_hi & 0xff) << 16) |
-	       ((shifter.bas_md & 0xff) << 8)  |
-	       ((shifter.bas_lo & 0xff));
-	par->screen_base = phys_to_virt(addr);
-}
-
-static void tt_set_par(struct atafb_par *par)
-{
-	shifter_tt.tt_shiftmode = par->hw.tt.mode;
-	shifter.syncmode = par->hw.tt.sync;
-	/* only set screen_base if really necessary */
-	if (current_par.screen_base != par->screen_base)
-		fbhw->set_screen_base(par->screen_base);
-}
-
-static int tt_setcolreg(unsigned int regno, unsigned int red,
-			unsigned int green, unsigned int blue,
-			unsigned int transp, struct fb_info *info)
-{
-	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
-		regno += 254;
-	if (regno > 255)
-		return 1;
-	tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
-			     (blue >> 12));
-	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
-	    TT_SHIFTER_STHIGH && regno == 254)
-		tt_palette[0] = 0;
-	return 0;
-}
-
-static int tt_detect(void)
-{
-	struct atafb_par par;
-
-	/* Determine the connected monitor: The DMA sound must be
-	 * disabled before reading the MFP GPIP, because the Sound
-	 * Done Signal and the Monochrome Detect are XORed together!
-	 *
-	 * Even on a TT, we should look if there is a DMA sound. It was
-	 * announced that the Eagle is TT compatible, but only the PCM is
-	 * missing...
-	 */
-	if (ATARIHW_PRESENT(PCM_8BIT)) {
-		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-		udelay(20);		/* wait a while for things to settle down */
-	}
-	mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
-
-	tt_get_par(&par);
-	tt_encode_var(&atafb_predefined[0], &par);
-
-	return 1;
-}
-
-#endif /* ATAFB_TT */
-
-/* ------------------- Falcon specific functions ---------------------- */
-
-#ifdef ATAFB_FALCON
-
-static int mon_type;		/* Falcon connected monitor */
-static int f030_bus_width;	/* Falcon ram bus width (for vid_control) */
-#define F_MON_SM	0
-#define F_MON_SC	1
-#define F_MON_VGA	2
-#define F_MON_TV	3
-
-static struct pixel_clock {
-	unsigned long f;	/* f/[Hz] */
-	unsigned long t;	/* t/[ps] (=1/f) */
-	int right, hsync, left;	/* standard timing in clock cycles, not pixel */
-	/* hsync initialized in falcon_detect() */
-	int sync_mask;		/* or-mask for hw.falcon.sync to set this clock */
-	int control_mask;	/* ditto, for hw.falcon.vid_control */
-} f25 = {
-	25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
-}, f32 = {
-	32000000, 31250, 18, 0, 42, 0x0, 0
-}, fext = {
-	0, 0, 18, 0, 42, 0x1, 0
-};
-
-/* VIDEL-prescale values [mon_type][pixel_length from VCO] */
-static int vdl_prescale[4][3] = {
-	{ 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
-};
-
-/* Default hsync timing [mon_type] in picoseconds */
-static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
-
-static inline int hxx_prescale(struct falcon_hw *hw)
-{
-	return hw->ste_mode ? 16
-			    : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
-}
-
-static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
-			     struct atafb_par *par)
-{
-	strcpy(fix->id, "Atari Builtin");
-	fix->smem_start = (unsigned long)real_screen_base;
-	fix->smem_len = screen_len;
-	fix->type = FB_TYPE_INTERLEAVED_PLANES;
-	fix->type_aux = 2;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	fix->xpanstep = 1;
-	fix->ypanstep = 1;
-	fix->ywrapstep = 0;
-	if (par->hw.falcon.mono) {
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->type_aux = 0;
-		/* no smooth scrolling with longword aligned video mem */
-		fix->xpanstep = 32;
-	} else if (par->hw.falcon.f_shift & 0x100) {
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->type_aux = 0;
-		/* Is this ok or should it be DIRECTCOLOR? */
-		fix->visual = FB_VISUAL_TRUECOLOR;
-		fix->xpanstep = 2;
-	}
-	fix->line_length = par->next_line;
-	fix->accel = FB_ACCEL_ATARIBLITT;
-	return 0;
-}
-
-static int falcon_decode_var(struct fb_var_screeninfo *var,
-			     struct atafb_par *par)
-{
-	int bpp = var->bits_per_pixel;
-	int xres = var->xres;
-	int yres = var->yres;
-	int xres_virtual = var->xres_virtual;
-	int yres_virtual = var->yres_virtual;
-	int left_margin, right_margin, hsync_len;
-	int upper_margin, lower_margin, vsync_len;
-	int linelen;
-	int interlace = 0, doubleline = 0;
-	struct pixel_clock *pclock;
-	int plen;			/* width of pixel in clock cycles */
-	int xstretch;
-	int prescale;
-	int longoffset = 0;
-	int hfreq, vfreq;
-	int hdb_off, hde_off, base_off;
-	int gstart, gend1, gend2, align;
-
-/*
-	Get the video params out of 'var'. If a value doesn't fit, round
-	it up, if it's too big, return EINVAL.
-	Round up in the following order: bits_per_pixel, xres, yres,
-	xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
-	horizontal timing, vertical timing.
-
-	There is a maximum of screen resolution determined by pixelclock
-	and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
-	In interlace mode this is     "     *    "     *vfmin <= pixelclock.
-	Additional constraints: hfreq.
-	Frequency range for multisync monitors is given via command line.
-	For TV and SM124 both frequencies are fixed.
-
-	X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
-	Y % 16 == 0 to fit 8x16 font
-	Y % 8 == 0 if Y<400
-
-	Currently interlace and doubleline mode in var are ignored.
-	On SM124 and TV only the standard resolutions can be used.
-*/
-
-	/* Reject uninitialized mode */
-	if (!xres || !yres || !bpp)
-		return -EINVAL;
-
-	if (mon_type == F_MON_SM && bpp != 1)
-		return -EINVAL;
-
-	if (bpp <= 1) {
-		bpp = 1;
-		par->hw.falcon.f_shift = 0x400;
-		par->hw.falcon.st_shift = 0x200;
-	} else if (bpp <= 2) {
-		bpp = 2;
-		par->hw.falcon.f_shift = 0x000;
-		par->hw.falcon.st_shift = 0x100;
-	} else if (bpp <= 4) {
-		bpp = 4;
-		par->hw.falcon.f_shift = 0x000;
-		par->hw.falcon.st_shift = 0x000;
-	} else if (bpp <= 8) {
-		bpp = 8;
-		par->hw.falcon.f_shift = 0x010;
-	} else if (bpp <= 16) {
-		bpp = 16;		/* packed pixel mode */
-		par->hw.falcon.f_shift = 0x100;	/* hicolor, no overlay */
-	} else
-		return -EINVAL;
-	par->hw.falcon.bpp = bpp;
-
-	if (mon_type == F_MON_SM || DontCalcRes) {
-		/* Skip all calculations. VGA/TV/SC1224 only supported. */
-		struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-
-		if (bpp > myvar->bits_per_pixel ||
-		    var->xres > myvar->xres ||
-		    var->yres > myvar->yres)
-			return -EINVAL;
-		fbhw->get_par(par);	/* Current par will be new par */
-		goto set_screen_base;	/* Don't forget this */
-	}
-
-	/* Only some fixed resolutions < 640x400 */
-	if (xres <= 320)
-		xres = 320;
-	else if (xres <= 640 && bpp != 16)
-		xres = 640;
-	if (yres <= 200)
-		yres = 200;
-	else if (yres <= 240)
-		yres = 240;
-	else if (yres <= 400)
-		yres = 400;
-
-	/* 2 planes must use STE compatibility mode */
-	par->hw.falcon.ste_mode = bpp == 2;
-	par->hw.falcon.mono = bpp == 1;
-
-	/* Total and visible scanline length must be a multiple of one longword,
-	 * this and the console fontwidth yields the alignment for xres and
-	 * xres_virtual.
-	 * TODO: this way "odd" fontheights are not supported
-	 *
-	 * Special case in STE mode: blank and graphic positions don't align,
-	 * avoid trash at right margin
-	 */
-	if (par->hw.falcon.ste_mode)
-		xres = (xres + 63) & ~63;
-	else if (bpp == 1)
-		xres = (xres + 31) & ~31;
-	else
-		xres = (xres + 15) & ~15;
-	if (yres >= 400)
-		yres = (yres + 15) & ~15;
-	else
-		yres = (yres + 7) & ~7;
-
-	if (xres_virtual < xres)
-		xres_virtual = xres;
-	else if (bpp == 1)
-		xres_virtual = (xres_virtual + 31) & ~31;
-	else
-		xres_virtual = (xres_virtual + 15) & ~15;
-
-	if (yres_virtual <= 0)
-		yres_virtual = 0;
-	else if (yres_virtual < yres)
-		yres_virtual = yres;
-
-	/* backward bug-compatibility */
-	if (var->pixclock > 1)
-		var->pixclock -= 1;
-
-	par->hw.falcon.line_width = bpp * xres / 16;
-	par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
-
-	/* single or double pixel width */
-	xstretch = (xres < 640) ? 2 : 1;
-
-#if 0 /* SM124 supports only 640x400, this is rejected above */
-	if (mon_type == F_MON_SM) {
-		if (xres != 640 && yres != 400)
-			return -EINVAL;
-		plen = 1;
-		pclock = &f32;
-		/* SM124-mode is special */
-		par->hw.falcon.ste_mode = 1;
-		par->hw.falcon.f_shift = 0x000;
-		par->hw.falcon.st_shift = 0x200;
-		left_margin = hsync_len = 128 / plen;
-		right_margin = 0;
-		/* TODO set all margins */
-	} else
-#endif
-	if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
-		plen = 2 * xstretch;
-		if (var->pixclock > f32.t * plen)
-			return -EINVAL;
-		pclock = &f32;
-		if (yres > 240)
-			interlace = 1;
-		if (var->pixclock == 0) {
-			/* set some minimal margins which center the screen */
-			left_margin = 32;
-			right_margin = 18;
-			hsync_len = pclock->hsync / plen;
-			upper_margin = 31;
-			lower_margin = 14;
-			vsync_len = interlace ? 3 : 4;
-		} else {
-			left_margin = var->left_margin;
-			right_margin = var->right_margin;
-			hsync_len = var->hsync_len;
-			upper_margin = var->upper_margin;
-			lower_margin = var->lower_margin;
-			vsync_len = var->vsync_len;
-			if (var->vmode & FB_VMODE_INTERLACED) {
-				upper_margin = (upper_margin + 1) / 2;
-				lower_margin = (lower_margin + 1) / 2;
-				vsync_len = (vsync_len + 1) / 2;
-			} else if (var->vmode & FB_VMODE_DOUBLE) {
-				upper_margin *= 2;
-				lower_margin *= 2;
-				vsync_len *= 2;
-			}
-		}
-	} else {			/* F_MON_VGA */
-		if (bpp == 16)
-			xstretch = 2;	/* Double pixel width only for hicolor */
-		/* Default values are used for vert./hor. timing if no pixelclock given. */
-		if (var->pixclock == 0) {
-			int linesize;
-
-			/* Choose master pixelclock depending on hor. timing */
-			plen = 1 * xstretch;
-			if ((plen * xres + f25.right + f25.hsync + f25.left) *
-			    fb_info.monspecs.hfmin < f25.f)
-				pclock = &f25;
-			else if ((plen * xres + f32.right + f32.hsync +
-				  f32.left) * fb_info.monspecs.hfmin < f32.f)
-				pclock = &f32;
-			else if ((plen * xres + fext.right + fext.hsync +
-				  fext.left) * fb_info.monspecs.hfmin < fext.f &&
-			         fext.f)
-				pclock = &fext;
-			else
-				return -EINVAL;
-
-			left_margin = pclock->left / plen;
-			right_margin = pclock->right / plen;
-			hsync_len = pclock->hsync / plen;
-			linesize = left_margin + xres + right_margin + hsync_len;
-			upper_margin = 31;
-			lower_margin = 11;
-			vsync_len = 3;
-		} else {
-			/* Choose largest pixelclock <= wanted clock */
-			int i;
-			unsigned long pcl = ULONG_MAX;
-			pclock = 0;
-			for (i = 1; i <= 4; i *= 2) {
-				if (f25.t * i >= var->pixclock &&
-				    f25.t * i < pcl) {
-					pcl = f25.t * i;
-					pclock = &f25;
-				}
-				if (f32.t * i >= var->pixclock &&
-				    f32.t * i < pcl) {
-					pcl = f32.t * i;
-					pclock = &f32;
-				}
-				if (fext.t && fext.t * i >= var->pixclock &&
-				    fext.t * i < pcl) {
-					pcl = fext.t * i;
-					pclock = &fext;
-				}
-			}
-			if (!pclock)
-				return -EINVAL;
-			plen = pcl / pclock->t;
-
-			left_margin = var->left_margin;
-			right_margin = var->right_margin;
-			hsync_len = var->hsync_len;
-			upper_margin = var->upper_margin;
-			lower_margin = var->lower_margin;
-			vsync_len = var->vsync_len;
-			/* Internal unit is [single lines per (half-)frame] */
-			if (var->vmode & FB_VMODE_INTERLACED) {
-				/* # lines in half frame */
-				/* External unit is [lines per full frame] */
-				upper_margin = (upper_margin + 1) / 2;
-				lower_margin = (lower_margin + 1) / 2;
-				vsync_len = (vsync_len + 1) / 2;
-			} else if (var->vmode & FB_VMODE_DOUBLE) {
-				/* External unit is [double lines per frame] */
-				upper_margin *= 2;
-				lower_margin *= 2;
-				vsync_len *= 2;
-			}
-		}
-		if (pclock == &fext)
-			longoffset = 1;	/* VIDEL doesn't synchronize on short offset */
-	}
-	/* Is video bus bandwidth (32MB/s) too low for this resolution? */
-	/* this is definitely wrong if bus clock != 32MHz */
-	if (pclock->f / plen / 8 * bpp > 32000000L)
-		return -EINVAL;
-
-	if (vsync_len < 1)
-		vsync_len = 1;
-
-	/* include sync lengths in right/lower margin for all calculations */
-	right_margin += hsync_len;
-	lower_margin += vsync_len;
-
-	/* ! In all calculations of margins we use # of lines in half frame
-	 * (which is a full frame in non-interlace mode), so we can switch
-	 * between interlace and non-interlace without messing around
-	 * with these.
-	 */
-again:
-	/* Set base_offset 128 and video bus width */
-	par->hw.falcon.vid_control = mon_type | f030_bus_width;
-	if (!longoffset)
-		par->hw.falcon.vid_control |= VCO_SHORTOFFS;	/* base_offset 64 */
-	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-		par->hw.falcon.vid_control |= VCO_HSYPOS;
-	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-		par->hw.falcon.vid_control |= VCO_VSYPOS;
-	/* Pixelclock */
-	par->hw.falcon.vid_control |= pclock->control_mask;
-	/* External or internal clock */
-	par->hw.falcon.sync = pclock->sync_mask | 0x2;
-	/* Pixellength and prescale */
-	par->hw.falcon.vid_mode = (2 / plen) << 2;
-	if (doubleline)
-		par->hw.falcon.vid_mode |= VMO_DOUBLE;
-	if (interlace)
-		par->hw.falcon.vid_mode |= VMO_INTER;
-
-	/*********************
-	 * Horizontal timing: unit = [master clock cycles]
-	 * unit of hxx-registers: [master clock cycles * prescale]
-	 * Hxx-registers are 9 bit wide
-	 *
-	 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
-	 *
-	 * graphic output = hdb & 0x200 ?
-	 *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
-	 *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
-	 * (this must be a multiple of plen*128/bpp, on VGA pixels
-	 *  to the right may be cut off with a bigger right margin)
-	 *
-	 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
-	 *        (hdb - hht - 2) * prescale + hdboff :
-	 *        hdb * prescale + hdboff
-	 *
-	 * end of graphics relative to start of 1st halfline =
-	 *        (hde + hht + 2) * prescale + hdeoff
-	 *********************/
-	/* Calculate VIDEL registers */
-{
-	prescale = hxx_prescale(&par->hw.falcon);
-	base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
-
-	/* Offsets depend on video mode */
-	/* Offsets are in clock cycles, divide by prescale to
-	 * calculate hd[be]-registers
-	 */
-	if (par->hw.falcon.f_shift & 0x100) {
-		align = 1;
-		hde_off = 0;
-		hdb_off = (base_off + 16 * plen) + prescale;
-	} else {
-		align = 128 / bpp;
-		hde_off = ((128 / bpp + 2) * plen);
-		if (par->hw.falcon.ste_mode)
-			hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
-		else
-			hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
-	}
-
-	gstart = (prescale / 2 + plen * left_margin) / prescale;
-	/* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
-	gend1 = gstart + roundup(xres, align) * plen / prescale;
-	/* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
-	gend2 = gstart + xres * plen / prescale;
-	par->HHT = plen * (left_margin + xres + right_margin) /
-			   (2 * prescale) - 2;
-/*	par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
-
-	par->HDB = gstart - hdb_off / prescale;
-	par->HBE = gstart;
-	if (par->HDB < 0)
-		par->HDB += par->HHT + 2 + 0x200;
-	par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
-	par->HBB = gend2 - par->HHT - 2;
-#if 0
-	/* One more Videl constraint: data fetch of two lines must not overlap */
-	if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
-		/* if this happens increase margins, decrease hfreq. */
-	}
-#endif
-	if (hde_off % prescale)
-		par->HBB++;		/* compensate for non matching hde and hbb */
-	par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
-	if (par->HSS < par->HBB)
-		par->HSS = par->HBB;
-}
-
-	/*  check hor. frequency */
-	hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
-	if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
-		/* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
-		/* Too high -> enlarge margin */
-		left_margin += 1;
-		right_margin += 1;
-		goto again;
-	}
-	if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
-		return -EINVAL;
-
-	/* Vxx-registers */
-	/* All Vxx must be odd in non-interlace, since frame starts in the middle
-	 * of the first displayed line!
-	 * One frame consists of VFT+1 half lines. VFT+1 must be even in
-	 * non-interlace, odd in interlace mode for synchronisation.
-	 * Vxx-registers are 11 bit wide
-	 */
-	par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
-	par->VDB = par->VBE;
-	par->VDE = yres;
-	if (!interlace)
-		par->VDE <<= 1;
-	if (doubleline)
-		par->VDE <<= 1;		/* VDE now half lines per (half-)frame */
-	par->VDE += par->VDB;
-	par->VBB = par->VDE;
-	par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
-	par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
-	/* vbb,vss,vft must be even in interlace mode */
-	if (interlace) {
-		par->VBB++;
-		par->VSS++;
-		par->VFT++;
-	}
-
-	/* V-frequency check, hope I didn't create any loop here. */
-	/* Interlace and doubleline are mutually exclusive. */
-	vfreq = (hfreq * 2) / (par->VFT + 1);
-	if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
-		/* Too high -> try again with doubleline */
-		doubleline = 1;
-		goto again;
-	} else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
-		/* Too low -> try again with interlace */
-		interlace = 1;
-		goto again;
-	} else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
-		/* Doubleline too low -> clear doubleline and enlarge margins */
-		int lines;
-		doubleline = 0;
-		for (lines = 0;
-		     (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
-		     fb_info.monspecs.vfmax;
-		     lines++)
-			;
-		upper_margin += lines;
-		lower_margin += lines;
-		goto again;
-	} else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
-		/* Doubleline too high -> enlarge margins */
-		int lines;
-		for (lines = 0;
-		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
-		     fb_info.monspecs.vfmax;
-		     lines += 2)
-			;
-		upper_margin += lines;
-		lower_margin += lines;
-		goto again;
-	} else if (vfreq > fb_info.monspecs.vfmax && interlace) {
-		/* Interlace, too high -> enlarge margins */
-		int lines;
-		for (lines = 0;
-		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
-		     fb_info.monspecs.vfmax;
-		     lines++)
-			;
-		upper_margin += lines;
-		lower_margin += lines;
-		goto again;
-	} else if (vfreq < fb_info.monspecs.vfmin ||
-		   vfreq > fb_info.monspecs.vfmax)
-		return -EINVAL;
-
-set_screen_base:
-	linelen = xres_virtual * bpp / 8;
-	if (yres_virtual * linelen > screen_len && screen_len)
-		return -EINVAL;
-	if (yres * linelen > screen_len && screen_len)
-		return -EINVAL;
-	if (var->yoffset + yres > yres_virtual && yres_virtual)
-		return -EINVAL;
-	par->yres_virtual = yres_virtual;
-	par->screen_base = screen_base + var->yoffset * linelen;
-	par->hw.falcon.xoffset = 0;
-
-	par->next_line = linelen;
-
-	return 0;
-}
-
-static int falcon_encode_var(struct fb_var_screeninfo *var,
-			     struct atafb_par *par)
-{
-/* !!! only for VGA !!! */
-	int linelen;
-	int prescale, plen;
-	int hdb_off, hde_off, base_off;
-	struct falcon_hw *hw = &par->hw.falcon;
-
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	/* possible frequencies: 25.175 or 32MHz */
-	var->pixclock = hw->sync & 0x1 ? fext.t :
-	                hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
-
-	var->height = -1;
-	var->width = -1;
-
-	var->sync = 0;
-	if (hw->vid_control & VCO_HSYPOS)
-		var->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (hw->vid_control & VCO_VSYPOS)
-		var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
-	var->vmode = FB_VMODE_NONINTERLACED;
-	if (hw->vid_mode & VMO_INTER)
-		var->vmode |= FB_VMODE_INTERLACED;
-	if (hw->vid_mode & VMO_DOUBLE)
-		var->vmode |= FB_VMODE_DOUBLE;
-
-	/* visible y resolution:
-	 * Graphics display starts at line VDB and ends at line
-	 * VDE. If interlace mode off unit of VC-registers is
-	 * half lines, else lines.
-	 */
-	var->yres = hw->vde - hw->vdb;
-	if (!(var->vmode & FB_VMODE_INTERLACED))
-		var->yres >>= 1;
-	if (var->vmode & FB_VMODE_DOUBLE)
-		var->yres >>= 1;
-
-	/*
-	 * to get bpp, we must examine f_shift and st_shift.
-	 * f_shift is valid if any of bits no. 10, 8 or 4
-	 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
-	 * if bit 10 set then bit 8 and bit 4 don't care...
-	 * If all these bits are 0 get display depth from st_shift
-	 * (as for ST and STE)
-	 */
-	if (hw->f_shift & 0x400)	/* 2 colors */
-		var->bits_per_pixel = 1;
-	else if (hw->f_shift & 0x100)	/* hicolor */
-		var->bits_per_pixel = 16;
-	else if (hw->f_shift & 0x010)	/* 8 bitplanes */
-		var->bits_per_pixel = 8;
-	else if (hw->st_shift == 0)
-		var->bits_per_pixel = 4;
-	else if (hw->st_shift == 0x100)
-		var->bits_per_pixel = 2;
-	else				/* if (hw->st_shift == 0x200) */
-		var->bits_per_pixel = 1;
-
-	var->xres = hw->line_width * 16 / var->bits_per_pixel;
-	var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
-	if (hw->xoffset)
-		var->xres_virtual += 16;
-
-	if (var->bits_per_pixel == 16) {
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->red.msb_right = 0;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->green.msb_right = 0;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->blue.msb_right = 0;
-	} else {
-		var->red.offset = 0;
-		var->red.length = hw->ste_mode ? 4 : 6;
-		if (var->red.length > var->bits_per_pixel)
-			var->red.length = var->bits_per_pixel;
-		var->red.msb_right = 0;
-		var->grayscale = 0;
-		var->blue = var->green = var->red;
-	}
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-
-	linelen = var->xres_virtual * var->bits_per_pixel / 8;
-	if (screen_len) {
-		if (par->yres_virtual)
-			var->yres_virtual = par->yres_virtual;
-		else
-			/* yres_virtual == 0 means use maximum */
-			var->yres_virtual = screen_len / linelen;
-	} else {
-		if (hwscroll < 0)
-			var->yres_virtual = 2 * var->yres;
-		else
-			var->yres_virtual = var->yres + hwscroll * 16;
-	}
-	var->xoffset = 0;		/* TODO change this */
-
-	/* hdX-offsets */
-	prescale = hxx_prescale(hw);
-	plen = 4 >> (hw->vid_mode >> 2 & 0x3);
-	base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
-	if (hw->f_shift & 0x100) {
-		hde_off = 0;
-		hdb_off = (base_off + 16 * plen) + prescale;
-	} else {
-		hde_off = ((128 / var->bits_per_pixel + 2) * plen);
-		if (hw->ste_mode)
-			hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
-					 + prescale;
-		else
-			hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
-					 + prescale;
-	}
-
-	/* Right margin includes hsync */
-	var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
-					   (hw->hdb & 0x200 ? 2 + hw->hht : 0));
-	if (hw->ste_mode || mon_type != F_MON_VGA)
-		var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
-	else
-		/* can't use this in ste_mode, because hbb is +1 off */
-		var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
-	var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
-
-	/* Lower margin includes vsync */
-	var->upper_margin = hw->vdb / 2;	/* round down to full lines */
-	var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;	/* round up */
-	var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;	/* round up */
-	if (var->vmode & FB_VMODE_INTERLACED) {
-		var->upper_margin *= 2;
-		var->lower_margin *= 2;
-		var->vsync_len *= 2;
-	} else if (var->vmode & FB_VMODE_DOUBLE) {
-		var->upper_margin = (var->upper_margin + 1) / 2;
-		var->lower_margin = (var->lower_margin + 1) / 2;
-		var->vsync_len = (var->vsync_len + 1) / 2;
-	}
-
-	var->pixclock *= plen;
-	var->left_margin /= plen;
-	var->right_margin /= plen;
-	var->hsync_len /= plen;
-
-	var->right_margin -= var->hsync_len;
-	var->lower_margin -= var->vsync_len;
-
-	if (screen_base)
-		var->yoffset = (par->screen_base - screen_base) / linelen;
-	else
-		var->yoffset = 0;
-	var->nonstd = 0;		/* what is this for? */
-	var->activate = 0;
-	return 0;
-}
-
-static int f_change_mode;
-static struct falcon_hw f_new_mode;
-static int f_pan_display;
-
-static void falcon_get_par(struct atafb_par *par)
-{
-	unsigned long addr;
-	struct falcon_hw *hw = &par->hw.falcon;
-
-	hw->line_width = shifter_f030.scn_width;
-	hw->line_offset = shifter_f030.off_next;
-	hw->st_shift = videl.st_shift & 0x300;
-	hw->f_shift = videl.f_shift;
-	hw->vid_control = videl.control;
-	hw->vid_mode = videl.mode;
-	hw->sync = shifter.syncmode & 0x1;
-	hw->xoffset = videl.xoffset & 0xf;
-	hw->hht = videl.hht;
-	hw->hbb = videl.hbb;
-	hw->hbe = videl.hbe;
-	hw->hdb = videl.hdb;
-	hw->hde = videl.hde;
-	hw->hss = videl.hss;
-	hw->vft = videl.vft;
-	hw->vbb = videl.vbb;
-	hw->vbe = videl.vbe;
-	hw->vdb = videl.vdb;
-	hw->vde = videl.vde;
-	hw->vss = videl.vss;
-
-	addr = (shifter.bas_hi & 0xff) << 16 |
-	       (shifter.bas_md & 0xff) << 8  |
-	       (shifter.bas_lo & 0xff);
-	par->screen_base = phys_to_virt(addr);
-
-	/* derived parameters */
-	hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
-	hw->mono = (hw->f_shift & 0x400) ||
-	           ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
-}
-
-static void falcon_set_par(struct atafb_par *par)
-{
-	f_change_mode = 0;
-
-	/* only set screen_base if really necessary */
-	if (current_par.screen_base != par->screen_base)
-		fbhw->set_screen_base(par->screen_base);
-
-	/* Don't touch any other registers if we keep the default resolution */
-	if (DontCalcRes)
-		return;
-
-	/* Tell vbl-handler to change video mode.
-	 * We change modes only on next VBL, to avoid desynchronisation
-	 * (a shift to the right and wrap around by a random number of pixels
-	 * in all monochrome modes).
-	 * This seems to work on my Falcon.
-	 */
-	f_new_mode = par->hw.falcon;
-	f_change_mode = 1;
-}
-
-static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
-{
-	struct falcon_hw *hw = &f_new_mode;
-
-	if (f_change_mode) {
-		f_change_mode = 0;
-
-		if (hw->sync & 0x1) {
-			/* Enable external pixelclock. This code only for ScreenWonder */
-			*(volatile unsigned short *)0xffff9202 = 0xffbf;
-		} else {
-			/* Turn off external clocks. Read sets all output bits to 1. */
-			*(volatile unsigned short *)0xffff9202;
-		}
-		shifter.syncmode = hw->sync;
-
-		videl.hht = hw->hht;
-		videl.hbb = hw->hbb;
-		videl.hbe = hw->hbe;
-		videl.hdb = hw->hdb;
-		videl.hde = hw->hde;
-		videl.hss = hw->hss;
-		videl.vft = hw->vft;
-		videl.vbb = hw->vbb;
-		videl.vbe = hw->vbe;
-		videl.vdb = hw->vdb;
-		videl.vde = hw->vde;
-		videl.vss = hw->vss;
-
-		videl.f_shift = 0;	/* write enables Falcon palette, 0: 4 planes */
-		if (hw->ste_mode) {
-			videl.st_shift = hw->st_shift;	/* write enables STE palette */
-		} else {
-			/* IMPORTANT:
-			 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
-			 * Writing 0 to f_shift enables 4 plane Falcon mode but
-			 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
-			 * with Falcon palette.
-			 */
-			videl.st_shift = 0;
-			/* now back to Falcon palette mode */
-			videl.f_shift = hw->f_shift;
-		}
-		/* writing to st_shift changed scn_width and vid_mode */
-		videl.xoffset = hw->xoffset;
-		shifter_f030.scn_width = hw->line_width;
-		shifter_f030.off_next = hw->line_offset;
-		videl.control = hw->vid_control;
-		videl.mode = hw->vid_mode;
-	}
-	if (f_pan_display) {
-		f_pan_display = 0;
-		videl.xoffset = current_par.hw.falcon.xoffset;
-		shifter_f030.off_next = current_par.hw.falcon.line_offset;
-	}
-	return IRQ_HANDLED;
-}
-
-static int falcon_pan_display(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct atafb_par *par = (struct atafb_par *)info->par;
-
-	int xoffset;
-	int bpp = info->var.bits_per_pixel;
-
-	if (bpp == 1)
-		var->xoffset = up(var->xoffset, 32);
-	if (bpp != 16)
-		par->hw.falcon.xoffset = var->xoffset & 15;
-	else {
-		par->hw.falcon.xoffset = 0;
-		var->xoffset = up(var->xoffset, 2);
-	}
-	par->hw.falcon.line_offset = bpp *
-		(info->var.xres_virtual - info->var.xres) / 16;
-	if (par->hw.falcon.xoffset)
-		par->hw.falcon.line_offset -= bpp;
-	xoffset = var->xoffset - par->hw.falcon.xoffset;
-
-	par->screen_base = screen_base +
-	        (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
-	if (fbhw->set_screen_base)
-		fbhw->set_screen_base(par->screen_base);
-	else
-		return -EINVAL;		/* shouldn't happen */
-	f_pan_display = 1;
-	return 0;
-}
-
-static int falcon_setcolreg(unsigned int regno, unsigned int red,
-			    unsigned int green, unsigned int blue,
-			    unsigned int transp, struct fb_info *info)
-{
-	if (regno > 255)
-		return 1;
-	f030_col[regno] = (((red & 0xfc00) << 16) |
-			   ((green & 0xfc00) << 8) |
-			   ((blue & 0xfc00) >> 8));
-	if (regno < 16) {
-		shifter_tt.color_reg[regno] =
-			(((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
-			(((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
-			((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
-		((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
-						       ((green & 0xfc00) >> 5) |
-						       ((blue & 0xf800) >> 11));
-	}
-	return 0;
-}
-
-static int falcon_blank(int blank_mode)
-{
-	/* ++guenther: we can switch off graphics by changing VDB and VDE,
-	 * so VIDEL doesn't hog the bus while saving.
-	 * (this may affect usleep()).
-	 */
-	int vdb, vss, hbe, hss;
-
-	if (mon_type == F_MON_SM)	/* this doesn't work on SM124 */
-		return 1;
-
-	vdb = current_par.VDB;
-	vss = current_par.VSS;
-	hbe = current_par.HBE;
-	hss = current_par.HSS;
-
-	if (blank_mode >= 1) {
-		/* disable graphics output (this speeds up the CPU) ... */
-		vdb = current_par.VFT + 1;
-		/* ... and blank all lines */
-		hbe = current_par.HHT + 2;
-	}
-	/* use VESA suspend modes on VGA monitors */
-	if (mon_type == F_MON_VGA) {
-		if (blank_mode == 2 || blank_mode == 4)
-			vss = current_par.VFT + 1;
-		if (blank_mode == 3 || blank_mode == 4)
-			hss = current_par.HHT + 2;
-	}
-
-	videl.vdb = vdb;
-	videl.vss = vss;
-	videl.hbe = hbe;
-	videl.hss = hss;
-
-	return 0;
-}
-
-static int falcon_detect(void)
-{
-	struct atafb_par par;
-	unsigned char fhw;
-
-	/* Determine connected monitor and set monitor parameters */
-	fhw = *(unsigned char *)0xffff8006;
-	mon_type = fhw >> 6 & 0x3;
-	/* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
-	f030_bus_width = fhw << 6 & 0x80;
-	switch (mon_type) {
-	case F_MON_SM:
-		fb_info.monspecs.vfmin = 70;
-		fb_info.monspecs.vfmax = 72;
-		fb_info.monspecs.hfmin = 35713;
-		fb_info.monspecs.hfmax = 35715;
-		break;
-	case F_MON_SC:
-	case F_MON_TV:
-		/* PAL...NTSC */
-		fb_info.monspecs.vfmin = 49;	/* not 50, since TOS defaults to 49.9x Hz */
-		fb_info.monspecs.vfmax = 60;
-		fb_info.monspecs.hfmin = 15620;
-		fb_info.monspecs.hfmax = 15755;
-		break;
-	}
-	/* initialize hsync-len */
-	f25.hsync = h_syncs[mon_type] / f25.t;
-	f32.hsync = h_syncs[mon_type] / f32.t;
-	if (fext.t)
-		fext.hsync = h_syncs[mon_type] / fext.t;
-
-	falcon_get_par(&par);
-	falcon_encode_var(&atafb_predefined[0], &par);
-
-	/* Detected mode is always the "autodetect" slot */
-	return 1;
-}
-
-#endif /* ATAFB_FALCON */
-
-/* ------------------- ST(E) specific functions ---------------------- */
-
-#ifdef ATAFB_STE
-
-static int stste_encode_fix(struct fb_fix_screeninfo *fix,
-			    struct atafb_par *par)
-{
-	int mode;
-
-	strcpy(fix->id, "Atari Builtin");
-	fix->smem_start = (unsigned long)real_screen_base;
-	fix->smem_len = screen_len;
-	fix->type = FB_TYPE_INTERLEAVED_PLANES;
-	fix->type_aux = 2;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	mode = par->hw.st.mode & 3;
-	if (mode == ST_HIGH) {
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->type_aux = 0;
-		fix->visual = FB_VISUAL_MONO10;
-	}
-	if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
-		fix->xpanstep = 16;
-		fix->ypanstep = 1;
-	} else {
-		fix->xpanstep = 0;
-		fix->ypanstep = 0;
-	}
-	fix->ywrapstep = 0;
-	fix->line_length = par->next_line;
-	fix->accel = FB_ACCEL_ATARIBLITT;
-	return 0;
-}
-
-static int stste_decode_var(struct fb_var_screeninfo *var,
-			    struct atafb_par *par)
-{
-	int xres = var->xres;
-	int yres = var->yres;
-	int bpp = var->bits_per_pixel;
-	int linelen;
-	int yres_virtual = var->yres_virtual;
-
-	if (mono_moni) {
-		if (bpp > 1 || xres > sttt_xres || yres > st_yres)
-			return -EINVAL;
-		par->hw.st.mode = ST_HIGH;
-		xres = sttt_xres;
-		yres = st_yres;
-		bpp = 1;
-	} else {
-		if (bpp > 4 || xres > sttt_xres || yres > st_yres)
-			return -EINVAL;
-		if (bpp > 2) {
-			if (xres > sttt_xres / 2 || yres > st_yres / 2)
-				return -EINVAL;
-			par->hw.st.mode = ST_LOW;
-			xres = sttt_xres / 2;
-			yres = st_yres / 2;
-			bpp = 4;
-		} else if (bpp > 1) {
-			if (xres > sttt_xres || yres > st_yres / 2)
-				return -EINVAL;
-			par->hw.st.mode = ST_MID;
-			xres = sttt_xres;
-			yres = st_yres / 2;
-			bpp = 2;
-		} else
-			return -EINVAL;
-	}
-	if (yres_virtual <= 0)
-		yres_virtual = 0;
-	else if (yres_virtual < yres)
-		yres_virtual = yres;
-	if (var->sync & FB_SYNC_EXT)
-		par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
-	else
-		par->hw.st.sync = (par->hw.st.sync & ~1);
-	linelen = xres * bpp / 8;
-	if (yres_virtual * linelen > screen_len && screen_len)
-		return -EINVAL;
-	if (yres * linelen > screen_len && screen_len)
-		return -EINVAL;
-	if (var->yoffset + yres > yres_virtual && yres_virtual)
-		return -EINVAL;
-	par->yres_virtual = yres_virtual;
-	par->screen_base = screen_base + var->yoffset * linelen;
-	par->next_line = linelen;
-	return 0;
-}
-
-static int stste_encode_var(struct fb_var_screeninfo *var,
-			    struct atafb_par *par)
-{
-	int linelen;
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->red.offset = 0;
-	var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
-	var->red.msb_right = 0;
-	var->grayscale = 0;
-
-	var->pixclock = 31041;
-	var->left_margin = 120;		/* these are incorrect */
-	var->right_margin = 100;
-	var->upper_margin = 8;
-	var->lower_margin = 16;
-	var->hsync_len = 140;
-	var->vsync_len = 30;
-
-	var->height = -1;
-	var->width = -1;
-
-	if (!(par->hw.st.sync & 1))
-		var->sync = 0;
-	else
-		var->sync = FB_SYNC_EXT;
-
-	switch (par->hw.st.mode & 3) {
-	case ST_LOW:
-		var->xres = sttt_xres / 2;
-		var->yres = st_yres / 2;
-		var->bits_per_pixel = 4;
-		break;
-	case ST_MID:
-		var->xres = sttt_xres;
-		var->yres = st_yres / 2;
-		var->bits_per_pixel = 2;
-		break;
-	case ST_HIGH:
-		var->xres = sttt_xres;
-		var->yres = st_yres;
-		var->bits_per_pixel = 1;
-		break;
-	}
-	var->blue = var->green = var->red;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-	var->xres_virtual = sttt_xres_virtual;
-	linelen = var->xres_virtual * var->bits_per_pixel / 8;
-	ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
-
-	if (!use_hwscroll)
-		var->yres_virtual = var->yres;
-	else if (screen_len) {
-		if (par->yres_virtual)
-			var->yres_virtual = par->yres_virtual;
-		else
-			/* yres_virtual == 0 means use maximum */
-			var->yres_virtual = screen_len / linelen;
-	} else {
-		if (hwscroll < 0)
-			var->yres_virtual = 2 * var->yres;
-		else
-			var->yres_virtual = var->yres + hwscroll * 16;
-	}
-	var->xoffset = 0;
-	if (screen_base)
-		var->yoffset = (par->screen_base - screen_base) / linelen;
-	else
-		var->yoffset = 0;
-	var->nonstd = 0;
-	var->activate = 0;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	return 0;
-}
-
-static void stste_get_par(struct atafb_par *par)
-{
-	unsigned long addr;
-	par->hw.st.mode = shifter_tt.st_shiftmode;
-	par->hw.st.sync = shifter.syncmode;
-	addr = ((shifter.bas_hi & 0xff) << 16) |
-	       ((shifter.bas_md & 0xff) << 8);
-	if (ATARIHW_PRESENT(EXTD_SHIFTER))
-		addr |= (shifter.bas_lo & 0xff);
-	par->screen_base = phys_to_virt(addr);
-}
-
-static void stste_set_par(struct atafb_par *par)
-{
-	shifter_tt.st_shiftmode = par->hw.st.mode;
-	shifter.syncmode = par->hw.st.sync;
-	/* only set screen_base if really necessary */
-	if (current_par.screen_base != par->screen_base)
-		fbhw->set_screen_base(par->screen_base);
-}
-
-static int stste_setcolreg(unsigned int regno, unsigned int red,
-			   unsigned int green, unsigned int blue,
-			   unsigned int transp, struct fb_info *info)
-{
-	if (regno > 15)
-		return 1;
-	red >>= 12;
-	blue >>= 12;
-	green >>= 12;
-	if (ATARIHW_PRESENT(EXTD_SHIFTER))
-		shifter_tt.color_reg[regno] =
-			(((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
-			(((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
-			((blue & 0xe) >> 1) | ((blue & 1) << 3);
-	else
-		shifter_tt.color_reg[regno] =
-			((red & 0xe) << 7) |
-			((green & 0xe) << 3) |
-			((blue & 0xe) >> 1);
-	return 0;
-}
-
-static int stste_detect(void)
-{
-	struct atafb_par par;
-
-	/* Determine the connected monitor: The DMA sound must be
-	 * disabled before reading the MFP GPIP, because the Sound
-	 * Done Signal and the Monochrome Detect are XORed together!
-	 */
-	if (ATARIHW_PRESENT(PCM_8BIT)) {
-		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-		udelay(20);		/* wait a while for things to settle down */
-	}
-	mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
-
-	stste_get_par(&par);
-	stste_encode_var(&atafb_predefined[0], &par);
-
-	if (!ATARIHW_PRESENT(EXTD_SHIFTER))
-		use_hwscroll = 0;
-	return 1;
-}
-
-static void stste_set_screen_base(void *s_base)
-{
-	unsigned long addr;
-	addr = virt_to_phys(s_base);
-	/* Setup Screen Memory */
-	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
-	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
-	if (ATARIHW_PRESENT(EXTD_SHIFTER))
-		shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
-}
-
-#endif /* ATAFB_STE */
-
-/* Switching the screen size should be done during vsync, otherwise
- * the margins may get messed up. This is a well known problem of
- * the ST's video system.
- *
- * Unfortunately there is hardly any way to find the vsync, as the
- * vertical blank interrupt is no longer in time on machines with
- * overscan type modifications.
- *
- * We can, however, use Timer B to safely detect the black shoulder,
- * but then we've got to guess an appropriate delay to find the vsync.
- * This might not work on every machine.
- *
- * martin_rogge @ ki.maus.de, 8th Aug 1995
- */
-
-#define LINE_DELAY  (mono_moni ? 30 : 70)
-#define SYNC_DELAY  (mono_moni ? 1500 : 2000)
-
-/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
-static void st_ovsc_switch(void)
-{
-	unsigned long flags;
-	register unsigned char old, new;
-
-	if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
-		return;
-	local_irq_save(flags);
-
-	st_mfp.tim_ct_b = 0x10;
-	st_mfp.active_edge |= 8;
-	st_mfp.tim_ct_b = 0;
-	st_mfp.tim_dt_b = 0xf0;
-	st_mfp.tim_ct_b = 8;
-	while (st_mfp.tim_dt_b > 1)	/* TOS does it this way, don't ask why */
-		;
-	new = st_mfp.tim_dt_b;
-	do {
-		udelay(LINE_DELAY);
-		old = new;
-		new = st_mfp.tim_dt_b;
-	} while (old != new);
-	st_mfp.tim_ct_b = 0x10;
-	udelay(SYNC_DELAY);
-
-	if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
-		acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
-	if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
-		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
-	if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
-		sound_ym.rd_data_reg_sel = 14;
-		sound_ym.wd_data = sound_ym.rd_data_reg_sel |
-				   ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
-				   ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
-	}
-	local_irq_restore(flags);
-}
-
-/* ------------------- External Video ---------------------- */
-
-#ifdef ATAFB_EXT
-
-static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
-{
-	strcpy(fix->id, "Unknown Extern");
-	fix->smem_start = (unsigned long)external_addr;
-	fix->smem_len = PAGE_ALIGN(external_len);
-	if (external_depth == 1) {
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		/* The letters 'n' and 'i' in the "atavideo=external:" stand
-		 * for "normal" and "inverted", rsp., in the monochrome case */
-		fix->visual =
-			(external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
-			 external_pmode == FB_TYPE_PACKED_PIXELS) ?
-				FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
-	} else {
-		/* Use STATIC if we don't know how to access color registers */
-		int visual = external_vgaiobase ?
-					 FB_VISUAL_PSEUDOCOLOR :
-					 FB_VISUAL_STATIC_PSEUDOCOLOR;
-		switch (external_pmode) {
-		case -1:		/* truecolor */
-			fix->type = FB_TYPE_PACKED_PIXELS;
-			fix->visual = FB_VISUAL_TRUECOLOR;
-			break;
-		case FB_TYPE_PACKED_PIXELS:
-			fix->type = FB_TYPE_PACKED_PIXELS;
-			fix->visual = visual;
-			break;
-		case FB_TYPE_PLANES:
-			fix->type = FB_TYPE_PLANES;
-			fix->visual = visual;
-			break;
-		case FB_TYPE_INTERLEAVED_PLANES:
-			fix->type = FB_TYPE_INTERLEAVED_PLANES;
-			fix->type_aux = 2;
-			fix->visual = visual;
-			break;
-		}
-	}
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-	fix->line_length = par->next_line;
-	return 0;
-}
-
-static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
-	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-
-	if (var->bits_per_pixel > myvar->bits_per_pixel ||
-	    var->xres > myvar->xres ||
-	    var->xres_virtual > myvar->xres_virtual ||
-	    var->yres > myvar->yres ||
-	    var->xoffset > 0 ||
-	    var->yoffset > 0)
-		return -EINVAL;
-
-	par->next_line = external_xres_virtual * external_depth / 8;
-	return 0;
-}
-
-static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->red.offset = 0;
-	var->red.length = (external_pmode == -1) ? external_depth / 3 :
-			(external_vgaiobase ? external_bitspercol : 0);
-	var->red.msb_right = 0;
-	var->grayscale = 0;
-
-	var->pixclock = 31041;
-	var->left_margin = 120;		/* these are surely incorrect */
-	var->right_margin = 100;
-	var->upper_margin = 8;
-	var->lower_margin = 16;
-	var->hsync_len = 140;
-	var->vsync_len = 30;
-
-	var->height = -1;
-	var->width = -1;
-
-	var->sync = 0;
-
-	var->xres = external_xres;
-	var->yres = external_yres;
-	var->xres_virtual = external_xres_virtual;
-	var->bits_per_pixel = external_depth;
-
-	var->blue = var->green = var->red;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-	var->yres_virtual = var->yres;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->nonstd = 0;
-	var->activate = 0;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	return 0;
-}
-
-static void ext_get_par(struct atafb_par *par)
-{
-	par->screen_base = external_addr;
-}
-
-static void ext_set_par(struct atafb_par *par)
-{
-}
-
-#define OUTB(port,val) \
-	*((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
-#define INB(port) \
-	(*((unsigned volatile char *) ((port)+external_vgaiobase)))
-#define DACDelay				\
-	do {					\
-		unsigned char tmp = INB(0x3da);	\
-		tmp = INB(0x3da);			\
-	} while (0)
-
-static int ext_setcolreg(unsigned int regno, unsigned int red,
-			 unsigned int green, unsigned int blue,
-			 unsigned int transp, struct fb_info *info)
-{
-	unsigned char colmask = (1 << external_bitspercol) - 1;
-
-	if (!external_vgaiobase)
-		return 1;
-
-	if (regno > 255)
-		return 1;
-
-	switch (external_card_type) {
-	case IS_VGA:
-		OUTB(0x3c8, regno);
-		DACDelay;
-		OUTB(0x3c9, red & colmask);
-		DACDelay;
-		OUTB(0x3c9, green & colmask);
-		DACDelay;
-		OUTB(0x3c9, blue & colmask);
-		DACDelay;
-		return 0;
-
-	case IS_MV300:
-		OUTB((MV300_reg[regno] << 2) + 1, red);
-		OUTB((MV300_reg[regno] << 2) + 1, green);
-		OUTB((MV300_reg[regno] << 2) + 1, blue);
-		return 0;
-
-	default:
-		return 1;
-	}
-}
-
-static int ext_detect(void)
-{
-	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-	struct atafb_par dummy_par;
-
-	myvar->xres = external_xres;
-	myvar->xres_virtual = external_xres_virtual;
-	myvar->yres = external_yres;
-	myvar->bits_per_pixel = external_depth;
-	ext_encode_var(myvar, &dummy_par);
-	return 1;
-}
-
-#endif /* ATAFB_EXT */
-
-/* ------ This is the same for most hardware types -------- */
-
-static void set_screen_base(void *s_base)
-{
-	unsigned long addr;
-
-	addr = virt_to_phys(s_base);
-	/* Setup Screen Memory */
-	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
-	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
-	shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
-}
-
-static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct atafb_par *par = (struct atafb_par *)info->par;
-
-	if (!fbhw->set_screen_base ||
-	    (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
-		return -EINVAL;
-	var->xoffset = up(var->xoffset, 16);
-	par->screen_base = screen_base +
-	        (var->yoffset * info->var.xres_virtual + var->xoffset)
-	        * info->var.bits_per_pixel / 8;
-	fbhw->set_screen_base(par->screen_base);
-	return 0;
-}
-
-/* ------------ Interfaces to hardware functions ------------ */
-
-#ifdef ATAFB_TT
-static struct fb_hwswitch tt_switch = {
-	.detect		= tt_detect,
-	.encode_fix	= tt_encode_fix,
-	.decode_var	= tt_decode_var,
-	.encode_var	= tt_encode_var,
-	.get_par	= tt_get_par,
-	.set_par	= tt_set_par,
-	.set_screen_base = set_screen_base,
-	.pan_display	= pan_display,
-};
-#endif
-
-#ifdef ATAFB_FALCON
-static struct fb_hwswitch falcon_switch = {
-	.detect		= falcon_detect,
-	.encode_fix	= falcon_encode_fix,
-	.decode_var	= falcon_decode_var,
-	.encode_var	= falcon_encode_var,
-	.get_par	= falcon_get_par,
-	.set_par	= falcon_set_par,
-	.set_screen_base = set_screen_base,
-	.blank		= falcon_blank,
-	.pan_display	= falcon_pan_display,
-};
-#endif
-
-#ifdef ATAFB_STE
-static struct fb_hwswitch st_switch = {
-	.detect		= stste_detect,
-	.encode_fix	= stste_encode_fix,
-	.decode_var	= stste_decode_var,
-	.encode_var	= stste_encode_var,
-	.get_par	= stste_get_par,
-	.set_par	= stste_set_par,
-	.set_screen_base = stste_set_screen_base,
-	.pan_display	= pan_display
-};
-#endif
-
-#ifdef ATAFB_EXT
-static struct fb_hwswitch ext_switch = {
-	.detect		= ext_detect,
-	.encode_fix	= ext_encode_fix,
-	.decode_var	= ext_decode_var,
-	.encode_var	= ext_encode_var,
-	.get_par	= ext_get_par,
-	.set_par	= ext_set_par,
-};
-#endif
-
-static void ata_get_par(struct atafb_par *par)
-{
-	if (current_par_valid)
-		*par = current_par;
-	else
-		fbhw->get_par(par);
-}
-
-static void ata_set_par(struct atafb_par *par)
-{
-	fbhw->set_par(par);
-	current_par = *par;
-	current_par_valid = 1;
-}
-
-
-/* =========================================================== */
-/* ============== Hardware Independent Functions ============= */
-/* =========================================================== */
-
-/* used for hardware scrolling */
-
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
-	int err, activate;
-	struct atafb_par par;
-
-	err = fbhw->decode_var(var, &par);
-	if (err)
-		return err;
-	activate = var->activate;
-	if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
-		ata_set_par(&par);
-	fbhw->encode_var(var, &par);
-	var->activate = activate;
-	return 0;
-}
-
-/* fbhw->encode_fix() must be called with fb_info->mm_lock held
- * if it is called after the register_framebuffer() - not a case here
- */
-static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
-{
-	struct atafb_par par;
-	int err;
-	// Get fix directly (case con == -1 before)??
-	err = fbhw->decode_var(&info->var, &par);
-	if (err)
-		return err;
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	err = fbhw->encode_fix(fix, &par);
-	return err;
-}
-
-static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct atafb_par par;
-
-	ata_get_par(&par);
-	fbhw->encode_var(var, &par);
-
-	return 0;
-}
-
-// No longer called by fbcon!
-// Still called by set_var internally
-
-static void atafb_set_disp(struct fb_info *info)
-{
-	atafb_get_var(&info->var, info);
-	atafb_get_fix(&info->fix, info);
-
-	info->screen_base = (void *)info->fix.smem_start;
-}
-
-static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
-}
-
-static int
-atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int xoffset = var->xoffset;
-	int yoffset = var->yoffset;
-	int err;
-
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
-			return -EINVAL;
-	} else {
-		if (xoffset + info->var.xres > info->var.xres_virtual ||
-		    yoffset + info->var.yres > info->var.yres_virtual)
-			return -EINVAL;
-	}
-
-	if (fbhw->pan_display) {
-		err = fbhw->pan_display(var, info);
-		if (err)
-			return err;
-	} else
-		return -EINVAL;
-
-	info->var.xoffset = xoffset;
-	info->var.yoffset = yoffset;
-
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-
-	return 0;
-}
-
-/*
- * generic drawing routines; imageblit needs updating for image depth > 1
- */
-
-#if BITS_PER_LONG == 32
-#define BYTES_PER_LONG	4
-#define SHIFT_PER_LONG	5
-#elif BITS_PER_LONG == 64
-#define BYTES_PER_LONG	8
-#define SHIFT_PER_LONG	6
-#else
-#define Please update me
-#endif
-
-
-static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct atafb_par *par = (struct atafb_par *)info->par;
-	int x2, y2;
-	u32 width, height;
-
-	if (!rect->width || !rect->height)
-		return;
-
-#ifdef ATAFB_FALCON
-	if (info->var.bits_per_pixel == 16) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-#endif
-
-	/*
-	 * We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly.
-	 * */
-	x2 = rect->dx + rect->width;
-	y2 = rect->dy + rect->height;
-	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
-	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	width = x2 - rect->dx;
-	height = y2 - rect->dy;
-
-	if (info->var.bits_per_pixel == 1)
-		atafb_mfb_fillrect(info, par->next_line, rect->color,
-				   rect->dy, rect->dx, height, width);
-	else if (info->var.bits_per_pixel == 2)
-		atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
-					rect->dy, rect->dx, height, width);
-	else if (info->var.bits_per_pixel == 4)
-		atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
-					rect->dy, rect->dx, height, width);
-	else
-		atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
-					rect->dy, rect->dx, height, width);
-
-	return;
-}
-
-static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct atafb_par *par = (struct atafb_par *)info->par;
-	int x2, y2;
-	u32 dx, dy, sx, sy, width, height;
-	int rev_copy = 0;
-
-#ifdef ATAFB_FALCON
-	if (info->var.bits_per_pixel == 16) {
-		cfb_copyarea(info, area);
-		return;
-	}
-#endif
-
-	/* clip the destination */
-	x2 = area->dx + area->width;
-	y2 = area->dy + area->height;
-	dx = area->dx > 0 ? area->dx : 0;
-	dy = area->dy > 0 ? area->dy : 0;
-	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
-	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	width = x2 - dx;
-	height = y2 - dy;
-
-	if (area->sx + dx < area->dx || area->sy + dy < area->dy)
-		return;
-
-	/* update sx,sy */
-	sx = area->sx + (dx - area->dx);
-	sy = area->sy + (dy - area->dy);
-
-	/* the source must be completely inside the virtual screen */
-	if (sx + width > info->var.xres_virtual ||
-			sy + height > info->var.yres_virtual)
-		return;
-
-	if (dy > sy || (dy == sy && dx > sx)) {
-		dy += height;
-		sy += height;
-		rev_copy = 1;
-	}
-
-	if (info->var.bits_per_pixel == 1)
-		atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
-	else if (info->var.bits_per_pixel == 2)
-		atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
-	else if (info->var.bits_per_pixel == 4)
-		atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
-	else
-		atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
-
-	return;
-}
-
-static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct atafb_par *par = (struct atafb_par *)info->par;
-	int x2, y2;
-	unsigned long *dst;
-	int dst_idx;
-	const char *src;
-	u32 dx, dy, width, height, pitch;
-
-#ifdef ATAFB_FALCON
-	if (info->var.bits_per_pixel == 16) {
-		cfb_imageblit(info, image);
-		return;
-	}
-#endif
-
-	/*
-	 * We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly like we are
-	 * doing here.
-	 */
-	x2 = image->dx + image->width;
-	y2 = image->dy + image->height;
-	dx = image->dx;
-	dy = image->dy;
-	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
-	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	width = x2 - dx;
-	height = y2 - dy;
-
-	if (image->depth == 1) {
-		// used for font data
-		dst = (unsigned long *)
-			((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
-		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
-		dst_idx += dy * par->next_line * 8 + dx;
-		src = image->data;
-		pitch = (image->width + 7) / 8;
-		while (height--) {
-
-			if (info->var.bits_per_pixel == 1)
-				atafb_mfb_linefill(info, par->next_line,
-						   dy, dx, width, src,
-						   image->bg_color, image->fg_color);
-			else if (info->var.bits_per_pixel == 2)
-				atafb_iplan2p2_linefill(info, par->next_line,
-							dy, dx, width, src,
-							image->bg_color, image->fg_color);
-			else if (info->var.bits_per_pixel == 4)
-				atafb_iplan2p4_linefill(info, par->next_line,
-							dy, dx, width, src,
-							image->bg_color, image->fg_color);
-			else
-				atafb_iplan2p8_linefill(info, par->next_line,
-							dy, dx, width, src,
-							image->bg_color, image->fg_color);
-			dy++;
-			src += pitch;
-		}
-	} else {
-		c2p_iplan2(info->screen_base, image->data, dx, dy, width,
-			   height, par->next_line, image->width,
-			   info->var.bits_per_pixel);
-	}
-}
-
-static int
-atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-#ifdef FBCMD_GET_CURRENTPAR
-	case FBCMD_GET_CURRENTPAR:
-		if (copy_to_user((void *)arg, (void *)&current_par,
-				 sizeof(struct atafb_par)))
-			return -EFAULT;
-		return 0;
-#endif
-#ifdef FBCMD_SET_CURRENTPAR
-	case FBCMD_SET_CURRENTPAR:
-		if (copy_from_user((void *)&current_par, (void *)arg,
-				   sizeof(struct atafb_par)))
-			return -EFAULT;
-		ata_set_par(&current_par);
-		return 0;
-#endif
-	}
-	return -EINVAL;
-}
-
-/* (un)blank/poweroff
- * 0 = unblank
- * 1 = blank
- * 2 = suspend vsync
- * 3 = suspend hsync
- * 4 = off
- */
-static int atafb_blank(int blank, struct fb_info *info)
-{
-	unsigned short black[16];
-	struct fb_cmap cmap;
-	if (fbhw->blank && !fbhw->blank(blank))
-		return 1;
-	if (blank) {
-		memset(black, 0, 16 * sizeof(unsigned short));
-		cmap.red = black;
-		cmap.green = black;
-		cmap.blue = black;
-		cmap.transp = NULL;
-		cmap.start = 0;
-		cmap.len = 16;
-		fb_set_cmap(&cmap, info);
-	}
-#if 0
-	else
-		do_install_cmap(info);
-#endif
-	return 0;
-}
-
-	/*
-	 * New fbcon interface ...
-	 */
-
-	 /* check var by decoding var into hw par, rounding if necessary,
-	  * then encoding hw par back into new, validated var */
-static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int err;
-	struct atafb_par par;
-
-	/* Validate wanted screen parameters */
-	// if ((err = ata_decode_var(var, &par)))
-	err = fbhw->decode_var(var, &par);
-	if (err)
-		return err;
-
-	/* Encode (possibly rounded) screen parameters */
-	fbhw->encode_var(var, &par);
-	return 0;
-}
-
-	/* actually set hw par by decoding var, then setting hardware from
-	 * hw par just decoded */
-static int atafb_set_par(struct fb_info *info)
-{
-	struct atafb_par *par = (struct atafb_par *)info->par;
-
-	/* Decode wanted screen parameters */
-	fbhw->decode_var(&info->var, par);
-	mutex_lock(&info->mm_lock);
-	fbhw->encode_fix(&info->fix, par);
-	mutex_unlock(&info->mm_lock);
-
-	/* Set new videomode */
-	ata_set_par(par);
-
-	return 0;
-}
-
-
-static struct fb_ops atafb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_check_var	= atafb_check_var,
-	.fb_set_par	= atafb_set_par,
-	.fb_setcolreg	= atafb_setcolreg,
-	.fb_blank =	atafb_blank,
-	.fb_pan_display	= atafb_pan_display,
-	.fb_fillrect	= atafb_fillrect,
-	.fb_copyarea	= atafb_copyarea,
-	.fb_imageblit	= atafb_imageblit,
-	.fb_ioctl =	atafb_ioctl,
-};
-
-static void check_default_par(int detected_mode)
-{
-	char default_name[10];
-	int i;
-	struct fb_var_screeninfo var;
-	unsigned long min_mem;
-
-	/* First try the user supplied mode */
-	if (default_par) {
-		var = atafb_predefined[default_par - 1];
-		var.activate = FB_ACTIVATE_TEST;
-		if (do_fb_set_var(&var, 1))
-			default_par = 0;	/* failed */
-	}
-	/* Next is the autodetected one */
-	if (!default_par) {
-		var = atafb_predefined[detected_mode - 1]; /* autodetect */
-		var.activate = FB_ACTIVATE_TEST;
-		if (!do_fb_set_var(&var, 1))
-			default_par = detected_mode;
-	}
-	/* If that also failed, try some default modes... */
-	if (!default_par) {
-		/* try default1, default2... */
-		for (i = 1; i < 10; i++) {
-			sprintf(default_name,"default%d", i);
-			default_par = get_video_mode(default_name);
-			if (!default_par)
-				panic("can't set default video mode");
-			var = atafb_predefined[default_par - 1];
-			var.activate = FB_ACTIVATE_TEST;
-			if (!do_fb_set_var(&var,1))
-				break;	/* ok */
-		}
-	}
-	min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
-	if (default_mem_req < min_mem)
-		default_mem_req = min_mem;
-}
-
-#ifdef ATAFB_EXT
-static void __init atafb_setup_ext(char *spec)
-{
-	int xres, xres_virtual, yres, depth, planes;
-	unsigned long addr, len;
-	char *p;
-
-	/* Format is: <xres>;<yres>;<depth>;<plane organ.>;
-	 *            <screen mem addr>
-	 *	      [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
-	 *	      [;<xres-virtual>]]]]]
-	 *
-	 * 09/23/97	Juergen
-	 * <xres_virtual>:	hardware's x-resolution (f.e. ProMST)
-	 *
-	 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
-	 */
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		return;
-	xres_virtual = xres = simple_strtoul(p, NULL, 10);
-	if (xres <= 0)
-		return;
-
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		return;
-	yres = simple_strtoul(p, NULL, 10);
-	if (yres <= 0)
-		return;
-
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		return;
-	depth = simple_strtoul(p, NULL, 10);
-	if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
-	    depth != 16 && depth != 24)
-		return;
-
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		return;
-	if (*p == 'i')
-		planes = FB_TYPE_INTERLEAVED_PLANES;
-	else if (*p == 'p')
-		planes = FB_TYPE_PACKED_PIXELS;
-	else if (*p == 'n')
-		planes = FB_TYPE_PLANES;
-	else if (*p == 't')
-		planes = -1;		/* true color */
-	else
-		return;
-
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		return;
-	addr = simple_strtoul(p, NULL, 0);
-
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		len = xres * yres * depth / 8;
-	else
-		len = simple_strtoul(p, NULL, 0);
-
-	p = strsep(&spec, ";");
-	if (p && *p)
-		external_vgaiobase = simple_strtoul(p, NULL, 0);
-
-	p = strsep(&spec, ";");
-	if (p && *p) {
-		external_bitspercol = simple_strtoul(p, NULL, 0);
-		if (external_bitspercol > 8)
-			external_bitspercol = 8;
-		else if (external_bitspercol < 1)
-			external_bitspercol = 1;
-	}
-
-	p = strsep(&spec, ";");
-	if (p && *p) {
-		if (!strcmp(p, "vga"))
-			external_card_type = IS_VGA;
-		if (!strcmp(p, "mv300"))
-			external_card_type = IS_MV300;
-	}
-
-	p = strsep(&spec, ";");
-	if (p && *p) {
-		xres_virtual = simple_strtoul(p, NULL, 10);
-		if (xres_virtual < xres)
-			xres_virtual = xres;
-		if (xres_virtual * yres * depth / 8 > len)
-			len = xres_virtual * yres * depth / 8;
-	}
-
-	external_xres = xres;
-	external_xres_virtual = xres_virtual;
-	external_yres = yres;
-	external_depth = depth;
-	external_pmode = planes;
-	external_addr = (void *)addr;
-	external_len = len;
-
-	if (external_card_type == IS_MV300) {
-		switch (external_depth) {
-		case 1:
-			MV300_reg = MV300_reg_1bit;
-			break;
-		case 4:
-			MV300_reg = MV300_reg_4bit;
-			break;
-		case 8:
-			MV300_reg = MV300_reg_8bit;
-			break;
-		}
-	}
-}
-#endif /* ATAFB_EXT */
-
-static void __init atafb_setup_int(char *spec)
-{
-	/* Format to config extended internal video hardware like OverScan:
-	 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
-	 * Explanation:
-	 * <xres>: x-resolution
-	 * <yres>: y-resolution
-	 * The following are only needed if you have an overscan which
-	 * needs a black border:
-	 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
-	 * <yres_max>: max. number of lines your OverScan hardware would allow
-	 * <offset>: Offset from physical beginning to visible beginning
-	 *	  of screen in bytes
-	 */
-	int xres;
-	char *p;
-
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	xres = simple_strtoul(p, NULL, 10);
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	sttt_xres = xres;
-	tt_yres = st_yres = simple_strtoul(p, NULL, 10);
-	if ((p = strsep(&spec, ";")) && *p)
-		sttt_xres_virtual = simple_strtoul(p, NULL, 10);
-	if ((p = strsep(&spec, ";")) && *p)
-		sttt_yres_virtual = simple_strtoul(p, NULL, 0);
-	if ((p = strsep(&spec, ";")) && *p)
-		ovsc_offset = simple_strtoul(p, NULL, 0);
-
-	if (ovsc_offset || (sttt_yres_virtual != st_yres))
-		use_hwscroll = 0;
-}
-
-#ifdef ATAFB_FALCON
-static void __init atafb_setup_mcap(char *spec)
-{
-	char *p;
-	int vmin, vmax, hmin, hmax;
-
-	/* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
-	 * <V*> vertical freq. in Hz
-	 * <H*> horizontal freq. in kHz
-	 */
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	vmin = simple_strtoul(p, NULL, 10);
-	if (vmin <= 0)
-		return;
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	vmax = simple_strtoul(p, NULL, 10);
-	if (vmax <= 0 || vmax <= vmin)
-		return;
-	if (!(p = strsep(&spec, ";")) || !*p)
-		return;
-	hmin = 1000 * simple_strtoul(p, NULL, 10);
-	if (hmin <= 0)
-		return;
-	if (!(p = strsep(&spec, "")) || !*p)
-		return;
-	hmax = 1000 * simple_strtoul(p, NULL, 10);
-	if (hmax <= 0 || hmax <= hmin)
-		return;
-
-	fb_info.monspecs.vfmin = vmin;
-	fb_info.monspecs.vfmax = vmax;
-	fb_info.monspecs.hfmin = hmin;
-	fb_info.monspecs.hfmax = hmax;
-}
-#endif /* ATAFB_FALCON */
-
-static void __init atafb_setup_user(char *spec)
-{
-	/* Format of user defined video mode is: <xres>;<yres>;<depth>
-	 */
-	char *p;
-	int xres, yres, depth, temp;
-
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		return;
-	xres = simple_strtoul(p, NULL, 10);
-	p = strsep(&spec, ";");
-	if (!p || !*p)
-		return;
-	yres = simple_strtoul(p, NULL, 10);
-	p = strsep(&spec, "");
-	if (!p || !*p)
-		return;
-	depth = simple_strtoul(p, NULL, 10);
-	temp = get_video_mode("user0");
-	if (temp) {
-		default_par = temp;
-		atafb_predefined[default_par - 1].xres = xres;
-		atafb_predefined[default_par - 1].yres = yres;
-		atafb_predefined[default_par - 1].bits_per_pixel = depth;
-	}
-}
-
-int __init atafb_setup(char *options)
-{
-	char *this_opt;
-	int temp;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if ((temp = get_video_mode(this_opt))) {
-			default_par = temp;
-			mode_option = this_opt;
-		} else if (!strcmp(this_opt, "inverse"))
-			inverse = 1;
-		else if (!strncmp(this_opt, "hwscroll_", 9)) {
-			hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
-			if (hwscroll < 0)
-				hwscroll = 0;
-			if (hwscroll > 200)
-				hwscroll = 200;
-		}
-#ifdef ATAFB_EXT
-		else if (!strcmp(this_opt, "mv300")) {
-			external_bitspercol = 8;
-			external_card_type = IS_MV300;
-		} else if (!strncmp(this_opt, "external:", 9))
-			atafb_setup_ext(this_opt + 9);
-#endif
-		else if (!strncmp(this_opt, "internal:", 9))
-			atafb_setup_int(this_opt + 9);
-#ifdef ATAFB_FALCON
-		else if (!strncmp(this_opt, "eclock:", 7)) {
-			fext.f = simple_strtoul(this_opt + 7, NULL, 10);
-			/* external pixelclock in kHz --> ps */
-			fext.t = 1000000000 / fext.f;
-			fext.f *= 1000;
-		} else if (!strncmp(this_opt, "monitorcap:", 11))
-			atafb_setup_mcap(this_opt + 11);
-#endif
-		else if (!strcmp(this_opt, "keep"))
-			DontCalcRes = 1;
-		else if (!strncmp(this_opt, "R", 1))
-			atafb_setup_user(this_opt + 1);
-	}
-	return 0;
-}
-
-int __init atafb_init(void)
-{
-	int pad, detected_mode, error;
-	unsigned int defmode = 0;
-	unsigned long mem_req;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("atafb", &option))
-		return -ENODEV;
-	atafb_setup(option);
-#endif
-	printk("atafb_init: start\n");
-
-	if (!MACH_IS_ATARI)
-		return -ENODEV;
-
-	do {
-#ifdef ATAFB_EXT
-		if (external_addr) {
-			printk("atafb_init: initializing external hw\n");
-			fbhw = &ext_switch;
-			atafb_ops.fb_setcolreg = &ext_setcolreg;
-			defmode = DEFMODE_EXT;
-			break;
-		}
-#endif
-#ifdef ATAFB_TT
-		if (ATARIHW_PRESENT(TT_SHIFTER)) {
-			printk("atafb_init: initializing TT hw\n");
-			fbhw = &tt_switch;
-			atafb_ops.fb_setcolreg = &tt_setcolreg;
-			defmode = DEFMODE_TT;
-			break;
-		}
-#endif
-#ifdef ATAFB_FALCON
-		if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
-			printk("atafb_init: initializing Falcon hw\n");
-			fbhw = &falcon_switch;
-			atafb_ops.fb_setcolreg = &falcon_setcolreg;
-			error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher,
-					    IRQ_TYPE_PRIO,
-					    "framebuffer:modeswitch",
-					    falcon_vbl_switcher);
-			if (error)
-				return error;
-			defmode = DEFMODE_F30;
-			break;
-		}
-#endif
-#ifdef ATAFB_STE
-		if (ATARIHW_PRESENT(STND_SHIFTER) ||
-		    ATARIHW_PRESENT(EXTD_SHIFTER)) {
-			printk("atafb_init: initializing ST/E hw\n");
-			fbhw = &st_switch;
-			atafb_ops.fb_setcolreg = &stste_setcolreg;
-			defmode = DEFMODE_STE;
-			break;
-		}
-		fbhw = &st_switch;
-		atafb_ops.fb_setcolreg = &stste_setcolreg;
-		printk("Cannot determine video hardware; defaulting to ST(e)\n");
-#else /* ATAFB_STE */
-		/* no default driver included */
-		/* Nobody will ever see this message :-) */
-		panic("Cannot initialize video hardware");
-#endif
-	} while (0);
-
-	/* Multisync monitor capabilities */
-	/* Atari-TOS defaults if no boot option present */
-	if (fb_info.monspecs.hfmin == 0) {
-		fb_info.monspecs.hfmin = 31000;
-		fb_info.monspecs.hfmax = 32000;
-		fb_info.monspecs.vfmin = 58;
-		fb_info.monspecs.vfmax = 62;
-	}
-
-	detected_mode = fbhw->detect();
-	check_default_par(detected_mode);
-#ifdef ATAFB_EXT
-	if (!external_addr) {
-#endif /* ATAFB_EXT */
-		mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
-		mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
-		screen_base = atari_stram_alloc(mem_req, "atafb");
-		if (!screen_base)
-			panic("Cannot allocate screen memory");
-		memset(screen_base, 0, mem_req);
-		pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
-		screen_base += pad;
-		real_screen_base = screen_base + ovsc_offset;
-		screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
-		st_ovsc_switch();
-		if (CPU_IS_040_OR_060) {
-			/* On a '040+, the cache mode of video RAM must be set to
-			 * write-through also for internal video hardware! */
-			cache_push(virt_to_phys(screen_base), screen_len);
-			kernel_set_cachemode(screen_base, screen_len,
-					     IOMAP_WRITETHROUGH);
-		}
-		printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
-			screen_base, real_screen_base, screen_len);
-#ifdef ATAFB_EXT
-	} else {
-		/* Map the video memory (physical address given) to somewhere
-		 * in the kernel address space.
-		 */
-		external_addr = ioremap_writethrough((unsigned long)external_addr,
-						     external_len);
-		if (external_vgaiobase)
-			external_vgaiobase =
-			  (unsigned long)ioremap(external_vgaiobase, 0x10000);
-		screen_base =
-		real_screen_base = external_addr;
-		screen_len = external_len & PAGE_MASK;
-		memset (screen_base, 0, external_len);
-	}
-#endif /* ATAFB_EXT */
-
-//	strcpy(fb_info.mode->name, "Atari Builtin ");
-	fb_info.fbops = &atafb_ops;
-	// try to set default (detected; requested) var
-	do_fb_set_var(&atafb_predefined[default_par - 1], 1);
-	// reads hw state into current par, which may not be sane yet
-	ata_get_par(&current_par);
-	fb_info.par = &current_par;
-	// tries to read from HW which may not be initialized yet
-	// so set sane var first, then call atafb_set_par
-	atafb_get_var(&fb_info.var, &fb_info);
-
-#ifdef ATAFB_FALCON
-	fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
-#endif
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
-
-	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
-			  NUM_TOTAL_MODES, &atafb_modedb[defmode],
-			  fb_info.var.bits_per_pixel)) {
-		return -EINVAL;
-	}
-
-	fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
-				 &fb_info.modelist);
-
-	atafb_set_disp(&fb_info);
-
-	fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
-
-
-	printk("Determined %dx%d, depth %d\n",
-	       fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
-	if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
-	    (fb_info.var.yres != fb_info.var.yres_virtual))
-		printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
-		       fb_info.var.yres_virtual);
-
-	if (register_framebuffer(&fb_info) < 0) {
-#ifdef ATAFB_EXT
-		if (external_addr) {
-			iounmap(external_addr);
-			external_addr = NULL;
-		}
-		if (external_vgaiobase) {
-			iounmap((void*)external_vgaiobase);
-			external_vgaiobase = 0;
-		}
-#endif
-		return -EINVAL;
-	}
-
-	fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
-		screen_len >> 10);
-
-	/* TODO: This driver cannot be unloaded yet */
-	return 0;
-}
-
-module_init(atafb_init);
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int cleanup_module(void)
-{
-	unregister_framebuffer(&fb_info);
-	return atafb_deinit();
-}
-#endif /* MODULE */
diff --git a/drivers/video/atafb.h b/drivers/video/atafb.h
deleted file mode 100644
index 014e05906cb1..000000000000
--- a/drivers/video/atafb.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _VIDEO_ATAFB_H
-#define _VIDEO_ATAFB_H
-
-void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
-			int dx, int height, int width);
-void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
-			int sy, int sx, int height, int width);
-void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
-			int dy, int dx, u32 width,
-			const u8 *data, u32 bgcolor, u32 fgcolor);
-
-void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
-			     int dx, int height, int width);
-void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
-			     int sy, int sx, int height, int width);
-void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
-			     int dy, int dx, u32 width,
-			     const u8 *data, u32 bgcolor, u32 fgcolor);
-
-void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
-			     int dx, int height, int width);
-void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
-			     int sy, int sx, int height, int width);
-void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
-			     int dy, int dx, u32 width,
-			     const u8 *data, u32 bgcolor, u32 fgcolor);
-
-void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
-			     int dx, int height, int width);
-void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
-			     int sy, int sx, int height, int width);
-void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
-			     int dy, int dx, u32 width,
-			     const u8 *data, u32 bgcolor, u32 fgcolor);
-
-#endif /* _VIDEO_ATAFB_H */
diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/atafb_iplan2p2.c
deleted file mode 100644
index 8cc9c50379d0..000000000000
--- a/drivers/video/atafb_iplan2p2.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- *  linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for
- *				      interleaved bitplanes à la Atari (2
- *				      planes, 2 bytes interleave)
- *
- *	Created 5 Apr 1997 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include <asm/setup.h>
-
-#include "atafb.h"
-
-#define BPL	2
-#include "atafb_utils.h"
-
-void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line,
-			     int sy, int sx, int dy, int dx,
-			     int height, int width)
-{
-	/*  bmove() has to distinguish two major cases: If both, source and
-	 *  destination, start at even addresses or both are at odd
-	 *  addresses, just the first odd and last even column (if present)
-	 *  require special treatment (memmove_col()). The rest between
-	 *  then can be copied by normal operations, because all adjacent
-	 *  bytes are affected and are to be stored in the same order.
-	 *    The pathological case is when the move should go from an odd
-	 *  address to an even or vice versa. Since the bytes in the plane
-	 *  words must be assembled in new order, it seems wisest to make
-	 *  all movements by memmove_col().
-	 */
-
-	u8 *src, *dst;
-	u32 *s, *d;
-	int w, l , i, j;
-	u_int colsize;
-	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
-
-	colsize = height;
-	if (!((sx ^ dx) & 15)) {
-		/* odd->odd or even->even */
-
-		if (upwards) {
-			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-			if (sx & 15) {
-				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
-				src += BPL * 2;
-				dst += BPL * 2;
-				width -= 8;
-			}
-			w = width >> 4;
-			if (w) {
-				s = (u32 *)src;
-				d = (u32 *)dst;
-				w *= BPL / 2;
-				l = next_line - w * 4;
-				for (j = height; j > 0; j--) {
-					for (i = w; i > 0; i--)
-						*d++ = *s++;
-					s = (u32 *)((u8 *)s + l);
-					d = (u32 *)((u8 *)d + l);
-				}
-			}
-			if (width & 15)
-				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
-					      0xff00ff00, height, next_line - BPL * 2);
-		} else {
-			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
-			if ((sx + width) & 15) {
-				src -= BPL * 2;
-				dst -= BPL * 2;
-				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
-				width -= 8;
-			}
-			w = width >> 4;
-			if (w) {
-				s = (u32 *)src;
-				d = (u32 *)dst;
-				w *= BPL / 2;
-				l = next_line - w * 4;
-				for (j = height; j > 0; j--) {
-					for (i = w; i > 0; i--)
-						*--d = *--s;
-					s = (u32 *)((u8 *)s - l);
-					d = (u32 *)((u8 *)d - l);
-				}
-			}
-			if (sx & 15)
-				memmove32_col(dst - (width - 16) / (8 / BPL),
-					      src - (width - 16) / (8 / BPL),
-					      0xff00ff, colsize, -next_line - BPL * 2);
-		}
-	} else {
-		/* odd->even or even->odd */
-		if (upwards) {
-			u32 *src32, *dst32;
-			u32 pval[4], v, v1, mask;
-			int i, j, w, f;
-
-			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-
-			mask = 0xff00ff00;
-			f = 0;
-			w = width;
-			if (sx & 15) {
-				f = 1;
-				w += 8;
-			}
-			if ((sx + width) & 15)
-				f |= 2;
-			w >>= 4;
-			for (i = height; i; i--) {
-				src32 = (u32 *)src;
-				dst32 = (u32 *)dst;
-
-				if (f & 1) {
-					pval[0] = (*src32++ << 8) & mask;
-				} else {
-					pval[0] = dst32[0] & mask;
-				}
-
-				for (j = w; j > 0; j--) {
-					v = *src32++;
-					v1 = v & mask;
-					*dst32++ = pval[0] | (v1 >> 8);
-					pval[0] = (v ^ v1) << 8;
-				}
-
-				if (f & 2) {
-					dst32[0] = (dst32[0] & mask) | pval[0];
-				}
-
-				src += next_line;
-				dst += next_line;
-			}
-		} else {
-			u32 *src32, *dst32;
-			u32 pval[4], v, v1, mask;
-			int i, j, w, f;
-
-			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
-			mask = 0xff00ff;
-			f = 0;
-			w = width;
-			if ((dx + width) & 15)
-				f = 1;
-			if (sx & 15) {
-				f |= 2;
-				w += 8;
-			}
-			w >>= 4;
-			for (i = height; i; i--) {
-				src32 = (u32 *)src;
-				dst32 = (u32 *)dst;
-
-				if (f & 1) {
-					pval[0] = dst32[-1] & mask;
-				} else {
-					pval[0] = (*--src32 >> 8) & mask;
-				}
-
-				for (j = w; j > 0; j--) {
-					v = *--src32;
-					v1 = v & mask;
-					*--dst32 = pval[0] | (v1 << 8);
-					pval[0] = (v ^ v1) >> 8;
-				}
-
-				if (!(f & 2)) {
-					dst32[-1] = (dst32[-1] & mask) | pval[0];
-				}
-
-				src -= next_line;
-				dst -= next_line;
-			}
-		}
-	}
-}
-
-void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
-                             int sy, int sx, int height, int width)
-{
-	u32 *dest;
-	int rows, i;
-	u32 cval[4];
-
-	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
-	if (sx & 15) {
-		u8 *dest8 = (u8 *)dest + 1;
-
-		expand8_col2mask(color, cval);
-
-		for (i = height; i; i--) {
-			fill8_col(dest8, cval);
-			dest8 += next_line;
-		}
-		dest += BPL / 2;
-		width -= 8;
-	}
-
-	expand16_col2mask(color, cval);
-	rows = width >> 4;
-	if (rows) {
-		u32 *d = dest;
-		u32 off = next_line - rows * BPL * 2;
-		for (i = height; i; i--) {
-			d = fill16_col(d, rows, cval);
-			d = (u32 *)((long)d + off);
-		}
-		dest += rows * BPL / 2;
-		width &= 15;
-	}
-
-	if (width) {
-		u8 *dest8 = (u8 *)dest;
-
-		expand8_col2mask(color, cval);
-
-		for (i = height; i; i--) {
-			fill8_col(dest8, cval);
-			dest8 += next_line;
-		}
-	}
-}
-
-void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
-                             int dy, int dx, u32 width,
-                             const u8 *data, u32 bgcolor, u32 fgcolor)
-{
-	u32 *dest;
-	const u16 *data16;
-	int rows;
-	u32 fgm[4], bgm[4], m;
-
-	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
-	if (dx & 15) {
-		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
-		dest += BPL / 2;
-		width -= 8;
-	}
-
-	if (width >= 16) {
-		data16 = (const u16 *)data;
-		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
-
-		for (rows = width / 16; rows; rows--) {
-			u16 d = *data16++;
-			m = d | ((u32)d << 16);
-			*dest++ = (m & fgm[0]) ^ bgm[0];
-		}
-
-		data = (const u8 *)data16;
-		width &= 15;
-	}
-
-	if (width)
-		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
-}
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return 0;
-}
-
-void cleanup_module(void)
-{
-}
-#endif /* MODULE */
-
-
-    /*
-     *  Visible symbols for modules
-     */
-
-EXPORT_SYMBOL(atafb_iplan2p2_copyarea);
-EXPORT_SYMBOL(atafb_iplan2p2_fillrect);
-EXPORT_SYMBOL(atafb_iplan2p2_linefill);
diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/atafb_iplan2p4.c
deleted file mode 100644
index bee0d89463f7..000000000000
--- a/drivers/video/atafb_iplan2p4.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- *  linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for
- *				      interleaved bitplanes à la Atari (4
- *				      planes, 2 bytes interleave)
- *
- *	Created 5 Apr 1997 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include <asm/setup.h>
-
-#include "atafb.h"
-
-#define BPL	4
-#include "atafb_utils.h"
-
-void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line,
-			     int sy, int sx, int dy, int dx,
-			     int height, int width)
-{
-	/*  bmove() has to distinguish two major cases: If both, source and
-	 *  destination, start at even addresses or both are at odd
-	 *  addresses, just the first odd and last even column (if present)
-	 *  require special treatment (memmove_col()). The rest between
-	 *  then can be copied by normal operations, because all adjacent
-	 *  bytes are affected and are to be stored in the same order.
-	 *    The pathological case is when the move should go from an odd
-	 *  address to an even or vice versa. Since the bytes in the plane
-	 *  words must be assembled in new order, it seems wisest to make
-	 *  all movements by memmove_col().
-	 */
-
-	u8 *src, *dst;
-	u32 *s, *d;
-	int w, l , i, j;
-	u_int colsize;
-	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
-
-	colsize = height;
-	if (!((sx ^ dx) & 15)) {
-		/* odd->odd or even->even */
-
-		if (upwards) {
-			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-			if (sx & 15) {
-				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
-				src += BPL * 2;
-				dst += BPL * 2;
-				width -= 8;
-			}
-			w = width >> 4;
-			if (w) {
-				s = (u32 *)src;
-				d = (u32 *)dst;
-				w *= BPL / 2;
-				l = next_line - w * 4;
-				for (j = height; j > 0; j--) {
-					for (i = w; i > 0; i--)
-						*d++ = *s++;
-					s = (u32 *)((u8 *)s + l);
-					d = (u32 *)((u8 *)d + l);
-				}
-			}
-			if (width & 15)
-				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
-					      0xff00ff00, height, next_line - BPL * 2);
-		} else {
-			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
-			if ((sx + width) & 15) {
-				src -= BPL * 2;
-				dst -= BPL * 2;
-				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
-				width -= 8;
-			}
-			w = width >> 4;
-			if (w) {
-				s = (u32 *)src;
-				d = (u32 *)dst;
-				w *= BPL / 2;
-				l = next_line - w * 4;
-				for (j = height; j > 0; j--) {
-					for (i = w; i > 0; i--)
-						*--d = *--s;
-					s = (u32 *)((u8 *)s - l);
-					d = (u32 *)((u8 *)d - l);
-				}
-			}
-			if (sx & 15)
-				memmove32_col(dst - (width - 16) / (8 / BPL),
-					      src - (width - 16) / (8 / BPL),
-					      0xff00ff, colsize, -next_line - BPL * 2);
-		}
-	} else {
-		/* odd->even or even->odd */
-		if (upwards) {
-			u32 *src32, *dst32;
-			u32 pval[4], v, v1, mask;
-			int i, j, w, f;
-
-			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-
-			mask = 0xff00ff00;
-			f = 0;
-			w = width;
-			if (sx & 15) {
-				f = 1;
-				w += 8;
-			}
-			if ((sx + width) & 15)
-				f |= 2;
-			w >>= 4;
-			for (i = height; i; i--) {
-				src32 = (u32 *)src;
-				dst32 = (u32 *)dst;
-
-				if (f & 1) {
-					pval[0] = (*src32++ << 8) & mask;
-					pval[1] = (*src32++ << 8) & mask;
-				} else {
-					pval[0] = dst32[0] & mask;
-					pval[1] = dst32[1] & mask;
-				}
-
-				for (j = w; j > 0; j--) {
-					v = *src32++;
-					v1 = v & mask;
-					*dst32++ = pval[0] | (v1 >> 8);
-					pval[0] = (v ^ v1) << 8;
-					v = *src32++;
-					v1 = v & mask;
-					*dst32++ = pval[1] | (v1 >> 8);
-					pval[1] = (v ^ v1) << 8;
-				}
-
-				if (f & 2) {
-					dst32[0] = (dst32[0] & mask) | pval[0];
-					dst32[1] = (dst32[1] & mask) | pval[1];
-				}
-
-				src += next_line;
-				dst += next_line;
-			}
-		} else {
-			u32 *src32, *dst32;
-			u32 pval[4], v, v1, mask;
-			int i, j, w, f;
-
-			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
-			mask = 0xff00ff;
-			f = 0;
-			w = width;
-			if ((dx + width) & 15)
-				f = 1;
-			if (sx & 15) {
-				f |= 2;
-				w += 8;
-			}
-			w >>= 4;
-			for (i = height; i; i--) {
-				src32 = (u32 *)src;
-				dst32 = (u32 *)dst;
-
-				if (f & 1) {
-					pval[0] = dst32[-1] & mask;
-					pval[1] = dst32[-2] & mask;
-				} else {
-					pval[0] = (*--src32 >> 8) & mask;
-					pval[1] = (*--src32 >> 8) & mask;
-				}
-
-				for (j = w; j > 0; j--) {
-					v = *--src32;
-					v1 = v & mask;
-					*--dst32 = pval[0] | (v1 << 8);
-					pval[0] = (v ^ v1) >> 8;
-					v = *--src32;
-					v1 = v & mask;
-					*--dst32 = pval[1] | (v1 << 8);
-					pval[1] = (v ^ v1) >> 8;
-				}
-
-				if (!(f & 2)) {
-					dst32[-1] = (dst32[-1] & mask) | pval[0];
-					dst32[-2] = (dst32[-2] & mask) | pval[1];
-				}
-
-				src -= next_line;
-				dst -= next_line;
-			}
-		}
-	}
-}
-
-void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
-                             int sy, int sx, int height, int width)
-{
-	u32 *dest;
-	int rows, i;
-	u32 cval[4];
-
-	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
-	if (sx & 15) {
-		u8 *dest8 = (u8 *)dest + 1;
-
-		expand8_col2mask(color, cval);
-
-		for (i = height; i; i--) {
-			fill8_col(dest8, cval);
-			dest8 += next_line;
-		}
-		dest += BPL / 2;
-		width -= 8;
-	}
-
-	expand16_col2mask(color, cval);
-	rows = width >> 4;
-	if (rows) {
-		u32 *d = dest;
-		u32 off = next_line - rows * BPL * 2;
-		for (i = height; i; i--) {
-			d = fill16_col(d, rows, cval);
-			d = (u32 *)((long)d + off);
-		}
-		dest += rows * BPL / 2;
-		width &= 15;
-	}
-
-	if (width) {
-		u8 *dest8 = (u8 *)dest;
-
-		expand8_col2mask(color, cval);
-
-		for (i = height; i; i--) {
-			fill8_col(dest8, cval);
-			dest8 += next_line;
-		}
-	}
-}
-
-void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
-                             int dy, int dx, u32 width,
-                             const u8 *data, u32 bgcolor, u32 fgcolor)
-{
-	u32 *dest;
-	const u16 *data16;
-	int rows;
-	u32 fgm[4], bgm[4], m;
-
-	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
-	if (dx & 15) {
-		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
-		dest += BPL / 2;
-		width -= 8;
-	}
-
-	if (width >= 16) {
-		data16 = (const u16 *)data;
-		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
-
-		for (rows = width / 16; rows; rows--) {
-			u16 d = *data16++;
-			m = d | ((u32)d << 16);
-			*dest++ = (m & fgm[0]) ^ bgm[0];
-			*dest++ = (m & fgm[1]) ^ bgm[1];
-		}
-
-		data = (const u8 *)data16;
-		width &= 15;
-	}
-
-	if (width)
-		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
-}
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return 0;
-}
-
-void cleanup_module(void)
-{
-}
-#endif /* MODULE */
-
-
-    /*
-     *  Visible symbols for modules
-     */
-
-EXPORT_SYMBOL(atafb_iplan2p4_copyarea);
-EXPORT_SYMBOL(atafb_iplan2p4_fillrect);
-EXPORT_SYMBOL(atafb_iplan2p4_linefill);
diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/atafb_iplan2p8.c
deleted file mode 100644
index 356fb52ce443..000000000000
--- a/drivers/video/atafb_iplan2p8.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- *  linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for
- *				      interleaved bitplanes à la Atari (8
- *				      planes, 2 bytes interleave)
- *
- *	Created 5 Apr 1997 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include <asm/setup.h>
-
-#include "atafb.h"
-
-#define BPL	8
-#include "atafb_utils.h"
-
-
-/* Copies a 8 plane column from 's', height 'h', to 'd'. */
-
-/* This expands a 8 bit color into two longs for two movepl (8 plane)
- * operations.
- */
-
-void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line,
-			     int sy, int sx, int dy, int dx,
-			     int height, int width)
-{
-	/*  bmove() has to distinguish two major cases: If both, source and
-	 *  destination, start at even addresses or both are at odd
-	 *  addresses, just the first odd and last even column (if present)
-	 *  require special treatment (memmove_col()). The rest between
-	 *  then can be copied by normal operations, because all adjacent
-	 *  bytes are affected and are to be stored in the same order.
-	 *    The pathological case is when the move should go from an odd
-	 *  address to an even or vice versa. Since the bytes in the plane
-	 *  words must be assembled in new order, it seems wisest to make
-	 *  all movements by memmove_col().
-	 */
-
-	u8 *src, *dst;
-	u32 *s, *d;
-	int w, l , i, j;
-	u_int colsize;
-	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
-
-	colsize = height;
-	if (!((sx ^ dx) & 15)) {
-		/* odd->odd or even->even */
-
-		if (upwards) {
-			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-			if (sx & 15) {
-				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
-				src += BPL * 2;
-				dst += BPL * 2;
-				width -= 8;
-			}
-			w = width >> 4;
-			if (w) {
-				s = (u32 *)src;
-				d = (u32 *)dst;
-				w *= BPL / 2;
-				l = next_line - w * 4;
-				for (j = height; j > 0; j--) {
-					for (i = w; i > 0; i--)
-						*d++ = *s++;
-					s = (u32 *)((u8 *)s + l);
-					d = (u32 *)((u8 *)d + l);
-				}
-			}
-			if (width & 15)
-				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
-					      0xff00ff00, height, next_line - BPL * 2);
-		} else {
-			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
-			if ((sx + width) & 15) {
-				src -= BPL * 2;
-				dst -= BPL * 2;
-				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
-				width -= 8;
-			}
-			w = width >> 4;
-			if (w) {
-				s = (u32 *)src;
-				d = (u32 *)dst;
-				w *= BPL / 2;
-				l = next_line - w * 4;
-				for (j = height; j > 0; j--) {
-					for (i = w; i > 0; i--)
-						*--d = *--s;
-					s = (u32 *)((u8 *)s - l);
-					d = (u32 *)((u8 *)d - l);
-				}
-			}
-			if (sx & 15)
-				memmove32_col(dst - (width - 16) / (8 / BPL),
-					      src - (width - 16) / (8 / BPL),
-					      0xff00ff, colsize, -next_line - BPL * 2);
-		}
-	} else {
-		/* odd->even or even->odd */
-		if (upwards) {
-			u32 *src32, *dst32;
-			u32 pval[4], v, v1, mask;
-			int i, j, w, f;
-
-			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-
-			mask = 0xff00ff00;
-			f = 0;
-			w = width;
-			if (sx & 15) {
-				f = 1;
-				w += 8;
-			}
-			if ((sx + width) & 15)
-				f |= 2;
-			w >>= 4;
-			for (i = height; i; i--) {
-				src32 = (u32 *)src;
-				dst32 = (u32 *)dst;
-
-				if (f & 1) {
-					pval[0] = (*src32++ << 8) & mask;
-					pval[1] = (*src32++ << 8) & mask;
-					pval[2] = (*src32++ << 8) & mask;
-					pval[3] = (*src32++ << 8) & mask;
-				} else {
-					pval[0] = dst32[0] & mask;
-					pval[1] = dst32[1] & mask;
-					pval[2] = dst32[2] & mask;
-					pval[3] = dst32[3] & mask;
-				}
-
-				for (j = w; j > 0; j--) {
-					v = *src32++;
-					v1 = v & mask;
-					*dst32++ = pval[0] | (v1 >> 8);
-					pval[0] = (v ^ v1) << 8;
-					v = *src32++;
-					v1 = v & mask;
-					*dst32++ = pval[1] | (v1 >> 8);
-					pval[1] = (v ^ v1) << 8;
-					v = *src32++;
-					v1 = v & mask;
-					*dst32++ = pval[2] | (v1 >> 8);
-					pval[2] = (v ^ v1) << 8;
-					v = *src32++;
-					v1 = v & mask;
-					*dst32++ = pval[3] | (v1 >> 8);
-					pval[3] = (v ^ v1) << 8;
-				}
-
-				if (f & 2) {
-					dst32[0] = (dst32[0] & mask) | pval[0];
-					dst32[1] = (dst32[1] & mask) | pval[1];
-					dst32[2] = (dst32[2] & mask) | pval[2];
-					dst32[3] = (dst32[3] & mask) | pval[3];
-				}
-
-				src += next_line;
-				dst += next_line;
-			}
-		} else {
-			u32 *src32, *dst32;
-			u32 pval[4], v, v1, mask;
-			int i, j, w, f;
-
-			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
-			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
-			mask = 0xff00ff;
-			f = 0;
-			w = width;
-			if ((dx + width) & 15)
-				f = 1;
-			if (sx & 15) {
-				f |= 2;
-				w += 8;
-			}
-			w >>= 4;
-			for (i = height; i; i--) {
-				src32 = (u32 *)src;
-				dst32 = (u32 *)dst;
-
-				if (f & 1) {
-					pval[0] = dst32[-1] & mask;
-					pval[1] = dst32[-2] & mask;
-					pval[2] = dst32[-3] & mask;
-					pval[3] = dst32[-4] & mask;
-				} else {
-					pval[0] = (*--src32 >> 8) & mask;
-					pval[1] = (*--src32 >> 8) & mask;
-					pval[2] = (*--src32 >> 8) & mask;
-					pval[3] = (*--src32 >> 8) & mask;
-				}
-
-				for (j = w; j > 0; j--) {
-					v = *--src32;
-					v1 = v & mask;
-					*--dst32 = pval[0] | (v1 << 8);
-					pval[0] = (v ^ v1) >> 8;
-					v = *--src32;
-					v1 = v & mask;
-					*--dst32 = pval[1] | (v1 << 8);
-					pval[1] = (v ^ v1) >> 8;
-					v = *--src32;
-					v1 = v & mask;
-					*--dst32 = pval[2] | (v1 << 8);
-					pval[2] = (v ^ v1) >> 8;
-					v = *--src32;
-					v1 = v & mask;
-					*--dst32 = pval[3] | (v1 << 8);
-					pval[3] = (v ^ v1) >> 8;
-				}
-
-				if (!(f & 2)) {
-					dst32[-1] = (dst32[-1] & mask) | pval[0];
-					dst32[-2] = (dst32[-2] & mask) | pval[1];
-					dst32[-3] = (dst32[-3] & mask) | pval[2];
-					dst32[-4] = (dst32[-4] & mask) | pval[3];
-				}
-
-				src -= next_line;
-				dst -= next_line;
-			}
-		}
-	}
-}
-
-void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
-                             int sy, int sx, int height, int width)
-{
-	u32 *dest;
-	int rows, i;
-	u32 cval[4];
-
-	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
-	if (sx & 15) {
-		u8 *dest8 = (u8 *)dest + 1;
-
-		expand8_col2mask(color, cval);
-
-		for (i = height; i; i--) {
-			fill8_col(dest8, cval);
-			dest8 += next_line;
-		}
-		dest += BPL / 2;
-		width -= 8;
-	}
-
-	expand16_col2mask(color, cval);
-	rows = width >> 4;
-	if (rows) {
-		u32 *d = dest;
-		u32 off = next_line - rows * BPL * 2;
-		for (i = height; i; i--) {
-			d = fill16_col(d, rows, cval);
-			d = (u32 *)((long)d + off);
-		}
-		dest += rows * BPL / 2;
-		width &= 15;
-	}
-
-	if (width) {
-		u8 *dest8 = (u8 *)dest;
-
-		expand8_col2mask(color, cval);
-
-		for (i = height; i; i--) {
-			fill8_col(dest8, cval);
-			dest8 += next_line;
-		}
-	}
-}
-
-void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
-			     int dy, int dx, u32 width,
-			     const u8 *data, u32 bgcolor, u32 fgcolor)
-{
-	u32 *dest;
-	const u16 *data16;
-	int rows;
-	u32 fgm[4], bgm[4], m;
-
-	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
-	if (dx & 15) {
-		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
-		dest += BPL / 2;
-		width -= 8;
-	}
-
-	if (width >= 16) {
-		data16 = (const u16 *)data;
-		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
-
-		for (rows = width / 16; rows; rows--) {
-			u16 d = *data16++;
-			m = d | ((u32)d << 16);
-			*dest++ = (m & fgm[0]) ^ bgm[0];
-			*dest++ = (m & fgm[1]) ^ bgm[1];
-			*dest++ = (m & fgm[2]) ^ bgm[2];
-			*dest++ = (m & fgm[3]) ^ bgm[3];
-		}
-
-		data = (const u8 *)data16;
-		width &= 15;
-	}
-
-	if (width)
-		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
-}
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return 0;
-}
-
-void cleanup_module(void)
-{
-}
-#endif /* MODULE */
-
-
-    /*
-     *  Visible symbols for modules
-     */
-
-EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
-EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
-EXPORT_SYMBOL(atafb_iplan2p8_linefill);
diff --git a/drivers/video/atafb_mfb.c b/drivers/video/atafb_mfb.c
deleted file mode 100644
index 6a352d62eecf..000000000000
--- a/drivers/video/atafb_mfb.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- *  linux/drivers/video/mfb.c -- Low level frame buffer operations for
- *				 monochrome
- *
- *	Created 5 Apr 1997 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include "atafb.h"
-#include "atafb_utils.h"
-
-
-    /*
-     *  Monochrome
-     */
-
-void atafb_mfb_copyarea(struct fb_info *info, u_long next_line,
-			int sy, int sx, int dy, int dx,
-			int height, int width)
-{
-	u8 *src, *dest;
-	u_int rows;
-
-	if (sx == 0 && dx == 0 && width == next_line) {
-		src = (u8 *)info->screen_base + sy * (width >> 3);
-		dest = (u8 *)info->screen_base + dy * (width >> 3);
-		fb_memmove(dest, src, height * (width >> 3));
-	} else if (dy <= sy) {
-		src = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
-		dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
-		for (rows = height; rows--;) {
-			fb_memmove(dest, src, width >> 3);
-			src += next_line;
-			dest += next_line;
-		}
-	} else {
-		src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3);
-		dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3);
-		for (rows = height; rows--;) {
-			fb_memmove(dest, src, width >> 3);
-			src -= next_line;
-			dest -= next_line;
-		}
-	}
-}
-
-void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
-			int sy, int sx, int height, int width)
-{
-	u8 *dest;
-	u_int rows;
-
-	dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
-
-	if (sx == 0 && width == next_line) {
-		if (color)
-			fb_memset255(dest, height * (width >> 3));
-		else
-			fb_memclear(dest, height * (width >> 3));
-	} else {
-		for (rows = height; rows--; dest += next_line) {
-			if (color)
-				fb_memset255(dest, width >> 3);
-			else
-				fb_memclear_small(dest, width >> 3);
-		}
-	}
-}
-
-void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
-			int dy, int dx, u32 width,
-			const u8 *data, u32 bgcolor, u32 fgcolor)
-{
-	u8 *dest;
-	u_int rows;
-
-	dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
-
-	for (rows = width / 8; rows--; /* check margins */ ) {
-		// use fast_memmove or fb_memmove
-		*dest++ = *data++;
-	}
-}
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return 0;
-}
-
-void cleanup_module(void)
-{
-}
-#endif /* MODULE */
-
-
-    /*
-     *  Visible symbols for modules
-     */
-
-EXPORT_SYMBOL(atafb_mfb_copyarea);
-EXPORT_SYMBOL(atafb_mfb_fillrect);
-EXPORT_SYMBOL(atafb_mfb_linefill);
diff --git a/drivers/video/atafb_utils.h b/drivers/video/atafb_utils.h
deleted file mode 100644
index ac9e19dc5057..000000000000
--- a/drivers/video/atafb_utils.h
+++ /dev/null
@@ -1,400 +0,0 @@
-#ifndef _VIDEO_ATAFB_UTILS_H
-#define _VIDEO_ATAFB_UTILS_H
-
-/* ================================================================= */
-/*                      Utility Assembler Functions                  */
-/* ================================================================= */
-
-/* ====================================================================== */
-
-/* Those of a delicate disposition might like to skip the next couple of
- * pages.
- *
- * These functions are drop in replacements for memmove and
- * memset(_, 0, _). However their five instances add at least a kilobyte
- * to the object file. You have been warned.
- *
- * Not a great fan of assembler for the sake of it, but I think
- * that these routines are at least 10 times faster than their C
- * equivalents for large blits, and that's important to the lowest level of
- * a graphics driver. Question is whether some scheme with the blitter
- * would be faster. I suspect not for simple text system - not much
- * asynchrony.
- *
- * Code is very simple, just gruesome expansion. Basic strategy is to
- * increase data moved/cleared at each step to 16 bytes to reduce
- * instruction per data move overhead. movem might be faster still
- * For more than 15 bytes, we try to align the write direction on a
- * longword boundary to get maximum speed. This is even more gruesome.
- * Unaligned read/write used requires 68020+ - think this is a problem?
- *
- * Sorry!
- */
-
-
-/* ++roman: I've optimized Robert's original versions in some minor
- * aspects, e.g. moveq instead of movel, let gcc choose the registers,
- * use movem in some places...
- * For other modes than 1 plane, lots of more such assembler functions
- * were needed (e.g. the ones using movep or expanding color values).
- */
-
-/* ++andreas: more optimizations:
-   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
-   addal is faster than addaw
-   movep is rather expensive compared to ordinary move's
-   some functions rewritten in C for clarity, no speed loss */
-
-static inline void *fb_memclear_small(void *s, size_t count)
-{
-	if (!count)
-		return 0;
-
-	asm volatile ("\n"
-		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
-		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
-		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
-		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
-		"1:"
-		: "=a" (s), "=d" (count)
-		: "d" (0), "0" ((char *)s + count), "1" (count));
-	asm volatile ("\n"
-		"	subq.l  #1,%1\n"
-		"	jcs	3f\n"
-		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
-		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
-		"	dbra	%1,2b\n"
-		"3:"
-		: "=a" (s), "=d" (count)
-		: "d" (0), "0" (s), "1" (count)
-		: "d4", "d5", "d6"
-		);
-
-	return 0;
-}
-
-
-static inline void *fb_memclear(void *s, size_t count)
-{
-	if (!count)
-		return 0;
-
-	if (count < 16) {
-		asm volatile ("\n"
-			"	lsr.l	#1,%1 ; jcc 1f ; clr.b (%0)+\n"
-			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.w (%0)+\n"
-			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+\n"
-			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n"
-			"1:"
-			: "=a" (s), "=d" (count)
-			: "0" (s), "1" (count));
-	} else {
-		long tmp;
-		asm volatile ("\n"
-			"	move.l	%1,%2\n"
-			"	lsr.l	#1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n"
-			"	lsr.l	#1,%2 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
-			"	clr.w	(%0)+  ; subq.w  #2,%1 ; jra 2f\n"
-			"1:	lsr.l	#1,%2 ; jcc 2f\n"
-			"	clr.w	(%0)+  ; subq.w  #2,%1\n"
-			"2:	move.w	%1,%2; lsr.l #2,%1 ; jeq 6f\n"
-			"	lsr.l	#1,%1 ; jcc 3f ; clr.l (%0)+\n"
-			"3:	lsr.l	#1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n"
-			"4:	subq.l	#1,%1 ; jcs 6f\n"
-			"5:	clr.l	(%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n"
-			"	dbra	%1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n"
-			"6:	move.w	%2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n"
-			"7:	btst	#0,%1 ; jeq 8f ; clr.b (%0)+\n"
-			"8:"
-			: "=a" (s), "=d" (count), "=d" (tmp)
-			: "0" (s), "1" (count));
-	}
-
-	return 0;
-}
-
-
-static inline void *fb_memset255(void *s, size_t count)
-{
-	if (!count)
-		return 0;
-
-	asm volatile ("\n"
-		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
-		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
-		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
-		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
-		"1:"
-		: "=a" (s), "=d" (count)
-		: "d" (-1), "0" ((char *)s+count), "1" (count));
-	asm volatile ("\n"
-		"	subq.l	#1,%1 ; jcs 3f\n"
-		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
-		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
-		"	dbra	%1,2b\n"
-		"3:"
-		: "=a" (s), "=d" (count)
-		: "d" (-1), "0" (s), "1" (count)
-		: "d4", "d5", "d6");
-
-	return 0;
-}
-
-
-static inline void *fb_memmove(void *d, const void *s, size_t count)
-{
-	if (d < s) {
-		if (count < 16) {
-			asm volatile ("\n"
-				"	lsr.l	#1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n"
-				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n"
-				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n"
-				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
-				"1:"
-				: "=a" (d), "=a" (s), "=d" (count)
-				: "0" (d), "1" (s), "2" (count));
-		} else {
-			long tmp;
-			asm volatile ("\n"
-				"	move.l	%0,%3\n"
-				"	lsr.l	#1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n"
-				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
-				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2 ; jra 2f\n"
-				"1:	lsr.l   #1,%3 ; jcc 2f\n"
-				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2\n"
-				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
-				"	lsr.l	#1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n"
-				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
-				"4:	subq.l	#1,%2 ; jcs 6f\n"
-				"5:	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
-				"	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
-				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
-				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n"
-				"7:	btst	#0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n"
-				"8:"
-				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
-				: "0" (d), "1" (s), "2" (count));
-		}
-	} else {
-		if (count < 16) {
-			asm volatile ("\n"
-				"	lsr.l	#1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n"
-				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n"
-				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n"
-				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
-				"1:"
-				: "=a" (d), "=a" (s), "=d" (count)
-				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
-		} else {
-			long tmp;
-
-			asm volatile ("\n"
-				"	move.l	%0,%3\n"
-				"	lsr.l	#1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n"
-				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
-				"	move.w	-(%1),-(%0) ; subqw  #2,%2 ; jra 2f\n"
-				"1:	lsr.l	#1,%3 ; jcc 2f\n"
-				"	move.w	-(%1),-(%0) ; subqw  #2,%2\n"
-				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
-				"	lsr.l	#1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n"
-				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
-				"4:	subq.l	#1,%2 ; jcs 6f\n"
-				"5:	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
-				"	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
-				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
-				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n"
-				"7:	btst	#0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n"
-				"8:"
-				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
-				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
-		}
-	}
-
-	return 0;
-}
-
-
-/* ++andreas: Simple and fast version of memmove, assumes size is
-   divisible by 16, suitable for moving the whole screen bitplane */
-static inline void fast_memmove(char *dst, const char *src, size_t size)
-{
-	if (!size)
-		return;
-	if (dst < src)
-		asm volatile ("\n"
-			"1:	movem.l	(%0)+,%%d0/%%d1/%%a0/%%a1\n"
-			"	movem.l	%%d0/%%d1/%%a0/%%a1,%1@\n"
-			"	addq.l	#8,%1; addq.l #8,%1\n"
-			"	dbra	%2,1b\n"
-			"	clr.w	%2; subq.l #1,%2\n"
-			"	jcc	1b"
-			: "=a" (src), "=a" (dst), "=d" (size)
-			: "0" (src), "1" (dst), "2" (size / 16 - 1)
-			: "d0", "d1", "a0", "a1", "memory");
-	else
-		asm volatile ("\n"
-			"1:	subq.l	#8,%0; subq.l #8,%0\n"
-			"	movem.l	%0@,%%d0/%%d1/%%a0/%%a1\n"
-			"	movem.l	%%d0/%%d1/%%a0/%%a1,-(%1)\n"
-			"	dbra	%2,1b\n"
-			"	clr.w	%2; subq.l #1,%2\n"
-			"	jcc 1b"
-			: "=a" (src), "=a" (dst), "=d" (size)
-			: "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
-			: "d0", "d1", "a0", "a1", "memory");
-}
-
-#ifdef BPL
-
-/*
- * This expands a up to 8 bit color into two longs
- * for movel operations.
- */
-static const u32 four2long[] = {
-	0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
-	0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
-	0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
-	0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff,
-};
-
-static inline void expand8_col2mask(u8 c, u32 m[])
-{
-	m[0] = four2long[c & 15];
-#if BPL > 4
-	m[1] = four2long[c >> 4];
-#endif
-}
-
-static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
-{
-	fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]);
-#if BPL > 4
-	fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]);
-#endif
-}
-
-/*
- * set an 8bit value to a color
- */
-static inline void fill8_col(u8 *dst, u32 m[])
-{
-	u32 tmp = m[0];
-	dst[0] = tmp;
-	dst[2] = (tmp >>= 8);
-#if BPL > 2
-	dst[4] = (tmp >>= 8);
-	dst[6] = tmp >> 8;
-#endif
-#if BPL > 4
-	tmp = m[1];
-	dst[8] = tmp;
-	dst[10] = (tmp >>= 8);
-	dst[12] = (tmp >>= 8);
-	dst[14] = tmp >> 8;
-#endif
-}
-
-/*
- * set an 8bit value according to foreground/background color
- */
-static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask)
-{
-	u32 fgm[2], bgm[2], tmp;
-
-	expand8_2col2mask(fg, bg, fgm, bgm);
-
-	mask |= mask << 8;
-#if BPL > 2
-	mask |= mask << 16;
-#endif
-	tmp = (mask & fgm[0]) ^ bgm[0];
-	dst[0] = tmp;
-	dst[2] = (tmp >>= 8);
-#if BPL > 2
-	dst[4] = (tmp >>= 8);
-	dst[6] = tmp >> 8;
-#endif
-#if BPL > 4
-	tmp = (mask & fgm[1]) ^ bgm[1];
-	dst[8] = tmp;
-	dst[10] = (tmp >>= 8);
-	dst[12] = (tmp >>= 8);
-	dst[14] = tmp >> 8;
-#endif
-}
-
-static const u32 two2word[] = {
-	0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
-};
-
-static inline void expand16_col2mask(u8 c, u32 m[])
-{
-	m[0] = two2word[c & 3];
-#if BPL > 2
-	m[1] = two2word[(c >> 2) & 3];
-#endif
-#if BPL > 4
-	m[2] = two2word[(c >> 4) & 3];
-	m[3] = two2word[c >> 6];
-#endif
-}
-
-static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
-{
-	bgm[0] = two2word[bg & 3];
-	fgm[0] = two2word[fg & 3] ^ bgm[0];
-#if BPL > 2
-	bgm[1] = two2word[(bg >> 2) & 3];
-	fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1];
-#endif
-#if BPL > 4
-	bgm[2] = two2word[(bg >> 4) & 3];
-	fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2];
-	bgm[3] = two2word[bg >> 6];
-	fgm[3] = two2word[fg >> 6] ^ bgm[3];
-#endif
-}
-
-static inline u32 *fill16_col(u32 *dst, int rows, u32 m[])
-{
-	while (rows) {
-		*dst++ = m[0];
-#if BPL > 2
-		*dst++ = m[1];
-#endif
-#if BPL > 4
-		*dst++ = m[2];
-		*dst++ = m[3];
-#endif
-		rows--;
-	}
-	return dst;
-}
-
-static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes)
-{
-	u32 *s, *d, v;
-
-        s = src;
-        d = dst;
-        do {
-                v = (*s++ & mask) | (*d  & ~mask);
-                *d++ = v;
-#if BPL > 2
-                v = (*s++ & mask) | (*d  & ~mask);
-                *d++ = v;
-#endif
-#if BPL > 4
-                v = (*s++ & mask) | (*d  & ~mask);
-                *d++ = v;
-                v = (*s++ & mask) | (*d  & ~mask);
-                *d++ = v;
-#endif
-                d = (u32 *)((u8 *)d + bytes);
-                s = (u32 *)((u8 *)s + bytes);
-        } while (--h);
-}
-
-#endif
-
-#endif /* _VIDEO_ATAFB_UTILS_H */
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
deleted file mode 100644
index e683b6ef9594..000000000000
--- a/drivers/video/atmel_lcdfb.c
+++ /dev/null
@@ -1,1453 +0,0 @@
-/*
- *  Driver for AT91/AT32 LCD Controller
- *
- *  Copyright (C) 2007 Atmel Corporation
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/backlight.h>
-#include <linux/gfp.h>
-#include <linux/module.h>
-#include <linux/platform_data/atmel.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <video/of_display_timing.h>
-#include <video/videomode.h>
-
-#include <mach/cpu.h>
-#include <asm/gpio.h>
-
-#include <video/atmel_lcdc.h>
-
-struct atmel_lcdfb_config {
-	bool have_alt_pixclock;
-	bool have_hozval;
-	bool have_intensity_bit;
-};
-
- /* LCD Controller info data structure, stored in device platform_data */
-struct atmel_lcdfb_info {
-	spinlock_t		lock;
-	struct fb_info		*info;
-	void __iomem		*mmio;
-	int			irq_base;
-	struct work_struct	task;
-
-	unsigned int		smem_len;
-	struct platform_device	*pdev;
-	struct clk		*bus_clk;
-	struct clk		*lcdc_clk;
-
-	struct backlight_device	*backlight;
-	u8			bl_power;
-	u8			saved_lcdcon;
-
-	u32			pseudo_palette[16];
-	bool			have_intensity_bit;
-
-	struct atmel_lcdfb_pdata pdata;
-
-	struct atmel_lcdfb_config *config;
-};
-
-struct atmel_lcdfb_power_ctrl_gpio {
-	int gpio;
-	int active_low;
-
-	struct list_head list;
-};
-
-#define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
-#define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))
-
-/* configurable parameters */
-#define ATMEL_LCDC_CVAL_DEFAULT		0xc8
-#define ATMEL_LCDC_DMA_BURST_LEN	8	/* words */
-#define ATMEL_LCDC_FIFO_SIZE		512	/* words */
-
-static struct atmel_lcdfb_config at91sam9261_config = {
-	.have_hozval		= true,
-	.have_intensity_bit	= true,
-};
-
-static struct atmel_lcdfb_config at91sam9263_config = {
-	.have_intensity_bit	= true,
-};
-
-static struct atmel_lcdfb_config at91sam9g10_config = {
-	.have_hozval		= true,
-};
-
-static struct atmel_lcdfb_config at91sam9g45_config = {
-	.have_alt_pixclock	= true,
-};
-
-static struct atmel_lcdfb_config at91sam9g45es_config = {
-};
-
-static struct atmel_lcdfb_config at91sam9rl_config = {
-	.have_intensity_bit	= true,
-};
-
-static struct atmel_lcdfb_config at32ap_config = {
-	.have_hozval		= true,
-};
-
-static const struct platform_device_id atmel_lcdfb_devtypes[] = {
-	{
-		.name = "at91sam9261-lcdfb",
-		.driver_data = (unsigned long)&at91sam9261_config,
-	}, {
-		.name = "at91sam9263-lcdfb",
-		.driver_data = (unsigned long)&at91sam9263_config,
-	}, {
-		.name = "at91sam9g10-lcdfb",
-		.driver_data = (unsigned long)&at91sam9g10_config,
-	}, {
-		.name = "at91sam9g45-lcdfb",
-		.driver_data = (unsigned long)&at91sam9g45_config,
-	}, {
-		.name = "at91sam9g45es-lcdfb",
-		.driver_data = (unsigned long)&at91sam9g45es_config,
-	}, {
-		.name = "at91sam9rl-lcdfb",
-		.driver_data = (unsigned long)&at91sam9rl_config,
-	}, {
-		.name = "at32ap-lcdfb",
-		.driver_data = (unsigned long)&at32ap_config,
-	}, {
-		/* terminator */
-	}
-};
-MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes);
-
-static struct atmel_lcdfb_config *
-atmel_lcdfb_get_config(struct platform_device *pdev)
-{
-	unsigned long data;
-
-	data = platform_get_device_id(pdev)->driver_data;
-
-	return (struct atmel_lcdfb_config *)data;
-}
-
-#if defined(CONFIG_ARCH_AT91)
-#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
-					 | FBINFO_PARTIAL_PAN_OK \
-					 | FBINFO_HWACCEL_YPAN)
-
-static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-					struct fb_var_screeninfo *var,
-					struct fb_info *info)
-{
-
-}
-#elif defined(CONFIG_AVR32)
-#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
-					| FBINFO_PARTIAL_PAN_OK \
-					| FBINFO_HWACCEL_XPAN \
-					| FBINFO_HWACCEL_YPAN)
-
-static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-				     struct fb_var_screeninfo *var,
-				     struct fb_info *info)
-{
-	u32 dma2dcfg;
-	u32 pixeloff;
-
-	pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
-
-	dma2dcfg = (info->var.xres_virtual - info->var.xres)
-		 * info->var.bits_per_pixel / 8;
-	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
-	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
-
-	/* Update configuration */
-	lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
-		    lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
-		    | ATMEL_LCDC_DMAUPDT);
-}
-#endif
-
-static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
-		| ATMEL_LCDC_POL_POSITIVE
-		| ATMEL_LCDC_ENA_PWMENABLE;
-
-#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
-
-/* some bl->props field just changed */
-static int atmel_bl_update_status(struct backlight_device *bl)
-{
-	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-	int			power = sinfo->bl_power;
-	int			brightness = bl->props.brightness;
-
-	/* REVISIT there may be a meaningful difference between
-	 * fb_blank and power ... there seem to be some cases
-	 * this doesn't handle correctly.
-	 */
-	if (bl->props.fb_blank != sinfo->bl_power)
-		power = bl->props.fb_blank;
-	else if (bl->props.power != sinfo->bl_power)
-		power = bl->props.power;
-
-	if (brightness < 0 && power == FB_BLANK_UNBLANK)
-		brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-	else if (power != FB_BLANK_UNBLANK)
-		brightness = 0;
-
-	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
-	if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
-		lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
-			brightness ? contrast_ctr : 0);
-	else
-		lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-
-	bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
-
-	return 0;
-}
-
-static int atmel_bl_get_brightness(struct backlight_device *bl)
-{
-	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-
-	return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-}
-
-static const struct backlight_ops atmel_lcdc_bl_ops = {
-	.update_status = atmel_bl_update_status,
-	.get_brightness = atmel_bl_get_brightness,
-};
-
-static void init_backlight(struct atmel_lcdfb_info *sinfo)
-{
-	struct backlight_properties props;
-	struct backlight_device	*bl;
-
-	sinfo->bl_power = FB_BLANK_UNBLANK;
-
-	if (sinfo->backlight)
-		return;
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 0xff;
-	bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
-				       &atmel_lcdc_bl_ops, &props);
-	if (IS_ERR(bl)) {
-		dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
-				PTR_ERR(bl));
-		return;
-	}
-	sinfo->backlight = bl;
-
-	bl->props.power = FB_BLANK_UNBLANK;
-	bl->props.fb_blank = FB_BLANK_UNBLANK;
-	bl->props.brightness = atmel_bl_get_brightness(bl);
-}
-
-static void exit_backlight(struct atmel_lcdfb_info *sinfo)
-{
-	if (!sinfo->backlight)
-		return;
-
-	if (sinfo->backlight->ops) {
-		sinfo->backlight->props.power = FB_BLANK_POWERDOWN;
-		sinfo->backlight->ops->update_status(sinfo->backlight);
-	}
-	backlight_device_unregister(sinfo->backlight);
-}
-
-#else
-
-static void init_backlight(struct atmel_lcdfb_info *sinfo)
-{
-	dev_warn(&sinfo->pdev->dev, "backlight control is not available\n");
-}
-
-static void exit_backlight(struct atmel_lcdfb_info *sinfo)
-{
-}
-
-#endif
-
-static void init_contrast(struct atmel_lcdfb_info *sinfo)
-{
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-
-	/* contrast pwm can be 'inverted' */
-	if (pdata->lcdcon_pol_negative)
-			contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
-
-	/* have some default contrast/backlight settings */
-	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
-	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
-
-	if (pdata->lcdcon_is_backlight)
-		init_backlight(sinfo);
-}
-
-static inline void atmel_lcdfb_power_control(struct atmel_lcdfb_info *sinfo, int on)
-{
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-
-	if (pdata->atmel_lcdfb_power_control)
-		pdata->atmel_lcdfb_power_control(pdata, on);
-}
-
-static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_TRUECOLOR,
-	.xpanstep	= 0,
-	.ypanstep	= 1,
-	.ywrapstep	= 0,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
-							unsigned long xres)
-{
-	unsigned long lcdcon2;
-	unsigned long value;
-
-	if (!sinfo->config->have_hozval)
-		return xres;
-
-	lcdcon2 = lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2);
-	value = xres;
-	if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
-		/* STN display */
-		if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) {
-			value *= 3;
-		}
-		if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4
-		   || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8
-		      && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL ))
-			value = DIV_ROUND_UP(value, 4);
-		else
-			value = DIV_ROUND_UP(value, 8);
-	}
-
-	return value;
-}
-
-static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
-{
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-
-	/* Turn off the LCD controller and the DMA controller */
-	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-			pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
-
-	/* Wait for the LCDC core to become idle */
-	while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
-		msleep(10);
-
-	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
-}
-
-static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
-{
-	atmel_lcdfb_stop_nowait(sinfo);
-
-	/* Wait for DMA engine to become idle... */
-	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-		msleep(10);
-}
-
-static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
-{
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-
-	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, pdata->default_dmacon);
-	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
-		(pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
-		| ATMEL_LCDC_PWR);
-}
-
-static void atmel_lcdfb_update_dma(struct fb_info *info,
-			       struct fb_var_screeninfo *var)
-{
-	struct atmel_lcdfb_info *sinfo = info->par;
-	struct fb_fix_screeninfo *fix = &info->fix;
-	unsigned long dma_addr;
-
-	dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-		    + var->xoffset * info->var.bits_per_pixel / 8);
-
-	dma_addr &= ~3UL;
-
-	/* Set framebuffer DMA base address and pixel offset */
-	lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
-
-	atmel_lcdfb_update_dma2d(sinfo, var, info);
-}
-
-static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
-{
-	struct fb_info *info = sinfo->info;
-
-	dma_free_writecombine(info->device, info->fix.smem_len,
-				info->screen_base, info->fix.smem_start);
-}
-
-/**
- *	atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
- *	@sinfo: the frame buffer to allocate memory for
- * 	
- * 	This function is called only from the atmel_lcdfb_probe()
- * 	so no locking by fb_info->mm_lock around smem_len setting is needed.
- */
-static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
-{
-	struct fb_info *info = sinfo->info;
-	struct fb_var_screeninfo *var = &info->var;
-	unsigned int smem_len;
-
-	smem_len = (var->xres_virtual * var->yres_virtual
-		    * ((var->bits_per_pixel + 7) / 8));
-	info->fix.smem_len = max(smem_len, sinfo->smem_len);
-
-	info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
-					(dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
-
-	if (!info->screen_base) {
-		return -ENOMEM;
-	}
-
-	memset(info->screen_base, 0, info->fix.smem_len);
-
-	return 0;
-}
-
-static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
-						     struct fb_info *info)
-{
-	struct fb_videomode varfbmode;
-	const struct fb_videomode *fbmode = NULL;
-
-	fb_var_to_videomode(&varfbmode, var);
-	fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
-	if (fbmode)
-		fb_videomode_to_var(var, fbmode);
-	return fbmode;
-}
-
-
-/**
- *      atmel_lcdfb_check_var - Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *	Checks to see if the hardware supports the state requested by
- *	var passed in. This function does not alter the hardware
- *	state!!!  This means the data stored in struct fb_info and
- *	struct atmel_lcdfb_info do not change. This includes the var
- *	inside of struct fb_info.  Do NOT change these. This function
- *	can be called on its own if we intent to only test a mode and
- *	not actually set it. The stuff in modedb.c is a example of
- *	this. If the var passed in is slightly off by what the
- *	hardware can support then we alter the var PASSED in to what
- *	we can do. If the hardware doesn't support mode change a
- *	-EINVAL will be returned by the upper layers. You don't need
- *	to implement this function then. If you hardware doesn't
- *	support changing the resolution then this function is not
- *	needed. In this case the driver would just provide a var that
- *	represents the static state the screen is in.
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct device *dev = info->device;
-	struct atmel_lcdfb_info *sinfo = info->par;
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-	unsigned long clk_value_khz;
-
-	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-
-	dev_dbg(dev, "%s:\n", __func__);
-
-	if (!(var->pixclock && var->bits_per_pixel)) {
-		/* choose a suitable mode if possible */
-		if (!atmel_lcdfb_choose_mode(var, info)) {
-			dev_err(dev, "needed value not specified\n");
-			return -EINVAL;
-		}
-	}
-
-	dev_dbg(dev, "  resolution: %ux%u\n", var->xres, var->yres);
-	dev_dbg(dev, "  pixclk:     %lu KHz\n", PICOS2KHZ(var->pixclock));
-	dev_dbg(dev, "  bpp:        %u\n", var->bits_per_pixel);
-	dev_dbg(dev, "  clk:        %lu KHz\n", clk_value_khz);
-
-	if (PICOS2KHZ(var->pixclock) > clk_value_khz) {
-		dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
-		return -EINVAL;
-	}
-
-	/* Do not allow to have real resoulution larger than virtual */
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-
-	/* Force same alignment for each line */
-	var->xres = (var->xres + 3) & ~3UL;
-	var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
-
-	var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-	var->transp.offset = var->transp.length = 0;
-	var->xoffset = var->yoffset = 0;
-
-	if (info->fix.smem_len) {
-		unsigned int smem_len = (var->xres_virtual * var->yres_virtual
-					 * ((var->bits_per_pixel + 7) / 8));
-		if (smem_len > info->fix.smem_len) {
-			dev_err(dev, "Frame buffer is too small (%u) for screen size (need at least %u)\n",
-				info->fix.smem_len, smem_len);
-			return -EINVAL;
-		}
-	}
-
-	/* Saturate vertical and horizontal timings at maximum values */
-	var->vsync_len = min_t(u32, var->vsync_len,
-			(ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
-	var->upper_margin = min_t(u32, var->upper_margin,
-			ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
-	var->lower_margin = min_t(u32, var->lower_margin,
-			ATMEL_LCDC_VFP);
-	var->right_margin = min_t(u32, var->right_margin,
-			(ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
-	var->hsync_len = min_t(u32, var->hsync_len,
-			(ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
-	var->left_margin = min_t(u32, var->left_margin,
-			ATMEL_LCDC_HBP + 1);
-
-	/* Some parameters can't be zero */
-	var->vsync_len = max_t(u32, var->vsync_len, 1);
-	var->right_margin = max_t(u32, var->right_margin, 1);
-	var->hsync_len = max_t(u32, var->hsync_len, 1);
-	var->left_margin = max_t(u32, var->left_margin, 1);
-
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-		var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length
-			= var->bits_per_pixel;
-		break;
-	case 16:
-		/* Older SOCs use IBGR:555 rather than BGR:565. */
-		if (sinfo->config->have_intensity_bit)
-			var->green.length = 5;
-		else
-			var->green.length = 6;
-
-		if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-			/* RGB:5X5 mode */
-			var->red.offset = var->green.length + 5;
-			var->blue.offset = 0;
-		} else {
-			/* BGR:5X5 mode */
-			var->red.offset = 0;
-			var->blue.offset = var->green.length + 5;
-		}
-		var->green.offset = 5;
-		var->red.length = var->blue.length = 5;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		/* fall through */
-	case 24:
-		if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-			/* RGB:888 mode */
-			var->red.offset = 16;
-			var->blue.offset = 0;
-		} else {
-			/* BGR:888 mode */
-			var->red.offset = 0;
-			var->blue.offset = 16;
-		}
-		var->green.offset = 8;
-		var->red.length = var->green.length = var->blue.length = 8;
-		break;
-	default:
-		dev_err(dev, "color depth %d not supported\n",
-					var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
- * LCD reset sequence
- */
-static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
-{
-	might_sleep();
-
-	atmel_lcdfb_stop(sinfo);
-	atmel_lcdfb_start(sinfo);
-}
-
-/**
- *      atmel_lcdfb_set_par - Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *	Using the fb_var_screeninfo in fb_info we set the resolution
- *	of the this particular framebuffer. This function alters the
- *	par AND the fb_fix_screeninfo stored in fb_info. It doesn't
- *	not alter var in fb_info since we are using that data. This
- *	means we depend on the data in var inside fb_info to be
- *	supported by the hardware.  atmel_lcdfb_check_var is always called
- *	before atmel_lcdfb_set_par to ensure this.  Again if you can't
- *	change the resolution you don't need this function.
- *
- */
-static int atmel_lcdfb_set_par(struct fb_info *info)
-{
-	struct atmel_lcdfb_info *sinfo = info->par;
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-	unsigned long hozval_linesz;
-	unsigned long value;
-	unsigned long clk_value_khz;
-	unsigned long bits_per_line;
-	unsigned long pix_factor = 2;
-
-	might_sleep();
-
-	dev_dbg(info->device, "%s:\n", __func__);
-	dev_dbg(info->device, "  * resolution: %ux%u (%ux%u virtual)\n",
-		 info->var.xres, info->var.yres,
-		 info->var.xres_virtual, info->var.yres_virtual);
-
-	atmel_lcdfb_stop_nowait(sinfo);
-
-	if (info->var.bits_per_pixel == 1)
-		info->fix.visual = FB_VISUAL_MONO01;
-	else if (info->var.bits_per_pixel <= 8)
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel;
-	info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8);
-
-	/* Re-initialize the DMA engine... */
-	dev_dbg(info->device, "  * update DMA engine\n");
-	atmel_lcdfb_update_dma(info, &info->var);
-
-	/* ...set frame size and burst length = 8 words (?) */
-	value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
-	value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
-	lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
-
-	/* Now, the LCDC core... */
-
-	/* Set pixel clock */
-	if (sinfo->config->have_alt_pixclock)
-		pix_factor = 1;
-
-	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
-
-	value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
-
-	if (value < pix_factor) {
-		dev_notice(info->device, "Bypassing pixel clock divider\n");
-		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
-	} else {
-		value = (value / pix_factor) - 1;
-		dev_dbg(info->device, "  * programming CLKVAL = 0x%08lx\n",
-				value);
-		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
-				value << ATMEL_LCDC_CLKVAL_OFFSET);
-		info->var.pixclock =
-			KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
-		dev_dbg(info->device, "  updated pixclk:     %lu KHz\n",
-					PICOS2KHZ(info->var.pixclock));
-	}
-
-
-	/* Initialize control register 2 */
-	value = pdata->default_lcdcon2;
-
-	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-		value |= ATMEL_LCDC_INVLINE_INVERTED;
-	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-		value |= ATMEL_LCDC_INVFRAME_INVERTED;
-
-	switch (info->var.bits_per_pixel) {
-		case 1:	value |= ATMEL_LCDC_PIXELSIZE_1; break;
-		case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
-		case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
-		case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
-		case 15: /* fall through */
-		case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
-		case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
-		case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
-		default: BUG(); break;
-	}
-	dev_dbg(info->device, "  * LCDCON2 = %08lx\n", value);
-	lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
-
-	/* Vertical timing */
-	value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
-	value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
-	value |= info->var.lower_margin;
-	dev_dbg(info->device, "  * LCDTIM1 = %08lx\n", value);
-	lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
-
-	/* Horizontal timing */
-	value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
-	value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
-	value |= (info->var.left_margin - 1);
-	dev_dbg(info->device, "  * LCDTIM2 = %08lx\n", value);
-	lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
-
-	/* Horizontal value (aka line size) */
-	hozval_linesz = compute_hozval(sinfo, info->var.xres);
-
-	/* Display size */
-	value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
-	value |= info->var.yres - 1;
-	dev_dbg(info->device, "  * LCDFRMCFG = %08lx\n", value);
-	lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
-
-	/* FIFO Threshold: Use formula from data sheet */
-	value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
-	lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
-
-	/* Toggle LCD_MODE every frame */
-	lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
-
-	/* Disable all interrupts */
-	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-	/* Enable FIFO & DMA errors */
-	lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-
-	/* ...wait for DMA engine to become idle... */
-	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
-		msleep(10);
-
-	atmel_lcdfb_start(sinfo);
-
-	dev_dbg(info->device, "  * DONE\n");
-
-	return 0;
-}
-
-static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-/**
- *  	atmel_lcdfb_setcolreg - Optional function. Sets a color register.
- *      @regno: Which register in the CLUT we are programming
- *      @red: The red value which can be up to 16 bits wide
- *	@green: The green value which can be up to 16 bits wide
- *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- *
- *  	Set a single color register. The values supplied have a 16 bit
- *  	magnitude which needs to be scaled in this function for the hardware.
- *	Things to take into consideration are how many color registers, if
- *	any, are supported with the current color visual. With truecolor mode
- *	no color palettes are supported. Here a pseudo palette is created
- *	which we store the value in pseudo_palette in struct fb_info. For
- *	pseudocolor mode we have a limited color palette. To deal with this
- *	we can program what color is displayed for a particular pixel value.
- *	DirectColor is similar in that we can program each color field. If
- *	we have a static colormap we don't need to implement this function.
- *
- *	Returns negative errno on error, or zero on success. In an
- *	ideal world, this would have been the case, but as it turns
- *	out, the other drivers return 1 on failure, so that's what
- *	we're going to do.
- */
-static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
-			     unsigned int green, unsigned int blue,
-			     unsigned int transp, struct fb_info *info)
-{
-	struct atmel_lcdfb_info *sinfo = info->par;
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-	unsigned int val;
-	u32 *pal;
-	int ret = 1;
-
-	if (info->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green
-				      + 7471 * blue) >> 16;
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		if (regno < 16) {
-			pal = info->pseudo_palette;
-
-			val  = chan_to_field(red, &info->var.red);
-			val |= chan_to_field(green, &info->var.green);
-			val |= chan_to_field(blue, &info->var.blue);
-
-			pal[regno] = val;
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno < 256) {
-			if (sinfo->config->have_intensity_bit) {
-				/* old style I+BGR:555 */
-				val  = ((red   >> 11) & 0x001f);
-				val |= ((green >>  6) & 0x03e0);
-				val |= ((blue  >>  1) & 0x7c00);
-
-				/*
-				 * TODO: intensity bit. Maybe something like
-				 *   ~(red[10] ^ green[10] ^ blue[10]) & 1
-				 */
-			} else {
-				/* new style BGR:565 / RGB:565 */
-				if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-					val  = ((blue >> 11) & 0x001f);
-					val |= ((red  >>  0) & 0xf800);
-				} else {
-					val  = ((red  >> 11) & 0x001f);
-					val |= ((blue >>  0) & 0xf800);
-				}
-
-				val |= ((green >>  5) & 0x07e0);
-			}
-
-			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_MONO01:
-		if (regno < 2) {
-			val = (regno == 0) ? 0x00 : 0x1F;
-			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
-			ret = 0;
-		}
-		break;
-
-	}
-
-	return ret;
-}
-
-static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
-			       struct fb_info *info)
-{
-	dev_dbg(info->device, "%s\n", __func__);
-
-	atmel_lcdfb_update_dma(info, var);
-
-	return 0;
-}
-
-static int atmel_lcdfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct atmel_lcdfb_info *sinfo = info->par;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		atmel_lcdfb_start(sinfo);
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-		break;
-	case FB_BLANK_POWERDOWN:
-		atmel_lcdfb_stop(sinfo);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* let fbcon do a soft blank for us */
-	return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
-}
-
-static struct fb_ops atmel_lcdfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= atmel_lcdfb_check_var,
-	.fb_set_par	= atmel_lcdfb_set_par,
-	.fb_setcolreg	= atmel_lcdfb_setcolreg,
-	.fb_blank	= atmel_lcdfb_blank,
-	.fb_pan_display	= atmel_lcdfb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
-{
-	struct fb_info *info = dev_id;
-	struct atmel_lcdfb_info *sinfo = info->par;
-	u32 status;
-
-	status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
-	if (status & ATMEL_LCDC_UFLWI) {
-		dev_warn(info->device, "FIFO underflow %#x\n", status);
-		/* reset DMA and FIFO to avoid screen shifting */
-		schedule_work(&sinfo->task);
-	}
-	lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
-	return IRQ_HANDLED;
-}
-
-/*
- * LCD controller task (to reset the LCD)
- */
-static void atmel_lcdfb_task(struct work_struct *work)
-{
-	struct atmel_lcdfb_info *sinfo =
-		container_of(work, struct atmel_lcdfb_info, task);
-
-	atmel_lcdfb_reset(sinfo);
-}
-
-static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
-{
-	struct fb_info *info = sinfo->info;
-	int ret = 0;
-
-	info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
-
-	dev_info(info->device,
-	       "%luKiB frame buffer at %08lx (mapped at %p)\n",
-	       (unsigned long)info->fix.smem_len / 1024,
-	       (unsigned long)info->fix.smem_start,
-	       info->screen_base);
-
-	/* Allocate colormap */
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret < 0)
-		dev_err(info->device, "Alloc color map failed\n");
-
-	return ret;
-}
-
-static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
-{
-	clk_prepare_enable(sinfo->bus_clk);
-	clk_prepare_enable(sinfo->lcdc_clk);
-}
-
-static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
-{
-	clk_disable_unprepare(sinfo->bus_clk);
-	clk_disable_unprepare(sinfo->lcdc_clk);
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id atmel_lcdfb_dt_ids[] = {
-	{ .compatible = "atmel,at91sam9261-lcdc" , .data = &at91sam9261_config, },
-	{ .compatible = "atmel,at91sam9263-lcdc" , .data = &at91sam9263_config, },
-	{ .compatible = "atmel,at91sam9g10-lcdc" , .data = &at91sam9g10_config, },
-	{ .compatible = "atmel,at91sam9g45-lcdc" , .data = &at91sam9g45_config, },
-	{ .compatible = "atmel,at91sam9g45es-lcdc" , .data = &at91sam9g45es_config, },
-	{ .compatible = "atmel,at91sam9rl-lcdc" , .data = &at91sam9rl_config, },
-	{ .compatible = "atmel,at32ap-lcdc" , .data = &at32ap_config, },
-	{ /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, atmel_lcdfb_dt_ids);
-
-static const char *atmel_lcdfb_wiring_modes[] = {
-	[ATMEL_LCDC_WIRING_BGR]	= "BRG",
-	[ATMEL_LCDC_WIRING_RGB]	= "RGB",
-};
-
-const int atmel_lcdfb_get_of_wiring_modes(struct device_node *np)
-{
-	const char *mode;
-	int err, i;
-
-	err = of_property_read_string(np, "atmel,lcd-wiring-mode", &mode);
-	if (err < 0)
-		return ATMEL_LCDC_WIRING_BGR;
-
-	for (i = 0; i < ARRAY_SIZE(atmel_lcdfb_wiring_modes); i++)
-		if (!strcasecmp(mode, atmel_lcdfb_wiring_modes[i]))
-			return i;
-
-	return -ENODEV;
-}
-
-static void atmel_lcdfb_power_control_gpio(struct atmel_lcdfb_pdata *pdata, int on)
-{
-	struct atmel_lcdfb_power_ctrl_gpio *og;
-
-	list_for_each_entry(og, &pdata->pwr_gpios, list)
-		gpio_set_value(og->gpio, on);
-}
-
-static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
-{
-	struct fb_info *info = sinfo->info;
-	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
-	struct fb_var_screeninfo *var = &info->var;
-	struct device *dev = &sinfo->pdev->dev;
-	struct device_node *np =dev->of_node;
-	struct device_node *display_np;
-	struct device_node *timings_np;
-	struct display_timings *timings;
-	enum of_gpio_flags flags;
-	struct atmel_lcdfb_power_ctrl_gpio *og;
-	bool is_gpio_power = false;
-	int ret = -ENOENT;
-	int i, gpio;
-
-	sinfo->config = (struct atmel_lcdfb_config*)
-		of_match_device(atmel_lcdfb_dt_ids, dev)->data;
-
-	display_np = of_parse_phandle(np, "display", 0);
-	if (!display_np) {
-		dev_err(dev, "failed to find display phandle\n");
-		return -ENOENT;
-	}
-
-	ret = of_property_read_u32(display_np, "bits-per-pixel", &var->bits_per_pixel);
-	if (ret < 0) {
-		dev_err(dev, "failed to get property bits-per-pixel\n");
-		goto put_display_node;
-	}
-
-	ret = of_property_read_u32(display_np, "atmel,guard-time", &pdata->guard_time);
-	if (ret < 0) {
-		dev_err(dev, "failed to get property atmel,guard-time\n");
-		goto put_display_node;
-	}
-
-	ret = of_property_read_u32(display_np, "atmel,lcdcon2", &pdata->default_lcdcon2);
-	if (ret < 0) {
-		dev_err(dev, "failed to get property atmel,lcdcon2\n");
-		goto put_display_node;
-	}
-
-	ret = of_property_read_u32(display_np, "atmel,dmacon", &pdata->default_dmacon);
-	if (ret < 0) {
-		dev_err(dev, "failed to get property bits-per-pixel\n");
-		goto put_display_node;
-	}
-
-	ret = -ENOMEM;
-	for (i = 0; i < of_gpio_named_count(display_np, "atmel,power-control-gpio"); i++) {
-		gpio = of_get_named_gpio_flags(display_np, "atmel,power-control-gpio",
-					       i, &flags);
-		if (gpio < 0)
-			continue;
-
-		og = devm_kzalloc(dev, sizeof(*og), GFP_KERNEL);
-		if (!og)
-			goto put_display_node;
-
-		og->gpio = gpio;
-		og->active_low = flags & OF_GPIO_ACTIVE_LOW;
-		is_gpio_power = true;
-		ret = devm_gpio_request(dev, gpio, "lcd-power-control-gpio");
-		if (ret) {
-			dev_err(dev, "request gpio %d failed\n", gpio);
-			goto put_display_node;
-		}
-
-		ret = gpio_direction_output(gpio, og->active_low);
-		if (ret) {
-			dev_err(dev, "set direction output gpio %d failed\n", gpio);
-			goto put_display_node;
-		}
-	}
-
-	if (is_gpio_power)
-		pdata->atmel_lcdfb_power_control = atmel_lcdfb_power_control_gpio;
-
-	ret = atmel_lcdfb_get_of_wiring_modes(display_np);
-	if (ret < 0) {
-		dev_err(dev, "invalid atmel,lcd-wiring-mode\n");
-		goto put_display_node;
-	}
-	pdata->lcd_wiring_mode = ret;
-
-	pdata->lcdcon_is_backlight = of_property_read_bool(display_np, "atmel,lcdcon-backlight");
-
-	timings = of_get_display_timings(display_np);
-	if (!timings) {
-		dev_err(dev, "failed to get display timings\n");
-		goto put_display_node;
-	}
-
-	timings_np = of_find_node_by_name(display_np, "display-timings");
-	if (!timings_np) {
-		dev_err(dev, "failed to find display-timings node\n");
-		goto put_display_node;
-	}
-
-	for (i = 0; i < of_get_child_count(timings_np); i++) {
-		struct videomode vm;
-		struct fb_videomode fb_vm;
-
-		ret = videomode_from_timings(timings, &vm, i);
-		if (ret < 0)
-			goto put_timings_node;
-		ret = fb_videomode_from_videomode(&vm, &fb_vm);
-		if (ret < 0)
-			goto put_timings_node;
-
-		fb_add_videomode(&fb_vm, &info->modelist);
-	}
-
-	return 0;
-
-put_timings_node:
-	of_node_put(timings_np);
-put_display_node:
-	of_node_put(display_np);
-	return ret;
-}
-#else
-static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
-{
-	return 0;
-}
-#endif
-
-static int __init atmel_lcdfb_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct fb_info *info;
-	struct atmel_lcdfb_info *sinfo;
-	struct atmel_lcdfb_pdata *pdata = NULL;
-	struct resource *regs = NULL;
-	struct resource *map = NULL;
-	struct fb_modelist *modelist;
-	int ret;
-
-	dev_dbg(dev, "%s BEGIN\n", __func__);
-
-	ret = -ENOMEM;
-	info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
-	if (!info) {
-		dev_err(dev, "cannot allocate memory\n");
-		goto out;
-	}
-
-	sinfo = info->par;
-	sinfo->pdev = pdev;
-	sinfo->info = info;
-
-	INIT_LIST_HEAD(&info->modelist);
-
-	if (pdev->dev.of_node) {
-		ret = atmel_lcdfb_of_init(sinfo);
-		if (ret)
-			goto free_info;
-	} else if (dev_get_platdata(dev)) {
-		struct fb_monspecs *monspecs;
-		int i;
-
-		pdata = dev_get_platdata(dev);
-		monspecs = pdata->default_monspecs;
-		sinfo->pdata = *pdata;
-
-		for (i = 0; i < monspecs->modedb_len; i++)
-			fb_add_videomode(&monspecs->modedb[i], &info->modelist);
-
-		sinfo->config = atmel_lcdfb_get_config(pdev);
-
-		info->var.bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
-		memcpy(&info->monspecs, pdata->default_monspecs, sizeof(info->monspecs));
-	} else {
-		dev_err(dev, "cannot get default configuration\n");
-		goto free_info;
-	}
-
-	if (!sinfo->config)
-		goto free_info;
-
-	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
-	info->pseudo_palette = sinfo->pseudo_palette;
-	info->fbops = &atmel_lcdfb_ops;
-
-	info->fix = atmel_lcdfb_fix;
-	strcpy(info->fix.id, sinfo->pdev->name);
-
-	/* Enable LCDC Clocks */
-	sinfo->bus_clk = clk_get(dev, "hclk");
-	if (IS_ERR(sinfo->bus_clk)) {
-		ret = PTR_ERR(sinfo->bus_clk);
-		goto free_info;
-	}
-	sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
-	if (IS_ERR(sinfo->lcdc_clk)) {
-		ret = PTR_ERR(sinfo->lcdc_clk);
-		goto put_bus_clk;
-	}
-	atmel_lcdfb_start_clock(sinfo);
-
-	modelist = list_first_entry(&info->modelist,
-			struct fb_modelist, list);
-	fb_videomode_to_var(&info->var, &modelist->mode);
-
-	atmel_lcdfb_check_var(&info->var, info);
-
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!regs) {
-		dev_err(dev, "resources unusable\n");
-		ret = -ENXIO;
-		goto stop_clk;
-	}
-
-	sinfo->irq_base = platform_get_irq(pdev, 0);
-	if (sinfo->irq_base < 0) {
-		dev_err(dev, "unable to get irq\n");
-		ret = sinfo->irq_base;
-		goto stop_clk;
-	}
-
-	/* Initialize video memory */
-	map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (map) {
-		/* use a pre-allocated memory buffer */
-		info->fix.smem_start = map->start;
-		info->fix.smem_len = resource_size(map);
-		if (!request_mem_region(info->fix.smem_start,
-					info->fix.smem_len, pdev->name)) {
-			ret = -EBUSY;
-			goto stop_clk;
-		}
-
-		info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-		if (!info->screen_base) {
-			ret = -ENOMEM;
-			goto release_intmem;
-		}
-
-		/*
-		 * Don't clear the framebuffer -- someone may have set
-		 * up a splash image.
-		 */
-	} else {
-		/* allocate memory buffer */
-		ret = atmel_lcdfb_alloc_video_memory(sinfo);
-		if (ret < 0) {
-			dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
-			goto stop_clk;
-		}
-	}
-
-	/* LCDC registers */
-	info->fix.mmio_start = regs->start;
-	info->fix.mmio_len = resource_size(regs);
-
-	if (!request_mem_region(info->fix.mmio_start,
-				info->fix.mmio_len, pdev->name)) {
-		ret = -EBUSY;
-		goto free_fb;
-	}
-
-	sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
-	if (!sinfo->mmio) {
-		dev_err(dev, "cannot map LCDC registers\n");
-		ret = -ENOMEM;
-		goto release_mem;
-	}
-
-	/* Initialize PWM for contrast or backlight ("off") */
-	init_contrast(sinfo);
-
-	/* interrupt */
-	ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
-	if (ret) {
-		dev_err(dev, "request_irq failed: %d\n", ret);
-		goto unmap_mmio;
-	}
-
-	/* Some operations on the LCDC might sleep and
-	 * require a preemptible task context */
-	INIT_WORK(&sinfo->task, atmel_lcdfb_task);
-
-	ret = atmel_lcdfb_init_fbinfo(sinfo);
-	if (ret < 0) {
-		dev_err(dev, "init fbinfo failed: %d\n", ret);
-		goto unregister_irqs;
-	}
-
-	ret = atmel_lcdfb_set_par(info);
-	if (ret < 0) {
-		dev_err(dev, "set par failed: %d\n", ret);
-		goto unregister_irqs;
-	}
-
-	dev_set_drvdata(dev, info);
-
-	/*
-	 * Tell the world that we're ready to go
-	 */
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		dev_err(dev, "failed to register framebuffer device: %d\n", ret);
-		goto reset_drvdata;
-	}
-
-	/* Power up the LCDC screen */
-	atmel_lcdfb_power_control(sinfo, 1);
-
-	dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
-		       info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
-
-	return 0;
-
-reset_drvdata:
-	dev_set_drvdata(dev, NULL);
-	fb_dealloc_cmap(&info->cmap);
-unregister_irqs:
-	cancel_work_sync(&sinfo->task);
-	free_irq(sinfo->irq_base, info);
-unmap_mmio:
-	exit_backlight(sinfo);
-	iounmap(sinfo->mmio);
-release_mem:
- 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-free_fb:
-	if (map)
-		iounmap(info->screen_base);
-	else
-		atmel_lcdfb_free_video_memory(sinfo);
-
-release_intmem:
-	if (map)
-		release_mem_region(info->fix.smem_start, info->fix.smem_len);
-stop_clk:
-	atmel_lcdfb_stop_clock(sinfo);
-	clk_put(sinfo->lcdc_clk);
-put_bus_clk:
-	clk_put(sinfo->bus_clk);
-free_info:
-	framebuffer_release(info);
-out:
-	dev_dbg(dev, "%s FAILED\n", __func__);
-	return ret;
-}
-
-static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct atmel_lcdfb_info *sinfo;
-	struct atmel_lcdfb_pdata *pdata;
-
-	if (!info || !info->par)
-		return 0;
-	sinfo = info->par;
-	pdata = &sinfo->pdata;
-
-	cancel_work_sync(&sinfo->task);
-	exit_backlight(sinfo);
-	atmel_lcdfb_power_control(sinfo, 0);
-	unregister_framebuffer(info);
-	atmel_lcdfb_stop_clock(sinfo);
-	clk_put(sinfo->lcdc_clk);
-	clk_put(sinfo->bus_clk);
-	fb_dealloc_cmap(&info->cmap);
-	free_irq(sinfo->irq_base, info);
-	iounmap(sinfo->mmio);
- 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-	if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
-		iounmap(info->screen_base);
-		release_mem_region(info->fix.smem_start, info->fix.smem_len);
-	} else {
-		atmel_lcdfb_free_video_memory(sinfo);
-	}
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct atmel_lcdfb_info *sinfo = info->par;
-
-	/*
-	 * We don't want to handle interrupts while the clock is
-	 * stopped. It may take forever.
-	 */
-	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
-
-	sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
-	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
-	atmel_lcdfb_power_control(sinfo, 0);
-	atmel_lcdfb_stop(sinfo);
-	atmel_lcdfb_stop_clock(sinfo);
-
-	return 0;
-}
-
-static int atmel_lcdfb_resume(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct atmel_lcdfb_info *sinfo = info->par;
-
-	atmel_lcdfb_start_clock(sinfo);
-	atmel_lcdfb_start(sinfo);
-	atmel_lcdfb_power_control(sinfo, 1);
-	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
-
-	/* Enable FIFO & DMA errors */
-	lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
-			| ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
-
-	return 0;
-}
-
-#else
-#define atmel_lcdfb_suspend	NULL
-#define atmel_lcdfb_resume	NULL
-#endif
-
-static struct platform_driver atmel_lcdfb_driver = {
-	.remove		= __exit_p(atmel_lcdfb_remove),
-	.suspend	= atmel_lcdfb_suspend,
-	.resume		= atmel_lcdfb_resume,
-	.id_table	= atmel_lcdfb_devtypes,
-	.driver		= {
-		.name	= "atmel_lcdfb",
-		.owner	= THIS_MODULE,
-		.of_match_table	= of_match_ptr(atmel_lcdfb_dt_ids),
-	},
-};
-
-module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe);
-
-MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
-MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
deleted file mode 100644
index a6cc0e9ec790..000000000000
--- a/drivers/video/aty/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-obj-$(CONFIG_FB_ATY) += atyfb.o
-obj-$(CONFIG_FB_ATY128) += aty128fb.o
-obj-$(CONFIG_FB_RADEON) += radeonfb.o
-
-atyfb-y				:= atyfb_base.o mach64_accel.o mach64_cursor.o
-atyfb-$(CONFIG_FB_ATY_GX)	+= mach64_gx.o
-atyfb-$(CONFIG_FB_ATY_CT)	+= mach64_ct.o
-
-atyfb-objs			:= $(atyfb-y)
-
-radeonfb-y			:= radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o
-radeonfb-$(CONFIG_FB_RADEON_I2C)	+= radeon_i2c.o
-radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT)	+= radeon_backlight.o
-radeonfb-objs			:= $(radeonfb-y)
-
diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h
deleted file mode 100644
index 3e9d28bcd9f8..000000000000
--- a/drivers/video/aty/ati_ids.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * ATI PCI IDs from XFree86, kept here to make sync'ing with
- * XFree much simpler. Currently, this list is only used by
- * radeonfb
- */
-
-#define PCI_CHIP_RV380_3150             0x3150
-#define PCI_CHIP_RV380_3151             0x3151
-#define PCI_CHIP_RV380_3152             0x3152
-#define PCI_CHIP_RV380_3153             0x3153
-#define PCI_CHIP_RV380_3154             0x3154
-#define PCI_CHIP_RV380_3156             0x3156
-#define PCI_CHIP_RV380_3E50             0x3E50
-#define PCI_CHIP_RV380_3E51             0x3E51
-#define PCI_CHIP_RV380_3E52             0x3E52
-#define PCI_CHIP_RV380_3E53             0x3E53
-#define PCI_CHIP_RV380_3E54             0x3E54
-#define PCI_CHIP_RV380_3E56             0x3E56
-#define PCI_CHIP_RS100_4136		0x4136
-#define PCI_CHIP_RS200_4137		0x4137
-#define PCI_CHIP_R300_AD		0x4144
-#define PCI_CHIP_R300_AE		0x4145
-#define PCI_CHIP_R300_AF		0x4146
-#define PCI_CHIP_R300_AG		0x4147
-#define PCI_CHIP_R350_AH                0x4148
-#define PCI_CHIP_R350_AI                0x4149
-#define PCI_CHIP_R350_AJ                0x414A
-#define PCI_CHIP_R350_AK                0x414B
-#define PCI_CHIP_RV350_AP               0x4150
-#define PCI_CHIP_RV350_AQ               0x4151
-#define PCI_CHIP_RV360_AR               0x4152
-#define PCI_CHIP_RV350_AS               0x4153
-#define PCI_CHIP_RV350_AT               0x4154
-#define PCI_CHIP_RV350_AV               0x4156
-#define PCI_CHIP_MACH32			0x4158
-#define PCI_CHIP_RS250_4237		0x4237
-#define PCI_CHIP_R200_BB		0x4242
-#define PCI_CHIP_R200_BC		0x4243
-#define PCI_CHIP_RS100_4336		0x4336
-#define PCI_CHIP_RS200_4337		0x4337
-#define PCI_CHIP_MACH64CT		0x4354
-#define PCI_CHIP_MACH64CX		0x4358
-#define PCI_CHIP_RS250_4437		0x4437
-#define PCI_CHIP_MACH64ET		0x4554
-#define PCI_CHIP_MACH64GB		0x4742
-#define PCI_CHIP_MACH64GD		0x4744
-#define PCI_CHIP_MACH64GI		0x4749
-#define PCI_CHIP_MACH64GL		0x474C
-#define PCI_CHIP_MACH64GM		0x474D
-#define PCI_CHIP_MACH64GN		0x474E
-#define PCI_CHIP_MACH64GO		0x474F
-#define PCI_CHIP_MACH64GP		0x4750
-#define PCI_CHIP_MACH64GQ		0x4751
-#define PCI_CHIP_MACH64GR		0x4752
-#define PCI_CHIP_MACH64GS		0x4753
-#define PCI_CHIP_MACH64GT		0x4754
-#define PCI_CHIP_MACH64GU		0x4755
-#define PCI_CHIP_MACH64GV		0x4756
-#define PCI_CHIP_MACH64GW		0x4757
-#define PCI_CHIP_MACH64GX		0x4758
-#define PCI_CHIP_MACH64GY		0x4759
-#define PCI_CHIP_MACH64GZ		0x475A
-#define PCI_CHIP_RV250_Id		0x4964
-#define PCI_CHIP_RV250_Ie		0x4965
-#define PCI_CHIP_RV250_If		0x4966
-#define PCI_CHIP_RV250_Ig		0x4967
-#define PCI_CHIP_R420_JH                0x4A48
-#define PCI_CHIP_R420_JI                0x4A49
-#define PCI_CHIP_R420_JJ                0x4A4A
-#define PCI_CHIP_R420_JK                0x4A4B
-#define PCI_CHIP_R420_JL                0x4A4C
-#define PCI_CHIP_R420_JM                0x4A4D
-#define PCI_CHIP_R420_JN                0x4A4E
-#define PCI_CHIP_R420_JP                0x4A50
-#define PCI_CHIP_MACH64LB		0x4C42
-#define PCI_CHIP_MACH64LD		0x4C44
-#define PCI_CHIP_RAGE128LE		0x4C45
-#define PCI_CHIP_RAGE128LF		0x4C46
-#define PCI_CHIP_MACH64LG		0x4C47
-#define PCI_CHIP_MACH64LI		0x4C49
-#define PCI_CHIP_MACH64LM		0x4C4D
-#define PCI_CHIP_MACH64LN		0x4C4E
-#define PCI_CHIP_MACH64LP		0x4C50
-#define PCI_CHIP_MACH64LQ		0x4C51
-#define PCI_CHIP_MACH64LR		0x4C52
-#define PCI_CHIP_MACH64LS		0x4C53
-#define PCI_CHIP_MACH64LT		0x4C54
-#define PCI_CHIP_RADEON_LW		0x4C57
-#define PCI_CHIP_RADEON_LX		0x4C58
-#define PCI_CHIP_RADEON_LY		0x4C59
-#define PCI_CHIP_RADEON_LZ		0x4C5A
-#define PCI_CHIP_RV250_Ld		0x4C64
-#define PCI_CHIP_RV250_Le		0x4C65
-#define PCI_CHIP_RV250_Lf		0x4C66
-#define PCI_CHIP_RV250_Lg		0x4C67
-#define PCI_CHIP_RV250_Ln		0x4C6E
-#define PCI_CHIP_RAGE128MF		0x4D46
-#define PCI_CHIP_RAGE128ML		0x4D4C
-#define PCI_CHIP_R300_ND		0x4E44
-#define PCI_CHIP_R300_NE		0x4E45
-#define PCI_CHIP_R300_NF		0x4E46
-#define PCI_CHIP_R300_NG		0x4E47
-#define PCI_CHIP_R350_NH                0x4E48  
-#define PCI_CHIP_R350_NI                0x4E49  
-#define PCI_CHIP_R360_NJ                0x4E4A  
-#define PCI_CHIP_R350_NK                0x4E4B  
-#define PCI_CHIP_RV350_NP               0x4E50
-#define PCI_CHIP_RV350_NQ               0x4E51
-#define PCI_CHIP_RV350_NR               0x4E52
-#define PCI_CHIP_RV350_NS               0x4E53
-#define PCI_CHIP_RV350_NT               0x4E54
-#define PCI_CHIP_RV350_NV               0x4E56
-#define PCI_CHIP_RAGE128PA		0x5041
-#define PCI_CHIP_RAGE128PB		0x5042
-#define PCI_CHIP_RAGE128PC		0x5043
-#define PCI_CHIP_RAGE128PD		0x5044
-#define PCI_CHIP_RAGE128PE		0x5045
-#define PCI_CHIP_RAGE128PF		0x5046
-#define PCI_CHIP_RAGE128PG		0x5047
-#define PCI_CHIP_RAGE128PH		0x5048
-#define PCI_CHIP_RAGE128PI		0x5049
-#define PCI_CHIP_RAGE128PJ		0x504A
-#define PCI_CHIP_RAGE128PK		0x504B
-#define PCI_CHIP_RAGE128PL		0x504C
-#define PCI_CHIP_RAGE128PM		0x504D
-#define PCI_CHIP_RAGE128PN		0x504E
-#define PCI_CHIP_RAGE128PO		0x504F
-#define PCI_CHIP_RAGE128PP		0x5050
-#define PCI_CHIP_RAGE128PQ		0x5051
-#define PCI_CHIP_RAGE128PR		0x5052
-#define PCI_CHIP_RAGE128PS		0x5053
-#define PCI_CHIP_RAGE128PT		0x5054
-#define PCI_CHIP_RAGE128PU		0x5055
-#define PCI_CHIP_RAGE128PV		0x5056
-#define PCI_CHIP_RAGE128PW		0x5057
-#define PCI_CHIP_RAGE128PX		0x5058
-#define PCI_CHIP_RADEON_QD		0x5144
-#define PCI_CHIP_RADEON_QE		0x5145
-#define PCI_CHIP_RADEON_QF		0x5146
-#define PCI_CHIP_RADEON_QG		0x5147
-#define PCI_CHIP_R200_QH		0x5148
-#define PCI_CHIP_R200_QI		0x5149
-#define PCI_CHIP_R200_QJ		0x514A
-#define PCI_CHIP_R200_QK		0x514B
-#define PCI_CHIP_R200_QL		0x514C
-#define PCI_CHIP_R200_QM		0x514D
-#define PCI_CHIP_R200_QN		0x514E
-#define PCI_CHIP_R200_QO		0x514F
-#define PCI_CHIP_RV200_QW		0x5157
-#define PCI_CHIP_RV200_QX		0x5158
-#define PCI_CHIP_RV100_QY		0x5159
-#define PCI_CHIP_RV100_QZ		0x515A
-#define PCI_CHIP_RN50			0x515E
-#define PCI_CHIP_RAGE128RE		0x5245
-#define PCI_CHIP_RAGE128RF		0x5246
-#define PCI_CHIP_RAGE128RG		0x5247
-#define PCI_CHIP_RAGE128RK		0x524B
-#define PCI_CHIP_RAGE128RL		0x524C
-#define PCI_CHIP_RAGE128SE		0x5345
-#define PCI_CHIP_RAGE128SF		0x5346
-#define PCI_CHIP_RAGE128SG		0x5347
-#define PCI_CHIP_RAGE128SH		0x5348
-#define PCI_CHIP_RAGE128SK		0x534B
-#define PCI_CHIP_RAGE128SL		0x534C
-#define PCI_CHIP_RAGE128SM		0x534D
-#define PCI_CHIP_RAGE128SN		0x534E
-#define PCI_CHIP_RAGE128TF		0x5446
-#define PCI_CHIP_RAGE128TL		0x544C
-#define PCI_CHIP_RAGE128TR		0x5452
-#define PCI_CHIP_RAGE128TS		0x5453
-#define PCI_CHIP_RAGE128TT		0x5454
-#define PCI_CHIP_RAGE128TU		0x5455
-#define PCI_CHIP_RV370_5460             0x5460
-#define PCI_CHIP_RV370_5461             0x5461
-#define PCI_CHIP_RV370_5462             0x5462
-#define PCI_CHIP_RV370_5463             0x5463
-#define PCI_CHIP_RV370_5464             0x5464
-#define PCI_CHIP_RV370_5465             0x5465
-#define PCI_CHIP_RV370_5466             0x5466
-#define PCI_CHIP_RV370_5467             0x5467
-#define PCI_CHIP_R423_UH                0x5548
-#define PCI_CHIP_R423_UI                0x5549
-#define PCI_CHIP_R423_UJ                0x554A
-#define PCI_CHIP_R423_UK                0x554B
-#define PCI_CHIP_R423_UQ                0x5551
-#define PCI_CHIP_R423_UR                0x5552
-#define PCI_CHIP_R423_UT                0x5554
-#define PCI_CHIP_MACH64VT		0x5654
-#define PCI_CHIP_MACH64VU		0x5655
-#define PCI_CHIP_MACH64VV		0x5656
-#define PCI_CHIP_RC410_5A62             0x5A62
-#define PCI_CHIP_RS300_5834		0x5834
-#define PCI_CHIP_RS300_5835		0x5835
-#define PCI_CHIP_RS300_5836		0x5836
-#define PCI_CHIP_RS300_5837		0x5837
-#define PCI_CHIP_RS480_5955             0x5955
-#define PCI_CHIP_RV280_5960		0x5960
-#define PCI_CHIP_RV280_5961		0x5961
-#define PCI_CHIP_RV280_5962		0x5962
-#define PCI_CHIP_RV280_5964		0x5964
-#define PCI_CHIP_RS482_5975		0x5975
-#define PCI_CHIP_RV370_5B60             0x5B60
-#define PCI_CHIP_RV370_5B61             0x5B61
-#define PCI_CHIP_RV370_5B62             0x5B62
-#define PCI_CHIP_RV370_5B63             0x5B63
-#define PCI_CHIP_RV370_5B64             0x5B64
-#define PCI_CHIP_RV370_5B65             0x5B65
-#define PCI_CHIP_RV370_5B66             0x5B66
-#define PCI_CHIP_RV370_5B67             0x5B67
-#define PCI_CHIP_RV280_5C61		0x5C61
-#define PCI_CHIP_RV280_5C63		0x5C63
-#define PCI_CHIP_R423_5D57              0x5D57
-#define PCI_CHIP_RS350_7834             0x7834
-#define PCI_CHIP_RS350_7835             0x7835
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
deleted file mode 100644
index 52108be69e77..000000000000
--- a/drivers/video/aty/aty128fb.c
+++ /dev/null
@@ -1,2591 +0,0 @@
-/* $Id: aty128fb.c,v 1.1.1.1.36.1 1999/12/11 09:03:05 Exp $
- *  linux/drivers/video/aty128fb.c -- Frame buffer device for ATI Rage128
- *
- *  Copyright (C) 1999-2003, Brad Douglas <brad@neruo.com>
- *  Copyright (C) 1999, Anthony Tong <atong@uiuc.edu>
- *
- *                Ani Joshi / Jeff Garzik
- *                      - Code cleanup
- *
- *                Michel Danzer <michdaen@iiic.ethz.ch>
- *                      - 15/16 bit cleanup
- *                      - fix panning
- *
- *                Benjamin Herrenschmidt
- *                      - pmac-specific PM stuff
- *			- various fixes & cleanups
- *
- *                Andreas Hundt <andi@convergence.de>
- *                      - FB_ACTIVATE fixes
- *
- *		  Paul Mackerras <paulus@samba.org>
- *			- Convert to new framebuffer API,
- *			  fix colormap setting at 16 bits/pixel (565)
- *
- *		  Paul Mundt 
- *		  	- PCI hotplug
- *
- *		  Jon Smirl <jonsmirl@yahoo.com>
- * 			- PCI ID update
- * 			- replace ROM BIOS search
- *
- *  Based off of Geert's atyfb.c and vfb.c.
- *
- *  TODO:
- *		- monitor sensing (DDC)
- *              - virtual display
- *		- other platform support (only ppc/x86 supported)
- *		- hardware cursor support
- *
- *    Please cc: your patches to brad@neruo.com.
- */
-
-/*
- * A special note of gratitude to ATI's devrel for providing documentation,
- * example code and hardware. Thanks Nitya.	-atong and brad
- */
-
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/console.h>
-#include <linux/backlight.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include "../macmodes.h"
-#endif
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
-#ifdef CONFIG_BOOTX_TEXT
-#include <asm/btext.h>
-#endif /* CONFIG_BOOTX_TEXT */
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/aty128.h>
-
-/* Debug flag */
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt, args...) \
-	printk(KERN_DEBUG "aty128fb: %s " fmt, __func__, ##args);
-#else
-#define DBG(fmt, args...)
-#endif
-
-#ifndef CONFIG_PPC_PMAC
-/* default mode */
-static struct fb_var_screeninfo default_var = {
-	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-	640, 480, 640, 480, 0, 0, 8, 0,
-	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
-
-#else /* CONFIG_PPC_PMAC */
-/* default to 1024x768 at 75Hz on PPC - this will work
- * on the iMac, the usual 640x480 @ 60Hz doesn't. */
-static struct fb_var_screeninfo default_var = {
-	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
-	1024, 768, 1024, 768, 0, 0, 8, 0,
-	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	0, 0, -1, -1, 0, 12699, 160, 32, 28, 1, 96, 3,
-	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	FB_VMODE_NONINTERLACED
-};
-#endif /* CONFIG_PPC_PMAC */
-
-/* default modedb mode */
-/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
-static struct fb_videomode defaultmode = {
-	.refresh =	60,
-	.xres =		640,
-	.yres =		480,
-	.pixclock =	39722,
-	.left_margin =	48,
-	.right_margin =	16,
-	.upper_margin =	33,
-	.lower_margin =	10,
-	.hsync_len =	96,
-	.vsync_len =	2,
-	.sync =		0,
-	.vmode =	FB_VMODE_NONINTERLACED
-};
-
-/* Chip generations */
-enum {
-	rage_128,
-	rage_128_pci,
-	rage_128_pro,
-	rage_128_pro_pci,
-	rage_M3,
-	rage_M3_pci,
-	rage_M4,
-	rage_128_ultra,
-};
-
-/* Must match above enum */
-static char * const r128_family[] = {
-	"AGP",
-	"PCI",
-	"PRO AGP",
-	"PRO PCI",
-	"M3 AGP",
-	"M3 PCI",
-	"M4 AGP",
-	"Ultra AGP",
-};
-
-/*
- * PCI driver prototypes
- */
-static int aty128_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent);
-static void aty128_remove(struct pci_dev *pdev);
-static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-static int aty128_pci_resume(struct pci_dev *pdev);
-static int aty128_do_resume(struct pci_dev *pdev);
-
-/* supported Rage128 chipsets */
-static struct pci_device_id aty128_pci_tbl[] = {
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3_pci },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LF,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_MF,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_ML,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PA,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PB,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PC,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PD,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PE,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PG,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PH,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PI,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PJ,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PK,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PM,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PN,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PP,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PQ,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PS,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PT,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PU,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PV,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PW,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PX,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RG,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SE,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SF,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SG,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SH,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SK,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SM,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SN,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TF,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TS,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TT,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
-	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TU,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, aty128_pci_tbl);
-
-static struct pci_driver aty128fb_driver = {
-	.name		= "aty128fb",
-	.id_table	= aty128_pci_tbl,
-	.probe		= aty128_probe,
-	.remove		= aty128_remove,
-	.suspend	= aty128_pci_suspend,
-	.resume		= aty128_pci_resume,
-};
-
-/* packed BIOS settings */
-#ifndef CONFIG_PPC
-typedef struct {
-	u8 clock_chip_type;
-	u8 struct_size;
-	u8 accelerator_entry;
-	u8 VGA_entry;
-	u16 VGA_table_offset;
-	u16 POST_table_offset;
-	u16 XCLK;
-	u16 MCLK;
-	u8 num_PLL_blocks;
-	u8 size_PLL_blocks;
-	u16 PCLK_ref_freq;
-	u16 PCLK_ref_divider;
-	u32 PCLK_min_freq;
-	u32 PCLK_max_freq;
-	u16 MCLK_ref_freq;
-	u16 MCLK_ref_divider;
-	u32 MCLK_min_freq;
-	u32 MCLK_max_freq;
-	u16 XCLK_ref_freq;
-	u16 XCLK_ref_divider;
-	u32 XCLK_min_freq;
-	u32 XCLK_max_freq;
-} __attribute__ ((packed)) PLL_BLOCK;
-#endif /* !CONFIG_PPC */
-
-/* onboard memory information */
-struct aty128_meminfo {
-	u8 ML;
-	u8 MB;
-	u8 Trcd;
-	u8 Trp;
-	u8 Twr;
-	u8 CL;
-	u8 Tr2w;
-	u8 LoopLatency;
-	u8 DspOn;
-	u8 Rloop;
-	const char *name;
-};
-
-/* various memory configurations */
-static const struct aty128_meminfo sdr_128   =
-	{ 4, 4, 3, 3, 1, 3, 1, 16, 30, 16, "128-bit SDR SGRAM (1:1)" };
-static const struct aty128_meminfo sdr_64    =
-	{ 4, 8, 3, 3, 1, 3, 1, 17, 46, 17, "64-bit SDR SGRAM (1:1)" };
-static const struct aty128_meminfo sdr_sgram =
-	{ 4, 4, 1, 2, 1, 2, 1, 16, 24, 16, "64-bit SDR SGRAM (2:1)" };
-static const struct aty128_meminfo ddr_sgram =
-	{ 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
-
-static struct fb_fix_screeninfo aty128fb_fix = {
-	.id		= "ATY Rage128",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep	= 8,
-	.ypanstep	= 1,
-	.mmio_len	= 0x2000,
-	.accel		= FB_ACCEL_ATI_RAGE128,
-};
-
-static char *mode_option = NULL;
-
-#ifdef CONFIG_PPC_PMAC
-static int default_vmode = VMODE_1024_768_60;
-static int default_cmode = CMODE_8;
-#endif
-
-static int default_crt_on = 0;
-static int default_lcd_on = 1;
-
-#ifdef CONFIG_MTRR
-static bool mtrr = true;
-#endif
-
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight = 1;
-#else
-static int backlight = 0;
-#endif
-#endif
-
-/* PLL constants */
-struct aty128_constants {
-	u32 ref_clk;
-	u32 ppll_min;
-	u32 ppll_max;
-	u32 ref_divider;
-	u32 xclk;
-	u32 fifo_width;
-	u32 fifo_depth;
-};
-
-struct aty128_crtc {
-	u32 gen_cntl;
-	u32 h_total, h_sync_strt_wid;
-	u32 v_total, v_sync_strt_wid;
-	u32 pitch;
-	u32 offset, offset_cntl;
-	u32 xoffset, yoffset;
-	u32 vxres, vyres;
-	u32 depth, bpp;
-};
-
-struct aty128_pll {
-	u32 post_divider;
-	u32 feedback_divider;
-	u32 vclk;
-};
-
-struct aty128_ddafifo {
-	u32 dda_config;
-	u32 dda_on_off;
-};
-
-/* register values for a specific mode */
-struct aty128fb_par {
-	struct aty128_crtc crtc;
-	struct aty128_pll pll;
-	struct aty128_ddafifo fifo_reg;
-	u32 accel_flags;
-	struct aty128_constants constants;  /* PLL and others      */
-	void __iomem *regbase;              /* remapped mmio       */
-	u32 vram_size;                      /* onboard video ram   */
-	int chip_gen;
-	const struct aty128_meminfo *mem;   /* onboard mem info    */
-#ifdef CONFIG_MTRR
-	struct { int vram; int vram_valid; } mtrr;
-#endif
-	int blitter_may_be_busy;
-	int fifo_slots;                 /* free slots in FIFO (64 max) */
-
-	int crt_on, lcd_on;
-	struct pci_dev *pdev;
-	struct fb_info *next;
-	int	asleep;
-	int	lock_blank;
-
-	u8	red[32];		/* see aty128fb_setcolreg */
-	u8	green[64];
-	u8	blue[32];
-	u32	pseudo_palette[16];	/* used for TRUECOLOR */
-};
-
-
-#define round_div(n, d) ((n+(d/2))/d)
-
-static int aty128fb_check_var(struct fb_var_screeninfo *var,
-			      struct fb_info *info);
-static int aty128fb_set_par(struct fb_info *info);
-static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			      u_int transp, struct fb_info *info);
-static int aty128fb_pan_display(struct fb_var_screeninfo *var,
-			   struct fb_info *fb);
-static int aty128fb_blank(int blank, struct fb_info *fb);
-static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg);
-static int aty128fb_sync(struct fb_info *info);
-
-    /*
-     *  Internal routines
-     */
-
-static int aty128_encode_var(struct fb_var_screeninfo *var,
-                             const struct aty128fb_par *par);
-static int aty128_decode_var(struct fb_var_screeninfo *var,
-                             struct aty128fb_par *par);
-#if 0
-static void aty128_get_pllinfo(struct aty128fb_par *par, void __iomem *bios);
-static void __iomem *aty128_map_ROM(struct pci_dev *pdev,
-				    const struct aty128fb_par *par);
-#endif
-static void aty128_timings(struct aty128fb_par *par);
-static void aty128_init_engine(struct aty128fb_par *par);
-static void aty128_reset_engine(const struct aty128fb_par *par);
-static void aty128_flush_pixel_cache(const struct aty128fb_par *par);
-static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par);
-static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
-static void wait_for_idle(struct aty128fb_par *par);
-static u32 depth_to_dst(u32 depth);
-
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-static void aty128_bl_set_power(struct fb_info *info, int power);
-#endif
-
-#define BIOS_IN8(v)  	(readb(bios + (v)))
-#define BIOS_IN16(v) 	(readb(bios + (v)) | \
-			  (readb(bios + (v) + 1) << 8))
-#define BIOS_IN32(v) 	(readb(bios + (v)) | \
-			  (readb(bios + (v) + 1) << 8) | \
-			  (readb(bios + (v) + 2) << 16) | \
-			  (readb(bios + (v) + 3) << 24))
-
-
-static struct fb_ops aty128fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= aty128fb_check_var,
-	.fb_set_par	= aty128fb_set_par,
-	.fb_setcolreg	= aty128fb_setcolreg,
-	.fb_pan_display = aty128fb_pan_display,
-	.fb_blank	= aty128fb_blank,
-	.fb_ioctl	= aty128fb_ioctl,
-	.fb_sync	= aty128fb_sync,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-    /*
-     * Functions to read from/write to the mmio registers
-     *	- endian conversions may possibly be avoided by
-     *    using the other register aperture. TODO.
-     */
-static inline u32 _aty_ld_le32(volatile unsigned int regindex, 
-			       const struct aty128fb_par *par)
-{
-	return readl (par->regbase + regindex);
-}
-
-static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, 
-				const struct aty128fb_par *par)
-{
-	writel (val, par->regbase + regindex);
-}
-
-static inline u8 _aty_ld_8(unsigned int regindex,
-			   const struct aty128fb_par *par)
-{
-	return readb (par->regbase + regindex);
-}
-
-static inline void _aty_st_8(unsigned int regindex, u8 val,
-			     const struct aty128fb_par *par)
-{
-	writeb (val, par->regbase + regindex);
-}
-
-#define aty_ld_le32(regindex)		_aty_ld_le32(regindex, par)
-#define aty_st_le32(regindex, val)	_aty_st_le32(regindex, val, par)
-#define aty_ld_8(regindex)		_aty_ld_8(regindex, par)
-#define aty_st_8(regindex, val)		_aty_st_8(regindex, val, par)
-
-    /*
-     * Functions to read from/write to the pll registers
-     */
-
-#define aty_ld_pll(pll_index)		_aty_ld_pll(pll_index, par)
-#define aty_st_pll(pll_index, val)	_aty_st_pll(pll_index, val, par)
-
-
-static u32 _aty_ld_pll(unsigned int pll_index,
-		       const struct aty128fb_par *par)
-{       
-	aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F);
-	return aty_ld_le32(CLOCK_CNTL_DATA);
-}
-
-    
-static void _aty_st_pll(unsigned int pll_index, u32 val,
-			const struct aty128fb_par *par)
-{
-	aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x3F) | PLL_WR_EN);
-	aty_st_le32(CLOCK_CNTL_DATA, val);
-}
-
-
-/* return true when the PLL has completed an atomic update */
-static int aty_pll_readupdate(const struct aty128fb_par *par)
-{
-	return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
-}
-
-
-static void aty_pll_wait_readupdate(const struct aty128fb_par *par)
-{
-	unsigned long timeout = jiffies + HZ/100; // should be more than enough
-	int reset = 1;
-
-	while (time_before(jiffies, timeout))
-		if (aty_pll_readupdate(par)) {
-			reset = 0;
-			break;
-		}
-
-	if (reset)	/* reset engine?? */
-		printk(KERN_DEBUG "aty128fb: PLL write timeout!\n");
-}
-
-
-/* tell PLL to update */
-static void aty_pll_writeupdate(const struct aty128fb_par *par)
-{
-	aty_pll_wait_readupdate(par);
-
-	aty_st_pll(PPLL_REF_DIV,
-		   aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W);
-}
-
-
-/* write to the scratch register to test r/w functionality */
-static int register_test(const struct aty128fb_par *par)
-{
-	u32 val;
-	int flag = 0;
-
-	val = aty_ld_le32(BIOS_0_SCRATCH);
-
-	aty_st_le32(BIOS_0_SCRATCH, 0x55555555);
-	if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) {
-		aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA);
-
-		if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA)
-			flag = 1; 
-	}
-
-	aty_st_le32(BIOS_0_SCRATCH, val);	// restore value
-	return flag;
-}
-
-
-/*
- * Accelerator engine functions
- */
-static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par)
-{
-	int i;
-
-	for (;;) {
-		for (i = 0; i < 2000000; i++) {
-			par->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
-			if (par->fifo_slots >= entries)
-				return;
-		}
-		aty128_reset_engine(par);
-	}
-}
-
-
-static void wait_for_idle(struct aty128fb_par *par)
-{
-	int i;
-
-	do_wait_for_fifo(64, par);
-
-	for (;;) {
-		for (i = 0; i < 2000000; i++) {
-			if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) {
-				aty128_flush_pixel_cache(par);
-				par->blitter_may_be_busy = 0;
-				return;
-			}
-		}
-		aty128_reset_engine(par);
-	}
-}
-
-
-static void wait_for_fifo(u16 entries, struct aty128fb_par *par)
-{
-	if (par->fifo_slots < entries)
-		do_wait_for_fifo(64, par);
-	par->fifo_slots -= entries;
-}
-
-
-static void aty128_flush_pixel_cache(const struct aty128fb_par *par)
-{
-	int i;
-	u32 tmp;
-
-	tmp = aty_ld_le32(PC_NGUI_CTLSTAT);
-	tmp &= ~(0x00ff);
-	tmp |= 0x00ff;
-	aty_st_le32(PC_NGUI_CTLSTAT, tmp);
-
-	for (i = 0; i < 2000000; i++)
-		if (!(aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY))
-			break;
-}
-
-
-static void aty128_reset_engine(const struct aty128fb_par *par)
-{
-	u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
-
-	aty128_flush_pixel_cache(par);
-
-	clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX);
-	mclk_cntl = aty_ld_pll(MCLK_CNTL);
-
-	aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000);
-
-	gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL);
-	aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
-	aty_ld_le32(GEN_RESET_CNTL);
-	aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI));
-	aty_ld_le32(GEN_RESET_CNTL);
-
-	aty_st_pll(MCLK_CNTL, mclk_cntl);
-	aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index);
-	aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl);
-
-	/* use old pio mode */
-	aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
-
-	DBG("engine reset");
-}
-
-
-static void aty128_init_engine(struct aty128fb_par *par)
-{
-	u32 pitch_value;
-
-	wait_for_idle(par);
-
-	/* 3D scaler not spoken here */
-	wait_for_fifo(1, par);
-	aty_st_le32(SCALE_3D_CNTL, 0x00000000);
-
-	aty128_reset_engine(par);
-
-	pitch_value = par->crtc.pitch;
-	if (par->crtc.bpp == 24) {
-		pitch_value = pitch_value * 3;
-	}
-
-	wait_for_fifo(4, par);
-	/* setup engine offset registers */
-	aty_st_le32(DEFAULT_OFFSET, 0x00000000);
-
-	/* setup engine pitch registers */
-	aty_st_le32(DEFAULT_PITCH, pitch_value);
-
-	/* set the default scissor register to max dimensions */
-	aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF);
-
-	/* set the drawing controls registers */
-	aty_st_le32(DP_GUI_MASTER_CNTL,
-		    GMC_SRC_PITCH_OFFSET_DEFAULT		|
-		    GMC_DST_PITCH_OFFSET_DEFAULT		|
-		    GMC_SRC_CLIP_DEFAULT			|
-		    GMC_DST_CLIP_DEFAULT			|
-		    GMC_BRUSH_SOLIDCOLOR			|
-		    (depth_to_dst(par->crtc.depth) << 8)	|
-		    GMC_SRC_DSTCOLOR			|
-		    GMC_BYTE_ORDER_MSB_TO_LSB		|
-		    GMC_DP_CONVERSION_TEMP_6500		|
-		    ROP3_PATCOPY				|
-		    GMC_DP_SRC_RECT				|
-		    GMC_3D_FCN_EN_CLR			|
-		    GMC_DST_CLR_CMP_FCN_CLEAR		|
-		    GMC_AUX_CLIP_CLEAR			|
-		    GMC_WRITE_MASK_SET);
-
-	wait_for_fifo(8, par);
-	/* clear the line drawing registers */
-	aty_st_le32(DST_BRES_ERR, 0);
-	aty_st_le32(DST_BRES_INC, 0);
-	aty_st_le32(DST_BRES_DEC, 0);
-
-	/* set brush color registers */
-	aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */
-	aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */
-
-	/* set source color registers */
-	aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF);   /* white */
-	aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000);   /* black */
-
-	/* default write mask */
-	aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
-
-	/* Wait for all the writes to be completed before returning */
-	wait_for_idle(par);
-}
-
-
-/* convert depth values to their register representation */
-static u32 depth_to_dst(u32 depth)
-{
-	if (depth <= 8)
-		return DST_8BPP;
-	else if (depth <= 15)
-		return DST_15BPP;
-	else if (depth == 16)
-		return DST_16BPP;
-	else if (depth <= 24)
-		return DST_24BPP;
-	else if (depth <= 32)
-		return DST_32BPP;
-
-	return -EINVAL;
-}
-
-/*
- * PLL informations retreival
- */
-
-
-#ifndef __sparc__
-static void __iomem *aty128_map_ROM(const struct aty128fb_par *par,
-				    struct pci_dev *dev)
-{
-	u16 dptr;
-	u8 rom_type;
-	void __iomem *bios;
-	size_t rom_size;
-
-    	/* Fix from ATI for problem with Rage128 hardware not leaving ROM enabled */
-    	unsigned int temp;
-	temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
-	temp &= 0x00ffffffu;
-	temp |= 0x04 << 24;
-	aty_st_le32(RAGE128_MPP_TB_CONFIG, temp);
-	temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
-
-	bios = pci_map_rom(dev, &rom_size);
-
-	if (!bios) {
-		printk(KERN_ERR "aty128fb: ROM failed to map\n");
-		return NULL;
-	}
-
-	/* Very simple test to make sure it appeared */
-	if (BIOS_IN16(0) != 0xaa55) {
-		printk(KERN_DEBUG "aty128fb: Invalid ROM signature %x should "
-			" be 0xaa55\n", BIOS_IN16(0));
-		goto failed;
-	}
-
-	/* Look for the PCI data to check the ROM type */
-	dptr = BIOS_IN16(0x18);
-
-	/* Check the PCI data signature. If it's wrong, we still assume a normal
-	 * x86 ROM for now, until I've verified this works everywhere.
-	 * The goal here is more to phase out Open Firmware images.
-	 *
-	 * Currently, we only look at the first PCI data, we could iteratre and
-	 * deal with them all, and we should use fb_bios_start relative to start
-	 * of image and not relative start of ROM, but so far, I never found a
-	 * dual-image ATI card.
-	 *
-	 * typedef struct {
-	 * 	u32	signature;	+ 0x00
-	 * 	u16	vendor;		+ 0x04
-	 * 	u16	device;		+ 0x06
-	 * 	u16	reserved_1;	+ 0x08
-	 * 	u16	dlen;		+ 0x0a
-	 * 	u8	drevision;	+ 0x0c
-	 * 	u8	class_hi;	+ 0x0d
-	 * 	u16	class_lo;	+ 0x0e
-	 * 	u16	ilen;		+ 0x10
-	 * 	u16	irevision;	+ 0x12
-	 * 	u8	type;		+ 0x14
-	 * 	u8	indicator;	+ 0x15
-	 * 	u16	reserved_2;	+ 0x16
-	 * } pci_data_t;
-	 */
-	if (BIOS_IN32(dptr) !=  (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
-		printk(KERN_WARNING "aty128fb: PCI DATA signature in ROM incorrect: %08x\n",
-		       BIOS_IN32(dptr));
-		goto anyway;
-	}
-	rom_type = BIOS_IN8(dptr + 0x14);
-	switch(rom_type) {
-	case 0:
-		printk(KERN_INFO "aty128fb: Found Intel x86 BIOS ROM Image\n");
-		break;
-	case 1:
-		printk(KERN_INFO "aty128fb: Found Open Firmware ROM Image\n");
-		goto failed;
-	case 2:
-		printk(KERN_INFO "aty128fb: Found HP PA-RISC ROM Image\n");
-		goto failed;
-	default:
-		printk(KERN_INFO "aty128fb: Found unknown type %d ROM Image\n",
-		       rom_type);
-		goto failed;
-	}
- anyway:
-	return bios;
-
- failed:
-	pci_unmap_rom(dev, bios);
-	return NULL;
-}
-
-static void aty128_get_pllinfo(struct aty128fb_par *par,
-			       unsigned char __iomem *bios)
-{
-	unsigned int bios_hdr;
-	unsigned int bios_pll;
-
-	bios_hdr = BIOS_IN16(0x48);
-	bios_pll = BIOS_IN16(bios_hdr + 0x30);
-	
-	par->constants.ppll_max = BIOS_IN32(bios_pll + 0x16);
-	par->constants.ppll_min = BIOS_IN32(bios_pll + 0x12);
-	par->constants.xclk = BIOS_IN16(bios_pll + 0x08);
-	par->constants.ref_divider = BIOS_IN16(bios_pll + 0x10);
-	par->constants.ref_clk = BIOS_IN16(bios_pll + 0x0e);
-
-	DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d ref clock %d\n",
-			par->constants.ppll_max, par->constants.ppll_min,
-			par->constants.xclk, par->constants.ref_divider,
-			par->constants.ref_clk);
-
-}           
-
-#ifdef CONFIG_X86
-static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par)
-{
-	/* I simplified this code as we used to miss the signatures in
-	 * a lot of case. It's now closer to XFree, we just don't check
-	 * for signatures at all... Something better will have to be done
-	 * if we end up having conflicts
-	 */
-        u32  segstart;
-        unsigned char __iomem *rom_base = NULL;
-                                                
-        for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
-                rom_base = ioremap(segstart, 0x10000);
-		if (rom_base == NULL)
-			return NULL;
-		if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
-	                break;
-                iounmap(rom_base);
-		rom_base = NULL;
-        }
-	return rom_base;
-}
-#endif
-#endif /* ndef(__sparc__) */
-
-/* fill in known card constants if pll_block is not available */
-static void aty128_timings(struct aty128fb_par *par)
-{
-#ifdef CONFIG_PPC_OF
-	/* instead of a table lookup, assume OF has properly
-	 * setup the PLL registers and use their values
-	 * to set the XCLK values and reference divider values */
-
-	u32 x_mpll_ref_fb_div;
-	u32 xclk_cntl;
-	u32 Nx, M;
-	unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
-#endif
-
-	if (!par->constants.ref_clk)
-		par->constants.ref_clk = 2950;
-
-#ifdef CONFIG_PPC_OF
-	x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
-	xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
-	Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
-	M  = x_mpll_ref_fb_div & 0x0000ff;
-
-	par->constants.xclk = round_div((2 * Nx * par->constants.ref_clk),
-					(M * PostDivSet[xclk_cntl]));
-
-	par->constants.ref_divider =
-		aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
-#endif
-
-	if (!par->constants.ref_divider) {
-		par->constants.ref_divider = 0x3b;
-
-		aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
-		aty_pll_writeupdate(par);
-	}
-	aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider);
-	aty_pll_writeupdate(par);
-
-	/* from documentation */
-	if (!par->constants.ppll_min)
-		par->constants.ppll_min = 12500;
-	if (!par->constants.ppll_max)
-		par->constants.ppll_max = 25000;    /* 23000 on some cards? */
-	if (!par->constants.xclk)
-		par->constants.xclk = 0x1d4d;	     /* same as mclk */
-
-	par->constants.fifo_width = 128;
-	par->constants.fifo_depth = 32;
-
-	switch (aty_ld_le32(MEM_CNTL) & 0x3) {
-	case 0:
-		par->mem = &sdr_128;
-		break;
-	case 1:
-		par->mem = &sdr_sgram;
-		break;
-	case 2:
-		par->mem = &ddr_sgram;
-		break;
-	default:
-		par->mem = &sdr_sgram;
-	}
-}
-
-
-
-/*
- * CRTC programming
- */
-
-/* Program the CRTC registers */
-static void aty128_set_crtc(const struct aty128_crtc *crtc,
-			    const struct aty128fb_par *par)
-{
-	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
-	aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
-	aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
-	aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total);
-	aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
-	aty_st_le32(CRTC_PITCH, crtc->pitch);
-	aty_st_le32(CRTC_OFFSET, crtc->offset);
-	aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl);
-	/* Disable ATOMIC updating.  Is this the right place? */
-	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~(0x00030000));
-}
-
-
-static int aty128_var_to_crtc(const struct fb_var_screeninfo *var,
-			      struct aty128_crtc *crtc,
-			      const struct aty128fb_par *par)
-{
-	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp, dst;
-	u32 left, right, upper, lower, hslen, vslen, sync, vmode;
-	u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
-	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
-	u32 depth, bytpp;
-	u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 };
-
-	/* input */
-	xres = var->xres;
-	yres = var->yres;
-	vxres   = var->xres_virtual;
-	vyres   = var->yres_virtual;
-	xoffset = var->xoffset;
-	yoffset = var->yoffset;
-	bpp   = var->bits_per_pixel;
-	left  = var->left_margin;
-	right = var->right_margin;
-	upper = var->upper_margin;
-	lower = var->lower_margin;
-	hslen = var->hsync_len;
-	vslen = var->vsync_len;
-	sync  = var->sync;
-	vmode = var->vmode;
-
-	if (bpp != 16)
-		depth = bpp;
-	else
-		depth = (var->green.length == 6) ? 16 : 15;
-
-	/* check for mode eligibility
-	 * accept only non interlaced modes */
-	if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	/* convert (and round up) and validate */
-	xres = (xres + 7) & ~7;
-	xoffset = (xoffset + 7) & ~7;
-
-	if (vxres < xres + xoffset)
-		vxres = xres + xoffset;
-
-	if (vyres < yres + yoffset)
-		vyres = yres + yoffset;
-
-	/* convert depth into ATI register depth */
-	dst = depth_to_dst(depth);
-
-	if (dst == -EINVAL) {
-		printk(KERN_ERR "aty128fb: Invalid depth or RGBA\n");
-		return -EINVAL;
-	}
-
-	/* convert register depth to bytes per pixel */
-	bytpp = mode_bytpp[dst];
-
-	/* make sure there is enough video ram for the mode */
-	if ((u32)(vxres * vyres * bytpp) > par->vram_size) {
-		printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
-		return -EINVAL;
-	}
-
-	h_disp = (xres >> 3) - 1;
-	h_total = (((xres + right + hslen + left) >> 3) - 1) & 0xFFFFL;
-
-	v_disp = yres - 1;
-	v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL;
-
-	/* check to make sure h_total and v_total are in range */
-	if (((h_total >> 3) - 1) > 0x1ff || (v_total - 1) > 0x7FF) {
-		printk(KERN_ERR "aty128fb: invalid width ranges\n");
-		return -EINVAL;
-	}
-
-	h_sync_wid = (hslen + 7) >> 3;
-	if (h_sync_wid == 0)
-		h_sync_wid = 1;
-	else if (h_sync_wid > 0x3f)        /* 0x3f = max hwidth */
-		h_sync_wid = 0x3f;
-
-	h_sync_strt = (h_disp << 3) + right;
-
-	v_sync_wid = vslen;
-	if (v_sync_wid == 0)
-		v_sync_wid = 1;
-	else if (v_sync_wid > 0x1f)        /* 0x1f = max vwidth */
-		v_sync_wid = 0x1f;
-    
-	v_sync_strt = v_disp + lower;
-
-	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
-	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-    
-	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
-
-	crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8);
-
-	crtc->h_total = h_total | (h_disp << 16);
-	crtc->v_total = v_total | (v_disp << 16);
-
-	crtc->h_sync_strt_wid = h_sync_strt | (h_sync_wid << 16) |
-	        (h_sync_pol << 23);
-	crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
-                (v_sync_pol << 23);
-
-	crtc->pitch = vxres >> 3;
-
-	crtc->offset = 0;
-
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
-		crtc->offset_cntl = 0x00010000;
-	else
-		crtc->offset_cntl = 0;
-
-	crtc->vxres = vxres;
-	crtc->vyres = vyres;
-	crtc->xoffset = xoffset;
-	crtc->yoffset = yoffset;
-	crtc->depth = depth;
-	crtc->bpp = bpp;
-
-	return 0;
-}
-
-
-static int aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
-{
-
-	/* fill in pixel info */
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.offset = 0;
-	var->blue.msb_right = 0;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-	switch (pix_width) {
-	case CRTC_PIX_WIDTH_8BPP:
-		var->bits_per_pixel = 8;
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	case CRTC_PIX_WIDTH_15BPP:
-		var->bits_per_pixel = 16;
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->blue.length = 5;
-		break;
-	case CRTC_PIX_WIDTH_16BPP:
-		var->bits_per_pixel = 16;
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.length = 5;
-		break;
-	case CRTC_PIX_WIDTH_24BPP:
-		var->bits_per_pixel = 24;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	case CRTC_PIX_WIDTH_32BPP:
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	default:
-		printk(KERN_ERR "aty128fb: Invalid pixel width\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
-static int aty128_crtc_to_var(const struct aty128_crtc *crtc,
-			      struct fb_var_screeninfo *var)
-{
-	u32 xres, yres, left, right, upper, lower, hslen, vslen, sync;
-	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
-	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
-	u32 pix_width;
-
-	/* fun with masking */
-	h_total     = crtc->h_total & 0x1ff;
-	h_disp      = (crtc->h_total >> 16) & 0xff;
-	h_sync_strt = (crtc->h_sync_strt_wid >> 3) & 0x1ff;
-	h_sync_dly  = crtc->h_sync_strt_wid & 0x7;
-	h_sync_wid  = (crtc->h_sync_strt_wid >> 16) & 0x3f;
-	h_sync_pol  = (crtc->h_sync_strt_wid >> 23) & 0x1;
-	v_total     = crtc->v_total & 0x7ff;
-	v_disp      = (crtc->v_total >> 16) & 0x7ff;
-	v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
-	v_sync_wid  = (crtc->v_sync_strt_wid >> 16) & 0x1f;
-	v_sync_pol  = (crtc->v_sync_strt_wid >> 23) & 0x1;
-	c_sync      = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
-	pix_width   = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
-
-	/* do conversions */
-	xres  = (h_disp + 1) << 3;
-	yres  = v_disp + 1;
-	left  = ((h_total - h_sync_strt - h_sync_wid) << 3) - h_sync_dly;
-	right = ((h_sync_strt - h_disp) << 3) + h_sync_dly;
-	hslen = h_sync_wid << 3;
-	upper = v_total - v_sync_strt - v_sync_wid;
-	lower = v_sync_strt - v_disp;
-	vslen = v_sync_wid;
-	sync  = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
-		(v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
-		(c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
-
-	aty128_pix_width_to_var(pix_width, var);
-
-	var->xres = xres;
-	var->yres = yres;
-	var->xres_virtual = crtc->vxres;
-	var->yres_virtual = crtc->vyres;
-	var->xoffset = crtc->xoffset;
-	var->yoffset = crtc->yoffset;
-	var->left_margin  = left;
-	var->right_margin = right;
-	var->upper_margin = upper;
-	var->lower_margin = lower;
-	var->hsync_len = hslen;
-	var->vsync_len = vslen;
-	var->sync  = sync;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	return 0;
-}
-
-static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
-{
-	if (on) {
-		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) |
-			    CRT_CRTC_ON);
-		aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) |
-			    DAC_PALETTE2_SNOOP_EN));
-	} else
-		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) &
-			    ~CRT_CRTC_ON);
-}
-
-static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
-{
-	u32 reg;
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-#endif
-
-	if (on) {
-		reg = aty_ld_le32(LVDS_GEN_CNTL);
-		reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
-		reg &= ~LVDS_DISPLAY_DIS;
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-		aty128_bl_set_power(info, FB_BLANK_UNBLANK);
-#endif	
-	} else {
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-		aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
-#endif	
-		reg = aty_ld_le32(LVDS_GEN_CNTL);
-		reg |= LVDS_DISPLAY_DIS;
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-		mdelay(100);
-		reg &= ~(LVDS_ON /*| LVDS_EN*/);
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-	}
-}
-
-static void aty128_set_pll(struct aty128_pll *pll,
-			   const struct aty128fb_par *par)
-{
-	u32 div3;
-
-	unsigned char post_conv[] =	/* register values for post dividers */
-        { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
-
-	/* select PPLL_DIV_3 */
-	aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
-
-	/* reset PLL */
-	aty_st_pll(PPLL_CNTL,
-		   aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
-
-	/* write the reference divider */
-	aty_pll_wait_readupdate(par);
-	aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider & 0x3ff);
-	aty_pll_writeupdate(par);
-
-	div3 = aty_ld_pll(PPLL_DIV_3);
-	div3 &= ~PPLL_FB3_DIV_MASK;
-	div3 |= pll->feedback_divider;
-	div3 &= ~PPLL_POST3_DIV_MASK;
-	div3 |= post_conv[pll->post_divider] << 16;
-
-	/* write feedback and post dividers */
-	aty_pll_wait_readupdate(par);
-	aty_st_pll(PPLL_DIV_3, div3);
-	aty_pll_writeupdate(par);
-
-	aty_pll_wait_readupdate(par);
-	aty_st_pll(HTOTAL_CNTL, 0);	/* no horiz crtc adjustment */
-	aty_pll_writeupdate(par);
-
-	/* clear the reset, just in case */
-	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
-}
-
-
-static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
-			     const struct aty128fb_par *par)
-{
-	const struct aty128_constants c = par->constants;
-	unsigned char post_dividers[] = {1,2,4,8,3,6,12};
-	u32 output_freq;
-	u32 vclk;        /* in .01 MHz */
-	int i = 0;
-	u32 n, d;
-
-	vclk = 100000000 / period_in_ps;	/* convert units to 10 kHz */
-
-	/* adjust pixel clock if necessary */
-	if (vclk > c.ppll_max)
-		vclk = c.ppll_max;
-	if (vclk * 12 < c.ppll_min)
-		vclk = c.ppll_min/12;
-
-	/* now, find an acceptable divider */
-	for (i = 0; i < ARRAY_SIZE(post_dividers); i++) {
-		output_freq = post_dividers[i] * vclk;
-		if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
-			pll->post_divider = post_dividers[i];
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(post_dividers))
-		return -EINVAL;
-
-	/* calculate feedback divider */
-	n = c.ref_divider * output_freq;
-	d = c.ref_clk;
-
-	pll->feedback_divider = round_div(n, d);
-	pll->vclk = vclk;
-
-	DBG("post %d feedback %d vlck %d output %d ref_divider %d "
-	    "vclk_per: %d\n", pll->post_divider,
-	    pll->feedback_divider, vclk, output_freq,
-	    c.ref_divider, period_in_ps);
-
-	return 0;
-}
-
-
-static int aty128_pll_to_var(const struct aty128_pll *pll,
-			     struct fb_var_screeninfo *var)
-{
-	var->pixclock = 100000000 / pll->vclk;
-
-	return 0;
-}
-
-
-static void aty128_set_fifo(const struct aty128_ddafifo *dsp,
-			    const struct aty128fb_par *par)
-{
-	aty_st_le32(DDA_CONFIG, dsp->dda_config);
-	aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);
-}
-
-
-static int aty128_ddafifo(struct aty128_ddafifo *dsp,
-			  const struct aty128_pll *pll,
-			  u32 depth,
-			  const struct aty128fb_par *par)
-{
-	const struct aty128_meminfo *m = par->mem;
-	u32 xclk = par->constants.xclk;
-	u32 fifo_width = par->constants.fifo_width;
-	u32 fifo_depth = par->constants.fifo_depth;
-	s32 x, b, p, ron, roff;
-	u32 n, d, bpp;
-
-	/* round up to multiple of 8 */
-	bpp = (depth+7) & ~7;
-
-	n = xclk * fifo_width;
-	d = pll->vclk * bpp;
-	x = round_div(n, d);
-
-	ron = 4 * m->MB +
-		3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +
-		2 * m->Trp +
-		m->Twr +
-		m->CL +
-		m->Tr2w +
-		x;
-
-	DBG("x %x\n", x);
-
-	b = 0;
-	while (x) {
-		x >>= 1;
-		b++;
-	}
-	p = b + 1;
-
-	ron <<= (11 - p);
-
-	n <<= (11 - p);
-	x = round_div(n, d);
-	roff = x * (fifo_depth - 4);
-
-	if ((ron + m->Rloop) >= roff) {
-		printk(KERN_ERR "aty128fb: Mode out of range!\n");
-		return -EINVAL;
-	}
-
-	DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
-	    p, m->Rloop, x, ron, roff);
-
-	dsp->dda_config = p << 16 | m->Rloop << 20 | x;
-	dsp->dda_on_off = ron << 16 | roff;
-
-	return 0;
-}
-
-
-/*
- * This actually sets the video mode.
- */
-static int aty128fb_set_par(struct fb_info *info)
-{ 
-	struct aty128fb_par *par = info->par;
-	u32 config;
-	int err;
-
-	if ((err = aty128_decode_var(&info->var, par)) != 0)
-		return err;
-
-	if (par->blitter_may_be_busy)
-		wait_for_idle(par);
-
-	/* clear all registers that may interfere with mode setting */
-	aty_st_le32(OVR_CLR, 0);
-	aty_st_le32(OVR_WID_LEFT_RIGHT, 0);
-	aty_st_le32(OVR_WID_TOP_BOTTOM, 0);
-	aty_st_le32(OV0_SCALE_CNTL, 0);
-	aty_st_le32(MPP_TB_CONFIG, 0);
-	aty_st_le32(MPP_GP_CONFIG, 0);
-	aty_st_le32(SUBPIC_CNTL, 0);
-	aty_st_le32(VIPH_CONTROL, 0);
-	aty_st_le32(I2C_CNTL_1, 0);         /* turn off i2c */
-	aty_st_le32(GEN_INT_CNTL, 0);	/* turn off interrupts */
-	aty_st_le32(CAP0_TRIG_CNTL, 0);
-	aty_st_le32(CAP1_TRIG_CNTL, 0);
-
-	aty_st_8(CRTC_EXT_CNTL + 1, 4);	/* turn video off */
-
-	aty128_set_crtc(&par->crtc, par);
-	aty128_set_pll(&par->pll, par);
-	aty128_set_fifo(&par->fifo_reg, par);
-
-	config = aty_ld_le32(CNFG_CNTL) & ~3;
-
-#if defined(__BIG_ENDIAN)
-	if (par->crtc.bpp == 32)
-		config |= 2;	/* make aperture do 32 bit swapping */
-	else if (par->crtc.bpp == 16)
-		config |= 1;	/* make aperture do 16 bit swapping */
-#endif
-
-	aty_st_le32(CNFG_CNTL, config);
-	aty_st_8(CRTC_EXT_CNTL + 1, 0);	/* turn the video back on */
-
-	info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
-	info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR
-		: FB_VISUAL_DIRECTCOLOR;
-
-	if (par->chip_gen == rage_M3) {
-		aty128_set_crt_enable(par, par->crt_on);
-		aty128_set_lcd_enable(par, par->lcd_on);
-	}
-	if (par->accel_flags & FB_ACCELF_TEXT)
-		aty128_init_engine(par);
-
-#ifdef CONFIG_BOOTX_TEXT
-	btext_update_display(info->fix.smem_start,
-			     (((par->crtc.h_total>>16) & 0xff)+1)*8,
-			     ((par->crtc.v_total>>16) & 0x7ff)+1,
-			     par->crtc.bpp,
-			     par->crtc.vxres*par->crtc.bpp/8);
-#endif /* CONFIG_BOOTX_TEXT */
-
-	return 0;
-}
-
-/*
- *  encode/decode the User Defined Part of the Display
- */
-
-static int aty128_decode_var(struct fb_var_screeninfo *var,
-			     struct aty128fb_par *par)
-{
-	int err;
-	struct aty128_crtc crtc;
-	struct aty128_pll pll;
-	struct aty128_ddafifo fifo_reg;
-
-	if ((err = aty128_var_to_crtc(var, &crtc, par)))
-		return err;
-
-	if ((err = aty128_var_to_pll(var->pixclock, &pll, par)))
-		return err;
-
-	if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par)))
-		return err;
-
-	par->crtc = crtc;
-	par->pll = pll;
-	par->fifo_reg = fifo_reg;
-	par->accel_flags = var->accel_flags;
-
-	return 0;
-}
-
-
-static int aty128_encode_var(struct fb_var_screeninfo *var,
-			     const struct aty128fb_par *par)
-{
-	int err;
-
-	if ((err = aty128_crtc_to_var(&par->crtc, var)))
-		return err;
-
-	if ((err = aty128_pll_to_var(&par->pll, var)))
-		return err;
-
-	var->nonstd = 0;
-	var->activate = 0;
-
-	var->height = -1;
-	var->width = -1;
-	var->accel_flags = par->accel_flags;
-
-	return 0;
-}           
-
-
-static int aty128fb_check_var(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct aty128fb_par par;
-	int err;
-
-	par = *(struct aty128fb_par *)info->par;
-	if ((err = aty128_decode_var(var, &par)) != 0)
-		return err;
-	aty128_encode_var(var, &par);
-	return 0;
-}
-
-
-/*
- *  Pan or Wrap the Display
- */
-static int aty128fb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *fb)
-{
-	struct aty128fb_par *par = fb->par;
-	u32 xoffset, yoffset;
-	u32 offset;
-	u32 xres, yres;
-
-	xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;
-	yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
-
-	xoffset = (var->xoffset +7) & ~7;
-	yoffset = var->yoffset;
-
-	if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
-		return -EINVAL;
-
-	par->crtc.xoffset = xoffset;
-	par->crtc.yoffset = yoffset;
-
-	offset = ((yoffset * par->crtc.vxres + xoffset) * (par->crtc.bpp >> 3))
-									  & ~7;
-
-	if (par->crtc.bpp == 24)
-		offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */
-
-	aty_st_le32(CRTC_OFFSET, offset);
-
-	return 0;
-}
-
-
-/*
- *  Helper function to store a single palette register
- */
-static void aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
-			  struct aty128fb_par *par)
-{
-	if (par->chip_gen == rage_M3) {
-#if 0
-		/* Note: For now, on M3, we set palette on both heads, which may
-		 * be useless. Can someone with a M3 check this ?
-		 * 
-		 * This code would still be useful if using the second CRTC to 
-		 * do mirroring
-		 */
-
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) |
-			    DAC_PALETTE_ACCESS_CNTL);
-		aty_st_8(PALETTE_INDEX, regno);
-		aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
-#endif
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) &
-			    ~DAC_PALETTE_ACCESS_CNTL);
-	}
-
-	aty_st_8(PALETTE_INDEX, regno);
-	aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
-}
-
-static int aty128fb_sync(struct fb_info *info)
-{
-	struct aty128fb_par *par = info->par;
-
-	if (par->blitter_may_be_busy)
-		wait_for_idle(par);
-	return 0;
-}
-
-#ifndef MODULE
-static int aty128fb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "lcd:", 4)) {
-			default_lcd_on = simple_strtoul(this_opt+4, NULL, 0);
-			continue;
-		} else if (!strncmp(this_opt, "crt:", 4)) {
-			default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
-			continue;
-		} else if (!strncmp(this_opt, "backlight:", 10)) {
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-			backlight = simple_strtoul(this_opt+10, NULL, 0);
-#endif
-			continue;
-		}
-#ifdef CONFIG_MTRR
-		if(!strncmp(this_opt, "nomtrr", 6)) {
-			mtrr = 0;
-			continue;
-		}
-#endif
-#ifdef CONFIG_PPC_PMAC
-		/* vmode and cmode deprecated */
-		if (!strncmp(this_opt, "vmode:", 6)) {
-			unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
-			if (vmode > 0 && vmode <= VMODE_MAX)
-				default_vmode = vmode;
-			continue;
-		} else if (!strncmp(this_opt, "cmode:", 6)) {
-			unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
-			switch (cmode) {
-			case 0:
-			case 8:
-				default_cmode = CMODE_8;
-				break;
-			case 15:
-			case 16:
-				default_cmode = CMODE_16;
-				break;
-			case 24:
-			case 32:
-				default_cmode = CMODE_32;
-				break;
-			}
-			continue;
-		}
-#endif /* CONFIG_PPC_PMAC */
-		mode_option = this_opt;
-	}
-	return 0;
-}
-#endif  /*  MODULE  */
-
-/* Backlight */
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-#define MAX_LEVEL 0xFF
-
-static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
-		int level)
-{
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int atylevel;
-
-	/* Get and convert the value */
-	/* No locking of bl_curve since we read a single value */
-	atylevel = MAX_LEVEL -
-		(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
-
-	if (atylevel < 0)
-		atylevel = 0;
-	else if (atylevel > MAX_LEVEL)
-		atylevel = MAX_LEVEL;
-
-	return atylevel;
-}
-
-/* We turn off the LCD completely instead of just dimming the backlight.
- * This provides greater power saving and the display is useless without
- * backlight anyway
- */
-#define BACKLIGHT_LVDS_OFF
-/* That one prevents proper CRT output with LCD off */
-#undef BACKLIGHT_DAC_OFF
-
-static int aty128_bl_update_status(struct backlight_device *bd)
-{
-	struct aty128fb_par *par = bl_get_data(bd);
-	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
-	int level;
-
-	if (bd->props.power != FB_BLANK_UNBLANK ||
-	    bd->props.fb_blank != FB_BLANK_UNBLANK ||
-	    !par->lcd_on)
-		level = 0;
-	else
-		level = bd->props.brightness;
-
-	reg |= LVDS_BL_MOD_EN | LVDS_BLON;
-	if (level > 0) {
-		reg |= LVDS_DIGION;
-		if (!(reg & LVDS_ON)) {
-			reg &= ~LVDS_BLON;
-			aty_st_le32(LVDS_GEN_CNTL, reg);
-			aty_ld_le32(LVDS_GEN_CNTL);
-			mdelay(10);
-			reg |= LVDS_BLON;
-			aty_st_le32(LVDS_GEN_CNTL, reg);
-		}
-		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
-		reg |= (aty128_bl_get_level_brightness(par, level) <<
-			LVDS_BL_MOD_LEVEL_SHIFT);
-#ifdef BACKLIGHT_LVDS_OFF
-		reg |= LVDS_ON | LVDS_EN;
-		reg &= ~LVDS_DISPLAY_DIS;
-#endif
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef BACKLIGHT_DAC_OFF
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
-#endif
-	} else {
-		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
-		reg |= (aty128_bl_get_level_brightness(par, 0) <<
-			LVDS_BL_MOD_LEVEL_SHIFT);
-#ifdef BACKLIGHT_LVDS_OFF
-		reg |= LVDS_DISPLAY_DIS;
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-		aty_ld_le32(LVDS_GEN_CNTL);
-		udelay(10);
-		reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
-#endif
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef BACKLIGHT_DAC_OFF
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
-#endif
-	}
-
-	return 0;
-}
-
-static int aty128_bl_get_brightness(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
-static const struct backlight_ops aty128_bl_data = {
-	.get_brightness	= aty128_bl_get_brightness,
-	.update_status	= aty128_bl_update_status,
-};
-
-static void aty128_bl_set_power(struct fb_info *info, int power)
-{
-	if (info->bl_dev) {
-		info->bl_dev->props.power = power;
-		backlight_update_status(info->bl_dev);
-	}
-}
-
-static void aty128_bl_init(struct aty128fb_par *par)
-{
-	struct backlight_properties props;
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	struct backlight_device *bd;
-	char name[12];
-
-	/* Could be extended to Rage128Pro LVDS output too */
-	if (par->chip_gen != rage_M3)
-		return;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (!pmac_has_backlight_type("ati"))
-		return;
-#endif
-
-	snprintf(name, sizeof(name), "aty128bl%d", info->node);
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
-	bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
-				       &props);
-	if (IS_ERR(bd)) {
-		info->bl_dev = NULL;
-		printk(KERN_WARNING "aty128: Backlight registration failed\n");
-		goto error;
-	}
-
-	info->bl_dev = bd;
-	fb_bl_default_curve(info, 0,
-		 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
-		219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-
-	bd->props.brightness = bd->props.max_brightness;
-	bd->props.power = FB_BLANK_UNBLANK;
-	backlight_update_status(bd);
-
-	printk("aty128: Backlight initialized (%s)\n", name);
-
-	return;
-
-error:
-	return;
-}
-
-static void aty128_bl_exit(struct backlight_device *bd)
-{
-	backlight_device_unregister(bd);
-	printk("aty128: Backlight unloaded\n");
-}
-#endif /* CONFIG_FB_ATY128_BACKLIGHT */
-
-/*
- *  Initialisation
- */
-
-#ifdef CONFIG_PPC_PMAC__disabled
-static void aty128_early_resume(void *data)
-{
-        struct aty128fb_par *par = data;
-
-	if (!console_trylock())
-		return;
-	pci_restore_state(par->pdev);
-	aty128_do_resume(par->pdev);
-	console_unlock();
-}
-#endif /* CONFIG_PPC_PMAC */
-
-static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct aty128fb_par *par = info->par;
-	struct fb_var_screeninfo var;
-	char video_card[50];
-	u8 chip_rev;
-	u32 dac;
-
-	/* Get the chip revision */
-	chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F;
-
-	strcpy(video_card, "Rage128 XX ");
-	video_card[8] = ent->device >> 8;
-	video_card[9] = ent->device & 0xFF;
-
-	/* range check to make sure */
-	if (ent->driver_data < ARRAY_SIZE(r128_family))
-		strlcat(video_card, r128_family[ent->driver_data],
-			sizeof(video_card));
-
-	printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
-
-	if (par->vram_size % (1024 * 1024) == 0)
-		printk("%dM %s\n", par->vram_size / (1024*1024), par->mem->name);
-	else
-		printk("%dk %s\n", par->vram_size / 1024, par->mem->name);
-
-	par->chip_gen = ent->driver_data;
-
-	/* fill in info */
-	info->fbops = &aty128fb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
-
-	par->lcd_on = default_lcd_on;
-	par->crt_on = default_crt_on;
-
-	var = default_var;
-#ifdef CONFIG_PPC_PMAC
-	if (machine_is(powermac)) {
-		/* Indicate sleep capability */
-		if (par->chip_gen == rage_M3) {
-			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
-#if 0 /* Disable the early video resume hack for now as it's causing problems,
-       * among others we now rely on the PCI core restoring the config space
-       * for us, which isn't the case with that hack, and that code path causes
-       * various things to be called with interrupts off while they shouldn't.
-       * I'm leaving the code in as it can be useful for debugging purposes
-       */
-			pmac_set_early_video_resume(aty128_early_resume, par);
-#endif
-		}
-
-		/* Find default mode */
-		if (mode_option) {
-			if (!mac_find_mode(&var, info, mode_option, 8))
-				var = default_var;
-		} else {
-			if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-				default_vmode = VMODE_1024_768_60;
-
-			/* iMacs need that resolution
-			 * PowerMac2,1 first r128 iMacs
-			 * PowerMac2,2 summer 2000 iMacs
-			 * PowerMac4,1 january 2001 iMacs "flower power"
-			 */
-			if (of_machine_is_compatible("PowerMac2,1") ||
-			    of_machine_is_compatible("PowerMac2,2") ||
-			    of_machine_is_compatible("PowerMac4,1"))
-				default_vmode = VMODE_1024_768_75;
-
-			/* iBook SE */
-			if (of_machine_is_compatible("PowerBook2,2"))
-				default_vmode = VMODE_800_600_60;
-
-			/* PowerBook Firewire (Pismo), iBook Dual USB */
-			if (of_machine_is_compatible("PowerBook3,1") ||
-			    of_machine_is_compatible("PowerBook4,1"))
-				default_vmode = VMODE_1024_768_60;
-
-			/* PowerBook Titanium */
-			if (of_machine_is_compatible("PowerBook3,2"))
-				default_vmode = VMODE_1152_768_60;
-	
-			if (default_cmode > 16) 
-				default_cmode = CMODE_32;
-			else if (default_cmode > 8) 
-				default_cmode = CMODE_16;
-			else 
-				default_cmode = CMODE_8;
-
-			if (mac_vmode_to_var(default_vmode, default_cmode, &var))
-				var = default_var;
-		}
-	} else
-#endif /* CONFIG_PPC_PMAC */
-	{
-		if (mode_option)
-			if (fb_find_mode(&var, info, mode_option, NULL, 
-					 0, &defaultmode, 8) == 0)
-				var = default_var;
-	}
-
-	var.accel_flags &= ~FB_ACCELF_TEXT;
-//	var.accel_flags |= FB_ACCELF_TEXT;/* FIXME Will add accel later */
-
-	if (aty128fb_check_var(&var, info)) {
-		printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
-		return 0;
-	}
-
-	/* setup the DAC the way we like it */
-	dac = aty_ld_le32(DAC_CNTL);
-	dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
-	dac |= DAC_MASK;
-	if (par->chip_gen == rage_M3)
-		dac |= DAC_PALETTE2_SNOOP_EN;
-	aty_st_le32(DAC_CNTL, dac);
-
-	/* turn off bus mastering, just in case */
-	aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
-
-	info->var = var;
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	var.activate = FB_ACTIVATE_NOW;
-
-	aty128_init_engine(par);
-
-	par->pdev = pdev;
-	par->asleep = 0;
-	par->lock_blank = 0;
-
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-	if (backlight)
-		aty128_bl_init(par);
-#endif
-
-	if (register_framebuffer(info) < 0)
-		return 0;
-
-	fb_info(info, "%s frame buffer device on %s\n",
-		info->fix.id, video_card);
-
-	return 1;	/* success! */
-}
-
-#ifdef CONFIG_PCI
-/* register a card    ++ajoshi */
-static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	unsigned long fb_addr, reg_addr;
-	struct aty128fb_par *par;
-	struct fb_info *info;
-	int err;
-#ifndef __sparc__
-	void __iomem *bios = NULL;
-#endif
-
-	/* Enable device in PCI config */
-	if ((err = pci_enable_device(pdev))) {
-		printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n",
-				err);
-		return -ENODEV;
-	}
-
-	fb_addr = pci_resource_start(pdev, 0);
-	if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
-				"aty128fb FB")) {
-		printk(KERN_ERR "aty128fb: cannot reserve frame "
-				"buffer memory\n");
-		return -ENODEV;
-	}
-
-	reg_addr = pci_resource_start(pdev, 2);
-	if (!request_mem_region(reg_addr, pci_resource_len(pdev, 2),
-				"aty128fb MMIO")) {
-		printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n");
-		goto err_free_fb;
-	}
-
-	/* We have the resources. Now virtualize them */
-	info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev);
-	if (info == NULL) {
-		printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
-		goto err_free_mmio;
-	}
-	par = info->par;
-
-	info->pseudo_palette = par->pseudo_palette;
-
-	/* Virtualize mmio region */
-	info->fix.mmio_start = reg_addr;
-	par->regbase = pci_ioremap_bar(pdev, 2);
-	if (!par->regbase)
-		goto err_free_info;
-
-	/* Grab memory size from the card */
-	// How does this relate to the resource length from the PCI hardware?
-	par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF;
-
-	/* Virtualize the framebuffer */
-	info->screen_base = ioremap(fb_addr, par->vram_size);
-	if (!info->screen_base)
-		goto err_unmap_out;
-
-	/* Set up info->fix */
-	info->fix = aty128fb_fix;
-	info->fix.smem_start = fb_addr;
-	info->fix.smem_len = par->vram_size;
-	info->fix.mmio_start = reg_addr;
-
-	/* If we can't test scratch registers, something is seriously wrong */
-	if (!register_test(par)) {
-		printk(KERN_ERR "aty128fb: Can't write to video register!\n");
-		goto err_out;
-	}
-
-#ifndef __sparc__
-	bios = aty128_map_ROM(par, pdev);
-#ifdef CONFIG_X86
-	if (bios == NULL)
-		bios = aty128_find_mem_vbios(par);
-#endif
-	if (bios == NULL)
-		printk(KERN_INFO "aty128fb: BIOS not located, guessing timings.\n");
-	else {
-		printk(KERN_INFO "aty128fb: Rage128 BIOS located\n");
-		aty128_get_pllinfo(par, bios);
-		pci_unmap_rom(pdev, bios);
-	}
-#endif /* __sparc__ */
-
-	aty128_timings(par);
-	pci_set_drvdata(pdev, info);
-
-	if (!aty128_init(pdev, ent))
-		goto err_out;
-
-#ifdef CONFIG_MTRR
-	if (mtrr) {
-		par->mtrr.vram = mtrr_add(info->fix.smem_start,
-				par->vram_size, MTRR_TYPE_WRCOMB, 1);
-		par->mtrr.vram_valid = 1;
-		/* let there be speed */
-		printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
-	}
-#endif /* CONFIG_MTRR */
-	return 0;
-
-err_out:
-	iounmap(info->screen_base);
-err_unmap_out:
-	iounmap(par->regbase);
-err_free_info:
-	framebuffer_release(info);
-err_free_mmio:
-	release_mem_region(pci_resource_start(pdev, 2),
-			pci_resource_len(pdev, 2));
-err_free_fb:
-	release_mem_region(pci_resource_start(pdev, 0),
-			pci_resource_len(pdev, 0));
-	return -ENODEV;
-}
-
-static void aty128_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct aty128fb_par *par;
-
-	if (!info)
-		return;
-
-	par = info->par;
-
-	unregister_framebuffer(info);
-
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-	aty128_bl_exit(info->bl_dev);
-#endif
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr.vram_valid)
-		mtrr_del(par->mtrr.vram, info->fix.smem_start,
-			 par->vram_size);
-#endif /* CONFIG_MTRR */
-	iounmap(par->regbase);
-	iounmap(info->screen_base);
-
-	release_mem_region(pci_resource_start(pdev, 0),
-			   pci_resource_len(pdev, 0));
-	release_mem_region(pci_resource_start(pdev, 2),
-			   pci_resource_len(pdev, 2));
-	framebuffer_release(info);
-}
-#endif /* CONFIG_PCI */
-
-
-
-    /*
-     *  Blank the display.
-     */
-static int aty128fb_blank(int blank, struct fb_info *fb)
-{
-	struct aty128fb_par *par = fb->par;
-	u8 state;
-
-	if (par->lock_blank || par->asleep)
-		return 0;
-
-	switch (blank) {
-	case FB_BLANK_NORMAL:
-		state = 4;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		state = 6;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		state = 5;
-		break;
-	case FB_BLANK_POWERDOWN:
-		state = 7;
-		break;
-	case FB_BLANK_UNBLANK:
-	default:
-		state = 0;
-		break;
-	}
-	aty_st_8(CRTC_EXT_CNTL+1, state);
-
-	if (par->chip_gen == rage_M3) {
-		aty128_set_crt_enable(par, par->crt_on && !blank);
-		aty128_set_lcd_enable(par, par->lcd_on && !blank);
-	}
-
-	return 0;
-}
-
-/*
- *  Set a single color register. The values supplied are already
- *  rounded down to the hardware's capabilities (according to the
- *  entries in the var structure). Return != 0 for invalid regno.
- */
-static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			      u_int transp, struct fb_info *info)
-{
-	struct aty128fb_par *par = info->par;
-
-	if (regno > 255
-	    || (par->crtc.depth == 16 && regno > 63)
-	    || (par->crtc.depth == 15 && regno > 31))
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	if (regno < 16) {
-		int i;
-		u32 *pal = info->pseudo_palette;
-
-		switch (par->crtc.depth) {
-		case 15:
-			pal[regno] = (regno << 10) | (regno << 5) | regno;
-			break;
-		case 16:
-			pal[regno] = (regno << 11) | (regno << 6) | regno;
-			break;
-		case 24:
-			pal[regno] = (regno << 16) | (regno << 8) | regno;
-			break;
-		case 32:
-			i = (regno << 8) | regno;
-			pal[regno] = (i << 16) | i;
-			break;
-		}
-	}
-
-	if (par->crtc.depth == 16 && regno > 0) {
-		/*
-		 * With the 5-6-5 split of bits for RGB at 16 bits/pixel, we
-		 * have 32 slots for R and B values but 64 slots for G values.
-		 * Thus the R and B values go in one slot but the G value
-		 * goes in a different slot, and we have to avoid disturbing
-		 * the other fields in the slots we touch.
-		 */
-		par->green[regno] = green;
-		if (regno < 32) {
-			par->red[regno] = red;
-			par->blue[regno] = blue;
-			aty128_st_pal(regno * 8, red, par->green[regno*2],
-				      blue, par);
-		}
-		red = par->red[regno/2];
-		blue = par->blue[regno/2];
-		regno <<= 2;
-	} else if (par->crtc.bpp == 16)
-		regno <<= 3;
-	aty128_st_pal(regno, red, green, blue, par);
-
-	return 0;
-}
-
-#define ATY_MIRROR_LCD_ON	0x00000001
-#define ATY_MIRROR_CRT_ON	0x00000002
-
-/* out param: u32*	backlight value: 0 to 15 */
-#define FBIO_ATY128_GET_MIRROR	_IOR('@', 1, __u32)
-/* in param: u32*	backlight value: 0 to 15 */
-#define FBIO_ATY128_SET_MIRROR	_IOW('@', 2, __u32)
-
-static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
-{
-	struct aty128fb_par *par = info->par;
-	u32 value;
-	int rc;
-    
-	switch (cmd) {
-	case FBIO_ATY128_SET_MIRROR:
-		if (par->chip_gen != rage_M3)
-			return -EINVAL;
-		rc = get_user(value, (__u32 __user *)arg);
-		if (rc)
-			return rc;
-		par->lcd_on = (value & 0x01) != 0;
-		par->crt_on = (value & 0x02) != 0;
-		if (!par->crt_on && !par->lcd_on)
-			par->lcd_on = 1;
-		aty128_set_crt_enable(par, par->crt_on);	
-		aty128_set_lcd_enable(par, par->lcd_on);	
-		return 0;
-	case FBIO_ATY128_GET_MIRROR:
-		if (par->chip_gen != rage_M3)
-			return -EINVAL;
-		value = (par->crt_on << 1) | par->lcd_on;
-		return put_user(value, (__u32 __user *)arg);
-	}
-	return -EINVAL;
-}
-
-#if 0
-    /*
-     *  Accelerated functions
-     */
-
-static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
-				   u_int width, u_int height,
-				   struct fb_info_aty128 *par)
-{
-	u32 save_dp_datatype, save_dp_cntl, dstval;
-
-	if (!width || !height)
-		return;
-
-	dstval = depth_to_dst(par->current_par.crtc.depth);
-	if (dstval == DST_24BPP) {
-		srcx *= 3;
-		dstx *= 3;
-		width *= 3;
-	} else if (dstval == -EINVAL) {
-		printk("aty128fb: invalid depth or RGBA\n");
-		return;
-	}
-
-	wait_for_fifo(2, par);
-	save_dp_datatype = aty_ld_le32(DP_DATATYPE);
-	save_dp_cntl     = aty_ld_le32(DP_CNTL);
-
-	wait_for_fifo(6, par);
-	aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
-	aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
-	aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
-	aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR);
-
-	aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
-	aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
-
-	par->blitter_may_be_busy = 1;
-
-	wait_for_fifo(2, par);
-	aty_st_le32(DP_DATATYPE, save_dp_datatype);
-	aty_st_le32(DP_CNTL, save_dp_cntl);
-}
-
-
-    /*
-     * Text mode accelerated functions
-     */
-
-static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy,
-			       int dx, int height, int width)
-{
-	sx     *= fontwidth(p);
-	sy     *= fontheight(p);
-	dx     *= fontwidth(p);
-	dy     *= fontheight(p);
-	width  *= fontwidth(p);
-	height *= fontheight(p);
-
-	aty128_rectcopy(sx, sy, dx, dy, width, height,
-			(struct fb_info_aty128 *)p->fb_info);
-}
-#endif /* 0 */
-
-static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
-{
-	u32	pmgt;
-	struct pci_dev *pdev = par->pdev;
-
-	if (!par->pdev->pm_cap)
-		return;
-		
-	/* Set the chip into the appropriate suspend mode (we use D2,
-	 * D3 would require a complete re-initialisation of the chip,
-	 * including PCI config registers, clocks, AGP configuration, ...)
-	 *
-	 * For resume, the core will have already brought us back to D0
-	 */
-	if (suspend) {
-		/* Make sure CRTC2 is reset. Remove that the day we decide to
-		 * actually use CRTC2 and replace it with real code for disabling
-		 * the CRTC2 output during sleep
-		 */
-		aty_st_le32(CRTC2_GEN_CNTL, aty_ld_le32(CRTC2_GEN_CNTL) &
-			~(CRTC2_EN));
-
-		/* Set the power management mode to be PCI based */
-		/* Use this magic value for now */
-		pmgt = 0x0c005407;
-		aty_st_pll(POWER_MANAGEMENT, pmgt);
-		(void)aty_ld_pll(POWER_MANAGEMENT);
-		aty_st_le32(BUS_CNTL1, 0x00000010);
-		aty_st_le32(MEM_POWER_MISC, 0x0c830000);
-		mdelay(100);
-
-		/* Switch PCI power management to D2 */
-		pci_set_power_state(pdev, PCI_D2);
-	}
-}
-
-static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct aty128fb_par *par = info->par;
-
-	/* Because we may change PCI D state ourselves, we need to
-	 * first save the config space content so the core can
-	 * restore it properly on resume.
-	 */
-	pci_save_state(pdev);
-
-	/* We don't do anything but D2, for now we return 0, but
-	 * we may want to change that. How do we know if the BIOS
-	 * can properly take care of D3 ? Also, with swsusp, we
-	 * know we'll be rebooted, ...
-	 */
-#ifndef CONFIG_PPC_PMAC
-	/* HACK ALERT ! Once I find a proper way to say to each driver
-	 * individually what will happen with it's PCI slot, I'll change
-	 * that. On laptops, the AGP slot is just unclocked, so D2 is
-	 * expected, while on desktops, the card is powered off
-	 */
-	return 0;
-#endif /* CONFIG_PPC_PMAC */
-	 
-	if (state.event == pdev->dev.power.power_state.event)
-		return 0;
-
-	printk(KERN_DEBUG "aty128fb: suspending...\n");
-	
-	console_lock();
-
-	fb_set_suspend(info, 1);
-
-	/* Make sure engine is reset */
-	wait_for_idle(par);
-	aty128_reset_engine(par);
-	wait_for_idle(par);
-
-	/* Blank display and LCD */
-	aty128fb_blank(FB_BLANK_POWERDOWN, info);
-
-	/* Sleep */
-	par->asleep = 1;
-	par->lock_blank = 1;
-
-#ifdef CONFIG_PPC_PMAC
-	/* On powermac, we have hooks to properly suspend/resume AGP now,
-	 * use them here. We'll ultimately need some generic support here,
-	 * but the generic code isn't quite ready for that yet
-	 */
-	pmac_suspend_agp_for_card(pdev);
-#endif /* CONFIG_PPC_PMAC */
-
-	/* We need a way to make sure the fbdev layer will _not_ touch the
-	 * framebuffer before we put the chip to suspend state. On 2.4, I
-	 * used dummy fb ops, 2.5 need proper support for this at the
-	 * fbdev level
-	 */
-	if (state.event != PM_EVENT_ON)
-		aty128_set_suspend(par, 1);
-
-	console_unlock();
-
-	pdev->dev.power.power_state = state;
-
-	return 0;
-}
-
-static int aty128_do_resume(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct aty128fb_par *par = info->par;
-
-	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
-		return 0;
-
-	/* PCI state will have been restored by the core, so
-	 * we should be in D0 now with our config space fully
-	 * restored
-	 */
-
-	/* Wakeup chip */
-	aty128_set_suspend(par, 0);
-	par->asleep = 0;
-
-	/* Restore display & engine */
-	aty128_reset_engine(par);
-	wait_for_idle(par);
-	aty128fb_set_par(info);
-	fb_pan_display(info, &info->var);
-	fb_set_cmap(&info->cmap, info);
-
-	/* Refresh */
-	fb_set_suspend(info, 0);
-
-	/* Unblank */
-	par->lock_blank = 0;
-	aty128fb_blank(0, info);
-
-#ifdef CONFIG_PPC_PMAC
-	/* On powermac, we have hooks to properly suspend/resume AGP now,
-	 * use them here. We'll ultimately need some generic support here,
-	 * but the generic code isn't quite ready for that yet
-	 */
-	pmac_resume_agp_for_card(pdev);
-#endif /* CONFIG_PPC_PMAC */
-
-	pdev->dev.power.power_state = PMSG_ON;
-
-	printk(KERN_DEBUG "aty128fb: resumed !\n");
-
-	return 0;
-}
-
-static int aty128_pci_resume(struct pci_dev *pdev)
-{
-	int rc;
-
-	console_lock();
-	rc = aty128_do_resume(pdev);
-	console_unlock();
-
-	return rc;
-}
-
-
-static int aty128fb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("aty128fb", &option))
-		return -ENODEV;
-	aty128fb_setup(option);
-#endif
-
-	return pci_register_driver(&aty128fb_driver);
-}
-
-static void __exit aty128fb_exit(void)
-{
-	pci_unregister_driver(&aty128fb_driver);
-}
-
-module_init(aty128fb_init);
-
-module_exit(aty128fb_exit);
-
-MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
-MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
-MODULE_LICENSE("GPL");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-#ifdef CONFIG_MTRR
-module_param_named(nomtrr, mtrr, invbool, 0);
-MODULE_PARM_DESC(nomtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");
-#endif
-
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
deleted file mode 100644
index 1f39a62f899b..000000000000
--- a/drivers/video/aty/atyfb.h
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- *  ATI Frame Buffer Device Driver Core Definitions
- */
-
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-    /*
-     *  Elements of the hardware specific atyfb_par structure
-     */
-
-struct crtc {
-	u32 vxres;
-	u32 vyres;
-	u32 xoffset;
-	u32 yoffset;
-	u32 bpp;
-	u32 h_tot_disp;
-	u32 h_sync_strt_wid;
-	u32 v_tot_disp;
-	u32 v_sync_strt_wid;
-	u32 vline_crnt_vline;
-	u32 off_pitch;
-	u32 gen_cntl;
-	u32 dp_pix_width;	/* acceleration */
-	u32 dp_chain_mask;	/* acceleration */
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	u32 horz_stretching;
-	u32 vert_stretching;
-	u32 ext_vert_stretch;
-	u32 shadow_h_tot_disp;
-	u32 shadow_h_sync_strt_wid;
-	u32 shadow_v_tot_disp;
-	u32 shadow_v_sync_strt_wid;
-	u32 lcd_gen_cntl;
-	u32 lcd_config_panel;
-	u32 lcd_index;
-#endif
-};
-
-struct aty_interrupt {
-	wait_queue_head_t wait;
-	unsigned int count;
-	int pan_display;
-};
-
-struct pll_info {
-	int pll_max;
-	int pll_min;
-	int sclk, mclk, mclk_pm, xclk;
-	int ref_div;
-	int ref_clk;
-	int ecp_max;
-};
-
-typedef struct {
-	u16 unknown1;
-	u16 PCLK_min_freq;
-	u16 PCLK_max_freq;
-	u16 unknown2;
-	u16 ref_freq;
-	u16 ref_divider;
-	u16 unknown3;
-	u16 MCLK_pwd;
-	u16 MCLK_max_freq;
-	u16 XCLK_max_freq;
-	u16 SCLK_freq;
-} __attribute__ ((packed)) PLL_BLOCK_MACH64;
-
-struct pll_514 {
-	u8 m;
-	u8 n;
-};
-
-struct pll_18818 {
-	u32 program_bits;
-	u32 locationAddr;
-	u32 period_in_ps;
-	u32 post_divider;
-};
-
-struct pll_ct {
-	u8 pll_ref_div;
-	u8 pll_gen_cntl;
-	u8 mclk_fb_div;
-	u8 mclk_fb_mult; /* 2 ro 4 */
-	u8 sclk_fb_div;
-	u8 pll_vclk_cntl;
-	u8 vclk_post_div;
-	u8 vclk_fb_div;
-	u8 pll_ext_cntl;
-	u8 ext_vpll_cntl;
-	u8 spll_cntl2;
-	u32 dsp_config; /* Mach64 GTB DSP */
-	u32 dsp_on_off; /* Mach64 GTB DSP */
-	u32 dsp_loop_latency;
-	u32 fifo_size;
-	u32 xclkpagefaultdelay;
-	u32 xclkmaxrasdelay;
-	u8 xclk_ref_div;
-	u8 xclk_post_div;
-	u8 mclk_post_div_real;
-	u8 xclk_post_div_real;
-	u8 vclk_post_div_real;
-	u8 features;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	u32 xres; /* use for LCD stretching/scaling */
-#endif
-};
-
-/*
-	for pll_ct.features
-*/
-#define DONT_USE_SPLL 0x1
-#define DONT_USE_XDLL 0x2
-#define USE_CPUCLK    0x4
-#define POWERDOWN_PLL 0x8
-
-union aty_pll {
-	struct pll_ct ct;
-	struct pll_514 ibm514;
-	struct pll_18818 ics2595;
-};
-
-    /*
-     *  The hardware parameters for each card
-     */
-
-struct atyfb_par {
-	u32 pseudo_palette[16];
-	struct { u8 red, green, blue; } palette[256];
-	const struct aty_dac_ops *dac_ops;
-	const struct aty_pll_ops *pll_ops;
-	void __iomem *ati_regbase;
-	unsigned long clk_wr_offset; /* meaning overloaded, clock id by CT */
-	struct crtc crtc;
-	union aty_pll pll;
-	struct pll_info pll_limits;
-	u32 features;
-	u32 ref_clk_per;
-	u32 pll_per;
-	u32 mclk_per;
-	u32 xclk_per;
-	u8 bus_type;
-	u8 ram_type;
-	u8 mem_refresh_rate;
-	u16 pci_id;
-	u32 accel_flags;
-	int blitter_may_be_busy;
-	int asleep;
-	int lock_blank;
-	unsigned long res_start;
-	unsigned long res_size;
-	struct pci_dev *pdev;
-#ifdef __sparc__
-	struct pci_mmap_map *mmap_map;
-	u8 mmaped;
-#endif
-	int open;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	unsigned long bios_base_phys;
-	unsigned long bios_base;
-	unsigned long lcd_table;
-	u16 lcd_width;
-	u16 lcd_height;
-	u32 lcd_pixclock;
-	u16 lcd_refreshrate;
-	u16 lcd_htotal;
-	u16 lcd_hdisp;
-	u16 lcd_hsync_dly;
-	u16 lcd_hsync_len;
-	u16 lcd_vtotal;
-	u16 lcd_vdisp;
-	u16 lcd_vsync_len;
-	u16 lcd_right_margin;
-	u16 lcd_lower_margin;
-	u16 lcd_hblank_len;
-	u16 lcd_vblank_len;
-#endif
-	unsigned long aux_start; /* auxiliary aperture */
-	unsigned long aux_size;
-	struct aty_interrupt vblank;
-	unsigned long irq_flags;
-	unsigned int irq;
-	spinlock_t int_lock;
-#ifdef CONFIG_MTRR
-	int mtrr_aper;
-	int mtrr_reg;
-#endif
-	u32 mem_cntl;
-	struct crtc saved_crtc;
-	union aty_pll saved_pll;
-};
-
-    /*
-     *  ATI Mach64 features
-     */
-
-#define M64_HAS(feature)	((par)->features & (M64F_##feature))
-
-#define M64F_RESET_3D		0x00000001
-#define M64F_MAGIC_FIFO		0x00000002
-#define M64F_GTB_DSP		0x00000004
-#define M64F_FIFO_32		0x00000008
-#define M64F_SDRAM_MAGIC_PLL	0x00000010
-#define M64F_MAGIC_POSTDIV	0x00000020
-#define M64F_INTEGRATED		0x00000040
-#define M64F_CT_BUS		0x00000080
-#define M64F_VT_BUS		0x00000100
-#define M64F_MOBIL_BUS		0x00000200
-#define M64F_GX			0x00000400
-#define M64F_CT			0x00000800
-#define M64F_VT			0x00001000
-#define M64F_GT			0x00002000
-#define M64F_MAGIC_VRAM_SIZE	0x00004000
-#define M64F_G3_PB_1_1		0x00008000
-#define M64F_G3_PB_1024x768	0x00010000
-#define M64F_EXTRA_BRIGHT	0x00020000
-#define M64F_LT_LCD_REGS	0x00040000
-#define M64F_XL_DLL		0x00080000
-#define M64F_MFB_FORCE_4	0x00100000
-#define M64F_HW_TRIPLE		0x00200000
-#define M64F_XL_MEM		0x00400000
-    /*
-     *  Register access
-     */
-
-static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par)
-{
-	/* Hack for bloc 1, should be cleanly optimized by compiler */
-	if (regindex >= 0x400)
-		regindex -= 0x800;
-
-#ifdef CONFIG_ATARI
-	return in_le32(par->ati_regbase + regindex);
-#else
-	return readl(par->ati_regbase + regindex);
-#endif
-}
-
-static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *par)
-{
-	/* Hack for bloc 1, should be cleanly optimized by compiler */
-	if (regindex >= 0x400)
-		regindex -= 0x800;
-
-#ifdef CONFIG_ATARI
-	out_le32(par->ati_regbase + regindex, val);
-#else
-	writel(val, par->ati_regbase + regindex);
-#endif
-}
-
-static inline void aty_st_le16(int regindex, u16 val,
-			       const struct atyfb_par *par)
-{
-	/* Hack for bloc 1, should be cleanly optimized by compiler */
-	if (regindex >= 0x400)
-		regindex -= 0x800;
-#ifdef CONFIG_ATARI
-	out_le16(par->ati_regbase + regindex, val);
-#else
-	writel(val, par->ati_regbase + regindex);
-#endif
-}
-
-static inline u8 aty_ld_8(int regindex, const struct atyfb_par *par)
-{
-	/* Hack for bloc 1, should be cleanly optimized by compiler */
-	if (regindex >= 0x400)
-		regindex -= 0x800;
-#ifdef CONFIG_ATARI
-	return in_8(par->ati_regbase + regindex);
-#else
-	return readb(par->ati_regbase + regindex);
-#endif
-}
-
-static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par)
-{
-	/* Hack for bloc 1, should be cleanly optimized by compiler */
-	if (regindex >= 0x400)
-		regindex -= 0x800;
-
-#ifdef CONFIG_ATARI
-	out_8(par->ati_regbase + regindex, val);
-#else
-	writeb(val, par->ati_regbase + regindex);
-#endif
-}
-
-#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
-defined (CONFIG_FB_ATY_GENERIC_LCD) || defined (CONFIG_FB_ATY_BACKLIGHT)
-extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par);
-extern u32 aty_ld_lcd(int index, const struct atyfb_par *par);
-#endif
-
-    /*
-     *  DAC operations
-     */
-
-struct aty_dac_ops {
-	int (*set_dac) (const struct fb_info * info,
-		const union aty_pll * pll, u32 bpp, u32 accel);
-};
-
-extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */
-extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */
-extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */
-extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */
-extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
-
-
-    /*
-     *  Clock operations
-     */
-
-struct aty_pll_ops {
-	int (*var_to_pll) (const struct fb_info * info, u32 vclk_per, u32 bpp, union aty_pll * pll);
-	u32 (*pll_to_var) (const struct fb_info * info, const union aty_pll * pll);
-	void (*set_pll)   (const struct fb_info * info, const union aty_pll * pll);
-	void (*get_pll)   (const struct fb_info *info, union aty_pll * pll);
-	int (*init_pll)   (const struct fb_info * info, union aty_pll * pll);
-	void (*resume_pll)(const struct fb_info *info, union aty_pll *pll);
-};
-
-extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
-extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */
-extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */
-extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */
-extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */
-extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */
-extern const struct aty_pll_ops aty_pll_ct; /* Integrated */
-
-
-extern void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll);
-extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
-
-
-    /*
-     *  Hardware cursor support
-     */
-
-extern int aty_init_cursor(struct fb_info *info);
-
-    /*
-     *  Hardware acceleration
-     */
-
-static inline void wait_for_fifo(u16 entries, const struct atyfb_par *par)
-{
-	while ((aty_ld_le32(FIFO_STAT, par) & 0xffff) >
-	       ((u32) (0x8000 >> entries)));
-}
-
-static inline void wait_for_idle(struct atyfb_par *par)
-{
-	wait_for_fifo(16, par);
-	while ((aty_ld_le32(GUI_STAT, par) & 1) != 0);
-	par->blitter_may_be_busy = 0;
-}
-
-extern void aty_reset_engine(const struct atyfb_par *par);
-extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
-extern u8   aty_ld_pll_ct(int offset, const struct atyfb_par *par);
-
-void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
-
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
deleted file mode 100644
index c3d0074a32db..000000000000
--- a/drivers/video/aty/atyfb_base.c
+++ /dev/null
@@ -1,4029 +0,0 @@
-/*
- *  ATI Frame Buffer Device Driver Core
- *
- *	Copyright (C) 2004  Alex Kern <alex.kern@gmx.de>
- *	Copyright (C) 1997-2001  Geert Uytterhoeven
- *	Copyright (C) 1998  Bernd Harries
- *	Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- *
- *  This driver supports the following ATI graphics chips:
- *    - ATI Mach64
- *
- *  To do: add support for
- *    - ATI Rage128 (from aty128fb.c)
- *    - ATI Radeon (from radeonfb.c)
- *
- *  This driver is partly based on the PowerMac console driver:
- *
- *	Copyright (C) 1996 Paul Mackerras
- *
- *  and on the PowerMac ATI/mach64 display driver:
- *
- *	Copyright (C) 1997 Michael AK Tesch
- *
- *	      with work by Jon Howell
- *			   Harry AC Eaton
- *			   Anthony Tong <atong@uiuc.edu>
- *
- *  Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
- *  Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- *
- *  Many thanks to Nitya from ATI devrel for support and patience !
- */
-
-/******************************************************************************
-
-  TODO:
-
-    - cursor support on all cards and all ramdacs.
-    - cursor parameters controlable via ioctl()s.
-    - guess PLL and MCLK based on the original PLL register values initialized
-      by Open Firmware (if they are initialized). BIOS is done
-
-    (Anyone with Mac to help with this?)
-
-******************************************************************************/
-
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/compiler.h>
-#include <linux/console.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/backlight.h>
-#include <linux/reboot.h>
-#include <linux/dmi.h>
-
-#include <asm/io.h>
-#include <linux/uaccess.h>
-
-#include <video/mach64.h>
-#include "atyfb.h"
-#include "ati_ids.h"
-
-#ifdef __powerpc__
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include "../macmodes.h"
-#endif
-#ifdef __sparc__
-#include <asm/fbio.h>
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#endif
-
-#ifdef CONFIG_ADB_PMU
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#endif
-#ifdef CONFIG_BOOTX_TEXT
-#include <asm/btext.h>
-#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-/*
- * Debug flags.
- */
-#undef DEBUG
-/*#define DEBUG*/
-
-/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
-/*  - must be large enough to catch all GUI-Regs   */
-/*  - must be aligned to a PAGE boundary           */
-#define GUI_RESERVE	(1 * PAGE_SIZE)
-
-/* FIXME: remove the FAIL definition */
-#define FAIL(msg) do { \
-	if (!(var->activate & FB_ACTIVATE_TEST)) \
-		printk(KERN_CRIT "atyfb: " msg "\n"); \
-	return -EINVAL; \
-} while (0)
-#define FAIL_MAX(msg, x, _max_) do { \
-	if (x > _max_) { \
-		if (!(var->activate & FB_ACTIVATE_TEST)) \
-			printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
-		return -EINVAL; \
-	} \
-} while (0)
-#ifdef DEBUG
-#define DPRINTK(fmt, args...)	printk(KERN_DEBUG "atyfb: " fmt, ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#define PRINTKI(fmt, args...)	printk(KERN_INFO "atyfb: " fmt, ## args)
-#define PRINTKE(fmt, args...)	printk(KERN_ERR "atyfb: " fmt, ## args)
-
-#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
-defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
-static const u32 lt_lcd_regs[] = {
-	CNFG_PANEL_LG,
-	LCD_GEN_CNTL_LG,
-	DSTN_CONTROL_LG,
-	HFB_PITCH_ADDR_LG,
-	HORZ_STRETCHING_LG,
-	VERT_STRETCHING_LG,
-	0, /* EXT_VERT_STRETCH */
-	LT_GIO_LG,
-	POWER_MANAGEMENT_LG
-};
-
-void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
-{
-	if (M64_HAS(LT_LCD_REGS)) {
-		aty_st_le32(lt_lcd_regs[index], val, par);
-	} else {
-		unsigned long temp;
-
-		/* write addr byte */
-		temp = aty_ld_le32(LCD_INDEX, par);
-		aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
-		/* write the register value */
-		aty_st_le32(LCD_DATA, val, par);
-	}
-}
-
-u32 aty_ld_lcd(int index, const struct atyfb_par *par)
-{
-	if (M64_HAS(LT_LCD_REGS)) {
-		return aty_ld_le32(lt_lcd_regs[index], par);
-	} else {
-		unsigned long temp;
-
-		/* write addr byte */
-		temp = aty_ld_le32(LCD_INDEX, par);
-		aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
-		/* read the register value */
-		return aty_ld_le32(LCD_DATA, par);
-	}
-}
-#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
-
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-/*
- * ATIReduceRatio --
- *
- * Reduce a fraction by factoring out the largest common divider of the
- * fraction's numerator and denominator.
- */
-static void ATIReduceRatio(int *Numerator, int *Denominator)
-{
-	int Multiplier, Divider, Remainder;
-
-	Multiplier = *Numerator;
-	Divider = *Denominator;
-
-	while ((Remainder = Multiplier % Divider)) {
-		Multiplier = Divider;
-		Divider = Remainder;
-	}
-
-	*Numerator /= Divider;
-	*Denominator /= Divider;
-}
-#endif
-/*
- * The Hardware parameters for each card
- */
-
-struct pci_mmap_map {
-	unsigned long voff;
-	unsigned long poff;
-	unsigned long size;
-	unsigned long prot_flag;
-	unsigned long prot_mask;
-};
-
-static struct fb_fix_screeninfo atyfb_fix = {
-	.id		= "ATY Mach64",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep	= 8,
-	.ypanstep	= 1,
-};
-
-/*
- * Frame buffer device API
- */
-
-static int atyfb_open(struct fb_info *info, int user);
-static int atyfb_release(struct fb_info *info, int user);
-static int atyfb_check_var(struct fb_var_screeninfo *var,
-			   struct fb_info *info);
-static int atyfb_set_par(struct fb_info *info);
-static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info);
-static int atyfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info);
-static int atyfb_blank(int blank, struct fb_info *info);
-static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
-#ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
-#endif
-static int atyfb_sync(struct fb_info *info);
-
-/*
- * Internal routines
- */
-
-static int aty_init(struct fb_info *info);
-
-static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
-
-static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
-static int aty_var_to_crtc(const struct fb_info *info,
-			   const struct fb_var_screeninfo *var,
-			   struct crtc *crtc);
-static int aty_crtc_to_var(const struct crtc *crtc,
-			   struct fb_var_screeninfo *var);
-static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
-#ifdef CONFIG_PPC
-static int read_aty_sense(const struct atyfb_par *par);
-#endif
-
-static DEFINE_MUTEX(reboot_lock);
-static struct fb_info *reboot_info;
-
-/*
- * Interface used by the world
- */
-
-static struct fb_var_screeninfo default_var = {
-	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-	640, 480, 640, 480, 0, 0, 8, 0,
-	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
-
-static struct fb_videomode defmode = {
-	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
-	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
-
-static struct fb_ops atyfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= atyfb_open,
-	.fb_release	= atyfb_release,
-	.fb_check_var	= atyfb_check_var,
-	.fb_set_par	= atyfb_set_par,
-	.fb_setcolreg	= atyfb_setcolreg,
-	.fb_pan_display	= atyfb_pan_display,
-	.fb_blank	= atyfb_blank,
-	.fb_ioctl	= atyfb_ioctl,
-	.fb_fillrect	= atyfb_fillrect,
-	.fb_copyarea	= atyfb_copyarea,
-	.fb_imageblit	= atyfb_imageblit,
-#ifdef __sparc__
-	.fb_mmap	= atyfb_mmap,
-#endif
-	.fb_sync	= atyfb_sync,
-};
-
-static bool noaccel;
-#ifdef CONFIG_MTRR
-static bool nomtrr;
-#endif
-static int vram;
-static int pll;
-static int mclk;
-static int xclk;
-static int comp_sync = -1;
-static char *mode;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight = 1;
-#else
-static int backlight = 0;
-#endif
-
-#ifdef CONFIG_PPC
-static int default_vmode = VMODE_CHOOSE;
-static int default_cmode = CMODE_CHOOSE;
-
-module_param_named(vmode, default_vmode, int, 0);
-MODULE_PARM_DESC(vmode, "int: video mode for mac");
-module_param_named(cmode, default_cmode, int, 0);
-MODULE_PARM_DESC(cmode, "int: color mode for mac");
-#endif
-
-#ifdef CONFIG_ATARI
-static unsigned int mach64_count = 0;
-static unsigned long phys_vmembase[FB_MAX] = { 0, };
-static unsigned long phys_size[FB_MAX] = { 0, };
-static unsigned long phys_guiregbase[FB_MAX] = { 0, };
-#endif
-
-/* top -> down is an evolution of mach64 chipset, any corrections? */
-#define ATI_CHIP_88800GX   (M64F_GX)
-#define ATI_CHIP_88800CX   (M64F_GX)
-
-#define ATI_CHIP_264CT     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
-#define ATI_CHIP_264ET     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
-
-#define ATI_CHIP_264VT     (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
-#define ATI_CHIP_264GT     (M64F_GT | M64F_INTEGRATED               | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
-
-#define ATI_CHIP_264VTB    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
-#define ATI_CHIP_264VT3    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
-#define ATI_CHIP_264VT4    (M64F_VT | M64F_INTEGRATED               | M64F_GTB_DSP)
-
-/* FIXME what is this chip? */
-#define ATI_CHIP_264LT     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP)
-
-/* make sets shorter */
-#define ATI_MODERN_SET     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
-
-#define ATI_CHIP_264GTB    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
-/*#define ATI_CHIP_264GTDVD  ?*/
-#define ATI_CHIP_264LTG    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
-
-#define ATI_CHIP_264GT2C   (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
-#define ATI_CHIP_264GTPRO  (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
-#define ATI_CHIP_264LTPRO  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
-
-#define ATI_CHIP_264XL     (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM)
-#define ATI_CHIP_MOBILITY  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS)
-
-static struct {
-	u16 pci_id;
-	const char *name;
-	int pll, mclk, xclk, ecp_max;
-	u32 features;
-} aty_chips[] = {
-#ifdef CONFIG_FB_ATY_GX
-	/* Mach64 GX */
-	{ PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
-	{ PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
-#endif /* CONFIG_FB_ATY_GX */
-
-#ifdef CONFIG_FB_ATY_CT
-	{ PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
-	{ PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
-
-	/* FIXME what is this chip? */
-	{ PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
-
-	{ PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
-	{ PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
-
-	{ PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
-	{ PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
-
-	{ PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
-
-	{ PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
-
-	{ PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
-	{ PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
-	{ PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
-	{ PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
-
-	{ PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
-	{ PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
-	{ PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
-	{ PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
-	{ PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
-
-	{ PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
-	{ PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
-	{ PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
-	{ PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 },
-	{ PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
-
-	{ PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
-	{ PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
-
-	{ PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
-	{ PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
-	{ PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
-	{ PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
-#endif /* CONFIG_FB_ATY_CT */
-};
-
-static int correct_chipset(struct atyfb_par *par)
-{
-	u8 rev;
-	u16 type;
-	u32 chip_id;
-	const char *name;
-	int i;
-
-	for (i = (int)ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
-		if (par->pci_id == aty_chips[i].pci_id)
-			break;
-
-	if (i < 0)
-		return -ENODEV;
-
-	name = aty_chips[i].name;
-	par->pll_limits.pll_max = aty_chips[i].pll;
-	par->pll_limits.mclk = aty_chips[i].mclk;
-	par->pll_limits.xclk = aty_chips[i].xclk;
-	par->pll_limits.ecp_max = aty_chips[i].ecp_max;
-	par->features = aty_chips[i].features;
-
-	chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
-	type = chip_id & CFG_CHIP_TYPE;
-	rev = (chip_id & CFG_CHIP_REV) >> 24;
-
-	switch (par->pci_id) {
-#ifdef CONFIG_FB_ATY_GX
-	case PCI_CHIP_MACH64GX:
-		if (type != 0x00d7)
-			return -ENODEV;
-		break;
-	case PCI_CHIP_MACH64CX:
-		if (type != 0x0057)
-			return -ENODEV;
-		break;
-#endif
-#ifdef CONFIG_FB_ATY_CT
-	case PCI_CHIP_MACH64VT:
-		switch (rev & 0x07) {
-		case 0x00:
-			switch (rev & 0xc0) {
-			case 0x00:
-				name = "ATI264VT (A3) (Mach64 VT)";
-				par->pll_limits.pll_max = 170;
-				par->pll_limits.mclk = 67;
-				par->pll_limits.xclk = 67;
-				par->pll_limits.ecp_max = 80;
-				par->features = ATI_CHIP_264VT;
-				break;
-			case 0x40:
-				name = "ATI264VT2 (A4) (Mach64 VT)";
-				par->pll_limits.pll_max = 200;
-				par->pll_limits.mclk = 67;
-				par->pll_limits.xclk = 67;
-				par->pll_limits.ecp_max = 80;
-				par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
-				break;
-			}
-			break;
-		case 0x01:
-			name = "ATI264VT3 (B1) (Mach64 VT)";
-			par->pll_limits.pll_max = 200;
-			par->pll_limits.mclk = 67;
-			par->pll_limits.xclk = 67;
-			par->pll_limits.ecp_max = 80;
-			par->features = ATI_CHIP_264VTB;
-			break;
-		case 0x02:
-			name = "ATI264VT3 (B2) (Mach64 VT)";
-			par->pll_limits.pll_max = 200;
-			par->pll_limits.mclk = 67;
-			par->pll_limits.xclk = 67;
-			par->pll_limits.ecp_max = 80;
-			par->features = ATI_CHIP_264VT3;
-			break;
-		}
-		break;
-	case PCI_CHIP_MACH64GT:
-		switch (rev & 0x07) {
-		case 0x01:
-			name = "3D RAGE II (Mach64 GT)";
-			par->pll_limits.pll_max = 170;
-			par->pll_limits.mclk = 67;
-			par->pll_limits.xclk = 67;
-			par->pll_limits.ecp_max = 80;
-			par->features = ATI_CHIP_264GTB;
-			break;
-		case 0x02:
-			name = "3D RAGE II+ (Mach64 GT)";
-			par->pll_limits.pll_max = 200;
-			par->pll_limits.mclk = 67;
-			par->pll_limits.xclk = 67;
-			par->pll_limits.ecp_max = 100;
-			par->features = ATI_CHIP_264GTB;
-			break;
-		}
-		break;
-#endif
-	}
-
-	PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
-	return 0;
-}
-
-static char ram_dram[] __maybe_unused = "DRAM";
-static char ram_resv[] __maybe_unused = "RESV";
-#ifdef CONFIG_FB_ATY_GX
-static char ram_vram[] = "VRAM";
-#endif /* CONFIG_FB_ATY_GX */
-#ifdef CONFIG_FB_ATY_CT
-static char ram_edo[] = "EDO";
-static char ram_sdram[] = "SDRAM (1:1)";
-static char ram_sgram[] = "SGRAM (1:1)";
-static char ram_sdram32[] = "SDRAM (2:1) (32-bit)";
-static char ram_wram[] = "WRAM";
-static char ram_off[] = "OFF";
-#endif /* CONFIG_FB_ATY_CT */
-
-
-#ifdef CONFIG_FB_ATY_GX
-static char *aty_gx_ram[8] = {
-	ram_dram, ram_vram, ram_vram, ram_dram,
-	ram_dram, ram_vram, ram_vram, ram_resv
-};
-#endif /* CONFIG_FB_ATY_GX */
-
-#ifdef CONFIG_FB_ATY_CT
-static char *aty_ct_ram[8] = {
-	ram_off, ram_dram, ram_edo, ram_edo,
-	ram_sdram, ram_sgram, ram_wram, ram_resv
-};
-static char *aty_xl_ram[8] = {
-	ram_off, ram_dram, ram_edo, ram_edo,
-	ram_sdram, ram_sgram, ram_sdram32, ram_resv
-};
-#endif /* CONFIG_FB_ATY_CT */
-
-static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var,
-			      struct atyfb_par *par)
-{
-	u32 pixclock = var->pixclock;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	u32 lcd_on_off;
-	par->pll.ct.xres = 0;
-	if (par->lcd_table != 0) {
-		lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
-		if (lcd_on_off & LCD_ON) {
-			par->pll.ct.xres = var->xres;
-			pixclock = par->lcd_pixclock;
-		}
-	}
-#endif
-	return pixclock;
-}
-
-#if defined(CONFIG_PPC)
-
-/*
- * Apple monitor sense
- */
-
-static int read_aty_sense(const struct atyfb_par *par)
-{
-	int sense, i;
-
-	aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */
-	__delay(200);
-	aty_st_le32(GP_IO, 0, par); /* turn off outputs */
-	__delay(2000);
-	i = aty_ld_le32(GP_IO, par); /* get primary sense value */
-	sense = ((i & 0x3000) >> 3) | (i & 0x100);
-
-	/* drive each sense line low in turn and collect the other 2 */
-	aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */
-	__delay(2000);
-	i = aty_ld_le32(GP_IO, par);
-	sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
-	aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */
-	__delay(200);
-
-	aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */
-	__delay(2000);
-	i = aty_ld_le32(GP_IO, par);
-	sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
-	aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */
-	__delay(200);
-
-	aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */
-	__delay(2000);
-	sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;
-	aty_st_le32(GP_IO, 0, par); /* turn off outputs */
-	return sense;
-}
-
-#endif /* defined(CONFIG_PPC) */
-
-/* ------------------------------------------------------------------------- */
-
-/*
- * CRTC programming
- */
-
-static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
-{
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		if (!M64_HAS(LT_LCD_REGS)) {
-			crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
-			aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
-		}
-		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);
-		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
-
-
-		/* switch to non shadow registers */
-		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
-			   ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
-
-		/* save stretching */
-		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
-		crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
-		if (!M64_HAS(LT_LCD_REGS))
-			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
-	}
-#endif
-	crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
-	crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
-	crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
-	crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
-	crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);
-	crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);
-	crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
-
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		/* switch to shadow registers */
-		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
-			   SHADOW_EN | SHADOW_RW_EN, par);
-
-		crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
-		crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
-		crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
-		crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
-
-		aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
-	}
-#endif /* CONFIG_FB_ATY_GENERIC_LCD */
-}
-
-static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
-{
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		/* stop CRTC */
-		aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl &
-			    ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
-
-		/* update non-shadow registers first */
-		aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);
-		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
-			   ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
-
-		/* temporarily disable stretching */
-		aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching &
-			   ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
-		aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching &
-			   ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
-			     VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
-	}
-#endif
-	/* turn off CRT */
-	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
-
-	DPRINTK("setting up CRTC\n");
-	DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
-		((((crtc->h_tot_disp >> 16) & 0xff) + 1) << 3),
-		(((crtc->v_tot_disp >> 16) & 0x7ff) + 1),
-		(crtc->h_sync_strt_wid & 0x200000) ? 'N' : 'P',
-		(crtc->v_sync_strt_wid & 0x200000) ? 'N' : 'P',
-		(crtc->gen_cntl & CRTC_CSYNC_EN) ? 'P' : 'N');
-
-	DPRINTK("CRTC_H_TOTAL_DISP: %x\n", crtc->h_tot_disp);
-	DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n", crtc->h_sync_strt_wid);
-	DPRINTK("CRTC_V_TOTAL_DISP: %x\n", crtc->v_tot_disp);
-	DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n", crtc->v_sync_strt_wid);
-	DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
-	DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
-	DPRINTK("CRTC_GEN_CNTL: %x\n", crtc->gen_cntl);
-
-	aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
-	aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
-	aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
-	aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
-	aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
-	aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
-
-	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
-#if 0
-	FIXME
-	if (par->accel_flags & FB_ACCELF_TEXT)
-		aty_init_engine(par, info);
-#endif
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	/* after setting the CRTC registers we should set the LCD registers. */
-	if (par->lcd_table != 0) {
-		/* switch to shadow registers */
-		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
-			   SHADOW_EN | SHADOW_RW_EN, par);
-
-		DPRINTK("set shadow CRT to %ix%i %c%c\n",
-			((((crtc->shadow_h_tot_disp >> 16) & 0xff) + 1) << 3),
-			(((crtc->shadow_v_tot_disp >> 16) & 0x7ff) + 1),
-			(crtc->shadow_h_sync_strt_wid & 0x200000) ? 'N' : 'P',
-			(crtc->shadow_v_sync_strt_wid & 0x200000) ? 'N' : 'P');
-
-		DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n",
-			crtc->shadow_h_tot_disp);
-		DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n",
-			crtc->shadow_h_sync_strt_wid);
-		DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n",
-			crtc->shadow_v_tot_disp);
-		DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n",
-			crtc->shadow_v_sync_strt_wid);
-
-		aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
-		aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
-		aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
-		aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
-
-		/* restore CRTC selection & shadow state and enable stretching */
-		DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
-		DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
-		DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
-		if (!M64_HAS(LT_LCD_REGS))
-			DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
-
-		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
-		aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
-		aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
-		if (!M64_HAS(LT_LCD_REGS)) {
-			aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
-			aty_ld_le32(LCD_INDEX, par);
-			aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
-		}
-	}
-#endif /* CONFIG_FB_ATY_GENERIC_LCD */
-}
-
-static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp)
-{
-	u32 line_length = vxres * bpp / 8;
-
-	if (par->ram_type == SGRAM ||
-	    (!M64_HAS(XL_MEM) && par->ram_type == WRAM))
-		line_length = (line_length + 63) & ~63;
-
-	return line_length;
-}
-
-static int aty_var_to_crtc(const struct fb_info *info,
-			   const struct fb_var_screeninfo *var,
-			   struct crtc *crtc)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
-	u32 sync, vmode, vdisplay;
-	u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
-	u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
-	u32 pix_width, dp_pix_width, dp_chain_mask;
-	u32 line_length;
-
-	/* input */
-	xres = (var->xres + 7) & ~7;
-	yres = var->yres;
-	vxres = (var->xres_virtual + 7) & ~7;
-	vyres = var->yres_virtual;
-	xoffset = (var->xoffset + 7) & ~7;
-	yoffset = var->yoffset;
-	bpp = var->bits_per_pixel;
-	if (bpp == 16)
-		bpp = (var->green.length == 5) ? 15 : 16;
-	sync = var->sync;
-	vmode = var->vmode;
-
-	/* convert (and round up) and validate */
-	if (vxres < xres + xoffset)
-		vxres = xres + xoffset;
-	h_disp = xres;
-
-	if (vyres < yres + yoffset)
-		vyres = yres + yoffset;
-	v_disp = yres;
-
-	if (bpp <= 8) {
-		bpp = 8;
-		pix_width = CRTC_PIX_WIDTH_8BPP;
-		dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
-			BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = DP_CHAIN_8BPP;
-	} else if (bpp <= 15) {
-		bpp = 16;
-		pix_width = CRTC_PIX_WIDTH_15BPP;
-		dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
-			BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = DP_CHAIN_15BPP;
-	} else if (bpp <= 16) {
-		bpp = 16;
-		pix_width = CRTC_PIX_WIDTH_16BPP;
-		dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
-			BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = DP_CHAIN_16BPP;
-	} else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
-		bpp = 24;
-		pix_width = CRTC_PIX_WIDTH_24BPP;
-		dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
-			BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = DP_CHAIN_24BPP;
-	} else if (bpp <= 32) {
-		bpp = 32;
-		pix_width = CRTC_PIX_WIDTH_32BPP;
-		dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
-			BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = DP_CHAIN_32BPP;
-	} else
-		FAIL("invalid bpp");
-
-	line_length = calc_line_length(par, vxres, bpp);
-
-	if (vyres * line_length > info->fix.smem_len)
-		FAIL("not enough video RAM");
-
-	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
-	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
-	if ((xres > 1920) || (yres > 1200)) {
-		FAIL("MACH64 chips are designed for max 1920x1200\n"
-		     "select another resolution.");
-	}
-	h_sync_strt = h_disp + var->right_margin;
-	h_sync_end = h_sync_strt + var->hsync_len;
-	h_sync_dly  = var->right_margin & 7;
-	h_total = h_sync_end + h_sync_dly + var->left_margin;
-
-	v_sync_strt = v_disp + var->lower_margin;
-	v_sync_end = v_sync_strt + var->vsync_len;
-	v_total = v_sync_end + var->upper_margin;
-
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		if (!M64_HAS(LT_LCD_REGS)) {
-			u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
-			crtc->lcd_index = lcd_index &
-				~(LCD_INDEX_MASK | LCD_DISPLAY_DIS |
-				  LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
-			aty_st_le32(LCD_INDEX, lcd_index, par);
-		}
-
-		if (!M64_HAS(MOBIL_BUS))
-			crtc->lcd_index |= CRTC2_DISPLAY_DIS;
-
-		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000;
-		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
-
-		crtc->lcd_gen_cntl &=
-			~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
-			/*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
-			USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
-		crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
-
-		if ((crtc->lcd_gen_cntl & LCD_ON) &&
-		    ((xres > par->lcd_width) || (yres > par->lcd_height))) {
-			/*
-			 * We cannot display the mode on the LCD. If the CRT is
-			 * enabled we can turn off the LCD.
-			 * If the CRT is off, it isn't a good idea to switch it
-			 * on; we don't know if one is connected. So it's better
-			 * to fail then.
-			 */
-			if (crtc->lcd_gen_cntl & CRT_ON) {
-				if (!(var->activate & FB_ACTIVATE_TEST))
-					PRINTKI("Disable LCD panel, because video mode does not fit.\n");
-				crtc->lcd_gen_cntl &= ~LCD_ON;
-				/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
-			} else {
-				if (!(var->activate & FB_ACTIVATE_TEST))
-					PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
-				return -EINVAL;
-			}
-		}
-	}
-
-	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
-		int VScan = 1;
-		/* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
-		const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
-		const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 };  */
-
-		vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
-
-		/*
-		 * This is horror! When we simulate, say 640x480 on an 800x600
-		 * LCD monitor, the CRTC should be programmed 800x600 values for
-		 * the non visible part, but 640x480 for the visible part.
-		 * This code has been tested on a laptop with it's 1400x1050 LCD
-		 * monitor and a conventional monitor both switched on.
-		 * Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
-		 * works with little glitches also with DOUBLESCAN modes
-		 */
-		if (yres < par->lcd_height) {
-			VScan = par->lcd_height / yres;
-			if (VScan > 1) {
-				VScan = 2;
-				vmode |= FB_VMODE_DOUBLE;
-			}
-		}
-
-		h_sync_strt = h_disp + par->lcd_right_margin;
-		h_sync_end = h_sync_strt + par->lcd_hsync_len;
-		h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;
-		h_total = h_disp + par->lcd_hblank_len;
-
-		v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
-		v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
-		v_total = v_disp + par->lcd_vblank_len / VScan;
-	}
-#endif /* CONFIG_FB_ATY_GENERIC_LCD */
-
-	h_disp = (h_disp >> 3) - 1;
-	h_sync_strt = (h_sync_strt >> 3) - 1;
-	h_sync_end = (h_sync_end >> 3) - 1;
-	h_total = (h_total >> 3) - 1;
-	h_sync_wid = h_sync_end - h_sync_strt;
-
-	FAIL_MAX("h_disp too large", h_disp, 0xff);
-	FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
-	/*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
-	if (h_sync_wid > 0x1f)
-		h_sync_wid = 0x1f;
-	FAIL_MAX("h_total too large", h_total, 0x1ff);
-
-	if (vmode & FB_VMODE_DOUBLE) {
-		v_disp <<= 1;
-		v_sync_strt <<= 1;
-		v_sync_end <<= 1;
-		v_total <<= 1;
-	}
-
-	vdisplay = yres;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))
-		vdisplay  = par->lcd_height;
-#endif
-
-	v_disp--;
-	v_sync_strt--;
-	v_sync_end--;
-	v_total--;
-	v_sync_wid = v_sync_end - v_sync_strt;
-
-	FAIL_MAX("v_disp too large", v_disp, 0x7ff);
-	FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
-	/*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
-	if (v_sync_wid > 0x1f)
-		v_sync_wid = 0x1f;
-	FAIL_MAX("v_total too large", v_total, 0x7ff);
-
-	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
-
-	/* output */
-	crtc->vxres = vxres;
-	crtc->vyres = vyres;
-	crtc->xoffset = xoffset;
-	crtc->yoffset = yoffset;
-	crtc->bpp = bpp;
-	crtc->off_pitch =
-		((yoffset * line_length + xoffset * bpp / 8) / 8) |
-		((line_length / bpp) << 22);
-	crtc->vline_crnt_vline = 0;
-
-	crtc->h_tot_disp = h_total | (h_disp << 16);
-	crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) |
-		((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) |
-		(h_sync_pol << 21);
-	crtc->v_tot_disp = v_total | (v_disp << 16);
-	crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
-		(v_sync_pol << 21);
-
-	/* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
-	crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
-	crtc->gen_cntl |= CRTC_VGA_LINEAR;
-
-	/* Enable doublescan mode if requested */
-	if (vmode & FB_VMODE_DOUBLE)
-		crtc->gen_cntl |= CRTC_DBL_SCAN_EN;
-	/* Enable interlaced mode if requested */
-	if (vmode & FB_VMODE_INTERLACED)
-		crtc->gen_cntl |= CRTC_INTERLACE_EN;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		vdisplay = yres;
-		if (vmode & FB_VMODE_DOUBLE)
-			vdisplay <<= 1;
-		crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
-		crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
-					/*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
-					USE_SHADOWED_VEND |
-					USE_SHADOWED_ROWCUR |
-					SHADOW_EN | SHADOW_RW_EN);
-		crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR/* | LOCK_8DOT*/;
-
-		/* MOBILITY M1 tested, FIXME: LT */
-		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
-		if (!M64_HAS(LT_LCD_REGS))
-			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
-				~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
-
-		crtc->horz_stretching &= ~(HORZ_STRETCH_RATIO |
-					   HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
-					   HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
-		if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
-			do {
-				/*
-				 * The horizontal blender misbehaves when
-				 * HDisplay is less than a certain threshold
-				 * (440 for a 1024-wide panel).  It doesn't
-				 * stretch such modes enough.  Use pixel
-				 * replication instead of blending to stretch
-				 * modes that can be made to exactly fit the
-				 * panel width.  The undocumented "NoLCDBlend"
-				 * option allows the pixel-replicated mode to
-				 * be slightly wider or narrower than the
-				 * panel width.  It also causes a mode that is
-				 * exactly half as wide as the panel to be
-				 * pixel-replicated, rather than blended.
-				 */
-				int HDisplay  = xres & ~7;
-				int nStretch  = par->lcd_width / HDisplay;
-				int Remainder = par->lcd_width % HDisplay;
-
-				if ((!Remainder && ((nStretch > 2))) ||
-				    (((HDisplay * 16) / par->lcd_width) < 7)) {
-					static const char StretchLoops[] = { 10, 12, 13, 15, 16 };
-					int horz_stretch_loop = -1, BestRemainder;
-					int Numerator = HDisplay, Denominator = par->lcd_width;
-					int Index = 5;
-					ATIReduceRatio(&Numerator, &Denominator);
-
-					BestRemainder = (Numerator * 16) / Denominator;
-					while (--Index >= 0) {
-						Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %
-							Denominator;
-						if (Remainder < BestRemainder) {
-							horz_stretch_loop = Index;
-							if (!(BestRemainder = Remainder))
-								break;
-						}
-					}
-
-					if ((horz_stretch_loop >= 0) && !BestRemainder) {
-						int horz_stretch_ratio = 0, Accumulator = 0;
-						int reuse_previous = 1;
-
-						Index = StretchLoops[horz_stretch_loop];
-
-						while (--Index >= 0) {
-							if (Accumulator > 0)
-								horz_stretch_ratio |= reuse_previous;
-							else
-								Accumulator += Denominator;
-							Accumulator -= Numerator;
-							reuse_previous <<= 1;
-						}
-
-						crtc->horz_stretching |= (HORZ_STRETCH_EN |
-							((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |
-							(horz_stretch_ratio & HORZ_STRETCH_RATIO));
-						break;      /* Out of the do { ... } while (0) */
-					}
-				}
-
-				crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |
-					(((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));
-			} while (0);
-		}
-
-		if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
-			crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
-				(((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
-
-			if (!M64_HAS(LT_LCD_REGS) &&
-			    xres <= (M64_HAS(MOBIL_BUS) ? 1024 : 800))
-				crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
-		} else {
-			/*
-			 * Don't use vertical blending if the mode is too wide
-			 * or not vertically stretched.
-			 */
-			crtc->vert_stretching = 0;
-		}
-		/* copy to shadow crtc */
-		crtc->shadow_h_tot_disp = crtc->h_tot_disp;
-		crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
-		crtc->shadow_v_tot_disp = crtc->v_tot_disp;
-		crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
-	}
-#endif /* CONFIG_FB_ATY_GENERIC_LCD */
-
-	if (M64_HAS(MAGIC_FIFO)) {
-		/* FIXME: display FIFO low watermark values */
-		crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
-	}
-	crtc->dp_pix_width = dp_pix_width;
-	crtc->dp_chain_mask = dp_chain_mask;
-
-	return 0;
-}
-
-static int aty_crtc_to_var(const struct crtc *crtc,
-			   struct fb_var_screeninfo *var)
-{
-	u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
-	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
-	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
-	u32 pix_width;
-	u32 double_scan, interlace;
-
-	/* input */
-	h_total = crtc->h_tot_disp & 0x1ff;
-	h_disp = (crtc->h_tot_disp >> 16) & 0xff;
-	h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
-	h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
-	h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
-	h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
-	v_total = crtc->v_tot_disp & 0x7ff;
-	v_disp = (crtc->v_tot_disp >> 16) & 0x7ff;
-	v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
-	v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;
-	v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
-	c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
-	pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
-	double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
-	interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
-
-	/* convert */
-	xres = (h_disp + 1) * 8;
-	yres = v_disp + 1;
-	left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly;
-	right = (h_sync_strt - h_disp) * 8 + h_sync_dly;
-	hslen = h_sync_wid * 8;
-	upper = v_total - v_sync_strt - v_sync_wid;
-	lower = v_sync_strt - v_disp;
-	vslen = v_sync_wid;
-	sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
-		(v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
-		(c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
-
-	switch (pix_width) {
-#if 0
-	case CRTC_PIX_WIDTH_4BPP:
-		bpp = 4;
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-#endif
-	case CRTC_PIX_WIDTH_8BPP:
-		bpp = 8;
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case CRTC_PIX_WIDTH_15BPP:	/* RGB 555 */
-		bpp = 16;
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case CRTC_PIX_WIDTH_16BPP:	/* RGB 565 */
-		bpp = 16;
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case CRTC_PIX_WIDTH_24BPP:	/* RGB 888 */
-		bpp = 24;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case CRTC_PIX_WIDTH_32BPP:	/* ARGB 8888 */
-		bpp = 32;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	default:
-		PRINTKE("Invalid pixel width\n");
-		return -EINVAL;
-	}
-
-	/* output */
-	var->xres = xres;
-	var->yres = yres;
-	var->xres_virtual = crtc->vxres;
-	var->yres_virtual = crtc->vyres;
-	var->bits_per_pixel = bpp;
-	var->left_margin = left;
-	var->right_margin = right;
-	var->upper_margin = upper;
-	var->lower_margin = lower;
-	var->hsync_len = hslen;
-	var->vsync_len = vslen;
-	var->sync = sync;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	/*
-	 * In double scan mode, the vertical parameters are doubled,
-	 * so we need to halve them to get the right values.
-	 * In interlaced mode the values are already correct,
-	 * so no correction is necessary.
-	 */
-	if (interlace)
-		var->vmode = FB_VMODE_INTERLACED;
-
-	if (double_scan) {
-		var->vmode = FB_VMODE_DOUBLE;
-		var->yres >>= 1;
-		var->upper_margin >>= 1;
-		var->lower_margin >>= 1;
-		var->vsync_len >>= 1;
-	}
-
-	return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int atyfb_set_par(struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	u32 tmp, pixclock;
-	int err;
-#ifdef DEBUG
-	struct fb_var_screeninfo debug;
-	u32 pixclock_in_ps;
-#endif
-	if (par->asleep)
-		return 0;
-
-	err = aty_var_to_crtc(info, var, &par->crtc);
-	if (err)
-		return err;
-
-	pixclock = atyfb_get_pixclock(var, par);
-
-	if (pixclock == 0) {
-		PRINTKE("Invalid pixclock\n");
-		return -EINVAL;
-	} else {
-		err = par->pll_ops->var_to_pll(info, pixclock,
-					       var->bits_per_pixel, &par->pll);
-		if (err)
-			return err;
-	}
-
-	par->accel_flags = var->accel_flags; /* hack */
-
-	if (var->accel_flags) {
-		info->fbops->fb_sync = atyfb_sync;
-		info->flags &= ~FBINFO_HWACCEL_DISABLED;
-	} else {
-		info->fbops->fb_sync = NULL;
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-	}
-
-	if (par->blitter_may_be_busy)
-		wait_for_idle(par);
-
-	aty_set_crtc(par, &par->crtc);
-	par->dac_ops->set_dac(info, &par->pll,
-			      var->bits_per_pixel, par->accel_flags);
-	par->pll_ops->set_pll(info, &par->pll);
-
-#ifdef DEBUG
-	if (par->pll_ops && par->pll_ops->pll_to_var)
-		pixclock_in_ps = par->pll_ops->pll_to_var(info, &par->pll);
-	else
-		pixclock_in_ps = 0;
-
-	if (0 == pixclock_in_ps) {
-		PRINTKE("ALERT ops->pll_to_var get 0\n");
-		pixclock_in_ps = pixclock;
-	}
-
-	memset(&debug, 0, sizeof(debug));
-	if (!aty_crtc_to_var(&par->crtc, &debug)) {
-		u32 hSync, vRefresh;
-		u32 h_disp, h_sync_strt, h_sync_end, h_total;
-		u32 v_disp, v_sync_strt, v_sync_end, v_total;
-
-		h_disp = debug.xres;
-		h_sync_strt = h_disp + debug.right_margin;
-		h_sync_end = h_sync_strt + debug.hsync_len;
-		h_total = h_sync_end + debug.left_margin;
-		v_disp = debug.yres;
-		v_sync_strt = v_disp + debug.lower_margin;
-		v_sync_end = v_sync_strt + debug.vsync_len;
-		v_total = v_sync_end + debug.upper_margin;
-
-		hSync = 1000000000 / (pixclock_in_ps * h_total);
-		vRefresh = (hSync * 1000) / v_total;
-		if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
-			vRefresh *= 2;
-		if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
-			vRefresh /= 2;
-
-		DPRINTK("atyfb_set_par\n");
-		DPRINTK(" Set Visible Mode to %ix%i-%i\n",
-			var->xres, var->yres, var->bits_per_pixel);
-		DPRINTK(" Virtual resolution %ix%i, "
-			"pixclock_in_ps %i (calculated %i)\n",
-			var->xres_virtual, var->yres_virtual,
-			pixclock, pixclock_in_ps);
-		DPRINTK(" Dot clock:           %i MHz\n",
-			1000000 / pixclock_in_ps);
-		DPRINTK(" Horizontal sync:     %i kHz\n", hSync);
-		DPRINTK(" Vertical refresh:    %i Hz\n", vRefresh);
-		DPRINTK(" x  style: %i.%03i %i %i %i %i   %i %i %i %i\n",
-			1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
-			h_disp, h_sync_strt, h_sync_end, h_total,
-			v_disp, v_sync_strt, v_sync_end, v_total);
-		DPRINTK(" fb style: %i  %i %i %i %i %i %i %i %i\n",
-			pixclock_in_ps,
-			debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
-			debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
-	}
-#endif /* DEBUG */
-
-	if (!M64_HAS(INTEGRATED)) {
-		/* Don't forget MEM_CNTL */
-		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
-		switch (var->bits_per_pixel) {
-		case 8:
-			tmp |= 0x02000000;
-			break;
-		case 16:
-			tmp |= 0x03000000;
-			break;
-		case 32:
-			tmp |= 0x06000000;
-			break;
-		}
-		aty_st_le32(MEM_CNTL, tmp, par);
-	} else {
-		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
-		if (!M64_HAS(MAGIC_POSTDIV))
-			tmp |= par->mem_refresh_rate << 20;
-		switch (var->bits_per_pixel) {
-		case 8:
-		case 24:
-			tmp |= 0x00000000;
-			break;
-		case 16:
-			tmp |= 0x04000000;
-			break;
-		case 32:
-			tmp |= 0x08000000;
-			break;
-		}
-		if (M64_HAS(CT_BUS)) {
-			aty_st_le32(DAC_CNTL, 0x87010184, par);
-			aty_st_le32(BUS_CNTL, 0x680000f9, par);
-		} else if (M64_HAS(VT_BUS)) {
-			aty_st_le32(DAC_CNTL, 0x87010184, par);
-			aty_st_le32(BUS_CNTL, 0x680000f9, par);
-		} else if (M64_HAS(MOBIL_BUS)) {
-			aty_st_le32(DAC_CNTL, 0x80010102, par);
-			aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
-		} else {
-			/* GT */
-			aty_st_le32(DAC_CNTL, 0x86010102, par);
-			aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
-			aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
-		}
-		aty_st_le32(MEM_CNTL, tmp, par);
-	}
-	aty_st_8(DAC_MASK, 0xff, par);
-
-	info->fix.line_length = calc_line_length(par, var->xres_virtual,
-						 var->bits_per_pixel);
-
-	info->fix.visual = var->bits_per_pixel <= 8 ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
-	/* Initialize the graphics engine */
-	if (par->accel_flags & FB_ACCELF_TEXT)
-		aty_init_engine(par, info);
-
-#ifdef CONFIG_BOOTX_TEXT
-	btext_update_display(info->fix.smem_start,
-		(((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
-		((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
-		var->bits_per_pixel,
-		par->crtc.vxres * var->bits_per_pixel / 8);
-#endif /* CONFIG_BOOTX_TEXT */
-#if 0
-	/* switch to accelerator mode */
-	if (!(par->crtc.gen_cntl & CRTC_EXT_DISP_EN))
-		aty_st_le32(CRTC_GEN_CNTL, par->crtc.gen_cntl | CRTC_EXT_DISP_EN, par);
-#endif
-#ifdef DEBUG
-{
-	/* dump non shadow CRTC, pll, LCD registers */
-	int i; u32 base;
-
-	/* CRTC registers */
-	base = 0x2000;
-	printk("debug atyfb: Mach64 non-shadow register values:");
-	for (i = 0; i < 256; i = i+4) {
-		if (i % 16 == 0)
-			printk("\ndebug atyfb: 0x%04X: ", base + i);
-		printk(" %08X", aty_ld_le32(i, par));
-	}
-	printk("\n\n");
-
-#ifdef CONFIG_FB_ATY_CT
-	/* PLL registers */
-	base = 0x00;
-	printk("debug atyfb: Mach64 PLL register values:");
-	for (i = 0; i < 64; i++) {
-		if (i % 16 == 0)
-			printk("\ndebug atyfb: 0x%02X: ", base + i);
-		if (i % 4 == 0)
-			printk(" ");
-		printk("%02X", aty_ld_pll_ct(i, par));
-	}
-	printk("\n\n");
-#endif	/* CONFIG_FB_ATY_CT */
-
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		/* LCD registers */
-		base = 0x00;
-		printk("debug atyfb: LCD register values:");
-		if (M64_HAS(LT_LCD_REGS)) {
-			for (i = 0; i <= POWER_MANAGEMENT; i++) {
-				if (i == EXT_VERT_STRETCH)
-					continue;
-				printk("\ndebug atyfb: 0x%04X: ",
-				       lt_lcd_regs[i]);
-				printk(" %08X", aty_ld_lcd(i, par));
-			}
-		} else {
-			for (i = 0; i < 64; i++) {
-				if (i % 4 == 0)
-					printk("\ndebug atyfb: 0x%02X: ",
-					       base + i);
-				printk(" %08X", aty_ld_lcd(i, par));
-			}
-		}
-		printk("\n\n");
-	}
-#endif /* CONFIG_FB_ATY_GENERIC_LCD */
-}
-#endif /* DEBUG */
-	return 0;
-}
-
-static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	int err;
-	struct crtc crtc;
-	union aty_pll pll;
-	u32 pixclock;
-
-	memcpy(&pll, &par->pll, sizeof(pll));
-
-	err = aty_var_to_crtc(info, var, &crtc);
-	if (err)
-		return err;
-
-	pixclock = atyfb_get_pixclock(var, par);
-
-	if (pixclock == 0) {
-		if (!(var->activate & FB_ACTIVATE_TEST))
-			PRINTKE("Invalid pixclock\n");
-		return -EINVAL;
-	} else {
-		err = par->pll_ops->var_to_pll(info, pixclock,
-					       var->bits_per_pixel, &pll);
-		if (err)
-			return err;
-	}
-
-	if (var->accel_flags & FB_ACCELF_TEXT)
-		info->var.accel_flags = FB_ACCELF_TEXT;
-	else
-		info->var.accel_flags = 0;
-
-	aty_crtc_to_var(&crtc, var);
-	var->pixclock = par->pll_ops->pll_to_var(info, &pll);
-	return 0;
-}
-
-static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
-{
-	u32 xoffset = info->var.xoffset;
-	u32 yoffset = info->var.yoffset;
-	u32 line_length = info->fix.line_length;
-	u32 bpp = info->var.bits_per_pixel;
-
-	par->crtc.off_pitch =
-		((yoffset * line_length + xoffset * bpp / 8) / 8) |
-		((line_length / bpp) << 22);
-}
-
-
-/*
- * Open/Release the frame buffer device
- */
-
-static int atyfb_open(struct fb_info *info, int user)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	if (user) {
-		par->open++;
-#ifdef __sparc__
-		par->mmaped = 0;
-#endif
-	}
-	return 0;
-}
-
-static irqreturn_t aty_irq(int irq, void *dev_id)
-{
-	struct atyfb_par *par = dev_id;
-	int handled = 0;
-	u32 int_cntl;
-
-	spin_lock(&par->int_lock);
-
-	int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
-
-	if (int_cntl & CRTC_VBLANK_INT) {
-		/* clear interrupt */
-		aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) |
-			    CRTC_VBLANK_INT_AK, par);
-		par->vblank.count++;
-		if (par->vblank.pan_display) {
-			par->vblank.pan_display = 0;
-			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
-		}
-		wake_up_interruptible(&par->vblank.wait);
-		handled = 1;
-	}
-
-	spin_unlock(&par->int_lock);
-
-	return IRQ_RETVAL(handled);
-}
-
-static int aty_enable_irq(struct atyfb_par *par, int reenable)
-{
-	u32 int_cntl;
-
-	if (!test_and_set_bit(0, &par->irq_flags)) {
-		if (request_irq(par->irq, aty_irq, IRQF_SHARED, "atyfb", par)) {
-			clear_bit(0, &par->irq_flags);
-			return -EINVAL;
-		}
-		spin_lock_irq(&par->int_lock);
-		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
-		/* clear interrupt */
-		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
-		/* enable interrupt */
-		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
-		spin_unlock_irq(&par->int_lock);
-	} else if (reenable) {
-		spin_lock_irq(&par->int_lock);
-		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
-		if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
-			printk("atyfb: someone disabled IRQ [%08x]\n",
-			       int_cntl);
-			/* re-enable interrupt */
-			aty_st_le32(CRTC_INT_CNTL, int_cntl |
-				    CRTC_VBLANK_INT_EN, par);
-		}
-		spin_unlock_irq(&par->int_lock);
-	}
-
-	return 0;
-}
-
-static int aty_disable_irq(struct atyfb_par *par)
-{
-	u32 int_cntl;
-
-	if (test_and_clear_bit(0, &par->irq_flags)) {
-		if (par->vblank.pan_display) {
-			par->vblank.pan_display = 0;
-			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
-		}
-		spin_lock_irq(&par->int_lock);
-		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
-		/* disable interrupt */
-		aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par);
-		spin_unlock_irq(&par->int_lock);
-		free_irq(par->irq, par);
-	}
-
-	return 0;
-}
-
-static int atyfb_release(struct fb_info *info, int user)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-#ifdef __sparc__
-	int was_mmaped;
-#endif
-
-	if (!user)
-		return 0;
-
-	par->open--;
-	mdelay(1);
-	wait_for_idle(par);
-
-	if (par->open)
-		return 0;
-
-#ifdef __sparc__
-	was_mmaped = par->mmaped;
-
-	par->mmaped = 0;
-
-	if (was_mmaped) {
-		struct fb_var_screeninfo var;
-
-		/*
-		 * Now reset the default display config, we have
-		 * no idea what the program(s) which mmap'd the
-		 * chip did to the configuration, nor whether it
-		 * restored it correctly.
-		 */
-		var = default_var;
-		if (noaccel)
-			var.accel_flags &= ~FB_ACCELF_TEXT;
-		else
-			var.accel_flags |= FB_ACCELF_TEXT;
-		if (var.yres == var.yres_virtual) {
-			u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
-			var.yres_virtual =
-				((videoram * 8) / var.bits_per_pixel) /
-				var.xres_virtual;
-			if (var.yres_virtual < var.yres)
-				var.yres_virtual = var.yres;
-		}
-	}
-#endif
-	aty_disable_irq(par);
-
-	return 0;
-}
-
-/*
- * Pan or Wrap the Display
- *
- * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- */
-
-static int atyfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 xres, yres, xoffset, yoffset;
-
-	xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
-	yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
-	if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
-		yres >>= 1;
-	xoffset = (var->xoffset + 7) & ~7;
-	yoffset = var->yoffset;
-	if (xoffset + xres > par->crtc.vxres ||
-	    yoffset + yres > par->crtc.vyres)
-		return -EINVAL;
-	info->var.xoffset = xoffset;
-	info->var.yoffset = yoffset;
-	if (par->asleep)
-		return 0;
-
-	set_off_pitch(par, info);
-	if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
-		par->vblank.pan_display = 1;
-	} else {
-		par->vblank.pan_display = 0;
-		aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
-	}
-
-	return 0;
-}
-
-static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
-{
-	struct aty_interrupt *vbl;
-	unsigned int count;
-	int ret;
-
-	switch (crtc) {
-	case 0:
-		vbl = &par->vblank;
-		break;
-	default:
-		return -ENODEV;
-	}
-
-	ret = aty_enable_irq(par, 0);
-	if (ret)
-		return ret;
-
-	count = vbl->count;
-	ret = wait_event_interruptible_timeout(vbl->wait,
-					       count != vbl->count, HZ/10);
-	if (ret < 0)
-		return ret;
-	if (ret == 0) {
-		aty_enable_irq(par, 1);
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-
-#ifdef DEBUG
-#define ATYIO_CLKR		0x41545900	/* ATY\00 */
-#define ATYIO_CLKW		0x41545901	/* ATY\01 */
-
-struct atyclk {
-	u32 ref_clk_per;
-	u8 pll_ref_div;
-	u8 mclk_fb_div;
-	u8 mclk_post_div;	/* 1,2,3,4,8 */
-	u8 mclk_fb_mult;	/* 2 or 4 */
-	u8 xclk_post_div;	/* 1,2,3,4,8 */
-	u8 vclk_fb_div;
-	u8 vclk_post_div;	/* 1,2,3,4,6,8,12 */
-	u32 dsp_xclks_per_row;	/* 0-16383 */
-	u32 dsp_loop_latency;	/* 0-15 */
-	u32 dsp_precision;	/* 0-7 */
-	u32 dsp_on;		/* 0-2047 */
-	u32 dsp_off;		/* 0-2047 */
-};
-
-#define ATYIO_FEATR		0x41545902	/* ATY\02 */
-#define ATYIO_FEATW		0x41545903	/* ATY\03 */
-#endif
-
-static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-#ifdef __sparc__
-	struct fbtype fbtyp;
-#endif
-
-	switch (cmd) {
-#ifdef __sparc__
-	case FBIOGTYPE:
-		fbtyp.fb_type = FBTYPE_PCI_GENERIC;
-		fbtyp.fb_width = par->crtc.vxres;
-		fbtyp.fb_height = par->crtc.vyres;
-		fbtyp.fb_depth = info->var.bits_per_pixel;
-		fbtyp.fb_cmsize = info->cmap.len;
-		fbtyp.fb_size = info->fix.smem_len;
-		if (copy_to_user((struct fbtype __user *) arg, &fbtyp,
-				 sizeof(fbtyp)))
-			return -EFAULT;
-		break;
-#endif /* __sparc__ */
-
-	case FBIO_WAITFORVSYNC:
-		{
-			u32 crtc;
-
-			if (get_user(crtc, (__u32 __user *) arg))
-				return -EFAULT;
-
-			return aty_waitforvblank(par, crtc);
-		}
-
-#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
-	case ATYIO_CLKR:
-		if (M64_HAS(INTEGRATED)) {
-			struct atyclk clk;
-			union aty_pll *pll = &par->pll;
-			u32 dsp_config = pll->ct.dsp_config;
-			u32 dsp_on_off = pll->ct.dsp_on_off;
-			clk.ref_clk_per = par->ref_clk_per;
-			clk.pll_ref_div = pll->ct.pll_ref_div;
-			clk.mclk_fb_div = pll->ct.mclk_fb_div;
-			clk.mclk_post_div = pll->ct.mclk_post_div_real;
-			clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
-			clk.xclk_post_div = pll->ct.xclk_post_div_real;
-			clk.vclk_fb_div = pll->ct.vclk_fb_div;
-			clk.vclk_post_div = pll->ct.vclk_post_div_real;
-			clk.dsp_xclks_per_row = dsp_config & 0x3fff;
-			clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;
-			clk.dsp_precision = (dsp_config >> 20) & 7;
-			clk.dsp_off = dsp_on_off & 0x7ff;
-			clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;
-			if (copy_to_user((struct atyclk __user *) arg, &clk,
-					 sizeof(clk)))
-				return -EFAULT;
-		} else
-			return -EINVAL;
-		break;
-	case ATYIO_CLKW:
-		if (M64_HAS(INTEGRATED)) {
-			struct atyclk clk;
-			union aty_pll *pll = &par->pll;
-			if (copy_from_user(&clk, (struct atyclk __user *) arg,
-					   sizeof(clk)))
-				return -EFAULT;
-			par->ref_clk_per = clk.ref_clk_per;
-			pll->ct.pll_ref_div = clk.pll_ref_div;
-			pll->ct.mclk_fb_div = clk.mclk_fb_div;
-			pll->ct.mclk_post_div_real = clk.mclk_post_div;
-			pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
-			pll->ct.xclk_post_div_real = clk.xclk_post_div;
-			pll->ct.vclk_fb_div = clk.vclk_fb_div;
-			pll->ct.vclk_post_div_real = clk.vclk_post_div;
-			pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
-				((clk.dsp_loop_latency & 0xf) << 16) |
-				((clk.dsp_precision & 7) << 20);
-			pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) |
-				((clk.dsp_on & 0x7ff) << 16);
-			/*aty_calc_pll_ct(info, &pll->ct);*/
-			aty_set_pll_ct(info, pll);
-		} else
-			return -EINVAL;
-		break;
-	case ATYIO_FEATR:
-		if (get_user(par->features, (u32 __user *) arg))
-			return -EFAULT;
-		break;
-	case ATYIO_FEATW:
-		if (put_user(par->features, (u32 __user *) arg))
-			return -EFAULT;
-		break;
-#endif /* DEBUG && CONFIG_FB_ATY_CT */
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int atyfb_sync(struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	if (par->blitter_may_be_busy)
-		wait_for_idle(par);
-	return 0;
-}
-
-#ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	unsigned int size, page, map_size = 0;
-	unsigned long map_offset = 0;
-	unsigned long off;
-	int i;
-
-	if (!par->mmap_map)
-		return -ENXIO;
-
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-	size = vma->vm_end - vma->vm_start;
-
-	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
-
-	if (((vma->vm_pgoff == 0) && (size == info->fix.smem_len)) ||
-	    ((off == info->fix.smem_len) && (size == PAGE_SIZE)))
-		off += 0x8000000000000000UL;
-
-	vma->vm_pgoff = off >> PAGE_SHIFT;	/* propagate off changes */
-
-	/* Each page, see which map applies */
-	for (page = 0; page < size;) {
-		map_size = 0;
-		for (i = 0; par->mmap_map[i].size; i++) {
-			unsigned long start = par->mmap_map[i].voff;
-			unsigned long end = start + par->mmap_map[i].size;
-			unsigned long offset = off + page;
-
-			if (start > offset)
-				continue;
-			if (offset >= end)
-				continue;
-
-			map_size = par->mmap_map[i].size - (offset - start);
-			map_offset = par->mmap_map[i].poff + (offset - start);
-			break;
-		}
-		if (!map_size) {
-			page += PAGE_SIZE;
-			continue;
-		}
-		if (page + map_size > size)
-			map_size = size - page;
-
-		pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
-		pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
-
-		if (remap_pfn_range(vma, vma->vm_start + page,
-			map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
-			return -EAGAIN;
-
-		page += map_size;
-	}
-
-	if (!map_size)
-		return -EINVAL;
-
-	if (!par->mmaped)
-		par->mmaped = 1;
-	return 0;
-}
-#endif /* __sparc__ */
-
-
-
-#if defined(CONFIG_PM) && defined(CONFIG_PCI)
-
-#ifdef CONFIG_PPC_PMAC
-/* Power management routines. Those are used for PowerBook sleep.
- */
-static int aty_power_mgmt(int sleep, struct atyfb_par *par)
-{
-	u32 pm;
-	int timeout;
-
-	pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
-	aty_st_lcd(POWER_MANAGEMENT, pm, par);
-	pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-
-	timeout = 2000;
-	if (sleep) {
-		/* Sleep */
-		pm &= ~PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-		udelay(10);
-		pm &= ~(PWR_BLON | AUTO_PWR_UP);
-		pm |= SUSPEND_NOW;
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-		do {
-			pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-			mdelay(1);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
-	} else {
-		/* Wakeup */
-		pm &= ~PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-		udelay(10);
-		pm &= ~SUSPEND_NOW;
-		pm |= (PWR_BLON | AUTO_PWR_UP);
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-		do {
-			pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-			mdelay(1);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
-	}
-	mdelay(500);
-
-	return timeout ? 0 : -EIO;
-}
-#endif /* CONFIG_PPC_PMAC */
-
-static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	if (state.event == pdev->dev.power.power_state.event)
-		return 0;
-
-	console_lock();
-
-	fb_set_suspend(info, 1);
-
-	/* Idle & reset engine */
-	wait_for_idle(par);
-	aty_reset_engine(par);
-
-	/* Blank display and LCD */
-	atyfb_blank(FB_BLANK_POWERDOWN, info);
-
-	par->asleep = 1;
-	par->lock_blank = 1;
-
-	/*
-	 * Because we may change PCI D state ourselves, we need to
-	 * first save the config space content so the core can
-	 * restore it properly on resume.
-	 */
-	pci_save_state(pdev);
-
-#ifdef CONFIG_PPC_PMAC
-	/* Set chip to "suspend" mode */
-	if (machine_is(powermac) && aty_power_mgmt(1, par)) {
-		par->asleep = 0;
-		par->lock_blank = 0;
-		atyfb_blank(FB_BLANK_UNBLANK, info);
-		fb_set_suspend(info, 0);
-		console_unlock();
-		return -EIO;
-	}
-#else
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-#endif
-
-	console_unlock();
-
-	pdev->dev.power.power_state = state;
-
-	return 0;
-}
-
-static void aty_resume_chip(struct fb_info *info)
-{
-	struct atyfb_par *par = info->par;
-
-	aty_st_le32(MEM_CNTL, par->mem_cntl, par);
-
-	if (par->pll_ops->resume_pll)
-		par->pll_ops->resume_pll(info, &par->pll);
-
-	if (par->aux_start)
-		aty_st_le32(BUS_CNTL,
-			aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
-}
-
-static int atyfb_pci_resume(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
-		return 0;
-
-	console_lock();
-
-	/*
-	 * PCI state will have been restored by the core, so
-	 * we should be in D0 now with our config space fully
-	 * restored
-	 */
-
-#ifdef CONFIG_PPC_PMAC
-	if (machine_is(powermac) &&
-	    pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
-		aty_power_mgmt(0, par);
-#endif
-
-	aty_resume_chip(info);
-
-	par->asleep = 0;
-
-	/* Restore display */
-	atyfb_set_par(info);
-
-	/* Refresh */
-	fb_set_suspend(info, 0);
-
-	/* Unblank */
-	par->lock_blank = 0;
-	atyfb_blank(FB_BLANK_UNBLANK, info);
-
-	console_unlock();
-
-	pdev->dev.power.power_state = PMSG_ON;
-
-	return 0;
-}
-
-#endif /*  defined(CONFIG_PM) && defined(CONFIG_PCI) */
-
-/* Backlight */
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-#define MAX_LEVEL 0xFF
-
-static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
-{
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int atylevel;
-
-	/* Get and convert the value */
-	/* No locking of bl_curve since we read a single value */
-	atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
-
-	if (atylevel < 0)
-		atylevel = 0;
-	else if (atylevel > MAX_LEVEL)
-		atylevel = MAX_LEVEL;
-
-	return atylevel;
-}
-
-static int aty_bl_update_status(struct backlight_device *bd)
-{
-	struct atyfb_par *par = bl_get_data(bd);
-	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
-	int level;
-
-	if (bd->props.power != FB_BLANK_UNBLANK ||
-	    bd->props.fb_blank != FB_BLANK_UNBLANK)
-		level = 0;
-	else
-		level = bd->props.brightness;
-
-	reg |= (BLMOD_EN | BIASMOD_EN);
-	if (level > 0) {
-		reg &= ~BIAS_MOD_LEVEL_MASK;
-		reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
-	} else {
-		reg &= ~BIAS_MOD_LEVEL_MASK;
-		reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
-	}
-	aty_st_lcd(LCD_MISC_CNTL, reg, par);
-
-	return 0;
-}
-
-static int aty_bl_get_brightness(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
-static const struct backlight_ops aty_bl_data = {
-	.get_brightness = aty_bl_get_brightness,
-	.update_status	= aty_bl_update_status,
-};
-
-static void aty_bl_init(struct atyfb_par *par)
-{
-	struct backlight_properties props;
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	struct backlight_device *bd;
-	char name[12];
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (!pmac_has_backlight_type("ati"))
-		return;
-#endif
-
-	snprintf(name, sizeof(name), "atybl%d", info->node);
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
-	bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
-				       &props);
-	if (IS_ERR(bd)) {
-		info->bl_dev = NULL;
-		printk(KERN_WARNING "aty: Backlight registration failed\n");
-		goto error;
-	}
-
-	info->bl_dev = bd;
-	fb_bl_default_curve(info, 0,
-			    0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
-			    0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
-
-	bd->props.brightness = bd->props.max_brightness;
-	bd->props.power = FB_BLANK_UNBLANK;
-	backlight_update_status(bd);
-
-	printk("aty: Backlight initialized (%s)\n", name);
-
-	return;
-
-error:
-	return;
-}
-
-#ifdef CONFIG_PCI
-static void aty_bl_exit(struct backlight_device *bd)
-{
-	backlight_device_unregister(bd);
-	printk("aty: Backlight unloaded\n");
-}
-#endif /* CONFIG_PCI */
-
-#endif /* CONFIG_FB_ATY_BACKLIGHT */
-
-static void aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
-{
-	const int ragepro_tbl[] = {
-		44, 50, 55, 66, 75, 80, 100
-	};
-	const int ragexl_tbl[] = {
-		50, 66, 75, 83, 90, 95, 100, 105,
-		110, 115, 120, 125, 133, 143, 166
-	};
-	const int *refresh_tbl;
-	int i, size;
-
-	if (M64_HAS(XL_MEM)) {
-		refresh_tbl = ragexl_tbl;
-		size = ARRAY_SIZE(ragexl_tbl);
-	} else {
-		refresh_tbl = ragepro_tbl;
-		size = ARRAY_SIZE(ragepro_tbl);
-	}
-
-	for (i = 0; i < size; i++) {
-		if (xclk < refresh_tbl[i])
-			break;
-	}
-	par->mem_refresh_rate = i;
-}
-
-/*
- * Initialisation
- */
-
-static struct fb_info *fb_list = NULL;
-
-#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
-static int atyfb_get_timings_from_lcd(struct atyfb_par *par,
-				      struct fb_var_screeninfo *var)
-{
-	int ret = -EINVAL;
-
-	if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
-		*var = default_var;
-		var->xres = var->xres_virtual = par->lcd_hdisp;
-		var->right_margin = par->lcd_right_margin;
-		var->left_margin = par->lcd_hblank_len -
-			(par->lcd_right_margin + par->lcd_hsync_dly +
-			 par->lcd_hsync_len);
-		var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
-		var->yres = var->yres_virtual = par->lcd_vdisp;
-		var->lower_margin = par->lcd_lower_margin;
-		var->upper_margin = par->lcd_vblank_len -
-			(par->lcd_lower_margin + par->lcd_vsync_len);
-		var->vsync_len = par->lcd_vsync_len;
-		var->pixclock = par->lcd_pixclock;
-		ret = 0;
-	}
-
-	return ret;
-}
-#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
-
-static int aty_init(struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	const char *ramname = NULL, *xtal;
-	int gtb_memsize, has_var = 0;
-	struct fb_var_screeninfo var;
-	int ret;
-
-	init_waitqueue_head(&par->vblank.wait);
-	spin_lock_init(&par->int_lock);
-
-#ifdef CONFIG_FB_ATY_GX
-	if (!M64_HAS(INTEGRATED)) {
-		u32 stat0;
-		u8 dac_type, dac_subtype, clk_type;
-		stat0 = aty_ld_le32(CNFG_STAT0, par);
-		par->bus_type = (stat0 >> 0) & 0x07;
-		par->ram_type = (stat0 >> 3) & 0x07;
-		ramname = aty_gx_ram[par->ram_type];
-		/* FIXME: clockchip/RAMDAC probing? */
-		dac_type = (aty_ld_le32(DAC_CNTL, par) >> 16) & 0x07;
-#ifdef CONFIG_ATARI
-		clk_type = CLK_ATI18818_1;
-		dac_type = (stat0 >> 9) & 0x07;
-		if (dac_type == 0x07)
-			dac_subtype = DAC_ATT20C408;
-		else
-			dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) | dac_type;
-#else
-		dac_type = DAC_IBMRGB514;
-		dac_subtype = DAC_IBMRGB514;
-		clk_type = CLK_IBMRGB514;
-#endif
-		switch (dac_subtype) {
-		case DAC_IBMRGB514:
-			par->dac_ops = &aty_dac_ibm514;
-			break;
-#ifdef CONFIG_ATARI
-		case DAC_ATI68860_B:
-		case DAC_ATI68860_C:
-			par->dac_ops = &aty_dac_ati68860b;
-			break;
-		case DAC_ATT20C408:
-		case DAC_ATT21C498:
-			par->dac_ops = &aty_dac_att21c498;
-			break;
-#endif
-		default:
-			PRINTKI("aty_init: DAC type not implemented yet!\n");
-			par->dac_ops = &aty_dac_unsupported;
-			break;
-		}
-		switch (clk_type) {
-#ifdef CONFIG_ATARI
-		case CLK_ATI18818_1:
-			par->pll_ops = &aty_pll_ati18818_1;
-			break;
-#else
-		case CLK_IBMRGB514:
-			par->pll_ops = &aty_pll_ibm514;
-			break;
-#endif
-#if 0 /* dead code */
-		case CLK_STG1703:
-			par->pll_ops = &aty_pll_stg1703;
-			break;
-		case CLK_CH8398:
-			par->pll_ops = &aty_pll_ch8398;
-			break;
-		case CLK_ATT20C408:
-			par->pll_ops = &aty_pll_att20c408;
-			break;
-#endif
-		default:
-			PRINTKI("aty_init: CLK type not implemented yet!");
-			par->pll_ops = &aty_pll_unsupported;
-			break;
-		}
-	}
-#endif /* CONFIG_FB_ATY_GX */
-#ifdef CONFIG_FB_ATY_CT
-	if (M64_HAS(INTEGRATED)) {
-		par->dac_ops = &aty_dac_ct;
-		par->pll_ops = &aty_pll_ct;
-		par->bus_type = PCI;
-		par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
-		if (M64_HAS(XL_MEM))
-			ramname = aty_xl_ram[par->ram_type];
-		else
-			ramname = aty_ct_ram[par->ram_type];
-		/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
-		if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
-			par->pll_limits.mclk = 63;
-		/* Mobility + 32bit memory interface need halved XCLK. */
-		if (M64_HAS(MOBIL_BUS) && par->ram_type == SDRAM32)
-			par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1;
-	}
-#endif
-#ifdef CONFIG_PPC_PMAC
-	/*
-	 * The Apple iBook1 uses non-standard memory frequencies.
-	 * We detect it and set the frequency manually.
-	 */
-	if (of_machine_is_compatible("PowerBook2,1")) {
-		par->pll_limits.mclk = 70;
-		par->pll_limits.xclk = 53;
-	}
-#endif
-
-	/* Allow command line to override clocks. */
-	if (pll)
-		par->pll_limits.pll_max = pll;
-	if (mclk)
-		par->pll_limits.mclk = mclk;
-	if (xclk)
-		par->pll_limits.xclk = xclk;
-
-	aty_calc_mem_refresh(par, par->pll_limits.xclk);
-	par->pll_per = 1000000/par->pll_limits.pll_max;
-	par->mclk_per = 1000000/par->pll_limits.mclk;
-	par->xclk_per = 1000000/par->pll_limits.xclk;
-
-	par->ref_clk_per = 1000000000000ULL / 14318180;
-	xtal = "14.31818";
-
-#ifdef CONFIG_FB_ATY_CT
-	if (M64_HAS(GTB_DSP)) {
-		u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
-
-		if (pll_ref_div) {
-			int diff1, diff2;
-			diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
-			diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
-			if (diff1 < 0)
-				diff1 = -diff1;
-			if (diff2 < 0)
-				diff2 = -diff2;
-			if (diff2 < diff1) {
-				par->ref_clk_per = 1000000000000ULL / 29498928;
-				xtal = "29.498928";
-			}
-		}
-	}
-#endif /* CONFIG_FB_ATY_CT */
-
-	/* save previous video mode */
-	aty_get_crtc(par, &par->saved_crtc);
-	if (par->pll_ops->get_pll)
-		par->pll_ops->get_pll(info, &par->saved_pll);
-
-	par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
-	gtb_memsize = M64_HAS(GTB_DSP);
-	if (gtb_memsize)
-		/* 0xF used instead of MEM_SIZE_ALIAS */
-		switch (par->mem_cntl & 0xF) {
-		case MEM_SIZE_512K:
-			info->fix.smem_len = 0x80000;
-			break;
-		case MEM_SIZE_1M:
-			info->fix.smem_len = 0x100000;
-			break;
-		case MEM_SIZE_2M_GTB:
-			info->fix.smem_len = 0x200000;
-			break;
-		case MEM_SIZE_4M_GTB:
-			info->fix.smem_len = 0x400000;
-			break;
-		case MEM_SIZE_6M_GTB:
-			info->fix.smem_len = 0x600000;
-			break;
-		case MEM_SIZE_8M_GTB:
-			info->fix.smem_len = 0x800000;
-			break;
-		default:
-			info->fix.smem_len = 0x80000;
-	} else
-		switch (par->mem_cntl & MEM_SIZE_ALIAS) {
-		case MEM_SIZE_512K:
-			info->fix.smem_len = 0x80000;
-			break;
-		case MEM_SIZE_1M:
-			info->fix.smem_len = 0x100000;
-			break;
-		case MEM_SIZE_2M:
-			info->fix.smem_len = 0x200000;
-			break;
-		case MEM_SIZE_4M:
-			info->fix.smem_len = 0x400000;
-			break;
-		case MEM_SIZE_6M:
-			info->fix.smem_len = 0x600000;
-			break;
-		case MEM_SIZE_8M:
-			info->fix.smem_len = 0x800000;
-			break;
-		default:
-			info->fix.smem_len = 0x80000;
-		}
-
-	if (M64_HAS(MAGIC_VRAM_SIZE)) {
-		if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000)
-			info->fix.smem_len += 0x400000;
-	}
-
-	if (vram) {
-		info->fix.smem_len = vram * 1024;
-		par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
-		if (info->fix.smem_len <= 0x80000)
-			par->mem_cntl |= MEM_SIZE_512K;
-		else if (info->fix.smem_len <= 0x100000)
-			par->mem_cntl |= MEM_SIZE_1M;
-		else if (info->fix.smem_len <= 0x200000)
-			par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
-		else if (info->fix.smem_len <= 0x400000)
-			par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
-		else if (info->fix.smem_len <= 0x600000)
-			par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
-		else
-			par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
-		aty_st_le32(MEM_CNTL, par->mem_cntl, par);
-	}
-
-	/*
-	 * Reg Block 0 (CT-compatible block) is at mmio_start
-	 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
-	 */
-	if (M64_HAS(GX)) {
-		info->fix.mmio_len = 0x400;
-		info->fix.accel = FB_ACCEL_ATI_MACH64GX;
-	} else if (M64_HAS(CT)) {
-		info->fix.mmio_len = 0x400;
-		info->fix.accel = FB_ACCEL_ATI_MACH64CT;
-	} else if (M64_HAS(VT)) {
-		info->fix.mmio_start -= 0x400;
-		info->fix.mmio_len = 0x800;
-		info->fix.accel = FB_ACCEL_ATI_MACH64VT;
-	} else {/* GT */
-		info->fix.mmio_start -= 0x400;
-		info->fix.mmio_len = 0x800;
-		info->fix.accel = FB_ACCEL_ATI_MACH64GT;
-	}
-
-	PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
-		info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len>>20),
-		info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal,
-		par->pll_limits.pll_max, par->pll_limits.mclk,
-		par->pll_limits.xclk);
-
-#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
-	if (M64_HAS(INTEGRATED)) {
-		int i;
-		printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL "
-		       "EXT_MEM_CNTL CRTC_GEN_CNTL DSP_CONFIG "
-		       "DSP_ON_OFF CLOCK_CNTL\n"
-		       "debug atyfb: %08x %08x %08x "
-		       "%08x     %08x      %08x   "
-		       "%08x   %08x\n"
-		       "debug atyfb: PLL",
-		       aty_ld_le32(BUS_CNTL, par),
-		       aty_ld_le32(DAC_CNTL, par),
-		       aty_ld_le32(MEM_CNTL, par),
-		       aty_ld_le32(EXT_MEM_CNTL, par),
-		       aty_ld_le32(CRTC_GEN_CNTL, par),
-		       aty_ld_le32(DSP_CONFIG, par),
-		       aty_ld_le32(DSP_ON_OFF, par),
-		       aty_ld_le32(CLOCK_CNTL, par));
-		for (i = 0; i < 40; i++)
-			printk(" %02x", aty_ld_pll_ct(i, par));
-		printk("\n");
-	}
-#endif
-	if (par->pll_ops->init_pll)
-		par->pll_ops->init_pll(info, &par->pll);
-	if (par->pll_ops->resume_pll)
-		par->pll_ops->resume_pll(info, &par->pll);
-
-	/*
-	 * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
-	 * unless the auxiliary register aperture is used.
-	 */
-	if (!par->aux_start &&
-	    (info->fix.smem_len == 0x800000 ||
-	     (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
-		info->fix.smem_len -= GUI_RESERVE;
-
-	/*
-	 * Disable register access through the linear aperture
-	 * if the auxiliary aperture is used so we can access
-	 * the full 8 MB of video RAM on 8 MB boards.
-	 */
-	if (par->aux_start)
-		aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) |
-			    BUS_APER_REG_DIS, par);
-
-#ifdef CONFIG_MTRR
-	par->mtrr_aper = -1;
-	par->mtrr_reg = -1;
-	if (!nomtrr) {
-		/* Cover the whole resource. */
-		par->mtrr_aper = mtrr_add(par->res_start, par->res_size,
-					  MTRR_TYPE_WRCOMB, 1);
-		if (par->mtrr_aper >= 0 && !par->aux_start) {
-			/* Make a hole for mmio. */
-			par->mtrr_reg = mtrr_add(par->res_start + 0x800000 -
-						 GUI_RESERVE, GUI_RESERVE,
-						 MTRR_TYPE_UNCACHABLE, 1);
-			if (par->mtrr_reg < 0) {
-				mtrr_del(par->mtrr_aper, 0, 0);
-				par->mtrr_aper = -1;
-			}
-		}
-	}
-#endif
-
-	info->fbops = &atyfb_ops;
-	info->pseudo_palette = par->pseudo_palette;
-	info->flags = FBINFO_DEFAULT           |
-		      FBINFO_HWACCEL_IMAGEBLIT |
-		      FBINFO_HWACCEL_FILLRECT  |
-		      FBINFO_HWACCEL_COPYAREA  |
-		      FBINFO_HWACCEL_YPAN      |
-		      FBINFO_READS_FAST;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (M64_HAS(G3_PB_1_1) && of_machine_is_compatible("PowerBook1,1")) {
-		/*
-		 * these bits let the 101 powerbook
-		 * wake up from sleep -- paulus
-		 */
-		aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) |
-			   USE_F32KHZ | TRISTATE_MEM_EN, par);
-	} else
-#endif
-	if (M64_HAS(MOBIL_BUS) && backlight) {
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-		aty_bl_init(par);
-#endif
-	}
-
-	memset(&var, 0, sizeof(var));
-#ifdef CONFIG_PPC
-	if (machine_is(powermac)) {
-		/*
-		 * FIXME: The NVRAM stuff should be put in a Mac-specific file,
-		 *        as it applies to all Mac video cards
-		 */
-		if (mode) {
-			if (mac_find_mode(&var, info, mode, 8))
-				has_var = 1;
-		} else {
-			if (default_vmode == VMODE_CHOOSE) {
-				int sense;
-				if (M64_HAS(G3_PB_1024x768))
-					/* G3 PowerBook with 1024x768 LCD */
-					default_vmode = VMODE_1024_768_60;
-				else if (of_machine_is_compatible("iMac"))
-					default_vmode = VMODE_1024_768_75;
-				else if (of_machine_is_compatible("PowerBook2,1"))
-					/* iBook with 800x600 LCD */
-					default_vmode = VMODE_800_600_60;
-				else
-					default_vmode = VMODE_640_480_67;
-				sense = read_aty_sense(par);
-				PRINTKI("monitor sense=%x, mode %d\n",
-					sense,  mac_map_monitor_sense(sense));
-			}
-			if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-				default_vmode = VMODE_640_480_60;
-			if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
-				default_cmode = CMODE_8;
-			if (!mac_vmode_to_var(default_vmode, default_cmode,
-					      &var))
-				has_var = 1;
-		}
-	}
-
-#endif /* !CONFIG_PPC */
-
-#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
-	if (!atyfb_get_timings_from_lcd(par, &var))
-		has_var = 1;
-#endif
-
-	if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
-		has_var = 1;
-
-	if (!has_var)
-		var = default_var;
-
-	if (noaccel)
-		var.accel_flags &= ~FB_ACCELF_TEXT;
-	else
-		var.accel_flags |= FB_ACCELF_TEXT;
-
-	if (comp_sync != -1) {
-		if (!comp_sync)
-			var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
-		else
-			var.sync |= FB_SYNC_COMP_HIGH_ACT;
-	}
-
-	if (var.yres == var.yres_virtual) {
-		u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
-		var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
-		if (var.yres_virtual < var.yres)
-			var.yres_virtual = var.yres;
-	}
-
-	ret = atyfb_check_var(&var, info);
-	if (ret) {
-		PRINTKE("can't set default video mode\n");
-		goto aty_init_exit;
-	}
-
-#ifdef CONFIG_FB_ATY_CT
-	if (!noaccel && M64_HAS(INTEGRATED))
-		aty_init_cursor(info);
-#endif /* CONFIG_FB_ATY_CT */
-	info->var = var;
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret < 0)
-		goto aty_init_exit;
-
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		fb_dealloc_cmap(&info->cmap);
-		goto aty_init_exit;
-	}
-
-	fb_list = info;
-
-	PRINTKI("fb%d: %s frame buffer device on %s\n",
-		info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
-	return 0;
-
-aty_init_exit:
-	/* restore video mode */
-	aty_set_crtc(par, &par->saved_crtc);
-	par->pll_ops->set_pll(info, &par->saved_pll);
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr_reg >= 0) {
-		mtrr_del(par->mtrr_reg, 0, 0);
-		par->mtrr_reg = -1;
-	}
-	if (par->mtrr_aper >= 0) {
-		mtrr_del(par->mtrr_aper, 0, 0);
-		par->mtrr_aper = -1;
-	}
-#endif
-	return ret;
-}
-
-#if defined(CONFIG_ATARI) && !defined(MODULE)
-static int store_video_par(char *video_str, unsigned char m64_num)
-{
-	char *p;
-	unsigned long vmembase, size, guiregbase;
-
-	PRINTKI("store_video_par() '%s' \n", video_str);
-
-	if (!(p = strsep(&video_str, ";")) || !*p)
-		goto mach64_invalid;
-	vmembase = simple_strtoul(p, NULL, 0);
-	if (!(p = strsep(&video_str, ";")) || !*p)
-		goto mach64_invalid;
-	size = simple_strtoul(p, NULL, 0);
-	if (!(p = strsep(&video_str, ";")) || !*p)
-		goto mach64_invalid;
-	guiregbase = simple_strtoul(p, NULL, 0);
-
-	phys_vmembase[m64_num] = vmembase;
-	phys_size[m64_num] = size;
-	phys_guiregbase[m64_num] = guiregbase;
-	PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
-		guiregbase);
-	return 0;
-
- mach64_invalid:
-	phys_vmembase[m64_num] = 0;
-	return -1;
-}
-#endif /* CONFIG_ATARI && !MODULE */
-
-/*
- * Blank the display.
- */
-
-static int atyfb_blank(int blank, struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 gen_cntl;
-
-	if (par->lock_blank || par->asleep)
-		return 0;
-
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table && blank > FB_BLANK_NORMAL &&
-	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
-		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-		pm &= ~PWR_BLON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-	}
-#endif
-
-	gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
-	gen_cntl &= ~0x400004c;
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-		break;
-	case FB_BLANK_NORMAL:
-		gen_cntl |= 0x4000040;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		gen_cntl |= 0x4000048;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		gen_cntl |= 0x4000044;
-		break;
-	case FB_BLANK_POWERDOWN:
-		gen_cntl |= 0x400004c;
-		break;
-	}
-	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
-
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
-	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
-		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
-		pm |= PWR_BLON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, par);
-	}
-#endif
-
-	return 0;
-}
-
-static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
-		       const struct atyfb_par *par)
-{
-	aty_st_8(DAC_W_INDEX, regno, par);
-	aty_st_8(DAC_DATA, red, par);
-	aty_st_8(DAC_DATA, green, par);
-	aty_st_8(DAC_DATA, blue, par);
-}
-
-/*
- * Set a single color register. The values supplied are already
- * rounded down to the hardware's capabilities (according to the
- * entries in the var structure). Return != 0 for invalid regno.
- * !! 4 & 8 =  PSEUDO, > 8 = DIRECTCOLOR
- */
-
-static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	int i, depth;
-	u32 *pal = info->pseudo_palette;
-
-	depth = info->var.bits_per_pixel;
-	if (depth == 16)
-		depth = (info->var.green.length == 5) ? 15 : 16;
-
-	if (par->asleep)
-		return 0;
-
-	if (regno > 255 ||
-	    (depth == 16 && regno > 63) ||
-	    (depth == 15 && regno > 31))
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	par->palette[regno].red = red;
-	par->palette[regno].green = green;
-	par->palette[regno].blue = blue;
-
-	if (regno < 16) {
-		switch (depth) {
-		case 15:
-			pal[regno] = (regno << 10) | (regno << 5) | regno;
-			break;
-		case 16:
-			pal[regno] = (regno << 11) | (regno << 5) | regno;
-			break;
-		case 24:
-			pal[regno] = (regno << 16) | (regno << 8) | regno;
-			break;
-		case 32:
-			i = (regno << 8) | regno;
-			pal[regno] = (i << 16) | i;
-			break;
-		}
-	}
-
-	i = aty_ld_8(DAC_CNTL, par) & 0xfc;
-	if (M64_HAS(EXTRA_BRIGHT))
-		i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
-	aty_st_8(DAC_CNTL, i, par);
-	aty_st_8(DAC_MASK, 0xff, par);
-
-	if (M64_HAS(INTEGRATED)) {
-		if (depth == 16) {
-			if (regno < 32)
-				aty_st_pal(regno << 3, red,
-					   par->palette[regno << 1].green,
-					   blue, par);
-			red = par->palette[regno >> 1].red;
-			blue = par->palette[regno >> 1].blue;
-			regno <<= 2;
-		} else if (depth == 15) {
-			regno <<= 3;
-			for (i = 0; i < 8; i++)
-				aty_st_pal(regno + i, red, green, blue, par);
-		}
-	}
-	aty_st_pal(regno, red, green, blue, par);
-
-	return 0;
-}
-
-#ifdef CONFIG_PCI
-
-#ifdef __sparc__
-
-static int atyfb_setup_sparc(struct pci_dev *pdev, struct fb_info *info,
-			     unsigned long addr)
-{
-	struct atyfb_par *par = info->par;
-	struct device_node *dp;
-	u32 mem, chip_id;
-	int i, j, ret;
-
-	/*
-	 * Map memory-mapped registers.
-	 */
-	par->ati_regbase = (void *)addr + 0x7ffc00UL;
-	info->fix.mmio_start = addr + 0x7ffc00UL;
-
-	/*
-	 * Map in big-endian aperture.
-	 */
-	info->screen_base = (char *) (addr + 0x800000UL);
-	info->fix.smem_start = addr + 0x800000UL;
-
-	/*
-	 * Figure mmap addresses from PCI config space.
-	 * Split Framebuffer in big- and little-endian halfs.
-	 */
-	for (i = 0; i < 6 && pdev->resource[i].start; i++)
-		/* nothing */ ;
-	j = i + 4;
-
-	par->mmap_map = kcalloc(j, sizeof(*par->mmap_map), GFP_ATOMIC);
-	if (!par->mmap_map) {
-		PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
-		return -ENOMEM;
-	}
-
-	for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
-		struct resource *rp = &pdev->resource[i];
-		int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
-		unsigned long base;
-		u32 size, pbase;
-
-		base = rp->start;
-
-		io = (rp->flags & IORESOURCE_IO);
-
-		size = rp->end - base + 1;
-
-		pci_read_config_dword(pdev, breg, &pbase);
-
-		if (io)
-			size &= ~1;
-
-		/*
-		 * Map the framebuffer a second time, this time without
-		 * the braindead _PAGE_IE setting. This is used by the
-		 * fixed Xserver, but we need to maintain the old mapping
-		 * to stay compatible with older ones...
-		 */
-		if (base == addr) {
-			par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
-			par->mmap_map[j].poff = base & PAGE_MASK;
-			par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
-			par->mmap_map[j].prot_mask = _PAGE_CACHE;
-			par->mmap_map[j].prot_flag = _PAGE_E;
-			j++;
-		}
-
-		/*
-		 * Here comes the old framebuffer mapping with _PAGE_IE
-		 * set for the big endian half of the framebuffer...
-		 */
-		if (base == addr) {
-			par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
-			par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
-			par->mmap_map[j].size = 0x800000;
-			par->mmap_map[j].prot_mask = _PAGE_CACHE;
-			par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
-			size -= 0x800000;
-			j++;
-		}
-
-		par->mmap_map[j].voff = pbase & PAGE_MASK;
-		par->mmap_map[j].poff = base & PAGE_MASK;
-		par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
-		par->mmap_map[j].prot_mask = _PAGE_CACHE;
-		par->mmap_map[j].prot_flag = _PAGE_E;
-		j++;
-	}
-
-	ret = correct_chipset(par);
-	if (ret)
-		return ret;
-
-	if (IS_XL(pdev->device)) {
-		/*
-		 * Fix PROMs idea of MEM_CNTL settings...
-		 */
-		mem = aty_ld_le32(MEM_CNTL, par);
-		chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
-		if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
-			switch (mem & 0x0f) {
-			case 3:
-				mem = (mem & ~(0x0f)) | 2;
-				break;
-			case 7:
-				mem = (mem & ~(0x0f)) | 3;
-				break;
-			case 9:
-				mem = (mem & ~(0x0f)) | 4;
-				break;
-			case 11:
-				mem = (mem & ~(0x0f)) | 5;
-				break;
-			default:
-				break;
-			}
-			if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM)
-				mem &= ~(0x00700000);
-		}
-		mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
-		aty_st_le32(MEM_CNTL, mem, par);
-	}
-
-	dp = pci_device_to_OF_node(pdev);
-	if (dp == of_console_device) {
-		struct fb_var_screeninfo *var = &default_var;
-		unsigned int N, P, Q, M, T, R;
-		u32 v_total, h_total;
-		struct crtc crtc;
-		u8 pll_regs[16];
-		u8 clock_cntl;
-
-		crtc.vxres = of_getintprop_default(dp, "width", 1024);
-		crtc.vyres = of_getintprop_default(dp, "height", 768);
-		var->bits_per_pixel = of_getintprop_default(dp, "depth", 8);
-		var->xoffset = var->yoffset = 0;
-		crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
-		crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
-		crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
-		crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
-		crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
-		aty_crtc_to_var(&crtc, var);
-
-		h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
-		v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
-
-		/*
-		 * Read the PLL to figure actual Refresh Rate.
-		 */
-		clock_cntl = aty_ld_8(CLOCK_CNTL, par);
-		/* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
-		for (i = 0; i < 16; i++)
-			pll_regs[i] = aty_ld_pll_ct(i, par);
-
-		/*
-		 * PLL Reference Divider M:
-		 */
-		M = pll_regs[2];
-
-		/*
-		 * PLL Feedback Divider N (Dependent on CLOCK_CNTL):
-		 */
-		N = pll_regs[7 + (clock_cntl & 3)];
-
-		/*
-		 * PLL Post Divider P (Dependent on CLOCK_CNTL):
-		 */
-		P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
-
-		/*
-		 * PLL Divider Q:
-		 */
-		Q = N / P;
-
-		/*
-		 * Target Frequency:
-		 *
-		 *      T * M
-		 * Q = -------
-		 *      2 * R
-		 *
-		 * where R is XTALIN (= 14318 or 29498 kHz).
-		 */
-		if (IS_XL(pdev->device))
-			R = 29498;
-		else
-			R = 14318;
-
-		T = 2 * Q * R / M;
-
-		default_var.pixclock = 1000000000 / T;
-	}
-
-	return 0;
-}
-
-#else /* __sparc__ */
-
-#ifdef __i386__
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
-{
-	u32 driv_inf_tab, sig;
-	u16 lcd_ofs;
-
-	/*
-	 * To support an LCD panel, we should know it's dimensions and
-	 *  it's desired pixel clock.
-	 * There are two ways to do it:
-	 *  - Check the startup video mode and calculate the panel
-	 *    size from it. This is unreliable.
-	 *  - Read it from the driver information table in the video BIOS.
-	 */
-	/* Address of driver information table is at offset 0x78. */
-	driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
-
-	/* Check for the driver information table signature. */
-	sig = *(u32 *)driv_inf_tab;
-	if ((sig == 0x54504c24) || /* Rage LT pro */
-	    (sig == 0x544d5224) || /* Rage mobility */
-	    (sig == 0x54435824) || /* Rage XC */
-	    (sig == 0x544c5824)) { /* Rage XL */
-		PRINTKI("BIOS contains driver information table.\n");
-		lcd_ofs = *(u16 *)(driv_inf_tab + 10);
-		par->lcd_table = 0;
-		if (lcd_ofs != 0)
-			par->lcd_table = bios_base + lcd_ofs;
-	}
-
-	if (par->lcd_table != 0) {
-		char model[24];
-		char strbuf[16];
-		char refresh_rates_buf[100];
-		int id, tech, f, i, m, default_refresh_rate;
-		char *txtcolour;
-		char *txtmonitor;
-		char *txtdual;
-		char *txtformat;
-		u16 width, height, panel_type, refresh_rates;
-		u16 *lcdmodeptr;
-		u32 format;
-		u8 lcd_refresh_rates[16] = { 50, 56, 60, 67, 70, 72, 75, 76, 85,
-					     90, 100, 120, 140, 150, 160, 200 };
-		/*
-		 * The most important information is the panel size at
-		 * offset 25 and 27, but there's some other nice information
-		 * which we print to the screen.
-		 */
-		id = *(u8 *)par->lcd_table;
-		strncpy(model, (char *)par->lcd_table+1, 24);
-		model[23] = 0;
-
-		width = par->lcd_width = *(u16 *)(par->lcd_table+25);
-		height = par->lcd_height = *(u16 *)(par->lcd_table+27);
-		panel_type = *(u16 *)(par->lcd_table+29);
-		if (panel_type & 1)
-			txtcolour = "colour";
-		else
-			txtcolour = "monochrome";
-		if (panel_type & 2)
-			txtdual = "dual (split) ";
-		else
-			txtdual = "";
-		tech = (panel_type >> 2) & 63;
-		switch (tech) {
-		case 0:
-			txtmonitor = "passive matrix";
-			break;
-		case 1:
-			txtmonitor = "active matrix";
-			break;
-		case 2:
-			txtmonitor = "active addressed STN";
-			break;
-		case 3:
-			txtmonitor = "EL";
-			break;
-		case 4:
-			txtmonitor = "plasma";
-			break;
-		default:
-			txtmonitor = "unknown";
-		}
-		format = *(u32 *)(par->lcd_table+57);
-		if (tech == 0 || tech == 2) {
-			switch (format & 7) {
-			case 0:
-				txtformat = "12 bit interface";
-				break;
-			case 1:
-				txtformat = "16 bit interface";
-				break;
-			case 2:
-				txtformat = "24 bit interface";
-				break;
-			default:
-				txtformat = "unknown format";
-			}
-		} else {
-			switch (format & 7) {
-			case 0:
-				txtformat = "8 colours";
-				break;
-			case 1:
-				txtformat = "512 colours";
-				break;
-			case 2:
-				txtformat = "4096 colours";
-				break;
-			case 4:
-				txtformat = "262144 colours (LT mode)";
-				break;
-			case 5:
-				txtformat = "16777216 colours";
-				break;
-			case 6:
-				txtformat = "262144 colours (FDPI-2 mode)";
-				break;
-			default:
-				txtformat = "unknown format";
-			}
-		}
-		PRINTKI("%s%s %s monitor detected: %s\n",
-			txtdual, txtcolour, txtmonitor, model);
-		PRINTKI("       id=%d, %dx%d pixels, %s\n",
-			id, width, height, txtformat);
-		refresh_rates_buf[0] = 0;
-		refresh_rates = *(u16 *)(par->lcd_table+62);
-		m = 1;
-		f = 0;
-		for (i = 0; i < 16; i++) {
-			if (refresh_rates & m) {
-				if (f == 0) {
-					sprintf(strbuf, "%d",
-						lcd_refresh_rates[i]);
-					f++;
-				} else {
-					sprintf(strbuf, ",%d",
-						lcd_refresh_rates[i]);
-				}
-				strcat(refresh_rates_buf, strbuf);
-			}
-			m = m << 1;
-		}
-		default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
-		PRINTKI("       supports refresh rates [%s], default %d Hz\n",
-			refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
-		par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
-		/*
-		 * We now need to determine the crtc parameters for the
-		 * LCD monitor. This is tricky, because they are not stored
-		 * individually in the BIOS. Instead, the BIOS contains a
-		 * table of display modes that work for this monitor.
-		 *
-		 * The idea is that we search for a mode of the same dimensions
-		 * as the dimensions of the LCD monitor. Say our LCD monitor
-		 * is 800x600 pixels, we search for a 800x600 monitor.
-		 * The CRTC parameters we find here are the ones that we need
-		 * to use to simulate other resolutions on the LCD screen.
-		 */
-		lcdmodeptr = (u16 *)(par->lcd_table + 64);
-		while (*lcdmodeptr != 0) {
-			u32 modeptr;
-			u16 mwidth, mheight, lcd_hsync_start, lcd_vsync_start;
-			modeptr = bios_base + *lcdmodeptr;
-
-			mwidth = *((u16 *)(modeptr+0));
-			mheight = *((u16 *)(modeptr+2));
-
-			if (mwidth == width && mheight == height) {
-				par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
-				par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
-				par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
-				lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
-				par->lcd_hsync_dly = (*((u16 *)(modeptr+21)) >> 9) & 7;
-				par->lcd_hsync_len = *((u8 *)(modeptr+23)) & 63;
-
-				par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
-				par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
-				lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
-				par->lcd_vsync_len = (*((u16 *)(modeptr+28)) >> 11) & 31;
-
-				par->lcd_htotal = (par->lcd_htotal + 1) * 8;
-				par->lcd_hdisp = (par->lcd_hdisp + 1) * 8;
-				lcd_hsync_start = (lcd_hsync_start + 1) * 8;
-				par->lcd_hsync_len = par->lcd_hsync_len * 8;
-
-				par->lcd_vtotal++;
-				par->lcd_vdisp++;
-				lcd_vsync_start++;
-
-				par->lcd_right_margin = lcd_hsync_start - par->lcd_hdisp;
-				par->lcd_lower_margin = lcd_vsync_start - par->lcd_vdisp;
-				par->lcd_hblank_len = par->lcd_htotal - par->lcd_hdisp;
-				par->lcd_vblank_len = par->lcd_vtotal - par->lcd_vdisp;
-				break;
-			}
-
-			lcdmodeptr++;
-		}
-		if (*lcdmodeptr == 0) {
-			PRINTKE("LCD monitor CRTC parameters not found!!!\n");
-			/* To do: Switch to CRT if possible. */
-		} else {
-			PRINTKI("       LCD CRTC parameters: %d.%d  %d %d %d %d  %d %d %d %d\n",
-				1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
-				par->lcd_hdisp,
-				par->lcd_hdisp + par->lcd_right_margin,
-				par->lcd_hdisp + par->lcd_right_margin
-					+ par->lcd_hsync_dly + par->lcd_hsync_len,
-				par->lcd_htotal,
-				par->lcd_vdisp,
-				par->lcd_vdisp + par->lcd_lower_margin,
-				par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
-				par->lcd_vtotal);
-			PRINTKI("                          : %d %d %d %d %d %d %d %d %d\n",
-				par->lcd_pixclock,
-				par->lcd_hblank_len - (par->lcd_right_margin +
-					par->lcd_hsync_dly + par->lcd_hsync_len),
-				par->lcd_hdisp,
-				par->lcd_right_margin,
-				par->lcd_hsync_len,
-				par->lcd_vblank_len - (par->lcd_lower_margin + par->lcd_vsync_len),
-				par->lcd_vdisp,
-				par->lcd_lower_margin,
-				par->lcd_vsync_len);
-		}
-	}
-}
-#endif /* CONFIG_FB_ATY_GENERIC_LCD */
-
-static int init_from_bios(struct atyfb_par *par)
-{
-	u32 bios_base, rom_addr;
-	int ret;
-
-	rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, par) & 0x7f) << 11);
-	bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
-
-	/* The BIOS starts with 0xaa55. */
-	if (*((u16 *)bios_base) == 0xaa55) {
-
-		u8 *bios_ptr;
-		u16 rom_table_offset, freq_table_offset;
-		PLL_BLOCK_MACH64 pll_block;
-
-		PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
-
-		/* check for frequncy table */
-		bios_ptr = (u8*)bios_base;
-		rom_table_offset = (u16)(bios_ptr[0x48] | (bios_ptr[0x49] << 8));
-		freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
-		memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
-
-		PRINTKI("BIOS frequency table:\n");
-		PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
-			pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
-			pll_block.ref_freq, pll_block.ref_divider);
-		PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
-			pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
-			pll_block.XCLK_max_freq, pll_block.SCLK_freq);
-
-		par->pll_limits.pll_min = pll_block.PCLK_min_freq/100;
-		par->pll_limits.pll_max = pll_block.PCLK_max_freq/100;
-		par->pll_limits.ref_clk = pll_block.ref_freq/100;
-		par->pll_limits.ref_div = pll_block.ref_divider;
-		par->pll_limits.sclk = pll_block.SCLK_freq/100;
-		par->pll_limits.mclk = pll_block.MCLK_max_freq/100;
-		par->pll_limits.mclk_pm = pll_block.MCLK_pwd/100;
-		par->pll_limits.xclk = pll_block.XCLK_max_freq/100;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-		aty_init_lcd(par, bios_base);
-#endif
-		ret = 0;
-	} else {
-		PRINTKE("no BIOS frequency table found, use parameters\n");
-		ret = -ENXIO;
-	}
-	iounmap((void __iomem *)bios_base);
-
-	return ret;
-}
-#endif /* __i386__ */
-
-static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
-			       unsigned long addr)
-{
-	struct atyfb_par *par = info->par;
-	u16 tmp;
-	unsigned long raddr;
-	struct resource *rrp;
-	int ret = 0;
-
-	raddr = addr + 0x7ff000UL;
-	rrp = &pdev->resource[2];
-	if ((rrp->flags & IORESOURCE_MEM) &&
-	    request_mem_region(rrp->start, resource_size(rrp), "atyfb")) {
-		par->aux_start = rrp->start;
-		par->aux_size = resource_size(rrp);
-		raddr = rrp->start;
-		PRINTKI("using auxiliary register aperture\n");
-	}
-
-	info->fix.mmio_start = raddr;
-	par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
-	if (par->ati_regbase == NULL)
-		return -ENOMEM;
-
-	info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
-	par->ati_regbase += par->aux_start ? 0x400 : 0xc00;
-
-	/*
-	 * Enable memory-space accesses using config-space
-	 * command register.
-	 */
-	pci_read_config_word(pdev, PCI_COMMAND, &tmp);
-	if (!(tmp & PCI_COMMAND_MEMORY)) {
-		tmp |= PCI_COMMAND_MEMORY;
-		pci_write_config_word(pdev, PCI_COMMAND, tmp);
-	}
-#ifdef __BIG_ENDIAN
-	/* Use the big-endian aperture */
-	addr += 0x800000;
-#endif
-
-	/* Map in frame buffer */
-	info->fix.smem_start = addr;
-	info->screen_base = ioremap(addr, 0x800000);
-	if (info->screen_base == NULL) {
-		ret = -ENOMEM;
-		goto atyfb_setup_generic_fail;
-	}
-
-	ret = correct_chipset(par);
-	if (ret)
-		goto atyfb_setup_generic_fail;
-#ifdef __i386__
-	ret = init_from_bios(par);
-	if (ret)
-		goto atyfb_setup_generic_fail;
-#endif
-	if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
-		par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
-	else
-		par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
-
-	/* according to ATI, we should use clock 3 for acelerated mode */
-	par->clk_wr_offset = 3;
-
-	return 0;
-
-atyfb_setup_generic_fail:
-	iounmap(par->ati_regbase);
-	par->ati_regbase = NULL;
-	if (info->screen_base) {
-		iounmap(info->screen_base);
-		info->screen_base = NULL;
-	}
-	return ret;
-}
-
-#endif /* !__sparc__ */
-
-static int atyfb_pci_probe(struct pci_dev *pdev,
-			   const struct pci_device_id *ent)
-{
-	unsigned long addr, res_start, res_size;
-	struct fb_info *info;
-	struct resource *rp;
-	struct atyfb_par *par;
-	int rc = -ENOMEM;
-
-	/* Enable device in PCI config */
-	if (pci_enable_device(pdev)) {
-		PRINTKE("Cannot enable PCI device\n");
-		return -ENXIO;
-	}
-
-	/* Find which resource to use */
-	rp = &pdev->resource[0];
-	if (rp->flags & IORESOURCE_IO)
-		rp = &pdev->resource[1];
-	addr = rp->start;
-	if (!addr)
-		return -ENXIO;
-
-	/* Reserve space */
-	res_start = rp->start;
-	res_size = resource_size(rp);
-	if (!request_mem_region(res_start, res_size, "atyfb"))
-		return -EBUSY;
-
-	/* Allocate framebuffer */
-	info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
-	if (!info) {
-		PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
-		return -ENOMEM;
-	}
-	par = info->par;
-	info->fix = atyfb_fix;
-	info->device = &pdev->dev;
-	par->pci_id = pdev->device;
-	par->res_start = res_start;
-	par->res_size = res_size;
-	par->irq = pdev->irq;
-	par->pdev = pdev;
-
-	/* Setup "info" structure */
-#ifdef __sparc__
-	rc = atyfb_setup_sparc(pdev, info, addr);
-#else
-	rc = atyfb_setup_generic(pdev, info, addr);
-#endif
-	if (rc)
-		goto err_release_mem;
-
-	pci_set_drvdata(pdev, info);
-
-	/* Init chip & register framebuffer */
-	rc = aty_init(info);
-	if (rc)
-		goto err_release_io;
-
-#ifdef __sparc__
-	/*
-	 * Add /dev/fb mmap values.
-	 */
-	par->mmap_map[0].voff = 0x8000000000000000UL;
-	par->mmap_map[0].poff = (unsigned long) info->screen_base & PAGE_MASK;
-	par->mmap_map[0].size = info->fix.smem_len;
-	par->mmap_map[0].prot_mask = _PAGE_CACHE;
-	par->mmap_map[0].prot_flag = _PAGE_E;
-	par->mmap_map[1].voff = par->mmap_map[0].voff + info->fix.smem_len;
-	par->mmap_map[1].poff = (long)par->ati_regbase & PAGE_MASK;
-	par->mmap_map[1].size = PAGE_SIZE;
-	par->mmap_map[1].prot_mask = _PAGE_CACHE;
-	par->mmap_map[1].prot_flag = _PAGE_E;
-#endif /* __sparc__ */
-
-	mutex_lock(&reboot_lock);
-	if (!reboot_info)
-		reboot_info = info;
-	mutex_unlock(&reboot_lock);
-
-	return 0;
-
-err_release_io:
-#ifdef __sparc__
-	kfree(par->mmap_map);
-#else
-	if (par->ati_regbase)
-		iounmap(par->ati_regbase);
-	if (info->screen_base)
-		iounmap(info->screen_base);
-#endif
-err_release_mem:
-	if (par->aux_start)
-		release_mem_region(par->aux_start, par->aux_size);
-
-	release_mem_region(par->res_start, par->res_size);
-	framebuffer_release(info);
-
-	return rc;
-}
-
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_ATARI
-
-static int __init atyfb_atari_probe(void)
-{
-	struct atyfb_par *par;
-	struct fb_info *info;
-	int m64_num;
-	u32 clock_r;
-	int num_found = 0;
-
-	for (m64_num = 0; m64_num < mach64_count; m64_num++) {
-		if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
-		    !phys_guiregbase[m64_num]) {
-			PRINTKI("phys_*[%d] parameters not set => "
-				"returning early. \n", m64_num);
-			continue;
-		}
-
-		info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
-		if (!info) {
-			PRINTKE("atyfb_atari_probe() can't alloc fb_info\n");
-			return -ENOMEM;
-		}
-		par = info->par;
-
-		info->fix = atyfb_fix;
-
-		par->irq = (unsigned int) -1; /* something invalid */
-
-		/*
-		 * Map the video memory (physical address given)
-		 * to somewhere in the kernel address space.
-		 */
-		info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
-		info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
-		par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
-						0xFC00ul;
-		info->fix.mmio_start = (unsigned long)par->ati_regbase; /* Fake! */
-
-		aty_st_le32(CLOCK_CNTL, 0x12345678, par);
-		clock_r = aty_ld_le32(CLOCK_CNTL, par);
-
-		switch (clock_r & 0x003F) {
-		case 0x12:
-			par->clk_wr_offset = 3; /*  */
-			break;
-		case 0x34:
-			par->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
-			break;
-		case 0x16:
-			par->clk_wr_offset = 1; /*  */
-			break;
-		case 0x38:
-			par->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
-			break;
-		}
-
-		/* Fake pci_id for correct_chipset() */
-		switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) {
-		case 0x00d7:
-			par->pci_id = PCI_CHIP_MACH64GX;
-			break;
-		case 0x0057:
-			par->pci_id = PCI_CHIP_MACH64CX;
-			break;
-		default:
-			break;
-		}
-
-		if (correct_chipset(par) || aty_init(info)) {
-			iounmap(info->screen_base);
-			iounmap(par->ati_regbase);
-			framebuffer_release(info);
-		} else {
-			num_found++;
-		}
-	}
-
-	return num_found ? 0 : -ENXIO;
-}
-
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_PCI
-
-static void atyfb_remove(struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	/* restore video mode */
-	aty_set_crtc(par, &par->saved_crtc);
-	par->pll_ops->set_pll(info, &par->saved_pll);
-
-	unregister_framebuffer(info);
-
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-	if (M64_HAS(MOBIL_BUS))
-		aty_bl_exit(info->bl_dev);
-#endif
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr_reg >= 0) {
-		mtrr_del(par->mtrr_reg, 0, 0);
-		par->mtrr_reg = -1;
-	}
-	if (par->mtrr_aper >= 0) {
-		mtrr_del(par->mtrr_aper, 0, 0);
-		par->mtrr_aper = -1;
-	}
-#endif
-#ifndef __sparc__
-	if (par->ati_regbase)
-		iounmap(par->ati_regbase);
-	if (info->screen_base)
-		iounmap(info->screen_base);
-#ifdef __BIG_ENDIAN
-	if (info->sprite.addr)
-		iounmap(info->sprite.addr);
-#endif
-#endif
-#ifdef __sparc__
-	kfree(par->mmap_map);
-#endif
-	if (par->aux_start)
-		release_mem_region(par->aux_start, par->aux_size);
-
-	if (par->res_start)
-		release_mem_region(par->res_start, par->res_size);
-
-	framebuffer_release(info);
-}
-
-
-static void atyfb_pci_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-
-	mutex_lock(&reboot_lock);
-	if (reboot_info == info)
-		reboot_info = NULL;
-	mutex_unlock(&reboot_lock);
-
-	atyfb_remove(info);
-}
-
-static struct pci_device_id atyfb_pci_tbl[] = {
-#ifdef CONFIG_FB_ATY_GX
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) },
-#endif /* CONFIG_FB_ATY_GX */
-
-#ifdef CONFIG_FB_ATY_CT
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) },
-
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) },
-#endif /* CONFIG_FB_ATY_CT */
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl);
-
-static struct pci_driver atyfb_driver = {
-	.name		= "atyfb",
-	.id_table	= atyfb_pci_tbl,
-	.probe		= atyfb_pci_probe,
-	.remove		= atyfb_pci_remove,
-#ifdef CONFIG_PM
-	.suspend	= atyfb_pci_suspend,
-	.resume		= atyfb_pci_resume,
-#endif /* CONFIG_PM */
-};
-
-#endif /* CONFIG_PCI */
-
-#ifndef MODULE
-static int __init atyfb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "noaccel", 7)) {
-			noaccel = 1;
-#ifdef CONFIG_MTRR
-		} else if (!strncmp(this_opt, "nomtrr", 6)) {
-			nomtrr = 1;
-#endif
-		} else if (!strncmp(this_opt, "vram:", 5))
-			vram = simple_strtoul(this_opt + 5, NULL, 0);
-		else if (!strncmp(this_opt, "pll:", 4))
-			pll = simple_strtoul(this_opt + 4, NULL, 0);
-		else if (!strncmp(this_opt, "mclk:", 5))
-			mclk = simple_strtoul(this_opt + 5, NULL, 0);
-		else if (!strncmp(this_opt, "xclk:", 5))
-			xclk = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "comp_sync:", 10))
-			comp_sync = simple_strtoul(this_opt+10, NULL, 0);
-		else if (!strncmp(this_opt, "backlight:", 10))
-			backlight = simple_strtoul(this_opt+10, NULL, 0);
-#ifdef CONFIG_PPC
-		else if (!strncmp(this_opt, "vmode:", 6)) {
-			unsigned int vmode =
-			    simple_strtoul(this_opt + 6, NULL, 0);
-			if (vmode > 0 && vmode <= VMODE_MAX)
-				default_vmode = vmode;
-		} else if (!strncmp(this_opt, "cmode:", 6)) {
-			unsigned int cmode =
-			    simple_strtoul(this_opt + 6, NULL, 0);
-			switch (cmode) {
-			case 0:
-			case 8:
-				default_cmode = CMODE_8;
-				break;
-			case 15:
-			case 16:
-				default_cmode = CMODE_16;
-				break;
-			case 24:
-			case 32:
-				default_cmode = CMODE_32;
-				break;
-			}
-		}
-#endif
-#ifdef CONFIG_ATARI
-		/*
-		 * Why do we need this silly Mach64 argument?
-		 * We are already here because of mach64= so its redundant.
-		 */
-		else if (MACH_IS_ATARI
-			 && (!strncmp(this_opt, "Mach64:", 7))) {
-			static unsigned char m64_num;
-			static char mach64_str[80];
-			strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
-			if (!store_video_par(mach64_str, m64_num)) {
-				m64_num++;
-				mach64_count = m64_num;
-			}
-		}
-#endif
-		else
-			mode = this_opt;
-	}
-	return 0;
-}
-#endif  /*  MODULE  */
-
-static int atyfb_reboot_notify(struct notifier_block *nb,
-			       unsigned long code, void *unused)
-{
-	struct atyfb_par *par;
-
-	if (code != SYS_RESTART)
-		return NOTIFY_DONE;
-
-	mutex_lock(&reboot_lock);
-
-	if (!reboot_info)
-		goto out;
-
-	if (!lock_fb_info(reboot_info))
-		goto out;
-
-	par = reboot_info->par;
-
-	/*
-	 * HP OmniBook 500's BIOS doesn't like the state of the
-	 * hardware after atyfb has been used. Restore the hardware
-	 * to the original state to allow successful reboots.
-	 */
-	aty_set_crtc(par, &par->saved_crtc);
-	par->pll_ops->set_pll(reboot_info, &par->saved_pll);
-
-	unlock_fb_info(reboot_info);
- out:
-	mutex_unlock(&reboot_lock);
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block atyfb_reboot_notifier = {
-	.notifier_call = atyfb_reboot_notify,
-};
-
-static const struct dmi_system_id atyfb_reboot_ids[] = {
-	{
-		.ident = "HP OmniBook 500",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"),
-		},
-	},
-
-	{ }
-};
-
-static int __init atyfb_init(void)
-{
-	int err1 = 1, err2 = 1;
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("atyfb", &option))
-		return -ENODEV;
-	atyfb_setup(option);
-#endif
-
-#ifdef CONFIG_PCI
-	err1 = pci_register_driver(&atyfb_driver);
-#endif
-#ifdef CONFIG_ATARI
-	err2 = atyfb_atari_probe();
-#endif
-
-	if (err1 && err2)
-		return -ENODEV;
-
-	if (dmi_check_system(atyfb_reboot_ids))
-		register_reboot_notifier(&atyfb_reboot_notifier);
-
-	return 0;
-}
-
-static void __exit atyfb_exit(void)
-{
-	if (dmi_check_system(atyfb_reboot_ids))
-		unregister_reboot_notifier(&atyfb_reboot_notifier);
-
-#ifdef CONFIG_PCI
-	pci_unregister_driver(&atyfb_driver);
-#endif
-}
-
-module_init(atyfb_init);
-module_exit(atyfb_exit);
-
-MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
-MODULE_LICENSE("GPL");
-module_param(noaccel, bool, 0);
-MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
-module_param(vram, int, 0);
-MODULE_PARM_DESC(vram, "int: override size of video ram");
-module_param(pll, int, 0);
-MODULE_PARM_DESC(pll, "int: override video clock");
-module_param(mclk, int, 0);
-MODULE_PARM_DESC(mclk, "int: override memory clock");
-module_param(xclk, int, 0);
-MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
-module_param(comp_sync, int, 0);
-MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high (1)");
-module_param(mode, charp, 0);
-MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, 0);
-MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
-#endif
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
deleted file mode 100644
index 182bd680141f..000000000000
--- a/drivers/video/aty/mach64_accel.c
+++ /dev/null
@@ -1,430 +0,0 @@
-
-/*
- *  ATI Mach64 Hardware Acceleration
- */
-
-#include <linux/delay.h>
-#include <asm/unaligned.h>
-#include <linux/fb.h>
-#include <video/mach64.h>
-#include "atyfb.h"
-
-    /*
-     *  Generic Mach64 routines
-     */
-
-/* this is for DMA GUI engine! work in progress */
-typedef struct {
-	u32 frame_buf_offset;
-	u32 system_mem_addr;
-	u32 command;
-	u32 reserved;
-} BM_DESCRIPTOR_ENTRY;
-
-#define LAST_DESCRIPTOR (1 << 31)
-#define SYSTEM_TO_FRAME_BUFFER 0
-
-static u32 rotation24bpp(u32 dx, u32 direction)
-{
-	u32 rotation;
-	if (direction & DST_X_LEFT_TO_RIGHT) {
-		rotation = (dx / 4) % 6;
-	} else {
-		rotation = ((dx + 2) / 4) % 6;
-	}
-
-	return ((rotation << 8) | DST_24_ROTATION_ENABLE);
-}
-
-void aty_reset_engine(const struct atyfb_par *par)
-{
-	/* reset engine */
-	aty_st_le32(GEN_TEST_CNTL,
-		aty_ld_le32(GEN_TEST_CNTL, par) &
-		~(GUI_ENGINE_ENABLE | HWCURSOR_ENABLE), par);
-	/* enable engine */
-	aty_st_le32(GEN_TEST_CNTL,
-		aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par);
-	/* ensure engine is not locked up by clearing any FIFO or */
-	/* HOST errors */
-	aty_st_le32(BUS_CNTL,
-		aty_ld_le32(BUS_CNTL, par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK, par);
-}
-
-static void reset_GTC_3D_engine(const struct atyfb_par *par)
-{
-	aty_st_le32(SCALE_3D_CNTL, 0xc0, par);
-	mdelay(GTC_3D_RESET_DELAY);
-	aty_st_le32(SETUP_CNTL, 0x00, par);
-	mdelay(GTC_3D_RESET_DELAY);
-	aty_st_le32(SCALE_3D_CNTL, 0x00, par);
-	mdelay(GTC_3D_RESET_DELAY);
-}
-
-void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
-{
-	u32 pitch_value;
-	u32 vxres;
-
-	/* determine modal information from global mode structure */
-	pitch_value = info->fix.line_length / (info->var.bits_per_pixel / 8);
-	vxres = info->var.xres_virtual;
-
-	if (info->var.bits_per_pixel == 24) {
-		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
-		/* horizontal coordinates and widths must be adjusted */
-		pitch_value *= 3;
-		vxres *= 3;
-	}
-
-	/* On GTC (RagePro), we need to reset the 3D engine before */
-	if (M64_HAS(RESET_3D))
-		reset_GTC_3D_engine(par);
-
-	/* Reset engine, enable, and clear any engine errors */
-	aty_reset_engine(par);
-	/* Ensure that vga page pointers are set to zero - the upper */
-	/* page pointers are set to 1 to handle overflows in the */
-	/* lower page */
-	aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, par);
-	aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, par);
-
-	/* ---- Setup standard engine context ---- */
-
-	/* All GUI registers here are FIFOed - therefore, wait for */
-	/* the appropriate number of empty FIFO entries */
-	wait_for_fifo(14, par);
-
-	/* enable all registers to be loaded for context loads */
-	aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, par);
-
-	/* set destination pitch to modal pitch, set offset to zero */
-	aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, par);
-
-	/* zero these registers (set them to a known state) */
-	aty_st_le32(DST_Y_X, 0, par);
-	aty_st_le32(DST_HEIGHT, 0, par);
-	aty_st_le32(DST_BRES_ERR, 0, par);
-	aty_st_le32(DST_BRES_INC, 0, par);
-	aty_st_le32(DST_BRES_DEC, 0, par);
-
-	/* set destination drawing attributes */
-	aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
-		    DST_X_LEFT_TO_RIGHT, par);
-
-	/* set source pitch to modal pitch, set offset to zero */
-	aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, par);
-
-	/* set these registers to a known state */
-	aty_st_le32(SRC_Y_X, 0, par);
-	aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, par);
-	aty_st_le32(SRC_Y_X_START, 0, par);
-	aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, par);
-
-	/* set source pixel retrieving attributes */
-	aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, par);
-
-	/* set host attributes */
-	wait_for_fifo(13, par);
-	aty_st_le32(HOST_CNTL, 0, par);
-
-	/* set pattern attributes */
-	aty_st_le32(PAT_REG0, 0, par);
-	aty_st_le32(PAT_REG1, 0, par);
-	aty_st_le32(PAT_CNTL, 0, par);
-
-	/* set scissors to modal size */
-	aty_st_le32(SC_LEFT, 0, par);
-	aty_st_le32(SC_TOP, 0, par);
-	aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par);
-	aty_st_le32(SC_RIGHT, vxres - 1, par);
-
-	/* set background color to minimum value (usually BLACK) */
-	aty_st_le32(DP_BKGD_CLR, 0, par);
-
-	/* set foreground color to maximum value (usually WHITE) */
-	aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, par);
-
-	/* set write mask to effect all pixel bits */
-	aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
-
-	/* set foreground mix to overpaint and background mix to */
-	/* no-effect */
-	aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, par);
-
-	/* set primary source pixel channel to foreground color */
-	/* register */
-	aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, par);
-
-	/* set compare functionality to false (no-effect on */
-	/* destination) */
-	wait_for_fifo(3, par);
-	aty_st_le32(CLR_CMP_CLR, 0, par);
-	aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, par);
-	aty_st_le32(CLR_CMP_CNTL, 0, par);
-
-	/* set pixel depth */
-	wait_for_fifo(2, par);
-	aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, par);
-	aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, par);
-
-	wait_for_fifo(5, par);
- 	aty_st_le32(SCALE_3D_CNTL, 0, par);
-	aty_st_le32(Z_CNTL, 0, par);
-	aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, par) & ~0x20,
-		    par);
-	aty_st_le32(GUI_TRAJ_CNTL, 0x100023, par);
-
-	/* insure engine is idle before leaving */
-	wait_for_idle(par);
-}
-
-    /*
-     *  Accelerated functions
-     */
-
-static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
-			     struct atyfb_par *par)
-{
-	/* perform rectangle fill */
-	wait_for_fifo(2, par);
-	aty_st_le32(DST_Y_X, (x << 16) | y, par);
-	aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, par);
-	par->blitter_may_be_busy = 1;
-}
-
-void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 dy = area->dy, sy = area->sy, direction = DST_LAST_PEL;
-	u32 sx = area->sx, dx = area->dx, width = area->width, rotation = 0;
-
-	if (par->asleep)
-		return;
-	if (!area->width || !area->height)
-		return;
-	if (!par->accel_flags) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	if (info->var.bits_per_pixel == 24) {
-		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
-		/* horizontal coordinates and widths must be adjusted */
-		sx *= 3;
-		dx *= 3;
-		width *= 3;
-	}
-
-	if (area->sy < area->dy) {
-		dy += area->height - 1;
-		sy += area->height - 1;
-	} else
-		direction |= DST_Y_TOP_TO_BOTTOM;
-
-	if (sx < dx) {
-		dx += width - 1;
-		sx += width - 1;
-	} else
-		direction |= DST_X_LEFT_TO_RIGHT;
-
-	if (info->var.bits_per_pixel == 24) {
-		rotation = rotation24bpp(dx, direction);
-	}
-
-	wait_for_fifo(4, par);
-	aty_st_le32(DP_SRC, FRGD_SRC_BLIT, par);
-	aty_st_le32(SRC_Y_X, (sx << 16) | sy, par);
-	aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | area->height, par);
-	aty_st_le32(DST_CNTL, direction | rotation, par);
-	draw_rect(dx, dy, width, area->height, par);
-}
-
-void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 color, dx = rect->dx, width = rect->width, rotation = 0;
-
-	if (par->asleep)
-		return;
-	if (!rect->width || !rect->height)
-		return;
-	if (!par->accel_flags) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
-		color = ((u32 *)(info->pseudo_palette))[rect->color];
-	else
-		color = rect->color;
-
-	if (info->var.bits_per_pixel == 24) {
-		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
-		/* horizontal coordinates and widths must be adjusted */
-		dx *= 3;
-		width *= 3;
-		rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
-	}
-
-	wait_for_fifo(3, par);
-	aty_st_le32(DP_FRGD_CLR, color, par);
-	aty_st_le32(DP_SRC,
-		    BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
-		    par);
-	aty_st_le32(DST_CNTL,
-		    DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
-		    DST_X_LEFT_TO_RIGHT | rotation, par);
-	draw_rect(dx, rect->dy, width, rect->height, par);
-}
-
-void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 src_bytes, dx = image->dx, dy = image->dy, width = image->width;
-	u32 pix_width_save, pix_width, host_cntl, rotation = 0, src, mix;
-
-	if (par->asleep)
-		return;
-	if (!image->width || !image->height)
-		return;
-	if (!par->accel_flags ||
-	    (image->depth != 1 && info->var.bits_per_pixel != image->depth)) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	pix_width = pix_width_save = aty_ld_le32(DP_PIX_WIDTH, par);
-	host_cntl = aty_ld_le32(HOST_CNTL, par) | HOST_BYTE_ALIGN;
-
-	switch (image->depth) {
-	case 1:
-	    pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
-	    pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_1BPP);
-	    break;
-	case 4:
-	    pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
-	    pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_4BPP);
-	    break;
-	case 8:
-	    pix_width &= ~HOST_MASK;
-	    pix_width |= HOST_8BPP;
-	    break;
-	case 15:
-	    pix_width &= ~HOST_MASK;
-	    pix_width |= HOST_15BPP;
-	    break;
-	case 16:
-	    pix_width &= ~HOST_MASK;
-	    pix_width |= HOST_16BPP;
-	    break;
-	case 24:
-	    pix_width &= ~HOST_MASK;
-	    pix_width |= HOST_24BPP;
-	    break;
-	case 32:
-	    pix_width &= ~HOST_MASK;
-	    pix_width |= HOST_32BPP;
-	    break;
-	}
-
-	if (info->var.bits_per_pixel == 24) {
-		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
-		/* horizontal coordinates and widths must be adjusted */
-		dx *= 3;
-		width *= 3;
-
-		rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
-
-		pix_width &= ~DST_MASK;
-		pix_width |= DST_8BPP;
-
-		/*
-		 * since Rage 3D IIc we have DP_HOST_TRIPLE_EN bit
-		 * this hwaccelerated triple has an issue with not aligned data
-		 */
-		if (M64_HAS(HW_TRIPLE) && image->width % 8 == 0)
-			pix_width |= DP_HOST_TRIPLE_EN;
-	}
-
-	if (image->depth == 1) {
-		u32 fg, bg;
-		if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-		    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-			fg = ((u32*)(info->pseudo_palette))[image->fg_color];
-			bg = ((u32*)(info->pseudo_palette))[image->bg_color];
-		} else {
-			fg = image->fg_color;
-			bg = image->bg_color;
-		}
-
-		wait_for_fifo(2, par);
-		aty_st_le32(DP_BKGD_CLR, bg, par);
-		aty_st_le32(DP_FRGD_CLR, fg, par);
-		src = MONO_SRC_HOST | FRGD_SRC_FRGD_CLR | BKGD_SRC_BKGD_CLR;
-		mix = FRGD_MIX_S | BKGD_MIX_S;
-	} else {
-		src = MONO_SRC_ONE | FRGD_SRC_HOST;
-		mix = FRGD_MIX_D_XOR_S | BKGD_MIX_D;
-	}
-
-	wait_for_fifo(6, par);
-	aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
-	aty_st_le32(DP_PIX_WIDTH, pix_width, par);
-	aty_st_le32(DP_MIX, mix, par);
-	aty_st_le32(DP_SRC, src, par);
-	aty_st_le32(HOST_CNTL, host_cntl, par);
-	aty_st_le32(DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT | rotation, par);
-
-	draw_rect(dx, dy, width, image->height, par);
-	src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
-
-	/* manual triple each pixel */
-	if (info->var.bits_per_pixel == 24 && !(pix_width & DP_HOST_TRIPLE_EN)) {
-		int inbit, outbit, mult24, byte_id_in_dword, width;
-		u8 *pbitmapin = (u8*)image->data, *pbitmapout;
-		u32 hostdword;
-
-		for (width = image->width, inbit = 7, mult24 = 0; src_bytes; ) {
-			for (hostdword = 0, pbitmapout = (u8*)&hostdword, byte_id_in_dword = 0;
-				byte_id_in_dword < 4 && src_bytes;
-				byte_id_in_dword++, pbitmapout++) {
-				for (outbit = 7; outbit >= 0; outbit--) {
-					*pbitmapout |= (((*pbitmapin >> inbit) & 1) << outbit);
-					mult24++;
-					/* next bit */
-					if (mult24 == 3) {
-						mult24 = 0;
-						inbit--;
-						width--;
-					}
-
-					/* next byte */
-					if (inbit < 0 || width == 0) {
-						src_bytes--;
-						pbitmapin++;
-						inbit = 7;
-
-						if (width == 0) {
-						    width = image->width;
-						    outbit = 0;
-						}
-					}
-				}
-			}
-			wait_for_fifo(1, par);
-			aty_st_le32(HOST_DATA0, hostdword, par);
-		}
-	} else {
-		u32 *pbitmap, dwords = (src_bytes + 3) / 4;
-		for (pbitmap = (u32*)(image->data); dwords; dwords--, pbitmap++) {
-			wait_for_fifo(1, par);
-			aty_st_le32(HOST_DATA0, get_unaligned_le32(pbitmap), par);
-		}
-	}
-
-	/* restore pix_width */
-	wait_for_fifo(1, par);
-	aty_st_le32(DP_PIX_WIDTH, pix_width_save, par);
-}
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
deleted file mode 100644
index 51f29d627ceb..000000000000
--- a/drivers/video/aty/mach64_ct.c
+++ /dev/null
@@ -1,649 +0,0 @@
-
-/*
- *  ATI Mach64 CT/VT/GT/LT Support
- */
-
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <video/mach64.h>
-#include "atyfb.h"
-#ifdef CONFIG_PPC
-#include <asm/machdep.h>
-#endif
-
-#undef DEBUG
-
-static int aty_valid_pll_ct (const struct fb_info *info, u32 vclk_per, struct pll_ct *pll);
-static int aty_dsp_gt       (const struct fb_info *info, u32 bpp, struct pll_ct *pll);
-static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll);
-static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll);
-
-u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par)
-{
-	u8 res;
-
-	/* write addr byte */
-	aty_st_8(CLOCK_CNTL_ADDR, (offset << 2) & PLL_ADDR, par);
-	/* read the register value */
-	res = aty_ld_8(CLOCK_CNTL_DATA, par);
-	return res;
-}
-
-static void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par)
-{
-	/* write addr byte */
-	aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) | PLL_WR_EN, par);
-	/* write the register value */
-	aty_st_8(CLOCK_CNTL_DATA, val & PLL_DATA, par);
-	aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) & ~PLL_WR_EN, par);
-}
-
-/*
- * by Daniel Mantione
- *                                  <daniel.mantione@freepascal.org>
- *
- *
- * ATI Mach64 CT clock synthesis description.
- *
- * All clocks on the Mach64 can be calculated using the same principle:
- *
- *       XTALIN * x * FB_DIV
- * CLK = ----------------------
- *       PLL_REF_DIV * POST_DIV
- *
- * XTALIN is a fixed speed clock. Common speeds are 14.31 MHz and 29.50 MHz.
- * PLL_REF_DIV can be set by the user, but is the same for all clocks.
- * FB_DIV can be set by the user for each clock individually, it should be set
- * between 128 and 255, the chip will generate a bad clock signal for too low
- * values.
- * x depends on the type of clock; usually it is 2, but for the MCLK it can also
- * be set to 4.
- * POST_DIV can be set by the user for each clock individually, Possible values
- * are 1,2,4,8 and for some clocks other values are available too.
- * CLK is of course the clock speed that is generated.
- *
- * The Mach64 has these clocks:
- *
- * MCLK			The clock rate of the chip
- * XCLK			The clock rate of the on-chip memory
- * VCLK0		First pixel clock of first CRT controller
- * VCLK1    Second pixel clock of first CRT controller
- * VCLK2		Third pixel clock of first CRT controller
- * VCLK3    Fourth pixel clock of first CRT controller
- * VCLK			Selected pixel clock, one of VCLK0, VCLK1, VCLK2, VCLK3
- * V2CLK		Pixel clock of the second CRT controller.
- * SCLK			Multi-purpose clock
- *
- * - MCLK and XCLK use the same FB_DIV
- * - VCLK0 .. VCLK3 use the same FB_DIV
- * - V2CLK is needed when the second CRTC is used (can be used for dualhead);
- *   i.e. CRT monitor connected to laptop has different resolution than built
- *   in LCD monitor.
- * - SCLK is not available on all cards; it is know to exist on the Rage LT-PRO,
- *   Rage XL and Rage Mobility. It is know not to exist on the Mach64 VT.
- * - V2CLK is not available on all cards, most likely only the Rage LT-PRO,
- *   the Rage XL and the Rage Mobility
- *
- * SCLK can be used to:
- * - Clock the chip instead of MCLK
- * - Replace XTALIN with a user defined frequency
- * - Generate the pixel clock for the LCD monitor (instead of VCLK)
- */
-
- /*
-  * It can be quite hard to calculate XCLK and MCLK if they don't run at the
-  * same frequency. Luckily, until now all cards that need asynchrone clock
-  * speeds seem to have SCLK.
-  * So this driver uses SCLK to clock the chip and XCLK to clock the memory.
-  */
-
-/* ------------------------------------------------------------------------- */
-
-/*
- *  PLL programming (Mach64 CT family)
- *
- *
- * This procedure sets the display fifo. The display fifo is a buffer that
- * contains data read from the video memory that waits to be processed by
- * the CRT controller.
- *
- * On the more modern Mach64 variants, the chip doesn't calculate the
- * interval after which the display fifo has to be reloaded from memory
- * automatically, the driver has to do it instead.
- */
-
-#define Maximum_DSP_PRECISION 7
-static u8 postdividers[] = {1,2,4,8,3};
-
-static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
-{
-	u32 dsp_off, dsp_on, dsp_xclks;
-	u32 multiplier, divider, ras_multiplier, ras_divider, tmp;
-	u8 vshift, xshift;
-	s8 dsp_precision;
-
-	multiplier = ((u32)pll->mclk_fb_div) * pll->vclk_post_div_real;
-	divider = ((u32)pll->vclk_fb_div) * pll->xclk_ref_div;
-
-	ras_multiplier = pll->xclkmaxrasdelay;
-	ras_divider = 1;
-
-	if (bpp>=8)
-		divider = divider * (bpp >> 2);
-
-	vshift = (6 - 2) - pll->xclk_post_div;	/* FIFO is 64 bits wide in accelerator mode ... */
-
-	if (bpp == 0)
-		vshift--;	/* ... but only 32 bits in VGA mode. */
-
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (pll->xres != 0) {
-		struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-		multiplier = multiplier * par->lcd_width;
-		divider = divider * pll->xres & ~7;
-
-		ras_multiplier = ras_multiplier * par->lcd_width;
-		ras_divider = ras_divider * pll->xres & ~7;
-	}
-#endif
-	/* If we don't do this, 32 bits for multiplier & divider won't be
-	enough in certain situations! */
-	while (((multiplier | divider) & 1) == 0) {
-		multiplier = multiplier >> 1;
-		divider = divider >> 1;
-	}
-
-	/* Determine DSP precision first */
-	tmp = ((multiplier * pll->fifo_size) << vshift) / divider;
-
-	for (dsp_precision = -5;  tmp;  dsp_precision++)
-		tmp >>= 1;
-	if (dsp_precision < 0)
-		dsp_precision = 0;
-	else if (dsp_precision > Maximum_DSP_PRECISION)
-		dsp_precision = Maximum_DSP_PRECISION;
-
-	xshift = 6 - dsp_precision;
-	vshift += xshift;
-
-	/* Move on to dsp_off */
-	dsp_off = ((multiplier * (pll->fifo_size - 1)) << vshift) / divider -
-		(1 << (vshift - xshift));
-
-/*    if (bpp == 0)
-        dsp_on = ((multiplier * 20 << vshift) + divider) / divider;
-    else */
-	{
-		dsp_on = ((multiplier << vshift) + divider) / divider;
-		tmp = ((ras_multiplier << xshift) + ras_divider) / ras_divider;
-		if (dsp_on < tmp)
-		dsp_on = tmp;
-		dsp_on = dsp_on + (tmp * 2) + (pll->xclkpagefaultdelay << xshift);
-	}
-
-	/* Calculate rounding factor and apply it to dsp_on */
-	tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1;
-	dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1);
-
-	if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) {
-		dsp_on = dsp_off - (multiplier << vshift) / divider;
-		dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
-	}
-
-	/* Last but not least:  dsp_xclks */
-	dsp_xclks = ((multiplier << (vshift + 5)) + divider) / divider;
-
-	/* Get register values. */
-	pll->dsp_on_off = (dsp_on << 16) + dsp_off;
-	pll->dsp_config = (dsp_precision << 20) | (pll->dsp_loop_latency << 16) | dsp_xclks;
-#ifdef DEBUG
-	printk("atyfb(%s): dsp_config 0x%08x, dsp_on_off 0x%08x\n",
-		__func__, pll->dsp_config, pll->dsp_on_off);
-#endif
-	return 0;
-}
-
-static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll_ct *pll)
-{
-	u32 q;
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	int pllvclk;
-
-	/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
-	q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per;
-	if (q < 16*8 || q > 255*8) {
-		printk(KERN_CRIT "atyfb: vclk out of range\n");
-		return -EINVAL;
-	} else {
-		pll->vclk_post_div  = (q < 128*8);
-		pll->vclk_post_div += (q <  64*8);
-		pll->vclk_post_div += (q <  32*8);
-	}
-	pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
-	//    pll->vclk_post_div <<= 6;
-	pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
-	pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
-		(par->ref_clk_per * pll->pll_ref_div);
-#ifdef DEBUG
-	printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
-		__func__, pllvclk, pllvclk / pll->vclk_post_div_real);
-#endif
-	pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
-
-	/* Set ECP (scaler/overlay clock) divider */
-	if (par->pll_limits.ecp_max) {
-		int ecp = pllvclk / pll->vclk_post_div_real;
-		int ecp_div = 0;
-
-		while (ecp > par->pll_limits.ecp_max && ecp_div < 2) {
-			ecp >>= 1;
-			ecp_div++;
-		}
-		pll->pll_vclk_cntl |= ecp_div << 4;
-	}
-
-	return 0;
-}
-
-static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	int err;
-
-	if ((err = aty_valid_pll_ct(info, vclk_per, &pll->ct)))
-		return err;
-	if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
-		return err;
-	/*aty_calc_pll_ct(info, &pll->ct);*/
-	return 0;
-}
-
-static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 ret;
-	ret = par->ref_clk_per * pll->ct.pll_ref_div * pll->ct.vclk_post_div_real / pll->ct.vclk_fb_div / 2;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if(pll->ct.xres > 0) {
-		ret *= par->lcd_width;
-		ret /= pll->ct.xres;
-	}
-#endif
-#ifdef DEBUG
-	printk("atyfb(%s): calculated 0x%08X(%i)\n", __func__, ret, ret);
-#endif
-	return ret;
-}
-
-void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 crtc_gen_cntl, lcd_gen_cntrl;
-	u8 tmp, tmp2;
-
-	lcd_gen_cntrl = 0;
-#ifdef DEBUG
-	printk("atyfb(%s): about to program:\n"
-		"pll_ext_cntl=0x%02x pll_gen_cntl=0x%02x pll_vclk_cntl=0x%02x\n",
-		__func__,
-		pll->ct.pll_ext_cntl, pll->ct.pll_gen_cntl, pll->ct.pll_vclk_cntl);
-
-	printk("atyfb(%s): setting clock %lu for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i(%i)\n",
-		__func__,
-		par->clk_wr_offset, pll->ct.vclk_fb_div,
-		pll->ct.pll_ref_div, pll->ct.vclk_post_div, pll->ct.vclk_post_div_real);
-#endif
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		/* turn off LCD */
-		lcd_gen_cntrl = aty_ld_lcd(LCD_GEN_CNTL, par);
-		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl & ~LCD_ON, par);
-	}
-#endif
-	aty_st_8(CLOCK_CNTL, par->clk_wr_offset | CLOCK_STROBE, par);
-
-	/* Temporarily switch to accelerator mode */
-	crtc_gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
-	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
-		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN, par);
-
-	/* Reset VCLK generator */
-	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
-
-	/* Set post-divider */
-	tmp2 = par->clk_wr_offset << 1;
-	tmp = aty_ld_pll_ct(VCLK_POST_DIV, par);
-	tmp &= ~(0x03U << tmp2);
-	tmp |= ((pll->ct.vclk_post_div & 0x03U) << tmp2);
-	aty_st_pll_ct(VCLK_POST_DIV, tmp, par);
-
-	/* Set extended post-divider */
-	tmp = aty_ld_pll_ct(PLL_EXT_CNTL, par);
-	tmp &= ~(0x10U << par->clk_wr_offset);
-	tmp &= 0xF0U;
-	tmp |= pll->ct.pll_ext_cntl;
-	aty_st_pll_ct(PLL_EXT_CNTL, tmp, par);
-
-	/* Set feedback divider */
-	tmp = VCLK0_FB_DIV + par->clk_wr_offset;
-	aty_st_pll_ct(tmp, (pll->ct.vclk_fb_div & 0xFFU), par);
-
-	aty_st_pll_ct(PLL_GEN_CNTL, (pll->ct.pll_gen_cntl & (~(PLL_OVERRIDE | PLL_MCLK_RST))) | OSC_EN, par);
-
-	/* End VCLK generator reset */
-	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl & ~(PLL_VCLK_RST), par);
-	mdelay(5);
-
-	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
-	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
-	mdelay(1);
-
-	/* Restore mode register */
-	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
-		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl, par);
-
-	if (M64_HAS(GTB_DSP)) {
-		u8 dll_cntl;
-
-		if (M64_HAS(XL_DLL))
-			dll_cntl = 0x80;
-		else if (par->ram_type >= SDRAM)
-			dll_cntl = 0xa6;
-		else
-			dll_cntl = 0xa0;
-		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
-		aty_st_pll_ct(VFC_CNTL, 0x1b, par);
-		aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par);
-		aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par);
-
-		mdelay(10);
-		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
-		mdelay(10);
-		aty_st_pll_ct(DLL_CNTL, dll_cntl | 0x40, par);
-		mdelay(10);
-		aty_st_pll_ct(DLL_CNTL, dll_cntl & ~0x40, par);
-	}
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
-	if (par->lcd_table != 0) {
-		/* restore LCD */
-		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl, par);
-	}
-#endif
-}
-
-static void aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u8 tmp, clock;
-
-	clock = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
-	tmp = clock << 1;
-	pll->ct.vclk_post_div = (aty_ld_pll_ct(VCLK_POST_DIV, par) >> tmp) & 0x03U;
-
-	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par) & 0x0FU;
-	pll->ct.vclk_fb_div = aty_ld_pll_ct(VCLK0_FB_DIV + clock, par) & 0xFFU;
-	pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
-	pll->ct.mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
-
-	pll->ct.pll_gen_cntl = aty_ld_pll_ct(PLL_GEN_CNTL, par);
-	pll->ct.pll_vclk_cntl = aty_ld_pll_ct(PLL_VCLK_CNTL, par);
-
-	if (M64_HAS(GTB_DSP)) {
-		pll->ct.dsp_config = aty_ld_le32(DSP_CONFIG, par);
-		pll->ct.dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
-	}
-}
-
-static int aty_init_pll_ct(const struct fb_info *info, union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u8 mpost_div, xpost_div, sclk_post_div_real;
-	u32 q, memcntl, trp;
-	u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
-#ifdef DEBUG
-	int pllmclk, pllsclk;
-#endif
-	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
-	pll->ct.xclk_post_div = pll->ct.pll_ext_cntl & 0x07;
-	pll->ct.xclk_ref_div = 1;
-	switch (pll->ct.xclk_post_div) {
-	case 0:  case 1:  case 2:  case 3:
-		break;
-
-	case 4:
-		pll->ct.xclk_ref_div = 3;
-		pll->ct.xclk_post_div = 0;
-		break;
-
-	default:
-		printk(KERN_CRIT "atyfb: Unsupported xclk source:  %d.\n", pll->ct.xclk_post_div);
-		return -EINVAL;
-	}
-	pll->ct.mclk_fb_mult = 2;
-	if(pll->ct.pll_ext_cntl & PLL_MFB_TIMES_4_2B) {
-		pll->ct.mclk_fb_mult = 4;
-		pll->ct.xclk_post_div -= 1;
-	}
-
-#ifdef DEBUG
-	printk("atyfb(%s): mclk_fb_mult=%d, xclk_post_div=%d\n",
-		__func__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div);
-#endif
-
-	memcntl = aty_ld_le32(MEM_CNTL, par);
-	trp = (memcntl & 0x300) >> 8;
-
-	pll->ct.xclkpagefaultdelay = ((memcntl & 0xc00) >> 10) + ((memcntl & 0x1000) >> 12) + trp + 2;
-	pll->ct.xclkmaxrasdelay = ((memcntl & 0x70000) >> 16) + trp + 2;
-
-	if (M64_HAS(FIFO_32)) {
-		pll->ct.fifo_size = 32;
-	} else {
-		pll->ct.fifo_size = 24;
-		pll->ct.xclkpagefaultdelay += 2;
-		pll->ct.xclkmaxrasdelay += 3;
-	}
-
-	switch (par->ram_type) {
-	case DRAM:
-		if (info->fix.smem_len<=ONE_MB) {
-			pll->ct.dsp_loop_latency = 10;
-		} else {
-			pll->ct.dsp_loop_latency = 8;
-			pll->ct.xclkpagefaultdelay += 2;
-		}
-		break;
-	case EDO:
-	case PSEUDO_EDO:
-		if (info->fix.smem_len<=ONE_MB) {
-			pll->ct.dsp_loop_latency = 9;
-		} else {
-			pll->ct.dsp_loop_latency = 8;
-			pll->ct.xclkpagefaultdelay += 1;
-		}
-		break;
-	case SDRAM:
-		if (info->fix.smem_len<=ONE_MB) {
-			pll->ct.dsp_loop_latency = 11;
-		} else {
-			pll->ct.dsp_loop_latency = 10;
-			pll->ct.xclkpagefaultdelay += 1;
-		}
-		break;
-	case SGRAM:
-		pll->ct.dsp_loop_latency = 8;
-		pll->ct.xclkpagefaultdelay += 3;
-		break;
-	default:
-		pll->ct.dsp_loop_latency = 11;
-		pll->ct.xclkpagefaultdelay += 3;
-		break;
-	}
-
-	if (pll->ct.xclkmaxrasdelay <= pll->ct.xclkpagefaultdelay)
-		pll->ct.xclkmaxrasdelay = pll->ct.xclkpagefaultdelay + 1;
-
-	/* Allow BIOS to override */
-	dsp_config = aty_ld_le32(DSP_CONFIG, par);
-	dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
-	vga_dsp_config = aty_ld_le32(VGA_DSP_CONFIG, par);
-	vga_dsp_on_off = aty_ld_le32(VGA_DSP_ON_OFF, par);
-
-	if (dsp_config)
-		pll->ct.dsp_loop_latency = (dsp_config & DSP_LOOP_LATENCY) >> 16;
-#if 0
-	FIXME: is it relevant for us?
-	if ((!dsp_on_off && !M64_HAS(RESET_3D)) ||
-		((dsp_on_off == vga_dsp_on_off) &&
-		(!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) {
-		vga_dsp_on_off &= VGA_DSP_OFF;
-		vga_dsp_config &= VGA_DSP_XCLKS_PER_QW;
-		if (ATIDivide(vga_dsp_on_off, vga_dsp_config, 5, 1) > 24)
-			pll->ct.fifo_size = 32;
-		else
-			pll->ct.fifo_size = 24;
-	}
-#endif
-	/* Exit if the user does not want us to tamper with the clock
-	rates of her chip. */
-	if (par->mclk_per == 0) {
-		u8 mclk_fb_div, pll_ext_cntl;
-		pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
-		pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
-		pll->ct.xclk_post_div_real = postdividers[pll_ext_cntl & 0x07];
-		mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
-		if (pll_ext_cntl & PLL_MFB_TIMES_4_2B)
-			mclk_fb_div <<= 1;
-		pll->ct.mclk_fb_div = mclk_fb_div;
-		return 0;
-	}
-
-	pll->ct.pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
-
-	/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
-	q = par->ref_clk_per * pll->ct.pll_ref_div * 8 /
-		(pll->ct.mclk_fb_mult * par->xclk_per);
-
-	if (q < 16*8 || q > 255*8) {
-		printk(KERN_CRIT "atxfb: xclk out of range\n");
-		return -EINVAL;
-	} else {
-		xpost_div  = (q < 128*8);
-		xpost_div += (q <  64*8);
-		xpost_div += (q <  32*8);
-	}
-	pll->ct.xclk_post_div_real = postdividers[xpost_div];
-	pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8;
-
-#ifdef CONFIG_PPC
-	if (machine_is(powermac)) {
-		/* Override PLL_EXT_CNTL & 0x07. */
-		pll->ct.xclk_post_div = xpost_div;
-		pll->ct.xclk_ref_div = 1;
-	}
-#endif
-
-#ifdef DEBUG
-	pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) /
-			(par->ref_clk_per * pll->ct.pll_ref_div);
-	printk("atyfb(%s): pllmclk=%d MHz, xclk=%d MHz\n",
-		__func__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);
-#endif
-
-	if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
-		pll->ct.pll_gen_cntl = OSC_EN;
-	else
-		pll->ct.pll_gen_cntl = OSC_EN | DLL_PWDN /* | FORCE_DCLK_TRI_STATE */;
-
-	if (M64_HAS(MAGIC_POSTDIV))
-		pll->ct.pll_ext_cntl = 0;
-	else
-		pll->ct.pll_ext_cntl = xpost_div;
-
-	if (pll->ct.mclk_fb_mult == 4)
-		pll->ct.pll_ext_cntl |= PLL_MFB_TIMES_4_2B;
-
-	if (par->mclk_per == par->xclk_per) {
-		pll->ct.pll_gen_cntl |= (xpost_div << 4); /* mclk == xclk */
-	} else {
-		/*
-		* The chip clock is not equal to the memory clock.
-		* Therefore we will use sclk to clock the chip.
-		*/
-		pll->ct.pll_gen_cntl |= (6 << 4); /* mclk == sclk */
-
-		q = par->ref_clk_per * pll->ct.pll_ref_div * 4 / par->mclk_per;
-		if (q < 16*8 || q > 255*8) {
-			printk(KERN_CRIT "atyfb: mclk out of range\n");
-			return -EINVAL;
-		} else {
-			mpost_div  = (q < 128*8);
-			mpost_div += (q <  64*8);
-			mpost_div += (q <  32*8);
-		}
-		sclk_post_div_real = postdividers[mpost_div];
-		pll->ct.sclk_fb_div = q * sclk_post_div_real / 8;
-		pll->ct.spll_cntl2 = mpost_div << 4;
-#ifdef DEBUG
-		pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) /
-			(par->ref_clk_per * pll->ct.pll_ref_div);
-		printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
-			__func__, pllsclk, pllsclk / sclk_post_div_real);
-#endif
-	}
-
-	/* Disable the extra precision pixel clock controls since we do not use them. */
-	pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par);
-	pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC);
-
-	return 0;
-}
-
-static void aty_resume_pll_ct(const struct fb_info *info,
-			      union aty_pll *pll)
-{
-	struct atyfb_par *par = info->par;
-
-	if (par->mclk_per != par->xclk_per) {
-		/*
-		* This disables the sclk, crashes the computer as reported:
-		* aty_st_pll_ct(SPLL_CNTL2, 3, info);
-		*
-		* So it seems the sclk must be enabled before it is used;
-		* so PLL_GEN_CNTL must be programmed *after* the sclk.
-		*/
-		aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par);
-		aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par);
-		/*
-		 * SCLK has been started. Wait for the PLL to lock. 5 ms
-		 * should be enough according to mach64 programmer's guide.
-		 */
-		mdelay(5);
-	}
-
-	aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par);
-	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
-	aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
-	aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
-	aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par);
-}
-
-static int dummy(void)
-{
-	return 0;
-}
-
-const struct aty_dac_ops aty_dac_ct = {
-	.set_dac	= (void *) dummy,
-};
-
-const struct aty_pll_ops aty_pll_ct = {
-	.var_to_pll	= aty_var_to_pll_ct,
-	.pll_to_var	= aty_pll_to_var_ct,
-	.set_pll	= aty_set_pll_ct,
-	.get_pll	= aty_get_pll_ct,
-	.init_pll	= aty_init_pll_ct,
-	.resume_pll	= aty_resume_pll_ct,
-};
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
deleted file mode 100644
index 0fe02e22d9a4..000000000000
--- a/drivers/video/aty/mach64_cursor.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- *  ATI Mach64 CT/VT/GT/LT Cursor Support
- */
-
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include "../fb_draw.h"
-
-#include <asm/io.h>
-
-#ifdef __sparc__
-#include <asm/fbio.h>
-#endif
-
-#include <video/mach64.h>
-#include "atyfb.h"
-
-/*
- * The hardware cursor definition requires 2 bits per pixel. The
- * Cursor size reguardless of the visible cursor size is 64 pixels
- * by 64 lines. The total memory required to define the cursor is
- * 16 bytes / line for 64 lines or 1024 bytes of data. The data
- * must be in a contigiuos format. The 2 bit cursor code values are
- * as follows:
- *
- *	00 - pixel colour = CURSOR_CLR_0
- *	01 - pixel colour = CURSOR_CLR_1
- *	10 - pixel colour = transparent (current display pixel)
- *	11 - pixel colour = 1's complement of current display pixel
- *
- *	Cursor Offset        64 pixels		 Actual Displayed Area
- *            \_________________________/
- *	      |			|	|	|
- *	      |<--------------->|	|	|
- *	      | CURS_HORZ_OFFSET|	|	|
- *	      |			|_______|	|  64 Lines
- *	      |			   ^	|	|
- *	      |			   |	|	|
- *	      |		CURS_VERT_OFFSET|	|
- *	      |			   |	|	|
- *	      |____________________|____|	|
- *
- *
- * The Screen position of the top left corner of the displayed
- * cursor is specificed by CURS_HORZ_VERT_POSN. Care must be taken
- * when the cursor hot spot is not the top left corner and the
- * physical cursor position becomes negative. It will be be displayed
- * if either the horizontal or vertical cursor position is negative
- *
- * If x becomes negative the cursor manager must adjust the CURS_HORZ_OFFSET
- * to a larger number and saturate CUR_HORZ_POSN to zero.
- *
- * if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number,
- * CUR_OFFSET must be adjusted to a point to the appropriate line in the cursor
- * definitation and CUR_VERT_POSN must be saturated to zero.
- */
-
-    /*
-     *  Hardware Cursor support.
-     */
-static const u8 cursor_bits_lookup[16] = {
-	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
-	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
-};
-
-static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u16 xoff, yoff;
-	int x, y, h;
-
-#ifdef __sparc__
-	if (par->mmaped)
-		return -EPERM;
-#endif
-	if (par->asleep)
-		return -EPERM;
-
-	wait_for_fifo(1, par);
-	if (cursor->enable)
-		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
-			    | HWCURSOR_ENABLE, par);
-	else
-		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
-				& ~HWCURSOR_ENABLE, par);
-
-	/* set position */
-	if (cursor->set & FB_CUR_SETPOS) {
-		x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
-		if (x < 0) {
-			xoff = -x;
-			x = 0;
-		} else {
-			xoff = 0;
-		}
-
-		y = cursor->image.dy - cursor->hot.y - info->var.yoffset;
-		if (y < 0) {
-			yoff = -y;
-			y = 0;
-		} else {
-			yoff = 0;
-		}
-
-		h = cursor->image.height;
-
-		/*
-		 * In doublescan mode, the cursor location
-		 * and heigh also needs to be doubled.
-		 */
-                if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) {
-			y<<=1;
-			h<<=1;
-		}
-		wait_for_fifo(3, par);
-		aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par);
-		aty_st_le32(CUR_HORZ_VERT_OFF,
-			    ((u32) (64 - h + yoff) << 16) | xoff, par);
-		aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
-	}
-
-	/* Set color map */
-	if (cursor->set & FB_CUR_SETCMAP) {
-		u32 fg_idx, bg_idx, fg, bg;
-
-		fg_idx = cursor->image.fg_color;
-		bg_idx = cursor->image.bg_color;
-
-		fg = ((info->cmap.red[fg_idx] & 0xff) << 24) |
-		     ((info->cmap.green[fg_idx] & 0xff) << 16) |
-		     ((info->cmap.blue[fg_idx] & 0xff) << 8) | 0xff;
-
-		bg = ((info->cmap.red[bg_idx] & 0xff) << 24) |
-		     ((info->cmap.green[bg_idx] & 0xff) << 16) |
-		     ((info->cmap.blue[bg_idx] & 0xff) << 8);
-
-		wait_for_fifo(2, par);
-		aty_st_le32(CUR_CLR0, bg, par);
-		aty_st_le32(CUR_CLR1, fg, par);
-	}
-
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
-	    u8 *src = (u8 *)cursor->image.data;
-	    u8 *msk = (u8 *)cursor->mask;
-	    u8 __iomem *dst = (u8 __iomem *)info->sprite.addr;
-	    unsigned int width = (cursor->image.width + 7) >> 3;
-	    unsigned int height = cursor->image.height;
-	    unsigned int align = info->sprite.scan_align;
-
-	    unsigned int i, j, offset;
-	    u8 m, b;
-
-	    // Clear cursor image with 1010101010...
-	    fb_memset(dst, 0xaa, 1024);
-
-	    offset = align - width*2;
-
-	    for (i = 0; i < height; i++) {
-		for (j = 0; j < width; j++) {
-			u16 l = 0xaaaa;
-			b = *src++;
-			m = *msk++;
-			switch (cursor->rop) {
-			case ROP_XOR:
-			    // Upper 4 bits of mask data
-			    l = cursor_bits_lookup[(b ^ m) >> 4] |
-			    // Lower 4 bits of mask
-				    (cursor_bits_lookup[(b ^ m) & 0x0f] << 8);
-			    break;
-			case ROP_COPY:
-			    // Upper 4 bits of mask data
-			    l = cursor_bits_lookup[(b & m) >> 4] |
-			    // Lower 4 bits of mask
-				    (cursor_bits_lookup[(b & m) & 0x0f] << 8);
-			    break;
-			}
-			/*
-			 * If cursor size is not a multiple of 8 characters
-			 * we must pad it with transparent pattern (0xaaaa).
-			 */
-			if ((j + 1) * 8 > cursor->image.width) {
-				l = comp(l, 0xaaaa,
-				    (1 << ((cursor->image.width & 7) * 2)) - 1);
-			}
-			fb_writeb(l & 0xff, dst++);
-			fb_writeb(l >> 8, dst++);
-		}
-		dst += offset;
-	    }
-	}
-
-	return 0;
-}
-
-int aty_init_cursor(struct fb_info *info)
-{
-	unsigned long addr;
-
-	info->fix.smem_len -= PAGE_SIZE;
-
-#ifdef __sparc__
-	addr = (unsigned long) info->screen_base - 0x800000 + info->fix.smem_len;
-	info->sprite.addr = (u8 *) addr;
-#else
-#ifdef __BIG_ENDIAN
-	addr = info->fix.smem_start - 0x800000 + info->fix.smem_len;
-	info->sprite.addr = (u8 *) ioremap(addr, 1024);
-#else
-	addr = (unsigned long) info->screen_base + info->fix.smem_len;
-	info->sprite.addr = (u8 *) addr;
-#endif
-#endif
-	if (!info->sprite.addr)
-		return -ENXIO;
-	info->sprite.size = PAGE_SIZE;
-	info->sprite.scan_align = 16;	/* Scratch pad 64 bytes wide */
-	info->sprite.buf_align = 16; 	/* and 64 lines tall. */
-	info->sprite.flags = FB_PIXMAP_IO;
-
-	info->fbops->fb_cursor = atyfb_cursor;
-
-	return 0;
-}
-
diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c
deleted file mode 100644
index 10c988aef58e..000000000000
--- a/drivers/video/aty/mach64_gx.c
+++ /dev/null
@@ -1,910 +0,0 @@
-
-/*
- *  ATI Mach64 GX Support
- */
-
-#include <linux/delay.h>
-#include <linux/fb.h>
-
-#include <asm/io.h>
-
-#include <video/mach64.h>
-#include "atyfb.h"
-
-/* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
-
-#define REF_FREQ_2595       1432	/*  14.33 MHz  (exact   14.31818) */
-#define REF_DIV_2595          46	/* really 43 on ICS 2595 !!!  */
-				  /* ohne Prescaler */
-#define MAX_FREQ_2595      15938	/* 159.38 MHz  (really 170.486) */
-#define MIN_FREQ_2595       8000	/*  80.00 MHz  (        85.565) */
-				  /* mit Prescaler 2, 4, 8 */
-#define ABS_MIN_FREQ_2595   1000	/*  10.00 MHz  (really  10.697) */
-#define N_ADJ_2595           257
-
-#define STOP_BITS_2595     0x1800
-
-
-#define MIN_N_408		2
-
-#define MIN_N_1703		6
-
-#define MIN_M		2
-#define MAX_M		30
-#define MIN_N		35
-#define MAX_N		255-8
-
-
-    /*
-     *  Support Functions
-     */
-
-static void aty_dac_waste4(const struct atyfb_par *par)
-{
-	(void) aty_ld_8(DAC_REGS, par);
-
-	(void) aty_ld_8(DAC_REGS + 2, par);
-	(void) aty_ld_8(DAC_REGS + 2, par);
-	(void) aty_ld_8(DAC_REGS + 2, par);
-	(void) aty_ld_8(DAC_REGS + 2, par);
-}
-
-static void aty_StrobeClock(const struct atyfb_par *par)
-{
-	u8 tmp;
-
-	udelay(26);
-
-	tmp = aty_ld_8(CLOCK_CNTL, par);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, tmp | CLOCK_STROBE, par);
-	return;
-}
-
-
-    /*
-     *  IBM RGB514 DAC and Clock Chip
-     */
-
-static void aty_st_514(int offset, u8 val, const struct atyfb_par *par)
-{
-	aty_st_8(DAC_CNTL, 1, par);
-	/* right addr byte */
-	aty_st_8(DAC_W_INDEX, offset & 0xff, par);
-	/* left addr byte */
-	aty_st_8(DAC_DATA, (offset >> 8) & 0xff, par);
-	aty_st_8(DAC_MASK, val, par);
-	aty_st_8(DAC_CNTL, 0, par);
-}
-
-static int aty_set_dac_514(const struct fb_info *info,
-			   const union aty_pll *pll, u32 bpp, u32 accel)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	static struct {
-		u8 pixel_dly;
-		u8 misc2_cntl;
-		u8 pixel_rep;
-		u8 pixel_cntl_index;
-		u8 pixel_cntl_v1;
-	} tab[3] = {
-		{
-		0, 0x41, 0x03, 0x71, 0x45},	/* 8 bpp */
-		{
-		0, 0x45, 0x04, 0x0c, 0x01},	/* 555 */
-		{
-		0, 0x45, 0x06, 0x0e, 0x00},	/* XRGB */
-	};
-	int i;
-
-	switch (bpp) {
-	case 8:
-	default:
-		i = 0;
-		break;
-	case 16:
-		i = 1;
-		break;
-	case 32:
-		i = 2;
-		break;
-	}
-	aty_st_514(0x90, 0x00, par);	/* VRAM Mask Low */
-	aty_st_514(0x04, tab[i].pixel_dly, par);	/* Horizontal Sync Control */
-	aty_st_514(0x05, 0x00, par);	/* Power Management */
-	aty_st_514(0x02, 0x01, par);	/* Misc Clock Control */
-	aty_st_514(0x71, tab[i].misc2_cntl, par);	/* Misc Control 2 */
-	aty_st_514(0x0a, tab[i].pixel_rep, par);	/* Pixel Format */
-	aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, par);
-	/* Misc Control 2 / 16 BPP Control / 32 BPP Control */
-	return 0;
-}
-
-static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
-			      u32 bpp, union aty_pll *pll)
-{
-	/*
-	 *  FIXME: use real calculations instead of using fixed values from the old
-	 *         driver
-	 */
-	static struct {
-		u32 limit;	/* pixlock rounding limit (arbitrary) */
-		u8 m;		/* (df<<6) | vco_div_count */
-		u8 n;		/* ref_div_count */
-	} RGB514_clocks[7] = {
-		{
-		8000, (3 << 6) | 20, 9},	/*  7395 ps / 135.2273 MHz */
-		{
-		10000, (1 << 6) | 19, 3},	/*  9977 ps / 100.2273 MHz */
-		{
-		13000, (1 << 6) | 2, 3},	/* 12509 ps /  79.9432 MHz */
-		{
-		14000, (2 << 6) | 8, 7},	/* 13394 ps /  74.6591 MHz */
-		{
-		16000, (1 << 6) | 44, 6},	/* 15378 ps /  65.0284 MHz */
-		{
-		25000, (1 << 6) | 15, 5},	/* 17460 ps /  57.2727 MHz */
-		{
-		50000, (0 << 6) | 53, 7},	/* 33145 ps /  30.1705 MHz */
-	};
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++)
-		if (vclk_per <= RGB514_clocks[i].limit) {
-			pll->ibm514.m = RGB514_clocks[i].m;
-			pll->ibm514.n = RGB514_clocks[i].n;
-			return 0;
-		}
-	return -EINVAL;
-}
-
-static u32 aty_pll_514_to_var(const struct fb_info *info,
-			      const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u8 df, vco_div_count, ref_div_count;
-
-	df = pll->ibm514.m >> 6;
-	vco_div_count = pll->ibm514.m & 0x3f;
-	ref_div_count = pll->ibm514.n;
-
-	return ((par->ref_clk_per * ref_div_count) << (3 - df))/
-	    		(vco_div_count + 65);
-}
-
-static void aty_set_pll_514(const struct fb_info *info,
-			    const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	aty_st_514(0x06, 0x02, par);	/* DAC Operation */
-	aty_st_514(0x10, 0x01, par);	/* PLL Control 1 */
-	aty_st_514(0x70, 0x01, par);	/* Misc Control 1 */
-	aty_st_514(0x8f, 0x1f, par);	/* PLL Ref. Divider Input */
-	aty_st_514(0x03, 0x00, par);	/* Sync Control */
-	aty_st_514(0x05, 0x00, par);	/* Power Management */
-	aty_st_514(0x20, pll->ibm514.m, par);	/* F0 / M0 */
-	aty_st_514(0x21, pll->ibm514.n, par);	/* F1 / N0 */
-}
-
-const struct aty_dac_ops aty_dac_ibm514 = {
-	.set_dac	= aty_set_dac_514,
-};
-
-const struct aty_pll_ops aty_pll_ibm514 = {
-	.var_to_pll	= aty_var_to_pll_514,
-	.pll_to_var	= aty_pll_514_to_var,
-	.set_pll	= aty_set_pll_514,
-};
-
-
-    /*
-     *  ATI 68860-B DAC
-     */
-
-static int aty_set_dac_ATI68860_B(const struct fb_info *info,
-				  const union aty_pll *pll, u32 bpp,
-				  u32 accel)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 gModeReg, devSetupRegA, temp, mask;
-
-	gModeReg = 0;
-	devSetupRegA = 0;
-
-	switch (bpp) {
-	case 8:
-		gModeReg = 0x83;
-		devSetupRegA =
-		    0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */ ;
-		break;
-	case 15:
-		gModeReg = 0xA0;
-		devSetupRegA = 0x60;
-		break;
-	case 16:
-		gModeReg = 0xA1;
-		devSetupRegA = 0x60;
-		break;
-	case 24:
-		gModeReg = 0xC0;
-		devSetupRegA = 0x60;
-		break;
-	case 32:
-		gModeReg = 0xE3;
-		devSetupRegA = 0x60;
-		break;
-	}
-
-	if (!accel) {
-		gModeReg = 0x80;
-		devSetupRegA = 0x61;
-	}
-
-	temp = aty_ld_8(DAC_CNTL, par);
-	aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
-		 par);
-
-	aty_st_8(DAC_REGS + 2, 0x1D, par);
-	aty_st_8(DAC_REGS + 3, gModeReg, par);
-	aty_st_8(DAC_REGS, 0x02, par);
-
-	temp = aty_ld_8(DAC_CNTL, par);
-	aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
-
-	if (info->fix.smem_len < ONE_MB)
-		mask = 0x04;
-	else if (info->fix.smem_len == ONE_MB)
-		mask = 0x08;
-	else
-		mask = 0x0C;
-
-	/* The following assumes that the BIOS has correctly set R7 of the
-	 * Device Setup Register A at boot time.
-	 */
-#define A860_DELAY_L	0x80
-
-	temp = aty_ld_8(DAC_REGS, par);
-	aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L),
-		 par);
-	temp = aty_ld_8(DAC_CNTL, par);
-	aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)),
-		 par);
-
-	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
-	aty_st_le32(DAC_CNTL, 0x47052100, par);
-	return 0;
-}
-
-const struct aty_dac_ops aty_dac_ati68860b = {
-	.set_dac	= aty_set_dac_ATI68860_B,
-};
-
-
-    /*
-     *  AT&T 21C498 DAC
-     */
-
-static int aty_set_dac_ATT21C498(const struct fb_info *info,
-				 const union aty_pll *pll, u32 bpp,
-				 u32 accel)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 dotClock;
-	int muxmode = 0;
-	int DACMask = 0;
-
-	dotClock = 100000000 / pll->ics2595.period_in_ps;
-
-	switch (bpp) {
-	case 8:
-		if (dotClock > 8000) {
-			DACMask = 0x24;
-			muxmode = 1;
-		} else
-			DACMask = 0x04;
-		break;
-	case 15:
-		DACMask = 0x16;
-		break;
-	case 16:
-		DACMask = 0x36;
-		break;
-	case 24:
-		DACMask = 0xE6;
-		break;
-	case 32:
-		DACMask = 0xE6;
-		break;
-	}
-
-	if (1 /* info->mach64DAC8Bit */ )
-		DACMask |= 0x02;
-
-	aty_dac_waste4(par);
-	aty_st_8(DAC_REGS + 2, DACMask, par);
-
-	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
-	aty_st_le32(DAC_CNTL, 0x00072000, par);
-	return muxmode;
-}
-
-const struct aty_dac_ops aty_dac_att21c498 = {
-	.set_dac	= aty_set_dac_ATT21C498,
-};
-
-
-    /*
-     *  ATI 18818 / ICS 2595 Clock Chip
-     */
-
-static int aty_var_to_pll_18818(const struct fb_info *info, u32 vclk_per,
-				u32 bpp, union aty_pll *pll)
-{
-	u32 MHz100;		/* in 0.01 MHz */
-	u32 program_bits;
-	u32 post_divider;
-
-	/* Calculate the programming word */
-	MHz100 = 100000000 / vclk_per;
-
-	program_bits = -1;
-	post_divider = 1;
-
-	if (MHz100 > MAX_FREQ_2595) {
-		MHz100 = MAX_FREQ_2595;
-		return -EINVAL;
-	} else if (MHz100 < ABS_MIN_FREQ_2595) {
-		program_bits = 0;	/* MHz100 = 257 */
-		return -EINVAL;
-	} else {
-		while (MHz100 < MIN_FREQ_2595) {
-			MHz100 *= 2;
-			post_divider *= 2;
-		}
-	}
-	MHz100 *= 1000;
-	MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
- 
-	MHz100 += 500;		/* + 0.5 round */
-	MHz100 /= 1000;
-
-	if (program_bits == -1) {
-		program_bits = MHz100 - N_ADJ_2595;
-		switch (post_divider) {
-		case 1:
-			program_bits |= 0x0600;
-			break;
-		case 2:
-			program_bits |= 0x0400;
-			break;
-		case 4:
-			program_bits |= 0x0200;
-			break;
-		case 8:
-		default:
-			break;
-		}
-	}
-
-	program_bits |= STOP_BITS_2595;
-
-	pll->ics2595.program_bits = program_bits;
-	pll->ics2595.locationAddr = 0;
-	pll->ics2595.post_divider = post_divider;
-	pll->ics2595.period_in_ps = vclk_per;
-
-	return 0;
-}
-
-static u32 aty_pll_18818_to_var(const struct fb_info *info,
-				const union aty_pll *pll)
-{
-	return (pll->ics2595.period_in_ps);	/* default for now */
-}
-
-static void aty_ICS2595_put1bit(u8 data, const struct atyfb_par *par)
-{
-	u8 tmp;
-
-	data &= 0x01;
-	tmp = aty_ld_8(CLOCK_CNTL, par);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
-		 (tmp & ~0x04) | (data << 2), par);
-
-	tmp = aty_ld_8(CLOCK_CNTL, par);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (0 << 3),
-		 par);
-
-	aty_StrobeClock(par);
-
-	tmp = aty_ld_8(CLOCK_CNTL, par);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (1 << 3),
-		 par);
-
-	aty_StrobeClock(par);
-	return;
-}
-
-static void aty_set_pll18818(const struct fb_info *info,
-			     const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 program_bits;
-	u32 locationAddr;
-
-	u32 i;
-
-	u8 old_clock_cntl;
-	u8 old_crtc_ext_disp;
-
-	old_clock_cntl = aty_ld_8(CLOCK_CNTL, par);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
-
-	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
-	aty_st_8(CRTC_GEN_CNTL + 3,
-		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
-
-	mdelay(15);		/* delay for 50 (15) ms */
-
-	program_bits = pll->ics2595.program_bits;
-	locationAddr = pll->ics2595.locationAddr;
-
-	/* Program the clock chip */
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);	/* Strobe = 0 */
-	aty_StrobeClock(par);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 1, par);	/* Strobe = 0 */
-	aty_StrobeClock(par);
-
-	aty_ICS2595_put1bit(1, par);	/* Send start bits */
-	aty_ICS2595_put1bit(0, par);	/* Start bit */
-	aty_ICS2595_put1bit(0, par);	/* Read / ~Write */
-
-	for (i = 0; i < 5; i++) {	/* Location 0..4 */
-		aty_ICS2595_put1bit(locationAddr & 1, par);
-		locationAddr >>= 1;
-	}
-
-	for (i = 0; i < 8 + 1 + 2 + 2; i++) {
-		aty_ICS2595_put1bit(program_bits & 1, par);
-		program_bits >>= 1;
-	}
-
-	mdelay(1);		/* delay for 1 ms */
-
-	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
-	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
-		 old_clock_cntl | CLOCK_STROBE, par);
-
-	mdelay(50);		/* delay for 50 (15) ms */
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
-		 ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par);
-	return;
-}
-
-const struct aty_pll_ops aty_pll_ati18818_1 = {
-	.var_to_pll	= aty_var_to_pll_18818,
-	.pll_to_var	= aty_pll_18818_to_var,
-	.set_pll	= aty_set_pll18818,
-};
-
-
-    /*
-     *  STG 1703 Clock Chip
-     */
-
-static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per,
-			       u32 bpp, union aty_pll *pll)
-{
-	u32 mhz100;		/* in 0.01 MHz */
-	u32 program_bits;
-	/* u32 post_divider; */
-	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
-	u32 temp, tempB;
-	u16 remainder, preRemainder;
-	short divider = 0, tempA;
-
-	/* Calculate the programming word */
-	mhz100 = 100000000 / vclk_per;
-	mach64MinFreq = MIN_FREQ_2595;
-	mach64MaxFreq = MAX_FREQ_2595;
-	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
-
-	/* Calculate program word */
-	if (mhz100 == 0)
-		program_bits = 0xE0;
-	else {
-		if (mhz100 < mach64MinFreq)
-			mhz100 = mach64MinFreq;
-		if (mhz100 > mach64MaxFreq)
-			mhz100 = mach64MaxFreq;
-
-		divider = 0;
-		while (mhz100 < (mach64MinFreq << 3)) {
-			mhz100 <<= 1;
-			divider += 0x20;
-		}
-
-		temp = (unsigned int) (mhz100);
-		temp = (unsigned int) (temp * (MIN_N_1703 + 2));
-		temp -= (short) (mach64RefFreq << 1);
-
-		tempA = MIN_N_1703;
-		preRemainder = 0xffff;
-
-		do {
-			tempB = temp;
-			remainder = tempB % mach64RefFreq;
-			tempB = tempB / mach64RefFreq;
-
-			if ((tempB & 0xffff) <= 127
-			    && (remainder <= preRemainder)) {
-				preRemainder = remainder;
-				divider &= ~0x1f;
-				divider |= tempA;
-				divider =
-				    (divider & 0x00ff) +
-				    ((tempB & 0xff) << 8);
-			}
-
-			temp += mhz100;
-			tempA++;
-		} while (tempA <= (MIN_N_1703 << 1));
-
-		program_bits = divider;
-	}
-
-	pll->ics2595.program_bits = program_bits;
-	pll->ics2595.locationAddr = 0;
-	pll->ics2595.post_divider = divider;	/* fuer nix */
-	pll->ics2595.period_in_ps = vclk_per;
-
-	return 0;
-}
-
-static u32 aty_pll_1703_to_var(const struct fb_info *info,
-			       const union aty_pll *pll)
-{
-	return (pll->ics2595.period_in_ps);	/* default for now */
-}
-
-static void aty_set_pll_1703(const struct fb_info *info,
-			     const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 program_bits;
-	u32 locationAddr;
-
-	char old_crtc_ext_disp;
-
-	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
-	aty_st_8(CRTC_GEN_CNTL + 3,
-		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
-
-	program_bits = pll->ics2595.program_bits;
-	locationAddr = pll->ics2595.locationAddr;
-
-	/* Program clock */
-	aty_dac_waste4(par);
-
-	(void) aty_ld_8(DAC_REGS + 2, par);
-	aty_st_8(DAC_REGS + 2, (locationAddr << 1) + 0x20, par);
-	aty_st_8(DAC_REGS + 2, 0, par);
-	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF00) >> 8, par);
-	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF), par);
-
-	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
-	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
-	return;
-}
-
-const struct aty_pll_ops aty_pll_stg1703 = {
-	.var_to_pll	= aty_var_to_pll_1703,
-	.pll_to_var	= aty_pll_1703_to_var,
-	.set_pll	= aty_set_pll_1703,
-};
-
-
-    /*
-     *  Chrontel 8398 Clock Chip
-     */
-
-static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
-			       u32 bpp, union aty_pll *pll)
-{
-	u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
-
-	u32 mhz100;		/* in 0.01 MHz */
-	u32 program_bits;
-	/* u32 post_divider; */
-	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
-	u16 m, n, k = 0, save_m, save_n, twoToKth;
-
-	/* Calculate the programming word */
-	mhz100 = 100000000 / vclk_per;
-	mach64MinFreq = MIN_FREQ_2595;
-	mach64MaxFreq = MAX_FREQ_2595;
-	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
-
-	save_m = 0;
-	save_n = 0;
-
-	/* Calculate program word */
-	if (mhz100 == 0)
-		program_bits = 0xE0;
-	else {
-		if (mhz100 < mach64MinFreq)
-			mhz100 = mach64MinFreq;
-		if (mhz100 > mach64MaxFreq)
-			mhz100 = mach64MaxFreq;
-
-		longMHz100 = mhz100 * 256 / 100;	/* 8 bit scale this */
-
-		while (mhz100 < (mach64MinFreq << 3)) {
-			mhz100 <<= 1;
-			k++;
-		}
-
-		twoToKth = 1 << k;
-		diff = 0;
-		preDiff = 0xFFFFFFFF;
-
-		for (m = MIN_M; m <= MAX_M; m++) {
-			for (n = MIN_N; n <= MAX_N; n++) {
-				tempA = 938356;		/* 14.31818 * 65536 */
-				tempA *= (n + 8);	/* 43..256 */
-				tempB = twoToKth * 256;
-				tempB *= (m + 2);	/* 4..32 */
-				fOut = tempA / tempB;	/* 8 bit scale */
-
-				if (longMHz100 > fOut)
-					diff = longMHz100 - fOut;
-				else
-					diff = fOut - longMHz100;
-
-				if (diff < preDiff) {
-					save_m = m;
-					save_n = n;
-					preDiff = diff;
-				}
-			}
-		}
-
-		program_bits = (k << 6) + (save_m) + (save_n << 8);
-	}
-
-	pll->ics2595.program_bits = program_bits;
-	pll->ics2595.locationAddr = 0;
-	pll->ics2595.post_divider = 0;
-	pll->ics2595.period_in_ps = vclk_per;
-
-	return 0;
-}
-
-static u32 aty_pll_8398_to_var(const struct fb_info *info,
-			       const union aty_pll *pll)
-{
-	return (pll->ics2595.period_in_ps);	/* default for now */
-}
-
-static void aty_set_pll_8398(const struct fb_info *info,
-			     const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 program_bits;
-	u32 locationAddr;
-
-	char old_crtc_ext_disp;
-	char tmp;
-
-	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
-	aty_st_8(CRTC_GEN_CNTL + 3,
-		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
-
-	program_bits = pll->ics2595.program_bits;
-	locationAddr = pll->ics2595.locationAddr;
-
-	/* Program clock */
-	tmp = aty_ld_8(DAC_CNTL, par);
-	aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
-
-	aty_st_8(DAC_REGS, locationAddr, par);
-	aty_st_8(DAC_REGS + 1, (program_bits & 0xff00) >> 8, par);
-	aty_st_8(DAC_REGS + 1, (program_bits & 0xff), par);
-
-	tmp = aty_ld_8(DAC_CNTL, par);
-	aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
-		 par);
-
-	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
-	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
-
-	return;
-}
-
-const struct aty_pll_ops aty_pll_ch8398 = {
-	.var_to_pll	= aty_var_to_pll_8398,
-	.pll_to_var	= aty_pll_8398_to_var,
-	.set_pll	= aty_set_pll_8398,
-};
-
-
-    /*
-     *  AT&T 20C408 Clock Chip
-     */
-
-static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per,
-			      u32 bpp, union aty_pll *pll)
-{
-	u32 mhz100;		/* in 0.01 MHz */
-	u32 program_bits;
-	/* u32 post_divider; */
-	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
-	u32 temp, tempB;
-	u16 remainder, preRemainder;
-	short divider = 0, tempA;
-
-	/* Calculate the programming word */
-	mhz100 = 100000000 / vclk_per;
-	mach64MinFreq = MIN_FREQ_2595;
-	mach64MaxFreq = MAX_FREQ_2595;
-	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
-
-	/* Calculate program word */
-	if (mhz100 == 0)
-		program_bits = 0xFF;
-	else {
-		if (mhz100 < mach64MinFreq)
-			mhz100 = mach64MinFreq;
-		if (mhz100 > mach64MaxFreq)
-			mhz100 = mach64MaxFreq;
-
-		while (mhz100 < (mach64MinFreq << 3)) {
-			mhz100 <<= 1;
-			divider += 0x40;
-		}
-
-		temp = (unsigned int) mhz100;
-		temp = (unsigned int) (temp * (MIN_N_408 + 2));
-		temp -= ((short) (mach64RefFreq << 1));
-
-		tempA = MIN_N_408;
-		preRemainder = 0xFFFF;
-
-		do {
-			tempB = temp;
-			remainder = tempB % mach64RefFreq;
-			tempB = tempB / mach64RefFreq;
-			if (((tempB & 0xFFFF) <= 255)
-			    && (remainder <= preRemainder)) {
-				preRemainder = remainder;
-				divider &= ~0x3f;
-				divider |= tempA;
-				divider =
-				    (divider & 0x00FF) +
-				    ((tempB & 0xFF) << 8);
-			}
-			temp += mhz100;
-			tempA++;
-		} while (tempA <= 32);
-
-		program_bits = divider;
-	}
-
-	pll->ics2595.program_bits = program_bits;
-	pll->ics2595.locationAddr = 0;
-	pll->ics2595.post_divider = divider;	/* fuer nix */
-	pll->ics2595.period_in_ps = vclk_per;
-
-	return 0;
-}
-
-static u32 aty_pll_408_to_var(const struct fb_info *info,
-			      const union aty_pll *pll)
-{
-	return (pll->ics2595.period_in_ps);	/* default for now */
-}
-
-static void aty_set_pll_408(const struct fb_info *info,
-			    const union aty_pll *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 program_bits;
-	u32 locationAddr;
-
-	u8 tmpA, tmpB, tmpC;
-	char old_crtc_ext_disp;
-
-	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
-	aty_st_8(CRTC_GEN_CNTL + 3,
-		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
-
-	program_bits = pll->ics2595.program_bits;
-	locationAddr = pll->ics2595.locationAddr;
-
-	/* Program clock */
-	aty_dac_waste4(par);
-	tmpB = aty_ld_8(DAC_REGS + 2, par) | 1;
-	aty_dac_waste4(par);
-	aty_st_8(DAC_REGS + 2, tmpB, par);
-
-	tmpA = tmpB;
-	tmpC = tmpA;
-	tmpA |= 8;
-	tmpB = 1;
-
-	aty_st_8(DAC_REGS, tmpB, par);
-	aty_st_8(DAC_REGS + 2, tmpA, par);
-
-	udelay(400);		/* delay for 400 us */
-
-	locationAddr = (locationAddr << 2) + 0x40;
-	tmpB = locationAddr;
-	tmpA = program_bits >> 8;
-
-	aty_st_8(DAC_REGS, tmpB, par);
-	aty_st_8(DAC_REGS + 2, tmpA, par);
-
-	tmpB = locationAddr + 1;
-	tmpA = (u8) program_bits;
-
-	aty_st_8(DAC_REGS, tmpB, par);
-	aty_st_8(DAC_REGS + 2, tmpA, par);
-
-	tmpB = locationAddr + 2;
-	tmpA = 0x77;
-
-	aty_st_8(DAC_REGS, tmpB, par);
-	aty_st_8(DAC_REGS + 2, tmpA, par);
-
-	udelay(400);		/* delay for 400 us */
-	tmpA = tmpC & (~(1 | 8));
-	tmpB = 1;
-
-	aty_st_8(DAC_REGS, tmpB, par);
-	aty_st_8(DAC_REGS + 2, tmpA, par);
-
-	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
-	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
-	return;
-}
-
-const struct aty_pll_ops aty_pll_att20c408 = {
-	.var_to_pll	= aty_var_to_pll_408,
-	.pll_to_var	= aty_pll_408_to_var,
-	.set_pll	= aty_set_pll_408,
-};
-
-
-    /*
-     *  Unsupported DAC and Clock Chip
-     */
-
-static int aty_set_dac_unsupported(const struct fb_info *info,
-				   const union aty_pll *pll, u32 bpp,
-				   u32 accel)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
-	aty_st_le32(DAC_CNTL, 0x47052100, par);
-	/* new in 2.2.3p1 from Geert. ???????? */
-	aty_st_le32(BUS_CNTL, 0x590e10ff, par);
-	aty_st_le32(DAC_CNTL, 0x47012100, par);
-	return 0;
-}
-
-static int dummy(void)
-{
-	return 0;
-}
-
-const struct aty_dac_ops aty_dac_unsupported = {
-	.set_dac	= aty_set_dac_unsupported,
-};
-
-const struct aty_pll_ops aty_pll_unsupported = {
-	.var_to_pll	= (void *) dummy,
-	.pll_to_var	= (void *) dummy,
-	.set_pll	= (void *) dummy,
-};
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
deleted file mode 100644
index a469a3d6edcb..000000000000
--- a/drivers/video/aty/radeon_accel.c
+++ /dev/null
@@ -1,328 +0,0 @@
-#include "radeonfb.h"
-
-/* the accelerated functions here are patterned after the 
- * "ACCEL_MMIO" ifdef branches in XFree86
- * --dte
- */
-
-static void radeon_fixup_offset(struct radeonfb_info *rinfo)
-{
-	u32 local_base;
-
-	/* *** Ugly workaround *** */
-	/*
-	 * On some platforms, the video memory is mapped at 0 in radeon chip space
-	 * (like PPCs) by the firmware. X will always move it up so that it's seen
-	 * by the chip to be at the same address as the PCI BAR.
-	 * That means that when switching back from X, there is a mismatch between
-	 * the offsets programmed into the engine. This means that potentially,
-	 * accel operations done before radeonfb has a chance to re-init the engine
-	 * will have incorrect offsets, and potentially trash system memory !
-	 *
-	 * The correct fix is for fbcon to never call any accel op before the engine
-	 * has properly been re-initialized (by a call to set_var), but this is a
-	 * complex fix. This workaround in the meantime, called before every accel
-	 * operation, makes sure the offsets are in sync.
-	 */
-
-	radeon_fifo_wait (1);
-	local_base = INREG(MC_FB_LOCATION) << 16;
-	if (local_base == rinfo->fb_local_base)
-		return;
-
-	rinfo->fb_local_base = local_base;
-
-	radeon_fifo_wait (3);
-	OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
-				     (rinfo->fb_local_base >> 10));
-	OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
-	OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
-}
-
-static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 
-				   const struct fb_fillrect *region)
-{
-	radeon_fifo_wait(4);  
-  
-	OUTREG(DP_GUI_MASTER_CNTL,  
-		rinfo->dp_gui_master_cntl  /* contains, like GMC_DST_32BPP */
-                | GMC_BRUSH_SOLID_COLOR
-                | ROP3_P);
-	if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
-		OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
-	else
-		OUTREG(DP_BRUSH_FRGD_CLR, region->color);
-	OUTREG(DP_WRITE_MSK, 0xffffffff);
-	OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
-
-	radeon_fifo_wait(2);
-	OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
-	OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-
-	radeon_fifo_wait(2);  
-	OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
-	OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
-}
-
-void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
-{
-	struct radeonfb_info *rinfo = info->par;
-	struct fb_fillrect modded;
-	int vxres, vyres;
-  
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(info, region);
-		return;
-	}
-
-	radeon_fixup_offset(rinfo);
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	memcpy(&modded, region, sizeof(struct fb_fillrect));
-
-	if(!modded.width || !modded.height ||
-	   modded.dx >= vxres || modded.dy >= vyres)
-		return;
-  
-	if(modded.dx + modded.width  > vxres) modded.width  = vxres - modded.dx;
-	if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
-
-	radeonfb_prim_fillrect(rinfo, &modded);
-}
-
-static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, 
-				   const struct fb_copyarea *area)
-{
-	int xdir, ydir;
-	u32 sx, sy, dx, dy, w, h;
-
-	w = area->width; h = area->height;
-	dx = area->dx; dy = area->dy;
-	sx = area->sx; sy = area->sy;
-	xdir = sx - dx;
-	ydir = sy - dy;
-
-	if ( xdir < 0 ) { sx += w-1; dx += w-1; }
-	if ( ydir < 0 ) { sy += h-1; dy += h-1; }
-
-	radeon_fifo_wait(3);
-	OUTREG(DP_GUI_MASTER_CNTL,
-		rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
-		| GMC_BRUSH_NONE
-		| GMC_SRC_DSTCOLOR
-		| ROP3_S 
-		| DP_SRC_SOURCE_MEMORY );
-	OUTREG(DP_WRITE_MSK, 0xffffffff);
-	OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
-			| (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
-
-	radeon_fifo_wait(2);
-	OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
-	OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-
-	radeon_fifo_wait(3);
-	OUTREG(SRC_Y_X, (sy << 16) | sx);
-	OUTREG(DST_Y_X, (dy << 16) | dx);
-	OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
-}
-
-
-void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct radeonfb_info *rinfo = info->par;
-	struct fb_copyarea modded;
-	u32 vxres, vyres;
-	modded.sx = area->sx;
-	modded.sy = area->sy;
-	modded.dx = area->dx;
-	modded.dy = area->dy;
-	modded.width  = area->width;
-	modded.height = area->height;
-  
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	radeon_fixup_offset(rinfo);
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	if(!modded.width || !modded.height ||
-	   modded.sx >= vxres || modded.sy >= vyres ||
-	   modded.dx >= vxres || modded.dy >= vyres)
-		return;
-  
-	if(modded.sx + modded.width > vxres)  modded.width = vxres - modded.sx;
-	if(modded.dx + modded.width > vxres)  modded.width = vxres - modded.dx;
-	if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
-	if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
-  
-	radeonfb_prim_copyarea(rinfo, &modded);
-}
-
-void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct radeonfb_info *rinfo = info->par;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	radeon_engine_idle();
-
-	cfb_imageblit(info, image);
-}
-
-int radeonfb_sync(struct fb_info *info)
-{
-	struct radeonfb_info *rinfo = info->par;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return 0;
-	radeon_engine_idle();
-
-	return 0;
-}
-
-void radeonfb_engine_reset(struct radeonfb_info *rinfo)
-{
-	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
-	u32 host_path_cntl;
-
-	radeon_engine_flush (rinfo);
-
-	clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
-	mclk_cntl = INPLL(MCLK_CNTL);
-
-	OUTPLL(MCLK_CNTL, (mclk_cntl |
-			   FORCEON_MCLKA |
-			   FORCEON_MCLKB |
-			   FORCEON_YCLKA |
-			   FORCEON_YCLKB |
-			   FORCEON_MC |
-			   FORCEON_AIC));
-
-	host_path_cntl = INREG(HOST_PATH_CNTL);
-	rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
-
-	if (IS_R300_VARIANT(rinfo)) {
-		u32 tmp;
-
-		OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
-					 SOFT_RESET_CP |
-					 SOFT_RESET_HI |
-					 SOFT_RESET_E2));
-		INREG(RBBM_SOFT_RESET);
-		OUTREG(RBBM_SOFT_RESET, 0);
-		tmp = INREG(RB2D_DSTCACHE_MODE);
-		OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */
-	} else {
-		OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
-					SOFT_RESET_CP |
-					SOFT_RESET_HI |
-					SOFT_RESET_SE |
-					SOFT_RESET_RE |
-					SOFT_RESET_PP |
-					SOFT_RESET_E2 |
-					SOFT_RESET_RB);
-		INREG(RBBM_SOFT_RESET);
-		OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
-					~(SOFT_RESET_CP |
-					  SOFT_RESET_HI |
-					  SOFT_RESET_SE |
-					  SOFT_RESET_RE |
-					  SOFT_RESET_PP |
-					  SOFT_RESET_E2 |
-					  SOFT_RESET_RB));
-		INREG(RBBM_SOFT_RESET);
-	}
-
-	OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET);
-	INREG(HOST_PATH_CNTL);
-	OUTREG(HOST_PATH_CNTL, host_path_cntl);
-
-	if (!IS_R300_VARIANT(rinfo))
-		OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
-
-	OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
-	OUTPLL(MCLK_CNTL, mclk_cntl);
-}
-
-void radeonfb_engine_init (struct radeonfb_info *rinfo)
-{
-	unsigned long temp;
-
-	/* disable 3D engine */
-	OUTREG(RB3D_CNTL, 0);
-
-	radeonfb_engine_reset(rinfo);
-
-	radeon_fifo_wait (1);
-	if (IS_R300_VARIANT(rinfo)) {
-		OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
-		       RB2D_DC_AUTOFLUSH_ENABLE |
-		       RB2D_DC_DC_DISABLE_IGNORE_PE);
-	} else {
-		/* This needs to be double checked with ATI. Latest X driver
-		 * completely "forgets" to set this register on < r3xx, and
-		 * we used to just write 0 there... I'll keep the 0 and update
-		 * that when we have sorted things out on X side.
-		 */
-		OUTREG(RB2D_DSTCACHE_MODE, 0);
-	}
-
-	radeon_fifo_wait (3);
-	/* We re-read MC_FB_LOCATION from card as it can have been
-	 * modified by XFree drivers (ouch !)
-	 */
-	rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
-
-	OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
-				     (rinfo->fb_local_base >> 10));
-	OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
-	OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
-
-	radeon_fifo_wait (1);
-#if defined(__BIG_ENDIAN)
-	OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
-#else
-	OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
-#endif
-	radeon_fifo_wait (2);
-	OUTREG(DEFAULT_SC_TOP_LEFT, 0);
-	OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
-					 DEFAULT_SC_BOTTOM_MAX));
-
-	temp = radeon_get_dstbpp(rinfo->depth);
-	rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
-
-	radeon_fifo_wait (1);
-	OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
-				    GMC_BRUSH_SOLID_COLOR |
-				    GMC_SRC_DATATYPE_COLOR));
-
-	radeon_fifo_wait (7);
-
-	/* clear line drawing regs */
-	OUTREG(DST_LINE_START, 0);
-	OUTREG(DST_LINE_END, 0);
-
-	/* set brush color regs */
-	OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
-	OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
-
-	/* set source color regs */
-	OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
-	OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
-
-	/* default write mask */
-	OUTREG(DP_WRITE_MSK, 0xffffffff);
-
-	radeon_engine_idle ();
-}
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
deleted file mode 100644
index db572df7e1ef..000000000000
--- a/drivers/video/aty/radeon_backlight.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Backlight code for ATI Radeon based graphic cards
- *
- * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org>
- * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "radeonfb.h"
-#include <linux/backlight.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
-#define MAX_RADEON_LEVEL 0xFF
-
-struct radeon_bl_privdata {
-	struct radeonfb_info *rinfo;
-	uint8_t negative;
-};
-
-static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
-		int level)
-{
-	int rlevel;
-
-	/* Get and convert the value */
-	/* No locking of bl_curve since we read a single value */
-	rlevel = pdata->rinfo->info->bl_curve[level] *
-		 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
-
-	if (rlevel < 0)
-		rlevel = 0;
-	else if (rlevel > MAX_RADEON_LEVEL)
-		rlevel = MAX_RADEON_LEVEL;
-
-	if (pdata->negative)
-		rlevel = MAX_RADEON_LEVEL - rlevel;
-
-	return rlevel;
-}
-
-static int radeon_bl_update_status(struct backlight_device *bd)
-{
-	struct radeon_bl_privdata *pdata = bl_get_data(bd);
-	struct radeonfb_info *rinfo = pdata->rinfo;
-	u32 lvds_gen_cntl, tmpPixclksCntl;
-	int level;
-
-	if (rinfo->mon1_type != MT_LCD)
-		return 0;
-
-	/* We turn off the LCD completely instead of just dimming the
-	 * backlight. This provides some greater power saving and the display
-	 * is useless without backlight anyway.
-	 */
-        if (bd->props.power != FB_BLANK_UNBLANK ||
-	    bd->props.fb_blank != FB_BLANK_UNBLANK)
-		level = 0;
-	else
-		level = bd->props.brightness;
-
-	del_timer_sync(&rinfo->lvds_timer);
-	radeon_engine_idle();
-
-	lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
-	if (level > 0) {
-		lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
-		if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
-			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
-			lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
-			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-			lvds_gen_cntl |=
-				(radeon_bl_get_level_brightness(pdata, level) <<
-				 LVDS_BL_MOD_LEVEL_SHIFT);
-			lvds_gen_cntl |= LVDS_ON;
-			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
-			rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
-			mod_timer(&rinfo->lvds_timer,
-				  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-		} else {
-			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-			lvds_gen_cntl |=
-				(radeon_bl_get_level_brightness(pdata, level) <<
-				 LVDS_BL_MOD_LEVEL_SHIFT);
-			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-		}
-		rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-		rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
-			& LVDS_STATE_MASK;
-	} else {
-		/* Asic bug, when turning off LVDS_ON, we have to make sure
-		   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
-		*/
-		tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
-		if (rinfo->is_mobility || rinfo->is_IGP)
-			OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
-		lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
-		lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
-				  LVDS_BL_MOD_LEVEL_SHIFT);
-		lvds_gen_cntl |= LVDS_DISPLAY_DIS;
-		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-		udelay(100);
-		lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
-		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-		lvds_gen_cntl &= ~(LVDS_DIGON);
-		rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
-		mod_timer(&rinfo->lvds_timer,
-			  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-		if (rinfo->is_mobility || rinfo->is_IGP)
-			OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
-	}
-	rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-	rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
-
-	return 0;
-}
-
-static int radeon_bl_get_brightness(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
-static const struct backlight_ops radeon_bl_data = {
-	.get_brightness = radeon_bl_get_brightness,
-	.update_status	= radeon_bl_update_status,
-};
-
-void radeonfb_bl_init(struct radeonfb_info *rinfo)
-{
-	struct backlight_properties props;
-	struct backlight_device *bd;
-	struct radeon_bl_privdata *pdata;
-	char name[12];
-
-	if (rinfo->mon1_type != MT_LCD)
-		return;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (!pmac_has_backlight_type("ati") &&
-	    !pmac_has_backlight_type("mnca"))
-		return;
-#endif
-
-	pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL);
-	if (!pdata) {
-		printk("radeonfb: Memory allocation failed\n");
-		goto error;
-	}
-
-	snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
-	bd = backlight_device_register(name, rinfo->info->dev, pdata,
-				       &radeon_bl_data, &props);
-	if (IS_ERR(bd)) {
-		rinfo->info->bl_dev = NULL;
-		printk("radeonfb: Backlight registration failed\n");
-		goto error;
-	}
-
-	pdata->rinfo = rinfo;
-
-	/* Pardon me for that hack... maybe some day we can figure out in what
-	 * direction backlight should work on a given panel?
-	 */
-	pdata->negative =
-		(rinfo->family != CHIP_FAMILY_RV200 &&
-		 rinfo->family != CHIP_FAMILY_RV250 &&
-		 rinfo->family != CHIP_FAMILY_RV280 &&
-		 rinfo->family != CHIP_FAMILY_RV350);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	pdata->negative = pdata->negative ||
-		of_machine_is_compatible("PowerBook4,3") ||
-		of_machine_is_compatible("PowerBook6,3") ||
-		of_machine_is_compatible("PowerBook6,5");
-#endif
-
-	rinfo->info->bl_dev = bd;
-	fb_bl_default_curve(rinfo->info, 0,
-		 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
-		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
-
-	bd->props.brightness = bd->props.max_brightness;
-	bd->props.power = FB_BLANK_UNBLANK;
-	backlight_update_status(bd);
-
-	printk("radeonfb: Backlight initialized (%s)\n", name);
-
-	return;
-
-error:
-	kfree(pdata);
-	return;
-}
-
-void radeonfb_bl_exit(struct radeonfb_info *rinfo)
-{
-	struct backlight_device *bd = rinfo->info->bl_dev;
-
-	if (bd) {
-		struct radeon_bl_privdata *pdata;
-
-		pdata = bl_get_data(bd);
-		backlight_device_unregister(bd);
-		kfree(pdata);
-		rinfo->info->bl_dev = NULL;
-
-		printk("radeonfb: Backlight unloaded\n");
-	}
-}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
deleted file mode 100644
index 26d80a4486fb..000000000000
--- a/drivers/video/aty/radeon_base.c
+++ /dev/null
@@ -1,2568 +0,0 @@
-/*
- *	drivers/video/aty/radeon_base.c
- *
- *	framebuffer driver for ATI Radeon chipset video boards
- *
- *	Copyright 2003	Ben. Herrenschmidt <benh@kernel.crashing.org>
- *	Copyright 2000	Ani Joshi <ajoshi@kernel.crashing.org>
- *
- *	i2c bits from Luca Tettamanti <kronos@kronoz.cjb.net>
- *	
- *	Special thanks to ATI DevRel team for their hardware donations.
- *
- *	...Insert GPL boilerplate here...
- *
- *	Significant portions of this driver apdated from XFree86 Radeon
- *	driver which has the following copyright notice:
- *
- *	Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
- *                     VA Linux Systems Inc., Fremont, California.
- *
- *	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 on 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 (including the
- *	next paragraph) shall be included in all copies or substantial
- *	portions of the Software.
- *
- *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * 	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *	NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
- *	THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- *	DEALINGS IN THE SOFTWARE.
- *
- *	XFree86 driver authors:
- *
- *	   Kevin E. Martin <martin@xfree86.org>
- *	   Rickard E. Faith <faith@valinux.com>
- *	   Alan Hourihane <alanh@fairlite.demon.co.uk>
- *
- */
-
-
-#define RADEON_VERSION	"0.2.0"
-
-#include "radeonfb.h"
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/device.h>
-
-#include <asm/io.h>
-#include <linux/uaccess.h>
-
-#ifdef CONFIG_PPC_OF
-
-#include <asm/pci-bridge.h>
-#include "../macmodes.h"
-
-#ifdef CONFIG_BOOTX_TEXT
-#include <asm/btext.h>
-#endif
-
-#endif /* CONFIG_PPC_OF */
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/radeon.h>
-#include <linux/radeonfb.h>
-
-#include "../edid.h" // MOVE THAT TO include/video
-#include "ati_ids.h"
-
-#define MAX_MAPPED_VRAM	(2048*2048*4)
-#define MIN_MAPPED_VRAM	(1024*768*1)
-
-#define CHIP_DEF(id, family, flags)					\
-	{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
-
-static struct pci_device_id radeonfb_pci_table[] = {
-        /* Radeon Xpress 200m */
-	CHIP_DEF(PCI_CHIP_RS480_5955,   RS480,  CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RS482_5975,	RS480,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* Mobility M6 */
-	CHIP_DEF(PCI_CHIP_RADEON_LY, 	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RADEON_LZ,	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* Radeon VE/7000 */
-	CHIP_DEF(PCI_CHIP_RV100_QY, 	RV100,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV100_QZ, 	RV100,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RN50,		RV100,	CHIP_HAS_CRTC2),
-	/* Radeon IGP320M (U1) */
-	CHIP_DEF(PCI_CHIP_RS100_4336,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* Radeon IGP320 (A3) */
-	CHIP_DEF(PCI_CHIP_RS100_4136,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP), 
-	/* IGP330M/340M/350M (U2) */
-	CHIP_DEF(PCI_CHIP_RS200_4337,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* IGP330/340/350 (A4) */
-	CHIP_DEF(PCI_CHIP_RS200_4137,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
-	/* Mobility 7000 IGP */
-	CHIP_DEF(PCI_CHIP_RS250_4437,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* 7000 IGP (A4+) */
-	CHIP_DEF(PCI_CHIP_RS250_4237,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
-	/* 8500 AIW */
-	CHIP_DEF(PCI_CHIP_R200_BB,	R200,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R200_BC,	R200,	CHIP_HAS_CRTC2),
-	/* 8700/8800 */
-	CHIP_DEF(PCI_CHIP_R200_QH,	R200,	CHIP_HAS_CRTC2),
-	/* 8500 */
-	CHIP_DEF(PCI_CHIP_R200_QL,	R200,	CHIP_HAS_CRTC2),
-	/* 9100 */
-	CHIP_DEF(PCI_CHIP_R200_QM,	R200,	CHIP_HAS_CRTC2),
-	/* Mobility M7 */
-	CHIP_DEF(PCI_CHIP_RADEON_LW,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RADEON_LX,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* 7500 */
-	CHIP_DEF(PCI_CHIP_RV200_QW,	RV200,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV200_QX,	RV200,	CHIP_HAS_CRTC2),
-	/* Mobility M9 */
-	CHIP_DEF(PCI_CHIP_RV250_Ld,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV250_Le,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV250_Lf,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV250_Lg,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* 9000/Pro */
-	CHIP_DEF(PCI_CHIP_RV250_If,	RV250,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV250_Ig,	RV250,	CHIP_HAS_CRTC2),
-
-	CHIP_DEF(PCI_CHIP_RC410_5A62,   RC410,  CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* Mobility 9100 IGP (U3) */
-	CHIP_DEF(PCI_CHIP_RS300_5835,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RS350_7835,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* 9100 IGP (A5) */
-	CHIP_DEF(PCI_CHIP_RS300_5834,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
-	CHIP_DEF(PCI_CHIP_RS350_7834,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
-	/* Mobility 9200 (M9+) */
-	CHIP_DEF(PCI_CHIP_RV280_5C61,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV280_5C63,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* 9200 */
-	CHIP_DEF(PCI_CHIP_RV280_5960,	RV280,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV280_5961,	RV280,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV280_5962,	RV280,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV280_5964,	RV280,	CHIP_HAS_CRTC2),
-	/* 9500 */
-	CHIP_DEF(PCI_CHIP_R300_AD,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_AE,	R300,	CHIP_HAS_CRTC2),
-	/* 9600TX / FireGL Z1 */
-	CHIP_DEF(PCI_CHIP_R300_AF,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_AG,	R300,	CHIP_HAS_CRTC2),
-	/* 9700/9500/Pro/FireGL X1 */
-	CHIP_DEF(PCI_CHIP_R300_ND,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_NE,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_NF,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_NG,	R300,	CHIP_HAS_CRTC2),
-	/* Mobility M10/M11 */
-	CHIP_DEF(PCI_CHIP_RV350_NP,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NQ,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NR,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NS,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NT,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NV,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* 9600/FireGL T2 */
-	CHIP_DEF(PCI_CHIP_RV350_AP,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AQ,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV360_AR,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AS,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AT,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AV,	RV350,	CHIP_HAS_CRTC2),
-	/* 9800/Pro/FileGL X2 */
-	CHIP_DEF(PCI_CHIP_R350_AH,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_AI,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_AJ,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_AK,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_NH,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_NI,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R360_NJ,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_NK,	R350,	CHIP_HAS_CRTC2),
-	/* Newer stuff */
-	CHIP_DEF(PCI_CHIP_RV380_3E50,	RV380,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV380_3E54,	RV380,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV380_3150,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV380_3154,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV370_5B60,	RV380,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV370_5B62,	RV380,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV370_5B63,	RV380,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV370_5B64,	RV380,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV370_5B65,	RV380,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV370_5460,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV370_5464,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_R420_JH,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R420_JI,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R420_JJ,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R420_JK,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R420_JL,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R420_JM,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R420_JN,	R420,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_R420_JP,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_UH,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_UI,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_UJ,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_UK,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_UQ,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_UR,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_UT,	R420,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R423_5D57,	R420,	CHIP_HAS_CRTC2),
-	/* Original Radeon/7200 */
-	CHIP_DEF(PCI_CHIP_RADEON_QD,	RADEON,	0),
-	CHIP_DEF(PCI_CHIP_RADEON_QE,	RADEON,	0),
-	CHIP_DEF(PCI_CHIP_RADEON_QF,	RADEON,	0),
-	CHIP_DEF(PCI_CHIP_RADEON_QG,	RADEON,	0),
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
-
-
-typedef struct {
-	u16 reg;
-	u32 val;
-} reg_val;
-
-
-/* these common regs are cleared before mode setting so they do not
- * interfere with anything
- */
-static reg_val common_regs[] = {
-	{ OVR_CLR, 0 },	
-	{ OVR_WID_LEFT_RIGHT, 0 },
-	{ OVR_WID_TOP_BOTTOM, 0 },
-	{ OV0_SCALE_CNTL, 0 },
-	{ SUBPIC_CNTL, 0 },
-	{ VIPH_CONTROL, 0 },
-	{ I2C_CNTL_1, 0 },
-	{ GEN_INT_CNTL, 0 },
-	{ CAP0_TRIG_CNTL, 0 },
-	{ CAP1_TRIG_CNTL, 0 },
-};
-
-/*
- * globals
- */
-        
-static char *mode_option;
-static char *monitor_layout;
-static bool noaccel = 0;
-static int default_dynclk = -2;
-static bool nomodeset = 0;
-static bool ignore_edid = 0;
-static bool mirror = 0;
-static int panel_yres = 0;
-static bool force_dfp = 0;
-static bool force_measure_pll = 0;
-#ifdef CONFIG_MTRR
-static bool nomtrr = 0;
-#endif
-static bool force_sleep;
-static bool ignore_devlist;
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight = 1;
-#else
-static int backlight = 0;
-#endif
-
-/*
- * prototypes
- */
-
-static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
-{
-	if (!rinfo->bios_seg)
-		return;
-	pci_unmap_rom(dev, rinfo->bios_seg);
-}
-
-static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
-{
-	void __iomem *rom;
-	u16 dptr;
-	u8 rom_type;
-	size_t rom_size;
-
-	/* If this is a primary card, there is a shadow copy of the
-	 * ROM somewhere in the first meg. We will just ignore the copy
-	 * and use the ROM directly.
-	 */
-    
-    	/* Fix from ATI for problem with Radeon hardware not leaving ROM enabled */
-    	unsigned int temp;
-	temp = INREG(MPP_TB_CONFIG);
-	temp &= 0x00ffffffu;
-	temp |= 0x04 << 24;
-	OUTREG(MPP_TB_CONFIG, temp);
-	temp = INREG(MPP_TB_CONFIG);
-                                                                                                          
-	rom = pci_map_rom(dev, &rom_size);
-	if (!rom) {
-		printk(KERN_ERR "radeonfb (%s): ROM failed to map\n",
-		       pci_name(rinfo->pdev));
-		return -ENOMEM;
-	}
-	
-	rinfo->bios_seg = rom;
-
-	/* Very simple test to make sure it appeared */
-	if (BIOS_IN16(0) != 0xaa55) {
-		printk(KERN_DEBUG "radeonfb (%s): Invalid ROM signature %x "
-			"should be 0xaa55\n",
-			pci_name(rinfo->pdev), BIOS_IN16(0));
-		goto failed;
-	}
-	/* Look for the PCI data to check the ROM type */
-	dptr = BIOS_IN16(0x18);
-
-	/* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM
-	 * for now, until I've verified this works everywhere. The goal here is more
-	 * to phase out Open Firmware images.
-	 *
-	 * Currently, we only look at the first PCI data, we could iteratre and deal with
-	 * them all, and we should use fb_bios_start relative to start of image and not
-	 * relative start of ROM, but so far, I never found a dual-image ATI card
-	 *
-	 * typedef struct {
-	 * 	u32	signature;	+ 0x00
-	 * 	u16	vendor;		+ 0x04
-	 * 	u16	device;		+ 0x06
-	 * 	u16	reserved_1;	+ 0x08
-	 * 	u16	dlen;		+ 0x0a
-	 * 	u8	drevision;	+ 0x0c
-	 * 	u8	class_hi;	+ 0x0d
-	 * 	u16	class_lo;	+ 0x0e
-	 * 	u16	ilen;		+ 0x10
-	 * 	u16	irevision;	+ 0x12
-	 * 	u8	type;		+ 0x14
-	 * 	u8	indicator;	+ 0x15
-	 * 	u16	reserved_2;	+ 0x16
-	 * } pci_data_t;
-	 */
-	if (BIOS_IN32(dptr) !=  (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
-		printk(KERN_WARNING "radeonfb (%s): PCI DATA signature in ROM"
-		       "incorrect: %08x\n", pci_name(rinfo->pdev), BIOS_IN32(dptr));
-		goto anyway;
-	}
-	rom_type = BIOS_IN8(dptr + 0x14);
-	switch(rom_type) {
-	case 0:
-		printk(KERN_INFO "radeonfb: Found Intel x86 BIOS ROM Image\n");
-		break;
-	case 1:
-		printk(KERN_INFO "radeonfb: Found Open Firmware ROM Image\n");
-		goto failed;
-	case 2:
-		printk(KERN_INFO "radeonfb: Found HP PA-RISC ROM Image\n");
-		goto failed;
-	default:
-		printk(KERN_INFO "radeonfb: Found unknown type %d ROM Image\n", rom_type);
-		goto failed;
-	}
- anyway:
-	/* Locate the flat panel infos, do some sanity checking !!! */
-	rinfo->fp_bios_start = BIOS_IN16(0x48);
-	return 0;
-
- failed:
-	rinfo->bios_seg = NULL;
-	radeon_unmap_ROM(rinfo, dev);
-	return -ENXIO;
-}
-
-#ifdef CONFIG_X86
-static int  radeon_find_mem_vbios(struct radeonfb_info *rinfo)
-{
-	/* I simplified this code as we used to miss the signatures in
-	 * a lot of case. It's now closer to XFree, we just don't check
-	 * for signatures at all... Something better will have to be done
-	 * if we end up having conflicts
-	 */
-        u32  segstart;
-	void __iomem *rom_base = NULL;
-                                                
-        for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
-                rom_base = ioremap(segstart, 0x10000);
-		if (rom_base == NULL)
-			return -ENOMEM;
-                if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
-	                break;
-                iounmap(rom_base);
-		rom_base = NULL;
-        }
-	if (rom_base == NULL)
-		return -ENXIO;
-
-	/* Locate the flat panel infos, do some sanity checking !!! */
-	rinfo->bios_seg = rom_base;
-	rinfo->fp_bios_start = BIOS_IN16(0x48);
-
-	return 0;
-}
-#endif
-
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-/*
- * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
- * tree. Hopefully, ATI OF driver is kind enough to fill these
- */
-static int radeon_read_xtal_OF(struct radeonfb_info *rinfo)
-{
-	struct device_node *dp = rinfo->of_node;
-	const u32 *val;
-
-	if (dp == NULL)
-		return -ENODEV;
-	val = of_get_property(dp, "ATY,RefCLK", NULL);
-	if (!val || !*val) {
-		printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
-		return -EINVAL;
-	}
-
-	rinfo->pll.ref_clk = (*val) / 10;
-
-	val = of_get_property(dp, "ATY,SCLK", NULL);
-	if (val && *val)
-		rinfo->pll.sclk = (*val) / 10;
-
-	val = of_get_property(dp, "ATY,MCLK", NULL);
-	if (val && *val)
-		rinfo->pll.mclk = (*val) / 10;
-
-       	return 0;
-}
-#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
-
-/*
- * Read PLL infos from chip registers
- */
-static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
-{
-	unsigned char ppll_div_sel;
-	unsigned Ns, Nm, M;
-	unsigned sclk, mclk, tmp, ref_div;
-	int hTotal, vTotal, num, denom, m, n;
-	unsigned long long hz, vclk;
-	long xtal;
-	struct timeval start_tv, stop_tv;
-	long total_secs, total_usecs;
-	int i;
-
-	/* Ugh, we cut interrupts, bad bad bad, but we want some precision
-	 * here, so... --BenH
-	 */
-
-	/* Flush PCI buffers ? */
-	tmp = INREG16(DEVICE_ID);
-
-	local_irq_disable();
-
-	for(i=0; i<1000000; i++)
-		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
-			break;
-
-	do_gettimeofday(&start_tv);
-
-	for(i=0; i<1000000; i++)
-		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0)
-			break;
-
-	for(i=0; i<1000000; i++)
-		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
-			break;
-	
-	do_gettimeofday(&stop_tv);
-	
-	local_irq_enable();
-
-	total_secs = stop_tv.tv_sec - start_tv.tv_sec;
-	if (total_secs > 10)
-		return -1;
-	total_usecs = stop_tv.tv_usec - start_tv.tv_usec;
-	total_usecs += total_secs * 1000000;
-	if (total_usecs < 0)
-		total_usecs = -total_usecs;
-	hz = 1000000/total_usecs;
- 
-	hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8;
-	vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1);
-	vclk = (long long)hTotal * (long long)vTotal * hz;
-
-	switch((INPLL(PPLL_REF_DIV) & 0x30000) >> 16) {
-	case 0:
-	default:
-		num = 1;
-		denom = 1;
-		break;
-	case 1:
-		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 16) & 0xff);
-		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);
-		num = 2*n;
-		denom = 2*m;
-		break;
-	case 2:
-		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 8) & 0xff);
-		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);
-		num = 2*n;
-		denom = 2*m;
-        break;
-	}
-
-	ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
-	radeon_pll_errata_after_index(rinfo);
-
-	n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
-	m = (INPLL(PPLL_REF_DIV) & 0x3ff);
-
-	num *= n;
-	denom *= m;
-
-	switch ((INPLL(PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) {
-	case 1:
-		denom *= 2;
-		break;
-	case 2:
-		denom *= 4;
-		break;
-	case 3:
-		denom *= 8;
-		break;
-	case 4:
-		denom *= 3;
-		break;
-	case 6:
-		denom *= 6;   
-		break;
-	case 7:
-		denom *= 12;
-		break;
-	}
-
-	vclk *= denom;
-	do_div(vclk, 1000 * num);
-	xtal = vclk;
-
-	if ((xtal > 26900) && (xtal < 27100))
-		xtal = 2700;
-	else if ((xtal > 14200) && (xtal < 14400))
-		xtal = 1432;
-	else if ((xtal > 29400) && (xtal < 29600))
-		xtal = 2950;
-	else {
-		printk(KERN_WARNING "xtal calculation failed: %ld\n", xtal);
-		return -1;
-	}
-
-	tmp = INPLL(M_SPLL_REF_FB_DIV);
-	ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
-
-	Ns = (tmp & 0xff0000) >> 16;
-	Nm = (tmp & 0xff00) >> 8;
-	M = (tmp & 0xff);
-	sclk = round_div((2 * Ns * xtal), (2 * M));
-	mclk = round_div((2 * Nm * xtal), (2 * M));
-
-	/* we're done, hopefully these are sane values */
-	rinfo->pll.ref_clk = xtal;
-	rinfo->pll.ref_div = ref_div;
-	rinfo->pll.sclk = sclk;
-	rinfo->pll.mclk = mclk;
-
-	return 0;
-}
-
-/*
- * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...)
- */
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
-{
-	/*
-	 * In the case nothing works, these are defaults; they are mostly
-	 * incomplete, however.  It does provide ppll_max and _min values
-	 * even for most other methods, however.
-	 */
-	switch (rinfo->chipset) {
-	case PCI_DEVICE_ID_ATI_RADEON_QW:
-	case PCI_DEVICE_ID_ATI_RADEON_QX:
-		rinfo->pll.ppll_max = 35000;
-		rinfo->pll.ppll_min = 12000;
-		rinfo->pll.mclk = 23000;
-		rinfo->pll.sclk = 23000;
-		rinfo->pll.ref_clk = 2700;
-		break;
-	case PCI_DEVICE_ID_ATI_RADEON_QL:
-	case PCI_DEVICE_ID_ATI_RADEON_QN:
-	case PCI_DEVICE_ID_ATI_RADEON_QO:
-	case PCI_DEVICE_ID_ATI_RADEON_Ql:
-	case PCI_DEVICE_ID_ATI_RADEON_BB:
-		rinfo->pll.ppll_max = 35000;
-		rinfo->pll.ppll_min = 12000;
-		rinfo->pll.mclk = 27500;
-		rinfo->pll.sclk = 27500;
-		rinfo->pll.ref_clk = 2700;
-		break;
-	case PCI_DEVICE_ID_ATI_RADEON_Id:
-	case PCI_DEVICE_ID_ATI_RADEON_Ie:
-	case PCI_DEVICE_ID_ATI_RADEON_If:
-	case PCI_DEVICE_ID_ATI_RADEON_Ig:
-		rinfo->pll.ppll_max = 35000;
-		rinfo->pll.ppll_min = 12000;
-		rinfo->pll.mclk = 25000;
-		rinfo->pll.sclk = 25000;
-		rinfo->pll.ref_clk = 2700;
-		break;
-	case PCI_DEVICE_ID_ATI_RADEON_ND:
-	case PCI_DEVICE_ID_ATI_RADEON_NE:
-	case PCI_DEVICE_ID_ATI_RADEON_NF:
-	case PCI_DEVICE_ID_ATI_RADEON_NG:
-		rinfo->pll.ppll_max = 40000;
-		rinfo->pll.ppll_min = 20000;
-		rinfo->pll.mclk = 27000;
-		rinfo->pll.sclk = 27000;
-		rinfo->pll.ref_clk = 2700;
-		break;
-	case PCI_DEVICE_ID_ATI_RADEON_QD:
-	case PCI_DEVICE_ID_ATI_RADEON_QE:
-	case PCI_DEVICE_ID_ATI_RADEON_QF:
-	case PCI_DEVICE_ID_ATI_RADEON_QG:
-	default:
-		rinfo->pll.ppll_max = 35000;
-		rinfo->pll.ppll_min = 12000;
-		rinfo->pll.mclk = 16600;
-		rinfo->pll.sclk = 16600;
-		rinfo->pll.ref_clk = 2700;
-		break;
-	}
-	rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
-
-
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-	/*
-	 * Retrieve PLL infos from Open Firmware first
-	 */
-       	if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
-       		printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n");
-		goto found;
-	}
-#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
-
-	/*
-	 * Check out if we have an X86 which gave us some PLL informations
-	 * and if yes, retrieve them
-	 */
-	if (!force_measure_pll && rinfo->bios_seg) {
-		u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
-
-		rinfo->pll.sclk		= BIOS_IN16(pll_info_block + 0x08);
-		rinfo->pll.mclk		= BIOS_IN16(pll_info_block + 0x0a);
-		rinfo->pll.ref_clk	= BIOS_IN16(pll_info_block + 0x0e);
-		rinfo->pll.ref_div	= BIOS_IN16(pll_info_block + 0x10);
-		rinfo->pll.ppll_min	= BIOS_IN32(pll_info_block + 0x12);
-		rinfo->pll.ppll_max	= BIOS_IN32(pll_info_block + 0x16);
-
-		printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n");
-		goto found;
-	}
-
-	/*
-	 * We didn't get PLL parameters from either OF or BIOS, we try to
-	 * probe them
-	 */
-	if (radeon_probe_pll_params(rinfo) == 0) {
-		printk(KERN_INFO "radeonfb: Retrieved PLL infos from registers\n");
-		goto found;
-	}
-
-	/*
-	 * Fall back to already-set defaults...
-	 */
-       	printk(KERN_INFO "radeonfb: Used default PLL infos\n");
-
-found:
-	/*
-	 * Some methods fail to retrieve SCLK and MCLK values, we apply default
-	 * settings in this case (200Mhz). If that really happens often, we
-	 * could fetch from registers instead...
-	 */
-	if (rinfo->pll.mclk == 0)
-		rinfo->pll.mclk = 20000;
-	if (rinfo->pll.sclk == 0)
-		rinfo->pll.sclk = 20000;
-
-	printk("radeonfb: Reference=%d.%02d MHz (RefDiv=%d) Memory=%d.%02d Mhz, System=%d.%02d MHz\n",
-	       rinfo->pll.ref_clk / 100, rinfo->pll.ref_clk % 100,
-	       rinfo->pll.ref_div,
-	       rinfo->pll.mclk / 100, rinfo->pll.mclk % 100,
-	       rinfo->pll.sclk / 100, rinfo->pll.sclk % 100);
-	printk("radeonfb: PLL min %d max %d\n", rinfo->pll.ppll_min, rinfo->pll.ppll_max);
-}
-
-static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct radeonfb_info *rinfo = info->par;
-        struct fb_var_screeninfo v;
-        int nom, den;
-	unsigned int pitch;
-
-	if (radeon_match_mode(rinfo, &v, var))
-		return -EINVAL;
-
-        switch (v.bits_per_pixel) {
-		case 0 ... 8:
-			v.bits_per_pixel = 8;
-			break;
-		case 9 ... 16:
-			v.bits_per_pixel = 16;
-			break;
-		case 17 ... 24:
-#if 0 /* Doesn't seem to work */
-			v.bits_per_pixel = 24;
-			break;
-#endif			
-			return -EINVAL;
-		case 25 ... 32:
-			v.bits_per_pixel = 32;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	switch (var_to_depth(&v)) {
-                case 8:
-                        nom = den = 1;
-                        v.red.offset = v.green.offset = v.blue.offset = 0;
-                        v.red.length = v.green.length = v.blue.length = 8;
-                        v.transp.offset = v.transp.length = 0;
-                        break;
-		case 15:
-			nom = 2;
-			den = 1;
-			v.red.offset = 10;
-			v.green.offset = 5;
-			v.blue.offset = 0;
-			v.red.length = v.green.length = v.blue.length = 5;
-			v.transp.offset = v.transp.length = 0;
-			break;
-                case 16:
-                        nom = 2;
-                        den = 1;
-                        v.red.offset = 11;
-                        v.green.offset = 5;
-                        v.blue.offset = 0;
-                        v.red.length = 5;
-                        v.green.length = 6;
-                        v.blue.length = 5;
-                        v.transp.offset = v.transp.length = 0;
-                        break;                          
-                case 24:
-                        nom = 4;
-                        den = 1;
-                        v.red.offset = 16;
-                        v.green.offset = 8;
-                        v.blue.offset = 0;
-                        v.red.length = v.blue.length = v.green.length = 8;
-                        v.transp.offset = v.transp.length = 0;
-                        break;
-                case 32:
-                        nom = 4;
-                        den = 1;
-                        v.red.offset = 16;
-                        v.green.offset = 8;
-                        v.blue.offset = 0;
-                        v.red.length = v.blue.length = v.green.length = 8;
-                        v.transp.offset = 24;
-                        v.transp.length = 8;
-                        break;
-                default:
-                        printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",
-                                var->xres, var->yres, var->bits_per_pixel);
-                        return -EINVAL;
-        }
-
-	if (v.yres_virtual < v.yres)
-		v.yres_virtual = v.yres;
-	if (v.xres_virtual < v.xres)
-		v.xres_virtual = v.xres;
-                
-
-	/* XXX I'm adjusting xres_virtual to the pitch, that may help XFree
-	 * with some panels, though I don't quite like this solution
-	 */
-  	if (rinfo->info->flags & FBINFO_HWACCEL_DISABLED) {
-		v.xres_virtual = v.xres_virtual & ~7ul;
-	} else {
-		pitch = ((v.xres_virtual * ((v.bits_per_pixel + 1) / 8) + 0x3f)
- 				& ~(0x3f)) >> 6;
-		v.xres_virtual = (pitch << 6) / ((v.bits_per_pixel + 1) / 8);
-	}
-
-	if (((v.xres_virtual * v.yres_virtual * nom) / den) > rinfo->mapped_vram)
-		return -EINVAL;
-
-	if (v.xres_virtual < v.xres)
-		v.xres = v.xres_virtual;
-
-        if (v.xoffset > v.xres_virtual - v.xres)
-                v.xoffset = v.xres_virtual - v.xres - 1;
-                        
-        if (v.yoffset > v.yres_virtual - v.yres)
-                v.yoffset = v.yres_virtual - v.yres - 1;
-         
-        v.red.msb_right = v.green.msb_right = v.blue.msb_right =
-                          v.transp.offset = v.transp.length =
-                          v.transp.msb_right = 0;
-	
-        memcpy(var, &v, sizeof(v));
-
-        return 0;
-}
-
-
-static int radeonfb_pan_display (struct fb_var_screeninfo *var,
-                                 struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = info->par;
-
-	if ((var->xoffset + info->var.xres > info->var.xres_virtual)
-	    || (var->yoffset + info->var.yres > info->var.yres_virtual))
-		return -EINVAL;
-                
-        if (rinfo->asleep)
-        	return 0;
-
-	radeon_fifo_wait(2);
-	OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
-			     var->xoffset * info->var.bits_per_pixel / 8) & ~7);
-        return 0;
-}
-
-
-static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
-                           unsigned long arg)
-{
-        struct radeonfb_info *rinfo = info->par;
-	unsigned int tmp;
-	u32 value = 0;
-	int rc;
-
-	switch (cmd) {
-		/*
-		 * TODO:  set mirror accordingly for non-Mobility chipsets with 2 CRTC's
-		 *        and do something better using 2nd CRTC instead of just hackish
-		 *        routing to second output
-		 */
-		case FBIO_RADEON_SET_MIRROR:
-			if (!rinfo->is_mobility)
-				return -EINVAL;
-
-			rc = get_user(value, (__u32 __user *)arg);
-
-			if (rc)
-				return rc;
-
-			radeon_fifo_wait(2);
-			if (value & 0x01) {
-				tmp = INREG(LVDS_GEN_CNTL);
-
-				tmp |= (LVDS_ON | LVDS_BLON);
-			} else {
-				tmp = INREG(LVDS_GEN_CNTL);
-
-				tmp &= ~(LVDS_ON | LVDS_BLON);
-			}
-
-			OUTREG(LVDS_GEN_CNTL, tmp);
-
-			if (value & 0x02) {
-				tmp = INREG(CRTC_EXT_CNTL);
-				tmp |= CRTC_CRT_ON;
-
-				mirror = 1;
-			} else {
-				tmp = INREG(CRTC_EXT_CNTL);
-				tmp &= ~CRTC_CRT_ON;
-
-				mirror = 0;
-			}
-
-			OUTREG(CRTC_EXT_CNTL, tmp);
-
-			return 0;
-		case FBIO_RADEON_GET_MIRROR:
-			if (!rinfo->is_mobility)
-				return -EINVAL;
-
-			tmp = INREG(LVDS_GEN_CNTL);
-			if ((LVDS_ON | LVDS_BLON) & tmp)
-				value |= 0x01;
-
-			tmp = INREG(CRTC_EXT_CNTL);
-			if (CRTC_CRT_ON & tmp)
-				value |= 0x02;
-
-			return put_user(value, (__u32 __user *)arg);
-		default:
-			return -EINVAL;
-	}
-
-	return -EINVAL;
-}
-
-
-int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
-{
-        u32 val;
-	u32 tmp_pix_clks;
-	int unblank = 0;
-
-	if (rinfo->lock_blank)
-		return 0;
-
-	radeon_engine_idle();
-
-	val = INREG(CRTC_EXT_CNTL);
-        val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
-                 CRTC_VSYNC_DIS);
-        switch (blank) {
-	case FB_BLANK_VSYNC_SUSPEND:
-		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
-		break;
-	case FB_BLANK_POWERDOWN:
-		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
-			CRTC_HSYNC_DIS);
-		break;
-	case FB_BLANK_NORMAL:
-		val |= CRTC_DISPLAY_DIS;
-		break;
-	case FB_BLANK_UNBLANK:
-	default:
-		unblank = 1;
-        }
-	OUTREG(CRTC_EXT_CNTL, val);
-
-
-	switch (rinfo->mon1_type) {
-	case MT_DFP:
-		if (unblank)
-			OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN),
-				~(FP_FPON | FP_TMDS_EN));
-		else {
-			if (mode_switch || blank == FB_BLANK_NORMAL)
-				break;
-			OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));
-		}
-		break;
-	case MT_LCD:
-		del_timer_sync(&rinfo->lvds_timer);
-		val = INREG(LVDS_GEN_CNTL);
-		if (unblank) {
-			u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON
-				| LVDS_EN | (rinfo->init_state.lvds_gen_cntl
-					     & (LVDS_DIGON | LVDS_BL_MOD_EN));
-			if ((val ^ target_val) == LVDS_DISPLAY_DIS)
-				OUTREG(LVDS_GEN_CNTL, target_val);
-			else if ((val ^ target_val) != 0) {
-				OUTREG(LVDS_GEN_CNTL, target_val
-				       & ~(LVDS_ON | LVDS_BL_MOD_EN));
-				rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-				rinfo->init_state.lvds_gen_cntl |=
-					target_val & LVDS_STATE_MASK;
-				if (mode_switch) {
-					radeon_msleep(rinfo->panel_info.pwr_delay);
-					OUTREG(LVDS_GEN_CNTL, target_val);
-				}
-				else {
-					rinfo->pending_lvds_gen_cntl = target_val;
-					mod_timer(&rinfo->lvds_timer,
-					   jiffies +
-					   msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-				}
-			}
-		} else {
-			val |= LVDS_DISPLAY_DIS;
-			OUTREG(LVDS_GEN_CNTL, val);
-
-			/* We don't do a full switch-off on a simple mode switch */
-			if (mode_switch || blank == FB_BLANK_NORMAL)
-				break;
-
-			/* Asic bug, when turning off LVDS_ON, we have to make sure
-			 * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
-			 */
-			tmp_pix_clks = INPLL(PIXCLKS_CNTL);
-			if (rinfo->is_mobility || rinfo->is_IGP)
-				OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
-			val &= ~(LVDS_BL_MOD_EN);
-			OUTREG(LVDS_GEN_CNTL, val);
-			udelay(100);
-			val &= ~(LVDS_ON | LVDS_EN);
-			OUTREG(LVDS_GEN_CNTL, val);
-			val &= ~LVDS_DIGON;
-			rinfo->pending_lvds_gen_cntl = val;
-			mod_timer(&rinfo->lvds_timer,
-				  jiffies +
-				  msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-			rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-			rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
-			if (rinfo->is_mobility || rinfo->is_IGP)
-				OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
-		}
-		break;
-	case MT_CRT:
-		// todo: powerdown DAC
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int radeonfb_blank (int blank, struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = info->par;
-
-	if (rinfo->asleep)
-		return 0;
-		
-	return radeon_screen_blank(rinfo, blank, 0);
-}
-
-static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
-                             unsigned blue, unsigned transp,
-			     struct radeonfb_info *rinfo)
-{
-	u32 pindex;
-	unsigned int i;
-
-
-	if (regno > 255)
-		return -EINVAL;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	rinfo->palette[regno].red = red;
-	rinfo->palette[regno].green = green;
-	rinfo->palette[regno].blue = blue;
-
-        /* default */
-        pindex = regno;
-
-        if (!rinfo->asleep) {
-		radeon_fifo_wait(9);
-
-		if (rinfo->bpp == 16) {
-			pindex = regno * 8;
-
-			if (rinfo->depth == 16 && regno > 63)
-				return -EINVAL;
-			if (rinfo->depth == 15 && regno > 31)
-				return -EINVAL;
-
-			/* For 565, the green component is mixed one order
-			 * below
-			 */
-			if (rinfo->depth == 16) {
-		                OUTREG(PALETTE_INDEX, pindex>>1);
-	       	         	OUTREG(PALETTE_DATA,
-				       (rinfo->palette[regno>>1].red << 16) |
-	                        	(green << 8) |
-				       (rinfo->palette[regno>>1].blue));
-	                	green = rinfo->palette[regno<<1].green;
-	        	}
-		}
-
-		if (rinfo->depth != 16 || regno < 32) {
-			OUTREG(PALETTE_INDEX, pindex);
-			OUTREG(PALETTE_DATA, (red << 16) |
-			       (green << 8) | blue);
-		}
-	}
- 	if (regno < 16) {
-		u32 *pal = rinfo->info->pseudo_palette;
-        	switch (rinfo->depth) {
-		case 15:
-			pal[regno] = (regno << 10) | (regno << 5) | regno;
-			break;
-		case 16:
-			pal[regno] = (regno << 11) | (regno << 5) | regno;
-			break;
-		case 24:
-			pal[regno] = (regno << 16) | (regno << 8) | regno;
-			break;
-		case 32:
-			i = (regno << 8) | regno;
-			pal[regno] = (i << 16) | i;
-			break;
-		}
-        }
-	return 0;
-}
-
-static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
-			       unsigned blue, unsigned transp,
-			       struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = info->par;
-	u32 dac_cntl2, vclk_cntl = 0;
-	int rc;
-
-        if (!rinfo->asleep) {
-		if (rinfo->is_mobility) {
-			vclk_cntl = INPLL(VCLK_ECP_CNTL);
-			OUTPLL(VCLK_ECP_CNTL,
-			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
-		}
-
-		/* Make sure we are on first palette */
-		if (rinfo->has_CRTC2) {
-			dac_cntl2 = INREG(DAC_CNTL2);
-			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
-			OUTREG(DAC_CNTL2, dac_cntl2);
-		}
-	}
-
-	rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo);
-
-	if (!rinfo->asleep && rinfo->is_mobility)
-		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
-
-	return rc;
-}
-
-static int radeonfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
-        struct radeonfb_info *rinfo = info->par;
-	u16 *red, *green, *blue, *transp;
-	u32 dac_cntl2, vclk_cntl = 0;
-	int i, start, rc = 0;
-
-        if (!rinfo->asleep) {
-		if (rinfo->is_mobility) {
-			vclk_cntl = INPLL(VCLK_ECP_CNTL);
-			OUTPLL(VCLK_ECP_CNTL,
-			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
-		}
-
-		/* Make sure we are on first palette */
-		if (rinfo->has_CRTC2) {
-			dac_cntl2 = INREG(DAC_CNTL2);
-			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
-			OUTREG(DAC_CNTL2, dac_cntl2);
-		}
-	}
-
-	red = cmap->red;
-	green = cmap->green;
-	blue = cmap->blue;
-	transp = cmap->transp;
-	start = cmap->start;
-
-	for (i = 0; i < cmap->len; i++) {
-		u_int hred, hgreen, hblue, htransp = 0xffff;
-
-		hred = *red++;
-		hgreen = *green++;
-		hblue = *blue++;
-		if (transp)
-			htransp = *transp++;
-		rc = radeon_setcolreg (start++, hred, hgreen, hblue, htransp,
-				       rinfo);
-		if (rc)
-			break;
-	}
-
-	if (!rinfo->asleep && rinfo->is_mobility)
-		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
-
-	return rc;
-}
-
-static void radeon_save_state (struct radeonfb_info *rinfo,
-			       struct radeon_regs *save)
-{
-	/* CRTC regs */
-	save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
-	save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
-	save->crtc_more_cntl = INREG(CRTC_MORE_CNTL);
-	save->dac_cntl = INREG(DAC_CNTL);
-        save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP);
-        save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID);
-        save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP);
-        save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID);
-	save->crtc_pitch = INREG(CRTC_PITCH);
-	save->surface_cntl = INREG(SURFACE_CNTL);
-
-	/* FP regs */
-	save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP);
-	save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP);
-	save->fp_gen_cntl = INREG(FP_GEN_CNTL);
-	save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID);
-	save->fp_horz_stretch = INREG(FP_HORZ_STRETCH);
-	save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID);
-	save->fp_vert_stretch = INREG(FP_VERT_STRETCH);
-	save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
-	save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);
-	save->tmds_crc = INREG(TMDS_CRC);
-	save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
-	save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
-
-	/* PLL regs */
-	save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
-	radeon_pll_errata_after_index(rinfo);
-	save->ppll_div_3 = INPLL(PPLL_DIV_3);
-	save->ppll_ref_div = INPLL(PPLL_REF_DIV);
-}
-
-
-static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
-{
-	int i;
-
-	radeon_fifo_wait(20);
-
-	/* Workaround from XFree */
-	if (rinfo->is_mobility) {
-	        /* A temporal workaround for the occasional blanking on certain laptop
-		 * panels. This appears to related to the PLL divider registers
-		 * (fail to lock?). It occurs even when all dividers are the same
-		 * with their old settings. In this case we really don't need to
-		 * fiddle with PLL registers. By doing this we can avoid the blanking
-		 * problem with some panels.
-	         */
-		if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
-		    (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
-					  (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
-			/* We still have to force a switch to selected PPLL div thanks to
-			 * an XFree86 driver bug which will switch it away in some cases
-			 * even when using UseFDev */
-			OUTREGP(CLOCK_CNTL_INDEX,
-				mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
-				~PPLL_DIV_SEL_MASK);
-			radeon_pll_errata_after_index(rinfo);
-			radeon_pll_errata_after_data(rinfo);
-            		return;
-		}
-	}
-
-	/* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
-	OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
-
-	/* Reset PPLL & enable atomic update */
-	OUTPLLP(PPLL_CNTL,
-		PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
-		~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
-
-	/* Switch to selected PPLL divider */
-	OUTREGP(CLOCK_CNTL_INDEX,
-		mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
-		~PPLL_DIV_SEL_MASK);
-	radeon_pll_errata_after_index(rinfo);
-	radeon_pll_errata_after_data(rinfo);
-
-	/* Set PPLL ref. div */
-	if (IS_R300_VARIANT(rinfo) ||
-	    rinfo->family == CHIP_FAMILY_RS300 ||
-	    rinfo->family == CHIP_FAMILY_RS400 ||
-	    rinfo->family == CHIP_FAMILY_RS480) {
-		if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
-			/* When restoring console mode, use saved PPLL_REF_DIV
-			 * setting.
-			 */
-			OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
-		} else {
-			/* R300 uses ref_div_acc field as real ref divider */
-			OUTPLLP(PPLL_REF_DIV,
-				(mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), 
-				~R300_PPLL_REF_DIV_ACC_MASK);
-		}
-	} else
-		OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
-
-	/* Set PPLL divider 3 & post divider*/
-	OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
-	OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
-
-	/* Write update */
-	while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
-		;
-	OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
-
-	/* Wait read update complete */
-	/* FIXME: Certain revisions of R300 can't recover here.  Not sure of
-	   the cause yet, but this workaround will mask the problem for now.
-	   Other chips usually will pass at the very first test, so the
-	   workaround shouldn't have any effect on them. */
-	for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
-		;
-	
-	OUTPLL(HTOTAL_CNTL, 0);
-
-	/* Clear reset & atomic update */
-	OUTPLLP(PPLL_CNTL, 0,
-		~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
-
-	/* We may want some locking ... oh well */
-       	radeon_msleep(5);
-
-	/* Switch back VCLK source to PPLL */
-	OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
-}
-
-/*
- * Timer function for delayed LVDS panel power up/down
- */
-static void radeon_lvds_timer_func(unsigned long data)
-{
-	struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
-
-	radeon_engine_idle();
-
-	OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
-}
-
-/*
- * Apply a video mode. This will apply the whole register set, including
- * the PLL registers, to the card
- */
-void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
-			int regs_only)
-{
-	int i;
-	int primary_mon = PRIMARY_MONITOR(rinfo);
-
-	if (nomodeset)
-		return;
-
-	if (!regs_only)
-		radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
-
-	radeon_fifo_wait(31);
-	for (i=0; i<10; i++)
-		OUTREG(common_regs[i].reg, common_regs[i].val);
-
-	/* Apply surface registers */
-	for (i=0; i<8; i++) {
-		OUTREG(SURFACE0_LOWER_BOUND + 0x10*i, mode->surf_lower_bound[i]);
-		OUTREG(SURFACE0_UPPER_BOUND + 0x10*i, mode->surf_upper_bound[i]);
-		OUTREG(SURFACE0_INFO + 0x10*i, mode->surf_info[i]);
-	}
-
-	OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
-	OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
-		~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
-	OUTREG(CRTC_MORE_CNTL, mode->crtc_more_cntl);
-	OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
-	OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
-	OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
-	OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
-	OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
-	OUTREG(CRTC_OFFSET, 0);
-	OUTREG(CRTC_OFFSET_CNTL, 0);
-	OUTREG(CRTC_PITCH, mode->crtc_pitch);
-	OUTREG(SURFACE_CNTL, mode->surface_cntl);
-
-	radeon_write_pll_regs(rinfo, mode);
-
-	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-		radeon_fifo_wait(10);
-		OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
-		OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
-		OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
-		OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid);
-		OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch);
-		OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch);
-		OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl);
-		OUTREG(TMDS_CRC, mode->tmds_crc);
-		OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
-	}
-
-	if (!regs_only)
-		radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
-
-	radeon_fifo_wait(2);
-	OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
-	
-	return;
-}
-
-/*
- * Calculate the PLL values for a given mode
- */
-static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs,
-				 unsigned long freq)
-{
-	const struct {
-		int divider;
-		int bitvalue;
-	} *post_div,
-	  post_divs[] = {
-		{ 1,  0 },
-		{ 2,  1 },
-		{ 4,  2 },
-		{ 8,  3 },
-		{ 3,  4 },
-		{ 16, 5 },
-		{ 6,  6 },
-		{ 12, 7 },
-		{ 0,  0 },
-	};
-	int fb_div, pll_output_freq = 0;
-	int uses_dvo = 0;
-
-	/* Check if the DVO port is enabled and sourced from the primary CRTC. I'm
-	 * not sure which model starts having FP2_GEN_CNTL, I assume anything more
-	 * recent than an r(v)100...
-	 */
-#if 1
-	/* XXX I had reports of flicker happening with the cinema display
-	 * on TMDS1 that seem to be fixed if I also forbit odd dividers in
-	 * this case. This could just be a bandwidth calculation issue, I
-	 * haven't implemented the bandwidth code yet, but in the meantime,
-	 * forcing uses_dvo to 1 fixes it and shouln't have bad side effects,
-	 * I haven't seen a case were were absolutely needed an odd PLL
-	 * divider. I'll find a better fix once I have more infos on the
-	 * real cause of the problem.
-	 */
-	while (rinfo->has_CRTC2) {
-		u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL);
-		u32 disp_output_cntl;
-		int source;
-
-		/* FP2 path not enabled */
-		if ((fp2_gen_cntl & FP2_ON) == 0)
-			break;
-		/* Not all chip revs have the same format for this register,
-		 * extract the source selection
-		 */
-		if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) {
-			source = (fp2_gen_cntl >> 10) & 0x3;
-			/* sourced from transform unit, check for transform unit
-			 * own source
-			 */
-			if (source == 3) {
-				disp_output_cntl = INREG(DISP_OUTPUT_CNTL);
-				source = (disp_output_cntl >> 12) & 0x3;
-			}
-		} else
-			source = (fp2_gen_cntl >> 13) & 0x1;
-		/* sourced from CRTC2 -> exit */
-		if (source == 1)
-			break;
-
-		/* so we end up on CRTC1, let's set uses_dvo to 1 now */
-		uses_dvo = 1;
-		break;
-	}
-#else
-	uses_dvo = 1;
-#endif
-	if (freq > rinfo->pll.ppll_max)
-		freq = rinfo->pll.ppll_max;
-	if (freq*12 < rinfo->pll.ppll_min)
-		freq = rinfo->pll.ppll_min / 12;
-	pr_debug("freq = %lu, PLL min = %u, PLL max = %u\n",
-	       freq, rinfo->pll.ppll_min, rinfo->pll.ppll_max);
-
-	for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
-		pll_output_freq = post_div->divider * freq;
-		/* If we output to the DVO port (external TMDS), we don't allow an
-		 * odd PLL divider as those aren't supported on this path
-		 */
-		if (uses_dvo && (post_div->divider & 1))
-			continue;
-		if (pll_output_freq >= rinfo->pll.ppll_min  &&
-		    pll_output_freq <= rinfo->pll.ppll_max)
-			break;
-	}
-
-	/* If we fall through the bottom, try the "default value"
-	   given by the terminal post_div->bitvalue */
-	if ( !post_div->divider ) {
-		post_div = &post_divs[post_div->bitvalue];
-		pll_output_freq = post_div->divider * freq;
-	}
-	pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
-	       rinfo->pll.ref_div, rinfo->pll.ref_clk,
-	       pll_output_freq);
-
-	/* If we fall through the bottom, try the "default value"
-	   given by the terminal post_div->bitvalue */
-	if ( !post_div->divider ) {
-		post_div = &post_divs[post_div->bitvalue];
-		pll_output_freq = post_div->divider * freq;
-	}
-	pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
-	       rinfo->pll.ref_div, rinfo->pll.ref_clk,
-	       pll_output_freq);
-
-	fb_div = round_div(rinfo->pll.ref_div*pll_output_freq,
-				  rinfo->pll.ref_clk);
-	regs->ppll_ref_div = rinfo->pll.ref_div;
-	regs->ppll_div_3 = fb_div | (post_div->bitvalue << 16);
-
-	pr_debug("post div = 0x%x\n", post_div->bitvalue);
-	pr_debug("fb_div = 0x%x\n", fb_div);
-	pr_debug("ppll_div_3 = 0x%x\n", regs->ppll_div_3);
-}
-
-static int radeonfb_set_par(struct fb_info *info)
-{
-	struct radeonfb_info *rinfo = info->par;
-	struct fb_var_screeninfo *mode = &info->var;
-	struct radeon_regs *newmode;
-	int hTotal, vTotal, hSyncStart, hSyncEnd,
-	    hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
-	u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
-	u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
-	u32 sync, h_sync_pol, v_sync_pol, dotClock, pixClock;
-	int i, freq;
-	int format = 0;
-	int nopllcalc = 0;
-	int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
-	int primary_mon = PRIMARY_MONITOR(rinfo);
-	int depth = var_to_depth(mode);
-	int use_rmx = 0;
-
-	newmode = kmalloc(sizeof(struct radeon_regs), GFP_KERNEL);
-	if (!newmode)
-		return -ENOMEM;
-
-	/* We always want engine to be idle on a mode switch, even
-	 * if we won't actually change the mode
-	 */
-	radeon_engine_idle();
-
-	hSyncStart = mode->xres + mode->right_margin;
-	hSyncEnd = hSyncStart + mode->hsync_len;
-	hTotal = hSyncEnd + mode->left_margin;
-
-	vSyncStart = mode->yres + mode->lower_margin;
-	vSyncEnd = vSyncStart + mode->vsync_len;
-	vTotal = vSyncEnd + mode->upper_margin;
-	pixClock = mode->pixclock;
-
-	sync = mode->sync;
-	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
-	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
-	if (primary_mon == MT_DFP || primary_mon == MT_LCD) {
-		if (rinfo->panel_info.xres < mode->xres)
-			mode->xres = rinfo->panel_info.xres;
-		if (rinfo->panel_info.yres < mode->yres)
-			mode->yres = rinfo->panel_info.yres;
-
-		hTotal = mode->xres + rinfo->panel_info.hblank;
-		hSyncStart = mode->xres + rinfo->panel_info.hOver_plus;
-		hSyncEnd = hSyncStart + rinfo->panel_info.hSync_width;
-
-		vTotal = mode->yres + rinfo->panel_info.vblank;
-		vSyncStart = mode->yres + rinfo->panel_info.vOver_plus;
-		vSyncEnd = vSyncStart + rinfo->panel_info.vSync_width;
-
-		h_sync_pol = !rinfo->panel_info.hAct_high;
-		v_sync_pol = !rinfo->panel_info.vAct_high;
-
-		pixClock = 100000000 / rinfo->panel_info.clock;
-
-		if (rinfo->panel_info.use_bios_dividers) {
-			nopllcalc = 1;
-			newmode->ppll_div_3 = rinfo->panel_info.fbk_divider |
-				(rinfo->panel_info.post_divider << 16);
-			newmode->ppll_ref_div = rinfo->panel_info.ref_divider;
-		}
-	}
-	dotClock = 1000000000 / pixClock;
-	freq = dotClock / 10; /* x100 */
-
-	pr_debug("hStart = %d, hEnd = %d, hTotal = %d\n",
-		hSyncStart, hSyncEnd, hTotal);
-	pr_debug("vStart = %d, vEnd = %d, vTotal = %d\n",
-		vSyncStart, vSyncEnd, vTotal);
-
-	hsync_wid = (hSyncEnd - hSyncStart) / 8;
-	vsync_wid = vSyncEnd - vSyncStart;
-	if (hsync_wid == 0)
-		hsync_wid = 1;
-	else if (hsync_wid > 0x3f)	/* max */
-		hsync_wid = 0x3f;
-
-	if (vsync_wid == 0)
-		vsync_wid = 1;
-	else if (vsync_wid > 0x1f)	/* max */
-		vsync_wid = 0x1f;
-
-	hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
-	vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
-	cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
-
-	format = radeon_get_dstbpp(depth);
-	bytpp = mode->bits_per_pixel >> 3;
-
-	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
-		hsync_fudge = hsync_fudge_fp[format-1];
-	else
-		hsync_fudge = hsync_adj_tab[format-1];
-
-	hsync_start = hSyncStart - 8 + hsync_fudge;
-
-	newmode->crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
-				(format << 8);
-
-	/* Clear auto-center etc... */
-	newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl;
-	newmode->crtc_more_cntl &= 0xfffffff0;
-	
-	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
-		if (mirror)
-			newmode->crtc_ext_cntl |= CRTC_CRT_ON;
-
-		newmode->crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
-					   CRTC_INTERLACE_EN);
-	} else {
-		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
-					CRTC_CRT_ON;
-	}
-
-	newmode->dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
-			   DAC_8BIT_EN;
-
-	newmode->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |
-				     (((mode->xres / 8) - 1) << 16));
-
-	newmode->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
-					(hsync_wid << 16) | (h_sync_pol << 23));
-
-	newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
-				    ((mode->yres - 1) << 16);
-
-	newmode->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
-					 (vsync_wid << 16) | (v_sync_pol  << 23));
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
-		/* We first calculate the engine pitch */
-		rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
- 				& ~(0x3f)) >> 6;
-
-		/* Then, re-multiply it to get the CRTC pitch */
-		newmode->crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);
-	} else
-		newmode->crtc_pitch = (mode->xres_virtual >> 3);
-
-	newmode->crtc_pitch |= (newmode->crtc_pitch << 16);
-
-	/*
-	 * It looks like recent chips have a problem with SURFACE_CNTL,
-	 * setting SURF_TRANSLATION_DIS completely disables the
-	 * swapper as well, so we leave it unset now.
-	 */
-	newmode->surface_cntl = 0;
-
-#if defined(__BIG_ENDIAN)
-
-	/* Setup swapping on both apertures, though we currently
-	 * only use aperture 0, enabling swapper on aperture 1
-	 * won't harm
-	 */
-	switch (mode->bits_per_pixel) {
-		case 16:
-			newmode->surface_cntl |= NONSURF_AP0_SWP_16BPP;
-			newmode->surface_cntl |= NONSURF_AP1_SWP_16BPP;
-			break;
-		case 24:	
-		case 32:
-			newmode->surface_cntl |= NONSURF_AP0_SWP_32BPP;
-			newmode->surface_cntl |= NONSURF_AP1_SWP_32BPP;
-			break;
-	}
-#endif
-
-	/* Clear surface registers */
-	for (i=0; i<8; i++) {
-		newmode->surf_lower_bound[i] = 0;
-		newmode->surf_upper_bound[i] = 0x1f;
-		newmode->surf_info[i] = 0;
-	}
-
-	pr_debug("h_total_disp = 0x%x\t   hsync_strt_wid = 0x%x\n",
-		newmode->crtc_h_total_disp, newmode->crtc_h_sync_strt_wid);
-	pr_debug("v_total_disp = 0x%x\t   vsync_strt_wid = 0x%x\n",
-		newmode->crtc_v_total_disp, newmode->crtc_v_sync_strt_wid);
-
-	rinfo->bpp = mode->bits_per_pixel;
-	rinfo->depth = depth;
-
-	pr_debug("pixclock = %lu\n", (unsigned long)pixClock);
-	pr_debug("freq = %lu\n", (unsigned long)freq);
-
-	/* We use PPLL_DIV_3 */
-	newmode->clk_cntl_index = 0x300;
-
-	/* Calculate PPLL value if necessary */
-	if (!nopllcalc)
-		radeon_calc_pll_regs(rinfo, newmode, freq);
-
-	newmode->vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;
-
-	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-		unsigned int hRatio, vRatio;
-
-		if (mode->xres > rinfo->panel_info.xres)
-			mode->xres = rinfo->panel_info.xres;
-		if (mode->yres > rinfo->panel_info.yres)
-			mode->yres = rinfo->panel_info.yres;
-
-		newmode->fp_horz_stretch = (((rinfo->panel_info.xres / 8) - 1)
-					   << HORZ_PANEL_SHIFT);
-		newmode->fp_vert_stretch = ((rinfo->panel_info.yres - 1)
-					   << VERT_PANEL_SHIFT);
-
-		if (mode->xres != rinfo->panel_info.xres) {
-			hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX,
-					   rinfo->panel_info.xres);
-			newmode->fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
-						   (newmode->fp_horz_stretch &
-						    (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |
-						     HORZ_AUTO_RATIO_INC)));
-			newmode->fp_horz_stretch |= (HORZ_STRETCH_BLEND |
-						    HORZ_STRETCH_ENABLE);
-			use_rmx = 1;
-		}
-		newmode->fp_horz_stretch &= ~HORZ_AUTO_RATIO;
-
-		if (mode->yres != rinfo->panel_info.yres) {
-			vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX,
-					   rinfo->panel_info.yres);
-			newmode->fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
-						   (newmode->fp_vert_stretch &
-						   (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));
-			newmode->fp_vert_stretch |= (VERT_STRETCH_BLEND |
-						    VERT_STRETCH_ENABLE);
-			use_rmx = 1;
-		}
-		newmode->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
-
-		newmode->fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)
-				       ~(FP_SEL_CRTC2 |
-					 FP_RMX_HVSYNC_CONTROL_EN |
-					 FP_DFP_SYNC_SEL |
-					 FP_CRT_SYNC_SEL |
-					 FP_CRTC_LOCK_8DOT |
-					 FP_USE_SHADOW_EN |
-					 FP_CRTC_USE_SHADOW_VEND |
-					 FP_CRT_SYNC_ALT));
-
-		newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR |
-					FP_CRTC_DONT_SHADOW_HEND |
-					FP_PANEL_FORMAT);
-
-		if (IS_R300_VARIANT(rinfo) ||
-		    (rinfo->family == CHIP_FAMILY_R200)) {
-			newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
-			if (use_rmx)
-				newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
-			else
-				newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
-		} else
-			newmode->fp_gen_cntl |= FP_SEL_CRTC1;
-
-		newmode->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl;
-		newmode->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl;
-		newmode->tmds_crc = rinfo->init_state.tmds_crc;
-		newmode->tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;
-
-		if (primary_mon == MT_LCD) {
-			newmode->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
-			newmode->fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN);
-		} else {
-			/* DFP */
-			newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
-			newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST);
-			/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
-			if (IS_R300_VARIANT(rinfo) ||
-			    (rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
-				newmode->tmds_transmitter_cntl &= ~TMDS_PLL_EN;
-			else
-				newmode->tmds_transmitter_cntl |= TMDS_PLL_EN;
-			newmode->crtc_ext_cntl &= ~CRTC_CRT_ON;
-		}
-
-		newmode->fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) |
-				(((mode->xres / 8) - 1) << 16));
-		newmode->fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) |
-				((mode->yres - 1) << 16);
-		newmode->fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) |
-				(hsync_wid << 16) | (h_sync_pol << 23));
-		newmode->fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) |
-				(vsync_wid << 16) | (v_sync_pol  << 23));
-	}
-
-	/* do it! */
-	if (!rinfo->asleep) {
-		memcpy(&rinfo->state, newmode, sizeof(*newmode));
-		radeon_write_mode (rinfo, newmode, 0);
-		/* (re)initialize the engine */
-		if (!(info->flags & FBINFO_HWACCEL_DISABLED))
-			radeonfb_engine_init (rinfo);
-	}
-	/* Update fix */
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
-        	info->fix.line_length = rinfo->pitch*64;
-        else
-		info->fix.line_length = mode->xres_virtual
-			* ((mode->bits_per_pixel + 1) / 8);
-        info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR
-		: FB_VISUAL_DIRECTCOLOR;
-
-#ifdef CONFIG_BOOTX_TEXT
-	/* Update debug text engine */
-	btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres,
-			     rinfo->depth, info->fix.line_length);
-#endif
-
-	kfree(newmode);
-	return 0;
-}
-
-
-static struct fb_ops radeonfb_ops = {
-	.owner			= THIS_MODULE,
-	.fb_check_var		= radeonfb_check_var,
-	.fb_set_par		= radeonfb_set_par,
-	.fb_setcolreg		= radeonfb_setcolreg,
-	.fb_setcmap		= radeonfb_setcmap,
-	.fb_pan_display 	= radeonfb_pan_display,
-	.fb_blank		= radeonfb_blank,
-	.fb_ioctl		= radeonfb_ioctl,
-	.fb_sync		= radeonfb_sync,
-	.fb_fillrect		= radeonfb_fillrect,
-	.fb_copyarea		= radeonfb_copyarea,
-	.fb_imageblit		= radeonfb_imageblit,
-};
-
-
-static int radeon_set_fbinfo(struct radeonfb_info *rinfo)
-{
-	struct fb_info *info = rinfo->info;
-
-	info->par = rinfo;
-	info->pseudo_palette = rinfo->pseudo_palette;
-	info->flags = FBINFO_DEFAULT
-		    | FBINFO_HWACCEL_COPYAREA
-		    | FBINFO_HWACCEL_FILLRECT
-		    | FBINFO_HWACCEL_XPAN
-		    | FBINFO_HWACCEL_YPAN;
-	info->fbops = &radeonfb_ops;
-	info->screen_base = rinfo->fb_base;
-	info->screen_size = rinfo->mapped_vram;
-	/* Fill fix common fields */
-	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
-        info->fix.smem_start = rinfo->fb_base_phys;
-        info->fix.smem_len = rinfo->video_ram;
-        info->fix.type = FB_TYPE_PACKED_PIXELS;
-        info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-        info->fix.xpanstep = 8;
-        info->fix.ypanstep = 1;
-        info->fix.ywrapstep = 0;
-        info->fix.type_aux = 0;
-        info->fix.mmio_start = rinfo->mmio_base_phys;
-        info->fix.mmio_len = RADEON_REGSIZE;
-	info->fix.accel = FB_ACCEL_ATI_RADEON;
-
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	if (noaccel)
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-
-        return 0;
-}
-
-/*
- * This reconfigure the card's internal memory map. In theory, we'd like
- * to setup the card's memory at the same address as it's PCI bus address,
- * and the AGP aperture right after that so that system RAM on 32 bits
- * machines at least, is directly accessible. However, doing so would
- * conflict with the current XFree drivers...
- * Ultimately, I hope XFree, GATOS and ATI binary drivers will all agree
- * on the proper way to set this up and duplicate this here. In the meantime,
- * I put the card's memory at 0 in card space and AGP at some random high
- * local (0xe0000000 for now) that will be changed by XFree/DRI anyway
- */
-#ifdef CONFIG_PPC_OF
-#undef SET_MC_FB_FROM_APERTURE
-static void fixup_memory_mappings(struct radeonfb_info *rinfo)
-{
-	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl = 0;
-	u32 save_crtc_ext_cntl;
-	u32 aper_base, aper_size;
-	u32 agp_base;
-
-	/* First, we disable display to avoid interfering */
-	if (rinfo->has_CRTC2) {
-		save_crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL);
-		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl | CRTC2_DISP_REQ_EN_B);
-	}
-	save_crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
-	save_crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
-	
-	OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl | CRTC_DISPLAY_DIS);
-	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
-	mdelay(100);
-
-	aper_base = INREG(CNFG_APER_0_BASE);
-	aper_size = INREG(CNFG_APER_SIZE);
-
-#ifdef SET_MC_FB_FROM_APERTURE
-	/* Set framebuffer to be at the same address as set in PCI BAR */
-	OUTREG(MC_FB_LOCATION, 
-		((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16));
-	rinfo->fb_local_base = aper_base;
-#else
-	OUTREG(MC_FB_LOCATION, 0x7fff0000);
-	rinfo->fb_local_base = 0;
-#endif
-	agp_base = aper_base + aper_size;
-	if (agp_base & 0xf0000000)
-		agp_base = (aper_base | 0x0fffffff) + 1;
-
-	/* Set AGP to be just after the framebuffer on a 256Mb boundary. This
-	 * assumes the FB isn't mapped to 0xf0000000 or above, but this is
-	 * always the case on PPCs afaik.
-	 */
-#ifdef SET_MC_FB_FROM_APERTURE
-	OUTREG(MC_AGP_LOCATION, 0xffff0000 | (agp_base >> 16));
-#else
-	OUTREG(MC_AGP_LOCATION, 0xffffe000);
-#endif
-
-	/* Fixup the display base addresses & engine offsets while we
-	 * are at it as well
-	 */
-#ifdef SET_MC_FB_FROM_APERTURE
-	OUTREG(DISPLAY_BASE_ADDR, aper_base);
-	if (rinfo->has_CRTC2)
-		OUTREG(CRTC2_DISPLAY_BASE_ADDR, aper_base);
-	OUTREG(OV0_BASE_ADDR, aper_base);
-#else
-	OUTREG(DISPLAY_BASE_ADDR, 0);
-	if (rinfo->has_CRTC2)
-		OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);
-	OUTREG(OV0_BASE_ADDR, 0);
-#endif
-	mdelay(100);
-
-	/* Restore display settings */
-	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl);
-	OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl);
-	if (rinfo->has_CRTC2)
-		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);	
-
-	pr_debug("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",
-		aper_base,
-		((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16),
-		0xffff0000 | (agp_base >> 16));
-}
-#endif /* CONFIG_PPC_OF */
-
-
-static void radeon_identify_vram(struct radeonfb_info *rinfo)
-{
-	u32 tmp;
-
-	/* framebuffer size */
-        if ((rinfo->family == CHIP_FAMILY_RS100) ||
-            (rinfo->family == CHIP_FAMILY_RS200) ||
-            (rinfo->family == CHIP_FAMILY_RS300) ||
-            (rinfo->family == CHIP_FAMILY_RC410) ||
-            (rinfo->family == CHIP_FAMILY_RS400) ||
-	    (rinfo->family == CHIP_FAMILY_RS480) ) {
-          u32 tom = INREG(NB_TOM);
-          tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
-
- 		radeon_fifo_wait(6);
-          OUTREG(MC_FB_LOCATION, tom);
-          OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
-
-          /* This is supposed to fix the crtc2 noise problem. */
-          OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
-
-          if ((rinfo->family == CHIP_FAMILY_RS100) ||
-              (rinfo->family == CHIP_FAMILY_RS200)) {
-             /* This is to workaround the asic bug for RMX, some versions
-                of BIOS doesn't have this register initialized correctly.
-             */
-             OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
-                     ~CRTC_H_CUTOFF_ACTIVE_EN);
-          }
-        } else {
-          tmp = INREG(CNFG_MEMSIZE);
-        }
-
-	/* mem size is bits [28:0], mask off the rest */
-	rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK;
-
-	/*
-	 * Hack to get around some busted production M6's
-	 * reporting no ram
-	 */
-	if (rinfo->video_ram == 0) {
-		switch (rinfo->pdev->device) {
-	       	case PCI_CHIP_RADEON_LY:
-		case PCI_CHIP_RADEON_LZ:
-	       		rinfo->video_ram = 8192 * 1024;
-	       		break;
-	       	default:
-	       		break;
-		}
-	}
-
-
-	/*
-	 * Now try to identify VRAM type
-	 */
-	if (rinfo->is_IGP || (rinfo->family >= CHIP_FAMILY_R300) ||
-	    (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
-		rinfo->vram_ddr = 1;
-	else
-		rinfo->vram_ddr = 0;
-
-	tmp = INREG(MEM_CNTL);
-	if (IS_R300_VARIANT(rinfo)) {
-		tmp &=  R300_MEM_NUM_CHANNELS_MASK;
-		switch (tmp) {
-		case 0:  rinfo->vram_width = 64; break;
-		case 1:  rinfo->vram_width = 128; break;
-		case 2:  rinfo->vram_width = 256; break;
-		default: rinfo->vram_width = 128; break;
-		}
-	} else if ((rinfo->family == CHIP_FAMILY_RV100) ||
-		   (rinfo->family == CHIP_FAMILY_RS100) ||
-		   (rinfo->family == CHIP_FAMILY_RS200)){
-		if (tmp & RV100_MEM_HALF_MODE)
-			rinfo->vram_width = 32;
-		else
-			rinfo->vram_width = 64;
-	} else {
-		if (tmp & MEM_NUM_CHANNELS_MASK)
-			rinfo->vram_width = 128;
-		else
-			rinfo->vram_width = 64;
-	}
-
-	/* This may not be correct, as some cards can have half of channel disabled
-	 * ToDo: identify these cases
-	 */
-
-	pr_debug("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n",
-	       pci_name(rinfo->pdev),
-	       rinfo->video_ram / 1024,
-	       rinfo->vram_ddr ? "DDR" : "SDRAM",
-	       rinfo->vram_width);
-}
-
-/*
- * Sysfs
- */
-
-static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid)
-{
-	return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH);
-}
-
-
-static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj,
-				 struct bin_attribute *bin_attr,
-				 char *buf, loff_t off, size_t count)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct pci_dev *pdev = to_pci_dev(dev);
-        struct fb_info *info = pci_get_drvdata(pdev);
-        struct radeonfb_info *rinfo = info->par;
-
-	return radeon_show_one_edid(buf, off, count, rinfo->mon1_EDID);
-}
-
-
-static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj,
-				 struct bin_attribute *bin_attr,
-				 char *buf, loff_t off, size_t count)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct pci_dev *pdev = to_pci_dev(dev);
-        struct fb_info *info = pci_get_drvdata(pdev);
-        struct radeonfb_info *rinfo = info->par;
-
-	return radeon_show_one_edid(buf, off, count, rinfo->mon2_EDID);
-}
-
-static struct bin_attribute edid1_attr = {
-	.attr   = {
-		.name	= "edid1",
-		.mode	= 0444,
-	},
-	.size	= EDID_LENGTH,
-	.read	= radeon_show_edid1,
-};
-
-static struct bin_attribute edid2_attr = {
-	.attr   = {
-		.name	= "edid2",
-		.mode	= 0444,
-	},
-	.size	= EDID_LENGTH,
-	.read	= radeon_show_edid2,
-};
-
-
-static int radeonfb_pci_register(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	struct fb_info *info;
-	struct radeonfb_info *rinfo;
-	int ret;
-	unsigned char c1, c2;
-	int err = 0;
-
-	pr_debug("radeonfb_pci_register BEGIN\n");
-	
-	/* Enable device in PCI config */
-	ret = pci_enable_device(pdev);
-	if (ret < 0) {
-		printk(KERN_ERR "radeonfb (%s): Cannot enable PCI device\n",
-		       pci_name(pdev));
-		goto err_out;
-	}
-
-	info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);
-	if (!info) {
-		printk (KERN_ERR "radeonfb (%s): could not allocate memory\n",
-			pci_name(pdev));
-		ret = -ENOMEM;
-		goto err_disable;
-	}
-	rinfo = info->par;
-	rinfo->info = info;	
-	rinfo->pdev = pdev;
-	
-	spin_lock_init(&rinfo->reg_lock);
-	init_timer(&rinfo->lvds_timer);
-	rinfo->lvds_timer.function = radeon_lvds_timer_func;
-	rinfo->lvds_timer.data = (unsigned long)rinfo;
-
-	c1 = ent->device >> 8;
-	c2 = ent->device & 0xff;
-	if (isprint(c1) && isprint(c2))
-		snprintf(rinfo->name, sizeof(rinfo->name),
-			 "ATI Radeon %x \"%c%c\"", ent->device & 0xffff, c1, c2);
-	else
-		snprintf(rinfo->name, sizeof(rinfo->name),
-			 "ATI Radeon %x", ent->device & 0xffff);
-
-	rinfo->family = ent->driver_data & CHIP_FAMILY_MASK;
-	rinfo->chipset = pdev->device;
-	rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
-	rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
-	rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
-
-	/* Set base addrs */
-	rinfo->fb_base_phys = pci_resource_start (pdev, 0);
-	rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
-
-	/* request the mem regions */
-	ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
-	if (ret < 0) {
-		printk( KERN_ERR "radeonfb (%s): cannot request region 0.\n",
-			pci_name(rinfo->pdev));
-		goto err_release_fb;
-	}
-
-	ret = pci_request_region(pdev, 2, "radeonfb mmio");
-	if (ret < 0) {
-		printk( KERN_ERR "radeonfb (%s): cannot request region 2.\n",
-			pci_name(rinfo->pdev));
-		goto err_release_pci0;
-	}
-
-	/* map the regions */
-	rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
-	if (!rinfo->mmio_base) {
-		printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n",
-		       pci_name(rinfo->pdev));
-		ret = -EIO;
-		goto err_release_pci2;
-	}
-
-	rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
-
-	/*
-	 * Check for errata
-	 */
-	rinfo->errata = 0;
-	if (rinfo->family == CHIP_FAMILY_R300 &&
-	    (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK)
-	    == CFG_ATI_REV_A11)
-		rinfo->errata |= CHIP_ERRATA_R300_CG;
-
-	if (rinfo->family == CHIP_FAMILY_RV200 ||
-	    rinfo->family == CHIP_FAMILY_RS200)
-		rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
-
-	if (rinfo->family == CHIP_FAMILY_RV100 ||
-	    rinfo->family == CHIP_FAMILY_RS100 ||
-	    rinfo->family == CHIP_FAMILY_RS200)
-		rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
-
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-	/* On PPC, we obtain the OF device-node pointer to the firmware
-	 * data for this chip
-	 */
-	rinfo->of_node = pci_device_to_OF_node(pdev);
-	if (rinfo->of_node == NULL)
-		printk(KERN_WARNING "radeonfb (%s): Cannot match card to OF node !\n",
-		       pci_name(rinfo->pdev));
-
-#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
-#ifdef CONFIG_PPC_OF
-	/* On PPC, the firmware sets up a memory mapping that tends
-	 * to cause lockups when enabling the engine. We reconfigure
-	 * the card internal memory mappings properly
-	 */
-	fixup_memory_mappings(rinfo);
-#endif /* CONFIG_PPC_OF */
-
-	/* Get VRAM size and type */
-	radeon_identify_vram(rinfo);
-
-	rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
-
-	do {
-		rinfo->fb_base = ioremap (rinfo->fb_base_phys,
-					  rinfo->mapped_vram);
-	} while (rinfo->fb_base == NULL &&
-		 ((rinfo->mapped_vram /= 2) >= MIN_MAPPED_VRAM));
-
-	if (rinfo->fb_base == NULL) {
-		printk (KERN_ERR "radeonfb (%s): cannot map FB\n",
-			pci_name(rinfo->pdev));
-		ret = -EIO;
-		goto err_unmap_rom;
-	}
-
-	pr_debug("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev),
-	       rinfo->mapped_vram/1024);
-
-	/*
-	 * Map the BIOS ROM if any and retrieve PLL parameters from
-	 * the BIOS. We skip that on mobility chips as the real panel
-	 * values we need aren't in the ROM but in the BIOS image in
-	 * memory. This is definitely not the best meacnism though,
-	 * we really need the arch code to tell us which is the "primary"
-	 * video adapter to use the memory image (or better, the arch
-	 * should provide us a copy of the BIOS image to shield us from
-	 * archs who would store that elsewhere and/or could initialize
-	 * more than one adapter during boot).
-	 */
-	if (!rinfo->is_mobility)
-		radeon_map_ROM(rinfo, pdev);
-
-	/*
-	 * On x86, the primary display on laptop may have it's BIOS
-	 * ROM elsewhere, try to locate it at the legacy memory hole.
-	 * We probably need to make sure this is the primary display,
-	 * but that is difficult without some arch support.
-	 */
-#ifdef CONFIG_X86
-	if (rinfo->bios_seg == NULL)
-		radeon_find_mem_vbios(rinfo);
-#endif
-
-	/* If both above failed, try the BIOS ROM again for mobility
-	 * chips
-	 */
-	if (rinfo->bios_seg == NULL && rinfo->is_mobility)
-		radeon_map_ROM(rinfo, pdev);
-
-	/* Get informations about the board's PLL */
-	radeon_get_pllinfo(rinfo);
-
-#ifdef CONFIG_FB_RADEON_I2C
-	/* Register I2C bus */
-	radeon_create_i2c_busses(rinfo);
-#endif
-
-	/* set all the vital stuff */
-	radeon_set_fbinfo (rinfo);
-
-	/* Probe screen types */
-	radeon_probe_screens(rinfo, monitor_layout, ignore_edid);
-
-	/* Build mode list, check out panel native model */
-	radeon_check_modes(rinfo, mode_option);
-
-	/* Register some sysfs stuff (should be done better) */
-	if (rinfo->mon1_EDID)
-		err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
-						&edid1_attr);
-	if (rinfo->mon2_EDID)
-		err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
-						&edid2_attr);
-	if (err)
-		pr_warning("%s() Creating sysfs files failed, continuing\n",
-			   __func__);
-
-	/* save current mode regs before we switch into the new one
-	 * so we can restore this upon __exit
-	 */
-	radeon_save_state (rinfo, &rinfo->init_state);
-	memcpy(&rinfo->state, &rinfo->init_state, sizeof(struct radeon_regs));
-
-	/* Setup Power Management capabilities */
-	if (default_dynclk < -1) {
-		/* -2 is special: means  ON on mobility chips and do not
-		 * change on others
-		 */
-		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
-	} else
-		radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep);
-
-	pci_set_drvdata(pdev, info);
-
-	/* Register with fbdev layer */
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		printk (KERN_ERR "radeonfb (%s): could not register framebuffer\n",
-			pci_name(rinfo->pdev));
-		goto err_unmap_fb;
-	}
-
-#ifdef CONFIG_MTRR
-	rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
-						 rinfo->video_ram,
-						 MTRR_TYPE_WRCOMB, 1);
-#endif
-
-	if (backlight)
-		radeonfb_bl_init(rinfo);
-
-	printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
-
-	if (rinfo->bios_seg)
-		radeon_unmap_ROM(rinfo, pdev);
-	pr_debug("radeonfb_pci_register END\n");
-
-	return 0;
-err_unmap_fb:
-	iounmap(rinfo->fb_base);
-err_unmap_rom:
-	kfree(rinfo->mon1_EDID);
-	kfree(rinfo->mon2_EDID);
-	if (rinfo->mon1_modedb)
-		fb_destroy_modedb(rinfo->mon1_modedb);
-	fb_dealloc_cmap(&info->cmap);
-#ifdef CONFIG_FB_RADEON_I2C
-	radeon_delete_i2c_busses(rinfo);
-#endif
-	if (rinfo->bios_seg)
-		radeon_unmap_ROM(rinfo, pdev);
-	iounmap(rinfo->mmio_base);
-err_release_pci2:
-	pci_release_region(pdev, 2);
-err_release_pci0:
-	pci_release_region(pdev, 0);
-err_release_fb:
-        framebuffer_release(info);
-err_disable:
-err_out:
-	return ret;
-}
-
-
-
-static void radeonfb_pci_unregister(struct pci_dev *pdev)
-{
-        struct fb_info *info = pci_get_drvdata(pdev);
-        struct radeonfb_info *rinfo = info->par;
- 
-        if (!rinfo)
-                return;
-
-	radeonfb_pm_exit(rinfo);
-
-	if (rinfo->mon1_EDID)
-		sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
-	if (rinfo->mon2_EDID)
-		sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
-
-#if 0
-	/* restore original state
-	 * 
-	 * Doesn't quite work yet, I suspect if we come from a legacy
-	 * VGA mode (or worse, text mode), we need to do some VGA black
-	 * magic here that I know nothing about. --BenH
-	 */
-        radeon_write_mode (rinfo, &rinfo->init_state, 1);
- #endif
-
-	del_timer_sync(&rinfo->lvds_timer);
-
-#ifdef CONFIG_MTRR
-	if (rinfo->mtrr_hdl >= 0)
-		mtrr_del(rinfo->mtrr_hdl, 0, 0);
-#endif
-
-        unregister_framebuffer(info);
-
-        radeonfb_bl_exit(rinfo);
-
-        iounmap(rinfo->mmio_base);
-        iounmap(rinfo->fb_base);
- 
-	pci_release_region(pdev, 2);
-	pci_release_region(pdev, 0);
-
-	kfree(rinfo->mon1_EDID);
-	kfree(rinfo->mon2_EDID);
-	if (rinfo->mon1_modedb)
-		fb_destroy_modedb(rinfo->mon1_modedb);
-#ifdef CONFIG_FB_RADEON_I2C
-	radeon_delete_i2c_busses(rinfo);
-#endif        
-	fb_dealloc_cmap(&info->cmap);
-        framebuffer_release(info);
-}
-
-
-static struct pci_driver radeonfb_driver = {
-	.name		= "radeonfb",
-	.id_table	= radeonfb_pci_table,
-	.probe		= radeonfb_pci_register,
-	.remove		= radeonfb_pci_unregister,
-#ifdef CONFIG_PM
-	.suspend       	= radeonfb_pci_suspend,
-	.resume		= radeonfb_pci_resume,
-#endif /* CONFIG_PM */
-};
-
-#ifndef MODULE
-static int __init radeonfb_setup (char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep (&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-
-		if (!strncmp(this_opt, "noaccel", 7)) {
-			noaccel = 1;
-		} else if (!strncmp(this_opt, "mirror", 6)) {
-			mirror = 1;
-		} else if (!strncmp(this_opt, "force_dfp", 9)) {
-			force_dfp = 1;
-		} else if (!strncmp(this_opt, "panel_yres:", 11)) {
-			panel_yres = simple_strtoul((this_opt+11), NULL, 0);
-		} else if (!strncmp(this_opt, "backlight:", 10)) {
-			backlight = simple_strtoul(this_opt+10, NULL, 0);
-#ifdef CONFIG_MTRR
-		} else if (!strncmp(this_opt, "nomtrr", 6)) {
-			nomtrr = 1;
-#endif
-		} else if (!strncmp(this_opt, "nomodeset", 9)) {
-			nomodeset = 1;
-		} else if (!strncmp(this_opt, "force_measure_pll", 17)) {
-			force_measure_pll = 1;
-		} else if (!strncmp(this_opt, "ignore_edid", 11)) {
-			ignore_edid = 1;
-#if defined(CONFIG_PM) && defined(CONFIG_X86)
-	 	} else if (!strncmp(this_opt, "force_sleep", 11)) {
-			force_sleep = 1;
-		} else if (!strncmp(this_opt, "ignore_devlist", 14)) {
-			ignore_devlist = 1;
-#endif
-		} else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-#endif  /*  MODULE  */
-
-static int __init radeonfb_init (void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("radeonfb", &option))
-		return -ENODEV;
-	radeonfb_setup(option);
-#endif
-	return pci_register_driver (&radeonfb_driver);
-}
-
-
-static void __exit radeonfb_exit (void)
-{
-	pci_unregister_driver (&radeonfb_driver);
-}
-
-module_init(radeonfb_init);
-module_exit(radeonfb_exit);
-
-MODULE_AUTHOR("Ani Joshi");
-MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
-MODULE_LICENSE("GPL");
-module_param(noaccel, bool, 0);
-module_param(default_dynclk, int, 0);
-MODULE_PARM_DESC(default_dynclk, "int: -2=enable on mobility only,-1=do not change,0=off,1=on");
-MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
-module_param(nomodeset, bool, 0);
-MODULE_PARM_DESC(nomodeset, "bool: disable actual setting of video mode");
-module_param(mirror, bool, 0);
-MODULE_PARM_DESC(mirror, "bool: mirror the display to both monitors");
-module_param(force_dfp, bool, 0);
-MODULE_PARM_DESC(force_dfp, "bool: force display to dfp");
-module_param(ignore_edid, bool, 0);
-MODULE_PARM_DESC(ignore_edid, "bool: Ignore EDID data when doing DDC probe");
-module_param(monitor_layout, charp, 0);
-MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)");
-module_param(force_measure_pll, bool, 0);
-MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)");
-#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, 0);
-MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
-#endif
-module_param(panel_yres, int, 0);
-MODULE_PARM_DESC(panel_yres, "int: set panel yres");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-#if defined(CONFIG_PM) && defined(CONFIG_X86)
-module_param(force_sleep, bool, 0);
-MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware");
-module_param(ignore_devlist, bool, 0);
-MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops");
-#endif
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
deleted file mode 100644
index ab1d0fd76316..000000000000
--- a/drivers/video/aty/radeon_i2c.c
+++ /dev/null
@@ -1,167 +0,0 @@
-#include "radeonfb.h"
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include <asm/io.h>
-
-#include <video/radeon.h>
-#include "../edid.h"
-
-static void radeon_gpio_setscl(void* data, int state)
-{
-	struct radeon_i2c_chan 	*chan = data;
-	struct radeonfb_info	*rinfo = chan->rinfo;
-	u32			val;
-	
-	val = INREG(chan->ddc_reg) & ~(VGA_DDC_CLK_OUT_EN);
-	if (!state)
-		val |= VGA_DDC_CLK_OUT_EN;
-
-	OUTREG(chan->ddc_reg, val);
-	(void)INREG(chan->ddc_reg);
-}
-
-static void radeon_gpio_setsda(void* data, int state)
-{
-	struct radeon_i2c_chan 	*chan = data;
-	struct radeonfb_info	*rinfo = chan->rinfo;
-	u32			val;
-	
-	val = INREG(chan->ddc_reg) & ~(VGA_DDC_DATA_OUT_EN);
-	if (!state)
-		val |= VGA_DDC_DATA_OUT_EN;
-
-	OUTREG(chan->ddc_reg, val);
-	(void)INREG(chan->ddc_reg);
-}
-
-static int radeon_gpio_getscl(void* data)
-{
-	struct radeon_i2c_chan 	*chan = data;
-	struct radeonfb_info	*rinfo = chan->rinfo;
-	u32			val;
-	
-	val = INREG(chan->ddc_reg);
-
-	return (val & VGA_DDC_CLK_INPUT) ? 1 : 0;
-}
-
-static int radeon_gpio_getsda(void* data)
-{
-	struct radeon_i2c_chan 	*chan = data;
-	struct radeonfb_info	*rinfo = chan->rinfo;
-	u32			val;
-	
-	val = INREG(chan->ddc_reg);
-
-	return (val & VGA_DDC_DATA_INPUT) ? 1 : 0;
-}
-
-static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
-{
-	int rc;
-
-	snprintf(chan->adapter.name, sizeof(chan->adapter.name),
-		 "radeonfb %s", name);
-	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.algo_data		= &chan->algo;
-	chan->adapter.dev.parent	= &chan->rinfo->pdev->dev;
-	chan->algo.setsda		= radeon_gpio_setsda;
-	chan->algo.setscl		= radeon_gpio_setscl;
-	chan->algo.getsda		= radeon_gpio_getsda;
-	chan->algo.getscl		= radeon_gpio_getscl;
-	chan->algo.udelay		= 10;
-	chan->algo.timeout		= 20;
-	chan->algo.data 		= chan;	
-	
-	i2c_set_adapdata(&chan->adapter, chan);
-	
-	/* Raise SCL and SDA */
-	radeon_gpio_setsda(chan, 1);
-	radeon_gpio_setscl(chan, 1);
-	udelay(20);
-
-	rc = i2c_bit_add_bus(&chan->adapter);
-	if (rc == 0)
-		dev_dbg(&chan->rinfo->pdev->dev, "I2C bus %s registered.\n", name);
-	else
-		dev_warn(&chan->rinfo->pdev->dev, "Failed to register I2C bus %s.\n", name);
-	return rc;
-}
-
-void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
-{
-	rinfo->i2c[0].rinfo	= rinfo;
-	rinfo->i2c[0].ddc_reg	= GPIO_MONID;
-#ifndef CONFIG_PPC
-	rinfo->i2c[0].adapter.class = I2C_CLASS_HWMON;
-#endif
-	radeon_setup_i2c_bus(&rinfo->i2c[0], "monid");
-
-	rinfo->i2c[1].rinfo	= rinfo;
-	rinfo->i2c[1].ddc_reg	= GPIO_DVI_DDC;
-	radeon_setup_i2c_bus(&rinfo->i2c[1], "dvi");
-
-	rinfo->i2c[2].rinfo	= rinfo;
-	rinfo->i2c[2].ddc_reg	= GPIO_VGA_DDC;
-	radeon_setup_i2c_bus(&rinfo->i2c[2], "vga");
-
-	rinfo->i2c[3].rinfo	= rinfo;
-	rinfo->i2c[3].ddc_reg	= GPIO_CRT2_DDC;
-	radeon_setup_i2c_bus(&rinfo->i2c[3], "crt2");
-}
-
-void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
-{
-	if (rinfo->i2c[0].rinfo)
-		i2c_del_adapter(&rinfo->i2c[0].adapter);
-	rinfo->i2c[0].rinfo = NULL;
-
-	if (rinfo->i2c[1].rinfo)
-		i2c_del_adapter(&rinfo->i2c[1].adapter);
-	rinfo->i2c[1].rinfo = NULL;
-
-	if (rinfo->i2c[2].rinfo)
-		i2c_del_adapter(&rinfo->i2c[2].adapter);
-	rinfo->i2c[2].rinfo = NULL;
-
-	if (rinfo->i2c[3].rinfo)
-		i2c_del_adapter(&rinfo->i2c[3].adapter);
-	rinfo->i2c[3].rinfo = NULL;
-}
-
-int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
-			       u8 **out_edid)
-{
-	u8 *edid;
-
-	edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter);
-
-	if (out_edid)
-		*out_edid = edid;
-	if (!edid) {
-		pr_debug("radeonfb: I2C (port %d) ... not found\n", conn);
-		return MT_NONE;
-	}
-	if (edid[0x14] & 0x80) {
-		/* Fix detection using BIOS tables */
-		if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
-		    (INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
-			pr_debug("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
-			return MT_LCD;
-		} else {
-			pr_debug("radeonfb: I2C (port %d) ... found TMDS panel\n", conn);
-			return MT_DFP;
-		}
-	}
-	pr_debug("radeonfb: I2C (port %d) ... found CRT display\n", conn);
-	return MT_CRT;
-}
-
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
deleted file mode 100644
index bc078d50d8f1..000000000000
--- a/drivers/video/aty/radeon_monitor.c
+++ /dev/null
@@ -1,1052 +0,0 @@
-#include "radeonfb.h"
-
-#include <linux/slab.h>
-
-#include "../edid.h"
-
-static struct fb_var_screeninfo radeonfb_default_var = {
-	.xres		= 640,
-	.yres		= 480,
-	.xres_virtual	= 640,
-	.yres_virtual	= 480,
-	.bits_per_pixel = 8,
-	.red		= { .length = 8 },
-	.green		= { .length = 8 },
-	.blue		= { .length = 8 },
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.pixclock	= 39721,
-	.left_margin	= 40,
-	.right_margin	= 24,
-	.upper_margin	= 32,
-	.lower_margin	= 11,
-	.hsync_len	= 96,
-	.vsync_len	= 2,
-	.vmode		= FB_VMODE_NONINTERLACED
-};
-
-static char *radeon_get_mon_name(int type)
-{
-	char *pret = NULL;
-
-	switch (type) {
-		case MT_NONE:
-			pret = "no";
-			break;
-		case MT_CRT:
-			pret = "CRT";
-			break;
-		case MT_DFP:
-			pret = "DFP";
-			break;
-		case MT_LCD:
-			pret = "LCD";
-			break;
-		case MT_CTV:
-			pret = "CTV";
-			break;
-		case MT_STV:
-			pret = "STV";
-			break;
-	}
-
-	return pret;
-}
-
-
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-/*
- * Try to find monitor informations & EDID data out of the Open Firmware
- * device-tree. This also contains some "hacks" to work around a few machine
- * models with broken OF probing by hard-coding known EDIDs for some Mac
- * laptops internal LVDS panel. (XXX: not done yet)
- */
-static int radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,
-				     int hdno)
-{
-        static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID",
-				     "EDID1", "EDID2",  NULL };
-	const u8 *pedid = NULL;
-	const u8 *pmt = NULL;
-	u8 *tmp;
-        int i, mt = MT_NONE;  
-	
-	pr_debug("analyzing OF properties...\n");
-	pmt = of_get_property(dp, "display-type", NULL);
-	if (!pmt)
-		return MT_NONE;
-	pr_debug("display-type: %s\n", pmt);
-	/* OF says "LCD" for DFP as well, we discriminate from the caller of this
-	 * function
-	 */
-	if (!strcmp(pmt, "LCD") || !strcmp(pmt, "DFP"))
-		mt = MT_DFP;
-	else if (!strcmp(pmt, "CRT"))
-		mt = MT_CRT;
-	else {
-		if (strcmp(pmt, "NONE") != 0)
-			printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n",
-			       pmt);
-		return MT_NONE;
-	}
-
-	for (i = 0; propnames[i] != NULL; ++i) {
-		pedid = of_get_property(dp, propnames[i], NULL);
-		if (pedid != NULL)
-			break;
-	}
-	/* We didn't find the EDID in the leaf node, some cards will actually
-	 * put EDID1/EDID2 in the parent, look for these (typically M6 tipb).
-	 * single-head cards have hdno == -1 and skip this step
-	 */
-	if (pedid == NULL && dp->parent && (hdno != -1))
-		pedid = of_get_property(dp->parent,
-				(hdno == 0) ? "EDID1" : "EDID2", NULL);
-	if (pedid == NULL && dp->parent && (hdno == 0))
-		pedid = of_get_property(dp->parent, "EDID", NULL);
-	if (pedid == NULL)
-		return mt;
-
-	tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
-	if (!tmp)
-		return mt;
-	*out_EDID = tmp;
-	return mt;
-}
-
-static int radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no,
-				u8 **out_EDID)
-{
-        struct device_node *dp;
-
-	pr_debug("radeon_probe_OF_head\n");
-
-        dp = rinfo->of_node;
-        while (dp == NULL)
-		return MT_NONE;
-
-	if (rinfo->has_CRTC2) {
-		const char *pname;
-		int len, second = 0;
-
-		dp = dp->child;
-		do {
-			if (!dp)
-				return MT_NONE;
-			pname = of_get_property(dp, "name", NULL);
-			if (!pname)
-				return MT_NONE;
-			len = strlen(pname);
-			pr_debug("head: %s (letter: %c, head_no: %d)\n",
-			       pname, pname[len-1], head_no);
-			if (pname[len-1] == 'A' && head_no == 0) {
-				int mt = radeon_parse_montype_prop(dp, out_EDID, 0);
-				/* Maybe check for LVDS_GEN_CNTL here ? I need to check out
-				 * what OF does when booting with lid closed
-				 */
-				if (mt == MT_DFP && rinfo->is_mobility)
-					mt = MT_LCD;
-				return mt;
-			} else if (pname[len-1] == 'B' && head_no == 1)
-				return radeon_parse_montype_prop(dp, out_EDID, 1);
-			second = 1;
-			dp = dp->sibling;
-		} while(!second);
-	} else {
-		if (head_no > 0)
-			return MT_NONE;
-		return radeon_parse_montype_prop(dp, out_EDID, -1);
-	}
-        return MT_NONE;
-}
-#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
-
-
-static int radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
-{
-	unsigned long tmp, tmp0;
-	char stmp[30];
-	int i;
-
-	if (!rinfo->bios_seg)
-		return 0;
-
-	if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) {
-		printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n");
-		rinfo->panel_info.pwr_delay = 200;
-		return 0;
-	}
-
-	for(i=0; i<24; i++)
-		stmp[i] = BIOS_IN8(tmp+i+1);
-	stmp[24] = 0;
-	printk("radeonfb: panel ID string: %s\n", stmp);
-	rinfo->panel_info.xres = BIOS_IN16(tmp + 25);
-	rinfo->panel_info.yres = BIOS_IN16(tmp + 27);
-	printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n",
-		rinfo->panel_info.xres, rinfo->panel_info.yres);
-
-	rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);
-	pr_debug("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay);
-	if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0)
-		rinfo->panel_info.pwr_delay = 2000;
-
-	/*
-	 * Some panels only work properly with some divider combinations
-	 */
-	rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46);
-	rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48);
-	rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49);
-	if (rinfo->panel_info.ref_divider != 0 &&
-	    rinfo->panel_info.fbk_divider > 3) {
-		rinfo->panel_info.use_bios_dividers = 1;
-		printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n");
-		pr_debug("ref_divider = %x\n", rinfo->panel_info.ref_divider);
-		pr_debug("post_divider = %x\n", rinfo->panel_info.post_divider);
-		pr_debug("fbk_divider = %x\n", rinfo->panel_info.fbk_divider);
-	}
-	pr_debug("Scanning BIOS table ...\n");
-	for(i=0; i<32; i++) {
-		tmp0 = BIOS_IN16(tmp+64+i*2);
-		if (tmp0 == 0)
-			break;
-		pr_debug(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2));
-		if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) &&
-		    (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) {
-			rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8;
-			rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) -
-							 BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff;
-			rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8;
-			rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26);
-			rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26);
-			rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11;
-			rinfo->panel_info.clock = BIOS_IN16(tmp0+9);
-			/* Assume high active syncs for now until ATI tells me more... maybe we
-			 * can probe register values here ?
-			 */
-			rinfo->panel_info.hAct_high = 1;
-			rinfo->panel_info.vAct_high = 1;
-			/* Mark panel infos valid */
-			rinfo->panel_info.valid = 1;
-
-			pr_debug("Found panel in BIOS table:\n");
-			pr_debug("  hblank: %d\n", rinfo->panel_info.hblank);
-			pr_debug("  hOver_plus: %d\n", rinfo->panel_info.hOver_plus);
-			pr_debug("  hSync_width: %d\n", rinfo->panel_info.hSync_width);
-			pr_debug("  vblank: %d\n", rinfo->panel_info.vblank);
-			pr_debug("  vOver_plus: %d\n", rinfo->panel_info.vOver_plus);
-			pr_debug("  vSync_width: %d\n", rinfo->panel_info.vSync_width);
-			pr_debug("  clock: %d\n", rinfo->panel_info.clock);
-				
-			return 1;
-		}
-	}
-	pr_debug("Didn't find panel in BIOS table !\n");
-
-	return 0;
-}
-
-/* Try to extract the connector informations from the BIOS. This
- * doesn't quite work yet, but it's output is still useful for
- * debugging
- */
-static void radeon_parse_connector_info(struct radeonfb_info *rinfo)
-{
-	int offset, chips, connectors, tmp, i, conn, type;
-
-	static char* __conn_type_table[16] = {
-		"NONE", "Proprietary", "CRT", "DVI-I", "DVI-D", "Unknown", "Unknown",
-		"Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
-		"Unknown", "Unknown", "Unknown"
-	};
-
-	if (!rinfo->bios_seg)
-		return;
-
-	offset = BIOS_IN16(rinfo->fp_bios_start + 0x50);
-	if (offset == 0) {
-		printk(KERN_WARNING "radeonfb: No connector info table detected\n");
-		return;
-	}
-
-	/* Don't do much more at this point but displaying the data if
-	 * DEBUG is enabled
-	 */
-	chips = BIOS_IN8(offset++) >> 4;
-	pr_debug("%d chips in connector info\n", chips);
-	for (i = 0; i < chips; i++) {
-		tmp = BIOS_IN8(offset++);
-		connectors = tmp & 0x0f;
-		pr_debug(" - chip %d has %d connectors\n", tmp >> 4, connectors);
-		for (conn = 0; ; conn++) {
-			tmp = BIOS_IN16(offset);
-			if (tmp == 0)
-				break;
-			offset += 2;
-			type = (tmp >> 12) & 0x0f;
-			pr_debug("  * connector %d of type %d (%s) : %04x\n",
-			       conn, type, __conn_type_table[type], tmp);
-		}
-	}
-}
-
-
-/*
- * Probe physical connection of a CRT. This code comes from XFree
- * as well and currently is only implemented for the CRT DAC, the
- * code for the TVDAC is commented out in XFree as "non working"
- */
-static int radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac)
-{
-    int	          connected = 0;
-
-    /* the monitor either wasn't connected or it is a non-DDC CRT.
-     * try to probe it
-     */
-    if (is_crt_dac) {
-	unsigned long ulOrigVCLK_ECP_CNTL;
-	unsigned long ulOrigDAC_CNTL;
-	unsigned long ulOrigDAC_EXT_CNTL;
-	unsigned long ulOrigCRTC_EXT_CNTL;
-	unsigned long ulData;
-	unsigned long ulMask;
-
-	ulOrigVCLK_ECP_CNTL = INPLL(VCLK_ECP_CNTL);
-
-	ulData              = ulOrigVCLK_ECP_CNTL;
-	ulData             &= ~(PIXCLK_ALWAYS_ONb
-				| PIXCLK_DAC_ALWAYS_ONb);
-	ulMask              = ~(PIXCLK_ALWAYS_ONb
-				| PIXCLK_DAC_ALWAYS_ONb);
-	OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);
-
-	ulOrigCRTC_EXT_CNTL = INREG(CRTC_EXT_CNTL);
-	ulData              = ulOrigCRTC_EXT_CNTL;
-	ulData             |= CRTC_CRT_ON;
-	OUTREG(CRTC_EXT_CNTL, ulData);
-   
-	ulOrigDAC_EXT_CNTL = INREG(DAC_EXT_CNTL);
-	ulData             = ulOrigDAC_EXT_CNTL;
-	ulData            &= ~DAC_FORCE_DATA_MASK;
-	ulData            |=  (DAC_FORCE_BLANK_OFF_EN
-			       |DAC_FORCE_DATA_EN
-			       |DAC_FORCE_DATA_SEL_MASK);
-	if ((rinfo->family == CHIP_FAMILY_RV250) ||
-	    (rinfo->family == CHIP_FAMILY_RV280))
-	    ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT);
-	else
-	    ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT);
-
-	OUTREG(DAC_EXT_CNTL, ulData);
-
-	ulOrigDAC_CNTL     = INREG(DAC_CNTL);
-	ulData             = ulOrigDAC_CNTL;
-	ulData            |= DAC_CMP_EN;
-	ulData            &= ~(DAC_RANGE_CNTL_MASK
-			       | DAC_PDWN);
-	ulData            |= 0x2;
-	OUTREG(DAC_CNTL, ulData);
-
-	mdelay(1);
-
-	ulData     = INREG(DAC_CNTL);
-	connected =  (DAC_CMP_OUTPUT & ulData) ? 1 : 0;
-  
-	ulData    = ulOrigVCLK_ECP_CNTL;
-	ulMask    = 0xFFFFFFFFL;
-	OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);
-
-	OUTREG(DAC_CNTL,      ulOrigDAC_CNTL     );
-	OUTREG(DAC_EXT_CNTL,  ulOrigDAC_EXT_CNTL );
-	OUTREG(CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);
-    }
-
-    return connected ? MT_CRT : MT_NONE;
-}
-
-/*
- * Parse the "monitor_layout" string if any. This code is mostly
- * copied from XFree's radeon driver
- */
-static int radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
-				       const char *monitor_layout)
-{
-	char s1[5], s2[5];
-	int i = 0, second = 0;
-	const char *s;
-
-	if (!monitor_layout)
-		return 0;
-
-	s = monitor_layout;
-	do {
-		switch(*s) {
-		case ',':
-			s1[i] = '\0';
-			i = 0;
-			second = 1;
-			break;
-		case ' ':
-		case '\0':
-			break;
-		default:
-			if (i > 4)
-				break;
-			if (second)
-				s2[i] = *s;
-			else
-				s1[i] = *s;
-			i++;
-		}
-
-		if (i > 4)
-			i = 4;
-
-	} while (*s++);
-	if (second)
-		s2[i] = 0;
-	else {
-		s1[i] = 0;
-		s2[0] = 0;
-	}
-	if (strcmp(s1, "CRT") == 0)
-		rinfo->mon1_type = MT_CRT;
-	else if (strcmp(s1, "TMDS") == 0)
-		rinfo->mon1_type = MT_DFP;
-	else if (strcmp(s1, "LVDS") == 0)
-		rinfo->mon1_type = MT_LCD;
-
-	if (strcmp(s2, "CRT") == 0)
-		rinfo->mon2_type = MT_CRT;
-	else if (strcmp(s2, "TMDS") == 0)
-		rinfo->mon2_type = MT_DFP;
-	else if (strcmp(s2, "LVDS") == 0)
-		rinfo->mon2_type = MT_LCD;
-
-	return 1;
-}
-
-/*
- * Probe display on both primary and secondary card's connector (if any)
- * by various available techniques (i2c, OF device tree, BIOS, ...) and
- * try to retrieve EDID. The algorithm here comes from XFree's radeon
- * driver
- */
-void radeon_probe_screens(struct radeonfb_info *rinfo,
-			  const char *monitor_layout, int ignore_edid)
-{
-#ifdef CONFIG_FB_RADEON_I2C
-	int ddc_crt2_used = 0;	
-#endif
-	int tmp, i;
-
-	radeon_parse_connector_info(rinfo);
-
-	if (radeon_parse_monitor_layout(rinfo, monitor_layout)) {
-
-		/*
-		 * If user specified a monitor_layout option, use it instead
-		 * of auto-detecting. Maybe we should only use this argument
-		 * on the first radeon card probed or provide a way to specify
-		 * a layout for each card ?
-		 */
-
-		pr_debug("Using specified monitor layout: %s", monitor_layout);
-#ifdef CONFIG_FB_RADEON_I2C
-		if (!ignore_edid) {
-			if (rinfo->mon1_type != MT_NONE)
-				if (!radeon_probe_i2c_connector(rinfo, ddc_dvi, &rinfo->mon1_EDID)) {
-					radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon1_EDID);
-					ddc_crt2_used = 1;
-				}
-			if (rinfo->mon2_type != MT_NONE)
-				if (!radeon_probe_i2c_connector(rinfo, ddc_vga, &rinfo->mon2_EDID) &&
-				    !ddc_crt2_used)
-					radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon2_EDID);
-		}
-#endif /* CONFIG_FB_RADEON_I2C */
-		if (rinfo->mon1_type == MT_NONE) {
-			if (rinfo->mon2_type != MT_NONE) {
-				rinfo->mon1_type = rinfo->mon2_type;
-				rinfo->mon1_EDID = rinfo->mon2_EDID;
-			} else {
-				rinfo->mon1_type = MT_CRT;
-				printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n");
-			}
-			rinfo->mon2_type = MT_NONE;
-			rinfo->mon2_EDID = NULL;
-		}
-	} else {
-		/*
-		 * Auto-detecting display type (well... trying to ...)
-		 */
-		
-		pr_debug("Starting monitor auto detection...\n");
-
-#if defined(DEBUG) && defined(CONFIG_FB_RADEON_I2C)
-		{
-			u8 *EDIDs[4] = { NULL, NULL, NULL, NULL };
-			int mon_types[4] = {MT_NONE, MT_NONE, MT_NONE, MT_NONE};
-			int i;
-
-			for (i = 0; i < 4; i++)
-				mon_types[i] = radeon_probe_i2c_connector(rinfo,
-									  i+1, &EDIDs[i]);
-		}
-#endif /* DEBUG */
-		/*
-		 * Old single head cards
-		 */
-		if (!rinfo->has_CRTC2) {
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-			if (rinfo->mon1_type == MT_NONE)
-				rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
-									&rinfo->mon1_EDID);
-#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
-#ifdef CONFIG_FB_RADEON_I2C
-			if (rinfo->mon1_type == MT_NONE)
-				rinfo->mon1_type =
-					radeon_probe_i2c_connector(rinfo, ddc_dvi,
-								   &rinfo->mon1_EDID);
-			if (rinfo->mon1_type == MT_NONE)
-				rinfo->mon1_type =
-					radeon_probe_i2c_connector(rinfo, ddc_vga,
-								   &rinfo->mon1_EDID);
-			if (rinfo->mon1_type == MT_NONE)
-				rinfo->mon1_type =
-					radeon_probe_i2c_connector(rinfo, ddc_crt2,
-								   &rinfo->mon1_EDID);	
-#endif /* CONFIG_FB_RADEON_I2C */
-			if (rinfo->mon1_type == MT_NONE)
-				rinfo->mon1_type = MT_CRT;
-			goto bail;
-		}
-
-		/*
-		 * Check for cards with reversed DACs or TMDS controllers using BIOS
-		 */
-		if (rinfo->bios_seg &&
-		    (tmp = BIOS_IN16(rinfo->fp_bios_start + 0x50))) {
-			for (i = 1; i < 4; i++) {
-				unsigned int tmp0;
-
-				if (!BIOS_IN8(tmp + i*2) && i > 1)
-					break;
-				tmp0 = BIOS_IN16(tmp + i*2);
-				if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0x0f) == ddc_dvi)) {
-					rinfo->reversed_DAC = 1;
-					printk(KERN_INFO "radeonfb: Reversed DACs detected\n");
-				}
-				if ((((tmp0 >> 8) & 0x0f) == ddc_dvi) && ((tmp0 >> 4) & 0x01)) {
-					rinfo->reversed_TMDS = 1;
-					printk(KERN_INFO "radeonfb: Reversed TMDS detected\n");
-				}
-			}
-		}
-
-		/*
-		 * Probe primary head (DVI or laptop internal panel)
-		 */
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-		if (rinfo->mon1_type == MT_NONE)
-			rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
-								&rinfo->mon1_EDID);
-#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
-#ifdef CONFIG_FB_RADEON_I2C
-		if (rinfo->mon1_type == MT_NONE)
-			rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
-								      &rinfo->mon1_EDID);
-		if (rinfo->mon1_type == MT_NONE) {
-			rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
-								      &rinfo->mon1_EDID);
-			if (rinfo->mon1_type != MT_NONE)
-				ddc_crt2_used = 1;
-		}
-#endif /* CONFIG_FB_RADEON_I2C */
-		if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility &&
-		    ((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4))
-		     || (INREG(LVDS_GEN_CNTL) & LVDS_ON))) {
-			rinfo->mon1_type = MT_LCD;
-			printk("Non-DDC laptop panel detected\n");
-		}
-		if (rinfo->mon1_type == MT_NONE)
-			rinfo->mon1_type = radeon_crt_is_connected(rinfo, rinfo->reversed_DAC);
-
-		/*
-		 * Probe secondary head (mostly VGA, can be DVI)
-		 */
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-		if (rinfo->mon2_type == MT_NONE)
-			rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1,
-								&rinfo->mon2_EDID);
-#endif /* CONFIG_PPC_OF || defined(CONFIG_SPARC) */
-#ifdef CONFIG_FB_RADEON_I2C
-		if (rinfo->mon2_type == MT_NONE)
-			rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_vga,
-								      &rinfo->mon2_EDID);
-		if (rinfo->mon2_type == MT_NONE && !ddc_crt2_used)
-			rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
-								      &rinfo->mon2_EDID);
-#endif /* CONFIG_FB_RADEON_I2C */
-		if (rinfo->mon2_type == MT_NONE)
-			rinfo->mon2_type = radeon_crt_is_connected(rinfo, !rinfo->reversed_DAC);
-
-		/*
-		 * If we only detected port 2, we swap them, if none detected,
-		 * assume CRT (maybe fallback to old BIOS_SCRATCH stuff ? or look
-		 * at FP registers ?)
-		 */
-		if (rinfo->mon1_type == MT_NONE) {
-			if (rinfo->mon2_type != MT_NONE) {
-				rinfo->mon1_type = rinfo->mon2_type;
-				rinfo->mon1_EDID = rinfo->mon2_EDID;
-			} else
-				rinfo->mon1_type = MT_CRT;
-			rinfo->mon2_type = MT_NONE;
-			rinfo->mon2_EDID = NULL;
-		}
-
-		/*
-		 * Deal with reversed TMDS
-		 */
-		if (rinfo->reversed_TMDS) {
-			/* Always keep internal TMDS as primary head */
-			if (rinfo->mon1_type == MT_DFP || rinfo->mon2_type == MT_DFP) {
-				int tmp_type = rinfo->mon1_type;
-				u8 *tmp_EDID = rinfo->mon1_EDID;
-				rinfo->mon1_type = rinfo->mon2_type;
-				rinfo->mon1_EDID = rinfo->mon2_EDID;
-				rinfo->mon2_type = tmp_type;
-				rinfo->mon2_EDID = tmp_EDID;
-				if (rinfo->mon1_type == MT_CRT || rinfo->mon2_type == MT_CRT)
-					rinfo->reversed_DAC ^= 1;
-			}
-		}
-	}
-	if (ignore_edid) {
-		kfree(rinfo->mon1_EDID);
-		rinfo->mon1_EDID = NULL;
-		kfree(rinfo->mon2_EDID);
-		rinfo->mon2_EDID = NULL;
-	}
-
- bail:
-	printk(KERN_INFO "radeonfb: Monitor 1 type %s found\n",
-	       radeon_get_mon_name(rinfo->mon1_type));
-	if (rinfo->mon1_EDID)
-		printk(KERN_INFO "radeonfb: EDID probed\n");
-	if (!rinfo->has_CRTC2)
-		return;
-	printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n",
-	       radeon_get_mon_name(rinfo->mon2_type));
-	if (rinfo->mon2_EDID)
-		printk(KERN_INFO "radeonfb: EDID probed\n");
-}
-
-
-/*
- * This functions applyes any arch/model/machine specific fixups
- * to the panel info. It may eventually alter EDID block as
- * well or whatever is specific to a given model and not probed
- * properly by the default code
- */
-static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
-{
-#ifdef CONFIG_PPC_OF
-	/*
-	 * LCD Flat panels should use fixed dividers, we enfore that on
-	 * PPC only for now...
-	 */
-	if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
-	    && rinfo->is_mobility) {
-		int ppll_div_sel;
-		u32 ppll_divn;
-		ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
-		radeon_pll_errata_after_index(rinfo);
-		ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
-		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
-		rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff;
-		rinfo->panel_info.post_divider = (ppll_divn >> 16) & 0x7;
-		rinfo->panel_info.use_bios_dividers = 1;
-
-		printk(KERN_DEBUG "radeonfb: Using Firmware dividers 0x%08x "
-		       "from PPLL %d\n",
-		       rinfo->panel_info.fbk_divider |
-		       (rinfo->panel_info.post_divider << 16),
-		       ppll_div_sel);
-	}
-#endif /* CONFIG_PPC_OF */
-}
-
-
-/*
- * Fill up panel infos from a mode definition, either returned by the EDID
- * or from the default mode when we can't do any better
- */
-static void radeon_var_to_panel_info(struct radeonfb_info *rinfo, struct fb_var_screeninfo *var)
-{
-	rinfo->panel_info.xres = var->xres;
-	rinfo->panel_info.yres = var->yres;
-	rinfo->panel_info.clock = 100000000 / var->pixclock;
-	rinfo->panel_info.hOver_plus = var->right_margin;
-	rinfo->panel_info.hSync_width = var->hsync_len;
-       	rinfo->panel_info.hblank = var->left_margin +
-		(var->right_margin + var->hsync_len);
-	rinfo->panel_info.vOver_plus = var->lower_margin;
-	rinfo->panel_info.vSync_width = var->vsync_len;
-       	rinfo->panel_info.vblank = var->upper_margin +
-		(var->lower_margin + var->vsync_len);
-	rinfo->panel_info.hAct_high =
-		(var->sync & FB_SYNC_HOR_HIGH_ACT) != 0;
-	rinfo->panel_info.vAct_high =
-		(var->sync & FB_SYNC_VERT_HIGH_ACT) != 0;
-	rinfo->panel_info.valid = 1;
-	/* We use a default of 200ms for the panel power delay, 
-	 * I need to have a real schedule() instead of mdelay's in the panel code.
-	 * we might be possible to figure out a better power delay either from
-	 * MacOS OF tree or from the EDID block (proprietary extensions ?)
-	 */
-	rinfo->panel_info.pwr_delay = 200;
-}
-
-static void radeon_videomode_to_var(struct fb_var_screeninfo *var,
-				    const struct fb_videomode *mode)
-{
-	var->xres = mode->xres;
-	var->yres = mode->yres;
-	var->xres_virtual = mode->xres;
-	var->yres_virtual = mode->yres;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->pixclock = mode->pixclock;
-	var->left_margin = mode->left_margin;
-	var->right_margin = mode->right_margin;
-	var->upper_margin = mode->upper_margin;
-	var->lower_margin = mode->lower_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
-	var->sync = mode->sync;
-	var->vmode = mode->vmode;
-}
-
-#ifdef CONFIG_PPC_PSERIES
-static int is_powerblade(const char *model)
-{
-	struct device_node *root;
-	const char* cp;
-	int len, l, rc = 0;
-
-	root = of_find_node_by_path("/");
-	if (root && model) {
-		l = strlen(model);
-		cp = of_get_property(root, "model", &len);
-		if (cp)
-			rc = memcmp(model, cp, min(len, l)) == 0;
-		of_node_put(root);
-	}
-	return rc;
-}
-#endif
-
-/*
- * Build the modedb for head 1 (head 2 will come later), check panel infos
- * from either BIOS or EDID, and pick up the default mode
- */
-void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option)
-{
-	struct fb_info * info = rinfo->info;
-	int has_default_mode = 0;
-
-	/*
-	 * Fill default var first
-	 */
-	info->var = radeonfb_default_var;
-	INIT_LIST_HEAD(&info->modelist);
-
-	/*
-	 * First check out what BIOS has to say
-	 */
-	if (rinfo->mon1_type == MT_LCD)
-		radeon_get_panel_info_BIOS(rinfo);
-
-	/*
-	 * Parse EDID detailed timings and deduce panel infos if any. Right now
-	 * we only deal with first entry returned by parse_EDID, we may do better
-	 * some day...
-	 */
-	if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type != MT_CRT
-	    && rinfo->mon1_EDID) {
-		struct fb_var_screeninfo var;
-		pr_debug("Parsing EDID data for panel info\n");
-		if (fb_parse_edid(rinfo->mon1_EDID, &var) == 0) {
-			if (var.xres >= rinfo->panel_info.xres &&
-			    var.yres >= rinfo->panel_info.yres)
-				radeon_var_to_panel_info(rinfo, &var);
-		}
-	}
-
-	/*
-	 * Do any additional platform/arch fixups to the panel infos
-	 */
-	radeon_fixup_panel_info(rinfo);
-
-	/*
-	 * If we have some valid panel infos, we setup the default mode based on
-	 * those
-	 */
-	if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) {
-		struct fb_var_screeninfo *var = &info->var;
-
-		pr_debug("Setting up default mode based on panel info\n");
-		var->xres = rinfo->panel_info.xres;
-		var->yres = rinfo->panel_info.yres;
-		var->xres_virtual = rinfo->panel_info.xres;
-		var->yres_virtual = rinfo->panel_info.yres;
-		var->xoffset = var->yoffset = 0;
-		var->bits_per_pixel = 8;
-		var->pixclock = 100000000 / rinfo->panel_info.clock;
-		var->left_margin = (rinfo->panel_info.hblank - rinfo->panel_info.hOver_plus
-				    - rinfo->panel_info.hSync_width);
-		var->right_margin = rinfo->panel_info.hOver_plus;
-		var->upper_margin = (rinfo->panel_info.vblank - rinfo->panel_info.vOver_plus
-				     - rinfo->panel_info.vSync_width);
-		var->lower_margin = rinfo->panel_info.vOver_plus;
-		var->hsync_len = rinfo->panel_info.hSync_width;
-		var->vsync_len = rinfo->panel_info.vSync_width;
-		var->sync = 0;
-		if (rinfo->panel_info.hAct_high)
-			var->sync |= FB_SYNC_HOR_HIGH_ACT;
-		if (rinfo->panel_info.vAct_high)
-			var->sync |= FB_SYNC_VERT_HIGH_ACT;
-		var->vmode = 0;
-		has_default_mode = 1;
-	}
-
-	/*
-	 * Now build modedb from EDID
-	 */
-	if (rinfo->mon1_EDID) {
-		fb_edid_to_monspecs(rinfo->mon1_EDID, &info->monspecs);
-		fb_videomode_to_modelist(info->monspecs.modedb,
-					 info->monspecs.modedb_len,
-					 &info->modelist);
-		rinfo->mon1_modedb = info->monspecs.modedb;
-		rinfo->mon1_dbsize = info->monspecs.modedb_len;
-	}
-
-	
-	/*
-	 * Finally, if we don't have panel infos we need to figure some (or
-	 * we try to read it from card), we try to pick a default mode
-	 * and create some panel infos. Whatever...
-	 */
-	if (rinfo->mon1_type != MT_CRT && !rinfo->panel_info.valid) {
-		struct fb_videomode	*modedb;
-		int			dbsize;
-		char			modename[32];
-
-		pr_debug("Guessing panel info...\n");
-		if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
-			u32 tmp = INREG(FP_HORZ_STRETCH) & HORZ_PANEL_SIZE;
-			rinfo->panel_info.xres = ((tmp >> HORZ_PANEL_SHIFT) + 1) * 8;
-			tmp = INREG(FP_VERT_STRETCH) & VERT_PANEL_SIZE;
-			rinfo->panel_info.yres = (tmp >> VERT_PANEL_SHIFT) + 1;
-		}
-		if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
-			printk(KERN_WARNING "radeonfb: Can't find panel size, going back to CRT\n");
-			rinfo->mon1_type = MT_CRT;
-			goto pickup_default;
-		}
-		printk(KERN_WARNING "radeonfb: Assuming panel size %dx%d\n",
-		       rinfo->panel_info.xres, rinfo->panel_info.yres);
-		modedb = rinfo->mon1_modedb;
-		dbsize = rinfo->mon1_dbsize;
-		snprintf(modename, 31, "%dx%d", rinfo->panel_info.xres, rinfo->panel_info.yres);
-		if (fb_find_mode(&info->var, info, modename,
-				 modedb, dbsize, NULL, 8) == 0) {
-			printk(KERN_WARNING "radeonfb: Can't find mode for panel size, going back to CRT\n");
-			rinfo->mon1_type = MT_CRT;
-			goto pickup_default;
-		}
-		has_default_mode = 1;
-		radeon_var_to_panel_info(rinfo, &info->var);
-	}
-
- pickup_default:
-	/*
-	 * Apply passed-in mode option if any
-	 */
-	if (mode_option) {
-		if (fb_find_mode(&info->var, info, mode_option,
-				 info->monspecs.modedb,
-				 info->monspecs.modedb_len, NULL, 8) != 0)
-			has_default_mode = 1;
- 	}
-
-#ifdef CONFIG_PPC_PSERIES
-	if (!has_default_mode && (
-		is_powerblade("IBM,8842") || /* JS20 */
-		is_powerblade("IBM,8844") || /* JS21 */
-		is_powerblade("IBM,7998") || /* JS12/JS21/JS22 */
-		is_powerblade("IBM,0792") || /* QS21 */
-		is_powerblade("IBM,0793")    /* QS22 */
-	    )) {
-		printk("Falling back to 800x600 on JSxx hardware\n");
-		if (fb_find_mode(&info->var, info, "800x600@60",
-				 info->monspecs.modedb,
-				 info->monspecs.modedb_len, NULL, 8) != 0)
-			has_default_mode = 1;
-	}
-#endif
-
-	/*
-	 * Still no mode, let's pick up a default from the db
-	 */
-	if (!has_default_mode && info->monspecs.modedb != NULL) {
-		struct fb_monspecs *specs = &info->monspecs;
-		struct fb_videomode *modedb = NULL;
-
-		/* get preferred timing */
-		if (specs->misc & FB_MISC_1ST_DETAIL) {
-			int i;
-
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-					modedb = &specs->modedb[i];
-					break;
-				}
-			}
-		} else {
-			/* otherwise, get first mode in database */
-			modedb = &specs->modedb[0];
-		}
-		if (modedb != NULL) {
-			info->var.bits_per_pixel = 8;
-			radeon_videomode_to_var(&info->var, modedb);
-			has_default_mode = 1;
-		}
-	}
-	if (1) {
-		struct fb_videomode mode;
-		/* Make sure that whatever mode got selected is actually in the
-		 * modelist or the kernel may die
-		 */
-		fb_var_to_videomode(&mode, &info->var);
-		fb_add_videomode(&mode, &info->modelist);
-	}
-}
-
-/*
- * The code below is used to pick up a mode in check_var and
- * set_var. It should be made generic
- */
-
-/*
- * This is used when looking for modes. We assign a "distance" value
- * to a mode in the modedb depending how "close" it is from what we
- * are looking for.
- * Currently, we don't compare that much, we could do better but
- * the current fbcon doesn't quite mind ;)
- */
-static int radeon_compare_modes(const struct fb_var_screeninfo *var,
-				const struct fb_videomode *mode)
-{
-	int distance = 0;
-
-	distance = mode->yres - var->yres;
-	distance += (mode->xres - var->xres)/2;
-	return distance;
-}
-
-/*
- * This function is called by check_var, it gets the passed in mode parameter, and
- * outputs a valid mode matching the passed-in one as closely as possible.
- * We need something better ultimately. Things like fbcon basically pass us out
- * current mode with xres/yres hacked, while things like XFree will actually
- * produce a full timing that we should respect as much as possible.
- *
- * This is why I added the FB_ACTIVATE_FIND that is used by fbcon. Without this,
- * we do a simple spec match, that's all. With it, we actually look for a mode in
- * either our monitor modedb or the vesa one if none
- *
- */
-int  radeon_match_mode(struct radeonfb_info *rinfo,
-		       struct fb_var_screeninfo *dest,
-		       const struct fb_var_screeninfo *src)
-{
-	const struct fb_videomode	*db = vesa_modes;
-	int				i, dbsize = 34;
-	int				has_rmx, native_db = 0;
-	int				distance = INT_MAX;
-	const struct fb_videomode	*candidate = NULL;
-
-	/* Start with a copy of the requested mode */
-	memcpy(dest, src, sizeof(struct fb_var_screeninfo));
-
-	/* Check if we have a modedb built from EDID */
-	if (rinfo->mon1_modedb) {
-		db = rinfo->mon1_modedb;
-		dbsize = rinfo->mon1_dbsize;
-		native_db = 1;
-	}
-
-	/* Check if we have a scaler allowing any fancy mode */
-	has_rmx = rinfo->mon1_type == MT_LCD || rinfo->mon1_type == MT_DFP;
-
-	/* If we have a scaler and are passed FB_ACTIVATE_TEST or
-	 * FB_ACTIVATE_NOW, just do basic checking and return if the
-	 * mode match
-	 */
-	if ((src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST ||
-	    (src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		/* We don't have an RMX, validate timings. If we don't have
-	 	 * monspecs, we should be paranoid and not let use go above
-		 * 640x480-60, but I assume userland knows what it's doing here
-		 * (though I may be proven wrong...)
-		 */
-		if (has_rmx == 0 && rinfo->mon1_modedb)
-			if (fb_validate_mode((struct fb_var_screeninfo *)src, rinfo->info))
-				return -EINVAL;
-		return 0;
-	}
-
-	/* Now look for a mode in the database */
-	while (db) {
-		for (i = 0; i < dbsize; i++) {
-			int d;
-
-			if (db[i].yres < src->yres)
-				continue;	
-			if (db[i].xres < src->xres)
-				continue;
-			d = radeon_compare_modes(src, &db[i]);
-			/* If the new mode is at least as good as the previous one,
-			 * then it's our new candidate
-			 */
-			if (d < distance) {
-				candidate = &db[i];
-				distance = d;
-			}
-		}
-		db = NULL;
-		/* If we have a scaler, we allow any mode from the database */
-		if (native_db && has_rmx) {
-			db = vesa_modes;
-			dbsize = 34;
-			native_db = 0;
-		}
-	}
-
-	/* If we have found a match, return it */
-	if (candidate != NULL) {
-		radeon_videomode_to_var(dest, candidate);
-		return 0;
-	}
-
-	/* If we haven't and don't have a scaler, fail */
-	if (!has_rmx)
-		return -EINVAL;
-
-	return 0;
-}
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
deleted file mode 100644
index 46a12f1a93c3..000000000000
--- a/drivers/video/aty/radeon_pm.c
+++ /dev/null
@@ -1,2906 +0,0 @@
-/*
- *	drivers/video/aty/radeon_pm.c
- *
- *	Copyright 2003,2004 Ben. Herrenschmidt <benh@kernel.crashing.org>
- *	Copyright 2004 Paul Mackerras <paulus@samba.org>
- *
- *	This is the power management code for ATI radeon chipsets. It contains
- *	some dynamic clock PM enable/disable code similar to what X.org does,
- *	some D2-state (APM-style) sleep/wakeup code for use on some PowerMacs,
- *	and the necessary bits to re-initialize from scratch a few chips found
- *	on PowerMacs as well. The later could be extended to more platforms
- *	provided the memory controller configuration code be made more generic,
- *	and you can get the proper mode register commands for your RAMs.
- *	Those things may be found in the BIOS image...
- */
-
-#include "radeonfb.h"
-
-#include <linux/console.h>
-#include <linux/agp_backend.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/pmac_feature.h>
-#endif
-
-#include "ati_ids.h"
-
-/*
- * Workarounds for bugs in PC laptops:
- * - enable D2 sleep in some IBM Thinkpads
- * - special case for Samsung P35
- *
- * Whitelist by subsystem vendor/device because
- * its the subsystem vendor's fault!
- */
-
-#if defined(CONFIG_PM) && defined(CONFIG_X86)
-static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
-
-struct radeon_device_id {
-        const char *ident;                     /* (arbitrary) Name */
-        const unsigned short subsystem_vendor; /* Subsystem Vendor ID */
-        const unsigned short subsystem_device; /* Subsystem Device ID */
-	const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */
-	const reinit_function_ptr new_reinit_func;   /* changed reinit_func */
-};
-
-#define BUGFIX(model, sv, sd, pm, fn) { \
-	.ident = model, \
-	.subsystem_vendor = sv, \
-	.subsystem_device = sd, \
-	.pm_mode_modifier = pm, \
-	.new_reinit_func  = fn  \
-}
-
-static struct radeon_device_id radeon_workaround_list[] = {
-	BUGFIX("IBM Thinkpad R32",
-	       PCI_VENDOR_ID_IBM, 0x1905,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad R40",
-	       PCI_VENDOR_ID_IBM, 0x0526,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad R40",
-	       PCI_VENDOR_ID_IBM, 0x0527,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad R50/R51/T40/T41",
-	       PCI_VENDOR_ID_IBM, 0x0531,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad R51/T40/T41/T42",
-	       PCI_VENDOR_ID_IBM, 0x0530,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad T30",
-	       PCI_VENDOR_ID_IBM, 0x0517,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad T40p",
-	       PCI_VENDOR_ID_IBM, 0x054d,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad T42",
-	       PCI_VENDOR_ID_IBM, 0x0550,
-	       radeon_pm_d2, NULL),
-	BUGFIX("IBM Thinkpad X31/X32",
-	       PCI_VENDOR_ID_IBM, 0x052f,
-	       radeon_pm_d2, NULL),
-	BUGFIX("Samsung P35",
-	       PCI_VENDOR_ID_SAMSUNG, 0xc00c,
-	       radeon_pm_off, radeon_reinitialize_M10),
-	BUGFIX("Acer Aspire 2010",
-	       PCI_VENDOR_ID_AI, 0x0061,
-	       radeon_pm_off, radeon_reinitialize_M10),
-	BUGFIX("Acer Travelmate 290D/292LMi",
-	       PCI_VENDOR_ID_AI, 0x005a,
-	       radeon_pm_off, radeon_reinitialize_M10),
-	{ .ident = NULL }
-};
-
-static int radeon_apply_workarounds(struct radeonfb_info *rinfo)
-{
-	struct radeon_device_id *id;
-
-	for (id = radeon_workaround_list; id->ident != NULL; id++ )
-		if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) &&
-		    (id->subsystem_device == rinfo->pdev->subsystem_device )) {
-
-			/* we found a device that requires workaround */
-			printk(KERN_DEBUG "radeonfb: %s detected"
-			       ", enabling workaround\n", id->ident);
-
-			rinfo->pm_mode |= id->pm_mode_modifier;
-
-			if (id->new_reinit_func != NULL)
-				rinfo->reinit_func = id->new_reinit_func;
-
-			return 1;
-		}
-	return 0;  /* not found */
-}
-
-#else  /* defined(CONFIG_PM) && defined(CONFIG_X86) */
-static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo)
-{
-        return 0;
-}
-#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */
-
-
-
-static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
-{
-	u32 tmp;
-
-	/* RV100 */
-	if ((rinfo->family == CHIP_FAMILY_RV100) && (!rinfo->is_mobility)) {
-		if (rinfo->has_CRTC2) {
-			tmp = INPLL(pllSCLK_CNTL);
-			tmp &= ~SCLK_CNTL__DYN_STOP_LAT_MASK;
-			tmp |= SCLK_CNTL__CP_MAX_DYN_STOP_LAT | SCLK_CNTL__FORCEON_MASK;
-			OUTPLL(pllSCLK_CNTL, tmp);
-		}
-		tmp = INPLL(pllMCLK_CNTL);
-		tmp |= (MCLK_CNTL__FORCE_MCLKA |
-		        MCLK_CNTL__FORCE_MCLKB |
-		        MCLK_CNTL__FORCE_YCLKA |
-		        MCLK_CNTL__FORCE_YCLKB |
-			MCLK_CNTL__FORCE_AIC |
-			MCLK_CNTL__FORCE_MC);
-                OUTPLL(pllMCLK_CNTL, tmp);
-		return;
-	}
-	/* R100 */
-	if (!rinfo->has_CRTC2) {
-                tmp = INPLL(pllSCLK_CNTL);
-                tmp |= (SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_HDP	|
-			SCLK_CNTL__FORCE_DISP1	| SCLK_CNTL__FORCE_TOP	|
-                        SCLK_CNTL__FORCE_E2	| SCLK_CNTL__FORCE_SE 	|
-			SCLK_CNTL__FORCE_IDCT	| SCLK_CNTL__FORCE_VIP	|
-			SCLK_CNTL__FORCE_RE	| SCLK_CNTL__FORCE_PB 	|
-			SCLK_CNTL__FORCE_TAM	| SCLK_CNTL__FORCE_TDM	|
-                        SCLK_CNTL__FORCE_RB);
-                OUTPLL(pllSCLK_CNTL, tmp);
-		return;
-	}
-	/* RV350 (M10/M11) */
-	if (rinfo->family == CHIP_FAMILY_RV350) {
-                /* for RV350/M10/M11, no delays are required. */
-                tmp = INPLL(pllSCLK_CNTL2);
-                tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
-                        SCLK_CNTL2__R300_FORCE_GA  |
-			SCLK_CNTL2__R300_FORCE_CBA);
-                OUTPLL(pllSCLK_CNTL2, tmp);
-
-                tmp = INPLL(pllSCLK_CNTL);
-                tmp |= (SCLK_CNTL__FORCE_DISP2		| SCLK_CNTL__FORCE_CP		|
-                        SCLK_CNTL__FORCE_HDP		| SCLK_CNTL__FORCE_DISP1	|
-                        SCLK_CNTL__FORCE_TOP		| SCLK_CNTL__FORCE_E2		|
-                        SCLK_CNTL__R300_FORCE_VAP	| SCLK_CNTL__FORCE_IDCT    	|
-			SCLK_CNTL__FORCE_VIP		| SCLK_CNTL__R300_FORCE_SR	|
-			SCLK_CNTL__R300_FORCE_PX	| SCLK_CNTL__R300_FORCE_TX	|
-			SCLK_CNTL__R300_FORCE_US	| SCLK_CNTL__FORCE_TV_SCLK	|
-                        SCLK_CNTL__R300_FORCE_SU	| SCLK_CNTL__FORCE_OV0);
-                OUTPLL(pllSCLK_CNTL, tmp);
-
-                tmp = INPLL(pllSCLK_MORE_CNTL);
-		tmp |= (SCLK_MORE_CNTL__FORCE_DISPREGS	| SCLK_MORE_CNTL__FORCE_MC_GUI	|
-			SCLK_MORE_CNTL__FORCE_MC_HOST);
-                OUTPLL(pllSCLK_MORE_CNTL, tmp);
-
-		tmp = INPLL(pllMCLK_CNTL);
-		tmp |= (MCLK_CNTL__FORCE_MCLKA |
-		        MCLK_CNTL__FORCE_MCLKB |
-		        MCLK_CNTL__FORCE_YCLKA |
-		        MCLK_CNTL__FORCE_YCLKB |
-			MCLK_CNTL__FORCE_MC);
-                OUTPLL(pllMCLK_CNTL, tmp);
-
-                tmp = INPLL(pllVCLK_ECP_CNTL);
-                tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb  |
-                         VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb |
-			 VCLK_ECP_CNTL__R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
-                OUTPLL(pllVCLK_ECP_CNTL, tmp);
-
-                tmp = INPLL(pllPIXCLKS_CNTL);
-                tmp &= ~(PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb	|
-			 PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb	|
-			 PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb	|
-			 PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb	|
-			 PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb		|
-			 PIXCLKS_CNTL__R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
-                OUTPLL(pllPIXCLKS_CNTL, tmp);
-
-		return;
-	}
-	
-	/* Default */
-
-	/* Force Core Clocks */
-	tmp = INPLL(pllSCLK_CNTL);
-	tmp |= (SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_E2);
-
-	/* XFree doesn't do that case, but we had this code from Apple and it
-	 * seem necessary for proper suspend/resume operations
-	 */
-	if (rinfo->is_mobility) {
-		tmp |= 	SCLK_CNTL__FORCE_HDP|
-			SCLK_CNTL__FORCE_DISP1|
-			SCLK_CNTL__FORCE_DISP2|
-			SCLK_CNTL__FORCE_TOP|
-			SCLK_CNTL__FORCE_SE|
-			SCLK_CNTL__FORCE_IDCT|
-			SCLK_CNTL__FORCE_VIP|
-			SCLK_CNTL__FORCE_PB|
-			SCLK_CNTL__FORCE_RE|
-			SCLK_CNTL__FORCE_TAM|
-			SCLK_CNTL__FORCE_TDM|
-			SCLK_CNTL__FORCE_RB|
-			SCLK_CNTL__FORCE_TV_SCLK|
-			SCLK_CNTL__FORCE_SUBPIC|
-			SCLK_CNTL__FORCE_OV0;
-	}
-	else if (rinfo->family == CHIP_FAMILY_R300 ||
-		   rinfo->family == CHIP_FAMILY_R350) {
-		tmp |=  SCLK_CNTL__FORCE_HDP   |
-			SCLK_CNTL__FORCE_DISP1 |
-			SCLK_CNTL__FORCE_DISP2 |
-			SCLK_CNTL__FORCE_TOP   |
-			SCLK_CNTL__FORCE_IDCT  |
-			SCLK_CNTL__FORCE_VIP;
-	}
-    	OUTPLL(pllSCLK_CNTL, tmp);
-	radeon_msleep(16);
-
-	if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
-		tmp = INPLL(pllSCLK_CNTL2);
-		tmp |=  SCLK_CNTL2__R300_FORCE_TCL |
-			SCLK_CNTL2__R300_FORCE_GA  |
-			SCLK_CNTL2__R300_FORCE_CBA;
-		OUTPLL(pllSCLK_CNTL2, tmp);
-		radeon_msleep(16);
-	}
-
-	tmp = INPLL(pllCLK_PIN_CNTL);
-	tmp &= ~CLK_PIN_CNTL__SCLK_DYN_START_CNTL;
-	OUTPLL(pllCLK_PIN_CNTL, tmp);
-	radeon_msleep(15);
-
-	if (rinfo->is_IGP) {
-		/* Weird  ... X is _un_ forcing clocks here, I think it's
-		 * doing backward. Imitate it for now...
-		 */
-		tmp = INPLL(pllMCLK_CNTL);
-		tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
-			 MCLK_CNTL__FORCE_YCLKA);
-		OUTPLL(pllMCLK_CNTL, tmp);
-		radeon_msleep(16);
-	}
-	/* Hrm... same shit, X doesn't do that but I have to */
-	else if (rinfo->is_mobility) {
-		tmp = INPLL(pllMCLK_CNTL);
-		tmp |= (MCLK_CNTL__FORCE_MCLKA |
-			MCLK_CNTL__FORCE_MCLKB |
-			MCLK_CNTL__FORCE_YCLKA |
-			MCLK_CNTL__FORCE_YCLKB);
-		OUTPLL(pllMCLK_CNTL, tmp);
-		radeon_msleep(16);
-
-		tmp = INPLL(pllMCLK_MISC);
-		tmp &= 	~(MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT|
-			  MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT|
-			  MCLK_MISC__MC_MCLK_DYN_ENABLE|
-			  MCLK_MISC__IO_MCLK_DYN_ENABLE);
-		OUTPLL(pllMCLK_MISC, tmp);
-		radeon_msleep(15);
-	}
-
-	if (rinfo->is_mobility) {
-		tmp = INPLL(pllSCLK_MORE_CNTL);
-		tmp |= 	SCLK_MORE_CNTL__FORCE_DISPREGS|
-			SCLK_MORE_CNTL__FORCE_MC_GUI|
-			SCLK_MORE_CNTL__FORCE_MC_HOST;
-		OUTPLL(pllSCLK_MORE_CNTL, tmp);
-		radeon_msleep(16);
-	}
-
-	tmp = INPLL(pllPIXCLKS_CNTL);
-	tmp &= ~(PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb |
-		 PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
-		 PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb |
-		 PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
-		 PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb|
-		 PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb|
-		 PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb);
- 	OUTPLL(pllPIXCLKS_CNTL, tmp);
-	radeon_msleep(16);
-
-	tmp = INPLL( pllVCLK_ECP_CNTL);
-	tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
-		 VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
-	OUTPLL( pllVCLK_ECP_CNTL, tmp);
-	radeon_msleep(16);
-}
-
-static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
-{
-	u32 tmp;
-
-	/* R100 */
-	if (!rinfo->has_CRTC2) {
-                tmp = INPLL(pllSCLK_CNTL);
-
-		if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
-                    tmp &= ~(SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_RB);
-                tmp &= ~(SCLK_CNTL__FORCE_HDP		| SCLK_CNTL__FORCE_DISP1 |
-			 SCLK_CNTL__FORCE_TOP		| SCLK_CNTL__FORCE_SE   |
-			 SCLK_CNTL__FORCE_IDCT		| SCLK_CNTL__FORCE_RE   |
-			 SCLK_CNTL__FORCE_PB		| SCLK_CNTL__FORCE_TAM  |
-			 SCLK_CNTL__FORCE_TDM);
-                OUTPLL(pllSCLK_CNTL, tmp);
-		return;
-	}
-
-	/* M10/M11 */
-	if (rinfo->family == CHIP_FAMILY_RV350) {
-		tmp = INPLL(pllSCLK_CNTL2);
-		tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
-			 SCLK_CNTL2__R300_FORCE_GA  |
-			 SCLK_CNTL2__R300_FORCE_CBA);
-		tmp |=  (SCLK_CNTL2__R300_TCL_MAX_DYN_STOP_LAT |
-			 SCLK_CNTL2__R300_GA_MAX_DYN_STOP_LAT  |
-			 SCLK_CNTL2__R300_CBA_MAX_DYN_STOP_LAT);
-		OUTPLL(pllSCLK_CNTL2, tmp);
-
-		tmp = INPLL(pllSCLK_CNTL);
-		tmp &= ~(SCLK_CNTL__FORCE_DISP2 | SCLK_CNTL__FORCE_CP      |
-			 SCLK_CNTL__FORCE_HDP   | SCLK_CNTL__FORCE_DISP1   |
-			 SCLK_CNTL__FORCE_TOP   | SCLK_CNTL__FORCE_E2      |
-			 SCLK_CNTL__R300_FORCE_VAP | SCLK_CNTL__FORCE_IDCT |
-			 SCLK_CNTL__FORCE_VIP   | SCLK_CNTL__R300_FORCE_SR |
-			 SCLK_CNTL__R300_FORCE_PX | SCLK_CNTL__R300_FORCE_TX |
-			 SCLK_CNTL__R300_FORCE_US | SCLK_CNTL__FORCE_TV_SCLK |
-			 SCLK_CNTL__R300_FORCE_SU | SCLK_CNTL__FORCE_OV0);
-		tmp |= SCLK_CNTL__DYN_STOP_LAT_MASK;
-		OUTPLL(pllSCLK_CNTL, tmp);
-
-		tmp = INPLL(pllSCLK_MORE_CNTL);
-		tmp &= ~SCLK_MORE_CNTL__FORCEON;
-		tmp |=  SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT |
-			SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT |
-			SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT;
-		OUTPLL(pllSCLK_MORE_CNTL, tmp);
-
-		tmp = INPLL(pllVCLK_ECP_CNTL);
-		tmp |= (VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
-			VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
-		OUTPLL(pllVCLK_ECP_CNTL, tmp);
-
-		tmp = INPLL(pllPIXCLKS_CNTL);
-		tmp |= (PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb         |
-			PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb     |
-			PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
-			PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb            |
-			PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb    |
-			PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb       |
-			PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb        |
-			PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb     |
-			PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb     |
-			PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb      |
-			PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb        |
-			PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb           |
-			PIXCLKS_CNTL__R300_P2G2CLK_DAC_ALWAYS_ONb);
-		OUTPLL(pllPIXCLKS_CNTL, tmp);
-
-		tmp = INPLL(pllMCLK_MISC);
-		tmp |= (MCLK_MISC__MC_MCLK_DYN_ENABLE |
-			MCLK_MISC__IO_MCLK_DYN_ENABLE);
-		OUTPLL(pllMCLK_MISC, tmp);
-
-		tmp = INPLL(pllMCLK_CNTL);
-		tmp |= (MCLK_CNTL__FORCE_MCLKA | MCLK_CNTL__FORCE_MCLKB);
-		tmp &= ~(MCLK_CNTL__FORCE_YCLKA  |
-			 MCLK_CNTL__FORCE_YCLKB  |
-			 MCLK_CNTL__FORCE_MC);
-
-		/* Some releases of vbios have set DISABLE_MC_MCLKA
-		 * and DISABLE_MC_MCLKB bits in the vbios table.  Setting these
-		 * bits will cause H/W hang when reading video memory with dynamic
-		 * clocking enabled.
-		 */
-		if ((tmp & MCLK_CNTL__R300_DISABLE_MC_MCLKA) &&
-		    (tmp & MCLK_CNTL__R300_DISABLE_MC_MCLKB)) {
-			/* If both bits are set, then check the active channels */
-			tmp = INPLL(pllMCLK_CNTL);
-			if (rinfo->vram_width == 64) {
-			    if (INREG(MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY)
-				tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKB;
-			    else
-				tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKA;
-			} else {
-			    tmp &= ~(MCLK_CNTL__R300_DISABLE_MC_MCLKA |
-				     MCLK_CNTL__R300_DISABLE_MC_MCLKB);
-			}
-		}
-		OUTPLL(pllMCLK_CNTL, tmp);
-		return;
-	}
-
-	/* R300 */
-	if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
-		tmp = INPLL(pllSCLK_CNTL);
-		tmp &= ~(SCLK_CNTL__R300_FORCE_VAP);
-		tmp |= SCLK_CNTL__FORCE_CP;
-		OUTPLL(pllSCLK_CNTL, tmp);
-		radeon_msleep(15);
-
-		tmp = INPLL(pllSCLK_CNTL2);
-		tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
-			 SCLK_CNTL2__R300_FORCE_GA  |
-			 SCLK_CNTL2__R300_FORCE_CBA);
-		OUTPLL(pllSCLK_CNTL2, tmp);
-	}
-
-	/* Others */
-
-	tmp = INPLL( pllCLK_PWRMGT_CNTL);
-	tmp &= ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK|
-		 CLK_PWRMGT_CNTL__DISP_DYN_STOP_LAT_MASK|
-		 CLK_PWRMGT_CNTL__DYN_STOP_MODE_MASK);
-	tmp |= CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE_MASK |
-	       (0x01 << CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT__SHIFT);
-	OUTPLL( pllCLK_PWRMGT_CNTL, tmp);
-	radeon_msleep(15);
-
-	tmp = INPLL(pllCLK_PIN_CNTL);
-	tmp |= CLK_PIN_CNTL__SCLK_DYN_START_CNTL;
-	OUTPLL(pllCLK_PIN_CNTL, tmp);
-	radeon_msleep(15);
-
-	/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
-	 * to lockup randomly, leave them as set by BIOS.
-	 */
-	tmp = INPLL(pllSCLK_CNTL);
-	tmp &= ~SCLK_CNTL__FORCEON_MASK;
-
-	/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
-	if ((rinfo->family == CHIP_FAMILY_RV250 &&
-	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
-	    ((rinfo->family == CHIP_FAMILY_RV100) &&
-	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
-		tmp |= SCLK_CNTL__FORCE_CP;
-		tmp |= SCLK_CNTL__FORCE_VIP;
-	}
-	OUTPLL(pllSCLK_CNTL, tmp);
-	radeon_msleep(15);
-
-	if ((rinfo->family == CHIP_FAMILY_RV200) ||
-	    (rinfo->family == CHIP_FAMILY_RV250) ||
-	    (rinfo->family == CHIP_FAMILY_RV280)) {
-		tmp = INPLL(pllSCLK_MORE_CNTL);
-		tmp &= ~SCLK_MORE_CNTL__FORCEON;
-
-		/* RV200::A11 A12 RV250::A11 A12 */
-		if (((rinfo->family == CHIP_FAMILY_RV200) ||
-		     (rinfo->family == CHIP_FAMILY_RV250)) &&
-		    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
-			tmp |= SCLK_MORE_CNTL__FORCEON;
-
-		OUTPLL(pllSCLK_MORE_CNTL, tmp);
-		radeon_msleep(15);
-	}
-	
-
-	/* RV200::A11 A12, RV250::A11 A12 */
-	if (((rinfo->family == CHIP_FAMILY_RV200) ||
-	     (rinfo->family == CHIP_FAMILY_RV250)) &&
-	    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
-		tmp = INPLL(pllPLL_PWRMGT_CNTL);
-		tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
-		OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
-		radeon_msleep(15);
-	}
-
-	tmp = INPLL(pllPIXCLKS_CNTL);
-	tmp |=  PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb |
-		PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb|
-		PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
-		PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb|
-		PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb|
-		PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
-		PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb;
-	OUTPLL(pllPIXCLKS_CNTL, tmp);
-	radeon_msleep(15);
-		
-	tmp = INPLL(pllVCLK_ECP_CNTL);
-	tmp |=  VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
-		VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb;
-	OUTPLL(pllVCLK_ECP_CNTL, tmp);
-
-	/* X doesn't do that ... hrm, we do on mobility && Macs */
-#ifdef CONFIG_PPC_OF
-	if (rinfo->is_mobility) {
-		tmp  = INPLL(pllMCLK_CNTL);
-		tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
-			 MCLK_CNTL__FORCE_MCLKB |
-			 MCLK_CNTL__FORCE_YCLKA |
-			 MCLK_CNTL__FORCE_YCLKB);
-		OUTPLL(pllMCLK_CNTL, tmp);
-		radeon_msleep(15);
-
-		tmp = INPLL(pllMCLK_MISC);
-		tmp |= 	MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT|
-			MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT|
-			MCLK_MISC__MC_MCLK_DYN_ENABLE|
-			MCLK_MISC__IO_MCLK_DYN_ENABLE;
-		OUTPLL(pllMCLK_MISC, tmp);
-		radeon_msleep(15);
-	}
-#endif /* CONFIG_PPC_OF */
-}
-
-#ifdef CONFIG_PM
-
-static void OUTMC( struct radeonfb_info *rinfo, u8 indx, u32 value)
-{
-	OUTREG( MC_IND_INDEX, indx | MC_IND_INDEX__MC_IND_WR_EN);	
-	OUTREG( MC_IND_DATA, value);		
-}
-
-static u32 INMC(struct radeonfb_info *rinfo, u8 indx)
-{
-	OUTREG( MC_IND_INDEX, indx);					
-	return INREG( MC_IND_DATA);
-}
-
-static void radeon_pm_save_regs(struct radeonfb_info *rinfo, int saving_for_d3)
-{
-	rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL);
-	rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL);
-	rinfo->save_regs[2] = INPLL(MCLK_CNTL);
-	rinfo->save_regs[3] = INPLL(SCLK_CNTL);
-	rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL);
-	rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL);
-	rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL);
-	rinfo->save_regs[7] = INPLL(MCLK_MISC);
-	rinfo->save_regs[8] = INPLL(P2PLL_CNTL);
-	
-	rinfo->save_regs[9] = INREG(DISP_MISC_CNTL);
-	rinfo->save_regs[10] = INREG(DISP_PWR_MAN);
-	rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL);
-	rinfo->save_regs[13] = INREG(TV_DAC_CNTL);
-	rinfo->save_regs[14] = INREG(BUS_CNTL1);
-	rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL);
-	rinfo->save_regs[16] = INREG(AGP_CNTL);
-	rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000;
-	rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000;
-	rinfo->save_regs[19] = INREG(GPIOPAD_A);
-	rinfo->save_regs[20] = INREG(GPIOPAD_EN);
-	rinfo->save_regs[21] = INREG(GPIOPAD_MASK);
-	rinfo->save_regs[22] = INREG(ZV_LCDPAD_A);
-	rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN);
-	rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK);
-	rinfo->save_regs[25] = INREG(GPIO_VGA_DDC);
-	rinfo->save_regs[26] = INREG(GPIO_DVI_DDC);
-	rinfo->save_regs[27] = INREG(GPIO_MONID);
-	rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC);
-
-	rinfo->save_regs[29] = INREG(SURFACE_CNTL);
-	rinfo->save_regs[30] = INREG(MC_FB_LOCATION);
-	rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR);
-	rinfo->save_regs[32] = INREG(MC_AGP_LOCATION);
-	rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR);
-
-	rinfo->save_regs[34] = INPLL(SCLK_MORE_CNTL);
-	rinfo->save_regs[35] = INREG(MEM_SDRAM_MODE_REG);
-	rinfo->save_regs[36] = INREG(BUS_CNTL);
-	rinfo->save_regs[39] = INREG(RBBM_CNTL);
-	rinfo->save_regs[40] = INREG(DAC_CNTL);
-	rinfo->save_regs[41] = INREG(HOST_PATH_CNTL);
-	rinfo->save_regs[37] = INREG(MPP_TB_CONFIG);
-	rinfo->save_regs[38] = INREG(FCP_CNTL);
-
-	if (rinfo->is_mobility) {
-		rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL);
-		rinfo->save_regs[43] = INPLL(pllSSPLL_CNTL);
-		rinfo->save_regs[44] = INPLL(pllSSPLL_REF_DIV);
-		rinfo->save_regs[45] = INPLL(pllSSPLL_DIV_0);
-		rinfo->save_regs[90] = INPLL(pllSS_INT_CNTL);
-		rinfo->save_regs[91] = INPLL(pllSS_TST_CNTL);
-		rinfo->save_regs[81] = INREG(LVDS_GEN_CNTL);
-	}
-
-	if (rinfo->family >= CHIP_FAMILY_RV200) {
-		rinfo->save_regs[42] = INREG(MEM_REFRESH_CNTL);
-		rinfo->save_regs[46] = INREG(MC_CNTL);
-		rinfo->save_regs[47] = INREG(MC_INIT_GFX_LAT_TIMER);
-		rinfo->save_regs[48] = INREG(MC_INIT_MISC_LAT_TIMER);
-		rinfo->save_regs[49] = INREG(MC_TIMING_CNTL);
-		rinfo->save_regs[50] = INREG(MC_READ_CNTL_AB);
-		rinfo->save_regs[51] = INREG(MC_IOPAD_CNTL);
-		rinfo->save_regs[52] = INREG(MC_CHIP_IO_OE_CNTL_AB);
-		rinfo->save_regs[53] = INREG(MC_DEBUG);
-	}
-	rinfo->save_regs[54] = INREG(PAMAC0_DLY_CNTL);
-	rinfo->save_regs[55] = INREG(PAMAC1_DLY_CNTL);
-	rinfo->save_regs[56] = INREG(PAD_CTLR_MISC);
-	rinfo->save_regs[57] = INREG(FW_CNTL);
-
-	if (rinfo->family >= CHIP_FAMILY_R300) {
-		rinfo->save_regs[58] = INMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER);
-		rinfo->save_regs[59] = INMC(rinfo, ixR300_MC_IMP_CNTL);
-		rinfo->save_regs[60] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0);
-		rinfo->save_regs[61] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1);
-		rinfo->save_regs[62] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0);
-		rinfo->save_regs[63] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1);
-		rinfo->save_regs[64] = INMC(rinfo, ixR300_MC_BIST_CNTL_3);
-		rinfo->save_regs[65] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0);
-		rinfo->save_regs[66] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1);
-		rinfo->save_regs[67] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0);
-		rinfo->save_regs[68] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1);
-		rinfo->save_regs[69] = INMC(rinfo, ixR300_MC_DEBUG_CNTL);
-		rinfo->save_regs[70] = INMC(rinfo, ixR300_MC_DLL_CNTL);
-		rinfo->save_regs[71] = INMC(rinfo, ixR300_MC_IMP_CNTL_0);
-		rinfo->save_regs[72] = INMC(rinfo, ixR300_MC_ELPIDA_CNTL);
-		rinfo->save_regs[96] = INMC(rinfo, ixR300_MC_READ_CNTL_CD);
-	} else {
-		rinfo->save_regs[59] = INMC(rinfo, ixMC_IMP_CNTL);
-		rinfo->save_regs[65] = INMC(rinfo, ixMC_CHP_IO_CNTL_A0);
-		rinfo->save_regs[66] = INMC(rinfo, ixMC_CHP_IO_CNTL_A1);
-		rinfo->save_regs[67] = INMC(rinfo, ixMC_CHP_IO_CNTL_B0);
-		rinfo->save_regs[68] = INMC(rinfo, ixMC_CHP_IO_CNTL_B1);
-		rinfo->save_regs[71] = INMC(rinfo, ixMC_IMP_CNTL_0);
-	}
-
-	rinfo->save_regs[73] = INPLL(pllMPLL_CNTL);
-	rinfo->save_regs[74] = INPLL(pllSPLL_CNTL);
-	rinfo->save_regs[75] = INPLL(pllMPLL_AUX_CNTL);
-	rinfo->save_regs[76] = INPLL(pllSPLL_AUX_CNTL);
-	rinfo->save_regs[77] = INPLL(pllM_SPLL_REF_FB_DIV);
-	rinfo->save_regs[78] = INPLL(pllAGP_PLL_CNTL);
-	rinfo->save_regs[79] = INREG(PAMAC2_DLY_CNTL);
-
-	rinfo->save_regs[80] = INREG(OV0_BASE_ADDR);
-	rinfo->save_regs[82] = INREG(FP_GEN_CNTL);
-	rinfo->save_regs[83] = INREG(FP2_GEN_CNTL);
-	rinfo->save_regs[84] = INREG(TMDS_CNTL);
-	rinfo->save_regs[85] = INREG(TMDS_TRANSMITTER_CNTL);
-	rinfo->save_regs[86] = INREG(DISP_OUTPUT_CNTL);
-	rinfo->save_regs[87] = INREG(DISP_HW_DEBUG);
-	rinfo->save_regs[88] = INREG(TV_MASTER_CNTL);
-	rinfo->save_regs[89] = INPLL(pllP2PLL_REF_DIV);
-	rinfo->save_regs[92] = INPLL(pllPPLL_DIV_0);
-	rinfo->save_regs[93] = INPLL(pllPPLL_CNTL);
-	rinfo->save_regs[94] = INREG(GRPH_BUFFER_CNTL);
-	rinfo->save_regs[95] = INREG(GRPH2_BUFFER_CNTL);
-	rinfo->save_regs[96] = INREG(HDP_DEBUG);
-	rinfo->save_regs[97] = INPLL(pllMDLL_CKO);
-	rinfo->save_regs[98] = INPLL(pllMDLL_RDCKA);
-	rinfo->save_regs[99] = INPLL(pllMDLL_RDCKB);
-}
-
-static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
-{
-	OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */
-	
-	OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
-	OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
-	OUTPLL(MCLK_CNTL, rinfo->save_regs[2]);
-	OUTPLL(SCLK_CNTL, rinfo->save_regs[3]);
-	OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
-	OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]);
-	OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]);
-	OUTPLL(MCLK_MISC, rinfo->save_regs[7]);
-	if (rinfo->family == CHIP_FAMILY_RV350)
-		OUTPLL(SCLK_MORE_CNTL, rinfo->save_regs[34]);
-
-	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
-	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
-	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
-	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
-	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
-	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
-
-	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
-	OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
-	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]);
-	OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]);
-	OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]);
-	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
-	OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]);
-	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
-	OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]);
-	OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]);
-	OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]);
-
-	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
-	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
-	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
-	OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]);
-	OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]);
-	OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]);
-	OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]);
-	OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]);
-	OUTREG(GPIO_MONID, rinfo->save_regs[27]);
-	OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]);
-}
-
-static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo)
-{		
-	OUTREG(GPIOPAD_MASK, 0x0001ffff);
-	OUTREG(GPIOPAD_EN, 0x00000400);
-	OUTREG(GPIOPAD_A, 0x00000000);		
-        OUTREG(ZV_LCDPAD_MASK, 0x00000000);
-        OUTREG(ZV_LCDPAD_EN, 0x00000000);
-      	OUTREG(ZV_LCDPAD_A, 0x00000000); 	
-	OUTREG(GPIO_VGA_DDC, 0x00030000);
-	OUTREG(GPIO_DVI_DDC, 0x00000000);
-	OUTREG(GPIO_MONID, 0x00030000);
-	OUTREG(GPIO_CRT2_DDC, 0x00000000);
-}
-
-static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
-{
-	/* Set v2clk to 65MHz */
-	if (rinfo->family <= CHIP_FAMILY_RV280) {
-		OUTPLL(pllPIXCLKS_CNTL,
-			 __INPLL(rinfo, pllPIXCLKS_CNTL)
-			 & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
-	 
-		OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
-		OUTPLL(pllP2PLL_CNTL, 0x0000bf00);
-	} else {
-		OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
-		INPLL(pllP2PLL_REF_DIV);
-		OUTPLL(pllP2PLL_CNTL, 0x0000a700);
-	}
-
-	OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W);
-	
-	OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP);
-	mdelay(1);
-
-	OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET);
-	mdelay( 1);
-
-  	OUTPLL(pllPIXCLKS_CNTL,
-  		(INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK)
-  		| (0x03 << PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT));
-	mdelay( 1);	
-}
-
-static void radeon_pm_low_current(struct radeonfb_info *rinfo)
-{
-	u32 reg;
-
-	reg  = INREG(BUS_CNTL1);
-	if (rinfo->family <= CHIP_FAMILY_RV280) {
-		reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
-		reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
-	} else {
-		reg |= 0x4080;
-	}
-	OUTREG(BUS_CNTL1, reg);
-	
-	reg  = INPLL(PLL_PWRMGT_CNTL);
-	reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF |
-		PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF;
-	reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
-	reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU;
-	OUTPLL(PLL_PWRMGT_CNTL, reg);
-	
-	reg  = INREG(TV_DAC_CNTL);
-	reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK);
-	reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD |
-		TV_DAC_CNTL_BDACPD |
-		(8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT);
-	OUTREG(TV_DAC_CNTL, reg);
-	
-	reg  = INREG(TMDS_TRANSMITTER_CNTL);
-	reg &= ~(TMDS_PLL_EN | TMDS_PLLRST);
-	OUTREG(TMDS_TRANSMITTER_CNTL, reg);
-
-	reg = INREG(DAC_CNTL);
-	reg &= ~DAC_CMP_EN;
-	OUTREG(DAC_CNTL, reg);
-
-	reg = INREG(DAC_CNTL2);
-	reg &= ~DAC2_CMP_EN;
-	OUTREG(DAC_CNTL2, reg);
-	
-	reg  = INREG(TV_DAC_CNTL);
-	reg &= ~TV_DAC_CNTL_DETECT;
-	OUTREG(TV_DAC_CNTL, reg);
-}
-
-static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
-{
-
-	u32 sclk_cntl, mclk_cntl, sclk_more_cntl;
-
-	u32 pll_pwrmgt_cntl;
-	u32 clk_pwrmgt_cntl;
-	u32 clk_pin_cntl;
-	u32 vclk_ecp_cntl; 
-	u32 pixclks_cntl;
-	u32 disp_mis_cntl;
-	u32 disp_pwr_man;
-	u32 tmp;
-	
-	/* Force Core Clocks */
-	sclk_cntl = INPLL( pllSCLK_CNTL);
-	sclk_cntl |= 	SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT|
-			SCLK_CNTL__VIP_MAX_DYN_STOP_LAT|
-			SCLK_CNTL__RE_MAX_DYN_STOP_LAT|
-			SCLK_CNTL__PB_MAX_DYN_STOP_LAT|
-			SCLK_CNTL__TAM_MAX_DYN_STOP_LAT|
-			SCLK_CNTL__TDM_MAX_DYN_STOP_LAT|
-			SCLK_CNTL__RB_MAX_DYN_STOP_LAT|
-			
-			SCLK_CNTL__FORCE_DISP2|
-			SCLK_CNTL__FORCE_CP|
-			SCLK_CNTL__FORCE_HDP|
-			SCLK_CNTL__FORCE_DISP1|
-			SCLK_CNTL__FORCE_TOP|
-			SCLK_CNTL__FORCE_E2|
-			SCLK_CNTL__FORCE_SE|
-			SCLK_CNTL__FORCE_IDCT|
-			SCLK_CNTL__FORCE_VIP|
-			
-			SCLK_CNTL__FORCE_PB|
-			SCLK_CNTL__FORCE_TAM|
-			SCLK_CNTL__FORCE_TDM|
-			SCLK_CNTL__FORCE_RB|
-			SCLK_CNTL__FORCE_TV_SCLK|
-			SCLK_CNTL__FORCE_SUBPIC|
-			SCLK_CNTL__FORCE_OV0;
-	if (rinfo->family <= CHIP_FAMILY_RV280)
-		sclk_cntl |= SCLK_CNTL__FORCE_RE;
-	else
-		sclk_cntl |= SCLK_CNTL__SE_MAX_DYN_STOP_LAT |
-			SCLK_CNTL__E2_MAX_DYN_STOP_LAT |
-			SCLK_CNTL__TV_MAX_DYN_STOP_LAT |
-			SCLK_CNTL__HDP_MAX_DYN_STOP_LAT |
-			SCLK_CNTL__CP_MAX_DYN_STOP_LAT;
-
-	OUTPLL( pllSCLK_CNTL, sclk_cntl);
-
-	sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL);
-	sclk_more_cntl |= 	SCLK_MORE_CNTL__FORCE_DISPREGS |
-				SCLK_MORE_CNTL__FORCE_MC_GUI |
-				SCLK_MORE_CNTL__FORCE_MC_HOST;
-
-	OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl);		
-
-	
-	mclk_cntl = INPLL( pllMCLK_CNTL);
-	mclk_cntl &= ~(	MCLK_CNTL__FORCE_MCLKA |
-			MCLK_CNTL__FORCE_MCLKB |
-			MCLK_CNTL__FORCE_YCLKA |
-			MCLK_CNTL__FORCE_YCLKB |
-			MCLK_CNTL__FORCE_MC
-		      );	
-    	OUTPLL( pllMCLK_CNTL, mclk_cntl);
-	
-	/* Force Display clocks	*/
-	vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL);
-	vclk_ecp_cntl &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb
-			   | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
-	vclk_ecp_cntl |= VCLK_ECP_CNTL__ECP_FORCE_ON;
-	OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl);
-	
-	
-	pixclks_cntl = INPLL( pllPIXCLKS_CNTL);
-	pixclks_cntl &= ~(	PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | 
-				PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
-				PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb |
-				PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
-				PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb|
-				PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb|
-				PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb);
-						
- 	OUTPLL( pllPIXCLKS_CNTL, pixclks_cntl);
-
-	/* Switch off LVDS interface */
-	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) &
-	       ~(LVDS_BLON | LVDS_EN | LVDS_ON | LVDS_DIGON));
-
-	/* Enable System power management */
-	pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL);
-	
-	pll_pwrmgt_cntl |= 	PLL_PWRMGT_CNTL__SPLL_TURNOFF |
-				PLL_PWRMGT_CNTL__MPLL_TURNOFF|
-				PLL_PWRMGT_CNTL__PPLL_TURNOFF|
-				PLL_PWRMGT_CNTL__P2PLL_TURNOFF|
-				PLL_PWRMGT_CNTL__TVPLL_TURNOFF;
-						
-	OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl);
-	
-	clk_pwrmgt_cntl	 = INPLL( pllCLK_PWRMGT_CNTL);
-	
-	clk_pwrmgt_cntl &= ~(	CLK_PWRMGT_CNTL__MPLL_PWRMGT_OFF|
-				CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF|
-				CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF|
-				CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF|
-				CLK_PWRMGT_CNTL__MCLK_TURNOFF|
-				CLK_PWRMGT_CNTL__SCLK_TURNOFF|
-				CLK_PWRMGT_CNTL__PCLK_TURNOFF|
-				CLK_PWRMGT_CNTL__P2CLK_TURNOFF|
-				CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF|
-				CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN|
-				CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE|
-				CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK|
-				CLK_PWRMGT_CNTL__CG_NO1_DEBUG_MASK
-			);
-						
-	clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN
-		| CLK_PWRMGT_CNTL__DISP_PM;
-	
-	OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl);
-	
-	clk_pin_cntl = INPLL( pllCLK_PIN_CNTL);
-	
-	clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND;
-
-	/* because both INPLL and OUTPLL take the same lock, that's why. */
-	tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND;
-	OUTPLL( pllMCLK_MISC, tmp);
-
-	/* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset
-	 * and radeon chip dependent. Thus we only enable it on Mac for
-	 * now (until we get more info on how to compute the correct
-	 * value for various X86 bridges).
-	 */
-#ifdef CONFIG_PPC_PMAC
-	if (machine_is(powermac)) {
-		/* AGP PLL control */
-		if (rinfo->family <= CHIP_FAMILY_RV280) {
-			OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
-			OUTREG(BUS_CNTL1,
-			       (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
-			       | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));	// 440BX
-		} else {
-			OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
-			OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
-		}
-	}
-#endif
-
-	OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL)
-				  & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
-	
-	clk_pin_cntl &= ~CLK_PIN_CNTL__CG_CLK_TO_OUTPIN;
-	clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb;	
-	OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl);
-
-	/* Solano2M */
-	OUTREG(AGP_CNTL,
-		(INREG(AGP_CNTL) & ~(AGP_CNTL__MAX_IDLE_CLK_MASK))
-		| (0x20<<AGP_CNTL__MAX_IDLE_CLK__SHIFT));
-
-	/* ACPI mode */
-	/* because both INPLL and OUTPLL take the same lock, that's why. */
-	tmp = INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL;
-	OUTPLL( pllPLL_PWRMGT_CNTL, tmp);
-
-
-	disp_mis_cntl = INREG(DISP_MISC_CNTL);
-	
-	disp_mis_cntl &= ~(	DISP_MISC_CNTL__SOFT_RESET_GRPH_PP | 
-				DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP | 
-				DISP_MISC_CNTL__SOFT_RESET_OV0_PP |
-				DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK|
-				DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK|
-				DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK|
-				DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP|
-				DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK|
-				DISP_MISC_CNTL__SOFT_RESET_LVDS|
-				DISP_MISC_CNTL__SOFT_RESET_TMDS|
-				DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS|
-				DISP_MISC_CNTL__SOFT_RESET_TV);
-	
-	OUTREG(DISP_MISC_CNTL, disp_mis_cntl);
-						
-	disp_pwr_man = INREG(DISP_PWR_MAN);
-	
-	disp_pwr_man &= ~(	DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN	| 
-				DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN |
-				DISP_PWR_MAN__DISP_PWR_MAN_DPMS_MASK|
-				DISP_PWR_MAN__DISP_D3_RST|
-				DISP_PWR_MAN__DISP_D3_REG_RST
-				);
-	
-	disp_pwr_man |= DISP_PWR_MAN__DISP_D3_GRPH_RST|
-					DISP_PWR_MAN__DISP_D3_SUBPIC_RST|
-					DISP_PWR_MAN__DISP_D3_OV0_RST|
-					DISP_PWR_MAN__DISP_D1D2_GRPH_RST|
-					DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST|
-					DISP_PWR_MAN__DISP_D1D2_OV0_RST|
-					DISP_PWR_MAN__DIG_TMDS_ENABLE_RST|
-					DISP_PWR_MAN__TV_ENABLE_RST| 
-//					DISP_PWR_MAN__AUTO_PWRUP_EN|
-					0;
-	
-	OUTREG(DISP_PWR_MAN, disp_pwr_man);					
-							
-	clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL);
-	pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL) ;
-	clk_pin_cntl 	= INPLL( pllCLK_PIN_CNTL);
-	disp_pwr_man	= INREG(DISP_PWR_MAN);
-		
-	
-	/* D2 */
-	clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__DISP_PM;
-	pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__MOBILE_SU | PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK;
-	clk_pin_cntl	|= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb;
-	disp_pwr_man 	&= ~(DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN_MASK
-			     | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN_MASK);
-
-	OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl);
-	OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl);
-	OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl);
-	OUTREG(DISP_PWR_MAN, disp_pwr_man);
-
-	/* disable display request & disable display */
-	OUTREG( CRTC_GEN_CNTL, (INREG( CRTC_GEN_CNTL) & ~CRTC_GEN_CNTL__CRTC_EN)
-		| CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B);
-	OUTREG( CRTC2_GEN_CNTL, (INREG( CRTC2_GEN_CNTL) & ~CRTC2_GEN_CNTL__CRTC2_EN)
-		| CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B);
-
-	mdelay(17);				   
-
-}
-
-static void radeon_pm_yclk_mclk_sync(struct radeonfb_info *rinfo)
-{
-	u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1;
-
-	mc_chp_io_cntl_a1 = INMC( rinfo, ixMC_CHP_IO_CNTL_A1)
-		& ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK;
-	mc_chp_io_cntl_b1 = INMC( rinfo, ixMC_CHP_IO_CNTL_B1)
-		& ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK;
-
-	OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1
-	       | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT));
-	OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1
-	       | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT));
-
-	OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1);
-	OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1);
-
-	mdelay( 1);
-}
-
-static void radeon_pm_yclk_mclk_sync_m10(struct radeonfb_info *rinfo)
-{
-	u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1;
-
-	mc_chp_io_cntl_a1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1)
-		& ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK;
-	mc_chp_io_cntl_b1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1)
-		& ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK;
-
-	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1,
-	       mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT));
-	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1,
-	       mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT));
-
-	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1);
-	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1);
-
-	mdelay( 1);
-}
-
-static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value,
-				       u8 delay_required)
-{  
-	u32 mem_sdram_mode;
-
-	mem_sdram_mode  = INREG( MEM_SDRAM_MODE_REG);
-
-	mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK;
-	mem_sdram_mode |= (value<<MEM_SDRAM_MODE_REG__MEM_MODE_REG__SHIFT)
-		| MEM_SDRAM_MODE_REG__MEM_CFG_TYPE;
-	OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
-	if (delay_required >= 2)
-		mdelay(1);
-
-	mem_sdram_mode |=  MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET;
-	OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
-	if (delay_required >= 2)
-		mdelay(1);
-
-	mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET;
-	OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
-	if (delay_required >= 2)
-		mdelay(1);
-
-	if (delay_required) {
-		do {
-			if (delay_required >= 2)
-				mdelay(1);
-		} while ((INREG(MC_STATUS)
-			  & (MC_STATUS__MEM_PWRUP_COMPL_A |
-			     MC_STATUS__MEM_PWRUP_COMPL_B)) == 0);
-	}
-}
-
-static void radeon_pm_m10_program_mode_wait(struct radeonfb_info *rinfo)
-{
-	int cnt;
-
-	for (cnt = 0; cnt < 100; ++cnt) {
-		mdelay(1);
-		if (INREG(MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A
-					| MC_STATUS__MEM_PWRUP_COMPL_B))
-			break;
-	}
-}
-
-
-static void radeon_pm_enable_dll(struct radeonfb_info *rinfo)
-{  
-#define DLL_RESET_DELAY 	5
-#define DLL_SLEEP_DELAY		1
-
-	u32 cko = INPLL(pllMDLL_CKO)   | MDLL_CKO__MCKOA_SLEEP
-		| MDLL_CKO__MCKOA_RESET;
-	u32 cka = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP
-		| MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET
-		| MDLL_RDCKA__MRDCKA1_RESET;
-	u32 ckb = INPLL(pllMDLL_RDCKB) | MDLL_RDCKB__MRDCKB0_SLEEP
-		| MDLL_RDCKB__MRDCKB1_SLEEP | MDLL_RDCKB__MRDCKB0_RESET
-		| MDLL_RDCKB__MRDCKB1_RESET;
-
-	/* Setting up the DLL range for write */
-	OUTPLL(pllMDLL_CKO,   	cko);
-	OUTPLL(pllMDLL_RDCKA,  	cka);
-	OUTPLL(pllMDLL_RDCKB,	ckb);
-
-	mdelay(DLL_RESET_DELAY*2);
-
-	cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP);
-	OUTPLL(pllMDLL_CKO, cko);
-	mdelay(DLL_SLEEP_DELAY);
-	cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET);
-	OUTPLL(pllMDLL_CKO, cko);
-	mdelay(DLL_RESET_DELAY);
-
-	cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP);
-	OUTPLL(pllMDLL_RDCKA, cka);
-	mdelay(DLL_SLEEP_DELAY);
-	cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET);
-	OUTPLL(pllMDLL_RDCKA, cka);
-	mdelay(DLL_RESET_DELAY);
-
-	ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP);
-	OUTPLL(pllMDLL_RDCKB, ckb);
-	mdelay(DLL_SLEEP_DELAY);
-	ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET);
-	OUTPLL(pllMDLL_RDCKB, ckb);
-	mdelay(DLL_RESET_DELAY);
-
-
-#undef DLL_RESET_DELAY
-#undef DLL_SLEEP_DELAY
-}
-
-static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo)
-{
-	u32 dll_value;
-	u32 dll_sleep_mask = 0;
-	u32 dll_reset_mask = 0;
-	u32 mc;
-
-#define DLL_RESET_DELAY 	5
-#define DLL_SLEEP_DELAY		1
-
-	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
-	mc = INREG(MC_CNTL);
-	/* Check which channels are enabled */
-	switch (mc & 0x3) {
-	case 1:
-		if (mc & 0x4)
-			break;
-	case 2:
-		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP;
-		dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET;
-	case 0:
-		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP;
-		dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET;
-	}
-	switch (mc & 0x3) {
-	case 1:
-		if (!(mc & 0x4))
-			break;
-	case 2:
-		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP;
-		dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET;
-		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKC_SLEEP;
-		dll_reset_mask |= MDLL_R300_RDCK__MRDCKC_RESET;
-	}
-
-	dll_value = INPLL(pllMDLL_RDCKA);
-
-	/* Power Up */
-	dll_value &= ~(dll_sleep_mask);
-	OUTPLL(pllMDLL_RDCKA, dll_value);
-	mdelay( DLL_SLEEP_DELAY);  		
-
-	dll_value &= ~(dll_reset_mask);
-	OUTPLL(pllMDLL_RDCKA, dll_value);
-	mdelay( DLL_RESET_DELAY);  		
-
-#undef DLL_RESET_DELAY 
-#undef DLL_SLEEP_DELAY
-}
-
-
-static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
-{
-	u32 crtcGenCntl, crtcGenCntl2, memRefreshCntl, crtc_more_cntl,
-		fp_gen_cntl, fp2_gen_cntl;
- 
-	crtcGenCntl  = INREG( CRTC_GEN_CNTL);
-	crtcGenCntl2 = INREG( CRTC2_GEN_CNTL);
-
-	crtc_more_cntl 	= INREG( CRTC_MORE_CNTL);
-	fp_gen_cntl 	= INREG( FP_GEN_CNTL);
-	fp2_gen_cntl 	= INREG( FP2_GEN_CNTL);
- 
-
-	OUTREG( CRTC_MORE_CNTL, 0);
-	OUTREG( FP_GEN_CNTL, 0);
-	OUTREG( FP2_GEN_CNTL,0);
- 
-	OUTREG( CRTC_GEN_CNTL,  (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) );
-	OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
-  
-	/* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */
-	if (rinfo->family == CHIP_FAMILY_RV350) {
-		u32 sdram_mode_reg = rinfo->save_regs[35];
-		static const u32 default_mrtable[] =
-			{ 0x21320032,
-			  0x21321000, 0xa1321000, 0x21321000, 0xffffffff,
-			  0x21320032, 0xa1320032, 0x21320032, 0xffffffff,
-			  0x21321002, 0xa1321002, 0x21321002, 0xffffffff,
-			  0x21320132, 0xa1320132, 0x21320132, 0xffffffff,
-			  0x21320032, 0xa1320032, 0x21320032, 0xffffffff,
-			  0x31320032 };
-
-		const u32 *mrtable = default_mrtable;
-		int i, mrtable_size = ARRAY_SIZE(default_mrtable);
-
-		mdelay(30);
-
-		/* Disable refresh */
-		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
-			& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
-		OUTREG( MEM_REFRESH_CNTL, memRefreshCntl
-			| MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
-
-		/* Configure and enable M & SPLLs */
-       		radeon_pm_enable_dll_m10(rinfo);
-		radeon_pm_yclk_mclk_sync_m10(rinfo);
-
-#ifdef CONFIG_PPC_OF
-		if (rinfo->of_node != NULL) {
-			int size;
-
-			mrtable = of_get_property(rinfo->of_node, "ATY,MRT", &size);
-			if (mrtable)
-				mrtable_size = size >> 2;
-			else
-				mrtable = default_mrtable;
-		}
-#endif /* CONFIG_PPC_OF */
-
-		/* Program the SDRAM */
-		sdram_mode_reg = mrtable[0];
-		OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg);
-		for (i = 0; i < mrtable_size; i++) {
-			if (mrtable[i] == 0xffffffffu)
-				radeon_pm_m10_program_mode_wait(rinfo);
-			else {
-				sdram_mode_reg &= ~(MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK
-						    | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE
-						    | MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET);
-				sdram_mode_reg |= mrtable[i];
-
-				OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg);
-				mdelay(1);
-			}
-		}
-
-		/* Restore memory refresh */
-		OUTREG(MEM_REFRESH_CNTL, memRefreshCntl);
-		mdelay(30);
-
-	}
-	/* Here come the desktop RV200 "QW" card */
-	else if (!rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV200) {
-		/* Disable refresh */
-		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
-			& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
-		OUTREG(MEM_REFRESH_CNTL, memRefreshCntl
-		       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
-		mdelay(30);
-
-		/* Reset memory */
-		OUTREG(MEM_SDRAM_MODE_REG,
-		       INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-
-		radeon_pm_program_mode_reg(rinfo, 0x2002, 2);
-		radeon_pm_program_mode_reg(rinfo, 0x0132, 2);
-		radeon_pm_program_mode_reg(rinfo, 0x0032, 2);
-
-		OUTREG(MEM_SDRAM_MODE_REG,
-		       INREG(MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-
-		OUTREG( MEM_REFRESH_CNTL, 	memRefreshCntl);
-
-	}
-	/* The M6 */
-	else if (rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV100) {
-		/* Disable refresh */
-		memRefreshCntl = INREG(EXT_MEM_CNTL) & ~(1 << 20);
-		OUTREG( EXT_MEM_CNTL, memRefreshCntl | (1 << 20));
- 
-		/* Reset memory */
-		OUTREG( MEM_SDRAM_MODE_REG,
-			INREG( MEM_SDRAM_MODE_REG)
-			& ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-
-		/* DLL */
-		radeon_pm_enable_dll(rinfo);
-
-		/* MLCK / YCLK sync */
-		radeon_pm_yclk_mclk_sync(rinfo);
-
-		/* Program Mode Register */
-		radeon_pm_program_mode_reg(rinfo, 0x2000, 1);   
-		radeon_pm_program_mode_reg(rinfo, 0x2001, 1);   
-		radeon_pm_program_mode_reg(rinfo, 0x2002, 1);   
-		radeon_pm_program_mode_reg(rinfo, 0x0132, 1);   
-		radeon_pm_program_mode_reg(rinfo, 0x0032, 1); 
-
-		/* Complete & re-enable refresh */
-		OUTREG( MEM_SDRAM_MODE_REG,
-			INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-
-		OUTREG(EXT_MEM_CNTL, memRefreshCntl);
-	}
-	/* And finally, the M7..M9 models, including M9+ (RV280) */
-	else if (rinfo->is_mobility) {
-
-		/* Disable refresh */
-		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
-			& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
-		OUTREG( MEM_REFRESH_CNTL, memRefreshCntl
-			| MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
-
-		/* Reset memory */
-		OUTREG( MEM_SDRAM_MODE_REG,
-			INREG( MEM_SDRAM_MODE_REG)
-			& ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-
-		/* DLL */
-		radeon_pm_enable_dll(rinfo);
-
-		/* MLCK / YCLK sync */
-		radeon_pm_yclk_mclk_sync(rinfo);
-
-		/* M6, M7 and M9 so far ... */
-		if (rinfo->family <= CHIP_FAMILY_RV250) {
-			radeon_pm_program_mode_reg(rinfo, 0x2000, 1);
-			radeon_pm_program_mode_reg(rinfo, 0x2001, 1);
-			radeon_pm_program_mode_reg(rinfo, 0x2002, 1);
-			radeon_pm_program_mode_reg(rinfo, 0x0132, 1);
-			radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
-		}
-		/* M9+ (iBook G4) */
-		else if (rinfo->family == CHIP_FAMILY_RV280) {
-			radeon_pm_program_mode_reg(rinfo, 0x2000, 1);
-			radeon_pm_program_mode_reg(rinfo, 0x0132, 1);
-			radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
-		}
-
-		/* Complete & re-enable refresh */
-		OUTREG( MEM_SDRAM_MODE_REG,
-			INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-
-		OUTREG( MEM_REFRESH_CNTL, 	memRefreshCntl);
-	}
-
-	OUTREG( CRTC_GEN_CNTL, 		crtcGenCntl);
-	OUTREG( CRTC2_GEN_CNTL, 	crtcGenCntl2);
-	OUTREG( FP_GEN_CNTL, 		fp_gen_cntl);
-	OUTREG( FP2_GEN_CNTL, 		fp2_gen_cntl);
-
-	OUTREG( CRTC_MORE_CNTL, 	crtc_more_cntl);
-
-	mdelay( 15);
-}
-
-#if defined(CONFIG_PM)
-#if defined(CONFIG_X86) || defined(CONFIG_PPC_PMAC)
-static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo)
-{
-	u32 tmp, tmp2;
-	int i,j;
-
-	/* Reset the PAD_CTLR_STRENGTH & wait for it to be stable */
-	INREG(PAD_CTLR_STRENGTH);
-	OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~PAD_MANUAL_OVERRIDE);
-	tmp = INREG(PAD_CTLR_STRENGTH);
-	for (i = j = 0; i < 65; ++i) {
-		mdelay(1);
-		tmp2 = INREG(PAD_CTLR_STRENGTH);
-		if (tmp != tmp2) {
-			tmp = tmp2;
-			i = 0;
-			j++;
-			if (j > 10) {
-				printk(KERN_WARNING "radeon: PAD_CTLR_STRENGTH doesn't "
-				       "stabilize !\n");
-				break;
-			}
-		}
-	}
-}
-
-static void radeon_pm_all_ppls_off(struct radeonfb_info *rinfo)
-{
-	u32 tmp;
-
-	tmp = INPLL(pllPPLL_CNTL);
-	OUTPLL(pllPPLL_CNTL, tmp | 0x3);
-	tmp = INPLL(pllP2PLL_CNTL);
-	OUTPLL(pllP2PLL_CNTL, tmp | 0x3);
-	tmp = INPLL(pllSPLL_CNTL);
-	OUTPLL(pllSPLL_CNTL, tmp | 0x3);
-	tmp = INPLL(pllMPLL_CNTL);
-	OUTPLL(pllMPLL_CNTL, tmp | 0x3);
-}
-
-static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
-{
-	u32 tmp;
-
-	/* Switch SPLL to PCI source */
-	tmp = INPLL(pllSCLK_CNTL);
-	OUTPLL(pllSCLK_CNTL, tmp & ~SCLK_CNTL__SCLK_SRC_SEL_MASK);
-
-	/* Reconfigure SPLL charge pump, VCO gain, duty cycle */
-	tmp = INPLL(pllSPLL_CNTL);
-	OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
-	radeon_pll_errata_after_data(rinfo);
-
-	/* Set SPLL feedback divider */
-	tmp = INPLL(pllM_SPLL_REF_FB_DIV);
-	tmp = (tmp & 0xff00fffful) | (rinfo->save_regs[77] & 0x00ff0000ul);
-	OUTPLL(pllM_SPLL_REF_FB_DIV, tmp);
-
-	/* Power up SPLL */
-	tmp = INPLL(pllSPLL_CNTL);
-	OUTPLL(pllSPLL_CNTL, tmp & ~1);
-	(void)INPLL(pllSPLL_CNTL);
-
-	mdelay(10);
-
-	/* Release SPLL reset */
-	tmp = INPLL(pllSPLL_CNTL);
-	OUTPLL(pllSPLL_CNTL, tmp & ~0x2);
-	(void)INPLL(pllSPLL_CNTL);
-
-	mdelay(10);
-
-	/* Select SCLK source  */
-	tmp = INPLL(pllSCLK_CNTL);
-	tmp &= ~SCLK_CNTL__SCLK_SRC_SEL_MASK;
-	tmp |= rinfo->save_regs[3] & SCLK_CNTL__SCLK_SRC_SEL_MASK;
-	OUTPLL(pllSCLK_CNTL, tmp);
-	(void)INPLL(pllSCLK_CNTL);
-
-	mdelay(10);
-
-	/* Reconfigure MPLL charge pump, VCO gain, duty cycle */
-	tmp = INPLL(pllMPLL_CNTL);
-	OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
-	radeon_pll_errata_after_data(rinfo);
-
-	/* Set MPLL feedback divider */
-	tmp = INPLL(pllM_SPLL_REF_FB_DIV);
-	tmp = (tmp & 0xffff00fful) | (rinfo->save_regs[77] & 0x0000ff00ul);
-
-	OUTPLL(pllM_SPLL_REF_FB_DIV, tmp);
-	/* Power up MPLL */
-	tmp = INPLL(pllMPLL_CNTL);
-	OUTPLL(pllMPLL_CNTL, tmp & ~0x2);
-	(void)INPLL(pllMPLL_CNTL);
-
-	mdelay(10);
-
-	/* Un-reset MPLL */
-	tmp = INPLL(pllMPLL_CNTL);
-	OUTPLL(pllMPLL_CNTL, tmp & ~0x1);
-	(void)INPLL(pllMPLL_CNTL);
-
-	mdelay(10);
-
-	/* Select source for MCLK */
-	tmp = INPLL(pllMCLK_CNTL);
-	tmp |= rinfo->save_regs[2] & 0xffff;
-	OUTPLL(pllMCLK_CNTL, tmp);
-	(void)INPLL(pllMCLK_CNTL);
-
-	mdelay(10);
-}
-
-static void radeon_pm_m10_disable_spread_spectrum(struct radeonfb_info *rinfo)
-{
-	u32 r2ec;
-
-	/* GACK ! I though we didn't have a DDA on Radeon's anymore
-	 * here we rewrite with the same value, ... I suppose we clear
-	 * some bits that are already clear ? Or maybe this 0x2ec
-	 * register is something new ?
-	 */
-	mdelay(20);
-	r2ec = INREG(VGA_DDA_ON_OFF);
-	OUTREG(VGA_DDA_ON_OFF, r2ec);
-	mdelay(1);
-
-	/* Spread spectrum PLLL off */
-	OUTPLL(pllSSPLL_CNTL, 0xbf03);
-
-	/* Spread spectrum disabled */
-	OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3);
-
-	/* The trace shows read & rewrite of LVDS_PLL_CNTL here with same
-	 * value, not sure what for...
-	 */
-
-	r2ec |= 0x3f0;
-	OUTREG(VGA_DDA_ON_OFF, r2ec);
-	mdelay(1);
-}
-
-static void radeon_pm_m10_enable_lvds_spread_spectrum(struct radeonfb_info *rinfo)
-{
-	u32 r2ec, tmp;
-
-	/* GACK (bis) ! I though we didn't have a DDA on Radeon's anymore
-	 * here we rewrite with the same value, ... I suppose we clear/set
-	 * some bits that are already clear/set ?
-	 */
-	r2ec = INREG(VGA_DDA_ON_OFF);
-	OUTREG(VGA_DDA_ON_OFF, r2ec);
-	mdelay(1);
-
-	/* Enable spread spectrum */
-	OUTPLL(pllSSPLL_CNTL, rinfo->save_regs[43] | 3);
-	mdelay(3);
-
-	OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44]);
-	OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45]);
-	tmp = INPLL(pllSSPLL_CNTL);
-	OUTPLL(pllSSPLL_CNTL, tmp & ~0x2);
-	mdelay(6);
-	tmp = INPLL(pllSSPLL_CNTL);
-	OUTPLL(pllSSPLL_CNTL, tmp & ~0x1);
-	mdelay(5);
-
-       	OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90]);
-
-	r2ec |= 8;
-	OUTREG(VGA_DDA_ON_OFF, r2ec);
-	mdelay(20);
-
-	/* Enable LVDS interface */
-	tmp = INREG(LVDS_GEN_CNTL);
-	OUTREG(LVDS_GEN_CNTL, tmp | LVDS_EN);
-
-	/* Enable LVDS_PLL */
-	tmp = INREG(LVDS_PLL_CNTL);
-	tmp &= ~0x30000;
-	tmp |= 0x10000;
-	OUTREG(LVDS_PLL_CNTL, tmp);
-
-	OUTPLL(pllSCLK_MORE_CNTL, rinfo->save_regs[34]);
-	OUTPLL(pllSS_TST_CNTL, rinfo->save_regs[91]);
-
-	/* The trace reads that one here, waiting for something to settle down ? */
-	INREG(RBBM_STATUS);
-
-	/* Ugh ? SS_TST_DEC is supposed to be a read register in the
-	 * R300 register spec at least...
-	 */
-	tmp = INPLL(pllSS_TST_CNTL);
-	tmp |= 0x00400000;
-	OUTPLL(pllSS_TST_CNTL, tmp);
-}
-
-static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
-{
-	u32 tmp;
-
-	OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA, 0);
-	radeon_pll_errata_after_data(rinfo);
-
-	tmp = INPLL(pllVCLK_ECP_CNTL);
-	OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80);
-	mdelay(5);
-
-	tmp = INPLL(pllPPLL_REF_DIV);
-	tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div;
-	OUTPLL(pllPPLL_REF_DIV, tmp);
-	INPLL(pllPPLL_REF_DIV);
-
-	/* Reconfigure SPLL charge pump, VCO gain, duty cycle,
-	 * probably useless since we already did it ...
-	 */
-	tmp = INPLL(pllPPLL_CNTL);
-	OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
-	radeon_pll_errata_after_data(rinfo);
-
-	/* Restore our "reference" PPLL divider set by firmware
-	 * according to proper spread spectrum calculations
-	 */
-	OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]);
-
-	tmp = INPLL(pllPPLL_CNTL);
-	OUTPLL(pllPPLL_CNTL, tmp & ~0x2);
-	mdelay(5);
-
-	tmp = INPLL(pllPPLL_CNTL);
-	OUTPLL(pllPPLL_CNTL, tmp & ~0x1);
-	mdelay(5);
-
-	tmp = INPLL(pllVCLK_ECP_CNTL);
-	OUTPLL(pllVCLK_ECP_CNTL, tmp | 3);
-	mdelay(5);
-
-	tmp = INPLL(pllVCLK_ECP_CNTL);
-	OUTPLL(pllVCLK_ECP_CNTL, tmp | 3);
-	mdelay(5);
-
-	/* Switch pixel clock to firmware default div 0 */
-	OUTREG8(CLOCK_CNTL_INDEX+1, 0);
-	radeon_pll_errata_after_index(rinfo);
-	radeon_pll_errata_after_data(rinfo);
-}
-
-static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo)
-{
-	OUTREG(MC_CNTL, rinfo->save_regs[46]);
-	OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]);
-	OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]);
-	OUTREG(MEM_SDRAM_MODE_REG,
-	       rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-	OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]);
-	OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]);
-	OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]);
-	OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]);
-	OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]);
-	OUTREG(MC_DEBUG, rinfo->save_regs[53]);
-
-	OUTMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER, rinfo->save_regs[58]);
-	OUTMC(rinfo, ixR300_MC_IMP_CNTL, rinfo->save_regs[59]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0, rinfo->save_regs[60]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1, rinfo->save_regs[61]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0, rinfo->save_regs[62]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1, rinfo->save_regs[63]);
-	OUTMC(rinfo, ixR300_MC_BIST_CNTL_3, rinfo->save_regs[64]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0, rinfo->save_regs[65]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1, rinfo->save_regs[66]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0, rinfo->save_regs[67]);
-	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1, rinfo->save_regs[68]);
-	OUTMC(rinfo, ixR300_MC_DEBUG_CNTL, rinfo->save_regs[69]);
-	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
-	OUTMC(rinfo, ixR300_MC_IMP_CNTL_0, rinfo->save_regs[71]);
-	OUTMC(rinfo, ixR300_MC_ELPIDA_CNTL, rinfo->save_regs[72]);
-	OUTMC(rinfo, ixR300_MC_READ_CNTL_CD, rinfo->save_regs[96]);
-	OUTREG(MC_IND_INDEX, 0);
-}
-
-static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
-{
-	u32 tmp, i;
-
-	/* Restore a bunch of registers first */
-	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
-	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
-	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
-	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
-	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
-	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
-	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
-	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
-	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
-	OUTREG(FCP_CNTL, rinfo->save_regs[38]);
-	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
-	OUTREG(DAC_CNTL, rinfo->save_regs[40]);
-	OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8);
-	OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8);
-
-	/* Hrm... */
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE);
-
-	/* Reset the PAD CTLR */
-	radeon_pm_reset_pad_ctlr_strength(rinfo);
-
-	/* Some PLLs are Read & written identically in the trace here...
-	 * I suppose it's actually to switch them all off & reset,
-	 * let's assume off is what we want. I'm just doing that for all major PLLs now.
-	 */
-	radeon_pm_all_ppls_off(rinfo);
-
-	/* Clear tiling, reset swappers */
-	INREG(SURFACE_CNTL);
-	OUTREG(SURFACE_CNTL, 0);
-
-	/* Some black magic with TV_DAC_CNTL, we should restore those from backups
-	 * rather than hard coding...
-	 */
-	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK;
-	tmp |= 8 << TV_DAC_CNTL_BGADJ__SHIFT;
-	OUTREG(TV_DAC_CNTL, tmp);
-
-	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK;
-	tmp |= 7 << TV_DAC_CNTL_DACADJ__SHIFT;
-	OUTREG(TV_DAC_CNTL, tmp);
-
-	/* More registers restored */
-	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
-	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]);
-	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
-
-	/* Hrmmm ... What is that ? */
-	tmp = rinfo->save_regs[1]
-		& ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK |
-		    CLK_PWRMGT_CNTL__MC_BUSY);
-	OUTPLL(pllCLK_PWRMGT_CNTL, tmp);
-
-	OUTREG(PAD_CTLR_MISC, rinfo->save_regs[56]);
-	OUTREG(FW_CNTL, rinfo->save_regs[57]);
-	OUTREG(HDP_DEBUG, rinfo->save_regs[96]);
-	OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]);
-	OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]);
-	OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]);
-
-	/* Restore Memory Controller configuration */
-	radeon_pm_m10_reconfigure_mc(rinfo);
-
-	/* Make sure CRTC's dont touch memory */
-	OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL)
-	       | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B);
-	OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL)
-	       | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B);
-	mdelay(30);
-
-	/* Disable SDRAM refresh */
-	OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL)
-	       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
-
-	/* Restore XTALIN routing (CLK_PIN_CNTL) */
-	OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]);
-
-	/* Switch MCLK, YCLK and SCLK PLLs to PCI source & force them ON */
-	tmp = rinfo->save_regs[2] & 0xff000000;
-	tmp |=	MCLK_CNTL__FORCE_MCLKA |
-		MCLK_CNTL__FORCE_MCLKB |
-		MCLK_CNTL__FORCE_YCLKA |
-		MCLK_CNTL__FORCE_YCLKB |
-		MCLK_CNTL__FORCE_MC;
-	OUTPLL(pllMCLK_CNTL, tmp);
-
-	/* Force all clocks on in SCLK */
-	tmp = INPLL(pllSCLK_CNTL);
-	tmp |=	SCLK_CNTL__FORCE_DISP2|
-		SCLK_CNTL__FORCE_CP|
-		SCLK_CNTL__FORCE_HDP|
-		SCLK_CNTL__FORCE_DISP1|
-		SCLK_CNTL__FORCE_TOP|
-		SCLK_CNTL__FORCE_E2|
-		SCLK_CNTL__FORCE_SE|
-		SCLK_CNTL__FORCE_IDCT|
-		SCLK_CNTL__FORCE_VIP|
-		SCLK_CNTL__FORCE_PB|
-		SCLK_CNTL__FORCE_TAM|
-		SCLK_CNTL__FORCE_TDM|
-		SCLK_CNTL__FORCE_RB|
-		SCLK_CNTL__FORCE_TV_SCLK|
-		SCLK_CNTL__FORCE_SUBPIC|
-		SCLK_CNTL__FORCE_OV0;
-	tmp |=	SCLK_CNTL__CP_MAX_DYN_STOP_LAT  |
-		SCLK_CNTL__HDP_MAX_DYN_STOP_LAT |
-		SCLK_CNTL__TV_MAX_DYN_STOP_LAT  |
-		SCLK_CNTL__E2_MAX_DYN_STOP_LAT  |
-		SCLK_CNTL__SE_MAX_DYN_STOP_LAT  |
-		SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT|
-		SCLK_CNTL__VIP_MAX_DYN_STOP_LAT |
-		SCLK_CNTL__RE_MAX_DYN_STOP_LAT  |
-		SCLK_CNTL__PB_MAX_DYN_STOP_LAT  |
-		SCLK_CNTL__TAM_MAX_DYN_STOP_LAT |
-		SCLK_CNTL__TDM_MAX_DYN_STOP_LAT |
-		SCLK_CNTL__RB_MAX_DYN_STOP_LAT;
-	OUTPLL(pllSCLK_CNTL, tmp);
-
-	OUTPLL(pllVCLK_ECP_CNTL, 0);
-	OUTPLL(pllPIXCLKS_CNTL, 0);
-	OUTPLL(pllMCLK_MISC,
-	       MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT |
-	       MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT);
-
-	mdelay(5);
-
-	/* Restore the M_SPLL_REF_FB_DIV, MPLL_AUX_CNTL and SPLL_AUX_CNTL values */
-	OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]);
-	OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]);
-	OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]);
-
-	/* Now restore the major PLLs settings, keeping them off & reset though */
-	OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3);
-	OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3);
-	OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03);
-	OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03);
-
-	/* Restore MC DLL state and switch it off/reset too  */
-	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
-
-	/* Switch MDLL off & reset */
-	OUTPLL(pllMDLL_RDCKA, rinfo->save_regs[98] | 0xff);
-	mdelay(5);
-
-	/* Setup some black magic bits in PLL_PWRMGT_CNTL. Hrm... we saved
-	 * 0xa1100007... and MacOS writes 0xa1000007 ..
-	 */
-	OUTPLL(pllPLL_PWRMGT_CNTL, rinfo->save_regs[0]);
-
-	/* Restore more stuffs */
-	OUTPLL(pllHTOTAL_CNTL, 0);
-	OUTPLL(pllHTOTAL2_CNTL, 0);
-
-	/* More PLL initial configuration */
-	tmp = INPLL(pllSCLK_CNTL2); /* What for ? */
-	OUTPLL(pllSCLK_CNTL2, tmp);
-
-	tmp = INPLL(pllSCLK_MORE_CNTL);
-	tmp |= 	SCLK_MORE_CNTL__FORCE_DISPREGS |	/* a guess */
-		SCLK_MORE_CNTL__FORCE_MC_GUI |
-		SCLK_MORE_CNTL__FORCE_MC_HOST;
-	OUTPLL(pllSCLK_MORE_CNTL, tmp);
-
-	/* Now we actually start MCLK and SCLK */
-	radeon_pm_start_mclk_sclk(rinfo);
-
-	/* Full reset sdrams, this also re-inits the MDLL */
-	radeon_pm_full_reset_sdram(rinfo);
-
-	/* Fill palettes */
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20);
-	for (i=0; i<256; i++)
-		OUTREG(PALETTE_30_DATA, 0x15555555);
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20);
-	udelay(20);
-	for (i=0; i<256; i++)
-		OUTREG(PALETTE_30_DATA, 0x15555555);
-
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20);
-	mdelay(3);
-
-	/* Restore TMDS */
-	OUTREG(FP_GEN_CNTL, rinfo->save_regs[82]);
-	OUTREG(FP2_GEN_CNTL, rinfo->save_regs[83]);
-
-	/* Set LVDS registers but keep interface & pll down */
-	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] &
-	       ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN));
-	OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000);
-
-	OUTREG(DISP_OUTPUT_CNTL, rinfo->save_regs[86]);
-
-	/* Restore GPIOPAD state */
-	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
-	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
-	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
-
-	/* write some stuff to the framebuffer... */
-	for (i = 0; i < 0x8000; ++i)
-		writeb(0, rinfo->fb_base + i);
-
-	mdelay(40);
-	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON);
-	mdelay(40);
-
-	/* Restore a few more things */
-	OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]);
-	OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]);
-
-	/* Take care of spread spectrum & PPLLs now */
-	radeon_pm_m10_disable_spread_spectrum(rinfo);
-	radeon_pm_restore_pixel_pll(rinfo);
-
-	/* GRRRR... I can't figure out the proper LVDS power sequence, and the
-	 * code I have for blank/unblank doesn't quite work on some laptop models
-	 * it seems ... Hrm. What I have here works most of the time ...
-	 */
-	radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
-}
-#endif
-
-#ifdef CONFIG_PPC_OF
-#ifdef CONFIG_PPC_PMAC
-static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
-{
-	OUTREG(MC_CNTL, rinfo->save_regs[46]);
-	OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]);
-	OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]);
-	OUTREG(MEM_SDRAM_MODE_REG,
-	       rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
-	OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]);
-	OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]);
-	OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]);
-	OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]);
-	OUTREG(MC_DEBUG, rinfo->save_regs[53]);
-	OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]);
-
-	OUTMC(rinfo, ixMC_IMP_CNTL, rinfo->save_regs[59] /*0x00f460d6*/);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, rinfo->save_regs[65] /*0xfecfa666*/);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, rinfo->save_regs[66] /*0x141555ff*/);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, rinfo->save_regs[67] /*0xfecfa666*/);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
-	OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
-	OUTREG(MC_IND_INDEX, 0);
-	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
-
-	mdelay(20);
-}
-
-static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo)
-{
-	u32 tmp, i;
-
-	/* Restore a bunch of registers first */
-	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
-	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
-	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
-	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
-	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
-	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
-	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
-	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
-	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
-	OUTREG(FCP_CNTL, rinfo->save_regs[38]);
-	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
-
-	OUTREG(DAC_CNTL, rinfo->save_regs[40]);
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE);
-
-	/* Reset the PAD CTLR */
-	radeon_pm_reset_pad_ctlr_strength(rinfo);
-
-	/* Some PLLs are Read & written identically in the trace here...
-	 * I suppose it's actually to switch them all off & reset,
-	 * let's assume off is what we want. I'm just doing that for all major PLLs now.
-	 */
-	radeon_pm_all_ppls_off(rinfo);
-
-	/* Clear tiling, reset swappers */
-	INREG(SURFACE_CNTL);
-	OUTREG(SURFACE_CNTL, 0);
-
-	/* Some black magic with TV_DAC_CNTL, we should restore those from backups
-	 * rather than hard coding...
-	 */
-	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK;
-	tmp |= 6 << TV_DAC_CNTL_BGADJ__SHIFT;
-	OUTREG(TV_DAC_CNTL, tmp);
-
-	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK;
-	tmp |= 6 << TV_DAC_CNTL_DACADJ__SHIFT;
-	OUTREG(TV_DAC_CNTL, tmp);
-
-	OUTPLL(pllAGP_PLL_CNTL, rinfo->save_regs[78]);
-
-	OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]);
-	OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]);
-	OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]);
-
-	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
-	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]); /* MacOS sets that to 0 !!! */
-	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
-
-	tmp  = rinfo->save_regs[1]
-		& ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK |
-		    CLK_PWRMGT_CNTL__MC_BUSY);
-	OUTPLL(pllCLK_PWRMGT_CNTL, tmp);
-
-	OUTREG(FW_CNTL, rinfo->save_regs[57]);
-
-	/* Disable SDRAM refresh */
-	OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL)
-	       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
-
-	/* Restore XTALIN routing (CLK_PIN_CNTL) */
-       	OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]);
-
-	/* Force MCLK to be PCI sourced and forced ON */
-	tmp = rinfo->save_regs[2] & 0xff000000;
-	tmp |=	MCLK_CNTL__FORCE_MCLKA |
-		MCLK_CNTL__FORCE_MCLKB |
-		MCLK_CNTL__FORCE_YCLKA |
-		MCLK_CNTL__FORCE_YCLKB |
-		MCLK_CNTL__FORCE_MC    |
-		MCLK_CNTL__FORCE_AIC;
-	OUTPLL(pllMCLK_CNTL, tmp);
-
-	/* Force SCLK to be PCI sourced with a bunch forced */
-	tmp =	0 |
-		SCLK_CNTL__FORCE_DISP2|
-		SCLK_CNTL__FORCE_CP|
-		SCLK_CNTL__FORCE_HDP|
-		SCLK_CNTL__FORCE_DISP1|
-		SCLK_CNTL__FORCE_TOP|
-		SCLK_CNTL__FORCE_E2|
-		SCLK_CNTL__FORCE_SE|
-		SCLK_CNTL__FORCE_IDCT|
-		SCLK_CNTL__FORCE_VIP|
-		SCLK_CNTL__FORCE_RE|
-		SCLK_CNTL__FORCE_PB|
-		SCLK_CNTL__FORCE_TAM|
-		SCLK_CNTL__FORCE_TDM|
-		SCLK_CNTL__FORCE_RB;
-	OUTPLL(pllSCLK_CNTL, tmp);
-
-	/* Clear VCLK_ECP_CNTL & PIXCLKS_CNTL  */
-	OUTPLL(pllVCLK_ECP_CNTL, 0);
-	OUTPLL(pllPIXCLKS_CNTL, 0);
-
-	/* Setup MCLK_MISC, non dynamic mode */
-	OUTPLL(pllMCLK_MISC,
-	       MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT |
-	       MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT);
-
-	mdelay(5);
-
-	/* Set back the default clock dividers */
-	OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]);
-	OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]);
-	OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]);
-
-	/* PPLL and P2PLL default values & off */
-	OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3);
-	OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3);
-
-	/* S and M PLLs are reset & off, configure them */
-	OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03);
-	OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03);
-
-	/* Default values for MDLL ... fixme */
-	OUTPLL(pllMDLL_CKO, 0x9c009c);
-	OUTPLL(pllMDLL_RDCKA, 0x08830883);
-	OUTPLL(pllMDLL_RDCKB, 0x08830883);
-	mdelay(5);
-
-	/* Restore PLL_PWRMGT_CNTL */ // XXXX
-	tmp = rinfo->save_regs[0];
-	tmp &= ~PLL_PWRMGT_CNTL_SU_SCLK_USE_BCLK;
-	tmp |= PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
-	OUTPLL(PLL_PWRMGT_CNTL,  tmp);
-
-	/* Clear HTOTAL_CNTL & HTOTAL2_CNTL */
-	OUTPLL(pllHTOTAL_CNTL, 0);
-	OUTPLL(pllHTOTAL2_CNTL, 0);
-
-	/* All outputs off */
-	OUTREG(CRTC_GEN_CNTL, 0x04000000);
-	OUTREG(CRTC2_GEN_CNTL, 0x04000000);
-	OUTREG(FP_GEN_CNTL, 0x00004008);
-	OUTREG(FP2_GEN_CNTL, 0x00000008);
-	OUTREG(LVDS_GEN_CNTL, 0x08000008);
-
-	/* Restore Memory Controller configuration */
-	radeon_pm_m9p_reconfigure_mc(rinfo);
-
-	/* Now we actually start MCLK and SCLK */
-	radeon_pm_start_mclk_sclk(rinfo);
-
-	/* Full reset sdrams, this also re-inits the MDLL */
-	radeon_pm_full_reset_sdram(rinfo);
-
-	/* Fill palettes */
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20);
-	for (i=0; i<256; i++)
-		OUTREG(PALETTE_30_DATA, 0x15555555);
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20);
-	udelay(20);
-	for (i=0; i<256; i++)
-		OUTREG(PALETTE_30_DATA, 0x15555555);
-
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20);
-	mdelay(3);
-
-	/* Restore TV stuff, make sure TV DAC is down */
-	OUTREG(TV_MASTER_CNTL, rinfo->save_regs[88]);
-	OUTREG(TV_DAC_CNTL, rinfo->save_regs[13] | 0x07000000);
-
-	/* Restore GPIOS. MacOS does some magic here with one of the GPIO bits,
-	 * possibly related to the weird PLL related workarounds and to the
-	 * fact that CLK_PIN_CNTL is tweaked in ways I don't fully understand,
-	 * but we keep things the simple way here
-	 */
-	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
-	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
-	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
-
-	/* Now do things with SCLK_MORE_CNTL. Force bits are already set, copy
-	 * high bits from backup
-	 */
-	tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff;
-	tmp |= rinfo->save_regs[34] & 0xffff0000;
-	tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS;
-	OUTPLL(pllSCLK_MORE_CNTL, tmp);
-
-	tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff;
-	tmp |= rinfo->save_regs[34] & 0xffff0000;
-	tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS;
-	OUTPLL(pllSCLK_MORE_CNTL, tmp);
-
-	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] &
-	       ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN));
-	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_BLON);
-	OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000);
-	mdelay(20);
-
-	/* write some stuff to the framebuffer... */
-	for (i = 0; i < 0x8000; ++i)
-		writeb(0, rinfo->fb_base + i);
-
-	OUTREG(0x2ec, 0x6332a020);
-	OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44] /*0x3f */);
-	OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45] /*0x000081bb */);
-	tmp = INPLL(pllSSPLL_CNTL);
-	tmp &= ~2;
-	OUTPLL(pllSSPLL_CNTL, tmp);
-	mdelay(6);
-	tmp &= ~1;
-	OUTPLL(pllSSPLL_CNTL, tmp);
-	mdelay(5);
-	tmp |= 3;
-	OUTPLL(pllSSPLL_CNTL, tmp);
-	mdelay(5);
-
-	OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3);/*0x0020300c*/
-	OUTREG(0x2ec, 0x6332a3f0);
-	mdelay(17);
-
-	OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div);
-	OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]);
-
-	mdelay(40);
-	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON);
-	mdelay(40);
-
-	/* Restore a few more things */
-	OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]);
-	OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]);
-
-	/* Restore PPLL, spread spectrum & LVDS */
-	radeon_pm_m10_disable_spread_spectrum(rinfo);
-	radeon_pm_restore_pixel_pll(rinfo);
-	radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
-}
-#endif
-#endif
-
-#if 0 /* Not ready yet */
-static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
-{
-	int i;
-	u32 tmp, tmp2;
-	u32 cko, cka, ckb;
-	u32 cgc, cec, c2gc;
-
-	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
-	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
-	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
-	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
-	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
-	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
-
-	INREG(PAD_CTLR_STRENGTH);
-	OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~0x10000);
-	for (i = 0; i < 65; ++i) {
-		mdelay(1);
-		INREG(PAD_CTLR_STRENGTH);
-	}
-
-	OUTREG(DISP_TEST_DEBUG_CNTL, INREG(DISP_TEST_DEBUG_CNTL) | 0x10000000);
-	OUTREG(OV0_FLAG_CNTRL, INREG(OV0_FLAG_CNTRL) | 0x100);
-	OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL));
-	OUTREG(DAC_CNTL, 0xff00410a);
-	OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL));
-	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x4000);
-
-	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
-	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
-	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]);
-	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
-
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, 0xf7bb4433);
-	OUTREG(MC_IND_INDEX, 0);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, 0xf7bb4433);
-	OUTREG(MC_IND_INDEX, 0);
-
-	OUTREG(CRTC_MORE_CNTL, INREG(CRTC_MORE_CNTL));
-
-	tmp = INPLL(pllVCLK_ECP_CNTL);
-	OUTPLL(pllVCLK_ECP_CNTL, tmp);
-	tmp = INPLL(pllPIXCLKS_CNTL);
-	OUTPLL(pllPIXCLKS_CNTL, tmp);
-
-	OUTPLL(MCLK_CNTL, 0xaa3f0000);
-	OUTPLL(SCLK_CNTL, 0xffff0000);
-	OUTPLL(pllMPLL_AUX_CNTL, 6);
-	OUTPLL(pllSPLL_AUX_CNTL, 1);
-	OUTPLL(MDLL_CKO, 0x9f009f);
-	OUTPLL(MDLL_RDCKA, 0x830083);
-	OUTPLL(pllMDLL_RDCKB, 0x830083);
-	OUTPLL(PPLL_CNTL, 0xa433);
-	OUTPLL(P2PLL_CNTL, 0xa433);
-	OUTPLL(MPLL_CNTL, 0x0400a403);
-	OUTPLL(SPLL_CNTL, 0x0400a433);
-
-	tmp = INPLL(M_SPLL_REF_FB_DIV);
-	OUTPLL(M_SPLL_REF_FB_DIV, tmp);
-	tmp = INPLL(M_SPLL_REF_FB_DIV);
-	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0xc);
-	INPLL(M_SPLL_REF_FB_DIV);
-
-	tmp = INPLL(MPLL_CNTL);
-	OUTREG8(CLOCK_CNTL_INDEX, MPLL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
-	radeon_pll_errata_after_data(rinfo);
-
-	tmp = INPLL(M_SPLL_REF_FB_DIV);
-	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x5900);
-
-	tmp = INPLL(MPLL_CNTL);
-	OUTPLL(MPLL_CNTL, tmp & ~0x2);
-	mdelay(1);
-	tmp = INPLL(MPLL_CNTL);
-	OUTPLL(MPLL_CNTL, tmp & ~0x1);
-	mdelay(10);
-
-	OUTPLL(MCLK_CNTL, 0xaa3f1212);
-	mdelay(1);
-
-	INPLL(M_SPLL_REF_FB_DIV);
-	INPLL(MCLK_CNTL);
-	INPLL(M_SPLL_REF_FB_DIV);
-
-	tmp = INPLL(SPLL_CNTL);
-	OUTREG8(CLOCK_CNTL_INDEX, SPLL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
-	radeon_pll_errata_after_data(rinfo);
-
-	tmp = INPLL(M_SPLL_REF_FB_DIV);
-	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x780000);
-
-	tmp = INPLL(SPLL_CNTL);
-	OUTPLL(SPLL_CNTL, tmp & ~0x1);
-	mdelay(1);
-	tmp = INPLL(SPLL_CNTL);
-	OUTPLL(SPLL_CNTL, tmp & ~0x2);
-	mdelay(10);
-
-	tmp = INPLL(SCLK_CNTL);
-	OUTPLL(SCLK_CNTL, tmp | 2);
-	mdelay(1);
-
-	cko = INPLL(pllMDLL_CKO);
-	cka = INPLL(pllMDLL_RDCKA);
-	ckb = INPLL(pllMDLL_RDCKB);
-
-	cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP);
-	OUTPLL(pllMDLL_CKO, cko);
-	mdelay(1);
-	cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET);
-	OUTPLL(pllMDLL_CKO, cko);
-	mdelay(5);
-
-	cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP);
-	OUTPLL(pllMDLL_RDCKA, cka);
-	mdelay(1);
-	cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET);
-	OUTPLL(pllMDLL_RDCKA, cka);
-	mdelay(5);
-
-	ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP);
-	OUTPLL(pllMDLL_RDCKB, ckb);
-	mdelay(1);
-	ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET);
-	OUTPLL(pllMDLL_RDCKB, ckb);
-	mdelay(5);
-
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x151550ff);
-	OUTREG(MC_IND_INDEX, 0);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x151550ff);
-	OUTREG(MC_IND_INDEX, 0);
-	mdelay(1);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x141550ff);
-	OUTREG(MC_IND_INDEX, 0);
-	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x141550ff);
-	OUTREG(MC_IND_INDEX, 0);
-	mdelay(1);
-
-	OUTPLL(pllHTOTAL_CNTL, 0);
-	OUTPLL(pllHTOTAL2_CNTL, 0);
-
-	OUTREG(MEM_CNTL, 0x29002901);
-	OUTREG(MEM_SDRAM_MODE_REG, 0x45320032);	/* XXX use save_regs[35]? */
-	OUTREG(EXT_MEM_CNTL, 0x1a394333);
-	OUTREG(MEM_IO_CNTL_A1, 0x0aac0aac);
-	OUTREG(MEM_INIT_LATENCY_TIMER, 0x34444444);
-	OUTREG(MEM_REFRESH_CNTL, 0x1f1f7218);	/* XXX or save_regs[42]? */
-	OUTREG(MC_DEBUG, 0);
-	OUTREG(MEM_IO_OE_CNTL, 0x04300430);
-
-	OUTMC(rinfo, ixMC_IMP_CNTL, 0x00f460d6);
-	OUTREG(MC_IND_INDEX, 0);
-	OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
-	OUTREG(MC_IND_INDEX, 0);
-
-	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
-
-	radeon_pm_full_reset_sdram(rinfo);
-
-	INREG(FP_GEN_CNTL);
-	OUTREG(TMDS_CNTL, 0x01000000);	/* XXX ? */
-	tmp = INREG(FP_GEN_CNTL);
-	tmp |= FP_CRTC_DONT_SHADOW_HEND | FP_CRTC_DONT_SHADOW_VPAR | 0x200;
-	OUTREG(FP_GEN_CNTL, tmp);
-
-	tmp = INREG(DISP_OUTPUT_CNTL);
-	tmp &= ~0x400;
-	OUTREG(DISP_OUTPUT_CNTL, tmp);
-
-	OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
-	OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
-	OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
-
-	tmp = INPLL(MCLK_MISC);
-	tmp |= MCLK_MISC__MC_MCLK_DYN_ENABLE | MCLK_MISC__IO_MCLK_DYN_ENABLE;
-	OUTPLL(MCLK_MISC, tmp);
-
-	tmp = INPLL(SCLK_CNTL);
-	OUTPLL(SCLK_CNTL, tmp);
-
-	OUTREG(CRTC_MORE_CNTL, 0);
-	OUTREG8(CRTC_GEN_CNTL+1, 6);
-	OUTREG8(CRTC_GEN_CNTL+3, 1);
-	OUTREG(CRTC_PITCH, 32);
-
-	tmp = INPLL(VCLK_ECP_CNTL);
-	OUTPLL(VCLK_ECP_CNTL, tmp);
-
-	tmp = INPLL(PPLL_CNTL);
-	OUTPLL(PPLL_CNTL, tmp);
-
-	/* palette stuff and BIOS_1_SCRATCH... */
-
-	tmp = INREG(FP_GEN_CNTL);
-	tmp2 = INREG(TMDS_TRANSMITTER_CNTL);
-	tmp |= 2;
-	OUTREG(FP_GEN_CNTL, tmp);
-	mdelay(5);
-	OUTREG(FP_GEN_CNTL, tmp);
-	mdelay(5);
-	OUTREG(TMDS_TRANSMITTER_CNTL, tmp2);
-	OUTREG(CRTC_MORE_CNTL, 0);
-	mdelay(20);
-
-	tmp = INREG(CRTC_MORE_CNTL);
-	OUTREG(CRTC_MORE_CNTL, tmp);
-
-	cgc = INREG(CRTC_GEN_CNTL);
-	cec = INREG(CRTC_EXT_CNTL);
-	c2gc = INREG(CRTC2_GEN_CNTL);
-
-	OUTREG(CRTC_H_SYNC_STRT_WID, 0x008e0580);
-	OUTREG(CRTC_H_TOTAL_DISP, 0x009f00d2);
-	OUTREG8(CLOCK_CNTL_INDEX, HTOTAL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA, 0);
-	radeon_pll_errata_after_data(rinfo);
-	OUTREG(CRTC_V_SYNC_STRT_WID, 0x00830403);
-	OUTREG(CRTC_V_TOTAL_DISP, 0x03ff0429);
-	OUTREG(FP_CRTC_H_TOTAL_DISP, 0x009f0033);
-	OUTREG(FP_H_SYNC_STRT_WID, 0x008e0080);
-	OUTREG(CRT_CRTC_H_SYNC_STRT_WID, 0x008e0080);
-	OUTREG(FP_CRTC_V_TOTAL_DISP, 0x03ff002a);
-	OUTREG(FP_V_SYNC_STRT_WID, 0x00830004);
-	OUTREG(CRT_CRTC_V_SYNC_STRT_WID, 0x00830004);
-	OUTREG(FP_HORZ_VERT_ACTIVE, 0x009f03ff);
-	OUTREG(FP_HORZ_STRETCH, 0);
-	OUTREG(FP_VERT_STRETCH, 0);
-	OUTREG(OVR_CLR, 0);
-	OUTREG(OVR_WID_LEFT_RIGHT, 0);
-	OUTREG(OVR_WID_TOP_BOTTOM, 0);
-
-	tmp = INPLL(PPLL_REF_DIV);
-	tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div;
-	OUTPLL(PPLL_REF_DIV, tmp);
-	INPLL(PPLL_REF_DIV);
-
-	OUTREG8(CLOCK_CNTL_INDEX, PPLL_CNTL + PLL_WR_EN);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG8(CLOCK_CNTL_DATA + 1, 0xbc);
-	radeon_pll_errata_after_data(rinfo);
-
-	tmp = INREG(CLOCK_CNTL_INDEX);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG(CLOCK_CNTL_INDEX, tmp & 0xff);
-	radeon_pll_errata_after_index(rinfo);
-	radeon_pll_errata_after_data(rinfo);
-
-	OUTPLL(PPLL_DIV_0, 0x48090);
-
-	tmp = INPLL(PPLL_CNTL);
-	OUTPLL(PPLL_CNTL, tmp & ~0x2);
-	mdelay(1);
-	tmp = INPLL(PPLL_CNTL);
-	OUTPLL(PPLL_CNTL, tmp & ~0x1);
-	mdelay(10);
-
-	tmp = INPLL(VCLK_ECP_CNTL);
-	OUTPLL(VCLK_ECP_CNTL, tmp | 3);
-	mdelay(1);
-
-	tmp = INPLL(VCLK_ECP_CNTL);
-	OUTPLL(VCLK_ECP_CNTL, tmp);
-
-	c2gc |= CRTC2_DISP_REQ_EN_B;
-	OUTREG(CRTC2_GEN_CNTL, c2gc);
-	cgc |= CRTC_EN;
-	OUTREG(CRTC_GEN_CNTL, cgc);
-	OUTREG(CRTC_EXT_CNTL, cec);
-	OUTREG(CRTC_PITCH, 0xa0);
-	OUTREG(CRTC_OFFSET, 0);
-	OUTREG(CRTC_OFFSET_CNTL, 0);
-
-	OUTREG(GRPH_BUFFER_CNTL, 0x20117c7c);
-	OUTREG(GRPH2_BUFFER_CNTL, 0x00205c5c);
-
-	tmp2 = INREG(FP_GEN_CNTL);
-	tmp = INREG(TMDS_TRANSMITTER_CNTL);
-	OUTREG(0x2a8, 0x0000061b);
-	tmp |= TMDS_PLL_EN;
-	OUTREG(TMDS_TRANSMITTER_CNTL, tmp);
-	mdelay(1);
-	tmp &= ~TMDS_PLLRST;
-	OUTREG(TMDS_TRANSMITTER_CNTL, tmp);
-	tmp2 &= ~2;
-	tmp2 |= FP_TMDS_EN;
-	OUTREG(FP_GEN_CNTL, tmp2);
-	mdelay(5);
-	tmp2 |= FP_FPON;
-	OUTREG(FP_GEN_CNTL, tmp2);
-
-	OUTREG(CUR_HORZ_VERT_OFF, CUR_LOCK | 1);
-	cgc = INREG(CRTC_GEN_CNTL);
-	OUTREG(CUR_HORZ_VERT_POSN, 0xbfff0fff);
-	cgc |= 0x10000;
-	OUTREG(CUR_OFFSET, 0);
-}
-#endif /* 0 */
-
-#endif /* CONFIG_PPC_OF */
-
-static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state)
-{
-	u16 pwr_cmd;
-
-	for (;;) {
-		pci_read_config_word(rinfo->pdev,
-				     rinfo->pdev->pm_cap + PCI_PM_CTRL,
-				     &pwr_cmd);
-		if (pwr_cmd & state)
-			break;
-		pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | state;
-		pci_write_config_word(rinfo->pdev,
-				      rinfo->pdev->pm_cap + PCI_PM_CTRL,
-				      pwr_cmd);
-		msleep(500);
-	}
-	rinfo->pdev->current_state = state;
-}
-
-static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
-{
-	u32 tmp;
-
-	if (!rinfo->pdev->pm_cap)
-		return;
-
-	/* Set the chip into appropriate suspend mode (we use D2,
-	 * D3 would require a compete re-initialization of the chip,
-	 * including PCI config registers, clocks, AGP conf, ...)
-	 */
-	if (suspend) {
-		printk(KERN_DEBUG "radeonfb (%s): switching to D2 state...\n",
-		       pci_name(rinfo->pdev));
-
-		/* Disable dynamic power management of clocks for the
-		 * duration of the suspend/resume process
-		 */
-		radeon_pm_disable_dynamic_mode(rinfo);
-
-		/* Save some registers */
-		radeon_pm_save_regs(rinfo, 0);
-
-		/* Prepare mobility chips for suspend.
-		 */
-		if (rinfo->is_mobility) {
-			/* Program V2CLK */
-			radeon_pm_program_v2clk(rinfo);
-		
-			/* Disable IO PADs */
-			radeon_pm_disable_iopad(rinfo);
-
-			/* Set low current */
-			radeon_pm_low_current(rinfo);
-
-			/* Prepare chip for power management */
-			radeon_pm_setup_for_suspend(rinfo);
-
-			if (rinfo->family <= CHIP_FAMILY_RV280) {
-				/* Reset the MDLL */
-				/* because both INPLL and OUTPLL take the same
-				 * lock, that's why. */
-				tmp = INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET
-					| MDLL_CKO__MCKOB_RESET;
-				OUTPLL( pllMDLL_CKO, tmp );
-			}
-		}
-
-		/* Switch PCI power management to D2. */
-		pci_disable_device(rinfo->pdev);
-		pci_save_state(rinfo->pdev);
-		/* The chip seems to need us to whack the PM register
-		 * repeatedly until it sticks. We do that -prior- to
-		 * calling pci_set_power_state()
-		 */
-		radeonfb_whack_power_state(rinfo, PCI_D2);
-		__pci_complete_power_transition(rinfo->pdev, PCI_D2);
-	} else {
-		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
-		       pci_name(rinfo->pdev));
-
-		if (rinfo->family <= CHIP_FAMILY_RV250) {
-			/* Reset the SDRAM controller  */
-			radeon_pm_full_reset_sdram(rinfo);
-
-			/* Restore some registers */
-			radeon_pm_restore_regs(rinfo);
-		} else {
-			/* Restore registers first */
-			radeon_pm_restore_regs(rinfo);
-			/* init sdram controller */
-			radeon_pm_full_reset_sdram(rinfo);
-		}
-	}
-}
-
-int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
-{
-        struct fb_info *info = pci_get_drvdata(pdev);
-        struct radeonfb_info *rinfo = info->par;
-
-	if (mesg.event == pdev->dev.power.power_state.event)
-		return 0;
-
-	printk(KERN_DEBUG "radeonfb (%s): suspending for event: %d...\n",
-	       pci_name(pdev), mesg.event);
-
-	/* For suspend-to-disk, we cheat here. We don't suspend anything and
-	 * let fbcon continue drawing until we are all set. That shouldn't
-	 * really cause any problem at this point, provided that the wakeup
-	 * code knows that any state in memory may not match the HW
-	 */
-	switch (mesg.event) {
-	case PM_EVENT_FREEZE:		/* about to take snapshot */
-	case PM_EVENT_PRETHAW:		/* before restoring snapshot */
-		goto done;
-	}
-
-	console_lock();
-
-	fb_set_suspend(info, 1);
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
-		/* Make sure engine is reset */
-		radeon_engine_idle();
-		radeonfb_engine_reset(rinfo);
-		radeon_engine_idle();
-	}
-
-	/* Blank display and LCD */
-	radeon_screen_blank(rinfo, FB_BLANK_POWERDOWN, 1);
-
-	/* Sleep */
-	rinfo->asleep = 1;
-	rinfo->lock_blank = 1;
-	del_timer_sync(&rinfo->lvds_timer);
-
-#ifdef CONFIG_PPC_PMAC
-	/* On powermac, we have hooks to properly suspend/resume AGP now,
-	 * use them here. We'll ultimately need some generic support here,
-	 * but the generic code isn't quite ready for that yet
-	 */
-	pmac_suspend_agp_for_card(pdev);
-#endif /* CONFIG_PPC_PMAC */
-
-	/* It's unclear whether or when the generic code will do that, so let's
-	 * do it ourselves. We save state before we do any power management
-	 */
-	pci_save_state(pdev);
-
-	/* If we support wakeup from poweroff, we save all regs we can including cfg
-	 * space
-	 */
-	if (rinfo->pm_mode & radeon_pm_off) {
-		/* Always disable dynamic clocks or weird things are happening when
-		 * the chip goes off (basically the panel doesn't shut down properly
-		 * and we crash on wakeup),
-		 * also, we want the saved regs context to have no dynamic clocks in
-		 * it, we'll restore the dynamic clocks state on wakeup
-		 */
-		radeon_pm_disable_dynamic_mode(rinfo);
-		mdelay(50);
-		radeon_pm_save_regs(rinfo, 1);
-
-		if (rinfo->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) {
-			/* Switch off LVDS interface */
-			mdelay(1);
-			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_BL_MOD_EN));
-			mdelay(1);
-			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_EN | LVDS_ON));
-			OUTREG(LVDS_PLL_CNTL, (INREG(LVDS_PLL_CNTL) & ~30000) | 0x20000);
-			mdelay(20);
-			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
-		}
-		pci_disable_device(pdev);
-	}
-	/* If we support D2, we go to it (should be fixed later with a flag forcing
-	 * D3 only for some laptops)
-	 */
-	if (rinfo->pm_mode & radeon_pm_d2)
-		radeon_set_suspend(rinfo, 1);
-
-	console_unlock();
-
- done:
-	pdev->dev.power.power_state = mesg;
-
-	return 0;
-}
-
-static int radeon_check_power_loss(struct radeonfb_info *rinfo)
-{
-	return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) ||
-	       rinfo->save_regs[2] != INPLL(MCLK_CNTL) ||
-	       rinfo->save_regs[3] != INPLL(SCLK_CNTL);
-}
-
-int radeonfb_pci_resume(struct pci_dev *pdev)
-{
-        struct fb_info *info = pci_get_drvdata(pdev);
-        struct radeonfb_info *rinfo = info->par;
-	int rc = 0;
-
-	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
-		return 0;
-
-	if (rinfo->no_schedule) {
-		if (!console_trylock())
-			return 0;
-	} else
-		console_lock();
-
-	printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
-	       pci_name(pdev), pdev->dev.power.power_state.event);
-
-	/* PCI state will have been restored by the core, so
-	 * we should be in D0 now with our config space fully
-	 * restored
-	 */
-	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-		/* Wakeup chip */
-		if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) {
-			if (rinfo->reinit_func != NULL)
-				rinfo->reinit_func(rinfo);
-			else {
-				printk(KERN_ERR "radeonfb (%s): can't resume radeon from"
-				       " D3 cold, need softboot !", pci_name(pdev));
-				rc = -EIO;
-				goto bail;
-			}
-		}
-		/* If we support D2, try to resume... we should check what was our
-		 * state though... (were we really in D2 state ?). Right now, this code
-		 * is only enable on Macs so it's fine.
-		 */
-		else if (rinfo->pm_mode & radeon_pm_d2)
-			radeon_set_suspend(rinfo, 0);
-
-		rinfo->asleep = 0;
-	} else
-		radeon_engine_idle();
-
-	/* Restore display & engine */
-	radeon_write_mode (rinfo, &rinfo->state, 1);
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
-		radeonfb_engine_init (rinfo);
-
-	fb_pan_display(info, &info->var);
-	fb_set_cmap(&info->cmap, info);
-
-	/* Refresh */
-	fb_set_suspend(info, 0);
-
-	/* Unblank */
-	rinfo->lock_blank = 0;
-	radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 1);
-
-#ifdef CONFIG_PPC_PMAC
-	/* On powermac, we have hooks to properly suspend/resume AGP now,
-	 * use them here. We'll ultimately need some generic support here,
-	 * but the generic code isn't quite ready for that yet
-	 */
-	pmac_resume_agp_for_card(pdev);
-#endif /* CONFIG_PPC_PMAC */
-
-
-	/* Check status of dynclk */
-	if (rinfo->dynclk == 1)
-		radeon_pm_enable_dynamic_mode(rinfo);
-	else if (rinfo->dynclk == 0)
-		radeon_pm_disable_dynamic_mode(rinfo);
-
-	pdev->dev.power.power_state = PMSG_ON;
-
- bail:
-	console_unlock();
-
-	return rc;
-}
-
-#ifdef CONFIG_PPC_OF__disabled
-static void radeonfb_early_resume(void *data)
-{
-        struct radeonfb_info *rinfo = data;
-
-	rinfo->no_schedule = 1;
-	pci_restore_state(rinfo->pdev);
-	radeonfb_pci_resume(rinfo->pdev);
-	rinfo->no_schedule = 0;
-}
-#endif /* CONFIG_PPC_OF */
-
-#endif /* CONFIG_PM */
-
-void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
-{
-	/* Enable/Disable dynamic clocks: TODO add sysfs access */
-	if (rinfo->family == CHIP_FAMILY_RS480)
-		rinfo->dynclk = -1;
-	else
-		rinfo->dynclk = dynclk;
-
-	if (rinfo->dynclk == 1) {
-		radeon_pm_enable_dynamic_mode(rinfo);
-		printk("radeonfb: Dynamic Clock Power Management enabled\n");
-	} else if (rinfo->dynclk == 0) {
-		radeon_pm_disable_dynamic_mode(rinfo);
-		printk("radeonfb: Dynamic Clock Power Management disabled\n");
-	}
-
-#if defined(CONFIG_PM)
-#if defined(CONFIG_PPC_PMAC)
-	/* Check if we can power manage on suspend/resume. We can do
-	 * D2 on M6, M7 and M9, and we can resume from D3 cold a few other
-	 * "Mac" cards, but that's all. We need more infos about what the
-	 * BIOS does tho. Right now, all this PM stuff is pmac-only for that
-	 * reason. --BenH
-	 */
-	if (machine_is(powermac) && rinfo->of_node) {
-		if (rinfo->is_mobility && rinfo->pdev->pm_cap &&
-		    rinfo->family <= CHIP_FAMILY_RV250)
-			rinfo->pm_mode |= radeon_pm_d2;
-
-		/* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
-		 * in some desktop G4s), Via (M9+ chip on iBook G4) and
-		 * Snowy (M11 chip on iBook G4 manufactured after July 2005)
-		 */
-		if (!strcmp(rinfo->of_node->name, "ATY,JasperParent") ||
-		    !strcmp(rinfo->of_node->name, "ATY,SnowyParent")) {
-			rinfo->reinit_func = radeon_reinitialize_M10;
-			rinfo->pm_mode |= radeon_pm_off;
-		}
-#if 0 /* Not ready yet */
-		if (!strcmp(rinfo->of_node->name, "ATY,BlueStoneParent")) {
-			rinfo->reinit_func = radeon_reinitialize_QW;
-			rinfo->pm_mode |= radeon_pm_off;
-		}
-#endif
-		if (!strcmp(rinfo->of_node->name, "ATY,ViaParent")) {
-			rinfo->reinit_func = radeon_reinitialize_M9P;
-			rinfo->pm_mode |= radeon_pm_off;
-		}
-
-		/* If any of the above is set, we assume the machine can sleep/resume.
-		 * It's a bit of a "shortcut" but will work fine. Ideally, we need infos
-		 * from the platform about what happens to the chip...
-		 * Now we tell the platform about our capability
-		 */
-		if (rinfo->pm_mode != radeon_pm_none) {
-			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1);
-#if 0 /* Disable the early video resume hack for now as it's causing problems, among
-       * others we now rely on the PCI core restoring the config space for us, which
-       * isn't the case with that hack, and that code path causes various things to
-       * be called with interrupts off while they shouldn't. I'm leaving the code in
-       * as it can be useful for debugging purposes
-       */
-			pmac_set_early_video_resume(radeonfb_early_resume, rinfo);
-#endif
-		}
-
-#if 0
-		/* Power down TV DAC, that saves a significant amount of power,
-		 * we'll have something better once we actually have some TVOut
-		 * support
-		 */
-		OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
-#endif
-	}
-#endif /* defined(CONFIG_PPC_PMAC) */
-#endif /* defined(CONFIG_PM) */
-
-	if (ignore_devlist)
-		printk(KERN_DEBUG
-		       "radeonfb: skipping test for device workarounds\n");
-	else
-		radeon_apply_workarounds(rinfo);
-
-	if (force_sleep) {
-		printk(KERN_DEBUG
-		       "radeonfb: forcefully enabling D2 sleep mode\n");
-		rinfo->pm_mode |= radeon_pm_d2;
-	}
-}
-
-void radeonfb_pm_exit(struct radeonfb_info *rinfo)
-{
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
-	if (rinfo->pm_mode != radeon_pm_none)
-		pmac_set_early_video_resume(NULL, NULL);
-#endif
-}
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
deleted file mode 100644
index cb846044f57c..000000000000
--- a/drivers/video/aty/radeonfb.h
+++ /dev/null
@@ -1,634 +0,0 @@
-#ifndef __RADEONFB_H__
-#define __RADEONFB_H__
-
-#ifdef CONFIG_FB_RADEON_DEBUG
-#define DEBUG		1
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/fb.h>
-
-
-#ifdef CONFIG_FB_RADEON_I2C
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#endif
-
-#include <asm/io.h>
-
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-#include <asm/prom.h>
-#endif
-
-#include <video/radeon.h>
-
-/***************************************************************
- * Most of the definitions here are adapted right from XFree86 *
- ***************************************************************/
-
-
-/*
- * Chip families. Must fit in the low 16 bits of a long word
- */
-enum radeon_family {
-	CHIP_FAMILY_UNKNOW,
-	CHIP_FAMILY_LEGACY,
-	CHIP_FAMILY_RADEON,
-	CHIP_FAMILY_RV100,
-	CHIP_FAMILY_RS100,    /* U1 (IGP320M) or A3 (IGP320)*/
-	CHIP_FAMILY_RV200,
-	CHIP_FAMILY_RS200,    /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350),
-				 RS250 (IGP 7000) */
-	CHIP_FAMILY_R200,
-	CHIP_FAMILY_RV250,
-	CHIP_FAMILY_RS300,    /* Radeon 9000 IGP */
-	CHIP_FAMILY_RV280,
-	CHIP_FAMILY_R300,
-	CHIP_FAMILY_R350,
-	CHIP_FAMILY_RV350,
-	CHIP_FAMILY_RV380,    /* RV370/RV380/M22/M24 */
-	CHIP_FAMILY_R420,     /* R420/R423/M18 */
-	CHIP_FAMILY_RC410,
-	CHIP_FAMILY_RS400,
-	CHIP_FAMILY_RS480,
-	CHIP_FAMILY_LAST,
-};
-
-#define IS_RV100_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_RV100)  || \
-				 ((rinfo)->family == CHIP_FAMILY_RV200)  || \
-				 ((rinfo)->family == CHIP_FAMILY_RS100)  || \
-				 ((rinfo)->family == CHIP_FAMILY_RS200)  || \
-				 ((rinfo)->family == CHIP_FAMILY_RV250)  || \
-				 ((rinfo)->family == CHIP_FAMILY_RV280)  || \
-				 ((rinfo)->family == CHIP_FAMILY_RS300))
-
-
-#define IS_R300_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_R300)  || \
-				((rinfo)->family == CHIP_FAMILY_RV350) || \
-				((rinfo)->family == CHIP_FAMILY_R350)  || \
-				((rinfo)->family == CHIP_FAMILY_RV380) || \
-				((rinfo)->family == CHIP_FAMILY_R420)  || \
-                               ((rinfo)->family == CHIP_FAMILY_RC410) || \
-                               ((rinfo)->family == CHIP_FAMILY_RS480))
-
-/*
- * Chip flags
- */
-enum radeon_chip_flags {
-	CHIP_FAMILY_MASK	= 0x0000ffffUL,
-	CHIP_FLAGS_MASK		= 0xffff0000UL,
-	CHIP_IS_MOBILITY	= 0x00010000UL,
-	CHIP_IS_IGP		= 0x00020000UL,
-	CHIP_HAS_CRTC2		= 0x00040000UL,	
-};
-
-/*
- * Errata workarounds
- */
-enum radeon_errata {
-	CHIP_ERRATA_R300_CG		= 0x00000001,
-	CHIP_ERRATA_PLL_DUMMYREADS	= 0x00000002,
-	CHIP_ERRATA_PLL_DELAY		= 0x00000004,
-};
-
-
-/*
- * Monitor types
- */
-enum radeon_montype {
-	MT_NONE = 0,
-	MT_CRT,		/* CRT */
-	MT_LCD,		/* LCD */
-	MT_DFP,		/* DVI */
-	MT_CTV,		/* composite TV */
-	MT_STV		/* S-Video out */
-};
-
-/*
- * DDC i2c ports
- */
-enum ddc_type {
-	ddc_none,
-	ddc_monid,
-	ddc_dvi,
-	ddc_vga,
-	ddc_crt2,
-};
-
-/*
- * Connector types
- */
-enum conn_type {
-	conn_none,
-	conn_proprietary,
-	conn_crt,
-	conn_DVI_I,
-	conn_DVI_D,
-};
-
-
-/*
- * PLL infos
- */
-struct pll_info {
-	int ppll_max;
-	int ppll_min;
-	int sclk, mclk;
-	int ref_div;
-	int ref_clk;
-};
-
-
-/*
- * This structure contains the various registers manipulated by this
- * driver for setting or restoring a mode. It's mostly copied from
- * XFree's RADEONSaveRec structure. A few chip settings might still be
- * tweaked without beeing reflected or saved in these registers though
- */
-struct radeon_regs {
-	/* Common registers */
-	u32		ovr_clr;
-	u32		ovr_wid_left_right;
-	u32		ovr_wid_top_bottom;
-	u32		ov0_scale_cntl;
-	u32		mpp_tb_config;
-	u32		mpp_gp_config;
-	u32		subpic_cntl;
-	u32		viph_control;
-	u32		i2c_cntl_1;
-	u32		gen_int_cntl;
-	u32		cap0_trig_cntl;
-	u32		cap1_trig_cntl;
-	u32		bus_cntl;
-	u32		surface_cntl;
-	u32		bios_5_scratch;
-
-	/* Other registers to save for VT switches or driver load/unload */
-	u32		dp_datatype;
-	u32		rbbm_soft_reset;
-	u32		clock_cntl_index;
-	u32		amcgpio_en_reg;
-	u32		amcgpio_mask;
-
-	/* Surface/tiling registers */
-	u32		surf_lower_bound[8];
-	u32		surf_upper_bound[8];
-	u32		surf_info[8];
-
-	/* CRTC registers */
-	u32		crtc_gen_cntl;
-	u32		crtc_ext_cntl;
-	u32		dac_cntl;
-	u32		crtc_h_total_disp;
-	u32		crtc_h_sync_strt_wid;
-	u32		crtc_v_total_disp;
-	u32		crtc_v_sync_strt_wid;
-	u32		crtc_offset;
-	u32		crtc_offset_cntl;
-	u32		crtc_pitch;
-	u32		disp_merge_cntl;
-	u32		grph_buffer_cntl;
-	u32		crtc_more_cntl;
-
-	/* CRTC2 registers */
-	u32		crtc2_gen_cntl;
-	u32		dac2_cntl;
-	u32		disp_output_cntl;
-	u32		disp_hw_debug;
-	u32		disp2_merge_cntl;
-	u32		grph2_buffer_cntl;
-	u32		crtc2_h_total_disp;
-	u32		crtc2_h_sync_strt_wid;
-	u32		crtc2_v_total_disp;
-	u32		crtc2_v_sync_strt_wid;
-	u32		crtc2_offset;
-	u32		crtc2_offset_cntl;
-	u32		crtc2_pitch;
-
-	/* Flat panel regs */
-	u32 		fp_crtc_h_total_disp;
-	u32		fp_crtc_v_total_disp;
-	u32		fp_gen_cntl;
-	u32		fp2_gen_cntl;
-	u32		fp_h_sync_strt_wid;
-	u32		fp2_h_sync_strt_wid;
-	u32		fp_horz_stretch;
-	u32		fp_panel_cntl;
-	u32		fp_v_sync_strt_wid;
-	u32		fp2_v_sync_strt_wid;
-	u32		fp_vert_stretch;
-	u32		lvds_gen_cntl;
-	u32		lvds_pll_cntl;
-	u32		tmds_crc;
-	u32		tmds_transmitter_cntl;
-
-	/* Computed values for PLL */
-	u32		dot_clock_freq;
-	int		feedback_div;
-	int		post_div;	
-
-	/* PLL registers */
-	u32		ppll_div_3;
-	u32		ppll_ref_div;
-	u32		vclk_ecp_cntl;
-	u32		clk_cntl_index;
-
-	/* Computed values for PLL2 */
-	u32		dot_clock_freq_2;
-	int		feedback_div_2;
-	int		post_div_2;
-
-	/* PLL2 registers */
-	u32		p2pll_ref_div;
-	u32		p2pll_div_0;
-	u32		htotal_cntl2;
-
-       	/* Palette */
-	int		palette_valid;
-};
-
-struct panel_info {
-	int xres, yres;
-	int valid;
-	int clock;
-	int hOver_plus, hSync_width, hblank;
-	int vOver_plus, vSync_width, vblank;
-	int hAct_high, vAct_high, interlaced;
-	int pwr_delay;
-	int use_bios_dividers;
-	int ref_divider;
-	int post_divider;
-	int fbk_divider;
-};
-
-struct radeonfb_info;
-
-#ifdef CONFIG_FB_RADEON_I2C
-struct radeon_i2c_chan {
-	struct radeonfb_info		*rinfo;
-	u32		 		ddc_reg;
-	struct i2c_adapter		adapter;
-	struct i2c_algo_bit_data	algo;
-};
-#endif
-
-enum radeon_pm_mode {
-	radeon_pm_none	= 0,		/* Nothing supported */
-	radeon_pm_d2	= 0x00000001,	/* Can do D2 state */
-	radeon_pm_off	= 0x00000002,	/* Can resume from D3 cold */
-};
-
-typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo);
-
-struct radeonfb_info {
-	struct fb_info		*info;
-
-	struct radeon_regs 	state;
-	struct radeon_regs	init_state;
-
-	char			name[50];
-
-	unsigned long		mmio_base_phys;
-	unsigned long		fb_base_phys;
-
-	void __iomem		*mmio_base;
-	void __iomem		*fb_base;
-
-	unsigned long		fb_local_base;
-
-	struct pci_dev		*pdev;
-#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
-	struct device_node	*of_node;
-#endif
-
-	void __iomem		*bios_seg;
-	int			fp_bios_start;
-
-	u32			pseudo_palette[16];
-	struct { u8 red, green, blue, pad; }
-				palette[256];
-
-	int			chipset;
-	u8			family;
-	u8			rev;
-	unsigned int		errata;
-	unsigned long		video_ram;
-	unsigned long		mapped_vram;
-	int			vram_width;
-	int			vram_ddr;
-
-	int			pitch, bpp, depth;
-
-	int			has_CRTC2;
-	int			is_mobility;
-	int			is_IGP;
-	int			reversed_DAC;
-	int			reversed_TMDS;
-	struct panel_info	panel_info;
-	int			mon1_type;
-	u8			*mon1_EDID;
-	struct fb_videomode	*mon1_modedb;
-	int			mon1_dbsize;
-	int			mon2_type;
-	u8		        *mon2_EDID;
-
-	u32			dp_gui_master_cntl;
-
-	struct pll_info		pll;
-
-	int			mtrr_hdl;
-
-	u32			save_regs[100];
-	int			asleep;
-	int			lock_blank;
-	int			dynclk;
-	int			no_schedule;
-	enum radeon_pm_mode	pm_mode;
-	reinit_function_ptr     reinit_func;
-
-	/* Lock on register access */
-	spinlock_t		reg_lock;
-
-	/* Timer used for delayed LVDS operations */
-	struct timer_list	lvds_timer;
-	u32			pending_lvds_gen_cntl;
-
-#ifdef CONFIG_FB_RADEON_I2C
-	struct radeon_i2c_chan 	i2c[4];
-#endif
-};
-
-
-#define PRIMARY_MONITOR(rinfo)	(rinfo->mon1_type)
-
-
-/*
- * IO macros
- */
-
-/* Note about this function: we have some rare cases where we must not schedule,
- * this typically happen with our special "wake up early" hook which allows us to
- * wake up the graphic chip (and thus get the console back) before everything else
- * on some machines that support that mechanism. At this point, interrupts are off
- * and scheduling is not permitted
- */
-static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
-{
-	if (rinfo->no_schedule || oops_in_progress)
-		mdelay(ms);
-	else
-		msleep(ms);
-}
-
-
-#define INREG8(addr)		readb((rinfo->mmio_base)+addr)
-#define OUTREG8(addr,val)	writeb(val, (rinfo->mmio_base)+addr)
-#define INREG16(addr)		readw((rinfo->mmio_base)+addr)
-#define OUTREG16(addr,val)	writew(val, (rinfo->mmio_base)+addr)
-#define INREG(addr)		readl((rinfo->mmio_base)+addr)
-#define OUTREG(addr,val)	writel(val, (rinfo->mmio_base)+addr)
-
-static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
-		       u32 val, u32 mask)
-{
-	unsigned long flags;
-	unsigned int tmp;
-
-	spin_lock_irqsave(&rinfo->reg_lock, flags);
-	tmp = INREG(addr);
-	tmp &= (mask);
-	tmp |= (val);
-	OUTREG(addr, tmp);
-	spin_unlock_irqrestore(&rinfo->reg_lock, flags);
-}
-
-#define OUTREGP(addr,val,mask)	_OUTREGP(rinfo, addr, val,mask)
-
-/*
- * Note about PLL register accesses:
- *
- * I have removed the spinlock on them on purpose. The driver now
- * expects that it will only manipulate the PLL registers in normal
- * task environment, where radeon_msleep() will be called, protected
- * by a semaphore (currently the console semaphore) so that no conflict
- * will happen on the PLL register index.
- *
- * With the latest changes to the VT layer, this is guaranteed for all
- * calls except the actual drawing/blits which aren't supposed to use
- * the PLL registers anyway
- *
- * This is very important for the workarounds to work properly. The only
- * possible exception to this rule is the call to unblank(), which may
- * be done at irq time if an oops is in progress.
- */
-static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
-{
-	if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
-		return;
-
-	(void)INREG(CLOCK_CNTL_DATA);
-	(void)INREG(CRTC_GEN_CNTL);
-}
-
-static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
-{
-	if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
-		/* we can't deal with posted writes here ... */
-		_radeon_msleep(rinfo, 5);
-	}
-	if (rinfo->errata & CHIP_ERRATA_R300_CG) {
-		u32 save, tmp;
-		save = INREG(CLOCK_CNTL_INDEX);
-		tmp = save & ~(0x3f | PLL_WR_EN);
-		OUTREG(CLOCK_CNTL_INDEX, tmp);
-		tmp = INREG(CLOCK_CNTL_DATA);
-		OUTREG(CLOCK_CNTL_INDEX, save);
-	}
-}
-
-static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
-	u32 data;
-
-	OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
-	radeon_pll_errata_after_index(rinfo);
-	data = INREG(CLOCK_CNTL_DATA);
-	radeon_pll_errata_after_data(rinfo);
-	return data;
-}
-
-static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
-			    u32 val)
-{
-
-	OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG(CLOCK_CNTL_DATA, val);
-	radeon_pll_errata_after_data(rinfo);
-}
-
-
-static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
-			     u32 val, u32 mask)
-{
-	unsigned int tmp;
-
-	tmp  = __INPLL(rinfo, index);
-	tmp &= (mask);
-	tmp |= (val);
-	__OUTPLL(rinfo, index, tmp);
-}
-
-
-#define INPLL(addr)			__INPLL(rinfo, addr)
-#define OUTPLL(index, val)		__OUTPLL(rinfo, index, val)
-#define OUTPLLP(index, val, mask)	__OUTPLLP(rinfo, index, val, mask)
-
-
-#define BIOS_IN8(v)  	(readb(rinfo->bios_seg + (v)))
-#define BIOS_IN16(v) 	(readb(rinfo->bios_seg + (v)) | \
-			  (readb(rinfo->bios_seg + (v) + 1) << 8))
-#define BIOS_IN32(v) 	(readb(rinfo->bios_seg + (v)) | \
-			  (readb(rinfo->bios_seg + (v) + 1) << 8) | \
-			  (readb(rinfo->bios_seg + (v) + 2) << 16) | \
-			  (readb(rinfo->bios_seg + (v) + 3) << 24))
-
-/*
- * Inline utilities
- */
-static inline int round_div(int num, int den)
-{
-        return (num + (den / 2)) / den;
-}
-
-static inline int var_to_depth(const struct fb_var_screeninfo *var)
-{
-	if (var->bits_per_pixel != 16)
-		return var->bits_per_pixel;
-	return (var->green.length == 5) ? 15 : 16;
-}
-
-static inline u32 radeon_get_dstbpp(u16 depth)
-{
-	switch (depth) {
-       	case 8:
-       		return DST_8BPP;
-       	case 15:
-       		return DST_15BPP;
-       	case 16:
-       		return DST_16BPP;
-       	case 32:
-       		return DST_32BPP;
-       	default:
-       		return 0;
-	}
-}
-
-/*
- * 2D Engine helper routines
- */
-
-static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
-{
-	int i;
-
-	for (i=0; i<2000000; i++) {
-		if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
-			return;
-		udelay(1);
-	}
-	printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
-}
-
-static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
-{
-	int i;
-
-	/* Initiate flush */
-	OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
-	        ~RB2D_DC_FLUSH_ALL);
-
-	/* Ensure FIFO is empty, ie, make sure the flush commands
-	 * has reached the cache
-	 */
-	_radeon_fifo_wait (rinfo, 64);
-
-	/* Wait for the flush to complete */
-	for (i=0; i < 2000000; i++) {
-		if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
-			return;
-		udelay(1);
-	}
-	printk(KERN_ERR "radeonfb: Flush Timeout !\n");
-}
-
-
-static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
-{
-	int i;
-
-	/* ensure FIFO is empty before waiting for idle */
-	_radeon_fifo_wait (rinfo, 64);
-
-	for (i=0; i<2000000; i++) {
-		if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
-			radeon_engine_flush (rinfo);
-			return;
-		}
-		udelay(1);
-	}
-	printk(KERN_ERR "radeonfb: Idle Timeout !\n");
-}
-
-
-#define radeon_engine_idle()		_radeon_engine_idle(rinfo)
-#define radeon_fifo_wait(entries)	_radeon_fifo_wait(rinfo,entries)
-#define radeon_msleep(ms)		_radeon_msleep(rinfo,ms)
-
-
-/* I2C Functions */
-extern void radeon_create_i2c_busses(struct radeonfb_info *rinfo);
-extern void radeon_delete_i2c_busses(struct radeonfb_info *rinfo);
-extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
-
-/* PM Functions */
-extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-extern int radeonfb_pci_resume(struct pci_dev *pdev);
-extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep);
-extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
-
-/* Monitor probe functions */
-extern void radeon_probe_screens(struct radeonfb_info *rinfo,
-				 const char *monitor_layout, int ignore_edid);
-extern void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option);
-extern int radeon_match_mode(struct radeonfb_info *rinfo,
-			     struct fb_var_screeninfo *dest,
-			     const struct fb_var_screeninfo *src);
-
-/* Accel functions */
-extern void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region);
-extern void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
-extern int radeonfb_sync(struct fb_info *info);
-extern void radeonfb_engine_init (struct radeonfb_info *rinfo);
-extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
-
-/* Other functions */
-extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
-extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
-			       int reg_only);
-
-/* Backlight functions */
-#ifdef CONFIG_FB_RADEON_BACKLIGHT
-extern void radeonfb_bl_init(struct radeonfb_info *rinfo);
-extern void radeonfb_bl_exit(struct radeonfb_info *rinfo);
-#else
-static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {}
-static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {}
-#endif
-
-#endif /* __RADEONFB_H__ */
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
deleted file mode 100644
index 372d4aea9d1c..000000000000
--- a/drivers/video/au1100fb.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Au1100 LCD Driver.
- *
- * Rewritten for 2.6 by Embedded Alley Solutions
- * 	<source@embeddedalley.com>, based on submissions by
- *  	Karl Lessard <klessard@sunrisetelecom.com>
- *  	<c.pellegrin@exadron.com>
- *
- * PM support added by Rodolfo Giometti <giometti@linux.it>
- * Cursor enable/disable by Rodolfo Giometti <giometti@linux.it>
- *
- * Copyright 2002 MontaVista Software
- * Author: MontaVista Software, Inc.
- *		ppopov@mvista.com or source@mvista.com
- *
- * Copyright 2002 Alchemy Semiconductor
- * Author: Alchemy Semiconductor
- *
- * Based on:
- * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
- *  Created 28 Dec 1997 by Geert Uytterhoeven
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ctype.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-#define DEBUG 0
-
-#include "au1100fb.h"
-
-#define DRIVER_NAME "au1100fb"
-#define DRIVER_DESC "LCD controller driver for AU1100 processors"
-
-#define to_au1100fb_device(_info) \
-	  (_info ? container_of(_info, struct au1100fb_device, info) : NULL);
-
-/* Bitfields format supported by the controller. Note that the order of formats
- * SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the
- * right pixel format by doing rgb_bitfields[LCD_CONTROL_SBPPF_XXX >> LCD_CONTROL_SBPPF]
- */
-struct fb_bitfield rgb_bitfields[][4] =
-{
-  	/*     Red, 	   Green, 	 Blue, 	     Transp   */
-	{ { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-	{ { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-	{ { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
-	{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
-	{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
-
-	/* The last is used to describe 12bpp format */
-	{ { 8, 4, 0 },  { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
-};
-
-static struct fb_fix_screeninfo au1100fb_fix = {
-	.id		= "AU1100 FB",
-	.xpanstep 	= 1,
-	.ypanstep 	= 1,
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo au1100fb_var = {
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-/* fb_blank
- * Blank the screen. Depending on the mode, the screen will be
- * activated with the backlight color, or desactivated
- */
-static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
-{
-	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
-
-	print_dbg("fb_blank %d %p", blank_mode, fbi);
-
-	switch (blank_mode) {
-
-	case VESA_NO_BLANKING:
-		/* Turn on panel */
-		fbdev->regs->lcd_control |= LCD_CONTROL_GO;
-		au_sync();
-		break;
-
-	case VESA_VSYNC_SUSPEND:
-	case VESA_HSYNC_SUSPEND:
-	case VESA_POWERDOWN:
-		/* Turn off panel */
-		fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
-		au_sync();
-		break;
-	default:
-		break;
-
-	}
-	return 0;
-}
-
-/*
- * Set hardware with var settings. This will enable the controller with a specific
- * mode, normally validated with the fb_check_var method
-	 */
-int au1100fb_setmode(struct au1100fb_device *fbdev)
-{
-	struct fb_info *info = &fbdev->info;
-	u32 words;
-	int index;
-
-	if (!fbdev)
-		return -EINVAL;
-
-	/* Update var-dependent FB info */
-	if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) {
-		if (info->var.bits_per_pixel <= 8) {
-			/* palettized */
-			info->var.red.offset    = 0;
-			info->var.red.length    = info->var.bits_per_pixel;
-			info->var.red.msb_right = 0;
-
-			info->var.green.offset  = 0;
-			info->var.green.length  = info->var.bits_per_pixel;
-			info->var.green.msb_right = 0;
-
-			info->var.blue.offset   = 0;
-			info->var.blue.length   = info->var.bits_per_pixel;
-			info->var.blue.msb_right = 0;
-
-			info->var.transp.offset = 0;
-			info->var.transp.length = 0;
-			info->var.transp.msb_right = 0;
-
-			info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-			info->fix.line_length = info->var.xres_virtual /
-							(8/info->var.bits_per_pixel);
-		} else {
-			/* non-palettized */
-			index = (fbdev->panel->control_base & LCD_CONTROL_SBPPF_MASK) >> LCD_CONTROL_SBPPF_BIT;
-			info->var.red = rgb_bitfields[index][0];
-			info->var.green = rgb_bitfields[index][1];
-			info->var.blue = rgb_bitfields[index][2];
-			info->var.transp = rgb_bitfields[index][3];
-
-			info->fix.visual = FB_VISUAL_TRUECOLOR;
-			info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */
-		}
-	} else {
-		/* mono */
-		info->fix.visual = FB_VISUAL_MONO10;
-		info->fix.line_length = info->var.xres_virtual / 8;
-	}
-
-	info->screen_size = info->fix.line_length * info->var.yres_virtual;
-	info->var.rotate = ((fbdev->panel->control_base&LCD_CONTROL_SM_MASK) \
-				>> LCD_CONTROL_SM_BIT) * 90;
-
-	/* Determine BPP mode and format */
-	fbdev->regs->lcd_control = fbdev->panel->control_base;
-	fbdev->regs->lcd_horztiming = fbdev->panel->horztiming;
-	fbdev->regs->lcd_verttiming = fbdev->panel->verttiming;
-	fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base;
-	fbdev->regs->lcd_intenable = 0;
-	fbdev->regs->lcd_intstatus = 0;
-	fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys);
-
-	if (panel_is_dual(fbdev->panel)) {
-		/* Second panel display seconf half of screen if possible,
-		 * otherwise display the same as the first panel */
-		if (info->var.yres_virtual >= (info->var.yres << 1)) {
-			fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys +
-							  (info->fix.line_length *
-						          (info->var.yres_virtual >> 1)));
-		} else {
-			fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys);
-		}
-	}
-
-	words = info->fix.line_length / sizeof(u32);
-	if (!info->var.rotate || (info->var.rotate == 180)) {
-		words *= info->var.yres_virtual;
-		if (info->var.rotate /* 180 */) {
-			words -= (words % 8); /* should be divisable by 8 */
-		}
-	}
-	fbdev->regs->lcd_words = LCD_WRD_WRDS_N(words);
-
-	fbdev->regs->lcd_pwmdiv = 0;
-	fbdev->regs->lcd_pwmhi = 0;
-
-	/* Resume controller */
-	fbdev->regs->lcd_control |= LCD_CONTROL_GO;
-	mdelay(10);
-	au1100fb_fb_blank(VESA_NO_BLANKING, info);
-
-	return 0;
-}
-
-/* fb_setcolreg
- * Set color in LCD palette.
- */
-int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
-{
-	struct au1100fb_device *fbdev;
-	u32 *palette;
-	u32 value;
-
-	fbdev = to_au1100fb_device(fbi);
-	palette = fbdev->regs->lcd_pallettebase;
-
-	if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
-		return -EINVAL;
-
-	if (fbi->var.grayscale) {
-		/* Convert color to grayscale */
-		red = green = blue =
-			(19595 * red + 38470 * green + 7471 * blue) >> 16;
-	}
-
-	if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
-		/* Place color in the pseudopalette */
-		if (regno > 16)
-			return -EINVAL;
-
-		palette = (u32*)fbi->pseudo_palette;
-
-		red   >>= (16 - fbi->var.red.length);
-		green >>= (16 - fbi->var.green.length);
-		blue  >>= (16 - fbi->var.blue.length);
-
-		value = (red   << fbi->var.red.offset) 	|
-			(green << fbi->var.green.offset)|
-			(blue  << fbi->var.blue.offset);
-		value &= 0xFFFF;
-
-	} else if (panel_is_active(fbdev->panel)) {
-		/* COLOR TFT PALLETTIZED (use RGB 565) */
-		value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F);
-		value &= 0xFFFF;
-
-	} else if (panel_is_color(fbdev->panel)) {
-		/* COLOR STN MODE */
-		value = (((panel_swap_rgb(fbdev->panel) ? blue : red) >> 12) & 0x000F) |
-			((green >> 8) & 0x00F0) |
-			(((panel_swap_rgb(fbdev->panel) ? red : blue) >> 4) & 0x0F00);
-		value &= 0xFFF;
-	} else {
-		/* MONOCHROME MODE */
-		value = (green >> 12) & 0x000F;
-		value &= 0xF;
-	}
-
-	palette[regno] = value;
-
-	return 0;
-}
-
-/* fb_pan_display
- * Pan display in x and/or y as specified
- */
-int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
-{
-	struct au1100fb_device *fbdev;
-	int dy;
-
-	fbdev = to_au1100fb_device(fbi);
-
-	print_dbg("fb_pan_display %p %p", var, fbi);
-
-	if (!var || !fbdev) {
-		return -EINVAL;
-	}
-
-	if (var->xoffset - fbi->var.xoffset) {
-		/* No support for X panning for now! */
-		return -EINVAL;
-	}
-
-	print_dbg("fb_pan_display 2 %p %p", var, fbi);
-	dy = var->yoffset - fbi->var.yoffset;
-	if (dy) {
-
-		u32 dmaaddr;
-
-		print_dbg("Panning screen of %d lines", dy);
-
-		dmaaddr = fbdev->regs->lcd_dmaaddr0;
-		dmaaddr += (fbi->fix.line_length * dy);
-
-		/* TODO: Wait for current frame to finished */
-		fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
-
-		if (panel_is_dual(fbdev->panel)) {
-			dmaaddr = fbdev->regs->lcd_dmaaddr1;
-			dmaaddr += (fbi->fix.line_length * dy);
-			fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
-	}
-	}
-	print_dbg("fb_pan_display 3 %p %p", var, fbi);
-
-	return 0;
-}
-
-/* fb_rotate
- * Rotate the display of this angle. This doesn't seems to be used by the core,
- * but as our hardware supports it, so why not implementing it...
- */
-void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
-{
-	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
-
-	print_dbg("fb_rotate %p %d", fbi, angle);
-
-	if (fbdev && (angle > 0) && !(angle % 90)) {
-
-		fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
-
-		fbdev->regs->lcd_control &= ~(LCD_CONTROL_SM_MASK);
-		fbdev->regs->lcd_control |= ((angle/90) << LCD_CONTROL_SM_BIT);
-
-		fbdev->regs->lcd_control |= LCD_CONTROL_GO;
-	}
-}
-
-/* fb_mmap
- * Map video memory in user space. We don't use the generic fb_mmap method mainly
- * to allow the use of the TLB streaming flag (CCA=6)
- */
-int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
-{
-	struct au1100fb_device *fbdev;
-
-	fbdev = to_au1100fb_device(fbi);
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-	pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
-
-	return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len);
-}
-
-static struct fb_ops au1100fb_ops =
-{
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= au1100fb_fb_setcolreg,
-	.fb_blank		= au1100fb_fb_blank,
-	.fb_pan_display		= au1100fb_fb_pan_display,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_rotate		= au1100fb_fb_rotate,
-	.fb_mmap		= au1100fb_fb_mmap,
-};
-
-
-/*-------------------------------------------------------------------------*/
-
-static int au1100fb_setup(struct au1100fb_device *fbdev)
-{
-	char *this_opt, *options;
-	int num_panels = ARRAY_SIZE(known_lcd_panels);
-
-	if (num_panels <= 0) {
-		print_err("No LCD panels supported by driver!");
-		return -ENODEV;
-	}
-
-	if (fb_get_options(DRIVER_NAME, &options))
-		return -ENODEV;
-	if (!options)
-		return -ENODEV;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		/* Panel option */
-		if (!strncmp(this_opt, "panel:", 6)) {
-			int i;
-			this_opt += 6;
-			for (i = 0; i < num_panels; i++) {
-				if (!strncmp(this_opt, known_lcd_panels[i].name,
-					     strlen(this_opt))) {
-					fbdev->panel = &known_lcd_panels[i];
-					fbdev->panel_idx = i;
-					break;
-				}
-			}
-			if (i >= num_panels) {
-				print_warn("Panel '%s' not supported!", this_opt);
-				return -ENODEV;
-			}
-		}
-		/* Unsupported option */
-		else
-			print_warn("Unsupported option \"%s\"", this_opt);
-	}
-
-	print_info("Panel=%s", fbdev->panel->name);
-
-	return 0;
-}
-
-static int au1100fb_drv_probe(struct platform_device *dev)
-{
-	struct au1100fb_device *fbdev = NULL;
-	struct resource *regs_res;
-	unsigned long page;
-	u32 sys_clksrc;
-
-	/* Allocate new device private */
-	fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
-			     GFP_KERNEL);
-	if (!fbdev) {
-		print_err("fail to allocate device private record");
-		return -ENOMEM;
-	}
-
-	if (au1100fb_setup(fbdev))
-		goto failed;
-
-	platform_set_drvdata(dev, (void *)fbdev);
-
-	/* Allocate region for our registers and map them */
-	regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!regs_res) {
-		print_err("fail to retrieve registers resource");
-		return -EFAULT;
-	}
-
-	au1100fb_fix.mmio_start = regs_res->start;
-	au1100fb_fix.mmio_len = resource_size(regs_res);
-
-	if (!devm_request_mem_region(&dev->dev,
-				     au1100fb_fix.mmio_start,
-				     au1100fb_fix.mmio_len,
-				     DRIVER_NAME)) {
-		print_err("fail to lock memory region at 0x%08lx",
-				au1100fb_fix.mmio_start);
-		return -EBUSY;
-	}
-
-	fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(au1100fb_fix.mmio_start);
-
-	print_dbg("Register memory map at %p", fbdev->regs);
-	print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
-
-	/* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
-	fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
-		  	(fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
-
-	fbdev->fb_mem = dmam_alloc_coherent(&dev->dev,
-					    PAGE_ALIGN(fbdev->fb_len),
-					    &fbdev->fb_phys, GFP_KERNEL);
-	if (!fbdev->fb_mem) {
-		print_err("fail to allocate frambuffer (size: %dK))",
-			  fbdev->fb_len / 1024);
-		return -ENOMEM;
-	}
-
-	au1100fb_fix.smem_start = fbdev->fb_phys;
-	au1100fb_fix.smem_len = fbdev->fb_len;
-
-	/*
-	 * Set page reserved so that mmap will work. This is necessary
-	 * since we'll be remapping normal memory.
-	 */
-	for (page = (unsigned long)fbdev->fb_mem;
-	     page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
-	     page += PAGE_SIZE) {
-#ifdef CONFIG_DMA_NONCOHERENT
-		SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
-#else
-		SetPageReserved(virt_to_page(page));
-#endif
-	}
-
-	print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
-	print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
-
-	/* Setup LCD clock to AUX (48 MHz) */
-	sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL);
-	au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC);
-
-	/* load the panel info into the var struct */
-	au1100fb_var.bits_per_pixel = fbdev->panel->bpp;
-	au1100fb_var.xres = fbdev->panel->xres;
-	au1100fb_var.xres_virtual = au1100fb_var.xres;
-	au1100fb_var.yres = fbdev->panel->yres;
-	au1100fb_var.yres_virtual = au1100fb_var.yres;
-
-	fbdev->info.screen_base = fbdev->fb_mem;
-	fbdev->info.fbops = &au1100fb_ops;
-	fbdev->info.fix = au1100fb_fix;
-
-	fbdev->info.pseudo_palette =
-		devm_kzalloc(&dev->dev, sizeof(u32) * 16, GFP_KERNEL);
-	if (!fbdev->info.pseudo_palette)
-		return -ENOMEM;
-
-	if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
-		print_err("Fail to allocate colormap (%d entries)",
-			   AU1100_LCD_NBR_PALETTE_ENTRIES);
-		return -EFAULT;
-	}
-
-	fbdev->info.var = au1100fb_var;
-
-	/* Set h/w registers */
-	au1100fb_setmode(fbdev);
-
-	/* Register new framebuffer */
-	if (register_framebuffer(&fbdev->info) < 0) {
-		print_err("cannot register new framebuffer");
-		goto failed;
-	}
-
-	return 0;
-
-failed:
-	if (fbdev->fb_mem) {
-		dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
-				     fbdev->fb_phys);
-	}
-	if (fbdev->info.cmap.len != 0) {
-		fb_dealloc_cmap(&fbdev->info.cmap);
-	}
-
-	return -ENODEV;
-}
-
-int au1100fb_drv_remove(struct platform_device *dev)
-{
-	struct au1100fb_device *fbdev = NULL;
-
-	if (!dev)
-		return -ENODEV;
-
-	fbdev = platform_get_drvdata(dev);
-
-#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
-	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
-#endif
-	fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
-
-	/* Clean up all probe data */
-	unregister_framebuffer(&fbdev->info);
-
-	fb_dealloc_cmap(&fbdev->info.cmap);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static u32 sys_clksrc;
-static struct au1100fb_regs fbregs;
-
-int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct au1100fb_device *fbdev = platform_get_drvdata(dev);
-
-	if (!fbdev)
-		return 0;
-
-	/* Save the clock source state */
-	sys_clksrc = au_readl(SYS_CLKSRC);
-
-	/* Blank the LCD */
-	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
-
-	/* Stop LCD clocking */
-	au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC);
-
-	memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs));
-
-	return 0;
-}
-
-int au1100fb_drv_resume(struct platform_device *dev)
-{
-	struct au1100fb_device *fbdev = platform_get_drvdata(dev);
-
-	if (!fbdev)
-		return 0;
-
-	memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs));
-
-	/* Restart LCD clocking */
-	au_writel(sys_clksrc, SYS_CLKSRC);
-
-	/* Unblank the LCD */
-	au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info);
-
-	return 0;
-}
-#else
-#define au1100fb_drv_suspend NULL
-#define au1100fb_drv_resume NULL
-#endif
-
-static struct platform_driver au1100fb_driver = {
-	.driver = {
-		.name		= "au1100-lcd",
-		.owner          = THIS_MODULE,
-	},
-	.probe		= au1100fb_drv_probe,
-        .remove		= au1100fb_drv_remove,
-	.suspend	= au1100fb_drv_suspend,
-        .resume		= au1100fb_drv_resume,
-};
-module_platform_driver(au1100fb_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h
deleted file mode 100644
index 12d9642d5465..000000000000
--- a/drivers/video/au1100fb.h
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Hardware definitions for the Au1100 LCD controller
- *
- * Copyright 2002 MontaVista Software
- * Copyright 2002 Alchemy Semiconductor
- * Author:	Alchemy Semiconductor, MontaVista Software
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _AU1100LCD_H
-#define _AU1100LCD_H
-
-#include <asm/mach-au1x00/au1000.h>
-
-#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
-#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
-#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
-
-#if DEBUG
-#define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg)
-#else
-#define print_dbg(f, arg...) do {} while (0)
-#endif
-
-#if defined(__BIG_ENDIAN)
-#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
-#else
-#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
-#endif
-#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
-
-/********************************************************************/
-
-/* LCD controller restrictions */
-#define AU1100_LCD_MAX_XRES	800
-#define AU1100_LCD_MAX_YRES	600
-#define AU1100_LCD_MAX_BPP	16
-#define AU1100_LCD_MAX_CLK	48000000
-#define AU1100_LCD_NBR_PALETTE_ENTRIES 256
-
-/* Default number of visible screen buffer to allocate */
-#define AU1100FB_NBR_VIDEO_BUFFERS 4
-
-/********************************************************************/
-
-struct au1100fb_panel
-{
-	const char name[25];		/* Full name <vendor>_<model> */
-
-	u32   	control_base;		/* Mode-independent control values */
-	u32	clkcontrol_base;	/* Panel pixclock preferences */
-
-	u32	horztiming;
-	u32	verttiming;
-
-	u32	xres;		/* Maximum horizontal resolution */
-	u32 	yres;		/* Maximum vertical resolution */
-	u32 	bpp;		/* Maximum depth supported */
-};
-
-struct au1100fb_regs
-{
-	u32  lcd_control;
-	u32  lcd_intstatus;
-	u32  lcd_intenable;
-	u32  lcd_horztiming;
-	u32  lcd_verttiming;
-	u32  lcd_clkcontrol;
-	u32  lcd_dmaaddr0;
-	u32  lcd_dmaaddr1;
-	u32  lcd_words;
-	u32  lcd_pwmdiv;
-	u32  lcd_pwmhi;
-	u32  reserved[(0x0400-0x002C)/4];
-	u32  lcd_pallettebase[256];
-};
-
-struct au1100fb_device {
-
-	struct fb_info info;			/* FB driver info record */
-
-	struct au1100fb_panel 	*panel;		/* Panel connected to this device */
-
-	struct au1100fb_regs* 	regs;		/* Registers memory map */
-	size_t       		regs_len;
-	unsigned int 		regs_phys;
-
-	unsigned char* 		fb_mem;		/* FrameBuffer memory map */
-	size_t	      		fb_len;
-	dma_addr_t    		fb_phys;
-	int			panel_idx;
-};
-
-/********************************************************************/
-
-#define LCD_CONTROL                (AU1100_LCD_BASE + 0x0)
-  #define LCD_CONTROL_SBB_BIT      21
-  #define LCD_CONTROL_SBB_MASK     (0x3 << LCD_CONTROL_SBB_BIT)
-    #define LCD_CONTROL_SBB_1        (0 << LCD_CONTROL_SBB_BIT)
-    #define LCD_CONTROL_SBB_2        (1 << LCD_CONTROL_SBB_BIT)
-    #define LCD_CONTROL_SBB_3        (2 << LCD_CONTROL_SBB_BIT)
-    #define LCD_CONTROL_SBB_4        (3 << LCD_CONTROL_SBB_BIT)
-  #define LCD_CONTROL_SBPPF_BIT    18
-  #define LCD_CONTROL_SBPPF_MASK   (0x7 << LCD_CONTROL_SBPPF_BIT)
-    #define LCD_CONTROL_SBPPF_655    (0 << LCD_CONTROL_SBPPF_BIT)
-    #define LCD_CONTROL_SBPPF_565    (1 << LCD_CONTROL_SBPPF_BIT)
-    #define LCD_CONTROL_SBPPF_556    (2 << LCD_CONTROL_SBPPF_BIT)
-    #define LCD_CONTROL_SBPPF_1555   (3 << LCD_CONTROL_SBPPF_BIT)
-    #define LCD_CONTROL_SBPPF_5551   (4 << LCD_CONTROL_SBPPF_BIT)
-  #define LCD_CONTROL_WP           (1<<17)
-  #define LCD_CONTROL_WD           (1<<16)
-  #define LCD_CONTROL_C            (1<<15)
-  #define LCD_CONTROL_SM_BIT       13
-  #define LCD_CONTROL_SM_MASK      (0x3 << LCD_CONTROL_SM_BIT)
-    #define LCD_CONTROL_SM_0         (0 << LCD_CONTROL_SM_BIT)
-    #define LCD_CONTROL_SM_90        (1 << LCD_CONTROL_SM_BIT)
-    #define LCD_CONTROL_SM_180       (2 << LCD_CONTROL_SM_BIT)
-    #define LCD_CONTROL_SM_270       (3 << LCD_CONTROL_SM_BIT)
-  #define LCD_CONTROL_DB           (1<<12)
-  #define LCD_CONTROL_CCO          (1<<11)
-  #define LCD_CONTROL_DP           (1<<10)
-  #define LCD_CONTROL_PO_BIT       8
-  #define LCD_CONTROL_PO_MASK      (0x3 << LCD_CONTROL_PO_BIT)
-    #define LCD_CONTROL_PO_00        (0 << LCD_CONTROL_PO_BIT)
-    #define LCD_CONTROL_PO_01        (1 << LCD_CONTROL_PO_BIT)
-    #define LCD_CONTROL_PO_10        (2 << LCD_CONTROL_PO_BIT)
-    #define LCD_CONTROL_PO_11        (3 << LCD_CONTROL_PO_BIT)
-  #define LCD_CONTROL_MPI          (1<<7)
-  #define LCD_CONTROL_PT           (1<<6)
-  #define LCD_CONTROL_PC           (1<<5)
-  #define LCD_CONTROL_BPP_BIT      1
-  #define LCD_CONTROL_BPP_MASK     (0x7 << LCD_CONTROL_BPP_BIT)
-    #define LCD_CONTROL_BPP_1        (0 << LCD_CONTROL_BPP_BIT)
-    #define LCD_CONTROL_BPP_2        (1 << LCD_CONTROL_BPP_BIT)
-    #define LCD_CONTROL_BPP_4        (2 << LCD_CONTROL_BPP_BIT)
-    #define LCD_CONTROL_BPP_8        (3 << LCD_CONTROL_BPP_BIT)
-    #define LCD_CONTROL_BPP_12       (4 << LCD_CONTROL_BPP_BIT)
-    #define LCD_CONTROL_BPP_16       (5 << LCD_CONTROL_BPP_BIT)
-  #define LCD_CONTROL_GO           (1<<0)
-
-#define LCD_INTSTATUS              (AU1100_LCD_BASE + 0x4)
-#define LCD_INTENABLE              (AU1100_LCD_BASE + 0x8)
-  #define LCD_INT_SD               (1<<7)
-  #define LCD_INT_OF               (1<<6)
-  #define LCD_INT_UF               (1<<5)
-  #define LCD_INT_SA               (1<<3)
-  #define LCD_INT_SS               (1<<2)
-  #define LCD_INT_S1               (1<<1)
-  #define LCD_INT_S0               (1<<0)
-
-#define LCD_HORZTIMING             (AU1100_LCD_BASE + 0xC)
-  #define LCD_HORZTIMING_HN2_BIT   24
-  #define LCD_HORZTIMING_HN2_MASK  (0xFF << LCD_HORZTIMING_HN2_BIT)
-  #define LCD_HORZTIMING_HN2_N(N)  ((((N)-1) << LCD_HORZTIMING_HN2_BIT) & LCD_HORZTIMING_HN2_MASK)
-  #define LCD_HORZTIMING_HN1_BIT   16
-  #define LCD_HORZTIMING_HN1_MASK  (0xFF << LCD_HORZTIMING_HN1_BIT)
-  #define LCD_HORZTIMING_HN1_N(N)  ((((N)-1) << LCD_HORZTIMING_HN1_BIT) & LCD_HORZTIMING_HN1_MASK)
-  #define LCD_HORZTIMING_HPW_BIT   10
-  #define LCD_HORZTIMING_HPW_MASK  (0x3F << LCD_HORZTIMING_HPW_BIT)
-  #define LCD_HORZTIMING_HPW_N(N)  ((((N)-1) << LCD_HORZTIMING_HPW_BIT) & LCD_HORZTIMING_HPW_MASK)
-  #define LCD_HORZTIMING_PPL_BIT   0
-  #define LCD_HORZTIMING_PPL_MASK  (0x3FF << LCD_HORZTIMING_PPL_BIT)
-  #define LCD_HORZTIMING_PPL_N(N)  ((((N)-1) << LCD_HORZTIMING_PPL_BIT) & LCD_HORZTIMING_PPL_MASK)
-
-#define LCD_VERTTIMING             (AU1100_LCD_BASE + 0x10)
-  #define LCD_VERTTIMING_VN2_BIT   24
-  #define LCD_VERTTIMING_VN2_MASK  (0xFF << LCD_VERTTIMING_VN2_BIT)
-  #define LCD_VERTTIMING_VN2_N(N)  ((((N)-1) << LCD_VERTTIMING_VN2_BIT) & LCD_VERTTIMING_VN2_MASK)
-  #define LCD_VERTTIMING_VN1_BIT   16
-  #define LCD_VERTTIMING_VN1_MASK  (0xFF << LCD_VERTTIMING_VN1_BIT)
-  #define LCD_VERTTIMING_VN1_N(N)  ((((N)-1) << LCD_VERTTIMING_VN1_BIT) & LCD_VERTTIMING_VN1_MASK)
-  #define LCD_VERTTIMING_VPW_BIT   10
-  #define LCD_VERTTIMING_VPW_MASK  (0x3F << LCD_VERTTIMING_VPW_BIT)
-  #define LCD_VERTTIMING_VPW_N(N)  ((((N)-1) << LCD_VERTTIMING_VPW_BIT) & LCD_VERTTIMING_VPW_MASK)
-  #define LCD_VERTTIMING_LPP_BIT   0
-  #define LCD_VERTTIMING_LPP_MASK  (0x3FF << LCD_VERTTIMING_LPP_BIT)
-  #define LCD_VERTTIMING_LPP_N(N)  ((((N)-1) << LCD_VERTTIMING_LPP_BIT) & LCD_VERTTIMING_LPP_MASK)
-
-#define LCD_CLKCONTROL             (AU1100_LCD_BASE + 0x14)
-  #define LCD_CLKCONTROL_IB        (1<<18)
-  #define LCD_CLKCONTROL_IC        (1<<17)
-  #define LCD_CLKCONTROL_IH        (1<<16)
-  #define LCD_CLKCONTROL_IV        (1<<15)
-  #define LCD_CLKCONTROL_BF_BIT    10
-  #define LCD_CLKCONTROL_BF_MASK   (0x1F << LCD_CLKCONTROL_BF_BIT)
-  #define LCD_CLKCONTROL_BF_N(N)   ((((N)-1) << LCD_CLKCONTROL_BF_BIT) & LCD_CLKCONTROL_BF_MASK)
-  #define LCD_CLKCONTROL_PCD_BIT   0
-  #define LCD_CLKCONTROL_PCD_MASK  (0x3FF << LCD_CLKCONTROL_PCD_BIT)
-  #define LCD_CLKCONTROL_PCD_N(N)  (((N) << LCD_CLKCONTROL_PCD_BIT) & LCD_CLKCONTROL_PCD_MASK)
-
-#define LCD_DMAADDR0               (AU1100_LCD_BASE + 0x18)
-#define LCD_DMAADDR1               (AU1100_LCD_BASE + 0x1C)
-  #define LCD_DMA_SA_BIT           5
-  #define LCD_DMA_SA_MASK          (0x7FFFFFF << LCD_DMA_SA_BIT)
-  #define LCD_DMA_SA_N(N)          ((N) & LCD_DMA_SA_MASK)
-
-#define LCD_WORDS                  (AU1100_LCD_BASE + 0x20)
-  #define LCD_WRD_WRDS_BIT         0
-  #define LCD_WRD_WRDS_MASK        (0xFFFFFFFF << LCD_WRD_WRDS_BIT)
-  #define LCD_WRD_WRDS_N(N)        ((((N)-1) << LCD_WRD_WRDS_BIT) & LCD_WRD_WRDS_MASK)
-
-#define LCD_PWMDIV                 (AU1100_LCD_BASE + 0x24)
-  #define LCD_PWMDIV_EN            (1<<12)
-  #define LCD_PWMDIV_PWMDIV_BIT    0
-  #define LCD_PWMDIV_PWMDIV_MASK   (0xFFF << LCD_PWMDIV_PWMDIV_BIT)
-  #define LCD_PWMDIV_PWMDIV_N(N)   ((((N)-1) << LCD_PWMDIV_PWMDIV_BIT) & LCD_PWMDIV_PWMDIV_MASK)
-
-#define LCD_PWMHI                  (AU1100_LCD_BASE + 0x28)
-  #define LCD_PWMHI_PWMHI1_BIT     12
-  #define LCD_PWMHI_PWMHI1_MASK    (0xFFF << LCD_PWMHI_PWMHI1_BIT)
-  #define LCD_PWMHI_PWMHI1_N(N)    (((N) << LCD_PWMHI_PWMHI1_BIT) & LCD_PWMHI_PWMHI1_MASK)
-  #define LCD_PWMHI_PWMHI0_BIT     0
-  #define LCD_PWMHI_PWMHI0_MASK    (0xFFF << LCD_PWMHI_PWMHI0_BIT)
-  #define LCD_PWMHI_PWMHI0_N(N)    (((N) << LCD_PWMHI_PWMHI0_BIT) & LCD_PWMHI_PWMHI0_MASK)
-
-#define LCD_PALLETTEBASE                (AU1100_LCD_BASE + 0x400)
-  #define LCD_PALLETTE_MONO_MI_BIT      0
-  #define LCD_PALLETTE_MONO_MI_MASK     (0xF << LCD_PALLETTE_MONO_MI_BIT)
-  #define LCD_PALLETTE_MONO_MI_N(N)     (((N)<< LCD_PALLETTE_MONO_MI_BIT) & LCD_PALLETTE_MONO_MI_MASK)
-
-  #define LCD_PALLETTE_COLOR_RI_BIT     8
-  #define LCD_PALLETTE_COLOR_RI_MASK    (0xF << LCD_PALLETTE_COLOR_RI_BIT)
-  #define LCD_PALLETTE_COLOR_RI_N(N)    (((N)<< LCD_PALLETTE_COLOR_RI_BIT) & LCD_PALLETTE_COLOR_RI_MASK)
-  #define LCD_PALLETTE_COLOR_GI_BIT     4
-  #define LCD_PALLETTE_COLOR_GI_MASK    (0xF << LCD_PALLETTE_COLOR_GI_BIT)
-  #define LCD_PALLETTE_COLOR_GI_N(N)    (((N)<< LCD_PALLETTE_COLOR_GI_BIT) & LCD_PALLETTE_COLOR_GI_MASK)
-  #define LCD_PALLETTE_COLOR_BI_BIT     0
-  #define LCD_PALLETTE_COLOR_BI_MASK    (0xF << LCD_PALLETTE_COLOR_BI_BIT)
-  #define LCD_PALLETTE_COLOR_BI_N(N)    (((N)<< LCD_PALLETTE_COLOR_BI_BIT) & LCD_PALLETTE_COLOR_BI_MASK)
-
-  #define LCD_PALLETTE_TFT_DC_BIT       0
-  #define LCD_PALLETTE_TFT_DC_MASK      (0xFFFF << LCD_PALLETTE_TFT_DC_BIT)
-  #define LCD_PALLETTE_TFT_DC_N(N)      (((N)<< LCD_PALLETTE_TFT_DC_BIT) & LCD_PALLETTE_TFT_DC_MASK)
-
-/********************************************************************/
-
-/* List of panels known to work with the AU1100 LCD controller.
- * To add a new panel, enter the same specifications as the
- * Generic_TFT one, and MAKE SURE that it doesn't conflicts
- * with the controller restrictions. Restrictions are:
- *
- * STN color panels: max_bpp <= 12
- * STN mono panels: max_bpp <= 4
- * TFT panels: max_bpp <= 16
- * max_xres <= 800
- * max_yres <= 600
- */
-static struct au1100fb_panel known_lcd_panels[] =
-{
-	/* 800x600x16bpp CRT */
-	[0] = {
-		.name = "CRT_800x600_16",
-		.xres = 800,
-		.yres = 600,
-		.bpp = 16,
-		.control_base =	0x0004886A |
-			LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF |
-			LCD_CONTROL_BPP_16 | LCD_CONTROL_SBB_4,
-		.clkcontrol_base = 0x00020000,
-		.horztiming = 0x005aff1f,
-		.verttiming = 0x16000e57,
-	},
-	/* just the standard LCD */
-	[1] = {
-		.name = "WWPC LCD",
-		.xres = 240,
-		.yres = 320,
-		.bpp = 16,
-		.control_base = 0x0006806A,
-		.horztiming = 0x0A1010EF,
-		.verttiming = 0x0301013F,
-		.clkcontrol_base = 0x00018001,
-	},
-	/* Sharp 320x240 TFT panel */
-	[2] = {
-		.name = "Sharp_LQ038Q5DR01",
-		.xres = 320,
-		.yres = 240,
-		.bpp = 16,
-		.control_base =
-		( LCD_CONTROL_SBPPF_565
-		| LCD_CONTROL_C
-		| LCD_CONTROL_SM_0
-			| LCD_CONTROL_DEFAULT_PO
-		| LCD_CONTROL_PT
-		| LCD_CONTROL_PC
-		| LCD_CONTROL_BPP_16 ),
-		.horztiming =
-		( LCD_HORZTIMING_HN2_N(8)
-		| LCD_HORZTIMING_HN1_N(60)
-		| LCD_HORZTIMING_HPW_N(12)
-		| LCD_HORZTIMING_PPL_N(320) ),
-		.verttiming =
-		( LCD_VERTTIMING_VN2_N(5)
-		| LCD_VERTTIMING_VN1_N(17)
-		| LCD_VERTTIMING_VPW_N(1)
-		| LCD_VERTTIMING_LPP_N(240) ),
-		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
-	},
-
-	/* Hitachi SP14Q005 and possibly others */
-	[3] = {
-		.name = "Hitachi_SP14Qxxx",
-		.xres = 320,
-		.yres = 240,
-		.bpp = 4,
-		.control_base =
-			( LCD_CONTROL_C
-			| LCD_CONTROL_BPP_4 ),
-		.horztiming =
-			( LCD_HORZTIMING_HN2_N(1)
-			| LCD_HORZTIMING_HN1_N(1)
-			| LCD_HORZTIMING_HPW_N(1)
-			| LCD_HORZTIMING_PPL_N(320) ),
-		.verttiming =
-			( LCD_VERTTIMING_VN2_N(1)
-			| LCD_VERTTIMING_VN1_N(1)
-			| LCD_VERTTIMING_VPW_N(1)
-			| LCD_VERTTIMING_LPP_N(240) ),
-		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(4),
-	},
-
-	/* Generic 640x480 TFT panel */
-	[4] = {
-		.name = "TFT_640x480_16",
-		.xres = 640,
-		.yres = 480,
-		.bpp = 16,
-		.control_base = 0x004806a | LCD_CONTROL_DEFAULT_PO,
-		.horztiming = 0x3434d67f,
-		.verttiming = 0x0e0e39df,
-		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
-	},
-
-	 /* Pb1100 LCDB 640x480 PrimeView TFT panel */
-	[5] = {
-		.name = "PrimeView_640x480_16",
-		.xres = 640,
-		.yres = 480,
-		.bpp = 16,
-		.control_base = 0x0004886a | LCD_CONTROL_DEFAULT_PO,
-		.horztiming = 0x0e4bfe7f,
-		.verttiming = 0x210805df,
-		.clkcontrol_base = 0x00038001,
-	},
-};
-
-/********************************************************************/
-
-/* Inline helpers */
-
-#define panel_is_dual(panel)  (panel->control_base & LCD_CONTROL_DP)
-#define panel_is_active(panel)(panel->control_base & LCD_CONTROL_PT)
-#define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC)
-#define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO)
-
-#endif /* _AU1100LCD_H */
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
deleted file mode 100644
index 4cfba78a1458..000000000000
--- a/drivers/video/au1200fb.c
+++ /dev/null
@@ -1,1859 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Au1200 LCD Driver.
- *
- * Copyright 2004-2005 AMD
- * Author: AMD
- *
- * Based on:
- * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
- *  Created 28 Dec 1997 by Geert Uytterhoeven
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ctype.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/au1200fb.h>	/* platform_data */
-#include "au1200fb.h"
-
-#define DRIVER_NAME "au1200fb"
-#define DRIVER_DESC "LCD controller driver for AU1200 processors"
-
-#define DEBUG 0
-
-#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
-#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
-#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
-
-#if DEBUG
-#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)
-#else
-#define print_dbg(f, arg...) do {} while (0)
-#endif
-
-
-#define AU1200_LCD_FB_IOCTL 0x46FF
-
-#define AU1200_LCD_SET_SCREEN 1
-#define AU1200_LCD_GET_SCREEN 2
-#define AU1200_LCD_SET_WINDOW 3
-#define AU1200_LCD_GET_WINDOW 4
-#define AU1200_LCD_SET_PANEL  5
-#define AU1200_LCD_GET_PANEL  6
-
-#define SCREEN_SIZE		    (1<< 1)
-#define SCREEN_BACKCOLOR    (1<< 2)
-#define SCREEN_BRIGHTNESS   (1<< 3)
-#define SCREEN_COLORKEY     (1<< 4)
-#define SCREEN_MASK         (1<< 5)
-
-struct au1200_lcd_global_regs_t {
-	unsigned int flags;
-	unsigned int xsize;
-	unsigned int ysize;
-	unsigned int backcolor;
-	unsigned int brightness;
-	unsigned int colorkey;
-	unsigned int mask;
-	unsigned int panel_choice;
-	char panel_desc[80];
-
-};
-
-#define WIN_POSITION            (1<< 0)
-#define WIN_ALPHA_COLOR         (1<< 1)
-#define WIN_ALPHA_MODE          (1<< 2)
-#define WIN_PRIORITY            (1<< 3)
-#define WIN_CHANNEL             (1<< 4)
-#define WIN_BUFFER_FORMAT       (1<< 5)
-#define WIN_COLOR_ORDER         (1<< 6)
-#define WIN_PIXEL_ORDER         (1<< 7)
-#define WIN_SIZE                (1<< 8)
-#define WIN_COLORKEY_MODE       (1<< 9)
-#define WIN_DOUBLE_BUFFER_MODE  (1<< 10)
-#define WIN_RAM_ARRAY_MODE      (1<< 11)
-#define WIN_BUFFER_SCALE        (1<< 12)
-#define WIN_ENABLE	            (1<< 13)
-
-struct au1200_lcd_window_regs_t {
-	unsigned int flags;
-	unsigned int xpos;
-	unsigned int ypos;
-	unsigned int alpha_color;
-	unsigned int alpha_mode;
-	unsigned int priority;
-	unsigned int channel;
-	unsigned int buffer_format;
-	unsigned int color_order;
-	unsigned int pixel_order;
-	unsigned int xsize;
-	unsigned int ysize;
-	unsigned int colorkey_mode;
-	unsigned int double_buffer_mode;
-	unsigned int ram_array_mode;
-	unsigned int xscale;
-	unsigned int yscale;
-	unsigned int enable;
-};
-
-
-struct au1200_lcd_iodata_t {
-	unsigned int subcmd;
-	struct au1200_lcd_global_regs_t global;
-	struct au1200_lcd_window_regs_t window;
-};
-
-#if defined(__BIG_ENDIAN)
-#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
-#else
-#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
-#endif
-#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
-
-/* Private, per-framebuffer management information (independent of the panel itself) */
-struct au1200fb_device {
-	struct fb_info *fb_info;		/* FB driver info record */
-	struct au1200fb_platdata *pd;
-
-	int					plane;
-	unsigned char* 		fb_mem;		/* FrameBuffer memory map */
-	unsigned int		fb_len;
-	dma_addr_t    		fb_phys;
-};
-
-/********************************************************************/
-
-/* LCD controller restrictions */
-#define AU1200_LCD_MAX_XRES	1280
-#define AU1200_LCD_MAX_YRES	1024
-#define AU1200_LCD_MAX_BPP	32
-#define AU1200_LCD_MAX_CLK	96000000 /* fixme: this needs to go away ? */
-#define AU1200_LCD_NBR_PALETTE_ENTRIES 256
-
-/* Default number of visible screen buffer to allocate */
-#define AU1200FB_NBR_VIDEO_BUFFERS 1
-
-/* Default maximum number of fb devices to create */
-#define MAX_DEVICE_COUNT	4
-
-/* Default window configuration entry to use (see windows[]) */
-#define DEFAULT_WINDOW_INDEX	2
-
-/********************************************************************/
-
-static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT];
-static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
-static int device_count = MAX_DEVICE_COUNT;
-static int window_index = DEFAULT_WINDOW_INDEX;	/* default is zero */
-static int panel_index = 2; /* default is zero */
-static struct window_settings *win;
-static struct panel_settings *panel;
-static int noblanking = 1;
-static int nohwcursor = 0;
-
-struct window_settings {
-	unsigned char name[64];
-	uint32 mode_backcolor;
-	uint32 mode_colorkey;
-	uint32 mode_colorkeymsk;
-	struct {
-		int xres;
-		int yres;
-		int xpos;
-		int ypos;
-		uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
-		uint32 mode_winenable;
-	} w[4];
-};
-
-#if defined(__BIG_ENDIAN)
-#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
-#else
-#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
-#endif
-
-/*
- * Default window configurations
- */
-static struct window_settings windows[] = {
-	{ /* Index 0 */
-		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
-		/* mode_backcolor	*/ 0x006600ff,
-		/* mode_colorkey,msk*/ 0, 0,
-		{
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP,
-			/* mode_winenable*/ LCD_WINENABLE_WEN0,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 100, 100, 100, 100,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP |
-				LCD_WINCTRL1_PIPE,
-			/* mode_winenable*/ LCD_WINENABLE_WEN1,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP,
-			/* mode_winenable*/ 0,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP |
-				LCD_WINCTRL1_PIPE,
-			/* mode_winenable*/ 0,
-			},
-		},
-	},
-
-	{ /* Index 1 */
-		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
-		/* mode_backcolor	*/ 0x006600ff,
-		/* mode_colorkey,msk*/ 0, 0,
-		{
-			{
-			/* xres, yres, xpos, ypos */ 320, 240, 5, 5,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |
-				LCD_WINCTRL1_PO_00,
-			/* mode_winenable*/ LCD_WINENABLE_WEN0,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565
-				| LCD_WINCTRL1_PO_16BPP,
-			/* mode_winenable*/ 0,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 100, 100, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP |
-				LCD_WINCTRL1_PIPE,
-			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 200, 25, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP |
-				LCD_WINCTRL1_PIPE,
-			/* mode_winenable*/ 0,
-			},
-		},
-	},
-	{ /* Index 2 */
-		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
-		/* mode_backcolor	*/ 0x006600ff,
-		/* mode_colorkey,msk*/ 0, 0,
-		{
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP,
-			/* mode_winenable*/ LCD_WINENABLE_WEN0,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP,
-			/* mode_winenable*/ 0,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |
-				LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,
-			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
-			},
-			{
-			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
-			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
-				LCD_WINCTRL1_PO_16BPP |
-				LCD_WINCTRL1_PIPE,
-			/* mode_winenable*/ 0,
-			},
-		},
-	},
-	/* Need VGA 640 @ 24bpp, @ 32bpp */
-	/* Need VGA 800 @ 24bpp, @ 32bpp */
-	/* Need VGA 1024 @ 24bpp, @ 32bpp */
-};
-
-/*
- * Controller configurations for various panels.
- */
-
-struct panel_settings
-{
-	const char name[25];		/* Full name <vendor>_<model> */
-
-	struct 	fb_monspecs monspecs; 	/* FB monitor specs */
-
-	/* panel timings */
-	uint32 mode_screen;
-	uint32 mode_horztiming;
-	uint32 mode_verttiming;
-	uint32 mode_clkcontrol;
-	uint32 mode_pwmdiv;
-	uint32 mode_pwmhi;
-	uint32 mode_outmask;
-	uint32 mode_fifoctrl;
-	uint32 mode_toyclksrc;
-	uint32 mode_backlight;
-	uint32 mode_auxpll;
-#define Xres min_xres
-#define Yres min_yres
-	u32	min_xres;		/* Minimum horizontal resolution */
-	u32	max_xres;		/* Maximum horizontal resolution */
-	u32 	min_yres;		/* Minimum vertical resolution */
-	u32 	max_yres;		/* Maximum vertical resolution */
-};
-
-/********************************************************************/
-/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */
-
-/* List of panels known to work with the AU1200 LCD controller.
- * To add a new panel, enter the same specifications as the
- * Generic_TFT one, and MAKE SURE that it doesn't conflicts
- * with the controller restrictions. Restrictions are:
- *
- * STN color panels: max_bpp <= 12
- * STN mono panels: max_bpp <= 4
- * TFT panels: max_bpp <= 16
- * max_xres <= 800
- * max_yres <= 600
- */
-static struct panel_settings known_lcd_panels[] =
-{
-	[0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */
-		.name = "QVGA_320x240",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= LCD_SCREEN_SX_N(320) |
-			LCD_SCREEN_SY_N(240),
-		.mode_horztiming	= 0x00c4623b,
-		.mode_verttiming	= 0x00502814,
-		.mode_clkcontrol	= 0x00020002, /* /4=24Mhz */
-		.mode_pwmdiv		= 0x00000000,
-		.mode_pwmhi		= 0x00000000,
-		.mode_outmask	= 0x00FFFFFF,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
-		320, 320,
-		240, 240,
-	},
-
-	[1] = { /* VGA 640x480 H:30.3kHz V:58Hz */
-		.name = "VGA_640x480",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= 0x13f9df80,
-		.mode_horztiming	= 0x003c5859,
-		.mode_verttiming	= 0x00741201,
-		.mode_clkcontrol	= 0x00020001, /* /4=24Mhz */
-		.mode_pwmdiv		= 0x00000000,
-		.mode_pwmhi		= 0x00000000,
-		.mode_outmask	= 0x00FFFFFF,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
-		640, 480,
-		640, 480,
-	},
-
-	[2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */
-		.name = "SVGA_800x600",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= 0x18fa5780,
-		.mode_horztiming	= 0x00dc7e77,
-		.mode_verttiming	= 0x00584805,
-		.mode_clkcontrol	= 0x00020000, /* /2=48Mhz */
-		.mode_pwmdiv		= 0x00000000,
-		.mode_pwmhi		= 0x00000000,
-		.mode_outmask	= 0x00FFFFFF,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
-		800, 800,
-		600, 600,
-	},
-
-	[3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */
-		.name = "XVGA_1024x768",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= 0x1ffaff80,
-		.mode_horztiming	= 0x007d0e57,
-		.mode_verttiming	= 0x00740a01,
-		.mode_clkcontrol	= 0x000A0000, /* /1 */
-		.mode_pwmdiv		= 0x00000000,
-		.mode_pwmhi		= 0x00000000,
-		.mode_outmask	= 0x00FFFFFF,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 6, /* 72MHz AUXPLL */
-		1024, 1024,
-		768, 768,
-	},
-
-	[4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */
-		.name = "XVGA_1280x1024",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= 0x27fbff80,
-		.mode_horztiming	= 0x00cdb2c7,
-		.mode_verttiming	= 0x00600002,
-		.mode_clkcontrol	= 0x000A0000, /* /1 */
-		.mode_pwmdiv		= 0x00000000,
-		.mode_pwmhi		= 0x00000000,
-		.mode_outmask	= 0x00FFFFFF,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 10, /* 120MHz AUXPLL */
-		1280, 1280,
-		1024, 1024,
-	},
-
-	[5] = { /* Samsung 1024x768 TFT */
-		.name = "Samsung_1024x768_TFT",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= 0x1ffaff80,
-		.mode_horztiming	= 0x018cc677,
-		.mode_verttiming	= 0x00241217,
-		.mode_clkcontrol	= 0x00000000, /* SCB 0x1 /4=24Mhz */
-		.mode_pwmdiv		= 0x8000063f, /* SCB 0x0 */
-		.mode_pwmhi		= 0x03400000, /* SCB 0x0 */
-		.mode_outmask	= 0x00FFFFFF,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
-		1024, 1024,
-		768, 768,
-	},
-
-	[6] = { /* Toshiba 640x480 TFT */
-		.name = "Toshiba_640x480_TFT",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= LCD_SCREEN_SX_N(640) |
-			LCD_SCREEN_SY_N(480),
-		.mode_horztiming	= LCD_HORZTIMING_HPW_N(96) |
-			LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
-		.mode_verttiming	= LCD_VERTTIMING_VPW_N(2) |
-			LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32),
-		.mode_clkcontrol	= 0x00000000, /* /4=24Mhz */
-		.mode_pwmdiv		= 0x8000063f,
-		.mode_pwmhi		= 0x03400000,
-		.mode_outmask	= 0x00fcfcfc,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
-		640, 480,
-		640, 480,
-	},
-
-	[7] = { /* Sharp 320x240 TFT */
-		.name = "Sharp_320x240_TFT",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 12500,
-			.hfmax = 20000,
-			.vfmin = 38,
-			.vfmax = 81,
-			.dclkmin = 4500000,
-			.dclkmax = 6800000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= LCD_SCREEN_SX_N(320) |
-			LCD_SCREEN_SY_N(240),
-		.mode_horztiming	= LCD_HORZTIMING_HPW_N(60) |
-			LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
-		.mode_verttiming	= LCD_VERTTIMING_VPW_N(2) |
-			LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5),
-		.mode_clkcontrol	= LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/
-		.mode_pwmdiv		= 0x8000063f,
-		.mode_pwmhi		= 0x03400000,
-		.mode_outmask	= 0x00fcfcfc,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
-		320, 320,
-		240, 240,
-	},
-
-	[8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */
-		.name = "Toppoly_TD070WGCB2",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= LCD_SCREEN_SX_N(856) |
-			LCD_SCREEN_SY_N(480),
-		.mode_horztiming	= LCD_HORZTIMING_HND2_N(43) |
-			LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114),
-		.mode_verttiming	= LCD_VERTTIMING_VND2_N(20) |
-			LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
-		.mode_clkcontrol	= 0x00020001, /* /4=24Mhz */
-		.mode_pwmdiv		= 0x8000063f,
-		.mode_pwmhi		= 0x03400000,
-		.mode_outmask	= 0x00fcfcfc,
-		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
-		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
-		856, 856,
-		480, 480,
-	},
-	[9] = {
-		.name = "DB1300_800x480",
-		.monspecs = {
-			.modedb = NULL,
-			.modedb_len = 0,
-			.hfmin = 30000,
-			.hfmax = 70000,
-			.vfmin = 60,
-			.vfmax = 60,
-			.dclkmin = 6000000,
-			.dclkmax = 28000000,
-			.input = FB_DISP_RGB,
-		},
-		.mode_screen		= LCD_SCREEN_SX_N(800) |
-					  LCD_SCREEN_SY_N(480),
-		.mode_horztiming	= LCD_HORZTIMING_HPW_N(5) |
-					  LCD_HORZTIMING_HND1_N(16) |
-					  LCD_HORZTIMING_HND2_N(8),
-		.mode_verttiming	= LCD_VERTTIMING_VPW_N(4) |
-					  LCD_VERTTIMING_VND1_N(8) |
-					  LCD_VERTTIMING_VND2_N(5),
-		.mode_clkcontrol	= LCD_CLKCONTROL_PCD_N(1) |
-					  LCD_CLKCONTROL_IV |
-					  LCD_CLKCONTROL_IH,
-		.mode_pwmdiv		= 0x00000000,
-		.mode_pwmhi		= 0x00000000,
-		.mode_outmask		= 0x00FFFFFF,
-		.mode_fifoctrl		= 0x2f2f2f2f,
-		.mode_toyclksrc		= 0x00000004, /* AUXPLL directly */
-		.mode_backlight		= 0x00000000,
-		.mode_auxpll		= (48/12) * 2,
-		800, 800,
-		480, 480,
-	},
-};
-
-#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
-
-/********************************************************************/
-
-static int winbpp (unsigned int winctrl1)
-{
-	int bits = 0;
-
-	/* how many bits are needed for each pixel format */
-	switch (winctrl1 & LCD_WINCTRL1_FRM) {
-	case LCD_WINCTRL1_FRM_1BPP:
-		bits = 1;
-		break;
-	case LCD_WINCTRL1_FRM_2BPP:
-		bits = 2;
-		break;
-	case LCD_WINCTRL1_FRM_4BPP:
-		bits = 4;
-		break;
-	case LCD_WINCTRL1_FRM_8BPP:
-		bits = 8;
-		break;
-	case LCD_WINCTRL1_FRM_12BPP:
-	case LCD_WINCTRL1_FRM_16BPP655:
-	case LCD_WINCTRL1_FRM_16BPP565:
-	case LCD_WINCTRL1_FRM_16BPP556:
-	case LCD_WINCTRL1_FRM_16BPPI1555:
-	case LCD_WINCTRL1_FRM_16BPPI5551:
-	case LCD_WINCTRL1_FRM_16BPPA1555:
-	case LCD_WINCTRL1_FRM_16BPPA5551:
-		bits = 16;
-		break;
-	case LCD_WINCTRL1_FRM_24BPP:
-	case LCD_WINCTRL1_FRM_32BPP:
-		bits = 32;
-		break;
-	}
-
-	return bits;
-}
-
-static int fbinfo2index (struct fb_info *fb_info)
-{
-	int i;
-
-	for (i = 0; i < device_count; ++i) {
-		if (fb_info == _au1200fb_infos[i])
-			return i;
-	}
-	printk("au1200fb: ERROR: fbinfo2index failed!\n");
-	return -1;
-}
-
-static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
-	int xpos, int ypos)
-{
-	uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
-	int xsz, ysz;
-
-	/* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
-
-	winctrl0 = lcd->window[plane].winctrl0;
-	winctrl1 = lcd->window[plane].winctrl1;
-	winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
-	winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
-
-	/* Check for off-screen adjustments */
-	xsz = win->w[plane].xres;
-	ysz = win->w[plane].yres;
-	if ((xpos + win->w[plane].xres) > panel->Xres) {
-		/* Off-screen to the right */
-		xsz = panel->Xres - xpos; /* off by 1 ??? */
-		/*printk("off screen right\n");*/
-	}
-
-	if ((ypos + win->w[plane].yres) > panel->Yres) {
-		/* Off-screen to the bottom */
-		ysz = panel->Yres - ypos; /* off by 1 ??? */
-		/*printk("off screen bottom\n");*/
-	}
-
-	if (xpos < 0) {
-		/* Off-screen to the left */
-		xsz = win->w[plane].xres + xpos;
-		fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
-		xpos = 0;
-		/*printk("off screen left\n");*/
-	}
-
-	if (ypos < 0) {
-		/* Off-screen to the top */
-		ysz = win->w[plane].yres + ypos;
-		/* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */
-		ypos = 0;
-		/*printk("off screen top\n");*/
-	}
-
-	/* record settings */
-	win->w[plane].xpos = xpos;
-	win->w[plane].ypos = ypos;
-
-	xsz -= 1;
-	ysz -= 1;
-	winctrl0 |= (xpos << 21);
-	winctrl0 |= (ypos << 10);
-	winctrl1 |= (xsz << 11);
-	winctrl1 |= (ysz << 0);
-
-	/* Disable the window while making changes, then restore WINEN */
-	winenable = lcd->winenable & (1 << plane);
-	au_sync();
-	lcd->winenable &= ~(1 << plane);
-	lcd->window[plane].winctrl0 = winctrl0;
-	lcd->window[plane].winctrl1 = winctrl1;
-	lcd->window[plane].winbuf0 =
-	lcd->window[plane].winbuf1 = fbdev->fb_phys;
-	lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
-	lcd->winenable |= winenable;
-	au_sync();
-
-	return 0;
-}
-
-static void au1200_setpanel(struct panel_settings *newpanel,
-			    struct au1200fb_platdata *pd)
-{
-	/*
-	 * Perform global setup/init of LCD controller
-	 */
-	uint32 winenable;
-
-	/* Make sure all windows disabled */
-	winenable = lcd->winenable;
-	lcd->winenable = 0;
-	au_sync();
-	/*
-	 * Ensure everything is disabled before reconfiguring
-	 */
-	if (lcd->screen & LCD_SCREEN_SEN) {
-		/* Wait for vertical sync period */
-		lcd->intstatus = LCD_INT_SS;
-		while ((lcd->intstatus & LCD_INT_SS) == 0) {
-			au_sync();
-		}
-
-		lcd->screen &= ~LCD_SCREEN_SEN;	/*disable the controller*/
-
-		do {
-			lcd->intstatus = lcd->intstatus; /*clear interrupts*/
-			au_sync();
-		/*wait for controller to shut down*/
-		} while ((lcd->intstatus & LCD_INT_SD) == 0);
-
-		/* Call shutdown of current panel (if up) */
-		/* this must occur last, because if an external clock is driving
-		    the controller, the clock cannot be turned off before first
-			shutting down the controller.
-		 */
-		if (pd->panel_shutdown)
-			pd->panel_shutdown();
-	}
-
-	/* Newpanel == NULL indicates a shutdown operation only */
-	if (newpanel == NULL)
-		return;
-
-	panel = newpanel;
-
-	printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
-
-	/*
-	 * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
-	 */
-	if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
-	{
-		uint32 sys_clksrc;
-		au_writel(panel->mode_auxpll, SYS_AUXPLL);
-		sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
-		sys_clksrc |= panel->mode_toyclksrc;
-		au_writel(sys_clksrc, SYS_CLKSRC);
-	}
-
-	/*
-	 * Configure panel timings
-	 */
-	lcd->screen = panel->mode_screen;
-	lcd->horztiming = panel->mode_horztiming;
-	lcd->verttiming = panel->mode_verttiming;
-	lcd->clkcontrol = panel->mode_clkcontrol;
-	lcd->pwmdiv = panel->mode_pwmdiv;
-	lcd->pwmhi = panel->mode_pwmhi;
-	lcd->outmask = panel->mode_outmask;
-	lcd->fifoctrl = panel->mode_fifoctrl;
-	au_sync();
-
-	/* fixme: Check window settings to make sure still valid
-	 * for new geometry */
-#if 0
-	au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos);
-	au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos);
-	au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos);
-	au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos);
-#endif
-	lcd->winenable = winenable;
-
-	/*
-	 * Re-enable screen now that it is configured
-	 */
-	lcd->screen |= LCD_SCREEN_SEN;
-	au_sync();
-
-	/* Call init of panel */
-	if (pd->panel_init)
-		pd->panel_init();
-
-	/* FIX!!!! not appropriate on panel change!!! Global setup/init */
-	lcd->intenable = 0;
-	lcd->intstatus = ~0;
-	lcd->backcolor = win->mode_backcolor;
-
-	/* Setup Color Key - FIX!!! */
-	lcd->colorkey = win->mode_colorkey;
-	lcd->colorkeymsk = win->mode_colorkeymsk;
-
-	/* Setup HWCursor - FIX!!! Need to support this eventually */
-	lcd->hwc.cursorctrl = 0;
-	lcd->hwc.cursorpos = 0;
-	lcd->hwc.cursorcolor0 = 0;
-	lcd->hwc.cursorcolor1 = 0;
-	lcd->hwc.cursorcolor2 = 0;
-	lcd->hwc.cursorcolor3 = 0;
-
-
-#if 0
-#define D(X) printk("%25s: %08X\n", #X, X)
-	D(lcd->screen);
-	D(lcd->horztiming);
-	D(lcd->verttiming);
-	D(lcd->clkcontrol);
-	D(lcd->pwmdiv);
-	D(lcd->pwmhi);
-	D(lcd->outmask);
-	D(lcd->fifoctrl);
-	D(lcd->window[0].winctrl0);
-	D(lcd->window[0].winctrl1);
-	D(lcd->window[0].winctrl2);
-	D(lcd->window[0].winbuf0);
-	D(lcd->window[0].winbuf1);
-	D(lcd->window[0].winbufctrl);
-	D(lcd->window[1].winctrl0);
-	D(lcd->window[1].winctrl1);
-	D(lcd->window[1].winctrl2);
-	D(lcd->window[1].winbuf0);
-	D(lcd->window[1].winbuf1);
-	D(lcd->window[1].winbufctrl);
-	D(lcd->window[2].winctrl0);
-	D(lcd->window[2].winctrl1);
-	D(lcd->window[2].winctrl2);
-	D(lcd->window[2].winbuf0);
-	D(lcd->window[2].winbuf1);
-	D(lcd->window[2].winbufctrl);
-	D(lcd->window[3].winctrl0);
-	D(lcd->window[3].winctrl1);
-	D(lcd->window[3].winctrl2);
-	D(lcd->window[3].winbuf0);
-	D(lcd->window[3].winbuf1);
-	D(lcd->window[3].winbufctrl);
-	D(lcd->winenable);
-	D(lcd->intenable);
-	D(lcd->intstatus);
-	D(lcd->backcolor);
-	D(lcd->winenable);
-	D(lcd->colorkey);
-    D(lcd->colorkeymsk);
-	D(lcd->hwc.cursorctrl);
-	D(lcd->hwc.cursorpos);
-	D(lcd->hwc.cursorcolor0);
-	D(lcd->hwc.cursorcolor1);
-	D(lcd->hwc.cursorcolor2);
-	D(lcd->hwc.cursorcolor3);
-#endif
-}
-
-static void au1200_setmode(struct au1200fb_device *fbdev)
-{
-	int plane = fbdev->plane;
-	/* Window/plane setup */
-	lcd->window[plane].winctrl1 = ( 0
-		| LCD_WINCTRL1_PRI_N(plane)
-		| win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
-		) ;
-
-	au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos);
-
-	lcd->window[plane].winctrl2 = ( 0
-		| LCD_WINCTRL2_CKMODE_00
-		| LCD_WINCTRL2_DBM
-		| LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length)
-		| LCD_WINCTRL2_SCX_1
-		| LCD_WINCTRL2_SCY_1
-		) ;
-	lcd->winenable |= win->w[plane].mode_winenable;
-	au_sync();
-}
-
-
-/* Inline helpers */
-
-/*#define panel_is_dual(panel)  ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
-/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
-
-#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)
-
-/* Bitfields format supported by the controller. */
-static struct fb_bitfield rgb_bitfields[][4] = {
-  	/*     Red, 	   Green, 	 Blue, 	     Transp   */
-	[LCD_WINCTRL1_FRM_16BPP655 >> 25] =
-		{ { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-
-	[LCD_WINCTRL1_FRM_16BPP565 >> 25] =
-		{ { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-
-	[LCD_WINCTRL1_FRM_16BPP556 >> 25] =
-		{ { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
-
-	[LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =
-		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-
-	[LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =
-		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },
-
-	[LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =
-		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
-
-	[LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =
-		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
-
-	[LCD_WINCTRL1_FRM_24BPP >> 25] =
-		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },
-
-	[LCD_WINCTRL1_FRM_32BPP >> 25] =
-		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Helpers */
-
-static void au1200fb_update_fbinfo(struct fb_info *fbi)
-{
-	/* FIX!!!! This also needs to take the window pixel format into account!!! */
-
-	/* Update var-dependent FB info */
-	if (panel_is_color(panel)) {
-		if (fbi->var.bits_per_pixel <= 8) {
-			/* palettized */
-			fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-			fbi->fix.line_length = fbi->var.xres_virtual /
-				(8/fbi->var.bits_per_pixel);
-		} else {
-			/* non-palettized */
-			fbi->fix.visual = FB_VISUAL_TRUECOLOR;
-			fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);
-		}
-	} else {
-		/* mono FIX!!! mono 8 and 4 bits */
-		fbi->fix.visual = FB_VISUAL_MONO10;
-		fbi->fix.line_length = fbi->var.xres_virtual / 8;
-	}
-
-	fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;
-	print_dbg("line length: %d\n", fbi->fix.line_length);
-	print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* AU1200 framebuffer driver */
-
-/* fb_check_var
- * Validate var settings with hardware restrictions and modify it if necessary
- */
-static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
-	struct fb_info *fbi)
-{
-	struct au1200fb_device *fbdev = fbi->par;
-	u32 pixclock;
-	int screen_size, plane;
-
-	plane = fbdev->plane;
-
-	/* Make sure that the mode respect all LCD controller and
-	 * panel restrictions. */
-	var->xres = win->w[plane].xres;
-	var->yres = win->w[plane].yres;
-
-	/* No need for virtual resolution support */
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-
-	var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);
-
-	screen_size = var->xres_virtual * var->yres_virtual;
-	if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);
-	else screen_size /= (8/var->bits_per_pixel);
-
-	if (fbdev->fb_len < screen_size)
-		return -EINVAL; /* Virtual screen is to big, abort */
-
-	/* FIX!!!! what are the implicaitons of ignoring this for windows ??? */
-	/* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel
-	 * clock can only be obtain by dividing this value by an even integer.
-	 * Fallback to a slower pixel clock if necessary. */
-	pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
-	pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2);
-
-	if (AU1200_LCD_MAX_CLK % pixclock) {
-		int diff = AU1200_LCD_MAX_CLK % pixclock;
-		pixclock -= diff;
-	}
-
-	var->pixclock = KHZ2PICOS(pixclock/1000);
-#if 0
-	if (!panel_is_active(panel)) {
-		int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;
-
-		if (!panel_is_color(panel)
-			&& (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {
-			/* STN 8bit mono panel support is up to 6MHz pixclock */
-			var->pixclock = KHZ2PICOS(6000);
-		} else if (!pcd) {
-			/* Other STN panel support is up to 12MHz  */
-			var->pixclock = KHZ2PICOS(12000);
-		}
-	}
-#endif
-	/* Set bitfield accordingly */
-	switch (var->bits_per_pixel) {
-		case 16:
-		{
-			/* 16bpp True color.
-			 * These must be set to MATCH WINCTRL[FORM] */
-			int idx;
-			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
-			var->red    = rgb_bitfields[idx][0];
-			var->green  = rgb_bitfields[idx][1];
-			var->blue   = rgb_bitfields[idx][2];
-			var->transp = rgb_bitfields[idx][3];
-			break;
-		}
-
-		case 32:
-		{
-			/* 32bpp True color.
-			 * These must be set to MATCH WINCTRL[FORM] */
-			int idx;
-			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
-			var->red    = rgb_bitfields[idx][0];
-			var->green  = rgb_bitfields[idx][1];
-			var->blue   = rgb_bitfields[idx][2];
-			var->transp = rgb_bitfields[idx][3];
-			break;
-		}
-		default:
-			print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);
-			return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* fb_set_par
- * Set hardware with var settings. This will enable the controller with a
- * specific mode, normally validated with the fb_check_var method
- */
-static int au1200fb_fb_set_par(struct fb_info *fbi)
-{
-	struct au1200fb_device *fbdev = fbi->par;
-
-	au1200fb_update_fbinfo(fbi);
-	au1200_setmode(fbdev);
-
-	return 0;
-}
-
-/* fb_setcolreg
- * Set color in LCD palette.
- */
-static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-	unsigned blue, unsigned transp, struct fb_info *fbi)
-{
-	volatile u32 *palette = lcd->palette;
-	u32 value;
-
-	if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))
-		return -EINVAL;
-
-	if (fbi->var.grayscale) {
-		/* Convert color to grayscale */
-		red = green = blue =
-			(19595 * red + 38470 * green + 7471 * blue) >> 16;
-	}
-
-	if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
-		/* Place color in the pseudopalette */
-		if (regno > 16)
-			return -EINVAL;
-
-		palette = (u32*) fbi->pseudo_palette;
-
-		red   >>= (16 - fbi->var.red.length);
-		green >>= (16 - fbi->var.green.length);
-		blue  >>= (16 - fbi->var.blue.length);
-
-		value = (red   << fbi->var.red.offset) 	|
-			(green << fbi->var.green.offset)|
-			(blue  << fbi->var.blue.offset);
-		value &= 0xFFFF;
-
-	} else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {
-		/* COLOR TFT PALLETTIZED (use RGB 565) */
-		value = (red & 0xF800)|((green >> 5) &
-				0x07E0)|((blue >> 11) & 0x001F);
-		value &= 0xFFFF;
-
-	} else if (0 /*panel_is_color(fbdev->panel)*/) {
-		/* COLOR STN MODE */
-		value = 0x1234;
-		value &= 0xFFF;
-	} else {
-		/* MONOCHROME MODE */
-		value = (green >> 12) & 0x000F;
-		value &= 0xF;
-	}
-
-	palette[regno] = value;
-
-	return 0;
-}
-
-/* fb_blank
- * Blank the screen. Depending on the mode, the screen will be
- * activated with the backlight color, or desactivated
- */
-static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
-{
-	struct au1200fb_device *fbdev = fbi->par;
-
-	/* Short-circuit screen blanking */
-	if (noblanking)
-		return 0;
-
-	switch (blank_mode) {
-
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		/* printk("turn on panel\n"); */
-		au1200_setpanel(panel, fbdev->pd);
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_POWERDOWN:
-		/* printk("turn off panel\n"); */
-		au1200_setpanel(NULL, fbdev->pd);
-		break;
-	default:
-		break;
-
-	}
-
-	/* FB_BLANK_NORMAL is a soft blank */
-	return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;
-}
-
-/* fb_mmap
- * Map video memory in user space. We don't use the generic fb_mmap
- * method mainly to allow the use of the TLB streaming flag (CCA=6)
- */
-static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct au1200fb_device *fbdev = info->par;
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-	pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
-
-	return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len);
-}
-
-static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
-{
-
-	unsigned int hi1, divider;
-
-	/* SCREEN_SIZE: user cannot reset size, must switch panel choice */
-
-	if (pdata->flags & SCREEN_BACKCOLOR)
-		lcd->backcolor = pdata->backcolor;
-
-	if (pdata->flags & SCREEN_BRIGHTNESS) {
-
-		// limit brightness pwm duty to >= 30/1600
-		if (pdata->brightness < 30) {
-			pdata->brightness = 30;
-		}
-		divider = (lcd->pwmdiv & 0x3FFFF) + 1;
-		hi1 = (lcd->pwmhi >> 16) + 1;
-		hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);
-		lcd->pwmhi &= 0xFFFF;
-		lcd->pwmhi |= (hi1 << 16);
-	}
-
-	if (pdata->flags & SCREEN_COLORKEY)
-		lcd->colorkey = pdata->colorkey;
-
-	if (pdata->flags & SCREEN_MASK)
-		lcd->colorkeymsk = pdata->mask;
-	au_sync();
-}
-
-static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
-{
-	unsigned int hi1, divider;
-
-	pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;
-	pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;
-
-	pdata->backcolor = lcd->backcolor;
-	pdata->colorkey = lcd->colorkey;
-	pdata->mask = lcd->colorkeymsk;
-
-	// brightness
-	hi1 = (lcd->pwmhi >> 16) + 1;
-	divider = (lcd->pwmdiv & 0x3FFFF) + 1;
-	pdata->brightness = ((hi1 << 8) / divider) - 1;
-	au_sync();
-}
-
-static void set_window(unsigned int plane,
-	struct au1200_lcd_window_regs_t *pdata)
-{
-	unsigned int val, bpp;
-
-	/* Window control register 0 */
-	if (pdata->flags & WIN_POSITION) {
-		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |
-				LCD_WINCTRL0_OY);
-		val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);
-		val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);
-		lcd->window[plane].winctrl0 = val;
-	}
-	if (pdata->flags & WIN_ALPHA_COLOR) {
-		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);
-		val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);
-		lcd->window[plane].winctrl0 = val;
-	}
-	if (pdata->flags & WIN_ALPHA_MODE) {
-		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);
-		val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);
-		lcd->window[plane].winctrl0 = val;
-	}
-
-	/* Window control register 1 */
-	if (pdata->flags & WIN_PRIORITY) {
-		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);
-		val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);
-		lcd->window[plane].winctrl1 = val;
-	}
-	if (pdata->flags & WIN_CHANNEL) {
-		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);
-		val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);
-		lcd->window[plane].winctrl1 = val;
-	}
-	if (pdata->flags & WIN_BUFFER_FORMAT) {
-		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);
-		val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);
-		lcd->window[plane].winctrl1 = val;
-	}
-	if (pdata->flags & WIN_COLOR_ORDER) {
-		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);
-		val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);
-		lcd->window[plane].winctrl1 = val;
-	}
-	if (pdata->flags & WIN_PIXEL_ORDER) {
-		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);
-		val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);
-		lcd->window[plane].winctrl1 = val;
-	}
-	if (pdata->flags & WIN_SIZE) {
-		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |
-				LCD_WINCTRL1_SZY);
-		val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);
-		val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);
-		lcd->window[plane].winctrl1 = val;
-		/* program buffer line width */
-		bpp = winbpp(val) / 8;
-		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);
-		val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);
-		lcd->window[plane].winctrl2 = val;
-	}
-
-	/* Window control register 2 */
-	if (pdata->flags & WIN_COLORKEY_MODE) {
-		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);
-		val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);
-		lcd->window[plane].winctrl2 = val;
-	}
-	if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {
-		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);
-		val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);
-		lcd->window[plane].winctrl2 = val;
-	}
-	if (pdata->flags & WIN_RAM_ARRAY_MODE) {
-		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);
-		val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);
-		lcd->window[plane].winctrl2 = val;
-	}
-
-	/* Buffer line width programmed with WIN_SIZE */
-
-	if (pdata->flags & WIN_BUFFER_SCALE) {
-		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |
-				LCD_WINCTRL2_SCY);
-		val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);
-		val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);
-		lcd->window[plane].winctrl2 = val;
-	}
-
-	if (pdata->flags & WIN_ENABLE) {
-		val = lcd->winenable;
-		val &= ~(1<<plane);
-		val |= (pdata->enable & 1) << plane;
-		lcd->winenable = val;
-	}
-	au_sync();
-}
-
-static void get_window(unsigned int plane,
-	struct au1200_lcd_window_regs_t *pdata)
-{
-	/* Window control register 0 */
-	pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
-	pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
-	pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;
-	pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;
-
-	/* Window control register 1 */
-	pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;
-	pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;
-	pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;
-	pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;
-	pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;
-	pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1;
-	pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1;
-
-	/* Window control register 2 */
-	pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;
-	pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;
-	pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
-
-	pdata->enable = (lcd->winenable >> plane) & 1;
-	au_sync();
-}
-
-static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
-                          unsigned long arg)
-{
-	struct au1200fb_device *fbdev = info->par;
-	int plane;
-	int val;
-
-	plane = fbinfo2index(info);
-	print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
-
-	if (cmd == AU1200_LCD_FB_IOCTL) {
-		struct au1200_lcd_iodata_t iodata;
-
-		if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata)))
-			return -EFAULT;
-
-		print_dbg("FB IOCTL called\n");
-
-		switch (iodata.subcmd) {
-		case AU1200_LCD_SET_SCREEN:
-			print_dbg("AU1200_LCD_SET_SCREEN\n");
-			set_global(cmd, &iodata.global);
-			break;
-
-		case AU1200_LCD_GET_SCREEN:
-			print_dbg("AU1200_LCD_GET_SCREEN\n");
-			get_global(cmd, &iodata.global);
-			break;
-
-		case AU1200_LCD_SET_WINDOW:
-			print_dbg("AU1200_LCD_SET_WINDOW\n");
-			set_window(plane, &iodata.window);
-			break;
-
-		case AU1200_LCD_GET_WINDOW:
-			print_dbg("AU1200_LCD_GET_WINDOW\n");
-			get_window(plane, &iodata.window);
-			break;
-
-		case AU1200_LCD_SET_PANEL:
-			print_dbg("AU1200_LCD_SET_PANEL\n");
-			if ((iodata.global.panel_choice >= 0) &&
-					(iodata.global.panel_choice <
-					 NUM_PANELS))
-			{
-				struct panel_settings *newpanel;
-				panel_index = iodata.global.panel_choice;
-				newpanel = &known_lcd_panels[panel_index];
-				au1200_setpanel(newpanel, fbdev->pd);
-			}
-			break;
-
-		case AU1200_LCD_GET_PANEL:
-			print_dbg("AU1200_LCD_GET_PANEL\n");
-			iodata.global.panel_choice = panel_index;
-			break;
-
-		default:
-			return -EINVAL;
-		}
-
-		val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata));
-		if (val) {
-			print_dbg("error: could not copy %d bytes\n", val);
-			return -EFAULT;
-		}
-	}
-
-	return 0;
-}
-
-
-static struct fb_ops au1200fb_fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= au1200fb_fb_check_var,
-	.fb_set_par	= au1200fb_fb_set_par,
-	.fb_setcolreg	= au1200fb_fb_setcolreg,
-	.fb_blank	= au1200fb_fb_blank,
-	.fb_fillrect	= sys_fillrect,
-	.fb_copyarea	= sys_copyarea,
-	.fb_imageblit	= sys_imageblit,
-	.fb_read	= fb_sys_read,
-	.fb_write	= fb_sys_write,
-	.fb_sync	= NULL,
-	.fb_ioctl	= au1200fb_ioctl,
-	.fb_mmap	= au1200fb_fb_mmap,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
-{
-	/* Nothing to do for now, just clear any pending interrupt */
-	lcd->intstatus = lcd->intstatus;
-	au_sync();
-
-	return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* AU1200 LCD device probe helpers */
-
-static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
-{
-	struct fb_info *fbi = fbdev->fb_info;
-	int bpp;
-
-	fbi->fbops = &au1200fb_fb_ops;
-
-	bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
-
-	/* Copy monitor specs from panel data */
-	/* fixme: we're setting up LCD controller windows, so these dont give a
-	damn as to what the monitor specs are (the panel itself does, but that
-	isn't done here...so maybe need a generic catchall monitor setting??? */
-	memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
-
-	/* We first try the user mode passed in argument. If that failed,
-	 * or if no one has been specified, we default to the first mode of the
-	 * panel list. Note that after this call, var data will be set */
-	if (!fb_find_mode(&fbi->var,
-			  fbi,
-			  NULL, /* drv_info.opt_mode, */
-			  fbi->monspecs.modedb,
-			  fbi->monspecs.modedb_len,
-			  fbi->monspecs.modedb,
-			  bpp)) {
-
-		print_err("Cannot find valid mode for panel %s", panel->name);
-		return -EFAULT;
-	}
-
-	fbi->pseudo_palette = kcalloc(16, sizeof(u32), GFP_KERNEL);
-	if (!fbi->pseudo_palette) {
-		return -ENOMEM;
-	}
-
-	if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
-		print_err("Fail to allocate colormap (%d entries)",
-			   AU1200_LCD_NBR_PALETTE_ENTRIES);
-		kfree(fbi->pseudo_palette);
-		return -EFAULT;
-	}
-
-	strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
-	fbi->fix.smem_start = fbdev->fb_phys;
-	fbi->fix.smem_len = fbdev->fb_len;
-	fbi->fix.type = FB_TYPE_PACKED_PIXELS;
-	fbi->fix.xpanstep = 0;
-	fbi->fix.ypanstep = 0;
-	fbi->fix.mmio_start = 0;
-	fbi->fix.mmio_len = 0;
-	fbi->fix.accel = FB_ACCEL_NONE;
-
-	fbi->screen_base = (char __iomem *) fbdev->fb_mem;
-
-	au1200fb_update_fbinfo(fbi);
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-
-static int au1200fb_setup(struct au1200fb_platdata *pd)
-{
-	char *options = NULL;
-	char *this_opt, *endptr;
-	int num_panels = ARRAY_SIZE(known_lcd_panels);
-	int panel_idx = -1;
-
-	fb_get_options(DRIVER_NAME, &options);
-
-	if (!options)
-		goto out;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		/* Panel option - can be panel name,
-		 * "bs" for board-switch, or number/index */
-		if (!strncmp(this_opt, "panel:", 6)) {
-			int i;
-			long int li;
-			char *endptr;
-			this_opt += 6;
-			/* First check for index, which allows
-			 * to short circuit this mess */
-			li = simple_strtol(this_opt, &endptr, 0);
-			if (*endptr == '\0')
-				panel_idx = (int)li;
-			else if (strcmp(this_opt, "bs") == 0)
-				panel_idx = pd->panel_index();
-			else {
-				for (i = 0; i < num_panels; i++) {
-					if (!strcmp(this_opt,
-						    known_lcd_panels[i].name)) {
-						panel_idx = i;
-						break;
-					}
-				}
-			}
-			if ((panel_idx < 0) || (panel_idx >= num_panels))
-				print_warn("Panel %s not supported!", this_opt);
-			else
-				panel_index = panel_idx;
-
-		} else if (strncmp(this_opt, "nohwcursor", 10) == 0)
-			nohwcursor = 1;
-		else if (strncmp(this_opt, "devices:", 8) == 0) {
-			this_opt += 8;
-			device_count = simple_strtol(this_opt, &endptr, 0);
-			if ((device_count < 0) ||
-			    (device_count > MAX_DEVICE_COUNT))
-				device_count = MAX_DEVICE_COUNT;
-		} else if (strncmp(this_opt, "wincfg:", 7) == 0) {
-			this_opt += 7;
-			window_index = simple_strtol(this_opt, &endptr, 0);
-			if ((window_index < 0) ||
-			    (window_index >= ARRAY_SIZE(windows)))
-				window_index = DEFAULT_WINDOW_INDEX;
-		} else if (strncmp(this_opt, "off", 3) == 0)
-			return 1;
-		else
-			print_warn("Unsupported option \"%s\"", this_opt);
-	}
-
-out:
-	return 0;
-}
-
-/* AU1200 LCD controller device driver */
-static int au1200fb_drv_probe(struct platform_device *dev)
-{
-	struct au1200fb_device *fbdev;
-	struct au1200fb_platdata *pd;
-	struct fb_info *fbi = NULL;
-	unsigned long page;
-	int bpp, plane, ret, irq;
-
-	print_info("" DRIVER_DESC "");
-
-	pd = dev->dev.platform_data;
-	if (!pd)
-		return -ENODEV;
-
-	/* Setup driver with options */
-	if (au1200fb_setup(pd))
-		return -ENODEV;
-
-	/* Point to the panel selected */
-	panel = &known_lcd_panels[panel_index];
-	win = &windows[window_index];
-
-	printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
-	printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
-
-	/* shut gcc up */
-	ret = 0;
-	fbdev = NULL;
-
-	for (plane = 0; plane < device_count; ++plane) {
-		bpp = winbpp(win->w[plane].mode_winctrl1);
-		if (win->w[plane].xres == 0)
-			win->w[plane].xres = panel->Xres;
-		if (win->w[plane].yres == 0)
-			win->w[plane].yres = panel->Yres;
-
-		fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
-					&dev->dev);
-		if (!fbi)
-			goto failed;
-
-		_au1200fb_infos[plane] = fbi;
-		fbdev = fbi->par;
-		fbdev->fb_info = fbi;
-		fbdev->pd = pd;
-
-		fbdev->plane = plane;
-
-		/* Allocate the framebuffer to the maximum screen size */
-		fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
-
-		fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev,
-				PAGE_ALIGN(fbdev->fb_len),
-				&fbdev->fb_phys, GFP_KERNEL);
-		if (!fbdev->fb_mem) {
-			print_err("fail to allocate frambuffer (size: %dK))",
-				  fbdev->fb_len / 1024);
-			return -ENOMEM;
-		}
-
-		/*
-		 * Set page reserved so that mmap will work. This is necessary
-		 * since we'll be remapping normal memory.
-		 */
-		for (page = (unsigned long)fbdev->fb_phys;
-		     page < PAGE_ALIGN((unsigned long)fbdev->fb_phys +
-			     fbdev->fb_len);
-		     page += PAGE_SIZE) {
-			SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */
-		}
-		print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
-		print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
-
-		/* Init FB data */
-		if ((ret = au1200fb_init_fbinfo(fbdev)) < 0)
-			goto failed;
-
-		/* Register new framebuffer */
-		ret = register_framebuffer(fbi);
-		if (ret < 0) {
-			print_err("cannot register new framebuffer");
-			goto failed;
-		}
-
-		au1200fb_fb_set_par(fbi);
-
-#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
-		if (plane == 0)
-			if (fb_prepare_logo(fbi, FB_ROTATE_UR)) {
-				/* Start display and show logo on boot */
-				fb_set_cmap(&fbi->cmap, fbi);
-				fb_show_logo(fbi, FB_ROTATE_UR);
-			}
-#endif
-	}
-
-	/* Now hook interrupt too */
-	irq = platform_get_irq(dev, 0);
-	ret = request_irq(irq, au1200fb_handle_irq,
-			  IRQF_SHARED, "lcd", (void *)dev);
-	if (ret) {
-		print_err("fail to request interrupt line %d (err: %d)",
-			  irq, ret);
-		goto failed;
-	}
-
-	platform_set_drvdata(dev, pd);
-
-	/* Kickstart the panel */
-	au1200_setpanel(panel, pd);
-
-	return 0;
-
-failed:
-	/* NOTE: This only does the current plane/window that failed; others are still active */
-	if (fbi) {
-		if (fbi->cmap.len != 0)
-			fb_dealloc_cmap(&fbi->cmap);
-		kfree(fbi->pseudo_palette);
-	}
-	if (plane == 0)
-		free_irq(AU1200_LCD_INT, (void*)dev);
-	return ret;
-}
-
-static int au1200fb_drv_remove(struct platform_device *dev)
-{
-	struct au1200fb_platdata *pd = platform_get_drvdata(dev);
-	struct au1200fb_device *fbdev;
-	struct fb_info *fbi;
-	int plane;
-
-	/* Turn off the panel */
-	au1200_setpanel(NULL, pd);
-
-	for (plane = 0; plane < device_count; ++plane)	{
-		fbi = _au1200fb_infos[plane];
-		fbdev = fbi->par;
-
-		/* Clean up all probe data */
-		unregister_framebuffer(fbi);
-		if (fbi->cmap.len != 0)
-			fb_dealloc_cmap(&fbi->cmap);
-		kfree(fbi->pseudo_palette);
-
-		framebuffer_release(fbi);
-		_au1200fb_infos[plane] = NULL;
-	}
-
-	free_irq(platform_get_irq(dev, 0), (void *)dev);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int au1200fb_drv_suspend(struct device *dev)
-{
-	struct au1200fb_platdata *pd = dev_get_drvdata(dev);
-	au1200_setpanel(NULL, pd);
-
-	lcd->outmask = 0;
-	au_sync();
-
-	return 0;
-}
-
-static int au1200fb_drv_resume(struct device *dev)
-{
-	struct au1200fb_platdata *pd = dev_get_drvdata(dev);
-	struct fb_info *fbi;
-	int i;
-
-	/* Kickstart the panel */
-	au1200_setpanel(panel, pd);
-
-	for (i = 0; i < device_count; i++) {
-		fbi = _au1200fb_infos[i];
-		au1200fb_fb_set_par(fbi);
-	}
-
-	return 0;
-}
-
-static const struct dev_pm_ops au1200fb_pmops = {
-	.suspend	= au1200fb_drv_suspend,
-	.resume		= au1200fb_drv_resume,
-	.freeze		= au1200fb_drv_suspend,
-	.thaw		= au1200fb_drv_resume,
-};
-
-#define AU1200FB_PMOPS	(&au1200fb_pmops)
-
-#else
-#define AU1200FB_PMOPS	NULL
-#endif /* CONFIG_PM */
-
-static struct platform_driver au1200fb_driver = {
-	.driver = {
-		.name	= "au1200-lcd",
-		.owner	= THIS_MODULE,
-		.pm	= AU1200FB_PMOPS,
-	},
-	.probe		= au1200fb_drv_probe,
-	.remove		= au1200fb_drv_remove,
-};
-module_platform_driver(au1200fb_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/au1200fb.h b/drivers/video/au1200fb.h
deleted file mode 100644
index e2672714d8d4..000000000000
--- a/drivers/video/au1200fb.h
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Hardware definitions for the Au1200 LCD controller
- *
- * Copyright 2004 AMD
- * Author:	AMD
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _AU1200LCD_H
-#define _AU1200LCD_H
-
-/********************************************************************/
-#define AU1200_LCD_ADDR		0xB5000000
-
-#define uint8 unsigned char
-#define uint32 unsigned int
-
-struct au1200_lcd {
-	volatile uint32	reserved0;
-	volatile uint32	screen;
-	volatile uint32	backcolor;
-	volatile uint32	horztiming;
-	volatile uint32	verttiming;
-	volatile uint32	clkcontrol;
-	volatile uint32	pwmdiv;
-	volatile uint32	pwmhi;
-	volatile uint32	reserved1;
-	volatile uint32	winenable;
-	volatile uint32	colorkey;
-	volatile uint32	colorkeymsk;
-	struct
-	{
-		volatile uint32	cursorctrl;
-		volatile uint32	cursorpos;
-		volatile uint32	cursorcolor0;
-		volatile uint32	cursorcolor1;
-		volatile uint32	cursorcolor2;
-		uint32	cursorcolor3;
-	} hwc;
-	volatile uint32	intstatus;
-	volatile uint32	intenable;
-	volatile uint32	outmask;
-	volatile uint32	fifoctrl;
-	uint32	reserved2[(0x0100-0x0058)/4];
-	struct
-	{
-		volatile uint32	winctrl0;
-		volatile uint32	winctrl1;
-		volatile uint32	winctrl2;
-		volatile uint32	winbuf0;
-		volatile uint32	winbuf1;
-		volatile uint32	winbufctrl;
-		uint32	winreserved0;
-		uint32	winreserved1;
-	} window[4];
-
-	uint32	reserved3[(0x0400-0x0180)/4];
-
-	volatile uint32	palette[(0x0800-0x0400)/4];
-
-	volatile uint8	cursorpattern[256];
-};
-
-/* lcd_screen */
-#define LCD_SCREEN_SEN		(1<<31)
-#define LCD_SCREEN_SX		(0x07FF<<19)
-#define LCD_SCREEN_SY		(0x07FF<< 8)
-#define LCD_SCREEN_SWP		(1<<7)
-#define LCD_SCREEN_SWD		(1<<6)
-#define LCD_SCREEN_PT		(7<<0)
-#define LCD_SCREEN_PT_TFT	(0<<0)
-#define LCD_SCREEN_SX_N(WIDTH)	((WIDTH-1)<<19)
-#define LCD_SCREEN_SY_N(HEIGHT)	((HEIGHT-1)<<8)
-#define LCD_SCREEN_PT_CSTN	(1<<0)
-#define LCD_SCREEN_PT_CDSTN	(2<<0)
-#define LCD_SCREEN_PT_M8STN	(3<<0)
-#define LCD_SCREEN_PT_M4STN	(4<<0)
-
-/* lcd_backcolor */
-#define LCD_BACKCOLOR_SBGR		(0xFF<<16)
-#define LCD_BACKCOLOR_SBGG		(0xFF<<8)
-#define LCD_BACKCOLOR_SBGB		(0xFF<<0)
-#define LCD_BACKCOLOR_SBGR_N(N)	((N)<<16)
-#define LCD_BACKCOLOR_SBGG_N(N)	((N)<<8)
-#define LCD_BACKCOLOR_SBGB_N(N)	((N)<<0)
-
-/* lcd_winenable */
-#define LCD_WINENABLE_WEN3		(1<<3)
-#define LCD_WINENABLE_WEN2		(1<<2)
-#define LCD_WINENABLE_WEN1		(1<<1)
-#define LCD_WINENABLE_WEN0		(1<<0)
-
-/* lcd_colorkey */
-#define LCD_COLORKEY_CKR		(0xFF<<16)
-#define LCD_COLORKEY_CKG		(0xFF<<8)
-#define LCD_COLORKEY_CKB		(0xFF<<0)
-#define LCD_COLORKEY_CKR_N(N)	((N)<<16)
-#define LCD_COLORKEY_CKG_N(N)	((N)<<8)
-#define LCD_COLORKEY_CKB_N(N)	((N)<<0)
-
-/* lcd_colorkeymsk */
-#define LCD_COLORKEYMSK_CKMR		(0xFF<<16)
-#define LCD_COLORKEYMSK_CKMG		(0xFF<<8)
-#define LCD_COLORKEYMSK_CKMB		(0xFF<<0)
-#define LCD_COLORKEYMSK_CKMR_N(N)	((N)<<16)
-#define LCD_COLORKEYMSK_CKMG_N(N)	((N)<<8)
-#define LCD_COLORKEYMSK_CKMB_N(N)	((N)<<0)
-
-/* lcd windows control 0 */
-#define LCD_WINCTRL0_OX		(0x07FF<<21)
-#define LCD_WINCTRL0_OY		(0x07FF<<10)
-#define LCD_WINCTRL0_A		(0x00FF<<2)
-#define LCD_WINCTRL0_AEN	(1<<1)
-#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
-#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
-#define LCD_WINCTRL0_A_N(N) ((N)<<2)
-
-/* lcd windows control 1 */
-#define LCD_WINCTRL1_PRI	(3<<30)
-#define LCD_WINCTRL1_PIPE	(1<<29)
-#define LCD_WINCTRL1_FRM	(0xF<<25)
-#define LCD_WINCTRL1_CCO	(1<<24)
-#define LCD_WINCTRL1_PO		(3<<22)
-#define LCD_WINCTRL1_SZX	(0x07FF<<11)
-#define LCD_WINCTRL1_SZY	(0x07FF<<0)
-#define LCD_WINCTRL1_FRM_1BPP	(0<<25)
-#define LCD_WINCTRL1_FRM_2BPP	(1<<25)
-#define LCD_WINCTRL1_FRM_4BPP	(2<<25)
-#define LCD_WINCTRL1_FRM_8BPP	(3<<25)
-#define LCD_WINCTRL1_FRM_12BPP	(4<<25)
-#define LCD_WINCTRL1_FRM_16BPP655	(5<<25)
-#define LCD_WINCTRL1_FRM_16BPP565	(6<<25)
-#define LCD_WINCTRL1_FRM_16BPP556	(7<<25)
-#define LCD_WINCTRL1_FRM_16BPPI1555	(8<<25)
-#define LCD_WINCTRL1_FRM_16BPPI5551	(9<<25)
-#define LCD_WINCTRL1_FRM_16BPPA1555	(10<<25)
-#define LCD_WINCTRL1_FRM_16BPPA5551	(11<<25)
-#define LCD_WINCTRL1_FRM_24BPP		(12<<25)
-#define LCD_WINCTRL1_FRM_32BPP		(13<<25)
-#define LCD_WINCTRL1_PRI_N(N)	((N)<<30)
-#define LCD_WINCTRL1_PO_00		(0<<22)
-#define LCD_WINCTRL1_PO_01		(1<<22)
-#define LCD_WINCTRL1_PO_10		(2<<22)
-#define LCD_WINCTRL1_PO_11		(3<<22)
-#define LCD_WINCTRL1_SZX_N(N)	((N-1)<<11)
-#define LCD_WINCTRL1_SZY_N(N)	((N-1)<<0)
-
-/* lcd windows control 2 */
-#define LCD_WINCTRL2_CKMODE		(3<<24)
-#define LCD_WINCTRL2_DBM		(1<<23)
-#define LCD_WINCTRL2_RAM		(3<<21)
-#define LCD_WINCTRL2_BX			(0x1FFF<<8)
-#define LCD_WINCTRL2_SCX		(0xF<<4)
-#define LCD_WINCTRL2_SCY		(0xF<<0)
-#define LCD_WINCTRL2_CKMODE_00		(0<<24)
-#define LCD_WINCTRL2_CKMODE_01		(1<<24)
-#define LCD_WINCTRL2_CKMODE_10		(2<<24)
-#define LCD_WINCTRL2_CKMODE_11		(3<<24)
-#define LCD_WINCTRL2_RAM_NONE		(0<<21)
-#define LCD_WINCTRL2_RAM_PALETTE	(1<<21)
-#define LCD_WINCTRL2_RAM_GAMMA		(2<<21)
-#define LCD_WINCTRL2_RAM_BUFFER		(3<<21)
-#define LCD_WINCTRL2_BX_N(N)	((N)<<8)
-#define LCD_WINCTRL2_SCX_1		(0<<4)
-#define LCD_WINCTRL2_SCX_2		(1<<4)
-#define LCD_WINCTRL2_SCX_4		(2<<4)
-#define LCD_WINCTRL2_SCY_1		(0<<0)
-#define LCD_WINCTRL2_SCY_2		(1<<0)
-#define LCD_WINCTRL2_SCY_4		(2<<0)
-
-/* lcd windows buffer control */
-#define LCD_WINBUFCTRL_DB		(1<<1)
-#define LCD_WINBUFCTRL_DBN		(1<<0)
-
-/* lcd_intstatus, lcd_intenable */
-#define LCD_INT_IFO				(0xF<<14)
-#define LCD_INT_IFU				(0xF<<10)
-#define LCD_INT_OFO				(1<<9)
-#define LCD_INT_OFU				(1<<8)
-#define LCD_INT_WAIT			(1<<3)
-#define LCD_INT_SD				(1<<2)
-#define LCD_INT_SA				(1<<1)
-#define LCD_INT_SS				(1<<0)
-
-/* lcd_horztiming */
-#define LCD_HORZTIMING_HND2		(0x1FF<<18)
-#define LCD_HORZTIMING_HND1		(0x1FF<<9)
-#define LCD_HORZTIMING_HPW		(0x1FF<<0)
-#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
-#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
-#define LCD_HORZTIMING_HPW_N(N)	(((N)-1)<<0)
-
-/* lcd_verttiming */
-#define LCD_VERTTIMING_VND2		(0x1FF<<18)
-#define LCD_VERTTIMING_VND1		(0x1FF<<9)
-#define LCD_VERTTIMING_VPW		(0x1FF<<0)
-#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
-#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
-#define LCD_VERTTIMING_VPW_N(N)	(((N)-1)<<0)
-
-/* lcd_clkcontrol */
-#define LCD_CLKCONTROL_EXT		(1<<22)
-#define LCD_CLKCONTROL_DELAY	(3<<20)
-#define LCD_CLKCONTROL_CDD		(1<<19)
-#define LCD_CLKCONTROL_IB		(1<<18)
-#define LCD_CLKCONTROL_IC		(1<<17)
-#define LCD_CLKCONTROL_IH		(1<<16)
-#define LCD_CLKCONTROL_IV		(1<<15)
-#define LCD_CLKCONTROL_BF		(0x1F<<10)
-#define LCD_CLKCONTROL_PCD		(0x3FF<<0)
-#define LCD_CLKCONTROL_BF_N(N)	(((N)-1)<<10)
-#define LCD_CLKCONTROL_PCD_N(N)	((N)<<0)
-
-/* lcd_pwmdiv */
-#define LCD_PWMDIV_EN			(1<<31)
-#define LCD_PWMDIV_PWMDIV		(0x1FFFF<<0)
-#define LCD_PWMDIV_PWMDIV_N(N)	((N)<<0)
-
-/* lcd_pwmhi */
-#define LCD_PWMHI_PWMHI1		(0xFFFF<<16)
-#define LCD_PWMHI_PWMHI0		(0xFFFF<<0)
-#define LCD_PWMHI_PWMHI1_N(N)	((N)<<16)
-#define LCD_PWMHI_PWMHI0_N(N)	((N)<<0)
-
-/* lcd_hwccon */
-#define LCD_HWCCON_EN			(1<<0)
-
-/* lcd_cursorpos */
-#define LCD_CURSORPOS_HWCXOFF		(0x1F<<27)
-#define LCD_CURSORPOS_HWCXPOS		(0x07FF<<16)
-#define LCD_CURSORPOS_HWCYOFF		(0x1F<<11)
-#define LCD_CURSORPOS_HWCYPOS		(0x07FF<<0)
-#define LCD_CURSORPOS_HWCXOFF_N(N)	((N)<<27)
-#define LCD_CURSORPOS_HWCXPOS_N(N)	((N)<<16)
-#define LCD_CURSORPOS_HWCYOFF_N(N)	((N)<<11)
-#define LCD_CURSORPOS_HWCYPOS_N(N)	((N)<<0)
-
-/* lcd_cursorcolor */
-#define LCD_CURSORCOLOR_HWCA		(0xFF<<24)
-#define LCD_CURSORCOLOR_HWCR		(0xFF<<16)
-#define LCD_CURSORCOLOR_HWCG		(0xFF<<8)
-#define LCD_CURSORCOLOR_HWCB		(0xFF<<0)
-#define LCD_CURSORCOLOR_HWCA_N(N)	((N)<<24)
-#define LCD_CURSORCOLOR_HWCR_N(N)	((N)<<16)
-#define LCD_CURSORCOLOR_HWCG_N(N)	((N)<<8)
-#define LCD_CURSORCOLOR_HWCB_N(N)	((N)<<0)
-
-/* lcd_fifoctrl */
-#define LCD_FIFOCTRL_F3IF		(1<<29)
-#define LCD_FIFOCTRL_F3REQ		(0x1F<<24)
-#define LCD_FIFOCTRL_F2IF		(1<<29)
-#define LCD_FIFOCTRL_F2REQ		(0x1F<<16)
-#define LCD_FIFOCTRL_F1IF		(1<<29)
-#define LCD_FIFOCTRL_F1REQ		(0x1F<<8)
-#define LCD_FIFOCTRL_F0IF		(1<<29)
-#define LCD_FIFOCTRL_F0REQ		(0x1F<<0)
-#define LCD_FIFOCTRL_F3REQ_N(N)	((N-1)<<24)
-#define LCD_FIFOCTRL_F2REQ_N(N)	((N-1)<<16)
-#define LCD_FIFOCTRL_F1REQ_N(N)	((N-1)<<8)
-#define LCD_FIFOCTRL_F0REQ_N(N)	((N-1)<<0)
-
-/* lcd_outmask */
-#define LCD_OUTMASK_MASK		(0x00FFFFFF)
-
-/********************************************************************/
-#endif /* _AU1200LCD_H */
-/*
- * BRIEF MODULE DESCRIPTION
- *	Hardware definitions for the Au1200 LCD controller
- *
- * Copyright 2004 AMD
- * Author:	AMD
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _AU1200LCD_H
-#define _AU1200LCD_H
-
-/********************************************************************/
-#define AU1200_LCD_ADDR		0xB5000000
-
-#define uint8 unsigned char
-#define uint32 unsigned int
-
-struct au1200_lcd {
-	volatile uint32	reserved0;
-	volatile uint32	screen;
-	volatile uint32	backcolor;
-	volatile uint32	horztiming;
-	volatile uint32	verttiming;
-	volatile uint32	clkcontrol;
-	volatile uint32	pwmdiv;
-	volatile uint32	pwmhi;
-	volatile uint32	reserved1;
-	volatile uint32	winenable;
-	volatile uint32	colorkey;
-	volatile uint32	colorkeymsk;
-	struct
-	{
-		volatile uint32	cursorctrl;
-		volatile uint32	cursorpos;
-		volatile uint32	cursorcolor0;
-		volatile uint32	cursorcolor1;
-		volatile uint32	cursorcolor2;
-		uint32	cursorcolor3;
-	} hwc;
-	volatile uint32	intstatus;
-	volatile uint32	intenable;
-	volatile uint32	outmask;
-	volatile uint32	fifoctrl;
-	uint32	reserved2[(0x0100-0x0058)/4];
-	struct
-	{
-		volatile uint32	winctrl0;
-		volatile uint32	winctrl1;
-		volatile uint32	winctrl2;
-		volatile uint32	winbuf0;
-		volatile uint32	winbuf1;
-		volatile uint32	winbufctrl;
-		uint32	winreserved0;
-		uint32	winreserved1;
-	} window[4];
-
-	uint32	reserved3[(0x0400-0x0180)/4];
-
-	volatile uint32	palette[(0x0800-0x0400)/4];
-
-	volatile uint8	cursorpattern[256];
-};
-
-/* lcd_screen */
-#define LCD_SCREEN_SEN		(1<<31)
-#define LCD_SCREEN_SX		(0x07FF<<19)
-#define LCD_SCREEN_SY		(0x07FF<< 8)
-#define LCD_SCREEN_SWP		(1<<7)
-#define LCD_SCREEN_SWD		(1<<6)
-#define LCD_SCREEN_PT		(7<<0)
-#define LCD_SCREEN_PT_TFT	(0<<0)
-#define LCD_SCREEN_SX_N(WIDTH)	((WIDTH-1)<<19)
-#define LCD_SCREEN_SY_N(HEIGHT)	((HEIGHT-1)<<8)
-#define LCD_SCREEN_PT_CSTN	(1<<0)
-#define LCD_SCREEN_PT_CDSTN	(2<<0)
-#define LCD_SCREEN_PT_M8STN	(3<<0)
-#define LCD_SCREEN_PT_M4STN	(4<<0)
-
-/* lcd_backcolor */
-#define LCD_BACKCOLOR_SBGR		(0xFF<<16)
-#define LCD_BACKCOLOR_SBGG		(0xFF<<8)
-#define LCD_BACKCOLOR_SBGB		(0xFF<<0)
-#define LCD_BACKCOLOR_SBGR_N(N)	((N)<<16)
-#define LCD_BACKCOLOR_SBGG_N(N)	((N)<<8)
-#define LCD_BACKCOLOR_SBGB_N(N)	((N)<<0)
-
-/* lcd_winenable */
-#define LCD_WINENABLE_WEN3		(1<<3)
-#define LCD_WINENABLE_WEN2		(1<<2)
-#define LCD_WINENABLE_WEN1		(1<<1)
-#define LCD_WINENABLE_WEN0		(1<<0)
-
-/* lcd_colorkey */
-#define LCD_COLORKEY_CKR		(0xFF<<16)
-#define LCD_COLORKEY_CKG		(0xFF<<8)
-#define LCD_COLORKEY_CKB		(0xFF<<0)
-#define LCD_COLORKEY_CKR_N(N)	((N)<<16)
-#define LCD_COLORKEY_CKG_N(N)	((N)<<8)
-#define LCD_COLORKEY_CKB_N(N)	((N)<<0)
-
-/* lcd_colorkeymsk */
-#define LCD_COLORKEYMSK_CKMR		(0xFF<<16)
-#define LCD_COLORKEYMSK_CKMG		(0xFF<<8)
-#define LCD_COLORKEYMSK_CKMB		(0xFF<<0)
-#define LCD_COLORKEYMSK_CKMR_N(N)	((N)<<16)
-#define LCD_COLORKEYMSK_CKMG_N(N)	((N)<<8)
-#define LCD_COLORKEYMSK_CKMB_N(N)	((N)<<0)
-
-/* lcd windows control 0 */
-#define LCD_WINCTRL0_OX		(0x07FF<<21)
-#define LCD_WINCTRL0_OY		(0x07FF<<10)
-#define LCD_WINCTRL0_A		(0x00FF<<2)
-#define LCD_WINCTRL0_AEN	(1<<1)
-#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
-#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
-#define LCD_WINCTRL0_A_N(N) ((N)<<2)
-
-/* lcd windows control 1 */
-#define LCD_WINCTRL1_PRI	(3<<30)
-#define LCD_WINCTRL1_PIPE	(1<<29)
-#define LCD_WINCTRL1_FRM	(0xF<<25)
-#define LCD_WINCTRL1_CCO	(1<<24)
-#define LCD_WINCTRL1_PO		(3<<22)
-#define LCD_WINCTRL1_SZX	(0x07FF<<11)
-#define LCD_WINCTRL1_SZY	(0x07FF<<0)
-#define LCD_WINCTRL1_FRM_1BPP	(0<<25)
-#define LCD_WINCTRL1_FRM_2BPP	(1<<25)
-#define LCD_WINCTRL1_FRM_4BPP	(2<<25)
-#define LCD_WINCTRL1_FRM_8BPP	(3<<25)
-#define LCD_WINCTRL1_FRM_12BPP	(4<<25)
-#define LCD_WINCTRL1_FRM_16BPP655	(5<<25)
-#define LCD_WINCTRL1_FRM_16BPP565	(6<<25)
-#define LCD_WINCTRL1_FRM_16BPP556	(7<<25)
-#define LCD_WINCTRL1_FRM_16BPPI1555	(8<<25)
-#define LCD_WINCTRL1_FRM_16BPPI5551	(9<<25)
-#define LCD_WINCTRL1_FRM_16BPPA1555	(10<<25)
-#define LCD_WINCTRL1_FRM_16BPPA5551	(11<<25)
-#define LCD_WINCTRL1_FRM_24BPP		(12<<25)
-#define LCD_WINCTRL1_FRM_32BPP		(13<<25)
-#define LCD_WINCTRL1_PRI_N(N)	((N)<<30)
-#define LCD_WINCTRL1_PO_00		(0<<22)
-#define LCD_WINCTRL1_PO_01		(1<<22)
-#define LCD_WINCTRL1_PO_10		(2<<22)
-#define LCD_WINCTRL1_PO_11		(3<<22)
-#define LCD_WINCTRL1_SZX_N(N)	((N-1)<<11)
-#define LCD_WINCTRL1_SZY_N(N)	((N-1)<<0)
-
-/* lcd windows control 2 */
-#define LCD_WINCTRL2_CKMODE		(3<<24)
-#define LCD_WINCTRL2_DBM		(1<<23)
-#define LCD_WINCTRL2_RAM		(3<<21)
-#define LCD_WINCTRL2_BX			(0x1FFF<<8)
-#define LCD_WINCTRL2_SCX		(0xF<<4)
-#define LCD_WINCTRL2_SCY		(0xF<<0)
-#define LCD_WINCTRL2_CKMODE_00		(0<<24)
-#define LCD_WINCTRL2_CKMODE_01		(1<<24)
-#define LCD_WINCTRL2_CKMODE_10		(2<<24)
-#define LCD_WINCTRL2_CKMODE_11		(3<<24)
-#define LCD_WINCTRL2_RAM_NONE		(0<<21)
-#define LCD_WINCTRL2_RAM_PALETTE	(1<<21)
-#define LCD_WINCTRL2_RAM_GAMMA		(2<<21)
-#define LCD_WINCTRL2_RAM_BUFFER		(3<<21)
-#define LCD_WINCTRL2_BX_N(N)	((N)<<8)
-#define LCD_WINCTRL2_SCX_1		(0<<4)
-#define LCD_WINCTRL2_SCX_2		(1<<4)
-#define LCD_WINCTRL2_SCX_4		(2<<4)
-#define LCD_WINCTRL2_SCY_1		(0<<0)
-#define LCD_WINCTRL2_SCY_2		(1<<0)
-#define LCD_WINCTRL2_SCY_4		(2<<0)
-
-/* lcd windows buffer control */
-#define LCD_WINBUFCTRL_DB		(1<<1)
-#define LCD_WINBUFCTRL_DBN		(1<<0)
-
-/* lcd_intstatus, lcd_intenable */
-#define LCD_INT_IFO				(0xF<<14)
-#define LCD_INT_IFU				(0xF<<10)
-#define LCD_INT_OFO				(1<<9)
-#define LCD_INT_OFU				(1<<8)
-#define LCD_INT_WAIT			(1<<3)
-#define LCD_INT_SD				(1<<2)
-#define LCD_INT_SA				(1<<1)
-#define LCD_INT_SS				(1<<0)
-
-/* lcd_horztiming */
-#define LCD_HORZTIMING_HND2		(0x1FF<<18)
-#define LCD_HORZTIMING_HND1		(0x1FF<<9)
-#define LCD_HORZTIMING_HPW		(0x1FF<<0)
-#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
-#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
-#define LCD_HORZTIMING_HPW_N(N)	(((N)-1)<<0)
-
-/* lcd_verttiming */
-#define LCD_VERTTIMING_VND2		(0x1FF<<18)
-#define LCD_VERTTIMING_VND1		(0x1FF<<9)
-#define LCD_VERTTIMING_VPW		(0x1FF<<0)
-#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
-#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
-#define LCD_VERTTIMING_VPW_N(N)	(((N)-1)<<0)
-
-/* lcd_clkcontrol */
-#define LCD_CLKCONTROL_EXT		(1<<22)
-#define LCD_CLKCONTROL_DELAY	(3<<20)
-#define LCD_CLKCONTROL_CDD		(1<<19)
-#define LCD_CLKCONTROL_IB		(1<<18)
-#define LCD_CLKCONTROL_IC		(1<<17)
-#define LCD_CLKCONTROL_IH		(1<<16)
-#define LCD_CLKCONTROL_IV		(1<<15)
-#define LCD_CLKCONTROL_BF		(0x1F<<10)
-#define LCD_CLKCONTROL_PCD		(0x3FF<<0)
-#define LCD_CLKCONTROL_BF_N(N)	(((N)-1)<<10)
-#define LCD_CLKCONTROL_PCD_N(N)	((N)<<0)
-
-/* lcd_pwmdiv */
-#define LCD_PWMDIV_EN			(1<<31)
-#define LCD_PWMDIV_PWMDIV		(0x1FFFF<<0)
-#define LCD_PWMDIV_PWMDIV_N(N)	((N)<<0)
-
-/* lcd_pwmhi */
-#define LCD_PWMHI_PWMHI1		(0xFFFF<<16)
-#define LCD_PWMHI_PWMHI0		(0xFFFF<<0)
-#define LCD_PWMHI_PWMHI1_N(N)	((N)<<16)
-#define LCD_PWMHI_PWMHI0_N(N)	((N)<<0)
-
-/* lcd_hwccon */
-#define LCD_HWCCON_EN			(1<<0)
-
-/* lcd_cursorpos */
-#define LCD_CURSORPOS_HWCXOFF		(0x1F<<27)
-#define LCD_CURSORPOS_HWCXPOS		(0x07FF<<16)
-#define LCD_CURSORPOS_HWCYOFF		(0x1F<<11)
-#define LCD_CURSORPOS_HWCYPOS		(0x07FF<<0)
-#define LCD_CURSORPOS_HWCXOFF_N(N)	((N)<<27)
-#define LCD_CURSORPOS_HWCXPOS_N(N)	((N)<<16)
-#define LCD_CURSORPOS_HWCYOFF_N(N)	((N)<<11)
-#define LCD_CURSORPOS_HWCYPOS_N(N)	((N)<<0)
-
-/* lcd_cursorcolor */
-#define LCD_CURSORCOLOR_HWCA		(0xFF<<24)
-#define LCD_CURSORCOLOR_HWCR		(0xFF<<16)
-#define LCD_CURSORCOLOR_HWCG		(0xFF<<8)
-#define LCD_CURSORCOLOR_HWCB		(0xFF<<0)
-#define LCD_CURSORCOLOR_HWCA_N(N)	((N)<<24)
-#define LCD_CURSORCOLOR_HWCR_N(N)	((N)<<16)
-#define LCD_CURSORCOLOR_HWCG_N(N)	((N)<<8)
-#define LCD_CURSORCOLOR_HWCB_N(N)	((N)<<0)
-
-/* lcd_fifoctrl */
-#define LCD_FIFOCTRL_F3IF		(1<<29)
-#define LCD_FIFOCTRL_F3REQ		(0x1F<<24)
-#define LCD_FIFOCTRL_F2IF		(1<<29)
-#define LCD_FIFOCTRL_F2REQ		(0x1F<<16)
-#define LCD_FIFOCTRL_F1IF		(1<<29)
-#define LCD_FIFOCTRL_F1REQ		(0x1F<<8)
-#define LCD_FIFOCTRL_F0IF		(1<<29)
-#define LCD_FIFOCTRL_F0REQ		(0x1F<<0)
-#define LCD_FIFOCTRL_F3REQ_N(N)	((N-1)<<24)
-#define LCD_FIFOCTRL_F2REQ_N(N)	((N-1)<<16)
-#define LCD_FIFOCTRL_F1REQ_N(N)	((N-1)<<8)
-#define LCD_FIFOCTRL_F0REQ_N(N)	((N-1)<<0)
-
-/* lcd_outmask */
-#define LCD_OUTMASK_MASK		(0x00FFFFFF)
-
-/********************************************************************/
-#endif /* _AU1200LCD_H */
diff --git a/drivers/video/auo_k1900fb.c b/drivers/video/auo_k1900fb.c
deleted file mode 100644
index f5b668e77af3..000000000000
--- a/drivers/video/auo_k1900fb.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * auok190xfb.c -- FB driver for AUO-K1900 controllers
- *
- * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * based on broadsheetfb.c
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This driver is written to be used with the AUO-K1900 display controller.
- *
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions.
- *
- * The controller supports different update modes:
- * mode0+1 16 step gray (4bit)
- * mode2 4 step gray (2bit) - FIXME: add strange refresh
- * mode3 2 step gray (1bit) - FIXME: add strange refresh
- * mode4 handwriting mode (strange behaviour)
- * mode5 automatic selection of update mode
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/firmware.h>
-#include <linux/gpio.h>
-#include <linux/pm_runtime.h>
-
-#include <video/auo_k190xfb.h>
-
-#include "auo_k190x.h"
-
-/*
- * AUO-K1900 specific commands
- */
-
-#define AUOK1900_CMD_PARTIALDISP	0x1001
-#define AUOK1900_CMD_ROTATION		0x1006
-#define AUOK1900_CMD_LUT_STOP		0x1009
-
-#define AUOK1900_INIT_TEMP_AVERAGE	(1 << 13)
-#define AUOK1900_INIT_ROTATE(_x)	((_x & 0x3) << 10)
-#define AUOK1900_INIT_RESOLUTION(_res)	((_res & 0x7) << 2)
-
-static void auok1900_init(struct auok190xfb_par *par)
-{
-	struct device *dev = par->info->device;
-	struct auok190x_board *board = par->board;
-	u16 init_param = 0;
-
-	pm_runtime_get_sync(dev);
-
-	init_param |= AUOK1900_INIT_TEMP_AVERAGE;
-	init_param |= AUOK1900_INIT_ROTATE(par->rotation);
-	init_param |= AUOK190X_INIT_INVERSE_WHITE;
-	init_param |= AUOK190X_INIT_FORMAT0;
-	init_param |= AUOK1900_INIT_RESOLUTION(par->resolution);
-	init_param |= AUOK190X_INIT_SHIFT_RIGHT;
-
-	auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
-
-	/* let the controller finish */
-	board->wait_for_rdy(par);
-
-	pm_runtime_mark_last_busy(dev);
-	pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1900_update_region(struct auok190xfb_par *par, int mode,
-						u16 y1, u16 y2)
-{
-	struct device *dev = par->info->device;
-	unsigned char *buf = (unsigned char *)par->info->screen_base;
-	int xres = par->info->var.xres;
-	int line_length = par->info->fix.line_length;
-	u16 args[4];
-
-	pm_runtime_get_sync(dev);
-
-	mutex_lock(&(par->io_lock));
-
-	/* y1 and y2 must be a multiple of 2 so drop the lowest bit */
-	y1 &= 0xfffe;
-	y2 &= 0xfffe;
-
-	dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
-		1, y1+1, xres, y2-y1, mode);
-
-	/* to FIX handle different partial update modes */
-	args[0] = mode | 1;
-	args[1] = y1 + 1;
-	args[2] = xres;
-	args[3] = y2 - y1;
-	buf += y1 * line_length;
-	auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
-				     ((y2 - y1) * line_length)/2, (u16 *) buf);
-	auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
-
-	par->update_cnt++;
-
-	mutex_unlock(&(par->io_lock));
-
-	pm_runtime_mark_last_busy(dev);
-	pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1900fb_dpy_update_pages(struct auok190xfb_par *par,
-						u16 y1, u16 y2)
-{
-	int mode;
-
-	if (par->update_mode < 0) {
-		mode = AUOK190X_UPDATE_MODE(1);
-		par->last_mode = -1;
-	} else {
-		mode = AUOK190X_UPDATE_MODE(par->update_mode);
-		par->last_mode = par->update_mode;
-	}
-
-	if (par->flash)
-		mode |= AUOK190X_UPDATE_NONFLASH;
-
-	auok1900_update_region(par, mode, y1, y2);
-}
-
-static void auok1900fb_dpy_update(struct auok190xfb_par *par)
-{
-	int mode;
-
-	if (par->update_mode < 0) {
-		mode = AUOK190X_UPDATE_MODE(0);
-		par->last_mode = -1;
-	} else {
-		mode = AUOK190X_UPDATE_MODE(par->update_mode);
-		par->last_mode = par->update_mode;
-	}
-
-	if (par->flash)
-		mode |= AUOK190X_UPDATE_NONFLASH;
-
-	auok1900_update_region(par, mode, 0, par->info->var.yres);
-	par->update_cnt = 0;
-}
-
-static bool auok1900fb_need_refresh(struct auok190xfb_par *par)
-{
-	return (par->update_cnt > 10);
-}
-
-static int auok1900fb_probe(struct platform_device *pdev)
-{
-	struct auok190x_init_data init;
-	struct auok190x_board *board;
-
-	/* pick up board specific routines */
-	board = pdev->dev.platform_data;
-	if (!board)
-		return -EINVAL;
-
-	/* fill temporary init struct for common init */
-	init.id = "auo_k1900fb";
-	init.board = board;
-	init.update_partial = auok1900fb_dpy_update_pages;
-	init.update_all = auok1900fb_dpy_update;
-	init.need_refresh = auok1900fb_need_refresh;
-	init.init = auok1900_init;
-
-	return auok190x_common_probe(pdev, &init);
-}
-
-static int auok1900fb_remove(struct platform_device *pdev)
-{
-	return auok190x_common_remove(pdev);
-}
-
-static struct platform_driver auok1900fb_driver = {
-	.probe	= auok1900fb_probe,
-	.remove = auok1900fb_remove,
-	.driver	= {
-		.owner	= THIS_MODULE,
-		.name	= "auo_k1900fb",
-		.pm = &auok190x_pm,
-	},
-};
-module_platform_driver(auok1900fb_driver);
-
-MODULE_DESCRIPTION("framebuffer driver for the AUO-K1900 EPD controller");
-MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/auo_k1901fb.c
deleted file mode 100644
index 12b9adcb75c5..000000000000
--- a/drivers/video/auo_k1901fb.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * auok190xfb.c -- FB driver for AUO-K1901 controllers
- *
- * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * based on broadsheetfb.c
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This driver is written to be used with the AUO-K1901 display controller.
- *
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions.
- *
- * The controller supports different update modes:
- * mode0+1 16 step gray (4bit)
- * mode2+3 4 step gray (2bit)
- * mode4+5 2 step gray (1bit)
- * - mode4 is described as "without LUT"
- * mode7 automatic selection of update mode
- *
- * The most interesting difference to the K1900 is the ability to do screen
- * updates in an asynchronous fashion. Where the K1900 needs to wait for the
- * current update to complete, the K1901 can process later updates already.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/firmware.h>
-#include <linux/gpio.h>
-#include <linux/pm_runtime.h>
-
-#include <video/auo_k190xfb.h>
-
-#include "auo_k190x.h"
-
-/*
- * AUO-K1901 specific commands
- */
-
-#define AUOK1901_CMD_LUT_INTERFACE	0x0005
-#define AUOK1901_CMD_DMA_START		0x1001
-#define AUOK1901_CMD_CURSOR_START	0x1007
-#define AUOK1901_CMD_CURSOR_STOP	AUOK190X_CMD_DATA_STOP
-#define AUOK1901_CMD_DDMA_START		0x1009
-
-#define AUOK1901_INIT_GATE_PULSE_LOW	(0 << 14)
-#define AUOK1901_INIT_GATE_PULSE_HIGH	(1 << 14)
-#define AUOK1901_INIT_SINGLE_GATE	(0 << 13)
-#define AUOK1901_INIT_DOUBLE_GATE	(1 << 13)
-
-/* Bits to pixels
- *   Mode	15-12	11-8	7-4	3-0
- *   format2	2	T	1	T
- *   format3	1	T	2	T
- *   format4	T	2	T	1
- *   format5	T	1	T	2
- *
- *   halftone modes:
- *   format6	2	2	1	1
- *   format7	1	1	2	2
- */
-#define AUOK1901_INIT_FORMAT2		(1 << 7)
-#define AUOK1901_INIT_FORMAT3		((1 << 7) | (1 << 6))
-#define AUOK1901_INIT_FORMAT4		(1 << 8)
-#define AUOK1901_INIT_FORMAT5		((1 << 8) | (1 << 6))
-#define AUOK1901_INIT_FORMAT6		((1 << 8) | (1 << 7))
-#define AUOK1901_INIT_FORMAT7		((1 << 8) | (1 << 7) | (1 << 6))
-
-/* res[4] to bit 10
- * res[3-0] to bits 5-2
- */
-#define AUOK1901_INIT_RESOLUTION(_res)	(((_res & (1 << 4)) << 6) \
-					 | ((_res & 0xf) << 2))
-
-/*
- * portrait / landscape orientation in AUOK1901_CMD_DMA_START
- */
-#define AUOK1901_DMA_ROTATE90(_rot)		((_rot & 1) << 13)
-
-/*
- * equivalent to 1 << 11, needs the ~ to have same rotation like K1900
- */
-#define AUOK1901_DDMA_ROTATE180(_rot)		((~_rot & 2) << 10)
-
-static void auok1901_init(struct auok190xfb_par *par)
-{
-	struct device *dev = par->info->device;
-	struct auok190x_board *board = par->board;
-	u16 init_param = 0;
-
-	pm_runtime_get_sync(dev);
-
-	init_param |= AUOK190X_INIT_INVERSE_WHITE;
-	init_param |= AUOK190X_INIT_FORMAT0;
-	init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
-	init_param |= AUOK190X_INIT_SHIFT_LEFT;
-
-	auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
-
-	/* let the controller finish */
-	board->wait_for_rdy(par);
-
-	pm_runtime_mark_last_busy(dev);
-	pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1901_update_region(struct auok190xfb_par *par, int mode,
-						u16 y1, u16 y2)
-{
-	struct device *dev = par->info->device;
-	unsigned char *buf = (unsigned char *)par->info->screen_base;
-	int xres = par->info->var.xres;
-	int line_length = par->info->fix.line_length;
-	u16 args[5];
-
-	pm_runtime_get_sync(dev);
-
-	mutex_lock(&(par->io_lock));
-
-	/* y1 and y2 must be a multiple of 2 so drop the lowest bit */
-	y1 &= 0xfffe;
-	y2 &= 0xfffe;
-
-	dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
-		1, y1+1, xres, y2-y1, mode);
-
-	/* K1901: first transfer the region data */
-	args[0] = AUOK1901_DMA_ROTATE90(par->rotation) | 1;
-	args[1] = y1 + 1;
-	args[2] = xres;
-	args[3] = y2 - y1;
-	buf += y1 * line_length;
-	auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
-					    args, ((y2 - y1) * line_length)/2,
-					    (u16 *) buf);
-	auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
-
-	/* K1901: second tell the controller to update the region with mode */
-	args[0] = mode | AUOK1901_DDMA_ROTATE180(par->rotation);
-	args[1] = 1;
-	args[2] = y1 + 1;
-	args[3] = xres;
-	args[4] = y2 - y1;
-	auok190x_send_cmdargs_nowait(par, AUOK1901_CMD_DDMA_START, 5, args);
-
-	par->update_cnt++;
-
-	mutex_unlock(&(par->io_lock));
-
-	pm_runtime_mark_last_busy(dev);
-	pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1901fb_dpy_update_pages(struct auok190xfb_par *par,
-						u16 y1, u16 y2)
-{
-	int mode;
-
-	if (par->update_mode < 0) {
-		mode = AUOK190X_UPDATE_MODE(1);
-		par->last_mode = -1;
-	} else {
-		mode = AUOK190X_UPDATE_MODE(par->update_mode);
-		par->last_mode = par->update_mode;
-	}
-
-	if (par->flash)
-		mode |= AUOK190X_UPDATE_NONFLASH;
-
-	auok1901_update_region(par, mode, y1, y2);
-}
-
-static void auok1901fb_dpy_update(struct auok190xfb_par *par)
-{
-	int mode;
-
-	/* When doing full updates, wait for the controller to be ready
-	 * This will hopefully catch some hangs of the K1901
-	 */
-	par->board->wait_for_rdy(par);
-
-	if (par->update_mode < 0) {
-		mode = AUOK190X_UPDATE_MODE(0);
-		par->last_mode = -1;
-	} else {
-		mode = AUOK190X_UPDATE_MODE(par->update_mode);
-		par->last_mode = par->update_mode;
-	}
-
-	if (par->flash)
-		mode |= AUOK190X_UPDATE_NONFLASH;
-
-	auok1901_update_region(par, mode, 0, par->info->var.yres);
-	par->update_cnt = 0;
-}
-
-static bool auok1901fb_need_refresh(struct auok190xfb_par *par)
-{
-	return (par->update_cnt > 10);
-}
-
-static int auok1901fb_probe(struct platform_device *pdev)
-{
-	struct auok190x_init_data init;
-	struct auok190x_board *board;
-
-	/* pick up board specific routines */
-	board = pdev->dev.platform_data;
-	if (!board)
-		return -EINVAL;
-
-	/* fill temporary init struct for common init */
-	init.id = "auo_k1901fb";
-	init.board = board;
-	init.update_partial = auok1901fb_dpy_update_pages;
-	init.update_all = auok1901fb_dpy_update;
-	init.need_refresh = auok1901fb_need_refresh;
-	init.init = auok1901_init;
-
-	return auok190x_common_probe(pdev, &init);
-}
-
-static int auok1901fb_remove(struct platform_device *pdev)
-{
-	return auok190x_common_remove(pdev);
-}
-
-static struct platform_driver auok1901fb_driver = {
-	.probe	= auok1901fb_probe,
-	.remove = auok1901fb_remove,
-	.driver	= {
-		.owner	= THIS_MODULE,
-		.name	= "auo_k1901fb",
-		.pm = &auok190x_pm,
-	},
-};
-module_platform_driver(auok1901fb_driver);
-
-MODULE_DESCRIPTION("framebuffer driver for the AUO-K1901 EPD controller");
-MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c
deleted file mode 100644
index 8d2499d1cafb..000000000000
--- a/drivers/video/auo_k190x.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-/*
- * Common code for AUO-K190X framebuffer drivers
- *
- * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/regulator/consumer.h>
-
-#include <video/auo_k190xfb.h>
-
-#include "auo_k190x.h"
-
-struct panel_info {
-	int w;
-	int h;
-};
-
-/* table of panel specific parameters to be indexed into by the board drivers */
-static struct panel_info panel_table[] = {
-	/* standard 6" */
-	[AUOK190X_RESOLUTION_800_600] = {
-		.w = 800,
-		.h = 600,
-	},
-	/* standard 9" */
-	[AUOK190X_RESOLUTION_1024_768] = {
-		.w = 1024,
-		.h = 768,
-	},
-	[AUOK190X_RESOLUTION_600_800] = {
-		.w = 600,
-		.h = 800,
-	},
-	[AUOK190X_RESOLUTION_768_1024] = {
-		.w = 768,
-		.h = 1024,
-	},
-};
-
-/*
- * private I80 interface to the board driver
- */
-
-static void auok190x_issue_data(struct auok190xfb_par *par, u16 data)
-{
-	par->board->set_ctl(par, AUOK190X_I80_WR, 0);
-	par->board->set_hdb(par, data);
-	par->board->set_ctl(par, AUOK190X_I80_WR, 1);
-}
-
-static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
-{
-	par->board->set_ctl(par, AUOK190X_I80_DC, 0);
-	auok190x_issue_data(par, data);
-	par->board->set_ctl(par, AUOK190X_I80_DC, 1);
-}
-
-/**
- * Conversion of 16bit color to 4bit grayscale
- * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
- */
-static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
-{
-	return ((((data & 0xF800) >> var->red.offset) * 77 +
-		 ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
-		 ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
-}
-
-static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
-					u16 *data)
-{
-	struct fb_var_screeninfo *var = &par->info->var;
-	struct device *dev = par->info->device;
-	int i;
-	u16 tmp;
-
-	if (size & 7) {
-		dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
-			size);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < (size >> 2); i++) {
-		par->board->set_ctl(par, AUOK190X_I80_WR, 0);
-
-		tmp  = (rgb565_to_gray4(data[4*i], var) & 0x000F);
-		tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
-		tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
-		tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
-
-		par->board->set_hdb(par, tmp);
-		par->board->set_ctl(par, AUOK190X_I80_WR, 1);
-	}
-
-	return 0;
-}
-
-static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
-				       u16 *data)
-{
-	struct device *dev = par->info->device;
-	int i;
-	u16 tmp;
-
-	if (size & 3) {
-		dev_err(dev, "issue_pixels: size %d must be a multiple of 4\n",
-			size);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < (size >> 1); i++) {
-		par->board->set_ctl(par, AUOK190X_I80_WR, 0);
-
-		/* simple reduction of 8bit staticgray to 4bit gray
-		 * combines 4 * 4bit pixel values into a 16bit value
-		 */
-		tmp  = (data[2*i] & 0xF0) >> 4;
-		tmp |= (data[2*i] & 0xF000) >> 8;
-		tmp |= (data[2*i+1] & 0xF0) << 4;
-		tmp |= (data[2*i+1] & 0xF000);
-
-		par->board->set_hdb(par, tmp);
-		par->board->set_ctl(par, AUOK190X_I80_WR, 1);
-	}
-
-	return 0;
-}
-
-static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
-				 u16 *data)
-{
-	struct fb_info *info = par->info;
-	struct device *dev = par->info->device;
-
-	if (info->var.bits_per_pixel == 8 && info->var.grayscale)
-		auok190x_issue_pixels_gray8(par, size, data);
-	else if (info->var.bits_per_pixel == 16)
-		auok190x_issue_pixels_rgb565(par, size, data);
-	else
-		dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
-			info->var.bits_per_pixel, info->var.grayscale);
-
-	return 0;
-}
-
-static u16 auok190x_read_data(struct auok190xfb_par *par)
-{
-	u16 data;
-
-	par->board->set_ctl(par, AUOK190X_I80_OE, 0);
-	data = par->board->get_hdb(par);
-	par->board->set_ctl(par, AUOK190X_I80_OE, 1);
-
-	return data;
-}
-
-/*
- * Command interface for the controller drivers
- */
-
-void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data)
-{
-	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
-	auok190x_issue_cmd(par, data);
-	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-}
-EXPORT_SYMBOL_GPL(auok190x_send_command_nowait);
-
-void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
-				  int argc, u16 *argv)
-{
-	int i;
-
-	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
-	auok190x_issue_cmd(par, cmd);
-
-	for (i = 0; i < argc; i++)
-		auok190x_issue_data(par, argv[i]);
-	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_nowait);
-
-int auok190x_send_command(struct auok190xfb_par *par, u16 data)
-{
-	int ret;
-
-	ret = par->board->wait_for_rdy(par);
-	if (ret)
-		return ret;
-
-	auok190x_send_command_nowait(par, data);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_send_command);
-
-int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
-			   int argc, u16 *argv)
-{
-	int ret;
-
-	ret = par->board->wait_for_rdy(par);
-	if (ret)
-		return ret;
-
-	auok190x_send_cmdargs_nowait(par, cmd, argc, argv);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs);
-
-int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
-			   int argc, u16 *argv)
-{
-	int i, ret;
-
-	ret = par->board->wait_for_rdy(par);
-	if (ret)
-		return ret;
-
-	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
-	auok190x_issue_cmd(par, cmd);
-
-	for (i = 0; i < argc; i++)
-		argv[i] = auok190x_read_data(par);
-	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_read_cmdargs);
-
-void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, u16 cmd,
-				  int argc, u16 *argv, int size, u16 *data)
-{
-	int i;
-
-	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
-
-	auok190x_issue_cmd(par, cmd);
-
-	for (i = 0; i < argc; i++)
-		auok190x_issue_data(par, argv[i]);
-
-	auok190x_issue_pixels(par, size, data);
-
-	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels_nowait);
-
-int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
-				  int argc, u16 *argv, int size, u16 *data)
-{
-	int ret;
-
-	ret = par->board->wait_for_rdy(par);
-	if (ret)
-		return ret;
-
-	auok190x_send_cmdargs_pixels_nowait(par, cmd, argc, argv, size, data);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels);
-
-/*
- * fbdefio callbacks - common on both controllers.
- */
-
-static void auok190xfb_dpy_first_io(struct fb_info *info)
-{
-	/* tell runtime-pm that we wish to use the device in a short time */
-	pm_runtime_get(info->device);
-}
-
-/* this is called back from the deferred io workqueue */
-static void auok190xfb_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct auok190xfb_par *par = info->par;
-	u16 line_length = info->fix.line_length;
-	u16 yres = info->var.yres;
-	u16 y1 = 0, h = 0;
-	int prev_index = -1;
-	struct page *cur;
-	int h_inc;
-	int threshold;
-
-	if (!list_empty(pagelist))
-		/* the device resume should've been requested through first_io,
-		 * if the resume did not finish until now, wait for it.
-		 */
-		pm_runtime_barrier(info->device);
-	else
-		/* We reached this via the fsync or some other way.
-		 * In either case the first_io function did not run,
-		 * so we runtime_resume the device here synchronously.
-		 */
-		pm_runtime_get_sync(info->device);
-
-	/* Do a full screen update every n updates to prevent
-	 * excessive darkening of the Sipix display.
-	 * If we do this, there is no need to walk the pages.
-	 */
-	if (par->need_refresh(par)) {
-		par->update_all(par);
-		goto out;
-	}
-
-	/* height increment is fixed per page */
-	h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
-
-	/* calculate number of pages from pixel height */
-	threshold = par->consecutive_threshold / h_inc;
-	if (threshold < 1)
-		threshold = 1;
-
-	/* walk the written page list and swizzle the data */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-		if (prev_index < 0) {
-			/* just starting so assign first page */
-			y1 = (cur->index << PAGE_SHIFT) / line_length;
-			h = h_inc;
-		} else if ((cur->index - prev_index) <= threshold) {
-			/* page is within our threshold for single updates */
-			h += h_inc * (cur->index - prev_index);
-		} else {
-			/* page not consecutive, issue previous update first */
-			par->update_partial(par, y1, y1 + h);
-
-			/* start over with our non consecutive page */
-			y1 = (cur->index << PAGE_SHIFT) / line_length;
-			h = h_inc;
-		}
-		prev_index = cur->index;
-	}
-
-	/* if we still have any pages to update we do so now */
-	if (h >= yres)
-		/* its a full screen update, just do it */
-		par->update_all(par);
-	else
-		par->update_partial(par, y1, min((u16) (y1 + h), yres));
-
-out:
-	pm_runtime_mark_last_busy(info->device);
-	pm_runtime_put_autosuspend(info->device);
-}
-
-/*
- * framebuffer operations
- */
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it's inefficient to do anything less than a full screen draw
- */
-static ssize_t auok190xfb_write(struct fb_info *info, const char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	struct auok190xfb_par *par = info->par;
-	unsigned long p = *ppos;
-	void *dst;
-	int err = 0;
-	unsigned long total_size;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EFBIG;
-
-	if (count > total_size) {
-		err = -EFBIG;
-		count = total_size;
-	}
-
-	if (count + p > total_size) {
-		if (!err)
-			err = -ENOSPC;
-
-		count = total_size - p;
-	}
-
-	dst = (void *)(info->screen_base + p);
-
-	if (copy_from_user(dst, buf, count))
-		err = -EFAULT;
-
-	if  (!err)
-		*ppos += count;
-
-	par->update_all(par);
-
-	return (err) ? err : count;
-}
-
-static void auok190xfb_fillrect(struct fb_info *info,
-				   const struct fb_fillrect *rect)
-{
-	struct auok190xfb_par *par = info->par;
-
-	sys_fillrect(info, rect);
-
-	par->update_all(par);
-}
-
-static void auok190xfb_copyarea(struct fb_info *info,
-				   const struct fb_copyarea *area)
-{
-	struct auok190xfb_par *par = info->par;
-
-	sys_copyarea(info, area);
-
-	par->update_all(par);
-}
-
-static void auok190xfb_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	struct auok190xfb_par *par = info->par;
-
-	sys_imageblit(info, image);
-
-	par->update_all(par);
-}
-
-static int auok190xfb_check_var(struct fb_var_screeninfo *var,
-				   struct fb_info *info)
-{
-	struct device *dev = info->device;
-	struct auok190xfb_par *par = info->par;
-	struct panel_info *panel = &panel_table[par->resolution];
-	int size;
-
-	/*
-	 * Color depth
-	 */
-
-	if (var->bits_per_pixel == 8 && var->grayscale == 1) {
-		/*
-		 * For 8-bit grayscale, R, G, and B offset are equal.
-		 */
-		var->red.length = 8;
-		var->red.offset = 0;
-		var->red.msb_right = 0;
-
-		var->green.length = 8;
-		var->green.offset = 0;
-		var->green.msb_right = 0;
-
-		var->blue.length = 8;
-		var->blue.offset = 0;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 0;
-		var->transp.offset = 0;
-		var->transp.msb_right = 0;
-	} else if (var->bits_per_pixel == 16) {
-		var->red.length = 5;
-		var->red.offset = 11;
-		var->red.msb_right = 0;
-
-		var->green.length = 6;
-		var->green.offset = 5;
-		var->green.msb_right = 0;
-
-		var->blue.length = 5;
-		var->blue.offset = 0;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 0;
-		var->transp.offset = 0;
-		var->transp.msb_right = 0;
-	} else {
-		dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
-			info->var.bits_per_pixel, info->var.grayscale);
-		return -EINVAL;
-	}
-
-	/*
-	 * Dimensions
-	 */
-
-	switch (var->rotate) {
-	case FB_ROTATE_UR:
-	case FB_ROTATE_UD:
-		var->xres = panel->w;
-		var->yres = panel->h;
-		break;
-	case FB_ROTATE_CW:
-	case FB_ROTATE_CCW:
-		var->xres = panel->h;
-		var->yres = panel->w;
-		break;
-	default:
-		dev_dbg(dev, "Invalid rotation request\n");
-		return -EINVAL;
-	}
-
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-
-	/*
-	 *  Memory limit
-	 */
-
-	size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
-	if (size > info->fix.smem_len) {
-		dev_err(dev, "Memory limit exceeded, requested %dK\n",
-			size >> 10);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static int auok190xfb_set_fix(struct fb_info *info)
-{
-	struct fb_fix_screeninfo *fix = &info->fix;
-	struct fb_var_screeninfo *var = &info->var;
-
-	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->accel = FB_ACCEL_NONE;
-	fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
-				       : FB_VISUAL_TRUECOLOR;
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-
-	return 0;
-}
-
-static int auok190xfb_set_par(struct fb_info *info)
-{
-	struct auok190xfb_par *par = info->par;
-
-	par->rotation = info->var.rotate;
-	auok190xfb_set_fix(info);
-
-	/* reinit the controller to honor the rotation */
-	par->init(par);
-
-	/* wait for init to complete */
-	par->board->wait_for_rdy(par);
-
-	return 0;
-}
-
-static struct fb_ops auok190xfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_read	= fb_sys_read,
-	.fb_write	= auok190xfb_write,
-	.fb_fillrect	= auok190xfb_fillrect,
-	.fb_copyarea	= auok190xfb_copyarea,
-	.fb_imageblit	= auok190xfb_imageblit,
-	.fb_check_var	= auok190xfb_check_var,
-	.fb_set_par     = auok190xfb_set_par,
-};
-
-/*
- * Controller-functions common to both K1900 and K1901
- */
-
-static int auok190x_read_temperature(struct auok190xfb_par *par)
-{
-	struct device *dev = par->info->device;
-	u16 data[4];
-	int temp;
-
-	pm_runtime_get_sync(dev);
-
-	mutex_lock(&(par->io_lock));
-
-	auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
-
-	mutex_unlock(&(par->io_lock));
-
-	pm_runtime_mark_last_busy(dev);
-	pm_runtime_put_autosuspend(dev);
-
-	/* sanitize and split of half-degrees for now */
-	temp = ((data[0] & AUOK190X_VERSION_TEMP_MASK) >> 1);
-
-	/* handle positive and negative temperatures */
-	if (temp >= 201)
-		return (255 - temp + 1) * (-1);
-	else
-		return temp;
-}
-
-static void auok190x_identify(struct auok190xfb_par *par)
-{
-	struct device *dev = par->info->device;
-	u16 data[4];
-
-	pm_runtime_get_sync(dev);
-
-	mutex_lock(&(par->io_lock));
-
-	auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
-
-	mutex_unlock(&(par->io_lock));
-
-	par->epd_type = data[1] & AUOK190X_VERSION_TEMP_MASK;
-
-	par->panel_size_int = AUOK190X_VERSION_SIZE_INT(data[2]);
-	par->panel_size_float = AUOK190X_VERSION_SIZE_FLOAT(data[2]);
-	par->panel_model = AUOK190X_VERSION_MODEL(data[2]);
-
-	par->tcon_version = AUOK190X_VERSION_TCON(data[3]);
-	par->lut_version = AUOK190X_VERSION_LUT(data[3]);
-
-	dev_dbg(dev, "panel %d.%din, model 0x%x, EPD 0x%x TCON-rev 0x%x, LUT-rev 0x%x",
-		par->panel_size_int, par->panel_size_float, par->panel_model,
-		par->epd_type, par->tcon_version, par->lut_version);
-
-	pm_runtime_mark_last_busy(dev);
-	pm_runtime_put_autosuspend(dev);
-}
-
-/*
- * Sysfs functions
- */
-
-static ssize_t update_mode_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct auok190xfb_par *par = info->par;
-
-	return sprintf(buf, "%d\n", par->update_mode);
-}
-
-static ssize_t update_mode_store(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct auok190xfb_par *par = info->par;
-	int mode, ret;
-
-	ret = kstrtoint(buf, 10, &mode);
-	if (ret)
-		return ret;
-
-	par->update_mode = mode;
-
-	/* if we enter a better mode, do a full update */
-	if (par->last_mode > 1 && mode < par->last_mode)
-		par->update_all(par);
-
-	return count;
-}
-
-static ssize_t flash_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct auok190xfb_par *par = info->par;
-
-	return sprintf(buf, "%d\n", par->flash);
-}
-
-static ssize_t flash_store(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct auok190xfb_par *par = info->par;
-	int flash, ret;
-
-	ret = kstrtoint(buf, 10, &flash);
-	if (ret)
-		return ret;
-
-	if (flash > 0)
-		par->flash = 1;
-	else
-		par->flash = 0;
-
-	return count;
-}
-
-static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
-			 char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct auok190xfb_par *par = info->par;
-	int temp;
-
-	temp = auok190x_read_temperature(par);
-	return sprintf(buf, "%d\n", temp);
-}
-
-static DEVICE_ATTR(update_mode, 0644, update_mode_show, update_mode_store);
-static DEVICE_ATTR(flash, 0644, flash_show, flash_store);
-static DEVICE_ATTR(temp, 0644, temp_show, NULL);
-
-static struct attribute *auok190x_attributes[] = {
-	&dev_attr_update_mode.attr,
-	&dev_attr_flash.attr,
-	&dev_attr_temp.attr,
-	NULL
-};
-
-static const struct attribute_group auok190x_attr_group = {
-	.attrs		= auok190x_attributes,
-};
-
-static int auok190x_power(struct auok190xfb_par *par, bool on)
-{
-	struct auok190x_board *board = par->board;
-	int ret;
-
-	if (on) {
-		/* We should maintain POWER up for at least 80ms before set
-		 * RST_N and SLP_N to high (TCON spec 20100803_v35 p59)
-		 */
-		ret = regulator_enable(par->regulator);
-		if (ret)
-			return ret;
-
-		msleep(200);
-		gpio_set_value(board->gpio_nrst, 1);
-		gpio_set_value(board->gpio_nsleep, 1);
-		msleep(200);
-	} else {
-		regulator_disable(par->regulator);
-		gpio_set_value(board->gpio_nrst, 0);
-		gpio_set_value(board->gpio_nsleep, 0);
-	}
-
-	return 0;
-}
-
-/*
- * Recovery - powercycle the controller
- */
-
-static void auok190x_recover(struct auok190xfb_par *par)
-{
-	struct device *dev = par->info->device;
-
-	auok190x_power(par, 0);
-	msleep(100);
-	auok190x_power(par, 1);
-
-	/* after powercycling the device, it's always active */
-	pm_runtime_set_active(dev);
-	par->standby = 0;
-
-	par->init(par);
-
-	/* wait for init to complete */
-	par->board->wait_for_rdy(par);
-}
-
-/*
- * Power-management
- */
-
-#ifdef CONFIG_PM
-static int auok190x_runtime_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct auok190xfb_par *par = info->par;
-	struct auok190x_board *board = par->board;
-	u16 standby_param;
-
-	/* take and keep the lock until we are resumed, as the controller
-	 * will never reach the non-busy state when in standby mode
-	 */
-	mutex_lock(&(par->io_lock));
-
-	if (par->standby) {
-		dev_warn(dev, "already in standby, runtime-pm pairing mismatch\n");
-		mutex_unlock(&(par->io_lock));
-		return 0;
-	}
-
-	/* according to runtime_pm.txt runtime_suspend only means, that the
-	 * device will not process data and will not communicate with the CPU
-	 * As we hold the lock, this stays true even without standby
-	 */
-	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
-		dev_dbg(dev, "runtime suspend without standby\n");
-		goto finish;
-	} else if (board->quirks & AUOK190X_QUIRK_STANDBYPARAM) {
-		/* for some TCON versions STANDBY expects a parameter (0) but
-		 * it seems the real tcon version has to be determined yet.
-		 */
-		dev_dbg(dev, "runtime suspend with additional empty param\n");
-		standby_param = 0;
-		auok190x_send_cmdargs(par, AUOK190X_CMD_STANDBY, 1,
-				      &standby_param);
-	} else {
-		dev_dbg(dev, "runtime suspend without param\n");
-		auok190x_send_command(par, AUOK190X_CMD_STANDBY);
-	}
-
-	msleep(64);
-
-finish:
-	par->standby = 1;
-
-	return 0;
-}
-
-static int auok190x_runtime_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct auok190xfb_par *par = info->par;
-	struct auok190x_board *board = par->board;
-
-	if (!par->standby) {
-		dev_warn(dev, "not in standby, runtime-pm pairing mismatch\n");
-		return 0;
-	}
-
-	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
-		dev_dbg(dev, "runtime resume without standby\n");
-	} else {
-		/* when in standby, controller is always busy
-		 * and only accepts the wakeup command
-		 */
-		dev_dbg(dev, "runtime resume from standby\n");
-		auok190x_send_command_nowait(par, AUOK190X_CMD_WAKEUP);
-
-		msleep(160);
-
-		/* wait for the controller to be ready and release the lock */
-		board->wait_for_rdy(par);
-	}
-
-	par->standby = 0;
-
-	mutex_unlock(&(par->io_lock));
-
-	return 0;
-}
-
-static int auok190x_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct auok190xfb_par *par = info->par;
-	struct auok190x_board *board = par->board;
-	int ret;
-
-	dev_dbg(dev, "suspend\n");
-	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
-		/* suspend via powering off the ic */
-		dev_dbg(dev, "suspend with broken standby\n");
-
-		auok190x_power(par, 0);
-	} else {
-		dev_dbg(dev, "suspend using sleep\n");
-
-		/* the sleep state can only be entered from the standby state.
-		 * pm_runtime_get_noresume gets called before the suspend call.
-		 * So the devices usage count is >0 but it is not necessarily
-		 * active.
-		 */
-		if (!pm_runtime_status_suspended(dev)) {
-			ret = auok190x_runtime_suspend(dev);
-			if (ret < 0) {
-				dev_err(dev, "auok190x_runtime_suspend failed with %d\n",
-					ret);
-				return ret;
-			}
-			par->manual_standby = 1;
-		}
-
-		gpio_direction_output(board->gpio_nsleep, 0);
-	}
-
-	msleep(100);
-
-	return 0;
-}
-
-static int auok190x_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct auok190xfb_par *par = info->par;
-	struct auok190x_board *board = par->board;
-
-	dev_dbg(dev, "resume\n");
-	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
-		dev_dbg(dev, "resume with broken standby\n");
-
-		auok190x_power(par, 1);
-
-		par->init(par);
-	} else {
-		dev_dbg(dev, "resume from sleep\n");
-
-		/* device should be in runtime suspend when we were suspended
-		 * and pm_runtime_put_sync gets called after this function.
-		 * So there is no need to touch the standby mode here at all.
-		 */
-		gpio_direction_output(board->gpio_nsleep, 1);
-		msleep(100);
-
-		/* an additional init call seems to be necessary after sleep */
-		auok190x_runtime_resume(dev);
-		par->init(par);
-
-		/* if we were runtime-suspended before, suspend again*/
-		if (!par->manual_standby)
-			auok190x_runtime_suspend(dev);
-		else
-			par->manual_standby = 0;
-	}
-
-	return 0;
-}
-#endif
-
-const struct dev_pm_ops auok190x_pm = {
-	SET_RUNTIME_PM_OPS(auok190x_runtime_suspend, auok190x_runtime_resume,
-			   NULL)
-	SET_SYSTEM_SLEEP_PM_OPS(auok190x_suspend, auok190x_resume)
-};
-EXPORT_SYMBOL_GPL(auok190x_pm);
-
-/*
- * Common probe and remove code
- */
-
-int auok190x_common_probe(struct platform_device *pdev,
-			  struct auok190x_init_data *init)
-{
-	struct auok190x_board *board = init->board;
-	struct auok190xfb_par *par;
-	struct fb_info *info;
-	struct panel_info *panel;
-	int videomemorysize, ret;
-	unsigned char *videomemory;
-
-	/* check board contents */
-	if (!board->init || !board->cleanup || !board->wait_for_rdy
-	    || !board->set_ctl || !board->set_hdb || !board->get_hdb
-	    || !board->setup_irq)
-		return -EINVAL;
-
-	info = framebuffer_alloc(sizeof(struct auok190xfb_par), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	par = info->par;
-	par->info = info;
-	par->board = board;
-	par->recover = auok190x_recover;
-	par->update_partial = init->update_partial;
-	par->update_all = init->update_all;
-	par->need_refresh = init->need_refresh;
-	par->init = init->init;
-
-	/* init update modes */
-	par->update_cnt = 0;
-	par->update_mode = -1;
-	par->last_mode = -1;
-	par->flash = 0;
-
-	par->regulator = regulator_get(info->device, "vdd");
-	if (IS_ERR(par->regulator)) {
-		ret = PTR_ERR(par->regulator);
-		dev_err(info->device, "Failed to get regulator: %d\n", ret);
-		goto err_reg;
-	}
-
-	ret = board->init(par);
-	if (ret) {
-		dev_err(info->device, "board init failed, %d\n", ret);
-		goto err_board;
-	}
-
-	ret = gpio_request(board->gpio_nsleep, "AUOK190x sleep");
-	if (ret) {
-		dev_err(info->device, "could not request sleep gpio, %d\n",
-			ret);
-		goto err_gpio1;
-	}
-
-	ret = gpio_direction_output(board->gpio_nsleep, 0);
-	if (ret) {
-		dev_err(info->device, "could not set sleep gpio, %d\n", ret);
-		goto err_gpio2;
-	}
-
-	ret = gpio_request(board->gpio_nrst, "AUOK190x reset");
-	if (ret) {
-		dev_err(info->device, "could not request reset gpio, %d\n",
-			ret);
-		goto err_gpio2;
-	}
-
-	ret = gpio_direction_output(board->gpio_nrst, 0);
-	if (ret) {
-		dev_err(info->device, "could not set reset gpio, %d\n", ret);
-		goto err_gpio3;
-	}
-
-	ret = auok190x_power(par, 1);
-	if (ret) {
-		dev_err(info->device, "could not power on the device, %d\n",
-			ret);
-		goto err_gpio3;
-	}
-
-	mutex_init(&par->io_lock);
-
-	init_waitqueue_head(&par->waitq);
-
-	ret = par->board->setup_irq(par->info);
-	if (ret) {
-		dev_err(info->device, "could not setup ready-irq, %d\n", ret);
-		goto err_irq;
-	}
-
-	/* wait for init to complete */
-	par->board->wait_for_rdy(par);
-
-	/*
-	 * From here on the controller can talk to us
-	 */
-
-	/* initialise fix, var, resolution and rotation */
-
-	strlcpy(info->fix.id, init->id, 16);
-	info->var.bits_per_pixel = 8;
-	info->var.grayscale = 1;
-
-	panel = &panel_table[board->resolution];
-
-	par->resolution = board->resolution;
-	par->rotation = 0;
-
-	/* videomemory handling */
-
-	videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
-	videomemory = vmalloc(videomemorysize);
-	if (!videomemory) {
-		ret = -ENOMEM;
-		goto err_irq;
-	}
-
-	memset(videomemory, 0, videomemorysize);
-	info->screen_base = (char *)videomemory;
-	info->fix.smem_len = videomemorysize;
-
-	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
-	info->fbops = &auok190xfb_ops;
-
-	ret = auok190xfb_check_var(&info->var, info);
-	if (ret)
-		goto err_defio;
-
-	auok190xfb_set_fix(info);
-
-	/* deferred io init */
-
-	info->fbdefio = devm_kzalloc(info->device,
-				     sizeof(struct fb_deferred_io),
-				     GFP_KERNEL);
-	if (!info->fbdefio) {
-		dev_err(info->device, "Failed to allocate memory\n");
-		ret = -ENOMEM;
-		goto err_defio;
-	}
-
-	dev_dbg(info->device, "targeting %d frames per second\n", board->fps);
-	info->fbdefio->delay = HZ / board->fps;
-	info->fbdefio->first_io = auok190xfb_dpy_first_io,
-	info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io,
-	fb_deferred_io_init(info);
-
-	/* color map */
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret < 0) {
-		dev_err(info->device, "Failed to allocate colormap\n");
-		goto err_cmap;
-	}
-
-	/* controller init */
-
-	par->consecutive_threshold = 100;
-	par->init(par);
-	auok190x_identify(par);
-
-	platform_set_drvdata(pdev, info);
-
-	ret = register_framebuffer(info);
-	if (ret < 0)
-		goto err_regfb;
-
-	ret = sysfs_create_group(&info->device->kobj, &auok190x_attr_group);
-	if (ret)
-		goto err_sysfs;
-
-	dev_info(info->device, "fb%d: %dx%d using %dK of video memory\n",
-		 info->node, info->var.xres, info->var.yres,
-		 videomemorysize >> 10);
-
-	/* increase autosuspend_delay when we use alternative methods
-	 * for runtime_pm
-	 */
-	par->autosuspend_delay = (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN)
-					? 1000 : 200;
-
-	pm_runtime_set_active(info->device);
-	pm_runtime_enable(info->device);
-	pm_runtime_set_autosuspend_delay(info->device, par->autosuspend_delay);
-	pm_runtime_use_autosuspend(info->device);
-
-	return 0;
-
-err_sysfs:
-	unregister_framebuffer(info);
-err_regfb:
-	fb_dealloc_cmap(&info->cmap);
-err_cmap:
-	fb_deferred_io_cleanup(info);
-err_defio:
-	vfree((void *)info->screen_base);
-err_irq:
-	auok190x_power(par, 0);
-err_gpio3:
-	gpio_free(board->gpio_nrst);
-err_gpio2:
-	gpio_free(board->gpio_nsleep);
-err_gpio1:
-	board->cleanup(par);
-err_board:
-	regulator_put(par->regulator);
-err_reg:
-	framebuffer_release(info);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(auok190x_common_probe);
-
-int  auok190x_common_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct auok190xfb_par *par = info->par;
-	struct auok190x_board *board = par->board;
-
-	pm_runtime_disable(info->device);
-
-	sysfs_remove_group(&info->device->kobj, &auok190x_attr_group);
-
-	unregister_framebuffer(info);
-
-	fb_dealloc_cmap(&info->cmap);
-
-	fb_deferred_io_cleanup(info);
-
-	vfree((void *)info->screen_base);
-
-	auok190x_power(par, 0);
-
-	gpio_free(board->gpio_nrst);
-	gpio_free(board->gpio_nsleep);
-
-	board->cleanup(par);
-
-	regulator_put(par->regulator);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_common_remove);
-
-MODULE_DESCRIPTION("Common code for AUO-K190X controllers");
-MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/auo_k190x.h b/drivers/video/auo_k190x.h
deleted file mode 100644
index e35af1f51b28..000000000000
--- a/drivers/video/auo_k190x.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Private common definitions for AUO-K190X framebuffer drivers
- *
- * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * I80 interface specific defines
- */
-
-#define AUOK190X_I80_CS			0x01
-#define AUOK190X_I80_DC			0x02
-#define AUOK190X_I80_WR			0x03
-#define AUOK190X_I80_OE			0x04
-
-/*
- * AUOK190x commands, common to both controllers
- */
-
-#define AUOK190X_CMD_INIT		0x0000
-#define AUOK190X_CMD_STANDBY		0x0001
-#define AUOK190X_CMD_WAKEUP		0x0002
-#define AUOK190X_CMD_TCON_RESET		0x0003
-#define AUOK190X_CMD_DATA_STOP		0x1002
-#define AUOK190X_CMD_LUT_START		0x1003
-#define AUOK190X_CMD_DISP_REFRESH	0x1004
-#define AUOK190X_CMD_DISP_RESET		0x1005
-#define AUOK190X_CMD_PRE_DISPLAY_START	0x100D
-#define AUOK190X_CMD_PRE_DISPLAY_STOP	0x100F
-#define AUOK190X_CMD_FLASH_W		0x2000
-#define AUOK190X_CMD_FLASH_E		0x2001
-#define AUOK190X_CMD_FLASH_STS		0x2002
-#define AUOK190X_CMD_FRAMERATE		0x3000
-#define AUOK190X_CMD_READ_VERSION	0x4000
-#define AUOK190X_CMD_READ_STATUS	0x4001
-#define AUOK190X_CMD_READ_LUT		0x4003
-#define AUOK190X_CMD_DRIVERTIMING	0x5000
-#define AUOK190X_CMD_LBALANCE		0x5001
-#define AUOK190X_CMD_AGINGMODE		0x6000
-#define AUOK190X_CMD_AGINGEXIT		0x6001
-
-/*
- * Common settings for AUOK190X_CMD_INIT
- */
-
-#define AUOK190X_INIT_DATA_FILTER	(0 << 12)
-#define AUOK190X_INIT_DATA_BYPASS	(1 << 12)
-#define AUOK190X_INIT_INVERSE_WHITE	(0 << 9)
-#define AUOK190X_INIT_INVERSE_BLACK	(1 << 9)
-#define AUOK190X_INIT_SCAN_DOWN		(0 << 1)
-#define AUOK190X_INIT_SCAN_UP		(1 << 1)
-#define AUOK190X_INIT_SHIFT_LEFT	(0 << 0)
-#define AUOK190X_INIT_SHIFT_RIGHT	(1 << 0)
-
-/* Common bits to pixels
- *   Mode	15-12	11-8	7-4	3-0
- *   format0	4	3	2	1
- *   format1	3	4	1	2
- */
-
-#define AUOK190X_INIT_FORMAT0		0
-#define AUOK190X_INIT_FORMAT1		(1 << 6)
-
-/*
- * settings for AUOK190X_CMD_RESET
- */
-
-#define AUOK190X_RESET_TCON		(0 << 0)
-#define AUOK190X_RESET_NORMAL		(1 << 0)
-#define AUOK190X_RESET_PON		(1 << 1)
-
-/*
- * AUOK190X_CMD_VERSION
- */
-
-#define AUOK190X_VERSION_TEMP_MASK		(0x1ff)
-#define AUOK190X_VERSION_EPD_MASK		(0xff)
-#define AUOK190X_VERSION_SIZE_INT(_val)		((_val & 0xfc00) >> 10)
-#define AUOK190X_VERSION_SIZE_FLOAT(_val)	((_val & 0x3c0) >> 6)
-#define AUOK190X_VERSION_MODEL(_val)		(_val & 0x3f)
-#define AUOK190X_VERSION_LUT(_val)		(_val & 0xff)
-#define AUOK190X_VERSION_TCON(_val)		((_val & 0xff00) >> 8)
-
-/*
- * update modes for CMD_PARTIALDISP on K1900 and CMD_DDMA on K1901
- */
-
-#define AUOK190X_UPDATE_MODE(_res)		((_res & 0x7) << 12)
-#define AUOK190X_UPDATE_NONFLASH		(1 << 15)
-
-/*
- * track panel specific parameters for common init
- */
-
-struct auok190x_init_data {
-	char *id;
-	struct auok190x_board *board;
-
-	void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
-	void (*update_all)(struct auok190xfb_par *par);
-	bool (*need_refresh)(struct auok190xfb_par *par);
-	void (*init)(struct auok190xfb_par *par);
-};
-
-
-extern void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data);
-extern int auok190x_send_command(struct auok190xfb_par *par, u16 data);
-extern void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
-					 int argc, u16 *argv);
-extern int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
-				  int argc, u16 *argv);
-extern void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par,
-						u16 cmd, int argc, u16 *argv,
-						int size, u16 *data);
-extern int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
-					int argc, u16 *argv, int size,
-					u16 *data);
-extern int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
-				  int argc, u16 *argv);
-
-extern int auok190x_common_probe(struct platform_device *pdev,
-				 struct auok190x_init_data *init);
-extern int auok190x_common_remove(struct platform_device *pdev);
-
-extern const struct dev_pm_ops auok190x_pm;
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index bd2172c2d650..31672740fe28 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -189,8 +189,6 @@ static ssize_t brightness_store(struct device *dev,
 	}
 	mutex_unlock(&bd->ops_lock);
 
-	backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS);
-
 	return rc;
 }
 static DEVICE_ATTR_RW(brightness);
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
deleted file mode 100644
index a82d2578d976..000000000000
--- a/drivers/video/bf537-lq035.c
+++ /dev/null
@@ -1,915 +0,0 @@
-/*
- * Analog Devices Blackfin(BF537 STAMP) + SHARP TFT LCD.
- * http://docs.blackfin.uclinux.org/doku.php?id=hw:cards:tft-lcd
- *
- * Copyright 2006-2010 Analog Devices Inc.
- * Licensed under the GPL-2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/device.h>
-#include <linux/backlight.h>
-#include <linux/lcd.h>
-#include <linux/i2c.h>
-#include <linux/spinlock.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-
-#include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/dpmc.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-
-#define NO_BL 1
-
-#define MAX_BRIGHENESS	95
-#define MIN_BRIGHENESS	5
-#define NBR_PALETTE	256
-
-static const unsigned short ppi_pins[] = {
-	P_PPI0_CLK, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
-	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
-	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
-	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 0
-};
-
-static unsigned char *fb_buffer;          /* RGB Buffer */
-static unsigned long *dma_desc_table;
-static int t_conf_done, lq035_open_cnt;
-static DEFINE_SPINLOCK(bfin_lq035_lock);
-
-static int landscape;
-module_param(landscape, int, 0);
-MODULE_PARM_DESC(landscape,
-	"LANDSCAPE use 320x240 instead of Native 240x320 Resolution");
-
-static int bgr;
-module_param(bgr, int, 0);
-MODULE_PARM_DESC(bgr,
-	"BGR use 16-bit BGR-565 instead of RGB-565");
-
-static int nocursor = 1;
-module_param(nocursor, int, 0644);
-MODULE_PARM_DESC(nocursor, "cursor enable/disable");
-
-static unsigned long current_brightness;  /* backlight */
-
-/* AD5280 vcomm */
-static unsigned char vcomm_value = 150;
-static struct i2c_client *ad5280_client;
-
-static void set_vcomm(void)
-{
-	int nr;
-
-	if (!ad5280_client)
-		return;
-
-	nr = i2c_smbus_write_byte_data(ad5280_client, 0x00, vcomm_value);
-	if (nr)
-		pr_err("i2c_smbus_write_byte_data fail: %d\n", nr);
-}
-
-static int ad5280_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	int ret;
-	if (!i2c_check_functionality(client->adapter,
-				     I2C_FUNC_SMBUS_BYTE_DATA)) {
-		dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
-		return -EIO;
-	}
-
-	ret = i2c_smbus_write_byte_data(client, 0x00, vcomm_value);
-	if (ret) {
-		dev_err(&client->dev, "write fail: %d\n", ret);
-		return ret;
-	}
-
-	ad5280_client = client;
-
-	return 0;
-}
-
-static int ad5280_remove(struct i2c_client *client)
-{
-	ad5280_client = NULL;
-	return 0;
-}
-
-static const struct i2c_device_id ad5280_id[] = {
-	{"bf537-lq035-ad5280", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, ad5280_id);
-
-static struct i2c_driver ad5280_driver = {
-	.driver = {
-		.name = "bf537-lq035-ad5280",
-	},
-	.probe = ad5280_probe,
-	.remove = ad5280_remove,
-	.id_table = ad5280_id,
-};
-
-#ifdef CONFIG_PNAV10
-#define MOD GPIO_PH13
-
-#define bfin_write_TIMER_LP_CONFIG	bfin_write_TIMER0_CONFIG
-#define bfin_write_TIMER_LP_WIDTH	bfin_write_TIMER0_WIDTH
-#define bfin_write_TIMER_LP_PERIOD	bfin_write_TIMER0_PERIOD
-#define bfin_read_TIMER_LP_COUNTER	bfin_read_TIMER0_COUNTER
-#define TIMDIS_LP			TIMDIS0
-#define TIMEN_LP			TIMEN0
-
-#define bfin_write_TIMER_SPS_CONFIG	bfin_write_TIMER1_CONFIG
-#define bfin_write_TIMER_SPS_WIDTH	bfin_write_TIMER1_WIDTH
-#define bfin_write_TIMER_SPS_PERIOD	bfin_write_TIMER1_PERIOD
-#define TIMDIS_SPS			TIMDIS1
-#define TIMEN_SPS			TIMEN1
-
-#define bfin_write_TIMER_SP_CONFIG	bfin_write_TIMER5_CONFIG
-#define bfin_write_TIMER_SP_WIDTH	bfin_write_TIMER5_WIDTH
-#define bfin_write_TIMER_SP_PERIOD	bfin_write_TIMER5_PERIOD
-#define TIMDIS_SP			TIMDIS5
-#define TIMEN_SP			TIMEN5
-
-#define bfin_write_TIMER_PS_CLS_CONFIG	bfin_write_TIMER2_CONFIG
-#define bfin_write_TIMER_PS_CLS_WIDTH	bfin_write_TIMER2_WIDTH
-#define bfin_write_TIMER_PS_CLS_PERIOD	bfin_write_TIMER2_PERIOD
-#define TIMDIS_PS_CLS			TIMDIS2
-#define TIMEN_PS_CLS			TIMEN2
-
-#define bfin_write_TIMER_REV_CONFIG	bfin_write_TIMER3_CONFIG
-#define bfin_write_TIMER_REV_WIDTH	bfin_write_TIMER3_WIDTH
-#define bfin_write_TIMER_REV_PERIOD	bfin_write_TIMER3_PERIOD
-#define TIMDIS_REV			TIMDIS3
-#define TIMEN_REV			TIMEN3
-#define bfin_read_TIMER_REV_COUNTER	bfin_read_TIMER3_COUNTER
-
-#define	FREQ_PPI_CLK         (5*1024*1024)  /* PPI_CLK 5MHz */
-
-#define TIMERS {P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR5, 0}
-
-#else
-
-#define UD      GPIO_PF13	/* Up / Down */
-#define MOD     GPIO_PF10
-#define LBR     GPIO_PF14	/* Left Right */
-
-#define bfin_write_TIMER_LP_CONFIG	bfin_write_TIMER6_CONFIG
-#define bfin_write_TIMER_LP_WIDTH	bfin_write_TIMER6_WIDTH
-#define bfin_write_TIMER_LP_PERIOD	bfin_write_TIMER6_PERIOD
-#define bfin_read_TIMER_LP_COUNTER	bfin_read_TIMER6_COUNTER
-#define TIMDIS_LP			TIMDIS6
-#define TIMEN_LP			TIMEN6
-
-#define bfin_write_TIMER_SPS_CONFIG	bfin_write_TIMER1_CONFIG
-#define bfin_write_TIMER_SPS_WIDTH	bfin_write_TIMER1_WIDTH
-#define bfin_write_TIMER_SPS_PERIOD	bfin_write_TIMER1_PERIOD
-#define TIMDIS_SPS			TIMDIS1
-#define TIMEN_SPS			TIMEN1
-
-#define bfin_write_TIMER_SP_CONFIG	bfin_write_TIMER0_CONFIG
-#define bfin_write_TIMER_SP_WIDTH	bfin_write_TIMER0_WIDTH
-#define bfin_write_TIMER_SP_PERIOD	bfin_write_TIMER0_PERIOD
-#define TIMDIS_SP			TIMDIS0
-#define TIMEN_SP			TIMEN0
-
-#define bfin_write_TIMER_PS_CLS_CONFIG	bfin_write_TIMER7_CONFIG
-#define bfin_write_TIMER_PS_CLS_WIDTH	bfin_write_TIMER7_WIDTH
-#define bfin_write_TIMER_PS_CLS_PERIOD	bfin_write_TIMER7_PERIOD
-#define TIMDIS_PS_CLS			TIMDIS7
-#define TIMEN_PS_CLS			TIMEN7
-
-#define bfin_write_TIMER_REV_CONFIG	bfin_write_TIMER5_CONFIG
-#define bfin_write_TIMER_REV_WIDTH	bfin_write_TIMER5_WIDTH
-#define bfin_write_TIMER_REV_PERIOD	bfin_write_TIMER5_PERIOD
-#define TIMDIS_REV			TIMDIS5
-#define TIMEN_REV			TIMEN5
-#define bfin_read_TIMER_REV_COUNTER	bfin_read_TIMER5_COUNTER
-
-#define	FREQ_PPI_CLK         (6*1000*1000)  /* PPI_CLK 6MHz */
-#define TIMERS {P_TMR0, P_TMR1, P_TMR5, P_TMR6, P_TMR7, 0}
-
-#endif
-
-#define LCD_X_RES			240 /* Horizontal Resolution */
-#define LCD_Y_RES			320 /* Vertical Resolution */
-
-#define LCD_BBP				16  /* Bit Per Pixel */
-
-/* the LCD and the DMA start counting differently;
- * since one starts at 0 and the other starts at 1,
- * we have a difference of 1 between START_LINES
- * and U_LINES.
- */
-#define START_LINES       8   /* lines for field flyback or field blanking signal */
-#define U_LINES           9   /* number of undisplayed blanking lines */
-
-#define FRAMES_PER_SEC    (60)
-
-#define DCLKS_PER_FRAME   (FREQ_PPI_CLK/FRAMES_PER_SEC)
-#define DCLKS_PER_LINE    (DCLKS_PER_FRAME/(LCD_Y_RES+U_LINES))
-
-#define PPI_CONFIG_VALUE  (PORT_DIR|XFR_TYPE|DLEN_16|POLS)
-#define PPI_DELAY_VALUE   (0)
-#define TIMER_CONFIG      (PWM_OUT|PERIOD_CNT|TIN_SEL|CLK_SEL)
-
-#define ACTIVE_VIDEO_MEM_OFFSET	(LCD_X_RES*START_LINES*(LCD_BBP/8))
-#define ACTIVE_VIDEO_MEM_SIZE	(LCD_Y_RES*LCD_X_RES*(LCD_BBP/8))
-#define TOTAL_VIDEO_MEM_SIZE	((LCD_Y_RES+U_LINES)*LCD_X_RES*(LCD_BBP/8))
-#define TOTAL_DMA_DESC_SIZE	(2 * sizeof(u32) * (LCD_Y_RES + U_LINES))
-
-static void start_timers(void) /* CHECK with HW */
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	bfin_write_TIMER_ENABLE(TIMEN_REV);
-	SSYNC();
-
-	while (bfin_read_TIMER_REV_COUNTER() <= 11)
-		continue;
-	bfin_write_TIMER_ENABLE(TIMEN_LP);
-	SSYNC();
-
-	while (bfin_read_TIMER_LP_COUNTER() < 3)
-		continue;
-	bfin_write_TIMER_ENABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS);
-	SSYNC();
-	t_conf_done = 1;
-	local_irq_restore(flags);
-}
-
-static void config_timers(void)
-{
-	/* Stop timers */
-	bfin_write_TIMER_DISABLE(TIMDIS_SP|TIMDIS_SPS|TIMDIS_REV|
-				 TIMDIS_LP|TIMDIS_PS_CLS);
-	SSYNC();
-
-	/* LP, timer 6 */
-	bfin_write_TIMER_LP_CONFIG(TIMER_CONFIG|PULSE_HI);
-	bfin_write_TIMER_LP_WIDTH(1);
-
-	bfin_write_TIMER_LP_PERIOD(DCLKS_PER_LINE);
-	SSYNC();
-
-	/* SPS, timer 1 */
-	bfin_write_TIMER_SPS_CONFIG(TIMER_CONFIG|PULSE_HI);
-	bfin_write_TIMER_SPS_WIDTH(DCLKS_PER_LINE*2);
-	bfin_write_TIMER_SPS_PERIOD((DCLKS_PER_LINE * (LCD_Y_RES+U_LINES)));
-	SSYNC();
-
-	/* SP, timer 0 */
-	bfin_write_TIMER_SP_CONFIG(TIMER_CONFIG|PULSE_HI);
-	bfin_write_TIMER_SP_WIDTH(1);
-	bfin_write_TIMER_SP_PERIOD(DCLKS_PER_LINE);
-	SSYNC();
-
-	/* PS & CLS, timer 7 */
-	bfin_write_TIMER_PS_CLS_CONFIG(TIMER_CONFIG);
-	bfin_write_TIMER_PS_CLS_WIDTH(LCD_X_RES + START_LINES);
-	bfin_write_TIMER_PS_CLS_PERIOD(DCLKS_PER_LINE);
-
-	SSYNC();
-
-#ifdef NO_BL
-	/* REV, timer 5 */
-	bfin_write_TIMER_REV_CONFIG(TIMER_CONFIG|PULSE_HI);
-
-	bfin_write_TIMER_REV_WIDTH(DCLKS_PER_LINE);
-	bfin_write_TIMER_REV_PERIOD(DCLKS_PER_LINE*2);
-
-	SSYNC();
-#endif
-}
-
-static void config_ppi(void)
-{
-	bfin_write_PPI_DELAY(PPI_DELAY_VALUE);
-	bfin_write_PPI_COUNT(LCD_X_RES-1);
-	/* 0x10 -> PORT_CFG -> 2 or 3 frame syncs */
-	bfin_write_PPI_CONTROL((PPI_CONFIG_VALUE|0x10) & (~POLS));
-}
-
-static int config_dma(void)
-{
-	u32 i;
-
-	if (landscape) {
-
-		for (i = 0; i < U_LINES; ++i) {
-			/* blanking lines point to first line of fb_buffer */
-			dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
-			dma_desc_table[2*i+1] = (unsigned long)fb_buffer;
-		}
-
-		for (i = U_LINES; i < U_LINES + LCD_Y_RES; ++i) {
-			/* visible lines */
-			dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
-			dma_desc_table[2*i+1] = (unsigned long)fb_buffer +
-						(LCD_Y_RES+U_LINES-1-i)*2;
-		}
-
-		/* last descriptor points to first */
-		dma_desc_table[2*(LCD_Y_RES+U_LINES-1)] = (unsigned long)&dma_desc_table[0];
-
-		set_dma_x_count(CH_PPI, LCD_X_RES);
-		set_dma_x_modify(CH_PPI, LCD_Y_RES * (LCD_BBP / 8));
-		set_dma_y_count(CH_PPI, 0);
-		set_dma_y_modify(CH_PPI, 0);
-		set_dma_next_desc_addr(CH_PPI, (void *)dma_desc_table[0]);
-		set_dma_config(CH_PPI, DMAFLOW_LARGE | NDSIZE_4 | WDSIZE_16);
-
-	} else {
-
-		set_dma_config(CH_PPI, set_bfin_dma_config(DIR_READ,
-				DMA_FLOW_AUTO,
-				INTR_DISABLE,
-				DIMENSION_2D,
-				DATA_SIZE_16,
-				DMA_NOSYNC_KEEP_DMA_BUF));
-		set_dma_x_count(CH_PPI, LCD_X_RES);
-		set_dma_x_modify(CH_PPI, LCD_BBP / 8);
-		set_dma_y_count(CH_PPI, LCD_Y_RES+U_LINES);
-		set_dma_y_modify(CH_PPI, LCD_BBP / 8);
-		set_dma_start_addr(CH_PPI, (unsigned long) fb_buffer);
-	}
-
-	return 0;
-}
-
-static int request_ports(void)
-{
-	u16 tmr_req[] = TIMERS;
-
-	/*
-		UD:      PF13
-		MOD:     PF10
-		LBR:     PF14
-		PPI_CLK: PF15
-	*/
-
-	if (peripheral_request_list(ppi_pins, KBUILD_MODNAME)) {
-		pr_err("requesting PPI peripheral failed\n");
-		return -EBUSY;
-	}
-
-	if (peripheral_request_list(tmr_req, KBUILD_MODNAME)) {
-		peripheral_free_list(ppi_pins);
-		pr_err("requesting timer peripheral failed\n");
-		return -EBUSY;
-	}
-
-#if (defined(UD) && defined(LBR))
-	if (gpio_request_one(UD, GPIOF_OUT_INIT_LOW, KBUILD_MODNAME)) {
-		pr_err("requesting GPIO %d failed\n", UD);
-		return -EBUSY;
-	}
-
-	if (gpio_request_one(LBR, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
-		pr_err("requesting GPIO %d failed\n", LBR);
-		gpio_free(UD);
-		return -EBUSY;
-	}
-#endif
-
-	if (gpio_request_one(MOD, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
-		pr_err("requesting GPIO %d failed\n", MOD);
-#if (defined(UD) && defined(LBR))
-		gpio_free(LBR);
-		gpio_free(UD);
-#endif
-		return -EBUSY;
-	}
-
-	SSYNC();
-	return 0;
-}
-
-static void free_ports(void)
-{
-	u16 tmr_req[] = TIMERS;
-
-	peripheral_free_list(ppi_pins);
-	peripheral_free_list(tmr_req);
-
-#if defined(UD) && defined(LBR)
-	gpio_free(LBR);
-	gpio_free(UD);
-#endif
-	gpio_free(MOD);
-}
-
-static struct fb_info bfin_lq035_fb;
-
-static struct fb_var_screeninfo bfin_lq035_fb_defined = {
-	.bits_per_pixel		= LCD_BBP,
-	.activate		= FB_ACTIVATE_TEST,
-	.xres			= LCD_X_RES,	/*default portrait mode RGB*/
-	.yres			= LCD_Y_RES,
-	.xres_virtual		= LCD_X_RES,
-	.yres_virtual		= LCD_Y_RES,
-	.height			= -1,
-	.width			= -1,
-	.left_margin		= 0,
-	.right_margin		= 0,
-	.upper_margin		= 0,
-	.lower_margin		= 0,
-	.red			= {11, 5, 0},
-	.green			= {5, 6, 0},
-	.blue			= {0, 5, 0},
-	.transp		= {0, 0, 0},
-};
-
-static struct fb_fix_screeninfo bfin_lq035_fb_fix = {
-	.id		= KBUILD_MODNAME,
-	.smem_len	= ACTIVE_VIDEO_MEM_SIZE,
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_TRUECOLOR,
-	.xpanstep	= 0,
-	.ypanstep	= 0,
-	.line_length	= LCD_X_RES*(LCD_BBP/8),
-	.accel		= FB_ACCEL_NONE,
-};
-
-
-static int bfin_lq035_fb_open(struct fb_info *info, int user)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&bfin_lq035_lock, flags);
-	lq035_open_cnt++;
-	spin_unlock_irqrestore(&bfin_lq035_lock, flags);
-
-	if (lq035_open_cnt <= 1) {
-		bfin_write_PPI_CONTROL(0);
-		SSYNC();
-
-		set_vcomm();
-		config_dma();
-		config_ppi();
-
-		/* start dma */
-		enable_dma(CH_PPI);
-		SSYNC();
-		bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
-		SSYNC();
-
-		if (!t_conf_done) {
-			config_timers();
-			start_timers();
-		}
-		/* gpio_set_value(MOD,1); */
-	}
-
-	return 0;
-}
-
-static int bfin_lq035_fb_release(struct fb_info *info, int user)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&bfin_lq035_lock, flags);
-	lq035_open_cnt--;
-	spin_unlock_irqrestore(&bfin_lq035_lock, flags);
-
-
-	if (lq035_open_cnt <= 0) {
-
-		bfin_write_PPI_CONTROL(0);
-		SSYNC();
-
-		disable_dma(CH_PPI);
-	}
-
-	return 0;
-}
-
-
-static int bfin_lq035_fb_check_var(struct fb_var_screeninfo *var,
-				   struct fb_info *info)
-{
-	switch (var->bits_per_pixel) {
-	case 16:/* DIRECTCOLOUR, 64k */
-		var->red.offset = info->var.red.offset;
-		var->green.offset = info->var.green.offset;
-		var->blue.offset = info->var.blue.offset;
-		var->red.length = info->var.red.length;
-		var->green.length = info->var.green.length;
-		var->blue.length = info->var.blue.length;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->transp.msb_right = 0;
-		var->red.msb_right = 0;
-		var->green.msb_right = 0;
-		var->blue.msb_right = 0;
-		break;
-	default:
-		pr_debug("%s: depth not supported: %u BPP\n", __func__,
-			 var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (info->var.xres != var->xres ||
-	    info->var.yres != var->yres ||
-	    info->var.xres_virtual != var->xres_virtual ||
-	    info->var.yres_virtual != var->yres_virtual) {
-		pr_debug("%s: Resolution not supported: X%u x Y%u\n",
-			 __func__, var->xres, var->yres);
-		return -EINVAL;
-	}
-
-	/*
-	 *  Memory limit
-	 */
-
-	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
-			 __func__, var->yres_virtual);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-/* fb_rotate
- * Rotate the display of this angle. This doesn't seems to be used by the core,
- * but as our hardware supports it, so why not implementing it...
- */
-static void bfin_lq035_fb_rotate(struct fb_info *fbi, int angle)
-{
-	pr_debug("%s: %p %d", __func__, fbi, angle);
-#if (defined(UD) && defined(LBR))
-	switch (angle) {
-
-	case 180:
-		gpio_set_value(LBR, 0);
-		gpio_set_value(UD, 1);
-		break;
-	default:
-		gpio_set_value(LBR, 1);
-		gpio_set_value(UD, 0);
-		break;
-	}
-#endif
-}
-
-static int bfin_lq035_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	if (nocursor)
-		return 0;
-	else
-		return -EINVAL;	/* just to force soft_cursor() call */
-}
-
-static int bfin_lq035_fb_setcolreg(u_int regno, u_int red, u_int green,
-				   u_int blue, u_int transp,
-				   struct fb_info *info)
-{
-	if (regno >= NBR_PALETTE)
-		return -EINVAL;
-
-	if (info->var.grayscale)
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-
-		u32 value;
-		/* Place color in the pseudopalette */
-		if (regno > 16)
-			return -EINVAL;
-
-		red   >>= (16 - info->var.red.length);
-		green >>= (16 - info->var.green.length);
-		blue  >>= (16 - info->var.blue.length);
-
-		value = (red   << info->var.red.offset) |
-			(green << info->var.green.offset)|
-			(blue  << info->var.blue.offset);
-		value &= 0xFFFF;
-
-		((u32 *) (info->pseudo_palette))[regno] = value;
-
-	}
-
-	return 0;
-}
-
-static struct fb_ops bfin_lq035_fb_ops = {
-	.owner			= THIS_MODULE,
-	.fb_open		= bfin_lq035_fb_open,
-	.fb_release		= bfin_lq035_fb_release,
-	.fb_check_var		= bfin_lq035_fb_check_var,
-	.fb_rotate		= bfin_lq035_fb_rotate,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_cursor		= bfin_lq035_fb_cursor,
-	.fb_setcolreg		= bfin_lq035_fb_setcolreg,
-};
-
-static int bl_get_brightness(struct backlight_device *bd)
-{
-	return current_brightness;
-}
-
-static const struct backlight_ops bfin_lq035fb_bl_ops = {
-	.get_brightness	= bl_get_brightness,
-};
-
-static struct backlight_device *bl_dev;
-
-static int bfin_lcd_get_power(struct lcd_device *dev)
-{
-	return 0;
-}
-
-static int bfin_lcd_set_power(struct lcd_device *dev, int power)
-{
-	return 0;
-}
-
-static int bfin_lcd_get_contrast(struct lcd_device *dev)
-{
-	return (int)vcomm_value;
-}
-
-static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
-{
-	if (contrast > 255)
-		contrast = 255;
-	if (contrast < 0)
-		contrast = 0;
-
-	vcomm_value = (unsigned char)contrast;
-	set_vcomm();
-	return 0;
-}
-
-static int bfin_lcd_check_fb(struct lcd_device *lcd, struct fb_info *fi)
-{
-	if (!fi || (fi == &bfin_lq035_fb))
-		return 1;
-	return 0;
-}
-
-static struct lcd_ops bfin_lcd_ops = {
-	.get_power	= bfin_lcd_get_power,
-	.set_power	= bfin_lcd_set_power,
-	.get_contrast	= bfin_lcd_get_contrast,
-	.set_contrast	= bfin_lcd_set_contrast,
-	.check_fb	= bfin_lcd_check_fb,
-};
-
-static struct lcd_device *lcd_dev;
-
-static int bfin_lq035_probe(struct platform_device *pdev)
-{
-	struct backlight_properties props;
-	dma_addr_t dma_handle;
-	int ret;
-
-	if (request_dma(CH_PPI, KBUILD_MODNAME)) {
-		pr_err("couldn't request PPI DMA\n");
-		return -EFAULT;
-	}
-
-	if (request_ports()) {
-		pr_err("couldn't request gpio port\n");
-		ret = -EFAULT;
-		goto out_ports;
-	}
-
-	fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE,
-				       &dma_handle, GFP_KERNEL);
-	if (fb_buffer == NULL) {
-		pr_err("couldn't allocate dma buffer\n");
-		ret = -ENOMEM;
-		goto out_dma_coherent;
-	}
-
-	if (L1_DATA_A_LENGTH)
-		dma_desc_table = l1_data_sram_zalloc(TOTAL_DMA_DESC_SIZE);
-	else
-		dma_desc_table = dma_alloc_coherent(NULL, TOTAL_DMA_DESC_SIZE,
-						    &dma_handle, 0);
-
-	if (dma_desc_table == NULL) {
-		pr_err("couldn't allocate dma descriptor\n");
-		ret = -ENOMEM;
-		goto out_table;
-	}
-
-	bfin_lq035_fb.screen_base = (void *)fb_buffer;
-	bfin_lq035_fb_fix.smem_start = (int)fb_buffer;
-	if (landscape) {
-		bfin_lq035_fb_defined.xres = LCD_Y_RES;
-		bfin_lq035_fb_defined.yres = LCD_X_RES;
-		bfin_lq035_fb_defined.xres_virtual = LCD_Y_RES;
-		bfin_lq035_fb_defined.yres_virtual = LCD_X_RES;
-
-		bfin_lq035_fb_fix.line_length = LCD_Y_RES*(LCD_BBP/8);
-	} else {
-		bfin_lq035_fb.screen_base += ACTIVE_VIDEO_MEM_OFFSET;
-		bfin_lq035_fb_fix.smem_start += ACTIVE_VIDEO_MEM_OFFSET;
-	}
-
-	bfin_lq035_fb_defined.green.msb_right = 0;
-	bfin_lq035_fb_defined.red.msb_right   = 0;
-	bfin_lq035_fb_defined.blue.msb_right  = 0;
-	bfin_lq035_fb_defined.green.offset    = 5;
-	bfin_lq035_fb_defined.green.length    = 6;
-	bfin_lq035_fb_defined.red.length      = 5;
-	bfin_lq035_fb_defined.blue.length     = 5;
-
-	if (bgr) {
-		bfin_lq035_fb_defined.red.offset  = 0;
-		bfin_lq035_fb_defined.blue.offset = 11;
-	} else {
-		bfin_lq035_fb_defined.red.offset  = 11;
-		bfin_lq035_fb_defined.blue.offset = 0;
-	}
-
-	bfin_lq035_fb.fbops = &bfin_lq035_fb_ops;
-	bfin_lq035_fb.var = bfin_lq035_fb_defined;
-
-	bfin_lq035_fb.fix = bfin_lq035_fb_fix;
-	bfin_lq035_fb.flags = FBINFO_DEFAULT;
-
-
-	bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev,
-						    sizeof(u32) * 16,
-						    GFP_KERNEL);
-	if (bfin_lq035_fb.pseudo_palette == NULL) {
-		pr_err("failed to allocate pseudo_palette\n");
-		ret = -ENOMEM;
-		goto out_table;
-	}
-
-	if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
-		pr_err("failed to allocate colormap (%d entries)\n",
-			NBR_PALETTE);
-		ret = -EFAULT;
-		goto out_table;
-	}
-
-	if (register_framebuffer(&bfin_lq035_fb) < 0) {
-		pr_err("unable to register framebuffer\n");
-		ret = -EINVAL;
-		goto out_reg;
-	}
-
-	i2c_add_driver(&ad5280_driver);
-
-	memset(&props, 0, sizeof(props));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = MAX_BRIGHENESS;
-	bl_dev = backlight_device_register("bf537-bl", NULL, NULL,
-					   &bfin_lq035fb_bl_ops, &props);
-
-	lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL,
-				      &bfin_lcd_ops);
-	if (IS_ERR(lcd_dev)) {
-		pr_err("unable to register lcd\n");
-		ret = PTR_ERR(lcd_dev);
-		goto out_lcd;
-	}
-	lcd_dev->props.max_contrast = 255,
-
-	pr_info("initialized");
-
-	return 0;
-out_lcd:
-	unregister_framebuffer(&bfin_lq035_fb);
-out_reg:
-	fb_dealloc_cmap(&bfin_lq035_fb.cmap);
-out_table:
-	dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
-	fb_buffer = NULL;
-out_dma_coherent:
-	free_ports();
-out_ports:
-	free_dma(CH_PPI);
-	return ret;
-}
-
-static int bfin_lq035_remove(struct platform_device *pdev)
-{
-	if (fb_buffer != NULL)
-		dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
-
-	if (L1_DATA_A_LENGTH)
-		l1_data_sram_free(dma_desc_table);
-	else
-		dma_free_coherent(NULL, TOTAL_DMA_DESC_SIZE, NULL, 0);
-
-	bfin_write_TIMER_DISABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS|
-				 TIMEN_LP|TIMEN_REV);
-	t_conf_done = 0;
-
-	free_dma(CH_PPI);
-
-
-	fb_dealloc_cmap(&bfin_lq035_fb.cmap);
-
-
-	lcd_device_unregister(lcd_dev);
-	backlight_device_unregister(bl_dev);
-
-	unregister_framebuffer(&bfin_lq035_fb);
-	i2c_del_driver(&ad5280_driver);
-
-	free_ports();
-
-	pr_info("unregistered LCD driver\n");
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_lq035_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	if (lq035_open_cnt > 0) {
-		bfin_write_PPI_CONTROL(0);
-		SSYNC();
-		disable_dma(CH_PPI);
-	}
-
-	return 0;
-}
-
-static int bfin_lq035_resume(struct platform_device *pdev)
-{
-	if (lq035_open_cnt > 0) {
-		bfin_write_PPI_CONTROL(0);
-		SSYNC();
-
-		config_dma();
-		config_ppi();
-
-		enable_dma(CH_PPI);
-		bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
-		SSYNC();
-
-		config_timers();
-		start_timers();
-	} else {
-		t_conf_done = 0;
-	}
-
-	return 0;
-}
-#else
-# define bfin_lq035_suspend	NULL
-# define bfin_lq035_resume	NULL
-#endif
-
-static struct platform_driver bfin_lq035_driver = {
-	.probe = bfin_lq035_probe,
-	.remove = bfin_lq035_remove,
-	.suspend = bfin_lq035_suspend,
-	.resume = bfin_lq035_resume,
-	.driver = {
-		.name = KBUILD_MODNAME,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init bfin_lq035_driver_init(void)
-{
-	request_module("i2c-bfin-twi");
-	return platform_driver_register(&bfin_lq035_driver);
-}
-module_init(bfin_lq035_driver_init);
-
-static void __exit bfin_lq035_driver_cleanup(void)
-{
-	platform_driver_unregister(&bfin_lq035_driver);
-}
-module_exit(bfin_lq035_driver_cleanup);
-
-MODULE_DESCRIPTION("SHARP LQ035Q7DB03 TFT LCD Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
deleted file mode 100644
index 42b8f9d11018..000000000000
--- a/drivers/video/bf54x-lq043fb.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * File:         drivers/video/bf54x-lq043.c
- * Based on:
- * Author:       Michael Hennerich <hennerich@blackfin.uclinux.org>
- *
- * Created:
- * Description:  ADSP-BF54x Framebuffer driver
- *
- *
- * Modified:
- *               Copyright 2007-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/device.h>
-#include <linux/backlight.h>
-#include <linux/lcd.h>
-#include <linux/spinlock.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-
-#include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/dpmc.h>
-#include <asm/dma-mapping.h>
-#include <asm/dma.h>
-#include <asm/gpio.h>
-#include <asm/portmux.h>
-
-#include <mach/bf54x-lq043.h>
-
-#define NO_BL_SUPPORT
-
-#define DRIVER_NAME "bf54x-lq043"
-static char driver_name[] = DRIVER_NAME;
-
-#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
-
-#define EPPI0_18 {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, \
- P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, \
- P_PPI0_D11, P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, P_PPI0_D16, P_PPI0_D17, 0}
-
-#define EPPI0_24 {P_PPI0_D18, P_PPI0_D19, P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, 0}
-
-struct bfin_bf54xfb_info {
-	struct fb_info *fb;
-	struct device *dev;
-
-	struct bfin_bf54xfb_mach_info *mach_info;
-
-	unsigned char *fb_buffer;	/* RGB Buffer */
-
-	dma_addr_t dma_handle;
-	int lq043_open_cnt;
-	int irq;
-	spinlock_t lock;	/* lock */
-};
-
-static int nocursor;
-module_param(nocursor, int, 0644);
-MODULE_PARM_DESC(nocursor, "cursor enable/disable");
-
-static int outp_rgb666;
-module_param(outp_rgb666, int, 0);
-MODULE_PARM_DESC(outp_rgb666, "Output 18-bit RGB666");
-
-#define LCD_X_RES		480	/*Horizontal Resolution */
-#define LCD_Y_RES		272	/* Vertical Resolution */
-
-#define LCD_BPP			24	/* Bit Per Pixel */
-#define	DMA_BUS_SIZE		32
-
-/* 	-- Horizontal synchronizing --
- *
- * Timing characteristics taken from the SHARP LQ043T1DG01 datasheet
- * (LCY-W-06602A Page 9 of 22)
- *
- * Clock Frequency 	1/Tc Min 7.83 Typ 9.00 Max 9.26 MHz
- *
- * Period 		TH - 525 - Clock
- * Pulse width 		THp - 41 - Clock
- * Horizontal period 	THd - 480 - Clock
- * Back porch 		THb - 2 - Clock
- * Front porch 		THf - 2 - Clock
- *
- * -- Vertical synchronizing --
- * Period 		TV - 286 - Line
- * Pulse width 		TVp - 10 - Line
- * Vertical period 	TVd - 272 - Line
- * Back porch 		TVb - 2 - Line
- * Front porch 		TVf - 2 - Line
- */
-
-#define	LCD_CLK         	(8*1000*1000)	/* 8MHz */
-
-/* # active data to transfer after Horizontal Delay clock */
-#define EPPI_HCOUNT		LCD_X_RES
-
-/* # active lines to transfer after Vertical Delay clock */
-#define EPPI_VCOUNT		LCD_Y_RES
-
-/* Samples per Line = 480 (active data) + 45 (padding) */
-#define EPPI_LINE		525
-
-/* Lines per Frame = 272 (active data) + 14 (padding) */
-#define EPPI_FRAME		286
-
-/* FS1 (Hsync) Width (Typical)*/
-#define EPPI_FS1W_HBL		41
-
-/* FS1 (Hsync) Period (Typical) */
-#define EPPI_FS1P_AVPL		EPPI_LINE
-
-/* Horizontal Delay clock after assertion of Hsync (Typical) */
-#define EPPI_HDELAY		43
-
-/* FS2 (Vsync) Width    = FS1 (Hsync) Period * 10 */
-#define EPPI_FS2W_LVB		(EPPI_LINE * 10)
-
- /* FS2 (Vsync) Period   = FS1 (Hsync) Period * Lines per Frame */
-#define EPPI_FS2P_LAVF		(EPPI_LINE * EPPI_FRAME)
-
-/* Vertical Delay after assertion of Vsync (2 Lines) */
-#define EPPI_VDELAY		12
-
-#define EPPI_CLIP		0xFF00FF00
-
-/* EPPI Control register configuration value for RGB out
- * - EPPI as Output
- * GP 2 frame sync mode,
- * Internal Clock generation disabled, Internal FS generation enabled,
- * Receives samples on EPPI_CLK raising edge, Transmits samples on EPPI_CLK falling edge,
- * FS1 & FS2 are active high,
- * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
- * DMA Unpacking disabled when RGB Formating is enabled, otherwise DMA unpacking enabled
- * Swapping Enabled,
- * One (DMA) Channel Mode,
- * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
- * Regular watermark - when FIFO is 100% full,
- * Urgent watermark - when FIFO is 75% full
- */
-
-#define EPPI_CONTROL		(0x20136E2E | SWAPEN)
-
-static inline u16 get_eppi_clkdiv(u32 target_ppi_clk)
-{
-	u32 sclk = get_sclk();
-
-	/* EPPI_CLK = (SCLK) / (2 * (EPPI_CLKDIV[15:0] + 1)) */
-
-	return (((sclk / target_ppi_clk) / 2) - 1);
-}
-
-static void config_ppi(struct bfin_bf54xfb_info *fbi)
-{
-
-	u16 eppi_clkdiv = get_eppi_clkdiv(LCD_CLK);
-
-	bfin_write_EPPI0_FS1W_HBL(EPPI_FS1W_HBL);
-	bfin_write_EPPI0_FS1P_AVPL(EPPI_FS1P_AVPL);
-	bfin_write_EPPI0_FS2W_LVB(EPPI_FS2W_LVB);
-	bfin_write_EPPI0_FS2P_LAVF(EPPI_FS2P_LAVF);
-	bfin_write_EPPI0_CLIP(EPPI_CLIP);
-
-	bfin_write_EPPI0_FRAME(EPPI_FRAME);
-	bfin_write_EPPI0_LINE(EPPI_LINE);
-
-	bfin_write_EPPI0_HCOUNT(EPPI_HCOUNT);
-	bfin_write_EPPI0_HDELAY(EPPI_HDELAY);
-	bfin_write_EPPI0_VCOUNT(EPPI_VCOUNT);
-	bfin_write_EPPI0_VDELAY(EPPI_VDELAY);
-
-	bfin_write_EPPI0_CLKDIV(eppi_clkdiv);
-
-/*
- * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
- * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
- */
-	if (outp_rgb666)
-		bfin_write_EPPI0_CONTROL((EPPI_CONTROL & ~DLENGTH) | DLEN_18 |
-					 RGB_FMT_EN);
-	else
-		bfin_write_EPPI0_CONTROL(((EPPI_CONTROL & ~DLENGTH) | DLEN_24) &
-					 ~RGB_FMT_EN);
-
-
-}
-
-static int config_dma(struct bfin_bf54xfb_info *fbi)
-{
-
-	set_dma_config(CH_EPPI0,
-		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
-					   INTR_DISABLE, DIMENSION_2D,
-					   DATA_SIZE_32,
-					   DMA_NOSYNC_KEEP_DMA_BUF));
-	set_dma_x_count(CH_EPPI0, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
-	set_dma_x_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
-	set_dma_y_count(CH_EPPI0, LCD_Y_RES);
-	set_dma_y_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
-	set_dma_start_addr(CH_EPPI0, (unsigned long)fbi->fb_buffer);
-
-	return 0;
-}
-
-static int request_ports(struct bfin_bf54xfb_info *fbi)
-{
-
-	u16 eppi_req_18[] = EPPI0_18;
-	u16 disp = fbi->mach_info->disp;
-
-	if (gpio_request_one(disp, GPIOF_OUT_INIT_HIGH, DRIVER_NAME)) {
-		printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
-		return -EFAULT;
-	}
-
-	if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) {
-		printk(KERN_ERR "Requesting Peripherals failed\n");
-		gpio_free(disp);
-		return -EFAULT;
-	}
-
-	if (!outp_rgb666) {
-
-		u16 eppi_req_24[] = EPPI0_24;
-
-		if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) {
-			printk(KERN_ERR "Requesting Peripherals failed\n");
-			peripheral_free_list(eppi_req_18);
-			gpio_free(disp);
-			return -EFAULT;
-		}
-	}
-
-	return 0;
-}
-
-static void free_ports(struct bfin_bf54xfb_info *fbi)
-{
-
-	u16 eppi_req_18[] = EPPI0_18;
-
-	gpio_free(fbi->mach_info->disp);
-
-	peripheral_free_list(eppi_req_18);
-
-	if (!outp_rgb666) {
-		u16 eppi_req_24[] = EPPI0_24;
-		peripheral_free_list(eppi_req_24);
-	}
-}
-
-static int bfin_bf54x_fb_open(struct fb_info *info, int user)
-{
-	struct bfin_bf54xfb_info *fbi = info->par;
-
-	spin_lock(&fbi->lock);
-	fbi->lq043_open_cnt++;
-
-	if (fbi->lq043_open_cnt <= 1) {
-
-		bfin_write_EPPI0_CONTROL(0);
-		SSYNC();
-
-		config_dma(fbi);
-		config_ppi(fbi);
-
-		/* start dma */
-		enable_dma(CH_EPPI0);
-		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
-	}
-
-	spin_unlock(&fbi->lock);
-
-	return 0;
-}
-
-static int bfin_bf54x_fb_release(struct fb_info *info, int user)
-{
-	struct bfin_bf54xfb_info *fbi = info->par;
-
-	spin_lock(&fbi->lock);
-
-	fbi->lq043_open_cnt--;
-
-	if (fbi->lq043_open_cnt <= 0) {
-
-		bfin_write_EPPI0_CONTROL(0);
-		SSYNC();
-		disable_dma(CH_EPPI0);
-	}
-
-	spin_unlock(&fbi->lock);
-
-	return 0;
-}
-
-static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
-				   struct fb_info *info)
-{
-
-	switch (var->bits_per_pixel) {
-	case 24:/* TRUECOLOUR, 16m */
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->transp.msb_right = 0;
-		var->red.msb_right = 0;
-		var->green.msb_right = 0;
-		var->blue.msb_right = 0;
-		break;
-	default:
-		pr_debug("%s: depth not supported: %u BPP\n", __func__,
-			 var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (info->var.xres != var->xres || info->var.yres != var->yres ||
-	    info->var.xres_virtual != var->xres_virtual ||
-	    info->var.yres_virtual != var->yres_virtual) {
-		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
-			 __func__, var->xres, var->yres);
-		return -EINVAL;
-	}
-
-	/*
-	 *  Memory limit
-	 */
-
-	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
-			 __func__, var->yres_virtual);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	if (nocursor)
-		return 0;
-	else
-		return -EINVAL;	/* just to force soft_cursor() call */
-}
-
-static int bfin_bf54x_fb_setcolreg(u_int regno, u_int red, u_int green,
-				   u_int blue, u_int transp,
-				   struct fb_info *info)
-{
-	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
-		return -EINVAL;
-
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-
-		u32 value;
-		/* Place color in the pseudopalette */
-		if (regno > 16)
-			return -EINVAL;
-
-		red >>= (16 - info->var.red.length);
-		green >>= (16 - info->var.green.length);
-		blue >>= (16 - info->var.blue.length);
-
-		value = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset);
-		value &= 0xFFFFFF;
-
-		((u32 *) (info->pseudo_palette))[regno] = value;
-
-	}
-
-	return 0;
-}
-
-static struct fb_ops bfin_bf54x_fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = bfin_bf54x_fb_open,
-	.fb_release = bfin_bf54x_fb_release,
-	.fb_check_var = bfin_bf54x_fb_check_var,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor = bfin_bf54x_fb_cursor,
-	.fb_setcolreg = bfin_bf54x_fb_setcolreg,
-};
-
-#ifndef NO_BL_SUPPORT
-static int bl_get_brightness(struct backlight_device *bd)
-{
-	return 0;
-}
-
-static const struct backlight_ops bfin_lq043fb_bl_ops = {
-	.get_brightness = bl_get_brightness,
-};
-
-static struct backlight_device *bl_dev;
-
-static int bfin_lcd_get_power(struct lcd_device *dev)
-{
-	return 0;
-}
-
-static int bfin_lcd_set_power(struct lcd_device *dev, int power)
-{
-	return 0;
-}
-
-static int bfin_lcd_get_contrast(struct lcd_device *dev)
-{
-	return 0;
-}
-
-static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
-{
-
-	return 0;
-}
-
-static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
-{
-	if (!fi || (fi == &bfin_bf54x_fb))
-		return 1;
-	return 0;
-}
-
-static struct lcd_ops bfin_lcd_ops = {
-	.get_power = bfin_lcd_get_power,
-	.set_power = bfin_lcd_set_power,
-	.get_contrast = bfin_lcd_get_contrast,
-	.set_contrast = bfin_lcd_set_contrast,
-	.check_fb = bfin_lcd_check_fb,
-};
-
-static struct lcd_device *lcd_dev;
-#endif
-
-static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
-{
-	/*struct bfin_bf54xfb_info *info = dev_id;*/
-
-	u16 status = bfin_read_EPPI0_STATUS();
-
-	bfin_write_EPPI0_STATUS(0xFFFF);
-
-	if (status) {
-		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
-		disable_dma(CH_EPPI0);
-
-		/* start dma */
-		enable_dma(CH_EPPI0);
-		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
-		bfin_write_EPPI0_STATUS(0xFFFF);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int bfin_bf54x_probe(struct platform_device *pdev)
-{
-#ifndef NO_BL_SUPPORT
-	struct backlight_properties props;
-#endif
-	struct bfin_bf54xfb_info *info;
-	struct fb_info *fbinfo;
-	int ret;
-
-	printk(KERN_INFO DRIVER_NAME ": FrameBuffer initializing...\n");
-
-	if (request_dma(CH_EPPI0, "CH_EPPI0") < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": couldn't request CH_EPPI0 DMA\n");
-		ret = -EFAULT;
-		goto out1;
-	}
-
-	fbinfo =
-	    framebuffer_alloc(sizeof(struct bfin_bf54xfb_info), &pdev->dev);
-	if (!fbinfo) {
-		ret = -ENOMEM;
-		goto out2;
-	}
-
-	info = fbinfo->par;
-	info->fb = fbinfo;
-	info->dev = &pdev->dev;
-	spin_lock_init(&info->lock);
-
-	platform_set_drvdata(pdev, fbinfo);
-
-	strcpy(fbinfo->fix.id, driver_name);
-
-	info->mach_info = pdev->dev.platform_data;
-
-	if (info->mach_info == NULL) {
-		dev_err(&pdev->dev,
-			"no platform data for lcd, cannot attach\n");
-		ret = -EINVAL;
-		goto out3;
-	}
-
-	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
-	fbinfo->fix.type_aux = 0;
-	fbinfo->fix.xpanstep = 0;
-	fbinfo->fix.ypanstep = 0;
-	fbinfo->fix.ywrapstep = 0;
-	fbinfo->fix.accel = FB_ACCEL_NONE;
-	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	fbinfo->var.nonstd = 0;
-	fbinfo->var.activate = FB_ACTIVATE_NOW;
-	fbinfo->var.height = info->mach_info->height;
-	fbinfo->var.width = info->mach_info->width;
-	fbinfo->var.accel_flags = 0;
-	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
-
-	fbinfo->fbops = &bfin_bf54x_fb_ops;
-	fbinfo->flags = FBINFO_FLAG_DEFAULT;
-
-	fbinfo->var.xres = info->mach_info->xres.defval;
-	fbinfo->var.xres_virtual = info->mach_info->xres.defval;
-	fbinfo->var.yres = info->mach_info->yres.defval;
-	fbinfo->var.yres_virtual = info->mach_info->yres.defval;
-	fbinfo->var.bits_per_pixel = info->mach_info->bpp.defval;
-
-	fbinfo->var.upper_margin = 0;
-	fbinfo->var.lower_margin = 0;
-	fbinfo->var.vsync_len = 0;
-
-	fbinfo->var.left_margin = 0;
-	fbinfo->var.right_margin = 0;
-	fbinfo->var.hsync_len = 0;
-
-	fbinfo->var.red.offset = 16;
-	fbinfo->var.green.offset = 8;
-	fbinfo->var.blue.offset = 0;
-	fbinfo->var.transp.offset = 0;
-	fbinfo->var.red.length = 8;
-	fbinfo->var.green.length = 8;
-	fbinfo->var.blue.length = 8;
-	fbinfo->var.transp.length = 0;
-	fbinfo->fix.smem_len = info->mach_info->xres.max *
-	    info->mach_info->yres.max * info->mach_info->bpp.max / 8;
-
-	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
-	    fbinfo->var.bits_per_pixel / 8;
-
-	info->fb_buffer =
-	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
-			       GFP_KERNEL);
-
-	if (NULL == info->fb_buffer) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": couldn't allocate dma buffer.\n");
-		ret = -ENOMEM;
-		goto out3;
-	}
-
-	fbinfo->screen_base = (void *)info->fb_buffer;
-	fbinfo->fix.smem_start = (int)info->fb_buffer;
-
-	fbinfo->fbops = &bfin_bf54x_fb_ops;
-
-	fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
-					      GFP_KERNEL);
-	if (!fbinfo->pseudo_palette) {
-		printk(KERN_ERR DRIVER_NAME
-		       "Fail to allocate pseudo_palette\n");
-
-		ret = -ENOMEM;
-		goto out4;
-	}
-
-	if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
-	    < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       "Fail to allocate colormap (%d entries)\n",
-		       BFIN_LCD_NBR_PALETTE_ENTRIES);
-		ret = -EFAULT;
-		goto out4;
-	}
-
-	if (request_ports(info)) {
-		printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
-		ret = -EFAULT;
-		goto out6;
-	}
-
-	info->irq = platform_get_irq(pdev, 0);
-	if (info->irq < 0) {
-		ret = -EINVAL;
-		goto out7;
-	}
-
-	if (request_irq(info->irq, bfin_bf54x_irq_error, 0,
-			"PPI ERROR", info) < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": unable to request PPI ERROR IRQ\n");
-		ret = -EFAULT;
-		goto out7;
-	}
-
-	if (register_framebuffer(fbinfo) < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": unable to register framebuffer.\n");
-		ret = -EINVAL;
-		goto out8;
-	}
-#ifndef NO_BL_SUPPORT
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 255;
-	bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
-					   &bfin_lq043fb_bl_ops, &props);
-	if (IS_ERR(bl_dev)) {
-		printk(KERN_ERR DRIVER_NAME
-			": unable to register backlight.\n");
-		ret = -EINVAL;
-		unregister_framebuffer(fbinfo);
-		goto out8;
-	}
-
-	lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
-	lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
-#endif
-
-	return 0;
-
-out8:
-	free_irq(info->irq, info);
-out7:
-	free_ports(info);
-out6:
-	fb_dealloc_cmap(&fbinfo->cmap);
-out4:
-	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-			  info->dma_handle);
-out3:
-	framebuffer_release(fbinfo);
-out2:
-	free_dma(CH_EPPI0);
-out1:
-
-	return ret;
-}
-
-static int bfin_bf54x_remove(struct platform_device *pdev)
-{
-
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct bfin_bf54xfb_info *info = fbinfo->par;
-
-	free_dma(CH_EPPI0);
-	free_irq(info->irq, info);
-
-	if (info->fb_buffer != NULL)
-		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-				  info->dma_handle);
-
-	fb_dealloc_cmap(&fbinfo->cmap);
-
-#ifndef NO_BL_SUPPORT
-	lcd_device_unregister(lcd_dev);
-	backlight_device_unregister(bl_dev);
-#endif
-
-	unregister_framebuffer(fbinfo);
-
-	free_ports(info);
-
-	printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-
-	bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
-	disable_dma(CH_EPPI0);
-	bfin_write_EPPI0_STATUS(0xFFFF);
-
-	return 0;
-}
-
-static int bfin_bf54x_resume(struct platform_device *pdev)
-{
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct bfin_bf54xfb_info *info = fbinfo->par;
-
-	if (info->lq043_open_cnt) {
-
-		bfin_write_EPPI0_CONTROL(0);
-		SSYNC();
-
-		config_dma(info);
-		config_ppi(info);
-
-		/* start dma */
-		enable_dma(CH_EPPI0);
-		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
-	}
-
-	return 0;
-}
-#else
-#define bfin_bf54x_suspend	NULL
-#define bfin_bf54x_resume	NULL
-#endif
-
-static struct platform_driver bfin_bf54x_driver = {
-	.probe = bfin_bf54x_probe,
-	.remove = bfin_bf54x_remove,
-	.suspend = bfin_bf54x_suspend,
-	.resume = bfin_bf54x_resume,
-	.driver = {
-		   .name = DRIVER_NAME,
-		   .owner = THIS_MODULE,
-		   },
-};
-module_platform_driver(bfin_bf54x_driver);
-
-MODULE_DESCRIPTION("Blackfin BF54x TFT LCD Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
deleted file mode 100644
index b594a58ff21d..000000000000
--- a/drivers/video/bfin-lq035q1-fb.c
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02
- *
- * Copyright 2008-2009 Analog Devices Inc.
- * Licensed under the GPL-2 or later.
- */
-
-#define DRIVER_NAME "bfin-lq035q1"
-#define pr_fmt(fmt) DRIVER_NAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/backlight.h>
-#include <linux/lcd.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-
-#include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-#include <asm/gptimers.h>
-
-#include <asm/bfin-lq035q1.h>
-
-#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
-#define TIMER_HSYNC_id			TIMER1_id
-#define TIMER_HSYNCbit			TIMER1bit
-#define TIMER_HSYNC_STATUS_TRUN		TIMER_STATUS_TRUN1
-#define TIMER_HSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL1
-#define TIMER_HSYNC_STATUS_TOVF		TIMER_STATUS_TOVF1
-
-#define TIMER_VSYNC_id			TIMER2_id
-#define TIMER_VSYNCbit			TIMER2bit
-#define TIMER_VSYNC_STATUS_TRUN		TIMER_STATUS_TRUN2
-#define TIMER_VSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL2
-#define TIMER_VSYNC_STATUS_TOVF		TIMER_STATUS_TOVF2
-#else
-#define TIMER_HSYNC_id			TIMER0_id
-#define TIMER_HSYNCbit			TIMER0bit
-#define TIMER_HSYNC_STATUS_TRUN		TIMER_STATUS_TRUN0
-#define TIMER_HSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL0
-#define TIMER_HSYNC_STATUS_TOVF		TIMER_STATUS_TOVF0
-
-#define TIMER_VSYNC_id			TIMER1_id
-#define TIMER_VSYNCbit			TIMER1bit
-#define TIMER_VSYNC_STATUS_TRUN		TIMER_STATUS_TRUN1
-#define TIMER_VSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL1
-#define TIMER_VSYNC_STATUS_TOVF		TIMER_STATUS_TOVF1
-#endif
-
-#define LCD_X_RES		320	/* Horizontal Resolution */
-#define LCD_Y_RES		240	/* Vertical Resolution */
-#define	DMA_BUS_SIZE		16
-#define U_LINE			4	/* Blanking Lines */
-
-
-/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD)
- * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
- */
-
-
-#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
-
-#define PPI_TX_MODE			0x2
-#define PPI_XFER_TYPE_11		0xC
-#define PPI_PORT_CFG_01			0x10
-#define PPI_POLS_1			0x8000
-
-#define LQ035_INDEX			0x74
-#define LQ035_DATA			0x76
-
-#define LQ035_DRIVER_OUTPUT_CTL		0x1
-#define LQ035_SHUT_CTL			0x11
-
-#define LQ035_DRIVER_OUTPUT_MASK	(LQ035_LR | LQ035_TB | LQ035_BGR | LQ035_REV)
-#define LQ035_DRIVER_OUTPUT_DEFAULT	(0x2AEF & ~LQ035_DRIVER_OUTPUT_MASK)
-
-#define LQ035_SHUT			(1 << 0)	/* Shutdown */
-#define LQ035_ON			(0 << 0)	/* Shutdown */
-
-struct bfin_lq035q1fb_info {
-	struct fb_info *fb;
-	struct device *dev;
-	struct spi_driver spidrv;
-	struct bfin_lq035q1fb_disp_info *disp_info;
-	unsigned char *fb_buffer;	/* RGB Buffer */
-	dma_addr_t dma_handle;
-	int lq035_open_cnt;
-	int irq;
-	spinlock_t lock;	/* lock */
-	u32 pseudo_pal[16];
-
-	u32 lcd_bpp;
-	u32 h_actpix;
-	u32 h_period;
-	u32 h_pulse;
-	u32 h_start;
-	u32 v_lines;
-	u32 v_pulse;
-	u32 v_period;
-};
-
-static int nocursor;
-module_param(nocursor, int, 0644);
-MODULE_PARM_DESC(nocursor, "cursor enable/disable");
-
-struct spi_control {
-	unsigned short mode;
-};
-
-static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned short value)
-{
-	int ret;
-	u8 regs[3] = { LQ035_INDEX, 0, 0 };
-	u8 dat[3] = { LQ035_DATA, 0, 0 };
-
-	if (!spi)
-		return -ENODEV;
-
-	regs[2] = reg;
-	dat[1] = value >> 8;
-	dat[2] = value & 0xFF;
-
-	ret = spi_write(spi, regs, ARRAY_SIZE(regs));
-	ret |= spi_write(spi, dat, ARRAY_SIZE(dat));
-	return ret;
-}
-
-static int lq035q1_spidev_probe(struct spi_device *spi)
-{
-	int ret;
-	struct spi_control *ctl;
-	struct bfin_lq035q1fb_info *info = container_of(spi->dev.driver,
-						struct bfin_lq035q1fb_info,
-						spidrv.driver);
-
-	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
-
-	if (!ctl)
-		return -ENOMEM;
-
-	ctl->mode = (info->disp_info->mode &
-		LQ035_DRIVER_OUTPUT_MASK) | LQ035_DRIVER_OUTPUT_DEFAULT;
-
-	ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
-	ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
-	if (ret) {
-		kfree(ctl);
-		return ret;
-	}
-
-	spi_set_drvdata(spi, ctl);
-
-	return 0;
-}
-
-static int lq035q1_spidev_remove(struct spi_device *spi)
-{
-	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int lq035q1_spidev_suspend(struct device *dev)
-{
-	struct spi_device *spi = to_spi_device(dev);
-
-	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
-}
-
-static int lq035q1_spidev_resume(struct device *dev)
-{
-	struct spi_device *spi = to_spi_device(dev);
-	struct spi_control *ctl = spi_get_drvdata(spi);
-	int ret;
-
-	ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
-	if (ret)
-		return ret;
-
-	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
-}
-
-static SIMPLE_DEV_PM_OPS(lq035q1_spidev_pm_ops, lq035q1_spidev_suspend,
-	lq035q1_spidev_resume);
-#define LQ035Q1_SPIDEV_PM_OPS (&lq035q1_spidev_pm_ops)
-
-#else
-#define LQ035Q1_SPIDEV_PM_OPS NULL
-#endif
-
-/* Power down all displays on reboot, poweroff or halt */
-static void lq035q1_spidev_shutdown(struct spi_device *spi)
-{
-	lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
-}
-
-static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg)
-{
-	if (info->disp_info->use_bl)
-		gpio_set_value(info->disp_info->gpio_bl, arg);
-
-	return 0;
-}
-
-static int bfin_lq035q1_calc_timing(struct bfin_lq035q1fb_info *fbi)
-{
-	unsigned long clocks_per_pix, cpld_pipeline_delay_cor;
-
-	/*
-	 * Interface 16/18-bit TFT over an 8-bit wide PPI using a small
-	 * Programmable Logic Device (CPLD)
-	 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
-	 */
-
-	switch (fbi->disp_info->ppi_mode) {
-	case USE_RGB565_16_BIT_PPI:
-		fbi->lcd_bpp = 16;
-		clocks_per_pix = 1;
-		cpld_pipeline_delay_cor = 0;
-		break;
-	case USE_RGB565_8_BIT_PPI:
-		fbi->lcd_bpp = 16;
-		clocks_per_pix = 2;
-		cpld_pipeline_delay_cor = 3;
-		break;
-	case USE_RGB888_8_BIT_PPI:
-		fbi->lcd_bpp = 24;
-		clocks_per_pix = 3;
-		cpld_pipeline_delay_cor = 5;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * HS and VS timing parameters (all in number of PPI clk ticks)
-	 */
-
-	fbi->h_actpix = (LCD_X_RES * clocks_per_pix);	/* active horizontal pixel */
-	fbi->h_period = (336 * clocks_per_pix);		/* HS period */
-	fbi->h_pulse = (2 * clocks_per_pix);				/* HS pulse width */
-	fbi->h_start = (7 * clocks_per_pix + cpld_pipeline_delay_cor);	/* first valid pixel */
-
-	fbi->v_lines = (LCD_Y_RES + U_LINE);		/* total vertical lines */
-	fbi->v_pulse = (2 * clocks_per_pix);		/* VS pulse width (1-5 H_PERIODs) */
-	fbi->v_period =	(fbi->h_period * fbi->v_lines);	/* VS period */
-
-	return 0;
-}
-
-static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi)
-{
-	unsigned ppi_pmode;
-
-	if (fbi->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI)
-		ppi_pmode = DLEN_16;
-	else
-		ppi_pmode = (DLEN_8 | PACK_EN);
-
-	bfin_write_PPI_DELAY(fbi->h_start);
-	bfin_write_PPI_COUNT(fbi->h_actpix - 1);
-	bfin_write_PPI_FRAME(fbi->v_lines);
-
-	bfin_write_PPI_CONTROL(PPI_TX_MODE |	   /* output mode , PORT_DIR */
-				PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
-				PPI_PORT_CFG_01 |  /* two frame sync PORT_CFG */
-				ppi_pmode |	   /* 8/16 bit data length / PACK_EN? */
-				PPI_POLS_1);	   /* faling edge syncs POLS */
-}
-
-static inline void bfin_lq035q1_disable_ppi(void)
-{
-	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
-}
-
-static inline void bfin_lq035q1_enable_ppi(void)
-{
-	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
-}
-
-static void bfin_lq035q1_start_timers(void)
-{
-	enable_gptimers(TIMER_VSYNCbit | TIMER_HSYNCbit);
-}
-
-static void bfin_lq035q1_stop_timers(void)
-{
-	disable_gptimers(TIMER_HSYNCbit | TIMER_VSYNCbit);
-
-	set_gptimer_status(0, TIMER_HSYNC_STATUS_TRUN | TIMER_VSYNC_STATUS_TRUN |
-				TIMER_HSYNC_STATUS_TIMIL | TIMER_VSYNC_STATUS_TIMIL |
-				 TIMER_HSYNC_STATUS_TOVF | TIMER_VSYNC_STATUS_TOVF);
-
-}
-
-static void bfin_lq035q1_init_timers(struct bfin_lq035q1fb_info *fbi)
-{
-
-	bfin_lq035q1_stop_timers();
-
-	set_gptimer_period(TIMER_HSYNC_id, fbi->h_period);
-	set_gptimer_pwidth(TIMER_HSYNC_id, fbi->h_pulse);
-	set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
-				      TIMER_TIN_SEL | TIMER_CLK_SEL|
-				      TIMER_EMU_RUN);
-
-	set_gptimer_period(TIMER_VSYNC_id, fbi->v_period);
-	set_gptimer_pwidth(TIMER_VSYNC_id, fbi->v_pulse);
-	set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
-				      TIMER_TIN_SEL | TIMER_CLK_SEL |
-				      TIMER_EMU_RUN);
-
-}
-
-static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi)
-{
-
-
-	set_dma_config(CH_PPI,
-		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
-					   INTR_DISABLE, DIMENSION_2D,
-					   DATA_SIZE_16,
-					   DMA_NOSYNC_KEEP_DMA_BUF));
-	set_dma_x_count(CH_PPI, (LCD_X_RES * fbi->lcd_bpp) / DMA_BUS_SIZE);
-	set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
-	set_dma_y_count(CH_PPI, fbi->v_lines);
-
-	set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
-	set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
-
-}
-
-static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
-			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
-			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
-			    P_PPI0_D6, P_PPI0_D7, P_PPI0_D8,
-			    P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
-			    P_PPI0_D12, P_PPI0_D13, P_PPI0_D14,
-			    P_PPI0_D15, 0};
-
-static const u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
-			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
-			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
-			    P_PPI0_D6, P_PPI0_D7, 0};
-
-static inline void bfin_lq035q1_free_ports(unsigned ppi16)
-{
-	if (ppi16)
-		peripheral_free_list(ppi0_req_16);
-	else
-		peripheral_free_list(ppi0_req_8);
-
-	if (ANOMALY_05000400)
-		gpio_free(P_IDENT(P_PPI0_FS3));
-}
-
-static int bfin_lq035q1_request_ports(struct platform_device *pdev,
-				      unsigned ppi16)
-{
-	int ret;
-	/* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode:
-	 * Drive PPI_FS3 Low
-	 */
-	if (ANOMALY_05000400) {
-		int ret = gpio_request_one(P_IDENT(P_PPI0_FS3),
-					GPIOF_OUT_INIT_LOW, "PPI_FS3");
-		if (ret)
-			return ret;
-	}
-
-	if (ppi16)
-		ret = peripheral_request_list(ppi0_req_16, DRIVER_NAME);
-	else
-		ret = peripheral_request_list(ppi0_req_8, DRIVER_NAME);
-
-	if (ret) {
-		dev_err(&pdev->dev, "requesting peripherals failed\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int bfin_lq035q1_fb_open(struct fb_info *info, int user)
-{
-	struct bfin_lq035q1fb_info *fbi = info->par;
-
-	spin_lock(&fbi->lock);
-	fbi->lq035_open_cnt++;
-
-	if (fbi->lq035_open_cnt <= 1) {
-
-		bfin_lq035q1_disable_ppi();
-		SSYNC();
-
-		bfin_lq035q1_config_dma(fbi);
-		bfin_lq035q1_config_ppi(fbi);
-		bfin_lq035q1_init_timers(fbi);
-
-		/* start dma */
-		enable_dma(CH_PPI);
-		bfin_lq035q1_enable_ppi();
-		bfin_lq035q1_start_timers();
-		lq035q1_backlight(fbi, 1);
-	}
-
-	spin_unlock(&fbi->lock);
-
-	return 0;
-}
-
-static int bfin_lq035q1_fb_release(struct fb_info *info, int user)
-{
-	struct bfin_lq035q1fb_info *fbi = info->par;
-
-	spin_lock(&fbi->lock);
-
-	fbi->lq035_open_cnt--;
-
-	if (fbi->lq035_open_cnt <= 0) {
-		lq035q1_backlight(fbi, 0);
-		bfin_lq035q1_disable_ppi();
-		SSYNC();
-		disable_dma(CH_PPI);
-		bfin_lq035q1_stop_timers();
-	}
-
-	spin_unlock(&fbi->lock);
-
-	return 0;
-}
-
-static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var,
-				     struct fb_info *info)
-{
-	struct bfin_lq035q1fb_info *fbi = info->par;
-
-	if (var->bits_per_pixel == fbi->lcd_bpp) {
-		var->red.offset = info->var.red.offset;
-		var->green.offset = info->var.green.offset;
-		var->blue.offset = info->var.blue.offset;
-		var->red.length = info->var.red.length;
-		var->green.length = info->var.green.length;
-		var->blue.length = info->var.blue.length;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->transp.msb_right = 0;
-		var->red.msb_right = 0;
-		var->green.msb_right = 0;
-		var->blue.msb_right = 0;
-	} else {
-		pr_debug("%s: depth not supported: %u BPP\n", __func__,
-			 var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (info->var.xres != var->xres || info->var.yres != var->yres ||
-	    info->var.xres_virtual != var->xres_virtual ||
-	    info->var.yres_virtual != var->yres_virtual) {
-		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
-			 __func__, var->xres, var->yres);
-		return -EINVAL;
-	}
-
-	/*
-	 *  Memory limit
-	 */
-
-	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
-			 __func__, var->yres_virtual);
-		return -ENOMEM;
-	}
-
-
-	return 0;
-}
-
-int bfin_lq035q1_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	if (nocursor)
-		return 0;
-	else
-		return -EINVAL;	/* just to force soft_cursor() call */
-}
-
-static int bfin_lq035q1_fb_setcolreg(u_int regno, u_int red, u_int green,
-				   u_int blue, u_int transp,
-				   struct fb_info *info)
-{
-	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
-		return -EINVAL;
-
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-
-		u32 value;
-		/* Place color in the pseudopalette */
-		if (regno > 16)
-			return -EINVAL;
-
-		red >>= (16 - info->var.red.length);
-		green >>= (16 - info->var.green.length);
-		blue >>= (16 - info->var.blue.length);
-
-		value = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset);
-		value &= 0xFFFFFF;
-
-		((u32 *) (info->pseudo_palette))[regno] = value;
-
-	}
-
-	return 0;
-}
-
-static struct fb_ops bfin_lq035q1_fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = bfin_lq035q1_fb_open,
-	.fb_release = bfin_lq035q1_fb_release,
-	.fb_check_var = bfin_lq035q1_fb_check_var,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor = bfin_lq035q1_fb_cursor,
-	.fb_setcolreg = bfin_lq035q1_fb_setcolreg,
-};
-
-static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id)
-{
-	/*struct bfin_lq035q1fb_info *info = (struct bfin_lq035q1fb_info *)dev_id;*/
-
-	u16 status = bfin_read_PPI_STATUS();
-	bfin_write_PPI_STATUS(-1);
-
-	if (status) {
-		bfin_lq035q1_disable_ppi();
-		disable_dma(CH_PPI);
-
-		/* start dma */
-		enable_dma(CH_PPI);
-		bfin_lq035q1_enable_ppi();
-		bfin_write_PPI_STATUS(-1);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int bfin_lq035q1_probe(struct platform_device *pdev)
-{
-	struct bfin_lq035q1fb_info *info;
-	struct fb_info *fbinfo;
-	u32 active_video_mem_offset;
-	int ret;
-
-	ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI");
-	if (ret < 0) {
-		dev_err(&pdev->dev, "PPI DMA unavailable\n");
-		goto out1;
-	}
-
-	fbinfo = framebuffer_alloc(sizeof(*info), &pdev->dev);
-	if (!fbinfo) {
-		ret = -ENOMEM;
-		goto out2;
-	}
-
-	info = fbinfo->par;
-	info->fb = fbinfo;
-	info->dev = &pdev->dev;
-	spin_lock_init(&info->lock);
-
-	info->disp_info = pdev->dev.platform_data;
-
-	platform_set_drvdata(pdev, fbinfo);
-
-	ret = bfin_lq035q1_calc_timing(info);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed PPI Mode\n");
-		goto out3;
-	}
-
-	strcpy(fbinfo->fix.id, DRIVER_NAME);
-
-	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
-	fbinfo->fix.type_aux = 0;
-	fbinfo->fix.xpanstep = 0;
-	fbinfo->fix.ypanstep = 0;
-	fbinfo->fix.ywrapstep = 0;
-	fbinfo->fix.accel = FB_ACCEL_NONE;
-	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	fbinfo->var.nonstd = 0;
-	fbinfo->var.activate = FB_ACTIVATE_NOW;
-	fbinfo->var.height = -1;
-	fbinfo->var.width = -1;
-	fbinfo->var.accel_flags = 0;
-	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
-
-	fbinfo->var.xres = LCD_X_RES;
-	fbinfo->var.xres_virtual = LCD_X_RES;
-	fbinfo->var.yres = LCD_Y_RES;
-	fbinfo->var.yres_virtual = LCD_Y_RES;
-	fbinfo->var.bits_per_pixel = info->lcd_bpp;
-
-	if (info->disp_info->mode & LQ035_BGR) {
-		if (info->lcd_bpp == 24) {
-			fbinfo->var.red.offset = 0;
-			fbinfo->var.green.offset = 8;
-			fbinfo->var.blue.offset = 16;
-		} else {
-			fbinfo->var.red.offset = 0;
-			fbinfo->var.green.offset = 5;
-			fbinfo->var.blue.offset = 11;
-		}
-	} else {
-		if (info->lcd_bpp == 24) {
-			fbinfo->var.red.offset = 16;
-			fbinfo->var.green.offset = 8;
-			fbinfo->var.blue.offset = 0;
-		} else {
-			fbinfo->var.red.offset = 11;
-			fbinfo->var.green.offset = 5;
-			fbinfo->var.blue.offset = 0;
-		}
-	}
-
-	fbinfo->var.transp.offset = 0;
-
-	if (info->lcd_bpp == 24) {
-		fbinfo->var.red.length = 8;
-		fbinfo->var.green.length = 8;
-		fbinfo->var.blue.length = 8;
-	} else {
-		fbinfo->var.red.length = 5;
-		fbinfo->var.green.length = 6;
-		fbinfo->var.blue.length = 5;
-	}
-
-	fbinfo->var.transp.length = 0;
-
-	active_video_mem_offset = ((U_LINE / 2) * LCD_X_RES * (info->lcd_bpp / 8));
-
-	fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * info->lcd_bpp / 8
-				+ active_video_mem_offset;
-
-	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
-	    fbinfo->var.bits_per_pixel / 8;
-
-
-	fbinfo->fbops = &bfin_lq035q1_fb_ops;
-	fbinfo->flags = FBINFO_FLAG_DEFAULT;
-
-	info->fb_buffer =
-	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
-			       GFP_KERNEL);
-
-	if (NULL == info->fb_buffer) {
-		dev_err(&pdev->dev, "couldn't allocate dma buffer\n");
-		ret = -ENOMEM;
-		goto out3;
-	}
-
-	fbinfo->screen_base = (void *)info->fb_buffer + active_video_mem_offset;
-	fbinfo->fix.smem_start = (int)info->fb_buffer + active_video_mem_offset;
-
-	fbinfo->fbops = &bfin_lq035q1_fb_ops;
-
-	fbinfo->pseudo_palette = &info->pseudo_pal;
-
-	ret = fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to allocate colormap (%d entries)\n",
-		       BFIN_LCD_NBR_PALETTE_ENTRIES);
-		goto out4;
-	}
-
-	ret = bfin_lq035q1_request_ports(pdev,
-			info->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI);
-	if (ret) {
-		dev_err(&pdev->dev, "couldn't request gpio port\n");
-		goto out6;
-	}
-
-	info->irq = platform_get_irq(pdev, 0);
-	if (info->irq < 0) {
-		ret = -EINVAL;
-		goto out7;
-	}
-
-	ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0,
-			DRIVER_NAME" PPI ERROR", info);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");
-		goto out7;
-	}
-
-	info->spidrv.driver.name = DRIVER_NAME"-spi";
-	info->spidrv.probe    = lq035q1_spidev_probe;
-	info->spidrv.remove   = lq035q1_spidev_remove;
-	info->spidrv.shutdown = lq035q1_spidev_shutdown;
-	info->spidrv.driver.pm = LQ035Q1_SPIDEV_PM_OPS;
-
-	ret = spi_register_driver(&info->spidrv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "couldn't register SPI Interface\n");
-		goto out8;
-	}
-
-	if (info->disp_info->use_bl) {
-		ret = gpio_request_one(info->disp_info->gpio_bl,
-					GPIOF_OUT_INIT_LOW, "LQ035 Backlight");
-
-		if (ret) {
-			dev_err(&pdev->dev, "failed to request GPIO %d\n",
-				info->disp_info->gpio_bl);
-			goto out9;
-		}
-	}
-
-	ret = register_framebuffer(fbinfo);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "unable to register framebuffer\n");
-		goto out10;
-	}
-
-	dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n",
-		LCD_X_RES, LCD_Y_RES, info->lcd_bpp);
-
-	return 0;
-
- out10:
-	if (info->disp_info->use_bl)
-		gpio_free(info->disp_info->gpio_bl);
- out9:
-	spi_unregister_driver(&info->spidrv);
- out8:
-	free_irq(info->irq, info);
- out7:
-	bfin_lq035q1_free_ports(info->disp_info->ppi_mode ==
-				USE_RGB565_16_BIT_PPI);
- out6:
-	fb_dealloc_cmap(&fbinfo->cmap);
- out4:
-	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-			  info->dma_handle);
- out3:
-	framebuffer_release(fbinfo);
- out2:
-	free_dma(CH_PPI);
- out1:
-
-	return ret;
-}
-
-static int bfin_lq035q1_remove(struct platform_device *pdev)
-{
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct bfin_lq035q1fb_info *info = fbinfo->par;
-
-	if (info->disp_info->use_bl)
-		gpio_free(info->disp_info->gpio_bl);
-
-	spi_unregister_driver(&info->spidrv);
-
-	unregister_framebuffer(fbinfo);
-
-	free_dma(CH_PPI);
-	free_irq(info->irq, info);
-
-	if (info->fb_buffer != NULL)
-		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-				  info->dma_handle);
-
-	fb_dealloc_cmap(&fbinfo->cmap);
-
-	bfin_lq035q1_free_ports(info->disp_info->ppi_mode ==
-				USE_RGB565_16_BIT_PPI);
-
-	framebuffer_release(fbinfo);
-
-	dev_info(&pdev->dev, "unregistered LCD driver\n");
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_lq035q1_suspend(struct device *dev)
-{
-	struct fb_info *fbinfo = dev_get_drvdata(dev);
-	struct bfin_lq035q1fb_info *info = fbinfo->par;
-
-	if (info->lq035_open_cnt) {
-		lq035q1_backlight(info, 0);
-		bfin_lq035q1_disable_ppi();
-		SSYNC();
-		disable_dma(CH_PPI);
-		bfin_lq035q1_stop_timers();
-		bfin_write_PPI_STATUS(-1);
-	}
-
-	return 0;
-}
-
-static int bfin_lq035q1_resume(struct device *dev)
-{
-	struct fb_info *fbinfo = dev_get_drvdata(dev);
-	struct bfin_lq035q1fb_info *info = fbinfo->par;
-
-	if (info->lq035_open_cnt) {
-		bfin_lq035q1_disable_ppi();
-		SSYNC();
-
-		bfin_lq035q1_config_dma(info);
-		bfin_lq035q1_config_ppi(info);
-		bfin_lq035q1_init_timers(info);
-
-		/* start dma */
-		enable_dma(CH_PPI);
-		bfin_lq035q1_enable_ppi();
-		bfin_lq035q1_start_timers();
-		lq035q1_backlight(info, 1);
-	}
-
-	return 0;
-}
-
-static struct dev_pm_ops bfin_lq035q1_dev_pm_ops = {
-	.suspend = bfin_lq035q1_suspend,
-	.resume  = bfin_lq035q1_resume,
-};
-#endif
-
-static struct platform_driver bfin_lq035q1_driver = {
-	.probe   = bfin_lq035q1_probe,
-	.remove  = bfin_lq035q1_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm   = &bfin_lq035q1_dev_pm_ops,
-#endif
-	},
-};
-
-module_platform_driver(bfin_lq035q1_driver);
-
-MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
deleted file mode 100644
index b5cf1307a3d9..000000000000
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * File:         drivers/video/bfin-t350mcqb-fb.c
- * Based on:
- * Author:       Michael Hennerich <hennerich@blackfin.uclinux.org>
- *
- * Created:
- * Description:  Blackfin LCD Framebuffer driver
- *
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/gfp.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/backlight.h>
-#include <linux/lcd.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-
-#include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/dma-mapping.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-#include <asm/gptimers.h>
-
-#define NO_BL_SUPPORT
-
-#define LCD_X_RES		320	/* Horizontal Resolution */
-#define LCD_Y_RES		240	/* Vertical Resolution */
-#define LCD_BPP			24	/* Bit Per Pixel */
-
-#define	DMA_BUS_SIZE		16
-#define	LCD_CLK         	(12*1000*1000)	/* 12MHz */
-
-#define CLOCKS_PER_PIX		3
-
-	/*
-	 * HS and VS timing parameters (all in number of PPI clk ticks)
-	 */
-
-#define U_LINE		1				/* Blanking Lines */
-
-#define H_ACTPIX	(LCD_X_RES * CLOCKS_PER_PIX)	/* active horizontal pixel */
-#define H_PERIOD	(408 * CLOCKS_PER_PIX)		/* HS period */
-#define H_PULSE		90				/* HS pulse width */
-#define H_START		204				/* first valid pixel */
-
-#define	V_LINES		(LCD_Y_RES + U_LINE)		/* total vertical lines */
-#define V_PULSE		(3 * H_PERIOD)			/* VS pulse width (1-5 H_PERIODs) */
-#define V_PERIOD	(H_PERIOD * V_LINES)		/* VS period */
-
-#define ACTIVE_VIDEO_MEM_OFFSET	(U_LINE * H_ACTPIX)
-
-#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
-
-#define DRIVER_NAME "bfin-t350mcqb"
-static char driver_name[] = DRIVER_NAME;
-
-struct bfin_t350mcqbfb_info {
-	struct fb_info *fb;
-	struct device *dev;
-	unsigned char *fb_buffer;	/* RGB Buffer */
-	dma_addr_t dma_handle;
-	int lq043_open_cnt;
-	int irq;
-	spinlock_t lock;	/* lock */
-	u32 pseudo_pal[16];
-};
-
-static int nocursor;
-module_param(nocursor, int, 0644);
-MODULE_PARM_DESC(nocursor, "cursor enable/disable");
-
-#define PPI_TX_MODE		0x2
-#define PPI_XFER_TYPE_11	0xC
-#define PPI_PORT_CFG_01		0x10
-#define PPI_PACK_EN		0x80
-#define PPI_POLS_1		0x8000
-
-static void bfin_t350mcqb_config_ppi(struct bfin_t350mcqbfb_info *fbi)
-{
-	bfin_write_PPI_DELAY(H_START);
-	bfin_write_PPI_COUNT(H_ACTPIX-1);
-	bfin_write_PPI_FRAME(V_LINES);
-
-	bfin_write_PPI_CONTROL(PPI_TX_MODE |	   /* output mode , PORT_DIR */
-				PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
-				PPI_PORT_CFG_01 |  /* two frame sync PORT_CFG */
-				PPI_PACK_EN |	   /* packing enabled PACK_EN */
-				PPI_POLS_1);	   /* faling edge syncs POLS */
-}
-
-static inline void bfin_t350mcqb_disable_ppi(void)
-{
-	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
-}
-
-static inline void bfin_t350mcqb_enable_ppi(void)
-{
-	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
-}
-
-static void bfin_t350mcqb_start_timers(void)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-		enable_gptimers(TIMER1bit);
-		enable_gptimers(TIMER0bit);
-	local_irq_restore(flags);
-}
-
-static void bfin_t350mcqb_stop_timers(void)
-{
-	disable_gptimers(TIMER0bit | TIMER1bit);
-
-	set_gptimer_status(0, TIMER_STATUS_TRUN0 | TIMER_STATUS_TRUN1 |
-				TIMER_STATUS_TIMIL0 | TIMER_STATUS_TIMIL1 |
-				 TIMER_STATUS_TOVF0 | TIMER_STATUS_TOVF1);
-
-}
-
-static void bfin_t350mcqb_init_timers(void)
-{
-
-	bfin_t350mcqb_stop_timers();
-
-	set_gptimer_period(TIMER0_id, H_PERIOD);
-	set_gptimer_pwidth(TIMER0_id, H_PULSE);
-	set_gptimer_config(TIMER0_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
-				      TIMER_TIN_SEL | TIMER_CLK_SEL|
-				      TIMER_EMU_RUN);
-
-	set_gptimer_period(TIMER1_id, V_PERIOD);
-	set_gptimer_pwidth(TIMER1_id, V_PULSE);
-	set_gptimer_config(TIMER1_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
-				      TIMER_TIN_SEL | TIMER_CLK_SEL |
-				      TIMER_EMU_RUN);
-
-}
-
-static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi)
-{
-
-	set_dma_config(CH_PPI,
-		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
-					   INTR_DISABLE, DIMENSION_2D,
-					   DATA_SIZE_16,
-					   DMA_NOSYNC_KEEP_DMA_BUF));
-	set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
-	set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
-	set_dma_y_count(CH_PPI, V_LINES);
-
-	set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
-	set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
-
-}
-
-static	u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
-			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
-			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
-			    P_PPI0_D6, P_PPI0_D7, 0};
-
-static int bfin_t350mcqb_request_ports(int action)
-{
-	if (action) {
-		if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
-			printk(KERN_ERR "Requesting Peripherals failed\n");
-			return -EFAULT;
-		}
-	} else
-		peripheral_free_list(ppi0_req_8);
-
-	return 0;
-}
-
-static int bfin_t350mcqb_fb_open(struct fb_info *info, int user)
-{
-	struct bfin_t350mcqbfb_info *fbi = info->par;
-
-	spin_lock(&fbi->lock);
-	fbi->lq043_open_cnt++;
-
-	if (fbi->lq043_open_cnt <= 1) {
-
-		bfin_t350mcqb_disable_ppi();
-		SSYNC();
-
-		bfin_t350mcqb_config_dma(fbi);
-		bfin_t350mcqb_config_ppi(fbi);
-		bfin_t350mcqb_init_timers();
-
-		/* start dma */
-		enable_dma(CH_PPI);
-		bfin_t350mcqb_enable_ppi();
-		bfin_t350mcqb_start_timers();
-	}
-
-	spin_unlock(&fbi->lock);
-
-	return 0;
-}
-
-static int bfin_t350mcqb_fb_release(struct fb_info *info, int user)
-{
-	struct bfin_t350mcqbfb_info *fbi = info->par;
-
-	spin_lock(&fbi->lock);
-
-	fbi->lq043_open_cnt--;
-
-	if (fbi->lq043_open_cnt <= 0) {
-		bfin_t350mcqb_disable_ppi();
-		SSYNC();
-		disable_dma(CH_PPI);
-		bfin_t350mcqb_stop_timers();
-	}
-
-	spin_unlock(&fbi->lock);
-
-	return 0;
-}
-
-static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
-				   struct fb_info *info)
-{
-
-	switch (var->bits_per_pixel) {
-	case 24:/* TRUECOLOUR, 16m */
-		var->red.offset = 0;
-		var->green.offset = 8;
-		var->blue.offset = 16;
-		var->red.length = var->green.length = var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->transp.msb_right = 0;
-		var->red.msb_right = 0;
-		var->green.msb_right = 0;
-		var->blue.msb_right = 0;
-		break;
-	default:
-		pr_debug("%s: depth not supported: %u BPP\n", __func__,
-			 var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (info->var.xres != var->xres || info->var.yres != var->yres ||
-	    info->var.xres_virtual != var->xres_virtual ||
-	    info->var.yres_virtual != var->yres_virtual) {
-		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
-			 __func__, var->xres, var->yres);
-		return -EINVAL;
-	}
-
-	/*
-	 *  Memory limit
-	 */
-
-	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
-			 __func__, var->yres_virtual);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	if (nocursor)
-		return 0;
-	else
-		return -EINVAL;	/* just to force soft_cursor() call */
-}
-
-static int bfin_t350mcqb_fb_setcolreg(u_int regno, u_int red, u_int green,
-				   u_int blue, u_int transp,
-				   struct fb_info *info)
-{
-	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
-		return -EINVAL;
-
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-
-		u32 value;
-		/* Place color in the pseudopalette */
-		if (regno > 16)
-			return -EINVAL;
-
-		red >>= (16 - info->var.red.length);
-		green >>= (16 - info->var.green.length);
-		blue >>= (16 - info->var.blue.length);
-
-		value = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset);
-		value &= 0xFFFFFF;
-
-		((u32 *) (info->pseudo_palette))[regno] = value;
-
-	}
-
-	return 0;
-}
-
-static struct fb_ops bfin_t350mcqb_fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = bfin_t350mcqb_fb_open,
-	.fb_release = bfin_t350mcqb_fb_release,
-	.fb_check_var = bfin_t350mcqb_fb_check_var,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor = bfin_t350mcqb_fb_cursor,
-	.fb_setcolreg = bfin_t350mcqb_fb_setcolreg,
-};
-
-#ifndef NO_BL_SUPPORT
-static int bl_get_brightness(struct backlight_device *bd)
-{
-	return 0;
-}
-
-static const struct backlight_ops bfin_lq043fb_bl_ops = {
-	.get_brightness = bl_get_brightness,
-};
-
-static struct backlight_device *bl_dev;
-
-static int bfin_lcd_get_power(struct lcd_device *dev)
-{
-	return 0;
-}
-
-static int bfin_lcd_set_power(struct lcd_device *dev, int power)
-{
-	return 0;
-}
-
-static int bfin_lcd_get_contrast(struct lcd_device *dev)
-{
-	return 0;
-}
-
-static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
-{
-
-	return 0;
-}
-
-static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
-{
-	if (!fi || (fi == &bfin_t350mcqb_fb))
-		return 1;
-	return 0;
-}
-
-static struct lcd_ops bfin_lcd_ops = {
-	.get_power = bfin_lcd_get_power,
-	.set_power = bfin_lcd_set_power,
-	.get_contrast = bfin_lcd_get_contrast,
-	.set_contrast = bfin_lcd_set_contrast,
-	.check_fb = bfin_lcd_check_fb,
-};
-
-static struct lcd_device *lcd_dev;
-#endif
-
-static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
-{
-	/*struct bfin_t350mcqbfb_info *info = (struct bfin_t350mcqbfb_info *)dev_id;*/
-
-	u16 status = bfin_read_PPI_STATUS();
-	bfin_write_PPI_STATUS(0xFFFF);
-
-	if (status) {
-		bfin_t350mcqb_disable_ppi();
-		disable_dma(CH_PPI);
-
-		/* start dma */
-		enable_dma(CH_PPI);
-		bfin_t350mcqb_enable_ppi();
-		bfin_write_PPI_STATUS(0xFFFF);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int bfin_t350mcqb_probe(struct platform_device *pdev)
-{
-#ifndef NO_BL_SUPPORT
-	struct backlight_properties props;
-#endif
-	struct bfin_t350mcqbfb_info *info;
-	struct fb_info *fbinfo;
-	int ret;
-
-	printk(KERN_INFO DRIVER_NAME ": %dx%d %d-bit RGB FrameBuffer initializing...\n",
-					 LCD_X_RES, LCD_Y_RES, LCD_BPP);
-
-	if (request_dma(CH_PPI, "CH_PPI") < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": couldn't request CH_PPI DMA\n");
-		ret = -EFAULT;
-		goto out1;
-	}
-
-	fbinfo =
-	    framebuffer_alloc(sizeof(struct bfin_t350mcqbfb_info), &pdev->dev);
-	if (!fbinfo) {
-		ret = -ENOMEM;
-		goto out2;
-	}
-
-	info = fbinfo->par;
-	info->fb = fbinfo;
-	info->dev = &pdev->dev;
-	spin_lock_init(&info->lock);
-
-	platform_set_drvdata(pdev, fbinfo);
-
-	strcpy(fbinfo->fix.id, driver_name);
-
-	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
-	fbinfo->fix.type_aux = 0;
-	fbinfo->fix.xpanstep = 0;
-	fbinfo->fix.ypanstep = 0;
-	fbinfo->fix.ywrapstep = 0;
-	fbinfo->fix.accel = FB_ACCEL_NONE;
-	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	fbinfo->var.nonstd = 0;
-	fbinfo->var.activate = FB_ACTIVATE_NOW;
-	fbinfo->var.height = 53;
-	fbinfo->var.width = 70;
-	fbinfo->var.accel_flags = 0;
-	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
-
-	fbinfo->var.xres = LCD_X_RES;
-	fbinfo->var.xres_virtual = LCD_X_RES;
-	fbinfo->var.yres = LCD_Y_RES;
-	fbinfo->var.yres_virtual = LCD_Y_RES;
-	fbinfo->var.bits_per_pixel = LCD_BPP;
-
-	fbinfo->var.red.offset = 0;
-	fbinfo->var.green.offset = 8;
-	fbinfo->var.blue.offset = 16;
-	fbinfo->var.transp.offset = 0;
-	fbinfo->var.red.length = 8;
-	fbinfo->var.green.length = 8;
-	fbinfo->var.blue.length = 8;
-	fbinfo->var.transp.length = 0;
-	fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8;
-
-	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
-	    fbinfo->var.bits_per_pixel / 8;
-
-
-	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
-	fbinfo->flags = FBINFO_FLAG_DEFAULT;
-
-	info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len +
-				ACTIVE_VIDEO_MEM_OFFSET,
-				&info->dma_handle, GFP_KERNEL);
-
-	if (NULL == info->fb_buffer) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": couldn't allocate dma buffer.\n");
-		ret = -ENOMEM;
-		goto out3;
-	}
-
-	fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
-	fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
-
-	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
-
-	fbinfo->pseudo_palette = &info->pseudo_pal;
-
-	if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
-	    < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       "Fail to allocate colormap (%d entries)\n",
-		       BFIN_LCD_NBR_PALETTE_ENTRIES);
-		ret = -EFAULT;
-		goto out4;
-	}
-
-	if (bfin_t350mcqb_request_ports(1)) {
-		printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
-		ret = -EFAULT;
-		goto out6;
-	}
-
-	info->irq = platform_get_irq(pdev, 0);
-	if (info->irq < 0) {
-		ret = -EINVAL;
-		goto out7;
-	}
-
-	ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0,
-			"PPI ERROR", info);
-	if (ret < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": unable to request PPI ERROR IRQ\n");
-		goto out7;
-	}
-
-	if (register_framebuffer(fbinfo) < 0) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": unable to register framebuffer.\n");
-		ret = -EINVAL;
-		goto out8;
-	}
-#ifndef NO_BL_SUPPORT
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 255;
-	bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
-					   &bfin_lq043fb_bl_ops, &props);
-	if (IS_ERR(bl_dev)) {
-		printk(KERN_ERR DRIVER_NAME
-			": unable to register backlight.\n");
-		ret = -EINVAL;
-		unregister_framebuffer(fbinfo);
-		goto out8;
-	}
-
-	lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
-	lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
-#endif
-
-	return 0;
-
-out8:
-	free_irq(info->irq, info);
-out7:
-	bfin_t350mcqb_request_ports(0);
-out6:
-	fb_dealloc_cmap(&fbinfo->cmap);
-out4:
-	dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET,
-			 info->fb_buffer, info->dma_handle);
-out3:
-	framebuffer_release(fbinfo);
-out2:
-	free_dma(CH_PPI);
-out1:
-
-	return ret;
-}
-
-static int bfin_t350mcqb_remove(struct platform_device *pdev)
-{
-
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct bfin_t350mcqbfb_info *info = fbinfo->par;
-
-	unregister_framebuffer(fbinfo);
-
-	free_dma(CH_PPI);
-	free_irq(info->irq, info);
-
-	if (info->fb_buffer != NULL)
-		dma_free_coherent(NULL, fbinfo->fix.smem_len +
-			ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer,
-			info->dma_handle);
-
-	fb_dealloc_cmap(&fbinfo->cmap);
-
-#ifndef NO_BL_SUPPORT
-	lcd_device_unregister(lcd_dev);
-	backlight_device_unregister(bl_dev);
-#endif
-
-	bfin_t350mcqb_request_ports(0);
-
-	framebuffer_release(fbinfo);
-
-	printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
-
-	if (fbi->lq043_open_cnt) {
-		bfin_t350mcqb_disable_ppi();
-		disable_dma(CH_PPI);
-		bfin_t350mcqb_stop_timers();
-		bfin_write_PPI_STATUS(-1);
-	}
-
-
-	return 0;
-}
-
-static int bfin_t350mcqb_resume(struct platform_device *pdev)
-{
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
-
-	if (fbi->lq043_open_cnt) {
-		bfin_t350mcqb_config_dma(fbi);
-		bfin_t350mcqb_config_ppi(fbi);
-		bfin_t350mcqb_init_timers();
-
-		/* start dma */
-		enable_dma(CH_PPI);
-		bfin_t350mcqb_enable_ppi();
-		bfin_t350mcqb_start_timers();
-	}
-
-	return 0;
-}
-#else
-#define bfin_t350mcqb_suspend	NULL
-#define bfin_t350mcqb_resume	NULL
-#endif
-
-static struct platform_driver bfin_t350mcqb_driver = {
-	.probe = bfin_t350mcqb_probe,
-	.remove = bfin_t350mcqb_remove,
-	.suspend = bfin_t350mcqb_suspend,
-	.resume = bfin_t350mcqb_resume,
-	.driver = {
-		   .name = DRIVER_NAME,
-		   .owner = THIS_MODULE,
-		   },
-};
-module_platform_driver(bfin_t350mcqb_driver);
-
-MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
deleted file mode 100644
index a54f7f7d763b..000000000000
--- a/drivers/video/bfin_adv7393fb.c
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Frame buffer driver for ADV7393/2 video encoder
- *
- * Copyright 2006-2009 Analog Devices Inc.
- * Licensed under the GPL-2 or late.
- */
-
-/*
- * TODO: Remove Globals
- * TODO: Code Cleanup
- */
-
-#define pr_fmt(fmt) DRIVER_NAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <linux/uaccess.h>
-#include <linux/gpio.h>
-#include <asm/portmux.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/proc_fs.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-
-#include "bfin_adv7393fb.h"
-
-static int mode = VMODE;
-static int mem = VMEM;
-static int nocursor = 1;
-
-static const unsigned short ppi_pins[] = {
-	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
-	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
-	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
-	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
-	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
-	0
-};
-
-/*
- * card parameters
- */
-
-static struct bfin_adv7393_fb_par {
-	/* structure holding blackfin / adv7393 parameters when
-	   screen is blanked */
-	struct {
-		u8 Mode;	/* ntsc/pal/? */
-	} vga_state;
-	atomic_t ref_count;
-} bfin_par;
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo bfin_adv7393_fb_defined = {
-	.xres = 720,
-	.yres = 480,
-	.xres_virtual = 720,
-	.yres_virtual = 480,
-	.bits_per_pixel = 16,
-	.activate = FB_ACTIVATE_TEST,
-	.height = -1,
-	.width = -1,
-	.left_margin = 0,
-	.right_margin = 0,
-	.upper_margin = 0,
-	.lower_margin = 0,
-	.vmode = FB_VMODE_INTERLACED,
-	.red = {11, 5, 0},
-	.green = {5, 6, 0},
-	.blue = {0, 5, 0},
-	.transp = {0, 0, 0},
-};
-
-static struct fb_fix_screeninfo bfin_adv7393_fb_fix = {
-	.id = "BFIN ADV7393",
-	.smem_len = 720 * 480 * 2,
-	.type = FB_TYPE_PACKED_PIXELS,
-	.visual = FB_VISUAL_TRUECOLOR,
-	.xpanstep = 0,
-	.ypanstep = 0,
-	.line_length = 720 * 2,
-	.accel = FB_ACCEL_NONE
-};
-
-static struct fb_ops bfin_adv7393_fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = bfin_adv7393_fb_open,
-	.fb_release = bfin_adv7393_fb_release,
-	.fb_check_var = bfin_adv7393_fb_check_var,
-	.fb_pan_display = bfin_adv7393_fb_pan_display,
-	.fb_blank = bfin_adv7393_fb_blank,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor = bfin_adv7393_fb_cursor,
-	.fb_setcolreg = bfin_adv7393_fb_setcolreg,
-};
-
-static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg)
-{
-	if (arg == BUILD) {	/* Build */
-		fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg));
-		if (fbdev->vb1 == NULL)
-			goto error;
-
-		fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg));
-		if (fbdev->av1 == NULL)
-			goto error;
-
-		fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg));
-		if (fbdev->vb2 == NULL)
-			goto error;
-
-		fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg));
-		if (fbdev->av2 == NULL)
-			goto error;
-
-		/* Build linked DMA descriptor list */
-		fbdev->vb1->next_desc_addr = fbdev->av1;
-		fbdev->av1->next_desc_addr = fbdev->vb2;
-		fbdev->vb2->next_desc_addr = fbdev->av2;
-		fbdev->av2->next_desc_addr = fbdev->vb1;
-
-		/* Save list head */
-		fbdev->descriptor_list_head = fbdev->av2;
-
-		/* Vertical Blanking Field 1 */
-		fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE;
-		fbdev->vb1->cfg = DMA_CFG_VAL;
-
-		fbdev->vb1->x_count =
-		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
-
-		fbdev->vb1->x_modify = 0;
-		fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines;
-		fbdev->vb1->y_modify = 0;
-
-		/* Active Video Field 1 */
-
-		fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem;
-		fbdev->av1->cfg = DMA_CFG_VAL;
-		fbdev->av1->x_count =
-		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
-		fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8;
-		fbdev->av1->y_count = fbdev->modes[mode].a_lines;
-		fbdev->av1->y_modify =
-		    (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
-		     1) * (fbdev->modes[mode].bpp / 8);
-
-		/* Vertical Blanking Field 2 */
-
-		fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE;
-		fbdev->vb2->cfg = DMA_CFG_VAL;
-		fbdev->vb2->x_count =
-		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
-
-		fbdev->vb2->x_modify = 0;
-		fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines;
-		fbdev->vb2->y_modify = 0;
-
-		/* Active Video Field 2 */
-
-		fbdev->av2->start_addr =
-		    (unsigned long)fbdev->fb_mem + fbdev->line_len;
-
-		fbdev->av2->cfg = DMA_CFG_VAL;
-
-		fbdev->av2->x_count =
-		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
-
-		fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8);
-		fbdev->av2->y_count = fbdev->modes[mode].a_lines;
-
-		fbdev->av2->y_modify =
-		    (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
-		     1) * (fbdev->modes[mode].bpp / 8);
-
-		return 1;
-	}
-
-error:
-	l1_data_sram_free(fbdev->vb1);
-	l1_data_sram_free(fbdev->av1);
-	l1_data_sram_free(fbdev->vb2);
-	l1_data_sram_free(fbdev->av2);
-
-	return 0;
-}
-
-static int bfin_config_dma(struct adv7393fb_device *fbdev)
-{
-	BUG_ON(!(fbdev->fb_mem));
-
-	set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count);
-	set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify);
-	set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count);
-	set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify);
-	set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr);
-	set_dma_next_desc_addr(CH_PPI,
-			       fbdev->descriptor_list_head->next_desc_addr);
-	set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg);
-
-	return 1;
-}
-
-static void bfin_disable_dma(void)
-{
-	bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN);
-}
-
-static void bfin_config_ppi(struct adv7393fb_device *fbdev)
-{
-	if (ANOMALY_05000183) {
-		bfin_write_TIMER2_CONFIG(WDTH_CAP);
-		bfin_write_TIMER_ENABLE(TIMEN2);
-	}
-
-	bfin_write_PPI_CONTROL(0x381E);
-	bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines);
-	bfin_write_PPI_COUNT(fbdev->modes[mode].xres +
-			     fbdev->modes[mode].boeft_blank - 1);
-	bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1);
-}
-
-static void bfin_enable_ppi(void)
-{
-	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
-}
-
-static void bfin_disable_ppi(void)
-{
-	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
-}
-
-static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static inline int adv7393_read(struct i2c_client *client, u8 reg)
-{
-	return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int
-adv7393_write_block(struct i2c_client *client,
-		    const u8 *data, unsigned int len)
-{
-	int ret = -1;
-	u8 reg;
-
-	while (len >= 2) {
-		reg = *data++;
-		ret = adv7393_write(client, reg, *data++);
-		if (ret < 0)
-			break;
-		len -= 2;
-	}
-
-	return ret;
-}
-
-static int adv7393_mode(struct i2c_client *client, u16 mode)
-{
-	switch (mode) {
-	case POWER_ON:		/* ADV7393 Sleep mode OFF */
-		adv7393_write(client, 0x00, 0x1E);
-		break;
-	case POWER_DOWN:	/* ADV7393 Sleep mode ON */
-		adv7393_write(client, 0x00, 0x1F);
-		break;
-	case BLANK_OFF:		/* Pixel Data Valid */
-		adv7393_write(client, 0x82, 0xCB);
-		break;
-	case BLANK_ON:		/* Pixel Data Invalid */
-		adv7393_write(client, 0x82, 0x8B);
-		break;
-	default:
-		return -EINVAL;
-		break;
-	}
-	return 0;
-}
-
-static irqreturn_t ppi_irq_error(int irq, void *dev_id)
-{
-
-	struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id;
-
-	u16 status = bfin_read_PPI_STATUS();
-
-	pr_debug("%s: PPI Status = 0x%X\n", __func__, status);
-
-	if (status) {
-		bfin_disable_dma();	/* TODO: Check Sequence */
-		bfin_disable_ppi();
-		bfin_clear_PPI_STATUS();
-		bfin_config_dma(fbdev);
-		bfin_enable_ppi();
-	}
-
-	return IRQ_HANDLED;
-
-}
-
-static int proc_output(char *buf)
-{
-	char *p = buf;
-
-	p += sprintf(p,
-		"Usage:\n"
-		"echo 0x[REG][Value] > adv7393\n"
-		"example: echo 0x1234 >adv7393\n"
-		"writes 0x34 into Register 0x12\n");
-
-	return p - buf;
-}
-
-static ssize_t
-adv7393_read_proc(struct file *file, char __user *buf,
-		  size_t size, loff_t *ppos)
-{
-	static const char message[] = "Usage:\n"
-		"echo 0x[REG][Value] > adv7393\n"
-		"example: echo 0x1234 >adv7393\n"
-		"writes 0x34 into Register 0x12\n";
-	return simple_read_from_buffer(buf, size, ppos, message,
-					sizeof(message));
-}
-
-static ssize_t
-adv7393_write_proc(struct file *file, const char __user * buffer,
-		   size_t count, loff_t *ppos)
-{
-	struct adv7393fb_device *fbdev = PDE_DATA(file_inode(file));
-	unsigned int val;
-	int ret;
-
-	ret = kstrtouint_from_user(buffer, count, 0, &val);
-	if (ret)
-		return -EFAULT;
-
-	adv7393_write(fbdev->client, val >> 8, val & 0xff);
-
-	return count;
-}
-
-static const struct file_operations fops = {
-	.read = adv7393_read_proc,
-	.write = adv7393_write_proc,
-	.llseek = default_llseek,
-};
-
-static int bfin_adv7393_fb_probe(struct i2c_client *client,
-				 const struct i2c_device_id *id)
-{
-	int ret = 0;
-	struct proc_dir_entry *entry;
-	int num_modes = ARRAY_SIZE(known_modes);
-
-	struct adv7393fb_device *fbdev = NULL;
-
-	if (mem > 2) {
-		dev_err(&client->dev, "mem out of allowed range [1;2]\n");
-		return -EINVAL;
-	}
-
-	if (mode > num_modes) {
-		dev_err(&client->dev, "mode %d: not supported", mode);
-		return -EFAULT;
-	}
-
-	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
-	if (!fbdev) {
-		dev_err(&client->dev, "failed to allocate device private record");
-		return -ENOMEM;
-	}
-
-	i2c_set_clientdata(client, fbdev);
-
-	fbdev->modes = known_modes;
-	fbdev->client = client;
-
-	fbdev->fb_len =
-	    mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres *
-	    (fbdev->modes[mode].bpp / 8);
-
-	fbdev->line_len =
-	    fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8);
-
-	/* Workaround "PPI Does Not Start Properly In Specific Mode" */
-	if (ANOMALY_05000400) {
-		ret = gpio_request_one(P_IDENT(P_PPI0_FS3), GPIOF_OUT_INIT_LOW,
-					"PPI0_FS3")
-		if (ret) {
-			dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
-			ret = -EBUSY;
-			goto free_fbdev;
-		}
-	}
-
-	if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
-		dev_err(&client->dev, "requesting PPI peripheral failed\n");
-		ret = -EFAULT;
-		goto free_gpio;
-	}
-
-	fbdev->fb_mem =
-	    dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle,
-			       GFP_KERNEL);
-
-	if (NULL == fbdev->fb_mem) {
-		dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n",
-		       (u32) fbdev->fb_len);
-		ret = -ENOMEM;
-		goto free_ppi_pins;
-	}
-
-	fbdev->info.screen_base = (void *)fbdev->fb_mem;
-	bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem;
-
-	bfin_adv7393_fb_fix.smem_len = fbdev->fb_len;
-	bfin_adv7393_fb_fix.line_length = fbdev->line_len;
-
-	if (mem > 1)
-		bfin_adv7393_fb_fix.ypanstep = 1;
-
-	bfin_adv7393_fb_defined.red.length = 5;
-	bfin_adv7393_fb_defined.green.length = 6;
-	bfin_adv7393_fb_defined.blue.length = 5;
-
-	bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres;
-	bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres;
-	bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres;
-	bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres;
-	bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp;
-
-	fbdev->info.fbops = &bfin_adv7393_fb_ops;
-	fbdev->info.var = bfin_adv7393_fb_defined;
-	fbdev->info.fix = bfin_adv7393_fb_fix;
-	fbdev->info.par = &bfin_par;
-	fbdev->info.flags = FBINFO_DEFAULT;
-
-	fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
-	if (!fbdev->info.pseudo_palette) {
-		dev_err(&client->dev, "failed to allocate pseudo_palette\n");
-		ret = -ENOMEM;
-		goto free_fb_mem;
-	}
-
-	if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
-		dev_err(&client->dev, "failed to allocate colormap (%d entries)\n",
-			   BFIN_LCD_NBR_PALETTE_ENTRIES);
-		ret = -EFAULT;
-		goto free_palette;
-	}
-
-	if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) {
-		dev_err(&client->dev, "unable to request PPI DMA\n");
-		ret = -EFAULT;
-		goto free_cmap;
-	}
-
-	if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0,
-			"PPI ERROR", fbdev) < 0) {
-		dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
-		ret = -EFAULT;
-		goto free_ch_ppi;
-	}
-
-	fbdev->open = 0;
-
-	ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd,
-				fbdev->modes[mode].adv7393_i2c_initd_len);
-
-	if (ret) {
-		dev_err(&client->dev, "i2c attach: init error\n");
-		goto free_irq_ppi;
-	}
-
-
-	if (register_framebuffer(&fbdev->info) < 0) {
-		dev_err(&client->dev, "unable to register framebuffer\n");
-		ret = -EFAULT;
-		goto free_irq_ppi;
-	}
-
-	dev_info(&client->dev, "fb%d: %s frame buffer device\n",
-	       fbdev->info.node, fbdev->info.fix.id);
-	dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
-
-	entry = proc_create_data("driver/adv7393", 0, NULL, &fops, fbdev);
-	if (!entry) {
-		dev_err(&client->dev, "unable to create /proc entry\n");
-		ret = -EFAULT;
-		goto free_fb;
-	}
-	return 0;
-
-free_fb:
-	unregister_framebuffer(&fbdev->info);
-free_irq_ppi:
-	free_irq(IRQ_PPI_ERROR, fbdev);
-free_ch_ppi:
-	free_dma(CH_PPI);
-free_cmap:
-	fb_dealloc_cmap(&fbdev->info.cmap);
-free_palette:
-	kfree(fbdev->info.pseudo_palette);
-free_fb_mem:
-	dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem,
-			  fbdev->dma_handle);
-free_ppi_pins:
-	peripheral_free_list(ppi_pins);
-free_gpio:
-	if (ANOMALY_05000400)
-		gpio_free(P_IDENT(P_PPI0_FS3));
-free_fbdev:
-	kfree(fbdev);
-
-	return ret;
-}
-
-static int bfin_adv7393_fb_open(struct fb_info *info, int user)
-{
-	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
-
-	fbdev->info.screen_base = (void *)fbdev->fb_mem;
-	if (!fbdev->info.screen_base) {
-		dev_err(&fbdev->client->dev, "unable to map device\n");
-		return -ENOMEM;
-	}
-
-	fbdev->open = 1;
-	dma_desc_list(fbdev, BUILD);
-	adv7393_mode(fbdev->client, BLANK_OFF);
-	bfin_config_ppi(fbdev);
-	bfin_config_dma(fbdev);
-	bfin_enable_ppi();
-
-	return 0;
-}
-
-static int bfin_adv7393_fb_release(struct fb_info *info, int user)
-{
-	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
-
-	adv7393_mode(fbdev->client, BLANK_ON);
-	bfin_disable_dma();
-	bfin_disable_ppi();
-	dma_desc_list(fbdev, DESTRUCT);
-	fbdev->open = 0;
-	return 0;
-}
-
-static int
-bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-
-	switch (var->bits_per_pixel) {
-	case 16:/* DIRECTCOLOUR, 64k */
-		var->red.offset = info->var.red.offset;
-		var->green.offset = info->var.green.offset;
-		var->blue.offset = info->var.blue.offset;
-		var->red.length = info->var.red.length;
-		var->green.length = info->var.green.length;
-		var->blue.length = info->var.blue.length;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->transp.msb_right = 0;
-		var->red.msb_right = 0;
-		var->green.msb_right = 0;
-		var->blue.msb_right = 0;
-		break;
-	default:
-		pr_debug("%s: depth not supported: %u BPP\n", __func__,
-			 var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (info->var.xres != var->xres ||
-	    info->var.yres != var->yres ||
-	    info->var.xres_virtual != var->xres_virtual ||
-	    info->var.yres_virtual != var->yres_virtual) {
-		pr_debug("%s: Resolution not supported: X%u x Y%u\n",
-			 __func__, var->xres, var->yres);
-		return -EINVAL;
-	}
-
-	/*
-	 *  Memory limit
-	 */
-
-	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
-		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
-			 __func__, var->yres_virtual);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static int
-bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int dy;
-	u32 dmaaddr;
-	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
-
-	if (!var || !info)
-		return -EINVAL;
-
-	if (var->xoffset - info->var.xoffset) {
-		/* No support for X panning for now! */
-		return -EINVAL;
-	}
-	dy = var->yoffset - info->var.yoffset;
-
-	if (dy) {
-		pr_debug("%s: Panning screen of %d lines\n", __func__, dy);
-
-		dmaaddr = fbdev->av1->start_addr;
-		dmaaddr += (info->fix.line_length * dy);
-		/* TODO: Wait for current frame to finished */
-
-		fbdev->av1->start_addr = (unsigned long)dmaaddr;
-		fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len;
-	}
-
-	return 0;
-
-}
-
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-static int bfin_adv7393_fb_blank(int blank, struct fb_info *info)
-{
-	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
-
-	switch (blank) {
-
-	case VESA_NO_BLANKING:
-		/* Turn on panel */
-		adv7393_mode(fbdev->client, BLANK_OFF);
-		break;
-
-	case VESA_VSYNC_SUSPEND:
-	case VESA_HSYNC_SUSPEND:
-	case VESA_POWERDOWN:
-		/* Turn off panel */
-		adv7393_mode(fbdev->client, BLANK_ON);
-		break;
-
-	default:
-		return -EINVAL;
-		break;
-	}
-	return 0;
-}
-
-int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	if (nocursor)
-		return 0;
-	else
-		return -EINVAL;	/* just to force soft_cursor() call */
-}
-
-static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green,
-				     u_int blue, u_int transp,
-				     struct fb_info *info)
-{
-	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
-		return -EINVAL;
-
-	if (info->var.grayscale)
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 value;
-		/* Place color in the pseudopalette */
-		if (regno > 16)
-			return -EINVAL;
-
-		red   >>= (16 - info->var.red.length);
-		green >>= (16 - info->var.green.length);
-		blue  >>= (16 - info->var.blue.length);
-
-		value = (red   << info->var.red.offset) |
-			(green << info->var.green.offset)|
-			(blue  << info->var.blue.offset);
-		value &= 0xFFFF;
-
-		((u32 *) (info->pseudo_palette))[regno] = value;
-	}
-
-	return 0;
-}
-
-static int bfin_adv7393_fb_remove(struct i2c_client *client)
-{
-	struct adv7393fb_device *fbdev = i2c_get_clientdata(client);
-
-	adv7393_mode(client, POWER_DOWN);
-
-	if (fbdev->fb_mem)
-		dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle);
-	free_dma(CH_PPI);
-	free_irq(IRQ_PPI_ERROR, fbdev);
-	unregister_framebuffer(&fbdev->info);
-	remove_proc_entry("driver/adv7393", NULL);
-	fb_dealloc_cmap(&fbdev->info.cmap);
-	kfree(fbdev->info.pseudo_palette);
-
-	if (ANOMALY_05000400)
-		gpio_free(P_IDENT(P_PPI0_FS3));	/* FS3 */
-	peripheral_free_list(ppi_pins);
-	kfree(fbdev);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_adv7393_fb_suspend(struct device *dev)
-{
-	struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
-
-	if (fbdev->open) {
-		bfin_disable_dma();
-		bfin_disable_ppi();
-		dma_desc_list(fbdev, DESTRUCT);
-	}
-	adv7393_mode(fbdev->client, POWER_DOWN);
-
-	return 0;
-}
-
-static int bfin_adv7393_fb_resume(struct device *dev)
-{
-	struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
-
-	adv7393_mode(fbdev->client, POWER_ON);
-
-	if (fbdev->open) {
-		dma_desc_list(fbdev, BUILD);
-		bfin_config_ppi(fbdev);
-		bfin_config_dma(fbdev);
-		bfin_enable_ppi();
-	}
-
-	return 0;
-}
-
-static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = {
-	.suspend = bfin_adv7393_fb_suspend,
-	.resume  = bfin_adv7393_fb_resume,
-};
-#endif
-
-static const struct i2c_device_id bfin_adv7393_id[] = {
-	{DRIVER_NAME, 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id);
-
-static struct i2c_driver bfin_adv7393_fb_driver = {
-	.driver = {
-		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm   = &bfin_adv7393_dev_pm_ops,
-#endif
-	},
-	.probe = bfin_adv7393_fb_probe,
-	.remove = bfin_adv7393_fb_remove,
-	.id_table = bfin_adv7393_id,
-};
-
-static int __init bfin_adv7393_fb_driver_init(void)
-{
-#if  defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
-	request_module("i2c-bfin-twi");
-#else
-	request_module("i2c-gpio");
-#endif
-
-	return i2c_add_driver(&bfin_adv7393_fb_driver);
-}
-module_init(bfin_adv7393_fb_driver_init);
-
-static void __exit bfin_adv7393_fb_driver_cleanup(void)
-{
-	i2c_del_driver(&bfin_adv7393_fb_driver);
-}
-module_exit(bfin_adv7393_fb_driver_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder");
-
-module_param(mode, int, 0);
-MODULE_PARM_DESC(mode,
-	"Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)");
-
-module_param(mem, int, 0);
-MODULE_PARM_DESC(mem,
-	"Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)");
-
-module_param(nocursor, int, 0644);
-MODULE_PARM_DESC(nocursor, "cursor enable/disable");
diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/bfin_adv7393fb.h
deleted file mode 100644
index cd591b5152a5..000000000000
--- a/drivers/video/bfin_adv7393fb.h
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Frame buffer driver for ADV7393/2 video encoder
- *
- * Copyright 2006-2009 Analog Devices Inc.
- * Licensed under the GPL-2 or late.
- */
-
-#ifndef __BFIN_ADV7393FB_H__
-#define __BFIN_ADV7393FB_H__
-
-#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
-
-#ifdef CONFIG_NTSC
-# define VMODE 0
-#endif
-#ifdef CONFIG_PAL
-# define VMODE 1
-#endif
-#ifdef CONFIG_NTSC_640x480
-# define VMODE 2
-#endif
-#ifdef CONFIG_PAL_640x480
-# define VMODE 3
-#endif
-#ifdef CONFIG_NTSC_YCBCR
-# define VMODE 4
-#endif
-#ifdef CONFIG_PAL_YCBCR
-# define VMODE 5
-#endif
-
-#ifndef VMODE
-# define VMODE 1
-#endif
-
-#ifdef CONFIG_ADV7393_2XMEM
-# define VMEM 2
-#else
-# define VMEM 1
-#endif
-
-#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
-# define DMA_CFG_VAL	0x7935	/* Set Sync Bit */
-# define VB_DUMMY_MEMORY_SOURCE	L1_DATA_B_START
-#else
-# define DMA_CFG_VAL	0x7915
-# define VB_DUMMY_MEMORY_SOURCE	BOOT_ROM_START
-#endif
-
-enum {
-	DESTRUCT,
-	BUILD,
-};
-
-enum {
-	POWER_ON,
-	POWER_DOWN,
-	BLANK_ON,
-	BLANK_OFF,
-};
-
-#define DRIVER_NAME "bfin-adv7393"
-
-struct adv7393fb_modes {
-	const s8 name[25];	/* Full name */
-	u16 xres;		/* Active Horizonzal Pixels  */
-	u16 yres;		/* Active Vertical Pixels  */
-	u16 bpp;
-	u16 vmode;
-	u16 a_lines;		/* Active Lines per Field */
-	u16 vb1_lines;		/* Vertical Blanking Field 1 Lines */
-	u16 vb2_lines;		/* Vertical Blanking Field 2 Lines */
-	u16 tot_lines;		/* Total Lines per Frame */
-	u16 boeft_blank;	/* Before Odd/Even Field Transition No. of Blank Pixels */
-	u16 aoeft_blank;	/* After Odd/Even Field Transition No. of Blank Pixels */
-	const s8 *adv7393_i2c_initd;
-	u16 adv7393_i2c_initd_len;
-};
-
-static const u8 init_NTSC_TESTPATTERN[] = {
-	0x00, 0x1E,	/* Power up all DACs and PLL */
-	0x01, 0x00,	/* SD-Only Mode */
-	0x80, 0x10,	/* SSAF Luma Filter Enabled, NTSC Mode */
-	0x82, 0xCB,	/* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */
-	0x84, 0x40,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
-};
-
-static const u8 init_NTSC[] = {
-	0x00, 0x1E,	/* Power up all DACs and PLL */
-	0xC3, 0x26,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xC5, 0x12,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xBD, 0x19,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xBF, 0x42,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
-	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
-	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
-	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
-	0x01, 0x00,	/* SD-Only Mode */
-	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
-	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
-	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
-	0x86, 0x82,
-	0x8B, 0x11,
-	0x88, 0x20,
-	0x8A, 0x0d,
-};
-
-static const u8 init_PAL[] = {
-	0x00, 0x1E,	/* Power up all DACs and PLL */
-	0xC3, 0x26,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xC5, 0x12,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xBD, 0x19,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0xBF, 0x42,	/* Program RGB->YCrCb Color Space conversion matrix */
-	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
-	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
-	0x8E, 0x09,	/* PAL Subcarrier Frequency */
-	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
-	0x01, 0x00,	/* SD-Only Mode */
-	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
-	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
-	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
-	0x86, 0x82,
-	0x8B, 0x11,
-	0x88, 0x20,
-	0x8A, 0x0d,
-};
-
-static const u8 init_NTSC_YCbCr[] = {
-	0x00, 0x1E,	/* Power up all DACs and PLL */
-	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
-	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
-	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
-	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
-	0x01, 0x00,	/* SD-Only Mode */
-	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
-	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
-	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
-	0x86, 0x82,
-	0x8B, 0x11,
-	0x88, 0x08,
-	0x8A, 0x0d,
-};
-
-static const u8 init_PAL_YCbCr[] = {
-	0x00, 0x1E,	/* Power up all DACs and PLL */
-	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
-	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
-	0x8E, 0x09,	/* PAL Subcarrier Frequency */
-	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
-	0x01, 0x00,	/* SD-Only Mode */
-	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
-	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
-	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
-	0x86, 0x82,
-	0x8B, 0x11,
-	0x88, 0x08,
-	0x8A, 0x0d,
-};
-
-static struct adv7393fb_modes known_modes[] = {
-	/* NTSC 720x480 CRT */
-	{
-		.name = "NTSC 720x480",
-		.xres = 720,
-		.yres = 480,
-		.bpp = 16,
-		.vmode = FB_VMODE_INTERLACED,
-		.a_lines = 240,
-		.vb1_lines = 22,
-		.vb2_lines = 23,
-		.tot_lines = 525,
-		.boeft_blank = 16,
-		.aoeft_blank = 122,
-		.adv7393_i2c_initd = init_NTSC,
-		.adv7393_i2c_initd_len = sizeof(init_NTSC)
-	},
-	/* PAL 720x480 CRT */
-	{
-		.name = "PAL 720x576",
-		.xres = 720,
-		.yres = 576,
-		.bpp = 16,
-		.vmode = FB_VMODE_INTERLACED,
-		.a_lines = 288,
-		.vb1_lines = 24,
-		.vb2_lines = 25,
-		.tot_lines = 625,
-		.boeft_blank = 12,
-		.aoeft_blank = 132,
-		.adv7393_i2c_initd = init_PAL,
-		.adv7393_i2c_initd_len = sizeof(init_PAL)
-	},
-	/* NTSC 640x480 CRT Experimental */
-	{
-		.name = "NTSC 640x480",
-		.xres = 640,
-		.yres = 480,
-		.bpp = 16,
-		.vmode = FB_VMODE_INTERLACED,
-		.a_lines = 240,
-		.vb1_lines = 22,
-		.vb2_lines = 23,
-		.tot_lines = 525,
-		.boeft_blank = 16 + 40,
-		.aoeft_blank = 122 + 40,
-		.adv7393_i2c_initd = init_NTSC,
-		.adv7393_i2c_initd_len = sizeof(init_NTSC)
-	},
-	/* PAL 640x480 CRT Experimental */
-	{
-		.name = "PAL 640x480",
-		.xres = 640,
-		.yres = 480,
-		.bpp = 16,
-		.vmode = FB_VMODE_INTERLACED,
-		.a_lines = 288 - 20,
-		.vb1_lines = 24 + 20,
-		.vb2_lines = 25 + 20,
-		.tot_lines = 625,
-		.boeft_blank = 12 + 40,
-		.aoeft_blank = 132 + 40,
-		.adv7393_i2c_initd = init_PAL,
-		.adv7393_i2c_initd_len = sizeof(init_PAL)
-	},
-	/* NTSC 720x480 YCbCR */
-	{
-		.name = "NTSC 720x480 YCbCR",
-		.xres = 720,
-		.yres = 480,
-		.bpp = 16,
-		.vmode = FB_VMODE_INTERLACED,
-		.a_lines = 240,
-		.vb1_lines = 22,
-		.vb2_lines = 23,
-		.tot_lines = 525,
-		.boeft_blank = 16,
-		.aoeft_blank = 122,
-		.adv7393_i2c_initd = init_NTSC_YCbCr,
-		.adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr)
-	},
-	/* PAL 720x480 CRT */
-	{
-		.name = "PAL 720x576 YCbCR",
-		.xres = 720,
-		.yres = 576,
-		.bpp = 16,
-		.vmode = FB_VMODE_INTERLACED,
-		.a_lines = 288,
-		.vb1_lines = 24,
-		.vb2_lines = 25,
-		.tot_lines = 625,
-		.boeft_blank = 12,
-		.aoeft_blank = 132,
-		.adv7393_i2c_initd = init_PAL_YCbCr,
-		.adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr)
-	}
-};
-
-struct adv7393fb_regs {
-
-};
-
-struct adv7393fb_device {
-	struct fb_info info;	/* FB driver info record */
-
-	struct i2c_client *client;
-
-	struct dmasg *descriptor_list_head;
-	struct dmasg *vb1;
-	struct dmasg *av1;
-	struct dmasg *vb2;
-	struct dmasg *av2;
-
-	dma_addr_t dma_handle;
-
-	struct fb_info bfin_adv7393_fb;
-
-	struct adv7393fb_modes *modes;
-
-	struct adv7393fb_regs *regs;	/* Registers memory map */
-	size_t regs_len;
-	size_t fb_len;
-	size_t line_len;
-	u16 open;
-	u16 *fb_mem;		/* RGB Buffer */
-
-};
-
-#define to_adv7393fb_device(_info) \
-	  (_info ? container_of(_info, struct adv7393fb_device, info) : NULL);
-
-static int bfin_adv7393_fb_open(struct fb_info *info, int user);
-static int bfin_adv7393_fb_release(struct fb_info *info, int user);
-static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var,
-				     struct fb_info *info);
-
-static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var,
-				       struct fb_info *info);
-
-static int bfin_adv7393_fb_blank(int blank, struct fb_info *info);
-
-static void bfin_config_ppi(struct adv7393fb_device *fbdev);
-static int bfin_config_dma(struct adv7393fb_device *fbdev);
-static void bfin_disable_dma(void);
-static void bfin_enable_ppi(void);
-static void bfin_disable_ppi(void);
-
-static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value);
-static inline int adv7393_read(struct i2c_client *client, u8 reg);
-static int adv7393_write_block(struct i2c_client *client, const u8 *data,
-			       unsigned int len);
-
-int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int,
-				     u_int, struct fb_info *info);
-
-#endif
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c
deleted file mode 100644
index 8556264b16b7..000000000000
--- a/drivers/video/broadsheetfb.c
+++ /dev/null
@@ -1,1223 +0,0 @@
-/*
- * broadsheetfb.c -- FB driver for E-Ink Broadsheet controller
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This driver is written to be used with the Broadsheet display controller.
- *
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/firmware.h>
-#include <linux/uaccess.h>
-
-#include <video/broadsheetfb.h>
-
-/* track panel specific parameters */
-struct panel_info {
-	int w;
-	int h;
-	u16 sdcfg;
-	u16 gdcfg;
-	u16 lutfmt;
-	u16 fsynclen;
-	u16 fendfbegin;
-	u16 lsynclen;
-	u16 lendlbegin;
-	u16 pixclk;
-};
-
-/* table of panel specific parameters to be indexed into by the board drivers */
-static struct panel_info panel_table[] = {
-	{	/* standard 6" on TFT backplane */
-		.w = 800,
-		.h = 600,
-		.sdcfg = (100 | (1 << 8) | (1 << 9)),
-		.gdcfg = 2,
-		.lutfmt = (4 | (1 << 7)),
-		.fsynclen = 4,
-		.fendfbegin = (10 << 8) | 4,
-		.lsynclen = 10,
-		.lendlbegin = (100 << 8) | 4,
-		.pixclk = 6,
-	},
-	{	/* custom 3.7" flexible on PET or steel */
-		.w = 320,
-		.h = 240,
-		.sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
-		.gdcfg = 3,
-		.lutfmt = (4 | (1 << 7)),
-		.fsynclen = 0,
-		.fendfbegin = (80 << 8) | 4,
-		.lsynclen = 10,
-		.lendlbegin = (80 << 8) | 20,
-		.pixclk = 14,
-	},
-	{	/* standard 9.7" on TFT backplane */
-		.w = 1200,
-		.h = 825,
-		.sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
-		.gdcfg = 2,
-		.lutfmt = (4 | (1 << 7)),
-		.fsynclen = 0,
-		.fendfbegin = (4 << 8) | 4,
-		.lsynclen = 4,
-		.lendlbegin = (60 << 8) | 10,
-		.pixclk = 3,
-	},
-};
-
-#define DPY_W 800
-#define DPY_H 600
-
-static struct fb_fix_screeninfo broadsheetfb_fix = {
-	.id =		"broadsheetfb",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_STATIC_PSEUDOCOLOR,
-	.xpanstep =	0,
-	.ypanstep =	0,
-	.ywrapstep =	0,
-	.line_length =	DPY_W,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo broadsheetfb_var = {
-	.xres		= DPY_W,
-	.yres		= DPY_H,
-	.xres_virtual	= DPY_W,
-	.yres_virtual	= DPY_H,
-	.bits_per_pixel	= 8,
-	.grayscale	= 1,
-	.red =		{ 0, 4, 0 },
-	.green =	{ 0, 4, 0 },
-	.blue =		{ 0, 4, 0 },
-	.transp =	{ 0, 0, 0 },
-};
-
-/* main broadsheetfb functions */
-static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
-{
-	par->board->set_ctl(par, BS_WR, 0);
-	par->board->set_hdb(par, data);
-	par->board->set_ctl(par, BS_WR, 1);
-}
-
-static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
-{
-	par->board->set_ctl(par, BS_DC, 0);
-	broadsheet_gpio_issue_data(par, data);
-}
-
-static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
-{
-	par->board->wait_for_rdy(par);
-
-	par->board->set_ctl(par, BS_CS, 0);
-	broadsheet_gpio_issue_cmd(par, data);
-	par->board->set_ctl(par, BS_DC, 1);
-	par->board->set_ctl(par, BS_CS, 1);
-}
-
-static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
-					int argc, u16 *argv)
-{
-	int i;
-
-	par->board->wait_for_rdy(par);
-
-	par->board->set_ctl(par, BS_CS, 0);
-	broadsheet_gpio_issue_cmd(par, cmd);
-	par->board->set_ctl(par, BS_DC, 1);
-
-	for (i = 0; i < argc; i++)
-		broadsheet_gpio_issue_data(par, argv[i]);
-	par->board->set_ctl(par, BS_CS, 1);
-}
-
-static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
-				    int argc, u16 *argv)
-{
-	int i;
-
-	par->board->mmio_write(par, BS_MMIO_CMD, cmd);
-
-	for (i = 0; i < argc; i++)
-		par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
-}
-
-static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
-{
-	if (par->board->mmio_write)
-		par->board->mmio_write(par, BS_MMIO_CMD, data);
-	else
-		broadsheet_gpio_send_command(par, data);
-}
-
-static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
-				    int argc, u16 *argv)
-{
-	if (par->board->mmio_write)
-		broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
-	else
-		broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
-}
-
-static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
-					u16 *data)
-{
-	int i;
-	u16 tmp;
-
-	par->board->set_ctl(par, BS_CS, 0);
-	par->board->set_ctl(par, BS_DC, 1);
-
-	for (i = 0; i < size; i++) {
-		par->board->set_ctl(par, BS_WR, 0);
-		tmp = (data[i] & 0x0F) << 4;
-		tmp |= (data[i] & 0x0F00) << 4;
-		par->board->set_hdb(par, tmp);
-		par->board->set_ctl(par, BS_WR, 1);
-	}
-
-	par->board->set_ctl(par, BS_CS, 1);
-}
-
-static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
-				   u16 *data)
-{
-	int i;
-	u16 tmp;
-
-	for (i = 0; i < size; i++) {
-		tmp = (data[i] & 0x0F) << 4;
-		tmp |= (data[i] & 0x0F00) << 4;
-		par->board->mmio_write(par, BS_MMIO_DATA, tmp);
-	}
-
-}
-
-static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
-				   u16 *data)
-{
-	if (par->board->mmio_write)
-		broadsheet_mmio_burst_write(par, size, data);
-	else
-		broadsheet_gpio_burst_write(par, size, data);
-}
-
-static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
-{
-	u16 res;
-	/* wait for ready to go hi. (lo is busy) */
-	par->board->wait_for_rdy(par);
-
-	/* cs lo, dc lo for cmd, we lo for each data, db as usual */
-	par->board->set_ctl(par, BS_DC, 1);
-	par->board->set_ctl(par, BS_CS, 0);
-	par->board->set_ctl(par, BS_WR, 0);
-
-	res = par->board->get_hdb(par);
-
-	/* strobe wr */
-	par->board->set_ctl(par, BS_WR, 1);
-	par->board->set_ctl(par, BS_CS, 1);
-
-	return res;
-}
-
-
-static u16 broadsheet_get_data(struct broadsheetfb_par *par)
-{
-	if (par->board->mmio_read)
-		return par->board->mmio_read(par);
-	else
-		return broadsheet_gpio_get_data(par);
-}
-
-static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
-					u16 data)
-{
-	/* wait for ready to go hi. (lo is busy) */
-	par->board->wait_for_rdy(par);
-
-	/* cs lo, dc lo for cmd, we lo for each data, db as usual */
-	par->board->set_ctl(par, BS_CS, 0);
-
-	broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
-
-	par->board->set_ctl(par, BS_DC, 1);
-
-	broadsheet_gpio_issue_data(par, reg);
-	broadsheet_gpio_issue_data(par, data);
-
-	par->board->set_ctl(par, BS_CS, 1);
-}
-
-static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
-				 u16 data)
-{
-	par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
-	par->board->mmio_write(par, BS_MMIO_DATA, reg);
-	par->board->mmio_write(par, BS_MMIO_DATA, data);
-
-}
-
-static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
-					u16 data)
-{
-	if (par->board->mmio_write)
-		broadsheet_mmio_write_reg(par, reg, data);
-	else
-		broadsheet_gpio_write_reg(par, reg, data);
-}
-
-static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
-					u32 data)
-{
-	broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
-	broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
-}
-
-
-static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
-{
-	broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, &reg);
-	par->board->wait_for_rdy(par);
-	return broadsheet_get_data(par);
-}
-
-/* functions for waveform manipulation */
-static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
-{
-	return broadsheet_read_reg(par, 0x000A) & 0x0001;
-}
-
-static int broadsheet_setup_plls(struct broadsheetfb_par *par)
-{
-	int retry_count = 0;
-	u16 tmp;
-
-	/* disable arral saemipu mode */
-	broadsheet_write_reg(par, 0x0006, 0x0000);
-
-	broadsheet_write_reg(par, 0x0010, 0x0004);
-	broadsheet_write_reg(par, 0x0012, 0x5949);
-	broadsheet_write_reg(par, 0x0014, 0x0040);
-	broadsheet_write_reg(par, 0x0016, 0x0000);
-
-	do {
-		if (retry_count++ > 100)
-			return -ETIMEDOUT;
-		mdelay(1);
-	} while (!is_broadsheet_pll_locked(par));
-
-	tmp = broadsheet_read_reg(par, 0x0006);
-	tmp &= ~0x1;
-	broadsheet_write_reg(par, 0x0006, tmp);
-
-	return 0;
-}
-
-static int broadsheet_setup_spi(struct broadsheetfb_par *par)
-{
-
-	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
-	broadsheet_write_reg(par, 0x0208, 0x0001);
-
-	return 0;
-}
-
-static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
-						u16 *orig_sfmcd)
-{
-
-	*orig_sfmcd = broadsheet_read_reg(par, 0x0204);
-	broadsheet_write_reg(par, 0x0208, 0);
-	broadsheet_write_reg(par, 0x0204, 0);
-	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
-
-	return 0;
-}
-
-static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
-						u16 reg, int bitnum, int val,
-						int timeout)
-{
-	u16 tmp;
-
-	do {
-		tmp = broadsheet_read_reg(par, reg);
-		if (((tmp >> bitnum) & 1) == val)
-			return 0;
-		mdelay(1);
-	} while (timeout--);
-
-	return -ETIMEDOUT;
-}
-
-static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
-{
-	broadsheet_write_reg(par, 0x0202, (data | 0x100));
-
-	return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
-}
-
-static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
-{
-	int err;
-	u16 tmp;
-
-	broadsheet_write_reg(par, 0x0202, 0);
-
-	err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
-	if (err)
-		return err;
-
-	tmp = broadsheet_read_reg(par, 0x200);
-
-	*data = tmp & 0xFF;
-
-	return 0;
-}
-
-static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
-								int timeout)
-{
-	u8 tmp;
-	int err;
-
-	do {
-		broadsheet_write_reg(par, 0x0208, 1);
-
-		err = broadsheet_spiflash_write_byte(par, 0x05);
-		if (err)
-			goto failout;
-
-		err = broadsheet_spiflash_read_byte(par, &tmp);
-		if (err)
-			goto failout;
-
-		broadsheet_write_reg(par, 0x0208, 0);
-
-		if (!(tmp & 0x1))
-			return 0;
-
-		mdelay(5);
-	} while (timeout--);
-
-	dev_err(par->info->device, "Timed out waiting for spiflash status\n");
-	return -ETIMEDOUT;
-
-failout:
-	broadsheet_write_reg(par, 0x0208, 0);
-	return err;
-}
-
-static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
-							u8 op, u32 addr)
-{
-	int i;
-	u8 tmp;
-	int err;
-
-	broadsheet_write_reg(par, 0x0208, 1);
-
-	err = broadsheet_spiflash_write_byte(par, op);
-	if (err)
-		return err;
-
-	for (i = 2; i >= 0; i--) {
-		tmp = ((addr >> (i * 8)) & 0xFF);
-		err = broadsheet_spiflash_write_byte(par, tmp);
-		if (err)
-			return err;
-	}
-
-	return err;
-}
-
-static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
-						int *flash_type)
-{
-	int err = 0;
-	u8 sig;
-
-	err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
-	if (err)
-		goto failout;
-
-	err = broadsheet_spiflash_read_byte(par, &sig);
-	if (err)
-		goto failout;
-
-	if ((sig != 0x10) && (sig != 0x11)) {
-		dev_err(par->info->device, "Unexpected flash type\n");
-		err = -EINVAL;
-		goto failout;
-	}
-
-	*flash_type = sig;
-
-failout:
-	broadsheet_write_reg(par, 0x0208, 0);
-	return err;
-}
-
-static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
-					u16 *initial_sfmcd, int *flash_type)
-
-{
-	int err;
-
-	err = broadsheet_setup_plls(par);
-	if (err)
-		return err;
-
-	broadsheet_write_reg(par, 0x0106, 0x0203);
-
-	err = broadsheet_setup_spi(par);
-	if (err)
-		return err;
-
-	err = broadsheet_setup_spiflash(par, initial_sfmcd);
-	if (err)
-		return err;
-
-	return broadsheet_verify_spiflash(par, flash_type);
-}
-
-static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
-						int mode)
-{
-	int err;
-
-	broadsheet_write_reg(par, 0x0208, 1);
-	if (mode)
-		err = broadsheet_spiflash_write_byte(par, 0x06);
-	else
-		err = broadsheet_spiflash_write_byte(par, 0x04);
-
-	broadsheet_write_reg(par, 0x0208, 0);
-	return err;
-}
-
-static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
-						int addr)
-{
-	int err;
-
-	broadsheet_spiflash_write_control(par, 1);
-
-	err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
-
-	broadsheet_write_reg(par, 0x0208, 0);
-
-	if (err)
-		return err;
-
-	err = broadsheet_spiflash_wait_for_status(par, 1000);
-
-	return err;
-}
-
-static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
-						int addr, int size, char *data)
-{
-	int err;
-	int i;
-
-	err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
-	if (err)
-		goto failout;
-
-	for (i = 0; i < size; i++) {
-		err = broadsheet_spiflash_read_byte(par, &data[i]);
-		if (err)
-			goto failout;
-	}
-
-failout:
-	broadsheet_write_reg(par, 0x0208, 0);
-	return err;
-}
-
-#define BS_SPIFLASH_PAGE_SIZE 256
-static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
-						int addr, const char *data)
-{
-	int err;
-	int i;
-
-	broadsheet_spiflash_write_control(par, 1);
-
-	err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
-	if (err)
-		goto failout;
-
-	for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
-		err = broadsheet_spiflash_write_byte(par, data[i]);
-		if (err)
-			goto failout;
-	}
-
-	broadsheet_write_reg(par, 0x0208, 0);
-
-	err = broadsheet_spiflash_wait_for_status(par, 100);
-
-failout:
-	return err;
-}
-
-static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
-				int addr, const char *data, int sector_size)
-{
-	int i;
-	int err;
-
-	for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
-		err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-/*
- * The caller must guarantee that the data to be rewritten is entirely
- * contained within this sector. That is, data_start_addr + data_len
- * must be less than sector_start_addr + sector_size.
- */
-static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
-					int sector_size, int data_start_addr,
-					int data_len, const char *data)
-{
-	int err;
-	char *sector_buffer;
-	int tail_start_addr;
-	int start_sector_addr;
-
-	sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL);
-	if (!sector_buffer)
-		return -ENOMEM;
-
-	/* the start address of the sector is the 0th byte of that sector */
-	start_sector_addr = (data_start_addr / sector_size) * sector_size;
-
-	/*
-	 * check if there is head data that we need to readback into our sector
-	 * buffer first
-	 */
-	if (data_start_addr != start_sector_addr) {
-		/*
-		 * we need to read every byte up till the start address of our
-		 * data and we put it into our sector buffer.
-		 */
-		err = broadsheet_spiflash_read_range(par, start_sector_addr,
-						data_start_addr, sector_buffer);
-		if (err)
-			return err;
-	}
-
-	/* now we copy our data into the right place in the sector buffer */
-	memcpy(sector_buffer + data_start_addr, data, data_len);
-
-	/*
-	 * now we check if there is a tail section of the sector that we need to
-	 * readback.
-	 */
-	tail_start_addr = (data_start_addr + data_len) % sector_size;
-
-	if (tail_start_addr) {
-		int tail_len;
-
-		tail_len = sector_size - tail_start_addr;
-
-		/* now we read this tail into our sector buffer */
-		err = broadsheet_spiflash_read_range(par, tail_start_addr,
-			tail_len, sector_buffer + tail_start_addr);
-		if (err)
-			return err;
-	}
-
-	/* if we got here we have the full sector that we want to rewrite. */
-
-	/* first erase the sector */
-	err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
-	if (err)
-		return err;
-
-	/* now write it */
-	err = broadsheet_spiflash_write_sector(par, start_sector_addr,
-					sector_buffer, sector_size);
-	return err;
-}
-
-static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
-				const u8 *wfm, int bytecount, int flash_type)
-{
-	int sector_size;
-	int err;
-	int cur_addr;
-	int writecount;
-	int maxlen;
-	int offset = 0;
-
-	switch (flash_type) {
-	case 0x10:
-		sector_size = 32*1024;
-		break;
-	case 0x11:
-	default:
-		sector_size = 64*1024;
-		break;
-	}
-
-	while (bytecount) {
-		cur_addr = wfm_addr + offset;
-		maxlen = roundup(cur_addr, sector_size) - cur_addr;
-		writecount = min(bytecount, maxlen);
-
-		err = broadsheet_spiflash_rewrite_sector(par, sector_size,
-				cur_addr, writecount, wfm + offset);
-		if (err)
-			return err;
-
-		offset += writecount;
-		bytecount -= writecount;
-	}
-
-	return 0;
-}
-
-static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
-						const u8 *wfm, size_t wfm_size)
-{
-	int err = 0;
-	u16 initial_sfmcd = 0;
-	int flash_type = 0;
-
-	err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
-	if (err)
-		goto failout;
-
-	err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
-
-failout:
-	broadsheet_write_reg(par, 0x0204, initial_sfmcd);
-	return err;
-}
-
-static ssize_t broadsheet_loadstore_waveform(struct device *dev,
-						struct device_attribute *attr,
-						const char *buf, size_t len)
-{
-	int err;
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct broadsheetfb_par *par = info->par;
-	const struct firmware *fw_entry;
-
-	if (len < 1)
-		return -EINVAL;
-
-	err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
-	if (err < 0) {
-		dev_err(dev, "Failed to get broadsheet waveform\n");
-		goto err_failed;
-	}
-
-	/* try to enforce reasonable min max on waveform */
-	if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
-		dev_err(dev, "Invalid waveform\n");
-		err = -EINVAL;
-		goto err_failed;
-	}
-
-	mutex_lock(&(par->io_lock));
-	err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
-							fw_entry->size);
-
-	mutex_unlock(&(par->io_lock));
-	if (err < 0) {
-		dev_err(dev, "Failed to store broadsheet waveform\n");
-		goto err_failed;
-	}
-
-	dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
-
-	return len;
-
-err_failed:
-	return err;
-}
-static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
-			broadsheet_loadstore_waveform);
-
-/* upper level functions that manipulate the display and other stuff */
-static void broadsheet_init_display(struct broadsheetfb_par *par)
-{
-	u16 args[5];
-	int xres = par->info->var.xres;
-	int yres = par->info->var.yres;
-
-	args[0] = panel_table[par->panel_index].w;
-	args[1] = panel_table[par->panel_index].h;
-	args[2] = panel_table[par->panel_index].sdcfg;
-	args[3] = panel_table[par->panel_index].gdcfg;
-	args[4] = panel_table[par->panel_index].lutfmt;
-	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
-
-	/* did the controller really set it? */
-	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
-
-	args[0] = panel_table[par->panel_index].fsynclen;
-	args[1] = panel_table[par->panel_index].fendfbegin;
-	args[2] = panel_table[par->panel_index].lsynclen;
-	args[3] = panel_table[par->panel_index].lendlbegin;
-	args[4] = panel_table[par->panel_index].pixclk;
-	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
-
-	broadsheet_write_reg32(par, 0x310, xres*yres*2);
-
-	/* setup waveform */
-	args[0] = 0x886;
-	args[1] = 0;
-	broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
-
-	broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
-
-	broadsheet_write_reg(par, 0x330, 0x84);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
-
-	args[0] = (0x3 << 4);
-	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
-
-	args[0] = 0x154;
-	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
-
-	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
-					panel_table[par->panel_index].h)/2,
-					(u16 *) par->info->screen_base);
-
-	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
-
-	args[0] = 0x4300;
-	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
-
-	par->board->wait_for_rdy(par);
-}
-
-static void broadsheet_identify(struct broadsheetfb_par *par)
-{
-	u16 rev, prc;
-	struct device *dev = par->info->device;
-
-	rev = broadsheet_read_reg(par, BS_REG_REV);
-	prc = broadsheet_read_reg(par, BS_REG_PRC);
-	dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
-
-	if (prc != 0x0047)
-		dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
-	if (rev != 0x0100)
-		dev_warn(dev, "Unrecognized Broadsheet Revision\n");
-}
-
-static void broadsheet_init(struct broadsheetfb_par *par)
-{
-	broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
-	/* the controller needs a second */
-	msleep(1000);
-	broadsheet_init_display(par);
-}
-
-static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
-						u16 y1, u16 y2)
-{
-	u16 args[5];
-	unsigned char *buf = (unsigned char *)par->info->screen_base;
-
-	mutex_lock(&(par->io_lock));
-	/* y1 must be a multiple of 4 so drop the lower bits */
-	y1 &= 0xFFFC;
-	/* y2 must be a multiple of 4 , but - 1 so up the lower bits */
-	y2 |= 0x0003;
-
-	args[0] = 0x3 << 4;
-	args[1] = 0;
-	args[2] = y1;
-	args[3] = cpu_to_le16(par->info->var.xres);
-	args[4] = y2;
-	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
-
-	args[0] = 0x154;
-	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
-
-	buf += y1 * par->info->var.xres;
-	broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
-				(u16 *) buf);
-
-	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
-
-	args[0] = 0x4300;
-	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
-
-	par->board->wait_for_rdy(par);
-	mutex_unlock(&(par->io_lock));
-
-}
-
-static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
-{
-	u16 args[5];
-
-	mutex_lock(&(par->io_lock));
-	args[0] = 0x3 << 4;
-	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
-
-	args[0] = 0x154;
-	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
-	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
-					panel_table[par->panel_index].h)/2,
-					(u16 *) par->info->screen_base);
-
-	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
-
-	args[0] = 0x4300;
-	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
-
-	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
-
-	par->board->wait_for_rdy(par);
-	mutex_unlock(&(par->io_lock));
-}
-
-/* this is called back from the deferred io workqueue */
-static void broadsheetfb_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	u16 y1 = 0, h = 0;
-	int prev_index = -1;
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	int h_inc;
-	u16 yres = info->var.yres;
-	u16 xres = info->var.xres;
-
-	/* height increment is fixed per page */
-	h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
-
-	/* walk the written page list and swizzle the data */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-		if (prev_index < 0) {
-			/* just starting so assign first page */
-			y1 = (cur->index << PAGE_SHIFT) / xres;
-			h = h_inc;
-		} else if ((prev_index + 1) == cur->index) {
-			/* this page is consecutive so increase our height */
-			h += h_inc;
-		} else {
-			/* page not consecutive, issue previous update first */
-			broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
-			/* start over with our non consecutive page */
-			y1 = (cur->index << PAGE_SHIFT) / xres;
-			h = h_inc;
-		}
-		prev_index = cur->index;
-	}
-
-	/* if we still have any pages to update we do so now */
-	if (h >= yres) {
-		/* its a full screen update, just do it */
-		broadsheetfb_dpy_update(info->par);
-	} else {
-		broadsheetfb_dpy_update_pages(info->par, y1,
-						min((u16) (y1 + h), yres));
-	}
-}
-
-static void broadsheetfb_fillrect(struct fb_info *info,
-				   const struct fb_fillrect *rect)
-{
-	struct broadsheetfb_par *par = info->par;
-
-	sys_fillrect(info, rect);
-
-	broadsheetfb_dpy_update(par);
-}
-
-static void broadsheetfb_copyarea(struct fb_info *info,
-				   const struct fb_copyarea *area)
-{
-	struct broadsheetfb_par *par = info->par;
-
-	sys_copyarea(info, area);
-
-	broadsheetfb_dpy_update(par);
-}
-
-static void broadsheetfb_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	struct broadsheetfb_par *par = info->par;
-
-	sys_imageblit(info, image);
-
-	broadsheetfb_dpy_update(par);
-}
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it's inefficient to do anything less than a full screen draw
- */
-static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	struct broadsheetfb_par *par = info->par;
-	unsigned long p = *ppos;
-	void *dst;
-	int err = 0;
-	unsigned long total_size;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EFBIG;
-
-	if (count > total_size) {
-		err = -EFBIG;
-		count = total_size;
-	}
-
-	if (count + p > total_size) {
-		if (!err)
-			err = -ENOSPC;
-
-		count = total_size - p;
-	}
-
-	dst = (void *)(info->screen_base + p);
-
-	if (copy_from_user(dst, buf, count))
-		err = -EFAULT;
-
-	if  (!err)
-		*ppos += count;
-
-	broadsheetfb_dpy_update(par);
-
-	return (err) ? err : count;
-}
-
-static struct fb_ops broadsheetfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_read        = fb_sys_read,
-	.fb_write	= broadsheetfb_write,
-	.fb_fillrect	= broadsheetfb_fillrect,
-	.fb_copyarea	= broadsheetfb_copyarea,
-	.fb_imageblit	= broadsheetfb_imageblit,
-};
-
-static struct fb_deferred_io broadsheetfb_defio = {
-	.delay		= HZ/4,
-	.deferred_io	= broadsheetfb_dpy_deferred_io,
-};
-
-static int broadsheetfb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	struct broadsheet_board *board;
-	int retval = -ENOMEM;
-	int videomemorysize;
-	unsigned char *videomemory;
-	struct broadsheetfb_par *par;
-	int i;
-	int dpyw, dpyh;
-	int panel_index;
-
-	/* pick up board specific routines */
-	board = dev->dev.platform_data;
-	if (!board)
-		return -EINVAL;
-
-	/* try to count device specific driver, if can't, platform recalls */
-	if (!try_module_get(board->owner))
-		return -ENODEV;
-
-	info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
-	if (!info)
-		goto err;
-
-	switch (board->get_panel_type()) {
-	case 37:
-		panel_index = 1;
-		break;
-	case 97:
-		panel_index = 2;
-		break;
-	case 6:
-	default:
-		panel_index = 0;
-		break;
-	}
-
-	dpyw = panel_table[panel_index].w;
-	dpyh = panel_table[panel_index].h;
-
-	videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
-
-	videomemory = vzalloc(videomemorysize);
-	if (!videomemory)
-		goto err_fb_rel;
-
-	info->screen_base = (char *)videomemory;
-	info->fbops = &broadsheetfb_ops;
-
-	broadsheetfb_var.xres = dpyw;
-	broadsheetfb_var.yres = dpyh;
-	broadsheetfb_var.xres_virtual = dpyw;
-	broadsheetfb_var.yres_virtual = dpyh;
-	info->var = broadsheetfb_var;
-
-	broadsheetfb_fix.line_length = dpyw;
-	info->fix = broadsheetfb_fix;
-	info->fix.smem_len = videomemorysize;
-	par = info->par;
-	par->panel_index = panel_index;
-	par->info = info;
-	par->board = board;
-	par->write_reg = broadsheet_write_reg;
-	par->read_reg = broadsheet_read_reg;
-	init_waitqueue_head(&par->waitq);
-
-	mutex_init(&par->io_lock);
-
-	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
-
-	info->fbdefio = &broadsheetfb_defio;
-	fb_deferred_io_init(info);
-
-	retval = fb_alloc_cmap(&info->cmap, 16, 0);
-	if (retval < 0) {
-		dev_err(&dev->dev, "Failed to allocate colormap\n");
-		goto err_vfree;
-	}
-
-	/* set cmap */
-	for (i = 0; i < 16; i++)
-		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
-	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
-	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
-
-	retval = par->board->setup_irq(info);
-	if (retval < 0)
-		goto err_cmap;
-
-	/* this inits the dpy */
-	retval = board->init(par);
-	if (retval < 0)
-		goto err_free_irq;
-
-	broadsheet_identify(par);
-
-	broadsheet_init(par);
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err_free_irq;
-
-	platform_set_drvdata(dev, info);
-
-	retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
-	if (retval < 0)
-		goto err_unreg_fb;
-
-	fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
-		videomemorysize >> 10);
-
-
-	return 0;
-
-err_unreg_fb:
-	unregister_framebuffer(info);
-err_free_irq:
-	board->cleanup(par);
-err_cmap:
-	fb_dealloc_cmap(&info->cmap);
-err_vfree:
-	vfree(videomemory);
-err_fb_rel:
-	framebuffer_release(info);
-err:
-	module_put(board->owner);
-	return retval;
-
-}
-
-static int broadsheetfb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		struct broadsheetfb_par *par = info->par;
-
-		device_remove_file(info->dev, &dev_attr_loadstore_waveform);
-		unregister_framebuffer(info);
-		fb_deferred_io_cleanup(info);
-		par->board->cleanup(par);
-		fb_dealloc_cmap(&info->cmap);
-		vfree((void *)info->screen_base);
-		module_put(par->board->owner);
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-static struct platform_driver broadsheetfb_driver = {
-	.probe	= broadsheetfb_probe,
-	.remove = broadsheetfb_remove,
-	.driver	= {
-		.owner	= THIS_MODULE,
-		.name	= "broadsheetfb",
-	},
-};
-module_platform_driver(broadsheetfb_driver);
-
-MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/bt431.h b/drivers/video/bt431.h
deleted file mode 100644
index 04e0cfbba538..000000000000
--- a/drivers/video/bt431.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *	linux/drivers/video/bt431.h
- *
- *	Copyright 2003  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
- *
- *	This file is subject to the terms and conditions of the GNU General
- *	Public License. See the file COPYING in the main directory of this
- *	archive for more details.
- */
-#include <linux/types.h>
-
-/*
- * Bt431 cursor generator registers, 32-bit aligned.
- * Two twin Bt431 are used on the DECstation's PMAG-AA.
- */
-struct bt431_regs {
-	volatile u16 addr_lo;
-	u16 pad0;
-	volatile u16 addr_hi;
-	u16 pad1;
-	volatile u16 addr_cmap;
-	u16 pad2;
-	volatile u16 addr_reg;
-	u16 pad3;
-};
-
-static inline u16 bt431_set_value(u8 val)
-{
-	return ((val << 8) | (val & 0xff)) & 0xffff;
-}
-
-static inline u8 bt431_get_value(u16 val)
-{
-	return val & 0xff;
-}
-
-/*
- * Additional registers addressed indirectly.
- */
-#define BT431_REG_CMD		0x0000
-#define BT431_REG_CXLO		0x0001
-#define BT431_REG_CXHI		0x0002
-#define BT431_REG_CYLO		0x0003
-#define BT431_REG_CYHI		0x0004
-#define BT431_REG_WXLO		0x0005
-#define BT431_REG_WXHI		0x0006
-#define BT431_REG_WYLO		0x0007
-#define BT431_REG_WYHI		0x0008
-#define BT431_REG_WWLO		0x0009
-#define BT431_REG_WWHI		0x000a
-#define BT431_REG_WHLO		0x000b
-#define BT431_REG_WHHI		0x000c
-
-#define BT431_REG_CRAM_BASE	0x0000
-#define BT431_REG_CRAM_END	0x01ff
-
-/*
- * Command register.
- */
-#define BT431_CMD_CURS_ENABLE	0x40
-#define BT431_CMD_XHAIR_ENABLE	0x20
-#define BT431_CMD_OR_CURSORS	0x10
-#define BT431_CMD_AND_CURSORS	0x00
-#define BT431_CMD_1_1_MUX	0x00
-#define BT431_CMD_4_1_MUX	0x04
-#define BT431_CMD_5_1_MUX	0x08
-#define BT431_CMD_xxx_MUX	0x0c
-#define BT431_CMD_THICK_1	0x00
-#define BT431_CMD_THICK_3	0x01
-#define BT431_CMD_THICK_5	0x02
-#define BT431_CMD_THICK_7	0x03
-
-static inline void bt431_select_reg(struct bt431_regs *regs, int ir)
-{
-	/*
-	 * The compiler splits the write in two bytes without these
-	 * helper variables.
-	 */
-	volatile u16 *lo = &(regs->addr_lo);
-	volatile u16 *hi = &(regs->addr_hi);
-
-	mb();
-	*lo = bt431_set_value(ir & 0xff);
-	wmb();
-	*hi = bt431_set_value((ir >> 8) & 0xff);
-}
-
-/* Autoincrement read/write. */
-static inline u8 bt431_read_reg_inc(struct bt431_regs *regs)
-{
-	/*
-	 * The compiler splits the write in two bytes without the
-	 * helper variable.
-	 */
-	volatile u16 *r = &(regs->addr_reg);
-
-	mb();
-	return bt431_get_value(*r);
-}
-
-static inline void bt431_write_reg_inc(struct bt431_regs *regs, u8 value)
-{
-	/*
-	 * The compiler splits the write in two bytes without the
-	 * helper variable.
-	 */
-	volatile u16 *r = &(regs->addr_reg);
-
-	mb();
-	*r = bt431_set_value(value);
-}
-
-static inline u8 bt431_read_reg(struct bt431_regs *regs, int ir)
-{
-	bt431_select_reg(regs, ir);
-	return bt431_read_reg_inc(regs);
-}
-
-static inline void bt431_write_reg(struct bt431_regs *regs, int ir, u8 value)
-{
-	bt431_select_reg(regs, ir);
-	bt431_write_reg_inc(regs, value);
-}
-
-/* Autoincremented read/write for the cursor map. */
-static inline u16 bt431_read_cmap_inc(struct bt431_regs *regs)
-{
-	/*
-	 * The compiler splits the write in two bytes without the
-	 * helper variable.
-	 */
-	volatile u16 *r = &(regs->addr_cmap);
-
-	mb();
-	return *r;
-}
-
-static inline void bt431_write_cmap_inc(struct bt431_regs *regs, u16 value)
-{
-	/*
-	 * The compiler splits the write in two bytes without the
-	 * helper variable.
-	 */
-	volatile u16 *r = &(regs->addr_cmap);
-
-	mb();
-	*r = value;
-}
-
-static inline u16 bt431_read_cmap(struct bt431_regs *regs, int cr)
-{
-	bt431_select_reg(regs, cr);
-	return bt431_read_cmap_inc(regs);
-}
-
-static inline void bt431_write_cmap(struct bt431_regs *regs, int cr, u16 value)
-{
-	bt431_select_reg(regs, cr);
-	bt431_write_cmap_inc(regs, value);
-}
-
-static inline void bt431_enable_cursor(struct bt431_regs *regs)
-{
-	bt431_write_reg(regs, BT431_REG_CMD,
-			BT431_CMD_CURS_ENABLE | BT431_CMD_OR_CURSORS
-			| BT431_CMD_4_1_MUX | BT431_CMD_THICK_1);
-}
-
-static inline void bt431_erase_cursor(struct bt431_regs *regs)
-{
-	bt431_write_reg(regs, BT431_REG_CMD, BT431_CMD_4_1_MUX);
-}
-
-static inline void bt431_position_cursor(struct bt431_regs *regs, u16 x, u16 y)
-{
-	/*
-	 * Magic from the MACH sources.
-	 *
-	 * Cx = x + D + H - P
-	 *  P = 37 if 1:1, 52 if 4:1, 57 if 5:1
-	 *  D = pixel skew between outdata and external data
-	 *  H = pixels between HSYNCH falling and active video
-	 *
-	 * Cy = y + V - 32
-	 *  V = scanlines between HSYNCH falling, two or more
-	 *      clocks after VSYNCH falling, and active video
-	 */
-	x += 412 - 52;
-	y += 68 - 32;
-
-	/* Use autoincrement. */
-	bt431_select_reg(regs, BT431_REG_CXLO);
-	bt431_write_reg_inc(regs, x & 0xff); /* BT431_REG_CXLO */
-	bt431_write_reg_inc(regs, (x >> 8) & 0x0f); /* BT431_REG_CXHI */
-	bt431_write_reg_inc(regs, y & 0xff); /* BT431_REG_CYLO */
-	bt431_write_reg_inc(regs, (y >> 8) & 0x0f); /* BT431_REG_CYHI */
-}
-
-static inline void bt431_set_font(struct bt431_regs *regs, u8 fgc,
-				  u16 width, u16 height)
-{
-	int i;
-	u16 fgp = fgc ? 0xffff : 0x0000;
-	u16 bgp = fgc ? 0x0000 : 0xffff;
-
-	bt431_select_reg(regs, BT431_REG_CRAM_BASE);
-	for (i = BT431_REG_CRAM_BASE; i <= BT431_REG_CRAM_END; i++) {
-		u16 value;
-
-		if (height << 6 <= i << 3)
-			value = bgp;
-		else if (width <= i % 8 << 3)
-			value = bgp;
-		else if (((width >> 3) & 0xffff) > i % 8)
-			value = fgp;
-		else
-			value = fgp & ~(bgp << (width % 8 << 1));
-
-		bt431_write_cmap_inc(regs, value);
-	}
-}
-
-static inline void bt431_init_cursor(struct bt431_regs *regs)
-{
-	/* no crosshair window */
-	bt431_select_reg(regs, BT431_REG_WXLO);
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WXLO */
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WXHI */
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WYLO */
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WYHI */
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WWLO */
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WWHI */
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WHLO */
-	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WHHI */
-}
diff --git a/drivers/video/bt455.h b/drivers/video/bt455.h
deleted file mode 100644
index 80f61b03e9ae..000000000000
--- a/drivers/video/bt455.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *	linux/drivers/video/bt455.h
- *
- *	Copyright 2003  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
- *
- *	This file is subject to the terms and conditions of the GNU General
- *	Public License. See the file COPYING in the main directory of this
- *	archive for more details.
- */
-#include <linux/types.h>
-
-/*
- * Bt455 byte-wide registers, 32-bit aligned.
- */
-struct bt455_regs {
-	volatile u8 addr_cmap;
-	u8 pad0[3];
-	volatile u8 addr_cmap_data;
-	u8 pad1[3];
-	volatile u8 addr_clr;
-	u8 pad2[3];
-	volatile u8 addr_ovly;
-	u8 pad3[3];
-};
-
-static inline void bt455_select_reg(struct bt455_regs *regs, int ir)
-{
-	mb();
-	regs->addr_cmap = ir & 0x0f;
-}
-
-/*
- * Read/write to a Bt455 color map register.
- */
-static inline void bt455_read_cmap_entry(struct bt455_regs *regs, int cr,
-					 u8* red, u8* green, u8* blue)
-{
-	bt455_select_reg(regs, cr);
-	mb();
-	*red = regs->addr_cmap_data & 0x0f;
-	rmb();
-	*green = regs->addr_cmap_data & 0x0f;
-	rmb();
-	*blue = regs->addr_cmap_data & 0x0f;
-}
-
-static inline void bt455_write_cmap_entry(struct bt455_regs *regs, int cr,
-					  u8 red, u8 green, u8 blue)
-{
-	bt455_select_reg(regs, cr);
-	wmb();
-	regs->addr_cmap_data = red & 0x0f;
-	wmb();
-	regs->addr_cmap_data = green & 0x0f;
-	wmb();
-	regs->addr_cmap_data = blue & 0x0f;
-}
-
-static inline void bt455_write_ovly_entry(struct bt455_regs *regs, int cr,
-					  u8 red, u8 green, u8 blue)
-{
-	bt455_select_reg(regs, cr);
-	wmb();
-	regs->addr_ovly = red & 0x0f;
-	wmb();
-	regs->addr_ovly = green & 0x0f;
-	wmb();
-	regs->addr_ovly = blue & 0x0f;
-}
-
-static inline void bt455_set_cursor(struct bt455_regs *regs)
-{
-	mb();
-	regs->addr_ovly = 0x0f;
-	wmb();
-	regs->addr_ovly = 0x0f;
-	wmb();
-	regs->addr_ovly = 0x0f;
-}
-
-static inline void bt455_erase_cursor(struct bt455_regs *regs)
-{
-	/* bt455_write_cmap_entry(regs, 8, 0x00, 0x00, 0x00); */
-	/* bt455_write_cmap_entry(regs, 9, 0x00, 0x00, 0x00); */
-	bt455_write_ovly_entry(regs, 8, 0x03, 0x03, 0x03);
-	bt455_write_ovly_entry(regs, 9, 0x07, 0x07, 0x07);
-
-	wmb();
-	regs->addr_ovly = 0x09;
-	wmb();
-	regs->addr_ovly = 0x09;
-	wmb();
-	regs->addr_ovly = 0x09;
-}
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
deleted file mode 100644
index bc123d6947a4..000000000000
--- a/drivers/video/bw2.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/* bw2.c: BWTWO frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int bw2_blank(int, struct fb_info *);
-
-static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
-static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops bw2_ops = {
-	.owner			= THIS_MODULE,
-	.fb_blank		= bw2_blank,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_mmap		= bw2_mmap,
-	.fb_ioctl		= bw2_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-/* OBio addresses for the bwtwo registers */
-#define BWTWO_REGISTER_OFFSET 0x400000
-
-struct bt_regs {
-	u32 addr;
-	u32 color_map;
-	u32 control;
-	u32 cursor;
-};
-
-struct bw2_regs {
-	struct bt_regs	cmap;
-	u8	control;
-	u8	status;
-	u8	cursor_start;
-	u8	cursor_end;
-	u8	h_blank_start;
-	u8	h_blank_end;
-	u8	h_sync_start;
-	u8	h_sync_end;
-	u8	comp_sync_end;
-	u8	v_blank_start_high;
-	u8	v_blank_start_low;
-	u8	v_blank_end;
-	u8	v_sync_start;
-	u8	v_sync_end;
-	u8	xfer_holdoff_start;
-	u8	xfer_holdoff_end;
-};
-
-/* Status Register Constants */
-#define BWTWO_SR_RES_MASK	0x70
-#define BWTWO_SR_1600_1280	0x50
-#define BWTWO_SR_1152_900_76_A	0x40
-#define BWTWO_SR_1152_900_76_B	0x60
-#define BWTWO_SR_ID_MASK	0x0f
-#define BWTWO_SR_ID_MONO	0x02
-#define BWTWO_SR_ID_MONO_ECL	0x03
-#define BWTWO_SR_ID_MSYNC	0x04
-#define BWTWO_SR_ID_NOCONN	0x0a
-
-/* Control Register Constants */
-#define BWTWO_CTL_ENABLE_INTS   0x80
-#define BWTWO_CTL_ENABLE_VIDEO  0x40
-#define BWTWO_CTL_ENABLE_TIMING 0x20
-#define BWTWO_CTL_ENABLE_CURCMP 0x10
-#define BWTWO_CTL_XTAL_MASK     0x0C
-#define BWTWO_CTL_DIVISOR_MASK  0x03
-
-/* Status Register Constants */
-#define BWTWO_STAT_PENDING_INT  0x80
-#define BWTWO_STAT_MSENSE_MASK  0x70
-#define BWTWO_STAT_ID_MASK      0x0f
-
-struct bw2_par {
-	spinlock_t		lock;
-	struct bw2_regs		__iomem *regs;
-
-	u32			flags;
-#define BW2_FLAG_BLANKED	0x00000001
-
-	unsigned long		which_io;
-};
-
-/**
- *      bw2_blank - Optional function.  Blanks the display.
- *      @blank_mode: the blank mode we want.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-bw2_blank(int blank, struct fb_info *info)
-{
-	struct bw2_par *par = (struct bw2_par *) info->par;
-	struct bw2_regs __iomem *regs = par->regs;
-	unsigned long flags;
-	u8 val;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		val = sbus_readb(&regs->control);
-		val |= BWTWO_CTL_ENABLE_VIDEO;
-		sbus_writeb(val, &regs->control);
-		par->flags &= ~BW2_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		val = sbus_readb(&regs->control);
-		val &= ~BWTWO_CTL_ENABLE_VIDEO;
-		sbus_writeb(val, &regs->control);
-		par->flags |= BW2_FLAG_BLANKED;
-		break;
-	}
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static struct sbus_mmap_map bw2_mmap_map[] = {
-	{
-		.size = SBUS_MMAP_FBSIZE(1)
-	},
-	{ .size = 0 }
-};
-
-static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct bw2_par *par = (struct bw2_par *)info->par;
-
-	return sbusfb_mmap_helper(bw2_mmap_map,
-				  info->fix.smem_start, info->fix.smem_len,
-				  par->which_io,
-				  vma);
-}
-
-static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	return sbusfb_ioctl_helper(cmd, arg, info,
-				   FBTYPE_SUN2BW, 1, info->fix.smem_len);
-}
-
-/*
- *  Initialisation
- */
-
-static void bw2_init_fix(struct fb_info *info, int linebytes)
-{
-	strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_MONO01;
-
-	info->fix.line_length = linebytes;
-
-	info->fix.accel = FB_ACCEL_SUN_BWTWO;
-}
-
-static u8 bw2regs_1600[] = {
-	0x14, 0x8b,	0x15, 0x28,	0x16, 0x03,	0x17, 0x13,
-	0x18, 0x7b,	0x19, 0x05,	0x1a, 0x34,	0x1b, 0x2e,
-	0x1c, 0x00,	0x1d, 0x0a,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x21,	0
-};
-
-static u8 bw2regs_ecl[] = {
-	0x14, 0x65,	0x15, 0x1e,	0x16, 0x04,	0x17, 0x0c,
-	0x18, 0x5e,	0x19, 0x03,	0x1a, 0xa7,	0x1b, 0x23,
-	0x1c, 0x00,	0x1d, 0x08,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x20,	0
-};
-
-static u8 bw2regs_analog[] = {
-	0x14, 0xbb,	0x15, 0x2b,	0x16, 0x03,	0x17, 0x13,
-	0x18, 0xb0,	0x19, 0x03,	0x1a, 0xa6,	0x1b, 0x22,
-	0x1c, 0x01,	0x1d, 0x05,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x20,	0
-};
-
-static u8 bw2regs_76hz[] = {
-	0x14, 0xb7,	0x15, 0x27,	0x16, 0x03,	0x17, 0x0f,
-	0x18, 0xae,	0x19, 0x03,	0x1a, 0xae,	0x1b, 0x2a,
-	0x1c, 0x01,	0x1d, 0x09,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x24,	0
-};
-
-static u8 bw2regs_66hz[] = {
-	0x14, 0xbb,	0x15, 0x2b,	0x16, 0x04,	0x17, 0x14,
-	0x18, 0xae,	0x19, 0x03,	0x1a, 0xa8,	0x1b, 0x24,
-	0x1c, 0x01,	0x1d, 0x05,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x20,	0
-};
-
-static int bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
-			       int *linebytes)
-{
-	u8 status, mon;
-	u8 *p;
-
-	status = sbus_readb(&par->regs->status);
-	mon = status & BWTWO_SR_RES_MASK;
-	switch (status & BWTWO_SR_ID_MASK) {
-	case BWTWO_SR_ID_MONO_ECL:
-		if (mon == BWTWO_SR_1600_1280) {
-			p = bw2regs_1600;
-			info->var.xres = info->var.xres_virtual = 1600;
-			info->var.yres = info->var.yres_virtual = 1280;
-			*linebytes = 1600 / 8;
-		} else
-			p = bw2regs_ecl;
-		break;
-
-	case BWTWO_SR_ID_MONO:
-		p = bw2regs_analog;
-		break;
-
-	case BWTWO_SR_ID_MSYNC:
-		if (mon == BWTWO_SR_1152_900_76_A ||
-		    mon == BWTWO_SR_1152_900_76_B)
-			p = bw2regs_76hz;
-		else
-			p = bw2regs_66hz;
-		break;
-
-	case BWTWO_SR_ID_NOCONN:
-		return 0;
-
-	default:
-		printk(KERN_ERR "bw2: can't handle SR %02x\n",
-		       status);
-		return -EINVAL;
-	}
-	for ( ; *p; p += 2) {
-		u8 __iomem *regp = &((u8 __iomem *)par->regs)[p[0]];
-		sbus_writeb(p[1], regp);
-	}
-	return 0;
-}
-
-static int bw2_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct bw2_par *par;
-	int linebytes, err;
-
-	info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-
-	info->fix.smem_start = op->resource[0].start;
-	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
-
-	sbusfb_fill_var(&info->var, dp, 1);
-	linebytes = of_getintprop_default(dp, "linebytes",
-					  info->var.xres);
-
-	info->var.red.length = info->var.green.length =
-		info->var.blue.length = info->var.bits_per_pixel;
-	info->var.red.offset = info->var.green.offset =
-		info->var.blue.offset = 0;
-
-	par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
-			       sizeof(struct bw2_regs), "bw2 regs");
-	if (!par->regs)
-		goto out_release_fb;
-
-	if (!of_find_property(dp, "width", NULL)) {
-		err = bw2_do_default_mode(par, info, &linebytes);
-		if (err)
-			goto out_unmap_regs;
-	}
-
-	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &bw2_ops;
-
-	info->screen_base = of_ioremap(&op->resource[0], 0,
-				       info->fix.smem_len, "bw2 ram");
-	if (!info->screen_base) {
-		err = -ENOMEM;
-		goto out_unmap_regs;
-	}
-
-	bw2_blank(FB_BLANK_UNBLANK, info);
-
-	bw2_init_fix(info, linebytes);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_unmap_screen;
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: bwtwo at %lx:%lx\n",
-	       dp->full_name, par->which_io, info->fix.smem_start);
-
-	return 0;
-
-out_unmap_screen:
-	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
-
-out_unmap_regs:
-	of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
-
-out_release_fb:
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int bw2_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct bw2_par *par = info->par;
-
-	unregister_framebuffer(info);
-
-	of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
-	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id bw2_match[] = {
-	{
-		.name = "bwtwo",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, bw2_match);
-
-static struct platform_driver bw2_driver = {
-	.driver = {
-		.name = "bw2",
-		.owner = THIS_MODULE,
-		.of_match_table = bw2_match,
-	},
-	.probe		= bw2_probe,
-	.remove		= bw2_remove,
-};
-
-static int __init bw2_init(void)
-{
-	if (fb_get_options("bw2fb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&bw2_driver);
-}
-
-static void __exit bw2_exit(void)
-{
-	platform_driver_unregister(&bw2_driver);
-}
-
-module_init(bw2_init);
-module_exit(bw2_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/c2p.h b/drivers/video/c2p.h
deleted file mode 100644
index 6c38d40427d8..000000000000
--- a/drivers/video/c2p.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  Fast C2P (Chunky-to-Planar) Conversion
- *
- *  Copyright (C) 2003-2008 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/types.h>
-
-extern void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
-		       u32 height, u32 dst_nextline, u32 dst_nextplane,
-		       u32 src_nextline, u32 bpp);
-
-extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
-		       u32 height, u32 dst_nextline, u32 src_nextline,
-		       u32 bpp);
diff --git a/drivers/video/c2p_core.h b/drivers/video/c2p_core.h
deleted file mode 100644
index e1035a865fb9..000000000000
--- a/drivers/video/c2p_core.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  Fast C2P (Chunky-to-Planar) Conversion
- *
- *  Copyright (C) 2003-2008 Geert Uytterhoeven
- *
- *  NOTES:
- *    - This code was inspired by Scout's C2P tutorial
- *    - It assumes to run on a big endian system
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-
-    /*
-     *  Basic transpose step
-     */
-
-static inline void _transp(u32 d[], unsigned int i1, unsigned int i2,
-			   unsigned int shift, u32 mask)
-{
-	u32 t = (d[i1] ^ (d[i2] >> shift)) & mask;
-
-	d[i1] ^= t;
-	d[i2] ^= t << shift;
-}
-
-
-extern void c2p_unsupported(void);
-
-static inline u32 get_mask(unsigned int n)
-{
-	switch (n) {
-	case 1:
-		return 0x55555555;
-
-	case 2:
-		return 0x33333333;
-
-	case 4:
-		return 0x0f0f0f0f;
-
-	case 8:
-		return 0x00ff00ff;
-
-	case 16:
-		return 0x0000ffff;
-	}
-
-	c2p_unsupported();
-	return 0;
-}
-
-
-    /*
-     *  Transpose operations on 8 32-bit words
-     */
-
-static inline void transp8(u32 d[], unsigned int n, unsigned int m)
-{
-	u32 mask = get_mask(n);
-
-	switch (m) {
-	case 1:
-		/* First n x 1 block */
-		_transp(d, 0, 1, n, mask);
-		/* Second n x 1 block */
-		_transp(d, 2, 3, n, mask);
-		/* Third n x 1 block */
-		_transp(d, 4, 5, n, mask);
-		/* Fourth n x 1 block */
-		_transp(d, 6, 7, n, mask);
-		return;
-
-	case 2:
-		/* First n x 2 block */
-		_transp(d, 0, 2, n, mask);
-		_transp(d, 1, 3, n, mask);
-		/* Second n x 2 block */
-		_transp(d, 4, 6, n, mask);
-		_transp(d, 5, 7, n, mask);
-		return;
-
-	case 4:
-		/* Single n x 4 block */
-		_transp(d, 0, 4, n, mask);
-		_transp(d, 1, 5, n, mask);
-		_transp(d, 2, 6, n, mask);
-		_transp(d, 3, 7, n, mask);
-		return;
-	}
-
-	c2p_unsupported();
-}
-
-
-    /*
-     *  Transpose operations on 4 32-bit words
-     */
-
-static inline void transp4(u32 d[], unsigned int n, unsigned int m)
-{
-	u32 mask = get_mask(n);
-
-	switch (m) {
-	case 1:
-		/* First n x 1 block */
-		_transp(d, 0, 1, n, mask);
-		/* Second n x 1 block */
-		_transp(d, 2, 3, n, mask);
-		return;
-
-	case 2:
-		/* Single n x 2 block */
-		_transp(d, 0, 2, n, mask);
-		_transp(d, 1, 3, n, mask);
-		return;
-	}
-
-	c2p_unsupported();
-}
-
-
-    /*
-     *  Transpose operations on 4 32-bit words (reverse order)
-     */
-
-static inline void transp4x(u32 d[], unsigned int n, unsigned int m)
-{
-	u32 mask = get_mask(n);
-
-	switch (m) {
-	case 2:
-		/* Single n x 2 block */
-		_transp(d, 2, 0, n, mask);
-		_transp(d, 3, 1, n, mask);
-		return;
-	}
-
-	c2p_unsupported();
-}
-
-
-    /*
-     *  Compose two values, using a bitmask as decision value
-     *  This is equivalent to (a & mask) | (b & ~mask)
-     */
-
-static inline u32 comp(u32 a, u32 b, u32 mask)
-{
-	return ((a ^ b) & mask) ^ b;
-}
diff --git a/drivers/video/c2p_iplan2.c b/drivers/video/c2p_iplan2.c
deleted file mode 100644
index 19156dc6158c..000000000000
--- a/drivers/video/c2p_iplan2.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  Fast C2P (Chunky-to-Planar) Conversion
- *
- *  Copyright (C) 2003-2008 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/unaligned.h>
-
-#include "c2p.h"
-#include "c2p_core.h"
-
-
-    /*
-     *  Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
-     *  containing
-     *    - 16 8-bit chunky pixels on input
-     *    - permutated planar data (2 planes per 32-bit word) on output
-     */
-
-static void c2p_16x8(u32 d[4])
-{
-	transp4(d, 8, 2);
-	transp4(d, 1, 2);
-	transp4x(d, 16, 2);
-	transp4x(d, 2, 2);
-	transp4(d, 4, 1);
-}
-
-
-    /*
-     *  Array containing the permutation indices of the planar data after c2p
-     */
-
-static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
-
-
-    /*
-     *  Store a full block of iplan2 data after c2p conversion
-     */
-
-static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
-{
-	int i;
-
-	for (i = 0; i < bpp/2; i++, dst += 4)
-		put_unaligned_be32(d[perm_c2p_16x8[i]], dst);
-}
-
-
-    /*
-     *  Store a partial block of iplan2 data after c2p conversion
-     */
-
-static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
-{
-	int i;
-
-	for (i = 0; i < bpp/2; i++, dst += 4)
-		put_unaligned_be32(comp(d[perm_c2p_16x8[i]],
-					get_unaligned_be32(dst), mask),
-				   dst);
-}
-
-
-    /*
-     *  c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
-     *  frame buffer with 2 bytes of interleave
-     *  @dst: Starting address of the planar frame buffer
-     *  @dx: Horizontal destination offset (in pixels)
-     *  @dy: Vertical destination offset (in pixels)
-     *  @width: Image width (in pixels)
-     *  @height: Image height (in pixels)
-     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
-     *  @src_nextline: Image offset to the next line (in bytes)
-     *  @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
-     */
-
-void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
-		u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
-{
-	union {
-		u8 pixels[16];
-		u32 words[4];
-	} d;
-	u32 dst_idx, first, last, w;
-	const u8 *c;
-	void *p;
-
-	dst += dy*dst_nextline+(dx & ~15)*bpp;
-	dst_idx = dx % 16;
-	first = 0xffffU >> dst_idx;
-	first |= first << 16;
-	last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
-	last |= last << 16;
-	while (height--) {
-		c = src;
-		p = dst;
-		w = width;
-		if (dst_idx+width <= 16) {
-			/* Single destination word */
-			first &= last;
-			memset(d.pixels, 0, sizeof(d));
-			memcpy(d.pixels+dst_idx, c, width);
-			c += width;
-			c2p_16x8(d.words);
-			store_iplan2_masked(p, bpp, d.words, first);
-			p += bpp*2;
-		} else {
-			/* Multiple destination words */
-			w = width;
-			/* Leading bits */
-			if (dst_idx) {
-				w = 16 - dst_idx;
-				memset(d.pixels, 0, dst_idx);
-				memcpy(d.pixels+dst_idx, c, w);
-				c += w;
-				c2p_16x8(d.words);
-				store_iplan2_masked(p, bpp, d.words, first);
-				p += bpp*2;
-				w = width-w;
-			}
-			/* Main chunk */
-			while (w >= 16) {
-				memcpy(d.pixels, c, 16);
-				c += 16;
-				c2p_16x8(d.words);
-				store_iplan2(p, bpp, d.words);
-				p += bpp*2;
-				w -= 16;
-			}
-			/* Trailing bits */
-			w %= 16;
-			if (w > 0) {
-				memcpy(d.pixels, c, w);
-				memset(d.pixels+w, 0, 16-w);
-				c2p_16x8(d.words);
-				store_iplan2_masked(p, bpp, d.words, last);
-			}
-		}
-		src += src_nextline;
-		dst += dst_nextline;
-	}
-}
-EXPORT_SYMBOL_GPL(c2p_iplan2);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/c2p_planar.c b/drivers/video/c2p_planar.c
deleted file mode 100644
index ec7ac8526f06..000000000000
--- a/drivers/video/c2p_planar.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- *  Fast C2P (Chunky-to-Planar) Conversion
- *
- *  Copyright (C) 2003-2008 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/unaligned.h>
-
-#include "c2p.h"
-#include "c2p_core.h"
-
-
-    /*
-     *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
-     *  containing
-     *    - 32 8-bit chunky pixels on input
-     *    - permutated planar data (1 plane per 32-bit word) on output
-     */
-
-static void c2p_32x8(u32 d[8])
-{
-	transp8(d, 16, 4);
-	transp8(d, 8, 2);
-	transp8(d, 4, 1);
-	transp8(d, 2, 4);
-	transp8(d, 1, 2);
-}
-
-
-    /*
-     *  Array containing the permutation indices of the planar data after c2p
-     */
-
-static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
-
-
-    /*
-     *  Store a full block of planar data after c2p conversion
-     */
-
-static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
-{
-	int i;
-
-	for (i = 0; i < bpp; i++, dst += dst_inc)
-		put_unaligned_be32(d[perm_c2p_32x8[i]], dst);
-}
-
-
-    /*
-     *  Store a partial block of planar data after c2p conversion
-     */
-
-static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
-				       u32 d[8], u32 mask)
-{
-	int i;
-
-	for (i = 0; i < bpp; i++, dst += dst_inc)
-		put_unaligned_be32(comp(d[perm_c2p_32x8[i]],
-					get_unaligned_be32(dst), mask),
-				   dst);
-}
-
-
-    /*
-     *  c2p_planar - Copy 8-bit chunky image data to a planar frame buffer
-     *  @dst: Starting address of the planar frame buffer
-     *  @dx: Horizontal destination offset (in pixels)
-     *  @dy: Vertical destination offset (in pixels)
-     *  @width: Image width (in pixels)
-     *  @height: Image height (in pixels)
-     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
-     *  @dst_nextplane: Frame buffer offset to the next plane (in bytes)
-     *  @src_nextline: Image offset to the next line (in bytes)
-     *  @bpp: Bits per pixel of the planar frame buffer (1-8)
-     */
-
-void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
-		u32 height, u32 dst_nextline, u32 dst_nextplane,
-		u32 src_nextline, u32 bpp)
-{
-	union {
-		u8 pixels[32];
-		u32 words[8];
-	} d;
-	u32 dst_idx, first, last, w;
-	const u8 *c;
-	void *p;
-
-	dst += dy*dst_nextline+(dx & ~31);
-	dst_idx = dx % 32;
-	first = 0xffffffffU >> dst_idx;
-	last = ~(0xffffffffU >> ((dst_idx+width) % 32));
-	while (height--) {
-		c = src;
-		p = dst;
-		w = width;
-		if (dst_idx+width <= 32) {
-			/* Single destination word */
-			first &= last;
-			memset(d.pixels, 0, sizeof(d));
-			memcpy(d.pixels+dst_idx, c, width);
-			c += width;
-			c2p_32x8(d.words);
-			store_planar_masked(p, dst_nextplane, bpp, d.words,
-					    first);
-			p += 4;
-		} else {
-			/* Multiple destination words */
-			w = width;
-			/* Leading bits */
-			if (dst_idx) {
-				w = 32 - dst_idx;
-				memset(d.pixels, 0, dst_idx);
-				memcpy(d.pixels+dst_idx, c, w);
-				c += w;
-				c2p_32x8(d.words);
-				store_planar_masked(p, dst_nextplane, bpp,
-						    d.words, first);
-				p += 4;
-				w = width-w;
-			}
-			/* Main chunk */
-			while (w >= 32) {
-				memcpy(d.pixels, c, 32);
-				c += 32;
-				c2p_32x8(d.words);
-				store_planar(p, dst_nextplane, bpp, d.words);
-				p += 4;
-				w -= 32;
-			}
-			/* Trailing bits */
-			w %= 32;
-			if (w > 0) {
-				memcpy(d.pixels, c, w);
-				memset(d.pixels+w, 0, 32-w);
-				c2p_32x8(d.words);
-				store_planar_masked(p, dst_nextplane, bpp,
-						    d.words, last);
-			}
-		}
-		src += src_nextline;
-		dst += dst_nextline;
-	}
-}
-EXPORT_SYMBOL_GPL(c2p_planar);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
deleted file mode 100644
index 65f7c15f5fdb..000000000000
--- a/drivers/video/carminefb.c
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * Frame buffer driver for the Carmine GPU.
- *
- * The driver configures the GPU as follows
- * - FB0 is display 0 with unique memory area
- * - FB1 is display 1 with unique memory area
- * - both display use 32 bit colors
- */
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include "carminefb.h"
-#include "carminefb_regs.h"
-
-#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
-#error  "The endianness of the target host has not been defined."
-#endif
-
-/*
- * The initial video mode can be supplied via two different ways:
- * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
- * - as an integer that picks the video mode from carmine_modedb[] (module
- *   option fb_mode)
- *
- * If nothing is used than the initial video mode will be the
- * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
- */
-#define CARMINEFB_DEFAULT_VIDEO_MODE	1
-
-static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
-module_param(fb_mode, uint, 0444);
-MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
-
-static char *fb_mode_str;
-module_param(fb_mode_str, charp, 0444);
-MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
-
-/*
- * Carminefb displays:
- * 0b000 None
- * 0b001 Display 0
- * 0b010 Display 1
- */
-static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
-module_param(fb_displays, int, 0444);
-MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
-
-struct carmine_hw {
-	void __iomem *v_regs;
-	void __iomem *screen_mem;
-	struct fb_info *fb[MAX_DISPLAY];
-};
-
-struct carmine_resolution {
-	u32 htp;
-	u32 hsp;
-	u32 hsw;
-	u32 hdp;
-	u32 vtr;
-	u32 vsp;
-	u32 vsw;
-	u32 vdp;
-	u32 disp_mode;
-};
-
-struct carmine_fb {
-	void __iomem *display_reg;
-	void __iomem *screen_base;
-	u32 smem_offset;
-	u32 cur_mode;
-	u32 new_mode;
-	struct carmine_resolution *res;
-	u32 pseudo_palette[16];
-};
-
-static struct fb_fix_screeninfo carminefb_fix = {
-	.id = "Carmine",
-	.type = FB_TYPE_PACKED_PIXELS,
-	.visual = FB_VISUAL_TRUECOLOR,
-	.accel = FB_ACCEL_NONE,
-};
-
-static const struct fb_videomode carmine_modedb[] = {
-	{
-		.name		= "640x480",
-		.xres		= 640,
-		.yres		= 480,
-	}, {
-		.name		= "800x600",
-		.xres		= 800,
-		.yres		= 600,
-	},
-};
-
-static struct carmine_resolution car_modes[] = {
-	{
-		/* 640x480 */
-		.htp = 800,
-		.hsp = 672,
-		.hsw = 96,
-		.hdp = 640,
-		.vtr = 525,
-		.vsp = 490,
-		.vsw = 2,
-		.vdp = 480,
-		.disp_mode = 0x1400,
-	},
-	{
-		/* 800x600 */
-		.htp = 1060,
-		.hsp = 864,
-		.hsw = 72,
-		.hdp = 800,
-		.vtr = 628,
-		.vsp = 601,
-		.vsw = 2,
-		.vdp = 600,
-		.disp_mode = 0x0d00,
-	}
-};
-
-static int carmine_find_mode(const struct fb_var_screeninfo *var)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(car_modes); i++)
-		if (car_modes[i].hdp == var->xres &&
-		    car_modes[i].vdp == var->yres)
-			return i;
-	return -EINVAL;
-}
-
-static void c_set_disp_reg(const struct carmine_fb *par,
-		u32 offset, u32 val)
-{
-	writel(val, par->display_reg + offset);
-}
-
-static u32 c_get_disp_reg(const struct carmine_fb *par,
-		u32 offset)
-{
-	return readl(par->display_reg + offset);
-}
-
-static void c_set_hw_reg(const struct carmine_hw *hw,
-		u32 offset, u32 val)
-{
-	writel(val, hw->v_regs + offset);
-}
-
-static u32 c_get_hw_reg(const struct carmine_hw *hw,
-		u32 offset)
-{
-	return readl(hw->v_regs + offset);
-}
-
-static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
-		unsigned blue, unsigned transp, struct fb_info *info)
-{
-	if (regno >= 16)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	transp >>= 8;
-
-	((__be32 *)info->pseudo_palette)[regno] = cpu_to_be32(transp << 24 |
-		red << 0 | green << 8 | blue << 16);
-	return 0;
-}
-
-static int carmine_check_var(struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-	int ret;
-
-	ret = carmine_find_mode(var);
-	if (ret < 0)
-		return ret;
-
-	if (var->grayscale || var->rotate || var->nonstd)
-		return -EINVAL;
-
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-
-	var->bits_per_pixel = 32;
-
-#ifdef __BIG_ENDIAN
-	var->transp.offset = 24;
-	var->red.offset = 0;
-	var->green.offset = 8;
-	var->blue.offset = 16;
-#else
-	var->transp.offset = 24;
-	var->red.offset = 16;
-	var->green.offset = 8;
-	var->blue.offset = 0;
-#endif
-
-	var->red.length = 8;
-	var->green.length = 8;
-	var->blue.length = 8;
-	var->transp.length = 8;
-
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-	return 0;
-}
-
-static void carmine_init_display_param(struct carmine_fb *par)
-{
-	u32 width;
-	u32 height;
-	u32 param;
-	u32 window_size;
-	u32 soffset = par->smem_offset;
-
-	c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
-			CARMINE_CURSOR0_PRIORITY_MASK |
-			CARMINE_CURSOR1_PRIORITY_MASK |
-			CARMINE_CURSOR_CUTZ_MASK);
-
-	/* Set default cursor position */
-	c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
-
-	/* Set default display mode */
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
-			CARMINE_EXT_CMODE_DIRECT24_RGBA);
-
-	/* Set default frame size to layer mode register */
-	width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
-	width = width << CARMINE_DISP_WIDTH_SHIFT;
-
-	height = par->res->vdp - 1;
-	param = width | height;
-
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
-
-	/* Set default pos and size */
-	window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
-	window_size |= par->res->hdp;
-
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
-
-	/* Set default origin address */
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
-
-	/* Set default display address */
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
-
-	/* Set default display position */
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
-
-	/* Set default blend mode */
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
-
-	/* default transparency mode */
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
-
-	/* Set default read skip parameter */
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
-
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
-
-	c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
-	c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
-}
-
-static void set_display_parameters(struct carmine_fb *par)
-{
-	u32 mode;
-	u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
-
-	/*
-	 * display timing. Parameters are decreased by one because hardware
-	 * spec is 0 to (n - 1)
-	 * */
-	hdp = par->res->hdp - 1;
-	vdp = par->res->vdp - 1;
-	htp = par->res->htp - 1;
-	hsp = par->res->hsp - 1;
-	hsw = par->res->hsw - 1;
-	vtr = par->res->vtr - 1;
-	vsp = par->res->vsp - 1;
-	vsw = par->res->vsw - 1;
-
-	c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
-			htp << CARMINE_DISP_HTP_SHIFT);
-	c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
-			(hdp << CARMINE_DISP_HDB_SHIFT)	| hdp);
-	c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
-			(vsw << CARMINE_DISP_VSW_SHIFT) |
-			(hsw << CARMINE_DISP_HSW_SHIFT) |
-			(hsp));
-	c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
-			vtr << CARMINE_DISP_VTR_SHIFT);
-	c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
-			(vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
-
-	/* clock */
-	mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
-	mode = (mode & ~CARMINE_DISP_DCM_MASK) |
-		(par->res->disp_mode & CARMINE_DISP_DCM_MASK);
-	/* enable video output and layer 0 */
-	mode |= CARMINE_DEN | CARMINE_L0E;
-	c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
-}
-
-static int carmine_set_par(struct fb_info *info)
-{
-	struct carmine_fb *par = info->par;
-	int ret;
-
-	ret = carmine_find_mode(&info->var);
-	if (ret < 0)
-		return ret;
-
-	par->new_mode = ret;
-	if (par->cur_mode != par->new_mode) {
-
-		par->cur_mode = par->new_mode;
-		par->res = &car_modes[par->new_mode];
-
-		carmine_init_display_param(par);
-		set_display_parameters(par);
-	}
-
-	info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
-	return 0;
-}
-
-static int init_hardware(struct carmine_hw *hw)
-{
-	u32 flags;
-	u32 loops;
-	u32 ret;
-
-	/* Initialize Carmine */
-	/* Sets internal clock */
-	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
-			CARMINE_DFLT_IP_CLOCK_ENABLE);
-
-	/* Video signal output is turned off */
-	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
-	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
-
-	/* Software reset */
-	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
-	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
-
-	/* I/O mode settings */
-	flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
-		CARMINE_DFLT_IP_DCTL_IO_CONT0;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
-			flags);
-
-	/* DRAM initial sequence */
-	flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
-			flags);
-
-	flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
-		CARMINE_DFLT_IP_DCTL_EMODE;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
-			flags);
-
-	flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
-		CARMINE_DFLT_IP_DCTL_SET_TIME2;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
-			flags);
-
-	flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
-		CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
-
-	flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
-			flags);
-
-	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
-		CARMINE_DFLT_IP_DCTL_STATES;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
-			flags);
-
-	/* Executes DLL reset */
-	if (CARMINE_DCTL_DLL_RESET) {
-		for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
-
-			ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
-					CARMINE_DCTL_REG_RSV0_STATES);
-			ret &= CARMINE_DCTL_REG_STATES_MASK;
-			if (!ret)
-				break;
-
-			mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
-		}
-
-		if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
-			printk(KERN_ERR "DRAM init failed\n");
-			return -EIO;
-		}
-	}
-
-	flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
-		CARMINE_DFLT_IP_DCTL_ADD;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
-
-	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
-		CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
-	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
-			flags);
-
-	/* Initialize the write back register */
-	c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
-			CARMINE_WB_REG_WBM_DEFAULT);
-
-	/* Initialize the Kottos registers */
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
-
-	/* Set DC offsets */
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
-	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
-	return 0;
-}
-
-static struct fb_ops carminefb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-
-	.fb_check_var	= carmine_check_var,
-	.fb_set_par	= carmine_set_par,
-	.fb_setcolreg	= carmine_setcolreg,
-};
-
-static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
-			    int smem_offset, struct device *device,
-			    struct fb_info **rinfo)
-{
-	int ret;
-	struct fb_info *info;
-	struct carmine_fb *par;
-
-	info = framebuffer_alloc(sizeof *par, device);
-	if (!info)
-		return -ENOMEM;
-
-	par = info->par;
-	par->display_reg = regs;
-	par->smem_offset = smem_offset;
-
-	info->screen_base = smem_base + smem_offset;
-	info->screen_size = CARMINE_DISPLAY_MEM;
-	info->fbops = &carminefb_ops;
-
-	info->fix = carminefb_fix;
-	info->pseudo_palette = par->pseudo_palette;
-	info->flags = FBINFO_DEFAULT;
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 1);
-	if (ret < 0)
-		goto err_free_fb;
-
-	if (fb_mode >= ARRAY_SIZE(carmine_modedb))
-		fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
-
-	par->cur_mode = par->new_mode = ~0;
-
-	ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
-			ARRAY_SIZE(carmine_modedb),
-			&carmine_modedb[fb_mode], 32);
-	if (!ret || ret == 4) {
-		ret = -EINVAL;
-		goto err_dealloc_cmap;
-	}
-
-	fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
-			&info->modelist);
-
-	ret = register_framebuffer(info);
-	if (ret < 0)
-		goto err_dealloc_cmap;
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	*rinfo = info;
-	return 0;
-
-err_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-err_free_fb:
-	framebuffer_release(info);
-	return ret;
-}
-
-static void cleanup_fb_device(struct fb_info *info)
-{
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-}
-
-static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	struct carmine_hw *hw;
-	struct device *device = &dev->dev;
-	struct fb_info *info;
-	int ret;
-
-	ret = pci_enable_device(dev);
-	if (ret)
-		return ret;
-
-	ret = -ENOMEM;
-	hw = kzalloc(sizeof *hw, GFP_KERNEL);
-	if (!hw)
-		goto err_enable_pci;
-
-	carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
-	carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
-
-	if (!request_mem_region(carminefb_fix.mmio_start,
-				carminefb_fix.mmio_len,
-				"carminefb regbase")) {
-		printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
-		ret = -EBUSY;
-		goto err_free_hw;
-	}
-	hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,
-			carminefb_fix.mmio_len);
-	if (!hw->v_regs) {
-		printk(KERN_ERR "carminefb: Can't remap %s register.\n",
-				carminefb_fix.id);
-		goto err_free_reg_mmio;
-	}
-
-	carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
-	carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
-
-	/* The memory area tends to be very large (256 MiB). Remap only what
-	 * is required for that largest resolution to avoid remaps at run
-	 * time
-	 */
-	if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
-		carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
-
-	else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
-		printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
-				"are required.", carminefb_fix.smem_len,
-				CARMINE_TOTAL_DIPLAY_MEM);
-		goto err_unmap_vregs;
-	}
-
-	if (!request_mem_region(carminefb_fix.smem_start,
-				carminefb_fix.smem_len,	"carminefb smem")) {
-		printk(KERN_ERR "carminefb: Can't reserve smem.\n");
-		goto err_unmap_vregs;
-	}
-
-	hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,
-			carminefb_fix.smem_len);
-	if (!hw->screen_mem) {
-		printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
-		goto err_reg_smem;
-	}
-
-	ret = init_hardware(hw);
-	if (ret)
-		goto err_unmap_screen;
-
-	info = NULL;
-	if (fb_displays & CARMINE_USE_DISPLAY0) {
-		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
-				hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
-				device, &info);
-		if (ret)
-			goto err_deinit_hw;
-	}
-
-	hw->fb[0] = info;
-
-	info = NULL;
-	if (fb_displays & CARMINE_USE_DISPLAY1) {
-		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
-				hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
-				device, &info);
-		if (ret)
-			goto err_cleanup_fb0;
-	}
-
-	hw->fb[1] = info;
-	info = NULL;
-
-	pci_set_drvdata(dev, hw);
-	return 0;
-
-err_cleanup_fb0:
-	cleanup_fb_device(hw->fb[0]);
-err_deinit_hw:
-	/* disable clock, etc */
-	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
-err_unmap_screen:
-	iounmap(hw->screen_mem);
-err_reg_smem:
-	release_mem_region(carminefb_fix.smem_start, carminefb_fix.smem_len);
-err_unmap_vregs:
-	iounmap(hw->v_regs);
-err_free_reg_mmio:
-	release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
-err_free_hw:
-	kfree(hw);
-err_enable_pci:
-	pci_disable_device(dev);
-	return ret;
-}
-
-static void carminefb_remove(struct pci_dev *dev)
-{
-	struct carmine_hw *hw = pci_get_drvdata(dev);
-	struct fb_fix_screeninfo fix;
-	int i;
-
-	/* in case we use only fb1 and not fb1 */
-	if (hw->fb[0])
-		fix = hw->fb[0]->fix;
-	else
-		fix = hw->fb[1]->fix;
-
-	/* deactivate display(s) and switch clocks */
-	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
-	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
-	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
-
-	for (i = 0; i < MAX_DISPLAY; i++)
-		cleanup_fb_device(hw->fb[i]);
-
-	iounmap(hw->screen_mem);
-	release_mem_region(fix.smem_start, fix.smem_len);
-	iounmap(hw->v_regs);
-	release_mem_region(fix.mmio_start, fix.mmio_len);
-
-	pci_disable_device(dev);
-	kfree(hw);
-}
-
-#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
-static struct pci_device_id carmine_devices[] = {
-{
-	PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
-	{0, 0, 0, 0, 0, 0, 0}
-};
-
-MODULE_DEVICE_TABLE(pci, carmine_devices);
-
-static struct pci_driver carmine_pci_driver = {
-	.name		= "carminefb",
-	.id_table	= carmine_devices,
-	.probe		= carminefb_probe,
-	.remove		= carminefb_remove,
-};
-
-static int __init carminefb_init(void)
-{
-	if (!(fb_displays &
-		(CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
-		printk(KERN_ERR "If you disable both displays than you don't "
-				"need the driver at all\n");
-		return -EINVAL;
-	}
-	return pci_register_driver(&carmine_pci_driver);
-}
-module_init(carminefb_init);
-
-static void __exit carminefb_cleanup(void)
-{
-	pci_unregister_driver(&carmine_pci_driver);
-}
-module_exit(carminefb_cleanup);
-
-MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
-MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/carminefb.h b/drivers/video/carminefb.h
deleted file mode 100644
index 05306de0c6b6..000000000000
--- a/drivers/video/carminefb.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef CARMINE_CARMINE_H
-#define CARMINE_CARMINE_H
-
-#define CARMINE_MEMORY_BAR	2
-#define CARMINE_CONFIG_BAR	3
-
-#define MAX_DISPLAY	2
-#define CARMINE_DISPLAY_MEM	(800 * 600 * 4)
-#define CARMINE_TOTAL_DIPLAY_MEM	(CARMINE_DISPLAY_MEM * MAX_DISPLAY)
-
-#define CARMINE_USE_DISPLAY0	(1 << 0)
-#define CARMINE_USE_DISPLAY1	(1 << 1)
-
-/*
- * This values work on the eval card. Custom boards may use different timings,
- * here an example :)
- */
-
-/* DRAM initialization values */
-#ifdef CONFIG_FB_CARMINE_DRAM_EVAL
-
-#define CARMINE_DFLT_IP_CLOCK_ENABLE		(0x03ff)
-#define CARMINE_DFLT_IP_DCTL_ADD		(0x05c3)
-#define CARMINE_DFLT_IP_DCTL_MODE		(0x0121)
-#define CARMINE_DFLT_IP_DCTL_EMODE		(0x8000)
-#define CARMINE_DFLT_IP_DCTL_SET_TIME1		(0x4749)
-#define CARMINE_DFLT_IP_DCTL_SET_TIME2		(0x2a22)
-#define CARMINE_DFLT_IP_DCTL_REFRESH		(0x0042)
-#define CARMINE_DFLT_IP_DCTL_STATES		(0x0003)
-#define CARMINE_DFLT_IP_DCTL_RESERVE0		(0x0020)
-#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH		(0x000f)
-#define CARMINE_DFLT_IP_DCTL_RESERVE2		(0x0000)
-#define CARMINE_DFLT_IP_DCTL_DDRIF1		(0x6646)
-#define CARMINE_DFLT_IP_DCTL_DDRIF2		(0x0055)
-#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST	(0x0021)
-#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST	(0x0002)
-#define CARMINE_DFLT_IP_DCTL_IO_CONT0		(0x0555)
-#define CARMINE_DFLT_IP_DCTL_IO_CONT1		(0x0555)
-#define CARMINE_DCTL_DLL_RESET			(1)
-#endif
-
-#ifdef CONFIG_CARMINE_DRAM_CUSTOM
-
-#define CARMINE_DFLT_IP_CLOCK_ENABLE		(0x03ff)
-#define CARMINE_DFLT_IP_DCTL_ADD		(0x03b2)
-#define CARMINE_DFLT_IP_DCTL_MODE		(0x0161)
-#define CARMINE_DFLT_IP_DCTL_EMODE		(0x8000)
-#define CARMINE_DFLT_IP_DCTL_SET_TIME1		(0x2628)
-#define CARMINE_DFLT_IP_DCTL_SET_TIME2		(0x1a09)
-#define CARMINE_DFLT_IP_DCTL_REFRESH		(0x00fe)
-#define CARMINE_DFLT_IP_DCTL_STATES		(0x0003)
-#define CARMINE_DFLT_IP_DCTL_RESERVE0		(0x0020)
-#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH		(0x000f)
-#define CARMINE_DFLT_IP_DCTL_RESERVE2		(0x0000)
-#define CARMINE_DFLT_IP_DCTL_DDRIF1		(0x0646)
-#define CARMINE_DFLT_IP_DCTL_DDRIF2		(0x55aa)
-#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST	(0x0061)
-#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST	(0x0002)
-#define CARMINE_DFLT_IP_DCTL_IO_CONT0		(0x0555)
-#define CARMINE_DFLT_IP_DCTL_IO_CONT1		(0x0555)
-#define CARMINE_DCTL_DLL_RESET			(1)
-#endif
-
-#endif
diff --git a/drivers/video/carminefb_regs.h b/drivers/video/carminefb_regs.h
deleted file mode 100644
index 045215600b73..000000000000
--- a/drivers/video/carminefb_regs.h
+++ /dev/null
@@ -1,159 +0,0 @@
-#ifndef _CARMINEFB_REGS_H
-#define _CARMINEFB_REGS_H
-
-#define CARMINE_OVERLAY_EXT_MODE	(0x00000002)
-#define CARMINE_GRAPH_REG		(0x00000000)
-#define CARMINE_DISP0_REG		(0x00100000)
-#define CARMINE_DISP1_REG		(0x00140000)
-#define CARMINE_WB_REG			(0x00180000)
-#define CARMINE_DCTL_REG		(0x00300000)
-#define CARMINE_CTL_REG			(0x00400000)
-#define CARMINE_WINDOW_MODE		(0x00000001)
-#define CARMINE_EXTEND_MODE		(CARMINE_WINDOW_MODE | \
-					CARMINE_OVERLAY_EXT_MODE)
-#define CARMINE_L0E			(1 << 16)
-#define CARMINE_L2E			(1 << 18)
-#define CARMINE_DEN			(1 << 31)
-
-#define CARMINE_EXT_CMODE_DIRECT24_RGBA		(0xC0000000)
-#define CARMINE_DCTL_REG_MODE_ADD		(0x00)
-#define CARMINE_DCTL_REG_SETTIME1_EMODE		(0x04)
-#define CARMINE_DCTL_REG_REFRESH_SETTIME2	(0x08)
-#define CARMINE_DCTL_REG_RSV0_STATES		(0x0C)
-#define CARMINE_DCTL_REG_RSV2_RSV1		(0x10)
-#define CARMINE_DCTL_REG_DDRIF2_DDRIF1		(0x14)
-#define CARMINE_DCTL_REG_IOCONT1_IOCONT0	(0x24)
-#define CARMINE_DCTL_REG_STATES_MASK		(0x000F)
-#define CARMINE_DCTL_INIT_WAIT_INTERVAL		(1)
-#define CARMINE_DCTL_INIT_WAIT_LIMIT		(5000)
-#define CARMINE_WB_REG_WBM_DEFAULT		(0x0001c020)
-#define CARMINE_DISP_REG_L0RM			(0x1880)
-#define CARMINE_DISP_REG_L0PX			(0x1884)
-#define CARMINE_DISP_REG_L0PY			(0x1888)
-#define CARMINE_DISP_REG_L2RM			(0x18A0)
-#define CARMINE_DISP_REG_L2PX			(0x18A4)
-#define CARMINE_DISP_REG_L2PY			(0x18A8)
-#define CARMINE_DISP_REG_L3RM			(0x18B0)
-#define CARMINE_DISP_REG_L3PX			(0x18B4)
-#define CARMINE_DISP_REG_L3PY			(0x18B8)
-#define CARMINE_DISP_REG_L4RM			(0x18C0)
-#define CARMINE_DISP_REG_L4PX			(0x18C4)
-#define CARMINE_DISP_REG_L4PY			(0x18C8)
-#define CARMINE_DISP_REG_L5RM			(0x18D0)
-#define CARMINE_DISP_REG_L5PX			(0x18D4)
-#define CARMINE_DISP_REG_L5PY			(0x18D8)
-#define CARMINE_DISP_REG_L6RM			(0x1924)
-#define CARMINE_DISP_REG_L6PX			(0x1928)
-#define CARMINE_DISP_REG_L6PY			(0x192C)
-#define CARMINE_DISP_REG_L7RM			(0x1964)
-#define CARMINE_DISP_REG_L7PX			(0x1968)
-#define CARMINE_DISP_REG_L7PY			(0x196C)
-#define CARMINE_WB_REG_WBM			(0x0004)
-#define CARMINE_DISP_HTP_SHIFT			(16)
-#define CARMINE_DISP_HDB_SHIFT			(16)
-#define CARMINE_DISP_HSW_SHIFT			(16)
-#define CARMINE_DISP_VSW_SHIFT			(24)
-#define CARMINE_DISP_VTR_SHIFT			(16)
-#define CARMINE_DISP_VDP_SHIFT			(16)
-#define CARMINE_CURSOR_CUTZ_MASK		(0x00000100)
-#define CARMINE_CURSOR0_PRIORITY_MASK		(0x00010000)
-#define CARMINE_CURSOR1_PRIORITY_MASK		(0x00020000)
-#define CARMINE_DISP_WIDTH_SHIFT		(16)
-#define CARMINE_DISP_WIN_H_SHIFT		(16)
-#define CARMINE_DISP_REG_H_TOTAL		(0x0004)
-#define CARMINE_DISP_REG_H_PERIOD		(0x0008)
-#define CARMINE_DISP_REG_V_H_W_H_POS		(0x000C)
-#define CARMINE_DISP_REG_V_TOTAL		(0x0010)
-#define CARMINE_DISP_REG_V_PERIOD_POS		(0x0014)
-#define CARMINE_DISP_REG_L0_MODE_W_H		(0x0020)
-#define CARMINE_DISP_REG_L0_ORG_ADR		(0x0024)
-#define CARMINE_DISP_REG_L0_DISP_ADR		(0x0028)
-#define CARMINE_DISP_REG_L0_DISP_POS		(0x002C)
-#define CARMINE_DISP_REG_L1_WIDTH		(0x0030)
-#define CARMINE_DISP_REG_L1_ORG_ADR		(0x0034)
-#define CARMINE_DISP_REG_L2_MODE_W_H		(0x0040)
-#define CARMINE_DISP_REG_L2_ORG_ADR1		(0x0044)
-#define CARMINE_DISP_REG_L2_DISP_ADR1		(0x0048)
-#define CARMINE_DISP_REG_L2_DISP_POS		(0x0054)
-#define CARMINE_DISP_REG_L3_MODE_W_H		(0x0058)
-#define CARMINE_DISP_REG_L3_ORG_ADR1		(0x005C)
-#define CARMINE_DISP_REG_L3_DISP_ADR1		(0x0060)
-#define CARMINE_DISP_REG_L3_DISP_POS		(0x006C)
-#define CARMINE_DISP_REG_L4_MODE_W_H		(0x0070)
-#define CARMINE_DISP_REG_L4_ORG_ADR1		(0x0074)
-#define CARMINE_DISP_REG_L4_DISP_ADR1		(0x0078)
-#define CARMINE_DISP_REG_L4_DISP_POS		(0x0084)
-#define CARMINE_DISP_REG_L5_MODE_W_H		(0x0088)
-#define CARMINE_DISP_REG_L5_ORG_ADR1		(0x008C)
-#define CARMINE_DISP_REG_L5_DISP_ADR1		(0x0090)
-#define CARMINE_DISP_REG_L5_DISP_POS		(0x009C)
-#define CARMINE_DISP_REG_CURSOR_MODE		(0x00A0)
-#define CARMINE_DISP_REG_CUR1_POS		(0x00A8)
-#define CARMINE_DISP_REG_CUR2_POS		(0x00B0)
-#define CARMINE_DISP_REG_C_TRANS		(0x00BC)
-#define CARMINE_DISP_REG_MLMR_TRANS		(0x00C0)
-#define CARMINE_DISP_REG_L0_EXT_MODE		(0x0110)
-#define CARMINE_DISP_REG_L0_WIN_POS		(0x0114)
-#define CARMINE_DISP_REG_L0_WIN_SIZE		(0x0118)
-#define CARMINE_DISP_REG_L1_EXT_MODE		(0x0120)
-#define CARMINE_DISP_REG_L1_WIN_POS		(0x0124)
-#define CARMINE_DISP_REG_L1_WIN_SIZE		(0x0128)
-#define CARMINE_DISP_REG_L2_EXT_MODE		(0x0130)
-#define CARMINE_DISP_REG_L2_WIN_POS		(0x0134)
-#define CARMINE_DISP_REG_L2_WIN_SIZE		(0x0138)
-#define CARMINE_DISP_REG_L3_EXT_MODE		(0x0140)
-#define CARMINE_DISP_REG_L3_WIN_POS		(0x0144)
-#define CARMINE_DISP_REG_L3_WIN_SIZE		(0x0148)
-#define CARMINE_DISP_REG_L4_EXT_MODE		(0x0150)
-#define CARMINE_DISP_REG_L4_WIN_POS		(0x0154)
-#define CARMINE_DISP_REG_L4_WIN_SIZE		(0x0158)
-#define CARMINE_DISP_REG_L5_EXT_MODE		(0x0160)
-#define CARMINE_DISP_REG_L5_WIN_POS		(0x0164)
-#define CARMINE_DISP_REG_L5_WIN_SIZE		(0x0168)
-#define CARMINE_DISP_REG_L6_EXT_MODE		(0x1918)
-#define CARMINE_DISP_REG_L6_WIN_POS		(0x191c)
-#define CARMINE_DISP_REG_L6_WIN_SIZE		(0x1920)
-#define CARMINE_DISP_REG_L7_EXT_MODE		(0x1958)
-#define CARMINE_DISP_REG_L7_WIN_POS		(0x195c)
-#define CARMINE_DISP_REG_L7_WIN_SIZE		(0x1960)
-#define CARMINE_DISP_REG_BLEND_MODE_L0		(0x00B4)
-#define CARMINE_DISP_REG_BLEND_MODE_L1		(0x0188)
-#define CARMINE_DISP_REG_BLEND_MODE_L2		(0x018C)
-#define CARMINE_DISP_REG_BLEND_MODE_L3		(0x0190)
-#define CARMINE_DISP_REG_BLEND_MODE_L4		(0x0194)
-#define CARMINE_DISP_REG_BLEND_MODE_L5		(0x0198)
-#define CARMINE_DISP_REG_BLEND_MODE_L6		(0x1990)
-#define CARMINE_DISP_REG_BLEND_MODE_L7		(0x1994)
-#define CARMINE_DISP_REG_L0_TRANS		(0x01A0)
-#define CARMINE_DISP_REG_L1_TRANS		(0x01A4)
-#define CARMINE_DISP_REG_L2_TRANS		(0x01A8)
-#define CARMINE_DISP_REG_L3_TRANS		(0x01AC)
-#define CARMINE_DISP_REG_L4_TRANS		(0x01B0)
-#define CARMINE_DISP_REG_L5_TRANS		(0x01B4)
-#define CARMINE_DISP_REG_L6_TRANS		(0x1998)
-#define CARMINE_DISP_REG_L7_TRANS		(0x199c)
-#define CARMINE_EXTEND_MODE_MASK		(0x00000003)
-#define CARMINE_DISP_DCM_MASK			(0x0000FFFF)
-#define CARMINE_DISP_REG_DCM1			(0x0100)
-#define CARMINE_DISP_WIDTH_UNIT			(64)
-#define CARMINE_DISP_REG_L6_MODE_W_H		(0x1900)
-#define CARMINE_DISP_REG_L6_ORG_ADR1		(0x1904)
-#define CARMINE_DISP_REG_L6_DISP_ADR0		(0x1908)
-#define CARMINE_DISP_REG_L6_DISP_POS		(0x1914)
-#define CARMINE_DISP_REG_L7_MODE_W_H		(0x1940)
-#define CARMINE_DISP_REG_L7_ORG_ADR1		(0x1944)
-#define CARMINE_DISP_REG_L7_DISP_ADR0		(0x1948)
-#define CARMINE_DISP_REG_L7_DISP_POS		(0x1954)
-#define CARMINE_CTL_REG_CLOCK_ENABLE		(0x000C)
-#define CARMINE_CTL_REG_SOFTWARE_RESET		(0x0010)
-#define CARMINE_CTL_REG_IST_MASK_ALL		(0x07FFFFFF)
-#define CARMINE_GRAPH_REG_VRINTM		(0x00028064)
-#define CARMINE_GRAPH_REG_VRERRM		(0x0002806C)
-#define CARMINE_GRAPH_REG_DC_OFFSET_PX		(0x0004005C)
-#define CARMINE_GRAPH_REG_DC_OFFSET_PY		(0x00040060)
-#define CARMINE_GRAPH_REG_DC_OFFSET_LX		(0x00040064)
-#define CARMINE_GRAPH_REG_DC_OFFSET_LY		(0x00040068)
-#define CARMINE_GRAPH_REG_DC_OFFSET_TX		(0x0004006C)
-#define CARMINE_GRAPH_REG_DC_OFFSET_TY		(0x00040070)
-
-#endif
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
deleted file mode 100644
index bcb57235fcc7..000000000000
--- a/drivers/video/cfbcopyarea.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- *  Generic function for frame buffer with packed pixels of any depth.
- *
- *      Copyright (C)  1999-2005 James Simmons <jsimmons@www.infradead.org>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- *
- * NOTES:
- *
- *  This is for cfb packed pixels. Iplan and such are incorporated in the
- *  drivers that need them.
- *
- *  FIXME
- *
- *  Also need to add code to deal with cards endians that are different than
- *  the native cpu endians. I also need to deal with MSB position in the word.
- *
- *  The two functions or copying forward and backward could be split up like
- *  the ones for filling, i.e. in aligned and unaligned versions. This would
- *  help moving some redundant computations and branches out of the loop, too.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <asm/types.h>
-#include <asm/io.h>
-#include "fb_draw.h"
-
-#if BITS_PER_LONG == 32
-#  define FB_WRITEL fb_writel
-#  define FB_READL  fb_readl
-#else
-#  define FB_WRITEL fb_writeq
-#  define FB_READL  fb_readq
-#endif
-
-    /*
-     *  Generic bitwise copy algorithm
-     */
-
-static void
-bitcpy(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx,
-		const unsigned long __iomem *src, unsigned src_idx, int bits,
-		unsigned n, u32 bswapmask)
-{
-	unsigned long first, last;
-	int const shift = dst_idx-src_idx;
-
-#if 0
-	/*
-	 * If you suspect bug in this function, compare it with this simple
-	 * memmove implementation.
-	 */
-	fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8,
-		   (char *)src + ((src_idx & (bits - 1))) / 8, n / 8);
-	return;
-#endif
-
-	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
-	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
-
-	if (!shift) {
-		// Same alignment for source and dest
-
-		if (dst_idx+n <= bits) {
-			// Single word
-			if (last)
-				first &= last;
-			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
-		} else {
-			// Multiple destination words
-
-			// Leading bits
-			if (first != ~0UL) {
-				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
-				dst++;
-				src++;
-				n -= bits - dst_idx;
-			}
-
-			// Main chunk
-			n /= bits;
-			while (n >= 8) {
-				FB_WRITEL(FB_READL(src++), dst++);
-				FB_WRITEL(FB_READL(src++), dst++);
-				FB_WRITEL(FB_READL(src++), dst++);
-				FB_WRITEL(FB_READL(src++), dst++);
-				FB_WRITEL(FB_READL(src++), dst++);
-				FB_WRITEL(FB_READL(src++), dst++);
-				FB_WRITEL(FB_READL(src++), dst++);
-				FB_WRITEL(FB_READL(src++), dst++);
-				n -= 8;
-			}
-			while (n--)
-				FB_WRITEL(FB_READL(src++), dst++);
-
-			// Trailing bits
-			if (last)
-				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
-		}
-	} else {
-		/* Different alignment for source and dest */
-		unsigned long d0, d1;
-		int m;
-
-		int const left = shift & (bits - 1);
-		int const right = -shift & (bits - 1);
-
-		if (dst_idx+n <= bits) {
-			// Single destination word
-			if (last)
-				first &= last;
-			d0 = FB_READL(src);
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			if (shift > 0) {
-				// Single source word
-				d0 <<= left;
-			} else if (src_idx+n <= bits) {
-				// Single source word
-				d0 >>= right;
-			} else {
-				// 2 source words
-				d1 = FB_READL(src + 1);
-				d1 = fb_rev_pixels_in_long(d1, bswapmask);
-				d0 = d0 >> right | d1 << left;
-			}
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
-		} else {
-			// Multiple destination words
-			/** We must always remember the last value read, because in case
-			SRC and DST overlap bitwise (e.g. when moving just one pixel in
-			1bpp), we always collect one full long for DST and that might
-			overlap with the current long from SRC. We store this value in
-			'd0'. */
-			d0 = FB_READL(src++);
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			// Leading bits
-			if (shift > 0) {
-				// Single source word
-				d1 = d0;
-				d0 <<= left;
-				n -= bits - dst_idx;
-			} else {
-				// 2 source words
-				d1 = FB_READL(src++);
-				d1 = fb_rev_pixels_in_long(d1, bswapmask);
-
-				d0 = d0 >> right | d1 << left;
-				n -= bits - dst_idx;
-			}
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
-			d0 = d1;
-			dst++;
-
-			// Main chunk
-			m = n % bits;
-			n /= bits;
-			while ((n >= 4) && !bswapmask) {
-				d1 = FB_READL(src++);
-				FB_WRITEL(d0 >> right | d1 << left, dst++);
-				d0 = d1;
-				d1 = FB_READL(src++);
-				FB_WRITEL(d0 >> right | d1 << left, dst++);
-				d0 = d1;
-				d1 = FB_READL(src++);
-				FB_WRITEL(d0 >> right | d1 << left, dst++);
-				d0 = d1;
-				d1 = FB_READL(src++);
-				FB_WRITEL(d0 >> right | d1 << left, dst++);
-				d0 = d1;
-				n -= 4;
-			}
-			while (n--) {
-				d1 = FB_READL(src++);
-				d1 = fb_rev_pixels_in_long(d1, bswapmask);
-				d0 = d0 >> right | d1 << left;
-				d0 = fb_rev_pixels_in_long(d0, bswapmask);
-				FB_WRITEL(d0, dst++);
-				d0 = d1;
-			}
-
-			// Trailing bits
-			if (m) {
-				if (m <= bits - right) {
-					// Single source word
-					d0 >>= right;
-				} else {
-					// 2 source words
-					d1 = FB_READL(src);
-					d1 = fb_rev_pixels_in_long(d1,
-								bswapmask);
-					d0 = d0 >> right | d1 << left;
-				}
-				d0 = fb_rev_pixels_in_long(d0, bswapmask);
-				FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
-			}
-		}
-	}
-}
-
-    /*
-     *  Generic bitwise copy algorithm, operating backward
-     */
-
-static void
-bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx,
-		const unsigned long __iomem *src, unsigned src_idx, int bits,
-		unsigned n, u32 bswapmask)
-{
-	unsigned long first, last;
-	int shift;
-
-#if 0
-	/*
-	 * If you suspect bug in this function, compare it with this simple
-	 * memmove implementation.
-	 */
-	fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8,
-		   (char *)src + ((src_idx & (bits - 1))) / 8, n / 8);
-	return;
-#endif
-
-	dst += (dst_idx + n - 1) / bits;
-	src += (src_idx + n - 1) / bits;
-	dst_idx = (dst_idx + n - 1) % bits;
-	src_idx = (src_idx + n - 1) % bits;
-
-	shift = dst_idx-src_idx;
-
-	first = ~fb_shifted_pixels_mask_long(p, (dst_idx + 1) % bits, bswapmask);
-	last = fb_shifted_pixels_mask_long(p, (bits + dst_idx + 1 - n) % bits, bswapmask);
-
-	if (!shift) {
-		// Same alignment for source and dest
-
-		if ((unsigned long)dst_idx+1 >= n) {
-			// Single word
-			if (first)
-				last &= first;
-			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
-		} else {
-			// Multiple destination words
-
-			// Leading bits
-			if (first) {
-				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
-				dst--;
-				src--;
-				n -= dst_idx+1;
-			}
-
-			// Main chunk
-			n /= bits;
-			while (n >= 8) {
-				FB_WRITEL(FB_READL(src--), dst--);
-				FB_WRITEL(FB_READL(src--), dst--);
-				FB_WRITEL(FB_READL(src--), dst--);
-				FB_WRITEL(FB_READL(src--), dst--);
-				FB_WRITEL(FB_READL(src--), dst--);
-				FB_WRITEL(FB_READL(src--), dst--);
-				FB_WRITEL(FB_READL(src--), dst--);
-				FB_WRITEL(FB_READL(src--), dst--);
-				n -= 8;
-			}
-			while (n--)
-				FB_WRITEL(FB_READL(src--), dst--);
-
-			// Trailing bits
-			if (last != -1UL)
-				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
-		}
-	} else {
-		// Different alignment for source and dest
-		unsigned long d0, d1;
-		int m;
-
-		int const left = shift & (bits-1);
-		int const right = -shift & (bits-1);
-
-		if ((unsigned long)dst_idx+1 >= n) {
-			// Single destination word
-			if (first)
-				last &= first;
-			d0 = FB_READL(src);
-			if (shift < 0) {
-				// Single source word
-				d0 >>= right;
-			} else if (1+(unsigned long)src_idx >= n) {
-				// Single source word
-				d0 <<= left;
-			} else {
-				// 2 source words
-				d1 = FB_READL(src - 1);
-				d1 = fb_rev_pixels_in_long(d1, bswapmask);
-				d0 = d0 << left | d1 >> right;
-			}
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
-		} else {
-			// Multiple destination words
-			/** We must always remember the last value read, because in case
-			SRC and DST overlap bitwise (e.g. when moving just one pixel in
-			1bpp), we always collect one full long for DST and that might
-			overlap with the current long from SRC. We store this value in
-			'd0'. */
-
-			d0 = FB_READL(src--);
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			// Leading bits
-			if (shift < 0) {
-				// Single source word
-				d1 = d0;
-				d0 >>= right;
-			} else {
-				// 2 source words
-				d1 = FB_READL(src--);
-				d1 = fb_rev_pixels_in_long(d1, bswapmask);
-				d0 = d0 << left | d1 >> right;
-			}
-			d0 = fb_rev_pixels_in_long(d0, bswapmask);
-			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
-			d0 = d1;
-			dst--;
-			n -= dst_idx+1;
-
-			// Main chunk
-			m = n % bits;
-			n /= bits;
-			while ((n >= 4) && !bswapmask) {
-				d1 = FB_READL(src--);
-				FB_WRITEL(d0 << left | d1 >> right, dst--);
-				d0 = d1;
-				d1 = FB_READL(src--);
-				FB_WRITEL(d0 << left | d1 >> right, dst--);
-				d0 = d1;
-				d1 = FB_READL(src--);
-				FB_WRITEL(d0 << left | d1 >> right, dst--);
-				d0 = d1;
-				d1 = FB_READL(src--);
-				FB_WRITEL(d0 << left | d1 >> right, dst--);
-				d0 = d1;
-				n -= 4;
-			}
-			while (n--) {
-				d1 = FB_READL(src--);
-				d1 = fb_rev_pixels_in_long(d1, bswapmask);
-				d0 = d0 << left | d1 >> right;
-				d0 = fb_rev_pixels_in_long(d0, bswapmask);
-				FB_WRITEL(d0, dst--);
-				d0 = d1;
-			}
-
-			// Trailing bits
-			if (m) {
-				if (m <= bits - left) {
-					// Single source word
-					d0 <<= left;
-				} else {
-					// 2 source words
-					d1 = FB_READL(src);
-					d1 = fb_rev_pixels_in_long(d1,
-								bswapmask);
-					d0 = d0 << left | d1 >> right;
-				}
-				d0 = fb_rev_pixels_in_long(d0, bswapmask);
-				FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
-			}
-		}
-	}
-}
-
-void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
-{
-	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
-	u32 height = area->height, width = area->width;
-	unsigned long const bits_per_line = p->fix.line_length*8u;
-	unsigned long __iomem *base = NULL;
-	int bits = BITS_PER_LONG, bytes = bits >> 3;
-	unsigned dst_idx = 0, src_idx = 0, rev_copy = 0;
-	u32 bswapmask = fb_compute_bswapmask(p);
-
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	/* if the beginning of the target area might overlap with the end of
-	the source area, be have to copy the area reverse. */
-	if ((dy == sy && dx > sx) || (dy > sy)) {
-		dy += height;
-		sy += height;
-		rev_copy = 1;
-	}
-
-	// split the base of the framebuffer into a long-aligned address and the
-	// index of the first bit
-	base = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
-	dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
-	// add offset of source and target area
-	dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
-	src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
-
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-
-	if (rev_copy) {
-		while (height--) {
-			dst_idx -= bits_per_line;
-			src_idx -= bits_per_line;
-			bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits,
-				base + (src_idx / bits), src_idx % bits, bits,
-				width*p->var.bits_per_pixel, bswapmask);
-		}
-	} else {
-		while (height--) {
-			bitcpy(p, base + (dst_idx / bits), dst_idx % bits,
-				base + (src_idx / bits), src_idx % bits, bits,
-				width*p->var.bits_per_pixel, bswapmask);
-			dst_idx += bits_per_line;
-			src_idx += bits_per_line;
-		}
-	}
-}
-
-EXPORT_SYMBOL(cfb_copyarea);
-
-MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
-MODULE_DESCRIPTION("Generic software accelerated copyarea");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
deleted file mode 100644
index ba9f58b2a5e8..000000000000
--- a/drivers/video/cfbfillrect.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- *  Generic fillrect for frame buffers with packed pixels of any depth.
- *
- *      Copyright (C)  2000 James Simmons (jsimmons@linux-fbdev.org)
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- *
- * NOTES:
- *
- *  Also need to add code to deal with cards endians that are different than
- *  the native cpu endians. I also need to deal with MSB position in the word.
- *
- */
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <asm/types.h>
-#include "fb_draw.h"
-
-#if BITS_PER_LONG == 32
-#  define FB_WRITEL fb_writel
-#  define FB_READL  fb_readl
-#else
-#  define FB_WRITEL fb_writeq
-#  define FB_READL  fb_readq
-#endif
-
-    /*
-     *  Aligned pattern fill using 32/64-bit memory accesses
-     */
-
-static void
-bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
-		unsigned long pat, unsigned n, int bits, u32 bswapmask)
-{
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
-	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
-
-	if (dst_idx+n <= bits) {
-		// Single word
-		if (last)
-			first &= last;
-		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
-	} else {
-		// Multiple destination words
-
-		// Leading bits
-		if (first!= ~0UL) {
-			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
-			dst++;
-			n -= bits - dst_idx;
-		}
-
-		// Main chunk
-		n /= bits;
-		while (n >= 8) {
-			FB_WRITEL(pat, dst++);
-			FB_WRITEL(pat, dst++);
-			FB_WRITEL(pat, dst++);
-			FB_WRITEL(pat, dst++);
-			FB_WRITEL(pat, dst++);
-			FB_WRITEL(pat, dst++);
-			FB_WRITEL(pat, dst++);
-			FB_WRITEL(pat, dst++);
-			n -= 8;
-		}
-		while (n--)
-			FB_WRITEL(pat, dst++);
-
-		// Trailing bits
-		if (last)
-			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
-	}
-}
-
-
-    /*
-     *  Unaligned generic pattern fill using 32/64-bit memory accesses
-     *  The pattern must have been expanded to a full 32/64-bit value
-     *  Left/right are the appropriate shifts to convert to the pattern to be
-     *  used for the next 32/64-bit word
-     */
-
-static void
-bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
-		  unsigned long pat, int left, int right, unsigned n, int bits)
-{
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
-	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
-
-	if (dst_idx+n <= bits) {
-		// Single word
-		if (last)
-			first &= last;
-		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
-	} else {
-		// Multiple destination words
-		// Leading bits
-		if (first) {
-			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
-			dst++;
-			pat = pat << left | pat >> right;
-			n -= bits - dst_idx;
-		}
-
-		// Main chunk
-		n /= bits;
-		while (n >= 4) {
-			FB_WRITEL(pat, dst++);
-			pat = pat << left | pat >> right;
-			FB_WRITEL(pat, dst++);
-			pat = pat << left | pat >> right;
-			FB_WRITEL(pat, dst++);
-			pat = pat << left | pat >> right;
-			FB_WRITEL(pat, dst++);
-			pat = pat << left | pat >> right;
-			n -= 4;
-		}
-		while (n--) {
-			FB_WRITEL(pat, dst++);
-			pat = pat << left | pat >> right;
-		}
-
-		// Trailing bits
-		if (last)
-			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
-	}
-}
-
-    /*
-     *  Aligned pattern invert using 32/64-bit memory accesses
-     */
-static void
-bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
-		    int dst_idx, unsigned long pat, unsigned n, int bits,
-		    u32 bswapmask)
-{
-	unsigned long val = pat, dat;
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
-	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
-
-	if (dst_idx+n <= bits) {
-		// Single word
-		if (last)
-			first &= last;
-		dat = FB_READL(dst);
-		FB_WRITEL(comp(dat ^ val, dat, first), dst);
-	} else {
-		// Multiple destination words
-		// Leading bits
-		if (first!=0UL) {
-			dat = FB_READL(dst);
-			FB_WRITEL(comp(dat ^ val, dat, first), dst);
-			dst++;
-			n -= bits - dst_idx;
-		}
-
-		// Main chunk
-		n /= bits;
-		while (n >= 8) {
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-			n -= 8;
-		}
-		while (n--) {
-			FB_WRITEL(FB_READL(dst) ^ val, dst);
-			dst++;
-		}
-		// Trailing bits
-		if (last) {
-			dat = FB_READL(dst);
-			FB_WRITEL(comp(dat ^ val, dat, last), dst);
-		}
-	}
-}
-
-
-    /*
-     *  Unaligned generic pattern invert using 32/64-bit memory accesses
-     *  The pattern must have been expanded to a full 32/64-bit value
-     *  Left/right are the appropriate shifts to convert to the pattern to be
-     *  used for the next 32/64-bit word
-     */
-
-static void
-bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
-		      int dst_idx, unsigned long pat, int left, int right,
-		      unsigned n, int bits)
-{
-	unsigned long first, last, dat;
-
-	if (!n)
-		return;
-
-	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
-	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
-
-	if (dst_idx+n <= bits) {
-		// Single word
-		if (last)
-			first &= last;
-		dat = FB_READL(dst);
-		FB_WRITEL(comp(dat ^ pat, dat, first), dst);
-	} else {
-		// Multiple destination words
-
-		// Leading bits
-		if (first != 0UL) {
-			dat = FB_READL(dst);
-			FB_WRITEL(comp(dat ^ pat, dat, first), dst);
-			dst++;
-			pat = pat << left | pat >> right;
-			n -= bits - dst_idx;
-		}
-
-		// Main chunk
-		n /= bits;
-		while (n >= 4) {
-			FB_WRITEL(FB_READL(dst) ^ pat, dst);
-			dst++;
-			pat = pat << left | pat >> right;
-			FB_WRITEL(FB_READL(dst) ^ pat, dst);
-			dst++;
-			pat = pat << left | pat >> right;
-			FB_WRITEL(FB_READL(dst) ^ pat, dst);
-			dst++;
-			pat = pat << left | pat >> right;
-			FB_WRITEL(FB_READL(dst) ^ pat, dst);
-			dst++;
-			pat = pat << left | pat >> right;
-			n -= 4;
-		}
-		while (n--) {
-			FB_WRITEL(FB_READL(dst) ^ pat, dst);
-			dst++;
-			pat = pat << left | pat >> right;
-		}
-
-		// Trailing bits
-		if (last) {
-			dat = FB_READL(dst);
-			FB_WRITEL(comp(dat ^ pat, dat, last), dst);
-		}
-	}
-}
-
-void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
-{
-	unsigned long pat, pat2, fg;
-	unsigned long width = rect->width, height = rect->height;
-	int bits = BITS_PER_LONG, bytes = bits >> 3;
-	u32 bpp = p->var.bits_per_pixel;
-	unsigned long __iomem *dst;
-	int dst_idx, left;
-
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
-	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
-		fg = ((u32 *) (p->pseudo_palette))[rect->color];
-	else
-		fg = rect->color;
-
-	pat = pixel_to_pat(bpp, fg);
-
-	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
-	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
-	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
-	/* FIXME For now we support 1-32 bpp only */
-	left = bits % bpp;
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-	if (!left) {
-		u32 bswapmask = fb_compute_bswapmask(p);
-		void (*fill_op32)(struct fb_info *p,
-				  unsigned long __iomem *dst, int dst_idx,
-		                  unsigned long pat, unsigned n, int bits,
-				  u32 bswapmask) = NULL;
-
-		switch (rect->rop) {
-		case ROP_XOR:
-			fill_op32 = bitfill_aligned_rev;
-			break;
-		case ROP_COPY:
-			fill_op32 = bitfill_aligned;
-			break;
-		default:
-			printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
-			fill_op32 = bitfill_aligned;
-			break;
-		}
-		while (height--) {
-			dst += dst_idx >> (ffs(bits) - 1);
-			dst_idx &= (bits - 1);
-			fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
-				  bswapmask);
-			dst_idx += p->fix.line_length*8;
-		}
-	} else {
-		int right, r;
-		void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
-				int dst_idx, unsigned long pat, int left,
-				int right, unsigned n, int bits) = NULL;
-#ifdef __LITTLE_ENDIAN
-		right = left;
-		left = bpp - right;
-#else
-		right = bpp - left;
-#endif
-		switch (rect->rop) {
-		case ROP_XOR:
-			fill_op = bitfill_unaligned_rev;
-			break;
-		case ROP_COPY:
-			fill_op = bitfill_unaligned;
-			break;
-		default:
-			printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
-			fill_op = bitfill_unaligned;
-			break;
-		}
-		while (height--) {
-			dst += dst_idx / bits;
-			dst_idx &= (bits - 1);
-			r = dst_idx % bpp;
-			/* rotate pattern to the correct start position */
-			pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
-			fill_op(p, dst, dst_idx, pat2, left, right,
-				width*bpp, bits);
-			dst_idx += p->fix.line_length*8;
-		}
-	}
-}
-
-EXPORT_SYMBOL(cfb_fillrect);
-
-MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
-MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
deleted file mode 100644
index a2bb276a8b24..000000000000
--- a/drivers/video/cfbimgblt.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- *  Generic BitBLT function for frame buffer with packed pixels of any depth.
- *
- *      Copyright (C)  June 1999 James Simmons
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- *
- * NOTES:
- *
- *    This function copys a image from system memory to video memory. The
- *  image can be a bitmap where each 0 represents the background color and
- *  each 1 represents the foreground color. Great for font handling. It can
- *  also be a color image. This is determined by image_depth. The color image
- *  must be laid out exactly in the same format as the framebuffer. Yes I know
- *  their are cards with hardware that coverts images of various depths to the
- *  framebuffer depth. But not every card has this. All images must be rounded
- *  up to the nearest byte. For example a bitmap 12 bits wide must be two 
- *  bytes width. 
- *
- *  Tony: 
- *  Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API.  This speeds 
- *  up the code significantly.
- *  
- *  Code for depths not multiples of BITS_PER_LONG is still kludgy, which is
- *  still processed a bit at a time.   
- *
- *  Also need to add code to deal with cards endians that are different than
- *  the native cpu endians. I also need to deal with MSB position in the word.
- */
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <asm/types.h>
-#include "fb_draw.h"
-
-#define DEBUG
-
-#ifdef DEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-static const u32 cfb_tab8_be[] = {
-    0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
-    0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
-    0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
-    0xffff0000,0xffff00ff,0xffffff00,0xffffffff
-};
-
-static const u32 cfb_tab8_le[] = {
-    0x00000000,0xff000000,0x00ff0000,0xffff0000,
-    0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
-    0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
-    0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
-};
-
-static const u32 cfb_tab16_be[] = {
-    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
-};
-
-static const u32 cfb_tab16_le[] = {
-    0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
-};
-
-static const u32 cfb_tab32[] = {
-	0x00000000, 0xffffffff
-};
-
-#define FB_WRITEL fb_writel
-#define FB_READL  fb_readl
-
-static inline void color_imageblit(const struct fb_image *image, 
-				   struct fb_info *p, u8 __iomem *dst1, 
-				   u32 start_index,
-				   u32 pitch_index)
-{
-	/* Draw the penguin */
-	u32 __iomem *dst, *dst2;
-	u32 color = 0, val, shift;
-	int i, n, bpp = p->var.bits_per_pixel;
-	u32 null_bits = 32 - bpp;
-	u32 *palette = (u32 *) p->pseudo_palette;
-	const u8 *src = image->data;
-	u32 bswapmask = fb_compute_bswapmask(p);
-
-	dst2 = (u32 __iomem *) dst1;
-	for (i = image->height; i--; ) {
-		n = image->width;
-		dst = (u32 __iomem *) dst1;
-		shift = 0;
-		val = 0;
-		
-		if (start_index) {
-			u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
-						start_index, bswapmask);
-			val = FB_READL(dst) & start_mask;
-			shift = start_index;
-		}
-		while (n--) {
-			if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
-			    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
-				color = palette[*src];
-			else
-				color = *src;
-			color <<= FB_LEFT_POS(p, bpp);
-			val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
-			if (shift >= null_bits) {
-				FB_WRITEL(val, dst++);
-	
-				val = (shift == null_bits) ? 0 : 
-					FB_SHIFT_LOW(p, color, 32 - shift);
-			}
-			shift += bpp;
-			shift &= (32 - 1);
-			src++;
-		}
-		if (shift) {
-			u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
-						bswapmask);
-
-			FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
-		}
-		dst1 += p->fix.line_length;
-		if (pitch_index) {
-			dst2 += p->fix.line_length;
-			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
-
-			start_index += pitch_index;
-			start_index &= 32 - 1;
-		}
-	}
-}
-
-static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, 
-				  u8 __iomem *dst1, u32 fgcolor,
-				  u32 bgcolor, 
-				  u32 start_index,
-				  u32 pitch_index)
-{
-	u32 shift, color = 0, bpp = p->var.bits_per_pixel;
-	u32 __iomem *dst, *dst2;
-	u32 val, pitch = p->fix.line_length;
-	u32 null_bits = 32 - bpp;
-	u32 spitch = (image->width+7)/8;
-	const u8 *src = image->data, *s;
-	u32 i, j, l;
-	u32 bswapmask = fb_compute_bswapmask(p);
-
-	dst2 = (u32 __iomem *) dst1;
-	fgcolor <<= FB_LEFT_POS(p, bpp);
-	bgcolor <<= FB_LEFT_POS(p, bpp);
-
-	for (i = image->height; i--; ) {
-		shift = val = 0;
-		l = 8;
-		j = image->width;
-		dst = (u32 __iomem *) dst1;
-		s = src;
-
-		/* write leading bits */
-		if (start_index) {
-			u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
-						start_index, bswapmask);
-			val = FB_READL(dst) & start_mask;
-			shift = start_index;
-		}
-
-		while (j--) {
-			l--;
-			color = (*s & (1 << l)) ? fgcolor : bgcolor;
-			val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
-			
-			/* Did the bitshift spill bits to the next long? */
-			if (shift >= null_bits) {
-				FB_WRITEL(val, dst++);
-				val = (shift == null_bits) ? 0 :
-					FB_SHIFT_LOW(p, color, 32 - shift);
-			}
-			shift += bpp;
-			shift &= (32 - 1);
-			if (!l) { l = 8; s++; }
-		}
-
-		/* write trailing bits */
- 		if (shift) {
-			u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
-						bswapmask);
-
-			FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
-		}
-		
-		dst1 += pitch;
-		src += spitch;	
-		if (pitch_index) {
-			dst2 += pitch;
-			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
-			start_index += pitch_index;
-			start_index &= 32 - 1;
-		}
-		
-	}
-}
-
-/*
- * fast_imageblit - optimized monochrome color expansion
- *
- * Only if:  bits_per_pixel == 8, 16, or 32
- *           image->width is divisible by pixel/dword (ppw);
- *           fix->line_legth is divisible by 4;
- *           beginning and end of a scanline is dword aligned
- */
-static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, 
-				  u8 __iomem *dst1, u32 fgcolor, 
-				  u32 bgcolor) 
-{
-	u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
-	u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
-	u32 bit_mask, end_mask, eorx, shift;
-	const char *s = image->data, *src;
-	u32 __iomem *dst;
-	const u32 *tab = NULL;
-	int i, j, k;
-
-	switch (bpp) {
-	case 8:
-		tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
-		break;
-	case 16:
-		tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
-		break;
-	case 32:
-	default:
-		tab = cfb_tab32;
-		break;
-	}
-
-	for (i = ppw-1; i--; ) {
-		fgx <<= bpp;
-		bgx <<= bpp;
-		fgx |= fgcolor;
-		bgx |= bgcolor;
-	}
-	
-	bit_mask = (1 << ppw) - 1;
-	eorx = fgx ^ bgx;
-	k = image->width/ppw;
-
-	for (i = image->height; i--; ) {
-		dst = (u32 __iomem *) dst1, shift = 8; src = s;
-		
-		for (j = k; j--; ) {
-			shift -= ppw;
-			end_mask = tab[(*src >> shift) & bit_mask];
-			FB_WRITEL((end_mask & eorx)^bgx, dst++);
-			if (!shift) { shift = 8; src++; }		
-		}
-		dst1 += p->fix.line_length;
-		s += spitch;
-	}
-}	
-	
-void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
-{
-	u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
-	u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
-	u32 width = image->width;
-	u32 dx = image->dx, dy = image->dy;
-	u8 __iomem *dst1;
-
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
-	start_index = bitstart & (32 - 1);
-	pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
-
-	bitstart /= 8;
-	bitstart &= ~(bpl - 1);
-	dst1 = p->screen_base + bitstart;
-
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-
-	if (image->depth == 1) {
-		if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
-		    p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-			fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
-			bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
-		} else {
-			fgcolor = image->fg_color;
-			bgcolor = image->bg_color;
-		}	
-		
-		if (32 % bpp == 0 && !start_index && !pitch_index && 
-		    ((width & (32/bpp-1)) == 0) &&
-		    bpp >= 8 && bpp <= 32) 			
-			fast_imageblit(image, p, dst1, fgcolor, bgcolor);
-		else 
-			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
-					start_index, pitch_index);
-	} else
-		color_imageblit(image, p, dst1, start_index, pitch_index);
-}
-
-EXPORT_SYMBOL(cfb_imageblit);
-
-MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
-MODULE_DESCRIPTION("Generic software accelerated imaging drawing");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
deleted file mode 100644
index c79745b136bb..000000000000
--- a/drivers/video/cg14.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/* cg14.c: CGFOURTEEN frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			 unsigned, struct fb_info *);
-
-static int cg14_mmap(struct fb_info *, struct vm_area_struct *);
-static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
-static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops cg14_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= cg14_setcolreg,
-	.fb_pan_display		= cg14_pan_display,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_mmap		= cg14_mmap,
-	.fb_ioctl		= cg14_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-#define CG14_MCR_INTENABLE_SHIFT	7
-#define CG14_MCR_INTENABLE_MASK		0x80
-#define CG14_MCR_VIDENABLE_SHIFT	6
-#define CG14_MCR_VIDENABLE_MASK		0x40
-#define CG14_MCR_PIXMODE_SHIFT		4
-#define CG14_MCR_PIXMODE_MASK		0x30
-#define CG14_MCR_TMR_SHIFT		2
-#define CG14_MCR_TMR_MASK		0x0c
-#define CG14_MCR_TMENABLE_SHIFT		1
-#define CG14_MCR_TMENABLE_MASK		0x02
-#define CG14_MCR_RESET_SHIFT		0
-#define CG14_MCR_RESET_MASK		0x01
-#define CG14_REV_REVISION_SHIFT		4
-#define CG14_REV_REVISION_MASK		0xf0
-#define CG14_REV_IMPL_SHIFT		0
-#define CG14_REV_IMPL_MASK		0x0f
-#define CG14_VBR_FRAMEBASE_SHIFT	12
-#define CG14_VBR_FRAMEBASE_MASK		0x00fff000
-#define CG14_VMCR1_SETUP_SHIFT		0
-#define CG14_VMCR1_SETUP_MASK		0x000001ff
-#define CG14_VMCR1_VCONFIG_SHIFT	9
-#define CG14_VMCR1_VCONFIG_MASK		0x00000e00
-#define CG14_VMCR2_REFRESH_SHIFT	0
-#define CG14_VMCR2_REFRESH_MASK		0x00000001
-#define CG14_VMCR2_TESTROWCNT_SHIFT	1
-#define CG14_VMCR2_TESTROWCNT_MASK	0x00000002
-#define CG14_VMCR2_FBCONFIG_SHIFT	2
-#define CG14_VMCR2_FBCONFIG_MASK	0x0000000c
-#define CG14_VCR_REFRESHREQ_SHIFT	0
-#define CG14_VCR_REFRESHREQ_MASK	0x000003ff
-#define CG14_VCR1_REFRESHENA_SHIFT	10
-#define CG14_VCR1_REFRESHENA_MASK	0x00000400
-#define CG14_VCA_CAD_SHIFT		0
-#define CG14_VCA_CAD_MASK		0x000003ff
-#define CG14_VCA_VERS_SHIFT		10
-#define CG14_VCA_VERS_MASK		0x00000c00
-#define CG14_VCA_RAMSPEED_SHIFT		12
-#define CG14_VCA_RAMSPEED_MASK		0x00001000
-#define CG14_VCA_8MB_SHIFT		13
-#define CG14_VCA_8MB_MASK		0x00002000
-
-#define CG14_MCR_PIXMODE_8		0
-#define CG14_MCR_PIXMODE_16		2
-#define CG14_MCR_PIXMODE_32		3
-
-struct cg14_regs{
-	u8 mcr;	/* Master Control Reg */
-	u8 ppr;	/* Packed Pixel Reg */
-	u8 tms[2];	/* Test Mode Status Regs */
-	u8 msr;	/* Master Status Reg */
-	u8 fsr;	/* Fault Status Reg */
-	u8 rev;	/* Revision & Impl */
-	u8 ccr;	/* Clock Control Reg */
-	u32 tmr;	/* Test Mode Read Back */
-	u8 mod;	/* Monitor Operation Data Reg */
-	u8 acr;	/* Aux Control */
-	u8 xxx0[6];
-	u16 hct;	/* Hor Counter */
-	u16 vct;	/* Vert Counter */
-	u16 hbs;	/* Hor Blank Start */
-	u16 hbc;	/* Hor Blank Clear */
-	u16 hss;	/* Hor Sync Start */
-	u16 hsc;	/* Hor Sync Clear */
-	u16 csc;	/* Composite Sync Clear */
-	u16 vbs;	/* Vert Blank Start */
-	u16 vbc;	/* Vert Blank Clear */
-	u16 vss;	/* Vert Sync Start */
-	u16 vsc;	/* Vert Sync Clear */
-	u16 xcs;
-	u16 xcc;
-	u16 fsa;	/* Fault Status Address */
-	u16 adr;	/* Address Registers */
-	u8 xxx1[0xce];
-	u8 pcg[0x100]; /* Pixel Clock Generator */
-	u32 vbr;	/* Frame Base Row */
-	u32 vmcr;	/* VBC Master Control */
-	u32 vcr;	/* VBC refresh */
-	u32 vca;	/* VBC Config */
-};
-
-#define CG14_CCR_ENABLE	0x04
-#define CG14_CCR_SELECT 0x02	/* HW/Full screen */
-
-struct cg14_cursor {
-	u32 cpl0[32];	/* Enable plane 0 */
-	u32 cpl1[32];  /* Color selection plane */
-	u8 ccr;	/* Cursor Control Reg */
-	u8 xxx0[3];
-	u16 cursx;	/* Cursor x,y position */
-	u16 cursy;	/* Cursor x,y position */
-	u32 color0;
-	u32 color1;
-	u32 xxx1[0x1bc];
-	u32 cpl0i[32];	/* Enable plane 0 autoinc */
-	u32 cpl1i[32]; /* Color selection autoinc */
-};
-
-struct cg14_dac {
-	u8 addr;	/* Address Register */
-	u8 xxx0[255];
-	u8 glut;	/* Gamma table */
-	u8 xxx1[255];
-	u8 select;	/* Register Select */
-	u8 xxx2[255];
-	u8 mode;	/* Mode Register */
-};
-
-struct cg14_xlut{
-	u8 x_xlut [256];
-	u8 x_xlutd [256];
-	u8 xxx0[0x600];
-	u8 x_xlut_inc [256];
-	u8 x_xlutd_inc [256];
-};
-
-/* Color look up table (clut) */
-/* Each one of these arrays hold the color lookup table (for 256
- * colors) for each MDI page (I assume then there should be 4 MDI
- * pages, I still wonder what they are.  I have seen NeXTStep split
- * the screen in four parts, while operating in 24 bits mode.  Each
- * integer holds 4 values: alpha value (transparency channel, thanks
- * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
- *
- * I currently use the clut instead of the Xlut
- */
-struct cg14_clut {
-	u32 c_clut [256];
-	u32 c_clutd [256];    /* i wonder what the 'd' is for */
-	u32 c_clut_inc [256];
-	u32 c_clutd_inc [256];
-};
-
-#define CG14_MMAP_ENTRIES	16
-
-struct cg14_par {
-	spinlock_t		lock;
-	struct cg14_regs	__iomem *regs;
-	struct cg14_clut	__iomem *clut;
-	struct cg14_cursor	__iomem *cursor;
-
-	u32			flags;
-#define CG14_FLAG_BLANKED	0x00000001
-
-	unsigned long		iospace;
-
-	struct sbus_mmap_map	mmap_map[CG14_MMAP_ENTRIES];
-
-	int			mode;
-	int			ramsize;
-};
-
-static void __cg14_reset(struct cg14_par *par)
-{
-	struct cg14_regs __iomem *regs = par->regs;
-	u8 val;
-
-	val = sbus_readb(&regs->mcr);
-	val &= ~(CG14_MCR_PIXMODE_MASK);
-	sbus_writeb(val, &regs->mcr);
-}
-
-static int cg14_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct cg14_par *par = (struct cg14_par *) info->par;
-	unsigned long flags;
-
-	/* We just use this to catch switches out of
-	 * graphics mode.
-	 */
-	spin_lock_irqsave(&par->lock, flags);
-	__cg14_reset(par);
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	if (var->xoffset || var->yoffset || var->vmode)
-		return -EINVAL;
-	return 0;
-}
-
-/**
- *      cg14_setcolreg - Optional function. Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *      @green: The green value which can be up to 16 bits wide
- *      @blue:  The blue value which can be up to 16 bits wide.
- *      @transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- */
-static int cg14_setcolreg(unsigned regno,
-			  unsigned red, unsigned green, unsigned blue,
-			  unsigned transp, struct fb_info *info)
-{
-	struct cg14_par *par = (struct cg14_par *) info->par;
-	struct cg14_clut __iomem *clut = par->clut;
-	unsigned long flags;
-	u32 val;
-
-	if (regno >= 256)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	val = (red | (green << 8) | (blue << 16));
-
-	spin_lock_irqsave(&par->lock, flags);
-	sbus_writel(val, &clut->c_clut[regno]);
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct cg14_par *par = (struct cg14_par *) info->par;
-
-	return sbusfb_mmap_helper(par->mmap_map,
-				  info->fix.smem_start, info->fix.smem_len,
-				  par->iospace, vma);
-}
-
-static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	struct cg14_par *par = (struct cg14_par *) info->par;
-	struct cg14_regs __iomem *regs = par->regs;
-	struct mdi_cfginfo kmdi, __user *mdii;
-	unsigned long flags;
-	int cur_mode, mode, ret = 0;
-
-	switch (cmd) {
-	case MDI_RESET:
-		spin_lock_irqsave(&par->lock, flags);
-		__cg14_reset(par);
-		spin_unlock_irqrestore(&par->lock, flags);
-		break;
-
-	case MDI_GET_CFGINFO:
-		memset(&kmdi, 0, sizeof(kmdi));
-
-		spin_lock_irqsave(&par->lock, flags);
-		kmdi.mdi_type = FBTYPE_MDICOLOR;
-		kmdi.mdi_height = info->var.yres;
-		kmdi.mdi_width = info->var.xres;
-		kmdi.mdi_mode = par->mode;
-		kmdi.mdi_pixfreq = 72; /* FIXME */
-		kmdi.mdi_size = par->ramsize;
-		spin_unlock_irqrestore(&par->lock, flags);
-
-		mdii = (struct mdi_cfginfo __user *) arg;
-		if (copy_to_user(mdii, &kmdi, sizeof(kmdi)))
-			ret = -EFAULT;
-		break;
-
-	case MDI_SET_PIXELMODE:
-		if (get_user(mode, (int __user *) arg)) {
-			ret = -EFAULT;
-			break;
-		}
-
-		spin_lock_irqsave(&par->lock, flags);
-		cur_mode = sbus_readb(&regs->mcr);
-		cur_mode &= ~CG14_MCR_PIXMODE_MASK;
-		switch(mode) {
-		case MDI_32_PIX:
-			cur_mode |= (CG14_MCR_PIXMODE_32 <<
-				     CG14_MCR_PIXMODE_SHIFT);
-			break;
-
-		case MDI_16_PIX:
-			cur_mode |= (CG14_MCR_PIXMODE_16 <<
-				     CG14_MCR_PIXMODE_SHIFT);
-			break;
-
-		case MDI_8_PIX:
-			break;
-
-		default:
-			ret = -ENOSYS;
-			break;
-		}
-		if (!ret) {
-			sbus_writeb(cur_mode, &regs->mcr);
-			par->mode = mode;
-		}
-		spin_unlock_irqrestore(&par->lock, flags);
-		break;
-
-	default:
-		ret = sbusfb_ioctl_helper(cmd, arg, info,
-					  FBTYPE_MDICOLOR, 8,
-					  info->fix.smem_len);
-		break;
-	}
-
-	return ret;
-}
-
-/*
- *  Initialisation
- */
-
-static void cg14_init_fix(struct fb_info *info, int linebytes,
-			  struct device_node *dp)
-{
-	const char *name = dp->name;
-
-	strlcpy(info->fix.id, name, sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = linebytes;
-
-	info->fix.accel = FB_ACCEL_SUN_CG14;
-}
-
-static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = {
-	{
-		.voff	= CG14_REGS,
-		.poff	= 0x80000000,
-		.size	= 0x1000
-	},
-	{
-		.voff	= CG14_XLUT,
-		.poff	= 0x80003000,
-		.size	= 0x1000
-	},
-	{
-		.voff	= CG14_CLUT1,
-		.poff	= 0x80004000,
-		.size	= 0x1000
-	},
-	{
-		.voff	= CG14_CLUT2,
-		.poff	= 0x80005000,
-		.size	= 0x1000
-	},
-	{
-		.voff	= CG14_CLUT3,
-		.poff	= 0x80006000,
-		.size	= 0x1000
-	},
-	{
-		.voff	= CG3_MMAP_OFFSET - 0x7000,
-		.poff	= 0x80000000,
-		.size	= 0x7000
-	},
-	{
-		.voff	= CG3_MMAP_OFFSET,
-		.poff	= 0x00000000,
-		.size	= SBUS_MMAP_FBSIZE(1)
-	},
-	{
-		.voff	= MDI_CURSOR_MAP,
-		.poff	= 0x80001000,
-		.size	= 0x1000
-	},
-	{
-		.voff	= MDI_CHUNKY_BGR_MAP,
-		.poff	= 0x01000000,
-		.size	= 0x400000
-	},
-	{
-		.voff	= MDI_PLANAR_X16_MAP,
-		.poff	= 0x02000000,
-		.size	= 0x200000
-	},
-	{
-		.voff	= MDI_PLANAR_C16_MAP,
-		.poff	= 0x02800000,
-		.size	= 0x200000
-	},
-	{
-		.voff	= MDI_PLANAR_X32_MAP,
-		.poff	= 0x03000000,
-		.size	= 0x100000
-	},
-	{
-		.voff	= MDI_PLANAR_B32_MAP,
-		.poff	= 0x03400000,
-		.size	= 0x100000
-	},
-	{
-		.voff	= MDI_PLANAR_G32_MAP,
-		.poff	= 0x03800000,
-		.size	= 0x100000
-	},
-	{
-		.voff	= MDI_PLANAR_R32_MAP,
-		.poff	= 0x03c00000,
-		.size	= 0x100000
-	},
-	{ .size = 0 }
-};
-
-static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
-			    struct cg14_par *par)
-{
-	if (par->regs)
-		of_iounmap(&op->resource[0],
-			   par->regs, sizeof(struct cg14_regs));
-	if (par->clut)
-		of_iounmap(&op->resource[0],
-			   par->clut, sizeof(struct cg14_clut));
-	if (par->cursor)
-		of_iounmap(&op->resource[0],
-			   par->cursor, sizeof(struct cg14_cursor));
-	if (info->screen_base)
-		of_iounmap(&op->resource[1],
-			   info->screen_base, info->fix.smem_len);
-}
-
-static int cg14_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct cg14_par *par;
-	int is_8mb, linebytes, i, err;
-
-	info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-
-	sbusfb_fill_var(&info->var, dp, 8);
-	info->var.red.length = 8;
-	info->var.green.length = 8;
-	info->var.blue.length = 8;
-
-	linebytes = of_getintprop_default(dp, "linebytes",
-					  info->var.xres);
-	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
-
-	if (!strcmp(dp->parent->name, "sbus") ||
-	    !strcmp(dp->parent->name, "sbi")) {
-		info->fix.smem_start = op->resource[0].start;
-		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
-	} else {
-		info->fix.smem_start = op->resource[1].start;
-		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
-	}
-
-	par->regs = of_ioremap(&op->resource[0], 0,
-			       sizeof(struct cg14_regs), "cg14 regs");
-	par->clut = of_ioremap(&op->resource[0], CG14_CLUT1,
-			       sizeof(struct cg14_clut), "cg14 clut");
-	par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
-				 sizeof(struct cg14_cursor), "cg14 cursor");
-
-	info->screen_base = of_ioremap(&op->resource[1], 0,
-				       info->fix.smem_len, "cg14 ram");
-
-	if (!par->regs || !par->clut || !par->cursor || !info->screen_base)
-		goto out_unmap_regs;
-
-	is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
-		  (8 * 1024 * 1024));
-
-	BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
-		
-	memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
-
-	for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
-		struct sbus_mmap_map *map = &par->mmap_map[i];
-
-		if (!map->size)
-			break;
-		if (map->poff & 0x80000000)
-			map->poff = (map->poff & 0x7fffffff) +
-				(op->resource[0].start -
-				 op->resource[1].start);
-		if (is_8mb &&
-		    map->size >= 0x100000 &&
-		    map->size <= 0x400000)
-			map->size *= 2;
-	}
-
-	par->mode = MDI_8_PIX;
-	par->ramsize = (is_8mb ? 0x800000 : 0x400000);
-
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	info->fbops = &cg14_ops;
-
-	__cg14_reset(par);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0))
-		goto out_unmap_regs;
-
-	fb_set_cmap(&info->cmap, info);
-
-	cg14_init_fix(info, linebytes, dp);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_dealloc_cmap;
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: cgfourteen at %lx:%lx, %dMB\n",
-	       dp->full_name,
-	       par->iospace, info->fix.smem_start,
-	       par->ramsize >> 20);
-
-	return 0;
-
-out_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-out_unmap_regs:
-	cg14_unmap_regs(op, info, par);
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int cg14_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct cg14_par *par = info->par;
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	cg14_unmap_regs(op, info, par);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id cg14_match[] = {
-	{
-		.name = "cgfourteen",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, cg14_match);
-
-static struct platform_driver cg14_driver = {
-	.driver = {
-		.name = "cg14",
-		.owner = THIS_MODULE,
-		.of_match_table = cg14_match,
-	},
-	.probe		= cg14_probe,
-	.remove		= cg14_remove,
-};
-
-static int __init cg14_init(void)
-{
-	if (fb_get_options("cg14fb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&cg14_driver);
-}
-
-static void __exit cg14_exit(void)
-{
-	platform_driver_unregister(&cg14_driver);
-}
-
-module_init(cg14_init);
-module_exit(cg14_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
deleted file mode 100644
index 64a89d5747ed..000000000000
--- a/drivers/video/cg3.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/* cg3.c: CGTHREE frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			 unsigned, struct fb_info *);
-static int cg3_blank(int, struct fb_info *);
-
-static int cg3_mmap(struct fb_info *, struct vm_area_struct *);
-static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops cg3_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= cg3_setcolreg,
-	.fb_blank		= cg3_blank,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_mmap		= cg3_mmap,
-	.fb_ioctl		= cg3_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-
-/* Control Register Constants */
-#define CG3_CR_ENABLE_INTS      0x80
-#define CG3_CR_ENABLE_VIDEO     0x40
-#define CG3_CR_ENABLE_TIMING    0x20
-#define CG3_CR_ENABLE_CURCMP    0x10
-#define CG3_CR_XTAL_MASK        0x0c
-#define CG3_CR_DIVISOR_MASK     0x03
-
-/* Status Register Constants */
-#define CG3_SR_PENDING_INT      0x80
-#define CG3_SR_RES_MASK         0x70
-#define CG3_SR_1152_900_76_A    0x40
-#define CG3_SR_1152_900_76_B    0x60
-#define CG3_SR_ID_MASK          0x0f
-#define CG3_SR_ID_COLOR         0x01
-#define CG3_SR_ID_MONO          0x02
-#define CG3_SR_ID_MONO_ECL      0x03
-
-enum cg3_type {
-	CG3_AT_66HZ = 0,
-	CG3_AT_76HZ,
-	CG3_RDI
-};
-
-struct bt_regs {
-	u32 addr;
-	u32 color_map;
-	u32 control;
-	u32 cursor;
-};
-
-struct cg3_regs {
-	struct bt_regs	cmap;
-	u8	control;
-	u8	status;
-	u8	cursor_start;
-	u8	cursor_end;
-	u8	h_blank_start;
-	u8	h_blank_end;
-	u8	h_sync_start;
-	u8	h_sync_end;
-	u8	comp_sync_end;
-	u8	v_blank_start_high;
-	u8	v_blank_start_low;
-	u8	v_blank_end;
-	u8	v_sync_start;
-	u8	v_sync_end;
-	u8	xfer_holdoff_start;
-	u8	xfer_holdoff_end;
-};
-
-/* Offset of interesting structures in the OBIO space */
-#define CG3_REGS_OFFSET	     0x400000UL
-#define CG3_RAM_OFFSET	     0x800000UL
-
-struct cg3_par {
-	spinlock_t		lock;
-	struct cg3_regs		__iomem *regs;
-	u32			sw_cmap[((256 * 3) + 3) / 4];
-
-	u32			flags;
-#define CG3_FLAG_BLANKED	0x00000001
-#define CG3_FLAG_RDI		0x00000002
-
-	unsigned long		which_io;
-};
-
-/**
- *      cg3_setcolreg - Optional function. Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *      @green: The green value which can be up to 16 bits wide
- *      @blue:  The blue value which can be up to 16 bits wide.
- *      @transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- *
- * The cg3 palette is loaded with 4 color values at each time
- * so you end up with: (rgb)(r), (gb)(rg), (b)(rgb), and so on.
- * We keep a sw copy of the hw cmap to assist us in this esoteric
- * loading procedure.
- */
-static int cg3_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	struct cg3_par *par = (struct cg3_par *) info->par;
-	struct bt_regs __iomem *bt = &par->regs->cmap;
-	unsigned long flags;
-	u32 *p32;
-	u8 *p8;
-	int count;
-
-	if (regno >= 256)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	p8 = (u8 *)par->sw_cmap + (regno * 3);
-	p8[0] = red;
-	p8[1] = green;
-	p8[2] = blue;
-
-#define D4M3(x) ((((x)>>2)<<1) + ((x)>>2))      /* (x/4)*3 */
-#define D4M4(x) ((x)&~0x3)                      /* (x/4)*4 */
-
-	count = 3;
-	p32 = &par->sw_cmap[D4M3(regno)];
-	sbus_writel(D4M4(regno), &bt->addr);
-	while (count--)
-		sbus_writel(*p32++, &bt->color_map);
-
-#undef D4M3
-#undef D4M4
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-/**
- *      cg3_blank - Optional function.  Blanks the display.
- *      @blank_mode: the blank mode we want.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int cg3_blank(int blank, struct fb_info *info)
-{
-	struct cg3_par *par = (struct cg3_par *) info->par;
-	struct cg3_regs __iomem *regs = par->regs;
-	unsigned long flags;
-	u8 val;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		val = sbus_readb(&regs->control);
-		val |= CG3_CR_ENABLE_VIDEO;
-		sbus_writeb(val, &regs->control);
-		par->flags &= ~CG3_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		val = sbus_readb(&regs->control);
-		val &= ~CG3_CR_ENABLE_VIDEO;
-		sbus_writeb(val, &regs->control);
-		par->flags |= CG3_FLAG_BLANKED;
-		break;
-	}
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static struct sbus_mmap_map cg3_mmap_map[] = {
-	{
-		.voff	= CG3_MMAP_OFFSET,
-		.poff	= CG3_RAM_OFFSET,
-		.size	= SBUS_MMAP_FBSIZE(1)
-	},
-	{ .size = 0 }
-};
-
-static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct cg3_par *par = (struct cg3_par *)info->par;
-
-	return sbusfb_mmap_helper(cg3_mmap_map,
-				  info->fix.smem_start, info->fix.smem_len,
-				  par->which_io,
-				  vma);
-}
-
-static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	return sbusfb_ioctl_helper(cmd, arg, info,
-				   FBTYPE_SUN3COLOR, 8, info->fix.smem_len);
-}
-
-/*
- *  Initialisation
- */
-
-static void cg3_init_fix(struct fb_info *info, int linebytes,
-			 struct device_node *dp)
-{
-	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = linebytes;
-
-	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
-}
-
-static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
-				    struct device_node *dp)
-{
-	const char *params;
-	char *p;
-	int ww, hh;
-
-	params = of_get_property(dp, "params", NULL);
-	if (params) {
-		ww = simple_strtoul(params, &p, 10);
-		if (ww && *p == 'x') {
-			hh = simple_strtoul(p + 1, &p, 10);
-			if (hh && *p == '-') {
-				if (var->xres != ww ||
-				    var->yres != hh) {
-					var->xres = var->xres_virtual = ww;
-					var->yres = var->yres_virtual = hh;
-				}
-			}
-		}
-	}
-}
-
-static u8 cg3regvals_66hz[] = {	/* 1152 x 900, 66 Hz */
-	0x14, 0xbb,	0x15, 0x2b,	0x16, 0x04,	0x17, 0x14,
-	0x18, 0xae,	0x19, 0x03,	0x1a, 0xa8,	0x1b, 0x24,
-	0x1c, 0x01,	0x1d, 0x05,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x20,	0
-};
-
-static u8 cg3regvals_76hz[] = {	/* 1152 x 900, 76 Hz */
-	0x14, 0xb7,	0x15, 0x27,	0x16, 0x03,	0x17, 0x0f,
-	0x18, 0xae,	0x19, 0x03,	0x1a, 0xae,	0x1b, 0x2a,
-	0x1c, 0x01,	0x1d, 0x09,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x24,	0
-};
-
-static u8 cg3regvals_rdi[] = {	/* 640 x 480, cgRDI */
-	0x14, 0x70,	0x15, 0x20,	0x16, 0x08,	0x17, 0x10,
-	0x18, 0x06,	0x19, 0x02,	0x1a, 0x31,	0x1b, 0x51,
-	0x1c, 0x06,	0x1d, 0x0c,	0x1e, 0xff,	0x1f, 0x01,
-	0x10, 0x22,	0
-};
-
-static u8 *cg3_regvals[] = {
-	cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi
-};
-
-static u_char cg3_dacvals[] = {
-	4, 0xff,	5, 0x00,	6, 0x70,	7, 0x00,	0
-};
-
-static int cg3_do_default_mode(struct cg3_par *par)
-{
-	enum cg3_type type;
-	u8 *p;
-
-	if (par->flags & CG3_FLAG_RDI)
-		type = CG3_RDI;
-	else {
-		u8 status = sbus_readb(&par->regs->status), mon;
-		if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) {
-			mon = status & CG3_SR_RES_MASK;
-			if (mon == CG3_SR_1152_900_76_A ||
-			    mon == CG3_SR_1152_900_76_B)
-				type = CG3_AT_76HZ;
-			else
-				type = CG3_AT_66HZ;
-		} else {
-			printk(KERN_ERR "cgthree: can't handle SR %02x\n",
-			       status);
-			return -EINVAL;
-		}
-	}
-
-	for (p = cg3_regvals[type]; *p; p += 2) {
-		u8 __iomem *regp = &((u8 __iomem *)par->regs)[p[0]];
-		sbus_writeb(p[1], regp);
-	}
-	for (p = cg3_dacvals; *p; p += 2) {
-		u8 __iomem *regp;
-
-		regp = (u8 __iomem *)&par->regs->cmap.addr;
-		sbus_writeb(p[0], regp);
-		regp = (u8 __iomem *)&par->regs->cmap.control;
-		sbus_writeb(p[1], regp);
-	}
-	return 0;
-}
-
-static int cg3_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct cg3_par *par;
-	int linebytes, err;
-
-	info = framebuffer_alloc(sizeof(struct cg3_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-
-	info->fix.smem_start = op->resource[0].start;
-	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
-
-	sbusfb_fill_var(&info->var, dp, 8);
-	info->var.red.length = 8;
-	info->var.green.length = 8;
-	info->var.blue.length = 8;
-	if (!strcmp(dp->name, "cgRDI"))
-		par->flags |= CG3_FLAG_RDI;
-	if (par->flags & CG3_FLAG_RDI)
-		cg3_rdi_maybe_fixup_var(&info->var, dp);
-
-	linebytes = of_getintprop_default(dp, "linebytes",
-					  info->var.xres);
-	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
-
-	par->regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
-			       sizeof(struct cg3_regs), "cg3 regs");
-	if (!par->regs)
-		goto out_release_fb;
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &cg3_ops;
-	info->screen_base = of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
-				       info->fix.smem_len, "cg3 ram");
-	if (!info->screen_base)
-		goto out_unmap_regs;
-
-	cg3_blank(FB_BLANK_UNBLANK, info);
-
-	if (!of_find_property(dp, "width", NULL)) {
-		err = cg3_do_default_mode(par);
-		if (err)
-			goto out_unmap_screen;
-	}
-
-	err = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (err)
-		goto out_unmap_screen;
-
-	fb_set_cmap(&info->cmap, info);
-
-	cg3_init_fix(info, linebytes, dp);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_dealloc_cmap;
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: cg3 at %lx:%lx\n",
-	       dp->full_name, par->which_io, info->fix.smem_start);
-
-	return 0;
-
-out_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-out_unmap_screen:
-	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
-
-out_unmap_regs:
-	of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
-
-out_release_fb:
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int cg3_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct cg3_par *par = info->par;
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
-	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id cg3_match[] = {
-	{
-		.name = "cgthree",
-	},
-	{
-		.name = "cgRDI",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, cg3_match);
-
-static struct platform_driver cg3_driver = {
-	.driver = {
-		.name = "cg3",
-		.owner = THIS_MODULE,
-		.of_match_table = cg3_match,
-	},
-	.probe		= cg3_probe,
-	.remove		= cg3_remove,
-};
-
-static int __init cg3_init(void)
-{
-	if (fb_get_options("cg3fb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&cg3_driver);
-}
-
-static void __exit cg3_exit(void)
-{
-	platform_driver_unregister(&cg3_driver);
-}
-
-module_init(cg3_init);
-module_exit(cg3_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for CGthree chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
deleted file mode 100644
index 70781fea092a..000000000000
--- a/drivers/video/cg6.c
+++ /dev/null
@@ -1,885 +0,0 @@
-/* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			 unsigned, struct fb_info *);
-static int cg6_blank(int, struct fb_info *);
-
-static void cg6_imageblit(struct fb_info *, const struct fb_image *);
-static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
-static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-static int cg6_sync(struct fb_info *);
-static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
-static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
-static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops cg6_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= cg6_setcolreg,
-	.fb_blank		= cg6_blank,
-	.fb_pan_display		= cg6_pan_display,
-	.fb_fillrect		= cg6_fillrect,
-	.fb_copyarea		= cg6_copyarea,
-	.fb_imageblit		= cg6_imageblit,
-	.fb_sync		= cg6_sync,
-	.fb_mmap		= cg6_mmap,
-	.fb_ioctl		= cg6_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-/* Offset of interesting structures in the OBIO space */
-/*
- * Brooktree is the video dac and is funny to program on the cg6.
- * (it's even funnier on the cg3)
- * The FBC could be the frame buffer control
- * The FHC could is the frame buffer hardware control.
- */
-#define CG6_ROM_OFFSET			0x0UL
-#define CG6_BROOKTREE_OFFSET		0x200000UL
-#define CG6_DHC_OFFSET			0x240000UL
-#define CG6_ALT_OFFSET			0x280000UL
-#define CG6_FHC_OFFSET			0x300000UL
-#define CG6_THC_OFFSET			0x301000UL
-#define CG6_FBC_OFFSET			0x700000UL
-#define CG6_TEC_OFFSET			0x701000UL
-#define CG6_RAM_OFFSET			0x800000UL
-
-/* FHC definitions */
-#define CG6_FHC_FBID_SHIFT		24
-#define CG6_FHC_FBID_MASK		255
-#define CG6_FHC_REV_SHIFT		20
-#define CG6_FHC_REV_MASK		15
-#define CG6_FHC_FROP_DISABLE		(1 << 19)
-#define CG6_FHC_ROW_DISABLE		(1 << 18)
-#define CG6_FHC_SRC_DISABLE		(1 << 17)
-#define CG6_FHC_DST_DISABLE		(1 << 16)
-#define CG6_FHC_RESET			(1 << 15)
-#define CG6_FHC_LITTLE_ENDIAN		(1 << 13)
-#define CG6_FHC_RES_MASK		(3 << 11)
-#define CG6_FHC_1024			(0 << 11)
-#define CG6_FHC_1152			(1 << 11)
-#define CG6_FHC_1280			(2 << 11)
-#define CG6_FHC_1600			(3 << 11)
-#define CG6_FHC_CPU_MASK		(3 << 9)
-#define CG6_FHC_CPU_SPARC		(0 << 9)
-#define CG6_FHC_CPU_68020		(1 << 9)
-#define CG6_FHC_CPU_386			(2 << 9)
-#define CG6_FHC_TEST			(1 << 8)
-#define CG6_FHC_TEST_X_SHIFT		4
-#define CG6_FHC_TEST_X_MASK		15
-#define CG6_FHC_TEST_Y_SHIFT		0
-#define CG6_FHC_TEST_Y_MASK		15
-
-/* FBC mode definitions */
-#define CG6_FBC_BLIT_IGNORE		0x00000000
-#define CG6_FBC_BLIT_NOSRC		0x00100000
-#define CG6_FBC_BLIT_SRC		0x00200000
-#define CG6_FBC_BLIT_ILLEGAL		0x00300000
-#define CG6_FBC_BLIT_MASK		0x00300000
-
-#define CG6_FBC_VBLANK			0x00080000
-
-#define CG6_FBC_MODE_IGNORE		0x00000000
-#define CG6_FBC_MODE_COLOR8		0x00020000
-#define CG6_FBC_MODE_COLOR1		0x00040000
-#define CG6_FBC_MODE_HRMONO		0x00060000
-#define CG6_FBC_MODE_MASK		0x00060000
-
-#define CG6_FBC_DRAW_IGNORE		0x00000000
-#define CG6_FBC_DRAW_RENDER		0x00008000
-#define CG6_FBC_DRAW_PICK		0x00010000
-#define CG6_FBC_DRAW_ILLEGAL		0x00018000
-#define CG6_FBC_DRAW_MASK		0x00018000
-
-#define CG6_FBC_BWRITE0_IGNORE		0x00000000
-#define CG6_FBC_BWRITE0_ENABLE		0x00002000
-#define CG6_FBC_BWRITE0_DISABLE		0x00004000
-#define CG6_FBC_BWRITE0_ILLEGAL		0x00006000
-#define CG6_FBC_BWRITE0_MASK		0x00006000
-
-#define CG6_FBC_BWRITE1_IGNORE		0x00000000
-#define CG6_FBC_BWRITE1_ENABLE		0x00000800
-#define CG6_FBC_BWRITE1_DISABLE		0x00001000
-#define CG6_FBC_BWRITE1_ILLEGAL		0x00001800
-#define CG6_FBC_BWRITE1_MASK		0x00001800
-
-#define CG6_FBC_BREAD_IGNORE		0x00000000
-#define CG6_FBC_BREAD_0			0x00000200
-#define CG6_FBC_BREAD_1			0x00000400
-#define CG6_FBC_BREAD_ILLEGAL		0x00000600
-#define CG6_FBC_BREAD_MASK		0x00000600
-
-#define CG6_FBC_BDISP_IGNORE		0x00000000
-#define CG6_FBC_BDISP_0			0x00000080
-#define CG6_FBC_BDISP_1			0x00000100
-#define CG6_FBC_BDISP_ILLEGAL		0x00000180
-#define CG6_FBC_BDISP_MASK		0x00000180
-
-#define CG6_FBC_INDEX_MOD		0x00000040
-#define CG6_FBC_INDEX_MASK		0x00000030
-
-/* THC definitions */
-#define CG6_THC_MISC_REV_SHIFT		16
-#define CG6_THC_MISC_REV_MASK		15
-#define CG6_THC_MISC_RESET		(1 << 12)
-#define CG6_THC_MISC_VIDEO		(1 << 10)
-#define CG6_THC_MISC_SYNC		(1 << 9)
-#define CG6_THC_MISC_VSYNC		(1 << 8)
-#define CG6_THC_MISC_SYNC_ENAB		(1 << 7)
-#define CG6_THC_MISC_CURS_RES		(1 << 6)
-#define CG6_THC_MISC_INT_ENAB		(1 << 5)
-#define CG6_THC_MISC_INT		(1 << 4)
-#define CG6_THC_MISC_INIT		0x9f
-#define CG6_THC_CURSOFF			((65536-32) | ((65536-32) << 16))
-
-/* The contents are unknown */
-struct cg6_tec {
-	int tec_matrix;
-	int tec_clip;
-	int tec_vdc;
-};
-
-struct cg6_thc {
-	u32	thc_pad0[512];
-	u32	thc_hs;		/* hsync timing */
-	u32	thc_hsdvs;
-	u32	thc_hd;
-	u32	thc_vs;		/* vsync timing */
-	u32	thc_vd;
-	u32	thc_refresh;
-	u32	thc_misc;
-	u32	thc_pad1[56];
-	u32	thc_cursxy;	/* cursor x,y position (16 bits each) */
-	u32	thc_cursmask[32];	/* cursor mask bits */
-	u32	thc_cursbits[32];	/* what to show where mask enabled */
-};
-
-struct cg6_fbc {
-	u32	xxx0[1];
-	u32	mode;
-	u32	clip;
-	u32	xxx1[1];
-	u32	s;
-	u32	draw;
-	u32	blit;
-	u32	font;
-	u32	xxx2[24];
-	u32	x0, y0, z0, color0;
-	u32	x1, y1, z1, color1;
-	u32	x2, y2, z2, color2;
-	u32	x3, y3, z3, color3;
-	u32	offx, offy;
-	u32	xxx3[2];
-	u32	incx, incy;
-	u32	xxx4[2];
-	u32	clipminx, clipminy;
-	u32	xxx5[2];
-	u32	clipmaxx, clipmaxy;
-	u32	xxx6[2];
-	u32	fg;
-	u32	bg;
-	u32	alu;
-	u32	pm;
-	u32	pixelm;
-	u32	xxx7[2];
-	u32	patalign;
-	u32	pattern[8];
-	u32	xxx8[432];
-	u32	apointx, apointy, apointz;
-	u32	xxx9[1];
-	u32	rpointx, rpointy, rpointz;
-	u32	xxx10[5];
-	u32	pointr, pointg, pointb, pointa;
-	u32	alinex, aliney, alinez;
-	u32	xxx11[1];
-	u32	rlinex, rliney, rlinez;
-	u32	xxx12[5];
-	u32	liner, lineg, lineb, linea;
-	u32	atrix, atriy, atriz;
-	u32	xxx13[1];
-	u32	rtrix, rtriy, rtriz;
-	u32	xxx14[5];
-	u32	trir, trig, trib, tria;
-	u32	aquadx, aquady, aquadz;
-	u32	xxx15[1];
-	u32	rquadx, rquady, rquadz;
-	u32	xxx16[5];
-	u32	quadr, quadg, quadb, quada;
-	u32	arectx, arecty, arectz;
-	u32	xxx17[1];
-	u32	rrectx, rrecty, rrectz;
-	u32	xxx18[5];
-	u32	rectr, rectg, rectb, recta;
-};
-
-struct bt_regs {
-	u32	addr;
-	u32	color_map;
-	u32	control;
-	u32	cursor;
-};
-
-struct cg6_par {
-	spinlock_t		lock;
-	struct bt_regs		__iomem *bt;
-	struct cg6_fbc		__iomem *fbc;
-	struct cg6_thc		__iomem *thc;
-	struct cg6_tec		__iomem *tec;
-	u32			__iomem *fhc;
-
-	u32			flags;
-#define CG6_FLAG_BLANKED	0x00000001
-
-	unsigned long		which_io;
-};
-
-static int cg6_sync(struct fb_info *info)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	struct cg6_fbc __iomem *fbc = par->fbc;
-	int limit = 10000;
-
-	do {
-		if (!(sbus_readl(&fbc->s) & 0x10000000))
-			break;
-		udelay(10);
-	} while (--limit > 0);
-
-	return 0;
-}
-
-static void cg6_switch_from_graph(struct cg6_par *par)
-{
-	struct cg6_thc __iomem *thc = par->thc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	/* Hide the cursor. */
-	sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-
-	/* We just use this to catch switches out of
-	 * graphics mode.
-	 */
-	cg6_switch_from_graph(par);
-
-	if (var->xoffset || var->yoffset || var->vmode)
-		return -EINVAL;
-	return 0;
-}
-
-/**
- *	cg6_fillrect -	Draws a rectangle on the screen.
- *
- *	@info: frame buffer structure that represents a single frame buffer
- *	@rect: structure defining the rectagle and operation.
- */
-static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	struct cg6_fbc __iomem *fbc = par->fbc;
-	unsigned long flags;
-	s32 val;
-
-	/* CG6 doesn't handle ROP_XOR */
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	cg6_sync(info);
-
-	sbus_writel(rect->color, &fbc->fg);
-	sbus_writel(~(u32)0, &fbc->pixelm);
-	sbus_writel(0xea80ff00, &fbc->alu);
-	sbus_writel(0, &fbc->s);
-	sbus_writel(0, &fbc->clip);
-	sbus_writel(~(u32)0, &fbc->pm);
-	sbus_writel(rect->dy, &fbc->arecty);
-	sbus_writel(rect->dx, &fbc->arectx);
-	sbus_writel(rect->dy + rect->height, &fbc->arecty);
-	sbus_writel(rect->dx + rect->width, &fbc->arectx);
-	do {
-		val = sbus_readl(&fbc->draw);
-	} while (val < 0 && (val & 0x20000000));
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-/**
- *	cg6_copyarea - Copies one area of the screen to another area.
- *
- *	@info: frame buffer structure that represents a single frame buffer
- *	@area: Structure providing the data to copy the framebuffer contents
- *		from one region to another.
- *
- *	This drawing operation copies a rectangular area from one area of the
- *	screen to another area.
- */
-static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	struct cg6_fbc __iomem *fbc = par->fbc;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	cg6_sync(info);
-
-	sbus_writel(0xff, &fbc->fg);
-	sbus_writel(0x00, &fbc->bg);
-	sbus_writel(~0, &fbc->pixelm);
-	sbus_writel(0xe880cccc, &fbc->alu);
-	sbus_writel(0, &fbc->s);
-	sbus_writel(0, &fbc->clip);
-
-	sbus_writel(area->sy, &fbc->y0);
-	sbus_writel(area->sx, &fbc->x0);
-	sbus_writel(area->sy + area->height - 1, &fbc->y1);
-	sbus_writel(area->sx + area->width - 1, &fbc->x1);
-	sbus_writel(area->dy, &fbc->y2);
-	sbus_writel(area->dx, &fbc->x2);
-	sbus_writel(area->dy + area->height - 1, &fbc->y3);
-	sbus_writel(area->dx + area->width - 1, &fbc->x3);
-	do {
-		i = sbus_readl(&fbc->blit);
-	} while (i < 0 && (i & 0x20000000));
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-/**
- *	cg6_imageblit -	Copies a image from system memory to the screen.
- *
- *	@info: frame buffer structure that represents a single frame buffer
- *	@image: structure defining the image.
- */
-static void cg6_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	struct cg6_fbc __iomem *fbc = par->fbc;
-	const u8 *data = image->data;
-	unsigned long flags;
-	u32 x, y;
-	int i, width;
-
-	if (image->depth > 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	cg6_sync(info);
-
-	sbus_writel(image->fg_color, &fbc->fg);
-	sbus_writel(image->bg_color, &fbc->bg);
-	sbus_writel(0x140000, &fbc->mode);
-	sbus_writel(0xe880fc30, &fbc->alu);
-	sbus_writel(~(u32)0, &fbc->pixelm);
-	sbus_writel(0, &fbc->s);
-	sbus_writel(0, &fbc->clip);
-	sbus_writel(0xff, &fbc->pm);
-	sbus_writel(32, &fbc->incx);
-	sbus_writel(0, &fbc->incy);
-
-	x = image->dx;
-	y = image->dy;
-	for (i = 0; i < image->height; i++) {
-		width = image->width;
-
-		while (width >= 32) {
-			u32 val;
-
-			sbus_writel(y, &fbc->y0);
-			sbus_writel(x, &fbc->x0);
-			sbus_writel(x + 32 - 1, &fbc->x1);
-
-			val = ((u32)data[0] << 24) |
-			      ((u32)data[1] << 16) |
-			      ((u32)data[2] <<  8) |
-			      ((u32)data[3] <<  0);
-			sbus_writel(val, &fbc->font);
-
-			data += 4;
-			x += 32;
-			width -= 32;
-		}
-		if (width) {
-			u32 val;
-
-			sbus_writel(y, &fbc->y0);
-			sbus_writel(x, &fbc->x0);
-			sbus_writel(x + width - 1, &fbc->x1);
-			if (width <= 8) {
-				val = (u32) data[0] << 24;
-				data += 1;
-			} else if (width <= 16) {
-				val = ((u32) data[0] << 24) |
-				      ((u32) data[1] << 16);
-				data += 2;
-			} else {
-				val = ((u32) data[0] << 24) |
-				      ((u32) data[1] << 16) |
-				      ((u32) data[2] <<  8);
-				data += 3;
-			}
-			sbus_writel(val, &fbc->font);
-		}
-
-		y += 1;
-		x = image->dx;
-	}
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-/**
- *	cg6_setcolreg - Sets a color register.
- *
- *	@regno: boolean, 0 copy local, 1 get_user() function
- *	@red: frame buffer colormap structure
- *	@green: The green value which can be up to 16 bits wide
- *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.
- *	@info: frame buffer info structure
- */
-static int cg6_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	struct bt_regs __iomem *bt = par->bt;
-	unsigned long flags;
-
-	if (regno >= 256)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	sbus_writel((u32)regno << 24, &bt->addr);
-	sbus_writel((u32)red << 24, &bt->color_map);
-	sbus_writel((u32)green << 24, &bt->color_map);
-	sbus_writel((u32)blue << 24, &bt->color_map);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-/**
- *	cg6_blank - Blanks the display.
- *
- *	@blank_mode: the blank mode we want.
- *	@info: frame buffer structure that represents a single frame buffer
- */
-static int cg6_blank(int blank, struct fb_info *info)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	struct cg6_thc __iomem *thc = par->thc;
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&par->lock, flags);
-	val = sbus_readl(&thc->thc_misc);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		val |= CG6_THC_MISC_VIDEO;
-		par->flags &= ~CG6_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		val &= ~CG6_THC_MISC_VIDEO;
-		par->flags |= CG6_FLAG_BLANKED;
-		break;
-	}
-
-	sbus_writel(val, &thc->thc_misc);
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static struct sbus_mmap_map cg6_mmap_map[] = {
-	{
-		.voff	= CG6_FBC,
-		.poff	= CG6_FBC_OFFSET,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= CG6_TEC,
-		.poff	= CG6_TEC_OFFSET,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= CG6_BTREGS,
-		.poff	= CG6_BROOKTREE_OFFSET,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= CG6_FHC,
-		.poff	= CG6_FHC_OFFSET,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= CG6_THC,
-		.poff	= CG6_THC_OFFSET,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= CG6_ROM,
-		.poff	= CG6_ROM_OFFSET,
-		.size	= 0x10000
-	},
-	{
-		.voff	= CG6_RAM,
-		.poff	= CG6_RAM_OFFSET,
-		.size	= SBUS_MMAP_FBSIZE(1)
-	},
-	{
-		.voff	= CG6_DHC,
-		.poff	= CG6_DHC_OFFSET,
-		.size	= 0x40000
-	},
-	{ .size	= 0 }
-};
-
-static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-
-	return sbusfb_mmap_helper(cg6_mmap_map,
-				  info->fix.smem_start, info->fix.smem_len,
-				  par->which_io, vma);
-}
-
-static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	return sbusfb_ioctl_helper(cmd, arg, info,
-				   FBTYPE_SUNFAST_COLOR, 8, info->fix.smem_len);
-}
-
-/*
- *  Initialisation
- */
-
-static void cg6_init_fix(struct fb_info *info, int linebytes)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	const char *cg6_cpu_name, *cg6_card_name;
-	u32 conf;
-
-	conf = sbus_readl(par->fhc);
-	switch (conf & CG6_FHC_CPU_MASK) {
-	case CG6_FHC_CPU_SPARC:
-		cg6_cpu_name = "sparc";
-		break;
-	case CG6_FHC_CPU_68020:
-		cg6_cpu_name = "68020";
-		break;
-	default:
-		cg6_cpu_name = "i386";
-		break;
-	}
-	if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
-		if (info->fix.smem_len <= 0x100000)
-			cg6_card_name = "TGX";
-		else
-			cg6_card_name = "TGX+";
-	} else {
-		if (info->fix.smem_len <= 0x100000)
-			cg6_card_name = "GX";
-		else
-			cg6_card_name = "GX+";
-	}
-
-	sprintf(info->fix.id, "%s %s", cg6_card_name, cg6_cpu_name);
-	info->fix.id[sizeof(info->fix.id) - 1] = 0;
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = linebytes;
-
-	info->fix.accel = FB_ACCEL_SUN_CGSIX;
-}
-
-/* Initialize Brooktree DAC */
-static void cg6_bt_init(struct cg6_par *par)
-{
-	struct bt_regs __iomem *bt = par->bt;
-
-	sbus_writel(0x04 << 24, &bt->addr);	 /* color planes */
-	sbus_writel(0xff << 24, &bt->control);
-	sbus_writel(0x05 << 24, &bt->addr);
-	sbus_writel(0x00 << 24, &bt->control);
-	sbus_writel(0x06 << 24, &bt->addr);	 /* overlay plane */
-	sbus_writel(0x73 << 24, &bt->control);
-	sbus_writel(0x07 << 24, &bt->addr);
-	sbus_writel(0x00 << 24, &bt->control);
-}
-
-static void cg6_chip_init(struct fb_info *info)
-{
-	struct cg6_par *par = (struct cg6_par *)info->par;
-	struct cg6_tec __iomem *tec = par->tec;
-	struct cg6_fbc __iomem *fbc = par->fbc;
-	struct cg6_thc __iomem *thc = par->thc;
-	u32 rev, conf, mode;
-	int i;
-
-	/* Hide the cursor. */
-	sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
-
-	/* Turn off stuff in the Transform Engine. */
-	sbus_writel(0, &tec->tec_matrix);
-	sbus_writel(0, &tec->tec_clip);
-	sbus_writel(0, &tec->tec_vdc);
-
-	/* Take care of bugs in old revisions. */
-	rev = (sbus_readl(par->fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
-	if (rev < 5) {
-		conf = (sbus_readl(par->fhc) & CG6_FHC_RES_MASK) |
-			CG6_FHC_CPU_68020 | CG6_FHC_TEST |
-			(11 << CG6_FHC_TEST_X_SHIFT) |
-			(11 << CG6_FHC_TEST_Y_SHIFT);
-		if (rev < 2)
-			conf |= CG6_FHC_DST_DISABLE;
-		sbus_writel(conf, par->fhc);
-	}
-
-	/* Set things in the FBC. Bad things appear to happen if we do
-	 * back to back store/loads on the mode register, so copy it
-	 * out instead. */
-	mode = sbus_readl(&fbc->mode);
-	do {
-		i = sbus_readl(&fbc->s);
-	} while (i & 0x10000000);
-	mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
-		  CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
-		  CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
-		  CG6_FBC_BDISP_MASK);
-	mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
-		 CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
-		 CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
-		 CG6_FBC_BDISP_0);
-	sbus_writel(mode, &fbc->mode);
-
-	sbus_writel(0, &fbc->clip);
-	sbus_writel(0, &fbc->offx);
-	sbus_writel(0, &fbc->offy);
-	sbus_writel(0, &fbc->clipminx);
-	sbus_writel(0, &fbc->clipminy);
-	sbus_writel(info->var.xres - 1, &fbc->clipmaxx);
-	sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
-}
-
-static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
-			   struct cg6_par *par)
-{
-	if (par->fbc)
-		of_iounmap(&op->resource[0], par->fbc, 4096);
-	if (par->tec)
-		of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec));
-	if (par->thc)
-		of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc));
-	if (par->bt)
-		of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs));
-	if (par->fhc)
-		of_iounmap(&op->resource[0], par->fhc, sizeof(u32));
-
-	if (info->screen_base)
-		of_iounmap(&op->resource[0], info->screen_base,
-			   info->fix.smem_len);
-}
-
-static int cg6_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct cg6_par *par;
-	int linebytes, err;
-	int dblbuf;
-
-	info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-
-	info->fix.smem_start = op->resource[0].start;
-	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
-
-	sbusfb_fill_var(&info->var, dp, 8);
-	info->var.red.length = 8;
-	info->var.green.length = 8;
-	info->var.blue.length = 8;
-
-	linebytes = of_getintprop_default(dp, "linebytes",
-					  info->var.xres);
-	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
-
-	dblbuf = of_getintprop_default(dp, "dblbuf", 0);
-	if (dblbuf)
-		info->fix.smem_len *= 4;
-
-	par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
-				4096, "cgsix fbc");
-	par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
-				sizeof(struct cg6_tec), "cgsix tec");
-	par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
-				sizeof(struct cg6_thc), "cgsix thc");
-	par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
-				sizeof(struct bt_regs), "cgsix dac");
-	par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
-				sizeof(u32), "cgsix fhc");
-
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
-			FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
-			FBINFO_READS_FAST;
-	info->fbops = &cg6_ops;
-
-	info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
-					info->fix.smem_len, "cgsix ram");
-	if (!par->fbc || !par->tec || !par->thc ||
-	    !par->bt || !par->fhc || !info->screen_base)
-		goto out_unmap_regs;
-
-	info->var.accel_flags = FB_ACCELF_TEXT;
-
-	cg6_bt_init(par);
-	cg6_chip_init(info);
-	cg6_blank(FB_BLANK_UNBLANK, info);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0))
-		goto out_unmap_regs;
-
-	fb_set_cmap(&info->cmap, info);
-	cg6_init_fix(info, linebytes);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_dealloc_cmap;
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: CGsix [%s] at %lx:%lx\n",
-	       dp->full_name, info->fix.id,
-	       par->which_io, info->fix.smem_start);
-
-	return 0;
-
-out_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-out_unmap_regs:
-	cg6_unmap_regs(op, info, par);
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int cg6_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct cg6_par *par = info->par;
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	cg6_unmap_regs(op, info, par);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id cg6_match[] = {
-	{
-		.name = "cgsix",
-	},
-	{
-		.name = "cgthree+",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, cg6_match);
-
-static struct platform_driver cg6_driver = {
-	.driver = {
-		.name = "cg6",
-		.owner = THIS_MODULE,
-		.of_match_table = cg6_match,
-	},
-	.probe		= cg6_probe,
-	.remove		= cg6_remove,
-};
-
-static int __init cg6_init(void)
-{
-	if (fb_get_options("cg6fb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&cg6_driver);
-}
-
-static void __exit cg6_exit(void)
-{
-	platform_driver_unregister(&cg6_driver);
-}
-
-module_init(cg6_init);
-module_exit(cg6_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
deleted file mode 100644
index 206a66b61072..000000000000
--- a/drivers/video/chipsfb.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- *  drivers/video/chipsfb.c -- frame buffer device for
- *  Chips & Technologies 65550 chip.
- *
- *  Copyright (C) 1998-2002 Paul Mackerras
- *
- *  This file is derived from the Powermac "chips" driver:
- *  Copyright (C) 1997 Fabio Riccardi.
- *  And from the frame buffer device for Open Firmware-initialized devices:
- *  Copyright (C) 1997 Geert Uytterhoeven.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/pm.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/console.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
-/*
- * Since we access the display with inb/outb to fixed port numbers,
- * we can only handle one 6555x chip.  -- paulus
- */
-#define write_ind(num, val, ap, dp)	do { \
-	outb((num), (ap)); outb((val), (dp)); \
-} while (0)
-#define read_ind(num, var, ap, dp)	do { \
-	outb((num), (ap)); var = inb((dp)); \
-} while (0)
-
-/* extension registers */
-#define write_xr(num, val)	write_ind(num, val, 0x3d6, 0x3d7)
-#define read_xr(num, var)	read_ind(num, var, 0x3d6, 0x3d7)
-/* flat panel registers */
-#define write_fr(num, val)	write_ind(num, val, 0x3d0, 0x3d1)
-#define read_fr(num, var)	read_ind(num, var, 0x3d0, 0x3d1)
-/* CRTC registers */
-#define write_cr(num, val)	write_ind(num, val, 0x3d4, 0x3d5)
-#define read_cr(num, var)	read_ind(num, var, 0x3d4, 0x3d5)
-/* graphics registers */
-#define write_gr(num, val)	write_ind(num, val, 0x3ce, 0x3cf)
-#define read_gr(num, var)	read_ind(num, var, 0x3ce, 0x3cf)
-/* sequencer registers */
-#define write_sr(num, val)	write_ind(num, val, 0x3c4, 0x3c5)
-#define read_sr(num, var)	read_ind(num, var, 0x3c4, 0x3c5)
-/* attribute registers - slightly strange */
-#define write_ar(num, val)	do { \
-	inb(0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
-} while (0)
-#define read_ar(num, var)	do { \
-	inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
-} while (0)
-
-/*
- * Exported functions
- */
-int chips_init(void);
-
-static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
-static int chipsfb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info);
-static int chipsfb_set_par(struct fb_info *info);
-static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info);
-static int chipsfb_blank(int blank, struct fb_info *info);
-
-static struct fb_ops chipsfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= chipsfb_check_var,
-	.fb_set_par	= chipsfb_set_par,
-	.fb_setcolreg	= chipsfb_setcolreg,
-	.fb_blank	= chipsfb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int chipsfb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	if (var->xres > 800 || var->yres > 600
-	    || var->xres_virtual > 800 || var->yres_virtual > 600
-	    || (var->bits_per_pixel != 8 && var->bits_per_pixel != 16)
-	    || var->nonstd
-	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	var->xres = var->xres_virtual = 800;
-	var->yres = var->yres_virtual = 600;
-
-	return 0;
-}
-
-static int chipsfb_set_par(struct fb_info *info)
-{
-	if (info->var.bits_per_pixel == 16) {
-		write_cr(0x13, 200);		// Set line length (doublewords)
-		write_xr(0x81, 0x14);		// 15 bit (555) color mode
-		write_xr(0x82, 0x00);		// Disable palettes
-		write_xr(0x20, 0x10);		// 16 bit blitter mode
-
-		info->fix.line_length = 800*2;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-		info->var.red.offset = 10;
-		info->var.green.offset = 5;
-		info->var.blue.offset = 0;
-		info->var.red.length = info->var.green.length =
-			info->var.blue.length = 5;
-		
-	} else {
-		/* p->var.bits_per_pixel == 8 */
-		write_cr(0x13, 100);		// Set line length (doublewords)
-		write_xr(0x81, 0x12);		// 8 bit color mode
-		write_xr(0x82, 0x08);		// Graphics gamma enable
-		write_xr(0x20, 0x00);		// 8 bit blitter mode
-
-		info->fix.line_length = 800;
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;		
-
- 		info->var.red.offset = info->var.green.offset =
-			info->var.blue.offset = 0;
-		info->var.red.length = info->var.green.length =
-			info->var.blue.length = 8;
-		
-	}
-	return 0;
-}
-
-static int chipsfb_blank(int blank, struct fb_info *info)
-{
-	return 1;	/* get fb_blank to set the colormap to all black */
-}
-
-static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info)
-{
-	if (regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	outb(regno, 0x3c8);
-	udelay(1);
-	outb(red, 0x3c9);
-	outb(green, 0x3c9);
-	outb(blue, 0x3c9);
-
-	return 0;
-}
-
-struct chips_init_reg {
-	unsigned char addr;
-	unsigned char data;
-};
-
-static struct chips_init_reg chips_init_sr[] = {
-	{ 0x00, 0x03 },
-	{ 0x01, 0x01 },
-	{ 0x02, 0x0f },
-	{ 0x04, 0x0e }
-};
-
-static struct chips_init_reg chips_init_gr[] = {
-	{ 0x05, 0x00 },
-	{ 0x06, 0x0d },
-	{ 0x08, 0xff }
-};
-
-static struct chips_init_reg chips_init_ar[] = {
-	{ 0x10, 0x01 },
-	{ 0x12, 0x0f },
-	{ 0x13, 0x00 }
-};
-
-static struct chips_init_reg chips_init_cr[] = {
-	{ 0x00, 0x7f },
-	{ 0x01, 0x63 },
-	{ 0x02, 0x63 },
-	{ 0x03, 0x83 },
-	{ 0x04, 0x66 },
-	{ 0x05, 0x10 },
-	{ 0x06, 0x72 },
-	{ 0x07, 0x3e },
-	{ 0x08, 0x00 },
-	{ 0x09, 0x40 },
-	{ 0x0c, 0x00 },
-	{ 0x0d, 0x00 },
-	{ 0x10, 0x59 },
-	{ 0x11, 0x0d },
-	{ 0x12, 0x57 },
-	{ 0x13, 0x64 },
-	{ 0x14, 0x00 },
-	{ 0x15, 0x57 },
-	{ 0x16, 0x73 },
-	{ 0x17, 0xe3 },
-	{ 0x18, 0xff },
-	{ 0x30, 0x02 },
-	{ 0x31, 0x02 },
-	{ 0x32, 0x02 },
-	{ 0x33, 0x02 },
-	{ 0x40, 0x00 },
-	{ 0x41, 0x00 },
-	{ 0x40, 0x80 }
-};
-
-static struct chips_init_reg chips_init_fr[] = {
-	{ 0x01, 0x02 },
-	{ 0x03, 0x08 },
-	{ 0x04, 0x81 },
-	{ 0x05, 0x21 },
-	{ 0x08, 0x0c },
-	{ 0x0a, 0x74 },
-	{ 0x0b, 0x11 },
-	{ 0x10, 0x0c },
-	{ 0x11, 0xe0 },
-	/* { 0x12, 0x40 }, -- 3400 needs 40, 2400 needs 48, no way to tell */
-	{ 0x20, 0x63 },
-	{ 0x21, 0x68 },
-	{ 0x22, 0x19 },
-	{ 0x23, 0x7f },
-	{ 0x24, 0x68 },
-	{ 0x26, 0x00 },
-	{ 0x27, 0x0f },
-	{ 0x30, 0x57 },
-	{ 0x31, 0x58 },
-	{ 0x32, 0x0d },
-	{ 0x33, 0x72 },
-	{ 0x34, 0x02 },
-	{ 0x35, 0x22 },
-	{ 0x36, 0x02 },
-	{ 0x37, 0x00 }
-};
-
-static struct chips_init_reg chips_init_xr[] = {
-	{ 0xce, 0x00 },		/* set default memory clock */
-	{ 0xcc, 0x43 },		/* memory clock ratio */
-	{ 0xcd, 0x18 },
-	{ 0xce, 0xa1 },
-	{ 0xc8, 0x84 },
-	{ 0xc9, 0x0a },
-	{ 0xca, 0x00 },
-	{ 0xcb, 0x20 },
-	{ 0xcf, 0x06 },
-	{ 0xd0, 0x0e },
-	{ 0x09, 0x01 },
-	{ 0x0a, 0x02 },
-	{ 0x0b, 0x01 },
-	{ 0x20, 0x00 },
-	{ 0x40, 0x03 },
-	{ 0x41, 0x01 },
-	{ 0x42, 0x00 },
-	{ 0x80, 0x82 },
-	{ 0x81, 0x12 },
-	{ 0x82, 0x08 },
-	{ 0xa0, 0x00 },
-	{ 0xa8, 0x00 }
-};
-
-static void __init chips_hw_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
-		write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
-	outb(0x29, 0x3c2); /* set misc output reg */
-	for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
-		write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
-	for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
-		write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
-	for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
-		write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
-	for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
-		write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
-	for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
-		write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
-}
-
-static struct fb_fix_screeninfo chipsfb_fix = {
-	.id =		"C&T 65550",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.accel =	FB_ACCEL_NONE,
-	.line_length =	800,
-
-// FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
-// * "3500" PowerBook G3 (the original PB G3) has 2MB.
-// * 2400 has 1MB composed of 2 Mitsubishi M5M4V4265CTP DRAM chips.
-//   Motherboard actually supports 2MB -- there are two blank locations
-//   for a second pair of DRAMs.  (Thanks, Apple!)
-// * 3400 has 1MB (I think).  Don't know if it's expandable.
-// -- Tim Seufert
-	.smem_len =	0x100000,	/* 1MB */
-};
-
-static struct fb_var_screeninfo chipsfb_var = {
-	.xres = 800,
-	.yres = 600,
-	.xres_virtual = 800,
-	.yres_virtual = 600,
-	.bits_per_pixel = 8,
-	.red = { .length = 8 },
-	.green = { .length = 8 },
-	.blue = { .length = 8 },
-	.height = -1,
-	.width = -1,
-	.vmode = FB_VMODE_NONINTERLACED,
-	.pixclock = 10000,
-	.left_margin = 16,
-	.right_margin = 16,
-	.upper_margin = 16,
-	.lower_margin = 16,
-	.hsync_len = 8,
-	.vsync_len = 8,
-};
-
-static void init_chips(struct fb_info *p, unsigned long addr)
-{
-	memset(p->screen_base, 0, 0x100000);
-
-	p->fix = chipsfb_fix;
-	p->fix.smem_start = addr;
-
-	p->var = chipsfb_var;
-
-	p->fbops = &chipsfb_ops;
-	p->flags = FBINFO_DEFAULT;
-
-	fb_alloc_cmap(&p->cmap, 256, 0);
-
-	chips_hw_init();
-}
-
-static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
-{
-	struct fb_info *p;
-	unsigned long addr, size;
-	unsigned short cmd;
-	int rc = -ENODEV;
-
-	if (pci_enable_device(dp) < 0) {
-		dev_err(&dp->dev, "Cannot enable PCI device\n");
-		goto err_out;
-	}
-
-	if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
-		goto err_disable;
-	addr = pci_resource_start(dp, 0);
-	size = pci_resource_len(dp, 0);
-	if (addr == 0)
-		goto err_disable;
-
-	p = framebuffer_alloc(0, &dp->dev);
-	if (p == NULL) {
-		dev_err(&dp->dev, "Cannot allocate framebuffer structure\n");
-		rc = -ENOMEM;
-		goto err_disable;
-	}
-
-	if (pci_request_region(dp, 0, "chipsfb") != 0) {
-		dev_err(&dp->dev, "Cannot request framebuffer\n");
-		rc = -EBUSY;
-		goto err_release_fb;
-	}
-
-#ifdef __BIG_ENDIAN
-	addr += 0x800000;	// Use big-endian aperture
-#endif
-
-	/* we should use pci_enable_device here, but,
-	   the device doesn't declare its I/O ports in its BARs
-	   so pci_enable_device won't turn on I/O responses */
-	pci_read_config_word(dp, PCI_COMMAND, &cmd);
-	cmd |= 3;	/* enable memory and IO space */
-	pci_write_config_word(dp, PCI_COMMAND, cmd);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* turn on the backlight */
-	mutex_lock(&pmac_backlight_mutex);
-	if (pmac_backlight) {
-		pmac_backlight->props.power = FB_BLANK_UNBLANK;
-		backlight_update_status(pmac_backlight);
-	}
-	mutex_unlock(&pmac_backlight_mutex);
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-#ifdef CONFIG_PPC
-	p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
-#else
-	p->screen_base = ioremap(addr, 0x200000);
-#endif
-	if (p->screen_base == NULL) {
-		dev_err(&dp->dev, "Cannot map framebuffer\n");
-		rc = -ENOMEM;
-		goto err_release_pci;
-	}
-
-	pci_set_drvdata(dp, p);
-
-	init_chips(p, addr);
-
-	if (register_framebuffer(p) < 0) {
-		dev_err(&dp->dev,"C&T 65550 framebuffer failed to register\n");
-		goto err_unmap;
-	}
-
-	dev_info(&dp->dev,"fb%d: Chips 65550 frame buffer"
-		 " (%dK RAM detected)\n",
-		 p->node, p->fix.smem_len / 1024);
-
-	return 0;
-
- err_unmap:
-	iounmap(p->screen_base);
- err_release_pci:
-	pci_release_region(dp, 0);
- err_release_fb:
-	framebuffer_release(p);
- err_disable:
- err_out:
-	return rc;
-}
-
-static void chipsfb_remove(struct pci_dev *dp)
-{
-	struct fb_info *p = pci_get_drvdata(dp);
-
-	if (p->screen_base == NULL)
-		return;
-	unregister_framebuffer(p);
-	iounmap(p->screen_base);
-	p->screen_base = NULL;
-	pci_release_region(dp, 0);
-}
-
-#ifdef CONFIG_PM
-static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-        struct fb_info *p = pci_get_drvdata(pdev);
-
-	if (state.event == pdev->dev.power.power_state.event)
-		return 0;
-	if (!(state.event & PM_EVENT_SLEEP))
-		goto done;
-
-	console_lock();
-	chipsfb_blank(1, p);
-	fb_set_suspend(p, 1);
-	console_unlock();
- done:
-	pdev->dev.power.power_state = state;
-	return 0;
-}
-
-static int chipsfb_pci_resume(struct pci_dev *pdev)
-{
-        struct fb_info *p = pci_get_drvdata(pdev);
-
-	console_lock();
-	fb_set_suspend(p, 0);
-	chipsfb_blank(0, p);
-	console_unlock();
-
-	pdev->dev.power.power_state = PMSG_ON;
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-
-static struct pci_device_id chipsfb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, chipsfb_pci_tbl);
-
-static struct pci_driver chipsfb_driver = {
-	.name =		"chipsfb",
-	.id_table =	chipsfb_pci_tbl,
-	.probe =	chipsfb_pci_init,
-	.remove =	chipsfb_remove,
-#ifdef CONFIG_PM
-	.suspend =	chipsfb_pci_suspend,
-	.resume =	chipsfb_pci_resume,
-#endif
-};
-
-int __init chips_init(void)
-{
-	if (fb_get_options("chipsfb", NULL))
-		return -ENODEV;
-
-	return pci_register_driver(&chipsfb_driver);
-}
-
-module_init(chips_init);
-
-static void __exit chipsfb_exit(void)
-{
-	pci_unregister_driver(&chipsfb_driver);
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
deleted file mode 100644
index d992aa5eb3f0..000000000000
--- a/drivers/video/cirrusfb.c
+++ /dev/null
@@ -1,2952 +0,0 @@
-/*
- * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
- *
- * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
- *
- * Contributors (thanks, all!)
- *
- *	David Eger:
- *	Overhaul for Linux 2.6
- *
- *      Jeff Rugen:
- *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
- *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
- *
- *	Geert Uytterhoeven:
- *	Excellent code review.
- *
- *	Lars Hecking:
- *	Amiga updates and testing.
- *
- * Original cirrusfb author:  Frank Neumann
- *
- * Based on retz3fb.c and cirrusfb.c:
- *      Copyright (C) 1997 Jes Sorensen
- *      Copyright (C) 1996 Frank Neumann
- *
- ***************************************************************
- *
- * Format this code with GNU indent '-kr -i8 -pcs' options.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/pgtable.h>
-
-#ifdef CONFIG_ZORRO
-#include <linux/zorro.h>
-#endif
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#endif
-
-#include <video/vga.h>
-#include <video/cirrus.h>
-
-/*****************************************************************
- *
- * debugging and utility macros
- *
- */
-
-/* disable runtime assertions? */
-/* #define CIRRUSFB_NDEBUG */
-
-/* debugging assertions */
-#ifndef CIRRUSFB_NDEBUG
-#define assert(expr) \
-	if (!(expr)) { \
-		printk("Assertion failed! %s,%s,%s,line=%d\n", \
-		#expr, __FILE__, __func__, __LINE__); \
-	}
-#else
-#define assert(expr)
-#endif
-
-#define MB_ (1024 * 1024)
-
-/*****************************************************************
- *
- * chipset information
- *
- */
-
-/* board types */
-enum cirrus_board {
-	BT_NONE = 0,
-	BT_SD64,	/* GD5434 */
-	BT_PICCOLO,	/* GD5426 */
-	BT_PICASSO,	/* GD5426 or GD5428 */
-	BT_SPECTRUM,	/* GD5426 or GD5428 */
-	BT_PICASSO4,	/* GD5446 */
-	BT_ALPINE,	/* GD543x/4x */
-	BT_GD5480,
-	BT_LAGUNA,	/* GD5462/64 */
-	BT_LAGUNAB,	/* GD5465 */
-};
-
-/*
- * per-board-type information, used for enumerating and abstracting
- * chip-specific information
- * NOTE: MUST be in the same order as enum cirrus_board in order to
- * use direct indexing on this array
- * NOTE: '__initdata' cannot be used as some of this info
- * is required at runtime.  Maybe separate into an init-only and
- * a run-time table?
- */
-static const struct cirrusfb_board_info_rec {
-	char *name;		/* ASCII name of chipset */
-	long maxclock[5];		/* maximum video clock */
-	/* for  1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
-	bool init_sr07 : 1; /* init SR07 during init_vgachip() */
-	bool init_sr1f : 1; /* write SR1F during init_vgachip() */
-	/* construct bit 19 of screen start address */
-	bool scrn_start_bit19 : 1;
-
-	/* initial SR07 value, then for each mode */
-	unsigned char sr07;
-	unsigned char sr07_1bpp;
-	unsigned char sr07_1bpp_mux;
-	unsigned char sr07_8bpp;
-	unsigned char sr07_8bpp_mux;
-
-	unsigned char sr1f;	/* SR1F VGA initial register value */
-} cirrusfb_board_info[] = {
-	[BT_SD64] = {
-		.name			= "CL SD64",
-		.maxclock		= {
-			/* guess */
-			/* the SD64/P4 have a higher max. videoclock */
-			135100, 135100, 85500, 85500, 0
-		},
-		.init_sr07		= true,
-		.init_sr1f		= true,
-		.scrn_start_bit19	= true,
-		.sr07			= 0xF0,
-		.sr07_1bpp		= 0xF0,
-		.sr07_1bpp_mux		= 0xF6,
-		.sr07_8bpp		= 0xF1,
-		.sr07_8bpp_mux		= 0xF7,
-		.sr1f			= 0x1E
-	},
-	[BT_PICCOLO] = {
-		.name			= "CL Piccolo",
-		.maxclock		= {
-			/* guess */
-			90000, 90000, 90000, 90000, 90000
-		},
-		.init_sr07		= true,
-		.init_sr1f		= true,
-		.scrn_start_bit19	= false,
-		.sr07			= 0x80,
-		.sr07_1bpp		= 0x80,
-		.sr07_8bpp		= 0x81,
-		.sr1f			= 0x22
-	},
-	[BT_PICASSO] = {
-		.name			= "CL Picasso",
-		.maxclock		= {
-			/* guess */
-			90000, 90000, 90000, 90000, 90000
-		},
-		.init_sr07		= true,
-		.init_sr1f		= true,
-		.scrn_start_bit19	= false,
-		.sr07			= 0x20,
-		.sr07_1bpp		= 0x20,
-		.sr07_8bpp		= 0x21,
-		.sr1f			= 0x22
-	},
-	[BT_SPECTRUM] = {
-		.name			= "CL Spectrum",
-		.maxclock		= {
-			/* guess */
-			90000, 90000, 90000, 90000, 90000
-		},
-		.init_sr07		= true,
-		.init_sr1f		= true,
-		.scrn_start_bit19	= false,
-		.sr07			= 0x80,
-		.sr07_1bpp		= 0x80,
-		.sr07_8bpp		= 0x81,
-		.sr1f			= 0x22
-	},
-	[BT_PICASSO4] = {
-		.name			= "CL Picasso4",
-		.maxclock		= {
-			135100, 135100, 85500, 85500, 0
-		},
-		.init_sr07		= true,
-		.init_sr1f		= false,
-		.scrn_start_bit19	= true,
-		.sr07			= 0xA0,
-		.sr07_1bpp		= 0xA0,
-		.sr07_1bpp_mux		= 0xA6,
-		.sr07_8bpp		= 0xA1,
-		.sr07_8bpp_mux		= 0xA7,
-		.sr1f			= 0
-	},
-	[BT_ALPINE] = {
-		.name			= "CL Alpine",
-		.maxclock		= {
-			/* for the GD5430.  GD5446 can do more... */
-			85500, 85500, 50000, 28500, 0
-		},
-		.init_sr07		= true,
-		.init_sr1f		= true,
-		.scrn_start_bit19	= true,
-		.sr07			= 0xA0,
-		.sr07_1bpp		= 0xA0,
-		.sr07_1bpp_mux		= 0xA6,
-		.sr07_8bpp		= 0xA1,
-		.sr07_8bpp_mux		= 0xA7,
-		.sr1f			= 0x1C
-	},
-	[BT_GD5480] = {
-		.name			= "CL GD5480",
-		.maxclock		= {
-			135100, 200000, 200000, 135100, 135100
-		},
-		.init_sr07		= true,
-		.init_sr1f		= true,
-		.scrn_start_bit19	= true,
-		.sr07			= 0x10,
-		.sr07_1bpp		= 0x11,
-		.sr07_8bpp		= 0x11,
-		.sr1f			= 0x1C
-	},
-	[BT_LAGUNA] = {
-		.name			= "CL Laguna",
-		.maxclock		= {
-			/* taken from X11 code */
-			170000, 170000, 170000, 170000, 135100,
-		},
-		.init_sr07		= false,
-		.init_sr1f		= false,
-		.scrn_start_bit19	= true,
-	},
-	[BT_LAGUNAB] = {
-		.name			= "CL Laguna AGP",
-		.maxclock		= {
-			/* taken from X11 code */
-			170000, 250000, 170000, 170000, 135100,
-		},
-		.init_sr07		= false,
-		.init_sr1f		= false,
-		.scrn_start_bit19	= true,
-	}
-};
-
-#ifdef CONFIG_PCI
-#define CHIP(id, btype) \
-	{ PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
-
-static struct pci_device_id cirrusfb_pci_table[] = {
-	CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
-	CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64),
-	CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64),
-	CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
-	CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
-	CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
-	CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
-	CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
-	CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
-	CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
-	CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
-#undef CHIP
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_ZORRO
-struct zorrocl {
-	enum cirrus_board type;	/* Board type */
-	u32 regoffset;		/* Offset of registers in first Zorro device */
-	u32 ramsize;		/* Size of video RAM in first Zorro device */
-				/* If zero, use autoprobe on RAM device */
-	u32 ramoffset;		/* Offset of video RAM in first Zorro device */
-	zorro_id ramid;		/* Zorro ID of RAM device */
-	zorro_id ramid2;	/* Zorro ID of optional second RAM device */
-};
-
-static const struct zorrocl zcl_sd64 = {
-	.type		= BT_SD64,
-	.ramid		= ZORRO_PROD_HELFRICH_SD64_RAM,
-};
-
-static const struct zorrocl zcl_piccolo = {
-	.type		= BT_PICCOLO,
-	.ramid		= ZORRO_PROD_HELFRICH_PICCOLO_RAM,
-};
-
-static const struct zorrocl zcl_picasso = {
-	.type		= BT_PICASSO,
-	.ramid		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
-};
-
-static const struct zorrocl zcl_spectrum = {
-	.type		= BT_SPECTRUM,
-	.ramid		= ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
-};
-
-static const struct zorrocl zcl_picasso4_z3 = {
-	.type		= BT_PICASSO4,
-	.regoffset	= 0x00600000,
-	.ramsize	= 4 * MB_,
-	.ramoffset	= 0x01000000,	/* 0x02000000 for 64 MiB boards */
-};
-
-static const struct zorrocl zcl_picasso4_z2 = {
-	.type		= BT_PICASSO4,
-	.regoffset	= 0x10000,
-	.ramid		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
-	.ramid2		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
-};
-
-
-static const struct zorro_device_id cirrusfb_zorro_table[] = {
-	{
-		.id		= ZORRO_PROD_HELFRICH_SD64_REG,
-		.driver_data	= (unsigned long)&zcl_sd64,
-	}, {
-		.id		= ZORRO_PROD_HELFRICH_PICCOLO_REG,
-		.driver_data	= (unsigned long)&zcl_piccolo,
-	}, {
-		.id	= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
-		.driver_data	= (unsigned long)&zcl_picasso,
-	}, {
-		.id		= ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
-		.driver_data	= (unsigned long)&zcl_spectrum,
-	}, {
-		.id		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
-		.driver_data	= (unsigned long)&zcl_picasso4_z3,
-	}, {
-		.id		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
-		.driver_data	= (unsigned long)&zcl_picasso4_z2,
-	},
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
-#endif /* CONFIG_ZORRO */
-
-#ifdef CIRRUSFB_DEBUG
-enum cirrusfb_dbg_reg_class {
-	CRT,
-	SEQ
-};
-#endif		/* CIRRUSFB_DEBUG */
-
-/* info about board */
-struct cirrusfb_info {
-	u8 __iomem *regbase;
-	u8 __iomem *laguna_mmio;
-	enum cirrus_board btype;
-	unsigned char SFR;	/* Shadow of special function register */
-
-	int multiplexing;
-	int doubleVCLK;
-	int blank_mode;
-	u32 pseudo_palette[16];
-
-	void (*unmap)(struct fb_info *info);
-};
-
-static bool noaccel;
-static char *mode_option = "640x480@60";
-
-/****************************************************************************/
-/**** BEGIN PROTOTYPES ******************************************************/
-
-/*--- Interface used by the world ------------------------------------------*/
-static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *info);
-
-/*--- Internal routines ----------------------------------------------------*/
-static void init_vgachip(struct fb_info *info);
-static void switch_monitor(struct cirrusfb_info *cinfo, int on);
-static void WGen(const struct cirrusfb_info *cinfo,
-		 int regnum, unsigned char val);
-static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
-static void AttrOn(const struct cirrusfb_info *cinfo);
-static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
-static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
-static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
-static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
-		  unsigned char red, unsigned char green, unsigned char blue);
-#if 0
-static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
-		  unsigned char *red, unsigned char *green,
-		  unsigned char *blue);
-#endif
-static void cirrusfb_WaitBLT(u8 __iomem *regbase);
-static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
-			    u_short curx, u_short cury,
-			    u_short destx, u_short desty,
-			    u_short width, u_short height,
-			    u_short line_length);
-static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
-			      u_short x, u_short y,
-			      u_short width, u_short height,
-			      u32 fg_color, u32 bg_color,
-			      u_short line_length, u_char blitmode);
-
-static void bestclock(long freq, int *nom, int *den, int *div);
-
-#ifdef CIRRUSFB_DEBUG
-static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase);
-static void cirrusfb_dbg_print_regs(struct fb_info *info,
-				    caddr_t regbase,
-				    enum cirrusfb_dbg_reg_class reg_class, ...);
-#endif /* CIRRUSFB_DEBUG */
-
-/*** END   PROTOTYPES ********************************************************/
-/*****************************************************************************/
-/*** BEGIN Interface Used by the World ***************************************/
-
-static inline int is_laguna(const struct cirrusfb_info *cinfo)
-{
-	return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB;
-}
-
-static int opencount;
-
-/*--- Open /dev/fbx ---------------------------------------------------------*/
-static int cirrusfb_open(struct fb_info *info, int user)
-{
-	if (opencount++ == 0)
-		switch_monitor(info->par, 1);
-	return 0;
-}
-
-/*--- Close /dev/fbx --------------------------------------------------------*/
-static int cirrusfb_release(struct fb_info *info, int user)
-{
-	if (--opencount == 0)
-		switch_monitor(info->par, 0);
-	return 0;
-}
-
-/**** END   Interface used by the World *************************************/
-/****************************************************************************/
-/**** BEGIN Hardware specific Routines **************************************/
-
-/* Check if the MCLK is not a better clock source */
-static int cirrusfb_check_mclk(struct fb_info *info, long freq)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
-
-	/* Read MCLK value */
-	mclk = (14318 * mclk) >> 3;
-	dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
-
-	/* Determine if we should use MCLK instead of VCLK, and if so, what we
-	 * should divide it by to get VCLK
-	 */
-
-	if (abs(freq - mclk) < 250) {
-		dev_dbg(info->device, "Using VCLK = MCLK\n");
-		return 1;
-	} else if (abs(freq - (mclk / 2)) < 250) {
-		dev_dbg(info->device, "Using VCLK = MCLK/2\n");
-		return 2;
-	}
-
-	return 0;
-}
-
-static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
-				   struct fb_info *info)
-{
-	long freq;
-	long maxclock;
-	struct cirrusfb_info *cinfo = info->par;
-	unsigned maxclockidx = var->bits_per_pixel >> 3;
-
-	/* convert from ps to kHz */
-	freq = PICOS2KHZ(var->pixclock);
-
-	dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
-
-	maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
-	cinfo->multiplexing = 0;
-
-	/* If the frequency is greater than we can support, we might be able
-	 * to use multiplexing for the video mode */
-	if (freq > maxclock) {
-		dev_err(info->device,
-			"Frequency greater than maxclock (%ld kHz)\n",
-			maxclock);
-		return -EINVAL;
-	}
-	/*
-	 * Additional constraint: 8bpp uses DAC clock doubling to allow maximum
-	 * pixel clock
-	 */
-	if (var->bits_per_pixel == 8) {
-		switch (cinfo->btype) {
-		case BT_ALPINE:
-		case BT_SD64:
-		case BT_PICASSO4:
-			if (freq > 85500)
-				cinfo->multiplexing = 1;
-			break;
-		case BT_GD5480:
-			if (freq > 135100)
-				cinfo->multiplexing = 1;
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	/* If we have a 1MB 5434, we need to put ourselves in a mode where
-	 * the VCLK is double the pixel clock. */
-	cinfo->doubleVCLK = 0;
-	if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ &&
-	    var->bits_per_pixel == 16) {
-		cinfo->doubleVCLK = 1;
-	}
-
-	return 0;
-}
-
-static int cirrusfb_check_var(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	int yres;
-	/* memory size in pixels */
-	unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
-	struct cirrusfb_info *cinfo = info->par;
-
-	switch (var->bits_per_pixel) {
-	case 1:
-		var->red.offset = 0;
-		var->red.length = 1;
-		var->green = var->red;
-		var->blue = var->red;
-		break;
-
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green = var->red;
-		var->blue = var->red;
-		break;
-
-	case 16:
-		var->red.offset = 11;
-		var->green.offset = 5;
-		var->blue.offset = 0;
-		var->red.length = 5;
-		var->green.length = 6;
-		var->blue.length = 5;
-		break;
-
-	case 24:
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-
-	default:
-		dev_dbg(info->device,
-			"Unsupported bpp size: %d\n", var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	/* use highest possible virtual resolution */
-	if (var->yres_virtual == -1) {
-		var->yres_virtual = pixels / var->xres_virtual;
-
-		dev_info(info->device,
-			 "virtual resolution set to maximum of %dx%d\n",
-			 var->xres_virtual, var->yres_virtual);
-	}
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	if (var->xres_virtual * var->yres_virtual > pixels) {
-		dev_err(info->device, "mode %dx%dx%d rejected... "
-		      "virtual resolution too high to fit into video memory!\n",
-			var->xres_virtual, var->yres_virtual,
-			var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	/* truncate xoffset and yoffset to maximum if too high */
-	if (var->xoffset > var->xres_virtual - var->xres)
-		var->xoffset = var->xres_virtual - var->xres - 1;
-	if (var->yoffset > var->yres_virtual - var->yres)
-		var->yoffset = var->yres_virtual - var->yres - 1;
-
-	var->red.msb_right =
-	    var->green.msb_right =
-	    var->blue.msb_right =
-	    var->transp.offset =
-	    var->transp.length =
-	    var->transp.msb_right = 0;
-
-	yres = var->yres;
-	if (var->vmode & FB_VMODE_DOUBLE)
-		yres *= 2;
-	else if (var->vmode & FB_VMODE_INTERLACED)
-		yres = (yres + 1) / 2;
-
-	if (yres >= 1280) {
-		dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
-			"special treatment required! (TODO)\n");
-		return -EINVAL;
-	}
-
-	if (cirrusfb_check_pixclock(var, info))
-		return -EINVAL;
-
-	if (!is_laguna(cinfo))
-		var->accel_flags = FB_ACCELF_TEXT;
-
-	return 0;
-}
-
-static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	unsigned char old1f, old1e;
-
-	assert(cinfo != NULL);
-	old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
-
-	if (div) {
-		dev_dbg(info->device, "Set %s as pixclock source.\n",
-			(div == 2) ? "MCLK/2" : "MCLK");
-		old1f |= 0x40;
-		old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
-		if (div == 2)
-			old1e |= 1;
-
-		vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
-	}
-	vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
-}
-
-/*************************************************************************
-	cirrusfb_set_par_foo()
-
-	actually writes the values for a new video mode into the hardware,
-**************************************************************************/
-static int cirrusfb_set_par_foo(struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	u8 __iomem *regbase = cinfo->regbase;
-	unsigned char tmp;
-	int pitch;
-	const struct cirrusfb_board_info_rec *bi;
-	int hdispend, hsyncstart, hsyncend, htotal;
-	int yres, vdispend, vsyncstart, vsyncend, vtotal;
-	long freq;
-	int nom, den, div;
-	unsigned int control = 0, format = 0, threshold = 0;
-
-	dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
-	       var->xres, var->yres, var->bits_per_pixel);
-
-	switch (var->bits_per_pixel) {
-	case 1:
-		info->fix.line_length = var->xres_virtual / 8;
-		info->fix.visual = FB_VISUAL_MONO10;
-		break;
-
-	case 8:
-		info->fix.line_length = var->xres_virtual;
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-
-	case 16:
-	case 24:
-		info->fix.line_length = var->xres_virtual *
-					var->bits_per_pixel >> 3;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	}
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-
-	init_vgachip(info);
-
-	bi = &cirrusfb_board_info[cinfo->btype];
-
-	hsyncstart = var->xres + var->right_margin;
-	hsyncend = hsyncstart + var->hsync_len;
-	htotal = (hsyncend + var->left_margin) / 8;
-	hdispend = var->xres / 8;
-	hsyncstart = hsyncstart / 8;
-	hsyncend = hsyncend / 8;
-
-	vdispend = var->yres;
-	vsyncstart = vdispend + var->lower_margin;
-	vsyncend = vsyncstart + var->vsync_len;
-	vtotal = vsyncend + var->upper_margin;
-
-	if (var->vmode & FB_VMODE_DOUBLE) {
-		vdispend *= 2;
-		vsyncstart *= 2;
-		vsyncend *= 2;
-		vtotal *= 2;
-	} else if (var->vmode & FB_VMODE_INTERLACED) {
-		vdispend = (vdispend + 1) / 2;
-		vsyncstart = (vsyncstart + 1) / 2;
-		vsyncend = (vsyncend + 1) / 2;
-		vtotal = (vtotal + 1) / 2;
-	}
-	yres = vdispend;
-	if (yres >= 1024) {
-		vtotal /= 2;
-		vsyncstart /= 2;
-		vsyncend /= 2;
-		vdispend /= 2;
-	}
-
-	vdispend -= 1;
-	vsyncstart -= 1;
-	vsyncend -= 1;
-	vtotal -= 2;
-
-	if (cinfo->multiplexing) {
-		htotal /= 2;
-		hsyncstart /= 2;
-		hsyncend /= 2;
-		hdispend /= 2;
-	}
-
-	htotal -= 5;
-	hdispend -= 1;
-	hsyncstart += 1;
-	hsyncend += 1;
-
-	/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
-	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);	/* previously: 0x00) */
-
-	/* if debugging is enabled, all parameters get output before writing */
-	dev_dbg(info->device, "CRT0: %d\n", htotal);
-	vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
-
-	dev_dbg(info->device, "CRT1: %d\n", hdispend);
-	vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
-
-	dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
-	vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
-
-	/*  + 128: Compatible read */
-	dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
-	vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
-		 128 + ((htotal + 5) % 32));
-
-	dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
-	vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
-
-	tmp = hsyncend % 32;
-	if ((htotal + 5) & 32)
-		tmp += 128;
-	dev_dbg(info->device, "CRT5: %d\n", tmp);
-	vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
-
-	dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
-	vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
-
-	tmp = 16;		/* LineCompare bit #9 */
-	if (vtotal & 256)
-		tmp |= 1;
-	if (vdispend & 256)
-		tmp |= 2;
-	if (vsyncstart & 256)
-		tmp |= 4;
-	if ((vdispend + 1) & 256)
-		tmp |= 8;
-	if (vtotal & 512)
-		tmp |= 32;
-	if (vdispend & 512)
-		tmp |= 64;
-	if (vsyncstart & 512)
-		tmp |= 128;
-	dev_dbg(info->device, "CRT7: %d\n", tmp);
-	vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
-
-	tmp = 0x40;		/* LineCompare bit #8 */
-	if ((vdispend + 1) & 512)
-		tmp |= 0x20;
-	if (var->vmode & FB_VMODE_DOUBLE)
-		tmp |= 0x80;
-	dev_dbg(info->device, "CRT9: %d\n", tmp);
-	vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
-
-	dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
-	vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
-
-	dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
-	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
-
-	dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
-	vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
-
-	dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
-	vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
-
-	dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
-	vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
-
-	dev_dbg(info->device, "CRT18: 0xff\n");
-	vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
-
-	tmp = 0;
-	if (var->vmode & FB_VMODE_INTERLACED)
-		tmp |= 1;
-	if ((htotal + 5) & 64)
-		tmp |= 16;
-	if ((htotal + 5) & 128)
-		tmp |= 32;
-	if (vtotal & 256)
-		tmp |= 64;
-	if (vtotal & 512)
-		tmp |= 128;
-
-	dev_dbg(info->device, "CRT1a: %d\n", tmp);
-	vga_wcrt(regbase, CL_CRT1A, tmp);
-
-	freq = PICOS2KHZ(var->pixclock);
-	if (var->bits_per_pixel == 24)
-		if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64)
-			freq *= 3;
-	if (cinfo->multiplexing)
-		freq /= 2;
-	if (cinfo->doubleVCLK)
-		freq *= 2;
-
-	bestclock(freq, &nom, &den, &div);
-
-	dev_dbg(info->device, "VCLK freq: %ld kHz  nom: %d  den: %d  div: %d\n",
-		freq, nom, den, div);
-
-	/* set VCLK0 */
-	/* hardware RefClock: 14.31818 MHz */
-	/* formula: VClk = (OSC * N) / (D * (1+P)) */
-	/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
-
-	if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 ||
-	    cinfo->btype == BT_SD64) {
-		/* if freq is close to mclk or mclk/2 select mclk
-		 * as clock source
-		 */
-		int divMCLK = cirrusfb_check_mclk(info, freq);
-		if (divMCLK)
-			nom = 0;
-		cirrusfb_set_mclk_as_source(info, divMCLK);
-	}
-	if (is_laguna(cinfo)) {
-		long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
-		unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
-		unsigned short tile_control;
-
-		if (cinfo->btype == BT_LAGUNAB) {
-			tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
-			tile_control &= ~0x80;
-			fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
-		}
-
-		fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
-		fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
-		control = fb_readw(cinfo->laguna_mmio + 0x402);
-		threshold = fb_readw(cinfo->laguna_mmio + 0xea);
-		control &= ~0x6800;
-		format = 0;
-		threshold &= 0xffc0 & 0x3fbf;
-	}
-	if (nom) {
-		tmp = den << 1;
-		if (div != 0)
-			tmp |= 1;
-		/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
-		if ((cinfo->btype == BT_SD64) ||
-		    (cinfo->btype == BT_ALPINE) ||
-		    (cinfo->btype == BT_GD5480))
-			tmp |= 0x80;
-
-		/* Laguna chipset has reversed clock registers */
-		if (is_laguna(cinfo)) {
-			vga_wseq(regbase, CL_SEQRE, tmp);
-			vga_wseq(regbase, CL_SEQR1E, nom);
-		} else {
-			vga_wseq(regbase, CL_SEQRE, nom);
-			vga_wseq(regbase, CL_SEQR1E, tmp);
-		}
-	}
-
-	if (yres >= 1024)
-		/* 1280x1024 */
-		vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
-	else
-		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
-		 * address wrap, no compat. */
-		vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
-
-	/* don't know if it would hurt to also program this if no interlaced */
-	/* mode is used, but I feel better this way.. :-) */
-	if (var->vmode & FB_VMODE_INTERLACED)
-		vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
-	else
-		vga_wcrt(regbase, VGA_CRTC_REGS, 0x00);	/* interlace control */
-
-	/* adjust horizontal/vertical sync type (low/high), use VCLK3 */
-	/* enable display memory & CRTC I/O address for color mode */
-	tmp = 0x03 | 0xc;
-	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-		tmp |= 0x40;
-	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-		tmp |= 0x80;
-	WGen(cinfo, VGA_MIS_W, tmp);
-
-	/* text cursor on and start line */
-	vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
-	/* text cursor end line */
-	vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
-
-	/******************************************************
-	 *
-	 * 1 bpp
-	 *
-	 */
-
-	/* programming for different color depths */
-	if (var->bits_per_pixel == 1) {
-		dev_dbg(info->device, "preparing for 1 bit deep display\n");
-		vga_wgfx(regbase, VGA_GFX_MODE, 0);	/* mode register */
-
-		/* SR07 */
-		switch (cinfo->btype) {
-		case BT_SD64:
-		case BT_PICCOLO:
-		case BT_PICASSO:
-		case BT_SPECTRUM:
-		case BT_PICASSO4:
-		case BT_ALPINE:
-		case BT_GD5480:
-			vga_wseq(regbase, CL_SEQR7,
-				 cinfo->multiplexing ?
-					bi->sr07_1bpp_mux : bi->sr07_1bpp);
-			break;
-
-		case BT_LAGUNA:
-		case BT_LAGUNAB:
-			vga_wseq(regbase, CL_SEQR7,
-				vga_rseq(regbase, CL_SEQR7) & ~0x01);
-			break;
-
-		default:
-			dev_warn(info->device, "unknown Board\n");
-			break;
-		}
-
-		/* Extended Sequencer Mode */
-		switch (cinfo->btype) {
-
-		case BT_PICCOLO:
-		case BT_SPECTRUM:
-			/* evtl d0 bei 1 bit? avoid FIFO underruns..? */
-			vga_wseq(regbase, CL_SEQRF, 0xb0);
-			break;
-
-		case BT_PICASSO:
-			/* ## vorher d0 avoid FIFO underruns..? */
-			vga_wseq(regbase, CL_SEQRF, 0xd0);
-			break;
-
-		case BT_SD64:
-		case BT_PICASSO4:
-		case BT_ALPINE:
-		case BT_GD5480:
-		case BT_LAGUNA:
-		case BT_LAGUNAB:
-			/* do nothing */
-			break;
-
-		default:
-			dev_warn(info->device, "unknown Board\n");
-			break;
-		}
-
-		/* pixel mask: pass-through for first plane */
-		WGen(cinfo, VGA_PEL_MSK, 0x01);
-		if (cinfo->multiplexing)
-			/* hidden dac reg: 1280x1024 */
-			WHDR(cinfo, 0x4a);
-		else
-			/* hidden dac: nothing */
-			WHDR(cinfo, 0);
-		/* memory mode: odd/even, ext. memory */
-		vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
-		/* plane mask: only write to first plane */
-		vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
-	}
-
-	/******************************************************
-	 *
-	 * 8 bpp
-	 *
-	 */
-
-	else if (var->bits_per_pixel == 8) {
-		dev_dbg(info->device, "preparing for 8 bit deep display\n");
-		switch (cinfo->btype) {
-		case BT_SD64:
-		case BT_PICCOLO:
-		case BT_PICASSO:
-		case BT_SPECTRUM:
-		case BT_PICASSO4:
-		case BT_ALPINE:
-		case BT_GD5480:
-			vga_wseq(regbase, CL_SEQR7,
-				  cinfo->multiplexing ?
-					bi->sr07_8bpp_mux : bi->sr07_8bpp);
-			break;
-
-		case BT_LAGUNA:
-		case BT_LAGUNAB:
-			vga_wseq(regbase, CL_SEQR7,
-				vga_rseq(regbase, CL_SEQR7) | 0x01);
-			threshold |= 0x10;
-			break;
-
-		default:
-			dev_warn(info->device, "unknown Board\n");
-			break;
-		}
-
-		switch (cinfo->btype) {
-		case BT_PICCOLO:
-		case BT_PICASSO:
-		case BT_SPECTRUM:
-			/* Fast Page-Mode writes */
-			vga_wseq(regbase, CL_SEQRF, 0xb0);
-			break;
-
-		case BT_PICASSO4:
-#ifdef CONFIG_ZORRO
-			/* ### INCOMPLETE!! */
-			vga_wseq(regbase, CL_SEQRF, 0xb8);
-#endif
-		case BT_ALPINE:
-		case BT_SD64:
-		case BT_GD5480:
-		case BT_LAGUNA:
-		case BT_LAGUNAB:
-			/* do nothing */
-			break;
-
-		default:
-			dev_warn(info->device, "unknown board\n");
-			break;
-		}
-
-		/* mode register: 256 color mode */
-		vga_wgfx(regbase, VGA_GFX_MODE, 64);
-		if (cinfo->multiplexing)
-			/* hidden dac reg: 1280x1024 */
-			WHDR(cinfo, 0x4a);
-		else
-			/* hidden dac: nothing */
-			WHDR(cinfo, 0);
-	}
-
-	/******************************************************
-	 *
-	 * 16 bpp
-	 *
-	 */
-
-	else if (var->bits_per_pixel == 16) {
-		dev_dbg(info->device, "preparing for 16 bit deep display\n");
-		switch (cinfo->btype) {
-		case BT_PICCOLO:
-		case BT_SPECTRUM:
-			vga_wseq(regbase, CL_SEQR7, 0x87);
-			/* Fast Page-Mode writes */
-			vga_wseq(regbase, CL_SEQRF, 0xb0);
-			break;
-
-		case BT_PICASSO:
-			vga_wseq(regbase, CL_SEQR7, 0x27);
-			/* Fast Page-Mode writes */
-			vga_wseq(regbase, CL_SEQRF, 0xb0);
-			break;
-
-		case BT_SD64:
-		case BT_PICASSO4:
-		case BT_ALPINE:
-			/* Extended Sequencer Mode: 256c col. mode */
-			vga_wseq(regbase, CL_SEQR7,
-					cinfo->doubleVCLK ? 0xa3 : 0xa7);
-			break;
-
-		case BT_GD5480:
-			vga_wseq(regbase, CL_SEQR7, 0x17);
-			/* We already set SRF and SR1F */
-			break;
-
-		case BT_LAGUNA:
-		case BT_LAGUNAB:
-			vga_wseq(regbase, CL_SEQR7,
-				vga_rseq(regbase, CL_SEQR7) & ~0x01);
-			control |= 0x2000;
-			format |= 0x1400;
-			threshold |= 0x10;
-			break;
-
-		default:
-			dev_warn(info->device, "unknown Board\n");
-			break;
-		}
-
-		/* mode register: 256 color mode */
-		vga_wgfx(regbase, VGA_GFX_MODE, 64);
-#ifdef CONFIG_PCI
-		WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1);
-#elif defined(CONFIG_ZORRO)
-		/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
-		WHDR(cinfo, 0xa0);	/* hidden dac reg: nothing special */
-#endif
-	}
-
-	/******************************************************
-	 *
-	 * 24 bpp
-	 *
-	 */
-
-	else if (var->bits_per_pixel == 24) {
-		dev_dbg(info->device, "preparing for 24 bit deep display\n");
-		switch (cinfo->btype) {
-		case BT_PICCOLO:
-		case BT_SPECTRUM:
-			vga_wseq(regbase, CL_SEQR7, 0x85);
-			/* Fast Page-Mode writes */
-			vga_wseq(regbase, CL_SEQRF, 0xb0);
-			break;
-
-		case BT_PICASSO:
-			vga_wseq(regbase, CL_SEQR7, 0x25);
-			/* Fast Page-Mode writes */
-			vga_wseq(regbase, CL_SEQRF, 0xb0);
-			break;
-
-		case BT_SD64:
-		case BT_PICASSO4:
-		case BT_ALPINE:
-			/* Extended Sequencer Mode: 256c col. mode */
-			vga_wseq(regbase, CL_SEQR7, 0xa5);
-			break;
-
-		case BT_GD5480:
-			vga_wseq(regbase, CL_SEQR7, 0x15);
-			/* We already set SRF and SR1F */
-			break;
-
-		case BT_LAGUNA:
-		case BT_LAGUNAB:
-			vga_wseq(regbase, CL_SEQR7,
-				vga_rseq(regbase, CL_SEQR7) & ~0x01);
-			control |= 0x4000;
-			format |= 0x2400;
-			threshold |= 0x20;
-			break;
-
-		default:
-			dev_warn(info->device, "unknown Board\n");
-			break;
-		}
-
-		/* mode register: 256 color mode */
-		vga_wgfx(regbase, VGA_GFX_MODE, 64);
-		/* hidden dac reg: 8-8-8 mode (24 or 32) */
-		WHDR(cinfo, 0xc5);
-	}
-
-	/******************************************************
-	 *
-	 * unknown/unsupported bpp
-	 *
-	 */
-
-	else
-		dev_err(info->device,
-			"What's this? requested color depth == %d.\n",
-			var->bits_per_pixel);
-
-	pitch = info->fix.line_length >> 3;
-	vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
-	tmp = 0x22;
-	if (pitch & 0x100)
-		tmp |= 0x10;	/* offset overflow bit */
-
-	/* screen start addr #16-18, fastpagemode cycles */
-	vga_wcrt(regbase, CL_CRT1B, tmp);
-
-	/* screen start address bit 19 */
-	if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
-		vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
-
-	if (is_laguna(cinfo)) {
-		tmp = 0;
-		if ((htotal + 5) & 256)
-			tmp |= 128;
-		if (hdispend & 256)
-			tmp |= 64;
-		if (hsyncstart & 256)
-			tmp |= 48;
-		if (vtotal & 1024)
-			tmp |= 8;
-		if (vdispend & 1024)
-			tmp |= 4;
-		if (vsyncstart & 1024)
-			tmp |= 3;
-
-		vga_wcrt(regbase, CL_CRT1E, tmp);
-		dev_dbg(info->device, "CRT1e: %d\n", tmp);
-	}
-
-	/* pixel panning */
-	vga_wattr(regbase, CL_AR33, 0);
-
-	/* [ EGS: SetOffset(); ] */
-	/* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
-	AttrOn(cinfo);
-
-	if (is_laguna(cinfo)) {
-		/* no tiles */
-		fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
-		fb_writew(format, cinfo->laguna_mmio + 0xc0);
-		fb_writew(threshold, cinfo->laguna_mmio + 0xea);
-	}
-	/* finally, turn on everything - turn off "FullBandwidth" bit */
-	/* also, set "DotClock%2" bit where requested */
-	tmp = 0x01;
-
-/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
-    if (var->vmode & FB_VMODE_CLOCK_HALVE)
-	tmp |= 0x08;
-*/
-
-	vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
-	dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
-
-#ifdef CIRRUSFB_DEBUG
-	cirrusfb_dbg_reg_dump(info, NULL);
-#endif
-
-	return 0;
-}
-
-/* for some reason incomprehensible to me, cirrusfb requires that you write
- * the registers twice for the settings to take..grr. -dte */
-static int cirrusfb_set_par(struct fb_info *info)
-{
-	cirrusfb_set_par_foo(info);
-	return cirrusfb_set_par_foo(info);
-}
-
-static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			      unsigned blue, unsigned transp,
-			      struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-
-	if (regno > 255)
-		return -EINVAL;
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 v;
-		red >>= (16 - info->var.red.length);
-		green >>= (16 - info->var.green.length);
-		blue >>= (16 - info->var.blue.length);
-
-		if (regno >= 16)
-			return 1;
-		v = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset);
-
-		cinfo->pseudo_palette[regno] = v;
-		return 0;
-	}
-
-	if (info->var.bits_per_pixel == 8)
-		WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
-
-	return 0;
-
-}
-
-/*************************************************************************
-	cirrusfb_pan_display()
-
-	performs display panning - provided hardware permits this
-**************************************************************************/
-static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	int xoffset;
-	unsigned long base;
-	unsigned char tmp, xpix;
-	struct cirrusfb_info *cinfo = info->par;
-
-	/* no range checks for xoffset and yoffset,   */
-	/* as fb_pan_display has already done this */
-	if (var->vmode & FB_VMODE_YWRAP)
-		return -EINVAL;
-
-	xoffset = var->xoffset * info->var.bits_per_pixel / 8;
-
-	base = var->yoffset * info->fix.line_length + xoffset;
-
-	if (info->var.bits_per_pixel == 1) {
-		/* base is already correct */
-		xpix = (unsigned char) (var->xoffset % 8);
-	} else {
-		base /= 4;
-		xpix = (unsigned char) ((xoffset % 4) * 2);
-	}
-
-	if (!is_laguna(cinfo))
-		cirrusfb_WaitBLT(cinfo->regbase);
-
-	/* lower 8 + 8 bits of screen start address */
-	vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
-	vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
-
-	/* 0xf2 is %11110010, exclude tmp bits */
-	tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
-	/* construct bits 16, 17 and 18 of screen start address */
-	if (base & 0x10000)
-		tmp |= 0x01;
-	if (base & 0x20000)
-		tmp |= 0x04;
-	if (base & 0x40000)
-		tmp |= 0x08;
-
-	vga_wcrt(cinfo->regbase, CL_CRT1B, tmp);
-
-	/* construct bit 19 of screen start address */
-	if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
-		tmp = vga_rcrt(cinfo->regbase, CL_CRT1D);
-		if (is_laguna(cinfo))
-			tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
-		else
-			tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
-		vga_wcrt(cinfo->regbase, CL_CRT1D, tmp);
-	}
-
-	/* write pixel panning value to AR33; this does not quite work in 8bpp
-	 *
-	 * ### Piccolo..? Will this work?
-	 */
-	if (info->var.bits_per_pixel == 1)
-		vga_wattr(cinfo->regbase, CL_AR33, xpix);
-
-	return 0;
-}
-
-static int cirrusfb_blank(int blank_mode, struct fb_info *info)
-{
-	/*
-	 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
-	 * then the caller blanks by setting the CLUT (Color Look Up Table)
-	 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
-	 * failed due to e.g. a video mode which doesn't support it.
-	 * Implements VESA suspend and powerdown modes on hardware that
-	 * supports disabling hsync/vsync:
-	 *   blank_mode == 2: suspend vsync
-	 *   blank_mode == 3: suspend hsync
-	 *   blank_mode == 4: powerdown
-	 */
-	unsigned char val;
-	struct cirrusfb_info *cinfo = info->par;
-	int current_mode = cinfo->blank_mode;
-
-	dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
-
-	if (info->state != FBINFO_STATE_RUNNING ||
-	    current_mode == blank_mode) {
-		dev_dbg(info->device, "EXIT, returning 0\n");
-		return 0;
-	}
-
-	/* Undo current */
-	if (current_mode == FB_BLANK_NORMAL ||
-	    current_mode == FB_BLANK_UNBLANK)
-		/* clear "FullBandwidth" bit */
-		val = 0;
-	else
-		/* set "FullBandwidth" bit */
-		val = 0x20;
-
-	val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
-	vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		val = 0x00;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		val = 0x04;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		val = 0x02;
-		break;
-	case FB_BLANK_POWERDOWN:
-		val = 0x06;
-		break;
-	default:
-		dev_dbg(info->device, "EXIT, returning 1\n");
-		return 1;
-	}
-
-	vga_wgfx(cinfo->regbase, CL_GRE, val);
-
-	cinfo->blank_mode = blank_mode;
-	dev_dbg(info->device, "EXIT, returning 0\n");
-
-	/* Let fbcon do a soft blank for us */
-	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
-}
-
-/**** END   Hardware specific Routines **************************************/
-/****************************************************************************/
-/**** BEGIN Internal Routines ***********************************************/
-
-static void init_vgachip(struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	const struct cirrusfb_board_info_rec *bi;
-
-	assert(cinfo != NULL);
-
-	bi = &cirrusfb_board_info[cinfo->btype];
-
-	/* reset board globally */
-	switch (cinfo->btype) {
-	case BT_PICCOLO:
-		WSFR(cinfo, 0x01);
-		udelay(500);
-		WSFR(cinfo, 0x51);
-		udelay(500);
-		break;
-	case BT_PICASSO:
-		WSFR2(cinfo, 0xff);
-		udelay(500);
-		break;
-	case BT_SD64:
-	case BT_SPECTRUM:
-		WSFR(cinfo, 0x1f);
-		udelay(500);
-		WSFR(cinfo, 0x4f);
-		udelay(500);
-		break;
-	case BT_PICASSO4:
-		/* disable flickerfixer */
-		vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
-		mdelay(100);
-		/* mode */
-		vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
-	case BT_GD5480:  /* fall through */
-		/* from Klaus' NetBSD driver: */
-		vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
-	case BT_ALPINE:  /* fall through */
-		/* put blitter into 542x compat */
-		vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
-		break;
-
-	case BT_LAGUNA:
-	case BT_LAGUNAB:
-		/* Nothing to do to reset the board. */
-		break;
-
-	default:
-		dev_err(info->device, "Warning: Unknown board type\n");
-		break;
-	}
-
-	/* make sure RAM size set by this point */
-	assert(info->screen_size > 0);
-
-	/* the P4 is not fully initialized here; I rely on it having been */
-	/* inited under AmigaOS already, which seems to work just fine    */
-	/* (Klaus advised to do it this way)			      */
-
-	if (cinfo->btype != BT_PICASSO4) {
-		WGen(cinfo, CL_VSSM, 0x10);	/* EGS: 0x16 */
-		WGen(cinfo, CL_POS102, 0x01);
-		WGen(cinfo, CL_VSSM, 0x08);	/* EGS: 0x0e */
-
-		if (cinfo->btype != BT_SD64)
-			WGen(cinfo, CL_VSSM2, 0x01);
-
-		/* reset sequencer logic */
-		vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03);
-
-		/* FullBandwidth (video off) and 8/9 dot clock */
-		vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
-
-		/* "magic cookie" - doesn't make any sense to me.. */
-/*      vga_wgfx(cinfo->regbase, CL_GRA, 0xce);   */
-		/* unlock all extension registers */
-		vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
-
-		switch (cinfo->btype) {
-		case BT_GD5480:
-			vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
-			break;
-		case BT_ALPINE:
-		case BT_LAGUNA:
-		case BT_LAGUNAB:
-			break;
-		case BT_SD64:
-#ifdef CONFIG_ZORRO
-			vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
-#endif
-			break;
-		default:
-			vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
-			vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
-			break;
-		}
-	}
-	/* plane mask: nothing */
-	vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
-	/* character map select: doesn't even matter in gx mode */
-	vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
-	/* memory mode: chain4, ext. memory */
-	vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
-
-	/* controller-internal base address of video memory */
-	if (bi->init_sr07)
-		vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
-
-	/*  vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
-	/* EEPROM control: shouldn't be necessary to write to this at all.. */
-
-	/* graphics cursor X position (incomplete; position gives rem. 3 bits */
-	vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
-	/* graphics cursor Y position (..."... ) */
-	vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
-	/* graphics cursor attributes */
-	vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
-	/* graphics cursor pattern address */
-	vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
-
-	/* writing these on a P4 might give problems..  */
-	if (cinfo->btype != BT_PICASSO4) {
-		/* configuration readback and ext. color */
-		vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
-		/* signature generator */
-		vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
-	}
-
-	/* Screen A preset row scan: none */
-	vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
-	/* Text cursor start: disable text cursor */
-	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
-	/* Text cursor end: - */
-	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
-	/* text cursor location high: 0 */
-	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
-	/* text cursor location low: 0 */
-	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
-
-	/* Underline Row scanline: - */
-	vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
-	/* ### add 0x40 for text modes with > 30 MHz pixclock */
-	/* ext. display controls: ext.adr. wrap */
-	vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
-
-	/* Set/Reset registers: - */
-	vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
-	/* Set/Reset enable: - */
-	vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
-	/* Color Compare: - */
-	vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
-	/* Data Rotate: - */
-	vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
-	/* Read Map Select: - */
-	vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
-	/* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
-	vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
-	/* Miscellaneous: memory map base address, graphics mode */
-	vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
-	/* Color Don't care: involve all planes */
-	vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
-	/* Bit Mask: no mask at all */
-	vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
-
-	if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 ||
-	    is_laguna(cinfo))
-		/* (5434 can't have bit 3 set for bitblt) */
-		vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
-	else
-	/* Graphics controller mode extensions: finer granularity,
-	 * 8byte data latches
-	 */
-		vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
-
-	vga_wgfx(cinfo->regbase, CL_GRC, 0xff);	/* Color Key compare: - */
-	vga_wgfx(cinfo->regbase, CL_GRD, 0x00);	/* Color Key compare mask: - */
-	vga_wgfx(cinfo->regbase, CL_GRE, 0x00);	/* Miscellaneous control: - */
-	/* Background color byte 1: - */
-	/*  vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
-	/*  vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
-
-	/* Attribute Controller palette registers: "identity mapping" */
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
-	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
-
-	/* Attribute Controller mode: graphics mode */
-	vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
-	/* Overscan color reg.: reg. 0 */
-	vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
-	/* Color Plane enable: Enable all 4 planes */
-	vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
-	/* Color Select: - */
-	vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
-
-	WGen(cinfo, VGA_PEL_MSK, 0xff);	/* Pixel mask: no mask */
-
-	/* BLT Start/status: Blitter reset */
-	vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
-	/* - " -	   : "end-of-reset" */
-	vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
-
-	/* misc... */
-	WHDR(cinfo, 0);	/* Hidden DAC register: - */
-	return;
-}
-
-static void switch_monitor(struct cirrusfb_info *cinfo, int on)
-{
-#ifdef CONFIG_ZORRO /* only works on Zorro boards */
-	static int IsOn = 0;	/* XXX not ok for multiple boards */
-
-	if (cinfo->btype == BT_PICASSO4)
-		return;		/* nothing to switch */
-	if (cinfo->btype == BT_ALPINE)
-		return;		/* nothing to switch */
-	if (cinfo->btype == BT_GD5480)
-		return;		/* nothing to switch */
-	if (cinfo->btype == BT_PICASSO) {
-		if ((on && !IsOn) || (!on && IsOn))
-			WSFR(cinfo, 0xff);
-		return;
-	}
-	if (on) {
-		switch (cinfo->btype) {
-		case BT_SD64:
-			WSFR(cinfo, cinfo->SFR | 0x21);
-			break;
-		case BT_PICCOLO:
-			WSFR(cinfo, cinfo->SFR | 0x28);
-			break;
-		case BT_SPECTRUM:
-			WSFR(cinfo, 0x6f);
-			break;
-		default: /* do nothing */ break;
-		}
-	} else {
-		switch (cinfo->btype) {
-		case BT_SD64:
-			WSFR(cinfo, cinfo->SFR & 0xde);
-			break;
-		case BT_PICCOLO:
-			WSFR(cinfo, cinfo->SFR & 0xd7);
-			break;
-		case BT_SPECTRUM:
-			WSFR(cinfo, 0x4f);
-			break;
-		default: /* do nothing */
-			break;
-		}
-	}
-#endif /* CONFIG_ZORRO */
-}
-
-/******************************************/
-/* Linux 2.6-style  accelerated functions */
-/******************************************/
-
-static int cirrusfb_sync(struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-
-	if (!is_laguna(cinfo)) {
-		while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03)
-			cpu_relax();
-	}
-	return 0;
-}
-
-static void cirrusfb_fillrect(struct fb_info *info,
-			      const struct fb_fillrect *region)
-{
-	struct fb_fillrect modded;
-	int vxres, vyres;
-	struct cirrusfb_info *cinfo = info->par;
-	int m = info->var.bits_per_pixel;
-	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
-		cinfo->pseudo_palette[region->color] : region->color;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(info, region);
-		return;
-	}
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	memcpy(&modded, region, sizeof(struct fb_fillrect));
-
-	if (!modded.width || !modded.height ||
-	   modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.dx + modded.width  > vxres)
-		modded.width  = vxres - modded.dx;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	cirrusfb_RectFill(cinfo->regbase,
-			  info->var.bits_per_pixel,
-			  (region->dx * m) / 8, region->dy,
-			  (region->width * m) / 8, region->height,
-			  color, color,
-			  info->fix.line_length, 0x40);
-}
-
-static void cirrusfb_copyarea(struct fb_info *info,
-			      const struct fb_copyarea *area)
-{
-	struct fb_copyarea modded;
-	u32 vxres, vyres;
-	struct cirrusfb_info *cinfo = info->par;
-	int m = info->var.bits_per_pixel;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-	memcpy(&modded, area, sizeof(struct fb_copyarea));
-
-	if (!modded.width || !modded.height ||
-	   modded.sx >= vxres || modded.sy >= vyres ||
-	   modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.sx + modded.width > vxres)
-		modded.width = vxres - modded.sx;
-	if (modded.dx + modded.width > vxres)
-		modded.width = vxres - modded.dx;
-	if (modded.sy + modded.height > vyres)
-		modded.height = vyres - modded.sy;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
-			(area->sx * m) / 8, area->sy,
-			(area->dx * m) / 8, area->dy,
-			(area->width * m) / 8, area->height,
-			info->fix.line_length);
-
-}
-
-static void cirrusfb_imageblit(struct fb_info *info,
-			       const struct fb_image *image)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	/* Alpine/SD64 does not work at 24bpp ??? */
-	if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
-		cfb_imageblit(info, image);
-	else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) &&
-		  op == 0xc)
-		cfb_imageblit(info, image);
-	else {
-		unsigned size = ((image->width + 7) >> 3) * image->height;
-		int m = info->var.bits_per_pixel;
-		u32 fg, bg;
-
-		if (info->var.bits_per_pixel == 8) {
-			fg = image->fg_color;
-			bg = image->bg_color;
-		} else {
-			fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
-			bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
-		}
-		if (info->var.bits_per_pixel == 24) {
-			/* clear background first */
-			cirrusfb_RectFill(cinfo->regbase,
-					  info->var.bits_per_pixel,
-					  (image->dx * m) / 8, image->dy,
-					  (image->width * m) / 8,
-					  image->height,
-					  bg, bg,
-					  info->fix.line_length, 0x40);
-		}
-		cirrusfb_RectFill(cinfo->regbase,
-				  info->var.bits_per_pixel,
-				  (image->dx * m) / 8, image->dy,
-				  (image->width * m) / 8, image->height,
-				  fg, bg,
-				  info->fix.line_length, op);
-		memcpy(info->screen_base, image->data, size);
-	}
-}
-
-#ifdef CONFIG_PCI
-static int release_io_ports;
-
-/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
- * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
- * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
- * seem to have. */
-static unsigned int cirrusfb_get_memsize(struct fb_info *info,
-					 u8 __iomem *regbase)
-{
-	unsigned long mem;
-	struct cirrusfb_info *cinfo = info->par;
-
-	if (is_laguna(cinfo)) {
-		unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
-
-		mem = ((SR14 & 7) + 1) << 20;
-	} else {
-		unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
-		switch ((SRF & 0x18)) {
-		case 0x08:
-			mem = 512 * 1024;
-			break;
-		case 0x10:
-			mem = 1024 * 1024;
-			break;
-		/* 64-bit DRAM data bus width; assume 2MB.
-		 * Also indicates 2MB memory on the 5430.
-		 */
-		case 0x18:
-			mem = 2048 * 1024;
-			break;
-		default:
-			dev_warn(info->device, "Unknown memory size!\n");
-			mem = 1024 * 1024;
-		}
-		/* If DRAM bank switching is enabled, there must be
-		 * twice as much memory installed. (4MB on the 5434)
-		 */
-		if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0)
-			mem *= 2;
-	}
-
-	/* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
-	return mem;
-}
-
-static void get_pci_addrs(const struct pci_dev *pdev,
-			  unsigned long *display, unsigned long *registers)
-{
-	assert(pdev != NULL);
-	assert(display != NULL);
-	assert(registers != NULL);
-
-	*display = 0;
-	*registers = 0;
-
-	/* This is a best-guess for now */
-
-	if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
-		*display = pci_resource_start(pdev, 1);
-		*registers = pci_resource_start(pdev, 0);
-	} else {
-		*display = pci_resource_start(pdev, 0);
-		*registers = pci_resource_start(pdev, 1);
-	}
-
-	assert(*display != 0);
-}
-
-static void cirrusfb_pci_unmap(struct fb_info *info)
-{
-	struct pci_dev *pdev = to_pci_dev(info->device);
-	struct cirrusfb_info *cinfo = info->par;
-
-	if (cinfo->laguna_mmio == NULL)
-		iounmap(cinfo->laguna_mmio);
-	iounmap(info->screen_base);
-#if 0 /* if system didn't claim this region, we would... */
-	release_mem_region(0xA0000, 65535);
-#endif
-	if (release_io_ports)
-		release_region(0x3C0, 32);
-	pci_release_regions(pdev);
-}
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_ZORRO
-static void cirrusfb_zorro_unmap(struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	struct zorro_dev *zdev = to_zorro_dev(info->device);
-
-	if (info->fix.smem_start > 16 * MB_)
-		iounmap(info->screen_base);
-	if (info->fix.mmio_start > 16 * MB_)
-		iounmap(cinfo->regbase);
-
-	zorro_release_device(zdev);
-}
-#endif /* CONFIG_ZORRO */
-
-/* function table of the above functions */
-static struct fb_ops cirrusfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= cirrusfb_open,
-	.fb_release	= cirrusfb_release,
-	.fb_setcolreg	= cirrusfb_setcolreg,
-	.fb_check_var	= cirrusfb_check_var,
-	.fb_set_par	= cirrusfb_set_par,
-	.fb_pan_display = cirrusfb_pan_display,
-	.fb_blank	= cirrusfb_blank,
-	.fb_fillrect	= cirrusfb_fillrect,
-	.fb_copyarea	= cirrusfb_copyarea,
-	.fb_sync	= cirrusfb_sync,
-	.fb_imageblit	= cirrusfb_imageblit,
-};
-
-static int cirrusfb_set_fbinfo(struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-
-	info->pseudo_palette = cinfo->pseudo_palette;
-	info->flags = FBINFO_DEFAULT
-		    | FBINFO_HWACCEL_XPAN
-		    | FBINFO_HWACCEL_YPAN
-		    | FBINFO_HWACCEL_FILLRECT
-		    | FBINFO_HWACCEL_IMAGEBLIT
-		    | FBINFO_HWACCEL_COPYAREA;
-	if (noaccel || is_laguna(cinfo)) {
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-		info->fix.accel = FB_ACCEL_NONE;
-	} else
-		info->fix.accel = FB_ACCEL_CIRRUS_ALPINE;
-
-	info->fbops = &cirrusfb_ops;
-
-	if (cinfo->btype == BT_GD5480) {
-		if (var->bits_per_pixel == 16)
-			info->screen_base += 1 * MB_;
-		if (var->bits_per_pixel == 32)
-			info->screen_base += 2 * MB_;
-	}
-
-	/* Fill fix common fields */
-	strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
-		sizeof(info->fix.id));
-
-	/* monochrome: only 1 memory plane */
-	/* 8 bit and above: Use whole memory area */
-	info->fix.smem_len   = info->screen_size;
-	if (var->bits_per_pixel == 1)
-		info->fix.smem_len /= 4;
-	info->fix.type_aux   = 0;
-	info->fix.xpanstep   = 1;
-	info->fix.ypanstep   = 1;
-	info->fix.ywrapstep  = 0;
-
-	/* FIXME: map region at 0xB8000 if available, fill in here */
-	info->fix.mmio_len   = 0;
-
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	return 0;
-}
-
-static int cirrusfb_register(struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-	int err;
-
-	/* sanity checks */
-	assert(cinfo->btype != BT_NONE);
-
-	/* set all the vital stuff */
-	cirrusfb_set_fbinfo(info);
-
-	dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
-
-	err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
-	if (!err) {
-		dev_dbg(info->device, "wrong initial video mode\n");
-		err = -EINVAL;
-		goto err_dealloc_cmap;
-	}
-
-	info->var.activate = FB_ACTIVATE_NOW;
-
-	err = cirrusfb_check_var(&info->var, info);
-	if (err < 0) {
-		/* should never happen */
-		dev_dbg(info->device,
-			"choking on default var... umm, no good.\n");
-		goto err_dealloc_cmap;
-	}
-
-	err = register_framebuffer(info);
-	if (err < 0) {
-		dev_err(info->device,
-			"could not register fb device; err = %d!\n", err);
-		goto err_dealloc_cmap;
-	}
-
-	return 0;
-
-err_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-	return err;
-}
-
-static void cirrusfb_cleanup(struct fb_info *info)
-{
-	struct cirrusfb_info *cinfo = info->par;
-
-	switch_monitor(cinfo, 0);
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-	dev_dbg(info->device, "Framebuffer unregistered\n");
-	cinfo->unmap(info);
-	framebuffer_release(info);
-}
-
-#ifdef CONFIG_PCI
-static int cirrusfb_pci_register(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	struct cirrusfb_info *cinfo;
-	struct fb_info *info;
-	unsigned long board_addr, board_size;
-	int ret;
-
-	ret = pci_enable_device(pdev);
-	if (ret < 0) {
-		printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
-		goto err_out;
-	}
-
-	info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
-	if (!info) {
-		printk(KERN_ERR "cirrusfb: could not allocate memory\n");
-		ret = -ENOMEM;
-		goto err_out;
-	}
-
-	cinfo = info->par;
-	cinfo->btype = (enum cirrus_board) ent->driver_data;
-
-	dev_dbg(info->device,
-		" Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
-		(unsigned long long)pdev->resource[0].start,  cinfo->btype);
-	dev_dbg(info->device, " base address 1 is 0x%Lx\n",
-		(unsigned long long)pdev->resource[1].start);
-
-	dev_dbg(info->device,
-		"Attempt to get PCI info for Cirrus Graphics Card\n");
-	get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
-	/* FIXME: this forces VGA.  alternatives? */
-	cinfo->regbase = NULL;
-	cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
-
-	dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
-		board_addr, info->fix.mmio_start);
-
-	board_size = (cinfo->btype == BT_GD5480) ?
-		32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
-
-	ret = pci_request_regions(pdev, "cirrusfb");
-	if (ret < 0) {
-		dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
-			board_addr);
-		goto err_release_fb;
-	}
-#if 0 /* if the system didn't claim this region, we would... */
-	if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
-		dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
-			0xA0000L);
-		ret = -EBUSY;
-		goto err_release_regions;
-	}
-#endif
-	if (request_region(0x3C0, 32, "cirrusfb"))
-		release_io_ports = 1;
-
-	info->screen_base = ioremap(board_addr, board_size);
-	if (!info->screen_base) {
-		ret = -EIO;
-		goto err_release_legacy;
-	}
-
-	info->fix.smem_start = board_addr;
-	info->screen_size = board_size;
-	cinfo->unmap = cirrusfb_pci_unmap;
-
-	dev_info(info->device,
-		 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
-		 info->screen_size >> 10, board_addr);
-	pci_set_drvdata(pdev, info);
-
-	ret = cirrusfb_register(info);
-	if (!ret)
-		return 0;
-
-	iounmap(info->screen_base);
-err_release_legacy:
-	if (release_io_ports)
-		release_region(0x3C0, 32);
-#if 0
-	release_mem_region(0xA0000, 65535);
-err_release_regions:
-#endif
-	pci_release_regions(pdev);
-err_release_fb:
-	if (cinfo->laguna_mmio != NULL)
-		iounmap(cinfo->laguna_mmio);
-	framebuffer_release(info);
-err_out:
-	return ret;
-}
-
-static void cirrusfb_pci_unregister(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-
-	cirrusfb_cleanup(info);
-}
-
-static struct pci_driver cirrusfb_pci_driver = {
-	.name		= "cirrusfb",
-	.id_table	= cirrusfb_pci_table,
-	.probe		= cirrusfb_pci_register,
-	.remove		= cirrusfb_pci_unregister,
-#ifdef CONFIG_PM
-#if 0
-	.suspend	= cirrusfb_pci_suspend,
-	.resume		= cirrusfb_pci_resume,
-#endif
-#endif
-};
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_ZORRO
-static int cirrusfb_zorro_register(struct zorro_dev *z,
-				   const struct zorro_device_id *ent)
-{
-	struct fb_info *info;
-	int error;
-	const struct zorrocl *zcl;
-	enum cirrus_board btype;
-	unsigned long regbase, ramsize, rambase;
-	struct cirrusfb_info *cinfo;
-
-	info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
-	if (!info) {
-		printk(KERN_ERR "cirrusfb: could not allocate memory\n");
-		return -ENOMEM;
-	}
-
-	zcl = (const struct zorrocl *)ent->driver_data;
-	btype = zcl->type;
-	regbase = zorro_resource_start(z) + zcl->regoffset;
-	ramsize = zcl->ramsize;
-	if (ramsize) {
-		rambase = zorro_resource_start(z) + zcl->ramoffset;
-		if (zorro_resource_len(z) == 64 * MB_) {
-			/* Quirk for 64 MiB Picasso IV */
-			rambase += zcl->ramoffset;
-		}
-	} else {
-		struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
-		if (!ram || !zorro_resource_len(ram)) {
-			dev_err(info->device, "No video RAM found\n");
-			error = -ENODEV;
-			goto err_release_fb;
-		}
-		rambase = zorro_resource_start(ram);
-		ramsize = zorro_resource_len(ram);
-		if (zcl->ramid2 &&
-		    (ram = zorro_find_device(zcl->ramid2, NULL))) {
-			if (zorro_resource_start(ram) != rambase + ramsize) {
-				dev_warn(info->device,
-					 "Skipping non-contiguous RAM at %pR\n",
-					 &ram->resource);
-			} else {
-				ramsize += zorro_resource_len(ram);
-			}
-		}
-	}
-
-	dev_info(info->device,
-		 "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
-		 cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
-		 rambase);
-
-	if (!zorro_request_device(z, "cirrusfb")) {
-		dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
-		error = -EBUSY;
-		goto err_release_fb;
-	}
-
-	cinfo = info->par;
-	cinfo->btype = btype;
-
-	info->fix.mmio_start = regbase;
-	cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
-					    : ZTWO_VADDR(regbase);
-	if (!cinfo->regbase) {
-		dev_err(info->device, "Cannot map registers\n");
-		error = -EIO;
-		goto err_release_dev;
-	}
-
-	info->fix.smem_start = rambase;
-	info->screen_size = ramsize;
-	info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
-					       : ZTWO_VADDR(rambase);
-	if (!info->screen_base) {
-		dev_err(info->device, "Cannot map video RAM\n");
-		error = -EIO;
-		goto err_unmap_reg;
-	}
-
-	cinfo->unmap = cirrusfb_zorro_unmap;
-
-	dev_info(info->device,
-		 "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
-		 ramsize / MB_, rambase);
-
-	/* MCLK select etc. */
-	if (cirrusfb_board_info[btype].init_sr1f)
-		vga_wseq(cinfo->regbase, CL_SEQR1F,
-			 cirrusfb_board_info[btype].sr1f);
-
-	error = cirrusfb_register(info);
-	if (error) {
-		dev_err(info->device, "Failed to register device, error %d\n",
-			error);
-		goto err_unmap_ram;
-	}
-
-	zorro_set_drvdata(z, info);
-	return 0;
-
-err_unmap_ram:
-	if (rambase > 16 * MB_)
-		iounmap(info->screen_base);
-
-err_unmap_reg:
-	if (regbase > 16 * MB_)
-		iounmap(cinfo->regbase);
-err_release_dev:
-	zorro_release_device(z);
-err_release_fb:
-	framebuffer_release(info);
-	return error;
-}
-
-void cirrusfb_zorro_unregister(struct zorro_dev *z)
-{
-	struct fb_info *info = zorro_get_drvdata(z);
-
-	cirrusfb_cleanup(info);
-	zorro_set_drvdata(z, NULL);
-}
-
-static struct zorro_driver cirrusfb_zorro_driver = {
-	.name		= "cirrusfb",
-	.id_table	= cirrusfb_zorro_table,
-	.probe		= cirrusfb_zorro_register,
-	.remove		= cirrusfb_zorro_unregister,
-};
-#endif /* CONFIG_ZORRO */
-
-#ifndef MODULE
-static int __init cirrusfb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-
-		if (!strcmp(this_opt, "noaccel"))
-			noaccel = 1;
-		else if (!strncmp(this_opt, "mode:", 5))
-			mode_option = this_opt + 5;
-		else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-#endif
-
-    /*
-     *  Modularization
-     */
-
-MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
-MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
-MODULE_LICENSE("GPL");
-
-static int __init cirrusfb_init(void)
-{
-	int error = 0;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("cirrusfb", &option))
-		return -ENODEV;
-	cirrusfb_setup(option);
-#endif
-
-#ifdef CONFIG_ZORRO
-	error |= zorro_register_driver(&cirrusfb_zorro_driver);
-#endif
-#ifdef CONFIG_PCI
-	error |= pci_register_driver(&cirrusfb_pci_driver);
-#endif
-	return error;
-}
-
-static void __exit cirrusfb_exit(void)
-{
-#ifdef CONFIG_PCI
-	pci_unregister_driver(&cirrusfb_pci_driver);
-#endif
-#ifdef CONFIG_ZORRO
-	zorro_unregister_driver(&cirrusfb_zorro_driver);
-#endif
-}
-
-module_init(cirrusfb_init);
-
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
-module_param(noaccel, bool, 0);
-MODULE_PARM_DESC(noaccel, "Disable acceleration");
-
-#ifdef MODULE
-module_exit(cirrusfb_exit);
-#endif
-
-/**********************************************************************/
-/* about the following functions - I have used the same names for the */
-/* functions as Markus Wild did in his Retina driver for NetBSD as    */
-/* they just made sense for this purpose. Apart from that, I wrote    */
-/* these functions myself.					    */
-/**********************************************************************/
-
-/*** WGen() - write into one of the external/general registers ***/
-static void WGen(const struct cirrusfb_info *cinfo,
-		  int regnum, unsigned char val)
-{
-	unsigned long regofs = 0;
-
-	if (cinfo->btype == BT_PICASSO) {
-		/* Picasso II specific hack */
-/*	      if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
-		  regnum == CL_VSSM2) */
-		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
-			regofs = 0xfff;
-	}
-
-	vga_w(cinfo->regbase, regofs + regnum, val);
-}
-
-/*** RGen() - read out one of the external/general registers ***/
-static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
-{
-	unsigned long regofs = 0;
-
-	if (cinfo->btype == BT_PICASSO) {
-		/* Picasso II specific hack */
-/*	      if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
-		  regnum == CL_VSSM2) */
-		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
-			regofs = 0xfff;
-	}
-
-	return vga_r(cinfo->regbase, regofs + regnum);
-}
-
-/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
-static void AttrOn(const struct cirrusfb_info *cinfo)
-{
-	assert(cinfo != NULL);
-
-	if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
-		/* if we're just in "write value" mode, write back the */
-		/* same value as before to not modify anything */
-		vga_w(cinfo->regbase, VGA_ATT_IW,
-		      vga_r(cinfo->regbase, VGA_ATT_R));
-	}
-	/* turn on video bit */
-/*      vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
-	vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
-
-	/* dummy write on Reg0 to be on "write index" mode next time */
-	vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
-}
-
-/*** WHDR() - write into the Hidden DAC register ***/
-/* as the HDR is the only extension register that requires special treatment
- * (the other extension registers are accessible just like the "ordinary"
- * registers of their functional group) here is a specialized routine for
- * accessing the HDR
- */
-static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
-{
-	unsigned char dummy;
-
-	if (is_laguna(cinfo))
-		return;
-	if (cinfo->btype == BT_PICASSO) {
-		/* Klaus' hint for correct access to HDR on some boards */
-		/* first write 0 to pixel mask (3c6) */
-		WGen(cinfo, VGA_PEL_MSK, 0x00);
-		udelay(200);
-		/* next read dummy from pixel address (3c8) */
-		dummy = RGen(cinfo, VGA_PEL_IW);
-		udelay(200);
-	}
-	/* now do the usual stuff to access the HDR */
-
-	dummy = RGen(cinfo, VGA_PEL_MSK);
-	udelay(200);
-	dummy = RGen(cinfo, VGA_PEL_MSK);
-	udelay(200);
-	dummy = RGen(cinfo, VGA_PEL_MSK);
-	udelay(200);
-	dummy = RGen(cinfo, VGA_PEL_MSK);
-	udelay(200);
-
-	WGen(cinfo, VGA_PEL_MSK, val);
-	udelay(200);
-
-	if (cinfo->btype == BT_PICASSO) {
-		/* now first reset HDR access counter */
-		dummy = RGen(cinfo, VGA_PEL_IW);
-		udelay(200);
-
-		/* and at the end, restore the mask value */
-		/* ## is this mask always 0xff? */
-		WGen(cinfo, VGA_PEL_MSK, 0xff);
-		udelay(200);
-	}
-}
-
-/*** WSFR() - write to the "special function register" (SFR) ***/
-static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
-{
-#ifdef CONFIG_ZORRO
-	assert(cinfo->regbase != NULL);
-	cinfo->SFR = val;
-	z_writeb(val, cinfo->regbase + 0x8000);
-#endif
-}
-
-/* The Picasso has a second register for switching the monitor bit */
-static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
-{
-#ifdef CONFIG_ZORRO
-	/* writing an arbitrary value to this one causes the monitor switcher */
-	/* to flip to Amiga display */
-	assert(cinfo->regbase != NULL);
-	cinfo->SFR = val;
-	z_writeb(val, cinfo->regbase + 0x9000);
-#endif
-}
-
-/*** WClut - set CLUT entry (range: 0..63) ***/
-static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
-	    unsigned char green, unsigned char blue)
-{
-	unsigned int data = VGA_PEL_D;
-
-	/* address write mode register is not translated.. */
-	vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
-
-	if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
-	    cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
-	    cinfo->btype == BT_SD64 || is_laguna(cinfo)) {
-		/* but DAC data register IS, at least for Picasso II */
-		if (cinfo->btype == BT_PICASSO)
-			data += 0xfff;
-		vga_w(cinfo->regbase, data, red);
-		vga_w(cinfo->regbase, data, green);
-		vga_w(cinfo->regbase, data, blue);
-	} else {
-		vga_w(cinfo->regbase, data, blue);
-		vga_w(cinfo->regbase, data, green);
-		vga_w(cinfo->regbase, data, red);
-	}
-}
-
-#if 0
-/*** RClut - read CLUT entry (range 0..63) ***/
-static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
-	    unsigned char *green, unsigned char *blue)
-{
-	unsigned int data = VGA_PEL_D;
-
-	vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
-
-	if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
-	    cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
-		if (cinfo->btype == BT_PICASSO)
-			data += 0xfff;
-		*red = vga_r(cinfo->regbase, data);
-		*green = vga_r(cinfo->regbase, data);
-		*blue = vga_r(cinfo->regbase, data);
-	} else {
-		*blue = vga_r(cinfo->regbase, data);
-		*green = vga_r(cinfo->regbase, data);
-		*red = vga_r(cinfo->regbase, data);
-	}
-}
-#endif
-
-/*******************************************************************
-	cirrusfb_WaitBLT()
-
-	Wait for the BitBLT engine to complete a possible earlier job
-*********************************************************************/
-
-/* FIXME: use interrupts instead */
-static void cirrusfb_WaitBLT(u8 __iomem *regbase)
-{
-	while (vga_rgfx(regbase, CL_GR31) & 0x08)
-		cpu_relax();
-}
-
-/*******************************************************************
-	cirrusfb_BitBLT()
-
-	perform accelerated "scrolling"
-********************************************************************/
-
-static void cirrusfb_set_blitter(u8 __iomem *regbase,
-			    u_short nwidth, u_short nheight,
-			    u_long nsrc, u_long ndest,
-			    u_short bltmode, u_short line_length)
-
-{
-	/* pitch: set to line_length */
-	/* dest pitch low */
-	vga_wgfx(regbase, CL_GR24, line_length & 0xff);
-	/* dest pitch hi */
-	vga_wgfx(regbase, CL_GR25, line_length >> 8);
-	/* source pitch low */
-	vga_wgfx(regbase, CL_GR26, line_length & 0xff);
-	/* source pitch hi */
-	vga_wgfx(regbase, CL_GR27, line_length >> 8);
-
-	/* BLT width: actual number of pixels - 1 */
-	/* BLT width low */
-	vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
-	/* BLT width hi */
-	vga_wgfx(regbase, CL_GR21, nwidth >> 8);
-
-	/* BLT height: actual number of lines -1 */
-	/* BLT height low */
-	vga_wgfx(regbase, CL_GR22, nheight & 0xff);
-	/* BLT width hi */
-	vga_wgfx(regbase, CL_GR23, nheight >> 8);
-
-	/* BLT destination */
-	/* BLT dest low */
-	vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
-	/* BLT dest mid */
-	vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
-	/* BLT dest hi */
-	vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
-
-	/* BLT source */
-	/* BLT src low */
-	vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
-	/* BLT src mid */
-	vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
-	/* BLT src hi */
-	vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
-
-	/* BLT mode */
-	vga_wgfx(regbase, CL_GR30, bltmode);	/* BLT mode */
-
-	/* BLT ROP: SrcCopy */
-	vga_wgfx(regbase, CL_GR32, 0x0d);	/* BLT ROP */
-
-	/* and finally: GO! */
-	vga_wgfx(regbase, CL_GR31, 0x02);	/* BLT Start/status */
-}
-
-/*******************************************************************
-	cirrusfb_BitBLT()
-
-	perform accelerated "scrolling"
-********************************************************************/
-
-static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
-			    u_short curx, u_short cury,
-			    u_short destx, u_short desty,
-			    u_short width, u_short height,
-			    u_short line_length)
-{
-	u_short nwidth = width - 1;
-	u_short nheight = height - 1;
-	u_long nsrc, ndest;
-	u_char bltmode;
-
-	bltmode = 0x00;
-	/* if source adr < dest addr, do the Blt backwards */
-	if (cury <= desty) {
-		if (cury == desty) {
-			/* if src and dest are on the same line, check x */
-			if (curx < destx)
-				bltmode |= 0x01;
-		} else
-			bltmode |= 0x01;
-	}
-	/* standard case: forward blitting */
-	nsrc = (cury * line_length) + curx;
-	ndest = (desty * line_length) + destx;
-	if (bltmode) {
-		/* this means start addresses are at the end,
-		 * counting backwards
-		 */
-		nsrc += nheight * line_length + nwidth;
-		ndest += nheight * line_length + nwidth;
-	}
-
-	cirrusfb_WaitBLT(regbase);
-
-	cirrusfb_set_blitter(regbase, nwidth, nheight,
-			    nsrc, ndest, bltmode, line_length);
-}
-
-/*******************************************************************
-	cirrusfb_RectFill()
-
-	perform accelerated rectangle fill
-********************************************************************/
-
-static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
-		     u_short x, u_short y, u_short width, u_short height,
-		     u32 fg_color, u32 bg_color, u_short line_length,
-		     u_char blitmode)
-{
-	u_long ndest = (y * line_length) + x;
-	u_char op;
-
-	cirrusfb_WaitBLT(regbase);
-
-	/* This is a ColorExpand Blt, using the */
-	/* same color for foreground and background */
-	vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color);
-	vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color);
-
-	op = 0x80;
-	if (bits_per_pixel >= 16) {
-		vga_wgfx(regbase, CL_GR10, bg_color >> 8);
-		vga_wgfx(regbase, CL_GR11, fg_color >> 8);
-		op = 0x90;
-	}
-	if (bits_per_pixel >= 24) {
-		vga_wgfx(regbase, CL_GR12, bg_color >> 16);
-		vga_wgfx(regbase, CL_GR13, fg_color >> 16);
-		op = 0xa0;
-	}
-	if (bits_per_pixel == 32) {
-		vga_wgfx(regbase, CL_GR14, bg_color >> 24);
-		vga_wgfx(regbase, CL_GR15, fg_color >> 24);
-		op = 0xb0;
-	}
-	cirrusfb_set_blitter(regbase, width - 1, height - 1,
-			    0, ndest, op | blitmode, line_length);
-}
-
-/**************************************************************************
- * bestclock() - determine closest possible clock lower(?) than the
- * desired pixel clock
- **************************************************************************/
-static void bestclock(long freq, int *nom, int *den, int *div)
-{
-	int n, d;
-	long h, diff;
-
-	assert(nom != NULL);
-	assert(den != NULL);
-	assert(div != NULL);
-
-	*nom = 0;
-	*den = 0;
-	*div = 0;
-
-	if (freq < 8000)
-		freq = 8000;
-
-	diff = freq;
-
-	for (n = 32; n < 128; n++) {
-		int s = 0;
-
-		d = (14318 * n) / freq;
-		if ((d >= 7) && (d <= 63)) {
-			int temp = d;
-
-			if (temp > 31) {
-				s = 1;
-				temp >>= 1;
-			}
-			h = ((14318 * n) / temp) >> s;
-			h = h > freq ? h - freq : freq - h;
-			if (h < diff) {
-				diff = h;
-				*nom = n;
-				*den = temp;
-				*div = s;
-			}
-		}
-		d++;
-		if ((d >= 7) && (d <= 63)) {
-			if (d > 31) {
-				s = 1;
-				d >>= 1;
-			}
-			h = ((14318 * n) / d) >> s;
-			h = h > freq ? h - freq : freq - h;
-			if (h < diff) {
-				diff = h;
-				*nom = n;
-				*den = d;
-				*div = s;
-			}
-		}
-	}
-}
-
-/* -------------------------------------------------------------------------
- *
- * debugging functions
- *
- * -------------------------------------------------------------------------
- */
-
-#ifdef CIRRUSFB_DEBUG
-
-/**
- * cirrusfb_dbg_print_regs
- * @base: If using newmmio, the newmmio base address, otherwise %NULL
- * @reg_class: type of registers to read: %CRT, or %SEQ
- *
- * DESCRIPTION:
- * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
- * old-style I/O ports are queried for information, otherwise MMIO is
- * used at the given @base address to query the information.
- */
-
-static void cirrusfb_dbg_print_regs(struct fb_info *info,
-				    caddr_t regbase,
-				    enum cirrusfb_dbg_reg_class reg_class, ...)
-{
-	va_list list;
-	unsigned char val = 0;
-	unsigned reg;
-	char *name;
-
-	va_start(list, reg_class);
-
-	name = va_arg(list, char *);
-	while (name != NULL) {
-		reg = va_arg(list, int);
-
-		switch (reg_class) {
-		case CRT:
-			val = vga_rcrt(regbase, (unsigned char) reg);
-			break;
-		case SEQ:
-			val = vga_rseq(regbase, (unsigned char) reg);
-			break;
-		default:
-			/* should never occur */
-			assert(false);
-			break;
-		}
-
-		dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
-
-		name = va_arg(list, char *);
-	}
-
-	va_end(list);
-}
-
-/**
- * cirrusfb_dbg_reg_dump
- * @base: If using newmmio, the newmmio base address, otherwise %NULL
- *
- * DESCRIPTION:
- * Dumps a list of interesting VGA and CIRRUSFB registers.  If @base is %NULL,
- * old-style I/O ports are queried for information, otherwise MMIO is
- * used at the given @base address to query the information.
- */
-
-static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
-{
-	dev_dbg(info->device, "VGA CRTC register dump:\n");
-
-	cirrusfb_dbg_print_regs(info, regbase, CRT,
-			   "CR00", 0x00,
-			   "CR01", 0x01,
-			   "CR02", 0x02,
-			   "CR03", 0x03,
-			   "CR04", 0x04,
-			   "CR05", 0x05,
-			   "CR06", 0x06,
-			   "CR07", 0x07,
-			   "CR08", 0x08,
-			   "CR09", 0x09,
-			   "CR0A", 0x0A,
-			   "CR0B", 0x0B,
-			   "CR0C", 0x0C,
-			   "CR0D", 0x0D,
-			   "CR0E", 0x0E,
-			   "CR0F", 0x0F,
-			   "CR10", 0x10,
-			   "CR11", 0x11,
-			   "CR12", 0x12,
-			   "CR13", 0x13,
-			   "CR14", 0x14,
-			   "CR15", 0x15,
-			   "CR16", 0x16,
-			   "CR17", 0x17,
-			   "CR18", 0x18,
-			   "CR22", 0x22,
-			   "CR24", 0x24,
-			   "CR26", 0x26,
-			   "CR2D", 0x2D,
-			   "CR2E", 0x2E,
-			   "CR2F", 0x2F,
-			   "CR30", 0x30,
-			   "CR31", 0x31,
-			   "CR32", 0x32,
-			   "CR33", 0x33,
-			   "CR34", 0x34,
-			   "CR35", 0x35,
-			   "CR36", 0x36,
-			   "CR37", 0x37,
-			   "CR38", 0x38,
-			   "CR39", 0x39,
-			   "CR3A", 0x3A,
-			   "CR3B", 0x3B,
-			   "CR3C", 0x3C,
-			   "CR3D", 0x3D,
-			   "CR3E", 0x3E,
-			   "CR3F", 0x3F,
-			   NULL);
-
-	dev_dbg(info->device, "\n");
-
-	dev_dbg(info->device, "VGA SEQ register dump:\n");
-
-	cirrusfb_dbg_print_regs(info, regbase, SEQ,
-			   "SR00", 0x00,
-			   "SR01", 0x01,
-			   "SR02", 0x02,
-			   "SR03", 0x03,
-			   "SR04", 0x04,
-			   "SR08", 0x08,
-			   "SR09", 0x09,
-			   "SR0A", 0x0A,
-			   "SR0B", 0x0B,
-			   "SR0D", 0x0D,
-			   "SR10", 0x10,
-			   "SR11", 0x11,
-			   "SR12", 0x12,
-			   "SR13", 0x13,
-			   "SR14", 0x14,
-			   "SR15", 0x15,
-			   "SR16", 0x16,
-			   "SR17", 0x17,
-			   "SR18", 0x18,
-			   "SR19", 0x19,
-			   "SR1A", 0x1A,
-			   "SR1B", 0x1B,
-			   "SR1C", 0x1C,
-			   "SR1D", 0x1D,
-			   "SR1E", 0x1E,
-			   "SR1F", 0x1F,
-			   NULL);
-
-	dev_dbg(info->device, "\n");
-}
-
-#endif				/* CIRRUSFB_DEBUG */
-
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
deleted file mode 100644
index f00980607b8f..000000000000
--- a/drivers/video/clps711xfb.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- *  linux/drivers/video/clps711xfb.c
- *
- *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *  Framebuffer driver for the CLPS7111 and EP7212 processors.
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <linux/uaccess.h>
-
-struct fb_info	*cfb;
-
-#define CMAP_MAX_SIZE	16
-
-/*
- * LCD AC Prescale.  This comes from the LCD panel manufacturers specifications.
- * This determines how many clocks + 1 of CL1 before the M signal toggles.
- * The number of lines on the display must not be divisible by this number.
- */
-static unsigned int lcd_ac_prescale = 13;
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-static int
-clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		     u_int transp, struct fb_info *info)
-{
-	unsigned int level, mask, shift, pal;
-
-	if (regno >= (1 << info->var.bits_per_pixel))
-		return 1;
-
-	/* gray = 0.30*R + 0.58*G + 0.11*B */
-	level = (red * 77 + green * 151 + blue * 28) >> 20;
-
-	/*
-	 * On an LCD, a high value is dark, while a low value is light. 
-	 * So we invert the level.
-	 *
-	 * This isn't true on all machines, so we only do it on EDB7211.
-	 *  --rmk
-	 */
-	if (machine_is_edb7211()) {
-		level = 15 - level;
-	}
-
-	shift = 4 * (regno & 7);
-	level <<= shift;
-	mask  = 15 << shift;
-	level &= mask;
-
-	regno = regno < 8 ? PALLSW : PALMSW;
-
-	pal = clps_readl(regno);
-	pal = (pal & ~mask) | level;
-	clps_writel(pal, regno);
-
-	return 0;
-}
-
-/*
- * Validate the purposed mode.
- */	
-static int
-clps7111fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	var->transp.msb_right	= 0;
-	var->transp.offset	= 0;
-	var->transp.length	= 0;
-	var->red.msb_right	= 0;
-	var->red.offset		= 0;
-	var->red.length		= var->bits_per_pixel;
-	var->green		= var->red;
-	var->blue		= var->red;
-
-	if (var->bits_per_pixel > 4) 
-		return -EINVAL;
-
-	return 0;
-}
-
-/*
- * Set the hardware state.
- */ 
-static int 
-clps7111fb_set_par(struct fb_info *info)
-{
-	unsigned int lcdcon, syscon, pixclock;
-
-	switch (info->var.bits_per_pixel) {
-	case 1:
-		info->fix.visual = FB_VISUAL_MONO01;
-		break;
-	case 2:
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 4:
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	}
-
-	info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
-
-	lcdcon = (info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel) / 128 - 1;
-	lcdcon |= ((info->var.xres_virtual / 16) - 1) << 13;
-	lcdcon |= lcd_ac_prescale << 25;
-
-	/*
-	 * Calculate pixel prescale value from the pixclock.  This is:
-	 *  36.864MHz / pixclock_mhz - 1.
-	 * However, pixclock is in picoseconds, so this ends up being:
-	 *  36864000 * pixclock_ps / 10^12 - 1
-	 * and this will overflow the 32-bit math.  We perform this as
-	 * (9 * 4096000 == 36864000):
-	 *  pixclock_ps * 9 * (4096000 / 10^12) - 1
-	 */
-	pixclock = 9 * info->var.pixclock / 244140 - 1;
-	lcdcon |= pixclock << 19;
-
-	if (info->var.bits_per_pixel == 4)
-		lcdcon |= LCDCON_GSMD;
-	if (info->var.bits_per_pixel >= 2)
-		lcdcon |= LCDCON_GSEN;
-
-	/*
-	 * LCDCON must only be changed while the LCD is disabled
-	 */
-	syscon = clps_readl(SYSCON1);
-	clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
-	clps_writel(lcdcon, LCDCON);
-	clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
-	return 0;
-}
-
-static int clps7111fb_blank(int blank, struct fb_info *info)
-{
-	/* Enable/Disable LCD controller. */
-	if (blank)
-		clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN, SYSCON1);
-	else
-		clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN, SYSCON1);
-
-	return 0;
-}
-
-static struct fb_ops clps7111fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= clps7111fb_check_var,
-	.fb_set_par	= clps7111fb_set_par,
-	.fb_setcolreg	= clps7111fb_setcolreg,
-	.fb_blank	= clps7111fb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static void clps711x_guess_lcd_params(struct fb_info *info)
-{
-	unsigned int lcdcon, syscon, size;
-	unsigned long phys_base = PAGE_OFFSET;
-	void *virt_base = (void *)PAGE_OFFSET;
-
-	info->var.xres_virtual	 = 640;
-	info->var.yres_virtual	 = 240;
-	info->var.bits_per_pixel = 4;
-	info->var.activate	 = FB_ACTIVATE_NOW;
-	info->var.height	 = -1;
-	info->var.width		 = -1;
-	info->var.pixclock	 = 93006; /* 10.752MHz pixel clock */
-
-	/*
-	 * If the LCD controller is already running, decode the values
-	 * in LCDCON to xres/yres/bpp/pixclock/acprescale
-	 */
-	syscon = clps_readl(SYSCON1);
-	if (syscon & SYSCON1_LCDEN) {
-		lcdcon = clps_readl(LCDCON);
-
-		/*
-		 * Decode GSMD and GSEN bits to bits per pixel
-		 */
-		switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
-		case LCDCON_GSMD | LCDCON_GSEN:
-			info->var.bits_per_pixel = 4;
-			break;
-
-		case LCDCON_GSEN:
-			info->var.bits_per_pixel = 2;
-			break;
-
-		default:
-			info->var.bits_per_pixel = 1;
-			break;
-		}
-
-		/*
-		 * Decode xres/yres
-		 */
-		info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
-		info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
-					  (info->var.xres_virtual *
-					   info->var.bits_per_pixel);
-
-		/*
-		 * Calculate pixclock
-		 */
-		info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
-
-		/*
-		 * Grab AC prescale
-		 */
-		lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
-	}
-
-	info->var.xres = info->var.xres_virtual;
-	info->var.yres = info->var.yres_virtual;
-	info->var.grayscale = info->var.bits_per_pixel > 1;
-
-	size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
-
-	/*
-	 * Might be worth checking to see if we can use the on-board
-	 * RAM if size here...
-	 * CLPS7110 - no on-board SRAM
-	 * EP7212   - 38400 bytes
-	 */
-	if (size <= 38400) {
-		printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
-	}
-
-	if ((syscon & SYSCON1_LCDEN) == 0) {
-		/*
-		 * The display isn't running.  Ensure that
-		 * the display memory is empty.
-		 */
-		memset(virt_base, 0, size);
-	}
-
-	info->screen_base    = virt_base;
-	info->fix.smem_start = phys_base;
-	info->fix.smem_len   = PAGE_ALIGN(size);
-	info->fix.type       = FB_TYPE_PACKED_PIXELS;
-}
-
-static int clps711x_fb_probe(struct platform_device *pdev)
-{
-	int err = -ENOMEM;
-
-	if (fb_get_options("clps711xfb", NULL))
-		return -ENODEV;
-
-	cfb = kzalloc(sizeof(*cfb), GFP_KERNEL);
-	if (!cfb)
-		goto out;
-
-	strcpy(cfb->fix.id, "clps711x");
-
-	cfb->fbops		= &clps7111fb_ops;
-	cfb->flags		= FBINFO_DEFAULT;
-
-	clps711x_guess_lcd_params(cfb);
-
-	fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
-
-	err = register_framebuffer(cfb);
-
-out:	return err;
-}
-
-static int clps711x_fb_remove(struct platform_device *pdev)
-{
-	unregister_framebuffer(cfb);
-	kfree(cfb);
-
-	return 0;
-}
-
-static struct platform_driver clps711x_fb_driver = {
-	.driver	= {
-		.name	= "video-clps711x",
-		.owner	= THIS_MODULE,
-	},
-	.probe	= clps711x_fb_probe,
-	.remove	= clps711x_fb_remove,
-};
-module_platform_driver(clps711x_fb_driver);
-
-MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-MODULE_DESCRIPTION("CLPS711X framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
deleted file mode 100644
index d5533f4db1cf..000000000000
--- a/drivers/video/cobalt_lcdfb.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- *  Cobalt/SEAD3 LCD frame buffer driver.
- *
- *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
- *  Copyright (C) 2012  MIPS Technologies, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-
-/*
- * Cursor position address
- * \X  0    1    2  ...  14   15
- * Y+----+----+----+---+----+----+
- * 0|0x00|0x01|0x02|...|0x0e|0x0f|
- *  +----+----+----+---+----+----+
- * 1|0x40|0x41|0x42|...|0x4e|0x4f|
- *  +----+----+----+---+----+----+
- */
-#define LCD_DATA_REG_OFFSET	0x10
-#define LCD_XRES_MAX		16
-#define LCD_YRES_MAX		2
-#define LCD_CHARS_MAX		32
-
-#define LCD_CLEAR		0x01
-#define LCD_CURSOR_MOVE_HOME	0x02
-#define LCD_RESET		0x06
-#define LCD_OFF			0x08
-#define LCD_CURSOR_OFF		0x0c
-#define LCD_CURSOR_BLINK_OFF	0x0e
-#define LCD_CURSOR_ON		0x0f
-#define LCD_ON			LCD_CURSOR_ON
-#define LCD_CURSOR_MOVE_LEFT	0x10
-#define LCD_CURSOR_MOVE_RIGHT	0x14
-#define LCD_DISPLAY_LEFT	0x18
-#define LCD_DISPLAY_RIGHT	0x1c
-#define LCD_PRERESET		0x3f	/* execute 4 times continuously */
-#define LCD_BUSY		0x80
-
-#define LCD_GRAPHIC_MODE	0x40
-#define LCD_TEXT_MODE		0x80
-#define LCD_CUR_POS_MASK	0x7f
-
-#define LCD_CUR_POS(x)		((x) & LCD_CUR_POS_MASK)
-#define LCD_TEXT_POS(x)		((x) | LCD_TEXT_MODE)
-
-#ifdef CONFIG_MIPS_COBALT
-static inline void lcd_write_control(struct fb_info *info, u8 control)
-{
-	writel((u32)control << 24, info->screen_base);
-}
-
-static inline u8 lcd_read_control(struct fb_info *info)
-{
-	return readl(info->screen_base) >> 24;
-}
-
-static inline void lcd_write_data(struct fb_info *info, u8 data)
-{
-	writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET);
-}
-
-static inline u8 lcd_read_data(struct fb_info *info)
-{
-	return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
-}
-#else
-
-#define LCD_CTL			0x00
-#define LCD_DATA		0x08
-#define CPLD_STATUS		0x10
-#define CPLD_DATA		0x18
-
-static inline void cpld_wait(struct fb_info *info)
-{
-	do {
-	} while (readl(info->screen_base + CPLD_STATUS) & 1);
-}
-
-static inline void lcd_write_control(struct fb_info *info, u8 control)
-{
-	cpld_wait(info);
-	writel(control, info->screen_base + LCD_CTL);
-}
-
-static inline u8 lcd_read_control(struct fb_info *info)
-{
-	cpld_wait(info);
-	readl(info->screen_base + LCD_CTL);
-	cpld_wait(info);
-	return readl(info->screen_base + CPLD_DATA) & 0xff;
-}
-
-static inline void lcd_write_data(struct fb_info *info, u8 data)
-{
-	cpld_wait(info);
-	writel(data, info->screen_base + LCD_DATA);
-}
-
-static inline u8 lcd_read_data(struct fb_info *info)
-{
-	cpld_wait(info);
-	readl(info->screen_base + LCD_DATA);
-	cpld_wait(info);
-	return readl(info->screen_base + CPLD_DATA) & 0xff;
-}
-#endif
-
-static int lcd_busy_wait(struct fb_info *info)
-{
-	u8 val = 0;
-	int timeout = 10, retval = 0;
-
-	do {
-		val = lcd_read_control(info);
-		val &= LCD_BUSY;
-		if (val != LCD_BUSY)
-			break;
-
-		if (msleep_interruptible(1))
-			return -EINTR;
-
-		timeout--;
-	} while (timeout);
-
-	if (val == LCD_BUSY)
-		retval = -EBUSY;
-
-	return retval;
-}
-
-static void lcd_clear(struct fb_info *info)
-{
-	int i;
-
-	for (i = 0; i < 4; i++) {
-		udelay(150);
-
-		lcd_write_control(info, LCD_PRERESET);
-	}
-
-	udelay(150);
-
-	lcd_write_control(info, LCD_CLEAR);
-
-	udelay(150);
-
-	lcd_write_control(info, LCD_RESET);
-}
-
-static struct fb_fix_screeninfo cobalt_lcdfb_fix = {
-	.id		= "cobalt-lcd",
-	.type		= FB_TYPE_TEXT,
-	.type_aux	= FB_AUX_TEXT_MDA,
-	.visual		= FB_VISUAL_MONO01,
-	.line_length	= LCD_XRES_MAX,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
-				 size_t count, loff_t *ppos)
-{
-	char src[LCD_CHARS_MAX];
-	unsigned long pos;
-	int len, retval = 0;
-
-	pos = *ppos;
-	if (pos >= LCD_CHARS_MAX || count == 0)
-		return 0;
-
-	if (count > LCD_CHARS_MAX)
-		count = LCD_CHARS_MAX;
-
-	if (pos + count > LCD_CHARS_MAX)
-		count = LCD_CHARS_MAX - pos;
-
-	for (len = 0; len < count; len++) {
-		retval = lcd_busy_wait(info);
-		if (retval < 0)
-			break;
-
-		lcd_write_control(info, LCD_TEXT_POS(pos));
-
-		retval = lcd_busy_wait(info);
-		if (retval < 0)
-			break;
-
-		src[len] = lcd_read_data(info);
-		if (pos == 0x0f)
-			pos = 0x40;
-		else
-			pos++;
-	}
-
-	if (retval < 0 && signal_pending(current))
-		return -ERESTARTSYS;
-
-	if (copy_to_user(buf, src, len))
-		return -EFAULT;
-
-	*ppos += len;
-
-	return len;
-}
-
-static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
-				  size_t count, loff_t *ppos)
-{
-	char dst[LCD_CHARS_MAX];
-	unsigned long pos;
-	int len, retval = 0;
-
-	pos = *ppos;
-	if (pos >= LCD_CHARS_MAX || count == 0)
-		return 0;
-
-	if (count > LCD_CHARS_MAX)
-		count = LCD_CHARS_MAX;
-
-	if (pos + count > LCD_CHARS_MAX)
-		count = LCD_CHARS_MAX - pos;
-
-	if (copy_from_user(dst, buf, count))
-		return -EFAULT;
-
-	for (len = 0; len < count; len++) {
-		retval = lcd_busy_wait(info);
-		if (retval < 0)
-			break;
-
-		lcd_write_control(info, LCD_TEXT_POS(pos));
-
-		retval = lcd_busy_wait(info);
-		if (retval < 0)
-			break;
-
-		lcd_write_data(info, dst[len]);
-		if (pos == 0x0f)
-			pos = 0x40;
-		else
-			pos++;
-	}
-
-	if (retval < 0 && signal_pending(current))
-		return -ERESTARTSYS;
-
-	*ppos += len;
-
-	return len;
-}
-
-static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info)
-{
-	int retval;
-
-	retval = lcd_busy_wait(info);
-	if (retval < 0)
-		return retval;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		lcd_write_control(info, LCD_ON);
-		break;
-	default:
-		lcd_write_control(info, LCD_OFF);
-		break;
-	}
-
-	return 0;
-}
-
-static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	u32 x, y;
-	int retval;
-
-	switch (cursor->set) {
-	case FB_CUR_SETPOS:
-		x = cursor->image.dx;
-		y = cursor->image.dy;
-		if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX)
-			return -EINVAL;
-
-		retval = lcd_busy_wait(info);
-		if (retval < 0)
-			return retval;
-
-		lcd_write_control(info,
-				  LCD_TEXT_POS(info->fix.line_length * y + x));
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	retval = lcd_busy_wait(info);
-	if (retval < 0)
-		return retval;
-
-	if (cursor->enable)
-		lcd_write_control(info, LCD_CURSOR_ON);
-	else
-		lcd_write_control(info, LCD_CURSOR_OFF);
-
-	return 0;
-}
-
-static struct fb_ops cobalt_lcd_fbops = {
-	.owner		= THIS_MODULE,
-	.fb_read	= cobalt_lcdfb_read,
-	.fb_write	= cobalt_lcdfb_write,
-	.fb_blank	= cobalt_lcdfb_blank,
-	.fb_cursor	= cobalt_lcdfb_cursor,
-};
-
-static int cobalt_lcdfb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	struct resource *res;
-	int retval;
-
-	info = framebuffer_alloc(0, &dev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res) {
-		framebuffer_release(info);
-		return -EBUSY;
-	}
-
-	info->screen_size = resource_size(res);
-	info->screen_base = devm_ioremap(&dev->dev, res->start,
-					 info->screen_size);
-	info->fbops = &cobalt_lcd_fbops;
-	info->fix = cobalt_lcdfb_fix;
-	info->fix.smem_start = res->start;
-	info->fix.smem_len = info->screen_size;
-	info->pseudo_palette = NULL;
-	info->par = NULL;
-	info->flags = FBINFO_DEFAULT;
-
-	retval = register_framebuffer(info);
-	if (retval < 0) {
-		framebuffer_release(info);
-		return retval;
-	}
-
-	platform_set_drvdata(dev, info);
-
-	lcd_clear(info);
-
-	fb_info(info, "Cobalt server LCD frame buffer device\n");
-
-	return 0;
-}
-
-static int cobalt_lcdfb_remove(struct platform_device *dev)
-{
-	struct fb_info *info;
-
-	info = platform_get_drvdata(dev);
-	if (info) {
-		unregister_framebuffer(info);
-		framebuffer_release(info);
-	}
-
-	return 0;
-}
-
-static struct platform_driver cobalt_lcdfb_driver = {
-	.probe	= cobalt_lcdfb_probe,
-	.remove	= cobalt_lcdfb_remove,
-	.driver	= {
-		.name	= "cobalt-lcd",
-		.owner	= THIS_MODULE,
-	},
-};
-module_platform_driver(cobalt_lcdfb_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Yoichi Yuasa");
-MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver");
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 5f65ca3d8564..026fd1215933 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -46,7 +46,7 @@
 
 #include <asm/io.h>
 
-#include "../sticore.h"
+#include "../fbdev/sticore.h"
 
 /* switching to graphics mode */
 #define BLANK 0
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index cecd3de01c24..7da1ad03acb5 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -28,7 +28,7 @@
 #include <asm/cacheflush.h>
 #include <asm/grfioctl.h>
 
-#include "../sticore.h"
+#include "../fbdev/sticore.h"
 
 #define STI_DRIVERVERSION "Version 0.9b"
 
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
deleted file mode 100644
index fdadef979238..000000000000
--- a/drivers/video/controlfb.c
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
- *  controlfb.c -- frame buffer device for the PowerMac 'control' display
- *
- *  Created 12 July 1998 by Dan Jacobowitz <dan@debian.org>
- *  Copyright (C) 1998 Dan Jacobowitz
- *  Copyright (C) 2001 Takashi Oe
- *
- *  Mmap code by Michel Lanners <mlan@cpu.lu>
- *
- *  Frame buffer structure from:
- *    drivers/video/chipsfb.c -- frame buffer device for
- *    Chips & Technologies 65550 chip.
- *
- *    Copyright (C) 1998 Paul Mackerras
- *
- *    This file is derived from the Powermac "chips" driver:
- *    Copyright (C) 1997 Fabio Riccardi.
- *    And from the frame buffer device for Open Firmware-initialized devices:
- *    Copyright (C) 1997 Geert Uytterhoeven.
- *
- *  Hardware information from:
- *    control.c: Console support for PowerMac "control" display adaptor.
- *    Copyright (C) 1996 Paul Mackerras
- *
- *  Updated to 2.5 framebuffer API by Ben Herrenschmidt
- *  <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>,
- *  and James Simmons <jsimmons@infradead.org>.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/nvram.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pgtable.h>
-#include <asm/btext.h>
-
-#include "macmodes.h"
-#include "controlfb.h"
-
-struct fb_par_control {
-	int	vmode, cmode;
-	int	xres, yres;
-	int	vxres, vyres;
-	int	xoffset, yoffset;
-	int	pitch;
-	struct control_regvals	regvals;
-	unsigned long sync;
-	unsigned char ctrl;
-};
-
-#define DIRTY(z) ((x)->z != (y)->z)
-#define DIRTY_CMAP(z) (memcmp(&((x)->z), &((y)->z), sizeof((y)->z)))
-static inline int PAR_EQUAL(struct fb_par_control *x, struct fb_par_control *y)
-{
-	int i, results;
-
-	results = 1;
-	for (i = 0; i < 3; i++)
-		results &= !DIRTY(regvals.clock_params[i]);
-	if (!results)
-		return 0;
-	for (i = 0; i < 16; i++)
-		results &= !DIRTY(regvals.regs[i]);
-	if (!results)
-		return 0;
-	return (!DIRTY(cmode) && !DIRTY(xres) && !DIRTY(yres)
-		&& !DIRTY(vxres) && !DIRTY(vyres));
-}
-static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninfo *y)
-{
-	return (!DIRTY(bits_per_pixel) && !DIRTY(xres)
-		&& !DIRTY(yres) && !DIRTY(xres_virtual)
-		&& !DIRTY(yres_virtual)
-		&& !DIRTY_CMAP(red) && !DIRTY_CMAP(green) && !DIRTY_CMAP(blue));
-}
-
-struct fb_info_control {
-	struct fb_info		info;
-	struct fb_par_control	par;
-	u32			pseudo_palette[16];
-		
-	struct cmap_regs	__iomem *cmap_regs;
-	unsigned long		cmap_regs_phys;
-	
-	struct control_regs	__iomem *control_regs;
-	unsigned long		control_regs_phys;
-	unsigned long		control_regs_size;
-	
-	__u8			__iomem *frame_buffer;
-	unsigned long		frame_buffer_phys;
-	unsigned long		fb_orig_base;
-	unsigned long		fb_orig_size;
-
-	int			control_use_bank2;
-	unsigned long		total_vram;
-	unsigned char		vram_attr;
-};
-
-/* control register access macro */
-#define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->REG).r))
-
-
-/******************** Prototypes for exported functions ********************/
-/*
- * struct fb_ops
- */
-static int controlfb_pan_display(struct fb_var_screeninfo *var,
-	struct fb_info *info);
-static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-	u_int transp, struct fb_info *info);
-static int controlfb_blank(int blank_mode, struct fb_info *info);
-static int controlfb_mmap(struct fb_info *info,
-	struct vm_area_struct *vma);
-static int controlfb_set_par (struct fb_info *info);
-static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
-
-/******************** Prototypes for internal functions **********************/
-
-static void set_control_clock(unsigned char *params);
-static int init_control(struct fb_info_control *p);
-static void control_set_hardware(struct fb_info_control *p,
-	struct fb_par_control *par);
-static int control_of_init(struct device_node *dp);
-static void find_vram_size(struct fb_info_control *p);
-static int read_control_sense(struct fb_info_control *p);
-static int calc_clock_params(unsigned long clk, unsigned char *param);
-static int control_var_to_par(struct fb_var_screeninfo *var,
-	struct fb_par_control *par, const struct fb_info *fb_info);
-static inline void control_par_to_var(struct fb_par_control *par,
-	struct fb_var_screeninfo *var);
-static void control_init_info(struct fb_info *info, struct fb_info_control *p);
-static void control_cleanup(void);
-
-
-/************************** Internal variables *******************************/
-
-static struct fb_info_control *control_fb;
-
-static int default_vmode __initdata = VMODE_NVRAM;
-static int default_cmode __initdata = CMODE_NVRAM;
-
-
-static struct fb_ops controlfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= controlfb_check_var,
-	.fb_set_par	= controlfb_set_par,
-	.fb_setcolreg	= controlfb_setcolreg,
-	.fb_pan_display = controlfb_pan_display,
-	.fb_blank	= controlfb_blank,
-	.fb_mmap	= controlfb_mmap,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-
-/********************  The functions for controlfb_ops ********************/
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	struct device_node *dp;
-	int ret = -ENXIO;
-
-	dp = of_find_node_by_name(NULL, "control");
-	if (dp != 0 && !control_of_init(dp))
-		ret = 0;
-	of_node_put(dp);
-
-	return ret;
-}
-
-void cleanup_module(void)
-{
-	control_cleanup();
-}
-#endif
-
-/*
- * Checks a var structure
- */
-static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct fb_par_control par;
-	int err;
-
-	err = control_var_to_par(var, &par, info);
-	if (err)
-		return err;	
-	control_par_to_var(&par, var);
-
-	return 0;
-}
-
-/*
- * Applies current var to display
- */
-static int controlfb_set_par (struct fb_info *info)
-{
-	struct fb_info_control *p = (struct fb_info_control *) info;
-	struct fb_par_control par;
-	int err;
-
-	if((err = control_var_to_par(&info->var, &par, info))) {
-		printk (KERN_ERR "controlfb_set_par: error calling"
-				 " control_var_to_par: %d.\n", err);
-		return err;
-	}
-	
-	control_set_hardware(p, &par);
-
-	info->fix.visual = (p->par.cmode == CMODE_8) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-	info->fix.line_length = p->par.pitch;
-	info->fix.xpanstep = 32 >> p->par.cmode;
-	info->fix.ypanstep = 1;
-
-	return 0;
-}
-
-/*
- * Set screen start address according to var offset values
- */
-static inline void set_screen_start(int xoffset, int yoffset,
-	struct fb_info_control *p)
-{
-	struct fb_par_control *par = &p->par;
-
-	par->xoffset = xoffset;
-	par->yoffset = yoffset;
-	out_le32(CNTRL_REG(p,start_addr),
-		 par->yoffset * par->pitch + (par->xoffset << par->cmode));
-}
-
-
-static int controlfb_pan_display(struct fb_var_screeninfo *var,
-				 struct fb_info *info)
-{
-	unsigned int xoffset, hstep;
-	struct fb_info_control *p = (struct fb_info_control *)info;
-	struct fb_par_control *par = &p->par;
-
-	/*
-	 * make sure start addr will be 32-byte aligned
-	 */
-	hstep = 0x1f >> par->cmode;
-	xoffset = (var->xoffset + hstep) & ~hstep;
-
-	if (xoffset+par->xres > par->vxres ||
-	    var->yoffset+par->yres > par->vyres)
-		return -EINVAL;
-
-	set_screen_start(xoffset, var->yoffset, p);
-
-	return 0;
-}
-
-
-/*
- * Private mmap since we want to have a different caching on the framebuffer
- * for controlfb.
- * Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
- */
-static int controlfb_mmap(struct fb_info *info,
-                       struct vm_area_struct *vma)
-{
-	unsigned long mmio_pgoff;
-	unsigned long start;
-	u32 len;
-
-	start = info->fix.smem_start;
-	len = info->fix.smem_len;
-	mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
-	if (vma->vm_pgoff >= mmio_pgoff) {
-		if (info->var.accel_flags)
-			return -EINVAL;
-		vma->vm_pgoff -= mmio_pgoff;
-		start = info->fix.mmio_start;
-		len = info->fix.mmio_len;
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-	} else {
-		/* framebuffer */
-		vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
-	}
-
-	return vm_iomap_memory(vma, start, len);
-}
-
-static int controlfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct fb_info_control *p = (struct fb_info_control *) info;
-	unsigned ctrl;
-
-	ctrl = ld_le32(CNTRL_REG(p,ctrl));
-	if (blank_mode > 0)
-		switch (blank_mode) {
-		case FB_BLANK_VSYNC_SUSPEND:
-			ctrl &= ~3;
-			break;
-		case FB_BLANK_HSYNC_SUSPEND:
-			ctrl &= ~0x30;
-			break;
-		case FB_BLANK_POWERDOWN:
-			ctrl &= ~0x33;
-			/* fall through */
-		case FB_BLANK_NORMAL:
-			ctrl |= 0x400;
-			break;
-		default:
-			break;
-		}
-	else {
-		ctrl &= ~0x400;
-		ctrl |= 0x33;
-	}
-	out_le32(CNTRL_REG(p,ctrl), ctrl);
-
-	return 0;
-}
-
-static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info)
-{
-	struct fb_info_control *p = (struct fb_info_control *) info;
-	__u8 r, g, b;
-
-	if (regno > 255)
-		return 1;
-
-	r = red >> 8;
-	g = green >> 8;
-	b = blue >> 8;
-
-	out_8(&p->cmap_regs->addr, regno);	/* tell clut what addr to fill	*/
-	out_8(&p->cmap_regs->lut, r);		/* send one color channel at	*/
-	out_8(&p->cmap_regs->lut, g);		/* a time...			*/
-	out_8(&p->cmap_regs->lut, b);
-
-	if (regno < 16) {
-		int i;
-		switch (p->par.cmode) {
-		case CMODE_16:
-			p->pseudo_palette[regno] =
-			    (regno << 10) | (regno << 5) | regno;
-			break;
-		case CMODE_32:
-			i = (regno << 8) | regno;
-			p->pseudo_palette[regno] = (i << 16) | i;
-			break;
-		}
-	}
-
-	return 0;
-}
-
-
-/********************  End of controlfb_ops implementation  ******************/
-
-
-
-static void set_control_clock(unsigned char *params)
-{
-#ifdef CONFIG_ADB_CUDA
-	struct adb_request req;
-	int i;
-
-	for (i = 0; i < 3; ++i) {
-		cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
-			     0x50, i + 1, params[i]);
-		while (!req.complete)
-			cuda_poll();
-	}
-#endif	
-}
-
-
-/*
- * finish off the driver initialization and register
- */
-static int __init init_control(struct fb_info_control *p)
-{
-	int full, sense, vmode, cmode, vyres;
-	struct fb_var_screeninfo var;
-	int rc;
-	
-	printk(KERN_INFO "controlfb: ");
-
-	full = p->total_vram == 0x400000;
-
-	/* Try to pick a video mode out of NVRAM if we have one. */
-#ifdef CONFIG_NVRAM
-	if (default_cmode == CMODE_NVRAM) {
-		cmode = nvram_read_byte(NV_CMODE);
-		if(cmode < CMODE_8 || cmode > CMODE_32)
-			cmode = CMODE_8;
-	} else
-#endif
-		cmode=default_cmode;
-#ifdef CONFIG_NVRAM
-	if (default_vmode == VMODE_NVRAM) {
-		vmode = nvram_read_byte(NV_VMODE);
-		if (vmode < 1 || vmode > VMODE_MAX ||
-		    control_mac_modes[vmode - 1].m[full] < cmode) {
-			sense = read_control_sense(p);
-			printk("Monitor sense value = 0x%x, ", sense);
-			vmode = mac_map_monitor_sense(sense);
-			if (control_mac_modes[vmode - 1].m[full] < cmode)
-				vmode = VMODE_640_480_60;
-		}
-	} else
-#endif
-	{
-		vmode=default_vmode;
-		if (control_mac_modes[vmode - 1].m[full] < cmode) {
-			if (cmode > CMODE_8)
-				cmode--;
-			else
-				vmode = VMODE_640_480_60;
-		}
-	}
-
-	/* Initialize info structure */
-	control_init_info(&p->info, p);
-
-	/* Setup default var */
-	if (mac_vmode_to_var(vmode, cmode, &var) < 0) {
-		/* This shouldn't happen! */
-		printk("mac_vmode_to_var(%d, %d,) failed\n", vmode, cmode);
-try_again:
-		vmode = VMODE_640_480_60;
-		cmode = CMODE_8;
-		if (mac_vmode_to_var(vmode, cmode, &var) < 0) {
-			printk(KERN_ERR "controlfb: mac_vmode_to_var() failed\n");
-			return -ENXIO;
-		}
-		printk(KERN_INFO "controlfb: ");
-	}
-	printk("using video mode %d and color mode %d.\n", vmode, cmode);
-
-	vyres = (p->total_vram - CTRLFB_OFF) / (var.xres << cmode);
-	if (vyres > var.yres)
-		var.yres_virtual = vyres;
-
-	/* Apply default var */
-	var.activate = FB_ACTIVATE_NOW;
-	rc = fb_set_var(&p->info, &var);
-	if (rc && (vmode != VMODE_640_480_60 || cmode != CMODE_8))
-		goto try_again;
-
-	/* Register with fbdev layer */
-	if (register_framebuffer(&p->info) < 0)
-		return -ENXIO;
-
-	fb_info(&p->info, "control display adapter\n");
-
-	return 0;
-}
-
-#define RADACAL_WRITE(a,d) \
-	out_8(&p->cmap_regs->addr, (a)); \
-	out_8(&p->cmap_regs->dat,   (d))
-
-/* Now how about actually saying, Make it so! */
-/* Some things in here probably don't need to be done each time. */
-static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par)
-{
-	struct control_regvals	*r;
-	volatile struct preg	__iomem *rp;
-	int			i, cmode;
-
-	if (PAR_EQUAL(&p->par, par)) {
-		/*
-		 * check if only xoffset or yoffset differs.
-		 * this prevents flickers in typical VT switch case.
-		 */
-		if (p->par.xoffset != par->xoffset ||
-		    p->par.yoffset != par->yoffset)
-			set_screen_start(par->xoffset, par->yoffset, p);
-			
-		return;
-	}
-	
-	p->par = *par;
-	cmode = p->par.cmode;
-	r = &par->regvals;
-	
-	/* Turn off display */
-	out_le32(CNTRL_REG(p,ctrl), 0x400 | par->ctrl);
-	
-	set_control_clock(r->clock_params);
-	
-	RADACAL_WRITE(0x20, r->radacal_ctrl);
-	RADACAL_WRITE(0x21, p->control_use_bank2 ? 0 : 1);
-	RADACAL_WRITE(0x10, 0);
-	RADACAL_WRITE(0x11, 0);
-
-	rp = &p->control_regs->vswin;
-	for (i = 0; i < 16; ++i, ++rp)
-		out_le32(&rp->r, r->regs[i]);
-	
-	out_le32(CNTRL_REG(p,pitch), par->pitch);
-	out_le32(CNTRL_REG(p,mode), r->mode);
-	out_le32(CNTRL_REG(p,vram_attr), p->vram_attr);
-	out_le32(CNTRL_REG(p,start_addr), par->yoffset * par->pitch
-		 + (par->xoffset << cmode));
-	out_le32(CNTRL_REG(p,rfrcnt), 0x1e5);
-	out_le32(CNTRL_REG(p,intr_ena), 0);
-
-	/* Turn on display */
-	out_le32(CNTRL_REG(p,ctrl), par->ctrl);
-
-#ifdef CONFIG_BOOTX_TEXT
-	btext_update_display(p->frame_buffer_phys + CTRLFB_OFF,
-			     p->par.xres, p->par.yres,
-			     (cmode == CMODE_32? 32: cmode == CMODE_16? 16: 8),
-			     p->par.pitch);
-#endif /* CONFIG_BOOTX_TEXT */
-}
-
-
-/*
- * Parse user specified options (`video=controlfb:')
- */
-static void __init control_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "vmode:", 6)) {
-			int vmode = simple_strtoul(this_opt+6, NULL, 0);
-			if (vmode > 0 && vmode <= VMODE_MAX &&
-			    control_mac_modes[vmode - 1].m[1] >= 0)
-				default_vmode = vmode;
-		} else if (!strncmp(this_opt, "cmode:", 6)) {
-			int depth = simple_strtoul(this_opt+6, NULL, 0);
-			switch (depth) {
-			 case CMODE_8:
-			 case CMODE_16:
-			 case CMODE_32:
-			 	default_cmode = depth;
-			 	break;
-			 case 8:
-				default_cmode = CMODE_8;
-				break;
-			 case 15:
-			 case 16:
-				default_cmode = CMODE_16;
-				break;
-			 case 24:
-			 case 32:
-				default_cmode = CMODE_32;
-				break;
-			}
-		}
-	}
-}
-
-static int __init control_init(void)
-{
-	struct device_node *dp;
-	char *option = NULL;
-	int ret = -ENXIO;
-
-	if (fb_get_options("controlfb", &option))
-		return -ENODEV;
-	control_setup(option);
-
-	dp = of_find_node_by_name(NULL, "control");
-	if (dp != 0 && !control_of_init(dp))
-		ret = 0;
-	of_node_put(dp);
-
-	return ret;
-}
-
-module_init(control_init);
-
-/* Work out which banks of VRAM we have installed. */
-/* danj: I guess the card just ignores writes to nonexistant VRAM... */
-
-static void __init find_vram_size(struct fb_info_control *p)
-{
-	int bank1, bank2;
-
-	/*
-	 * Set VRAM in 2MB (bank 1) mode
-	 * VRAM Bank 2 will be accessible through offset 0x600000 if present
-	 * and VRAM Bank 1 will not respond at that offset even if present
-	 */
-	out_le32(CNTRL_REG(p,vram_attr), 0x31);
-
-	out_8(&p->frame_buffer[0x600000], 0xb3);
-	out_8(&p->frame_buffer[0x600001], 0x71);
-	asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0x600000])
-					: "memory" );
-	mb();
-	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000])
-					: "memory" );
-	mb();
-
-	bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xb3)
-		&& (in_8(&p->frame_buffer[0x600001]) == 0x71);
-
-	/*
-	 * Set VRAM in 2MB (bank 2) mode
-	 * VRAM Bank 1 will be accessible through offset 0x000000 if present
-	 * and VRAM Bank 2 will not respond at that offset even if present
-	 */
-	out_le32(CNTRL_REG(p,vram_attr), 0x39);
-
-	out_8(&p->frame_buffer[0], 0x5a);
-	out_8(&p->frame_buffer[1], 0xc7);
-	asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0])
-					: "memory" );
-	mb();
-	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0])
-					: "memory" );
-	mb();
-
-	bank1 = (in_8(&p->frame_buffer[0]) == 0x5a)
-		&& (in_8(&p->frame_buffer[1]) == 0xc7);
-
-	if (bank2) {
-		if (!bank1) {
-			/*
-			 * vram bank 2 only
-			 */
-			p->control_use_bank2 = 1;
-			p->vram_attr = 0x39;
-			p->frame_buffer += 0x600000;
-			p->frame_buffer_phys += 0x600000;
-		} else {
-			/*
-			 * 4 MB vram
-			 */
-			p->vram_attr = 0x51;
-		}
-	} else {
-		/*
-		 * vram bank 1 only
-		 */
-		p->vram_attr = 0x31;
-	}
-
-        p->total_vram = (bank1 + bank2) * 0x200000;
-
-	printk(KERN_INFO "controlfb: VRAM Total = %dMB "
-			"(%dMB @ bank 1, %dMB @ bank 2)\n",
-			(bank1 + bank2) << 1, bank1 << 1, bank2 << 1);
-}
-
-
-/*
- * find "control" and initialize
- */
-static int __init control_of_init(struct device_node *dp)
-{
-	struct fb_info_control	*p;
-	struct resource		fb_res, reg_res;
-
-	if (control_fb) {
-		printk(KERN_ERR "controlfb: only one control is supported\n");
-		return -ENXIO;
-	}
-
-	if (of_pci_address_to_resource(dp, 2, &fb_res) ||
-	    of_pci_address_to_resource(dp, 1, &reg_res)) {
-		printk(KERN_ERR "can't get 2 addresses for control\n");
-		return -ENXIO;
-	}
-	p = kzalloc(sizeof(*p), GFP_KERNEL);
-	if (p == 0)
-		return -ENXIO;
-	control_fb = p;	/* save it for cleanups */
-
-	/* Map in frame buffer and registers */
-	p->fb_orig_base = fb_res.start;
-	p->fb_orig_size = resource_size(&fb_res);
-	/* use the big-endian aperture (??) */
-	p->frame_buffer_phys = fb_res.start + 0x800000;
-	p->control_regs_phys = reg_res.start;
-	p->control_regs_size = resource_size(&reg_res);
-
-	if (!p->fb_orig_base ||
-	    !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {
-		p->fb_orig_base = 0;
-		goto error_out;
-	}
-	/* map at most 8MB for the frame buffer */
-	p->frame_buffer = __ioremap(p->frame_buffer_phys, 0x800000,
-				    _PAGE_WRITETHRU);
-
-	if (!p->control_regs_phys ||
-	    !request_mem_region(p->control_regs_phys, p->control_regs_size,
-	    "controlfb regs")) {
-		p->control_regs_phys = 0;
-		goto error_out;
-	}
-	p->control_regs = ioremap(p->control_regs_phys, p->control_regs_size);
-
-	p->cmap_regs_phys = 0xf301b000;	 /* XXX not in prom? */
-	if (!request_mem_region(p->cmap_regs_phys, 0x1000, "controlfb cmap")) {
-		p->cmap_regs_phys = 0;
-		goto error_out;
-	}
-	p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
-
-	if (!p->cmap_regs || !p->control_regs || !p->frame_buffer)
-		goto error_out;
-
-	find_vram_size(p);
-	if (!p->total_vram)
-		goto error_out;
-
-	if (init_control(p) < 0)
-		goto error_out;
-
-	return 0;
-
-error_out:
-	control_cleanup();
-	return -ENXIO;
-}
-
-/*
- * Get the monitor sense value.
- * Note that this can be called before calibrate_delay,
- * so we can't use udelay.
- */
-static int read_control_sense(struct fb_info_control *p)
-{
-	int sense;
-
-	out_le32(CNTRL_REG(p,mon_sense), 7);	/* drive all lines high */
-	__delay(200);
-	out_le32(CNTRL_REG(p,mon_sense), 077);	/* turn off drivers */
-	__delay(2000);
-	sense = (in_le32(CNTRL_REG(p,mon_sense)) & 0x1c0) << 2;
-
-	/* drive each sense line low in turn and collect the other 2 */
-	out_le32(CNTRL_REG(p,mon_sense), 033);	/* drive A low */
-	__delay(2000);
-	sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0xc0) >> 2;
-	out_le32(CNTRL_REG(p,mon_sense), 055);	/* drive B low */
-	__delay(2000);
-	sense |= ((in_le32(CNTRL_REG(p,mon_sense)) & 0x100) >> 5)
-		| ((in_le32(CNTRL_REG(p,mon_sense)) & 0x40) >> 4);
-	out_le32(CNTRL_REG(p,mon_sense), 066);	/* drive C low */
-	__delay(2000);
-	sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0x180) >> 7;
-
-	out_le32(CNTRL_REG(p,mon_sense), 077);	/* turn off drivers */
-	
-	return sense;
-}
-
-/**********************  Various translation functions  **********************/
-
-#define CONTROL_PIXCLOCK_BASE	256016
-#define CONTROL_PIXCLOCK_MIN	5000	/* ~ 200 MHz dot clock */
-
-/*
- * calculate the clock paramaters to be sent to CUDA according to given
- * pixclock in pico second.
- */
-static int calc_clock_params(unsigned long clk, unsigned char *param)
-{
-	unsigned long p0, p1, p2, k, l, m, n, min;
-
-	if (clk > (CONTROL_PIXCLOCK_BASE << 3))
-		return 1;
-
-	p2 = ((clk << 4) < CONTROL_PIXCLOCK_BASE)? 3: 2;
-	l = clk << p2;
-	p0 = 0;
-	p1 = 0;
-	for (k = 1, min = l; k < 32; k++) {
-		unsigned long rem;
-
-		m = CONTROL_PIXCLOCK_BASE * k;
-		n = m / l;
-		rem = m % l;
-		if (n && (n < 128) && rem < min) {
-			p0 = k;
-			p1 = n;
-			min = rem;
-		}
-	}
-	if (!p0 || !p1)
-		return 1;
-
-	param[0] = p0;
-	param[1] = p1;
-	param[2] = p2;
-
-	return 0;
-}
-
-
-/*
- * This routine takes a user-supplied var, and picks the best vmode/cmode
- * from it.
- */
-
-static int control_var_to_par(struct fb_var_screeninfo *var,
-	struct fb_par_control *par, const struct fb_info *fb_info)
-{
-	int cmode, piped_diff, hstep;
-	unsigned hperiod, hssync, hsblank, hesync, heblank, piped, heq, hlfln,
-		 hserr, vperiod, vssync, vesync, veblank, vsblank, vswin, vewin;
-	unsigned long pixclock;
-	struct fb_info_control *p = (struct fb_info_control *) fb_info;
-	struct control_regvals *r = &par->regvals;
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		par->cmode = CMODE_8;
-		if (p->total_vram > 0x200000) {
-			r->mode = 3;
-			r->radacal_ctrl = 0x20;
-			piped_diff = 13;
-		} else {
-			r->mode = 2;
-			r->radacal_ctrl = 0x10;
-			piped_diff = 9;
-		}
-		break;
-	case 15:
-	case 16:
-		par->cmode = CMODE_16;
-		if (p->total_vram > 0x200000) {
-			r->mode = 2;
-			r->radacal_ctrl = 0x24;
-			piped_diff = 5;
-		} else {
-			r->mode = 1;
-			r->radacal_ctrl = 0x14;
-			piped_diff = 3;
-		}
-		break;
-	case 32:
-		par->cmode = CMODE_32;
-		if (p->total_vram > 0x200000) {
-			r->mode = 1;
-			r->radacal_ctrl = 0x28;
-		} else {
-			r->mode = 0;
-			r->radacal_ctrl = 0x18;
-		}
-		piped_diff = 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * adjust xres and vxres so that the corresponding memory widths are
-	 * 32-byte aligned
-	 */
-	hstep = 31 >> par->cmode;
-	par->xres = (var->xres + hstep) & ~hstep;
-	par->vxres = (var->xres_virtual + hstep) & ~hstep;
-	par->xoffset = (var->xoffset + hstep) & ~hstep;
-	if (par->vxres < par->xres)
-		par->vxres = par->xres;
-	par->pitch = par->vxres << par->cmode;
-
-	par->yres = var->yres;
-	par->vyres = var->yres_virtual;
-	par->yoffset = var->yoffset;
-	if (par->vyres < par->yres)
-		par->vyres = par->yres;
-
-	par->sync = var->sync;
-
-	if (par->pitch * par->vyres + CTRLFB_OFF > p->total_vram)
-		return -EINVAL;
-
-	if (par->xoffset + par->xres > par->vxres)
-		par->xoffset = par->vxres - par->xres;
-	if (par->yoffset + par->yres > par->vyres)
-		par->yoffset = par->vyres - par->yres;
-
-	pixclock = (var->pixclock < CONTROL_PIXCLOCK_MIN)? CONTROL_PIXCLOCK_MIN:
-		   var->pixclock;
-	if (calc_clock_params(pixclock, r->clock_params))
-		return -EINVAL;
-
-	hperiod = ((var->left_margin + par->xres + var->right_margin
-		    + var->hsync_len) >> 1) - 2;
-	hssync = hperiod + 1;
-	hsblank = hssync - (var->right_margin >> 1);
-	hesync = (var->hsync_len >> 1) - 1;
-	heblank = (var->left_margin >> 1) + hesync;
-	piped = heblank - piped_diff;
-	heq = var->hsync_len >> 2;
-	hlfln = (hperiod+2) >> 1;
-	hserr = hssync-hesync;
-	vperiod = (var->vsync_len + var->lower_margin + par->yres
-		   + var->upper_margin) << 1;
-	vssync = vperiod - 2;
-	vesync = (var->vsync_len << 1) - vperiod + vssync;
-	veblank = (var->upper_margin << 1) + vesync;
-	vsblank = vssync - (var->lower_margin << 1);
-	vswin = (vsblank+vssync) >> 1;
-	vewin = (vesync+veblank) >> 1;
-
-	r->regs[0] = vswin;
-	r->regs[1] = vsblank;
-	r->regs[2] = veblank;
-	r->regs[3] = vewin;
-	r->regs[4] = vesync;
-	r->regs[5] = vssync;
-	r->regs[6] = vperiod;
-	r->regs[7] = piped;
-	r->regs[8] = hperiod;
-	r->regs[9] = hsblank;
-	r->regs[10] = heblank;
-	r->regs[11] = hesync;
-	r->regs[12] = hssync;
-	r->regs[13] = heq;
-	r->regs[14] = hlfln;
-	r->regs[15] = hserr;
-
-	if (par->xres >= 1280 && par->cmode >= CMODE_16)
-		par->ctrl = 0x7f;
-	else
-		par->ctrl = 0x3b;
-
-	if (mac_var_to_vmode(var, &par->vmode, &cmode))
-		par->vmode = 0;
-
-	return 0;
-}
-
-
-/*
- * Convert hardware data in par to an fb_var_screeninfo
- */
-
-static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
-{
-	struct control_regints *rv;
-	
-	rv = (struct control_regints *) par->regvals.regs;
-	
-	memset(var, 0, sizeof(*var));
-	var->xres = par->xres;
-	var->yres = par->yres;
-	var->xres_virtual = par->vxres;
-	var->yres_virtual = par->vyres;
-	var->xoffset = par->xoffset;
-	var->yoffset = par->yoffset;
-	
-	switch(par->cmode) {
-	default:
-	case CMODE_8:
-		var->bits_per_pixel = 8;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	case CMODE_16:	/* RGB 555 */
-		var->bits_per_pixel = 16;
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->blue.length = 5;
-		break;
-	case CMODE_32:	/* RGB 888 */
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	}
-	var->height = -1;
-	var->width = -1;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	var->left_margin = (rv->heblank - rv->hesync) << 1;
-	var->right_margin = (rv->hssync - rv->hsblank) << 1;
-	var->hsync_len = (rv->hperiod + 2 - rv->hssync + rv->hesync) << 1;
-
-	var->upper_margin = (rv->veblank - rv->vesync) >> 1;
-	var->lower_margin = (rv->vssync - rv->vsblank) >> 1;
-	var->vsync_len = (rv->vperiod - rv->vssync + rv->vesync) >> 1;
-
-	var->sync = par->sync;
-
-	/*
-	 * 10^12 * clock_params[0] / (3906400 * clock_params[1]
-	 *			      * 2^clock_params[2])
-	 * (10^12 * clock_params[0] / (3906400 * clock_params[1]))
-	 * >> clock_params[2]
-	 */
-	/* (255990.17 * clock_params[0] / clock_params[1]) >> clock_params[2] */
-	var->pixclock = CONTROL_PIXCLOCK_BASE * par->regvals.clock_params[0];
-	var->pixclock /= par->regvals.clock_params[1];
-	var->pixclock >>= par->regvals.clock_params[2];
-}
-
-/*
- * Set misc info vars for this driver
- */
-static void __init control_init_info(struct fb_info *info, struct fb_info_control *p)
-{
-	/* Fill fb_info */
-	info->par = &p->par;
-	info->fbops = &controlfb_ops;
-	info->pseudo_palette = p->pseudo_palette;
-        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	info->screen_base = p->frame_buffer + CTRLFB_OFF;
-
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	/* Fill fix common fields */
-	strcpy(info->fix.id, "control");
-	info->fix.mmio_start = p->control_regs_phys;
-	info->fix.mmio_len = sizeof(struct control_regs);
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.smem_start = p->frame_buffer_phys + CTRLFB_OFF;
-	info->fix.smem_len = p->total_vram - CTRLFB_OFF;
-        info->fix.ywrapstep = 0;
-        info->fix.type_aux = 0;
-        info->fix.accel = FB_ACCEL_NONE;
-}
-
-
-static void control_cleanup(void)
-{
-	struct fb_info_control	*p = control_fb;
-
-	if (!p)
-		return;
-
-	if (p->cmap_regs)
-		iounmap(p->cmap_regs);
-	if (p->control_regs)
-		iounmap(p->control_regs);
-	if (p->frame_buffer) {
-		if (p->control_use_bank2)
-			p->frame_buffer -= 0x600000;
-		iounmap(p->frame_buffer);
-	}
-	if (p->cmap_regs_phys)
-		release_mem_region(p->cmap_regs_phys, 0x1000);
-	if (p->control_regs_phys)
-		release_mem_region(p->control_regs_phys, p->control_regs_size);
-	if (p->fb_orig_base)
-		release_mem_region(p->fb_orig_base, p->fb_orig_size);
-	kfree(p);
-}
-
-
diff --git a/drivers/video/controlfb.h b/drivers/video/controlfb.h
deleted file mode 100644
index 6026c60fc100..000000000000
--- a/drivers/video/controlfb.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * controlfb_hw.h: Constants of all sorts for controlfb
- *
- * Copyright (C) 1998 Daniel Jacobowitz <dan@debian.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Based on an awful lot of code, including:
- *
- * control.c: Console support for PowerMac "control" display adaptor.
- * Copyright (C) 1996 Paul Mackerras.
- *
- * The so far unpublished platinumfb.c
- * Copyright (C) 1998 Jon Howell
- */
-
-/*
- * Structure of the registers for the RADACAL colormap device.
- */
-struct cmap_regs {
-	unsigned char addr;	/* index for both cmap and misc registers */
-	char pad1[15];
-	unsigned char crsr;	/* cursor palette */
-	char pad2[15];
-	unsigned char dat;	/* RADACAL misc register data */
-	char pad3[15];
-	unsigned char lut;	/* cmap data */
-	char pad4[15];
-};
-
-/*
- * Structure of the registers for the "control" display adaptor.
- */
-#define PAD(x)	char x[12]
-
-struct preg {			/* padded register */
-	unsigned r;
-	char pad[12];
-};
-
-struct control_regs {
-	struct preg vcount;	/* vertical counter */
-	/* Vertical parameters are in units of 1/2 scan line */
-	struct preg vswin;	/* between vsblank and vssync */
-	struct preg vsblank;	/* vert start blank */
-	struct preg veblank;	/* vert end blank (display start) */
-	struct preg vewin;	/* between vesync and veblank */
-	struct preg vesync;	/* vert end sync */
-	struct preg vssync;	/* vert start sync */
-	struct preg vperiod;	/* vert period */
-	struct preg piped;	/* pipe delay hardware cursor */
-	/* Horizontal params are in units of 2 pixels */
-	struct preg hperiod;	/* horiz period - 2 */
-	struct preg hsblank;	/* horiz start blank */
-	struct preg heblank;	/* horiz end blank */
-	struct preg hesync;	/* horiz end sync */
-	struct preg hssync;	/* horiz start sync */
-	struct preg heq;	/* half horiz sync len */
-	struct preg hlfln;	/* half horiz period */
-	struct preg hserr;	/* horiz period - horiz sync len */
-	struct preg cnttst;
-	struct preg ctrl;	/* display control */
-	struct preg start_addr;	/* start address: 5 lsbs zero */
-	struct preg pitch;	/* addrs diff between scan lines */
-	struct preg mon_sense;	/* monitor sense bits */
-	struct preg vram_attr;	/* enable vram banks */
-	struct preg mode;
-	struct preg rfrcnt;	/* refresh count */
-	struct preg intr_ena;	/* interrupt enable */
-	struct preg intr_stat;	/* interrupt status */
-	struct preg res[5];
-};
-
-struct control_regints {
-	/* Vertical parameters are in units of 1/2 scan line */
-	unsigned vswin;	/* between vsblank and vssync */
-	unsigned vsblank;	/* vert start blank */
-	unsigned veblank;	/* vert end blank (display start) */
-	unsigned vewin;	/* between vesync and veblank */
-	unsigned vesync;	/* vert end sync */
-	unsigned vssync;	/* vert start sync */
-	unsigned vperiod;	/* vert period */
-	unsigned piped;		/* pipe delay hardware cursor */
-	/* Horizontal params are in units of 2 pixels */
-	/* Except, apparently, for hres > 1024 (or == 1280?) */
-	unsigned hperiod;	/* horiz period - 2 */
-	unsigned hsblank;	/* horiz start blank */
-	unsigned heblank;	/* horiz end blank */
-	unsigned hesync;	/* horiz end sync */
-	unsigned hssync;	/* horiz start sync */
-	unsigned heq;		/* half horiz sync len */
-	unsigned hlfln;		/* half horiz period */
-	unsigned hserr;		/* horiz period - horiz sync len */
-};
-	
-/*
- * Dot clock rate is
- * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0].
- */
-struct control_regvals {
-	unsigned regs[16];		/* for vswin .. hserr */
-	unsigned char mode;
-	unsigned char radacal_ctrl;
-	unsigned char clock_params[3];
-};
-
-#define CTRLFB_OFF 16	/* position of pixel 0 in frame buffer */
-
-
-/*
- * Best cmode supported by control
- */
-struct max_cmodes {
-	int m[2];	/* 0: 2MB vram, 1: 4MB vram */
-};
-
-/*
- * Video modes supported by macmodes.c
- */
-static struct max_cmodes control_mac_modes[] = {
-	{{-1,-1}},	/* 512x384, 60Hz interlaced (NTSC) */
-	{{-1,-1}},	/* 512x384, 60Hz */
-	{{-1,-1}},	/* 640x480, 50Hz interlaced (PAL) */
-	{{-1,-1}},	/* 640x480, 60Hz interlaced (NTSC) */
-	{{ 2, 2}},	/* 640x480, 60Hz (VGA) */
-	{{ 2, 2}},	/* 640x480, 67Hz */
-	{{-1,-1}},	/* 640x870, 75Hz (portrait) */
-	{{-1,-1}},	/* 768x576, 50Hz (PAL full frame) */
-	{{ 2, 2}},	/* 800x600, 56Hz */
-	{{ 2, 2}},	/* 800x600, 60Hz */
-	{{ 2, 2}},	/* 800x600, 72Hz */
-	{{ 2, 2}},	/* 800x600, 75Hz */
-	{{ 1, 2}},	/* 832x624, 75Hz */
-	{{ 1, 2}},	/* 1024x768, 60Hz */
-	{{ 1, 2}},	/* 1024x768, 70Hz (or 72Hz?) */
-	{{ 1, 2}},	/* 1024x768, 75Hz (VESA) */
-	{{ 1, 2}},	/* 1024x768, 75Hz */
-	{{ 1, 2}},	/* 1152x870, 75Hz */
-	{{ 0, 1}},	/* 1280x960, 75Hz */
-	{{ 0, 1}},	/* 1280x1024, 75Hz */
-};
-
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
deleted file mode 100644
index b0a950f36970..000000000000
--- a/drivers/video/cyber2000fb.c
+++ /dev/null
@@ -1,1901 +0,0 @@
-/*
- *  linux/drivers/video/cyber2000fb.c
- *
- *  Copyright (C) 1998-2002 Russell King
- *
- *  MIPS and 50xx clock support
- *  Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
- *
- *  32 bit support, text color and panning fixes for modes != 8 bit
- *  Copyright (C) 2002 Denis Oliver Kropp <dok@directfb.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
- *
- * Based on cyberfb.c.
- *
- * Note that we now use the new fbcon fix, var and cmap scheme.  We do
- * still have to check which console is the currently displayed one
- * however, especially for the colourmap stuff.
- *
- * We also use the new hotplug PCI subsystem.  I'm not sure if there
- * are any such cards, but I'm erring on the side of caution.  We don't
- * want to go pop just because someone does have one.
- *
- * Note that this doesn't work fully in the case of multiple CyberPro
- * cards with grabbers.  We currently can only attach to the first
- * CyberPro card found.
- *
- * When we're in truecolour mode, we power down the LUT RAM as a power
- * saving feature.  Also, when we enter any of the powersaving modes
- * (except soft blanking) we power down the RAMDACs.  This saves about
- * 1W, which is roughly 8% of the power consumption of a NetWinder
- * (which, incidentally, is about the same saving as a 2.5in hard disk
- * entering standby mode.)
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include <asm/pgtable.h>
-
-#ifdef __arm__
-#include <asm/mach-types.h>
-#endif
-
-#include "cyber2000fb.h"
-
-struct cfb_info {
-	struct fb_info		fb;
-	struct display_switch	*dispsw;
-	struct display		*display;
-	unsigned char		__iomem *region;
-	unsigned char		__iomem *regs;
-	u_int			id;
-	u_int			irq;
-	int			func_use_count;
-	u_long			ref_ps;
-
-	/*
-	 * Clock divisors
-	 */
-	u_int			divisors[4];
-
-	struct {
-		u8 red, green, blue;
-	} palette[NR_PALETTE];
-
-	u_char			mem_ctl1;
-	u_char			mem_ctl2;
-	u_char			mclk_mult;
-	u_char			mclk_div;
-	/*
-	 * RAMDAC control register is both of these or'ed together
-	 */
-	u_char			ramdac_ctrl;
-	u_char			ramdac_powerdown;
-
-	u32			pseudo_palette[16];
-
-	spinlock_t		reg_b0_lock;
-
-#ifdef CONFIG_FB_CYBER2000_DDC
-	bool			ddc_registered;
-	struct i2c_adapter	ddc_adapter;
-	struct i2c_algo_bit_data	ddc_algo;
-#endif
-
-#ifdef CONFIG_FB_CYBER2000_I2C
-	struct i2c_adapter	i2c_adapter;
-	struct i2c_algo_bit_data i2c_algo;
-#endif
-};
-
-static char *default_font = "Acorn8x8";
-module_param(default_font, charp, 0);
-MODULE_PARM_DESC(default_font, "Default font name");
-
-/*
- * Our access methods.
- */
-#define cyber2000fb_writel(val, reg, cfb)	writel(val, (cfb)->regs + (reg))
-#define cyber2000fb_writew(val, reg, cfb)	writew(val, (cfb)->regs + (reg))
-#define cyber2000fb_writeb(val, reg, cfb)	writeb(val, (cfb)->regs + (reg))
-
-#define cyber2000fb_readb(reg, cfb)		readb((cfb)->regs + (reg))
-
-static inline void
-cyber2000_crtcw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
-{
-	cyber2000fb_writew((reg & 255) | val << 8, 0x3d4, cfb);
-}
-
-static inline void
-cyber2000_grphw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
-{
-	cyber2000fb_writew((reg & 255) | val << 8, 0x3ce, cfb);
-}
-
-static inline unsigned int
-cyber2000_grphr(unsigned int reg, struct cfb_info *cfb)
-{
-	cyber2000fb_writeb(reg, 0x3ce, cfb);
-	return cyber2000fb_readb(0x3cf, cfb);
-}
-
-static inline void
-cyber2000_attrw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
-{
-	cyber2000fb_readb(0x3da, cfb);
-	cyber2000fb_writeb(reg, 0x3c0, cfb);
-	cyber2000fb_readb(0x3c1, cfb);
-	cyber2000fb_writeb(val, 0x3c0, cfb);
-}
-
-static inline void
-cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
-{
-	cyber2000fb_writew((reg & 255) | val << 8, 0x3c4, cfb);
-}
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/*
- * Hardware Cyber2000 Acceleration
- */
-static void
-cyber2000fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-	unsigned long dst, col;
-
-	if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
-	cyber2000fb_writew(rect->width - 1, CO_REG_PIXWIDTH, cfb);
-	cyber2000fb_writew(rect->height - 1, CO_REG_PIXHEIGHT, cfb);
-
-	col = rect->color;
-	if (cfb->fb.var.bits_per_pixel > 8)
-		col = ((u32 *)cfb->fb.pseudo_palette)[col];
-	cyber2000fb_writel(col, CO_REG_FGCOLOUR, cfb);
-
-	dst = rect->dx + rect->dy * cfb->fb.var.xres_virtual;
-	if (cfb->fb.var.bits_per_pixel == 24) {
-		cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-		dst *= 3;
-	}
-
-	cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-	cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
-	cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
-	cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
-}
-
-static void
-cyber2000fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-	unsigned int cmd = CO_CMD_L_PATTERN_FGCOL;
-	unsigned long src, dst;
-
-	if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
-		cfb_copyarea(info, region);
-		return;
-	}
-
-	cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
-	cyber2000fb_writew(region->width - 1, CO_REG_PIXWIDTH, cfb);
-	cyber2000fb_writew(region->height - 1, CO_REG_PIXHEIGHT, cfb);
-
-	src = region->sx + region->sy * cfb->fb.var.xres_virtual;
-	dst = region->dx + region->dy * cfb->fb.var.xres_virtual;
-
-	if (region->sx < region->dx) {
-		src += region->width - 1;
-		dst += region->width - 1;
-		cmd |= CO_CMD_L_INC_LEFT;
-	}
-
-	if (region->sy < region->dy) {
-		src += (region->height - 1) * cfb->fb.var.xres_virtual;
-		dst += (region->height - 1) * cfb->fb.var.xres_virtual;
-		cmd |= CO_CMD_L_INC_UP;
-	}
-
-	if (cfb->fb.var.bits_per_pixel == 24) {
-		cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-		src *= 3;
-		dst *= 3;
-	}
-	cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
-	cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-	cyber2000fb_writew(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
-	cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
-	cyber2000fb_writew(CO_CMD_H_FGSRCMAP | CO_CMD_H_BLITTER,
-			   CO_REG_CMD_H, cfb);
-}
-
-static void
-cyber2000fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	cfb_imageblit(info, image);
-	return;
-}
-
-static int cyber2000fb_sync(struct fb_info *info)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-	int count = 100000;
-
-	if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT))
-		return 0;
-
-	while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
-		if (!count--) {
-			debug_printf("accel_wait timed out\n");
-			cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
-			break;
-		}
-		udelay(1);
-	}
-	return 0;
-}
-
-/*
- * ===========================================================================
- */
-
-static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
-{
-	u_int mask = (1 << bf->length) - 1;
-
-	return (val >> (16 - bf->length) & mask) << bf->offset;
-}
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-static int
-cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		      u_int transp, struct fb_info *info)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-	struct fb_var_screeninfo *var = &cfb->fb.var;
-	u32 pseudo_val;
-	int ret = 1;
-
-	switch (cfb->fb.fix.visual) {
-	default:
-		return 1;
-
-	/*
-	 * Pseudocolour:
-	 *	   8     8
-	 * pixel --/--+--/-->  red lut  --> red dac
-	 *	      |  8
-	 *	      +--/--> green lut --> green dac
-	 *	      |  8
-	 *	      +--/-->  blue lut --> blue dac
-	 */
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno >= NR_PALETTE)
-			return 1;
-
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-
-		cfb->palette[regno].red = red;
-		cfb->palette[regno].green = green;
-		cfb->palette[regno].blue = blue;
-
-		cyber2000fb_writeb(regno, 0x3c8, cfb);
-		cyber2000fb_writeb(red, 0x3c9, cfb);
-		cyber2000fb_writeb(green, 0x3c9, cfb);
-		cyber2000fb_writeb(blue, 0x3c9, cfb);
-		return 0;
-
-	/*
-	 * Direct colour:
-	 *	   n     rl
-	 * pixel --/--+--/-->  red lut  --> red dac
-	 *	      |  gl
-	 *	      +--/--> green lut --> green dac
-	 *	      |  bl
-	 *	      +--/-->  blue lut --> blue dac
-	 * n = bpp, rl = red length, gl = green length, bl = blue length
-	 */
-	case FB_VISUAL_DIRECTCOLOR:
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-
-		if (var->green.length == 6 && regno < 64) {
-			cfb->palette[regno << 2].green = green;
-
-			/*
-			 * The 6 bits of the green component are applied
-			 * to the high 6 bits of the LUT.
-			 */
-			cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
-			cyber2000fb_writeb(cfb->palette[regno >> 1].red,
-					   0x3c9, cfb);
-			cyber2000fb_writeb(green, 0x3c9, cfb);
-			cyber2000fb_writeb(cfb->palette[regno >> 1].blue,
-					   0x3c9, cfb);
-
-			green = cfb->palette[regno << 3].green;
-
-			ret = 0;
-		}
-
-		if (var->green.length >= 5 && regno < 32) {
-			cfb->palette[regno << 3].red = red;
-			cfb->palette[regno << 3].green = green;
-			cfb->palette[regno << 3].blue = blue;
-
-			/*
-			 * The 5 bits of each colour component are
-			 * applied to the high 5 bits of the LUT.
-			 */
-			cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
-			cyber2000fb_writeb(red, 0x3c9, cfb);
-			cyber2000fb_writeb(green, 0x3c9, cfb);
-			cyber2000fb_writeb(blue, 0x3c9, cfb);
-			ret = 0;
-		}
-
-		if (var->green.length == 4 && regno < 16) {
-			cfb->palette[regno << 4].red = red;
-			cfb->palette[regno << 4].green = green;
-			cfb->palette[regno << 4].blue = blue;
-
-			/*
-			 * The 5 bits of each colour component are
-			 * applied to the high 5 bits of the LUT.
-			 */
-			cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
-			cyber2000fb_writeb(red, 0x3c9, cfb);
-			cyber2000fb_writeb(green, 0x3c9, cfb);
-			cyber2000fb_writeb(blue, 0x3c9, cfb);
-			ret = 0;
-		}
-
-		/*
-		 * Since this is only used for the first 16 colours, we
-		 * don't have to care about overflowing for regno >= 32
-		 */
-		pseudo_val = regno << var->red.offset |
-			     regno << var->green.offset |
-			     regno << var->blue.offset;
-		break;
-
-	/*
-	 * True colour:
-	 *	   n     rl
-	 * pixel --/--+--/--> red dac
-	 *	      |  gl
-	 *	      +--/--> green dac
-	 *	      |  bl
-	 *	      +--/--> blue dac
-	 * n = bpp, rl = red length, gl = green length, bl = blue length
-	 */
-	case FB_VISUAL_TRUECOLOR:
-		pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
-		pseudo_val |= convert_bitfield(red, &var->red);
-		pseudo_val |= convert_bitfield(green, &var->green);
-		pseudo_val |= convert_bitfield(blue, &var->blue);
-		ret = 0;
-		break;
-	}
-
-	/*
-	 * Now set our pseudo palette for the CFB16/24/32 drivers.
-	 */
-	if (regno < 16)
-		((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
-
-	return ret;
-}
-
-struct par_info {
-	/*
-	 * Hardware
-	 */
-	u_char	clock_mult;
-	u_char	clock_div;
-	u_char	extseqmisc;
-	u_char	co_pixfmt;
-	u_char	crtc_ofl;
-	u_char	crtc[19];
-	u_int	width;
-	u_int	pitch;
-	u_int	fetch;
-
-	/*
-	 * Other
-	 */
-	u_char	ramdac;
-};
-
-static const u_char crtc_idx[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09,
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
-};
-
-static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
-{
-	unsigned int i;
-	unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
-
-	cyber2000fb_writeb(0x56, 0x3ce, cfb);
-	i = cyber2000fb_readb(0x3cf, cfb);
-	cyber2000fb_writeb(i | 4, 0x3cf, cfb);
-	cyber2000fb_writeb(val, 0x3c6, cfb);
-	cyber2000fb_writeb(i, 0x3cf, cfb);
-	/* prevent card lock-up observed on x86 with CyberPro 2000 */
-	cyber2000fb_readb(0x3cf, cfb);
-}
-
-static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
-{
-	u_int i;
-
-	/*
-	 * Blank palette
-	 */
-	for (i = 0; i < NR_PALETTE; i++) {
-		cyber2000fb_writeb(i, 0x3c8, cfb);
-		cyber2000fb_writeb(0, 0x3c9, cfb);
-		cyber2000fb_writeb(0, 0x3c9, cfb);
-		cyber2000fb_writeb(0, 0x3c9, cfb);
-	}
-
-	cyber2000fb_writeb(0xef, 0x3c2, cfb);
-	cyber2000_crtcw(0x11, 0x0b, cfb);
-	cyber2000_attrw(0x11, 0x00, cfb);
-
-	cyber2000_seqw(0x00, 0x01, cfb);
-	cyber2000_seqw(0x01, 0x01, cfb);
-	cyber2000_seqw(0x02, 0x0f, cfb);
-	cyber2000_seqw(0x03, 0x00, cfb);
-	cyber2000_seqw(0x04, 0x0e, cfb);
-	cyber2000_seqw(0x00, 0x03, cfb);
-
-	for (i = 0; i < sizeof(crtc_idx); i++)
-		cyber2000_crtcw(crtc_idx[i], hw->crtc[i], cfb);
-
-	for (i = 0x0a; i < 0x10; i++)
-		cyber2000_crtcw(i, 0, cfb);
-
-	cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
-	cyber2000_grphw(0x00, 0x00, cfb);
-	cyber2000_grphw(0x01, 0x00, cfb);
-	cyber2000_grphw(0x02, 0x00, cfb);
-	cyber2000_grphw(0x03, 0x00, cfb);
-	cyber2000_grphw(0x04, 0x00, cfb);
-	cyber2000_grphw(0x05, 0x60, cfb);
-	cyber2000_grphw(0x06, 0x05, cfb);
-	cyber2000_grphw(0x07, 0x0f, cfb);
-	cyber2000_grphw(0x08, 0xff, cfb);
-
-	/* Attribute controller registers */
-	for (i = 0; i < 16; i++)
-		cyber2000_attrw(i, i, cfb);
-
-	cyber2000_attrw(0x10, 0x01, cfb);
-	cyber2000_attrw(0x11, 0x00, cfb);
-	cyber2000_attrw(0x12, 0x0f, cfb);
-	cyber2000_attrw(0x13, 0x00, cfb);
-	cyber2000_attrw(0x14, 0x00, cfb);
-
-	/* PLL registers */
-	spin_lock(&cfb->reg_b0_lock);
-	cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
-	cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
-	cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
-	cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
-	cyber2000_grphw(0x90, 0x01, cfb);
-	cyber2000_grphw(0xb9, 0x80, cfb);
-	cyber2000_grphw(0xb9, 0x00, cfb);
-	spin_unlock(&cfb->reg_b0_lock);
-
-	cfb->ramdac_ctrl = hw->ramdac;
-	cyber2000fb_write_ramdac_ctrl(cfb);
-
-	cyber2000fb_writeb(0x20, 0x3c0, cfb);
-	cyber2000fb_writeb(0xff, 0x3c6, cfb);
-
-	cyber2000_grphw(0x14, hw->fetch, cfb);
-	cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
-			      ((hw->pitch >> 4) & 0x30), cfb);
-	cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
-
-	/*
-	 * Set up accelerator registers
-	 */
-	cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
-	cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
-	cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
-}
-
-static inline int
-cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
-{
-	u_int base = var->yoffset * var->xres_virtual + var->xoffset;
-
-	base *= var->bits_per_pixel;
-
-	/*
-	 * Convert to bytes and shift two extra bits because DAC
-	 * can only start on 4 byte aligned data.
-	 */
-	base >>= 5;
-
-	if (base >= 1 << 20)
-		return -EINVAL;
-
-	cyber2000_grphw(0x10, base >> 16 | 0x10, cfb);
-	cyber2000_crtcw(0x0c, base >> 8, cfb);
-	cyber2000_crtcw(0x0d, base, cfb);
-
-	return 0;
-}
-
-static int
-cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
-			struct fb_var_screeninfo *var)
-{
-	u_int Htotal, Hblankend, Hsyncend;
-	u_int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
-#define ENCODE_BIT(v, b1, m, b2) ((((v) >> (b1)) & (m)) << (b2))
-
-	hw->crtc[13] = hw->pitch;
-	hw->crtc[17] = 0xe3;
-	hw->crtc[14] = 0;
-	hw->crtc[8]  = 0;
-
-	Htotal     = var->xres + var->right_margin +
-		     var->hsync_len + var->left_margin;
-
-	if (Htotal > 2080)
-		return -EINVAL;
-
-	hw->crtc[0] = (Htotal >> 3) - 5;
-	hw->crtc[1] = (var->xres >> 3) - 1;
-	hw->crtc[2] = var->xres >> 3;
-	hw->crtc[4] = (var->xres + var->right_margin) >> 3;
-
-	Hblankend   = (Htotal - 4 * 8) >> 3;
-
-	hw->crtc[3] = ENCODE_BIT(Hblankend,  0, 0x1f,  0) |
-		      ENCODE_BIT(1,          0, 0x01,  7);
-
-	Hsyncend    = (var->xres + var->right_margin + var->hsync_len) >> 3;
-
-	hw->crtc[5] = ENCODE_BIT(Hsyncend,   0, 0x1f,  0) |
-		      ENCODE_BIT(Hblankend,  5, 0x01,  7);
-
-	Vdispend    = var->yres - 1;
-	Vsyncstart  = var->yres + var->lower_margin;
-	Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
-	Vtotal      = var->yres + var->lower_margin + var->vsync_len +
-		      var->upper_margin - 2;
-
-	if (Vtotal > 2047)
-		return -EINVAL;
-
-	Vblankstart = var->yres + 6;
-	Vblankend   = Vtotal - 10;
-
-	hw->crtc[6]  = Vtotal;
-	hw->crtc[7]  = ENCODE_BIT(Vtotal,     8, 0x01,  0) |
-			ENCODE_BIT(Vdispend,   8, 0x01,  1) |
-			ENCODE_BIT(Vsyncstart, 8, 0x01,  2) |
-			ENCODE_BIT(Vblankstart, 8, 0x01,  3) |
-			ENCODE_BIT(1,          0, 0x01,  4) |
-			ENCODE_BIT(Vtotal,     9, 0x01,  5) |
-			ENCODE_BIT(Vdispend,   9, 0x01,  6) |
-			ENCODE_BIT(Vsyncstart, 9, 0x01,  7);
-	hw->crtc[9]  = ENCODE_BIT(0,          0, 0x1f,  0) |
-			ENCODE_BIT(Vblankstart, 9, 0x01,  5) |
-			ENCODE_BIT(1,          0, 0x01,  6);
-	hw->crtc[10] = Vsyncstart;
-	hw->crtc[11] = ENCODE_BIT(Vsyncend,   0, 0x0f,  0) |
-		       ENCODE_BIT(1,          0, 0x01,  7);
-	hw->crtc[12] = Vdispend;
-	hw->crtc[15] = Vblankstart;
-	hw->crtc[16] = Vblankend;
-	hw->crtc[18] = 0xff;
-
-	/*
-	 * overflow - graphics reg 0x11
-	 * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
-	 * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
-	 */
-	hw->crtc_ofl =
-		ENCODE_BIT(Vtotal, 10, 0x01, 0) |
-		ENCODE_BIT(Vdispend, 10, 0x01, 1) |
-		ENCODE_BIT(Vsyncstart, 10, 0x01, 2) |
-		ENCODE_BIT(Vblankstart, 10, 0x01, 3) |
-		EXT_CRT_VRTOFL_LINECOMP10;
-
-	/* woody: set the interlaced bit... */
-	/* FIXME: what about doublescan? */
-	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
-		hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
-
-	return 0;
-}
-
-/*
- * The following was discovered by a good monitor, bit twiddling, theorising
- * and but mostly luck.  Strangely, it looks like everyone elses' PLL!
- *
- * Clock registers:
- *   fclock = fpll / div2
- *   fpll   = fref * mult / div1
- * where:
- *   fref = 14.318MHz (69842ps)
- *   mult = reg0xb0.7:0
- *   div1 = (reg0xb1.5:0 + 1)
- *   div2 =  2^(reg0xb1.7:6)
- *   fpll should be between 115 and 260 MHz
- *  (8696ps and 3846ps)
- */
-static int
-cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,
-			 struct fb_var_screeninfo *var)
-{
-	u_long pll_ps = var->pixclock;
-	const u_long ref_ps = cfb->ref_ps;
-	u_int div2, t_div1, best_div1, best_mult;
-	int best_diff;
-	int vco;
-
-	/*
-	 * Step 1:
-	 *   find div2 such that 115MHz < fpll < 260MHz
-	 *   and 0 <= div2 < 4
-	 */
-	for (div2 = 0; div2 < 4; div2++) {
-		u_long new_pll;
-
-		new_pll = pll_ps / cfb->divisors[div2];
-		if (8696 > new_pll && new_pll > 3846) {
-			pll_ps = new_pll;
-			break;
-		}
-	}
-
-	if (div2 == 4)
-		return -EINVAL;
-
-	/*
-	 * Step 2:
-	 *  Given pll_ps and ref_ps, find:
-	 *    pll_ps * 0.995 < pll_ps_calc < pll_ps * 1.005
-	 *  where { 1 < best_div1 < 32, 1 < best_mult < 256 }
-	 *    pll_ps_calc = best_div1 / (ref_ps * best_mult)
-	 */
-	best_diff = 0x7fffffff;
-	best_mult = 2;
-	best_div1 = 32;
-	for (t_div1 = 2; t_div1 < 32; t_div1 += 1) {
-		u_int rr, t_mult, t_pll_ps;
-		int diff;
-
-		/*
-		 * Find the multiplier for this divisor
-		 */
-		rr = ref_ps * t_div1;
-		t_mult = (rr + pll_ps / 2) / pll_ps;
-
-		/*
-		 * Is the multiplier within the correct range?
-		 */
-		if (t_mult > 256 || t_mult < 2)
-			continue;
-
-		/*
-		 * Calculate the actual clock period from this multiplier
-		 * and divisor, and estimate the error.
-		 */
-		t_pll_ps = (rr + t_mult / 2) / t_mult;
-		diff = pll_ps - t_pll_ps;
-		if (diff < 0)
-			diff = -diff;
-
-		if (diff < best_diff) {
-			best_diff = diff;
-			best_mult = t_mult;
-			best_div1 = t_div1;
-		}
-
-		/*
-		 * If we hit an exact value, there is no point in continuing.
-		 */
-		if (diff == 0)
-			break;
-	}
-
-	/*
-	 * Step 3:
-	 *  combine values
-	 */
-	hw->clock_mult = best_mult - 1;
-	hw->clock_div  = div2 << 6 | (best_div1 - 1);
-
-	vco = ref_ps * best_div1 / best_mult;
-	if ((ref_ps == 40690) && (vco < 5556))
-		/* Set VFSEL when VCO > 180MHz (5.556 ps). */
-		hw->clock_div |= EXT_DCLK_DIV_VFSEL;
-
-	return 0;
-}
-
-/*
- *    Set the User Defined Part of the Display
- */
-static int
-cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-	struct par_info hw;
-	unsigned int mem;
-	int err;
-
-	var->transp.msb_right	= 0;
-	var->red.msb_right	= 0;
-	var->green.msb_right	= 0;
-	var->blue.msb_right	= 0;
-	var->transp.offset	= 0;
-	var->transp.length	= 0;
-
-	switch (var->bits_per_pixel) {
-	case 8:	/* PSEUDOCOLOUR, 256 */
-		var->red.offset		= 0;
-		var->red.length		= 8;
-		var->green.offset	= 0;
-		var->green.length	= 8;
-		var->blue.offset	= 0;
-		var->blue.length	= 8;
-		break;
-
-	case 16:/* DIRECTCOLOUR, 64k or 32k */
-		switch (var->green.length) {
-		case 6: /* RGB565, 64k */
-			var->red.offset		= 11;
-			var->red.length		= 5;
-			var->green.offset	= 5;
-			var->green.length	= 6;
-			var->blue.offset	= 0;
-			var->blue.length	= 5;
-			break;
-
-		default:
-		case 5: /* RGB555, 32k */
-			var->red.offset		= 10;
-			var->red.length		= 5;
-			var->green.offset	= 5;
-			var->green.length	= 5;
-			var->blue.offset	= 0;
-			var->blue.length	= 5;
-			break;
-
-		case 4: /* RGB444, 4k + transparency? */
-			var->transp.offset	= 12;
-			var->transp.length	= 4;
-			var->red.offset		= 8;
-			var->red.length		= 4;
-			var->green.offset	= 4;
-			var->green.length	= 4;
-			var->blue.offset	= 0;
-			var->blue.length	= 4;
-			break;
-		}
-		break;
-
-	case 24:/* TRUECOLOUR, 16m */
-		var->red.offset		= 16;
-		var->red.length		= 8;
-		var->green.offset	= 8;
-		var->green.length	= 8;
-		var->blue.offset	= 0;
-		var->blue.length	= 8;
-		break;
-
-	case 32:/* TRUECOLOUR, 16m */
-		var->transp.offset	= 24;
-		var->transp.length	= 8;
-		var->red.offset		= 16;
-		var->red.length		= 8;
-		var->green.offset	= 8;
-		var->green.length	= 8;
-		var->blue.offset	= 0;
-		var->blue.length	= 8;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
-	if (mem > cfb->fb.fix.smem_len)
-		var->yres_virtual = cfb->fb.fix.smem_len * 8 /
-				    (var->bits_per_pixel * var->xres_virtual);
-
-	if (var->yres > var->yres_virtual)
-		var->yres = var->yres_virtual;
-	if (var->xres > var->xres_virtual)
-		var->xres = var->xres_virtual;
-
-	err = cyber2000fb_decode_clock(&hw, cfb, var);
-	if (err)
-		return err;
-
-	err = cyber2000fb_decode_crtc(&hw, cfb, var);
-	if (err)
-		return err;
-
-	return 0;
-}
-
-static int cyber2000fb_set_par(struct fb_info *info)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-	struct fb_var_screeninfo *var = &cfb->fb.var;
-	struct par_info hw;
-	unsigned int mem;
-
-	hw.width = var->xres_virtual;
-	hw.ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		hw.co_pixfmt		= CO_PIXFMT_8BPP;
-		hw.pitch		= hw.width >> 3;
-		hw.extseqmisc		= EXT_SEQ_MISC_8;
-		break;
-
-	case 16:
-		hw.co_pixfmt		= CO_PIXFMT_16BPP;
-		hw.pitch		= hw.width >> 2;
-
-		switch (var->green.length) {
-		case 6: /* RGB565, 64k */
-			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB565;
-			break;
-		case 5: /* RGB555, 32k */
-			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB555;
-			break;
-		case 4: /* RGB444, 4k + transparency? */
-			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB444;
-			break;
-		default:
-			BUG();
-		}
-		break;
-
-	case 24:/* TRUECOLOUR, 16m */
-		hw.co_pixfmt		= CO_PIXFMT_24BPP;
-		hw.width		*= 3;
-		hw.pitch		= hw.width >> 3;
-		hw.ramdac		|= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-		hw.extseqmisc		= EXT_SEQ_MISC_24_RGB888;
-		break;
-
-	case 32:/* TRUECOLOUR, 16m */
-		hw.co_pixfmt		= CO_PIXFMT_32BPP;
-		hw.pitch		= hw.width >> 1;
-		hw.ramdac		|= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-		hw.extseqmisc		= EXT_SEQ_MISC_32;
-		break;
-
-	default:
-		BUG();
-	}
-
-	/*
-	 * Sigh, this is absolutely disgusting, but caused by
-	 * the way the fbcon developers want to separate out
-	 * the "checking" and the "setting" of the video mode.
-	 *
-	 * If the mode is not suitable for the hardware here,
-	 * we can't prevent it being set by returning an error.
-	 *
-	 * In theory, since NetWinders contain just one VGA card,
-	 * we should never end up hitting this problem.
-	 */
-	BUG_ON(cyber2000fb_decode_clock(&hw, cfb, var) != 0);
-	BUG_ON(cyber2000fb_decode_crtc(&hw, cfb, var) != 0);
-
-	hw.width -= 1;
-	hw.fetch = hw.pitch;
-	if (!(cfb->mem_ctl2 & MEM_CTL2_64BIT))
-		hw.fetch <<= 1;
-	hw.fetch += 1;
-
-	cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
-
-	/*
-	 * Same here - if the size of the video mode exceeds the
-	 * available RAM, we can't prevent this mode being set.
-	 *
-	 * In theory, since NetWinders contain just one VGA card,
-	 * we should never end up hitting this problem.
-	 */
-	mem = cfb->fb.fix.line_length * var->yres_virtual;
-	BUG_ON(mem > cfb->fb.fix.smem_len);
-
-	/*
-	 * 8bpp displays are always pseudo colour.  16bpp and above
-	 * are direct colour or true colour, depending on whether
-	 * the RAMDAC palettes are bypassed.  (Direct colour has
-	 * palettes, true colour does not.)
-	 */
-	if (var->bits_per_pixel == 8)
-		cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else if (hw.ramdac & RAMDAC_BYPASS)
-		cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-	else
-		cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
-
-	cyber2000fb_set_timing(cfb, &hw);
-	cyber2000fb_update_start(cfb, var);
-
-	return 0;
-}
-
-/*
- *    Pan or Wrap the Display
- */
-static int
-cyber2000fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-
-	if (cyber2000fb_update_start(cfb, var))
-		return -EINVAL;
-
-	cfb->fb.var.xoffset = var->xoffset;
-	cfb->fb.var.yoffset = var->yoffset;
-
-	if (var->vmode & FB_VMODE_YWRAP) {
-		cfb->fb.var.vmode |= FB_VMODE_YWRAP;
-	} else {
-		cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
-	}
-
-	return 0;
-}
-
-/*
- *    (Un)Blank the display.
- *
- *  Blank the screen if blank_mode != 0, else unblank. If
- *  blank == NULL then the caller blanks by setting the CLUT
- *  (Color Look Up Table) to all black. Return 0 if blanking
- *  succeeded, != 0 if un-/blanking failed due to e.g. a
- *  video mode which doesn't support it. Implements VESA
- *  suspend and powerdown modes on hardware that supports
- *  disabling hsync/vsync:
- *    blank_mode == 2: suspend vsync
- *    blank_mode == 3: suspend hsync
- *    blank_mode == 4: powerdown
- *
- *  wms...Enable VESA DMPS compatible powerdown mode
- *  run "setterm -powersave powerdown" to take advantage
- */
-static int cyber2000fb_blank(int blank, struct fb_info *info)
-{
-	struct cfb_info *cfb = (struct cfb_info *)info;
-	unsigned int sync = 0;
-	int i;
-
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:	/* powerdown - both sync lines down */
-		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:	/* hsync off */
-		sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:	/* vsync off */
-		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
-		break;
-	case FB_BLANK_NORMAL:		/* soft blank */
-	default:			/* unblank */
-		break;
-	}
-
-	cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
-
-	if (blank <= 1) {
-		/* turn on ramdacs */
-		cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS |
-					   RAMDAC_RAMPWRDN);
-		cyber2000fb_write_ramdac_ctrl(cfb);
-	}
-
-	/*
-	 * Soft blank/unblank the display.
-	 */
-	if (blank) {	/* soft blank */
-		for (i = 0; i < NR_PALETTE; i++) {
-			cyber2000fb_writeb(i, 0x3c8, cfb);
-			cyber2000fb_writeb(0, 0x3c9, cfb);
-			cyber2000fb_writeb(0, 0x3c9, cfb);
-			cyber2000fb_writeb(0, 0x3c9, cfb);
-		}
-	} else {	/* unblank */
-		for (i = 0; i < NR_PALETTE; i++) {
-			cyber2000fb_writeb(i, 0x3c8, cfb);
-			cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
-			cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
-			cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
-		}
-	}
-
-	if (blank >= 2) {
-		/* turn off ramdacs */
-		cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS |
-					 RAMDAC_RAMPWRDN;
-		cyber2000fb_write_ramdac_ctrl(cfb);
-	}
-
-	return 0;
-}
-
-static struct fb_ops cyber2000fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= cyber2000fb_check_var,
-	.fb_set_par	= cyber2000fb_set_par,
-	.fb_setcolreg	= cyber2000fb_setcolreg,
-	.fb_blank	= cyber2000fb_blank,
-	.fb_pan_display	= cyber2000fb_pan_display,
-	.fb_fillrect	= cyber2000fb_fillrect,
-	.fb_copyarea	= cyber2000fb_copyarea,
-	.fb_imageblit	= cyber2000fb_imageblit,
-	.fb_sync	= cyber2000fb_sync,
-};
-
-/*
- * This is the only "static" reference to the internal data structures
- * of this driver.  It is here solely at the moment to support the other
- * CyberPro modules external to this driver.
- */
-static struct cfb_info *int_cfb_info;
-
-/*
- * Enable access to the extended registers
- */
-void cyber2000fb_enable_extregs(struct cfb_info *cfb)
-{
-	cfb->func_use_count += 1;
-
-	if (cfb->func_use_count == 1) {
-		int old;
-
-		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
-		old |= EXT_FUNC_CTL_EXTREGENBL;
-		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
-	}
-}
-EXPORT_SYMBOL(cyber2000fb_enable_extregs);
-
-/*
- * Disable access to the extended registers
- */
-void cyber2000fb_disable_extregs(struct cfb_info *cfb)
-{
-	if (cfb->func_use_count == 1) {
-		int old;
-
-		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
-		old &= ~EXT_FUNC_CTL_EXTREGENBL;
-		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
-	}
-
-	if (cfb->func_use_count == 0)
-		printk(KERN_ERR "disable_extregs: count = 0\n");
-	else
-		cfb->func_use_count -= 1;
-}
-EXPORT_SYMBOL(cyber2000fb_disable_extregs);
-
-/*
- * Attach a capture/tv driver to the core CyberX0X0 driver.
- */
-int cyber2000fb_attach(struct cyberpro_info *info, int idx)
-{
-	if (int_cfb_info != NULL) {
-		info->dev	      = int_cfb_info->fb.device;
-#ifdef CONFIG_FB_CYBER2000_I2C
-		info->i2c	      = &int_cfb_info->i2c_adapter;
-#else
-		info->i2c	      = NULL;
-#endif
-		info->regs	      = int_cfb_info->regs;
-		info->irq             = int_cfb_info->irq;
-		info->fb	      = int_cfb_info->fb.screen_base;
-		info->fb_size	      = int_cfb_info->fb.fix.smem_len;
-		info->info	      = int_cfb_info;
-
-		strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
-			sizeof(info->dev_name));
-	}
-
-	return int_cfb_info != NULL;
-}
-EXPORT_SYMBOL(cyber2000fb_attach);
-
-/*
- * Detach a capture/tv driver from the core CyberX0X0 driver.
- */
-void cyber2000fb_detach(int idx)
-{
-}
-EXPORT_SYMBOL(cyber2000fb_detach);
-
-#ifdef CONFIG_FB_CYBER2000_DDC
-
-#define DDC_REG		0xb0
-#define DDC_SCL_OUT	(1 << 0)
-#define DDC_SDA_OUT	(1 << 4)
-#define DDC_SCL_IN	(1 << 2)
-#define DDC_SDA_IN	(1 << 6)
-
-static void cyber2000fb_enable_ddc(struct cfb_info *cfb)
-{
-	spin_lock(&cfb->reg_b0_lock);
-	cyber2000fb_writew(0x1bf, 0x3ce, cfb);
-}
-
-static void cyber2000fb_disable_ddc(struct cfb_info *cfb)
-{
-	cyber2000fb_writew(0x0bf, 0x3ce, cfb);
-	spin_unlock(&cfb->reg_b0_lock);
-}
-
-
-static void cyber2000fb_ddc_setscl(void *data, int val)
-{
-	struct cfb_info *cfb = data;
-	unsigned char reg;
-
-	cyber2000fb_enable_ddc(cfb);
-	reg = cyber2000_grphr(DDC_REG, cfb);
-	if (!val)	/* bit is inverted */
-		reg |= DDC_SCL_OUT;
-	else
-		reg &= ~DDC_SCL_OUT;
-	cyber2000_grphw(DDC_REG, reg, cfb);
-	cyber2000fb_disable_ddc(cfb);
-}
-
-static void cyber2000fb_ddc_setsda(void *data, int val)
-{
-	struct cfb_info *cfb = data;
-	unsigned char reg;
-
-	cyber2000fb_enable_ddc(cfb);
-	reg = cyber2000_grphr(DDC_REG, cfb);
-	if (!val)	/* bit is inverted */
-		reg |= DDC_SDA_OUT;
-	else
-		reg &= ~DDC_SDA_OUT;
-	cyber2000_grphw(DDC_REG, reg, cfb);
-	cyber2000fb_disable_ddc(cfb);
-}
-
-static int cyber2000fb_ddc_getscl(void *data)
-{
-	struct cfb_info *cfb = data;
-	int retval;
-
-	cyber2000fb_enable_ddc(cfb);
-	retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SCL_IN);
-	cyber2000fb_disable_ddc(cfb);
-
-	return retval;
-}
-
-static int cyber2000fb_ddc_getsda(void *data)
-{
-	struct cfb_info *cfb = data;
-	int retval;
-
-	cyber2000fb_enable_ddc(cfb);
-	retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SDA_IN);
-	cyber2000fb_disable_ddc(cfb);
-
-	return retval;
-}
-
-static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
-{
-	strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
-		sizeof(cfb->ddc_adapter.name));
-	cfb->ddc_adapter.owner		= THIS_MODULE;
-	cfb->ddc_adapter.class		= I2C_CLASS_DDC;
-	cfb->ddc_adapter.algo_data	= &cfb->ddc_algo;
-	cfb->ddc_adapter.dev.parent	= cfb->fb.device;
-	cfb->ddc_algo.setsda		= cyber2000fb_ddc_setsda;
-	cfb->ddc_algo.setscl		= cyber2000fb_ddc_setscl;
-	cfb->ddc_algo.getsda		= cyber2000fb_ddc_getsda;
-	cfb->ddc_algo.getscl		= cyber2000fb_ddc_getscl;
-	cfb->ddc_algo.udelay		= 10;
-	cfb->ddc_algo.timeout		= 20;
-	cfb->ddc_algo.data		= cfb;
-
-	i2c_set_adapdata(&cfb->ddc_adapter, cfb);
-
-	return i2c_bit_add_bus(&cfb->ddc_adapter);
-}
-#endif /* CONFIG_FB_CYBER2000_DDC */
-
-#ifdef CONFIG_FB_CYBER2000_I2C
-static void cyber2000fb_i2c_setsda(void *data, int state)
-{
-	struct cfb_info *cfb = data;
-	unsigned int latch2;
-
-	spin_lock(&cfb->reg_b0_lock);
-	latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
-	latch2 &= EXT_LATCH2_I2C_CLKEN;
-	if (state)
-		latch2 |= EXT_LATCH2_I2C_DATEN;
-	cyber2000_grphw(EXT_LATCH2, latch2, cfb);
-	spin_unlock(&cfb->reg_b0_lock);
-}
-
-static void cyber2000fb_i2c_setscl(void *data, int state)
-{
-	struct cfb_info *cfb = data;
-	unsigned int latch2;
-
-	spin_lock(&cfb->reg_b0_lock);
-	latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
-	latch2 &= EXT_LATCH2_I2C_DATEN;
-	if (state)
-		latch2 |= EXT_LATCH2_I2C_CLKEN;
-	cyber2000_grphw(EXT_LATCH2, latch2, cfb);
-	spin_unlock(&cfb->reg_b0_lock);
-}
-
-static int cyber2000fb_i2c_getsda(void *data)
-{
-	struct cfb_info *cfb = data;
-	int ret;
-
-	spin_lock(&cfb->reg_b0_lock);
-	ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
-	spin_unlock(&cfb->reg_b0_lock);
-
-	return ret;
-}
-
-static int cyber2000fb_i2c_getscl(void *data)
-{
-	struct cfb_info *cfb = data;
-	int ret;
-
-	spin_lock(&cfb->reg_b0_lock);
-	ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
-	spin_unlock(&cfb->reg_b0_lock);
-
-	return ret;
-}
-
-static int cyber2000fb_i2c_register(struct cfb_info *cfb)
-{
-	strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
-		sizeof(cfb->i2c_adapter.name));
-	cfb->i2c_adapter.owner = THIS_MODULE;
-	cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
-	cfb->i2c_adapter.dev.parent = cfb->fb.device;
-	cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
-	cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
-	cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
-	cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
-	cfb->i2c_algo.udelay = 5;
-	cfb->i2c_algo.timeout = msecs_to_jiffies(100);
-	cfb->i2c_algo.data = cfb;
-
-	return i2c_bit_add_bus(&cfb->i2c_adapter);
-}
-
-static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
-{
-	i2c_del_adapter(&cfb->i2c_adapter);
-}
-#else
-#define cyber2000fb_i2c_register(cfb)	(0)
-#define cyber2000fb_i2c_unregister(cfb)	do { } while (0)
-#endif
-
-/*
- * These parameters give
- * 640x480, hsync 31.5kHz, vsync 60Hz
- */
-static struct fb_videomode cyber2000fb_default_mode = {
-	.refresh	= 60,
-	.xres		= 640,
-	.yres		= 480,
-	.pixclock	= 39722,
-	.left_margin	= 56,
-	.right_margin	= 16,
-	.upper_margin	= 34,
-	.lower_margin	= 9,
-	.hsync_len	= 88,
-	.vsync_len	= 2,
-	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode		= FB_VMODE_NONINTERLACED
-};
-
-static char igs_regs[] = {
-	EXT_CRT_IRQ,		0,
-	EXT_CRT_TEST,		0,
-	EXT_SYNC_CTL,		0,
-	EXT_SEG_WRITE_PTR,	0,
-	EXT_SEG_READ_PTR,	0,
-	EXT_BIU_MISC,		EXT_BIU_MISC_LIN_ENABLE |
-				EXT_BIU_MISC_COP_ENABLE |
-				EXT_BIU_MISC_COP_BFC,
-	EXT_FUNC_CTL,		0,
-	CURS_H_START,		0,
-	CURS_H_START + 1,	0,
-	CURS_H_PRESET,		0,
-	CURS_V_START,		0,
-	CURS_V_START + 1,	0,
-	CURS_V_PRESET,		0,
-	CURS_CTL,		0,
-	EXT_ATTRIB_CTL,		EXT_ATTRIB_CTL_EXT,
-	EXT_OVERSCAN_RED,	0,
-	EXT_OVERSCAN_GREEN,	0,
-	EXT_OVERSCAN_BLUE,	0,
-
-	/* some of these are questionable when we have a BIOS */
-	EXT_MEM_CTL0,		EXT_MEM_CTL0_7CLK |
-				EXT_MEM_CTL0_RAS_1 |
-				EXT_MEM_CTL0_MULTCAS,
-	EXT_HIDDEN_CTL1,	0x30,
-	EXT_FIFO_CTL,		0x0b,
-	EXT_FIFO_CTL + 1,	0x17,
-	0x76,			0x00,
-	EXT_HIDDEN_CTL4,	0xc8
-};
-
-/*
- * Initialise the CyberPro hardware.  On the CyberPro5XXXX,
- * ensure that we're using the correct PLL (5XXX's may be
- * programmed to use an additional set of PLLs.)
- */
-static void cyberpro_init_hw(struct cfb_info *cfb)
-{
-	int i;
-
-	for (i = 0; i < sizeof(igs_regs); i += 2)
-		cyber2000_grphw(igs_regs[i], igs_regs[i + 1], cfb);
-
-	if (cfb->id == ID_CYBERPRO_5000) {
-		unsigned char val;
-		cyber2000fb_writeb(0xba, 0x3ce, cfb);
-		val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
-		cyber2000fb_writeb(val, 0x3cf, cfb);
-	}
-}
-
-static struct cfb_info *cyberpro_alloc_fb_info(unsigned int id, char *name)
-{
-	struct cfb_info *cfb;
-
-	cfb = kzalloc(sizeof(struct cfb_info), GFP_KERNEL);
-	if (!cfb)
-		return NULL;
-
-
-	cfb->id			= id;
-
-	if (id == ID_CYBERPRO_5000)
-		cfb->ref_ps	= 40690; /* 24.576 MHz */
-	else
-		cfb->ref_ps	= 69842; /* 14.31818 MHz (69841?) */
-
-	cfb->divisors[0]	= 1;
-	cfb->divisors[1]	= 2;
-	cfb->divisors[2]	= 4;
-
-	if (id == ID_CYBERPRO_2000)
-		cfb->divisors[3] = 8;
-	else
-		cfb->divisors[3] = 6;
-
-	strcpy(cfb->fb.fix.id, name);
-
-	cfb->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
-	cfb->fb.fix.type_aux	= 0;
-	cfb->fb.fix.xpanstep	= 0;
-	cfb->fb.fix.ypanstep	= 1;
-	cfb->fb.fix.ywrapstep	= 0;
-
-	switch (id) {
-	case ID_IGA_1682:
-		cfb->fb.fix.accel = 0;
-		break;
-
-	case ID_CYBERPRO_2000:
-		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
-		break;
-
-	case ID_CYBERPRO_2010:
-		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
-		break;
-
-	case ID_CYBERPRO_5000:
-		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
-		break;
-	}
-
-	cfb->fb.var.nonstd	= 0;
-	cfb->fb.var.activate	= FB_ACTIVATE_NOW;
-	cfb->fb.var.height	= -1;
-	cfb->fb.var.width	= -1;
-	cfb->fb.var.accel_flags	= FB_ACCELF_TEXT;
-
-	cfb->fb.fbops		= &cyber2000fb_ops;
-	cfb->fb.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	cfb->fb.pseudo_palette	= cfb->pseudo_palette;
-
-	spin_lock_init(&cfb->reg_b0_lock);
-
-	fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
-
-	return cfb;
-}
-
-static void cyberpro_free_fb_info(struct cfb_info *cfb)
-{
-	if (cfb) {
-		/*
-		 * Free the colourmap
-		 */
-		fb_alloc_cmap(&cfb->fb.cmap, 0, 0);
-
-		kfree(cfb);
-	}
-}
-
-/*
- * Parse Cyber2000fb options.  Usage:
- *  video=cyber2000:font:fontname
- */
-#ifndef MODULE
-static int cyber2000fb_setup(char *options)
-{
-	char *opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-
-		if (strncmp(opt, "font:", 5) == 0) {
-			static char default_font_storage[40];
-
-			strlcpy(default_font_storage, opt + 5,
-				sizeof(default_font_storage));
-			default_font = default_font_storage;
-			continue;
-		}
-
-		printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", opt);
-	}
-	return 0;
-}
-#endif  /*  MODULE  */
-
-/*
- * The CyberPro chips can be placed on many different bus types.
- * This probe function is common to all bus types.  The bus-specific
- * probe function is expected to have:
- *  - enabled access to the linear memory region
- *  - memory mapped access to the registers
- *  - initialised mem_ctl1 and mem_ctl2 appropriately.
- */
-static int cyberpro_common_probe(struct cfb_info *cfb)
-{
-	u_long smem_size;
-	u_int h_sync, v_sync;
-	int err;
-
-	cyberpro_init_hw(cfb);
-
-	/*
-	 * Get the video RAM size and width from the VGA register.
-	 * This should have been already initialised by the BIOS,
-	 * but if it's garbage, claim default 1MB VRAM (woody)
-	 */
-	cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
-	cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
-
-	/*
-	 * Determine the size of the memory.
-	 */
-	switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
-	case MEM_CTL2_SIZE_4MB:
-		smem_size = 0x00400000;
-		break;
-	case MEM_CTL2_SIZE_2MB:
-		smem_size = 0x00200000;
-		break;
-	case MEM_CTL2_SIZE_1MB:
-		smem_size = 0x00100000;
-		break;
-	default:
-		smem_size = 0x00100000;
-		break;
-	}
-
-	cfb->fb.fix.smem_len   = smem_size;
-	cfb->fb.fix.mmio_len   = MMIO_SIZE;
-	cfb->fb.screen_base    = cfb->region;
-
-#ifdef CONFIG_FB_CYBER2000_DDC
-	if (cyber2000fb_setup_ddc_bus(cfb) == 0)
-		cfb->ddc_registered = true;
-#endif
-
-	err = -EINVAL;
-	if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
-			  &cyber2000fb_default_mode, 8)) {
-		printk(KERN_ERR "%s: no valid mode found\n", cfb->fb.fix.id);
-		goto failed;
-	}
-
-	cfb->fb.var.yres_virtual = cfb->fb.fix.smem_len * 8 /
-			(cfb->fb.var.bits_per_pixel * cfb->fb.var.xres_virtual);
-
-	if (cfb->fb.var.yres_virtual < cfb->fb.var.yres)
-		cfb->fb.var.yres_virtual = cfb->fb.var.yres;
-
-/*	fb_set_var(&cfb->fb.var, -1, &cfb->fb); */
-
-	/*
-	 * Calculate the hsync and vsync frequencies.  Note that
-	 * we split the 1e12 constant up so that we can preserve
-	 * the precision and fit the results into 32-bit registers.
-	 *  (1953125000 * 512 = 1e12)
-	 */
-	h_sync = 1953125000 / cfb->fb.var.pixclock;
-	h_sync = h_sync * 512 / (cfb->fb.var.xres + cfb->fb.var.left_margin +
-		 cfb->fb.var.right_margin + cfb->fb.var.hsync_len);
-	v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
-		 cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
-
-	printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
-		cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
-		cfb->fb.var.xres, cfb->fb.var.yres,
-		h_sync / 1000, h_sync % 1000, v_sync);
-
-	err = cyber2000fb_i2c_register(cfb);
-	if (err)
-		goto failed;
-
-	err = register_framebuffer(&cfb->fb);
-	if (err)
-		cyber2000fb_i2c_unregister(cfb);
-
-failed:
-#ifdef CONFIG_FB_CYBER2000_DDC
-	if (err && cfb->ddc_registered)
-		i2c_del_adapter(&cfb->ddc_adapter);
-#endif
-	return err;
-}
-
-static void cyberpro_common_remove(struct cfb_info *cfb)
-{
-	unregister_framebuffer(&cfb->fb);
-#ifdef CONFIG_FB_CYBER2000_DDC
-	if (cfb->ddc_registered)
-		i2c_del_adapter(&cfb->ddc_adapter);
-#endif
-	cyber2000fb_i2c_unregister(cfb);
-}
-
-static void cyberpro_common_resume(struct cfb_info *cfb)
-{
-	cyberpro_init_hw(cfb);
-
-	/*
-	 * Reprogram the MEM_CTL1 and MEM_CTL2 registers
-	 */
-	cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
-	cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
-
-	/*
-	 * Restore the old video mode and the palette.
-	 * We also need to tell fbcon to redraw the console.
-	 */
-	cyber2000fb_set_par(&cfb->fb);
-}
-
-/*
- * PCI specific support.
- */
-#ifdef CONFIG_PCI
-/*
- * We need to wake up the CyberPro, and make sure its in linear memory
- * mode.  Unfortunately, this is specific to the platform and card that
- * we are running on.
- *
- * On x86 and ARM, should we be initialising the CyberPro first via the
- * IO registers, and then the MMIO registers to catch all cases?  Can we
- * end up in the situation where the chip is in MMIO mode, but not awake
- * on an x86 system?
- */
-static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
-{
-	unsigned char val;
-
-#if defined(__sparc_v9__)
-#error "You lose, consult DaveM."
-#elif defined(__sparc__)
-	/*
-	 * SPARC does not have an "outb" instruction, so we generate
-	 * I/O cycles storing into a reserved memory space at
-	 * physical address 0x3000000
-	 */
-	unsigned char __iomem *iop;
-
-	iop = ioremap(0x3000000, 0x5000);
-	if (iop == NULL) {
-		printk(KERN_ERR "iga5000: cannot map I/O\n");
-		return -ENOMEM;
-	}
-
-	writeb(0x18, iop + 0x46e8);
-	writeb(0x01, iop + 0x102);
-	writeb(0x08, iop + 0x46e8);
-	writeb(EXT_BIU_MISC, iop + 0x3ce);
-	writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
-
-	iounmap(iop);
-#else
-	/*
-	 * Most other machine types are "normal", so
-	 * we use the standard IO-based wakeup.
-	 */
-	outb(0x18, 0x46e8);
-	outb(0x01, 0x102);
-	outb(0x08, 0x46e8);
-	outb(EXT_BIU_MISC, 0x3ce);
-	outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
-#endif
-
-	/*
-	 * Allow the CyberPro to accept PCI burst accesses
-	 */
-	if (cfb->id == ID_CYBERPRO_2010) {
-		printk(KERN_INFO "%s: NOT enabling PCI bursts\n",
-		       cfb->fb.fix.id);
-	} else {
-		val = cyber2000_grphr(EXT_BUS_CTL, cfb);
-		if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
-			printk(KERN_INFO "%s: enabling PCI bursts\n",
-				cfb->fb.fix.id);
-
-			val |= EXT_BUS_CTL_PCIBURST_WRITE;
-
-			if (cfb->id == ID_CYBERPRO_5000)
-				val |= EXT_BUS_CTL_PCIBURST_READ;
-
-			cyber2000_grphw(EXT_BUS_CTL, val, cfb);
-		}
-	}
-
-	return 0;
-}
-
-static int cyberpro_pci_probe(struct pci_dev *dev,
-			      const struct pci_device_id *id)
-{
-	struct cfb_info *cfb;
-	char name[16];
-	int err;
-
-	sprintf(name, "CyberPro%4X", id->device);
-
-	err = pci_enable_device(dev);
-	if (err)
-		return err;
-
-	err = -ENOMEM;
-	cfb = cyberpro_alloc_fb_info(id->driver_data, name);
-	if (!cfb)
-		goto failed_release;
-
-	err = pci_request_regions(dev, cfb->fb.fix.id);
-	if (err)
-		goto failed_regions;
-
-	cfb->irq = dev->irq;
-	cfb->region = pci_ioremap_bar(dev, 0);
-	if (!cfb->region) {
-		err = -ENOMEM;
-		goto failed_ioremap;
-	}
-
-	cfb->regs = cfb->region + MMIO_OFFSET;
-	cfb->fb.device = &dev->dev;
-	cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
-	cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
-
-	/*
-	 * Bring up the hardware.  This is expected to enable access
-	 * to the linear memory region, and allow access to the memory
-	 * mapped registers.  Also, mem_ctl1 and mem_ctl2 must be
-	 * initialised.
-	 */
-	err = cyberpro_pci_enable_mmio(cfb);
-	if (err)
-		goto failed;
-
-	/*
-	 * Use MCLK from BIOS. FIXME: what about hotplug?
-	 */
-	cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
-	cfb->mclk_div  = cyber2000_grphr(EXT_MCLK_DIV, cfb);
-
-#ifdef __arm__
-	/*
-	 * MCLK on the NetWinder and the Shark is fixed at 75MHz
-	 */
-	if (machine_is_netwinder()) {
-		cfb->mclk_mult = 0xdb;
-		cfb->mclk_div  = 0x54;
-	}
-#endif
-
-	err = cyberpro_common_probe(cfb);
-	if (err)
-		goto failed;
-
-	/*
-	 * Our driver data
-	 */
-	pci_set_drvdata(dev, cfb);
-	if (int_cfb_info == NULL)
-		int_cfb_info = cfb;
-
-	return 0;
-
-failed:
-	iounmap(cfb->region);
-failed_ioremap:
-	pci_release_regions(dev);
-failed_regions:
-	cyberpro_free_fb_info(cfb);
-failed_release:
-	return err;
-}
-
-static void cyberpro_pci_remove(struct pci_dev *dev)
-{
-	struct cfb_info *cfb = pci_get_drvdata(dev);
-
-	if (cfb) {
-		cyberpro_common_remove(cfb);
-		iounmap(cfb->region);
-		cyberpro_free_fb_info(cfb);
-
-		if (cfb == int_cfb_info)
-			int_cfb_info = NULL;
-
-		pci_release_regions(dev);
-	}
-}
-
-static int cyberpro_pci_suspend(struct pci_dev *dev, pm_message_t state)
-{
-	return 0;
-}
-
-/*
- * Re-initialise the CyberPro hardware
- */
-static int cyberpro_pci_resume(struct pci_dev *dev)
-{
-	struct cfb_info *cfb = pci_get_drvdata(dev);
-
-	if (cfb) {
-		cyberpro_pci_enable_mmio(cfb);
-		cyberpro_common_resume(cfb);
-	}
-
-	return 0;
-}
-
-static struct pci_device_id cyberpro_pci_table[] = {
-/*	Not yet
- *	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
- *		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
- */
-	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
-	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
-	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, cyberpro_pci_table);
-
-static struct pci_driver cyberpro_driver = {
-	.name		= "CyberPro",
-	.probe		= cyberpro_pci_probe,
-	.remove		= cyberpro_pci_remove,
-	.suspend	= cyberpro_pci_suspend,
-	.resume		= cyberpro_pci_resume,
-	.id_table	= cyberpro_pci_table
-};
-#endif
-
-/*
- * I don't think we can use the "module_init" stuff here because
- * the fbcon stuff may not be initialised yet.  Hence the #ifdef
- * around module_init.
- *
- * Tony: "module_init" is now required
- */
-static int __init cyber2000fb_init(void)
-{
-	int ret = -1, err;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("cyber2000fb", &option))
-		return -ENODEV;
-	cyber2000fb_setup(option);
-#endif
-
-	err = pci_register_driver(&cyberpro_driver);
-	if (!err)
-		ret = 0;
-
-	return ret ? err : 0;
-}
-module_init(cyber2000fb_init);
-
-static void __exit cyberpro_exit(void)
-{
-	pci_unregister_driver(&cyberpro_driver);
-}
-module_exit(cyberpro_exit);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/cyber2000fb.h b/drivers/video/cyber2000fb.h
deleted file mode 100644
index bad69102e774..000000000000
--- a/drivers/video/cyber2000fb.h
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- *  linux/drivers/video/cyber2000fb.h
- *
- *  Copyright (C) 1998-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Integraphics Cyber2000 frame buffer device
- */
-
-/*
- * Internal CyberPro sizes and offsets.
- */
-#define MMIO_OFFSET	0x00800000
-#define MMIO_SIZE	0x000c0000
-
-#define NR_PALETTE	256
-
-#if defined(DEBUG) && defined(CONFIG_DEBUG_LL)
-static void debug_printf(char *fmt, ...)
-{
-	extern void printascii(const char *);
-	char buffer[128];
-	va_list ap;
-
-	va_start(ap, fmt);
-	vsprintf(buffer, fmt, ap);
-	va_end(ap);
-
-	printascii(buffer);
-}
-#else
-#define debug_printf(x...) do { } while (0)
-#endif
-
-#define RAMDAC_RAMPWRDN		0x01
-#define RAMDAC_DAC8BIT		0x02
-#define RAMDAC_VREFEN		0x04
-#define RAMDAC_BYPASS		0x10
-#define RAMDAC_DACPWRDN		0x40
-
-#define EXT_CRT_VRTOFL		0x11
-#define EXT_CRT_VRTOFL_LINECOMP10	0x10
-#define EXT_CRT_VRTOFL_INTERLACE	0x20
-
-#define EXT_CRT_IRQ		0x12
-#define EXT_CRT_IRQ_ENABLE		0x01
-#define EXT_CRT_IRQ_ACT_HIGH		0x04
-
-#define EXT_CRT_TEST		0x13
-
-#define EXT_SYNC_CTL		0x16
-#define EXT_SYNC_CTL_HS_NORMAL		0x00
-#define EXT_SYNC_CTL_HS_0		0x01
-#define EXT_SYNC_CTL_HS_1		0x02
-#define EXT_SYNC_CTL_HS_HSVS		0x03
-#define EXT_SYNC_CTL_VS_NORMAL		0x00
-#define EXT_SYNC_CTL_VS_0		0x04
-#define EXT_SYNC_CTL_VS_1		0x08
-#define EXT_SYNC_CTL_VS_COMP		0x0c
-
-#define EXT_BUS_CTL		0x30
-#define EXT_BUS_CTL_LIN_1MB		0x00
-#define EXT_BUS_CTL_LIN_2MB		0x01
-#define EXT_BUS_CTL_LIN_4MB		0x02
-#define EXT_BUS_CTL_ZEROWAIT		0x04
-#define EXT_BUS_CTL_PCIBURST_WRITE	0x20
-#define EXT_BUS_CTL_PCIBURST_READ	0x80	/* CyberPro 5000 only */
-
-#define EXT_SEG_WRITE_PTR	0x31
-#define EXT_SEG_READ_PTR	0x32
-#define EXT_BIU_MISC		0x33
-#define EXT_BIU_MISC_LIN_ENABLE		0x01
-#define EXT_BIU_MISC_COP_ENABLE		0x04
-#define EXT_BIU_MISC_COP_BFC		0x08
-
-#define EXT_FUNC_CTL		0x3c
-#define EXT_FUNC_CTL_EXTREGENBL		0x80	/* enable access to 0xbcxxx		*/
-
-#define PCI_BM_CTL		0x3e
-#define PCI_BM_CTL_ENABLE		0x01	/* enable bus-master			*/
-#define PCI_BM_CTL_BURST		0x02	/* enable burst				*/
-#define PCI_BM_CTL_BACK2BACK		0x04	/* enable back to back			*/
-#define PCI_BM_CTL_DUMMY		0x08	/* insert dummy cycle			*/
-
-#define X_V2_VID_MEM_START	0x40
-#define X_V2_VID_SRC_WIDTH	0x43
-#define X_V2_X_START		0x45
-#define X_V2_X_END		0x47
-#define X_V2_Y_START		0x49
-#define X_V2_Y_END		0x4b
-#define X_V2_VID_SRC_WIN_WIDTH	0x4d
-
-#define Y_V2_DDA_X_INC		0x43
-#define Y_V2_DDA_Y_INC		0x47
-#define Y_V2_VID_FIFO_CTL	0x49
-#define Y_V2_VID_FMT		0x4b
-#define Y_V2_VID_DISP_CTL1	0x4c
-#define Y_V2_VID_FIFO_CTL1	0x4d
-
-#define J_X2_VID_MEM_START	0x40
-#define J_X2_VID_SRC_WIDTH	0x43
-#define J_X2_X_START		0x47
-#define J_X2_X_END		0x49
-#define J_X2_Y_START		0x4b
-#define J_X2_Y_END		0x4d
-#define J_X2_VID_SRC_WIN_WIDTH	0x4f
-
-#define K_X2_DDA_X_INIT		0x40
-#define K_X2_DDA_X_INC		0x42
-#define K_X2_DDA_Y_INIT		0x44
-#define K_X2_DDA_Y_INC		0x46
-#define K_X2_VID_FMT		0x48
-#define K_X2_VID_DISP_CTL1	0x49
-
-#define K_CAP_X2_CTL1		0x49
-
-#define CURS_H_START		0x50
-#define CURS_H_PRESET		0x52
-#define CURS_V_START		0x53
-#define CURS_V_PRESET		0x55
-#define CURS_CTL		0x56
-
-#define EXT_ATTRIB_CTL		0x57
-#define EXT_ATTRIB_CTL_EXT		0x01
-
-#define EXT_OVERSCAN_RED	0x58
-#define EXT_OVERSCAN_GREEN	0x59
-#define EXT_OVERSCAN_BLUE	0x5a
-
-#define CAP_X_START		0x60
-#define CAP_X_END		0x62
-#define CAP_Y_START		0x64
-#define CAP_Y_END		0x66
-#define CAP_DDA_X_INIT		0x68
-#define CAP_DDA_X_INC		0x6a
-#define CAP_DDA_Y_INIT		0x6c
-#define CAP_DDA_Y_INC		0x6e
-
-#define EXT_MEM_CTL0		0x70
-#define EXT_MEM_CTL0_7CLK		0x01
-#define EXT_MEM_CTL0_RAS_1		0x02
-#define EXT_MEM_CTL0_RAS2CAS_1		0x04
-#define EXT_MEM_CTL0_MULTCAS		0x08
-#define EXT_MEM_CTL0_ASYM		0x10
-#define EXT_MEM_CTL0_CAS1ON		0x20
-#define EXT_MEM_CTL0_FIFOFLUSH		0x40
-#define EXT_MEM_CTL0_SEQRESET		0x80
-
-#define EXT_MEM_CTL1		0x71
-#define EXT_MEM_CTL1_PAR		0x00
-#define EXT_MEM_CTL1_SERPAR		0x01
-#define EXT_MEM_CTL1_SER		0x03
-#define EXT_MEM_CTL1_SYNC		0x04
-#define EXT_MEM_CTL1_VRAM		0x08
-#define EXT_MEM_CTL1_4K_REFRESH		0x10
-#define EXT_MEM_CTL1_256Kx4		0x00
-#define EXT_MEM_CTL1_512Kx8		0x40
-#define EXT_MEM_CTL1_1Mx16		0x60
-
-#define EXT_MEM_CTL2		0x72
-#define MEM_CTL2_SIZE_1MB		0x00
-#define MEM_CTL2_SIZE_2MB		0x01
-#define MEM_CTL2_SIZE_4MB		0x02
-#define MEM_CTL2_SIZE_MASK		0x03
-#define MEM_CTL2_64BIT			0x04
-
-#define EXT_HIDDEN_CTL1		0x73
-
-#define EXT_FIFO_CTL		0x74
-
-#define EXT_SEQ_MISC		0x77
-#define EXT_SEQ_MISC_8			0x01
-#define EXT_SEQ_MISC_16_RGB565		0x02
-#define EXT_SEQ_MISC_32			0x03
-#define EXT_SEQ_MISC_24_RGB888		0x04
-#define EXT_SEQ_MISC_16_RGB555		0x06
-#define EXT_SEQ_MISC_8_RGB332		0x09
-#define EXT_SEQ_MISC_16_RGB444		0x0a
-
-#define EXT_HIDDEN_CTL4		0x7a
-
-#define CURS_MEM_START		0x7e		/* bits 23..12 */
-
-#define CAP_PIP_X_START		0x80
-#define CAP_PIP_X_END		0x82
-#define CAP_PIP_Y_START		0x84
-#define CAP_PIP_Y_END		0x86
-
-#define EXT_CAP_CTL1		0x88
-
-#define EXT_CAP_CTL2		0x89
-#define EXT_CAP_CTL2_ODDFRAMEIRQ	0x01
-#define EXT_CAP_CTL2_ANYFRAMEIRQ	0x02
-
-#define BM_CTRL0		0x9c
-#define BM_CTRL1		0x9d
-
-#define EXT_CAP_MODE1		0xa4
-#define EXT_CAP_MODE1_8BIT		0x01	/* enable 8bit capture mode		*/
-#define EXT_CAP_MODE1_CCIR656		0x02	/* CCIR656 mode				*/
-#define EXT_CAP_MODE1_IGNOREVGT		0x04	/* ignore VGT				*/
-#define EXT_CAP_MODE1_ALTFIFO		0x10	/* use alternate FIFO for capture	*/
-#define EXT_CAP_MODE1_SWAPUV		0x20	/* swap UV bytes			*/
-#define EXT_CAP_MODE1_MIRRORY		0x40	/* mirror vertically			*/
-#define EXT_CAP_MODE1_MIRRORX		0x80	/* mirror horizontally			*/
-
-#define EXT_CAP_MODE2		0xa5
-#define EXT_CAP_MODE2_CCIRINVOE		0x01
-#define EXT_CAP_MODE2_CCIRINVVGT	0x02
-#define EXT_CAP_MODE2_CCIRINVHGT	0x04
-#define EXT_CAP_MODE2_CCIRINVDG		0x08
-#define EXT_CAP_MODE2_DATEND		0x10
-#define EXT_CAP_MODE2_CCIRDGH		0x20
-#define EXT_CAP_MODE2_FIXSONY		0x40
-#define EXT_CAP_MODE2_SYNCFREEZE	0x80
-
-#define EXT_TV_CTL		0xae
-
-#define EXT_DCLK_MULT		0xb0
-#define EXT_DCLK_DIV		0xb1
-#define EXT_DCLK_DIV_VFSEL		0x20
-#define EXT_MCLK_MULT		0xb2
-#define EXT_MCLK_DIV		0xb3
-
-#define EXT_LATCH1		0xb5
-#define EXT_LATCH1_VAFC_EN		0x01	/* enable VAFC				*/
-
-#define EXT_FEATURE		0xb7
-#define EXT_FEATURE_BUS_MASK		0x07	/* host bus mask			*/
-#define EXT_FEATURE_BUS_PCI		0x00
-#define EXT_FEATURE_BUS_VL_STD		0x04
-#define EXT_FEATURE_BUS_VL_LINEAR	0x05
-#define EXT_FEATURE_1682		0x20	/* IGS 1682 compatibility		*/
-
-#define EXT_LATCH2		0xb6
-#define EXT_LATCH2_I2C_CLKEN		0x10
-#define EXT_LATCH2_I2C_CLK		0x20
-#define EXT_LATCH2_I2C_DATEN		0x40
-#define EXT_LATCH2_I2C_DAT		0x80
-
-#define EXT_XT_CTL		0xbe
-#define EXT_XT_CAP16			0x04
-#define EXT_XT_LINEARFB			0x08
-#define EXT_XT_PAL			0x10
-
-#define EXT_MEM_START		0xc0		/* ext start address 21 bits		*/
-#define HOR_PHASE_SHIFT		0xc2		/* high 3 bits				*/
-#define EXT_SRC_WIDTH		0xc3		/* ext offset phase  10 bits		*/
-#define EXT_SRC_HEIGHT		0xc4		/* high 6 bits				*/
-#define EXT_X_START		0xc5		/* ext->screen, 16 bits			*/
-#define EXT_X_END		0xc7		/* ext->screen, 16 bits			*/
-#define EXT_Y_START		0xc9		/* ext->screen, 16 bits			*/
-#define EXT_Y_END		0xcb		/* ext->screen, 16 bits			*/
-#define EXT_SRC_WIN_WIDTH	0xcd		/* 8 bits				*/
-#define EXT_COLOUR_COMPARE	0xce		/* 24 bits				*/
-#define EXT_DDA_X_INIT		0xd1		/* ext->screen 16 bits			*/
-#define EXT_DDA_X_INC		0xd3		/* ext->screen 16 bits			*/
-#define EXT_DDA_Y_INIT		0xd5		/* ext->screen 16 bits			*/
-#define EXT_DDA_Y_INC		0xd7		/* ext->screen 16 bits			*/
-
-#define EXT_VID_FIFO_CTL	0xd9
-
-#define EXT_VID_FMT		0xdb
-#define EXT_VID_FMT_YUV422		0x00	/* formats - does this cause conversion? */
-#define EXT_VID_FMT_RGB555		0x01
-#define EXT_VID_FMT_RGB565		0x02
-#define EXT_VID_FMT_RGB888_24		0x03
-#define EXT_VID_FMT_RGB888_32		0x04
-#define EXT_VID_FMT_RGB8		0x05
-#define EXT_VID_FMT_RGB4444		0x06
-#define EXT_VID_FMT_RGB8T		0x07
-#define EXT_VID_FMT_DUP_PIX_ZOON	0x08	/* duplicate pixel zoom			*/
-#define EXT_VID_FMT_MOD_3RD_PIX		0x20	/* modify 3rd duplicated pixel		*/
-#define EXT_VID_FMT_DBL_H_PIX		0x40	/* double horiz pixels			*/
-#define EXT_VID_FMT_YUV128		0x80	/* YUV data offset by 128		*/
-
-#define EXT_VID_DISP_CTL1	0xdc
-#define EXT_VID_DISP_CTL1_INTRAM	0x01	/* video pixels go to internal RAM	*/
-#define EXT_VID_DISP_CTL1_IGNORE_CCOMP	0x02	/* ignore colour compare registers	*/
-#define EXT_VID_DISP_CTL1_NOCLIP	0x04	/* do not clip to 16235,16240		*/
-#define EXT_VID_DISP_CTL1_UV_AVG	0x08	/* U/V data is averaged			*/
-#define EXT_VID_DISP_CTL1_Y128		0x10	/* Y data offset by 128 (if YUV128 set)	*/
-#define EXT_VID_DISP_CTL1_VINTERPOL_OFF	0x20	/* disable vertical interpolation	*/
-#define EXT_VID_DISP_CTL1_FULL_WIN	0x40	/* video out window full		*/
-#define EXT_VID_DISP_CTL1_ENABLE_WINDOW	0x80	/* enable video window			*/
-
-#define EXT_VID_FIFO_CTL1	0xdd
-#define EXT_VID_FIFO_CTL1_OE_HIGH	0x02
-#define EXT_VID_FIFO_CTL1_INTERLEAVE	0x04	/* enable interleaved memory read	*/
-
-#define EXT_ROM_UCB4GH		0xe5
-#define EXT_ROM_UCB4GH_FREEZE		0x02	/* capture frozen			*/
-#define EXT_ROM_UCB4GH_ODDFRAME		0x04	/* 1 = odd frame captured		*/
-#define EXT_ROM_UCB4GH_1HL		0x08	/* first horizonal line after VGT falling edge */
-#define EXT_ROM_UCB4GH_ODD		0x10	/* odd frame indicator			*/
-#define EXT_ROM_UCB4GH_INTSTAT		0x20	/* video interrupt			*/
-
-#define VFAC_CTL1		0xe8
-#define VFAC_CTL1_CAPTURE		0x01	/* capture enable (only when VSYNC high)*/
-#define VFAC_CTL1_VFAC_ENABLE		0x02	/* vfac enable				*/
-#define VFAC_CTL1_FREEZE_CAPTURE	0x04	/* freeze capture			*/
-#define VFAC_CTL1_FREEZE_CAPTURE_SYNC	0x08	/* sync freeze capture			*/
-#define VFAC_CTL1_VALIDFRAME_SRC	0x10	/* select valid frame source		*/
-#define VFAC_CTL1_PHILIPS		0x40	/* select Philips mode			*/
-#define VFAC_CTL1_MODVINTERPOLCLK	0x80	/* modify vertical interpolation clocl	*/
-
-#define VFAC_CTL2		0xe9
-#define VFAC_CTL2_INVERT_VIDDATAVALID	0x01	/* invert video data valid		*/
-#define VFAC_CTL2_INVERT_GRAPHREADY	0x02	/* invert graphic ready output sig	*/
-#define VFAC_CTL2_INVERT_DATACLK	0x04	/* invert data clock signal		*/
-#define VFAC_CTL2_INVERT_HSYNC		0x08	/* invert hsync input			*/
-#define VFAC_CTL2_INVERT_VSYNC		0x10	/* invert vsync input			*/
-#define VFAC_CTL2_INVERT_FRAME		0x20	/* invert frame odd/even input		*/
-#define VFAC_CTL2_INVERT_BLANK		0x40	/* invert blank output			*/
-#define VFAC_CTL2_INVERT_OVSYNC		0x80	/* invert other vsync input		*/
-
-#define VFAC_CTL3		0xea
-#define VFAC_CTL3_CAP_LARGE_FIFO	0x01	/* large capture fifo			*/
-#define VFAC_CTL3_CAP_INTERLACE		0x02	/* capture odd and even fields		*/
-#define VFAC_CTL3_CAP_HOLD_4NS		0x00	/* hold capture data for 4ns		*/
-#define VFAC_CTL3_CAP_HOLD_2NS		0x04	/* hold capture data for 2ns		*/
-#define VFAC_CTL3_CAP_HOLD_6NS		0x08	/* hold capture data for 6ns		*/
-#define VFAC_CTL3_CAP_HOLD_0NS		0x0c	/* hold capture data for 0ns		*/
-#define VFAC_CTL3_CHROMAKEY		0x20	/* capture data will be chromakeyed	*/
-#define VFAC_CTL3_CAP_IRQ		0x40	/* enable capture interrupt		*/
-
-#define CAP_MEM_START		0xeb		/* 18 bits				*/
-#define CAP_MAP_WIDTH		0xed		/* high 6 bits				*/
-#define CAP_PITCH		0xee		/* 8 bits				*/
-
-#define CAP_CTL_MISC		0xef
-#define CAP_CTL_MISC_HDIV		0x01
-#define CAP_CTL_MISC_HDIV4		0x02
-#define CAP_CTL_MISC_ODDEVEN		0x04
-#define CAP_CTL_MISC_HSYNCDIV2		0x08
-#define CAP_CTL_MISC_SYNCTZHIGH		0x10
-#define CAP_CTL_MISC_SYNCTZOR		0x20
-#define CAP_CTL_MISC_DISPUSED		0x80
-
-#define REG_BANK		0xfa
-#define REG_BANK_X			0x00
-#define REG_BANK_Y			0x01
-#define REG_BANK_W			0x02
-#define REG_BANK_T			0x03
-#define REG_BANK_J			0x04
-#define REG_BANK_K			0x05
-
-/*
- * Bus-master
- */
-#define BM_VID_ADDR_LOW		0xbc040
-#define BM_VID_ADDR_HIGH	0xbc044
-#define BM_ADDRESS_LOW		0xbc080
-#define BM_ADDRESS_HIGH		0xbc084
-#define BM_LENGTH		0xbc088
-#define BM_CONTROL		0xbc08c
-#define BM_CONTROL_ENABLE		0x01	/* enable transfer			*/
-#define BM_CONTROL_IRQEN		0x02	/* enable IRQ at end of transfer	*/
-#define BM_CONTROL_INIT			0x04	/* initialise status & count		*/
-#define BM_COUNT		0xbc090		/* read-only				*/
-
-/*
- * TV registers
- */
-#define TV_VBLANK_EVEN_START	0xbe43c
-#define TV_VBLANK_EVEN_END	0xbe440
-#define TV_VBLANK_ODD_START	0xbe444
-#define TV_VBLANK_ODD_END	0xbe448
-#define TV_SYNC_YGAIN		0xbe44c
-#define TV_UV_GAIN		0xbe450
-#define TV_PED_UVDET		0xbe454
-#define TV_UV_BURST_AMP		0xbe458
-#define TV_HSYNC_START		0xbe45c
-#define TV_HSYNC_END		0xbe460
-#define TV_Y_DELAY1		0xbe464
-#define TV_Y_DELAY2		0xbe468
-#define TV_UV_DELAY1		0xbe46c
-#define TV_BURST_START		0xbe470
-#define TV_BURST_END		0xbe474
-#define TV_HBLANK_START		0xbe478
-#define TV_HBLANK_END		0xbe47c
-#define TV_PED_EVEN_START	0xbe480
-#define TV_PED_EVEN_END		0xbe484
-#define TV_PED_ODD_START	0xbe488
-#define TV_PED_ODD_END		0xbe48c
-#define TV_VSYNC_EVEN_START	0xbe490
-#define TV_VSYNC_EVEN_END	0xbe494
-#define TV_VSYNC_ODD_START	0xbe498
-#define TV_VSYNC_ODD_END	0xbe49c
-#define TV_SCFL			0xbe4a0
-#define TV_SCFH			0xbe4a4
-#define TV_SCP			0xbe4a8
-#define TV_DELAYBYPASS		0xbe4b4
-#define TV_EQL_END		0xbe4bc
-#define TV_SERR_START		0xbe4c0
-#define TV_SERR_END		0xbe4c4
-#define TV_CTL			0xbe4dc	/* reflects a previous register- MVFCLR, MVPCLR etc P241*/
-#define TV_VSYNC_VGA_HS		0xbe4e8
-#define TV_FLICK_XMIN		0xbe514
-#define TV_FLICK_XMAX		0xbe518
-#define TV_FLICK_YMIN		0xbe51c
-#define TV_FLICK_YMAX		0xbe520
-
-/*
- * Graphics Co-processor
- */
-#define CO_REG_CONTROL		0xbf011
-#define CO_CTRL_BUSY			0x80
-#define CO_CTRL_CMDFULL			0x04
-#define CO_CTRL_FIFOEMPTY		0x02
-#define CO_CTRL_READY			0x01
-
-#define CO_REG_SRC_WIDTH	0xbf018
-#define CO_REG_PIXFMT		0xbf01c
-#define CO_PIXFMT_32BPP			0x03
-#define CO_PIXFMT_24BPP			0x02
-#define CO_PIXFMT_16BPP			0x01
-#define CO_PIXFMT_8BPP			0x00
-
-#define CO_REG_FGMIX		0xbf048
-#define CO_FG_MIX_ZERO			0x00
-#define CO_FG_MIX_SRC_AND_DST		0x01
-#define CO_FG_MIX_SRC_AND_NDST		0x02
-#define CO_FG_MIX_SRC			0x03
-#define CO_FG_MIX_NSRC_AND_DST		0x04
-#define CO_FG_MIX_DST			0x05
-#define CO_FG_MIX_SRC_XOR_DST		0x06
-#define CO_FG_MIX_SRC_OR_DST		0x07
-#define CO_FG_MIX_NSRC_AND_NDST		0x08
-#define CO_FG_MIX_SRC_XOR_NDST		0x09
-#define CO_FG_MIX_NDST			0x0a
-#define CO_FG_MIX_SRC_OR_NDST		0x0b
-#define CO_FG_MIX_NSRC			0x0c
-#define CO_FG_MIX_NSRC_OR_DST		0x0d
-#define CO_FG_MIX_NSRC_OR_NDST		0x0e
-#define CO_FG_MIX_ONES			0x0f
-
-#define CO_REG_FGCOLOUR		0xbf058
-#define CO_REG_BGCOLOUR		0xbf05c
-#define CO_REG_PIXWIDTH		0xbf060
-#define CO_REG_PIXHEIGHT	0xbf062
-#define CO_REG_X_PHASE		0xbf078
-#define CO_REG_CMD_L		0xbf07c
-#define CO_CMD_L_PATTERN_FGCOL		0x8000
-#define CO_CMD_L_INC_LEFT		0x0004
-#define CO_CMD_L_INC_UP			0x0002
-
-#define CO_REG_CMD_H		0xbf07e
-#define CO_CMD_H_BGSRCMAP		0x8000	/* otherwise bg colour */
-#define CO_CMD_H_FGSRCMAP		0x2000	/* otherwise fg colour */
-#define CO_CMD_H_BLITTER		0x0800
-
-#define CO_REG_SRC1_PTR		0xbf170
-#define CO_REG_SRC2_PTR		0xbf174
-#define CO_REG_DEST_PTR		0xbf178
-#define CO_REG_DEST_WIDTH	0xbf218
-
-/*
- * Private structure
- */
-struct cfb_info;
-
-struct cyberpro_info {
-	struct device	*dev;
-	struct i2c_adapter *i2c;
-	unsigned char	__iomem *regs;
-	char		__iomem *fb;
-	char		dev_name[32];
-	unsigned int	fb_size;
-	unsigned int	chip_id;
-	unsigned int	irq;
-
-	/*
-	 * The following is a pointer to be passed into the
-	 * functions below.  The modules outside the main
-	 * cyber2000fb.c driver have no knowledge as to what
-	 * is within this structure.
-	 */
-	struct cfb_info *info;
-};
-
-#define ID_IGA_1682		0
-#define ID_CYBERPRO_2000	1
-#define ID_CYBERPRO_2010	2
-#define ID_CYBERPRO_5000	3
-
-/*
- * Note! Writing to the Cyber20x0 registers from an interrupt
- * routine is definitely a bad idea atm.
- */
-int cyber2000fb_attach(struct cyberpro_info *info, int idx);
-void cyber2000fb_detach(int idx);
-void cyber2000fb_enable_extregs(struct cfb_info *cfb);
-void cyber2000fb_disable_extregs(struct cfb_info *cfb);
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
deleted file mode 100644
index 0c0ba920ea48..000000000000
--- a/drivers/video/da8xx-fb.c
+++ /dev/null
@@ -1,1667 +0,0 @@
-/*
- * Copyright (C) 2008-2009 MontaVista Software Inc.
- * Copyright (C) 2008-2009 Texas Instruments Inc
- *
- * Based on the LCD driver for TI Avalanche processors written by
- * Ajay Singh and Shalom Hai.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option)any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/dma-mapping.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/pm_runtime.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/console.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/lcm.h>
-#include <video/da8xx-fb.h>
-#include <asm/div64.h>
-
-#define DRIVER_NAME "da8xx_lcdc"
-
-#define LCD_VERSION_1	1
-#define LCD_VERSION_2	2
-
-/* LCD Status Register */
-#define LCD_END_OF_FRAME1		BIT(9)
-#define LCD_END_OF_FRAME0		BIT(8)
-#define LCD_PL_LOAD_DONE		BIT(6)
-#define LCD_FIFO_UNDERFLOW		BIT(5)
-#define LCD_SYNC_LOST			BIT(2)
-#define LCD_FRAME_DONE			BIT(0)
-
-/* LCD DMA Control Register */
-#define LCD_DMA_BURST_SIZE(x)		((x) << 4)
-#define LCD_DMA_BURST_1			0x0
-#define LCD_DMA_BURST_2			0x1
-#define LCD_DMA_BURST_4			0x2
-#define LCD_DMA_BURST_8			0x3
-#define LCD_DMA_BURST_16		0x4
-#define LCD_V1_END_OF_FRAME_INT_ENA	BIT(2)
-#define LCD_V2_END_OF_FRAME0_INT_ENA	BIT(8)
-#define LCD_V2_END_OF_FRAME1_INT_ENA	BIT(9)
-#define LCD_DUAL_FRAME_BUFFER_ENABLE	BIT(0)
-
-/* LCD Control Register */
-#define LCD_CLK_DIVISOR(x)		((x) << 8)
-#define LCD_RASTER_MODE			0x01
-
-/* LCD Raster Control Register */
-#define LCD_PALETTE_LOAD_MODE(x)	((x) << 20)
-#define PALETTE_AND_DATA		0x00
-#define PALETTE_ONLY			0x01
-#define DATA_ONLY			0x02
-
-#define LCD_MONO_8BIT_MODE		BIT(9)
-#define LCD_RASTER_ORDER		BIT(8)
-#define LCD_TFT_MODE			BIT(7)
-#define LCD_V1_UNDERFLOW_INT_ENA	BIT(6)
-#define LCD_V2_UNDERFLOW_INT_ENA	BIT(5)
-#define LCD_V1_PL_INT_ENA		BIT(4)
-#define LCD_V2_PL_INT_ENA		BIT(6)
-#define LCD_MONOCHROME_MODE		BIT(1)
-#define LCD_RASTER_ENABLE		BIT(0)
-#define LCD_TFT_ALT_ENABLE		BIT(23)
-#define LCD_STN_565_ENABLE		BIT(24)
-#define LCD_V2_DMA_CLK_EN		BIT(2)
-#define LCD_V2_LIDD_CLK_EN		BIT(1)
-#define LCD_V2_CORE_CLK_EN		BIT(0)
-#define LCD_V2_LPP_B10			26
-#define LCD_V2_TFT_24BPP_MODE		BIT(25)
-#define LCD_V2_TFT_24BPP_UNPACK		BIT(26)
-
-/* LCD Raster Timing 2 Register */
-#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)	((x) << 16)
-#define LCD_AC_BIAS_FREQUENCY(x)		((x) << 8)
-#define LCD_SYNC_CTRL				BIT(25)
-#define LCD_SYNC_EDGE				BIT(24)
-#define LCD_INVERT_PIXEL_CLOCK			BIT(22)
-#define LCD_INVERT_LINE_CLOCK			BIT(21)
-#define LCD_INVERT_FRAME_CLOCK			BIT(20)
-
-/* LCD Block */
-#define  LCD_PID_REG				0x0
-#define  LCD_CTRL_REG				0x4
-#define  LCD_STAT_REG				0x8
-#define  LCD_RASTER_CTRL_REG			0x28
-#define  LCD_RASTER_TIMING_0_REG		0x2C
-#define  LCD_RASTER_TIMING_1_REG		0x30
-#define  LCD_RASTER_TIMING_2_REG		0x34
-#define  LCD_DMA_CTRL_REG			0x40
-#define  LCD_DMA_FRM_BUF_BASE_ADDR_0_REG	0x44
-#define  LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG	0x48
-#define  LCD_DMA_FRM_BUF_BASE_ADDR_1_REG	0x4C
-#define  LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG	0x50
-
-/* Interrupt Registers available only in Version 2 */
-#define  LCD_RAW_STAT_REG			0x58
-#define  LCD_MASKED_STAT_REG			0x5c
-#define  LCD_INT_ENABLE_SET_REG			0x60
-#define  LCD_INT_ENABLE_CLR_REG			0x64
-#define  LCD_END_OF_INT_IND_REG			0x68
-
-/* Clock registers available only on Version 2 */
-#define  LCD_CLK_ENABLE_REG			0x6c
-#define  LCD_CLK_RESET_REG			0x70
-#define  LCD_CLK_MAIN_RESET			BIT(3)
-
-#define LCD_NUM_BUFFERS	2
-
-#define PALETTE_SIZE	256
-
-#define	CLK_MIN_DIV	2
-#define	CLK_MAX_DIV	255
-
-static void __iomem *da8xx_fb_reg_base;
-static unsigned int lcd_revision;
-static irq_handler_t lcdc_irq_handler;
-static wait_queue_head_t frame_done_wq;
-static int frame_done_flag;
-
-static unsigned int lcdc_read(unsigned int addr)
-{
-	return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
-}
-
-static void lcdc_write(unsigned int val, unsigned int addr)
-{
-	__raw_writel(val, da8xx_fb_reg_base + (addr));
-}
-
-struct da8xx_fb_par {
-	struct device		*dev;
-	resource_size_t p_palette_base;
-	unsigned char *v_palette_base;
-	dma_addr_t		vram_phys;
-	unsigned long		vram_size;
-	void			*vram_virt;
-	unsigned int		dma_start;
-	unsigned int		dma_end;
-	struct clk *lcdc_clk;
-	int irq;
-	unsigned int palette_sz;
-	int blank;
-	wait_queue_head_t	vsync_wait;
-	int			vsync_flag;
-	int			vsync_timeout;
-	spinlock_t		lock_for_chan_update;
-
-	/*
-	 * LCDC has 2 ping pong DMA channels, channel 0
-	 * and channel 1.
-	 */
-	unsigned int		which_dma_channel_done;
-#ifdef CONFIG_CPU_FREQ
-	struct notifier_block	freq_transition;
-#endif
-	unsigned int		lcdc_clk_rate;
-	void (*panel_power_ctrl)(int);
-	u32 pseudo_palette[16];
-	struct fb_videomode	mode;
-	struct lcd_ctrl_config	cfg;
-};
-
-static struct fb_var_screeninfo da8xx_fb_var;
-
-static struct fb_fix_screeninfo da8xx_fb_fix = {
-	.id = "DA8xx FB Drv",
-	.type = FB_TYPE_PACKED_PIXELS,
-	.type_aux = 0,
-	.visual = FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep = 0,
-	.ypanstep = 1,
-	.ywrapstep = 0,
-	.accel = FB_ACCEL_NONE
-};
-
-static struct fb_videomode known_lcd_panels[] = {
-	/* Sharp LCD035Q3DG01 */
-	[0] = {
-		.name           = "Sharp_LCD035Q3DG01",
-		.xres           = 320,
-		.yres           = 240,
-		.pixclock       = KHZ2PICOS(4607),
-		.left_margin    = 6,
-		.right_margin   = 8,
-		.upper_margin   = 2,
-		.lower_margin   = 2,
-		.hsync_len      = 0,
-		.vsync_len      = 0,
-		.sync           = FB_SYNC_CLK_INVERT |
-			FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	},
-	/* Sharp LK043T1DG01 */
-	[1] = {
-		.name           = "Sharp_LK043T1DG01",
-		.xres           = 480,
-		.yres           = 272,
-		.pixclock       = KHZ2PICOS(7833),
-		.left_margin    = 2,
-		.right_margin   = 2,
-		.upper_margin   = 2,
-		.lower_margin   = 2,
-		.hsync_len      = 41,
-		.vsync_len      = 10,
-		.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.flag           = 0,
-	},
-	[2] = {
-		/* Hitachi SP10Q010 */
-		.name           = "SP10Q010",
-		.xres           = 320,
-		.yres           = 240,
-		.pixclock       = KHZ2PICOS(7833),
-		.left_margin    = 10,
-		.right_margin   = 10,
-		.upper_margin   = 10,
-		.lower_margin   = 10,
-		.hsync_len      = 10,
-		.vsync_len      = 10,
-		.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.flag           = 0,
-	},
-};
-
-static bool da8xx_fb_is_raster_enabled(void)
-{
-	return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE);
-}
-
-/* Enable the Raster Engine of the LCD Controller */
-static void lcd_enable_raster(void)
-{
-	u32 reg;
-
-	/* Put LCDC in reset for several cycles */
-	if (lcd_revision == LCD_VERSION_2)
-		/* Write 1 to reset LCDC */
-		lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
-	mdelay(1);
-
-	/* Bring LCDC out of reset */
-	if (lcd_revision == LCD_VERSION_2)
-		lcdc_write(0, LCD_CLK_RESET_REG);
-	mdelay(1);
-
-	/* Above reset sequence doesnot reset register context */
-	reg = lcdc_read(LCD_RASTER_CTRL_REG);
-	if (!(reg & LCD_RASTER_ENABLE))
-		lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
-}
-
-/* Disable the Raster Engine of the LCD Controller */
-static void lcd_disable_raster(enum da8xx_frame_complete wait_for_frame_done)
-{
-	u32 reg;
-	int ret;
-
-	reg = lcdc_read(LCD_RASTER_CTRL_REG);
-	if (reg & LCD_RASTER_ENABLE)
-		lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
-	else
-		/* return if already disabled */
-		return;
-
-	if ((wait_for_frame_done == DA8XX_FRAME_WAIT) &&
-			(lcd_revision == LCD_VERSION_2)) {
-		frame_done_flag = 0;
-		ret = wait_event_interruptible_timeout(frame_done_wq,
-				frame_done_flag != 0,
-				msecs_to_jiffies(50));
-		if (ret == 0)
-			pr_err("LCD Controller timed out\n");
-	}
-}
-
-static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
-{
-	u32 start;
-	u32 end;
-	u32 reg_ras;
-	u32 reg_dma;
-	u32 reg_int;
-
-	/* init reg to clear PLM (loading mode) fields */
-	reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
-	reg_ras &= ~(3 << 20);
-
-	reg_dma  = lcdc_read(LCD_DMA_CTRL_REG);
-
-	if (load_mode == LOAD_DATA) {
-		start    = par->dma_start;
-		end      = par->dma_end;
-
-		reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
-		if (lcd_revision == LCD_VERSION_1) {
-			reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
-		} else {
-			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
-				LCD_V2_END_OF_FRAME0_INT_ENA |
-				LCD_V2_END_OF_FRAME1_INT_ENA |
-				LCD_FRAME_DONE | LCD_SYNC_LOST;
-			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
-		}
-		reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
-
-		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-		lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
-		lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
-	} else if (load_mode == LOAD_PALETTE) {
-		start    = par->p_palette_base;
-		end      = start + par->palette_sz - 1;
-
-		reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
-
-		if (lcd_revision == LCD_VERSION_1) {
-			reg_ras |= LCD_V1_PL_INT_ENA;
-		} else {
-			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
-				LCD_V2_PL_INT_ENA;
-			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
-		}
-
-		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-		lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-	}
-
-	lcdc_write(reg_dma, LCD_DMA_CTRL_REG);
-	lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
-
-	/*
-	 * The Raster enable bit must be set after all other control fields are
-	 * set.
-	 */
-	lcd_enable_raster();
-}
-
-/* Configure the Burst Size and fifo threhold of DMA */
-static int lcd_cfg_dma(int burst_size, int fifo_th)
-{
-	u32 reg;
-
-	reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001;
-	switch (burst_size) {
-	case 1:
-		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1);
-		break;
-	case 2:
-		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2);
-		break;
-	case 4:
-		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4);
-		break;
-	case 8:
-		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
-		break;
-	case 16:
-	default:
-		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
-		break;
-	}
-
-	reg |= (fifo_th << 8);
-
-	lcdc_write(reg, LCD_DMA_CTRL_REG);
-
-	return 0;
-}
-
-static void lcd_cfg_ac_bias(int period, int transitions_per_int)
-{
-	u32 reg;
-
-	/* Set the AC Bias Period and Number of Transisitons per Interrupt */
-	reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000;
-	reg |= LCD_AC_BIAS_FREQUENCY(period) |
-		LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int);
-	lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
-}
-
-static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
-		int front_porch)
-{
-	u32 reg;
-
-	reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf;
-	reg |= (((back_porch-1) & 0xff) << 24)
-	    | (((front_porch-1) & 0xff) << 16)
-	    | (((pulse_width-1) & 0x3f) << 10);
-	lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
-
-	/*
-	 * LCDC Version 2 adds some extra bits that increase the allowable
-	 * size of the horizontal timing registers.
-	 * remember that the registers use 0 to represent 1 so all values
-	 * that get set into register need to be decremented by 1
-	 */
-	if (lcd_revision == LCD_VERSION_2) {
-		/* Mask off the bits we want to change */
-		reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & ~0x780000ff;
-		reg |= ((front_porch-1) & 0x300) >> 8;
-		reg |= ((back_porch-1) & 0x300) >> 4;
-		reg |= ((pulse_width-1) & 0x3c0) << 21;
-		lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
-	}
-}
-
-static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
-		int front_porch)
-{
-	u32 reg;
-
-	reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff;
-	reg |= ((back_porch & 0xff) << 24)
-	    | ((front_porch & 0xff) << 16)
-	    | (((pulse_width-1) & 0x3f) << 10);
-	lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
-}
-
-static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
-		struct fb_videomode *panel)
-{
-	u32 reg;
-	u32 reg_int;
-
-	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
-						LCD_MONO_8BIT_MODE |
-						LCD_MONOCHROME_MODE);
-
-	switch (cfg->panel_shade) {
-	case MONOCHROME:
-		reg |= LCD_MONOCHROME_MODE;
-		if (cfg->mono_8bit_mode)
-			reg |= LCD_MONO_8BIT_MODE;
-		break;
-	case COLOR_ACTIVE:
-		reg |= LCD_TFT_MODE;
-		if (cfg->tft_alt_mode)
-			reg |= LCD_TFT_ALT_ENABLE;
-		break;
-
-	case COLOR_PASSIVE:
-		/* AC bias applicable only for Pasive panels */
-		lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
-		if (cfg->bpp == 12 && cfg->stn_565_mode)
-			reg |= LCD_STN_565_ENABLE;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* enable additional interrupts here */
-	if (lcd_revision == LCD_VERSION_1) {
-		reg |= LCD_V1_UNDERFLOW_INT_ENA;
-	} else {
-		reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
-			LCD_V2_UNDERFLOW_INT_ENA;
-		lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
-	}
-
-	lcdc_write(reg, LCD_RASTER_CTRL_REG);
-
-	reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
-
-	reg |= LCD_SYNC_CTRL;
-
-	if (cfg->sync_edge)
-		reg |= LCD_SYNC_EDGE;
-	else
-		reg &= ~LCD_SYNC_EDGE;
-
-	if ((panel->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
-		reg |= LCD_INVERT_LINE_CLOCK;
-	else
-		reg &= ~LCD_INVERT_LINE_CLOCK;
-
-	if ((panel->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
-		reg |= LCD_INVERT_FRAME_CLOCK;
-	else
-		reg &= ~LCD_INVERT_FRAME_CLOCK;
-
-	lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
-
-	return 0;
-}
-
-static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
-		u32 bpp, u32 raster_order)
-{
-	u32 reg;
-
-	if (bpp > 16 && lcd_revision == LCD_VERSION_1)
-		return -EINVAL;
-
-	/* Set the Panel Width */
-	/* Pixels per line = (PPL + 1)*16 */
-	if (lcd_revision == LCD_VERSION_1) {
-		/*
-		 * 0x3F in bits 4..9 gives max horizontal resolution = 1024
-		 * pixels.
-		 */
-		width &= 0x3f0;
-	} else {
-		/*
-		 * 0x7F in bits 4..10 gives max horizontal resolution = 2048
-		 * pixels.
-		 */
-		width &= 0x7f0;
-	}
-
-	reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
-	reg &= 0xfffffc00;
-	if (lcd_revision == LCD_VERSION_1) {
-		reg |= ((width >> 4) - 1) << 4;
-	} else {
-		width = (width >> 4) - 1;
-		reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3);
-	}
-	lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
-
-	/* Set the Panel Height */
-	/* Set bits 9:0 of Lines Per Pixel */
-	reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
-	reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
-	lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
-
-	/* Set bit 10 of Lines Per Pixel */
-	if (lcd_revision == LCD_VERSION_2) {
-		reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
-		reg |= ((height - 1) & 0x400) << 16;
-		lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
-	}
-
-	/* Set the Raster Order of the Frame Buffer */
-	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
-	if (raster_order)
-		reg |= LCD_RASTER_ORDER;
-
-	par->palette_sz = 16 * 2;
-
-	switch (bpp) {
-	case 1:
-	case 2:
-	case 4:
-	case 16:
-		break;
-	case 24:
-		reg |= LCD_V2_TFT_24BPP_MODE;
-		break;
-	case 32:
-		reg |= LCD_V2_TFT_24BPP_MODE;
-		reg |= LCD_V2_TFT_24BPP_UNPACK;
-		break;
-	case 8:
-		par->palette_sz = 256 * 2;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	lcdc_write(reg, LCD_RASTER_CTRL_REG);
-
-	return 0;
-}
-
-#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
-static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			      unsigned blue, unsigned transp,
-			      struct fb_info *info)
-{
-	struct da8xx_fb_par *par = info->par;
-	unsigned short *palette = (unsigned short *) par->v_palette_base;
-	u_short pal;
-	int update_hw = 0;
-
-	if (regno > 255)
-		return 1;
-
-	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
-		return 1;
-
-	if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
-		return -EINVAL;
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		red = CNVT_TOHW(red, info->var.red.length);
-		green = CNVT_TOHW(green, info->var.green.length);
-		blue = CNVT_TOHW(blue, info->var.blue.length);
-		break;
-	case FB_VISUAL_PSEUDOCOLOR:
-		switch (info->var.bits_per_pixel) {
-		case 4:
-			if (regno > 15)
-				return -EINVAL;
-
-			if (info->var.grayscale) {
-				pal = regno;
-			} else {
-				red >>= 4;
-				green >>= 8;
-				blue >>= 12;
-
-				pal = red & 0x0f00;
-				pal |= green & 0x00f0;
-				pal |= blue & 0x000f;
-			}
-			if (regno == 0)
-				pal |= 0x2000;
-			palette[regno] = pal;
-			break;
-
-		case 8:
-			red >>= 4;
-			green >>= 8;
-			blue >>= 12;
-
-			pal = (red & 0x0f00);
-			pal |= (green & 0x00f0);
-			pal |= (blue & 0x000f);
-
-			if (palette[regno] != pal) {
-				update_hw = 1;
-				palette[regno] = pal;
-			}
-			break;
-		}
-		break;
-	}
-
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 v;
-
-		if (regno > 15)
-			return -EINVAL;
-
-		v = (red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset);
-
-		switch (info->var.bits_per_pixel) {
-		case 16:
-			((u16 *) (info->pseudo_palette))[regno] = v;
-			break;
-		case 24:
-		case 32:
-			((u32 *) (info->pseudo_palette))[regno] = v;
-			break;
-		}
-		if (palette[0] != 0x4000) {
-			update_hw = 1;
-			palette[0] = 0x4000;
-		}
-	}
-
-	/* Update the palette in the h/w as needed. */
-	if (update_hw)
-		lcd_blit(LOAD_PALETTE, par);
-
-	return 0;
-}
-#undef CNVT_TOHW
-
-static void da8xx_fb_lcd_reset(void)
-{
-	/* DMA has to be disabled */
-	lcdc_write(0, LCD_DMA_CTRL_REG);
-	lcdc_write(0, LCD_RASTER_CTRL_REG);
-
-	if (lcd_revision == LCD_VERSION_2) {
-		lcdc_write(0, LCD_INT_ENABLE_SET_REG);
-		/* Write 1 to reset */
-		lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
-		lcdc_write(0, LCD_CLK_RESET_REG);
-	}
-}
-
-static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par,
-					      unsigned lcdc_clk_div,
-					      unsigned lcdc_clk_rate)
-{
-	int ret;
-
-	if (par->lcdc_clk_rate != lcdc_clk_rate) {
-		ret = clk_set_rate(par->lcdc_clk, lcdc_clk_rate);
-		if (IS_ERR_VALUE(ret)) {
-			dev_err(par->dev,
-				"unable to set clock rate at %u\n",
-				lcdc_clk_rate);
-			return ret;
-		}
-		par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
-	}
-
-	/* Configure the LCD clock divisor. */
-	lcdc_write(LCD_CLK_DIVISOR(lcdc_clk_div) |
-			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
-
-	if (lcd_revision == LCD_VERSION_2)
-		lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
-				LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
-
-	return 0;
-}
-
-static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
-					      unsigned pixclock,
-					      unsigned *lcdc_clk_rate)
-{
-	unsigned lcdc_clk_div;
-
-	pixclock = PICOS2KHZ(pixclock) * 1000;
-
-	*lcdc_clk_rate = par->lcdc_clk_rate;
-
-	if (pixclock < (*lcdc_clk_rate / CLK_MAX_DIV)) {
-		*lcdc_clk_rate = clk_round_rate(par->lcdc_clk,
-						pixclock * CLK_MAX_DIV);
-		lcdc_clk_div = CLK_MAX_DIV;
-	} else if (pixclock > (*lcdc_clk_rate / CLK_MIN_DIV)) {
-		*lcdc_clk_rate = clk_round_rate(par->lcdc_clk,
-						pixclock * CLK_MIN_DIV);
-		lcdc_clk_div = CLK_MIN_DIV;
-	} else {
-		lcdc_clk_div = *lcdc_clk_rate / pixclock;
-	}
-
-	return lcdc_clk_div;
-}
-
-static int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
-					    struct fb_videomode *mode)
-{
-	unsigned lcdc_clk_rate;
-	unsigned lcdc_clk_div = da8xx_fb_calc_clk_divider(par, mode->pixclock,
-							  &lcdc_clk_rate);
-
-	return da8xx_fb_config_clk_divider(par, lcdc_clk_div, lcdc_clk_rate);
-}
-
-static unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
-					  unsigned pixclock)
-{
-	unsigned lcdc_clk_div, lcdc_clk_rate;
-
-	lcdc_clk_div = da8xx_fb_calc_clk_divider(par, pixclock, &lcdc_clk_rate);
-	return KHZ2PICOS(lcdc_clk_rate / (1000 * lcdc_clk_div));
-}
-
-static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
-		struct fb_videomode *panel)
-{
-	u32 bpp;
-	int ret = 0;
-
-	ret = da8xx_fb_calc_config_clk_divider(par, panel);
-	if (IS_ERR_VALUE(ret)) {
-		dev_err(par->dev, "unable to configure clock\n");
-		return ret;
-	}
-
-	if (panel->sync & FB_SYNC_CLK_INVERT)
-		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
-			LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
-	else
-		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
-			~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
-
-	/* Configure the DMA burst size and fifo threshold. */
-	ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th);
-	if (ret < 0)
-		return ret;
-
-	/* Configure the vertical and horizontal sync properties. */
-	lcd_cfg_vertical_sync(panel->upper_margin, panel->vsync_len,
-			panel->lower_margin);
-	lcd_cfg_horizontal_sync(panel->left_margin, panel->hsync_len,
-			panel->right_margin);
-
-	/* Configure for disply */
-	ret = lcd_cfg_display(cfg, panel);
-	if (ret < 0)
-		return ret;
-
-	bpp = cfg->bpp;
-
-	if (bpp == 12)
-		bpp = 16;
-	ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
-				(unsigned int)panel->yres, bpp,
-				cfg->raster_order);
-	if (ret < 0)
-		return ret;
-
-	/* Configure FDD */
-	lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) |
-		       (cfg->fdd << 12), LCD_RASTER_CTRL_REG);
-
-	return 0;
-}
-
-/* IRQ handler for version 2 of LCDC */
-static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
-{
-	struct da8xx_fb_par *par = arg;
-	u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
-
-	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
-		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
-		lcdc_write(stat, LCD_MASKED_STAT_REG);
-		lcd_enable_raster();
-	} else if (stat & LCD_PL_LOAD_DONE) {
-		/*
-		 * Must disable raster before changing state of any control bit.
-		 * And also must be disabled before clearing the PL loading
-		 * interrupt via the following write to the status register. If
-		 * this is done after then one gets multiple PL done interrupts.
-		 */
-		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
-
-		lcdc_write(stat, LCD_MASKED_STAT_REG);
-
-		/* Disable PL completion interrupt */
-		lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG);
-
-		/* Setup and start data loading mode */
-		lcd_blit(LOAD_DATA, par);
-	} else {
-		lcdc_write(stat, LCD_MASKED_STAT_REG);
-
-		if (stat & LCD_END_OF_FRAME0) {
-			par->which_dma_channel_done = 0;
-			lcdc_write(par->dma_start,
-				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-			lcdc_write(par->dma_end,
-				   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-			par->vsync_flag = 1;
-			wake_up_interruptible(&par->vsync_wait);
-		}
-
-		if (stat & LCD_END_OF_FRAME1) {
-			par->which_dma_channel_done = 1;
-			lcdc_write(par->dma_start,
-				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
-			lcdc_write(par->dma_end,
-				   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
-			par->vsync_flag = 1;
-			wake_up_interruptible(&par->vsync_wait);
-		}
-
-		/* Set only when controller is disabled and at the end of
-		 * active frame
-		 */
-		if (stat & BIT(0)) {
-			frame_done_flag = 1;
-			wake_up_interruptible(&frame_done_wq);
-		}
-	}
-
-	lcdc_write(0, LCD_END_OF_INT_IND_REG);
-	return IRQ_HANDLED;
-}
-
-/* IRQ handler for version 1 LCDC */
-static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
-{
-	struct da8xx_fb_par *par = arg;
-	u32 stat = lcdc_read(LCD_STAT_REG);
-	u32 reg_ras;
-
-	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
-		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
-		lcdc_write(stat, LCD_STAT_REG);
-		lcd_enable_raster();
-	} else if (stat & LCD_PL_LOAD_DONE) {
-		/*
-		 * Must disable raster before changing state of any control bit.
-		 * And also must be disabled before clearing the PL loading
-		 * interrupt via the following write to the status register. If
-		 * this is done after then one gets multiple PL done interrupts.
-		 */
-		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
-
-		lcdc_write(stat, LCD_STAT_REG);
-
-		/* Disable PL completion inerrupt */
-		reg_ras  = lcdc_read(LCD_RASTER_CTRL_REG);
-		reg_ras &= ~LCD_V1_PL_INT_ENA;
-		lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
-
-		/* Setup and start data loading mode */
-		lcd_blit(LOAD_DATA, par);
-	} else {
-		lcdc_write(stat, LCD_STAT_REG);
-
-		if (stat & LCD_END_OF_FRAME0) {
-			par->which_dma_channel_done = 0;
-			lcdc_write(par->dma_start,
-				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-			lcdc_write(par->dma_end,
-				   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-			par->vsync_flag = 1;
-			wake_up_interruptible(&par->vsync_wait);
-		}
-
-		if (stat & LCD_END_OF_FRAME1) {
-			par->which_dma_channel_done = 1;
-			lcdc_write(par->dma_start,
-				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
-			lcdc_write(par->dma_end,
-				   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
-			par->vsync_flag = 1;
-			wake_up_interruptible(&par->vsync_wait);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int fb_check_var(struct fb_var_screeninfo *var,
-			struct fb_info *info)
-{
-	int err = 0;
-	struct da8xx_fb_par *par = info->par;
-	int bpp = var->bits_per_pixel >> 3;
-	unsigned long line_size = var->xres_virtual * bpp;
-
-	if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
-		return -EINVAL;
-
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->nonstd = 0;
-		break;
-	case 4:
-		var->red.offset = 0;
-		var->red.length = 4;
-		var->green.offset = 0;
-		var->green.length = 4;
-		var->blue.offset = 0;
-		var->blue.length = 4;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->nonstd = FB_NONSTD_REV_PIX_IN_B;
-		break;
-	case 16:		/* RGB 565 */
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->nonstd = 0;
-		break;
-	case 24:
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->nonstd = 0;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->nonstd = 0;
-		break;
-	default:
-		err = -EINVAL;
-	}
-
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	if (line_size * var->yres_virtual > par->vram_size)
-		var->yres_virtual = par->vram_size / line_size;
-
-	if (var->yres > var->yres_virtual)
-		var->yres = var->yres_virtual;
-
-	if (var->xres > var->xres_virtual)
-		var->xres = var->xres_virtual;
-
-	if (var->xres + var->xoffset > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yres + var->yoffset > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	var->pixclock = da8xx_fb_round_clk(par, var->pixclock);
-
-	return err;
-}
-
-#ifdef CONFIG_CPU_FREQ
-static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
-				     unsigned long val, void *data)
-{
-	struct da8xx_fb_par *par;
-
-	par = container_of(nb, struct da8xx_fb_par, freq_transition);
-	if (val == CPUFREQ_POSTCHANGE) {
-		if (par->lcdc_clk_rate != clk_get_rate(par->lcdc_clk)) {
-			par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
-			lcd_disable_raster(DA8XX_FRAME_WAIT);
-			da8xx_fb_calc_config_clk_divider(par, &par->mode);
-			if (par->blank == FB_BLANK_UNBLANK)
-				lcd_enable_raster();
-		}
-	}
-
-	return 0;
-}
-
-static int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par)
-{
-	par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition;
-
-	return cpufreq_register_notifier(&par->freq_transition,
-					 CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
-{
-	cpufreq_unregister_notifier(&par->freq_transition,
-				    CPUFREQ_TRANSITION_NOTIFIER);
-}
-#endif
-
-static int fb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = dev_get_drvdata(&dev->dev);
-
-	if (info) {
-		struct da8xx_fb_par *par = info->par;
-
-#ifdef CONFIG_CPU_FREQ
-		lcd_da8xx_cpufreq_deregister(par);
-#endif
-		if (par->panel_power_ctrl)
-			par->panel_power_ctrl(0);
-
-		lcd_disable_raster(DA8XX_FRAME_WAIT);
-		lcdc_write(0, LCD_RASTER_CTRL_REG);
-
-		/* disable DMA  */
-		lcdc_write(0, LCD_DMA_CTRL_REG);
-
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
-				  par->p_palette_base);
-		dma_free_coherent(NULL, par->vram_size, par->vram_virt,
-				  par->vram_phys);
-		pm_runtime_put_sync(&dev->dev);
-		pm_runtime_disable(&dev->dev);
-		framebuffer_release(info);
-
-	}
-	return 0;
-}
-
-/*
- * Function to wait for vertical sync which for this LCD peripheral
- * translates into waiting for the current raster frame to complete.
- */
-static int fb_wait_for_vsync(struct fb_info *info)
-{
-	struct da8xx_fb_par *par = info->par;
-	int ret;
-
-	/*
-	 * Set flag to 0 and wait for isr to set to 1. It would seem there is a
-	 * race condition here where the ISR could have occurred just before or
-	 * just after this set. But since we are just coarsely waiting for
-	 * a frame to complete then that's OK. i.e. if the frame completed
-	 * just before this code executed then we have to wait another full
-	 * frame time but there is no way to avoid such a situation. On the
-	 * other hand if the frame completed just after then we don't need
-	 * to wait long at all. Either way we are guaranteed to return to the
-	 * user immediately after a frame completion which is all that is
-	 * required.
-	 */
-	par->vsync_flag = 0;
-	ret = wait_event_interruptible_timeout(par->vsync_wait,
-					       par->vsync_flag != 0,
-					       par->vsync_timeout);
-	if (ret < 0)
-		return ret;
-	if (ret == 0)
-		return -ETIMEDOUT;
-
-	return 0;
-}
-
-static int fb_ioctl(struct fb_info *info, unsigned int cmd,
-			  unsigned long arg)
-{
-	struct lcd_sync_arg sync_arg;
-
-	switch (cmd) {
-	case FBIOGET_CONTRAST:
-	case FBIOPUT_CONTRAST:
-	case FBIGET_BRIGHTNESS:
-	case FBIPUT_BRIGHTNESS:
-	case FBIGET_COLOR:
-	case FBIPUT_COLOR:
-		return -ENOTTY;
-	case FBIPUT_HSYNC:
-		if (copy_from_user(&sync_arg, (char *)arg,
-				sizeof(struct lcd_sync_arg)))
-			return -EFAULT;
-		lcd_cfg_horizontal_sync(sync_arg.back_porch,
-					sync_arg.pulse_width,
-					sync_arg.front_porch);
-		break;
-	case FBIPUT_VSYNC:
-		if (copy_from_user(&sync_arg, (char *)arg,
-				sizeof(struct lcd_sync_arg)))
-			return -EFAULT;
-		lcd_cfg_vertical_sync(sync_arg.back_porch,
-					sync_arg.pulse_width,
-					sync_arg.front_porch);
-		break;
-	case FBIO_WAITFORVSYNC:
-		return fb_wait_for_vsync(info);
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int cfb_blank(int blank, struct fb_info *info)
-{
-	struct da8xx_fb_par *par = info->par;
-	int ret = 0;
-
-	if (par->blank == blank)
-		return 0;
-
-	par->blank = blank;
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-		lcd_enable_raster();
-
-		if (par->panel_power_ctrl)
-			par->panel_power_ctrl(1);
-		break;
-	case FB_BLANK_NORMAL:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_POWERDOWN:
-		if (par->panel_power_ctrl)
-			par->panel_power_ctrl(0);
-
-		lcd_disable_raster(DA8XX_FRAME_WAIT);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-/*
- * Set new x,y offsets in the virtual display for the visible area and switch
- * to the new mode.
- */
-static int da8xx_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *fbi)
-{
-	int ret = 0;
-	struct fb_var_screeninfo new_var;
-	struct da8xx_fb_par         *par = fbi->par;
-	struct fb_fix_screeninfo    *fix = &fbi->fix;
-	unsigned int end;
-	unsigned int start;
-	unsigned long irq_flags;
-
-	if (var->xoffset != fbi->var.xoffset ||
-			var->yoffset != fbi->var.yoffset) {
-		memcpy(&new_var, &fbi->var, sizeof(new_var));
-		new_var.xoffset = var->xoffset;
-		new_var.yoffset = var->yoffset;
-		if (fb_check_var(&new_var, fbi))
-			ret = -EINVAL;
-		else {
-			memcpy(&fbi->var, &new_var, sizeof(new_var));
-
-			start	= fix->smem_start +
-				new_var.yoffset * fix->line_length +
-				new_var.xoffset * fbi->var.bits_per_pixel / 8;
-			end	= start + fbi->var.yres * fix->line_length - 1;
-			par->dma_start	= start;
-			par->dma_end	= end;
-			spin_lock_irqsave(&par->lock_for_chan_update,
-					irq_flags);
-			if (par->which_dma_channel_done == 0) {
-				lcdc_write(par->dma_start,
-					   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-				lcdc_write(par->dma_end,
-					   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-			} else if (par->which_dma_channel_done == 1) {
-				lcdc_write(par->dma_start,
-					   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
-				lcdc_write(par->dma_end,
-					   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
-			}
-			spin_unlock_irqrestore(&par->lock_for_chan_update,
-					irq_flags);
-		}
-	}
-
-	return ret;
-}
-
-static int da8xxfb_set_par(struct fb_info *info)
-{
-	struct da8xx_fb_par *par = info->par;
-	int ret;
-	bool raster = da8xx_fb_is_raster_enabled();
-
-	if (raster)
-		lcd_disable_raster(DA8XX_FRAME_WAIT);
-
-	fb_var_to_videomode(&par->mode, &info->var);
-
-	par->cfg.bpp = info->var.bits_per_pixel;
-
-	info->fix.visual = (par->cfg.bpp <= 8) ?
-				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8;
-
-	ret = lcd_init(par, &par->cfg, &par->mode);
-	if (ret < 0) {
-		dev_err(par->dev, "lcd init failed\n");
-		return ret;
-	}
-
-	par->dma_start = info->fix.smem_start +
-			 info->var.yoffset * info->fix.line_length +
-			 info->var.xoffset * info->var.bits_per_pixel / 8;
-	par->dma_end   = par->dma_start +
-			 info->var.yres * info->fix.line_length - 1;
-
-	lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-	lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-	lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
-	lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
-
-	if (raster)
-		lcd_enable_raster();
-
-	return 0;
-}
-
-static struct fb_ops da8xx_fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = fb_check_var,
-	.fb_set_par = da8xxfb_set_par,
-	.fb_setcolreg = fb_setcolreg,
-	.fb_pan_display = da8xx_pan_display,
-	.fb_ioctl = fb_ioctl,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_blank = cfb_blank,
-};
-
-static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
-{
-	struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev);
-	struct fb_videomode *lcdc_info;
-	int i;
-
-	for (i = 0, lcdc_info = known_lcd_panels;
-		i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
-		if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(known_lcd_panels)) {
-		dev_err(&dev->dev, "no panel found\n");
-		return NULL;
-	}
-	dev_info(&dev->dev, "found %s panel\n", lcdc_info->name);
-
-	return lcdc_info;
-}
-
-static int fb_probe(struct platform_device *device)
-{
-	struct da8xx_lcdc_platform_data *fb_pdata =
-						dev_get_platdata(&device->dev);
-	static struct resource *lcdc_regs;
-	struct lcd_ctrl_config *lcd_cfg;
-	struct fb_videomode *lcdc_info;
-	struct fb_info *da8xx_fb_info;
-	struct da8xx_fb_par *par;
-	struct clk *tmp_lcdc_clk;
-	int ret;
-	unsigned long ulcm;
-
-	if (fb_pdata == NULL) {
-		dev_err(&device->dev, "Can not get platform data\n");
-		return -ENOENT;
-	}
-
-	lcdc_info = da8xx_fb_get_videomode(device);
-	if (lcdc_info == NULL)
-		return -ENODEV;
-
-	lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
-	da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs);
-	if (IS_ERR(da8xx_fb_reg_base))
-		return PTR_ERR(da8xx_fb_reg_base);
-
-	tmp_lcdc_clk = devm_clk_get(&device->dev, "fck");
-	if (IS_ERR(tmp_lcdc_clk)) {
-		dev_err(&device->dev, "Can not get device clock\n");
-		return PTR_ERR(tmp_lcdc_clk);
-	}
-
-	pm_runtime_enable(&device->dev);
-	pm_runtime_get_sync(&device->dev);
-
-	/* Determine LCD IP Version */
-	switch (lcdc_read(LCD_PID_REG)) {
-	case 0x4C100102:
-		lcd_revision = LCD_VERSION_1;
-		break;
-	case 0x4F200800:
-	case 0x4F201000:
-		lcd_revision = LCD_VERSION_2;
-		break;
-	default:
-		dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
-				"defaulting to LCD revision 1\n",
-				lcdc_read(LCD_PID_REG));
-		lcd_revision = LCD_VERSION_1;
-		break;
-	}
-
-	lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
-
-	if (!lcd_cfg) {
-		ret = -EINVAL;
-		goto err_pm_runtime_disable;
-	}
-
-	da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
-					&device->dev);
-	if (!da8xx_fb_info) {
-		dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");
-		ret = -ENOMEM;
-		goto err_pm_runtime_disable;
-	}
-
-	par = da8xx_fb_info->par;
-	par->dev = &device->dev;
-	par->lcdc_clk = tmp_lcdc_clk;
-	par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
-	if (fb_pdata->panel_power_ctrl) {
-		par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
-		par->panel_power_ctrl(1);
-	}
-
-	fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
-	par->cfg = *lcd_cfg;
-
-	da8xx_fb_lcd_reset();
-
-	/* allocate frame buffer */
-	par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
-	ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
-	par->vram_size = roundup(par->vram_size/8, ulcm);
-	par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
-
-	par->vram_virt = dma_alloc_coherent(NULL,
-					    par->vram_size,
-					    (resource_size_t *) &par->vram_phys,
-					    GFP_KERNEL | GFP_DMA);
-	if (!par->vram_virt) {
-		dev_err(&device->dev,
-			"GLCD: kmalloc for frame buffer failed\n");
-		ret = -EINVAL;
-		goto err_release_fb;
-	}
-
-	da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
-	da8xx_fb_fix.smem_start    = par->vram_phys;
-	da8xx_fb_fix.smem_len      = par->vram_size;
-	da8xx_fb_fix.line_length   = (lcdc_info->xres * lcd_cfg->bpp) / 8;
-
-	par->dma_start = par->vram_phys;
-	par->dma_end   = par->dma_start + lcdc_info->yres *
-		da8xx_fb_fix.line_length - 1;
-
-	/* allocate palette buffer */
-	par->v_palette_base = dma_alloc_coherent(NULL,
-					       PALETTE_SIZE,
-					       (resource_size_t *)
-					       &par->p_palette_base,
-					       GFP_KERNEL | GFP_DMA);
-	if (!par->v_palette_base) {
-		dev_err(&device->dev,
-			"GLCD: kmalloc for palette buffer failed\n");
-		ret = -EINVAL;
-		goto err_release_fb_mem;
-	}
-	memset(par->v_palette_base, 0, PALETTE_SIZE);
-
-	par->irq = platform_get_irq(device, 0);
-	if (par->irq < 0) {
-		ret = -ENOENT;
-		goto err_release_pl_mem;
-	}
-
-	da8xx_fb_var.grayscale =
-	    lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
-	da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
-
-	/* Initialize fbinfo */
-	da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
-	da8xx_fb_info->fix = da8xx_fb_fix;
-	da8xx_fb_info->var = da8xx_fb_var;
-	da8xx_fb_info->fbops = &da8xx_fb_ops;
-	da8xx_fb_info->pseudo_palette = par->pseudo_palette;
-	da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ?
-				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-
-	ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
-	if (ret)
-		goto err_release_pl_mem;
-	da8xx_fb_info->cmap.len = par->palette_sz;
-
-	/* initialize var_screeninfo */
-	da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
-	fb_set_var(da8xx_fb_info, &da8xx_fb_var);
-
-	dev_set_drvdata(&device->dev, da8xx_fb_info);
-
-	/* initialize the vsync wait queue */
-	init_waitqueue_head(&par->vsync_wait);
-	par->vsync_timeout = HZ / 5;
-	par->which_dma_channel_done = -1;
-	spin_lock_init(&par->lock_for_chan_update);
-
-	/* Register the Frame Buffer  */
-	if (register_framebuffer(da8xx_fb_info) < 0) {
-		dev_err(&device->dev,
-			"GLCD: Frame Buffer Registration Failed!\n");
-		ret = -EINVAL;
-		goto err_dealloc_cmap;
-	}
-
-#ifdef CONFIG_CPU_FREQ
-	ret = lcd_da8xx_cpufreq_register(par);
-	if (ret) {
-		dev_err(&device->dev, "failed to register cpufreq\n");
-		goto err_cpu_freq;
-	}
-#endif
-
-	if (lcd_revision == LCD_VERSION_1)
-		lcdc_irq_handler = lcdc_irq_handler_rev01;
-	else {
-		init_waitqueue_head(&frame_done_wq);
-		lcdc_irq_handler = lcdc_irq_handler_rev02;
-	}
-
-	ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
-			       DRIVER_NAME, par);
-	if (ret)
-		goto irq_freq;
-	return 0;
-
-irq_freq:
-#ifdef CONFIG_CPU_FREQ
-	lcd_da8xx_cpufreq_deregister(par);
-err_cpu_freq:
-#endif
-	unregister_framebuffer(da8xx_fb_info);
-
-err_dealloc_cmap:
-	fb_dealloc_cmap(&da8xx_fb_info->cmap);
-
-err_release_pl_mem:
-	dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
-			  par->p_palette_base);
-
-err_release_fb_mem:
-	dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys);
-
-err_release_fb:
-	framebuffer_release(da8xx_fb_info);
-
-err_pm_runtime_disable:
-	pm_runtime_put_sync(&device->dev);
-	pm_runtime_disable(&device->dev);
-
-	return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static struct lcdc_context {
-	u32 clk_enable;
-	u32 ctrl;
-	u32 dma_ctrl;
-	u32 raster_timing_0;
-	u32 raster_timing_1;
-	u32 raster_timing_2;
-	u32 int_enable_set;
-	u32 dma_frm_buf_base_addr_0;
-	u32 dma_frm_buf_ceiling_addr_0;
-	u32 dma_frm_buf_base_addr_1;
-	u32 dma_frm_buf_ceiling_addr_1;
-	u32 raster_ctrl;
-} reg_context;
-
-static void lcd_context_save(void)
-{
-	if (lcd_revision == LCD_VERSION_2) {
-		reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG);
-		reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG);
-	}
-
-	reg_context.ctrl = lcdc_read(LCD_CTRL_REG);
-	reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG);
-	reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG);
-	reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG);
-	reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG);
-	reg_context.dma_frm_buf_base_addr_0 =
-		lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-	reg_context.dma_frm_buf_ceiling_addr_0 =
-		lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-	reg_context.dma_frm_buf_base_addr_1 =
-		lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
-	reg_context.dma_frm_buf_ceiling_addr_1 =
-		lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
-	reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG);
-	return;
-}
-
-static void lcd_context_restore(void)
-{
-	if (lcd_revision == LCD_VERSION_2) {
-		lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG);
-		lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG);
-	}
-
-	lcdc_write(reg_context.ctrl, LCD_CTRL_REG);
-	lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG);
-	lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG);
-	lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG);
-	lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG);
-	lcdc_write(reg_context.dma_frm_buf_base_addr_0,
-			LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
-	lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0,
-			LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
-	lcdc_write(reg_context.dma_frm_buf_base_addr_1,
-			LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
-	lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1,
-			LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
-	lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG);
-	return;
-}
-
-static int fb_suspend(struct device *dev)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct da8xx_fb_par *par = info->par;
-
-	console_lock();
-	if (par->panel_power_ctrl)
-		par->panel_power_ctrl(0);
-
-	fb_set_suspend(info, 1);
-	lcd_disable_raster(DA8XX_FRAME_WAIT);
-	lcd_context_save();
-	pm_runtime_put_sync(dev);
-	console_unlock();
-
-	return 0;
-}
-static int fb_resume(struct device *dev)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct da8xx_fb_par *par = info->par;
-
-	console_lock();
-	pm_runtime_get_sync(dev);
-	lcd_context_restore();
-	if (par->blank == FB_BLANK_UNBLANK) {
-		lcd_enable_raster();
-
-		if (par->panel_power_ctrl)
-			par->panel_power_ctrl(1);
-	}
-
-	fb_set_suspend(info, 0);
-	console_unlock();
-
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(fb_pm_ops, fb_suspend, fb_resume);
-
-static struct platform_driver da8xx_fb_driver = {
-	.probe = fb_probe,
-	.remove = fb_remove,
-	.driver = {
-		   .name = DRIVER_NAME,
-		   .owner = THIS_MODULE,
-		   .pm	= &fb_pm_ops,
-		   },
-};
-module_platform_driver(da8xx_fb_driver);
-
-MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx");
-MODULE_AUTHOR("Texas Instruments");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
deleted file mode 100644
index 3526899da61b..000000000000
--- a/drivers/video/dnfb.c
+++ /dev/null
@@ -1,303 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/apollohw.h>
-#include <linux/fb.h>
-#include <linux/module.h>
-
-/* apollo video HW definitions */
-
-/*
- * Control Registers.   IOBASE + $x
- *
- * Note: these are the Memory/IO BASE definitions for a mono card set to the
- * alternate address
- *
- * Control 3A and 3B serve identical functions except that 3A
- * deals with control 1 and 3b deals with Color LUT reg.
- */
-
-#define AP_IOBASE       0x3b0	/* Base address of 1 plane board. */
-#define AP_STATUS       isaIO2mem(AP_IOBASE+0)	/* Status register.  Read */
-#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0)	/* Write Enable Register Write */
-#define AP_DEVICE_ID    isaIO2mem(AP_IOBASE+1)	/* Device ID Register. Read */
-#define AP_ROP_1        isaIO2mem(AP_IOBASE+2)	/* Raster Operation reg. Write Word */
-#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4)	/* Diagnostic Memory Request. Write Word */
-#define AP_CONTROL_0    isaIO2mem(AP_IOBASE+8)	/* Control Register 0.  Read/Write */
-#define AP_CONTROL_1    isaIO2mem(AP_IOBASE+0xa)	/* Control Register 1.  Read/Write */
-#define AP_CONTROL_3A   isaIO2mem(AP_IOBASE+0xe)	/* Control Register 3a. Read/Write */
-#define AP_CONTROL_2    isaIO2mem(AP_IOBASE+0xc)	/* Control Register 2. Read/Write */
-
-
-#define FRAME_BUFFER_START 0x0FA0000
-#define FRAME_BUFFER_LEN 0x40000
-
-/* CREG 0 */
-#define VECTOR_MODE 0x40	/* 010x.xxxx */
-#define DBLT_MODE   0x80	/* 100x.xxxx */
-#define NORMAL_MODE 0xE0	/* 111x.xxxx */
-#define SHIFT_BITS  0x1F	/* xxx1.1111 */
-	/* other bits are Shift value */
-
-/* CREG 1 */
-#define AD_BLT      0x80	/* 1xxx.xxxx */
-#define NORMAL      0x80 /* 1xxx.xxxx */	/* What is happening here ?? */
-#define INVERSE     0x00 /* 0xxx.xxxx */	/* Clearing this reverses the screen */
-#define PIX_BLT     0x00	/* 0xxx.xxxx */
-
-#define AD_HIBIT        0x40	/* xIxx.xxxx */
-
-#define ROP_EN          0x10	/* xxx1.xxxx */
-#define DST_EQ_SRC      0x00	/* xxx0.xxxx */
-#define nRESET_SYNC     0x08	/* xxxx.1xxx */
-#define SYNC_ENAB       0x02	/* xxxx.xx1x */
-
-#define BLANK_DISP      0x00	/* xxxx.xxx0 */
-#define ENAB_DISP       0x01	/* xxxx.xxx1 */
-
-#define NORM_CREG1      (nRESET_SYNC | SYNC_ENAB | ENAB_DISP)	/* no reset sync */
-
-/* CREG 2 */
-
-/*
- * Following 3 defines are common to 1, 4 and 8 plane.
- */
-
-#define S_DATA_1s   0x00 /* 00xx.xxxx */	/* set source to all 1's -- vector drawing */
-#define S_DATA_PIX  0x40 /* 01xx.xxxx */	/* takes source from ls-bits and replicates over 16 bits */
-#define S_DATA_PLN  0xC0 /* 11xx.xxxx */	/* normal, each data access =16-bits in
-						   one plane of image mem */
-
-/* CREG 3A/CREG 3B */
-#       define RESET_CREG 0x80	/* 1000.0000 */
-
-/* ROP REG  -  all one nibble */
-/*      ********* NOTE : this is used r0,r1,r2,r3 *********** */
-#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
-#define DEST_ZERO               0x0
-#define SRC_AND_DEST    0x1
-#define SRC_AND_nDEST   0x2
-#define SRC                             0x3
-#define nSRC_AND_DEST   0x4
-#define DEST                    0x5
-#define SRC_XOR_DEST    0x6
-#define SRC_OR_DEST             0x7
-#define SRC_NOR_DEST    0x8
-#define SRC_XNOR_DEST   0x9
-#define nDEST                   0xA
-#define SRC_OR_nDEST    0xB
-#define nSRC                    0xC
-#define nSRC_OR_DEST    0xD
-#define SRC_NAND_DEST   0xE
-#define DEST_ONE                0xF
-
-#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
-
-/* frame buffer operations */
-
-static int dnfb_blank(int blank, struct fb_info *info);
-static void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-
-static struct fb_ops dn_fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_blank	= dnfb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= dnfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-struct fb_var_screeninfo dnfb_var = {
-	.xres		= 1280,
-	.yres		= 1024,
-	.xres_virtual	= 2048,
-	.yres_virtual	= 1024,
-	.bits_per_pixel	= 1,
-	.height		= -1,
-	.width		= -1,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo dnfb_fix = {
-	.id		= "Apollo Mono",
-	.smem_start	= (FRAME_BUFFER_START + IO_BASE),
-	.smem_len	= FRAME_BUFFER_LEN,
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_MONO10,
-	.line_length	= 256,
-};
-
-static int dnfb_blank(int blank, struct fb_info *info)
-{
-	if (blank)
-		out_8(AP_CONTROL_3A, 0x0);
-	else
-		out_8(AP_CONTROL_3A, 0x1);
-	return 0;
-}
-
-static
-void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-
-	int incr, y_delta, pre_read = 0, x_end, x_word_count;
-	uint start_mask, end_mask, dest;
-	ushort *src, dummy;
-	short i, j;
-
-	incr = (area->dy <= area->sy) ? 1 : -1;
-
-	src = (ushort *)(info->screen_base + area->sy * info->fix.line_length +
-			(area->sx >> 4));
-	dest = area->dy * (info->fix.line_length >> 1) + (area->dx >> 4);
-
-	if (incr > 0) {
-		y_delta = (info->fix.line_length * 8) - area->sx - area->width;
-		x_end = area->dx + area->width - 1;
-		x_word_count = (x_end >> 4) - (area->dx >> 4) + 1;
-		start_mask = 0xffff0000 >> (area->dx & 0xf);
-		end_mask = 0x7ffff >> (x_end & 0xf);
-		out_8(AP_CONTROL_0,
-		     (((area->dx & 0xf) - (area->sx & 0xf)) % 16) | (0x4 << 5));
-		if ((area->dx & 0xf) < (area->sx & 0xf))
-			pre_read = 1;
-	} else {
-		y_delta = -((info->fix.line_length * 8) - area->sx - area->width);
-		x_end = area->dx - area->width + 1;
-		x_word_count = (area->dx >> 4) - (x_end >> 4) + 1;
-		start_mask = 0x7ffff >> (area->dx & 0xf);
-		end_mask = 0xffff0000 >> (x_end & 0xf);
-		out_8(AP_CONTROL_0,
-		     ((-((area->sx & 0xf) - (area->dx & 0xf))) % 16) |
-		     (0x4 << 5));
-		if ((area->dx & 0xf) > (area->sx & 0xf))
-			pre_read = 1;
-	}
-
-	for (i = 0; i < area->height; i++) {
-
-		out_8(AP_CONTROL_3A, 0xc | (dest >> 16));
-
-		if (pre_read) {
-			dummy = *src;
-			src += incr;
-		}
-
-		if (x_word_count) {
-			out_8(AP_WRITE_ENABLE, start_mask);
-			*src = dest;
-			src += incr;
-			dest += incr;
-			out_8(AP_WRITE_ENABLE, 0);
-
-			for (j = 1; j < (x_word_count - 1); j++) {
-				*src = dest;
-				src += incr;
-				dest += incr;
-			}
-
-			out_8(AP_WRITE_ENABLE, start_mask);
-			*src = dest;
-			dest += incr;
-			src += incr;
-		} else {
-			out_8(AP_WRITE_ENABLE, start_mask | end_mask);
-			*src = dest;
-			dest += incr;
-			src += incr;
-		}
-		src += (y_delta / 16);
-		dest += (y_delta / 16);
-	}
-	out_8(AP_CONTROL_0, NORMAL_MODE);
-}
-
-/*
- * Initialization
- */
-
-static int dnfb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	int err = 0;
-
-	info = framebuffer_alloc(0, &dev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	info->fbops = &dn_fb_ops;
-	info->fix = dnfb_fix;
-	info->var = dnfb_var;
-	info->var.red.length = 1;
-	info->var.red.offset = 0;
-	info->var.green = info->var.blue = info->var.red;
-	info->screen_base = (u_char *) info->fix.smem_start;
-
-	err = fb_alloc_cmap(&info->cmap, 2, 0);
-	if (err < 0) {
-		framebuffer_release(info);
-		return err;
-	}
-
-	err = register_framebuffer(info);
-	if (err < 0) {
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-		return err;
-	}
-	platform_set_drvdata(dev, info);
-
-	/* now we have registered we can safely setup the hardware */
-	out_8(AP_CONTROL_3A, RESET_CREG);
-	out_be16(AP_WRITE_ENABLE, 0x0);
-	out_8(AP_CONTROL_0, NORMAL_MODE);
-	out_8(AP_CONTROL_1, (AD_BLT | DST_EQ_SRC | NORM_CREG1));
-	out_8(AP_CONTROL_2, S_DATA_PLN);
-	out_be16(AP_ROP_1, SWAP(0x3));
-
-	printk("apollo frame buffer alive and kicking !\n");
-	return err;
-}
-
-static struct platform_driver dnfb_driver = {
-	.probe	= dnfb_probe,
-	.driver	= {
-		.name	= "dnfb",
-	},
-};
-
-static struct platform_device dnfb_device = {
-	.name	= "dnfb",
-};
-
-int __init dnfb_init(void)
-{
-	int ret;
-
-	if (!MACH_IS_APOLLO)
-		return -ENODEV;
-
-	if (fb_get_options("dnfb", NULL))
-		return -ENODEV;
-
-	ret = platform_driver_register(&dnfb_driver);
-
-	if (!ret) {
-		ret = platform_device_register(&dnfb_device);
-		if (ret)
-			platform_driver_unregister(&dnfb_driver);
-	}
-	return ret;
-}
-
-module_init(dnfb_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/edid.h b/drivers/video/edid.h
deleted file mode 100644
index d03a232d90b2..000000000000
--- a/drivers/video/edid.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* 
- * drivers/video/edid.h - EDID/DDC Header
- *
- * Based on:
- *   1. XFree86 4.3.0, edid.h
- *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
- * 
- *   2. John Fremlin <vii@users.sourceforge.net> and 
- *      Ani Joshi <ajoshi@unixbox.com>
- *
- * DDC is a Trademark of VESA (Video Electronics Standard Association).
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
-*/
-
-#ifndef __EDID_H__
-#define __EDID_H__
-
-#define EDID_LENGTH				0x80
-#define EDID_HEADER				0x00
-#define EDID_HEADER_END				0x07
-
-#define ID_MANUFACTURER_NAME			0x08
-#define ID_MANUFACTURER_NAME_END		0x09
-#define ID_MODEL				0x0a
-
-#define ID_SERIAL_NUMBER			0x0c
-
-#define MANUFACTURE_WEEK			0x10
-#define MANUFACTURE_YEAR			0x11
-
-#define EDID_STRUCT_VERSION			0x12
-#define EDID_STRUCT_REVISION			0x13
-
-#define EDID_STRUCT_DISPLAY                     0x14
-
-#define DPMS_FLAGS				0x18
-#define ESTABLISHED_TIMING_1			0x23
-#define ESTABLISHED_TIMING_2			0x24
-#define MANUFACTURERS_TIMINGS			0x25
-
-/* standard timings supported */
-#define STD_TIMING                              8
-#define STD_TIMING_DESCRIPTION_SIZE             2
-#define STD_TIMING_DESCRIPTIONS_START           0x26
-
-#define DETAILED_TIMING_DESCRIPTIONS_START	0x36
-#define DETAILED_TIMING_DESCRIPTION_SIZE	18
-#define NO_DETAILED_TIMING_DESCRIPTIONS		4
-
-#define DETAILED_TIMING_DESCRIPTION_1		0x36
-#define DETAILED_TIMING_DESCRIPTION_2		0x48
-#define DETAILED_TIMING_DESCRIPTION_3		0x5a
-#define DETAILED_TIMING_DESCRIPTION_4		0x6c
-
-#define DESCRIPTOR_DATA				5
-
-#define UPPER_NIBBLE( x ) \
-        (((128|64|32|16) & (x)) >> 4)
-
-#define LOWER_NIBBLE( x ) \
-        ((1|2|4|8) & (x))
-
-#define COMBINE_HI_8LO( hi, lo ) \
-        ( (((unsigned)hi) << 8) | (unsigned)lo )
-
-#define COMBINE_HI_4LO( hi, lo ) \
-        ( (((unsigned)hi) << 4) | (unsigned)lo )
-
-#define PIXEL_CLOCK_LO     (unsigned)block[ 0 ]
-#define PIXEL_CLOCK_HI     (unsigned)block[ 1 ]
-#define PIXEL_CLOCK	   (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
-#define H_ACTIVE_LO        (unsigned)block[ 2 ]
-#define H_BLANKING_LO      (unsigned)block[ 3 ]
-#define H_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 4 ] )
-#define H_ACTIVE           COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
-#define H_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 4 ] )
-#define H_BLANKING         COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
-
-#define V_ACTIVE_LO        (unsigned)block[ 5 ]
-#define V_BLANKING_LO      (unsigned)block[ 6 ]
-#define V_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 7 ] )
-#define V_ACTIVE           COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
-#define V_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 7 ] )
-#define V_BLANKING         COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
-
-#define H_SYNC_OFFSET_LO   (unsigned)block[ 8 ]
-#define H_SYNC_WIDTH_LO    (unsigned)block[ 9 ]
-
-#define V_SYNC_OFFSET_LO   UPPER_NIBBLE( (unsigned)block[ 10 ] )
-#define V_SYNC_WIDTH_LO    LOWER_NIBBLE( (unsigned)block[ 10 ] )
-
-#define V_SYNC_WIDTH_HI    ((unsigned)block[ 11 ] & (1|2))
-#define V_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (4|8)) >> 2)
-
-#define H_SYNC_WIDTH_HI    (((unsigned)block[ 11 ] & (16|32)) >> 4)
-#define H_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (64|128)) >> 6)
-
-#define V_SYNC_WIDTH       COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
-#define V_SYNC_OFFSET      COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
-
-#define H_SYNC_WIDTH       COMBINE_HI_8LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
-#define H_SYNC_OFFSET      COMBINE_HI_8LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
-
-#define H_SIZE_LO          (unsigned)block[ 12 ]
-#define V_SIZE_LO          (unsigned)block[ 13 ]
-
-#define H_SIZE_HI          UPPER_NIBBLE( (unsigned)block[ 14 ] )
-#define V_SIZE_HI          LOWER_NIBBLE( (unsigned)block[ 14 ] )
-
-#define H_SIZE             COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
-#define V_SIZE             COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
-
-#define H_BORDER           (unsigned)block[ 15 ]
-#define V_BORDER           (unsigned)block[ 16 ]
-
-#define FLAGS              (unsigned)block[ 17 ]
-
-#define INTERLACED         (FLAGS&128)
-#define SYNC_TYPE          (FLAGS&3<<3)	/* bits 4,3 */
-#define SYNC_SEPARATE      (3<<3)
-#define HSYNC_POSITIVE     (FLAGS & 4)
-#define VSYNC_POSITIVE     (FLAGS & 2)
-
-#define V_MIN_RATE              block[ 5 ]
-#define V_MAX_RATE              block[ 6 ]
-#define H_MIN_RATE              block[ 7 ]
-#define H_MAX_RATE              block[ 8 ]
-#define MAX_PIXEL_CLOCK         (((int)block[ 9 ]) * 10)
-#define GTF_SUPPORT		block[10]
-
-#define DPMS_ACTIVE_OFF		(1 << 5)
-#define DPMS_SUSPEND		(1 << 6)
-#define DPMS_STANDBY		(1 << 7)
-
-#endif /* __EDID_H__ */
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
deleted file mode 100644
index ae9618ff6735..000000000000
--- a/drivers/video/efifb.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Framebuffer driver for EFI/UEFI based system
- *
- * (c) 2006 Edgar Hucek <gimli@dark-green.com>
- * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/platform_device.h>
-#include <linux/screen_info.h>
-#include <linux/dmi.h>
-#include <linux/pci.h>
-#include <video/vga.h>
-#include <asm/sysfb.h>
-
-static bool request_mem_succeeded = false;
-
-static struct pci_dev *default_vga;
-
-static struct fb_var_screeninfo efifb_defined = {
-	.activate		= FB_ACTIVATE_NOW,
-	.height			= -1,
-	.width			= -1,
-	.right_margin		= 32,
-	.upper_margin		= 16,
-	.lower_margin		= 4,
-	.vsync_len		= 4,
-	.vmode			= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo efifb_fix = {
-	.id			= "EFI VGA",
-	.type			= FB_TYPE_PACKED_PIXELS,
-	.accel			= FB_ACCEL_NONE,
-	.visual			= FB_VISUAL_TRUECOLOR,
-};
-
-static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	/*
-	 *  Set a single color register. The values supplied are
-	 *  already rounded down to the hardware's capabilities
-	 *  (according to the entries in the `var' structure). Return
-	 *  != 0 for invalid regno.
-	 */
-
-	if (regno >= info->cmap.len)
-		return 1;
-
-	if (regno < 16) {
-		red   >>= 8;
-		green >>= 8;
-		blue  >>= 8;
-		((u32 *)(info->pseudo_palette))[regno] =
-			(red   << info->var.red.offset)   |
-			(green << info->var.green.offset) |
-			(blue  << info->var.blue.offset);
-	}
-	return 0;
-}
-
-static void efifb_destroy(struct fb_info *info)
-{
-	if (info->screen_base)
-		iounmap(info->screen_base);
-	if (request_mem_succeeded)
-		release_mem_region(info->apertures->ranges[0].base,
-				   info->apertures->ranges[0].size);
-	fb_dealloc_cmap(&info->cmap);
-}
-
-static struct fb_ops efifb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_destroy	= efifb_destroy,
-	.fb_setcolreg	= efifb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-struct pci_dev *vga_default_device(void)
-{
-	return default_vga;
-}
-
-EXPORT_SYMBOL_GPL(vga_default_device);
-
-void vga_set_default_device(struct pci_dev *pdev)
-{
-	default_vga = pdev;
-}
-
-static int efifb_setup(char *options)
-{
-	char *this_opt;
-	int i;
-	struct pci_dev *dev = NULL;
-
-	if (options && *options) {
-		while ((this_opt = strsep(&options, ",")) != NULL) {
-			if (!*this_opt) continue;
-
-			for (i = 0; i < M_UNKNOWN; i++) {
-				if (efifb_dmi_list[i].base != 0 &&
-				    !strcmp(this_opt, efifb_dmi_list[i].optname)) {
-					screen_info.lfb_base = efifb_dmi_list[i].base;
-					screen_info.lfb_linelength = efifb_dmi_list[i].stride;
-					screen_info.lfb_width = efifb_dmi_list[i].width;
-					screen_info.lfb_height = efifb_dmi_list[i].height;
-				}
-			}
-			if (!strncmp(this_opt, "base:", 5))
-				screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
-			else if (!strncmp(this_opt, "stride:", 7))
-				screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
-			else if (!strncmp(this_opt, "height:", 7))
-				screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
-			else if (!strncmp(this_opt, "width:", 6))
-				screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
-		}
-	}
-
-	for_each_pci_dev(dev) {
-		int i;
-
-		if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
-			continue;
-
-		for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
-			resource_size_t start, end;
-
-			if (!(pci_resource_flags(dev, i) & IORESOURCE_MEM))
-				continue;
-
-			start = pci_resource_start(dev, i);
-			end  = pci_resource_end(dev, i);
-
-			if (!start || !end)
-				continue;
-
-			if (screen_info.lfb_base >= start &&
-			    (screen_info.lfb_base + screen_info.lfb_size) < end)
-				default_vga = dev;
-		}
-	}
-
-	return 0;
-}
-
-static int efifb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	int err;
-	unsigned int size_vmode;
-	unsigned int size_remap;
-	unsigned int size_total;
-	char *option = NULL;
-
-	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
-		return -ENODEV;
-
-	if (fb_get_options("efifb", &option))
-		return -ENODEV;
-	efifb_setup(option);
-
-	/* We don't get linelength from UGA Draw Protocol, only from
-	 * EFI Graphics Protocol.  So if it's not in DMI, and it's not
-	 * passed in from the user, we really can't use the framebuffer.
-	 */
-	if (!screen_info.lfb_linelength)
-		return -ENODEV;
-
-	if (!screen_info.lfb_depth)
-		screen_info.lfb_depth = 32;
-	if (!screen_info.pages)
-		screen_info.pages = 1;
-	if (!screen_info.lfb_base) {
-		printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
-		return -ENODEV;
-	}
-	printk(KERN_INFO "efifb: probing for efifb\n");
-
-	/* just assume they're all unset if any are */
-	if (!screen_info.blue_size) {
-		screen_info.blue_size = 8;
-		screen_info.blue_pos = 0;
-		screen_info.green_size = 8;
-		screen_info.green_pos = 8;
-		screen_info.red_size = 8;
-		screen_info.red_pos = 16;
-		screen_info.rsvd_size = 8;
-		screen_info.rsvd_pos = 24;
-	}
-
-	efifb_fix.smem_start = screen_info.lfb_base;
-	efifb_defined.bits_per_pixel = screen_info.lfb_depth;
-	efifb_defined.xres = screen_info.lfb_width;
-	efifb_defined.yres = screen_info.lfb_height;
-	efifb_fix.line_length = screen_info.lfb_linelength;
-
-	/*   size_vmode -- that is the amount of memory needed for the
-	 *                 used video mode, i.e. the minimum amount of
-	 *                 memory we need. */
-	size_vmode = efifb_defined.yres * efifb_fix.line_length;
-
-	/*   size_total -- all video memory we have. Used for
-	 *                 entries, ressource allocation and bounds
-	 *                 checking. */
-	size_total = screen_info.lfb_size;
-	if (size_total < size_vmode)
-		size_total = size_vmode;
-
-	/*   size_remap -- the amount of video memory we are going to
-	 *                 use for efifb.  With modern cards it is no
-	 *                 option to simply use size_total as that
-	 *                 wastes plenty of kernel address space. */
-	size_remap  = size_vmode * 2;
-	if (size_remap > size_total)
-		size_remap = size_total;
-	if (size_remap % PAGE_SIZE)
-		size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
-	efifb_fix.smem_len = size_remap;
-
-	if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
-		request_mem_succeeded = true;
-	} else {
-		/* We cannot make this fatal. Sometimes this comes from magic
-		   spaces our resource handlers simply don't know about */
-		printk(KERN_WARNING
-		       "efifb: cannot reserve video memory at 0x%lx\n",
-			efifb_fix.smem_start);
-	}
-
-	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
-	if (!info) {
-		printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
-		err = -ENOMEM;
-		goto err_release_mem;
-	}
-	platform_set_drvdata(dev, info);
-	info->pseudo_palette = info->par;
-	info->par = NULL;
-
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures) {
-		err = -ENOMEM;
-		goto err_release_fb;
-	}
-	info->apertures->ranges[0].base = efifb_fix.smem_start;
-	info->apertures->ranges[0].size = size_remap;
-
-	info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
-	if (!info->screen_base) {
-		printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
-				"0x%x @ 0x%lx\n",
-			efifb_fix.smem_len, efifb_fix.smem_start);
-		err = -EIO;
-		goto err_release_fb;
-	}
-
-	printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
-	       "using %dk, total %dk\n",
-	       efifb_fix.smem_start, info->screen_base,
-	       size_remap/1024, size_total/1024);
-	printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
-	       efifb_defined.xres, efifb_defined.yres,
-	       efifb_defined.bits_per_pixel, efifb_fix.line_length,
-	       screen_info.pages);
-
-	efifb_defined.xres_virtual = efifb_defined.xres;
-	efifb_defined.yres_virtual = efifb_fix.smem_len /
-					efifb_fix.line_length;
-	printk(KERN_INFO "efifb: scrolling: redraw\n");
-	efifb_defined.yres_virtual = efifb_defined.yres;
-
-	/* some dummy values for timing to make fbset happy */
-	efifb_defined.pixclock     = 10000000 / efifb_defined.xres *
-					1000 / efifb_defined.yres;
-	efifb_defined.left_margin  = (efifb_defined.xres / 8) & 0xf8;
-	efifb_defined.hsync_len    = (efifb_defined.xres / 8) & 0xf8;
-
-	efifb_defined.red.offset    = screen_info.red_pos;
-	efifb_defined.red.length    = screen_info.red_size;
-	efifb_defined.green.offset  = screen_info.green_pos;
-	efifb_defined.green.length  = screen_info.green_size;
-	efifb_defined.blue.offset   = screen_info.blue_pos;
-	efifb_defined.blue.length   = screen_info.blue_size;
-	efifb_defined.transp.offset = screen_info.rsvd_pos;
-	efifb_defined.transp.length = screen_info.rsvd_size;
-
-	printk(KERN_INFO "efifb: %s: "
-	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
-	       "Truecolor",
-	       screen_info.rsvd_size,
-	       screen_info.red_size,
-	       screen_info.green_size,
-	       screen_info.blue_size,
-	       screen_info.rsvd_pos,
-	       screen_info.red_pos,
-	       screen_info.green_pos,
-	       screen_info.blue_pos);
-
-	efifb_fix.ypanstep  = 0;
-	efifb_fix.ywrapstep = 0;
-
-	info->fbops = &efifb_ops;
-	info->var = efifb_defined;
-	info->fix = efifb_fix;
-	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
-
-	if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
-		printk(KERN_ERR "efifb: cannot allocate colormap\n");
-		goto err_unmap;
-	}
-	if ((err = register_framebuffer(info)) < 0) {
-		printk(KERN_ERR "efifb: cannot register framebuffer\n");
-		goto err_fb_dealoc;
-	}
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	return 0;
-
-err_fb_dealoc:
-	fb_dealloc_cmap(&info->cmap);
-err_unmap:
-	iounmap(info->screen_base);
-err_release_fb:
-	framebuffer_release(info);
-err_release_mem:
-	if (request_mem_succeeded)
-		release_mem_region(efifb_fix.smem_start, size_total);
-	return err;
-}
-
-static int efifb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-
-	unregister_framebuffer(info);
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static struct platform_driver efifb_driver = {
-	.driver = {
-		.name = "efi-framebuffer",
-		.owner = THIS_MODULE,
-	},
-	.probe = efifb_probe,
-	.remove = efifb_remove,
-};
-
-module_platform_driver(efifb_driver);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
deleted file mode 100644
index 35a0f533f1a2..000000000000
--- a/drivers/video/ep93xx-fb.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * linux/drivers/video/ep93xx-fb.c
- *
- * Framebuffer support for the EP93xx series.
- *
- * Copyright (C) 2007 Bluewater Systems Ltd
- * Author: Ryan Mallon
- *
- * Copyright (c) 2009 H Hartley Sweeten <hsweeten@visionengravers.com>
- *
- * Based on the Cirrus Logic ep93xxfb driver, and various other ep93xxfb
- * drivers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/fb.h>
-#include <linux/io.h>
-
-#include <linux/platform_data/video-ep93xx.h>
-
-/* Vertical Frame Timing Registers */
-#define EP93XXFB_VLINES_TOTAL			0x0000	/* SW locked */
-#define EP93XXFB_VSYNC				0x0004	/* SW locked */
-#define EP93XXFB_VACTIVE			0x0008	/* SW locked */
-#define EP93XXFB_VBLANK				0x0228	/* SW locked */
-#define EP93XXFB_VCLK				0x000c	/* SW locked */
-
-/* Horizontal Frame Timing Registers */
-#define EP93XXFB_HCLKS_TOTAL			0x0010	/* SW locked */
-#define EP93XXFB_HSYNC				0x0014	/* SW locked */
-#define EP93XXFB_HACTIVE			0x0018	/* SW locked */
-#define EP93XXFB_HBLANK				0x022c	/* SW locked */
-#define EP93XXFB_HCLK				0x001c	/* SW locked */
-
-/* Frame Buffer Memory Configuration Registers */
-#define EP93XXFB_SCREEN_PAGE			0x0028
-#define EP93XXFB_SCREEN_HPAGE			0x002c
-#define EP93XXFB_SCREEN_LINES			0x0030
-#define EP93XXFB_LINE_LENGTH			0x0034
-#define EP93XXFB_VLINE_STEP			0x0038
-#define EP93XXFB_LINE_CARRY			0x003c	/* SW locked */
-#define EP93XXFB_EOL_OFFSET			0x0230
-
-/* Other Video Registers */
-#define EP93XXFB_BRIGHTNESS			0x0020
-#define EP93XXFB_ATTRIBS			0x0024	/* SW locked */
-#define EP93XXFB_SWLOCK				0x007c	/* SW locked */
-#define EP93XXFB_AC_RATE			0x0214
-#define EP93XXFB_FIFO_LEVEL			0x0234
-#define EP93XXFB_PIXELMODE			0x0054
-#define EP93XXFB_PIXELMODE_32BPP		(0x7 << 0)
-#define EP93XXFB_PIXELMODE_24BPP		(0x6 << 0)
-#define EP93XXFB_PIXELMODE_16BPP		(0x4 << 0)
-#define EP93XXFB_PIXELMODE_8BPP			(0x2 << 0)
-#define EP93XXFB_PIXELMODE_SHIFT_1P_24B		(0x0 << 3)
-#define EP93XXFB_PIXELMODE_SHIFT_1P_18B		(0x1 << 3)
-#define EP93XXFB_PIXELMODE_COLOR_LUT		(0x0 << 10)
-#define EP93XXFB_PIXELMODE_COLOR_888		(0x4 << 10)
-#define EP93XXFB_PIXELMODE_COLOR_555		(0x5 << 10)
-#define EP93XXFB_PARL_IF_OUT			0x0058
-#define EP93XXFB_PARL_IF_IN			0x005c
-
-/* Blink Control Registers */
-#define EP93XXFB_BLINK_RATE			0x0040
-#define EP93XXFB_BLINK_MASK			0x0044
-#define EP93XXFB_BLINK_PATTRN			0x0048
-#define EP93XXFB_PATTRN_MASK			0x004c
-#define EP93XXFB_BKGRND_OFFSET			0x0050
-
-/* Hardware Cursor Registers */
-#define EP93XXFB_CURSOR_ADR_START		0x0060
-#define EP93XXFB_CURSOR_ADR_RESET		0x0064
-#define EP93XXFB_CURSOR_SIZE			0x0068
-#define EP93XXFB_CURSOR_COLOR1			0x006c
-#define EP93XXFB_CURSOR_COLOR2			0x0070
-#define EP93XXFB_CURSOR_BLINK_COLOR1		0x021c
-#define EP93XXFB_CURSOR_BLINK_COLOR2		0x0220
-#define EP93XXFB_CURSOR_XY_LOC			0x0074
-#define EP93XXFB_CURSOR_DSCAN_HY_LOC		0x0078
-#define EP93XXFB_CURSOR_BLINK_RATE_CTRL		0x0224
-
-/* LUT Registers */
-#define EP93XXFB_GRY_SCL_LUTR			0x0080
-#define EP93XXFB_GRY_SCL_LUTG			0x0280
-#define EP93XXFB_GRY_SCL_LUTB			0x0300
-#define EP93XXFB_LUT_SW_CONTROL			0x0218
-#define EP93XXFB_LUT_SW_CONTROL_SWTCH		(1 << 0)
-#define EP93XXFB_LUT_SW_CONTROL_SSTAT		(1 << 1)
-#define EP93XXFB_COLOR_LUT			0x0400
-
-/* Video Signature Registers */
-#define EP93XXFB_VID_SIG_RSLT_VAL		0x0200
-#define EP93XXFB_VID_SIG_CTRL			0x0204
-#define EP93XXFB_VSIG				0x0208
-#define EP93XXFB_HSIG				0x020c
-#define EP93XXFB_SIG_CLR_STR			0x0210
-
-/* Minimum / Maximum resolutions supported */
-#define EP93XXFB_MIN_XRES			64
-#define EP93XXFB_MIN_YRES			64
-#define EP93XXFB_MAX_XRES			1024
-#define EP93XXFB_MAX_YRES			768
-
-struct ep93xx_fbi {
-	struct ep93xxfb_mach_info	*mach_info;
-	struct clk			*clk;
-	struct resource			*res;
-	void __iomem			*mmio_base;
-	unsigned int			pseudo_palette[256];
-};
-
-static int check_screenpage_bug = 1;
-module_param(check_screenpage_bug, int, 0644);
-MODULE_PARM_DESC(check_screenpage_bug,
-		 "Check for bit 27 screen page bug. Default = 1");
-
-static inline unsigned int ep93xxfb_readl(struct ep93xx_fbi *fbi,
-					  unsigned int off)
-{
-	return __raw_readl(fbi->mmio_base + off);
-}
-
-static inline void ep93xxfb_writel(struct ep93xx_fbi *fbi,
-				   unsigned int val, unsigned int off)
-{
-	__raw_writel(val, fbi->mmio_base + off);
-}
-
-/*
- * Write to one of the locked raster registers.
- */
-static inline void ep93xxfb_out_locked(struct ep93xx_fbi *fbi,
-				       unsigned int val, unsigned int reg)
-{
-	/*
-	 * We don't need a lock or delay here since the raster register
-	 * block will remain unlocked until the next access.
-	 */
-	ep93xxfb_writel(fbi, 0xaa, EP93XXFB_SWLOCK);
-	ep93xxfb_writel(fbi, val, reg);
-}
-
-static void ep93xxfb_set_video_attribs(struct fb_info *info)
-{
-	struct ep93xx_fbi *fbi = info->par;
-	unsigned int attribs;
-
-	attribs = EP93XXFB_ENABLE;
-	attribs |= fbi->mach_info->flags;
-	ep93xxfb_out_locked(fbi, attribs, EP93XXFB_ATTRIBS);
-}
-
-static int ep93xxfb_set_pixelmode(struct fb_info *info)
-{
-	struct ep93xx_fbi *fbi = info->par;
-	unsigned int val;
-
-	info->var.transp.offset = 0;
-	info->var.transp.length = 0;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		val = EP93XXFB_PIXELMODE_8BPP | EP93XXFB_PIXELMODE_COLOR_LUT |
-			EP93XXFB_PIXELMODE_SHIFT_1P_18B;
-
-		info->var.red.offset	= 0;
-		info->var.red.length	= 8;
-		info->var.green.offset	= 0;
-		info->var.green.length	= 8;
-		info->var.blue.offset	= 0;
-		info->var.blue.length	= 8;
-		info->fix.visual 	= FB_VISUAL_PSEUDOCOLOR;
-		break;
-
-	case 16:
-		val = EP93XXFB_PIXELMODE_16BPP | EP93XXFB_PIXELMODE_COLOR_555 |
-			EP93XXFB_PIXELMODE_SHIFT_1P_18B;
-
-		info->var.red.offset	= 11;
-		info->var.red.length	= 5;
-		info->var.green.offset	= 5;
-		info->var.green.length	= 6;
-		info->var.blue.offset	= 0;
-		info->var.blue.length	= 5;
-		info->fix.visual 	= FB_VISUAL_TRUECOLOR;
-		break;
-
-	case 24:
-		val = EP93XXFB_PIXELMODE_24BPP | EP93XXFB_PIXELMODE_COLOR_888 |
-			EP93XXFB_PIXELMODE_SHIFT_1P_24B;
-
-		info->var.red.offset	= 16;
-		info->var.red.length	= 8;
-		info->var.green.offset	= 8;
-		info->var.green.length	= 8;
-		info->var.blue.offset	= 0;
-		info->var.blue.length	= 8;
-		info->fix.visual 	= FB_VISUAL_TRUECOLOR;
-		break;
-
-	case 32:
-		val = EP93XXFB_PIXELMODE_32BPP | EP93XXFB_PIXELMODE_COLOR_888 |
-			EP93XXFB_PIXELMODE_SHIFT_1P_24B;
-
-		info->var.red.offset	= 16;
-		info->var.red.length	= 8;
-		info->var.green.offset	= 8;
-		info->var.green.length	= 8;
-		info->var.blue.offset	= 0;
-		info->var.blue.length	= 8;
-		info->fix.visual 	= FB_VISUAL_TRUECOLOR;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	ep93xxfb_writel(fbi, val, EP93XXFB_PIXELMODE);
-	return 0;
-}
-
-static void ep93xxfb_set_timing(struct fb_info *info)
-{
-	struct ep93xx_fbi *fbi = info->par;
-	unsigned int vlines_total, hclks_total, start, stop;
-
-	vlines_total = info->var.yres + info->var.upper_margin +
-		info->var.lower_margin + info->var.vsync_len - 1;
-
-	hclks_total = info->var.xres + info->var.left_margin +
-		info->var.right_margin + info->var.hsync_len - 1;
-
-	ep93xxfb_out_locked(fbi, vlines_total, EP93XXFB_VLINES_TOTAL);
-	ep93xxfb_out_locked(fbi, hclks_total, EP93XXFB_HCLKS_TOTAL);
-
-	start = vlines_total;
-	stop = vlines_total - info->var.vsync_len;
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VSYNC);
-
-	start = vlines_total - info->var.vsync_len - info->var.upper_margin;
-	stop = info->var.lower_margin - 1;
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VBLANK);
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VACTIVE);
-
-	start = vlines_total;
-	stop = vlines_total + 1;
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VCLK);
-
-	start = hclks_total;
-	stop = hclks_total - info->var.hsync_len;
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HSYNC);
-
-	start = hclks_total - info->var.hsync_len - info->var.left_margin;
-	stop = info->var.right_margin - 1;
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HBLANK);
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HACTIVE);
-
-	start = hclks_total;
-	stop = hclks_total;
-	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HCLK);
-
-	ep93xxfb_out_locked(fbi, 0x0, EP93XXFB_LINE_CARRY);
-}
-
-static int ep93xxfb_set_par(struct fb_info *info)
-{
-	struct ep93xx_fbi *fbi = info->par;
-
-	clk_set_rate(fbi->clk, 1000 * PICOS2KHZ(info->var.pixclock));
-
-	ep93xxfb_set_timing(info);
-
-	info->fix.line_length = info->var.xres_virtual *
-		info->var.bits_per_pixel / 8;
-
-	ep93xxfb_writel(fbi, info->fix.smem_start, EP93XXFB_SCREEN_PAGE);
-	ep93xxfb_writel(fbi, info->var.yres - 1, EP93XXFB_SCREEN_LINES);
-	ep93xxfb_writel(fbi, ((info->var.xres * info->var.bits_per_pixel)
-			      / 32) - 1, EP93XXFB_LINE_LENGTH);
-	ep93xxfb_writel(fbi, info->fix.line_length / 4, EP93XXFB_VLINE_STEP);
-	ep93xxfb_set_video_attribs(info);
-	return 0;
-}
-
-static int ep93xxfb_check_var(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	int err;
-
-	err = ep93xxfb_set_pixelmode(info);
-	if (err)
-		return err;
-
-	var->xres = max_t(unsigned int, var->xres, EP93XXFB_MIN_XRES);
-	var->xres = min_t(unsigned int, var->xres, EP93XXFB_MAX_XRES);
-	var->xres_virtual = max(var->xres_virtual, var->xres);
-
-	var->yres = max_t(unsigned int, var->yres, EP93XXFB_MIN_YRES);
-	var->yres = min_t(unsigned int, var->yres, EP93XXFB_MAX_YRES);
-	var->yres_virtual = max(var->yres_virtual, var->yres);
-
-	return 0;
-}
-
-static int ep93xxfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	unsigned int offset = vma->vm_pgoff << PAGE_SHIFT;
-
-	if (offset < info->fix.smem_len) {
-		return dma_mmap_writecombine(info->dev, vma, info->screen_base,
-					     info->fix.smem_start,
-					     info->fix.smem_len);
-	}
-
-	return -EINVAL;
-}
-
-static int ep93xxfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct ep93xx_fbi *fbi = info->par;
-	unsigned int attribs = ep93xxfb_readl(fbi, EP93XXFB_ATTRIBS);
-
-	if (blank_mode) {
-		if (fbi->mach_info->blank)
-			fbi->mach_info->blank(blank_mode, info);
-		ep93xxfb_out_locked(fbi, attribs & ~EP93XXFB_ENABLE,
-				    EP93XXFB_ATTRIBS);
-		clk_disable(fbi->clk);
-	} else {
-		clk_enable(fbi->clk);
-		ep93xxfb_out_locked(fbi, attribs | EP93XXFB_ENABLE,
-				    EP93XXFB_ATTRIBS);
-		if (fbi->mach_info->blank)
-			fbi->mach_info->blank(blank_mode, info);
-	}
-
-	return 0;
-}
-
-static inline int ep93xxfb_convert_color(int val, int width)
-{
-	return ((val << width) + 0x7fff - val) >> 16;
-}
-
-static int ep93xxfb_setcolreg(unsigned int regno, unsigned int red,
-			      unsigned int green, unsigned int blue,
-			      unsigned int transp, struct fb_info *info)
-{
-	struct ep93xx_fbi *fbi = info->par;
-	unsigned int *pal = info->pseudo_palette;
-	unsigned int ctrl, i, rgb, lut_current, lut_stat;
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno > 255)
-			return 1;
-		rgb = ((red & 0xff00) << 8) | (green & 0xff00) |
-			((blue & 0xff00) >> 8);
-
-		pal[regno] = rgb;
-		ep93xxfb_writel(fbi, rgb, (EP93XXFB_COLOR_LUT + (regno << 2)));
-		ctrl = ep93xxfb_readl(fbi, EP93XXFB_LUT_SW_CONTROL);
-		lut_stat = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SSTAT);
-		lut_current = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SWTCH);
-
-		if (lut_stat == lut_current) {
-			for (i = 0; i < 256; i++) {
-				ep93xxfb_writel(fbi, pal[i],
-					EP93XXFB_COLOR_LUT + (i << 2));
-			}
-
-			ep93xxfb_writel(fbi,
-					ctrl ^ EP93XXFB_LUT_SW_CONTROL_SWTCH,
-					EP93XXFB_LUT_SW_CONTROL);
-		}
-		break;
-
-	case FB_VISUAL_TRUECOLOR:
-		if (regno > 16)
-			return 1;
-
-		red = ep93xxfb_convert_color(red, info->var.red.length);
-		green = ep93xxfb_convert_color(green, info->var.green.length);
-		blue = ep93xxfb_convert_color(blue, info->var.blue.length);
-		transp = ep93xxfb_convert_color(transp,
-						info->var.transp.length);
-
-		pal[regno] = (red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset) |
-			(transp << info->var.transp.offset);
-		break;
-
-	default:
-		return 1;
-	}
-
-	return 0;
-}
-
-static struct fb_ops ep93xxfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= ep93xxfb_check_var,
-	.fb_set_par	= ep93xxfb_set_par,
-	.fb_blank	= ep93xxfb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_setcolreg	= ep93xxfb_setcolreg,
-	.fb_mmap	= ep93xxfb_mmap,
-};
-
-static int ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
-{
-	int i, fb_size = 0;
-
-	if (mach_info->num_modes == EP93XXFB_USE_MODEDB) {
-		fb_size = EP93XXFB_MAX_XRES * EP93XXFB_MAX_YRES *
-			mach_info->bpp / 8;
-	} else {
-		for (i = 0; i < mach_info->num_modes; i++) {
-			const struct fb_videomode *mode;
-			int size;
-
-			mode = &mach_info->modes[i];
-			size = mode->xres * mode->yres * mach_info->bpp / 8;
-			if (size > fb_size)
-				fb_size = size;
-		}
-	}
-
-	return fb_size;
-}
-
-static int ep93xxfb_alloc_videomem(struct fb_info *info)
-{
-	struct ep93xx_fbi *fbi = info->par;
-	char __iomem *virt_addr;
-	dma_addr_t phys_addr;
-	unsigned int fb_size;
-
-	fb_size = ep93xxfb_calc_fbsize(fbi->mach_info);
-	virt_addr = dma_alloc_writecombine(info->dev, fb_size,
-					   &phys_addr, GFP_KERNEL);
-	if (!virt_addr)
-		return -ENOMEM;
-
-	/*
-	 * There is a bug in the ep93xx framebuffer which causes problems
-	 * if bit 27 of the physical address is set.
-	 * See: http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
-	 * There does not seem to be any official errata for this, but I
-	 * have confirmed the problem exists on my hardware (ep9315) at
-	 * least.
-	 */
-	if (check_screenpage_bug && phys_addr & (1 << 27)) {
-		dev_err(info->dev, "ep93xx framebuffer bug. phys addr (0x%x) "
-			"has bit 27 set: cannot init framebuffer\n",
-			phys_addr);
-
-		dma_free_coherent(info->dev, fb_size, virt_addr, phys_addr);
-		return -ENOMEM;
-	}
-
-	info->fix.smem_start = phys_addr;
-	info->fix.smem_len = fb_size;
-	info->screen_base = virt_addr;
-
-	return 0;
-}
-
-static void ep93xxfb_dealloc_videomem(struct fb_info *info)
-{
-	if (info->screen_base)
-		dma_free_coherent(info->dev, info->fix.smem_len,
-				  info->screen_base, info->fix.smem_start);
-}
-
-static int ep93xxfb_probe(struct platform_device *pdev)
-{
-	struct ep93xxfb_mach_info *mach_info = dev_get_platdata(&pdev->dev);
-	struct fb_info *info;
-	struct ep93xx_fbi *fbi;
-	struct resource *res;
-	char *video_mode;
-	int err;
-
-	if (!mach_info)
-		return -EINVAL;
-
-	info = framebuffer_alloc(sizeof(struct ep93xx_fbi), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	info->dev = &pdev->dev;
-	platform_set_drvdata(pdev, info);
-	fbi = info->par;
-	fbi->mach_info = mach_info;
-
-	err = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (err)
-		goto failed_cmap;
-
-	err = ep93xxfb_alloc_videomem(info);
-	if (err)
-		goto failed_videomem;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		err = -ENXIO;
-		goto failed_resource;
-	}
-
-	/*
-	 * FIXME - We don't do a request_mem_region here because we are
-	 * sharing the register space with the backlight driver (see
-	 * drivers/video/backlight/ep93xx_bl.c) and doing so will cause
-	 * the second loaded driver to return -EBUSY.
-	 *
-	 * NOTE: No locking is required; the backlight does not touch
-	 * any of the framebuffer registers.
-	 */
-	fbi->res = res;
-	fbi->mmio_base = devm_ioremap(&pdev->dev, res->start,
-				      resource_size(res));
-	if (!fbi->mmio_base) {
-		err = -ENXIO;
-		goto failed_resource;
-	}
-
-	strcpy(info->fix.id, pdev->name);
-	info->fbops		= &ep93xxfb_ops;
-	info->fix.type		= FB_TYPE_PACKED_PIXELS;
-	info->fix.accel		= FB_ACCEL_NONE;
-	info->var.activate	= FB_ACTIVATE_NOW;
-	info->var.vmode		= FB_VMODE_NONINTERLACED;
-	info->flags		= FBINFO_DEFAULT;
-	info->node		= -1;
-	info->state		= FBINFO_STATE_RUNNING;
-	info->pseudo_palette	= &fbi->pseudo_palette;
-
-	fb_get_options("ep93xx-fb", &video_mode);
-	err = fb_find_mode(&info->var, info, video_mode,
-			   fbi->mach_info->modes, fbi->mach_info->num_modes,
-			   fbi->mach_info->default_mode, fbi->mach_info->bpp);
-	if (err == 0) {
-		dev_err(info->dev, "No suitable video mode found\n");
-		err = -EINVAL;
-		goto failed_resource;
-	}
-
-	if (mach_info->setup) {
-		err = mach_info->setup(pdev);
-		if (err)
-			goto failed_resource;
-	}
-
-	err = ep93xxfb_check_var(&info->var, info);
-	if (err)
-		goto failed_check;
-
-	fbi->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(fbi->clk)) {
-		err = PTR_ERR(fbi->clk);
-		fbi->clk = NULL;
-		goto failed_check;
-	}
-
-	ep93xxfb_set_par(info);
-	clk_enable(fbi->clk);
-
-	err = register_framebuffer(info);
-	if (err)
-		goto failed_check;
-
-	dev_info(info->dev, "registered. Mode = %dx%d-%d\n",
-		 info->var.xres, info->var.yres, info->var.bits_per_pixel);
-	return 0;
-
-failed_check:
-	if (fbi->mach_info->teardown)
-		fbi->mach_info->teardown(pdev);
-failed_resource:
-	ep93xxfb_dealloc_videomem(info);
-failed_videomem:
-	fb_dealloc_cmap(&info->cmap);
-failed_cmap:
-	kfree(info);
-
-	return err;
-}
-
-static int ep93xxfb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct ep93xx_fbi *fbi = info->par;
-
-	unregister_framebuffer(info);
-	clk_disable(fbi->clk);
-	ep93xxfb_dealloc_videomem(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	if (fbi->mach_info->teardown)
-		fbi->mach_info->teardown(pdev);
-
-	kfree(info);
-
-	return 0;
-}
-
-static struct platform_driver ep93xxfb_driver = {
-	.probe		= ep93xxfb_probe,
-	.remove		= ep93xxfb_remove,
-	.driver = {
-		.name	= "ep93xx-fb",
-		.owner	= THIS_MODULE,
-	},
-};
-module_platform_driver(ep93xxfb_driver);
-
-MODULE_DESCRIPTION("EP93XX Framebuffer Driver");
-MODULE_ALIAS("platform:ep93xx-fb");
-MODULE_AUTHOR("Ryan Mallon, "
-	      "H Hartley Sweeten <hsweeten@visionengravers.com");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
deleted file mode 100644
index fcf2d48ac6d1..000000000000
--- a/drivers/video/exynos/Kconfig
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Exynos Video configuration
-#
-
-menuconfig EXYNOS_VIDEO
-	bool "Exynos Video driver support"
-	help
-	  This enables support for EXYNOS Video device.
-
-if EXYNOS_VIDEO
-
-#
-# MIPI DSI driver
-#
-
-config EXYNOS_MIPI_DSI
-	bool "EXYNOS MIPI DSI driver support."
-	depends on ARCH_S5PV210 || ARCH_EXYNOS
-	select GENERIC_PHY
-	help
-	  This enables support for MIPI-DSI device.
-
-config EXYNOS_LCD_S6E8AX0
-	bool "S6E8AX0 MIPI AMOLED LCD Driver"
-	depends on EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE
-	depends on (LCD_CLASS_DEVICE = y)
-	default n
-	help
-	  If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
-	  LCD control driver.
-
-endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
deleted file mode 100644
index b5b1bd228abb..000000000000
--- a/drivers/video/exynos/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the exynos video drivers.
-#
-
-obj-$(CONFIG_EXYNOS_MIPI_DSI)		+= exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
-				     	exynos_mipi_dsi_lowlevel.o
-obj-$(CONFIG_EXYNOS_LCD_S6E8AX0)	+= s6e8ax0.o
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
deleted file mode 100644
index cee9602f9a7b..000000000000
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/* linux/drivers/video/exynos/exynos_mipi_dsi.c
- *
- * Samsung SoC MIPI-DSIM driver.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd
- *
- * InKi Dae, <inki.dae@samsung.com>
- * Donghwa Lee, <dh09.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/ctype.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/memory.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kthread.h>
-#include <linux/notifier.h>
-#include <linux/phy/phy.h>
-#include <linux/regulator/consumer.h>
-#include <linux/pm_runtime.h>
-#include <linux/err.h>
-
-#include <video/exynos_mipi_dsim.h>
-
-#include "exynos_mipi_dsi_common.h"
-#include "exynos_mipi_dsi_lowlevel.h"
-
-struct mipi_dsim_ddi {
-	int				bus_id;
-	struct list_head		list;
-	struct mipi_dsim_lcd_device	*dsim_lcd_dev;
-	struct mipi_dsim_lcd_driver	*dsim_lcd_drv;
-};
-
-static LIST_HEAD(dsim_ddi_list);
-
-static DEFINE_MUTEX(mipi_dsim_lock);
-
-static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
-							*pdev)
-{
-	return pdev->dev.platform_data;
-}
-
-static struct regulator_bulk_data supplies[] = {
-	{ .supply = "vdd11", },
-	{ .supply = "vdd18", },
-};
-
-static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
-{
-	int ret;
-
-	mutex_lock(&dsim->lock);
-	ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
-	mutex_unlock(&dsim->lock);
-
-	return ret;
-}
-
-static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
-{
-	int ret;
-
-	mutex_lock(&dsim->lock);
-	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
-	mutex_unlock(&dsim->lock);
-
-	return ret;
-}
-
-/* update all register settings to MIPI DSI controller. */
-static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
-{
-	/*
-	 * data from Display controller(FIMD) is not transferred in video mode
-	 * but in case of command mode, all settings is not updated to
-	 * registers.
-	 */
-	exynos_mipi_dsi_stand_by(dsim, 0);
-
-	exynos_mipi_dsi_init_dsim(dsim);
-	exynos_mipi_dsi_init_link(dsim);
-
-	exynos_mipi_dsi_set_hs_enable(dsim);
-
-	/* set display timing. */
-	exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
-
-	exynos_mipi_dsi_init_interrupt(dsim);
-
-	/*
-	 * data from Display controller(FIMD) is transferred in video mode
-	 * but in case of command mode, all settings are updated to registers.
-	 */
-	exynos_mipi_dsi_stand_by(dsim, 1);
-}
-
-static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
-		int power)
-{
-	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
-	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
-
-	switch (power) {
-	case FB_BLANK_POWERDOWN:
-		if (dsim->suspended)
-			return 0;
-
-		if (client_drv && client_drv->suspend)
-			client_drv->suspend(client_dev);
-
-		clk_disable(dsim->clock);
-
-		exynos_mipi_regulator_disable(dsim);
-
-		dsim->suspended = true;
-
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
-{
-	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
-	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
-
-	switch (power) {
-	case FB_BLANK_UNBLANK:
-		if (!dsim->suspended)
-			return 0;
-
-		/* lcd panel power on. */
-		if (client_drv && client_drv->power_on)
-			client_drv->power_on(client_dev, 1);
-
-		exynos_mipi_regulator_enable(dsim);
-
-		/* enable MIPI-DSI PHY. */
-		phy_power_on(dsim->phy);
-
-		clk_enable(dsim->clock);
-
-		exynos_mipi_update_cfg(dsim);
-
-		/* set lcd panel sequence commands. */
-		if (client_drv && client_drv->set_sequence)
-			client_drv->set_sequence(client_dev);
-
-		dsim->suspended = false;
-
-		break;
-	case FB_BLANK_NORMAL:
-		/* TODO. */
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
-{
-	struct mipi_dsim_ddi *dsim_ddi;
-
-	if (!lcd_dev->name) {
-		pr_err("dsim_lcd_device name is NULL.\n");
-		return -EFAULT;
-	}
-
-	dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
-	if (!dsim_ddi) {
-		pr_err("failed to allocate dsim_ddi object.\n");
-		return -ENOMEM;
-	}
-
-	dsim_ddi->dsim_lcd_dev = lcd_dev;
-
-	mutex_lock(&mipi_dsim_lock);
-	list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
-	mutex_unlock(&mipi_dsim_lock);
-
-	return 0;
-}
-
-static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
-					struct mipi_dsim_lcd_driver *lcd_drv)
-{
-	struct mipi_dsim_ddi *dsim_ddi, *next;
-	struct mipi_dsim_lcd_device *lcd_dev;
-
-	mutex_lock(&mipi_dsim_lock);
-
-	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
-		if (!dsim_ddi)
-			goto out;
-
-		lcd_dev = dsim_ddi->dsim_lcd_dev;
-		if (!lcd_dev)
-			continue;
-
-		if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
-			/**
-			 * bus_id would be used to identify
-			 * connected bus.
-			 */
-			dsim_ddi->bus_id = lcd_dev->bus_id;
-			mutex_unlock(&mipi_dsim_lock);
-
-			return dsim_ddi;
-		}
-
-		list_del(&dsim_ddi->list);
-		kfree(dsim_ddi);
-	}
-
-out:
-	mutex_unlock(&mipi_dsim_lock);
-
-	return NULL;
-}
-
-int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
-{
-	struct mipi_dsim_ddi *dsim_ddi;
-
-	if (!lcd_drv->name) {
-		pr_err("dsim_lcd_driver name is NULL.\n");
-		return -EFAULT;
-	}
-
-	dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
-	if (!dsim_ddi) {
-		pr_err("mipi_dsim_ddi object not found.\n");
-		return -EFAULT;
-	}
-
-	dsim_ddi->dsim_lcd_drv = lcd_drv;
-
-	pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
-		lcd_drv->name);
-
-	return 0;
-
-}
-
-static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
-						struct mipi_dsim_device *dsim,
-						const char *name)
-{
-	struct mipi_dsim_ddi *dsim_ddi, *next;
-	struct mipi_dsim_lcd_driver *lcd_drv;
-	struct mipi_dsim_lcd_device *lcd_dev;
-	int ret;
-
-	mutex_lock(&dsim->lock);
-
-	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
-		lcd_drv = dsim_ddi->dsim_lcd_drv;
-		lcd_dev = dsim_ddi->dsim_lcd_dev;
-		if (!lcd_drv || !lcd_dev ||
-			(dsim->id != dsim_ddi->bus_id))
-				continue;
-
-		dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
-				lcd_drv->id, lcd_dev->id);
-		dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
-				lcd_dev->bus_id, dsim->id);
-
-		if ((strcmp(lcd_drv->name, name) == 0)) {
-			lcd_dev->master = dsim;
-
-			lcd_dev->dev.parent = dsim->dev;
-			dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
-
-			ret = device_register(&lcd_dev->dev);
-			if (ret < 0) {
-				dev_err(dsim->dev,
-					"can't register %s, status %d\n",
-					dev_name(&lcd_dev->dev), ret);
-				mutex_unlock(&dsim->lock);
-
-				return NULL;
-			}
-
-			dsim->dsim_lcd_dev = lcd_dev;
-			dsim->dsim_lcd_drv = lcd_drv;
-
-			mutex_unlock(&dsim->lock);
-
-			return dsim_ddi;
-		}
-	}
-
-	mutex_unlock(&dsim->lock);
-
-	return NULL;
-}
-
-/* define MIPI-DSI Master operations. */
-static struct mipi_dsim_master_ops master_ops = {
-	.cmd_read			= exynos_mipi_dsi_rd_data,
-	.cmd_write			= exynos_mipi_dsi_wr_data,
-	.get_dsim_frame_done		= exynos_mipi_dsi_get_frame_done_status,
-	.clear_dsim_frame_done		= exynos_mipi_dsi_clear_frame_done,
-	.set_early_blank_mode		= exynos_mipi_dsi_early_blank_mode,
-	.set_blank_mode			= exynos_mipi_dsi_blank_mode,
-};
-
-static int exynos_mipi_dsi_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct mipi_dsim_device *dsim;
-	struct mipi_dsim_config *dsim_config;
-	struct mipi_dsim_platform_data *dsim_pd;
-	struct mipi_dsim_ddi *dsim_ddi;
-	int ret = -EINVAL;
-
-	dsim = devm_kzalloc(&pdev->dev, sizeof(struct mipi_dsim_device),
-				GFP_KERNEL);
-	if (!dsim) {
-		dev_err(&pdev->dev, "failed to allocate dsim object.\n");
-		return -ENOMEM;
-	}
-
-	dsim->pd = to_dsim_plat(pdev);
-	dsim->dev = &pdev->dev;
-	dsim->id = pdev->id;
-
-	/* get mipi_dsim_platform_data. */
-	dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
-	if (dsim_pd == NULL) {
-		dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
-		return -EINVAL;
-	}
-	/* get mipi_dsim_config. */
-	dsim_config = dsim_pd->dsim_config;
-	if (dsim_config == NULL) {
-		dev_err(&pdev->dev, "failed to get dsim config data.\n");
-		return -EINVAL;
-	}
-
-	dsim->dsim_config = dsim_config;
-	dsim->master_ops = &master_ops;
-
-	mutex_init(&dsim->lock);
-
-	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies),
-					supplies);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
-		return ret;
-	}
-
-	dsim->phy = devm_phy_get(&pdev->dev, "dsim");
-	if (IS_ERR(dsim->phy))
-		return PTR_ERR(dsim->phy);
-
-	dsim->clock = devm_clk_get(&pdev->dev, "dsim0");
-	if (IS_ERR(dsim->clock)) {
-		dev_err(&pdev->dev, "failed to get dsim clock source\n");
-		return -ENODEV;
-	}
-
-	clk_enable(dsim->clock);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	dsim->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dsim->reg_base)) {
-		ret = PTR_ERR(dsim->reg_base);
-		goto error;
-	}
-
-	mutex_init(&dsim->lock);
-
-	/* bind lcd ddi matched with panel name. */
-	dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
-	if (!dsim_ddi) {
-		dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
-		ret = -EINVAL;
-		goto error;
-	}
-
-	dsim->irq = platform_get_irq(pdev, 0);
-	if (IS_ERR_VALUE(dsim->irq)) {
-		dev_err(&pdev->dev, "failed to request dsim irq resource\n");
-		ret = -EINVAL;
-		goto error;
-	}
-
-	init_completion(&dsim_wr_comp);
-	init_completion(&dsim_rd_comp);
-	platform_set_drvdata(pdev, dsim);
-
-	ret = devm_request_irq(&pdev->dev, dsim->irq,
-			exynos_mipi_dsi_interrupt_handler,
-			IRQF_SHARED, dev_name(&pdev->dev), dsim);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "failed to request dsim irq\n");
-		ret = -EINVAL;
-		goto error;
-	}
-
-	/* enable interrupts */
-	exynos_mipi_dsi_init_interrupt(dsim);
-
-	/* initialize mipi-dsi client(lcd panel). */
-	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
-		dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
-
-	/* in case mipi-dsi has been enabled by bootloader */
-	if (dsim_pd->enabled) {
-		exynos_mipi_regulator_enable(dsim);
-		goto done;
-	}
-
-	/* lcd panel power on. */
-	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
-		dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
-
-	exynos_mipi_regulator_enable(dsim);
-
-	/* enable MIPI-DSI PHY. */
-	phy_power_on(dsim->phy);
-
-	exynos_mipi_update_cfg(dsim);
-
-	/* set lcd panel sequence commands. */
-	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
-		dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
-
-	dsim->suspended = false;
-
-done:
-	platform_set_drvdata(pdev, dsim);
-
-	dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__,
-		dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB");
-
-	return 0;
-
-error:
-	clk_disable(dsim->clock);
-	return ret;
-}
-
-static int exynos_mipi_dsi_remove(struct platform_device *pdev)
-{
-	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
-	struct mipi_dsim_ddi *dsim_ddi, *next;
-	struct mipi_dsim_lcd_driver *dsim_lcd_drv;
-
-	clk_disable(dsim->clock);
-
-	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
-		if (dsim_ddi) {
-			if (dsim->id != dsim_ddi->bus_id)
-				continue;
-
-			dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
-
-			if (dsim_lcd_drv->remove)
-				dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
-
-			kfree(dsim_ddi);
-		}
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos_mipi_dsi_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
-	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
-	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
-
-	disable_irq(dsim->irq);
-
-	if (dsim->suspended)
-		return 0;
-
-	if (client_drv && client_drv->suspend)
-		client_drv->suspend(client_dev);
-
-	/* disable MIPI-DSI PHY. */
-	phy_power_off(dsim->phy);
-
-	clk_disable(dsim->clock);
-
-	exynos_mipi_regulator_disable(dsim);
-
-	dsim->suspended = true;
-
-	return 0;
-}
-
-static int exynos_mipi_dsi_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
-	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
-	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
-
-	enable_irq(dsim->irq);
-
-	if (!dsim->suspended)
-		return 0;
-
-	/* lcd panel power on. */
-	if (client_drv && client_drv->power_on)
-		client_drv->power_on(client_dev, 1);
-
-	exynos_mipi_regulator_enable(dsim);
-
-	/* enable MIPI-DSI PHY. */
-	phy_power_on(dsim->phy);
-
-	clk_enable(dsim->clock);
-
-	exynos_mipi_update_cfg(dsim);
-
-	/* set lcd panel sequence commands. */
-	if (client_drv && client_drv->set_sequence)
-		client_drv->set_sequence(client_dev);
-
-	dsim->suspended = false;
-
-	return 0;
-}
-#endif
-
-static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume)
-};
-
-static struct platform_driver exynos_mipi_dsi_driver = {
-	.probe = exynos_mipi_dsi_probe,
-	.remove = exynos_mipi_dsi_remove,
-	.driver = {
-		   .name = "exynos-mipi-dsim",
-		   .owner = THIS_MODULE,
-		   .pm = &exynos_mipi_dsi_pm_ops,
-	},
-};
-
-module_platform_driver(exynos_mipi_dsi_driver);
-
-MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
deleted file mode 100644
index 85edabfdef5a..000000000000
--- a/drivers/video/exynos/exynos_mipi_dsi_common.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/* linux/drivers/video/exynos/exynos_mipi_dsi_common.c
- *
- * Samsung SoC MIPI-DSI common driver.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd
- *
- * InKi Dae, <inki.dae@samsung.com>
- * Donghwa Lee, <dh09.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/ctype.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/memory.h>
-#include <linux/delay.h>
-#include <linux/irqreturn.h>
-#include <linux/kthread.h>
-
-#include <video/mipi_display.h>
-#include <video/exynos_mipi_dsim.h>
-
-#include "exynos_mipi_dsi_regs.h"
-#include "exynos_mipi_dsi_lowlevel.h"
-#include "exynos_mipi_dsi_common.h"
-
-#define MIPI_FIFO_TIMEOUT	msecs_to_jiffies(250)
-#define MIPI_RX_FIFO_READ_DONE  0x30800002
-#define MIPI_MAX_RX_FIFO        20
-#define MHZ			(1000 * 1000)
-#define FIN_HZ			(24 * MHZ)
-
-#define DFIN_PLL_MIN_HZ		(6 * MHZ)
-#define DFIN_PLL_MAX_HZ		(12 * MHZ)
-
-#define DFVCO_MIN_HZ		(500 * MHZ)
-#define DFVCO_MAX_HZ		(1000 * MHZ)
-
-#define TRY_GET_FIFO_TIMEOUT	(5000 * 2)
-#define TRY_FIFO_CLEAR		(10)
-
-/* MIPI-DSIM status types. */
-enum {
-	DSIM_STATE_INIT,	/* should be initialized. */
-	DSIM_STATE_STOP,	/* CPU and LCDC are LP mode. */
-	DSIM_STATE_HSCLKEN,	/* HS clock was enabled. */
-	DSIM_STATE_ULPS
-};
-
-/* define DSI lane types. */
-enum {
-	DSIM_LANE_CLOCK = (1 << 0),
-	DSIM_LANE_DATA0 = (1 << 1),
-	DSIM_LANE_DATA1 = (1 << 2),
-	DSIM_LANE_DATA2 = (1 << 3),
-	DSIM_LANE_DATA3 = (1 << 4)
-};
-
-static unsigned int dpll_table[15] = {
-	100, 120, 170, 220, 270,
-	320, 390, 450, 510, 560,
-	640, 690, 770, 870, 950
-};
-
-irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
-{
-	struct mipi_dsim_device *dsim = dev_id;
-	unsigned int intsrc, intmsk;
-
-	intsrc = exynos_mipi_dsi_read_interrupt(dsim);
-	intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
-	intmsk = ~intmsk & intsrc;
-
-	if (intsrc & INTMSK_RX_DONE) {
-		complete(&dsim_rd_comp);
-		dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n");
-	}
-	if (intsrc & INTMSK_FIFO_EMPTY) {
-		complete(&dsim_wr_comp);
-		dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n");
-	}
-
-	exynos_mipi_dsi_clear_interrupt(dsim, intmsk);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * write long packet to mipi dsi slave
- * @dsim: mipi dsim device structure.
- * @data0: packet data to send.
- * @data1: size of packet data
- */
-static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim,
-		const unsigned char *data0, unsigned int data_size)
-{
-	unsigned int data_cnt = 0, payload = 0;
-
-	/* in case that data count is more then 4 */
-	for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
-		/*
-		 * after sending 4bytes per one time,
-		 * send remainder data less then 4.
-		 */
-		if ((data_size - data_cnt) < 4) {
-			if ((data_size - data_cnt) == 3) {
-				payload = data0[data_cnt] |
-				    data0[data_cnt + 1] << 8 |
-					data0[data_cnt + 2] << 16;
-			dev_dbg(dsim->dev, "count = 3 payload = %x, %x %x %x\n",
-				payload, data0[data_cnt],
-				data0[data_cnt + 1],
-				data0[data_cnt + 2]);
-			} else if ((data_size - data_cnt) == 2) {
-				payload = data0[data_cnt] |
-					data0[data_cnt + 1] << 8;
-			dev_dbg(dsim->dev,
-				"count = 2 payload = %x, %x %x\n", payload,
-				data0[data_cnt],
-				data0[data_cnt + 1]);
-			} else if ((data_size - data_cnt) == 1) {
-				payload = data0[data_cnt];
-			}
-
-			exynos_mipi_dsi_wr_tx_data(dsim, payload);
-		/* send 4bytes per one time. */
-		} else {
-			payload = data0[data_cnt] |
-				data0[data_cnt + 1] << 8 |
-				data0[data_cnt + 2] << 16 |
-				data0[data_cnt + 3] << 24;
-
-			dev_dbg(dsim->dev,
-				"count = 4 payload = %x, %x %x %x %x\n",
-				payload, *(u8 *)(data0 + data_cnt),
-				data0[data_cnt + 1],
-				data0[data_cnt + 2],
-				data0[data_cnt + 3]);
-
-			exynos_mipi_dsi_wr_tx_data(dsim, payload);
-		}
-	}
-}
-
-int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
-	const unsigned char *data0, unsigned int data_size)
-{
-	unsigned int check_rx_ack = 0;
-
-	if (dsim->state == DSIM_STATE_ULPS) {
-		dev_err(dsim->dev, "state is ULPS.\n");
-
-		return -EINVAL;
-	}
-
-	/* FIXME!!! why does it need this delay? */
-	msleep(20);
-
-	mutex_lock(&dsim->lock);
-
-	switch (data_id) {
-	/* short packet types of packet types for command. */
-	case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
-	case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
-	case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
-	case MIPI_DSI_DCS_SHORT_WRITE:
-	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
-	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
-		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
-		if (check_rx_ack) {
-			/* process response func should be implemented */
-			mutex_unlock(&dsim->lock);
-			return 0;
-		} else {
-			mutex_unlock(&dsim->lock);
-			return -EINVAL;
-		}
-
-	/* general command */
-	case MIPI_DSI_COLOR_MODE_OFF:
-	case MIPI_DSI_COLOR_MODE_ON:
-	case MIPI_DSI_SHUTDOWN_PERIPHERAL:
-	case MIPI_DSI_TURN_ON_PERIPHERAL:
-		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
-		if (check_rx_ack) {
-			/* process response func should be implemented. */
-			mutex_unlock(&dsim->lock);
-			return 0;
-		} else {
-			mutex_unlock(&dsim->lock);
-			return -EINVAL;
-		}
-
-	/* packet types for video data */
-	case MIPI_DSI_V_SYNC_START:
-	case MIPI_DSI_V_SYNC_END:
-	case MIPI_DSI_H_SYNC_START:
-	case MIPI_DSI_H_SYNC_END:
-	case MIPI_DSI_END_OF_TRANSMISSION:
-		mutex_unlock(&dsim->lock);
-		return 0;
-
-	/* long packet type and null packet */
-	case MIPI_DSI_NULL_PACKET:
-	case MIPI_DSI_BLANKING_PACKET:
-		mutex_unlock(&dsim->lock);
-		return 0;
-	case MIPI_DSI_GENERIC_LONG_WRITE:
-	case MIPI_DSI_DCS_LONG_WRITE:
-	{
-		unsigned int size, payload = 0;
-		reinit_completion(&dsim_wr_comp);
-
-		size = data_size * 4;
-
-		/* if data count is less then 4, then send 3bytes data.  */
-		if (data_size < 4) {
-			payload = data0[0] |
-				data0[1] << 8 |
-				data0[2] << 16;
-
-			exynos_mipi_dsi_wr_tx_data(dsim, payload);
-
-			dev_dbg(dsim->dev, "count = %d payload = %x,%x %x %x\n",
-				data_size, payload, data0[0],
-				data0[1], data0[2]);
-
-		/* in case that data count is more then 4 */
-		} else
-			exynos_mipi_dsi_long_data_wr(dsim, data0, data_size);
-
-		/* put data into header fifo */
-		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data_size & 0xff,
-			(data_size & 0xff00) >> 8);
-
-		if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp,
-							MIPI_FIFO_TIMEOUT)) {
-			dev_warn(dsim->dev, "command write timeout.\n");
-			mutex_unlock(&dsim->lock);
-			return -EAGAIN;
-		}
-
-		if (check_rx_ack) {
-			/* process response func should be implemented. */
-			mutex_unlock(&dsim->lock);
-			return 0;
-		} else {
-			mutex_unlock(&dsim->lock);
-			return -EINVAL;
-		}
-	}
-
-	/* packet typo for video data */
-	case MIPI_DSI_PACKED_PIXEL_STREAM_16:
-	case MIPI_DSI_PACKED_PIXEL_STREAM_18:
-	case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
-	case MIPI_DSI_PACKED_PIXEL_STREAM_24:
-		if (check_rx_ack) {
-			/* process response func should be implemented. */
-			mutex_unlock(&dsim->lock);
-			return 0;
-		} else {
-			mutex_unlock(&dsim->lock);
-			return -EINVAL;
-		}
-	default:
-		dev_warn(dsim->dev,
-			"data id %x is not supported current DSI spec.\n",
-			data_id);
-
-		mutex_unlock(&dsim->lock);
-		return -EINVAL;
-	}
-}
-
-static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
-		unsigned int req_size, unsigned int rx_data, u8 *rx_buf)
-{
-	unsigned int rcv_pkt, i, j;
-	u16 rxsize;
-
-	/* for long packet */
-	rxsize = (u16)((rx_data & 0x00ffff00) >> 8);
-	dev_dbg(dsim->dev, "mipi dsi rx size : %d\n", rxsize);
-	if (rxsize != req_size) {
-		dev_dbg(dsim->dev,
-			"received size mismatch received: %d, requested: %d\n",
-			rxsize, req_size);
-		goto err;
-	}
-
-	for (i = 0; i < (rxsize >> 2); i++) {
-		rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
-		dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
-		for (j = 0; j < 4; j++) {
-			rx_buf[(i * 4) + j] =
-					(u8)(rcv_pkt >> (j * 8)) & 0xff;
-			dev_dbg(dsim->dev, "received value : %02x\n",
-					(rcv_pkt >> (j * 8)) & 0xff);
-		}
-	}
-	if (rxsize % 4) {
-		rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
-		dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
-		for (j = 0; j < (rxsize % 4); j++) {
-			rx_buf[(i * 4) + j] =
-					(u8)(rcv_pkt >> (j * 8)) & 0xff;
-			dev_dbg(dsim->dev, "received value : %02x\n",
-					(rcv_pkt >> (j * 8)) & 0xff);
-		}
-	}
-
-	return rxsize;
-
-err:
-	return -EINVAL;
-}
-
-static unsigned int exynos_mipi_dsi_response_size(unsigned int req_size)
-{
-	switch (req_size) {
-	case 1:
-		return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE;
-	case 2:
-		return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE;
-	default:
-		return MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE;
-	}
-}
-
-int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
-	unsigned int data0, unsigned int req_size, u8 *rx_buf)
-{
-	unsigned int rx_data, rcv_pkt, i;
-	u8 response = 0;
-	u16 rxsize;
-
-	if (dsim->state == DSIM_STATE_ULPS) {
-		dev_err(dsim->dev, "state is ULPS.\n");
-
-		return -EINVAL;
-	}
-
-	/* FIXME!!! */
-	msleep(20);
-
-	mutex_lock(&dsim->lock);
-	reinit_completion(&dsim_rd_comp);
-	exynos_mipi_dsi_rd_tx_header(dsim,
-		MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, req_size);
-
-	response = exynos_mipi_dsi_response_size(req_size);
-
-	switch (data_id) {
-	case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
-	case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
-	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
-	case MIPI_DSI_DCS_READ:
-		exynos_mipi_dsi_rd_tx_header(dsim,
-			data_id, data0);
-		/* process response func should be implemented. */
-		break;
-	default:
-		dev_warn(dsim->dev,
-			"data id %x is not supported current DSI spec.\n",
-			data_id);
-
-		mutex_unlock(&dsim->lock);
-		return -EINVAL;
-	}
-
-	if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp,
-				MIPI_FIFO_TIMEOUT)) {
-		pr_err("RX done interrupt timeout\n");
-		mutex_unlock(&dsim->lock);
-		return 0;
-	}
-
-	msleep(20);
-
-	rx_data = exynos_mipi_dsi_rd_rx_fifo(dsim);
-
-	if ((u8)(rx_data & 0xff) != response) {
-		printk(KERN_ERR
-			"mipi dsi wrong response rx_data : %x, response:%x\n",
-			rx_data, response);
-		goto clear_rx_fifo;
-	}
-
-	if (req_size <= 2) {
-		/* for short packet */
-		for (i = 0; i < req_size; i++)
-			rx_buf[i] = (rx_data >> (8 + (i * 8))) & 0xff;
-		rxsize = req_size;
-	} else {
-		/* for long packet */
-		rxsize = exynos_mipi_dsi_long_data_rd(dsim, req_size, rx_data,
-							rx_buf);
-		if (rxsize != req_size)
-			goto clear_rx_fifo;
-	}
-
-	rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
-
-	msleep(20);
-
-	if (rcv_pkt != MIPI_RX_FIFO_READ_DONE) {
-		dev_info(dsim->dev,
-			"Can't found RX FIFO READ DONE FLAG : %x\n", rcv_pkt);
-		goto clear_rx_fifo;
-	}
-
-	mutex_unlock(&dsim->lock);
-
-	return rxsize;
-
-clear_rx_fifo:
-	i = 0;
-	while (1) {
-		rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
-		if ((rcv_pkt == MIPI_RX_FIFO_READ_DONE)
-				|| (i > MIPI_MAX_RX_FIFO))
-			break;
-		dev_dbg(dsim->dev,
-				"mipi dsi clear rx fifo : %08x\n", rcv_pkt);
-		i++;
-	}
-	dev_info(dsim->dev,
-		"mipi dsi rx done count : %d, rcv_pkt : %08x\n", i, rcv_pkt);
-
-	mutex_unlock(&dsim->lock);
-
-	return 0;
-}
-
-static int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim,
-				unsigned int enable)
-{
-	int sw_timeout;
-
-	if (enable) {
-		sw_timeout = 1000;
-
-		exynos_mipi_dsi_enable_pll(dsim, 1);
-		while (1) {
-			sw_timeout--;
-			if (exynos_mipi_dsi_is_pll_stable(dsim))
-				return 0;
-			if (sw_timeout == 0)
-				return -EINVAL;
-		}
-	} else
-		exynos_mipi_dsi_enable_pll(dsim, 0);
-
-	return 0;
-}
-
-static unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim,
-	unsigned int pre_divider, unsigned int main_divider,
-	unsigned int scaler)
-{
-	unsigned long dfin_pll, dfvco, dpll_out;
-	unsigned int i, freq_band = 0xf;
-
-	dfin_pll = (FIN_HZ / pre_divider);
-
-	/******************************************************
-	 *	Serial Clock(=ByteClk X 8)	FreqBand[3:0] *
-	 ******************************************************
-	 *	~ 99.99 MHz			0000
-	 *	100 ~ 119.99 MHz		0001
-	 *	120 ~ 159.99 MHz		0010
-	 *	160 ~ 199.99 MHz		0011
-	 *	200 ~ 239.99 MHz		0100
-	 *	140 ~ 319.99 MHz		0101
-	 *	320 ~ 389.99 MHz		0110
-	 *	390 ~ 449.99 MHz		0111
-	 *	450 ~ 509.99 MHz		1000
-	 *	510 ~ 559.99 MHz		1001
-	 *	560 ~ 639.99 MHz		1010
-	 *	640 ~ 689.99 MHz		1011
-	 *	690 ~ 769.99 MHz		1100
-	 *	770 ~ 869.99 MHz		1101
-	 *	870 ~ 949.99 MHz		1110
-	 *	950 ~ 1000 MHz			1111
-	 ******************************************************/
-	if (dfin_pll < DFIN_PLL_MIN_HZ || dfin_pll > DFIN_PLL_MAX_HZ) {
-		dev_warn(dsim->dev, "fin_pll range should be 6MHz ~ 12MHz\n");
-		exynos_mipi_dsi_enable_afc(dsim, 0, 0);
-	} else {
-		if (dfin_pll < 7 * MHZ)
-			exynos_mipi_dsi_enable_afc(dsim, 1, 0x1);
-		else if (dfin_pll < 8 * MHZ)
-			exynos_mipi_dsi_enable_afc(dsim, 1, 0x0);
-		else if (dfin_pll < 9 * MHZ)
-			exynos_mipi_dsi_enable_afc(dsim, 1, 0x3);
-		else if (dfin_pll < 10 * MHZ)
-			exynos_mipi_dsi_enable_afc(dsim, 1, 0x2);
-		else if (dfin_pll < 11 * MHZ)
-			exynos_mipi_dsi_enable_afc(dsim, 1, 0x5);
-		else
-			exynos_mipi_dsi_enable_afc(dsim, 1, 0x4);
-	}
-
-	dfvco = dfin_pll * main_divider;
-	dev_dbg(dsim->dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n",
-				dfvco, dfin_pll, main_divider);
-	if (dfvco < DFVCO_MIN_HZ || dfvco > DFVCO_MAX_HZ)
-		dev_warn(dsim->dev, "fvco range should be 500MHz ~ 1000MHz\n");
-
-	dpll_out = dfvco / (1 << scaler);
-	dev_dbg(dsim->dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n",
-		dpll_out, dfvco, scaler);
-
-	for (i = 0; i < ARRAY_SIZE(dpll_table); i++) {
-		if (dpll_out < dpll_table[i] * MHZ) {
-			freq_band = i;
-			break;
-		}
-	}
-
-	dev_dbg(dsim->dev, "freq_band = %d\n", freq_band);
-
-	exynos_mipi_dsi_pll_freq(dsim, pre_divider, main_divider, scaler);
-
-	exynos_mipi_dsi_hs_zero_ctrl(dsim, 0);
-	exynos_mipi_dsi_prep_ctrl(dsim, 0);
-
-	/* Freq Band */
-	exynos_mipi_dsi_pll_freq_band(dsim, freq_band);
-
-	/* Stable time */
-	exynos_mipi_dsi_pll_stable_time(dsim, dsim->dsim_config->pll_stable_time);
-
-	/* Enable PLL */
-	dev_dbg(dsim->dev, "FOUT of mipi dphy pll is %luMHz\n",
-		(dpll_out / MHZ));
-
-	return dpll_out;
-}
-
-static int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim,
-	unsigned int byte_clk_sel, unsigned int enable)
-{
-	unsigned int esc_div;
-	unsigned long esc_clk_error_rate;
-	unsigned long hs_clk = 0, byte_clk = 0, escape_clk = 0;
-
-	if (enable) {
-		dsim->e_clk_src = byte_clk_sel;
-
-		/* Escape mode clock and byte clock source */
-		exynos_mipi_dsi_set_byte_clock_src(dsim, byte_clk_sel);
-
-		/* DPHY, DSIM Link : D-PHY clock out */
-		if (byte_clk_sel == DSIM_PLL_OUT_DIV8) {
-			hs_clk = exynos_mipi_dsi_change_pll(dsim,
-				dsim->dsim_config->p, dsim->dsim_config->m,
-				dsim->dsim_config->s);
-			if (hs_clk == 0) {
-				dev_err(dsim->dev,
-					"failed to get hs clock.\n");
-				return -EINVAL;
-			}
-
-			byte_clk = hs_clk / 8;
-			exynos_mipi_dsi_enable_pll_bypass(dsim, 0);
-			exynos_mipi_dsi_pll_on(dsim, 1);
-		/* DPHY : D-PHY clock out, DSIM link : external clock out */
-		} else if (byte_clk_sel == DSIM_EXT_CLK_DIV8) {
-			dev_warn(dsim->dev, "this project is not support\n");
-			dev_warn(dsim->dev,
-				"external clock source for MIPI DSIM.\n");
-		} else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS) {
-			dev_warn(dsim->dev, "this project is not support\n");
-			dev_warn(dsim->dev,
-				"external clock source for MIPI DSIM\n");
-		}
-
-		/* escape clock divider */
-		esc_div = byte_clk / (dsim->dsim_config->esc_clk);
-		dev_dbg(dsim->dev,
-			"esc_div = %d, byte_clk = %lu, esc_clk = %lu\n",
-			esc_div, byte_clk, dsim->dsim_config->esc_clk);
-		if ((byte_clk / esc_div) >= (20 * MHZ) ||
-				(byte_clk / esc_div) >
-					dsim->dsim_config->esc_clk)
-			esc_div += 1;
-
-		escape_clk = byte_clk / esc_div;
-		dev_dbg(dsim->dev,
-			"escape_clk = %lu, byte_clk = %lu, esc_div = %d\n",
-			escape_clk, byte_clk, esc_div);
-
-		/* enable escape clock. */
-		exynos_mipi_dsi_enable_byte_clock(dsim, 1);
-
-		/* enable byte clk and escape clock */
-		exynos_mipi_dsi_set_esc_clk_prs(dsim, 1, esc_div);
-		/* escape clock on lane */
-		exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
-			(DSIM_LANE_CLOCK | dsim->data_lane), 1);
-
-		dev_dbg(dsim->dev, "byte clock is %luMHz\n",
-			(byte_clk / MHZ));
-		dev_dbg(dsim->dev, "escape clock that user's need is %lu\n",
-			(dsim->dsim_config->esc_clk / MHZ));
-		dev_dbg(dsim->dev, "escape clock divider is %x\n", esc_div);
-		dev_dbg(dsim->dev, "escape clock is %luMHz\n",
-			((byte_clk / esc_div) / MHZ));
-
-		if ((byte_clk / esc_div) > escape_clk) {
-			esc_clk_error_rate = escape_clk /
-				(byte_clk / esc_div);
-			dev_warn(dsim->dev, "error rate is %lu over.\n",
-				(esc_clk_error_rate / 100));
-		} else if ((byte_clk / esc_div) < (escape_clk)) {
-			esc_clk_error_rate = (byte_clk / esc_div) /
-				escape_clk;
-			dev_warn(dsim->dev, "error rate is %lu under.\n",
-				(esc_clk_error_rate / 100));
-		}
-	} else {
-		exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
-			(DSIM_LANE_CLOCK | dsim->data_lane), 0);
-		exynos_mipi_dsi_set_esc_clk_prs(dsim, 0, 0);
-
-		/* disable escape clock. */
-		exynos_mipi_dsi_enable_byte_clock(dsim, 0);
-
-		if (byte_clk_sel == DSIM_PLL_OUT_DIV8)
-			exynos_mipi_dsi_pll_on(dsim, 0);
-	}
-
-	return 0;
-}
-
-int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim)
-{
-	dsim->state = DSIM_STATE_INIT;
-
-	switch (dsim->dsim_config->e_no_data_lane) {
-	case DSIM_DATA_LANE_1:
-		dsim->data_lane = DSIM_LANE_DATA0;
-		break;
-	case DSIM_DATA_LANE_2:
-		dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1;
-		break;
-	case DSIM_DATA_LANE_3:
-		dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
-			DSIM_LANE_DATA2;
-		break;
-	case DSIM_DATA_LANE_4:
-		dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
-			DSIM_LANE_DATA2 | DSIM_LANE_DATA3;
-		break;
-	default:
-		dev_info(dsim->dev, "data lane is invalid.\n");
-		return -EINVAL;
-	}
-
-	exynos_mipi_dsi_sw_reset(dsim);
-	exynos_mipi_dsi_func_reset(dsim);
-
-	exynos_mipi_dsi_dp_dn_swap(dsim, 0);
-
-	return 0;
-}
-
-void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim)
-{
-	unsigned int src = 0;
-
-	src = (INTSRC_SFR_FIFO_EMPTY | INTSRC_RX_DATA_DONE);
-	exynos_mipi_dsi_set_interrupt(dsim, src, 1);
-
-	src = 0;
-	src = ~(INTMSK_RX_DONE | INTMSK_FIFO_EMPTY);
-	exynos_mipi_dsi_set_interrupt_mask(dsim, src, 1);
-}
-
-int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
-	unsigned int enable)
-{
-	/* enable only frame done interrupt */
-	exynos_mipi_dsi_set_interrupt_mask(dsim, INTMSK_FRAME_DONE, enable);
-
-	return 0;
-}
-
-void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
-		unsigned int enable)
-{
-
-	/* consider Main display and Sub display. */
-
-	exynos_mipi_dsi_set_main_stand_by(dsim, enable);
-}
-
-int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
-	struct mipi_dsim_config *dsim_config)
-{
-	struct mipi_dsim_platform_data *dsim_pd;
-	struct fb_videomode *timing;
-
-	dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
-	timing = (struct fb_videomode *)dsim_pd->lcd_panel_info;
-
-	/* in case of VIDEO MODE (RGB INTERFACE), it sets polarities. */
-	if (dsim_config->e_interface == (u32) DSIM_VIDEO) {
-		if (dsim_config->auto_vertical_cnt == 0) {
-			exynos_mipi_dsi_set_main_disp_vporch(dsim,
-				dsim_config->cmd_allow,
-				timing->lower_margin,
-				timing->upper_margin);
-			exynos_mipi_dsi_set_main_disp_hporch(dsim,
-				timing->right_margin,
-				timing->left_margin);
-			exynos_mipi_dsi_set_main_disp_sync_area(dsim,
-				timing->vsync_len,
-				timing->hsync_len);
-		}
-	}
-
-	exynos_mipi_dsi_set_main_disp_resol(dsim, timing->xres,
-			timing->yres);
-
-	exynos_mipi_dsi_display_config(dsim, dsim_config);
-
-	dev_info(dsim->dev, "lcd panel ==> width = %d, height = %d\n",
-			timing->xres, timing->yres);
-
-	return 0;
-}
-
-int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim)
-{
-	unsigned int time_out = 100;
-
-	switch (dsim->state) {
-	case DSIM_STATE_INIT:
-		exynos_mipi_dsi_init_fifo_pointer(dsim, 0x1f);
-
-		/* dsi configuration */
-		exynos_mipi_dsi_init_config(dsim);
-		exynos_mipi_dsi_enable_lane(dsim, DSIM_LANE_CLOCK, 1);
-		exynos_mipi_dsi_enable_lane(dsim, dsim->data_lane, 1);
-
-		/* set clock configuration */
-		exynos_mipi_dsi_set_clock(dsim, dsim->dsim_config->e_byte_clk, 1);
-
-		/* check clock and data lane state are stop state */
-		while (!(exynos_mipi_dsi_is_lane_state(dsim))) {
-			time_out--;
-			if (time_out == 0) {
-				dev_err(dsim->dev,
-					"DSI Master is not stop state.\n");
-				dev_err(dsim->dev,
-					"Check initialization process\n");
-
-				return -EINVAL;
-			}
-		}
-		if (time_out != 0) {
-			dev_info(dsim->dev,
-				"DSI Master driver has been completed.\n");
-			dev_info(dsim->dev, "DSI Master state is stop state\n");
-		}
-
-		dsim->state = DSIM_STATE_STOP;
-
-		/* BTA sequence counters */
-		exynos_mipi_dsi_set_stop_state_counter(dsim,
-			dsim->dsim_config->stop_holding_cnt);
-		exynos_mipi_dsi_set_bta_timeout(dsim,
-			dsim->dsim_config->bta_timeout);
-		exynos_mipi_dsi_set_lpdr_timeout(dsim,
-			dsim->dsim_config->rx_timeout);
-
-		return 0;
-	default:
-		dev_info(dsim->dev, "DSI Master is already init.\n");
-		return 0;
-	}
-
-	return 0;
-}
-
-int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim)
-{
-	if (dsim->state != DSIM_STATE_STOP) {
-		dev_warn(dsim->dev, "DSIM is not in stop state.\n");
-		return 0;
-	}
-
-	if (dsim->e_clk_src == DSIM_EXT_CLK_BYPASS) {
-		dev_warn(dsim->dev, "clock source is external bypass.\n");
-		return 0;
-	}
-
-	dsim->state = DSIM_STATE_HSCLKEN;
-
-	 /* set LCDC and CPU transfer mode to HS. */
-	exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
-	exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
-	exynos_mipi_dsi_enable_hs_clock(dsim, 1);
-
-	return 0;
-}
-
-int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
-		unsigned int mode)
-{
-	if (mode) {
-		if (dsim->state != DSIM_STATE_HSCLKEN) {
-			dev_err(dsim->dev, "HS Clock lane is not enabled.\n");
-			return -EINVAL;
-		}
-
-		exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
-	} else {
-		if (dsim->state == DSIM_STATE_INIT || dsim->state ==
-			DSIM_STATE_ULPS) {
-			dev_err(dsim->dev,
-				"DSI Master is not STOP or HSDT state.\n");
-			return -EINVAL;
-		}
-
-		exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
-	}
-
-	return 0;
-}
-
-int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
-{
-	return _exynos_mipi_dsi_get_frame_done_status(dsim);
-}
-
-int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
-{
-	_exynos_mipi_dsi_clear_frame_done(dsim);
-
-	return 0;
-}
-
-int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
-				unsigned int val)
-{
-	int try = TRY_FIFO_CLEAR;
-
-	exynos_mipi_dsi_sw_reset_release(dsim);
-	exynos_mipi_dsi_func_reset(dsim);
-
-	do {
-		if (exynos_mipi_dsi_get_sw_reset_release(dsim)) {
-			exynos_mipi_dsi_init_interrupt(dsim);
-			dev_dbg(dsim->dev, "reset release done.\n");
-			return 0;
-		}
-	} while (--try);
-
-	dev_err(dsim->dev, "failed to clear dsim fifo.\n");
-	return -EAGAIN;
-}
-
-MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("Samusung SoC MIPI-DSI common driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.h b/drivers/video/exynos/exynos_mipi_dsi_common.h
deleted file mode 100644
index 412552274df3..000000000000
--- a/drivers/video/exynos/exynos_mipi_dsi_common.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* linux/drivers/video/exynos_mipi_dsi_common.h
- *
- * Header file for Samsung SoC MIPI-DSI common driver.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd
- *
- * InKi Dae <inki.dae@samsung.com>
- * Donghwa Lee <dh09.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef _EXYNOS_MIPI_DSI_COMMON_H
-#define _EXYNOS_MIPI_DSI_COMMON_H
-
-static DECLARE_COMPLETION(dsim_rd_comp);
-static DECLARE_COMPLETION(dsim_wr_comp);
-
-int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
-	const unsigned char *data0, unsigned int data_size);
-int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
-	unsigned int data0, unsigned int req_size, u8 *rx_buf);
-irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id);
-void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim);
-int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
-		unsigned int enable);
-int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
-			struct mipi_dsim_config *dsim_info);
-int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim);
-int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim);
-int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
-		unsigned int mode);
-int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
-	unsigned int enable);
-int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
-int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
-
-extern struct fb_info *registered_fb[FB_MAX] __read_mostly;
-
-int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
-				unsigned int val);
-
-#endif /* _EXYNOS_MIPI_DSI_COMMON_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
deleted file mode 100644
index c148d06540c1..000000000000
--- a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
- *
- * Samsung SoC MIPI-DSI lowlevel driver.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd
- *
- * InKi Dae, <inki.dae@samsung.com>
- * Donghwa Lee, <dh09.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/ctype.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <video/exynos_mipi_dsim.h>
-
-#include "exynos_mipi_dsi_regs.h"
-#include "exynos_mipi_dsi_lowlevel.h"
-
-void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
-
-	reg |= DSIM_FUNCRST;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
-}
-
-void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
-
-	reg |= DSIM_SWRST;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
-}
-
-void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
-
-	reg |= INTSRC_SW_RST_RELEASE;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
-}
-
-int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim)
-{
-	return (readl(dsim->reg_base + EXYNOS_DSIM_INTSRC)) &
-			INTSRC_SW_RST_RELEASE;
-}
-
-unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_INTMSK);
-
-	return reg;
-}
-
-void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
-		unsigned int mode, unsigned int mask)
-{
-	unsigned int reg = 0;
-
-	if (mask)
-		reg |= mode;
-	else
-		reg &= ~mode;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTMSK);
-}
-
-void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
-		unsigned int cfg)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
-
-	writel(reg & ~(cfg), dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
-	mdelay(10);
-	reg |= cfg;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
-}
-
-/*
- * this function set PLL P, M and S value in D-PHY
- */
-void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
-		unsigned int value)
-{
-	writel(DSIM_AFC_CTL(value), dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
-}
-
-void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
-		unsigned int enable)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL);
-
-	reg &= ~DSIM_MAIN_STAND_BY;
-
-	if (enable)
-		reg |= DSIM_MAIN_STAND_BY;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
-}
-
-void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
-	unsigned int width_resol, unsigned int height_resol)
-{
-	unsigned int reg;
-
-	/* standby should be set after configuration so set to not ready*/
-	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL)) &
-		~(DSIM_MAIN_STAND_BY);
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
-
-	reg &= ~((0x7ff << 16) | (0x7ff << 0));
-	reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol);
-
-	reg |= DSIM_MAIN_STAND_BY;
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
-}
-
-void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
-	unsigned int cmd_allow, unsigned int vfront, unsigned int vback)
-{
-	unsigned int reg;
-
-	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MVPORCH)) &
-		~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) |
-		(DSIM_MAIN_VBP_MASK));
-
-	reg |= (DSIM_CMD_ALLOW_SHIFT(cmd_allow & 0xf) |
-		DSIM_STABLE_VFP_SHIFT(vfront & 0x7ff) |
-		DSIM_MAIN_VBP_SHIFT(vback & 0x7ff));
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_MVPORCH);
-}
-
-void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
-	unsigned int front, unsigned int back)
-{
-	unsigned int reg;
-
-	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MHPORCH)) &
-		~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK));
-
-	reg |= DSIM_MAIN_HFP_SHIFT(front) | DSIM_MAIN_HBP_SHIFT(back);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_MHPORCH);
-}
-
-void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
-	unsigned int vert, unsigned int hori)
-{
-	unsigned int reg;
-
-	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MSYNC)) &
-		~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK));
-
-	reg |= (DSIM_MAIN_VSA_SHIFT(vert & 0x3ff) |
-		DSIM_MAIN_HSA_SHIFT(hori));
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_MSYNC);
-}
-
-void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
-	unsigned int vert, unsigned int hori)
-{
-	unsigned int reg;
-
-	reg = (readl(dsim->reg_base + EXYNOS_DSIM_SDRESOL)) &
-		~(DSIM_SUB_STANDY_MASK);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
-
-	reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK);
-	reg |= (DSIM_SUB_VRESOL_SHIFT(vert & 0x7ff) |
-		DSIM_SUB_HRESOL_SHIFT(hori & 0x7ff));
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
-
-	reg |= DSIM_SUB_STANDY_SHIFT(1);
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
-}
-
-void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim)
-{
-	struct mipi_dsim_config *dsim_config = dsim->dsim_config;
-
-	unsigned int cfg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
-		~((1 << 28) | (0x1f << 20) | (0x3 << 5));
-
-	cfg =	((DSIM_AUTO_FLUSH(dsim_config->auto_flush)) |
-		(DSIM_EOT_DISABLE(dsim_config->eot_disable)) |
-		(DSIM_AUTO_MODE_SHIFT(dsim_config->auto_vertical_cnt)) |
-		(DSIM_HSE_MODE_SHIFT(dsim_config->hse)) |
-		(DSIM_HFP_MODE_SHIFT(dsim_config->hfp)) |
-		(DSIM_HBP_MODE_SHIFT(dsim_config->hbp)) |
-		(DSIM_HSA_MODE_SHIFT(dsim_config->hsa)) |
-		(DSIM_NUM_OF_DATALANE_SHIFT(dsim_config->e_no_data_lane)));
-
-	writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
-}
-
-void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
-				struct mipi_dsim_config *dsim_config)
-{
-	u32 reg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
-		~((0x3 << 26) | (1 << 25) | (0x3 << 18) | (0x7 << 12) |
-		(0x3 << 16) | (0x7 << 8));
-
-	if (dsim_config->e_interface == DSIM_VIDEO)
-		reg |= (1 << 25);
-	else if (dsim_config->e_interface == DSIM_COMMAND)
-		reg &= ~(1 << 25);
-	else {
-		dev_err(dsim->dev, "unknown lcd type.\n");
-		return;
-	}
-
-	/* main lcd */
-	reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << 26 |
-		((u8) (dsim_config->e_virtual_ch) & 0x3) << 18 |
-		((u8) (dsim_config->e_pixel_format) & 0x7) << 12;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
-}
-
-void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
-	unsigned int enable)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_CONFIG);
-
-	if (enable)
-		reg |= DSIM_LANE_ENx(lane);
-	else
-		reg &= ~DSIM_LANE_ENx(lane);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
-}
-
-
-void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
-	unsigned int count)
-{
-	unsigned int cfg;
-
-	/* get the data lane number. */
-	cfg = DSIM_NUM_OF_DATALANE_SHIFT(count);
-
-	writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
-}
-
-void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
-	unsigned int afc_code)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
-
-	if (enable) {
-		reg |= (1 << 14);
-		reg &= ~(0x7 << 5);
-		reg |= (afc_code & 0x7) << 5;
-	} else
-		reg &= ~(1 << 14);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
-}
-
-void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
-	unsigned int enable)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
-		~(DSIM_PLL_BYPASS_SHIFT(0x1));
-
-	reg |= DSIM_PLL_BYPASS_SHIFT(enable);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
-}
-
-void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
-	unsigned int m, unsigned int s)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
-
-	reg |= ((p & 0x3f) << 13) | ((m & 0x1ff) << 4) | ((s & 0x7) << 1);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
-}
-
-void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
-		unsigned int freq_band)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
-		~(DSIM_FREQ_BAND_SHIFT(0x1f));
-
-	reg |= DSIM_FREQ_BAND_SHIFT(freq_band & 0x1f);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
-}
-
-void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
-		unsigned int pre_divider, unsigned int main_divider,
-		unsigned int scaler)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
-		~(0x7ffff << 1);
-
-	reg |= (pre_divider & 0x3f) << 13 | (main_divider & 0x1ff) << 4 |
-		(scaler & 0x7) << 1;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
-}
-
-void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
-	unsigned int lock_time)
-{
-	writel(lock_time, dsim->reg_base + EXYNOS_DSIM_PLLTMR);
-}
-
-void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, unsigned int enable)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
-		~(DSIM_PLL_EN_SHIFT(0x1));
-
-	reg |= DSIM_PLL_EN_SHIFT(enable & 0x1);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
-}
-
-void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
-		unsigned int src)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
-		~(DSIM_BYTE_CLK_SRC_SHIFT(0x3));
-
-	reg |= (DSIM_BYTE_CLK_SRC_SHIFT(src));
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
-}
-
-void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
-		unsigned int enable)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
-		~(DSIM_BYTE_CLKEN_SHIFT(0x1));
-
-	reg |= DSIM_BYTE_CLKEN_SHIFT(enable);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
-}
-
-void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
-		unsigned int enable, unsigned int prs_val)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
-		~(DSIM_ESC_CLKEN_SHIFT(0x1) | 0xffff);
-
-	reg |= DSIM_ESC_CLKEN_SHIFT(enable);
-	if (enable)
-		reg |= prs_val;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
-}
-
-void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
-		unsigned int lane_sel, unsigned int enable)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
-
-	if (enable)
-		reg |= DSIM_LANE_ESC_CLKEN(lane_sel);
-	else
-
-		reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
-}
-
-void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
-	unsigned int enable)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
-		~(DSIM_FORCE_STOP_STATE_SHIFT(0x1));
-
-	reg |= (DSIM_FORCE_STOP_STATE_SHIFT(enable & 0x1));
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
-}
-
-unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
-
-	/**
-	 * check clock and data lane states.
-	 * if MIPI-DSI controller was enabled at bootloader then
-	 * TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK.
-	 * so it should be checked for two case.
-	 */
-	if ((reg & DSIM_STOP_STATE_DAT(0xf)) &&
-			((reg & DSIM_STOP_STATE_CLK) ||
-			 (reg & DSIM_TX_READY_HS_CLK)))
-		return 1;
-
-	return 0;
-}
-
-void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
-		unsigned int cnt_val)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
-		~(DSIM_STOP_STATE_CNT_SHIFT(0x7ff));
-
-	reg |= (DSIM_STOP_STATE_CNT_SHIFT(cnt_val & 0x7ff));
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
-}
-
-void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
-		unsigned int timeout)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
-		~(DSIM_BTA_TOUT_SHIFT(0xff));
-
-	reg |= (DSIM_BTA_TOUT_SHIFT(timeout));
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
-}
-
-void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
-		unsigned int timeout)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
-		~(DSIM_LPDR_TOUT_SHIFT(0xffff));
-
-	reg |= (DSIM_LPDR_TOUT_SHIFT(timeout));
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
-}
-
-void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
-		unsigned int lp)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
-
-	reg &= ~DSIM_CMD_LPDT_LP;
-
-	if (lp)
-		reg |= DSIM_CMD_LPDT_LP;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
-}
-
-void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
-		unsigned int lp)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
-
-	reg &= ~DSIM_TX_LPDT_LP;
-
-	if (lp)
-		reg |= DSIM_TX_LPDT_LP;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
-}
-
-void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
-		unsigned int enable)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
-		~(DSIM_TX_REQUEST_HSCLK_SHIFT(0x1));
-
-	reg |= DSIM_TX_REQUEST_HSCLK_SHIFT(enable);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
-}
-
-void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
-		unsigned int swap_en)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
-
-	reg &= ~(0x3 << 0);
-	reg |= (swap_en & 0x3) << 0;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
-}
-
-void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
-		unsigned int hs_zero)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
-		~(0xf << 28);
-
-	reg |= ((hs_zero & 0xf) << 28);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
-}
-
-void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep)
-{
-	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
-		~(0x7 << 20);
-
-	reg |= ((prep & 0x7) << 20);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
-}
-
-unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim)
-{
-	return readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
-}
-
-void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
-					unsigned int src)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
-
-	reg |= src;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
-}
-
-void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
-					unsigned int src, unsigned int enable)
-{
-	unsigned int reg = 0;
-
-	if (enable)
-		reg |= src;
-	else
-		reg &= ~src;
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
-}
-
-unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg;
-
-	reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
-
-	return reg & (1 << 31) ? 1 : 0;
-}
-
-unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)
-{
-	return readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL) & ~(0x1f);
-}
-
-void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim,
-	unsigned int di, unsigned int data0, unsigned int data1)
-{
-	unsigned int reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
-}
-
-void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
-	unsigned int di, unsigned int data0)
-{
-	unsigned int reg = (data0 << 8) | (di << 0);
-
-	writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
-}
-
-unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim)
-{
-	return readl(dsim->reg_base + EXYNOS_DSIM_RXFIFO);
-}
-
-unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
-
-	return (reg & INTSRC_FRAME_DONE) ? 1 : 0;
-}
-
-void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
-{
-	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
-
-	writel(reg | INTSRC_FRAME_DONE, dsim->reg_base +
-		EXYNOS_DSIM_INTSRC);
-}
-
-void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
-		unsigned int tx_data)
-{
-	writel(tx_data, dsim->reg_base + EXYNOS_DSIM_PAYLOAD);
-}
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
deleted file mode 100644
index 85460701c7ea..000000000000
--- a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
- *
- * Header file for Samsung SoC MIPI-DSI lowlevel driver.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd
- *
- * InKi Dae <inki.dae@samsung.com>
- * Donghwa Lee <dh09.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H
-#define _EXYNOS_MIPI_DSI_LOWLEVEL_H
-
-void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim);
-int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
-	unsigned int mode, unsigned int mask);
-void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
-					unsigned int count);
-void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
-					unsigned int cfg);
-void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
-				unsigned int value);
-void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
-				unsigned int value);
-void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
-		unsigned int enable);
-void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
-		unsigned int width_resol, unsigned int height_resol);
-void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
-	unsigned int cmd_allow, unsigned int vfront, unsigned int vback);
-void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
-			unsigned int front, unsigned int back);
-void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
-				unsigned int vert, unsigned int hori);
-void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
-				unsigned int vert, unsigned int hori);
-void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
-				struct mipi_dsim_config *dsim_config);
-void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
-				unsigned int count);
-void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
-				unsigned int enable);
-void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
-				unsigned int afc_code);
-void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
-				unsigned int enable);
-void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
-				unsigned int m, unsigned int s);
-void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
-				unsigned int freq_band);
-void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
-			unsigned int pre_divider, unsigned int main_divider,
-			unsigned int scaler);
-void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
-			unsigned int lock_time);
-void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim,
-					unsigned int enable);
-void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
-					unsigned int src);
-void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
-					unsigned int enable);
-void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
-				unsigned int enable, unsigned int prs_val);
-void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
-				unsigned int lane_sel, unsigned int enable);
-void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
-				unsigned int enable);
-unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
-				unsigned int cnt_val);
-void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
-				unsigned int timeout);
-void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
-				unsigned int timeout);
-void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
-					unsigned int lp);
-void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
-					unsigned int lp);
-void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
-				unsigned int enable);
-void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
-				unsigned int swap_en);
-void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
-				unsigned int hs_zero);
-void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep);
-unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim);
-unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
-					unsigned int src);
-void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
-					unsigned int src, unsigned int enable);
-unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim);
-unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim);
-unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
-void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
-void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, unsigned int di,
-				unsigned int data0, unsigned int data1);
-void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
-		unsigned int tx_data);
-void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
-		unsigned int data0, unsigned int data1);
-unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim);
-
-#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_regs.h b/drivers/video/exynos/exynos_mipi_dsi_regs.h
deleted file mode 100644
index 4227106d3fd0..000000000000
--- a/drivers/video/exynos/exynos_mipi_dsi_regs.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* linux/driver/video/exynos/exynos_mipi_dsi_regs.h
- *
- * Register definition file for Samsung MIPI-DSIM driver
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd
- *
- * InKi Dae <inki.dae@samsung.com>
- * Donghwa Lee <dh09.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef _EXYNOS_MIPI_DSI_REGS_H
-#define _EXYNOS_MIPI_DSI_REGS_H
-
-#define EXYNOS_DSIM_STATUS		0x0	/* Status register */
-#define EXYNOS_DSIM_SWRST		0x4	/* Software reset register */
-#define EXYNOS_DSIM_CLKCTRL		0x8	/* Clock control register */
-#define EXYNOS_DSIM_TIMEOUT		0xc	/* Time out register */
-#define EXYNOS_DSIM_CONFIG		0x10	/* Configuration register */
-#define EXYNOS_DSIM_ESCMODE		0x14	/* Escape mode register */
-
-/* Main display image resolution register */
-#define EXYNOS_DSIM_MDRESOL		0x18
-#define EXYNOS_DSIM_MVPORCH		0x1c	/* Main display Vporch register */
-#define EXYNOS_DSIM_MHPORCH		0x20	/* Main display Hporch register */
-#define EXYNOS_DSIM_MSYNC		0x24	/* Main display sync area register */
-
-/* Sub display image resolution register */
-#define EXYNOS_DSIM_SDRESOL		0x28
-#define EXYNOS_DSIM_INTSRC		0x2c	/* Interrupt source register */
-#define EXYNOS_DSIM_INTMSK		0x30	/* Interrupt mask register */
-#define EXYNOS_DSIM_PKTHDR		0x34	/* Packet Header FIFO register */
-#define EXYNOS_DSIM_PAYLOAD		0x38	/* Payload FIFO register */
-#define EXYNOS_DSIM_RXFIFO		0x3c	/* Read FIFO register */
-#define EXYNOS_DSIM_FIFOTHLD		0x40	/* FIFO threshold level register */
-#define EXYNOS_DSIM_FIFOCTRL		0x44	/* FIFO status and control register */
-
-/* FIFO memory AC characteristic register */
-#define EXYNOS_DSIM_PLLCTRL		0x4c	/* PLL control register */
-#define EXYNOS_DSIM_PLLTMR		0x50	/* PLL timer register */
-#define EXYNOS_DSIM_PHYACCHR		0x54	/* D-PHY AC characteristic register */
-#define EXYNOS_DSIM_PHYACCHR1		0x58	/* D-PHY AC characteristic register1 */
-
-/* DSIM_STATUS */
-#define DSIM_STOP_STATE_DAT(x)		(((x) & 0xf) << 0)
-#define DSIM_STOP_STATE_CLK		(1 << 8)
-#define DSIM_TX_READY_HS_CLK		(1 << 10)
-
-/* DSIM_SWRST */
-#define DSIM_FUNCRST			(1 << 16)
-#define DSIM_SWRST			(1 << 0)
-
-/* EXYNOS_DSIM_TIMEOUT */
-#define DSIM_LPDR_TOUT_SHIFT(x)		((x) << 0)
-#define DSIM_BTA_TOUT_SHIFT(x)		((x) << 16)
-
-/* EXYNOS_DSIM_CLKCTRL */
-#define DSIM_LANE_ESC_CLKEN(x)		(((x) & 0x1f) << 19)
-#define DSIM_BYTE_CLKEN_SHIFT(x)	((x) << 24)
-#define DSIM_BYTE_CLK_SRC_SHIFT(x)	((x) <<	25)
-#define DSIM_PLL_BYPASS_SHIFT(x)	((x) <<	27)
-#define DSIM_ESC_CLKEN_SHIFT(x)		((x) << 28)
-#define DSIM_TX_REQUEST_HSCLK_SHIFT(x)	((x) << 31)
-
-/* EXYNOS_DSIM_CONFIG */
-#define DSIM_LANE_ENx(x)		(((x) & 0x1f) << 0)
-#define DSIM_NUM_OF_DATALANE_SHIFT(x)	((x) << 5)
-#define DSIM_HSA_MODE_SHIFT(x)		((x) << 20)
-#define DSIM_HBP_MODE_SHIFT(x)		((x) << 21)
-#define DSIM_HFP_MODE_SHIFT(x)		((x) << 22)
-#define DSIM_HSE_MODE_SHIFT(x)		((x) << 23)
-#define DSIM_AUTO_MODE_SHIFT(x)		((x) << 24)
-#define DSIM_EOT_DISABLE(x)		((x) << 28)
-#define DSIM_AUTO_FLUSH(x)		((x) << 29)
-
-#define DSIM_NUM_OF_DATA_LANE(x)	((x) << DSIM_NUM_OF_DATALANE_SHIFT)
-
-/* EXYNOS_DSIM_ESCMODE */
-#define DSIM_TX_LPDT_LP			(1 << 6)
-#define DSIM_CMD_LPDT_LP		(1 << 7)
-#define DSIM_FORCE_STOP_STATE_SHIFT(x)	((x) << 20)
-#define DSIM_STOP_STATE_CNT_SHIFT(x)	((x) << 21)
-
-/* EXYNOS_DSIM_MDRESOL */
-#define DSIM_MAIN_STAND_BY		(1 << 31)
-#define DSIM_MAIN_VRESOL(x)		(((x) & 0x7ff) << 16)
-#define DSIM_MAIN_HRESOL(x)		(((x) & 0X7ff) << 0)
-
-/* EXYNOS_DSIM_MVPORCH */
-#define DSIM_CMD_ALLOW_SHIFT(x)		((x) << 28)
-#define DSIM_STABLE_VFP_SHIFT(x)	((x) << 16)
-#define DSIM_MAIN_VBP_SHIFT(x)		((x) << 0)
-#define DSIM_CMD_ALLOW_MASK		(0xf << 28)
-#define DSIM_STABLE_VFP_MASK		(0x7ff << 16)
-#define DSIM_MAIN_VBP_MASK		(0x7ff << 0)
-
-/* EXYNOS_DSIM_MHPORCH */
-#define DSIM_MAIN_HFP_SHIFT(x)		((x) << 16)
-#define DSIM_MAIN_HBP_SHIFT(x)		((x) << 0)
-#define DSIM_MAIN_HFP_MASK		((0xffff) << 16)
-#define DSIM_MAIN_HBP_MASK		((0xffff) << 0)
-
-/* EXYNOS_DSIM_MSYNC */
-#define DSIM_MAIN_VSA_SHIFT(x)		((x) << 22)
-#define DSIM_MAIN_HSA_SHIFT(x)		((x) << 0)
-#define DSIM_MAIN_VSA_MASK		((0x3ff) << 22)
-#define DSIM_MAIN_HSA_MASK		((0xffff) << 0)
-
-/* EXYNOS_DSIM_SDRESOL */
-#define DSIM_SUB_STANDY_SHIFT(x)	((x) << 31)
-#define DSIM_SUB_VRESOL_SHIFT(x)	((x) << 16)
-#define DSIM_SUB_HRESOL_SHIFT(x)	((x) << 0)
-#define DSIM_SUB_STANDY_MASK		((0x1) << 31)
-#define DSIM_SUB_VRESOL_MASK		((0x7ff) << 16)
-#define DSIM_SUB_HRESOL_MASK		((0x7ff) << 0)
-
-/* EXYNOS_DSIM_INTSRC */
-#define INTSRC_PLL_STABLE		(1 << 31)
-#define INTSRC_SW_RST_RELEASE		(1 << 30)
-#define INTSRC_SFR_FIFO_EMPTY		(1 << 29)
-#define INTSRC_FRAME_DONE		(1 << 24)
-#define INTSRC_RX_DATA_DONE		(1 << 18)
-
-/* EXYNOS_DSIM_INTMSK */
-#define INTMSK_FIFO_EMPTY		(1 << 29)
-#define INTMSK_BTA			(1 << 25)
-#define INTMSK_FRAME_DONE		(1 << 24)
-#define INTMSK_RX_TIMEOUT		(1 << 21)
-#define INTMSK_BTA_TIMEOUT		(1 << 20)
-#define INTMSK_RX_DONE			(1 << 18)
-#define INTMSK_RX_TE			(1 << 17)
-#define INTMSK_RX_ACK			(1 << 16)
-#define INTMSK_RX_ECC_ERR		(1 << 15)
-#define INTMSK_RX_CRC_ERR		(1 << 14)
-
-/* EXYNOS_DSIM_FIFOCTRL */
-#define SFR_HEADER_EMPTY		(1 << 22)
-
-/* EXYNOS_DSIM_PHYACCHR */
-#define DSIM_AFC_CTL(x)			(((x) & 0x7) << 5)
-
-/* EXYNOS_DSIM_PLLCTRL */
-#define DSIM_PLL_EN_SHIFT(x)		((x) << 23)
-#define DSIM_FREQ_BAND_SHIFT(x)		((x) << 24)
-
-#endif /* _EXYNOS_MIPI_DSI_REGS_H */
diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/exynos/s6e8ax0.c
deleted file mode 100644
index 29e70ed3f154..000000000000
--- a/drivers/video/exynos/s6e8ax0.c
+++ /dev/null
@@ -1,898 +0,0 @@
-/* linux/drivers/video/exynos/s6e8ax0.c
- *
- * MIPI-DSI based s6e8ax0 AMOLED lcd 4.65 inch panel driver.
- *
- * Inki Dae, <inki.dae@samsung.com>
- * Donghwa Lee, <dh09.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/ctype.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/lcd.h>
-#include <linux/fb.h>
-#include <linux/backlight.h>
-#include <linux/regulator/consumer.h>
-
-#include <video/mipi_display.h>
-#include <video/exynos_mipi_dsim.h>
-
-#define LDI_MTP_LENGTH		24
-#define DSIM_PM_STABLE_TIME	10
-#define MIN_BRIGHTNESS		0
-#define MAX_BRIGHTNESS		24
-#define GAMMA_TABLE_COUNT	26
-
-#define POWER_IS_ON(pwr)	((pwr) == FB_BLANK_UNBLANK)
-#define POWER_IS_OFF(pwr)	((pwr) == FB_BLANK_POWERDOWN)
-#define POWER_IS_NRM(pwr)	((pwr) == FB_BLANK_NORMAL)
-
-#define lcd_to_master(a)	(a->dsim_dev->master)
-#define lcd_to_master_ops(a)	((lcd_to_master(a))->master_ops)
-
-enum {
-	DSIM_NONE_STATE = 0,
-	DSIM_RESUME_COMPLETE = 1,
-	DSIM_FRAME_DONE = 2,
-};
-
-struct s6e8ax0 {
-	struct device	*dev;
-	unsigned int			power;
-	unsigned int			id;
-	unsigned int			gamma;
-	unsigned int			acl_enable;
-	unsigned int			cur_acl;
-
-	struct lcd_device	*ld;
-	struct backlight_device	*bd;
-
-	struct mipi_dsim_lcd_device	*dsim_dev;
-	struct lcd_platform_data	*ddi_pd;
-	struct mutex			lock;
-	bool  enabled;
-};
-
-
-static struct regulator_bulk_data supplies[] = {
-	{ .supply = "vdd3", },
-	{ .supply = "vci", },
-};
-
-static void s6e8ax0_regulator_enable(struct s6e8ax0 *lcd)
-{
-	int ret = 0;
-	struct lcd_platform_data *pd = NULL;
-
-	pd = lcd->ddi_pd;
-	mutex_lock(&lcd->lock);
-	if (!lcd->enabled) {
-		ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
-		if (ret)
-			goto out;
-
-		lcd->enabled = true;
-	}
-	msleep(pd->power_on_delay);
-out:
-	mutex_unlock(&lcd->lock);
-}
-
-static void s6e8ax0_regulator_disable(struct s6e8ax0 *lcd)
-{
-	int ret = 0;
-
-	mutex_lock(&lcd->lock);
-	if (lcd->enabled) {
-		ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
-		if (ret)
-			goto out;
-
-		lcd->enabled = false;
-	}
-out:
-	mutex_unlock(&lcd->lock);
-}
-
-static const unsigned char s6e8ax0_22_gamma_30[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xf5, 0x00, 0xff, 0xad, 0xaf,
-	0xbA, 0xc3, 0xd8, 0xc5, 0x9f, 0xc6, 0x9e, 0xc1, 0xdc, 0xc0,
-	0x00, 0x61, 0x00, 0x5a, 0x00, 0x74,
-};
-
-static const unsigned char s6e8ax0_22_gamma_50[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xe8, 0x1f, 0xf7, 0xad, 0xc0,
-	0xb5, 0xc4, 0xdc, 0xc4, 0x9e, 0xc6, 0x9c, 0xbb, 0xd8, 0xbb,
-	0x00, 0x70, 0x00, 0x68, 0x00, 0x86,
-};
-
-static const unsigned char s6e8ax0_22_gamma_60[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xde, 0x1f, 0xef, 0xad, 0xc4,
-	0xb3, 0xc3, 0xdd, 0xc4, 0x9e, 0xc6, 0x9c, 0xbc, 0xd6, 0xba,
-	0x00, 0x75, 0x00, 0x6e, 0x00, 0x8d,
-};
-
-static const unsigned char s6e8ax0_22_gamma_70[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xd8, 0x1f, 0xe7, 0xaf, 0xc8,
-	0xb4, 0xc4, 0xdd, 0xc3, 0x9d, 0xc6, 0x9c, 0xbb, 0xd6, 0xb9,
-	0x00, 0x7a, 0x00, 0x72, 0x00, 0x93,
-};
-
-static const unsigned char s6e8ax0_22_gamma_80[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xc9, 0x1f, 0xde, 0xae, 0xc9,
-	0xb1, 0xc3, 0xdd, 0xc2, 0x9d, 0xc5, 0x9b, 0xbc, 0xd6, 0xbb,
-	0x00, 0x7f, 0x00, 0x77, 0x00, 0x99,
-};
-
-static const unsigned char s6e8ax0_22_gamma_90[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xc7, 0x1f, 0xd9, 0xb0, 0xcc,
-	0xb2, 0xc3, 0xdc, 0xc1, 0x9c, 0xc6, 0x9c, 0xbc, 0xd4, 0xb9,
-	0x00, 0x83, 0x00, 0x7b, 0x00, 0x9e,
-};
-
-static const unsigned char s6e8ax0_22_gamma_100[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xbd, 0x80, 0xcd, 0xba, 0xce,
-	0xb3, 0xc4, 0xde, 0xc3, 0x9c, 0xc4, 0x9, 0xb8, 0xd3, 0xb6,
-	0x00, 0x88, 0x00, 0x80, 0x00, 0xa5,
-};
-
-static const unsigned char s6e8ax0_22_gamma_120[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb9, 0x95, 0xc8, 0xb1, 0xcf,
-	0xb2, 0xc6, 0xdf, 0xc5, 0x9b, 0xc3, 0x99, 0xb6, 0xd2, 0xb6,
-	0x00, 0x8f, 0x00, 0x86, 0x00, 0xac,
-};
-
-static const unsigned char s6e8ax0_22_gamma_130[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc7, 0xb1, 0xd0,
-	0xb2, 0xc4, 0xdd, 0xc3, 0x9a, 0xc3, 0x98, 0xb6, 0xd0, 0xb4,
-	0x00, 0x92, 0x00, 0x8a, 0x00, 0xb1,
-};
-
-static const unsigned char s6e8ax0_22_gamma_140[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc5, 0xb2, 0xd0,
-	0xb3, 0xc3, 0xde, 0xc3, 0x9b, 0xc2, 0x98, 0xb6, 0xd0, 0xb4,
-	0x00, 0x95, 0x00, 0x8d, 0x00, 0xb5,
-};
-
-static const unsigned char s6e8ax0_22_gamma_150[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xa0, 0xc2, 0xb2, 0xd0,
-	0xb2, 0xc1, 0xdd, 0xc2, 0x9b, 0xc2, 0x98, 0xb4, 0xcf, 0xb1,
-	0x00, 0x99, 0x00, 0x90, 0x00, 0xba,
-};
-
-static const unsigned char s6e8ax0_22_gamma_160[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xa5, 0xbf, 0xb0, 0xd0,
-	0xb1, 0xc3, 0xde, 0xc2, 0x99, 0xc1, 0x97, 0xb4, 0xce, 0xb1,
-	0x00, 0x9c, 0x00, 0x93, 0x00, 0xbe,
-};
-
-static const unsigned char s6e8ax0_22_gamma_170[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb5, 0xbf, 0xb1, 0xd1,
-	0xb1, 0xc3, 0xde, 0xc3, 0x99, 0xc0, 0x96, 0xb4, 0xce, 0xb1,
-	0x00, 0x9f, 0x00, 0x96, 0x00, 0xc2,
-};
-
-static const unsigned char s6e8ax0_22_gamma_180[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb7, 0xbe, 0xb3, 0xd2,
-	0xb3, 0xc3, 0xde, 0xc2, 0x97, 0xbf, 0x95, 0xb4, 0xcd, 0xb1,
-	0x00, 0xa2, 0x00, 0x99, 0x00, 0xc5,
-};
-
-static const unsigned char s6e8ax0_22_gamma_190[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbe, 0xb2, 0xd2,
-	0xb2, 0xc3, 0xdd, 0xc3, 0x98, 0xbf, 0x95, 0xb2, 0xcc, 0xaf,
-	0x00, 0xa5, 0x00, 0x9c, 0x00, 0xc9,
-};
-
-static const unsigned char s6e8ax0_22_gamma_200[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbc, 0xb2, 0xd2,
-	0xb1, 0xc4, 0xdd, 0xc3, 0x97, 0xbe, 0x95, 0xb1, 0xcb, 0xae,
-	0x00, 0xa8, 0x00, 0x9f, 0x00, 0xcd,
-};
-
-static const unsigned char s6e8ax0_22_gamma_210[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc1, 0xbd, 0xb1, 0xd1,
-	0xb1, 0xc2, 0xde, 0xc2, 0x97, 0xbe, 0x94, 0xB0, 0xc9, 0xad,
-	0x00, 0xae, 0x00, 0xa4, 0x00, 0xd4,
-};
-
-static const unsigned char s6e8ax0_22_gamma_220[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc7, 0xbd, 0xb1, 0xd1,
-	0xb1, 0xc2, 0xdd, 0xc2, 0x97, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
-	0x00, 0xad, 0x00, 0xa2, 0x00, 0xd3,
-};
-
-static const unsigned char s6e8ax0_22_gamma_230[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc3, 0xbd, 0xb2, 0xd1,
-	0xb1, 0xc3, 0xdd, 0xc1, 0x96, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
-	0x00, 0xb0, 0x00, 0xa7, 0x00, 0xd7,
-};
-
-static const unsigned char s6e8ax0_22_gamma_240[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xcb, 0xbd, 0xb1, 0xd2,
-	0xb1, 0xc3, 0xdD, 0xc2, 0x95, 0xbd, 0x93, 0xaf, 0xc8, 0xab,
-	0x00, 0xb3, 0x00, 0xa9, 0x00, 0xdb,
-};
-
-static const unsigned char s6e8ax0_22_gamma_250[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xcc, 0xbe, 0xb0, 0xd2,
-	0xb0, 0xc3, 0xdD, 0xc2, 0x94, 0xbc, 0x92, 0xae, 0xc8, 0xab,
-	0x00, 0xb6, 0x00, 0xab, 0x00, 0xde,
-};
-
-static const unsigned char s6e8ax0_22_gamma_260[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xd0, 0xbe, 0xaf, 0xd1,
-	0xaf, 0xc2, 0xdd, 0xc1, 0x96, 0xbc, 0x93, 0xaf, 0xc8, 0xac,
-	0x00, 0xb7, 0x00, 0xad, 0x00, 0xe0,
-};
-
-static const unsigned char s6e8ax0_22_gamma_270[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xcF, 0xbd, 0xb0, 0xd2,
-	0xaf, 0xc2, 0xdc, 0xc1, 0x95, 0xbd, 0x93, 0xae, 0xc6, 0xaa,
-	0x00, 0xba, 0x00, 0xb0, 0x00, 0xe4,
-};
-
-static const unsigned char s6e8ax0_22_gamma_280[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xd0, 0xbd, 0xaf, 0xd0,
-	0xad, 0xc4, 0xdd, 0xc3, 0x95, 0xbd, 0x93, 0xac, 0xc5, 0xa9,
-	0x00, 0xbd, 0x00, 0xb2, 0x00, 0xe7,
-};
-
-static const unsigned char s6e8ax0_22_gamma_300[] = {
-	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb5, 0xd3, 0xbd, 0xb1, 0xd2,
-	0xb0, 0xc0, 0xdc, 0xc0, 0x94, 0xba, 0x91, 0xac, 0xc5, 0xa9,
-	0x00, 0xc2, 0x00, 0xb7, 0x00, 0xed,
-};
-
-static const unsigned char *s6e8ax0_22_gamma_table[] = {
-	s6e8ax0_22_gamma_30,
-	s6e8ax0_22_gamma_50,
-	s6e8ax0_22_gamma_60,
-	s6e8ax0_22_gamma_70,
-	s6e8ax0_22_gamma_80,
-	s6e8ax0_22_gamma_90,
-	s6e8ax0_22_gamma_100,
-	s6e8ax0_22_gamma_120,
-	s6e8ax0_22_gamma_130,
-	s6e8ax0_22_gamma_140,
-	s6e8ax0_22_gamma_150,
-	s6e8ax0_22_gamma_160,
-	s6e8ax0_22_gamma_170,
-	s6e8ax0_22_gamma_180,
-	s6e8ax0_22_gamma_190,
-	s6e8ax0_22_gamma_200,
-	s6e8ax0_22_gamma_210,
-	s6e8ax0_22_gamma_220,
-	s6e8ax0_22_gamma_230,
-	s6e8ax0_22_gamma_240,
-	s6e8ax0_22_gamma_250,
-	s6e8ax0_22_gamma_260,
-	s6e8ax0_22_gamma_270,
-	s6e8ax0_22_gamma_280,
-	s6e8ax0_22_gamma_300,
-};
-
-static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-
-	static const unsigned char data_to_send[] = {
-		0xf8, 0x3d, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
-		0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
-		0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
-		0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8
-	};
-	static const unsigned char data_to_send_panel_reverse[] = {
-		0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
-		0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
-		0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
-		0xc1, 0x01, 0x41, 0xc1, 0x00, 0xc1, 0xf6, 0xf6, 0xc1
-	};
-
-	if (lcd->dsim_dev->panel_reverse)
-		ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-				data_to_send_panel_reverse,
-				ARRAY_SIZE(data_to_send_panel_reverse));
-	else
-		ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-				data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_display_cond(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xf2, 0x80, 0x03, 0x0d
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-/* Gamma 2.2 Setting (200cd, 7500K, 10MPCD) */
-static void s6e8ax0_gamma_cond(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	unsigned int gamma = lcd->bd->props.brightness;
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-			s6e8ax0_22_gamma_table[gamma],
-			GAMMA_TABLE_COUNT);
-}
-
-static void s6e8ax0_gamma_update(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xf7, 0x03
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send,
-		ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_etc_cond1(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xd1, 0xfe, 0x80, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x40,
-		0x0d, 0x00, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_etc_cond2(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0,
-		0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_etc_cond3(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xe1, 0x10, 0x1c, 0x17, 0x08, 0x1d
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_etc_cond4(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xe2, 0xed, 0x07, 0xc3, 0x13, 0x0d, 0x03
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_etc_cond5(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x19, 0x33, 0x02
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-static void s6e8ax0_etc_cond6(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xe3, 0x40
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE_PARAM,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_etc_cond7(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xe4, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_elvss_set(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xb1, 0x04, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_elvss_nvm_set(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xd9, 0x5c, 0x20, 0x0c, 0x0f, 0x41, 0x00, 0x10, 0x11,
-		0x12, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcb, 0xed,
-		0x64, 0xaf
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_sleep_in(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0x10, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_sleep_out(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0x11, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_display_on(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0x29, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_display_off(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0x28, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_apply_level2_key(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xf0, 0x5a, 0x5a
-	};
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_acl_on(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xc0, 0x01
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-static void s6e8ax0_acl_off(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	static const unsigned char data_to_send[] = {
-		0xc0, 0x00
-	};
-
-	ops->cmd_write(lcd_to_master(lcd),
-		MIPI_DSI_DCS_SHORT_WRITE,
-		data_to_send, ARRAY_SIZE(data_to_send));
-}
-
-/* Full white 50% reducing setting */
-static void s6e8ax0_acl_ctrl_set(struct s6e8ax0 *lcd)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	/* Full white 50% reducing setting */
-	static const unsigned char cutoff_50[] = {
-		0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
-		0x00, 0x00, 0x04, 0xff,	0x00, 0x00, 0x00, 0x00, 0x00,
-		0x01, 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2a, 0x31, 0x38,
-		0x3f, 0x46
-	};
-	/* Full white 45% reducing setting */
-	static const unsigned char cutoff_45[] = {
-		0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
-		0x00, 0x00, 0x04, 0xff,	0x00, 0x00, 0x00, 0x00, 0x00,
-		0x01, 0x07, 0x0d, 0x13, 0x19, 0x1f, 0x25, 0x2b, 0x31,
-		0x37, 0x3d
-	};
-	/* Full white 40% reducing setting */
-	static const unsigned char cutoff_40[] = {
-		0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
-		0x00, 0x00, 0x04, 0xff,	0x00, 0x00, 0x00, 0x00, 0x00,
-		0x01, 0x06, 0x0c, 0x11, 0x16, 0x1c, 0x21, 0x26, 0x2b,
-		0x31, 0x36
-	};
-
-	if (lcd->acl_enable) {
-		if (lcd->cur_acl == 0) {
-			if (lcd->gamma == 0 || lcd->gamma == 1) {
-				s6e8ax0_acl_off(lcd);
-				dev_dbg(&lcd->ld->dev,
-					"cur_acl=%d\n", lcd->cur_acl);
-			} else
-				s6e8ax0_acl_on(lcd);
-		}
-		switch (lcd->gamma) {
-		case 0: /* 30cd */
-			s6e8ax0_acl_off(lcd);
-			lcd->cur_acl = 0;
-			break;
-		case 1 ... 3: /* 50cd ~ 90cd */
-			ops->cmd_write(lcd_to_master(lcd),
-				MIPI_DSI_DCS_LONG_WRITE,
-				cutoff_40,
-				ARRAY_SIZE(cutoff_40));
-			lcd->cur_acl = 40;
-			break;
-		case 4 ... 7: /* 120cd ~ 210cd */
-			ops->cmd_write(lcd_to_master(lcd),
-				MIPI_DSI_DCS_LONG_WRITE,
-				cutoff_45,
-				ARRAY_SIZE(cutoff_45));
-			lcd->cur_acl = 45;
-			break;
-		case 8 ... 10: /* 220cd ~ 300cd */
-			ops->cmd_write(lcd_to_master(lcd),
-				MIPI_DSI_DCS_LONG_WRITE,
-				cutoff_50,
-				ARRAY_SIZE(cutoff_50));
-			lcd->cur_acl = 50;
-			break;
-		default:
-			break;
-		}
-	} else {
-		s6e8ax0_acl_off(lcd);
-		lcd->cur_acl = 0;
-		dev_dbg(&lcd->ld->dev, "cur_acl = %d\n", lcd->cur_acl);
-	}
-}
-
-static void s6e8ax0_read_id(struct s6e8ax0 *lcd, u8 *mtp_id)
-{
-	unsigned int ret;
-	unsigned int addr = 0xd1;	/* MTP ID */
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-
-	ret = ops->cmd_read(lcd_to_master(lcd),
-			MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM,
-			addr, 3, mtp_id);
-}
-
-static int s6e8ax0_panel_init(struct s6e8ax0 *lcd)
-{
-	s6e8ax0_apply_level2_key(lcd);
-	s6e8ax0_sleep_out(lcd);
-	msleep(1);
-	s6e8ax0_panel_cond(lcd);
-	s6e8ax0_display_cond(lcd);
-	s6e8ax0_gamma_cond(lcd);
-	s6e8ax0_gamma_update(lcd);
-
-	s6e8ax0_etc_cond1(lcd);
-	s6e8ax0_etc_cond2(lcd);
-	s6e8ax0_etc_cond3(lcd);
-	s6e8ax0_etc_cond4(lcd);
-	s6e8ax0_etc_cond5(lcd);
-	s6e8ax0_etc_cond6(lcd);
-	s6e8ax0_etc_cond7(lcd);
-
-	s6e8ax0_elvss_nvm_set(lcd);
-	s6e8ax0_elvss_set(lcd);
-
-	s6e8ax0_acl_ctrl_set(lcd);
-	s6e8ax0_acl_on(lcd);
-
-	/* if ID3 value is not 33h, branch private elvss mode */
-	msleep(lcd->ddi_pd->power_on_delay);
-
-	return 0;
-}
-
-static int s6e8ax0_update_gamma_ctrl(struct s6e8ax0 *lcd, int brightness)
-{
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-
-	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
-			s6e8ax0_22_gamma_table[brightness],
-			ARRAY_SIZE(s6e8ax0_22_gamma_table));
-
-	/* update gamma table. */
-	s6e8ax0_gamma_update(lcd);
-	lcd->gamma = brightness;
-
-	return 0;
-}
-
-static int s6e8ax0_gamma_ctrl(struct s6e8ax0 *lcd, int gamma)
-{
-	s6e8ax0_update_gamma_ctrl(lcd, gamma);
-
-	return 0;
-}
-
-static int s6e8ax0_set_power(struct lcd_device *ld, int power)
-{
-	struct s6e8ax0 *lcd = lcd_get_data(ld);
-	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
-	int ret = 0;
-
-	if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
-			power != FB_BLANK_NORMAL) {
-		dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
-		return -EINVAL;
-	}
-
-	if ((power == FB_BLANK_UNBLANK) && ops->set_blank_mode) {
-		/* LCD power on */
-		if ((POWER_IS_ON(power) && POWER_IS_OFF(lcd->power))
-			|| (POWER_IS_ON(power) && POWER_IS_NRM(lcd->power))) {
-			ret = ops->set_blank_mode(lcd_to_master(lcd), power);
-			if (!ret && lcd->power != power)
-				lcd->power = power;
-		}
-	} else if ((power == FB_BLANK_POWERDOWN) && ops->set_early_blank_mode) {
-		/* LCD power off */
-		if ((POWER_IS_OFF(power) && POWER_IS_ON(lcd->power)) ||
-		(POWER_IS_ON(lcd->power) && POWER_IS_NRM(power))) {
-			ret = ops->set_early_blank_mode(lcd_to_master(lcd),
-							power);
-			if (!ret && lcd->power != power)
-				lcd->power = power;
-		}
-	}
-
-	return ret;
-}
-
-static int s6e8ax0_get_power(struct lcd_device *ld)
-{
-	struct s6e8ax0 *lcd = lcd_get_data(ld);
-
-	return lcd->power;
-}
-
-static int s6e8ax0_get_brightness(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
-static int s6e8ax0_set_brightness(struct backlight_device *bd)
-{
-	int ret = 0, brightness = bd->props.brightness;
-	struct s6e8ax0 *lcd = bl_get_data(bd);
-
-	if (brightness < MIN_BRIGHTNESS ||
-		brightness > bd->props.max_brightness) {
-		dev_err(lcd->dev, "lcd brightness should be %d to %d.\n",
-			MIN_BRIGHTNESS, MAX_BRIGHTNESS);
-		return -EINVAL;
-	}
-
-	ret = s6e8ax0_gamma_ctrl(lcd, brightness);
-	if (ret) {
-		dev_err(&bd->dev, "lcd brightness setting failed.\n");
-		return -EIO;
-	}
-
-	return ret;
-}
-
-static struct lcd_ops s6e8ax0_lcd_ops = {
-	.set_power = s6e8ax0_set_power,
-	.get_power = s6e8ax0_get_power,
-};
-
-static const struct backlight_ops s6e8ax0_backlight_ops = {
-	.get_brightness = s6e8ax0_get_brightness,
-	.update_status = s6e8ax0_set_brightness,
-};
-
-static void s6e8ax0_power_on(struct mipi_dsim_lcd_device *dsim_dev, int power)
-{
-	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
-
-	msleep(lcd->ddi_pd->power_on_delay);
-
-	/* lcd power on */
-	if (power)
-		s6e8ax0_regulator_enable(lcd);
-	else
-		s6e8ax0_regulator_disable(lcd);
-
-	msleep(lcd->ddi_pd->reset_delay);
-
-	/* lcd reset */
-	if (lcd->ddi_pd->reset)
-		lcd->ddi_pd->reset(lcd->ld);
-	msleep(5);
-}
-
-static void s6e8ax0_set_sequence(struct mipi_dsim_lcd_device *dsim_dev)
-{
-	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
-
-	s6e8ax0_panel_init(lcd);
-	s6e8ax0_display_on(lcd);
-
-	lcd->power = FB_BLANK_UNBLANK;
-}
-
-static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev)
-{
-	struct s6e8ax0 *lcd;
-	int ret;
-	u8 mtp_id[3] = {0, };
-
-	lcd = devm_kzalloc(&dsim_dev->dev, sizeof(struct s6e8ax0), GFP_KERNEL);
-	if (!lcd) {
-		dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n");
-		return -ENOMEM;
-	}
-
-	lcd->dsim_dev = dsim_dev;
-	lcd->ddi_pd = (struct lcd_platform_data *)dsim_dev->platform_data;
-	lcd->dev = &dsim_dev->dev;
-
-	mutex_init(&lcd->lock);
-
-	ret = devm_regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
-	if (ret) {
-		dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
-		return ret;
-	}
-
-	lcd->ld = devm_lcd_device_register(lcd->dev, "s6e8ax0", lcd->dev, lcd,
-			&s6e8ax0_lcd_ops);
-	if (IS_ERR(lcd->ld)) {
-		dev_err(lcd->dev, "failed to register lcd ops.\n");
-		return PTR_ERR(lcd->ld);
-	}
-
-	lcd->bd = devm_backlight_device_register(lcd->dev, "s6e8ax0-bl",
-				lcd->dev, lcd, &s6e8ax0_backlight_ops, NULL);
-	if (IS_ERR(lcd->bd)) {
-		dev_err(lcd->dev, "failed to register backlight ops.\n");
-		return PTR_ERR(lcd->bd);
-	}
-
-	lcd->bd->props.max_brightness = MAX_BRIGHTNESS;
-	lcd->bd->props.brightness = MAX_BRIGHTNESS;
-
-	s6e8ax0_read_id(lcd, mtp_id);
-	if (mtp_id[0] == 0x00)
-		dev_err(lcd->dev, "read id failed\n");
-
-	dev_info(lcd->dev, "Read ID : %x, %x, %x\n",
-			mtp_id[0], mtp_id[1], mtp_id[2]);
-
-	if (mtp_id[2] == 0x33)
-		dev_info(lcd->dev,
-			"ID-3 is 0xff does not support dynamic elvss\n");
-	else
-		dev_info(lcd->dev,
-			"ID-3 is 0x%x support dynamic elvss\n", mtp_id[2]);
-
-	lcd->acl_enable = 1;
-	lcd->cur_acl = 0;
-
-	dev_set_drvdata(&dsim_dev->dev, lcd);
-
-	dev_dbg(lcd->dev, "probed s6e8ax0 panel driver.\n");
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
-{
-	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
-
-	s6e8ax0_sleep_in(lcd);
-	msleep(lcd->ddi_pd->power_off_delay);
-	s6e8ax0_display_off(lcd);
-
-	s6e8ax0_regulator_disable(lcd);
-
-	return 0;
-}
-
-static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
-{
-	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
-
-	s6e8ax0_sleep_out(lcd);
-	msleep(lcd->ddi_pd->power_on_delay);
-
-	s6e8ax0_regulator_enable(lcd);
-	s6e8ax0_set_sequence(dsim_dev);
-
-	return 0;
-}
-#else
-#define s6e8ax0_suspend		NULL
-#define s6e8ax0_resume		NULL
-#endif
-
-static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = {
-	.name = "s6e8ax0",
-	.id = -1,
-
-	.power_on = s6e8ax0_power_on,
-	.set_sequence = s6e8ax0_set_sequence,
-	.probe = s6e8ax0_probe,
-	.suspend = s6e8ax0_suspend,
-	.resume = s6e8ax0_resume,
-};
-
-static int s6e8ax0_init(void)
-{
-	exynos_mipi_dsi_register_lcd_driver(&s6e8ax0_dsim_ddi_driver);
-
-	return 0;
-}
-
-static void s6e8ax0_exit(void)
-{
-	return;
-}
-
-module_init(s6e8ax0_init);
-module_exit(s6e8ax0_exit);
-
-MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
-MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
-MODULE_DESCRIPTION("MIPI-DSI based s6e8ax0 AMOLED LCD Panel Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
deleted file mode 100644
index 6db9ebd042a3..000000000000
--- a/drivers/video/fb-puv3.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * Frame Buffer Driver for PKUnity-v3 Unigfx
- * Code specific to PKUnity SoC and UniCore ISA
- *
- *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
- *	Copyright (C) 2001-2010 Guan Xuetao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-
-/* Platform_data reserved for unifb registers. */
-#define UNIFB_REGS_NUM		10
-/* RAM reserved for the frame buffer. */
-#define UNIFB_MEMSIZE		(SZ_4M)		/* 4 MB for 1024*768*32b */
-
-/*
- * cause UNIGFX don not have EDID
- * all the modes are organized as follow
- */
-static const struct fb_videomode unifb_modes[] = {
-	/* 0 640x480-60 VESA */
-	{ "640x480@60",  60,  640, 480,  25175000,  48, 16, 34, 10,  96, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1 640x480-75 VESA */
-	{ "640x480@75",  75,  640, 480,  31500000, 120, 16, 18,  1,  64, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 2 800x600-60 VESA */
-	{ "800x600@60",  60,  800, 600,  40000000,  88, 40, 26,  1, 128, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 3 800x600-75 VESA */
-	{ "800x600@75",  75,  800, 600,  49500000, 160, 16, 23,  1,  80, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 4 1024x768-60 VESA */
-	{ "1024x768@60", 60, 1024, 768,  65000000, 160, 24, 34,  3, 136, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 5 1024x768-75 VESA */
-	{ "1024x768@75", 75, 1024, 768,  78750000, 176, 16, 30,  1,  96, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 6 1280x960-60 VESA */
-	{ "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38,  1, 112, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 7 1440x900-60 VESA */
-	{ "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30,  3, 152, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 8 FIXME 9 1024x600-60 VESA UNTESTED */
-	{ "1024x600@60", 60, 1024, 600,  50650000, 160, 24, 26,  1, 136, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 9 FIXME 10 1024x600-75 VESA UNTESTED */
-	{ "1024x600@75", 75, 1024, 600,  61500000, 176, 16, 23,  1,  96, 1,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 10 FIXME 11 1366x768-60 VESA UNTESTED */
-	{ "1366x768@60", 60, 1366, 768,  85500000, 256, 58, 18,  1,  112, 3,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-};
-
-static struct fb_var_screeninfo unifb_default = {
-	.xres =		640,
-	.yres =		480,
-	.xres_virtual =	640,
-	.yres_virtual =	480,
-	.bits_per_pixel = 16,
-	.red =		{ 11, 5, 0 },
-	.green =	{ 5,  6, 0 },
-	.blue =		{ 0,  5, 0 },
-	.activate =	FB_ACTIVATE_NOW,
-	.height =	-1,
-	.width =	-1,
-	.pixclock =	25175000,
-	.left_margin =	48,
-	.right_margin =	16,
-	.upper_margin =	33,
-	.lower_margin =	10,
-	.hsync_len =	96,
-	.vsync_len =	2,
-	.vmode =	FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo unifb_fix = {
-	.id =		"UNIGFX FB",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	1,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static void unifb_sync(struct fb_info *info)
-{
-	/* TODO: may, this can be replaced by interrupt */
-	int cnt;
-
-	for (cnt = 0; cnt < 0x10000000; cnt++) {
-		if (readl(UGE_COMMAND) & 0x1000000)
-			return;
-	}
-
-	if (cnt > 0x8000000)
-		dev_warn(info->device, "Warning: UniGFX GE time out ...\n");
-}
-
-static void unifb_prim_fillrect(struct fb_info *info,
-				const struct fb_fillrect *region)
-{
-	int awidth = region->width;
-	int aheight = region->height;
-	int m_iBpp = info->var.bits_per_pixel;
-	int screen_width = info->var.xres;
-	int src_sel = 1;	/* from fg_color */
-	int pat_sel = 1;
-	int src_x0 = 0;
-	int dst_x0 = region->dx;
-	int src_y0 = 0;
-	int dst_y0 = region->dy;
-	int rop_alpha_sel = 0;
-	int rop_alpha_code = 0xCC;
-	int x_dir = 1;
-	int y_dir = 1;
-	int alpha_r = 0;
-	int alpha_sel = 0;
-	int dst_pitch = screen_width * (m_iBpp / 8);
-	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
-	int src_pitch = screen_width * (m_iBpp / 8);
-	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
-	unsigned int command = 0;
-	int clip_region = 0;
-	int clip_en = 0;
-	int tp_en = 0;
-	int fg_color = 0;
-	int bottom = info->var.yres - 1;
-	int right = info->var.xres - 1;
-	int top = 0;
-
-	bottom = (bottom << 16) | right;
-	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
-		| (x_dir << 20) | (y_dir << 21) | (command << 24)
-		| (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
-	src_pitch = (dst_pitch << 16) | src_pitch;
-	awidth = awidth | (aheight << 16);
-	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
-		| (alpha_sel << 16);
-	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
-	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
-	fg_color = region->color;
-
-	unifb_sync(info);
-
-	writel(((u32 *)(info->pseudo_palette))[fg_color], UGE_FCOLOR);
-	writel(0, UGE_BCOLOR);
-	writel(src_pitch, UGE_PITCH);
-	writel(src_offset, UGE_SRCSTART);
-	writel(dst_offset, UGE_DSTSTART);
-	writel(awidth, UGE_WIDHEIGHT);
-	writel(top, UGE_CLIP0);
-	writel(bottom, UGE_CLIP1);
-	writel(alpha_r, UGE_ROPALPHA);
-	writel(src_x0, UGE_SRCXY);
-	writel(dst_x0, UGE_DSTXY);
-	writel(command, UGE_COMMAND);
-}
-
-static void unifb_fillrect(struct fb_info *info,
-		const struct fb_fillrect *region)
-{
-	struct fb_fillrect modded;
-	int vxres, vyres;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		sys_fillrect(info, region);
-		return;
-	}
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	memcpy(&modded, region, sizeof(struct fb_fillrect));
-
-	if (!modded.width || !modded.height ||
-	    modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.dx + modded.width > vxres)
-		modded.width = vxres - modded.dx;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	unifb_prim_fillrect(info, &modded);
-}
-
-static void unifb_prim_copyarea(struct fb_info *info,
-				const struct fb_copyarea *area)
-{
-	int awidth = area->width;
-	int aheight = area->height;
-	int m_iBpp = info->var.bits_per_pixel;
-	int screen_width = info->var.xres;
-	int src_sel = 2;	/* from mem */
-	int pat_sel = 0;
-	int src_x0 = area->sx;
-	int dst_x0 = area->dx;
-	int src_y0 = area->sy;
-	int dst_y0 = area->dy;
-
-	int rop_alpha_sel = 0;
-	int rop_alpha_code = 0xCC;
-	int x_dir = 1;
-	int y_dir = 1;
-
-	int alpha_r = 0;
-	int alpha_sel = 0;
-	int dst_pitch = screen_width * (m_iBpp / 8);
-	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
-	int src_pitch = screen_width * (m_iBpp / 8);
-	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
-	unsigned int command = 0;
-	int clip_region = 0;
-	int clip_en = 1;
-	int tp_en = 0;
-	int top = 0;
-	int bottom = info->var.yres;
-	int right = info->var.xres;
-	int fg_color = 0;
-	int bg_color = 0;
-
-	if (src_x0 < 0)
-		src_x0 = 0;
-	if (src_y0 < 0)
-		src_y0 = 0;
-
-	if (src_y0 - dst_y0 > 0) {
-		y_dir = 1;
-	} else {
-		y_dir = 0;
-		src_offset = (src_y0 + aheight) * src_pitch +
-				src_x0 * (m_iBpp / 8);
-		dst_offset = (dst_y0 + aheight) * dst_pitch +
-				dst_x0 * (m_iBpp / 8);
-		src_y0 += aheight;
-		dst_y0 += aheight;
-	}
-
-	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
-		(x_dir << 20) | (y_dir << 21) | (command << 24) |
-		(clip_region << 23) | (clip_en << 22) | (tp_en << 27);
-	src_pitch = (dst_pitch << 16) | src_pitch;
-	awidth = awidth | (aheight << 16);
-	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
-		(alpha_sel << 16);
-	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
-	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
-	bottom = (bottom << 16) | right;
-
-	unifb_sync(info);
-
-	writel(src_pitch, UGE_PITCH);
-	writel(src_offset, UGE_SRCSTART);
-	writel(dst_offset, UGE_DSTSTART);
-	writel(awidth, UGE_WIDHEIGHT);
-	writel(top, UGE_CLIP0);
-	writel(bottom, UGE_CLIP1);
-	writel(bg_color, UGE_BCOLOR);
-	writel(fg_color, UGE_FCOLOR);
-	writel(alpha_r, UGE_ROPALPHA);
-	writel(src_x0, UGE_SRCXY);
-	writel(dst_x0, UGE_DSTXY);
-	writel(command, UGE_COMMAND);
-}
-
-static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct fb_copyarea modded;
-	u32 vxres, vyres;
-	modded.sx = area->sx;
-	modded.sy = area->sy;
-	modded.dx = area->dx;
-	modded.dy = area->dy;
-	modded.width = area->width;
-	modded.height = area->height;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		sys_copyarea(info, area);
-		return;
-	}
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	if (!modded.width || !modded.height ||
-	    modded.sx >= vxres || modded.sy >= vyres ||
-	    modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.sx + modded.width > vxres)
-		modded.width = vxres - modded.sx;
-	if (modded.dx + modded.width > vxres)
-		modded.width = vxres - modded.dx;
-	if (modded.sy + modded.height > vyres)
-		modded.height = vyres - modded.sy;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	unifb_prim_copyarea(info, &modded);
-}
-
-static void unifb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	sys_imageblit(info, image);
-}
-
-static u_long get_line_length(int xres_virtual, int bpp)
-{
-	u_long length;
-
-	length = xres_virtual * bpp;
-	length = (length + 31) & ~31;
-	length >>= 3;
-	return length;
-}
-
-/*
- *  Setting the video mode has been split into two parts.
- *  First part, xxxfb_check_var, must not write anything
- *  to hardware, it should only verify and adjust var.
- *  This means it doesn't alter par but it does use hardware
- *  data from it to check this var.
- */
-static int unifb_check_var(struct fb_var_screeninfo *var,
-			 struct fb_info *info)
-{
-	u_long line_length;
-
-	/*
-	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
-	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
-	 */
-
-	if (var->vmode & FB_VMODE_CONUPDATE) {
-		var->vmode |= FB_VMODE_YWRAP;
-		var->xoffset = info->var.xoffset;
-		var->yoffset = info->var.yoffset;
-	}
-
-	/*
-	 *  Some very basic checks
-	 */
-	if (!var->xres)
-		var->xres = 1;
-	if (!var->yres)
-		var->yres = 1;
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-	if (var->bits_per_pixel <= 1)
-		var->bits_per_pixel = 1;
-	else if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel <= 24)
-		var->bits_per_pixel = 24;
-	else if (var->bits_per_pixel <= 32)
-		var->bits_per_pixel = 32;
-	else
-		return -EINVAL;
-
-	if (var->xres_virtual < var->xoffset + var->xres)
-		var->xres_virtual = var->xoffset + var->xres;
-	if (var->yres_virtual < var->yoffset + var->yres)
-		var->yres_virtual = var->yoffset + var->yres;
-
-	/*
-	 *  Memory limit
-	 */
-	line_length =
-	    get_line_length(var->xres_virtual, var->bits_per_pixel);
-	if (line_length * var->yres_virtual > UNIFB_MEMSIZE)
-		return -ENOMEM;
-
-	/*
-	 * Now that we checked it we alter var. The reason being is that the
-	 * video mode passed in might not work but slight changes to it might
-	 * make it work. This way we let the user know what is acceptable.
-	 */
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:		/* RGBA 5551 */
-		if (var->transp.length) {
-			var->red.offset = 0;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 5;
-			var->blue.offset = 10;
-			var->blue.length = 5;
-			var->transp.offset = 15;
-			var->transp.length = 1;
-		} else {	/* RGB 565 */
-			var->red.offset = 11;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 6;
-			var->blue.offset = 0;
-			var->blue.length = 5;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-		}
-		break;
-	case 24:		/* RGB 888 */
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 16;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 32:		/* RGBA 8888 */
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	}
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	return 0;
-}
-
-/*
- * This routine actually sets the video mode. It's in here where we
- * the hardware state info->par and fix which can be affected by the
- * change in par. For this driver it doesn't do much.
- */
-static int unifb_set_par(struct fb_info *info)
-{
-	int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
-	int format;
-
-#ifdef CONFIG_PUV3_PM
-	struct clk *clk_vga;
-	u32 pixclk = 0;
-	int i;
-
-	for (i = 0; i <= 10; i++) {
-		if    (info->var.xres         == unifb_modes[i].xres
-		    && info->var.yres         == unifb_modes[i].yres
-		    && info->var.upper_margin == unifb_modes[i].upper_margin
-		    && info->var.lower_margin == unifb_modes[i].lower_margin
-		    && info->var.left_margin  == unifb_modes[i].left_margin
-		    && info->var.right_margin == unifb_modes[i].right_margin
-		    && info->var.hsync_len    == unifb_modes[i].hsync_len
-		    && info->var.vsync_len    == unifb_modes[i].vsync_len) {
-			pixclk = unifb_modes[i].pixclock;
-			break;
-		}
-	}
-
-	/* set clock rate */
-	clk_vga = clk_get(info->device, "VGA_CLK");
-	if (clk_vga == ERR_PTR(-ENOENT))
-		return -ENOENT;
-
-	if (pixclk != 0) {
-		if (clk_set_rate(clk_vga, pixclk)) { /* set clock failed */
-			info->fix = unifb_fix;
-			info->var = unifb_default;
-			if (clk_set_rate(clk_vga, unifb_default.pixclock))
-				return -EINVAL;
-		}
-	}
-#endif
-
-	info->fix.line_length = get_line_length(info->var.xres_virtual,
-						info->var.bits_per_pixel);
-
-	hSyncStart = info->var.xres + info->var.right_margin;
-	hSyncEnd = hSyncStart + info->var.hsync_len;
-	hTotal = hSyncEnd + info->var.left_margin;
-
-	vSyncStart = info->var.yres + info->var.lower_margin;
-	vSyncEnd = vSyncStart + info->var.vsync_len;
-	vTotal = vSyncEnd + info->var.upper_margin;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		format = UDE_CFG_DST8;
-		break;
-	case 16:
-		format = UDE_CFG_DST16;
-		break;
-	case 24:
-		format = UDE_CFG_DST24;
-		break;
-	case 32:
-		format = UDE_CFG_DST32;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	writel(info->fix.smem_start, UDE_FSA);
-	writel(info->var.yres, UDE_LS);
-	writel(get_line_length(info->var.xres,
-			info->var.bits_per_pixel) >> 3, UDE_PS);
-			/* >> 3 for hardware required. */
-	writel((hTotal << 16) | (info->var.xres), UDE_HAT);
-	writel(((hTotal - 1) << 16) | (info->var.xres - 1), UDE_HBT);
-	writel(((hSyncEnd - 1) << 16) | (hSyncStart - 1), UDE_HST);
-	writel((vTotal << 16) | (info->var.yres), UDE_VAT);
-	writel(((vTotal - 1) << 16) | (info->var.yres - 1), UDE_VBT);
-	writel(((vSyncEnd - 1) << 16) | (vSyncStart - 1), UDE_VST);
-	writel(UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE
-			| format | 0xC0000001, UDE_CFG);
-
-	return 0;
-}
-
-/*
- *  Set a single color register. The values supplied are already
- *  rounded down to the hardware's capabilities (according to the
- *  entries in the var structure). Return != 0 for invalid regno.
- */
-static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			 u_int transp, struct fb_info *info)
-{
-	if (regno >= 256)	/* no. of hw registers */
-		return 1;
-
-	/* grayscale works only partially under directcolor */
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue =
-		    (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		red = CNVT_TOHW(red, info->var.red.length);
-		green = CNVT_TOHW(green, info->var.green.length);
-		blue = CNVT_TOHW(blue, info->var.blue.length);
-		transp = CNVT_TOHW(transp, info->var.transp.length);
-		break;
-	case FB_VISUAL_DIRECTCOLOR:
-		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
-		green = CNVT_TOHW(green, 8);
-		blue = CNVT_TOHW(blue, 8);
-		/* hey, there is bug in transp handling... */
-		transp = CNVT_TOHW(transp, 8);
-		break;
-	}
-#undef CNVT_TOHW
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 v;
-
-		if (regno >= 16)
-			return 1;
-
-		v = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset) |
-		    (transp << info->var.transp.offset);
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			break;
-		case 16:
-		case 24:
-		case 32:
-			((u32 *) (info->pseudo_palette))[regno] = v;
-			break;
-		default:
-			return 1;
-		}
-		return 0;
-	}
-	return 0;
-}
-
-/*
- *  Pan or Wrap the Display
- *
- *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- */
-static int unifb_pan_display(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
-{
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0
-		    || var->yoffset >= info->var.yres_virtual
-		    || var->xoffset)
-			return -EINVAL;
-	} else {
-		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-		    var->yoffset + info->var.yres > info->var.yres_virtual)
-			return -EINVAL;
-	}
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-	return 0;
-}
-
-int unifb_mmap(struct fb_info *info,
-		    struct vm_area_struct *vma)
-{
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
-}
-
-static struct fb_ops unifb_ops = {
-	.fb_read        = fb_sys_read,
-	.fb_write       = fb_sys_write,
-	.fb_check_var	= unifb_check_var,
-	.fb_set_par	= unifb_set_par,
-	.fb_setcolreg	= unifb_setcolreg,
-	.fb_pan_display	= unifb_pan_display,
-	.fb_fillrect	= unifb_fillrect,
-	.fb_copyarea	= unifb_copyarea,
-	.fb_imageblit   = unifb_imageblit,
-	.fb_mmap	= unifb_mmap,
-};
-
-/*
- *  Initialisation
- */
-static int unifb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	u32 unifb_regs[UNIFB_REGS_NUM];
-	int retval = -ENOMEM;
-	struct resource *iomem;
-	void *videomemory;
-
-	videomemory = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP,
-				get_order(UNIFB_MEMSIZE));
-	if (!videomemory)
-		goto err;
-
-	memset(videomemory, 0, UNIFB_MEMSIZE);
-
-	unifb_fix.smem_start = virt_to_phys(videomemory);
-	unifb_fix.smem_len = UNIFB_MEMSIZE;
-
-	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	unifb_fix.mmio_start = iomem->start;
-
-	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
-	if (!info)
-		goto err;
-
-	info->screen_base = (char __iomem *)videomemory;
-	info->fbops = &unifb_ops;
-
-	retval = fb_find_mode(&info->var, info, NULL,
-			      unifb_modes, 10, &unifb_modes[0], 16);
-
-	if (!retval || (retval == 4))
-		info->var = unifb_default;
-
-	info->fix = unifb_fix;
-	info->pseudo_palette = info->par;
-	info->par = NULL;
-	info->flags = FBINFO_FLAG_DEFAULT;
-#ifdef FB_ACCEL_PUV3_UNIGFX
-	info->fix.accel = FB_ACCEL_PUV3_UNIGFX;
-#endif
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0)
-		goto err1;
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err2;
-	platform_set_drvdata(dev, info);
-	platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM);
-
-	fb_info(info, "Virtual frame buffer device, using %dM of video memory\n",
-		UNIFB_MEMSIZE >> 20);
-	return 0;
-err2:
-	fb_dealloc_cmap(&info->cmap);
-err1:
-	framebuffer_release(info);
-err:
-	return retval;
-}
-
-static int unifb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int unifb_resume(struct platform_device *dev)
-{
-	int rc = 0;
-	u32 *unifb_regs = dev->dev.platform_data;
-
-	if (dev->dev.power.power_state.event == PM_EVENT_ON)
-		return 0;
-
-	console_lock();
-
-	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-		writel(unifb_regs[0], UDE_FSA);
-		writel(unifb_regs[1], UDE_LS);
-		writel(unifb_regs[2], UDE_PS);
-		writel(unifb_regs[3], UDE_HAT);
-		writel(unifb_regs[4], UDE_HBT);
-		writel(unifb_regs[5], UDE_HST);
-		writel(unifb_regs[6], UDE_VAT);
-		writel(unifb_regs[7], UDE_VBT);
-		writel(unifb_regs[8], UDE_VST);
-		writel(unifb_regs[9], UDE_CFG);
-	}
-	dev->dev.power.power_state = PMSG_ON;
-
-	console_unlock();
-
-	return rc;
-}
-
-static int unifb_suspend(struct platform_device *dev, pm_message_t mesg)
-{
-	u32 *unifb_regs = dev->dev.platform_data;
-
-	unifb_regs[0] = readl(UDE_FSA);
-	unifb_regs[1] = readl(UDE_LS);
-	unifb_regs[2] = readl(UDE_PS);
-	unifb_regs[3] = readl(UDE_HAT);
-	unifb_regs[4] = readl(UDE_HBT);
-	unifb_regs[5] = readl(UDE_HST);
-	unifb_regs[6] = readl(UDE_VAT);
-	unifb_regs[7] = readl(UDE_VBT);
-	unifb_regs[8] = readl(UDE_VST);
-	unifb_regs[9] = readl(UDE_CFG);
-
-	if (mesg.event == dev->dev.power.power_state.event)
-		return 0;
-
-	switch (mesg.event) {
-	case PM_EVENT_FREEZE:		/* about to take snapshot */
-	case PM_EVENT_PRETHAW:		/* before restoring snapshot */
-		goto done;
-	}
-
-	console_lock();
-
-	/* do nothing... */
-
-	console_unlock();
-
-done:
-	dev->dev.power.power_state = mesg;
-
-	return 0;
-}
-#else
-#define	unifb_resume	NULL
-#define unifb_suspend	NULL
-#endif
-
-static struct platform_driver unifb_driver = {
-	.probe	 = unifb_probe,
-	.remove  = unifb_remove,
-	.resume  = unifb_resume,
-	.suspend = unifb_suspend,
-	.driver  = {
-		.name	= "PKUnity-v3-UNIGFX",
-	},
-};
-
-static int __init unifb_init(void)
-{
-#ifndef MODULE
-	if (fb_get_options("unifb", NULL))
-		return -ENODEV;
-#endif
-
-	return platform_driver_register(&unifb_driver);
-}
-
-module_init(unifb_init);
-
-static void __exit unifb_exit(void)
-{
-	platform_driver_unregister(&unifb_driver);
-}
-
-module_exit(unifb_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c
deleted file mode 100644
index 2b106f046fde..000000000000
--- a/drivers/video/fb_ddc.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * drivers/video/fb_ddc.c - DDC/EDID read support.
- *
- *  Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/fb.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/slab.h>
-
-#include "edid.h"
-
-#define DDC_ADDR	0x50
-
-static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter)
-{
-	unsigned char start = 0x0;
-	unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
-	struct i2c_msg msgs[] = {
-		{
-			.addr	= DDC_ADDR,
-			.flags	= 0,
-			.len	= 1,
-			.buf	= &start,
-		}, {
-			.addr	= DDC_ADDR,
-			.flags	= I2C_M_RD,
-			.len	= EDID_LENGTH,
-			.buf	= buf,
-		}
-	};
-
-	if (!buf) {
-		dev_warn(&adapter->dev, "unable to allocate memory for EDID "
-			 "block.\n");
-		return NULL;
-	}
-
-	if (i2c_transfer(adapter, msgs, 2) == 2)
-		return buf;
-
-	dev_warn(&adapter->dev, "unable to read EDID block.\n");
-	kfree(buf);
-	return NULL;
-}
-
-unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
-{
-	struct i2c_algo_bit_data *algo_data = adapter->algo_data;
-	unsigned char *edid = NULL;
-	int i, j;
-
-	algo_data->setscl(algo_data->data, 1);
-
-	for (i = 0; i < 3; i++) {
-		/* For some old monitors we need the
-		 * following process to initialize/stop DDC
-		 */
-		algo_data->setsda(algo_data->data, 1);
-		msleep(13);
-
-		algo_data->setscl(algo_data->data, 1);
-		for (j = 0; j < 5; j++) {
-			msleep(10);
-			if (algo_data->getscl(algo_data->data))
-				break;
-		}
-		if (j == 5)
-			continue;
-
-		algo_data->setsda(algo_data->data, 0);
-		msleep(15);
-		algo_data->setscl(algo_data->data, 0);
-		msleep(15);
-		algo_data->setsda(algo_data->data, 1);
-		msleep(15);
-
-		/* Do the real work */
-		edid = fb_do_probe_ddc_edid(adapter);
-		algo_data->setsda(algo_data->data, 0);
-		algo_data->setscl(algo_data->data, 0);
-		msleep(15);
-
-		algo_data->setscl(algo_data->data, 1);
-		for (j = 0; j < 10; j++) {
-			msleep(10);
-			if (algo_data->getscl(algo_data->data))
-				break;
-		}
-
-		algo_data->setsda(algo_data->data, 1);
-		msleep(15);
-		algo_data->setscl(algo_data->data, 0);
-		algo_data->setsda(algo_data->data, 0);
-		if (edid)
-			break;
-	}
-	/* Release the DDC lines when done or the Apple Cinema HD display
-	 * will switch off
-	 */
-	algo_data->setsda(algo_data->data, 1);
-	algo_data->setscl(algo_data->data, 1);
-
-	adapter->class |= I2C_CLASS_DDC;
-	return edid;
-}
-
-EXPORT_SYMBOL_GPL(fb_ddc_read);
-
-MODULE_AUTHOR("Dennis Munsie <dmunsie@cecropia.com>");
-MODULE_DESCRIPTION("DDC/EDID reading support");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
deleted file mode 100644
index 900aa4ecd617..000000000000
--- a/drivers/video/fb_defio.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- *  linux/drivers/video/fb_defio.c
- *
- *  Copyright (C) 2006 Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/list.h>
-
-/* to support deferred IO */
-#include <linux/rmap.h>
-#include <linux/pagemap.h>
-
-static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs)
-{
-	void *screen_base = (void __force *) info->screen_base;
-	struct page *page;
-
-	if (is_vmalloc_addr(screen_base + offs))
-		page = vmalloc_to_page(screen_base + offs);
-	else
-		page = pfn_to_page((info->fix.smem_start + offs) >> PAGE_SHIFT);
-
-	return page;
-}
-
-/* this is to find and return the vmalloc-ed fb pages */
-static int fb_deferred_io_fault(struct vm_area_struct *vma,
-				struct vm_fault *vmf)
-{
-	unsigned long offset;
-	struct page *page;
-	struct fb_info *info = vma->vm_private_data;
-
-	offset = vmf->pgoff << PAGE_SHIFT;
-	if (offset >= info->fix.smem_len)
-		return VM_FAULT_SIGBUS;
-
-	page = fb_deferred_io_page(info, offset);
-	if (!page)
-		return VM_FAULT_SIGBUS;
-
-	get_page(page);
-
-	if (vma->vm_file)
-		page->mapping = vma->vm_file->f_mapping;
-	else
-		printk(KERN_ERR "no mapping available\n");
-
-	BUG_ON(!page->mapping);
-	page->index = vmf->pgoff;
-
-	vmf->page = page;
-	return 0;
-}
-
-int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
-	struct fb_info *info = file->private_data;
-	struct inode *inode = file_inode(file);
-	int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
-	if (err)
-		return err;
-
-	/* Skip if deferred io is compiled-in but disabled on this fbdev */
-	if (!info->fbdefio)
-		return 0;
-
-	mutex_lock(&inode->i_mutex);
-	/* Kill off the delayed work */
-	cancel_delayed_work_sync(&info->deferred_work);
-
-	/* Run it immediately */
-	err = schedule_delayed_work(&info->deferred_work, 0);
-	mutex_unlock(&inode->i_mutex);
-	return err;
-}
-EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
-
-/* vm_ops->page_mkwrite handler */
-static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
-				  struct vm_fault *vmf)
-{
-	struct page *page = vmf->page;
-	struct fb_info *info = vma->vm_private_data;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct page *cur;
-
-	/* this is a callback we get when userspace first tries to
-	write to the page. we schedule a workqueue. that workqueue
-	will eventually mkclean the touched pages and execute the
-	deferred framebuffer IO. then if userspace touches a page
-	again, we repeat the same scheme */
-
-	file_update_time(vma->vm_file);
-
-	/* protect against the workqueue changing the page list */
-	mutex_lock(&fbdefio->lock);
-
-	/* first write in this cycle, notify the driver */
-	if (fbdefio->first_io && list_empty(&fbdefio->pagelist))
-		fbdefio->first_io(info);
-
-	/*
-	 * We want the page to remain locked from ->page_mkwrite until
-	 * the PTE is marked dirty to avoid page_mkclean() being called
-	 * before the PTE is updated, which would leave the page ignored
-	 * by defio.
-	 * Do this by locking the page here and informing the caller
-	 * about it with VM_FAULT_LOCKED.
-	 */
-	lock_page(page);
-
-	/* we loop through the pagelist before adding in order
-	to keep the pagelist sorted */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-		/* this check is to catch the case where a new
-		process could start writing to the same page
-		through a new pte. this new access can cause the
-		mkwrite even when the original ps's pte is marked
-		writable */
-		if (unlikely(cur == page))
-			goto page_already_added;
-		else if (cur->index > page->index)
-			break;
-	}
-
-	list_add_tail(&page->lru, &cur->lru);
-
-page_already_added:
-	mutex_unlock(&fbdefio->lock);
-
-	/* come back after delay to process the deferred IO */
-	schedule_delayed_work(&info->deferred_work, fbdefio->delay);
-	return VM_FAULT_LOCKED;
-}
-
-static const struct vm_operations_struct fb_deferred_io_vm_ops = {
-	.fault		= fb_deferred_io_fault,
-	.page_mkwrite	= fb_deferred_io_mkwrite,
-};
-
-static int fb_deferred_io_set_page_dirty(struct page *page)
-{
-	if (!PageDirty(page))
-		SetPageDirty(page);
-	return 0;
-}
-
-static const struct address_space_operations fb_deferred_io_aops = {
-	.set_page_dirty = fb_deferred_io_set_page_dirty,
-};
-
-static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	vma->vm_ops = &fb_deferred_io_vm_ops;
-	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
-	if (!(info->flags & FBINFO_VIRTFB))
-		vma->vm_flags |= VM_IO;
-	vma->vm_private_data = info;
-	return 0;
-}
-
-/* workqueue callback */
-static void fb_deferred_io_work(struct work_struct *work)
-{
-	struct fb_info *info = container_of(work, struct fb_info,
-						deferred_work.work);
-	struct list_head *node, *next;
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-
-	/* here we mkclean the pages, then do all deferred IO */
-	mutex_lock(&fbdefio->lock);
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-		lock_page(cur);
-		page_mkclean(cur);
-		unlock_page(cur);
-	}
-
-	/* driver's callback with pagelist */
-	fbdefio->deferred_io(info, &fbdefio->pagelist);
-
-	/* clear the list */
-	list_for_each_safe(node, next, &fbdefio->pagelist) {
-		list_del(node);
-	}
-	mutex_unlock(&fbdefio->lock);
-}
-
-void fb_deferred_io_init(struct fb_info *info)
-{
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-
-	BUG_ON(!fbdefio);
-	mutex_init(&fbdefio->lock);
-	info->fbops->fb_mmap = fb_deferred_io_mmap;
-	INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work);
-	INIT_LIST_HEAD(&fbdefio->pagelist);
-	if (fbdefio->delay == 0) /* set a default of 1 s */
-		fbdefio->delay = HZ;
-}
-EXPORT_SYMBOL_GPL(fb_deferred_io_init);
-
-void fb_deferred_io_open(struct fb_info *info,
-			 struct inode *inode,
-			 struct file *file)
-{
-	file->f_mapping->a_ops = &fb_deferred_io_aops;
-}
-EXPORT_SYMBOL_GPL(fb_deferred_io_open);
-
-void fb_deferred_io_cleanup(struct fb_info *info)
-{
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct page *page;
-	int i;
-
-	BUG_ON(!fbdefio);
-	cancel_delayed_work_sync(&info->deferred_work);
-
-	/* clear out the mapping that we setup */
-	for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
-		page = fb_deferred_io_page(info, i);
-		page->mapping = NULL;
-	}
-
-	info->fbops->fb_mmap = NULL;
-	mutex_destroy(&fbdefio->lock);
-}
-EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
deleted file mode 100644
index 624ee115f129..000000000000
--- a/drivers/video/fb_draw.h
+++ /dev/null
@@ -1,186 +0,0 @@
-#ifndef _FB_DRAW_H
-#define _FB_DRAW_H
-
-#include <asm/types.h>
-#include <linux/fb.h>
-#include <linux/bug.h>
-
-    /*
-     *  Compose two values, using a bitmask as decision value
-     *  This is equivalent to (a & mask) | (b & ~mask)
-     */
-
-static inline unsigned long
-comp(unsigned long a, unsigned long b, unsigned long mask)
-{
-    return ((a ^ b) & mask) ^ b;
-}
-
-    /*
-     *  Create a pattern with the given pixel's color
-     */
-
-#if BITS_PER_LONG == 64
-static inline unsigned long
-pixel_to_pat( u32 bpp, u32 pixel)
-{
-	switch (bpp) {
-	case 1:
-		return 0xfffffffffffffffful*pixel;
-	case 2:
-		return 0x5555555555555555ul*pixel;
-	case 4:
-		return 0x1111111111111111ul*pixel;
-	case 8:
-		return 0x0101010101010101ul*pixel;
-	case 12:
-		return 0x1001001001001001ul*pixel;
-	case 16:
-		return 0x0001000100010001ul*pixel;
-	case 24:
-		return 0x0001000001000001ul*pixel;
-	case 32:
-		return 0x0000000100000001ul*pixel;
-	default:
-		WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp);
-		return 0;
-    }
-}
-#else
-static inline unsigned long
-pixel_to_pat( u32 bpp, u32 pixel)
-{
-	switch (bpp) {
-	case 1:
-		return 0xfffffffful*pixel;
-	case 2:
-		return 0x55555555ul*pixel;
-	case 4:
-		return 0x11111111ul*pixel;
-	case 8:
-		return 0x01010101ul*pixel;
-	case 12:
-		return 0x01001001ul*pixel;
-	case 16:
-		return 0x00010001ul*pixel;
-	case 24:
-		return 0x01000001ul*pixel;
-	case 32:
-		return 0x00000001ul*pixel;
-	default:
-		WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp);
-		return 0;
-    }
-}
-#endif
-
-#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE
-#if BITS_PER_LONG == 64
-#define REV_PIXELS_MASK1 0x5555555555555555ul
-#define REV_PIXELS_MASK2 0x3333333333333333ul
-#define REV_PIXELS_MASK4 0x0f0f0f0f0f0f0f0ful
-#else
-#define REV_PIXELS_MASK1 0x55555555ul
-#define REV_PIXELS_MASK2 0x33333333ul
-#define REV_PIXELS_MASK4 0x0f0f0f0ful
-#endif
-
-static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
-						  u32 bswapmask)
-{
-	if (bswapmask & 1)
-		val = comp(val >> 1, val << 1, REV_PIXELS_MASK1);
-	if (bswapmask & 2)
-		val = comp(val >> 2, val << 2, REV_PIXELS_MASK2);
-	if (bswapmask & 3)
-		val = comp(val >> 4, val << 4, REV_PIXELS_MASK4);
-	return val;
-}
-
-static inline u32 fb_shifted_pixels_mask_u32(struct fb_info *p, u32 index,
-					     u32 bswapmask)
-{
-	u32 mask;
-
-	if (!bswapmask) {
-		mask = FB_SHIFT_HIGH(p, ~(u32)0, index);
-	} else {
-		mask = 0xff << FB_LEFT_POS(p, 8);
-		mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask;
-		mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask));
-#if defined(__i386__) || defined(__x86_64__)
-		/* Shift argument is limited to 0 - 31 on x86 based CPU's */
-		if(index + bswapmask < 32)
-#endif
-			mask |= FB_SHIFT_HIGH(p, ~(u32)0,
-					(index + bswapmask) & ~(bswapmask));
-	}
-	return mask;
-}
-
-static inline unsigned long fb_shifted_pixels_mask_long(struct fb_info *p,
-							u32 index,
-							u32 bswapmask)
-{
-	unsigned long mask;
-
-	if (!bswapmask) {
-		mask = FB_SHIFT_HIGH(p, ~0UL, index);
-	} else {
-		mask = 0xff << FB_LEFT_POS(p, 8);
-		mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask;
-		mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask));
-#if defined(__i386__) || defined(__x86_64__)
-		/* Shift argument is limited to 0 - 31 on x86 based CPU's */
-		if(index + bswapmask < BITS_PER_LONG)
-#endif
-			mask |= FB_SHIFT_HIGH(p, ~0UL,
-					(index + bswapmask) & ~(bswapmask));
-	}
-	return mask;
-}
-
-
-static inline u32 fb_compute_bswapmask(struct fb_info *info)
-{
-	u32 bswapmask = 0;
-	unsigned bpp = info->var.bits_per_pixel;
-
-	if ((bpp < 8) && (info->var.nonstd & FB_NONSTD_REV_PIX_IN_B)) {
-		/*
-		 * Reversed order of pixel layout in bytes
-		 * works only for 1, 2 and 4 bpp
-		 */
-		bswapmask = 7 - bpp + 1;
-	}
-	return bswapmask;
-}
-
-#else /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
-
-static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
-						  u32 bswapmask)
-{
-	return val;
-}
-
-#define fb_shifted_pixels_mask_u32(p, i, b) FB_SHIFT_HIGH((p), ~(u32)0, (i))
-#define fb_shifted_pixels_mask_long(p, i, b) FB_SHIFT_HIGH((p), ~0UL, (i))
-#define fb_compute_bswapmask(...) 0
-
-#endif  /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
-
-#define cpu_to_le_long _cpu_to_le_long(BITS_PER_LONG)
-#define _cpu_to_le_long(x) __cpu_to_le_long(x)
-#define __cpu_to_le_long(x) cpu_to_le##x
-
-#define le_long_to_cpu _le_long_to_cpu(BITS_PER_LONG)
-#define _le_long_to_cpu(x) __le_long_to_cpu(x)
-#define __le_long_to_cpu(x) le##x##_to_cpu
-
-static inline unsigned long rolx(unsigned long word, unsigned int shift, unsigned int x)
-{
-	return (word << shift) | (word >> (x - shift));
-}
-
-#endif /* FB_DRAW_H */
diff --git a/drivers/video/fb_notify.c b/drivers/video/fb_notify.c
deleted file mode 100644
index 74c2da528884..000000000000
--- a/drivers/video/fb_notify.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  linux/drivers/video/fb_notify.c
- *
- *  Copyright (C) 2006 Antonino Daplas <adaplas@pol.net>
- *
- *	2001 - Documented with DocBook
- *	- Brad Douglas <brad@neruo.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-#include <linux/fb.h>
-#include <linux/notifier.h>
-#include <linux/export.h>
-
-static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
-
-/**
- *	fb_register_client - register a client notifier
- *	@nb: notifier block to callback on events
- */
-int fb_register_client(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&fb_notifier_list, nb);
-}
-EXPORT_SYMBOL(fb_register_client);
-
-/**
- *	fb_unregister_client - unregister a client notifier
- *	@nb: notifier block to callback on events
- */
-int fb_unregister_client(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
-}
-EXPORT_SYMBOL(fb_unregister_client);
-
-/**
- * fb_notifier_call_chain - notify clients of fb_events
- *
- */
-int fb_notifier_call_chain(unsigned long val, void *v)
-{
-	return blocking_notifier_call_chain(&fb_notifier_list, val, v);
-}
-EXPORT_SYMBOL_GPL(fb_notifier_call_chain);
diff --git a/drivers/video/fb_sys_fops.c b/drivers/video/fb_sys_fops.c
deleted file mode 100644
index ff275d7f3eaf..000000000000
--- a/drivers/video/fb_sys_fops.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * linux/drivers/video/fb_sys_read.c - Generic file operations where
- * framebuffer is in system RAM
- *
- * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-#include <linux/fb.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-
-ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
-		    loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	void *src;
-	int err = 0;
-	unsigned long total_size;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->screen_size;
-
-	if (total_size == 0)
-		total_size = info->fix.smem_len;
-
-	if (p >= total_size)
-		return 0;
-
-	if (count >= total_size)
-		count = total_size;
-
-	if (count + p > total_size)
-		count = total_size - p;
-
-	src = (void __force *)(info->screen_base + p);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	if (copy_to_user(buf, src, count))
-		err = -EFAULT;
-
-	if  (!err)
-		*ppos += count;
-
-	return (err) ? err : count;
-}
-EXPORT_SYMBOL_GPL(fb_sys_read);
-
-ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
-		     size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	void *dst;
-	int err = 0;
-	unsigned long total_size;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->screen_size;
-
-	if (total_size == 0)
-		total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EFBIG;
-
-	if (count > total_size) {
-		err = -EFBIG;
-		count = total_size;
-	}
-
-	if (count + p > total_size) {
-		if (!err)
-			err = -ENOSPC;
-
-		count = total_size - p;
-	}
-
-	dst = (void __force *) (info->screen_base + p);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	if (copy_from_user(dst, buf, count))
-		err = -EFAULT;
-
-	if  (!err)
-		*ppos += count;
-
-	return (err) ? err : count;
-}
-EXPORT_SYMBOL_GPL(fb_sys_write);
-
-MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
-MODULE_DESCRIPTION("Generic file read (fb in system RAM)");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
deleted file mode 100644
index f89245b8ba8e..000000000000
--- a/drivers/video/fbcmap.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- *  linux/drivers/video/fbcmap.c -- Colormap handling for frame buffer devices
- *
- *	Created 15 Jun 1997 by Geert Uytterhoeven
- *
- *	2001 - Documented with DocBook
- *	- Brad Douglas <brad@neruo.com>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/fb.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-static u16 red2[] __read_mostly = {
-    0x0000, 0xaaaa
-};
-static u16 green2[] __read_mostly = {
-    0x0000, 0xaaaa
-};
-static u16 blue2[] __read_mostly = {
-    0x0000, 0xaaaa
-};
-
-static u16 red4[] __read_mostly = {
-    0x0000, 0xaaaa, 0x5555, 0xffff
-};
-static u16 green4[] __read_mostly = {
-    0x0000, 0xaaaa, 0x5555, 0xffff
-};
-static u16 blue4[] __read_mostly = {
-    0x0000, 0xaaaa, 0x5555, 0xffff
-};
-
-static u16 red8[] __read_mostly = {
-    0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa
-};
-static u16 green8[] __read_mostly = {
-    0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa
-};
-static u16 blue8[] __read_mostly = {
-    0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa
-};
-
-static u16 red16[] __read_mostly = {
-    0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
-    0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
-};
-static u16 green16[] __read_mostly = {
-    0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
-    0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
-};
-static u16 blue16[] __read_mostly = {
-    0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
-    0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
-};
-
-static const struct fb_cmap default_2_colors = {
-    .len=2, .red=red2, .green=green2, .blue=blue2
-};
-static const struct fb_cmap default_8_colors = {
-    .len=8, .red=red8, .green=green8, .blue=blue8
-};
-static const struct fb_cmap default_4_colors = {
-    .len=4, .red=red4, .green=green4, .blue=blue4
-};
-static const struct fb_cmap default_16_colors = {
-    .len=16, .red=red16, .green=green16, .blue=blue16
-};
-
-
-
-/**
- *	fb_alloc_cmap - allocate a colormap
- *	@cmap: frame buffer colormap structure
- *	@len: length of @cmap
- *	@transp: boolean, 1 if there is transparency, 0 otherwise
- *	@flags: flags for kmalloc memory allocation
- *
- *	Allocates memory for a colormap @cmap.  @len is the
- *	number of entries in the palette.
- *
- *	Returns negative errno on error, or zero on success.
- *
- */
-
-int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
-{
-	int size = len * sizeof(u16);
-	int ret = -ENOMEM;
-
-	if (cmap->len != len) {
-		fb_dealloc_cmap(cmap);
-		if (!len)
-			return 0;
-
-		cmap->red = kmalloc(size, flags);
-		if (!cmap->red)
-			goto fail;
-		cmap->green = kmalloc(size, flags);
-		if (!cmap->green)
-			goto fail;
-		cmap->blue = kmalloc(size, flags);
-		if (!cmap->blue)
-			goto fail;
-		if (transp) {
-			cmap->transp = kmalloc(size, flags);
-			if (!cmap->transp)
-				goto fail;
-		} else {
-			cmap->transp = NULL;
-		}
-	}
-	cmap->start = 0;
-	cmap->len = len;
-	ret = fb_copy_cmap(fb_default_cmap(len), cmap);
-	if (ret)
-		goto fail;
-	return 0;
-
-fail:
-	fb_dealloc_cmap(cmap);
-	return ret;
-}
-
-int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
-{
-	return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
-}
-
-/**
- *      fb_dealloc_cmap - deallocate a colormap
- *      @cmap: frame buffer colormap structure
- *
- *      Deallocates a colormap that was previously allocated with
- *      fb_alloc_cmap().
- *
- */
-
-void fb_dealloc_cmap(struct fb_cmap *cmap)
-{
-	kfree(cmap->red);
-	kfree(cmap->green);
-	kfree(cmap->blue);
-	kfree(cmap->transp);
-
-	cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
-	cmap->len = 0;
-}
-
-/**
- *	fb_copy_cmap - copy a colormap
- *	@from: frame buffer colormap structure
- *	@to: frame buffer colormap structure
- *
- *	Copy contents of colormap from @from to @to.
- */
-
-int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
-{
-	int tooff = 0, fromoff = 0;
-	int size;
-
-	if (to->start > from->start)
-		fromoff = to->start - from->start;
-	else
-		tooff = from->start - to->start;
-	size = to->len - tooff;
-	if (size > (int) (from->len - fromoff))
-		size = from->len - fromoff;
-	if (size <= 0)
-		return -EINVAL;
-	size *= sizeof(u16);
-
-	memcpy(to->red+tooff, from->red+fromoff, size);
-	memcpy(to->green+tooff, from->green+fromoff, size);
-	memcpy(to->blue+tooff, from->blue+fromoff, size);
-	if (from->transp && to->transp)
-		memcpy(to->transp+tooff, from->transp+fromoff, size);
-	return 0;
-}
-
-int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
-{
-	int tooff = 0, fromoff = 0;
-	int size;
-
-	if (to->start > from->start)
-		fromoff = to->start - from->start;
-	else
-		tooff = from->start - to->start;
-	size = to->len - tooff;
-	if (size > (int) (from->len - fromoff))
-		size = from->len - fromoff;
-	if (size <= 0)
-		return -EINVAL;
-	size *= sizeof(u16);
-
-	if (copy_to_user(to->red+tooff, from->red+fromoff, size))
-		return -EFAULT;
-	if (copy_to_user(to->green+tooff, from->green+fromoff, size))
-		return -EFAULT;
-	if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
-		return -EFAULT;
-	if (from->transp && to->transp)
-		if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
-			return -EFAULT;
-	return 0;
-}
-
-/**
- *	fb_set_cmap - set the colormap
- *	@cmap: frame buffer colormap structure
- *	@info: frame buffer info structure
- *
- *	Sets the colormap @cmap for a screen of device @info.
- *
- *	Returns negative errno on error, or zero on success.
- *
- */
-
-int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
-{
-	int i, start, rc = 0;
-	u16 *red, *green, *blue, *transp;
-	u_int hred, hgreen, hblue, htransp = 0xffff;
-
-	red = cmap->red;
-	green = cmap->green;
-	blue = cmap->blue;
-	transp = cmap->transp;
-	start = cmap->start;
-
-	if (start < 0 || (!info->fbops->fb_setcolreg &&
-			  !info->fbops->fb_setcmap))
-		return -EINVAL;
-	if (info->fbops->fb_setcmap) {
-		rc = info->fbops->fb_setcmap(cmap, info);
-	} else {
-		for (i = 0; i < cmap->len; i++) {
-			hred = *red++;
-			hgreen = *green++;
-			hblue = *blue++;
-			if (transp)
-				htransp = *transp++;
-			if (info->fbops->fb_setcolreg(start++,
-						      hred, hgreen, hblue,
-						      htransp, info))
-				break;
-		}
-	}
-	if (rc == 0)
-		fb_copy_cmap(cmap, &info->cmap);
-
-	return rc;
-}
-
-int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
-{
-	int rc, size = cmap->len * sizeof(u16);
-	struct fb_cmap umap;
-
-	if (size < 0 || size < cmap->len)
-		return -E2BIG;
-
-	memset(&umap, 0, sizeof(struct fb_cmap));
-	rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
-				GFP_KERNEL);
-	if (rc)
-		return rc;
-	if (copy_from_user(umap.red, cmap->red, size) ||
-	    copy_from_user(umap.green, cmap->green, size) ||
-	    copy_from_user(umap.blue, cmap->blue, size) ||
-	    (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
-		rc = -EFAULT;
-		goto out;
-	}
-	umap.start = cmap->start;
-	if (!lock_fb_info(info)) {
-		rc = -ENODEV;
-		goto out;
-	}
-
-	rc = fb_set_cmap(&umap, info);
-	unlock_fb_info(info);
-out:
-	fb_dealloc_cmap(&umap);
-	return rc;
-}
-
-/**
- *	fb_default_cmap - get default colormap
- *	@len: size of palette for a depth
- *
- *	Gets the default colormap for a specific screen depth.  @len
- *	is the size of the palette for a particular screen depth.
- *
- *	Returns pointer to a frame buffer colormap structure.
- *
- */
-
-const struct fb_cmap *fb_default_cmap(int len)
-{
-    if (len <= 2)
-	return &default_2_colors;
-    if (len <= 4)
-	return &default_4_colors;
-    if (len <= 8)
-	return &default_8_colors;
-    return &default_16_colors;
-}
-
-
-/**
- *	fb_invert_cmaps - invert all defaults colormaps
- *
- *	Invert all default colormaps.
- *
- */
-
-void fb_invert_cmaps(void)
-{
-    u_int i;
-
-    for (i = 0; i < ARRAY_SIZE(red2); i++) {
-	red2[i] = ~red2[i];
-	green2[i] = ~green2[i];
-	blue2[i] = ~blue2[i];
-    }
-    for (i = 0; i < ARRAY_SIZE(red4); i++) {
-	red4[i] = ~red4[i];
-	green4[i] = ~green4[i];
-	blue4[i] = ~blue4[i];
-    }
-    for (i = 0; i < ARRAY_SIZE(red8); i++) {
-	red8[i] = ~red8[i];
-	green8[i] = ~green8[i];
-	blue8[i] = ~blue8[i];
-    }
-    for (i = 0; i < ARRAY_SIZE(red16); i++) {
-	red16[i] = ~red16[i];
-	green16[i] = ~green16[i];
-	blue16[i] = ~blue16[i];
-    }
-}
-
-
-    /*
-     *  Visible symbols for modules
-     */
-
-EXPORT_SYMBOL(fb_alloc_cmap);
-EXPORT_SYMBOL(fb_dealloc_cmap);
-EXPORT_SYMBOL(fb_copy_cmap);
-EXPORT_SYMBOL(fb_set_cmap);
-EXPORT_SYMBOL(fb_default_cmap);
-EXPORT_SYMBOL(fb_invert_cmaps);
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
deleted file mode 100644
index 7cb715dfc0e1..000000000000
--- a/drivers/video/fbcvt.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * linux/drivers/video/fbcvt.c - VESA(TM) Coordinated Video Timings
- *
- * Copyright (C) 2005 Antonino Daplas <adaplas@pol.net>
- *
- *      Based from the VESA(TM) Coordinated Video Timing Generator by
- *      Graham Loveridge April 9, 2003 available at
- *      http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-#include <linux/fb.h>
-#include <linux/slab.h>
-
-#define FB_CVT_CELLSIZE               8
-#define FB_CVT_GTF_C                 40
-#define FB_CVT_GTF_J                 20
-#define FB_CVT_GTF_K                128
-#define FB_CVT_GTF_M                600
-#define FB_CVT_MIN_VSYNC_BP         550
-#define FB_CVT_MIN_VPORCH             3
-#define FB_CVT_MIN_BPORCH             6
-
-#define FB_CVT_RB_MIN_VBLANK        460
-#define FB_CVT_RB_HBLANK            160
-#define FB_CVT_RB_V_FPORCH            3
-
-#define FB_CVT_FLAG_REDUCED_BLANK 1
-#define FB_CVT_FLAG_MARGINS       2
-#define FB_CVT_FLAG_INTERLACED    4
-
-struct fb_cvt_data {
-	u32 xres;
-	u32 yres;
-	u32 refresh;
-	u32 f_refresh;
-	u32 pixclock;
-	u32 hperiod;
-	u32 hblank;
-	u32 hfreq;
-	u32 htotal;
-	u32 vtotal;
-	u32 vsync;
-	u32 hsync;
-	u32 h_front_porch;
-	u32 h_back_porch;
-	u32 v_front_porch;
-	u32 v_back_porch;
-	u32 h_margin;
-	u32 v_margin;
-	u32 interlace;
-	u32 aspect_ratio;
-	u32 active_pixels;
-	u32 flags;
-	u32 status;
-};
-
-static const unsigned char fb_cvt_vbi_tab[] = {
-	4,        /* 4:3      */
-	5,        /* 16:9     */
-	6,        /* 16:10    */
-	7,        /* 5:4      */
-	7,        /* 15:9     */
-	8,        /* reserved */
-	9,        /* reserved */
-	10        /* custom   */
-};
-
-/* returns hperiod * 1000 */
-static u32 fb_cvt_hperiod(struct fb_cvt_data *cvt)
-{
-	u32 num = 1000000000/cvt->f_refresh;
-	u32 den;
-
-	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
-		num -= FB_CVT_RB_MIN_VBLANK * 1000;
-		den = 2 * (cvt->yres/cvt->interlace + 2 * cvt->v_margin);
-	} else {
-		num -= FB_CVT_MIN_VSYNC_BP * 1000;
-		den = 2 * (cvt->yres/cvt->interlace + cvt->v_margin * 2
-			   + FB_CVT_MIN_VPORCH + cvt->interlace/2);
-	}
-
-	return 2 * (num/den);
-}
-
-/* returns ideal duty cycle * 1000 */
-static u32 fb_cvt_ideal_duty_cycle(struct fb_cvt_data *cvt)
-{
-	u32 c_prime = (FB_CVT_GTF_C - FB_CVT_GTF_J) *
-		(FB_CVT_GTF_K) + 256 * FB_CVT_GTF_J;
-	u32 m_prime = (FB_CVT_GTF_K * FB_CVT_GTF_M);
-	u32 h_period_est = cvt->hperiod;
-
-	return (1000 * c_prime  - ((m_prime * h_period_est)/1000))/256;
-}
-
-static u32 fb_cvt_hblank(struct fb_cvt_data *cvt)
-{
-	u32 hblank = 0;
-
-	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
-		hblank = FB_CVT_RB_HBLANK;
-	else {
-		u32 ideal_duty_cycle = fb_cvt_ideal_duty_cycle(cvt);
-		u32 active_pixels = cvt->active_pixels;
-
-		if (ideal_duty_cycle < 20000)
-			hblank = (active_pixels * 20000)/
-				(100000 - 20000);
-		else {
-			hblank = (active_pixels * ideal_duty_cycle)/
-				(100000 - ideal_duty_cycle);
-		}
-	}
-
-	hblank &= ~((2 * FB_CVT_CELLSIZE) - 1);
-
-	return hblank;
-}
-
-static u32 fb_cvt_hsync(struct fb_cvt_data *cvt)
-{
-	u32 hsync;
-
-	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
-		hsync = 32;
-	else
-		hsync = (FB_CVT_CELLSIZE * cvt->htotal)/100;
-
-	hsync &= ~(FB_CVT_CELLSIZE - 1);
-	return hsync;
-}
-
-static u32 fb_cvt_vbi_lines(struct fb_cvt_data *cvt)
-{
-	u32 vbi_lines, min_vbi_lines, act_vbi_lines;
-
-	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
-		vbi_lines = (1000 * FB_CVT_RB_MIN_VBLANK)/cvt->hperiod + 1;
-		min_vbi_lines =  FB_CVT_RB_V_FPORCH + cvt->vsync +
-			FB_CVT_MIN_BPORCH;
-
-	} else {
-		vbi_lines = (FB_CVT_MIN_VSYNC_BP * 1000)/cvt->hperiod + 1 +
-			 FB_CVT_MIN_VPORCH;
-		min_vbi_lines = cvt->vsync + FB_CVT_MIN_BPORCH +
-			FB_CVT_MIN_VPORCH;
-	}
-
-	if (vbi_lines < min_vbi_lines)
-		act_vbi_lines = min_vbi_lines;
-	else
-		act_vbi_lines = vbi_lines;
-
-	return act_vbi_lines;
-}
-
-static u32 fb_cvt_vtotal(struct fb_cvt_data *cvt)
-{
-	u32 vtotal = cvt->yres/cvt->interlace;
-
-	vtotal += 2 * cvt->v_margin + cvt->interlace/2 + fb_cvt_vbi_lines(cvt);
-	vtotal |= cvt->interlace/2;
-
-	return vtotal;
-}
-
-static u32 fb_cvt_pixclock(struct fb_cvt_data *cvt)
-{
-	u32 pixclock;
-
-	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
-		pixclock = (cvt->f_refresh * cvt->vtotal * cvt->htotal)/1000;
-	else
-		pixclock = (cvt->htotal * 1000000)/cvt->hperiod;
-
-	pixclock /= 250;
-	pixclock *= 250;
-	pixclock *= 1000;
-
-	return pixclock;
-}
-
-static u32 fb_cvt_aspect_ratio(struct fb_cvt_data *cvt)
-{
-	u32 xres = cvt->xres;
-	u32 yres = cvt->yres;
-	u32 aspect = -1;
-
-	if (xres == (yres * 4)/3 && !((yres * 4) % 3))
-		aspect = 0;
-	else if (xres == (yres * 16)/9 && !((yres * 16) % 9))
-		aspect = 1;
-	else if (xres == (yres * 16)/10 && !((yres * 16) % 10))
-		aspect = 2;
-	else if (xres == (yres * 5)/4 && !((yres * 5) % 4))
-		aspect = 3;
-	else if (xres == (yres * 15)/9 && !((yres * 15) % 9))
-		aspect = 4;
-	else {
-		printk(KERN_INFO "fbcvt: Aspect ratio not CVT "
-		       "standard\n");
-		aspect = 7;
-		cvt->status = 1;
-	}
-
-	return aspect;
-}
-
-static void fb_cvt_print_name(struct fb_cvt_data *cvt)
-{
-	u32 pixcount, pixcount_mod;
-	int cnt = 255, offset = 0, read = 0;
-	u8 *buf = kzalloc(256, GFP_KERNEL);
-
-	if (!buf)
-		return;
-
-	pixcount = (cvt->xres * (cvt->yres/cvt->interlace))/1000000;
-	pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000;
-	pixcount_mod /= 1000;
-
-	read = snprintf(buf+offset, cnt, "fbcvt: %dx%d@%d: CVT Name - ",
-			cvt->xres, cvt->yres, cvt->refresh);
-	offset += read;
-	cnt -= read;
-
-	if (cvt->status)
-		snprintf(buf+offset, cnt, "Not a CVT standard - %d.%03d Mega "
-			 "Pixel Image\n", pixcount, pixcount_mod);
-	else {
-		if (pixcount) {
-			read = snprintf(buf+offset, cnt, "%d", pixcount);
-			cnt -= read;
-			offset += read;
-		}
-
-		read = snprintf(buf+offset, cnt, ".%03dM", pixcount_mod);
-		cnt -= read;
-		offset += read;
-
-		if (cvt->aspect_ratio == 0)
-			read = snprintf(buf+offset, cnt, "3");
-		else if (cvt->aspect_ratio == 3)
-			read = snprintf(buf+offset, cnt, "4");
-		else if (cvt->aspect_ratio == 1 || cvt->aspect_ratio == 4)
-			read = snprintf(buf+offset, cnt, "9");
-		else if (cvt->aspect_ratio == 2)
-			read = snprintf(buf+offset, cnt, "A");
-		else
-			read = 0;
-		cnt -= read;
-		offset += read;
-
-		if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
-			read = snprintf(buf+offset, cnt, "-R");
-			cnt -= read;
-			offset += read;
-		}
-	}
-
-	printk(KERN_INFO "%s\n", buf);
-	kfree(buf);
-}
-
-static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt,
-				   struct fb_videomode *mode)
-{
-	mode->refresh = cvt->f_refresh;
-	mode->pixclock = KHZ2PICOS(cvt->pixclock/1000);
-	mode->left_margin = cvt->h_back_porch;
-	mode->right_margin = cvt->h_front_porch;
-	mode->hsync_len = cvt->hsync;
-	mode->upper_margin = cvt->v_back_porch;
-	mode->lower_margin = cvt->v_front_porch;
-	mode->vsync_len = cvt->vsync;
-
-	mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
-
-	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
-		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
-	else
-		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
-}
-
-/*
- * fb_find_mode_cvt - calculate mode using VESA(TM) CVT
- * @mode: pointer to fb_videomode; xres, yres, refresh and vmode must be
- *        pre-filled with the desired values
- * @margins: add margin to calculation (1.8% of xres and yres)
- * @rb: compute with reduced blanking (for flatpanels)
- *
- * RETURNS:
- * 0 for success
- * @mode is filled with computed values.  If interlaced, the refresh field
- * will be filled with the field rate (2x the frame rate)
- *
- * DESCRIPTION:
- * Computes video timings using VESA(TM) Coordinated Video Timings
- */
-int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb)
-{
-	struct fb_cvt_data cvt;
-
-	memset(&cvt, 0, sizeof(cvt));
-
-	if (margins)
-	    cvt.flags |= FB_CVT_FLAG_MARGINS;
-
-	if (rb)
-	    cvt.flags |= FB_CVT_FLAG_REDUCED_BLANK;
-
-	if (mode->vmode & FB_VMODE_INTERLACED)
-	    cvt.flags |= FB_CVT_FLAG_INTERLACED;
-
-	cvt.xres = mode->xres;
-	cvt.yres = mode->yres;
-	cvt.refresh = mode->refresh;
-	cvt.f_refresh = cvt.refresh;
-	cvt.interlace = 1;
-
-	if (!cvt.xres || !cvt.yres || !cvt.refresh) {
-		printk(KERN_INFO "fbcvt: Invalid input parameters\n");
-		return 1;
-	}
-
-	if (!(cvt.refresh == 50 || cvt.refresh == 60 || cvt.refresh == 70 ||
-	      cvt.refresh == 85)) {
-		printk(KERN_INFO "fbcvt: Refresh rate not CVT "
-		       "standard\n");
-		cvt.status = 1;
-	}
-
-	cvt.xres &= ~(FB_CVT_CELLSIZE - 1);
-
-	if (cvt.flags & FB_CVT_FLAG_INTERLACED) {
-		cvt.interlace = 2;
-		cvt.f_refresh *= 2;
-	}
-
-	if (cvt.flags & FB_CVT_FLAG_REDUCED_BLANK) {
-		if (cvt.refresh != 60) {
-			printk(KERN_INFO "fbcvt: 60Hz refresh rate "
-			       "advised for reduced blanking\n");
-			cvt.status = 1;
-		}
-	}
-
-	if (cvt.flags & FB_CVT_FLAG_MARGINS) {
-		cvt.h_margin = (cvt.xres * 18)/1000;
-		cvt.h_margin &= ~(FB_CVT_CELLSIZE - 1);
-		cvt.v_margin = ((cvt.yres/cvt.interlace)* 18)/1000;
-	}
-
-	cvt.aspect_ratio = fb_cvt_aspect_ratio(&cvt);
-	cvt.active_pixels = cvt.xres + 2 * cvt.h_margin;
-	cvt.hperiod = fb_cvt_hperiod(&cvt);
-	cvt.vsync = fb_cvt_vbi_tab[cvt.aspect_ratio];
-	cvt.vtotal = fb_cvt_vtotal(&cvt);
-	cvt.hblank = fb_cvt_hblank(&cvt);
-	cvt.htotal = cvt.active_pixels + cvt.hblank;
-	cvt.hsync = fb_cvt_hsync(&cvt);
-	cvt.pixclock = fb_cvt_pixclock(&cvt);
-	cvt.hfreq = cvt.pixclock/cvt.htotal;
-	cvt.h_back_porch = cvt.hblank/2 + cvt.h_margin;
-	cvt.h_front_porch = cvt.hblank - cvt.hsync - cvt.h_back_porch +
-		2 * cvt.h_margin;
-	cvt.v_back_porch = 3 + cvt.v_margin;
-	cvt.v_front_porch = cvt.vtotal - cvt.yres/cvt.interlace -
-	    cvt.v_back_porch - cvt.vsync;
-	fb_cvt_print_name(&cvt);
-	fb_cvt_convert_to_mode(&cvt, mode);
-
-	return 0;
-}
diff --git a/drivers/video/fbdev/68328fb.c b/drivers/video/fbdev/68328fb.c
new file mode 100644
index 000000000000..552258c8f99d
--- /dev/null
+++ b/drivers/video/fbdev/68328fb.c
@@ -0,0 +1,503 @@
+/*
+ *  linux/drivers/video/68328fb.c -- Low level implementation of the
+ *                                   mc68x328 LCD frame buffer device
+ *
+ *	Copyright (C) 2003 Georges Menie
+ *
+ *  This driver assumes an already configured controller (e.g. from config.c)
+ *  Keep the code clean of board specific initialization.
+ *
+ *  This code has not been tested with colors, colormap management functions
+ *  are minimal (no colormap data written to the 68328 registers...)
+ *
+ *  initial version of this driver:
+ *    Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>,
+ *                            The Silver Hammer Group, Ltd.
+ *
+ *  this version is based on :
+ *
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *      Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#if defined(CONFIG_M68VZ328)
+#include <asm/MC68VZ328.h>
+#elif defined(CONFIG_M68EZ328)
+#include <asm/MC68EZ328.h>
+#elif defined(CONFIG_M68328)
+#include <asm/MC68328.h>
+#else
+#error wrong architecture for the MC68x328 frame buffer device
+#endif
+
+#if defined(CONFIG_FB_68328_INVERT)
+#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO01
+#else
+#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO10
+#endif
+
+static u_long videomemory;
+static u_long videomemorysize;
+
+static struct fb_info fb_info;
+static u32 mc68x328fb_pseudo_palette[16];
+
+static struct fb_var_screeninfo mc68x328fb_default __initdata = {
+	.red =		{ 0, 8, 0 },
+      	.green =	{ 0, 8, 0 },
+      	.blue =		{ 0, 8, 0 },
+      	.activate =	FB_ACTIVATE_TEST,
+      	.height =	-1,
+      	.width =	-1,
+      	.pixclock =	20000,
+      	.left_margin =	64,
+      	.right_margin =	64,
+      	.upper_margin =	32,
+      	.lower_margin =	32,
+      	.hsync_len =	64,
+      	.vsync_len =	2,
+      	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo mc68x328fb_fix __initdata = {
+	.id =		"68328fb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+    /*
+     *  Interface used by the world
+     */
+int mc68x328fb_init(void);
+int mc68x328fb_setup(char *);
+
+static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info);
+static int mc68x328fb_set_par(struct fb_info *info);
+static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info);
+static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info);
+static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
+
+static struct fb_ops mc68x328fb_ops = {
+	.fb_check_var	= mc68x328fb_check_var,
+	.fb_set_par	= mc68x328fb_set_par,
+	.fb_setcolreg	= mc68x328fb_setcolreg,
+	.fb_pan_display	= mc68x328fb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_mmap	= mc68x328fb_mmap,
+};
+
+    /*
+     *  Internal routines
+     */
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+	u_long length;
+
+	length = xres_virtual * bpp;
+	length = (length + 31) & ~31;
+	length >>= 3;
+	return (length);
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var. 
+     */
+
+static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	u_long line_length;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/*
+	 *  Some very basic checks
+	 */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->bits_per_pixel <= 1)
+		var->bits_per_pixel = 1;
+	else if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xoffset + var->xres)
+		var->xres_virtual = var->xoffset + var->xres;
+	if (var->yres_virtual < var->yoffset + var->yres)
+		var->yres_virtual = var->yoffset + var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length =
+	    get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > videomemorysize)
+		return -ENOMEM;
+
+	/*
+	 * Now that we checked it we alter var. The reason being is that the video
+	 * mode passed in might not work but slight changes to it might make it 
+	 * work. This way we let the user know what is acceptable.
+	 */
+	switch (var->bits_per_pixel) {
+	case 1:
+		var->red.offset = 0;
+		var->red.length = 1;
+		var->green.offset = 0;
+		var->green.length = 1;
+		var->blue.offset = 0;
+		var->blue.length = 1;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGBA 5551 */
+		if (var->transp.length) {
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 10;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {	/* RGB 565 */
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 11;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:		/* RGB 888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/* This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the 
+ * change in par. For this driver it doesn't do much. 
+ */
+static int mc68x328fb_set_par(struct fb_info *info)
+{
+	info->fix.line_length = get_line_length(info->var.xres_virtual,
+						info->var.bits_per_pixel);
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info)
+{
+	if (regno >= 256)	/* no. of hw registers */
+		return 1;
+	/*
+	 * Program hardware... do anything you want with transp
+	 */
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of RAMDAC
+	 *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 * 
+	 * Pseudocolor:
+	 *    uses offset = 0 && length = RAMDAC register width.
+	 *    var->{color}.offset is 0
+	 *    var->{color}.length contains width of DAC
+	 *    cmap is not used
+	 *    RAMDAC[X] is programmed to (red, green, blue)
+	 * Truecolor:
+	 *    does not use DAC. Usually 3 are present.
+	 *    var->{color}.offset contains start of bitfield
+	 *    var->{color}.length contains length of bitfield
+	 *    cmap is programmed to (red << red.offset) | (green << green.offset) |
+	 *                      (blue << blue.offset) | (transp << transp.offset)
+	 *    RAMDAC does not exist
+	 */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return 1;
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		case 24:
+		case 32:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+     */
+
+static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0
+		    || var->yoffset >= info->var.yres_virtual
+		    || var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+		    var->yoffset + info->var.yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+    /*
+     *  Most drivers don't need their own mmap function 
+     */
+
+static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+#ifndef MMU
+	/* this is uClinux (no MMU) specific code */
+
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+	vma->vm_start = videomemory;
+
+	return 0;
+#else
+	return -EINVAL;
+#endif
+}
+
+int __init mc68x328fb_setup(char *options)
+{
+#if 0
+	char *this_opt;
+#endif
+
+	if (!options || !*options)
+		return 1;
+#if 0
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "disable", 7))
+			mc68x328fb_enable = 0;
+	}
+#endif
+	return 1;
+}
+
+    /*
+     *  Initialisation
+     */
+
+int __init mc68x328fb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("68328fb", &option))
+		return -ENODEV;
+	mc68x328fb_setup(option);
+#endif
+	/*
+	 *  initialize the default mode from the LCD controller registers
+	 */
+	mc68x328fb_default.xres = LXMAX;
+	mc68x328fb_default.yres = LYMAX+1;
+	mc68x328fb_default.xres_virtual = mc68x328fb_default.xres;
+	mc68x328fb_default.yres_virtual = mc68x328fb_default.yres;
+	mc68x328fb_default.bits_per_pixel = 1 + (LPICF & 0x01);
+	videomemory = LSSA;
+	videomemorysize = (mc68x328fb_default.xres_virtual+7) / 8 *
+		mc68x328fb_default.yres_virtual * mc68x328fb_default.bits_per_pixel;
+
+	fb_info.screen_base = (void *)videomemory;
+	fb_info.fbops = &mc68x328fb_ops;
+	fb_info.var = mc68x328fb_default;
+	fb_info.fix = mc68x328fb_fix;
+	fb_info.fix.smem_start = videomemory;
+	fb_info.fix.smem_len = videomemorysize;
+	fb_info.fix.line_length =
+		get_line_length(mc68x328fb_default.xres_virtual, mc68x328fb_default.bits_per_pixel);
+	fb_info.fix.visual = (mc68x328fb_default.bits_per_pixel) == 1 ?
+		MC68X328FB_MONO_VISUAL : FB_VISUAL_PSEUDOCOLOR;
+	if (fb_info.var.bits_per_pixel == 1) {
+		fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1;
+		fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0;
+	}
+	fb_info.pseudo_palette = &mc68x328fb_pseudo_palette;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	if (fb_alloc_cmap(&fb_info.cmap, 256, 0))
+		return -ENOMEM;
+
+	if (register_framebuffer(&fb_info) < 0) {
+		fb_dealloc_cmap(&fb_info.cmap);
+		return -EINVAL;
+	}
+
+	fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
+	fb_info(&fb_info, "%dx%dx%d at 0x%08lx\n",
+		mc68x328fb_default.xres_virtual,
+		mc68x328fb_default.yres_virtual,
+		1 << mc68x328fb_default.bits_per_pixel, videomemory);
+
+	return 0;
+}
+
+module_init(mc68x328fb_init);
+
+#ifdef MODULE
+
+static void __exit mc68x328fb_cleanup(void)
+{
+	unregister_framebuffer(&fb_info);
+	fb_dealloc_cmap(&fb_info.cmap);
+}
+
+module_exit(mc68x328fb_cleanup);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
new file mode 100644
index 000000000000..e1f47272fdea
--- /dev/null
+++ b/drivers/video/fbdev/Kconfig
@@ -0,0 +1,2474 @@
+#
+# fbdev configuration
+#
+
+menuconfig FB
+	tristate "Support for frame buffer devices"
+	---help---
+	  The frame buffer device provides an abstraction for the graphics
+	  hardware. It represents the frame buffer of some video hardware and
+	  allows application software to access the graphics hardware through
+	  a well-defined interface, so the software doesn't need to know
+	  anything about the low-level (hardware register) stuff.
+
+	  Frame buffer devices work identically across the different
+	  architectures supported by Linux and make the implementation of
+	  application programs easier and more portable; at this point, an X
+	  server exists which uses the frame buffer device exclusively.
+	  On several non-X86 architectures, the frame buffer device is the
+	  only way to use the graphics hardware.
+
+	  The device is accessed through special device nodes, usually located
+	  in the /dev directory, i.e. /dev/fb*.
+
+	  You need an utility program called fbset to make full use of frame
+	  buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
+	  and the Framebuffer-HOWTO at
+	  <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.3.html> for more
+	  information.
+
+	  Say Y here and to the driver for your graphics board below if you
+	  are compiling a kernel for a non-x86 architecture.
+
+	  If you are compiling for the x86 architecture, you can say Y if you
+	  want to play with it, but it is not essential. Please note that
+	  running graphical applications that directly touch the hardware
+	  (e.g. an accelerated X server) and that are not frame buffer
+	  device-aware may cause unexpected results. If unsure, say N.
+
+config FIRMWARE_EDID
+       bool "Enable firmware EDID"
+       depends on FB
+       default n
+       ---help---
+         This enables access to the EDID transferred from the firmware.
+	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+	 transfers do not work for your driver and if you are using
+	 nvidiafb, i810fb or savagefb.
+
+	 In general, choosing Y for this option is safe.  If you
+	 experience extremely long delays while booting before you get
+	 something on your display, try setting this to N.  Matrox cards in
+	 combination with certain motherboards and monitors are known to
+	 suffer from this problem.
+
+config FB_DDC
+       tristate
+       depends on FB
+       select I2C_ALGOBIT
+       select I2C
+       default n
+
+config FB_BOOT_VESA_SUPPORT
+	bool
+	depends on FB
+	default n
+	---help---
+	  If true, at least one selected framebuffer driver can take advantage
+	  of VESA video modes set at an early boot stage via the vga= parameter.
+
+config FB_CFB_FILLRECT
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the cfb_fillrect function for generic software rectangle
+	  filling. This is used by drivers that don't provide their own
+	  (accelerated) version.
+
+config FB_CFB_COPYAREA
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the cfb_copyarea function for generic software area copying.
+	  This is used by drivers that don't provide their own (accelerated)
+	  version.
+
+config FB_CFB_IMAGEBLIT
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the cfb_imageblit function for generic software image
+	  blitting. This is used by drivers that don't provide their own
+	  (accelerated) version.
+
+config FB_CFB_REV_PIXELS_IN_BYTE
+	bool
+	depends on FB
+	default n
+	---help---
+	  Allow generic frame-buffer functions to work on displays with 1, 2
+	  and 4 bits per pixel depths which has opposite order of pixels in
+	  byte order to bytes in long order.
+
+config FB_SYS_FILLRECT
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the sys_fillrect function for generic software rectangle
+	  filling. This is used by drivers that don't provide their own
+	  (accelerated) version and the framebuffer is in system RAM.
+
+config FB_SYS_COPYAREA
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the sys_copyarea function for generic software area copying.
+	  This is used by drivers that don't provide their own (accelerated)
+	  version and the framebuffer is in system RAM.
+
+config FB_SYS_IMAGEBLIT
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the sys_imageblit function for generic software image
+	  blitting. This is used by drivers that don't provide their own
+	  (accelerated) version and the framebuffer is in system RAM.
+
+menuconfig FB_FOREIGN_ENDIAN
+	bool "Framebuffer foreign endianness support"
+	depends on FB
+	---help---
+	  This menu will let you enable support for the framebuffers with
+	  non-native endianness (e.g. Little-Endian framebuffer on a
+	  Big-Endian machine). Most probably you don't have such hardware,
+	  so it's safe to say "n" here.
+
+choice
+	prompt "Choice endianness support"
+	depends on FB_FOREIGN_ENDIAN
+
+config FB_BOTH_ENDIAN
+	bool "Support for Big- and Little-Endian framebuffers"
+
+config FB_BIG_ENDIAN
+	bool "Support for Big-Endian framebuffers only"
+
+config FB_LITTLE_ENDIAN
+	bool "Support for Little-Endian framebuffers only"
+
+endchoice
+
+config FB_SYS_FOPS
+       tristate
+       depends on FB
+       default n
+
+config FB_DEFERRED_IO
+	bool
+	depends on FB
+
+config FB_HECUBA
+	tristate
+	depends on FB
+	depends on FB_DEFERRED_IO
+
+config FB_SVGALIB
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Common utility functions useful to fbdev drivers of VGA-based
+	  cards.
+
+config FB_MACMODES
+       tristate
+       depends on FB
+       default n
+
+config FB_BACKLIGHT
+	bool
+	depends on FB
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	default n
+
+config FB_MODE_HELPERS
+        bool "Enable Video Mode Handling Helpers"
+        depends on FB
+	default n
+	---help---
+	  This enables functions for handling video modes using the
+	  Generalized Timing Formula and the EDID parser. A few drivers rely
+          on this feature such as the radeonfb, rivafb, and the i810fb. If
+	  your driver does not take advantage of this feature, choosing Y will
+	  just increase the kernel size by about 5K.
+
+config FB_TILEBLITTING
+       bool "Enable Tile Blitting Support"
+       depends on FB
+       default n
+       ---help---
+         This enables tile blitting.  Tile blitting is a drawing technique
+	 where the screen is divided into rectangular sections (tiles), whereas
+	 the standard blitting divides the screen into pixels. Because the
+	 default drawing element is a tile, drawing functions will be passed
+	 parameters in terms of number of tiles instead of number of pixels.
+	 For example, to draw a single character, instead of using bitmaps,
+	 an index to an array of bitmaps will be used.  To clear or move a
+	 rectangular section of a screen, the rectangle will be described in
+	 terms of number of tiles in the x- and y-axis.
+
+	 This is particularly important to one driver, matroxfb.  If
+	 unsure, say N.
+
+comment "Frame buffer hardware drivers"
+	depends on FB
+
+config FB_GRVGA
+	tristate "Aeroflex Gaisler framebuffer support"
+	depends on FB && SPARC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
+
+config FB_CIRRUS
+	tristate "Cirrus Logic support"
+	depends on FB && (ZORRO || PCI)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  This enables support for Cirrus Logic GD542x/543x based boards on
+	  Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
+
+	  If you have a PCI-based system, this enables support for these
+	  chips: GD-543x, GD-544x, GD-5480.
+
+	  Please read the file <file:Documentation/fb/cirrusfb.txt>.
+
+	  Say N unless you have such a graphics board or plan to get one
+	  before you next recompile the kernel.
+
+config FB_PM2
+	tristate "Permedia2 support"
+	depends on FB && ((AMIGA && BROKEN) || PCI)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for cards based on
+	  the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
+	  The driver was tested on the following cards:
+		Diamond FireGL 1000 PRO AGP
+		ELSA Gloria Synergy PCI
+		Appian Jeronimo PRO (both heads) PCI
+		3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
+		Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
+		ASK Graphic Blaster Exxtreme AGP
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pm2fb.
+
+config FB_PM2_FIFO_DISCONNECT
+	bool "enable FIFO disconnect feature"
+	depends on FB_PM2 && PCI
+	help
+	  Support the Permedia2 FIFO disconnect feature.
+
+config FB_ARMCLCD
+	tristate "ARM PrimeCell PL110 support"
+	depends on ARM || ARM64 || COMPILE_TEST
+	depends on FB && ARM_AMBA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This framebuffer device driver is for the ARM PrimeCell PL110
+	  Colour LCD controller.  ARM PrimeCells provide the building
+	  blocks for System on a Chip devices.
+
+	  If you want to compile this as a module (=code which can be
+	  inserted into and removed from the running kernel), say M
+	  here and read <file:Documentation/kbuild/modules.txt>.  The module
+	  will be called amba-clcd.
+
+config FB_ACORN
+	bool "Acorn VIDC support"
+	depends on (FB = y) && ARM && ARCH_ACORN
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Acorn VIDC graphics
+	  hardware found in Acorn RISC PCs and other ARM-based machines.  If
+	  unsure, say N.
+
+config FB_CLPS711X
+	bool "CLPS711X LCD support"
+	depends on (FB = y) && ARM && ARCH_CLPS711X
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Say Y to enable the Framebuffer driver for the CLPS7111 and
+	  EP7212 processors.
+
+config FB_SA1100
+	bool "SA-1100 LCD support"
+	depends on (FB = y) && ARM && ARCH_SA1100
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is a framebuffer device for the SA-1100 LCD Controller.
+	  See <http://www.linux-fbdev.org/> for information on framebuffer
+	  devices.
+
+	  If you plan to use the LCD display with your SA-1100 system, say
+	  Y here.
+
+config FB_IMX
+	tristate "Freescale i.MX1/21/25/27 LCD support"
+	depends on FB && ARCH_MXC
+	select BACKLIGHT_LCD_SUPPORT
+	select LCD_CLASS_DEVICE
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
+
+config FB_CYBER2000
+	tristate "CyberPro 2000/2010/5000 support"
+	depends on FB && PCI && (BROKEN || !SPARC64)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This enables support for the Integraphics CyberPro 20x0 and 5000
+	  VGA chips used in the Rebel.com Netwinder and other machines.
+	  Say Y if you have a NetWinder or a graphics card containing this
+	  device, otherwise say N.
+
+config FB_CYBER2000_DDC
+	bool "DDC for CyberPro support"
+	depends on FB_CYBER2000
+	select FB_DDC
+	default y
+	help
+	  Say Y here if you want DDC support for your CyberPro graphics
+	  card. This is only I2C bus support, driver does not use EDID.
+
+config FB_CYBER2000_I2C
+	bool "CyberPro 2000/2010/5000 I2C support"
+	depends on FB_CYBER2000 && I2C && ARCH_NETWINDER
+	select I2C_ALGOBIT
+	help
+	  Enable support for the I2C video decoder interface on the
+	  Integraphics CyberPro 20x0 and 5000 VGA chips.  This is used
+	  on the Netwinder machines for the SAA7111 video capture.
+
+config FB_APOLLO
+	bool
+	depends on (FB = y) && APOLLO
+	default y
+	select FB_CFB_FILLRECT
+	select FB_CFB_IMAGEBLIT
+
+config FB_Q40
+	bool
+	depends on (FB = y) && Q40
+	default y
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+
+config FB_AMIGA
+	tristate "Amiga native chipset support"
+	depends on FB && AMIGA
+	help
+	  This is the frame buffer device driver for the builtin graphics
+	  chipset found in Amigas.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called amifb.
+
+config FB_AMIGA_OCS
+	bool "Amiga OCS chipset support"
+	depends on FB_AMIGA
+	help
+	  This enables support for the original Agnus and Denise video chips,
+	  found in the Amiga 1000 and most A500's and A2000's. If you intend
+	  to run Linux on any of these systems, say Y; otherwise say N.
+
+config FB_AMIGA_ECS
+	bool "Amiga ECS chipset support"
+	depends on FB_AMIGA
+	help
+	  This enables support for the Enhanced Chip Set, found in later
+	  A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If
+	  you intend to run Linux on any of these systems, say Y; otherwise
+	  say N.
+
+config FB_AMIGA_AGA
+	bool "Amiga AGA chipset support"
+	depends on FB_AMIGA
+	help
+	  This enables support for the Advanced Graphics Architecture (also
+	  known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T
+	  and CD32. If you intend to run Linux on any of these systems, say Y;
+	  otherwise say N.
+
+config FB_FM2
+	bool "Amiga FrameMaster II/Rainbow II support"
+	depends on (FB = y) && ZORRO
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Amiga FrameMaster
+	  card from BSC (exhibited 1992 but not shipped as a CBM product).
+
+config FB_ARC
+	tristate "Arc Monochrome LCD board support"
+	depends on FB && X86
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  This enables support for the Arc Monochrome LCD board. The board
+	  is based on the KS-108 lcd controller and is typically a matrix
+	  of 2*n chips. This driver was tested with a 128x64 panel. This
+	  driver supports it for use with x86 SBCs through a 16 bit GPIO
+	  interface (8 bit data, 8 bit control). If you anticipate using
+	  this driver, say Y or M; otherwise say N. You must specify the
+	  GPIO IO address to be used for setting control and data.
+
+config FB_ATARI
+	bool "Atari native chipset support"
+	depends on (FB = y) && ATARI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the builtin graphics
+	  chipset found in Ataris.
+
+config FB_OF
+	bool "Open Firmware frame buffer device support"
+	depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MACMODES
+	help
+	  Say Y if you want support with Open Firmware for your graphics
+	  board.
+
+config FB_CONTROL
+	bool "Apple \"control\" display support"
+	depends on (FB = y) && PPC_PMAC && PPC32
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MACMODES
+	help
+	  This driver supports a frame buffer for the graphics adapter in the
+	  Power Macintosh 7300 and others.
+
+config FB_PLATINUM
+	bool "Apple \"platinum\" display support"
+	depends on (FB = y) && PPC_PMAC && PPC32
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MACMODES
+	help
+	  This driver supports a frame buffer for the "platinum" graphics
+	  adapter in some Power Macintoshes.
+
+config FB_VALKYRIE
+	bool "Apple \"valkyrie\" display support"
+	depends on (FB = y) && (MAC || (PPC_PMAC && PPC32))
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MACMODES
+	help
+	  This driver supports a frame buffer for the "valkyrie" graphics
+	  adapter in some Power Macintoshes.
+
+config FB_CT65550
+	bool "Chips 65550 display support"
+	depends on (FB = y) && PPC32 && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Chips & Technologies
+	  65550 graphics chip in PowerBooks.
+
+config FB_ASILIANT
+	bool "Asiliant (Chips) 69000 display support"
+	depends on (FB = y) && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Asiliant 69030 chipset
+
+config FB_IMSTT
+	bool "IMS Twin Turbo display support"
+	depends on (FB = y) && PCI
+	select FB_CFB_IMAGEBLIT
+	select FB_MACMODES if PPC
+	help
+	  The IMS Twin Turbo is a PCI-based frame buffer card bundled with
+	  many Macintosh and compatible computers.
+
+config FB_VGA16
+	tristate "VGA 16-color graphics support"
+	depends on FB && (X86 || PPC)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VGASTATE
+	select FONT_8x16 if FRAMEBUFFER_CONSOLE
+	help
+	  This is the frame buffer device driver for VGA 16 color graphic
+	  cards. Say Y if you have such a card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vga16fb.
+
+config FB_BF54X_LQ043
+	tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)"
+	depends on FB && (BF54x) && !BF542
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	 This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
+
+config FB_BFIN_T350MCQB
+	tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)"
+	depends on FB && BLACKFIN
+	select BFIN_GPTIMERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	 This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD
+	 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
+	 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
+
+config FB_BFIN_LQ035Q1
+	tristate "SHARP LQ035Q1DH02 TFT LCD"
+	depends on FB && BLACKFIN && SPI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select BFIN_GPTIMERS
+	help
+	  This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on
+	  the Blackfin Landscape LCD EZ-Extender Card.
+	  This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI
+	  It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bfin-lq035q1-fb.
+
+config FB_BF537_LQ035
+	tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
+	depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select BFIN_GPTIMERS
+	help
+	  This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
+	  attached to a BF537.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bf537-lq035.
+
+config FB_BFIN_7393
+	tristate "Blackfin ADV7393 Video encoder"
+	depends on FB && BLACKFIN
+	select I2C
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for a ADV7393 video encoder
+	  attached to a Blackfin on the PPI port.
+	  If your Blackfin board has a ADV7393 select Y.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bfin_adv7393fb.
+
+choice
+	prompt  "Video mode support"
+	depends on FB_BFIN_7393
+	default NTSC
+
+config NTSC
+	bool 'NTSC 720x480'
+
+config PAL
+	bool 'PAL 720x576'
+
+config NTSC_640x480
+	bool 'NTSC 640x480 (Experimental)'
+
+config PAL_640x480
+	bool 'PAL 640x480 (Experimental)'
+
+config NTSC_YCBCR
+	bool 'NTSC 720x480 YCbCR input'
+
+config PAL_YCBCR
+	bool 'PAL 720x576 YCbCR input'
+
+endchoice
+
+choice
+	prompt  "Size of ADV7393 frame buffer memory Single/Double Size"
+	depends on (FB_BFIN_7393)
+	default ADV7393_1XMEM
+
+config ADV7393_1XMEM
+	bool 'Single'
+
+config ADV7393_2XMEM
+	bool 'Double'
+endchoice
+
+config FB_STI
+	tristate "HP STI frame buffer device support"
+	depends on FB && PARISC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select STI_CONSOLE
+	select VT
+	default y
+	---help---
+	  STI refers to the HP "Standard Text Interface" which is a set of
+	  BIOS routines contained in a ROM chip in HP PA-RISC based machines.
+	  Enabling this option will implement the linux framebuffer device
+	  using calls to the STI BIOS routines for initialisation.
+	
+	  If you enable this option, you will get a planar framebuffer device
+	  /dev/fb which will work on the most common HP graphic cards of the
+	  NGLE family, including the artist chips (in the 7xx and Bxxx series),
+	  HCRX, HCRX24, CRX, CRX24 and VisEG series.
+
+	  It is safe to enable this option, so you should probably say "Y".
+
+config FB_MAC
+	bool "Generic Macintosh display support"
+	depends on (FB = y) && MAC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MACMODES
+
+config FB_HP300
+	bool
+	depends on (FB = y) && DIO
+	select FB_CFB_IMAGEBLIT
+	default y
+
+config FB_TGA
+	tristate "TGA/SFB+ framebuffer support"
+	depends on FB && (ALPHA || TC)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select BITREVERSE
+	---help---
+	  This is the frame buffer device driver for generic TGA and SFB+
+	  graphic cards.  These include DEC ZLXp-E1, -E2 and -E3 PCI cards,
+	  also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3
+	  TURBOchannel cards, also known as PMAGD-A, -B and -C.
+
+	  Due to hardware limitations ZLX-E2 and E3 cards are not supported
+	  for DECstation 5000/200 systems.  Additionally due to firmware
+	  limitations these cards may cause troubles with booting DECstation
+	  5000/240 and /260 systems, but are fully supported under Linux if
+	  you manage to get it going. ;-)
+
+	  Say Y if you have one of those.
+
+config FB_UVESA
+	tristate "Userspace VESA VGA graphics support"
+	depends on FB && CONNECTOR
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS
+	help
+	  This is the frame buffer driver for generic VBE 2.0 compliant
+	  graphic cards. It can also take advantage of VBE 3.0 features,
+	  such as refresh rate adjustment.
+
+	  This driver generally provides more features than vesafb but
+	  requires a userspace helper application called 'v86d'. See
+	  <file:Documentation/fb/uvesafb.txt> for more information.
+
+	  If unsure, say N.
+
+config FB_VESA
+	bool "VESA VGA graphics support"
+	depends on (FB = y) && X86
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_BOOT_VESA_SUPPORT
+	help
+	  This is the frame buffer device driver for generic VESA 2.0
+	  compliant graphic cards. The older VESA 1.2 cards are not supported.
+	  You will get a boot time penguin logo at no additional cost. Please
+	  read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
+
+config FB_EFI
+	bool "EFI-based Framebuffer Support"
+	depends on (FB = y) && X86 && EFI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the EFI frame buffer device driver. If the firmware on
+	  your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
+	  using the EFI framebuffer as your console.
+
+config FB_N411
+       tristate "N411 Apollo/Hecuba devkit support"
+       depends on FB && X86 && MMU
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
+       select FB_DEFERRED_IO
+       select FB_HECUBA
+       help
+         This enables support for the Apollo display controller in its
+         Hecuba form using the n411 devkit.
+
+config FB_HGA
+	tristate "Hercules mono graphics support"
+	depends on FB && X86
+	help
+	  Say Y here if you have a Hercules mono graphics card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hgafb.
+
+	  As this card technology is at least 25 years old,
+	  most people will answer N here.
+
+config FB_GBE
+	bool "SGI Graphics Backend frame buffer support"
+	depends on (FB = y) && SGI_IP32
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+ 	help
+	  This is the frame buffer device driver for SGI Graphics Backend.
+	  This chip is used in SGI O2 and Visual Workstation 320/540.
+
+config FB_GBE_MEM
+	int "Video memory size in MB"
+	depends on FB_GBE
+	default 4
+	help
+	  This is the amount of memory reserved for the framebuffer,
+	  which can be any value between 1MB and 8MB.
+
+config FB_SBUS
+	bool "SBUS and UPA framebuffers"
+	depends on (FB = y) && SPARC
+	help
+	  Say Y if you want support for SBUS or UPA based frame buffer device.
+
+config FB_BW2
+	bool "BWtwo support"
+	depends on (FB = y) && (SPARC && FB_SBUS)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the BWtwo frame buffer.
+
+config FB_CG3
+	bool "CGthree support"
+	depends on (FB = y) && (SPARC && FB_SBUS)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the CGthree frame buffer.
+
+config FB_CG6
+	bool "CGsix (GX,TurboGX) support"
+	depends on (FB = y) && (SPARC && FB_SBUS)
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the CGsix (GX, TurboGX)
+	  frame buffer.
+
+config FB_FFB
+	bool "Creator/Creator3D/Elite3D support"
+	depends on FB_SBUS && SPARC64
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Creator, Creator3D,
+	  and Elite3D graphics boards.
+
+config FB_TCX
+	bool "TCX (SS4/SS5 only) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the TCX 24/8bit frame
+	  buffer.
+
+config FB_CG14
+	bool "CGfourteen (SX) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the CGfourteen frame
+	  buffer on Desktop SPARCsystems with the SX graphics option.
+
+config FB_P9100
+	bool "P9100 (Sparcbook 3 only) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the P9100 card
+	  supported on Sparcbook 3 machines.
+
+config FB_LEO
+	bool "Leo (ZX) support"
+	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the SBUS-based Sun ZX
+	  (leo) frame buffer cards.
+
+config FB_IGA
+	bool "IGA 168x display support"
+	depends on (FB = y) && SPARC32
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for the INTERGRAPHICS 1680 and
+	  successor frame buffer cards.
+
+config FB_XVR500
+	bool "Sun XVR-500 3DLABS Wildcat support"
+	depends on (FB = y) && PCI && SPARC64
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for the Sun XVR-500 and similar
+	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+	  only works on sparc64 systems where the system firmware has
+	  mostly initialized the card already.  It is treated as a
+	  completely dumb framebuffer device.
+
+config FB_XVR2500
+	bool "Sun XVR-2500 3DLABS Wildcat support"
+	depends on (FB = y) && PCI && SPARC64
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for the Sun XVR-2500 and similar
+	  graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+	  only works on sparc64 systems where the system firmware has
+	  mostly initialized the card already.  It is treated as a
+	  completely dumb framebuffer device.
+
+config FB_XVR1000
+	bool "Sun XVR-1000 support"
+	depends on (FB = y) && SPARC64
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for the Sun XVR-1000 and similar
+	  graphics cards.  The driver only works on sparc64 systems where
+	  the system firmware has mostly initialized the card already.  It
+	  is treated as a completely dumb framebuffer device.
+
+config FB_PVR2
+	tristate "NEC PowerVR 2 display support"
+	depends on FB && SH_DREAMCAST
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Say Y here if you have a PowerVR 2 card in your box.  If you plan to
+	  run linux on your Dreamcast, you will have to say Y here.
+	  This driver may or may not work on other PowerVR 2 cards, but is
+	  totally untested.  Use at your own risk.  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pvr2fb.
+
+	  You can pass several parameters to the driver at boot time or at
+	  module load time.  The parameters look like "video=pvr2:XXX", where
+	  the meaning of XXX can be found at the end of the main source file
+	  (<file:drivers/video/pvr2fb.c>). Please see the file
+	  <file:Documentation/fb/pvr2fb.txt>.
+
+config FB_OPENCORES
+	tristate "OpenCores VGA/LCD core 2.0 framebuffer support"
+	depends on FB && HAS_DMA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This enables support for the OpenCores VGA/LCD core.
+
+	  The OpenCores VGA/LCD core is typically used together with
+	  softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor
+	  systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs.
+
+	  The source code and specification for the core is available at
+	  <http://opencores.org/project,vga_lcd>
+
+config FB_S1D13XXX
+	tristate "Epson S1D13XXX framebuffer support"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Support for S1D13XXX framebuffer device family (currently only
+	  working with S1D13806). Product specs at
+	  <http://vdc.epson.com/>
+
+config FB_ATMEL
+	tristate "AT91/AT32 LCD Controller support"
+	depends on FB && HAVE_FB_ATMEL
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
+	help
+	  This enables support for the AT91/AT32 LCD Controller.
+
+config FB_INTSRAM
+	bool "Frame Buffer in internal SRAM"
+	depends on FB_ATMEL && ARCH_AT91SAM9261
+	help
+	  Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
+	  to let frame buffer in external SDRAM.
+
+config FB_ATMEL_STN
+	bool "Use a STN display with AT91/AT32 LCD Controller"
+	depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK)
+	default n
+	help
+	  Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
+	  Controller. Say N if you want to connect a TFT.
+
+	  If unsure, say N.
+
+config FB_NVIDIA
+	tristate "nVidia Framebuffer Support"
+	depends on FB && PCI
+	select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select BITREVERSE
+	select VGASTATE
+	help
+	  This driver supports graphics boards with the nVidia chips, TNT
+	  and newer. For very old chipsets, such as the RIVA128, then use
+	  the rivafb.
+	  Say Y if you have such a graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called nvidiafb.
+
+config FB_NVIDIA_I2C
+       bool "Enable DDC Support"
+       depends on FB_NVIDIA
+       select FB_DDC
+       help
+	  This enables I2C support for nVidia Chipsets.  This is used
+	  only for getting EDID information from the attached display
+	  allowing for robust video mode handling and switching.
+
+	  Because fbdev-2.6 requires that drivers must be able to
+	  independently validate video mode parameters, you should say Y
+	  here.
+
+config FB_NVIDIA_DEBUG
+	bool "Lots of debug output"
+	depends on FB_NVIDIA
+	default n
+	help
+	  Say Y here if you want the nVidia driver to output all sorts
+	  of debugging information to provide to the maintainer when
+	  something goes wrong.
+
+config FB_NVIDIA_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_NVIDIA
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
+config FB_RIVA
+	tristate "nVidia Riva support"
+	depends on FB && PCI
+	select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select BITREVERSE
+	select VGASTATE
+	help
+	  This driver supports graphics boards with the nVidia Riva/Geforce
+	  chips.
+	  Say Y if you have such a graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rivafb.
+
+config FB_RIVA_I2C
+       bool "Enable DDC Support"
+       depends on FB_RIVA
+       select FB_DDC
+       help
+	  This enables I2C support for nVidia Chipsets.  This is used
+	  only for getting EDID information from the attached display
+	  allowing for robust video mode handling and switching.
+
+	  Because fbdev-2.6 requires that drivers must be able to
+	  independently validate video mode parameters, you should say Y
+	  here.
+
+config FB_RIVA_DEBUG
+	bool "Lots of debug output"
+	depends on FB_RIVA
+	default n
+	help
+	  Say Y here if you want the Riva driver to output all sorts
+	  of debugging information to provide to the maintainer when
+	  something goes wrong.
+
+config FB_RIVA_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_RIVA
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
+config FB_I740
+	tristate "Intel740 support"
+	depends on FB && PCI
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VGASTATE
+	select FB_DDC
+	help
+	  This driver supports graphics cards based on Intel740 chip.
+
+config FB_I810
+	tristate "Intel 810/815 support"
+	depends on FB && PCI && X86_32 && AGP_INTEL
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VGASTATE
+	help
+	  This driver supports the on-board graphics built in to the Intel 810 
+          and 815 chipsets.  Say Y if you have and plan to use such a board.
+
+          To compile this driver as a module, choose M here: the
+	  module will be called i810fb.
+
+          For more information, please read 
+	  <file:Documentation/fb/intel810.txt>
+
+config FB_I810_GTF
+	bool "use VESA Generalized Timing Formula"
+	depends on FB_I810
+	help
+	  If you say Y, then the VESA standard, Generalized Timing Formula 
+          or GTF, will be used to calculate the required video timing values
+	  per video mode.  Since the GTF allows nondiscrete timings 
+          (nondiscrete being a range of values as opposed to discrete being a
+          set of values), you'll be able to use any combination of horizontal 
+	  and vertical resolutions, and vertical refresh rates without having
+	  to specify your own timing parameters.  This is especially useful
+	  to maximize the performance of an aging display, or if you just 
+          have a display with nonstandard dimensions. A VESA compliant 
+	  monitor is recommended, but can still work with non-compliant ones.
+	  If you need or want this, then select this option. The timings may 
+	  not be compliant with Intel's recommended values. Use at your own 
+	  risk.
+
+          If you say N, the driver will revert to discrete video timings 
+	  using a set recommended by Intel in their documentation.
+  
+          If unsure, say N.
+
+config FB_I810_I2C
+	bool "Enable DDC Support"
+	depends on FB_I810 && FB_I810_GTF
+	select FB_DDC
+	help
+
+config FB_LE80578
+	tristate "Intel LE80578 (Vermilion) support"
+	depends on FB && PCI && X86
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This driver supports the LE80578 (Vermilion Range) chipset
+
+config FB_CARILLO_RANCH
+	tristate "Intel Carillo Ranch support"
+	depends on FB_LE80578 && FB && PCI && X86
+	help
+	  This driver supports the LE80578 (Carillo Ranch) board
+
+config FB_INTEL
+	tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support"
+	depends on FB && PCI && X86 && AGP_INTEL && EXPERT
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_BOOT_VESA_SUPPORT if FB_INTEL = y
+	depends on !DRM_I915
+	help
+	  This driver supports the on-board graphics built in to the Intel
+          830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
+          Say Y if you have and plan to use such a board.
+
+	  To make FB_INTELFB=Y work you need to say AGP_INTEL=y too.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called intelfb.
+
+	  For more information, please read <file:Documentation/fb/intelfb.txt>
+
+config FB_INTEL_DEBUG
+	bool "Intel driver Debug Messages"
+	depends on FB_INTEL
+	---help---
+	  Say Y here if you want the Intel driver to output all sorts
+	  of debugging information to provide to the maintainer when
+	  something goes wrong.
+
+config FB_INTEL_I2C
+	bool "DDC/I2C for Intel framebuffer support"
+	depends on FB_INTEL
+	select FB_DDC
+	default y
+	help
+	  Say Y here if you want DDC/I2C support for your on-board Intel graphics.
+
+config FB_MATROX
+	tristate "Matrox acceleration"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_TILEBLITTING
+	select FB_MACMODES if PPC_PMAC
+	---help---
+	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
+	  Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
+	  Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
+	  Matrox G400, G450 or G550 card in your box.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called matroxfb.
+
+	  You can pass several parameters to the driver at boot time or at
+	  module load time. The parameters look like "video=matroxfb:XXX", and
+	  are described in <file:Documentation/fb/matroxfb.txt>.
+
+config FB_MATROX_MILLENIUM
+	bool "Millennium I/II support"
+	depends on FB_MATROX
+	help
+	  Say Y here if you have a Matrox Millennium or Matrox Millennium II
+	  video card. If you select "Advanced lowlevel driver options" below,
+	  you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp
+	  packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can
+	  also use font widths different from 8.
+
+config FB_MATROX_MYSTIQUE
+	bool "Mystique support"
+	depends on FB_MATROX
+	help
+	  Say Y here if you have a Matrox Mystique or Matrox Mystique 220
+	  video card. If you select "Advanced lowlevel driver options" below,
+	  you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp
+	  packed pixel and 32 bpp packed pixel. You can also use font widths
+	  different from 8.
+
+config FB_MATROX_G
+	bool "G100/G200/G400/G450/G550 support"
+	depends on FB_MATROX
+	---help---
+	  Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based
+	  video card. If you select "Advanced lowlevel driver options", you
+	  should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
+	  pixel and 32 bpp packed pixel. You can also use font widths
+	  different from 8.
+
+	  If you need support for G400 secondary head, you must say Y to
+	  "Matrox I2C support" and "G400 second head support" right below.
+	  G450/G550 secondary head and digital output are supported without
+	  additional modules.
+
+	  The driver starts in monitor mode. You must use the matroxset tool 
+	  (available at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to 
+	  swap primary and secondary head outputs, or to change output mode.  
+	  Secondary head driver always start in 640x480 resolution and you 
+	  must use fbset to change it.
+
+	  Do not forget that second head supports only 16 and 32 bpp
+	  packed pixels, so it is a good idea to compile them into the kernel
+	  too. You can use only some font widths, as the driver uses generic
+	  painting procedures (the secondary head does not use acceleration
+	  engine).
+
+	  G450/G550 hardware can display TV picture only from secondary CRTC,
+	  and it performs no scaling, so picture must have 525 or 625 lines.
+
+config FB_MATROX_I2C
+	tristate "Matrox I2C support"
+	depends on FB_MATROX
+	select FB_DDC
+	---help---
+	  This drivers creates I2C buses which are needed for accessing the
+	  DDC (I2C) bus present on all Matroxes, an I2C bus which
+	  interconnects Matrox optional devices, like MGA-TVO on G200 and
+	  G400, and the secondary head DDC bus, present on G400 only.
+
+	  You can say Y or M here if you want to experiment with monitor
+	  detection code. You must say Y or M here if you want to use either
+	  second head of G400 or MGA-TVO on G200 or G400.
+
+	  If you compile it as module, it will create a module named
+	  i2c-matroxfb.
+
+config FB_MATROX_MAVEN
+	tristate "G400 second head support"
+	depends on FB_MATROX_G && FB_MATROX_I2C
+	---help---
+	  WARNING !!! This support does not work with G450 !!!
+
+	  Say Y or M here if you want to use a secondary head (meaning two
+	  monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary
+	  head is not compatible with accelerated XFree 3.3.x SVGA servers -
+	  secondary head output is blanked while you are in X. With XFree
+	  3.9.17 preview you can use both heads if you use SVGA over fbdev or
+	  the fbdev driver on first head and the fbdev driver on second head.
+
+	  If you compile it as module, two modules are created,
+	  matroxfb_crtc2 and matroxfb_maven. Matroxfb_maven is needed for
+	  both G200 and G400, matroxfb_crtc2 is needed only by G400. You must
+	  also load i2c-matroxfb to get it to run.
+
+	  The driver starts in monitor mode and you must use the matroxset
+	  tool (available at
+	  <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to switch it to
+	  PAL or NTSC or to swap primary and secondary head outputs.
+	  Secondary head driver also always start in 640x480 resolution, you
+	  must use fbset to change it.
+
+	  Also do not forget that second head supports only 16 and 32 bpp
+	  packed pixels, so it is a good idea to compile them into the kernel
+	  too.  You can use only some font widths, as the driver uses generic
+	  painting procedures (the secondary head does not use acceleration
+	  engine).
+
+config FB_RADEON
+	tristate "ATI Radeon display support"
+	depends on FB && PCI
+	select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MACMODES if PPC_OF
+	help
+	  Choose this option if you want to use an ATI Radeon graphics card as
+	  a framebuffer device.  There are both PCI and AGP versions.  You
+	  don't need to choose this to run the Radeon in plain VGA mode.
+
+	  There is a product page at
+	  http://products.amd.com/en-us/GraphicCardResult.aspx
+
+config FB_RADEON_I2C
+	bool "DDC/I2C for ATI Radeon support"
+	depends on FB_RADEON
+	select FB_DDC
+	default y
+	help
+	  Say Y here if you want DDC/I2C support for your Radeon board. 
+
+config FB_RADEON_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_RADEON
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
+config FB_RADEON_DEBUG
+	bool "Lots of debug output from Radeon driver"
+	depends on FB_RADEON
+	default n
+	help
+	  Say Y here if you want the Radeon driver to output all sorts
+	  of debugging information to provide to the maintainer when
+	  something goes wrong.
+
+config FB_ATY128
+	tristate "ATI Rage128 display support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
+	select FB_MACMODES if PPC_PMAC
+	help
+	  This driver supports graphics boards with the ATI Rage128 chips.
+	  Say Y if you have such a graphics board and read
+	  <file:Documentation/fb/aty128fb.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called aty128fb.
+
+config FB_ATY128_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_ATY128
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
+config FB_ATY
+	tristate "ATI Mach64 display support" if PCI || ATARI
+	depends on FB && !SPARC32
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_BACKLIGHT if FB_ATY_BACKLIGHT
+	select FB_MACMODES if PPC
+	help
+	  This driver supports graphics boards with the ATI Mach64 chips.
+	  Say Y if you have such a graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atyfb.
+
+config FB_ATY_CT
+	bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
+	depends on PCI && FB_ATY
+	default y if SPARC64 && PCI
+	help
+	  Say Y here to support use of ATI's 64-bit Rage boards (or other
+	  boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
+	  framebuffer device.  The ATI product support page for these boards
+	  is at <http://support.ati.com/products/pc/mach64/mach64.html>.
+
+config FB_ATY_GENERIC_LCD
+	bool "Mach64 generic LCD support"
+	depends on FB_ATY_CT
+	help
+	  Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
+	  Rage XC, or Rage XL chipset.
+
+config FB_ATY_GX
+	bool "Mach64 GX support" if PCI
+	depends on FB_ATY
+	default y if ATARI
+	help
+	  Say Y here to support use of the ATI Mach64 Graphics Expression
+	  board (or other boards based on the Mach64 GX chipset) as a
+	  framebuffer device.  The ATI product support page for these boards
+	  is at
+	  <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
+
+config FB_ATY_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_ATY
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
+config FB_S3
+	tristate "S3 Trio/Virge support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_TILEBLITTING
+	select FB_SVGALIB
+	select VGASTATE
+	select FONT_8x16 if FRAMEBUFFER_CONSOLE
+	---help---
+	  Driver for graphics boards with S3 Trio / S3 Virge chip.
+
+config FB_S3_DDC
+	bool "DDC for S3 support"
+	depends on FB_S3
+	select FB_DDC
+	default y
+	help
+	  Say Y here if you want DDC support for your S3 graphics card.
+
+config FB_SAVAGE
+	tristate "S3 Savage support"
+	depends on FB && PCI
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VGASTATE
+	help
+	  This driver supports notebooks and computers with S3 Savage PCI/AGP
+	  chips.
+
+	  Say Y if you have such a graphics card.
+
+	  To compile this driver as a module, choose M here; the module
+	  will be called savagefb.
+
+config FB_SAVAGE_I2C
+       bool "Enable DDC2 Support"
+       depends on FB_SAVAGE
+       select FB_DDC
+       help
+	  This enables I2C support for S3 Savage Chipsets.  This is used
+	  only for getting EDID information from the attached display
+	  allowing for robust video mode handling and switching.
+
+	  Because fbdev-2.6 requires that drivers must be able to
+	  independently validate video mode parameters, you should say Y
+	  here.
+
+config FB_SAVAGE_ACCEL
+       bool "Enable Console Acceleration"
+       depends on FB_SAVAGE
+       default n
+       help
+          This option will compile in console acceleration support. If
+          the resulting framebuffer console has bothersome glitches, then
+          choose N here.
+
+config FB_SIS
+	tristate "SiS/XGI display support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_BOOT_VESA_SUPPORT if FB_SIS = y
+	help
+	  This is the frame buffer device driver for the SiS 300, 315, 330
+	  and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
+	  Specs available at <http://www.sis.com> and <http://www.xgitech.com>.
+
+	  To compile this driver as a module, choose M here; the module
+	  will be called sisfb.
+
+config FB_SIS_300
+	bool "SiS 300 series support"
+	depends on FB_SIS
+	help
+	  Say Y here to support use of the SiS 300/305, 540, 630 and 730.
+
+config FB_SIS_315
+	bool "SiS 315/330/340 series and XGI support"
+	depends on FB_SIS
+	help
+	  Say Y here to support use of the SiS 315, 330 and 340 series
+	  (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
+	  as XGI V3XT, V5, V8 and Z7.
+
+config FB_VIA
+       tristate "VIA UniChrome (Pro) and Chrome9 display support"
+       depends on FB && PCI && X86
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select I2C_ALGOBIT
+       select I2C
+       select GPIOLIB
+       help
+	  This is the frame buffer device driver for Graphics chips of VIA
+	  UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
+	  CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
+ 	  /P4M900,VX800)
+	  Say Y if you have a VIA UniChrome graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called viafb.
+
+if FB_VIA
+
+config FB_VIA_DIRECT_PROCFS
+	bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
+	depends on FB_VIA
+	default n
+	help
+	  Allow direct hardware access to some output registers via procfs.
+	  This is dangerous but may provide the only chance to get the
+	  correct output device configuration.
+	  Its use is strongly discouraged.
+
+config FB_VIA_X_COMPATIBILITY
+	bool "X server compatibility"
+	depends on FB_VIA
+	default n
+	help
+	  This option reduces the functionality (power saving, ...) of the
+	  framebuffer to avoid negative impact on the OpenChrome X server.
+	  If you use any X server other than fbdev you should enable this
+	  otherwise it should be safe to disable it and allow using all
+	  features.
+
+endif
+
+config FB_NEOMAGIC
+	tristate "NeoMagic display support"
+	depends on FB && PCI
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VGASTATE
+	help
+	  This driver supports notebooks with NeoMagic PCI chips.
+	  Say Y if you have such a graphics card. 
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called neofb.
+
+config FB_KYRO
+	tristate "IMG Kyro support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
+	  graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called kyrofb.
+
+config FB_3DFX
+	tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
+	depends on FB && PCI
+	select FB_CFB_IMAGEBLIT
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_MODE_HELPERS
+	help
+	  This driver supports graphics boards with the 3Dfx Banshee,
+	  Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
+	  such a graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tdfxfb.
+
+config FB_3DFX_ACCEL
+	bool "3Dfx Acceleration functions"
+	depends on FB_3DFX
+	---help---
+	This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
+	device driver with acceleration functions.
+
+config FB_3DFX_I2C
+	bool "Enable DDC/I2C support"
+	depends on FB_3DFX
+	select FB_DDC
+	default y
+	help
+	  Say Y here if you want DDC/I2C support for your 3dfx Voodoo3.
+
+config FB_VOODOO1
+	tristate "3Dfx Voodoo Graphics (sst1) support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or 
+	  Voodoo2 (cvg) based graphics card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sstfb.
+
+	  WARNING: Do not use any application that uses the 3D engine
+	  (namely glide) while using this driver.
+	  Please read the <file:Documentation/fb/sstfb.txt> for supported
+	  options and other important info  support.
+
+config FB_VT8623
+	tristate "VIA VT8623 support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_TILEBLITTING
+	select FB_SVGALIB
+	select VGASTATE
+	select FONT_8x16 if FRAMEBUFFER_CONSOLE
+	---help---
+	  Driver for CastleRock integrated graphics core in the
+	  VIA VT8623 [Apollo CLE266] chipset.
+
+config FB_TRIDENT
+	tristate "Trident/CyberXXX/CyberBlade support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  This is the frame buffer device driver for Trident PCI/AGP chipsets.
+	  Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
+	  and Blade XP.
+	  There are also integrated versions of these chips called CyberXXXX,
+	  CyberImage or CyberBlade. These chips are mostly found in laptops
+	  but also on some motherboards including early VIA EPIA motherboards.
+	  For more information, read <file:Documentation/fb/tridentfb.txt>
+
+	  Say Y if you have such a graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tridentfb.
+
+config FB_ARK
+	tristate "ARK 2000PV support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_TILEBLITTING
+	select FB_SVGALIB
+	select VGASTATE
+	select FONT_8x16 if FRAMEBUFFER_CONSOLE
+	---help---
+	  Driver for PCI graphics boards with ARK 2000PV chip
+	  and ICS 5342 RAMDAC.
+
+config FB_PM3
+	tristate "Permedia3 support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the 3DLabs Permedia3
+	  chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
+	  similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
+	  and maybe other boards.
+
+config FB_CARMINE
+	tristate "Fujitsu carmine frame buffer support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Fujitsu Carmine chip.
+	  The driver provides two independent frame buffer devices.
+
+choice
+	depends on FB_CARMINE
+	prompt "DRAM timing"
+	default FB_CARMINE_DRAM_EVAL
+
+config FB_CARMINE_DRAM_EVAL
+	bool "Eval board timings"
+	help
+	  Use timings which work on the eval card.
+
+config CARMINE_DRAM_CUSTOM
+	bool "Custom board timings"
+	help
+	  Use custom board timings.
+endchoice
+
+config FB_AU1100
+	bool "Au1100 LCD Driver"
+	depends on (FB = y) && MIPS_ALCHEMY
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer driver for the AMD Au1100 SOC.  It can drive
+	  various panels and CRTs by passing in kernel cmd line option
+	  au1100fb:panel=<name>.
+
+config FB_AU1200
+	bool "Au1200/Au1300 LCD Driver"
+	depends on (FB = y) && MIPS_ALCHEMY
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  This is the framebuffer driver for the Au1200/Au1300 SOCs.
+	  It can drive various panels and CRTs by passing in kernel cmd line
+	  option au1200fb:panel=<name>.
+
+config FB_VT8500
+	bool "VIA VT8500 framebuffer support"
+	depends on (FB = y) && ARM && ARCH_VT8500
+	select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+	select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
+	select FB_SYS_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
+	help
+	  This is the framebuffer driver for VIA VT8500 integrated LCD
+	  controller.
+
+config FB_WM8505
+	bool "Wondermedia WM8xxx-series frame buffer support"
+	depends on (FB = y) && ARM && ARCH_VT8500
+	select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+	select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
+	select FB_SYS_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
+	help
+	  This is the framebuffer driver for WonderMedia WM8xxx-series
+	  integrated LCD controller. This driver covers the WM8505, WM8650
+	  and WM8850 SoCs.
+
+config FB_WMT_GE_ROPS
+	bool "VT8500/WM8xxx accelerated raster ops support"
+	depends on (FB = y) && (FB_VT8500 || FB_WM8505)
+	default n
+	help
+	  This adds support for accelerated raster operations on the
+	  VIA VT8500 and Wondermedia 85xx series SoCs.
+
+source "drivers/video/fbdev/geode/Kconfig"
+
+config FB_HIT
+	tristate "HD64461 Frame Buffer support"
+	depends on FB && HD64461
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Hitachi HD64461 LCD
+	  frame buffer card.
+
+config FB_PMAG_AA
+	bool "PMAG-AA TURBOchannel framebuffer support"
+	depends on (FB = y) && TC
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	help
+	  Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1)
+	  used mainly in the MIPS-based DECstation series.
+
+config FB_PMAG_BA
+	tristate "PMAG-BA TURBOchannel framebuffer support"
+	depends on FB && TC
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	help
+	  Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8)
+	  used mainly in the MIPS-based DECstation series.
+
+config FB_PMAGB_B
+	tristate "PMAGB-B TURBOchannel framebuffer support"
+	depends on FB && TC
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	help
+	  Support for the PMAGB-B TURBOchannel framebuffer card used mainly
+	  in the MIPS-based DECstation series. The card is currently only
+	  supported in 1280x1024x8 mode.
+
+config FB_MAXINE
+	bool "Maxine (Personal DECstation) onboard framebuffer support"
+	depends on (FB = y) && MACH_DECSTATION
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	help
+	  Support for the onboard framebuffer (1024x768x8) in the Personal
+	  DECstation series (Personal DECstation 5000/20, /25, /33, /50,
+	  Codename "Maxine").
+
+config FB_G364
+	bool "G364 frame buffer support"
+	depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700)
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	help
+	  The G364 driver is the framebuffer used in MIPS Magnum 4000 and
+	  Olivetti M700-10 systems.
+
+config FB_68328
+	bool "Motorola 68328 native frame buffer support"
+	depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328)
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	help
+	  Say Y here if you want to support the built-in frame buffer of
+	  the Motorola 68328 CPU family.
+
+config FB_PXA168
+	tristate "PXA168/910 LCD framebuffer support"
+	depends on FB && (CPU_PXA168 || CPU_PXA910)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the built-in LCD controller in the Marvell
+	  MMP processor.
+
+config FB_PXA
+	tristate "PXA LCD framebuffer support"
+	depends on FB && ARCH_PXA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the built-in LCD controller in the Intel
+	  PXA2x0 processor.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called pxafb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/kbuild/modules.txt>.
+
+	  If unsure, say N.
+
+config FB_PXA_OVERLAY
+	bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer"
+	default n
+	depends on FB_PXA && (PXA27x || PXA3xx)
+
+config FB_PXA_SMARTPANEL
+	bool "PXA Smartpanel LCD support"
+	default n
+	depends on FB_PXA
+
+config FB_PXA_PARAMETERS
+	bool "PXA LCD command line parameters"
+	default n
+	depends on FB_PXA
+	---help---
+	  Enable the use of kernel command line or module parameters
+	  to configure the physical properties of the LCD panel when
+	  using the PXA LCD driver.
+
+	  This option allows you to override the panel parameters
+	  supplied by the platform in order to support multiple
+	  different models of flatpanel. If you will only be using a
+	  single model of flatpanel then you can safely leave this
+	  option disabled.
+
+	  <file:Documentation/fb/pxafb.txt> describes the available parameters.
+
+config PXA3XX_GCU
+	tristate "PXA3xx 2D graphics accelerator driver"
+	depends on FB_PXA
+	help
+	  Kernelspace driver for the 2D graphics controller unit (GCU)
+	  found on PXA3xx processors. There is a counterpart driver in the
+	  DirectFB suite, see http://www.directfb.org/
+
+	  If you compile this as a module, it will be called pxa3xx_gcu.
+
+config FB_MBX
+	tristate "2700G LCD framebuffer support"
+	depends on FB && ARCH_PXA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Framebuffer driver for the Intel 2700G (Marathon) Graphics
+	  Accelerator
+
+config FB_MBX_DEBUG
+       bool "Enable debugging info via debugfs"
+       depends on FB_MBX && DEBUG_FS
+       default n
+       ---help---
+         Enable this if you want debugging information using the debug
+         filesystem (debugfs)
+
+         If unsure, say N.
+
+config FB_FSL_DIU
+	tristate "Freescale DIU framebuffer support"
+	depends on FB && FSL_SOC
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select PPC_LIB_RHEAP
+	---help---
+	  Framebuffer driver for the Freescale SoC DIU
+
+config FB_W100
+	tristate "W100 frame buffer support"
+	depends on FB && ARCH_PXA
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
+	  It can also drive the w3220 chip found on iPAQ hx4700.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called w100fb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/kbuild/modules.txt>.
+
+	  If unsure, say N.
+
+config FB_SH_MOBILE_LCDC
+	tristate "SuperH Mobile LCDC framebuffer support"
+	depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	select FB_BACKLIGHT
+	select SH_MIPI_DSI if SH_LCD_MIPI_DSI
+	---help---
+	  Frame buffer driver for the on-chip SH-Mobile LCD controller.
+
+config FB_SH_MOBILE_HDMI
+	tristate "SuperH Mobile HDMI controller support"
+	depends on FB_SH_MOBILE_LCDC
+	select FB_MODE_HELPERS
+	select SOUND
+	select SND
+	select SND_SOC
+	---help---
+	  Driver for the on-chip SH-Mobile HDMI controller.
+
+config FB_TMIO
+	tristate "Toshiba Mobile IO FrameBuffer support"
+	depends on FB && MFD_CORE
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the Toshiba Mobile IO integrated as found
+	  on the Sharp SL-6000 series
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called tmiofb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/kbuild/modules.txt>.
+
+	  If unsure, say N.
+
+config FB_TMIO_ACCELL
+	bool "tmiofb acceleration"
+	depends on FB_TMIO
+	default y
+
+config FB_S3C
+	tristate "Samsung S3C framebuffer support"
+	depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \
+		ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the built-in FB controller in the Samsung
+	  SoC line from the S3C2443 onwards, including the S3C2416, S3C2450,
+	  and the S3C64XX series such as the S3C6400 and S3C6410.
+
+	  These chips all have the same basic framebuffer design with the
+	  actual capabilities depending on the chip. For instance the S3C6400
+	  and S3C6410 support 4 hardware windows whereas the S3C24XX series
+	  currently only have two.
+
+	  Currently the support is only for the S3C6400 and S3C6410 SoCs.
+
+config FB_S3C_DEBUG_REGWRITE
+       bool "Debug register writes"
+       depends on FB_S3C
+       ---help---
+         Show all register writes via pr_debug()
+
+config FB_S3C2410
+	tristate "S3C2410 LCD framebuffer support"
+	depends on FB && ARCH_S3C24XX
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the built-in LCD controller in the Samsung
+	  S3C2410 processor.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called s3c2410fb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/kbuild/modules.txt>.
+
+	  If unsure, say N.
+config FB_S3C2410_DEBUG
+	bool "S3C2410 lcd debug messages"
+	depends on FB_S3C2410
+	help
+	  Turn on debugging messages. Note that you can set/unset at run time
+	  through sysfs
+
+config FB_NUC900
+        bool "NUC900 LCD framebuffer support"
+        depends on FB && ARCH_W90X900
+        select FB_CFB_FILLRECT
+        select FB_CFB_COPYAREA
+        select FB_CFB_IMAGEBLIT
+        ---help---
+          Frame buffer driver for the built-in LCD controller in the Nuvoton
+          NUC900 processor
+
+config GPM1040A0_320X240
+        bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
+        depends on FB_NUC900
+
+config FB_SM501
+	tristate "Silicon Motion SM501 framebuffer support"
+	depends on FB && MFD_SM501
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the CRT and LCD controllers in the Silicon
+	  Motion SM501.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called sm501fb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/kbuild/modules.txt>.
+
+	  If unsure, say N.
+
+config FB_SMSCUFX
+	tristate "SMSC UFX6000/7000 USB Framebuffer support"
+	depends on FB && USB
+	select FB_MODE_HELPERS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	---help---
+	  This is a kernel framebuffer driver for SMSC UFX USB devices.
+	  Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
+	  mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000
+	  (USB 3.0) devices.
+	  To compile as a module, choose M here: the module name is smscufx.
+
+config FB_UDL
+	tristate "Displaylink USB Framebuffer support"
+	depends on FB && USB
+	select FB_MODE_HELPERS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	---help---
+	  This is a kernel framebuffer driver for DisplayLink USB devices.
+	  Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
+	  mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
+	  To compile as a module, choose M here: the module name is udlfb.
+
+config FB_IBM_GXT4500
+	tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors"
+	depends on FB && PPC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Say Y here to enable support for the IBM GXT4000P/6000P and
+	  GXT4500P/6500P display adaptor based on Raster Engine RC1000,
+	  found on some IBM System P (pSeries) machines. This driver
+	  doesn't use Geometry Engine GT1000.
+
+config FB_PS3
+	tristate "PS3 GPU framebuffer driver"
+	depends on FB && PS3_PS3AV
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
+	---help---
+	  Include support for the virtual frame buffer in the PS3 platform.
+
+config FB_PS3_DEFAULT_SIZE_M
+	int "PS3 default frame buffer size (in MiB)"
+	depends on FB_PS3
+	default 9
+	---help---
+	  This is the default size (in MiB) of the virtual frame buffer in
+	  the PS3.
+	  The default value can be overridden on the kernel command line
+	  using the "ps3fb" option (e.g. "ps3fb=9M");
+
+config FB_XILINX
+	tristate "Xilinx frame buffer support"
+	depends on FB && (XILINX_VIRTEX || MICROBLAZE || ARCH_ZYNQ)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Include support for the Xilinx ML300/ML403 reference design
+	  framebuffer. ML300 carries a 640*480 LCD display on the board,
+	  ML403 uses a standard DB15 VGA connector.
+
+config FB_GOLDFISH
+	tristate "Goldfish Framebuffer"
+	depends on FB && HAS_DMA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Framebuffer driver for Goldfish Virtual Platform
+
+config FB_COBALT
+	tristate "Cobalt server LCD frame buffer support"
+	depends on FB && (MIPS_COBALT || MIPS_SEAD3)
+
+config FB_SH7760
+	bool "SH7760/SH7763/SH7720/SH7721 LCDC support"
+	depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
+		|| CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Support for the SH7760/SH7763/SH7720/SH7721 integrated
+	  (D)STN/TFT LCD Controller.
+	  Supports display resolutions up to 1024x1024 pixel, grayscale and
+	  color operation, with depths ranging from 1 bpp to 8 bpp monochrome
+	  and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
+	  panels <= 320 pixel horizontal resolution.
+
+config FB_DA8XX
+	tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support"
+	depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_CFB_REV_PIXELS_IN_BYTE
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
+	---help---
+	  This is the frame buffer device driver for the TI LCD controller
+	  found on DA8xx/OMAP-L1xx/AM335x SoCs.
+	  If unsure, say N.
+
+config FB_VIRTUAL
+	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
+	depends on FB
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	---help---
+	  This is a `virtual' frame buffer device. It operates on a chunk of
+	  unswappable kernel memory instead of on the memory of a graphics
+	  board. This means you cannot see any output sent to this frame
+	  buffer device, while it does consume precious memory. The main use
+	  of this frame buffer device is testing and debugging the frame
+	  buffer subsystem. Do NOT enable it for normal systems! To protect
+	  the innocent, it has to be enabled explicitly at boot time using the
+	  kernel option `video=vfb:'.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vfb. In order to load it, you must use
+	  the vfb_enable=1 option.
+
+	  If unsure, say N.
+
+config XEN_FBDEV_FRONTEND
+	tristate "Xen virtual frame buffer support"
+	depends on FB && XEN
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
+	select XEN_XENBUS_FRONTEND
+	default y
+	help
+	  This driver implements the front-end of the Xen virtual
+	  frame buffer driver.  It communicates with a back-end
+	  in another domain.
+
+config FB_METRONOME
+	tristate "E-Ink Metronome/8track controller support"
+	depends on FB
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	help
+	  This driver implements support for the E-Ink Metronome
+	  controller. The pre-release name for this device was 8track
+	  and could also have been called by some vendors as PVI-nnnn.
+
+config FB_MB862XX
+	tristate "Fujitsu MB862xx GDC support"
+	depends on FB
+	depends on PCI || (OF && PPC)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers.
+
+choice
+	prompt "GDC variant"
+	depends on FB_MB862XX
+
+config FB_MB862XX_PCI_GDC
+	bool "Carmine/Coral-P(A) GDC"
+	depends on PCI
+	---help---
+	  This enables framebuffer support for Fujitsu Carmine/Coral-P(A)
+	  PCI graphics controller devices.
+
+config FB_MB862XX_LIME
+	bool "Lime GDC"
+	depends on OF && PPC
+	select FB_FOREIGN_ENDIAN
+	select FB_LITTLE_ENDIAN
+	---help---
+	  Framebuffer support for Fujitsu Lime GDC on host CPU bus.
+
+endchoice
+
+config FB_MB862XX_I2C
+	bool "Support I2C bus on MB862XX GDC"
+	depends on FB_MB862XX && I2C
+	default y
+	help
+	  Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter
+	  driver to support accessing I2C devices on controller's I2C bus.
+	  These are usually some video decoder chips.
+
+config FB_EP93XX
+	tristate "EP93XX frame buffer support"
+	depends on FB && ARCH_EP93XX
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Framebuffer driver for the Cirrus Logic EP93XX series of processors.
+	  This driver is also available as a module. The module will be called
+	  ep93xx-fb.
+
+config FB_PRE_INIT_FB
+	bool "Don't reinitialize, use bootloader's GDC/Display configuration"
+	depends on FB && FB_MB862XX_LIME
+	---help---
+	  Select this option if display contents should be inherited as set by
+	  the bootloader.
+
+config FB_MSM
+	tristate "MSM Framebuffer support"
+	depends on FB && ARCH_MSM
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+
+config FB_MX3
+	tristate "MX3 Framebuffer support"
+	depends on FB && MX3_IPU
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	default y
+	help
+	  This is a framebuffer device for the i.MX31 LCD Controller. So
+	  far only synchronous displays are supported. If you plan to use
+	  an LCD display with your i.MX31 system, say Y here.
+
+config FB_BROADSHEET
+	tristate "E-Ink Broadsheet/Epson S1D13521 controller support"
+	depends on FB
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	help
+	  This driver implements support for the E-Ink Broadsheet
+	  controller. The release name for this device was Epson S1D13521
+	  and could also have been called by other names when coupled with
+	  a bridge adapter.
+
+config FB_AUO_K190X
+	tristate "AUO-K190X EPD controller support"
+	depends on FB
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	help
+	  Provides support for epaper controllers from the K190X series
+	  of AUO. These controllers can be used to drive epaper displays
+	  from Sipix.
+
+	  This option enables the common support, shared by the individual
+	  controller drivers. You will also have to enable the driver
+	  for the controller type used in your device.
+
+config FB_AUO_K1900
+	tristate "AUO-K1900 EPD controller support"
+	depends on FB && FB_AUO_K190X
+	help
+	  This driver implements support for the AUO K1900 epd-controller.
+	  This controller can drive Sipix epaper displays but can only do
+	  serial updates, reducing the number of possible frames per second.
+
+config FB_AUO_K1901
+	tristate "AUO-K1901 EPD controller support"
+	depends on FB && FB_AUO_K190X
+	help
+	  This driver implements support for the AUO K1901 epd-controller.
+	  This controller can drive Sipix epaper displays and supports
+	  concurrent updates, making higher frames per second possible.
+
+config FB_JZ4740
+	tristate "JZ4740 LCD framebuffer support"
+	depends on FB && MACH_JZ4740
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	help
+	  Framebuffer support for the JZ4740 SoC.
+
+config FB_MXS
+	tristate "MXS LCD framebuffer support"
+	depends on FB && ARCH_MXS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS
+	select VIDEOMODE_HELPERS
+	help
+	  Framebuffer support for the MXS SoC.
+
+config FB_PUV3_UNIGFX
+	tristate "PKUnity v3 Unigfx framebuffer support"
+	depends on FB && UNICORE32 && ARCH_PUV3
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  Choose this option if you want to use the Unigfx device as a
+	  framebuffer device. Without the support of PCI & AGP.
+
+config FB_HYPERV
+	tristate "Microsoft Hyper-V Synthetic Video support"
+	depends on FB && HYPERV
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
+
+config FB_SIMPLE
+	bool "Simple framebuffer support"
+	depends on (FB = y)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Say Y if you want support for a simple frame-buffer.
+
+	  This driver assumes that the display hardware has been initialized
+	  before the kernel boots, and the kernel will simply render to the
+	  pre-allocated frame buffer surface.
+
+	  Configuration re: surface address, size, and format must be provided
+	  through device tree, or plain old platform data.
+
+source "drivers/video/fbdev/omap/Kconfig"
+source "drivers/video/fbdev/omap2/Kconfig"
+source "drivers/video/fbdev/exynos/Kconfig"
+source "drivers/video/fbdev/mmp/Kconfig"
+
+config FB_SH_MOBILE_MERAM
+	tristate "SuperH Mobile MERAM read ahead support"
+	depends on (SUPERH || ARCH_SHMOBILE)
+	select GENERIC_ALLOCATOR
+	---help---
+	  Enable MERAM support for the SuperH controller.
+
+	  This will allow for caching of the framebuffer to provide more
+	  reliable access under heavy main memory bus traffic situations.
+	  Up to 4 memory channels can be configured, allowing 4 RGB or
+	  2 YCbCr framebuffers to be configured.
+
+config FB_SSD1307
+	tristate "Solomon SSD1307 framebuffer support"
+	depends on FB && I2C
+	depends on OF
+	depends on GPIOLIB
+	select FB_SYS_FOPS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_DEFERRED_IO
+	select PWM
+	help
+	  This driver implements support for the Solomon SSD1307
+	  OLED controller over I2C.
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
new file mode 100644
index 000000000000..0284f2a12538
--- /dev/null
+++ b/drivers/video/fbdev/Makefile
@@ -0,0 +1,152 @@
+# Makefile for the Linux video drivers.
+# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net>
+# Rewritten to use lists instead of if-statements.
+
+# Each configuration option enables a list of files.
+
+obj-y				+= core/
+
+obj-$(CONFIG_EXYNOS_VIDEO)     += exynos/
+
+obj-$(CONFIG_FB_MACMODES)      += macmodes.o
+obj-$(CONFIG_FB_WMT_GE_ROPS)   += wmt_ge_rops.o
+
+# Hardware specific drivers go first
+obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
+obj-$(CONFIG_FB_ARC)              += arcfb.o
+obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
+obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
+obj-$(CONFIG_FB_GRVGA)            += grvga.o
+obj-$(CONFIG_FB_PM2)              += pm2fb.o
+obj-$(CONFIG_FB_PM3)		  += pm3fb.o
+
+obj-$(CONFIG_FB_I740)		  += i740fb.o
+obj-$(CONFIG_FB_MATROX)		  += matrox/
+obj-$(CONFIG_FB_RIVA)		  += riva/
+obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
+obj-$(CONFIG_FB_ATY)		  += aty/ macmodes.o
+obj-$(CONFIG_FB_ATY128)		  += aty/ macmodes.o
+obj-$(CONFIG_FB_RADEON)		  += aty/
+obj-$(CONFIG_FB_SIS)		  += sis/
+obj-$(CONFIG_FB_VIA)		  += via/
+obj-$(CONFIG_FB_KYRO)             += kyro/
+obj-$(CONFIG_FB_SAVAGE)		  += savage/
+obj-$(CONFIG_FB_GEODE)		  += geode/
+obj-$(CONFIG_FB_MBX)		  += mbx/
+obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o
+obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
+obj-$(CONFIG_FB_CONTROL)          += controlfb.o
+obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
+obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
+obj-$(CONFIG_FB_CT65550)          += chipsfb.o
+obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
+obj-$(CONFIG_FB_FM2)              += fm2fb.o
+obj-$(CONFIG_FB_VT8623)           += vt8623fb.o
+obj-$(CONFIG_FB_TRIDENT)          += tridentfb.o
+obj-$(CONFIG_FB_LE80578)          += vermilion/
+obj-$(CONFIG_FB_S3)               += s3fb.o
+obj-$(CONFIG_FB_ARK)              += arkfb.o
+obj-$(CONFIG_FB_STI)              += stifb.o
+obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
+obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
+obj-$(CONFIG_FB_CG3)              += cg3.o sbuslib.o
+obj-$(CONFIG_FB_BW2)              += bw2.o sbuslib.o
+obj-$(CONFIG_FB_CG14)             += cg14.o sbuslib.o
+obj-$(CONFIG_FB_P9100)            += p9100.o sbuslib.o
+obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o
+obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
+obj-$(CONFIG_FB_ACORN)            += acornfb.o
+obj-$(CONFIG_FB_ATARI)            += atafb.o c2p_iplan2.o atafb_mfb.o \
+                                     atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
+obj-$(CONFIG_FB_MAC)              += macfb.o
+obj-$(CONFIG_FB_HECUBA)           += hecubafb.o
+obj-$(CONFIG_FB_N411)             += n411.o
+obj-$(CONFIG_FB_HGA)              += hgafb.o
+obj-$(CONFIG_FB_XVR500)           += sunxvr500.o
+obj-$(CONFIG_FB_XVR2500)          += sunxvr2500.o
+obj-$(CONFIG_FB_XVR1000)          += sunxvr1000.o
+obj-$(CONFIG_FB_IGA)              += igafb.o
+obj-$(CONFIG_FB_APOLLO)           += dnfb.o
+obj-$(CONFIG_FB_Q40)              += q40fb.o
+obj-$(CONFIG_FB_TGA)              += tgafb.o
+obj-$(CONFIG_FB_HP300)            += hpfb.o
+obj-$(CONFIG_FB_G364)             += g364fb.o
+obj-$(CONFIG_FB_EP93XX)		  += ep93xx-fb.o
+obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
+obj-$(CONFIG_FB_HIT)              += hitfb.o
+obj-$(CONFIG_FB_ATMEL)		  += atmel_lcdfb.o
+obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
+obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
+obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o
+obj-$(CONFIG_FB_GOLDFISH)         += goldfishfb.o
+obj-$(CONFIG_FB_68328)            += 68328fb.o
+obj-$(CONFIG_FB_GBE)              += gbefb.o
+obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o
+obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
+obj-$(CONFIG_FB_PXA)		  += pxafb.o
+obj-$(CONFIG_FB_PXA168)		  += pxa168fb.o
+obj-$(CONFIG_PXA3XX_GCU)	  += pxa3xx-gcu.o
+obj-$(CONFIG_MMP_DISP)           += mmp/
+obj-$(CONFIG_FB_W100)		  += w100fb.o
+obj-$(CONFIG_FB_TMIO)		  += tmiofb.o
+obj-$(CONFIG_FB_AU1100)		  += au1100fb.o
+obj-$(CONFIG_FB_AU1200)		  += au1200fb.o
+obj-$(CONFIG_FB_VT8500)		  += vt8500lcdfb.o
+obj-$(CONFIG_FB_WM8505)		  += wm8505fb.o
+obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o
+obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o
+obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o
+obj-$(CONFIG_FB_MAXINE)		  += maxinefb.o
+obj-$(CONFIG_FB_METRONOME)        += metronomefb.o
+obj-$(CONFIG_FB_BROADSHEET)       += broadsheetfb.o
+obj-$(CONFIG_FB_AUO_K190X)	  += auo_k190x.o
+obj-$(CONFIG_FB_AUO_K1900)	  += auo_k1900fb.o
+obj-$(CONFIG_FB_AUO_K1901)	  += auo_k1901fb.o
+obj-$(CONFIG_FB_S1D13XXX)	  += s1d13xxxfb.o
+obj-$(CONFIG_FB_SH7760)		  += sh7760fb.o
+obj-$(CONFIG_FB_IMX)              += imxfb.o
+obj-$(CONFIG_FB_S3C)		  += s3c-fb.o
+obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.o
+obj-$(CONFIG_FB_FSL_DIU)	  += fsl-diu-fb.o
+obj-$(CONFIG_FB_COBALT)           += cobalt_lcdfb.o
+obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
+obj-$(CONFIG_FB_PS3)		  += ps3fb.o
+obj-$(CONFIG_FB_SM501)            += sm501fb.o
+obj-$(CONFIG_FB_UDL)		  += udlfb.o
+obj-$(CONFIG_FB_SMSCUFX)	  += smscufx.o
+obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
+obj-$(CONFIG_SH_MIPI_DSI)	  += sh_mipi_dsi.o
+obj-$(CONFIG_FB_SH_MOBILE_HDMI)	  += sh_mobile_hdmi.o
+obj-$(CONFIG_FB_SH_MOBILE_MERAM)  += sh_mobile_meram.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC)	  += sh_mobile_lcdcfb.o
+obj-$(CONFIG_FB_OMAP)             += omap/
+obj-y                             += omap2/
+obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
+obj-$(CONFIG_FB_CARMINE)          += carminefb.o
+obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
+obj-$(CONFIG_FB_MSM)              += msm/
+obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
+obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
+obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
+obj-$(CONFIG_FB_HYPERV)		  += hyperv_fb.o
+obj-$(CONFIG_FB_OPENCORES)	  += ocfb.o
+
+# Platform or fallback drivers go here
+obj-$(CONFIG_FB_UVESA)            += uvesafb.o
+obj-$(CONFIG_FB_VESA)             += vesafb.o
+obj-$(CONFIG_FB_EFI)              += efifb.o
+obj-$(CONFIG_FB_VGA16)            += vga16fb.o
+obj-$(CONFIG_FB_OF)               += offb.o
+obj-$(CONFIG_FB_BF537_LQ035)      += bf537-lq035.o
+obj-$(CONFIG_FB_BF54X_LQ043)	  += bf54x-lq043fb.o
+obj-$(CONFIG_FB_BFIN_LQ035Q1)     += bfin-lq035q1-fb.o
+obj-$(CONFIG_FB_BFIN_T350MCQB)	  += bfin-t350mcqb-fb.o
+obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
+obj-$(CONFIG_FB_MX3)		  += mx3fb.o
+obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
+obj-$(CONFIG_FB_MXS)		  += mxsfb.o
+obj-$(CONFIG_FB_SSD1307)	  += ssd1307fb.o
+obj-$(CONFIG_FB_SIMPLE)           += simplefb.o
+
+# the test framebuffer is last
+obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff --git a/drivers/video/fbdev/acornfb.c b/drivers/video/fbdev/acornfb.c
new file mode 100644
index 000000000000..a305caea58ee
--- /dev/null
+++ b/drivers/video/fbdev/acornfb.c
@@ -0,0 +1,1143 @@
+/*
+ *  linux/drivers/video/acornfb.c
+ *
+ *  Copyright (C) 1998-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Frame buffer code for Acorn platforms
+ *
+ * NOTE: Most of the modes with X!=640 will disappear shortly.
+ * NOTE: Startup setting of HS & VS polarity not supported.
+ *       (do we need to support it if we're coming up in 640x480?)
+ *
+ * FIXME: (things broken by the "new improved" FBCON API)
+ *  - Blanking 8bpp displays with VIDC
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/gfp.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+
+#include "acornfb.h"
+
+/*
+ * Default resolution.
+ * NOTE that it has to be supported in the table towards
+ * the end of this file.
+ */
+#define DEFAULT_XRES	640
+#define DEFAULT_YRES	480
+#define DEFAULT_BPP	4
+
+/*
+ * define this to debug the video mode selection
+ */
+#undef DEBUG_MODE_SELECTION
+
+/*
+ * Translation from RISC OS monitor types to actual
+ * HSYNC and VSYNC frequency ranges.  These are
+ * probably not right, but they're the best info I
+ * have.  Allow 1% either way on the nominal for TVs.
+ */
+#define NR_MONTYPES	6
+static struct fb_monspecs monspecs[NR_MONTYPES] = {
+	{	/* TV		*/
+		.hfmin	= 15469,
+		.hfmax	= 15781,
+		.vfmin	= 49,
+		.vfmax	= 51,
+	}, {	/* Multi Freq	*/
+		.hfmin	= 0,
+		.hfmax	= 99999,
+		.vfmin	= 0,
+		.vfmax	= 199,
+	}, {	/* Hi-res mono	*/
+		.hfmin	= 58608,
+		.hfmax	= 58608,
+		.vfmin	= 64,
+		.vfmax	= 64,
+	}, {	/* VGA		*/
+		.hfmin	= 30000,
+		.hfmax	= 70000,
+		.vfmin	= 60,
+		.vfmax	= 60,
+	}, {	/* SVGA		*/
+		.hfmin	= 30000,
+		.hfmax	= 70000,
+		.vfmin	= 56,
+		.vfmax	= 75,
+	}, {
+		.hfmin	= 30000,
+		.hfmax	= 70000,
+		.vfmin	= 60,
+		.vfmax	= 60,
+	}
+};
+
+static struct fb_info fb_info;
+static struct acornfb_par current_par;
+static struct vidc_timing current_vidc;
+
+extern unsigned int vram_size;	/* set by setup.c */
+
+#ifdef HAS_VIDC20
+#include <mach/acornfb.h>
+
+#define MAX_SIZE	2*1024*1024
+
+/* VIDC20 has a different set of rules from the VIDC:
+ *  hcr  : must be multiple of 4
+ *  hswr : must be even
+ *  hdsr : must be even
+ *  hder : must be even
+ *  vcr  : >= 2, (interlace, must be odd)
+ *  vswr : >= 1
+ *  vdsr : >= 1
+ *  vder : >= vdsr
+ */
+static void acornfb_set_timing(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct vidc_timing vidc;
+	u_int vcr, fsize;
+	u_int ext_ctl, dat_ctl;
+	u_int words_per_line;
+
+	memset(&vidc, 0, sizeof(vidc));
+
+	vidc.h_sync_width	= var->hsync_len - 8;
+	vidc.h_border_start	= vidc.h_sync_width + var->left_margin + 8 - 12;
+	vidc.h_display_start	= vidc.h_border_start + 12 - 18;
+	vidc.h_display_end	= vidc.h_display_start + var->xres;
+	vidc.h_border_end	= vidc.h_display_end + 18 - 12;
+	vidc.h_cycle		= vidc.h_border_end + var->right_margin + 12 - 8;
+	vidc.h_interlace	= vidc.h_cycle / 2;
+	vidc.v_sync_width	= var->vsync_len - 1;
+	vidc.v_border_start	= vidc.v_sync_width + var->upper_margin;
+	vidc.v_display_start	= vidc.v_border_start;
+	vidc.v_display_end	= vidc.v_display_start + var->yres;
+	vidc.v_border_end	= vidc.v_display_end;
+	vidc.control		= acornfb_default_control();
+
+	vcr = var->vsync_len + var->upper_margin + var->yres +
+	      var->lower_margin;
+
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		vidc.v_cycle = (vcr - 3) / 2;
+		vidc.control |= VIDC20_CTRL_INT;
+	} else
+		vidc.v_cycle = vcr - 2;
+
+	switch (var->bits_per_pixel) {
+	case  1: vidc.control |= VIDC20_CTRL_1BPP;	break;
+	case  2: vidc.control |= VIDC20_CTRL_2BPP;	break;
+	case  4: vidc.control |= VIDC20_CTRL_4BPP;	break;
+	default:
+	case  8: vidc.control |= VIDC20_CTRL_8BPP;	break;
+	case 16: vidc.control |= VIDC20_CTRL_16BPP;	break;
+	case 32: vidc.control |= VIDC20_CTRL_32BPP;	break;
+	}
+
+	acornfb_vidc20_find_rates(&vidc, var);
+	fsize = var->vsync_len + var->upper_margin + var->lower_margin - 1;
+
+	if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
+		current_vidc = vidc;
+
+		vidc_writel(VIDC20_CTRL| vidc.control);
+		vidc_writel(0xd0000000 | vidc.pll_ctl);
+		vidc_writel(0x80000000 | vidc.h_cycle);
+		vidc_writel(0x81000000 | vidc.h_sync_width);
+		vidc_writel(0x82000000 | vidc.h_border_start);
+		vidc_writel(0x83000000 | vidc.h_display_start);
+		vidc_writel(0x84000000 | vidc.h_display_end);
+		vidc_writel(0x85000000 | vidc.h_border_end);
+		vidc_writel(0x86000000);
+		vidc_writel(0x87000000 | vidc.h_interlace);
+		vidc_writel(0x90000000 | vidc.v_cycle);
+		vidc_writel(0x91000000 | vidc.v_sync_width);
+		vidc_writel(0x92000000 | vidc.v_border_start);
+		vidc_writel(0x93000000 | vidc.v_display_start);
+		vidc_writel(0x94000000 | vidc.v_display_end);
+		vidc_writel(0x95000000 | vidc.v_border_end);
+		vidc_writel(0x96000000);
+		vidc_writel(0x97000000);
+	}
+
+	iomd_writel(fsize, IOMD_FSIZE);
+
+	ext_ctl = acornfb_default_econtrol();
+
+	if (var->sync & FB_SYNC_COMP_HIGH_ACT) /* should be FB_SYNC_COMP */
+		ext_ctl |= VIDC20_ECTL_HS_NCSYNC | VIDC20_ECTL_VS_NCSYNC;
+	else {
+		if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+			ext_ctl |= VIDC20_ECTL_HS_HSYNC;
+		else
+			ext_ctl |= VIDC20_ECTL_HS_NHSYNC;
+
+		if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+			ext_ctl |= VIDC20_ECTL_VS_VSYNC;
+		else
+			ext_ctl |= VIDC20_ECTL_VS_NVSYNC;
+	}
+
+	vidc_writel(VIDC20_ECTL | ext_ctl);
+
+	words_per_line = var->xres * var->bits_per_pixel / 32;
+
+	if (current_par.using_vram && info->fix.smem_len == 2048*1024)
+		words_per_line /= 2;
+
+	/* RiscPC doesn't use the VIDC's VRAM control. */
+	dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;
+
+	/* The data bus width is dependent on both the type
+	 * and amount of video memory.
+	 *     DRAM	32bit low
+	 * 1MB VRAM	32bit
+	 * 2MB VRAM	64bit
+	 */
+	if (current_par.using_vram && current_par.vram_half_sam == 2048)
+		dat_ctl |= VIDC20_DCTL_BUS_D63_0;
+	else
+		dat_ctl |= VIDC20_DCTL_BUS_D31_0;
+
+	vidc_writel(VIDC20_DCTL | dat_ctl);
+
+#ifdef DEBUG_MODE_SELECTION
+	printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
+	       var->yres, var->bits_per_pixel);
+	printk(KERN_DEBUG " H-cycle          : %d\n", vidc.h_cycle);
+	printk(KERN_DEBUG " H-sync-width     : %d\n", vidc.h_sync_width);
+	printk(KERN_DEBUG " H-border-start   : %d\n", vidc.h_border_start);
+	printk(KERN_DEBUG " H-display-start  : %d\n", vidc.h_display_start);
+	printk(KERN_DEBUG " H-display-end    : %d\n", vidc.h_display_end);
+	printk(KERN_DEBUG " H-border-end     : %d\n", vidc.h_border_end);
+	printk(KERN_DEBUG " H-interlace      : %d\n", vidc.h_interlace);
+	printk(KERN_DEBUG " V-cycle          : %d\n", vidc.v_cycle);
+	printk(KERN_DEBUG " V-sync-width     : %d\n", vidc.v_sync_width);
+	printk(KERN_DEBUG " V-border-start   : %d\n", vidc.v_border_start);
+	printk(KERN_DEBUG " V-display-start  : %d\n", vidc.v_display_start);
+	printk(KERN_DEBUG " V-display-end    : %d\n", vidc.v_display_end);
+	printk(KERN_DEBUG " V-border-end     : %d\n", vidc.v_border_end);
+	printk(KERN_DEBUG " Ext Ctrl  (C)    : 0x%08X\n", ext_ctl);
+	printk(KERN_DEBUG " PLL Ctrl  (D)    : 0x%08X\n", vidc.pll_ctl);
+	printk(KERN_DEBUG " Ctrl      (E)    : 0x%08X\n", vidc.control);
+	printk(KERN_DEBUG " Data Ctrl (F)    : 0x%08X\n", dat_ctl);
+	printk(KERN_DEBUG " Fsize            : 0x%08X\n", fsize);
+#endif
+}
+
+/*
+ * We have to take note of the VIDC20's 16-bit palette here.
+ * The VIDC20 looks up a 16 bit pixel as follows:
+ *
+ *   bits   111111
+ *          5432109876543210
+ *   red            ++++++++  (8 bits,  7 to 0)
+ *  green       ++++++++      (8 bits, 11 to 4)
+ *   blue   ++++++++          (8 bits, 15 to 8)
+ *
+ * We use a pixel which looks like:
+ *
+ *   bits   111111
+ *          5432109876543210
+ *   red               +++++  (5 bits,  4 to  0)
+ *  green         +++++       (5 bits,  9 to  5)
+ *   blue    +++++            (5 bits, 14 to 10)
+ */
+static int
+acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		  u_int trans, struct fb_info *info)
+{
+	union palette pal;
+
+	if (regno >= current_par.palette_size)
+		return 1;
+
+	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		u32 pseudo_val;
+
+		pseudo_val  = regno << info->var.red.offset;
+		pseudo_val |= regno << info->var.green.offset;
+		pseudo_val |= regno << info->var.blue.offset;
+
+		((u32 *)info->pseudo_palette)[regno] = pseudo_val;
+	}
+
+	pal.p = 0;
+	pal.vidc20.red   = red >> 8;
+	pal.vidc20.green = green >> 8;
+	pal.vidc20.blue  = blue >> 8;
+
+	current_par.palette[regno] = pal;
+
+	if (info->var.bits_per_pixel == 16) {
+		int i;
+
+		pal.p = 0;
+		vidc_writel(0x10000000);
+		for (i = 0; i < 256; i += 1) {
+			pal.vidc20.red   = current_par.palette[ i       & 31].vidc20.red;
+			pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
+			pal.vidc20.blue  = current_par.palette[(i >> 2) & 31].vidc20.blue;
+			vidc_writel(pal.p);
+			/* Palette register pointer auto-increments */
+		}
+	} else {
+		vidc_writel(0x10000000 | regno);
+		vidc_writel(pal.p);
+	}
+
+	return 0;
+}
+#endif
+
+/*
+ * Before selecting the timing parameters, adjust
+ * the resolution to fit the rules.
+ */
+static int
+acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, u_int fontht)
+{
+	u_int font_line_len, sam_size, min_size, size, nr_y;
+
+	/* xres must be even */
+	var->xres = (var->xres + 1) & ~1;
+
+	/*
+	 * We don't allow xres_virtual to differ from xres
+	 */
+	var->xres_virtual = var->xres;
+	var->xoffset = 0;
+
+	if (current_par.using_vram)
+		sam_size = current_par.vram_half_sam * 2;
+	else
+		sam_size = 16;
+
+	/*
+	 * Now, find a value for yres_virtual which allows
+	 * us to do ywrap scrolling.  The value of
+	 * yres_virtual must be such that the end of the
+	 * displayable frame buffer must be aligned with
+	 * the start of a font line.
+	 */
+	font_line_len = var->xres * var->bits_per_pixel * fontht / 8;
+	min_size = var->xres * var->yres * var->bits_per_pixel / 8;
+
+	/*
+	 * If minimum screen size is greater than that we have
+	 * available, reject it.
+	 */
+	if (min_size > info->fix.smem_len)
+		return -EINVAL;
+
+	/* Find int 'y', such that y * fll == s * sam < maxsize
+	 * y = s * sam / fll; s = maxsize / sam
+	 */
+	for (size = info->fix.smem_len;
+	     nr_y = size / font_line_len, min_size <= size;
+	     size -= sam_size) {
+		if (nr_y * font_line_len == size)
+			break;
+	}
+	nr_y *= fontht;
+
+	if (var->accel_flags & FB_ACCELF_TEXT) {
+		if (min_size > size) {
+			/*
+			 * failed, use ypan
+			 */
+			size = info->fix.smem_len;
+			var->yres_virtual = size / (font_line_len / fontht);
+		} else
+			var->yres_virtual = nr_y;
+	} else if (var->yres_virtual > nr_y)
+		var->yres_virtual = nr_y;
+
+	current_par.screen_end = info->fix.smem_start + size;
+
+	/*
+	 * Fix yres & yoffset if needed.
+	 */
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset > var->yres_virtual)
+			var->yoffset = var->yres_virtual;
+	} else {
+		if (var->yoffset + var->yres > var->yres_virtual)
+			var->yoffset = var->yres_virtual - var->yres;
+	}
+
+	/* hsync_len must be even */
+	var->hsync_len = (var->hsync_len + 1) & ~1;
+
+#if defined(HAS_VIDC20)
+	/* left_margin must be even */
+	if (var->left_margin & 1) {
+		var->left_margin += 1;
+		var->right_margin -= 1;
+	}
+
+	/* right_margin must be even */
+	if (var->right_margin & 1)
+		var->right_margin += 1;
+#endif
+
+	if (var->vsync_len < 1)
+		var->vsync_len = 1;
+
+	return 0;
+}
+
+static int
+acornfb_validate_timing(struct fb_var_screeninfo *var,
+			struct fb_monspecs *monspecs)
+{
+	unsigned long hs, vs;
+
+	/*
+	 * hs(Hz) = 10^12 / (pixclock * xtotal)
+	 * vs(Hz) = hs(Hz) / ytotal
+	 *
+	 * No need to do long long divisions or anything
+	 * like that if you factor it correctly
+	 */
+	hs = 1953125000 / var->pixclock;
+	hs = hs * 512 /
+	     (var->xres + var->left_margin + var->right_margin + var->hsync_len);
+	vs = hs /
+	     (var->yres + var->upper_margin + var->lower_margin + var->vsync_len);
+
+	return (vs >= monspecs->vfmin && vs <= monspecs->vfmax &&
+		hs >= monspecs->hfmin && hs <= monspecs->hfmax) ? 0 : -EINVAL;
+}
+
+static inline void
+acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+	u_int off = var->yoffset * info->fix.line_length;
+
+#if defined(HAS_MEMC)
+	memc_write(VDMA_INIT, off >> 2);
+#elif defined(HAS_IOMD)
+	iomd_writel(info->fix.smem_start + off, IOMD_VIDINIT);
+#endif
+}
+
+static int
+acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u_int fontht;
+	int err;
+
+	/*
+	 * FIXME: Find the font height
+	 */
+	fontht = 8;
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	switch (var->bits_per_pixel) {
+	case 1:	case 2:	case 4:	case 8:
+		var->red.offset    = 0;
+		var->red.length    = var->bits_per_pixel;
+		var->green         = var->red;
+		var->blue          = var->red;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+
+#ifdef HAS_VIDC20
+	case 16:
+		var->red.offset    = 0;
+		var->red.length    = 5;
+		var->green.offset  = 5;
+		var->green.length  = 5;
+		var->blue.offset   = 10;
+		var->blue.length   = 5;
+		var->transp.offset = 15;
+		var->transp.length = 1;
+		break;
+
+	case 32:
+		var->red.offset    = 0;
+		var->red.length    = 8;
+		var->green.offset  = 8;
+		var->green.length  = 8;
+		var->blue.offset   = 16;
+		var->blue.length   = 8;
+		var->transp.offset = 24;
+		var->transp.length = 4;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Check to see if the pixel rate is valid.
+	 */
+	if (!acornfb_valid_pixrate(var))
+		return -EINVAL;
+
+	/*
+	 * Validate and adjust the resolution to
+	 * match the video generator hardware.
+	 */
+	err = acornfb_adjust_timing(info, var, fontht);
+	if (err)
+		return err;
+
+	/*
+	 * Validate the timing against the
+	 * monitor hardware.
+	 */
+	return acornfb_validate_timing(var, &info->monspecs);
+}
+
+static int acornfb_set_par(struct fb_info *info)
+{
+	switch (info->var.bits_per_pixel) {
+	case 1:
+		current_par.palette_size = 2;
+		info->fix.visual = FB_VISUAL_MONO10;
+		break;
+	case 2:
+		current_par.palette_size = 4;
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 4:
+		current_par.palette_size = 16;
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 8:
+		current_par.palette_size = VIDC_PALETTE_SIZE;
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+#ifdef HAS_VIDC20
+	case 16:
+		current_par.palette_size = 32;
+		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+	case 32:
+		current_par.palette_size = VIDC_PALETTE_SIZE;
+		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+#endif
+	default:
+		BUG();
+	}
+
+	info->fix.line_length	= (info->var.xres * info->var.bits_per_pixel) / 8;
+
+#if defined(HAS_MEMC)
+	{
+		unsigned long size = info->fix.smem_len - VDMA_XFERSIZE;
+
+		memc_write(VDMA_START, 0);
+		memc_write(VDMA_END, size >> 2);
+	}
+#elif defined(HAS_IOMD)
+	{
+		unsigned long start, size;
+		u_int control;
+
+		start = info->fix.smem_start;
+		size  = current_par.screen_end;
+
+		if (current_par.using_vram) {
+			size -= current_par.vram_half_sam;
+			control = DMA_CR_E | (current_par.vram_half_sam / 256);
+		} else {
+			size -= 16;
+			control = DMA_CR_E | DMA_CR_D | 16;
+		}
+
+		iomd_writel(start,   IOMD_VIDSTART);
+		iomd_writel(size,    IOMD_VIDEND);
+		iomd_writel(control, IOMD_VIDCR);
+	}
+#endif
+
+	acornfb_update_dma(info, &info->var);
+	acornfb_set_timing(info);
+
+	return 0;
+}
+
+static int
+acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u_int y_bottom = var->yoffset;
+
+	if (!(var->vmode & FB_VMODE_YWRAP))
+		y_bottom += info->var.yres;
+
+	if (y_bottom > info->var.yres_virtual)
+		return -EINVAL;
+
+	acornfb_update_dma(info, var);
+
+	return 0;
+}
+
+static struct fb_ops acornfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= acornfb_check_var,
+	.fb_set_par	= acornfb_set_par,
+	.fb_setcolreg	= acornfb_setcolreg,
+	.fb_pan_display	= acornfb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/*
+ * Everything after here is initialisation!!!
+ */
+static struct fb_videomode modedb[] = {
+	{	/* 320x256 @ 50Hz */
+		NULL, 50,  320,  256, 125000,  92,  62,  35, 19,  38, 2,
+		FB_SYNC_COMP_HIGH_ACT,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x250 @ 50Hz, 15.6 kHz hsync */
+		NULL, 50,  640,  250,  62500, 185, 123,  38, 21,  76, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x256 @ 50Hz, 15.6 kHz hsync */
+		NULL, 50,  640,  256,  62500, 185, 123,  35, 18,  76, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x512 @ 50Hz, 26.8 kHz hsync */
+		NULL, 50,  640,  512,  41667, 113,  87,  18,  1,  56, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x250 @ 70Hz, 31.5 kHz hsync */
+		NULL, 70,  640,  250,  39722,  48,  16, 109, 88,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x256 @ 70Hz, 31.5 kHz hsync */
+		NULL, 70,  640,  256,  39722,  48,  16, 106, 85,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x352 @ 70Hz, 31.5 kHz hsync */
+		NULL, 70,  640,  352,  39722,  48,  16,  58, 37,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 640x480 @ 60Hz, 31.5 kHz hsync */
+		NULL, 60,  640,  480,  39722,  48,  16,  32, 11,  96, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 800x600 @ 56Hz, 35.2 kHz hsync */
+		NULL, 56,  800,  600,  27778, 101,  23,  22,  1, 100, 2,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 896x352 @ 60Hz, 21.8 kHz hsync */
+		NULL, 60,  896,  352,  41667,  59,  27,   9,  0, 118, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 1024x 768 @ 60Hz, 48.4 kHz hsync */
+		NULL, 60, 1024,  768,  15385, 160,  24,  29,  3, 136, 6,
+		0,
+		FB_VMODE_NONINTERLACED
+	}, {	/* 1280x1024 @ 60Hz, 63.8 kHz hsync */
+		NULL, 60, 1280, 1024,   9090, 186,  96,  38,  1, 160, 3,
+		0,
+		FB_VMODE_NONINTERLACED
+	}
+};
+
+static struct fb_videomode acornfb_default_mode = {
+	.name =		NULL,
+	.refresh =	60,
+	.xres =		640,
+	.yres =		480,
+	.pixclock =	39722,
+	.left_margin =	56,
+	.right_margin =	16,
+	.upper_margin =	34,
+	.lower_margin =	9,
+	.hsync_len =	88,
+	.vsync_len =	2,
+	.sync =		0,
+	.vmode =	FB_VMODE_NONINTERLACED
+};
+
+static void acornfb_init_fbinfo(void)
+{
+	static int first = 1;
+
+	if (!first)
+		return;
+	first = 0;
+
+	fb_info.fbops		= &acornfb_ops;
+	fb_info.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	fb_info.pseudo_palette	= current_par.pseudo_palette;
+
+	strcpy(fb_info.fix.id, "Acorn");
+	fb_info.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fb_info.fix.type_aux	= 0;
+	fb_info.fix.xpanstep	= 0;
+	fb_info.fix.ypanstep	= 1;
+	fb_info.fix.ywrapstep	= 1;
+	fb_info.fix.line_length	= 0;
+	fb_info.fix.accel	= FB_ACCEL_NONE;
+
+	/*
+	 * setup initial parameters
+	 */
+	memset(&fb_info.var, 0, sizeof(fb_info.var));
+
+#if defined(HAS_VIDC20)
+	fb_info.var.red.length	   = 8;
+	fb_info.var.transp.length  = 4;
+#endif
+	fb_info.var.green	   = fb_info.var.red;
+	fb_info.var.blue	   = fb_info.var.red;
+	fb_info.var.nonstd	   = 0;
+	fb_info.var.activate	   = FB_ACTIVATE_NOW;
+	fb_info.var.height	   = -1;
+	fb_info.var.width	   = -1;
+	fb_info.var.vmode	   = FB_VMODE_NONINTERLACED;
+	fb_info.var.accel_flags	   = FB_ACCELF_TEXT;
+
+	current_par.dram_size	   = 0;
+	current_par.montype	   = -1;
+	current_par.dpms	   = 0;
+}
+
+/*
+ * setup acornfb options:
+ *
+ *  mon:hmin-hmax:vmin-vmax:dpms:width:height
+ *	Set monitor parameters:
+ *		hmin   = horizontal minimum frequency (Hz)
+ *		hmax   = horizontal maximum frequency (Hz)	(optional)
+ *		vmin   = vertical minimum frequency (Hz)
+ *		vmax   = vertical maximum frequency (Hz)	(optional)
+ *		dpms   = DPMS supported?			(optional)
+ *		width  = width of picture in mm.		(optional)
+ *		height = height of picture in mm.		(optional)
+ *
+ * montype:type
+ *	Set RISC-OS style monitor type:
+ *		0 (or tv)	- TV frequency
+ *		1 (or multi)	- Multi frequency
+ *		2 (or hires)	- Hi-res monochrome
+ *		3 (or vga)	- VGA
+ *		4 (or svga)	- SVGA
+ *		auto, or option missing
+ *				- try hardware detect
+ *
+ * dram:size
+ *	Set the amount of DRAM to use for the frame buffer
+ *	(even if you have VRAM).
+ *	size can optionally be followed by 'M' or 'K' for
+ *	MB or KB respectively.
+ */
+static void acornfb_parse_mon(char *opt)
+{
+	char *p = opt;
+
+	current_par.montype = -2;
+
+	fb_info.monspecs.hfmin = simple_strtoul(p, &p, 0);
+	if (*p == '-')
+		fb_info.monspecs.hfmax = simple_strtoul(p + 1, &p, 0);
+	else
+		fb_info.monspecs.hfmax = fb_info.monspecs.hfmin;
+
+	if (*p != ':')
+		goto bad;
+
+	fb_info.monspecs.vfmin = simple_strtoul(p + 1, &p, 0);
+	if (*p == '-')
+		fb_info.monspecs.vfmax = simple_strtoul(p + 1, &p, 0);
+	else
+		fb_info.monspecs.vfmax = fb_info.monspecs.vfmin;
+
+	if (*p != ':')
+		goto check_values;
+
+	fb_info.monspecs.dpms = simple_strtoul(p + 1, &p, 0);
+
+	if (*p != ':')
+		goto check_values;
+
+	fb_info.var.width = simple_strtoul(p + 1, &p, 0);
+
+	if (*p != ':')
+		goto check_values;
+
+	fb_info.var.height = simple_strtoul(p + 1, NULL, 0);
+
+check_values:
+	if (fb_info.monspecs.hfmax < fb_info.monspecs.hfmin ||
+	    fb_info.monspecs.vfmax < fb_info.monspecs.vfmin)
+		goto bad;
+	return;
+
+bad:
+	printk(KERN_ERR "Acornfb: bad monitor settings: %s\n", opt);
+	current_par.montype = -1;
+}
+
+static void acornfb_parse_montype(char *opt)
+{
+	current_par.montype = -2;
+
+	if (strncmp(opt, "tv", 2) == 0) {
+		opt += 2;
+		current_par.montype = 0;
+	} else if (strncmp(opt, "multi", 5) == 0) {
+		opt += 5;
+		current_par.montype = 1;
+	} else if (strncmp(opt, "hires", 5) == 0) {
+		opt += 5;
+		current_par.montype = 2;
+	} else if (strncmp(opt, "vga", 3) == 0) {
+		opt += 3;
+		current_par.montype = 3;
+	} else if (strncmp(opt, "svga", 4) == 0) {
+		opt += 4;
+		current_par.montype = 4;
+	} else if (strncmp(opt, "auto", 4) == 0) {
+		opt += 4;
+		current_par.montype = -1;
+	} else if (isdigit(*opt))
+		current_par.montype = simple_strtoul(opt, &opt, 0);
+
+	if (current_par.montype == -2 ||
+	    current_par.montype > NR_MONTYPES) {
+		printk(KERN_ERR "acornfb: unknown monitor type: %s\n",
+			opt);
+		current_par.montype = -1;
+	} else
+	if (opt && *opt) {
+		if (strcmp(opt, ",dpms") == 0)
+			current_par.dpms = 1;
+		else
+			printk(KERN_ERR
+			       "acornfb: unknown monitor option: %s\n",
+			       opt);
+	}
+}
+
+static void acornfb_parse_dram(char *opt)
+{
+	unsigned int size;
+
+	size = simple_strtoul(opt, &opt, 0);
+
+	if (opt) {
+		switch (*opt) {
+		case 'M':
+		case 'm':
+			size *= 1024;
+		case 'K':
+		case 'k':
+			size *= 1024;
+		default:
+			break;
+		}
+	}
+
+	current_par.dram_size = size;
+}
+
+static struct options {
+	char *name;
+	void (*parse)(char *opt);
+} opt_table[] = {
+	{ "mon",     acornfb_parse_mon     },
+	{ "montype", acornfb_parse_montype },
+	{ "dram",    acornfb_parse_dram    },
+	{ NULL, NULL }
+};
+
+static int acornfb_setup(char *options)
+{
+	struct options *optp;
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	acornfb_init_fbinfo();
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+
+		for (optp = opt_table; optp->name; optp++) {
+			int optlen;
+
+			optlen = strlen(optp->name);
+
+			if (strncmp(opt, optp->name, optlen) == 0 &&
+			    opt[optlen] == ':') {
+				optp->parse(opt + optlen + 1);
+				break;
+			}
+		}
+
+		if (!optp->name)
+			printk(KERN_ERR "acornfb: unknown parameter: %s\n",
+			       opt);
+	}
+	return 0;
+}
+
+/*
+ * Detect type of monitor connected
+ *  For now, we just assume SVGA
+ */
+static int acornfb_detect_monitortype(void)
+{
+	return 4;
+}
+
+/*
+ * This enables the unused memory to be freed on older Acorn machines.
+ * We are freeing memory on behalf of the architecture initialisation
+ * code here.
+ */
+static inline void
+free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
+{
+	int mb_freed = 0;
+
+	/*
+	 * Align addresses
+	 */
+	virtual_start = PAGE_ALIGN(virtual_start);
+	virtual_end = PAGE_ALIGN(virtual_end);
+
+	while (virtual_start < virtual_end) {
+		struct page *page;
+
+		/*
+		 * Clear page reserved bit,
+		 * set count to 1, and free
+		 * the page.
+		 */
+		page = virt_to_page(virtual_start);
+		__free_reserved_page(page);
+
+		virtual_start += PAGE_SIZE;
+		mb_freed += PAGE_SIZE / 1024;
+	}
+
+	printk("acornfb: freed %dK memory\n", mb_freed);
+}
+
+static int acornfb_probe(struct platform_device *dev)
+{
+	unsigned long size;
+	u_int h_sync, v_sync;
+	int rc, i;
+	char *option = NULL;
+
+	if (fb_get_options("acornfb", &option))
+		return -ENODEV;
+	acornfb_setup(option);
+
+	acornfb_init_fbinfo();
+
+	current_par.dev = &dev->dev;
+
+	if (current_par.montype == -1)
+		current_par.montype = acornfb_detect_monitortype();
+
+	if (current_par.montype == -1 || current_par.montype > NR_MONTYPES)
+		current_par.montype = 4;
+
+	if (current_par.montype >= 0) {
+		fb_info.monspecs = monspecs[current_par.montype];
+		fb_info.monspecs.dpms = current_par.dpms;
+	}
+
+	/*
+	 * Try to select a suitable default mode
+	 */
+	for (i = 0; i < ARRAY_SIZE(modedb); i++) {
+		unsigned long hs;
+
+		hs = modedb[i].refresh *
+		     (modedb[i].yres + modedb[i].upper_margin +
+		      modedb[i].lower_margin + modedb[i].vsync_len);
+		if (modedb[i].xres == DEFAULT_XRES &&
+		    modedb[i].yres == DEFAULT_YRES &&
+		    modedb[i].refresh >= fb_info.monspecs.vfmin &&
+		    modedb[i].refresh <= fb_info.monspecs.vfmax &&
+		    hs                >= fb_info.monspecs.hfmin &&
+		    hs                <= fb_info.monspecs.hfmax) {
+			acornfb_default_mode = modedb[i];
+			break;
+		}
+	}
+
+	fb_info.screen_base    = (char *)SCREEN_BASE;
+	fb_info.fix.smem_start = SCREEN_START;
+	current_par.using_vram = 0;
+
+	/*
+	 * If vram_size is set, we are using VRAM in
+	 * a Risc PC.  However, if the user has specified
+	 * an amount of DRAM then use that instead.
+	 */
+	if (vram_size && !current_par.dram_size) {
+		size = vram_size;
+		current_par.vram_half_sam = vram_size / 1024;
+		current_par.using_vram = 1;
+	} else if (current_par.dram_size)
+		size = current_par.dram_size;
+	else
+		size = MAX_SIZE;
+
+	/*
+	 * Limit maximum screen size.
+	 */
+	if (size > MAX_SIZE)
+		size = MAX_SIZE;
+
+	size = PAGE_ALIGN(size);
+
+#if defined(HAS_VIDC20)
+	if (!current_par.using_vram) {
+		dma_addr_t handle;
+		void *base;
+
+		/*
+		 * RiscPC needs to allocate the DRAM memory
+		 * for the framebuffer if we are not using
+		 * VRAM.
+		 */
+		base = dma_alloc_writecombine(current_par.dev, size, &handle,
+					      GFP_KERNEL);
+		if (base == NULL) {
+			printk(KERN_ERR "acornfb: unable to allocate screen "
+			       "memory\n");
+			return -ENOMEM;
+		}
+
+		fb_info.screen_base = base;
+		fb_info.fix.smem_start = handle;
+	}
+#endif
+	fb_info.fix.smem_len = size;
+	current_par.palette_size   = VIDC_PALETTE_SIZE;
+
+	/*
+	 * Lookup the timing for this resolution.  If we can't
+	 * find it, then we can't restore it if we change
+	 * the resolution, so we disable this feature.
+	 */
+	do {
+		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
+				 ARRAY_SIZE(modedb),
+				 &acornfb_default_mode, DEFAULT_BPP);
+		/*
+		 * If we found an exact match, all ok.
+		 */
+		if (rc == 1)
+			break;
+
+		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
+				  &acornfb_default_mode, DEFAULT_BPP);
+		/*
+		 * If we found an exact match, all ok.
+		 */
+		if (rc == 1)
+			break;
+
+		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
+				 ARRAY_SIZE(modedb),
+				 &acornfb_default_mode, DEFAULT_BPP);
+		if (rc)
+			break;
+
+		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
+				  &acornfb_default_mode, DEFAULT_BPP);
+	} while (0);
+
+	/*
+	 * If we didn't find an exact match, try the
+	 * generic database.
+	 */
+	if (rc == 0) {
+		printk("Acornfb: no valid mode found\n");
+		return -EINVAL;
+	}
+
+	h_sync = 1953125000 / fb_info.var.pixclock;
+	h_sync = h_sync * 512 / (fb_info.var.xres + fb_info.var.left_margin +
+		 fb_info.var.right_margin + fb_info.var.hsync_len);
+	v_sync = h_sync / (fb_info.var.yres + fb_info.var.upper_margin +
+		 fb_info.var.lower_margin + fb_info.var.vsync_len);
+
+	printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, "
+		"%d.%03dkHz, %dHz\n",
+		fb_info.fix.smem_len / 1024,
+		current_par.using_vram ? 'V' : 'D',
+		VIDC_NAME, fb_info.var.xres, fb_info.var.yres,
+		h_sync / 1000, h_sync % 1000, v_sync);
+
+	printk(KERN_INFO "Acornfb: Monitor: %d.%03d-%d.%03dkHz, %d-%dHz%s\n",
+		fb_info.monspecs.hfmin / 1000, fb_info.monspecs.hfmin % 1000,
+		fb_info.monspecs.hfmax / 1000, fb_info.monspecs.hfmax % 1000,
+		fb_info.monspecs.vfmin, fb_info.monspecs.vfmax,
+		fb_info.monspecs.dpms ? ", DPMS" : "");
+
+	if (fb_set_var(&fb_info, &fb_info.var))
+		printk(KERN_ERR "Acornfb: unable to set display parameters\n");
+
+	if (register_framebuffer(&fb_info) < 0)
+		return -EINVAL;
+	return 0;
+}
+
+static struct platform_driver acornfb_driver = {
+	.probe	= acornfb_probe,
+	.driver	= {
+		.name	= "acornfb",
+	},
+};
+
+static int __init acornfb_init(void)
+{
+	return platform_driver_register(&acornfb_driver);
+}
+
+module_init(acornfb_init);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/acornfb.h b/drivers/video/fbdev/acornfb.h
new file mode 100644
index 000000000000..175c8ff3367c
--- /dev/null
+++ b/drivers/video/fbdev/acornfb.h
@@ -0,0 +1,169 @@
+/*
+ *  linux/drivers/video/acornfb.h
+ *
+ *  Copyright (C) 1998,1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Frame buffer code for Acorn platforms
+ */
+#if defined(HAS_VIDC20)
+#include <asm/hardware/iomd.h>
+#define VIDC_PALETTE_SIZE	256
+#define VIDC_NAME		"VIDC20"
+#endif
+
+#define EXTEND8(x) ((x)|(x)<<8)
+#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
+
+struct vidc20_palette {
+	u_int red:8;
+	u_int green:8;
+	u_int blue:8;
+	u_int ext:4;
+	u_int unused:4;
+};
+
+struct vidc_palette {
+	u_int red:4;
+	u_int green:4;
+	u_int blue:4;
+	u_int trans:1;
+	u_int sbz1:13;
+	u_int reg:4;
+	u_int sbz2:2;
+};
+
+union palette {
+	struct vidc20_palette	vidc20;
+	struct vidc_palette	vidc;
+	u_int	p;
+};
+
+struct acornfb_par {
+	struct device	*dev;
+	unsigned long	screen_end;
+	unsigned int	dram_size;
+	unsigned int	vram_half_sam;
+	unsigned int	palette_size;
+	  signed int	montype;
+	unsigned int	using_vram	: 1;
+	unsigned int	dpms		: 1;
+
+	union palette palette[VIDC_PALETTE_SIZE];
+
+	u32		pseudo_palette[16];
+};
+
+struct vidc_timing {
+	u_int	h_cycle;
+	u_int	h_sync_width;
+	u_int	h_border_start;
+	u_int	h_display_start;
+	u_int	h_display_end;
+	u_int	h_border_end;
+	u_int	h_interlace;
+
+	u_int	v_cycle;
+	u_int	v_sync_width;
+	u_int	v_border_start;
+	u_int	v_display_start;
+	u_int	v_display_end;
+	u_int	v_border_end;
+
+	u_int	control;
+
+	/* VIDC20 only */
+	u_int	pll_ctl;
+};
+
+struct modey_params {
+	u_int	y_res;
+	u_int	u_margin;
+	u_int	b_margin;
+	u_int	vsync_len;
+	u_int	vf;
+};
+
+struct modex_params {
+	u_int	x_res;
+	u_int	l_margin;
+	u_int	r_margin;
+	u_int	hsync_len;
+	u_int	clock;
+	u_int	hf;
+	const struct modey_params *modey;
+};
+
+#ifdef HAS_VIDC20
+/*
+ * VIDC20 registers
+ */
+#define VIDC20_CTRL		0xe0000000
+#define VIDC20_CTRL_PIX_VCLK	(0 << 0)
+#define VIDC20_CTRL_PIX_HCLK	(1 << 0)
+#define VIDC20_CTRL_PIX_RCLK	(2 << 0)
+#define VIDC20_CTRL_PIX_CK	(0 << 2)
+#define VIDC20_CTRL_PIX_CK2	(1 << 2)
+#define VIDC20_CTRL_PIX_CK3	(2 << 2)
+#define VIDC20_CTRL_PIX_CK4	(3 << 2)
+#define VIDC20_CTRL_PIX_CK5	(4 << 2)
+#define VIDC20_CTRL_PIX_CK6	(5 << 2)
+#define VIDC20_CTRL_PIX_CK7	(6 << 2)
+#define VIDC20_CTRL_PIX_CK8	(7 << 2)
+#define VIDC20_CTRL_1BPP	(0 << 5)
+#define VIDC20_CTRL_2BPP	(1 << 5)
+#define VIDC20_CTRL_4BPP	(2 << 5)
+#define VIDC20_CTRL_8BPP	(3 << 5)
+#define VIDC20_CTRL_16BPP	(4 << 5)
+#define VIDC20_CTRL_32BPP	(6 << 5)
+#define VIDC20_CTRL_FIFO_NS	(0 << 8)
+#define VIDC20_CTRL_FIFO_4	(1 << 8)
+#define VIDC20_CTRL_FIFO_8	(2 << 8)
+#define VIDC20_CTRL_FIFO_12	(3 << 8)
+#define VIDC20_CTRL_FIFO_16	(4 << 8)
+#define VIDC20_CTRL_FIFO_20	(5 << 8)
+#define VIDC20_CTRL_FIFO_24	(6 << 8)
+#define VIDC20_CTRL_FIFO_28	(7 << 8)
+#define VIDC20_CTRL_INT		(1 << 12)
+#define VIDC20_CTRL_DUP		(1 << 13)
+#define VIDC20_CTRL_PDOWN	(1 << 14)
+
+#define VIDC20_ECTL		0xc0000000
+#define VIDC20_ECTL_REG(x)	((x) & 0xf3)
+#define VIDC20_ECTL_ECK		(1 << 2)
+#define VIDC20_ECTL_REDPED	(1 << 8)
+#define VIDC20_ECTL_GREENPED	(1 << 9)
+#define VIDC20_ECTL_BLUEPED	(1 << 10)
+#define VIDC20_ECTL_DAC		(1 << 12)
+#define VIDC20_ECTL_LCDGS	(1 << 13)
+#define VIDC20_ECTL_HRM		(1 << 14)
+
+#define VIDC20_ECTL_HS_MASK	(3 << 16)
+#define VIDC20_ECTL_HS_HSYNC	(0 << 16)
+#define VIDC20_ECTL_HS_NHSYNC	(1 << 16)
+#define VIDC20_ECTL_HS_CSYNC	(2 << 16)
+#define VIDC20_ECTL_HS_NCSYNC	(3 << 16)
+
+#define VIDC20_ECTL_VS_MASK	(3 << 18)
+#define VIDC20_ECTL_VS_VSYNC	(0 << 18)
+#define VIDC20_ECTL_VS_NVSYNC	(1 << 18)
+#define VIDC20_ECTL_VS_CSYNC	(2 << 18)
+#define VIDC20_ECTL_VS_NCSYNC	(3 << 18)
+
+#define VIDC20_DCTL		0xf0000000
+/* 0-9 = number of words in scanline */
+#define VIDC20_DCTL_SNA		(1 << 12)
+#define VIDC20_DCTL_HDIS	(1 << 13)
+#define VIDC20_DCTL_BUS_NS	(0 << 16)
+#define VIDC20_DCTL_BUS_D31_0	(1 << 16)
+#define VIDC20_DCTL_BUS_D63_32	(2 << 16)
+#define VIDC20_DCTL_BUS_D63_0	(3 << 16)
+#define VIDC20_DCTL_VRAM_DIS	(0 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK	(1 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK2	(2 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK4	(3 << 18)
+
+#endif
diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c
new file mode 100644
index 000000000000..14d6b3793e0a
--- /dev/null
+++ b/drivers/video/fbdev/amba-clcd.c
@@ -0,0 +1,656 @@
+/*
+ *  linux/drivers/video/amba-clcd.c
+ *
+ * Copyright (C) 2001 ARM Limited, by David A Rusling
+ * Updated to 2.5, Deep Blue Solutions Ltd.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ *  ARM PrimeCell PL110 Color LCD Controller
+ */
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/clk.h>
+#include <linux/hardirq.h>
+
+#include <asm/sizes.h>
+
+#define to_clcd(info)	container_of(info, struct clcd_fb, fb)
+
+/* This is limited to 16 characters when displayed by X startup */
+static const char *clcd_name = "CLCD FB";
+
+/*
+ * Unfortunately, the enable/disable functions may be called either from
+ * process or IRQ context, and we _need_ to delay.  This is _not_ good.
+ */
+static inline void clcdfb_sleep(unsigned int ms)
+{
+	if (in_atomic()) {
+		mdelay(ms);
+	} else {
+		msleep(ms);
+	}
+}
+
+static inline void clcdfb_set_start(struct clcd_fb *fb)
+{
+	unsigned long ustart = fb->fb.fix.smem_start;
+	unsigned long lstart;
+
+	ustart += fb->fb.var.yoffset * fb->fb.fix.line_length;
+	lstart = ustart + fb->fb.var.yres * fb->fb.fix.line_length / 2;
+
+	writel(ustart, fb->regs + CLCD_UBAS);
+	writel(lstart, fb->regs + CLCD_LBAS);
+}
+
+static void clcdfb_disable(struct clcd_fb *fb)
+{
+	u32 val;
+
+	if (fb->board->disable)
+		fb->board->disable(fb);
+
+	val = readl(fb->regs + fb->off_cntl);
+	if (val & CNTL_LCDPWR) {
+		val &= ~CNTL_LCDPWR;
+		writel(val, fb->regs + fb->off_cntl);
+
+		clcdfb_sleep(20);
+	}
+	if (val & CNTL_LCDEN) {
+		val &= ~CNTL_LCDEN;
+		writel(val, fb->regs + fb->off_cntl);
+	}
+
+	/*
+	 * Disable CLCD clock source.
+	 */
+	if (fb->clk_enabled) {
+		fb->clk_enabled = false;
+		clk_disable(fb->clk);
+	}
+}
+
+static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
+{
+	/*
+	 * Enable the CLCD clock source.
+	 */
+	if (!fb->clk_enabled) {
+		fb->clk_enabled = true;
+		clk_enable(fb->clk);
+	}
+
+	/*
+	 * Bring up by first enabling..
+	 */
+	cntl |= CNTL_LCDEN;
+	writel(cntl, fb->regs + fb->off_cntl);
+
+	clcdfb_sleep(20);
+
+	/*
+	 * and now apply power.
+	 */
+	cntl |= CNTL_LCDPWR;
+	writel(cntl, fb->regs + fb->off_cntl);
+
+	/*
+	 * finally, enable the interface.
+	 */
+	if (fb->board->enable)
+		fb->board->enable(fb);
+}
+
+static int
+clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+	u32 caps;
+	int ret = 0;
+
+	if (fb->panel->caps && fb->board->caps)
+		caps = fb->panel->caps & fb->board->caps;
+	else {
+		/* Old way of specifying what can be used */
+		caps = fb->panel->cntl & CNTL_BGR ?
+			CLCD_CAP_BGR : CLCD_CAP_RGB;
+		/* But mask out 444 modes as they weren't supported */
+		caps &= ~CLCD_CAP_444;
+	}
+
+	/* Only TFT panels can do RGB888/BGR888 */
+	if (!(fb->panel->cntl & CNTL_LCDTFT))
+		caps &= ~CLCD_CAP_888;
+
+	memset(&var->transp, 0, sizeof(var->transp));
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		/* If we can't do 5551, reject */
+		caps &= CLCD_CAP_5551;
+		if (!caps) {
+			ret = -EINVAL;
+			break;
+		}
+
+		var->red.length		= var->bits_per_pixel;
+		var->red.offset		= 0;
+		var->green.length	= var->bits_per_pixel;
+		var->green.offset	= 0;
+		var->blue.length	= var->bits_per_pixel;
+		var->blue.offset	= 0;
+		break;
+
+	case 16:
+		/* If we can't do 444, 5551 or 565, reject */
+		if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) {
+			ret = -EINVAL;
+			break;
+		}
+
+		/*
+		 * Green length can be 4, 5 or 6 depending whether
+		 * we're operating in 444, 5551 or 565 mode.
+		 */
+		if (var->green.length == 4 && caps & CLCD_CAP_444)
+			caps &= CLCD_CAP_444;
+		if (var->green.length == 5 && caps & CLCD_CAP_5551)
+			caps &= CLCD_CAP_5551;
+		else if (var->green.length == 6 && caps & CLCD_CAP_565)
+			caps &= CLCD_CAP_565;
+		else {
+			/*
+			 * PL110 officially only supports RGB555,
+			 * but may be wired up to allow RGB565.
+			 */
+			if (caps & CLCD_CAP_565) {
+				var->green.length = 6;
+				caps &= CLCD_CAP_565;
+			} else if (caps & CLCD_CAP_5551) {
+				var->green.length = 5;
+				caps &= CLCD_CAP_5551;
+			} else {
+				var->green.length = 4;
+				caps &= CLCD_CAP_444;
+			}
+		}
+
+		if (var->green.length >= 5) {
+			var->red.length = 5;
+			var->blue.length = 5;
+		} else {
+			var->red.length = 4;
+			var->blue.length = 4;
+		}
+		break;
+	case 32:
+		/* If we can't do 888, reject */
+		caps &= CLCD_CAP_888;
+		if (!caps) {
+			ret = -EINVAL;
+			break;
+		}
+
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	/*
+	 * >= 16bpp displays have separate colour component bitfields
+	 * encoded in the pixel data.  Calculate their position from
+	 * the bitfield length defined above.
+	 */
+	if (ret == 0 && var->bits_per_pixel >= 16) {
+		bool bgr, rgb;
+
+		bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
+		rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
+
+		if (!bgr && !rgb)
+			/*
+			 * The requested format was not possible, try just
+			 * our capabilities.  One of BGR or RGB must be
+			 * supported.
+			 */
+			bgr = caps & CLCD_CAP_BGR;
+
+		if (bgr) {
+			var->blue.offset = 0;
+			var->green.offset = var->blue.offset + var->blue.length;
+			var->red.offset = var->green.offset + var->green.length;
+		} else {
+			var->red.offset = 0;
+			var->green.offset = var->red.offset + var->red.length;
+			var->blue.offset = var->green.offset + var->green.length;
+		}
+	}
+
+	return ret;
+}
+
+static int clcdfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+	int ret = -EINVAL;
+
+	if (fb->board->check)
+		ret = fb->board->check(fb, var);
+
+	if (ret == 0 &&
+	    var->xres_virtual * var->bits_per_pixel / 8 *
+	    var->yres_virtual > fb->fb.fix.smem_len)
+		ret = -EINVAL;
+
+	if (ret == 0)
+		ret = clcdfb_set_bitfields(fb, var);
+
+	return ret;
+}
+
+static int clcdfb_set_par(struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+	struct clcd_regs regs;
+
+	fb->fb.fix.line_length = fb->fb.var.xres_virtual *
+				 fb->fb.var.bits_per_pixel / 8;
+
+	if (fb->fb.var.bits_per_pixel <= 8)
+		fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+
+	fb->board->decode(fb, &regs);
+
+	clcdfb_disable(fb);
+
+	writel(regs.tim0, fb->regs + CLCD_TIM0);
+	writel(regs.tim1, fb->regs + CLCD_TIM1);
+	writel(regs.tim2, fb->regs + CLCD_TIM2);
+	writel(regs.tim3, fb->regs + CLCD_TIM3);
+
+	clcdfb_set_start(fb);
+
+	clk_set_rate(fb->clk, (1000000000 / regs.pixclock) * 1000);
+
+	fb->clcd_cntl = regs.cntl;
+
+	clcdfb_enable(fb, regs.cntl);
+
+#ifdef DEBUG
+	printk(KERN_INFO
+	       "CLCD: Registers set to\n"
+	       "  %08x %08x %08x %08x\n"
+	       "  %08x %08x %08x %08x\n",
+		readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
+		readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
+		readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
+		readl(fb->regs + fb->off_ienb), readl(fb->regs + fb->off_cntl));
+#endif
+
+	return 0;
+}
+
+static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
+{
+	unsigned int mask = (1 << bf->length) - 1;
+
+	return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
+/*
+ *  Set a single color register. The values supplied have a 16 bit
+ *  magnitude.  Return != 0 for invalid regno.
+ */
+static int
+clcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+		 unsigned int blue, unsigned int transp, struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+
+	if (regno < 16)
+		fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+				  convert_bitfield(blue, &fb->fb.var.blue) |
+				  convert_bitfield(green, &fb->fb.var.green) |
+				  convert_bitfield(red, &fb->fb.var.red);
+
+	if (fb->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
+		int hw_reg = CLCD_PALETTE + ((regno * 2) & ~3);
+		u32 val, mask, newval;
+
+		newval  = (red >> 11)  & 0x001f;
+		newval |= (green >> 6) & 0x03e0;
+		newval |= (blue >> 1)  & 0x7c00;
+
+		/*
+		 * 3.2.11: if we're configured for big endian
+		 * byte order, the palette entries are swapped.
+		 */
+		if (fb->clcd_cntl & CNTL_BEBO)
+			regno ^= 1;
+
+		if (regno & 1) {
+			newval <<= 16;
+			mask = 0x0000ffff;
+		} else {
+			mask = 0xffff0000;
+		}
+
+		val = readl(fb->regs + hw_reg) & mask;
+		writel(val | newval, fb->regs + hw_reg);
+	}
+
+	return regno > 255;
+}
+
+/*
+ *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+ *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+ *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+ *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+ *  and powerdown modes on hardware that supports disabling hsync/vsync:
+ *    blank_mode == 2: suspend vsync
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ */
+static int clcdfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+
+	if (blank_mode != 0) {
+		clcdfb_disable(fb);
+	} else {
+		clcdfb_enable(fb, fb->clcd_cntl);
+	}
+	return 0;
+}
+
+static int clcdfb_mmap(struct fb_info *info,
+		       struct vm_area_struct *vma)
+{
+	struct clcd_fb *fb = to_clcd(info);
+	unsigned long len, off = vma->vm_pgoff << PAGE_SHIFT;
+	int ret = -EINVAL;
+
+	len = info->fix.smem_len;
+
+	if (off <= len && vma->vm_end - vma->vm_start <= len - off &&
+	    fb->board->mmap)
+		ret = fb->board->mmap(fb, vma);
+
+	return ret;
+}
+
+static struct fb_ops clcdfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= clcdfb_check_var,
+	.fb_set_par	= clcdfb_set_par,
+	.fb_setcolreg	= clcdfb_setcolreg,
+	.fb_blank	= clcdfb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_mmap	= clcdfb_mmap,
+};
+
+static int clcdfb_register(struct clcd_fb *fb)
+{
+	int ret;
+
+	/*
+	 * ARM PL111 always has IENB at 0x1c; it's only PL110
+	 * which is reversed on some platforms.
+	 */
+	if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
+		fb->off_ienb = CLCD_PL111_IENB;
+		fb->off_cntl = CLCD_PL111_CNTL;
+	} else {
+#ifdef CONFIG_ARCH_VERSATILE
+		fb->off_ienb = CLCD_PL111_IENB;
+		fb->off_cntl = CLCD_PL111_CNTL;
+#else
+		fb->off_ienb = CLCD_PL110_IENB;
+		fb->off_cntl = CLCD_PL110_CNTL;
+#endif
+	}
+
+	fb->clk = clk_get(&fb->dev->dev, NULL);
+	if (IS_ERR(fb->clk)) {
+		ret = PTR_ERR(fb->clk);
+		goto out;
+	}
+
+	ret = clk_prepare(fb->clk);
+	if (ret)
+		goto free_clk;
+
+	fb->fb.device		= &fb->dev->dev;
+
+	fb->fb.fix.mmio_start	= fb->dev->res.start;
+	fb->fb.fix.mmio_len	= resource_size(&fb->dev->res);
+
+	fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len);
+	if (!fb->regs) {
+		printk(KERN_ERR "CLCD: unable to remap registers\n");
+		ret = -ENOMEM;
+		goto clk_unprep;
+	}
+
+	fb->fb.fbops		= &clcdfb_ops;
+	fb->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fb->fb.pseudo_palette	= fb->cmap;
+
+	strncpy(fb->fb.fix.id, clcd_name, sizeof(fb->fb.fix.id));
+	fb->fb.fix.type		= FB_TYPE_PACKED_PIXELS;
+	fb->fb.fix.type_aux	= 0;
+	fb->fb.fix.xpanstep	= 0;
+	fb->fb.fix.ypanstep	= 0;
+	fb->fb.fix.ywrapstep	= 0;
+	fb->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fb->fb.var.xres		= fb->panel->mode.xres;
+	fb->fb.var.yres		= fb->panel->mode.yres;
+	fb->fb.var.xres_virtual	= fb->panel->mode.xres;
+	fb->fb.var.yres_virtual	= fb->panel->mode.yres;
+	fb->fb.var.bits_per_pixel = fb->panel->bpp;
+	fb->fb.var.grayscale	= fb->panel->grayscale;
+	fb->fb.var.pixclock	= fb->panel->mode.pixclock;
+	fb->fb.var.left_margin	= fb->panel->mode.left_margin;
+	fb->fb.var.right_margin	= fb->panel->mode.right_margin;
+	fb->fb.var.upper_margin	= fb->panel->mode.upper_margin;
+	fb->fb.var.lower_margin	= fb->panel->mode.lower_margin;
+	fb->fb.var.hsync_len	= fb->panel->mode.hsync_len;
+	fb->fb.var.vsync_len	= fb->panel->mode.vsync_len;
+	fb->fb.var.sync		= fb->panel->mode.sync;
+	fb->fb.var.vmode	= fb->panel->mode.vmode;
+	fb->fb.var.activate	= FB_ACTIVATE_NOW;
+	fb->fb.var.nonstd	= 0;
+	fb->fb.var.height	= fb->panel->height;
+	fb->fb.var.width	= fb->panel->width;
+	fb->fb.var.accel_flags	= 0;
+
+	fb->fb.monspecs.hfmin	= 0;
+	fb->fb.monspecs.hfmax   = 100000;
+	fb->fb.monspecs.vfmin	= 0;
+	fb->fb.monspecs.vfmax	= 400;
+	fb->fb.monspecs.dclkmin = 1000000;
+	fb->fb.monspecs.dclkmax	= 100000000;
+
+	/*
+	 * Make sure that the bitfields are set appropriately.
+	 */
+	clcdfb_set_bitfields(fb, &fb->fb.var);
+
+	/*
+	 * Allocate colourmap.
+	 */
+	ret = fb_alloc_cmap(&fb->fb.cmap, 256, 0);
+	if (ret)
+		goto unmap;
+
+	/*
+	 * Ensure interrupts are disabled.
+	 */
+	writel(0, fb->regs + fb->off_ienb);
+
+	fb_set_var(&fb->fb, &fb->fb.var);
+
+	dev_info(&fb->dev->dev, "%s hardware, %s display\n",
+	         fb->board->name, fb->panel->mode.name);
+
+	ret = register_framebuffer(&fb->fb);
+	if (ret == 0)
+		goto out;
+
+	printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
+
+	fb_dealloc_cmap(&fb->fb.cmap);
+ unmap:
+	iounmap(fb->regs);
+ clk_unprep:
+	clk_unprepare(fb->clk);
+ free_clk:
+	clk_put(fb->clk);
+ out:
+	return ret;
+}
+
+static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
+{
+	struct clcd_board *board = dev_get_platdata(&dev->dev);
+	struct clcd_fb *fb;
+	int ret;
+
+	if (!board)
+		return -EINVAL;
+
+	ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+	if (ret)
+		goto out;
+
+	ret = amba_request_regions(dev, NULL);
+	if (ret) {
+		printk(KERN_ERR "CLCD: unable to reserve regs region\n");
+		goto out;
+	}
+
+	fb = kzalloc(sizeof(struct clcd_fb), GFP_KERNEL);
+	if (!fb) {
+		printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
+		ret = -ENOMEM;
+		goto free_region;
+	}
+
+	fb->dev = dev;
+	fb->board = board;
+
+	dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n",
+		amba_part(dev), amba_rev(dev),
+		(unsigned long long)dev->res.start);
+
+	ret = fb->board->setup(fb);
+	if (ret)
+		goto free_fb;
+
+	ret = clcdfb_register(fb); 
+	if (ret == 0) {
+		amba_set_drvdata(dev, fb);
+		goto out;
+	}
+
+	fb->board->remove(fb);
+ free_fb:
+	kfree(fb);
+ free_region:
+	amba_release_regions(dev);
+ out:
+	return ret;
+}
+
+static int clcdfb_remove(struct amba_device *dev)
+{
+	struct clcd_fb *fb = amba_get_drvdata(dev);
+
+	clcdfb_disable(fb);
+	unregister_framebuffer(&fb->fb);
+	if (fb->fb.cmap.len)
+		fb_dealloc_cmap(&fb->fb.cmap);
+	iounmap(fb->regs);
+	clk_unprepare(fb->clk);
+	clk_put(fb->clk);
+
+	fb->board->remove(fb);
+
+	kfree(fb);
+
+	amba_release_regions(dev);
+
+	return 0;
+}
+
+static struct amba_id clcdfb_id_table[] = {
+	{
+		.id	= 0x00041110,
+		.mask	= 0x000ffffe,
+	},
+	{ 0, 0 },
+};
+
+MODULE_DEVICE_TABLE(amba, clcdfb_id_table);
+
+static struct amba_driver clcd_driver = {
+	.drv 		= {
+		.name	= "clcd-pl11x",
+	},
+	.probe		= clcdfb_probe,
+	.remove		= clcdfb_remove,
+	.id_table	= clcdfb_id_table,
+};
+
+static int __init amba_clcdfb_init(void)
+{
+	if (fb_get_options("ambafb", NULL))
+		return -ENODEV;
+
+	return amba_driver_register(&clcd_driver);
+}
+
+module_init(amba_clcdfb_init);
+
+static void __exit amba_clcdfb_exit(void)
+{
+	amba_driver_unregister(&clcd_driver);
+}
+
+module_exit(amba_clcdfb_exit);
+
+MODULE_DESCRIPTION("ARM PrimeCell PL110 CLCD core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/amifb.c b/drivers/video/fbdev/amifb.c
new file mode 100644
index 000000000000..518f790ef88a
--- /dev/null
+++ b/drivers/video/fbdev/amifb.c
@@ -0,0 +1,3792 @@
+/*
+ * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
+ *
+ *    Copyright (C) 1995-2003 Geert Uytterhoeven
+ *
+ *          with work by Roman Zippel
+ *
+ *
+ * This file is based on the Atari frame buffer device (atafb.c):
+ *
+ *    Copyright (C) 1994 Martin Schaller
+ *                       Roman Hodek
+ *
+ *          with work by Andreas Schwab
+ *                       Guenther Kelleter
+ *
+ * and on the original Amiga console driver (amicon.c):
+ *
+ *    Copyright (C) 1993 Hamish Macdonald
+ *                       Greg Harp
+ *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
+ *
+ *          with work by William Rucklidge (wjr@cs.cornell.edu)
+ *                       Geert Uytterhoeven
+ *                       Jes Sorensen (jds@kom.auc.dk)
+ *
+ *
+ * History:
+ *
+ *   - 24 Jul 96: Copper generates now vblank interrupt and
+ *                VESA Power Saving Protocol is fully implemented
+ *   - 14 Jul 96: Rework and hopefully last ECS bugs fixed
+ *   -  7 Mar 96: Hardware sprite support by Roman Zippel
+ *   - 18 Feb 96: OCS and ECS support by Roman Zippel
+ *                Hardware functions completely rewritten
+ *   -  2 Dec 95: AGA version by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/setup.h>
+
+#include "c2p.h"
+
+
+#define DEBUG
+
+#if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
+#define CONFIG_FB_AMIGA_OCS   /* define at least one fb driver, this will change later */
+#endif
+
+#if !defined(CONFIG_FB_AMIGA_OCS)
+#  define IS_OCS (0)
+#elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
+#  define IS_OCS (chipset == TAG_OCS)
+#else
+#  define CONFIG_FB_AMIGA_OCS_ONLY
+#  define IS_OCS (1)
+#endif
+
+#if !defined(CONFIG_FB_AMIGA_ECS)
+#  define IS_ECS (0)
+#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
+#  define IS_ECS (chipset == TAG_ECS)
+#else
+#  define CONFIG_FB_AMIGA_ECS_ONLY
+#  define IS_ECS (1)
+#endif
+
+#if !defined(CONFIG_FB_AMIGA_AGA)
+#  define IS_AGA (0)
+#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
+#  define IS_AGA (chipset == TAG_AGA)
+#else
+#  define CONFIG_FB_AMIGA_AGA_ONLY
+#  define IS_AGA (1)
+#endif
+
+#ifdef DEBUG
+#  define DPRINTK(fmt, args...)	printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+#else
+#  define DPRINTK(fmt, args...)
+#endif
+
+/*******************************************************************************
+
+
+   Generic video timings
+   ---------------------
+
+   Timings used by the frame buffer interface:
+
+   +----------+---------------------------------------------+----------+-------+
+   |          |                ^                            |          |       |
+   |          |                |upper_margin                |          |       |
+   |          |                v                            |          |       |
+   +----------###############################################----------+-------+
+   |          #                ^                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |   left   #                |                            #  right   | hsync |
+   |  margin  #                |       xres                 #  margin  |  len  |
+   |<-------->#<---------------+--------------------------->#<-------->|<----->|
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |yres                        #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                |                            #          |       |
+   |          #                v                            #          |       |
+   +----------###############################################----------+-------+
+   |          |                ^                            |          |       |
+   |          |                |lower_margin                |          |       |
+   |          |                v                            |          |       |
+   +----------+---------------------------------------------+----------+-------+
+   |          |                ^                            |          |       |
+   |          |                |vsync_len                   |          |       |
+   |          |                v                            |          |       |
+   +----------+---------------------------------------------+----------+-------+
+
+
+   Amiga video timings
+   -------------------
+
+   The Amiga native chipsets uses another timing scheme:
+
+      - hsstrt:   Start of horizontal synchronization pulse
+      - hsstop:   End of horizontal synchronization pulse
+      - htotal:   Last value on the line (i.e. line length = htotal + 1)
+      - vsstrt:   Start of vertical synchronization pulse
+      - vsstop:   End of vertical synchronization pulse
+      - vtotal:   Last line value (i.e. number of lines = vtotal + 1)
+      - hcenter:  Start of vertical retrace for interlace
+
+   You can specify the blanking timings independently. Currently I just set
+   them equal to the respective synchronization values:
+
+      - hbstrt:   Start of horizontal blank
+      - hbstop:   End of horizontal blank
+      - vbstrt:   Start of vertical blank
+      - vbstop:   End of vertical blank
+
+   Horizontal values are in color clock cycles (280 ns), vertical values are in
+   scanlines.
+
+   (0, 0) is somewhere in the upper-left corner :-)
+
+
+   Amiga visible window definitions
+   --------------------------------
+
+   Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
+   make corrections and/or additions.
+
+   Within the above synchronization specifications, the visible window is
+   defined by the following parameters (actual register resolutions may be
+   different; all horizontal values are normalized with respect to the pixel
+   clock):
+
+      - diwstrt_h:   Horizontal start of the visible window
+      - diwstop_h:   Horizontal stop + 1(*) of the visible window
+      - diwstrt_v:   Vertical start of the visible window
+      - diwstop_v:   Vertical stop of the visible window
+      - ddfstrt:     Horizontal start of display DMA
+      - ddfstop:     Horizontal stop of display DMA
+      - hscroll:     Horizontal display output delay
+
+   Sprite positioning:
+
+      - sprstrt_h:   Horizontal start - 4 of sprite
+      - sprstrt_v:   Vertical start of sprite
+
+   (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
+
+   Horizontal values are in dotclock cycles (35 ns), vertical values are in
+   scanlines.
+
+   (0, 0) is somewhere in the upper-left corner :-)
+
+
+   Dependencies (AGA, SHRES (35 ns dotclock))
+   -------------------------------------------
+
+   Since there are much more parameters for the Amiga display than for the
+   frame buffer interface, there must be some dependencies among the Amiga
+   display parameters. Here's what I found out:
+
+      - ddfstrt and ddfstop are best aligned to 64 pixels.
+      - the chipset needs 64 + 4 horizontal pixels after the DMA start before
+	the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
+	to display the first pixel on the line too. Increase diwstrt_h for
+	virtual screen panning.
+      - the display DMA always fetches 64 pixels at a time (fmode = 3).
+      - ddfstop is ddfstrt+#pixels - 64.
+      - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
+	be 1 more than htotal.
+      - hscroll simply adds a delay to the display output. Smooth horizontal
+	panning needs an extra 64 pixels on the left to prefetch the pixels that
+	`fall off' on the left.
+      - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
+	DMA, so it's best to make the DMA start as late as possible.
+      - you really don't want to make ddfstrt < 128, since this will steal DMA
+	cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
+      - I make diwstop_h and diwstop_v as large as possible.
+
+   General dependencies
+   --------------------
+
+      - all values are SHRES pixel (35ns)
+
+		  table 1:fetchstart  table 2:prefetch    table 3:fetchsize
+		  ------------------  ----------------    -----------------
+   Pixclock     # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
+   -------------#------+-----+------#------+-----+------#------+-----+------
+   Bus width 1x #   16 |  32 |  64  #   16 |  32 |  64  #   64 |  64 |  64
+   Bus width 2x #   32 |  64 | 128  #   32 |  64 |  64  #   64 |  64 | 128
+   Bus width 4x #   64 | 128 | 256  #   64 |  64 |  64  #   64 | 128 | 256
+
+      - chipset needs 4 pixels before the first pixel is output
+      - ddfstrt must be aligned to fetchstart (table 1)
+      - chipset needs also prefetch (table 2) to get first pixel data, so
+	ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
+      - for horizontal panning decrease diwstrt_h
+      - the length of a fetchline must be aligned to fetchsize (table 3)
+      - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
+	moved to optimize use of dma (useful for OCS/ECS overscan displays)
+      - ddfstop is ddfstrt + ddfsize - fetchsize
+      - If C= didn't change anything for AGA, then at following positions the
+	dma bus is already used:
+	ddfstrt <  48 -> memory refresh
+		<  96 -> disk dma
+		< 160 -> audio dma
+		< 192 -> sprite 0 dma
+		< 416 -> sprite dma (32 per sprite)
+      - in accordance with the hardware reference manual a hardware stop is at
+	192, but AGA (ECS?) can go below this.
+
+   DMA priorities
+   --------------
+
+   Since there are limits on the earliest start value for display DMA and the
+   display of sprites, I use the following policy on horizontal panning and
+   the hardware cursor:
+
+      - if you want to start display DMA too early, you lose the ability to
+	do smooth horizontal panning (xpanstep 1 -> 64).
+      - if you want to go even further, you lose the hardware cursor too.
+
+   IMHO a hardware cursor is more important for X than horizontal scrolling,
+   so that's my motivation.
+
+
+   Implementation
+   --------------
+
+   ami_decode_var() converts the frame buffer values to the Amiga values. It's
+   just a `straightforward' implementation of the above rules.
+
+
+   Standard VGA timings
+   --------------------
+
+	       xres  yres    left  right  upper  lower    hsync    vsync
+	       ----  ----    ----  -----  -----  -----    -----    -----
+      80x25     720   400      27     45     35     12      108        2
+      80x30     720   480      27     45     30      9      108        2
+
+   These were taken from a XFree86 configuration file, recalculated for a 28 MHz
+   dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
+   generic timings.
+
+   As a comparison, graphics/monitor.h suggests the following:
+
+	       xres  yres    left  right  upper  lower    hsync    vsync
+	       ----  ----    ----  -----  -----  -----    -----    -----
+
+      VGA       640   480      52    112     24     19    112 -      2 +
+      VGA70     640   400      52    112     27     21    112 -      2 -
+
+
+   Sync polarities
+   ---------------
+
+      VSYNC    HSYNC    Vertical size    Vertical total
+      -----    -----    -------------    --------------
+	+        +           Reserved          Reserved
+	+        -                400               414
+	-        +                350               362
+	-        -                480               496
+
+   Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
+
+
+   Broadcast video timings
+   -----------------------
+
+   According to the CCIR and RETMA specifications, we have the following values:
+
+   CCIR -> PAL
+   -----------
+
+      - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
+	736 visible 70 ns pixels per line.
+      - we have 625 scanlines, of which 575 are visible (interlaced); after
+	rounding this becomes 576.
+
+   RETMA -> NTSC
+   -------------
+
+      - a scanline is 63.5 µs long, of which 53.5 µs are visible.  This is about
+	736 visible 70 ns pixels per line.
+      - we have 525 scanlines, of which 485 are visible (interlaced); after
+	rounding this becomes 484.
+
+   Thus if you want a PAL compatible display, you have to do the following:
+
+      - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
+	timings are to be used.
+      - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
+	interlaced, 312 for a non-interlaced and 156 for a doublescanned
+	display.
+      - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
+	SHRES, 908 for a HIRES and 454 for a LORES display.
+      - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
+	left_margin + 2 * hsync_len must be greater or equal.
+      - the upper visible part begins at 48 (interlaced; non-interlaced:24,
+	doublescanned:12), upper_margin + 2 * vsync_len must be greater or
+	equal.
+      - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
+	of 4 scanlines
+
+   The settings for a NTSC compatible display are straightforward.
+
+   Note that in a strict sense the PAL and NTSC standards only define the
+   encoding of the color part (chrominance) of the video signal and don't say
+   anything about horizontal/vertical synchronization nor refresh rates.
+
+
+							    -- Geert --
+
+*******************************************************************************/
+
+
+	/*
+	 * Custom Chipset Definitions
+	 */
+
+#define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
+
+	/*
+	 * BPLCON0 -- Bitplane Control Register 0
+	 */
+
+#define BPC0_HIRES	(0x8000)
+#define BPC0_BPU2	(0x4000) /* Bit plane used count */
+#define BPC0_BPU1	(0x2000)
+#define BPC0_BPU0	(0x1000)
+#define BPC0_HAM	(0x0800) /* HAM mode */
+#define BPC0_DPF	(0x0400) /* Double playfield */
+#define BPC0_COLOR	(0x0200) /* Enable colorburst */
+#define BPC0_GAUD	(0x0100) /* Genlock audio enable */
+#define BPC0_UHRES	(0x0080) /* Ultrahi res enable */
+#define BPC0_SHRES	(0x0040) /* Super hi res mode */
+#define BPC0_BYPASS	(0x0020) /* Bypass LUT - AGA */
+#define BPC0_BPU3	(0x0010) /* AGA */
+#define BPC0_LPEN	(0x0008) /* Light pen enable */
+#define BPC0_LACE	(0x0004) /* Interlace */
+#define BPC0_ERSY	(0x0002) /* External resync */
+#define BPC0_ECSENA	(0x0001) /* ECS enable */
+
+	/*
+	 * BPLCON2 -- Bitplane Control Register 2
+	 */
+
+#define BPC2_ZDBPSEL2	(0x4000) /* Bitplane to be used for ZD - AGA */
+#define BPC2_ZDBPSEL1	(0x2000)
+#define BPC2_ZDBPSEL0	(0x1000)
+#define BPC2_ZDBPEN	(0x0800) /* Enable ZD with ZDBPSELx - AGA */
+#define BPC2_ZDCTEN	(0x0400) /* Enable ZD with palette bit #31 - AGA */
+#define BPC2_KILLEHB	(0x0200) /* Kill EHB mode - AGA */
+#define BPC2_RDRAM	(0x0100) /* Color table accesses read, not write - AGA */
+#define BPC2_SOGEN	(0x0080) /* SOG output pin high - AGA */
+#define BPC2_PF2PRI	(0x0040) /* PF2 priority over PF1 */
+#define BPC2_PF2P2	(0x0020) /* PF2 priority wrt sprites */
+#define BPC2_PF2P1	(0x0010)
+#define BPC2_PF2P0	(0x0008)
+#define BPC2_PF1P2	(0x0004) /* ditto PF1 */
+#define BPC2_PF1P1	(0x0002)
+#define BPC2_PF1P0	(0x0001)
+
+	/*
+	 * BPLCON3 -- Bitplane Control Register 3 (AGA)
+	 */
+
+#define BPC3_BANK2	(0x8000) /* Bits to select color register bank */
+#define BPC3_BANK1	(0x4000)
+#define BPC3_BANK0	(0x2000)
+#define BPC3_PF2OF2	(0x1000) /* Bits for color table offset when PF2 */
+#define BPC3_PF2OF1	(0x0800)
+#define BPC3_PF2OF0	(0x0400)
+#define BPC3_LOCT	(0x0200) /* Color register writes go to low bits */
+#define BPC3_SPRES1	(0x0080) /* Sprite resolution bits */
+#define BPC3_SPRES0	(0x0040)
+#define BPC3_BRDRBLNK	(0x0020) /* Border blanked? */
+#define BPC3_BRDRTRAN	(0x0010) /* Border transparent? */
+#define BPC3_ZDCLKEN	(0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
+#define BPC3_BRDRSPRT	(0x0002) /* Sprites in border? */
+#define BPC3_EXTBLKEN	(0x0001) /* BLANK programmable */
+
+	/*
+	 * BPLCON4 -- Bitplane Control Register 4 (AGA)
+	 */
+
+#define BPC4_BPLAM7	(0x8000) /* bitplane color XOR field */
+#define BPC4_BPLAM6	(0x4000)
+#define BPC4_BPLAM5	(0x2000)
+#define BPC4_BPLAM4	(0x1000)
+#define BPC4_BPLAM3	(0x0800)
+#define BPC4_BPLAM2	(0x0400)
+#define BPC4_BPLAM1	(0x0200)
+#define BPC4_BPLAM0	(0x0100)
+#define BPC4_ESPRM7	(0x0080) /* 4 high bits for even sprite colors */
+#define BPC4_ESPRM6	(0x0040)
+#define BPC4_ESPRM5	(0x0020)
+#define BPC4_ESPRM4	(0x0010)
+#define BPC4_OSPRM7	(0x0008) /* 4 high bits for odd sprite colors */
+#define BPC4_OSPRM6	(0x0004)
+#define BPC4_OSPRM5	(0x0002)
+#define BPC4_OSPRM4	(0x0001)
+
+	/*
+	 * BEAMCON0 -- Beam Control Register
+	 */
+
+#define BMC0_HARDDIS	(0x4000) /* Disable hardware limits */
+#define BMC0_LPENDIS	(0x2000) /* Disable light pen latch */
+#define BMC0_VARVBEN	(0x1000) /* Enable variable vertical blank */
+#define BMC0_LOLDIS	(0x0800) /* Disable long/short line toggle */
+#define BMC0_CSCBEN	(0x0400) /* Composite sync/blank */
+#define BMC0_VARVSYEN	(0x0200) /* Enable variable vertical sync */
+#define BMC0_VARHSYEN	(0x0100) /* Enable variable horizontal sync */
+#define BMC0_VARBEAMEN	(0x0080) /* Enable variable beam counters */
+#define BMC0_DUAL	(0x0040) /* Enable alternate horizontal beam counter */
+#define BMC0_PAL	(0x0020) /* Set decodes for PAL */
+#define BMC0_VARCSYEN	(0x0010) /* Enable variable composite sync */
+#define BMC0_BLANKEN	(0x0008) /* Blank enable (no longer used on AGA) */
+#define BMC0_CSYTRUE	(0x0004) /* CSY polarity */
+#define BMC0_VSYTRUE	(0x0002) /* VSY polarity */
+#define BMC0_HSYTRUE	(0x0001) /* HSY polarity */
+
+
+	/*
+	 * FMODE -- Fetch Mode Control Register (AGA)
+	 */
+
+#define FMODE_SSCAN2	(0x8000) /* Sprite scan-doubling */
+#define FMODE_BSCAN2	(0x4000) /* Use PF2 modulus every other line */
+#define FMODE_SPAGEM	(0x0008) /* Sprite page mode */
+#define FMODE_SPR32	(0x0004) /* Sprite 32 bit fetch */
+#define FMODE_BPAGEM	(0x0002) /* Bitplane page mode */
+#define FMODE_BPL32	(0x0001) /* Bitplane 32 bit fetch */
+
+	/*
+	 * Tags used to indicate a specific Pixel Clock
+	 *
+	 * clk_shift is the shift value to get the timings in 35 ns units
+	 */
+
+enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
+
+	/*
+	 * Tags used to indicate the specific chipset
+	 */
+
+enum { TAG_OCS, TAG_ECS, TAG_AGA };
+
+	/*
+	 * Tags used to indicate the memory bandwidth
+	 */
+
+enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
+
+
+	/*
+	 * Clock Definitions, Maximum Display Depth
+	 *
+	 * These depend on the E-Clock or the Chipset, so they are filled in
+	 * dynamically
+	 */
+
+static u_long pixclock[3];	/* SHRES/HIRES/LORES: index = clk_shift */
+static u_short maxdepth[3];	/* SHRES/HIRES/LORES: index = clk_shift */
+static u_short maxfmode, chipset;
+
+
+	/*
+	 * Broadcast Video Timings
+	 *
+	 * Horizontal values are in 35 ns (SHRES) units
+	 * Vertical values are in interlaced scanlines
+	 */
+
+#define PAL_DIWSTRT_H	(360)	/* PAL Window Limits */
+#define PAL_DIWSTRT_V	(48)
+#define PAL_HTOTAL	(1816)
+#define PAL_VTOTAL	(625)
+
+#define NTSC_DIWSTRT_H	(360)	/* NTSC Window Limits */
+#define NTSC_DIWSTRT_V	(40)
+#define NTSC_HTOTAL	(1816)
+#define NTSC_VTOTAL	(525)
+
+
+	/*
+	 * Various macros
+	 */
+
+#define up2(v)		(((v) + 1) & -2)
+#define down2(v)	((v) & -2)
+#define div2(v)		((v)>>1)
+#define mod2(v)		((v) & 1)
+
+#define up4(v)		(((v) + 3) & -4)
+#define down4(v)	((v) & -4)
+#define mul4(v)		((v) << 2)
+#define div4(v)		((v)>>2)
+#define mod4(v)		((v) & 3)
+
+#define up8(v)		(((v) + 7) & -8)
+#define down8(v)	((v) & -8)
+#define div8(v)		((v)>>3)
+#define mod8(v)		((v) & 7)
+
+#define up16(v)		(((v) + 15) & -16)
+#define down16(v)	((v) & -16)
+#define div16(v)	((v)>>4)
+#define mod16(v)	((v) & 15)
+
+#define up32(v)		(((v) + 31) & -32)
+#define down32(v)	((v) & -32)
+#define div32(v)	((v)>>5)
+#define mod32(v)	((v) & 31)
+
+#define up64(v)		(((v) + 63) & -64)
+#define down64(v)	((v) & -64)
+#define div64(v)	((v)>>6)
+#define mod64(v)	((v) & 63)
+
+#define upx(x, v)	(((v) + (x) - 1) & -(x))
+#define downx(x, v)	((v) & -(x))
+#define modx(x, v)	((v) & ((x) - 1))
+
+/* if x1 is not a constant, this macro won't make real sense :-) */
+#ifdef __mc68000__
+#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
+	"d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
+#else
+/* We know a bit about the numbers, so we can do it this way */
+#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
+	((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
+#endif
+
+#define highw(x)	((u_long)(x)>>16 & 0xffff)
+#define loww(x)		((u_long)(x) & 0xffff)
+
+#define custom		amiga_custom
+
+#define VBlankOn()	custom.intena = IF_SETCLR|IF_COPER
+#define VBlankOff()	custom.intena = IF_COPER
+
+
+	/*
+	 * Chip RAM we reserve for the Frame Buffer
+	 *
+	 * This defines the Maximum Virtual Screen Size
+	 * (Setable per kernel options?)
+	 */
+
+#define VIDEOMEMSIZE_AGA_2M	(1310720) /* AGA (2MB) : max 1280*1024*256  */
+#define VIDEOMEMSIZE_AGA_1M	(786432)  /* AGA (1MB) : max 1024*768*256   */
+#define VIDEOMEMSIZE_ECS_2M	(655360)  /* ECS (2MB) : max 1280*1024*16   */
+#define VIDEOMEMSIZE_ECS_1M	(393216)  /* ECS (1MB) : max 1024*768*16    */
+#define VIDEOMEMSIZE_OCS	(262144)  /* OCS       : max ca. 800*600*16 */
+
+#define SPRITEMEMSIZE		(64 * 64 / 4) /* max 64*64*4 */
+#define DUMMYSPRITEMEMSIZE	(8)
+static u_long spritememory;
+
+#define CHIPRAM_SAFETY_LIMIT	(16384)
+
+static u_long videomemory;
+
+	/*
+	 * This is the earliest allowed start of fetching display data.
+	 * Only if you really want no hardware cursor and audio,
+	 * set this to 128, but let it better at 192
+	 */
+
+static u_long min_fstrt = 192;
+
+#define assignchunk(name, type, ptr, size) \
+{ \
+	(name) = (type)(ptr); \
+	ptr += size; \
+}
+
+
+	/*
+	 * Copper Instructions
+	 */
+
+#define CMOVE(val, reg)		(CUSTOM_OFS(reg) << 16 | (val))
+#define CMOVE2(val, reg)	((CUSTOM_OFS(reg) + 2) << 16 | (val))
+#define CWAIT(x, y)		(((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
+#define CEND			(0xfffffffe)
+
+
+typedef union {
+	u_long l;
+	u_short w[2];
+} copins;
+
+static struct copdisplay {
+	copins *init;
+	copins *wait;
+	copins *list[2][2];
+	copins *rebuild[2];
+} copdisplay;
+
+static u_short currentcop = 0;
+
+	/*
+	 * Hardware Cursor API Definitions
+	 * These used to be in linux/fb.h, but were preliminary and used by
+	 * amifb only anyway
+	 */
+
+#define FBIOGET_FCURSORINFO     0x4607
+#define FBIOGET_VCURSORINFO     0x4608
+#define FBIOPUT_VCURSORINFO     0x4609
+#define FBIOGET_CURSORSTATE     0x460A
+#define FBIOPUT_CURSORSTATE     0x460B
+
+
+struct fb_fix_cursorinfo {
+	__u16 crsr_width;		/* width and height of the cursor in */
+	__u16 crsr_height;		/* pixels (zero if no cursor)	*/
+	__u16 crsr_xsize;		/* cursor size in display pixels */
+	__u16 crsr_ysize;
+	__u16 crsr_color1;		/* colormap entry for cursor color1 */
+	__u16 crsr_color2;		/* colormap entry for cursor color2 */
+};
+
+struct fb_var_cursorinfo {
+	__u16 width;
+	__u16 height;
+	__u16 xspot;
+	__u16 yspot;
+	__u8 data[1];			/* field with [height][width]        */
+};
+
+struct fb_cursorstate {
+	__s16 xoffset;
+	__s16 yoffset;
+	__u16 mode;
+};
+
+#define FB_CURSOR_OFF		0
+#define FB_CURSOR_ON		1
+#define FB_CURSOR_FLASH		2
+
+
+	/*
+	 * Hardware Cursor
+	 */
+
+static int cursorrate = 20;	/* Number of frames/flash toggle */
+static u_short cursorstate = -1;
+static u_short cursormode = FB_CURSOR_OFF;
+
+static u_short *lofsprite, *shfsprite, *dummysprite;
+
+	/*
+	 * Current Video Mode
+	 */
+
+struct amifb_par {
+
+	/* General Values */
+
+	int xres;		/* vmode */
+	int yres;		/* vmode */
+	int vxres;		/* vmode */
+	int vyres;		/* vmode */
+	int xoffset;		/* vmode */
+	int yoffset;		/* vmode */
+	u_short bpp;		/* vmode */
+	u_short clk_shift;	/* vmode */
+	u_short line_shift;	/* vmode */
+	int vmode;		/* vmode */
+	u_short diwstrt_h;	/* vmode */
+	u_short diwstop_h;	/* vmode */
+	u_short diwstrt_v;	/* vmode */
+	u_short diwstop_v;	/* vmode */
+	u_long next_line;	/* modulo for next line */
+	u_long next_plane;	/* modulo for next plane */
+
+	/* Cursor Values */
+
+	struct {
+		short crsr_x;	/* movecursor */
+		short crsr_y;	/* movecursor */
+		short spot_x;
+		short spot_y;
+		u_short height;
+		u_short width;
+		u_short fmode;
+	} crsr;
+
+	/* OCS Hardware Registers */
+
+	u_long bplpt0;		/* vmode, pan (Note: physical address) */
+	u_long bplpt0wrap;	/* vmode, pan (Note: physical address) */
+	u_short ddfstrt;
+	u_short ddfstop;
+	u_short bpl1mod;
+	u_short bpl2mod;
+	u_short bplcon0;	/* vmode */
+	u_short bplcon1;	/* vmode */
+	u_short htotal;		/* vmode */
+	u_short vtotal;		/* vmode */
+
+	/* Additional ECS Hardware Registers */
+
+	u_short bplcon3;	/* vmode */
+	u_short beamcon0;	/* vmode */
+	u_short hsstrt;		/* vmode */
+	u_short hsstop;		/* vmode */
+	u_short hbstrt;		/* vmode */
+	u_short hbstop;		/* vmode */
+	u_short vsstrt;		/* vmode */
+	u_short vsstop;		/* vmode */
+	u_short vbstrt;		/* vmode */
+	u_short vbstop;		/* vmode */
+	u_short hcenter;	/* vmode */
+
+	/* Additional AGA Hardware Registers */
+
+	u_short fmode;		/* vmode */
+};
+
+
+	/*
+	 *  Saved color entry 0 so we can restore it when unblanking
+	 */
+
+static u_char red0, green0, blue0;
+
+
+#if defined(CONFIG_FB_AMIGA_ECS)
+static u_short ecs_palette[32];
+#endif
+
+
+	/*
+	 * Latches for Display Changes during VBlank
+	 */
+
+static u_short do_vmode_full = 0;	/* Change the Video Mode */
+static u_short do_vmode_pan = 0;	/* Update the Video Mode */
+static short do_blank = 0;		/* (Un)Blank the Screen (±1) */
+static u_short do_cursor = 0;		/* Move the Cursor */
+
+
+	/*
+	 * Various Flags
+	 */
+
+static u_short is_blanked = 0;		/* Screen is Blanked */
+static u_short is_lace = 0;		/* Screen is laced */
+
+	/*
+	 * Predefined Video Modes
+	 *
+	 */
+
+static struct fb_videomode ami_modedb[] __initdata = {
+
+	/*
+	 *  AmigaOS Video Modes
+	 *
+	 *  If you change these, make sure to update DEFMODE_* as well!
+	 */
+
+	{
+		/* 640x200, 15 kHz, 60 Hz (NTSC) */
+		"ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
+		FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
+		"ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
+		FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x256, 15 kHz, 50 Hz (PAL) */
+		"pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
+		FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
+		"pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
+		FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x480, 29 kHz, 57 Hz */
+		"multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x960, 29 kHz, 57 Hz interlaced */
+		"multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
+		16,
+		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x200, 15 kHz, 72 Hz */
+		"euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 15 kHz, 72 Hz interlaced */
+		"euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
+		10,
+		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 29 kHz, 68 Hz */
+		"euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x800, 29 kHz, 68 Hz interlaced */
+		"euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
+		16,
+		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 800x300, 23 kHz, 70 Hz */
+		"super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 800x600, 23 kHz, 70 Hz interlaced */
+		"super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
+		14,
+		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x200, 27 kHz, 57 Hz doublescan */
+		"dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
+		0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 27 kHz, 57 Hz */
+		"dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x800, 27 kHz, 57 Hz interlaced */
+		"dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
+		14,
+		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x256, 27 kHz, 47 Hz doublescan */
+		"dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
+		0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
+	}, {
+		/* 640x512, 27 kHz, 47 Hz */
+		"dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x1024, 27 kHz, 47 Hz interlaced */
+		"dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
+		14,
+		0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+	},
+
+	/*
+	 *  VGA Video Modes
+	 */
+
+	{
+		/* 640x480, 31 kHz, 60 Hz (VGA) */
+		"vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 31 kHz, 70 Hz (VGA) */
+		"vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
+		FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
+		FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	},
+
+#if 0
+
+	/*
+	 *  A2024 video modes
+	 *  These modes don't work yet because there's no A2024 driver.
+	 */
+
+	{
+		/* 1024x800, 10 Hz */
+		"a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 1024x800, 15 Hz */
+		"a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}
+#endif
+};
+
+#define NUM_TOTAL_MODES  ARRAY_SIZE(ami_modedb)
+
+static char *mode_option __initdata = NULL;
+static int round_down_bpp = 1;	/* for mode probing */
+
+	/*
+	 * Some default modes
+	 */
+
+
+#define DEFMODE_PAL	    2	/* "pal" for PAL OCS/ECS */
+#define DEFMODE_NTSC	    0	/* "ntsc" for NTSC OCS/ECS */
+#define DEFMODE_AMBER_PAL   3	/* "pal-lace" for flicker fixed PAL (A3000) */
+#define DEFMODE_AMBER_NTSC  1	/* "ntsc-lace" for flicker fixed NTSC (A3000) */
+#define DEFMODE_AGA	    19	/* "vga70" for AGA */
+
+
+static int amifb_ilbm = 0;	/* interleaved or normal bitplanes */
+
+static u32 amifb_hfmin __initdata;	/* monitor hfreq lower limit (Hz) */
+static u32 amifb_hfmax __initdata;	/* monitor hfreq upper limit (Hz) */
+static u16 amifb_vfmin __initdata;	/* monitor vfreq lower limit (Hz) */
+static u16 amifb_vfmax __initdata;	/* monitor vfreq upper limit (Hz) */
+
+
+	/*
+	 * Macros for the conversion from real world values to hardware register
+	 * values
+	 *
+	 * This helps us to keep our attention on the real stuff...
+	 *
+	 * Hardware limits for AGA:
+	 *
+	 *	parameter  min    max  step
+	 *	---------  ---   ----  ----
+	 *	diwstrt_h    0   2047     1
+	 *	diwstrt_v    0   2047     1
+	 *	diwstop_h    0   4095     1
+	 *	diwstop_v    0   4095     1
+	 *
+	 *	ddfstrt      0   2032    16
+	 *	ddfstop      0   2032    16
+	 *
+	 *	htotal       8   2048     8
+	 *	hsstrt       0   2040     8
+	 *	hsstop       0   2040     8
+	 *	vtotal       1   4096     1
+	 *	vsstrt       0   4095     1
+	 *	vsstop       0   4095     1
+	 *	hcenter      0   2040     8
+	 *
+	 *	hbstrt       0   2047     1
+	 *	hbstop       0   2047     1
+	 *	vbstrt       0   4095     1
+	 *	vbstop       0   4095     1
+	 *
+	 * Horizontal values are in 35 ns (SHRES) pixels
+	 * Vertical values are in half scanlines
+	 */
+
+/* bplcon1 (smooth scrolling) */
+
+#define hscroll2hw(hscroll) \
+	(((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
+	 ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
+	 ((hscroll)>>2 & 0x000f))
+
+/* diwstrt/diwstop/diwhigh (visible display window) */
+
+#define diwstrt2hw(diwstrt_h, diwstrt_v) \
+	(((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
+#define diwstop2hw(diwstop_h, diwstop_v) \
+	(((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
+#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
+	(((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
+	 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
+	 ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
+
+/* ddfstrt/ddfstop (display DMA) */
+
+#define ddfstrt2hw(ddfstrt)	div8(ddfstrt)
+#define ddfstop2hw(ddfstop)	div8(ddfstop)
+
+/* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */
+
+#define hsstrt2hw(hsstrt)	(div8(hsstrt))
+#define hsstop2hw(hsstop)	(div8(hsstop))
+#define htotal2hw(htotal)	(div8(htotal) - 1)
+#define vsstrt2hw(vsstrt)	(div2(vsstrt))
+#define vsstop2hw(vsstop)	(div2(vsstop))
+#define vtotal2hw(vtotal)	(div2(vtotal) - 1)
+#define hcenter2hw(htotal)	(div8(htotal))
+
+/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
+
+#define hbstrt2hw(hbstrt)	(((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
+#define hbstop2hw(hbstop)	(((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
+#define vbstrt2hw(vbstrt)	(div2(vbstrt))
+#define vbstop2hw(vbstop)	(div2(vbstop))
+
+/* colour */
+
+#define rgb2hw8_high(red, green, blue) \
+	(((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
+#define rgb2hw8_low(red, green, blue) \
+	(((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
+#define rgb2hw4(red, green, blue) \
+	(((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
+#define rgb2hw2(red, green, blue) \
+	(((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
+
+/* sprpos/sprctl (sprite positioning) */
+
+#define spr2hw_pos(start_v, start_h) \
+	(((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
+#define spr2hw_ctl(start_v, start_h, stop_v) \
+	(((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
+	 ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
+	 ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
+	 ((start_h)>>2 & 0x0001))
+
+/* get current vertical position of beam */
+#define get_vbpos()	((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
+
+	/*
+	 * Copper Initialisation List
+	 */
+
+#define COPINITSIZE (sizeof(copins) * 40)
+
+enum {
+	cip_bplcon0
+};
+
+	/*
+	 * Long Frame/Short Frame Copper List
+	 * Don't change the order, build_copper()/rebuild_copper() rely on this
+	 */
+
+#define COPLISTSIZE (sizeof(copins) * 64)
+
+enum {
+	cop_wait, cop_bplcon0,
+	cop_spr0ptrh, cop_spr0ptrl,
+	cop_diwstrt, cop_diwstop,
+	cop_diwhigh,
+};
+
+	/*
+	 * Pixel modes for Bitplanes and Sprites
+	 */
+
+static u_short bplpixmode[3] = {
+	BPC0_SHRES,			/*  35 ns */
+	BPC0_HIRES,			/*  70 ns */
+	0				/* 140 ns */
+};
+
+static u_short sprpixmode[3] = {
+	BPC3_SPRES1 | BPC3_SPRES0,	/*  35 ns */
+	BPC3_SPRES1,			/*  70 ns */
+	BPC3_SPRES0			/* 140 ns */
+};
+
+	/*
+	 * Fetch modes for Bitplanes and Sprites
+	 */
+
+static u_short bplfetchmode[3] = {
+	0,				/* 1x */
+	FMODE_BPL32,			/* 2x */
+	FMODE_BPAGEM | FMODE_BPL32	/* 4x */
+};
+
+static u_short sprfetchmode[3] = {
+	0,				/* 1x */
+	FMODE_SPR32,			/* 2x */
+	FMODE_SPAGEM | FMODE_SPR32	/* 4x */
+};
+
+
+/* --------------------------- Hardware routines --------------------------- */
+
+	/*
+	 * Get the video params out of `var'. If a value doesn't fit, round
+	 * it up, if it's too big, return -EINVAL.
+	 */
+
+static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
+			  const struct fb_info *info)
+{
+	u_short clk_shift, line_shift;
+	u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
+	u_int htotal, vtotal;
+
+	/*
+	 * Find a matching Pixel Clock
+	 */
+
+	for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
+		if (var->pixclock <= pixclock[clk_shift])
+			break;
+	if (clk_shift > TAG_LORES) {
+		DPRINTK("pixclock too high\n");
+		return -EINVAL;
+	}
+	par->clk_shift = clk_shift;
+
+	/*
+	 * Check the Geometry Values
+	 */
+
+	if ((par->xres = var->xres) < 64)
+		par->xres = 64;
+	if ((par->yres = var->yres) < 64)
+		par->yres = 64;
+	if ((par->vxres = var->xres_virtual) < par->xres)
+		par->vxres = par->xres;
+	if ((par->vyres = var->yres_virtual) < par->yres)
+		par->vyres = par->yres;
+
+	par->bpp = var->bits_per_pixel;
+	if (!var->nonstd) {
+		if (par->bpp < 1)
+			par->bpp = 1;
+		if (par->bpp > maxdepth[clk_shift]) {
+			if (round_down_bpp && maxdepth[clk_shift])
+				par->bpp = maxdepth[clk_shift];
+			else {
+				DPRINTK("invalid bpp\n");
+				return -EINVAL;
+			}
+		}
+	} else if (var->nonstd == FB_NONSTD_HAM) {
+		if (par->bpp < 6)
+			par->bpp = 6;
+		if (par->bpp != 6) {
+			if (par->bpp < 8)
+				par->bpp = 8;
+			if (par->bpp != 8 || !IS_AGA) {
+				DPRINTK("invalid bpp for ham mode\n");
+				return -EINVAL;
+			}
+		}
+	} else {
+		DPRINTK("unknown nonstd mode\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the following
+	 * checks failed and smooth scrolling is not possible
+	 */
+
+	par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
+	switch (par->vmode & FB_VMODE_MASK) {
+	case FB_VMODE_INTERLACED:
+		line_shift = 0;
+		break;
+	case FB_VMODE_NONINTERLACED:
+		line_shift = 1;
+		break;
+	case FB_VMODE_DOUBLE:
+		if (!IS_AGA) {
+			DPRINTK("double mode only possible with aga\n");
+			return -EINVAL;
+		}
+		line_shift = 2;
+		break;
+	default:
+		DPRINTK("unknown video mode\n");
+		return -EINVAL;
+		break;
+	}
+	par->line_shift = line_shift;
+
+	/*
+	 * Vertical and Horizontal Timings
+	 */
+
+	xres_n = par->xres << clk_shift;
+	yres_n = par->yres << line_shift;
+	par->htotal = down8((var->left_margin + par->xres + var->right_margin +
+			     var->hsync_len) << clk_shift);
+	par->vtotal =
+		down2(((var->upper_margin + par->yres + var->lower_margin +
+			var->vsync_len) << line_shift) + 1);
+
+	if (IS_AGA)
+		par->bplcon3 = sprpixmode[clk_shift];
+	else
+		par->bplcon3 = 0;
+	if (var->sync & FB_SYNC_BROADCAST) {
+		par->diwstop_h = par->htotal -
+			((var->right_margin - var->hsync_len) << clk_shift);
+		if (IS_AGA)
+			par->diwstop_h += mod4(var->hsync_len);
+		else
+			par->diwstop_h = down4(par->diwstop_h);
+
+		par->diwstrt_h = par->diwstop_h - xres_n;
+		par->diwstop_v = par->vtotal -
+			((var->lower_margin - var->vsync_len) << line_shift);
+		par->diwstrt_v = par->diwstop_v - yres_n;
+		if (par->diwstop_h >= par->htotal + 8) {
+			DPRINTK("invalid diwstop_h\n");
+			return -EINVAL;
+		}
+		if (par->diwstop_v > par->vtotal) {
+			DPRINTK("invalid diwstop_v\n");
+			return -EINVAL;
+		}
+
+		if (!IS_OCS) {
+			/* Initialize sync with some reasonable values for pwrsave */
+			par->hsstrt = 160;
+			par->hsstop = 320;
+			par->vsstrt = 30;
+			par->vsstop = 34;
+		} else {
+			par->hsstrt = 0;
+			par->hsstop = 0;
+			par->vsstrt = 0;
+			par->vsstop = 0;
+		}
+		if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
+			/* PAL video mode */
+			if (par->htotal != PAL_HTOTAL) {
+				DPRINTK("htotal invalid for pal\n");
+				return -EINVAL;
+			}
+			if (par->diwstrt_h < PAL_DIWSTRT_H) {
+				DPRINTK("diwstrt_h too low for pal\n");
+				return -EINVAL;
+			}
+			if (par->diwstrt_v < PAL_DIWSTRT_V) {
+				DPRINTK("diwstrt_v too low for pal\n");
+				return -EINVAL;
+			}
+			htotal = PAL_HTOTAL>>clk_shift;
+			vtotal = PAL_VTOTAL>>1;
+			if (!IS_OCS) {
+				par->beamcon0 = BMC0_PAL;
+				par->bplcon3 |= BPC3_BRDRBLNK;
+			} else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
+				   AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
+				par->beamcon0 = BMC0_PAL;
+				par->hsstop = 1;
+			} else if (amiga_vblank != 50) {
+				DPRINTK("pal not supported by this chipset\n");
+				return -EINVAL;
+			}
+		} else {
+			/* NTSC video mode
+			 * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
+			 * and NTSC activated, so than better let diwstop_h <= 1812
+			 */
+			if (par->htotal != NTSC_HTOTAL) {
+				DPRINTK("htotal invalid for ntsc\n");
+				return -EINVAL;
+			}
+			if (par->diwstrt_h < NTSC_DIWSTRT_H) {
+				DPRINTK("diwstrt_h too low for ntsc\n");
+				return -EINVAL;
+			}
+			if (par->diwstrt_v < NTSC_DIWSTRT_V) {
+				DPRINTK("diwstrt_v too low for ntsc\n");
+				return -EINVAL;
+			}
+			htotal = NTSC_HTOTAL>>clk_shift;
+			vtotal = NTSC_VTOTAL>>1;
+			if (!IS_OCS) {
+				par->beamcon0 = 0;
+				par->bplcon3 |= BPC3_BRDRBLNK;
+			} else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
+				   AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
+				par->beamcon0 = 0;
+				par->hsstop = 1;
+			} else if (amiga_vblank != 60) {
+				DPRINTK("ntsc not supported by this chipset\n");
+				return -EINVAL;
+			}
+		}
+		if (IS_OCS) {
+			if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
+			    par->diwstrt_v >=  512 || par->diwstop_v <  256) {
+				DPRINTK("invalid position for display on ocs\n");
+				return -EINVAL;
+			}
+		}
+	} else if (!IS_OCS) {
+		/* Programmable video mode */
+		par->hsstrt = var->right_margin << clk_shift;
+		par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
+		par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
+		if (!IS_AGA)
+			par->diwstop_h = down4(par->diwstop_h) - 16;
+		par->diwstrt_h = par->diwstop_h - xres_n;
+		par->hbstop = par->diwstrt_h + 4;
+		par->hbstrt = par->diwstop_h + 4;
+		if (par->hbstrt >= par->htotal + 8)
+			par->hbstrt -= par->htotal;
+		par->hcenter = par->hsstrt + (par->htotal >> 1);
+		par->vsstrt = var->lower_margin << line_shift;
+		par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
+		par->diwstop_v = par->vtotal;
+		if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+			par->diwstop_v -= 2;
+		par->diwstrt_v = par->diwstop_v - yres_n;
+		par->vbstop = par->diwstrt_v - 2;
+		par->vbstrt = par->diwstop_v - 2;
+		if (par->vtotal > 2048) {
+			DPRINTK("vtotal too high\n");
+			return -EINVAL;
+		}
+		if (par->htotal > 2048) {
+			DPRINTK("htotal too high\n");
+			return -EINVAL;
+		}
+		par->bplcon3 |= BPC3_EXTBLKEN;
+		par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
+				BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
+				BMC0_PAL | BMC0_VARCSYEN;
+		if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+			par->beamcon0 |= BMC0_HSYTRUE;
+		if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+			par->beamcon0 |= BMC0_VSYTRUE;
+		if (var->sync & FB_SYNC_COMP_HIGH_ACT)
+			par->beamcon0 |= BMC0_CSYTRUE;
+		htotal = par->htotal>>clk_shift;
+		vtotal = par->vtotal>>1;
+	} else {
+		DPRINTK("only broadcast modes possible for ocs\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Checking the DMA timing
+	 */
+
+	fconst = 16 << maxfmode << clk_shift;
+
+	/*
+	 * smallest window start value without turn off other dma cycles
+	 * than sprite1-7, unless you change min_fstrt
+	 */
+
+
+	fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
+	fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
+	if (fstrt < min_fstrt) {
+		DPRINTK("fetch start too low\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * smallest window start value where smooth scrolling is possible
+	 */
+
+	fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
+		fsize;
+	if (fstrt < min_fstrt)
+		par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+	maxfetchstop = down16(par->htotal - 80);
+
+	fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
+	fsize = upx(fconst, xres_n +
+		    modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
+	if (fstrt + fsize > maxfetchstop)
+		par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+	fsize = upx(fconst, xres_n);
+	if (fstrt + fsize > maxfetchstop) {
+		DPRINTK("fetch stop too high\n");
+		return -EINVAL;
+	}
+
+	if (maxfmode + clk_shift <= 1) {
+		fsize = up64(xres_n + fconst - 1);
+		if (min_fstrt + fsize - 64 > maxfetchstop)
+			par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+		fsize = up64(xres_n);
+		if (min_fstrt + fsize - 64 > maxfetchstop) {
+			DPRINTK("fetch size too high\n");
+			return -EINVAL;
+		}
+
+		fsize -= 64;
+	} else
+		fsize -= fconst;
+
+	/*
+	 * Check if there is enough time to update the bitplane pointers for ywrap
+	 */
+
+	if (par->htotal - fsize - 64 < par->bpp * 64)
+		par->vmode &= ~FB_VMODE_YWRAP;
+
+	/*
+	 * Bitplane calculations and check the Memory Requirements
+	 */
+
+	if (amifb_ilbm) {
+		par->next_plane = div8(upx(16 << maxfmode, par->vxres));
+		par->next_line = par->bpp * par->next_plane;
+		if (par->next_line * par->vyres > info->fix.smem_len) {
+			DPRINTK("too few video mem\n");
+			return -EINVAL;
+		}
+	} else {
+		par->next_line = div8(upx(16 << maxfmode, par->vxres));
+		par->next_plane = par->vyres * par->next_line;
+		if (par->next_plane * par->bpp > info->fix.smem_len) {
+			DPRINTK("too few video mem\n");
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Hardware Register Values
+	 */
+
+	par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
+	if (!IS_OCS)
+		par->bplcon0 |= BPC0_ECSENA;
+	if (par->bpp == 8)
+		par->bplcon0 |= BPC0_BPU3;
+	else
+		par->bplcon0 |= par->bpp << 12;
+	if (var->nonstd == FB_NONSTD_HAM)
+		par->bplcon0 |= BPC0_HAM;
+	if (var->sync & FB_SYNC_EXT)
+		par->bplcon0 |= BPC0_ERSY;
+
+	if (IS_AGA)
+		par->fmode = bplfetchmode[maxfmode];
+
+	switch (par->vmode & FB_VMODE_MASK) {
+	case FB_VMODE_INTERLACED:
+		par->bplcon0 |= BPC0_LACE;
+		break;
+	case FB_VMODE_DOUBLE:
+		if (IS_AGA)
+			par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
+		break;
+	}
+
+	if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
+		par->xoffset = var->xoffset;
+		par->yoffset = var->yoffset;
+		if (par->vmode & FB_VMODE_YWRAP) {
+			if (par->xoffset || par->yoffset < 0 ||
+			    par->yoffset >= par->vyres)
+				par->xoffset = par->yoffset = 0;
+		} else {
+			if (par->xoffset < 0 ||
+			    par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
+			    par->yoffset < 0 || par->yoffset > par->vyres - par->yres)
+				par->xoffset = par->yoffset = 0;
+		}
+	} else
+		par->xoffset = par->yoffset = 0;
+
+	par->crsr.crsr_x = par->crsr.crsr_y = 0;
+	par->crsr.spot_x = par->crsr.spot_y = 0;
+	par->crsr.height = par->crsr.width = 0;
+
+	return 0;
+}
+
+	/*
+	 * Fill the `var' structure based on the values in `par' and maybe
+	 * other values read out of the hardware.
+	 */
+
+static void ami_encode_var(struct fb_var_screeninfo *var,
+			   struct amifb_par *par)
+{
+	u_short clk_shift, line_shift;
+
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+
+	clk_shift = par->clk_shift;
+	line_shift = par->line_shift;
+
+	var->xres = par->xres;
+	var->yres = par->yres;
+	var->xres_virtual = par->vxres;
+	var->yres_virtual = par->vyres;
+	var->xoffset = par->xoffset;
+	var->yoffset = par->yoffset;
+
+	var->bits_per_pixel = par->bpp;
+	var->grayscale = 0;
+
+	var->red.offset = 0;
+	var->red.msb_right = 0;
+	var->red.length = par->bpp;
+	if (par->bplcon0 & BPC0_HAM)
+		var->red.length -= 2;
+	var->blue = var->green = var->red;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+
+	if (par->bplcon0 & BPC0_HAM)
+		var->nonstd = FB_NONSTD_HAM;
+	else
+		var->nonstd = 0;
+	var->activate = 0;
+
+	var->height = -1;
+	var->width = -1;
+
+	var->pixclock = pixclock[clk_shift];
+
+	if (IS_AGA && par->fmode & FMODE_BSCAN2)
+		var->vmode = FB_VMODE_DOUBLE;
+	else if (par->bplcon0 & BPC0_LACE)
+		var->vmode = FB_VMODE_INTERLACED;
+	else
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+	if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
+		var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
+		var->right_margin = par->hsstrt>>clk_shift;
+		var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
+		var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
+		var->lower_margin = par->vsstrt>>line_shift;
+		var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
+		var->sync = 0;
+		if (par->beamcon0 & BMC0_HSYTRUE)
+			var->sync |= FB_SYNC_HOR_HIGH_ACT;
+		if (par->beamcon0 & BMC0_VSYTRUE)
+			var->sync |= FB_SYNC_VERT_HIGH_ACT;
+		if (par->beamcon0 & BMC0_CSYTRUE)
+			var->sync |= FB_SYNC_COMP_HIGH_ACT;
+	} else {
+		var->sync = FB_SYNC_BROADCAST;
+		var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
+		var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
+		var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
+		var->vsync_len = 4>>line_shift;
+		var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
+		var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
+				    var->lower_margin - var->vsync_len;
+	}
+
+	if (par->bplcon0 & BPC0_ERSY)
+		var->sync |= FB_SYNC_EXT;
+	if (par->vmode & FB_VMODE_YWRAP)
+		var->vmode |= FB_VMODE_YWRAP;
+}
+
+
+	/*
+	 * Update hardware
+	 */
+
+static void ami_update_par(struct fb_info *info)
+{
+	struct amifb_par *par = info->par;
+	short clk_shift, vshift, fstrt, fsize, fstop, fconst,  shift, move, mod;
+
+	clk_shift = par->clk_shift;
+
+	if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
+		par->xoffset = upx(16 << maxfmode, par->xoffset);
+
+	fconst = 16 << maxfmode << clk_shift;
+	vshift = modx(16 << maxfmode, par->xoffset);
+	fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
+	fsize = (par->xres + vshift) << clk_shift;
+	shift = modx(fconst, fstrt);
+	move = downx(2 << maxfmode, div8(par->xoffset));
+	if (maxfmode + clk_shift > 1) {
+		fstrt = downx(fconst, fstrt) - 64;
+		fsize = upx(fconst, fsize);
+		fstop = fstrt + fsize - fconst;
+	} else {
+		mod = fstrt = downx(fconst, fstrt) - fconst;
+		fstop = fstrt + upx(fconst, fsize) - 64;
+		fsize = up64(fsize);
+		fstrt = fstop - fsize + 64;
+		if (fstrt < min_fstrt) {
+			fstop += min_fstrt - fstrt;
+			fstrt = min_fstrt;
+		}
+		move = move - div8((mod - fstrt)>>clk_shift);
+	}
+	mod = par->next_line - div8(fsize>>clk_shift);
+	par->ddfstrt = fstrt;
+	par->ddfstop = fstop;
+	par->bplcon1 = hscroll2hw(shift);
+	par->bpl2mod = mod;
+	if (par->bplcon0 & BPC0_LACE)
+		par->bpl2mod += par->next_line;
+	if (IS_AGA && (par->fmode & FMODE_BSCAN2))
+		par->bpl1mod = -div8(fsize>>clk_shift);
+	else
+		par->bpl1mod = par->bpl2mod;
+
+	if (par->yoffset) {
+		par->bplpt0 = info->fix.smem_start +
+			      par->next_line * par->yoffset + move;
+		if (par->vmode & FB_VMODE_YWRAP) {
+			if (par->yoffset > par->vyres - par->yres) {
+				par->bplpt0wrap = info->fix.smem_start + move;
+				if (par->bplcon0 & BPC0_LACE &&
+				    mod2(par->diwstrt_v + par->vyres -
+					 par->yoffset))
+					par->bplpt0wrap += par->next_line;
+			}
+		}
+	} else
+		par->bplpt0 = info->fix.smem_start + move;
+
+	if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
+		par->bplpt0 += par->next_line;
+}
+
+
+	/*
+	 * Pan or Wrap the Display
+	 *
+	 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+	 * in `var'.
+	 */
+
+static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct amifb_par *par = info->par;
+
+	par->xoffset = var->xoffset;
+	par->yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		par->vmode |= FB_VMODE_YWRAP;
+	else
+		par->vmode &= ~FB_VMODE_YWRAP;
+
+	do_vmode_pan = 0;
+	ami_update_par(info);
+	do_vmode_pan = 1;
+}
+
+
+static void ami_update_display(const struct amifb_par *par)
+{
+	custom.bplcon1 = par->bplcon1;
+	custom.bpl1mod = par->bpl1mod;
+	custom.bpl2mod = par->bpl2mod;
+	custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
+	custom.ddfstop = ddfstop2hw(par->ddfstop);
+}
+
+	/*
+	 * Change the video mode (called by VBlank interrupt)
+	 */
+
+static void ami_init_display(const struct amifb_par *par)
+{
+	int i;
+
+	custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
+	custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
+	if (!IS_OCS) {
+		custom.bplcon3 = par->bplcon3;
+		if (IS_AGA)
+			custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
+		if (par->beamcon0 & BMC0_VARBEAMEN) {
+			custom.htotal = htotal2hw(par->htotal);
+			custom.hbstrt = hbstrt2hw(par->hbstrt);
+			custom.hbstop = hbstop2hw(par->hbstop);
+			custom.hsstrt = hsstrt2hw(par->hsstrt);
+			custom.hsstop = hsstop2hw(par->hsstop);
+			custom.hcenter = hcenter2hw(par->hcenter);
+			custom.vtotal = vtotal2hw(par->vtotal);
+			custom.vbstrt = vbstrt2hw(par->vbstrt);
+			custom.vbstop = vbstop2hw(par->vbstop);
+			custom.vsstrt = vsstrt2hw(par->vsstrt);
+			custom.vsstop = vsstop2hw(par->vsstop);
+		}
+	}
+	if (!IS_OCS || par->hsstop)
+		custom.beamcon0 = par->beamcon0;
+	if (IS_AGA)
+		custom.fmode = par->fmode;
+
+	/*
+	 * The minimum period for audio depends on htotal
+	 */
+
+	amiga_audio_min_period = div16(par->htotal);
+
+	is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
+#if 1
+	if (is_lace) {
+		i = custom.vposr >> 15;
+	} else {
+		custom.vposw = custom.vposr | 0x8000;
+		i = 1;
+	}
+#else
+	i = 1;
+	custom.vposw = custom.vposr | 0x8000;
+#endif
+	custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
+}
+
+	/*
+	 * (Un)Blank the screen (called by VBlank interrupt)
+	 */
+
+static void ami_do_blank(const struct amifb_par *par)
+{
+#if defined(CONFIG_FB_AMIGA_AGA)
+	u_short bplcon3 = par->bplcon3;
+#endif
+	u_char red, green, blue;
+
+	if (do_blank > 0) {
+		custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
+		red = green = blue = 0;
+		if (!IS_OCS && do_blank > 1) {
+			switch (do_blank) {
+			case FB_BLANK_VSYNC_SUSPEND:
+				custom.hsstrt = hsstrt2hw(par->hsstrt);
+				custom.hsstop = hsstop2hw(par->hsstop);
+				custom.vsstrt = vsstrt2hw(par->vtotal + 4);
+				custom.vsstop = vsstop2hw(par->vtotal + 4);
+				break;
+			case FB_BLANK_HSYNC_SUSPEND:
+				custom.hsstrt = hsstrt2hw(par->htotal + 16);
+				custom.hsstop = hsstop2hw(par->htotal + 16);
+				custom.vsstrt = vsstrt2hw(par->vsstrt);
+				custom.vsstop = vsstrt2hw(par->vsstop);
+				break;
+			case FB_BLANK_POWERDOWN:
+				custom.hsstrt = hsstrt2hw(par->htotal + 16);
+				custom.hsstop = hsstop2hw(par->htotal + 16);
+				custom.vsstrt = vsstrt2hw(par->vtotal + 4);
+				custom.vsstop = vsstop2hw(par->vtotal + 4);
+				break;
+			}
+			if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
+				custom.htotal = htotal2hw(par->htotal);
+				custom.vtotal = vtotal2hw(par->vtotal);
+				custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
+						  BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
+			}
+		}
+	} else {
+		custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
+		red = red0;
+		green = green0;
+		blue = blue0;
+		if (!IS_OCS) {
+			custom.hsstrt = hsstrt2hw(par->hsstrt);
+			custom.hsstop = hsstop2hw(par->hsstop);
+			custom.vsstrt = vsstrt2hw(par->vsstrt);
+			custom.vsstop = vsstop2hw(par->vsstop);
+			custom.beamcon0 = par->beamcon0;
+		}
+	}
+#if defined(CONFIG_FB_AMIGA_AGA)
+	if (IS_AGA) {
+		custom.bplcon3 = bplcon3;
+		custom.color[0] = rgb2hw8_high(red, green, blue);
+		custom.bplcon3 = bplcon3 | BPC3_LOCT;
+		custom.color[0] = rgb2hw8_low(red, green, blue);
+		custom.bplcon3 = bplcon3;
+	} else
+#endif
+#if defined(CONFIG_FB_AMIGA_ECS)
+	if (par->bplcon0 & BPC0_SHRES) {
+		u_short color, mask;
+		int i;
+
+		mask = 0x3333;
+		color = rgb2hw2(red, green, blue);
+		for (i = 12; i >= 0; i -= 4)
+			custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+		mask <<= 2; color >>= 2;
+		for (i = 3; i >= 0; i--)
+			custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+	} else
+#endif
+		custom.color[0] = rgb2hw4(red, green, blue);
+	is_blanked = do_blank > 0 ? do_blank : 0;
+}
+
+static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
+				  const struct amifb_par *par)
+{
+	fix->crsr_width = fix->crsr_xsize = par->crsr.width;
+	fix->crsr_height = fix->crsr_ysize = par->crsr.height;
+	fix->crsr_color1 = 17;
+	fix->crsr_color2 = 18;
+	return 0;
+}
+
+static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
+				  u_char __user *data,
+				  const struct amifb_par *par)
+{
+	register u_short *lspr, *sspr;
+#ifdef __mc68000__
+	register u_long datawords asm ("d2");
+#else
+	register u_long datawords;
+#endif
+	register short delta;
+	register u_char color;
+	short height, width, bits, words;
+	int size, alloc;
+
+	size = par->crsr.height * par->crsr.width;
+	alloc = var->height * var->width;
+	var->height = par->crsr.height;
+	var->width = par->crsr.width;
+	var->xspot = par->crsr.spot_x;
+	var->yspot = par->crsr.spot_y;
+	if (size > var->height * var->width)
+		return -ENAMETOOLONG;
+	if (!access_ok(VERIFY_WRITE, data, size))
+		return -EFAULT;
+	delta = 1 << par->crsr.fmode;
+	lspr = lofsprite + (delta << 1);
+	if (par->bplcon0 & BPC0_LACE)
+		sspr = shfsprite + (delta << 1);
+	else
+		sspr = NULL;
+	for (height = (short)var->height - 1; height >= 0; height--) {
+		bits = 0; words = delta; datawords = 0;
+		for (width = (short)var->width - 1; width >= 0; width--) {
+			if (bits == 0) {
+				bits = 16; --words;
+#ifdef __mc68000__
+				asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
+					: "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
+#else
+				datawords = (*(lspr + delta) << 16) | (*lspr++);
+#endif
+			}
+			--bits;
+#ifdef __mc68000__
+			asm volatile (
+				"clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
+				"swap %1 ; lslw #1,%1 ; roxlb #1,%0"
+				: "=d" (color), "=d" (datawords) : "1" (datawords));
+#else
+			color = (((datawords >> 30) & 2)
+				 | ((datawords >> 15) & 1));
+			datawords <<= 1;
+#endif
+			put_user(color, data++);
+		}
+		if (bits > 0) {
+			--words; ++lspr;
+		}
+		while (--words >= 0)
+			++lspr;
+#ifdef __mc68000__
+		asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
+			: "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
+#else
+		lspr += delta;
+		if (sspr) {
+			u_short *tmp = lspr;
+			lspr = sspr;
+			sspr = tmp;
+		}
+#endif
+	}
+	return 0;
+}
+
+static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
+				  u_char __user *data, struct amifb_par *par)
+{
+	register u_short *lspr, *sspr;
+#ifdef __mc68000__
+	register u_long datawords asm ("d2");
+#else
+	register u_long datawords;
+#endif
+	register short delta;
+	u_short fmode;
+	short height, width, bits, words;
+
+	if (!var->width)
+		return -EINVAL;
+	else if (var->width <= 16)
+		fmode = TAG_FMODE_1;
+	else if (var->width <= 32)
+		fmode = TAG_FMODE_2;
+	else if (var->width <= 64)
+		fmode = TAG_FMODE_4;
+	else
+		return -EINVAL;
+	if (fmode > maxfmode)
+		return -EINVAL;
+	if (!var->height)
+		return -EINVAL;
+	if (!access_ok(VERIFY_READ, data, var->width * var->height))
+		return -EFAULT;
+	delta = 1 << fmode;
+	lofsprite = shfsprite = (u_short *)spritememory;
+	lspr = lofsprite + (delta << 1);
+	if (par->bplcon0 & BPC0_LACE) {
+		if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
+			return -EINVAL;
+		memset(lspr, 0, (var->height + 4) << fmode << 2);
+		shfsprite += ((var->height + 5)&-2) << fmode;
+		sspr = shfsprite + (delta << 1);
+	} else {
+		if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
+			return -EINVAL;
+		memset(lspr, 0, (var->height + 2) << fmode << 2);
+		sspr = NULL;
+	}
+	for (height = (short)var->height - 1; height >= 0; height--) {
+		bits = 16; words = delta; datawords = 0;
+		for (width = (short)var->width - 1; width >= 0; width--) {
+			unsigned long tdata = 0;
+			get_user(tdata, data);
+			data++;
+#ifdef __mc68000__
+			asm volatile (
+				"lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
+				"lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
+				: "=d" (datawords)
+				: "0" (datawords), "d" (tdata));
+#else
+			datawords = ((datawords << 1) & 0xfffefffe);
+			datawords |= tdata & 1;
+			datawords |= (tdata & 2) << (16 - 1);
+#endif
+			if (--bits == 0) {
+				bits = 16; --words;
+#ifdef __mc68000__
+				asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
+					: "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
+#else
+				*(lspr + delta) = (u_short) (datawords >> 16);
+				*lspr++ = (u_short) (datawords & 0xffff);
+#endif
+			}
+		}
+		if (bits < 16) {
+			--words;
+#ifdef __mc68000__
+			asm volatile (
+				"swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
+				"swap %2 ; lslw %4,%2 ; movew %2,%0@+"
+				: "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
+#else
+			*(lspr + delta) = (u_short) (datawords >> (16 + bits));
+			*lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
+#endif
+		}
+		while (--words >= 0) {
+#ifdef __mc68000__
+			asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
+				: "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
+#else
+			*(lspr + delta) = 0;
+			*lspr++ = 0;
+#endif
+		}
+#ifdef __mc68000__
+		asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
+			: "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
+#else
+		lspr += delta;
+		if (sspr) {
+			u_short *tmp = lspr;
+			lspr = sspr;
+			sspr = tmp;
+		}
+#endif
+	}
+	par->crsr.height = var->height;
+	par->crsr.width = var->width;
+	par->crsr.spot_x = var->xspot;
+	par->crsr.spot_y = var->yspot;
+	par->crsr.fmode = fmode;
+	if (IS_AGA) {
+		par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
+		par->fmode |= sprfetchmode[fmode];
+		custom.fmode = par->fmode;
+	}
+	return 0;
+}
+
+static int ami_get_cursorstate(struct fb_cursorstate *state,
+			       const struct amifb_par *par)
+{
+	state->xoffset = par->crsr.crsr_x;
+	state->yoffset = par->crsr.crsr_y;
+	state->mode = cursormode;
+	return 0;
+}
+
+static int ami_set_cursorstate(struct fb_cursorstate *state,
+			       struct amifb_par *par)
+{
+	par->crsr.crsr_x = state->xoffset;
+	par->crsr.crsr_y = state->yoffset;
+	if ((cursormode = state->mode) == FB_CURSOR_OFF)
+		cursorstate = -1;
+	do_cursor = 1;
+	return 0;
+}
+
+static void ami_set_sprite(const struct amifb_par *par)
+{
+	copins *copl, *cops;
+	u_short hs, vs, ve;
+	u_long pl, ps, pt;
+	short mx, my;
+
+	cops = copdisplay.list[currentcop][0];
+	copl = copdisplay.list[currentcop][1];
+	ps = pl = ZTWO_PADDR(dummysprite);
+	mx = par->crsr.crsr_x - par->crsr.spot_x;
+	my = par->crsr.crsr_y - par->crsr.spot_y;
+	if (!(par->vmode & FB_VMODE_YWRAP)) {
+		mx -= par->xoffset;
+		my -= par->yoffset;
+	}
+	if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
+	    mx > -(short)par->crsr.width && mx < par->xres &&
+	    my > -(short)par->crsr.height && my < par->yres) {
+		pl = ZTWO_PADDR(lofsprite);
+		hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
+		vs = par->diwstrt_v + (my << par->line_shift);
+		ve = vs + (par->crsr.height << par->line_shift);
+		if (par->bplcon0 & BPC0_LACE) {
+			ps = ZTWO_PADDR(shfsprite);
+			lofsprite[0] = spr2hw_pos(vs, hs);
+			shfsprite[0] = spr2hw_pos(vs + 1, hs);
+			if (mod2(vs)) {
+				lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
+				shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
+				pt = pl; pl = ps; ps = pt;
+			} else {
+				lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
+				shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
+			}
+		} else {
+			lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
+			lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
+		}
+	}
+	copl[cop_spr0ptrh].w[1] = highw(pl);
+	copl[cop_spr0ptrl].w[1] = loww(pl);
+	if (par->bplcon0 & BPC0_LACE) {
+		cops[cop_spr0ptrh].w[1] = highw(ps);
+		cops[cop_spr0ptrl].w[1] = loww(ps);
+	}
+}
+
+
+	/*
+	 * Initialise the Copper Initialisation List
+	 */
+
+static void __init ami_init_copper(void)
+{
+	copins *cop = copdisplay.init;
+	u_long p;
+	int i;
+
+	if (!IS_OCS) {
+		(cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
+		(cop++)->l = CMOVE(0x0181, diwstrt);
+		(cop++)->l = CMOVE(0x0281, diwstop);
+		(cop++)->l = CMOVE(0x0000, diwhigh);
+	} else
+		(cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
+	p = ZTWO_PADDR(dummysprite);
+	for (i = 0; i < 8; i++) {
+		(cop++)->l = CMOVE(0, spr[i].pos);
+		(cop++)->l = CMOVE(highw(p), sprpt[i]);
+		(cop++)->l = CMOVE2(loww(p), sprpt[i]);
+	}
+
+	(cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
+	copdisplay.wait = cop;
+	(cop++)->l = CEND;
+	(cop++)->l = CMOVE(0, copjmp2);
+	cop->l = CEND;
+
+	custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
+	custom.copjmp1 = 0;
+}
+
+static void ami_reinit_copper(const struct amifb_par *par)
+{
+	copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
+	copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
+}
+
+
+	/*
+	 * Rebuild the Copper List
+	 *
+	 * We only change the things that are not static
+	 */
+
+static void ami_rebuild_copper(const struct amifb_par *par)
+{
+	copins *copl, *cops;
+	u_short line, h_end1, h_end2;
+	short i;
+	u_long p;
+
+	if (IS_AGA && maxfmode + par->clk_shift == 0)
+		h_end1 = par->diwstrt_h - 64;
+	else
+		h_end1 = par->htotal - 32;
+	h_end2 = par->ddfstop + 64;
+
+	ami_set_sprite(par);
+
+	copl = copdisplay.rebuild[1];
+	p = par->bplpt0;
+	if (par->vmode & FB_VMODE_YWRAP) {
+		if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
+			if (par->yoffset > par->vyres - par->yres) {
+				for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+					(copl++)->l = CMOVE(highw(p), bplpt[i]);
+					(copl++)->l = CMOVE2(loww(p), bplpt[i]);
+				}
+				line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
+				while (line >= 512) {
+					(copl++)->l = CWAIT(h_end1, 510);
+					line -= 512;
+				}
+				if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
+					(copl++)->l = CWAIT(h_end1, line);
+				else
+					(copl++)->l = CWAIT(h_end2, line);
+				p = par->bplpt0wrap;
+			}
+		} else
+			p = par->bplpt0wrap;
+	}
+	for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+		(copl++)->l = CMOVE(highw(p), bplpt[i]);
+		(copl++)->l = CMOVE2(loww(p), bplpt[i]);
+	}
+	copl->l = CEND;
+
+	if (par->bplcon0 & BPC0_LACE) {
+		cops = copdisplay.rebuild[0];
+		p = par->bplpt0;
+		if (mod2(par->diwstrt_v))
+			p -= par->next_line;
+		else
+			p += par->next_line;
+		if (par->vmode & FB_VMODE_YWRAP) {
+			if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
+				if (par->yoffset > par->vyres - par->yres + 1) {
+					for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+						(cops++)->l = CMOVE(highw(p), bplpt[i]);
+						(cops++)->l = CMOVE2(loww(p), bplpt[i]);
+					}
+					line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
+					while (line >= 512) {
+						(cops++)->l = CWAIT(h_end1, 510);
+						line -= 512;
+					}
+					if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
+						(cops++)->l = CWAIT(h_end1, line);
+					else
+						(cops++)->l = CWAIT(h_end2, line);
+					p = par->bplpt0wrap;
+					if (mod2(par->diwstrt_v + par->vyres -
+					    par->yoffset))
+						p -= par->next_line;
+					else
+						p += par->next_line;
+				}
+			} else
+				p = par->bplpt0wrap - par->next_line;
+		}
+		for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+			(cops++)->l = CMOVE(highw(p), bplpt[i]);
+			(cops++)->l = CMOVE2(loww(p), bplpt[i]);
+		}
+		cops->l = CEND;
+	}
+}
+
+
+	/*
+	 * Build the Copper List
+	 */
+
+static void ami_build_copper(struct fb_info *info)
+{
+	struct amifb_par *par = info->par;
+	copins *copl, *cops;
+	u_long p;
+
+	currentcop = 1 - currentcop;
+
+	copl = copdisplay.list[currentcop][1];
+
+	(copl++)->l = CWAIT(0, 10);
+	(copl++)->l = CMOVE(par->bplcon0, bplcon0);
+	(copl++)->l = CMOVE(0, sprpt[0]);
+	(copl++)->l = CMOVE2(0, sprpt[0]);
+
+	if (par->bplcon0 & BPC0_LACE) {
+		cops = copdisplay.list[currentcop][0];
+
+		(cops++)->l = CWAIT(0, 10);
+		(cops++)->l = CMOVE(par->bplcon0, bplcon0);
+		(cops++)->l = CMOVE(0, sprpt[0]);
+		(cops++)->l = CMOVE2(0, sprpt[0]);
+
+		(copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
+		(copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
+		(cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
+		(cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
+		if (!IS_OCS) {
+			(copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
+					    par->diwstop_h, par->diwstop_v + 1), diwhigh);
+			(cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
+					    par->diwstop_h, par->diwstop_v), diwhigh);
+#if 0
+			if (par->beamcon0 & BMC0_VARBEAMEN) {
+				(copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
+				(copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
+				(copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
+				(cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
+				(cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
+				(cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
+			}
+#endif
+		}
+		p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
+		(copl++)->l = CMOVE(highw(p), cop2lc);
+		(copl++)->l = CMOVE2(loww(p), cop2lc);
+		p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
+		(cops++)->l = CMOVE(highw(p), cop2lc);
+		(cops++)->l = CMOVE2(loww(p), cop2lc);
+		copdisplay.rebuild[0] = cops;
+	} else {
+		(copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
+		(copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
+		if (!IS_OCS) {
+			(copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
+					    par->diwstop_h, par->diwstop_v), diwhigh);
+#if 0
+			if (par->beamcon0 & BMC0_VARBEAMEN) {
+				(copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
+				(copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
+				(copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
+			}
+#endif
+		}
+	}
+	copdisplay.rebuild[1] = copl;
+
+	ami_update_par(info);
+	ami_rebuild_copper(info->par);
+}
+
+
+static void __init amifb_setup_mcap(char *spec)
+{
+	char *p;
+	int vmin, vmax, hmin, hmax;
+
+	/* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
+	 * <V*> vertical freq. in Hz
+	 * <H*> horizontal freq. in kHz
+	 */
+
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	vmin = simple_strtoul(p, NULL, 10);
+	if (vmin <= 0)
+		return;
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	vmax = simple_strtoul(p, NULL, 10);
+	if (vmax <= 0 || vmax <= vmin)
+		return;
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	hmin = 1000 * simple_strtoul(p, NULL, 10);
+	if (hmin <= 0)
+		return;
+	if (!(p = strsep(&spec, "")) || !*p)
+		return;
+	hmax = 1000 * simple_strtoul(p, NULL, 10);
+	if (hmax <= 0 || hmax <= hmin)
+		return;
+
+	amifb_hfmin = hmin;
+	amifb_hfmax = hmax;
+	amifb_vfmin = vmin;
+	amifb_vfmax = vmax;
+}
+
+static int __init amifb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strcmp(this_opt, "inverse")) {
+			fb_invert_cmaps();
+		} else if (!strcmp(this_opt, "ilbm"))
+			amifb_ilbm = 1;
+		else if (!strncmp(this_opt, "monitorcap:", 11))
+			amifb_setup_mcap(this_opt + 11);
+		else if (!strncmp(this_opt, "fstart:", 7))
+			min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
+		else
+			mode_option = this_opt;
+	}
+
+	if (min_fstrt < 48)
+		min_fstrt = 48;
+
+	return 0;
+}
+
+
+static int amifb_check_var(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	int err;
+	struct amifb_par par;
+
+	/* Validate wanted screen parameters */
+	err = ami_decode_var(var, &par, info);
+	if (err)
+		return err;
+
+	/* Encode (possibly rounded) screen parameters */
+	ami_encode_var(var, &par);
+	return 0;
+}
+
+
+static int amifb_set_par(struct fb_info *info)
+{
+	struct amifb_par *par = info->par;
+	int error;
+
+	do_vmode_pan = 0;
+	do_vmode_full = 0;
+
+	/* Decode wanted screen parameters */
+	error = ami_decode_var(&info->var, par, info);
+	if (error)
+		return error;
+
+	/* Set new videomode */
+	ami_build_copper(info);
+
+	/* Set VBlank trigger */
+	do_vmode_full = 1;
+
+	/* Update fix for new screen parameters */
+	if (par->bpp == 1) {
+		info->fix.type = FB_TYPE_PACKED_PIXELS;
+		info->fix.type_aux = 0;
+	} else if (amifb_ilbm) {
+		info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
+		info->fix.type_aux = par->next_line;
+	} else {
+		info->fix.type = FB_TYPE_PLANES;
+		info->fix.type_aux = 0;
+	}
+	info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
+
+	if (par->vmode & FB_VMODE_YWRAP) {
+		info->fix.ywrapstep = 1;
+		info->fix.xpanstep = 0;
+		info->fix.ypanstep = 0;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
+			FBINFO_READS_FAST; /* override SCROLL_REDRAW */
+	} else {
+		info->fix.ywrapstep = 0;
+		if (par->vmode & FB_VMODE_SMOOTH_XPAN)
+			info->fix.xpanstep = 1;
+		else
+			info->fix.xpanstep = 16 << maxfmode;
+		info->fix.ypanstep = 1;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	}
+	return 0;
+}
+
+
+	/*
+	 * Set a single color register. The values supplied are already
+	 * rounded down to the hardware's capabilities (according to the
+	 * entries in the var structure). Return != 0 for invalid regno.
+	 */
+
+static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info)
+{
+	const struct amifb_par *par = info->par;
+
+	if (IS_AGA) {
+		if (regno > 255)
+			return 1;
+	} else if (par->bplcon0 & BPC0_SHRES) {
+		if (regno > 3)
+			return 1;
+	} else {
+		if (regno > 31)
+			return 1;
+	}
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	if (!regno) {
+		red0 = red;
+		green0 = green;
+		blue0 = blue;
+	}
+
+	/*
+	 * Update the corresponding Hardware Color Register, unless it's Color
+	 * Register 0 and the screen is blanked.
+	 *
+	 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
+	 * being changed by ami_do_blank() during the VBlank.
+	 */
+
+	if (regno || !is_blanked) {
+#if defined(CONFIG_FB_AMIGA_AGA)
+		if (IS_AGA) {
+			u_short bplcon3 = par->bplcon3;
+			VBlankOff();
+			custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
+			custom.color[regno & 31] = rgb2hw8_high(red, green,
+								blue);
+			custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
+					 BPC3_LOCT;
+			custom.color[regno & 31] = rgb2hw8_low(red, green,
+							       blue);
+			custom.bplcon3 = bplcon3;
+			VBlankOn();
+		} else
+#endif
+#if defined(CONFIG_FB_AMIGA_ECS)
+		if (par->bplcon0 & BPC0_SHRES) {
+			u_short color, mask;
+			int i;
+
+			mask = 0x3333;
+			color = rgb2hw2(red, green, blue);
+			VBlankOff();
+			for (i = regno + 12; i >= (int)regno; i -= 4)
+				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+			mask <<= 2; color >>= 2;
+			regno = down16(regno) + mul4(mod4(regno));
+			for (i = regno + 3; i >= (int)regno; i--)
+				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+			VBlankOn();
+		} else
+#endif
+			custom.color[regno] = rgb2hw4(red, green, blue);
+	}
+	return 0;
+}
+
+
+	/*
+	 * Blank the display.
+	 */
+
+static int amifb_blank(int blank, struct fb_info *info)
+{
+	do_blank = blank ? blank : -1;
+
+	return 0;
+}
+
+
+	/*
+	 * Pan or Wrap the Display
+	 *
+	 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+	 */
+
+static int amifb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0 ||
+			var->yoffset >= info->var.yres_virtual || var->xoffset)
+				return -EINVAL;
+	} else {
+		/*
+		 * TODO: There will be problems when xpan!=1, so some columns
+		 * on the right side will never be seen
+		 */
+		if (var->xoffset + info->var.xres >
+		    upx(16 << maxfmode, info->var.xres_virtual) ||
+		    var->yoffset + info->var.yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	ami_pan_var(var, info);
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+
+#if BITS_PER_LONG == 32
+#define BYTES_PER_LONG	4
+#define SHIFT_PER_LONG	5
+#elif BITS_PER_LONG == 64
+#define BYTES_PER_LONG	8
+#define SHIFT_PER_LONG	6
+#else
+#define Please update me
+#endif
+
+
+	/*
+	 *  Compose two values, using a bitmask as decision value
+	 *  This is equivalent to (a & mask) | (b & ~mask)
+	 */
+
+static inline unsigned long comp(unsigned long a, unsigned long b,
+				 unsigned long mask)
+{
+	return ((a ^ b) & mask) ^ b;
+}
+
+
+static inline unsigned long xor(unsigned long a, unsigned long b,
+				unsigned long mask)
+{
+	return (a & mask) ^ b;
+}
+
+
+	/*
+	 *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses
+	 */
+
+static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
+		   int src_idx, u32 n)
+{
+	unsigned long first, last;
+	int shift = dst_idx - src_idx, left, right;
+	unsigned long d0, d1;
+	int m;
+
+	if (!n)
+		return;
+
+	shift = dst_idx - src_idx;
+	first = ~0UL >> dst_idx;
+	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
+
+	if (!shift) {
+		// Same alignment for source and dest
+
+		if (dst_idx + n <= BITS_PER_LONG) {
+			// Single word
+			if (last)
+				first &= last;
+			*dst = comp(*src, *dst, first);
+		} else {
+			// Multiple destination words
+			// Leading bits
+			if (first) {
+				*dst = comp(*src, *dst, first);
+				dst++;
+				src++;
+				n -= BITS_PER_LONG - dst_idx;
+			}
+
+			// Main chunk
+			n /= BITS_PER_LONG;
+			while (n >= 8) {
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				n -= 8;
+			}
+			while (n--)
+				*dst++ = *src++;
+
+			// Trailing bits
+			if (last)
+				*dst = comp(*src, *dst, last);
+		}
+	} else {
+		// Different alignment for source and dest
+
+		right = shift & (BITS_PER_LONG - 1);
+		left = -shift & (BITS_PER_LONG - 1);
+
+		if (dst_idx + n <= BITS_PER_LONG) {
+			// Single destination word
+			if (last)
+				first &= last;
+			if (shift > 0) {
+				// Single source word
+				*dst = comp(*src >> right, *dst, first);
+			} else if (src_idx + n <= BITS_PER_LONG) {
+				// Single source word
+				*dst = comp(*src << left, *dst, first);
+			} else {
+				// 2 source words
+				d0 = *src++;
+				d1 = *src;
+				*dst = comp(d0 << left | d1 >> right, *dst,
+					    first);
+			}
+		} else {
+			// Multiple destination words
+			d0 = *src++;
+			// Leading bits
+			if (shift > 0) {
+				// Single source word
+				*dst = comp(d0 >> right, *dst, first);
+				dst++;
+				n -= BITS_PER_LONG - dst_idx;
+			} else {
+				// 2 source words
+				d1 = *src++;
+				*dst = comp(d0 << left | d1 >> right, *dst,
+					    first);
+				d0 = d1;
+				dst++;
+				n -= BITS_PER_LONG - dst_idx;
+			}
+
+			// Main chunk
+			m = n % BITS_PER_LONG;
+			n /= BITS_PER_LONG;
+			while (n >= 4) {
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				n -= 4;
+			}
+			while (n--) {
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+			}
+
+			// Trailing bits
+			if (last) {
+				if (m <= right) {
+					// Single source word
+					*dst = comp(d0 << left, *dst, last);
+				} else {
+					// 2 source words
+					d1 = *src;
+					*dst = comp(d0 << left | d1 >> right,
+						    *dst, last);
+				}
+			}
+		}
+	}
+}
+
+
+	/*
+	 *  Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
+	 */
+
+static void bitcpy_rev(unsigned long *dst, int dst_idx,
+		       const unsigned long *src, int src_idx, u32 n)
+{
+	unsigned long first, last;
+	int shift = dst_idx - src_idx, left, right;
+	unsigned long d0, d1;
+	int m;
+
+	if (!n)
+		return;
+
+	dst += (n - 1) / BITS_PER_LONG;
+	src += (n - 1) / BITS_PER_LONG;
+	if ((n - 1) % BITS_PER_LONG) {
+		dst_idx += (n - 1) % BITS_PER_LONG;
+		dst += dst_idx >> SHIFT_PER_LONG;
+		dst_idx &= BITS_PER_LONG - 1;
+		src_idx += (n - 1) % BITS_PER_LONG;
+		src += src_idx >> SHIFT_PER_LONG;
+		src_idx &= BITS_PER_LONG - 1;
+	}
+
+	shift = dst_idx - src_idx;
+	first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
+	last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
+
+	if (!shift) {
+		// Same alignment for source and dest
+
+		if ((unsigned long)dst_idx + 1 >= n) {
+			// Single word
+			if (last)
+				first &= last;
+			*dst = comp(*src, *dst, first);
+		} else {
+			// Multiple destination words
+			// Leading bits
+			if (first) {
+				*dst = comp(*src, *dst, first);
+				dst--;
+				src--;
+				n -= dst_idx + 1;
+			}
+
+			// Main chunk
+			n /= BITS_PER_LONG;
+			while (n >= 8) {
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				n -= 8;
+			}
+			while (n--)
+				*dst-- = *src--;
+
+			// Trailing bits
+			if (last)
+				*dst = comp(*src, *dst, last);
+		}
+	} else {
+		// Different alignment for source and dest
+
+		right = shift & (BITS_PER_LONG - 1);
+		left = -shift & (BITS_PER_LONG - 1);
+
+		if ((unsigned long)dst_idx + 1 >= n) {
+			// Single destination word
+			if (last)
+				first &= last;
+			if (shift < 0) {
+				// Single source word
+				*dst = comp(*src << left, *dst, first);
+			} else if (1 + (unsigned long)src_idx >= n) {
+				// Single source word
+				*dst = comp(*src >> right, *dst, first);
+			} else {
+				// 2 source words
+				d0 = *src--;
+				d1 = *src;
+				*dst = comp(d0 >> right | d1 << left, *dst,
+					    first);
+			}
+		} else {
+			// Multiple destination words
+			d0 = *src--;
+			// Leading bits
+			if (shift < 0) {
+				// Single source word
+				*dst = comp(d0 << left, *dst, first);
+				dst--;
+				n -= dst_idx + 1;
+			} else {
+				// 2 source words
+				d1 = *src--;
+				*dst = comp(d0 >> right | d1 << left, *dst,
+					    first);
+				d0 = d1;
+				dst--;
+				n -= dst_idx + 1;
+			}
+
+			// Main chunk
+			m = n % BITS_PER_LONG;
+			n /= BITS_PER_LONG;
+			while (n >= 4) {
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				n -= 4;
+			}
+			while (n--) {
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+			}
+
+			// Trailing bits
+			if (last) {
+				if (m <= left) {
+					// Single source word
+					*dst = comp(d0 >> right, *dst, last);
+				} else {
+					// 2 source words
+					d1 = *src;
+					*dst = comp(d0 >> right | d1 << left,
+						    *dst, last);
+				}
+			}
+		}
+	}
+}
+
+
+	/*
+	 *  Unaligned forward inverting bit copy using 32-bit or 64-bit memory
+	 *  accesses
+	 */
+
+static void bitcpy_not(unsigned long *dst, int dst_idx,
+		       const unsigned long *src, int src_idx, u32 n)
+{
+	unsigned long first, last;
+	int shift = dst_idx - src_idx, left, right;
+	unsigned long d0, d1;
+	int m;
+
+	if (!n)
+		return;
+
+	shift = dst_idx - src_idx;
+	first = ~0UL >> dst_idx;
+	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
+
+	if (!shift) {
+		// Same alignment for source and dest
+
+		if (dst_idx + n <= BITS_PER_LONG) {
+			// Single word
+			if (last)
+				first &= last;
+			*dst = comp(~*src, *dst, first);
+		} else {
+			// Multiple destination words
+			// Leading bits
+			if (first) {
+				*dst = comp(~*src, *dst, first);
+				dst++;
+				src++;
+				n -= BITS_PER_LONG - dst_idx;
+			}
+
+			// Main chunk
+			n /= BITS_PER_LONG;
+			while (n >= 8) {
+				*dst++ = ~*src++;
+				*dst++ = ~*src++;
+				*dst++ = ~*src++;
+				*dst++ = ~*src++;
+				*dst++ = ~*src++;
+				*dst++ = ~*src++;
+				*dst++ = ~*src++;
+				*dst++ = ~*src++;
+				n -= 8;
+			}
+			while (n--)
+				*dst++ = ~*src++;
+
+			// Trailing bits
+			if (last)
+				*dst = comp(~*src, *dst, last);
+		}
+	} else {
+		// Different alignment for source and dest
+
+		right = shift & (BITS_PER_LONG - 1);
+		left = -shift & (BITS_PER_LONG - 1);
+
+		if (dst_idx + n <= BITS_PER_LONG) {
+			// Single destination word
+			if (last)
+				first &= last;
+			if (shift > 0) {
+				// Single source word
+				*dst = comp(~*src >> right, *dst, first);
+			} else if (src_idx + n <= BITS_PER_LONG) {
+				// Single source word
+				*dst = comp(~*src << left, *dst, first);
+			} else {
+				// 2 source words
+				d0 = ~*src++;
+				d1 = ~*src;
+				*dst = comp(d0 << left | d1 >> right, *dst,
+					    first);
+			}
+		} else {
+			// Multiple destination words
+			d0 = ~*src++;
+			// Leading bits
+			if (shift > 0) {
+				// Single source word
+				*dst = comp(d0 >> right, *dst, first);
+				dst++;
+				n -= BITS_PER_LONG - dst_idx;
+			} else {
+				// 2 source words
+				d1 = ~*src++;
+				*dst = comp(d0 << left | d1 >> right, *dst,
+					    first);
+				d0 = d1;
+				dst++;
+				n -= BITS_PER_LONG - dst_idx;
+			}
+
+			// Main chunk
+			m = n % BITS_PER_LONG;
+			n /= BITS_PER_LONG;
+			while (n >= 4) {
+				d1 = ~*src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = ~*src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = ~*src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = ~*src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				n -= 4;
+			}
+			while (n--) {
+				d1 = ~*src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+			}
+
+			// Trailing bits
+			if (last) {
+				if (m <= right) {
+					// Single source word
+					*dst = comp(d0 << left, *dst, last);
+				} else {
+					// 2 source words
+					d1 = ~*src;
+					*dst = comp(d0 << left | d1 >> right,
+						    *dst, last);
+				}
+			}
+		}
+	}
+}
+
+
+	/*
+	 *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
+	 */
+
+static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+{
+	unsigned long val = pat;
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+#if BITS_PER_LONG == 64
+	val |= val << 32;
+#endif
+
+	first = ~0UL >> dst_idx;
+	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
+
+	if (dst_idx + n <= BITS_PER_LONG) {
+		// Single word
+		if (last)
+			first &= last;
+		*dst = comp(val, *dst, first);
+	} else {
+		// Multiple destination words
+		// Leading bits
+		if (first) {
+			*dst = comp(val, *dst, first);
+			dst++;
+			n -= BITS_PER_LONG - dst_idx;
+		}
+
+		// Main chunk
+		n /= BITS_PER_LONG;
+		while (n >= 8) {
+			*dst++ = val;
+			*dst++ = val;
+			*dst++ = val;
+			*dst++ = val;
+			*dst++ = val;
+			*dst++ = val;
+			*dst++ = val;
+			*dst++ = val;
+			n -= 8;
+		}
+		while (n--)
+			*dst++ = val;
+
+		// Trailing bits
+		if (last)
+			*dst = comp(val, *dst, last);
+	}
+}
+
+
+	/*
+	 *  Unaligned 32-bit pattern xor using 32/64-bit memory accesses
+	 */
+
+static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+{
+	unsigned long val = pat;
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+#if BITS_PER_LONG == 64
+	val |= val << 32;
+#endif
+
+	first = ~0UL >> dst_idx;
+	last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
+
+	if (dst_idx + n <= BITS_PER_LONG) {
+		// Single word
+		if (last)
+			first &= last;
+		*dst = xor(val, *dst, first);
+	} else {
+		// Multiple destination words
+		// Leading bits
+		if (first) {
+			*dst = xor(val, *dst, first);
+			dst++;
+			n -= BITS_PER_LONG - dst_idx;
+		}
+
+		// Main chunk
+		n /= BITS_PER_LONG;
+		while (n >= 4) {
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			n -= 4;
+		}
+		while (n--)
+			*dst++ ^= val;
+
+		// Trailing bits
+		if (last)
+			*dst = xor(val, *dst, last);
+	}
+}
+
+static inline void fill_one_line(int bpp, unsigned long next_plane,
+				 unsigned long *dst, int dst_idx, u32 n,
+				 u32 color)
+{
+	while (1) {
+		dst += dst_idx >> SHIFT_PER_LONG;
+		dst_idx &= (BITS_PER_LONG - 1);
+		bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
+		if (!--bpp)
+			break;
+		color >>= 1;
+		dst_idx += next_plane * 8;
+	}
+}
+
+static inline void xor_one_line(int bpp, unsigned long next_plane,
+				unsigned long *dst, int dst_idx, u32 n,
+				u32 color)
+{
+	while (color) {
+		dst += dst_idx >> SHIFT_PER_LONG;
+		dst_idx &= (BITS_PER_LONG - 1);
+		bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
+		if (!--bpp)
+			break;
+		color >>= 1;
+		dst_idx += next_plane * 8;
+	}
+}
+
+
+static void amifb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect)
+{
+	struct amifb_par *par = info->par;
+	int dst_idx, x2, y2;
+	unsigned long *dst;
+	u32 width, height;
+
+	if (!rect->width || !rect->height)
+		return;
+
+	/*
+	 * We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly.
+	 * */
+	x2 = rect->dx + rect->width;
+	y2 = rect->dy + rect->height;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - rect->dx;
+	height = y2 - rect->dy;
+
+	dst = (unsigned long *)
+		((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+	dst_idx += rect->dy * par->next_line * 8 + rect->dx;
+	while (height--) {
+		switch (rect->rop) {
+		case ROP_COPY:
+			fill_one_line(info->var.bits_per_pixel,
+				      par->next_plane, dst, dst_idx, width,
+				      rect->color);
+			break;
+
+		case ROP_XOR:
+			xor_one_line(info->var.bits_per_pixel, par->next_plane,
+				     dst, dst_idx, width, rect->color);
+			break;
+		}
+		dst_idx += par->next_line * 8;
+	}
+}
+
+static inline void copy_one_line(int bpp, unsigned long next_plane,
+				 unsigned long *dst, int dst_idx,
+				 unsigned long *src, int src_idx, u32 n)
+{
+	while (1) {
+		dst += dst_idx >> SHIFT_PER_LONG;
+		dst_idx &= (BITS_PER_LONG - 1);
+		src += src_idx >> SHIFT_PER_LONG;
+		src_idx &= (BITS_PER_LONG - 1);
+		bitcpy(dst, dst_idx, src, src_idx, n);
+		if (!--bpp)
+			break;
+		dst_idx += next_plane * 8;
+		src_idx += next_plane * 8;
+	}
+}
+
+static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
+				     unsigned long *dst, int dst_idx,
+				     unsigned long *src, int src_idx, u32 n)
+{
+	while (1) {
+		dst += dst_idx >> SHIFT_PER_LONG;
+		dst_idx &= (BITS_PER_LONG - 1);
+		src += src_idx >> SHIFT_PER_LONG;
+		src_idx &= (BITS_PER_LONG - 1);
+		bitcpy_rev(dst, dst_idx, src, src_idx, n);
+		if (!--bpp)
+			break;
+		dst_idx += next_plane * 8;
+		src_idx += next_plane * 8;
+	}
+}
+
+
+static void amifb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *area)
+{
+	struct amifb_par *par = info->par;
+	int x2, y2;
+	u32 dx, dy, sx, sy, width, height;
+	unsigned long *dst, *src;
+	int dst_idx, src_idx;
+	int rev_copy = 0;
+
+	/* clip the destination */
+	x2 = area->dx + area->width;
+	y2 = area->dy + area->height;
+	dx = area->dx > 0 ? area->dx : 0;
+	dy = area->dy > 0 ? area->dy : 0;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - dx;
+	height = y2 - dy;
+
+	if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+		return;
+
+	/* update sx,sy */
+	sx = area->sx + (dx - area->dx);
+	sy = area->sy + (dy - area->dy);
+
+	/* the source must be completely inside the virtual screen */
+	if (sx + width > info->var.xres_virtual ||
+			sy + height > info->var.yres_virtual)
+		return;
+
+	if (dy > sy || (dy == sy && dx > sx)) {
+		dy += height;
+		sy += height;
+		rev_copy = 1;
+	}
+	dst = (unsigned long *)
+		((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+	src = dst;
+	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+	src_idx = dst_idx;
+	dst_idx += dy * par->next_line * 8 + dx;
+	src_idx += sy * par->next_line * 8 + sx;
+	if (rev_copy) {
+		while (height--) {
+			dst_idx -= par->next_line * 8;
+			src_idx -= par->next_line * 8;
+			copy_one_line_rev(info->var.bits_per_pixel,
+					  par->next_plane, dst, dst_idx, src,
+					  src_idx, width);
+		}
+	} else {
+		while (height--) {
+			copy_one_line(info->var.bits_per_pixel,
+				      par->next_plane, dst, dst_idx, src,
+				      src_idx, width);
+			dst_idx += par->next_line * 8;
+			src_idx += par->next_line * 8;
+		}
+	}
+}
+
+
+static inline void expand_one_line(int bpp, unsigned long next_plane,
+				   unsigned long *dst, int dst_idx, u32 n,
+				   const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	const unsigned long *src;
+	int src_idx;
+
+	while (1) {
+		dst += dst_idx >> SHIFT_PER_LONG;
+		dst_idx &= (BITS_PER_LONG - 1);
+		if ((bgcolor ^ fgcolor) & 1) {
+			src = (unsigned long *)
+				((unsigned long)data & ~(BYTES_PER_LONG - 1));
+			src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
+			if (fgcolor & 1)
+				bitcpy(dst, dst_idx, src, src_idx, n);
+			else
+				bitcpy_not(dst, dst_idx, src, src_idx, n);
+			/* set or clear */
+		} else
+			bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
+		if (!--bpp)
+			break;
+		bgcolor >>= 1;
+		fgcolor >>= 1;
+		dst_idx += next_plane * 8;
+	}
+}
+
+
+static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct amifb_par *par = info->par;
+	int x2, y2;
+	unsigned long *dst;
+	int dst_idx;
+	const char *src;
+	u32 dx, dy, width, height, pitch;
+
+	/*
+	 * We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly like we are
+	 * doing here.
+	 */
+	x2 = image->dx + image->width;
+	y2 = image->dy + image->height;
+	dx = image->dx;
+	dy = image->dy;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width  = x2 - dx;
+	height = y2 - dy;
+
+	if (image->depth == 1) {
+		dst = (unsigned long *)
+			((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+		dst_idx += dy * par->next_line * 8 + dx;
+		src = image->data;
+		pitch = (image->width + 7) / 8;
+		while (height--) {
+			expand_one_line(info->var.bits_per_pixel,
+					par->next_plane, dst, dst_idx, width,
+					src, image->bg_color,
+					image->fg_color);
+			dst_idx += par->next_line * 8;
+			src += pitch;
+		}
+	} else {
+		c2p_planar(info->screen_base, image->data, dx, dy, width,
+			   height, par->next_line, par->next_plane,
+			   image->width, info->var.bits_per_pixel);
+	}
+}
+
+
+	/*
+	 * Amiga Frame Buffer Specific ioctls
+	 */
+
+static int amifb_ioctl(struct fb_info *info,
+		       unsigned int cmd, unsigned long arg)
+{
+	union {
+		struct fb_fix_cursorinfo fix;
+		struct fb_var_cursorinfo var;
+		struct fb_cursorstate state;
+	} crsr;
+	void __user *argp = (void __user *)arg;
+	int i;
+
+	switch (cmd) {
+	case FBIOGET_FCURSORINFO:
+		i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
+		if (i)
+			return i;
+		return copy_to_user(argp, &crsr.fix,
+				    sizeof(crsr.fix)) ? -EFAULT : 0;
+
+	case FBIOGET_VCURSORINFO:
+		i = ami_get_var_cursorinfo(&crsr.var,
+			((struct fb_var_cursorinfo __user *)arg)->data,
+			info->par);
+		if (i)
+			return i;
+		return copy_to_user(argp, &crsr.var,
+				    sizeof(crsr.var)) ? -EFAULT : 0;
+
+	case FBIOPUT_VCURSORINFO:
+		if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
+			return -EFAULT;
+		return ami_set_var_cursorinfo(&crsr.var,
+			((struct fb_var_cursorinfo __user *)arg)->data,
+			info->par);
+
+	case FBIOGET_CURSORSTATE:
+		i = ami_get_cursorstate(&crsr.state, info->par);
+		if (i)
+			return i;
+		return copy_to_user(argp, &crsr.state,
+				    sizeof(crsr.state)) ? -EFAULT : 0;
+
+	case FBIOPUT_CURSORSTATE:
+		if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
+			return -EFAULT;
+		return ami_set_cursorstate(&crsr.state, info->par);
+	}
+	return -EINVAL;
+}
+
+
+	/*
+	 * Flash the cursor (called by VBlank interrupt)
+	 */
+
+static int flash_cursor(void)
+{
+	static int cursorcount = 1;
+
+	if (cursormode == FB_CURSOR_FLASH) {
+		if (!--cursorcount) {
+			cursorstate = -cursorstate;
+			cursorcount = cursorrate;
+			if (!is_blanked)
+				return 1;
+		}
+	}
+	return 0;
+}
+
+	/*
+	 * VBlank Display Interrupt
+	 */
+
+static irqreturn_t amifb_interrupt(int irq, void *dev_id)
+{
+	struct amifb_par *par = dev_id;
+
+	if (do_vmode_pan || do_vmode_full)
+		ami_update_display(par);
+
+	if (do_vmode_full)
+		ami_init_display(par);
+
+	if (do_vmode_pan) {
+		flash_cursor();
+		ami_rebuild_copper(par);
+		do_cursor = do_vmode_pan = 0;
+	} else if (do_cursor) {
+		flash_cursor();
+		ami_set_sprite(par);
+		do_cursor = 0;
+	} else {
+		if (flash_cursor())
+			ami_set_sprite(par);
+	}
+
+	if (do_blank) {
+		ami_do_blank(par);
+		do_blank = 0;
+	}
+
+	if (do_vmode_full) {
+		ami_reinit_copper(par);
+		do_vmode_full = 0;
+	}
+	return IRQ_HANDLED;
+}
+
+
+static struct fb_ops amifb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= amifb_check_var,
+	.fb_set_par	= amifb_set_par,
+	.fb_setcolreg	= amifb_setcolreg,
+	.fb_blank	= amifb_blank,
+	.fb_pan_display	= amifb_pan_display,
+	.fb_fillrect	= amifb_fillrect,
+	.fb_copyarea	= amifb_copyarea,
+	.fb_imageblit	= amifb_imageblit,
+	.fb_ioctl	= amifb_ioctl,
+};
+
+
+	/*
+	 * Allocate, Clear and Align a Block of Chip Memory
+	 */
+
+static void *aligned_chipptr;
+
+static inline u_long __init chipalloc(u_long size)
+{
+	aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
+	if (!aligned_chipptr) {
+		pr_err("amifb: No Chip RAM for frame buffer");
+		return 0;
+	}
+	memset(aligned_chipptr, 0, size);
+	return (u_long)aligned_chipptr;
+}
+
+static inline void chipfree(void)
+{
+	if (aligned_chipptr)
+		amiga_chip_free(aligned_chipptr);
+}
+
+
+	/*
+	 * Initialisation
+	 */
+
+static int __init amifb_probe(struct platform_device *pdev)
+{
+	struct fb_info *info;
+	int tag, i, err = 0;
+	u_long chipptr;
+	u_int defmode;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("amifb", &option)) {
+		amifb_video_off();
+		return -ENODEV;
+	}
+	amifb_setup(option);
+#endif
+	custom.dmacon = DMAF_ALL | DMAF_MASTER;
+
+	info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
+	if (!info) {
+		dev_err(&pdev->dev, "framebuffer_alloc failed\n");
+		return -ENOMEM;
+	}
+
+	strcpy(info->fix.id, "Amiga ");
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	info->fix.accel = FB_ACCEL_AMIGABLITT;
+
+	switch (amiga_chipset) {
+#ifdef CONFIG_FB_AMIGA_OCS
+	case CS_OCS:
+		strcat(info->fix.id, "OCS");
+default_chipset:
+		chipset = TAG_OCS;
+		maxdepth[TAG_SHRES] = 0;	/* OCS means no SHRES */
+		maxdepth[TAG_HIRES] = 4;
+		maxdepth[TAG_LORES] = 6;
+		maxfmode = TAG_FMODE_1;
+		defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
+		info->fix.smem_len = VIDEOMEMSIZE_OCS;
+		break;
+#endif /* CONFIG_FB_AMIGA_OCS */
+
+#ifdef CONFIG_FB_AMIGA_ECS
+	case CS_ECS:
+		strcat(info->fix.id, "ECS");
+		chipset = TAG_ECS;
+		maxdepth[TAG_SHRES] = 2;
+		maxdepth[TAG_HIRES] = 4;
+		maxdepth[TAG_LORES] = 6;
+		maxfmode = TAG_FMODE_1;
+		if (AMIGAHW_PRESENT(AMBER_FF))
+			defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
+						     : DEFMODE_AMBER_NTSC;
+		else
+			defmode = amiga_vblank == 50 ? DEFMODE_PAL
+						     : DEFMODE_NTSC;
+		if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
+		    VIDEOMEMSIZE_ECS_2M)
+			info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
+		else
+			info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
+		break;
+#endif /* CONFIG_FB_AMIGA_ECS */
+
+#ifdef CONFIG_FB_AMIGA_AGA
+	case CS_AGA:
+		strcat(info->fix.id, "AGA");
+		chipset = TAG_AGA;
+		maxdepth[TAG_SHRES] = 8;
+		maxdepth[TAG_HIRES] = 8;
+		maxdepth[TAG_LORES] = 8;
+		maxfmode = TAG_FMODE_4;
+		defmode = DEFMODE_AGA;
+		if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
+		    VIDEOMEMSIZE_AGA_2M)
+			info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
+		else
+			info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
+		break;
+#endif /* CONFIG_FB_AMIGA_AGA */
+
+	default:
+#ifdef CONFIG_FB_AMIGA_OCS
+		printk("Unknown graphics chipset, defaulting to OCS\n");
+		strcat(info->fix.id, "Unknown");
+		goto default_chipset;
+#else /* CONFIG_FB_AMIGA_OCS */
+		err = -ENODEV;
+		goto release;
+#endif /* CONFIG_FB_AMIGA_OCS */
+		break;
+	}
+
+	/*
+	 * Calculate the Pixel Clock Values for this Machine
+	 */
+
+	{
+	u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
+
+	pixclock[TAG_SHRES] = (tmp + 4) / 8;	/* SHRES:  35 ns / 28 MHz */
+	pixclock[TAG_HIRES] = (tmp + 2) / 4;	/* HIRES:  70 ns / 14 MHz */
+	pixclock[TAG_LORES] = (tmp + 1) / 2;	/* LORES: 140 ns /  7 MHz */
+	}
+
+	/*
+	 * Replace the Tag Values with the Real Pixel Clock Values
+	 */
+
+	for (i = 0; i < NUM_TOTAL_MODES; i++) {
+		struct fb_videomode *mode = &ami_modedb[i];
+		tag = mode->pixclock;
+		if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
+			mode->pixclock = pixclock[tag];
+		}
+	}
+
+	if (amifb_hfmin) {
+		info->monspecs.hfmin = amifb_hfmin;
+		info->monspecs.hfmax = amifb_hfmax;
+		info->monspecs.vfmin = amifb_vfmin;
+		info->monspecs.vfmax = amifb_vfmax;
+	} else {
+		/*
+		 *  These are for a typical Amiga monitor (e.g. A1960)
+		 */
+		info->monspecs.hfmin = 15000;
+		info->monspecs.hfmax = 38000;
+		info->monspecs.vfmin = 49;
+		info->monspecs.vfmax = 90;
+	}
+
+	info->fbops = &amifb_ops;
+	info->flags = FBINFO_DEFAULT;
+	info->device = &pdev->dev;
+
+	if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
+			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
+		err = -EINVAL;
+		goto release;
+	}
+
+	fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
+				 &info->modelist);
+
+	round_down_bpp = 0;
+	chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
+			    DUMMYSPRITEMEMSIZE + COPINITSIZE +
+			    4 * COPLISTSIZE);
+	if (!chipptr) {
+		err = -ENOMEM;
+		goto release;
+	}
+
+	assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
+	assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
+	assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
+	assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
+	assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
+	assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
+	assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
+	assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
+
+	/*
+	 * access the videomem with writethrough cache
+	 */
+	info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
+	videomemory = (u_long)ioremap_writethrough(info->fix.smem_start,
+						   info->fix.smem_len);
+	if (!videomemory) {
+		dev_warn(&pdev->dev,
+			 "Unable to map videomem cached writethrough\n");
+		info->screen_base = ZTWO_VADDR(info->fix.smem_start);
+	} else
+		info->screen_base = (char *)videomemory;
+
+	memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
+
+	/*
+	 * Make sure the Copper has something to do
+	 */
+	ami_init_copper();
+
+	/*
+	 * Enable Display DMA
+	 */
+	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
+			DMAF_BLITTER | DMAF_SPRITE;
+
+	err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
+			  "fb vertb handler", info->par);
+	if (err)
+		goto disable_dma;
+
+	err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
+	if (err)
+		goto free_irq;
+
+	dev_set_drvdata(&pdev->dev, info);
+
+	err = register_framebuffer(info);
+	if (err)
+		goto unset_drvdata;
+
+	fb_info(info, "%s frame buffer device, using %dK of video memory\n",
+		info->fix.id, info->fix.smem_len>>10);
+
+	return 0;
+
+unset_drvdata:
+	fb_dealloc_cmap(&info->cmap);
+free_irq:
+	free_irq(IRQ_AMIGA_COPPER, info->par);
+disable_dma:
+	custom.dmacon = DMAF_ALL | DMAF_MASTER;
+	if (videomemory)
+		iounmap((void *)videomemory);
+	chipfree();
+release:
+	framebuffer_release(info);
+	return err;
+}
+
+
+static int __exit amifb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = dev_get_drvdata(&pdev->dev);
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+	free_irq(IRQ_AMIGA_COPPER, info->par);
+	custom.dmacon = DMAF_ALL | DMAF_MASTER;
+	if (videomemory)
+		iounmap((void *)videomemory);
+	chipfree();
+	framebuffer_release(info);
+	amifb_video_off();
+	return 0;
+}
+
+static struct platform_driver amifb_driver = {
+	.remove = __exit_p(amifb_remove),
+	.driver   = {
+		.name	= "amiga-video",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver_probe(amifb_driver, amifb_probe);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c
new file mode 100644
index 000000000000..1b0b233b8b39
--- /dev/null
+++ b/drivers/video/fbdev/arcfb.c
@@ -0,0 +1,667 @@
+/*
+ * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
+ *
+ * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver was written to be used with the Arc LCD board. Arc uses a
+ * set of KS108 chips that control individual 64x64 LCD matrices. The board
+ * can be paneled in a variety of setups such as 2x1=128x64, 4x4=256x256 and
+ * so on. The interface between the board and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 4+n lines for control. On a
+ * GPIO-less system, the board can be tested by connecting the respective sigs
+ * up to a parallel port connector. The driver requires the IO addresses for
+ * data and control GPIO at load time. It is unable to probe for the
+ * existence of the LCD so it must be told at load time whether it should
+ * be enabled or not.
+ *
+ * Todo:
+ * - testing with 4x4
+ * - testing with interrupt hw
+ *
+ * General notes:
+ * - User must set tuhold. It's in microseconds. According to the 108 spec,
+ *   the hold time is supposed to be at least 1 microsecond.
+ * - User must set num_cols=x num_rows=y, eg: x=2 means 128
+ * - User must set arcfb_enable=1 to enable it
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/arcfb.h>
+#include <linux/platform_device.h>
+
+#include <linux/uaccess.h>
+
+#define floor8(a) (a&(~0x07))
+#define floorXres(a,xres) (a&(~(xres - 1)))
+#define iceil8(a) (((int)((a+7)/8))*8)
+#define ceil64(a) (a|0x3F)
+#define ceilXres(a,xres) (a|(xres - 1))
+
+/* ks108 chipset specific defines and code */
+
+#define KS_SET_DPY_START_LINE 	0xC0
+#define KS_SET_PAGE_NUM 	0xB8
+#define KS_SET_X 		0x40
+#define KS_CEHI 		0x01
+#define KS_CELO 		0x00
+#define KS_SEL_CMD 		0x08
+#define KS_SEL_DATA 		0x00
+#define KS_DPY_ON 		0x3F
+#define KS_DPY_OFF 		0x3E
+#define KS_INTACK 		0x40
+#define KS_CLRINT		0x02
+
+struct arcfb_par {
+	unsigned long dio_addr;
+	unsigned long cio_addr;
+	unsigned long c2io_addr;
+	atomic_t ref_count;
+	unsigned char cslut[9];
+	struct fb_info *info;
+	unsigned int irq;
+	spinlock_t lock;
+};
+
+static struct fb_fix_screeninfo arcfb_fix = {
+	.id =		"arcfb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_MONO01,
+	.xpanstep =	0,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo arcfb_var = {
+	.xres		= 128,
+	.yres		= 64,
+	.xres_virtual	= 128,
+	.yres_virtual	= 64,
+	.bits_per_pixel	= 1,
+	.nonstd		= 1,
+};
+
+static unsigned long num_cols;
+static unsigned long num_rows;
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned long tuhold;
+static unsigned int nosplash;
+static unsigned int arcfb_enable;
+static unsigned int irq;
+
+static DECLARE_WAIT_QUEUE_HEAD(arcfb_waitq);
+
+static void ks108_writeb_ctl(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char value)
+{
+	unsigned char chipselval = par->cslut[chipindex];
+
+	outb(chipselval|KS_CEHI|KS_SEL_CMD, par->cio_addr);
+	outb(value, par->dio_addr);
+	udelay(tuhold);
+	outb(chipselval|KS_CELO|KS_SEL_CMD, par->cio_addr);
+}
+
+static void ks108_writeb_mainctl(struct arcfb_par *par, unsigned char value)
+{
+
+	outb(value, par->cio_addr);
+	udelay(tuhold);
+}
+
+static unsigned char ks108_readb_ctl2(struct arcfb_par *par)
+{
+	return inb(par->c2io_addr);
+}
+
+static void ks108_writeb_data(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char value)
+{
+	unsigned char chipselval = par->cslut[chipindex];
+
+	outb(chipselval|KS_CEHI|KS_SEL_DATA, par->cio_addr);
+	outb(value, par->dio_addr);
+	udelay(tuhold);
+	outb(chipselval|KS_CELO|KS_SEL_DATA, par->cio_addr);
+}
+
+static void ks108_set_start_line(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char y)
+{
+	ks108_writeb_ctl(par, chipindex, KS_SET_DPY_START_LINE|y);
+}
+
+static void ks108_set_yaddr(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char y)
+{
+	ks108_writeb_ctl(par, chipindex, KS_SET_PAGE_NUM|y);
+}
+
+static void ks108_set_xaddr(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char x)
+{
+	ks108_writeb_ctl(par, chipindex, KS_SET_X|x);
+}
+
+static void ks108_clear_lcd(struct arcfb_par *par, unsigned int chipindex)
+{
+	int i,j;
+
+	for (i = 0; i <= 8; i++) {
+		ks108_set_yaddr(par, chipindex, i);
+		ks108_set_xaddr(par, chipindex, 0);
+		for (j = 0; j < 64; j++) {
+			ks108_writeb_data(par, chipindex,
+				(unsigned char) splashval);
+		}
+	}
+}
+
+/* main arcfb functions */
+
+static int arcfb_open(struct fb_info *info, int user)
+{
+	struct arcfb_par *par = info->par;
+
+	atomic_inc(&par->ref_count);
+	return 0;
+}
+
+static int arcfb_release(struct fb_info *info, int user)
+{
+	struct arcfb_par *par = info->par;
+	int count = atomic_read(&par->ref_count);
+
+	if (!count)
+		return -EINVAL;
+	atomic_dec(&par->ref_count);
+	return 0;
+}
+
+static int arcfb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	int i;
+	struct arcfb_par *par = info->par;
+
+	if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 64)
+		&& (info->var.yres <= 64)) {
+		for (i = 0; i < num_cols; i++) {
+			ks108_set_start_line(par, i, var->yoffset);
+		}
+		info->var.yoffset = var->yoffset;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static irqreturn_t arcfb_interrupt(int vec, void *dev_instance)
+{
+	struct fb_info *info = dev_instance;
+	unsigned char ctl2status;
+	struct arcfb_par *par = info->par;
+
+	ctl2status = ks108_readb_ctl2(par);
+
+	if (!(ctl2status & KS_INTACK)) /* not arc generated interrupt */
+		return IRQ_NONE;
+
+	ks108_writeb_mainctl(par, KS_CLRINT);
+
+	spin_lock(&par->lock);
+        if (waitqueue_active(&arcfb_waitq)) {
+                wake_up(&arcfb_waitq);
+        }
+	spin_unlock(&par->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * here we handle a specific page on the lcd. the complexity comes from
+ * the fact that the fb is laidout in 8xX vertical columns. we extract
+ * each write of 8 vertical pixels. then we shift out as we move along
+ * X. That's what rightshift does. bitmask selects the desired input bit.
+ */
+static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
+		unsigned int left, unsigned int right, unsigned int distance)
+{
+	unsigned char *src;
+	unsigned int xindex, yindex, chipindex, linesize;
+	int i;
+	unsigned char val;
+	unsigned char bitmask, rightshift;
+
+	xindex = left >> 6;
+	yindex = upper >> 6;
+	chipindex = (xindex + (yindex*num_cols));
+
+	ks108_set_yaddr(par, chipindex, upper/8);
+
+	linesize = par->info->var.xres/8;
+	src = (unsigned char __force *) par->info->screen_base + (left/8) +
+		(upper * linesize);
+	ks108_set_xaddr(par, chipindex, left);
+
+	bitmask=1;
+	rightshift=0;
+	while (left <= right) {
+		val = 0;
+		for (i = 0; i < 8; i++) {
+			if ( i > rightshift) {
+				val |= (*(src + (i*linesize)) & bitmask)
+						<< (i - rightshift);
+			} else {
+				val |= (*(src + (i*linesize)) & bitmask)
+						 >> (rightshift - i);
+			}
+		}
+		ks108_writeb_data(par, chipindex, val);
+		left++;
+		if (bitmask == 0x80) {
+			bitmask = 1;
+			src++;
+			rightshift=0;
+		} else {
+			bitmask <<= 1;
+			rightshift++;
+		}
+	}
+}
+
+/*
+ * here we handle the entire vertical page of the update. we write across
+ * lcd chips. update_page uses the upper/left values to decide which
+ * chip to select for the right. upper is needed for setting the page
+ * desired for the write.
+ */
+static void arcfb_lcd_update_vert(struct arcfb_par *par, unsigned int top,
+		unsigned int bottom, unsigned int left, unsigned int right)
+{
+	unsigned int distance, upper, lower;
+
+	distance = (bottom - top) + 1;
+	upper = top;
+	lower = top + 7;
+
+	while (distance > 0) {
+		distance -= 8;
+		arcfb_lcd_update_page(par, upper, left, right, 8);
+		upper = lower + 1;
+		lower = upper + 7;
+	}
+}
+
+/*
+ * here we handle horizontal blocks for the update. update_vert will
+ * handle spaning multiple pages. we break out each horizontal
+ * block in to individual blocks no taller than 64 pixels.
+ */
+static void arcfb_lcd_update_horiz(struct arcfb_par *par, unsigned int left,
+			unsigned int right, unsigned int top, unsigned int h)
+{
+	unsigned int distance, upper, lower;
+
+	distance = h;
+	upper = floor8(top);
+	lower = min(upper + distance - 1, ceil64(upper));
+
+	while (distance > 0) {
+		distance -= ((lower - upper) + 1 );
+		arcfb_lcd_update_vert(par, upper, lower, left, right);
+		upper = lower + 1;
+		lower = min(upper + distance - 1, ceil64(upper));
+	}
+}
+
+/*
+ * here we start the process of splitting out the fb update into
+ * individual blocks of pixels. we end up splitting into 64x64 blocks
+ * and finally down to 64x8 pages.
+ */
+static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
+			unsigned int dy, unsigned int w, unsigned int h)
+{
+	unsigned int left, right, distance, y;
+
+	/* align the request first */
+	y = floor8(dy);
+	h += dy - y;
+	h = iceil8(h);
+
+	distance = w;
+	left = dx;
+	right = min(left + w - 1, ceil64(left));
+
+	while (distance > 0) {
+		arcfb_lcd_update_horiz(par, left, right, y, h);
+		distance -= ((right - left) + 1);
+		left = right + 1;
+		right = min(left + distance - 1, ceil64(left));
+	}
+}
+
+static void arcfb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect)
+{
+	struct arcfb_par *par = info->par;
+
+	sys_fillrect(info, rect);
+
+	/* update the physical lcd */
+	arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+static void arcfb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *area)
+{
+	struct arcfb_par *par = info->par;
+
+	sys_copyarea(info, area);
+
+	/* update the physical lcd */
+	arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
+}
+
+static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct arcfb_par *par = info->par;
+
+	sys_imageblit(info, image);
+
+	/* update the physical lcd */
+	arcfb_lcd_update(par, image->dx, image->dy, image->width,
+				image->height);
+}
+
+static int arcfb_ioctl(struct fb_info *info,
+			  unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	struct arcfb_par *par = info->par;
+	unsigned long flags;
+
+	switch (cmd) {
+		case FBIO_WAITEVENT:
+		{
+			DEFINE_WAIT(wait);
+			/* illegal to wait on arc if no irq will occur */
+			if (!par->irq)
+				return -EINVAL;
+
+			/* wait until the Arc has generated an interrupt
+			 * which will wake us up */
+			spin_lock_irqsave(&par->lock, flags);
+			prepare_to_wait(&arcfb_waitq, &wait,
+					TASK_INTERRUPTIBLE);
+			spin_unlock_irqrestore(&par->lock, flags);
+			schedule();
+			finish_wait(&arcfb_waitq, &wait);
+		}
+		case FBIO_GETCONTROL2:
+		{
+			unsigned char ctl2;
+
+			ctl2 = ks108_readb_ctl2(info->par);
+			if (copy_to_user(argp, &ctl2, sizeof(ctl2)))
+				return -EFAULT;
+			return 0;
+		}
+		default:
+			return -EINVAL;
+	}
+}
+
+/*
+ * this is the access path from userspace. they can seek and write to
+ * the fb. it's inefficient for them to do anything less than 64*8
+ * writes since we update the lcd in each write() anyway.
+ */
+static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
+			   size_t count, loff_t *ppos)
+{
+	/* modded from epson 1355 */
+
+	unsigned long p;
+	int err=-EINVAL;
+	unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
+	struct arcfb_par *par;
+	unsigned int xres;
+
+	p = *ppos;
+	par = info->par;
+	xres = info->var.xres;
+	fbmemlength = (xres * info->var.yres)/8;
+
+	if (p > fbmemlength)
+		return -ENOSPC;
+
+	err = 0;
+	if ((count + p) > fbmemlength) {
+		count = fbmemlength - p;
+		err = -ENOSPC;
+	}
+
+	if (count) {
+		char *base_addr;
+
+		base_addr = (char __force *)info->screen_base;
+		count -= copy_from_user(base_addr + p, buf, count);
+		*ppos += count;
+		err = -EFAULT;
+	}
+
+
+	bitppos = p*8;
+	startpos = floorXres(bitppos, xres);
+	endpos = ceilXres((bitppos + (count*8)), xres);
+	bitcount = endpos - startpos;
+
+	x = startpos % xres;
+	y = startpos / xres;
+	w = xres;
+	h = bitcount / xres;
+	arcfb_lcd_update(par, x, y, w, h);
+
+	if (count)
+		return count;
+	return err;
+}
+
+static struct fb_ops arcfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= arcfb_open,
+	.fb_read        = fb_sys_read,
+	.fb_write	= arcfb_write,
+	.fb_release	= arcfb_release,
+	.fb_pan_display	= arcfb_pan_display,
+	.fb_fillrect	= arcfb_fillrect,
+	.fb_copyarea	= arcfb_copyarea,
+	.fb_imageblit	= arcfb_imageblit,
+	.fb_ioctl 	= arcfb_ioctl,
+};
+
+static int arcfb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	int videomemorysize;
+	unsigned char *videomemory;
+	struct arcfb_par *par;
+	int i;
+
+	videomemorysize = (((64*64)*num_cols)*num_rows)/8;
+
+	/* We need a flat backing store for the Arc's
+	   less-flat actual paged framebuffer */
+	videomemory = vzalloc(videomemorysize);
+	if (!videomemory)
+		return retval;
+
+	info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
+	if (!info)
+		goto err;
+
+	info->screen_base = (char __iomem *)videomemory;
+	info->fbops = &arcfb_ops;
+
+	info->var = arcfb_var;
+	info->fix = arcfb_fix;
+	par = info->par;
+	par->info = info;
+
+	if (!dio_addr || !cio_addr || !c2io_addr) {
+		printk(KERN_WARNING "no IO addresses supplied\n");
+		goto err1;
+	}
+	par->dio_addr = dio_addr;
+	par->cio_addr = cio_addr;
+	par->c2io_addr = c2io_addr;
+	par->cslut[0] = 0x00;
+	par->cslut[1] = 0x06;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	spin_lock_init(&par->lock);
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err1;
+	platform_set_drvdata(dev, info);
+	if (irq) {
+		par->irq = irq;
+		if (request_irq(par->irq, &arcfb_interrupt, IRQF_SHARED,
+				"arcfb", info)) {
+			printk(KERN_INFO
+				"arcfb: Failed req IRQ %d\n", par->irq);
+			retval = -EBUSY;
+			goto err1;
+		}
+	}
+	fb_info(info, "Arc frame buffer device, using %dK of video memory\n",
+		videomemorysize >> 10);
+
+	/* this inits the lcd but doesn't clear dirty pixels */
+	for (i = 0; i < num_cols * num_rows; i++) {
+		ks108_writeb_ctl(par, i, KS_DPY_OFF);
+		ks108_set_start_line(par, i, 0);
+		ks108_set_yaddr(par, i, 0);
+		ks108_set_xaddr(par, i, 0);
+		ks108_writeb_ctl(par, i, KS_DPY_ON);
+	}
+
+	/* if we were told to splash the screen, we just clear it */
+	if (!nosplash) {
+		for (i = 0; i < num_cols * num_rows; i++) {
+			fb_info(info, "splashing lcd %d\n", i);
+			ks108_set_start_line(par, i, 0);
+			ks108_clear_lcd(par, i);
+		}
+	}
+
+	return 0;
+err1:
+	framebuffer_release(info);
+err:
+	vfree(videomemory);
+	return retval;
+}
+
+static int arcfb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		vfree((void __force *)info->screen_base);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct platform_driver arcfb_driver = {
+	.probe	= arcfb_probe,
+	.remove = arcfb_remove,
+	.driver	= {
+		.name	= "arcfb",
+	},
+};
+
+static struct platform_device *arcfb_device;
+
+static int __init arcfb_init(void)
+{
+	int ret;
+
+	if (!arcfb_enable)
+		return -ENXIO;
+
+	ret = platform_driver_register(&arcfb_driver);
+	if (!ret) {
+		arcfb_device = platform_device_alloc("arcfb", 0);
+		if (arcfb_device) {
+			ret = platform_device_add(arcfb_device);
+		} else {
+			ret = -ENOMEM;
+		}
+		if (ret) {
+			platform_device_put(arcfb_device);
+			platform_driver_unregister(&arcfb_driver);
+		}
+	}
+	return ret;
+
+}
+
+static void __exit arcfb_exit(void)
+{
+	platform_device_unregister(arcfb_device);
+	platform_driver_unregister(&arcfb_driver);
+}
+
+module_param(num_cols, ulong, 0);
+MODULE_PARM_DESC(num_cols, "Num horiz panels, eg: 2 = 128 bit wide");
+module_param(num_rows, ulong, 0);
+MODULE_PARM_DESC(num_rows, "Num vert panels, eg: 1 = 64 bit high");
+module_param(nosplash, uint, 0);
+MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
+module_param(arcfb_enable, uint, 0);
+MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
+module_param(dio_addr, ulong, 0);
+MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
+module_param(cio_addr, ulong, 0);
+MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
+module_param(c2io_addr, ulong, 0);
+MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
+module_param(splashval, ulong, 0);
+MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
+module_param(tuhold, ulong, 0);
+MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
+module_param(irq, uint, 0);
+MODULE_PARM_DESC(irq, "IRQ for the Arc board");
+
+module_init(arcfb_init);
+module_exit(arcfb_exit);
+
+MODULE_DESCRIPTION("fbdev driver for Arc monochrome LCD board");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/arkfb.c b/drivers/video/fbdev/arkfb.c
new file mode 100644
index 000000000000..adc4ea2cc5a0
--- /dev/null
+++ b/drivers/video/fbdev/arkfb.c
@@ -0,0 +1,1231 @@
+/*
+ *  linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV
+ *  with ICS 5342 dac (it is easy to add support for different dacs).
+ *
+ *  Copyright (c) 2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *  Code is based on s3fb
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+struct arkfb_info {
+	int mclk_freq;
+	int mtrr_reg;
+
+	struct dac_info *dac;
+	struct vgastate state;
+	struct mutex open_lock;
+	unsigned int ref_count;
+	u32 pseudo_palette[16];
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static const struct svga_fb_format arkfb_formats[] = {
+	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 8},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
+		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 8},
+	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
+	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
+	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 8, 8},
+	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 2},
+	SVGA_FORMAT_END
+};
+
+
+/* CRT timing register sets */
+
+static const struct vga_regset ark_h_total_regs[]        = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END};
+static const struct vga_regset ark_h_display_regs[]      = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END};
+static const struct vga_regset ark_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7	}, VGA_REGSET_END};
+static const struct vga_regset ark_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset ark_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
+
+static const struct vga_regset ark_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END};
+static const struct vga_regset ark_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END};
+// const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
+static const struct vga_regset ark_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset ark_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
+
+static const struct vga_regset ark_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset ark_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
+static const struct vga_regset ark_offset_regs[]         = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
+
+static const struct svga_timing_regs ark_timing_regs     = {
+	ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs,
+	ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs,
+	ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs,
+	ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Module parameters */
+
+static char *mode_option = "640x480-8@60";
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
+
+module_param(mode_option, charp, 0444);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+module_param_named(mode, mode_option, charp, 0444);
+MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
+
+static int threshold = 4;
+
+module_param(threshold, int, 0644);
+MODULE_PARM_DESC(threshold, "FIFO threshold");
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+		       map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (c = 0; c < map->length; c++) {
+		for (i = 0; i < map->height; i++) {
+			fb_writeb(font[i], &fb[i * 4]);
+			fb_writeb(font[i], &fb[i * 4 + (128 * 8)]);
+		}
+		fb += 128;
+
+		if ((c % 8) == 7)
+			fb += 128*8;
+
+		font += map->height;
+	}
+}
+
+static void arkfb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
+{
+	struct arkfb_info *par = info->par;
+
+	svga_tilecursor(par->state.vgabase, info, cursor);
+}
+
+static struct fb_tile_ops arkfb_tile_ops = {
+	.fb_settile	= arkfb_settile,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = arkfb_tilecursor,
+	.fb_get_tilemax = svga_get_tilemax,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* image data is MSB-first, fb structure is MSB-first too */
+static inline u32 expand_color(u32 c)
+{
+	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
+}
+
+/* arkfb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void arkfb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = expand_color(image->fg_color);
+	u32 bg = expand_color(image->bg_color);
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = *(src++) * 0x01010101;
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+
+}
+
+/* arkfb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
+static void arkfb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u32 fg = expand_color(rect->color);
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	int x, y;
+
+	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
+		 + ((rect->dx / 8) * 4);
+
+	for (y = 0; y < rect->height; y++) {
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < rect->width; x += 8) {
+			fb_writel(fg, dst++);
+		}
+		dst1 += info->fix.line_length;
+	}
+
+}
+
+
+/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
+static inline u32 expand_pixel(u32 c)
+{
+	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
+		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
+}
+
+/* arkfb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void arkfb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = image->fg_color * 0x11111111;
+	u32 bg = image->bg_color * 0x11111111;
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = expand_pixel(*(src++));
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+
+}
+
+static void arkfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
+	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
+		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
+			arkfb_iplan_imageblit(info, image);
+		else
+			arkfb_cfb4_imageblit(info, image);
+	} else
+		cfb_imageblit(info, image);
+}
+
+static void arkfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	if ((info->var.bits_per_pixel == 4)
+	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
+	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
+		arkfb_iplan_fillrect(info, rect);
+	 else
+		cfb_fillrect(info, rect);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+enum
+{
+	DAC_PSEUDO8_8,
+	DAC_RGB1555_8,
+	DAC_RGB0565_8,
+	DAC_RGB0888_8,
+	DAC_RGB8888_8,
+	DAC_PSEUDO8_16,
+	DAC_RGB1555_16,
+	DAC_RGB0565_16,
+	DAC_RGB0888_16,
+	DAC_RGB8888_16,
+	DAC_MAX
+};
+
+struct dac_ops {
+	int (*dac_get_mode)(struct dac_info *info);
+	int (*dac_set_mode)(struct dac_info *info, int mode);
+	int (*dac_get_freq)(struct dac_info *info, int channel);
+	int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq);
+	void (*dac_release)(struct dac_info *info);
+};
+
+typedef void (*dac_read_regs_t)(void *data, u8 *code, int count);
+typedef void (*dac_write_regs_t)(void *data, u8 *code, int count);
+
+struct dac_info
+{
+	struct dac_ops *dacops;
+	dac_read_regs_t dac_read_regs;
+	dac_write_regs_t dac_write_regs;
+	void *data;
+};
+
+
+static inline u8 dac_read_reg(struct dac_info *info, u8 reg)
+{
+	u8 code[2] = {reg, 0};
+	info->dac_read_regs(info->data, code, 1);
+	return code[1];
+}
+
+static inline void dac_read_regs(struct dac_info *info, u8 *code, int count)
+{
+	info->dac_read_regs(info->data, code, count);
+}
+
+static inline void dac_write_reg(struct dac_info *info, u8 reg, u8 val)
+{
+	u8 code[2] = {reg, val};
+	info->dac_write_regs(info->data, code, 1);
+}
+
+static inline void dac_write_regs(struct dac_info *info, u8 *code, int count)
+{
+	info->dac_write_regs(info->data, code, count);
+}
+
+static inline int dac_set_mode(struct dac_info *info, int mode)
+{
+	return info->dacops->dac_set_mode(info, mode);
+}
+
+static inline int dac_set_freq(struct dac_info *info, int channel, u32 freq)
+{
+	return info->dacops->dac_set_freq(info, channel, freq);
+}
+
+static inline void dac_release(struct dac_info *info)
+{
+	info->dacops->dac_release(info);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* ICS5342 DAC */
+
+struct ics5342_info
+{
+	struct dac_info dac;
+	u8 mode;
+};
+
+#define DAC_PAR(info) ((struct ics5342_info *) info)
+
+/* LSB is set to distinguish unused slots */
+static const u8 ics5342_mode_table[DAC_MAX] = {
+	[DAC_PSEUDO8_8]  = 0x01, [DAC_RGB1555_8]  = 0x21, [DAC_RGB0565_8]  = 0x61,
+	[DAC_RGB0888_8]  = 0x41, [DAC_PSEUDO8_16] = 0x11, [DAC_RGB1555_16] = 0x31,
+	[DAC_RGB0565_16] = 0x51, [DAC_RGB0888_16] = 0x91, [DAC_RGB8888_16] = 0x71
+};
+
+static int ics5342_set_mode(struct dac_info *info, int mode)
+{
+	u8 code;
+
+	if (mode >= DAC_MAX)
+		return -EINVAL;
+
+	code = ics5342_mode_table[mode];
+
+	if (! code)
+		return -EINVAL;
+
+	dac_write_reg(info, 6, code & 0xF0);
+	DAC_PAR(info)->mode = mode;
+
+	return 0;
+}
+
+static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3,
+	60000, 250000, 14318};
+
+/* pd4 - allow only posdivider 4 (r=2) */
+static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2,
+	60000, 335000, 14318};
+
+/* 270 MHz should be upper bound for VCO clock according to specs,
+   but that is too restrictive in pd4 case */
+
+static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq)
+{
+	u16 m, n, r;
+
+	/* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */
+	int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16)
+				  ? &ics5342_pll_pd4 : &ics5342_pll,
+				  freq, &m, &n, &r, 0);
+
+	if (rv < 0) {
+		return -EINVAL;
+	} else {
+		u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)};
+		dac_write_regs(info, code, 3);
+		return 0;
+	}
+}
+
+static void ics5342_release(struct dac_info *info)
+{
+	ics5342_set_mode(info, DAC_PSEUDO8_8);
+	kfree(info);
+}
+
+static struct dac_ops ics5342_ops = {
+	.dac_set_mode	= ics5342_set_mode,
+	.dac_set_freq	= ics5342_set_freq,
+	.dac_release	= ics5342_release
+};
+
+
+static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data)
+{
+	struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL);
+
+	if (! info)
+		return NULL;
+
+	info->dacops = &ics5342_ops;
+	info->dac_read_regs = drr;
+	info->dac_write_regs = dwr;
+	info->data = data;
+	DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */
+	return info;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};
+
+static void ark_dac_read_regs(void *data, u8 *code, int count)
+{
+	struct fb_info *info = data;
+	struct arkfb_info *par;
+	u8 regval;
+
+	par = info->par;
+	regval = vga_rseq(par->state.vgabase, 0x1C);
+	while (count != 0)
+	{
+		vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
+		code[1] = vga_r(par->state.vgabase, dac_regs[code[0] & 3]);
+		count--;
+		code += 2;
+	}
+
+	vga_wseq(par->state.vgabase, 0x1C, regval);
+}
+
+static void ark_dac_write_regs(void *data, u8 *code, int count)
+{
+	struct fb_info *info = data;
+	struct arkfb_info *par;
+	u8 regval;
+
+	par = info->par;
+	regval = vga_rseq(par->state.vgabase, 0x1C);
+	while (count != 0)
+	{
+		vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
+		vga_w(par->state.vgabase, dac_regs[code[0] & 3], code[1]);
+		count--;
+		code += 2;
+	}
+
+	vga_wseq(par->state.vgabase, 0x1C, regval);
+}
+
+
+static void ark_set_pixclock(struct fb_info *info, u32 pixclock)
+{
+	struct arkfb_info *par = info->par;
+	u8 regval;
+
+	int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
+	if (rv < 0) {
+		fb_err(info, "cannot set requested pixclock, keeping old value\n");
+		return;
+	}
+
+	/* Set VGA misc register  */
+	regval = vga_r(par->state.vgabase, VGA_MIS_R);
+	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
+}
+
+
+/* Open framebuffer */
+
+static int arkfb_open(struct fb_info *info, int user)
+{
+	struct arkfb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		void __iomem *vgabase = par->state.vgabase;
+
+		memset(&(par->state), 0, sizeof(struct vgastate));
+		par->state.vgabase = vgabase;
+		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
+		par->state.num_crtc = 0x60;
+		par->state.num_seq = 0x30;
+		save_vga(&(par->state));
+	}
+
+	par->ref_count++;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Close framebuffer */
+
+static int arkfb_release(struct fb_info *info, int user)
+{
+	struct arkfb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		return -EINVAL;
+	}
+
+	if (par->ref_count == 1) {
+		restore_vga(&(par->state));
+		dac_set_mode(par->dac, DAC_PSEUDO8_8);
+	}
+
+	par->ref_count--;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Validate passed in var */
+
+static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int rv, mem, step;
+
+	/* Find appropriate format */
+	rv = svga_match_format (arkfb_formats, var, NULL);
+	if (rv < 0)
+	{
+		fb_err(info, "unsupported mode requested\n");
+		return rv;
+	}
+
+	/* Do not allow to have real resoulution larger than virtual */
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	/* Round up xres_virtual to have proper alignment of lines */
+	step = arkfb_formats[rv].xresstep - 1;
+	var->xres_virtual = (var->xres_virtual+step) & ~step;
+
+
+	/* Check whether have enough memory */
+	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
+	if (mem > info->screen_size)
+	{
+		fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n",
+		       mem >> 10, (unsigned int) (info->screen_size >> 10));
+		return -EINVAL;
+	}
+
+	rv = svga_check_timings (&ark_timing_regs, var, info->node);
+	if (rv < 0)
+	{
+		fb_err(info, "invalid timings requested\n");
+		return rv;
+	}
+
+	/* Interlaced mode is broken */
+	if (var->vmode & FB_VMODE_INTERLACED)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Set video mode from par */
+
+static int arkfb_set_par(struct fb_info *info)
+{
+	struct arkfb_info *par = info->par;
+	u32 value, mode, hmul, hdiv, offset_value, screen_size;
+	u32 bpp = info->var.bits_per_pixel;
+	u8 regval;
+
+	if (bpp != 0) {
+		info->fix.ypanstep = 1;
+		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
+
+		info->flags &= ~FBINFO_MISC_TILEBLITTING;
+		info->tileops = NULL;
+
+		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
+		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
+		info->pixmap.blit_y = ~(u32)0;
+
+		offset_value = (info->var.xres_virtual * bpp) / 64;
+		screen_size = info->var.yres_virtual * info->fix.line_length;
+	} else {
+		info->fix.ypanstep = 16;
+		info->fix.line_length = 0;
+
+		info->flags |= FBINFO_MISC_TILEBLITTING;
+		info->tileops = &arkfb_tile_ops;
+
+		/* supports 8x16 tiles only */
+		info->pixmap.blit_x = 1 << (8 - 1);
+		info->pixmap.blit_y = 1 << (16 - 1);
+
+		offset_value = info->var.xres_virtual / 16;
+		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
+	}
+
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	/* Unlock registers */
+	svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
+
+	/* Blank screen and turn off sync */
+	svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+	svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
+
+	/* Set default values */
+	svga_set_default_gfx_regs(par->state.vgabase);
+	svga_set_default_atc_regs(par->state.vgabase);
+	svga_set_default_seq_regs(par->state.vgabase);
+	svga_set_default_crt_regs(par->state.vgabase);
+	svga_wcrt_multi(par->state.vgabase, ark_line_compare_regs, 0xFFFFFFFF);
+	svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, 0);
+
+	/* ARK specific initialization */
+	svga_wseq_mask(par->state.vgabase, 0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */
+	svga_wseq_mask(par->state.vgabase, 0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */
+
+	vga_wseq(par->state.vgabase, 0x13, info->fix.smem_start >> 16);
+	vga_wseq(par->state.vgabase, 0x14, info->fix.smem_start >> 24);
+	vga_wseq(par->state.vgabase, 0x15, 0);
+	vga_wseq(par->state.vgabase, 0x16, 0);
+
+	/* Set the FIFO threshold register */
+	/* It is fascinating way to store 5-bit value in 8-bit register */
+	regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;
+	vga_wseq(par->state.vgabase, 0x18, regval);
+
+	/* Set the offset register */
+	fb_dbg(info, "offset register       : %d\n", offset_value);
+	svga_wcrt_multi(par->state.vgabase, ark_offset_regs, offset_value);
+
+	/* fix for hi-res textmode */
+	svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08);
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
+	else
+		svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		svga_wcrt_mask(par->state.vgabase, 0x44, 0x04, 0x04);
+	else
+		svga_wcrt_mask(par->state.vgabase, 0x44, 0x00, 0x04);
+
+	hmul = 1;
+	hdiv = 1;
+	mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix));
+
+	/* Set mode-specific register values */
+	switch (mode) {
+	case 0:
+		fb_dbg(info, "text mode\n");
+		svga_set_textmode_vga_regs(par->state.vgabase);
+
+		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
+		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
+		dac_set_mode(par->dac, DAC_PSEUDO8_8);
+
+		break;
+	case 1:
+		fb_dbg(info, "4 bit pseudocolor\n");
+		vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
+
+		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
+		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
+		dac_set_mode(par->dac, DAC_PSEUDO8_8);
+		break;
+	case 2:
+		fb_dbg(info, "4 bit pseudocolor, planar\n");
+
+		vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
+		svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
+		dac_set_mode(par->dac, DAC_PSEUDO8_8);
+		break;
+	case 3:
+		fb_dbg(info, "8 bit pseudocolor\n");
+
+		vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode */
+
+		if (info->var.pixclock > 20000) {
+			fb_dbg(info, "not using multiplex\n");
+			svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
+			dac_set_mode(par->dac, DAC_PSEUDO8_8);
+		} else {
+			fb_dbg(info, "using multiplex\n");
+			svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
+			dac_set_mode(par->dac, DAC_PSEUDO8_16);
+			hdiv = 2;
+		}
+		break;
+	case 4:
+		fb_dbg(info, "5/5/5 truecolor\n");
+
+		vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
+		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
+		dac_set_mode(par->dac, DAC_RGB1555_16);
+		break;
+	case 5:
+		fb_dbg(info, "5/6/5 truecolor\n");
+
+		vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
+		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
+		dac_set_mode(par->dac, DAC_RGB0565_16);
+		break;
+	case 6:
+		fb_dbg(info, "8/8/8 truecolor\n");
+
+		vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode ??? */
+		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
+		dac_set_mode(par->dac, DAC_RGB0888_16);
+		hmul = 3;
+		hdiv = 2;
+		break;
+	case 7:
+		fb_dbg(info, "8/8/8/8 truecolor\n");
+
+		vga_wseq(par->state.vgabase, 0x11, 0x1E); /* 32bpp accel mode */
+		svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
+		dac_set_mode(par->dac, DAC_RGB8888_16);
+		hmul = 2;
+		break;
+	default:
+		fb_err(info, "unsupported mode - bug\n");
+		return -EINVAL;
+	}
+
+	ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
+	svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv,
+			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
+			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
+			  hmul, info->node);
+
+	/* Set interlaced mode start/end register */
+	value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
+	value = ((value * hmul / hdiv) / 8) - 5;
+	vga_wcrt(par->state.vgabase, 0x42, (value + 1) / 2);
+
+	memset_io(info->screen_base, 0x00, screen_size);
+	/* Device and screen back on */
+	svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
+	svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
+
+	return 0;
+}
+
+/* Set a colour register */
+
+static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+				u_int transp, struct fb_info *fb)
+{
+	switch (fb->var.bits_per_pixel) {
+	case 0:
+	case 4:
+		if (regno >= 16)
+			return -EINVAL;
+
+		if ((fb->var.bits_per_pixel == 4) &&
+		    (fb->var.nonstd == 0)) {
+			outb(0xF0, VGA_PEL_MSK);
+			outb(regno*16, VGA_PEL_IW);
+		} else {
+			outb(0x0F, VGA_PEL_MSK);
+			outb(regno, VGA_PEL_IW);
+		}
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 8:
+		if (regno >= 256)
+			return -EINVAL;
+
+		outb(0xFF, VGA_PEL_MSK);
+		outb(regno, VGA_PEL_IW);
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 16:
+		if (regno >= 16)
+			return 0;
+
+		if (fb->var.green.length == 5)
+			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
+				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+		else if (fb->var.green.length == 6)
+			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
+				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+		else
+			return -EINVAL;
+		break;
+	case 24:
+	case 32:
+		if (regno >= 16)
+			return 0;
+
+		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
+			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Set the display blanking state */
+
+static int arkfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct arkfb_info *par = info->par;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		fb_dbg(info, "unblank\n");
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
+		svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
+		break;
+	case FB_BLANK_NORMAL:
+		fb_dbg(info, "blank\n");
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
+		break;
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+		fb_dbg(info, "sync down\n");
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
+		break;
+	}
+	return 0;
+}
+
+
+/* Pan the display */
+
+static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct arkfb_info *par = info->par;
+	unsigned int offset;
+
+	/* Calculate the offset */
+	if (info->var.bits_per_pixel == 0) {
+		offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
+		       + (var->xoffset / 2);
+		offset = offset >> 2;
+	} else {
+		offset = (var->yoffset * info->fix.line_length) +
+			 (var->xoffset * info->var.bits_per_pixel / 8);
+		offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3);
+	}
+
+	/* Set the offset */
+	svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, offset);
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Frame buffer operations */
+
+static struct fb_ops arkfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= arkfb_open,
+	.fb_release	= arkfb_release,
+	.fb_check_var	= arkfb_check_var,
+	.fb_set_par	= arkfb_set_par,
+	.fb_setcolreg	= arkfb_setcolreg,
+	.fb_blank	= arkfb_blank,
+	.fb_pan_display	= arkfb_pan_display,
+	.fb_fillrect	= arkfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= arkfb_imageblit,
+	.fb_get_caps    = svga_get_caps,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* PCI probe */
+static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct pci_bus_region bus_reg;
+	struct resource vga_res;
+	struct fb_info *info;
+	struct arkfb_info *par;
+	int rc;
+	u8 regval;
+
+	/* Ignore secondary VGA device because there is no VGA arbitration */
+	if (! svga_primary_device(dev)) {
+		dev_info(&(dev->dev), "ignoring secondary device\n");
+		return -ENODEV;
+	}
+
+	/* Allocate and fill driver data structure */
+	info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev));
+	if (! info) {
+		dev_err(&(dev->dev), "cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	mutex_init(&par->open_lock);
+
+	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+	info->fbops = &arkfb_ops;
+
+	/* Prepare PCI device */
+	rc = pci_enable_device(dev);
+	if (rc < 0) {
+		dev_err(info->device, "cannot enable PCI device\n");
+		goto err_enable_device;
+	}
+
+	rc = pci_request_regions(dev, "arkfb");
+	if (rc < 0) {
+		dev_err(info->device, "cannot reserve framebuffer region\n");
+		goto err_request_regions;
+	}
+
+	par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
+	if (! par->dac) {
+		rc = -ENOMEM;
+		dev_err(info->device, "RAMDAC initialization failed\n");
+		goto err_dac;
+	}
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = pci_resource_len(dev, 0);
+
+	/* Map physical IO memory address into kernel space */
+	info->screen_base = pci_iomap(dev, 0, 0);
+	if (! info->screen_base) {
+		rc = -ENOMEM;
+		dev_err(info->device, "iomap for framebuffer failed\n");
+		goto err_iomap;
+	}
+
+	bus_reg.start = 0;
+	bus_reg.end = 64 * 1024;
+
+	vga_res.flags = IORESOURCE_IO;
+
+	pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
+
+	par->state.vgabase = (void __iomem *) vga_res.start;
+
+	/* FIXME get memsize */
+	regval = vga_rseq(par->state.vgabase, 0x10);
+	info->screen_size = (1 << (regval >> 6)) << 20;
+	info->fix.smem_len = info->screen_size;
+
+	strcpy(info->fix.id, "ARK 2000PV");
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	info->fix.ypanstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->pseudo_palette = (void*) (par->pseudo_palette);
+
+	/* Prepare startup mode */
+	rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
+	if (! ((rc == 1) || (rc == 2))) {
+		rc = -EINVAL;
+		dev_err(info->device, "mode %s not found\n", mode_option);
+		goto err_find_mode;
+	}
+
+	rc = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (rc < 0) {
+		dev_err(info->device, "cannot allocate colormap\n");
+		goto err_alloc_cmap;
+	}
+
+	rc = register_framebuffer(info);
+	if (rc < 0) {
+		dev_err(info->device, "cannot register framebuffer\n");
+		goto err_reg_fb;
+	}
+
+	fb_info(info, "%s on %s, %d MB RAM\n",
+		info->fix.id, pci_name(dev), info->fix.smem_len >> 20);
+
+	/* Record a reference to the driver data */
+	pci_set_drvdata(dev, info);
+
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		par->mtrr_reg = -1;
+		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+	}
+#endif
+
+	return 0;
+
+	/* Error handling */
+err_reg_fb:
+	fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+	pci_iounmap(dev, info->screen_base);
+err_iomap:
+	dac_release(par->dac);
+err_dac:
+	pci_release_regions(dev);
+err_request_regions:
+/*	pci_disable_device(dev); */
+err_enable_device:
+	framebuffer_release(info);
+	return rc;
+}
+
+/* PCI remove */
+
+static void ark_pci_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+
+	if (info) {
+		struct arkfb_info *par = info->par;
+
+#ifdef CONFIG_MTRR
+		if (par->mtrr_reg >= 0) {
+			mtrr_del(par->mtrr_reg, 0, 0);
+			par->mtrr_reg = -1;
+		}
+#endif
+
+		dac_release(par->dac);
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+		pci_iounmap(dev, info->screen_base);
+		pci_release_regions(dev);
+/*		pci_disable_device(dev); */
+
+		framebuffer_release(info);
+	}
+}
+
+
+#ifdef CONFIG_PM
+/* PCI suspend */
+
+static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct arkfb_info *par = info->par;
+
+	dev_info(info->device, "suspend\n");
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
+		mutex_unlock(&(par->open_lock));
+		console_unlock();
+		return 0;
+	}
+
+	fb_set_suspend(info, 1);
+
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
+
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+
+	return 0;
+}
+
+
+/* PCI resume */
+
+static int ark_pci_resume (struct pci_dev* dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct arkfb_info *par = info->par;
+
+	dev_info(info->device, "resume\n");
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	if (par->ref_count == 0)
+		goto fail;
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+
+	if (pci_enable_device(dev))
+		goto fail;
+
+	pci_set_master(dev);
+
+	arkfb_set_par(info);
+	fb_set_suspend(info, 0);
+
+fail:
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+	return 0;
+}
+#else
+#define ark_pci_suspend NULL
+#define ark_pci_resume NULL
+#endif /* CONFIG_PM */
+
+/* List of boards that we are trying to support */
+
+static struct pci_device_id ark_devices[] = {
+	{PCI_DEVICE(0xEDD8, 0xA099)},
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+
+MODULE_DEVICE_TABLE(pci, ark_devices);
+
+static struct pci_driver arkfb_pci_driver = {
+	.name		= "arkfb",
+	.id_table	= ark_devices,
+	.probe		= ark_pci_probe,
+	.remove		= ark_pci_remove,
+	.suspend	= ark_pci_suspend,
+	.resume		= ark_pci_resume,
+};
+
+/* Cleanup */
+
+static void __exit arkfb_cleanup(void)
+{
+	pr_debug("arkfb: cleaning up\n");
+	pci_unregister_driver(&arkfb_pci_driver);
+}
+
+/* Driver Initialisation */
+
+static int __init arkfb_init(void)
+{
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("arkfb", &option))
+		return -ENODEV;
+
+	if (option && *option)
+		mode_option = option;
+#endif
+
+	pr_debug("arkfb: initializing\n");
+	return pci_register_driver(&arkfb_pci_driver);
+}
+
+module_init(arkfb_init);
+module_exit(arkfb_cleanup);
diff --git a/drivers/video/fbdev/asiliantfb.c b/drivers/video/fbdev/asiliantfb.c
new file mode 100644
index 000000000000..7e8ddf00ccc2
--- /dev/null
+++ b/drivers/video/fbdev/asiliantfb.c
@@ -0,0 +1,624 @@
+/*
+ * drivers/video/asiliantfb.c
+ *  frame buffer driver for Asiliant 69000 chip
+ *  Copyright (C) 2001-2003 Saito.K & Jeanne
+ *
+ *  from driver/video/chipsfb.c and,
+ *
+ *  drivers/video/asiliantfb.c -- frame buffer device for
+ *  Asiliant 69030 chip (formerly Intel, formerly Chips & Technologies)
+ *  Author: apc@agelectronics.co.uk
+ *  Copyright (C) 2000 AG Electronics
+ *  Note: the data sheets don't seem to be available from Asiliant.
+ *  They are available by searching developer.intel.com, but are not otherwise
+ *  linked to.
+ *
+ *  This driver should be portable with minimal effort to the 69000 display
+ *  chip, and to the twin-display mode of the 69030.
+ *  Contains code from Thomas Hhenleitner <th@visuelle-maschinen.de> (thanks)
+ *
+ *  Derived from the CT65550 driver chipsfb.c:
+ *  Copyright (C) 1998 Paul Mackerras
+ *  ...which was derived from the Powermac "chips" driver:
+ *  Copyright (C) 1997 Fabio Riccardi.
+ *  And from the frame buffer device for Open Firmware-initialized devices:
+ *  Copyright (C) 1997 Geert Uytterhoeven.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+/* Built in clock of the 69030 */
+static const unsigned Fref = 14318180;
+
+#define mmio_base (p->screen_base + 0x400000)
+
+#define mm_write_ind(num, val, ap, dp)	do { \
+	writeb((num), mmio_base + (ap)); writeb((val), mmio_base + (dp)); \
+} while (0)
+
+static void mm_write_xr(struct fb_info *p, u8 reg, u8 data)
+{
+	mm_write_ind(reg, data, 0x7ac, 0x7ad);
+}
+#define write_xr(num, val)	mm_write_xr(p, num, val)
+
+static void mm_write_fr(struct fb_info *p, u8 reg, u8 data)
+{
+	mm_write_ind(reg, data, 0x7a0, 0x7a1);
+}
+#define write_fr(num, val)	mm_write_fr(p, num, val)
+
+static void mm_write_cr(struct fb_info *p, u8 reg, u8 data)
+{
+	mm_write_ind(reg, data, 0x7a8, 0x7a9);
+}
+#define write_cr(num, val)	mm_write_cr(p, num, val)
+
+static void mm_write_gr(struct fb_info *p, u8 reg, u8 data)
+{
+	mm_write_ind(reg, data, 0x79c, 0x79d);
+}
+#define write_gr(num, val)	mm_write_gr(p, num, val)
+
+static void mm_write_sr(struct fb_info *p, u8 reg, u8 data)
+{
+	mm_write_ind(reg, data, 0x788, 0x789);
+}
+#define write_sr(num, val)	mm_write_sr(p, num, val)
+
+static void mm_write_ar(struct fb_info *p, u8 reg, u8 data)
+{
+	readb(mmio_base + 0x7b4);
+	mm_write_ind(reg, data, 0x780, 0x780);
+}
+#define write_ar(num, val)	mm_write_ar(p, num, val)
+
+static int asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
+static int asiliantfb_check_var(struct fb_var_screeninfo *var,
+				struct fb_info *info);
+static int asiliantfb_set_par(struct fb_info *info);
+static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+				u_int transp, struct fb_info *info);
+
+static struct fb_ops asiliantfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= asiliantfb_check_var,
+	.fb_set_par	= asiliantfb_set_par,
+	.fb_setcolreg	= asiliantfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/* Calculate the ratios for the dot clocks without using a single long long
+ * value */
+static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dclk2_div)
+{
+	unsigned pixclock = *ppixclock;
+	unsigned Ftarget = 1000000 * (1000000 / pixclock);
+	unsigned n;
+	unsigned best_error = 0xffffffff;
+	unsigned best_m = 0xffffffff,
+	         best_n = 0xffffffff;
+	unsigned ratio;
+	unsigned remainder;
+	unsigned char divisor = 0;
+
+	/* Calculate the frequency required. This is hard enough. */
+	ratio = 1000000 / pixclock;
+	remainder = 1000000 % pixclock;
+	Ftarget = 1000000 * ratio + (1000000 * remainder) / pixclock;
+
+	while (Ftarget < 100000000) {
+		divisor += 0x10;
+		Ftarget <<= 1;
+	}
+
+	ratio = Ftarget / Fref;
+	remainder = Ftarget % Fref;
+
+	/* This expresses the constraint that 150kHz <= Fref/n <= 5Mhz,
+	 * together with 3 <= n <= 257. */
+	for (n = 3; n <= 257; n++) {
+		unsigned m = n * ratio + (n * remainder) / Fref;
+
+		/* 3 <= m <= 257 */
+		if (m >= 3 && m <= 257) {
+			unsigned new_error = Ftarget * n >= Fref * m ?
+					       ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n));
+			if (new_error < best_error) {
+				best_n = n;
+				best_m = m;
+				best_error = new_error;
+			}
+		}
+		/* But if VLD = 4, then 4m <= 1028 */
+		else if (m <= 1028) {
+			/* remember there are still only 8-bits of precision in m, so
+			 * avoid over-optimistic error calculations */
+			unsigned new_error = Ftarget * n >= Fref * (m & ~3) ?
+					       ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n));
+			if (new_error < best_error) {
+				best_n = n;
+				best_m = m;
+				best_error = new_error;
+			}
+		}
+	}
+	if (best_m > 257)
+		best_m >>= 2;	/* divide m by 4, and leave VCO loop divide at 4 */
+	else
+		divisor |= 4;	/* or set VCO loop divide to 1 */
+	*dclk2_m = best_m - 2;
+	*dclk2_n = best_n - 2;
+	*dclk2_div = divisor;
+	*ppixclock = pixclock;
+	return;
+}
+
+static void asiliant_set_timing(struct fb_info *p)
+{
+	unsigned hd = p->var.xres / 8;
+	unsigned hs = (p->var.xres + p->var.right_margin) / 8;
+       	unsigned he = (p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
+	unsigned ht = (p->var.left_margin + p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
+	unsigned vd = p->var.yres;
+	unsigned vs = p->var.yres + p->var.lower_margin;
+	unsigned ve = p->var.yres + p->var.lower_margin + p->var.vsync_len;
+	unsigned vt = p->var.upper_margin + p->var.yres + p->var.lower_margin + p->var.vsync_len;
+	unsigned wd = (p->var.xres_virtual * ((p->var.bits_per_pixel+7)/8)) / 8;
+
+	if ((p->var.xres == 640) && (p->var.yres == 480) && (p->var.pixclock == 39722)) {
+	  write_fr(0x01, 0x02);  /* LCD */
+	} else {
+	  write_fr(0x01, 0x01);  /* CRT */
+	}
+
+	write_cr(0x11, (ve - 1) & 0x0f);
+	write_cr(0x00, (ht - 5) & 0xff);
+	write_cr(0x01, hd - 1);
+	write_cr(0x02, hd);
+	write_cr(0x03, ((ht - 1) & 0x1f) | 0x80);
+	write_cr(0x04, hs);
+	write_cr(0x05, (((ht - 1) & 0x20) <<2) | (he & 0x1f));
+	write_cr(0x3c, (ht - 1) & 0xc0);
+	write_cr(0x06, (vt - 2) & 0xff);
+	write_cr(0x30, (vt - 2) >> 8);
+	write_cr(0x07, 0x00);
+	write_cr(0x08, 0x00);
+	write_cr(0x09, 0x00);
+	write_cr(0x10, (vs - 1) & 0xff);
+	write_cr(0x32, ((vs - 1) >> 8) & 0xf);
+	write_cr(0x11, ((ve - 1) & 0x0f) | 0x80);
+	write_cr(0x12, (vd - 1) & 0xff);
+	write_cr(0x31, ((vd - 1) & 0xf00) >> 8);
+	write_cr(0x13, wd & 0xff);
+	write_cr(0x41, (wd & 0xf00) >> 8);
+	write_cr(0x15, (vs - 1) & 0xff);
+	write_cr(0x33, ((vs - 1) >> 8) & 0xf);
+	write_cr(0x38, ((ht - 5) & 0x100) >> 8);
+	write_cr(0x16, (vt - 1) & 0xff);
+	write_cr(0x18, 0x00);
+
+	if (p->var.xres == 640) {
+	  writeb(0xc7, mmio_base + 0x784);	/* set misc output reg */
+	} else {
+	  writeb(0x07, mmio_base + 0x784);	/* set misc output reg */
+	}
+}
+
+static int asiliantfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *p)
+{
+	unsigned long Ftarget, ratio, remainder;
+
+	ratio = 1000000 / var->pixclock;
+	remainder = 1000000 % var->pixclock;
+	Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock;
+
+	/* First check the constraint that the maximum post-VCO divisor is 32,
+	 * and the maximum Fvco is 220MHz */
+	if (Ftarget > 220000000 || Ftarget < 3125000) {
+		printk(KERN_ERR "asiliantfb dotclock must be between 3.125 and 220MHz\n");
+		return -ENXIO;
+	}
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	if (var->bits_per_pixel == 24) {
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = var->blue.length = var->green.length = 8;
+	} else if (var->bits_per_pixel == 16) {
+		switch (var->red.offset) {
+			case 11:
+				var->green.length = 6;
+				break;
+			case 10:
+				var->green.length = 5;
+				break;
+			default:
+				return -EINVAL;
+		}
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = var->blue.length = 5;
+	} else if (var->bits_per_pixel == 8) {
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+	}
+	return 0;
+}
+
+static int asiliantfb_set_par(struct fb_info *p)
+{
+	u8 dclk2_m;		/* Holds m-2 value for register */
+	u8 dclk2_n;		/* Holds n-2 value for register */
+	u8 dclk2_div;		/* Holds divisor bitmask */
+
+	/* Set pixclock */
+	asiliant_calc_dclk2(&p->var.pixclock, &dclk2_m, &dclk2_n, &dclk2_div);
+
+	/* Set color depth */
+	if (p->var.bits_per_pixel == 24) {
+		write_xr(0x81, 0x16);	/* 24 bit packed color mode */
+		write_xr(0x82, 0x00);	/* Disable palettes */
+		write_xr(0x20, 0x20);	/* 24 bit blitter mode */
+	} else if (p->var.bits_per_pixel == 16) {
+		if (p->var.red.offset == 11)
+			write_xr(0x81, 0x15);	/* 16 bit color mode */
+		else
+			write_xr(0x81, 0x14);	/* 15 bit color mode */
+		write_xr(0x82, 0x00);	/* Disable palettes */
+		write_xr(0x20, 0x10);	/* 16 bit blitter mode */
+	} else if (p->var.bits_per_pixel == 8) {
+		write_xr(0x0a, 0x02);	/* Linear */
+		write_xr(0x81, 0x12);	/* 8 bit color mode */
+		write_xr(0x82, 0x00);	/* Graphics gamma enable */
+		write_xr(0x20, 0x00);	/* 8 bit blitter mode */
+	}
+	p->fix.line_length = p->var.xres * (p->var.bits_per_pixel >> 3);
+	p->fix.visual = (p->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	write_xr(0xc4, dclk2_m);
+	write_xr(0xc5, dclk2_n);
+	write_xr(0xc7, dclk2_div);
+	/* Set up the CR registers */
+	asiliant_set_timing(p);
+	return 0;
+}
+
+static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *p)
+{
+	if (regno > 255)
+		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+        /* Set hardware palete */
+	writeb(regno, mmio_base + 0x790);
+	udelay(1);
+	writeb(red, mmio_base + 0x791);
+	writeb(green, mmio_base + 0x791);
+	writeb(blue, mmio_base + 0x791);
+
+	if (regno < 16) {
+		switch(p->var.red.offset) {
+		case 10: /* RGB 555 */
+			((u32 *)(p->pseudo_palette))[regno] =
+				((red & 0xf8) << 7) |
+				((green & 0xf8) << 2) |
+				((blue & 0xf8) >> 3);
+			break;
+		case 11: /* RGB 565 */
+			((u32 *)(p->pseudo_palette))[regno] =
+				((red & 0xf8) << 8) |
+				((green & 0xfc) << 3) |
+				((blue & 0xf8) >> 3);
+			break;
+		case 16: /* RGB 888 */
+			((u32 *)(p->pseudo_palette))[regno] =
+				(red << 16)  |
+				(green << 8) |
+				(blue);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+struct chips_init_reg {
+	unsigned char addr;
+	unsigned char data;
+};
+
+static struct chips_init_reg chips_init_sr[] =
+{
+	{0x00, 0x03},		/* Reset register */
+	{0x01, 0x01},		/* Clocking mode */
+	{0x02, 0x0f},		/* Plane mask */
+	{0x04, 0x0e}		/* Memory mode */
+};
+
+static struct chips_init_reg chips_init_gr[] =
+{
+        {0x03, 0x00},		/* Data rotate */
+	{0x05, 0x00},		/* Graphics mode */
+	{0x06, 0x01},		/* Miscellaneous */
+	{0x08, 0x00}		/* Bit mask */
+};
+
+static struct chips_init_reg chips_init_ar[] =
+{
+	{0x10, 0x01},		/* Mode control */
+	{0x11, 0x00},		/* Overscan */
+	{0x12, 0x0f},		/* Memory plane enable */
+	{0x13, 0x00}		/* Horizontal pixel panning */
+};
+
+static struct chips_init_reg chips_init_cr[] =
+{
+	{0x0c, 0x00},		/* Start address high */
+	{0x0d, 0x00},		/* Start address low */
+	{0x40, 0x00},		/* Extended Start Address */
+	{0x41, 0x00},		/* Extended Start Address */
+	{0x14, 0x00},		/* Underline location */
+	{0x17, 0xe3},		/* CRT mode control */
+	{0x70, 0x00}		/* Interlace control */
+};
+
+
+static struct chips_init_reg chips_init_fr[] =
+{
+	{0x01, 0x02},
+	{0x03, 0x08},
+	{0x08, 0xcc},
+	{0x0a, 0x08},
+	{0x18, 0x00},
+	{0x1e, 0x80},
+	{0x40, 0x83},
+	{0x41, 0x00},
+	{0x48, 0x13},
+	{0x4d, 0x60},
+	{0x4e, 0x0f},
+
+	{0x0b, 0x01},
+
+	{0x21, 0x51},
+	{0x22, 0x1d},
+	{0x23, 0x5f},
+	{0x20, 0x4f},
+	{0x34, 0x00},
+	{0x24, 0x51},
+	{0x25, 0x00},
+	{0x27, 0x0b},
+	{0x26, 0x00},
+	{0x37, 0x80},
+	{0x33, 0x0b},
+	{0x35, 0x11},
+	{0x36, 0x02},
+	{0x31, 0xea},
+	{0x32, 0x0c},
+	{0x30, 0xdf},
+	{0x10, 0x0c},
+	{0x11, 0xe0},
+	{0x12, 0x50},
+	{0x13, 0x00},
+	{0x16, 0x03},
+	{0x17, 0xbd},
+	{0x1a, 0x00},
+};
+
+
+static struct chips_init_reg chips_init_xr[] =
+{
+	{0xce, 0x00},		/* set default memory clock */
+	{0xcc, 200 },	        /* MCLK ratio M */
+	{0xcd, 18  },	        /* MCLK ratio N */
+	{0xce, 0x90},		/* MCLK divisor = 2 */
+
+	{0xc4, 209 },
+	{0xc5, 118 },
+	{0xc7, 32  },
+	{0xcf, 0x06},
+	{0x09, 0x01},		/* IO Control - CRT controller extensions */
+	{0x0a, 0x02},		/* Frame buffer mapping */
+	{0x0b, 0x01},		/* PCI burst write */
+	{0x40, 0x03},		/* Memory access control */
+	{0x80, 0x82},		/* Pixel pipeline configuration 0 */
+	{0x81, 0x12},		/* Pixel pipeline configuration 1 */
+	{0x82, 0x08},		/* Pixel pipeline configuration 2 */
+
+	{0xd0, 0x0f},
+	{0xd1, 0x01},
+};
+
+static void chips_hw_init(struct fb_info *p)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
+		write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
+	write_xr(0x81, 0x12);
+	write_xr(0x82, 0x08);
+	write_xr(0x20, 0x00);
+	for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
+		write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
+	for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
+		write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
+	for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
+		write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
+	/* Enable video output in attribute index register */
+	writeb(0x20, mmio_base + 0x780);
+	for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
+		write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
+	for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
+		write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
+}
+
+static struct fb_fix_screeninfo asiliantfb_fix = {
+	.id =		"Asiliant 69000",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.accel =	FB_ACCEL_NONE,
+	.line_length =	640,
+	.smem_len =	0x200000,	/* 2MB */
+};
+
+static struct fb_var_screeninfo asiliantfb_var = {
+	.xres 		= 640,
+	.yres 		= 480,
+	.xres_virtual 	= 640,
+	.yres_virtual 	= 480,
+	.bits_per_pixel = 8,
+	.red 		= { .length = 8 },
+	.green 		= { .length = 8 },
+	.blue 		= { .length = 8 },
+	.height 	= -1,
+	.width 		= -1,
+	.vmode 		= FB_VMODE_NONINTERLACED,
+	.pixclock 	= 39722,
+	.left_margin 	= 48,
+	.right_margin 	= 16,
+	.upper_margin 	= 33,
+	.lower_margin 	= 10,
+	.hsync_len 	= 96,
+	.vsync_len 	= 2,
+};
+
+static int init_asiliant(struct fb_info *p, unsigned long addr)
+{
+	int err;
+
+	p->fix			= asiliantfb_fix;
+	p->fix.smem_start	= addr;
+	p->var			= asiliantfb_var;
+	p->fbops		= &asiliantfb_ops;
+	p->flags		= FBINFO_DEFAULT;
+
+	err = fb_alloc_cmap(&p->cmap, 256, 0);
+	if (err) {
+		printk(KERN_ERR "C&T 69000 fb failed to alloc cmap memory\n");
+		return err;
+	}
+
+	err = register_framebuffer(p);
+	if (err < 0) {
+		printk(KERN_ERR "C&T 69000 framebuffer failed to register\n");
+		fb_dealloc_cmap(&p->cmap);
+		return err;
+	}
+
+	fb_info(p, "Asiliant 69000 frame buffer (%dK RAM detected)\n",
+		p->fix.smem_len / 1024);
+
+	writeb(0xff, mmio_base + 0x78c);
+	chips_hw_init(p);
+	return 0;
+}
+
+static int asiliantfb_pci_init(struct pci_dev *dp,
+			       const struct pci_device_id *ent)
+{
+	unsigned long addr, size;
+	struct fb_info *p;
+	int err;
+
+	if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
+		return -ENODEV;
+	addr = pci_resource_start(dp, 0);
+	size = pci_resource_len(dp, 0);
+	if (addr == 0)
+		return -ENODEV;
+	if (!request_mem_region(addr, size, "asiliantfb"))
+		return -EBUSY;
+
+	p = framebuffer_alloc(sizeof(u32) * 16, &dp->dev);
+	if (!p)	{
+		release_mem_region(addr, size);
+		return -ENOMEM;
+	}
+	p->pseudo_palette = p->par;
+	p->par = NULL;
+
+	p->screen_base = ioremap(addr, 0x800000);
+	if (p->screen_base == NULL) {
+		release_mem_region(addr, size);
+		framebuffer_release(p);
+		return -ENOMEM;
+	}
+
+	pci_write_config_dword(dp, 4, 0x02800083);
+	writeb(3, p->screen_base + 0x400784);
+
+	err = init_asiliant(p, addr);
+	if (err) {
+		iounmap(p->screen_base);
+		release_mem_region(addr, size);
+		framebuffer_release(p);
+		return err;
+	}
+
+	pci_set_drvdata(dp, p);
+	return 0;
+}
+
+static void asiliantfb_remove(struct pci_dev *dp)
+{
+	struct fb_info *p = pci_get_drvdata(dp);
+
+	unregister_framebuffer(p);
+	fb_dealloc_cmap(&p->cmap);
+	iounmap(p->screen_base);
+	release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0));
+	framebuffer_release(p);
+}
+
+static struct pci_device_id asiliantfb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000, PCI_ANY_ID, PCI_ANY_ID },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, asiliantfb_pci_tbl);
+
+static struct pci_driver asiliantfb_driver = {
+	.name =		"asiliantfb",
+	.id_table =	asiliantfb_pci_tbl,
+	.probe =	asiliantfb_pci_init,
+	.remove =	asiliantfb_remove,
+};
+
+static int __init asiliantfb_init(void)
+{
+	if (fb_get_options("asiliantfb", NULL))
+		return -ENODEV;
+
+	return pci_register_driver(&asiliantfb_driver);
+}
+
+module_init(asiliantfb_init);
+
+static void __exit asiliantfb_exit(void)
+{
+	pci_unregister_driver(&asiliantfb_driver);
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/atafb.c b/drivers/video/fbdev/atafb.c
new file mode 100644
index 000000000000..e21d1f58554c
--- /dev/null
+++ b/drivers/video/fbdev/atafb.c
@@ -0,0 +1,3266 @@
+/*
+ * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
+ *
+ *  Copyright (C) 1994 Martin Schaller & Roman Hodek
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * History:
+ *   - 03 Jan 95: Original version by Martin Schaller: The TT driver and
+ *                all the device independent stuff
+ *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
+ *                and wrote the Falcon, ST(E), and External drivers
+ *                based on the original TT driver.
+ *   - 07 May 95: Martin: Added colormap operations for the external driver
+ *   - 21 May 95: Martin: Added support for overscan
+ *		  Andreas: some bug fixes for this
+ *   -    Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
+ *                Programmable Falcon video modes
+ *                (thanks to Christian Cartus for documentation
+ *                of VIDEL registers).
+ *   - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
+ *                on minor 24...31. "user0" may be set on commandline by
+ *                "R<x>;<y>;<depth>". (Makes sense only on Falcon)
+ *                Video mode switch on Falcon now done at next VBL interrupt
+ *                to avoid the annoying right shift of the screen.
+ *   - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
+ *                The external-part is legacy, therefore hardware-specific
+ *                functions like panning/hardwarescrolling/blanking isn't
+ *				  supported.
+ *   - 29 Sep 97: Juergen: added Romans suggestion for pan_display
+ *				  (var->xoffset was changed even if no set_screen_base avail.)
+ *	 - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
+ *				  we know how to set the colors
+ *				  ext_*palette: read from ext_colors (former MV300_colors)
+ *							    write to ext_colors and RAMDAC
+ *
+ * To do:
+ *   - For the Falcon it is not possible to set random video modes on
+ *     SM124 and SC/TV, only the bootup resolution is supported.
+ *
+ */
+
+#define ATAFB_TT
+#define ATAFB_STE
+#define ATAFB_EXT
+#define ATAFB_FALCON
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <linux/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atari_stram.h>
+
+#include <linux/fb.h>
+#include <asm/atarikb.h>
+
+#include "c2p.h"
+#include "atafb.h"
+
+#define SWITCH_ACIA 0x01		/* modes for switch on OverScan */
+#define SWITCH_SND6 0x40
+#define SWITCH_SND7 0x80
+#define SWITCH_NONE 0x00
+
+
+#define up(x, r) (((x) + (r) - 1) & ~((r)-1))
+
+	/*
+	 * Interface to the world
+	 */
+
+static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+static int atafb_set_par(struct fb_info *info);
+static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+			   unsigned int blue, unsigned int transp,
+			   struct fb_info *info);
+static int atafb_blank(int blank, struct fb_info *info);
+static int atafb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static void atafb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect);
+static void atafb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *region);
+static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
+static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg);
+
+
+static int default_par;		/* default resolution (0=none) */
+
+static unsigned long default_mem_req;
+
+static int hwscroll = -1;
+
+static int use_hwscroll = 1;
+
+static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
+static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
+static int ovsc_offset, ovsc_addlen;
+
+	/*
+	 * Hardware parameters for current mode
+	 */
+
+static struct atafb_par {
+	void *screen_base;
+	int yres_virtual;
+	u_long next_line;
+#if defined ATAFB_TT || defined ATAFB_STE
+	union {
+		struct {
+			int mode;
+			int sync;
+		} tt, st;
+#endif
+#ifdef ATAFB_FALCON
+		struct falcon_hw {
+			/* Here are fields for storing a video mode, as direct
+			 * parameters for the hardware.
+			 */
+			short sync;
+			short line_width;
+			short line_offset;
+			short st_shift;
+			short f_shift;
+			short vid_control;
+			short vid_mode;
+			short xoffset;
+			short hht, hbb, hbe, hdb, hde, hss;
+			short vft, vbb, vbe, vdb, vde, vss;
+			/* auxiliary information */
+			short mono;
+			short ste_mode;
+			short bpp;
+			u32 pseudo_palette[16];
+		} falcon;
+#endif
+		/* Nothing needed for external mode */
+	} hw;
+} current_par;
+
+/* Don't calculate an own resolution, and thus don't change the one found when
+ * booting (currently used for the Falcon to keep settings for internal video
+ * hardware extensions (e.g. ScreenBlaster)  */
+static int DontCalcRes = 0;
+
+#ifdef ATAFB_FALCON
+#define HHT hw.falcon.hht
+#define HBB hw.falcon.hbb
+#define HBE hw.falcon.hbe
+#define HDB hw.falcon.hdb
+#define HDE hw.falcon.hde
+#define HSS hw.falcon.hss
+#define VFT hw.falcon.vft
+#define VBB hw.falcon.vbb
+#define VBE hw.falcon.vbe
+#define VDB hw.falcon.vdb
+#define VDE hw.falcon.vde
+#define VSS hw.falcon.vss
+#define VCO_CLOCK25		0x04
+#define VCO_CSYPOS		0x10
+#define VCO_VSYPOS		0x20
+#define VCO_HSYPOS		0x40
+#define VCO_SHORTOFFS	0x100
+#define VMO_DOUBLE		0x01
+#define VMO_INTER		0x02
+#define VMO_PREMASK		0x0c
+#endif
+
+static struct fb_info fb_info = {
+	.fix = {
+		.id	= "Atari ",
+		.visual	= FB_VISUAL_PSEUDOCOLOR,
+		.accel	= FB_ACCEL_NONE,
+	}
+};
+
+static void *screen_base;	/* base address of screen */
+static void *real_screen_base;	/* (only for Overscan) */
+
+static int screen_len;
+
+static int current_par_valid;
+
+static int mono_moni;
+
+
+#ifdef ATAFB_EXT
+
+/* external video handling */
+static unsigned int external_xres;
+static unsigned int external_xres_virtual;
+static unsigned int external_yres;
+
+/*
+ * not needed - atafb will never support panning/hardwarescroll with external
+ * static unsigned int external_yres_virtual;
+ */
+static unsigned int external_depth;
+static int external_pmode;
+static void *external_addr;
+static unsigned long external_len;
+static unsigned long external_vgaiobase;
+static unsigned int external_bitspercol = 6;
+
+/*
+ * JOE <joe@amber.dinoco.de>:
+ * added card type for external driver, is only needed for
+ * colormap handling.
+ */
+enum cardtype { IS_VGA, IS_MV300 };
+static enum cardtype external_card_type = IS_VGA;
+
+/*
+ * The MV300 mixes the color registers. So we need an array of munged
+ * indices in order to access the correct reg.
+ */
+static int MV300_reg_1bit[2] = {
+	0, 1
+};
+static int MV300_reg_4bit[16] = {
+	0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
+};
+static int MV300_reg_8bit[256] = {
+	0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
+	8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
+	4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
+	12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
+	2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
+	10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
+	6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
+	14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
+	1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
+	9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
+	5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
+	13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
+	3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
+	11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
+	7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
+	15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
+};
+
+static int *MV300_reg = MV300_reg_8bit;
+#endif /* ATAFB_EXT */
+
+
+static int inverse;
+
+extern int fontheight_8x8;
+extern int fontwidth_8x8;
+extern unsigned char fontdata_8x8[];
+
+extern int fontheight_8x16;
+extern int fontwidth_8x16;
+extern unsigned char fontdata_8x16[];
+
+/*
+ * struct fb_ops {
+ *	* open/release and usage marking
+ *	struct module *owner;
+ *	int (*fb_open)(struct fb_info *info, int user);
+ *	int (*fb_release)(struct fb_info *info, int user);
+ *
+ *	* For framebuffers with strange non linear layouts or that do not
+ *	* work with normal memory mapped access
+ *	ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
+ *	ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+ *
+ *	* checks var and eventually tweaks it to something supported,
+ *	* DOES NOT MODIFY PAR *
+ *	int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
+ *
+ *	* set the video mode according to info->var *
+ *	int (*fb_set_par)(struct fb_info *info);
+ *
+ *	* set color register *
+ *	int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
+ *			    unsigned int blue, unsigned int transp, struct fb_info *info);
+ *
+ *	* set color registers in batch *
+ *	int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
+ *
+ *	* blank display *
+ *	int (*fb_blank)(int blank, struct fb_info *info);
+ *
+ *	* pan display *
+ *	int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
+ *
+ *	*** The meat of the drawing engine ***
+ *	* Draws a rectangle *
+ *	void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
+ *	* Copy data from area to another *
+ *	void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
+ *	* Draws a image to the display *
+ *	void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
+ *
+ *	* Draws cursor *
+ *	int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
+ *
+ *	* Rotates the display *
+ *	void (*fb_rotate)(struct fb_info *info, int angle);
+ *
+ *	* wait for blit idle, optional *
+ *	int (*fb_sync)(struct fb_info *info);
+ *
+ *	* perform fb specific ioctl (optional) *
+ *	int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
+ *			unsigned long arg);
+ *
+ *	* Handle 32bit compat ioctl (optional) *
+ *	int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
+ *			unsigned long arg);
+ *
+ *	* perform fb specific mmap *
+ *	int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
+ * } ;
+ */
+
+
+/* ++roman: This structure abstracts from the underlying hardware (ST(e),
+ * TT, or Falcon.
+ *
+ * int (*detect)(void)
+ *   This function should detect the current video mode settings and
+ *   store them in atafb_predefined[0] for later reference by the
+ *   user. Return the index+1 of an equivalent predefined mode or 0
+ *   if there is no such.
+ *
+ * int (*encode_fix)(struct fb_fix_screeninfo *fix,
+ *                   struct atafb_par *par)
+ *   This function should fill in the 'fix' structure based on the
+ *   values in the 'par' structure.
+ * !!! Obsolete, perhaps !!!
+ *
+ * int (*decode_var)(struct fb_var_screeninfo *var,
+ *                   struct atafb_par *par)
+ *   Get the video params out of 'var'. If a value doesn't fit, round
+ *   it up, if it's too big, return EINVAL.
+ *   Round up in the following order: bits_per_pixel, xres, yres,
+ *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
+ *   horizontal timing, vertical timing.
+ *
+ * int (*encode_var)(struct fb_var_screeninfo *var,
+ *                   struct atafb_par *par);
+ *   Fill the 'var' structure based on the values in 'par' and maybe
+ *   other values read out of the hardware.
+ *
+ * void (*get_par)(struct atafb_par *par)
+ *   Fill the hardware's 'par' structure.
+ *   !!! Used only by detect() !!!
+ *
+ * void (*set_par)(struct atafb_par *par)
+ *   Set the hardware according to 'par'.
+ *
+ * void (*set_screen_base)(void *s_base)
+ *   Set the base address of the displayed frame buffer. Only called
+ *   if yres_virtual > yres or xres_virtual > xres.
+ *
+ * int (*blank)(int blank_mode)
+ *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
+ *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
+ *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
+ *   doesn't support it. Implements VESA suspend and powerdown modes on
+ *   hardware that supports disabling hsync/vsync:
+ *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
+ */
+
+static struct fb_hwswitch {
+	int (*detect)(void);
+	int (*encode_fix)(struct fb_fix_screeninfo *fix,
+			  struct atafb_par *par);
+	int (*decode_var)(struct fb_var_screeninfo *var,
+			  struct atafb_par *par);
+	int (*encode_var)(struct fb_var_screeninfo *var,
+			  struct atafb_par *par);
+	void (*get_par)(struct atafb_par *par);
+	void (*set_par)(struct atafb_par *par);
+	void (*set_screen_base)(void *s_base);
+	int (*blank)(int blank_mode);
+	int (*pan_display)(struct fb_var_screeninfo *var,
+			   struct fb_info *info);
+} *fbhw;
+
+static char *autodetect_names[] = { "autodetect", NULL };
+static char *stlow_names[] = { "stlow", NULL };
+static char *stmid_names[] = { "stmid", "default5", NULL };
+static char *sthigh_names[] = { "sthigh", "default4", NULL };
+static char *ttlow_names[] = { "ttlow", NULL };
+static char *ttmid_names[] = { "ttmid", "default1", NULL };
+static char *tthigh_names[] = { "tthigh", "default2", NULL };
+static char *vga2_names[] = { "vga2", NULL };
+static char *vga4_names[] = { "vga4", NULL };
+static char *vga16_names[] = { "vga16", "default3", NULL };
+static char *vga256_names[] = { "vga256", NULL };
+static char *falh2_names[] = { "falh2", NULL };
+static char *falh16_names[] = { "falh16", NULL };
+
+static char **fb_var_names[] = {
+	autodetect_names,
+	stlow_names,
+	stmid_names,
+	sthigh_names,
+	ttlow_names,
+	ttmid_names,
+	tthigh_names,
+	vga2_names,
+	vga4_names,
+	vga16_names,
+	vga256_names,
+	falh2_names,
+	falh16_names,
+	NULL
+};
+
+static struct fb_var_screeninfo atafb_predefined[] = {
+	/*
+	 * yres_virtual == 0 means use hw-scrolling if possible, else yres
+	 */
+	{ /* autodetect */
+	  0, 0, 0, 0, 0, 0, 0, 0,		/* xres-grayscale */
+	  {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},	/* red green blue tran*/
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* st low */
+	  320, 200, 320, 0, 0, 0, 4, 0,
+	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* st mid */
+	  640, 200, 640, 0, 0, 0, 2, 0,
+	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* st high */
+	  640, 400, 640, 0, 0, 0, 1, 0,
+	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* tt low */
+	  320, 480, 320, 0, 0, 0, 8, 0,
+	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* tt mid */
+	  640, 480, 640, 0, 0, 0, 4, 0,
+	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* tt high */
+	  1280, 960, 1280, 0, 0, 0, 1, 0,
+	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* vga2 */
+	  640, 480, 640, 0, 0, 0, 1, 0,
+	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* vga4 */
+	  640, 480, 640, 0, 0, 0, 2, 0,
+	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* vga16 */
+	  640, 480, 640, 0, 0, 0, 4, 0,
+	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* vga256 */
+	  640, 480, 640, 0, 0, 0, 8, 0,
+	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* falh2 */
+	  896, 608, 896, 0, 0, 0, 1, 0,
+	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ /* falh16 */
+	  896, 608, 896, 0, 0, 0, 4, 0,
+	  {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
+	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
+
+static struct fb_videomode atafb_modedb[] __initdata = {
+	/*
+	 *  Atari Video Modes
+	 *
+	 *  If you change these, make sure to update DEFMODE_* as well!
+	 */
+
+	/*
+	 *  ST/TT Video Modes
+	 */
+
+	{
+		/* 320x200, 15 kHz, 60 Hz (ST low) */
+		"st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x200, 15 kHz, 60 Hz (ST medium) */
+		"st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
+		"st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 320x480, 15 kHz, 60 Hz (TT low) */
+		"tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x480, 29 kHz, 57 Hz (TT medium) */
+		"tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 1280x960, 29 kHz, 60 Hz (TT high) */
+		"tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	},
+
+	/*
+	 *  VGA Video Modes
+	 */
+
+	{
+		/* 640x480, 31 kHz, 60 Hz (VGA) */
+		"vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 31 kHz, 70 Hz (VGA) */
+		"vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
+		FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	},
+
+	/*
+	 *  Falcon HiRes Video Modes
+	 */
+
+	{
+		/* 896x608, 31 kHz, 60 Hz (Falcon High) */
+		"falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	},
+};
+
+#define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
+
+static char *mode_option __initdata = NULL;
+
+ /* default modes */
+
+#define DEFMODE_TT	5		/* "tt-high" for TT */
+#define DEFMODE_F30	7		/* "vga70" for Falcon */
+#define DEFMODE_STE	2		/* "st-high" for ST/E */
+#define DEFMODE_EXT	6		/* "vga" for external */
+
+
+static int get_video_mode(char *vname)
+{
+	char ***name_list;
+	char **name;
+	int i;
+
+	name_list = fb_var_names;
+	for (i = 0; i < num_atafb_predefined; i++) {
+		name = *name_list++;
+		if (!name || !*name)
+			break;
+		while (*name) {
+			if (!strcmp(vname, *name))
+				return i + 1;
+			name++;
+		}
+	}
+	return 0;
+}
+
+
+
+/* ------------------- TT specific functions ---------------------- */
+
+#ifdef ATAFB_TT
+
+static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
+{
+	int mode;
+
+	strcpy(fix->id, "Atari Builtin");
+	fix->smem_start = (unsigned long)real_screen_base;
+	fix->smem_len = screen_len;
+	fix->type = FB_TYPE_INTERLEAVED_PLANES;
+	fix->type_aux = 2;
+	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
+	if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->type_aux = 0;
+		if (mode == TT_SHIFTER_TTHIGH)
+			fix->visual = FB_VISUAL_MONO01;
+	}
+	fix->xpanstep = 0;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->line_length = par->next_line;
+	fix->accel = FB_ACCEL_ATARIBLITT;
+	return 0;
+}
+
+static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+{
+	int xres = var->xres;
+	int yres = var->yres;
+	int bpp = var->bits_per_pixel;
+	int linelen;
+	int yres_virtual = var->yres_virtual;
+
+	if (mono_moni) {
+		if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
+			return -EINVAL;
+		par->hw.tt.mode = TT_SHIFTER_TTHIGH;
+		xres = sttt_xres * 2;
+		yres = tt_yres * 2;
+		bpp = 1;
+	} else {
+		if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
+			return -EINVAL;
+		if (bpp > 4) {
+			if (xres > sttt_xres / 2 || yres > tt_yres)
+				return -EINVAL;
+			par->hw.tt.mode = TT_SHIFTER_TTLOW;
+			xres = sttt_xres / 2;
+			yres = tt_yres;
+			bpp = 8;
+		} else if (bpp > 2) {
+			if (xres > sttt_xres || yres > tt_yres)
+				return -EINVAL;
+			if (xres > sttt_xres / 2 || yres > st_yres / 2) {
+				par->hw.tt.mode = TT_SHIFTER_TTMID;
+				xres = sttt_xres;
+				yres = tt_yres;
+				bpp = 4;
+			} else {
+				par->hw.tt.mode = TT_SHIFTER_STLOW;
+				xres = sttt_xres / 2;
+				yres = st_yres / 2;
+				bpp = 4;
+			}
+		} else if (bpp > 1) {
+			if (xres > sttt_xres || yres > st_yres / 2)
+				return -EINVAL;
+			par->hw.tt.mode = TT_SHIFTER_STMID;
+			xres = sttt_xres;
+			yres = st_yres / 2;
+			bpp = 2;
+		} else if (var->xres > sttt_xres || var->yres > st_yres) {
+			return -EINVAL;
+		} else {
+			par->hw.tt.mode = TT_SHIFTER_STHIGH;
+			xres = sttt_xres;
+			yres = st_yres;
+			bpp = 1;
+		}
+	}
+	if (yres_virtual <= 0)
+		yres_virtual = 0;
+	else if (yres_virtual < yres)
+		yres_virtual = yres;
+	if (var->sync & FB_SYNC_EXT)
+		par->hw.tt.sync = 0;
+	else
+		par->hw.tt.sync = 1;
+	linelen = xres * bpp / 8;
+	if (yres_virtual * linelen > screen_len && screen_len)
+		return -EINVAL;
+	if (yres * linelen > screen_len && screen_len)
+		return -EINVAL;
+	if (var->yoffset + yres > yres_virtual && yres_virtual)
+		return -EINVAL;
+	par->yres_virtual = yres_virtual;
+	par->screen_base = screen_base + var->yoffset * linelen;
+	par->next_line = linelen;
+	return 0;
+}
+
+static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+{
+	int linelen;
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+	var->red.offset = 0;
+	var->red.length = 4;
+	var->red.msb_right = 0;
+	var->grayscale = 0;
+
+	var->pixclock = 31041;
+	var->left_margin = 120;		/* these may be incorrect */
+	var->right_margin = 100;
+	var->upper_margin = 8;
+	var->lower_margin = 16;
+	var->hsync_len = 140;
+	var->vsync_len = 30;
+
+	var->height = -1;
+	var->width = -1;
+
+	if (par->hw.tt.sync & 1)
+		var->sync = 0;
+	else
+		var->sync = FB_SYNC_EXT;
+
+	switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
+	case TT_SHIFTER_STLOW:
+		var->xres = sttt_xres / 2;
+		var->xres_virtual = sttt_xres_virtual / 2;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 4;
+		break;
+	case TT_SHIFTER_STMID:
+		var->xres = sttt_xres;
+		var->xres_virtual = sttt_xres_virtual;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 2;
+		break;
+	case TT_SHIFTER_STHIGH:
+		var->xres = sttt_xres;
+		var->xres_virtual = sttt_xres_virtual;
+		var->yres = st_yres;
+		var->bits_per_pixel = 1;
+		break;
+	case TT_SHIFTER_TTLOW:
+		var->xres = sttt_xres / 2;
+		var->xres_virtual = sttt_xres_virtual / 2;
+		var->yres = tt_yres;
+		var->bits_per_pixel = 8;
+		break;
+	case TT_SHIFTER_TTMID:
+		var->xres = sttt_xres;
+		var->xres_virtual = sttt_xres_virtual;
+		var->yres = tt_yres;
+		var->bits_per_pixel = 4;
+		break;
+	case TT_SHIFTER_TTHIGH:
+		var->red.length = 0;
+		var->xres = sttt_xres * 2;
+		var->xres_virtual = sttt_xres_virtual * 2;
+		var->yres = tt_yres * 2;
+		var->bits_per_pixel = 1;
+		break;
+	}
+	var->blue = var->green = var->red;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	linelen = var->xres_virtual * var->bits_per_pixel / 8;
+	if (!use_hwscroll)
+		var->yres_virtual = var->yres;
+	else if (screen_len) {
+		if (par->yres_virtual)
+			var->yres_virtual = par->yres_virtual;
+		else
+			/* yres_virtual == 0 means use maximum */
+			var->yres_virtual = screen_len / linelen;
+	} else {
+		if (hwscroll < 0)
+			var->yres_virtual = 2 * var->yres;
+		else
+			var->yres_virtual = var->yres + hwscroll * 16;
+	}
+	var->xoffset = 0;
+	if (screen_base)
+		var->yoffset = (par->screen_base - screen_base) / linelen;
+	else
+		var->yoffset = 0;
+	var->nonstd = 0;
+	var->activate = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	return 0;
+}
+
+static void tt_get_par(struct atafb_par *par)
+{
+	unsigned long addr;
+	par->hw.tt.mode = shifter_tt.tt_shiftmode;
+	par->hw.tt.sync = shifter.syncmode;
+	addr = ((shifter.bas_hi & 0xff) << 16) |
+	       ((shifter.bas_md & 0xff) << 8)  |
+	       ((shifter.bas_lo & 0xff));
+	par->screen_base = phys_to_virt(addr);
+}
+
+static void tt_set_par(struct atafb_par *par)
+{
+	shifter_tt.tt_shiftmode = par->hw.tt.mode;
+	shifter.syncmode = par->hw.tt.sync;
+	/* only set screen_base if really necessary */
+	if (current_par.screen_base != par->screen_base)
+		fbhw->set_screen_base(par->screen_base);
+}
+
+static int tt_setcolreg(unsigned int regno, unsigned int red,
+			unsigned int green, unsigned int blue,
+			unsigned int transp, struct fb_info *info)
+{
+	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
+		regno += 254;
+	if (regno > 255)
+		return 1;
+	tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
+			     (blue >> 12));
+	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
+	    TT_SHIFTER_STHIGH && regno == 254)
+		tt_palette[0] = 0;
+	return 0;
+}
+
+static int tt_detect(void)
+{
+	struct atafb_par par;
+
+	/* Determine the connected monitor: The DMA sound must be
+	 * disabled before reading the MFP GPIP, because the Sound
+	 * Done Signal and the Monochrome Detect are XORed together!
+	 *
+	 * Even on a TT, we should look if there is a DMA sound. It was
+	 * announced that the Eagle is TT compatible, but only the PCM is
+	 * missing...
+	 */
+	if (ATARIHW_PRESENT(PCM_8BIT)) {
+		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+		udelay(20);		/* wait a while for things to settle down */
+	}
+	mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
+
+	tt_get_par(&par);
+	tt_encode_var(&atafb_predefined[0], &par);
+
+	return 1;
+}
+
+#endif /* ATAFB_TT */
+
+/* ------------------- Falcon specific functions ---------------------- */
+
+#ifdef ATAFB_FALCON
+
+static int mon_type;		/* Falcon connected monitor */
+static int f030_bus_width;	/* Falcon ram bus width (for vid_control) */
+#define F_MON_SM	0
+#define F_MON_SC	1
+#define F_MON_VGA	2
+#define F_MON_TV	3
+
+static struct pixel_clock {
+	unsigned long f;	/* f/[Hz] */
+	unsigned long t;	/* t/[ps] (=1/f) */
+	int right, hsync, left;	/* standard timing in clock cycles, not pixel */
+	/* hsync initialized in falcon_detect() */
+	int sync_mask;		/* or-mask for hw.falcon.sync to set this clock */
+	int control_mask;	/* ditto, for hw.falcon.vid_control */
+} f25 = {
+	25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
+}, f32 = {
+	32000000, 31250, 18, 0, 42, 0x0, 0
+}, fext = {
+	0, 0, 18, 0, 42, 0x1, 0
+};
+
+/* VIDEL-prescale values [mon_type][pixel_length from VCO] */
+static int vdl_prescale[4][3] = {
+	{ 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
+};
+
+/* Default hsync timing [mon_type] in picoseconds */
+static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
+
+static inline int hxx_prescale(struct falcon_hw *hw)
+{
+	return hw->ste_mode ? 16
+			    : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
+}
+
+static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
+			     struct atafb_par *par)
+{
+	strcpy(fix->id, "Atari Builtin");
+	fix->smem_start = (unsigned long)real_screen_base;
+	fix->smem_len = screen_len;
+	fix->type = FB_TYPE_INTERLEAVED_PLANES;
+	fix->type_aux = 2;
+	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	if (par->hw.falcon.mono) {
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->type_aux = 0;
+		/* no smooth scrolling with longword aligned video mem */
+		fix->xpanstep = 32;
+	} else if (par->hw.falcon.f_shift & 0x100) {
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->type_aux = 0;
+		/* Is this ok or should it be DIRECTCOLOR? */
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		fix->xpanstep = 2;
+	}
+	fix->line_length = par->next_line;
+	fix->accel = FB_ACCEL_ATARIBLITT;
+	return 0;
+}
+
+static int falcon_decode_var(struct fb_var_screeninfo *var,
+			     struct atafb_par *par)
+{
+	int bpp = var->bits_per_pixel;
+	int xres = var->xres;
+	int yres = var->yres;
+	int xres_virtual = var->xres_virtual;
+	int yres_virtual = var->yres_virtual;
+	int left_margin, right_margin, hsync_len;
+	int upper_margin, lower_margin, vsync_len;
+	int linelen;
+	int interlace = 0, doubleline = 0;
+	struct pixel_clock *pclock;
+	int plen;			/* width of pixel in clock cycles */
+	int xstretch;
+	int prescale;
+	int longoffset = 0;
+	int hfreq, vfreq;
+	int hdb_off, hde_off, base_off;
+	int gstart, gend1, gend2, align;
+
+/*
+	Get the video params out of 'var'. If a value doesn't fit, round
+	it up, if it's too big, return EINVAL.
+	Round up in the following order: bits_per_pixel, xres, yres,
+	xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
+	horizontal timing, vertical timing.
+
+	There is a maximum of screen resolution determined by pixelclock
+	and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
+	In interlace mode this is     "     *    "     *vfmin <= pixelclock.
+	Additional constraints: hfreq.
+	Frequency range for multisync monitors is given via command line.
+	For TV and SM124 both frequencies are fixed.
+
+	X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
+	Y % 16 == 0 to fit 8x16 font
+	Y % 8 == 0 if Y<400
+
+	Currently interlace and doubleline mode in var are ignored.
+	On SM124 and TV only the standard resolutions can be used.
+*/
+
+	/* Reject uninitialized mode */
+	if (!xres || !yres || !bpp)
+		return -EINVAL;
+
+	if (mon_type == F_MON_SM && bpp != 1)
+		return -EINVAL;
+
+	if (bpp <= 1) {
+		bpp = 1;
+		par->hw.falcon.f_shift = 0x400;
+		par->hw.falcon.st_shift = 0x200;
+	} else if (bpp <= 2) {
+		bpp = 2;
+		par->hw.falcon.f_shift = 0x000;
+		par->hw.falcon.st_shift = 0x100;
+	} else if (bpp <= 4) {
+		bpp = 4;
+		par->hw.falcon.f_shift = 0x000;
+		par->hw.falcon.st_shift = 0x000;
+	} else if (bpp <= 8) {
+		bpp = 8;
+		par->hw.falcon.f_shift = 0x010;
+	} else if (bpp <= 16) {
+		bpp = 16;		/* packed pixel mode */
+		par->hw.falcon.f_shift = 0x100;	/* hicolor, no overlay */
+	} else
+		return -EINVAL;
+	par->hw.falcon.bpp = bpp;
+
+	if (mon_type == F_MON_SM || DontCalcRes) {
+		/* Skip all calculations. VGA/TV/SC1224 only supported. */
+		struct fb_var_screeninfo *myvar = &atafb_predefined[0];
+
+		if (bpp > myvar->bits_per_pixel ||
+		    var->xres > myvar->xres ||
+		    var->yres > myvar->yres)
+			return -EINVAL;
+		fbhw->get_par(par);	/* Current par will be new par */
+		goto set_screen_base;	/* Don't forget this */
+	}
+
+	/* Only some fixed resolutions < 640x400 */
+	if (xres <= 320)
+		xres = 320;
+	else if (xres <= 640 && bpp != 16)
+		xres = 640;
+	if (yres <= 200)
+		yres = 200;
+	else if (yres <= 240)
+		yres = 240;
+	else if (yres <= 400)
+		yres = 400;
+
+	/* 2 planes must use STE compatibility mode */
+	par->hw.falcon.ste_mode = bpp == 2;
+	par->hw.falcon.mono = bpp == 1;
+
+	/* Total and visible scanline length must be a multiple of one longword,
+	 * this and the console fontwidth yields the alignment for xres and
+	 * xres_virtual.
+	 * TODO: this way "odd" fontheights are not supported
+	 *
+	 * Special case in STE mode: blank and graphic positions don't align,
+	 * avoid trash at right margin
+	 */
+	if (par->hw.falcon.ste_mode)
+		xres = (xres + 63) & ~63;
+	else if (bpp == 1)
+		xres = (xres + 31) & ~31;
+	else
+		xres = (xres + 15) & ~15;
+	if (yres >= 400)
+		yres = (yres + 15) & ~15;
+	else
+		yres = (yres + 7) & ~7;
+
+	if (xres_virtual < xres)
+		xres_virtual = xres;
+	else if (bpp == 1)
+		xres_virtual = (xres_virtual + 31) & ~31;
+	else
+		xres_virtual = (xres_virtual + 15) & ~15;
+
+	if (yres_virtual <= 0)
+		yres_virtual = 0;
+	else if (yres_virtual < yres)
+		yres_virtual = yres;
+
+	/* backward bug-compatibility */
+	if (var->pixclock > 1)
+		var->pixclock -= 1;
+
+	par->hw.falcon.line_width = bpp * xres / 16;
+	par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
+
+	/* single or double pixel width */
+	xstretch = (xres < 640) ? 2 : 1;
+
+#if 0 /* SM124 supports only 640x400, this is rejected above */
+	if (mon_type == F_MON_SM) {
+		if (xres != 640 && yres != 400)
+			return -EINVAL;
+		plen = 1;
+		pclock = &f32;
+		/* SM124-mode is special */
+		par->hw.falcon.ste_mode = 1;
+		par->hw.falcon.f_shift = 0x000;
+		par->hw.falcon.st_shift = 0x200;
+		left_margin = hsync_len = 128 / plen;
+		right_margin = 0;
+		/* TODO set all margins */
+	} else
+#endif
+	if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
+		plen = 2 * xstretch;
+		if (var->pixclock > f32.t * plen)
+			return -EINVAL;
+		pclock = &f32;
+		if (yres > 240)
+			interlace = 1;
+		if (var->pixclock == 0) {
+			/* set some minimal margins which center the screen */
+			left_margin = 32;
+			right_margin = 18;
+			hsync_len = pclock->hsync / plen;
+			upper_margin = 31;
+			lower_margin = 14;
+			vsync_len = interlace ? 3 : 4;
+		} else {
+			left_margin = var->left_margin;
+			right_margin = var->right_margin;
+			hsync_len = var->hsync_len;
+			upper_margin = var->upper_margin;
+			lower_margin = var->lower_margin;
+			vsync_len = var->vsync_len;
+			if (var->vmode & FB_VMODE_INTERLACED) {
+				upper_margin = (upper_margin + 1) / 2;
+				lower_margin = (lower_margin + 1) / 2;
+				vsync_len = (vsync_len + 1) / 2;
+			} else if (var->vmode & FB_VMODE_DOUBLE) {
+				upper_margin *= 2;
+				lower_margin *= 2;
+				vsync_len *= 2;
+			}
+		}
+	} else {			/* F_MON_VGA */
+		if (bpp == 16)
+			xstretch = 2;	/* Double pixel width only for hicolor */
+		/* Default values are used for vert./hor. timing if no pixelclock given. */
+		if (var->pixclock == 0) {
+			int linesize;
+
+			/* Choose master pixelclock depending on hor. timing */
+			plen = 1 * xstretch;
+			if ((plen * xres + f25.right + f25.hsync + f25.left) *
+			    fb_info.monspecs.hfmin < f25.f)
+				pclock = &f25;
+			else if ((plen * xres + f32.right + f32.hsync +
+				  f32.left) * fb_info.monspecs.hfmin < f32.f)
+				pclock = &f32;
+			else if ((plen * xres + fext.right + fext.hsync +
+				  fext.left) * fb_info.monspecs.hfmin < fext.f &&
+			         fext.f)
+				pclock = &fext;
+			else
+				return -EINVAL;
+
+			left_margin = pclock->left / plen;
+			right_margin = pclock->right / plen;
+			hsync_len = pclock->hsync / plen;
+			linesize = left_margin + xres + right_margin + hsync_len;
+			upper_margin = 31;
+			lower_margin = 11;
+			vsync_len = 3;
+		} else {
+			/* Choose largest pixelclock <= wanted clock */
+			int i;
+			unsigned long pcl = ULONG_MAX;
+			pclock = 0;
+			for (i = 1; i <= 4; i *= 2) {
+				if (f25.t * i >= var->pixclock &&
+				    f25.t * i < pcl) {
+					pcl = f25.t * i;
+					pclock = &f25;
+				}
+				if (f32.t * i >= var->pixclock &&
+				    f32.t * i < pcl) {
+					pcl = f32.t * i;
+					pclock = &f32;
+				}
+				if (fext.t && fext.t * i >= var->pixclock &&
+				    fext.t * i < pcl) {
+					pcl = fext.t * i;
+					pclock = &fext;
+				}
+			}
+			if (!pclock)
+				return -EINVAL;
+			plen = pcl / pclock->t;
+
+			left_margin = var->left_margin;
+			right_margin = var->right_margin;
+			hsync_len = var->hsync_len;
+			upper_margin = var->upper_margin;
+			lower_margin = var->lower_margin;
+			vsync_len = var->vsync_len;
+			/* Internal unit is [single lines per (half-)frame] */
+			if (var->vmode & FB_VMODE_INTERLACED) {
+				/* # lines in half frame */
+				/* External unit is [lines per full frame] */
+				upper_margin = (upper_margin + 1) / 2;
+				lower_margin = (lower_margin + 1) / 2;
+				vsync_len = (vsync_len + 1) / 2;
+			} else if (var->vmode & FB_VMODE_DOUBLE) {
+				/* External unit is [double lines per frame] */
+				upper_margin *= 2;
+				lower_margin *= 2;
+				vsync_len *= 2;
+			}
+		}
+		if (pclock == &fext)
+			longoffset = 1;	/* VIDEL doesn't synchronize on short offset */
+	}
+	/* Is video bus bandwidth (32MB/s) too low for this resolution? */
+	/* this is definitely wrong if bus clock != 32MHz */
+	if (pclock->f / plen / 8 * bpp > 32000000L)
+		return -EINVAL;
+
+	if (vsync_len < 1)
+		vsync_len = 1;
+
+	/* include sync lengths in right/lower margin for all calculations */
+	right_margin += hsync_len;
+	lower_margin += vsync_len;
+
+	/* ! In all calculations of margins we use # of lines in half frame
+	 * (which is a full frame in non-interlace mode), so we can switch
+	 * between interlace and non-interlace without messing around
+	 * with these.
+	 */
+again:
+	/* Set base_offset 128 and video bus width */
+	par->hw.falcon.vid_control = mon_type | f030_bus_width;
+	if (!longoffset)
+		par->hw.falcon.vid_control |= VCO_SHORTOFFS;	/* base_offset 64 */
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		par->hw.falcon.vid_control |= VCO_HSYPOS;
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		par->hw.falcon.vid_control |= VCO_VSYPOS;
+	/* Pixelclock */
+	par->hw.falcon.vid_control |= pclock->control_mask;
+	/* External or internal clock */
+	par->hw.falcon.sync = pclock->sync_mask | 0x2;
+	/* Pixellength and prescale */
+	par->hw.falcon.vid_mode = (2 / plen) << 2;
+	if (doubleline)
+		par->hw.falcon.vid_mode |= VMO_DOUBLE;
+	if (interlace)
+		par->hw.falcon.vid_mode |= VMO_INTER;
+
+	/*********************
+	 * Horizontal timing: unit = [master clock cycles]
+	 * unit of hxx-registers: [master clock cycles * prescale]
+	 * Hxx-registers are 9 bit wide
+	 *
+	 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
+	 *
+	 * graphic output = hdb & 0x200 ?
+	 *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
+	 *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
+	 * (this must be a multiple of plen*128/bpp, on VGA pixels
+	 *  to the right may be cut off with a bigger right margin)
+	 *
+	 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
+	 *        (hdb - hht - 2) * prescale + hdboff :
+	 *        hdb * prescale + hdboff
+	 *
+	 * end of graphics relative to start of 1st halfline =
+	 *        (hde + hht + 2) * prescale + hdeoff
+	 *********************/
+	/* Calculate VIDEL registers */
+{
+	prescale = hxx_prescale(&par->hw.falcon);
+	base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
+
+	/* Offsets depend on video mode */
+	/* Offsets are in clock cycles, divide by prescale to
+	 * calculate hd[be]-registers
+	 */
+	if (par->hw.falcon.f_shift & 0x100) {
+		align = 1;
+		hde_off = 0;
+		hdb_off = (base_off + 16 * plen) + prescale;
+	} else {
+		align = 128 / bpp;
+		hde_off = ((128 / bpp + 2) * plen);
+		if (par->hw.falcon.ste_mode)
+			hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
+		else
+			hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
+	}
+
+	gstart = (prescale / 2 + plen * left_margin) / prescale;
+	/* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
+	gend1 = gstart + roundup(xres, align) * plen / prescale;
+	/* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
+	gend2 = gstart + xres * plen / prescale;
+	par->HHT = plen * (left_margin + xres + right_margin) /
+			   (2 * prescale) - 2;
+/*	par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
+
+	par->HDB = gstart - hdb_off / prescale;
+	par->HBE = gstart;
+	if (par->HDB < 0)
+		par->HDB += par->HHT + 2 + 0x200;
+	par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
+	par->HBB = gend2 - par->HHT - 2;
+#if 0
+	/* One more Videl constraint: data fetch of two lines must not overlap */
+	if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
+		/* if this happens increase margins, decrease hfreq. */
+	}
+#endif
+	if (hde_off % prescale)
+		par->HBB++;		/* compensate for non matching hde and hbb */
+	par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
+	if (par->HSS < par->HBB)
+		par->HSS = par->HBB;
+}
+
+	/*  check hor. frequency */
+	hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
+	if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
+		/* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
+		/* Too high -> enlarge margin */
+		left_margin += 1;
+		right_margin += 1;
+		goto again;
+	}
+	if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
+		return -EINVAL;
+
+	/* Vxx-registers */
+	/* All Vxx must be odd in non-interlace, since frame starts in the middle
+	 * of the first displayed line!
+	 * One frame consists of VFT+1 half lines. VFT+1 must be even in
+	 * non-interlace, odd in interlace mode for synchronisation.
+	 * Vxx-registers are 11 bit wide
+	 */
+	par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
+	par->VDB = par->VBE;
+	par->VDE = yres;
+	if (!interlace)
+		par->VDE <<= 1;
+	if (doubleline)
+		par->VDE <<= 1;		/* VDE now half lines per (half-)frame */
+	par->VDE += par->VDB;
+	par->VBB = par->VDE;
+	par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
+	par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
+	/* vbb,vss,vft must be even in interlace mode */
+	if (interlace) {
+		par->VBB++;
+		par->VSS++;
+		par->VFT++;
+	}
+
+	/* V-frequency check, hope I didn't create any loop here. */
+	/* Interlace and doubleline are mutually exclusive. */
+	vfreq = (hfreq * 2) / (par->VFT + 1);
+	if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
+		/* Too high -> try again with doubleline */
+		doubleline = 1;
+		goto again;
+	} else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
+		/* Too low -> try again with interlace */
+		interlace = 1;
+		goto again;
+	} else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
+		/* Doubleline too low -> clear doubleline and enlarge margins */
+		int lines;
+		doubleline = 0;
+		for (lines = 0;
+		     (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
+		     fb_info.monspecs.vfmax;
+		     lines++)
+			;
+		upper_margin += lines;
+		lower_margin += lines;
+		goto again;
+	} else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
+		/* Doubleline too high -> enlarge margins */
+		int lines;
+		for (lines = 0;
+		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
+		     fb_info.monspecs.vfmax;
+		     lines += 2)
+			;
+		upper_margin += lines;
+		lower_margin += lines;
+		goto again;
+	} else if (vfreq > fb_info.monspecs.vfmax && interlace) {
+		/* Interlace, too high -> enlarge margins */
+		int lines;
+		for (lines = 0;
+		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
+		     fb_info.monspecs.vfmax;
+		     lines++)
+			;
+		upper_margin += lines;
+		lower_margin += lines;
+		goto again;
+	} else if (vfreq < fb_info.monspecs.vfmin ||
+		   vfreq > fb_info.monspecs.vfmax)
+		return -EINVAL;
+
+set_screen_base:
+	linelen = xres_virtual * bpp / 8;
+	if (yres_virtual * linelen > screen_len && screen_len)
+		return -EINVAL;
+	if (yres * linelen > screen_len && screen_len)
+		return -EINVAL;
+	if (var->yoffset + yres > yres_virtual && yres_virtual)
+		return -EINVAL;
+	par->yres_virtual = yres_virtual;
+	par->screen_base = screen_base + var->yoffset * linelen;
+	par->hw.falcon.xoffset = 0;
+
+	par->next_line = linelen;
+
+	return 0;
+}
+
+static int falcon_encode_var(struct fb_var_screeninfo *var,
+			     struct atafb_par *par)
+{
+/* !!! only for VGA !!! */
+	int linelen;
+	int prescale, plen;
+	int hdb_off, hde_off, base_off;
+	struct falcon_hw *hw = &par->hw.falcon;
+
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+	/* possible frequencies: 25.175 or 32MHz */
+	var->pixclock = hw->sync & 0x1 ? fext.t :
+	                hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
+
+	var->height = -1;
+	var->width = -1;
+
+	var->sync = 0;
+	if (hw->vid_control & VCO_HSYPOS)
+		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (hw->vid_control & VCO_VSYPOS)
+		var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+	var->vmode = FB_VMODE_NONINTERLACED;
+	if (hw->vid_mode & VMO_INTER)
+		var->vmode |= FB_VMODE_INTERLACED;
+	if (hw->vid_mode & VMO_DOUBLE)
+		var->vmode |= FB_VMODE_DOUBLE;
+
+	/* visible y resolution:
+	 * Graphics display starts at line VDB and ends at line
+	 * VDE. If interlace mode off unit of VC-registers is
+	 * half lines, else lines.
+	 */
+	var->yres = hw->vde - hw->vdb;
+	if (!(var->vmode & FB_VMODE_INTERLACED))
+		var->yres >>= 1;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		var->yres >>= 1;
+
+	/*
+	 * to get bpp, we must examine f_shift and st_shift.
+	 * f_shift is valid if any of bits no. 10, 8 or 4
+	 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
+	 * if bit 10 set then bit 8 and bit 4 don't care...
+	 * If all these bits are 0 get display depth from st_shift
+	 * (as for ST and STE)
+	 */
+	if (hw->f_shift & 0x400)	/* 2 colors */
+		var->bits_per_pixel = 1;
+	else if (hw->f_shift & 0x100)	/* hicolor */
+		var->bits_per_pixel = 16;
+	else if (hw->f_shift & 0x010)	/* 8 bitplanes */
+		var->bits_per_pixel = 8;
+	else if (hw->st_shift == 0)
+		var->bits_per_pixel = 4;
+	else if (hw->st_shift == 0x100)
+		var->bits_per_pixel = 2;
+	else				/* if (hw->st_shift == 0x200) */
+		var->bits_per_pixel = 1;
+
+	var->xres = hw->line_width * 16 / var->bits_per_pixel;
+	var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
+	if (hw->xoffset)
+		var->xres_virtual += 16;
+
+	if (var->bits_per_pixel == 16) {
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->red.msb_right = 0;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->green.msb_right = 0;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->blue.msb_right = 0;
+	} else {
+		var->red.offset = 0;
+		var->red.length = hw->ste_mode ? 4 : 6;
+		if (var->red.length > var->bits_per_pixel)
+			var->red.length = var->bits_per_pixel;
+		var->red.msb_right = 0;
+		var->grayscale = 0;
+		var->blue = var->green = var->red;
+	}
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+
+	linelen = var->xres_virtual * var->bits_per_pixel / 8;
+	if (screen_len) {
+		if (par->yres_virtual)
+			var->yres_virtual = par->yres_virtual;
+		else
+			/* yres_virtual == 0 means use maximum */
+			var->yres_virtual = screen_len / linelen;
+	} else {
+		if (hwscroll < 0)
+			var->yres_virtual = 2 * var->yres;
+		else
+			var->yres_virtual = var->yres + hwscroll * 16;
+	}
+	var->xoffset = 0;		/* TODO change this */
+
+	/* hdX-offsets */
+	prescale = hxx_prescale(hw);
+	plen = 4 >> (hw->vid_mode >> 2 & 0x3);
+	base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
+	if (hw->f_shift & 0x100) {
+		hde_off = 0;
+		hdb_off = (base_off + 16 * plen) + prescale;
+	} else {
+		hde_off = ((128 / var->bits_per_pixel + 2) * plen);
+		if (hw->ste_mode)
+			hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
+					 + prescale;
+		else
+			hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
+					 + prescale;
+	}
+
+	/* Right margin includes hsync */
+	var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
+					   (hw->hdb & 0x200 ? 2 + hw->hht : 0));
+	if (hw->ste_mode || mon_type != F_MON_VGA)
+		var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
+	else
+		/* can't use this in ste_mode, because hbb is +1 off */
+		var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
+	var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
+
+	/* Lower margin includes vsync */
+	var->upper_margin = hw->vdb / 2;	/* round down to full lines */
+	var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;	/* round up */
+	var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;	/* round up */
+	if (var->vmode & FB_VMODE_INTERLACED) {
+		var->upper_margin *= 2;
+		var->lower_margin *= 2;
+		var->vsync_len *= 2;
+	} else if (var->vmode & FB_VMODE_DOUBLE) {
+		var->upper_margin = (var->upper_margin + 1) / 2;
+		var->lower_margin = (var->lower_margin + 1) / 2;
+		var->vsync_len = (var->vsync_len + 1) / 2;
+	}
+
+	var->pixclock *= plen;
+	var->left_margin /= plen;
+	var->right_margin /= plen;
+	var->hsync_len /= plen;
+
+	var->right_margin -= var->hsync_len;
+	var->lower_margin -= var->vsync_len;
+
+	if (screen_base)
+		var->yoffset = (par->screen_base - screen_base) / linelen;
+	else
+		var->yoffset = 0;
+	var->nonstd = 0;		/* what is this for? */
+	var->activate = 0;
+	return 0;
+}
+
+static int f_change_mode;
+static struct falcon_hw f_new_mode;
+static int f_pan_display;
+
+static void falcon_get_par(struct atafb_par *par)
+{
+	unsigned long addr;
+	struct falcon_hw *hw = &par->hw.falcon;
+
+	hw->line_width = shifter_f030.scn_width;
+	hw->line_offset = shifter_f030.off_next;
+	hw->st_shift = videl.st_shift & 0x300;
+	hw->f_shift = videl.f_shift;
+	hw->vid_control = videl.control;
+	hw->vid_mode = videl.mode;
+	hw->sync = shifter.syncmode & 0x1;
+	hw->xoffset = videl.xoffset & 0xf;
+	hw->hht = videl.hht;
+	hw->hbb = videl.hbb;
+	hw->hbe = videl.hbe;
+	hw->hdb = videl.hdb;
+	hw->hde = videl.hde;
+	hw->hss = videl.hss;
+	hw->vft = videl.vft;
+	hw->vbb = videl.vbb;
+	hw->vbe = videl.vbe;
+	hw->vdb = videl.vdb;
+	hw->vde = videl.vde;
+	hw->vss = videl.vss;
+
+	addr = (shifter.bas_hi & 0xff) << 16 |
+	       (shifter.bas_md & 0xff) << 8  |
+	       (shifter.bas_lo & 0xff);
+	par->screen_base = phys_to_virt(addr);
+
+	/* derived parameters */
+	hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
+	hw->mono = (hw->f_shift & 0x400) ||
+	           ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
+}
+
+static void falcon_set_par(struct atafb_par *par)
+{
+	f_change_mode = 0;
+
+	/* only set screen_base if really necessary */
+	if (current_par.screen_base != par->screen_base)
+		fbhw->set_screen_base(par->screen_base);
+
+	/* Don't touch any other registers if we keep the default resolution */
+	if (DontCalcRes)
+		return;
+
+	/* Tell vbl-handler to change video mode.
+	 * We change modes only on next VBL, to avoid desynchronisation
+	 * (a shift to the right and wrap around by a random number of pixels
+	 * in all monochrome modes).
+	 * This seems to work on my Falcon.
+	 */
+	f_new_mode = par->hw.falcon;
+	f_change_mode = 1;
+}
+
+static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
+{
+	struct falcon_hw *hw = &f_new_mode;
+
+	if (f_change_mode) {
+		f_change_mode = 0;
+
+		if (hw->sync & 0x1) {
+			/* Enable external pixelclock. This code only for ScreenWonder */
+			*(volatile unsigned short *)0xffff9202 = 0xffbf;
+		} else {
+			/* Turn off external clocks. Read sets all output bits to 1. */
+			*(volatile unsigned short *)0xffff9202;
+		}
+		shifter.syncmode = hw->sync;
+
+		videl.hht = hw->hht;
+		videl.hbb = hw->hbb;
+		videl.hbe = hw->hbe;
+		videl.hdb = hw->hdb;
+		videl.hde = hw->hde;
+		videl.hss = hw->hss;
+		videl.vft = hw->vft;
+		videl.vbb = hw->vbb;
+		videl.vbe = hw->vbe;
+		videl.vdb = hw->vdb;
+		videl.vde = hw->vde;
+		videl.vss = hw->vss;
+
+		videl.f_shift = 0;	/* write enables Falcon palette, 0: 4 planes */
+		if (hw->ste_mode) {
+			videl.st_shift = hw->st_shift;	/* write enables STE palette */
+		} else {
+			/* IMPORTANT:
+			 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
+			 * Writing 0 to f_shift enables 4 plane Falcon mode but
+			 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
+			 * with Falcon palette.
+			 */
+			videl.st_shift = 0;
+			/* now back to Falcon palette mode */
+			videl.f_shift = hw->f_shift;
+		}
+		/* writing to st_shift changed scn_width and vid_mode */
+		videl.xoffset = hw->xoffset;
+		shifter_f030.scn_width = hw->line_width;
+		shifter_f030.off_next = hw->line_offset;
+		videl.control = hw->vid_control;
+		videl.mode = hw->vid_mode;
+	}
+	if (f_pan_display) {
+		f_pan_display = 0;
+		videl.xoffset = current_par.hw.falcon.xoffset;
+		shifter_f030.off_next = current_par.hw.falcon.line_offset;
+	}
+	return IRQ_HANDLED;
+}
+
+static int falcon_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+
+	int xoffset;
+	int bpp = info->var.bits_per_pixel;
+
+	if (bpp == 1)
+		var->xoffset = up(var->xoffset, 32);
+	if (bpp != 16)
+		par->hw.falcon.xoffset = var->xoffset & 15;
+	else {
+		par->hw.falcon.xoffset = 0;
+		var->xoffset = up(var->xoffset, 2);
+	}
+	par->hw.falcon.line_offset = bpp *
+		(info->var.xres_virtual - info->var.xres) / 16;
+	if (par->hw.falcon.xoffset)
+		par->hw.falcon.line_offset -= bpp;
+	xoffset = var->xoffset - par->hw.falcon.xoffset;
+
+	par->screen_base = screen_base +
+	        (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
+	if (fbhw->set_screen_base)
+		fbhw->set_screen_base(par->screen_base);
+	else
+		return -EINVAL;		/* shouldn't happen */
+	f_pan_display = 1;
+	return 0;
+}
+
+static int falcon_setcolreg(unsigned int regno, unsigned int red,
+			    unsigned int green, unsigned int blue,
+			    unsigned int transp, struct fb_info *info)
+{
+	if (regno > 255)
+		return 1;
+	f030_col[regno] = (((red & 0xfc00) << 16) |
+			   ((green & 0xfc00) << 8) |
+			   ((blue & 0xfc00) >> 8));
+	if (regno < 16) {
+		shifter_tt.color_reg[regno] =
+			(((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
+			(((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
+			((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
+		((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
+						       ((green & 0xfc00) >> 5) |
+						       ((blue & 0xf800) >> 11));
+	}
+	return 0;
+}
+
+static int falcon_blank(int blank_mode)
+{
+	/* ++guenther: we can switch off graphics by changing VDB and VDE,
+	 * so VIDEL doesn't hog the bus while saving.
+	 * (this may affect usleep()).
+	 */
+	int vdb, vss, hbe, hss;
+
+	if (mon_type == F_MON_SM)	/* this doesn't work on SM124 */
+		return 1;
+
+	vdb = current_par.VDB;
+	vss = current_par.VSS;
+	hbe = current_par.HBE;
+	hss = current_par.HSS;
+
+	if (blank_mode >= 1) {
+		/* disable graphics output (this speeds up the CPU) ... */
+		vdb = current_par.VFT + 1;
+		/* ... and blank all lines */
+		hbe = current_par.HHT + 2;
+	}
+	/* use VESA suspend modes on VGA monitors */
+	if (mon_type == F_MON_VGA) {
+		if (blank_mode == 2 || blank_mode == 4)
+			vss = current_par.VFT + 1;
+		if (blank_mode == 3 || blank_mode == 4)
+			hss = current_par.HHT + 2;
+	}
+
+	videl.vdb = vdb;
+	videl.vss = vss;
+	videl.hbe = hbe;
+	videl.hss = hss;
+
+	return 0;
+}
+
+static int falcon_detect(void)
+{
+	struct atafb_par par;
+	unsigned char fhw;
+
+	/* Determine connected monitor and set monitor parameters */
+	fhw = *(unsigned char *)0xffff8006;
+	mon_type = fhw >> 6 & 0x3;
+	/* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
+	f030_bus_width = fhw << 6 & 0x80;
+	switch (mon_type) {
+	case F_MON_SM:
+		fb_info.monspecs.vfmin = 70;
+		fb_info.monspecs.vfmax = 72;
+		fb_info.monspecs.hfmin = 35713;
+		fb_info.monspecs.hfmax = 35715;
+		break;
+	case F_MON_SC:
+	case F_MON_TV:
+		/* PAL...NTSC */
+		fb_info.monspecs.vfmin = 49;	/* not 50, since TOS defaults to 49.9x Hz */
+		fb_info.monspecs.vfmax = 60;
+		fb_info.monspecs.hfmin = 15620;
+		fb_info.monspecs.hfmax = 15755;
+		break;
+	}
+	/* initialize hsync-len */
+	f25.hsync = h_syncs[mon_type] / f25.t;
+	f32.hsync = h_syncs[mon_type] / f32.t;
+	if (fext.t)
+		fext.hsync = h_syncs[mon_type] / fext.t;
+
+	falcon_get_par(&par);
+	falcon_encode_var(&atafb_predefined[0], &par);
+
+	/* Detected mode is always the "autodetect" slot */
+	return 1;
+}
+
+#endif /* ATAFB_FALCON */
+
+/* ------------------- ST(E) specific functions ---------------------- */
+
+#ifdef ATAFB_STE
+
+static int stste_encode_fix(struct fb_fix_screeninfo *fix,
+			    struct atafb_par *par)
+{
+	int mode;
+
+	strcpy(fix->id, "Atari Builtin");
+	fix->smem_start = (unsigned long)real_screen_base;
+	fix->smem_len = screen_len;
+	fix->type = FB_TYPE_INTERLEAVED_PLANES;
+	fix->type_aux = 2;
+	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	mode = par->hw.st.mode & 3;
+	if (mode == ST_HIGH) {
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->type_aux = 0;
+		fix->visual = FB_VISUAL_MONO10;
+	}
+	if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
+		fix->xpanstep = 16;
+		fix->ypanstep = 1;
+	} else {
+		fix->xpanstep = 0;
+		fix->ypanstep = 0;
+	}
+	fix->ywrapstep = 0;
+	fix->line_length = par->next_line;
+	fix->accel = FB_ACCEL_ATARIBLITT;
+	return 0;
+}
+
+static int stste_decode_var(struct fb_var_screeninfo *var,
+			    struct atafb_par *par)
+{
+	int xres = var->xres;
+	int yres = var->yres;
+	int bpp = var->bits_per_pixel;
+	int linelen;
+	int yres_virtual = var->yres_virtual;
+
+	if (mono_moni) {
+		if (bpp > 1 || xres > sttt_xres || yres > st_yres)
+			return -EINVAL;
+		par->hw.st.mode = ST_HIGH;
+		xres = sttt_xres;
+		yres = st_yres;
+		bpp = 1;
+	} else {
+		if (bpp > 4 || xres > sttt_xres || yres > st_yres)
+			return -EINVAL;
+		if (bpp > 2) {
+			if (xres > sttt_xres / 2 || yres > st_yres / 2)
+				return -EINVAL;
+			par->hw.st.mode = ST_LOW;
+			xres = sttt_xres / 2;
+			yres = st_yres / 2;
+			bpp = 4;
+		} else if (bpp > 1) {
+			if (xres > sttt_xres || yres > st_yres / 2)
+				return -EINVAL;
+			par->hw.st.mode = ST_MID;
+			xres = sttt_xres;
+			yres = st_yres / 2;
+			bpp = 2;
+		} else
+			return -EINVAL;
+	}
+	if (yres_virtual <= 0)
+		yres_virtual = 0;
+	else if (yres_virtual < yres)
+		yres_virtual = yres;
+	if (var->sync & FB_SYNC_EXT)
+		par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
+	else
+		par->hw.st.sync = (par->hw.st.sync & ~1);
+	linelen = xres * bpp / 8;
+	if (yres_virtual * linelen > screen_len && screen_len)
+		return -EINVAL;
+	if (yres * linelen > screen_len && screen_len)
+		return -EINVAL;
+	if (var->yoffset + yres > yres_virtual && yres_virtual)
+		return -EINVAL;
+	par->yres_virtual = yres_virtual;
+	par->screen_base = screen_base + var->yoffset * linelen;
+	par->next_line = linelen;
+	return 0;
+}
+
+static int stste_encode_var(struct fb_var_screeninfo *var,
+			    struct atafb_par *par)
+{
+	int linelen;
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+	var->red.offset = 0;
+	var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
+	var->red.msb_right = 0;
+	var->grayscale = 0;
+
+	var->pixclock = 31041;
+	var->left_margin = 120;		/* these are incorrect */
+	var->right_margin = 100;
+	var->upper_margin = 8;
+	var->lower_margin = 16;
+	var->hsync_len = 140;
+	var->vsync_len = 30;
+
+	var->height = -1;
+	var->width = -1;
+
+	if (!(par->hw.st.sync & 1))
+		var->sync = 0;
+	else
+		var->sync = FB_SYNC_EXT;
+
+	switch (par->hw.st.mode & 3) {
+	case ST_LOW:
+		var->xres = sttt_xres / 2;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 4;
+		break;
+	case ST_MID:
+		var->xres = sttt_xres;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 2;
+		break;
+	case ST_HIGH:
+		var->xres = sttt_xres;
+		var->yres = st_yres;
+		var->bits_per_pixel = 1;
+		break;
+	}
+	var->blue = var->green = var->red;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	var->xres_virtual = sttt_xres_virtual;
+	linelen = var->xres_virtual * var->bits_per_pixel / 8;
+	ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
+
+	if (!use_hwscroll)
+		var->yres_virtual = var->yres;
+	else if (screen_len) {
+		if (par->yres_virtual)
+			var->yres_virtual = par->yres_virtual;
+		else
+			/* yres_virtual == 0 means use maximum */
+			var->yres_virtual = screen_len / linelen;
+	} else {
+		if (hwscroll < 0)
+			var->yres_virtual = 2 * var->yres;
+		else
+			var->yres_virtual = var->yres + hwscroll * 16;
+	}
+	var->xoffset = 0;
+	if (screen_base)
+		var->yoffset = (par->screen_base - screen_base) / linelen;
+	else
+		var->yoffset = 0;
+	var->nonstd = 0;
+	var->activate = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	return 0;
+}
+
+static void stste_get_par(struct atafb_par *par)
+{
+	unsigned long addr;
+	par->hw.st.mode = shifter_tt.st_shiftmode;
+	par->hw.st.sync = shifter.syncmode;
+	addr = ((shifter.bas_hi & 0xff) << 16) |
+	       ((shifter.bas_md & 0xff) << 8);
+	if (ATARIHW_PRESENT(EXTD_SHIFTER))
+		addr |= (shifter.bas_lo & 0xff);
+	par->screen_base = phys_to_virt(addr);
+}
+
+static void stste_set_par(struct atafb_par *par)
+{
+	shifter_tt.st_shiftmode = par->hw.st.mode;
+	shifter.syncmode = par->hw.st.sync;
+	/* only set screen_base if really necessary */
+	if (current_par.screen_base != par->screen_base)
+		fbhw->set_screen_base(par->screen_base);
+}
+
+static int stste_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp, struct fb_info *info)
+{
+	if (regno > 15)
+		return 1;
+	red >>= 12;
+	blue >>= 12;
+	green >>= 12;
+	if (ATARIHW_PRESENT(EXTD_SHIFTER))
+		shifter_tt.color_reg[regno] =
+			(((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
+			(((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
+			((blue & 0xe) >> 1) | ((blue & 1) << 3);
+	else
+		shifter_tt.color_reg[regno] =
+			((red & 0xe) << 7) |
+			((green & 0xe) << 3) |
+			((blue & 0xe) >> 1);
+	return 0;
+}
+
+static int stste_detect(void)
+{
+	struct atafb_par par;
+
+	/* Determine the connected monitor: The DMA sound must be
+	 * disabled before reading the MFP GPIP, because the Sound
+	 * Done Signal and the Monochrome Detect are XORed together!
+	 */
+	if (ATARIHW_PRESENT(PCM_8BIT)) {
+		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+		udelay(20);		/* wait a while for things to settle down */
+	}
+	mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
+
+	stste_get_par(&par);
+	stste_encode_var(&atafb_predefined[0], &par);
+
+	if (!ATARIHW_PRESENT(EXTD_SHIFTER))
+		use_hwscroll = 0;
+	return 1;
+}
+
+static void stste_set_screen_base(void *s_base)
+{
+	unsigned long addr;
+	addr = virt_to_phys(s_base);
+	/* Setup Screen Memory */
+	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
+	if (ATARIHW_PRESENT(EXTD_SHIFTER))
+		shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
+}
+
+#endif /* ATAFB_STE */
+
+/* Switching the screen size should be done during vsync, otherwise
+ * the margins may get messed up. This is a well known problem of
+ * the ST's video system.
+ *
+ * Unfortunately there is hardly any way to find the vsync, as the
+ * vertical blank interrupt is no longer in time on machines with
+ * overscan type modifications.
+ *
+ * We can, however, use Timer B to safely detect the black shoulder,
+ * but then we've got to guess an appropriate delay to find the vsync.
+ * This might not work on every machine.
+ *
+ * martin_rogge @ ki.maus.de, 8th Aug 1995
+ */
+
+#define LINE_DELAY  (mono_moni ? 30 : 70)
+#define SYNC_DELAY  (mono_moni ? 1500 : 2000)
+
+/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
+static void st_ovsc_switch(void)
+{
+	unsigned long flags;
+	register unsigned char old, new;
+
+	if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
+		return;
+	local_irq_save(flags);
+
+	st_mfp.tim_ct_b = 0x10;
+	st_mfp.active_edge |= 8;
+	st_mfp.tim_ct_b = 0;
+	st_mfp.tim_dt_b = 0xf0;
+	st_mfp.tim_ct_b = 8;
+	while (st_mfp.tim_dt_b > 1)	/* TOS does it this way, don't ask why */
+		;
+	new = st_mfp.tim_dt_b;
+	do {
+		udelay(LINE_DELAY);
+		old = new;
+		new = st_mfp.tim_dt_b;
+	} while (old != new);
+	st_mfp.tim_ct_b = 0x10;
+	udelay(SYNC_DELAY);
+
+	if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+		acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
+	if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+	if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
+		sound_ym.rd_data_reg_sel = 14;
+		sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+				   ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
+				   ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
+	}
+	local_irq_restore(flags);
+}
+
+/* ------------------- External Video ---------------------- */
+
+#ifdef ATAFB_EXT
+
+static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
+{
+	strcpy(fix->id, "Unknown Extern");
+	fix->smem_start = (unsigned long)external_addr;
+	fix->smem_len = PAGE_ALIGN(external_len);
+	if (external_depth == 1) {
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		/* The letters 'n' and 'i' in the "atavideo=external:" stand
+		 * for "normal" and "inverted", rsp., in the monochrome case */
+		fix->visual =
+			(external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
+			 external_pmode == FB_TYPE_PACKED_PIXELS) ?
+				FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
+	} else {
+		/* Use STATIC if we don't know how to access color registers */
+		int visual = external_vgaiobase ?
+					 FB_VISUAL_PSEUDOCOLOR :
+					 FB_VISUAL_STATIC_PSEUDOCOLOR;
+		switch (external_pmode) {
+		case -1:		/* truecolor */
+			fix->type = FB_TYPE_PACKED_PIXELS;
+			fix->visual = FB_VISUAL_TRUECOLOR;
+			break;
+		case FB_TYPE_PACKED_PIXELS:
+			fix->type = FB_TYPE_PACKED_PIXELS;
+			fix->visual = visual;
+			break;
+		case FB_TYPE_PLANES:
+			fix->type = FB_TYPE_PLANES;
+			fix->visual = visual;
+			break;
+		case FB_TYPE_INTERLEAVED_PLANES:
+			fix->type = FB_TYPE_INTERLEAVED_PLANES;
+			fix->type_aux = 2;
+			fix->visual = visual;
+			break;
+		}
+	}
+	fix->xpanstep = 0;
+	fix->ypanstep = 0;
+	fix->ywrapstep = 0;
+	fix->line_length = par->next_line;
+	return 0;
+}
+
+static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+{
+	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
+
+	if (var->bits_per_pixel > myvar->bits_per_pixel ||
+	    var->xres > myvar->xres ||
+	    var->xres_virtual > myvar->xres_virtual ||
+	    var->yres > myvar->yres ||
+	    var->xoffset > 0 ||
+	    var->yoffset > 0)
+		return -EINVAL;
+
+	par->next_line = external_xres_virtual * external_depth / 8;
+	return 0;
+}
+
+static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
+{
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+	var->red.offset = 0;
+	var->red.length = (external_pmode == -1) ? external_depth / 3 :
+			(external_vgaiobase ? external_bitspercol : 0);
+	var->red.msb_right = 0;
+	var->grayscale = 0;
+
+	var->pixclock = 31041;
+	var->left_margin = 120;		/* these are surely incorrect */
+	var->right_margin = 100;
+	var->upper_margin = 8;
+	var->lower_margin = 16;
+	var->hsync_len = 140;
+	var->vsync_len = 30;
+
+	var->height = -1;
+	var->width = -1;
+
+	var->sync = 0;
+
+	var->xres = external_xres;
+	var->yres = external_yres;
+	var->xres_virtual = external_xres_virtual;
+	var->bits_per_pixel = external_depth;
+
+	var->blue = var->green = var->red;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	var->yres_virtual = var->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->nonstd = 0;
+	var->activate = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	return 0;
+}
+
+static void ext_get_par(struct atafb_par *par)
+{
+	par->screen_base = external_addr;
+}
+
+static void ext_set_par(struct atafb_par *par)
+{
+}
+
+#define OUTB(port,val) \
+	*((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
+#define INB(port) \
+	(*((unsigned volatile char *) ((port)+external_vgaiobase)))
+#define DACDelay				\
+	do {					\
+		unsigned char tmp = INB(0x3da);	\
+		tmp = INB(0x3da);			\
+	} while (0)
+
+static int ext_setcolreg(unsigned int regno, unsigned int red,
+			 unsigned int green, unsigned int blue,
+			 unsigned int transp, struct fb_info *info)
+{
+	unsigned char colmask = (1 << external_bitspercol) - 1;
+
+	if (!external_vgaiobase)
+		return 1;
+
+	if (regno > 255)
+		return 1;
+
+	switch (external_card_type) {
+	case IS_VGA:
+		OUTB(0x3c8, regno);
+		DACDelay;
+		OUTB(0x3c9, red & colmask);
+		DACDelay;
+		OUTB(0x3c9, green & colmask);
+		DACDelay;
+		OUTB(0x3c9, blue & colmask);
+		DACDelay;
+		return 0;
+
+	case IS_MV300:
+		OUTB((MV300_reg[regno] << 2) + 1, red);
+		OUTB((MV300_reg[regno] << 2) + 1, green);
+		OUTB((MV300_reg[regno] << 2) + 1, blue);
+		return 0;
+
+	default:
+		return 1;
+	}
+}
+
+static int ext_detect(void)
+{
+	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
+	struct atafb_par dummy_par;
+
+	myvar->xres = external_xres;
+	myvar->xres_virtual = external_xres_virtual;
+	myvar->yres = external_yres;
+	myvar->bits_per_pixel = external_depth;
+	ext_encode_var(myvar, &dummy_par);
+	return 1;
+}
+
+#endif /* ATAFB_EXT */
+
+/* ------ This is the same for most hardware types -------- */
+
+static void set_screen_base(void *s_base)
+{
+	unsigned long addr;
+
+	addr = virt_to_phys(s_base);
+	/* Setup Screen Memory */
+	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
+	shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
+}
+
+static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+
+	if (!fbhw->set_screen_base ||
+	    (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
+		return -EINVAL;
+	var->xoffset = up(var->xoffset, 16);
+	par->screen_base = screen_base +
+	        (var->yoffset * info->var.xres_virtual + var->xoffset)
+	        * info->var.bits_per_pixel / 8;
+	fbhw->set_screen_base(par->screen_base);
+	return 0;
+}
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+#ifdef ATAFB_TT
+static struct fb_hwswitch tt_switch = {
+	.detect		= tt_detect,
+	.encode_fix	= tt_encode_fix,
+	.decode_var	= tt_decode_var,
+	.encode_var	= tt_encode_var,
+	.get_par	= tt_get_par,
+	.set_par	= tt_set_par,
+	.set_screen_base = set_screen_base,
+	.pan_display	= pan_display,
+};
+#endif
+
+#ifdef ATAFB_FALCON
+static struct fb_hwswitch falcon_switch = {
+	.detect		= falcon_detect,
+	.encode_fix	= falcon_encode_fix,
+	.decode_var	= falcon_decode_var,
+	.encode_var	= falcon_encode_var,
+	.get_par	= falcon_get_par,
+	.set_par	= falcon_set_par,
+	.set_screen_base = set_screen_base,
+	.blank		= falcon_blank,
+	.pan_display	= falcon_pan_display,
+};
+#endif
+
+#ifdef ATAFB_STE
+static struct fb_hwswitch st_switch = {
+	.detect		= stste_detect,
+	.encode_fix	= stste_encode_fix,
+	.decode_var	= stste_decode_var,
+	.encode_var	= stste_encode_var,
+	.get_par	= stste_get_par,
+	.set_par	= stste_set_par,
+	.set_screen_base = stste_set_screen_base,
+	.pan_display	= pan_display
+};
+#endif
+
+#ifdef ATAFB_EXT
+static struct fb_hwswitch ext_switch = {
+	.detect		= ext_detect,
+	.encode_fix	= ext_encode_fix,
+	.decode_var	= ext_decode_var,
+	.encode_var	= ext_encode_var,
+	.get_par	= ext_get_par,
+	.set_par	= ext_set_par,
+};
+#endif
+
+static void ata_get_par(struct atafb_par *par)
+{
+	if (current_par_valid)
+		*par = current_par;
+	else
+		fbhw->get_par(par);
+}
+
+static void ata_set_par(struct atafb_par *par)
+{
+	fbhw->set_par(par);
+	current_par = *par;
+	current_par_valid = 1;
+}
+
+
+/* =========================================================== */
+/* ============== Hardware Independent Functions ============= */
+/* =========================================================== */
+
+/* used for hardware scrolling */
+
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+{
+	int err, activate;
+	struct atafb_par par;
+
+	err = fbhw->decode_var(var, &par);
+	if (err)
+		return err;
+	activate = var->activate;
+	if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
+		ata_set_par(&par);
+	fbhw->encode_var(var, &par);
+	var->activate = activate;
+	return 0;
+}
+
+/* fbhw->encode_fix() must be called with fb_info->mm_lock held
+ * if it is called after the register_framebuffer() - not a case here
+ */
+static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
+{
+	struct atafb_par par;
+	int err;
+	// Get fix directly (case con == -1 before)??
+	err = fbhw->decode_var(&info->var, &par);
+	if (err)
+		return err;
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	err = fbhw->encode_fix(fix, &par);
+	return err;
+}
+
+static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct atafb_par par;
+
+	ata_get_par(&par);
+	fbhw->encode_var(var, &par);
+
+	return 0;
+}
+
+// No longer called by fbcon!
+// Still called by set_var internally
+
+static void atafb_set_disp(struct fb_info *info)
+{
+	atafb_get_var(&info->var, info);
+	atafb_get_fix(&info->fix, info);
+
+	info->screen_base = (void *)info->fix.smem_start;
+}
+
+static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info)
+{
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
+}
+
+static int
+atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int xoffset = var->xoffset;
+	int yoffset = var->yoffset;
+	int err;
+
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
+			return -EINVAL;
+	} else {
+		if (xoffset + info->var.xres > info->var.xres_virtual ||
+		    yoffset + info->var.yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+
+	if (fbhw->pan_display) {
+		err = fbhw->pan_display(var, info);
+		if (err)
+			return err;
+	} else
+		return -EINVAL;
+
+	info->var.xoffset = xoffset;
+	info->var.yoffset = yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+
+	return 0;
+}
+
+/*
+ * generic drawing routines; imageblit needs updating for image depth > 1
+ */
+
+#if BITS_PER_LONG == 32
+#define BYTES_PER_LONG	4
+#define SHIFT_PER_LONG	5
+#elif BITS_PER_LONG == 64
+#define BYTES_PER_LONG	8
+#define SHIFT_PER_LONG	6
+#else
+#define Please update me
+#endif
+
+
+static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+	int x2, y2;
+	u32 width, height;
+
+	if (!rect->width || !rect->height)
+		return;
+
+#ifdef ATAFB_FALCON
+	if (info->var.bits_per_pixel == 16) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+#endif
+
+	/*
+	 * We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly.
+	 * */
+	x2 = rect->dx + rect->width;
+	y2 = rect->dy + rect->height;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - rect->dx;
+	height = y2 - rect->dy;
+
+	if (info->var.bits_per_pixel == 1)
+		atafb_mfb_fillrect(info, par->next_line, rect->color,
+				   rect->dy, rect->dx, height, width);
+	else if (info->var.bits_per_pixel == 2)
+		atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
+					rect->dy, rect->dx, height, width);
+	else if (info->var.bits_per_pixel == 4)
+		atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
+					rect->dy, rect->dx, height, width);
+	else
+		atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
+					rect->dy, rect->dx, height, width);
+
+	return;
+}
+
+static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+	int x2, y2;
+	u32 dx, dy, sx, sy, width, height;
+	int rev_copy = 0;
+
+#ifdef ATAFB_FALCON
+	if (info->var.bits_per_pixel == 16) {
+		cfb_copyarea(info, area);
+		return;
+	}
+#endif
+
+	/* clip the destination */
+	x2 = area->dx + area->width;
+	y2 = area->dy + area->height;
+	dx = area->dx > 0 ? area->dx : 0;
+	dy = area->dy > 0 ? area->dy : 0;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - dx;
+	height = y2 - dy;
+
+	if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+		return;
+
+	/* update sx,sy */
+	sx = area->sx + (dx - area->dx);
+	sy = area->sy + (dy - area->dy);
+
+	/* the source must be completely inside the virtual screen */
+	if (sx + width > info->var.xres_virtual ||
+			sy + height > info->var.yres_virtual)
+		return;
+
+	if (dy > sy || (dy == sy && dx > sx)) {
+		dy += height;
+		sy += height;
+		rev_copy = 1;
+	}
+
+	if (info->var.bits_per_pixel == 1)
+		atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+	else if (info->var.bits_per_pixel == 2)
+		atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+	else if (info->var.bits_per_pixel == 4)
+		atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+	else
+		atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+
+	return;
+}
+
+static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+	int x2, y2;
+	unsigned long *dst;
+	int dst_idx;
+	const char *src;
+	u32 dx, dy, width, height, pitch;
+
+#ifdef ATAFB_FALCON
+	if (info->var.bits_per_pixel == 16) {
+		cfb_imageblit(info, image);
+		return;
+	}
+#endif
+
+	/*
+	 * We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly like we are
+	 * doing here.
+	 */
+	x2 = image->dx + image->width;
+	y2 = image->dy + image->height;
+	dx = image->dx;
+	dy = image->dy;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - dx;
+	height = y2 - dy;
+
+	if (image->depth == 1) {
+		// used for font data
+		dst = (unsigned long *)
+			((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+		dst_idx += dy * par->next_line * 8 + dx;
+		src = image->data;
+		pitch = (image->width + 7) / 8;
+		while (height--) {
+
+			if (info->var.bits_per_pixel == 1)
+				atafb_mfb_linefill(info, par->next_line,
+						   dy, dx, width, src,
+						   image->bg_color, image->fg_color);
+			else if (info->var.bits_per_pixel == 2)
+				atafb_iplan2p2_linefill(info, par->next_line,
+							dy, dx, width, src,
+							image->bg_color, image->fg_color);
+			else if (info->var.bits_per_pixel == 4)
+				atafb_iplan2p4_linefill(info, par->next_line,
+							dy, dx, width, src,
+							image->bg_color, image->fg_color);
+			else
+				atafb_iplan2p8_linefill(info, par->next_line,
+							dy, dx, width, src,
+							image->bg_color, image->fg_color);
+			dy++;
+			src += pitch;
+		}
+	} else {
+		c2p_iplan2(info->screen_base, image->data, dx, dy, width,
+			   height, par->next_line, image->width,
+			   info->var.bits_per_pixel);
+	}
+}
+
+static int
+atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+#ifdef FBCMD_GET_CURRENTPAR
+	case FBCMD_GET_CURRENTPAR:
+		if (copy_to_user((void *)arg, (void *)&current_par,
+				 sizeof(struct atafb_par)))
+			return -EFAULT;
+		return 0;
+#endif
+#ifdef FBCMD_SET_CURRENTPAR
+	case FBCMD_SET_CURRENTPAR:
+		if (copy_from_user((void *)&current_par, (void *)arg,
+				   sizeof(struct atafb_par)))
+			return -EFAULT;
+		ata_set_par(&current_par);
+		return 0;
+#endif
+	}
+	return -EINVAL;
+}
+
+/* (un)blank/poweroff
+ * 0 = unblank
+ * 1 = blank
+ * 2 = suspend vsync
+ * 3 = suspend hsync
+ * 4 = off
+ */
+static int atafb_blank(int blank, struct fb_info *info)
+{
+	unsigned short black[16];
+	struct fb_cmap cmap;
+	if (fbhw->blank && !fbhw->blank(blank))
+		return 1;
+	if (blank) {
+		memset(black, 0, 16 * sizeof(unsigned short));
+		cmap.red = black;
+		cmap.green = black;
+		cmap.blue = black;
+		cmap.transp = NULL;
+		cmap.start = 0;
+		cmap.len = 16;
+		fb_set_cmap(&cmap, info);
+	}
+#if 0
+	else
+		do_install_cmap(info);
+#endif
+	return 0;
+}
+
+	/*
+	 * New fbcon interface ...
+	 */
+
+	 /* check var by decoding var into hw par, rounding if necessary,
+	  * then encoding hw par back into new, validated var */
+static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int err;
+	struct atafb_par par;
+
+	/* Validate wanted screen parameters */
+	// if ((err = ata_decode_var(var, &par)))
+	err = fbhw->decode_var(var, &par);
+	if (err)
+		return err;
+
+	/* Encode (possibly rounded) screen parameters */
+	fbhw->encode_var(var, &par);
+	return 0;
+}
+
+	/* actually set hw par by decoding var, then setting hardware from
+	 * hw par just decoded */
+static int atafb_set_par(struct fb_info *info)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+
+	/* Decode wanted screen parameters */
+	fbhw->decode_var(&info->var, par);
+	mutex_lock(&info->mm_lock);
+	fbhw->encode_fix(&info->fix, par);
+	mutex_unlock(&info->mm_lock);
+
+	/* Set new videomode */
+	ata_set_par(par);
+
+	return 0;
+}
+
+
+static struct fb_ops atafb_ops = {
+	.owner =	THIS_MODULE,
+	.fb_check_var	= atafb_check_var,
+	.fb_set_par	= atafb_set_par,
+	.fb_setcolreg	= atafb_setcolreg,
+	.fb_blank =	atafb_blank,
+	.fb_pan_display	= atafb_pan_display,
+	.fb_fillrect	= atafb_fillrect,
+	.fb_copyarea	= atafb_copyarea,
+	.fb_imageblit	= atafb_imageblit,
+	.fb_ioctl =	atafb_ioctl,
+};
+
+static void check_default_par(int detected_mode)
+{
+	char default_name[10];
+	int i;
+	struct fb_var_screeninfo var;
+	unsigned long min_mem;
+
+	/* First try the user supplied mode */
+	if (default_par) {
+		var = atafb_predefined[default_par - 1];
+		var.activate = FB_ACTIVATE_TEST;
+		if (do_fb_set_var(&var, 1))
+			default_par = 0;	/* failed */
+	}
+	/* Next is the autodetected one */
+	if (!default_par) {
+		var = atafb_predefined[detected_mode - 1]; /* autodetect */
+		var.activate = FB_ACTIVATE_TEST;
+		if (!do_fb_set_var(&var, 1))
+			default_par = detected_mode;
+	}
+	/* If that also failed, try some default modes... */
+	if (!default_par) {
+		/* try default1, default2... */
+		for (i = 1; i < 10; i++) {
+			sprintf(default_name,"default%d", i);
+			default_par = get_video_mode(default_name);
+			if (!default_par)
+				panic("can't set default video mode");
+			var = atafb_predefined[default_par - 1];
+			var.activate = FB_ACTIVATE_TEST;
+			if (!do_fb_set_var(&var,1))
+				break;	/* ok */
+		}
+	}
+	min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
+	if (default_mem_req < min_mem)
+		default_mem_req = min_mem;
+}
+
+#ifdef ATAFB_EXT
+static void __init atafb_setup_ext(char *spec)
+{
+	int xres, xres_virtual, yres, depth, planes;
+	unsigned long addr, len;
+	char *p;
+
+	/* Format is: <xres>;<yres>;<depth>;<plane organ.>;
+	 *            <screen mem addr>
+	 *	      [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
+	 *	      [;<xres-virtual>]]]]]
+	 *
+	 * 09/23/97	Juergen
+	 * <xres_virtual>:	hardware's x-resolution (f.e. ProMST)
+	 *
+	 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
+	 */
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
+	xres_virtual = xres = simple_strtoul(p, NULL, 10);
+	if (xres <= 0)
+		return;
+
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
+	yres = simple_strtoul(p, NULL, 10);
+	if (yres <= 0)
+		return;
+
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
+	depth = simple_strtoul(p, NULL, 10);
+	if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
+	    depth != 16 && depth != 24)
+		return;
+
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
+	if (*p == 'i')
+		planes = FB_TYPE_INTERLEAVED_PLANES;
+	else if (*p == 'p')
+		planes = FB_TYPE_PACKED_PIXELS;
+	else if (*p == 'n')
+		planes = FB_TYPE_PLANES;
+	else if (*p == 't')
+		planes = -1;		/* true color */
+	else
+		return;
+
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
+	addr = simple_strtoul(p, NULL, 0);
+
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		len = xres * yres * depth / 8;
+	else
+		len = simple_strtoul(p, NULL, 0);
+
+	p = strsep(&spec, ";");
+	if (p && *p)
+		external_vgaiobase = simple_strtoul(p, NULL, 0);
+
+	p = strsep(&spec, ";");
+	if (p && *p) {
+		external_bitspercol = simple_strtoul(p, NULL, 0);
+		if (external_bitspercol > 8)
+			external_bitspercol = 8;
+		else if (external_bitspercol < 1)
+			external_bitspercol = 1;
+	}
+
+	p = strsep(&spec, ";");
+	if (p && *p) {
+		if (!strcmp(p, "vga"))
+			external_card_type = IS_VGA;
+		if (!strcmp(p, "mv300"))
+			external_card_type = IS_MV300;
+	}
+
+	p = strsep(&spec, ";");
+	if (p && *p) {
+		xres_virtual = simple_strtoul(p, NULL, 10);
+		if (xres_virtual < xres)
+			xres_virtual = xres;
+		if (xres_virtual * yres * depth / 8 > len)
+			len = xres_virtual * yres * depth / 8;
+	}
+
+	external_xres = xres;
+	external_xres_virtual = xres_virtual;
+	external_yres = yres;
+	external_depth = depth;
+	external_pmode = planes;
+	external_addr = (void *)addr;
+	external_len = len;
+
+	if (external_card_type == IS_MV300) {
+		switch (external_depth) {
+		case 1:
+			MV300_reg = MV300_reg_1bit;
+			break;
+		case 4:
+			MV300_reg = MV300_reg_4bit;
+			break;
+		case 8:
+			MV300_reg = MV300_reg_8bit;
+			break;
+		}
+	}
+}
+#endif /* ATAFB_EXT */
+
+static void __init atafb_setup_int(char *spec)
+{
+	/* Format to config extended internal video hardware like OverScan:
+	 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
+	 * Explanation:
+	 * <xres>: x-resolution
+	 * <yres>: y-resolution
+	 * The following are only needed if you have an overscan which
+	 * needs a black border:
+	 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
+	 * <yres_max>: max. number of lines your OverScan hardware would allow
+	 * <offset>: Offset from physical beginning to visible beginning
+	 *	  of screen in bytes
+	 */
+	int xres;
+	char *p;
+
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	xres = simple_strtoul(p, NULL, 10);
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	sttt_xres = xres;
+	tt_yres = st_yres = simple_strtoul(p, NULL, 10);
+	if ((p = strsep(&spec, ";")) && *p)
+		sttt_xres_virtual = simple_strtoul(p, NULL, 10);
+	if ((p = strsep(&spec, ";")) && *p)
+		sttt_yres_virtual = simple_strtoul(p, NULL, 0);
+	if ((p = strsep(&spec, ";")) && *p)
+		ovsc_offset = simple_strtoul(p, NULL, 0);
+
+	if (ovsc_offset || (sttt_yres_virtual != st_yres))
+		use_hwscroll = 0;
+}
+
+#ifdef ATAFB_FALCON
+static void __init atafb_setup_mcap(char *spec)
+{
+	char *p;
+	int vmin, vmax, hmin, hmax;
+
+	/* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
+	 * <V*> vertical freq. in Hz
+	 * <H*> horizontal freq. in kHz
+	 */
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	vmin = simple_strtoul(p, NULL, 10);
+	if (vmin <= 0)
+		return;
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	vmax = simple_strtoul(p, NULL, 10);
+	if (vmax <= 0 || vmax <= vmin)
+		return;
+	if (!(p = strsep(&spec, ";")) || !*p)
+		return;
+	hmin = 1000 * simple_strtoul(p, NULL, 10);
+	if (hmin <= 0)
+		return;
+	if (!(p = strsep(&spec, "")) || !*p)
+		return;
+	hmax = 1000 * simple_strtoul(p, NULL, 10);
+	if (hmax <= 0 || hmax <= hmin)
+		return;
+
+	fb_info.monspecs.vfmin = vmin;
+	fb_info.monspecs.vfmax = vmax;
+	fb_info.monspecs.hfmin = hmin;
+	fb_info.monspecs.hfmax = hmax;
+}
+#endif /* ATAFB_FALCON */
+
+static void __init atafb_setup_user(char *spec)
+{
+	/* Format of user defined video mode is: <xres>;<yres>;<depth>
+	 */
+	char *p;
+	int xres, yres, depth, temp;
+
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
+	xres = simple_strtoul(p, NULL, 10);
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
+	yres = simple_strtoul(p, NULL, 10);
+	p = strsep(&spec, "");
+	if (!p || !*p)
+		return;
+	depth = simple_strtoul(p, NULL, 10);
+	temp = get_video_mode("user0");
+	if (temp) {
+		default_par = temp;
+		atafb_predefined[default_par - 1].xres = xres;
+		atafb_predefined[default_par - 1].yres = yres;
+		atafb_predefined[default_par - 1].bits_per_pixel = depth;
+	}
+}
+
+int __init atafb_setup(char *options)
+{
+	char *this_opt;
+	int temp;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if ((temp = get_video_mode(this_opt))) {
+			default_par = temp;
+			mode_option = this_opt;
+		} else if (!strcmp(this_opt, "inverse"))
+			inverse = 1;
+		else if (!strncmp(this_opt, "hwscroll_", 9)) {
+			hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
+			if (hwscroll < 0)
+				hwscroll = 0;
+			if (hwscroll > 200)
+				hwscroll = 200;
+		}
+#ifdef ATAFB_EXT
+		else if (!strcmp(this_opt, "mv300")) {
+			external_bitspercol = 8;
+			external_card_type = IS_MV300;
+		} else if (!strncmp(this_opt, "external:", 9))
+			atafb_setup_ext(this_opt + 9);
+#endif
+		else if (!strncmp(this_opt, "internal:", 9))
+			atafb_setup_int(this_opt + 9);
+#ifdef ATAFB_FALCON
+		else if (!strncmp(this_opt, "eclock:", 7)) {
+			fext.f = simple_strtoul(this_opt + 7, NULL, 10);
+			/* external pixelclock in kHz --> ps */
+			fext.t = 1000000000 / fext.f;
+			fext.f *= 1000;
+		} else if (!strncmp(this_opt, "monitorcap:", 11))
+			atafb_setup_mcap(this_opt + 11);
+#endif
+		else if (!strcmp(this_opt, "keep"))
+			DontCalcRes = 1;
+		else if (!strncmp(this_opt, "R", 1))
+			atafb_setup_user(this_opt + 1);
+	}
+	return 0;
+}
+
+int __init atafb_init(void)
+{
+	int pad, detected_mode, error;
+	unsigned int defmode = 0;
+	unsigned long mem_req;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("atafb", &option))
+		return -ENODEV;
+	atafb_setup(option);
+#endif
+	printk("atafb_init: start\n");
+
+	if (!MACH_IS_ATARI)
+		return -ENODEV;
+
+	do {
+#ifdef ATAFB_EXT
+		if (external_addr) {
+			printk("atafb_init: initializing external hw\n");
+			fbhw = &ext_switch;
+			atafb_ops.fb_setcolreg = &ext_setcolreg;
+			defmode = DEFMODE_EXT;
+			break;
+		}
+#endif
+#ifdef ATAFB_TT
+		if (ATARIHW_PRESENT(TT_SHIFTER)) {
+			printk("atafb_init: initializing TT hw\n");
+			fbhw = &tt_switch;
+			atafb_ops.fb_setcolreg = &tt_setcolreg;
+			defmode = DEFMODE_TT;
+			break;
+		}
+#endif
+#ifdef ATAFB_FALCON
+		if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
+			printk("atafb_init: initializing Falcon hw\n");
+			fbhw = &falcon_switch;
+			atafb_ops.fb_setcolreg = &falcon_setcolreg;
+			error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher,
+					    IRQ_TYPE_PRIO,
+					    "framebuffer:modeswitch",
+					    falcon_vbl_switcher);
+			if (error)
+				return error;
+			defmode = DEFMODE_F30;
+			break;
+		}
+#endif
+#ifdef ATAFB_STE
+		if (ATARIHW_PRESENT(STND_SHIFTER) ||
+		    ATARIHW_PRESENT(EXTD_SHIFTER)) {
+			printk("atafb_init: initializing ST/E hw\n");
+			fbhw = &st_switch;
+			atafb_ops.fb_setcolreg = &stste_setcolreg;
+			defmode = DEFMODE_STE;
+			break;
+		}
+		fbhw = &st_switch;
+		atafb_ops.fb_setcolreg = &stste_setcolreg;
+		printk("Cannot determine video hardware; defaulting to ST(e)\n");
+#else /* ATAFB_STE */
+		/* no default driver included */
+		/* Nobody will ever see this message :-) */
+		panic("Cannot initialize video hardware");
+#endif
+	} while (0);
+
+	/* Multisync monitor capabilities */
+	/* Atari-TOS defaults if no boot option present */
+	if (fb_info.monspecs.hfmin == 0) {
+		fb_info.monspecs.hfmin = 31000;
+		fb_info.monspecs.hfmax = 32000;
+		fb_info.monspecs.vfmin = 58;
+		fb_info.monspecs.vfmax = 62;
+	}
+
+	detected_mode = fbhw->detect();
+	check_default_par(detected_mode);
+#ifdef ATAFB_EXT
+	if (!external_addr) {
+#endif /* ATAFB_EXT */
+		mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
+		mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
+		screen_base = atari_stram_alloc(mem_req, "atafb");
+		if (!screen_base)
+			panic("Cannot allocate screen memory");
+		memset(screen_base, 0, mem_req);
+		pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
+		screen_base += pad;
+		real_screen_base = screen_base + ovsc_offset;
+		screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
+		st_ovsc_switch();
+		if (CPU_IS_040_OR_060) {
+			/* On a '040+, the cache mode of video RAM must be set to
+			 * write-through also for internal video hardware! */
+			cache_push(virt_to_phys(screen_base), screen_len);
+			kernel_set_cachemode(screen_base, screen_len,
+					     IOMAP_WRITETHROUGH);
+		}
+		printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
+			screen_base, real_screen_base, screen_len);
+#ifdef ATAFB_EXT
+	} else {
+		/* Map the video memory (physical address given) to somewhere
+		 * in the kernel address space.
+		 */
+		external_addr = ioremap_writethrough((unsigned long)external_addr,
+						     external_len);
+		if (external_vgaiobase)
+			external_vgaiobase =
+			  (unsigned long)ioremap(external_vgaiobase, 0x10000);
+		screen_base =
+		real_screen_base = external_addr;
+		screen_len = external_len & PAGE_MASK;
+		memset (screen_base, 0, external_len);
+	}
+#endif /* ATAFB_EXT */
+
+//	strcpy(fb_info.mode->name, "Atari Builtin ");
+	fb_info.fbops = &atafb_ops;
+	// try to set default (detected; requested) var
+	do_fb_set_var(&atafb_predefined[default_par - 1], 1);
+	// reads hw state into current par, which may not be sane yet
+	ata_get_par(&current_par);
+	fb_info.par = &current_par;
+	// tries to read from HW which may not be initialized yet
+	// so set sane var first, then call atafb_set_par
+	atafb_get_var(&fb_info.var, &fb_info);
+
+#ifdef ATAFB_FALCON
+	fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
+#endif
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
+			  NUM_TOTAL_MODES, &atafb_modedb[defmode],
+			  fb_info.var.bits_per_pixel)) {
+		return -EINVAL;
+	}
+
+	fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
+				 &fb_info.modelist);
+
+	atafb_set_disp(&fb_info);
+
+	fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
+
+
+	printk("Determined %dx%d, depth %d\n",
+	       fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
+	if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
+	    (fb_info.var.yres != fb_info.var.yres_virtual))
+		printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
+		       fb_info.var.yres_virtual);
+
+	if (register_framebuffer(&fb_info) < 0) {
+#ifdef ATAFB_EXT
+		if (external_addr) {
+			iounmap(external_addr);
+			external_addr = NULL;
+		}
+		if (external_vgaiobase) {
+			iounmap((void*)external_vgaiobase);
+			external_vgaiobase = 0;
+		}
+#endif
+		return -EINVAL;
+	}
+
+	fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
+		screen_len >> 10);
+
+	/* TODO: This driver cannot be unloaded yet */
+	return 0;
+}
+
+module_init(atafb_init);
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int cleanup_module(void)
+{
+	unregister_framebuffer(&fb_info);
+	return atafb_deinit();
+}
+#endif /* MODULE */
diff --git a/drivers/video/fbdev/atafb.h b/drivers/video/fbdev/atafb.h
new file mode 100644
index 000000000000..014e05906cb1
--- /dev/null
+++ b/drivers/video/fbdev/atafb.h
@@ -0,0 +1,36 @@
+#ifndef _VIDEO_ATAFB_H
+#define _VIDEO_ATAFB_H
+
+void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			int dx, int height, int width);
+void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			int sy, int sx, int height, int width);
+void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
+			int dy, int dx, u32 width,
+			const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			     int dx, int height, int width);
+void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			     int sy, int sx, int height, int width);
+void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			     int dx, int height, int width);
+void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			     int sy, int sx, int height, int width);
+void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			     int dx, int height, int width);
+void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			     int sy, int sx, int height, int width);
+void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor);
+
+#endif /* _VIDEO_ATAFB_H */
diff --git a/drivers/video/fbdev/atafb_iplan2p2.c b/drivers/video/fbdev/atafb_iplan2p2.c
new file mode 100644
index 000000000000..8cc9c50379d0
--- /dev/null
+++ b/drivers/video/fbdev/atafb_iplan2p2.c
@@ -0,0 +1,293 @@
+/*
+ *  linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for
+ *				      interleaved bitplanes à la Atari (2
+ *				      planes, 2 bytes interleave)
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL	2
+#include "atafb_utils.h"
+
+void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line,
+			     int sy, int sx, int dy, int dx,
+			     int height, int width)
+{
+	/*  bmove() has to distinguish two major cases: If both, source and
+	 *  destination, start at even addresses or both are at odd
+	 *  addresses, just the first odd and last even column (if present)
+	 *  require special treatment (memmove_col()). The rest between
+	 *  then can be copied by normal operations, because all adjacent
+	 *  bytes are affected and are to be stored in the same order.
+	 *    The pathological case is when the move should go from an odd
+	 *  address to an even or vice versa. Since the bytes in the plane
+	 *  words must be assembled in new order, it seems wisest to make
+	 *  all movements by memmove_col().
+	 */
+
+	u8 *src, *dst;
+	u32 *s, *d;
+	int w, l , i, j;
+	u_int colsize;
+	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+	colsize = height;
+	if (!((sx ^ dx) & 15)) {
+		/* odd->odd or even->even */
+
+		if (upwards) {
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+			if (sx & 15) {
+				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+				src += BPL * 2;
+				dst += BPL * 2;
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*d++ = *s++;
+					s = (u32 *)((u8 *)s + l);
+					d = (u32 *)((u8 *)d + l);
+				}
+			}
+			if (width & 15)
+				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+					      0xff00ff00, height, next_line - BPL * 2);
+		} else {
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			if ((sx + width) & 15) {
+				src -= BPL * 2;
+				dst -= BPL * 2;
+				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*--d = *--s;
+					s = (u32 *)((u8 *)s - l);
+					d = (u32 *)((u8 *)d - l);
+				}
+			}
+			if (sx & 15)
+				memmove32_col(dst - (width - 16) / (8 / BPL),
+					      src - (width - 16) / (8 / BPL),
+					      0xff00ff, colsize, -next_line - BPL * 2);
+		}
+	} else {
+		/* odd->even or even->odd */
+		if (upwards) {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+			mask = 0xff00ff00;
+			f = 0;
+			w = width;
+			if (sx & 15) {
+				f = 1;
+				w += 8;
+			}
+			if ((sx + width) & 15)
+				f |= 2;
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = (*src32++ << 8) & mask;
+				} else {
+					pval[0] = dst32[0] & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[0] | (v1 >> 8);
+					pval[0] = (v ^ v1) << 8;
+				}
+
+				if (f & 2) {
+					dst32[0] = (dst32[0] & mask) | pval[0];
+				}
+
+				src += next_line;
+				dst += next_line;
+			}
+		} else {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			mask = 0xff00ff;
+			f = 0;
+			w = width;
+			if ((dx + width) & 15)
+				f = 1;
+			if (sx & 15) {
+				f |= 2;
+				w += 8;
+			}
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = dst32[-1] & mask;
+				} else {
+					pval[0] = (*--src32 >> 8) & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[0] | (v1 << 8);
+					pval[0] = (v ^ v1) >> 8;
+				}
+
+				if (!(f & 2)) {
+					dst32[-1] = (dst32[-1] & mask) | pval[0];
+				}
+
+				src -= next_line;
+				dst -= next_line;
+			}
+		}
+	}
+}
+
+void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+	u32 *dest;
+	int rows, i;
+	u32 cval[4];
+
+	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+	if (sx & 15) {
+		u8 *dest8 = (u8 *)dest + 1;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	expand16_col2mask(color, cval);
+	rows = width >> 4;
+	if (rows) {
+		u32 *d = dest;
+		u32 off = next_line - rows * BPL * 2;
+		for (i = height; i; i--) {
+			d = fill16_col(d, rows, cval);
+			d = (u32 *)((long)d + off);
+		}
+		dest += rows * BPL / 2;
+		width &= 15;
+	}
+
+	if (width) {
+		u8 *dest8 = (u8 *)dest;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+	}
+}
+
+void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
+                             int dy, int dx, u32 width,
+                             const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u32 *dest;
+	const u16 *data16;
+	int rows;
+	u32 fgm[4], bgm[4], m;
+
+	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+	if (dx & 15) {
+		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	if (width >= 16) {
+		data16 = (const u16 *)data;
+		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+		for (rows = width / 16; rows; rows--) {
+			u16 d = *data16++;
+			m = d | ((u32)d << 16);
+			*dest++ = (m & fgm[0]) ^ bgm[0];
+		}
+
+		data = (const u8 *)data16;
+		width &= 15;
+	}
+
+	if (width)
+		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p2_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p2_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p2_linefill);
diff --git a/drivers/video/fbdev/atafb_iplan2p4.c b/drivers/video/fbdev/atafb_iplan2p4.c
new file mode 100644
index 000000000000..bee0d89463f7
--- /dev/null
+++ b/drivers/video/fbdev/atafb_iplan2p4.c
@@ -0,0 +1,308 @@
+/*
+ *  linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for
+ *				      interleaved bitplanes à la Atari (4
+ *				      planes, 2 bytes interleave)
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL	4
+#include "atafb_utils.h"
+
+void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line,
+			     int sy, int sx, int dy, int dx,
+			     int height, int width)
+{
+	/*  bmove() has to distinguish two major cases: If both, source and
+	 *  destination, start at even addresses or both are at odd
+	 *  addresses, just the first odd and last even column (if present)
+	 *  require special treatment (memmove_col()). The rest between
+	 *  then can be copied by normal operations, because all adjacent
+	 *  bytes are affected and are to be stored in the same order.
+	 *    The pathological case is when the move should go from an odd
+	 *  address to an even or vice versa. Since the bytes in the plane
+	 *  words must be assembled in new order, it seems wisest to make
+	 *  all movements by memmove_col().
+	 */
+
+	u8 *src, *dst;
+	u32 *s, *d;
+	int w, l , i, j;
+	u_int colsize;
+	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+	colsize = height;
+	if (!((sx ^ dx) & 15)) {
+		/* odd->odd or even->even */
+
+		if (upwards) {
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+			if (sx & 15) {
+				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+				src += BPL * 2;
+				dst += BPL * 2;
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*d++ = *s++;
+					s = (u32 *)((u8 *)s + l);
+					d = (u32 *)((u8 *)d + l);
+				}
+			}
+			if (width & 15)
+				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+					      0xff00ff00, height, next_line - BPL * 2);
+		} else {
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			if ((sx + width) & 15) {
+				src -= BPL * 2;
+				dst -= BPL * 2;
+				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*--d = *--s;
+					s = (u32 *)((u8 *)s - l);
+					d = (u32 *)((u8 *)d - l);
+				}
+			}
+			if (sx & 15)
+				memmove32_col(dst - (width - 16) / (8 / BPL),
+					      src - (width - 16) / (8 / BPL),
+					      0xff00ff, colsize, -next_line - BPL * 2);
+		}
+	} else {
+		/* odd->even or even->odd */
+		if (upwards) {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+			mask = 0xff00ff00;
+			f = 0;
+			w = width;
+			if (sx & 15) {
+				f = 1;
+				w += 8;
+			}
+			if ((sx + width) & 15)
+				f |= 2;
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = (*src32++ << 8) & mask;
+					pval[1] = (*src32++ << 8) & mask;
+				} else {
+					pval[0] = dst32[0] & mask;
+					pval[1] = dst32[1] & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[0] | (v1 >> 8);
+					pval[0] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[1] | (v1 >> 8);
+					pval[1] = (v ^ v1) << 8;
+				}
+
+				if (f & 2) {
+					dst32[0] = (dst32[0] & mask) | pval[0];
+					dst32[1] = (dst32[1] & mask) | pval[1];
+				}
+
+				src += next_line;
+				dst += next_line;
+			}
+		} else {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			mask = 0xff00ff;
+			f = 0;
+			w = width;
+			if ((dx + width) & 15)
+				f = 1;
+			if (sx & 15) {
+				f |= 2;
+				w += 8;
+			}
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = dst32[-1] & mask;
+					pval[1] = dst32[-2] & mask;
+				} else {
+					pval[0] = (*--src32 >> 8) & mask;
+					pval[1] = (*--src32 >> 8) & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[0] | (v1 << 8);
+					pval[0] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[1] | (v1 << 8);
+					pval[1] = (v ^ v1) >> 8;
+				}
+
+				if (!(f & 2)) {
+					dst32[-1] = (dst32[-1] & mask) | pval[0];
+					dst32[-2] = (dst32[-2] & mask) | pval[1];
+				}
+
+				src -= next_line;
+				dst -= next_line;
+			}
+		}
+	}
+}
+
+void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+	u32 *dest;
+	int rows, i;
+	u32 cval[4];
+
+	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+	if (sx & 15) {
+		u8 *dest8 = (u8 *)dest + 1;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	expand16_col2mask(color, cval);
+	rows = width >> 4;
+	if (rows) {
+		u32 *d = dest;
+		u32 off = next_line - rows * BPL * 2;
+		for (i = height; i; i--) {
+			d = fill16_col(d, rows, cval);
+			d = (u32 *)((long)d + off);
+		}
+		dest += rows * BPL / 2;
+		width &= 15;
+	}
+
+	if (width) {
+		u8 *dest8 = (u8 *)dest;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+	}
+}
+
+void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
+                             int dy, int dx, u32 width,
+                             const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u32 *dest;
+	const u16 *data16;
+	int rows;
+	u32 fgm[4], bgm[4], m;
+
+	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+	if (dx & 15) {
+		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	if (width >= 16) {
+		data16 = (const u16 *)data;
+		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+		for (rows = width / 16; rows; rows--) {
+			u16 d = *data16++;
+			m = d | ((u32)d << 16);
+			*dest++ = (m & fgm[0]) ^ bgm[0];
+			*dest++ = (m & fgm[1]) ^ bgm[1];
+		}
+
+		data = (const u8 *)data16;
+		width &= 15;
+	}
+
+	if (width)
+		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p4_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p4_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p4_linefill);
diff --git a/drivers/video/fbdev/atafb_iplan2p8.c b/drivers/video/fbdev/atafb_iplan2p8.c
new file mode 100644
index 000000000000..356fb52ce443
--- /dev/null
+++ b/drivers/video/fbdev/atafb_iplan2p8.c
@@ -0,0 +1,345 @@
+/*
+ *  linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for
+ *				      interleaved bitplanes à la Atari (8
+ *				      planes, 2 bytes interleave)
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL	8
+#include "atafb_utils.h"
+
+
+/* Copies a 8 plane column from 's', height 'h', to 'd'. */
+
+/* This expands a 8 bit color into two longs for two movepl (8 plane)
+ * operations.
+ */
+
+void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line,
+			     int sy, int sx, int dy, int dx,
+			     int height, int width)
+{
+	/*  bmove() has to distinguish two major cases: If both, source and
+	 *  destination, start at even addresses or both are at odd
+	 *  addresses, just the first odd and last even column (if present)
+	 *  require special treatment (memmove_col()). The rest between
+	 *  then can be copied by normal operations, because all adjacent
+	 *  bytes are affected and are to be stored in the same order.
+	 *    The pathological case is when the move should go from an odd
+	 *  address to an even or vice versa. Since the bytes in the plane
+	 *  words must be assembled in new order, it seems wisest to make
+	 *  all movements by memmove_col().
+	 */
+
+	u8 *src, *dst;
+	u32 *s, *d;
+	int w, l , i, j;
+	u_int colsize;
+	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+	colsize = height;
+	if (!((sx ^ dx) & 15)) {
+		/* odd->odd or even->even */
+
+		if (upwards) {
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+			if (sx & 15) {
+				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+				src += BPL * 2;
+				dst += BPL * 2;
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*d++ = *s++;
+					s = (u32 *)((u8 *)s + l);
+					d = (u32 *)((u8 *)d + l);
+				}
+			}
+			if (width & 15)
+				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+					      0xff00ff00, height, next_line - BPL * 2);
+		} else {
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			if ((sx + width) & 15) {
+				src -= BPL * 2;
+				dst -= BPL * 2;
+				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*--d = *--s;
+					s = (u32 *)((u8 *)s - l);
+					d = (u32 *)((u8 *)d - l);
+				}
+			}
+			if (sx & 15)
+				memmove32_col(dst - (width - 16) / (8 / BPL),
+					      src - (width - 16) / (8 / BPL),
+					      0xff00ff, colsize, -next_line - BPL * 2);
+		}
+	} else {
+		/* odd->even or even->odd */
+		if (upwards) {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+			mask = 0xff00ff00;
+			f = 0;
+			w = width;
+			if (sx & 15) {
+				f = 1;
+				w += 8;
+			}
+			if ((sx + width) & 15)
+				f |= 2;
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = (*src32++ << 8) & mask;
+					pval[1] = (*src32++ << 8) & mask;
+					pval[2] = (*src32++ << 8) & mask;
+					pval[3] = (*src32++ << 8) & mask;
+				} else {
+					pval[0] = dst32[0] & mask;
+					pval[1] = dst32[1] & mask;
+					pval[2] = dst32[2] & mask;
+					pval[3] = dst32[3] & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[0] | (v1 >> 8);
+					pval[0] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[1] | (v1 >> 8);
+					pval[1] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[2] | (v1 >> 8);
+					pval[2] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[3] | (v1 >> 8);
+					pval[3] = (v ^ v1) << 8;
+				}
+
+				if (f & 2) {
+					dst32[0] = (dst32[0] & mask) | pval[0];
+					dst32[1] = (dst32[1] & mask) | pval[1];
+					dst32[2] = (dst32[2] & mask) | pval[2];
+					dst32[3] = (dst32[3] & mask) | pval[3];
+				}
+
+				src += next_line;
+				dst += next_line;
+			}
+		} else {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			mask = 0xff00ff;
+			f = 0;
+			w = width;
+			if ((dx + width) & 15)
+				f = 1;
+			if (sx & 15) {
+				f |= 2;
+				w += 8;
+			}
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = dst32[-1] & mask;
+					pval[1] = dst32[-2] & mask;
+					pval[2] = dst32[-3] & mask;
+					pval[3] = dst32[-4] & mask;
+				} else {
+					pval[0] = (*--src32 >> 8) & mask;
+					pval[1] = (*--src32 >> 8) & mask;
+					pval[2] = (*--src32 >> 8) & mask;
+					pval[3] = (*--src32 >> 8) & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[0] | (v1 << 8);
+					pval[0] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[1] | (v1 << 8);
+					pval[1] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[2] | (v1 << 8);
+					pval[2] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[3] | (v1 << 8);
+					pval[3] = (v ^ v1) >> 8;
+				}
+
+				if (!(f & 2)) {
+					dst32[-1] = (dst32[-1] & mask) | pval[0];
+					dst32[-2] = (dst32[-2] & mask) | pval[1];
+					dst32[-3] = (dst32[-3] & mask) | pval[2];
+					dst32[-4] = (dst32[-4] & mask) | pval[3];
+				}
+
+				src -= next_line;
+				dst -= next_line;
+			}
+		}
+	}
+}
+
+void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+	u32 *dest;
+	int rows, i;
+	u32 cval[4];
+
+	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+	if (sx & 15) {
+		u8 *dest8 = (u8 *)dest + 1;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	expand16_col2mask(color, cval);
+	rows = width >> 4;
+	if (rows) {
+		u32 *d = dest;
+		u32 off = next_line - rows * BPL * 2;
+		for (i = height; i; i--) {
+			d = fill16_col(d, rows, cval);
+			d = (u32 *)((long)d + off);
+		}
+		dest += rows * BPL / 2;
+		width &= 15;
+	}
+
+	if (width) {
+		u8 *dest8 = (u8 *)dest;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+	}
+}
+
+void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u32 *dest;
+	const u16 *data16;
+	int rows;
+	u32 fgm[4], bgm[4], m;
+
+	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+	if (dx & 15) {
+		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	if (width >= 16) {
+		data16 = (const u16 *)data;
+		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+		for (rows = width / 16; rows; rows--) {
+			u16 d = *data16++;
+			m = d | ((u32)d << 16);
+			*dest++ = (m & fgm[0]) ^ bgm[0];
+			*dest++ = (m & fgm[1]) ^ bgm[1];
+			*dest++ = (m & fgm[2]) ^ bgm[2];
+			*dest++ = (m & fgm[3]) ^ bgm[3];
+		}
+
+		data = (const u8 *)data16;
+		width &= 15;
+	}
+
+	if (width)
+		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p8_linefill);
diff --git a/drivers/video/fbdev/atafb_mfb.c b/drivers/video/fbdev/atafb_mfb.c
new file mode 100644
index 000000000000..6a352d62eecf
--- /dev/null
+++ b/drivers/video/fbdev/atafb_mfb.c
@@ -0,0 +1,112 @@
+/*
+ *  linux/drivers/video/mfb.c -- Low level frame buffer operations for
+ *				 monochrome
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include "atafb.h"
+#include "atafb_utils.h"
+
+
+    /*
+     *  Monochrome
+     */
+
+void atafb_mfb_copyarea(struct fb_info *info, u_long next_line,
+			int sy, int sx, int dy, int dx,
+			int height, int width)
+{
+	u8 *src, *dest;
+	u_int rows;
+
+	if (sx == 0 && dx == 0 && width == next_line) {
+		src = (u8 *)info->screen_base + sy * (width >> 3);
+		dest = (u8 *)info->screen_base + dy * (width >> 3);
+		fb_memmove(dest, src, height * (width >> 3));
+	} else if (dy <= sy) {
+		src = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
+		dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
+		for (rows = height; rows--;) {
+			fb_memmove(dest, src, width >> 3);
+			src += next_line;
+			dest += next_line;
+		}
+	} else {
+		src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3);
+		dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3);
+		for (rows = height; rows--;) {
+			fb_memmove(dest, src, width >> 3);
+			src -= next_line;
+			dest -= next_line;
+		}
+	}
+}
+
+void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			int sy, int sx, int height, int width)
+{
+	u8 *dest;
+	u_int rows;
+
+	dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
+
+	if (sx == 0 && width == next_line) {
+		if (color)
+			fb_memset255(dest, height * (width >> 3));
+		else
+			fb_memclear(dest, height * (width >> 3));
+	} else {
+		for (rows = height; rows--; dest += next_line) {
+			if (color)
+				fb_memset255(dest, width >> 3);
+			else
+				fb_memclear_small(dest, width >> 3);
+		}
+	}
+}
+
+void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
+			int dy, int dx, u32 width,
+			const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u8 *dest;
+	u_int rows;
+
+	dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
+
+	for (rows = width / 8; rows--; /* check margins */ ) {
+		// use fast_memmove or fb_memmove
+		*dest++ = *data++;
+	}
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_mfb_copyarea);
+EXPORT_SYMBOL(atafb_mfb_fillrect);
+EXPORT_SYMBOL(atafb_mfb_linefill);
diff --git a/drivers/video/fbdev/atafb_utils.h b/drivers/video/fbdev/atafb_utils.h
new file mode 100644
index 000000000000..ac9e19dc5057
--- /dev/null
+++ b/drivers/video/fbdev/atafb_utils.h
@@ -0,0 +1,400 @@
+#ifndef _VIDEO_ATAFB_UTILS_H
+#define _VIDEO_ATAFB_UTILS_H
+
+/* ================================================================= */
+/*                      Utility Assembler Functions                  */
+/* ================================================================= */
+
+/* ====================================================================== */
+
+/* Those of a delicate disposition might like to skip the next couple of
+ * pages.
+ *
+ * These functions are drop in replacements for memmove and
+ * memset(_, 0, _). However their five instances add at least a kilobyte
+ * to the object file. You have been warned.
+ *
+ * Not a great fan of assembler for the sake of it, but I think
+ * that these routines are at least 10 times faster than their C
+ * equivalents for large blits, and that's important to the lowest level of
+ * a graphics driver. Question is whether some scheme with the blitter
+ * would be faster. I suspect not for simple text system - not much
+ * asynchrony.
+ *
+ * Code is very simple, just gruesome expansion. Basic strategy is to
+ * increase data moved/cleared at each step to 16 bytes to reduce
+ * instruction per data move overhead. movem might be faster still
+ * For more than 15 bytes, we try to align the write direction on a
+ * longword boundary to get maximum speed. This is even more gruesome.
+ * Unaligned read/write used requires 68020+ - think this is a problem?
+ *
+ * Sorry!
+ */
+
+
+/* ++roman: I've optimized Robert's original versions in some minor
+ * aspects, e.g. moveq instead of movel, let gcc choose the registers,
+ * use movem in some places...
+ * For other modes than 1 plane, lots of more such assembler functions
+ * were needed (e.g. the ones using movep or expanding color values).
+ */
+
+/* ++andreas: more optimizations:
+   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
+   addal is faster than addaw
+   movep is rather expensive compared to ordinary move's
+   some functions rewritten in C for clarity, no speed loss */
+
+static inline void *fb_memclear_small(void *s, size_t count)
+{
+	if (!count)
+		return 0;
+
+	asm volatile ("\n"
+		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
+		"1:"
+		: "=a" (s), "=d" (count)
+		: "d" (0), "0" ((char *)s + count), "1" (count));
+	asm volatile ("\n"
+		"	subq.l  #1,%1\n"
+		"	jcs	3f\n"
+		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
+		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
+		"	dbra	%1,2b\n"
+		"3:"
+		: "=a" (s), "=d" (count)
+		: "d" (0), "0" (s), "1" (count)
+		: "d4", "d5", "d6"
+		);
+
+	return 0;
+}
+
+
+static inline void *fb_memclear(void *s, size_t count)
+{
+	if (!count)
+		return 0;
+
+	if (count < 16) {
+		asm volatile ("\n"
+			"	lsr.l	#1,%1 ; jcc 1f ; clr.b (%0)+\n"
+			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.w (%0)+\n"
+			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+\n"
+			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n"
+			"1:"
+			: "=a" (s), "=d" (count)
+			: "0" (s), "1" (count));
+	} else {
+		long tmp;
+		asm volatile ("\n"
+			"	move.l	%1,%2\n"
+			"	lsr.l	#1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n"
+			"	lsr.l	#1,%2 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+			"	clr.w	(%0)+  ; subq.w  #2,%1 ; jra 2f\n"
+			"1:	lsr.l	#1,%2 ; jcc 2f\n"
+			"	clr.w	(%0)+  ; subq.w  #2,%1\n"
+			"2:	move.w	%1,%2; lsr.l #2,%1 ; jeq 6f\n"
+			"	lsr.l	#1,%1 ; jcc 3f ; clr.l (%0)+\n"
+			"3:	lsr.l	#1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n"
+			"4:	subq.l	#1,%1 ; jcs 6f\n"
+			"5:	clr.l	(%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n"
+			"	dbra	%1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n"
+			"6:	move.w	%2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n"
+			"7:	btst	#0,%1 ; jeq 8f ; clr.b (%0)+\n"
+			"8:"
+			: "=a" (s), "=d" (count), "=d" (tmp)
+			: "0" (s), "1" (count));
+	}
+
+	return 0;
+}
+
+
+static inline void *fb_memset255(void *s, size_t count)
+{
+	if (!count)
+		return 0;
+
+	asm volatile ("\n"
+		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
+		"1:"
+		: "=a" (s), "=d" (count)
+		: "d" (-1), "0" ((char *)s+count), "1" (count));
+	asm volatile ("\n"
+		"	subq.l	#1,%1 ; jcs 3f\n"
+		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
+		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
+		"	dbra	%1,2b\n"
+		"3:"
+		: "=a" (s), "=d" (count)
+		: "d" (-1), "0" (s), "1" (count)
+		: "d4", "d5", "d6");
+
+	return 0;
+}
+
+
+static inline void *fb_memmove(void *d, const void *s, size_t count)
+{
+	if (d < s) {
+		if (count < 16) {
+			asm volatile ("\n"
+				"	lsr.l	#1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
+				"1:"
+				: "=a" (d), "=a" (s), "=d" (count)
+				: "0" (d), "1" (s), "2" (count));
+		} else {
+			long tmp;
+			asm volatile ("\n"
+				"	move.l	%0,%3\n"
+				"	lsr.l	#1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n"
+				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2 ; jra 2f\n"
+				"1:	lsr.l   #1,%3 ; jcc 2f\n"
+				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2\n"
+				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
+				"	lsr.l	#1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n"
+				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
+				"4:	subq.l	#1,%2 ; jcs 6f\n"
+				"5:	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
+				"	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
+				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
+				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n"
+				"7:	btst	#0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n"
+				"8:"
+				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+				: "0" (d), "1" (s), "2" (count));
+		}
+	} else {
+		if (count < 16) {
+			asm volatile ("\n"
+				"	lsr.l	#1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
+				"1:"
+				: "=a" (d), "=a" (s), "=d" (count)
+				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
+		} else {
+			long tmp;
+
+			asm volatile ("\n"
+				"	move.l	%0,%3\n"
+				"	lsr.l	#1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n"
+				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+				"	move.w	-(%1),-(%0) ; subqw  #2,%2 ; jra 2f\n"
+				"1:	lsr.l	#1,%3 ; jcc 2f\n"
+				"	move.w	-(%1),-(%0) ; subqw  #2,%2\n"
+				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
+				"	lsr.l	#1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n"
+				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
+				"4:	subq.l	#1,%2 ; jcs 6f\n"
+				"5:	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
+				"	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
+				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
+				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n"
+				"7:	btst	#0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n"
+				"8:"
+				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
+		}
+	}
+
+	return 0;
+}
+
+
+/* ++andreas: Simple and fast version of memmove, assumes size is
+   divisible by 16, suitable for moving the whole screen bitplane */
+static inline void fast_memmove(char *dst, const char *src, size_t size)
+{
+	if (!size)
+		return;
+	if (dst < src)
+		asm volatile ("\n"
+			"1:	movem.l	(%0)+,%%d0/%%d1/%%a0/%%a1\n"
+			"	movem.l	%%d0/%%d1/%%a0/%%a1,%1@\n"
+			"	addq.l	#8,%1; addq.l #8,%1\n"
+			"	dbra	%2,1b\n"
+			"	clr.w	%2; subq.l #1,%2\n"
+			"	jcc	1b"
+			: "=a" (src), "=a" (dst), "=d" (size)
+			: "0" (src), "1" (dst), "2" (size / 16 - 1)
+			: "d0", "d1", "a0", "a1", "memory");
+	else
+		asm volatile ("\n"
+			"1:	subq.l	#8,%0; subq.l #8,%0\n"
+			"	movem.l	%0@,%%d0/%%d1/%%a0/%%a1\n"
+			"	movem.l	%%d0/%%d1/%%a0/%%a1,-(%1)\n"
+			"	dbra	%2,1b\n"
+			"	clr.w	%2; subq.l #1,%2\n"
+			"	jcc 1b"
+			: "=a" (src), "=a" (dst), "=d" (size)
+			: "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
+			: "d0", "d1", "a0", "a1", "memory");
+}
+
+#ifdef BPL
+
+/*
+ * This expands a up to 8 bit color into two longs
+ * for movel operations.
+ */
+static const u32 four2long[] = {
+	0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+	0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+	0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+	0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff,
+};
+
+static inline void expand8_col2mask(u8 c, u32 m[])
+{
+	m[0] = four2long[c & 15];
+#if BPL > 4
+	m[1] = four2long[c >> 4];
+#endif
+}
+
+static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
+{
+	fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]);
+#if BPL > 4
+	fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]);
+#endif
+}
+
+/*
+ * set an 8bit value to a color
+ */
+static inline void fill8_col(u8 *dst, u32 m[])
+{
+	u32 tmp = m[0];
+	dst[0] = tmp;
+	dst[2] = (tmp >>= 8);
+#if BPL > 2
+	dst[4] = (tmp >>= 8);
+	dst[6] = tmp >> 8;
+#endif
+#if BPL > 4
+	tmp = m[1];
+	dst[8] = tmp;
+	dst[10] = (tmp >>= 8);
+	dst[12] = (tmp >>= 8);
+	dst[14] = tmp >> 8;
+#endif
+}
+
+/*
+ * set an 8bit value according to foreground/background color
+ */
+static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask)
+{
+	u32 fgm[2], bgm[2], tmp;
+
+	expand8_2col2mask(fg, bg, fgm, bgm);
+
+	mask |= mask << 8;
+#if BPL > 2
+	mask |= mask << 16;
+#endif
+	tmp = (mask & fgm[0]) ^ bgm[0];
+	dst[0] = tmp;
+	dst[2] = (tmp >>= 8);
+#if BPL > 2
+	dst[4] = (tmp >>= 8);
+	dst[6] = tmp >> 8;
+#endif
+#if BPL > 4
+	tmp = (mask & fgm[1]) ^ bgm[1];
+	dst[8] = tmp;
+	dst[10] = (tmp >>= 8);
+	dst[12] = (tmp >>= 8);
+	dst[14] = tmp >> 8;
+#endif
+}
+
+static const u32 two2word[] = {
+	0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+};
+
+static inline void expand16_col2mask(u8 c, u32 m[])
+{
+	m[0] = two2word[c & 3];
+#if BPL > 2
+	m[1] = two2word[(c >> 2) & 3];
+#endif
+#if BPL > 4
+	m[2] = two2word[(c >> 4) & 3];
+	m[3] = two2word[c >> 6];
+#endif
+}
+
+static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
+{
+	bgm[0] = two2word[bg & 3];
+	fgm[0] = two2word[fg & 3] ^ bgm[0];
+#if BPL > 2
+	bgm[1] = two2word[(bg >> 2) & 3];
+	fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1];
+#endif
+#if BPL > 4
+	bgm[2] = two2word[(bg >> 4) & 3];
+	fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2];
+	bgm[3] = two2word[bg >> 6];
+	fgm[3] = two2word[fg >> 6] ^ bgm[3];
+#endif
+}
+
+static inline u32 *fill16_col(u32 *dst, int rows, u32 m[])
+{
+	while (rows) {
+		*dst++ = m[0];
+#if BPL > 2
+		*dst++ = m[1];
+#endif
+#if BPL > 4
+		*dst++ = m[2];
+		*dst++ = m[3];
+#endif
+		rows--;
+	}
+	return dst;
+}
+
+static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes)
+{
+	u32 *s, *d, v;
+
+        s = src;
+        d = dst;
+        do {
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#if BPL > 2
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#endif
+#if BPL > 4
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#endif
+                d = (u32 *)((u8 *)d + bytes);
+                s = (u32 *)((u8 *)s + bytes);
+        } while (--h);
+}
+
+#endif
+
+#endif /* _VIDEO_ATAFB_UTILS_H */
diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c
new file mode 100644
index 000000000000..e683b6ef9594
--- /dev/null
+++ b/drivers/video/fbdev/atmel_lcdfb.c
@@ -0,0 +1,1453 @@
+/*
+ *  Driver for AT91/AT32 LCD Controller
+ *
+ *  Copyright (C) 2007 Atmel Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/backlight.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/platform_data/atmel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+#include <mach/cpu.h>
+#include <asm/gpio.h>
+
+#include <video/atmel_lcdc.h>
+
+struct atmel_lcdfb_config {
+	bool have_alt_pixclock;
+	bool have_hozval;
+	bool have_intensity_bit;
+};
+
+ /* LCD Controller info data structure, stored in device platform_data */
+struct atmel_lcdfb_info {
+	spinlock_t		lock;
+	struct fb_info		*info;
+	void __iomem		*mmio;
+	int			irq_base;
+	struct work_struct	task;
+
+	unsigned int		smem_len;
+	struct platform_device	*pdev;
+	struct clk		*bus_clk;
+	struct clk		*lcdc_clk;
+
+	struct backlight_device	*backlight;
+	u8			bl_power;
+	u8			saved_lcdcon;
+
+	u32			pseudo_palette[16];
+	bool			have_intensity_bit;
+
+	struct atmel_lcdfb_pdata pdata;
+
+	struct atmel_lcdfb_config *config;
+};
+
+struct atmel_lcdfb_power_ctrl_gpio {
+	int gpio;
+	int active_low;
+
+	struct list_head list;
+};
+
+#define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
+#define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))
+
+/* configurable parameters */
+#define ATMEL_LCDC_CVAL_DEFAULT		0xc8
+#define ATMEL_LCDC_DMA_BURST_LEN	8	/* words */
+#define ATMEL_LCDC_FIFO_SIZE		512	/* words */
+
+static struct atmel_lcdfb_config at91sam9261_config = {
+	.have_hozval		= true,
+	.have_intensity_bit	= true,
+};
+
+static struct atmel_lcdfb_config at91sam9263_config = {
+	.have_intensity_bit	= true,
+};
+
+static struct atmel_lcdfb_config at91sam9g10_config = {
+	.have_hozval		= true,
+};
+
+static struct atmel_lcdfb_config at91sam9g45_config = {
+	.have_alt_pixclock	= true,
+};
+
+static struct atmel_lcdfb_config at91sam9g45es_config = {
+};
+
+static struct atmel_lcdfb_config at91sam9rl_config = {
+	.have_intensity_bit	= true,
+};
+
+static struct atmel_lcdfb_config at32ap_config = {
+	.have_hozval		= true,
+};
+
+static const struct platform_device_id atmel_lcdfb_devtypes[] = {
+	{
+		.name = "at91sam9261-lcdfb",
+		.driver_data = (unsigned long)&at91sam9261_config,
+	}, {
+		.name = "at91sam9263-lcdfb",
+		.driver_data = (unsigned long)&at91sam9263_config,
+	}, {
+		.name = "at91sam9g10-lcdfb",
+		.driver_data = (unsigned long)&at91sam9g10_config,
+	}, {
+		.name = "at91sam9g45-lcdfb",
+		.driver_data = (unsigned long)&at91sam9g45_config,
+	}, {
+		.name = "at91sam9g45es-lcdfb",
+		.driver_data = (unsigned long)&at91sam9g45es_config,
+	}, {
+		.name = "at91sam9rl-lcdfb",
+		.driver_data = (unsigned long)&at91sam9rl_config,
+	}, {
+		.name = "at32ap-lcdfb",
+		.driver_data = (unsigned long)&at32ap_config,
+	}, {
+		/* terminator */
+	}
+};
+MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes);
+
+static struct atmel_lcdfb_config *
+atmel_lcdfb_get_config(struct platform_device *pdev)
+{
+	unsigned long data;
+
+	data = platform_get_device_id(pdev)->driver_data;
+
+	return (struct atmel_lcdfb_config *)data;
+}
+
+#if defined(CONFIG_ARCH_AT91)
+#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
+					 | FBINFO_PARTIAL_PAN_OK \
+					 | FBINFO_HWACCEL_YPAN)
+
+static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+					struct fb_var_screeninfo *var,
+					struct fb_info *info)
+{
+
+}
+#elif defined(CONFIG_AVR32)
+#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
+					| FBINFO_PARTIAL_PAN_OK \
+					| FBINFO_HWACCEL_XPAN \
+					| FBINFO_HWACCEL_YPAN)
+
+static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+				     struct fb_var_screeninfo *var,
+				     struct fb_info *info)
+{
+	u32 dma2dcfg;
+	u32 pixeloff;
+
+	pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
+
+	dma2dcfg = (info->var.xres_virtual - info->var.xres)
+		 * info->var.bits_per_pixel / 8;
+	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
+	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
+
+	/* Update configuration */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
+		    lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
+		    | ATMEL_LCDC_DMAUPDT);
+}
+#endif
+
+static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
+		| ATMEL_LCDC_POL_POSITIVE
+		| ATMEL_LCDC_ENA_PWMENABLE;
+
+#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
+
+/* some bl->props field just changed */
+static int atmel_bl_update_status(struct backlight_device *bl)
+{
+	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
+	int			power = sinfo->bl_power;
+	int			brightness = bl->props.brightness;
+
+	/* REVISIT there may be a meaningful difference between
+	 * fb_blank and power ... there seem to be some cases
+	 * this doesn't handle correctly.
+	 */
+	if (bl->props.fb_blank != sinfo->bl_power)
+		power = bl->props.fb_blank;
+	else if (bl->props.power != sinfo->bl_power)
+		power = bl->props.power;
+
+	if (brightness < 0 && power == FB_BLANK_UNBLANK)
+		brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+	else if (power != FB_BLANK_UNBLANK)
+		brightness = 0;
+
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
+	if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
+		lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
+			brightness ? contrast_ctr : 0);
+	else
+		lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
+
+	bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
+
+	return 0;
+}
+
+static int atmel_bl_get_brightness(struct backlight_device *bl)
+{
+	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
+
+	return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+}
+
+static const struct backlight_ops atmel_lcdc_bl_ops = {
+	.update_status = atmel_bl_update_status,
+	.get_brightness = atmel_bl_get_brightness,
+};
+
+static void init_backlight(struct atmel_lcdfb_info *sinfo)
+{
+	struct backlight_properties props;
+	struct backlight_device	*bl;
+
+	sinfo->bl_power = FB_BLANK_UNBLANK;
+
+	if (sinfo->backlight)
+		return;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 0xff;
+	bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
+				       &atmel_lcdc_bl_ops, &props);
+	if (IS_ERR(bl)) {
+		dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
+				PTR_ERR(bl));
+		return;
+	}
+	sinfo->backlight = bl;
+
+	bl->props.power = FB_BLANK_UNBLANK;
+	bl->props.fb_blank = FB_BLANK_UNBLANK;
+	bl->props.brightness = atmel_bl_get_brightness(bl);
+}
+
+static void exit_backlight(struct atmel_lcdfb_info *sinfo)
+{
+	if (!sinfo->backlight)
+		return;
+
+	if (sinfo->backlight->ops) {
+		sinfo->backlight->props.power = FB_BLANK_POWERDOWN;
+		sinfo->backlight->ops->update_status(sinfo->backlight);
+	}
+	backlight_device_unregister(sinfo->backlight);
+}
+
+#else
+
+static void init_backlight(struct atmel_lcdfb_info *sinfo)
+{
+	dev_warn(&sinfo->pdev->dev, "backlight control is not available\n");
+}
+
+static void exit_backlight(struct atmel_lcdfb_info *sinfo)
+{
+}
+
+#endif
+
+static void init_contrast(struct atmel_lcdfb_info *sinfo)
+{
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+	/* contrast pwm can be 'inverted' */
+	if (pdata->lcdcon_pol_negative)
+			contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
+
+	/* have some default contrast/backlight settings */
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
+
+	if (pdata->lcdcon_is_backlight)
+		init_backlight(sinfo);
+}
+
+static inline void atmel_lcdfb_power_control(struct atmel_lcdfb_info *sinfo, int on)
+{
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+	if (pdata->atmel_lcdfb_power_control)
+		pdata->atmel_lcdfb_power_control(pdata, on);
+}
+
+static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 1,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
+							unsigned long xres)
+{
+	unsigned long lcdcon2;
+	unsigned long value;
+
+	if (!sinfo->config->have_hozval)
+		return xres;
+
+	lcdcon2 = lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2);
+	value = xres;
+	if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
+		/* STN display */
+		if ((lcdcon2 & ATMEL_LCDC_DISTYPE) == ATMEL_LCDC_DISTYPE_STNCOLOR) {
+			value *= 3;
+		}
+		if ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_4
+		   || ( (lcdcon2 & ATMEL_LCDC_IFWIDTH) == ATMEL_LCDC_IFWIDTH_8
+		      && (lcdcon2 & ATMEL_LCDC_SCANMOD) == ATMEL_LCDC_SCANMOD_DUAL ))
+			value = DIV_ROUND_UP(value, 4);
+		else
+			value = DIV_ROUND_UP(value, 8);
+	}
+
+	return value;
+}
+
+static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
+{
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+	/* Turn off the LCD controller and the DMA controller */
+	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+			pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+	/* Wait for the LCDC core to become idle */
+	while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
+		msleep(10);
+
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+}
+
+static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
+{
+	atmel_lcdfb_stop_nowait(sinfo);
+
+	/* Wait for DMA engine to become idle... */
+	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+		msleep(10);
+}
+
+static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
+{
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, pdata->default_dmacon);
+	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+		(pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
+		| ATMEL_LCDC_PWR);
+}
+
+static void atmel_lcdfb_update_dma(struct fb_info *info,
+			       struct fb_var_screeninfo *var)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	unsigned long dma_addr;
+
+	dma_addr = (fix->smem_start + var->yoffset * fix->line_length
+		    + var->xoffset * info->var.bits_per_pixel / 8);
+
+	dma_addr &= ~3UL;
+
+	/* Set framebuffer DMA base address and pixel offset */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
+
+	atmel_lcdfb_update_dma2d(sinfo, var, info);
+}
+
+static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+
+	dma_free_writecombine(info->device, info->fix.smem_len,
+				info->screen_base, info->fix.smem_start);
+}
+
+/**
+ *	atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
+ *	@sinfo: the frame buffer to allocate memory for
+ * 	
+ * 	This function is called only from the atmel_lcdfb_probe()
+ * 	so no locking by fb_info->mm_lock around smem_len setting is needed.
+ */
+static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned int smem_len;
+
+	smem_len = (var->xres_virtual * var->yres_virtual
+		    * ((var->bits_per_pixel + 7) / 8));
+	info->fix.smem_len = max(smem_len, sinfo->smem_len);
+
+	info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
+					(dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
+
+	if (!info->screen_base) {
+		return -ENOMEM;
+	}
+
+	memset(info->screen_base, 0, info->fix.smem_len);
+
+	return 0;
+}
+
+static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
+						     struct fb_info *info)
+{
+	struct fb_videomode varfbmode;
+	const struct fb_videomode *fbmode = NULL;
+
+	fb_var_to_videomode(&varfbmode, var);
+	fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
+	if (fbmode)
+		fb_videomode_to_var(var, fbmode);
+	return fbmode;
+}
+
+
+/**
+ *      atmel_lcdfb_check_var - Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Checks to see if the hardware supports the state requested by
+ *	var passed in. This function does not alter the hardware
+ *	state!!!  This means the data stored in struct fb_info and
+ *	struct atmel_lcdfb_info do not change. This includes the var
+ *	inside of struct fb_info.  Do NOT change these. This function
+ *	can be called on its own if we intent to only test a mode and
+ *	not actually set it. The stuff in modedb.c is a example of
+ *	this. If the var passed in is slightly off by what the
+ *	hardware can support then we alter the var PASSED in to what
+ *	we can do. If the hardware doesn't support mode change a
+ *	-EINVAL will be returned by the upper layers. You don't need
+ *	to implement this function then. If you hardware doesn't
+ *	support changing the resolution then this function is not
+ *	needed. In this case the driver would just provide a var that
+ *	represents the static state the screen is in.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct device *dev = info->device;
+	struct atmel_lcdfb_info *sinfo = info->par;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+	unsigned long clk_value_khz;
+
+	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+	dev_dbg(dev, "%s:\n", __func__);
+
+	if (!(var->pixclock && var->bits_per_pixel)) {
+		/* choose a suitable mode if possible */
+		if (!atmel_lcdfb_choose_mode(var, info)) {
+			dev_err(dev, "needed value not specified\n");
+			return -EINVAL;
+		}
+	}
+
+	dev_dbg(dev, "  resolution: %ux%u\n", var->xres, var->yres);
+	dev_dbg(dev, "  pixclk:     %lu KHz\n", PICOS2KHZ(var->pixclock));
+	dev_dbg(dev, "  bpp:        %u\n", var->bits_per_pixel);
+	dev_dbg(dev, "  clk:        %lu KHz\n", clk_value_khz);
+
+	if (PICOS2KHZ(var->pixclock) > clk_value_khz) {
+		dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+
+	/* Do not allow to have real resoulution larger than virtual */
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	/* Force same alignment for each line */
+	var->xres = (var->xres + 3) & ~3UL;
+	var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
+
+	var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+	var->transp.offset = var->transp.length = 0;
+	var->xoffset = var->yoffset = 0;
+
+	if (info->fix.smem_len) {
+		unsigned int smem_len = (var->xres_virtual * var->yres_virtual
+					 * ((var->bits_per_pixel + 7) / 8));
+		if (smem_len > info->fix.smem_len) {
+			dev_err(dev, "Frame buffer is too small (%u) for screen size (need at least %u)\n",
+				info->fix.smem_len, smem_len);
+			return -EINVAL;
+		}
+	}
+
+	/* Saturate vertical and horizontal timings at maximum values */
+	var->vsync_len = min_t(u32, var->vsync_len,
+			(ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
+	var->upper_margin = min_t(u32, var->upper_margin,
+			ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
+	var->lower_margin = min_t(u32, var->lower_margin,
+			ATMEL_LCDC_VFP);
+	var->right_margin = min_t(u32, var->right_margin,
+			(ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
+	var->hsync_len = min_t(u32, var->hsync_len,
+			(ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
+	var->left_margin = min_t(u32, var->left_margin,
+			ATMEL_LCDC_HBP + 1);
+
+	/* Some parameters can't be zero */
+	var->vsync_len = max_t(u32, var->vsync_len, 1);
+	var->right_margin = max_t(u32, var->right_margin, 1);
+	var->hsync_len = max_t(u32, var->hsync_len, 1);
+	var->left_margin = max_t(u32, var->left_margin, 1);
+
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length
+			= var->bits_per_pixel;
+		break;
+	case 16:
+		/* Older SOCs use IBGR:555 rather than BGR:565. */
+		if (sinfo->config->have_intensity_bit)
+			var->green.length = 5;
+		else
+			var->green.length = 6;
+
+		if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
+			/* RGB:5X5 mode */
+			var->red.offset = var->green.length + 5;
+			var->blue.offset = 0;
+		} else {
+			/* BGR:5X5 mode */
+			var->red.offset = 0;
+			var->blue.offset = var->green.length + 5;
+		}
+		var->green.offset = 5;
+		var->red.length = var->blue.length = 5;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		/* fall through */
+	case 24:
+		if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
+			/* RGB:888 mode */
+			var->red.offset = 16;
+			var->blue.offset = 0;
+		} else {
+			/* BGR:888 mode */
+			var->red.offset = 0;
+			var->blue.offset = 16;
+		}
+		var->green.offset = 8;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	default:
+		dev_err(dev, "color depth %d not supported\n",
+					var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * LCD reset sequence
+ */
+static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
+{
+	might_sleep();
+
+	atmel_lcdfb_stop(sinfo);
+	atmel_lcdfb_start(sinfo);
+}
+
+/**
+ *      atmel_lcdfb_set_par - Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Using the fb_var_screeninfo in fb_info we set the resolution
+ *	of the this particular framebuffer. This function alters the
+ *	par AND the fb_fix_screeninfo stored in fb_info. It doesn't
+ *	not alter var in fb_info since we are using that data. This
+ *	means we depend on the data in var inside fb_info to be
+ *	supported by the hardware.  atmel_lcdfb_check_var is always called
+ *	before atmel_lcdfb_set_par to ensure this.  Again if you can't
+ *	change the resolution you don't need this function.
+ *
+ */
+static int atmel_lcdfb_set_par(struct fb_info *info)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+	unsigned long hozval_linesz;
+	unsigned long value;
+	unsigned long clk_value_khz;
+	unsigned long bits_per_line;
+	unsigned long pix_factor = 2;
+
+	might_sleep();
+
+	dev_dbg(info->device, "%s:\n", __func__);
+	dev_dbg(info->device, "  * resolution: %ux%u (%ux%u virtual)\n",
+		 info->var.xres, info->var.yres,
+		 info->var.xres_virtual, info->var.yres_virtual);
+
+	atmel_lcdfb_stop_nowait(sinfo);
+
+	if (info->var.bits_per_pixel == 1)
+		info->fix.visual = FB_VISUAL_MONO01;
+	else if (info->var.bits_per_pixel <= 8)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	bits_per_line = info->var.xres_virtual * info->var.bits_per_pixel;
+	info->fix.line_length = DIV_ROUND_UP(bits_per_line, 8);
+
+	/* Re-initialize the DMA engine... */
+	dev_dbg(info->device, "  * update DMA engine\n");
+	atmel_lcdfb_update_dma(info, &info->var);
+
+	/* ...set frame size and burst length = 8 words (?) */
+	value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
+	value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
+	lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
+
+	/* Now, the LCDC core... */
+
+	/* Set pixel clock */
+	if (sinfo->config->have_alt_pixclock)
+		pix_factor = 1;
+
+	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+	value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
+
+	if (value < pix_factor) {
+		dev_notice(info->device, "Bypassing pixel clock divider\n");
+		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
+	} else {
+		value = (value / pix_factor) - 1;
+		dev_dbg(info->device, "  * programming CLKVAL = 0x%08lx\n",
+				value);
+		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
+				value << ATMEL_LCDC_CLKVAL_OFFSET);
+		info->var.pixclock =
+			KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
+		dev_dbg(info->device, "  updated pixclk:     %lu KHz\n",
+					PICOS2KHZ(info->var.pixclock));
+	}
+
+
+	/* Initialize control register 2 */
+	value = pdata->default_lcdcon2;
+
+	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+		value |= ATMEL_LCDC_INVLINE_INVERTED;
+	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+		value |= ATMEL_LCDC_INVFRAME_INVERTED;
+
+	switch (info->var.bits_per_pixel) {
+		case 1:	value |= ATMEL_LCDC_PIXELSIZE_1; break;
+		case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
+		case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
+		case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
+		case 15: /* fall through */
+		case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
+		case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
+		case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
+		default: BUG(); break;
+	}
+	dev_dbg(info->device, "  * LCDCON2 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
+
+	/* Vertical timing */
+	value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
+	value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
+	value |= info->var.lower_margin;
+	dev_dbg(info->device, "  * LCDTIM1 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
+
+	/* Horizontal timing */
+	value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
+	value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
+	value |= (info->var.left_margin - 1);
+	dev_dbg(info->device, "  * LCDTIM2 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
+
+	/* Horizontal value (aka line size) */
+	hozval_linesz = compute_hozval(sinfo, info->var.xres);
+
+	/* Display size */
+	value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
+	value |= info->var.yres - 1;
+	dev_dbg(info->device, "  * LCDFRMCFG = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
+
+	/* FIFO Threshold: Use formula from data sheet */
+	value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
+	lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
+
+	/* Toggle LCD_MODE every frame */
+	lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
+
+	/* Disable all interrupts */
+	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+	/* Enable FIFO & DMA errors */
+	lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
+
+	/* ...wait for DMA engine to become idle... */
+	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+		msleep(10);
+
+	atmel_lcdfb_start(sinfo);
+
+	dev_dbg(info->device, "  * DONE\n");
+
+	return 0;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/**
+ *  	atmel_lcdfb_setcolreg - Optional function. Sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *  	Set a single color register. The values supplied have a 16 bit
+ *  	magnitude which needs to be scaled in this function for the hardware.
+ *	Things to take into consideration are how many color registers, if
+ *	any, are supported with the current color visual. With truecolor mode
+ *	no color palettes are supported. Here a pseudo palette is created
+ *	which we store the value in pseudo_palette in struct fb_info. For
+ *	pseudocolor mode we have a limited color palette. To deal with this
+ *	we can program what color is displayed for a particular pixel value.
+ *	DirectColor is similar in that we can program each color field. If
+ *	we have a static colormap we don't need to implement this function.
+ *
+ *	Returns negative errno on error, or zero on success. In an
+ *	ideal world, this would have been the case, but as it turns
+ *	out, the other drivers return 1 on failure, so that's what
+ *	we're going to do.
+ */
+static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
+			     unsigned int green, unsigned int blue,
+			     unsigned int transp, struct fb_info *info)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+	unsigned int val;
+	u32 *pal;
+	int ret = 1;
+
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green
+				      + 7471 * blue) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			if (sinfo->config->have_intensity_bit) {
+				/* old style I+BGR:555 */
+				val  = ((red   >> 11) & 0x001f);
+				val |= ((green >>  6) & 0x03e0);
+				val |= ((blue  >>  1) & 0x7c00);
+
+				/*
+				 * TODO: intensity bit. Maybe something like
+				 *   ~(red[10] ^ green[10] ^ blue[10]) & 1
+				 */
+			} else {
+				/* new style BGR:565 / RGB:565 */
+				if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
+					val  = ((blue >> 11) & 0x001f);
+					val |= ((red  >>  0) & 0xf800);
+				} else {
+					val  = ((red  >> 11) & 0x001f);
+					val |= ((blue >>  0) & 0xf800);
+				}
+
+				val |= ((green >>  5) & 0x07e0);
+			}
+
+			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_MONO01:
+		if (regno < 2) {
+			val = (regno == 0) ? 0x00 : 0x1F;
+			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
+			ret = 0;
+		}
+		break;
+
+	}
+
+	return ret;
+}
+
+static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	dev_dbg(info->device, "%s\n", __func__);
+
+	atmel_lcdfb_update_dma(info, var);
+
+	return 0;
+}
+
+static int atmel_lcdfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		atmel_lcdfb_start(sinfo);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+		break;
+	case FB_BLANK_POWERDOWN:
+		atmel_lcdfb_stop(sinfo);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* let fbcon do a soft blank for us */
+	return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
+}
+
+static struct fb_ops atmel_lcdfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= atmel_lcdfb_check_var,
+	.fb_set_par	= atmel_lcdfb_set_par,
+	.fb_setcolreg	= atmel_lcdfb_setcolreg,
+	.fb_blank	= atmel_lcdfb_blank,
+	.fb_pan_display	= atmel_lcdfb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
+{
+	struct fb_info *info = dev_id;
+	struct atmel_lcdfb_info *sinfo = info->par;
+	u32 status;
+
+	status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
+	if (status & ATMEL_LCDC_UFLWI) {
+		dev_warn(info->device, "FIFO underflow %#x\n", status);
+		/* reset DMA and FIFO to avoid screen shifting */
+		schedule_work(&sinfo->task);
+	}
+	lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
+	return IRQ_HANDLED;
+}
+
+/*
+ * LCD controller task (to reset the LCD)
+ */
+static void atmel_lcdfb_task(struct work_struct *work)
+{
+	struct atmel_lcdfb_info *sinfo =
+		container_of(work, struct atmel_lcdfb_info, task);
+
+	atmel_lcdfb_reset(sinfo);
+}
+
+static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+	int ret = 0;
+
+	info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
+
+	dev_info(info->device,
+	       "%luKiB frame buffer at %08lx (mapped at %p)\n",
+	       (unsigned long)info->fix.smem_len / 1024,
+	       (unsigned long)info->fix.smem_start,
+	       info->screen_base);
+
+	/* Allocate colormap */
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret < 0)
+		dev_err(info->device, "Alloc color map failed\n");
+
+	return ret;
+}
+
+static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
+{
+	clk_prepare_enable(sinfo->bus_clk);
+	clk_prepare_enable(sinfo->lcdc_clk);
+}
+
+static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
+{
+	clk_disable_unprepare(sinfo->bus_clk);
+	clk_disable_unprepare(sinfo->lcdc_clk);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_lcdfb_dt_ids[] = {
+	{ .compatible = "atmel,at91sam9261-lcdc" , .data = &at91sam9261_config, },
+	{ .compatible = "atmel,at91sam9263-lcdc" , .data = &at91sam9263_config, },
+	{ .compatible = "atmel,at91sam9g10-lcdc" , .data = &at91sam9g10_config, },
+	{ .compatible = "atmel,at91sam9g45-lcdc" , .data = &at91sam9g45_config, },
+	{ .compatible = "atmel,at91sam9g45es-lcdc" , .data = &at91sam9g45es_config, },
+	{ .compatible = "atmel,at91sam9rl-lcdc" , .data = &at91sam9rl_config, },
+	{ .compatible = "atmel,at32ap-lcdc" , .data = &at32ap_config, },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_lcdfb_dt_ids);
+
+static const char *atmel_lcdfb_wiring_modes[] = {
+	[ATMEL_LCDC_WIRING_BGR]	= "BRG",
+	[ATMEL_LCDC_WIRING_RGB]	= "RGB",
+};
+
+const int atmel_lcdfb_get_of_wiring_modes(struct device_node *np)
+{
+	const char *mode;
+	int err, i;
+
+	err = of_property_read_string(np, "atmel,lcd-wiring-mode", &mode);
+	if (err < 0)
+		return ATMEL_LCDC_WIRING_BGR;
+
+	for (i = 0; i < ARRAY_SIZE(atmel_lcdfb_wiring_modes); i++)
+		if (!strcasecmp(mode, atmel_lcdfb_wiring_modes[i]))
+			return i;
+
+	return -ENODEV;
+}
+
+static void atmel_lcdfb_power_control_gpio(struct atmel_lcdfb_pdata *pdata, int on)
+{
+	struct atmel_lcdfb_power_ctrl_gpio *og;
+
+	list_for_each_entry(og, &pdata->pwr_gpios, list)
+		gpio_set_value(og->gpio, on);
+}
+
+static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+	struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+	struct fb_var_screeninfo *var = &info->var;
+	struct device *dev = &sinfo->pdev->dev;
+	struct device_node *np =dev->of_node;
+	struct device_node *display_np;
+	struct device_node *timings_np;
+	struct display_timings *timings;
+	enum of_gpio_flags flags;
+	struct atmel_lcdfb_power_ctrl_gpio *og;
+	bool is_gpio_power = false;
+	int ret = -ENOENT;
+	int i, gpio;
+
+	sinfo->config = (struct atmel_lcdfb_config*)
+		of_match_device(atmel_lcdfb_dt_ids, dev)->data;
+
+	display_np = of_parse_phandle(np, "display", 0);
+	if (!display_np) {
+		dev_err(dev, "failed to find display phandle\n");
+		return -ENOENT;
+	}
+
+	ret = of_property_read_u32(display_np, "bits-per-pixel", &var->bits_per_pixel);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bits-per-pixel\n");
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "atmel,guard-time", &pdata->guard_time);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property atmel,guard-time\n");
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "atmel,lcdcon2", &pdata->default_lcdcon2);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property atmel,lcdcon2\n");
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "atmel,dmacon", &pdata->default_dmacon);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bits-per-pixel\n");
+		goto put_display_node;
+	}
+
+	ret = -ENOMEM;
+	for (i = 0; i < of_gpio_named_count(display_np, "atmel,power-control-gpio"); i++) {
+		gpio = of_get_named_gpio_flags(display_np, "atmel,power-control-gpio",
+					       i, &flags);
+		if (gpio < 0)
+			continue;
+
+		og = devm_kzalloc(dev, sizeof(*og), GFP_KERNEL);
+		if (!og)
+			goto put_display_node;
+
+		og->gpio = gpio;
+		og->active_low = flags & OF_GPIO_ACTIVE_LOW;
+		is_gpio_power = true;
+		ret = devm_gpio_request(dev, gpio, "lcd-power-control-gpio");
+		if (ret) {
+			dev_err(dev, "request gpio %d failed\n", gpio);
+			goto put_display_node;
+		}
+
+		ret = gpio_direction_output(gpio, og->active_low);
+		if (ret) {
+			dev_err(dev, "set direction output gpio %d failed\n", gpio);
+			goto put_display_node;
+		}
+	}
+
+	if (is_gpio_power)
+		pdata->atmel_lcdfb_power_control = atmel_lcdfb_power_control_gpio;
+
+	ret = atmel_lcdfb_get_of_wiring_modes(display_np);
+	if (ret < 0) {
+		dev_err(dev, "invalid atmel,lcd-wiring-mode\n");
+		goto put_display_node;
+	}
+	pdata->lcd_wiring_mode = ret;
+
+	pdata->lcdcon_is_backlight = of_property_read_bool(display_np, "atmel,lcdcon-backlight");
+
+	timings = of_get_display_timings(display_np);
+	if (!timings) {
+		dev_err(dev, "failed to get display timings\n");
+		goto put_display_node;
+	}
+
+	timings_np = of_find_node_by_name(display_np, "display-timings");
+	if (!timings_np) {
+		dev_err(dev, "failed to find display-timings node\n");
+		goto put_display_node;
+	}
+
+	for (i = 0; i < of_get_child_count(timings_np); i++) {
+		struct videomode vm;
+		struct fb_videomode fb_vm;
+
+		ret = videomode_from_timings(timings, &vm, i);
+		if (ret < 0)
+			goto put_timings_node;
+		ret = fb_videomode_from_videomode(&vm, &fb_vm);
+		if (ret < 0)
+			goto put_timings_node;
+
+		fb_add_videomode(&fb_vm, &info->modelist);
+	}
+
+	return 0;
+
+put_timings_node:
+	of_node_put(timings_np);
+put_display_node:
+	of_node_put(display_np);
+	return ret;
+}
+#else
+static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
+{
+	return 0;
+}
+#endif
+
+static int __init atmel_lcdfb_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fb_info *info;
+	struct atmel_lcdfb_info *sinfo;
+	struct atmel_lcdfb_pdata *pdata = NULL;
+	struct resource *regs = NULL;
+	struct resource *map = NULL;
+	struct fb_modelist *modelist;
+	int ret;
+
+	dev_dbg(dev, "%s BEGIN\n", __func__);
+
+	ret = -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
+	if (!info) {
+		dev_err(dev, "cannot allocate memory\n");
+		goto out;
+	}
+
+	sinfo = info->par;
+	sinfo->pdev = pdev;
+	sinfo->info = info;
+
+	INIT_LIST_HEAD(&info->modelist);
+
+	if (pdev->dev.of_node) {
+		ret = atmel_lcdfb_of_init(sinfo);
+		if (ret)
+			goto free_info;
+	} else if (dev_get_platdata(dev)) {
+		struct fb_monspecs *monspecs;
+		int i;
+
+		pdata = dev_get_platdata(dev);
+		monspecs = pdata->default_monspecs;
+		sinfo->pdata = *pdata;
+
+		for (i = 0; i < monspecs->modedb_len; i++)
+			fb_add_videomode(&monspecs->modedb[i], &info->modelist);
+
+		sinfo->config = atmel_lcdfb_get_config(pdev);
+
+		info->var.bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
+		memcpy(&info->monspecs, pdata->default_monspecs, sizeof(info->monspecs));
+	} else {
+		dev_err(dev, "cannot get default configuration\n");
+		goto free_info;
+	}
+
+	if (!sinfo->config)
+		goto free_info;
+
+	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
+	info->pseudo_palette = sinfo->pseudo_palette;
+	info->fbops = &atmel_lcdfb_ops;
+
+	info->fix = atmel_lcdfb_fix;
+	strcpy(info->fix.id, sinfo->pdev->name);
+
+	/* Enable LCDC Clocks */
+	sinfo->bus_clk = clk_get(dev, "hclk");
+	if (IS_ERR(sinfo->bus_clk)) {
+		ret = PTR_ERR(sinfo->bus_clk);
+		goto free_info;
+	}
+	sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
+	if (IS_ERR(sinfo->lcdc_clk)) {
+		ret = PTR_ERR(sinfo->lcdc_clk);
+		goto put_bus_clk;
+	}
+	atmel_lcdfb_start_clock(sinfo);
+
+	modelist = list_first_entry(&info->modelist,
+			struct fb_modelist, list);
+	fb_videomode_to_var(&info->var, &modelist->mode);
+
+	atmel_lcdfb_check_var(&info->var, info);
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_err(dev, "resources unusable\n");
+		ret = -ENXIO;
+		goto stop_clk;
+	}
+
+	sinfo->irq_base = platform_get_irq(pdev, 0);
+	if (sinfo->irq_base < 0) {
+		dev_err(dev, "unable to get irq\n");
+		ret = sinfo->irq_base;
+		goto stop_clk;
+	}
+
+	/* Initialize video memory */
+	map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (map) {
+		/* use a pre-allocated memory buffer */
+		info->fix.smem_start = map->start;
+		info->fix.smem_len = resource_size(map);
+		if (!request_mem_region(info->fix.smem_start,
+					info->fix.smem_len, pdev->name)) {
+			ret = -EBUSY;
+			goto stop_clk;
+		}
+
+		info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+		if (!info->screen_base) {
+			ret = -ENOMEM;
+			goto release_intmem;
+		}
+
+		/*
+		 * Don't clear the framebuffer -- someone may have set
+		 * up a splash image.
+		 */
+	} else {
+		/* allocate memory buffer */
+		ret = atmel_lcdfb_alloc_video_memory(sinfo);
+		if (ret < 0) {
+			dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
+			goto stop_clk;
+		}
+	}
+
+	/* LCDC registers */
+	info->fix.mmio_start = regs->start;
+	info->fix.mmio_len = resource_size(regs);
+
+	if (!request_mem_region(info->fix.mmio_start,
+				info->fix.mmio_len, pdev->name)) {
+		ret = -EBUSY;
+		goto free_fb;
+	}
+
+	sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
+	if (!sinfo->mmio) {
+		dev_err(dev, "cannot map LCDC registers\n");
+		ret = -ENOMEM;
+		goto release_mem;
+	}
+
+	/* Initialize PWM for contrast or backlight ("off") */
+	init_contrast(sinfo);
+
+	/* interrupt */
+	ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
+	if (ret) {
+		dev_err(dev, "request_irq failed: %d\n", ret);
+		goto unmap_mmio;
+	}
+
+	/* Some operations on the LCDC might sleep and
+	 * require a preemptible task context */
+	INIT_WORK(&sinfo->task, atmel_lcdfb_task);
+
+	ret = atmel_lcdfb_init_fbinfo(sinfo);
+	if (ret < 0) {
+		dev_err(dev, "init fbinfo failed: %d\n", ret);
+		goto unregister_irqs;
+	}
+
+	ret = atmel_lcdfb_set_par(info);
+	if (ret < 0) {
+		dev_err(dev, "set par failed: %d\n", ret);
+		goto unregister_irqs;
+	}
+
+	dev_set_drvdata(dev, info);
+
+	/*
+	 * Tell the world that we're ready to go
+	 */
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(dev, "failed to register framebuffer device: %d\n", ret);
+		goto reset_drvdata;
+	}
+
+	/* Power up the LCDC screen */
+	atmel_lcdfb_power_control(sinfo, 1);
+
+	dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
+		       info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
+
+	return 0;
+
+reset_drvdata:
+	dev_set_drvdata(dev, NULL);
+	fb_dealloc_cmap(&info->cmap);
+unregister_irqs:
+	cancel_work_sync(&sinfo->task);
+	free_irq(sinfo->irq_base, info);
+unmap_mmio:
+	exit_backlight(sinfo);
+	iounmap(sinfo->mmio);
+release_mem:
+ 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+free_fb:
+	if (map)
+		iounmap(info->screen_base);
+	else
+		atmel_lcdfb_free_video_memory(sinfo);
+
+release_intmem:
+	if (map)
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+stop_clk:
+	atmel_lcdfb_stop_clock(sinfo);
+	clk_put(sinfo->lcdc_clk);
+put_bus_clk:
+	clk_put(sinfo->bus_clk);
+free_info:
+	framebuffer_release(info);
+out:
+	dev_dbg(dev, "%s FAILED\n", __func__);
+	return ret;
+}
+
+static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct atmel_lcdfb_info *sinfo;
+	struct atmel_lcdfb_pdata *pdata;
+
+	if (!info || !info->par)
+		return 0;
+	sinfo = info->par;
+	pdata = &sinfo->pdata;
+
+	cancel_work_sync(&sinfo->task);
+	exit_backlight(sinfo);
+	atmel_lcdfb_power_control(sinfo, 0);
+	unregister_framebuffer(info);
+	atmel_lcdfb_stop_clock(sinfo);
+	clk_put(sinfo->lcdc_clk);
+	clk_put(sinfo->bus_clk);
+	fb_dealloc_cmap(&info->cmap);
+	free_irq(sinfo->irq_base, info);
+	iounmap(sinfo->mmio);
+ 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+	if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
+		iounmap(info->screen_base);
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+	} else {
+		atmel_lcdfb_free_video_memory(sinfo);
+	}
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct atmel_lcdfb_info *sinfo = info->par;
+
+	/*
+	 * We don't want to handle interrupts while the clock is
+	 * stopped. It may take forever.
+	 */
+	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+
+	sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
+	atmel_lcdfb_power_control(sinfo, 0);
+	atmel_lcdfb_stop(sinfo);
+	atmel_lcdfb_stop_clock(sinfo);
+
+	return 0;
+}
+
+static int atmel_lcdfb_resume(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct atmel_lcdfb_info *sinfo = info->par;
+
+	atmel_lcdfb_start_clock(sinfo);
+	atmel_lcdfb_start(sinfo);
+	atmel_lcdfb_power_control(sinfo, 1);
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
+
+	/* Enable FIFO & DMA errors */
+	lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
+			| ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
+
+	return 0;
+}
+
+#else
+#define atmel_lcdfb_suspend	NULL
+#define atmel_lcdfb_resume	NULL
+#endif
+
+static struct platform_driver atmel_lcdfb_driver = {
+	.remove		= __exit_p(atmel_lcdfb_remove),
+	.suspend	= atmel_lcdfb_suspend,
+	.resume		= atmel_lcdfb_resume,
+	.id_table	= atmel_lcdfb_devtypes,
+	.driver		= {
+		.name	= "atmel_lcdfb",
+		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(atmel_lcdfb_dt_ids),
+	},
+};
+
+module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe);
+
+MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/aty/Makefile b/drivers/video/fbdev/aty/Makefile
new file mode 100644
index 000000000000..a6cc0e9ec790
--- /dev/null
+++ b/drivers/video/fbdev/aty/Makefile
@@ -0,0 +1,15 @@
+obj-$(CONFIG_FB_ATY) += atyfb.o
+obj-$(CONFIG_FB_ATY128) += aty128fb.o
+obj-$(CONFIG_FB_RADEON) += radeonfb.o
+
+atyfb-y				:= atyfb_base.o mach64_accel.o mach64_cursor.o
+atyfb-$(CONFIG_FB_ATY_GX)	+= mach64_gx.o
+atyfb-$(CONFIG_FB_ATY_CT)	+= mach64_ct.o
+
+atyfb-objs			:= $(atyfb-y)
+
+radeonfb-y			:= radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o
+radeonfb-$(CONFIG_FB_RADEON_I2C)	+= radeon_i2c.o
+radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT)	+= radeon_backlight.o
+radeonfb-objs			:= $(radeonfb-y)
+
diff --git a/drivers/video/fbdev/aty/ati_ids.h b/drivers/video/fbdev/aty/ati_ids.h
new file mode 100644
index 000000000000..3e9d28bcd9f8
--- /dev/null
+++ b/drivers/video/fbdev/aty/ati_ids.h
@@ -0,0 +1,214 @@
+/*
+ * ATI PCI IDs from XFree86, kept here to make sync'ing with
+ * XFree much simpler. Currently, this list is only used by
+ * radeonfb
+ */
+
+#define PCI_CHIP_RV380_3150             0x3150
+#define PCI_CHIP_RV380_3151             0x3151
+#define PCI_CHIP_RV380_3152             0x3152
+#define PCI_CHIP_RV380_3153             0x3153
+#define PCI_CHIP_RV380_3154             0x3154
+#define PCI_CHIP_RV380_3156             0x3156
+#define PCI_CHIP_RV380_3E50             0x3E50
+#define PCI_CHIP_RV380_3E51             0x3E51
+#define PCI_CHIP_RV380_3E52             0x3E52
+#define PCI_CHIP_RV380_3E53             0x3E53
+#define PCI_CHIP_RV380_3E54             0x3E54
+#define PCI_CHIP_RV380_3E56             0x3E56
+#define PCI_CHIP_RS100_4136		0x4136
+#define PCI_CHIP_RS200_4137		0x4137
+#define PCI_CHIP_R300_AD		0x4144
+#define PCI_CHIP_R300_AE		0x4145
+#define PCI_CHIP_R300_AF		0x4146
+#define PCI_CHIP_R300_AG		0x4147
+#define PCI_CHIP_R350_AH                0x4148
+#define PCI_CHIP_R350_AI                0x4149
+#define PCI_CHIP_R350_AJ                0x414A
+#define PCI_CHIP_R350_AK                0x414B
+#define PCI_CHIP_RV350_AP               0x4150
+#define PCI_CHIP_RV350_AQ               0x4151
+#define PCI_CHIP_RV360_AR               0x4152
+#define PCI_CHIP_RV350_AS               0x4153
+#define PCI_CHIP_RV350_AT               0x4154
+#define PCI_CHIP_RV350_AV               0x4156
+#define PCI_CHIP_MACH32			0x4158
+#define PCI_CHIP_RS250_4237		0x4237
+#define PCI_CHIP_R200_BB		0x4242
+#define PCI_CHIP_R200_BC		0x4243
+#define PCI_CHIP_RS100_4336		0x4336
+#define PCI_CHIP_RS200_4337		0x4337
+#define PCI_CHIP_MACH64CT		0x4354
+#define PCI_CHIP_MACH64CX		0x4358
+#define PCI_CHIP_RS250_4437		0x4437
+#define PCI_CHIP_MACH64ET		0x4554
+#define PCI_CHIP_MACH64GB		0x4742
+#define PCI_CHIP_MACH64GD		0x4744
+#define PCI_CHIP_MACH64GI		0x4749
+#define PCI_CHIP_MACH64GL		0x474C
+#define PCI_CHIP_MACH64GM		0x474D
+#define PCI_CHIP_MACH64GN		0x474E
+#define PCI_CHIP_MACH64GO		0x474F
+#define PCI_CHIP_MACH64GP		0x4750
+#define PCI_CHIP_MACH64GQ		0x4751
+#define PCI_CHIP_MACH64GR		0x4752
+#define PCI_CHIP_MACH64GS		0x4753
+#define PCI_CHIP_MACH64GT		0x4754
+#define PCI_CHIP_MACH64GU		0x4755
+#define PCI_CHIP_MACH64GV		0x4756
+#define PCI_CHIP_MACH64GW		0x4757
+#define PCI_CHIP_MACH64GX		0x4758
+#define PCI_CHIP_MACH64GY		0x4759
+#define PCI_CHIP_MACH64GZ		0x475A
+#define PCI_CHIP_RV250_Id		0x4964
+#define PCI_CHIP_RV250_Ie		0x4965
+#define PCI_CHIP_RV250_If		0x4966
+#define PCI_CHIP_RV250_Ig		0x4967
+#define PCI_CHIP_R420_JH                0x4A48
+#define PCI_CHIP_R420_JI                0x4A49
+#define PCI_CHIP_R420_JJ                0x4A4A
+#define PCI_CHIP_R420_JK                0x4A4B
+#define PCI_CHIP_R420_JL                0x4A4C
+#define PCI_CHIP_R420_JM                0x4A4D
+#define PCI_CHIP_R420_JN                0x4A4E
+#define PCI_CHIP_R420_JP                0x4A50
+#define PCI_CHIP_MACH64LB		0x4C42
+#define PCI_CHIP_MACH64LD		0x4C44
+#define PCI_CHIP_RAGE128LE		0x4C45
+#define PCI_CHIP_RAGE128LF		0x4C46
+#define PCI_CHIP_MACH64LG		0x4C47
+#define PCI_CHIP_MACH64LI		0x4C49
+#define PCI_CHIP_MACH64LM		0x4C4D
+#define PCI_CHIP_MACH64LN		0x4C4E
+#define PCI_CHIP_MACH64LP		0x4C50
+#define PCI_CHIP_MACH64LQ		0x4C51
+#define PCI_CHIP_MACH64LR		0x4C52
+#define PCI_CHIP_MACH64LS		0x4C53
+#define PCI_CHIP_MACH64LT		0x4C54
+#define PCI_CHIP_RADEON_LW		0x4C57
+#define PCI_CHIP_RADEON_LX		0x4C58
+#define PCI_CHIP_RADEON_LY		0x4C59
+#define PCI_CHIP_RADEON_LZ		0x4C5A
+#define PCI_CHIP_RV250_Ld		0x4C64
+#define PCI_CHIP_RV250_Le		0x4C65
+#define PCI_CHIP_RV250_Lf		0x4C66
+#define PCI_CHIP_RV250_Lg		0x4C67
+#define PCI_CHIP_RV250_Ln		0x4C6E
+#define PCI_CHIP_RAGE128MF		0x4D46
+#define PCI_CHIP_RAGE128ML		0x4D4C
+#define PCI_CHIP_R300_ND		0x4E44
+#define PCI_CHIP_R300_NE		0x4E45
+#define PCI_CHIP_R300_NF		0x4E46
+#define PCI_CHIP_R300_NG		0x4E47
+#define PCI_CHIP_R350_NH                0x4E48  
+#define PCI_CHIP_R350_NI                0x4E49  
+#define PCI_CHIP_R360_NJ                0x4E4A  
+#define PCI_CHIP_R350_NK                0x4E4B  
+#define PCI_CHIP_RV350_NP               0x4E50
+#define PCI_CHIP_RV350_NQ               0x4E51
+#define PCI_CHIP_RV350_NR               0x4E52
+#define PCI_CHIP_RV350_NS               0x4E53
+#define PCI_CHIP_RV350_NT               0x4E54
+#define PCI_CHIP_RV350_NV               0x4E56
+#define PCI_CHIP_RAGE128PA		0x5041
+#define PCI_CHIP_RAGE128PB		0x5042
+#define PCI_CHIP_RAGE128PC		0x5043
+#define PCI_CHIP_RAGE128PD		0x5044
+#define PCI_CHIP_RAGE128PE		0x5045
+#define PCI_CHIP_RAGE128PF		0x5046
+#define PCI_CHIP_RAGE128PG		0x5047
+#define PCI_CHIP_RAGE128PH		0x5048
+#define PCI_CHIP_RAGE128PI		0x5049
+#define PCI_CHIP_RAGE128PJ		0x504A
+#define PCI_CHIP_RAGE128PK		0x504B
+#define PCI_CHIP_RAGE128PL		0x504C
+#define PCI_CHIP_RAGE128PM		0x504D
+#define PCI_CHIP_RAGE128PN		0x504E
+#define PCI_CHIP_RAGE128PO		0x504F
+#define PCI_CHIP_RAGE128PP		0x5050
+#define PCI_CHIP_RAGE128PQ		0x5051
+#define PCI_CHIP_RAGE128PR		0x5052
+#define PCI_CHIP_RAGE128PS		0x5053
+#define PCI_CHIP_RAGE128PT		0x5054
+#define PCI_CHIP_RAGE128PU		0x5055
+#define PCI_CHIP_RAGE128PV		0x5056
+#define PCI_CHIP_RAGE128PW		0x5057
+#define PCI_CHIP_RAGE128PX		0x5058
+#define PCI_CHIP_RADEON_QD		0x5144
+#define PCI_CHIP_RADEON_QE		0x5145
+#define PCI_CHIP_RADEON_QF		0x5146
+#define PCI_CHIP_RADEON_QG		0x5147
+#define PCI_CHIP_R200_QH		0x5148
+#define PCI_CHIP_R200_QI		0x5149
+#define PCI_CHIP_R200_QJ		0x514A
+#define PCI_CHIP_R200_QK		0x514B
+#define PCI_CHIP_R200_QL		0x514C
+#define PCI_CHIP_R200_QM		0x514D
+#define PCI_CHIP_R200_QN		0x514E
+#define PCI_CHIP_R200_QO		0x514F
+#define PCI_CHIP_RV200_QW		0x5157
+#define PCI_CHIP_RV200_QX		0x5158
+#define PCI_CHIP_RV100_QY		0x5159
+#define PCI_CHIP_RV100_QZ		0x515A
+#define PCI_CHIP_RN50			0x515E
+#define PCI_CHIP_RAGE128RE		0x5245
+#define PCI_CHIP_RAGE128RF		0x5246
+#define PCI_CHIP_RAGE128RG		0x5247
+#define PCI_CHIP_RAGE128RK		0x524B
+#define PCI_CHIP_RAGE128RL		0x524C
+#define PCI_CHIP_RAGE128SE		0x5345
+#define PCI_CHIP_RAGE128SF		0x5346
+#define PCI_CHIP_RAGE128SG		0x5347
+#define PCI_CHIP_RAGE128SH		0x5348
+#define PCI_CHIP_RAGE128SK		0x534B
+#define PCI_CHIP_RAGE128SL		0x534C
+#define PCI_CHIP_RAGE128SM		0x534D
+#define PCI_CHIP_RAGE128SN		0x534E
+#define PCI_CHIP_RAGE128TF		0x5446
+#define PCI_CHIP_RAGE128TL		0x544C
+#define PCI_CHIP_RAGE128TR		0x5452
+#define PCI_CHIP_RAGE128TS		0x5453
+#define PCI_CHIP_RAGE128TT		0x5454
+#define PCI_CHIP_RAGE128TU		0x5455
+#define PCI_CHIP_RV370_5460             0x5460
+#define PCI_CHIP_RV370_5461             0x5461
+#define PCI_CHIP_RV370_5462             0x5462
+#define PCI_CHIP_RV370_5463             0x5463
+#define PCI_CHIP_RV370_5464             0x5464
+#define PCI_CHIP_RV370_5465             0x5465
+#define PCI_CHIP_RV370_5466             0x5466
+#define PCI_CHIP_RV370_5467             0x5467
+#define PCI_CHIP_R423_UH                0x5548
+#define PCI_CHIP_R423_UI                0x5549
+#define PCI_CHIP_R423_UJ                0x554A
+#define PCI_CHIP_R423_UK                0x554B
+#define PCI_CHIP_R423_UQ                0x5551
+#define PCI_CHIP_R423_UR                0x5552
+#define PCI_CHIP_R423_UT                0x5554
+#define PCI_CHIP_MACH64VT		0x5654
+#define PCI_CHIP_MACH64VU		0x5655
+#define PCI_CHIP_MACH64VV		0x5656
+#define PCI_CHIP_RC410_5A62             0x5A62
+#define PCI_CHIP_RS300_5834		0x5834
+#define PCI_CHIP_RS300_5835		0x5835
+#define PCI_CHIP_RS300_5836		0x5836
+#define PCI_CHIP_RS300_5837		0x5837
+#define PCI_CHIP_RS480_5955             0x5955
+#define PCI_CHIP_RV280_5960		0x5960
+#define PCI_CHIP_RV280_5961		0x5961
+#define PCI_CHIP_RV280_5962		0x5962
+#define PCI_CHIP_RV280_5964		0x5964
+#define PCI_CHIP_RS482_5975		0x5975
+#define PCI_CHIP_RV370_5B60             0x5B60
+#define PCI_CHIP_RV370_5B61             0x5B61
+#define PCI_CHIP_RV370_5B62             0x5B62
+#define PCI_CHIP_RV370_5B63             0x5B63
+#define PCI_CHIP_RV370_5B64             0x5B64
+#define PCI_CHIP_RV370_5B65             0x5B65
+#define PCI_CHIP_RV370_5B66             0x5B66
+#define PCI_CHIP_RV370_5B67             0x5B67
+#define PCI_CHIP_RV280_5C61		0x5C61
+#define PCI_CHIP_RV280_5C63		0x5C63
+#define PCI_CHIP_R423_5D57              0x5D57
+#define PCI_CHIP_RS350_7834             0x7834
+#define PCI_CHIP_RS350_7835             0x7835
diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c
new file mode 100644
index 000000000000..52108be69e77
--- /dev/null
+++ b/drivers/video/fbdev/aty/aty128fb.c
@@ -0,0 +1,2591 @@
+/* $Id: aty128fb.c,v 1.1.1.1.36.1 1999/12/11 09:03:05 Exp $
+ *  linux/drivers/video/aty128fb.c -- Frame buffer device for ATI Rage128
+ *
+ *  Copyright (C) 1999-2003, Brad Douglas <brad@neruo.com>
+ *  Copyright (C) 1999, Anthony Tong <atong@uiuc.edu>
+ *
+ *                Ani Joshi / Jeff Garzik
+ *                      - Code cleanup
+ *
+ *                Michel Danzer <michdaen@iiic.ethz.ch>
+ *                      - 15/16 bit cleanup
+ *                      - fix panning
+ *
+ *                Benjamin Herrenschmidt
+ *                      - pmac-specific PM stuff
+ *			- various fixes & cleanups
+ *
+ *                Andreas Hundt <andi@convergence.de>
+ *                      - FB_ACTIVATE fixes
+ *
+ *		  Paul Mackerras <paulus@samba.org>
+ *			- Convert to new framebuffer API,
+ *			  fix colormap setting at 16 bits/pixel (565)
+ *
+ *		  Paul Mundt 
+ *		  	- PCI hotplug
+ *
+ *		  Jon Smirl <jonsmirl@yahoo.com>
+ * 			- PCI ID update
+ * 			- replace ROM BIOS search
+ *
+ *  Based off of Geert's atyfb.c and vfb.c.
+ *
+ *  TODO:
+ *		- monitor sensing (DDC)
+ *              - virtual display
+ *		- other platform support (only ppc/x86 supported)
+ *		- hardware cursor support
+ *
+ *    Please cc: your patches to brad@neruo.com.
+ */
+
+/*
+ * A special note of gratitude to ATI's devrel for providing documentation,
+ * example code and hardware. Thanks Nitya.	-atong and brad
+ */
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/backlight.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include "../macmodes.h"
+#endif
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#ifdef CONFIG_BOOTX_TEXT
+#include <asm/btext.h>
+#endif /* CONFIG_BOOTX_TEXT */
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/aty128.h>
+
+/* Debug flag */
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) \
+	printk(KERN_DEBUG "aty128fb: %s " fmt, __func__, ##args);
+#else
+#define DBG(fmt, args...)
+#endif
+
+#ifndef CONFIG_PPC_PMAC
+/* default mode */
+static struct fb_var_screeninfo default_var = {
+	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+	640, 480, 640, 480, 0, 0, 8, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+};
+
+#else /* CONFIG_PPC_PMAC */
+/* default to 1024x768 at 75Hz on PPC - this will work
+ * on the iMac, the usual 640x480 @ 60Hz doesn't. */
+static struct fb_var_screeninfo default_var = {
+	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+	1024, 768, 1024, 768, 0, 0, 8, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, 0, 12699, 160, 32, 28, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	FB_VMODE_NONINTERLACED
+};
+#endif /* CONFIG_PPC_PMAC */
+
+/* default modedb mode */
+/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
+static struct fb_videomode defaultmode = {
+	.refresh =	60,
+	.xres =		640,
+	.yres =		480,
+	.pixclock =	39722,
+	.left_margin =	48,
+	.right_margin =	16,
+	.upper_margin =	33,
+	.lower_margin =	10,
+	.hsync_len =	96,
+	.vsync_len =	2,
+	.sync =		0,
+	.vmode =	FB_VMODE_NONINTERLACED
+};
+
+/* Chip generations */
+enum {
+	rage_128,
+	rage_128_pci,
+	rage_128_pro,
+	rage_128_pro_pci,
+	rage_M3,
+	rage_M3_pci,
+	rage_M4,
+	rage_128_ultra,
+};
+
+/* Must match above enum */
+static char * const r128_family[] = {
+	"AGP",
+	"PCI",
+	"PRO AGP",
+	"PRO PCI",
+	"M3 AGP",
+	"M3 PCI",
+	"M4 AGP",
+	"Ultra AGP",
+};
+
+/*
+ * PCI driver prototypes
+ */
+static int aty128_probe(struct pci_dev *pdev,
+                               const struct pci_device_id *ent);
+static void aty128_remove(struct pci_dev *pdev);
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state);
+static int aty128_pci_resume(struct pci_dev *pdev);
+static int aty128_do_resume(struct pci_dev *pdev);
+
+/* supported Rage128 chipsets */
+static struct pci_device_id aty128_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3_pci },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LF,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_MF,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_ML,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PA,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PB,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PC,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PD,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PE,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PG,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PH,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PI,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PJ,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PK,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PM,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PN,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PP,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PQ,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PS,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PT,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PU,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PV,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PW,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PX,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RG,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SE,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SF,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SG,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SH,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SK,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SM,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SN,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TF,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TS,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TT,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TU,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, aty128_pci_tbl);
+
+static struct pci_driver aty128fb_driver = {
+	.name		= "aty128fb",
+	.id_table	= aty128_pci_tbl,
+	.probe		= aty128_probe,
+	.remove		= aty128_remove,
+	.suspend	= aty128_pci_suspend,
+	.resume		= aty128_pci_resume,
+};
+
+/* packed BIOS settings */
+#ifndef CONFIG_PPC
+typedef struct {
+	u8 clock_chip_type;
+	u8 struct_size;
+	u8 accelerator_entry;
+	u8 VGA_entry;
+	u16 VGA_table_offset;
+	u16 POST_table_offset;
+	u16 XCLK;
+	u16 MCLK;
+	u8 num_PLL_blocks;
+	u8 size_PLL_blocks;
+	u16 PCLK_ref_freq;
+	u16 PCLK_ref_divider;
+	u32 PCLK_min_freq;
+	u32 PCLK_max_freq;
+	u16 MCLK_ref_freq;
+	u16 MCLK_ref_divider;
+	u32 MCLK_min_freq;
+	u32 MCLK_max_freq;
+	u16 XCLK_ref_freq;
+	u16 XCLK_ref_divider;
+	u32 XCLK_min_freq;
+	u32 XCLK_max_freq;
+} __attribute__ ((packed)) PLL_BLOCK;
+#endif /* !CONFIG_PPC */
+
+/* onboard memory information */
+struct aty128_meminfo {
+	u8 ML;
+	u8 MB;
+	u8 Trcd;
+	u8 Trp;
+	u8 Twr;
+	u8 CL;
+	u8 Tr2w;
+	u8 LoopLatency;
+	u8 DspOn;
+	u8 Rloop;
+	const char *name;
+};
+
+/* various memory configurations */
+static const struct aty128_meminfo sdr_128   =
+	{ 4, 4, 3, 3, 1, 3, 1, 16, 30, 16, "128-bit SDR SGRAM (1:1)" };
+static const struct aty128_meminfo sdr_64    =
+	{ 4, 8, 3, 3, 1, 3, 1, 17, 46, 17, "64-bit SDR SGRAM (1:1)" };
+static const struct aty128_meminfo sdr_sgram =
+	{ 4, 4, 1, 2, 1, 2, 1, 16, 24, 16, "64-bit SDR SGRAM (2:1)" };
+static const struct aty128_meminfo ddr_sgram =
+	{ 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
+
+static struct fb_fix_screeninfo aty128fb_fix = {
+	.id		= "ATY Rage128",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep	= 8,
+	.ypanstep	= 1,
+	.mmio_len	= 0x2000,
+	.accel		= FB_ACCEL_ATI_RAGE128,
+};
+
+static char *mode_option = NULL;
+
+#ifdef CONFIG_PPC_PMAC
+static int default_vmode = VMODE_1024_768_60;
+static int default_cmode = CMODE_8;
+#endif
+
+static int default_crt_on = 0;
+static int default_lcd_on = 1;
+
+#ifdef CONFIG_MTRR
+static bool mtrr = true;
+#endif
+
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight = 1;
+#else
+static int backlight = 0;
+#endif
+#endif
+
+/* PLL constants */
+struct aty128_constants {
+	u32 ref_clk;
+	u32 ppll_min;
+	u32 ppll_max;
+	u32 ref_divider;
+	u32 xclk;
+	u32 fifo_width;
+	u32 fifo_depth;
+};
+
+struct aty128_crtc {
+	u32 gen_cntl;
+	u32 h_total, h_sync_strt_wid;
+	u32 v_total, v_sync_strt_wid;
+	u32 pitch;
+	u32 offset, offset_cntl;
+	u32 xoffset, yoffset;
+	u32 vxres, vyres;
+	u32 depth, bpp;
+};
+
+struct aty128_pll {
+	u32 post_divider;
+	u32 feedback_divider;
+	u32 vclk;
+};
+
+struct aty128_ddafifo {
+	u32 dda_config;
+	u32 dda_on_off;
+};
+
+/* register values for a specific mode */
+struct aty128fb_par {
+	struct aty128_crtc crtc;
+	struct aty128_pll pll;
+	struct aty128_ddafifo fifo_reg;
+	u32 accel_flags;
+	struct aty128_constants constants;  /* PLL and others      */
+	void __iomem *regbase;              /* remapped mmio       */
+	u32 vram_size;                      /* onboard video ram   */
+	int chip_gen;
+	const struct aty128_meminfo *mem;   /* onboard mem info    */
+#ifdef CONFIG_MTRR
+	struct { int vram; int vram_valid; } mtrr;
+#endif
+	int blitter_may_be_busy;
+	int fifo_slots;                 /* free slots in FIFO (64 max) */
+
+	int crt_on, lcd_on;
+	struct pci_dev *pdev;
+	struct fb_info *next;
+	int	asleep;
+	int	lock_blank;
+
+	u8	red[32];		/* see aty128fb_setcolreg */
+	u8	green[64];
+	u8	blue[32];
+	u32	pseudo_palette[16];	/* used for TRUECOLOR */
+};
+
+
+#define round_div(n, d) ((n+(d/2))/d)
+
+static int aty128fb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info);
+static int aty128fb_set_par(struct fb_info *info);
+static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			      u_int transp, struct fb_info *info);
+static int aty128fb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *fb);
+static int aty128fb_blank(int blank, struct fb_info *fb);
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg);
+static int aty128fb_sync(struct fb_info *info);
+
+    /*
+     *  Internal routines
+     */
+
+static int aty128_encode_var(struct fb_var_screeninfo *var,
+                             const struct aty128fb_par *par);
+static int aty128_decode_var(struct fb_var_screeninfo *var,
+                             struct aty128fb_par *par);
+#if 0
+static void aty128_get_pllinfo(struct aty128fb_par *par, void __iomem *bios);
+static void __iomem *aty128_map_ROM(struct pci_dev *pdev,
+				    const struct aty128fb_par *par);
+#endif
+static void aty128_timings(struct aty128fb_par *par);
+static void aty128_init_engine(struct aty128fb_par *par);
+static void aty128_reset_engine(const struct aty128fb_par *par);
+static void aty128_flush_pixel_cache(const struct aty128fb_par *par);
+static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par);
+static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
+static void wait_for_idle(struct aty128fb_par *par);
+static u32 depth_to_dst(u32 depth);
+
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+static void aty128_bl_set_power(struct fb_info *info, int power);
+#endif
+
+#define BIOS_IN8(v)  	(readb(bios + (v)))
+#define BIOS_IN16(v) 	(readb(bios + (v)) | \
+			  (readb(bios + (v) + 1) << 8))
+#define BIOS_IN32(v) 	(readb(bios + (v)) | \
+			  (readb(bios + (v) + 1) << 8) | \
+			  (readb(bios + (v) + 2) << 16) | \
+			  (readb(bios + (v) + 3) << 24))
+
+
+static struct fb_ops aty128fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= aty128fb_check_var,
+	.fb_set_par	= aty128fb_set_par,
+	.fb_setcolreg	= aty128fb_setcolreg,
+	.fb_pan_display = aty128fb_pan_display,
+	.fb_blank	= aty128fb_blank,
+	.fb_ioctl	= aty128fb_ioctl,
+	.fb_sync	= aty128fb_sync,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+    /*
+     * Functions to read from/write to the mmio registers
+     *	- endian conversions may possibly be avoided by
+     *    using the other register aperture. TODO.
+     */
+static inline u32 _aty_ld_le32(volatile unsigned int regindex, 
+			       const struct aty128fb_par *par)
+{
+	return readl (par->regbase + regindex);
+}
+
+static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, 
+				const struct aty128fb_par *par)
+{
+	writel (val, par->regbase + regindex);
+}
+
+static inline u8 _aty_ld_8(unsigned int regindex,
+			   const struct aty128fb_par *par)
+{
+	return readb (par->regbase + regindex);
+}
+
+static inline void _aty_st_8(unsigned int regindex, u8 val,
+			     const struct aty128fb_par *par)
+{
+	writeb (val, par->regbase + regindex);
+}
+
+#define aty_ld_le32(regindex)		_aty_ld_le32(regindex, par)
+#define aty_st_le32(regindex, val)	_aty_st_le32(regindex, val, par)
+#define aty_ld_8(regindex)		_aty_ld_8(regindex, par)
+#define aty_st_8(regindex, val)		_aty_st_8(regindex, val, par)
+
+    /*
+     * Functions to read from/write to the pll registers
+     */
+
+#define aty_ld_pll(pll_index)		_aty_ld_pll(pll_index, par)
+#define aty_st_pll(pll_index, val)	_aty_st_pll(pll_index, val, par)
+
+
+static u32 _aty_ld_pll(unsigned int pll_index,
+		       const struct aty128fb_par *par)
+{       
+	aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F);
+	return aty_ld_le32(CLOCK_CNTL_DATA);
+}
+
+    
+static void _aty_st_pll(unsigned int pll_index, u32 val,
+			const struct aty128fb_par *par)
+{
+	aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x3F) | PLL_WR_EN);
+	aty_st_le32(CLOCK_CNTL_DATA, val);
+}
+
+
+/* return true when the PLL has completed an atomic update */
+static int aty_pll_readupdate(const struct aty128fb_par *par)
+{
+	return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
+}
+
+
+static void aty_pll_wait_readupdate(const struct aty128fb_par *par)
+{
+	unsigned long timeout = jiffies + HZ/100; // should be more than enough
+	int reset = 1;
+
+	while (time_before(jiffies, timeout))
+		if (aty_pll_readupdate(par)) {
+			reset = 0;
+			break;
+		}
+
+	if (reset)	/* reset engine?? */
+		printk(KERN_DEBUG "aty128fb: PLL write timeout!\n");
+}
+
+
+/* tell PLL to update */
+static void aty_pll_writeupdate(const struct aty128fb_par *par)
+{
+	aty_pll_wait_readupdate(par);
+
+	aty_st_pll(PPLL_REF_DIV,
+		   aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W);
+}
+
+
+/* write to the scratch register to test r/w functionality */
+static int register_test(const struct aty128fb_par *par)
+{
+	u32 val;
+	int flag = 0;
+
+	val = aty_ld_le32(BIOS_0_SCRATCH);
+
+	aty_st_le32(BIOS_0_SCRATCH, 0x55555555);
+	if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) {
+		aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA);
+
+		if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA)
+			flag = 1; 
+	}
+
+	aty_st_le32(BIOS_0_SCRATCH, val);	// restore value
+	return flag;
+}
+
+
+/*
+ * Accelerator engine functions
+ */
+static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par)
+{
+	int i;
+
+	for (;;) {
+		for (i = 0; i < 2000000; i++) {
+			par->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
+			if (par->fifo_slots >= entries)
+				return;
+		}
+		aty128_reset_engine(par);
+	}
+}
+
+
+static void wait_for_idle(struct aty128fb_par *par)
+{
+	int i;
+
+	do_wait_for_fifo(64, par);
+
+	for (;;) {
+		for (i = 0; i < 2000000; i++) {
+			if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) {
+				aty128_flush_pixel_cache(par);
+				par->blitter_may_be_busy = 0;
+				return;
+			}
+		}
+		aty128_reset_engine(par);
+	}
+}
+
+
+static void wait_for_fifo(u16 entries, struct aty128fb_par *par)
+{
+	if (par->fifo_slots < entries)
+		do_wait_for_fifo(64, par);
+	par->fifo_slots -= entries;
+}
+
+
+static void aty128_flush_pixel_cache(const struct aty128fb_par *par)
+{
+	int i;
+	u32 tmp;
+
+	tmp = aty_ld_le32(PC_NGUI_CTLSTAT);
+	tmp &= ~(0x00ff);
+	tmp |= 0x00ff;
+	aty_st_le32(PC_NGUI_CTLSTAT, tmp);
+
+	for (i = 0; i < 2000000; i++)
+		if (!(aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY))
+			break;
+}
+
+
+static void aty128_reset_engine(const struct aty128fb_par *par)
+{
+	u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
+
+	aty128_flush_pixel_cache(par);
+
+	clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX);
+	mclk_cntl = aty_ld_pll(MCLK_CNTL);
+
+	aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000);
+
+	gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL);
+	aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
+	aty_ld_le32(GEN_RESET_CNTL);
+	aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI));
+	aty_ld_le32(GEN_RESET_CNTL);
+
+	aty_st_pll(MCLK_CNTL, mclk_cntl);
+	aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index);
+	aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl);
+
+	/* use old pio mode */
+	aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
+
+	DBG("engine reset");
+}
+
+
+static void aty128_init_engine(struct aty128fb_par *par)
+{
+	u32 pitch_value;
+
+	wait_for_idle(par);
+
+	/* 3D scaler not spoken here */
+	wait_for_fifo(1, par);
+	aty_st_le32(SCALE_3D_CNTL, 0x00000000);
+
+	aty128_reset_engine(par);
+
+	pitch_value = par->crtc.pitch;
+	if (par->crtc.bpp == 24) {
+		pitch_value = pitch_value * 3;
+	}
+
+	wait_for_fifo(4, par);
+	/* setup engine offset registers */
+	aty_st_le32(DEFAULT_OFFSET, 0x00000000);
+
+	/* setup engine pitch registers */
+	aty_st_le32(DEFAULT_PITCH, pitch_value);
+
+	/* set the default scissor register to max dimensions */
+	aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF);
+
+	/* set the drawing controls registers */
+	aty_st_le32(DP_GUI_MASTER_CNTL,
+		    GMC_SRC_PITCH_OFFSET_DEFAULT		|
+		    GMC_DST_PITCH_OFFSET_DEFAULT		|
+		    GMC_SRC_CLIP_DEFAULT			|
+		    GMC_DST_CLIP_DEFAULT			|
+		    GMC_BRUSH_SOLIDCOLOR			|
+		    (depth_to_dst(par->crtc.depth) << 8)	|
+		    GMC_SRC_DSTCOLOR			|
+		    GMC_BYTE_ORDER_MSB_TO_LSB		|
+		    GMC_DP_CONVERSION_TEMP_6500		|
+		    ROP3_PATCOPY				|
+		    GMC_DP_SRC_RECT				|
+		    GMC_3D_FCN_EN_CLR			|
+		    GMC_DST_CLR_CMP_FCN_CLEAR		|
+		    GMC_AUX_CLIP_CLEAR			|
+		    GMC_WRITE_MASK_SET);
+
+	wait_for_fifo(8, par);
+	/* clear the line drawing registers */
+	aty_st_le32(DST_BRES_ERR, 0);
+	aty_st_le32(DST_BRES_INC, 0);
+	aty_st_le32(DST_BRES_DEC, 0);
+
+	/* set brush color registers */
+	aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */
+	aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */
+
+	/* set source color registers */
+	aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF);   /* white */
+	aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000);   /* black */
+
+	/* default write mask */
+	aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
+
+	/* Wait for all the writes to be completed before returning */
+	wait_for_idle(par);
+}
+
+
+/* convert depth values to their register representation */
+static u32 depth_to_dst(u32 depth)
+{
+	if (depth <= 8)
+		return DST_8BPP;
+	else if (depth <= 15)
+		return DST_15BPP;
+	else if (depth == 16)
+		return DST_16BPP;
+	else if (depth <= 24)
+		return DST_24BPP;
+	else if (depth <= 32)
+		return DST_32BPP;
+
+	return -EINVAL;
+}
+
+/*
+ * PLL informations retreival
+ */
+
+
+#ifndef __sparc__
+static void __iomem *aty128_map_ROM(const struct aty128fb_par *par,
+				    struct pci_dev *dev)
+{
+	u16 dptr;
+	u8 rom_type;
+	void __iomem *bios;
+	size_t rom_size;
+
+    	/* Fix from ATI for problem with Rage128 hardware not leaving ROM enabled */
+    	unsigned int temp;
+	temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
+	temp &= 0x00ffffffu;
+	temp |= 0x04 << 24;
+	aty_st_le32(RAGE128_MPP_TB_CONFIG, temp);
+	temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
+
+	bios = pci_map_rom(dev, &rom_size);
+
+	if (!bios) {
+		printk(KERN_ERR "aty128fb: ROM failed to map\n");
+		return NULL;
+	}
+
+	/* Very simple test to make sure it appeared */
+	if (BIOS_IN16(0) != 0xaa55) {
+		printk(KERN_DEBUG "aty128fb: Invalid ROM signature %x should "
+			" be 0xaa55\n", BIOS_IN16(0));
+		goto failed;
+	}
+
+	/* Look for the PCI data to check the ROM type */
+	dptr = BIOS_IN16(0x18);
+
+	/* Check the PCI data signature. If it's wrong, we still assume a normal
+	 * x86 ROM for now, until I've verified this works everywhere.
+	 * The goal here is more to phase out Open Firmware images.
+	 *
+	 * Currently, we only look at the first PCI data, we could iteratre and
+	 * deal with them all, and we should use fb_bios_start relative to start
+	 * of image and not relative start of ROM, but so far, I never found a
+	 * dual-image ATI card.
+	 *
+	 * typedef struct {
+	 * 	u32	signature;	+ 0x00
+	 * 	u16	vendor;		+ 0x04
+	 * 	u16	device;		+ 0x06
+	 * 	u16	reserved_1;	+ 0x08
+	 * 	u16	dlen;		+ 0x0a
+	 * 	u8	drevision;	+ 0x0c
+	 * 	u8	class_hi;	+ 0x0d
+	 * 	u16	class_lo;	+ 0x0e
+	 * 	u16	ilen;		+ 0x10
+	 * 	u16	irevision;	+ 0x12
+	 * 	u8	type;		+ 0x14
+	 * 	u8	indicator;	+ 0x15
+	 * 	u16	reserved_2;	+ 0x16
+	 * } pci_data_t;
+	 */
+	if (BIOS_IN32(dptr) !=  (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
+		printk(KERN_WARNING "aty128fb: PCI DATA signature in ROM incorrect: %08x\n",
+		       BIOS_IN32(dptr));
+		goto anyway;
+	}
+	rom_type = BIOS_IN8(dptr + 0x14);
+	switch(rom_type) {
+	case 0:
+		printk(KERN_INFO "aty128fb: Found Intel x86 BIOS ROM Image\n");
+		break;
+	case 1:
+		printk(KERN_INFO "aty128fb: Found Open Firmware ROM Image\n");
+		goto failed;
+	case 2:
+		printk(KERN_INFO "aty128fb: Found HP PA-RISC ROM Image\n");
+		goto failed;
+	default:
+		printk(KERN_INFO "aty128fb: Found unknown type %d ROM Image\n",
+		       rom_type);
+		goto failed;
+	}
+ anyway:
+	return bios;
+
+ failed:
+	pci_unmap_rom(dev, bios);
+	return NULL;
+}
+
+static void aty128_get_pllinfo(struct aty128fb_par *par,
+			       unsigned char __iomem *bios)
+{
+	unsigned int bios_hdr;
+	unsigned int bios_pll;
+
+	bios_hdr = BIOS_IN16(0x48);
+	bios_pll = BIOS_IN16(bios_hdr + 0x30);
+	
+	par->constants.ppll_max = BIOS_IN32(bios_pll + 0x16);
+	par->constants.ppll_min = BIOS_IN32(bios_pll + 0x12);
+	par->constants.xclk = BIOS_IN16(bios_pll + 0x08);
+	par->constants.ref_divider = BIOS_IN16(bios_pll + 0x10);
+	par->constants.ref_clk = BIOS_IN16(bios_pll + 0x0e);
+
+	DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d ref clock %d\n",
+			par->constants.ppll_max, par->constants.ppll_min,
+			par->constants.xclk, par->constants.ref_divider,
+			par->constants.ref_clk);
+
+}           
+
+#ifdef CONFIG_X86
+static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par)
+{
+	/* I simplified this code as we used to miss the signatures in
+	 * a lot of case. It's now closer to XFree, we just don't check
+	 * for signatures at all... Something better will have to be done
+	 * if we end up having conflicts
+	 */
+        u32  segstart;
+        unsigned char __iomem *rom_base = NULL;
+                                                
+        for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
+                rom_base = ioremap(segstart, 0x10000);
+		if (rom_base == NULL)
+			return NULL;
+		if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
+	                break;
+                iounmap(rom_base);
+		rom_base = NULL;
+        }
+	return rom_base;
+}
+#endif
+#endif /* ndef(__sparc__) */
+
+/* fill in known card constants if pll_block is not available */
+static void aty128_timings(struct aty128fb_par *par)
+{
+#ifdef CONFIG_PPC_OF
+	/* instead of a table lookup, assume OF has properly
+	 * setup the PLL registers and use their values
+	 * to set the XCLK values and reference divider values */
+
+	u32 x_mpll_ref_fb_div;
+	u32 xclk_cntl;
+	u32 Nx, M;
+	unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
+#endif
+
+	if (!par->constants.ref_clk)
+		par->constants.ref_clk = 2950;
+
+#ifdef CONFIG_PPC_OF
+	x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
+	xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
+	Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
+	M  = x_mpll_ref_fb_div & 0x0000ff;
+
+	par->constants.xclk = round_div((2 * Nx * par->constants.ref_clk),
+					(M * PostDivSet[xclk_cntl]));
+
+	par->constants.ref_divider =
+		aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
+#endif
+
+	if (!par->constants.ref_divider) {
+		par->constants.ref_divider = 0x3b;
+
+		aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
+		aty_pll_writeupdate(par);
+	}
+	aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider);
+	aty_pll_writeupdate(par);
+
+	/* from documentation */
+	if (!par->constants.ppll_min)
+		par->constants.ppll_min = 12500;
+	if (!par->constants.ppll_max)
+		par->constants.ppll_max = 25000;    /* 23000 on some cards? */
+	if (!par->constants.xclk)
+		par->constants.xclk = 0x1d4d;	     /* same as mclk */
+
+	par->constants.fifo_width = 128;
+	par->constants.fifo_depth = 32;
+
+	switch (aty_ld_le32(MEM_CNTL) & 0x3) {
+	case 0:
+		par->mem = &sdr_128;
+		break;
+	case 1:
+		par->mem = &sdr_sgram;
+		break;
+	case 2:
+		par->mem = &ddr_sgram;
+		break;
+	default:
+		par->mem = &sdr_sgram;
+	}
+}
+
+
+
+/*
+ * CRTC programming
+ */
+
+/* Program the CRTC registers */
+static void aty128_set_crtc(const struct aty128_crtc *crtc,
+			    const struct aty128fb_par *par)
+{
+	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
+	aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
+	aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
+	aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total);
+	aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
+	aty_st_le32(CRTC_PITCH, crtc->pitch);
+	aty_st_le32(CRTC_OFFSET, crtc->offset);
+	aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl);
+	/* Disable ATOMIC updating.  Is this the right place? */
+	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~(0x00030000));
+}
+
+
+static int aty128_var_to_crtc(const struct fb_var_screeninfo *var,
+			      struct aty128_crtc *crtc,
+			      const struct aty128fb_par *par)
+{
+	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp, dst;
+	u32 left, right, upper, lower, hslen, vslen, sync, vmode;
+	u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
+	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
+	u32 depth, bytpp;
+	u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 };
+
+	/* input */
+	xres = var->xres;
+	yres = var->yres;
+	vxres   = var->xres_virtual;
+	vyres   = var->yres_virtual;
+	xoffset = var->xoffset;
+	yoffset = var->yoffset;
+	bpp   = var->bits_per_pixel;
+	left  = var->left_margin;
+	right = var->right_margin;
+	upper = var->upper_margin;
+	lower = var->lower_margin;
+	hslen = var->hsync_len;
+	vslen = var->vsync_len;
+	sync  = var->sync;
+	vmode = var->vmode;
+
+	if (bpp != 16)
+		depth = bpp;
+	else
+		depth = (var->green.length == 6) ? 16 : 15;
+
+	/* check for mode eligibility
+	 * accept only non interlaced modes */
+	if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	/* convert (and round up) and validate */
+	xres = (xres + 7) & ~7;
+	xoffset = (xoffset + 7) & ~7;
+
+	if (vxres < xres + xoffset)
+		vxres = xres + xoffset;
+
+	if (vyres < yres + yoffset)
+		vyres = yres + yoffset;
+
+	/* convert depth into ATI register depth */
+	dst = depth_to_dst(depth);
+
+	if (dst == -EINVAL) {
+		printk(KERN_ERR "aty128fb: Invalid depth or RGBA\n");
+		return -EINVAL;
+	}
+
+	/* convert register depth to bytes per pixel */
+	bytpp = mode_bytpp[dst];
+
+	/* make sure there is enough video ram for the mode */
+	if ((u32)(vxres * vyres * bytpp) > par->vram_size) {
+		printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
+		return -EINVAL;
+	}
+
+	h_disp = (xres >> 3) - 1;
+	h_total = (((xres + right + hslen + left) >> 3) - 1) & 0xFFFFL;
+
+	v_disp = yres - 1;
+	v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL;
+
+	/* check to make sure h_total and v_total are in range */
+	if (((h_total >> 3) - 1) > 0x1ff || (v_total - 1) > 0x7FF) {
+		printk(KERN_ERR "aty128fb: invalid width ranges\n");
+		return -EINVAL;
+	}
+
+	h_sync_wid = (hslen + 7) >> 3;
+	if (h_sync_wid == 0)
+		h_sync_wid = 1;
+	else if (h_sync_wid > 0x3f)        /* 0x3f = max hwidth */
+		h_sync_wid = 0x3f;
+
+	h_sync_strt = (h_disp << 3) + right;
+
+	v_sync_wid = vslen;
+	if (v_sync_wid == 0)
+		v_sync_wid = 1;
+	else if (v_sync_wid > 0x1f)        /* 0x1f = max vwidth */
+		v_sync_wid = 0x1f;
+    
+	v_sync_strt = v_disp + lower;
+
+	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+    
+	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
+
+	crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8);
+
+	crtc->h_total = h_total | (h_disp << 16);
+	crtc->v_total = v_total | (v_disp << 16);
+
+	crtc->h_sync_strt_wid = h_sync_strt | (h_sync_wid << 16) |
+	        (h_sync_pol << 23);
+	crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
+                (v_sync_pol << 23);
+
+	crtc->pitch = vxres >> 3;
+
+	crtc->offset = 0;
+
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+		crtc->offset_cntl = 0x00010000;
+	else
+		crtc->offset_cntl = 0;
+
+	crtc->vxres = vxres;
+	crtc->vyres = vyres;
+	crtc->xoffset = xoffset;
+	crtc->yoffset = yoffset;
+	crtc->depth = depth;
+	crtc->bpp = bpp;
+
+	return 0;
+}
+
+
+static int aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
+{
+
+	/* fill in pixel info */
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.offset = 0;
+	var->blue.msb_right = 0;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	switch (pix_width) {
+	case CRTC_PIX_WIDTH_8BPP:
+		var->bits_per_pixel = 8;
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case CRTC_PIX_WIDTH_15BPP:
+		var->bits_per_pixel = 16;
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		break;
+	case CRTC_PIX_WIDTH_16BPP:
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case CRTC_PIX_WIDTH_24BPP:
+		var->bits_per_pixel = 24;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case CRTC_PIX_WIDTH_32BPP:
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	default:
+		printk(KERN_ERR "aty128fb: Invalid pixel width\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+static int aty128_crtc_to_var(const struct aty128_crtc *crtc,
+			      struct fb_var_screeninfo *var)
+{
+	u32 xres, yres, left, right, upper, lower, hslen, vslen, sync;
+	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
+	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
+	u32 pix_width;
+
+	/* fun with masking */
+	h_total     = crtc->h_total & 0x1ff;
+	h_disp      = (crtc->h_total >> 16) & 0xff;
+	h_sync_strt = (crtc->h_sync_strt_wid >> 3) & 0x1ff;
+	h_sync_dly  = crtc->h_sync_strt_wid & 0x7;
+	h_sync_wid  = (crtc->h_sync_strt_wid >> 16) & 0x3f;
+	h_sync_pol  = (crtc->h_sync_strt_wid >> 23) & 0x1;
+	v_total     = crtc->v_total & 0x7ff;
+	v_disp      = (crtc->v_total >> 16) & 0x7ff;
+	v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
+	v_sync_wid  = (crtc->v_sync_strt_wid >> 16) & 0x1f;
+	v_sync_pol  = (crtc->v_sync_strt_wid >> 23) & 0x1;
+	c_sync      = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
+	pix_width   = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
+
+	/* do conversions */
+	xres  = (h_disp + 1) << 3;
+	yres  = v_disp + 1;
+	left  = ((h_total - h_sync_strt - h_sync_wid) << 3) - h_sync_dly;
+	right = ((h_sync_strt - h_disp) << 3) + h_sync_dly;
+	hslen = h_sync_wid << 3;
+	upper = v_total - v_sync_strt - v_sync_wid;
+	lower = v_sync_strt - v_disp;
+	vslen = v_sync_wid;
+	sync  = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
+		(v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+		(c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
+
+	aty128_pix_width_to_var(pix_width, var);
+
+	var->xres = xres;
+	var->yres = yres;
+	var->xres_virtual = crtc->vxres;
+	var->yres_virtual = crtc->vyres;
+	var->xoffset = crtc->xoffset;
+	var->yoffset = crtc->yoffset;
+	var->left_margin  = left;
+	var->right_margin = right;
+	var->upper_margin = upper;
+	var->lower_margin = lower;
+	var->hsync_len = hslen;
+	var->vsync_len = vslen;
+	var->sync  = sync;
+	var->vmode = FB_VMODE_NONINTERLACED;
+
+	return 0;
+}
+
+static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
+{
+	if (on) {
+		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) |
+			    CRT_CRTC_ON);
+		aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) |
+			    DAC_PALETTE2_SNOOP_EN));
+	} else
+		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) &
+			    ~CRT_CRTC_ON);
+}
+
+static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
+{
+	u32 reg;
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+#endif
+
+	if (on) {
+		reg = aty_ld_le32(LVDS_GEN_CNTL);
+		reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
+		reg &= ~LVDS_DISPLAY_DIS;
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+		aty128_bl_set_power(info, FB_BLANK_UNBLANK);
+#endif	
+	} else {
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+		aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
+#endif	
+		reg = aty_ld_le32(LVDS_GEN_CNTL);
+		reg |= LVDS_DISPLAY_DIS;
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+		mdelay(100);
+		reg &= ~(LVDS_ON /*| LVDS_EN*/);
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+	}
+}
+
+static void aty128_set_pll(struct aty128_pll *pll,
+			   const struct aty128fb_par *par)
+{
+	u32 div3;
+
+	unsigned char post_conv[] =	/* register values for post dividers */
+        { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
+
+	/* select PPLL_DIV_3 */
+	aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
+
+	/* reset PLL */
+	aty_st_pll(PPLL_CNTL,
+		   aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
+
+	/* write the reference divider */
+	aty_pll_wait_readupdate(par);
+	aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider & 0x3ff);
+	aty_pll_writeupdate(par);
+
+	div3 = aty_ld_pll(PPLL_DIV_3);
+	div3 &= ~PPLL_FB3_DIV_MASK;
+	div3 |= pll->feedback_divider;
+	div3 &= ~PPLL_POST3_DIV_MASK;
+	div3 |= post_conv[pll->post_divider] << 16;
+
+	/* write feedback and post dividers */
+	aty_pll_wait_readupdate(par);
+	aty_st_pll(PPLL_DIV_3, div3);
+	aty_pll_writeupdate(par);
+
+	aty_pll_wait_readupdate(par);
+	aty_st_pll(HTOTAL_CNTL, 0);	/* no horiz crtc adjustment */
+	aty_pll_writeupdate(par);
+
+	/* clear the reset, just in case */
+	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
+}
+
+
+static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
+			     const struct aty128fb_par *par)
+{
+	const struct aty128_constants c = par->constants;
+	unsigned char post_dividers[] = {1,2,4,8,3,6,12};
+	u32 output_freq;
+	u32 vclk;        /* in .01 MHz */
+	int i = 0;
+	u32 n, d;
+
+	vclk = 100000000 / period_in_ps;	/* convert units to 10 kHz */
+
+	/* adjust pixel clock if necessary */
+	if (vclk > c.ppll_max)
+		vclk = c.ppll_max;
+	if (vclk * 12 < c.ppll_min)
+		vclk = c.ppll_min/12;
+
+	/* now, find an acceptable divider */
+	for (i = 0; i < ARRAY_SIZE(post_dividers); i++) {
+		output_freq = post_dividers[i] * vclk;
+		if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
+			pll->post_divider = post_dividers[i];
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(post_dividers))
+		return -EINVAL;
+
+	/* calculate feedback divider */
+	n = c.ref_divider * output_freq;
+	d = c.ref_clk;
+
+	pll->feedback_divider = round_div(n, d);
+	pll->vclk = vclk;
+
+	DBG("post %d feedback %d vlck %d output %d ref_divider %d "
+	    "vclk_per: %d\n", pll->post_divider,
+	    pll->feedback_divider, vclk, output_freq,
+	    c.ref_divider, period_in_ps);
+
+	return 0;
+}
+
+
+static int aty128_pll_to_var(const struct aty128_pll *pll,
+			     struct fb_var_screeninfo *var)
+{
+	var->pixclock = 100000000 / pll->vclk;
+
+	return 0;
+}
+
+
+static void aty128_set_fifo(const struct aty128_ddafifo *dsp,
+			    const struct aty128fb_par *par)
+{
+	aty_st_le32(DDA_CONFIG, dsp->dda_config);
+	aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);
+}
+
+
+static int aty128_ddafifo(struct aty128_ddafifo *dsp,
+			  const struct aty128_pll *pll,
+			  u32 depth,
+			  const struct aty128fb_par *par)
+{
+	const struct aty128_meminfo *m = par->mem;
+	u32 xclk = par->constants.xclk;
+	u32 fifo_width = par->constants.fifo_width;
+	u32 fifo_depth = par->constants.fifo_depth;
+	s32 x, b, p, ron, roff;
+	u32 n, d, bpp;
+
+	/* round up to multiple of 8 */
+	bpp = (depth+7) & ~7;
+
+	n = xclk * fifo_width;
+	d = pll->vclk * bpp;
+	x = round_div(n, d);
+
+	ron = 4 * m->MB +
+		3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +
+		2 * m->Trp +
+		m->Twr +
+		m->CL +
+		m->Tr2w +
+		x;
+
+	DBG("x %x\n", x);
+
+	b = 0;
+	while (x) {
+		x >>= 1;
+		b++;
+	}
+	p = b + 1;
+
+	ron <<= (11 - p);
+
+	n <<= (11 - p);
+	x = round_div(n, d);
+	roff = x * (fifo_depth - 4);
+
+	if ((ron + m->Rloop) >= roff) {
+		printk(KERN_ERR "aty128fb: Mode out of range!\n");
+		return -EINVAL;
+	}
+
+	DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
+	    p, m->Rloop, x, ron, roff);
+
+	dsp->dda_config = p << 16 | m->Rloop << 20 | x;
+	dsp->dda_on_off = ron << 16 | roff;
+
+	return 0;
+}
+
+
+/*
+ * This actually sets the video mode.
+ */
+static int aty128fb_set_par(struct fb_info *info)
+{ 
+	struct aty128fb_par *par = info->par;
+	u32 config;
+	int err;
+
+	if ((err = aty128_decode_var(&info->var, par)) != 0)
+		return err;
+
+	if (par->blitter_may_be_busy)
+		wait_for_idle(par);
+
+	/* clear all registers that may interfere with mode setting */
+	aty_st_le32(OVR_CLR, 0);
+	aty_st_le32(OVR_WID_LEFT_RIGHT, 0);
+	aty_st_le32(OVR_WID_TOP_BOTTOM, 0);
+	aty_st_le32(OV0_SCALE_CNTL, 0);
+	aty_st_le32(MPP_TB_CONFIG, 0);
+	aty_st_le32(MPP_GP_CONFIG, 0);
+	aty_st_le32(SUBPIC_CNTL, 0);
+	aty_st_le32(VIPH_CONTROL, 0);
+	aty_st_le32(I2C_CNTL_1, 0);         /* turn off i2c */
+	aty_st_le32(GEN_INT_CNTL, 0);	/* turn off interrupts */
+	aty_st_le32(CAP0_TRIG_CNTL, 0);
+	aty_st_le32(CAP1_TRIG_CNTL, 0);
+
+	aty_st_8(CRTC_EXT_CNTL + 1, 4);	/* turn video off */
+
+	aty128_set_crtc(&par->crtc, par);
+	aty128_set_pll(&par->pll, par);
+	aty128_set_fifo(&par->fifo_reg, par);
+
+	config = aty_ld_le32(CNFG_CNTL) & ~3;
+
+#if defined(__BIG_ENDIAN)
+	if (par->crtc.bpp == 32)
+		config |= 2;	/* make aperture do 32 bit swapping */
+	else if (par->crtc.bpp == 16)
+		config |= 1;	/* make aperture do 16 bit swapping */
+#endif
+
+	aty_st_le32(CNFG_CNTL, config);
+	aty_st_8(CRTC_EXT_CNTL + 1, 0);	/* turn the video back on */
+
+	info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
+	info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR
+		: FB_VISUAL_DIRECTCOLOR;
+
+	if (par->chip_gen == rage_M3) {
+		aty128_set_crt_enable(par, par->crt_on);
+		aty128_set_lcd_enable(par, par->lcd_on);
+	}
+	if (par->accel_flags & FB_ACCELF_TEXT)
+		aty128_init_engine(par);
+
+#ifdef CONFIG_BOOTX_TEXT
+	btext_update_display(info->fix.smem_start,
+			     (((par->crtc.h_total>>16) & 0xff)+1)*8,
+			     ((par->crtc.v_total>>16) & 0x7ff)+1,
+			     par->crtc.bpp,
+			     par->crtc.vxres*par->crtc.bpp/8);
+#endif /* CONFIG_BOOTX_TEXT */
+
+	return 0;
+}
+
+/*
+ *  encode/decode the User Defined Part of the Display
+ */
+
+static int aty128_decode_var(struct fb_var_screeninfo *var,
+			     struct aty128fb_par *par)
+{
+	int err;
+	struct aty128_crtc crtc;
+	struct aty128_pll pll;
+	struct aty128_ddafifo fifo_reg;
+
+	if ((err = aty128_var_to_crtc(var, &crtc, par)))
+		return err;
+
+	if ((err = aty128_var_to_pll(var->pixclock, &pll, par)))
+		return err;
+
+	if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par)))
+		return err;
+
+	par->crtc = crtc;
+	par->pll = pll;
+	par->fifo_reg = fifo_reg;
+	par->accel_flags = var->accel_flags;
+
+	return 0;
+}
+
+
+static int aty128_encode_var(struct fb_var_screeninfo *var,
+			     const struct aty128fb_par *par)
+{
+	int err;
+
+	if ((err = aty128_crtc_to_var(&par->crtc, var)))
+		return err;
+
+	if ((err = aty128_pll_to_var(&par->pll, var)))
+		return err;
+
+	var->nonstd = 0;
+	var->activate = 0;
+
+	var->height = -1;
+	var->width = -1;
+	var->accel_flags = par->accel_flags;
+
+	return 0;
+}           
+
+
+static int aty128fb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct aty128fb_par par;
+	int err;
+
+	par = *(struct aty128fb_par *)info->par;
+	if ((err = aty128_decode_var(var, &par)) != 0)
+		return err;
+	aty128_encode_var(var, &par);
+	return 0;
+}
+
+
+/*
+ *  Pan or Wrap the Display
+ */
+static int aty128fb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *fb)
+{
+	struct aty128fb_par *par = fb->par;
+	u32 xoffset, yoffset;
+	u32 offset;
+	u32 xres, yres;
+
+	xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;
+	yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
+
+	xoffset = (var->xoffset +7) & ~7;
+	yoffset = var->yoffset;
+
+	if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
+		return -EINVAL;
+
+	par->crtc.xoffset = xoffset;
+	par->crtc.yoffset = yoffset;
+
+	offset = ((yoffset * par->crtc.vxres + xoffset) * (par->crtc.bpp >> 3))
+									  & ~7;
+
+	if (par->crtc.bpp == 24)
+		offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */
+
+	aty_st_le32(CRTC_OFFSET, offset);
+
+	return 0;
+}
+
+
+/*
+ *  Helper function to store a single palette register
+ */
+static void aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
+			  struct aty128fb_par *par)
+{
+	if (par->chip_gen == rage_M3) {
+#if 0
+		/* Note: For now, on M3, we set palette on both heads, which may
+		 * be useless. Can someone with a M3 check this ?
+		 * 
+		 * This code would still be useful if using the second CRTC to 
+		 * do mirroring
+		 */
+
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) |
+			    DAC_PALETTE_ACCESS_CNTL);
+		aty_st_8(PALETTE_INDEX, regno);
+		aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
+#endif
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) &
+			    ~DAC_PALETTE_ACCESS_CNTL);
+	}
+
+	aty_st_8(PALETTE_INDEX, regno);
+	aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
+}
+
+static int aty128fb_sync(struct fb_info *info)
+{
+	struct aty128fb_par *par = info->par;
+
+	if (par->blitter_may_be_busy)
+		wait_for_idle(par);
+	return 0;
+}
+
+#ifndef MODULE
+static int aty128fb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "lcd:", 4)) {
+			default_lcd_on = simple_strtoul(this_opt+4, NULL, 0);
+			continue;
+		} else if (!strncmp(this_opt, "crt:", 4)) {
+			default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
+			continue;
+		} else if (!strncmp(this_opt, "backlight:", 10)) {
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+			backlight = simple_strtoul(this_opt+10, NULL, 0);
+#endif
+			continue;
+		}
+#ifdef CONFIG_MTRR
+		if(!strncmp(this_opt, "nomtrr", 6)) {
+			mtrr = 0;
+			continue;
+		}
+#endif
+#ifdef CONFIG_PPC_PMAC
+		/* vmode and cmode deprecated */
+		if (!strncmp(this_opt, "vmode:", 6)) {
+			unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
+			if (vmode > 0 && vmode <= VMODE_MAX)
+				default_vmode = vmode;
+			continue;
+		} else if (!strncmp(this_opt, "cmode:", 6)) {
+			unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+			switch (cmode) {
+			case 0:
+			case 8:
+				default_cmode = CMODE_8;
+				break;
+			case 15:
+			case 16:
+				default_cmode = CMODE_16;
+				break;
+			case 24:
+			case 32:
+				default_cmode = CMODE_32;
+				break;
+			}
+			continue;
+		}
+#endif /* CONFIG_PPC_PMAC */
+		mode_option = this_opt;
+	}
+	return 0;
+}
+#endif  /*  MODULE  */
+
+/* Backlight */
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+#define MAX_LEVEL 0xFF
+
+static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
+		int level)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	int atylevel;
+
+	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
+	atylevel = MAX_LEVEL -
+		(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
+
+	if (atylevel < 0)
+		atylevel = 0;
+	else if (atylevel > MAX_LEVEL)
+		atylevel = MAX_LEVEL;
+
+	return atylevel;
+}
+
+/* We turn off the LCD completely instead of just dimming the backlight.
+ * This provides greater power saving and the display is useless without
+ * backlight anyway
+ */
+#define BACKLIGHT_LVDS_OFF
+/* That one prevents proper CRT output with LCD off */
+#undef BACKLIGHT_DAC_OFF
+
+static int aty128_bl_update_status(struct backlight_device *bd)
+{
+	struct aty128fb_par *par = bl_get_data(bd);
+	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
+	int level;
+
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK ||
+	    !par->lcd_on)
+		level = 0;
+	else
+		level = bd->props.brightness;
+
+	reg |= LVDS_BL_MOD_EN | LVDS_BLON;
+	if (level > 0) {
+		reg |= LVDS_DIGION;
+		if (!(reg & LVDS_ON)) {
+			reg &= ~LVDS_BLON;
+			aty_st_le32(LVDS_GEN_CNTL, reg);
+			aty_ld_le32(LVDS_GEN_CNTL);
+			mdelay(10);
+			reg |= LVDS_BLON;
+			aty_st_le32(LVDS_GEN_CNTL, reg);
+		}
+		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+		reg |= (aty128_bl_get_level_brightness(par, level) <<
+			LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+		reg |= LVDS_ON | LVDS_EN;
+		reg &= ~LVDS_DISPLAY_DIS;
+#endif
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
+#endif
+	} else {
+		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+		reg |= (aty128_bl_get_level_brightness(par, 0) <<
+			LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+		reg |= LVDS_DISPLAY_DIS;
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+		aty_ld_le32(LVDS_GEN_CNTL);
+		udelay(10);
+		reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
+#endif
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
+#endif
+	}
+
+	return 0;
+}
+
+static int aty128_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops aty128_bl_data = {
+	.get_brightness	= aty128_bl_get_brightness,
+	.update_status	= aty128_bl_update_status,
+};
+
+static void aty128_bl_set_power(struct fb_info *info, int power)
+{
+	if (info->bl_dev) {
+		info->bl_dev->props.power = power;
+		backlight_update_status(info->bl_dev);
+	}
+}
+
+static void aty128_bl_init(struct aty128fb_par *par)
+{
+	struct backlight_properties props;
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd;
+	char name[12];
+
+	/* Could be extended to Rage128Pro LVDS output too */
+	if (par->chip_gen != rage_M3)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati"))
+		return;
+#endif
+
+	snprintf(name, sizeof(name), "aty128bl%d", info->node);
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
+				       &props);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk(KERN_WARNING "aty128: Backlight registration failed\n");
+		goto error;
+	}
+
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+		 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+		219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	printk("aty128: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+static void aty128_bl_exit(struct backlight_device *bd)
+{
+	backlight_device_unregister(bd);
+	printk("aty128: Backlight unloaded\n");
+}
+#endif /* CONFIG_FB_ATY128_BACKLIGHT */
+
+/*
+ *  Initialisation
+ */
+
+#ifdef CONFIG_PPC_PMAC__disabled
+static void aty128_early_resume(void *data)
+{
+        struct aty128fb_par *par = data;
+
+	if (!console_trylock())
+		return;
+	pci_restore_state(par->pdev);
+	aty128_do_resume(par->pdev);
+	console_unlock();
+}
+#endif /* CONFIG_PPC_PMAC */
+
+static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct aty128fb_par *par = info->par;
+	struct fb_var_screeninfo var;
+	char video_card[50];
+	u8 chip_rev;
+	u32 dac;
+
+	/* Get the chip revision */
+	chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F;
+
+	strcpy(video_card, "Rage128 XX ");
+	video_card[8] = ent->device >> 8;
+	video_card[9] = ent->device & 0xFF;
+
+	/* range check to make sure */
+	if (ent->driver_data < ARRAY_SIZE(r128_family))
+		strlcat(video_card, r128_family[ent->driver_data],
+			sizeof(video_card));
+
+	printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
+
+	if (par->vram_size % (1024 * 1024) == 0)
+		printk("%dM %s\n", par->vram_size / (1024*1024), par->mem->name);
+	else
+		printk("%dk %s\n", par->vram_size / 1024, par->mem->name);
+
+	par->chip_gen = ent->driver_data;
+
+	/* fill in info */
+	info->fbops = &aty128fb_ops;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	par->lcd_on = default_lcd_on;
+	par->crt_on = default_crt_on;
+
+	var = default_var;
+#ifdef CONFIG_PPC_PMAC
+	if (machine_is(powermac)) {
+		/* Indicate sleep capability */
+		if (par->chip_gen == rage_M3) {
+			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
+#if 0 /* Disable the early video resume hack for now as it's causing problems,
+       * among others we now rely on the PCI core restoring the config space
+       * for us, which isn't the case with that hack, and that code path causes
+       * various things to be called with interrupts off while they shouldn't.
+       * I'm leaving the code in as it can be useful for debugging purposes
+       */
+			pmac_set_early_video_resume(aty128_early_resume, par);
+#endif
+		}
+
+		/* Find default mode */
+		if (mode_option) {
+			if (!mac_find_mode(&var, info, mode_option, 8))
+				var = default_var;
+		} else {
+			if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+				default_vmode = VMODE_1024_768_60;
+
+			/* iMacs need that resolution
+			 * PowerMac2,1 first r128 iMacs
+			 * PowerMac2,2 summer 2000 iMacs
+			 * PowerMac4,1 january 2001 iMacs "flower power"
+			 */
+			if (of_machine_is_compatible("PowerMac2,1") ||
+			    of_machine_is_compatible("PowerMac2,2") ||
+			    of_machine_is_compatible("PowerMac4,1"))
+				default_vmode = VMODE_1024_768_75;
+
+			/* iBook SE */
+			if (of_machine_is_compatible("PowerBook2,2"))
+				default_vmode = VMODE_800_600_60;
+
+			/* PowerBook Firewire (Pismo), iBook Dual USB */
+			if (of_machine_is_compatible("PowerBook3,1") ||
+			    of_machine_is_compatible("PowerBook4,1"))
+				default_vmode = VMODE_1024_768_60;
+
+			/* PowerBook Titanium */
+			if (of_machine_is_compatible("PowerBook3,2"))
+				default_vmode = VMODE_1152_768_60;
+	
+			if (default_cmode > 16) 
+				default_cmode = CMODE_32;
+			else if (default_cmode > 8) 
+				default_cmode = CMODE_16;
+			else 
+				default_cmode = CMODE_8;
+
+			if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+				var = default_var;
+		}
+	} else
+#endif /* CONFIG_PPC_PMAC */
+	{
+		if (mode_option)
+			if (fb_find_mode(&var, info, mode_option, NULL, 
+					 0, &defaultmode, 8) == 0)
+				var = default_var;
+	}
+
+	var.accel_flags &= ~FB_ACCELF_TEXT;
+//	var.accel_flags |= FB_ACCELF_TEXT;/* FIXME Will add accel later */
+
+	if (aty128fb_check_var(&var, info)) {
+		printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
+		return 0;
+	}
+
+	/* setup the DAC the way we like it */
+	dac = aty_ld_le32(DAC_CNTL);
+	dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
+	dac |= DAC_MASK;
+	if (par->chip_gen == rage_M3)
+		dac |= DAC_PALETTE2_SNOOP_EN;
+	aty_st_le32(DAC_CNTL, dac);
+
+	/* turn off bus mastering, just in case */
+	aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
+
+	info->var = var;
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	var.activate = FB_ACTIVATE_NOW;
+
+	aty128_init_engine(par);
+
+	par->pdev = pdev;
+	par->asleep = 0;
+	par->lock_blank = 0;
+
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	if (backlight)
+		aty128_bl_init(par);
+#endif
+
+	if (register_framebuffer(info) < 0)
+		return 0;
+
+	fb_info(info, "%s frame buffer device on %s\n",
+		info->fix.id, video_card);
+
+	return 1;	/* success! */
+}
+
+#ifdef CONFIG_PCI
+/* register a card    ++ajoshi */
+static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	unsigned long fb_addr, reg_addr;
+	struct aty128fb_par *par;
+	struct fb_info *info;
+	int err;
+#ifndef __sparc__
+	void __iomem *bios = NULL;
+#endif
+
+	/* Enable device in PCI config */
+	if ((err = pci_enable_device(pdev))) {
+		printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n",
+				err);
+		return -ENODEV;
+	}
+
+	fb_addr = pci_resource_start(pdev, 0);
+	if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
+				"aty128fb FB")) {
+		printk(KERN_ERR "aty128fb: cannot reserve frame "
+				"buffer memory\n");
+		return -ENODEV;
+	}
+
+	reg_addr = pci_resource_start(pdev, 2);
+	if (!request_mem_region(reg_addr, pci_resource_len(pdev, 2),
+				"aty128fb MMIO")) {
+		printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n");
+		goto err_free_fb;
+	}
+
+	/* We have the resources. Now virtualize them */
+	info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev);
+	if (info == NULL) {
+		printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
+		goto err_free_mmio;
+	}
+	par = info->par;
+
+	info->pseudo_palette = par->pseudo_palette;
+
+	/* Virtualize mmio region */
+	info->fix.mmio_start = reg_addr;
+	par->regbase = pci_ioremap_bar(pdev, 2);
+	if (!par->regbase)
+		goto err_free_info;
+
+	/* Grab memory size from the card */
+	// How does this relate to the resource length from the PCI hardware?
+	par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF;
+
+	/* Virtualize the framebuffer */
+	info->screen_base = ioremap(fb_addr, par->vram_size);
+	if (!info->screen_base)
+		goto err_unmap_out;
+
+	/* Set up info->fix */
+	info->fix = aty128fb_fix;
+	info->fix.smem_start = fb_addr;
+	info->fix.smem_len = par->vram_size;
+	info->fix.mmio_start = reg_addr;
+
+	/* If we can't test scratch registers, something is seriously wrong */
+	if (!register_test(par)) {
+		printk(KERN_ERR "aty128fb: Can't write to video register!\n");
+		goto err_out;
+	}
+
+#ifndef __sparc__
+	bios = aty128_map_ROM(par, pdev);
+#ifdef CONFIG_X86
+	if (bios == NULL)
+		bios = aty128_find_mem_vbios(par);
+#endif
+	if (bios == NULL)
+		printk(KERN_INFO "aty128fb: BIOS not located, guessing timings.\n");
+	else {
+		printk(KERN_INFO "aty128fb: Rage128 BIOS located\n");
+		aty128_get_pllinfo(par, bios);
+		pci_unmap_rom(pdev, bios);
+	}
+#endif /* __sparc__ */
+
+	aty128_timings(par);
+	pci_set_drvdata(pdev, info);
+
+	if (!aty128_init(pdev, ent))
+		goto err_out;
+
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		par->mtrr.vram = mtrr_add(info->fix.smem_start,
+				par->vram_size, MTRR_TYPE_WRCOMB, 1);
+		par->mtrr.vram_valid = 1;
+		/* let there be speed */
+		printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
+	}
+#endif /* CONFIG_MTRR */
+	return 0;
+
+err_out:
+	iounmap(info->screen_base);
+err_unmap_out:
+	iounmap(par->regbase);
+err_free_info:
+	framebuffer_release(info);
+err_free_mmio:
+	release_mem_region(pci_resource_start(pdev, 2),
+			pci_resource_len(pdev, 2));
+err_free_fb:
+	release_mem_region(pci_resource_start(pdev, 0),
+			pci_resource_len(pdev, 0));
+	return -ENODEV;
+}
+
+static void aty128_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct aty128fb_par *par;
+
+	if (!info)
+		return;
+
+	par = info->par;
+
+	unregister_framebuffer(info);
+
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	aty128_bl_exit(info->bl_dev);
+#endif
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr.vram_valid)
+		mtrr_del(par->mtrr.vram, info->fix.smem_start,
+			 par->vram_size);
+#endif /* CONFIG_MTRR */
+	iounmap(par->regbase);
+	iounmap(info->screen_base);
+
+	release_mem_region(pci_resource_start(pdev, 0),
+			   pci_resource_len(pdev, 0));
+	release_mem_region(pci_resource_start(pdev, 2),
+			   pci_resource_len(pdev, 2));
+	framebuffer_release(info);
+}
+#endif /* CONFIG_PCI */
+
+
+
+    /*
+     *  Blank the display.
+     */
+static int aty128fb_blank(int blank, struct fb_info *fb)
+{
+	struct aty128fb_par *par = fb->par;
+	u8 state;
+
+	if (par->lock_blank || par->asleep)
+		return 0;
+
+	switch (blank) {
+	case FB_BLANK_NORMAL:
+		state = 4;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		state = 6;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		state = 5;
+		break;
+	case FB_BLANK_POWERDOWN:
+		state = 7;
+		break;
+	case FB_BLANK_UNBLANK:
+	default:
+		state = 0;
+		break;
+	}
+	aty_st_8(CRTC_EXT_CNTL+1, state);
+
+	if (par->chip_gen == rage_M3) {
+		aty128_set_crt_enable(par, par->crt_on && !blank);
+		aty128_set_lcd_enable(par, par->lcd_on && !blank);
+	}
+
+	return 0;
+}
+
+/*
+ *  Set a single color register. The values supplied are already
+ *  rounded down to the hardware's capabilities (according to the
+ *  entries in the var structure). Return != 0 for invalid regno.
+ */
+static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			      u_int transp, struct fb_info *info)
+{
+	struct aty128fb_par *par = info->par;
+
+	if (regno > 255
+	    || (par->crtc.depth == 16 && regno > 63)
+	    || (par->crtc.depth == 15 && regno > 31))
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	if (regno < 16) {
+		int i;
+		u32 *pal = info->pseudo_palette;
+
+		switch (par->crtc.depth) {
+		case 15:
+			pal[regno] = (regno << 10) | (regno << 5) | regno;
+			break;
+		case 16:
+			pal[regno] = (regno << 11) | (regno << 6) | regno;
+			break;
+		case 24:
+			pal[regno] = (regno << 16) | (regno << 8) | regno;
+			break;
+		case 32:
+			i = (regno << 8) | regno;
+			pal[regno] = (i << 16) | i;
+			break;
+		}
+	}
+
+	if (par->crtc.depth == 16 && regno > 0) {
+		/*
+		 * With the 5-6-5 split of bits for RGB at 16 bits/pixel, we
+		 * have 32 slots for R and B values but 64 slots for G values.
+		 * Thus the R and B values go in one slot but the G value
+		 * goes in a different slot, and we have to avoid disturbing
+		 * the other fields in the slots we touch.
+		 */
+		par->green[regno] = green;
+		if (regno < 32) {
+			par->red[regno] = red;
+			par->blue[regno] = blue;
+			aty128_st_pal(regno * 8, red, par->green[regno*2],
+				      blue, par);
+		}
+		red = par->red[regno/2];
+		blue = par->blue[regno/2];
+		regno <<= 2;
+	} else if (par->crtc.bpp == 16)
+		regno <<= 3;
+	aty128_st_pal(regno, red, green, blue, par);
+
+	return 0;
+}
+
+#define ATY_MIRROR_LCD_ON	0x00000001
+#define ATY_MIRROR_CRT_ON	0x00000002
+
+/* out param: u32*	backlight value: 0 to 15 */
+#define FBIO_ATY128_GET_MIRROR	_IOR('@', 1, __u32)
+/* in param: u32*	backlight value: 0 to 15 */
+#define FBIO_ATY128_SET_MIRROR	_IOW('@', 2, __u32)
+
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+{
+	struct aty128fb_par *par = info->par;
+	u32 value;
+	int rc;
+    
+	switch (cmd) {
+	case FBIO_ATY128_SET_MIRROR:
+		if (par->chip_gen != rage_M3)
+			return -EINVAL;
+		rc = get_user(value, (__u32 __user *)arg);
+		if (rc)
+			return rc;
+		par->lcd_on = (value & 0x01) != 0;
+		par->crt_on = (value & 0x02) != 0;
+		if (!par->crt_on && !par->lcd_on)
+			par->lcd_on = 1;
+		aty128_set_crt_enable(par, par->crt_on);	
+		aty128_set_lcd_enable(par, par->lcd_on);	
+		return 0;
+	case FBIO_ATY128_GET_MIRROR:
+		if (par->chip_gen != rage_M3)
+			return -EINVAL;
+		value = (par->crt_on << 1) | par->lcd_on;
+		return put_user(value, (__u32 __user *)arg);
+	}
+	return -EINVAL;
+}
+
+#if 0
+    /*
+     *  Accelerated functions
+     */
+
+static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
+				   u_int width, u_int height,
+				   struct fb_info_aty128 *par)
+{
+	u32 save_dp_datatype, save_dp_cntl, dstval;
+
+	if (!width || !height)
+		return;
+
+	dstval = depth_to_dst(par->current_par.crtc.depth);
+	if (dstval == DST_24BPP) {
+		srcx *= 3;
+		dstx *= 3;
+		width *= 3;
+	} else if (dstval == -EINVAL) {
+		printk("aty128fb: invalid depth or RGBA\n");
+		return;
+	}
+
+	wait_for_fifo(2, par);
+	save_dp_datatype = aty_ld_le32(DP_DATATYPE);
+	save_dp_cntl     = aty_ld_le32(DP_CNTL);
+
+	wait_for_fifo(6, par);
+	aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
+	aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
+	aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+	aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR);
+
+	aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
+	aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
+
+	par->blitter_may_be_busy = 1;
+
+	wait_for_fifo(2, par);
+	aty_st_le32(DP_DATATYPE, save_dp_datatype);
+	aty_st_le32(DP_CNTL, save_dp_cntl);
+}
+
+
+    /*
+     * Text mode accelerated functions
+     */
+
+static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy,
+			       int dx, int height, int width)
+{
+	sx     *= fontwidth(p);
+	sy     *= fontheight(p);
+	dx     *= fontwidth(p);
+	dy     *= fontheight(p);
+	width  *= fontwidth(p);
+	height *= fontheight(p);
+
+	aty128_rectcopy(sx, sy, dx, dy, width, height,
+			(struct fb_info_aty128 *)p->fb_info);
+}
+#endif /* 0 */
+
+static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
+{
+	u32	pmgt;
+	struct pci_dev *pdev = par->pdev;
+
+	if (!par->pdev->pm_cap)
+		return;
+		
+	/* Set the chip into the appropriate suspend mode (we use D2,
+	 * D3 would require a complete re-initialisation of the chip,
+	 * including PCI config registers, clocks, AGP configuration, ...)
+	 *
+	 * For resume, the core will have already brought us back to D0
+	 */
+	if (suspend) {
+		/* Make sure CRTC2 is reset. Remove that the day we decide to
+		 * actually use CRTC2 and replace it with real code for disabling
+		 * the CRTC2 output during sleep
+		 */
+		aty_st_le32(CRTC2_GEN_CNTL, aty_ld_le32(CRTC2_GEN_CNTL) &
+			~(CRTC2_EN));
+
+		/* Set the power management mode to be PCI based */
+		/* Use this magic value for now */
+		pmgt = 0x0c005407;
+		aty_st_pll(POWER_MANAGEMENT, pmgt);
+		(void)aty_ld_pll(POWER_MANAGEMENT);
+		aty_st_le32(BUS_CNTL1, 0x00000010);
+		aty_st_le32(MEM_POWER_MISC, 0x0c830000);
+		mdelay(100);
+
+		/* Switch PCI power management to D2 */
+		pci_set_power_state(pdev, PCI_D2);
+	}
+}
+
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct aty128fb_par *par = info->par;
+
+	/* Because we may change PCI D state ourselves, we need to
+	 * first save the config space content so the core can
+	 * restore it properly on resume.
+	 */
+	pci_save_state(pdev);
+
+	/* We don't do anything but D2, for now we return 0, but
+	 * we may want to change that. How do we know if the BIOS
+	 * can properly take care of D3 ? Also, with swsusp, we
+	 * know we'll be rebooted, ...
+	 */
+#ifndef CONFIG_PPC_PMAC
+	/* HACK ALERT ! Once I find a proper way to say to each driver
+	 * individually what will happen with it's PCI slot, I'll change
+	 * that. On laptops, the AGP slot is just unclocked, so D2 is
+	 * expected, while on desktops, the card is powered off
+	 */
+	return 0;
+#endif /* CONFIG_PPC_PMAC */
+	 
+	if (state.event == pdev->dev.power.power_state.event)
+		return 0;
+
+	printk(KERN_DEBUG "aty128fb: suspending...\n");
+	
+	console_lock();
+
+	fb_set_suspend(info, 1);
+
+	/* Make sure engine is reset */
+	wait_for_idle(par);
+	aty128_reset_engine(par);
+	wait_for_idle(par);
+
+	/* Blank display and LCD */
+	aty128fb_blank(FB_BLANK_POWERDOWN, info);
+
+	/* Sleep */
+	par->asleep = 1;
+	par->lock_blank = 1;
+
+#ifdef CONFIG_PPC_PMAC
+	/* On powermac, we have hooks to properly suspend/resume AGP now,
+	 * use them here. We'll ultimately need some generic support here,
+	 * but the generic code isn't quite ready for that yet
+	 */
+	pmac_suspend_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
+
+	/* We need a way to make sure the fbdev layer will _not_ touch the
+	 * framebuffer before we put the chip to suspend state. On 2.4, I
+	 * used dummy fb ops, 2.5 need proper support for this at the
+	 * fbdev level
+	 */
+	if (state.event != PM_EVENT_ON)
+		aty128_set_suspend(par, 1);
+
+	console_unlock();
+
+	pdev->dev.power.power_state = state;
+
+	return 0;
+}
+
+static int aty128_do_resume(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct aty128fb_par *par = info->par;
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
+		return 0;
+
+	/* PCI state will have been restored by the core, so
+	 * we should be in D0 now with our config space fully
+	 * restored
+	 */
+
+	/* Wakeup chip */
+	aty128_set_suspend(par, 0);
+	par->asleep = 0;
+
+	/* Restore display & engine */
+	aty128_reset_engine(par);
+	wait_for_idle(par);
+	aty128fb_set_par(info);
+	fb_pan_display(info, &info->var);
+	fb_set_cmap(&info->cmap, info);
+
+	/* Refresh */
+	fb_set_suspend(info, 0);
+
+	/* Unblank */
+	par->lock_blank = 0;
+	aty128fb_blank(0, info);
+
+#ifdef CONFIG_PPC_PMAC
+	/* On powermac, we have hooks to properly suspend/resume AGP now,
+	 * use them here. We'll ultimately need some generic support here,
+	 * but the generic code isn't quite ready for that yet
+	 */
+	pmac_resume_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
+
+	pdev->dev.power.power_state = PMSG_ON;
+
+	printk(KERN_DEBUG "aty128fb: resumed !\n");
+
+	return 0;
+}
+
+static int aty128_pci_resume(struct pci_dev *pdev)
+{
+	int rc;
+
+	console_lock();
+	rc = aty128_do_resume(pdev);
+	console_unlock();
+
+	return rc;
+}
+
+
+static int aty128fb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("aty128fb", &option))
+		return -ENODEV;
+	aty128fb_setup(option);
+#endif
+
+	return pci_register_driver(&aty128fb_driver);
+}
+
+static void __exit aty128fb_exit(void)
+{
+	pci_unregister_driver(&aty128fb_driver);
+}
+
+module_init(aty128fb_init);
+
+module_exit(aty128fb_exit);
+
+MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
+MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
+MODULE_LICENSE("GPL");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+#ifdef CONFIG_MTRR
+module_param_named(nomtrr, mtrr, invbool, 0);
+MODULE_PARM_DESC(nomtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");
+#endif
+
diff --git a/drivers/video/fbdev/aty/atyfb.h b/drivers/video/fbdev/aty/atyfb.h
new file mode 100644
index 000000000000..1f39a62f899b
--- /dev/null
+++ b/drivers/video/fbdev/aty/atyfb.h
@@ -0,0 +1,369 @@
+/*
+ *  ATI Frame Buffer Device Driver Core Definitions
+ */
+
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+    /*
+     *  Elements of the hardware specific atyfb_par structure
+     */
+
+struct crtc {
+	u32 vxres;
+	u32 vyres;
+	u32 xoffset;
+	u32 yoffset;
+	u32 bpp;
+	u32 h_tot_disp;
+	u32 h_sync_strt_wid;
+	u32 v_tot_disp;
+	u32 v_sync_strt_wid;
+	u32 vline_crnt_vline;
+	u32 off_pitch;
+	u32 gen_cntl;
+	u32 dp_pix_width;	/* acceleration */
+	u32 dp_chain_mask;	/* acceleration */
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	u32 horz_stretching;
+	u32 vert_stretching;
+	u32 ext_vert_stretch;
+	u32 shadow_h_tot_disp;
+	u32 shadow_h_sync_strt_wid;
+	u32 shadow_v_tot_disp;
+	u32 shadow_v_sync_strt_wid;
+	u32 lcd_gen_cntl;
+	u32 lcd_config_panel;
+	u32 lcd_index;
+#endif
+};
+
+struct aty_interrupt {
+	wait_queue_head_t wait;
+	unsigned int count;
+	int pan_display;
+};
+
+struct pll_info {
+	int pll_max;
+	int pll_min;
+	int sclk, mclk, mclk_pm, xclk;
+	int ref_div;
+	int ref_clk;
+	int ecp_max;
+};
+
+typedef struct {
+	u16 unknown1;
+	u16 PCLK_min_freq;
+	u16 PCLK_max_freq;
+	u16 unknown2;
+	u16 ref_freq;
+	u16 ref_divider;
+	u16 unknown3;
+	u16 MCLK_pwd;
+	u16 MCLK_max_freq;
+	u16 XCLK_max_freq;
+	u16 SCLK_freq;
+} __attribute__ ((packed)) PLL_BLOCK_MACH64;
+
+struct pll_514 {
+	u8 m;
+	u8 n;
+};
+
+struct pll_18818 {
+	u32 program_bits;
+	u32 locationAddr;
+	u32 period_in_ps;
+	u32 post_divider;
+};
+
+struct pll_ct {
+	u8 pll_ref_div;
+	u8 pll_gen_cntl;
+	u8 mclk_fb_div;
+	u8 mclk_fb_mult; /* 2 ro 4 */
+	u8 sclk_fb_div;
+	u8 pll_vclk_cntl;
+	u8 vclk_post_div;
+	u8 vclk_fb_div;
+	u8 pll_ext_cntl;
+	u8 ext_vpll_cntl;
+	u8 spll_cntl2;
+	u32 dsp_config; /* Mach64 GTB DSP */
+	u32 dsp_on_off; /* Mach64 GTB DSP */
+	u32 dsp_loop_latency;
+	u32 fifo_size;
+	u32 xclkpagefaultdelay;
+	u32 xclkmaxrasdelay;
+	u8 xclk_ref_div;
+	u8 xclk_post_div;
+	u8 mclk_post_div_real;
+	u8 xclk_post_div_real;
+	u8 vclk_post_div_real;
+	u8 features;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	u32 xres; /* use for LCD stretching/scaling */
+#endif
+};
+
+/*
+	for pll_ct.features
+*/
+#define DONT_USE_SPLL 0x1
+#define DONT_USE_XDLL 0x2
+#define USE_CPUCLK    0x4
+#define POWERDOWN_PLL 0x8
+
+union aty_pll {
+	struct pll_ct ct;
+	struct pll_514 ibm514;
+	struct pll_18818 ics2595;
+};
+
+    /*
+     *  The hardware parameters for each card
+     */
+
+struct atyfb_par {
+	u32 pseudo_palette[16];
+	struct { u8 red, green, blue; } palette[256];
+	const struct aty_dac_ops *dac_ops;
+	const struct aty_pll_ops *pll_ops;
+	void __iomem *ati_regbase;
+	unsigned long clk_wr_offset; /* meaning overloaded, clock id by CT */
+	struct crtc crtc;
+	union aty_pll pll;
+	struct pll_info pll_limits;
+	u32 features;
+	u32 ref_clk_per;
+	u32 pll_per;
+	u32 mclk_per;
+	u32 xclk_per;
+	u8 bus_type;
+	u8 ram_type;
+	u8 mem_refresh_rate;
+	u16 pci_id;
+	u32 accel_flags;
+	int blitter_may_be_busy;
+	int asleep;
+	int lock_blank;
+	unsigned long res_start;
+	unsigned long res_size;
+	struct pci_dev *pdev;
+#ifdef __sparc__
+	struct pci_mmap_map *mmap_map;
+	u8 mmaped;
+#endif
+	int open;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	unsigned long bios_base_phys;
+	unsigned long bios_base;
+	unsigned long lcd_table;
+	u16 lcd_width;
+	u16 lcd_height;
+	u32 lcd_pixclock;
+	u16 lcd_refreshrate;
+	u16 lcd_htotal;
+	u16 lcd_hdisp;
+	u16 lcd_hsync_dly;
+	u16 lcd_hsync_len;
+	u16 lcd_vtotal;
+	u16 lcd_vdisp;
+	u16 lcd_vsync_len;
+	u16 lcd_right_margin;
+	u16 lcd_lower_margin;
+	u16 lcd_hblank_len;
+	u16 lcd_vblank_len;
+#endif
+	unsigned long aux_start; /* auxiliary aperture */
+	unsigned long aux_size;
+	struct aty_interrupt vblank;
+	unsigned long irq_flags;
+	unsigned int irq;
+	spinlock_t int_lock;
+#ifdef CONFIG_MTRR
+	int mtrr_aper;
+	int mtrr_reg;
+#endif
+	u32 mem_cntl;
+	struct crtc saved_crtc;
+	union aty_pll saved_pll;
+};
+
+    /*
+     *  ATI Mach64 features
+     */
+
+#define M64_HAS(feature)	((par)->features & (M64F_##feature))
+
+#define M64F_RESET_3D		0x00000001
+#define M64F_MAGIC_FIFO		0x00000002
+#define M64F_GTB_DSP		0x00000004
+#define M64F_FIFO_32		0x00000008
+#define M64F_SDRAM_MAGIC_PLL	0x00000010
+#define M64F_MAGIC_POSTDIV	0x00000020
+#define M64F_INTEGRATED		0x00000040
+#define M64F_CT_BUS		0x00000080
+#define M64F_VT_BUS		0x00000100
+#define M64F_MOBIL_BUS		0x00000200
+#define M64F_GX			0x00000400
+#define M64F_CT			0x00000800
+#define M64F_VT			0x00001000
+#define M64F_GT			0x00002000
+#define M64F_MAGIC_VRAM_SIZE	0x00004000
+#define M64F_G3_PB_1_1		0x00008000
+#define M64F_G3_PB_1024x768	0x00010000
+#define M64F_EXTRA_BRIGHT	0x00020000
+#define M64F_LT_LCD_REGS	0x00040000
+#define M64F_XL_DLL		0x00080000
+#define M64F_MFB_FORCE_4	0x00100000
+#define M64F_HW_TRIPLE		0x00200000
+#define M64F_XL_MEM		0x00400000
+    /*
+     *  Register access
+     */
+
+static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par)
+{
+	/* Hack for bloc 1, should be cleanly optimized by compiler */
+	if (regindex >= 0x400)
+		regindex -= 0x800;
+
+#ifdef CONFIG_ATARI
+	return in_le32(par->ati_regbase + regindex);
+#else
+	return readl(par->ati_regbase + regindex);
+#endif
+}
+
+static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *par)
+{
+	/* Hack for bloc 1, should be cleanly optimized by compiler */
+	if (regindex >= 0x400)
+		regindex -= 0x800;
+
+#ifdef CONFIG_ATARI
+	out_le32(par->ati_regbase + regindex, val);
+#else
+	writel(val, par->ati_regbase + regindex);
+#endif
+}
+
+static inline void aty_st_le16(int regindex, u16 val,
+			       const struct atyfb_par *par)
+{
+	/* Hack for bloc 1, should be cleanly optimized by compiler */
+	if (regindex >= 0x400)
+		regindex -= 0x800;
+#ifdef CONFIG_ATARI
+	out_le16(par->ati_regbase + regindex, val);
+#else
+	writel(val, par->ati_regbase + regindex);
+#endif
+}
+
+static inline u8 aty_ld_8(int regindex, const struct atyfb_par *par)
+{
+	/* Hack for bloc 1, should be cleanly optimized by compiler */
+	if (regindex >= 0x400)
+		regindex -= 0x800;
+#ifdef CONFIG_ATARI
+	return in_8(par->ati_regbase + regindex);
+#else
+	return readb(par->ati_regbase + regindex);
+#endif
+}
+
+static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par)
+{
+	/* Hack for bloc 1, should be cleanly optimized by compiler */
+	if (regindex >= 0x400)
+		regindex -= 0x800;
+
+#ifdef CONFIG_ATARI
+	out_8(par->ati_regbase + regindex, val);
+#else
+	writeb(val, par->ati_regbase + regindex);
+#endif
+}
+
+#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
+defined (CONFIG_FB_ATY_GENERIC_LCD) || defined (CONFIG_FB_ATY_BACKLIGHT)
+extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par);
+extern u32 aty_ld_lcd(int index, const struct atyfb_par *par);
+#endif
+
+    /*
+     *  DAC operations
+     */
+
+struct aty_dac_ops {
+	int (*set_dac) (const struct fb_info * info,
+		const union aty_pll * pll, u32 bpp, u32 accel);
+};
+
+extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */
+extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */
+extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */
+extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */
+extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
+
+
+    /*
+     *  Clock operations
+     */
+
+struct aty_pll_ops {
+	int (*var_to_pll) (const struct fb_info * info, u32 vclk_per, u32 bpp, union aty_pll * pll);
+	u32 (*pll_to_var) (const struct fb_info * info, const union aty_pll * pll);
+	void (*set_pll)   (const struct fb_info * info, const union aty_pll * pll);
+	void (*get_pll)   (const struct fb_info *info, union aty_pll * pll);
+	int (*init_pll)   (const struct fb_info * info, union aty_pll * pll);
+	void (*resume_pll)(const struct fb_info *info, union aty_pll *pll);
+};
+
+extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
+extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */
+extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */
+extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */
+extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */
+extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */
+extern const struct aty_pll_ops aty_pll_ct; /* Integrated */
+
+
+extern void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll);
+extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
+
+
+    /*
+     *  Hardware cursor support
+     */
+
+extern int aty_init_cursor(struct fb_info *info);
+
+    /*
+     *  Hardware acceleration
+     */
+
+static inline void wait_for_fifo(u16 entries, const struct atyfb_par *par)
+{
+	while ((aty_ld_le32(FIFO_STAT, par) & 0xffff) >
+	       ((u32) (0x8000 >> entries)));
+}
+
+static inline void wait_for_idle(struct atyfb_par *par)
+{
+	wait_for_fifo(16, par);
+	while ((aty_ld_le32(GUI_STAT, par) & 1) != 0);
+	par->blitter_may_be_busy = 0;
+}
+
+extern void aty_reset_engine(const struct atyfb_par *par);
+extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
+extern u8   aty_ld_pll_ct(int offset, const struct atyfb_par *par);
+
+void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
+
diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c
new file mode 100644
index 000000000000..c3d0074a32db
--- /dev/null
+++ b/drivers/video/fbdev/aty/atyfb_base.c
@@ -0,0 +1,4029 @@
+/*
+ *  ATI Frame Buffer Device Driver Core
+ *
+ *	Copyright (C) 2004  Alex Kern <alex.kern@gmx.de>
+ *	Copyright (C) 1997-2001  Geert Uytterhoeven
+ *	Copyright (C) 1998  Bernd Harries
+ *	Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ *
+ *  This driver supports the following ATI graphics chips:
+ *    - ATI Mach64
+ *
+ *  To do: add support for
+ *    - ATI Rage128 (from aty128fb.c)
+ *    - ATI Radeon (from radeonfb.c)
+ *
+ *  This driver is partly based on the PowerMac console driver:
+ *
+ *	Copyright (C) 1996 Paul Mackerras
+ *
+ *  and on the PowerMac ATI/mach64 display driver:
+ *
+ *	Copyright (C) 1997 Michael AK Tesch
+ *
+ *	      with work by Jon Howell
+ *			   Harry AC Eaton
+ *			   Anthony Tong <atong@uiuc.edu>
+ *
+ *  Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
+ *  Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *  Many thanks to Nitya from ATI devrel for support and patience !
+ */
+
+/******************************************************************************
+
+  TODO:
+
+    - cursor support on all cards and all ramdacs.
+    - cursor parameters controlable via ioctl()s.
+    - guess PLL and MCLK based on the original PLL register values initialized
+      by Open Firmware (if they are initialized). BIOS is done
+
+    (Anyone with Mac to help with this?)
+
+******************************************************************************/
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/compiler.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/backlight.h>
+#include <linux/reboot.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <linux/uaccess.h>
+
+#include <video/mach64.h>
+#include "atyfb.h"
+#include "ati_ids.h"
+
+#ifdef __powerpc__
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include "../macmodes.h"
+#endif
+#ifdef __sparc__
+#include <asm/fbio.h>
+#include <asm/oplib.h>
+#include <asm/prom.h>
+#endif
+
+#ifdef CONFIG_ADB_PMU
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#endif
+#ifdef CONFIG_BOOTX_TEXT
+#include <asm/btext.h>
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+/*
+ * Debug flags.
+ */
+#undef DEBUG
+/*#define DEBUG*/
+
+/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
+/*  - must be large enough to catch all GUI-Regs   */
+/*  - must be aligned to a PAGE boundary           */
+#define GUI_RESERVE	(1 * PAGE_SIZE)
+
+/* FIXME: remove the FAIL definition */
+#define FAIL(msg) do { \
+	if (!(var->activate & FB_ACTIVATE_TEST)) \
+		printk(KERN_CRIT "atyfb: " msg "\n"); \
+	return -EINVAL; \
+} while (0)
+#define FAIL_MAX(msg, x, _max_) do { \
+	if (x > _max_) { \
+		if (!(var->activate & FB_ACTIVATE_TEST)) \
+			printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
+		return -EINVAL; \
+	} \
+} while (0)
+#ifdef DEBUG
+#define DPRINTK(fmt, args...)	printk(KERN_DEBUG "atyfb: " fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define PRINTKI(fmt, args...)	printk(KERN_INFO "atyfb: " fmt, ## args)
+#define PRINTKE(fmt, args...)	printk(KERN_ERR "atyfb: " fmt, ## args)
+
+#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
+defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
+static const u32 lt_lcd_regs[] = {
+	CNFG_PANEL_LG,
+	LCD_GEN_CNTL_LG,
+	DSTN_CONTROL_LG,
+	HFB_PITCH_ADDR_LG,
+	HORZ_STRETCHING_LG,
+	VERT_STRETCHING_LG,
+	0, /* EXT_VERT_STRETCH */
+	LT_GIO_LG,
+	POWER_MANAGEMENT_LG
+};
+
+void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
+{
+	if (M64_HAS(LT_LCD_REGS)) {
+		aty_st_le32(lt_lcd_regs[index], val, par);
+	} else {
+		unsigned long temp;
+
+		/* write addr byte */
+		temp = aty_ld_le32(LCD_INDEX, par);
+		aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
+		/* write the register value */
+		aty_st_le32(LCD_DATA, val, par);
+	}
+}
+
+u32 aty_ld_lcd(int index, const struct atyfb_par *par)
+{
+	if (M64_HAS(LT_LCD_REGS)) {
+		return aty_ld_le32(lt_lcd_regs[index], par);
+	} else {
+		unsigned long temp;
+
+		/* write addr byte */
+		temp = aty_ld_le32(LCD_INDEX, par);
+		aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
+		/* read the register value */
+		return aty_ld_le32(LCD_DATA, par);
+	}
+}
+#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+/*
+ * ATIReduceRatio --
+ *
+ * Reduce a fraction by factoring out the largest common divider of the
+ * fraction's numerator and denominator.
+ */
+static void ATIReduceRatio(int *Numerator, int *Denominator)
+{
+	int Multiplier, Divider, Remainder;
+
+	Multiplier = *Numerator;
+	Divider = *Denominator;
+
+	while ((Remainder = Multiplier % Divider)) {
+		Multiplier = Divider;
+		Divider = Remainder;
+	}
+
+	*Numerator /= Divider;
+	*Denominator /= Divider;
+}
+#endif
+/*
+ * The Hardware parameters for each card
+ */
+
+struct pci_mmap_map {
+	unsigned long voff;
+	unsigned long poff;
+	unsigned long size;
+	unsigned long prot_flag;
+	unsigned long prot_mask;
+};
+
+static struct fb_fix_screeninfo atyfb_fix = {
+	.id		= "ATY Mach64",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep	= 8,
+	.ypanstep	= 1,
+};
+
+/*
+ * Frame buffer device API
+ */
+
+static int atyfb_open(struct fb_info *info, int user);
+static int atyfb_release(struct fb_info *info, int user);
+static int atyfb_check_var(struct fb_var_screeninfo *var,
+			   struct fb_info *info);
+static int atyfb_set_par(struct fb_info *info);
+static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info);
+static int atyfb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static int atyfb_blank(int blank, struct fb_info *info);
+static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
+#ifdef __sparc__
+static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
+#endif
+static int atyfb_sync(struct fb_info *info);
+
+/*
+ * Internal routines
+ */
+
+static int aty_init(struct fb_info *info);
+
+static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
+
+static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
+static int aty_var_to_crtc(const struct fb_info *info,
+			   const struct fb_var_screeninfo *var,
+			   struct crtc *crtc);
+static int aty_crtc_to_var(const struct crtc *crtc,
+			   struct fb_var_screeninfo *var);
+static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
+#ifdef CONFIG_PPC
+static int read_aty_sense(const struct atyfb_par *par);
+#endif
+
+static DEFINE_MUTEX(reboot_lock);
+static struct fb_info *reboot_info;
+
+/*
+ * Interface used by the world
+ */
+
+static struct fb_var_screeninfo default_var = {
+	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+	640, 480, 640, 480, 0, 0, 8, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+};
+
+static struct fb_videomode defmode = {
+	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
+	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+};
+
+static struct fb_ops atyfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= atyfb_open,
+	.fb_release	= atyfb_release,
+	.fb_check_var	= atyfb_check_var,
+	.fb_set_par	= atyfb_set_par,
+	.fb_setcolreg	= atyfb_setcolreg,
+	.fb_pan_display	= atyfb_pan_display,
+	.fb_blank	= atyfb_blank,
+	.fb_ioctl	= atyfb_ioctl,
+	.fb_fillrect	= atyfb_fillrect,
+	.fb_copyarea	= atyfb_copyarea,
+	.fb_imageblit	= atyfb_imageblit,
+#ifdef __sparc__
+	.fb_mmap	= atyfb_mmap,
+#endif
+	.fb_sync	= atyfb_sync,
+};
+
+static bool noaccel;
+#ifdef CONFIG_MTRR
+static bool nomtrr;
+#endif
+static int vram;
+static int pll;
+static int mclk;
+static int xclk;
+static int comp_sync = -1;
+static char *mode;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight = 1;
+#else
+static int backlight = 0;
+#endif
+
+#ifdef CONFIG_PPC
+static int default_vmode = VMODE_CHOOSE;
+static int default_cmode = CMODE_CHOOSE;
+
+module_param_named(vmode, default_vmode, int, 0);
+MODULE_PARM_DESC(vmode, "int: video mode for mac");
+module_param_named(cmode, default_cmode, int, 0);
+MODULE_PARM_DESC(cmode, "int: color mode for mac");
+#endif
+
+#ifdef CONFIG_ATARI
+static unsigned int mach64_count = 0;
+static unsigned long phys_vmembase[FB_MAX] = { 0, };
+static unsigned long phys_size[FB_MAX] = { 0, };
+static unsigned long phys_guiregbase[FB_MAX] = { 0, };
+#endif
+
+/* top -> down is an evolution of mach64 chipset, any corrections? */
+#define ATI_CHIP_88800GX   (M64F_GX)
+#define ATI_CHIP_88800CX   (M64F_GX)
+
+#define ATI_CHIP_264CT     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
+#define ATI_CHIP_264ET     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
+
+#define ATI_CHIP_264VT     (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
+#define ATI_CHIP_264GT     (M64F_GT | M64F_INTEGRATED               | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
+
+#define ATI_CHIP_264VTB    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
+#define ATI_CHIP_264VT3    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
+#define ATI_CHIP_264VT4    (M64F_VT | M64F_INTEGRATED               | M64F_GTB_DSP)
+
+/* FIXME what is this chip? */
+#define ATI_CHIP_264LT     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP)
+
+/* make sets shorter */
+#define ATI_MODERN_SET     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
+
+#define ATI_CHIP_264GTB    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
+/*#define ATI_CHIP_264GTDVD  ?*/
+#define ATI_CHIP_264LTG    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
+
+#define ATI_CHIP_264GT2C   (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
+#define ATI_CHIP_264GTPRO  (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
+#define ATI_CHIP_264LTPRO  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
+
+#define ATI_CHIP_264XL     (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM)
+#define ATI_CHIP_MOBILITY  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS)
+
+static struct {
+	u16 pci_id;
+	const char *name;
+	int pll, mclk, xclk, ecp_max;
+	u32 features;
+} aty_chips[] = {
+#ifdef CONFIG_FB_ATY_GX
+	/* Mach64 GX */
+	{ PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
+	{ PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
+#endif /* CONFIG_FB_ATY_GX */
+
+#ifdef CONFIG_FB_ATY_CT
+	{ PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
+	{ PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
+
+	/* FIXME what is this chip? */
+	{ PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
+
+	{ PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
+	{ PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
+
+	{ PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
+	{ PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
+
+	{ PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
+
+	{ PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
+
+	{ PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+
+	{ PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
+	{ PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+
+	{ PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
+	{ PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 },
+	{ PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+
+	{ PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
+	{ PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
+
+	{ PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+#endif /* CONFIG_FB_ATY_CT */
+};
+
+static int correct_chipset(struct atyfb_par *par)
+{
+	u8 rev;
+	u16 type;
+	u32 chip_id;
+	const char *name;
+	int i;
+
+	for (i = (int)ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
+		if (par->pci_id == aty_chips[i].pci_id)
+			break;
+
+	if (i < 0)
+		return -ENODEV;
+
+	name = aty_chips[i].name;
+	par->pll_limits.pll_max = aty_chips[i].pll;
+	par->pll_limits.mclk = aty_chips[i].mclk;
+	par->pll_limits.xclk = aty_chips[i].xclk;
+	par->pll_limits.ecp_max = aty_chips[i].ecp_max;
+	par->features = aty_chips[i].features;
+
+	chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
+	type = chip_id & CFG_CHIP_TYPE;
+	rev = (chip_id & CFG_CHIP_REV) >> 24;
+
+	switch (par->pci_id) {
+#ifdef CONFIG_FB_ATY_GX
+	case PCI_CHIP_MACH64GX:
+		if (type != 0x00d7)
+			return -ENODEV;
+		break;
+	case PCI_CHIP_MACH64CX:
+		if (type != 0x0057)
+			return -ENODEV;
+		break;
+#endif
+#ifdef CONFIG_FB_ATY_CT
+	case PCI_CHIP_MACH64VT:
+		switch (rev & 0x07) {
+		case 0x00:
+			switch (rev & 0xc0) {
+			case 0x00:
+				name = "ATI264VT (A3) (Mach64 VT)";
+				par->pll_limits.pll_max = 170;
+				par->pll_limits.mclk = 67;
+				par->pll_limits.xclk = 67;
+				par->pll_limits.ecp_max = 80;
+				par->features = ATI_CHIP_264VT;
+				break;
+			case 0x40:
+				name = "ATI264VT2 (A4) (Mach64 VT)";
+				par->pll_limits.pll_max = 200;
+				par->pll_limits.mclk = 67;
+				par->pll_limits.xclk = 67;
+				par->pll_limits.ecp_max = 80;
+				par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
+				break;
+			}
+			break;
+		case 0x01:
+			name = "ATI264VT3 (B1) (Mach64 VT)";
+			par->pll_limits.pll_max = 200;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 80;
+			par->features = ATI_CHIP_264VTB;
+			break;
+		case 0x02:
+			name = "ATI264VT3 (B2) (Mach64 VT)";
+			par->pll_limits.pll_max = 200;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 80;
+			par->features = ATI_CHIP_264VT3;
+			break;
+		}
+		break;
+	case PCI_CHIP_MACH64GT:
+		switch (rev & 0x07) {
+		case 0x01:
+			name = "3D RAGE II (Mach64 GT)";
+			par->pll_limits.pll_max = 170;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 80;
+			par->features = ATI_CHIP_264GTB;
+			break;
+		case 0x02:
+			name = "3D RAGE II+ (Mach64 GT)";
+			par->pll_limits.pll_max = 200;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->pll_limits.ecp_max = 100;
+			par->features = ATI_CHIP_264GTB;
+			break;
+		}
+		break;
+#endif
+	}
+
+	PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
+	return 0;
+}
+
+static char ram_dram[] __maybe_unused = "DRAM";
+static char ram_resv[] __maybe_unused = "RESV";
+#ifdef CONFIG_FB_ATY_GX
+static char ram_vram[] = "VRAM";
+#endif /* CONFIG_FB_ATY_GX */
+#ifdef CONFIG_FB_ATY_CT
+static char ram_edo[] = "EDO";
+static char ram_sdram[] = "SDRAM (1:1)";
+static char ram_sgram[] = "SGRAM (1:1)";
+static char ram_sdram32[] = "SDRAM (2:1) (32-bit)";
+static char ram_wram[] = "WRAM";
+static char ram_off[] = "OFF";
+#endif /* CONFIG_FB_ATY_CT */
+
+
+#ifdef CONFIG_FB_ATY_GX
+static char *aty_gx_ram[8] = {
+	ram_dram, ram_vram, ram_vram, ram_dram,
+	ram_dram, ram_vram, ram_vram, ram_resv
+};
+#endif /* CONFIG_FB_ATY_GX */
+
+#ifdef CONFIG_FB_ATY_CT
+static char *aty_ct_ram[8] = {
+	ram_off, ram_dram, ram_edo, ram_edo,
+	ram_sdram, ram_sgram, ram_wram, ram_resv
+};
+static char *aty_xl_ram[8] = {
+	ram_off, ram_dram, ram_edo, ram_edo,
+	ram_sdram, ram_sgram, ram_sdram32, ram_resv
+};
+#endif /* CONFIG_FB_ATY_CT */
+
+static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var,
+			      struct atyfb_par *par)
+{
+	u32 pixclock = var->pixclock;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	u32 lcd_on_off;
+	par->pll.ct.xres = 0;
+	if (par->lcd_table != 0) {
+		lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
+		if (lcd_on_off & LCD_ON) {
+			par->pll.ct.xres = var->xres;
+			pixclock = par->lcd_pixclock;
+		}
+	}
+#endif
+	return pixclock;
+}
+
+#if defined(CONFIG_PPC)
+
+/*
+ * Apple monitor sense
+ */
+
+static int read_aty_sense(const struct atyfb_par *par)
+{
+	int sense, i;
+
+	aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */
+	__delay(200);
+	aty_st_le32(GP_IO, 0, par); /* turn off outputs */
+	__delay(2000);
+	i = aty_ld_le32(GP_IO, par); /* get primary sense value */
+	sense = ((i & 0x3000) >> 3) | (i & 0x100);
+
+	/* drive each sense line low in turn and collect the other 2 */
+	aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */
+	__delay(2000);
+	i = aty_ld_le32(GP_IO, par);
+	sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
+	aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */
+	__delay(200);
+
+	aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */
+	__delay(2000);
+	i = aty_ld_le32(GP_IO, par);
+	sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
+	aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */
+	__delay(200);
+
+	aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */
+	__delay(2000);
+	sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;
+	aty_st_le32(GP_IO, 0, par); /* turn off outputs */
+	return sense;
+}
+
+#endif /* defined(CONFIG_PPC) */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * CRTC programming
+ */
+
+static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
+{
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		if (!M64_HAS(LT_LCD_REGS)) {
+			crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
+			aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
+		}
+		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);
+		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
+
+
+		/* switch to non shadow registers */
+		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
+			   ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
+
+		/* save stretching */
+		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
+		crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
+		if (!M64_HAS(LT_LCD_REGS))
+			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
+	}
+#endif
+	crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
+	crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
+	crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
+	crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
+	crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);
+	crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);
+	crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* switch to shadow registers */
+		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
+			   SHADOW_EN | SHADOW_RW_EN, par);
+
+		crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
+		crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
+		crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
+		crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
+
+		aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+}
+
+static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
+{
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* stop CRTC */
+		aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl &
+			    ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
+
+		/* update non-shadow registers first */
+		aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);
+		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
+			   ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
+
+		/* temporarily disable stretching */
+		aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching &
+			   ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
+		aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching &
+			   ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
+			     VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
+	}
+#endif
+	/* turn off CRT */
+	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
+
+	DPRINTK("setting up CRTC\n");
+	DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
+		((((crtc->h_tot_disp >> 16) & 0xff) + 1) << 3),
+		(((crtc->v_tot_disp >> 16) & 0x7ff) + 1),
+		(crtc->h_sync_strt_wid & 0x200000) ? 'N' : 'P',
+		(crtc->v_sync_strt_wid & 0x200000) ? 'N' : 'P',
+		(crtc->gen_cntl & CRTC_CSYNC_EN) ? 'P' : 'N');
+
+	DPRINTK("CRTC_H_TOTAL_DISP: %x\n", crtc->h_tot_disp);
+	DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n", crtc->h_sync_strt_wid);
+	DPRINTK("CRTC_V_TOTAL_DISP: %x\n", crtc->v_tot_disp);
+	DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n", crtc->v_sync_strt_wid);
+	DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
+	DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
+	DPRINTK("CRTC_GEN_CNTL: %x\n", crtc->gen_cntl);
+
+	aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
+	aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
+	aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
+	aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
+	aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
+	aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
+
+	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
+#if 0
+	FIXME
+	if (par->accel_flags & FB_ACCELF_TEXT)
+		aty_init_engine(par, info);
+#endif
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	/* after setting the CRTC registers we should set the LCD registers. */
+	if (par->lcd_table != 0) {
+		/* switch to shadow registers */
+		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
+			   SHADOW_EN | SHADOW_RW_EN, par);
+
+		DPRINTK("set shadow CRT to %ix%i %c%c\n",
+			((((crtc->shadow_h_tot_disp >> 16) & 0xff) + 1) << 3),
+			(((crtc->shadow_v_tot_disp >> 16) & 0x7ff) + 1),
+			(crtc->shadow_h_sync_strt_wid & 0x200000) ? 'N' : 'P',
+			(crtc->shadow_v_sync_strt_wid & 0x200000) ? 'N' : 'P');
+
+		DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n",
+			crtc->shadow_h_tot_disp);
+		DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n",
+			crtc->shadow_h_sync_strt_wid);
+		DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n",
+			crtc->shadow_v_tot_disp);
+		DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n",
+			crtc->shadow_v_sync_strt_wid);
+
+		aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
+		aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
+		aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
+		aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
+
+		/* restore CRTC selection & shadow state and enable stretching */
+		DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
+		DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
+		DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
+		if (!M64_HAS(LT_LCD_REGS))
+			DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
+
+		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
+		aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
+		aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
+		if (!M64_HAS(LT_LCD_REGS)) {
+			aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
+			aty_ld_le32(LCD_INDEX, par);
+			aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
+		}
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+}
+
+static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp)
+{
+	u32 line_length = vxres * bpp / 8;
+
+	if (par->ram_type == SGRAM ||
+	    (!M64_HAS(XL_MEM) && par->ram_type == WRAM))
+		line_length = (line_length + 63) & ~63;
+
+	return line_length;
+}
+
+static int aty_var_to_crtc(const struct fb_info *info,
+			   const struct fb_var_screeninfo *var,
+			   struct crtc *crtc)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
+	u32 sync, vmode, vdisplay;
+	u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
+	u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
+	u32 pix_width, dp_pix_width, dp_chain_mask;
+	u32 line_length;
+
+	/* input */
+	xres = (var->xres + 7) & ~7;
+	yres = var->yres;
+	vxres = (var->xres_virtual + 7) & ~7;
+	vyres = var->yres_virtual;
+	xoffset = (var->xoffset + 7) & ~7;
+	yoffset = var->yoffset;
+	bpp = var->bits_per_pixel;
+	if (bpp == 16)
+		bpp = (var->green.length == 5) ? 15 : 16;
+	sync = var->sync;
+	vmode = var->vmode;
+
+	/* convert (and round up) and validate */
+	if (vxres < xres + xoffset)
+		vxres = xres + xoffset;
+	h_disp = xres;
+
+	if (vyres < yres + yoffset)
+		vyres = yres + yoffset;
+	v_disp = yres;
+
+	if (bpp <= 8) {
+		bpp = 8;
+		pix_width = CRTC_PIX_WIDTH_8BPP;
+		dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
+			BYTE_ORDER_LSB_TO_MSB;
+		dp_chain_mask = DP_CHAIN_8BPP;
+	} else if (bpp <= 15) {
+		bpp = 16;
+		pix_width = CRTC_PIX_WIDTH_15BPP;
+		dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
+			BYTE_ORDER_LSB_TO_MSB;
+		dp_chain_mask = DP_CHAIN_15BPP;
+	} else if (bpp <= 16) {
+		bpp = 16;
+		pix_width = CRTC_PIX_WIDTH_16BPP;
+		dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
+			BYTE_ORDER_LSB_TO_MSB;
+		dp_chain_mask = DP_CHAIN_16BPP;
+	} else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
+		bpp = 24;
+		pix_width = CRTC_PIX_WIDTH_24BPP;
+		dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
+			BYTE_ORDER_LSB_TO_MSB;
+		dp_chain_mask = DP_CHAIN_24BPP;
+	} else if (bpp <= 32) {
+		bpp = 32;
+		pix_width = CRTC_PIX_WIDTH_32BPP;
+		dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
+			BYTE_ORDER_LSB_TO_MSB;
+		dp_chain_mask = DP_CHAIN_32BPP;
+	} else
+		FAIL("invalid bpp");
+
+	line_length = calc_line_length(par, vxres, bpp);
+
+	if (vyres * line_length > info->fix.smem_len)
+		FAIL("not enough video RAM");
+
+	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+
+	if ((xres > 1920) || (yres > 1200)) {
+		FAIL("MACH64 chips are designed for max 1920x1200\n"
+		     "select another resolution.");
+	}
+	h_sync_strt = h_disp + var->right_margin;
+	h_sync_end = h_sync_strt + var->hsync_len;
+	h_sync_dly  = var->right_margin & 7;
+	h_total = h_sync_end + h_sync_dly + var->left_margin;
+
+	v_sync_strt = v_disp + var->lower_margin;
+	v_sync_end = v_sync_strt + var->vsync_len;
+	v_total = v_sync_end + var->upper_margin;
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		if (!M64_HAS(LT_LCD_REGS)) {
+			u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
+			crtc->lcd_index = lcd_index &
+				~(LCD_INDEX_MASK | LCD_DISPLAY_DIS |
+				  LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
+			aty_st_le32(LCD_INDEX, lcd_index, par);
+		}
+
+		if (!M64_HAS(MOBIL_BUS))
+			crtc->lcd_index |= CRTC2_DISPLAY_DIS;
+
+		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000;
+		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
+
+		crtc->lcd_gen_cntl &=
+			~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
+			/*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
+			USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
+		crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
+
+		if ((crtc->lcd_gen_cntl & LCD_ON) &&
+		    ((xres > par->lcd_width) || (yres > par->lcd_height))) {
+			/*
+			 * We cannot display the mode on the LCD. If the CRT is
+			 * enabled we can turn off the LCD.
+			 * If the CRT is off, it isn't a good idea to switch it
+			 * on; we don't know if one is connected. So it's better
+			 * to fail then.
+			 */
+			if (crtc->lcd_gen_cntl & CRT_ON) {
+				if (!(var->activate & FB_ACTIVATE_TEST))
+					PRINTKI("Disable LCD panel, because video mode does not fit.\n");
+				crtc->lcd_gen_cntl &= ~LCD_ON;
+				/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
+			} else {
+				if (!(var->activate & FB_ACTIVATE_TEST))
+					PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
+		int VScan = 1;
+		/* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
+		const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
+		const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 };  */
+
+		vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
+
+		/*
+		 * This is horror! When we simulate, say 640x480 on an 800x600
+		 * LCD monitor, the CRTC should be programmed 800x600 values for
+		 * the non visible part, but 640x480 for the visible part.
+		 * This code has been tested on a laptop with it's 1400x1050 LCD
+		 * monitor and a conventional monitor both switched on.
+		 * Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
+		 * works with little glitches also with DOUBLESCAN modes
+		 */
+		if (yres < par->lcd_height) {
+			VScan = par->lcd_height / yres;
+			if (VScan > 1) {
+				VScan = 2;
+				vmode |= FB_VMODE_DOUBLE;
+			}
+		}
+
+		h_sync_strt = h_disp + par->lcd_right_margin;
+		h_sync_end = h_sync_strt + par->lcd_hsync_len;
+		h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;
+		h_total = h_disp + par->lcd_hblank_len;
+
+		v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
+		v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
+		v_total = v_disp + par->lcd_vblank_len / VScan;
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+
+	h_disp = (h_disp >> 3) - 1;
+	h_sync_strt = (h_sync_strt >> 3) - 1;
+	h_sync_end = (h_sync_end >> 3) - 1;
+	h_total = (h_total >> 3) - 1;
+	h_sync_wid = h_sync_end - h_sync_strt;
+
+	FAIL_MAX("h_disp too large", h_disp, 0xff);
+	FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
+	/*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
+	if (h_sync_wid > 0x1f)
+		h_sync_wid = 0x1f;
+	FAIL_MAX("h_total too large", h_total, 0x1ff);
+
+	if (vmode & FB_VMODE_DOUBLE) {
+		v_disp <<= 1;
+		v_sync_strt <<= 1;
+		v_sync_end <<= 1;
+		v_total <<= 1;
+	}
+
+	vdisplay = yres;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))
+		vdisplay  = par->lcd_height;
+#endif
+
+	v_disp--;
+	v_sync_strt--;
+	v_sync_end--;
+	v_total--;
+	v_sync_wid = v_sync_end - v_sync_strt;
+
+	FAIL_MAX("v_disp too large", v_disp, 0x7ff);
+	FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
+	/*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
+	if (v_sync_wid > 0x1f)
+		v_sync_wid = 0x1f;
+	FAIL_MAX("v_total too large", v_total, 0x7ff);
+
+	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
+
+	/* output */
+	crtc->vxres = vxres;
+	crtc->vyres = vyres;
+	crtc->xoffset = xoffset;
+	crtc->yoffset = yoffset;
+	crtc->bpp = bpp;
+	crtc->off_pitch =
+		((yoffset * line_length + xoffset * bpp / 8) / 8) |
+		((line_length / bpp) << 22);
+	crtc->vline_crnt_vline = 0;
+
+	crtc->h_tot_disp = h_total | (h_disp << 16);
+	crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) |
+		((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) |
+		(h_sync_pol << 21);
+	crtc->v_tot_disp = v_total | (v_disp << 16);
+	crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
+		(v_sync_pol << 21);
+
+	/* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
+	crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
+	crtc->gen_cntl |= CRTC_VGA_LINEAR;
+
+	/* Enable doublescan mode if requested */
+	if (vmode & FB_VMODE_DOUBLE)
+		crtc->gen_cntl |= CRTC_DBL_SCAN_EN;
+	/* Enable interlaced mode if requested */
+	if (vmode & FB_VMODE_INTERLACED)
+		crtc->gen_cntl |= CRTC_INTERLACE_EN;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		vdisplay = yres;
+		if (vmode & FB_VMODE_DOUBLE)
+			vdisplay <<= 1;
+		crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
+		crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
+					/*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
+					USE_SHADOWED_VEND |
+					USE_SHADOWED_ROWCUR |
+					SHADOW_EN | SHADOW_RW_EN);
+		crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR/* | LOCK_8DOT*/;
+
+		/* MOBILITY M1 tested, FIXME: LT */
+		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
+		if (!M64_HAS(LT_LCD_REGS))
+			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
+				~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
+
+		crtc->horz_stretching &= ~(HORZ_STRETCH_RATIO |
+					   HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
+					   HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
+		if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
+			do {
+				/*
+				 * The horizontal blender misbehaves when
+				 * HDisplay is less than a certain threshold
+				 * (440 for a 1024-wide panel).  It doesn't
+				 * stretch such modes enough.  Use pixel
+				 * replication instead of blending to stretch
+				 * modes that can be made to exactly fit the
+				 * panel width.  The undocumented "NoLCDBlend"
+				 * option allows the pixel-replicated mode to
+				 * be slightly wider or narrower than the
+				 * panel width.  It also causes a mode that is
+				 * exactly half as wide as the panel to be
+				 * pixel-replicated, rather than blended.
+				 */
+				int HDisplay  = xres & ~7;
+				int nStretch  = par->lcd_width / HDisplay;
+				int Remainder = par->lcd_width % HDisplay;
+
+				if ((!Remainder && ((nStretch > 2))) ||
+				    (((HDisplay * 16) / par->lcd_width) < 7)) {
+					static const char StretchLoops[] = { 10, 12, 13, 15, 16 };
+					int horz_stretch_loop = -1, BestRemainder;
+					int Numerator = HDisplay, Denominator = par->lcd_width;
+					int Index = 5;
+					ATIReduceRatio(&Numerator, &Denominator);
+
+					BestRemainder = (Numerator * 16) / Denominator;
+					while (--Index >= 0) {
+						Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %
+							Denominator;
+						if (Remainder < BestRemainder) {
+							horz_stretch_loop = Index;
+							if (!(BestRemainder = Remainder))
+								break;
+						}
+					}
+
+					if ((horz_stretch_loop >= 0) && !BestRemainder) {
+						int horz_stretch_ratio = 0, Accumulator = 0;
+						int reuse_previous = 1;
+
+						Index = StretchLoops[horz_stretch_loop];
+
+						while (--Index >= 0) {
+							if (Accumulator > 0)
+								horz_stretch_ratio |= reuse_previous;
+							else
+								Accumulator += Denominator;
+							Accumulator -= Numerator;
+							reuse_previous <<= 1;
+						}
+
+						crtc->horz_stretching |= (HORZ_STRETCH_EN |
+							((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |
+							(horz_stretch_ratio & HORZ_STRETCH_RATIO));
+						break;      /* Out of the do { ... } while (0) */
+					}
+				}
+
+				crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |
+					(((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));
+			} while (0);
+		}
+
+		if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
+			crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
+				(((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
+
+			if (!M64_HAS(LT_LCD_REGS) &&
+			    xres <= (M64_HAS(MOBIL_BUS) ? 1024 : 800))
+				crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
+		} else {
+			/*
+			 * Don't use vertical blending if the mode is too wide
+			 * or not vertically stretched.
+			 */
+			crtc->vert_stretching = 0;
+		}
+		/* copy to shadow crtc */
+		crtc->shadow_h_tot_disp = crtc->h_tot_disp;
+		crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
+		crtc->shadow_v_tot_disp = crtc->v_tot_disp;
+		crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+
+	if (M64_HAS(MAGIC_FIFO)) {
+		/* FIXME: display FIFO low watermark values */
+		crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
+	}
+	crtc->dp_pix_width = dp_pix_width;
+	crtc->dp_chain_mask = dp_chain_mask;
+
+	return 0;
+}
+
+static int aty_crtc_to_var(const struct crtc *crtc,
+			   struct fb_var_screeninfo *var)
+{
+	u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
+	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
+	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
+	u32 pix_width;
+	u32 double_scan, interlace;
+
+	/* input */
+	h_total = crtc->h_tot_disp & 0x1ff;
+	h_disp = (crtc->h_tot_disp >> 16) & 0xff;
+	h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
+	h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
+	h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
+	h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
+	v_total = crtc->v_tot_disp & 0x7ff;
+	v_disp = (crtc->v_tot_disp >> 16) & 0x7ff;
+	v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
+	v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;
+	v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
+	c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
+	pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
+	double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
+	interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
+
+	/* convert */
+	xres = (h_disp + 1) * 8;
+	yres = v_disp + 1;
+	left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly;
+	right = (h_sync_strt - h_disp) * 8 + h_sync_dly;
+	hslen = h_sync_wid * 8;
+	upper = v_total - v_sync_strt - v_sync_wid;
+	lower = v_sync_strt - v_disp;
+	vslen = v_sync_wid;
+	sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
+		(v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+		(c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
+
+	switch (pix_width) {
+#if 0
+	case CRTC_PIX_WIDTH_4BPP:
+		bpp = 4;
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+#endif
+	case CRTC_PIX_WIDTH_8BPP:
+		bpp = 8;
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case CRTC_PIX_WIDTH_15BPP:	/* RGB 555 */
+		bpp = 16;
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 5;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case CRTC_PIX_WIDTH_16BPP:	/* RGB 565 */
+		bpp = 16;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case CRTC_PIX_WIDTH_24BPP:	/* RGB 888 */
+		bpp = 24;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case CRTC_PIX_WIDTH_32BPP:	/* ARGB 8888 */
+		bpp = 32;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	default:
+		PRINTKE("Invalid pixel width\n");
+		return -EINVAL;
+	}
+
+	/* output */
+	var->xres = xres;
+	var->yres = yres;
+	var->xres_virtual = crtc->vxres;
+	var->yres_virtual = crtc->vyres;
+	var->bits_per_pixel = bpp;
+	var->left_margin = left;
+	var->right_margin = right;
+	var->upper_margin = upper;
+	var->lower_margin = lower;
+	var->hsync_len = hslen;
+	var->vsync_len = vslen;
+	var->sync = sync;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	/*
+	 * In double scan mode, the vertical parameters are doubled,
+	 * so we need to halve them to get the right values.
+	 * In interlaced mode the values are already correct,
+	 * so no correction is necessary.
+	 */
+	if (interlace)
+		var->vmode = FB_VMODE_INTERLACED;
+
+	if (double_scan) {
+		var->vmode = FB_VMODE_DOUBLE;
+		var->yres >>= 1;
+		var->upper_margin >>= 1;
+		var->lower_margin >>= 1;
+		var->vsync_len >>= 1;
+	}
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int atyfb_set_par(struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	u32 tmp, pixclock;
+	int err;
+#ifdef DEBUG
+	struct fb_var_screeninfo debug;
+	u32 pixclock_in_ps;
+#endif
+	if (par->asleep)
+		return 0;
+
+	err = aty_var_to_crtc(info, var, &par->crtc);
+	if (err)
+		return err;
+
+	pixclock = atyfb_get_pixclock(var, par);
+
+	if (pixclock == 0) {
+		PRINTKE("Invalid pixclock\n");
+		return -EINVAL;
+	} else {
+		err = par->pll_ops->var_to_pll(info, pixclock,
+					       var->bits_per_pixel, &par->pll);
+		if (err)
+			return err;
+	}
+
+	par->accel_flags = var->accel_flags; /* hack */
+
+	if (var->accel_flags) {
+		info->fbops->fb_sync = atyfb_sync;
+		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+	} else {
+		info->fbops->fb_sync = NULL;
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+
+	if (par->blitter_may_be_busy)
+		wait_for_idle(par);
+
+	aty_set_crtc(par, &par->crtc);
+	par->dac_ops->set_dac(info, &par->pll,
+			      var->bits_per_pixel, par->accel_flags);
+	par->pll_ops->set_pll(info, &par->pll);
+
+#ifdef DEBUG
+	if (par->pll_ops && par->pll_ops->pll_to_var)
+		pixclock_in_ps = par->pll_ops->pll_to_var(info, &par->pll);
+	else
+		pixclock_in_ps = 0;
+
+	if (0 == pixclock_in_ps) {
+		PRINTKE("ALERT ops->pll_to_var get 0\n");
+		pixclock_in_ps = pixclock;
+	}
+
+	memset(&debug, 0, sizeof(debug));
+	if (!aty_crtc_to_var(&par->crtc, &debug)) {
+		u32 hSync, vRefresh;
+		u32 h_disp, h_sync_strt, h_sync_end, h_total;
+		u32 v_disp, v_sync_strt, v_sync_end, v_total;
+
+		h_disp = debug.xres;
+		h_sync_strt = h_disp + debug.right_margin;
+		h_sync_end = h_sync_strt + debug.hsync_len;
+		h_total = h_sync_end + debug.left_margin;
+		v_disp = debug.yres;
+		v_sync_strt = v_disp + debug.lower_margin;
+		v_sync_end = v_sync_strt + debug.vsync_len;
+		v_total = v_sync_end + debug.upper_margin;
+
+		hSync = 1000000000 / (pixclock_in_ps * h_total);
+		vRefresh = (hSync * 1000) / v_total;
+		if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
+			vRefresh *= 2;
+		if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
+			vRefresh /= 2;
+
+		DPRINTK("atyfb_set_par\n");
+		DPRINTK(" Set Visible Mode to %ix%i-%i\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK(" Virtual resolution %ix%i, "
+			"pixclock_in_ps %i (calculated %i)\n",
+			var->xres_virtual, var->yres_virtual,
+			pixclock, pixclock_in_ps);
+		DPRINTK(" Dot clock:           %i MHz\n",
+			1000000 / pixclock_in_ps);
+		DPRINTK(" Horizontal sync:     %i kHz\n", hSync);
+		DPRINTK(" Vertical refresh:    %i Hz\n", vRefresh);
+		DPRINTK(" x  style: %i.%03i %i %i %i %i   %i %i %i %i\n",
+			1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
+			h_disp, h_sync_strt, h_sync_end, h_total,
+			v_disp, v_sync_strt, v_sync_end, v_total);
+		DPRINTK(" fb style: %i  %i %i %i %i %i %i %i %i\n",
+			pixclock_in_ps,
+			debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
+			debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
+	}
+#endif /* DEBUG */
+
+	if (!M64_HAS(INTEGRATED)) {
+		/* Don't forget MEM_CNTL */
+		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
+		switch (var->bits_per_pixel) {
+		case 8:
+			tmp |= 0x02000000;
+			break;
+		case 16:
+			tmp |= 0x03000000;
+			break;
+		case 32:
+			tmp |= 0x06000000;
+			break;
+		}
+		aty_st_le32(MEM_CNTL, tmp, par);
+	} else {
+		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
+		if (!M64_HAS(MAGIC_POSTDIV))
+			tmp |= par->mem_refresh_rate << 20;
+		switch (var->bits_per_pixel) {
+		case 8:
+		case 24:
+			tmp |= 0x00000000;
+			break;
+		case 16:
+			tmp |= 0x04000000;
+			break;
+		case 32:
+			tmp |= 0x08000000;
+			break;
+		}
+		if (M64_HAS(CT_BUS)) {
+			aty_st_le32(DAC_CNTL, 0x87010184, par);
+			aty_st_le32(BUS_CNTL, 0x680000f9, par);
+		} else if (M64_HAS(VT_BUS)) {
+			aty_st_le32(DAC_CNTL, 0x87010184, par);
+			aty_st_le32(BUS_CNTL, 0x680000f9, par);
+		} else if (M64_HAS(MOBIL_BUS)) {
+			aty_st_le32(DAC_CNTL, 0x80010102, par);
+			aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
+		} else {
+			/* GT */
+			aty_st_le32(DAC_CNTL, 0x86010102, par);
+			aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
+			aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
+		}
+		aty_st_le32(MEM_CNTL, tmp, par);
+	}
+	aty_st_8(DAC_MASK, 0xff, par);
+
+	info->fix.line_length = calc_line_length(par, var->xres_virtual,
+						 var->bits_per_pixel);
+
+	info->fix.visual = var->bits_per_pixel <= 8 ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+	/* Initialize the graphics engine */
+	if (par->accel_flags & FB_ACCELF_TEXT)
+		aty_init_engine(par, info);
+
+#ifdef CONFIG_BOOTX_TEXT
+	btext_update_display(info->fix.smem_start,
+		(((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
+		((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
+		var->bits_per_pixel,
+		par->crtc.vxres * var->bits_per_pixel / 8);
+#endif /* CONFIG_BOOTX_TEXT */
+#if 0
+	/* switch to accelerator mode */
+	if (!(par->crtc.gen_cntl & CRTC_EXT_DISP_EN))
+		aty_st_le32(CRTC_GEN_CNTL, par->crtc.gen_cntl | CRTC_EXT_DISP_EN, par);
+#endif
+#ifdef DEBUG
+{
+	/* dump non shadow CRTC, pll, LCD registers */
+	int i; u32 base;
+
+	/* CRTC registers */
+	base = 0x2000;
+	printk("debug atyfb: Mach64 non-shadow register values:");
+	for (i = 0; i < 256; i = i+4) {
+		if (i % 16 == 0)
+			printk("\ndebug atyfb: 0x%04X: ", base + i);
+		printk(" %08X", aty_ld_le32(i, par));
+	}
+	printk("\n\n");
+
+#ifdef CONFIG_FB_ATY_CT
+	/* PLL registers */
+	base = 0x00;
+	printk("debug atyfb: Mach64 PLL register values:");
+	for (i = 0; i < 64; i++) {
+		if (i % 16 == 0)
+			printk("\ndebug atyfb: 0x%02X: ", base + i);
+		if (i % 4 == 0)
+			printk(" ");
+		printk("%02X", aty_ld_pll_ct(i, par));
+	}
+	printk("\n\n");
+#endif	/* CONFIG_FB_ATY_CT */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* LCD registers */
+		base = 0x00;
+		printk("debug atyfb: LCD register values:");
+		if (M64_HAS(LT_LCD_REGS)) {
+			for (i = 0; i <= POWER_MANAGEMENT; i++) {
+				if (i == EXT_VERT_STRETCH)
+					continue;
+				printk("\ndebug atyfb: 0x%04X: ",
+				       lt_lcd_regs[i]);
+				printk(" %08X", aty_ld_lcd(i, par));
+			}
+		} else {
+			for (i = 0; i < 64; i++) {
+				if (i % 4 == 0)
+					printk("\ndebug atyfb: 0x%02X: ",
+					       base + i);
+				printk(" %08X", aty_ld_lcd(i, par));
+			}
+		}
+		printk("\n\n");
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+}
+#endif /* DEBUG */
+	return 0;
+}
+
+static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	int err;
+	struct crtc crtc;
+	union aty_pll pll;
+	u32 pixclock;
+
+	memcpy(&pll, &par->pll, sizeof(pll));
+
+	err = aty_var_to_crtc(info, var, &crtc);
+	if (err)
+		return err;
+
+	pixclock = atyfb_get_pixclock(var, par);
+
+	if (pixclock == 0) {
+		if (!(var->activate & FB_ACTIVATE_TEST))
+			PRINTKE("Invalid pixclock\n");
+		return -EINVAL;
+	} else {
+		err = par->pll_ops->var_to_pll(info, pixclock,
+					       var->bits_per_pixel, &pll);
+		if (err)
+			return err;
+	}
+
+	if (var->accel_flags & FB_ACCELF_TEXT)
+		info->var.accel_flags = FB_ACCELF_TEXT;
+	else
+		info->var.accel_flags = 0;
+
+	aty_crtc_to_var(&crtc, var);
+	var->pixclock = par->pll_ops->pll_to_var(info, &pll);
+	return 0;
+}
+
+static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
+{
+	u32 xoffset = info->var.xoffset;
+	u32 yoffset = info->var.yoffset;
+	u32 line_length = info->fix.line_length;
+	u32 bpp = info->var.bits_per_pixel;
+
+	par->crtc.off_pitch =
+		((yoffset * line_length + xoffset * bpp / 8) / 8) |
+		((line_length / bpp) << 22);
+}
+
+
+/*
+ * Open/Release the frame buffer device
+ */
+
+static int atyfb_open(struct fb_info *info, int user)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	if (user) {
+		par->open++;
+#ifdef __sparc__
+		par->mmaped = 0;
+#endif
+	}
+	return 0;
+}
+
+static irqreturn_t aty_irq(int irq, void *dev_id)
+{
+	struct atyfb_par *par = dev_id;
+	int handled = 0;
+	u32 int_cntl;
+
+	spin_lock(&par->int_lock);
+
+	int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
+
+	if (int_cntl & CRTC_VBLANK_INT) {
+		/* clear interrupt */
+		aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) |
+			    CRTC_VBLANK_INT_AK, par);
+		par->vblank.count++;
+		if (par->vblank.pan_display) {
+			par->vblank.pan_display = 0;
+			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+		}
+		wake_up_interruptible(&par->vblank.wait);
+		handled = 1;
+	}
+
+	spin_unlock(&par->int_lock);
+
+	return IRQ_RETVAL(handled);
+}
+
+static int aty_enable_irq(struct atyfb_par *par, int reenable)
+{
+	u32 int_cntl;
+
+	if (!test_and_set_bit(0, &par->irq_flags)) {
+		if (request_irq(par->irq, aty_irq, IRQF_SHARED, "atyfb", par)) {
+			clear_bit(0, &par->irq_flags);
+			return -EINVAL;
+		}
+		spin_lock_irq(&par->int_lock);
+		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+		/* clear interrupt */
+		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
+		/* enable interrupt */
+		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
+		spin_unlock_irq(&par->int_lock);
+	} else if (reenable) {
+		spin_lock_irq(&par->int_lock);
+		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+		if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
+			printk("atyfb: someone disabled IRQ [%08x]\n",
+			       int_cntl);
+			/* re-enable interrupt */
+			aty_st_le32(CRTC_INT_CNTL, int_cntl |
+				    CRTC_VBLANK_INT_EN, par);
+		}
+		spin_unlock_irq(&par->int_lock);
+	}
+
+	return 0;
+}
+
+static int aty_disable_irq(struct atyfb_par *par)
+{
+	u32 int_cntl;
+
+	if (test_and_clear_bit(0, &par->irq_flags)) {
+		if (par->vblank.pan_display) {
+			par->vblank.pan_display = 0;
+			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+		}
+		spin_lock_irq(&par->int_lock);
+		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+		/* disable interrupt */
+		aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par);
+		spin_unlock_irq(&par->int_lock);
+		free_irq(par->irq, par);
+	}
+
+	return 0;
+}
+
+static int atyfb_release(struct fb_info *info, int user)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+#ifdef __sparc__
+	int was_mmaped;
+#endif
+
+	if (!user)
+		return 0;
+
+	par->open--;
+	mdelay(1);
+	wait_for_idle(par);
+
+	if (par->open)
+		return 0;
+
+#ifdef __sparc__
+	was_mmaped = par->mmaped;
+
+	par->mmaped = 0;
+
+	if (was_mmaped) {
+		struct fb_var_screeninfo var;
+
+		/*
+		 * Now reset the default display config, we have
+		 * no idea what the program(s) which mmap'd the
+		 * chip did to the configuration, nor whether it
+		 * restored it correctly.
+		 */
+		var = default_var;
+		if (noaccel)
+			var.accel_flags &= ~FB_ACCELF_TEXT;
+		else
+			var.accel_flags |= FB_ACCELF_TEXT;
+		if (var.yres == var.yres_virtual) {
+			u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
+			var.yres_virtual =
+				((videoram * 8) / var.bits_per_pixel) /
+				var.xres_virtual;
+			if (var.yres_virtual < var.yres)
+				var.yres_virtual = var.yres;
+		}
+	}
+#endif
+	aty_disable_irq(par);
+
+	return 0;
+}
+
+/*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int atyfb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 xres, yres, xoffset, yoffset;
+
+	xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
+	yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
+	if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
+		yres >>= 1;
+	xoffset = (var->xoffset + 7) & ~7;
+	yoffset = var->yoffset;
+	if (xoffset + xres > par->crtc.vxres ||
+	    yoffset + yres > par->crtc.vyres)
+		return -EINVAL;
+	info->var.xoffset = xoffset;
+	info->var.yoffset = yoffset;
+	if (par->asleep)
+		return 0;
+
+	set_off_pitch(par, info);
+	if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
+		par->vblank.pan_display = 1;
+	} else {
+		par->vblank.pan_display = 0;
+		aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+	}
+
+	return 0;
+}
+
+static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
+{
+	struct aty_interrupt *vbl;
+	unsigned int count;
+	int ret;
+
+	switch (crtc) {
+	case 0:
+		vbl = &par->vblank;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	ret = aty_enable_irq(par, 0);
+	if (ret)
+		return ret;
+
+	count = vbl->count;
+	ret = wait_event_interruptible_timeout(vbl->wait,
+					       count != vbl->count, HZ/10);
+	if (ret < 0)
+		return ret;
+	if (ret == 0) {
+		aty_enable_irq(par, 1);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+
+#ifdef DEBUG
+#define ATYIO_CLKR		0x41545900	/* ATY\00 */
+#define ATYIO_CLKW		0x41545901	/* ATY\01 */
+
+struct atyclk {
+	u32 ref_clk_per;
+	u8 pll_ref_div;
+	u8 mclk_fb_div;
+	u8 mclk_post_div;	/* 1,2,3,4,8 */
+	u8 mclk_fb_mult;	/* 2 or 4 */
+	u8 xclk_post_div;	/* 1,2,3,4,8 */
+	u8 vclk_fb_div;
+	u8 vclk_post_div;	/* 1,2,3,4,6,8,12 */
+	u32 dsp_xclks_per_row;	/* 0-16383 */
+	u32 dsp_loop_latency;	/* 0-15 */
+	u32 dsp_precision;	/* 0-7 */
+	u32 dsp_on;		/* 0-2047 */
+	u32 dsp_off;		/* 0-2047 */
+};
+
+#define ATYIO_FEATR		0x41545902	/* ATY\02 */
+#define ATYIO_FEATW		0x41545903	/* ATY\03 */
+#endif
+
+static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+#ifdef __sparc__
+	struct fbtype fbtyp;
+#endif
+
+	switch (cmd) {
+#ifdef __sparc__
+	case FBIOGTYPE:
+		fbtyp.fb_type = FBTYPE_PCI_GENERIC;
+		fbtyp.fb_width = par->crtc.vxres;
+		fbtyp.fb_height = par->crtc.vyres;
+		fbtyp.fb_depth = info->var.bits_per_pixel;
+		fbtyp.fb_cmsize = info->cmap.len;
+		fbtyp.fb_size = info->fix.smem_len;
+		if (copy_to_user((struct fbtype __user *) arg, &fbtyp,
+				 sizeof(fbtyp)))
+			return -EFAULT;
+		break;
+#endif /* __sparc__ */
+
+	case FBIO_WAITFORVSYNC:
+		{
+			u32 crtc;
+
+			if (get_user(crtc, (__u32 __user *) arg))
+				return -EFAULT;
+
+			return aty_waitforvblank(par, crtc);
+		}
+
+#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
+	case ATYIO_CLKR:
+		if (M64_HAS(INTEGRATED)) {
+			struct atyclk clk;
+			union aty_pll *pll = &par->pll;
+			u32 dsp_config = pll->ct.dsp_config;
+			u32 dsp_on_off = pll->ct.dsp_on_off;
+			clk.ref_clk_per = par->ref_clk_per;
+			clk.pll_ref_div = pll->ct.pll_ref_div;
+			clk.mclk_fb_div = pll->ct.mclk_fb_div;
+			clk.mclk_post_div = pll->ct.mclk_post_div_real;
+			clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
+			clk.xclk_post_div = pll->ct.xclk_post_div_real;
+			clk.vclk_fb_div = pll->ct.vclk_fb_div;
+			clk.vclk_post_div = pll->ct.vclk_post_div_real;
+			clk.dsp_xclks_per_row = dsp_config & 0x3fff;
+			clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;
+			clk.dsp_precision = (dsp_config >> 20) & 7;
+			clk.dsp_off = dsp_on_off & 0x7ff;
+			clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;
+			if (copy_to_user((struct atyclk __user *) arg, &clk,
+					 sizeof(clk)))
+				return -EFAULT;
+		} else
+			return -EINVAL;
+		break;
+	case ATYIO_CLKW:
+		if (M64_HAS(INTEGRATED)) {
+			struct atyclk clk;
+			union aty_pll *pll = &par->pll;
+			if (copy_from_user(&clk, (struct atyclk __user *) arg,
+					   sizeof(clk)))
+				return -EFAULT;
+			par->ref_clk_per = clk.ref_clk_per;
+			pll->ct.pll_ref_div = clk.pll_ref_div;
+			pll->ct.mclk_fb_div = clk.mclk_fb_div;
+			pll->ct.mclk_post_div_real = clk.mclk_post_div;
+			pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
+			pll->ct.xclk_post_div_real = clk.xclk_post_div;
+			pll->ct.vclk_fb_div = clk.vclk_fb_div;
+			pll->ct.vclk_post_div_real = clk.vclk_post_div;
+			pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
+				((clk.dsp_loop_latency & 0xf) << 16) |
+				((clk.dsp_precision & 7) << 20);
+			pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) |
+				((clk.dsp_on & 0x7ff) << 16);
+			/*aty_calc_pll_ct(info, &pll->ct);*/
+			aty_set_pll_ct(info, pll);
+		} else
+			return -EINVAL;
+		break;
+	case ATYIO_FEATR:
+		if (get_user(par->features, (u32 __user *) arg))
+			return -EFAULT;
+		break;
+	case ATYIO_FEATW:
+		if (put_user(par->features, (u32 __user *) arg))
+			return -EFAULT;
+		break;
+#endif /* DEBUG && CONFIG_FB_ATY_CT */
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int atyfb_sync(struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	if (par->blitter_may_be_busy)
+		wait_for_idle(par);
+	return 0;
+}
+
+#ifdef __sparc__
+static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	unsigned int size, page, map_size = 0;
+	unsigned long map_offset = 0;
+	unsigned long off;
+	int i;
+
+	if (!par->mmap_map)
+		return -ENXIO;
+
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+
+	off = vma->vm_pgoff << PAGE_SHIFT;
+	size = vma->vm_end - vma->vm_start;
+
+	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
+
+	if (((vma->vm_pgoff == 0) && (size == info->fix.smem_len)) ||
+	    ((off == info->fix.smem_len) && (size == PAGE_SIZE)))
+		off += 0x8000000000000000UL;
+
+	vma->vm_pgoff = off >> PAGE_SHIFT;	/* propagate off changes */
+
+	/* Each page, see which map applies */
+	for (page = 0; page < size;) {
+		map_size = 0;
+		for (i = 0; par->mmap_map[i].size; i++) {
+			unsigned long start = par->mmap_map[i].voff;
+			unsigned long end = start + par->mmap_map[i].size;
+			unsigned long offset = off + page;
+
+			if (start > offset)
+				continue;
+			if (offset >= end)
+				continue;
+
+			map_size = par->mmap_map[i].size - (offset - start);
+			map_offset = par->mmap_map[i].poff + (offset - start);
+			break;
+		}
+		if (!map_size) {
+			page += PAGE_SIZE;
+			continue;
+		}
+		if (page + map_size > size)
+			map_size = size - page;
+
+		pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
+		pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
+
+		if (remap_pfn_range(vma, vma->vm_start + page,
+			map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
+			return -EAGAIN;
+
+		page += map_size;
+	}
+
+	if (!map_size)
+		return -EINVAL;
+
+	if (!par->mmaped)
+		par->mmaped = 1;
+	return 0;
+}
+#endif /* __sparc__ */
+
+
+
+#if defined(CONFIG_PM) && defined(CONFIG_PCI)
+
+#ifdef CONFIG_PPC_PMAC
+/* Power management routines. Those are used for PowerBook sleep.
+ */
+static int aty_power_mgmt(int sleep, struct atyfb_par *par)
+{
+	u32 pm;
+	int timeout;
+
+	pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
+	aty_st_lcd(POWER_MANAGEMENT, pm, par);
+	pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+
+	timeout = 2000;
+	if (sleep) {
+		/* Sleep */
+		pm &= ~PWR_MGT_ON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		udelay(10);
+		pm &= ~(PWR_BLON | AUTO_PWR_UP);
+		pm |= SUSPEND_NOW;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		udelay(10);
+		pm |= PWR_MGT_ON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+		do {
+			pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+			mdelay(1);
+			if ((--timeout) == 0)
+				break;
+		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
+	} else {
+		/* Wakeup */
+		pm &= ~PWR_MGT_ON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		udelay(10);
+		pm &= ~SUSPEND_NOW;
+		pm |= (PWR_BLON | AUTO_PWR_UP);
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+		pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		udelay(10);
+		pm |= PWR_MGT_ON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+		do {
+			pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+			mdelay(1);
+			if ((--timeout) == 0)
+				break;
+		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
+	}
+	mdelay(500);
+
+	return timeout ? 0 : -EIO;
+}
+#endif /* CONFIG_PPC_PMAC */
+
+static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	if (state.event == pdev->dev.power.power_state.event)
+		return 0;
+
+	console_lock();
+
+	fb_set_suspend(info, 1);
+
+	/* Idle & reset engine */
+	wait_for_idle(par);
+	aty_reset_engine(par);
+
+	/* Blank display and LCD */
+	atyfb_blank(FB_BLANK_POWERDOWN, info);
+
+	par->asleep = 1;
+	par->lock_blank = 1;
+
+	/*
+	 * Because we may change PCI D state ourselves, we need to
+	 * first save the config space content so the core can
+	 * restore it properly on resume.
+	 */
+	pci_save_state(pdev);
+
+#ifdef CONFIG_PPC_PMAC
+	/* Set chip to "suspend" mode */
+	if (machine_is(powermac) && aty_power_mgmt(1, par)) {
+		par->asleep = 0;
+		par->lock_blank = 0;
+		atyfb_blank(FB_BLANK_UNBLANK, info);
+		fb_set_suspend(info, 0);
+		console_unlock();
+		return -EIO;
+	}
+#else
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+#endif
+
+	console_unlock();
+
+	pdev->dev.power.power_state = state;
+
+	return 0;
+}
+
+static void aty_resume_chip(struct fb_info *info)
+{
+	struct atyfb_par *par = info->par;
+
+	aty_st_le32(MEM_CNTL, par->mem_cntl, par);
+
+	if (par->pll_ops->resume_pll)
+		par->pll_ops->resume_pll(info, &par->pll);
+
+	if (par->aux_start)
+		aty_st_le32(BUS_CNTL,
+			aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
+}
+
+static int atyfb_pci_resume(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
+		return 0;
+
+	console_lock();
+
+	/*
+	 * PCI state will have been restored by the core, so
+	 * we should be in D0 now with our config space fully
+	 * restored
+	 */
+
+#ifdef CONFIG_PPC_PMAC
+	if (machine_is(powermac) &&
+	    pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
+		aty_power_mgmt(0, par);
+#endif
+
+	aty_resume_chip(info);
+
+	par->asleep = 0;
+
+	/* Restore display */
+	atyfb_set_par(info);
+
+	/* Refresh */
+	fb_set_suspend(info, 0);
+
+	/* Unblank */
+	par->lock_blank = 0;
+	atyfb_blank(FB_BLANK_UNBLANK, info);
+
+	console_unlock();
+
+	pdev->dev.power.power_state = PMSG_ON;
+
+	return 0;
+}
+
+#endif /*  defined(CONFIG_PM) && defined(CONFIG_PCI) */
+
+/* Backlight */
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+#define MAX_LEVEL 0xFF
+
+static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	int atylevel;
+
+	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
+	atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
+
+	if (atylevel < 0)
+		atylevel = 0;
+	else if (atylevel > MAX_LEVEL)
+		atylevel = MAX_LEVEL;
+
+	return atylevel;
+}
+
+static int aty_bl_update_status(struct backlight_device *bd)
+{
+	struct atyfb_par *par = bl_get_data(bd);
+	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
+	int level;
+
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props.brightness;
+
+	reg |= (BLMOD_EN | BIASMOD_EN);
+	if (level > 0) {
+		reg &= ~BIAS_MOD_LEVEL_MASK;
+		reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
+	} else {
+		reg &= ~BIAS_MOD_LEVEL_MASK;
+		reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
+	}
+	aty_st_lcd(LCD_MISC_CNTL, reg, par);
+
+	return 0;
+}
+
+static int aty_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops aty_bl_data = {
+	.get_brightness = aty_bl_get_brightness,
+	.update_status	= aty_bl_update_status,
+};
+
+static void aty_bl_init(struct atyfb_par *par)
+{
+	struct backlight_properties props;
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd;
+	char name[12];
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati"))
+		return;
+#endif
+
+	snprintf(name, sizeof(name), "atybl%d", info->node);
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
+				       &props);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk(KERN_WARNING "aty: Backlight registration failed\n");
+		goto error;
+	}
+
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+			    0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
+			    0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
+
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	printk("aty: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+#ifdef CONFIG_PCI
+static void aty_bl_exit(struct backlight_device *bd)
+{
+	backlight_device_unregister(bd);
+	printk("aty: Backlight unloaded\n");
+}
+#endif /* CONFIG_PCI */
+
+#endif /* CONFIG_FB_ATY_BACKLIGHT */
+
+static void aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
+{
+	const int ragepro_tbl[] = {
+		44, 50, 55, 66, 75, 80, 100
+	};
+	const int ragexl_tbl[] = {
+		50, 66, 75, 83, 90, 95, 100, 105,
+		110, 115, 120, 125, 133, 143, 166
+	};
+	const int *refresh_tbl;
+	int i, size;
+
+	if (M64_HAS(XL_MEM)) {
+		refresh_tbl = ragexl_tbl;
+		size = ARRAY_SIZE(ragexl_tbl);
+	} else {
+		refresh_tbl = ragepro_tbl;
+		size = ARRAY_SIZE(ragepro_tbl);
+	}
+
+	for (i = 0; i < size; i++) {
+		if (xclk < refresh_tbl[i])
+			break;
+	}
+	par->mem_refresh_rate = i;
+}
+
+/*
+ * Initialisation
+ */
+
+static struct fb_info *fb_list = NULL;
+
+#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
+static int atyfb_get_timings_from_lcd(struct atyfb_par *par,
+				      struct fb_var_screeninfo *var)
+{
+	int ret = -EINVAL;
+
+	if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+		*var = default_var;
+		var->xres = var->xres_virtual = par->lcd_hdisp;
+		var->right_margin = par->lcd_right_margin;
+		var->left_margin = par->lcd_hblank_len -
+			(par->lcd_right_margin + par->lcd_hsync_dly +
+			 par->lcd_hsync_len);
+		var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
+		var->yres = var->yres_virtual = par->lcd_vdisp;
+		var->lower_margin = par->lcd_lower_margin;
+		var->upper_margin = par->lcd_vblank_len -
+			(par->lcd_lower_margin + par->lcd_vsync_len);
+		var->vsync_len = par->lcd_vsync_len;
+		var->pixclock = par->lcd_pixclock;
+		ret = 0;
+	}
+
+	return ret;
+}
+#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
+
+static int aty_init(struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	const char *ramname = NULL, *xtal;
+	int gtb_memsize, has_var = 0;
+	struct fb_var_screeninfo var;
+	int ret;
+
+	init_waitqueue_head(&par->vblank.wait);
+	spin_lock_init(&par->int_lock);
+
+#ifdef CONFIG_FB_ATY_GX
+	if (!M64_HAS(INTEGRATED)) {
+		u32 stat0;
+		u8 dac_type, dac_subtype, clk_type;
+		stat0 = aty_ld_le32(CNFG_STAT0, par);
+		par->bus_type = (stat0 >> 0) & 0x07;
+		par->ram_type = (stat0 >> 3) & 0x07;
+		ramname = aty_gx_ram[par->ram_type];
+		/* FIXME: clockchip/RAMDAC probing? */
+		dac_type = (aty_ld_le32(DAC_CNTL, par) >> 16) & 0x07;
+#ifdef CONFIG_ATARI
+		clk_type = CLK_ATI18818_1;
+		dac_type = (stat0 >> 9) & 0x07;
+		if (dac_type == 0x07)
+			dac_subtype = DAC_ATT20C408;
+		else
+			dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) | dac_type;
+#else
+		dac_type = DAC_IBMRGB514;
+		dac_subtype = DAC_IBMRGB514;
+		clk_type = CLK_IBMRGB514;
+#endif
+		switch (dac_subtype) {
+		case DAC_IBMRGB514:
+			par->dac_ops = &aty_dac_ibm514;
+			break;
+#ifdef CONFIG_ATARI
+		case DAC_ATI68860_B:
+		case DAC_ATI68860_C:
+			par->dac_ops = &aty_dac_ati68860b;
+			break;
+		case DAC_ATT20C408:
+		case DAC_ATT21C498:
+			par->dac_ops = &aty_dac_att21c498;
+			break;
+#endif
+		default:
+			PRINTKI("aty_init: DAC type not implemented yet!\n");
+			par->dac_ops = &aty_dac_unsupported;
+			break;
+		}
+		switch (clk_type) {
+#ifdef CONFIG_ATARI
+		case CLK_ATI18818_1:
+			par->pll_ops = &aty_pll_ati18818_1;
+			break;
+#else
+		case CLK_IBMRGB514:
+			par->pll_ops = &aty_pll_ibm514;
+			break;
+#endif
+#if 0 /* dead code */
+		case CLK_STG1703:
+			par->pll_ops = &aty_pll_stg1703;
+			break;
+		case CLK_CH8398:
+			par->pll_ops = &aty_pll_ch8398;
+			break;
+		case CLK_ATT20C408:
+			par->pll_ops = &aty_pll_att20c408;
+			break;
+#endif
+		default:
+			PRINTKI("aty_init: CLK type not implemented yet!");
+			par->pll_ops = &aty_pll_unsupported;
+			break;
+		}
+	}
+#endif /* CONFIG_FB_ATY_GX */
+#ifdef CONFIG_FB_ATY_CT
+	if (M64_HAS(INTEGRATED)) {
+		par->dac_ops = &aty_dac_ct;
+		par->pll_ops = &aty_pll_ct;
+		par->bus_type = PCI;
+		par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
+		if (M64_HAS(XL_MEM))
+			ramname = aty_xl_ram[par->ram_type];
+		else
+			ramname = aty_ct_ram[par->ram_type];
+		/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
+		if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
+			par->pll_limits.mclk = 63;
+		/* Mobility + 32bit memory interface need halved XCLK. */
+		if (M64_HAS(MOBIL_BUS) && par->ram_type == SDRAM32)
+			par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1;
+	}
+#endif
+#ifdef CONFIG_PPC_PMAC
+	/*
+	 * The Apple iBook1 uses non-standard memory frequencies.
+	 * We detect it and set the frequency manually.
+	 */
+	if (of_machine_is_compatible("PowerBook2,1")) {
+		par->pll_limits.mclk = 70;
+		par->pll_limits.xclk = 53;
+	}
+#endif
+
+	/* Allow command line to override clocks. */
+	if (pll)
+		par->pll_limits.pll_max = pll;
+	if (mclk)
+		par->pll_limits.mclk = mclk;
+	if (xclk)
+		par->pll_limits.xclk = xclk;
+
+	aty_calc_mem_refresh(par, par->pll_limits.xclk);
+	par->pll_per = 1000000/par->pll_limits.pll_max;
+	par->mclk_per = 1000000/par->pll_limits.mclk;
+	par->xclk_per = 1000000/par->pll_limits.xclk;
+
+	par->ref_clk_per = 1000000000000ULL / 14318180;
+	xtal = "14.31818";
+
+#ifdef CONFIG_FB_ATY_CT
+	if (M64_HAS(GTB_DSP)) {
+		u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+
+		if (pll_ref_div) {
+			int diff1, diff2;
+			diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
+			diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
+			if (diff1 < 0)
+				diff1 = -diff1;
+			if (diff2 < 0)
+				diff2 = -diff2;
+			if (diff2 < diff1) {
+				par->ref_clk_per = 1000000000000ULL / 29498928;
+				xtal = "29.498928";
+			}
+		}
+	}
+#endif /* CONFIG_FB_ATY_CT */
+
+	/* save previous video mode */
+	aty_get_crtc(par, &par->saved_crtc);
+	if (par->pll_ops->get_pll)
+		par->pll_ops->get_pll(info, &par->saved_pll);
+
+	par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
+	gtb_memsize = M64_HAS(GTB_DSP);
+	if (gtb_memsize)
+		/* 0xF used instead of MEM_SIZE_ALIAS */
+		switch (par->mem_cntl & 0xF) {
+		case MEM_SIZE_512K:
+			info->fix.smem_len = 0x80000;
+			break;
+		case MEM_SIZE_1M:
+			info->fix.smem_len = 0x100000;
+			break;
+		case MEM_SIZE_2M_GTB:
+			info->fix.smem_len = 0x200000;
+			break;
+		case MEM_SIZE_4M_GTB:
+			info->fix.smem_len = 0x400000;
+			break;
+		case MEM_SIZE_6M_GTB:
+			info->fix.smem_len = 0x600000;
+			break;
+		case MEM_SIZE_8M_GTB:
+			info->fix.smem_len = 0x800000;
+			break;
+		default:
+			info->fix.smem_len = 0x80000;
+	} else
+		switch (par->mem_cntl & MEM_SIZE_ALIAS) {
+		case MEM_SIZE_512K:
+			info->fix.smem_len = 0x80000;
+			break;
+		case MEM_SIZE_1M:
+			info->fix.smem_len = 0x100000;
+			break;
+		case MEM_SIZE_2M:
+			info->fix.smem_len = 0x200000;
+			break;
+		case MEM_SIZE_4M:
+			info->fix.smem_len = 0x400000;
+			break;
+		case MEM_SIZE_6M:
+			info->fix.smem_len = 0x600000;
+			break;
+		case MEM_SIZE_8M:
+			info->fix.smem_len = 0x800000;
+			break;
+		default:
+			info->fix.smem_len = 0x80000;
+		}
+
+	if (M64_HAS(MAGIC_VRAM_SIZE)) {
+		if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000)
+			info->fix.smem_len += 0x400000;
+	}
+
+	if (vram) {
+		info->fix.smem_len = vram * 1024;
+		par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
+		if (info->fix.smem_len <= 0x80000)
+			par->mem_cntl |= MEM_SIZE_512K;
+		else if (info->fix.smem_len <= 0x100000)
+			par->mem_cntl |= MEM_SIZE_1M;
+		else if (info->fix.smem_len <= 0x200000)
+			par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
+		else if (info->fix.smem_len <= 0x400000)
+			par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
+		else if (info->fix.smem_len <= 0x600000)
+			par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
+		else
+			par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
+		aty_st_le32(MEM_CNTL, par->mem_cntl, par);
+	}
+
+	/*
+	 * Reg Block 0 (CT-compatible block) is at mmio_start
+	 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
+	 */
+	if (M64_HAS(GX)) {
+		info->fix.mmio_len = 0x400;
+		info->fix.accel = FB_ACCEL_ATI_MACH64GX;
+	} else if (M64_HAS(CT)) {
+		info->fix.mmio_len = 0x400;
+		info->fix.accel = FB_ACCEL_ATI_MACH64CT;
+	} else if (M64_HAS(VT)) {
+		info->fix.mmio_start -= 0x400;
+		info->fix.mmio_len = 0x800;
+		info->fix.accel = FB_ACCEL_ATI_MACH64VT;
+	} else {/* GT */
+		info->fix.mmio_start -= 0x400;
+		info->fix.mmio_len = 0x800;
+		info->fix.accel = FB_ACCEL_ATI_MACH64GT;
+	}
+
+	PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
+		info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len>>20),
+		info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal,
+		par->pll_limits.pll_max, par->pll_limits.mclk,
+		par->pll_limits.xclk);
+
+#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
+	if (M64_HAS(INTEGRATED)) {
+		int i;
+		printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL "
+		       "EXT_MEM_CNTL CRTC_GEN_CNTL DSP_CONFIG "
+		       "DSP_ON_OFF CLOCK_CNTL\n"
+		       "debug atyfb: %08x %08x %08x "
+		       "%08x     %08x      %08x   "
+		       "%08x   %08x\n"
+		       "debug atyfb: PLL",
+		       aty_ld_le32(BUS_CNTL, par),
+		       aty_ld_le32(DAC_CNTL, par),
+		       aty_ld_le32(MEM_CNTL, par),
+		       aty_ld_le32(EXT_MEM_CNTL, par),
+		       aty_ld_le32(CRTC_GEN_CNTL, par),
+		       aty_ld_le32(DSP_CONFIG, par),
+		       aty_ld_le32(DSP_ON_OFF, par),
+		       aty_ld_le32(CLOCK_CNTL, par));
+		for (i = 0; i < 40; i++)
+			printk(" %02x", aty_ld_pll_ct(i, par));
+		printk("\n");
+	}
+#endif
+	if (par->pll_ops->init_pll)
+		par->pll_ops->init_pll(info, &par->pll);
+	if (par->pll_ops->resume_pll)
+		par->pll_ops->resume_pll(info, &par->pll);
+
+	/*
+	 * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
+	 * unless the auxiliary register aperture is used.
+	 */
+	if (!par->aux_start &&
+	    (info->fix.smem_len == 0x800000 ||
+	     (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
+		info->fix.smem_len -= GUI_RESERVE;
+
+	/*
+	 * Disable register access through the linear aperture
+	 * if the auxiliary aperture is used so we can access
+	 * the full 8 MB of video RAM on 8 MB boards.
+	 */
+	if (par->aux_start)
+		aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) |
+			    BUS_APER_REG_DIS, par);
+
+#ifdef CONFIG_MTRR
+	par->mtrr_aper = -1;
+	par->mtrr_reg = -1;
+	if (!nomtrr) {
+		/* Cover the whole resource. */
+		par->mtrr_aper = mtrr_add(par->res_start, par->res_size,
+					  MTRR_TYPE_WRCOMB, 1);
+		if (par->mtrr_aper >= 0 && !par->aux_start) {
+			/* Make a hole for mmio. */
+			par->mtrr_reg = mtrr_add(par->res_start + 0x800000 -
+						 GUI_RESERVE, GUI_RESERVE,
+						 MTRR_TYPE_UNCACHABLE, 1);
+			if (par->mtrr_reg < 0) {
+				mtrr_del(par->mtrr_aper, 0, 0);
+				par->mtrr_aper = -1;
+			}
+		}
+	}
+#endif
+
+	info->fbops = &atyfb_ops;
+	info->pseudo_palette = par->pseudo_palette;
+	info->flags = FBINFO_DEFAULT           |
+		      FBINFO_HWACCEL_IMAGEBLIT |
+		      FBINFO_HWACCEL_FILLRECT  |
+		      FBINFO_HWACCEL_COPYAREA  |
+		      FBINFO_HWACCEL_YPAN      |
+		      FBINFO_READS_FAST;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (M64_HAS(G3_PB_1_1) && of_machine_is_compatible("PowerBook1,1")) {
+		/*
+		 * these bits let the 101 powerbook
+		 * wake up from sleep -- paulus
+		 */
+		aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) |
+			   USE_F32KHZ | TRISTATE_MEM_EN, par);
+	} else
+#endif
+	if (M64_HAS(MOBIL_BUS) && backlight) {
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+		aty_bl_init(par);
+#endif
+	}
+
+	memset(&var, 0, sizeof(var));
+#ifdef CONFIG_PPC
+	if (machine_is(powermac)) {
+		/*
+		 * FIXME: The NVRAM stuff should be put in a Mac-specific file,
+		 *        as it applies to all Mac video cards
+		 */
+		if (mode) {
+			if (mac_find_mode(&var, info, mode, 8))
+				has_var = 1;
+		} else {
+			if (default_vmode == VMODE_CHOOSE) {
+				int sense;
+				if (M64_HAS(G3_PB_1024x768))
+					/* G3 PowerBook with 1024x768 LCD */
+					default_vmode = VMODE_1024_768_60;
+				else if (of_machine_is_compatible("iMac"))
+					default_vmode = VMODE_1024_768_75;
+				else if (of_machine_is_compatible("PowerBook2,1"))
+					/* iBook with 800x600 LCD */
+					default_vmode = VMODE_800_600_60;
+				else
+					default_vmode = VMODE_640_480_67;
+				sense = read_aty_sense(par);
+				PRINTKI("monitor sense=%x, mode %d\n",
+					sense,  mac_map_monitor_sense(sense));
+			}
+			if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+				default_vmode = VMODE_640_480_60;
+			if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+				default_cmode = CMODE_8;
+			if (!mac_vmode_to_var(default_vmode, default_cmode,
+					      &var))
+				has_var = 1;
+		}
+	}
+
+#endif /* !CONFIG_PPC */
+
+#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
+	if (!atyfb_get_timings_from_lcd(par, &var))
+		has_var = 1;
+#endif
+
+	if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
+		has_var = 1;
+
+	if (!has_var)
+		var = default_var;
+
+	if (noaccel)
+		var.accel_flags &= ~FB_ACCELF_TEXT;
+	else
+		var.accel_flags |= FB_ACCELF_TEXT;
+
+	if (comp_sync != -1) {
+		if (!comp_sync)
+			var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
+		else
+			var.sync |= FB_SYNC_COMP_HIGH_ACT;
+	}
+
+	if (var.yres == var.yres_virtual) {
+		u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
+		var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
+		if (var.yres_virtual < var.yres)
+			var.yres_virtual = var.yres;
+	}
+
+	ret = atyfb_check_var(&var, info);
+	if (ret) {
+		PRINTKE("can't set default video mode\n");
+		goto aty_init_exit;
+	}
+
+#ifdef CONFIG_FB_ATY_CT
+	if (!noaccel && M64_HAS(INTEGRATED))
+		aty_init_cursor(info);
+#endif /* CONFIG_FB_ATY_CT */
+	info->var = var;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret < 0)
+		goto aty_init_exit;
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		fb_dealloc_cmap(&info->cmap);
+		goto aty_init_exit;
+	}
+
+	fb_list = info;
+
+	PRINTKI("fb%d: %s frame buffer device on %s\n",
+		info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
+	return 0;
+
+aty_init_exit:
+	/* restore video mode */
+	aty_set_crtc(par, &par->saved_crtc);
+	par->pll_ops->set_pll(info, &par->saved_pll);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr_reg >= 0) {
+		mtrr_del(par->mtrr_reg, 0, 0);
+		par->mtrr_reg = -1;
+	}
+	if (par->mtrr_aper >= 0) {
+		mtrr_del(par->mtrr_aper, 0, 0);
+		par->mtrr_aper = -1;
+	}
+#endif
+	return ret;
+}
+
+#if defined(CONFIG_ATARI) && !defined(MODULE)
+static int store_video_par(char *video_str, unsigned char m64_num)
+{
+	char *p;
+	unsigned long vmembase, size, guiregbase;
+
+	PRINTKI("store_video_par() '%s' \n", video_str);
+
+	if (!(p = strsep(&video_str, ";")) || !*p)
+		goto mach64_invalid;
+	vmembase = simple_strtoul(p, NULL, 0);
+	if (!(p = strsep(&video_str, ";")) || !*p)
+		goto mach64_invalid;
+	size = simple_strtoul(p, NULL, 0);
+	if (!(p = strsep(&video_str, ";")) || !*p)
+		goto mach64_invalid;
+	guiregbase = simple_strtoul(p, NULL, 0);
+
+	phys_vmembase[m64_num] = vmembase;
+	phys_size[m64_num] = size;
+	phys_guiregbase[m64_num] = guiregbase;
+	PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
+		guiregbase);
+	return 0;
+
+ mach64_invalid:
+	phys_vmembase[m64_num] = 0;
+	return -1;
+}
+#endif /* CONFIG_ATARI && !MODULE */
+
+/*
+ * Blank the display.
+ */
+
+static int atyfb_blank(int blank, struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 gen_cntl;
+
+	if (par->lock_blank || par->asleep)
+		return 0;
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table && blank > FB_BLANK_NORMAL &&
+	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		pm &= ~PWR_BLON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+	}
+#endif
+
+	gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+	gen_cntl &= ~0x400004c;
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		break;
+	case FB_BLANK_NORMAL:
+		gen_cntl |= 0x4000040;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		gen_cntl |= 0x4000048;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		gen_cntl |= 0x4000044;
+		break;
+	case FB_BLANK_POWERDOWN:
+		gen_cntl |= 0x400004c;
+		break;
+	}
+	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
+	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		pm |= PWR_BLON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+	}
+#endif
+
+	return 0;
+}
+
+static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
+		       const struct atyfb_par *par)
+{
+	aty_st_8(DAC_W_INDEX, regno, par);
+	aty_st_8(DAC_DATA, red, par);
+	aty_st_8(DAC_DATA, green, par);
+	aty_st_8(DAC_DATA, blue, par);
+}
+
+/*
+ * Set a single color register. The values supplied are already
+ * rounded down to the hardware's capabilities (according to the
+ * entries in the var structure). Return != 0 for invalid regno.
+ * !! 4 & 8 =  PSEUDO, > 8 = DIRECTCOLOR
+ */
+
+static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	int i, depth;
+	u32 *pal = info->pseudo_palette;
+
+	depth = info->var.bits_per_pixel;
+	if (depth == 16)
+		depth = (info->var.green.length == 5) ? 15 : 16;
+
+	if (par->asleep)
+		return 0;
+
+	if (regno > 255 ||
+	    (depth == 16 && regno > 63) ||
+	    (depth == 15 && regno > 31))
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	par->palette[regno].red = red;
+	par->palette[regno].green = green;
+	par->palette[regno].blue = blue;
+
+	if (regno < 16) {
+		switch (depth) {
+		case 15:
+			pal[regno] = (regno << 10) | (regno << 5) | regno;
+			break;
+		case 16:
+			pal[regno] = (regno << 11) | (regno << 5) | regno;
+			break;
+		case 24:
+			pal[regno] = (regno << 16) | (regno << 8) | regno;
+			break;
+		case 32:
+			i = (regno << 8) | regno;
+			pal[regno] = (i << 16) | i;
+			break;
+		}
+	}
+
+	i = aty_ld_8(DAC_CNTL, par) & 0xfc;
+	if (M64_HAS(EXTRA_BRIGHT))
+		i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
+	aty_st_8(DAC_CNTL, i, par);
+	aty_st_8(DAC_MASK, 0xff, par);
+
+	if (M64_HAS(INTEGRATED)) {
+		if (depth == 16) {
+			if (regno < 32)
+				aty_st_pal(regno << 3, red,
+					   par->palette[regno << 1].green,
+					   blue, par);
+			red = par->palette[regno >> 1].red;
+			blue = par->palette[regno >> 1].blue;
+			regno <<= 2;
+		} else if (depth == 15) {
+			regno <<= 3;
+			for (i = 0; i < 8; i++)
+				aty_st_pal(regno + i, red, green, blue, par);
+		}
+	}
+	aty_st_pal(regno, red, green, blue, par);
+
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+
+#ifdef __sparc__
+
+static int atyfb_setup_sparc(struct pci_dev *pdev, struct fb_info *info,
+			     unsigned long addr)
+{
+	struct atyfb_par *par = info->par;
+	struct device_node *dp;
+	u32 mem, chip_id;
+	int i, j, ret;
+
+	/*
+	 * Map memory-mapped registers.
+	 */
+	par->ati_regbase = (void *)addr + 0x7ffc00UL;
+	info->fix.mmio_start = addr + 0x7ffc00UL;
+
+	/*
+	 * Map in big-endian aperture.
+	 */
+	info->screen_base = (char *) (addr + 0x800000UL);
+	info->fix.smem_start = addr + 0x800000UL;
+
+	/*
+	 * Figure mmap addresses from PCI config space.
+	 * Split Framebuffer in big- and little-endian halfs.
+	 */
+	for (i = 0; i < 6 && pdev->resource[i].start; i++)
+		/* nothing */ ;
+	j = i + 4;
+
+	par->mmap_map = kcalloc(j, sizeof(*par->mmap_map), GFP_ATOMIC);
+	if (!par->mmap_map) {
+		PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
+		struct resource *rp = &pdev->resource[i];
+		int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
+		unsigned long base;
+		u32 size, pbase;
+
+		base = rp->start;
+
+		io = (rp->flags & IORESOURCE_IO);
+
+		size = rp->end - base + 1;
+
+		pci_read_config_dword(pdev, breg, &pbase);
+
+		if (io)
+			size &= ~1;
+
+		/*
+		 * Map the framebuffer a second time, this time without
+		 * the braindead _PAGE_IE setting. This is used by the
+		 * fixed Xserver, but we need to maintain the old mapping
+		 * to stay compatible with older ones...
+		 */
+		if (base == addr) {
+			par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
+			par->mmap_map[j].poff = base & PAGE_MASK;
+			par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+			par->mmap_map[j].prot_mask = _PAGE_CACHE;
+			par->mmap_map[j].prot_flag = _PAGE_E;
+			j++;
+		}
+
+		/*
+		 * Here comes the old framebuffer mapping with _PAGE_IE
+		 * set for the big endian half of the framebuffer...
+		 */
+		if (base == addr) {
+			par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
+			par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
+			par->mmap_map[j].size = 0x800000;
+			par->mmap_map[j].prot_mask = _PAGE_CACHE;
+			par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
+			size -= 0x800000;
+			j++;
+		}
+
+		par->mmap_map[j].voff = pbase & PAGE_MASK;
+		par->mmap_map[j].poff = base & PAGE_MASK;
+		par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+		par->mmap_map[j].prot_mask = _PAGE_CACHE;
+		par->mmap_map[j].prot_flag = _PAGE_E;
+		j++;
+	}
+
+	ret = correct_chipset(par);
+	if (ret)
+		return ret;
+
+	if (IS_XL(pdev->device)) {
+		/*
+		 * Fix PROMs idea of MEM_CNTL settings...
+		 */
+		mem = aty_ld_le32(MEM_CNTL, par);
+		chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
+		if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
+			switch (mem & 0x0f) {
+			case 3:
+				mem = (mem & ~(0x0f)) | 2;
+				break;
+			case 7:
+				mem = (mem & ~(0x0f)) | 3;
+				break;
+			case 9:
+				mem = (mem & ~(0x0f)) | 4;
+				break;
+			case 11:
+				mem = (mem & ~(0x0f)) | 5;
+				break;
+			default:
+				break;
+			}
+			if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM)
+				mem &= ~(0x00700000);
+		}
+		mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
+		aty_st_le32(MEM_CNTL, mem, par);
+	}
+
+	dp = pci_device_to_OF_node(pdev);
+	if (dp == of_console_device) {
+		struct fb_var_screeninfo *var = &default_var;
+		unsigned int N, P, Q, M, T, R;
+		u32 v_total, h_total;
+		struct crtc crtc;
+		u8 pll_regs[16];
+		u8 clock_cntl;
+
+		crtc.vxres = of_getintprop_default(dp, "width", 1024);
+		crtc.vyres = of_getintprop_default(dp, "height", 768);
+		var->bits_per_pixel = of_getintprop_default(dp, "depth", 8);
+		var->xoffset = var->yoffset = 0;
+		crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
+		crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
+		crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
+		crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
+		crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+		aty_crtc_to_var(&crtc, var);
+
+		h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+		v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
+
+		/*
+		 * Read the PLL to figure actual Refresh Rate.
+		 */
+		clock_cntl = aty_ld_8(CLOCK_CNTL, par);
+		/* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
+		for (i = 0; i < 16; i++)
+			pll_regs[i] = aty_ld_pll_ct(i, par);
+
+		/*
+		 * PLL Reference Divider M:
+		 */
+		M = pll_regs[2];
+
+		/*
+		 * PLL Feedback Divider N (Dependent on CLOCK_CNTL):
+		 */
+		N = pll_regs[7 + (clock_cntl & 3)];
+
+		/*
+		 * PLL Post Divider P (Dependent on CLOCK_CNTL):
+		 */
+		P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
+
+		/*
+		 * PLL Divider Q:
+		 */
+		Q = N / P;
+
+		/*
+		 * Target Frequency:
+		 *
+		 *      T * M
+		 * Q = -------
+		 *      2 * R
+		 *
+		 * where R is XTALIN (= 14318 or 29498 kHz).
+		 */
+		if (IS_XL(pdev->device))
+			R = 29498;
+		else
+			R = 14318;
+
+		T = 2 * Q * R / M;
+
+		default_var.pixclock = 1000000000 / T;
+	}
+
+	return 0;
+}
+
+#else /* __sparc__ */
+
+#ifdef __i386__
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+{
+	u32 driv_inf_tab, sig;
+	u16 lcd_ofs;
+
+	/*
+	 * To support an LCD panel, we should know it's dimensions and
+	 *  it's desired pixel clock.
+	 * There are two ways to do it:
+	 *  - Check the startup video mode and calculate the panel
+	 *    size from it. This is unreliable.
+	 *  - Read it from the driver information table in the video BIOS.
+	 */
+	/* Address of driver information table is at offset 0x78. */
+	driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
+
+	/* Check for the driver information table signature. */
+	sig = *(u32 *)driv_inf_tab;
+	if ((sig == 0x54504c24) || /* Rage LT pro */
+	    (sig == 0x544d5224) || /* Rage mobility */
+	    (sig == 0x54435824) || /* Rage XC */
+	    (sig == 0x544c5824)) { /* Rage XL */
+		PRINTKI("BIOS contains driver information table.\n");
+		lcd_ofs = *(u16 *)(driv_inf_tab + 10);
+		par->lcd_table = 0;
+		if (lcd_ofs != 0)
+			par->lcd_table = bios_base + lcd_ofs;
+	}
+
+	if (par->lcd_table != 0) {
+		char model[24];
+		char strbuf[16];
+		char refresh_rates_buf[100];
+		int id, tech, f, i, m, default_refresh_rate;
+		char *txtcolour;
+		char *txtmonitor;
+		char *txtdual;
+		char *txtformat;
+		u16 width, height, panel_type, refresh_rates;
+		u16 *lcdmodeptr;
+		u32 format;
+		u8 lcd_refresh_rates[16] = { 50, 56, 60, 67, 70, 72, 75, 76, 85,
+					     90, 100, 120, 140, 150, 160, 200 };
+		/*
+		 * The most important information is the panel size at
+		 * offset 25 and 27, but there's some other nice information
+		 * which we print to the screen.
+		 */
+		id = *(u8 *)par->lcd_table;
+		strncpy(model, (char *)par->lcd_table+1, 24);
+		model[23] = 0;
+
+		width = par->lcd_width = *(u16 *)(par->lcd_table+25);
+		height = par->lcd_height = *(u16 *)(par->lcd_table+27);
+		panel_type = *(u16 *)(par->lcd_table+29);
+		if (panel_type & 1)
+			txtcolour = "colour";
+		else
+			txtcolour = "monochrome";
+		if (panel_type & 2)
+			txtdual = "dual (split) ";
+		else
+			txtdual = "";
+		tech = (panel_type >> 2) & 63;
+		switch (tech) {
+		case 0:
+			txtmonitor = "passive matrix";
+			break;
+		case 1:
+			txtmonitor = "active matrix";
+			break;
+		case 2:
+			txtmonitor = "active addressed STN";
+			break;
+		case 3:
+			txtmonitor = "EL";
+			break;
+		case 4:
+			txtmonitor = "plasma";
+			break;
+		default:
+			txtmonitor = "unknown";
+		}
+		format = *(u32 *)(par->lcd_table+57);
+		if (tech == 0 || tech == 2) {
+			switch (format & 7) {
+			case 0:
+				txtformat = "12 bit interface";
+				break;
+			case 1:
+				txtformat = "16 bit interface";
+				break;
+			case 2:
+				txtformat = "24 bit interface";
+				break;
+			default:
+				txtformat = "unknown format";
+			}
+		} else {
+			switch (format & 7) {
+			case 0:
+				txtformat = "8 colours";
+				break;
+			case 1:
+				txtformat = "512 colours";
+				break;
+			case 2:
+				txtformat = "4096 colours";
+				break;
+			case 4:
+				txtformat = "262144 colours (LT mode)";
+				break;
+			case 5:
+				txtformat = "16777216 colours";
+				break;
+			case 6:
+				txtformat = "262144 colours (FDPI-2 mode)";
+				break;
+			default:
+				txtformat = "unknown format";
+			}
+		}
+		PRINTKI("%s%s %s monitor detected: %s\n",
+			txtdual, txtcolour, txtmonitor, model);
+		PRINTKI("       id=%d, %dx%d pixels, %s\n",
+			id, width, height, txtformat);
+		refresh_rates_buf[0] = 0;
+		refresh_rates = *(u16 *)(par->lcd_table+62);
+		m = 1;
+		f = 0;
+		for (i = 0; i < 16; i++) {
+			if (refresh_rates & m) {
+				if (f == 0) {
+					sprintf(strbuf, "%d",
+						lcd_refresh_rates[i]);
+					f++;
+				} else {
+					sprintf(strbuf, ",%d",
+						lcd_refresh_rates[i]);
+				}
+				strcat(refresh_rates_buf, strbuf);
+			}
+			m = m << 1;
+		}
+		default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
+		PRINTKI("       supports refresh rates [%s], default %d Hz\n",
+			refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
+		par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
+		/*
+		 * We now need to determine the crtc parameters for the
+		 * LCD monitor. This is tricky, because they are not stored
+		 * individually in the BIOS. Instead, the BIOS contains a
+		 * table of display modes that work for this monitor.
+		 *
+		 * The idea is that we search for a mode of the same dimensions
+		 * as the dimensions of the LCD monitor. Say our LCD monitor
+		 * is 800x600 pixels, we search for a 800x600 monitor.
+		 * The CRTC parameters we find here are the ones that we need
+		 * to use to simulate other resolutions on the LCD screen.
+		 */
+		lcdmodeptr = (u16 *)(par->lcd_table + 64);
+		while (*lcdmodeptr != 0) {
+			u32 modeptr;
+			u16 mwidth, mheight, lcd_hsync_start, lcd_vsync_start;
+			modeptr = bios_base + *lcdmodeptr;
+
+			mwidth = *((u16 *)(modeptr+0));
+			mheight = *((u16 *)(modeptr+2));
+
+			if (mwidth == width && mheight == height) {
+				par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
+				par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
+				par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
+				lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
+				par->lcd_hsync_dly = (*((u16 *)(modeptr+21)) >> 9) & 7;
+				par->lcd_hsync_len = *((u8 *)(modeptr+23)) & 63;
+
+				par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
+				par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
+				lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
+				par->lcd_vsync_len = (*((u16 *)(modeptr+28)) >> 11) & 31;
+
+				par->lcd_htotal = (par->lcd_htotal + 1) * 8;
+				par->lcd_hdisp = (par->lcd_hdisp + 1) * 8;
+				lcd_hsync_start = (lcd_hsync_start + 1) * 8;
+				par->lcd_hsync_len = par->lcd_hsync_len * 8;
+
+				par->lcd_vtotal++;
+				par->lcd_vdisp++;
+				lcd_vsync_start++;
+
+				par->lcd_right_margin = lcd_hsync_start - par->lcd_hdisp;
+				par->lcd_lower_margin = lcd_vsync_start - par->lcd_vdisp;
+				par->lcd_hblank_len = par->lcd_htotal - par->lcd_hdisp;
+				par->lcd_vblank_len = par->lcd_vtotal - par->lcd_vdisp;
+				break;
+			}
+
+			lcdmodeptr++;
+		}
+		if (*lcdmodeptr == 0) {
+			PRINTKE("LCD monitor CRTC parameters not found!!!\n");
+			/* To do: Switch to CRT if possible. */
+		} else {
+			PRINTKI("       LCD CRTC parameters: %d.%d  %d %d %d %d  %d %d %d %d\n",
+				1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
+				par->lcd_hdisp,
+				par->lcd_hdisp + par->lcd_right_margin,
+				par->lcd_hdisp + par->lcd_right_margin
+					+ par->lcd_hsync_dly + par->lcd_hsync_len,
+				par->lcd_htotal,
+				par->lcd_vdisp,
+				par->lcd_vdisp + par->lcd_lower_margin,
+				par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
+				par->lcd_vtotal);
+			PRINTKI("                          : %d %d %d %d %d %d %d %d %d\n",
+				par->lcd_pixclock,
+				par->lcd_hblank_len - (par->lcd_right_margin +
+					par->lcd_hsync_dly + par->lcd_hsync_len),
+				par->lcd_hdisp,
+				par->lcd_right_margin,
+				par->lcd_hsync_len,
+				par->lcd_vblank_len - (par->lcd_lower_margin + par->lcd_vsync_len),
+				par->lcd_vdisp,
+				par->lcd_lower_margin,
+				par->lcd_vsync_len);
+		}
+	}
+}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+
+static int init_from_bios(struct atyfb_par *par)
+{
+	u32 bios_base, rom_addr;
+	int ret;
+
+	rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, par) & 0x7f) << 11);
+	bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
+
+	/* The BIOS starts with 0xaa55. */
+	if (*((u16 *)bios_base) == 0xaa55) {
+
+		u8 *bios_ptr;
+		u16 rom_table_offset, freq_table_offset;
+		PLL_BLOCK_MACH64 pll_block;
+
+		PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
+
+		/* check for frequncy table */
+		bios_ptr = (u8*)bios_base;
+		rom_table_offset = (u16)(bios_ptr[0x48] | (bios_ptr[0x49] << 8));
+		freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
+		memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
+
+		PRINTKI("BIOS frequency table:\n");
+		PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
+			pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
+			pll_block.ref_freq, pll_block.ref_divider);
+		PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
+			pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
+			pll_block.XCLK_max_freq, pll_block.SCLK_freq);
+
+		par->pll_limits.pll_min = pll_block.PCLK_min_freq/100;
+		par->pll_limits.pll_max = pll_block.PCLK_max_freq/100;
+		par->pll_limits.ref_clk = pll_block.ref_freq/100;
+		par->pll_limits.ref_div = pll_block.ref_divider;
+		par->pll_limits.sclk = pll_block.SCLK_freq/100;
+		par->pll_limits.mclk = pll_block.MCLK_max_freq/100;
+		par->pll_limits.mclk_pm = pll_block.MCLK_pwd/100;
+		par->pll_limits.xclk = pll_block.XCLK_max_freq/100;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+		aty_init_lcd(par, bios_base);
+#endif
+		ret = 0;
+	} else {
+		PRINTKE("no BIOS frequency table found, use parameters\n");
+		ret = -ENXIO;
+	}
+	iounmap((void __iomem *)bios_base);
+
+	return ret;
+}
+#endif /* __i386__ */
+
+static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
+			       unsigned long addr)
+{
+	struct atyfb_par *par = info->par;
+	u16 tmp;
+	unsigned long raddr;
+	struct resource *rrp;
+	int ret = 0;
+
+	raddr = addr + 0x7ff000UL;
+	rrp = &pdev->resource[2];
+	if ((rrp->flags & IORESOURCE_MEM) &&
+	    request_mem_region(rrp->start, resource_size(rrp), "atyfb")) {
+		par->aux_start = rrp->start;
+		par->aux_size = resource_size(rrp);
+		raddr = rrp->start;
+		PRINTKI("using auxiliary register aperture\n");
+	}
+
+	info->fix.mmio_start = raddr;
+	par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
+	if (par->ati_regbase == NULL)
+		return -ENOMEM;
+
+	info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
+	par->ati_regbase += par->aux_start ? 0x400 : 0xc00;
+
+	/*
+	 * Enable memory-space accesses using config-space
+	 * command register.
+	 */
+	pci_read_config_word(pdev, PCI_COMMAND, &tmp);
+	if (!(tmp & PCI_COMMAND_MEMORY)) {
+		tmp |= PCI_COMMAND_MEMORY;
+		pci_write_config_word(pdev, PCI_COMMAND, tmp);
+	}
+#ifdef __BIG_ENDIAN
+	/* Use the big-endian aperture */
+	addr += 0x800000;
+#endif
+
+	/* Map in frame buffer */
+	info->fix.smem_start = addr;
+	info->screen_base = ioremap(addr, 0x800000);
+	if (info->screen_base == NULL) {
+		ret = -ENOMEM;
+		goto atyfb_setup_generic_fail;
+	}
+
+	ret = correct_chipset(par);
+	if (ret)
+		goto atyfb_setup_generic_fail;
+#ifdef __i386__
+	ret = init_from_bios(par);
+	if (ret)
+		goto atyfb_setup_generic_fail;
+#endif
+	if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
+		par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
+	else
+		par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
+
+	/* according to ATI, we should use clock 3 for acelerated mode */
+	par->clk_wr_offset = 3;
+
+	return 0;
+
+atyfb_setup_generic_fail:
+	iounmap(par->ati_regbase);
+	par->ati_regbase = NULL;
+	if (info->screen_base) {
+		iounmap(info->screen_base);
+		info->screen_base = NULL;
+	}
+	return ret;
+}
+
+#endif /* !__sparc__ */
+
+static int atyfb_pci_probe(struct pci_dev *pdev,
+			   const struct pci_device_id *ent)
+{
+	unsigned long addr, res_start, res_size;
+	struct fb_info *info;
+	struct resource *rp;
+	struct atyfb_par *par;
+	int rc = -ENOMEM;
+
+	/* Enable device in PCI config */
+	if (pci_enable_device(pdev)) {
+		PRINTKE("Cannot enable PCI device\n");
+		return -ENXIO;
+	}
+
+	/* Find which resource to use */
+	rp = &pdev->resource[0];
+	if (rp->flags & IORESOURCE_IO)
+		rp = &pdev->resource[1];
+	addr = rp->start;
+	if (!addr)
+		return -ENXIO;
+
+	/* Reserve space */
+	res_start = rp->start;
+	res_size = resource_size(rp);
+	if (!request_mem_region(res_start, res_size, "atyfb"))
+		return -EBUSY;
+
+	/* Allocate framebuffer */
+	info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
+	if (!info) {
+		PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
+		return -ENOMEM;
+	}
+	par = info->par;
+	info->fix = atyfb_fix;
+	info->device = &pdev->dev;
+	par->pci_id = pdev->device;
+	par->res_start = res_start;
+	par->res_size = res_size;
+	par->irq = pdev->irq;
+	par->pdev = pdev;
+
+	/* Setup "info" structure */
+#ifdef __sparc__
+	rc = atyfb_setup_sparc(pdev, info, addr);
+#else
+	rc = atyfb_setup_generic(pdev, info, addr);
+#endif
+	if (rc)
+		goto err_release_mem;
+
+	pci_set_drvdata(pdev, info);
+
+	/* Init chip & register framebuffer */
+	rc = aty_init(info);
+	if (rc)
+		goto err_release_io;
+
+#ifdef __sparc__
+	/*
+	 * Add /dev/fb mmap values.
+	 */
+	par->mmap_map[0].voff = 0x8000000000000000UL;
+	par->mmap_map[0].poff = (unsigned long) info->screen_base & PAGE_MASK;
+	par->mmap_map[0].size = info->fix.smem_len;
+	par->mmap_map[0].prot_mask = _PAGE_CACHE;
+	par->mmap_map[0].prot_flag = _PAGE_E;
+	par->mmap_map[1].voff = par->mmap_map[0].voff + info->fix.smem_len;
+	par->mmap_map[1].poff = (long)par->ati_regbase & PAGE_MASK;
+	par->mmap_map[1].size = PAGE_SIZE;
+	par->mmap_map[1].prot_mask = _PAGE_CACHE;
+	par->mmap_map[1].prot_flag = _PAGE_E;
+#endif /* __sparc__ */
+
+	mutex_lock(&reboot_lock);
+	if (!reboot_info)
+		reboot_info = info;
+	mutex_unlock(&reboot_lock);
+
+	return 0;
+
+err_release_io:
+#ifdef __sparc__
+	kfree(par->mmap_map);
+#else
+	if (par->ati_regbase)
+		iounmap(par->ati_regbase);
+	if (info->screen_base)
+		iounmap(info->screen_base);
+#endif
+err_release_mem:
+	if (par->aux_start)
+		release_mem_region(par->aux_start, par->aux_size);
+
+	release_mem_region(par->res_start, par->res_size);
+	framebuffer_release(info);
+
+	return rc;
+}
+
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_ATARI
+
+static int __init atyfb_atari_probe(void)
+{
+	struct atyfb_par *par;
+	struct fb_info *info;
+	int m64_num;
+	u32 clock_r;
+	int num_found = 0;
+
+	for (m64_num = 0; m64_num < mach64_count; m64_num++) {
+		if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
+		    !phys_guiregbase[m64_num]) {
+			PRINTKI("phys_*[%d] parameters not set => "
+				"returning early. \n", m64_num);
+			continue;
+		}
+
+		info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
+		if (!info) {
+			PRINTKE("atyfb_atari_probe() can't alloc fb_info\n");
+			return -ENOMEM;
+		}
+		par = info->par;
+
+		info->fix = atyfb_fix;
+
+		par->irq = (unsigned int) -1; /* something invalid */
+
+		/*
+		 * Map the video memory (physical address given)
+		 * to somewhere in the kernel address space.
+		 */
+		info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
+		info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
+		par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
+						0xFC00ul;
+		info->fix.mmio_start = (unsigned long)par->ati_regbase; /* Fake! */
+
+		aty_st_le32(CLOCK_CNTL, 0x12345678, par);
+		clock_r = aty_ld_le32(CLOCK_CNTL, par);
+
+		switch (clock_r & 0x003F) {
+		case 0x12:
+			par->clk_wr_offset = 3; /*  */
+			break;
+		case 0x34:
+			par->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
+			break;
+		case 0x16:
+			par->clk_wr_offset = 1; /*  */
+			break;
+		case 0x38:
+			par->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
+			break;
+		}
+
+		/* Fake pci_id for correct_chipset() */
+		switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) {
+		case 0x00d7:
+			par->pci_id = PCI_CHIP_MACH64GX;
+			break;
+		case 0x0057:
+			par->pci_id = PCI_CHIP_MACH64CX;
+			break;
+		default:
+			break;
+		}
+
+		if (correct_chipset(par) || aty_init(info)) {
+			iounmap(info->screen_base);
+			iounmap(par->ati_regbase);
+			framebuffer_release(info);
+		} else {
+			num_found++;
+		}
+	}
+
+	return num_found ? 0 : -ENXIO;
+}
+
+#endif /* CONFIG_ATARI */
+
+#ifdef CONFIG_PCI
+
+static void atyfb_remove(struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	/* restore video mode */
+	aty_set_crtc(par, &par->saved_crtc);
+	par->pll_ops->set_pll(info, &par->saved_pll);
+
+	unregister_framebuffer(info);
+
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+	if (M64_HAS(MOBIL_BUS))
+		aty_bl_exit(info->bl_dev);
+#endif
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr_reg >= 0) {
+		mtrr_del(par->mtrr_reg, 0, 0);
+		par->mtrr_reg = -1;
+	}
+	if (par->mtrr_aper >= 0) {
+		mtrr_del(par->mtrr_aper, 0, 0);
+		par->mtrr_aper = -1;
+	}
+#endif
+#ifndef __sparc__
+	if (par->ati_regbase)
+		iounmap(par->ati_regbase);
+	if (info->screen_base)
+		iounmap(info->screen_base);
+#ifdef __BIG_ENDIAN
+	if (info->sprite.addr)
+		iounmap(info->sprite.addr);
+#endif
+#endif
+#ifdef __sparc__
+	kfree(par->mmap_map);
+#endif
+	if (par->aux_start)
+		release_mem_region(par->aux_start, par->aux_size);
+
+	if (par->res_start)
+		release_mem_region(par->res_start, par->res_size);
+
+	framebuffer_release(info);
+}
+
+
+static void atyfb_pci_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+
+	mutex_lock(&reboot_lock);
+	if (reboot_info == info)
+		reboot_info = NULL;
+	mutex_unlock(&reboot_lock);
+
+	atyfb_remove(info);
+}
+
+static struct pci_device_id atyfb_pci_tbl[] = {
+#ifdef CONFIG_FB_ATY_GX
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) },
+#endif /* CONFIG_FB_ATY_GX */
+
+#ifdef CONFIG_FB_ATY_CT
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) },
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) },
+#endif /* CONFIG_FB_ATY_CT */
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl);
+
+static struct pci_driver atyfb_driver = {
+	.name		= "atyfb",
+	.id_table	= atyfb_pci_tbl,
+	.probe		= atyfb_pci_probe,
+	.remove		= atyfb_pci_remove,
+#ifdef CONFIG_PM
+	.suspend	= atyfb_pci_suspend,
+	.resume		= atyfb_pci_resume,
+#endif /* CONFIG_PM */
+};
+
+#endif /* CONFIG_PCI */
+
+#ifndef MODULE
+static int __init atyfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "noaccel", 7)) {
+			noaccel = 1;
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else if (!strncmp(this_opt, "vram:", 5))
+			vram = simple_strtoul(this_opt + 5, NULL, 0);
+		else if (!strncmp(this_opt, "pll:", 4))
+			pll = simple_strtoul(this_opt + 4, NULL, 0);
+		else if (!strncmp(this_opt, "mclk:", 5))
+			mclk = simple_strtoul(this_opt + 5, NULL, 0);
+		else if (!strncmp(this_opt, "xclk:", 5))
+			xclk = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "comp_sync:", 10))
+			comp_sync = simple_strtoul(this_opt+10, NULL, 0);
+		else if (!strncmp(this_opt, "backlight:", 10))
+			backlight = simple_strtoul(this_opt+10, NULL, 0);
+#ifdef CONFIG_PPC
+		else if (!strncmp(this_opt, "vmode:", 6)) {
+			unsigned int vmode =
+			    simple_strtoul(this_opt + 6, NULL, 0);
+			if (vmode > 0 && vmode <= VMODE_MAX)
+				default_vmode = vmode;
+		} else if (!strncmp(this_opt, "cmode:", 6)) {
+			unsigned int cmode =
+			    simple_strtoul(this_opt + 6, NULL, 0);
+			switch (cmode) {
+			case 0:
+			case 8:
+				default_cmode = CMODE_8;
+				break;
+			case 15:
+			case 16:
+				default_cmode = CMODE_16;
+				break;
+			case 24:
+			case 32:
+				default_cmode = CMODE_32;
+				break;
+			}
+		}
+#endif
+#ifdef CONFIG_ATARI
+		/*
+		 * Why do we need this silly Mach64 argument?
+		 * We are already here because of mach64= so its redundant.
+		 */
+		else if (MACH_IS_ATARI
+			 && (!strncmp(this_opt, "Mach64:", 7))) {
+			static unsigned char m64_num;
+			static char mach64_str[80];
+			strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
+			if (!store_video_par(mach64_str, m64_num)) {
+				m64_num++;
+				mach64_count = m64_num;
+			}
+		}
+#endif
+		else
+			mode = this_opt;
+	}
+	return 0;
+}
+#endif  /*  MODULE  */
+
+static int atyfb_reboot_notify(struct notifier_block *nb,
+			       unsigned long code, void *unused)
+{
+	struct atyfb_par *par;
+
+	if (code != SYS_RESTART)
+		return NOTIFY_DONE;
+
+	mutex_lock(&reboot_lock);
+
+	if (!reboot_info)
+		goto out;
+
+	if (!lock_fb_info(reboot_info))
+		goto out;
+
+	par = reboot_info->par;
+
+	/*
+	 * HP OmniBook 500's BIOS doesn't like the state of the
+	 * hardware after atyfb has been used. Restore the hardware
+	 * to the original state to allow successful reboots.
+	 */
+	aty_set_crtc(par, &par->saved_crtc);
+	par->pll_ops->set_pll(reboot_info, &par->saved_pll);
+
+	unlock_fb_info(reboot_info);
+ out:
+	mutex_unlock(&reboot_lock);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block atyfb_reboot_notifier = {
+	.notifier_call = atyfb_reboot_notify,
+};
+
+static const struct dmi_system_id atyfb_reboot_ids[] = {
+	{
+		.ident = "HP OmniBook 500",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"),
+		},
+	},
+
+	{ }
+};
+
+static int __init atyfb_init(void)
+{
+	int err1 = 1, err2 = 1;
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("atyfb", &option))
+		return -ENODEV;
+	atyfb_setup(option);
+#endif
+
+#ifdef CONFIG_PCI
+	err1 = pci_register_driver(&atyfb_driver);
+#endif
+#ifdef CONFIG_ATARI
+	err2 = atyfb_atari_probe();
+#endif
+
+	if (err1 && err2)
+		return -ENODEV;
+
+	if (dmi_check_system(atyfb_reboot_ids))
+		register_reboot_notifier(&atyfb_reboot_notifier);
+
+	return 0;
+}
+
+static void __exit atyfb_exit(void)
+{
+	if (dmi_check_system(atyfb_reboot_ids))
+		unregister_reboot_notifier(&atyfb_reboot_notifier);
+
+#ifdef CONFIG_PCI
+	pci_unregister_driver(&atyfb_driver);
+#endif
+}
+
+module_init(atyfb_init);
+module_exit(atyfb_exit);
+
+MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
+MODULE_LICENSE("GPL");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram, "int: override size of video ram");
+module_param(pll, int, 0);
+MODULE_PARM_DESC(pll, "int: override video clock");
+module_param(mclk, int, 0);
+MODULE_PARM_DESC(mclk, "int: override memory clock");
+module_param(xclk, int, 0);
+MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
+module_param(comp_sync, int, 0);
+MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high (1)");
+module_param(mode, charp, 0);
+MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
+#endif
diff --git a/drivers/video/fbdev/aty/mach64_accel.c b/drivers/video/fbdev/aty/mach64_accel.c
new file mode 100644
index 000000000000..182bd680141f
--- /dev/null
+++ b/drivers/video/fbdev/aty/mach64_accel.c
@@ -0,0 +1,430 @@
+
+/*
+ *  ATI Mach64 Hardware Acceleration
+ */
+
+#include <linux/delay.h>
+#include <asm/unaligned.h>
+#include <linux/fb.h>
+#include <video/mach64.h>
+#include "atyfb.h"
+
+    /*
+     *  Generic Mach64 routines
+     */
+
+/* this is for DMA GUI engine! work in progress */
+typedef struct {
+	u32 frame_buf_offset;
+	u32 system_mem_addr;
+	u32 command;
+	u32 reserved;
+} BM_DESCRIPTOR_ENTRY;
+
+#define LAST_DESCRIPTOR (1 << 31)
+#define SYSTEM_TO_FRAME_BUFFER 0
+
+static u32 rotation24bpp(u32 dx, u32 direction)
+{
+	u32 rotation;
+	if (direction & DST_X_LEFT_TO_RIGHT) {
+		rotation = (dx / 4) % 6;
+	} else {
+		rotation = ((dx + 2) / 4) % 6;
+	}
+
+	return ((rotation << 8) | DST_24_ROTATION_ENABLE);
+}
+
+void aty_reset_engine(const struct atyfb_par *par)
+{
+	/* reset engine */
+	aty_st_le32(GEN_TEST_CNTL,
+		aty_ld_le32(GEN_TEST_CNTL, par) &
+		~(GUI_ENGINE_ENABLE | HWCURSOR_ENABLE), par);
+	/* enable engine */
+	aty_st_le32(GEN_TEST_CNTL,
+		aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par);
+	/* ensure engine is not locked up by clearing any FIFO or */
+	/* HOST errors */
+	aty_st_le32(BUS_CNTL,
+		aty_ld_le32(BUS_CNTL, par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK, par);
+}
+
+static void reset_GTC_3D_engine(const struct atyfb_par *par)
+{
+	aty_st_le32(SCALE_3D_CNTL, 0xc0, par);
+	mdelay(GTC_3D_RESET_DELAY);
+	aty_st_le32(SETUP_CNTL, 0x00, par);
+	mdelay(GTC_3D_RESET_DELAY);
+	aty_st_le32(SCALE_3D_CNTL, 0x00, par);
+	mdelay(GTC_3D_RESET_DELAY);
+}
+
+void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
+{
+	u32 pitch_value;
+	u32 vxres;
+
+	/* determine modal information from global mode structure */
+	pitch_value = info->fix.line_length / (info->var.bits_per_pixel / 8);
+	vxres = info->var.xres_virtual;
+
+	if (info->var.bits_per_pixel == 24) {
+		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
+		/* horizontal coordinates and widths must be adjusted */
+		pitch_value *= 3;
+		vxres *= 3;
+	}
+
+	/* On GTC (RagePro), we need to reset the 3D engine before */
+	if (M64_HAS(RESET_3D))
+		reset_GTC_3D_engine(par);
+
+	/* Reset engine, enable, and clear any engine errors */
+	aty_reset_engine(par);
+	/* Ensure that vga page pointers are set to zero - the upper */
+	/* page pointers are set to 1 to handle overflows in the */
+	/* lower page */
+	aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, par);
+	aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, par);
+
+	/* ---- Setup standard engine context ---- */
+
+	/* All GUI registers here are FIFOed - therefore, wait for */
+	/* the appropriate number of empty FIFO entries */
+	wait_for_fifo(14, par);
+
+	/* enable all registers to be loaded for context loads */
+	aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, par);
+
+	/* set destination pitch to modal pitch, set offset to zero */
+	aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, par);
+
+	/* zero these registers (set them to a known state) */
+	aty_st_le32(DST_Y_X, 0, par);
+	aty_st_le32(DST_HEIGHT, 0, par);
+	aty_st_le32(DST_BRES_ERR, 0, par);
+	aty_st_le32(DST_BRES_INC, 0, par);
+	aty_st_le32(DST_BRES_DEC, 0, par);
+
+	/* set destination drawing attributes */
+	aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
+		    DST_X_LEFT_TO_RIGHT, par);
+
+	/* set source pitch to modal pitch, set offset to zero */
+	aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, par);
+
+	/* set these registers to a known state */
+	aty_st_le32(SRC_Y_X, 0, par);
+	aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, par);
+	aty_st_le32(SRC_Y_X_START, 0, par);
+	aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, par);
+
+	/* set source pixel retrieving attributes */
+	aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, par);
+
+	/* set host attributes */
+	wait_for_fifo(13, par);
+	aty_st_le32(HOST_CNTL, 0, par);
+
+	/* set pattern attributes */
+	aty_st_le32(PAT_REG0, 0, par);
+	aty_st_le32(PAT_REG1, 0, par);
+	aty_st_le32(PAT_CNTL, 0, par);
+
+	/* set scissors to modal size */
+	aty_st_le32(SC_LEFT, 0, par);
+	aty_st_le32(SC_TOP, 0, par);
+	aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par);
+	aty_st_le32(SC_RIGHT, vxres - 1, par);
+
+	/* set background color to minimum value (usually BLACK) */
+	aty_st_le32(DP_BKGD_CLR, 0, par);
+
+	/* set foreground color to maximum value (usually WHITE) */
+	aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, par);
+
+	/* set write mask to effect all pixel bits */
+	aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
+
+	/* set foreground mix to overpaint and background mix to */
+	/* no-effect */
+	aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, par);
+
+	/* set primary source pixel channel to foreground color */
+	/* register */
+	aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, par);
+
+	/* set compare functionality to false (no-effect on */
+	/* destination) */
+	wait_for_fifo(3, par);
+	aty_st_le32(CLR_CMP_CLR, 0, par);
+	aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, par);
+	aty_st_le32(CLR_CMP_CNTL, 0, par);
+
+	/* set pixel depth */
+	wait_for_fifo(2, par);
+	aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, par);
+	aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, par);
+
+	wait_for_fifo(5, par);
+ 	aty_st_le32(SCALE_3D_CNTL, 0, par);
+	aty_st_le32(Z_CNTL, 0, par);
+	aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, par) & ~0x20,
+		    par);
+	aty_st_le32(GUI_TRAJ_CNTL, 0x100023, par);
+
+	/* insure engine is idle before leaving */
+	wait_for_idle(par);
+}
+
+    /*
+     *  Accelerated functions
+     */
+
+static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
+			     struct atyfb_par *par)
+{
+	/* perform rectangle fill */
+	wait_for_fifo(2, par);
+	aty_st_le32(DST_Y_X, (x << 16) | y, par);
+	aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, par);
+	par->blitter_may_be_busy = 1;
+}
+
+void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 dy = area->dy, sy = area->sy, direction = DST_LAST_PEL;
+	u32 sx = area->sx, dx = area->dx, width = area->width, rotation = 0;
+
+	if (par->asleep)
+		return;
+	if (!area->width || !area->height)
+		return;
+	if (!par->accel_flags) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	if (info->var.bits_per_pixel == 24) {
+		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
+		/* horizontal coordinates and widths must be adjusted */
+		sx *= 3;
+		dx *= 3;
+		width *= 3;
+	}
+
+	if (area->sy < area->dy) {
+		dy += area->height - 1;
+		sy += area->height - 1;
+	} else
+		direction |= DST_Y_TOP_TO_BOTTOM;
+
+	if (sx < dx) {
+		dx += width - 1;
+		sx += width - 1;
+	} else
+		direction |= DST_X_LEFT_TO_RIGHT;
+
+	if (info->var.bits_per_pixel == 24) {
+		rotation = rotation24bpp(dx, direction);
+	}
+
+	wait_for_fifo(4, par);
+	aty_st_le32(DP_SRC, FRGD_SRC_BLIT, par);
+	aty_st_le32(SRC_Y_X, (sx << 16) | sy, par);
+	aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | area->height, par);
+	aty_st_le32(DST_CNTL, direction | rotation, par);
+	draw_rect(dx, dy, width, area->height, par);
+}
+
+void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 color, dx = rect->dx, width = rect->width, rotation = 0;
+
+	if (par->asleep)
+		return;
+	if (!rect->width || !rect->height)
+		return;
+	if (!par->accel_flags) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		color = ((u32 *)(info->pseudo_palette))[rect->color];
+	else
+		color = rect->color;
+
+	if (info->var.bits_per_pixel == 24) {
+		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
+		/* horizontal coordinates and widths must be adjusted */
+		dx *= 3;
+		width *= 3;
+		rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
+	}
+
+	wait_for_fifo(3, par);
+	aty_st_le32(DP_FRGD_CLR, color, par);
+	aty_st_le32(DP_SRC,
+		    BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
+		    par);
+	aty_st_le32(DST_CNTL,
+		    DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
+		    DST_X_LEFT_TO_RIGHT | rotation, par);
+	draw_rect(dx, rect->dy, width, rect->height, par);
+}
+
+void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 src_bytes, dx = image->dx, dy = image->dy, width = image->width;
+	u32 pix_width_save, pix_width, host_cntl, rotation = 0, src, mix;
+
+	if (par->asleep)
+		return;
+	if (!image->width || !image->height)
+		return;
+	if (!par->accel_flags ||
+	    (image->depth != 1 && info->var.bits_per_pixel != image->depth)) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	pix_width = pix_width_save = aty_ld_le32(DP_PIX_WIDTH, par);
+	host_cntl = aty_ld_le32(HOST_CNTL, par) | HOST_BYTE_ALIGN;
+
+	switch (image->depth) {
+	case 1:
+	    pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
+	    pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_1BPP);
+	    break;
+	case 4:
+	    pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
+	    pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_4BPP);
+	    break;
+	case 8:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_8BPP;
+	    break;
+	case 15:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_15BPP;
+	    break;
+	case 16:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_16BPP;
+	    break;
+	case 24:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_24BPP;
+	    break;
+	case 32:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_32BPP;
+	    break;
+	}
+
+	if (info->var.bits_per_pixel == 24) {
+		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
+		/* horizontal coordinates and widths must be adjusted */
+		dx *= 3;
+		width *= 3;
+
+		rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
+
+		pix_width &= ~DST_MASK;
+		pix_width |= DST_8BPP;
+
+		/*
+		 * since Rage 3D IIc we have DP_HOST_TRIPLE_EN bit
+		 * this hwaccelerated triple has an issue with not aligned data
+		 */
+		if (M64_HAS(HW_TRIPLE) && image->width % 8 == 0)
+			pix_width |= DP_HOST_TRIPLE_EN;
+	}
+
+	if (image->depth == 1) {
+		u32 fg, bg;
+		if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+		    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+			fg = ((u32*)(info->pseudo_palette))[image->fg_color];
+			bg = ((u32*)(info->pseudo_palette))[image->bg_color];
+		} else {
+			fg = image->fg_color;
+			bg = image->bg_color;
+		}
+
+		wait_for_fifo(2, par);
+		aty_st_le32(DP_BKGD_CLR, bg, par);
+		aty_st_le32(DP_FRGD_CLR, fg, par);
+		src = MONO_SRC_HOST | FRGD_SRC_FRGD_CLR | BKGD_SRC_BKGD_CLR;
+		mix = FRGD_MIX_S | BKGD_MIX_S;
+	} else {
+		src = MONO_SRC_ONE | FRGD_SRC_HOST;
+		mix = FRGD_MIX_D_XOR_S | BKGD_MIX_D;
+	}
+
+	wait_for_fifo(6, par);
+	aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
+	aty_st_le32(DP_PIX_WIDTH, pix_width, par);
+	aty_st_le32(DP_MIX, mix, par);
+	aty_st_le32(DP_SRC, src, par);
+	aty_st_le32(HOST_CNTL, host_cntl, par);
+	aty_st_le32(DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT | rotation, par);
+
+	draw_rect(dx, dy, width, image->height, par);
+	src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
+
+	/* manual triple each pixel */
+	if (info->var.bits_per_pixel == 24 && !(pix_width & DP_HOST_TRIPLE_EN)) {
+		int inbit, outbit, mult24, byte_id_in_dword, width;
+		u8 *pbitmapin = (u8*)image->data, *pbitmapout;
+		u32 hostdword;
+
+		for (width = image->width, inbit = 7, mult24 = 0; src_bytes; ) {
+			for (hostdword = 0, pbitmapout = (u8*)&hostdword, byte_id_in_dword = 0;
+				byte_id_in_dword < 4 && src_bytes;
+				byte_id_in_dword++, pbitmapout++) {
+				for (outbit = 7; outbit >= 0; outbit--) {
+					*pbitmapout |= (((*pbitmapin >> inbit) & 1) << outbit);
+					mult24++;
+					/* next bit */
+					if (mult24 == 3) {
+						mult24 = 0;
+						inbit--;
+						width--;
+					}
+
+					/* next byte */
+					if (inbit < 0 || width == 0) {
+						src_bytes--;
+						pbitmapin++;
+						inbit = 7;
+
+						if (width == 0) {
+						    width = image->width;
+						    outbit = 0;
+						}
+					}
+				}
+			}
+			wait_for_fifo(1, par);
+			aty_st_le32(HOST_DATA0, hostdword, par);
+		}
+	} else {
+		u32 *pbitmap, dwords = (src_bytes + 3) / 4;
+		for (pbitmap = (u32*)(image->data); dwords; dwords--, pbitmap++) {
+			wait_for_fifo(1, par);
+			aty_st_le32(HOST_DATA0, get_unaligned_le32(pbitmap), par);
+		}
+	}
+
+	/* restore pix_width */
+	wait_for_fifo(1, par);
+	aty_st_le32(DP_PIX_WIDTH, pix_width_save, par);
+}
diff --git a/drivers/video/fbdev/aty/mach64_ct.c b/drivers/video/fbdev/aty/mach64_ct.c
new file mode 100644
index 000000000000..51f29d627ceb
--- /dev/null
+++ b/drivers/video/fbdev/aty/mach64_ct.c
@@ -0,0 +1,649 @@
+
+/*
+ *  ATI Mach64 CT/VT/GT/LT Support
+ */
+
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <video/mach64.h>
+#include "atyfb.h"
+#ifdef CONFIG_PPC
+#include <asm/machdep.h>
+#endif
+
+#undef DEBUG
+
+static int aty_valid_pll_ct (const struct fb_info *info, u32 vclk_per, struct pll_ct *pll);
+static int aty_dsp_gt       (const struct fb_info *info, u32 bpp, struct pll_ct *pll);
+static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll);
+static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll);
+
+u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par)
+{
+	u8 res;
+
+	/* write addr byte */
+	aty_st_8(CLOCK_CNTL_ADDR, (offset << 2) & PLL_ADDR, par);
+	/* read the register value */
+	res = aty_ld_8(CLOCK_CNTL_DATA, par);
+	return res;
+}
+
+static void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par)
+{
+	/* write addr byte */
+	aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) | PLL_WR_EN, par);
+	/* write the register value */
+	aty_st_8(CLOCK_CNTL_DATA, val & PLL_DATA, par);
+	aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) & ~PLL_WR_EN, par);
+}
+
+/*
+ * by Daniel Mantione
+ *                                  <daniel.mantione@freepascal.org>
+ *
+ *
+ * ATI Mach64 CT clock synthesis description.
+ *
+ * All clocks on the Mach64 can be calculated using the same principle:
+ *
+ *       XTALIN * x * FB_DIV
+ * CLK = ----------------------
+ *       PLL_REF_DIV * POST_DIV
+ *
+ * XTALIN is a fixed speed clock. Common speeds are 14.31 MHz and 29.50 MHz.
+ * PLL_REF_DIV can be set by the user, but is the same for all clocks.
+ * FB_DIV can be set by the user for each clock individually, it should be set
+ * between 128 and 255, the chip will generate a bad clock signal for too low
+ * values.
+ * x depends on the type of clock; usually it is 2, but for the MCLK it can also
+ * be set to 4.
+ * POST_DIV can be set by the user for each clock individually, Possible values
+ * are 1,2,4,8 and for some clocks other values are available too.
+ * CLK is of course the clock speed that is generated.
+ *
+ * The Mach64 has these clocks:
+ *
+ * MCLK			The clock rate of the chip
+ * XCLK			The clock rate of the on-chip memory
+ * VCLK0		First pixel clock of first CRT controller
+ * VCLK1    Second pixel clock of first CRT controller
+ * VCLK2		Third pixel clock of first CRT controller
+ * VCLK3    Fourth pixel clock of first CRT controller
+ * VCLK			Selected pixel clock, one of VCLK0, VCLK1, VCLK2, VCLK3
+ * V2CLK		Pixel clock of the second CRT controller.
+ * SCLK			Multi-purpose clock
+ *
+ * - MCLK and XCLK use the same FB_DIV
+ * - VCLK0 .. VCLK3 use the same FB_DIV
+ * - V2CLK is needed when the second CRTC is used (can be used for dualhead);
+ *   i.e. CRT monitor connected to laptop has different resolution than built
+ *   in LCD monitor.
+ * - SCLK is not available on all cards; it is know to exist on the Rage LT-PRO,
+ *   Rage XL and Rage Mobility. It is know not to exist on the Mach64 VT.
+ * - V2CLK is not available on all cards, most likely only the Rage LT-PRO,
+ *   the Rage XL and the Rage Mobility
+ *
+ * SCLK can be used to:
+ * - Clock the chip instead of MCLK
+ * - Replace XTALIN with a user defined frequency
+ * - Generate the pixel clock for the LCD monitor (instead of VCLK)
+ */
+
+ /*
+  * It can be quite hard to calculate XCLK and MCLK if they don't run at the
+  * same frequency. Luckily, until now all cards that need asynchrone clock
+  * speeds seem to have SCLK.
+  * So this driver uses SCLK to clock the chip and XCLK to clock the memory.
+  */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ *  PLL programming (Mach64 CT family)
+ *
+ *
+ * This procedure sets the display fifo. The display fifo is a buffer that
+ * contains data read from the video memory that waits to be processed by
+ * the CRT controller.
+ *
+ * On the more modern Mach64 variants, the chip doesn't calculate the
+ * interval after which the display fifo has to be reloaded from memory
+ * automatically, the driver has to do it instead.
+ */
+
+#define Maximum_DSP_PRECISION 7
+static u8 postdividers[] = {1,2,4,8,3};
+
+static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
+{
+	u32 dsp_off, dsp_on, dsp_xclks;
+	u32 multiplier, divider, ras_multiplier, ras_divider, tmp;
+	u8 vshift, xshift;
+	s8 dsp_precision;
+
+	multiplier = ((u32)pll->mclk_fb_div) * pll->vclk_post_div_real;
+	divider = ((u32)pll->vclk_fb_div) * pll->xclk_ref_div;
+
+	ras_multiplier = pll->xclkmaxrasdelay;
+	ras_divider = 1;
+
+	if (bpp>=8)
+		divider = divider * (bpp >> 2);
+
+	vshift = (6 - 2) - pll->xclk_post_div;	/* FIFO is 64 bits wide in accelerator mode ... */
+
+	if (bpp == 0)
+		vshift--;	/* ... but only 32 bits in VGA mode. */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (pll->xres != 0) {
+		struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+		multiplier = multiplier * par->lcd_width;
+		divider = divider * pll->xres & ~7;
+
+		ras_multiplier = ras_multiplier * par->lcd_width;
+		ras_divider = ras_divider * pll->xres & ~7;
+	}
+#endif
+	/* If we don't do this, 32 bits for multiplier & divider won't be
+	enough in certain situations! */
+	while (((multiplier | divider) & 1) == 0) {
+		multiplier = multiplier >> 1;
+		divider = divider >> 1;
+	}
+
+	/* Determine DSP precision first */
+	tmp = ((multiplier * pll->fifo_size) << vshift) / divider;
+
+	for (dsp_precision = -5;  tmp;  dsp_precision++)
+		tmp >>= 1;
+	if (dsp_precision < 0)
+		dsp_precision = 0;
+	else if (dsp_precision > Maximum_DSP_PRECISION)
+		dsp_precision = Maximum_DSP_PRECISION;
+
+	xshift = 6 - dsp_precision;
+	vshift += xshift;
+
+	/* Move on to dsp_off */
+	dsp_off = ((multiplier * (pll->fifo_size - 1)) << vshift) / divider -
+		(1 << (vshift - xshift));
+
+/*    if (bpp == 0)
+        dsp_on = ((multiplier * 20 << vshift) + divider) / divider;
+    else */
+	{
+		dsp_on = ((multiplier << vshift) + divider) / divider;
+		tmp = ((ras_multiplier << xshift) + ras_divider) / ras_divider;
+		if (dsp_on < tmp)
+		dsp_on = tmp;
+		dsp_on = dsp_on + (tmp * 2) + (pll->xclkpagefaultdelay << xshift);
+	}
+
+	/* Calculate rounding factor and apply it to dsp_on */
+	tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1;
+	dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1);
+
+	if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) {
+		dsp_on = dsp_off - (multiplier << vshift) / divider;
+		dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
+	}
+
+	/* Last but not least:  dsp_xclks */
+	dsp_xclks = ((multiplier << (vshift + 5)) + divider) / divider;
+
+	/* Get register values. */
+	pll->dsp_on_off = (dsp_on << 16) + dsp_off;
+	pll->dsp_config = (dsp_precision << 20) | (pll->dsp_loop_latency << 16) | dsp_xclks;
+#ifdef DEBUG
+	printk("atyfb(%s): dsp_config 0x%08x, dsp_on_off 0x%08x\n",
+		__func__, pll->dsp_config, pll->dsp_on_off);
+#endif
+	return 0;
+}
+
+static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll_ct *pll)
+{
+	u32 q;
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	int pllvclk;
+
+	/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
+	q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per;
+	if (q < 16*8 || q > 255*8) {
+		printk(KERN_CRIT "atyfb: vclk out of range\n");
+		return -EINVAL;
+	} else {
+		pll->vclk_post_div  = (q < 128*8);
+		pll->vclk_post_div += (q <  64*8);
+		pll->vclk_post_div += (q <  32*8);
+	}
+	pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
+	//    pll->vclk_post_div <<= 6;
+	pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
+	pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
+		(par->ref_clk_per * pll->pll_ref_div);
+#ifdef DEBUG
+	printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
+		__func__, pllvclk, pllvclk / pll->vclk_post_div_real);
+#endif
+	pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
+
+	/* Set ECP (scaler/overlay clock) divider */
+	if (par->pll_limits.ecp_max) {
+		int ecp = pllvclk / pll->vclk_post_div_real;
+		int ecp_div = 0;
+
+		while (ecp > par->pll_limits.ecp_max && ecp_div < 2) {
+			ecp >>= 1;
+			ecp_div++;
+		}
+		pll->pll_vclk_cntl |= ecp_div << 4;
+	}
+
+	return 0;
+}
+
+static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	int err;
+
+	if ((err = aty_valid_pll_ct(info, vclk_per, &pll->ct)))
+		return err;
+	if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
+		return err;
+	/*aty_calc_pll_ct(info, &pll->ct);*/
+	return 0;
+}
+
+static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 ret;
+	ret = par->ref_clk_per * pll->ct.pll_ref_div * pll->ct.vclk_post_div_real / pll->ct.vclk_fb_div / 2;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if(pll->ct.xres > 0) {
+		ret *= par->lcd_width;
+		ret /= pll->ct.xres;
+	}
+#endif
+#ifdef DEBUG
+	printk("atyfb(%s): calculated 0x%08X(%i)\n", __func__, ret, ret);
+#endif
+	return ret;
+}
+
+void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 crtc_gen_cntl, lcd_gen_cntrl;
+	u8 tmp, tmp2;
+
+	lcd_gen_cntrl = 0;
+#ifdef DEBUG
+	printk("atyfb(%s): about to program:\n"
+		"pll_ext_cntl=0x%02x pll_gen_cntl=0x%02x pll_vclk_cntl=0x%02x\n",
+		__func__,
+		pll->ct.pll_ext_cntl, pll->ct.pll_gen_cntl, pll->ct.pll_vclk_cntl);
+
+	printk("atyfb(%s): setting clock %lu for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i(%i)\n",
+		__func__,
+		par->clk_wr_offset, pll->ct.vclk_fb_div,
+		pll->ct.pll_ref_div, pll->ct.vclk_post_div, pll->ct.vclk_post_div_real);
+#endif
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* turn off LCD */
+		lcd_gen_cntrl = aty_ld_lcd(LCD_GEN_CNTL, par);
+		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl & ~LCD_ON, par);
+	}
+#endif
+	aty_st_8(CLOCK_CNTL, par->clk_wr_offset | CLOCK_STROBE, par);
+
+	/* Temporarily switch to accelerator mode */
+	crtc_gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN, par);
+
+	/* Reset VCLK generator */
+	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
+
+	/* Set post-divider */
+	tmp2 = par->clk_wr_offset << 1;
+	tmp = aty_ld_pll_ct(VCLK_POST_DIV, par);
+	tmp &= ~(0x03U << tmp2);
+	tmp |= ((pll->ct.vclk_post_div & 0x03U) << tmp2);
+	aty_st_pll_ct(VCLK_POST_DIV, tmp, par);
+
+	/* Set extended post-divider */
+	tmp = aty_ld_pll_ct(PLL_EXT_CNTL, par);
+	tmp &= ~(0x10U << par->clk_wr_offset);
+	tmp &= 0xF0U;
+	tmp |= pll->ct.pll_ext_cntl;
+	aty_st_pll_ct(PLL_EXT_CNTL, tmp, par);
+
+	/* Set feedback divider */
+	tmp = VCLK0_FB_DIV + par->clk_wr_offset;
+	aty_st_pll_ct(tmp, (pll->ct.vclk_fb_div & 0xFFU), par);
+
+	aty_st_pll_ct(PLL_GEN_CNTL, (pll->ct.pll_gen_cntl & (~(PLL_OVERRIDE | PLL_MCLK_RST))) | OSC_EN, par);
+
+	/* End VCLK generator reset */
+	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl & ~(PLL_VCLK_RST), par);
+	mdelay(5);
+
+	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
+	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
+	mdelay(1);
+
+	/* Restore mode register */
+	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl, par);
+
+	if (M64_HAS(GTB_DSP)) {
+		u8 dll_cntl;
+
+		if (M64_HAS(XL_DLL))
+			dll_cntl = 0x80;
+		else if (par->ram_type >= SDRAM)
+			dll_cntl = 0xa6;
+		else
+			dll_cntl = 0xa0;
+		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
+		aty_st_pll_ct(VFC_CNTL, 0x1b, par);
+		aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par);
+		aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par);
+
+		mdelay(10);
+		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
+		mdelay(10);
+		aty_st_pll_ct(DLL_CNTL, dll_cntl | 0x40, par);
+		mdelay(10);
+		aty_st_pll_ct(DLL_CNTL, dll_cntl & ~0x40, par);
+	}
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* restore LCD */
+		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl, par);
+	}
+#endif
+}
+
+static void aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u8 tmp, clock;
+
+	clock = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
+	tmp = clock << 1;
+	pll->ct.vclk_post_div = (aty_ld_pll_ct(VCLK_POST_DIV, par) >> tmp) & 0x03U;
+
+	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par) & 0x0FU;
+	pll->ct.vclk_fb_div = aty_ld_pll_ct(VCLK0_FB_DIV + clock, par) & 0xFFU;
+	pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+	pll->ct.mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
+
+	pll->ct.pll_gen_cntl = aty_ld_pll_ct(PLL_GEN_CNTL, par);
+	pll->ct.pll_vclk_cntl = aty_ld_pll_ct(PLL_VCLK_CNTL, par);
+
+	if (M64_HAS(GTB_DSP)) {
+		pll->ct.dsp_config = aty_ld_le32(DSP_CONFIG, par);
+		pll->ct.dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
+	}
+}
+
+static int aty_init_pll_ct(const struct fb_info *info, union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u8 mpost_div, xpost_div, sclk_post_div_real;
+	u32 q, memcntl, trp;
+	u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
+#ifdef DEBUG
+	int pllmclk, pllsclk;
+#endif
+	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
+	pll->ct.xclk_post_div = pll->ct.pll_ext_cntl & 0x07;
+	pll->ct.xclk_ref_div = 1;
+	switch (pll->ct.xclk_post_div) {
+	case 0:  case 1:  case 2:  case 3:
+		break;
+
+	case 4:
+		pll->ct.xclk_ref_div = 3;
+		pll->ct.xclk_post_div = 0;
+		break;
+
+	default:
+		printk(KERN_CRIT "atyfb: Unsupported xclk source:  %d.\n", pll->ct.xclk_post_div);
+		return -EINVAL;
+	}
+	pll->ct.mclk_fb_mult = 2;
+	if(pll->ct.pll_ext_cntl & PLL_MFB_TIMES_4_2B) {
+		pll->ct.mclk_fb_mult = 4;
+		pll->ct.xclk_post_div -= 1;
+	}
+
+#ifdef DEBUG
+	printk("atyfb(%s): mclk_fb_mult=%d, xclk_post_div=%d\n",
+		__func__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div);
+#endif
+
+	memcntl = aty_ld_le32(MEM_CNTL, par);
+	trp = (memcntl & 0x300) >> 8;
+
+	pll->ct.xclkpagefaultdelay = ((memcntl & 0xc00) >> 10) + ((memcntl & 0x1000) >> 12) + trp + 2;
+	pll->ct.xclkmaxrasdelay = ((memcntl & 0x70000) >> 16) + trp + 2;
+
+	if (M64_HAS(FIFO_32)) {
+		pll->ct.fifo_size = 32;
+	} else {
+		pll->ct.fifo_size = 24;
+		pll->ct.xclkpagefaultdelay += 2;
+		pll->ct.xclkmaxrasdelay += 3;
+	}
+
+	switch (par->ram_type) {
+	case DRAM:
+		if (info->fix.smem_len<=ONE_MB) {
+			pll->ct.dsp_loop_latency = 10;
+		} else {
+			pll->ct.dsp_loop_latency = 8;
+			pll->ct.xclkpagefaultdelay += 2;
+		}
+		break;
+	case EDO:
+	case PSEUDO_EDO:
+		if (info->fix.smem_len<=ONE_MB) {
+			pll->ct.dsp_loop_latency = 9;
+		} else {
+			pll->ct.dsp_loop_latency = 8;
+			pll->ct.xclkpagefaultdelay += 1;
+		}
+		break;
+	case SDRAM:
+		if (info->fix.smem_len<=ONE_MB) {
+			pll->ct.dsp_loop_latency = 11;
+		} else {
+			pll->ct.dsp_loop_latency = 10;
+			pll->ct.xclkpagefaultdelay += 1;
+		}
+		break;
+	case SGRAM:
+		pll->ct.dsp_loop_latency = 8;
+		pll->ct.xclkpagefaultdelay += 3;
+		break;
+	default:
+		pll->ct.dsp_loop_latency = 11;
+		pll->ct.xclkpagefaultdelay += 3;
+		break;
+	}
+
+	if (pll->ct.xclkmaxrasdelay <= pll->ct.xclkpagefaultdelay)
+		pll->ct.xclkmaxrasdelay = pll->ct.xclkpagefaultdelay + 1;
+
+	/* Allow BIOS to override */
+	dsp_config = aty_ld_le32(DSP_CONFIG, par);
+	dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
+	vga_dsp_config = aty_ld_le32(VGA_DSP_CONFIG, par);
+	vga_dsp_on_off = aty_ld_le32(VGA_DSP_ON_OFF, par);
+
+	if (dsp_config)
+		pll->ct.dsp_loop_latency = (dsp_config & DSP_LOOP_LATENCY) >> 16;
+#if 0
+	FIXME: is it relevant for us?
+	if ((!dsp_on_off && !M64_HAS(RESET_3D)) ||
+		((dsp_on_off == vga_dsp_on_off) &&
+		(!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) {
+		vga_dsp_on_off &= VGA_DSP_OFF;
+		vga_dsp_config &= VGA_DSP_XCLKS_PER_QW;
+		if (ATIDivide(vga_dsp_on_off, vga_dsp_config, 5, 1) > 24)
+			pll->ct.fifo_size = 32;
+		else
+			pll->ct.fifo_size = 24;
+	}
+#endif
+	/* Exit if the user does not want us to tamper with the clock
+	rates of her chip. */
+	if (par->mclk_per == 0) {
+		u8 mclk_fb_div, pll_ext_cntl;
+		pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+		pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
+		pll->ct.xclk_post_div_real = postdividers[pll_ext_cntl & 0x07];
+		mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
+		if (pll_ext_cntl & PLL_MFB_TIMES_4_2B)
+			mclk_fb_div <<= 1;
+		pll->ct.mclk_fb_div = mclk_fb_div;
+		return 0;
+	}
+
+	pll->ct.pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
+
+	/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
+	q = par->ref_clk_per * pll->ct.pll_ref_div * 8 /
+		(pll->ct.mclk_fb_mult * par->xclk_per);
+
+	if (q < 16*8 || q > 255*8) {
+		printk(KERN_CRIT "atxfb: xclk out of range\n");
+		return -EINVAL;
+	} else {
+		xpost_div  = (q < 128*8);
+		xpost_div += (q <  64*8);
+		xpost_div += (q <  32*8);
+	}
+	pll->ct.xclk_post_div_real = postdividers[xpost_div];
+	pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8;
+
+#ifdef CONFIG_PPC
+	if (machine_is(powermac)) {
+		/* Override PLL_EXT_CNTL & 0x07. */
+		pll->ct.xclk_post_div = xpost_div;
+		pll->ct.xclk_ref_div = 1;
+	}
+#endif
+
+#ifdef DEBUG
+	pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) /
+			(par->ref_clk_per * pll->ct.pll_ref_div);
+	printk("atyfb(%s): pllmclk=%d MHz, xclk=%d MHz\n",
+		__func__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);
+#endif
+
+	if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
+		pll->ct.pll_gen_cntl = OSC_EN;
+	else
+		pll->ct.pll_gen_cntl = OSC_EN | DLL_PWDN /* | FORCE_DCLK_TRI_STATE */;
+
+	if (M64_HAS(MAGIC_POSTDIV))
+		pll->ct.pll_ext_cntl = 0;
+	else
+		pll->ct.pll_ext_cntl = xpost_div;
+
+	if (pll->ct.mclk_fb_mult == 4)
+		pll->ct.pll_ext_cntl |= PLL_MFB_TIMES_4_2B;
+
+	if (par->mclk_per == par->xclk_per) {
+		pll->ct.pll_gen_cntl |= (xpost_div << 4); /* mclk == xclk */
+	} else {
+		/*
+		* The chip clock is not equal to the memory clock.
+		* Therefore we will use sclk to clock the chip.
+		*/
+		pll->ct.pll_gen_cntl |= (6 << 4); /* mclk == sclk */
+
+		q = par->ref_clk_per * pll->ct.pll_ref_div * 4 / par->mclk_per;
+		if (q < 16*8 || q > 255*8) {
+			printk(KERN_CRIT "atyfb: mclk out of range\n");
+			return -EINVAL;
+		} else {
+			mpost_div  = (q < 128*8);
+			mpost_div += (q <  64*8);
+			mpost_div += (q <  32*8);
+		}
+		sclk_post_div_real = postdividers[mpost_div];
+		pll->ct.sclk_fb_div = q * sclk_post_div_real / 8;
+		pll->ct.spll_cntl2 = mpost_div << 4;
+#ifdef DEBUG
+		pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) /
+			(par->ref_clk_per * pll->ct.pll_ref_div);
+		printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
+			__func__, pllsclk, pllsclk / sclk_post_div_real);
+#endif
+	}
+
+	/* Disable the extra precision pixel clock controls since we do not use them. */
+	pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par);
+	pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC);
+
+	return 0;
+}
+
+static void aty_resume_pll_ct(const struct fb_info *info,
+			      union aty_pll *pll)
+{
+	struct atyfb_par *par = info->par;
+
+	if (par->mclk_per != par->xclk_per) {
+		/*
+		* This disables the sclk, crashes the computer as reported:
+		* aty_st_pll_ct(SPLL_CNTL2, 3, info);
+		*
+		* So it seems the sclk must be enabled before it is used;
+		* so PLL_GEN_CNTL must be programmed *after* the sclk.
+		*/
+		aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par);
+		aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par);
+		/*
+		 * SCLK has been started. Wait for the PLL to lock. 5 ms
+		 * should be enough according to mach64 programmer's guide.
+		 */
+		mdelay(5);
+	}
+
+	aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par);
+	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
+	aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
+	aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
+	aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par);
+}
+
+static int dummy(void)
+{
+	return 0;
+}
+
+const struct aty_dac_ops aty_dac_ct = {
+	.set_dac	= (void *) dummy,
+};
+
+const struct aty_pll_ops aty_pll_ct = {
+	.var_to_pll	= aty_var_to_pll_ct,
+	.pll_to_var	= aty_pll_to_var_ct,
+	.set_pll	= aty_set_pll_ct,
+	.get_pll	= aty_get_pll_ct,
+	.init_pll	= aty_init_pll_ct,
+	.resume_pll	= aty_resume_pll_ct,
+};
diff --git a/drivers/video/fbdev/aty/mach64_cursor.c b/drivers/video/fbdev/aty/mach64_cursor.c
new file mode 100644
index 000000000000..2fa0317ab3c7
--- /dev/null
+++ b/drivers/video/fbdev/aty/mach64_cursor.c
@@ -0,0 +1,225 @@
+/*
+ *  ATI Mach64 CT/VT/GT/LT Cursor Support
+ */
+
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include "../core/fb_draw.h"
+
+#include <asm/io.h>
+
+#ifdef __sparc__
+#include <asm/fbio.h>
+#endif
+
+#include <video/mach64.h>
+#include "atyfb.h"
+
+/*
+ * The hardware cursor definition requires 2 bits per pixel. The
+ * Cursor size reguardless of the visible cursor size is 64 pixels
+ * by 64 lines. The total memory required to define the cursor is
+ * 16 bytes / line for 64 lines or 1024 bytes of data. The data
+ * must be in a contigiuos format. The 2 bit cursor code values are
+ * as follows:
+ *
+ *	00 - pixel colour = CURSOR_CLR_0
+ *	01 - pixel colour = CURSOR_CLR_1
+ *	10 - pixel colour = transparent (current display pixel)
+ *	11 - pixel colour = 1's complement of current display pixel
+ *
+ *	Cursor Offset        64 pixels		 Actual Displayed Area
+ *            \_________________________/
+ *	      |			|	|	|
+ *	      |<--------------->|	|	|
+ *	      | CURS_HORZ_OFFSET|	|	|
+ *	      |			|_______|	|  64 Lines
+ *	      |			   ^	|	|
+ *	      |			   |	|	|
+ *	      |		CURS_VERT_OFFSET|	|
+ *	      |			   |	|	|
+ *	      |____________________|____|	|
+ *
+ *
+ * The Screen position of the top left corner of the displayed
+ * cursor is specificed by CURS_HORZ_VERT_POSN. Care must be taken
+ * when the cursor hot spot is not the top left corner and the
+ * physical cursor position becomes negative. It will be be displayed
+ * if either the horizontal or vertical cursor position is negative
+ *
+ * If x becomes negative the cursor manager must adjust the CURS_HORZ_OFFSET
+ * to a larger number and saturate CUR_HORZ_POSN to zero.
+ *
+ * if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number,
+ * CUR_OFFSET must be adjusted to a point to the appropriate line in the cursor
+ * definitation and CUR_VERT_POSN must be saturated to zero.
+ */
+
+    /*
+     *  Hardware Cursor support.
+     */
+static const u8 cursor_bits_lookup[16] = {
+	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
+	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
+};
+
+static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u16 xoff, yoff;
+	int x, y, h;
+
+#ifdef __sparc__
+	if (par->mmaped)
+		return -EPERM;
+#endif
+	if (par->asleep)
+		return -EPERM;
+
+	wait_for_fifo(1, par);
+	if (cursor->enable)
+		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
+			    | HWCURSOR_ENABLE, par);
+	else
+		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
+				& ~HWCURSOR_ENABLE, par);
+
+	/* set position */
+	if (cursor->set & FB_CUR_SETPOS) {
+		x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
+		if (x < 0) {
+			xoff = -x;
+			x = 0;
+		} else {
+			xoff = 0;
+		}
+
+		y = cursor->image.dy - cursor->hot.y - info->var.yoffset;
+		if (y < 0) {
+			yoff = -y;
+			y = 0;
+		} else {
+			yoff = 0;
+		}
+
+		h = cursor->image.height;
+
+		/*
+		 * In doublescan mode, the cursor location
+		 * and heigh also needs to be doubled.
+		 */
+                if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) {
+			y<<=1;
+			h<<=1;
+		}
+		wait_for_fifo(3, par);
+		aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par);
+		aty_st_le32(CUR_HORZ_VERT_OFF,
+			    ((u32) (64 - h + yoff) << 16) | xoff, par);
+		aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
+	}
+
+	/* Set color map */
+	if (cursor->set & FB_CUR_SETCMAP) {
+		u32 fg_idx, bg_idx, fg, bg;
+
+		fg_idx = cursor->image.fg_color;
+		bg_idx = cursor->image.bg_color;
+
+		fg = ((info->cmap.red[fg_idx] & 0xff) << 24) |
+		     ((info->cmap.green[fg_idx] & 0xff) << 16) |
+		     ((info->cmap.blue[fg_idx] & 0xff) << 8) | 0xff;
+
+		bg = ((info->cmap.red[bg_idx] & 0xff) << 24) |
+		     ((info->cmap.green[bg_idx] & 0xff) << 16) |
+		     ((info->cmap.blue[bg_idx] & 0xff) << 8);
+
+		wait_for_fifo(2, par);
+		aty_st_le32(CUR_CLR0, bg, par);
+		aty_st_le32(CUR_CLR1, fg, par);
+	}
+
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+	    u8 *src = (u8 *)cursor->image.data;
+	    u8 *msk = (u8 *)cursor->mask;
+	    u8 __iomem *dst = (u8 __iomem *)info->sprite.addr;
+	    unsigned int width = (cursor->image.width + 7) >> 3;
+	    unsigned int height = cursor->image.height;
+	    unsigned int align = info->sprite.scan_align;
+
+	    unsigned int i, j, offset;
+	    u8 m, b;
+
+	    // Clear cursor image with 1010101010...
+	    fb_memset(dst, 0xaa, 1024);
+
+	    offset = align - width*2;
+
+	    for (i = 0; i < height; i++) {
+		for (j = 0; j < width; j++) {
+			u16 l = 0xaaaa;
+			b = *src++;
+			m = *msk++;
+			switch (cursor->rop) {
+			case ROP_XOR:
+			    // Upper 4 bits of mask data
+			    l = cursor_bits_lookup[(b ^ m) >> 4] |
+			    // Lower 4 bits of mask
+				    (cursor_bits_lookup[(b ^ m) & 0x0f] << 8);
+			    break;
+			case ROP_COPY:
+			    // Upper 4 bits of mask data
+			    l = cursor_bits_lookup[(b & m) >> 4] |
+			    // Lower 4 bits of mask
+				    (cursor_bits_lookup[(b & m) & 0x0f] << 8);
+			    break;
+			}
+			/*
+			 * If cursor size is not a multiple of 8 characters
+			 * we must pad it with transparent pattern (0xaaaa).
+			 */
+			if ((j + 1) * 8 > cursor->image.width) {
+				l = comp(l, 0xaaaa,
+				    (1 << ((cursor->image.width & 7) * 2)) - 1);
+			}
+			fb_writeb(l & 0xff, dst++);
+			fb_writeb(l >> 8, dst++);
+		}
+		dst += offset;
+	    }
+	}
+
+	return 0;
+}
+
+int aty_init_cursor(struct fb_info *info)
+{
+	unsigned long addr;
+
+	info->fix.smem_len -= PAGE_SIZE;
+
+#ifdef __sparc__
+	addr = (unsigned long) info->screen_base - 0x800000 + info->fix.smem_len;
+	info->sprite.addr = (u8 *) addr;
+#else
+#ifdef __BIG_ENDIAN
+	addr = info->fix.smem_start - 0x800000 + info->fix.smem_len;
+	info->sprite.addr = (u8 *) ioremap(addr, 1024);
+#else
+	addr = (unsigned long) info->screen_base + info->fix.smem_len;
+	info->sprite.addr = (u8 *) addr;
+#endif
+#endif
+	if (!info->sprite.addr)
+		return -ENXIO;
+	info->sprite.size = PAGE_SIZE;
+	info->sprite.scan_align = 16;	/* Scratch pad 64 bytes wide */
+	info->sprite.buf_align = 16; 	/* and 64 lines tall. */
+	info->sprite.flags = FB_PIXMAP_IO;
+
+	info->fbops->fb_cursor = atyfb_cursor;
+
+	return 0;
+}
+
diff --git a/drivers/video/fbdev/aty/mach64_gx.c b/drivers/video/fbdev/aty/mach64_gx.c
new file mode 100644
index 000000000000..10c988aef58e
--- /dev/null
+++ b/drivers/video/fbdev/aty/mach64_gx.c
@@ -0,0 +1,910 @@
+
+/*
+ *  ATI Mach64 GX Support
+ */
+
+#include <linux/delay.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <video/mach64.h>
+#include "atyfb.h"
+
+/* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
+
+#define REF_FREQ_2595       1432	/*  14.33 MHz  (exact   14.31818) */
+#define REF_DIV_2595          46	/* really 43 on ICS 2595 !!!  */
+				  /* ohne Prescaler */
+#define MAX_FREQ_2595      15938	/* 159.38 MHz  (really 170.486) */
+#define MIN_FREQ_2595       8000	/*  80.00 MHz  (        85.565) */
+				  /* mit Prescaler 2, 4, 8 */
+#define ABS_MIN_FREQ_2595   1000	/*  10.00 MHz  (really  10.697) */
+#define N_ADJ_2595           257
+
+#define STOP_BITS_2595     0x1800
+
+
+#define MIN_N_408		2
+
+#define MIN_N_1703		6
+
+#define MIN_M		2
+#define MAX_M		30
+#define MIN_N		35
+#define MAX_N		255-8
+
+
+    /*
+     *  Support Functions
+     */
+
+static void aty_dac_waste4(const struct atyfb_par *par)
+{
+	(void) aty_ld_8(DAC_REGS, par);
+
+	(void) aty_ld_8(DAC_REGS + 2, par);
+	(void) aty_ld_8(DAC_REGS + 2, par);
+	(void) aty_ld_8(DAC_REGS + 2, par);
+	(void) aty_ld_8(DAC_REGS + 2, par);
+}
+
+static void aty_StrobeClock(const struct atyfb_par *par)
+{
+	u8 tmp;
+
+	udelay(26);
+
+	tmp = aty_ld_8(CLOCK_CNTL, par);
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, tmp | CLOCK_STROBE, par);
+	return;
+}
+
+
+    /*
+     *  IBM RGB514 DAC and Clock Chip
+     */
+
+static void aty_st_514(int offset, u8 val, const struct atyfb_par *par)
+{
+	aty_st_8(DAC_CNTL, 1, par);
+	/* right addr byte */
+	aty_st_8(DAC_W_INDEX, offset & 0xff, par);
+	/* left addr byte */
+	aty_st_8(DAC_DATA, (offset >> 8) & 0xff, par);
+	aty_st_8(DAC_MASK, val, par);
+	aty_st_8(DAC_CNTL, 0, par);
+}
+
+static int aty_set_dac_514(const struct fb_info *info,
+			   const union aty_pll *pll, u32 bpp, u32 accel)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	static struct {
+		u8 pixel_dly;
+		u8 misc2_cntl;
+		u8 pixel_rep;
+		u8 pixel_cntl_index;
+		u8 pixel_cntl_v1;
+	} tab[3] = {
+		{
+		0, 0x41, 0x03, 0x71, 0x45},	/* 8 bpp */
+		{
+		0, 0x45, 0x04, 0x0c, 0x01},	/* 555 */
+		{
+		0, 0x45, 0x06, 0x0e, 0x00},	/* XRGB */
+	};
+	int i;
+
+	switch (bpp) {
+	case 8:
+	default:
+		i = 0;
+		break;
+	case 16:
+		i = 1;
+		break;
+	case 32:
+		i = 2;
+		break;
+	}
+	aty_st_514(0x90, 0x00, par);	/* VRAM Mask Low */
+	aty_st_514(0x04, tab[i].pixel_dly, par);	/* Horizontal Sync Control */
+	aty_st_514(0x05, 0x00, par);	/* Power Management */
+	aty_st_514(0x02, 0x01, par);	/* Misc Clock Control */
+	aty_st_514(0x71, tab[i].misc2_cntl, par);	/* Misc Control 2 */
+	aty_st_514(0x0a, tab[i].pixel_rep, par);	/* Pixel Format */
+	aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, par);
+	/* Misc Control 2 / 16 BPP Control / 32 BPP Control */
+	return 0;
+}
+
+static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
+			      u32 bpp, union aty_pll *pll)
+{
+	/*
+	 *  FIXME: use real calculations instead of using fixed values from the old
+	 *         driver
+	 */
+	static struct {
+		u32 limit;	/* pixlock rounding limit (arbitrary) */
+		u8 m;		/* (df<<6) | vco_div_count */
+		u8 n;		/* ref_div_count */
+	} RGB514_clocks[7] = {
+		{
+		8000, (3 << 6) | 20, 9},	/*  7395 ps / 135.2273 MHz */
+		{
+		10000, (1 << 6) | 19, 3},	/*  9977 ps / 100.2273 MHz */
+		{
+		13000, (1 << 6) | 2, 3},	/* 12509 ps /  79.9432 MHz */
+		{
+		14000, (2 << 6) | 8, 7},	/* 13394 ps /  74.6591 MHz */
+		{
+		16000, (1 << 6) | 44, 6},	/* 15378 ps /  65.0284 MHz */
+		{
+		25000, (1 << 6) | 15, 5},	/* 17460 ps /  57.2727 MHz */
+		{
+		50000, (0 << 6) | 53, 7},	/* 33145 ps /  30.1705 MHz */
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++)
+		if (vclk_per <= RGB514_clocks[i].limit) {
+			pll->ibm514.m = RGB514_clocks[i].m;
+			pll->ibm514.n = RGB514_clocks[i].n;
+			return 0;
+		}
+	return -EINVAL;
+}
+
+static u32 aty_pll_514_to_var(const struct fb_info *info,
+			      const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u8 df, vco_div_count, ref_div_count;
+
+	df = pll->ibm514.m >> 6;
+	vco_div_count = pll->ibm514.m & 0x3f;
+	ref_div_count = pll->ibm514.n;
+
+	return ((par->ref_clk_per * ref_div_count) << (3 - df))/
+	    		(vco_div_count + 65);
+}
+
+static void aty_set_pll_514(const struct fb_info *info,
+			    const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	aty_st_514(0x06, 0x02, par);	/* DAC Operation */
+	aty_st_514(0x10, 0x01, par);	/* PLL Control 1 */
+	aty_st_514(0x70, 0x01, par);	/* Misc Control 1 */
+	aty_st_514(0x8f, 0x1f, par);	/* PLL Ref. Divider Input */
+	aty_st_514(0x03, 0x00, par);	/* Sync Control */
+	aty_st_514(0x05, 0x00, par);	/* Power Management */
+	aty_st_514(0x20, pll->ibm514.m, par);	/* F0 / M0 */
+	aty_st_514(0x21, pll->ibm514.n, par);	/* F1 / N0 */
+}
+
+const struct aty_dac_ops aty_dac_ibm514 = {
+	.set_dac	= aty_set_dac_514,
+};
+
+const struct aty_pll_ops aty_pll_ibm514 = {
+	.var_to_pll	= aty_var_to_pll_514,
+	.pll_to_var	= aty_pll_514_to_var,
+	.set_pll	= aty_set_pll_514,
+};
+
+
+    /*
+     *  ATI 68860-B DAC
+     */
+
+static int aty_set_dac_ATI68860_B(const struct fb_info *info,
+				  const union aty_pll *pll, u32 bpp,
+				  u32 accel)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 gModeReg, devSetupRegA, temp, mask;
+
+	gModeReg = 0;
+	devSetupRegA = 0;
+
+	switch (bpp) {
+	case 8:
+		gModeReg = 0x83;
+		devSetupRegA =
+		    0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */ ;
+		break;
+	case 15:
+		gModeReg = 0xA0;
+		devSetupRegA = 0x60;
+		break;
+	case 16:
+		gModeReg = 0xA1;
+		devSetupRegA = 0x60;
+		break;
+	case 24:
+		gModeReg = 0xC0;
+		devSetupRegA = 0x60;
+		break;
+	case 32:
+		gModeReg = 0xE3;
+		devSetupRegA = 0x60;
+		break;
+	}
+
+	if (!accel) {
+		gModeReg = 0x80;
+		devSetupRegA = 0x61;
+	}
+
+	temp = aty_ld_8(DAC_CNTL, par);
+	aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
+		 par);
+
+	aty_st_8(DAC_REGS + 2, 0x1D, par);
+	aty_st_8(DAC_REGS + 3, gModeReg, par);
+	aty_st_8(DAC_REGS, 0x02, par);
+
+	temp = aty_ld_8(DAC_CNTL, par);
+	aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
+
+	if (info->fix.smem_len < ONE_MB)
+		mask = 0x04;
+	else if (info->fix.smem_len == ONE_MB)
+		mask = 0x08;
+	else
+		mask = 0x0C;
+
+	/* The following assumes that the BIOS has correctly set R7 of the
+	 * Device Setup Register A at boot time.
+	 */
+#define A860_DELAY_L	0x80
+
+	temp = aty_ld_8(DAC_REGS, par);
+	aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L),
+		 par);
+	temp = aty_ld_8(DAC_CNTL, par);
+	aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)),
+		 par);
+
+	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
+	aty_st_le32(DAC_CNTL, 0x47052100, par);
+	return 0;
+}
+
+const struct aty_dac_ops aty_dac_ati68860b = {
+	.set_dac	= aty_set_dac_ATI68860_B,
+};
+
+
+    /*
+     *  AT&T 21C498 DAC
+     */
+
+static int aty_set_dac_ATT21C498(const struct fb_info *info,
+				 const union aty_pll *pll, u32 bpp,
+				 u32 accel)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 dotClock;
+	int muxmode = 0;
+	int DACMask = 0;
+
+	dotClock = 100000000 / pll->ics2595.period_in_ps;
+
+	switch (bpp) {
+	case 8:
+		if (dotClock > 8000) {
+			DACMask = 0x24;
+			muxmode = 1;
+		} else
+			DACMask = 0x04;
+		break;
+	case 15:
+		DACMask = 0x16;
+		break;
+	case 16:
+		DACMask = 0x36;
+		break;
+	case 24:
+		DACMask = 0xE6;
+		break;
+	case 32:
+		DACMask = 0xE6;
+		break;
+	}
+
+	if (1 /* info->mach64DAC8Bit */ )
+		DACMask |= 0x02;
+
+	aty_dac_waste4(par);
+	aty_st_8(DAC_REGS + 2, DACMask, par);
+
+	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
+	aty_st_le32(DAC_CNTL, 0x00072000, par);
+	return muxmode;
+}
+
+const struct aty_dac_ops aty_dac_att21c498 = {
+	.set_dac	= aty_set_dac_ATT21C498,
+};
+
+
+    /*
+     *  ATI 18818 / ICS 2595 Clock Chip
+     */
+
+static int aty_var_to_pll_18818(const struct fb_info *info, u32 vclk_per,
+				u32 bpp, union aty_pll *pll)
+{
+	u32 MHz100;		/* in 0.01 MHz */
+	u32 program_bits;
+	u32 post_divider;
+
+	/* Calculate the programming word */
+	MHz100 = 100000000 / vclk_per;
+
+	program_bits = -1;
+	post_divider = 1;
+
+	if (MHz100 > MAX_FREQ_2595) {
+		MHz100 = MAX_FREQ_2595;
+		return -EINVAL;
+	} else if (MHz100 < ABS_MIN_FREQ_2595) {
+		program_bits = 0;	/* MHz100 = 257 */
+		return -EINVAL;
+	} else {
+		while (MHz100 < MIN_FREQ_2595) {
+			MHz100 *= 2;
+			post_divider *= 2;
+		}
+	}
+	MHz100 *= 1000;
+	MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
+ 
+	MHz100 += 500;		/* + 0.5 round */
+	MHz100 /= 1000;
+
+	if (program_bits == -1) {
+		program_bits = MHz100 - N_ADJ_2595;
+		switch (post_divider) {
+		case 1:
+			program_bits |= 0x0600;
+			break;
+		case 2:
+			program_bits |= 0x0400;
+			break;
+		case 4:
+			program_bits |= 0x0200;
+			break;
+		case 8:
+		default:
+			break;
+		}
+	}
+
+	program_bits |= STOP_BITS_2595;
+
+	pll->ics2595.program_bits = program_bits;
+	pll->ics2595.locationAddr = 0;
+	pll->ics2595.post_divider = post_divider;
+	pll->ics2595.period_in_ps = vclk_per;
+
+	return 0;
+}
+
+static u32 aty_pll_18818_to_var(const struct fb_info *info,
+				const union aty_pll *pll)
+{
+	return (pll->ics2595.period_in_ps);	/* default for now */
+}
+
+static void aty_ICS2595_put1bit(u8 data, const struct atyfb_par *par)
+{
+	u8 tmp;
+
+	data &= 0x01;
+	tmp = aty_ld_8(CLOCK_CNTL, par);
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
+		 (tmp & ~0x04) | (data << 2), par);
+
+	tmp = aty_ld_8(CLOCK_CNTL, par);
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (0 << 3),
+		 par);
+
+	aty_StrobeClock(par);
+
+	tmp = aty_ld_8(CLOCK_CNTL, par);
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (1 << 3),
+		 par);
+
+	aty_StrobeClock(par);
+	return;
+}
+
+static void aty_set_pll18818(const struct fb_info *info,
+			     const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 program_bits;
+	u32 locationAddr;
+
+	u32 i;
+
+	u8 old_clock_cntl;
+	u8 old_crtc_ext_disp;
+
+	old_clock_cntl = aty_ld_8(CLOCK_CNTL, par);
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
+
+	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
+	aty_st_8(CRTC_GEN_CNTL + 3,
+		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
+
+	mdelay(15);		/* delay for 50 (15) ms */
+
+	program_bits = pll->ics2595.program_bits;
+	locationAddr = pll->ics2595.locationAddr;
+
+	/* Program the clock chip */
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);	/* Strobe = 0 */
+	aty_StrobeClock(par);
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 1, par);	/* Strobe = 0 */
+	aty_StrobeClock(par);
+
+	aty_ICS2595_put1bit(1, par);	/* Send start bits */
+	aty_ICS2595_put1bit(0, par);	/* Start bit */
+	aty_ICS2595_put1bit(0, par);	/* Read / ~Write */
+
+	for (i = 0; i < 5; i++) {	/* Location 0..4 */
+		aty_ICS2595_put1bit(locationAddr & 1, par);
+		locationAddr >>= 1;
+	}
+
+	for (i = 0; i < 8 + 1 + 2 + 2; i++) {
+		aty_ICS2595_put1bit(program_bits & 1, par);
+		program_bits >>= 1;
+	}
+
+	mdelay(1);		/* delay for 1 ms */
+
+	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
+	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
+		 old_clock_cntl | CLOCK_STROBE, par);
+
+	mdelay(50);		/* delay for 50 (15) ms */
+	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
+		 ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par);
+	return;
+}
+
+const struct aty_pll_ops aty_pll_ati18818_1 = {
+	.var_to_pll	= aty_var_to_pll_18818,
+	.pll_to_var	= aty_pll_18818_to_var,
+	.set_pll	= aty_set_pll18818,
+};
+
+
+    /*
+     *  STG 1703 Clock Chip
+     */
+
+static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per,
+			       u32 bpp, union aty_pll *pll)
+{
+	u32 mhz100;		/* in 0.01 MHz */
+	u32 program_bits;
+	/* u32 post_divider; */
+	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
+	u32 temp, tempB;
+	u16 remainder, preRemainder;
+	short divider = 0, tempA;
+
+	/* Calculate the programming word */
+	mhz100 = 100000000 / vclk_per;
+	mach64MinFreq = MIN_FREQ_2595;
+	mach64MaxFreq = MAX_FREQ_2595;
+	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
+
+	/* Calculate program word */
+	if (mhz100 == 0)
+		program_bits = 0xE0;
+	else {
+		if (mhz100 < mach64MinFreq)
+			mhz100 = mach64MinFreq;
+		if (mhz100 > mach64MaxFreq)
+			mhz100 = mach64MaxFreq;
+
+		divider = 0;
+		while (mhz100 < (mach64MinFreq << 3)) {
+			mhz100 <<= 1;
+			divider += 0x20;
+		}
+
+		temp = (unsigned int) (mhz100);
+		temp = (unsigned int) (temp * (MIN_N_1703 + 2));
+		temp -= (short) (mach64RefFreq << 1);
+
+		tempA = MIN_N_1703;
+		preRemainder = 0xffff;
+
+		do {
+			tempB = temp;
+			remainder = tempB % mach64RefFreq;
+			tempB = tempB / mach64RefFreq;
+
+			if ((tempB & 0xffff) <= 127
+			    && (remainder <= preRemainder)) {
+				preRemainder = remainder;
+				divider &= ~0x1f;
+				divider |= tempA;
+				divider =
+				    (divider & 0x00ff) +
+				    ((tempB & 0xff) << 8);
+			}
+
+			temp += mhz100;
+			tempA++;
+		} while (tempA <= (MIN_N_1703 << 1));
+
+		program_bits = divider;
+	}
+
+	pll->ics2595.program_bits = program_bits;
+	pll->ics2595.locationAddr = 0;
+	pll->ics2595.post_divider = divider;	/* fuer nix */
+	pll->ics2595.period_in_ps = vclk_per;
+
+	return 0;
+}
+
+static u32 aty_pll_1703_to_var(const struct fb_info *info,
+			       const union aty_pll *pll)
+{
+	return (pll->ics2595.period_in_ps);	/* default for now */
+}
+
+static void aty_set_pll_1703(const struct fb_info *info,
+			     const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 program_bits;
+	u32 locationAddr;
+
+	char old_crtc_ext_disp;
+
+	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
+	aty_st_8(CRTC_GEN_CNTL + 3,
+		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
+
+	program_bits = pll->ics2595.program_bits;
+	locationAddr = pll->ics2595.locationAddr;
+
+	/* Program clock */
+	aty_dac_waste4(par);
+
+	(void) aty_ld_8(DAC_REGS + 2, par);
+	aty_st_8(DAC_REGS + 2, (locationAddr << 1) + 0x20, par);
+	aty_st_8(DAC_REGS + 2, 0, par);
+	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF00) >> 8, par);
+	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF), par);
+
+	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
+	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
+	return;
+}
+
+const struct aty_pll_ops aty_pll_stg1703 = {
+	.var_to_pll	= aty_var_to_pll_1703,
+	.pll_to_var	= aty_pll_1703_to_var,
+	.set_pll	= aty_set_pll_1703,
+};
+
+
+    /*
+     *  Chrontel 8398 Clock Chip
+     */
+
+static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
+			       u32 bpp, union aty_pll *pll)
+{
+	u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
+
+	u32 mhz100;		/* in 0.01 MHz */
+	u32 program_bits;
+	/* u32 post_divider; */
+	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
+	u16 m, n, k = 0, save_m, save_n, twoToKth;
+
+	/* Calculate the programming word */
+	mhz100 = 100000000 / vclk_per;
+	mach64MinFreq = MIN_FREQ_2595;
+	mach64MaxFreq = MAX_FREQ_2595;
+	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
+
+	save_m = 0;
+	save_n = 0;
+
+	/* Calculate program word */
+	if (mhz100 == 0)
+		program_bits = 0xE0;
+	else {
+		if (mhz100 < mach64MinFreq)
+			mhz100 = mach64MinFreq;
+		if (mhz100 > mach64MaxFreq)
+			mhz100 = mach64MaxFreq;
+
+		longMHz100 = mhz100 * 256 / 100;	/* 8 bit scale this */
+
+		while (mhz100 < (mach64MinFreq << 3)) {
+			mhz100 <<= 1;
+			k++;
+		}
+
+		twoToKth = 1 << k;
+		diff = 0;
+		preDiff = 0xFFFFFFFF;
+
+		for (m = MIN_M; m <= MAX_M; m++) {
+			for (n = MIN_N; n <= MAX_N; n++) {
+				tempA = 938356;		/* 14.31818 * 65536 */
+				tempA *= (n + 8);	/* 43..256 */
+				tempB = twoToKth * 256;
+				tempB *= (m + 2);	/* 4..32 */
+				fOut = tempA / tempB;	/* 8 bit scale */
+
+				if (longMHz100 > fOut)
+					diff = longMHz100 - fOut;
+				else
+					diff = fOut - longMHz100;
+
+				if (diff < preDiff) {
+					save_m = m;
+					save_n = n;
+					preDiff = diff;
+				}
+			}
+		}
+
+		program_bits = (k << 6) + (save_m) + (save_n << 8);
+	}
+
+	pll->ics2595.program_bits = program_bits;
+	pll->ics2595.locationAddr = 0;
+	pll->ics2595.post_divider = 0;
+	pll->ics2595.period_in_ps = vclk_per;
+
+	return 0;
+}
+
+static u32 aty_pll_8398_to_var(const struct fb_info *info,
+			       const union aty_pll *pll)
+{
+	return (pll->ics2595.period_in_ps);	/* default for now */
+}
+
+static void aty_set_pll_8398(const struct fb_info *info,
+			     const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 program_bits;
+	u32 locationAddr;
+
+	char old_crtc_ext_disp;
+	char tmp;
+
+	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
+	aty_st_8(CRTC_GEN_CNTL + 3,
+		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
+
+	program_bits = pll->ics2595.program_bits;
+	locationAddr = pll->ics2595.locationAddr;
+
+	/* Program clock */
+	tmp = aty_ld_8(DAC_CNTL, par);
+	aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
+
+	aty_st_8(DAC_REGS, locationAddr, par);
+	aty_st_8(DAC_REGS + 1, (program_bits & 0xff00) >> 8, par);
+	aty_st_8(DAC_REGS + 1, (program_bits & 0xff), par);
+
+	tmp = aty_ld_8(DAC_CNTL, par);
+	aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
+		 par);
+
+	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
+	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
+
+	return;
+}
+
+const struct aty_pll_ops aty_pll_ch8398 = {
+	.var_to_pll	= aty_var_to_pll_8398,
+	.pll_to_var	= aty_pll_8398_to_var,
+	.set_pll	= aty_set_pll_8398,
+};
+
+
+    /*
+     *  AT&T 20C408 Clock Chip
+     */
+
+static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per,
+			      u32 bpp, union aty_pll *pll)
+{
+	u32 mhz100;		/* in 0.01 MHz */
+	u32 program_bits;
+	/* u32 post_divider; */
+	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
+	u32 temp, tempB;
+	u16 remainder, preRemainder;
+	short divider = 0, tempA;
+
+	/* Calculate the programming word */
+	mhz100 = 100000000 / vclk_per;
+	mach64MinFreq = MIN_FREQ_2595;
+	mach64MaxFreq = MAX_FREQ_2595;
+	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
+
+	/* Calculate program word */
+	if (mhz100 == 0)
+		program_bits = 0xFF;
+	else {
+		if (mhz100 < mach64MinFreq)
+			mhz100 = mach64MinFreq;
+		if (mhz100 > mach64MaxFreq)
+			mhz100 = mach64MaxFreq;
+
+		while (mhz100 < (mach64MinFreq << 3)) {
+			mhz100 <<= 1;
+			divider += 0x40;
+		}
+
+		temp = (unsigned int) mhz100;
+		temp = (unsigned int) (temp * (MIN_N_408 + 2));
+		temp -= ((short) (mach64RefFreq << 1));
+
+		tempA = MIN_N_408;
+		preRemainder = 0xFFFF;
+
+		do {
+			tempB = temp;
+			remainder = tempB % mach64RefFreq;
+			tempB = tempB / mach64RefFreq;
+			if (((tempB & 0xFFFF) <= 255)
+			    && (remainder <= preRemainder)) {
+				preRemainder = remainder;
+				divider &= ~0x3f;
+				divider |= tempA;
+				divider =
+				    (divider & 0x00FF) +
+				    ((tempB & 0xFF) << 8);
+			}
+			temp += mhz100;
+			tempA++;
+		} while (tempA <= 32);
+
+		program_bits = divider;
+	}
+
+	pll->ics2595.program_bits = program_bits;
+	pll->ics2595.locationAddr = 0;
+	pll->ics2595.post_divider = divider;	/* fuer nix */
+	pll->ics2595.period_in_ps = vclk_per;
+
+	return 0;
+}
+
+static u32 aty_pll_408_to_var(const struct fb_info *info,
+			      const union aty_pll *pll)
+{
+	return (pll->ics2595.period_in_ps);	/* default for now */
+}
+
+static void aty_set_pll_408(const struct fb_info *info,
+			    const union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 program_bits;
+	u32 locationAddr;
+
+	u8 tmpA, tmpB, tmpC;
+	char old_crtc_ext_disp;
+
+	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
+	aty_st_8(CRTC_GEN_CNTL + 3,
+		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
+
+	program_bits = pll->ics2595.program_bits;
+	locationAddr = pll->ics2595.locationAddr;
+
+	/* Program clock */
+	aty_dac_waste4(par);
+	tmpB = aty_ld_8(DAC_REGS + 2, par) | 1;
+	aty_dac_waste4(par);
+	aty_st_8(DAC_REGS + 2, tmpB, par);
+
+	tmpA = tmpB;
+	tmpC = tmpA;
+	tmpA |= 8;
+	tmpB = 1;
+
+	aty_st_8(DAC_REGS, tmpB, par);
+	aty_st_8(DAC_REGS + 2, tmpA, par);
+
+	udelay(400);		/* delay for 400 us */
+
+	locationAddr = (locationAddr << 2) + 0x40;
+	tmpB = locationAddr;
+	tmpA = program_bits >> 8;
+
+	aty_st_8(DAC_REGS, tmpB, par);
+	aty_st_8(DAC_REGS + 2, tmpA, par);
+
+	tmpB = locationAddr + 1;
+	tmpA = (u8) program_bits;
+
+	aty_st_8(DAC_REGS, tmpB, par);
+	aty_st_8(DAC_REGS + 2, tmpA, par);
+
+	tmpB = locationAddr + 2;
+	tmpA = 0x77;
+
+	aty_st_8(DAC_REGS, tmpB, par);
+	aty_st_8(DAC_REGS + 2, tmpA, par);
+
+	udelay(400);		/* delay for 400 us */
+	tmpA = tmpC & (~(1 | 8));
+	tmpB = 1;
+
+	aty_st_8(DAC_REGS, tmpB, par);
+	aty_st_8(DAC_REGS + 2, tmpA, par);
+
+	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
+	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
+	return;
+}
+
+const struct aty_pll_ops aty_pll_att20c408 = {
+	.var_to_pll	= aty_var_to_pll_408,
+	.pll_to_var	= aty_pll_408_to_var,
+	.set_pll	= aty_set_pll_408,
+};
+
+
+    /*
+     *  Unsupported DAC and Clock Chip
+     */
+
+static int aty_set_dac_unsupported(const struct fb_info *info,
+				   const union aty_pll *pll, u32 bpp,
+				   u32 accel)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
+	aty_st_le32(DAC_CNTL, 0x47052100, par);
+	/* new in 2.2.3p1 from Geert. ???????? */
+	aty_st_le32(BUS_CNTL, 0x590e10ff, par);
+	aty_st_le32(DAC_CNTL, 0x47012100, par);
+	return 0;
+}
+
+static int dummy(void)
+{
+	return 0;
+}
+
+const struct aty_dac_ops aty_dac_unsupported = {
+	.set_dac	= aty_set_dac_unsupported,
+};
+
+const struct aty_pll_ops aty_pll_unsupported = {
+	.var_to_pll	= (void *) dummy,
+	.pll_to_var	= (void *) dummy,
+	.set_pll	= (void *) dummy,
+};
diff --git a/drivers/video/fbdev/aty/radeon_accel.c b/drivers/video/fbdev/aty/radeon_accel.c
new file mode 100644
index 000000000000..a469a3d6edcb
--- /dev/null
+++ b/drivers/video/fbdev/aty/radeon_accel.c
@@ -0,0 +1,328 @@
+#include "radeonfb.h"
+
+/* the accelerated functions here are patterned after the 
+ * "ACCEL_MMIO" ifdef branches in XFree86
+ * --dte
+ */
+
+static void radeon_fixup_offset(struct radeonfb_info *rinfo)
+{
+	u32 local_base;
+
+	/* *** Ugly workaround *** */
+	/*
+	 * On some platforms, the video memory is mapped at 0 in radeon chip space
+	 * (like PPCs) by the firmware. X will always move it up so that it's seen
+	 * by the chip to be at the same address as the PCI BAR.
+	 * That means that when switching back from X, there is a mismatch between
+	 * the offsets programmed into the engine. This means that potentially,
+	 * accel operations done before radeonfb has a chance to re-init the engine
+	 * will have incorrect offsets, and potentially trash system memory !
+	 *
+	 * The correct fix is for fbcon to never call any accel op before the engine
+	 * has properly been re-initialized (by a call to set_var), but this is a
+	 * complex fix. This workaround in the meantime, called before every accel
+	 * operation, makes sure the offsets are in sync.
+	 */
+
+	radeon_fifo_wait (1);
+	local_base = INREG(MC_FB_LOCATION) << 16;
+	if (local_base == rinfo->fb_local_base)
+		return;
+
+	rinfo->fb_local_base = local_base;
+
+	radeon_fifo_wait (3);
+	OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
+				     (rinfo->fb_local_base >> 10));
+	OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+	OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+}
+
+static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 
+				   const struct fb_fillrect *region)
+{
+	radeon_fifo_wait(4);  
+  
+	OUTREG(DP_GUI_MASTER_CNTL,  
+		rinfo->dp_gui_master_cntl  /* contains, like GMC_DST_32BPP */
+                | GMC_BRUSH_SOLID_COLOR
+                | ROP3_P);
+	if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
+		OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
+	else
+		OUTREG(DP_BRUSH_FRGD_CLR, region->color);
+	OUTREG(DP_WRITE_MSK, 0xffffffff);
+	OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
+
+	radeon_fifo_wait(2);
+	OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
+	OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
+
+	radeon_fifo_wait(2);  
+	OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
+	OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
+}
+
+void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
+{
+	struct radeonfb_info *rinfo = info->par;
+	struct fb_fillrect modded;
+	int vxres, vyres;
+  
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(info, region);
+		return;
+	}
+
+	radeon_fixup_offset(rinfo);
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if(!modded.width || !modded.height ||
+	   modded.dx >= vxres || modded.dy >= vyres)
+		return;
+  
+	if(modded.dx + modded.width  > vxres) modded.width  = vxres - modded.dx;
+	if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
+
+	radeonfb_prim_fillrect(rinfo, &modded);
+}
+
+static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, 
+				   const struct fb_copyarea *area)
+{
+	int xdir, ydir;
+	u32 sx, sy, dx, dy, w, h;
+
+	w = area->width; h = area->height;
+	dx = area->dx; dy = area->dy;
+	sx = area->sx; sy = area->sy;
+	xdir = sx - dx;
+	ydir = sy - dy;
+
+	if ( xdir < 0 ) { sx += w-1; dx += w-1; }
+	if ( ydir < 0 ) { sy += h-1; dy += h-1; }
+
+	radeon_fifo_wait(3);
+	OUTREG(DP_GUI_MASTER_CNTL,
+		rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
+		| GMC_BRUSH_NONE
+		| GMC_SRC_DSTCOLOR
+		| ROP3_S 
+		| DP_SRC_SOURCE_MEMORY );
+	OUTREG(DP_WRITE_MSK, 0xffffffff);
+	OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
+			| (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
+
+	radeon_fifo_wait(2);
+	OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
+	OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
+
+	radeon_fifo_wait(3);
+	OUTREG(SRC_Y_X, (sy << 16) | sx);
+	OUTREG(DST_Y_X, (dy << 16) | dx);
+	OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
+}
+
+
+void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct radeonfb_info *rinfo = info->par;
+	struct fb_copyarea modded;
+	u32 vxres, vyres;
+	modded.sx = area->sx;
+	modded.sy = area->sy;
+	modded.dx = area->dx;
+	modded.dy = area->dy;
+	modded.width  = area->width;
+	modded.height = area->height;
+  
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	radeon_fixup_offset(rinfo);
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if(!modded.width || !modded.height ||
+	   modded.sx >= vxres || modded.sy >= vyres ||
+	   modded.dx >= vxres || modded.dy >= vyres)
+		return;
+  
+	if(modded.sx + modded.width > vxres)  modded.width = vxres - modded.sx;
+	if(modded.dx + modded.width > vxres)  modded.width = vxres - modded.dx;
+	if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
+	if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
+  
+	radeonfb_prim_copyarea(rinfo, &modded);
+}
+
+void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct radeonfb_info *rinfo = info->par;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	radeon_engine_idle();
+
+	cfb_imageblit(info, image);
+}
+
+int radeonfb_sync(struct fb_info *info)
+{
+	struct radeonfb_info *rinfo = info->par;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return 0;
+	radeon_engine_idle();
+
+	return 0;
+}
+
+void radeonfb_engine_reset(struct radeonfb_info *rinfo)
+{
+	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+	u32 host_path_cntl;
+
+	radeon_engine_flush (rinfo);
+
+	clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
+	mclk_cntl = INPLL(MCLK_CNTL);
+
+	OUTPLL(MCLK_CNTL, (mclk_cntl |
+			   FORCEON_MCLKA |
+			   FORCEON_MCLKB |
+			   FORCEON_YCLKA |
+			   FORCEON_YCLKB |
+			   FORCEON_MC |
+			   FORCEON_AIC));
+
+	host_path_cntl = INREG(HOST_PATH_CNTL);
+	rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
+
+	if (IS_R300_VARIANT(rinfo)) {
+		u32 tmp;
+
+		OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
+					 SOFT_RESET_CP |
+					 SOFT_RESET_HI |
+					 SOFT_RESET_E2));
+		INREG(RBBM_SOFT_RESET);
+		OUTREG(RBBM_SOFT_RESET, 0);
+		tmp = INREG(RB2D_DSTCACHE_MODE);
+		OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */
+	} else {
+		OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
+					SOFT_RESET_CP |
+					SOFT_RESET_HI |
+					SOFT_RESET_SE |
+					SOFT_RESET_RE |
+					SOFT_RESET_PP |
+					SOFT_RESET_E2 |
+					SOFT_RESET_RB);
+		INREG(RBBM_SOFT_RESET);
+		OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
+					~(SOFT_RESET_CP |
+					  SOFT_RESET_HI |
+					  SOFT_RESET_SE |
+					  SOFT_RESET_RE |
+					  SOFT_RESET_PP |
+					  SOFT_RESET_E2 |
+					  SOFT_RESET_RB));
+		INREG(RBBM_SOFT_RESET);
+	}
+
+	OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET);
+	INREG(HOST_PATH_CNTL);
+	OUTREG(HOST_PATH_CNTL, host_path_cntl);
+
+	if (!IS_R300_VARIANT(rinfo))
+		OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
+
+	OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
+	OUTPLL(MCLK_CNTL, mclk_cntl);
+}
+
+void radeonfb_engine_init (struct radeonfb_info *rinfo)
+{
+	unsigned long temp;
+
+	/* disable 3D engine */
+	OUTREG(RB3D_CNTL, 0);
+
+	radeonfb_engine_reset(rinfo);
+
+	radeon_fifo_wait (1);
+	if (IS_R300_VARIANT(rinfo)) {
+		OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
+		       RB2D_DC_AUTOFLUSH_ENABLE |
+		       RB2D_DC_DC_DISABLE_IGNORE_PE);
+	} else {
+		/* This needs to be double checked with ATI. Latest X driver
+		 * completely "forgets" to set this register on < r3xx, and
+		 * we used to just write 0 there... I'll keep the 0 and update
+		 * that when we have sorted things out on X side.
+		 */
+		OUTREG(RB2D_DSTCACHE_MODE, 0);
+	}
+
+	radeon_fifo_wait (3);
+	/* We re-read MC_FB_LOCATION from card as it can have been
+	 * modified by XFree drivers (ouch !)
+	 */
+	rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+
+	OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
+				     (rinfo->fb_local_base >> 10));
+	OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+	OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+
+	radeon_fifo_wait (1);
+#if defined(__BIG_ENDIAN)
+	OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
+#else
+	OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
+#endif
+	radeon_fifo_wait (2);
+	OUTREG(DEFAULT_SC_TOP_LEFT, 0);
+	OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
+					 DEFAULT_SC_BOTTOM_MAX));
+
+	temp = radeon_get_dstbpp(rinfo->depth);
+	rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
+
+	radeon_fifo_wait (1);
+	OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
+				    GMC_BRUSH_SOLID_COLOR |
+				    GMC_SRC_DATATYPE_COLOR));
+
+	radeon_fifo_wait (7);
+
+	/* clear line drawing regs */
+	OUTREG(DST_LINE_START, 0);
+	OUTREG(DST_LINE_END, 0);
+
+	/* set brush color regs */
+	OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
+	OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
+
+	/* set source color regs */
+	OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
+	OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
+
+	/* default write mask */
+	OUTREG(DP_WRITE_MSK, 0xffffffff);
+
+	radeon_engine_idle ();
+}
diff --git a/drivers/video/fbdev/aty/radeon_backlight.c b/drivers/video/fbdev/aty/radeon_backlight.c
new file mode 100644
index 000000000000..db572df7e1ef
--- /dev/null
+++ b/drivers/video/fbdev/aty/radeon_backlight.c
@@ -0,0 +1,221 @@
+/*
+ * Backlight code for ATI Radeon based graphic cards
+ *
+ * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org>
+ * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "radeonfb.h"
+#include <linux/backlight.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#define MAX_RADEON_LEVEL 0xFF
+
+struct radeon_bl_privdata {
+	struct radeonfb_info *rinfo;
+	uint8_t negative;
+};
+
+static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
+		int level)
+{
+	int rlevel;
+
+	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
+	rlevel = pdata->rinfo->info->bl_curve[level] *
+		 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
+
+	if (rlevel < 0)
+		rlevel = 0;
+	else if (rlevel > MAX_RADEON_LEVEL)
+		rlevel = MAX_RADEON_LEVEL;
+
+	if (pdata->negative)
+		rlevel = MAX_RADEON_LEVEL - rlevel;
+
+	return rlevel;
+}
+
+static int radeon_bl_update_status(struct backlight_device *bd)
+{
+	struct radeon_bl_privdata *pdata = bl_get_data(bd);
+	struct radeonfb_info *rinfo = pdata->rinfo;
+	u32 lvds_gen_cntl, tmpPixclksCntl;
+	int level;
+
+	if (rinfo->mon1_type != MT_LCD)
+		return 0;
+
+	/* We turn off the LCD completely instead of just dimming the
+	 * backlight. This provides some greater power saving and the display
+	 * is useless without backlight anyway.
+	 */
+        if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props.brightness;
+
+	del_timer_sync(&rinfo->lvds_timer);
+	radeon_engine_idle();
+
+	lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+	if (level > 0) {
+		lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
+		if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
+			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
+			lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
+			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+			lvds_gen_cntl |=
+				(radeon_bl_get_level_brightness(pdata, level) <<
+				 LVDS_BL_MOD_LEVEL_SHIFT);
+			lvds_gen_cntl |= LVDS_ON;
+			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
+			rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+			mod_timer(&rinfo->lvds_timer,
+				  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+		} else {
+			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+			lvds_gen_cntl |=
+				(radeon_bl_get_level_brightness(pdata, level) <<
+				 LVDS_BL_MOD_LEVEL_SHIFT);
+			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+		}
+		rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+		rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
+			& LVDS_STATE_MASK;
+	} else {
+		/* Asic bug, when turning off LVDS_ON, we have to make sure
+		   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+		*/
+		tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
+		if (rinfo->is_mobility || rinfo->is_IGP)
+			OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+		lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
+		lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
+				  LVDS_BL_MOD_LEVEL_SHIFT);
+		lvds_gen_cntl |= LVDS_DISPLAY_DIS;
+		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+		udelay(100);
+		lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
+		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+		lvds_gen_cntl &= ~(LVDS_DIGON);
+		rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+		mod_timer(&rinfo->lvds_timer,
+			  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+		if (rinfo->is_mobility || rinfo->is_IGP)
+			OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
+	}
+	rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+	rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
+
+	return 0;
+}
+
+static int radeon_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops radeon_bl_data = {
+	.get_brightness = radeon_bl_get_brightness,
+	.update_status	= radeon_bl_update_status,
+};
+
+void radeonfb_bl_init(struct radeonfb_info *rinfo)
+{
+	struct backlight_properties props;
+	struct backlight_device *bd;
+	struct radeon_bl_privdata *pdata;
+	char name[12];
+
+	if (rinfo->mon1_type != MT_LCD)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati") &&
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL);
+	if (!pdata) {
+		printk("radeonfb: Memory allocation failed\n");
+		goto error;
+	}
+
+	snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd = backlight_device_register(name, rinfo->info->dev, pdata,
+				       &radeon_bl_data, &props);
+	if (IS_ERR(bd)) {
+		rinfo->info->bl_dev = NULL;
+		printk("radeonfb: Backlight registration failed\n");
+		goto error;
+	}
+
+	pdata->rinfo = rinfo;
+
+	/* Pardon me for that hack... maybe some day we can figure out in what
+	 * direction backlight should work on a given panel?
+	 */
+	pdata->negative =
+		(rinfo->family != CHIP_FAMILY_RV200 &&
+		 rinfo->family != CHIP_FAMILY_RV250 &&
+		 rinfo->family != CHIP_FAMILY_RV280 &&
+		 rinfo->family != CHIP_FAMILY_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	pdata->negative = pdata->negative ||
+		of_machine_is_compatible("PowerBook4,3") ||
+		of_machine_is_compatible("PowerBook6,3") ||
+		of_machine_is_compatible("PowerBook6,5");
+#endif
+
+	rinfo->info->bl_dev = bd;
+	fb_bl_default_curve(rinfo->info, 0,
+		 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
+		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
+
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	printk("radeonfb: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	kfree(pdata);
+	return;
+}
+
+void radeonfb_bl_exit(struct radeonfb_info *rinfo)
+{
+	struct backlight_device *bd = rinfo->info->bl_dev;
+
+	if (bd) {
+		struct radeon_bl_privdata *pdata;
+
+		pdata = bl_get_data(bd);
+		backlight_device_unregister(bd);
+		kfree(pdata);
+		rinfo->info->bl_dev = NULL;
+
+		printk("radeonfb: Backlight unloaded\n");
+	}
+}
diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c
new file mode 100644
index 000000000000..26d80a4486fb
--- /dev/null
+++ b/drivers/video/fbdev/aty/radeon_base.c
@@ -0,0 +1,2568 @@
+/*
+ *	drivers/video/aty/radeon_base.c
+ *
+ *	framebuffer driver for ATI Radeon chipset video boards
+ *
+ *	Copyright 2003	Ben. Herrenschmidt <benh@kernel.crashing.org>
+ *	Copyright 2000	Ani Joshi <ajoshi@kernel.crashing.org>
+ *
+ *	i2c bits from Luca Tettamanti <kronos@kronoz.cjb.net>
+ *	
+ *	Special thanks to ATI DevRel team for their hardware donations.
+ *
+ *	...Insert GPL boilerplate here...
+ *
+ *	Significant portions of this driver apdated from XFree86 Radeon
+ *	driver which has the following copyright notice:
+ *
+ *	Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ *                     VA Linux Systems Inc., Fremont, California.
+ *
+ *	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 on 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 (including the
+ *	next paragraph) shall be included in all copies or substantial
+ *	portions of the Software.
+ *
+ *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * 	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *	NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ *	THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *	DEALINGS IN THE SOFTWARE.
+ *
+ *	XFree86 driver authors:
+ *
+ *	   Kevin E. Martin <martin@xfree86.org>
+ *	   Rickard E. Faith <faith@valinux.com>
+ *	   Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ */
+
+
+#define RADEON_VERSION	"0.2.0"
+
+#include "radeonfb.h"
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <linux/uaccess.h>
+
+#ifdef CONFIG_PPC_OF
+
+#include <asm/pci-bridge.h>
+#include "../macmodes.h"
+
+#ifdef CONFIG_BOOTX_TEXT
+#include <asm/btext.h>
+#endif
+
+#endif /* CONFIG_PPC_OF */
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/radeon.h>
+#include <linux/radeonfb.h>
+
+#include "../edid.h" // MOVE THAT TO include/video
+#include "ati_ids.h"
+
+#define MAX_MAPPED_VRAM	(2048*2048*4)
+#define MIN_MAPPED_VRAM	(1024*768*1)
+
+#define CHIP_DEF(id, family, flags)					\
+	{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
+
+static struct pci_device_id radeonfb_pci_table[] = {
+        /* Radeon Xpress 200m */
+	CHIP_DEF(PCI_CHIP_RS480_5955,   RS480,  CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RS482_5975,	RS480,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* Mobility M6 */
+	CHIP_DEF(PCI_CHIP_RADEON_LY, 	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RADEON_LZ,	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* Radeon VE/7000 */
+	CHIP_DEF(PCI_CHIP_RV100_QY, 	RV100,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV100_QZ, 	RV100,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RN50,		RV100,	CHIP_HAS_CRTC2),
+	/* Radeon IGP320M (U1) */
+	CHIP_DEF(PCI_CHIP_RS100_4336,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* Radeon IGP320 (A3) */
+	CHIP_DEF(PCI_CHIP_RS100_4136,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP), 
+	/* IGP330M/340M/350M (U2) */
+	CHIP_DEF(PCI_CHIP_RS200_4337,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* IGP330/340/350 (A4) */
+	CHIP_DEF(PCI_CHIP_RS200_4137,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+	/* Mobility 7000 IGP */
+	CHIP_DEF(PCI_CHIP_RS250_4437,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* 7000 IGP (A4+) */
+	CHIP_DEF(PCI_CHIP_RS250_4237,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+	/* 8500 AIW */
+	CHIP_DEF(PCI_CHIP_R200_BB,	R200,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R200_BC,	R200,	CHIP_HAS_CRTC2),
+	/* 8700/8800 */
+	CHIP_DEF(PCI_CHIP_R200_QH,	R200,	CHIP_HAS_CRTC2),
+	/* 8500 */
+	CHIP_DEF(PCI_CHIP_R200_QL,	R200,	CHIP_HAS_CRTC2),
+	/* 9100 */
+	CHIP_DEF(PCI_CHIP_R200_QM,	R200,	CHIP_HAS_CRTC2),
+	/* Mobility M7 */
+	CHIP_DEF(PCI_CHIP_RADEON_LW,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RADEON_LX,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* 7500 */
+	CHIP_DEF(PCI_CHIP_RV200_QW,	RV200,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV200_QX,	RV200,	CHIP_HAS_CRTC2),
+	/* Mobility M9 */
+	CHIP_DEF(PCI_CHIP_RV250_Ld,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV250_Le,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV250_Lf,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV250_Lg,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* 9000/Pro */
+	CHIP_DEF(PCI_CHIP_RV250_If,	RV250,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV250_Ig,	RV250,	CHIP_HAS_CRTC2),
+
+	CHIP_DEF(PCI_CHIP_RC410_5A62,   RC410,  CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* Mobility 9100 IGP (U3) */
+	CHIP_DEF(PCI_CHIP_RS300_5835,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RS350_7835,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* 9100 IGP (A5) */
+	CHIP_DEF(PCI_CHIP_RS300_5834,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+	CHIP_DEF(PCI_CHIP_RS350_7834,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+	/* Mobility 9200 (M9+) */
+	CHIP_DEF(PCI_CHIP_RV280_5C61,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV280_5C63,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* 9200 */
+	CHIP_DEF(PCI_CHIP_RV280_5960,	RV280,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV280_5961,	RV280,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV280_5962,	RV280,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV280_5964,	RV280,	CHIP_HAS_CRTC2),
+	/* 9500 */
+	CHIP_DEF(PCI_CHIP_R300_AD,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_AE,	R300,	CHIP_HAS_CRTC2),
+	/* 9600TX / FireGL Z1 */
+	CHIP_DEF(PCI_CHIP_R300_AF,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_AG,	R300,	CHIP_HAS_CRTC2),
+	/* 9700/9500/Pro/FireGL X1 */
+	CHIP_DEF(PCI_CHIP_R300_ND,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_NE,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_NF,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_NG,	R300,	CHIP_HAS_CRTC2),
+	/* Mobility M10/M11 */
+	CHIP_DEF(PCI_CHIP_RV350_NP,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NQ,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NR,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NS,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NT,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NV,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* 9600/FireGL T2 */
+	CHIP_DEF(PCI_CHIP_RV350_AP,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AQ,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV360_AR,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AS,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AT,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AV,	RV350,	CHIP_HAS_CRTC2),
+	/* 9800/Pro/FileGL X2 */
+	CHIP_DEF(PCI_CHIP_R350_AH,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_AI,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_AJ,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_AK,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_NH,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_NI,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R360_NJ,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_NK,	R350,	CHIP_HAS_CRTC2),
+	/* Newer stuff */
+	CHIP_DEF(PCI_CHIP_RV380_3E50,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV380_3E54,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV380_3150,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV380_3154,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV370_5B60,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5B62,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5B63,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5B64,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5B65,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5460,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV370_5464,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_R420_JH,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JI,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JJ,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JK,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JL,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JM,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JN,	R420,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_R420_JP,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UH,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UI,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UJ,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UK,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UQ,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UR,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UT,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_5D57,	R420,	CHIP_HAS_CRTC2),
+	/* Original Radeon/7200 */
+	CHIP_DEF(PCI_CHIP_RADEON_QD,	RADEON,	0),
+	CHIP_DEF(PCI_CHIP_RADEON_QE,	RADEON,	0),
+	CHIP_DEF(PCI_CHIP_RADEON_QF,	RADEON,	0),
+	CHIP_DEF(PCI_CHIP_RADEON_QG,	RADEON,	0),
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
+
+
+typedef struct {
+	u16 reg;
+	u32 val;
+} reg_val;
+
+
+/* these common regs are cleared before mode setting so they do not
+ * interfere with anything
+ */
+static reg_val common_regs[] = {
+	{ OVR_CLR, 0 },	
+	{ OVR_WID_LEFT_RIGHT, 0 },
+	{ OVR_WID_TOP_BOTTOM, 0 },
+	{ OV0_SCALE_CNTL, 0 },
+	{ SUBPIC_CNTL, 0 },
+	{ VIPH_CONTROL, 0 },
+	{ I2C_CNTL_1, 0 },
+	{ GEN_INT_CNTL, 0 },
+	{ CAP0_TRIG_CNTL, 0 },
+	{ CAP1_TRIG_CNTL, 0 },
+};
+
+/*
+ * globals
+ */
+        
+static char *mode_option;
+static char *monitor_layout;
+static bool noaccel = 0;
+static int default_dynclk = -2;
+static bool nomodeset = 0;
+static bool ignore_edid = 0;
+static bool mirror = 0;
+static int panel_yres = 0;
+static bool force_dfp = 0;
+static bool force_measure_pll = 0;
+#ifdef CONFIG_MTRR
+static bool nomtrr = 0;
+#endif
+static bool force_sleep;
+static bool ignore_devlist;
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight = 1;
+#else
+static int backlight = 0;
+#endif
+
+/*
+ * prototypes
+ */
+
+static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
+{
+	if (!rinfo->bios_seg)
+		return;
+	pci_unmap_rom(dev, rinfo->bios_seg);
+}
+
+static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
+{
+	void __iomem *rom;
+	u16 dptr;
+	u8 rom_type;
+	size_t rom_size;
+
+	/* If this is a primary card, there is a shadow copy of the
+	 * ROM somewhere in the first meg. We will just ignore the copy
+	 * and use the ROM directly.
+	 */
+    
+    	/* Fix from ATI for problem with Radeon hardware not leaving ROM enabled */
+    	unsigned int temp;
+	temp = INREG(MPP_TB_CONFIG);
+	temp &= 0x00ffffffu;
+	temp |= 0x04 << 24;
+	OUTREG(MPP_TB_CONFIG, temp);
+	temp = INREG(MPP_TB_CONFIG);
+                                                                                                          
+	rom = pci_map_rom(dev, &rom_size);
+	if (!rom) {
+		printk(KERN_ERR "radeonfb (%s): ROM failed to map\n",
+		       pci_name(rinfo->pdev));
+		return -ENOMEM;
+	}
+	
+	rinfo->bios_seg = rom;
+
+	/* Very simple test to make sure it appeared */
+	if (BIOS_IN16(0) != 0xaa55) {
+		printk(KERN_DEBUG "radeonfb (%s): Invalid ROM signature %x "
+			"should be 0xaa55\n",
+			pci_name(rinfo->pdev), BIOS_IN16(0));
+		goto failed;
+	}
+	/* Look for the PCI data to check the ROM type */
+	dptr = BIOS_IN16(0x18);
+
+	/* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM
+	 * for now, until I've verified this works everywhere. The goal here is more
+	 * to phase out Open Firmware images.
+	 *
+	 * Currently, we only look at the first PCI data, we could iteratre and deal with
+	 * them all, and we should use fb_bios_start relative to start of image and not
+	 * relative start of ROM, but so far, I never found a dual-image ATI card
+	 *
+	 * typedef struct {
+	 * 	u32	signature;	+ 0x00
+	 * 	u16	vendor;		+ 0x04
+	 * 	u16	device;		+ 0x06
+	 * 	u16	reserved_1;	+ 0x08
+	 * 	u16	dlen;		+ 0x0a
+	 * 	u8	drevision;	+ 0x0c
+	 * 	u8	class_hi;	+ 0x0d
+	 * 	u16	class_lo;	+ 0x0e
+	 * 	u16	ilen;		+ 0x10
+	 * 	u16	irevision;	+ 0x12
+	 * 	u8	type;		+ 0x14
+	 * 	u8	indicator;	+ 0x15
+	 * 	u16	reserved_2;	+ 0x16
+	 * } pci_data_t;
+	 */
+	if (BIOS_IN32(dptr) !=  (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
+		printk(KERN_WARNING "radeonfb (%s): PCI DATA signature in ROM"
+		       "incorrect: %08x\n", pci_name(rinfo->pdev), BIOS_IN32(dptr));
+		goto anyway;
+	}
+	rom_type = BIOS_IN8(dptr + 0x14);
+	switch(rom_type) {
+	case 0:
+		printk(KERN_INFO "radeonfb: Found Intel x86 BIOS ROM Image\n");
+		break;
+	case 1:
+		printk(KERN_INFO "radeonfb: Found Open Firmware ROM Image\n");
+		goto failed;
+	case 2:
+		printk(KERN_INFO "radeonfb: Found HP PA-RISC ROM Image\n");
+		goto failed;
+	default:
+		printk(KERN_INFO "radeonfb: Found unknown type %d ROM Image\n", rom_type);
+		goto failed;
+	}
+ anyway:
+	/* Locate the flat panel infos, do some sanity checking !!! */
+	rinfo->fp_bios_start = BIOS_IN16(0x48);
+	return 0;
+
+ failed:
+	rinfo->bios_seg = NULL;
+	radeon_unmap_ROM(rinfo, dev);
+	return -ENXIO;
+}
+
+#ifdef CONFIG_X86
+static int  radeon_find_mem_vbios(struct radeonfb_info *rinfo)
+{
+	/* I simplified this code as we used to miss the signatures in
+	 * a lot of case. It's now closer to XFree, we just don't check
+	 * for signatures at all... Something better will have to be done
+	 * if we end up having conflicts
+	 */
+        u32  segstart;
+	void __iomem *rom_base = NULL;
+                                                
+        for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
+                rom_base = ioremap(segstart, 0x10000);
+		if (rom_base == NULL)
+			return -ENOMEM;
+                if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
+	                break;
+                iounmap(rom_base);
+		rom_base = NULL;
+        }
+	if (rom_base == NULL)
+		return -ENXIO;
+
+	/* Locate the flat panel infos, do some sanity checking !!! */
+	rinfo->bios_seg = rom_base;
+	rinfo->fp_bios_start = BIOS_IN16(0x48);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+/*
+ * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
+ * tree. Hopefully, ATI OF driver is kind enough to fill these
+ */
+static int radeon_read_xtal_OF(struct radeonfb_info *rinfo)
+{
+	struct device_node *dp = rinfo->of_node;
+	const u32 *val;
+
+	if (dp == NULL)
+		return -ENODEV;
+	val = of_get_property(dp, "ATY,RefCLK", NULL);
+	if (!val || !*val) {
+		printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
+		return -EINVAL;
+	}
+
+	rinfo->pll.ref_clk = (*val) / 10;
+
+	val = of_get_property(dp, "ATY,SCLK", NULL);
+	if (val && *val)
+		rinfo->pll.sclk = (*val) / 10;
+
+	val = of_get_property(dp, "ATY,MCLK", NULL);
+	if (val && *val)
+		rinfo->pll.mclk = (*val) / 10;
+
+       	return 0;
+}
+#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
+
+/*
+ * Read PLL infos from chip registers
+ */
+static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
+{
+	unsigned char ppll_div_sel;
+	unsigned Ns, Nm, M;
+	unsigned sclk, mclk, tmp, ref_div;
+	int hTotal, vTotal, num, denom, m, n;
+	unsigned long long hz, vclk;
+	long xtal;
+	struct timeval start_tv, stop_tv;
+	long total_secs, total_usecs;
+	int i;
+
+	/* Ugh, we cut interrupts, bad bad bad, but we want some precision
+	 * here, so... --BenH
+	 */
+
+	/* Flush PCI buffers ? */
+	tmp = INREG16(DEVICE_ID);
+
+	local_irq_disable();
+
+	for(i=0; i<1000000; i++)
+		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
+			break;
+
+	do_gettimeofday(&start_tv);
+
+	for(i=0; i<1000000; i++)
+		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0)
+			break;
+
+	for(i=0; i<1000000; i++)
+		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
+			break;
+	
+	do_gettimeofday(&stop_tv);
+	
+	local_irq_enable();
+
+	total_secs = stop_tv.tv_sec - start_tv.tv_sec;
+	if (total_secs > 10)
+		return -1;
+	total_usecs = stop_tv.tv_usec - start_tv.tv_usec;
+	total_usecs += total_secs * 1000000;
+	if (total_usecs < 0)
+		total_usecs = -total_usecs;
+	hz = 1000000/total_usecs;
+ 
+	hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8;
+	vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1);
+	vclk = (long long)hTotal * (long long)vTotal * hz;
+
+	switch((INPLL(PPLL_REF_DIV) & 0x30000) >> 16) {
+	case 0:
+	default:
+		num = 1;
+		denom = 1;
+		break;
+	case 1:
+		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 16) & 0xff);
+		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);
+		num = 2*n;
+		denom = 2*m;
+		break;
+	case 2:
+		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 8) & 0xff);
+		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);
+		num = 2*n;
+		denom = 2*m;
+        break;
+	}
+
+	ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
+	radeon_pll_errata_after_index(rinfo);
+
+	n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
+	m = (INPLL(PPLL_REF_DIV) & 0x3ff);
+
+	num *= n;
+	denom *= m;
+
+	switch ((INPLL(PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) {
+	case 1:
+		denom *= 2;
+		break;
+	case 2:
+		denom *= 4;
+		break;
+	case 3:
+		denom *= 8;
+		break;
+	case 4:
+		denom *= 3;
+		break;
+	case 6:
+		denom *= 6;   
+		break;
+	case 7:
+		denom *= 12;
+		break;
+	}
+
+	vclk *= denom;
+	do_div(vclk, 1000 * num);
+	xtal = vclk;
+
+	if ((xtal > 26900) && (xtal < 27100))
+		xtal = 2700;
+	else if ((xtal > 14200) && (xtal < 14400))
+		xtal = 1432;
+	else if ((xtal > 29400) && (xtal < 29600))
+		xtal = 2950;
+	else {
+		printk(KERN_WARNING "xtal calculation failed: %ld\n", xtal);
+		return -1;
+	}
+
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+
+	Ns = (tmp & 0xff0000) >> 16;
+	Nm = (tmp & 0xff00) >> 8;
+	M = (tmp & 0xff);
+	sclk = round_div((2 * Ns * xtal), (2 * M));
+	mclk = round_div((2 * Nm * xtal), (2 * M));
+
+	/* we're done, hopefully these are sane values */
+	rinfo->pll.ref_clk = xtal;
+	rinfo->pll.ref_div = ref_div;
+	rinfo->pll.sclk = sclk;
+	rinfo->pll.mclk = mclk;
+
+	return 0;
+}
+
+/*
+ * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...)
+ */
+static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
+{
+	/*
+	 * In the case nothing works, these are defaults; they are mostly
+	 * incomplete, however.  It does provide ppll_max and _min values
+	 * even for most other methods, however.
+	 */
+	switch (rinfo->chipset) {
+	case PCI_DEVICE_ID_ATI_RADEON_QW:
+	case PCI_DEVICE_ID_ATI_RADEON_QX:
+		rinfo->pll.ppll_max = 35000;
+		rinfo->pll.ppll_min = 12000;
+		rinfo->pll.mclk = 23000;
+		rinfo->pll.sclk = 23000;
+		rinfo->pll.ref_clk = 2700;
+		break;
+	case PCI_DEVICE_ID_ATI_RADEON_QL:
+	case PCI_DEVICE_ID_ATI_RADEON_QN:
+	case PCI_DEVICE_ID_ATI_RADEON_QO:
+	case PCI_DEVICE_ID_ATI_RADEON_Ql:
+	case PCI_DEVICE_ID_ATI_RADEON_BB:
+		rinfo->pll.ppll_max = 35000;
+		rinfo->pll.ppll_min = 12000;
+		rinfo->pll.mclk = 27500;
+		rinfo->pll.sclk = 27500;
+		rinfo->pll.ref_clk = 2700;
+		break;
+	case PCI_DEVICE_ID_ATI_RADEON_Id:
+	case PCI_DEVICE_ID_ATI_RADEON_Ie:
+	case PCI_DEVICE_ID_ATI_RADEON_If:
+	case PCI_DEVICE_ID_ATI_RADEON_Ig:
+		rinfo->pll.ppll_max = 35000;
+		rinfo->pll.ppll_min = 12000;
+		rinfo->pll.mclk = 25000;
+		rinfo->pll.sclk = 25000;
+		rinfo->pll.ref_clk = 2700;
+		break;
+	case PCI_DEVICE_ID_ATI_RADEON_ND:
+	case PCI_DEVICE_ID_ATI_RADEON_NE:
+	case PCI_DEVICE_ID_ATI_RADEON_NF:
+	case PCI_DEVICE_ID_ATI_RADEON_NG:
+		rinfo->pll.ppll_max = 40000;
+		rinfo->pll.ppll_min = 20000;
+		rinfo->pll.mclk = 27000;
+		rinfo->pll.sclk = 27000;
+		rinfo->pll.ref_clk = 2700;
+		break;
+	case PCI_DEVICE_ID_ATI_RADEON_QD:
+	case PCI_DEVICE_ID_ATI_RADEON_QE:
+	case PCI_DEVICE_ID_ATI_RADEON_QF:
+	case PCI_DEVICE_ID_ATI_RADEON_QG:
+	default:
+		rinfo->pll.ppll_max = 35000;
+		rinfo->pll.ppll_min = 12000;
+		rinfo->pll.mclk = 16600;
+		rinfo->pll.sclk = 16600;
+		rinfo->pll.ref_clk = 2700;
+		break;
+	}
+	rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
+
+
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+	/*
+	 * Retrieve PLL infos from Open Firmware first
+	 */
+       	if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
+       		printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n");
+		goto found;
+	}
+#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
+
+	/*
+	 * Check out if we have an X86 which gave us some PLL informations
+	 * and if yes, retrieve them
+	 */
+	if (!force_measure_pll && rinfo->bios_seg) {
+		u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
+
+		rinfo->pll.sclk		= BIOS_IN16(pll_info_block + 0x08);
+		rinfo->pll.mclk		= BIOS_IN16(pll_info_block + 0x0a);
+		rinfo->pll.ref_clk	= BIOS_IN16(pll_info_block + 0x0e);
+		rinfo->pll.ref_div	= BIOS_IN16(pll_info_block + 0x10);
+		rinfo->pll.ppll_min	= BIOS_IN32(pll_info_block + 0x12);
+		rinfo->pll.ppll_max	= BIOS_IN32(pll_info_block + 0x16);
+
+		printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n");
+		goto found;
+	}
+
+	/*
+	 * We didn't get PLL parameters from either OF or BIOS, we try to
+	 * probe them
+	 */
+	if (radeon_probe_pll_params(rinfo) == 0) {
+		printk(KERN_INFO "radeonfb: Retrieved PLL infos from registers\n");
+		goto found;
+	}
+
+	/*
+	 * Fall back to already-set defaults...
+	 */
+       	printk(KERN_INFO "radeonfb: Used default PLL infos\n");
+
+found:
+	/*
+	 * Some methods fail to retrieve SCLK and MCLK values, we apply default
+	 * settings in this case (200Mhz). If that really happens often, we
+	 * could fetch from registers instead...
+	 */
+	if (rinfo->pll.mclk == 0)
+		rinfo->pll.mclk = 20000;
+	if (rinfo->pll.sclk == 0)
+		rinfo->pll.sclk = 20000;
+
+	printk("radeonfb: Reference=%d.%02d MHz (RefDiv=%d) Memory=%d.%02d Mhz, System=%d.%02d MHz\n",
+	       rinfo->pll.ref_clk / 100, rinfo->pll.ref_clk % 100,
+	       rinfo->pll.ref_div,
+	       rinfo->pll.mclk / 100, rinfo->pll.mclk % 100,
+	       rinfo->pll.sclk / 100, rinfo->pll.sclk % 100);
+	printk("radeonfb: PLL min %d max %d\n", rinfo->pll.ppll_min, rinfo->pll.ppll_max);
+}
+
+static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct radeonfb_info *rinfo = info->par;
+        struct fb_var_screeninfo v;
+        int nom, den;
+	unsigned int pitch;
+
+	if (radeon_match_mode(rinfo, &v, var))
+		return -EINVAL;
+
+        switch (v.bits_per_pixel) {
+		case 0 ... 8:
+			v.bits_per_pixel = 8;
+			break;
+		case 9 ... 16:
+			v.bits_per_pixel = 16;
+			break;
+		case 17 ... 24:
+#if 0 /* Doesn't seem to work */
+			v.bits_per_pixel = 24;
+			break;
+#endif			
+			return -EINVAL;
+		case 25 ... 32:
+			v.bits_per_pixel = 32;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	switch (var_to_depth(&v)) {
+                case 8:
+                        nom = den = 1;
+                        v.red.offset = v.green.offset = v.blue.offset = 0;
+                        v.red.length = v.green.length = v.blue.length = 8;
+                        v.transp.offset = v.transp.length = 0;
+                        break;
+		case 15:
+			nom = 2;
+			den = 1;
+			v.red.offset = 10;
+			v.green.offset = 5;
+			v.blue.offset = 0;
+			v.red.length = v.green.length = v.blue.length = 5;
+			v.transp.offset = v.transp.length = 0;
+			break;
+                case 16:
+                        nom = 2;
+                        den = 1;
+                        v.red.offset = 11;
+                        v.green.offset = 5;
+                        v.blue.offset = 0;
+                        v.red.length = 5;
+                        v.green.length = 6;
+                        v.blue.length = 5;
+                        v.transp.offset = v.transp.length = 0;
+                        break;                          
+                case 24:
+                        nom = 4;
+                        den = 1;
+                        v.red.offset = 16;
+                        v.green.offset = 8;
+                        v.blue.offset = 0;
+                        v.red.length = v.blue.length = v.green.length = 8;
+                        v.transp.offset = v.transp.length = 0;
+                        break;
+                case 32:
+                        nom = 4;
+                        den = 1;
+                        v.red.offset = 16;
+                        v.green.offset = 8;
+                        v.blue.offset = 0;
+                        v.red.length = v.blue.length = v.green.length = 8;
+                        v.transp.offset = 24;
+                        v.transp.length = 8;
+                        break;
+                default:
+                        printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",
+                                var->xres, var->yres, var->bits_per_pixel);
+                        return -EINVAL;
+        }
+
+	if (v.yres_virtual < v.yres)
+		v.yres_virtual = v.yres;
+	if (v.xres_virtual < v.xres)
+		v.xres_virtual = v.xres;
+                
+
+	/* XXX I'm adjusting xres_virtual to the pitch, that may help XFree
+	 * with some panels, though I don't quite like this solution
+	 */
+  	if (rinfo->info->flags & FBINFO_HWACCEL_DISABLED) {
+		v.xres_virtual = v.xres_virtual & ~7ul;
+	} else {
+		pitch = ((v.xres_virtual * ((v.bits_per_pixel + 1) / 8) + 0x3f)
+ 				& ~(0x3f)) >> 6;
+		v.xres_virtual = (pitch << 6) / ((v.bits_per_pixel + 1) / 8);
+	}
+
+	if (((v.xres_virtual * v.yres_virtual * nom) / den) > rinfo->mapped_vram)
+		return -EINVAL;
+
+	if (v.xres_virtual < v.xres)
+		v.xres = v.xres_virtual;
+
+        if (v.xoffset > v.xres_virtual - v.xres)
+                v.xoffset = v.xres_virtual - v.xres - 1;
+                        
+        if (v.yoffset > v.yres_virtual - v.yres)
+                v.yoffset = v.yres_virtual - v.yres - 1;
+         
+        v.red.msb_right = v.green.msb_right = v.blue.msb_right =
+                          v.transp.offset = v.transp.length =
+                          v.transp.msb_right = 0;
+	
+        memcpy(var, &v, sizeof(v));
+
+        return 0;
+}
+
+
+static int radeonfb_pan_display (struct fb_var_screeninfo *var,
+                                 struct fb_info *info)
+{
+        struct radeonfb_info *rinfo = info->par;
+
+	if ((var->xoffset + info->var.xres > info->var.xres_virtual)
+	    || (var->yoffset + info->var.yres > info->var.yres_virtual))
+		return -EINVAL;
+                
+        if (rinfo->asleep)
+        	return 0;
+
+	radeon_fifo_wait(2);
+	OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
+			     var->xoffset * info->var.bits_per_pixel / 8) & ~7);
+        return 0;
+}
+
+
+static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
+                           unsigned long arg)
+{
+        struct radeonfb_info *rinfo = info->par;
+	unsigned int tmp;
+	u32 value = 0;
+	int rc;
+
+	switch (cmd) {
+		/*
+		 * TODO:  set mirror accordingly for non-Mobility chipsets with 2 CRTC's
+		 *        and do something better using 2nd CRTC instead of just hackish
+		 *        routing to second output
+		 */
+		case FBIO_RADEON_SET_MIRROR:
+			if (!rinfo->is_mobility)
+				return -EINVAL;
+
+			rc = get_user(value, (__u32 __user *)arg);
+
+			if (rc)
+				return rc;
+
+			radeon_fifo_wait(2);
+			if (value & 0x01) {
+				tmp = INREG(LVDS_GEN_CNTL);
+
+				tmp |= (LVDS_ON | LVDS_BLON);
+			} else {
+				tmp = INREG(LVDS_GEN_CNTL);
+
+				tmp &= ~(LVDS_ON | LVDS_BLON);
+			}
+
+			OUTREG(LVDS_GEN_CNTL, tmp);
+
+			if (value & 0x02) {
+				tmp = INREG(CRTC_EXT_CNTL);
+				tmp |= CRTC_CRT_ON;
+
+				mirror = 1;
+			} else {
+				tmp = INREG(CRTC_EXT_CNTL);
+				tmp &= ~CRTC_CRT_ON;
+
+				mirror = 0;
+			}
+
+			OUTREG(CRTC_EXT_CNTL, tmp);
+
+			return 0;
+		case FBIO_RADEON_GET_MIRROR:
+			if (!rinfo->is_mobility)
+				return -EINVAL;
+
+			tmp = INREG(LVDS_GEN_CNTL);
+			if ((LVDS_ON | LVDS_BLON) & tmp)
+				value |= 0x01;
+
+			tmp = INREG(CRTC_EXT_CNTL);
+			if (CRTC_CRT_ON & tmp)
+				value |= 0x02;
+
+			return put_user(value, (__u32 __user *)arg);
+		default:
+			return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+
+int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
+{
+        u32 val;
+	u32 tmp_pix_clks;
+	int unblank = 0;
+
+	if (rinfo->lock_blank)
+		return 0;
+
+	radeon_engine_idle();
+
+	val = INREG(CRTC_EXT_CNTL);
+        val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
+                 CRTC_VSYNC_DIS);
+        switch (blank) {
+	case FB_BLANK_VSYNC_SUSPEND:
+		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
+		break;
+	case FB_BLANK_POWERDOWN:
+		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
+			CRTC_HSYNC_DIS);
+		break;
+	case FB_BLANK_NORMAL:
+		val |= CRTC_DISPLAY_DIS;
+		break;
+	case FB_BLANK_UNBLANK:
+	default:
+		unblank = 1;
+        }
+	OUTREG(CRTC_EXT_CNTL, val);
+
+
+	switch (rinfo->mon1_type) {
+	case MT_DFP:
+		if (unblank)
+			OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN),
+				~(FP_FPON | FP_TMDS_EN));
+		else {
+			if (mode_switch || blank == FB_BLANK_NORMAL)
+				break;
+			OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));
+		}
+		break;
+	case MT_LCD:
+		del_timer_sync(&rinfo->lvds_timer);
+		val = INREG(LVDS_GEN_CNTL);
+		if (unblank) {
+			u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON
+				| LVDS_EN | (rinfo->init_state.lvds_gen_cntl
+					     & (LVDS_DIGON | LVDS_BL_MOD_EN));
+			if ((val ^ target_val) == LVDS_DISPLAY_DIS)
+				OUTREG(LVDS_GEN_CNTL, target_val);
+			else if ((val ^ target_val) != 0) {
+				OUTREG(LVDS_GEN_CNTL, target_val
+				       & ~(LVDS_ON | LVDS_BL_MOD_EN));
+				rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+				rinfo->init_state.lvds_gen_cntl |=
+					target_val & LVDS_STATE_MASK;
+				if (mode_switch) {
+					radeon_msleep(rinfo->panel_info.pwr_delay);
+					OUTREG(LVDS_GEN_CNTL, target_val);
+				}
+				else {
+					rinfo->pending_lvds_gen_cntl = target_val;
+					mod_timer(&rinfo->lvds_timer,
+					   jiffies +
+					   msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+				}
+			}
+		} else {
+			val |= LVDS_DISPLAY_DIS;
+			OUTREG(LVDS_GEN_CNTL, val);
+
+			/* We don't do a full switch-off on a simple mode switch */
+			if (mode_switch || blank == FB_BLANK_NORMAL)
+				break;
+
+			/* Asic bug, when turning off LVDS_ON, we have to make sure
+			 * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+			 */
+			tmp_pix_clks = INPLL(PIXCLKS_CNTL);
+			if (rinfo->is_mobility || rinfo->is_IGP)
+				OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+			val &= ~(LVDS_BL_MOD_EN);
+			OUTREG(LVDS_GEN_CNTL, val);
+			udelay(100);
+			val &= ~(LVDS_ON | LVDS_EN);
+			OUTREG(LVDS_GEN_CNTL, val);
+			val &= ~LVDS_DIGON;
+			rinfo->pending_lvds_gen_cntl = val;
+			mod_timer(&rinfo->lvds_timer,
+				  jiffies +
+				  msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+			rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+			rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
+			if (rinfo->is_mobility || rinfo->is_IGP)
+				OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
+		}
+		break;
+	case MT_CRT:
+		// todo: powerdown DAC
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int radeonfb_blank (int blank, struct fb_info *info)
+{
+        struct radeonfb_info *rinfo = info->par;
+
+	if (rinfo->asleep)
+		return 0;
+		
+	return radeon_screen_blank(rinfo, blank, 0);
+}
+
+static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
+                             unsigned blue, unsigned transp,
+			     struct radeonfb_info *rinfo)
+{
+	u32 pindex;
+	unsigned int i;
+
+
+	if (regno > 255)
+		return -EINVAL;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	rinfo->palette[regno].red = red;
+	rinfo->palette[regno].green = green;
+	rinfo->palette[regno].blue = blue;
+
+        /* default */
+        pindex = regno;
+
+        if (!rinfo->asleep) {
+		radeon_fifo_wait(9);
+
+		if (rinfo->bpp == 16) {
+			pindex = regno * 8;
+
+			if (rinfo->depth == 16 && regno > 63)
+				return -EINVAL;
+			if (rinfo->depth == 15 && regno > 31)
+				return -EINVAL;
+
+			/* For 565, the green component is mixed one order
+			 * below
+			 */
+			if (rinfo->depth == 16) {
+		                OUTREG(PALETTE_INDEX, pindex>>1);
+	       	         	OUTREG(PALETTE_DATA,
+				       (rinfo->palette[regno>>1].red << 16) |
+	                        	(green << 8) |
+				       (rinfo->palette[regno>>1].blue));
+	                	green = rinfo->palette[regno<<1].green;
+	        	}
+		}
+
+		if (rinfo->depth != 16 || regno < 32) {
+			OUTREG(PALETTE_INDEX, pindex);
+			OUTREG(PALETTE_DATA, (red << 16) |
+			       (green << 8) | blue);
+		}
+	}
+ 	if (regno < 16) {
+		u32 *pal = rinfo->info->pseudo_palette;
+        	switch (rinfo->depth) {
+		case 15:
+			pal[regno] = (regno << 10) | (regno << 5) | regno;
+			break;
+		case 16:
+			pal[regno] = (regno << 11) | (regno << 5) | regno;
+			break;
+		case 24:
+			pal[regno] = (regno << 16) | (regno << 8) | regno;
+			break;
+		case 32:
+			i = (regno << 8) | regno;
+			pal[regno] = (i << 16) | i;
+			break;
+		}
+        }
+	return 0;
+}
+
+static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
+			       unsigned blue, unsigned transp,
+			       struct fb_info *info)
+{
+        struct radeonfb_info *rinfo = info->par;
+	u32 dac_cntl2, vclk_cntl = 0;
+	int rc;
+
+        if (!rinfo->asleep) {
+		if (rinfo->is_mobility) {
+			vclk_cntl = INPLL(VCLK_ECP_CNTL);
+			OUTPLL(VCLK_ECP_CNTL,
+			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
+		}
+
+		/* Make sure we are on first palette */
+		if (rinfo->has_CRTC2) {
+			dac_cntl2 = INREG(DAC_CNTL2);
+			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
+			OUTREG(DAC_CNTL2, dac_cntl2);
+		}
+	}
+
+	rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo);
+
+	if (!rinfo->asleep && rinfo->is_mobility)
+		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
+
+	return rc;
+}
+
+static int radeonfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+        struct radeonfb_info *rinfo = info->par;
+	u16 *red, *green, *blue, *transp;
+	u32 dac_cntl2, vclk_cntl = 0;
+	int i, start, rc = 0;
+
+        if (!rinfo->asleep) {
+		if (rinfo->is_mobility) {
+			vclk_cntl = INPLL(VCLK_ECP_CNTL);
+			OUTPLL(VCLK_ECP_CNTL,
+			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
+		}
+
+		/* Make sure we are on first palette */
+		if (rinfo->has_CRTC2) {
+			dac_cntl2 = INREG(DAC_CNTL2);
+			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
+			OUTREG(DAC_CNTL2, dac_cntl2);
+		}
+	}
+
+	red = cmap->red;
+	green = cmap->green;
+	blue = cmap->blue;
+	transp = cmap->transp;
+	start = cmap->start;
+
+	for (i = 0; i < cmap->len; i++) {
+		u_int hred, hgreen, hblue, htransp = 0xffff;
+
+		hred = *red++;
+		hgreen = *green++;
+		hblue = *blue++;
+		if (transp)
+			htransp = *transp++;
+		rc = radeon_setcolreg (start++, hred, hgreen, hblue, htransp,
+				       rinfo);
+		if (rc)
+			break;
+	}
+
+	if (!rinfo->asleep && rinfo->is_mobility)
+		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
+
+	return rc;
+}
+
+static void radeon_save_state (struct radeonfb_info *rinfo,
+			       struct radeon_regs *save)
+{
+	/* CRTC regs */
+	save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
+	save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
+	save->crtc_more_cntl = INREG(CRTC_MORE_CNTL);
+	save->dac_cntl = INREG(DAC_CNTL);
+        save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP);
+        save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID);
+        save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP);
+        save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID);
+	save->crtc_pitch = INREG(CRTC_PITCH);
+	save->surface_cntl = INREG(SURFACE_CNTL);
+
+	/* FP regs */
+	save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP);
+	save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP);
+	save->fp_gen_cntl = INREG(FP_GEN_CNTL);
+	save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID);
+	save->fp_horz_stretch = INREG(FP_HORZ_STRETCH);
+	save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID);
+	save->fp_vert_stretch = INREG(FP_VERT_STRETCH);
+	save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+	save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);
+	save->tmds_crc = INREG(TMDS_CRC);
+	save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
+	save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
+
+	/* PLL regs */
+	save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
+	radeon_pll_errata_after_index(rinfo);
+	save->ppll_div_3 = INPLL(PPLL_DIV_3);
+	save->ppll_ref_div = INPLL(PPLL_REF_DIV);
+}
+
+
+static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
+{
+	int i;
+
+	radeon_fifo_wait(20);
+
+	/* Workaround from XFree */
+	if (rinfo->is_mobility) {
+	        /* A temporal workaround for the occasional blanking on certain laptop
+		 * panels. This appears to related to the PLL divider registers
+		 * (fail to lock?). It occurs even when all dividers are the same
+		 * with their old settings. In this case we really don't need to
+		 * fiddle with PLL registers. By doing this we can avoid the blanking
+		 * problem with some panels.
+	         */
+		if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
+		    (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
+					  (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
+			/* We still have to force a switch to selected PPLL div thanks to
+			 * an XFree86 driver bug which will switch it away in some cases
+			 * even when using UseFDev */
+			OUTREGP(CLOCK_CNTL_INDEX,
+				mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+				~PPLL_DIV_SEL_MASK);
+			radeon_pll_errata_after_index(rinfo);
+			radeon_pll_errata_after_data(rinfo);
+            		return;
+		}
+	}
+
+	/* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
+	OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
+
+	/* Reset PPLL & enable atomic update */
+	OUTPLLP(PPLL_CNTL,
+		PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
+		~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+	/* Switch to selected PPLL divider */
+	OUTREGP(CLOCK_CNTL_INDEX,
+		mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+		~PPLL_DIV_SEL_MASK);
+	radeon_pll_errata_after_index(rinfo);
+	radeon_pll_errata_after_data(rinfo);
+
+	/* Set PPLL ref. div */
+	if (IS_R300_VARIANT(rinfo) ||
+	    rinfo->family == CHIP_FAMILY_RS300 ||
+	    rinfo->family == CHIP_FAMILY_RS400 ||
+	    rinfo->family == CHIP_FAMILY_RS480) {
+		if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
+			/* When restoring console mode, use saved PPLL_REF_DIV
+			 * setting.
+			 */
+			OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
+		} else {
+			/* R300 uses ref_div_acc field as real ref divider */
+			OUTPLLP(PPLL_REF_DIV,
+				(mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), 
+				~R300_PPLL_REF_DIV_ACC_MASK);
+		}
+	} else
+		OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
+
+	/* Set PPLL divider 3 & post divider*/
+	OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
+	OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
+
+	/* Write update */
+	while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
+		;
+	OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
+
+	/* Wait read update complete */
+	/* FIXME: Certain revisions of R300 can't recover here.  Not sure of
+	   the cause yet, but this workaround will mask the problem for now.
+	   Other chips usually will pass at the very first test, so the
+	   workaround shouldn't have any effect on them. */
+	for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
+		;
+	
+	OUTPLL(HTOTAL_CNTL, 0);
+
+	/* Clear reset & atomic update */
+	OUTPLLP(PPLL_CNTL, 0,
+		~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+	/* We may want some locking ... oh well */
+       	radeon_msleep(5);
+
+	/* Switch back VCLK source to PPLL */
+	OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
+}
+
+/*
+ * Timer function for delayed LVDS panel power up/down
+ */
+static void radeon_lvds_timer_func(unsigned long data)
+{
+	struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
+
+	radeon_engine_idle();
+
+	OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
+}
+
+/*
+ * Apply a video mode. This will apply the whole register set, including
+ * the PLL registers, to the card
+ */
+void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
+			int regs_only)
+{
+	int i;
+	int primary_mon = PRIMARY_MONITOR(rinfo);
+
+	if (nomodeset)
+		return;
+
+	if (!regs_only)
+		radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
+
+	radeon_fifo_wait(31);
+	for (i=0; i<10; i++)
+		OUTREG(common_regs[i].reg, common_regs[i].val);
+
+	/* Apply surface registers */
+	for (i=0; i<8; i++) {
+		OUTREG(SURFACE0_LOWER_BOUND + 0x10*i, mode->surf_lower_bound[i]);
+		OUTREG(SURFACE0_UPPER_BOUND + 0x10*i, mode->surf_upper_bound[i]);
+		OUTREG(SURFACE0_INFO + 0x10*i, mode->surf_info[i]);
+	}
+
+	OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
+	OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
+		~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
+	OUTREG(CRTC_MORE_CNTL, mode->crtc_more_cntl);
+	OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
+	OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
+	OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
+	OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
+	OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
+	OUTREG(CRTC_OFFSET, 0);
+	OUTREG(CRTC_OFFSET_CNTL, 0);
+	OUTREG(CRTC_PITCH, mode->crtc_pitch);
+	OUTREG(SURFACE_CNTL, mode->surface_cntl);
+
+	radeon_write_pll_regs(rinfo, mode);
+
+	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
+		radeon_fifo_wait(10);
+		OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
+		OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
+		OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
+		OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid);
+		OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch);
+		OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch);
+		OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl);
+		OUTREG(TMDS_CRC, mode->tmds_crc);
+		OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
+	}
+
+	if (!regs_only)
+		radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
+
+	radeon_fifo_wait(2);
+	OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
+	
+	return;
+}
+
+/*
+ * Calculate the PLL values for a given mode
+ */
+static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs,
+				 unsigned long freq)
+{
+	const struct {
+		int divider;
+		int bitvalue;
+	} *post_div,
+	  post_divs[] = {
+		{ 1,  0 },
+		{ 2,  1 },
+		{ 4,  2 },
+		{ 8,  3 },
+		{ 3,  4 },
+		{ 16, 5 },
+		{ 6,  6 },
+		{ 12, 7 },
+		{ 0,  0 },
+	};
+	int fb_div, pll_output_freq = 0;
+	int uses_dvo = 0;
+
+	/* Check if the DVO port is enabled and sourced from the primary CRTC. I'm
+	 * not sure which model starts having FP2_GEN_CNTL, I assume anything more
+	 * recent than an r(v)100...
+	 */
+#if 1
+	/* XXX I had reports of flicker happening with the cinema display
+	 * on TMDS1 that seem to be fixed if I also forbit odd dividers in
+	 * this case. This could just be a bandwidth calculation issue, I
+	 * haven't implemented the bandwidth code yet, but in the meantime,
+	 * forcing uses_dvo to 1 fixes it and shouln't have bad side effects,
+	 * I haven't seen a case were were absolutely needed an odd PLL
+	 * divider. I'll find a better fix once I have more infos on the
+	 * real cause of the problem.
+	 */
+	while (rinfo->has_CRTC2) {
+		u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL);
+		u32 disp_output_cntl;
+		int source;
+
+		/* FP2 path not enabled */
+		if ((fp2_gen_cntl & FP2_ON) == 0)
+			break;
+		/* Not all chip revs have the same format for this register,
+		 * extract the source selection
+		 */
+		if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) {
+			source = (fp2_gen_cntl >> 10) & 0x3;
+			/* sourced from transform unit, check for transform unit
+			 * own source
+			 */
+			if (source == 3) {
+				disp_output_cntl = INREG(DISP_OUTPUT_CNTL);
+				source = (disp_output_cntl >> 12) & 0x3;
+			}
+		} else
+			source = (fp2_gen_cntl >> 13) & 0x1;
+		/* sourced from CRTC2 -> exit */
+		if (source == 1)
+			break;
+
+		/* so we end up on CRTC1, let's set uses_dvo to 1 now */
+		uses_dvo = 1;
+		break;
+	}
+#else
+	uses_dvo = 1;
+#endif
+	if (freq > rinfo->pll.ppll_max)
+		freq = rinfo->pll.ppll_max;
+	if (freq*12 < rinfo->pll.ppll_min)
+		freq = rinfo->pll.ppll_min / 12;
+	pr_debug("freq = %lu, PLL min = %u, PLL max = %u\n",
+	       freq, rinfo->pll.ppll_min, rinfo->pll.ppll_max);
+
+	for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+		pll_output_freq = post_div->divider * freq;
+		/* If we output to the DVO port (external TMDS), we don't allow an
+		 * odd PLL divider as those aren't supported on this path
+		 */
+		if (uses_dvo && (post_div->divider & 1))
+			continue;
+		if (pll_output_freq >= rinfo->pll.ppll_min  &&
+		    pll_output_freq <= rinfo->pll.ppll_max)
+			break;
+	}
+
+	/* If we fall through the bottom, try the "default value"
+	   given by the terminal post_div->bitvalue */
+	if ( !post_div->divider ) {
+		post_div = &post_divs[post_div->bitvalue];
+		pll_output_freq = post_div->divider * freq;
+	}
+	pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
+	       rinfo->pll.ref_div, rinfo->pll.ref_clk,
+	       pll_output_freq);
+
+	/* If we fall through the bottom, try the "default value"
+	   given by the terminal post_div->bitvalue */
+	if ( !post_div->divider ) {
+		post_div = &post_divs[post_div->bitvalue];
+		pll_output_freq = post_div->divider * freq;
+	}
+	pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
+	       rinfo->pll.ref_div, rinfo->pll.ref_clk,
+	       pll_output_freq);
+
+	fb_div = round_div(rinfo->pll.ref_div*pll_output_freq,
+				  rinfo->pll.ref_clk);
+	regs->ppll_ref_div = rinfo->pll.ref_div;
+	regs->ppll_div_3 = fb_div | (post_div->bitvalue << 16);
+
+	pr_debug("post div = 0x%x\n", post_div->bitvalue);
+	pr_debug("fb_div = 0x%x\n", fb_div);
+	pr_debug("ppll_div_3 = 0x%x\n", regs->ppll_div_3);
+}
+
+static int radeonfb_set_par(struct fb_info *info)
+{
+	struct radeonfb_info *rinfo = info->par;
+	struct fb_var_screeninfo *mode = &info->var;
+	struct radeon_regs *newmode;
+	int hTotal, vTotal, hSyncStart, hSyncEnd,
+	    hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
+	u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
+	u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
+	u32 sync, h_sync_pol, v_sync_pol, dotClock, pixClock;
+	int i, freq;
+	int format = 0;
+	int nopllcalc = 0;
+	int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
+	int primary_mon = PRIMARY_MONITOR(rinfo);
+	int depth = var_to_depth(mode);
+	int use_rmx = 0;
+
+	newmode = kmalloc(sizeof(struct radeon_regs), GFP_KERNEL);
+	if (!newmode)
+		return -ENOMEM;
+
+	/* We always want engine to be idle on a mode switch, even
+	 * if we won't actually change the mode
+	 */
+	radeon_engine_idle();
+
+	hSyncStart = mode->xres + mode->right_margin;
+	hSyncEnd = hSyncStart + mode->hsync_len;
+	hTotal = hSyncEnd + mode->left_margin;
+
+	vSyncStart = mode->yres + mode->lower_margin;
+	vSyncEnd = vSyncStart + mode->vsync_len;
+	vTotal = vSyncEnd + mode->upper_margin;
+	pixClock = mode->pixclock;
+
+	sync = mode->sync;
+	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+
+	if (primary_mon == MT_DFP || primary_mon == MT_LCD) {
+		if (rinfo->panel_info.xres < mode->xres)
+			mode->xres = rinfo->panel_info.xres;
+		if (rinfo->panel_info.yres < mode->yres)
+			mode->yres = rinfo->panel_info.yres;
+
+		hTotal = mode->xres + rinfo->panel_info.hblank;
+		hSyncStart = mode->xres + rinfo->panel_info.hOver_plus;
+		hSyncEnd = hSyncStart + rinfo->panel_info.hSync_width;
+
+		vTotal = mode->yres + rinfo->panel_info.vblank;
+		vSyncStart = mode->yres + rinfo->panel_info.vOver_plus;
+		vSyncEnd = vSyncStart + rinfo->panel_info.vSync_width;
+
+		h_sync_pol = !rinfo->panel_info.hAct_high;
+		v_sync_pol = !rinfo->panel_info.vAct_high;
+
+		pixClock = 100000000 / rinfo->panel_info.clock;
+
+		if (rinfo->panel_info.use_bios_dividers) {
+			nopllcalc = 1;
+			newmode->ppll_div_3 = rinfo->panel_info.fbk_divider |
+				(rinfo->panel_info.post_divider << 16);
+			newmode->ppll_ref_div = rinfo->panel_info.ref_divider;
+		}
+	}
+	dotClock = 1000000000 / pixClock;
+	freq = dotClock / 10; /* x100 */
+
+	pr_debug("hStart = %d, hEnd = %d, hTotal = %d\n",
+		hSyncStart, hSyncEnd, hTotal);
+	pr_debug("vStart = %d, vEnd = %d, vTotal = %d\n",
+		vSyncStart, vSyncEnd, vTotal);
+
+	hsync_wid = (hSyncEnd - hSyncStart) / 8;
+	vsync_wid = vSyncEnd - vSyncStart;
+	if (hsync_wid == 0)
+		hsync_wid = 1;
+	else if (hsync_wid > 0x3f)	/* max */
+		hsync_wid = 0x3f;
+
+	if (vsync_wid == 0)
+		vsync_wid = 1;
+	else if (vsync_wid > 0x1f)	/* max */
+		vsync_wid = 0x1f;
+
+	hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+	vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+
+	cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
+
+	format = radeon_get_dstbpp(depth);
+	bytpp = mode->bits_per_pixel >> 3;
+
+	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
+		hsync_fudge = hsync_fudge_fp[format-1];
+	else
+		hsync_fudge = hsync_adj_tab[format-1];
+
+	hsync_start = hSyncStart - 8 + hsync_fudge;
+
+	newmode->crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
+				(format << 8);
+
+	/* Clear auto-center etc... */
+	newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl;
+	newmode->crtc_more_cntl &= 0xfffffff0;
+	
+	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
+		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
+		if (mirror)
+			newmode->crtc_ext_cntl |= CRTC_CRT_ON;
+
+		newmode->crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
+					   CRTC_INTERLACE_EN);
+	} else {
+		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
+					CRTC_CRT_ON;
+	}
+
+	newmode->dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
+			   DAC_8BIT_EN;
+
+	newmode->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |
+				     (((mode->xres / 8) - 1) << 16));
+
+	newmode->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
+					(hsync_wid << 16) | (h_sync_pol << 23));
+
+	newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
+				    ((mode->yres - 1) << 16);
+
+	newmode->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
+					 (vsync_wid << 16) | (v_sync_pol  << 23));
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
+		/* We first calculate the engine pitch */
+		rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
+ 				& ~(0x3f)) >> 6;
+
+		/* Then, re-multiply it to get the CRTC pitch */
+		newmode->crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);
+	} else
+		newmode->crtc_pitch = (mode->xres_virtual >> 3);
+
+	newmode->crtc_pitch |= (newmode->crtc_pitch << 16);
+
+	/*
+	 * It looks like recent chips have a problem with SURFACE_CNTL,
+	 * setting SURF_TRANSLATION_DIS completely disables the
+	 * swapper as well, so we leave it unset now.
+	 */
+	newmode->surface_cntl = 0;
+
+#if defined(__BIG_ENDIAN)
+
+	/* Setup swapping on both apertures, though we currently
+	 * only use aperture 0, enabling swapper on aperture 1
+	 * won't harm
+	 */
+	switch (mode->bits_per_pixel) {
+		case 16:
+			newmode->surface_cntl |= NONSURF_AP0_SWP_16BPP;
+			newmode->surface_cntl |= NONSURF_AP1_SWP_16BPP;
+			break;
+		case 24:	
+		case 32:
+			newmode->surface_cntl |= NONSURF_AP0_SWP_32BPP;
+			newmode->surface_cntl |= NONSURF_AP1_SWP_32BPP;
+			break;
+	}
+#endif
+
+	/* Clear surface registers */
+	for (i=0; i<8; i++) {
+		newmode->surf_lower_bound[i] = 0;
+		newmode->surf_upper_bound[i] = 0x1f;
+		newmode->surf_info[i] = 0;
+	}
+
+	pr_debug("h_total_disp = 0x%x\t   hsync_strt_wid = 0x%x\n",
+		newmode->crtc_h_total_disp, newmode->crtc_h_sync_strt_wid);
+	pr_debug("v_total_disp = 0x%x\t   vsync_strt_wid = 0x%x\n",
+		newmode->crtc_v_total_disp, newmode->crtc_v_sync_strt_wid);
+
+	rinfo->bpp = mode->bits_per_pixel;
+	rinfo->depth = depth;
+
+	pr_debug("pixclock = %lu\n", (unsigned long)pixClock);
+	pr_debug("freq = %lu\n", (unsigned long)freq);
+
+	/* We use PPLL_DIV_3 */
+	newmode->clk_cntl_index = 0x300;
+
+	/* Calculate PPLL value if necessary */
+	if (!nopllcalc)
+		radeon_calc_pll_regs(rinfo, newmode, freq);
+
+	newmode->vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;
+
+	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
+		unsigned int hRatio, vRatio;
+
+		if (mode->xres > rinfo->panel_info.xres)
+			mode->xres = rinfo->panel_info.xres;
+		if (mode->yres > rinfo->panel_info.yres)
+			mode->yres = rinfo->panel_info.yres;
+
+		newmode->fp_horz_stretch = (((rinfo->panel_info.xres / 8) - 1)
+					   << HORZ_PANEL_SHIFT);
+		newmode->fp_vert_stretch = ((rinfo->panel_info.yres - 1)
+					   << VERT_PANEL_SHIFT);
+
+		if (mode->xres != rinfo->panel_info.xres) {
+			hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX,
+					   rinfo->panel_info.xres);
+			newmode->fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
+						   (newmode->fp_horz_stretch &
+						    (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |
+						     HORZ_AUTO_RATIO_INC)));
+			newmode->fp_horz_stretch |= (HORZ_STRETCH_BLEND |
+						    HORZ_STRETCH_ENABLE);
+			use_rmx = 1;
+		}
+		newmode->fp_horz_stretch &= ~HORZ_AUTO_RATIO;
+
+		if (mode->yres != rinfo->panel_info.yres) {
+			vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX,
+					   rinfo->panel_info.yres);
+			newmode->fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
+						   (newmode->fp_vert_stretch &
+						   (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));
+			newmode->fp_vert_stretch |= (VERT_STRETCH_BLEND |
+						    VERT_STRETCH_ENABLE);
+			use_rmx = 1;
+		}
+		newmode->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
+
+		newmode->fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)
+				       ~(FP_SEL_CRTC2 |
+					 FP_RMX_HVSYNC_CONTROL_EN |
+					 FP_DFP_SYNC_SEL |
+					 FP_CRT_SYNC_SEL |
+					 FP_CRTC_LOCK_8DOT |
+					 FP_USE_SHADOW_EN |
+					 FP_CRTC_USE_SHADOW_VEND |
+					 FP_CRT_SYNC_ALT));
+
+		newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR |
+					FP_CRTC_DONT_SHADOW_HEND |
+					FP_PANEL_FORMAT);
+
+		if (IS_R300_VARIANT(rinfo) ||
+		    (rinfo->family == CHIP_FAMILY_R200)) {
+			newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
+			if (use_rmx)
+				newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
+			else
+				newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
+		} else
+			newmode->fp_gen_cntl |= FP_SEL_CRTC1;
+
+		newmode->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl;
+		newmode->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl;
+		newmode->tmds_crc = rinfo->init_state.tmds_crc;
+		newmode->tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;
+
+		if (primary_mon == MT_LCD) {
+			newmode->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
+			newmode->fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN);
+		} else {
+			/* DFP */
+			newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
+			newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST);
+			/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
+			if (IS_R300_VARIANT(rinfo) ||
+			    (rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
+				newmode->tmds_transmitter_cntl &= ~TMDS_PLL_EN;
+			else
+				newmode->tmds_transmitter_cntl |= TMDS_PLL_EN;
+			newmode->crtc_ext_cntl &= ~CRTC_CRT_ON;
+		}
+
+		newmode->fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) |
+				(((mode->xres / 8) - 1) << 16));
+		newmode->fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) |
+				((mode->yres - 1) << 16);
+		newmode->fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) |
+				(hsync_wid << 16) | (h_sync_pol << 23));
+		newmode->fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) |
+				(vsync_wid << 16) | (v_sync_pol  << 23));
+	}
+
+	/* do it! */
+	if (!rinfo->asleep) {
+		memcpy(&rinfo->state, newmode, sizeof(*newmode));
+		radeon_write_mode (rinfo, newmode, 0);
+		/* (re)initialize the engine */
+		if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+			radeonfb_engine_init (rinfo);
+	}
+	/* Update fix */
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+        	info->fix.line_length = rinfo->pitch*64;
+        else
+		info->fix.line_length = mode->xres_virtual
+			* ((mode->bits_per_pixel + 1) / 8);
+        info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR
+		: FB_VISUAL_DIRECTCOLOR;
+
+#ifdef CONFIG_BOOTX_TEXT
+	/* Update debug text engine */
+	btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres,
+			     rinfo->depth, info->fix.line_length);
+#endif
+
+	kfree(newmode);
+	return 0;
+}
+
+
+static struct fb_ops radeonfb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_check_var		= radeonfb_check_var,
+	.fb_set_par		= radeonfb_set_par,
+	.fb_setcolreg		= radeonfb_setcolreg,
+	.fb_setcmap		= radeonfb_setcmap,
+	.fb_pan_display 	= radeonfb_pan_display,
+	.fb_blank		= radeonfb_blank,
+	.fb_ioctl		= radeonfb_ioctl,
+	.fb_sync		= radeonfb_sync,
+	.fb_fillrect		= radeonfb_fillrect,
+	.fb_copyarea		= radeonfb_copyarea,
+	.fb_imageblit		= radeonfb_imageblit,
+};
+
+
+static int radeon_set_fbinfo(struct radeonfb_info *rinfo)
+{
+	struct fb_info *info = rinfo->info;
+
+	info->par = rinfo;
+	info->pseudo_palette = rinfo->pseudo_palette;
+	info->flags = FBINFO_DEFAULT
+		    | FBINFO_HWACCEL_COPYAREA
+		    | FBINFO_HWACCEL_FILLRECT
+		    | FBINFO_HWACCEL_XPAN
+		    | FBINFO_HWACCEL_YPAN;
+	info->fbops = &radeonfb_ops;
+	info->screen_base = rinfo->fb_base;
+	info->screen_size = rinfo->mapped_vram;
+	/* Fill fix common fields */
+	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
+        info->fix.smem_start = rinfo->fb_base_phys;
+        info->fix.smem_len = rinfo->video_ram;
+        info->fix.type = FB_TYPE_PACKED_PIXELS;
+        info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+        info->fix.xpanstep = 8;
+        info->fix.ypanstep = 1;
+        info->fix.ywrapstep = 0;
+        info->fix.type_aux = 0;
+        info->fix.mmio_start = rinfo->mmio_base_phys;
+        info->fix.mmio_len = RADEON_REGSIZE;
+	info->fix.accel = FB_ACCEL_ATI_RADEON;
+
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	if (noaccel)
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+
+        return 0;
+}
+
+/*
+ * This reconfigure the card's internal memory map. In theory, we'd like
+ * to setup the card's memory at the same address as it's PCI bus address,
+ * and the AGP aperture right after that so that system RAM on 32 bits
+ * machines at least, is directly accessible. However, doing so would
+ * conflict with the current XFree drivers...
+ * Ultimately, I hope XFree, GATOS and ATI binary drivers will all agree
+ * on the proper way to set this up and duplicate this here. In the meantime,
+ * I put the card's memory at 0 in card space and AGP at some random high
+ * local (0xe0000000 for now) that will be changed by XFree/DRI anyway
+ */
+#ifdef CONFIG_PPC_OF
+#undef SET_MC_FB_FROM_APERTURE
+static void fixup_memory_mappings(struct radeonfb_info *rinfo)
+{
+	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl = 0;
+	u32 save_crtc_ext_cntl;
+	u32 aper_base, aper_size;
+	u32 agp_base;
+
+	/* First, we disable display to avoid interfering */
+	if (rinfo->has_CRTC2) {
+		save_crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL);
+		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl | CRTC2_DISP_REQ_EN_B);
+	}
+	save_crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
+	save_crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
+	
+	OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl | CRTC_DISPLAY_DIS);
+	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
+	mdelay(100);
+
+	aper_base = INREG(CNFG_APER_0_BASE);
+	aper_size = INREG(CNFG_APER_SIZE);
+
+#ifdef SET_MC_FB_FROM_APERTURE
+	/* Set framebuffer to be at the same address as set in PCI BAR */
+	OUTREG(MC_FB_LOCATION, 
+		((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16));
+	rinfo->fb_local_base = aper_base;
+#else
+	OUTREG(MC_FB_LOCATION, 0x7fff0000);
+	rinfo->fb_local_base = 0;
+#endif
+	agp_base = aper_base + aper_size;
+	if (agp_base & 0xf0000000)
+		agp_base = (aper_base | 0x0fffffff) + 1;
+
+	/* Set AGP to be just after the framebuffer on a 256Mb boundary. This
+	 * assumes the FB isn't mapped to 0xf0000000 or above, but this is
+	 * always the case on PPCs afaik.
+	 */
+#ifdef SET_MC_FB_FROM_APERTURE
+	OUTREG(MC_AGP_LOCATION, 0xffff0000 | (agp_base >> 16));
+#else
+	OUTREG(MC_AGP_LOCATION, 0xffffe000);
+#endif
+
+	/* Fixup the display base addresses & engine offsets while we
+	 * are at it as well
+	 */
+#ifdef SET_MC_FB_FROM_APERTURE
+	OUTREG(DISPLAY_BASE_ADDR, aper_base);
+	if (rinfo->has_CRTC2)
+		OUTREG(CRTC2_DISPLAY_BASE_ADDR, aper_base);
+	OUTREG(OV0_BASE_ADDR, aper_base);
+#else
+	OUTREG(DISPLAY_BASE_ADDR, 0);
+	if (rinfo->has_CRTC2)
+		OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);
+	OUTREG(OV0_BASE_ADDR, 0);
+#endif
+	mdelay(100);
+
+	/* Restore display settings */
+	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl);
+	OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl);
+	if (rinfo->has_CRTC2)
+		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);	
+
+	pr_debug("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",
+		aper_base,
+		((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16),
+		0xffff0000 | (agp_base >> 16));
+}
+#endif /* CONFIG_PPC_OF */
+
+
+static void radeon_identify_vram(struct radeonfb_info *rinfo)
+{
+	u32 tmp;
+
+	/* framebuffer size */
+        if ((rinfo->family == CHIP_FAMILY_RS100) ||
+            (rinfo->family == CHIP_FAMILY_RS200) ||
+            (rinfo->family == CHIP_FAMILY_RS300) ||
+            (rinfo->family == CHIP_FAMILY_RC410) ||
+            (rinfo->family == CHIP_FAMILY_RS400) ||
+	    (rinfo->family == CHIP_FAMILY_RS480) ) {
+          u32 tom = INREG(NB_TOM);
+          tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
+
+ 		radeon_fifo_wait(6);
+          OUTREG(MC_FB_LOCATION, tom);
+          OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+          OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+          OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
+
+          /* This is supposed to fix the crtc2 noise problem. */
+          OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
+
+          if ((rinfo->family == CHIP_FAMILY_RS100) ||
+              (rinfo->family == CHIP_FAMILY_RS200)) {
+             /* This is to workaround the asic bug for RMX, some versions
+                of BIOS doesn't have this register initialized correctly.
+             */
+             OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
+                     ~CRTC_H_CUTOFF_ACTIVE_EN);
+          }
+        } else {
+          tmp = INREG(CNFG_MEMSIZE);
+        }
+
+	/* mem size is bits [28:0], mask off the rest */
+	rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK;
+
+	/*
+	 * Hack to get around some busted production M6's
+	 * reporting no ram
+	 */
+	if (rinfo->video_ram == 0) {
+		switch (rinfo->pdev->device) {
+	       	case PCI_CHIP_RADEON_LY:
+		case PCI_CHIP_RADEON_LZ:
+	       		rinfo->video_ram = 8192 * 1024;
+	       		break;
+	       	default:
+	       		break;
+		}
+	}
+
+
+	/*
+	 * Now try to identify VRAM type
+	 */
+	if (rinfo->is_IGP || (rinfo->family >= CHIP_FAMILY_R300) ||
+	    (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
+		rinfo->vram_ddr = 1;
+	else
+		rinfo->vram_ddr = 0;
+
+	tmp = INREG(MEM_CNTL);
+	if (IS_R300_VARIANT(rinfo)) {
+		tmp &=  R300_MEM_NUM_CHANNELS_MASK;
+		switch (tmp) {
+		case 0:  rinfo->vram_width = 64; break;
+		case 1:  rinfo->vram_width = 128; break;
+		case 2:  rinfo->vram_width = 256; break;
+		default: rinfo->vram_width = 128; break;
+		}
+	} else if ((rinfo->family == CHIP_FAMILY_RV100) ||
+		   (rinfo->family == CHIP_FAMILY_RS100) ||
+		   (rinfo->family == CHIP_FAMILY_RS200)){
+		if (tmp & RV100_MEM_HALF_MODE)
+			rinfo->vram_width = 32;
+		else
+			rinfo->vram_width = 64;
+	} else {
+		if (tmp & MEM_NUM_CHANNELS_MASK)
+			rinfo->vram_width = 128;
+		else
+			rinfo->vram_width = 64;
+	}
+
+	/* This may not be correct, as some cards can have half of channel disabled
+	 * ToDo: identify these cases
+	 */
+
+	pr_debug("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n",
+	       pci_name(rinfo->pdev),
+	       rinfo->video_ram / 1024,
+	       rinfo->vram_ddr ? "DDR" : "SDRAM",
+	       rinfo->vram_width);
+}
+
+/*
+ * Sysfs
+ */
+
+static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid)
+{
+	return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH);
+}
+
+
+static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+        struct fb_info *info = pci_get_drvdata(pdev);
+        struct radeonfb_info *rinfo = info->par;
+
+	return radeon_show_one_edid(buf, off, count, rinfo->mon1_EDID);
+}
+
+
+static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj,
+				 struct bin_attribute *bin_attr,
+				 char *buf, loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+        struct fb_info *info = pci_get_drvdata(pdev);
+        struct radeonfb_info *rinfo = info->par;
+
+	return radeon_show_one_edid(buf, off, count, rinfo->mon2_EDID);
+}
+
+static struct bin_attribute edid1_attr = {
+	.attr   = {
+		.name	= "edid1",
+		.mode	= 0444,
+	},
+	.size	= EDID_LENGTH,
+	.read	= radeon_show_edid1,
+};
+
+static struct bin_attribute edid2_attr = {
+	.attr   = {
+		.name	= "edid2",
+		.mode	= 0444,
+	},
+	.size	= EDID_LENGTH,
+	.read	= radeon_show_edid2,
+};
+
+
+static int radeonfb_pci_register(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct radeonfb_info *rinfo;
+	int ret;
+	unsigned char c1, c2;
+	int err = 0;
+
+	pr_debug("radeonfb_pci_register BEGIN\n");
+	
+	/* Enable device in PCI config */
+	ret = pci_enable_device(pdev);
+	if (ret < 0) {
+		printk(KERN_ERR "radeonfb (%s): Cannot enable PCI device\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+
+	info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);
+	if (!info) {
+		printk (KERN_ERR "radeonfb (%s): could not allocate memory\n",
+			pci_name(pdev));
+		ret = -ENOMEM;
+		goto err_disable;
+	}
+	rinfo = info->par;
+	rinfo->info = info;	
+	rinfo->pdev = pdev;
+	
+	spin_lock_init(&rinfo->reg_lock);
+	init_timer(&rinfo->lvds_timer);
+	rinfo->lvds_timer.function = radeon_lvds_timer_func;
+	rinfo->lvds_timer.data = (unsigned long)rinfo;
+
+	c1 = ent->device >> 8;
+	c2 = ent->device & 0xff;
+	if (isprint(c1) && isprint(c2))
+		snprintf(rinfo->name, sizeof(rinfo->name),
+			 "ATI Radeon %x \"%c%c\"", ent->device & 0xffff, c1, c2);
+	else
+		snprintf(rinfo->name, sizeof(rinfo->name),
+			 "ATI Radeon %x", ent->device & 0xffff);
+
+	rinfo->family = ent->driver_data & CHIP_FAMILY_MASK;
+	rinfo->chipset = pdev->device;
+	rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
+	rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
+	rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
+
+	/* Set base addrs */
+	rinfo->fb_base_phys = pci_resource_start (pdev, 0);
+	rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
+
+	/* request the mem regions */
+	ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
+	if (ret < 0) {
+		printk( KERN_ERR "radeonfb (%s): cannot request region 0.\n",
+			pci_name(rinfo->pdev));
+		goto err_release_fb;
+	}
+
+	ret = pci_request_region(pdev, 2, "radeonfb mmio");
+	if (ret < 0) {
+		printk( KERN_ERR "radeonfb (%s): cannot request region 2.\n",
+			pci_name(rinfo->pdev));
+		goto err_release_pci0;
+	}
+
+	/* map the regions */
+	rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
+	if (!rinfo->mmio_base) {
+		printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n",
+		       pci_name(rinfo->pdev));
+		ret = -EIO;
+		goto err_release_pci2;
+	}
+
+	rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+
+	/*
+	 * Check for errata
+	 */
+	rinfo->errata = 0;
+	if (rinfo->family == CHIP_FAMILY_R300 &&
+	    (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK)
+	    == CFG_ATI_REV_A11)
+		rinfo->errata |= CHIP_ERRATA_R300_CG;
+
+	if (rinfo->family == CHIP_FAMILY_RV200 ||
+	    rinfo->family == CHIP_FAMILY_RS200)
+		rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+
+	if (rinfo->family == CHIP_FAMILY_RV100 ||
+	    rinfo->family == CHIP_FAMILY_RS100 ||
+	    rinfo->family == CHIP_FAMILY_RS200)
+		rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
+
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+	/* On PPC, we obtain the OF device-node pointer to the firmware
+	 * data for this chip
+	 */
+	rinfo->of_node = pci_device_to_OF_node(pdev);
+	if (rinfo->of_node == NULL)
+		printk(KERN_WARNING "radeonfb (%s): Cannot match card to OF node !\n",
+		       pci_name(rinfo->pdev));
+
+#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
+#ifdef CONFIG_PPC_OF
+	/* On PPC, the firmware sets up a memory mapping that tends
+	 * to cause lockups when enabling the engine. We reconfigure
+	 * the card internal memory mappings properly
+	 */
+	fixup_memory_mappings(rinfo);
+#endif /* CONFIG_PPC_OF */
+
+	/* Get VRAM size and type */
+	radeon_identify_vram(rinfo);
+
+	rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
+
+	do {
+		rinfo->fb_base = ioremap (rinfo->fb_base_phys,
+					  rinfo->mapped_vram);
+	} while (rinfo->fb_base == NULL &&
+		 ((rinfo->mapped_vram /= 2) >= MIN_MAPPED_VRAM));
+
+	if (rinfo->fb_base == NULL) {
+		printk (KERN_ERR "radeonfb (%s): cannot map FB\n",
+			pci_name(rinfo->pdev));
+		ret = -EIO;
+		goto err_unmap_rom;
+	}
+
+	pr_debug("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev),
+	       rinfo->mapped_vram/1024);
+
+	/*
+	 * Map the BIOS ROM if any and retrieve PLL parameters from
+	 * the BIOS. We skip that on mobility chips as the real panel
+	 * values we need aren't in the ROM but in the BIOS image in
+	 * memory. This is definitely not the best meacnism though,
+	 * we really need the arch code to tell us which is the "primary"
+	 * video adapter to use the memory image (or better, the arch
+	 * should provide us a copy of the BIOS image to shield us from
+	 * archs who would store that elsewhere and/or could initialize
+	 * more than one adapter during boot).
+	 */
+	if (!rinfo->is_mobility)
+		radeon_map_ROM(rinfo, pdev);
+
+	/*
+	 * On x86, the primary display on laptop may have it's BIOS
+	 * ROM elsewhere, try to locate it at the legacy memory hole.
+	 * We probably need to make sure this is the primary display,
+	 * but that is difficult without some arch support.
+	 */
+#ifdef CONFIG_X86
+	if (rinfo->bios_seg == NULL)
+		radeon_find_mem_vbios(rinfo);
+#endif
+
+	/* If both above failed, try the BIOS ROM again for mobility
+	 * chips
+	 */
+	if (rinfo->bios_seg == NULL && rinfo->is_mobility)
+		radeon_map_ROM(rinfo, pdev);
+
+	/* Get informations about the board's PLL */
+	radeon_get_pllinfo(rinfo);
+
+#ifdef CONFIG_FB_RADEON_I2C
+	/* Register I2C bus */
+	radeon_create_i2c_busses(rinfo);
+#endif
+
+	/* set all the vital stuff */
+	radeon_set_fbinfo (rinfo);
+
+	/* Probe screen types */
+	radeon_probe_screens(rinfo, monitor_layout, ignore_edid);
+
+	/* Build mode list, check out panel native model */
+	radeon_check_modes(rinfo, mode_option);
+
+	/* Register some sysfs stuff (should be done better) */
+	if (rinfo->mon1_EDID)
+		err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+						&edid1_attr);
+	if (rinfo->mon2_EDID)
+		err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+						&edid2_attr);
+	if (err)
+		pr_warning("%s() Creating sysfs files failed, continuing\n",
+			   __func__);
+
+	/* save current mode regs before we switch into the new one
+	 * so we can restore this upon __exit
+	 */
+	radeon_save_state (rinfo, &rinfo->init_state);
+	memcpy(&rinfo->state, &rinfo->init_state, sizeof(struct radeon_regs));
+
+	/* Setup Power Management capabilities */
+	if (default_dynclk < -1) {
+		/* -2 is special: means  ON on mobility chips and do not
+		 * change on others
+		 */
+		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
+	} else
+		radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep);
+
+	pci_set_drvdata(pdev, info);
+
+	/* Register with fbdev layer */
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		printk (KERN_ERR "radeonfb (%s): could not register framebuffer\n",
+			pci_name(rinfo->pdev));
+		goto err_unmap_fb;
+	}
+
+#ifdef CONFIG_MTRR
+	rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
+						 rinfo->video_ram,
+						 MTRR_TYPE_WRCOMB, 1);
+#endif
+
+	if (backlight)
+		radeonfb_bl_init(rinfo);
+
+	printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
+
+	if (rinfo->bios_seg)
+		radeon_unmap_ROM(rinfo, pdev);
+	pr_debug("radeonfb_pci_register END\n");
+
+	return 0;
+err_unmap_fb:
+	iounmap(rinfo->fb_base);
+err_unmap_rom:
+	kfree(rinfo->mon1_EDID);
+	kfree(rinfo->mon2_EDID);
+	if (rinfo->mon1_modedb)
+		fb_destroy_modedb(rinfo->mon1_modedb);
+	fb_dealloc_cmap(&info->cmap);
+#ifdef CONFIG_FB_RADEON_I2C
+	radeon_delete_i2c_busses(rinfo);
+#endif
+	if (rinfo->bios_seg)
+		radeon_unmap_ROM(rinfo, pdev);
+	iounmap(rinfo->mmio_base);
+err_release_pci2:
+	pci_release_region(pdev, 2);
+err_release_pci0:
+	pci_release_region(pdev, 0);
+err_release_fb:
+        framebuffer_release(info);
+err_disable:
+err_out:
+	return ret;
+}
+
+
+
+static void radeonfb_pci_unregister(struct pci_dev *pdev)
+{
+        struct fb_info *info = pci_get_drvdata(pdev);
+        struct radeonfb_info *rinfo = info->par;
+ 
+        if (!rinfo)
+                return;
+
+	radeonfb_pm_exit(rinfo);
+
+	if (rinfo->mon1_EDID)
+		sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+	if (rinfo->mon2_EDID)
+		sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+
+#if 0
+	/* restore original state
+	 * 
+	 * Doesn't quite work yet, I suspect if we come from a legacy
+	 * VGA mode (or worse, text mode), we need to do some VGA black
+	 * magic here that I know nothing about. --BenH
+	 */
+        radeon_write_mode (rinfo, &rinfo->init_state, 1);
+ #endif
+
+	del_timer_sync(&rinfo->lvds_timer);
+
+#ifdef CONFIG_MTRR
+	if (rinfo->mtrr_hdl >= 0)
+		mtrr_del(rinfo->mtrr_hdl, 0, 0);
+#endif
+
+        unregister_framebuffer(info);
+
+        radeonfb_bl_exit(rinfo);
+
+        iounmap(rinfo->mmio_base);
+        iounmap(rinfo->fb_base);
+ 
+	pci_release_region(pdev, 2);
+	pci_release_region(pdev, 0);
+
+	kfree(rinfo->mon1_EDID);
+	kfree(rinfo->mon2_EDID);
+	if (rinfo->mon1_modedb)
+		fb_destroy_modedb(rinfo->mon1_modedb);
+#ifdef CONFIG_FB_RADEON_I2C
+	radeon_delete_i2c_busses(rinfo);
+#endif        
+	fb_dealloc_cmap(&info->cmap);
+        framebuffer_release(info);
+}
+
+
+static struct pci_driver radeonfb_driver = {
+	.name		= "radeonfb",
+	.id_table	= radeonfb_pci_table,
+	.probe		= radeonfb_pci_register,
+	.remove		= radeonfb_pci_unregister,
+#ifdef CONFIG_PM
+	.suspend       	= radeonfb_pci_suspend,
+	.resume		= radeonfb_pci_resume,
+#endif /* CONFIG_PM */
+};
+
+#ifndef MODULE
+static int __init radeonfb_setup (char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep (&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+
+		if (!strncmp(this_opt, "noaccel", 7)) {
+			noaccel = 1;
+		} else if (!strncmp(this_opt, "mirror", 6)) {
+			mirror = 1;
+		} else if (!strncmp(this_opt, "force_dfp", 9)) {
+			force_dfp = 1;
+		} else if (!strncmp(this_opt, "panel_yres:", 11)) {
+			panel_yres = simple_strtoul((this_opt+11), NULL, 0);
+		} else if (!strncmp(this_opt, "backlight:", 10)) {
+			backlight = simple_strtoul(this_opt+10, NULL, 0);
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else if (!strncmp(this_opt, "nomodeset", 9)) {
+			nomodeset = 1;
+		} else if (!strncmp(this_opt, "force_measure_pll", 17)) {
+			force_measure_pll = 1;
+		} else if (!strncmp(this_opt, "ignore_edid", 11)) {
+			ignore_edid = 1;
+#if defined(CONFIG_PM) && defined(CONFIG_X86)
+	 	} else if (!strncmp(this_opt, "force_sleep", 11)) {
+			force_sleep = 1;
+		} else if (!strncmp(this_opt, "ignore_devlist", 14)) {
+			ignore_devlist = 1;
+#endif
+		} else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+#endif  /*  MODULE  */
+
+static int __init radeonfb_init (void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("radeonfb", &option))
+		return -ENODEV;
+	radeonfb_setup(option);
+#endif
+	return pci_register_driver (&radeonfb_driver);
+}
+
+
+static void __exit radeonfb_exit (void)
+{
+	pci_unregister_driver (&radeonfb_driver);
+}
+
+module_init(radeonfb_init);
+module_exit(radeonfb_exit);
+
+MODULE_AUTHOR("Ani Joshi");
+MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
+MODULE_LICENSE("GPL");
+module_param(noaccel, bool, 0);
+module_param(default_dynclk, int, 0);
+MODULE_PARM_DESC(default_dynclk, "int: -2=enable on mobility only,-1=do not change,0=off,1=on");
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+module_param(nomodeset, bool, 0);
+MODULE_PARM_DESC(nomodeset, "bool: disable actual setting of video mode");
+module_param(mirror, bool, 0);
+MODULE_PARM_DESC(mirror, "bool: mirror the display to both monitors");
+module_param(force_dfp, bool, 0);
+MODULE_PARM_DESC(force_dfp, "bool: force display to dfp");
+module_param(ignore_edid, bool, 0);
+MODULE_PARM_DESC(ignore_edid, "bool: Ignore EDID data when doing DDC probe");
+module_param(monitor_layout, charp, 0);
+MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)");
+module_param(force_measure_pll, bool, 0);
+MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
+#endif
+module_param(panel_yres, int, 0);
+MODULE_PARM_DESC(panel_yres, "int: set panel yres");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+#if defined(CONFIG_PM) && defined(CONFIG_X86)
+module_param(force_sleep, bool, 0);
+MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware");
+module_param(ignore_devlist, bool, 0);
+MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops");
+#endif
diff --git a/drivers/video/fbdev/aty/radeon_i2c.c b/drivers/video/fbdev/aty/radeon_i2c.c
new file mode 100644
index 000000000000..ab1d0fd76316
--- /dev/null
+++ b/drivers/video/fbdev/aty/radeon_i2c.c
@@ -0,0 +1,167 @@
+#include "radeonfb.h"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/io.h>
+
+#include <video/radeon.h>
+#include "../edid.h"
+
+static void radeon_gpio_setscl(void* data, int state)
+{
+	struct radeon_i2c_chan 	*chan = data;
+	struct radeonfb_info	*rinfo = chan->rinfo;
+	u32			val;
+	
+	val = INREG(chan->ddc_reg) & ~(VGA_DDC_CLK_OUT_EN);
+	if (!state)
+		val |= VGA_DDC_CLK_OUT_EN;
+
+	OUTREG(chan->ddc_reg, val);
+	(void)INREG(chan->ddc_reg);
+}
+
+static void radeon_gpio_setsda(void* data, int state)
+{
+	struct radeon_i2c_chan 	*chan = data;
+	struct radeonfb_info	*rinfo = chan->rinfo;
+	u32			val;
+	
+	val = INREG(chan->ddc_reg) & ~(VGA_DDC_DATA_OUT_EN);
+	if (!state)
+		val |= VGA_DDC_DATA_OUT_EN;
+
+	OUTREG(chan->ddc_reg, val);
+	(void)INREG(chan->ddc_reg);
+}
+
+static int radeon_gpio_getscl(void* data)
+{
+	struct radeon_i2c_chan 	*chan = data;
+	struct radeonfb_info	*rinfo = chan->rinfo;
+	u32			val;
+	
+	val = INREG(chan->ddc_reg);
+
+	return (val & VGA_DDC_CLK_INPUT) ? 1 : 0;
+}
+
+static int radeon_gpio_getsda(void* data)
+{
+	struct radeon_i2c_chan 	*chan = data;
+	struct radeonfb_info	*rinfo = chan->rinfo;
+	u32			val;
+	
+	val = INREG(chan->ddc_reg);
+
+	return (val & VGA_DDC_DATA_INPUT) ? 1 : 0;
+}
+
+static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
+{
+	int rc;
+
+	snprintf(chan->adapter.name, sizeof(chan->adapter.name),
+		 "radeonfb %s", name);
+	chan->adapter.owner		= THIS_MODULE;
+	chan->adapter.algo_data		= &chan->algo;
+	chan->adapter.dev.parent	= &chan->rinfo->pdev->dev;
+	chan->algo.setsda		= radeon_gpio_setsda;
+	chan->algo.setscl		= radeon_gpio_setscl;
+	chan->algo.getsda		= radeon_gpio_getsda;
+	chan->algo.getscl		= radeon_gpio_getscl;
+	chan->algo.udelay		= 10;
+	chan->algo.timeout		= 20;
+	chan->algo.data 		= chan;	
+	
+	i2c_set_adapdata(&chan->adapter, chan);
+	
+	/* Raise SCL and SDA */
+	radeon_gpio_setsda(chan, 1);
+	radeon_gpio_setscl(chan, 1);
+	udelay(20);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		dev_dbg(&chan->rinfo->pdev->dev, "I2C bus %s registered.\n", name);
+	else
+		dev_warn(&chan->rinfo->pdev->dev, "Failed to register I2C bus %s.\n", name);
+	return rc;
+}
+
+void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
+{
+	rinfo->i2c[0].rinfo	= rinfo;
+	rinfo->i2c[0].ddc_reg	= GPIO_MONID;
+#ifndef CONFIG_PPC
+	rinfo->i2c[0].adapter.class = I2C_CLASS_HWMON;
+#endif
+	radeon_setup_i2c_bus(&rinfo->i2c[0], "monid");
+
+	rinfo->i2c[1].rinfo	= rinfo;
+	rinfo->i2c[1].ddc_reg	= GPIO_DVI_DDC;
+	radeon_setup_i2c_bus(&rinfo->i2c[1], "dvi");
+
+	rinfo->i2c[2].rinfo	= rinfo;
+	rinfo->i2c[2].ddc_reg	= GPIO_VGA_DDC;
+	radeon_setup_i2c_bus(&rinfo->i2c[2], "vga");
+
+	rinfo->i2c[3].rinfo	= rinfo;
+	rinfo->i2c[3].ddc_reg	= GPIO_CRT2_DDC;
+	radeon_setup_i2c_bus(&rinfo->i2c[3], "crt2");
+}
+
+void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
+{
+	if (rinfo->i2c[0].rinfo)
+		i2c_del_adapter(&rinfo->i2c[0].adapter);
+	rinfo->i2c[0].rinfo = NULL;
+
+	if (rinfo->i2c[1].rinfo)
+		i2c_del_adapter(&rinfo->i2c[1].adapter);
+	rinfo->i2c[1].rinfo = NULL;
+
+	if (rinfo->i2c[2].rinfo)
+		i2c_del_adapter(&rinfo->i2c[2].adapter);
+	rinfo->i2c[2].rinfo = NULL;
+
+	if (rinfo->i2c[3].rinfo)
+		i2c_del_adapter(&rinfo->i2c[3].adapter);
+	rinfo->i2c[3].rinfo = NULL;
+}
+
+int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
+			       u8 **out_edid)
+{
+	u8 *edid;
+
+	edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter);
+
+	if (out_edid)
+		*out_edid = edid;
+	if (!edid) {
+		pr_debug("radeonfb: I2C (port %d) ... not found\n", conn);
+		return MT_NONE;
+	}
+	if (edid[0x14] & 0x80) {
+		/* Fix detection using BIOS tables */
+		if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
+		    (INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
+			pr_debug("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
+			return MT_LCD;
+		} else {
+			pr_debug("radeonfb: I2C (port %d) ... found TMDS panel\n", conn);
+			return MT_DFP;
+		}
+	}
+	pr_debug("radeonfb: I2C (port %d) ... found CRT display\n", conn);
+	return MT_CRT;
+}
+
diff --git a/drivers/video/fbdev/aty/radeon_monitor.c b/drivers/video/fbdev/aty/radeon_monitor.c
new file mode 100644
index 000000000000..bc078d50d8f1
--- /dev/null
+++ b/drivers/video/fbdev/aty/radeon_monitor.c
@@ -0,0 +1,1052 @@
+#include "radeonfb.h"
+
+#include <linux/slab.h>
+
+#include "../edid.h"
+
+static struct fb_var_screeninfo radeonfb_default_var = {
+	.xres		= 640,
+	.yres		= 480,
+	.xres_virtual	= 640,
+	.yres_virtual	= 480,
+	.bits_per_pixel = 8,
+	.red		= { .length = 8 },
+	.green		= { .length = 8 },
+	.blue		= { .length = 8 },
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.pixclock	= 39721,
+	.left_margin	= 40,
+	.right_margin	= 24,
+	.upper_margin	= 32,
+	.lower_margin	= 11,
+	.hsync_len	= 96,
+	.vsync_len	= 2,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
+static char *radeon_get_mon_name(int type)
+{
+	char *pret = NULL;
+
+	switch (type) {
+		case MT_NONE:
+			pret = "no";
+			break;
+		case MT_CRT:
+			pret = "CRT";
+			break;
+		case MT_DFP:
+			pret = "DFP";
+			break;
+		case MT_LCD:
+			pret = "LCD";
+			break;
+		case MT_CTV:
+			pret = "CTV";
+			break;
+		case MT_STV:
+			pret = "STV";
+			break;
+	}
+
+	return pret;
+}
+
+
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+/*
+ * Try to find monitor informations & EDID data out of the Open Firmware
+ * device-tree. This also contains some "hacks" to work around a few machine
+ * models with broken OF probing by hard-coding known EDIDs for some Mac
+ * laptops internal LVDS panel. (XXX: not done yet)
+ */
+static int radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,
+				     int hdno)
+{
+        static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID",
+				     "EDID1", "EDID2",  NULL };
+	const u8 *pedid = NULL;
+	const u8 *pmt = NULL;
+	u8 *tmp;
+        int i, mt = MT_NONE;  
+	
+	pr_debug("analyzing OF properties...\n");
+	pmt = of_get_property(dp, "display-type", NULL);
+	if (!pmt)
+		return MT_NONE;
+	pr_debug("display-type: %s\n", pmt);
+	/* OF says "LCD" for DFP as well, we discriminate from the caller of this
+	 * function
+	 */
+	if (!strcmp(pmt, "LCD") || !strcmp(pmt, "DFP"))
+		mt = MT_DFP;
+	else if (!strcmp(pmt, "CRT"))
+		mt = MT_CRT;
+	else {
+		if (strcmp(pmt, "NONE") != 0)
+			printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n",
+			       pmt);
+		return MT_NONE;
+	}
+
+	for (i = 0; propnames[i] != NULL; ++i) {
+		pedid = of_get_property(dp, propnames[i], NULL);
+		if (pedid != NULL)
+			break;
+	}
+	/* We didn't find the EDID in the leaf node, some cards will actually
+	 * put EDID1/EDID2 in the parent, look for these (typically M6 tipb).
+	 * single-head cards have hdno == -1 and skip this step
+	 */
+	if (pedid == NULL && dp->parent && (hdno != -1))
+		pedid = of_get_property(dp->parent,
+				(hdno == 0) ? "EDID1" : "EDID2", NULL);
+	if (pedid == NULL && dp->parent && (hdno == 0))
+		pedid = of_get_property(dp->parent, "EDID", NULL);
+	if (pedid == NULL)
+		return mt;
+
+	tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
+	if (!tmp)
+		return mt;
+	*out_EDID = tmp;
+	return mt;
+}
+
+static int radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no,
+				u8 **out_EDID)
+{
+        struct device_node *dp;
+
+	pr_debug("radeon_probe_OF_head\n");
+
+        dp = rinfo->of_node;
+        while (dp == NULL)
+		return MT_NONE;
+
+	if (rinfo->has_CRTC2) {
+		const char *pname;
+		int len, second = 0;
+
+		dp = dp->child;
+		do {
+			if (!dp)
+				return MT_NONE;
+			pname = of_get_property(dp, "name", NULL);
+			if (!pname)
+				return MT_NONE;
+			len = strlen(pname);
+			pr_debug("head: %s (letter: %c, head_no: %d)\n",
+			       pname, pname[len-1], head_no);
+			if (pname[len-1] == 'A' && head_no == 0) {
+				int mt = radeon_parse_montype_prop(dp, out_EDID, 0);
+				/* Maybe check for LVDS_GEN_CNTL here ? I need to check out
+				 * what OF does when booting with lid closed
+				 */
+				if (mt == MT_DFP && rinfo->is_mobility)
+					mt = MT_LCD;
+				return mt;
+			} else if (pname[len-1] == 'B' && head_no == 1)
+				return radeon_parse_montype_prop(dp, out_EDID, 1);
+			second = 1;
+			dp = dp->sibling;
+		} while(!second);
+	} else {
+		if (head_no > 0)
+			return MT_NONE;
+		return radeon_parse_montype_prop(dp, out_EDID, -1);
+	}
+        return MT_NONE;
+}
+#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
+
+
+static int radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
+{
+	unsigned long tmp, tmp0;
+	char stmp[30];
+	int i;
+
+	if (!rinfo->bios_seg)
+		return 0;
+
+	if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) {
+		printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n");
+		rinfo->panel_info.pwr_delay = 200;
+		return 0;
+	}
+
+	for(i=0; i<24; i++)
+		stmp[i] = BIOS_IN8(tmp+i+1);
+	stmp[24] = 0;
+	printk("radeonfb: panel ID string: %s\n", stmp);
+	rinfo->panel_info.xres = BIOS_IN16(tmp + 25);
+	rinfo->panel_info.yres = BIOS_IN16(tmp + 27);
+	printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n",
+		rinfo->panel_info.xres, rinfo->panel_info.yres);
+
+	rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);
+	pr_debug("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay);
+	if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0)
+		rinfo->panel_info.pwr_delay = 2000;
+
+	/*
+	 * Some panels only work properly with some divider combinations
+	 */
+	rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46);
+	rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48);
+	rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49);
+	if (rinfo->panel_info.ref_divider != 0 &&
+	    rinfo->panel_info.fbk_divider > 3) {
+		rinfo->panel_info.use_bios_dividers = 1;
+		printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n");
+		pr_debug("ref_divider = %x\n", rinfo->panel_info.ref_divider);
+		pr_debug("post_divider = %x\n", rinfo->panel_info.post_divider);
+		pr_debug("fbk_divider = %x\n", rinfo->panel_info.fbk_divider);
+	}
+	pr_debug("Scanning BIOS table ...\n");
+	for(i=0; i<32; i++) {
+		tmp0 = BIOS_IN16(tmp+64+i*2);
+		if (tmp0 == 0)
+			break;
+		pr_debug(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2));
+		if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) &&
+		    (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) {
+			rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8;
+			rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) -
+							 BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff;
+			rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8;
+			rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26);
+			rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26);
+			rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11;
+			rinfo->panel_info.clock = BIOS_IN16(tmp0+9);
+			/* Assume high active syncs for now until ATI tells me more... maybe we
+			 * can probe register values here ?
+			 */
+			rinfo->panel_info.hAct_high = 1;
+			rinfo->panel_info.vAct_high = 1;
+			/* Mark panel infos valid */
+			rinfo->panel_info.valid = 1;
+
+			pr_debug("Found panel in BIOS table:\n");
+			pr_debug("  hblank: %d\n", rinfo->panel_info.hblank);
+			pr_debug("  hOver_plus: %d\n", rinfo->panel_info.hOver_plus);
+			pr_debug("  hSync_width: %d\n", rinfo->panel_info.hSync_width);
+			pr_debug("  vblank: %d\n", rinfo->panel_info.vblank);
+			pr_debug("  vOver_plus: %d\n", rinfo->panel_info.vOver_plus);
+			pr_debug("  vSync_width: %d\n", rinfo->panel_info.vSync_width);
+			pr_debug("  clock: %d\n", rinfo->panel_info.clock);
+				
+			return 1;
+		}
+	}
+	pr_debug("Didn't find panel in BIOS table !\n");
+
+	return 0;
+}
+
+/* Try to extract the connector informations from the BIOS. This
+ * doesn't quite work yet, but it's output is still useful for
+ * debugging
+ */
+static void radeon_parse_connector_info(struct radeonfb_info *rinfo)
+{
+	int offset, chips, connectors, tmp, i, conn, type;
+
+	static char* __conn_type_table[16] = {
+		"NONE", "Proprietary", "CRT", "DVI-I", "DVI-D", "Unknown", "Unknown",
+		"Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
+		"Unknown", "Unknown", "Unknown"
+	};
+
+	if (!rinfo->bios_seg)
+		return;
+
+	offset = BIOS_IN16(rinfo->fp_bios_start + 0x50);
+	if (offset == 0) {
+		printk(KERN_WARNING "radeonfb: No connector info table detected\n");
+		return;
+	}
+
+	/* Don't do much more at this point but displaying the data if
+	 * DEBUG is enabled
+	 */
+	chips = BIOS_IN8(offset++) >> 4;
+	pr_debug("%d chips in connector info\n", chips);
+	for (i = 0; i < chips; i++) {
+		tmp = BIOS_IN8(offset++);
+		connectors = tmp & 0x0f;
+		pr_debug(" - chip %d has %d connectors\n", tmp >> 4, connectors);
+		for (conn = 0; ; conn++) {
+			tmp = BIOS_IN16(offset);
+			if (tmp == 0)
+				break;
+			offset += 2;
+			type = (tmp >> 12) & 0x0f;
+			pr_debug("  * connector %d of type %d (%s) : %04x\n",
+			       conn, type, __conn_type_table[type], tmp);
+		}
+	}
+}
+
+
+/*
+ * Probe physical connection of a CRT. This code comes from XFree
+ * as well and currently is only implemented for the CRT DAC, the
+ * code for the TVDAC is commented out in XFree as "non working"
+ */
+static int radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac)
+{
+    int	          connected = 0;
+
+    /* the monitor either wasn't connected or it is a non-DDC CRT.
+     * try to probe it
+     */
+    if (is_crt_dac) {
+	unsigned long ulOrigVCLK_ECP_CNTL;
+	unsigned long ulOrigDAC_CNTL;
+	unsigned long ulOrigDAC_EXT_CNTL;
+	unsigned long ulOrigCRTC_EXT_CNTL;
+	unsigned long ulData;
+	unsigned long ulMask;
+
+	ulOrigVCLK_ECP_CNTL = INPLL(VCLK_ECP_CNTL);
+
+	ulData              = ulOrigVCLK_ECP_CNTL;
+	ulData             &= ~(PIXCLK_ALWAYS_ONb
+				| PIXCLK_DAC_ALWAYS_ONb);
+	ulMask              = ~(PIXCLK_ALWAYS_ONb
+				| PIXCLK_DAC_ALWAYS_ONb);
+	OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);
+
+	ulOrigCRTC_EXT_CNTL = INREG(CRTC_EXT_CNTL);
+	ulData              = ulOrigCRTC_EXT_CNTL;
+	ulData             |= CRTC_CRT_ON;
+	OUTREG(CRTC_EXT_CNTL, ulData);
+   
+	ulOrigDAC_EXT_CNTL = INREG(DAC_EXT_CNTL);
+	ulData             = ulOrigDAC_EXT_CNTL;
+	ulData            &= ~DAC_FORCE_DATA_MASK;
+	ulData            |=  (DAC_FORCE_BLANK_OFF_EN
+			       |DAC_FORCE_DATA_EN
+			       |DAC_FORCE_DATA_SEL_MASK);
+	if ((rinfo->family == CHIP_FAMILY_RV250) ||
+	    (rinfo->family == CHIP_FAMILY_RV280))
+	    ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT);
+	else
+	    ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT);
+
+	OUTREG(DAC_EXT_CNTL, ulData);
+
+	ulOrigDAC_CNTL     = INREG(DAC_CNTL);
+	ulData             = ulOrigDAC_CNTL;
+	ulData            |= DAC_CMP_EN;
+	ulData            &= ~(DAC_RANGE_CNTL_MASK
+			       | DAC_PDWN);
+	ulData            |= 0x2;
+	OUTREG(DAC_CNTL, ulData);
+
+	mdelay(1);
+
+	ulData     = INREG(DAC_CNTL);
+	connected =  (DAC_CMP_OUTPUT & ulData) ? 1 : 0;
+  
+	ulData    = ulOrigVCLK_ECP_CNTL;
+	ulMask    = 0xFFFFFFFFL;
+	OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);
+
+	OUTREG(DAC_CNTL,      ulOrigDAC_CNTL     );
+	OUTREG(DAC_EXT_CNTL,  ulOrigDAC_EXT_CNTL );
+	OUTREG(CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);
+    }
+
+    return connected ? MT_CRT : MT_NONE;
+}
+
+/*
+ * Parse the "monitor_layout" string if any. This code is mostly
+ * copied from XFree's radeon driver
+ */
+static int radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
+				       const char *monitor_layout)
+{
+	char s1[5], s2[5];
+	int i = 0, second = 0;
+	const char *s;
+
+	if (!monitor_layout)
+		return 0;
+
+	s = monitor_layout;
+	do {
+		switch(*s) {
+		case ',':
+			s1[i] = '\0';
+			i = 0;
+			second = 1;
+			break;
+		case ' ':
+		case '\0':
+			break;
+		default:
+			if (i > 4)
+				break;
+			if (second)
+				s2[i] = *s;
+			else
+				s1[i] = *s;
+			i++;
+		}
+
+		if (i > 4)
+			i = 4;
+
+	} while (*s++);
+	if (second)
+		s2[i] = 0;
+	else {
+		s1[i] = 0;
+		s2[0] = 0;
+	}
+	if (strcmp(s1, "CRT") == 0)
+		rinfo->mon1_type = MT_CRT;
+	else if (strcmp(s1, "TMDS") == 0)
+		rinfo->mon1_type = MT_DFP;
+	else if (strcmp(s1, "LVDS") == 0)
+		rinfo->mon1_type = MT_LCD;
+
+	if (strcmp(s2, "CRT") == 0)
+		rinfo->mon2_type = MT_CRT;
+	else if (strcmp(s2, "TMDS") == 0)
+		rinfo->mon2_type = MT_DFP;
+	else if (strcmp(s2, "LVDS") == 0)
+		rinfo->mon2_type = MT_LCD;
+
+	return 1;
+}
+
+/*
+ * Probe display on both primary and secondary card's connector (if any)
+ * by various available techniques (i2c, OF device tree, BIOS, ...) and
+ * try to retrieve EDID. The algorithm here comes from XFree's radeon
+ * driver
+ */
+void radeon_probe_screens(struct radeonfb_info *rinfo,
+			  const char *monitor_layout, int ignore_edid)
+{
+#ifdef CONFIG_FB_RADEON_I2C
+	int ddc_crt2_used = 0;	
+#endif
+	int tmp, i;
+
+	radeon_parse_connector_info(rinfo);
+
+	if (radeon_parse_monitor_layout(rinfo, monitor_layout)) {
+
+		/*
+		 * If user specified a monitor_layout option, use it instead
+		 * of auto-detecting. Maybe we should only use this argument
+		 * on the first radeon card probed or provide a way to specify
+		 * a layout for each card ?
+		 */
+
+		pr_debug("Using specified monitor layout: %s", monitor_layout);
+#ifdef CONFIG_FB_RADEON_I2C
+		if (!ignore_edid) {
+			if (rinfo->mon1_type != MT_NONE)
+				if (!radeon_probe_i2c_connector(rinfo, ddc_dvi, &rinfo->mon1_EDID)) {
+					radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon1_EDID);
+					ddc_crt2_used = 1;
+				}
+			if (rinfo->mon2_type != MT_NONE)
+				if (!radeon_probe_i2c_connector(rinfo, ddc_vga, &rinfo->mon2_EDID) &&
+				    !ddc_crt2_used)
+					radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon2_EDID);
+		}
+#endif /* CONFIG_FB_RADEON_I2C */
+		if (rinfo->mon1_type == MT_NONE) {
+			if (rinfo->mon2_type != MT_NONE) {
+				rinfo->mon1_type = rinfo->mon2_type;
+				rinfo->mon1_EDID = rinfo->mon2_EDID;
+			} else {
+				rinfo->mon1_type = MT_CRT;
+				printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n");
+			}
+			rinfo->mon2_type = MT_NONE;
+			rinfo->mon2_EDID = NULL;
+		}
+	} else {
+		/*
+		 * Auto-detecting display type (well... trying to ...)
+		 */
+		
+		pr_debug("Starting monitor auto detection...\n");
+
+#if defined(DEBUG) && defined(CONFIG_FB_RADEON_I2C)
+		{
+			u8 *EDIDs[4] = { NULL, NULL, NULL, NULL };
+			int mon_types[4] = {MT_NONE, MT_NONE, MT_NONE, MT_NONE};
+			int i;
+
+			for (i = 0; i < 4; i++)
+				mon_types[i] = radeon_probe_i2c_connector(rinfo,
+									  i+1, &EDIDs[i]);
+		}
+#endif /* DEBUG */
+		/*
+		 * Old single head cards
+		 */
+		if (!rinfo->has_CRTC2) {
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+			if (rinfo->mon1_type == MT_NONE)
+				rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
+									&rinfo->mon1_EDID);
+#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
+#ifdef CONFIG_FB_RADEON_I2C
+			if (rinfo->mon1_type == MT_NONE)
+				rinfo->mon1_type =
+					radeon_probe_i2c_connector(rinfo, ddc_dvi,
+								   &rinfo->mon1_EDID);
+			if (rinfo->mon1_type == MT_NONE)
+				rinfo->mon1_type =
+					radeon_probe_i2c_connector(rinfo, ddc_vga,
+								   &rinfo->mon1_EDID);
+			if (rinfo->mon1_type == MT_NONE)
+				rinfo->mon1_type =
+					radeon_probe_i2c_connector(rinfo, ddc_crt2,
+								   &rinfo->mon1_EDID);	
+#endif /* CONFIG_FB_RADEON_I2C */
+			if (rinfo->mon1_type == MT_NONE)
+				rinfo->mon1_type = MT_CRT;
+			goto bail;
+		}
+
+		/*
+		 * Check for cards with reversed DACs or TMDS controllers using BIOS
+		 */
+		if (rinfo->bios_seg &&
+		    (tmp = BIOS_IN16(rinfo->fp_bios_start + 0x50))) {
+			for (i = 1; i < 4; i++) {
+				unsigned int tmp0;
+
+				if (!BIOS_IN8(tmp + i*2) && i > 1)
+					break;
+				tmp0 = BIOS_IN16(tmp + i*2);
+				if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0x0f) == ddc_dvi)) {
+					rinfo->reversed_DAC = 1;
+					printk(KERN_INFO "radeonfb: Reversed DACs detected\n");
+				}
+				if ((((tmp0 >> 8) & 0x0f) == ddc_dvi) && ((tmp0 >> 4) & 0x01)) {
+					rinfo->reversed_TMDS = 1;
+					printk(KERN_INFO "radeonfb: Reversed TMDS detected\n");
+				}
+			}
+		}
+
+		/*
+		 * Probe primary head (DVI or laptop internal panel)
+		 */
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+		if (rinfo->mon1_type == MT_NONE)
+			rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
+								&rinfo->mon1_EDID);
+#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
+#ifdef CONFIG_FB_RADEON_I2C
+		if (rinfo->mon1_type == MT_NONE)
+			rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
+								      &rinfo->mon1_EDID);
+		if (rinfo->mon1_type == MT_NONE) {
+			rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
+								      &rinfo->mon1_EDID);
+			if (rinfo->mon1_type != MT_NONE)
+				ddc_crt2_used = 1;
+		}
+#endif /* CONFIG_FB_RADEON_I2C */
+		if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility &&
+		    ((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4))
+		     || (INREG(LVDS_GEN_CNTL) & LVDS_ON))) {
+			rinfo->mon1_type = MT_LCD;
+			printk("Non-DDC laptop panel detected\n");
+		}
+		if (rinfo->mon1_type == MT_NONE)
+			rinfo->mon1_type = radeon_crt_is_connected(rinfo, rinfo->reversed_DAC);
+
+		/*
+		 * Probe secondary head (mostly VGA, can be DVI)
+		 */
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+		if (rinfo->mon2_type == MT_NONE)
+			rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1,
+								&rinfo->mon2_EDID);
+#endif /* CONFIG_PPC_OF || defined(CONFIG_SPARC) */
+#ifdef CONFIG_FB_RADEON_I2C
+		if (rinfo->mon2_type == MT_NONE)
+			rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_vga,
+								      &rinfo->mon2_EDID);
+		if (rinfo->mon2_type == MT_NONE && !ddc_crt2_used)
+			rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
+								      &rinfo->mon2_EDID);
+#endif /* CONFIG_FB_RADEON_I2C */
+		if (rinfo->mon2_type == MT_NONE)
+			rinfo->mon2_type = radeon_crt_is_connected(rinfo, !rinfo->reversed_DAC);
+
+		/*
+		 * If we only detected port 2, we swap them, if none detected,
+		 * assume CRT (maybe fallback to old BIOS_SCRATCH stuff ? or look
+		 * at FP registers ?)
+		 */
+		if (rinfo->mon1_type == MT_NONE) {
+			if (rinfo->mon2_type != MT_NONE) {
+				rinfo->mon1_type = rinfo->mon2_type;
+				rinfo->mon1_EDID = rinfo->mon2_EDID;
+			} else
+				rinfo->mon1_type = MT_CRT;
+			rinfo->mon2_type = MT_NONE;
+			rinfo->mon2_EDID = NULL;
+		}
+
+		/*
+		 * Deal with reversed TMDS
+		 */
+		if (rinfo->reversed_TMDS) {
+			/* Always keep internal TMDS as primary head */
+			if (rinfo->mon1_type == MT_DFP || rinfo->mon2_type == MT_DFP) {
+				int tmp_type = rinfo->mon1_type;
+				u8 *tmp_EDID = rinfo->mon1_EDID;
+				rinfo->mon1_type = rinfo->mon2_type;
+				rinfo->mon1_EDID = rinfo->mon2_EDID;
+				rinfo->mon2_type = tmp_type;
+				rinfo->mon2_EDID = tmp_EDID;
+				if (rinfo->mon1_type == MT_CRT || rinfo->mon2_type == MT_CRT)
+					rinfo->reversed_DAC ^= 1;
+			}
+		}
+	}
+	if (ignore_edid) {
+		kfree(rinfo->mon1_EDID);
+		rinfo->mon1_EDID = NULL;
+		kfree(rinfo->mon2_EDID);
+		rinfo->mon2_EDID = NULL;
+	}
+
+ bail:
+	printk(KERN_INFO "radeonfb: Monitor 1 type %s found\n",
+	       radeon_get_mon_name(rinfo->mon1_type));
+	if (rinfo->mon1_EDID)
+		printk(KERN_INFO "radeonfb: EDID probed\n");
+	if (!rinfo->has_CRTC2)
+		return;
+	printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n",
+	       radeon_get_mon_name(rinfo->mon2_type));
+	if (rinfo->mon2_EDID)
+		printk(KERN_INFO "radeonfb: EDID probed\n");
+}
+
+
+/*
+ * This functions applyes any arch/model/machine specific fixups
+ * to the panel info. It may eventually alter EDID block as
+ * well or whatever is specific to a given model and not probed
+ * properly by the default code
+ */
+static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
+{
+#ifdef CONFIG_PPC_OF
+	/*
+	 * LCD Flat panels should use fixed dividers, we enfore that on
+	 * PPC only for now...
+	 */
+	if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
+	    && rinfo->is_mobility) {
+		int ppll_div_sel;
+		u32 ppll_divn;
+		ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
+		radeon_pll_errata_after_index(rinfo);
+		ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
+		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
+		rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff;
+		rinfo->panel_info.post_divider = (ppll_divn >> 16) & 0x7;
+		rinfo->panel_info.use_bios_dividers = 1;
+
+		printk(KERN_DEBUG "radeonfb: Using Firmware dividers 0x%08x "
+		       "from PPLL %d\n",
+		       rinfo->panel_info.fbk_divider |
+		       (rinfo->panel_info.post_divider << 16),
+		       ppll_div_sel);
+	}
+#endif /* CONFIG_PPC_OF */
+}
+
+
+/*
+ * Fill up panel infos from a mode definition, either returned by the EDID
+ * or from the default mode when we can't do any better
+ */
+static void radeon_var_to_panel_info(struct radeonfb_info *rinfo, struct fb_var_screeninfo *var)
+{
+	rinfo->panel_info.xres = var->xres;
+	rinfo->panel_info.yres = var->yres;
+	rinfo->panel_info.clock = 100000000 / var->pixclock;
+	rinfo->panel_info.hOver_plus = var->right_margin;
+	rinfo->panel_info.hSync_width = var->hsync_len;
+       	rinfo->panel_info.hblank = var->left_margin +
+		(var->right_margin + var->hsync_len);
+	rinfo->panel_info.vOver_plus = var->lower_margin;
+	rinfo->panel_info.vSync_width = var->vsync_len;
+       	rinfo->panel_info.vblank = var->upper_margin +
+		(var->lower_margin + var->vsync_len);
+	rinfo->panel_info.hAct_high =
+		(var->sync & FB_SYNC_HOR_HIGH_ACT) != 0;
+	rinfo->panel_info.vAct_high =
+		(var->sync & FB_SYNC_VERT_HIGH_ACT) != 0;
+	rinfo->panel_info.valid = 1;
+	/* We use a default of 200ms for the panel power delay, 
+	 * I need to have a real schedule() instead of mdelay's in the panel code.
+	 * we might be possible to figure out a better power delay either from
+	 * MacOS OF tree or from the EDID block (proprietary extensions ?)
+	 */
+	rinfo->panel_info.pwr_delay = 200;
+}
+
+static void radeon_videomode_to_var(struct fb_var_screeninfo *var,
+				    const struct fb_videomode *mode)
+{
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->sync = mode->sync;
+	var->vmode = mode->vmode;
+}
+
+#ifdef CONFIG_PPC_PSERIES
+static int is_powerblade(const char *model)
+{
+	struct device_node *root;
+	const char* cp;
+	int len, l, rc = 0;
+
+	root = of_find_node_by_path("/");
+	if (root && model) {
+		l = strlen(model);
+		cp = of_get_property(root, "model", &len);
+		if (cp)
+			rc = memcmp(model, cp, min(len, l)) == 0;
+		of_node_put(root);
+	}
+	return rc;
+}
+#endif
+
+/*
+ * Build the modedb for head 1 (head 2 will come later), check panel infos
+ * from either BIOS or EDID, and pick up the default mode
+ */
+void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option)
+{
+	struct fb_info * info = rinfo->info;
+	int has_default_mode = 0;
+
+	/*
+	 * Fill default var first
+	 */
+	info->var = radeonfb_default_var;
+	INIT_LIST_HEAD(&info->modelist);
+
+	/*
+	 * First check out what BIOS has to say
+	 */
+	if (rinfo->mon1_type == MT_LCD)
+		radeon_get_panel_info_BIOS(rinfo);
+
+	/*
+	 * Parse EDID detailed timings and deduce panel infos if any. Right now
+	 * we only deal with first entry returned by parse_EDID, we may do better
+	 * some day...
+	 */
+	if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type != MT_CRT
+	    && rinfo->mon1_EDID) {
+		struct fb_var_screeninfo var;
+		pr_debug("Parsing EDID data for panel info\n");
+		if (fb_parse_edid(rinfo->mon1_EDID, &var) == 0) {
+			if (var.xres >= rinfo->panel_info.xres &&
+			    var.yres >= rinfo->panel_info.yres)
+				radeon_var_to_panel_info(rinfo, &var);
+		}
+	}
+
+	/*
+	 * Do any additional platform/arch fixups to the panel infos
+	 */
+	radeon_fixup_panel_info(rinfo);
+
+	/*
+	 * If we have some valid panel infos, we setup the default mode based on
+	 * those
+	 */
+	if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) {
+		struct fb_var_screeninfo *var = &info->var;
+
+		pr_debug("Setting up default mode based on panel info\n");
+		var->xres = rinfo->panel_info.xres;
+		var->yres = rinfo->panel_info.yres;
+		var->xres_virtual = rinfo->panel_info.xres;
+		var->yres_virtual = rinfo->panel_info.yres;
+		var->xoffset = var->yoffset = 0;
+		var->bits_per_pixel = 8;
+		var->pixclock = 100000000 / rinfo->panel_info.clock;
+		var->left_margin = (rinfo->panel_info.hblank - rinfo->panel_info.hOver_plus
+				    - rinfo->panel_info.hSync_width);
+		var->right_margin = rinfo->panel_info.hOver_plus;
+		var->upper_margin = (rinfo->panel_info.vblank - rinfo->panel_info.vOver_plus
+				     - rinfo->panel_info.vSync_width);
+		var->lower_margin = rinfo->panel_info.vOver_plus;
+		var->hsync_len = rinfo->panel_info.hSync_width;
+		var->vsync_len = rinfo->panel_info.vSync_width;
+		var->sync = 0;
+		if (rinfo->panel_info.hAct_high)
+			var->sync |= FB_SYNC_HOR_HIGH_ACT;
+		if (rinfo->panel_info.vAct_high)
+			var->sync |= FB_SYNC_VERT_HIGH_ACT;
+		var->vmode = 0;
+		has_default_mode = 1;
+	}
+
+	/*
+	 * Now build modedb from EDID
+	 */
+	if (rinfo->mon1_EDID) {
+		fb_edid_to_monspecs(rinfo->mon1_EDID, &info->monspecs);
+		fb_videomode_to_modelist(info->monspecs.modedb,
+					 info->monspecs.modedb_len,
+					 &info->modelist);
+		rinfo->mon1_modedb = info->monspecs.modedb;
+		rinfo->mon1_dbsize = info->monspecs.modedb_len;
+	}
+
+	
+	/*
+	 * Finally, if we don't have panel infos we need to figure some (or
+	 * we try to read it from card), we try to pick a default mode
+	 * and create some panel infos. Whatever...
+	 */
+	if (rinfo->mon1_type != MT_CRT && !rinfo->panel_info.valid) {
+		struct fb_videomode	*modedb;
+		int			dbsize;
+		char			modename[32];
+
+		pr_debug("Guessing panel info...\n");
+		if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
+			u32 tmp = INREG(FP_HORZ_STRETCH) & HORZ_PANEL_SIZE;
+			rinfo->panel_info.xres = ((tmp >> HORZ_PANEL_SHIFT) + 1) * 8;
+			tmp = INREG(FP_VERT_STRETCH) & VERT_PANEL_SIZE;
+			rinfo->panel_info.yres = (tmp >> VERT_PANEL_SHIFT) + 1;
+		}
+		if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
+			printk(KERN_WARNING "radeonfb: Can't find panel size, going back to CRT\n");
+			rinfo->mon1_type = MT_CRT;
+			goto pickup_default;
+		}
+		printk(KERN_WARNING "radeonfb: Assuming panel size %dx%d\n",
+		       rinfo->panel_info.xres, rinfo->panel_info.yres);
+		modedb = rinfo->mon1_modedb;
+		dbsize = rinfo->mon1_dbsize;
+		snprintf(modename, 31, "%dx%d", rinfo->panel_info.xres, rinfo->panel_info.yres);
+		if (fb_find_mode(&info->var, info, modename,
+				 modedb, dbsize, NULL, 8) == 0) {
+			printk(KERN_WARNING "radeonfb: Can't find mode for panel size, going back to CRT\n");
+			rinfo->mon1_type = MT_CRT;
+			goto pickup_default;
+		}
+		has_default_mode = 1;
+		radeon_var_to_panel_info(rinfo, &info->var);
+	}
+
+ pickup_default:
+	/*
+	 * Apply passed-in mode option if any
+	 */
+	if (mode_option) {
+		if (fb_find_mode(&info->var, info, mode_option,
+				 info->monspecs.modedb,
+				 info->monspecs.modedb_len, NULL, 8) != 0)
+			has_default_mode = 1;
+ 	}
+
+#ifdef CONFIG_PPC_PSERIES
+	if (!has_default_mode && (
+		is_powerblade("IBM,8842") || /* JS20 */
+		is_powerblade("IBM,8844") || /* JS21 */
+		is_powerblade("IBM,7998") || /* JS12/JS21/JS22 */
+		is_powerblade("IBM,0792") || /* QS21 */
+		is_powerblade("IBM,0793")    /* QS22 */
+	    )) {
+		printk("Falling back to 800x600 on JSxx hardware\n");
+		if (fb_find_mode(&info->var, info, "800x600@60",
+				 info->monspecs.modedb,
+				 info->monspecs.modedb_len, NULL, 8) != 0)
+			has_default_mode = 1;
+	}
+#endif
+
+	/*
+	 * Still no mode, let's pick up a default from the db
+	 */
+	if (!has_default_mode && info->monspecs.modedb != NULL) {
+		struct fb_monspecs *specs = &info->monspecs;
+		struct fb_videomode *modedb = NULL;
+
+		/* get preferred timing */
+		if (specs->misc & FB_MISC_1ST_DETAIL) {
+			int i;
+
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = &specs->modedb[i];
+					break;
+				}
+			}
+		} else {
+			/* otherwise, get first mode in database */
+			modedb = &specs->modedb[0];
+		}
+		if (modedb != NULL) {
+			info->var.bits_per_pixel = 8;
+			radeon_videomode_to_var(&info->var, modedb);
+			has_default_mode = 1;
+		}
+	}
+	if (1) {
+		struct fb_videomode mode;
+		/* Make sure that whatever mode got selected is actually in the
+		 * modelist or the kernel may die
+		 */
+		fb_var_to_videomode(&mode, &info->var);
+		fb_add_videomode(&mode, &info->modelist);
+	}
+}
+
+/*
+ * The code below is used to pick up a mode in check_var and
+ * set_var. It should be made generic
+ */
+
+/*
+ * This is used when looking for modes. We assign a "distance" value
+ * to a mode in the modedb depending how "close" it is from what we
+ * are looking for.
+ * Currently, we don't compare that much, we could do better but
+ * the current fbcon doesn't quite mind ;)
+ */
+static int radeon_compare_modes(const struct fb_var_screeninfo *var,
+				const struct fb_videomode *mode)
+{
+	int distance = 0;
+
+	distance = mode->yres - var->yres;
+	distance += (mode->xres - var->xres)/2;
+	return distance;
+}
+
+/*
+ * This function is called by check_var, it gets the passed in mode parameter, and
+ * outputs a valid mode matching the passed-in one as closely as possible.
+ * We need something better ultimately. Things like fbcon basically pass us out
+ * current mode with xres/yres hacked, while things like XFree will actually
+ * produce a full timing that we should respect as much as possible.
+ *
+ * This is why I added the FB_ACTIVATE_FIND that is used by fbcon. Without this,
+ * we do a simple spec match, that's all. With it, we actually look for a mode in
+ * either our monitor modedb or the vesa one if none
+ *
+ */
+int  radeon_match_mode(struct radeonfb_info *rinfo,
+		       struct fb_var_screeninfo *dest,
+		       const struct fb_var_screeninfo *src)
+{
+	const struct fb_videomode	*db = vesa_modes;
+	int				i, dbsize = 34;
+	int				has_rmx, native_db = 0;
+	int				distance = INT_MAX;
+	const struct fb_videomode	*candidate = NULL;
+
+	/* Start with a copy of the requested mode */
+	memcpy(dest, src, sizeof(struct fb_var_screeninfo));
+
+	/* Check if we have a modedb built from EDID */
+	if (rinfo->mon1_modedb) {
+		db = rinfo->mon1_modedb;
+		dbsize = rinfo->mon1_dbsize;
+		native_db = 1;
+	}
+
+	/* Check if we have a scaler allowing any fancy mode */
+	has_rmx = rinfo->mon1_type == MT_LCD || rinfo->mon1_type == MT_DFP;
+
+	/* If we have a scaler and are passed FB_ACTIVATE_TEST or
+	 * FB_ACTIVATE_NOW, just do basic checking and return if the
+	 * mode match
+	 */
+	if ((src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST ||
+	    (src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+		/* We don't have an RMX, validate timings. If we don't have
+	 	 * monspecs, we should be paranoid and not let use go above
+		 * 640x480-60, but I assume userland knows what it's doing here
+		 * (though I may be proven wrong...)
+		 */
+		if (has_rmx == 0 && rinfo->mon1_modedb)
+			if (fb_validate_mode((struct fb_var_screeninfo *)src, rinfo->info))
+				return -EINVAL;
+		return 0;
+	}
+
+	/* Now look for a mode in the database */
+	while (db) {
+		for (i = 0; i < dbsize; i++) {
+			int d;
+
+			if (db[i].yres < src->yres)
+				continue;	
+			if (db[i].xres < src->xres)
+				continue;
+			d = radeon_compare_modes(src, &db[i]);
+			/* If the new mode is at least as good as the previous one,
+			 * then it's our new candidate
+			 */
+			if (d < distance) {
+				candidate = &db[i];
+				distance = d;
+			}
+		}
+		db = NULL;
+		/* If we have a scaler, we allow any mode from the database */
+		if (native_db && has_rmx) {
+			db = vesa_modes;
+			dbsize = 34;
+			native_db = 0;
+		}
+	}
+
+	/* If we have found a match, return it */
+	if (candidate != NULL) {
+		radeon_videomode_to_var(dest, candidate);
+		return 0;
+	}
+
+	/* If we haven't and don't have a scaler, fail */
+	if (!has_rmx)
+		return -EINVAL;
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c
new file mode 100644
index 000000000000..46a12f1a93c3
--- /dev/null
+++ b/drivers/video/fbdev/aty/radeon_pm.c
@@ -0,0 +1,2906 @@
+/*
+ *	drivers/video/aty/radeon_pm.c
+ *
+ *	Copyright 2003,2004 Ben. Herrenschmidt <benh@kernel.crashing.org>
+ *	Copyright 2004 Paul Mackerras <paulus@samba.org>
+ *
+ *	This is the power management code for ATI radeon chipsets. It contains
+ *	some dynamic clock PM enable/disable code similar to what X.org does,
+ *	some D2-state (APM-style) sleep/wakeup code for use on some PowerMacs,
+ *	and the necessary bits to re-initialize from scratch a few chips found
+ *	on PowerMacs as well. The later could be extended to more platforms
+ *	provided the memory controller configuration code be made more generic,
+ *	and you can get the proper mode register commands for your RAMs.
+ *	Those things may be found in the BIOS image...
+ */
+
+#include "radeonfb.h"
+
+#include <linux/console.h>
+#include <linux/agp_backend.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/pmac_feature.h>
+#endif
+
+#include "ati_ids.h"
+
+/*
+ * Workarounds for bugs in PC laptops:
+ * - enable D2 sleep in some IBM Thinkpads
+ * - special case for Samsung P35
+ *
+ * Whitelist by subsystem vendor/device because
+ * its the subsystem vendor's fault!
+ */
+
+#if defined(CONFIG_PM) && defined(CONFIG_X86)
+static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
+
+struct radeon_device_id {
+        const char *ident;                     /* (arbitrary) Name */
+        const unsigned short subsystem_vendor; /* Subsystem Vendor ID */
+        const unsigned short subsystem_device; /* Subsystem Device ID */
+	const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */
+	const reinit_function_ptr new_reinit_func;   /* changed reinit_func */
+};
+
+#define BUGFIX(model, sv, sd, pm, fn) { \
+	.ident = model, \
+	.subsystem_vendor = sv, \
+	.subsystem_device = sd, \
+	.pm_mode_modifier = pm, \
+	.new_reinit_func  = fn  \
+}
+
+static struct radeon_device_id radeon_workaround_list[] = {
+	BUGFIX("IBM Thinkpad R32",
+	       PCI_VENDOR_ID_IBM, 0x1905,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R40",
+	       PCI_VENDOR_ID_IBM, 0x0526,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R40",
+	       PCI_VENDOR_ID_IBM, 0x0527,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R50/R51/T40/T41",
+	       PCI_VENDOR_ID_IBM, 0x0531,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R51/T40/T41/T42",
+	       PCI_VENDOR_ID_IBM, 0x0530,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad T30",
+	       PCI_VENDOR_ID_IBM, 0x0517,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad T40p",
+	       PCI_VENDOR_ID_IBM, 0x054d,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad T42",
+	       PCI_VENDOR_ID_IBM, 0x0550,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad X31/X32",
+	       PCI_VENDOR_ID_IBM, 0x052f,
+	       radeon_pm_d2, NULL),
+	BUGFIX("Samsung P35",
+	       PCI_VENDOR_ID_SAMSUNG, 0xc00c,
+	       radeon_pm_off, radeon_reinitialize_M10),
+	BUGFIX("Acer Aspire 2010",
+	       PCI_VENDOR_ID_AI, 0x0061,
+	       radeon_pm_off, radeon_reinitialize_M10),
+	BUGFIX("Acer Travelmate 290D/292LMi",
+	       PCI_VENDOR_ID_AI, 0x005a,
+	       radeon_pm_off, radeon_reinitialize_M10),
+	{ .ident = NULL }
+};
+
+static int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+{
+	struct radeon_device_id *id;
+
+	for (id = radeon_workaround_list; id->ident != NULL; id++ )
+		if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) &&
+		    (id->subsystem_device == rinfo->pdev->subsystem_device )) {
+
+			/* we found a device that requires workaround */
+			printk(KERN_DEBUG "radeonfb: %s detected"
+			       ", enabling workaround\n", id->ident);
+
+			rinfo->pm_mode |= id->pm_mode_modifier;
+
+			if (id->new_reinit_func != NULL)
+				rinfo->reinit_func = id->new_reinit_func;
+
+			return 1;
+		}
+	return 0;  /* not found */
+}
+
+#else  /* defined(CONFIG_PM) && defined(CONFIG_X86) */
+static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+{
+        return 0;
+}
+#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */
+
+
+
+static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
+{
+	u32 tmp;
+
+	/* RV100 */
+	if ((rinfo->family == CHIP_FAMILY_RV100) && (!rinfo->is_mobility)) {
+		if (rinfo->has_CRTC2) {
+			tmp = INPLL(pllSCLK_CNTL);
+			tmp &= ~SCLK_CNTL__DYN_STOP_LAT_MASK;
+			tmp |= SCLK_CNTL__CP_MAX_DYN_STOP_LAT | SCLK_CNTL__FORCEON_MASK;
+			OUTPLL(pllSCLK_CNTL, tmp);
+		}
+		tmp = INPLL(pllMCLK_CNTL);
+		tmp |= (MCLK_CNTL__FORCE_MCLKA |
+		        MCLK_CNTL__FORCE_MCLKB |
+		        MCLK_CNTL__FORCE_YCLKA |
+		        MCLK_CNTL__FORCE_YCLKB |
+			MCLK_CNTL__FORCE_AIC |
+			MCLK_CNTL__FORCE_MC);
+                OUTPLL(pllMCLK_CNTL, tmp);
+		return;
+	}
+	/* R100 */
+	if (!rinfo->has_CRTC2) {
+                tmp = INPLL(pllSCLK_CNTL);
+                tmp |= (SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_HDP	|
+			SCLK_CNTL__FORCE_DISP1	| SCLK_CNTL__FORCE_TOP	|
+                        SCLK_CNTL__FORCE_E2	| SCLK_CNTL__FORCE_SE 	|
+			SCLK_CNTL__FORCE_IDCT	| SCLK_CNTL__FORCE_VIP	|
+			SCLK_CNTL__FORCE_RE	| SCLK_CNTL__FORCE_PB 	|
+			SCLK_CNTL__FORCE_TAM	| SCLK_CNTL__FORCE_TDM	|
+                        SCLK_CNTL__FORCE_RB);
+                OUTPLL(pllSCLK_CNTL, tmp);
+		return;
+	}
+	/* RV350 (M10/M11) */
+	if (rinfo->family == CHIP_FAMILY_RV350) {
+                /* for RV350/M10/M11, no delays are required. */
+                tmp = INPLL(pllSCLK_CNTL2);
+                tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
+                        SCLK_CNTL2__R300_FORCE_GA  |
+			SCLK_CNTL2__R300_FORCE_CBA);
+                OUTPLL(pllSCLK_CNTL2, tmp);
+
+                tmp = INPLL(pllSCLK_CNTL);
+                tmp |= (SCLK_CNTL__FORCE_DISP2		| SCLK_CNTL__FORCE_CP		|
+                        SCLK_CNTL__FORCE_HDP		| SCLK_CNTL__FORCE_DISP1	|
+                        SCLK_CNTL__FORCE_TOP		| SCLK_CNTL__FORCE_E2		|
+                        SCLK_CNTL__R300_FORCE_VAP	| SCLK_CNTL__FORCE_IDCT    	|
+			SCLK_CNTL__FORCE_VIP		| SCLK_CNTL__R300_FORCE_SR	|
+			SCLK_CNTL__R300_FORCE_PX	| SCLK_CNTL__R300_FORCE_TX	|
+			SCLK_CNTL__R300_FORCE_US	| SCLK_CNTL__FORCE_TV_SCLK	|
+                        SCLK_CNTL__R300_FORCE_SU	| SCLK_CNTL__FORCE_OV0);
+                OUTPLL(pllSCLK_CNTL, tmp);
+
+                tmp = INPLL(pllSCLK_MORE_CNTL);
+		tmp |= (SCLK_MORE_CNTL__FORCE_DISPREGS	| SCLK_MORE_CNTL__FORCE_MC_GUI	|
+			SCLK_MORE_CNTL__FORCE_MC_HOST);
+                OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+		tmp = INPLL(pllMCLK_CNTL);
+		tmp |= (MCLK_CNTL__FORCE_MCLKA |
+		        MCLK_CNTL__FORCE_MCLKB |
+		        MCLK_CNTL__FORCE_YCLKA |
+		        MCLK_CNTL__FORCE_YCLKB |
+			MCLK_CNTL__FORCE_MC);
+                OUTPLL(pllMCLK_CNTL, tmp);
+
+                tmp = INPLL(pllVCLK_ECP_CNTL);
+                tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb  |
+                         VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb |
+			 VCLK_ECP_CNTL__R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
+                OUTPLL(pllVCLK_ECP_CNTL, tmp);
+
+                tmp = INPLL(pllPIXCLKS_CNTL);
+                tmp &= ~(PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb	|
+			 PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb	|
+			 PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb	|
+			 PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb	|
+			 PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb		|
+			 PIXCLKS_CNTL__R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
+                OUTPLL(pllPIXCLKS_CNTL, tmp);
+
+		return;
+	}
+	
+	/* Default */
+
+	/* Force Core Clocks */
+	tmp = INPLL(pllSCLK_CNTL);
+	tmp |= (SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_E2);
+
+	/* XFree doesn't do that case, but we had this code from Apple and it
+	 * seem necessary for proper suspend/resume operations
+	 */
+	if (rinfo->is_mobility) {
+		tmp |= 	SCLK_CNTL__FORCE_HDP|
+			SCLK_CNTL__FORCE_DISP1|
+			SCLK_CNTL__FORCE_DISP2|
+			SCLK_CNTL__FORCE_TOP|
+			SCLK_CNTL__FORCE_SE|
+			SCLK_CNTL__FORCE_IDCT|
+			SCLK_CNTL__FORCE_VIP|
+			SCLK_CNTL__FORCE_PB|
+			SCLK_CNTL__FORCE_RE|
+			SCLK_CNTL__FORCE_TAM|
+			SCLK_CNTL__FORCE_TDM|
+			SCLK_CNTL__FORCE_RB|
+			SCLK_CNTL__FORCE_TV_SCLK|
+			SCLK_CNTL__FORCE_SUBPIC|
+			SCLK_CNTL__FORCE_OV0;
+	}
+	else if (rinfo->family == CHIP_FAMILY_R300 ||
+		   rinfo->family == CHIP_FAMILY_R350) {
+		tmp |=  SCLK_CNTL__FORCE_HDP   |
+			SCLK_CNTL__FORCE_DISP1 |
+			SCLK_CNTL__FORCE_DISP2 |
+			SCLK_CNTL__FORCE_TOP   |
+			SCLK_CNTL__FORCE_IDCT  |
+			SCLK_CNTL__FORCE_VIP;
+	}
+    	OUTPLL(pllSCLK_CNTL, tmp);
+	radeon_msleep(16);
+
+	if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
+		tmp = INPLL(pllSCLK_CNTL2);
+		tmp |=  SCLK_CNTL2__R300_FORCE_TCL |
+			SCLK_CNTL2__R300_FORCE_GA  |
+			SCLK_CNTL2__R300_FORCE_CBA;
+		OUTPLL(pllSCLK_CNTL2, tmp);
+		radeon_msleep(16);
+	}
+
+	tmp = INPLL(pllCLK_PIN_CNTL);
+	tmp &= ~CLK_PIN_CNTL__SCLK_DYN_START_CNTL;
+	OUTPLL(pllCLK_PIN_CNTL, tmp);
+	radeon_msleep(15);
+
+	if (rinfo->is_IGP) {
+		/* Weird  ... X is _un_ forcing clocks here, I think it's
+		 * doing backward. Imitate it for now...
+		 */
+		tmp = INPLL(pllMCLK_CNTL);
+		tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
+			 MCLK_CNTL__FORCE_YCLKA);
+		OUTPLL(pllMCLK_CNTL, tmp);
+		radeon_msleep(16);
+	}
+	/* Hrm... same shit, X doesn't do that but I have to */
+	else if (rinfo->is_mobility) {
+		tmp = INPLL(pllMCLK_CNTL);
+		tmp |= (MCLK_CNTL__FORCE_MCLKA |
+			MCLK_CNTL__FORCE_MCLKB |
+			MCLK_CNTL__FORCE_YCLKA |
+			MCLK_CNTL__FORCE_YCLKB);
+		OUTPLL(pllMCLK_CNTL, tmp);
+		radeon_msleep(16);
+
+		tmp = INPLL(pllMCLK_MISC);
+		tmp &= 	~(MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT|
+			  MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT|
+			  MCLK_MISC__MC_MCLK_DYN_ENABLE|
+			  MCLK_MISC__IO_MCLK_DYN_ENABLE);
+		OUTPLL(pllMCLK_MISC, tmp);
+		radeon_msleep(15);
+	}
+
+	if (rinfo->is_mobility) {
+		tmp = INPLL(pllSCLK_MORE_CNTL);
+		tmp |= 	SCLK_MORE_CNTL__FORCE_DISPREGS|
+			SCLK_MORE_CNTL__FORCE_MC_GUI|
+			SCLK_MORE_CNTL__FORCE_MC_HOST;
+		OUTPLL(pllSCLK_MORE_CNTL, tmp);
+		radeon_msleep(16);
+	}
+
+	tmp = INPLL(pllPIXCLKS_CNTL);
+	tmp &= ~(PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb |
+		 PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
+		 PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb |
+		 PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
+		 PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb|
+		 PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb|
+		 PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb);
+ 	OUTPLL(pllPIXCLKS_CNTL, tmp);
+	radeon_msleep(16);
+
+	tmp = INPLL( pllVCLK_ECP_CNTL);
+	tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
+		 VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
+	OUTPLL( pllVCLK_ECP_CNTL, tmp);
+	radeon_msleep(16);
+}
+
+static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
+{
+	u32 tmp;
+
+	/* R100 */
+	if (!rinfo->has_CRTC2) {
+                tmp = INPLL(pllSCLK_CNTL);
+
+		if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
+                    tmp &= ~(SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_RB);
+                tmp &= ~(SCLK_CNTL__FORCE_HDP		| SCLK_CNTL__FORCE_DISP1 |
+			 SCLK_CNTL__FORCE_TOP		| SCLK_CNTL__FORCE_SE   |
+			 SCLK_CNTL__FORCE_IDCT		| SCLK_CNTL__FORCE_RE   |
+			 SCLK_CNTL__FORCE_PB		| SCLK_CNTL__FORCE_TAM  |
+			 SCLK_CNTL__FORCE_TDM);
+                OUTPLL(pllSCLK_CNTL, tmp);
+		return;
+	}
+
+	/* M10/M11 */
+	if (rinfo->family == CHIP_FAMILY_RV350) {
+		tmp = INPLL(pllSCLK_CNTL2);
+		tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
+			 SCLK_CNTL2__R300_FORCE_GA  |
+			 SCLK_CNTL2__R300_FORCE_CBA);
+		tmp |=  (SCLK_CNTL2__R300_TCL_MAX_DYN_STOP_LAT |
+			 SCLK_CNTL2__R300_GA_MAX_DYN_STOP_LAT  |
+			 SCLK_CNTL2__R300_CBA_MAX_DYN_STOP_LAT);
+		OUTPLL(pllSCLK_CNTL2, tmp);
+
+		tmp = INPLL(pllSCLK_CNTL);
+		tmp &= ~(SCLK_CNTL__FORCE_DISP2 | SCLK_CNTL__FORCE_CP      |
+			 SCLK_CNTL__FORCE_HDP   | SCLK_CNTL__FORCE_DISP1   |
+			 SCLK_CNTL__FORCE_TOP   | SCLK_CNTL__FORCE_E2      |
+			 SCLK_CNTL__R300_FORCE_VAP | SCLK_CNTL__FORCE_IDCT |
+			 SCLK_CNTL__FORCE_VIP   | SCLK_CNTL__R300_FORCE_SR |
+			 SCLK_CNTL__R300_FORCE_PX | SCLK_CNTL__R300_FORCE_TX |
+			 SCLK_CNTL__R300_FORCE_US | SCLK_CNTL__FORCE_TV_SCLK |
+			 SCLK_CNTL__R300_FORCE_SU | SCLK_CNTL__FORCE_OV0);
+		tmp |= SCLK_CNTL__DYN_STOP_LAT_MASK;
+		OUTPLL(pllSCLK_CNTL, tmp);
+
+		tmp = INPLL(pllSCLK_MORE_CNTL);
+		tmp &= ~SCLK_MORE_CNTL__FORCEON;
+		tmp |=  SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT |
+			SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT |
+			SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT;
+		OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+		tmp = INPLL(pllVCLK_ECP_CNTL);
+		tmp |= (VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
+			VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
+		OUTPLL(pllVCLK_ECP_CNTL, tmp);
+
+		tmp = INPLL(pllPIXCLKS_CNTL);
+		tmp |= (PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb         |
+			PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb     |
+			PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+			PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb            |
+			PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb    |
+			PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb       |
+			PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb        |
+			PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb     |
+			PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb     |
+			PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb      |
+			PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb        |
+			PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb           |
+			PIXCLKS_CNTL__R300_P2G2CLK_DAC_ALWAYS_ONb);
+		OUTPLL(pllPIXCLKS_CNTL, tmp);
+
+		tmp = INPLL(pllMCLK_MISC);
+		tmp |= (MCLK_MISC__MC_MCLK_DYN_ENABLE |
+			MCLK_MISC__IO_MCLK_DYN_ENABLE);
+		OUTPLL(pllMCLK_MISC, tmp);
+
+		tmp = INPLL(pllMCLK_CNTL);
+		tmp |= (MCLK_CNTL__FORCE_MCLKA | MCLK_CNTL__FORCE_MCLKB);
+		tmp &= ~(MCLK_CNTL__FORCE_YCLKA  |
+			 MCLK_CNTL__FORCE_YCLKB  |
+			 MCLK_CNTL__FORCE_MC);
+
+		/* Some releases of vbios have set DISABLE_MC_MCLKA
+		 * and DISABLE_MC_MCLKB bits in the vbios table.  Setting these
+		 * bits will cause H/W hang when reading video memory with dynamic
+		 * clocking enabled.
+		 */
+		if ((tmp & MCLK_CNTL__R300_DISABLE_MC_MCLKA) &&
+		    (tmp & MCLK_CNTL__R300_DISABLE_MC_MCLKB)) {
+			/* If both bits are set, then check the active channels */
+			tmp = INPLL(pllMCLK_CNTL);
+			if (rinfo->vram_width == 64) {
+			    if (INREG(MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY)
+				tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKB;
+			    else
+				tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKA;
+			} else {
+			    tmp &= ~(MCLK_CNTL__R300_DISABLE_MC_MCLKA |
+				     MCLK_CNTL__R300_DISABLE_MC_MCLKB);
+			}
+		}
+		OUTPLL(pllMCLK_CNTL, tmp);
+		return;
+	}
+
+	/* R300 */
+	if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
+		tmp = INPLL(pllSCLK_CNTL);
+		tmp &= ~(SCLK_CNTL__R300_FORCE_VAP);
+		tmp |= SCLK_CNTL__FORCE_CP;
+		OUTPLL(pllSCLK_CNTL, tmp);
+		radeon_msleep(15);
+
+		tmp = INPLL(pllSCLK_CNTL2);
+		tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
+			 SCLK_CNTL2__R300_FORCE_GA  |
+			 SCLK_CNTL2__R300_FORCE_CBA);
+		OUTPLL(pllSCLK_CNTL2, tmp);
+	}
+
+	/* Others */
+
+	tmp = INPLL( pllCLK_PWRMGT_CNTL);
+	tmp &= ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK|
+		 CLK_PWRMGT_CNTL__DISP_DYN_STOP_LAT_MASK|
+		 CLK_PWRMGT_CNTL__DYN_STOP_MODE_MASK);
+	tmp |= CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE_MASK |
+	       (0x01 << CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT__SHIFT);
+	OUTPLL( pllCLK_PWRMGT_CNTL, tmp);
+	radeon_msleep(15);
+
+	tmp = INPLL(pllCLK_PIN_CNTL);
+	tmp |= CLK_PIN_CNTL__SCLK_DYN_START_CNTL;
+	OUTPLL(pllCLK_PIN_CNTL, tmp);
+	radeon_msleep(15);
+
+	/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
+	 * to lockup randomly, leave them as set by BIOS.
+	 */
+	tmp = INPLL(pllSCLK_CNTL);
+	tmp &= ~SCLK_CNTL__FORCEON_MASK;
+
+	/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
+	if ((rinfo->family == CHIP_FAMILY_RV250 &&
+	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
+	    ((rinfo->family == CHIP_FAMILY_RV100) &&
+	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
+		tmp |= SCLK_CNTL__FORCE_CP;
+		tmp |= SCLK_CNTL__FORCE_VIP;
+	}
+	OUTPLL(pllSCLK_CNTL, tmp);
+	radeon_msleep(15);
+
+	if ((rinfo->family == CHIP_FAMILY_RV200) ||
+	    (rinfo->family == CHIP_FAMILY_RV250) ||
+	    (rinfo->family == CHIP_FAMILY_RV280)) {
+		tmp = INPLL(pllSCLK_MORE_CNTL);
+		tmp &= ~SCLK_MORE_CNTL__FORCEON;
+
+		/* RV200::A11 A12 RV250::A11 A12 */
+		if (((rinfo->family == CHIP_FAMILY_RV200) ||
+		     (rinfo->family == CHIP_FAMILY_RV250)) &&
+		    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
+			tmp |= SCLK_MORE_CNTL__FORCEON;
+
+		OUTPLL(pllSCLK_MORE_CNTL, tmp);
+		radeon_msleep(15);
+	}
+	
+
+	/* RV200::A11 A12, RV250::A11 A12 */
+	if (((rinfo->family == CHIP_FAMILY_RV200) ||
+	     (rinfo->family == CHIP_FAMILY_RV250)) &&
+	    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
+		tmp = INPLL(pllPLL_PWRMGT_CNTL);
+		tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
+		OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
+		radeon_msleep(15);
+	}
+
+	tmp = INPLL(pllPIXCLKS_CNTL);
+	tmp |=  PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb |
+		PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb|
+		PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
+		PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb|
+		PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb|
+		PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
+		PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb;
+	OUTPLL(pllPIXCLKS_CNTL, tmp);
+	radeon_msleep(15);
+		
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	tmp |=  VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
+		VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb;
+	OUTPLL(pllVCLK_ECP_CNTL, tmp);
+
+	/* X doesn't do that ... hrm, we do on mobility && Macs */
+#ifdef CONFIG_PPC_OF
+	if (rinfo->is_mobility) {
+		tmp  = INPLL(pllMCLK_CNTL);
+		tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
+			 MCLK_CNTL__FORCE_MCLKB |
+			 MCLK_CNTL__FORCE_YCLKA |
+			 MCLK_CNTL__FORCE_YCLKB);
+		OUTPLL(pllMCLK_CNTL, tmp);
+		radeon_msleep(15);
+
+		tmp = INPLL(pllMCLK_MISC);
+		tmp |= 	MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT|
+			MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT|
+			MCLK_MISC__MC_MCLK_DYN_ENABLE|
+			MCLK_MISC__IO_MCLK_DYN_ENABLE;
+		OUTPLL(pllMCLK_MISC, tmp);
+		radeon_msleep(15);
+	}
+#endif /* CONFIG_PPC_OF */
+}
+
+#ifdef CONFIG_PM
+
+static void OUTMC( struct radeonfb_info *rinfo, u8 indx, u32 value)
+{
+	OUTREG( MC_IND_INDEX, indx | MC_IND_INDEX__MC_IND_WR_EN);	
+	OUTREG( MC_IND_DATA, value);		
+}
+
+static u32 INMC(struct radeonfb_info *rinfo, u8 indx)
+{
+	OUTREG( MC_IND_INDEX, indx);					
+	return INREG( MC_IND_DATA);
+}
+
+static void radeon_pm_save_regs(struct radeonfb_info *rinfo, int saving_for_d3)
+{
+	rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL);
+	rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL);
+	rinfo->save_regs[2] = INPLL(MCLK_CNTL);
+	rinfo->save_regs[3] = INPLL(SCLK_CNTL);
+	rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL);
+	rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL);
+	rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL);
+	rinfo->save_regs[7] = INPLL(MCLK_MISC);
+	rinfo->save_regs[8] = INPLL(P2PLL_CNTL);
+	
+	rinfo->save_regs[9] = INREG(DISP_MISC_CNTL);
+	rinfo->save_regs[10] = INREG(DISP_PWR_MAN);
+	rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL);
+	rinfo->save_regs[13] = INREG(TV_DAC_CNTL);
+	rinfo->save_regs[14] = INREG(BUS_CNTL1);
+	rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL);
+	rinfo->save_regs[16] = INREG(AGP_CNTL);
+	rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000;
+	rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000;
+	rinfo->save_regs[19] = INREG(GPIOPAD_A);
+	rinfo->save_regs[20] = INREG(GPIOPAD_EN);
+	rinfo->save_regs[21] = INREG(GPIOPAD_MASK);
+	rinfo->save_regs[22] = INREG(ZV_LCDPAD_A);
+	rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN);
+	rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK);
+	rinfo->save_regs[25] = INREG(GPIO_VGA_DDC);
+	rinfo->save_regs[26] = INREG(GPIO_DVI_DDC);
+	rinfo->save_regs[27] = INREG(GPIO_MONID);
+	rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC);
+
+	rinfo->save_regs[29] = INREG(SURFACE_CNTL);
+	rinfo->save_regs[30] = INREG(MC_FB_LOCATION);
+	rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR);
+	rinfo->save_regs[32] = INREG(MC_AGP_LOCATION);
+	rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR);
+
+	rinfo->save_regs[34] = INPLL(SCLK_MORE_CNTL);
+	rinfo->save_regs[35] = INREG(MEM_SDRAM_MODE_REG);
+	rinfo->save_regs[36] = INREG(BUS_CNTL);
+	rinfo->save_regs[39] = INREG(RBBM_CNTL);
+	rinfo->save_regs[40] = INREG(DAC_CNTL);
+	rinfo->save_regs[41] = INREG(HOST_PATH_CNTL);
+	rinfo->save_regs[37] = INREG(MPP_TB_CONFIG);
+	rinfo->save_regs[38] = INREG(FCP_CNTL);
+
+	if (rinfo->is_mobility) {
+		rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL);
+		rinfo->save_regs[43] = INPLL(pllSSPLL_CNTL);
+		rinfo->save_regs[44] = INPLL(pllSSPLL_REF_DIV);
+		rinfo->save_regs[45] = INPLL(pllSSPLL_DIV_0);
+		rinfo->save_regs[90] = INPLL(pllSS_INT_CNTL);
+		rinfo->save_regs[91] = INPLL(pllSS_TST_CNTL);
+		rinfo->save_regs[81] = INREG(LVDS_GEN_CNTL);
+	}
+
+	if (rinfo->family >= CHIP_FAMILY_RV200) {
+		rinfo->save_regs[42] = INREG(MEM_REFRESH_CNTL);
+		rinfo->save_regs[46] = INREG(MC_CNTL);
+		rinfo->save_regs[47] = INREG(MC_INIT_GFX_LAT_TIMER);
+		rinfo->save_regs[48] = INREG(MC_INIT_MISC_LAT_TIMER);
+		rinfo->save_regs[49] = INREG(MC_TIMING_CNTL);
+		rinfo->save_regs[50] = INREG(MC_READ_CNTL_AB);
+		rinfo->save_regs[51] = INREG(MC_IOPAD_CNTL);
+		rinfo->save_regs[52] = INREG(MC_CHIP_IO_OE_CNTL_AB);
+		rinfo->save_regs[53] = INREG(MC_DEBUG);
+	}
+	rinfo->save_regs[54] = INREG(PAMAC0_DLY_CNTL);
+	rinfo->save_regs[55] = INREG(PAMAC1_DLY_CNTL);
+	rinfo->save_regs[56] = INREG(PAD_CTLR_MISC);
+	rinfo->save_regs[57] = INREG(FW_CNTL);
+
+	if (rinfo->family >= CHIP_FAMILY_R300) {
+		rinfo->save_regs[58] = INMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER);
+		rinfo->save_regs[59] = INMC(rinfo, ixR300_MC_IMP_CNTL);
+		rinfo->save_regs[60] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0);
+		rinfo->save_regs[61] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1);
+		rinfo->save_regs[62] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0);
+		rinfo->save_regs[63] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1);
+		rinfo->save_regs[64] = INMC(rinfo, ixR300_MC_BIST_CNTL_3);
+		rinfo->save_regs[65] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0);
+		rinfo->save_regs[66] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1);
+		rinfo->save_regs[67] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0);
+		rinfo->save_regs[68] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1);
+		rinfo->save_regs[69] = INMC(rinfo, ixR300_MC_DEBUG_CNTL);
+		rinfo->save_regs[70] = INMC(rinfo, ixR300_MC_DLL_CNTL);
+		rinfo->save_regs[71] = INMC(rinfo, ixR300_MC_IMP_CNTL_0);
+		rinfo->save_regs[72] = INMC(rinfo, ixR300_MC_ELPIDA_CNTL);
+		rinfo->save_regs[96] = INMC(rinfo, ixR300_MC_READ_CNTL_CD);
+	} else {
+		rinfo->save_regs[59] = INMC(rinfo, ixMC_IMP_CNTL);
+		rinfo->save_regs[65] = INMC(rinfo, ixMC_CHP_IO_CNTL_A0);
+		rinfo->save_regs[66] = INMC(rinfo, ixMC_CHP_IO_CNTL_A1);
+		rinfo->save_regs[67] = INMC(rinfo, ixMC_CHP_IO_CNTL_B0);
+		rinfo->save_regs[68] = INMC(rinfo, ixMC_CHP_IO_CNTL_B1);
+		rinfo->save_regs[71] = INMC(rinfo, ixMC_IMP_CNTL_0);
+	}
+
+	rinfo->save_regs[73] = INPLL(pllMPLL_CNTL);
+	rinfo->save_regs[74] = INPLL(pllSPLL_CNTL);
+	rinfo->save_regs[75] = INPLL(pllMPLL_AUX_CNTL);
+	rinfo->save_regs[76] = INPLL(pllSPLL_AUX_CNTL);
+	rinfo->save_regs[77] = INPLL(pllM_SPLL_REF_FB_DIV);
+	rinfo->save_regs[78] = INPLL(pllAGP_PLL_CNTL);
+	rinfo->save_regs[79] = INREG(PAMAC2_DLY_CNTL);
+
+	rinfo->save_regs[80] = INREG(OV0_BASE_ADDR);
+	rinfo->save_regs[82] = INREG(FP_GEN_CNTL);
+	rinfo->save_regs[83] = INREG(FP2_GEN_CNTL);
+	rinfo->save_regs[84] = INREG(TMDS_CNTL);
+	rinfo->save_regs[85] = INREG(TMDS_TRANSMITTER_CNTL);
+	rinfo->save_regs[86] = INREG(DISP_OUTPUT_CNTL);
+	rinfo->save_regs[87] = INREG(DISP_HW_DEBUG);
+	rinfo->save_regs[88] = INREG(TV_MASTER_CNTL);
+	rinfo->save_regs[89] = INPLL(pllP2PLL_REF_DIV);
+	rinfo->save_regs[92] = INPLL(pllPPLL_DIV_0);
+	rinfo->save_regs[93] = INPLL(pllPPLL_CNTL);
+	rinfo->save_regs[94] = INREG(GRPH_BUFFER_CNTL);
+	rinfo->save_regs[95] = INREG(GRPH2_BUFFER_CNTL);
+	rinfo->save_regs[96] = INREG(HDP_DEBUG);
+	rinfo->save_regs[97] = INPLL(pllMDLL_CKO);
+	rinfo->save_regs[98] = INPLL(pllMDLL_RDCKA);
+	rinfo->save_regs[99] = INPLL(pllMDLL_RDCKB);
+}
+
+static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
+{
+	OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */
+	
+	OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
+	OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
+	OUTPLL(MCLK_CNTL, rinfo->save_regs[2]);
+	OUTPLL(SCLK_CNTL, rinfo->save_regs[3]);
+	OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
+	OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]);
+	OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]);
+	OUTPLL(MCLK_MISC, rinfo->save_regs[7]);
+	if (rinfo->family == CHIP_FAMILY_RV350)
+		OUTPLL(SCLK_MORE_CNTL, rinfo->save_regs[34]);
+
+	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
+	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
+
+	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+	OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
+	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]);
+	OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]);
+	OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]);
+	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
+	OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]);
+	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+	OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]);
+	OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]);
+	OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]);
+
+	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
+	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
+	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
+	OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]);
+	OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]);
+	OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]);
+	OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]);
+	OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]);
+	OUTREG(GPIO_MONID, rinfo->save_regs[27]);
+	OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]);
+}
+
+static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo)
+{		
+	OUTREG(GPIOPAD_MASK, 0x0001ffff);
+	OUTREG(GPIOPAD_EN, 0x00000400);
+	OUTREG(GPIOPAD_A, 0x00000000);		
+        OUTREG(ZV_LCDPAD_MASK, 0x00000000);
+        OUTREG(ZV_LCDPAD_EN, 0x00000000);
+      	OUTREG(ZV_LCDPAD_A, 0x00000000); 	
+	OUTREG(GPIO_VGA_DDC, 0x00030000);
+	OUTREG(GPIO_DVI_DDC, 0x00000000);
+	OUTREG(GPIO_MONID, 0x00030000);
+	OUTREG(GPIO_CRT2_DDC, 0x00000000);
+}
+
+static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
+{
+	/* Set v2clk to 65MHz */
+	if (rinfo->family <= CHIP_FAMILY_RV280) {
+		OUTPLL(pllPIXCLKS_CNTL,
+			 __INPLL(rinfo, pllPIXCLKS_CNTL)
+			 & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
+	 
+		OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
+		OUTPLL(pllP2PLL_CNTL, 0x0000bf00);
+	} else {
+		OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
+		INPLL(pllP2PLL_REF_DIV);
+		OUTPLL(pllP2PLL_CNTL, 0x0000a700);
+	}
+
+	OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W);
+	
+	OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP);
+	mdelay(1);
+
+	OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET);
+	mdelay( 1);
+
+  	OUTPLL(pllPIXCLKS_CNTL,
+  		(INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK)
+  		| (0x03 << PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT));
+	mdelay( 1);	
+}
+
+static void radeon_pm_low_current(struct radeonfb_info *rinfo)
+{
+	u32 reg;
+
+	reg  = INREG(BUS_CNTL1);
+	if (rinfo->family <= CHIP_FAMILY_RV280) {
+		reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
+		reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
+	} else {
+		reg |= 0x4080;
+	}
+	OUTREG(BUS_CNTL1, reg);
+	
+	reg  = INPLL(PLL_PWRMGT_CNTL);
+	reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF |
+		PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF;
+	reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
+	reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU;
+	OUTPLL(PLL_PWRMGT_CNTL, reg);
+	
+	reg  = INREG(TV_DAC_CNTL);
+	reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK);
+	reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD |
+		TV_DAC_CNTL_BDACPD |
+		(8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT);
+	OUTREG(TV_DAC_CNTL, reg);
+	
+	reg  = INREG(TMDS_TRANSMITTER_CNTL);
+	reg &= ~(TMDS_PLL_EN | TMDS_PLLRST);
+	OUTREG(TMDS_TRANSMITTER_CNTL, reg);
+
+	reg = INREG(DAC_CNTL);
+	reg &= ~DAC_CMP_EN;
+	OUTREG(DAC_CNTL, reg);
+
+	reg = INREG(DAC_CNTL2);
+	reg &= ~DAC2_CMP_EN;
+	OUTREG(DAC_CNTL2, reg);
+	
+	reg  = INREG(TV_DAC_CNTL);
+	reg &= ~TV_DAC_CNTL_DETECT;
+	OUTREG(TV_DAC_CNTL, reg);
+}
+
+static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
+{
+
+	u32 sclk_cntl, mclk_cntl, sclk_more_cntl;
+
+	u32 pll_pwrmgt_cntl;
+	u32 clk_pwrmgt_cntl;
+	u32 clk_pin_cntl;
+	u32 vclk_ecp_cntl; 
+	u32 pixclks_cntl;
+	u32 disp_mis_cntl;
+	u32 disp_pwr_man;
+	u32 tmp;
+	
+	/* Force Core Clocks */
+	sclk_cntl = INPLL( pllSCLK_CNTL);
+	sclk_cntl |= 	SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT|
+			SCLK_CNTL__VIP_MAX_DYN_STOP_LAT|
+			SCLK_CNTL__RE_MAX_DYN_STOP_LAT|
+			SCLK_CNTL__PB_MAX_DYN_STOP_LAT|
+			SCLK_CNTL__TAM_MAX_DYN_STOP_LAT|
+			SCLK_CNTL__TDM_MAX_DYN_STOP_LAT|
+			SCLK_CNTL__RB_MAX_DYN_STOP_LAT|
+			
+			SCLK_CNTL__FORCE_DISP2|
+			SCLK_CNTL__FORCE_CP|
+			SCLK_CNTL__FORCE_HDP|
+			SCLK_CNTL__FORCE_DISP1|
+			SCLK_CNTL__FORCE_TOP|
+			SCLK_CNTL__FORCE_E2|
+			SCLK_CNTL__FORCE_SE|
+			SCLK_CNTL__FORCE_IDCT|
+			SCLK_CNTL__FORCE_VIP|
+			
+			SCLK_CNTL__FORCE_PB|
+			SCLK_CNTL__FORCE_TAM|
+			SCLK_CNTL__FORCE_TDM|
+			SCLK_CNTL__FORCE_RB|
+			SCLK_CNTL__FORCE_TV_SCLK|
+			SCLK_CNTL__FORCE_SUBPIC|
+			SCLK_CNTL__FORCE_OV0;
+	if (rinfo->family <= CHIP_FAMILY_RV280)
+		sclk_cntl |= SCLK_CNTL__FORCE_RE;
+	else
+		sclk_cntl |= SCLK_CNTL__SE_MAX_DYN_STOP_LAT |
+			SCLK_CNTL__E2_MAX_DYN_STOP_LAT |
+			SCLK_CNTL__TV_MAX_DYN_STOP_LAT |
+			SCLK_CNTL__HDP_MAX_DYN_STOP_LAT |
+			SCLK_CNTL__CP_MAX_DYN_STOP_LAT;
+
+	OUTPLL( pllSCLK_CNTL, sclk_cntl);
+
+	sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL);
+	sclk_more_cntl |= 	SCLK_MORE_CNTL__FORCE_DISPREGS |
+				SCLK_MORE_CNTL__FORCE_MC_GUI |
+				SCLK_MORE_CNTL__FORCE_MC_HOST;
+
+	OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl);		
+
+	
+	mclk_cntl = INPLL( pllMCLK_CNTL);
+	mclk_cntl &= ~(	MCLK_CNTL__FORCE_MCLKA |
+			MCLK_CNTL__FORCE_MCLKB |
+			MCLK_CNTL__FORCE_YCLKA |
+			MCLK_CNTL__FORCE_YCLKB |
+			MCLK_CNTL__FORCE_MC
+		      );	
+    	OUTPLL( pllMCLK_CNTL, mclk_cntl);
+	
+	/* Force Display clocks	*/
+	vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL);
+	vclk_ecp_cntl &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb
+			   | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
+	vclk_ecp_cntl |= VCLK_ECP_CNTL__ECP_FORCE_ON;
+	OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl);
+	
+	
+	pixclks_cntl = INPLL( pllPIXCLKS_CNTL);
+	pixclks_cntl &= ~(	PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | 
+				PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
+				PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb |
+				PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
+				PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb|
+				PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb|
+				PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb);
+						
+ 	OUTPLL( pllPIXCLKS_CNTL, pixclks_cntl);
+
+	/* Switch off LVDS interface */
+	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) &
+	       ~(LVDS_BLON | LVDS_EN | LVDS_ON | LVDS_DIGON));
+
+	/* Enable System power management */
+	pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL);
+	
+	pll_pwrmgt_cntl |= 	PLL_PWRMGT_CNTL__SPLL_TURNOFF |
+				PLL_PWRMGT_CNTL__MPLL_TURNOFF|
+				PLL_PWRMGT_CNTL__PPLL_TURNOFF|
+				PLL_PWRMGT_CNTL__P2PLL_TURNOFF|
+				PLL_PWRMGT_CNTL__TVPLL_TURNOFF;
+						
+	OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl);
+	
+	clk_pwrmgt_cntl	 = INPLL( pllCLK_PWRMGT_CNTL);
+	
+	clk_pwrmgt_cntl &= ~(	CLK_PWRMGT_CNTL__MPLL_PWRMGT_OFF|
+				CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF|
+				CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF|
+				CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF|
+				CLK_PWRMGT_CNTL__MCLK_TURNOFF|
+				CLK_PWRMGT_CNTL__SCLK_TURNOFF|
+				CLK_PWRMGT_CNTL__PCLK_TURNOFF|
+				CLK_PWRMGT_CNTL__P2CLK_TURNOFF|
+				CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF|
+				CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN|
+				CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE|
+				CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK|
+				CLK_PWRMGT_CNTL__CG_NO1_DEBUG_MASK
+			);
+						
+	clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN
+		| CLK_PWRMGT_CNTL__DISP_PM;
+	
+	OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl);
+	
+	clk_pin_cntl = INPLL( pllCLK_PIN_CNTL);
+	
+	clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND;
+
+	/* because both INPLL and OUTPLL take the same lock, that's why. */
+	tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND;
+	OUTPLL( pllMCLK_MISC, tmp);
+
+	/* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset
+	 * and radeon chip dependent. Thus we only enable it on Mac for
+	 * now (until we get more info on how to compute the correct
+	 * value for various X86 bridges).
+	 */
+#ifdef CONFIG_PPC_PMAC
+	if (machine_is(powermac)) {
+		/* AGP PLL control */
+		if (rinfo->family <= CHIP_FAMILY_RV280) {
+			OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
+			OUTREG(BUS_CNTL1,
+			       (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
+			       | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));	// 440BX
+		} else {
+			OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
+			OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+		}
+	}
+#endif
+
+	OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL)
+				  & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
+	
+	clk_pin_cntl &= ~CLK_PIN_CNTL__CG_CLK_TO_OUTPIN;
+	clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb;	
+	OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl);
+
+	/* Solano2M */
+	OUTREG(AGP_CNTL,
+		(INREG(AGP_CNTL) & ~(AGP_CNTL__MAX_IDLE_CLK_MASK))
+		| (0x20<<AGP_CNTL__MAX_IDLE_CLK__SHIFT));
+
+	/* ACPI mode */
+	/* because both INPLL and OUTPLL take the same lock, that's why. */
+	tmp = INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL;
+	OUTPLL( pllPLL_PWRMGT_CNTL, tmp);
+
+
+	disp_mis_cntl = INREG(DISP_MISC_CNTL);
+	
+	disp_mis_cntl &= ~(	DISP_MISC_CNTL__SOFT_RESET_GRPH_PP | 
+				DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP | 
+				DISP_MISC_CNTL__SOFT_RESET_OV0_PP |
+				DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK|
+				DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK|
+				DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK|
+				DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP|
+				DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK|
+				DISP_MISC_CNTL__SOFT_RESET_LVDS|
+				DISP_MISC_CNTL__SOFT_RESET_TMDS|
+				DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS|
+				DISP_MISC_CNTL__SOFT_RESET_TV);
+	
+	OUTREG(DISP_MISC_CNTL, disp_mis_cntl);
+						
+	disp_pwr_man = INREG(DISP_PWR_MAN);
+	
+	disp_pwr_man &= ~(	DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN	| 
+				DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN |
+				DISP_PWR_MAN__DISP_PWR_MAN_DPMS_MASK|
+				DISP_PWR_MAN__DISP_D3_RST|
+				DISP_PWR_MAN__DISP_D3_REG_RST
+				);
+	
+	disp_pwr_man |= DISP_PWR_MAN__DISP_D3_GRPH_RST|
+					DISP_PWR_MAN__DISP_D3_SUBPIC_RST|
+					DISP_PWR_MAN__DISP_D3_OV0_RST|
+					DISP_PWR_MAN__DISP_D1D2_GRPH_RST|
+					DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST|
+					DISP_PWR_MAN__DISP_D1D2_OV0_RST|
+					DISP_PWR_MAN__DIG_TMDS_ENABLE_RST|
+					DISP_PWR_MAN__TV_ENABLE_RST| 
+//					DISP_PWR_MAN__AUTO_PWRUP_EN|
+					0;
+	
+	OUTREG(DISP_PWR_MAN, disp_pwr_man);					
+							
+	clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL);
+	pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL) ;
+	clk_pin_cntl 	= INPLL( pllCLK_PIN_CNTL);
+	disp_pwr_man	= INREG(DISP_PWR_MAN);
+		
+	
+	/* D2 */
+	clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__DISP_PM;
+	pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__MOBILE_SU | PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK;
+	clk_pin_cntl	|= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb;
+	disp_pwr_man 	&= ~(DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN_MASK
+			     | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN_MASK);
+
+	OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl);
+	OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl);
+	OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl);
+	OUTREG(DISP_PWR_MAN, disp_pwr_man);
+
+	/* disable display request & disable display */
+	OUTREG( CRTC_GEN_CNTL, (INREG( CRTC_GEN_CNTL) & ~CRTC_GEN_CNTL__CRTC_EN)
+		| CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B);
+	OUTREG( CRTC2_GEN_CNTL, (INREG( CRTC2_GEN_CNTL) & ~CRTC2_GEN_CNTL__CRTC2_EN)
+		| CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B);
+
+	mdelay(17);				   
+
+}
+
+static void radeon_pm_yclk_mclk_sync(struct radeonfb_info *rinfo)
+{
+	u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1;
+
+	mc_chp_io_cntl_a1 = INMC( rinfo, ixMC_CHP_IO_CNTL_A1)
+		& ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK;
+	mc_chp_io_cntl_b1 = INMC( rinfo, ixMC_CHP_IO_CNTL_B1)
+		& ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK;
+
+	OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1
+	       | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT));
+	OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1
+	       | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT));
+
+	OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1);
+	OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1);
+
+	mdelay( 1);
+}
+
+static void radeon_pm_yclk_mclk_sync_m10(struct radeonfb_info *rinfo)
+{
+	u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1;
+
+	mc_chp_io_cntl_a1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1)
+		& ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK;
+	mc_chp_io_cntl_b1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1)
+		& ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK;
+
+	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1,
+	       mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT));
+	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1,
+	       mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT));
+
+	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1);
+	OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1);
+
+	mdelay( 1);
+}
+
+static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value,
+				       u8 delay_required)
+{  
+	u32 mem_sdram_mode;
+
+	mem_sdram_mode  = INREG( MEM_SDRAM_MODE_REG);
+
+	mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK;
+	mem_sdram_mode |= (value<<MEM_SDRAM_MODE_REG__MEM_MODE_REG__SHIFT)
+		| MEM_SDRAM_MODE_REG__MEM_CFG_TYPE;
+	OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
+	if (delay_required >= 2)
+		mdelay(1);
+
+	mem_sdram_mode |=  MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET;
+	OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
+	if (delay_required >= 2)
+		mdelay(1);
+
+	mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET;
+	OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
+	if (delay_required >= 2)
+		mdelay(1);
+
+	if (delay_required) {
+		do {
+			if (delay_required >= 2)
+				mdelay(1);
+		} while ((INREG(MC_STATUS)
+			  & (MC_STATUS__MEM_PWRUP_COMPL_A |
+			     MC_STATUS__MEM_PWRUP_COMPL_B)) == 0);
+	}
+}
+
+static void radeon_pm_m10_program_mode_wait(struct radeonfb_info *rinfo)
+{
+	int cnt;
+
+	for (cnt = 0; cnt < 100; ++cnt) {
+		mdelay(1);
+		if (INREG(MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A
+					| MC_STATUS__MEM_PWRUP_COMPL_B))
+			break;
+	}
+}
+
+
+static void radeon_pm_enable_dll(struct radeonfb_info *rinfo)
+{  
+#define DLL_RESET_DELAY 	5
+#define DLL_SLEEP_DELAY		1
+
+	u32 cko = INPLL(pllMDLL_CKO)   | MDLL_CKO__MCKOA_SLEEP
+		| MDLL_CKO__MCKOA_RESET;
+	u32 cka = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP
+		| MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET
+		| MDLL_RDCKA__MRDCKA1_RESET;
+	u32 ckb = INPLL(pllMDLL_RDCKB) | MDLL_RDCKB__MRDCKB0_SLEEP
+		| MDLL_RDCKB__MRDCKB1_SLEEP | MDLL_RDCKB__MRDCKB0_RESET
+		| MDLL_RDCKB__MRDCKB1_RESET;
+
+	/* Setting up the DLL range for write */
+	OUTPLL(pllMDLL_CKO,   	cko);
+	OUTPLL(pllMDLL_RDCKA,  	cka);
+	OUTPLL(pllMDLL_RDCKB,	ckb);
+
+	mdelay(DLL_RESET_DELAY*2);
+
+	cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP);
+	OUTPLL(pllMDLL_CKO, cko);
+	mdelay(DLL_SLEEP_DELAY);
+	cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET);
+	OUTPLL(pllMDLL_CKO, cko);
+	mdelay(DLL_RESET_DELAY);
+
+	cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP);
+	OUTPLL(pllMDLL_RDCKA, cka);
+	mdelay(DLL_SLEEP_DELAY);
+	cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET);
+	OUTPLL(pllMDLL_RDCKA, cka);
+	mdelay(DLL_RESET_DELAY);
+
+	ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP);
+	OUTPLL(pllMDLL_RDCKB, ckb);
+	mdelay(DLL_SLEEP_DELAY);
+	ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET);
+	OUTPLL(pllMDLL_RDCKB, ckb);
+	mdelay(DLL_RESET_DELAY);
+
+
+#undef DLL_RESET_DELAY
+#undef DLL_SLEEP_DELAY
+}
+
+static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo)
+{
+	u32 dll_value;
+	u32 dll_sleep_mask = 0;
+	u32 dll_reset_mask = 0;
+	u32 mc;
+
+#define DLL_RESET_DELAY 	5
+#define DLL_SLEEP_DELAY		1
+
+	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
+	mc = INREG(MC_CNTL);
+	/* Check which channels are enabled */
+	switch (mc & 0x3) {
+	case 1:
+		if (mc & 0x4)
+			break;
+	case 2:
+		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP;
+		dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET;
+	case 0:
+		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP;
+		dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET;
+	}
+	switch (mc & 0x3) {
+	case 1:
+		if (!(mc & 0x4))
+			break;
+	case 2:
+		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP;
+		dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET;
+		dll_sleep_mask |= MDLL_R300_RDCK__MRDCKC_SLEEP;
+		dll_reset_mask |= MDLL_R300_RDCK__MRDCKC_RESET;
+	}
+
+	dll_value = INPLL(pllMDLL_RDCKA);
+
+	/* Power Up */
+	dll_value &= ~(dll_sleep_mask);
+	OUTPLL(pllMDLL_RDCKA, dll_value);
+	mdelay( DLL_SLEEP_DELAY);  		
+
+	dll_value &= ~(dll_reset_mask);
+	OUTPLL(pllMDLL_RDCKA, dll_value);
+	mdelay( DLL_RESET_DELAY);  		
+
+#undef DLL_RESET_DELAY 
+#undef DLL_SLEEP_DELAY
+}
+
+
+static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
+{
+	u32 crtcGenCntl, crtcGenCntl2, memRefreshCntl, crtc_more_cntl,
+		fp_gen_cntl, fp2_gen_cntl;
+ 
+	crtcGenCntl  = INREG( CRTC_GEN_CNTL);
+	crtcGenCntl2 = INREG( CRTC2_GEN_CNTL);
+
+	crtc_more_cntl 	= INREG( CRTC_MORE_CNTL);
+	fp_gen_cntl 	= INREG( FP_GEN_CNTL);
+	fp2_gen_cntl 	= INREG( FP2_GEN_CNTL);
+ 
+
+	OUTREG( CRTC_MORE_CNTL, 0);
+	OUTREG( FP_GEN_CNTL, 0);
+	OUTREG( FP2_GEN_CNTL,0);
+ 
+	OUTREG( CRTC_GEN_CNTL,  (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) );
+	OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
+  
+	/* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */
+	if (rinfo->family == CHIP_FAMILY_RV350) {
+		u32 sdram_mode_reg = rinfo->save_regs[35];
+		static const u32 default_mrtable[] =
+			{ 0x21320032,
+			  0x21321000, 0xa1321000, 0x21321000, 0xffffffff,
+			  0x21320032, 0xa1320032, 0x21320032, 0xffffffff,
+			  0x21321002, 0xa1321002, 0x21321002, 0xffffffff,
+			  0x21320132, 0xa1320132, 0x21320132, 0xffffffff,
+			  0x21320032, 0xa1320032, 0x21320032, 0xffffffff,
+			  0x31320032 };
+
+		const u32 *mrtable = default_mrtable;
+		int i, mrtable_size = ARRAY_SIZE(default_mrtable);
+
+		mdelay(30);
+
+		/* Disable refresh */
+		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
+			& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
+		OUTREG( MEM_REFRESH_CNTL, memRefreshCntl
+			| MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+
+		/* Configure and enable M & SPLLs */
+       		radeon_pm_enable_dll_m10(rinfo);
+		radeon_pm_yclk_mclk_sync_m10(rinfo);
+
+#ifdef CONFIG_PPC_OF
+		if (rinfo->of_node != NULL) {
+			int size;
+
+			mrtable = of_get_property(rinfo->of_node, "ATY,MRT", &size);
+			if (mrtable)
+				mrtable_size = size >> 2;
+			else
+				mrtable = default_mrtable;
+		}
+#endif /* CONFIG_PPC_OF */
+
+		/* Program the SDRAM */
+		sdram_mode_reg = mrtable[0];
+		OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg);
+		for (i = 0; i < mrtable_size; i++) {
+			if (mrtable[i] == 0xffffffffu)
+				radeon_pm_m10_program_mode_wait(rinfo);
+			else {
+				sdram_mode_reg &= ~(MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK
+						    | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE
+						    | MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET);
+				sdram_mode_reg |= mrtable[i];
+
+				OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg);
+				mdelay(1);
+			}
+		}
+
+		/* Restore memory refresh */
+		OUTREG(MEM_REFRESH_CNTL, memRefreshCntl);
+		mdelay(30);
+
+	}
+	/* Here come the desktop RV200 "QW" card */
+	else if (!rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV200) {
+		/* Disable refresh */
+		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
+			& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
+		OUTREG(MEM_REFRESH_CNTL, memRefreshCntl
+		       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+		mdelay(30);
+
+		/* Reset memory */
+		OUTREG(MEM_SDRAM_MODE_REG,
+		       INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+
+		radeon_pm_program_mode_reg(rinfo, 0x2002, 2);
+		radeon_pm_program_mode_reg(rinfo, 0x0132, 2);
+		radeon_pm_program_mode_reg(rinfo, 0x0032, 2);
+
+		OUTREG(MEM_SDRAM_MODE_REG,
+		       INREG(MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+
+		OUTREG( MEM_REFRESH_CNTL, 	memRefreshCntl);
+
+	}
+	/* The M6 */
+	else if (rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV100) {
+		/* Disable refresh */
+		memRefreshCntl = INREG(EXT_MEM_CNTL) & ~(1 << 20);
+		OUTREG( EXT_MEM_CNTL, memRefreshCntl | (1 << 20));
+ 
+		/* Reset memory */
+		OUTREG( MEM_SDRAM_MODE_REG,
+			INREG( MEM_SDRAM_MODE_REG)
+			& ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+
+		/* DLL */
+		radeon_pm_enable_dll(rinfo);
+
+		/* MLCK / YCLK sync */
+		radeon_pm_yclk_mclk_sync(rinfo);
+
+		/* Program Mode Register */
+		radeon_pm_program_mode_reg(rinfo, 0x2000, 1);   
+		radeon_pm_program_mode_reg(rinfo, 0x2001, 1);   
+		radeon_pm_program_mode_reg(rinfo, 0x2002, 1);   
+		radeon_pm_program_mode_reg(rinfo, 0x0132, 1);   
+		radeon_pm_program_mode_reg(rinfo, 0x0032, 1); 
+
+		/* Complete & re-enable refresh */
+		OUTREG( MEM_SDRAM_MODE_REG,
+			INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+
+		OUTREG(EXT_MEM_CNTL, memRefreshCntl);
+	}
+	/* And finally, the M7..M9 models, including M9+ (RV280) */
+	else if (rinfo->is_mobility) {
+
+		/* Disable refresh */
+		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
+			& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
+		OUTREG( MEM_REFRESH_CNTL, memRefreshCntl
+			| MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+
+		/* Reset memory */
+		OUTREG( MEM_SDRAM_MODE_REG,
+			INREG( MEM_SDRAM_MODE_REG)
+			& ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+
+		/* DLL */
+		radeon_pm_enable_dll(rinfo);
+
+		/* MLCK / YCLK sync */
+		radeon_pm_yclk_mclk_sync(rinfo);
+
+		/* M6, M7 and M9 so far ... */
+		if (rinfo->family <= CHIP_FAMILY_RV250) {
+			radeon_pm_program_mode_reg(rinfo, 0x2000, 1);
+			radeon_pm_program_mode_reg(rinfo, 0x2001, 1);
+			radeon_pm_program_mode_reg(rinfo, 0x2002, 1);
+			radeon_pm_program_mode_reg(rinfo, 0x0132, 1);
+			radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
+		}
+		/* M9+ (iBook G4) */
+		else if (rinfo->family == CHIP_FAMILY_RV280) {
+			radeon_pm_program_mode_reg(rinfo, 0x2000, 1);
+			radeon_pm_program_mode_reg(rinfo, 0x0132, 1);
+			radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
+		}
+
+		/* Complete & re-enable refresh */
+		OUTREG( MEM_SDRAM_MODE_REG,
+			INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+
+		OUTREG( MEM_REFRESH_CNTL, 	memRefreshCntl);
+	}
+
+	OUTREG( CRTC_GEN_CNTL, 		crtcGenCntl);
+	OUTREG( CRTC2_GEN_CNTL, 	crtcGenCntl2);
+	OUTREG( FP_GEN_CNTL, 		fp_gen_cntl);
+	OUTREG( FP2_GEN_CNTL, 		fp2_gen_cntl);
+
+	OUTREG( CRTC_MORE_CNTL, 	crtc_more_cntl);
+
+	mdelay( 15);
+}
+
+#if defined(CONFIG_PM)
+#if defined(CONFIG_X86) || defined(CONFIG_PPC_PMAC)
+static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo)
+{
+	u32 tmp, tmp2;
+	int i,j;
+
+	/* Reset the PAD_CTLR_STRENGTH & wait for it to be stable */
+	INREG(PAD_CTLR_STRENGTH);
+	OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~PAD_MANUAL_OVERRIDE);
+	tmp = INREG(PAD_CTLR_STRENGTH);
+	for (i = j = 0; i < 65; ++i) {
+		mdelay(1);
+		tmp2 = INREG(PAD_CTLR_STRENGTH);
+		if (tmp != tmp2) {
+			tmp = tmp2;
+			i = 0;
+			j++;
+			if (j > 10) {
+				printk(KERN_WARNING "radeon: PAD_CTLR_STRENGTH doesn't "
+				       "stabilize !\n");
+				break;
+			}
+		}
+	}
+}
+
+static void radeon_pm_all_ppls_off(struct radeonfb_info *rinfo)
+{
+	u32 tmp;
+
+	tmp = INPLL(pllPPLL_CNTL);
+	OUTPLL(pllPPLL_CNTL, tmp | 0x3);
+	tmp = INPLL(pllP2PLL_CNTL);
+	OUTPLL(pllP2PLL_CNTL, tmp | 0x3);
+	tmp = INPLL(pllSPLL_CNTL);
+	OUTPLL(pllSPLL_CNTL, tmp | 0x3);
+	tmp = INPLL(pllMPLL_CNTL);
+	OUTPLL(pllMPLL_CNTL, tmp | 0x3);
+}
+
+static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
+{
+	u32 tmp;
+
+	/* Switch SPLL to PCI source */
+	tmp = INPLL(pllSCLK_CNTL);
+	OUTPLL(pllSCLK_CNTL, tmp & ~SCLK_CNTL__SCLK_SRC_SEL_MASK);
+
+	/* Reconfigure SPLL charge pump, VCO gain, duty cycle */
+	tmp = INPLL(pllSPLL_CNTL);
+	OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+	radeon_pll_errata_after_data(rinfo);
+
+	/* Set SPLL feedback divider */
+	tmp = INPLL(pllM_SPLL_REF_FB_DIV);
+	tmp = (tmp & 0xff00fffful) | (rinfo->save_regs[77] & 0x00ff0000ul);
+	OUTPLL(pllM_SPLL_REF_FB_DIV, tmp);
+
+	/* Power up SPLL */
+	tmp = INPLL(pllSPLL_CNTL);
+	OUTPLL(pllSPLL_CNTL, tmp & ~1);
+	(void)INPLL(pllSPLL_CNTL);
+
+	mdelay(10);
+
+	/* Release SPLL reset */
+	tmp = INPLL(pllSPLL_CNTL);
+	OUTPLL(pllSPLL_CNTL, tmp & ~0x2);
+	(void)INPLL(pllSPLL_CNTL);
+
+	mdelay(10);
+
+	/* Select SCLK source  */
+	tmp = INPLL(pllSCLK_CNTL);
+	tmp &= ~SCLK_CNTL__SCLK_SRC_SEL_MASK;
+	tmp |= rinfo->save_regs[3] & SCLK_CNTL__SCLK_SRC_SEL_MASK;
+	OUTPLL(pllSCLK_CNTL, tmp);
+	(void)INPLL(pllSCLK_CNTL);
+
+	mdelay(10);
+
+	/* Reconfigure MPLL charge pump, VCO gain, duty cycle */
+	tmp = INPLL(pllMPLL_CNTL);
+	OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+	radeon_pll_errata_after_data(rinfo);
+
+	/* Set MPLL feedback divider */
+	tmp = INPLL(pllM_SPLL_REF_FB_DIV);
+	tmp = (tmp & 0xffff00fful) | (rinfo->save_regs[77] & 0x0000ff00ul);
+
+	OUTPLL(pllM_SPLL_REF_FB_DIV, tmp);
+	/* Power up MPLL */
+	tmp = INPLL(pllMPLL_CNTL);
+	OUTPLL(pllMPLL_CNTL, tmp & ~0x2);
+	(void)INPLL(pllMPLL_CNTL);
+
+	mdelay(10);
+
+	/* Un-reset MPLL */
+	tmp = INPLL(pllMPLL_CNTL);
+	OUTPLL(pllMPLL_CNTL, tmp & ~0x1);
+	(void)INPLL(pllMPLL_CNTL);
+
+	mdelay(10);
+
+	/* Select source for MCLK */
+	tmp = INPLL(pllMCLK_CNTL);
+	tmp |= rinfo->save_regs[2] & 0xffff;
+	OUTPLL(pllMCLK_CNTL, tmp);
+	(void)INPLL(pllMCLK_CNTL);
+
+	mdelay(10);
+}
+
+static void radeon_pm_m10_disable_spread_spectrum(struct radeonfb_info *rinfo)
+{
+	u32 r2ec;
+
+	/* GACK ! I though we didn't have a DDA on Radeon's anymore
+	 * here we rewrite with the same value, ... I suppose we clear
+	 * some bits that are already clear ? Or maybe this 0x2ec
+	 * register is something new ?
+	 */
+	mdelay(20);
+	r2ec = INREG(VGA_DDA_ON_OFF);
+	OUTREG(VGA_DDA_ON_OFF, r2ec);
+	mdelay(1);
+
+	/* Spread spectrum PLLL off */
+	OUTPLL(pllSSPLL_CNTL, 0xbf03);
+
+	/* Spread spectrum disabled */
+	OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3);
+
+	/* The trace shows read & rewrite of LVDS_PLL_CNTL here with same
+	 * value, not sure what for...
+	 */
+
+	r2ec |= 0x3f0;
+	OUTREG(VGA_DDA_ON_OFF, r2ec);
+	mdelay(1);
+}
+
+static void radeon_pm_m10_enable_lvds_spread_spectrum(struct radeonfb_info *rinfo)
+{
+	u32 r2ec, tmp;
+
+	/* GACK (bis) ! I though we didn't have a DDA on Radeon's anymore
+	 * here we rewrite with the same value, ... I suppose we clear/set
+	 * some bits that are already clear/set ?
+	 */
+	r2ec = INREG(VGA_DDA_ON_OFF);
+	OUTREG(VGA_DDA_ON_OFF, r2ec);
+	mdelay(1);
+
+	/* Enable spread spectrum */
+	OUTPLL(pllSSPLL_CNTL, rinfo->save_regs[43] | 3);
+	mdelay(3);
+
+	OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44]);
+	OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45]);
+	tmp = INPLL(pllSSPLL_CNTL);
+	OUTPLL(pllSSPLL_CNTL, tmp & ~0x2);
+	mdelay(6);
+	tmp = INPLL(pllSSPLL_CNTL);
+	OUTPLL(pllSSPLL_CNTL, tmp & ~0x1);
+	mdelay(5);
+
+       	OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90]);
+
+	r2ec |= 8;
+	OUTREG(VGA_DDA_ON_OFF, r2ec);
+	mdelay(20);
+
+	/* Enable LVDS interface */
+	tmp = INREG(LVDS_GEN_CNTL);
+	OUTREG(LVDS_GEN_CNTL, tmp | LVDS_EN);
+
+	/* Enable LVDS_PLL */
+	tmp = INREG(LVDS_PLL_CNTL);
+	tmp &= ~0x30000;
+	tmp |= 0x10000;
+	OUTREG(LVDS_PLL_CNTL, tmp);
+
+	OUTPLL(pllSCLK_MORE_CNTL, rinfo->save_regs[34]);
+	OUTPLL(pllSS_TST_CNTL, rinfo->save_regs[91]);
+
+	/* The trace reads that one here, waiting for something to settle down ? */
+	INREG(RBBM_STATUS);
+
+	/* Ugh ? SS_TST_DEC is supposed to be a read register in the
+	 * R300 register spec at least...
+	 */
+	tmp = INPLL(pllSS_TST_CNTL);
+	tmp |= 0x00400000;
+	OUTPLL(pllSS_TST_CNTL, tmp);
+}
+
+static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
+{
+	u32 tmp;
+
+	OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA, 0);
+	radeon_pll_errata_after_data(rinfo);
+
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80);
+	mdelay(5);
+
+	tmp = INPLL(pllPPLL_REF_DIV);
+	tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div;
+	OUTPLL(pllPPLL_REF_DIV, tmp);
+	INPLL(pllPPLL_REF_DIV);
+
+	/* Reconfigure SPLL charge pump, VCO gain, duty cycle,
+	 * probably useless since we already did it ...
+	 */
+	tmp = INPLL(pllPPLL_CNTL);
+	OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+	radeon_pll_errata_after_data(rinfo);
+
+	/* Restore our "reference" PPLL divider set by firmware
+	 * according to proper spread spectrum calculations
+	 */
+	OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]);
+
+	tmp = INPLL(pllPPLL_CNTL);
+	OUTPLL(pllPPLL_CNTL, tmp & ~0x2);
+	mdelay(5);
+
+	tmp = INPLL(pllPPLL_CNTL);
+	OUTPLL(pllPPLL_CNTL, tmp & ~0x1);
+	mdelay(5);
+
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	OUTPLL(pllVCLK_ECP_CNTL, tmp | 3);
+	mdelay(5);
+
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	OUTPLL(pllVCLK_ECP_CNTL, tmp | 3);
+	mdelay(5);
+
+	/* Switch pixel clock to firmware default div 0 */
+	OUTREG8(CLOCK_CNTL_INDEX+1, 0);
+	radeon_pll_errata_after_index(rinfo);
+	radeon_pll_errata_after_data(rinfo);
+}
+
+static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo)
+{
+	OUTREG(MC_CNTL, rinfo->save_regs[46]);
+	OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]);
+	OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]);
+	OUTREG(MEM_SDRAM_MODE_REG,
+	       rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+	OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]);
+	OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]);
+	OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]);
+	OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]);
+	OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]);
+	OUTREG(MC_DEBUG, rinfo->save_regs[53]);
+
+	OUTMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER, rinfo->save_regs[58]);
+	OUTMC(rinfo, ixR300_MC_IMP_CNTL, rinfo->save_regs[59]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0, rinfo->save_regs[60]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1, rinfo->save_regs[61]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0, rinfo->save_regs[62]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1, rinfo->save_regs[63]);
+	OUTMC(rinfo, ixR300_MC_BIST_CNTL_3, rinfo->save_regs[64]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0, rinfo->save_regs[65]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1, rinfo->save_regs[66]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0, rinfo->save_regs[67]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1, rinfo->save_regs[68]);
+	OUTMC(rinfo, ixR300_MC_DEBUG_CNTL, rinfo->save_regs[69]);
+	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
+	OUTMC(rinfo, ixR300_MC_IMP_CNTL_0, rinfo->save_regs[71]);
+	OUTMC(rinfo, ixR300_MC_ELPIDA_CNTL, rinfo->save_regs[72]);
+	OUTMC(rinfo, ixR300_MC_READ_CNTL_CD, rinfo->save_regs[96]);
+	OUTREG(MC_IND_INDEX, 0);
+}
+
+static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
+{
+	u32 tmp, i;
+
+	/* Restore a bunch of registers first */
+	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
+	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
+	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
+	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
+	OUTREG(FCP_CNTL, rinfo->save_regs[38]);
+	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
+	OUTREG(DAC_CNTL, rinfo->save_regs[40]);
+	OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8);
+	OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8);
+
+	/* Hrm... */
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE);
+
+	/* Reset the PAD CTLR */
+	radeon_pm_reset_pad_ctlr_strength(rinfo);
+
+	/* Some PLLs are Read & written identically in the trace here...
+	 * I suppose it's actually to switch them all off & reset,
+	 * let's assume off is what we want. I'm just doing that for all major PLLs now.
+	 */
+	radeon_pm_all_ppls_off(rinfo);
+
+	/* Clear tiling, reset swappers */
+	INREG(SURFACE_CNTL);
+	OUTREG(SURFACE_CNTL, 0);
+
+	/* Some black magic with TV_DAC_CNTL, we should restore those from backups
+	 * rather than hard coding...
+	 */
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK;
+	tmp |= 8 << TV_DAC_CNTL_BGADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK;
+	tmp |= 7 << TV_DAC_CNTL_DACADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+
+	/* More registers restored */
+	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]);
+	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+
+	/* Hrmmm ... What is that ? */
+	tmp = rinfo->save_regs[1]
+		& ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK |
+		    CLK_PWRMGT_CNTL__MC_BUSY);
+	OUTPLL(pllCLK_PWRMGT_CNTL, tmp);
+
+	OUTREG(PAD_CTLR_MISC, rinfo->save_regs[56]);
+	OUTREG(FW_CNTL, rinfo->save_regs[57]);
+	OUTREG(HDP_DEBUG, rinfo->save_regs[96]);
+	OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]);
+	OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]);
+	OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]);
+
+	/* Restore Memory Controller configuration */
+	radeon_pm_m10_reconfigure_mc(rinfo);
+
+	/* Make sure CRTC's dont touch memory */
+	OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL)
+	       | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B);
+	OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL)
+	       | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B);
+	mdelay(30);
+
+	/* Disable SDRAM refresh */
+	OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL)
+	       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+
+	/* Restore XTALIN routing (CLK_PIN_CNTL) */
+	OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]);
+
+	/* Switch MCLK, YCLK and SCLK PLLs to PCI source & force them ON */
+	tmp = rinfo->save_regs[2] & 0xff000000;
+	tmp |=	MCLK_CNTL__FORCE_MCLKA |
+		MCLK_CNTL__FORCE_MCLKB |
+		MCLK_CNTL__FORCE_YCLKA |
+		MCLK_CNTL__FORCE_YCLKB |
+		MCLK_CNTL__FORCE_MC;
+	OUTPLL(pllMCLK_CNTL, tmp);
+
+	/* Force all clocks on in SCLK */
+	tmp = INPLL(pllSCLK_CNTL);
+	tmp |=	SCLK_CNTL__FORCE_DISP2|
+		SCLK_CNTL__FORCE_CP|
+		SCLK_CNTL__FORCE_HDP|
+		SCLK_CNTL__FORCE_DISP1|
+		SCLK_CNTL__FORCE_TOP|
+		SCLK_CNTL__FORCE_E2|
+		SCLK_CNTL__FORCE_SE|
+		SCLK_CNTL__FORCE_IDCT|
+		SCLK_CNTL__FORCE_VIP|
+		SCLK_CNTL__FORCE_PB|
+		SCLK_CNTL__FORCE_TAM|
+		SCLK_CNTL__FORCE_TDM|
+		SCLK_CNTL__FORCE_RB|
+		SCLK_CNTL__FORCE_TV_SCLK|
+		SCLK_CNTL__FORCE_SUBPIC|
+		SCLK_CNTL__FORCE_OV0;
+	tmp |=	SCLK_CNTL__CP_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__HDP_MAX_DYN_STOP_LAT |
+		SCLK_CNTL__TV_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__E2_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__SE_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT|
+		SCLK_CNTL__VIP_MAX_DYN_STOP_LAT |
+		SCLK_CNTL__RE_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__PB_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__TAM_MAX_DYN_STOP_LAT |
+		SCLK_CNTL__TDM_MAX_DYN_STOP_LAT |
+		SCLK_CNTL__RB_MAX_DYN_STOP_LAT;
+	OUTPLL(pllSCLK_CNTL, tmp);
+
+	OUTPLL(pllVCLK_ECP_CNTL, 0);
+	OUTPLL(pllPIXCLKS_CNTL, 0);
+	OUTPLL(pllMCLK_MISC,
+	       MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT |
+	       MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT);
+
+	mdelay(5);
+
+	/* Restore the M_SPLL_REF_FB_DIV, MPLL_AUX_CNTL and SPLL_AUX_CNTL values */
+	OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]);
+	OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]);
+	OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]);
+
+	/* Now restore the major PLLs settings, keeping them off & reset though */
+	OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3);
+	OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3);
+	OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03);
+	OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03);
+
+	/* Restore MC DLL state and switch it off/reset too  */
+	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
+
+	/* Switch MDLL off & reset */
+	OUTPLL(pllMDLL_RDCKA, rinfo->save_regs[98] | 0xff);
+	mdelay(5);
+
+	/* Setup some black magic bits in PLL_PWRMGT_CNTL. Hrm... we saved
+	 * 0xa1100007... and MacOS writes 0xa1000007 ..
+	 */
+	OUTPLL(pllPLL_PWRMGT_CNTL, rinfo->save_regs[0]);
+
+	/* Restore more stuffs */
+	OUTPLL(pllHTOTAL_CNTL, 0);
+	OUTPLL(pllHTOTAL2_CNTL, 0);
+
+	/* More PLL initial configuration */
+	tmp = INPLL(pllSCLK_CNTL2); /* What for ? */
+	OUTPLL(pllSCLK_CNTL2, tmp);
+
+	tmp = INPLL(pllSCLK_MORE_CNTL);
+	tmp |= 	SCLK_MORE_CNTL__FORCE_DISPREGS |	/* a guess */
+		SCLK_MORE_CNTL__FORCE_MC_GUI |
+		SCLK_MORE_CNTL__FORCE_MC_HOST;
+	OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+	/* Now we actually start MCLK and SCLK */
+	radeon_pm_start_mclk_sclk(rinfo);
+
+	/* Full reset sdrams, this also re-inits the MDLL */
+	radeon_pm_full_reset_sdram(rinfo);
+
+	/* Fill palettes */
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20);
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20);
+	udelay(20);
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20);
+	mdelay(3);
+
+	/* Restore TMDS */
+	OUTREG(FP_GEN_CNTL, rinfo->save_regs[82]);
+	OUTREG(FP2_GEN_CNTL, rinfo->save_regs[83]);
+
+	/* Set LVDS registers but keep interface & pll down */
+	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] &
+	       ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN));
+	OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000);
+
+	OUTREG(DISP_OUTPUT_CNTL, rinfo->save_regs[86]);
+
+	/* Restore GPIOPAD state */
+	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
+	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
+	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
+
+	/* write some stuff to the framebuffer... */
+	for (i = 0; i < 0x8000; ++i)
+		writeb(0, rinfo->fb_base + i);
+
+	mdelay(40);
+	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON);
+	mdelay(40);
+
+	/* Restore a few more things */
+	OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]);
+	OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]);
+
+	/* Take care of spread spectrum & PPLLs now */
+	radeon_pm_m10_disable_spread_spectrum(rinfo);
+	radeon_pm_restore_pixel_pll(rinfo);
+
+	/* GRRRR... I can't figure out the proper LVDS power sequence, and the
+	 * code I have for blank/unblank doesn't quite work on some laptop models
+	 * it seems ... Hrm. What I have here works most of the time ...
+	 */
+	radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
+}
+#endif
+
+#ifdef CONFIG_PPC_OF
+#ifdef CONFIG_PPC_PMAC
+static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
+{
+	OUTREG(MC_CNTL, rinfo->save_regs[46]);
+	OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]);
+	OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]);
+	OUTREG(MEM_SDRAM_MODE_REG,
+	       rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+	OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]);
+	OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]);
+	OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]);
+	OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]);
+	OUTREG(MC_DEBUG, rinfo->save_regs[53]);
+	OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]);
+
+	OUTMC(rinfo, ixMC_IMP_CNTL, rinfo->save_regs[59] /*0x00f460d6*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, rinfo->save_regs[65] /*0xfecfa666*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, rinfo->save_regs[66] /*0x141555ff*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, rinfo->save_regs[67] /*0xfecfa666*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
+	OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
+
+	mdelay(20);
+}
+
+static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo)
+{
+	u32 tmp, i;
+
+	/* Restore a bunch of registers first */
+	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
+	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
+	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
+	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
+	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
+	OUTREG(FCP_CNTL, rinfo->save_regs[38]);
+	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
+
+	OUTREG(DAC_CNTL, rinfo->save_regs[40]);
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE);
+
+	/* Reset the PAD CTLR */
+	radeon_pm_reset_pad_ctlr_strength(rinfo);
+
+	/* Some PLLs are Read & written identically in the trace here...
+	 * I suppose it's actually to switch them all off & reset,
+	 * let's assume off is what we want. I'm just doing that for all major PLLs now.
+	 */
+	radeon_pm_all_ppls_off(rinfo);
+
+	/* Clear tiling, reset swappers */
+	INREG(SURFACE_CNTL);
+	OUTREG(SURFACE_CNTL, 0);
+
+	/* Some black magic with TV_DAC_CNTL, we should restore those from backups
+	 * rather than hard coding...
+	 */
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK;
+	tmp |= 6 << TV_DAC_CNTL_BGADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK;
+	tmp |= 6 << TV_DAC_CNTL_DACADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+
+	OUTPLL(pllAGP_PLL_CNTL, rinfo->save_regs[78]);
+
+	OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]);
+	OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]);
+	OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]);
+
+	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]); /* MacOS sets that to 0 !!! */
+	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+
+	tmp  = rinfo->save_regs[1]
+		& ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK |
+		    CLK_PWRMGT_CNTL__MC_BUSY);
+	OUTPLL(pllCLK_PWRMGT_CNTL, tmp);
+
+	OUTREG(FW_CNTL, rinfo->save_regs[57]);
+
+	/* Disable SDRAM refresh */
+	OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL)
+	       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+
+	/* Restore XTALIN routing (CLK_PIN_CNTL) */
+       	OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]);
+
+	/* Force MCLK to be PCI sourced and forced ON */
+	tmp = rinfo->save_regs[2] & 0xff000000;
+	tmp |=	MCLK_CNTL__FORCE_MCLKA |
+		MCLK_CNTL__FORCE_MCLKB |
+		MCLK_CNTL__FORCE_YCLKA |
+		MCLK_CNTL__FORCE_YCLKB |
+		MCLK_CNTL__FORCE_MC    |
+		MCLK_CNTL__FORCE_AIC;
+	OUTPLL(pllMCLK_CNTL, tmp);
+
+	/* Force SCLK to be PCI sourced with a bunch forced */
+	tmp =	0 |
+		SCLK_CNTL__FORCE_DISP2|
+		SCLK_CNTL__FORCE_CP|
+		SCLK_CNTL__FORCE_HDP|
+		SCLK_CNTL__FORCE_DISP1|
+		SCLK_CNTL__FORCE_TOP|
+		SCLK_CNTL__FORCE_E2|
+		SCLK_CNTL__FORCE_SE|
+		SCLK_CNTL__FORCE_IDCT|
+		SCLK_CNTL__FORCE_VIP|
+		SCLK_CNTL__FORCE_RE|
+		SCLK_CNTL__FORCE_PB|
+		SCLK_CNTL__FORCE_TAM|
+		SCLK_CNTL__FORCE_TDM|
+		SCLK_CNTL__FORCE_RB;
+	OUTPLL(pllSCLK_CNTL, tmp);
+
+	/* Clear VCLK_ECP_CNTL & PIXCLKS_CNTL  */
+	OUTPLL(pllVCLK_ECP_CNTL, 0);
+	OUTPLL(pllPIXCLKS_CNTL, 0);
+
+	/* Setup MCLK_MISC, non dynamic mode */
+	OUTPLL(pllMCLK_MISC,
+	       MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT |
+	       MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT);
+
+	mdelay(5);
+
+	/* Set back the default clock dividers */
+	OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]);
+	OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]);
+	OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]);
+
+	/* PPLL and P2PLL default values & off */
+	OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3);
+	OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3);
+
+	/* S and M PLLs are reset & off, configure them */
+	OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03);
+	OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03);
+
+	/* Default values for MDLL ... fixme */
+	OUTPLL(pllMDLL_CKO, 0x9c009c);
+	OUTPLL(pllMDLL_RDCKA, 0x08830883);
+	OUTPLL(pllMDLL_RDCKB, 0x08830883);
+	mdelay(5);
+
+	/* Restore PLL_PWRMGT_CNTL */ // XXXX
+	tmp = rinfo->save_regs[0];
+	tmp &= ~PLL_PWRMGT_CNTL_SU_SCLK_USE_BCLK;
+	tmp |= PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
+	OUTPLL(PLL_PWRMGT_CNTL,  tmp);
+
+	/* Clear HTOTAL_CNTL & HTOTAL2_CNTL */
+	OUTPLL(pllHTOTAL_CNTL, 0);
+	OUTPLL(pllHTOTAL2_CNTL, 0);
+
+	/* All outputs off */
+	OUTREG(CRTC_GEN_CNTL, 0x04000000);
+	OUTREG(CRTC2_GEN_CNTL, 0x04000000);
+	OUTREG(FP_GEN_CNTL, 0x00004008);
+	OUTREG(FP2_GEN_CNTL, 0x00000008);
+	OUTREG(LVDS_GEN_CNTL, 0x08000008);
+
+	/* Restore Memory Controller configuration */
+	radeon_pm_m9p_reconfigure_mc(rinfo);
+
+	/* Now we actually start MCLK and SCLK */
+	radeon_pm_start_mclk_sclk(rinfo);
+
+	/* Full reset sdrams, this also re-inits the MDLL */
+	radeon_pm_full_reset_sdram(rinfo);
+
+	/* Fill palettes */
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20);
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20);
+	udelay(20);
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20);
+	mdelay(3);
+
+	/* Restore TV stuff, make sure TV DAC is down */
+	OUTREG(TV_MASTER_CNTL, rinfo->save_regs[88]);
+	OUTREG(TV_DAC_CNTL, rinfo->save_regs[13] | 0x07000000);
+
+	/* Restore GPIOS. MacOS does some magic here with one of the GPIO bits,
+	 * possibly related to the weird PLL related workarounds and to the
+	 * fact that CLK_PIN_CNTL is tweaked in ways I don't fully understand,
+	 * but we keep things the simple way here
+	 */
+	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
+	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
+	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
+
+	/* Now do things with SCLK_MORE_CNTL. Force bits are already set, copy
+	 * high bits from backup
+	 */
+	tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff;
+	tmp |= rinfo->save_regs[34] & 0xffff0000;
+	tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS;
+	OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+	tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff;
+	tmp |= rinfo->save_regs[34] & 0xffff0000;
+	tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS;
+	OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] &
+	       ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN));
+	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_BLON);
+	OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000);
+	mdelay(20);
+
+	/* write some stuff to the framebuffer... */
+	for (i = 0; i < 0x8000; ++i)
+		writeb(0, rinfo->fb_base + i);
+
+	OUTREG(0x2ec, 0x6332a020);
+	OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44] /*0x3f */);
+	OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45] /*0x000081bb */);
+	tmp = INPLL(pllSSPLL_CNTL);
+	tmp &= ~2;
+	OUTPLL(pllSSPLL_CNTL, tmp);
+	mdelay(6);
+	tmp &= ~1;
+	OUTPLL(pllSSPLL_CNTL, tmp);
+	mdelay(5);
+	tmp |= 3;
+	OUTPLL(pllSSPLL_CNTL, tmp);
+	mdelay(5);
+
+	OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3);/*0x0020300c*/
+	OUTREG(0x2ec, 0x6332a3f0);
+	mdelay(17);
+
+	OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div);
+	OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]);
+
+	mdelay(40);
+	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON);
+	mdelay(40);
+
+	/* Restore a few more things */
+	OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]);
+	OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]);
+
+	/* Restore PPLL, spread spectrum & LVDS */
+	radeon_pm_m10_disable_spread_spectrum(rinfo);
+	radeon_pm_restore_pixel_pll(rinfo);
+	radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
+}
+#endif
+#endif
+
+#if 0 /* Not ready yet */
+static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
+{
+	int i;
+	u32 tmp, tmp2;
+	u32 cko, cka, ckb;
+	u32 cgc, cec, c2gc;
+
+	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
+	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
+
+	INREG(PAD_CTLR_STRENGTH);
+	OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~0x10000);
+	for (i = 0; i < 65; ++i) {
+		mdelay(1);
+		INREG(PAD_CTLR_STRENGTH);
+	}
+
+	OUTREG(DISP_TEST_DEBUG_CNTL, INREG(DISP_TEST_DEBUG_CNTL) | 0x10000000);
+	OUTREG(OV0_FLAG_CNTRL, INREG(OV0_FLAG_CNTRL) | 0x100);
+	OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL));
+	OUTREG(DAC_CNTL, 0xff00410a);
+	OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL));
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x4000);
+
+	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
+	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]);
+	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, 0xf7bb4433);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, 0xf7bb4433);
+	OUTREG(MC_IND_INDEX, 0);
+
+	OUTREG(CRTC_MORE_CNTL, INREG(CRTC_MORE_CNTL));
+
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	OUTPLL(pllVCLK_ECP_CNTL, tmp);
+	tmp = INPLL(pllPIXCLKS_CNTL);
+	OUTPLL(pllPIXCLKS_CNTL, tmp);
+
+	OUTPLL(MCLK_CNTL, 0xaa3f0000);
+	OUTPLL(SCLK_CNTL, 0xffff0000);
+	OUTPLL(pllMPLL_AUX_CNTL, 6);
+	OUTPLL(pllSPLL_AUX_CNTL, 1);
+	OUTPLL(MDLL_CKO, 0x9f009f);
+	OUTPLL(MDLL_RDCKA, 0x830083);
+	OUTPLL(pllMDLL_RDCKB, 0x830083);
+	OUTPLL(PPLL_CNTL, 0xa433);
+	OUTPLL(P2PLL_CNTL, 0xa433);
+	OUTPLL(MPLL_CNTL, 0x0400a403);
+	OUTPLL(SPLL_CNTL, 0x0400a433);
+
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp);
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0xc);
+	INPLL(M_SPLL_REF_FB_DIV);
+
+	tmp = INPLL(MPLL_CNTL);
+	OUTREG8(CLOCK_CNTL_INDEX, MPLL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+	radeon_pll_errata_after_data(rinfo);
+
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x5900);
+
+	tmp = INPLL(MPLL_CNTL);
+	OUTPLL(MPLL_CNTL, tmp & ~0x2);
+	mdelay(1);
+	tmp = INPLL(MPLL_CNTL);
+	OUTPLL(MPLL_CNTL, tmp & ~0x1);
+	mdelay(10);
+
+	OUTPLL(MCLK_CNTL, 0xaa3f1212);
+	mdelay(1);
+
+	INPLL(M_SPLL_REF_FB_DIV);
+	INPLL(MCLK_CNTL);
+	INPLL(M_SPLL_REF_FB_DIV);
+
+	tmp = INPLL(SPLL_CNTL);
+	OUTREG8(CLOCK_CNTL_INDEX, SPLL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+	radeon_pll_errata_after_data(rinfo);
+
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x780000);
+
+	tmp = INPLL(SPLL_CNTL);
+	OUTPLL(SPLL_CNTL, tmp & ~0x1);
+	mdelay(1);
+	tmp = INPLL(SPLL_CNTL);
+	OUTPLL(SPLL_CNTL, tmp & ~0x2);
+	mdelay(10);
+
+	tmp = INPLL(SCLK_CNTL);
+	OUTPLL(SCLK_CNTL, tmp | 2);
+	mdelay(1);
+
+	cko = INPLL(pllMDLL_CKO);
+	cka = INPLL(pllMDLL_RDCKA);
+	ckb = INPLL(pllMDLL_RDCKB);
+
+	cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP);
+	OUTPLL(pllMDLL_CKO, cko);
+	mdelay(1);
+	cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET);
+	OUTPLL(pllMDLL_CKO, cko);
+	mdelay(5);
+
+	cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP);
+	OUTPLL(pllMDLL_RDCKA, cka);
+	mdelay(1);
+	cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET);
+	OUTPLL(pllMDLL_RDCKA, cka);
+	mdelay(5);
+
+	ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP);
+	OUTPLL(pllMDLL_RDCKB, ckb);
+	mdelay(1);
+	ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET);
+	OUTPLL(pllMDLL_RDCKB, ckb);
+	mdelay(5);
+
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x151550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x151550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	mdelay(1);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x141550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x141550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	mdelay(1);
+
+	OUTPLL(pllHTOTAL_CNTL, 0);
+	OUTPLL(pllHTOTAL2_CNTL, 0);
+
+	OUTREG(MEM_CNTL, 0x29002901);
+	OUTREG(MEM_SDRAM_MODE_REG, 0x45320032);	/* XXX use save_regs[35]? */
+	OUTREG(EXT_MEM_CNTL, 0x1a394333);
+	OUTREG(MEM_IO_CNTL_A1, 0x0aac0aac);
+	OUTREG(MEM_INIT_LATENCY_TIMER, 0x34444444);
+	OUTREG(MEM_REFRESH_CNTL, 0x1f1f7218);	/* XXX or save_regs[42]? */
+	OUTREG(MC_DEBUG, 0);
+	OUTREG(MEM_IO_OE_CNTL, 0x04300430);
+
+	OUTMC(rinfo, ixMC_IMP_CNTL, 0x00f460d6);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
+	OUTREG(MC_IND_INDEX, 0);
+
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
+
+	radeon_pm_full_reset_sdram(rinfo);
+
+	INREG(FP_GEN_CNTL);
+	OUTREG(TMDS_CNTL, 0x01000000);	/* XXX ? */
+	tmp = INREG(FP_GEN_CNTL);
+	tmp |= FP_CRTC_DONT_SHADOW_HEND | FP_CRTC_DONT_SHADOW_VPAR | 0x200;
+	OUTREG(FP_GEN_CNTL, tmp);
+
+	tmp = INREG(DISP_OUTPUT_CNTL);
+	tmp &= ~0x400;
+	OUTREG(DISP_OUTPUT_CNTL, tmp);
+
+	OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
+	OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
+	OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
+
+	tmp = INPLL(MCLK_MISC);
+	tmp |= MCLK_MISC__MC_MCLK_DYN_ENABLE | MCLK_MISC__IO_MCLK_DYN_ENABLE;
+	OUTPLL(MCLK_MISC, tmp);
+
+	tmp = INPLL(SCLK_CNTL);
+	OUTPLL(SCLK_CNTL, tmp);
+
+	OUTREG(CRTC_MORE_CNTL, 0);
+	OUTREG8(CRTC_GEN_CNTL+1, 6);
+	OUTREG8(CRTC_GEN_CNTL+3, 1);
+	OUTREG(CRTC_PITCH, 32);
+
+	tmp = INPLL(VCLK_ECP_CNTL);
+	OUTPLL(VCLK_ECP_CNTL, tmp);
+
+	tmp = INPLL(PPLL_CNTL);
+	OUTPLL(PPLL_CNTL, tmp);
+
+	/* palette stuff and BIOS_1_SCRATCH... */
+
+	tmp = INREG(FP_GEN_CNTL);
+	tmp2 = INREG(TMDS_TRANSMITTER_CNTL);
+	tmp |= 2;
+	OUTREG(FP_GEN_CNTL, tmp);
+	mdelay(5);
+	OUTREG(FP_GEN_CNTL, tmp);
+	mdelay(5);
+	OUTREG(TMDS_TRANSMITTER_CNTL, tmp2);
+	OUTREG(CRTC_MORE_CNTL, 0);
+	mdelay(20);
+
+	tmp = INREG(CRTC_MORE_CNTL);
+	OUTREG(CRTC_MORE_CNTL, tmp);
+
+	cgc = INREG(CRTC_GEN_CNTL);
+	cec = INREG(CRTC_EXT_CNTL);
+	c2gc = INREG(CRTC2_GEN_CNTL);
+
+	OUTREG(CRTC_H_SYNC_STRT_WID, 0x008e0580);
+	OUTREG(CRTC_H_TOTAL_DISP, 0x009f00d2);
+	OUTREG8(CLOCK_CNTL_INDEX, HTOTAL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA, 0);
+	radeon_pll_errata_after_data(rinfo);
+	OUTREG(CRTC_V_SYNC_STRT_WID, 0x00830403);
+	OUTREG(CRTC_V_TOTAL_DISP, 0x03ff0429);
+	OUTREG(FP_CRTC_H_TOTAL_DISP, 0x009f0033);
+	OUTREG(FP_H_SYNC_STRT_WID, 0x008e0080);
+	OUTREG(CRT_CRTC_H_SYNC_STRT_WID, 0x008e0080);
+	OUTREG(FP_CRTC_V_TOTAL_DISP, 0x03ff002a);
+	OUTREG(FP_V_SYNC_STRT_WID, 0x00830004);
+	OUTREG(CRT_CRTC_V_SYNC_STRT_WID, 0x00830004);
+	OUTREG(FP_HORZ_VERT_ACTIVE, 0x009f03ff);
+	OUTREG(FP_HORZ_STRETCH, 0);
+	OUTREG(FP_VERT_STRETCH, 0);
+	OUTREG(OVR_CLR, 0);
+	OUTREG(OVR_WID_LEFT_RIGHT, 0);
+	OUTREG(OVR_WID_TOP_BOTTOM, 0);
+
+	tmp = INPLL(PPLL_REF_DIV);
+	tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div;
+	OUTPLL(PPLL_REF_DIV, tmp);
+	INPLL(PPLL_REF_DIV);
+
+	OUTREG8(CLOCK_CNTL_INDEX, PPLL_CNTL + PLL_WR_EN);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG8(CLOCK_CNTL_DATA + 1, 0xbc);
+	radeon_pll_errata_after_data(rinfo);
+
+	tmp = INREG(CLOCK_CNTL_INDEX);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG(CLOCK_CNTL_INDEX, tmp & 0xff);
+	radeon_pll_errata_after_index(rinfo);
+	radeon_pll_errata_after_data(rinfo);
+
+	OUTPLL(PPLL_DIV_0, 0x48090);
+
+	tmp = INPLL(PPLL_CNTL);
+	OUTPLL(PPLL_CNTL, tmp & ~0x2);
+	mdelay(1);
+	tmp = INPLL(PPLL_CNTL);
+	OUTPLL(PPLL_CNTL, tmp & ~0x1);
+	mdelay(10);
+
+	tmp = INPLL(VCLK_ECP_CNTL);
+	OUTPLL(VCLK_ECP_CNTL, tmp | 3);
+	mdelay(1);
+
+	tmp = INPLL(VCLK_ECP_CNTL);
+	OUTPLL(VCLK_ECP_CNTL, tmp);
+
+	c2gc |= CRTC2_DISP_REQ_EN_B;
+	OUTREG(CRTC2_GEN_CNTL, c2gc);
+	cgc |= CRTC_EN;
+	OUTREG(CRTC_GEN_CNTL, cgc);
+	OUTREG(CRTC_EXT_CNTL, cec);
+	OUTREG(CRTC_PITCH, 0xa0);
+	OUTREG(CRTC_OFFSET, 0);
+	OUTREG(CRTC_OFFSET_CNTL, 0);
+
+	OUTREG(GRPH_BUFFER_CNTL, 0x20117c7c);
+	OUTREG(GRPH2_BUFFER_CNTL, 0x00205c5c);
+
+	tmp2 = INREG(FP_GEN_CNTL);
+	tmp = INREG(TMDS_TRANSMITTER_CNTL);
+	OUTREG(0x2a8, 0x0000061b);
+	tmp |= TMDS_PLL_EN;
+	OUTREG(TMDS_TRANSMITTER_CNTL, tmp);
+	mdelay(1);
+	tmp &= ~TMDS_PLLRST;
+	OUTREG(TMDS_TRANSMITTER_CNTL, tmp);
+	tmp2 &= ~2;
+	tmp2 |= FP_TMDS_EN;
+	OUTREG(FP_GEN_CNTL, tmp2);
+	mdelay(5);
+	tmp2 |= FP_FPON;
+	OUTREG(FP_GEN_CNTL, tmp2);
+
+	OUTREG(CUR_HORZ_VERT_OFF, CUR_LOCK | 1);
+	cgc = INREG(CRTC_GEN_CNTL);
+	OUTREG(CUR_HORZ_VERT_POSN, 0xbfff0fff);
+	cgc |= 0x10000;
+	OUTREG(CUR_OFFSET, 0);
+}
+#endif /* 0 */
+
+#endif /* CONFIG_PPC_OF */
+
+static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state)
+{
+	u16 pwr_cmd;
+
+	for (;;) {
+		pci_read_config_word(rinfo->pdev,
+				     rinfo->pdev->pm_cap + PCI_PM_CTRL,
+				     &pwr_cmd);
+		if (pwr_cmd & state)
+			break;
+		pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | state;
+		pci_write_config_word(rinfo->pdev,
+				      rinfo->pdev->pm_cap + PCI_PM_CTRL,
+				      pwr_cmd);
+		msleep(500);
+	}
+	rinfo->pdev->current_state = state;
+}
+
+static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
+{
+	u32 tmp;
+
+	if (!rinfo->pdev->pm_cap)
+		return;
+
+	/* Set the chip into appropriate suspend mode (we use D2,
+	 * D3 would require a compete re-initialization of the chip,
+	 * including PCI config registers, clocks, AGP conf, ...)
+	 */
+	if (suspend) {
+		printk(KERN_DEBUG "radeonfb (%s): switching to D2 state...\n",
+		       pci_name(rinfo->pdev));
+
+		/* Disable dynamic power management of clocks for the
+		 * duration of the suspend/resume process
+		 */
+		radeon_pm_disable_dynamic_mode(rinfo);
+
+		/* Save some registers */
+		radeon_pm_save_regs(rinfo, 0);
+
+		/* Prepare mobility chips for suspend.
+		 */
+		if (rinfo->is_mobility) {
+			/* Program V2CLK */
+			radeon_pm_program_v2clk(rinfo);
+		
+			/* Disable IO PADs */
+			radeon_pm_disable_iopad(rinfo);
+
+			/* Set low current */
+			radeon_pm_low_current(rinfo);
+
+			/* Prepare chip for power management */
+			radeon_pm_setup_for_suspend(rinfo);
+
+			if (rinfo->family <= CHIP_FAMILY_RV280) {
+				/* Reset the MDLL */
+				/* because both INPLL and OUTPLL take the same
+				 * lock, that's why. */
+				tmp = INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET
+					| MDLL_CKO__MCKOB_RESET;
+				OUTPLL( pllMDLL_CKO, tmp );
+			}
+		}
+
+		/* Switch PCI power management to D2. */
+		pci_disable_device(rinfo->pdev);
+		pci_save_state(rinfo->pdev);
+		/* The chip seems to need us to whack the PM register
+		 * repeatedly until it sticks. We do that -prior- to
+		 * calling pci_set_power_state()
+		 */
+		radeonfb_whack_power_state(rinfo, PCI_D2);
+		__pci_complete_power_transition(rinfo->pdev, PCI_D2);
+	} else {
+		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
+		       pci_name(rinfo->pdev));
+
+		if (rinfo->family <= CHIP_FAMILY_RV250) {
+			/* Reset the SDRAM controller  */
+			radeon_pm_full_reset_sdram(rinfo);
+
+			/* Restore some registers */
+			radeon_pm_restore_regs(rinfo);
+		} else {
+			/* Restore registers first */
+			radeon_pm_restore_regs(rinfo);
+			/* init sdram controller */
+			radeon_pm_full_reset_sdram(rinfo);
+		}
+	}
+}
+
+int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+        struct fb_info *info = pci_get_drvdata(pdev);
+        struct radeonfb_info *rinfo = info->par;
+
+	if (mesg.event == pdev->dev.power.power_state.event)
+		return 0;
+
+	printk(KERN_DEBUG "radeonfb (%s): suspending for event: %d...\n",
+	       pci_name(pdev), mesg.event);
+
+	/* For suspend-to-disk, we cheat here. We don't suspend anything and
+	 * let fbcon continue drawing until we are all set. That shouldn't
+	 * really cause any problem at this point, provided that the wakeup
+	 * code knows that any state in memory may not match the HW
+	 */
+	switch (mesg.event) {
+	case PM_EVENT_FREEZE:		/* about to take snapshot */
+	case PM_EVENT_PRETHAW:		/* before restoring snapshot */
+		goto done;
+	}
+
+	console_lock();
+
+	fb_set_suspend(info, 1);
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
+		/* Make sure engine is reset */
+		radeon_engine_idle();
+		radeonfb_engine_reset(rinfo);
+		radeon_engine_idle();
+	}
+
+	/* Blank display and LCD */
+	radeon_screen_blank(rinfo, FB_BLANK_POWERDOWN, 1);
+
+	/* Sleep */
+	rinfo->asleep = 1;
+	rinfo->lock_blank = 1;
+	del_timer_sync(&rinfo->lvds_timer);
+
+#ifdef CONFIG_PPC_PMAC
+	/* On powermac, we have hooks to properly suspend/resume AGP now,
+	 * use them here. We'll ultimately need some generic support here,
+	 * but the generic code isn't quite ready for that yet
+	 */
+	pmac_suspend_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
+
+	/* It's unclear whether or when the generic code will do that, so let's
+	 * do it ourselves. We save state before we do any power management
+	 */
+	pci_save_state(pdev);
+
+	/* If we support wakeup from poweroff, we save all regs we can including cfg
+	 * space
+	 */
+	if (rinfo->pm_mode & radeon_pm_off) {
+		/* Always disable dynamic clocks or weird things are happening when
+		 * the chip goes off (basically the panel doesn't shut down properly
+		 * and we crash on wakeup),
+		 * also, we want the saved regs context to have no dynamic clocks in
+		 * it, we'll restore the dynamic clocks state on wakeup
+		 */
+		radeon_pm_disable_dynamic_mode(rinfo);
+		mdelay(50);
+		radeon_pm_save_regs(rinfo, 1);
+
+		if (rinfo->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) {
+			/* Switch off LVDS interface */
+			mdelay(1);
+			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_BL_MOD_EN));
+			mdelay(1);
+			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_EN | LVDS_ON));
+			OUTREG(LVDS_PLL_CNTL, (INREG(LVDS_PLL_CNTL) & ~30000) | 0x20000);
+			mdelay(20);
+			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
+		}
+		pci_disable_device(pdev);
+	}
+	/* If we support D2, we go to it (should be fixed later with a flag forcing
+	 * D3 only for some laptops)
+	 */
+	if (rinfo->pm_mode & radeon_pm_d2)
+		radeon_set_suspend(rinfo, 1);
+
+	console_unlock();
+
+ done:
+	pdev->dev.power.power_state = mesg;
+
+	return 0;
+}
+
+static int radeon_check_power_loss(struct radeonfb_info *rinfo)
+{
+	return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) ||
+	       rinfo->save_regs[2] != INPLL(MCLK_CNTL) ||
+	       rinfo->save_regs[3] != INPLL(SCLK_CNTL);
+}
+
+int radeonfb_pci_resume(struct pci_dev *pdev)
+{
+        struct fb_info *info = pci_get_drvdata(pdev);
+        struct radeonfb_info *rinfo = info->par;
+	int rc = 0;
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
+		return 0;
+
+	if (rinfo->no_schedule) {
+		if (!console_trylock())
+			return 0;
+	} else
+		console_lock();
+
+	printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
+	       pci_name(pdev), pdev->dev.power.power_state.event);
+
+	/* PCI state will have been restored by the core, so
+	 * we should be in D0 now with our config space fully
+	 * restored
+	 */
+	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+		/* Wakeup chip */
+		if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) {
+			if (rinfo->reinit_func != NULL)
+				rinfo->reinit_func(rinfo);
+			else {
+				printk(KERN_ERR "radeonfb (%s): can't resume radeon from"
+				       " D3 cold, need softboot !", pci_name(pdev));
+				rc = -EIO;
+				goto bail;
+			}
+		}
+		/* If we support D2, try to resume... we should check what was our
+		 * state though... (were we really in D2 state ?). Right now, this code
+		 * is only enable on Macs so it's fine.
+		 */
+		else if (rinfo->pm_mode & radeon_pm_d2)
+			radeon_set_suspend(rinfo, 0);
+
+		rinfo->asleep = 0;
+	} else
+		radeon_engine_idle();
+
+	/* Restore display & engine */
+	radeon_write_mode (rinfo, &rinfo->state, 1);
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+		radeonfb_engine_init (rinfo);
+
+	fb_pan_display(info, &info->var);
+	fb_set_cmap(&info->cmap, info);
+
+	/* Refresh */
+	fb_set_suspend(info, 0);
+
+	/* Unblank */
+	rinfo->lock_blank = 0;
+	radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 1);
+
+#ifdef CONFIG_PPC_PMAC
+	/* On powermac, we have hooks to properly suspend/resume AGP now,
+	 * use them here. We'll ultimately need some generic support here,
+	 * but the generic code isn't quite ready for that yet
+	 */
+	pmac_resume_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
+
+
+	/* Check status of dynclk */
+	if (rinfo->dynclk == 1)
+		radeon_pm_enable_dynamic_mode(rinfo);
+	else if (rinfo->dynclk == 0)
+		radeon_pm_disable_dynamic_mode(rinfo);
+
+	pdev->dev.power.power_state = PMSG_ON;
+
+ bail:
+	console_unlock();
+
+	return rc;
+}
+
+#ifdef CONFIG_PPC_OF__disabled
+static void radeonfb_early_resume(void *data)
+{
+        struct radeonfb_info *rinfo = data;
+
+	rinfo->no_schedule = 1;
+	pci_restore_state(rinfo->pdev);
+	radeonfb_pci_resume(rinfo->pdev);
+	rinfo->no_schedule = 0;
+}
+#endif /* CONFIG_PPC_OF */
+
+#endif /* CONFIG_PM */
+
+void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
+{
+	/* Enable/Disable dynamic clocks: TODO add sysfs access */
+	if (rinfo->family == CHIP_FAMILY_RS480)
+		rinfo->dynclk = -1;
+	else
+		rinfo->dynclk = dynclk;
+
+	if (rinfo->dynclk == 1) {
+		radeon_pm_enable_dynamic_mode(rinfo);
+		printk("radeonfb: Dynamic Clock Power Management enabled\n");
+	} else if (rinfo->dynclk == 0) {
+		radeon_pm_disable_dynamic_mode(rinfo);
+		printk("radeonfb: Dynamic Clock Power Management disabled\n");
+	}
+
+#if defined(CONFIG_PM)
+#if defined(CONFIG_PPC_PMAC)
+	/* Check if we can power manage on suspend/resume. We can do
+	 * D2 on M6, M7 and M9, and we can resume from D3 cold a few other
+	 * "Mac" cards, but that's all. We need more infos about what the
+	 * BIOS does tho. Right now, all this PM stuff is pmac-only for that
+	 * reason. --BenH
+	 */
+	if (machine_is(powermac) && rinfo->of_node) {
+		if (rinfo->is_mobility && rinfo->pdev->pm_cap &&
+		    rinfo->family <= CHIP_FAMILY_RV250)
+			rinfo->pm_mode |= radeon_pm_d2;
+
+		/* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
+		 * in some desktop G4s), Via (M9+ chip on iBook G4) and
+		 * Snowy (M11 chip on iBook G4 manufactured after July 2005)
+		 */
+		if (!strcmp(rinfo->of_node->name, "ATY,JasperParent") ||
+		    !strcmp(rinfo->of_node->name, "ATY,SnowyParent")) {
+			rinfo->reinit_func = radeon_reinitialize_M10;
+			rinfo->pm_mode |= radeon_pm_off;
+		}
+#if 0 /* Not ready yet */
+		if (!strcmp(rinfo->of_node->name, "ATY,BlueStoneParent")) {
+			rinfo->reinit_func = radeon_reinitialize_QW;
+			rinfo->pm_mode |= radeon_pm_off;
+		}
+#endif
+		if (!strcmp(rinfo->of_node->name, "ATY,ViaParent")) {
+			rinfo->reinit_func = radeon_reinitialize_M9P;
+			rinfo->pm_mode |= radeon_pm_off;
+		}
+
+		/* If any of the above is set, we assume the machine can sleep/resume.
+		 * It's a bit of a "shortcut" but will work fine. Ideally, we need infos
+		 * from the platform about what happens to the chip...
+		 * Now we tell the platform about our capability
+		 */
+		if (rinfo->pm_mode != radeon_pm_none) {
+			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1);
+#if 0 /* Disable the early video resume hack for now as it's causing problems, among
+       * others we now rely on the PCI core restoring the config space for us, which
+       * isn't the case with that hack, and that code path causes various things to
+       * be called with interrupts off while they shouldn't. I'm leaving the code in
+       * as it can be useful for debugging purposes
+       */
+			pmac_set_early_video_resume(radeonfb_early_resume, rinfo);
+#endif
+		}
+
+#if 0
+		/* Power down TV DAC, that saves a significant amount of power,
+		 * we'll have something better once we actually have some TVOut
+		 * support
+		 */
+		OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
+#endif
+	}
+#endif /* defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PM) */
+
+	if (ignore_devlist)
+		printk(KERN_DEBUG
+		       "radeonfb: skipping test for device workarounds\n");
+	else
+		radeon_apply_workarounds(rinfo);
+
+	if (force_sleep) {
+		printk(KERN_DEBUG
+		       "radeonfb: forcefully enabling D2 sleep mode\n");
+		rinfo->pm_mode |= radeon_pm_d2;
+	}
+}
+
+void radeonfb_pm_exit(struct radeonfb_info *rinfo)
+{
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
+	if (rinfo->pm_mode != radeon_pm_none)
+		pmac_set_early_video_resume(NULL, NULL);
+#endif
+}
diff --git a/drivers/video/fbdev/aty/radeonfb.h b/drivers/video/fbdev/aty/radeonfb.h
new file mode 100644
index 000000000000..cb846044f57c
--- /dev/null
+++ b/drivers/video/fbdev/aty/radeonfb.h
@@ -0,0 +1,634 @@
+#ifndef __RADEONFB_H__
+#define __RADEONFB_H__
+
+#ifdef CONFIG_FB_RADEON_DEBUG
+#define DEBUG		1
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+
+#ifdef CONFIG_FB_RADEON_I2C
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#endif
+
+#include <asm/io.h>
+
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+#include <asm/prom.h>
+#endif
+
+#include <video/radeon.h>
+
+/***************************************************************
+ * Most of the definitions here are adapted right from XFree86 *
+ ***************************************************************/
+
+
+/*
+ * Chip families. Must fit in the low 16 bits of a long word
+ */
+enum radeon_family {
+	CHIP_FAMILY_UNKNOW,
+	CHIP_FAMILY_LEGACY,
+	CHIP_FAMILY_RADEON,
+	CHIP_FAMILY_RV100,
+	CHIP_FAMILY_RS100,    /* U1 (IGP320M) or A3 (IGP320)*/
+	CHIP_FAMILY_RV200,
+	CHIP_FAMILY_RS200,    /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350),
+				 RS250 (IGP 7000) */
+	CHIP_FAMILY_R200,
+	CHIP_FAMILY_RV250,
+	CHIP_FAMILY_RS300,    /* Radeon 9000 IGP */
+	CHIP_FAMILY_RV280,
+	CHIP_FAMILY_R300,
+	CHIP_FAMILY_R350,
+	CHIP_FAMILY_RV350,
+	CHIP_FAMILY_RV380,    /* RV370/RV380/M22/M24 */
+	CHIP_FAMILY_R420,     /* R420/R423/M18 */
+	CHIP_FAMILY_RC410,
+	CHIP_FAMILY_RS400,
+	CHIP_FAMILY_RS480,
+	CHIP_FAMILY_LAST,
+};
+
+#define IS_RV100_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_RV100)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RV200)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RS100)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RS200)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RV250)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RV280)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RS300))
+
+
+#define IS_R300_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_R300)  || \
+				((rinfo)->family == CHIP_FAMILY_RV350) || \
+				((rinfo)->family == CHIP_FAMILY_R350)  || \
+				((rinfo)->family == CHIP_FAMILY_RV380) || \
+				((rinfo)->family == CHIP_FAMILY_R420)  || \
+                               ((rinfo)->family == CHIP_FAMILY_RC410) || \
+                               ((rinfo)->family == CHIP_FAMILY_RS480))
+
+/*
+ * Chip flags
+ */
+enum radeon_chip_flags {
+	CHIP_FAMILY_MASK	= 0x0000ffffUL,
+	CHIP_FLAGS_MASK		= 0xffff0000UL,
+	CHIP_IS_MOBILITY	= 0x00010000UL,
+	CHIP_IS_IGP		= 0x00020000UL,
+	CHIP_HAS_CRTC2		= 0x00040000UL,	
+};
+
+/*
+ * Errata workarounds
+ */
+enum radeon_errata {
+	CHIP_ERRATA_R300_CG		= 0x00000001,
+	CHIP_ERRATA_PLL_DUMMYREADS	= 0x00000002,
+	CHIP_ERRATA_PLL_DELAY		= 0x00000004,
+};
+
+
+/*
+ * Monitor types
+ */
+enum radeon_montype {
+	MT_NONE = 0,
+	MT_CRT,		/* CRT */
+	MT_LCD,		/* LCD */
+	MT_DFP,		/* DVI */
+	MT_CTV,		/* composite TV */
+	MT_STV		/* S-Video out */
+};
+
+/*
+ * DDC i2c ports
+ */
+enum ddc_type {
+	ddc_none,
+	ddc_monid,
+	ddc_dvi,
+	ddc_vga,
+	ddc_crt2,
+};
+
+/*
+ * Connector types
+ */
+enum conn_type {
+	conn_none,
+	conn_proprietary,
+	conn_crt,
+	conn_DVI_I,
+	conn_DVI_D,
+};
+
+
+/*
+ * PLL infos
+ */
+struct pll_info {
+	int ppll_max;
+	int ppll_min;
+	int sclk, mclk;
+	int ref_div;
+	int ref_clk;
+};
+
+
+/*
+ * This structure contains the various registers manipulated by this
+ * driver for setting or restoring a mode. It's mostly copied from
+ * XFree's RADEONSaveRec structure. A few chip settings might still be
+ * tweaked without beeing reflected or saved in these registers though
+ */
+struct radeon_regs {
+	/* Common registers */
+	u32		ovr_clr;
+	u32		ovr_wid_left_right;
+	u32		ovr_wid_top_bottom;
+	u32		ov0_scale_cntl;
+	u32		mpp_tb_config;
+	u32		mpp_gp_config;
+	u32		subpic_cntl;
+	u32		viph_control;
+	u32		i2c_cntl_1;
+	u32		gen_int_cntl;
+	u32		cap0_trig_cntl;
+	u32		cap1_trig_cntl;
+	u32		bus_cntl;
+	u32		surface_cntl;
+	u32		bios_5_scratch;
+
+	/* Other registers to save for VT switches or driver load/unload */
+	u32		dp_datatype;
+	u32		rbbm_soft_reset;
+	u32		clock_cntl_index;
+	u32		amcgpio_en_reg;
+	u32		amcgpio_mask;
+
+	/* Surface/tiling registers */
+	u32		surf_lower_bound[8];
+	u32		surf_upper_bound[8];
+	u32		surf_info[8];
+
+	/* CRTC registers */
+	u32		crtc_gen_cntl;
+	u32		crtc_ext_cntl;
+	u32		dac_cntl;
+	u32		crtc_h_total_disp;
+	u32		crtc_h_sync_strt_wid;
+	u32		crtc_v_total_disp;
+	u32		crtc_v_sync_strt_wid;
+	u32		crtc_offset;
+	u32		crtc_offset_cntl;
+	u32		crtc_pitch;
+	u32		disp_merge_cntl;
+	u32		grph_buffer_cntl;
+	u32		crtc_more_cntl;
+
+	/* CRTC2 registers */
+	u32		crtc2_gen_cntl;
+	u32		dac2_cntl;
+	u32		disp_output_cntl;
+	u32		disp_hw_debug;
+	u32		disp2_merge_cntl;
+	u32		grph2_buffer_cntl;
+	u32		crtc2_h_total_disp;
+	u32		crtc2_h_sync_strt_wid;
+	u32		crtc2_v_total_disp;
+	u32		crtc2_v_sync_strt_wid;
+	u32		crtc2_offset;
+	u32		crtc2_offset_cntl;
+	u32		crtc2_pitch;
+
+	/* Flat panel regs */
+	u32 		fp_crtc_h_total_disp;
+	u32		fp_crtc_v_total_disp;
+	u32		fp_gen_cntl;
+	u32		fp2_gen_cntl;
+	u32		fp_h_sync_strt_wid;
+	u32		fp2_h_sync_strt_wid;
+	u32		fp_horz_stretch;
+	u32		fp_panel_cntl;
+	u32		fp_v_sync_strt_wid;
+	u32		fp2_v_sync_strt_wid;
+	u32		fp_vert_stretch;
+	u32		lvds_gen_cntl;
+	u32		lvds_pll_cntl;
+	u32		tmds_crc;
+	u32		tmds_transmitter_cntl;
+
+	/* Computed values for PLL */
+	u32		dot_clock_freq;
+	int		feedback_div;
+	int		post_div;	
+
+	/* PLL registers */
+	u32		ppll_div_3;
+	u32		ppll_ref_div;
+	u32		vclk_ecp_cntl;
+	u32		clk_cntl_index;
+
+	/* Computed values for PLL2 */
+	u32		dot_clock_freq_2;
+	int		feedback_div_2;
+	int		post_div_2;
+
+	/* PLL2 registers */
+	u32		p2pll_ref_div;
+	u32		p2pll_div_0;
+	u32		htotal_cntl2;
+
+       	/* Palette */
+	int		palette_valid;
+};
+
+struct panel_info {
+	int xres, yres;
+	int valid;
+	int clock;
+	int hOver_plus, hSync_width, hblank;
+	int vOver_plus, vSync_width, vblank;
+	int hAct_high, vAct_high, interlaced;
+	int pwr_delay;
+	int use_bios_dividers;
+	int ref_divider;
+	int post_divider;
+	int fbk_divider;
+};
+
+struct radeonfb_info;
+
+#ifdef CONFIG_FB_RADEON_I2C
+struct radeon_i2c_chan {
+	struct radeonfb_info		*rinfo;
+	u32		 		ddc_reg;
+	struct i2c_adapter		adapter;
+	struct i2c_algo_bit_data	algo;
+};
+#endif
+
+enum radeon_pm_mode {
+	radeon_pm_none	= 0,		/* Nothing supported */
+	radeon_pm_d2	= 0x00000001,	/* Can do D2 state */
+	radeon_pm_off	= 0x00000002,	/* Can resume from D3 cold */
+};
+
+typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo);
+
+struct radeonfb_info {
+	struct fb_info		*info;
+
+	struct radeon_regs 	state;
+	struct radeon_regs	init_state;
+
+	char			name[50];
+
+	unsigned long		mmio_base_phys;
+	unsigned long		fb_base_phys;
+
+	void __iomem		*mmio_base;
+	void __iomem		*fb_base;
+
+	unsigned long		fb_local_base;
+
+	struct pci_dev		*pdev;
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
+	struct device_node	*of_node;
+#endif
+
+	void __iomem		*bios_seg;
+	int			fp_bios_start;
+
+	u32			pseudo_palette[16];
+	struct { u8 red, green, blue, pad; }
+				palette[256];
+
+	int			chipset;
+	u8			family;
+	u8			rev;
+	unsigned int		errata;
+	unsigned long		video_ram;
+	unsigned long		mapped_vram;
+	int			vram_width;
+	int			vram_ddr;
+
+	int			pitch, bpp, depth;
+
+	int			has_CRTC2;
+	int			is_mobility;
+	int			is_IGP;
+	int			reversed_DAC;
+	int			reversed_TMDS;
+	struct panel_info	panel_info;
+	int			mon1_type;
+	u8			*mon1_EDID;
+	struct fb_videomode	*mon1_modedb;
+	int			mon1_dbsize;
+	int			mon2_type;
+	u8		        *mon2_EDID;
+
+	u32			dp_gui_master_cntl;
+
+	struct pll_info		pll;
+
+	int			mtrr_hdl;
+
+	u32			save_regs[100];
+	int			asleep;
+	int			lock_blank;
+	int			dynclk;
+	int			no_schedule;
+	enum radeon_pm_mode	pm_mode;
+	reinit_function_ptr     reinit_func;
+
+	/* Lock on register access */
+	spinlock_t		reg_lock;
+
+	/* Timer used for delayed LVDS operations */
+	struct timer_list	lvds_timer;
+	u32			pending_lvds_gen_cntl;
+
+#ifdef CONFIG_FB_RADEON_I2C
+	struct radeon_i2c_chan 	i2c[4];
+#endif
+};
+
+
+#define PRIMARY_MONITOR(rinfo)	(rinfo->mon1_type)
+
+
+/*
+ * IO macros
+ */
+
+/* Note about this function: we have some rare cases where we must not schedule,
+ * this typically happen with our special "wake up early" hook which allows us to
+ * wake up the graphic chip (and thus get the console back) before everything else
+ * on some machines that support that mechanism. At this point, interrupts are off
+ * and scheduling is not permitted
+ */
+static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
+{
+	if (rinfo->no_schedule || oops_in_progress)
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+
+#define INREG8(addr)		readb((rinfo->mmio_base)+addr)
+#define OUTREG8(addr,val)	writeb(val, (rinfo->mmio_base)+addr)
+#define INREG16(addr)		readw((rinfo->mmio_base)+addr)
+#define OUTREG16(addr,val)	writew(val, (rinfo->mmio_base)+addr)
+#define INREG(addr)		readl((rinfo->mmio_base)+addr)
+#define OUTREG(addr,val)	writel(val, (rinfo->mmio_base)+addr)
+
+static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
+		       u32 val, u32 mask)
+{
+	unsigned long flags;
+	unsigned int tmp;
+
+	spin_lock_irqsave(&rinfo->reg_lock, flags);
+	tmp = INREG(addr);
+	tmp &= (mask);
+	tmp |= (val);
+	OUTREG(addr, tmp);
+	spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+}
+
+#define OUTREGP(addr,val,mask)	_OUTREGP(rinfo, addr, val,mask)
+
+/*
+ * Note about PLL register accesses:
+ *
+ * I have removed the spinlock on them on purpose. The driver now
+ * expects that it will only manipulate the PLL registers in normal
+ * task environment, where radeon_msleep() will be called, protected
+ * by a semaphore (currently the console semaphore) so that no conflict
+ * will happen on the PLL register index.
+ *
+ * With the latest changes to the VT layer, this is guaranteed for all
+ * calls except the actual drawing/blits which aren't supposed to use
+ * the PLL registers anyway
+ *
+ * This is very important for the workarounds to work properly. The only
+ * possible exception to this rule is the call to unblank(), which may
+ * be done at irq time if an oops is in progress.
+ */
+static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
+{
+	if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
+		return;
+
+	(void)INREG(CLOCK_CNTL_DATA);
+	(void)INREG(CRTC_GEN_CNTL);
+}
+
+static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
+{
+	if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
+		/* we can't deal with posted writes here ... */
+		_radeon_msleep(rinfo, 5);
+	}
+	if (rinfo->errata & CHIP_ERRATA_R300_CG) {
+		u32 save, tmp;
+		save = INREG(CLOCK_CNTL_INDEX);
+		tmp = save & ~(0x3f | PLL_WR_EN);
+		OUTREG(CLOCK_CNTL_INDEX, tmp);
+		tmp = INREG(CLOCK_CNTL_DATA);
+		OUTREG(CLOCK_CNTL_INDEX, save);
+	}
+}
+
+static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
+{
+	u32 data;
+
+	OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
+	radeon_pll_errata_after_index(rinfo);
+	data = INREG(CLOCK_CNTL_DATA);
+	radeon_pll_errata_after_data(rinfo);
+	return data;
+}
+
+static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
+			    u32 val)
+{
+
+	OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+	radeon_pll_errata_after_index(rinfo);
+	OUTREG(CLOCK_CNTL_DATA, val);
+	radeon_pll_errata_after_data(rinfo);
+}
+
+
+static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+			     u32 val, u32 mask)
+{
+	unsigned int tmp;
+
+	tmp  = __INPLL(rinfo, index);
+	tmp &= (mask);
+	tmp |= (val);
+	__OUTPLL(rinfo, index, tmp);
+}
+
+
+#define INPLL(addr)			__INPLL(rinfo, addr)
+#define OUTPLL(index, val)		__OUTPLL(rinfo, index, val)
+#define OUTPLLP(index, val, mask)	__OUTPLLP(rinfo, index, val, mask)
+
+
+#define BIOS_IN8(v)  	(readb(rinfo->bios_seg + (v)))
+#define BIOS_IN16(v) 	(readb(rinfo->bios_seg + (v)) | \
+			  (readb(rinfo->bios_seg + (v) + 1) << 8))
+#define BIOS_IN32(v) 	(readb(rinfo->bios_seg + (v)) | \
+			  (readb(rinfo->bios_seg + (v) + 1) << 8) | \
+			  (readb(rinfo->bios_seg + (v) + 2) << 16) | \
+			  (readb(rinfo->bios_seg + (v) + 3) << 24))
+
+/*
+ * Inline utilities
+ */
+static inline int round_div(int num, int den)
+{
+        return (num + (den / 2)) / den;
+}
+
+static inline int var_to_depth(const struct fb_var_screeninfo *var)
+{
+	if (var->bits_per_pixel != 16)
+		return var->bits_per_pixel;
+	return (var->green.length == 5) ? 15 : 16;
+}
+
+static inline u32 radeon_get_dstbpp(u16 depth)
+{
+	switch (depth) {
+       	case 8:
+       		return DST_8BPP;
+       	case 15:
+       		return DST_15BPP;
+       	case 16:
+       		return DST_16BPP;
+       	case 32:
+       		return DST_32BPP;
+       	default:
+       		return 0;
+	}
+}
+
+/*
+ * 2D Engine helper routines
+ */
+
+static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+	int i;
+
+	for (i=0; i<2000000; i++) {
+		if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
+			return;
+		udelay(1);
+	}
+	printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
+}
+
+static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
+{
+	int i;
+
+	/* Initiate flush */
+	OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+	        ~RB2D_DC_FLUSH_ALL);
+
+	/* Ensure FIFO is empty, ie, make sure the flush commands
+	 * has reached the cache
+	 */
+	_radeon_fifo_wait (rinfo, 64);
+
+	/* Wait for the flush to complete */
+	for (i=0; i < 2000000; i++) {
+		if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+			return;
+		udelay(1);
+	}
+	printk(KERN_ERR "radeonfb: Flush Timeout !\n");
+}
+
+
+static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
+{
+	int i;
+
+	/* ensure FIFO is empty before waiting for idle */
+	_radeon_fifo_wait (rinfo, 64);
+
+	for (i=0; i<2000000; i++) {
+		if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
+			radeon_engine_flush (rinfo);
+			return;
+		}
+		udelay(1);
+	}
+	printk(KERN_ERR "radeonfb: Idle Timeout !\n");
+}
+
+
+#define radeon_engine_idle()		_radeon_engine_idle(rinfo)
+#define radeon_fifo_wait(entries)	_radeon_fifo_wait(rinfo,entries)
+#define radeon_msleep(ms)		_radeon_msleep(rinfo,ms)
+
+
+/* I2C Functions */
+extern void radeon_create_i2c_busses(struct radeonfb_info *rinfo);
+extern void radeon_delete_i2c_busses(struct radeonfb_info *rinfo);
+extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
+
+/* PM Functions */
+extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
+extern int radeonfb_pci_resume(struct pci_dev *pdev);
+extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep);
+extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
+
+/* Monitor probe functions */
+extern void radeon_probe_screens(struct radeonfb_info *rinfo,
+				 const char *monitor_layout, int ignore_edid);
+extern void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option);
+extern int radeon_match_mode(struct radeonfb_info *rinfo,
+			     struct fb_var_screeninfo *dest,
+			     const struct fb_var_screeninfo *src);
+
+/* Accel functions */
+extern void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region);
+extern void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
+extern int radeonfb_sync(struct fb_info *info);
+extern void radeonfb_engine_init (struct radeonfb_info *rinfo);
+extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
+
+/* Other functions */
+extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
+extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
+			       int reg_only);
+
+/* Backlight functions */
+#ifdef CONFIG_FB_RADEON_BACKLIGHT
+extern void radeonfb_bl_init(struct radeonfb_info *rinfo);
+extern void radeonfb_bl_exit(struct radeonfb_info *rinfo);
+#else
+static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {}
+static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {}
+#endif
+
+#endif /* __RADEONFB_H__ */
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c
new file mode 100644
index 000000000000..372d4aea9d1c
--- /dev/null
+++ b/drivers/video/fbdev/au1100fb.c
@@ -0,0 +1,642 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1100 LCD Driver.
+ *
+ * Rewritten for 2.6 by Embedded Alley Solutions
+ * 	<source@embeddedalley.com>, based on submissions by
+ *  	Karl Lessard <klessard@sunrisetelecom.com>
+ *  	<c.pellegrin@exadron.com>
+ *
+ * PM support added by Rodolfo Giometti <giometti@linux.it>
+ * Cursor enable/disable by Rodolfo Giometti <giometti@linux.it>
+ *
+ * Copyright 2002 MontaVista Software
+ * Author: MontaVista Software, Inc.
+ *		ppopov@mvista.com or source@mvista.com
+ *
+ * Copyright 2002 Alchemy Semiconductor
+ * Author: Alchemy Semiconductor
+ *
+ * Based on:
+ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
+ *  Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+#define DEBUG 0
+
+#include "au1100fb.h"
+
+#define DRIVER_NAME "au1100fb"
+#define DRIVER_DESC "LCD controller driver for AU1100 processors"
+
+#define to_au1100fb_device(_info) \
+	  (_info ? container_of(_info, struct au1100fb_device, info) : NULL);
+
+/* Bitfields format supported by the controller. Note that the order of formats
+ * SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the
+ * right pixel format by doing rgb_bitfields[LCD_CONTROL_SBPPF_XXX >> LCD_CONTROL_SBPPF]
+ */
+struct fb_bitfield rgb_bitfields[][4] =
+{
+  	/*     Red, 	   Green, 	 Blue, 	     Transp   */
+	{ { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+	{ { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+	{ { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
+	{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
+	{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
+
+	/* The last is used to describe 12bpp format */
+	{ { 8, 4, 0 },  { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
+};
+
+static struct fb_fix_screeninfo au1100fb_fix = {
+	.id		= "AU1100 FB",
+	.xpanstep 	= 1,
+	.ypanstep 	= 1,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo au1100fb_var = {
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+/* fb_blank
+ * Blank the screen. Depending on the mode, the screen will be
+ * activated with the backlight color, or desactivated
+ */
+static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
+{
+	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+
+	print_dbg("fb_blank %d %p", blank_mode, fbi);
+
+	switch (blank_mode) {
+
+	case VESA_NO_BLANKING:
+		/* Turn on panel */
+		fbdev->regs->lcd_control |= LCD_CONTROL_GO;
+		au_sync();
+		break;
+
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+	case VESA_POWERDOWN:
+		/* Turn off panel */
+		fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
+		au_sync();
+		break;
+	default:
+		break;
+
+	}
+	return 0;
+}
+
+/*
+ * Set hardware with var settings. This will enable the controller with a specific
+ * mode, normally validated with the fb_check_var method
+	 */
+int au1100fb_setmode(struct au1100fb_device *fbdev)
+{
+	struct fb_info *info = &fbdev->info;
+	u32 words;
+	int index;
+
+	if (!fbdev)
+		return -EINVAL;
+
+	/* Update var-dependent FB info */
+	if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) {
+		if (info->var.bits_per_pixel <= 8) {
+			/* palettized */
+			info->var.red.offset    = 0;
+			info->var.red.length    = info->var.bits_per_pixel;
+			info->var.red.msb_right = 0;
+
+			info->var.green.offset  = 0;
+			info->var.green.length  = info->var.bits_per_pixel;
+			info->var.green.msb_right = 0;
+
+			info->var.blue.offset   = 0;
+			info->var.blue.length   = info->var.bits_per_pixel;
+			info->var.blue.msb_right = 0;
+
+			info->var.transp.offset = 0;
+			info->var.transp.length = 0;
+			info->var.transp.msb_right = 0;
+
+			info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+			info->fix.line_length = info->var.xres_virtual /
+							(8/info->var.bits_per_pixel);
+		} else {
+			/* non-palettized */
+			index = (fbdev->panel->control_base & LCD_CONTROL_SBPPF_MASK) >> LCD_CONTROL_SBPPF_BIT;
+			info->var.red = rgb_bitfields[index][0];
+			info->var.green = rgb_bitfields[index][1];
+			info->var.blue = rgb_bitfields[index][2];
+			info->var.transp = rgb_bitfields[index][3];
+
+			info->fix.visual = FB_VISUAL_TRUECOLOR;
+			info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */
+		}
+	} else {
+		/* mono */
+		info->fix.visual = FB_VISUAL_MONO10;
+		info->fix.line_length = info->var.xres_virtual / 8;
+	}
+
+	info->screen_size = info->fix.line_length * info->var.yres_virtual;
+	info->var.rotate = ((fbdev->panel->control_base&LCD_CONTROL_SM_MASK) \
+				>> LCD_CONTROL_SM_BIT) * 90;
+
+	/* Determine BPP mode and format */
+	fbdev->regs->lcd_control = fbdev->panel->control_base;
+	fbdev->regs->lcd_horztiming = fbdev->panel->horztiming;
+	fbdev->regs->lcd_verttiming = fbdev->panel->verttiming;
+	fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base;
+	fbdev->regs->lcd_intenable = 0;
+	fbdev->regs->lcd_intstatus = 0;
+	fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys);
+
+	if (panel_is_dual(fbdev->panel)) {
+		/* Second panel display seconf half of screen if possible,
+		 * otherwise display the same as the first panel */
+		if (info->var.yres_virtual >= (info->var.yres << 1)) {
+			fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys +
+							  (info->fix.line_length *
+						          (info->var.yres_virtual >> 1)));
+		} else {
+			fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys);
+		}
+	}
+
+	words = info->fix.line_length / sizeof(u32);
+	if (!info->var.rotate || (info->var.rotate == 180)) {
+		words *= info->var.yres_virtual;
+		if (info->var.rotate /* 180 */) {
+			words -= (words % 8); /* should be divisable by 8 */
+		}
+	}
+	fbdev->regs->lcd_words = LCD_WRD_WRDS_N(words);
+
+	fbdev->regs->lcd_pwmdiv = 0;
+	fbdev->regs->lcd_pwmhi = 0;
+
+	/* Resume controller */
+	fbdev->regs->lcd_control |= LCD_CONTROL_GO;
+	mdelay(10);
+	au1100fb_fb_blank(VESA_NO_BLANKING, info);
+
+	return 0;
+}
+
+/* fb_setcolreg
+ * Set color in LCD palette.
+ */
+int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
+{
+	struct au1100fb_device *fbdev;
+	u32 *palette;
+	u32 value;
+
+	fbdev = to_au1100fb_device(fbi);
+	palette = fbdev->regs->lcd_pallettebase;
+
+	if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
+		return -EINVAL;
+
+	if (fbi->var.grayscale) {
+		/* Convert color to grayscale */
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+	}
+
+	if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		palette = (u32*)fbi->pseudo_palette;
+
+		red   >>= (16 - fbi->var.red.length);
+		green >>= (16 - fbi->var.green.length);
+		blue  >>= (16 - fbi->var.blue.length);
+
+		value = (red   << fbi->var.red.offset) 	|
+			(green << fbi->var.green.offset)|
+			(blue  << fbi->var.blue.offset);
+		value &= 0xFFFF;
+
+	} else if (panel_is_active(fbdev->panel)) {
+		/* COLOR TFT PALLETTIZED (use RGB 565) */
+		value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F);
+		value &= 0xFFFF;
+
+	} else if (panel_is_color(fbdev->panel)) {
+		/* COLOR STN MODE */
+		value = (((panel_swap_rgb(fbdev->panel) ? blue : red) >> 12) & 0x000F) |
+			((green >> 8) & 0x00F0) |
+			(((panel_swap_rgb(fbdev->panel) ? red : blue) >> 4) & 0x0F00);
+		value &= 0xFFF;
+	} else {
+		/* MONOCHROME MODE */
+		value = (green >> 12) & 0x000F;
+		value &= 0xF;
+	}
+
+	palette[regno] = value;
+
+	return 0;
+}
+
+/* fb_pan_display
+ * Pan display in x and/or y as specified
+ */
+int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	struct au1100fb_device *fbdev;
+	int dy;
+
+	fbdev = to_au1100fb_device(fbi);
+
+	print_dbg("fb_pan_display %p %p", var, fbi);
+
+	if (!var || !fbdev) {
+		return -EINVAL;
+	}
+
+	if (var->xoffset - fbi->var.xoffset) {
+		/* No support for X panning for now! */
+		return -EINVAL;
+	}
+
+	print_dbg("fb_pan_display 2 %p %p", var, fbi);
+	dy = var->yoffset - fbi->var.yoffset;
+	if (dy) {
+
+		u32 dmaaddr;
+
+		print_dbg("Panning screen of %d lines", dy);
+
+		dmaaddr = fbdev->regs->lcd_dmaaddr0;
+		dmaaddr += (fbi->fix.line_length * dy);
+
+		/* TODO: Wait for current frame to finished */
+		fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
+
+		if (panel_is_dual(fbdev->panel)) {
+			dmaaddr = fbdev->regs->lcd_dmaaddr1;
+			dmaaddr += (fbi->fix.line_length * dy);
+			fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
+	}
+	}
+	print_dbg("fb_pan_display 3 %p %p", var, fbi);
+
+	return 0;
+}
+
+/* fb_rotate
+ * Rotate the display of this angle. This doesn't seems to be used by the core,
+ * but as our hardware supports it, so why not implementing it...
+ */
+void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
+{
+	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+
+	print_dbg("fb_rotate %p %d", fbi, angle);
+
+	if (fbdev && (angle > 0) && !(angle % 90)) {
+
+		fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
+
+		fbdev->regs->lcd_control &= ~(LCD_CONTROL_SM_MASK);
+		fbdev->regs->lcd_control |= ((angle/90) << LCD_CONTROL_SM_BIT);
+
+		fbdev->regs->lcd_control |= LCD_CONTROL_GO;
+	}
+}
+
+/* fb_mmap
+ * Map video memory in user space. We don't use the generic fb_mmap method mainly
+ * to allow the use of the TLB streaming flag (CCA=6)
+ */
+int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
+{
+	struct au1100fb_device *fbdev;
+
+	fbdev = to_au1100fb_device(fbi);
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
+
+	return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len);
+}
+
+static struct fb_ops au1100fb_ops =
+{
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= au1100fb_fb_setcolreg,
+	.fb_blank		= au1100fb_fb_blank,
+	.fb_pan_display		= au1100fb_fb_pan_display,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_rotate		= au1100fb_fb_rotate,
+	.fb_mmap		= au1100fb_fb_mmap,
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+static int au1100fb_setup(struct au1100fb_device *fbdev)
+{
+	char *this_opt, *options;
+	int num_panels = ARRAY_SIZE(known_lcd_panels);
+
+	if (num_panels <= 0) {
+		print_err("No LCD panels supported by driver!");
+		return -ENODEV;
+	}
+
+	if (fb_get_options(DRIVER_NAME, &options))
+		return -ENODEV;
+	if (!options)
+		return -ENODEV;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		/* Panel option */
+		if (!strncmp(this_opt, "panel:", 6)) {
+			int i;
+			this_opt += 6;
+			for (i = 0; i < num_panels; i++) {
+				if (!strncmp(this_opt, known_lcd_panels[i].name,
+					     strlen(this_opt))) {
+					fbdev->panel = &known_lcd_panels[i];
+					fbdev->panel_idx = i;
+					break;
+				}
+			}
+			if (i >= num_panels) {
+				print_warn("Panel '%s' not supported!", this_opt);
+				return -ENODEV;
+			}
+		}
+		/* Unsupported option */
+		else
+			print_warn("Unsupported option \"%s\"", this_opt);
+	}
+
+	print_info("Panel=%s", fbdev->panel->name);
+
+	return 0;
+}
+
+static int au1100fb_drv_probe(struct platform_device *dev)
+{
+	struct au1100fb_device *fbdev = NULL;
+	struct resource *regs_res;
+	unsigned long page;
+	u32 sys_clksrc;
+
+	/* Allocate new device private */
+	fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
+			     GFP_KERNEL);
+	if (!fbdev) {
+		print_err("fail to allocate device private record");
+		return -ENOMEM;
+	}
+
+	if (au1100fb_setup(fbdev))
+		goto failed;
+
+	platform_set_drvdata(dev, (void *)fbdev);
+
+	/* Allocate region for our registers and map them */
+	regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!regs_res) {
+		print_err("fail to retrieve registers resource");
+		return -EFAULT;
+	}
+
+	au1100fb_fix.mmio_start = regs_res->start;
+	au1100fb_fix.mmio_len = resource_size(regs_res);
+
+	if (!devm_request_mem_region(&dev->dev,
+				     au1100fb_fix.mmio_start,
+				     au1100fb_fix.mmio_len,
+				     DRIVER_NAME)) {
+		print_err("fail to lock memory region at 0x%08lx",
+				au1100fb_fix.mmio_start);
+		return -EBUSY;
+	}
+
+	fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(au1100fb_fix.mmio_start);
+
+	print_dbg("Register memory map at %p", fbdev->regs);
+	print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
+
+	/* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
+	fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
+		  	(fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
+
+	fbdev->fb_mem = dmam_alloc_coherent(&dev->dev,
+					    PAGE_ALIGN(fbdev->fb_len),
+					    &fbdev->fb_phys, GFP_KERNEL);
+	if (!fbdev->fb_mem) {
+		print_err("fail to allocate frambuffer (size: %dK))",
+			  fbdev->fb_len / 1024);
+		return -ENOMEM;
+	}
+
+	au1100fb_fix.smem_start = fbdev->fb_phys;
+	au1100fb_fix.smem_len = fbdev->fb_len;
+
+	/*
+	 * Set page reserved so that mmap will work. This is necessary
+	 * since we'll be remapping normal memory.
+	 */
+	for (page = (unsigned long)fbdev->fb_mem;
+	     page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
+	     page += PAGE_SIZE) {
+#ifdef CONFIG_DMA_NONCOHERENT
+		SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
+#else
+		SetPageReserved(virt_to_page(page));
+#endif
+	}
+
+	print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
+	print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
+
+	/* Setup LCD clock to AUX (48 MHz) */
+	sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL);
+	au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC);
+
+	/* load the panel info into the var struct */
+	au1100fb_var.bits_per_pixel = fbdev->panel->bpp;
+	au1100fb_var.xres = fbdev->panel->xres;
+	au1100fb_var.xres_virtual = au1100fb_var.xres;
+	au1100fb_var.yres = fbdev->panel->yres;
+	au1100fb_var.yres_virtual = au1100fb_var.yres;
+
+	fbdev->info.screen_base = fbdev->fb_mem;
+	fbdev->info.fbops = &au1100fb_ops;
+	fbdev->info.fix = au1100fb_fix;
+
+	fbdev->info.pseudo_palette =
+		devm_kzalloc(&dev->dev, sizeof(u32) * 16, GFP_KERNEL);
+	if (!fbdev->info.pseudo_palette)
+		return -ENOMEM;
+
+	if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+		print_err("Fail to allocate colormap (%d entries)",
+			   AU1100_LCD_NBR_PALETTE_ENTRIES);
+		return -EFAULT;
+	}
+
+	fbdev->info.var = au1100fb_var;
+
+	/* Set h/w registers */
+	au1100fb_setmode(fbdev);
+
+	/* Register new framebuffer */
+	if (register_framebuffer(&fbdev->info) < 0) {
+		print_err("cannot register new framebuffer");
+		goto failed;
+	}
+
+	return 0;
+
+failed:
+	if (fbdev->fb_mem) {
+		dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
+				     fbdev->fb_phys);
+	}
+	if (fbdev->info.cmap.len != 0) {
+		fb_dealloc_cmap(&fbdev->info.cmap);
+	}
+
+	return -ENODEV;
+}
+
+int au1100fb_drv_remove(struct platform_device *dev)
+{
+	struct au1100fb_device *fbdev = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	fbdev = platform_get_drvdata(dev);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
+#endif
+	fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
+
+	/* Clean up all probe data */
+	unregister_framebuffer(&fbdev->info);
+
+	fb_dealloc_cmap(&fbdev->info.cmap);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static u32 sys_clksrc;
+static struct au1100fb_regs fbregs;
+
+int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct au1100fb_device *fbdev = platform_get_drvdata(dev);
+
+	if (!fbdev)
+		return 0;
+
+	/* Save the clock source state */
+	sys_clksrc = au_readl(SYS_CLKSRC);
+
+	/* Blank the LCD */
+	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
+
+	/* Stop LCD clocking */
+	au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC);
+
+	memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs));
+
+	return 0;
+}
+
+int au1100fb_drv_resume(struct platform_device *dev)
+{
+	struct au1100fb_device *fbdev = platform_get_drvdata(dev);
+
+	if (!fbdev)
+		return 0;
+
+	memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs));
+
+	/* Restart LCD clocking */
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	/* Unblank the LCD */
+	au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info);
+
+	return 0;
+}
+#else
+#define au1100fb_drv_suspend NULL
+#define au1100fb_drv_resume NULL
+#endif
+
+static struct platform_driver au1100fb_driver = {
+	.driver = {
+		.name		= "au1100-lcd",
+		.owner          = THIS_MODULE,
+	},
+	.probe		= au1100fb_drv_probe,
+        .remove		= au1100fb_drv_remove,
+	.suspend	= au1100fb_drv_suspend,
+        .resume		= au1100fb_drv_resume,
+};
+module_platform_driver(au1100fb_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/au1100fb.h b/drivers/video/fbdev/au1100fb.h
new file mode 100644
index 000000000000..12d9642d5465
--- /dev/null
+++ b/drivers/video/fbdev/au1100fb.h
@@ -0,0 +1,377 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Hardware definitions for the Au1100 LCD controller
+ *
+ * Copyright 2002 MontaVista Software
+ * Copyright 2002 Alchemy Semiconductor
+ * Author:	Alchemy Semiconductor, MontaVista Software
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _AU1100LCD_H
+#define _AU1100LCD_H
+
+#include <asm/mach-au1x00/au1000.h>
+
+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
+
+#if DEBUG
+#define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg)
+#else
+#define print_dbg(f, arg...) do {} while (0)
+#endif
+
+#if defined(__BIG_ENDIAN)
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
+#else
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
+#endif
+#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
+
+/********************************************************************/
+
+/* LCD controller restrictions */
+#define AU1100_LCD_MAX_XRES	800
+#define AU1100_LCD_MAX_YRES	600
+#define AU1100_LCD_MAX_BPP	16
+#define AU1100_LCD_MAX_CLK	48000000
+#define AU1100_LCD_NBR_PALETTE_ENTRIES 256
+
+/* Default number of visible screen buffer to allocate */
+#define AU1100FB_NBR_VIDEO_BUFFERS 4
+
+/********************************************************************/
+
+struct au1100fb_panel
+{
+	const char name[25];		/* Full name <vendor>_<model> */
+
+	u32   	control_base;		/* Mode-independent control values */
+	u32	clkcontrol_base;	/* Panel pixclock preferences */
+
+	u32	horztiming;
+	u32	verttiming;
+
+	u32	xres;		/* Maximum horizontal resolution */
+	u32 	yres;		/* Maximum vertical resolution */
+	u32 	bpp;		/* Maximum depth supported */
+};
+
+struct au1100fb_regs
+{
+	u32  lcd_control;
+	u32  lcd_intstatus;
+	u32  lcd_intenable;
+	u32  lcd_horztiming;
+	u32  lcd_verttiming;
+	u32  lcd_clkcontrol;
+	u32  lcd_dmaaddr0;
+	u32  lcd_dmaaddr1;
+	u32  lcd_words;
+	u32  lcd_pwmdiv;
+	u32  lcd_pwmhi;
+	u32  reserved[(0x0400-0x002C)/4];
+	u32  lcd_pallettebase[256];
+};
+
+struct au1100fb_device {
+
+	struct fb_info info;			/* FB driver info record */
+
+	struct au1100fb_panel 	*panel;		/* Panel connected to this device */
+
+	struct au1100fb_regs* 	regs;		/* Registers memory map */
+	size_t       		regs_len;
+	unsigned int 		regs_phys;
+
+	unsigned char* 		fb_mem;		/* FrameBuffer memory map */
+	size_t	      		fb_len;
+	dma_addr_t    		fb_phys;
+	int			panel_idx;
+};
+
+/********************************************************************/
+
+#define LCD_CONTROL                (AU1100_LCD_BASE + 0x0)
+  #define LCD_CONTROL_SBB_BIT      21
+  #define LCD_CONTROL_SBB_MASK     (0x3 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_1        (0 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_2        (1 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_3        (2 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_4        (3 << LCD_CONTROL_SBB_BIT)
+  #define LCD_CONTROL_SBPPF_BIT    18
+  #define LCD_CONTROL_SBPPF_MASK   (0x7 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_655    (0 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_565    (1 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_556    (2 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_1555   (3 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_5551   (4 << LCD_CONTROL_SBPPF_BIT)
+  #define LCD_CONTROL_WP           (1<<17)
+  #define LCD_CONTROL_WD           (1<<16)
+  #define LCD_CONTROL_C            (1<<15)
+  #define LCD_CONTROL_SM_BIT       13
+  #define LCD_CONTROL_SM_MASK      (0x3 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_0         (0 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_90        (1 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_180       (2 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_270       (3 << LCD_CONTROL_SM_BIT)
+  #define LCD_CONTROL_DB           (1<<12)
+  #define LCD_CONTROL_CCO          (1<<11)
+  #define LCD_CONTROL_DP           (1<<10)
+  #define LCD_CONTROL_PO_BIT       8
+  #define LCD_CONTROL_PO_MASK      (0x3 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_00        (0 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_01        (1 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_10        (2 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_11        (3 << LCD_CONTROL_PO_BIT)
+  #define LCD_CONTROL_MPI          (1<<7)
+  #define LCD_CONTROL_PT           (1<<6)
+  #define LCD_CONTROL_PC           (1<<5)
+  #define LCD_CONTROL_BPP_BIT      1
+  #define LCD_CONTROL_BPP_MASK     (0x7 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_1        (0 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_2        (1 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_4        (2 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_8        (3 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_12       (4 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_16       (5 << LCD_CONTROL_BPP_BIT)
+  #define LCD_CONTROL_GO           (1<<0)
+
+#define LCD_INTSTATUS              (AU1100_LCD_BASE + 0x4)
+#define LCD_INTENABLE              (AU1100_LCD_BASE + 0x8)
+  #define LCD_INT_SD               (1<<7)
+  #define LCD_INT_OF               (1<<6)
+  #define LCD_INT_UF               (1<<5)
+  #define LCD_INT_SA               (1<<3)
+  #define LCD_INT_SS               (1<<2)
+  #define LCD_INT_S1               (1<<1)
+  #define LCD_INT_S0               (1<<0)
+
+#define LCD_HORZTIMING             (AU1100_LCD_BASE + 0xC)
+  #define LCD_HORZTIMING_HN2_BIT   24
+  #define LCD_HORZTIMING_HN2_MASK  (0xFF << LCD_HORZTIMING_HN2_BIT)
+  #define LCD_HORZTIMING_HN2_N(N)  ((((N)-1) << LCD_HORZTIMING_HN2_BIT) & LCD_HORZTIMING_HN2_MASK)
+  #define LCD_HORZTIMING_HN1_BIT   16
+  #define LCD_HORZTIMING_HN1_MASK  (0xFF << LCD_HORZTIMING_HN1_BIT)
+  #define LCD_HORZTIMING_HN1_N(N)  ((((N)-1) << LCD_HORZTIMING_HN1_BIT) & LCD_HORZTIMING_HN1_MASK)
+  #define LCD_HORZTIMING_HPW_BIT   10
+  #define LCD_HORZTIMING_HPW_MASK  (0x3F << LCD_HORZTIMING_HPW_BIT)
+  #define LCD_HORZTIMING_HPW_N(N)  ((((N)-1) << LCD_HORZTIMING_HPW_BIT) & LCD_HORZTIMING_HPW_MASK)
+  #define LCD_HORZTIMING_PPL_BIT   0
+  #define LCD_HORZTIMING_PPL_MASK  (0x3FF << LCD_HORZTIMING_PPL_BIT)
+  #define LCD_HORZTIMING_PPL_N(N)  ((((N)-1) << LCD_HORZTIMING_PPL_BIT) & LCD_HORZTIMING_PPL_MASK)
+
+#define LCD_VERTTIMING             (AU1100_LCD_BASE + 0x10)
+  #define LCD_VERTTIMING_VN2_BIT   24
+  #define LCD_VERTTIMING_VN2_MASK  (0xFF << LCD_VERTTIMING_VN2_BIT)
+  #define LCD_VERTTIMING_VN2_N(N)  ((((N)-1) << LCD_VERTTIMING_VN2_BIT) & LCD_VERTTIMING_VN2_MASK)
+  #define LCD_VERTTIMING_VN1_BIT   16
+  #define LCD_VERTTIMING_VN1_MASK  (0xFF << LCD_VERTTIMING_VN1_BIT)
+  #define LCD_VERTTIMING_VN1_N(N)  ((((N)-1) << LCD_VERTTIMING_VN1_BIT) & LCD_VERTTIMING_VN1_MASK)
+  #define LCD_VERTTIMING_VPW_BIT   10
+  #define LCD_VERTTIMING_VPW_MASK  (0x3F << LCD_VERTTIMING_VPW_BIT)
+  #define LCD_VERTTIMING_VPW_N(N)  ((((N)-1) << LCD_VERTTIMING_VPW_BIT) & LCD_VERTTIMING_VPW_MASK)
+  #define LCD_VERTTIMING_LPP_BIT   0
+  #define LCD_VERTTIMING_LPP_MASK  (0x3FF << LCD_VERTTIMING_LPP_BIT)
+  #define LCD_VERTTIMING_LPP_N(N)  ((((N)-1) << LCD_VERTTIMING_LPP_BIT) & LCD_VERTTIMING_LPP_MASK)
+
+#define LCD_CLKCONTROL             (AU1100_LCD_BASE + 0x14)
+  #define LCD_CLKCONTROL_IB        (1<<18)
+  #define LCD_CLKCONTROL_IC        (1<<17)
+  #define LCD_CLKCONTROL_IH        (1<<16)
+  #define LCD_CLKCONTROL_IV        (1<<15)
+  #define LCD_CLKCONTROL_BF_BIT    10
+  #define LCD_CLKCONTROL_BF_MASK   (0x1F << LCD_CLKCONTROL_BF_BIT)
+  #define LCD_CLKCONTROL_BF_N(N)   ((((N)-1) << LCD_CLKCONTROL_BF_BIT) & LCD_CLKCONTROL_BF_MASK)
+  #define LCD_CLKCONTROL_PCD_BIT   0
+  #define LCD_CLKCONTROL_PCD_MASK  (0x3FF << LCD_CLKCONTROL_PCD_BIT)
+  #define LCD_CLKCONTROL_PCD_N(N)  (((N) << LCD_CLKCONTROL_PCD_BIT) & LCD_CLKCONTROL_PCD_MASK)
+
+#define LCD_DMAADDR0               (AU1100_LCD_BASE + 0x18)
+#define LCD_DMAADDR1               (AU1100_LCD_BASE + 0x1C)
+  #define LCD_DMA_SA_BIT           5
+  #define LCD_DMA_SA_MASK          (0x7FFFFFF << LCD_DMA_SA_BIT)
+  #define LCD_DMA_SA_N(N)          ((N) & LCD_DMA_SA_MASK)
+
+#define LCD_WORDS                  (AU1100_LCD_BASE + 0x20)
+  #define LCD_WRD_WRDS_BIT         0
+  #define LCD_WRD_WRDS_MASK        (0xFFFFFFFF << LCD_WRD_WRDS_BIT)
+  #define LCD_WRD_WRDS_N(N)        ((((N)-1) << LCD_WRD_WRDS_BIT) & LCD_WRD_WRDS_MASK)
+
+#define LCD_PWMDIV                 (AU1100_LCD_BASE + 0x24)
+  #define LCD_PWMDIV_EN            (1<<12)
+  #define LCD_PWMDIV_PWMDIV_BIT    0
+  #define LCD_PWMDIV_PWMDIV_MASK   (0xFFF << LCD_PWMDIV_PWMDIV_BIT)
+  #define LCD_PWMDIV_PWMDIV_N(N)   ((((N)-1) << LCD_PWMDIV_PWMDIV_BIT) & LCD_PWMDIV_PWMDIV_MASK)
+
+#define LCD_PWMHI                  (AU1100_LCD_BASE + 0x28)
+  #define LCD_PWMHI_PWMHI1_BIT     12
+  #define LCD_PWMHI_PWMHI1_MASK    (0xFFF << LCD_PWMHI_PWMHI1_BIT)
+  #define LCD_PWMHI_PWMHI1_N(N)    (((N) << LCD_PWMHI_PWMHI1_BIT) & LCD_PWMHI_PWMHI1_MASK)
+  #define LCD_PWMHI_PWMHI0_BIT     0
+  #define LCD_PWMHI_PWMHI0_MASK    (0xFFF << LCD_PWMHI_PWMHI0_BIT)
+  #define LCD_PWMHI_PWMHI0_N(N)    (((N) << LCD_PWMHI_PWMHI0_BIT) & LCD_PWMHI_PWMHI0_MASK)
+
+#define LCD_PALLETTEBASE                (AU1100_LCD_BASE + 0x400)
+  #define LCD_PALLETTE_MONO_MI_BIT      0
+  #define LCD_PALLETTE_MONO_MI_MASK     (0xF << LCD_PALLETTE_MONO_MI_BIT)
+  #define LCD_PALLETTE_MONO_MI_N(N)     (((N)<< LCD_PALLETTE_MONO_MI_BIT) & LCD_PALLETTE_MONO_MI_MASK)
+
+  #define LCD_PALLETTE_COLOR_RI_BIT     8
+  #define LCD_PALLETTE_COLOR_RI_MASK    (0xF << LCD_PALLETTE_COLOR_RI_BIT)
+  #define LCD_PALLETTE_COLOR_RI_N(N)    (((N)<< LCD_PALLETTE_COLOR_RI_BIT) & LCD_PALLETTE_COLOR_RI_MASK)
+  #define LCD_PALLETTE_COLOR_GI_BIT     4
+  #define LCD_PALLETTE_COLOR_GI_MASK    (0xF << LCD_PALLETTE_COLOR_GI_BIT)
+  #define LCD_PALLETTE_COLOR_GI_N(N)    (((N)<< LCD_PALLETTE_COLOR_GI_BIT) & LCD_PALLETTE_COLOR_GI_MASK)
+  #define LCD_PALLETTE_COLOR_BI_BIT     0
+  #define LCD_PALLETTE_COLOR_BI_MASK    (0xF << LCD_PALLETTE_COLOR_BI_BIT)
+  #define LCD_PALLETTE_COLOR_BI_N(N)    (((N)<< LCD_PALLETTE_COLOR_BI_BIT) & LCD_PALLETTE_COLOR_BI_MASK)
+
+  #define LCD_PALLETTE_TFT_DC_BIT       0
+  #define LCD_PALLETTE_TFT_DC_MASK      (0xFFFF << LCD_PALLETTE_TFT_DC_BIT)
+  #define LCD_PALLETTE_TFT_DC_N(N)      (((N)<< LCD_PALLETTE_TFT_DC_BIT) & LCD_PALLETTE_TFT_DC_MASK)
+
+/********************************************************************/
+
+/* List of panels known to work with the AU1100 LCD controller.
+ * To add a new panel, enter the same specifications as the
+ * Generic_TFT one, and MAKE SURE that it doesn't conflicts
+ * with the controller restrictions. Restrictions are:
+ *
+ * STN color panels: max_bpp <= 12
+ * STN mono panels: max_bpp <= 4
+ * TFT panels: max_bpp <= 16
+ * max_xres <= 800
+ * max_yres <= 600
+ */
+static struct au1100fb_panel known_lcd_panels[] =
+{
+	/* 800x600x16bpp CRT */
+	[0] = {
+		.name = "CRT_800x600_16",
+		.xres = 800,
+		.yres = 600,
+		.bpp = 16,
+		.control_base =	0x0004886A |
+			LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF |
+			LCD_CONTROL_BPP_16 | LCD_CONTROL_SBB_4,
+		.clkcontrol_base = 0x00020000,
+		.horztiming = 0x005aff1f,
+		.verttiming = 0x16000e57,
+	},
+	/* just the standard LCD */
+	[1] = {
+		.name = "WWPC LCD",
+		.xres = 240,
+		.yres = 320,
+		.bpp = 16,
+		.control_base = 0x0006806A,
+		.horztiming = 0x0A1010EF,
+		.verttiming = 0x0301013F,
+		.clkcontrol_base = 0x00018001,
+	},
+	/* Sharp 320x240 TFT panel */
+	[2] = {
+		.name = "Sharp_LQ038Q5DR01",
+		.xres = 320,
+		.yres = 240,
+		.bpp = 16,
+		.control_base =
+		( LCD_CONTROL_SBPPF_565
+		| LCD_CONTROL_C
+		| LCD_CONTROL_SM_0
+			| LCD_CONTROL_DEFAULT_PO
+		| LCD_CONTROL_PT
+		| LCD_CONTROL_PC
+		| LCD_CONTROL_BPP_16 ),
+		.horztiming =
+		( LCD_HORZTIMING_HN2_N(8)
+		| LCD_HORZTIMING_HN1_N(60)
+		| LCD_HORZTIMING_HPW_N(12)
+		| LCD_HORZTIMING_PPL_N(320) ),
+		.verttiming =
+		( LCD_VERTTIMING_VN2_N(5)
+		| LCD_VERTTIMING_VN1_N(17)
+		| LCD_VERTTIMING_VPW_N(1)
+		| LCD_VERTTIMING_LPP_N(240) ),
+		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
+	},
+
+	/* Hitachi SP14Q005 and possibly others */
+	[3] = {
+		.name = "Hitachi_SP14Qxxx",
+		.xres = 320,
+		.yres = 240,
+		.bpp = 4,
+		.control_base =
+			( LCD_CONTROL_C
+			| LCD_CONTROL_BPP_4 ),
+		.horztiming =
+			( LCD_HORZTIMING_HN2_N(1)
+			| LCD_HORZTIMING_HN1_N(1)
+			| LCD_HORZTIMING_HPW_N(1)
+			| LCD_HORZTIMING_PPL_N(320) ),
+		.verttiming =
+			( LCD_VERTTIMING_VN2_N(1)
+			| LCD_VERTTIMING_VN1_N(1)
+			| LCD_VERTTIMING_VPW_N(1)
+			| LCD_VERTTIMING_LPP_N(240) ),
+		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(4),
+	},
+
+	/* Generic 640x480 TFT panel */
+	[4] = {
+		.name = "TFT_640x480_16",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.control_base = 0x004806a | LCD_CONTROL_DEFAULT_PO,
+		.horztiming = 0x3434d67f,
+		.verttiming = 0x0e0e39df,
+		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
+	},
+
+	 /* Pb1100 LCDB 640x480 PrimeView TFT panel */
+	[5] = {
+		.name = "PrimeView_640x480_16",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.control_base = 0x0004886a | LCD_CONTROL_DEFAULT_PO,
+		.horztiming = 0x0e4bfe7f,
+		.verttiming = 0x210805df,
+		.clkcontrol_base = 0x00038001,
+	},
+};
+
+/********************************************************************/
+
+/* Inline helpers */
+
+#define panel_is_dual(panel)  (panel->control_base & LCD_CONTROL_DP)
+#define panel_is_active(panel)(panel->control_base & LCD_CONTROL_PT)
+#define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC)
+#define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO)
+
+#endif /* _AU1100LCD_H */
diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c
new file mode 100644
index 000000000000..4cfba78a1458
--- /dev/null
+++ b/drivers/video/fbdev/au1200fb.c
@@ -0,0 +1,1859 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1200 LCD Driver.
+ *
+ * Copyright 2004-2005 AMD
+ * Author: AMD
+ *
+ * Based on:
+ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
+ *  Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1200fb.h>	/* platform_data */
+#include "au1200fb.h"
+
+#define DRIVER_NAME "au1200fb"
+#define DRIVER_DESC "LCD controller driver for AU1200 processors"
+
+#define DEBUG 0
+
+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
+
+#if DEBUG
+#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)
+#else
+#define print_dbg(f, arg...) do {} while (0)
+#endif
+
+
+#define AU1200_LCD_FB_IOCTL 0x46FF
+
+#define AU1200_LCD_SET_SCREEN 1
+#define AU1200_LCD_GET_SCREEN 2
+#define AU1200_LCD_SET_WINDOW 3
+#define AU1200_LCD_GET_WINDOW 4
+#define AU1200_LCD_SET_PANEL  5
+#define AU1200_LCD_GET_PANEL  6
+
+#define SCREEN_SIZE		    (1<< 1)
+#define SCREEN_BACKCOLOR    (1<< 2)
+#define SCREEN_BRIGHTNESS   (1<< 3)
+#define SCREEN_COLORKEY     (1<< 4)
+#define SCREEN_MASK         (1<< 5)
+
+struct au1200_lcd_global_regs_t {
+	unsigned int flags;
+	unsigned int xsize;
+	unsigned int ysize;
+	unsigned int backcolor;
+	unsigned int brightness;
+	unsigned int colorkey;
+	unsigned int mask;
+	unsigned int panel_choice;
+	char panel_desc[80];
+
+};
+
+#define WIN_POSITION            (1<< 0)
+#define WIN_ALPHA_COLOR         (1<< 1)
+#define WIN_ALPHA_MODE          (1<< 2)
+#define WIN_PRIORITY            (1<< 3)
+#define WIN_CHANNEL             (1<< 4)
+#define WIN_BUFFER_FORMAT       (1<< 5)
+#define WIN_COLOR_ORDER         (1<< 6)
+#define WIN_PIXEL_ORDER         (1<< 7)
+#define WIN_SIZE                (1<< 8)
+#define WIN_COLORKEY_MODE       (1<< 9)
+#define WIN_DOUBLE_BUFFER_MODE  (1<< 10)
+#define WIN_RAM_ARRAY_MODE      (1<< 11)
+#define WIN_BUFFER_SCALE        (1<< 12)
+#define WIN_ENABLE	            (1<< 13)
+
+struct au1200_lcd_window_regs_t {
+	unsigned int flags;
+	unsigned int xpos;
+	unsigned int ypos;
+	unsigned int alpha_color;
+	unsigned int alpha_mode;
+	unsigned int priority;
+	unsigned int channel;
+	unsigned int buffer_format;
+	unsigned int color_order;
+	unsigned int pixel_order;
+	unsigned int xsize;
+	unsigned int ysize;
+	unsigned int colorkey_mode;
+	unsigned int double_buffer_mode;
+	unsigned int ram_array_mode;
+	unsigned int xscale;
+	unsigned int yscale;
+	unsigned int enable;
+};
+
+
+struct au1200_lcd_iodata_t {
+	unsigned int subcmd;
+	struct au1200_lcd_global_regs_t global;
+	struct au1200_lcd_window_regs_t window;
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
+#else
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
+#endif
+#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
+
+/* Private, per-framebuffer management information (independent of the panel itself) */
+struct au1200fb_device {
+	struct fb_info *fb_info;		/* FB driver info record */
+	struct au1200fb_platdata *pd;
+
+	int					plane;
+	unsigned char* 		fb_mem;		/* FrameBuffer memory map */
+	unsigned int		fb_len;
+	dma_addr_t    		fb_phys;
+};
+
+/********************************************************************/
+
+/* LCD controller restrictions */
+#define AU1200_LCD_MAX_XRES	1280
+#define AU1200_LCD_MAX_YRES	1024
+#define AU1200_LCD_MAX_BPP	32
+#define AU1200_LCD_MAX_CLK	96000000 /* fixme: this needs to go away ? */
+#define AU1200_LCD_NBR_PALETTE_ENTRIES 256
+
+/* Default number of visible screen buffer to allocate */
+#define AU1200FB_NBR_VIDEO_BUFFERS 1
+
+/* Default maximum number of fb devices to create */
+#define MAX_DEVICE_COUNT	4
+
+/* Default window configuration entry to use (see windows[]) */
+#define DEFAULT_WINDOW_INDEX	2
+
+/********************************************************************/
+
+static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT];
+static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
+static int device_count = MAX_DEVICE_COUNT;
+static int window_index = DEFAULT_WINDOW_INDEX;	/* default is zero */
+static int panel_index = 2; /* default is zero */
+static struct window_settings *win;
+static struct panel_settings *panel;
+static int noblanking = 1;
+static int nohwcursor = 0;
+
+struct window_settings {
+	unsigned char name[64];
+	uint32 mode_backcolor;
+	uint32 mode_colorkey;
+	uint32 mode_colorkeymsk;
+	struct {
+		int xres;
+		int yres;
+		int xpos;
+		int ypos;
+		uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
+		uint32 mode_winenable;
+	} w[4];
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
+#else
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
+#endif
+
+/*
+ * Default window configurations
+ */
+static struct window_settings windows[] = {
+	{ /* Index 0 */
+		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+		/* mode_backcolor	*/ 0x006600ff,
+		/* mode_colorkey,msk*/ 0, 0,
+		{
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP,
+			/* mode_winenable*/ LCD_WINENABLE_WEN0,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 100, 100, 100, 100,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP |
+				LCD_WINCTRL1_PIPE,
+			/* mode_winenable*/ LCD_WINENABLE_WEN1,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP,
+			/* mode_winenable*/ 0,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP |
+				LCD_WINCTRL1_PIPE,
+			/* mode_winenable*/ 0,
+			},
+		},
+	},
+
+	{ /* Index 1 */
+		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+		/* mode_backcolor	*/ 0x006600ff,
+		/* mode_colorkey,msk*/ 0, 0,
+		{
+			{
+			/* xres, yres, xpos, ypos */ 320, 240, 5, 5,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |
+				LCD_WINCTRL1_PO_00,
+			/* mode_winenable*/ LCD_WINENABLE_WEN0,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565
+				| LCD_WINCTRL1_PO_16BPP,
+			/* mode_winenable*/ 0,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 100, 100, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP |
+				LCD_WINCTRL1_PIPE,
+			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 200, 25, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP |
+				LCD_WINCTRL1_PIPE,
+			/* mode_winenable*/ 0,
+			},
+		},
+	},
+	{ /* Index 2 */
+		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+		/* mode_backcolor	*/ 0x006600ff,
+		/* mode_colorkey,msk*/ 0, 0,
+		{
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP,
+			/* mode_winenable*/ LCD_WINENABLE_WEN0,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP,
+			/* mode_winenable*/ 0,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |
+				LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,
+			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+			},
+			{
+			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+				LCD_WINCTRL1_PO_16BPP |
+				LCD_WINCTRL1_PIPE,
+			/* mode_winenable*/ 0,
+			},
+		},
+	},
+	/* Need VGA 640 @ 24bpp, @ 32bpp */
+	/* Need VGA 800 @ 24bpp, @ 32bpp */
+	/* Need VGA 1024 @ 24bpp, @ 32bpp */
+};
+
+/*
+ * Controller configurations for various panels.
+ */
+
+struct panel_settings
+{
+	const char name[25];		/* Full name <vendor>_<model> */
+
+	struct 	fb_monspecs monspecs; 	/* FB monitor specs */
+
+	/* panel timings */
+	uint32 mode_screen;
+	uint32 mode_horztiming;
+	uint32 mode_verttiming;
+	uint32 mode_clkcontrol;
+	uint32 mode_pwmdiv;
+	uint32 mode_pwmhi;
+	uint32 mode_outmask;
+	uint32 mode_fifoctrl;
+	uint32 mode_toyclksrc;
+	uint32 mode_backlight;
+	uint32 mode_auxpll;
+#define Xres min_xres
+#define Yres min_yres
+	u32	min_xres;		/* Minimum horizontal resolution */
+	u32	max_xres;		/* Maximum horizontal resolution */
+	u32 	min_yres;		/* Minimum vertical resolution */
+	u32 	max_yres;		/* Maximum vertical resolution */
+};
+
+/********************************************************************/
+/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */
+
+/* List of panels known to work with the AU1200 LCD controller.
+ * To add a new panel, enter the same specifications as the
+ * Generic_TFT one, and MAKE SURE that it doesn't conflicts
+ * with the controller restrictions. Restrictions are:
+ *
+ * STN color panels: max_bpp <= 12
+ * STN mono panels: max_bpp <= 4
+ * TFT panels: max_bpp <= 16
+ * max_xres <= 800
+ * max_yres <= 600
+ */
+static struct panel_settings known_lcd_panels[] =
+{
+	[0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */
+		.name = "QVGA_320x240",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= LCD_SCREEN_SX_N(320) |
+			LCD_SCREEN_SY_N(240),
+		.mode_horztiming	= 0x00c4623b,
+		.mode_verttiming	= 0x00502814,
+		.mode_clkcontrol	= 0x00020002, /* /4=24Mhz */
+		.mode_pwmdiv		= 0x00000000,
+		.mode_pwmhi		= 0x00000000,
+		.mode_outmask	= 0x00FFFFFF,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		320, 320,
+		240, 240,
+	},
+
+	[1] = { /* VGA 640x480 H:30.3kHz V:58Hz */
+		.name = "VGA_640x480",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= 0x13f9df80,
+		.mode_horztiming	= 0x003c5859,
+		.mode_verttiming	= 0x00741201,
+		.mode_clkcontrol	= 0x00020001, /* /4=24Mhz */
+		.mode_pwmdiv		= 0x00000000,
+		.mode_pwmhi		= 0x00000000,
+		.mode_outmask	= 0x00FFFFFF,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		640, 480,
+		640, 480,
+	},
+
+	[2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */
+		.name = "SVGA_800x600",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= 0x18fa5780,
+		.mode_horztiming	= 0x00dc7e77,
+		.mode_verttiming	= 0x00584805,
+		.mode_clkcontrol	= 0x00020000, /* /2=48Mhz */
+		.mode_pwmdiv		= 0x00000000,
+		.mode_pwmhi		= 0x00000000,
+		.mode_outmask	= 0x00FFFFFF,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		800, 800,
+		600, 600,
+	},
+
+	[3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */
+		.name = "XVGA_1024x768",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= 0x1ffaff80,
+		.mode_horztiming	= 0x007d0e57,
+		.mode_verttiming	= 0x00740a01,
+		.mode_clkcontrol	= 0x000A0000, /* /1 */
+		.mode_pwmdiv		= 0x00000000,
+		.mode_pwmhi		= 0x00000000,
+		.mode_outmask	= 0x00FFFFFF,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 6, /* 72MHz AUXPLL */
+		1024, 1024,
+		768, 768,
+	},
+
+	[4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */
+		.name = "XVGA_1280x1024",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= 0x27fbff80,
+		.mode_horztiming	= 0x00cdb2c7,
+		.mode_verttiming	= 0x00600002,
+		.mode_clkcontrol	= 0x000A0000, /* /1 */
+		.mode_pwmdiv		= 0x00000000,
+		.mode_pwmhi		= 0x00000000,
+		.mode_outmask	= 0x00FFFFFF,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 10, /* 120MHz AUXPLL */
+		1280, 1280,
+		1024, 1024,
+	},
+
+	[5] = { /* Samsung 1024x768 TFT */
+		.name = "Samsung_1024x768_TFT",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= 0x1ffaff80,
+		.mode_horztiming	= 0x018cc677,
+		.mode_verttiming	= 0x00241217,
+		.mode_clkcontrol	= 0x00000000, /* SCB 0x1 /4=24Mhz */
+		.mode_pwmdiv		= 0x8000063f, /* SCB 0x0 */
+		.mode_pwmhi		= 0x03400000, /* SCB 0x0 */
+		.mode_outmask	= 0x00FFFFFF,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		1024, 1024,
+		768, 768,
+	},
+
+	[6] = { /* Toshiba 640x480 TFT */
+		.name = "Toshiba_640x480_TFT",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= LCD_SCREEN_SX_N(640) |
+			LCD_SCREEN_SY_N(480),
+		.mode_horztiming	= LCD_HORZTIMING_HPW_N(96) |
+			LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
+		.mode_verttiming	= LCD_VERTTIMING_VPW_N(2) |
+			LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32),
+		.mode_clkcontrol	= 0x00000000, /* /4=24Mhz */
+		.mode_pwmdiv		= 0x8000063f,
+		.mode_pwmhi		= 0x03400000,
+		.mode_outmask	= 0x00fcfcfc,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		640, 480,
+		640, 480,
+	},
+
+	[7] = { /* Sharp 320x240 TFT */
+		.name = "Sharp_320x240_TFT",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 12500,
+			.hfmax = 20000,
+			.vfmin = 38,
+			.vfmax = 81,
+			.dclkmin = 4500000,
+			.dclkmax = 6800000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= LCD_SCREEN_SX_N(320) |
+			LCD_SCREEN_SY_N(240),
+		.mode_horztiming	= LCD_HORZTIMING_HPW_N(60) |
+			LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
+		.mode_verttiming	= LCD_VERTTIMING_VPW_N(2) |
+			LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5),
+		.mode_clkcontrol	= LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/
+		.mode_pwmdiv		= 0x8000063f,
+		.mode_pwmhi		= 0x03400000,
+		.mode_outmask	= 0x00fcfcfc,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		320, 320,
+		240, 240,
+	},
+
+	[8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */
+		.name = "Toppoly_TD070WGCB2",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= LCD_SCREEN_SX_N(856) |
+			LCD_SCREEN_SY_N(480),
+		.mode_horztiming	= LCD_HORZTIMING_HND2_N(43) |
+			LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114),
+		.mode_verttiming	= LCD_VERTTIMING_VND2_N(20) |
+			LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
+		.mode_clkcontrol	= 0x00020001, /* /4=24Mhz */
+		.mode_pwmdiv		= 0x8000063f,
+		.mode_pwmhi		= 0x03400000,
+		.mode_outmask	= 0x00fcfcfc,
+		.mode_fifoctrl	= 0x2f2f2f2f,
+		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
+		.mode_backlight	= 0x00000000,
+		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		856, 856,
+		480, 480,
+	},
+	[9] = {
+		.name = "DB1300_800x480",
+		.monspecs = {
+			.modedb = NULL,
+			.modedb_len = 0,
+			.hfmin = 30000,
+			.hfmax = 70000,
+			.vfmin = 60,
+			.vfmax = 60,
+			.dclkmin = 6000000,
+			.dclkmax = 28000000,
+			.input = FB_DISP_RGB,
+		},
+		.mode_screen		= LCD_SCREEN_SX_N(800) |
+					  LCD_SCREEN_SY_N(480),
+		.mode_horztiming	= LCD_HORZTIMING_HPW_N(5) |
+					  LCD_HORZTIMING_HND1_N(16) |
+					  LCD_HORZTIMING_HND2_N(8),
+		.mode_verttiming	= LCD_VERTTIMING_VPW_N(4) |
+					  LCD_VERTTIMING_VND1_N(8) |
+					  LCD_VERTTIMING_VND2_N(5),
+		.mode_clkcontrol	= LCD_CLKCONTROL_PCD_N(1) |
+					  LCD_CLKCONTROL_IV |
+					  LCD_CLKCONTROL_IH,
+		.mode_pwmdiv		= 0x00000000,
+		.mode_pwmhi		= 0x00000000,
+		.mode_outmask		= 0x00FFFFFF,
+		.mode_fifoctrl		= 0x2f2f2f2f,
+		.mode_toyclksrc		= 0x00000004, /* AUXPLL directly */
+		.mode_backlight		= 0x00000000,
+		.mode_auxpll		= (48/12) * 2,
+		800, 800,
+		480, 480,
+	},
+};
+
+#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
+
+/********************************************************************/
+
+static int winbpp (unsigned int winctrl1)
+{
+	int bits = 0;
+
+	/* how many bits are needed for each pixel format */
+	switch (winctrl1 & LCD_WINCTRL1_FRM) {
+	case LCD_WINCTRL1_FRM_1BPP:
+		bits = 1;
+		break;
+	case LCD_WINCTRL1_FRM_2BPP:
+		bits = 2;
+		break;
+	case LCD_WINCTRL1_FRM_4BPP:
+		bits = 4;
+		break;
+	case LCD_WINCTRL1_FRM_8BPP:
+		bits = 8;
+		break;
+	case LCD_WINCTRL1_FRM_12BPP:
+	case LCD_WINCTRL1_FRM_16BPP655:
+	case LCD_WINCTRL1_FRM_16BPP565:
+	case LCD_WINCTRL1_FRM_16BPP556:
+	case LCD_WINCTRL1_FRM_16BPPI1555:
+	case LCD_WINCTRL1_FRM_16BPPI5551:
+	case LCD_WINCTRL1_FRM_16BPPA1555:
+	case LCD_WINCTRL1_FRM_16BPPA5551:
+		bits = 16;
+		break;
+	case LCD_WINCTRL1_FRM_24BPP:
+	case LCD_WINCTRL1_FRM_32BPP:
+		bits = 32;
+		break;
+	}
+
+	return bits;
+}
+
+static int fbinfo2index (struct fb_info *fb_info)
+{
+	int i;
+
+	for (i = 0; i < device_count; ++i) {
+		if (fb_info == _au1200fb_infos[i])
+			return i;
+	}
+	printk("au1200fb: ERROR: fbinfo2index failed!\n");
+	return -1;
+}
+
+static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
+	int xpos, int ypos)
+{
+	uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
+	int xsz, ysz;
+
+	/* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
+
+	winctrl0 = lcd->window[plane].winctrl0;
+	winctrl1 = lcd->window[plane].winctrl1;
+	winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
+	winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
+
+	/* Check for off-screen adjustments */
+	xsz = win->w[plane].xres;
+	ysz = win->w[plane].yres;
+	if ((xpos + win->w[plane].xres) > panel->Xres) {
+		/* Off-screen to the right */
+		xsz = panel->Xres - xpos; /* off by 1 ??? */
+		/*printk("off screen right\n");*/
+	}
+
+	if ((ypos + win->w[plane].yres) > panel->Yres) {
+		/* Off-screen to the bottom */
+		ysz = panel->Yres - ypos; /* off by 1 ??? */
+		/*printk("off screen bottom\n");*/
+	}
+
+	if (xpos < 0) {
+		/* Off-screen to the left */
+		xsz = win->w[plane].xres + xpos;
+		fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
+		xpos = 0;
+		/*printk("off screen left\n");*/
+	}
+
+	if (ypos < 0) {
+		/* Off-screen to the top */
+		ysz = win->w[plane].yres + ypos;
+		/* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */
+		ypos = 0;
+		/*printk("off screen top\n");*/
+	}
+
+	/* record settings */
+	win->w[plane].xpos = xpos;
+	win->w[plane].ypos = ypos;
+
+	xsz -= 1;
+	ysz -= 1;
+	winctrl0 |= (xpos << 21);
+	winctrl0 |= (ypos << 10);
+	winctrl1 |= (xsz << 11);
+	winctrl1 |= (ysz << 0);
+
+	/* Disable the window while making changes, then restore WINEN */
+	winenable = lcd->winenable & (1 << plane);
+	au_sync();
+	lcd->winenable &= ~(1 << plane);
+	lcd->window[plane].winctrl0 = winctrl0;
+	lcd->window[plane].winctrl1 = winctrl1;
+	lcd->window[plane].winbuf0 =
+	lcd->window[plane].winbuf1 = fbdev->fb_phys;
+	lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
+	lcd->winenable |= winenable;
+	au_sync();
+
+	return 0;
+}
+
+static void au1200_setpanel(struct panel_settings *newpanel,
+			    struct au1200fb_platdata *pd)
+{
+	/*
+	 * Perform global setup/init of LCD controller
+	 */
+	uint32 winenable;
+
+	/* Make sure all windows disabled */
+	winenable = lcd->winenable;
+	lcd->winenable = 0;
+	au_sync();
+	/*
+	 * Ensure everything is disabled before reconfiguring
+	 */
+	if (lcd->screen & LCD_SCREEN_SEN) {
+		/* Wait for vertical sync period */
+		lcd->intstatus = LCD_INT_SS;
+		while ((lcd->intstatus & LCD_INT_SS) == 0) {
+			au_sync();
+		}
+
+		lcd->screen &= ~LCD_SCREEN_SEN;	/*disable the controller*/
+
+		do {
+			lcd->intstatus = lcd->intstatus; /*clear interrupts*/
+			au_sync();
+		/*wait for controller to shut down*/
+		} while ((lcd->intstatus & LCD_INT_SD) == 0);
+
+		/* Call shutdown of current panel (if up) */
+		/* this must occur last, because if an external clock is driving
+		    the controller, the clock cannot be turned off before first
+			shutting down the controller.
+		 */
+		if (pd->panel_shutdown)
+			pd->panel_shutdown();
+	}
+
+	/* Newpanel == NULL indicates a shutdown operation only */
+	if (newpanel == NULL)
+		return;
+
+	panel = newpanel;
+
+	printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
+
+	/*
+	 * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
+	 */
+	if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
+	{
+		uint32 sys_clksrc;
+		au_writel(panel->mode_auxpll, SYS_AUXPLL);
+		sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
+		sys_clksrc |= panel->mode_toyclksrc;
+		au_writel(sys_clksrc, SYS_CLKSRC);
+	}
+
+	/*
+	 * Configure panel timings
+	 */
+	lcd->screen = panel->mode_screen;
+	lcd->horztiming = panel->mode_horztiming;
+	lcd->verttiming = panel->mode_verttiming;
+	lcd->clkcontrol = panel->mode_clkcontrol;
+	lcd->pwmdiv = panel->mode_pwmdiv;
+	lcd->pwmhi = panel->mode_pwmhi;
+	lcd->outmask = panel->mode_outmask;
+	lcd->fifoctrl = panel->mode_fifoctrl;
+	au_sync();
+
+	/* fixme: Check window settings to make sure still valid
+	 * for new geometry */
+#if 0
+	au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos);
+	au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos);
+	au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos);
+	au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos);
+#endif
+	lcd->winenable = winenable;
+
+	/*
+	 * Re-enable screen now that it is configured
+	 */
+	lcd->screen |= LCD_SCREEN_SEN;
+	au_sync();
+
+	/* Call init of panel */
+	if (pd->panel_init)
+		pd->panel_init();
+
+	/* FIX!!!! not appropriate on panel change!!! Global setup/init */
+	lcd->intenable = 0;
+	lcd->intstatus = ~0;
+	lcd->backcolor = win->mode_backcolor;
+
+	/* Setup Color Key - FIX!!! */
+	lcd->colorkey = win->mode_colorkey;
+	lcd->colorkeymsk = win->mode_colorkeymsk;
+
+	/* Setup HWCursor - FIX!!! Need to support this eventually */
+	lcd->hwc.cursorctrl = 0;
+	lcd->hwc.cursorpos = 0;
+	lcd->hwc.cursorcolor0 = 0;
+	lcd->hwc.cursorcolor1 = 0;
+	lcd->hwc.cursorcolor2 = 0;
+	lcd->hwc.cursorcolor3 = 0;
+
+
+#if 0
+#define D(X) printk("%25s: %08X\n", #X, X)
+	D(lcd->screen);
+	D(lcd->horztiming);
+	D(lcd->verttiming);
+	D(lcd->clkcontrol);
+	D(lcd->pwmdiv);
+	D(lcd->pwmhi);
+	D(lcd->outmask);
+	D(lcd->fifoctrl);
+	D(lcd->window[0].winctrl0);
+	D(lcd->window[0].winctrl1);
+	D(lcd->window[0].winctrl2);
+	D(lcd->window[0].winbuf0);
+	D(lcd->window[0].winbuf1);
+	D(lcd->window[0].winbufctrl);
+	D(lcd->window[1].winctrl0);
+	D(lcd->window[1].winctrl1);
+	D(lcd->window[1].winctrl2);
+	D(lcd->window[1].winbuf0);
+	D(lcd->window[1].winbuf1);
+	D(lcd->window[1].winbufctrl);
+	D(lcd->window[2].winctrl0);
+	D(lcd->window[2].winctrl1);
+	D(lcd->window[2].winctrl2);
+	D(lcd->window[2].winbuf0);
+	D(lcd->window[2].winbuf1);
+	D(lcd->window[2].winbufctrl);
+	D(lcd->window[3].winctrl0);
+	D(lcd->window[3].winctrl1);
+	D(lcd->window[3].winctrl2);
+	D(lcd->window[3].winbuf0);
+	D(lcd->window[3].winbuf1);
+	D(lcd->window[3].winbufctrl);
+	D(lcd->winenable);
+	D(lcd->intenable);
+	D(lcd->intstatus);
+	D(lcd->backcolor);
+	D(lcd->winenable);
+	D(lcd->colorkey);
+    D(lcd->colorkeymsk);
+	D(lcd->hwc.cursorctrl);
+	D(lcd->hwc.cursorpos);
+	D(lcd->hwc.cursorcolor0);
+	D(lcd->hwc.cursorcolor1);
+	D(lcd->hwc.cursorcolor2);
+	D(lcd->hwc.cursorcolor3);
+#endif
+}
+
+static void au1200_setmode(struct au1200fb_device *fbdev)
+{
+	int plane = fbdev->plane;
+	/* Window/plane setup */
+	lcd->window[plane].winctrl1 = ( 0
+		| LCD_WINCTRL1_PRI_N(plane)
+		| win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
+		) ;
+
+	au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos);
+
+	lcd->window[plane].winctrl2 = ( 0
+		| LCD_WINCTRL2_CKMODE_00
+		| LCD_WINCTRL2_DBM
+		| LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length)
+		| LCD_WINCTRL2_SCX_1
+		| LCD_WINCTRL2_SCY_1
+		) ;
+	lcd->winenable |= win->w[plane].mode_winenable;
+	au_sync();
+}
+
+
+/* Inline helpers */
+
+/*#define panel_is_dual(panel)  ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+
+#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)
+
+/* Bitfields format supported by the controller. */
+static struct fb_bitfield rgb_bitfields[][4] = {
+  	/*     Red, 	   Green, 	 Blue, 	     Transp   */
+	[LCD_WINCTRL1_FRM_16BPP655 >> 25] =
+		{ { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+	[LCD_WINCTRL1_FRM_16BPP565 >> 25] =
+		{ { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+	[LCD_WINCTRL1_FRM_16BPP556 >> 25] =
+		{ { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
+
+	[LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =
+		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+	[LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =
+		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },
+
+	[LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =
+		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
+
+	[LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =
+		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
+
+	[LCD_WINCTRL1_FRM_24BPP >> 25] =
+		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },
+
+	[LCD_WINCTRL1_FRM_32BPP >> 25] =
+		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Helpers */
+
+static void au1200fb_update_fbinfo(struct fb_info *fbi)
+{
+	/* FIX!!!! This also needs to take the window pixel format into account!!! */
+
+	/* Update var-dependent FB info */
+	if (panel_is_color(panel)) {
+		if (fbi->var.bits_per_pixel <= 8) {
+			/* palettized */
+			fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+			fbi->fix.line_length = fbi->var.xres_virtual /
+				(8/fbi->var.bits_per_pixel);
+		} else {
+			/* non-palettized */
+			fbi->fix.visual = FB_VISUAL_TRUECOLOR;
+			fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);
+		}
+	} else {
+		/* mono FIX!!! mono 8 and 4 bits */
+		fbi->fix.visual = FB_VISUAL_MONO10;
+		fbi->fix.line_length = fbi->var.xres_virtual / 8;
+	}
+
+	fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;
+	print_dbg("line length: %d\n", fbi->fix.line_length);
+	print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 framebuffer driver */
+
+/* fb_check_var
+ * Validate var settings with hardware restrictions and modify it if necessary
+ */
+static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
+	struct fb_info *fbi)
+{
+	struct au1200fb_device *fbdev = fbi->par;
+	u32 pixclock;
+	int screen_size, plane;
+
+	plane = fbdev->plane;
+
+	/* Make sure that the mode respect all LCD controller and
+	 * panel restrictions. */
+	var->xres = win->w[plane].xres;
+	var->yres = win->w[plane].yres;
+
+	/* No need for virtual resolution support */
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);
+
+	screen_size = var->xres_virtual * var->yres_virtual;
+	if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);
+	else screen_size /= (8/var->bits_per_pixel);
+
+	if (fbdev->fb_len < screen_size)
+		return -EINVAL; /* Virtual screen is to big, abort */
+
+	/* FIX!!!! what are the implicaitons of ignoring this for windows ??? */
+	/* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel
+	 * clock can only be obtain by dividing this value by an even integer.
+	 * Fallback to a slower pixel clock if necessary. */
+	pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
+	pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2);
+
+	if (AU1200_LCD_MAX_CLK % pixclock) {
+		int diff = AU1200_LCD_MAX_CLK % pixclock;
+		pixclock -= diff;
+	}
+
+	var->pixclock = KHZ2PICOS(pixclock/1000);
+#if 0
+	if (!panel_is_active(panel)) {
+		int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;
+
+		if (!panel_is_color(panel)
+			&& (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {
+			/* STN 8bit mono panel support is up to 6MHz pixclock */
+			var->pixclock = KHZ2PICOS(6000);
+		} else if (!pcd) {
+			/* Other STN panel support is up to 12MHz  */
+			var->pixclock = KHZ2PICOS(12000);
+		}
+	}
+#endif
+	/* Set bitfield accordingly */
+	switch (var->bits_per_pixel) {
+		case 16:
+		{
+			/* 16bpp True color.
+			 * These must be set to MATCH WINCTRL[FORM] */
+			int idx;
+			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+			var->red    = rgb_bitfields[idx][0];
+			var->green  = rgb_bitfields[idx][1];
+			var->blue   = rgb_bitfields[idx][2];
+			var->transp = rgb_bitfields[idx][3];
+			break;
+		}
+
+		case 32:
+		{
+			/* 32bpp True color.
+			 * These must be set to MATCH WINCTRL[FORM] */
+			int idx;
+			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+			var->red    = rgb_bitfields[idx][0];
+			var->green  = rgb_bitfields[idx][1];
+			var->blue   = rgb_bitfields[idx][2];
+			var->transp = rgb_bitfields[idx][3];
+			break;
+		}
+		default:
+			print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* fb_set_par
+ * Set hardware with var settings. This will enable the controller with a
+ * specific mode, normally validated with the fb_check_var method
+ */
+static int au1200fb_fb_set_par(struct fb_info *fbi)
+{
+	struct au1200fb_device *fbdev = fbi->par;
+
+	au1200fb_update_fbinfo(fbi);
+	au1200_setmode(fbdev);
+
+	return 0;
+}
+
+/* fb_setcolreg
+ * Set color in LCD palette.
+ */
+static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+	unsigned blue, unsigned transp, struct fb_info *fbi)
+{
+	volatile u32 *palette = lcd->palette;
+	u32 value;
+
+	if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))
+		return -EINVAL;
+
+	if (fbi->var.grayscale) {
+		/* Convert color to grayscale */
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+	}
+
+	if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		palette = (u32*) fbi->pseudo_palette;
+
+		red   >>= (16 - fbi->var.red.length);
+		green >>= (16 - fbi->var.green.length);
+		blue  >>= (16 - fbi->var.blue.length);
+
+		value = (red   << fbi->var.red.offset) 	|
+			(green << fbi->var.green.offset)|
+			(blue  << fbi->var.blue.offset);
+		value &= 0xFFFF;
+
+	} else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {
+		/* COLOR TFT PALLETTIZED (use RGB 565) */
+		value = (red & 0xF800)|((green >> 5) &
+				0x07E0)|((blue >> 11) & 0x001F);
+		value &= 0xFFFF;
+
+	} else if (0 /*panel_is_color(fbdev->panel)*/) {
+		/* COLOR STN MODE */
+		value = 0x1234;
+		value &= 0xFFF;
+	} else {
+		/* MONOCHROME MODE */
+		value = (green >> 12) & 0x000F;
+		value &= 0xF;
+	}
+
+	palette[regno] = value;
+
+	return 0;
+}
+
+/* fb_blank
+ * Blank the screen. Depending on the mode, the screen will be
+ * activated with the backlight color, or desactivated
+ */
+static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
+{
+	struct au1200fb_device *fbdev = fbi->par;
+
+	/* Short-circuit screen blanking */
+	if (noblanking)
+		return 0;
+
+	switch (blank_mode) {
+
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		/* printk("turn on panel\n"); */
+		au1200_setpanel(panel, fbdev->pd);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		/* printk("turn off panel\n"); */
+		au1200_setpanel(NULL, fbdev->pd);
+		break;
+	default:
+		break;
+
+	}
+
+	/* FB_BLANK_NORMAL is a soft blank */
+	return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;
+}
+
+/* fb_mmap
+ * Map video memory in user space. We don't use the generic fb_mmap
+ * method mainly to allow the use of the TLB streaming flag (CCA=6)
+ */
+static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct au1200fb_device *fbdev = info->par;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
+
+	return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len);
+}
+
+static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+
+	unsigned int hi1, divider;
+
+	/* SCREEN_SIZE: user cannot reset size, must switch panel choice */
+
+	if (pdata->flags & SCREEN_BACKCOLOR)
+		lcd->backcolor = pdata->backcolor;
+
+	if (pdata->flags & SCREEN_BRIGHTNESS) {
+
+		// limit brightness pwm duty to >= 30/1600
+		if (pdata->brightness < 30) {
+			pdata->brightness = 30;
+		}
+		divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+		hi1 = (lcd->pwmhi >> 16) + 1;
+		hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);
+		lcd->pwmhi &= 0xFFFF;
+		lcd->pwmhi |= (hi1 << 16);
+	}
+
+	if (pdata->flags & SCREEN_COLORKEY)
+		lcd->colorkey = pdata->colorkey;
+
+	if (pdata->flags & SCREEN_MASK)
+		lcd->colorkeymsk = pdata->mask;
+	au_sync();
+}
+
+static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+	unsigned int hi1, divider;
+
+	pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;
+	pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;
+
+	pdata->backcolor = lcd->backcolor;
+	pdata->colorkey = lcd->colorkey;
+	pdata->mask = lcd->colorkeymsk;
+
+	// brightness
+	hi1 = (lcd->pwmhi >> 16) + 1;
+	divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+	pdata->brightness = ((hi1 << 8) / divider) - 1;
+	au_sync();
+}
+
+static void set_window(unsigned int plane,
+	struct au1200_lcd_window_regs_t *pdata)
+{
+	unsigned int val, bpp;
+
+	/* Window control register 0 */
+	if (pdata->flags & WIN_POSITION) {
+		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |
+				LCD_WINCTRL0_OY);
+		val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);
+		val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);
+		lcd->window[plane].winctrl0 = val;
+	}
+	if (pdata->flags & WIN_ALPHA_COLOR) {
+		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);
+		val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);
+		lcd->window[plane].winctrl0 = val;
+	}
+	if (pdata->flags & WIN_ALPHA_MODE) {
+		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);
+		val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);
+		lcd->window[plane].winctrl0 = val;
+	}
+
+	/* Window control register 1 */
+	if (pdata->flags & WIN_PRIORITY) {
+		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);
+		val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);
+		lcd->window[plane].winctrl1 = val;
+	}
+	if (pdata->flags & WIN_CHANNEL) {
+		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);
+		val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);
+		lcd->window[plane].winctrl1 = val;
+	}
+	if (pdata->flags & WIN_BUFFER_FORMAT) {
+		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);
+		val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);
+		lcd->window[plane].winctrl1 = val;
+	}
+	if (pdata->flags & WIN_COLOR_ORDER) {
+		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);
+		val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);
+		lcd->window[plane].winctrl1 = val;
+	}
+	if (pdata->flags & WIN_PIXEL_ORDER) {
+		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);
+		val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);
+		lcd->window[plane].winctrl1 = val;
+	}
+	if (pdata->flags & WIN_SIZE) {
+		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |
+				LCD_WINCTRL1_SZY);
+		val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);
+		val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);
+		lcd->window[plane].winctrl1 = val;
+		/* program buffer line width */
+		bpp = winbpp(val) / 8;
+		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);
+		val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);
+		lcd->window[plane].winctrl2 = val;
+	}
+
+	/* Window control register 2 */
+	if (pdata->flags & WIN_COLORKEY_MODE) {
+		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);
+		val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);
+		lcd->window[plane].winctrl2 = val;
+	}
+	if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {
+		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);
+		val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);
+		lcd->window[plane].winctrl2 = val;
+	}
+	if (pdata->flags & WIN_RAM_ARRAY_MODE) {
+		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);
+		val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);
+		lcd->window[plane].winctrl2 = val;
+	}
+
+	/* Buffer line width programmed with WIN_SIZE */
+
+	if (pdata->flags & WIN_BUFFER_SCALE) {
+		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |
+				LCD_WINCTRL2_SCY);
+		val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);
+		val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);
+		lcd->window[plane].winctrl2 = val;
+	}
+
+	if (pdata->flags & WIN_ENABLE) {
+		val = lcd->winenable;
+		val &= ~(1<<plane);
+		val |= (pdata->enable & 1) << plane;
+		lcd->winenable = val;
+	}
+	au_sync();
+}
+
+static void get_window(unsigned int plane,
+	struct au1200_lcd_window_regs_t *pdata)
+{
+	/* Window control register 0 */
+	pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
+	pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
+	pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;
+	pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;
+
+	/* Window control register 1 */
+	pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;
+	pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;
+	pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+	pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;
+	pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;
+	pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1;
+	pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1;
+
+	/* Window control register 2 */
+	pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;
+	pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;
+	pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
+
+	pdata->enable = (lcd->winenable >> plane) & 1;
+	au_sync();
+}
+
+static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
+                          unsigned long arg)
+{
+	struct au1200fb_device *fbdev = info->par;
+	int plane;
+	int val;
+
+	plane = fbinfo2index(info);
+	print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
+
+	if (cmd == AU1200_LCD_FB_IOCTL) {
+		struct au1200_lcd_iodata_t iodata;
+
+		if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata)))
+			return -EFAULT;
+
+		print_dbg("FB IOCTL called\n");
+
+		switch (iodata.subcmd) {
+		case AU1200_LCD_SET_SCREEN:
+			print_dbg("AU1200_LCD_SET_SCREEN\n");
+			set_global(cmd, &iodata.global);
+			break;
+
+		case AU1200_LCD_GET_SCREEN:
+			print_dbg("AU1200_LCD_GET_SCREEN\n");
+			get_global(cmd, &iodata.global);
+			break;
+
+		case AU1200_LCD_SET_WINDOW:
+			print_dbg("AU1200_LCD_SET_WINDOW\n");
+			set_window(plane, &iodata.window);
+			break;
+
+		case AU1200_LCD_GET_WINDOW:
+			print_dbg("AU1200_LCD_GET_WINDOW\n");
+			get_window(plane, &iodata.window);
+			break;
+
+		case AU1200_LCD_SET_PANEL:
+			print_dbg("AU1200_LCD_SET_PANEL\n");
+			if ((iodata.global.panel_choice >= 0) &&
+					(iodata.global.panel_choice <
+					 NUM_PANELS))
+			{
+				struct panel_settings *newpanel;
+				panel_index = iodata.global.panel_choice;
+				newpanel = &known_lcd_panels[panel_index];
+				au1200_setpanel(newpanel, fbdev->pd);
+			}
+			break;
+
+		case AU1200_LCD_GET_PANEL:
+			print_dbg("AU1200_LCD_GET_PANEL\n");
+			iodata.global.panel_choice = panel_index;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata));
+		if (val) {
+			print_dbg("error: could not copy %d bytes\n", val);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+
+static struct fb_ops au1200fb_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= au1200fb_fb_check_var,
+	.fb_set_par	= au1200fb_fb_set_par,
+	.fb_setcolreg	= au1200fb_fb_setcolreg,
+	.fb_blank	= au1200fb_fb_blank,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_read	= fb_sys_read,
+	.fb_write	= fb_sys_write,
+	.fb_sync	= NULL,
+	.fb_ioctl	= au1200fb_ioctl,
+	.fb_mmap	= au1200fb_fb_mmap,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
+{
+	/* Nothing to do for now, just clear any pending interrupt */
+	lcd->intstatus = lcd->intstatus;
+	au_sync();
+
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 LCD device probe helpers */
+
+static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
+{
+	struct fb_info *fbi = fbdev->fb_info;
+	int bpp;
+
+	fbi->fbops = &au1200fb_fb_ops;
+
+	bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
+
+	/* Copy monitor specs from panel data */
+	/* fixme: we're setting up LCD controller windows, so these dont give a
+	damn as to what the monitor specs are (the panel itself does, but that
+	isn't done here...so maybe need a generic catchall monitor setting??? */
+	memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
+
+	/* We first try the user mode passed in argument. If that failed,
+	 * or if no one has been specified, we default to the first mode of the
+	 * panel list. Note that after this call, var data will be set */
+	if (!fb_find_mode(&fbi->var,
+			  fbi,
+			  NULL, /* drv_info.opt_mode, */
+			  fbi->monspecs.modedb,
+			  fbi->monspecs.modedb_len,
+			  fbi->monspecs.modedb,
+			  bpp)) {
+
+		print_err("Cannot find valid mode for panel %s", panel->name);
+		return -EFAULT;
+	}
+
+	fbi->pseudo_palette = kcalloc(16, sizeof(u32), GFP_KERNEL);
+	if (!fbi->pseudo_palette) {
+		return -ENOMEM;
+	}
+
+	if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+		print_err("Fail to allocate colormap (%d entries)",
+			   AU1200_LCD_NBR_PALETTE_ENTRIES);
+		kfree(fbi->pseudo_palette);
+		return -EFAULT;
+	}
+
+	strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
+	fbi->fix.smem_start = fbdev->fb_phys;
+	fbi->fix.smem_len = fbdev->fb_len;
+	fbi->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbi->fix.xpanstep = 0;
+	fbi->fix.ypanstep = 0;
+	fbi->fix.mmio_start = 0;
+	fbi->fix.mmio_len = 0;
+	fbi->fix.accel = FB_ACCEL_NONE;
+
+	fbi->screen_base = (char __iomem *) fbdev->fb_mem;
+
+	au1200fb_update_fbinfo(fbi);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+static int au1200fb_setup(struct au1200fb_platdata *pd)
+{
+	char *options = NULL;
+	char *this_opt, *endptr;
+	int num_panels = ARRAY_SIZE(known_lcd_panels);
+	int panel_idx = -1;
+
+	fb_get_options(DRIVER_NAME, &options);
+
+	if (!options)
+		goto out;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		/* Panel option - can be panel name,
+		 * "bs" for board-switch, or number/index */
+		if (!strncmp(this_opt, "panel:", 6)) {
+			int i;
+			long int li;
+			char *endptr;
+			this_opt += 6;
+			/* First check for index, which allows
+			 * to short circuit this mess */
+			li = simple_strtol(this_opt, &endptr, 0);
+			if (*endptr == '\0')
+				panel_idx = (int)li;
+			else if (strcmp(this_opt, "bs") == 0)
+				panel_idx = pd->panel_index();
+			else {
+				for (i = 0; i < num_panels; i++) {
+					if (!strcmp(this_opt,
+						    known_lcd_panels[i].name)) {
+						panel_idx = i;
+						break;
+					}
+				}
+			}
+			if ((panel_idx < 0) || (panel_idx >= num_panels))
+				print_warn("Panel %s not supported!", this_opt);
+			else
+				panel_index = panel_idx;
+
+		} else if (strncmp(this_opt, "nohwcursor", 10) == 0)
+			nohwcursor = 1;
+		else if (strncmp(this_opt, "devices:", 8) == 0) {
+			this_opt += 8;
+			device_count = simple_strtol(this_opt, &endptr, 0);
+			if ((device_count < 0) ||
+			    (device_count > MAX_DEVICE_COUNT))
+				device_count = MAX_DEVICE_COUNT;
+		} else if (strncmp(this_opt, "wincfg:", 7) == 0) {
+			this_opt += 7;
+			window_index = simple_strtol(this_opt, &endptr, 0);
+			if ((window_index < 0) ||
+			    (window_index >= ARRAY_SIZE(windows)))
+				window_index = DEFAULT_WINDOW_INDEX;
+		} else if (strncmp(this_opt, "off", 3) == 0)
+			return 1;
+		else
+			print_warn("Unsupported option \"%s\"", this_opt);
+	}
+
+out:
+	return 0;
+}
+
+/* AU1200 LCD controller device driver */
+static int au1200fb_drv_probe(struct platform_device *dev)
+{
+	struct au1200fb_device *fbdev;
+	struct au1200fb_platdata *pd;
+	struct fb_info *fbi = NULL;
+	unsigned long page;
+	int bpp, plane, ret, irq;
+
+	print_info("" DRIVER_DESC "");
+
+	pd = dev->dev.platform_data;
+	if (!pd)
+		return -ENODEV;
+
+	/* Setup driver with options */
+	if (au1200fb_setup(pd))
+		return -ENODEV;
+
+	/* Point to the panel selected */
+	panel = &known_lcd_panels[panel_index];
+	win = &windows[window_index];
+
+	printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
+	printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
+
+	/* shut gcc up */
+	ret = 0;
+	fbdev = NULL;
+
+	for (plane = 0; plane < device_count; ++plane) {
+		bpp = winbpp(win->w[plane].mode_winctrl1);
+		if (win->w[plane].xres == 0)
+			win->w[plane].xres = panel->Xres;
+		if (win->w[plane].yres == 0)
+			win->w[plane].yres = panel->Yres;
+
+		fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
+					&dev->dev);
+		if (!fbi)
+			goto failed;
+
+		_au1200fb_infos[plane] = fbi;
+		fbdev = fbi->par;
+		fbdev->fb_info = fbi;
+		fbdev->pd = pd;
+
+		fbdev->plane = plane;
+
+		/* Allocate the framebuffer to the maximum screen size */
+		fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
+
+		fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev,
+				PAGE_ALIGN(fbdev->fb_len),
+				&fbdev->fb_phys, GFP_KERNEL);
+		if (!fbdev->fb_mem) {
+			print_err("fail to allocate frambuffer (size: %dK))",
+				  fbdev->fb_len / 1024);
+			return -ENOMEM;
+		}
+
+		/*
+		 * Set page reserved so that mmap will work. This is necessary
+		 * since we'll be remapping normal memory.
+		 */
+		for (page = (unsigned long)fbdev->fb_phys;
+		     page < PAGE_ALIGN((unsigned long)fbdev->fb_phys +
+			     fbdev->fb_len);
+		     page += PAGE_SIZE) {
+			SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */
+		}
+		print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
+		print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
+
+		/* Init FB data */
+		if ((ret = au1200fb_init_fbinfo(fbdev)) < 0)
+			goto failed;
+
+		/* Register new framebuffer */
+		ret = register_framebuffer(fbi);
+		if (ret < 0) {
+			print_err("cannot register new framebuffer");
+			goto failed;
+		}
+
+		au1200fb_fb_set_par(fbi);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+		if (plane == 0)
+			if (fb_prepare_logo(fbi, FB_ROTATE_UR)) {
+				/* Start display and show logo on boot */
+				fb_set_cmap(&fbi->cmap, fbi);
+				fb_show_logo(fbi, FB_ROTATE_UR);
+			}
+#endif
+	}
+
+	/* Now hook interrupt too */
+	irq = platform_get_irq(dev, 0);
+	ret = request_irq(irq, au1200fb_handle_irq,
+			  IRQF_SHARED, "lcd", (void *)dev);
+	if (ret) {
+		print_err("fail to request interrupt line %d (err: %d)",
+			  irq, ret);
+		goto failed;
+	}
+
+	platform_set_drvdata(dev, pd);
+
+	/* Kickstart the panel */
+	au1200_setpanel(panel, pd);
+
+	return 0;
+
+failed:
+	/* NOTE: This only does the current plane/window that failed; others are still active */
+	if (fbi) {
+		if (fbi->cmap.len != 0)
+			fb_dealloc_cmap(&fbi->cmap);
+		kfree(fbi->pseudo_palette);
+	}
+	if (plane == 0)
+		free_irq(AU1200_LCD_INT, (void*)dev);
+	return ret;
+}
+
+static int au1200fb_drv_remove(struct platform_device *dev)
+{
+	struct au1200fb_platdata *pd = platform_get_drvdata(dev);
+	struct au1200fb_device *fbdev;
+	struct fb_info *fbi;
+	int plane;
+
+	/* Turn off the panel */
+	au1200_setpanel(NULL, pd);
+
+	for (plane = 0; plane < device_count; ++plane)	{
+		fbi = _au1200fb_infos[plane];
+		fbdev = fbi->par;
+
+		/* Clean up all probe data */
+		unregister_framebuffer(fbi);
+		if (fbi->cmap.len != 0)
+			fb_dealloc_cmap(&fbi->cmap);
+		kfree(fbi->pseudo_palette);
+
+		framebuffer_release(fbi);
+		_au1200fb_infos[plane] = NULL;
+	}
+
+	free_irq(platform_get_irq(dev, 0), (void *)dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1200fb_drv_suspend(struct device *dev)
+{
+	struct au1200fb_platdata *pd = dev_get_drvdata(dev);
+	au1200_setpanel(NULL, pd);
+
+	lcd->outmask = 0;
+	au_sync();
+
+	return 0;
+}
+
+static int au1200fb_drv_resume(struct device *dev)
+{
+	struct au1200fb_platdata *pd = dev_get_drvdata(dev);
+	struct fb_info *fbi;
+	int i;
+
+	/* Kickstart the panel */
+	au1200_setpanel(panel, pd);
+
+	for (i = 0; i < device_count; i++) {
+		fbi = _au1200fb_infos[i];
+		au1200fb_fb_set_par(fbi);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops au1200fb_pmops = {
+	.suspend	= au1200fb_drv_suspend,
+	.resume		= au1200fb_drv_resume,
+	.freeze		= au1200fb_drv_suspend,
+	.thaw		= au1200fb_drv_resume,
+};
+
+#define AU1200FB_PMOPS	(&au1200fb_pmops)
+
+#else
+#define AU1200FB_PMOPS	NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver au1200fb_driver = {
+	.driver = {
+		.name	= "au1200-lcd",
+		.owner	= THIS_MODULE,
+		.pm	= AU1200FB_PMOPS,
+	},
+	.probe		= au1200fb_drv_probe,
+	.remove		= au1200fb_drv_remove,
+};
+module_platform_driver(au1200fb_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/au1200fb.h b/drivers/video/fbdev/au1200fb.h
new file mode 100644
index 000000000000..e2672714d8d4
--- /dev/null
+++ b/drivers/video/fbdev/au1200fb.h
@@ -0,0 +1,572 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Hardware definitions for the Au1200 LCD controller
+ *
+ * Copyright 2004 AMD
+ * Author:	AMD
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _AU1200LCD_H
+#define _AU1200LCD_H
+
+/********************************************************************/
+#define AU1200_LCD_ADDR		0xB5000000
+
+#define uint8 unsigned char
+#define uint32 unsigned int
+
+struct au1200_lcd {
+	volatile uint32	reserved0;
+	volatile uint32	screen;
+	volatile uint32	backcolor;
+	volatile uint32	horztiming;
+	volatile uint32	verttiming;
+	volatile uint32	clkcontrol;
+	volatile uint32	pwmdiv;
+	volatile uint32	pwmhi;
+	volatile uint32	reserved1;
+	volatile uint32	winenable;
+	volatile uint32	colorkey;
+	volatile uint32	colorkeymsk;
+	struct
+	{
+		volatile uint32	cursorctrl;
+		volatile uint32	cursorpos;
+		volatile uint32	cursorcolor0;
+		volatile uint32	cursorcolor1;
+		volatile uint32	cursorcolor2;
+		uint32	cursorcolor3;
+	} hwc;
+	volatile uint32	intstatus;
+	volatile uint32	intenable;
+	volatile uint32	outmask;
+	volatile uint32	fifoctrl;
+	uint32	reserved2[(0x0100-0x0058)/4];
+	struct
+	{
+		volatile uint32	winctrl0;
+		volatile uint32	winctrl1;
+		volatile uint32	winctrl2;
+		volatile uint32	winbuf0;
+		volatile uint32	winbuf1;
+		volatile uint32	winbufctrl;
+		uint32	winreserved0;
+		uint32	winreserved1;
+	} window[4];
+
+	uint32	reserved3[(0x0400-0x0180)/4];
+
+	volatile uint32	palette[(0x0800-0x0400)/4];
+
+	volatile uint8	cursorpattern[256];
+};
+
+/* lcd_screen */
+#define LCD_SCREEN_SEN		(1<<31)
+#define LCD_SCREEN_SX		(0x07FF<<19)
+#define LCD_SCREEN_SY		(0x07FF<< 8)
+#define LCD_SCREEN_SWP		(1<<7)
+#define LCD_SCREEN_SWD		(1<<6)
+#define LCD_SCREEN_PT		(7<<0)
+#define LCD_SCREEN_PT_TFT	(0<<0)
+#define LCD_SCREEN_SX_N(WIDTH)	((WIDTH-1)<<19)
+#define LCD_SCREEN_SY_N(HEIGHT)	((HEIGHT-1)<<8)
+#define LCD_SCREEN_PT_CSTN	(1<<0)
+#define LCD_SCREEN_PT_CDSTN	(2<<0)
+#define LCD_SCREEN_PT_M8STN	(3<<0)
+#define LCD_SCREEN_PT_M4STN	(4<<0)
+
+/* lcd_backcolor */
+#define LCD_BACKCOLOR_SBGR		(0xFF<<16)
+#define LCD_BACKCOLOR_SBGG		(0xFF<<8)
+#define LCD_BACKCOLOR_SBGB		(0xFF<<0)
+#define LCD_BACKCOLOR_SBGR_N(N)	((N)<<16)
+#define LCD_BACKCOLOR_SBGG_N(N)	((N)<<8)
+#define LCD_BACKCOLOR_SBGB_N(N)	((N)<<0)
+
+/* lcd_winenable */
+#define LCD_WINENABLE_WEN3		(1<<3)
+#define LCD_WINENABLE_WEN2		(1<<2)
+#define LCD_WINENABLE_WEN1		(1<<1)
+#define LCD_WINENABLE_WEN0		(1<<0)
+
+/* lcd_colorkey */
+#define LCD_COLORKEY_CKR		(0xFF<<16)
+#define LCD_COLORKEY_CKG		(0xFF<<8)
+#define LCD_COLORKEY_CKB		(0xFF<<0)
+#define LCD_COLORKEY_CKR_N(N)	((N)<<16)
+#define LCD_COLORKEY_CKG_N(N)	((N)<<8)
+#define LCD_COLORKEY_CKB_N(N)	((N)<<0)
+
+/* lcd_colorkeymsk */
+#define LCD_COLORKEYMSK_CKMR		(0xFF<<16)
+#define LCD_COLORKEYMSK_CKMG		(0xFF<<8)
+#define LCD_COLORKEYMSK_CKMB		(0xFF<<0)
+#define LCD_COLORKEYMSK_CKMR_N(N)	((N)<<16)
+#define LCD_COLORKEYMSK_CKMG_N(N)	((N)<<8)
+#define LCD_COLORKEYMSK_CKMB_N(N)	((N)<<0)
+
+/* lcd windows control 0 */
+#define LCD_WINCTRL0_OX		(0x07FF<<21)
+#define LCD_WINCTRL0_OY		(0x07FF<<10)
+#define LCD_WINCTRL0_A		(0x00FF<<2)
+#define LCD_WINCTRL0_AEN	(1<<1)
+#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
+#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
+#define LCD_WINCTRL0_A_N(N) ((N)<<2)
+
+/* lcd windows control 1 */
+#define LCD_WINCTRL1_PRI	(3<<30)
+#define LCD_WINCTRL1_PIPE	(1<<29)
+#define LCD_WINCTRL1_FRM	(0xF<<25)
+#define LCD_WINCTRL1_CCO	(1<<24)
+#define LCD_WINCTRL1_PO		(3<<22)
+#define LCD_WINCTRL1_SZX	(0x07FF<<11)
+#define LCD_WINCTRL1_SZY	(0x07FF<<0)
+#define LCD_WINCTRL1_FRM_1BPP	(0<<25)
+#define LCD_WINCTRL1_FRM_2BPP	(1<<25)
+#define LCD_WINCTRL1_FRM_4BPP	(2<<25)
+#define LCD_WINCTRL1_FRM_8BPP	(3<<25)
+#define LCD_WINCTRL1_FRM_12BPP	(4<<25)
+#define LCD_WINCTRL1_FRM_16BPP655	(5<<25)
+#define LCD_WINCTRL1_FRM_16BPP565	(6<<25)
+#define LCD_WINCTRL1_FRM_16BPP556	(7<<25)
+#define LCD_WINCTRL1_FRM_16BPPI1555	(8<<25)
+#define LCD_WINCTRL1_FRM_16BPPI5551	(9<<25)
+#define LCD_WINCTRL1_FRM_16BPPA1555	(10<<25)
+#define LCD_WINCTRL1_FRM_16BPPA5551	(11<<25)
+#define LCD_WINCTRL1_FRM_24BPP		(12<<25)
+#define LCD_WINCTRL1_FRM_32BPP		(13<<25)
+#define LCD_WINCTRL1_PRI_N(N)	((N)<<30)
+#define LCD_WINCTRL1_PO_00		(0<<22)
+#define LCD_WINCTRL1_PO_01		(1<<22)
+#define LCD_WINCTRL1_PO_10		(2<<22)
+#define LCD_WINCTRL1_PO_11		(3<<22)
+#define LCD_WINCTRL1_SZX_N(N)	((N-1)<<11)
+#define LCD_WINCTRL1_SZY_N(N)	((N-1)<<0)
+
+/* lcd windows control 2 */
+#define LCD_WINCTRL2_CKMODE		(3<<24)
+#define LCD_WINCTRL2_DBM		(1<<23)
+#define LCD_WINCTRL2_RAM		(3<<21)
+#define LCD_WINCTRL2_BX			(0x1FFF<<8)
+#define LCD_WINCTRL2_SCX		(0xF<<4)
+#define LCD_WINCTRL2_SCY		(0xF<<0)
+#define LCD_WINCTRL2_CKMODE_00		(0<<24)
+#define LCD_WINCTRL2_CKMODE_01		(1<<24)
+#define LCD_WINCTRL2_CKMODE_10		(2<<24)
+#define LCD_WINCTRL2_CKMODE_11		(3<<24)
+#define LCD_WINCTRL2_RAM_NONE		(0<<21)
+#define LCD_WINCTRL2_RAM_PALETTE	(1<<21)
+#define LCD_WINCTRL2_RAM_GAMMA		(2<<21)
+#define LCD_WINCTRL2_RAM_BUFFER		(3<<21)
+#define LCD_WINCTRL2_BX_N(N)	((N)<<8)
+#define LCD_WINCTRL2_SCX_1		(0<<4)
+#define LCD_WINCTRL2_SCX_2		(1<<4)
+#define LCD_WINCTRL2_SCX_4		(2<<4)
+#define LCD_WINCTRL2_SCY_1		(0<<0)
+#define LCD_WINCTRL2_SCY_2		(1<<0)
+#define LCD_WINCTRL2_SCY_4		(2<<0)
+
+/* lcd windows buffer control */
+#define LCD_WINBUFCTRL_DB		(1<<1)
+#define LCD_WINBUFCTRL_DBN		(1<<0)
+
+/* lcd_intstatus, lcd_intenable */
+#define LCD_INT_IFO				(0xF<<14)
+#define LCD_INT_IFU				(0xF<<10)
+#define LCD_INT_OFO				(1<<9)
+#define LCD_INT_OFU				(1<<8)
+#define LCD_INT_WAIT			(1<<3)
+#define LCD_INT_SD				(1<<2)
+#define LCD_INT_SA				(1<<1)
+#define LCD_INT_SS				(1<<0)
+
+/* lcd_horztiming */
+#define LCD_HORZTIMING_HND2		(0x1FF<<18)
+#define LCD_HORZTIMING_HND1		(0x1FF<<9)
+#define LCD_HORZTIMING_HPW		(0x1FF<<0)
+#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
+#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
+#define LCD_HORZTIMING_HPW_N(N)	(((N)-1)<<0)
+
+/* lcd_verttiming */
+#define LCD_VERTTIMING_VND2		(0x1FF<<18)
+#define LCD_VERTTIMING_VND1		(0x1FF<<9)
+#define LCD_VERTTIMING_VPW		(0x1FF<<0)
+#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
+#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
+#define LCD_VERTTIMING_VPW_N(N)	(((N)-1)<<0)
+
+/* lcd_clkcontrol */
+#define LCD_CLKCONTROL_EXT		(1<<22)
+#define LCD_CLKCONTROL_DELAY	(3<<20)
+#define LCD_CLKCONTROL_CDD		(1<<19)
+#define LCD_CLKCONTROL_IB		(1<<18)
+#define LCD_CLKCONTROL_IC		(1<<17)
+#define LCD_CLKCONTROL_IH		(1<<16)
+#define LCD_CLKCONTROL_IV		(1<<15)
+#define LCD_CLKCONTROL_BF		(0x1F<<10)
+#define LCD_CLKCONTROL_PCD		(0x3FF<<0)
+#define LCD_CLKCONTROL_BF_N(N)	(((N)-1)<<10)
+#define LCD_CLKCONTROL_PCD_N(N)	((N)<<0)
+
+/* lcd_pwmdiv */
+#define LCD_PWMDIV_EN			(1<<31)
+#define LCD_PWMDIV_PWMDIV		(0x1FFFF<<0)
+#define LCD_PWMDIV_PWMDIV_N(N)	((N)<<0)
+
+/* lcd_pwmhi */
+#define LCD_PWMHI_PWMHI1		(0xFFFF<<16)
+#define LCD_PWMHI_PWMHI0		(0xFFFF<<0)
+#define LCD_PWMHI_PWMHI1_N(N)	((N)<<16)
+#define LCD_PWMHI_PWMHI0_N(N)	((N)<<0)
+
+/* lcd_hwccon */
+#define LCD_HWCCON_EN			(1<<0)
+
+/* lcd_cursorpos */
+#define LCD_CURSORPOS_HWCXOFF		(0x1F<<27)
+#define LCD_CURSORPOS_HWCXPOS		(0x07FF<<16)
+#define LCD_CURSORPOS_HWCYOFF		(0x1F<<11)
+#define LCD_CURSORPOS_HWCYPOS		(0x07FF<<0)
+#define LCD_CURSORPOS_HWCXOFF_N(N)	((N)<<27)
+#define LCD_CURSORPOS_HWCXPOS_N(N)	((N)<<16)
+#define LCD_CURSORPOS_HWCYOFF_N(N)	((N)<<11)
+#define LCD_CURSORPOS_HWCYPOS_N(N)	((N)<<0)
+
+/* lcd_cursorcolor */
+#define LCD_CURSORCOLOR_HWCA		(0xFF<<24)
+#define LCD_CURSORCOLOR_HWCR		(0xFF<<16)
+#define LCD_CURSORCOLOR_HWCG		(0xFF<<8)
+#define LCD_CURSORCOLOR_HWCB		(0xFF<<0)
+#define LCD_CURSORCOLOR_HWCA_N(N)	((N)<<24)
+#define LCD_CURSORCOLOR_HWCR_N(N)	((N)<<16)
+#define LCD_CURSORCOLOR_HWCG_N(N)	((N)<<8)
+#define LCD_CURSORCOLOR_HWCB_N(N)	((N)<<0)
+
+/* lcd_fifoctrl */
+#define LCD_FIFOCTRL_F3IF		(1<<29)
+#define LCD_FIFOCTRL_F3REQ		(0x1F<<24)
+#define LCD_FIFOCTRL_F2IF		(1<<29)
+#define LCD_FIFOCTRL_F2REQ		(0x1F<<16)
+#define LCD_FIFOCTRL_F1IF		(1<<29)
+#define LCD_FIFOCTRL_F1REQ		(0x1F<<8)
+#define LCD_FIFOCTRL_F0IF		(1<<29)
+#define LCD_FIFOCTRL_F0REQ		(0x1F<<0)
+#define LCD_FIFOCTRL_F3REQ_N(N)	((N-1)<<24)
+#define LCD_FIFOCTRL_F2REQ_N(N)	((N-1)<<16)
+#define LCD_FIFOCTRL_F1REQ_N(N)	((N-1)<<8)
+#define LCD_FIFOCTRL_F0REQ_N(N)	((N-1)<<0)
+
+/* lcd_outmask */
+#define LCD_OUTMASK_MASK		(0x00FFFFFF)
+
+/********************************************************************/
+#endif /* _AU1200LCD_H */
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Hardware definitions for the Au1200 LCD controller
+ *
+ * Copyright 2004 AMD
+ * Author:	AMD
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _AU1200LCD_H
+#define _AU1200LCD_H
+
+/********************************************************************/
+#define AU1200_LCD_ADDR		0xB5000000
+
+#define uint8 unsigned char
+#define uint32 unsigned int
+
+struct au1200_lcd {
+	volatile uint32	reserved0;
+	volatile uint32	screen;
+	volatile uint32	backcolor;
+	volatile uint32	horztiming;
+	volatile uint32	verttiming;
+	volatile uint32	clkcontrol;
+	volatile uint32	pwmdiv;
+	volatile uint32	pwmhi;
+	volatile uint32	reserved1;
+	volatile uint32	winenable;
+	volatile uint32	colorkey;
+	volatile uint32	colorkeymsk;
+	struct
+	{
+		volatile uint32	cursorctrl;
+		volatile uint32	cursorpos;
+		volatile uint32	cursorcolor0;
+		volatile uint32	cursorcolor1;
+		volatile uint32	cursorcolor2;
+		uint32	cursorcolor3;
+	} hwc;
+	volatile uint32	intstatus;
+	volatile uint32	intenable;
+	volatile uint32	outmask;
+	volatile uint32	fifoctrl;
+	uint32	reserved2[(0x0100-0x0058)/4];
+	struct
+	{
+		volatile uint32	winctrl0;
+		volatile uint32	winctrl1;
+		volatile uint32	winctrl2;
+		volatile uint32	winbuf0;
+		volatile uint32	winbuf1;
+		volatile uint32	winbufctrl;
+		uint32	winreserved0;
+		uint32	winreserved1;
+	} window[4];
+
+	uint32	reserved3[(0x0400-0x0180)/4];
+
+	volatile uint32	palette[(0x0800-0x0400)/4];
+
+	volatile uint8	cursorpattern[256];
+};
+
+/* lcd_screen */
+#define LCD_SCREEN_SEN		(1<<31)
+#define LCD_SCREEN_SX		(0x07FF<<19)
+#define LCD_SCREEN_SY		(0x07FF<< 8)
+#define LCD_SCREEN_SWP		(1<<7)
+#define LCD_SCREEN_SWD		(1<<6)
+#define LCD_SCREEN_PT		(7<<0)
+#define LCD_SCREEN_PT_TFT	(0<<0)
+#define LCD_SCREEN_SX_N(WIDTH)	((WIDTH-1)<<19)
+#define LCD_SCREEN_SY_N(HEIGHT)	((HEIGHT-1)<<8)
+#define LCD_SCREEN_PT_CSTN	(1<<0)
+#define LCD_SCREEN_PT_CDSTN	(2<<0)
+#define LCD_SCREEN_PT_M8STN	(3<<0)
+#define LCD_SCREEN_PT_M4STN	(4<<0)
+
+/* lcd_backcolor */
+#define LCD_BACKCOLOR_SBGR		(0xFF<<16)
+#define LCD_BACKCOLOR_SBGG		(0xFF<<8)
+#define LCD_BACKCOLOR_SBGB		(0xFF<<0)
+#define LCD_BACKCOLOR_SBGR_N(N)	((N)<<16)
+#define LCD_BACKCOLOR_SBGG_N(N)	((N)<<8)
+#define LCD_BACKCOLOR_SBGB_N(N)	((N)<<0)
+
+/* lcd_winenable */
+#define LCD_WINENABLE_WEN3		(1<<3)
+#define LCD_WINENABLE_WEN2		(1<<2)
+#define LCD_WINENABLE_WEN1		(1<<1)
+#define LCD_WINENABLE_WEN0		(1<<0)
+
+/* lcd_colorkey */
+#define LCD_COLORKEY_CKR		(0xFF<<16)
+#define LCD_COLORKEY_CKG		(0xFF<<8)
+#define LCD_COLORKEY_CKB		(0xFF<<0)
+#define LCD_COLORKEY_CKR_N(N)	((N)<<16)
+#define LCD_COLORKEY_CKG_N(N)	((N)<<8)
+#define LCD_COLORKEY_CKB_N(N)	((N)<<0)
+
+/* lcd_colorkeymsk */
+#define LCD_COLORKEYMSK_CKMR		(0xFF<<16)
+#define LCD_COLORKEYMSK_CKMG		(0xFF<<8)
+#define LCD_COLORKEYMSK_CKMB		(0xFF<<0)
+#define LCD_COLORKEYMSK_CKMR_N(N)	((N)<<16)
+#define LCD_COLORKEYMSK_CKMG_N(N)	((N)<<8)
+#define LCD_COLORKEYMSK_CKMB_N(N)	((N)<<0)
+
+/* lcd windows control 0 */
+#define LCD_WINCTRL0_OX		(0x07FF<<21)
+#define LCD_WINCTRL0_OY		(0x07FF<<10)
+#define LCD_WINCTRL0_A		(0x00FF<<2)
+#define LCD_WINCTRL0_AEN	(1<<1)
+#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
+#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
+#define LCD_WINCTRL0_A_N(N) ((N)<<2)
+
+/* lcd windows control 1 */
+#define LCD_WINCTRL1_PRI	(3<<30)
+#define LCD_WINCTRL1_PIPE	(1<<29)
+#define LCD_WINCTRL1_FRM	(0xF<<25)
+#define LCD_WINCTRL1_CCO	(1<<24)
+#define LCD_WINCTRL1_PO		(3<<22)
+#define LCD_WINCTRL1_SZX	(0x07FF<<11)
+#define LCD_WINCTRL1_SZY	(0x07FF<<0)
+#define LCD_WINCTRL1_FRM_1BPP	(0<<25)
+#define LCD_WINCTRL1_FRM_2BPP	(1<<25)
+#define LCD_WINCTRL1_FRM_4BPP	(2<<25)
+#define LCD_WINCTRL1_FRM_8BPP	(3<<25)
+#define LCD_WINCTRL1_FRM_12BPP	(4<<25)
+#define LCD_WINCTRL1_FRM_16BPP655	(5<<25)
+#define LCD_WINCTRL1_FRM_16BPP565	(6<<25)
+#define LCD_WINCTRL1_FRM_16BPP556	(7<<25)
+#define LCD_WINCTRL1_FRM_16BPPI1555	(8<<25)
+#define LCD_WINCTRL1_FRM_16BPPI5551	(9<<25)
+#define LCD_WINCTRL1_FRM_16BPPA1555	(10<<25)
+#define LCD_WINCTRL1_FRM_16BPPA5551	(11<<25)
+#define LCD_WINCTRL1_FRM_24BPP		(12<<25)
+#define LCD_WINCTRL1_FRM_32BPP		(13<<25)
+#define LCD_WINCTRL1_PRI_N(N)	((N)<<30)
+#define LCD_WINCTRL1_PO_00		(0<<22)
+#define LCD_WINCTRL1_PO_01		(1<<22)
+#define LCD_WINCTRL1_PO_10		(2<<22)
+#define LCD_WINCTRL1_PO_11		(3<<22)
+#define LCD_WINCTRL1_SZX_N(N)	((N-1)<<11)
+#define LCD_WINCTRL1_SZY_N(N)	((N-1)<<0)
+
+/* lcd windows control 2 */
+#define LCD_WINCTRL2_CKMODE		(3<<24)
+#define LCD_WINCTRL2_DBM		(1<<23)
+#define LCD_WINCTRL2_RAM		(3<<21)
+#define LCD_WINCTRL2_BX			(0x1FFF<<8)
+#define LCD_WINCTRL2_SCX		(0xF<<4)
+#define LCD_WINCTRL2_SCY		(0xF<<0)
+#define LCD_WINCTRL2_CKMODE_00		(0<<24)
+#define LCD_WINCTRL2_CKMODE_01		(1<<24)
+#define LCD_WINCTRL2_CKMODE_10		(2<<24)
+#define LCD_WINCTRL2_CKMODE_11		(3<<24)
+#define LCD_WINCTRL2_RAM_NONE		(0<<21)
+#define LCD_WINCTRL2_RAM_PALETTE	(1<<21)
+#define LCD_WINCTRL2_RAM_GAMMA		(2<<21)
+#define LCD_WINCTRL2_RAM_BUFFER		(3<<21)
+#define LCD_WINCTRL2_BX_N(N)	((N)<<8)
+#define LCD_WINCTRL2_SCX_1		(0<<4)
+#define LCD_WINCTRL2_SCX_2		(1<<4)
+#define LCD_WINCTRL2_SCX_4		(2<<4)
+#define LCD_WINCTRL2_SCY_1		(0<<0)
+#define LCD_WINCTRL2_SCY_2		(1<<0)
+#define LCD_WINCTRL2_SCY_4		(2<<0)
+
+/* lcd windows buffer control */
+#define LCD_WINBUFCTRL_DB		(1<<1)
+#define LCD_WINBUFCTRL_DBN		(1<<0)
+
+/* lcd_intstatus, lcd_intenable */
+#define LCD_INT_IFO				(0xF<<14)
+#define LCD_INT_IFU				(0xF<<10)
+#define LCD_INT_OFO				(1<<9)
+#define LCD_INT_OFU				(1<<8)
+#define LCD_INT_WAIT			(1<<3)
+#define LCD_INT_SD				(1<<2)
+#define LCD_INT_SA				(1<<1)
+#define LCD_INT_SS				(1<<0)
+
+/* lcd_horztiming */
+#define LCD_HORZTIMING_HND2		(0x1FF<<18)
+#define LCD_HORZTIMING_HND1		(0x1FF<<9)
+#define LCD_HORZTIMING_HPW		(0x1FF<<0)
+#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
+#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
+#define LCD_HORZTIMING_HPW_N(N)	(((N)-1)<<0)
+
+/* lcd_verttiming */
+#define LCD_VERTTIMING_VND2		(0x1FF<<18)
+#define LCD_VERTTIMING_VND1		(0x1FF<<9)
+#define LCD_VERTTIMING_VPW		(0x1FF<<0)
+#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
+#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
+#define LCD_VERTTIMING_VPW_N(N)	(((N)-1)<<0)
+
+/* lcd_clkcontrol */
+#define LCD_CLKCONTROL_EXT		(1<<22)
+#define LCD_CLKCONTROL_DELAY	(3<<20)
+#define LCD_CLKCONTROL_CDD		(1<<19)
+#define LCD_CLKCONTROL_IB		(1<<18)
+#define LCD_CLKCONTROL_IC		(1<<17)
+#define LCD_CLKCONTROL_IH		(1<<16)
+#define LCD_CLKCONTROL_IV		(1<<15)
+#define LCD_CLKCONTROL_BF		(0x1F<<10)
+#define LCD_CLKCONTROL_PCD		(0x3FF<<0)
+#define LCD_CLKCONTROL_BF_N(N)	(((N)-1)<<10)
+#define LCD_CLKCONTROL_PCD_N(N)	((N)<<0)
+
+/* lcd_pwmdiv */
+#define LCD_PWMDIV_EN			(1<<31)
+#define LCD_PWMDIV_PWMDIV		(0x1FFFF<<0)
+#define LCD_PWMDIV_PWMDIV_N(N)	((N)<<0)
+
+/* lcd_pwmhi */
+#define LCD_PWMHI_PWMHI1		(0xFFFF<<16)
+#define LCD_PWMHI_PWMHI0		(0xFFFF<<0)
+#define LCD_PWMHI_PWMHI1_N(N)	((N)<<16)
+#define LCD_PWMHI_PWMHI0_N(N)	((N)<<0)
+
+/* lcd_hwccon */
+#define LCD_HWCCON_EN			(1<<0)
+
+/* lcd_cursorpos */
+#define LCD_CURSORPOS_HWCXOFF		(0x1F<<27)
+#define LCD_CURSORPOS_HWCXPOS		(0x07FF<<16)
+#define LCD_CURSORPOS_HWCYOFF		(0x1F<<11)
+#define LCD_CURSORPOS_HWCYPOS		(0x07FF<<0)
+#define LCD_CURSORPOS_HWCXOFF_N(N)	((N)<<27)
+#define LCD_CURSORPOS_HWCXPOS_N(N)	((N)<<16)
+#define LCD_CURSORPOS_HWCYOFF_N(N)	((N)<<11)
+#define LCD_CURSORPOS_HWCYPOS_N(N)	((N)<<0)
+
+/* lcd_cursorcolor */
+#define LCD_CURSORCOLOR_HWCA		(0xFF<<24)
+#define LCD_CURSORCOLOR_HWCR		(0xFF<<16)
+#define LCD_CURSORCOLOR_HWCG		(0xFF<<8)
+#define LCD_CURSORCOLOR_HWCB		(0xFF<<0)
+#define LCD_CURSORCOLOR_HWCA_N(N)	((N)<<24)
+#define LCD_CURSORCOLOR_HWCR_N(N)	((N)<<16)
+#define LCD_CURSORCOLOR_HWCG_N(N)	((N)<<8)
+#define LCD_CURSORCOLOR_HWCB_N(N)	((N)<<0)
+
+/* lcd_fifoctrl */
+#define LCD_FIFOCTRL_F3IF		(1<<29)
+#define LCD_FIFOCTRL_F3REQ		(0x1F<<24)
+#define LCD_FIFOCTRL_F2IF		(1<<29)
+#define LCD_FIFOCTRL_F2REQ		(0x1F<<16)
+#define LCD_FIFOCTRL_F1IF		(1<<29)
+#define LCD_FIFOCTRL_F1REQ		(0x1F<<8)
+#define LCD_FIFOCTRL_F0IF		(1<<29)
+#define LCD_FIFOCTRL_F0REQ		(0x1F<<0)
+#define LCD_FIFOCTRL_F3REQ_N(N)	((N-1)<<24)
+#define LCD_FIFOCTRL_F2REQ_N(N)	((N-1)<<16)
+#define LCD_FIFOCTRL_F1REQ_N(N)	((N-1)<<8)
+#define LCD_FIFOCTRL_F0REQ_N(N)	((N-1)<<0)
+
+/* lcd_outmask */
+#define LCD_OUTMASK_MASK		(0x00FFFFFF)
+
+/********************************************************************/
+#endif /* _AU1200LCD_H */
diff --git a/drivers/video/fbdev/auo_k1900fb.c b/drivers/video/fbdev/auo_k1900fb.c
new file mode 100644
index 000000000000..f5b668e77af3
--- /dev/null
+++ b/drivers/video/fbdev/auo_k1900fb.c
@@ -0,0 +1,205 @@
+/*
+ * auok190xfb.c -- FB driver for AUO-K1900 controllers
+ *
+ * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on broadsheetfb.c
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver is written to be used with the AUO-K1900 display controller.
+ *
+ * It is intended to be architecture independent. A board specific driver
+ * must be used to perform all the physical IO interactions.
+ *
+ * The controller supports different update modes:
+ * mode0+1 16 step gray (4bit)
+ * mode2 4 step gray (2bit) - FIXME: add strange refresh
+ * mode3 2 step gray (1bit) - FIXME: add strange refresh
+ * mode4 handwriting mode (strange behaviour)
+ * mode5 automatic selection of update mode
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/pm_runtime.h>
+
+#include <video/auo_k190xfb.h>
+
+#include "auo_k190x.h"
+
+/*
+ * AUO-K1900 specific commands
+ */
+
+#define AUOK1900_CMD_PARTIALDISP	0x1001
+#define AUOK1900_CMD_ROTATION		0x1006
+#define AUOK1900_CMD_LUT_STOP		0x1009
+
+#define AUOK1900_INIT_TEMP_AVERAGE	(1 << 13)
+#define AUOK1900_INIT_ROTATE(_x)	((_x & 0x3) << 10)
+#define AUOK1900_INIT_RESOLUTION(_res)	((_res & 0x7) << 2)
+
+static void auok1900_init(struct auok190xfb_par *par)
+{
+	struct device *dev = par->info->device;
+	struct auok190x_board *board = par->board;
+	u16 init_param = 0;
+
+	pm_runtime_get_sync(dev);
+
+	init_param |= AUOK1900_INIT_TEMP_AVERAGE;
+	init_param |= AUOK1900_INIT_ROTATE(par->rotation);
+	init_param |= AUOK190X_INIT_INVERSE_WHITE;
+	init_param |= AUOK190X_INIT_FORMAT0;
+	init_param |= AUOK1900_INIT_RESOLUTION(par->resolution);
+	init_param |= AUOK190X_INIT_SHIFT_RIGHT;
+
+	auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
+
+	/* let the controller finish */
+	board->wait_for_rdy(par);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
+static void auok1900_update_region(struct auok190xfb_par *par, int mode,
+						u16 y1, u16 y2)
+{
+	struct device *dev = par->info->device;
+	unsigned char *buf = (unsigned char *)par->info->screen_base;
+	int xres = par->info->var.xres;
+	int line_length = par->info->fix.line_length;
+	u16 args[4];
+
+	pm_runtime_get_sync(dev);
+
+	mutex_lock(&(par->io_lock));
+
+	/* y1 and y2 must be a multiple of 2 so drop the lowest bit */
+	y1 &= 0xfffe;
+	y2 &= 0xfffe;
+
+	dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
+		1, y1+1, xres, y2-y1, mode);
+
+	/* to FIX handle different partial update modes */
+	args[0] = mode | 1;
+	args[1] = y1 + 1;
+	args[2] = xres;
+	args[3] = y2 - y1;
+	buf += y1 * line_length;
+	auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
+				     ((y2 - y1) * line_length)/2, (u16 *) buf);
+	auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
+
+	par->update_cnt++;
+
+	mutex_unlock(&(par->io_lock));
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
+static void auok1900fb_dpy_update_pages(struct auok190xfb_par *par,
+						u16 y1, u16 y2)
+{
+	int mode;
+
+	if (par->update_mode < 0) {
+		mode = AUOK190X_UPDATE_MODE(1);
+		par->last_mode = -1;
+	} else {
+		mode = AUOK190X_UPDATE_MODE(par->update_mode);
+		par->last_mode = par->update_mode;
+	}
+
+	if (par->flash)
+		mode |= AUOK190X_UPDATE_NONFLASH;
+
+	auok1900_update_region(par, mode, y1, y2);
+}
+
+static void auok1900fb_dpy_update(struct auok190xfb_par *par)
+{
+	int mode;
+
+	if (par->update_mode < 0) {
+		mode = AUOK190X_UPDATE_MODE(0);
+		par->last_mode = -1;
+	} else {
+		mode = AUOK190X_UPDATE_MODE(par->update_mode);
+		par->last_mode = par->update_mode;
+	}
+
+	if (par->flash)
+		mode |= AUOK190X_UPDATE_NONFLASH;
+
+	auok1900_update_region(par, mode, 0, par->info->var.yres);
+	par->update_cnt = 0;
+}
+
+static bool auok1900fb_need_refresh(struct auok190xfb_par *par)
+{
+	return (par->update_cnt > 10);
+}
+
+static int auok1900fb_probe(struct platform_device *pdev)
+{
+	struct auok190x_init_data init;
+	struct auok190x_board *board;
+
+	/* pick up board specific routines */
+	board = pdev->dev.platform_data;
+	if (!board)
+		return -EINVAL;
+
+	/* fill temporary init struct for common init */
+	init.id = "auo_k1900fb";
+	init.board = board;
+	init.update_partial = auok1900fb_dpy_update_pages;
+	init.update_all = auok1900fb_dpy_update;
+	init.need_refresh = auok1900fb_need_refresh;
+	init.init = auok1900_init;
+
+	return auok190x_common_probe(pdev, &init);
+}
+
+static int auok1900fb_remove(struct platform_device *pdev)
+{
+	return auok190x_common_remove(pdev);
+}
+
+static struct platform_driver auok1900fb_driver = {
+	.probe	= auok1900fb_probe,
+	.remove = auok1900fb_remove,
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "auo_k1900fb",
+		.pm = &auok190x_pm,
+	},
+};
+module_platform_driver(auok1900fb_driver);
+
+MODULE_DESCRIPTION("framebuffer driver for the AUO-K1900 EPD controller");
+MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/auo_k1901fb.c b/drivers/video/fbdev/auo_k1901fb.c
new file mode 100644
index 000000000000..12b9adcb75c5
--- /dev/null
+++ b/drivers/video/fbdev/auo_k1901fb.c
@@ -0,0 +1,258 @@
+/*
+ * auok190xfb.c -- FB driver for AUO-K1901 controllers
+ *
+ * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on broadsheetfb.c
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver is written to be used with the AUO-K1901 display controller.
+ *
+ * It is intended to be architecture independent. A board specific driver
+ * must be used to perform all the physical IO interactions.
+ *
+ * The controller supports different update modes:
+ * mode0+1 16 step gray (4bit)
+ * mode2+3 4 step gray (2bit)
+ * mode4+5 2 step gray (1bit)
+ * - mode4 is described as "without LUT"
+ * mode7 automatic selection of update mode
+ *
+ * The most interesting difference to the K1900 is the ability to do screen
+ * updates in an asynchronous fashion. Where the K1900 needs to wait for the
+ * current update to complete, the K1901 can process later updates already.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/pm_runtime.h>
+
+#include <video/auo_k190xfb.h>
+
+#include "auo_k190x.h"
+
+/*
+ * AUO-K1901 specific commands
+ */
+
+#define AUOK1901_CMD_LUT_INTERFACE	0x0005
+#define AUOK1901_CMD_DMA_START		0x1001
+#define AUOK1901_CMD_CURSOR_START	0x1007
+#define AUOK1901_CMD_CURSOR_STOP	AUOK190X_CMD_DATA_STOP
+#define AUOK1901_CMD_DDMA_START		0x1009
+
+#define AUOK1901_INIT_GATE_PULSE_LOW	(0 << 14)
+#define AUOK1901_INIT_GATE_PULSE_HIGH	(1 << 14)
+#define AUOK1901_INIT_SINGLE_GATE	(0 << 13)
+#define AUOK1901_INIT_DOUBLE_GATE	(1 << 13)
+
+/* Bits to pixels
+ *   Mode	15-12	11-8	7-4	3-0
+ *   format2	2	T	1	T
+ *   format3	1	T	2	T
+ *   format4	T	2	T	1
+ *   format5	T	1	T	2
+ *
+ *   halftone modes:
+ *   format6	2	2	1	1
+ *   format7	1	1	2	2
+ */
+#define AUOK1901_INIT_FORMAT2		(1 << 7)
+#define AUOK1901_INIT_FORMAT3		((1 << 7) | (1 << 6))
+#define AUOK1901_INIT_FORMAT4		(1 << 8)
+#define AUOK1901_INIT_FORMAT5		((1 << 8) | (1 << 6))
+#define AUOK1901_INIT_FORMAT6		((1 << 8) | (1 << 7))
+#define AUOK1901_INIT_FORMAT7		((1 << 8) | (1 << 7) | (1 << 6))
+
+/* res[4] to bit 10
+ * res[3-0] to bits 5-2
+ */
+#define AUOK1901_INIT_RESOLUTION(_res)	(((_res & (1 << 4)) << 6) \
+					 | ((_res & 0xf) << 2))
+
+/*
+ * portrait / landscape orientation in AUOK1901_CMD_DMA_START
+ */
+#define AUOK1901_DMA_ROTATE90(_rot)		((_rot & 1) << 13)
+
+/*
+ * equivalent to 1 << 11, needs the ~ to have same rotation like K1900
+ */
+#define AUOK1901_DDMA_ROTATE180(_rot)		((~_rot & 2) << 10)
+
+static void auok1901_init(struct auok190xfb_par *par)
+{
+	struct device *dev = par->info->device;
+	struct auok190x_board *board = par->board;
+	u16 init_param = 0;
+
+	pm_runtime_get_sync(dev);
+
+	init_param |= AUOK190X_INIT_INVERSE_WHITE;
+	init_param |= AUOK190X_INIT_FORMAT0;
+	init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
+	init_param |= AUOK190X_INIT_SHIFT_LEFT;
+
+	auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
+
+	/* let the controller finish */
+	board->wait_for_rdy(par);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
+static void auok1901_update_region(struct auok190xfb_par *par, int mode,
+						u16 y1, u16 y2)
+{
+	struct device *dev = par->info->device;
+	unsigned char *buf = (unsigned char *)par->info->screen_base;
+	int xres = par->info->var.xres;
+	int line_length = par->info->fix.line_length;
+	u16 args[5];
+
+	pm_runtime_get_sync(dev);
+
+	mutex_lock(&(par->io_lock));
+
+	/* y1 and y2 must be a multiple of 2 so drop the lowest bit */
+	y1 &= 0xfffe;
+	y2 &= 0xfffe;
+
+	dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
+		1, y1+1, xres, y2-y1, mode);
+
+	/* K1901: first transfer the region data */
+	args[0] = AUOK1901_DMA_ROTATE90(par->rotation) | 1;
+	args[1] = y1 + 1;
+	args[2] = xres;
+	args[3] = y2 - y1;
+	buf += y1 * line_length;
+	auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
+					    args, ((y2 - y1) * line_length)/2,
+					    (u16 *) buf);
+	auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
+
+	/* K1901: second tell the controller to update the region with mode */
+	args[0] = mode | AUOK1901_DDMA_ROTATE180(par->rotation);
+	args[1] = 1;
+	args[2] = y1 + 1;
+	args[3] = xres;
+	args[4] = y2 - y1;
+	auok190x_send_cmdargs_nowait(par, AUOK1901_CMD_DDMA_START, 5, args);
+
+	par->update_cnt++;
+
+	mutex_unlock(&(par->io_lock));
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
+static void auok1901fb_dpy_update_pages(struct auok190xfb_par *par,
+						u16 y1, u16 y2)
+{
+	int mode;
+
+	if (par->update_mode < 0) {
+		mode = AUOK190X_UPDATE_MODE(1);
+		par->last_mode = -1;
+	} else {
+		mode = AUOK190X_UPDATE_MODE(par->update_mode);
+		par->last_mode = par->update_mode;
+	}
+
+	if (par->flash)
+		mode |= AUOK190X_UPDATE_NONFLASH;
+
+	auok1901_update_region(par, mode, y1, y2);
+}
+
+static void auok1901fb_dpy_update(struct auok190xfb_par *par)
+{
+	int mode;
+
+	/* When doing full updates, wait for the controller to be ready
+	 * This will hopefully catch some hangs of the K1901
+	 */
+	par->board->wait_for_rdy(par);
+
+	if (par->update_mode < 0) {
+		mode = AUOK190X_UPDATE_MODE(0);
+		par->last_mode = -1;
+	} else {
+		mode = AUOK190X_UPDATE_MODE(par->update_mode);
+		par->last_mode = par->update_mode;
+	}
+
+	if (par->flash)
+		mode |= AUOK190X_UPDATE_NONFLASH;
+
+	auok1901_update_region(par, mode, 0, par->info->var.yres);
+	par->update_cnt = 0;
+}
+
+static bool auok1901fb_need_refresh(struct auok190xfb_par *par)
+{
+	return (par->update_cnt > 10);
+}
+
+static int auok1901fb_probe(struct platform_device *pdev)
+{
+	struct auok190x_init_data init;
+	struct auok190x_board *board;
+
+	/* pick up board specific routines */
+	board = pdev->dev.platform_data;
+	if (!board)
+		return -EINVAL;
+
+	/* fill temporary init struct for common init */
+	init.id = "auo_k1901fb";
+	init.board = board;
+	init.update_partial = auok1901fb_dpy_update_pages;
+	init.update_all = auok1901fb_dpy_update;
+	init.need_refresh = auok1901fb_need_refresh;
+	init.init = auok1901_init;
+
+	return auok190x_common_probe(pdev, &init);
+}
+
+static int auok1901fb_remove(struct platform_device *pdev)
+{
+	return auok190x_common_remove(pdev);
+}
+
+static struct platform_driver auok1901fb_driver = {
+	.probe	= auok1901fb_probe,
+	.remove = auok1901fb_remove,
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "auo_k1901fb",
+		.pm = &auok190x_pm,
+	},
+};
+module_platform_driver(auok1901fb_driver);
+
+MODULE_DESCRIPTION("framebuffer driver for the AUO-K1901 EPD controller");
+MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/auo_k190x.c b/drivers/video/fbdev/auo_k190x.c
new file mode 100644
index 000000000000..8d2499d1cafb
--- /dev/null
+++ b/drivers/video/fbdev/auo_k190x.c
@@ -0,0 +1,1198 @@
+/*
+ * Common code for AUO-K190X framebuffer drivers
+ *
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/auo_k190xfb.h>
+
+#include "auo_k190x.h"
+
+struct panel_info {
+	int w;
+	int h;
+};
+
+/* table of panel specific parameters to be indexed into by the board drivers */
+static struct panel_info panel_table[] = {
+	/* standard 6" */
+	[AUOK190X_RESOLUTION_800_600] = {
+		.w = 800,
+		.h = 600,
+	},
+	/* standard 9" */
+	[AUOK190X_RESOLUTION_1024_768] = {
+		.w = 1024,
+		.h = 768,
+	},
+	[AUOK190X_RESOLUTION_600_800] = {
+		.w = 600,
+		.h = 800,
+	},
+	[AUOK190X_RESOLUTION_768_1024] = {
+		.w = 768,
+		.h = 1024,
+	},
+};
+
+/*
+ * private I80 interface to the board driver
+ */
+
+static void auok190x_issue_data(struct auok190xfb_par *par, u16 data)
+{
+	par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+	par->board->set_hdb(par, data);
+	par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+}
+
+static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
+{
+	par->board->set_ctl(par, AUOK190X_I80_DC, 0);
+	auok190x_issue_data(par, data);
+	par->board->set_ctl(par, AUOK190X_I80_DC, 1);
+}
+
+/**
+ * Conversion of 16bit color to 4bit grayscale
+ * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
+ */
+static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
+{
+	return ((((data & 0xF800) >> var->red.offset) * 77 +
+		 ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
+		 ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
+}
+
+static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
+					u16 *data)
+{
+	struct fb_var_screeninfo *var = &par->info->var;
+	struct device *dev = par->info->device;
+	int i;
+	u16 tmp;
+
+	if (size & 7) {
+		dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
+			size);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < (size >> 2); i++) {
+		par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+
+		tmp  = (rgb565_to_gray4(data[4*i], var) & 0x000F);
+		tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
+		tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
+		tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
+
+		par->board->set_hdb(par, tmp);
+		par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+	}
+
+	return 0;
+}
+
+static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
+				       u16 *data)
+{
+	struct device *dev = par->info->device;
+	int i;
+	u16 tmp;
+
+	if (size & 3) {
+		dev_err(dev, "issue_pixels: size %d must be a multiple of 4\n",
+			size);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < (size >> 1); i++) {
+		par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+
+		/* simple reduction of 8bit staticgray to 4bit gray
+		 * combines 4 * 4bit pixel values into a 16bit value
+		 */
+		tmp  = (data[2*i] & 0xF0) >> 4;
+		tmp |= (data[2*i] & 0xF000) >> 8;
+		tmp |= (data[2*i+1] & 0xF0) << 4;
+		tmp |= (data[2*i+1] & 0xF000);
+
+		par->board->set_hdb(par, tmp);
+		par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+	}
+
+	return 0;
+}
+
+static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
+				 u16 *data)
+{
+	struct fb_info *info = par->info;
+	struct device *dev = par->info->device;
+
+	if (info->var.bits_per_pixel == 8 && info->var.grayscale)
+		auok190x_issue_pixels_gray8(par, size, data);
+	else if (info->var.bits_per_pixel == 16)
+		auok190x_issue_pixels_rgb565(par, size, data);
+	else
+		dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
+			info->var.bits_per_pixel, info->var.grayscale);
+
+	return 0;
+}
+
+static u16 auok190x_read_data(struct auok190xfb_par *par)
+{
+	u16 data;
+
+	par->board->set_ctl(par, AUOK190X_I80_OE, 0);
+	data = par->board->get_hdb(par);
+	par->board->set_ctl(par, AUOK190X_I80_OE, 1);
+
+	return data;
+}
+
+/*
+ * Command interface for the controller drivers
+ */
+
+void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data)
+{
+	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+	auok190x_issue_cmd(par, data);
+	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+}
+EXPORT_SYMBOL_GPL(auok190x_send_command_nowait);
+
+void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
+				  int argc, u16 *argv)
+{
+	int i;
+
+	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+	auok190x_issue_cmd(par, cmd);
+
+	for (i = 0; i < argc; i++)
+		auok190x_issue_data(par, argv[i]);
+	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_nowait);
+
+int auok190x_send_command(struct auok190xfb_par *par, u16 data)
+{
+	int ret;
+
+	ret = par->board->wait_for_rdy(par);
+	if (ret)
+		return ret;
+
+	auok190x_send_command_nowait(par, data);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_send_command);
+
+int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
+			   int argc, u16 *argv)
+{
+	int ret;
+
+	ret = par->board->wait_for_rdy(par);
+	if (ret)
+		return ret;
+
+	auok190x_send_cmdargs_nowait(par, cmd, argc, argv);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs);
+
+int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
+			   int argc, u16 *argv)
+{
+	int i, ret;
+
+	ret = par->board->wait_for_rdy(par);
+	if (ret)
+		return ret;
+
+	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+	auok190x_issue_cmd(par, cmd);
+
+	for (i = 0; i < argc; i++)
+		argv[i] = auok190x_read_data(par);
+	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_read_cmdargs);
+
+void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, u16 cmd,
+				  int argc, u16 *argv, int size, u16 *data)
+{
+	int i;
+
+	par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+
+	auok190x_issue_cmd(par, cmd);
+
+	for (i = 0; i < argc; i++)
+		auok190x_issue_data(par, argv[i]);
+
+	auok190x_issue_pixels(par, size, data);
+
+	par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels_nowait);
+
+int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
+				  int argc, u16 *argv, int size, u16 *data)
+{
+	int ret;
+
+	ret = par->board->wait_for_rdy(par);
+	if (ret)
+		return ret;
+
+	auok190x_send_cmdargs_pixels_nowait(par, cmd, argc, argv, size, data);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels);
+
+/*
+ * fbdefio callbacks - common on both controllers.
+ */
+
+static void auok190xfb_dpy_first_io(struct fb_info *info)
+{
+	/* tell runtime-pm that we wish to use the device in a short time */
+	pm_runtime_get(info->device);
+}
+
+/* this is called back from the deferred io workqueue */
+static void auok190xfb_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct auok190xfb_par *par = info->par;
+	u16 line_length = info->fix.line_length;
+	u16 yres = info->var.yres;
+	u16 y1 = 0, h = 0;
+	int prev_index = -1;
+	struct page *cur;
+	int h_inc;
+	int threshold;
+
+	if (!list_empty(pagelist))
+		/* the device resume should've been requested through first_io,
+		 * if the resume did not finish until now, wait for it.
+		 */
+		pm_runtime_barrier(info->device);
+	else
+		/* We reached this via the fsync or some other way.
+		 * In either case the first_io function did not run,
+		 * so we runtime_resume the device here synchronously.
+		 */
+		pm_runtime_get_sync(info->device);
+
+	/* Do a full screen update every n updates to prevent
+	 * excessive darkening of the Sipix display.
+	 * If we do this, there is no need to walk the pages.
+	 */
+	if (par->need_refresh(par)) {
+		par->update_all(par);
+		goto out;
+	}
+
+	/* height increment is fixed per page */
+	h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
+
+	/* calculate number of pages from pixel height */
+	threshold = par->consecutive_threshold / h_inc;
+	if (threshold < 1)
+		threshold = 1;
+
+	/* walk the written page list and swizzle the data */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+		if (prev_index < 0) {
+			/* just starting so assign first page */
+			y1 = (cur->index << PAGE_SHIFT) / line_length;
+			h = h_inc;
+		} else if ((cur->index - prev_index) <= threshold) {
+			/* page is within our threshold for single updates */
+			h += h_inc * (cur->index - prev_index);
+		} else {
+			/* page not consecutive, issue previous update first */
+			par->update_partial(par, y1, y1 + h);
+
+			/* start over with our non consecutive page */
+			y1 = (cur->index << PAGE_SHIFT) / line_length;
+			h = h_inc;
+		}
+		prev_index = cur->index;
+	}
+
+	/* if we still have any pages to update we do so now */
+	if (h >= yres)
+		/* its a full screen update, just do it */
+		par->update_all(par);
+	else
+		par->update_partial(par, y1, min((u16) (y1 + h), yres));
+
+out:
+	pm_runtime_mark_last_busy(info->device);
+	pm_runtime_put_autosuspend(info->device);
+}
+
+/*
+ * framebuffer operations
+ */
+
+/*
+ * this is the slow path from userspace. they can seek and write to
+ * the fb. it's inefficient to do anything less than a full screen draw
+ */
+static ssize_t auok190xfb_write(struct fb_info *info, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct auok190xfb_par *par = info->par;
+	unsigned long p = *ppos;
+	void *dst;
+	int err = 0;
+	unsigned long total_size;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
+		count = total_size - p;
+	}
+
+	dst = (void *)(info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		err = -EFAULT;
+
+	if  (!err)
+		*ppos += count;
+
+	par->update_all(par);
+
+	return (err) ? err : count;
+}
+
+static void auok190xfb_fillrect(struct fb_info *info,
+				   const struct fb_fillrect *rect)
+{
+	struct auok190xfb_par *par = info->par;
+
+	sys_fillrect(info, rect);
+
+	par->update_all(par);
+}
+
+static void auok190xfb_copyarea(struct fb_info *info,
+				   const struct fb_copyarea *area)
+{
+	struct auok190xfb_par *par = info->par;
+
+	sys_copyarea(info, area);
+
+	par->update_all(par);
+}
+
+static void auok190xfb_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	struct auok190xfb_par *par = info->par;
+
+	sys_imageblit(info, image);
+
+	par->update_all(par);
+}
+
+static int auok190xfb_check_var(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
+{
+	struct device *dev = info->device;
+	struct auok190xfb_par *par = info->par;
+	struct panel_info *panel = &panel_table[par->resolution];
+	int size;
+
+	/*
+	 * Color depth
+	 */
+
+	if (var->bits_per_pixel == 8 && var->grayscale == 1) {
+		/*
+		 * For 8-bit grayscale, R, G, and B offset are equal.
+		 */
+		var->red.length = 8;
+		var->red.offset = 0;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 0;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+	} else if (var->bits_per_pixel == 16) {
+		var->red.length = 5;
+		var->red.offset = 11;
+		var->red.msb_right = 0;
+
+		var->green.length = 6;
+		var->green.offset = 5;
+		var->green.msb_right = 0;
+
+		var->blue.length = 5;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+	} else {
+		dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
+			info->var.bits_per_pixel, info->var.grayscale);
+		return -EINVAL;
+	}
+
+	/*
+	 * Dimensions
+	 */
+
+	switch (var->rotate) {
+	case FB_ROTATE_UR:
+	case FB_ROTATE_UD:
+		var->xres = panel->w;
+		var->yres = panel->h;
+		break;
+	case FB_ROTATE_CW:
+	case FB_ROTATE_CCW:
+		var->xres = panel->h;
+		var->yres = panel->w;
+		break;
+	default:
+		dev_dbg(dev, "Invalid rotation request\n");
+		return -EINVAL;
+	}
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+
+	size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
+	if (size > info->fix.smem_len) {
+		dev_err(dev, "Memory limit exceeded, requested %dK\n",
+			size >> 10);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int auok190xfb_set_fix(struct fb_info *info)
+{
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct fb_var_screeninfo *var = &info->var;
+
+	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->accel = FB_ACCEL_NONE;
+	fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
+				       : FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 0;
+	fix->ypanstep = 0;
+	fix->ywrapstep = 0;
+
+	return 0;
+}
+
+static int auok190xfb_set_par(struct fb_info *info)
+{
+	struct auok190xfb_par *par = info->par;
+
+	par->rotation = info->var.rotate;
+	auok190xfb_set_fix(info);
+
+	/* reinit the controller to honor the rotation */
+	par->init(par);
+
+	/* wait for init to complete */
+	par->board->wait_for_rdy(par);
+
+	return 0;
+}
+
+static struct fb_ops auok190xfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read	= fb_sys_read,
+	.fb_write	= auok190xfb_write,
+	.fb_fillrect	= auok190xfb_fillrect,
+	.fb_copyarea	= auok190xfb_copyarea,
+	.fb_imageblit	= auok190xfb_imageblit,
+	.fb_check_var	= auok190xfb_check_var,
+	.fb_set_par     = auok190xfb_set_par,
+};
+
+/*
+ * Controller-functions common to both K1900 and K1901
+ */
+
+static int auok190x_read_temperature(struct auok190xfb_par *par)
+{
+	struct device *dev = par->info->device;
+	u16 data[4];
+	int temp;
+
+	pm_runtime_get_sync(dev);
+
+	mutex_lock(&(par->io_lock));
+
+	auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
+
+	mutex_unlock(&(par->io_lock));
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
+	/* sanitize and split of half-degrees for now */
+	temp = ((data[0] & AUOK190X_VERSION_TEMP_MASK) >> 1);
+
+	/* handle positive and negative temperatures */
+	if (temp >= 201)
+		return (255 - temp + 1) * (-1);
+	else
+		return temp;
+}
+
+static void auok190x_identify(struct auok190xfb_par *par)
+{
+	struct device *dev = par->info->device;
+	u16 data[4];
+
+	pm_runtime_get_sync(dev);
+
+	mutex_lock(&(par->io_lock));
+
+	auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
+
+	mutex_unlock(&(par->io_lock));
+
+	par->epd_type = data[1] & AUOK190X_VERSION_TEMP_MASK;
+
+	par->panel_size_int = AUOK190X_VERSION_SIZE_INT(data[2]);
+	par->panel_size_float = AUOK190X_VERSION_SIZE_FLOAT(data[2]);
+	par->panel_model = AUOK190X_VERSION_MODEL(data[2]);
+
+	par->tcon_version = AUOK190X_VERSION_TCON(data[3]);
+	par->lut_version = AUOK190X_VERSION_LUT(data[3]);
+
+	dev_dbg(dev, "panel %d.%din, model 0x%x, EPD 0x%x TCON-rev 0x%x, LUT-rev 0x%x",
+		par->panel_size_int, par->panel_size_float, par->panel_model,
+		par->epd_type, par->tcon_version, par->lut_version);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
+/*
+ * Sysfs functions
+ */
+
+static ssize_t update_mode_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct auok190xfb_par *par = info->par;
+
+	return sprintf(buf, "%d\n", par->update_mode);
+}
+
+static ssize_t update_mode_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct auok190xfb_par *par = info->par;
+	int mode, ret;
+
+	ret = kstrtoint(buf, 10, &mode);
+	if (ret)
+		return ret;
+
+	par->update_mode = mode;
+
+	/* if we enter a better mode, do a full update */
+	if (par->last_mode > 1 && mode < par->last_mode)
+		par->update_all(par);
+
+	return count;
+}
+
+static ssize_t flash_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct auok190xfb_par *par = info->par;
+
+	return sprintf(buf, "%d\n", par->flash);
+}
+
+static ssize_t flash_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct auok190xfb_par *par = info->par;
+	int flash, ret;
+
+	ret = kstrtoint(buf, 10, &flash);
+	if (ret)
+		return ret;
+
+	if (flash > 0)
+		par->flash = 1;
+	else
+		par->flash = 0;
+
+	return count;
+}
+
+static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct auok190xfb_par *par = info->par;
+	int temp;
+
+	temp = auok190x_read_temperature(par);
+	return sprintf(buf, "%d\n", temp);
+}
+
+static DEVICE_ATTR(update_mode, 0644, update_mode_show, update_mode_store);
+static DEVICE_ATTR(flash, 0644, flash_show, flash_store);
+static DEVICE_ATTR(temp, 0644, temp_show, NULL);
+
+static struct attribute *auok190x_attributes[] = {
+	&dev_attr_update_mode.attr,
+	&dev_attr_flash.attr,
+	&dev_attr_temp.attr,
+	NULL
+};
+
+static const struct attribute_group auok190x_attr_group = {
+	.attrs		= auok190x_attributes,
+};
+
+static int auok190x_power(struct auok190xfb_par *par, bool on)
+{
+	struct auok190x_board *board = par->board;
+	int ret;
+
+	if (on) {
+		/* We should maintain POWER up for at least 80ms before set
+		 * RST_N and SLP_N to high (TCON spec 20100803_v35 p59)
+		 */
+		ret = regulator_enable(par->regulator);
+		if (ret)
+			return ret;
+
+		msleep(200);
+		gpio_set_value(board->gpio_nrst, 1);
+		gpio_set_value(board->gpio_nsleep, 1);
+		msleep(200);
+	} else {
+		regulator_disable(par->regulator);
+		gpio_set_value(board->gpio_nrst, 0);
+		gpio_set_value(board->gpio_nsleep, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * Recovery - powercycle the controller
+ */
+
+static void auok190x_recover(struct auok190xfb_par *par)
+{
+	struct device *dev = par->info->device;
+
+	auok190x_power(par, 0);
+	msleep(100);
+	auok190x_power(par, 1);
+
+	/* after powercycling the device, it's always active */
+	pm_runtime_set_active(dev);
+	par->standby = 0;
+
+	par->init(par);
+
+	/* wait for init to complete */
+	par->board->wait_for_rdy(par);
+}
+
+/*
+ * Power-management
+ */
+
+#ifdef CONFIG_PM
+static int auok190x_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct auok190xfb_par *par = info->par;
+	struct auok190x_board *board = par->board;
+	u16 standby_param;
+
+	/* take and keep the lock until we are resumed, as the controller
+	 * will never reach the non-busy state when in standby mode
+	 */
+	mutex_lock(&(par->io_lock));
+
+	if (par->standby) {
+		dev_warn(dev, "already in standby, runtime-pm pairing mismatch\n");
+		mutex_unlock(&(par->io_lock));
+		return 0;
+	}
+
+	/* according to runtime_pm.txt runtime_suspend only means, that the
+	 * device will not process data and will not communicate with the CPU
+	 * As we hold the lock, this stays true even without standby
+	 */
+	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+		dev_dbg(dev, "runtime suspend without standby\n");
+		goto finish;
+	} else if (board->quirks & AUOK190X_QUIRK_STANDBYPARAM) {
+		/* for some TCON versions STANDBY expects a parameter (0) but
+		 * it seems the real tcon version has to be determined yet.
+		 */
+		dev_dbg(dev, "runtime suspend with additional empty param\n");
+		standby_param = 0;
+		auok190x_send_cmdargs(par, AUOK190X_CMD_STANDBY, 1,
+				      &standby_param);
+	} else {
+		dev_dbg(dev, "runtime suspend without param\n");
+		auok190x_send_command(par, AUOK190X_CMD_STANDBY);
+	}
+
+	msleep(64);
+
+finish:
+	par->standby = 1;
+
+	return 0;
+}
+
+static int auok190x_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct auok190xfb_par *par = info->par;
+	struct auok190x_board *board = par->board;
+
+	if (!par->standby) {
+		dev_warn(dev, "not in standby, runtime-pm pairing mismatch\n");
+		return 0;
+	}
+
+	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+		dev_dbg(dev, "runtime resume without standby\n");
+	} else {
+		/* when in standby, controller is always busy
+		 * and only accepts the wakeup command
+		 */
+		dev_dbg(dev, "runtime resume from standby\n");
+		auok190x_send_command_nowait(par, AUOK190X_CMD_WAKEUP);
+
+		msleep(160);
+
+		/* wait for the controller to be ready and release the lock */
+		board->wait_for_rdy(par);
+	}
+
+	par->standby = 0;
+
+	mutex_unlock(&(par->io_lock));
+
+	return 0;
+}
+
+static int auok190x_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct auok190xfb_par *par = info->par;
+	struct auok190x_board *board = par->board;
+	int ret;
+
+	dev_dbg(dev, "suspend\n");
+	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+		/* suspend via powering off the ic */
+		dev_dbg(dev, "suspend with broken standby\n");
+
+		auok190x_power(par, 0);
+	} else {
+		dev_dbg(dev, "suspend using sleep\n");
+
+		/* the sleep state can only be entered from the standby state.
+		 * pm_runtime_get_noresume gets called before the suspend call.
+		 * So the devices usage count is >0 but it is not necessarily
+		 * active.
+		 */
+		if (!pm_runtime_status_suspended(dev)) {
+			ret = auok190x_runtime_suspend(dev);
+			if (ret < 0) {
+				dev_err(dev, "auok190x_runtime_suspend failed with %d\n",
+					ret);
+				return ret;
+			}
+			par->manual_standby = 1;
+		}
+
+		gpio_direction_output(board->gpio_nsleep, 0);
+	}
+
+	msleep(100);
+
+	return 0;
+}
+
+static int auok190x_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct auok190xfb_par *par = info->par;
+	struct auok190x_board *board = par->board;
+
+	dev_dbg(dev, "resume\n");
+	if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+		dev_dbg(dev, "resume with broken standby\n");
+
+		auok190x_power(par, 1);
+
+		par->init(par);
+	} else {
+		dev_dbg(dev, "resume from sleep\n");
+
+		/* device should be in runtime suspend when we were suspended
+		 * and pm_runtime_put_sync gets called after this function.
+		 * So there is no need to touch the standby mode here at all.
+		 */
+		gpio_direction_output(board->gpio_nsleep, 1);
+		msleep(100);
+
+		/* an additional init call seems to be necessary after sleep */
+		auok190x_runtime_resume(dev);
+		par->init(par);
+
+		/* if we were runtime-suspended before, suspend again*/
+		if (!par->manual_standby)
+			auok190x_runtime_suspend(dev);
+		else
+			par->manual_standby = 0;
+	}
+
+	return 0;
+}
+#endif
+
+const struct dev_pm_ops auok190x_pm = {
+	SET_RUNTIME_PM_OPS(auok190x_runtime_suspend, auok190x_runtime_resume,
+			   NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(auok190x_suspend, auok190x_resume)
+};
+EXPORT_SYMBOL_GPL(auok190x_pm);
+
+/*
+ * Common probe and remove code
+ */
+
+int auok190x_common_probe(struct platform_device *pdev,
+			  struct auok190x_init_data *init)
+{
+	struct auok190x_board *board = init->board;
+	struct auok190xfb_par *par;
+	struct fb_info *info;
+	struct panel_info *panel;
+	int videomemorysize, ret;
+	unsigned char *videomemory;
+
+	/* check board contents */
+	if (!board->init || !board->cleanup || !board->wait_for_rdy
+	    || !board->set_ctl || !board->set_hdb || !board->get_hdb
+	    || !board->setup_irq)
+		return -EINVAL;
+
+	info = framebuffer_alloc(sizeof(struct auok190xfb_par), &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	par = info->par;
+	par->info = info;
+	par->board = board;
+	par->recover = auok190x_recover;
+	par->update_partial = init->update_partial;
+	par->update_all = init->update_all;
+	par->need_refresh = init->need_refresh;
+	par->init = init->init;
+
+	/* init update modes */
+	par->update_cnt = 0;
+	par->update_mode = -1;
+	par->last_mode = -1;
+	par->flash = 0;
+
+	par->regulator = regulator_get(info->device, "vdd");
+	if (IS_ERR(par->regulator)) {
+		ret = PTR_ERR(par->regulator);
+		dev_err(info->device, "Failed to get regulator: %d\n", ret);
+		goto err_reg;
+	}
+
+	ret = board->init(par);
+	if (ret) {
+		dev_err(info->device, "board init failed, %d\n", ret);
+		goto err_board;
+	}
+
+	ret = gpio_request(board->gpio_nsleep, "AUOK190x sleep");
+	if (ret) {
+		dev_err(info->device, "could not request sleep gpio, %d\n",
+			ret);
+		goto err_gpio1;
+	}
+
+	ret = gpio_direction_output(board->gpio_nsleep, 0);
+	if (ret) {
+		dev_err(info->device, "could not set sleep gpio, %d\n", ret);
+		goto err_gpio2;
+	}
+
+	ret = gpio_request(board->gpio_nrst, "AUOK190x reset");
+	if (ret) {
+		dev_err(info->device, "could not request reset gpio, %d\n",
+			ret);
+		goto err_gpio2;
+	}
+
+	ret = gpio_direction_output(board->gpio_nrst, 0);
+	if (ret) {
+		dev_err(info->device, "could not set reset gpio, %d\n", ret);
+		goto err_gpio3;
+	}
+
+	ret = auok190x_power(par, 1);
+	if (ret) {
+		dev_err(info->device, "could not power on the device, %d\n",
+			ret);
+		goto err_gpio3;
+	}
+
+	mutex_init(&par->io_lock);
+
+	init_waitqueue_head(&par->waitq);
+
+	ret = par->board->setup_irq(par->info);
+	if (ret) {
+		dev_err(info->device, "could not setup ready-irq, %d\n", ret);
+		goto err_irq;
+	}
+
+	/* wait for init to complete */
+	par->board->wait_for_rdy(par);
+
+	/*
+	 * From here on the controller can talk to us
+	 */
+
+	/* initialise fix, var, resolution and rotation */
+
+	strlcpy(info->fix.id, init->id, 16);
+	info->var.bits_per_pixel = 8;
+	info->var.grayscale = 1;
+
+	panel = &panel_table[board->resolution];
+
+	par->resolution = board->resolution;
+	par->rotation = 0;
+
+	/* videomemory handling */
+
+	videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
+	videomemory = vmalloc(videomemorysize);
+	if (!videomemory) {
+		ret = -ENOMEM;
+		goto err_irq;
+	}
+
+	memset(videomemory, 0, videomemorysize);
+	info->screen_base = (char *)videomemory;
+	info->fix.smem_len = videomemorysize;
+
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+	info->fbops = &auok190xfb_ops;
+
+	ret = auok190xfb_check_var(&info->var, info);
+	if (ret)
+		goto err_defio;
+
+	auok190xfb_set_fix(info);
+
+	/* deferred io init */
+
+	info->fbdefio = devm_kzalloc(info->device,
+				     sizeof(struct fb_deferred_io),
+				     GFP_KERNEL);
+	if (!info->fbdefio) {
+		dev_err(info->device, "Failed to allocate memory\n");
+		ret = -ENOMEM;
+		goto err_defio;
+	}
+
+	dev_dbg(info->device, "targeting %d frames per second\n", board->fps);
+	info->fbdefio->delay = HZ / board->fps;
+	info->fbdefio->first_io = auok190xfb_dpy_first_io,
+	info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io,
+	fb_deferred_io_init(info);
+
+	/* color map */
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret < 0) {
+		dev_err(info->device, "Failed to allocate colormap\n");
+		goto err_cmap;
+	}
+
+	/* controller init */
+
+	par->consecutive_threshold = 100;
+	par->init(par);
+	auok190x_identify(par);
+
+	platform_set_drvdata(pdev, info);
+
+	ret = register_framebuffer(info);
+	if (ret < 0)
+		goto err_regfb;
+
+	ret = sysfs_create_group(&info->device->kobj, &auok190x_attr_group);
+	if (ret)
+		goto err_sysfs;
+
+	dev_info(info->device, "fb%d: %dx%d using %dK of video memory\n",
+		 info->node, info->var.xres, info->var.yres,
+		 videomemorysize >> 10);
+
+	/* increase autosuspend_delay when we use alternative methods
+	 * for runtime_pm
+	 */
+	par->autosuspend_delay = (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN)
+					? 1000 : 200;
+
+	pm_runtime_set_active(info->device);
+	pm_runtime_enable(info->device);
+	pm_runtime_set_autosuspend_delay(info->device, par->autosuspend_delay);
+	pm_runtime_use_autosuspend(info->device);
+
+	return 0;
+
+err_sysfs:
+	unregister_framebuffer(info);
+err_regfb:
+	fb_dealloc_cmap(&info->cmap);
+err_cmap:
+	fb_deferred_io_cleanup(info);
+err_defio:
+	vfree((void *)info->screen_base);
+err_irq:
+	auok190x_power(par, 0);
+err_gpio3:
+	gpio_free(board->gpio_nrst);
+err_gpio2:
+	gpio_free(board->gpio_nsleep);
+err_gpio1:
+	board->cleanup(par);
+err_board:
+	regulator_put(par->regulator);
+err_reg:
+	framebuffer_release(info);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(auok190x_common_probe);
+
+int  auok190x_common_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct auok190xfb_par *par = info->par;
+	struct auok190x_board *board = par->board;
+
+	pm_runtime_disable(info->device);
+
+	sysfs_remove_group(&info->device->kobj, &auok190x_attr_group);
+
+	unregister_framebuffer(info);
+
+	fb_dealloc_cmap(&info->cmap);
+
+	fb_deferred_io_cleanup(info);
+
+	vfree((void *)info->screen_base);
+
+	auok190x_power(par, 0);
+
+	gpio_free(board->gpio_nrst);
+	gpio_free(board->gpio_nsleep);
+
+	board->cleanup(par);
+
+	regulator_put(par->regulator);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_common_remove);
+
+MODULE_DESCRIPTION("Common code for AUO-K190X controllers");
+MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/auo_k190x.h b/drivers/video/fbdev/auo_k190x.h
new file mode 100644
index 000000000000..e35af1f51b28
--- /dev/null
+++ b/drivers/video/fbdev/auo_k190x.h
@@ -0,0 +1,129 @@
+/*
+ * Private common definitions for AUO-K190X framebuffer drivers
+ *
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * I80 interface specific defines
+ */
+
+#define AUOK190X_I80_CS			0x01
+#define AUOK190X_I80_DC			0x02
+#define AUOK190X_I80_WR			0x03
+#define AUOK190X_I80_OE			0x04
+
+/*
+ * AUOK190x commands, common to both controllers
+ */
+
+#define AUOK190X_CMD_INIT		0x0000
+#define AUOK190X_CMD_STANDBY		0x0001
+#define AUOK190X_CMD_WAKEUP		0x0002
+#define AUOK190X_CMD_TCON_RESET		0x0003
+#define AUOK190X_CMD_DATA_STOP		0x1002
+#define AUOK190X_CMD_LUT_START		0x1003
+#define AUOK190X_CMD_DISP_REFRESH	0x1004
+#define AUOK190X_CMD_DISP_RESET		0x1005
+#define AUOK190X_CMD_PRE_DISPLAY_START	0x100D
+#define AUOK190X_CMD_PRE_DISPLAY_STOP	0x100F
+#define AUOK190X_CMD_FLASH_W		0x2000
+#define AUOK190X_CMD_FLASH_E		0x2001
+#define AUOK190X_CMD_FLASH_STS		0x2002
+#define AUOK190X_CMD_FRAMERATE		0x3000
+#define AUOK190X_CMD_READ_VERSION	0x4000
+#define AUOK190X_CMD_READ_STATUS	0x4001
+#define AUOK190X_CMD_READ_LUT		0x4003
+#define AUOK190X_CMD_DRIVERTIMING	0x5000
+#define AUOK190X_CMD_LBALANCE		0x5001
+#define AUOK190X_CMD_AGINGMODE		0x6000
+#define AUOK190X_CMD_AGINGEXIT		0x6001
+
+/*
+ * Common settings for AUOK190X_CMD_INIT
+ */
+
+#define AUOK190X_INIT_DATA_FILTER	(0 << 12)
+#define AUOK190X_INIT_DATA_BYPASS	(1 << 12)
+#define AUOK190X_INIT_INVERSE_WHITE	(0 << 9)
+#define AUOK190X_INIT_INVERSE_BLACK	(1 << 9)
+#define AUOK190X_INIT_SCAN_DOWN		(0 << 1)
+#define AUOK190X_INIT_SCAN_UP		(1 << 1)
+#define AUOK190X_INIT_SHIFT_LEFT	(0 << 0)
+#define AUOK190X_INIT_SHIFT_RIGHT	(1 << 0)
+
+/* Common bits to pixels
+ *   Mode	15-12	11-8	7-4	3-0
+ *   format0	4	3	2	1
+ *   format1	3	4	1	2
+ */
+
+#define AUOK190X_INIT_FORMAT0		0
+#define AUOK190X_INIT_FORMAT1		(1 << 6)
+
+/*
+ * settings for AUOK190X_CMD_RESET
+ */
+
+#define AUOK190X_RESET_TCON		(0 << 0)
+#define AUOK190X_RESET_NORMAL		(1 << 0)
+#define AUOK190X_RESET_PON		(1 << 1)
+
+/*
+ * AUOK190X_CMD_VERSION
+ */
+
+#define AUOK190X_VERSION_TEMP_MASK		(0x1ff)
+#define AUOK190X_VERSION_EPD_MASK		(0xff)
+#define AUOK190X_VERSION_SIZE_INT(_val)		((_val & 0xfc00) >> 10)
+#define AUOK190X_VERSION_SIZE_FLOAT(_val)	((_val & 0x3c0) >> 6)
+#define AUOK190X_VERSION_MODEL(_val)		(_val & 0x3f)
+#define AUOK190X_VERSION_LUT(_val)		(_val & 0xff)
+#define AUOK190X_VERSION_TCON(_val)		((_val & 0xff00) >> 8)
+
+/*
+ * update modes for CMD_PARTIALDISP on K1900 and CMD_DDMA on K1901
+ */
+
+#define AUOK190X_UPDATE_MODE(_res)		((_res & 0x7) << 12)
+#define AUOK190X_UPDATE_NONFLASH		(1 << 15)
+
+/*
+ * track panel specific parameters for common init
+ */
+
+struct auok190x_init_data {
+	char *id;
+	struct auok190x_board *board;
+
+	void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
+	void (*update_all)(struct auok190xfb_par *par);
+	bool (*need_refresh)(struct auok190xfb_par *par);
+	void (*init)(struct auok190xfb_par *par);
+};
+
+
+extern void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data);
+extern int auok190x_send_command(struct auok190xfb_par *par, u16 data);
+extern void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
+					 int argc, u16 *argv);
+extern int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
+				  int argc, u16 *argv);
+extern void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par,
+						u16 cmd, int argc, u16 *argv,
+						int size, u16 *data);
+extern int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
+					int argc, u16 *argv, int size,
+					u16 *data);
+extern int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
+				  int argc, u16 *argv);
+
+extern int auok190x_common_probe(struct platform_device *pdev,
+				 struct auok190x_init_data *init);
+extern int auok190x_common_remove(struct platform_device *pdev);
+
+extern const struct dev_pm_ops auok190x_pm;
diff --git a/drivers/video/fbdev/bf537-lq035.c b/drivers/video/fbdev/bf537-lq035.c
new file mode 100644
index 000000000000..a82d2578d976
--- /dev/null
+++ b/drivers/video/fbdev/bf537-lq035.c
@@ -0,0 +1,915 @@
+/*
+ * Analog Devices Blackfin(BF537 STAMP) + SHARP TFT LCD.
+ * http://docs.blackfin.uclinux.org/doku.php?id=hw:cards:tft-lcd
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ * Licensed under the GPL-2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/i2c.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dpmc.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define NO_BL 1
+
+#define MAX_BRIGHENESS	95
+#define MIN_BRIGHENESS	5
+#define NBR_PALETTE	256
+
+static const unsigned short ppi_pins[] = {
+	P_PPI0_CLK, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 0
+};
+
+static unsigned char *fb_buffer;          /* RGB Buffer */
+static unsigned long *dma_desc_table;
+static int t_conf_done, lq035_open_cnt;
+static DEFINE_SPINLOCK(bfin_lq035_lock);
+
+static int landscape;
+module_param(landscape, int, 0);
+MODULE_PARM_DESC(landscape,
+	"LANDSCAPE use 320x240 instead of Native 240x320 Resolution");
+
+static int bgr;
+module_param(bgr, int, 0);
+MODULE_PARM_DESC(bgr,
+	"BGR use 16-bit BGR-565 instead of RGB-565");
+
+static int nocursor = 1;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+static unsigned long current_brightness;  /* backlight */
+
+/* AD5280 vcomm */
+static unsigned char vcomm_value = 150;
+static struct i2c_client *ad5280_client;
+
+static void set_vcomm(void)
+{
+	int nr;
+
+	if (!ad5280_client)
+		return;
+
+	nr = i2c_smbus_write_byte_data(ad5280_client, 0x00, vcomm_value);
+	if (nr)
+		pr_err("i2c_smbus_write_byte_data fail: %d\n", nr);
+}
+
+static int ad5280_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+		return -EIO;
+	}
+
+	ret = i2c_smbus_write_byte_data(client, 0x00, vcomm_value);
+	if (ret) {
+		dev_err(&client->dev, "write fail: %d\n", ret);
+		return ret;
+	}
+
+	ad5280_client = client;
+
+	return 0;
+}
+
+static int ad5280_remove(struct i2c_client *client)
+{
+	ad5280_client = NULL;
+	return 0;
+}
+
+static const struct i2c_device_id ad5280_id[] = {
+	{"bf537-lq035-ad5280", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad5280_id);
+
+static struct i2c_driver ad5280_driver = {
+	.driver = {
+		.name = "bf537-lq035-ad5280",
+	},
+	.probe = ad5280_probe,
+	.remove = ad5280_remove,
+	.id_table = ad5280_id,
+};
+
+#ifdef CONFIG_PNAV10
+#define MOD GPIO_PH13
+
+#define bfin_write_TIMER_LP_CONFIG	bfin_write_TIMER0_CONFIG
+#define bfin_write_TIMER_LP_WIDTH	bfin_write_TIMER0_WIDTH
+#define bfin_write_TIMER_LP_PERIOD	bfin_write_TIMER0_PERIOD
+#define bfin_read_TIMER_LP_COUNTER	bfin_read_TIMER0_COUNTER
+#define TIMDIS_LP			TIMDIS0
+#define TIMEN_LP			TIMEN0
+
+#define bfin_write_TIMER_SPS_CONFIG	bfin_write_TIMER1_CONFIG
+#define bfin_write_TIMER_SPS_WIDTH	bfin_write_TIMER1_WIDTH
+#define bfin_write_TIMER_SPS_PERIOD	bfin_write_TIMER1_PERIOD
+#define TIMDIS_SPS			TIMDIS1
+#define TIMEN_SPS			TIMEN1
+
+#define bfin_write_TIMER_SP_CONFIG	bfin_write_TIMER5_CONFIG
+#define bfin_write_TIMER_SP_WIDTH	bfin_write_TIMER5_WIDTH
+#define bfin_write_TIMER_SP_PERIOD	bfin_write_TIMER5_PERIOD
+#define TIMDIS_SP			TIMDIS5
+#define TIMEN_SP			TIMEN5
+
+#define bfin_write_TIMER_PS_CLS_CONFIG	bfin_write_TIMER2_CONFIG
+#define bfin_write_TIMER_PS_CLS_WIDTH	bfin_write_TIMER2_WIDTH
+#define bfin_write_TIMER_PS_CLS_PERIOD	bfin_write_TIMER2_PERIOD
+#define TIMDIS_PS_CLS			TIMDIS2
+#define TIMEN_PS_CLS			TIMEN2
+
+#define bfin_write_TIMER_REV_CONFIG	bfin_write_TIMER3_CONFIG
+#define bfin_write_TIMER_REV_WIDTH	bfin_write_TIMER3_WIDTH
+#define bfin_write_TIMER_REV_PERIOD	bfin_write_TIMER3_PERIOD
+#define TIMDIS_REV			TIMDIS3
+#define TIMEN_REV			TIMEN3
+#define bfin_read_TIMER_REV_COUNTER	bfin_read_TIMER3_COUNTER
+
+#define	FREQ_PPI_CLK         (5*1024*1024)  /* PPI_CLK 5MHz */
+
+#define TIMERS {P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR5, 0}
+
+#else
+
+#define UD      GPIO_PF13	/* Up / Down */
+#define MOD     GPIO_PF10
+#define LBR     GPIO_PF14	/* Left Right */
+
+#define bfin_write_TIMER_LP_CONFIG	bfin_write_TIMER6_CONFIG
+#define bfin_write_TIMER_LP_WIDTH	bfin_write_TIMER6_WIDTH
+#define bfin_write_TIMER_LP_PERIOD	bfin_write_TIMER6_PERIOD
+#define bfin_read_TIMER_LP_COUNTER	bfin_read_TIMER6_COUNTER
+#define TIMDIS_LP			TIMDIS6
+#define TIMEN_LP			TIMEN6
+
+#define bfin_write_TIMER_SPS_CONFIG	bfin_write_TIMER1_CONFIG
+#define bfin_write_TIMER_SPS_WIDTH	bfin_write_TIMER1_WIDTH
+#define bfin_write_TIMER_SPS_PERIOD	bfin_write_TIMER1_PERIOD
+#define TIMDIS_SPS			TIMDIS1
+#define TIMEN_SPS			TIMEN1
+
+#define bfin_write_TIMER_SP_CONFIG	bfin_write_TIMER0_CONFIG
+#define bfin_write_TIMER_SP_WIDTH	bfin_write_TIMER0_WIDTH
+#define bfin_write_TIMER_SP_PERIOD	bfin_write_TIMER0_PERIOD
+#define TIMDIS_SP			TIMDIS0
+#define TIMEN_SP			TIMEN0
+
+#define bfin_write_TIMER_PS_CLS_CONFIG	bfin_write_TIMER7_CONFIG
+#define bfin_write_TIMER_PS_CLS_WIDTH	bfin_write_TIMER7_WIDTH
+#define bfin_write_TIMER_PS_CLS_PERIOD	bfin_write_TIMER7_PERIOD
+#define TIMDIS_PS_CLS			TIMDIS7
+#define TIMEN_PS_CLS			TIMEN7
+
+#define bfin_write_TIMER_REV_CONFIG	bfin_write_TIMER5_CONFIG
+#define bfin_write_TIMER_REV_WIDTH	bfin_write_TIMER5_WIDTH
+#define bfin_write_TIMER_REV_PERIOD	bfin_write_TIMER5_PERIOD
+#define TIMDIS_REV			TIMDIS5
+#define TIMEN_REV			TIMEN5
+#define bfin_read_TIMER_REV_COUNTER	bfin_read_TIMER5_COUNTER
+
+#define	FREQ_PPI_CLK         (6*1000*1000)  /* PPI_CLK 6MHz */
+#define TIMERS {P_TMR0, P_TMR1, P_TMR5, P_TMR6, P_TMR7, 0}
+
+#endif
+
+#define LCD_X_RES			240 /* Horizontal Resolution */
+#define LCD_Y_RES			320 /* Vertical Resolution */
+
+#define LCD_BBP				16  /* Bit Per Pixel */
+
+/* the LCD and the DMA start counting differently;
+ * since one starts at 0 and the other starts at 1,
+ * we have a difference of 1 between START_LINES
+ * and U_LINES.
+ */
+#define START_LINES       8   /* lines for field flyback or field blanking signal */
+#define U_LINES           9   /* number of undisplayed blanking lines */
+
+#define FRAMES_PER_SEC    (60)
+
+#define DCLKS_PER_FRAME   (FREQ_PPI_CLK/FRAMES_PER_SEC)
+#define DCLKS_PER_LINE    (DCLKS_PER_FRAME/(LCD_Y_RES+U_LINES))
+
+#define PPI_CONFIG_VALUE  (PORT_DIR|XFR_TYPE|DLEN_16|POLS)
+#define PPI_DELAY_VALUE   (0)
+#define TIMER_CONFIG      (PWM_OUT|PERIOD_CNT|TIN_SEL|CLK_SEL)
+
+#define ACTIVE_VIDEO_MEM_OFFSET	(LCD_X_RES*START_LINES*(LCD_BBP/8))
+#define ACTIVE_VIDEO_MEM_SIZE	(LCD_Y_RES*LCD_X_RES*(LCD_BBP/8))
+#define TOTAL_VIDEO_MEM_SIZE	((LCD_Y_RES+U_LINES)*LCD_X_RES*(LCD_BBP/8))
+#define TOTAL_DMA_DESC_SIZE	(2 * sizeof(u32) * (LCD_Y_RES + U_LINES))
+
+static void start_timers(void) /* CHECK with HW */
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	bfin_write_TIMER_ENABLE(TIMEN_REV);
+	SSYNC();
+
+	while (bfin_read_TIMER_REV_COUNTER() <= 11)
+		continue;
+	bfin_write_TIMER_ENABLE(TIMEN_LP);
+	SSYNC();
+
+	while (bfin_read_TIMER_LP_COUNTER() < 3)
+		continue;
+	bfin_write_TIMER_ENABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS);
+	SSYNC();
+	t_conf_done = 1;
+	local_irq_restore(flags);
+}
+
+static void config_timers(void)
+{
+	/* Stop timers */
+	bfin_write_TIMER_DISABLE(TIMDIS_SP|TIMDIS_SPS|TIMDIS_REV|
+				 TIMDIS_LP|TIMDIS_PS_CLS);
+	SSYNC();
+
+	/* LP, timer 6 */
+	bfin_write_TIMER_LP_CONFIG(TIMER_CONFIG|PULSE_HI);
+	bfin_write_TIMER_LP_WIDTH(1);
+
+	bfin_write_TIMER_LP_PERIOD(DCLKS_PER_LINE);
+	SSYNC();
+
+	/* SPS, timer 1 */
+	bfin_write_TIMER_SPS_CONFIG(TIMER_CONFIG|PULSE_HI);
+	bfin_write_TIMER_SPS_WIDTH(DCLKS_PER_LINE*2);
+	bfin_write_TIMER_SPS_PERIOD((DCLKS_PER_LINE * (LCD_Y_RES+U_LINES)));
+	SSYNC();
+
+	/* SP, timer 0 */
+	bfin_write_TIMER_SP_CONFIG(TIMER_CONFIG|PULSE_HI);
+	bfin_write_TIMER_SP_WIDTH(1);
+	bfin_write_TIMER_SP_PERIOD(DCLKS_PER_LINE);
+	SSYNC();
+
+	/* PS & CLS, timer 7 */
+	bfin_write_TIMER_PS_CLS_CONFIG(TIMER_CONFIG);
+	bfin_write_TIMER_PS_CLS_WIDTH(LCD_X_RES + START_LINES);
+	bfin_write_TIMER_PS_CLS_PERIOD(DCLKS_PER_LINE);
+
+	SSYNC();
+
+#ifdef NO_BL
+	/* REV, timer 5 */
+	bfin_write_TIMER_REV_CONFIG(TIMER_CONFIG|PULSE_HI);
+
+	bfin_write_TIMER_REV_WIDTH(DCLKS_PER_LINE);
+	bfin_write_TIMER_REV_PERIOD(DCLKS_PER_LINE*2);
+
+	SSYNC();
+#endif
+}
+
+static void config_ppi(void)
+{
+	bfin_write_PPI_DELAY(PPI_DELAY_VALUE);
+	bfin_write_PPI_COUNT(LCD_X_RES-1);
+	/* 0x10 -> PORT_CFG -> 2 or 3 frame syncs */
+	bfin_write_PPI_CONTROL((PPI_CONFIG_VALUE|0x10) & (~POLS));
+}
+
+static int config_dma(void)
+{
+	u32 i;
+
+	if (landscape) {
+
+		for (i = 0; i < U_LINES; ++i) {
+			/* blanking lines point to first line of fb_buffer */
+			dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
+			dma_desc_table[2*i+1] = (unsigned long)fb_buffer;
+		}
+
+		for (i = U_LINES; i < U_LINES + LCD_Y_RES; ++i) {
+			/* visible lines */
+			dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
+			dma_desc_table[2*i+1] = (unsigned long)fb_buffer +
+						(LCD_Y_RES+U_LINES-1-i)*2;
+		}
+
+		/* last descriptor points to first */
+		dma_desc_table[2*(LCD_Y_RES+U_LINES-1)] = (unsigned long)&dma_desc_table[0];
+
+		set_dma_x_count(CH_PPI, LCD_X_RES);
+		set_dma_x_modify(CH_PPI, LCD_Y_RES * (LCD_BBP / 8));
+		set_dma_y_count(CH_PPI, 0);
+		set_dma_y_modify(CH_PPI, 0);
+		set_dma_next_desc_addr(CH_PPI, (void *)dma_desc_table[0]);
+		set_dma_config(CH_PPI, DMAFLOW_LARGE | NDSIZE_4 | WDSIZE_16);
+
+	} else {
+
+		set_dma_config(CH_PPI, set_bfin_dma_config(DIR_READ,
+				DMA_FLOW_AUTO,
+				INTR_DISABLE,
+				DIMENSION_2D,
+				DATA_SIZE_16,
+				DMA_NOSYNC_KEEP_DMA_BUF));
+		set_dma_x_count(CH_PPI, LCD_X_RES);
+		set_dma_x_modify(CH_PPI, LCD_BBP / 8);
+		set_dma_y_count(CH_PPI, LCD_Y_RES+U_LINES);
+		set_dma_y_modify(CH_PPI, LCD_BBP / 8);
+		set_dma_start_addr(CH_PPI, (unsigned long) fb_buffer);
+	}
+
+	return 0;
+}
+
+static int request_ports(void)
+{
+	u16 tmr_req[] = TIMERS;
+
+	/*
+		UD:      PF13
+		MOD:     PF10
+		LBR:     PF14
+		PPI_CLK: PF15
+	*/
+
+	if (peripheral_request_list(ppi_pins, KBUILD_MODNAME)) {
+		pr_err("requesting PPI peripheral failed\n");
+		return -EBUSY;
+	}
+
+	if (peripheral_request_list(tmr_req, KBUILD_MODNAME)) {
+		peripheral_free_list(ppi_pins);
+		pr_err("requesting timer peripheral failed\n");
+		return -EBUSY;
+	}
+
+#if (defined(UD) && defined(LBR))
+	if (gpio_request_one(UD, GPIOF_OUT_INIT_LOW, KBUILD_MODNAME)) {
+		pr_err("requesting GPIO %d failed\n", UD);
+		return -EBUSY;
+	}
+
+	if (gpio_request_one(LBR, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
+		pr_err("requesting GPIO %d failed\n", LBR);
+		gpio_free(UD);
+		return -EBUSY;
+	}
+#endif
+
+	if (gpio_request_one(MOD, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
+		pr_err("requesting GPIO %d failed\n", MOD);
+#if (defined(UD) && defined(LBR))
+		gpio_free(LBR);
+		gpio_free(UD);
+#endif
+		return -EBUSY;
+	}
+
+	SSYNC();
+	return 0;
+}
+
+static void free_ports(void)
+{
+	u16 tmr_req[] = TIMERS;
+
+	peripheral_free_list(ppi_pins);
+	peripheral_free_list(tmr_req);
+
+#if defined(UD) && defined(LBR)
+	gpio_free(LBR);
+	gpio_free(UD);
+#endif
+	gpio_free(MOD);
+}
+
+static struct fb_info bfin_lq035_fb;
+
+static struct fb_var_screeninfo bfin_lq035_fb_defined = {
+	.bits_per_pixel		= LCD_BBP,
+	.activate		= FB_ACTIVATE_TEST,
+	.xres			= LCD_X_RES,	/*default portrait mode RGB*/
+	.yres			= LCD_Y_RES,
+	.xres_virtual		= LCD_X_RES,
+	.yres_virtual		= LCD_Y_RES,
+	.height			= -1,
+	.width			= -1,
+	.left_margin		= 0,
+	.right_margin		= 0,
+	.upper_margin		= 0,
+	.lower_margin		= 0,
+	.red			= {11, 5, 0},
+	.green			= {5, 6, 0},
+	.blue			= {0, 5, 0},
+	.transp		= {0, 0, 0},
+};
+
+static struct fb_fix_screeninfo bfin_lq035_fb_fix = {
+	.id		= KBUILD_MODNAME,
+	.smem_len	= ACTIVE_VIDEO_MEM_SIZE,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.line_length	= LCD_X_RES*(LCD_BBP/8),
+	.accel		= FB_ACCEL_NONE,
+};
+
+
+static int bfin_lq035_fb_open(struct fb_info *info, int user)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bfin_lq035_lock, flags);
+	lq035_open_cnt++;
+	spin_unlock_irqrestore(&bfin_lq035_lock, flags);
+
+	if (lq035_open_cnt <= 1) {
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+
+		set_vcomm();
+		config_dma();
+		config_ppi();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		SSYNC();
+		bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+		SSYNC();
+
+		if (!t_conf_done) {
+			config_timers();
+			start_timers();
+		}
+		/* gpio_set_value(MOD,1); */
+	}
+
+	return 0;
+}
+
+static int bfin_lq035_fb_release(struct fb_info *info, int user)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bfin_lq035_lock, flags);
+	lq035_open_cnt--;
+	spin_unlock_irqrestore(&bfin_lq035_lock, flags);
+
+
+	if (lq035_open_cnt <= 0) {
+
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+
+		disable_dma(CH_PPI);
+	}
+
+	return 0;
+}
+
+
+static int bfin_lq035_fb_check_var(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
+{
+	switch (var->bits_per_pixel) {
+	case 16:/* DIRECTCOLOUR, 64k */
+		var->red.offset = info->var.red.offset;
+		var->green.offset = info->var.green.offset;
+		var->blue.offset = info->var.blue.offset;
+		var->red.length = info->var.red.length;
+		var->green.length = info->var.green.length;
+		var->blue.length = info->var.blue.length;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		break;
+	default:
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres ||
+	    info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u\n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/* fb_rotate
+ * Rotate the display of this angle. This doesn't seems to be used by the core,
+ * but as our hardware supports it, so why not implementing it...
+ */
+static void bfin_lq035_fb_rotate(struct fb_info *fbi, int angle)
+{
+	pr_debug("%s: %p %d", __func__, fbi, angle);
+#if (defined(UD) && defined(LBR))
+	switch (angle) {
+
+	case 180:
+		gpio_set_value(LBR, 0);
+		gpio_set_value(UD, 1);
+		break;
+	default:
+		gpio_set_value(LBR, 1);
+		gpio_set_value(UD, 0);
+		break;
+	}
+#endif
+}
+
+static int bfin_lq035_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_lq035_fb_setcolreg(u_int regno, u_int red, u_int green,
+				   u_int blue, u_int transp,
+				   struct fb_info *info)
+{
+	if (regno >= NBR_PALETTE)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red   >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue  >>= (16 - info->var.blue.length);
+
+		value = (red   << info->var.red.offset) |
+			(green << info->var.green.offset)|
+			(blue  << info->var.blue.offset);
+		value &= 0xFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+
+	}
+
+	return 0;
+}
+
+static struct fb_ops bfin_lq035_fb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_open		= bfin_lq035_fb_open,
+	.fb_release		= bfin_lq035_fb_release,
+	.fb_check_var		= bfin_lq035_fb_check_var,
+	.fb_rotate		= bfin_lq035_fb_rotate,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_cursor		= bfin_lq035_fb_cursor,
+	.fb_setcolreg		= bfin_lq035_fb_setcolreg,
+};
+
+static int bl_get_brightness(struct backlight_device *bd)
+{
+	return current_brightness;
+}
+
+static const struct backlight_ops bfin_lq035fb_bl_ops = {
+	.get_brightness	= bl_get_brightness,
+};
+
+static struct backlight_device *bl_dev;
+
+static int bfin_lcd_get_power(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_power(struct lcd_device *dev, int power)
+{
+	return 0;
+}
+
+static int bfin_lcd_get_contrast(struct lcd_device *dev)
+{
+	return (int)vcomm_value;
+}
+
+static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
+{
+	if (contrast > 255)
+		contrast = 255;
+	if (contrast < 0)
+		contrast = 0;
+
+	vcomm_value = (unsigned char)contrast;
+	set_vcomm();
+	return 0;
+}
+
+static int bfin_lcd_check_fb(struct lcd_device *lcd, struct fb_info *fi)
+{
+	if (!fi || (fi == &bfin_lq035_fb))
+		return 1;
+	return 0;
+}
+
+static struct lcd_ops bfin_lcd_ops = {
+	.get_power	= bfin_lcd_get_power,
+	.set_power	= bfin_lcd_set_power,
+	.get_contrast	= bfin_lcd_get_contrast,
+	.set_contrast	= bfin_lcd_set_contrast,
+	.check_fb	= bfin_lcd_check_fb,
+};
+
+static struct lcd_device *lcd_dev;
+
+static int bfin_lq035_probe(struct platform_device *pdev)
+{
+	struct backlight_properties props;
+	dma_addr_t dma_handle;
+	int ret;
+
+	if (request_dma(CH_PPI, KBUILD_MODNAME)) {
+		pr_err("couldn't request PPI DMA\n");
+		return -EFAULT;
+	}
+
+	if (request_ports()) {
+		pr_err("couldn't request gpio port\n");
+		ret = -EFAULT;
+		goto out_ports;
+	}
+
+	fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE,
+				       &dma_handle, GFP_KERNEL);
+	if (fb_buffer == NULL) {
+		pr_err("couldn't allocate dma buffer\n");
+		ret = -ENOMEM;
+		goto out_dma_coherent;
+	}
+
+	if (L1_DATA_A_LENGTH)
+		dma_desc_table = l1_data_sram_zalloc(TOTAL_DMA_DESC_SIZE);
+	else
+		dma_desc_table = dma_alloc_coherent(NULL, TOTAL_DMA_DESC_SIZE,
+						    &dma_handle, 0);
+
+	if (dma_desc_table == NULL) {
+		pr_err("couldn't allocate dma descriptor\n");
+		ret = -ENOMEM;
+		goto out_table;
+	}
+
+	bfin_lq035_fb.screen_base = (void *)fb_buffer;
+	bfin_lq035_fb_fix.smem_start = (int)fb_buffer;
+	if (landscape) {
+		bfin_lq035_fb_defined.xres = LCD_Y_RES;
+		bfin_lq035_fb_defined.yres = LCD_X_RES;
+		bfin_lq035_fb_defined.xres_virtual = LCD_Y_RES;
+		bfin_lq035_fb_defined.yres_virtual = LCD_X_RES;
+
+		bfin_lq035_fb_fix.line_length = LCD_Y_RES*(LCD_BBP/8);
+	} else {
+		bfin_lq035_fb.screen_base += ACTIVE_VIDEO_MEM_OFFSET;
+		bfin_lq035_fb_fix.smem_start += ACTIVE_VIDEO_MEM_OFFSET;
+	}
+
+	bfin_lq035_fb_defined.green.msb_right = 0;
+	bfin_lq035_fb_defined.red.msb_right   = 0;
+	bfin_lq035_fb_defined.blue.msb_right  = 0;
+	bfin_lq035_fb_defined.green.offset    = 5;
+	bfin_lq035_fb_defined.green.length    = 6;
+	bfin_lq035_fb_defined.red.length      = 5;
+	bfin_lq035_fb_defined.blue.length     = 5;
+
+	if (bgr) {
+		bfin_lq035_fb_defined.red.offset  = 0;
+		bfin_lq035_fb_defined.blue.offset = 11;
+	} else {
+		bfin_lq035_fb_defined.red.offset  = 11;
+		bfin_lq035_fb_defined.blue.offset = 0;
+	}
+
+	bfin_lq035_fb.fbops = &bfin_lq035_fb_ops;
+	bfin_lq035_fb.var = bfin_lq035_fb_defined;
+
+	bfin_lq035_fb.fix = bfin_lq035_fb_fix;
+	bfin_lq035_fb.flags = FBINFO_DEFAULT;
+
+
+	bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev,
+						    sizeof(u32) * 16,
+						    GFP_KERNEL);
+	if (bfin_lq035_fb.pseudo_palette == NULL) {
+		pr_err("failed to allocate pseudo_palette\n");
+		ret = -ENOMEM;
+		goto out_table;
+	}
+
+	if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
+		pr_err("failed to allocate colormap (%d entries)\n",
+			NBR_PALETTE);
+		ret = -EFAULT;
+		goto out_table;
+	}
+
+	if (register_framebuffer(&bfin_lq035_fb) < 0) {
+		pr_err("unable to register framebuffer\n");
+		ret = -EINVAL;
+		goto out_reg;
+	}
+
+	i2c_add_driver(&ad5280_driver);
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = MAX_BRIGHENESS;
+	bl_dev = backlight_device_register("bf537-bl", NULL, NULL,
+					   &bfin_lq035fb_bl_ops, &props);
+
+	lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL,
+				      &bfin_lcd_ops);
+	if (IS_ERR(lcd_dev)) {
+		pr_err("unable to register lcd\n");
+		ret = PTR_ERR(lcd_dev);
+		goto out_lcd;
+	}
+	lcd_dev->props.max_contrast = 255,
+
+	pr_info("initialized");
+
+	return 0;
+out_lcd:
+	unregister_framebuffer(&bfin_lq035_fb);
+out_reg:
+	fb_dealloc_cmap(&bfin_lq035_fb.cmap);
+out_table:
+	dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+	fb_buffer = NULL;
+out_dma_coherent:
+	free_ports();
+out_ports:
+	free_dma(CH_PPI);
+	return ret;
+}
+
+static int bfin_lq035_remove(struct platform_device *pdev)
+{
+	if (fb_buffer != NULL)
+		dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+
+	if (L1_DATA_A_LENGTH)
+		l1_data_sram_free(dma_desc_table);
+	else
+		dma_free_coherent(NULL, TOTAL_DMA_DESC_SIZE, NULL, 0);
+
+	bfin_write_TIMER_DISABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS|
+				 TIMEN_LP|TIMEN_REV);
+	t_conf_done = 0;
+
+	free_dma(CH_PPI);
+
+
+	fb_dealloc_cmap(&bfin_lq035_fb.cmap);
+
+
+	lcd_device_unregister(lcd_dev);
+	backlight_device_unregister(bl_dev);
+
+	unregister_framebuffer(&bfin_lq035_fb);
+	i2c_del_driver(&ad5280_driver);
+
+	free_ports();
+
+	pr_info("unregistered LCD driver\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_lq035_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (lq035_open_cnt > 0) {
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+		disable_dma(CH_PPI);
+	}
+
+	return 0;
+}
+
+static int bfin_lq035_resume(struct platform_device *pdev)
+{
+	if (lq035_open_cnt > 0) {
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+
+		config_dma();
+		config_ppi();
+
+		enable_dma(CH_PPI);
+		bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+		SSYNC();
+
+		config_timers();
+		start_timers();
+	} else {
+		t_conf_done = 0;
+	}
+
+	return 0;
+}
+#else
+# define bfin_lq035_suspend	NULL
+# define bfin_lq035_resume	NULL
+#endif
+
+static struct platform_driver bfin_lq035_driver = {
+	.probe = bfin_lq035_probe,
+	.remove = bfin_lq035_remove,
+	.suspend = bfin_lq035_suspend,
+	.resume = bfin_lq035_resume,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init bfin_lq035_driver_init(void)
+{
+	request_module("i2c-bfin-twi");
+	return platform_driver_register(&bfin_lq035_driver);
+}
+module_init(bfin_lq035_driver_init);
+
+static void __exit bfin_lq035_driver_cleanup(void)
+{
+	platform_driver_unregister(&bfin_lq035_driver);
+}
+module_exit(bfin_lq035_driver_cleanup);
+
+MODULE_DESCRIPTION("SHARP LQ035Q7DB03 TFT LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/bf54x-lq043fb.c b/drivers/video/fbdev/bf54x-lq043fb.c
new file mode 100644
index 000000000000..e2c42ad8515a
--- /dev/null
+++ b/drivers/video/fbdev/bf54x-lq043fb.c
@@ -0,0 +1,767 @@
+/*
+ * File:         drivers/video/bf54x-lq043.c
+ * Based on:
+ * Author:       Michael Hennerich <hennerich@blackfin.uclinux.org>
+ *
+ * Created:
+ * Description:  ADSP-BF54x Framebuffer driver
+ *
+ *
+ * Modified:
+ *               Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dpmc.h>
+#include <asm/dma-mapping.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#include <mach/bf54x-lq043.h>
+
+#define NO_BL_SUPPORT
+
+#define DRIVER_NAME "bf54x-lq043"
+static char driver_name[] = DRIVER_NAME;
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
+
+#define EPPI0_18 {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, \
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, \
+ P_PPI0_D11, P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, P_PPI0_D16, P_PPI0_D17, 0}
+
+#define EPPI0_24 {P_PPI0_D18, P_PPI0_D19, P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, 0}
+
+struct bfin_bf54xfb_info {
+	struct fb_info *fb;
+	struct device *dev;
+
+	struct bfin_bf54xfb_mach_info *mach_info;
+
+	unsigned char *fb_buffer;	/* RGB Buffer */
+
+	dma_addr_t dma_handle;
+	int lq043_open_cnt;
+	int irq;
+	spinlock_t lock;	/* lock */
+};
+
+static int nocursor;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+static int outp_rgb666;
+module_param(outp_rgb666, int, 0);
+MODULE_PARM_DESC(outp_rgb666, "Output 18-bit RGB666");
+
+#define LCD_X_RES		480	/*Horizontal Resolution */
+#define LCD_Y_RES		272	/* Vertical Resolution */
+
+#define LCD_BPP			24	/* Bit Per Pixel */
+#define	DMA_BUS_SIZE		32
+
+/* 	-- Horizontal synchronizing --
+ *
+ * Timing characteristics taken from the SHARP LQ043T1DG01 datasheet
+ * (LCY-W-06602A Page 9 of 22)
+ *
+ * Clock Frequency 	1/Tc Min 7.83 Typ 9.00 Max 9.26 MHz
+ *
+ * Period 		TH - 525 - Clock
+ * Pulse width 		THp - 41 - Clock
+ * Horizontal period 	THd - 480 - Clock
+ * Back porch 		THb - 2 - Clock
+ * Front porch 		THf - 2 - Clock
+ *
+ * -- Vertical synchronizing --
+ * Period 		TV - 286 - Line
+ * Pulse width 		TVp - 10 - Line
+ * Vertical period 	TVd - 272 - Line
+ * Back porch 		TVb - 2 - Line
+ * Front porch 		TVf - 2 - Line
+ */
+
+#define	LCD_CLK         	(8*1000*1000)	/* 8MHz */
+
+/* # active data to transfer after Horizontal Delay clock */
+#define EPPI_HCOUNT		LCD_X_RES
+
+/* # active lines to transfer after Vertical Delay clock */
+#define EPPI_VCOUNT		LCD_Y_RES
+
+/* Samples per Line = 480 (active data) + 45 (padding) */
+#define EPPI_LINE		525
+
+/* Lines per Frame = 272 (active data) + 14 (padding) */
+#define EPPI_FRAME		286
+
+/* FS1 (Hsync) Width (Typical)*/
+#define EPPI_FS1W_HBL		41
+
+/* FS1 (Hsync) Period (Typical) */
+#define EPPI_FS1P_AVPL		EPPI_LINE
+
+/* Horizontal Delay clock after assertion of Hsync (Typical) */
+#define EPPI_HDELAY		43
+
+/* FS2 (Vsync) Width    = FS1 (Hsync) Period * 10 */
+#define EPPI_FS2W_LVB		(EPPI_LINE * 10)
+
+ /* FS2 (Vsync) Period   = FS1 (Hsync) Period * Lines per Frame */
+#define EPPI_FS2P_LAVF		(EPPI_LINE * EPPI_FRAME)
+
+/* Vertical Delay after assertion of Vsync (2 Lines) */
+#define EPPI_VDELAY		12
+
+#define EPPI_CLIP		0xFF00FF00
+
+/* EPPI Control register configuration value for RGB out
+ * - EPPI as Output
+ * GP 2 frame sync mode,
+ * Internal Clock generation disabled, Internal FS generation enabled,
+ * Receives samples on EPPI_CLK raising edge, Transmits samples on EPPI_CLK falling edge,
+ * FS1 & FS2 are active high,
+ * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
+ * DMA Unpacking disabled when RGB Formating is enabled, otherwise DMA unpacking enabled
+ * Swapping Enabled,
+ * One (DMA) Channel Mode,
+ * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
+ * Regular watermark - when FIFO is 100% full,
+ * Urgent watermark - when FIFO is 75% full
+ */
+
+#define EPPI_CONTROL		(0x20136E2E | SWAPEN)
+
+static inline u16 get_eppi_clkdiv(u32 target_ppi_clk)
+{
+	u32 sclk = get_sclk();
+
+	/* EPPI_CLK = (SCLK) / (2 * (EPPI_CLKDIV[15:0] + 1)) */
+
+	return (((sclk / target_ppi_clk) / 2) - 1);
+}
+
+static void config_ppi(struct bfin_bf54xfb_info *fbi)
+{
+
+	u16 eppi_clkdiv = get_eppi_clkdiv(LCD_CLK);
+
+	bfin_write_EPPI0_FS1W_HBL(EPPI_FS1W_HBL);
+	bfin_write_EPPI0_FS1P_AVPL(EPPI_FS1P_AVPL);
+	bfin_write_EPPI0_FS2W_LVB(EPPI_FS2W_LVB);
+	bfin_write_EPPI0_FS2P_LAVF(EPPI_FS2P_LAVF);
+	bfin_write_EPPI0_CLIP(EPPI_CLIP);
+
+	bfin_write_EPPI0_FRAME(EPPI_FRAME);
+	bfin_write_EPPI0_LINE(EPPI_LINE);
+
+	bfin_write_EPPI0_HCOUNT(EPPI_HCOUNT);
+	bfin_write_EPPI0_HDELAY(EPPI_HDELAY);
+	bfin_write_EPPI0_VCOUNT(EPPI_VCOUNT);
+	bfin_write_EPPI0_VDELAY(EPPI_VDELAY);
+
+	bfin_write_EPPI0_CLKDIV(eppi_clkdiv);
+
+/*
+ * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
+ * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
+ */
+	if (outp_rgb666)
+		bfin_write_EPPI0_CONTROL((EPPI_CONTROL & ~DLENGTH) | DLEN_18 |
+					 RGB_FMT_EN);
+	else
+		bfin_write_EPPI0_CONTROL(((EPPI_CONTROL & ~DLENGTH) | DLEN_24) &
+					 ~RGB_FMT_EN);
+
+
+}
+
+static int config_dma(struct bfin_bf54xfb_info *fbi)
+{
+
+	set_dma_config(CH_EPPI0,
+		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
+					   INTR_DISABLE, DIMENSION_2D,
+					   DATA_SIZE_32,
+					   DMA_NOSYNC_KEEP_DMA_BUF));
+	set_dma_x_count(CH_EPPI0, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
+	set_dma_x_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
+	set_dma_y_count(CH_EPPI0, LCD_Y_RES);
+	set_dma_y_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
+	set_dma_start_addr(CH_EPPI0, (unsigned long)fbi->fb_buffer);
+
+	return 0;
+}
+
+static int request_ports(struct bfin_bf54xfb_info *fbi)
+{
+
+	u16 eppi_req_18[] = EPPI0_18;
+	u16 disp = fbi->mach_info->disp;
+
+	if (gpio_request_one(disp, GPIOF_OUT_INIT_HIGH, DRIVER_NAME)) {
+		printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
+		return -EFAULT;
+	}
+
+	if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) {
+		printk(KERN_ERR "Requesting Peripherals failed\n");
+		gpio_free(disp);
+		return -EFAULT;
+	}
+
+	if (!outp_rgb666) {
+
+		u16 eppi_req_24[] = EPPI0_24;
+
+		if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) {
+			printk(KERN_ERR "Requesting Peripherals failed\n");
+			peripheral_free_list(eppi_req_18);
+			gpio_free(disp);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+static void free_ports(struct bfin_bf54xfb_info *fbi)
+{
+
+	u16 eppi_req_18[] = EPPI0_18;
+
+	gpio_free(fbi->mach_info->disp);
+
+	peripheral_free_list(eppi_req_18);
+
+	if (!outp_rgb666) {
+		u16 eppi_req_24[] = EPPI0_24;
+		peripheral_free_list(eppi_req_24);
+	}
+}
+
+static int bfin_bf54x_fb_open(struct fb_info *info, int user)
+{
+	struct bfin_bf54xfb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+	fbi->lq043_open_cnt++;
+
+	if (fbi->lq043_open_cnt <= 1) {
+
+		bfin_write_EPPI0_CONTROL(0);
+		SSYNC();
+
+		config_dma(fbi);
+		config_ppi(fbi);
+
+		/* start dma */
+		enable_dma(CH_EPPI0);
+		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_bf54x_fb_release(struct fb_info *info, int user)
+{
+	struct bfin_bf54xfb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+
+	fbi->lq043_open_cnt--;
+
+	if (fbi->lq043_open_cnt <= 0) {
+
+		bfin_write_EPPI0_CONTROL(0);
+		SSYNC();
+		disable_dma(CH_EPPI0);
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
+{
+
+	switch (var->bits_per_pixel) {
+	case 24:/* TRUECOLOUR, 16m */
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		break;
+	default:
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres || info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_bf54x_fb_setcolreg(u_int regno, u_int red, u_int green,
+				   u_int blue, u_int transp,
+				   struct fb_info *info)
+{
+	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+
+		value = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset);
+		value &= 0xFFFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+
+	}
+
+	return 0;
+}
+
+static struct fb_ops bfin_bf54x_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = bfin_bf54x_fb_open,
+	.fb_release = bfin_bf54x_fb_release,
+	.fb_check_var = bfin_bf54x_fb_check_var,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = bfin_bf54x_fb_cursor,
+	.fb_setcolreg = bfin_bf54x_fb_setcolreg,
+};
+
+#ifndef NO_BL_SUPPORT
+static int bl_get_brightness(struct backlight_device *bd)
+{
+	return 0;
+}
+
+static const struct backlight_ops bfin_lq043fb_bl_ops = {
+	.get_brightness = bl_get_brightness,
+};
+
+static struct backlight_device *bl_dev;
+
+static int bfin_lcd_get_power(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_power(struct lcd_device *dev, int power)
+{
+	return 0;
+}
+
+static int bfin_lcd_get_contrast(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
+{
+
+	return 0;
+}
+
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
+{
+	if (!fi || (fi == &bfin_bf54x_fb))
+		return 1;
+	return 0;
+}
+
+static struct lcd_ops bfin_lcd_ops = {
+	.get_power = bfin_lcd_get_power,
+	.set_power = bfin_lcd_set_power,
+	.get_contrast = bfin_lcd_get_contrast,
+	.set_contrast = bfin_lcd_set_contrast,
+	.check_fb = bfin_lcd_check_fb,
+};
+
+static struct lcd_device *lcd_dev;
+#endif
+
+static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
+{
+	/*struct bfin_bf54xfb_info *info = dev_id;*/
+
+	u16 status = bfin_read_EPPI0_STATUS();
+
+	bfin_write_EPPI0_STATUS(0xFFFF);
+
+	if (status) {
+		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
+		disable_dma(CH_EPPI0);
+
+		/* start dma */
+		enable_dma(CH_EPPI0);
+		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+		bfin_write_EPPI0_STATUS(0xFFFF);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int bfin_bf54x_probe(struct platform_device *pdev)
+{
+#ifndef NO_BL_SUPPORT
+	struct backlight_properties props;
+#endif
+	struct bfin_bf54xfb_info *info;
+	struct fb_info *fbinfo;
+	int ret;
+
+	printk(KERN_INFO DRIVER_NAME ": FrameBuffer initializing...\n");
+
+	if (request_dma(CH_EPPI0, "CH_EPPI0") < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": couldn't request CH_EPPI0 DMA\n");
+		ret = -EFAULT;
+		goto out1;
+	}
+
+	fbinfo =
+	    framebuffer_alloc(sizeof(struct bfin_bf54xfb_info), &pdev->dev);
+	if (!fbinfo) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	info = fbinfo->par;
+	info->fb = fbinfo;
+	info->dev = &pdev->dev;
+	spin_lock_init(&info->lock);
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	strcpy(fbinfo->fix.id, driver_name);
+
+	info->mach_info = pdev->dev.platform_data;
+
+	if (info->mach_info == NULL) {
+		dev_err(&pdev->dev,
+			"no platform data for lcd, cannot attach\n");
+		ret = -EINVAL;
+		goto out3;
+	}
+
+	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux = 0;
+	fbinfo->fix.xpanstep = 0;
+	fbinfo->fix.ypanstep = 0;
+	fbinfo->fix.ywrapstep = 0;
+	fbinfo->fix.accel = FB_ACCEL_NONE;
+	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	fbinfo->var.nonstd = 0;
+	fbinfo->var.activate = FB_ACTIVATE_NOW;
+	fbinfo->var.height = info->mach_info->height;
+	fbinfo->var.width = info->mach_info->width;
+	fbinfo->var.accel_flags = 0;
+	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+	fbinfo->fbops = &bfin_bf54x_fb_ops;
+	fbinfo->flags = FBINFO_FLAG_DEFAULT;
+
+	fbinfo->var.xres = info->mach_info->xres.defval;
+	fbinfo->var.xres_virtual = info->mach_info->xres.defval;
+	fbinfo->var.yres = info->mach_info->yres.defval;
+	fbinfo->var.yres_virtual = info->mach_info->yres.defval;
+	fbinfo->var.bits_per_pixel = info->mach_info->bpp.defval;
+
+	fbinfo->var.upper_margin = 0;
+	fbinfo->var.lower_margin = 0;
+	fbinfo->var.vsync_len = 0;
+
+	fbinfo->var.left_margin = 0;
+	fbinfo->var.right_margin = 0;
+	fbinfo->var.hsync_len = 0;
+
+	fbinfo->var.red.offset = 16;
+	fbinfo->var.green.offset = 8;
+	fbinfo->var.blue.offset = 0;
+	fbinfo->var.transp.offset = 0;
+	fbinfo->var.red.length = 8;
+	fbinfo->var.green.length = 8;
+	fbinfo->var.blue.length = 8;
+	fbinfo->var.transp.length = 0;
+	fbinfo->fix.smem_len = info->mach_info->xres.max *
+	    info->mach_info->yres.max * info->mach_info->bpp.max / 8;
+
+	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
+	    fbinfo->var.bits_per_pixel / 8;
+
+	info->fb_buffer =
+	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
+			       GFP_KERNEL);
+
+	if (NULL == info->fb_buffer) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": couldn't allocate dma buffer.\n");
+		ret = -ENOMEM;
+		goto out3;
+	}
+
+	fbinfo->screen_base = (void *)info->fb_buffer;
+	fbinfo->fix.smem_start = (int)info->fb_buffer;
+
+	fbinfo->fbops = &bfin_bf54x_fb_ops;
+
+	fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
+					      GFP_KERNEL);
+	if (!fbinfo->pseudo_palette) {
+		printk(KERN_ERR DRIVER_NAME
+		       "Fail to allocate pseudo_palette\n");
+
+		ret = -ENOMEM;
+		goto out4;
+	}
+
+	if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
+	    < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       "Fail to allocate colormap (%d entries)\n",
+		       BFIN_LCD_NBR_PALETTE_ENTRIES);
+		ret = -EFAULT;
+		goto out4;
+	}
+
+	if (request_ports(info)) {
+		printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
+		ret = -EFAULT;
+		goto out6;
+	}
+
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		ret = -EINVAL;
+		goto out7;
+	}
+
+	if (request_irq(info->irq, bfin_bf54x_irq_error, 0,
+			"PPI ERROR", info) < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": unable to request PPI ERROR IRQ\n");
+		ret = -EFAULT;
+		goto out7;
+	}
+
+	if (register_framebuffer(fbinfo) < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": unable to register framebuffer.\n");
+		ret = -EINVAL;
+		goto out8;
+	}
+#ifndef NO_BL_SUPPORT
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 255;
+	bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
+					   &bfin_lq043fb_bl_ops, &props);
+	if (IS_ERR(bl_dev)) {
+		printk(KERN_ERR DRIVER_NAME
+			": unable to register backlight.\n");
+		ret = -EINVAL;
+		unregister_framebuffer(fbinfo);
+		goto out8;
+	}
+
+	lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
+	lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
+#endif
+
+	return 0;
+
+out8:
+	free_irq(info->irq, info);
+out7:
+	free_ports(info);
+out6:
+	fb_dealloc_cmap(&fbinfo->cmap);
+out4:
+	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+			  info->dma_handle);
+out3:
+	framebuffer_release(fbinfo);
+out2:
+	free_dma(CH_EPPI0);
+out1:
+
+	return ret;
+}
+
+static int bfin_bf54x_remove(struct platform_device *pdev)
+{
+
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_bf54xfb_info *info = fbinfo->par;
+
+	free_dma(CH_EPPI0);
+	free_irq(info->irq, info);
+
+	if (info->fb_buffer != NULL)
+		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+				  info->dma_handle);
+
+	fb_dealloc_cmap(&fbinfo->cmap);
+
+#ifndef NO_BL_SUPPORT
+	lcd_device_unregister(lcd_dev);
+	backlight_device_unregister(bl_dev);
+#endif
+
+	unregister_framebuffer(fbinfo);
+
+	free_ports(info);
+
+	printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+
+	bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
+	disable_dma(CH_EPPI0);
+	bfin_write_EPPI0_STATUS(0xFFFF);
+
+	return 0;
+}
+
+static int bfin_bf54x_resume(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_bf54xfb_info *info = fbinfo->par;
+
+	if (info->lq043_open_cnt) {
+
+		bfin_write_EPPI0_CONTROL(0);
+		SSYNC();
+
+		config_dma(info);
+		config_ppi(info);
+
+		/* start dma */
+		enable_dma(CH_EPPI0);
+		bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
+	}
+
+	return 0;
+}
+#else
+#define bfin_bf54x_suspend	NULL
+#define bfin_bf54x_resume	NULL
+#endif
+
+static struct platform_driver bfin_bf54x_driver = {
+	.probe = bfin_bf54x_probe,
+	.remove = bfin_bf54x_remove,
+	.suspend = bfin_bf54x_suspend,
+	.resume = bfin_bf54x_resume,
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   },
+};
+module_platform_driver(bfin_bf54x_driver);
+
+MODULE_DESCRIPTION("Blackfin BF54x TFT LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/bfin-lq035q1-fb.c b/drivers/video/fbdev/bfin-lq035q1-fb.c
new file mode 100644
index 000000000000..b594a58ff21d
--- /dev/null
+++ b/drivers/video/fbdev/bfin-lq035q1-fb.c
@@ -0,0 +1,864 @@
+/*
+ * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02
+ *
+ * Copyright 2008-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#define DRIVER_NAME "bfin-lq035q1"
+#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+#include <asm/gptimers.h>
+
+#include <asm/bfin-lq035q1.h>
+
+#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
+#define TIMER_HSYNC_id			TIMER1_id
+#define TIMER_HSYNCbit			TIMER1bit
+#define TIMER_HSYNC_STATUS_TRUN		TIMER_STATUS_TRUN1
+#define TIMER_HSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL1
+#define TIMER_HSYNC_STATUS_TOVF		TIMER_STATUS_TOVF1
+
+#define TIMER_VSYNC_id			TIMER2_id
+#define TIMER_VSYNCbit			TIMER2bit
+#define TIMER_VSYNC_STATUS_TRUN		TIMER_STATUS_TRUN2
+#define TIMER_VSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL2
+#define TIMER_VSYNC_STATUS_TOVF		TIMER_STATUS_TOVF2
+#else
+#define TIMER_HSYNC_id			TIMER0_id
+#define TIMER_HSYNCbit			TIMER0bit
+#define TIMER_HSYNC_STATUS_TRUN		TIMER_STATUS_TRUN0
+#define TIMER_HSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL0
+#define TIMER_HSYNC_STATUS_TOVF		TIMER_STATUS_TOVF0
+
+#define TIMER_VSYNC_id			TIMER1_id
+#define TIMER_VSYNCbit			TIMER1bit
+#define TIMER_VSYNC_STATUS_TRUN		TIMER_STATUS_TRUN1
+#define TIMER_VSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL1
+#define TIMER_VSYNC_STATUS_TOVF		TIMER_STATUS_TOVF1
+#endif
+
+#define LCD_X_RES		320	/* Horizontal Resolution */
+#define LCD_Y_RES		240	/* Vertical Resolution */
+#define	DMA_BUS_SIZE		16
+#define U_LINE			4	/* Blanking Lines */
+
+
+/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD)
+ * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
+ */
+
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
+
+#define PPI_TX_MODE			0x2
+#define PPI_XFER_TYPE_11		0xC
+#define PPI_PORT_CFG_01			0x10
+#define PPI_POLS_1			0x8000
+
+#define LQ035_INDEX			0x74
+#define LQ035_DATA			0x76
+
+#define LQ035_DRIVER_OUTPUT_CTL		0x1
+#define LQ035_SHUT_CTL			0x11
+
+#define LQ035_DRIVER_OUTPUT_MASK	(LQ035_LR | LQ035_TB | LQ035_BGR | LQ035_REV)
+#define LQ035_DRIVER_OUTPUT_DEFAULT	(0x2AEF & ~LQ035_DRIVER_OUTPUT_MASK)
+
+#define LQ035_SHUT			(1 << 0)	/* Shutdown */
+#define LQ035_ON			(0 << 0)	/* Shutdown */
+
+struct bfin_lq035q1fb_info {
+	struct fb_info *fb;
+	struct device *dev;
+	struct spi_driver spidrv;
+	struct bfin_lq035q1fb_disp_info *disp_info;
+	unsigned char *fb_buffer;	/* RGB Buffer */
+	dma_addr_t dma_handle;
+	int lq035_open_cnt;
+	int irq;
+	spinlock_t lock;	/* lock */
+	u32 pseudo_pal[16];
+
+	u32 lcd_bpp;
+	u32 h_actpix;
+	u32 h_period;
+	u32 h_pulse;
+	u32 h_start;
+	u32 v_lines;
+	u32 v_pulse;
+	u32 v_period;
+};
+
+static int nocursor;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+struct spi_control {
+	unsigned short mode;
+};
+
+static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned short value)
+{
+	int ret;
+	u8 regs[3] = { LQ035_INDEX, 0, 0 };
+	u8 dat[3] = { LQ035_DATA, 0, 0 };
+
+	if (!spi)
+		return -ENODEV;
+
+	regs[2] = reg;
+	dat[1] = value >> 8;
+	dat[2] = value & 0xFF;
+
+	ret = spi_write(spi, regs, ARRAY_SIZE(regs));
+	ret |= spi_write(spi, dat, ARRAY_SIZE(dat));
+	return ret;
+}
+
+static int lq035q1_spidev_probe(struct spi_device *spi)
+{
+	int ret;
+	struct spi_control *ctl;
+	struct bfin_lq035q1fb_info *info = container_of(spi->dev.driver,
+						struct bfin_lq035q1fb_info,
+						spidrv.driver);
+
+	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
+
+	if (!ctl)
+		return -ENOMEM;
+
+	ctl->mode = (info->disp_info->mode &
+		LQ035_DRIVER_OUTPUT_MASK) | LQ035_DRIVER_OUTPUT_DEFAULT;
+
+	ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
+	ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
+	if (ret) {
+		kfree(ctl);
+		return ret;
+	}
+
+	spi_set_drvdata(spi, ctl);
+
+	return 0;
+}
+
+static int lq035q1_spidev_remove(struct spi_device *spi)
+{
+	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lq035q1_spidev_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+
+	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
+}
+
+static int lq035q1_spidev_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct spi_control *ctl = spi_get_drvdata(spi);
+	int ret;
+
+	ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
+	if (ret)
+		return ret;
+
+	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
+}
+
+static SIMPLE_DEV_PM_OPS(lq035q1_spidev_pm_ops, lq035q1_spidev_suspend,
+	lq035q1_spidev_resume);
+#define LQ035Q1_SPIDEV_PM_OPS (&lq035q1_spidev_pm_ops)
+
+#else
+#define LQ035Q1_SPIDEV_PM_OPS NULL
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+static void lq035q1_spidev_shutdown(struct spi_device *spi)
+{
+	lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
+}
+
+static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg)
+{
+	if (info->disp_info->use_bl)
+		gpio_set_value(info->disp_info->gpio_bl, arg);
+
+	return 0;
+}
+
+static int bfin_lq035q1_calc_timing(struct bfin_lq035q1fb_info *fbi)
+{
+	unsigned long clocks_per_pix, cpld_pipeline_delay_cor;
+
+	/*
+	 * Interface 16/18-bit TFT over an 8-bit wide PPI using a small
+	 * Programmable Logic Device (CPLD)
+	 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
+	 */
+
+	switch (fbi->disp_info->ppi_mode) {
+	case USE_RGB565_16_BIT_PPI:
+		fbi->lcd_bpp = 16;
+		clocks_per_pix = 1;
+		cpld_pipeline_delay_cor = 0;
+		break;
+	case USE_RGB565_8_BIT_PPI:
+		fbi->lcd_bpp = 16;
+		clocks_per_pix = 2;
+		cpld_pipeline_delay_cor = 3;
+		break;
+	case USE_RGB888_8_BIT_PPI:
+		fbi->lcd_bpp = 24;
+		clocks_per_pix = 3;
+		cpld_pipeline_delay_cor = 5;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * HS and VS timing parameters (all in number of PPI clk ticks)
+	 */
+
+	fbi->h_actpix = (LCD_X_RES * clocks_per_pix);	/* active horizontal pixel */
+	fbi->h_period = (336 * clocks_per_pix);		/* HS period */
+	fbi->h_pulse = (2 * clocks_per_pix);				/* HS pulse width */
+	fbi->h_start = (7 * clocks_per_pix + cpld_pipeline_delay_cor);	/* first valid pixel */
+
+	fbi->v_lines = (LCD_Y_RES + U_LINE);		/* total vertical lines */
+	fbi->v_pulse = (2 * clocks_per_pix);		/* VS pulse width (1-5 H_PERIODs) */
+	fbi->v_period =	(fbi->h_period * fbi->v_lines);	/* VS period */
+
+	return 0;
+}
+
+static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi)
+{
+	unsigned ppi_pmode;
+
+	if (fbi->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI)
+		ppi_pmode = DLEN_16;
+	else
+		ppi_pmode = (DLEN_8 | PACK_EN);
+
+	bfin_write_PPI_DELAY(fbi->h_start);
+	bfin_write_PPI_COUNT(fbi->h_actpix - 1);
+	bfin_write_PPI_FRAME(fbi->v_lines);
+
+	bfin_write_PPI_CONTROL(PPI_TX_MODE |	   /* output mode , PORT_DIR */
+				PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
+				PPI_PORT_CFG_01 |  /* two frame sync PORT_CFG */
+				ppi_pmode |	   /* 8/16 bit data length / PACK_EN? */
+				PPI_POLS_1);	   /* faling edge syncs POLS */
+}
+
+static inline void bfin_lq035q1_disable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
+}
+
+static inline void bfin_lq035q1_enable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+}
+
+static void bfin_lq035q1_start_timers(void)
+{
+	enable_gptimers(TIMER_VSYNCbit | TIMER_HSYNCbit);
+}
+
+static void bfin_lq035q1_stop_timers(void)
+{
+	disable_gptimers(TIMER_HSYNCbit | TIMER_VSYNCbit);
+
+	set_gptimer_status(0, TIMER_HSYNC_STATUS_TRUN | TIMER_VSYNC_STATUS_TRUN |
+				TIMER_HSYNC_STATUS_TIMIL | TIMER_VSYNC_STATUS_TIMIL |
+				 TIMER_HSYNC_STATUS_TOVF | TIMER_VSYNC_STATUS_TOVF);
+
+}
+
+static void bfin_lq035q1_init_timers(struct bfin_lq035q1fb_info *fbi)
+{
+
+	bfin_lq035q1_stop_timers();
+
+	set_gptimer_period(TIMER_HSYNC_id, fbi->h_period);
+	set_gptimer_pwidth(TIMER_HSYNC_id, fbi->h_pulse);
+	set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL|
+				      TIMER_EMU_RUN);
+
+	set_gptimer_period(TIMER_VSYNC_id, fbi->v_period);
+	set_gptimer_pwidth(TIMER_VSYNC_id, fbi->v_pulse);
+	set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL |
+				      TIMER_EMU_RUN);
+
+}
+
+static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi)
+{
+
+
+	set_dma_config(CH_PPI,
+		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
+					   INTR_DISABLE, DIMENSION_2D,
+					   DATA_SIZE_16,
+					   DMA_NOSYNC_KEEP_DMA_BUF));
+	set_dma_x_count(CH_PPI, (LCD_X_RES * fbi->lcd_bpp) / DMA_BUS_SIZE);
+	set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_y_count(CH_PPI, fbi->v_lines);
+
+	set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
+
+}
+
+static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
+			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
+			    P_PPI0_D6, P_PPI0_D7, P_PPI0_D8,
+			    P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+			    P_PPI0_D12, P_PPI0_D13, P_PPI0_D14,
+			    P_PPI0_D15, 0};
+
+static const u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
+			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
+			    P_PPI0_D6, P_PPI0_D7, 0};
+
+static inline void bfin_lq035q1_free_ports(unsigned ppi16)
+{
+	if (ppi16)
+		peripheral_free_list(ppi0_req_16);
+	else
+		peripheral_free_list(ppi0_req_8);
+
+	if (ANOMALY_05000400)
+		gpio_free(P_IDENT(P_PPI0_FS3));
+}
+
+static int bfin_lq035q1_request_ports(struct platform_device *pdev,
+				      unsigned ppi16)
+{
+	int ret;
+	/* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode:
+	 * Drive PPI_FS3 Low
+	 */
+	if (ANOMALY_05000400) {
+		int ret = gpio_request_one(P_IDENT(P_PPI0_FS3),
+					GPIOF_OUT_INIT_LOW, "PPI_FS3");
+		if (ret)
+			return ret;
+	}
+
+	if (ppi16)
+		ret = peripheral_request_list(ppi0_req_16, DRIVER_NAME);
+	else
+		ret = peripheral_request_list(ppi0_req_8, DRIVER_NAME);
+
+	if (ret) {
+		dev_err(&pdev->dev, "requesting peripherals failed\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int bfin_lq035q1_fb_open(struct fb_info *info, int user)
+{
+	struct bfin_lq035q1fb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+	fbi->lq035_open_cnt++;
+
+	if (fbi->lq035_open_cnt <= 1) {
+
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+
+		bfin_lq035q1_config_dma(fbi);
+		bfin_lq035q1_config_ppi(fbi);
+		bfin_lq035q1_init_timers(fbi);
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_lq035q1_enable_ppi();
+		bfin_lq035q1_start_timers();
+		lq035q1_backlight(fbi, 1);
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_lq035q1_fb_release(struct fb_info *info, int user)
+{
+	struct bfin_lq035q1fb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+
+	fbi->lq035_open_cnt--;
+
+	if (fbi->lq035_open_cnt <= 0) {
+		lq035q1_backlight(fbi, 0);
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+		disable_dma(CH_PPI);
+		bfin_lq035q1_stop_timers();
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var,
+				     struct fb_info *info)
+{
+	struct bfin_lq035q1fb_info *fbi = info->par;
+
+	if (var->bits_per_pixel == fbi->lcd_bpp) {
+		var->red.offset = info->var.red.offset;
+		var->green.offset = info->var.green.offset;
+		var->blue.offset = info->var.blue.offset;
+		var->red.length = info->var.red.length;
+		var->green.length = info->var.green.length;
+		var->blue.length = info->var.blue.length;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+	} else {
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres || info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+
+	return 0;
+}
+
+int bfin_lq035q1_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_lq035q1_fb_setcolreg(u_int regno, u_int red, u_int green,
+				   u_int blue, u_int transp,
+				   struct fb_info *info)
+{
+	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+
+		value = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset);
+		value &= 0xFFFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+
+	}
+
+	return 0;
+}
+
+static struct fb_ops bfin_lq035q1_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = bfin_lq035q1_fb_open,
+	.fb_release = bfin_lq035q1_fb_release,
+	.fb_check_var = bfin_lq035q1_fb_check_var,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = bfin_lq035q1_fb_cursor,
+	.fb_setcolreg = bfin_lq035q1_fb_setcolreg,
+};
+
+static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id)
+{
+	/*struct bfin_lq035q1fb_info *info = (struct bfin_lq035q1fb_info *)dev_id;*/
+
+	u16 status = bfin_read_PPI_STATUS();
+	bfin_write_PPI_STATUS(-1);
+
+	if (status) {
+		bfin_lq035q1_disable_ppi();
+		disable_dma(CH_PPI);
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_lq035q1_enable_ppi();
+		bfin_write_PPI_STATUS(-1);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int bfin_lq035q1_probe(struct platform_device *pdev)
+{
+	struct bfin_lq035q1fb_info *info;
+	struct fb_info *fbinfo;
+	u32 active_video_mem_offset;
+	int ret;
+
+	ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI");
+	if (ret < 0) {
+		dev_err(&pdev->dev, "PPI DMA unavailable\n");
+		goto out1;
+	}
+
+	fbinfo = framebuffer_alloc(sizeof(*info), &pdev->dev);
+	if (!fbinfo) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	info = fbinfo->par;
+	info->fb = fbinfo;
+	info->dev = &pdev->dev;
+	spin_lock_init(&info->lock);
+
+	info->disp_info = pdev->dev.platform_data;
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	ret = bfin_lq035q1_calc_timing(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed PPI Mode\n");
+		goto out3;
+	}
+
+	strcpy(fbinfo->fix.id, DRIVER_NAME);
+
+	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux = 0;
+	fbinfo->fix.xpanstep = 0;
+	fbinfo->fix.ypanstep = 0;
+	fbinfo->fix.ywrapstep = 0;
+	fbinfo->fix.accel = FB_ACCEL_NONE;
+	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	fbinfo->var.nonstd = 0;
+	fbinfo->var.activate = FB_ACTIVATE_NOW;
+	fbinfo->var.height = -1;
+	fbinfo->var.width = -1;
+	fbinfo->var.accel_flags = 0;
+	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+	fbinfo->var.xres = LCD_X_RES;
+	fbinfo->var.xres_virtual = LCD_X_RES;
+	fbinfo->var.yres = LCD_Y_RES;
+	fbinfo->var.yres_virtual = LCD_Y_RES;
+	fbinfo->var.bits_per_pixel = info->lcd_bpp;
+
+	if (info->disp_info->mode & LQ035_BGR) {
+		if (info->lcd_bpp == 24) {
+			fbinfo->var.red.offset = 0;
+			fbinfo->var.green.offset = 8;
+			fbinfo->var.blue.offset = 16;
+		} else {
+			fbinfo->var.red.offset = 0;
+			fbinfo->var.green.offset = 5;
+			fbinfo->var.blue.offset = 11;
+		}
+	} else {
+		if (info->lcd_bpp == 24) {
+			fbinfo->var.red.offset = 16;
+			fbinfo->var.green.offset = 8;
+			fbinfo->var.blue.offset = 0;
+		} else {
+			fbinfo->var.red.offset = 11;
+			fbinfo->var.green.offset = 5;
+			fbinfo->var.blue.offset = 0;
+		}
+	}
+
+	fbinfo->var.transp.offset = 0;
+
+	if (info->lcd_bpp == 24) {
+		fbinfo->var.red.length = 8;
+		fbinfo->var.green.length = 8;
+		fbinfo->var.blue.length = 8;
+	} else {
+		fbinfo->var.red.length = 5;
+		fbinfo->var.green.length = 6;
+		fbinfo->var.blue.length = 5;
+	}
+
+	fbinfo->var.transp.length = 0;
+
+	active_video_mem_offset = ((U_LINE / 2) * LCD_X_RES * (info->lcd_bpp / 8));
+
+	fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * info->lcd_bpp / 8
+				+ active_video_mem_offset;
+
+	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
+	    fbinfo->var.bits_per_pixel / 8;
+
+
+	fbinfo->fbops = &bfin_lq035q1_fb_ops;
+	fbinfo->flags = FBINFO_FLAG_DEFAULT;
+
+	info->fb_buffer =
+	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
+			       GFP_KERNEL);
+
+	if (NULL == info->fb_buffer) {
+		dev_err(&pdev->dev, "couldn't allocate dma buffer\n");
+		ret = -ENOMEM;
+		goto out3;
+	}
+
+	fbinfo->screen_base = (void *)info->fb_buffer + active_video_mem_offset;
+	fbinfo->fix.smem_start = (int)info->fb_buffer + active_video_mem_offset;
+
+	fbinfo->fbops = &bfin_lq035q1_fb_ops;
+
+	fbinfo->pseudo_palette = &info->pseudo_pal;
+
+	ret = fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to allocate colormap (%d entries)\n",
+		       BFIN_LCD_NBR_PALETTE_ENTRIES);
+		goto out4;
+	}
+
+	ret = bfin_lq035q1_request_ports(pdev,
+			info->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request gpio port\n");
+		goto out6;
+	}
+
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		ret = -EINVAL;
+		goto out7;
+	}
+
+	ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0,
+			DRIVER_NAME" PPI ERROR", info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");
+		goto out7;
+	}
+
+	info->spidrv.driver.name = DRIVER_NAME"-spi";
+	info->spidrv.probe    = lq035q1_spidev_probe;
+	info->spidrv.remove   = lq035q1_spidev_remove;
+	info->spidrv.shutdown = lq035q1_spidev_shutdown;
+	info->spidrv.driver.pm = LQ035Q1_SPIDEV_PM_OPS;
+
+	ret = spi_register_driver(&info->spidrv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "couldn't register SPI Interface\n");
+		goto out8;
+	}
+
+	if (info->disp_info->use_bl) {
+		ret = gpio_request_one(info->disp_info->gpio_bl,
+					GPIOF_OUT_INIT_LOW, "LQ035 Backlight");
+
+		if (ret) {
+			dev_err(&pdev->dev, "failed to request GPIO %d\n",
+				info->disp_info->gpio_bl);
+			goto out9;
+		}
+	}
+
+	ret = register_framebuffer(fbinfo);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to register framebuffer\n");
+		goto out10;
+	}
+
+	dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n",
+		LCD_X_RES, LCD_Y_RES, info->lcd_bpp);
+
+	return 0;
+
+ out10:
+	if (info->disp_info->use_bl)
+		gpio_free(info->disp_info->gpio_bl);
+ out9:
+	spi_unregister_driver(&info->spidrv);
+ out8:
+	free_irq(info->irq, info);
+ out7:
+	bfin_lq035q1_free_ports(info->disp_info->ppi_mode ==
+				USE_RGB565_16_BIT_PPI);
+ out6:
+	fb_dealloc_cmap(&fbinfo->cmap);
+ out4:
+	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+			  info->dma_handle);
+ out3:
+	framebuffer_release(fbinfo);
+ out2:
+	free_dma(CH_PPI);
+ out1:
+
+	return ret;
+}
+
+static int bfin_lq035q1_remove(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_lq035q1fb_info *info = fbinfo->par;
+
+	if (info->disp_info->use_bl)
+		gpio_free(info->disp_info->gpio_bl);
+
+	spi_unregister_driver(&info->spidrv);
+
+	unregister_framebuffer(fbinfo);
+
+	free_dma(CH_PPI);
+	free_irq(info->irq, info);
+
+	if (info->fb_buffer != NULL)
+		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+				  info->dma_handle);
+
+	fb_dealloc_cmap(&fbinfo->cmap);
+
+	bfin_lq035q1_free_ports(info->disp_info->ppi_mode ==
+				USE_RGB565_16_BIT_PPI);
+
+	framebuffer_release(fbinfo);
+
+	dev_info(&pdev->dev, "unregistered LCD driver\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_lq035q1_suspend(struct device *dev)
+{
+	struct fb_info *fbinfo = dev_get_drvdata(dev);
+	struct bfin_lq035q1fb_info *info = fbinfo->par;
+
+	if (info->lq035_open_cnt) {
+		lq035q1_backlight(info, 0);
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+		disable_dma(CH_PPI);
+		bfin_lq035q1_stop_timers();
+		bfin_write_PPI_STATUS(-1);
+	}
+
+	return 0;
+}
+
+static int bfin_lq035q1_resume(struct device *dev)
+{
+	struct fb_info *fbinfo = dev_get_drvdata(dev);
+	struct bfin_lq035q1fb_info *info = fbinfo->par;
+
+	if (info->lq035_open_cnt) {
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+
+		bfin_lq035q1_config_dma(info);
+		bfin_lq035q1_config_ppi(info);
+		bfin_lq035q1_init_timers(info);
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_lq035q1_enable_ppi();
+		bfin_lq035q1_start_timers();
+		lq035q1_backlight(info, 1);
+	}
+
+	return 0;
+}
+
+static struct dev_pm_ops bfin_lq035q1_dev_pm_ops = {
+	.suspend = bfin_lq035q1_suspend,
+	.resume  = bfin_lq035q1_resume,
+};
+#endif
+
+static struct platform_driver bfin_lq035q1_driver = {
+	.probe   = bfin_lq035q1_probe,
+	.remove  = bfin_lq035q1_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+#ifdef CONFIG_PM
+		.pm   = &bfin_lq035q1_dev_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(bfin_lq035q1_driver);
+
+MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/bfin-t350mcqb-fb.c b/drivers/video/fbdev/bfin-t350mcqb-fb.c
new file mode 100644
index 000000000000..b5cf1307a3d9
--- /dev/null
+++ b/drivers/video/fbdev/bfin-t350mcqb-fb.c
@@ -0,0 +1,670 @@
+/*
+ * File:         drivers/video/bfin-t350mcqb-fb.c
+ * Based on:
+ * Author:       Michael Hennerich <hennerich@blackfin.uclinux.org>
+ *
+ * Created:
+ * Description:  Blackfin LCD Framebuffer driver
+ *
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/gfp.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dma-mapping.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+#include <asm/gptimers.h>
+
+#define NO_BL_SUPPORT
+
+#define LCD_X_RES		320	/* Horizontal Resolution */
+#define LCD_Y_RES		240	/* Vertical Resolution */
+#define LCD_BPP			24	/* Bit Per Pixel */
+
+#define	DMA_BUS_SIZE		16
+#define	LCD_CLK         	(12*1000*1000)	/* 12MHz */
+
+#define CLOCKS_PER_PIX		3
+
+	/*
+	 * HS and VS timing parameters (all in number of PPI clk ticks)
+	 */
+
+#define U_LINE		1				/* Blanking Lines */
+
+#define H_ACTPIX	(LCD_X_RES * CLOCKS_PER_PIX)	/* active horizontal pixel */
+#define H_PERIOD	(408 * CLOCKS_PER_PIX)		/* HS period */
+#define H_PULSE		90				/* HS pulse width */
+#define H_START		204				/* first valid pixel */
+
+#define	V_LINES		(LCD_Y_RES + U_LINE)		/* total vertical lines */
+#define V_PULSE		(3 * H_PERIOD)			/* VS pulse width (1-5 H_PERIODs) */
+#define V_PERIOD	(H_PERIOD * V_LINES)		/* VS period */
+
+#define ACTIVE_VIDEO_MEM_OFFSET	(U_LINE * H_ACTPIX)
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
+
+#define DRIVER_NAME "bfin-t350mcqb"
+static char driver_name[] = DRIVER_NAME;
+
+struct bfin_t350mcqbfb_info {
+	struct fb_info *fb;
+	struct device *dev;
+	unsigned char *fb_buffer;	/* RGB Buffer */
+	dma_addr_t dma_handle;
+	int lq043_open_cnt;
+	int irq;
+	spinlock_t lock;	/* lock */
+	u32 pseudo_pal[16];
+};
+
+static int nocursor;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+#define PPI_TX_MODE		0x2
+#define PPI_XFER_TYPE_11	0xC
+#define PPI_PORT_CFG_01		0x10
+#define PPI_PACK_EN		0x80
+#define PPI_POLS_1		0x8000
+
+static void bfin_t350mcqb_config_ppi(struct bfin_t350mcqbfb_info *fbi)
+{
+	bfin_write_PPI_DELAY(H_START);
+	bfin_write_PPI_COUNT(H_ACTPIX-1);
+	bfin_write_PPI_FRAME(V_LINES);
+
+	bfin_write_PPI_CONTROL(PPI_TX_MODE |	   /* output mode , PORT_DIR */
+				PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
+				PPI_PORT_CFG_01 |  /* two frame sync PORT_CFG */
+				PPI_PACK_EN |	   /* packing enabled PACK_EN */
+				PPI_POLS_1);	   /* faling edge syncs POLS */
+}
+
+static inline void bfin_t350mcqb_disable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
+}
+
+static inline void bfin_t350mcqb_enable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+}
+
+static void bfin_t350mcqb_start_timers(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+		enable_gptimers(TIMER1bit);
+		enable_gptimers(TIMER0bit);
+	local_irq_restore(flags);
+}
+
+static void bfin_t350mcqb_stop_timers(void)
+{
+	disable_gptimers(TIMER0bit | TIMER1bit);
+
+	set_gptimer_status(0, TIMER_STATUS_TRUN0 | TIMER_STATUS_TRUN1 |
+				TIMER_STATUS_TIMIL0 | TIMER_STATUS_TIMIL1 |
+				 TIMER_STATUS_TOVF0 | TIMER_STATUS_TOVF1);
+
+}
+
+static void bfin_t350mcqb_init_timers(void)
+{
+
+	bfin_t350mcqb_stop_timers();
+
+	set_gptimer_period(TIMER0_id, H_PERIOD);
+	set_gptimer_pwidth(TIMER0_id, H_PULSE);
+	set_gptimer_config(TIMER0_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL|
+				      TIMER_EMU_RUN);
+
+	set_gptimer_period(TIMER1_id, V_PERIOD);
+	set_gptimer_pwidth(TIMER1_id, V_PULSE);
+	set_gptimer_config(TIMER1_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL |
+				      TIMER_EMU_RUN);
+
+}
+
+static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi)
+{
+
+	set_dma_config(CH_PPI,
+		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
+					   INTR_DISABLE, DIMENSION_2D,
+					   DATA_SIZE_16,
+					   DMA_NOSYNC_KEEP_DMA_BUF));
+	set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
+	set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_y_count(CH_PPI, V_LINES);
+
+	set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
+
+}
+
+static	u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
+			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
+			    P_PPI0_D6, P_PPI0_D7, 0};
+
+static int bfin_t350mcqb_request_ports(int action)
+{
+	if (action) {
+		if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
+			printk(KERN_ERR "Requesting Peripherals failed\n");
+			return -EFAULT;
+		}
+	} else
+		peripheral_free_list(ppi0_req_8);
+
+	return 0;
+}
+
+static int bfin_t350mcqb_fb_open(struct fb_info *info, int user)
+{
+	struct bfin_t350mcqbfb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+	fbi->lq043_open_cnt++;
+
+	if (fbi->lq043_open_cnt <= 1) {
+
+		bfin_t350mcqb_disable_ppi();
+		SSYNC();
+
+		bfin_t350mcqb_config_dma(fbi);
+		bfin_t350mcqb_config_ppi(fbi);
+		bfin_t350mcqb_init_timers();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_t350mcqb_enable_ppi();
+		bfin_t350mcqb_start_timers();
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_t350mcqb_fb_release(struct fb_info *info, int user)
+{
+	struct bfin_t350mcqbfb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+
+	fbi->lq043_open_cnt--;
+
+	if (fbi->lq043_open_cnt <= 0) {
+		bfin_t350mcqb_disable_ppi();
+		SSYNC();
+		disable_dma(CH_PPI);
+		bfin_t350mcqb_stop_timers();
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
+{
+
+	switch (var->bits_per_pixel) {
+	case 24:/* TRUECOLOUR, 16m */
+		var->red.offset = 0;
+		var->green.offset = 8;
+		var->blue.offset = 16;
+		var->red.length = var->green.length = var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		break;
+	default:
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres || info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_t350mcqb_fb_setcolreg(u_int regno, u_int red, u_int green,
+				   u_int blue, u_int transp,
+				   struct fb_info *info)
+{
+	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+
+		value = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset);
+		value &= 0xFFFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+
+	}
+
+	return 0;
+}
+
+static struct fb_ops bfin_t350mcqb_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = bfin_t350mcqb_fb_open,
+	.fb_release = bfin_t350mcqb_fb_release,
+	.fb_check_var = bfin_t350mcqb_fb_check_var,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = bfin_t350mcqb_fb_cursor,
+	.fb_setcolreg = bfin_t350mcqb_fb_setcolreg,
+};
+
+#ifndef NO_BL_SUPPORT
+static int bl_get_brightness(struct backlight_device *bd)
+{
+	return 0;
+}
+
+static const struct backlight_ops bfin_lq043fb_bl_ops = {
+	.get_brightness = bl_get_brightness,
+};
+
+static struct backlight_device *bl_dev;
+
+static int bfin_lcd_get_power(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_power(struct lcd_device *dev, int power)
+{
+	return 0;
+}
+
+static int bfin_lcd_get_contrast(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
+{
+
+	return 0;
+}
+
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
+{
+	if (!fi || (fi == &bfin_t350mcqb_fb))
+		return 1;
+	return 0;
+}
+
+static struct lcd_ops bfin_lcd_ops = {
+	.get_power = bfin_lcd_get_power,
+	.set_power = bfin_lcd_set_power,
+	.get_contrast = bfin_lcd_get_contrast,
+	.set_contrast = bfin_lcd_set_contrast,
+	.check_fb = bfin_lcd_check_fb,
+};
+
+static struct lcd_device *lcd_dev;
+#endif
+
+static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
+{
+	/*struct bfin_t350mcqbfb_info *info = (struct bfin_t350mcqbfb_info *)dev_id;*/
+
+	u16 status = bfin_read_PPI_STATUS();
+	bfin_write_PPI_STATUS(0xFFFF);
+
+	if (status) {
+		bfin_t350mcqb_disable_ppi();
+		disable_dma(CH_PPI);
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_t350mcqb_enable_ppi();
+		bfin_write_PPI_STATUS(0xFFFF);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int bfin_t350mcqb_probe(struct platform_device *pdev)
+{
+#ifndef NO_BL_SUPPORT
+	struct backlight_properties props;
+#endif
+	struct bfin_t350mcqbfb_info *info;
+	struct fb_info *fbinfo;
+	int ret;
+
+	printk(KERN_INFO DRIVER_NAME ": %dx%d %d-bit RGB FrameBuffer initializing...\n",
+					 LCD_X_RES, LCD_Y_RES, LCD_BPP);
+
+	if (request_dma(CH_PPI, "CH_PPI") < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": couldn't request CH_PPI DMA\n");
+		ret = -EFAULT;
+		goto out1;
+	}
+
+	fbinfo =
+	    framebuffer_alloc(sizeof(struct bfin_t350mcqbfb_info), &pdev->dev);
+	if (!fbinfo) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	info = fbinfo->par;
+	info->fb = fbinfo;
+	info->dev = &pdev->dev;
+	spin_lock_init(&info->lock);
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	strcpy(fbinfo->fix.id, driver_name);
+
+	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux = 0;
+	fbinfo->fix.xpanstep = 0;
+	fbinfo->fix.ypanstep = 0;
+	fbinfo->fix.ywrapstep = 0;
+	fbinfo->fix.accel = FB_ACCEL_NONE;
+	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	fbinfo->var.nonstd = 0;
+	fbinfo->var.activate = FB_ACTIVATE_NOW;
+	fbinfo->var.height = 53;
+	fbinfo->var.width = 70;
+	fbinfo->var.accel_flags = 0;
+	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+	fbinfo->var.xres = LCD_X_RES;
+	fbinfo->var.xres_virtual = LCD_X_RES;
+	fbinfo->var.yres = LCD_Y_RES;
+	fbinfo->var.yres_virtual = LCD_Y_RES;
+	fbinfo->var.bits_per_pixel = LCD_BPP;
+
+	fbinfo->var.red.offset = 0;
+	fbinfo->var.green.offset = 8;
+	fbinfo->var.blue.offset = 16;
+	fbinfo->var.transp.offset = 0;
+	fbinfo->var.red.length = 8;
+	fbinfo->var.green.length = 8;
+	fbinfo->var.blue.length = 8;
+	fbinfo->var.transp.length = 0;
+	fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8;
+
+	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
+	    fbinfo->var.bits_per_pixel / 8;
+
+
+	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
+	fbinfo->flags = FBINFO_FLAG_DEFAULT;
+
+	info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len +
+				ACTIVE_VIDEO_MEM_OFFSET,
+				&info->dma_handle, GFP_KERNEL);
+
+	if (NULL == info->fb_buffer) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": couldn't allocate dma buffer.\n");
+		ret = -ENOMEM;
+		goto out3;
+	}
+
+	fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
+	fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
+
+	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
+
+	fbinfo->pseudo_palette = &info->pseudo_pal;
+
+	if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
+	    < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       "Fail to allocate colormap (%d entries)\n",
+		       BFIN_LCD_NBR_PALETTE_ENTRIES);
+		ret = -EFAULT;
+		goto out4;
+	}
+
+	if (bfin_t350mcqb_request_ports(1)) {
+		printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
+		ret = -EFAULT;
+		goto out6;
+	}
+
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		ret = -EINVAL;
+		goto out7;
+	}
+
+	ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0,
+			"PPI ERROR", info);
+	if (ret < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": unable to request PPI ERROR IRQ\n");
+		goto out7;
+	}
+
+	if (register_framebuffer(fbinfo) < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": unable to register framebuffer.\n");
+		ret = -EINVAL;
+		goto out8;
+	}
+#ifndef NO_BL_SUPPORT
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 255;
+	bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
+					   &bfin_lq043fb_bl_ops, &props);
+	if (IS_ERR(bl_dev)) {
+		printk(KERN_ERR DRIVER_NAME
+			": unable to register backlight.\n");
+		ret = -EINVAL;
+		unregister_framebuffer(fbinfo);
+		goto out8;
+	}
+
+	lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
+	lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
+#endif
+
+	return 0;
+
+out8:
+	free_irq(info->irq, info);
+out7:
+	bfin_t350mcqb_request_ports(0);
+out6:
+	fb_dealloc_cmap(&fbinfo->cmap);
+out4:
+	dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET,
+			 info->fb_buffer, info->dma_handle);
+out3:
+	framebuffer_release(fbinfo);
+out2:
+	free_dma(CH_PPI);
+out1:
+
+	return ret;
+}
+
+static int bfin_t350mcqb_remove(struct platform_device *pdev)
+{
+
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *info = fbinfo->par;
+
+	unregister_framebuffer(fbinfo);
+
+	free_dma(CH_PPI);
+	free_irq(info->irq, info);
+
+	if (info->fb_buffer != NULL)
+		dma_free_coherent(NULL, fbinfo->fix.smem_len +
+			ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer,
+			info->dma_handle);
+
+	fb_dealloc_cmap(&fbinfo->cmap);
+
+#ifndef NO_BL_SUPPORT
+	lcd_device_unregister(lcd_dev);
+	backlight_device_unregister(bl_dev);
+#endif
+
+	bfin_t350mcqb_request_ports(0);
+
+	framebuffer_release(fbinfo);
+
+	printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
+
+	if (fbi->lq043_open_cnt) {
+		bfin_t350mcqb_disable_ppi();
+		disable_dma(CH_PPI);
+		bfin_t350mcqb_stop_timers();
+		bfin_write_PPI_STATUS(-1);
+	}
+
+
+	return 0;
+}
+
+static int bfin_t350mcqb_resume(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
+
+	if (fbi->lq043_open_cnt) {
+		bfin_t350mcqb_config_dma(fbi);
+		bfin_t350mcqb_config_ppi(fbi);
+		bfin_t350mcqb_init_timers();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_t350mcqb_enable_ppi();
+		bfin_t350mcqb_start_timers();
+	}
+
+	return 0;
+}
+#else
+#define bfin_t350mcqb_suspend	NULL
+#define bfin_t350mcqb_resume	NULL
+#endif
+
+static struct platform_driver bfin_t350mcqb_driver = {
+	.probe = bfin_t350mcqb_probe,
+	.remove = bfin_t350mcqb_remove,
+	.suspend = bfin_t350mcqb_suspend,
+	.resume = bfin_t350mcqb_resume,
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   },
+};
+module_platform_driver(bfin_t350mcqb_driver);
+
+MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/bfin_adv7393fb.c b/drivers/video/fbdev/bfin_adv7393fb.c
new file mode 100644
index 000000000000..a54f7f7d763b
--- /dev/null
+++ b/drivers/video/fbdev/bfin_adv7393fb.c
@@ -0,0 +1,827 @@
+/*
+ * Frame buffer driver for ADV7393/2 video encoder
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or late.
+ */
+
+/*
+ * TODO: Remove Globals
+ * TODO: Code Cleanup
+ */
+
+#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <asm/portmux.h>
+
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include "bfin_adv7393fb.h"
+
+static int mode = VMODE;
+static int mem = VMEM;
+static int nocursor = 1;
+
+static const unsigned short ppi_pins[] = {
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+	0
+};
+
+/*
+ * card parameters
+ */
+
+static struct bfin_adv7393_fb_par {
+	/* structure holding blackfin / adv7393 parameters when
+	   screen is blanked */
+	struct {
+		u8 Mode;	/* ntsc/pal/? */
+	} vga_state;
+	atomic_t ref_count;
+} bfin_par;
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo bfin_adv7393_fb_defined = {
+	.xres = 720,
+	.yres = 480,
+	.xres_virtual = 720,
+	.yres_virtual = 480,
+	.bits_per_pixel = 16,
+	.activate = FB_ACTIVATE_TEST,
+	.height = -1,
+	.width = -1,
+	.left_margin = 0,
+	.right_margin = 0,
+	.upper_margin = 0,
+	.lower_margin = 0,
+	.vmode = FB_VMODE_INTERLACED,
+	.red = {11, 5, 0},
+	.green = {5, 6, 0},
+	.blue = {0, 5, 0},
+	.transp = {0, 0, 0},
+};
+
+static struct fb_fix_screeninfo bfin_adv7393_fb_fix = {
+	.id = "BFIN ADV7393",
+	.smem_len = 720 * 480 * 2,
+	.type = FB_TYPE_PACKED_PIXELS,
+	.visual = FB_VISUAL_TRUECOLOR,
+	.xpanstep = 0,
+	.ypanstep = 0,
+	.line_length = 720 * 2,
+	.accel = FB_ACCEL_NONE
+};
+
+static struct fb_ops bfin_adv7393_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = bfin_adv7393_fb_open,
+	.fb_release = bfin_adv7393_fb_release,
+	.fb_check_var = bfin_adv7393_fb_check_var,
+	.fb_pan_display = bfin_adv7393_fb_pan_display,
+	.fb_blank = bfin_adv7393_fb_blank,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = bfin_adv7393_fb_cursor,
+	.fb_setcolreg = bfin_adv7393_fb_setcolreg,
+};
+
+static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg)
+{
+	if (arg == BUILD) {	/* Build */
+		fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->vb1 == NULL)
+			goto error;
+
+		fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->av1 == NULL)
+			goto error;
+
+		fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->vb2 == NULL)
+			goto error;
+
+		fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->av2 == NULL)
+			goto error;
+
+		/* Build linked DMA descriptor list */
+		fbdev->vb1->next_desc_addr = fbdev->av1;
+		fbdev->av1->next_desc_addr = fbdev->vb2;
+		fbdev->vb2->next_desc_addr = fbdev->av2;
+		fbdev->av2->next_desc_addr = fbdev->vb1;
+
+		/* Save list head */
+		fbdev->descriptor_list_head = fbdev->av2;
+
+		/* Vertical Blanking Field 1 */
+		fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE;
+		fbdev->vb1->cfg = DMA_CFG_VAL;
+
+		fbdev->vb1->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+		fbdev->vb1->x_modify = 0;
+		fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines;
+		fbdev->vb1->y_modify = 0;
+
+		/* Active Video Field 1 */
+
+		fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem;
+		fbdev->av1->cfg = DMA_CFG_VAL;
+		fbdev->av1->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+		fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8;
+		fbdev->av1->y_count = fbdev->modes[mode].a_lines;
+		fbdev->av1->y_modify =
+		    (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
+		     1) * (fbdev->modes[mode].bpp / 8);
+
+		/* Vertical Blanking Field 2 */
+
+		fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE;
+		fbdev->vb2->cfg = DMA_CFG_VAL;
+		fbdev->vb2->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+		fbdev->vb2->x_modify = 0;
+		fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines;
+		fbdev->vb2->y_modify = 0;
+
+		/* Active Video Field 2 */
+
+		fbdev->av2->start_addr =
+		    (unsigned long)fbdev->fb_mem + fbdev->line_len;
+
+		fbdev->av2->cfg = DMA_CFG_VAL;
+
+		fbdev->av2->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+		fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8);
+		fbdev->av2->y_count = fbdev->modes[mode].a_lines;
+
+		fbdev->av2->y_modify =
+		    (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
+		     1) * (fbdev->modes[mode].bpp / 8);
+
+		return 1;
+	}
+
+error:
+	l1_data_sram_free(fbdev->vb1);
+	l1_data_sram_free(fbdev->av1);
+	l1_data_sram_free(fbdev->vb2);
+	l1_data_sram_free(fbdev->av2);
+
+	return 0;
+}
+
+static int bfin_config_dma(struct adv7393fb_device *fbdev)
+{
+	BUG_ON(!(fbdev->fb_mem));
+
+	set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count);
+	set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify);
+	set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count);
+	set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify);
+	set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr);
+	set_dma_next_desc_addr(CH_PPI,
+			       fbdev->descriptor_list_head->next_desc_addr);
+	set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg);
+
+	return 1;
+}
+
+static void bfin_disable_dma(void)
+{
+	bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN);
+}
+
+static void bfin_config_ppi(struct adv7393fb_device *fbdev)
+{
+	if (ANOMALY_05000183) {
+		bfin_write_TIMER2_CONFIG(WDTH_CAP);
+		bfin_write_TIMER_ENABLE(TIMEN2);
+	}
+
+	bfin_write_PPI_CONTROL(0x381E);
+	bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines);
+	bfin_write_PPI_COUNT(fbdev->modes[mode].xres +
+			     fbdev->modes[mode].boeft_blank - 1);
+	bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1);
+}
+
+static void bfin_enable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+}
+
+static void bfin_disable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
+}
+
+static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static inline int adv7393_read(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int
+adv7393_write_block(struct i2c_client *client,
+		    const u8 *data, unsigned int len)
+{
+	int ret = -1;
+	u8 reg;
+
+	while (len >= 2) {
+		reg = *data++;
+		ret = adv7393_write(client, reg, *data++);
+		if (ret < 0)
+			break;
+		len -= 2;
+	}
+
+	return ret;
+}
+
+static int adv7393_mode(struct i2c_client *client, u16 mode)
+{
+	switch (mode) {
+	case POWER_ON:		/* ADV7393 Sleep mode OFF */
+		adv7393_write(client, 0x00, 0x1E);
+		break;
+	case POWER_DOWN:	/* ADV7393 Sleep mode ON */
+		adv7393_write(client, 0x00, 0x1F);
+		break;
+	case BLANK_OFF:		/* Pixel Data Valid */
+		adv7393_write(client, 0x82, 0xCB);
+		break;
+	case BLANK_ON:		/* Pixel Data Invalid */
+		adv7393_write(client, 0x82, 0x8B);
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+static irqreturn_t ppi_irq_error(int irq, void *dev_id)
+{
+
+	struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id;
+
+	u16 status = bfin_read_PPI_STATUS();
+
+	pr_debug("%s: PPI Status = 0x%X\n", __func__, status);
+
+	if (status) {
+		bfin_disable_dma();	/* TODO: Check Sequence */
+		bfin_disable_ppi();
+		bfin_clear_PPI_STATUS();
+		bfin_config_dma(fbdev);
+		bfin_enable_ppi();
+	}
+
+	return IRQ_HANDLED;
+
+}
+
+static int proc_output(char *buf)
+{
+	char *p = buf;
+
+	p += sprintf(p,
+		"Usage:\n"
+		"echo 0x[REG][Value] > adv7393\n"
+		"example: echo 0x1234 >adv7393\n"
+		"writes 0x34 into Register 0x12\n");
+
+	return p - buf;
+}
+
+static ssize_t
+adv7393_read_proc(struct file *file, char __user *buf,
+		  size_t size, loff_t *ppos)
+{
+	static const char message[] = "Usage:\n"
+		"echo 0x[REG][Value] > adv7393\n"
+		"example: echo 0x1234 >adv7393\n"
+		"writes 0x34 into Register 0x12\n";
+	return simple_read_from_buffer(buf, size, ppos, message,
+					sizeof(message));
+}
+
+static ssize_t
+adv7393_write_proc(struct file *file, const char __user * buffer,
+		   size_t count, loff_t *ppos)
+{
+	struct adv7393fb_device *fbdev = PDE_DATA(file_inode(file));
+	unsigned int val;
+	int ret;
+
+	ret = kstrtouint_from_user(buffer, count, 0, &val);
+	if (ret)
+		return -EFAULT;
+
+	adv7393_write(fbdev->client, val >> 8, val & 0xff);
+
+	return count;
+}
+
+static const struct file_operations fops = {
+	.read = adv7393_read_proc,
+	.write = adv7393_write_proc,
+	.llseek = default_llseek,
+};
+
+static int bfin_adv7393_fb_probe(struct i2c_client *client,
+				 const struct i2c_device_id *id)
+{
+	int ret = 0;
+	struct proc_dir_entry *entry;
+	int num_modes = ARRAY_SIZE(known_modes);
+
+	struct adv7393fb_device *fbdev = NULL;
+
+	if (mem > 2) {
+		dev_err(&client->dev, "mem out of allowed range [1;2]\n");
+		return -EINVAL;
+	}
+
+	if (mode > num_modes) {
+		dev_err(&client->dev, "mode %d: not supported", mode);
+		return -EFAULT;
+	}
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev) {
+		dev_err(&client->dev, "failed to allocate device private record");
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(client, fbdev);
+
+	fbdev->modes = known_modes;
+	fbdev->client = client;
+
+	fbdev->fb_len =
+	    mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres *
+	    (fbdev->modes[mode].bpp / 8);
+
+	fbdev->line_len =
+	    fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8);
+
+	/* Workaround "PPI Does Not Start Properly In Specific Mode" */
+	if (ANOMALY_05000400) {
+		ret = gpio_request_one(P_IDENT(P_PPI0_FS3), GPIOF_OUT_INIT_LOW,
+					"PPI0_FS3")
+		if (ret) {
+			dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
+			ret = -EBUSY;
+			goto free_fbdev;
+		}
+	}
+
+	if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
+		dev_err(&client->dev, "requesting PPI peripheral failed\n");
+		ret = -EFAULT;
+		goto free_gpio;
+	}
+
+	fbdev->fb_mem =
+	    dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle,
+			       GFP_KERNEL);
+
+	if (NULL == fbdev->fb_mem) {
+		dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n",
+		       (u32) fbdev->fb_len);
+		ret = -ENOMEM;
+		goto free_ppi_pins;
+	}
+
+	fbdev->info.screen_base = (void *)fbdev->fb_mem;
+	bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem;
+
+	bfin_adv7393_fb_fix.smem_len = fbdev->fb_len;
+	bfin_adv7393_fb_fix.line_length = fbdev->line_len;
+
+	if (mem > 1)
+		bfin_adv7393_fb_fix.ypanstep = 1;
+
+	bfin_adv7393_fb_defined.red.length = 5;
+	bfin_adv7393_fb_defined.green.length = 6;
+	bfin_adv7393_fb_defined.blue.length = 5;
+
+	bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres;
+	bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres;
+	bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres;
+	bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres;
+	bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp;
+
+	fbdev->info.fbops = &bfin_adv7393_fb_ops;
+	fbdev->info.var = bfin_adv7393_fb_defined;
+	fbdev->info.fix = bfin_adv7393_fb_fix;
+	fbdev->info.par = &bfin_par;
+	fbdev->info.flags = FBINFO_DEFAULT;
+
+	fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
+	if (!fbdev->info.pseudo_palette) {
+		dev_err(&client->dev, "failed to allocate pseudo_palette\n");
+		ret = -ENOMEM;
+		goto free_fb_mem;
+	}
+
+	if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+		dev_err(&client->dev, "failed to allocate colormap (%d entries)\n",
+			   BFIN_LCD_NBR_PALETTE_ENTRIES);
+		ret = -EFAULT;
+		goto free_palette;
+	}
+
+	if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) {
+		dev_err(&client->dev, "unable to request PPI DMA\n");
+		ret = -EFAULT;
+		goto free_cmap;
+	}
+
+	if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0,
+			"PPI ERROR", fbdev) < 0) {
+		dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
+		ret = -EFAULT;
+		goto free_ch_ppi;
+	}
+
+	fbdev->open = 0;
+
+	ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd,
+				fbdev->modes[mode].adv7393_i2c_initd_len);
+
+	if (ret) {
+		dev_err(&client->dev, "i2c attach: init error\n");
+		goto free_irq_ppi;
+	}
+
+
+	if (register_framebuffer(&fbdev->info) < 0) {
+		dev_err(&client->dev, "unable to register framebuffer\n");
+		ret = -EFAULT;
+		goto free_irq_ppi;
+	}
+
+	dev_info(&client->dev, "fb%d: %s frame buffer device\n",
+	       fbdev->info.node, fbdev->info.fix.id);
+	dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
+
+	entry = proc_create_data("driver/adv7393", 0, NULL, &fops, fbdev);
+	if (!entry) {
+		dev_err(&client->dev, "unable to create /proc entry\n");
+		ret = -EFAULT;
+		goto free_fb;
+	}
+	return 0;
+
+free_fb:
+	unregister_framebuffer(&fbdev->info);
+free_irq_ppi:
+	free_irq(IRQ_PPI_ERROR, fbdev);
+free_ch_ppi:
+	free_dma(CH_PPI);
+free_cmap:
+	fb_dealloc_cmap(&fbdev->info.cmap);
+free_palette:
+	kfree(fbdev->info.pseudo_palette);
+free_fb_mem:
+	dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem,
+			  fbdev->dma_handle);
+free_ppi_pins:
+	peripheral_free_list(ppi_pins);
+free_gpio:
+	if (ANOMALY_05000400)
+		gpio_free(P_IDENT(P_PPI0_FS3));
+free_fbdev:
+	kfree(fbdev);
+
+	return ret;
+}
+
+static int bfin_adv7393_fb_open(struct fb_info *info, int user)
+{
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	fbdev->info.screen_base = (void *)fbdev->fb_mem;
+	if (!fbdev->info.screen_base) {
+		dev_err(&fbdev->client->dev, "unable to map device\n");
+		return -ENOMEM;
+	}
+
+	fbdev->open = 1;
+	dma_desc_list(fbdev, BUILD);
+	adv7393_mode(fbdev->client, BLANK_OFF);
+	bfin_config_ppi(fbdev);
+	bfin_config_dma(fbdev);
+	bfin_enable_ppi();
+
+	return 0;
+}
+
+static int bfin_adv7393_fb_release(struct fb_info *info, int user)
+{
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	adv7393_mode(fbdev->client, BLANK_ON);
+	bfin_disable_dma();
+	bfin_disable_ppi();
+	dma_desc_list(fbdev, DESTRUCT);
+	fbdev->open = 0;
+	return 0;
+}
+
+static int
+bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+
+	switch (var->bits_per_pixel) {
+	case 16:/* DIRECTCOLOUR, 64k */
+		var->red.offset = info->var.red.offset;
+		var->green.offset = info->var.green.offset;
+		var->blue.offset = info->var.blue.offset;
+		var->red.length = info->var.red.length;
+		var->green.length = info->var.green.length;
+		var->blue.length = info->var.blue.length;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		break;
+	default:
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres ||
+	    info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u\n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int
+bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int dy;
+	u32 dmaaddr;
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	if (!var || !info)
+		return -EINVAL;
+
+	if (var->xoffset - info->var.xoffset) {
+		/* No support for X panning for now! */
+		return -EINVAL;
+	}
+	dy = var->yoffset - info->var.yoffset;
+
+	if (dy) {
+		pr_debug("%s: Panning screen of %d lines\n", __func__, dy);
+
+		dmaaddr = fbdev->av1->start_addr;
+		dmaaddr += (info->fix.line_length * dy);
+		/* TODO: Wait for current frame to finished */
+
+		fbdev->av1->start_addr = (unsigned long)dmaaddr;
+		fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len;
+	}
+
+	return 0;
+
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+static int bfin_adv7393_fb_blank(int blank, struct fb_info *info)
+{
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	switch (blank) {
+
+	case VESA_NO_BLANKING:
+		/* Turn on panel */
+		adv7393_mode(fbdev->client, BLANK_OFF);
+		break;
+
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+	case VESA_POWERDOWN:
+		/* Turn off panel */
+		adv7393_mode(fbdev->client, BLANK_ON);
+		break;
+
+	default:
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green,
+				     u_int blue, u_int transp,
+				     struct fb_info *info)
+{
+	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red   >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue  >>= (16 - info->var.blue.length);
+
+		value = (red   << info->var.red.offset) |
+			(green << info->var.green.offset)|
+			(blue  << info->var.blue.offset);
+		value &= 0xFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+	}
+
+	return 0;
+}
+
+static int bfin_adv7393_fb_remove(struct i2c_client *client)
+{
+	struct adv7393fb_device *fbdev = i2c_get_clientdata(client);
+
+	adv7393_mode(client, POWER_DOWN);
+
+	if (fbdev->fb_mem)
+		dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle);
+	free_dma(CH_PPI);
+	free_irq(IRQ_PPI_ERROR, fbdev);
+	unregister_framebuffer(&fbdev->info);
+	remove_proc_entry("driver/adv7393", NULL);
+	fb_dealloc_cmap(&fbdev->info.cmap);
+	kfree(fbdev->info.pseudo_palette);
+
+	if (ANOMALY_05000400)
+		gpio_free(P_IDENT(P_PPI0_FS3));	/* FS3 */
+	peripheral_free_list(ppi_pins);
+	kfree(fbdev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_adv7393_fb_suspend(struct device *dev)
+{
+	struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
+
+	if (fbdev->open) {
+		bfin_disable_dma();
+		bfin_disable_ppi();
+		dma_desc_list(fbdev, DESTRUCT);
+	}
+	adv7393_mode(fbdev->client, POWER_DOWN);
+
+	return 0;
+}
+
+static int bfin_adv7393_fb_resume(struct device *dev)
+{
+	struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
+
+	adv7393_mode(fbdev->client, POWER_ON);
+
+	if (fbdev->open) {
+		dma_desc_list(fbdev, BUILD);
+		bfin_config_ppi(fbdev);
+		bfin_config_dma(fbdev);
+		bfin_enable_ppi();
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = {
+	.suspend = bfin_adv7393_fb_suspend,
+	.resume  = bfin_adv7393_fb_resume,
+};
+#endif
+
+static const struct i2c_device_id bfin_adv7393_id[] = {
+	{DRIVER_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id);
+
+static struct i2c_driver bfin_adv7393_fb_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+#ifdef CONFIG_PM
+		.pm   = &bfin_adv7393_dev_pm_ops,
+#endif
+	},
+	.probe = bfin_adv7393_fb_probe,
+	.remove = bfin_adv7393_fb_remove,
+	.id_table = bfin_adv7393_id,
+};
+
+static int __init bfin_adv7393_fb_driver_init(void)
+{
+#if  defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+	request_module("i2c-bfin-twi");
+#else
+	request_module("i2c-gpio");
+#endif
+
+	return i2c_add_driver(&bfin_adv7393_fb_driver);
+}
+module_init(bfin_adv7393_fb_driver_init);
+
+static void __exit bfin_adv7393_fb_driver_cleanup(void)
+{
+	i2c_del_driver(&bfin_adv7393_fb_driver);
+}
+module_exit(bfin_adv7393_fb_driver_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder");
+
+module_param(mode, int, 0);
+MODULE_PARM_DESC(mode,
+	"Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)");
+
+module_param(mem, int, 0);
+MODULE_PARM_DESC(mem,
+	"Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)");
+
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
diff --git a/drivers/video/fbdev/bfin_adv7393fb.h b/drivers/video/fbdev/bfin_adv7393fb.h
new file mode 100644
index 000000000000..cd591b5152a5
--- /dev/null
+++ b/drivers/video/fbdev/bfin_adv7393fb.h
@@ -0,0 +1,321 @@
+/*
+ * Frame buffer driver for ADV7393/2 video encoder
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or late.
+ */
+
+#ifndef __BFIN_ADV7393FB_H__
+#define __BFIN_ADV7393FB_H__
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
+
+#ifdef CONFIG_NTSC
+# define VMODE 0
+#endif
+#ifdef CONFIG_PAL
+# define VMODE 1
+#endif
+#ifdef CONFIG_NTSC_640x480
+# define VMODE 2
+#endif
+#ifdef CONFIG_PAL_640x480
+# define VMODE 3
+#endif
+#ifdef CONFIG_NTSC_YCBCR
+# define VMODE 4
+#endif
+#ifdef CONFIG_PAL_YCBCR
+# define VMODE 5
+#endif
+
+#ifndef VMODE
+# define VMODE 1
+#endif
+
+#ifdef CONFIG_ADV7393_2XMEM
+# define VMEM 2
+#else
+# define VMEM 1
+#endif
+
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
+# define DMA_CFG_VAL	0x7935	/* Set Sync Bit */
+# define VB_DUMMY_MEMORY_SOURCE	L1_DATA_B_START
+#else
+# define DMA_CFG_VAL	0x7915
+# define VB_DUMMY_MEMORY_SOURCE	BOOT_ROM_START
+#endif
+
+enum {
+	DESTRUCT,
+	BUILD,
+};
+
+enum {
+	POWER_ON,
+	POWER_DOWN,
+	BLANK_ON,
+	BLANK_OFF,
+};
+
+#define DRIVER_NAME "bfin-adv7393"
+
+struct adv7393fb_modes {
+	const s8 name[25];	/* Full name */
+	u16 xres;		/* Active Horizonzal Pixels  */
+	u16 yres;		/* Active Vertical Pixels  */
+	u16 bpp;
+	u16 vmode;
+	u16 a_lines;		/* Active Lines per Field */
+	u16 vb1_lines;		/* Vertical Blanking Field 1 Lines */
+	u16 vb2_lines;		/* Vertical Blanking Field 2 Lines */
+	u16 tot_lines;		/* Total Lines per Frame */
+	u16 boeft_blank;	/* Before Odd/Even Field Transition No. of Blank Pixels */
+	u16 aoeft_blank;	/* After Odd/Even Field Transition No. of Blank Pixels */
+	const s8 *adv7393_i2c_initd;
+	u16 adv7393_i2c_initd_len;
+};
+
+static const u8 init_NTSC_TESTPATTERN[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x10,	/* SSAF Luma Filter Enabled, NTSC Mode */
+	0x82, 0xCB,	/* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x84, 0x40,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+};
+
+static const u8 init_NTSC[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0xC3, 0x26,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xC5, 0x12,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xBD, 0x19,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xBF, 0x42,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
+	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
+	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
+	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x20,
+	0x8A, 0x0d,
+};
+
+static const u8 init_PAL[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0xC3, 0x26,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xC5, 0x12,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xBD, 0x19,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0xBF, 0x42,	/* Program RGB->YCrCb Color Space conversion matrix */
+	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
+	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
+	0x8E, 0x09,	/* PAL Subcarrier Frequency */
+	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x20,
+	0x8A, 0x0d,
+};
+
+static const u8 init_NTSC_YCbCr[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
+	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
+	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
+	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x08,
+	0x8A, 0x0d,
+};
+
+static const u8 init_PAL_YCbCr[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
+	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
+	0x8E, 0x09,	/* PAL Subcarrier Frequency */
+	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x08,
+	0x8A, 0x0d,
+};
+
+static struct adv7393fb_modes known_modes[] = {
+	/* NTSC 720x480 CRT */
+	{
+		.name = "NTSC 720x480",
+		.xres = 720,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 240,
+		.vb1_lines = 22,
+		.vb2_lines = 23,
+		.tot_lines = 525,
+		.boeft_blank = 16,
+		.aoeft_blank = 122,
+		.adv7393_i2c_initd = init_NTSC,
+		.adv7393_i2c_initd_len = sizeof(init_NTSC)
+	},
+	/* PAL 720x480 CRT */
+	{
+		.name = "PAL 720x576",
+		.xres = 720,
+		.yres = 576,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 288,
+		.vb1_lines = 24,
+		.vb2_lines = 25,
+		.tot_lines = 625,
+		.boeft_blank = 12,
+		.aoeft_blank = 132,
+		.adv7393_i2c_initd = init_PAL,
+		.adv7393_i2c_initd_len = sizeof(init_PAL)
+	},
+	/* NTSC 640x480 CRT Experimental */
+	{
+		.name = "NTSC 640x480",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 240,
+		.vb1_lines = 22,
+		.vb2_lines = 23,
+		.tot_lines = 525,
+		.boeft_blank = 16 + 40,
+		.aoeft_blank = 122 + 40,
+		.adv7393_i2c_initd = init_NTSC,
+		.adv7393_i2c_initd_len = sizeof(init_NTSC)
+	},
+	/* PAL 640x480 CRT Experimental */
+	{
+		.name = "PAL 640x480",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 288 - 20,
+		.vb1_lines = 24 + 20,
+		.vb2_lines = 25 + 20,
+		.tot_lines = 625,
+		.boeft_blank = 12 + 40,
+		.aoeft_blank = 132 + 40,
+		.adv7393_i2c_initd = init_PAL,
+		.adv7393_i2c_initd_len = sizeof(init_PAL)
+	},
+	/* NTSC 720x480 YCbCR */
+	{
+		.name = "NTSC 720x480 YCbCR",
+		.xres = 720,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 240,
+		.vb1_lines = 22,
+		.vb2_lines = 23,
+		.tot_lines = 525,
+		.boeft_blank = 16,
+		.aoeft_blank = 122,
+		.adv7393_i2c_initd = init_NTSC_YCbCr,
+		.adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr)
+	},
+	/* PAL 720x480 CRT */
+	{
+		.name = "PAL 720x576 YCbCR",
+		.xres = 720,
+		.yres = 576,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 288,
+		.vb1_lines = 24,
+		.vb2_lines = 25,
+		.tot_lines = 625,
+		.boeft_blank = 12,
+		.aoeft_blank = 132,
+		.adv7393_i2c_initd = init_PAL_YCbCr,
+		.adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr)
+	}
+};
+
+struct adv7393fb_regs {
+
+};
+
+struct adv7393fb_device {
+	struct fb_info info;	/* FB driver info record */
+
+	struct i2c_client *client;
+
+	struct dmasg *descriptor_list_head;
+	struct dmasg *vb1;
+	struct dmasg *av1;
+	struct dmasg *vb2;
+	struct dmasg *av2;
+
+	dma_addr_t dma_handle;
+
+	struct fb_info bfin_adv7393_fb;
+
+	struct adv7393fb_modes *modes;
+
+	struct adv7393fb_regs *regs;	/* Registers memory map */
+	size_t regs_len;
+	size_t fb_len;
+	size_t line_len;
+	u16 open;
+	u16 *fb_mem;		/* RGB Buffer */
+
+};
+
+#define to_adv7393fb_device(_info) \
+	  (_info ? container_of(_info, struct adv7393fb_device, info) : NULL);
+
+static int bfin_adv7393_fb_open(struct fb_info *info, int user);
+static int bfin_adv7393_fb_release(struct fb_info *info, int user);
+static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var,
+				     struct fb_info *info);
+
+static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var,
+				       struct fb_info *info);
+
+static int bfin_adv7393_fb_blank(int blank, struct fb_info *info);
+
+static void bfin_config_ppi(struct adv7393fb_device *fbdev);
+static int bfin_config_dma(struct adv7393fb_device *fbdev);
+static void bfin_disable_dma(void);
+static void bfin_enable_ppi(void);
+static void bfin_disable_ppi(void);
+
+static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value);
+static inline int adv7393_read(struct i2c_client *client, u8 reg);
+static int adv7393_write_block(struct i2c_client *client, const u8 *data,
+			       unsigned int len);
+
+int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int,
+				     u_int, struct fb_info *info);
+
+#endif
diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c
new file mode 100644
index 000000000000..8556264b16b7
--- /dev/null
+++ b/drivers/video/fbdev/broadsheetfb.c
@@ -0,0 +1,1223 @@
+/*
+ * broadsheetfb.c -- FB driver for E-Ink Broadsheet controller
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver is written to be used with the Broadsheet display controller.
+ *
+ * It is intended to be architecture independent. A board specific driver
+ * must be used to perform all the physical IO interactions.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/firmware.h>
+#include <linux/uaccess.h>
+
+#include <video/broadsheetfb.h>
+
+/* track panel specific parameters */
+struct panel_info {
+	int w;
+	int h;
+	u16 sdcfg;
+	u16 gdcfg;
+	u16 lutfmt;
+	u16 fsynclen;
+	u16 fendfbegin;
+	u16 lsynclen;
+	u16 lendlbegin;
+	u16 pixclk;
+};
+
+/* table of panel specific parameters to be indexed into by the board drivers */
+static struct panel_info panel_table[] = {
+	{	/* standard 6" on TFT backplane */
+		.w = 800,
+		.h = 600,
+		.sdcfg = (100 | (1 << 8) | (1 << 9)),
+		.gdcfg = 2,
+		.lutfmt = (4 | (1 << 7)),
+		.fsynclen = 4,
+		.fendfbegin = (10 << 8) | 4,
+		.lsynclen = 10,
+		.lendlbegin = (100 << 8) | 4,
+		.pixclk = 6,
+	},
+	{	/* custom 3.7" flexible on PET or steel */
+		.w = 320,
+		.h = 240,
+		.sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
+		.gdcfg = 3,
+		.lutfmt = (4 | (1 << 7)),
+		.fsynclen = 0,
+		.fendfbegin = (80 << 8) | 4,
+		.lsynclen = 10,
+		.lendlbegin = (80 << 8) | 20,
+		.pixclk = 14,
+	},
+	{	/* standard 9.7" on TFT backplane */
+		.w = 1200,
+		.h = 825,
+		.sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
+		.gdcfg = 2,
+		.lutfmt = (4 | (1 << 7)),
+		.fsynclen = 0,
+		.fendfbegin = (4 << 8) | 4,
+		.lsynclen = 4,
+		.lendlbegin = (60 << 8) | 10,
+		.pixclk = 3,
+	},
+};
+
+#define DPY_W 800
+#define DPY_H 600
+
+static struct fb_fix_screeninfo broadsheetfb_fix = {
+	.id =		"broadsheetfb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_STATIC_PSEUDOCOLOR,
+	.xpanstep =	0,
+	.ypanstep =	0,
+	.ywrapstep =	0,
+	.line_length =	DPY_W,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo broadsheetfb_var = {
+	.xres		= DPY_W,
+	.yres		= DPY_H,
+	.xres_virtual	= DPY_W,
+	.yres_virtual	= DPY_H,
+	.bits_per_pixel	= 8,
+	.grayscale	= 1,
+	.red =		{ 0, 4, 0 },
+	.green =	{ 0, 4, 0 },
+	.blue =		{ 0, 4, 0 },
+	.transp =	{ 0, 0, 0 },
+};
+
+/* main broadsheetfb functions */
+static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
+{
+	par->board->set_ctl(par, BS_WR, 0);
+	par->board->set_hdb(par, data);
+	par->board->set_ctl(par, BS_WR, 1);
+}
+
+static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
+{
+	par->board->set_ctl(par, BS_DC, 0);
+	broadsheet_gpio_issue_data(par, data);
+}
+
+static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
+{
+	par->board->wait_for_rdy(par);
+
+	par->board->set_ctl(par, BS_CS, 0);
+	broadsheet_gpio_issue_cmd(par, data);
+	par->board->set_ctl(par, BS_DC, 1);
+	par->board->set_ctl(par, BS_CS, 1);
+}
+
+static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
+					int argc, u16 *argv)
+{
+	int i;
+
+	par->board->wait_for_rdy(par);
+
+	par->board->set_ctl(par, BS_CS, 0);
+	broadsheet_gpio_issue_cmd(par, cmd);
+	par->board->set_ctl(par, BS_DC, 1);
+
+	for (i = 0; i < argc; i++)
+		broadsheet_gpio_issue_data(par, argv[i]);
+	par->board->set_ctl(par, BS_CS, 1);
+}
+
+static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
+				    int argc, u16 *argv)
+{
+	int i;
+
+	par->board->mmio_write(par, BS_MMIO_CMD, cmd);
+
+	for (i = 0; i < argc; i++)
+		par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
+}
+
+static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
+{
+	if (par->board->mmio_write)
+		par->board->mmio_write(par, BS_MMIO_CMD, data);
+	else
+		broadsheet_gpio_send_command(par, data);
+}
+
+static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
+				    int argc, u16 *argv)
+{
+	if (par->board->mmio_write)
+		broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
+	else
+		broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
+}
+
+static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
+					u16 *data)
+{
+	int i;
+	u16 tmp;
+
+	par->board->set_ctl(par, BS_CS, 0);
+	par->board->set_ctl(par, BS_DC, 1);
+
+	for (i = 0; i < size; i++) {
+		par->board->set_ctl(par, BS_WR, 0);
+		tmp = (data[i] & 0x0F) << 4;
+		tmp |= (data[i] & 0x0F00) << 4;
+		par->board->set_hdb(par, tmp);
+		par->board->set_ctl(par, BS_WR, 1);
+	}
+
+	par->board->set_ctl(par, BS_CS, 1);
+}
+
+static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
+				   u16 *data)
+{
+	int i;
+	u16 tmp;
+
+	for (i = 0; i < size; i++) {
+		tmp = (data[i] & 0x0F) << 4;
+		tmp |= (data[i] & 0x0F00) << 4;
+		par->board->mmio_write(par, BS_MMIO_DATA, tmp);
+	}
+
+}
+
+static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
+				   u16 *data)
+{
+	if (par->board->mmio_write)
+		broadsheet_mmio_burst_write(par, size, data);
+	else
+		broadsheet_gpio_burst_write(par, size, data);
+}
+
+static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
+{
+	u16 res;
+	/* wait for ready to go hi. (lo is busy) */
+	par->board->wait_for_rdy(par);
+
+	/* cs lo, dc lo for cmd, we lo for each data, db as usual */
+	par->board->set_ctl(par, BS_DC, 1);
+	par->board->set_ctl(par, BS_CS, 0);
+	par->board->set_ctl(par, BS_WR, 0);
+
+	res = par->board->get_hdb(par);
+
+	/* strobe wr */
+	par->board->set_ctl(par, BS_WR, 1);
+	par->board->set_ctl(par, BS_CS, 1);
+
+	return res;
+}
+
+
+static u16 broadsheet_get_data(struct broadsheetfb_par *par)
+{
+	if (par->board->mmio_read)
+		return par->board->mmio_read(par);
+	else
+		return broadsheet_gpio_get_data(par);
+}
+
+static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
+					u16 data)
+{
+	/* wait for ready to go hi. (lo is busy) */
+	par->board->wait_for_rdy(par);
+
+	/* cs lo, dc lo for cmd, we lo for each data, db as usual */
+	par->board->set_ctl(par, BS_CS, 0);
+
+	broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
+
+	par->board->set_ctl(par, BS_DC, 1);
+
+	broadsheet_gpio_issue_data(par, reg);
+	broadsheet_gpio_issue_data(par, data);
+
+	par->board->set_ctl(par, BS_CS, 1);
+}
+
+static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
+				 u16 data)
+{
+	par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
+	par->board->mmio_write(par, BS_MMIO_DATA, reg);
+	par->board->mmio_write(par, BS_MMIO_DATA, data);
+
+}
+
+static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
+					u16 data)
+{
+	if (par->board->mmio_write)
+		broadsheet_mmio_write_reg(par, reg, data);
+	else
+		broadsheet_gpio_write_reg(par, reg, data);
+}
+
+static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
+					u32 data)
+{
+	broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
+	broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
+}
+
+
+static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
+{
+	broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, &reg);
+	par->board->wait_for_rdy(par);
+	return broadsheet_get_data(par);
+}
+
+/* functions for waveform manipulation */
+static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
+{
+	return broadsheet_read_reg(par, 0x000A) & 0x0001;
+}
+
+static int broadsheet_setup_plls(struct broadsheetfb_par *par)
+{
+	int retry_count = 0;
+	u16 tmp;
+
+	/* disable arral saemipu mode */
+	broadsheet_write_reg(par, 0x0006, 0x0000);
+
+	broadsheet_write_reg(par, 0x0010, 0x0004);
+	broadsheet_write_reg(par, 0x0012, 0x5949);
+	broadsheet_write_reg(par, 0x0014, 0x0040);
+	broadsheet_write_reg(par, 0x0016, 0x0000);
+
+	do {
+		if (retry_count++ > 100)
+			return -ETIMEDOUT;
+		mdelay(1);
+	} while (!is_broadsheet_pll_locked(par));
+
+	tmp = broadsheet_read_reg(par, 0x0006);
+	tmp &= ~0x1;
+	broadsheet_write_reg(par, 0x0006, tmp);
+
+	return 0;
+}
+
+static int broadsheet_setup_spi(struct broadsheetfb_par *par)
+{
+
+	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
+	broadsheet_write_reg(par, 0x0208, 0x0001);
+
+	return 0;
+}
+
+static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
+						u16 *orig_sfmcd)
+{
+
+	*orig_sfmcd = broadsheet_read_reg(par, 0x0204);
+	broadsheet_write_reg(par, 0x0208, 0);
+	broadsheet_write_reg(par, 0x0204, 0);
+	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
+
+	return 0;
+}
+
+static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
+						u16 reg, int bitnum, int val,
+						int timeout)
+{
+	u16 tmp;
+
+	do {
+		tmp = broadsheet_read_reg(par, reg);
+		if (((tmp >> bitnum) & 1) == val)
+			return 0;
+		mdelay(1);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
+{
+	broadsheet_write_reg(par, 0x0202, (data | 0x100));
+
+	return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
+}
+
+static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
+{
+	int err;
+	u16 tmp;
+
+	broadsheet_write_reg(par, 0x0202, 0);
+
+	err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
+	if (err)
+		return err;
+
+	tmp = broadsheet_read_reg(par, 0x200);
+
+	*data = tmp & 0xFF;
+
+	return 0;
+}
+
+static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
+								int timeout)
+{
+	u8 tmp;
+	int err;
+
+	do {
+		broadsheet_write_reg(par, 0x0208, 1);
+
+		err = broadsheet_spiflash_write_byte(par, 0x05);
+		if (err)
+			goto failout;
+
+		err = broadsheet_spiflash_read_byte(par, &tmp);
+		if (err)
+			goto failout;
+
+		broadsheet_write_reg(par, 0x0208, 0);
+
+		if (!(tmp & 0x1))
+			return 0;
+
+		mdelay(5);
+	} while (timeout--);
+
+	dev_err(par->info->device, "Timed out waiting for spiflash status\n");
+	return -ETIMEDOUT;
+
+failout:
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
+							u8 op, u32 addr)
+{
+	int i;
+	u8 tmp;
+	int err;
+
+	broadsheet_write_reg(par, 0x0208, 1);
+
+	err = broadsheet_spiflash_write_byte(par, op);
+	if (err)
+		return err;
+
+	for (i = 2; i >= 0; i--) {
+		tmp = ((addr >> (i * 8)) & 0xFF);
+		err = broadsheet_spiflash_write_byte(par, tmp);
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
+						int *flash_type)
+{
+	int err = 0;
+	u8 sig;
+
+	err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
+	if (err)
+		goto failout;
+
+	err = broadsheet_spiflash_read_byte(par, &sig);
+	if (err)
+		goto failout;
+
+	if ((sig != 0x10) && (sig != 0x11)) {
+		dev_err(par->info->device, "Unexpected flash type\n");
+		err = -EINVAL;
+		goto failout;
+	}
+
+	*flash_type = sig;
+
+failout:
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
+					u16 *initial_sfmcd, int *flash_type)
+
+{
+	int err;
+
+	err = broadsheet_setup_plls(par);
+	if (err)
+		return err;
+
+	broadsheet_write_reg(par, 0x0106, 0x0203);
+
+	err = broadsheet_setup_spi(par);
+	if (err)
+		return err;
+
+	err = broadsheet_setup_spiflash(par, initial_sfmcd);
+	if (err)
+		return err;
+
+	return broadsheet_verify_spiflash(par, flash_type);
+}
+
+static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
+						int mode)
+{
+	int err;
+
+	broadsheet_write_reg(par, 0x0208, 1);
+	if (mode)
+		err = broadsheet_spiflash_write_byte(par, 0x06);
+	else
+		err = broadsheet_spiflash_write_byte(par, 0x04);
+
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
+						int addr)
+{
+	int err;
+
+	broadsheet_spiflash_write_control(par, 1);
+
+	err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
+
+	broadsheet_write_reg(par, 0x0208, 0);
+
+	if (err)
+		return err;
+
+	err = broadsheet_spiflash_wait_for_status(par, 1000);
+
+	return err;
+}
+
+static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
+						int addr, int size, char *data)
+{
+	int err;
+	int i;
+
+	err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
+	if (err)
+		goto failout;
+
+	for (i = 0; i < size; i++) {
+		err = broadsheet_spiflash_read_byte(par, &data[i]);
+		if (err)
+			goto failout;
+	}
+
+failout:
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+#define BS_SPIFLASH_PAGE_SIZE 256
+static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
+						int addr, const char *data)
+{
+	int err;
+	int i;
+
+	broadsheet_spiflash_write_control(par, 1);
+
+	err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
+	if (err)
+		goto failout;
+
+	for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
+		err = broadsheet_spiflash_write_byte(par, data[i]);
+		if (err)
+			goto failout;
+	}
+
+	broadsheet_write_reg(par, 0x0208, 0);
+
+	err = broadsheet_spiflash_wait_for_status(par, 100);
+
+failout:
+	return err;
+}
+
+static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
+				int addr, const char *data, int sector_size)
+{
+	int i;
+	int err;
+
+	for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
+		err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+/*
+ * The caller must guarantee that the data to be rewritten is entirely
+ * contained within this sector. That is, data_start_addr + data_len
+ * must be less than sector_start_addr + sector_size.
+ */
+static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
+					int sector_size, int data_start_addr,
+					int data_len, const char *data)
+{
+	int err;
+	char *sector_buffer;
+	int tail_start_addr;
+	int start_sector_addr;
+
+	sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL);
+	if (!sector_buffer)
+		return -ENOMEM;
+
+	/* the start address of the sector is the 0th byte of that sector */
+	start_sector_addr = (data_start_addr / sector_size) * sector_size;
+
+	/*
+	 * check if there is head data that we need to readback into our sector
+	 * buffer first
+	 */
+	if (data_start_addr != start_sector_addr) {
+		/*
+		 * we need to read every byte up till the start address of our
+		 * data and we put it into our sector buffer.
+		 */
+		err = broadsheet_spiflash_read_range(par, start_sector_addr,
+						data_start_addr, sector_buffer);
+		if (err)
+			return err;
+	}
+
+	/* now we copy our data into the right place in the sector buffer */
+	memcpy(sector_buffer + data_start_addr, data, data_len);
+
+	/*
+	 * now we check if there is a tail section of the sector that we need to
+	 * readback.
+	 */
+	tail_start_addr = (data_start_addr + data_len) % sector_size;
+
+	if (tail_start_addr) {
+		int tail_len;
+
+		tail_len = sector_size - tail_start_addr;
+
+		/* now we read this tail into our sector buffer */
+		err = broadsheet_spiflash_read_range(par, tail_start_addr,
+			tail_len, sector_buffer + tail_start_addr);
+		if (err)
+			return err;
+	}
+
+	/* if we got here we have the full sector that we want to rewrite. */
+
+	/* first erase the sector */
+	err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
+	if (err)
+		return err;
+
+	/* now write it */
+	err = broadsheet_spiflash_write_sector(par, start_sector_addr,
+					sector_buffer, sector_size);
+	return err;
+}
+
+static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
+				const u8 *wfm, int bytecount, int flash_type)
+{
+	int sector_size;
+	int err;
+	int cur_addr;
+	int writecount;
+	int maxlen;
+	int offset = 0;
+
+	switch (flash_type) {
+	case 0x10:
+		sector_size = 32*1024;
+		break;
+	case 0x11:
+	default:
+		sector_size = 64*1024;
+		break;
+	}
+
+	while (bytecount) {
+		cur_addr = wfm_addr + offset;
+		maxlen = roundup(cur_addr, sector_size) - cur_addr;
+		writecount = min(bytecount, maxlen);
+
+		err = broadsheet_spiflash_rewrite_sector(par, sector_size,
+				cur_addr, writecount, wfm + offset);
+		if (err)
+			return err;
+
+		offset += writecount;
+		bytecount -= writecount;
+	}
+
+	return 0;
+}
+
+static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
+						const u8 *wfm, size_t wfm_size)
+{
+	int err = 0;
+	u16 initial_sfmcd = 0;
+	int flash_type = 0;
+
+	err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
+	if (err)
+		goto failout;
+
+	err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
+
+failout:
+	broadsheet_write_reg(par, 0x0204, initial_sfmcd);
+	return err;
+}
+
+static ssize_t broadsheet_loadstore_waveform(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t len)
+{
+	int err;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct broadsheetfb_par *par = info->par;
+	const struct firmware *fw_entry;
+
+	if (len < 1)
+		return -EINVAL;
+
+	err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
+	if (err < 0) {
+		dev_err(dev, "Failed to get broadsheet waveform\n");
+		goto err_failed;
+	}
+
+	/* try to enforce reasonable min max on waveform */
+	if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
+		dev_err(dev, "Invalid waveform\n");
+		err = -EINVAL;
+		goto err_failed;
+	}
+
+	mutex_lock(&(par->io_lock));
+	err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
+							fw_entry->size);
+
+	mutex_unlock(&(par->io_lock));
+	if (err < 0) {
+		dev_err(dev, "Failed to store broadsheet waveform\n");
+		goto err_failed;
+	}
+
+	dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
+
+	return len;
+
+err_failed:
+	return err;
+}
+static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
+			broadsheet_loadstore_waveform);
+
+/* upper level functions that manipulate the display and other stuff */
+static void broadsheet_init_display(struct broadsheetfb_par *par)
+{
+	u16 args[5];
+	int xres = par->info->var.xres;
+	int yres = par->info->var.yres;
+
+	args[0] = panel_table[par->panel_index].w;
+	args[1] = panel_table[par->panel_index].h;
+	args[2] = panel_table[par->panel_index].sdcfg;
+	args[3] = panel_table[par->panel_index].gdcfg;
+	args[4] = panel_table[par->panel_index].lutfmt;
+	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
+
+	/* did the controller really set it? */
+	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
+
+	args[0] = panel_table[par->panel_index].fsynclen;
+	args[1] = panel_table[par->panel_index].fendfbegin;
+	args[2] = panel_table[par->panel_index].lsynclen;
+	args[3] = panel_table[par->panel_index].lendlbegin;
+	args[4] = panel_table[par->panel_index].pixclk;
+	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
+
+	broadsheet_write_reg32(par, 0x310, xres*yres*2);
+
+	/* setup waveform */
+	args[0] = 0x886;
+	args[1] = 0;
+	broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
+
+	broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
+
+	broadsheet_write_reg(par, 0x330, 0x84);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
+
+	args[0] = (0x3 << 4);
+	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
+
+	args[0] = 0x154;
+	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
+
+	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
+					panel_table[par->panel_index].h)/2,
+					(u16 *) par->info->screen_base);
+
+	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
+
+	args[0] = 0x4300;
+	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
+
+	par->board->wait_for_rdy(par);
+}
+
+static void broadsheet_identify(struct broadsheetfb_par *par)
+{
+	u16 rev, prc;
+	struct device *dev = par->info->device;
+
+	rev = broadsheet_read_reg(par, BS_REG_REV);
+	prc = broadsheet_read_reg(par, BS_REG_PRC);
+	dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
+
+	if (prc != 0x0047)
+		dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
+	if (rev != 0x0100)
+		dev_warn(dev, "Unrecognized Broadsheet Revision\n");
+}
+
+static void broadsheet_init(struct broadsheetfb_par *par)
+{
+	broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
+	/* the controller needs a second */
+	msleep(1000);
+	broadsheet_init_display(par);
+}
+
+static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
+						u16 y1, u16 y2)
+{
+	u16 args[5];
+	unsigned char *buf = (unsigned char *)par->info->screen_base;
+
+	mutex_lock(&(par->io_lock));
+	/* y1 must be a multiple of 4 so drop the lower bits */
+	y1 &= 0xFFFC;
+	/* y2 must be a multiple of 4 , but - 1 so up the lower bits */
+	y2 |= 0x0003;
+
+	args[0] = 0x3 << 4;
+	args[1] = 0;
+	args[2] = y1;
+	args[3] = cpu_to_le16(par->info->var.xres);
+	args[4] = y2;
+	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
+
+	args[0] = 0x154;
+	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
+
+	buf += y1 * par->info->var.xres;
+	broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
+				(u16 *) buf);
+
+	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
+
+	args[0] = 0x4300;
+	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
+
+	par->board->wait_for_rdy(par);
+	mutex_unlock(&(par->io_lock));
+
+}
+
+static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
+{
+	u16 args[5];
+
+	mutex_lock(&(par->io_lock));
+	args[0] = 0x3 << 4;
+	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
+
+	args[0] = 0x154;
+	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
+	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
+					panel_table[par->panel_index].h)/2,
+					(u16 *) par->info->screen_base);
+
+	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
+
+	args[0] = 0x4300;
+	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
+
+	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
+
+	par->board->wait_for_rdy(par);
+	mutex_unlock(&(par->io_lock));
+}
+
+/* this is called back from the deferred io workqueue */
+static void broadsheetfb_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	u16 y1 = 0, h = 0;
+	int prev_index = -1;
+	struct page *cur;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	int h_inc;
+	u16 yres = info->var.yres;
+	u16 xres = info->var.xres;
+
+	/* height increment is fixed per page */
+	h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
+
+	/* walk the written page list and swizzle the data */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+		if (prev_index < 0) {
+			/* just starting so assign first page */
+			y1 = (cur->index << PAGE_SHIFT) / xres;
+			h = h_inc;
+		} else if ((prev_index + 1) == cur->index) {
+			/* this page is consecutive so increase our height */
+			h += h_inc;
+		} else {
+			/* page not consecutive, issue previous update first */
+			broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
+			/* start over with our non consecutive page */
+			y1 = (cur->index << PAGE_SHIFT) / xres;
+			h = h_inc;
+		}
+		prev_index = cur->index;
+	}
+
+	/* if we still have any pages to update we do so now */
+	if (h >= yres) {
+		/* its a full screen update, just do it */
+		broadsheetfb_dpy_update(info->par);
+	} else {
+		broadsheetfb_dpy_update_pages(info->par, y1,
+						min((u16) (y1 + h), yres));
+	}
+}
+
+static void broadsheetfb_fillrect(struct fb_info *info,
+				   const struct fb_fillrect *rect)
+{
+	struct broadsheetfb_par *par = info->par;
+
+	sys_fillrect(info, rect);
+
+	broadsheetfb_dpy_update(par);
+}
+
+static void broadsheetfb_copyarea(struct fb_info *info,
+				   const struct fb_copyarea *area)
+{
+	struct broadsheetfb_par *par = info->par;
+
+	sys_copyarea(info, area);
+
+	broadsheetfb_dpy_update(par);
+}
+
+static void broadsheetfb_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	struct broadsheetfb_par *par = info->par;
+
+	sys_imageblit(info, image);
+
+	broadsheetfb_dpy_update(par);
+}
+
+/*
+ * this is the slow path from userspace. they can seek and write to
+ * the fb. it's inefficient to do anything less than a full screen draw
+ */
+static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct broadsheetfb_par *par = info->par;
+	unsigned long p = *ppos;
+	void *dst;
+	int err = 0;
+	unsigned long total_size;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
+		count = total_size - p;
+	}
+
+	dst = (void *)(info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		err = -EFAULT;
+
+	if  (!err)
+		*ppos += count;
+
+	broadsheetfb_dpy_update(par);
+
+	return (err) ? err : count;
+}
+
+static struct fb_ops broadsheetfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read        = fb_sys_read,
+	.fb_write	= broadsheetfb_write,
+	.fb_fillrect	= broadsheetfb_fillrect,
+	.fb_copyarea	= broadsheetfb_copyarea,
+	.fb_imageblit	= broadsheetfb_imageblit,
+};
+
+static struct fb_deferred_io broadsheetfb_defio = {
+	.delay		= HZ/4,
+	.deferred_io	= broadsheetfb_dpy_deferred_io,
+};
+
+static int broadsheetfb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	struct broadsheet_board *board;
+	int retval = -ENOMEM;
+	int videomemorysize;
+	unsigned char *videomemory;
+	struct broadsheetfb_par *par;
+	int i;
+	int dpyw, dpyh;
+	int panel_index;
+
+	/* pick up board specific routines */
+	board = dev->dev.platform_data;
+	if (!board)
+		return -EINVAL;
+
+	/* try to count device specific driver, if can't, platform recalls */
+	if (!try_module_get(board->owner))
+		return -ENODEV;
+
+	info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
+	if (!info)
+		goto err;
+
+	switch (board->get_panel_type()) {
+	case 37:
+		panel_index = 1;
+		break;
+	case 97:
+		panel_index = 2;
+		break;
+	case 6:
+	default:
+		panel_index = 0;
+		break;
+	}
+
+	dpyw = panel_table[panel_index].w;
+	dpyh = panel_table[panel_index].h;
+
+	videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
+
+	videomemory = vzalloc(videomemorysize);
+	if (!videomemory)
+		goto err_fb_rel;
+
+	info->screen_base = (char *)videomemory;
+	info->fbops = &broadsheetfb_ops;
+
+	broadsheetfb_var.xres = dpyw;
+	broadsheetfb_var.yres = dpyh;
+	broadsheetfb_var.xres_virtual = dpyw;
+	broadsheetfb_var.yres_virtual = dpyh;
+	info->var = broadsheetfb_var;
+
+	broadsheetfb_fix.line_length = dpyw;
+	info->fix = broadsheetfb_fix;
+	info->fix.smem_len = videomemorysize;
+	par = info->par;
+	par->panel_index = panel_index;
+	par->info = info;
+	par->board = board;
+	par->write_reg = broadsheet_write_reg;
+	par->read_reg = broadsheet_read_reg;
+	init_waitqueue_head(&par->waitq);
+
+	mutex_init(&par->io_lock);
+
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+
+	info->fbdefio = &broadsheetfb_defio;
+	fb_deferred_io_init(info);
+
+	retval = fb_alloc_cmap(&info->cmap, 16, 0);
+	if (retval < 0) {
+		dev_err(&dev->dev, "Failed to allocate colormap\n");
+		goto err_vfree;
+	}
+
+	/* set cmap */
+	for (i = 0; i < 16; i++)
+		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
+	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
+	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
+
+	retval = par->board->setup_irq(info);
+	if (retval < 0)
+		goto err_cmap;
+
+	/* this inits the dpy */
+	retval = board->init(par);
+	if (retval < 0)
+		goto err_free_irq;
+
+	broadsheet_identify(par);
+
+	broadsheet_init(par);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_free_irq;
+
+	platform_set_drvdata(dev, info);
+
+	retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
+	if (retval < 0)
+		goto err_unreg_fb;
+
+	fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
+		videomemorysize >> 10);
+
+
+	return 0;
+
+err_unreg_fb:
+	unregister_framebuffer(info);
+err_free_irq:
+	board->cleanup(par);
+err_cmap:
+	fb_dealloc_cmap(&info->cmap);
+err_vfree:
+	vfree(videomemory);
+err_fb_rel:
+	framebuffer_release(info);
+err:
+	module_put(board->owner);
+	return retval;
+
+}
+
+static int broadsheetfb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		struct broadsheetfb_par *par = info->par;
+
+		device_remove_file(info->dev, &dev_attr_loadstore_waveform);
+		unregister_framebuffer(info);
+		fb_deferred_io_cleanup(info);
+		par->board->cleanup(par);
+		fb_dealloc_cmap(&info->cmap);
+		vfree((void *)info->screen_base);
+		module_put(par->board->owner);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct platform_driver broadsheetfb_driver = {
+	.probe	= broadsheetfb_probe,
+	.remove = broadsheetfb_remove,
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "broadsheetfb",
+	},
+};
+module_platform_driver(broadsheetfb_driver);
+
+MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/bt431.h b/drivers/video/fbdev/bt431.h
new file mode 100644
index 000000000000..04e0cfbba538
--- /dev/null
+++ b/drivers/video/fbdev/bt431.h
@@ -0,0 +1,235 @@
+/*
+ *	linux/drivers/video/bt431.h
+ *
+ *	Copyright 2003  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
+ *
+ *	This file is subject to the terms and conditions of the GNU General
+ *	Public License. See the file COPYING in the main directory of this
+ *	archive for more details.
+ */
+#include <linux/types.h>
+
+/*
+ * Bt431 cursor generator registers, 32-bit aligned.
+ * Two twin Bt431 are used on the DECstation's PMAG-AA.
+ */
+struct bt431_regs {
+	volatile u16 addr_lo;
+	u16 pad0;
+	volatile u16 addr_hi;
+	u16 pad1;
+	volatile u16 addr_cmap;
+	u16 pad2;
+	volatile u16 addr_reg;
+	u16 pad3;
+};
+
+static inline u16 bt431_set_value(u8 val)
+{
+	return ((val << 8) | (val & 0xff)) & 0xffff;
+}
+
+static inline u8 bt431_get_value(u16 val)
+{
+	return val & 0xff;
+}
+
+/*
+ * Additional registers addressed indirectly.
+ */
+#define BT431_REG_CMD		0x0000
+#define BT431_REG_CXLO		0x0001
+#define BT431_REG_CXHI		0x0002
+#define BT431_REG_CYLO		0x0003
+#define BT431_REG_CYHI		0x0004
+#define BT431_REG_WXLO		0x0005
+#define BT431_REG_WXHI		0x0006
+#define BT431_REG_WYLO		0x0007
+#define BT431_REG_WYHI		0x0008
+#define BT431_REG_WWLO		0x0009
+#define BT431_REG_WWHI		0x000a
+#define BT431_REG_WHLO		0x000b
+#define BT431_REG_WHHI		0x000c
+
+#define BT431_REG_CRAM_BASE	0x0000
+#define BT431_REG_CRAM_END	0x01ff
+
+/*
+ * Command register.
+ */
+#define BT431_CMD_CURS_ENABLE	0x40
+#define BT431_CMD_XHAIR_ENABLE	0x20
+#define BT431_CMD_OR_CURSORS	0x10
+#define BT431_CMD_AND_CURSORS	0x00
+#define BT431_CMD_1_1_MUX	0x00
+#define BT431_CMD_4_1_MUX	0x04
+#define BT431_CMD_5_1_MUX	0x08
+#define BT431_CMD_xxx_MUX	0x0c
+#define BT431_CMD_THICK_1	0x00
+#define BT431_CMD_THICK_3	0x01
+#define BT431_CMD_THICK_5	0x02
+#define BT431_CMD_THICK_7	0x03
+
+static inline void bt431_select_reg(struct bt431_regs *regs, int ir)
+{
+	/*
+	 * The compiler splits the write in two bytes without these
+	 * helper variables.
+	 */
+	volatile u16 *lo = &(regs->addr_lo);
+	volatile u16 *hi = &(regs->addr_hi);
+
+	mb();
+	*lo = bt431_set_value(ir & 0xff);
+	wmb();
+	*hi = bt431_set_value((ir >> 8) & 0xff);
+}
+
+/* Autoincrement read/write. */
+static inline u8 bt431_read_reg_inc(struct bt431_regs *regs)
+{
+	/*
+	 * The compiler splits the write in two bytes without the
+	 * helper variable.
+	 */
+	volatile u16 *r = &(regs->addr_reg);
+
+	mb();
+	return bt431_get_value(*r);
+}
+
+static inline void bt431_write_reg_inc(struct bt431_regs *regs, u8 value)
+{
+	/*
+	 * The compiler splits the write in two bytes without the
+	 * helper variable.
+	 */
+	volatile u16 *r = &(regs->addr_reg);
+
+	mb();
+	*r = bt431_set_value(value);
+}
+
+static inline u8 bt431_read_reg(struct bt431_regs *regs, int ir)
+{
+	bt431_select_reg(regs, ir);
+	return bt431_read_reg_inc(regs);
+}
+
+static inline void bt431_write_reg(struct bt431_regs *regs, int ir, u8 value)
+{
+	bt431_select_reg(regs, ir);
+	bt431_write_reg_inc(regs, value);
+}
+
+/* Autoincremented read/write for the cursor map. */
+static inline u16 bt431_read_cmap_inc(struct bt431_regs *regs)
+{
+	/*
+	 * The compiler splits the write in two bytes without the
+	 * helper variable.
+	 */
+	volatile u16 *r = &(regs->addr_cmap);
+
+	mb();
+	return *r;
+}
+
+static inline void bt431_write_cmap_inc(struct bt431_regs *regs, u16 value)
+{
+	/*
+	 * The compiler splits the write in two bytes without the
+	 * helper variable.
+	 */
+	volatile u16 *r = &(regs->addr_cmap);
+
+	mb();
+	*r = value;
+}
+
+static inline u16 bt431_read_cmap(struct bt431_regs *regs, int cr)
+{
+	bt431_select_reg(regs, cr);
+	return bt431_read_cmap_inc(regs);
+}
+
+static inline void bt431_write_cmap(struct bt431_regs *regs, int cr, u16 value)
+{
+	bt431_select_reg(regs, cr);
+	bt431_write_cmap_inc(regs, value);
+}
+
+static inline void bt431_enable_cursor(struct bt431_regs *regs)
+{
+	bt431_write_reg(regs, BT431_REG_CMD,
+			BT431_CMD_CURS_ENABLE | BT431_CMD_OR_CURSORS
+			| BT431_CMD_4_1_MUX | BT431_CMD_THICK_1);
+}
+
+static inline void bt431_erase_cursor(struct bt431_regs *regs)
+{
+	bt431_write_reg(regs, BT431_REG_CMD, BT431_CMD_4_1_MUX);
+}
+
+static inline void bt431_position_cursor(struct bt431_regs *regs, u16 x, u16 y)
+{
+	/*
+	 * Magic from the MACH sources.
+	 *
+	 * Cx = x + D + H - P
+	 *  P = 37 if 1:1, 52 if 4:1, 57 if 5:1
+	 *  D = pixel skew between outdata and external data
+	 *  H = pixels between HSYNCH falling and active video
+	 *
+	 * Cy = y + V - 32
+	 *  V = scanlines between HSYNCH falling, two or more
+	 *      clocks after VSYNCH falling, and active video
+	 */
+	x += 412 - 52;
+	y += 68 - 32;
+
+	/* Use autoincrement. */
+	bt431_select_reg(regs, BT431_REG_CXLO);
+	bt431_write_reg_inc(regs, x & 0xff); /* BT431_REG_CXLO */
+	bt431_write_reg_inc(regs, (x >> 8) & 0x0f); /* BT431_REG_CXHI */
+	bt431_write_reg_inc(regs, y & 0xff); /* BT431_REG_CYLO */
+	bt431_write_reg_inc(regs, (y >> 8) & 0x0f); /* BT431_REG_CYHI */
+}
+
+static inline void bt431_set_font(struct bt431_regs *regs, u8 fgc,
+				  u16 width, u16 height)
+{
+	int i;
+	u16 fgp = fgc ? 0xffff : 0x0000;
+	u16 bgp = fgc ? 0x0000 : 0xffff;
+
+	bt431_select_reg(regs, BT431_REG_CRAM_BASE);
+	for (i = BT431_REG_CRAM_BASE; i <= BT431_REG_CRAM_END; i++) {
+		u16 value;
+
+		if (height << 6 <= i << 3)
+			value = bgp;
+		else if (width <= i % 8 << 3)
+			value = bgp;
+		else if (((width >> 3) & 0xffff) > i % 8)
+			value = fgp;
+		else
+			value = fgp & ~(bgp << (width % 8 << 1));
+
+		bt431_write_cmap_inc(regs, value);
+	}
+}
+
+static inline void bt431_init_cursor(struct bt431_regs *regs)
+{
+	/* no crosshair window */
+	bt431_select_reg(regs, BT431_REG_WXLO);
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WXLO */
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WXHI */
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WYLO */
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WYHI */
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WWLO */
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WWHI */
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WHLO */
+	bt431_write_reg_inc(regs, 0x00); /* BT431_REG_WHHI */
+}
diff --git a/drivers/video/fbdev/bt455.h b/drivers/video/fbdev/bt455.h
new file mode 100644
index 000000000000..80f61b03e9ae
--- /dev/null
+++ b/drivers/video/fbdev/bt455.h
@@ -0,0 +1,94 @@
+/*
+ *	linux/drivers/video/bt455.h
+ *
+ *	Copyright 2003  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
+ *
+ *	This file is subject to the terms and conditions of the GNU General
+ *	Public License. See the file COPYING in the main directory of this
+ *	archive for more details.
+ */
+#include <linux/types.h>
+
+/*
+ * Bt455 byte-wide registers, 32-bit aligned.
+ */
+struct bt455_regs {
+	volatile u8 addr_cmap;
+	u8 pad0[3];
+	volatile u8 addr_cmap_data;
+	u8 pad1[3];
+	volatile u8 addr_clr;
+	u8 pad2[3];
+	volatile u8 addr_ovly;
+	u8 pad3[3];
+};
+
+static inline void bt455_select_reg(struct bt455_regs *regs, int ir)
+{
+	mb();
+	regs->addr_cmap = ir & 0x0f;
+}
+
+/*
+ * Read/write to a Bt455 color map register.
+ */
+static inline void bt455_read_cmap_entry(struct bt455_regs *regs, int cr,
+					 u8* red, u8* green, u8* blue)
+{
+	bt455_select_reg(regs, cr);
+	mb();
+	*red = regs->addr_cmap_data & 0x0f;
+	rmb();
+	*green = regs->addr_cmap_data & 0x0f;
+	rmb();
+	*blue = regs->addr_cmap_data & 0x0f;
+}
+
+static inline void bt455_write_cmap_entry(struct bt455_regs *regs, int cr,
+					  u8 red, u8 green, u8 blue)
+{
+	bt455_select_reg(regs, cr);
+	wmb();
+	regs->addr_cmap_data = red & 0x0f;
+	wmb();
+	regs->addr_cmap_data = green & 0x0f;
+	wmb();
+	regs->addr_cmap_data = blue & 0x0f;
+}
+
+static inline void bt455_write_ovly_entry(struct bt455_regs *regs, int cr,
+					  u8 red, u8 green, u8 blue)
+{
+	bt455_select_reg(regs, cr);
+	wmb();
+	regs->addr_ovly = red & 0x0f;
+	wmb();
+	regs->addr_ovly = green & 0x0f;
+	wmb();
+	regs->addr_ovly = blue & 0x0f;
+}
+
+static inline void bt455_set_cursor(struct bt455_regs *regs)
+{
+	mb();
+	regs->addr_ovly = 0x0f;
+	wmb();
+	regs->addr_ovly = 0x0f;
+	wmb();
+	regs->addr_ovly = 0x0f;
+}
+
+static inline void bt455_erase_cursor(struct bt455_regs *regs)
+{
+	/* bt455_write_cmap_entry(regs, 8, 0x00, 0x00, 0x00); */
+	/* bt455_write_cmap_entry(regs, 9, 0x00, 0x00, 0x00); */
+	bt455_write_ovly_entry(regs, 8, 0x03, 0x03, 0x03);
+	bt455_write_ovly_entry(regs, 9, 0x07, 0x07, 0x07);
+
+	wmb();
+	regs->addr_ovly = 0x09;
+	wmb();
+	regs->addr_ovly = 0x09;
+	wmb();
+	regs->addr_ovly = 0x09;
+}
diff --git a/drivers/video/fbdev/bw2.c b/drivers/video/fbdev/bw2.c
new file mode 100644
index 000000000000..bc123d6947a4
--- /dev/null
+++ b/drivers/video/fbdev/bw2.c
@@ -0,0 +1,406 @@
+/* bw2.c: BWTWO frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int bw2_blank(int, struct fb_info *);
+
+static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
+static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops bw2_ops = {
+	.owner			= THIS_MODULE,
+	.fb_blank		= bw2_blank,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= bw2_mmap,
+	.fb_ioctl		= bw2_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+/* OBio addresses for the bwtwo registers */
+#define BWTWO_REGISTER_OFFSET 0x400000
+
+struct bt_regs {
+	u32 addr;
+	u32 color_map;
+	u32 control;
+	u32 cursor;
+};
+
+struct bw2_regs {
+	struct bt_regs	cmap;
+	u8	control;
+	u8	status;
+	u8	cursor_start;
+	u8	cursor_end;
+	u8	h_blank_start;
+	u8	h_blank_end;
+	u8	h_sync_start;
+	u8	h_sync_end;
+	u8	comp_sync_end;
+	u8	v_blank_start_high;
+	u8	v_blank_start_low;
+	u8	v_blank_end;
+	u8	v_sync_start;
+	u8	v_sync_end;
+	u8	xfer_holdoff_start;
+	u8	xfer_holdoff_end;
+};
+
+/* Status Register Constants */
+#define BWTWO_SR_RES_MASK	0x70
+#define BWTWO_SR_1600_1280	0x50
+#define BWTWO_SR_1152_900_76_A	0x40
+#define BWTWO_SR_1152_900_76_B	0x60
+#define BWTWO_SR_ID_MASK	0x0f
+#define BWTWO_SR_ID_MONO	0x02
+#define BWTWO_SR_ID_MONO_ECL	0x03
+#define BWTWO_SR_ID_MSYNC	0x04
+#define BWTWO_SR_ID_NOCONN	0x0a
+
+/* Control Register Constants */
+#define BWTWO_CTL_ENABLE_INTS   0x80
+#define BWTWO_CTL_ENABLE_VIDEO  0x40
+#define BWTWO_CTL_ENABLE_TIMING 0x20
+#define BWTWO_CTL_ENABLE_CURCMP 0x10
+#define BWTWO_CTL_XTAL_MASK     0x0C
+#define BWTWO_CTL_DIVISOR_MASK  0x03
+
+/* Status Register Constants */
+#define BWTWO_STAT_PENDING_INT  0x80
+#define BWTWO_STAT_MSENSE_MASK  0x70
+#define BWTWO_STAT_ID_MASK      0x0f
+
+struct bw2_par {
+	spinlock_t		lock;
+	struct bw2_regs		__iomem *regs;
+
+	u32			flags;
+#define BW2_FLAG_BLANKED	0x00000001
+
+	unsigned long		which_io;
+};
+
+/**
+ *      bw2_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+bw2_blank(int blank, struct fb_info *info)
+{
+	struct bw2_par *par = (struct bw2_par *) info->par;
+	struct bw2_regs __iomem *regs = par->regs;
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		val = sbus_readb(&regs->control);
+		val |= BWTWO_CTL_ENABLE_VIDEO;
+		sbus_writeb(val, &regs->control);
+		par->flags &= ~BW2_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		val = sbus_readb(&regs->control);
+		val &= ~BWTWO_CTL_ENABLE_VIDEO;
+		sbus_writeb(val, &regs->control);
+		par->flags |= BW2_FLAG_BLANKED;
+		break;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map bw2_mmap_map[] = {
+	{
+		.size = SBUS_MMAP_FBSIZE(1)
+	},
+	{ .size = 0 }
+};
+
+static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct bw2_par *par = (struct bw2_par *)info->par;
+
+	return sbusfb_mmap_helper(bw2_mmap_map,
+				  info->fix.smem_start, info->fix.smem_len,
+				  par->which_io,
+				  vma);
+}
+
+static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN2BW, 1, info->fix.smem_len);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void bw2_init_fix(struct fb_info *info, int linebytes)
+{
+	strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_MONO01;
+
+	info->fix.line_length = linebytes;
+
+	info->fix.accel = FB_ACCEL_SUN_BWTWO;
+}
+
+static u8 bw2regs_1600[] = {
+	0x14, 0x8b,	0x15, 0x28,	0x16, 0x03,	0x17, 0x13,
+	0x18, 0x7b,	0x19, 0x05,	0x1a, 0x34,	0x1b, 0x2e,
+	0x1c, 0x00,	0x1d, 0x0a,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x21,	0
+};
+
+static u8 bw2regs_ecl[] = {
+	0x14, 0x65,	0x15, 0x1e,	0x16, 0x04,	0x17, 0x0c,
+	0x18, 0x5e,	0x19, 0x03,	0x1a, 0xa7,	0x1b, 0x23,
+	0x1c, 0x00,	0x1d, 0x08,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x20,	0
+};
+
+static u8 bw2regs_analog[] = {
+	0x14, 0xbb,	0x15, 0x2b,	0x16, 0x03,	0x17, 0x13,
+	0x18, 0xb0,	0x19, 0x03,	0x1a, 0xa6,	0x1b, 0x22,
+	0x1c, 0x01,	0x1d, 0x05,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x20,	0
+};
+
+static u8 bw2regs_76hz[] = {
+	0x14, 0xb7,	0x15, 0x27,	0x16, 0x03,	0x17, 0x0f,
+	0x18, 0xae,	0x19, 0x03,	0x1a, 0xae,	0x1b, 0x2a,
+	0x1c, 0x01,	0x1d, 0x09,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x24,	0
+};
+
+static u8 bw2regs_66hz[] = {
+	0x14, 0xbb,	0x15, 0x2b,	0x16, 0x04,	0x17, 0x14,
+	0x18, 0xae,	0x19, 0x03,	0x1a, 0xa8,	0x1b, 0x24,
+	0x1c, 0x01,	0x1d, 0x05,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x20,	0
+};
+
+static int bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
+			       int *linebytes)
+{
+	u8 status, mon;
+	u8 *p;
+
+	status = sbus_readb(&par->regs->status);
+	mon = status & BWTWO_SR_RES_MASK;
+	switch (status & BWTWO_SR_ID_MASK) {
+	case BWTWO_SR_ID_MONO_ECL:
+		if (mon == BWTWO_SR_1600_1280) {
+			p = bw2regs_1600;
+			info->var.xres = info->var.xres_virtual = 1600;
+			info->var.yres = info->var.yres_virtual = 1280;
+			*linebytes = 1600 / 8;
+		} else
+			p = bw2regs_ecl;
+		break;
+
+	case BWTWO_SR_ID_MONO:
+		p = bw2regs_analog;
+		break;
+
+	case BWTWO_SR_ID_MSYNC:
+		if (mon == BWTWO_SR_1152_900_76_A ||
+		    mon == BWTWO_SR_1152_900_76_B)
+			p = bw2regs_76hz;
+		else
+			p = bw2regs_66hz;
+		break;
+
+	case BWTWO_SR_ID_NOCONN:
+		return 0;
+
+	default:
+		printk(KERN_ERR "bw2: can't handle SR %02x\n",
+		       status);
+		return -EINVAL;
+	}
+	for ( ; *p; p += 2) {
+		u8 __iomem *regp = &((u8 __iomem *)par->regs)[p[0]];
+		sbus_writeb(p[1], regp);
+	}
+	return 0;
+}
+
+static int bw2_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct bw2_par *par;
+	int linebytes, err;
+
+	info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+
+	info->fix.smem_start = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+	sbusfb_fill_var(&info->var, dp, 1);
+	linebytes = of_getintprop_default(dp, "linebytes",
+					  info->var.xres);
+
+	info->var.red.length = info->var.green.length =
+		info->var.blue.length = info->var.bits_per_pixel;
+	info->var.red.offset = info->var.green.offset =
+		info->var.blue.offset = 0;
+
+	par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
+			       sizeof(struct bw2_regs), "bw2 regs");
+	if (!par->regs)
+		goto out_release_fb;
+
+	if (!of_find_property(dp, "width", NULL)) {
+		err = bw2_do_default_mode(par, info, &linebytes);
+		if (err)
+			goto out_unmap_regs;
+	}
+
+	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &bw2_ops;
+
+	info->screen_base = of_ioremap(&op->resource[0], 0,
+				       info->fix.smem_len, "bw2 ram");
+	if (!info->screen_base) {
+		err = -ENOMEM;
+		goto out_unmap_regs;
+	}
+
+	bw2_blank(FB_BLANK_UNBLANK, info);
+
+	bw2_init_fix(info, linebytes);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_unmap_screen;
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: bwtwo at %lx:%lx\n",
+	       dp->full_name, par->which_io, info->fix.smem_start);
+
+	return 0;
+
+out_unmap_screen:
+	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
+
+out_unmap_regs:
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
+
+out_release_fb:
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int bw2_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct bw2_par *par = info->par;
+
+	unregister_framebuffer(info);
+
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
+	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id bw2_match[] = {
+	{
+		.name = "bwtwo",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, bw2_match);
+
+static struct platform_driver bw2_driver = {
+	.driver = {
+		.name = "bw2",
+		.owner = THIS_MODULE,
+		.of_match_table = bw2_match,
+	},
+	.probe		= bw2_probe,
+	.remove		= bw2_remove,
+};
+
+static int __init bw2_init(void)
+{
+	if (fb_get_options("bw2fb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&bw2_driver);
+}
+
+static void __exit bw2_exit(void)
+{
+	platform_driver_unregister(&bw2_driver);
+}
+
+module_init(bw2_init);
+module_exit(bw2_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/c2p.h b/drivers/video/fbdev/c2p.h
new file mode 100644
index 000000000000..6c38d40427d8
--- /dev/null
+++ b/drivers/video/fbdev/c2p.h
@@ -0,0 +1,19 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/types.h>
+
+extern void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		       u32 height, u32 dst_nextline, u32 dst_nextplane,
+		       u32 src_nextline, u32 bpp);
+
+extern void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		       u32 height, u32 dst_nextline, u32 src_nextline,
+		       u32 bpp);
diff --git a/drivers/video/fbdev/c2p_core.h b/drivers/video/fbdev/c2p_core.h
new file mode 100644
index 000000000000..e1035a865fb9
--- /dev/null
+++ b/drivers/video/fbdev/c2p_core.h
@@ -0,0 +1,153 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  NOTES:
+ *    - This code was inspired by Scout's C2P tutorial
+ *    - It assumes to run on a big endian system
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+
+    /*
+     *  Basic transpose step
+     */
+
+static inline void _transp(u32 d[], unsigned int i1, unsigned int i2,
+			   unsigned int shift, u32 mask)
+{
+	u32 t = (d[i1] ^ (d[i2] >> shift)) & mask;
+
+	d[i1] ^= t;
+	d[i2] ^= t << shift;
+}
+
+
+extern void c2p_unsupported(void);
+
+static inline u32 get_mask(unsigned int n)
+{
+	switch (n) {
+	case 1:
+		return 0x55555555;
+
+	case 2:
+		return 0x33333333;
+
+	case 4:
+		return 0x0f0f0f0f;
+
+	case 8:
+		return 0x00ff00ff;
+
+	case 16:
+		return 0x0000ffff;
+	}
+
+	c2p_unsupported();
+	return 0;
+}
+
+
+    /*
+     *  Transpose operations on 8 32-bit words
+     */
+
+static inline void transp8(u32 d[], unsigned int n, unsigned int m)
+{
+	u32 mask = get_mask(n);
+
+	switch (m) {
+	case 1:
+		/* First n x 1 block */
+		_transp(d, 0, 1, n, mask);
+		/* Second n x 1 block */
+		_transp(d, 2, 3, n, mask);
+		/* Third n x 1 block */
+		_transp(d, 4, 5, n, mask);
+		/* Fourth n x 1 block */
+		_transp(d, 6, 7, n, mask);
+		return;
+
+	case 2:
+		/* First n x 2 block */
+		_transp(d, 0, 2, n, mask);
+		_transp(d, 1, 3, n, mask);
+		/* Second n x 2 block */
+		_transp(d, 4, 6, n, mask);
+		_transp(d, 5, 7, n, mask);
+		return;
+
+	case 4:
+		/* Single n x 4 block */
+		_transp(d, 0, 4, n, mask);
+		_transp(d, 1, 5, n, mask);
+		_transp(d, 2, 6, n, mask);
+		_transp(d, 3, 7, n, mask);
+		return;
+	}
+
+	c2p_unsupported();
+}
+
+
+    /*
+     *  Transpose operations on 4 32-bit words
+     */
+
+static inline void transp4(u32 d[], unsigned int n, unsigned int m)
+{
+	u32 mask = get_mask(n);
+
+	switch (m) {
+	case 1:
+		/* First n x 1 block */
+		_transp(d, 0, 1, n, mask);
+		/* Second n x 1 block */
+		_transp(d, 2, 3, n, mask);
+		return;
+
+	case 2:
+		/* Single n x 2 block */
+		_transp(d, 0, 2, n, mask);
+		_transp(d, 1, 3, n, mask);
+		return;
+	}
+
+	c2p_unsupported();
+}
+
+
+    /*
+     *  Transpose operations on 4 32-bit words (reverse order)
+     */
+
+static inline void transp4x(u32 d[], unsigned int n, unsigned int m)
+{
+	u32 mask = get_mask(n);
+
+	switch (m) {
+	case 2:
+		/* Single n x 2 block */
+		_transp(d, 2, 0, n, mask);
+		_transp(d, 3, 1, n, mask);
+		return;
+	}
+
+	c2p_unsupported();
+}
+
+
+    /*
+     *  Compose two values, using a bitmask as decision value
+     *  This is equivalent to (a & mask) | (b & ~mask)
+     */
+
+static inline u32 comp(u32 a, u32 b, u32 mask)
+{
+	return ((a ^ b) & mask) ^ b;
+}
diff --git a/drivers/video/fbdev/c2p_iplan2.c b/drivers/video/fbdev/c2p_iplan2.c
new file mode 100644
index 000000000000..19156dc6158c
--- /dev/null
+++ b/drivers/video/fbdev/c2p_iplan2.c
@@ -0,0 +1,153 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/unaligned.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+    /*
+     *  Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
+     *  containing
+     *    - 16 8-bit chunky pixels on input
+     *    - permutated planar data (2 planes per 32-bit word) on output
+     */
+
+static void c2p_16x8(u32 d[4])
+{
+	transp4(d, 8, 2);
+	transp4(d, 1, 2);
+	transp4x(d, 16, 2);
+	transp4x(d, 2, 2);
+	transp4(d, 4, 1);
+}
+
+
+    /*
+     *  Array containing the permutation indices of the planar data after c2p
+     */
+
+static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
+
+
+    /*
+     *  Store a full block of iplan2 data after c2p conversion
+     */
+
+static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
+{
+	int i;
+
+	for (i = 0; i < bpp/2; i++, dst += 4)
+		put_unaligned_be32(d[perm_c2p_16x8[i]], dst);
+}
+
+
+    /*
+     *  Store a partial block of iplan2 data after c2p conversion
+     */
+
+static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
+{
+	int i;
+
+	for (i = 0; i < bpp/2; i++, dst += 4)
+		put_unaligned_be32(comp(d[perm_c2p_16x8[i]],
+					get_unaligned_be32(dst), mask),
+				   dst);
+}
+
+
+    /*
+     *  c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
+     *  frame buffer with 2 bytes of interleave
+     *  @dst: Starting address of the planar frame buffer
+     *  @dx: Horizontal destination offset (in pixels)
+     *  @dy: Vertical destination offset (in pixels)
+     *  @width: Image width (in pixels)
+     *  @height: Image height (in pixels)
+     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
+     *  @src_nextline: Image offset to the next line (in bytes)
+     *  @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
+     */
+
+void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
+{
+	union {
+		u8 pixels[16];
+		u32 words[4];
+	} d;
+	u32 dst_idx, first, last, w;
+	const u8 *c;
+	void *p;
+
+	dst += dy*dst_nextline+(dx & ~15)*bpp;
+	dst_idx = dx % 16;
+	first = 0xffffU >> dst_idx;
+	first |= first << 16;
+	last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
+	last |= last << 16;
+	while (height--) {
+		c = src;
+		p = dst;
+		w = width;
+		if (dst_idx+width <= 16) {
+			/* Single destination word */
+			first &= last;
+			memset(d.pixels, 0, sizeof(d));
+			memcpy(d.pixels+dst_idx, c, width);
+			c += width;
+			c2p_16x8(d.words);
+			store_iplan2_masked(p, bpp, d.words, first);
+			p += bpp*2;
+		} else {
+			/* Multiple destination words */
+			w = width;
+			/* Leading bits */
+			if (dst_idx) {
+				w = 16 - dst_idx;
+				memset(d.pixels, 0, dst_idx);
+				memcpy(d.pixels+dst_idx, c, w);
+				c += w;
+				c2p_16x8(d.words);
+				store_iplan2_masked(p, bpp, d.words, first);
+				p += bpp*2;
+				w = width-w;
+			}
+			/* Main chunk */
+			while (w >= 16) {
+				memcpy(d.pixels, c, 16);
+				c += 16;
+				c2p_16x8(d.words);
+				store_iplan2(p, bpp, d.words);
+				p += bpp*2;
+				w -= 16;
+			}
+			/* Trailing bits */
+			w %= 16;
+			if (w > 0) {
+				memcpy(d.pixels, c, w);
+				memset(d.pixels+w, 0, 16-w);
+				c2p_16x8(d.words);
+				store_iplan2_masked(p, bpp, d.words, last);
+			}
+		}
+		src += src_nextline;
+		dst += dst_nextline;
+	}
+}
+EXPORT_SYMBOL_GPL(c2p_iplan2);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/c2p_planar.c b/drivers/video/fbdev/c2p_planar.c
new file mode 100644
index 000000000000..ec7ac8526f06
--- /dev/null
+++ b/drivers/video/fbdev/c2p_planar.c
@@ -0,0 +1,156 @@
+/*
+ *  Fast C2P (Chunky-to-Planar) Conversion
+ *
+ *  Copyright (C) 2003-2008 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/unaligned.h>
+
+#include "c2p.h"
+#include "c2p_core.h"
+
+
+    /*
+     *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
+     *  containing
+     *    - 32 8-bit chunky pixels on input
+     *    - permutated planar data (1 plane per 32-bit word) on output
+     */
+
+static void c2p_32x8(u32 d[8])
+{
+	transp8(d, 16, 4);
+	transp8(d, 8, 2);
+	transp8(d, 4, 1);
+	transp8(d, 2, 4);
+	transp8(d, 1, 2);
+}
+
+
+    /*
+     *  Array containing the permutation indices of the planar data after c2p
+     */
+
+static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
+
+
+    /*
+     *  Store a full block of planar data after c2p conversion
+     */
+
+static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
+{
+	int i;
+
+	for (i = 0; i < bpp; i++, dst += dst_inc)
+		put_unaligned_be32(d[perm_c2p_32x8[i]], dst);
+}
+
+
+    /*
+     *  Store a partial block of planar data after c2p conversion
+     */
+
+static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
+				       u32 d[8], u32 mask)
+{
+	int i;
+
+	for (i = 0; i < bpp; i++, dst += dst_inc)
+		put_unaligned_be32(comp(d[perm_c2p_32x8[i]],
+					get_unaligned_be32(dst), mask),
+				   dst);
+}
+
+
+    /*
+     *  c2p_planar - Copy 8-bit chunky image data to a planar frame buffer
+     *  @dst: Starting address of the planar frame buffer
+     *  @dx: Horizontal destination offset (in pixels)
+     *  @dy: Vertical destination offset (in pixels)
+     *  @width: Image width (in pixels)
+     *  @height: Image height (in pixels)
+     *  @dst_nextline: Frame buffer offset to the next line (in bytes)
+     *  @dst_nextplane: Frame buffer offset to the next plane (in bytes)
+     *  @src_nextline: Image offset to the next line (in bytes)
+     *  @bpp: Bits per pixel of the planar frame buffer (1-8)
+     */
+
+void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
+		u32 height, u32 dst_nextline, u32 dst_nextplane,
+		u32 src_nextline, u32 bpp)
+{
+	union {
+		u8 pixels[32];
+		u32 words[8];
+	} d;
+	u32 dst_idx, first, last, w;
+	const u8 *c;
+	void *p;
+
+	dst += dy*dst_nextline+(dx & ~31);
+	dst_idx = dx % 32;
+	first = 0xffffffffU >> dst_idx;
+	last = ~(0xffffffffU >> ((dst_idx+width) % 32));
+	while (height--) {
+		c = src;
+		p = dst;
+		w = width;
+		if (dst_idx+width <= 32) {
+			/* Single destination word */
+			first &= last;
+			memset(d.pixels, 0, sizeof(d));
+			memcpy(d.pixels+dst_idx, c, width);
+			c += width;
+			c2p_32x8(d.words);
+			store_planar_masked(p, dst_nextplane, bpp, d.words,
+					    first);
+			p += 4;
+		} else {
+			/* Multiple destination words */
+			w = width;
+			/* Leading bits */
+			if (dst_idx) {
+				w = 32 - dst_idx;
+				memset(d.pixels, 0, dst_idx);
+				memcpy(d.pixels+dst_idx, c, w);
+				c += w;
+				c2p_32x8(d.words);
+				store_planar_masked(p, dst_nextplane, bpp,
+						    d.words, first);
+				p += 4;
+				w = width-w;
+			}
+			/* Main chunk */
+			while (w >= 32) {
+				memcpy(d.pixels, c, 32);
+				c += 32;
+				c2p_32x8(d.words);
+				store_planar(p, dst_nextplane, bpp, d.words);
+				p += 4;
+				w -= 32;
+			}
+			/* Trailing bits */
+			w %= 32;
+			if (w > 0) {
+				memcpy(d.pixels, c, w);
+				memset(d.pixels+w, 0, 32-w);
+				c2p_32x8(d.words);
+				store_planar_masked(p, dst_nextplane, bpp,
+						    d.words, last);
+			}
+		}
+		src += src_nextline;
+		dst += dst_nextline;
+	}
+}
+EXPORT_SYMBOL_GPL(c2p_planar);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/carminefb.c b/drivers/video/fbdev/carminefb.c
new file mode 100644
index 000000000000..65f7c15f5fdb
--- /dev/null
+++ b/drivers/video/fbdev/carminefb.c
@@ -0,0 +1,788 @@
+/*
+ * Frame buffer driver for the Carmine GPU.
+ *
+ * The driver configures the GPU as follows
+ * - FB0 is display 0 with unique memory area
+ * - FB1 is display 1 with unique memory area
+ * - both display use 32 bit colors
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include "carminefb.h"
+#include "carminefb_regs.h"
+
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error  "The endianness of the target host has not been defined."
+#endif
+
+/*
+ * The initial video mode can be supplied via two different ways:
+ * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
+ * - as an integer that picks the video mode from carmine_modedb[] (module
+ *   option fb_mode)
+ *
+ * If nothing is used than the initial video mode will be the
+ * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
+ */
+#define CARMINEFB_DEFAULT_VIDEO_MODE	1
+
+static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+module_param(fb_mode, uint, 0444);
+MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
+
+static char *fb_mode_str;
+module_param(fb_mode_str, charp, 0444);
+MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
+
+/*
+ * Carminefb displays:
+ * 0b000 None
+ * 0b001 Display 0
+ * 0b010 Display 1
+ */
+static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
+module_param(fb_displays, int, 0444);
+MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
+
+struct carmine_hw {
+	void __iomem *v_regs;
+	void __iomem *screen_mem;
+	struct fb_info *fb[MAX_DISPLAY];
+};
+
+struct carmine_resolution {
+	u32 htp;
+	u32 hsp;
+	u32 hsw;
+	u32 hdp;
+	u32 vtr;
+	u32 vsp;
+	u32 vsw;
+	u32 vdp;
+	u32 disp_mode;
+};
+
+struct carmine_fb {
+	void __iomem *display_reg;
+	void __iomem *screen_base;
+	u32 smem_offset;
+	u32 cur_mode;
+	u32 new_mode;
+	struct carmine_resolution *res;
+	u32 pseudo_palette[16];
+};
+
+static struct fb_fix_screeninfo carminefb_fix = {
+	.id = "Carmine",
+	.type = FB_TYPE_PACKED_PIXELS,
+	.visual = FB_VISUAL_TRUECOLOR,
+	.accel = FB_ACCEL_NONE,
+};
+
+static const struct fb_videomode carmine_modedb[] = {
+	{
+		.name		= "640x480",
+		.xres		= 640,
+		.yres		= 480,
+	}, {
+		.name		= "800x600",
+		.xres		= 800,
+		.yres		= 600,
+	},
+};
+
+static struct carmine_resolution car_modes[] = {
+	{
+		/* 640x480 */
+		.htp = 800,
+		.hsp = 672,
+		.hsw = 96,
+		.hdp = 640,
+		.vtr = 525,
+		.vsp = 490,
+		.vsw = 2,
+		.vdp = 480,
+		.disp_mode = 0x1400,
+	},
+	{
+		/* 800x600 */
+		.htp = 1060,
+		.hsp = 864,
+		.hsw = 72,
+		.hdp = 800,
+		.vtr = 628,
+		.vsp = 601,
+		.vsw = 2,
+		.vdp = 600,
+		.disp_mode = 0x0d00,
+	}
+};
+
+static int carmine_find_mode(const struct fb_var_screeninfo *var)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(car_modes); i++)
+		if (car_modes[i].hdp == var->xres &&
+		    car_modes[i].vdp == var->yres)
+			return i;
+	return -EINVAL;
+}
+
+static void c_set_disp_reg(const struct carmine_fb *par,
+		u32 offset, u32 val)
+{
+	writel(val, par->display_reg + offset);
+}
+
+static u32 c_get_disp_reg(const struct carmine_fb *par,
+		u32 offset)
+{
+	return readl(par->display_reg + offset);
+}
+
+static void c_set_hw_reg(const struct carmine_hw *hw,
+		u32 offset, u32 val)
+{
+	writel(val, hw->v_regs + offset);
+}
+
+static u32 c_get_hw_reg(const struct carmine_hw *hw,
+		u32 offset)
+{
+	return readl(hw->v_regs + offset);
+}
+
+static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
+		unsigned blue, unsigned transp, struct fb_info *info)
+{
+	if (regno >= 16)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	transp >>= 8;
+
+	((__be32 *)info->pseudo_palette)[regno] = cpu_to_be32(transp << 24 |
+		red << 0 | green << 8 | blue << 16);
+	return 0;
+}
+
+static int carmine_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	int ret;
+
+	ret = carmine_find_mode(var);
+	if (ret < 0)
+		return ret;
+
+	if (var->grayscale || var->rotate || var->nonstd)
+		return -EINVAL;
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	var->bits_per_pixel = 32;
+
+#ifdef __BIG_ENDIAN
+	var->transp.offset = 24;
+	var->red.offset = 0;
+	var->green.offset = 8;
+	var->blue.offset = 16;
+#else
+	var->transp.offset = 24;
+	var->red.offset = 16;
+	var->green.offset = 8;
+	var->blue.offset = 0;
+#endif
+
+	var->red.length = 8;
+	var->green.length = 8;
+	var->blue.length = 8;
+	var->transp.length = 8;
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+	return 0;
+}
+
+static void carmine_init_display_param(struct carmine_fb *par)
+{
+	u32 width;
+	u32 height;
+	u32 param;
+	u32 window_size;
+	u32 soffset = par->smem_offset;
+
+	c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
+			CARMINE_CURSOR0_PRIORITY_MASK |
+			CARMINE_CURSOR1_PRIORITY_MASK |
+			CARMINE_CURSOR_CUTZ_MASK);
+
+	/* Set default cursor position */
+	c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
+
+	/* Set default display mode */
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
+			CARMINE_EXT_CMODE_DIRECT24_RGBA);
+
+	/* Set default frame size to layer mode register */
+	width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
+	width = width << CARMINE_DISP_WIDTH_SHIFT;
+
+	height = par->res->vdp - 1;
+	param = width | height;
+
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
+
+	/* Set default pos and size */
+	window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
+	window_size |= par->res->hdp;
+
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
+
+	/* Set default origin address */
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
+
+	/* Set default display address */
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
+
+	/* Set default display position */
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
+
+	/* Set default blend mode */
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
+
+	/* default transparency mode */
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
+
+	/* Set default read skip parameter */
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
+
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
+
+	c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
+	c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
+}
+
+static void set_display_parameters(struct carmine_fb *par)
+{
+	u32 mode;
+	u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
+
+	/*
+	 * display timing. Parameters are decreased by one because hardware
+	 * spec is 0 to (n - 1)
+	 * */
+	hdp = par->res->hdp - 1;
+	vdp = par->res->vdp - 1;
+	htp = par->res->htp - 1;
+	hsp = par->res->hsp - 1;
+	hsw = par->res->hsw - 1;
+	vtr = par->res->vtr - 1;
+	vsp = par->res->vsp - 1;
+	vsw = par->res->vsw - 1;
+
+	c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
+			htp << CARMINE_DISP_HTP_SHIFT);
+	c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
+			(hdp << CARMINE_DISP_HDB_SHIFT)	| hdp);
+	c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
+			(vsw << CARMINE_DISP_VSW_SHIFT) |
+			(hsw << CARMINE_DISP_HSW_SHIFT) |
+			(hsp));
+	c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
+			vtr << CARMINE_DISP_VTR_SHIFT);
+	c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
+			(vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
+
+	/* clock */
+	mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
+	mode = (mode & ~CARMINE_DISP_DCM_MASK) |
+		(par->res->disp_mode & CARMINE_DISP_DCM_MASK);
+	/* enable video output and layer 0 */
+	mode |= CARMINE_DEN | CARMINE_L0E;
+	c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
+}
+
+static int carmine_set_par(struct fb_info *info)
+{
+	struct carmine_fb *par = info->par;
+	int ret;
+
+	ret = carmine_find_mode(&info->var);
+	if (ret < 0)
+		return ret;
+
+	par->new_mode = ret;
+	if (par->cur_mode != par->new_mode) {
+
+		par->cur_mode = par->new_mode;
+		par->res = &car_modes[par->new_mode];
+
+		carmine_init_display_param(par);
+		set_display_parameters(par);
+	}
+
+	info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
+	return 0;
+}
+
+static int init_hardware(struct carmine_hw *hw)
+{
+	u32 flags;
+	u32 loops;
+	u32 ret;
+
+	/* Initialize Carmine */
+	/* Sets internal clock */
+	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
+			CARMINE_DFLT_IP_CLOCK_ENABLE);
+
+	/* Video signal output is turned off */
+	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+
+	/* Software reset */
+	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
+	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
+
+	/* I/O mode settings */
+	flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
+		CARMINE_DFLT_IP_DCTL_IO_CONT0;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
+			flags);
+
+	/* DRAM initial sequence */
+	flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
+			flags);
+
+	flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
+		CARMINE_DFLT_IP_DCTL_EMODE;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
+			flags);
+
+	flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
+		CARMINE_DFLT_IP_DCTL_SET_TIME2;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
+			flags);
+
+	flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
+		CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
+
+	flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
+			flags);
+
+	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+		CARMINE_DFLT_IP_DCTL_STATES;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+			flags);
+
+	/* Executes DLL reset */
+	if (CARMINE_DCTL_DLL_RESET) {
+		for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
+
+			ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
+					CARMINE_DCTL_REG_RSV0_STATES);
+			ret &= CARMINE_DCTL_REG_STATES_MASK;
+			if (!ret)
+				break;
+
+			mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
+		}
+
+		if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
+			printk(KERN_ERR "DRAM init failed\n");
+			return -EIO;
+		}
+	}
+
+	flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
+		CARMINE_DFLT_IP_DCTL_ADD;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
+
+	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+		CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
+	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+			flags);
+
+	/* Initialize the write back register */
+	c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
+			CARMINE_WB_REG_WBM_DEFAULT);
+
+	/* Initialize the Kottos registers */
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
+
+	/* Set DC offsets */
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
+	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
+	return 0;
+}
+
+static struct fb_ops carminefb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+
+	.fb_check_var	= carmine_check_var,
+	.fb_set_par	= carmine_set_par,
+	.fb_setcolreg	= carmine_setcolreg,
+};
+
+static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
+			    int smem_offset, struct device *device,
+			    struct fb_info **rinfo)
+{
+	int ret;
+	struct fb_info *info;
+	struct carmine_fb *par;
+
+	info = framebuffer_alloc(sizeof *par, device);
+	if (!info)
+		return -ENOMEM;
+
+	par = info->par;
+	par->display_reg = regs;
+	par->smem_offset = smem_offset;
+
+	info->screen_base = smem_base + smem_offset;
+	info->screen_size = CARMINE_DISPLAY_MEM;
+	info->fbops = &carminefb_ops;
+
+	info->fix = carminefb_fix;
+	info->pseudo_palette = par->pseudo_palette;
+	info->flags = FBINFO_DEFAULT;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 1);
+	if (ret < 0)
+		goto err_free_fb;
+
+	if (fb_mode >= ARRAY_SIZE(carmine_modedb))
+		fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+
+	par->cur_mode = par->new_mode = ~0;
+
+	ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
+			ARRAY_SIZE(carmine_modedb),
+			&carmine_modedb[fb_mode], 32);
+	if (!ret || ret == 4) {
+		ret = -EINVAL;
+		goto err_dealloc_cmap;
+	}
+
+	fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
+			&info->modelist);
+
+	ret = register_framebuffer(info);
+	if (ret < 0)
+		goto err_dealloc_cmap;
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	*rinfo = info;
+	return 0;
+
+err_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+err_free_fb:
+	framebuffer_release(info);
+	return ret;
+}
+
+static void cleanup_fb_device(struct fb_info *info)
+{
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+}
+
+static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+	struct carmine_hw *hw;
+	struct device *device = &dev->dev;
+	struct fb_info *info;
+	int ret;
+
+	ret = pci_enable_device(dev);
+	if (ret)
+		return ret;
+
+	ret = -ENOMEM;
+	hw = kzalloc(sizeof *hw, GFP_KERNEL);
+	if (!hw)
+		goto err_enable_pci;
+
+	carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
+	carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
+
+	if (!request_mem_region(carminefb_fix.mmio_start,
+				carminefb_fix.mmio_len,
+				"carminefb regbase")) {
+		printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
+		ret = -EBUSY;
+		goto err_free_hw;
+	}
+	hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,
+			carminefb_fix.mmio_len);
+	if (!hw->v_regs) {
+		printk(KERN_ERR "carminefb: Can't remap %s register.\n",
+				carminefb_fix.id);
+		goto err_free_reg_mmio;
+	}
+
+	carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
+	carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
+
+	/* The memory area tends to be very large (256 MiB). Remap only what
+	 * is required for that largest resolution to avoid remaps at run
+	 * time
+	 */
+	if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
+		carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
+
+	else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
+		printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
+				"are required.", carminefb_fix.smem_len,
+				CARMINE_TOTAL_DIPLAY_MEM);
+		goto err_unmap_vregs;
+	}
+
+	if (!request_mem_region(carminefb_fix.smem_start,
+				carminefb_fix.smem_len,	"carminefb smem")) {
+		printk(KERN_ERR "carminefb: Can't reserve smem.\n");
+		goto err_unmap_vregs;
+	}
+
+	hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,
+			carminefb_fix.smem_len);
+	if (!hw->screen_mem) {
+		printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
+		goto err_reg_smem;
+	}
+
+	ret = init_hardware(hw);
+	if (ret)
+		goto err_unmap_screen;
+
+	info = NULL;
+	if (fb_displays & CARMINE_USE_DISPLAY0) {
+		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
+				hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
+				device, &info);
+		if (ret)
+			goto err_deinit_hw;
+	}
+
+	hw->fb[0] = info;
+
+	info = NULL;
+	if (fb_displays & CARMINE_USE_DISPLAY1) {
+		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
+				hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
+				device, &info);
+		if (ret)
+			goto err_cleanup_fb0;
+	}
+
+	hw->fb[1] = info;
+	info = NULL;
+
+	pci_set_drvdata(dev, hw);
+	return 0;
+
+err_cleanup_fb0:
+	cleanup_fb_device(hw->fb[0]);
+err_deinit_hw:
+	/* disable clock, etc */
+	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+err_unmap_screen:
+	iounmap(hw->screen_mem);
+err_reg_smem:
+	release_mem_region(carminefb_fix.smem_start, carminefb_fix.smem_len);
+err_unmap_vregs:
+	iounmap(hw->v_regs);
+err_free_reg_mmio:
+	release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+err_free_hw:
+	kfree(hw);
+err_enable_pci:
+	pci_disable_device(dev);
+	return ret;
+}
+
+static void carminefb_remove(struct pci_dev *dev)
+{
+	struct carmine_hw *hw = pci_get_drvdata(dev);
+	struct fb_fix_screeninfo fix;
+	int i;
+
+	/* in case we use only fb1 and not fb1 */
+	if (hw->fb[0])
+		fix = hw->fb[0]->fix;
+	else
+		fix = hw->fb[1]->fix;
+
+	/* deactivate display(s) and switch clocks */
+	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+
+	for (i = 0; i < MAX_DISPLAY; i++)
+		cleanup_fb_device(hw->fb[i]);
+
+	iounmap(hw->screen_mem);
+	release_mem_region(fix.smem_start, fix.smem_len);
+	iounmap(hw->v_regs);
+	release_mem_region(fix.mmio_start, fix.mmio_len);
+
+	pci_disable_device(dev);
+	kfree(hw);
+}
+
+#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
+static struct pci_device_id carmine_devices[] = {
+{
+	PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, carmine_devices);
+
+static struct pci_driver carmine_pci_driver = {
+	.name		= "carminefb",
+	.id_table	= carmine_devices,
+	.probe		= carminefb_probe,
+	.remove		= carminefb_remove,
+};
+
+static int __init carminefb_init(void)
+{
+	if (!(fb_displays &
+		(CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
+		printk(KERN_ERR "If you disable both displays than you don't "
+				"need the driver at all\n");
+		return -EINVAL;
+	}
+	return pci_register_driver(&carmine_pci_driver);
+}
+module_init(carminefb_init);
+
+static void __exit carminefb_cleanup(void)
+{
+	pci_unregister_driver(&carmine_pci_driver);
+}
+module_exit(carminefb_cleanup);
+
+MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/carminefb.h b/drivers/video/fbdev/carminefb.h
new file mode 100644
index 000000000000..05306de0c6b6
--- /dev/null
+++ b/drivers/video/fbdev/carminefb.h
@@ -0,0 +1,64 @@
+#ifndef CARMINE_CARMINE_H
+#define CARMINE_CARMINE_H
+
+#define CARMINE_MEMORY_BAR	2
+#define CARMINE_CONFIG_BAR	3
+
+#define MAX_DISPLAY	2
+#define CARMINE_DISPLAY_MEM	(800 * 600 * 4)
+#define CARMINE_TOTAL_DIPLAY_MEM	(CARMINE_DISPLAY_MEM * MAX_DISPLAY)
+
+#define CARMINE_USE_DISPLAY0	(1 << 0)
+#define CARMINE_USE_DISPLAY1	(1 << 1)
+
+/*
+ * This values work on the eval card. Custom boards may use different timings,
+ * here an example :)
+ */
+
+/* DRAM initialization values */
+#ifdef CONFIG_FB_CARMINE_DRAM_EVAL
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE		(0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD		(0x05c3)
+#define CARMINE_DFLT_IP_DCTL_MODE		(0x0121)
+#define CARMINE_DFLT_IP_DCTL_EMODE		(0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1		(0x4749)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2		(0x2a22)
+#define CARMINE_DFLT_IP_DCTL_REFRESH		(0x0042)
+#define CARMINE_DFLT_IP_DCTL_STATES		(0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0		(0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH		(0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2		(0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1		(0x6646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2		(0x0055)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST	(0x0021)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST	(0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0		(0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1		(0x0555)
+#define CARMINE_DCTL_DLL_RESET			(1)
+#endif
+
+#ifdef CONFIG_CARMINE_DRAM_CUSTOM
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE		(0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD		(0x03b2)
+#define CARMINE_DFLT_IP_DCTL_MODE		(0x0161)
+#define CARMINE_DFLT_IP_DCTL_EMODE		(0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1		(0x2628)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2		(0x1a09)
+#define CARMINE_DFLT_IP_DCTL_REFRESH		(0x00fe)
+#define CARMINE_DFLT_IP_DCTL_STATES		(0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0		(0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH		(0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2		(0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1		(0x0646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2		(0x55aa)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST	(0x0061)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST	(0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0		(0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1		(0x0555)
+#define CARMINE_DCTL_DLL_RESET			(1)
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/carminefb_regs.h b/drivers/video/fbdev/carminefb_regs.h
new file mode 100644
index 000000000000..045215600b73
--- /dev/null
+++ b/drivers/video/fbdev/carminefb_regs.h
@@ -0,0 +1,159 @@
+#ifndef _CARMINEFB_REGS_H
+#define _CARMINEFB_REGS_H
+
+#define CARMINE_OVERLAY_EXT_MODE	(0x00000002)
+#define CARMINE_GRAPH_REG		(0x00000000)
+#define CARMINE_DISP0_REG		(0x00100000)
+#define CARMINE_DISP1_REG		(0x00140000)
+#define CARMINE_WB_REG			(0x00180000)
+#define CARMINE_DCTL_REG		(0x00300000)
+#define CARMINE_CTL_REG			(0x00400000)
+#define CARMINE_WINDOW_MODE		(0x00000001)
+#define CARMINE_EXTEND_MODE		(CARMINE_WINDOW_MODE | \
+					CARMINE_OVERLAY_EXT_MODE)
+#define CARMINE_L0E			(1 << 16)
+#define CARMINE_L2E			(1 << 18)
+#define CARMINE_DEN			(1 << 31)
+
+#define CARMINE_EXT_CMODE_DIRECT24_RGBA		(0xC0000000)
+#define CARMINE_DCTL_REG_MODE_ADD		(0x00)
+#define CARMINE_DCTL_REG_SETTIME1_EMODE		(0x04)
+#define CARMINE_DCTL_REG_REFRESH_SETTIME2	(0x08)
+#define CARMINE_DCTL_REG_RSV0_STATES		(0x0C)
+#define CARMINE_DCTL_REG_RSV2_RSV1		(0x10)
+#define CARMINE_DCTL_REG_DDRIF2_DDRIF1		(0x14)
+#define CARMINE_DCTL_REG_IOCONT1_IOCONT0	(0x24)
+#define CARMINE_DCTL_REG_STATES_MASK		(0x000F)
+#define CARMINE_DCTL_INIT_WAIT_INTERVAL		(1)
+#define CARMINE_DCTL_INIT_WAIT_LIMIT		(5000)
+#define CARMINE_WB_REG_WBM_DEFAULT		(0x0001c020)
+#define CARMINE_DISP_REG_L0RM			(0x1880)
+#define CARMINE_DISP_REG_L0PX			(0x1884)
+#define CARMINE_DISP_REG_L0PY			(0x1888)
+#define CARMINE_DISP_REG_L2RM			(0x18A0)
+#define CARMINE_DISP_REG_L2PX			(0x18A4)
+#define CARMINE_DISP_REG_L2PY			(0x18A8)
+#define CARMINE_DISP_REG_L3RM			(0x18B0)
+#define CARMINE_DISP_REG_L3PX			(0x18B4)
+#define CARMINE_DISP_REG_L3PY			(0x18B8)
+#define CARMINE_DISP_REG_L4RM			(0x18C0)
+#define CARMINE_DISP_REG_L4PX			(0x18C4)
+#define CARMINE_DISP_REG_L4PY			(0x18C8)
+#define CARMINE_DISP_REG_L5RM			(0x18D0)
+#define CARMINE_DISP_REG_L5PX			(0x18D4)
+#define CARMINE_DISP_REG_L5PY			(0x18D8)
+#define CARMINE_DISP_REG_L6RM			(0x1924)
+#define CARMINE_DISP_REG_L6PX			(0x1928)
+#define CARMINE_DISP_REG_L6PY			(0x192C)
+#define CARMINE_DISP_REG_L7RM			(0x1964)
+#define CARMINE_DISP_REG_L7PX			(0x1968)
+#define CARMINE_DISP_REG_L7PY			(0x196C)
+#define CARMINE_WB_REG_WBM			(0x0004)
+#define CARMINE_DISP_HTP_SHIFT			(16)
+#define CARMINE_DISP_HDB_SHIFT			(16)
+#define CARMINE_DISP_HSW_SHIFT			(16)
+#define CARMINE_DISP_VSW_SHIFT			(24)
+#define CARMINE_DISP_VTR_SHIFT			(16)
+#define CARMINE_DISP_VDP_SHIFT			(16)
+#define CARMINE_CURSOR_CUTZ_MASK		(0x00000100)
+#define CARMINE_CURSOR0_PRIORITY_MASK		(0x00010000)
+#define CARMINE_CURSOR1_PRIORITY_MASK		(0x00020000)
+#define CARMINE_DISP_WIDTH_SHIFT		(16)
+#define CARMINE_DISP_WIN_H_SHIFT		(16)
+#define CARMINE_DISP_REG_H_TOTAL		(0x0004)
+#define CARMINE_DISP_REG_H_PERIOD		(0x0008)
+#define CARMINE_DISP_REG_V_H_W_H_POS		(0x000C)
+#define CARMINE_DISP_REG_V_TOTAL		(0x0010)
+#define CARMINE_DISP_REG_V_PERIOD_POS		(0x0014)
+#define CARMINE_DISP_REG_L0_MODE_W_H		(0x0020)
+#define CARMINE_DISP_REG_L0_ORG_ADR		(0x0024)
+#define CARMINE_DISP_REG_L0_DISP_ADR		(0x0028)
+#define CARMINE_DISP_REG_L0_DISP_POS		(0x002C)
+#define CARMINE_DISP_REG_L1_WIDTH		(0x0030)
+#define CARMINE_DISP_REG_L1_ORG_ADR		(0x0034)
+#define CARMINE_DISP_REG_L2_MODE_W_H		(0x0040)
+#define CARMINE_DISP_REG_L2_ORG_ADR1		(0x0044)
+#define CARMINE_DISP_REG_L2_DISP_ADR1		(0x0048)
+#define CARMINE_DISP_REG_L2_DISP_POS		(0x0054)
+#define CARMINE_DISP_REG_L3_MODE_W_H		(0x0058)
+#define CARMINE_DISP_REG_L3_ORG_ADR1		(0x005C)
+#define CARMINE_DISP_REG_L3_DISP_ADR1		(0x0060)
+#define CARMINE_DISP_REG_L3_DISP_POS		(0x006C)
+#define CARMINE_DISP_REG_L4_MODE_W_H		(0x0070)
+#define CARMINE_DISP_REG_L4_ORG_ADR1		(0x0074)
+#define CARMINE_DISP_REG_L4_DISP_ADR1		(0x0078)
+#define CARMINE_DISP_REG_L4_DISP_POS		(0x0084)
+#define CARMINE_DISP_REG_L5_MODE_W_H		(0x0088)
+#define CARMINE_DISP_REG_L5_ORG_ADR1		(0x008C)
+#define CARMINE_DISP_REG_L5_DISP_ADR1		(0x0090)
+#define CARMINE_DISP_REG_L5_DISP_POS		(0x009C)
+#define CARMINE_DISP_REG_CURSOR_MODE		(0x00A0)
+#define CARMINE_DISP_REG_CUR1_POS		(0x00A8)
+#define CARMINE_DISP_REG_CUR2_POS		(0x00B0)
+#define CARMINE_DISP_REG_C_TRANS		(0x00BC)
+#define CARMINE_DISP_REG_MLMR_TRANS		(0x00C0)
+#define CARMINE_DISP_REG_L0_EXT_MODE		(0x0110)
+#define CARMINE_DISP_REG_L0_WIN_POS		(0x0114)
+#define CARMINE_DISP_REG_L0_WIN_SIZE		(0x0118)
+#define CARMINE_DISP_REG_L1_EXT_MODE		(0x0120)
+#define CARMINE_DISP_REG_L1_WIN_POS		(0x0124)
+#define CARMINE_DISP_REG_L1_WIN_SIZE		(0x0128)
+#define CARMINE_DISP_REG_L2_EXT_MODE		(0x0130)
+#define CARMINE_DISP_REG_L2_WIN_POS		(0x0134)
+#define CARMINE_DISP_REG_L2_WIN_SIZE		(0x0138)
+#define CARMINE_DISP_REG_L3_EXT_MODE		(0x0140)
+#define CARMINE_DISP_REG_L3_WIN_POS		(0x0144)
+#define CARMINE_DISP_REG_L3_WIN_SIZE		(0x0148)
+#define CARMINE_DISP_REG_L4_EXT_MODE		(0x0150)
+#define CARMINE_DISP_REG_L4_WIN_POS		(0x0154)
+#define CARMINE_DISP_REG_L4_WIN_SIZE		(0x0158)
+#define CARMINE_DISP_REG_L5_EXT_MODE		(0x0160)
+#define CARMINE_DISP_REG_L5_WIN_POS		(0x0164)
+#define CARMINE_DISP_REG_L5_WIN_SIZE		(0x0168)
+#define CARMINE_DISP_REG_L6_EXT_MODE		(0x1918)
+#define CARMINE_DISP_REG_L6_WIN_POS		(0x191c)
+#define CARMINE_DISP_REG_L6_WIN_SIZE		(0x1920)
+#define CARMINE_DISP_REG_L7_EXT_MODE		(0x1958)
+#define CARMINE_DISP_REG_L7_WIN_POS		(0x195c)
+#define CARMINE_DISP_REG_L7_WIN_SIZE		(0x1960)
+#define CARMINE_DISP_REG_BLEND_MODE_L0		(0x00B4)
+#define CARMINE_DISP_REG_BLEND_MODE_L1		(0x0188)
+#define CARMINE_DISP_REG_BLEND_MODE_L2		(0x018C)
+#define CARMINE_DISP_REG_BLEND_MODE_L3		(0x0190)
+#define CARMINE_DISP_REG_BLEND_MODE_L4		(0x0194)
+#define CARMINE_DISP_REG_BLEND_MODE_L5		(0x0198)
+#define CARMINE_DISP_REG_BLEND_MODE_L6		(0x1990)
+#define CARMINE_DISP_REG_BLEND_MODE_L7		(0x1994)
+#define CARMINE_DISP_REG_L0_TRANS		(0x01A0)
+#define CARMINE_DISP_REG_L1_TRANS		(0x01A4)
+#define CARMINE_DISP_REG_L2_TRANS		(0x01A8)
+#define CARMINE_DISP_REG_L3_TRANS		(0x01AC)
+#define CARMINE_DISP_REG_L4_TRANS		(0x01B0)
+#define CARMINE_DISP_REG_L5_TRANS		(0x01B4)
+#define CARMINE_DISP_REG_L6_TRANS		(0x1998)
+#define CARMINE_DISP_REG_L7_TRANS		(0x199c)
+#define CARMINE_EXTEND_MODE_MASK		(0x00000003)
+#define CARMINE_DISP_DCM_MASK			(0x0000FFFF)
+#define CARMINE_DISP_REG_DCM1			(0x0100)
+#define CARMINE_DISP_WIDTH_UNIT			(64)
+#define CARMINE_DISP_REG_L6_MODE_W_H		(0x1900)
+#define CARMINE_DISP_REG_L6_ORG_ADR1		(0x1904)
+#define CARMINE_DISP_REG_L6_DISP_ADR0		(0x1908)
+#define CARMINE_DISP_REG_L6_DISP_POS		(0x1914)
+#define CARMINE_DISP_REG_L7_MODE_W_H		(0x1940)
+#define CARMINE_DISP_REG_L7_ORG_ADR1		(0x1944)
+#define CARMINE_DISP_REG_L7_DISP_ADR0		(0x1948)
+#define CARMINE_DISP_REG_L7_DISP_POS		(0x1954)
+#define CARMINE_CTL_REG_CLOCK_ENABLE		(0x000C)
+#define CARMINE_CTL_REG_SOFTWARE_RESET		(0x0010)
+#define CARMINE_CTL_REG_IST_MASK_ALL		(0x07FFFFFF)
+#define CARMINE_GRAPH_REG_VRINTM		(0x00028064)
+#define CARMINE_GRAPH_REG_VRERRM		(0x0002806C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PX		(0x0004005C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PY		(0x00040060)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LX		(0x00040064)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LY		(0x00040068)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TX		(0x0004006C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TY		(0x00040070)
+
+#endif
diff --git a/drivers/video/fbdev/cg14.c b/drivers/video/fbdev/cg14.c
new file mode 100644
index 000000000000..c79745b136bb
--- /dev/null
+++ b/drivers/video/fbdev/cg14.c
@@ -0,0 +1,626 @@
+/* cg14.c: CGFOURTEEN frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+
+static int cg14_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
+static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops cg14_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= cg14_setcolreg,
+	.fb_pan_display		= cg14_pan_display,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= cg14_mmap,
+	.fb_ioctl		= cg14_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+#define CG14_MCR_INTENABLE_SHIFT	7
+#define CG14_MCR_INTENABLE_MASK		0x80
+#define CG14_MCR_VIDENABLE_SHIFT	6
+#define CG14_MCR_VIDENABLE_MASK		0x40
+#define CG14_MCR_PIXMODE_SHIFT		4
+#define CG14_MCR_PIXMODE_MASK		0x30
+#define CG14_MCR_TMR_SHIFT		2
+#define CG14_MCR_TMR_MASK		0x0c
+#define CG14_MCR_TMENABLE_SHIFT		1
+#define CG14_MCR_TMENABLE_MASK		0x02
+#define CG14_MCR_RESET_SHIFT		0
+#define CG14_MCR_RESET_MASK		0x01
+#define CG14_REV_REVISION_SHIFT		4
+#define CG14_REV_REVISION_MASK		0xf0
+#define CG14_REV_IMPL_SHIFT		0
+#define CG14_REV_IMPL_MASK		0x0f
+#define CG14_VBR_FRAMEBASE_SHIFT	12
+#define CG14_VBR_FRAMEBASE_MASK		0x00fff000
+#define CG14_VMCR1_SETUP_SHIFT		0
+#define CG14_VMCR1_SETUP_MASK		0x000001ff
+#define CG14_VMCR1_VCONFIG_SHIFT	9
+#define CG14_VMCR1_VCONFIG_MASK		0x00000e00
+#define CG14_VMCR2_REFRESH_SHIFT	0
+#define CG14_VMCR2_REFRESH_MASK		0x00000001
+#define CG14_VMCR2_TESTROWCNT_SHIFT	1
+#define CG14_VMCR2_TESTROWCNT_MASK	0x00000002
+#define CG14_VMCR2_FBCONFIG_SHIFT	2
+#define CG14_VMCR2_FBCONFIG_MASK	0x0000000c
+#define CG14_VCR_REFRESHREQ_SHIFT	0
+#define CG14_VCR_REFRESHREQ_MASK	0x000003ff
+#define CG14_VCR1_REFRESHENA_SHIFT	10
+#define CG14_VCR1_REFRESHENA_MASK	0x00000400
+#define CG14_VCA_CAD_SHIFT		0
+#define CG14_VCA_CAD_MASK		0x000003ff
+#define CG14_VCA_VERS_SHIFT		10
+#define CG14_VCA_VERS_MASK		0x00000c00
+#define CG14_VCA_RAMSPEED_SHIFT		12
+#define CG14_VCA_RAMSPEED_MASK		0x00001000
+#define CG14_VCA_8MB_SHIFT		13
+#define CG14_VCA_8MB_MASK		0x00002000
+
+#define CG14_MCR_PIXMODE_8		0
+#define CG14_MCR_PIXMODE_16		2
+#define CG14_MCR_PIXMODE_32		3
+
+struct cg14_regs{
+	u8 mcr;	/* Master Control Reg */
+	u8 ppr;	/* Packed Pixel Reg */
+	u8 tms[2];	/* Test Mode Status Regs */
+	u8 msr;	/* Master Status Reg */
+	u8 fsr;	/* Fault Status Reg */
+	u8 rev;	/* Revision & Impl */
+	u8 ccr;	/* Clock Control Reg */
+	u32 tmr;	/* Test Mode Read Back */
+	u8 mod;	/* Monitor Operation Data Reg */
+	u8 acr;	/* Aux Control */
+	u8 xxx0[6];
+	u16 hct;	/* Hor Counter */
+	u16 vct;	/* Vert Counter */
+	u16 hbs;	/* Hor Blank Start */
+	u16 hbc;	/* Hor Blank Clear */
+	u16 hss;	/* Hor Sync Start */
+	u16 hsc;	/* Hor Sync Clear */
+	u16 csc;	/* Composite Sync Clear */
+	u16 vbs;	/* Vert Blank Start */
+	u16 vbc;	/* Vert Blank Clear */
+	u16 vss;	/* Vert Sync Start */
+	u16 vsc;	/* Vert Sync Clear */
+	u16 xcs;
+	u16 xcc;
+	u16 fsa;	/* Fault Status Address */
+	u16 adr;	/* Address Registers */
+	u8 xxx1[0xce];
+	u8 pcg[0x100]; /* Pixel Clock Generator */
+	u32 vbr;	/* Frame Base Row */
+	u32 vmcr;	/* VBC Master Control */
+	u32 vcr;	/* VBC refresh */
+	u32 vca;	/* VBC Config */
+};
+
+#define CG14_CCR_ENABLE	0x04
+#define CG14_CCR_SELECT 0x02	/* HW/Full screen */
+
+struct cg14_cursor {
+	u32 cpl0[32];	/* Enable plane 0 */
+	u32 cpl1[32];  /* Color selection plane */
+	u8 ccr;	/* Cursor Control Reg */
+	u8 xxx0[3];
+	u16 cursx;	/* Cursor x,y position */
+	u16 cursy;	/* Cursor x,y position */
+	u32 color0;
+	u32 color1;
+	u32 xxx1[0x1bc];
+	u32 cpl0i[32];	/* Enable plane 0 autoinc */
+	u32 cpl1i[32]; /* Color selection autoinc */
+};
+
+struct cg14_dac {
+	u8 addr;	/* Address Register */
+	u8 xxx0[255];
+	u8 glut;	/* Gamma table */
+	u8 xxx1[255];
+	u8 select;	/* Register Select */
+	u8 xxx2[255];
+	u8 mode;	/* Mode Register */
+};
+
+struct cg14_xlut{
+	u8 x_xlut [256];
+	u8 x_xlutd [256];
+	u8 xxx0[0x600];
+	u8 x_xlut_inc [256];
+	u8 x_xlutd_inc [256];
+};
+
+/* Color look up table (clut) */
+/* Each one of these arrays hold the color lookup table (for 256
+ * colors) for each MDI page (I assume then there should be 4 MDI
+ * pages, I still wonder what they are.  I have seen NeXTStep split
+ * the screen in four parts, while operating in 24 bits mode.  Each
+ * integer holds 4 values: alpha value (transparency channel, thanks
+ * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
+ *
+ * I currently use the clut instead of the Xlut
+ */
+struct cg14_clut {
+	u32 c_clut [256];
+	u32 c_clutd [256];    /* i wonder what the 'd' is for */
+	u32 c_clut_inc [256];
+	u32 c_clutd_inc [256];
+};
+
+#define CG14_MMAP_ENTRIES	16
+
+struct cg14_par {
+	spinlock_t		lock;
+	struct cg14_regs	__iomem *regs;
+	struct cg14_clut	__iomem *clut;
+	struct cg14_cursor	__iomem *cursor;
+
+	u32			flags;
+#define CG14_FLAG_BLANKED	0x00000001
+
+	unsigned long		iospace;
+
+	struct sbus_mmap_map	mmap_map[CG14_MMAP_ENTRIES];
+
+	int			mode;
+	int			ramsize;
+};
+
+static void __cg14_reset(struct cg14_par *par)
+{
+	struct cg14_regs __iomem *regs = par->regs;
+	u8 val;
+
+	val = sbus_readb(&regs->mcr);
+	val &= ~(CG14_MCR_PIXMODE_MASK);
+	sbus_writeb(val, &regs->mcr);
+}
+
+static int cg14_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct cg14_par *par = (struct cg14_par *) info->par;
+	unsigned long flags;
+
+	/* We just use this to catch switches out of
+	 * graphics mode.
+	 */
+	spin_lock_irqsave(&par->lock, flags);
+	__cg14_reset(par);
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	if (var->xoffset || var->yoffset || var->vmode)
+		return -EINVAL;
+	return 0;
+}
+
+/**
+ *      cg14_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int cg14_setcolreg(unsigned regno,
+			  unsigned red, unsigned green, unsigned blue,
+			  unsigned transp, struct fb_info *info)
+{
+	struct cg14_par *par = (struct cg14_par *) info->par;
+	struct cg14_clut __iomem *clut = par->clut;
+	unsigned long flags;
+	u32 val;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	val = (red | (green << 8) | (blue << 16));
+
+	spin_lock_irqsave(&par->lock, flags);
+	sbus_writel(val, &clut->c_clut[regno]);
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct cg14_par *par = (struct cg14_par *) info->par;
+
+	return sbusfb_mmap_helper(par->mmap_map,
+				  info->fix.smem_start, info->fix.smem_len,
+				  par->iospace, vma);
+}
+
+static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	struct cg14_par *par = (struct cg14_par *) info->par;
+	struct cg14_regs __iomem *regs = par->regs;
+	struct mdi_cfginfo kmdi, __user *mdii;
+	unsigned long flags;
+	int cur_mode, mode, ret = 0;
+
+	switch (cmd) {
+	case MDI_RESET:
+		spin_lock_irqsave(&par->lock, flags);
+		__cg14_reset(par);
+		spin_unlock_irqrestore(&par->lock, flags);
+		break;
+
+	case MDI_GET_CFGINFO:
+		memset(&kmdi, 0, sizeof(kmdi));
+
+		spin_lock_irqsave(&par->lock, flags);
+		kmdi.mdi_type = FBTYPE_MDICOLOR;
+		kmdi.mdi_height = info->var.yres;
+		kmdi.mdi_width = info->var.xres;
+		kmdi.mdi_mode = par->mode;
+		kmdi.mdi_pixfreq = 72; /* FIXME */
+		kmdi.mdi_size = par->ramsize;
+		spin_unlock_irqrestore(&par->lock, flags);
+
+		mdii = (struct mdi_cfginfo __user *) arg;
+		if (copy_to_user(mdii, &kmdi, sizeof(kmdi)))
+			ret = -EFAULT;
+		break;
+
+	case MDI_SET_PIXELMODE:
+		if (get_user(mode, (int __user *) arg)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		spin_lock_irqsave(&par->lock, flags);
+		cur_mode = sbus_readb(&regs->mcr);
+		cur_mode &= ~CG14_MCR_PIXMODE_MASK;
+		switch(mode) {
+		case MDI_32_PIX:
+			cur_mode |= (CG14_MCR_PIXMODE_32 <<
+				     CG14_MCR_PIXMODE_SHIFT);
+			break;
+
+		case MDI_16_PIX:
+			cur_mode |= (CG14_MCR_PIXMODE_16 <<
+				     CG14_MCR_PIXMODE_SHIFT);
+			break;
+
+		case MDI_8_PIX:
+			break;
+
+		default:
+			ret = -ENOSYS;
+			break;
+		}
+		if (!ret) {
+			sbus_writeb(cur_mode, &regs->mcr);
+			par->mode = mode;
+		}
+		spin_unlock_irqrestore(&par->lock, flags);
+		break;
+
+	default:
+		ret = sbusfb_ioctl_helper(cmd, arg, info,
+					  FBTYPE_MDICOLOR, 8,
+					  info->fix.smem_len);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ *  Initialisation
+ */
+
+static void cg14_init_fix(struct fb_info *info, int linebytes,
+			  struct device_node *dp)
+{
+	const char *name = dp->name;
+
+	strlcpy(info->fix.id, name, sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = linebytes;
+
+	info->fix.accel = FB_ACCEL_SUN_CG14;
+}
+
+static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = {
+	{
+		.voff	= CG14_REGS,
+		.poff	= 0x80000000,
+		.size	= 0x1000
+	},
+	{
+		.voff	= CG14_XLUT,
+		.poff	= 0x80003000,
+		.size	= 0x1000
+	},
+	{
+		.voff	= CG14_CLUT1,
+		.poff	= 0x80004000,
+		.size	= 0x1000
+	},
+	{
+		.voff	= CG14_CLUT2,
+		.poff	= 0x80005000,
+		.size	= 0x1000
+	},
+	{
+		.voff	= CG14_CLUT3,
+		.poff	= 0x80006000,
+		.size	= 0x1000
+	},
+	{
+		.voff	= CG3_MMAP_OFFSET - 0x7000,
+		.poff	= 0x80000000,
+		.size	= 0x7000
+	},
+	{
+		.voff	= CG3_MMAP_OFFSET,
+		.poff	= 0x00000000,
+		.size	= SBUS_MMAP_FBSIZE(1)
+	},
+	{
+		.voff	= MDI_CURSOR_MAP,
+		.poff	= 0x80001000,
+		.size	= 0x1000
+	},
+	{
+		.voff	= MDI_CHUNKY_BGR_MAP,
+		.poff	= 0x01000000,
+		.size	= 0x400000
+	},
+	{
+		.voff	= MDI_PLANAR_X16_MAP,
+		.poff	= 0x02000000,
+		.size	= 0x200000
+	},
+	{
+		.voff	= MDI_PLANAR_C16_MAP,
+		.poff	= 0x02800000,
+		.size	= 0x200000
+	},
+	{
+		.voff	= MDI_PLANAR_X32_MAP,
+		.poff	= 0x03000000,
+		.size	= 0x100000
+	},
+	{
+		.voff	= MDI_PLANAR_B32_MAP,
+		.poff	= 0x03400000,
+		.size	= 0x100000
+	},
+	{
+		.voff	= MDI_PLANAR_G32_MAP,
+		.poff	= 0x03800000,
+		.size	= 0x100000
+	},
+	{
+		.voff	= MDI_PLANAR_R32_MAP,
+		.poff	= 0x03c00000,
+		.size	= 0x100000
+	},
+	{ .size = 0 }
+};
+
+static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
+			    struct cg14_par *par)
+{
+	if (par->regs)
+		of_iounmap(&op->resource[0],
+			   par->regs, sizeof(struct cg14_regs));
+	if (par->clut)
+		of_iounmap(&op->resource[0],
+			   par->clut, sizeof(struct cg14_clut));
+	if (par->cursor)
+		of_iounmap(&op->resource[0],
+			   par->cursor, sizeof(struct cg14_cursor));
+	if (info->screen_base)
+		of_iounmap(&op->resource[1],
+			   info->screen_base, info->fix.smem_len);
+}
+
+static int cg14_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct cg14_par *par;
+	int is_8mb, linebytes, i, err;
+
+	info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+
+	sbusfb_fill_var(&info->var, dp, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
+
+	linebytes = of_getintprop_default(dp, "linebytes",
+					  info->var.xres);
+	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
+
+	if (!strcmp(dp->parent->name, "sbus") ||
+	    !strcmp(dp->parent->name, "sbi")) {
+		info->fix.smem_start = op->resource[0].start;
+		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
+	} else {
+		info->fix.smem_start = op->resource[1].start;
+		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
+	}
+
+	par->regs = of_ioremap(&op->resource[0], 0,
+			       sizeof(struct cg14_regs), "cg14 regs");
+	par->clut = of_ioremap(&op->resource[0], CG14_CLUT1,
+			       sizeof(struct cg14_clut), "cg14 clut");
+	par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
+				 sizeof(struct cg14_cursor), "cg14 cursor");
+
+	info->screen_base = of_ioremap(&op->resource[1], 0,
+				       info->fix.smem_len, "cg14 ram");
+
+	if (!par->regs || !par->clut || !par->cursor || !info->screen_base)
+		goto out_unmap_regs;
+
+	is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
+		  (8 * 1024 * 1024));
+
+	BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
+		
+	memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
+
+	for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
+		struct sbus_mmap_map *map = &par->mmap_map[i];
+
+		if (!map->size)
+			break;
+		if (map->poff & 0x80000000)
+			map->poff = (map->poff & 0x7fffffff) +
+				(op->resource[0].start -
+				 op->resource[1].start);
+		if (is_8mb &&
+		    map->size >= 0x100000 &&
+		    map->size <= 0x400000)
+			map->size *= 2;
+	}
+
+	par->mode = MDI_8_PIX;
+	par->ramsize = (is_8mb ? 0x800000 : 0x400000);
+
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	info->fbops = &cg14_ops;
+
+	__cg14_reset(par);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
+
+	fb_set_cmap(&info->cmap, info);
+
+	cg14_init_fix(info, linebytes, dp);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: cgfourteen at %lx:%lx, %dMB\n",
+	       dp->full_name,
+	       par->iospace, info->fix.smem_start,
+	       par->ramsize >> 20);
+
+	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	cg14_unmap_regs(op, info, par);
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int cg14_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct cg14_par *par = info->par;
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	cg14_unmap_regs(op, info, par);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id cg14_match[] = {
+	{
+		.name = "cgfourteen",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, cg14_match);
+
+static struct platform_driver cg14_driver = {
+	.driver = {
+		.name = "cg14",
+		.owner = THIS_MODULE,
+		.of_match_table = cg14_match,
+	},
+	.probe		= cg14_probe,
+	.remove		= cg14_remove,
+};
+
+static int __init cg14_init(void)
+{
+	if (fb_get_options("cg14fb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&cg14_driver);
+}
+
+static void __exit cg14_exit(void)
+{
+	platform_driver_unregister(&cg14_driver);
+}
+
+module_init(cg14_init);
+module_exit(cg14_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for CGfourteen chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/cg3.c b/drivers/video/fbdev/cg3.c
new file mode 100644
index 000000000000..64a89d5747ed
--- /dev/null
+++ b/drivers/video/fbdev/cg3.c
@@ -0,0 +1,492 @@
+/* cg3.c: CGTHREE frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int cg3_blank(int, struct fb_info *);
+
+static int cg3_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops cg3_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= cg3_setcolreg,
+	.fb_blank		= cg3_blank,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= cg3_mmap,
+	.fb_ioctl		= cg3_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+
+/* Control Register Constants */
+#define CG3_CR_ENABLE_INTS      0x80
+#define CG3_CR_ENABLE_VIDEO     0x40
+#define CG3_CR_ENABLE_TIMING    0x20
+#define CG3_CR_ENABLE_CURCMP    0x10
+#define CG3_CR_XTAL_MASK        0x0c
+#define CG3_CR_DIVISOR_MASK     0x03
+
+/* Status Register Constants */
+#define CG3_SR_PENDING_INT      0x80
+#define CG3_SR_RES_MASK         0x70
+#define CG3_SR_1152_900_76_A    0x40
+#define CG3_SR_1152_900_76_B    0x60
+#define CG3_SR_ID_MASK          0x0f
+#define CG3_SR_ID_COLOR         0x01
+#define CG3_SR_ID_MONO          0x02
+#define CG3_SR_ID_MONO_ECL      0x03
+
+enum cg3_type {
+	CG3_AT_66HZ = 0,
+	CG3_AT_76HZ,
+	CG3_RDI
+};
+
+struct bt_regs {
+	u32 addr;
+	u32 color_map;
+	u32 control;
+	u32 cursor;
+};
+
+struct cg3_regs {
+	struct bt_regs	cmap;
+	u8	control;
+	u8	status;
+	u8	cursor_start;
+	u8	cursor_end;
+	u8	h_blank_start;
+	u8	h_blank_end;
+	u8	h_sync_start;
+	u8	h_sync_end;
+	u8	comp_sync_end;
+	u8	v_blank_start_high;
+	u8	v_blank_start_low;
+	u8	v_blank_end;
+	u8	v_sync_start;
+	u8	v_sync_end;
+	u8	xfer_holdoff_start;
+	u8	xfer_holdoff_end;
+};
+
+/* Offset of interesting structures in the OBIO space */
+#define CG3_REGS_OFFSET	     0x400000UL
+#define CG3_RAM_OFFSET	     0x800000UL
+
+struct cg3_par {
+	spinlock_t		lock;
+	struct cg3_regs		__iomem *regs;
+	u32			sw_cmap[((256 * 3) + 3) / 4];
+
+	u32			flags;
+#define CG3_FLAG_BLANKED	0x00000001
+#define CG3_FLAG_RDI		0x00000002
+
+	unsigned long		which_io;
+};
+
+/**
+ *      cg3_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ * The cg3 palette is loaded with 4 color values at each time
+ * so you end up with: (rgb)(r), (gb)(rg), (b)(rgb), and so on.
+ * We keep a sw copy of the hw cmap to assist us in this esoteric
+ * loading procedure.
+ */
+static int cg3_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct cg3_par *par = (struct cg3_par *) info->par;
+	struct bt_regs __iomem *bt = &par->regs->cmap;
+	unsigned long flags;
+	u32 *p32;
+	u8 *p8;
+	int count;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	p8 = (u8 *)par->sw_cmap + (regno * 3);
+	p8[0] = red;
+	p8[1] = green;
+	p8[2] = blue;
+
+#define D4M3(x) ((((x)>>2)<<1) + ((x)>>2))      /* (x/4)*3 */
+#define D4M4(x) ((x)&~0x3)                      /* (x/4)*4 */
+
+	count = 3;
+	p32 = &par->sw_cmap[D4M3(regno)];
+	sbus_writel(D4M4(regno), &bt->addr);
+	while (count--)
+		sbus_writel(*p32++, &bt->color_map);
+
+#undef D4M3
+#undef D4M4
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *      cg3_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int cg3_blank(int blank, struct fb_info *info)
+{
+	struct cg3_par *par = (struct cg3_par *) info->par;
+	struct cg3_regs __iomem *regs = par->regs;
+	unsigned long flags;
+	u8 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		val = sbus_readb(&regs->control);
+		val |= CG3_CR_ENABLE_VIDEO;
+		sbus_writeb(val, &regs->control);
+		par->flags &= ~CG3_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		val = sbus_readb(&regs->control);
+		val &= ~CG3_CR_ENABLE_VIDEO;
+		sbus_writeb(val, &regs->control);
+		par->flags |= CG3_FLAG_BLANKED;
+		break;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map cg3_mmap_map[] = {
+	{
+		.voff	= CG3_MMAP_OFFSET,
+		.poff	= CG3_RAM_OFFSET,
+		.size	= SBUS_MMAP_FBSIZE(1)
+	},
+	{ .size = 0 }
+};
+
+static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct cg3_par *par = (struct cg3_par *)info->par;
+
+	return sbusfb_mmap_helper(cg3_mmap_map,
+				  info->fix.smem_start, info->fix.smem_len,
+				  par->which_io,
+				  vma);
+}
+
+static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN3COLOR, 8, info->fix.smem_len);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void cg3_init_fix(struct fb_info *info, int linebytes,
+			 struct device_node *dp)
+{
+	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = linebytes;
+
+	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
+}
+
+static void cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
+				    struct device_node *dp)
+{
+	const char *params;
+	char *p;
+	int ww, hh;
+
+	params = of_get_property(dp, "params", NULL);
+	if (params) {
+		ww = simple_strtoul(params, &p, 10);
+		if (ww && *p == 'x') {
+			hh = simple_strtoul(p + 1, &p, 10);
+			if (hh && *p == '-') {
+				if (var->xres != ww ||
+				    var->yres != hh) {
+					var->xres = var->xres_virtual = ww;
+					var->yres = var->yres_virtual = hh;
+				}
+			}
+		}
+	}
+}
+
+static u8 cg3regvals_66hz[] = {	/* 1152 x 900, 66 Hz */
+	0x14, 0xbb,	0x15, 0x2b,	0x16, 0x04,	0x17, 0x14,
+	0x18, 0xae,	0x19, 0x03,	0x1a, 0xa8,	0x1b, 0x24,
+	0x1c, 0x01,	0x1d, 0x05,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x20,	0
+};
+
+static u8 cg3regvals_76hz[] = {	/* 1152 x 900, 76 Hz */
+	0x14, 0xb7,	0x15, 0x27,	0x16, 0x03,	0x17, 0x0f,
+	0x18, 0xae,	0x19, 0x03,	0x1a, 0xae,	0x1b, 0x2a,
+	0x1c, 0x01,	0x1d, 0x09,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x24,	0
+};
+
+static u8 cg3regvals_rdi[] = {	/* 640 x 480, cgRDI */
+	0x14, 0x70,	0x15, 0x20,	0x16, 0x08,	0x17, 0x10,
+	0x18, 0x06,	0x19, 0x02,	0x1a, 0x31,	0x1b, 0x51,
+	0x1c, 0x06,	0x1d, 0x0c,	0x1e, 0xff,	0x1f, 0x01,
+	0x10, 0x22,	0
+};
+
+static u8 *cg3_regvals[] = {
+	cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi
+};
+
+static u_char cg3_dacvals[] = {
+	4, 0xff,	5, 0x00,	6, 0x70,	7, 0x00,	0
+};
+
+static int cg3_do_default_mode(struct cg3_par *par)
+{
+	enum cg3_type type;
+	u8 *p;
+
+	if (par->flags & CG3_FLAG_RDI)
+		type = CG3_RDI;
+	else {
+		u8 status = sbus_readb(&par->regs->status), mon;
+		if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) {
+			mon = status & CG3_SR_RES_MASK;
+			if (mon == CG3_SR_1152_900_76_A ||
+			    mon == CG3_SR_1152_900_76_B)
+				type = CG3_AT_76HZ;
+			else
+				type = CG3_AT_66HZ;
+		} else {
+			printk(KERN_ERR "cgthree: can't handle SR %02x\n",
+			       status);
+			return -EINVAL;
+		}
+	}
+
+	for (p = cg3_regvals[type]; *p; p += 2) {
+		u8 __iomem *regp = &((u8 __iomem *)par->regs)[p[0]];
+		sbus_writeb(p[1], regp);
+	}
+	for (p = cg3_dacvals; *p; p += 2) {
+		u8 __iomem *regp;
+
+		regp = (u8 __iomem *)&par->regs->cmap.addr;
+		sbus_writeb(p[0], regp);
+		regp = (u8 __iomem *)&par->regs->cmap.control;
+		sbus_writeb(p[1], regp);
+	}
+	return 0;
+}
+
+static int cg3_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct cg3_par *par;
+	int linebytes, err;
+
+	info = framebuffer_alloc(sizeof(struct cg3_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+
+	info->fix.smem_start = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+	sbusfb_fill_var(&info->var, dp, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
+	if (!strcmp(dp->name, "cgRDI"))
+		par->flags |= CG3_FLAG_RDI;
+	if (par->flags & CG3_FLAG_RDI)
+		cg3_rdi_maybe_fixup_var(&info->var, dp);
+
+	linebytes = of_getintprop_default(dp, "linebytes",
+					  info->var.xres);
+	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
+
+	par->regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
+			       sizeof(struct cg3_regs), "cg3 regs");
+	if (!par->regs)
+		goto out_release_fb;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &cg3_ops;
+	info->screen_base = of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
+				       info->fix.smem_len, "cg3 ram");
+	if (!info->screen_base)
+		goto out_unmap_regs;
+
+	cg3_blank(FB_BLANK_UNBLANK, info);
+
+	if (!of_find_property(dp, "width", NULL)) {
+		err = cg3_do_default_mode(par);
+		if (err)
+			goto out_unmap_screen;
+	}
+
+	err = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (err)
+		goto out_unmap_screen;
+
+	fb_set_cmap(&info->cmap, info);
+
+	cg3_init_fix(info, linebytes, dp);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: cg3 at %lx:%lx\n",
+	       dp->full_name, par->which_io, info->fix.smem_start);
+
+	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_screen:
+	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
+
+out_unmap_regs:
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
+
+out_release_fb:
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int cg3_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct cg3_par *par = info->par;
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
+	of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id cg3_match[] = {
+	{
+		.name = "cgthree",
+	},
+	{
+		.name = "cgRDI",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, cg3_match);
+
+static struct platform_driver cg3_driver = {
+	.driver = {
+		.name = "cg3",
+		.owner = THIS_MODULE,
+		.of_match_table = cg3_match,
+	},
+	.probe		= cg3_probe,
+	.remove		= cg3_remove,
+};
+
+static int __init cg3_init(void)
+{
+	if (fb_get_options("cg3fb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&cg3_driver);
+}
+
+static void __exit cg3_exit(void)
+{
+	platform_driver_unregister(&cg3_driver);
+}
+
+module_init(cg3_init);
+module_exit(cg3_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for CGthree chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/cg6.c b/drivers/video/fbdev/cg6.c
new file mode 100644
index 000000000000..70781fea092a
--- /dev/null
+++ b/drivers/video/fbdev/cg6.c
@@ -0,0 +1,885 @@
+/* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int cg6_blank(int, struct fb_info *);
+
+static void cg6_imageblit(struct fb_info *, const struct fb_image *);
+static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
+static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+static int cg6_sync(struct fb_info *);
+static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
+static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops cg6_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= cg6_setcolreg,
+	.fb_blank		= cg6_blank,
+	.fb_pan_display		= cg6_pan_display,
+	.fb_fillrect		= cg6_fillrect,
+	.fb_copyarea		= cg6_copyarea,
+	.fb_imageblit		= cg6_imageblit,
+	.fb_sync		= cg6_sync,
+	.fb_mmap		= cg6_mmap,
+	.fb_ioctl		= cg6_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+/* Offset of interesting structures in the OBIO space */
+/*
+ * Brooktree is the video dac and is funny to program on the cg6.
+ * (it's even funnier on the cg3)
+ * The FBC could be the frame buffer control
+ * The FHC could is the frame buffer hardware control.
+ */
+#define CG6_ROM_OFFSET			0x0UL
+#define CG6_BROOKTREE_OFFSET		0x200000UL
+#define CG6_DHC_OFFSET			0x240000UL
+#define CG6_ALT_OFFSET			0x280000UL
+#define CG6_FHC_OFFSET			0x300000UL
+#define CG6_THC_OFFSET			0x301000UL
+#define CG6_FBC_OFFSET			0x700000UL
+#define CG6_TEC_OFFSET			0x701000UL
+#define CG6_RAM_OFFSET			0x800000UL
+
+/* FHC definitions */
+#define CG6_FHC_FBID_SHIFT		24
+#define CG6_FHC_FBID_MASK		255
+#define CG6_FHC_REV_SHIFT		20
+#define CG6_FHC_REV_MASK		15
+#define CG6_FHC_FROP_DISABLE		(1 << 19)
+#define CG6_FHC_ROW_DISABLE		(1 << 18)
+#define CG6_FHC_SRC_DISABLE		(1 << 17)
+#define CG6_FHC_DST_DISABLE		(1 << 16)
+#define CG6_FHC_RESET			(1 << 15)
+#define CG6_FHC_LITTLE_ENDIAN		(1 << 13)
+#define CG6_FHC_RES_MASK		(3 << 11)
+#define CG6_FHC_1024			(0 << 11)
+#define CG6_FHC_1152			(1 << 11)
+#define CG6_FHC_1280			(2 << 11)
+#define CG6_FHC_1600			(3 << 11)
+#define CG6_FHC_CPU_MASK		(3 << 9)
+#define CG6_FHC_CPU_SPARC		(0 << 9)
+#define CG6_FHC_CPU_68020		(1 << 9)
+#define CG6_FHC_CPU_386			(2 << 9)
+#define CG6_FHC_TEST			(1 << 8)
+#define CG6_FHC_TEST_X_SHIFT		4
+#define CG6_FHC_TEST_X_MASK		15
+#define CG6_FHC_TEST_Y_SHIFT		0
+#define CG6_FHC_TEST_Y_MASK		15
+
+/* FBC mode definitions */
+#define CG6_FBC_BLIT_IGNORE		0x00000000
+#define CG6_FBC_BLIT_NOSRC		0x00100000
+#define CG6_FBC_BLIT_SRC		0x00200000
+#define CG6_FBC_BLIT_ILLEGAL		0x00300000
+#define CG6_FBC_BLIT_MASK		0x00300000
+
+#define CG6_FBC_VBLANK			0x00080000
+
+#define CG6_FBC_MODE_IGNORE		0x00000000
+#define CG6_FBC_MODE_COLOR8		0x00020000
+#define CG6_FBC_MODE_COLOR1		0x00040000
+#define CG6_FBC_MODE_HRMONO		0x00060000
+#define CG6_FBC_MODE_MASK		0x00060000
+
+#define CG6_FBC_DRAW_IGNORE		0x00000000
+#define CG6_FBC_DRAW_RENDER		0x00008000
+#define CG6_FBC_DRAW_PICK		0x00010000
+#define CG6_FBC_DRAW_ILLEGAL		0x00018000
+#define CG6_FBC_DRAW_MASK		0x00018000
+
+#define CG6_FBC_BWRITE0_IGNORE		0x00000000
+#define CG6_FBC_BWRITE0_ENABLE		0x00002000
+#define CG6_FBC_BWRITE0_DISABLE		0x00004000
+#define CG6_FBC_BWRITE0_ILLEGAL		0x00006000
+#define CG6_FBC_BWRITE0_MASK		0x00006000
+
+#define CG6_FBC_BWRITE1_IGNORE		0x00000000
+#define CG6_FBC_BWRITE1_ENABLE		0x00000800
+#define CG6_FBC_BWRITE1_DISABLE		0x00001000
+#define CG6_FBC_BWRITE1_ILLEGAL		0x00001800
+#define CG6_FBC_BWRITE1_MASK		0x00001800
+
+#define CG6_FBC_BREAD_IGNORE		0x00000000
+#define CG6_FBC_BREAD_0			0x00000200
+#define CG6_FBC_BREAD_1			0x00000400
+#define CG6_FBC_BREAD_ILLEGAL		0x00000600
+#define CG6_FBC_BREAD_MASK		0x00000600
+
+#define CG6_FBC_BDISP_IGNORE		0x00000000
+#define CG6_FBC_BDISP_0			0x00000080
+#define CG6_FBC_BDISP_1			0x00000100
+#define CG6_FBC_BDISP_ILLEGAL		0x00000180
+#define CG6_FBC_BDISP_MASK		0x00000180
+
+#define CG6_FBC_INDEX_MOD		0x00000040
+#define CG6_FBC_INDEX_MASK		0x00000030
+
+/* THC definitions */
+#define CG6_THC_MISC_REV_SHIFT		16
+#define CG6_THC_MISC_REV_MASK		15
+#define CG6_THC_MISC_RESET		(1 << 12)
+#define CG6_THC_MISC_VIDEO		(1 << 10)
+#define CG6_THC_MISC_SYNC		(1 << 9)
+#define CG6_THC_MISC_VSYNC		(1 << 8)
+#define CG6_THC_MISC_SYNC_ENAB		(1 << 7)
+#define CG6_THC_MISC_CURS_RES		(1 << 6)
+#define CG6_THC_MISC_INT_ENAB		(1 << 5)
+#define CG6_THC_MISC_INT		(1 << 4)
+#define CG6_THC_MISC_INIT		0x9f
+#define CG6_THC_CURSOFF			((65536-32) | ((65536-32) << 16))
+
+/* The contents are unknown */
+struct cg6_tec {
+	int tec_matrix;
+	int tec_clip;
+	int tec_vdc;
+};
+
+struct cg6_thc {
+	u32	thc_pad0[512];
+	u32	thc_hs;		/* hsync timing */
+	u32	thc_hsdvs;
+	u32	thc_hd;
+	u32	thc_vs;		/* vsync timing */
+	u32	thc_vd;
+	u32	thc_refresh;
+	u32	thc_misc;
+	u32	thc_pad1[56];
+	u32	thc_cursxy;	/* cursor x,y position (16 bits each) */
+	u32	thc_cursmask[32];	/* cursor mask bits */
+	u32	thc_cursbits[32];	/* what to show where mask enabled */
+};
+
+struct cg6_fbc {
+	u32	xxx0[1];
+	u32	mode;
+	u32	clip;
+	u32	xxx1[1];
+	u32	s;
+	u32	draw;
+	u32	blit;
+	u32	font;
+	u32	xxx2[24];
+	u32	x0, y0, z0, color0;
+	u32	x1, y1, z1, color1;
+	u32	x2, y2, z2, color2;
+	u32	x3, y3, z3, color3;
+	u32	offx, offy;
+	u32	xxx3[2];
+	u32	incx, incy;
+	u32	xxx4[2];
+	u32	clipminx, clipminy;
+	u32	xxx5[2];
+	u32	clipmaxx, clipmaxy;
+	u32	xxx6[2];
+	u32	fg;
+	u32	bg;
+	u32	alu;
+	u32	pm;
+	u32	pixelm;
+	u32	xxx7[2];
+	u32	patalign;
+	u32	pattern[8];
+	u32	xxx8[432];
+	u32	apointx, apointy, apointz;
+	u32	xxx9[1];
+	u32	rpointx, rpointy, rpointz;
+	u32	xxx10[5];
+	u32	pointr, pointg, pointb, pointa;
+	u32	alinex, aliney, alinez;
+	u32	xxx11[1];
+	u32	rlinex, rliney, rlinez;
+	u32	xxx12[5];
+	u32	liner, lineg, lineb, linea;
+	u32	atrix, atriy, atriz;
+	u32	xxx13[1];
+	u32	rtrix, rtriy, rtriz;
+	u32	xxx14[5];
+	u32	trir, trig, trib, tria;
+	u32	aquadx, aquady, aquadz;
+	u32	xxx15[1];
+	u32	rquadx, rquady, rquadz;
+	u32	xxx16[5];
+	u32	quadr, quadg, quadb, quada;
+	u32	arectx, arecty, arectz;
+	u32	xxx17[1];
+	u32	rrectx, rrecty, rrectz;
+	u32	xxx18[5];
+	u32	rectr, rectg, rectb, recta;
+};
+
+struct bt_regs {
+	u32	addr;
+	u32	color_map;
+	u32	control;
+	u32	cursor;
+};
+
+struct cg6_par {
+	spinlock_t		lock;
+	struct bt_regs		__iomem *bt;
+	struct cg6_fbc		__iomem *fbc;
+	struct cg6_thc		__iomem *thc;
+	struct cg6_tec		__iomem *tec;
+	u32			__iomem *fhc;
+
+	u32			flags;
+#define CG6_FLAG_BLANKED	0x00000001
+
+	unsigned long		which_io;
+};
+
+static int cg6_sync(struct fb_info *info)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	struct cg6_fbc __iomem *fbc = par->fbc;
+	int limit = 10000;
+
+	do {
+		if (!(sbus_readl(&fbc->s) & 0x10000000))
+			break;
+		udelay(10);
+	} while (--limit > 0);
+
+	return 0;
+}
+
+static void cg6_switch_from_graph(struct cg6_par *par)
+{
+	struct cg6_thc __iomem *thc = par->thc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	/* Hide the cursor. */
+	sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+
+	/* We just use this to catch switches out of
+	 * graphics mode.
+	 */
+	cg6_switch_from_graph(par);
+
+	if (var->xoffset || var->yoffset || var->vmode)
+		return -EINVAL;
+	return 0;
+}
+
+/**
+ *	cg6_fillrect -	Draws a rectangle on the screen.
+ *
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@rect: structure defining the rectagle and operation.
+ */
+static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	struct cg6_fbc __iomem *fbc = par->fbc;
+	unsigned long flags;
+	s32 val;
+
+	/* CG6 doesn't handle ROP_XOR */
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	cg6_sync(info);
+
+	sbus_writel(rect->color, &fbc->fg);
+	sbus_writel(~(u32)0, &fbc->pixelm);
+	sbus_writel(0xea80ff00, &fbc->alu);
+	sbus_writel(0, &fbc->s);
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(~(u32)0, &fbc->pm);
+	sbus_writel(rect->dy, &fbc->arecty);
+	sbus_writel(rect->dx, &fbc->arectx);
+	sbus_writel(rect->dy + rect->height, &fbc->arecty);
+	sbus_writel(rect->dx + rect->width, &fbc->arectx);
+	do {
+		val = sbus_readl(&fbc->draw);
+	} while (val < 0 && (val & 0x20000000));
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *	cg6_copyarea - Copies one area of the screen to another area.
+ *
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@area: Structure providing the data to copy the framebuffer contents
+ *		from one region to another.
+ *
+ *	This drawing operation copies a rectangular area from one area of the
+ *	screen to another area.
+ */
+static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	struct cg6_fbc __iomem *fbc = par->fbc;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	cg6_sync(info);
+
+	sbus_writel(0xff, &fbc->fg);
+	sbus_writel(0x00, &fbc->bg);
+	sbus_writel(~0, &fbc->pixelm);
+	sbus_writel(0xe880cccc, &fbc->alu);
+	sbus_writel(0, &fbc->s);
+	sbus_writel(0, &fbc->clip);
+
+	sbus_writel(area->sy, &fbc->y0);
+	sbus_writel(area->sx, &fbc->x0);
+	sbus_writel(area->sy + area->height - 1, &fbc->y1);
+	sbus_writel(area->sx + area->width - 1, &fbc->x1);
+	sbus_writel(area->dy, &fbc->y2);
+	sbus_writel(area->dx, &fbc->x2);
+	sbus_writel(area->dy + area->height - 1, &fbc->y3);
+	sbus_writel(area->dx + area->width - 1, &fbc->x3);
+	do {
+		i = sbus_readl(&fbc->blit);
+	} while (i < 0 && (i & 0x20000000));
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *	cg6_imageblit -	Copies a image from system memory to the screen.
+ *
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@image: structure defining the image.
+ */
+static void cg6_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	struct cg6_fbc __iomem *fbc = par->fbc;
+	const u8 *data = image->data;
+	unsigned long flags;
+	u32 x, y;
+	int i, width;
+
+	if (image->depth > 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	cg6_sync(info);
+
+	sbus_writel(image->fg_color, &fbc->fg);
+	sbus_writel(image->bg_color, &fbc->bg);
+	sbus_writel(0x140000, &fbc->mode);
+	sbus_writel(0xe880fc30, &fbc->alu);
+	sbus_writel(~(u32)0, &fbc->pixelm);
+	sbus_writel(0, &fbc->s);
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(0xff, &fbc->pm);
+	sbus_writel(32, &fbc->incx);
+	sbus_writel(0, &fbc->incy);
+
+	x = image->dx;
+	y = image->dy;
+	for (i = 0; i < image->height; i++) {
+		width = image->width;
+
+		while (width >= 32) {
+			u32 val;
+
+			sbus_writel(y, &fbc->y0);
+			sbus_writel(x, &fbc->x0);
+			sbus_writel(x + 32 - 1, &fbc->x1);
+
+			val = ((u32)data[0] << 24) |
+			      ((u32)data[1] << 16) |
+			      ((u32)data[2] <<  8) |
+			      ((u32)data[3] <<  0);
+			sbus_writel(val, &fbc->font);
+
+			data += 4;
+			x += 32;
+			width -= 32;
+		}
+		if (width) {
+			u32 val;
+
+			sbus_writel(y, &fbc->y0);
+			sbus_writel(x, &fbc->x0);
+			sbus_writel(x + width - 1, &fbc->x1);
+			if (width <= 8) {
+				val = (u32) data[0] << 24;
+				data += 1;
+			} else if (width <= 16) {
+				val = ((u32) data[0] << 24) |
+				      ((u32) data[1] << 16);
+				data += 2;
+			} else {
+				val = ((u32) data[0] << 24) |
+				      ((u32) data[1] << 16) |
+				      ((u32) data[2] <<  8);
+				data += 3;
+			}
+			sbus_writel(val, &fbc->font);
+		}
+
+		y += 1;
+		x = image->dx;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *	cg6_setcolreg - Sets a color register.
+ *
+ *	@regno: boolean, 0 copy local, 1 get_user() function
+ *	@red: frame buffer colormap structure
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *	@info: frame buffer info structure
+ */
+static int cg6_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	struct bt_regs __iomem *bt = par->bt;
+	unsigned long flags;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	sbus_writel((u32)regno << 24, &bt->addr);
+	sbus_writel((u32)red << 24, &bt->color_map);
+	sbus_writel((u32)green << 24, &bt->color_map);
+	sbus_writel((u32)blue << 24, &bt->color_map);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *	cg6_blank - Blanks the display.
+ *
+ *	@blank_mode: the blank mode we want.
+ *	@info: frame buffer structure that represents a single frame buffer
+ */
+static int cg6_blank(int blank, struct fb_info *info)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	struct cg6_thc __iomem *thc = par->thc;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+	val = sbus_readl(&thc->thc_misc);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		val |= CG6_THC_MISC_VIDEO;
+		par->flags &= ~CG6_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		val &= ~CG6_THC_MISC_VIDEO;
+		par->flags |= CG6_FLAG_BLANKED;
+		break;
+	}
+
+	sbus_writel(val, &thc->thc_misc);
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map cg6_mmap_map[] = {
+	{
+		.voff	= CG6_FBC,
+		.poff	= CG6_FBC_OFFSET,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= CG6_TEC,
+		.poff	= CG6_TEC_OFFSET,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= CG6_BTREGS,
+		.poff	= CG6_BROOKTREE_OFFSET,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= CG6_FHC,
+		.poff	= CG6_FHC_OFFSET,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= CG6_THC,
+		.poff	= CG6_THC_OFFSET,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= CG6_ROM,
+		.poff	= CG6_ROM_OFFSET,
+		.size	= 0x10000
+	},
+	{
+		.voff	= CG6_RAM,
+		.poff	= CG6_RAM_OFFSET,
+		.size	= SBUS_MMAP_FBSIZE(1)
+	},
+	{
+		.voff	= CG6_DHC,
+		.poff	= CG6_DHC_OFFSET,
+		.size	= 0x40000
+	},
+	{ .size	= 0 }
+};
+
+static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+
+	return sbusfb_mmap_helper(cg6_mmap_map,
+				  info->fix.smem_start, info->fix.smem_len,
+				  par->which_io, vma);
+}
+
+static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUNFAST_COLOR, 8, info->fix.smem_len);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void cg6_init_fix(struct fb_info *info, int linebytes)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	const char *cg6_cpu_name, *cg6_card_name;
+	u32 conf;
+
+	conf = sbus_readl(par->fhc);
+	switch (conf & CG6_FHC_CPU_MASK) {
+	case CG6_FHC_CPU_SPARC:
+		cg6_cpu_name = "sparc";
+		break;
+	case CG6_FHC_CPU_68020:
+		cg6_cpu_name = "68020";
+		break;
+	default:
+		cg6_cpu_name = "i386";
+		break;
+	}
+	if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
+		if (info->fix.smem_len <= 0x100000)
+			cg6_card_name = "TGX";
+		else
+			cg6_card_name = "TGX+";
+	} else {
+		if (info->fix.smem_len <= 0x100000)
+			cg6_card_name = "GX";
+		else
+			cg6_card_name = "GX+";
+	}
+
+	sprintf(info->fix.id, "%s %s", cg6_card_name, cg6_cpu_name);
+	info->fix.id[sizeof(info->fix.id) - 1] = 0;
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = linebytes;
+
+	info->fix.accel = FB_ACCEL_SUN_CGSIX;
+}
+
+/* Initialize Brooktree DAC */
+static void cg6_bt_init(struct cg6_par *par)
+{
+	struct bt_regs __iomem *bt = par->bt;
+
+	sbus_writel(0x04 << 24, &bt->addr);	 /* color planes */
+	sbus_writel(0xff << 24, &bt->control);
+	sbus_writel(0x05 << 24, &bt->addr);
+	sbus_writel(0x00 << 24, &bt->control);
+	sbus_writel(0x06 << 24, &bt->addr);	 /* overlay plane */
+	sbus_writel(0x73 << 24, &bt->control);
+	sbus_writel(0x07 << 24, &bt->addr);
+	sbus_writel(0x00 << 24, &bt->control);
+}
+
+static void cg6_chip_init(struct fb_info *info)
+{
+	struct cg6_par *par = (struct cg6_par *)info->par;
+	struct cg6_tec __iomem *tec = par->tec;
+	struct cg6_fbc __iomem *fbc = par->fbc;
+	struct cg6_thc __iomem *thc = par->thc;
+	u32 rev, conf, mode;
+	int i;
+
+	/* Hide the cursor. */
+	sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
+
+	/* Turn off stuff in the Transform Engine. */
+	sbus_writel(0, &tec->tec_matrix);
+	sbus_writel(0, &tec->tec_clip);
+	sbus_writel(0, &tec->tec_vdc);
+
+	/* Take care of bugs in old revisions. */
+	rev = (sbus_readl(par->fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
+	if (rev < 5) {
+		conf = (sbus_readl(par->fhc) & CG6_FHC_RES_MASK) |
+			CG6_FHC_CPU_68020 | CG6_FHC_TEST |
+			(11 << CG6_FHC_TEST_X_SHIFT) |
+			(11 << CG6_FHC_TEST_Y_SHIFT);
+		if (rev < 2)
+			conf |= CG6_FHC_DST_DISABLE;
+		sbus_writel(conf, par->fhc);
+	}
+
+	/* Set things in the FBC. Bad things appear to happen if we do
+	 * back to back store/loads on the mode register, so copy it
+	 * out instead. */
+	mode = sbus_readl(&fbc->mode);
+	do {
+		i = sbus_readl(&fbc->s);
+	} while (i & 0x10000000);
+	mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
+		  CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
+		  CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
+		  CG6_FBC_BDISP_MASK);
+	mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
+		 CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
+		 CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
+		 CG6_FBC_BDISP_0);
+	sbus_writel(mode, &fbc->mode);
+
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(0, &fbc->offx);
+	sbus_writel(0, &fbc->offy);
+	sbus_writel(0, &fbc->clipminx);
+	sbus_writel(0, &fbc->clipminy);
+	sbus_writel(info->var.xres - 1, &fbc->clipmaxx);
+	sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
+}
+
+static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
+			   struct cg6_par *par)
+{
+	if (par->fbc)
+		of_iounmap(&op->resource[0], par->fbc, 4096);
+	if (par->tec)
+		of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec));
+	if (par->thc)
+		of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc));
+	if (par->bt)
+		of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs));
+	if (par->fhc)
+		of_iounmap(&op->resource[0], par->fhc, sizeof(u32));
+
+	if (info->screen_base)
+		of_iounmap(&op->resource[0], info->screen_base,
+			   info->fix.smem_len);
+}
+
+static int cg6_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct cg6_par *par;
+	int linebytes, err;
+	int dblbuf;
+
+	info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+
+	info->fix.smem_start = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+	sbusfb_fill_var(&info->var, dp, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
+
+	linebytes = of_getintprop_default(dp, "linebytes",
+					  info->var.xres);
+	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
+
+	dblbuf = of_getintprop_default(dp, "dblbuf", 0);
+	if (dblbuf)
+		info->fix.smem_len *= 4;
+
+	par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
+				4096, "cgsix fbc");
+	par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
+				sizeof(struct cg6_tec), "cgsix tec");
+	par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
+				sizeof(struct cg6_thc), "cgsix thc");
+	par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
+				sizeof(struct bt_regs), "cgsix dac");
+	par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
+				sizeof(u32), "cgsix fhc");
+
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
+			FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+			FBINFO_READS_FAST;
+	info->fbops = &cg6_ops;
+
+	info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
+					info->fix.smem_len, "cgsix ram");
+	if (!par->fbc || !par->tec || !par->thc ||
+	    !par->bt || !par->fhc || !info->screen_base)
+		goto out_unmap_regs;
+
+	info->var.accel_flags = FB_ACCELF_TEXT;
+
+	cg6_bt_init(par);
+	cg6_chip_init(info);
+	cg6_blank(FB_BLANK_UNBLANK, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
+
+	fb_set_cmap(&info->cmap, info);
+	cg6_init_fix(info, linebytes);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: CGsix [%s] at %lx:%lx\n",
+	       dp->full_name, info->fix.id,
+	       par->which_io, info->fix.smem_start);
+
+	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	cg6_unmap_regs(op, info, par);
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int cg6_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct cg6_par *par = info->par;
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	cg6_unmap_regs(op, info, par);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id cg6_match[] = {
+	{
+		.name = "cgsix",
+	},
+	{
+		.name = "cgthree+",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, cg6_match);
+
+static struct platform_driver cg6_driver = {
+	.driver = {
+		.name = "cg6",
+		.owner = THIS_MODULE,
+		.of_match_table = cg6_match,
+	},
+	.probe		= cg6_probe,
+	.remove		= cg6_remove,
+};
+
+static int __init cg6_init(void)
+{
+	if (fb_get_options("cg6fb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&cg6_driver);
+}
+
+static void __exit cg6_exit(void)
+{
+	platform_driver_unregister(&cg6_driver);
+}
+
+module_init(cg6_init);
+module_exit(cg6_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c
new file mode 100644
index 000000000000..206a66b61072
--- /dev/null
+++ b/drivers/video/fbdev/chipsfb.c
@@ -0,0 +1,519 @@
+/*
+ *  drivers/video/chipsfb.c -- frame buffer device for
+ *  Chips & Technologies 65550 chip.
+ *
+ *  Copyright (C) 1998-2002 Paul Mackerras
+ *
+ *  This file is derived from the Powermac "chips" driver:
+ *  Copyright (C) 1997 Fabio Riccardi.
+ *  And from the frame buffer device for Open Firmware-initialized devices:
+ *  Copyright (C) 1997 Geert Uytterhoeven.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+/*
+ * Since we access the display with inb/outb to fixed port numbers,
+ * we can only handle one 6555x chip.  -- paulus
+ */
+#define write_ind(num, val, ap, dp)	do { \
+	outb((num), (ap)); outb((val), (dp)); \
+} while (0)
+#define read_ind(num, var, ap, dp)	do { \
+	outb((num), (ap)); var = inb((dp)); \
+} while (0)
+
+/* extension registers */
+#define write_xr(num, val)	write_ind(num, val, 0x3d6, 0x3d7)
+#define read_xr(num, var)	read_ind(num, var, 0x3d6, 0x3d7)
+/* flat panel registers */
+#define write_fr(num, val)	write_ind(num, val, 0x3d0, 0x3d1)
+#define read_fr(num, var)	read_ind(num, var, 0x3d0, 0x3d1)
+/* CRTC registers */
+#define write_cr(num, val)	write_ind(num, val, 0x3d4, 0x3d5)
+#define read_cr(num, var)	read_ind(num, var, 0x3d4, 0x3d5)
+/* graphics registers */
+#define write_gr(num, val)	write_ind(num, val, 0x3ce, 0x3cf)
+#define read_gr(num, var)	read_ind(num, var, 0x3ce, 0x3cf)
+/* sequencer registers */
+#define write_sr(num, val)	write_ind(num, val, 0x3c4, 0x3c5)
+#define read_sr(num, var)	read_ind(num, var, 0x3c4, 0x3c5)
+/* attribute registers - slightly strange */
+#define write_ar(num, val)	do { \
+	inb(0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
+} while (0)
+#define read_ar(num, var)	do { \
+	inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
+} while (0)
+
+/*
+ * Exported functions
+ */
+int chips_init(void);
+
+static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
+static int chipsfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static int chipsfb_set_par(struct fb_info *info);
+static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info);
+static int chipsfb_blank(int blank, struct fb_info *info);
+
+static struct fb_ops chipsfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= chipsfb_check_var,
+	.fb_set_par	= chipsfb_set_par,
+	.fb_setcolreg	= chipsfb_setcolreg,
+	.fb_blank	= chipsfb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int chipsfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	if (var->xres > 800 || var->yres > 600
+	    || var->xres_virtual > 800 || var->yres_virtual > 600
+	    || (var->bits_per_pixel != 8 && var->bits_per_pixel != 16)
+	    || var->nonstd
+	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	var->xres = var->xres_virtual = 800;
+	var->yres = var->yres_virtual = 600;
+
+	return 0;
+}
+
+static int chipsfb_set_par(struct fb_info *info)
+{
+	if (info->var.bits_per_pixel == 16) {
+		write_cr(0x13, 200);		// Set line length (doublewords)
+		write_xr(0x81, 0x14);		// 15 bit (555) color mode
+		write_xr(0x82, 0x00);		// Disable palettes
+		write_xr(0x20, 0x10);		// 16 bit blitter mode
+
+		info->fix.line_length = 800*2;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+		info->var.red.offset = 10;
+		info->var.green.offset = 5;
+		info->var.blue.offset = 0;
+		info->var.red.length = info->var.green.length =
+			info->var.blue.length = 5;
+		
+	} else {
+		/* p->var.bits_per_pixel == 8 */
+		write_cr(0x13, 100);		// Set line length (doublewords)
+		write_xr(0x81, 0x12);		// 8 bit color mode
+		write_xr(0x82, 0x08);		// Graphics gamma enable
+		write_xr(0x20, 0x00);		// 8 bit blitter mode
+
+		info->fix.line_length = 800;
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;		
+
+ 		info->var.red.offset = info->var.green.offset =
+			info->var.blue.offset = 0;
+		info->var.red.length = info->var.green.length =
+			info->var.blue.length = 8;
+		
+	}
+	return 0;
+}
+
+static int chipsfb_blank(int blank, struct fb_info *info)
+{
+	return 1;	/* get fb_blank to set the colormap to all black */
+}
+
+static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info)
+{
+	if (regno > 255)
+		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	outb(regno, 0x3c8);
+	udelay(1);
+	outb(red, 0x3c9);
+	outb(green, 0x3c9);
+	outb(blue, 0x3c9);
+
+	return 0;
+}
+
+struct chips_init_reg {
+	unsigned char addr;
+	unsigned char data;
+};
+
+static struct chips_init_reg chips_init_sr[] = {
+	{ 0x00, 0x03 },
+	{ 0x01, 0x01 },
+	{ 0x02, 0x0f },
+	{ 0x04, 0x0e }
+};
+
+static struct chips_init_reg chips_init_gr[] = {
+	{ 0x05, 0x00 },
+	{ 0x06, 0x0d },
+	{ 0x08, 0xff }
+};
+
+static struct chips_init_reg chips_init_ar[] = {
+	{ 0x10, 0x01 },
+	{ 0x12, 0x0f },
+	{ 0x13, 0x00 }
+};
+
+static struct chips_init_reg chips_init_cr[] = {
+	{ 0x00, 0x7f },
+	{ 0x01, 0x63 },
+	{ 0x02, 0x63 },
+	{ 0x03, 0x83 },
+	{ 0x04, 0x66 },
+	{ 0x05, 0x10 },
+	{ 0x06, 0x72 },
+	{ 0x07, 0x3e },
+	{ 0x08, 0x00 },
+	{ 0x09, 0x40 },
+	{ 0x0c, 0x00 },
+	{ 0x0d, 0x00 },
+	{ 0x10, 0x59 },
+	{ 0x11, 0x0d },
+	{ 0x12, 0x57 },
+	{ 0x13, 0x64 },
+	{ 0x14, 0x00 },
+	{ 0x15, 0x57 },
+	{ 0x16, 0x73 },
+	{ 0x17, 0xe3 },
+	{ 0x18, 0xff },
+	{ 0x30, 0x02 },
+	{ 0x31, 0x02 },
+	{ 0x32, 0x02 },
+	{ 0x33, 0x02 },
+	{ 0x40, 0x00 },
+	{ 0x41, 0x00 },
+	{ 0x40, 0x80 }
+};
+
+static struct chips_init_reg chips_init_fr[] = {
+	{ 0x01, 0x02 },
+	{ 0x03, 0x08 },
+	{ 0x04, 0x81 },
+	{ 0x05, 0x21 },
+	{ 0x08, 0x0c },
+	{ 0x0a, 0x74 },
+	{ 0x0b, 0x11 },
+	{ 0x10, 0x0c },
+	{ 0x11, 0xe0 },
+	/* { 0x12, 0x40 }, -- 3400 needs 40, 2400 needs 48, no way to tell */
+	{ 0x20, 0x63 },
+	{ 0x21, 0x68 },
+	{ 0x22, 0x19 },
+	{ 0x23, 0x7f },
+	{ 0x24, 0x68 },
+	{ 0x26, 0x00 },
+	{ 0x27, 0x0f },
+	{ 0x30, 0x57 },
+	{ 0x31, 0x58 },
+	{ 0x32, 0x0d },
+	{ 0x33, 0x72 },
+	{ 0x34, 0x02 },
+	{ 0x35, 0x22 },
+	{ 0x36, 0x02 },
+	{ 0x37, 0x00 }
+};
+
+static struct chips_init_reg chips_init_xr[] = {
+	{ 0xce, 0x00 },		/* set default memory clock */
+	{ 0xcc, 0x43 },		/* memory clock ratio */
+	{ 0xcd, 0x18 },
+	{ 0xce, 0xa1 },
+	{ 0xc8, 0x84 },
+	{ 0xc9, 0x0a },
+	{ 0xca, 0x00 },
+	{ 0xcb, 0x20 },
+	{ 0xcf, 0x06 },
+	{ 0xd0, 0x0e },
+	{ 0x09, 0x01 },
+	{ 0x0a, 0x02 },
+	{ 0x0b, 0x01 },
+	{ 0x20, 0x00 },
+	{ 0x40, 0x03 },
+	{ 0x41, 0x01 },
+	{ 0x42, 0x00 },
+	{ 0x80, 0x82 },
+	{ 0x81, 0x12 },
+	{ 0x82, 0x08 },
+	{ 0xa0, 0x00 },
+	{ 0xa8, 0x00 }
+};
+
+static void __init chips_hw_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
+		write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
+	outb(0x29, 0x3c2); /* set misc output reg */
+	for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
+		write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
+	for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
+		write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
+	for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
+		write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
+	for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
+		write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
+	for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
+		write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
+}
+
+static struct fb_fix_screeninfo chipsfb_fix = {
+	.id =		"C&T 65550",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.accel =	FB_ACCEL_NONE,
+	.line_length =	800,
+
+// FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
+// * "3500" PowerBook G3 (the original PB G3) has 2MB.
+// * 2400 has 1MB composed of 2 Mitsubishi M5M4V4265CTP DRAM chips.
+//   Motherboard actually supports 2MB -- there are two blank locations
+//   for a second pair of DRAMs.  (Thanks, Apple!)
+// * 3400 has 1MB (I think).  Don't know if it's expandable.
+// -- Tim Seufert
+	.smem_len =	0x100000,	/* 1MB */
+};
+
+static struct fb_var_screeninfo chipsfb_var = {
+	.xres = 800,
+	.yres = 600,
+	.xres_virtual = 800,
+	.yres_virtual = 600,
+	.bits_per_pixel = 8,
+	.red = { .length = 8 },
+	.green = { .length = 8 },
+	.blue = { .length = 8 },
+	.height = -1,
+	.width = -1,
+	.vmode = FB_VMODE_NONINTERLACED,
+	.pixclock = 10000,
+	.left_margin = 16,
+	.right_margin = 16,
+	.upper_margin = 16,
+	.lower_margin = 16,
+	.hsync_len = 8,
+	.vsync_len = 8,
+};
+
+static void init_chips(struct fb_info *p, unsigned long addr)
+{
+	memset(p->screen_base, 0, 0x100000);
+
+	p->fix = chipsfb_fix;
+	p->fix.smem_start = addr;
+
+	p->var = chipsfb_var;
+
+	p->fbops = &chipsfb_ops;
+	p->flags = FBINFO_DEFAULT;
+
+	fb_alloc_cmap(&p->cmap, 256, 0);
+
+	chips_hw_init();
+}
+
+static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
+{
+	struct fb_info *p;
+	unsigned long addr, size;
+	unsigned short cmd;
+	int rc = -ENODEV;
+
+	if (pci_enable_device(dp) < 0) {
+		dev_err(&dp->dev, "Cannot enable PCI device\n");
+		goto err_out;
+	}
+
+	if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
+		goto err_disable;
+	addr = pci_resource_start(dp, 0);
+	size = pci_resource_len(dp, 0);
+	if (addr == 0)
+		goto err_disable;
+
+	p = framebuffer_alloc(0, &dp->dev);
+	if (p == NULL) {
+		dev_err(&dp->dev, "Cannot allocate framebuffer structure\n");
+		rc = -ENOMEM;
+		goto err_disable;
+	}
+
+	if (pci_request_region(dp, 0, "chipsfb") != 0) {
+		dev_err(&dp->dev, "Cannot request framebuffer\n");
+		rc = -EBUSY;
+		goto err_release_fb;
+	}
+
+#ifdef __BIG_ENDIAN
+	addr += 0x800000;	// Use big-endian aperture
+#endif
+
+	/* we should use pci_enable_device here, but,
+	   the device doesn't declare its I/O ports in its BARs
+	   so pci_enable_device won't turn on I/O responses */
+	pci_read_config_word(dp, PCI_COMMAND, &cmd);
+	cmd |= 3;	/* enable memory and IO space */
+	pci_write_config_word(dp, PCI_COMMAND, cmd);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* turn on the backlight */
+	mutex_lock(&pmac_backlight_mutex);
+	if (pmac_backlight) {
+		pmac_backlight->props.power = FB_BLANK_UNBLANK;
+		backlight_update_status(pmac_backlight);
+	}
+	mutex_unlock(&pmac_backlight_mutex);
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+#ifdef CONFIG_PPC
+	p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
+#else
+	p->screen_base = ioremap(addr, 0x200000);
+#endif
+	if (p->screen_base == NULL) {
+		dev_err(&dp->dev, "Cannot map framebuffer\n");
+		rc = -ENOMEM;
+		goto err_release_pci;
+	}
+
+	pci_set_drvdata(dp, p);
+
+	init_chips(p, addr);
+
+	if (register_framebuffer(p) < 0) {
+		dev_err(&dp->dev,"C&T 65550 framebuffer failed to register\n");
+		goto err_unmap;
+	}
+
+	dev_info(&dp->dev,"fb%d: Chips 65550 frame buffer"
+		 " (%dK RAM detected)\n",
+		 p->node, p->fix.smem_len / 1024);
+
+	return 0;
+
+ err_unmap:
+	iounmap(p->screen_base);
+ err_release_pci:
+	pci_release_region(dp, 0);
+ err_release_fb:
+	framebuffer_release(p);
+ err_disable:
+ err_out:
+	return rc;
+}
+
+static void chipsfb_remove(struct pci_dev *dp)
+{
+	struct fb_info *p = pci_get_drvdata(dp);
+
+	if (p->screen_base == NULL)
+		return;
+	unregister_framebuffer(p);
+	iounmap(p->screen_base);
+	p->screen_base = NULL;
+	pci_release_region(dp, 0);
+}
+
+#ifdef CONFIG_PM
+static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+        struct fb_info *p = pci_get_drvdata(pdev);
+
+	if (state.event == pdev->dev.power.power_state.event)
+		return 0;
+	if (!(state.event & PM_EVENT_SLEEP))
+		goto done;
+
+	console_lock();
+	chipsfb_blank(1, p);
+	fb_set_suspend(p, 1);
+	console_unlock();
+ done:
+	pdev->dev.power.power_state = state;
+	return 0;
+}
+
+static int chipsfb_pci_resume(struct pci_dev *pdev)
+{
+        struct fb_info *p = pci_get_drvdata(pdev);
+
+	console_lock();
+	fb_set_suspend(p, 0);
+	chipsfb_blank(0, p);
+	console_unlock();
+
+	pdev->dev.power.power_state = PMSG_ON;
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+
+static struct pci_device_id chipsfb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, chipsfb_pci_tbl);
+
+static struct pci_driver chipsfb_driver = {
+	.name =		"chipsfb",
+	.id_table =	chipsfb_pci_tbl,
+	.probe =	chipsfb_pci_init,
+	.remove =	chipsfb_remove,
+#ifdef CONFIG_PM
+	.suspend =	chipsfb_pci_suspend,
+	.resume =	chipsfb_pci_resume,
+#endif
+};
+
+int __init chips_init(void)
+{
+	if (fb_get_options("chipsfb", NULL))
+		return -ENODEV;
+
+	return pci_register_driver(&chipsfb_driver);
+}
+
+module_init(chips_init);
+
+static void __exit chipsfb_exit(void)
+{
+	pci_unregister_driver(&chipsfb_driver);
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c
new file mode 100644
index 000000000000..d992aa5eb3f0
--- /dev/null
+++ b/drivers/video/fbdev/cirrusfb.c
@@ -0,0 +1,2952 @@
+/*
+ * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
+ *
+ * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
+ *
+ * Contributors (thanks, all!)
+ *
+ *	David Eger:
+ *	Overhaul for Linux 2.6
+ *
+ *      Jeff Rugen:
+ *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
+ *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
+ *
+ *	Geert Uytterhoeven:
+ *	Excellent code review.
+ *
+ *	Lars Hecking:
+ *	Amiga updates and testing.
+ *
+ * Original cirrusfb author:  Frank Neumann
+ *
+ * Based on retz3fb.c and cirrusfb.c:
+ *      Copyright (C) 1997 Jes Sorensen
+ *      Copyright (C) 1996 Frank Neumann
+ *
+ ***************************************************************
+ *
+ * Format this code with GNU indent '-kr -i8 -pcs' options.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_ZORRO
+#include <linux/zorro.h>
+#endif
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+#ifdef CONFIG_AMIGA
+#include <asm/amigahw.h>
+#endif
+
+#include <video/vga.h>
+#include <video/cirrus.h>
+
+/*****************************************************************
+ *
+ * debugging and utility macros
+ *
+ */
+
+/* disable runtime assertions? */
+/* #define CIRRUSFB_NDEBUG */
+
+/* debugging assertions */
+#ifndef CIRRUSFB_NDEBUG
+#define assert(expr) \
+	if (!(expr)) { \
+		printk("Assertion failed! %s,%s,%s,line=%d\n", \
+		#expr, __FILE__, __func__, __LINE__); \
+	}
+#else
+#define assert(expr)
+#endif
+
+#define MB_ (1024 * 1024)
+
+/*****************************************************************
+ *
+ * chipset information
+ *
+ */
+
+/* board types */
+enum cirrus_board {
+	BT_NONE = 0,
+	BT_SD64,	/* GD5434 */
+	BT_PICCOLO,	/* GD5426 */
+	BT_PICASSO,	/* GD5426 or GD5428 */
+	BT_SPECTRUM,	/* GD5426 or GD5428 */
+	BT_PICASSO4,	/* GD5446 */
+	BT_ALPINE,	/* GD543x/4x */
+	BT_GD5480,
+	BT_LAGUNA,	/* GD5462/64 */
+	BT_LAGUNAB,	/* GD5465 */
+};
+
+/*
+ * per-board-type information, used for enumerating and abstracting
+ * chip-specific information
+ * NOTE: MUST be in the same order as enum cirrus_board in order to
+ * use direct indexing on this array
+ * NOTE: '__initdata' cannot be used as some of this info
+ * is required at runtime.  Maybe separate into an init-only and
+ * a run-time table?
+ */
+static const struct cirrusfb_board_info_rec {
+	char *name;		/* ASCII name of chipset */
+	long maxclock[5];		/* maximum video clock */
+	/* for  1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
+	bool init_sr07 : 1; /* init SR07 during init_vgachip() */
+	bool init_sr1f : 1; /* write SR1F during init_vgachip() */
+	/* construct bit 19 of screen start address */
+	bool scrn_start_bit19 : 1;
+
+	/* initial SR07 value, then for each mode */
+	unsigned char sr07;
+	unsigned char sr07_1bpp;
+	unsigned char sr07_1bpp_mux;
+	unsigned char sr07_8bpp;
+	unsigned char sr07_8bpp_mux;
+
+	unsigned char sr1f;	/* SR1F VGA initial register value */
+} cirrusfb_board_info[] = {
+	[BT_SD64] = {
+		.name			= "CL SD64",
+		.maxclock		= {
+			/* guess */
+			/* the SD64/P4 have a higher max. videoclock */
+			135100, 135100, 85500, 85500, 0
+		},
+		.init_sr07		= true,
+		.init_sr1f		= true,
+		.scrn_start_bit19	= true,
+		.sr07			= 0xF0,
+		.sr07_1bpp		= 0xF0,
+		.sr07_1bpp_mux		= 0xF6,
+		.sr07_8bpp		= 0xF1,
+		.sr07_8bpp_mux		= 0xF7,
+		.sr1f			= 0x1E
+	},
+	[BT_PICCOLO] = {
+		.name			= "CL Piccolo",
+		.maxclock		= {
+			/* guess */
+			90000, 90000, 90000, 90000, 90000
+		},
+		.init_sr07		= true,
+		.init_sr1f		= true,
+		.scrn_start_bit19	= false,
+		.sr07			= 0x80,
+		.sr07_1bpp		= 0x80,
+		.sr07_8bpp		= 0x81,
+		.sr1f			= 0x22
+	},
+	[BT_PICASSO] = {
+		.name			= "CL Picasso",
+		.maxclock		= {
+			/* guess */
+			90000, 90000, 90000, 90000, 90000
+		},
+		.init_sr07		= true,
+		.init_sr1f		= true,
+		.scrn_start_bit19	= false,
+		.sr07			= 0x20,
+		.sr07_1bpp		= 0x20,
+		.sr07_8bpp		= 0x21,
+		.sr1f			= 0x22
+	},
+	[BT_SPECTRUM] = {
+		.name			= "CL Spectrum",
+		.maxclock		= {
+			/* guess */
+			90000, 90000, 90000, 90000, 90000
+		},
+		.init_sr07		= true,
+		.init_sr1f		= true,
+		.scrn_start_bit19	= false,
+		.sr07			= 0x80,
+		.sr07_1bpp		= 0x80,
+		.sr07_8bpp		= 0x81,
+		.sr1f			= 0x22
+	},
+	[BT_PICASSO4] = {
+		.name			= "CL Picasso4",
+		.maxclock		= {
+			135100, 135100, 85500, 85500, 0
+		},
+		.init_sr07		= true,
+		.init_sr1f		= false,
+		.scrn_start_bit19	= true,
+		.sr07			= 0xA0,
+		.sr07_1bpp		= 0xA0,
+		.sr07_1bpp_mux		= 0xA6,
+		.sr07_8bpp		= 0xA1,
+		.sr07_8bpp_mux		= 0xA7,
+		.sr1f			= 0
+	},
+	[BT_ALPINE] = {
+		.name			= "CL Alpine",
+		.maxclock		= {
+			/* for the GD5430.  GD5446 can do more... */
+			85500, 85500, 50000, 28500, 0
+		},
+		.init_sr07		= true,
+		.init_sr1f		= true,
+		.scrn_start_bit19	= true,
+		.sr07			= 0xA0,
+		.sr07_1bpp		= 0xA0,
+		.sr07_1bpp_mux		= 0xA6,
+		.sr07_8bpp		= 0xA1,
+		.sr07_8bpp_mux		= 0xA7,
+		.sr1f			= 0x1C
+	},
+	[BT_GD5480] = {
+		.name			= "CL GD5480",
+		.maxclock		= {
+			135100, 200000, 200000, 135100, 135100
+		},
+		.init_sr07		= true,
+		.init_sr1f		= true,
+		.scrn_start_bit19	= true,
+		.sr07			= 0x10,
+		.sr07_1bpp		= 0x11,
+		.sr07_8bpp		= 0x11,
+		.sr1f			= 0x1C
+	},
+	[BT_LAGUNA] = {
+		.name			= "CL Laguna",
+		.maxclock		= {
+			/* taken from X11 code */
+			170000, 170000, 170000, 170000, 135100,
+		},
+		.init_sr07		= false,
+		.init_sr1f		= false,
+		.scrn_start_bit19	= true,
+	},
+	[BT_LAGUNAB] = {
+		.name			= "CL Laguna AGP",
+		.maxclock		= {
+			/* taken from X11 code */
+			170000, 250000, 170000, 170000, 135100,
+		},
+		.init_sr07		= false,
+		.init_sr1f		= false,
+		.scrn_start_bit19	= true,
+	}
+};
+
+#ifdef CONFIG_PCI
+#define CHIP(id, btype) \
+	{ PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
+
+static struct pci_device_id cirrusfb_pci_table[] = {
+	CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
+	CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64),
+	CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64),
+	CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
+	CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
+	CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
+	CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
+	CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
+	CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
+	CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
+	CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
+#undef CHIP
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_ZORRO
+struct zorrocl {
+	enum cirrus_board type;	/* Board type */
+	u32 regoffset;		/* Offset of registers in first Zorro device */
+	u32 ramsize;		/* Size of video RAM in first Zorro device */
+				/* If zero, use autoprobe on RAM device */
+	u32 ramoffset;		/* Offset of video RAM in first Zorro device */
+	zorro_id ramid;		/* Zorro ID of RAM device */
+	zorro_id ramid2;	/* Zorro ID of optional second RAM device */
+};
+
+static const struct zorrocl zcl_sd64 = {
+	.type		= BT_SD64,
+	.ramid		= ZORRO_PROD_HELFRICH_SD64_RAM,
+};
+
+static const struct zorrocl zcl_piccolo = {
+	.type		= BT_PICCOLO,
+	.ramid		= ZORRO_PROD_HELFRICH_PICCOLO_RAM,
+};
+
+static const struct zorrocl zcl_picasso = {
+	.type		= BT_PICASSO,
+	.ramid		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+};
+
+static const struct zorrocl zcl_spectrum = {
+	.type		= BT_SPECTRUM,
+	.ramid		= ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
+};
+
+static const struct zorrocl zcl_picasso4_z3 = {
+	.type		= BT_PICASSO4,
+	.regoffset	= 0x00600000,
+	.ramsize	= 4 * MB_,
+	.ramoffset	= 0x01000000,	/* 0x02000000 for 64 MiB boards */
+};
+
+static const struct zorrocl zcl_picasso4_z2 = {
+	.type		= BT_PICASSO4,
+	.regoffset	= 0x10000,
+	.ramid		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
+	.ramid2		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
+};
+
+
+static const struct zorro_device_id cirrusfb_zorro_table[] = {
+	{
+		.id		= ZORRO_PROD_HELFRICH_SD64_REG,
+		.driver_data	= (unsigned long)&zcl_sd64,
+	}, {
+		.id		= ZORRO_PROD_HELFRICH_PICCOLO_REG,
+		.driver_data	= (unsigned long)&zcl_piccolo,
+	}, {
+		.id	= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
+		.driver_data	= (unsigned long)&zcl_picasso,
+	}, {
+		.id		= ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
+		.driver_data	= (unsigned long)&zcl_spectrum,
+	}, {
+		.id		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
+		.driver_data	= (unsigned long)&zcl_picasso4_z3,
+	}, {
+		.id		= ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
+		.driver_data	= (unsigned long)&zcl_picasso4_z2,
+	},
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
+#endif /* CONFIG_ZORRO */
+
+#ifdef CIRRUSFB_DEBUG
+enum cirrusfb_dbg_reg_class {
+	CRT,
+	SEQ
+};
+#endif		/* CIRRUSFB_DEBUG */
+
+/* info about board */
+struct cirrusfb_info {
+	u8 __iomem *regbase;
+	u8 __iomem *laguna_mmio;
+	enum cirrus_board btype;
+	unsigned char SFR;	/* Shadow of special function register */
+
+	int multiplexing;
+	int doubleVCLK;
+	int blank_mode;
+	u32 pseudo_palette[16];
+
+	void (*unmap)(struct fb_info *info);
+};
+
+static bool noaccel;
+static char *mode_option = "640x480@60";
+
+/****************************************************************************/
+/**** BEGIN PROTOTYPES ******************************************************/
+
+/*--- Interface used by the world ------------------------------------------*/
+static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info);
+
+/*--- Internal routines ----------------------------------------------------*/
+static void init_vgachip(struct fb_info *info);
+static void switch_monitor(struct cirrusfb_info *cinfo, int on);
+static void WGen(const struct cirrusfb_info *cinfo,
+		 int regnum, unsigned char val);
+static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
+static void AttrOn(const struct cirrusfb_info *cinfo);
+static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
+static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
+static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
+static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
+		  unsigned char red, unsigned char green, unsigned char blue);
+#if 0
+static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
+		  unsigned char *red, unsigned char *green,
+		  unsigned char *blue);
+#endif
+static void cirrusfb_WaitBLT(u8 __iomem *regbase);
+static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
+			    u_short curx, u_short cury,
+			    u_short destx, u_short desty,
+			    u_short width, u_short height,
+			    u_short line_length);
+static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
+			      u_short x, u_short y,
+			      u_short width, u_short height,
+			      u32 fg_color, u32 bg_color,
+			      u_short line_length, u_char blitmode);
+
+static void bestclock(long freq, int *nom, int *den, int *div);
+
+#ifdef CIRRUSFB_DEBUG
+static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase);
+static void cirrusfb_dbg_print_regs(struct fb_info *info,
+				    caddr_t regbase,
+				    enum cirrusfb_dbg_reg_class reg_class, ...);
+#endif /* CIRRUSFB_DEBUG */
+
+/*** END   PROTOTYPES ********************************************************/
+/*****************************************************************************/
+/*** BEGIN Interface Used by the World ***************************************/
+
+static inline int is_laguna(const struct cirrusfb_info *cinfo)
+{
+	return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB;
+}
+
+static int opencount;
+
+/*--- Open /dev/fbx ---------------------------------------------------------*/
+static int cirrusfb_open(struct fb_info *info, int user)
+{
+	if (opencount++ == 0)
+		switch_monitor(info->par, 1);
+	return 0;
+}
+
+/*--- Close /dev/fbx --------------------------------------------------------*/
+static int cirrusfb_release(struct fb_info *info, int user)
+{
+	if (--opencount == 0)
+		switch_monitor(info->par, 0);
+	return 0;
+}
+
+/**** END   Interface used by the World *************************************/
+/****************************************************************************/
+/**** BEGIN Hardware specific Routines **************************************/
+
+/* Check if the MCLK is not a better clock source */
+static int cirrusfb_check_mclk(struct fb_info *info, long freq)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
+
+	/* Read MCLK value */
+	mclk = (14318 * mclk) >> 3;
+	dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
+
+	/* Determine if we should use MCLK instead of VCLK, and if so, what we
+	 * should divide it by to get VCLK
+	 */
+
+	if (abs(freq - mclk) < 250) {
+		dev_dbg(info->device, "Using VCLK = MCLK\n");
+		return 1;
+	} else if (abs(freq - (mclk / 2)) < 250) {
+		dev_dbg(info->device, "Using VCLK = MCLK/2\n");
+		return 2;
+	}
+
+	return 0;
+}
+
+static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
+				   struct fb_info *info)
+{
+	long freq;
+	long maxclock;
+	struct cirrusfb_info *cinfo = info->par;
+	unsigned maxclockidx = var->bits_per_pixel >> 3;
+
+	/* convert from ps to kHz */
+	freq = PICOS2KHZ(var->pixclock);
+
+	dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
+
+	maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
+	cinfo->multiplexing = 0;
+
+	/* If the frequency is greater than we can support, we might be able
+	 * to use multiplexing for the video mode */
+	if (freq > maxclock) {
+		dev_err(info->device,
+			"Frequency greater than maxclock (%ld kHz)\n",
+			maxclock);
+		return -EINVAL;
+	}
+	/*
+	 * Additional constraint: 8bpp uses DAC clock doubling to allow maximum
+	 * pixel clock
+	 */
+	if (var->bits_per_pixel == 8) {
+		switch (cinfo->btype) {
+		case BT_ALPINE:
+		case BT_SD64:
+		case BT_PICASSO4:
+			if (freq > 85500)
+				cinfo->multiplexing = 1;
+			break;
+		case BT_GD5480:
+			if (freq > 135100)
+				cinfo->multiplexing = 1;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* If we have a 1MB 5434, we need to put ourselves in a mode where
+	 * the VCLK is double the pixel clock. */
+	cinfo->doubleVCLK = 0;
+	if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ &&
+	    var->bits_per_pixel == 16) {
+		cinfo->doubleVCLK = 1;
+	}
+
+	return 0;
+}
+
+static int cirrusfb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	int yres;
+	/* memory size in pixels */
+	unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
+	struct cirrusfb_info *cinfo = info->par;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		var->red.offset = 0;
+		var->red.length = 1;
+		var->green = var->red;
+		var->blue = var->red;
+		break;
+
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green = var->red;
+		var->blue = var->red;
+		break;
+
+	case 16:
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+
+	case 24:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+
+	default:
+		dev_dbg(info->device,
+			"Unsupported bpp size: %d\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	/* use highest possible virtual resolution */
+	if (var->yres_virtual == -1) {
+		var->yres_virtual = pixels / var->xres_virtual;
+
+		dev_info(info->device,
+			 "virtual resolution set to maximum of %dx%d\n",
+			 var->xres_virtual, var->yres_virtual);
+	}
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->xres_virtual * var->yres_virtual > pixels) {
+		dev_err(info->device, "mode %dx%dx%d rejected... "
+		      "virtual resolution too high to fit into video memory!\n",
+			var->xres_virtual, var->yres_virtual,
+			var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* truncate xoffset and yoffset to maximum if too high */
+	if (var->xoffset > var->xres_virtual - var->xres)
+		var->xoffset = var->xres_virtual - var->xres - 1;
+	if (var->yoffset > var->yres_virtual - var->yres)
+		var->yoffset = var->yres_virtual - var->yres - 1;
+
+	var->red.msb_right =
+	    var->green.msb_right =
+	    var->blue.msb_right =
+	    var->transp.offset =
+	    var->transp.length =
+	    var->transp.msb_right = 0;
+
+	yres = var->yres;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		yres *= 2;
+	else if (var->vmode & FB_VMODE_INTERLACED)
+		yres = (yres + 1) / 2;
+
+	if (yres >= 1280) {
+		dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
+			"special treatment required! (TODO)\n");
+		return -EINVAL;
+	}
+
+	if (cirrusfb_check_pixclock(var, info))
+		return -EINVAL;
+
+	if (!is_laguna(cinfo))
+		var->accel_flags = FB_ACCELF_TEXT;
+
+	return 0;
+}
+
+static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	unsigned char old1f, old1e;
+
+	assert(cinfo != NULL);
+	old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
+
+	if (div) {
+		dev_dbg(info->device, "Set %s as pixclock source.\n",
+			(div == 2) ? "MCLK/2" : "MCLK");
+		old1f |= 0x40;
+		old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
+		if (div == 2)
+			old1e |= 1;
+
+		vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
+	}
+	vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
+}
+
+/*************************************************************************
+	cirrusfb_set_par_foo()
+
+	actually writes the values for a new video mode into the hardware,
+**************************************************************************/
+static int cirrusfb_set_par_foo(struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	u8 __iomem *regbase = cinfo->regbase;
+	unsigned char tmp;
+	int pitch;
+	const struct cirrusfb_board_info_rec *bi;
+	int hdispend, hsyncstart, hsyncend, htotal;
+	int yres, vdispend, vsyncstart, vsyncend, vtotal;
+	long freq;
+	int nom, den, div;
+	unsigned int control = 0, format = 0, threshold = 0;
+
+	dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
+	       var->xres, var->yres, var->bits_per_pixel);
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		info->fix.line_length = var->xres_virtual / 8;
+		info->fix.visual = FB_VISUAL_MONO10;
+		break;
+
+	case 8:
+		info->fix.line_length = var->xres_virtual;
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+
+	case 16:
+	case 24:
+		info->fix.line_length = var->xres_virtual *
+					var->bits_per_pixel >> 3;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	}
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+
+	init_vgachip(info);
+
+	bi = &cirrusfb_board_info[cinfo->btype];
+
+	hsyncstart = var->xres + var->right_margin;
+	hsyncend = hsyncstart + var->hsync_len;
+	htotal = (hsyncend + var->left_margin) / 8;
+	hdispend = var->xres / 8;
+	hsyncstart = hsyncstart / 8;
+	hsyncend = hsyncend / 8;
+
+	vdispend = var->yres;
+	vsyncstart = vdispend + var->lower_margin;
+	vsyncend = vsyncstart + var->vsync_len;
+	vtotal = vsyncend + var->upper_margin;
+
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		vdispend *= 2;
+		vsyncstart *= 2;
+		vsyncend *= 2;
+		vtotal *= 2;
+	} else if (var->vmode & FB_VMODE_INTERLACED) {
+		vdispend = (vdispend + 1) / 2;
+		vsyncstart = (vsyncstart + 1) / 2;
+		vsyncend = (vsyncend + 1) / 2;
+		vtotal = (vtotal + 1) / 2;
+	}
+	yres = vdispend;
+	if (yres >= 1024) {
+		vtotal /= 2;
+		vsyncstart /= 2;
+		vsyncend /= 2;
+		vdispend /= 2;
+	}
+
+	vdispend -= 1;
+	vsyncstart -= 1;
+	vsyncend -= 1;
+	vtotal -= 2;
+
+	if (cinfo->multiplexing) {
+		htotal /= 2;
+		hsyncstart /= 2;
+		hsyncend /= 2;
+		hdispend /= 2;
+	}
+
+	htotal -= 5;
+	hdispend -= 1;
+	hsyncstart += 1;
+	hsyncend += 1;
+
+	/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
+	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);	/* previously: 0x00) */
+
+	/* if debugging is enabled, all parameters get output before writing */
+	dev_dbg(info->device, "CRT0: %d\n", htotal);
+	vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
+
+	dev_dbg(info->device, "CRT1: %d\n", hdispend);
+	vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
+
+	dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
+	vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
+
+	/*  + 128: Compatible read */
+	dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
+	vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
+		 128 + ((htotal + 5) % 32));
+
+	dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
+	vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
+
+	tmp = hsyncend % 32;
+	if ((htotal + 5) & 32)
+		tmp += 128;
+	dev_dbg(info->device, "CRT5: %d\n", tmp);
+	vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
+
+	dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
+	vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
+
+	tmp = 16;		/* LineCompare bit #9 */
+	if (vtotal & 256)
+		tmp |= 1;
+	if (vdispend & 256)
+		tmp |= 2;
+	if (vsyncstart & 256)
+		tmp |= 4;
+	if ((vdispend + 1) & 256)
+		tmp |= 8;
+	if (vtotal & 512)
+		tmp |= 32;
+	if (vdispend & 512)
+		tmp |= 64;
+	if (vsyncstart & 512)
+		tmp |= 128;
+	dev_dbg(info->device, "CRT7: %d\n", tmp);
+	vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
+
+	tmp = 0x40;		/* LineCompare bit #8 */
+	if ((vdispend + 1) & 512)
+		tmp |= 0x20;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		tmp |= 0x80;
+	dev_dbg(info->device, "CRT9: %d\n", tmp);
+	vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
+
+	dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
+	vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
+
+	dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
+	vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
+
+	dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
+	vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
+
+	dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
+	vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
+
+	dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
+	vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
+
+	dev_dbg(info->device, "CRT18: 0xff\n");
+	vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
+
+	tmp = 0;
+	if (var->vmode & FB_VMODE_INTERLACED)
+		tmp |= 1;
+	if ((htotal + 5) & 64)
+		tmp |= 16;
+	if ((htotal + 5) & 128)
+		tmp |= 32;
+	if (vtotal & 256)
+		tmp |= 64;
+	if (vtotal & 512)
+		tmp |= 128;
+
+	dev_dbg(info->device, "CRT1a: %d\n", tmp);
+	vga_wcrt(regbase, CL_CRT1A, tmp);
+
+	freq = PICOS2KHZ(var->pixclock);
+	if (var->bits_per_pixel == 24)
+		if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64)
+			freq *= 3;
+	if (cinfo->multiplexing)
+		freq /= 2;
+	if (cinfo->doubleVCLK)
+		freq *= 2;
+
+	bestclock(freq, &nom, &den, &div);
+
+	dev_dbg(info->device, "VCLK freq: %ld kHz  nom: %d  den: %d  div: %d\n",
+		freq, nom, den, div);
+
+	/* set VCLK0 */
+	/* hardware RefClock: 14.31818 MHz */
+	/* formula: VClk = (OSC * N) / (D * (1+P)) */
+	/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
+
+	if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 ||
+	    cinfo->btype == BT_SD64) {
+		/* if freq is close to mclk or mclk/2 select mclk
+		 * as clock source
+		 */
+		int divMCLK = cirrusfb_check_mclk(info, freq);
+		if (divMCLK)
+			nom = 0;
+		cirrusfb_set_mclk_as_source(info, divMCLK);
+	}
+	if (is_laguna(cinfo)) {
+		long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
+		unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
+		unsigned short tile_control;
+
+		if (cinfo->btype == BT_LAGUNAB) {
+			tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
+			tile_control &= ~0x80;
+			fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
+		}
+
+		fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
+		fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
+		control = fb_readw(cinfo->laguna_mmio + 0x402);
+		threshold = fb_readw(cinfo->laguna_mmio + 0xea);
+		control &= ~0x6800;
+		format = 0;
+		threshold &= 0xffc0 & 0x3fbf;
+	}
+	if (nom) {
+		tmp = den << 1;
+		if (div != 0)
+			tmp |= 1;
+		/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
+		if ((cinfo->btype == BT_SD64) ||
+		    (cinfo->btype == BT_ALPINE) ||
+		    (cinfo->btype == BT_GD5480))
+			tmp |= 0x80;
+
+		/* Laguna chipset has reversed clock registers */
+		if (is_laguna(cinfo)) {
+			vga_wseq(regbase, CL_SEQRE, tmp);
+			vga_wseq(regbase, CL_SEQR1E, nom);
+		} else {
+			vga_wseq(regbase, CL_SEQRE, nom);
+			vga_wseq(regbase, CL_SEQR1E, tmp);
+		}
+	}
+
+	if (yres >= 1024)
+		/* 1280x1024 */
+		vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
+	else
+		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
+		 * address wrap, no compat. */
+		vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
+
+	/* don't know if it would hurt to also program this if no interlaced */
+	/* mode is used, but I feel better this way.. :-) */
+	if (var->vmode & FB_VMODE_INTERLACED)
+		vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
+	else
+		vga_wcrt(regbase, VGA_CRTC_REGS, 0x00);	/* interlace control */
+
+	/* adjust horizontal/vertical sync type (low/high), use VCLK3 */
+	/* enable display memory & CRTC I/O address for color mode */
+	tmp = 0x03 | 0xc;
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		tmp |= 0x40;
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		tmp |= 0x80;
+	WGen(cinfo, VGA_MIS_W, tmp);
+
+	/* text cursor on and start line */
+	vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
+	/* text cursor end line */
+	vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
+
+	/******************************************************
+	 *
+	 * 1 bpp
+	 *
+	 */
+
+	/* programming for different color depths */
+	if (var->bits_per_pixel == 1) {
+		dev_dbg(info->device, "preparing for 1 bit deep display\n");
+		vga_wgfx(regbase, VGA_GFX_MODE, 0);	/* mode register */
+
+		/* SR07 */
+		switch (cinfo->btype) {
+		case BT_SD64:
+		case BT_PICCOLO:
+		case BT_PICASSO:
+		case BT_SPECTRUM:
+		case BT_PICASSO4:
+		case BT_ALPINE:
+		case BT_GD5480:
+			vga_wseq(regbase, CL_SEQR7,
+				 cinfo->multiplexing ?
+					bi->sr07_1bpp_mux : bi->sr07_1bpp);
+			break;
+
+		case BT_LAGUNA:
+		case BT_LAGUNAB:
+			vga_wseq(regbase, CL_SEQR7,
+				vga_rseq(regbase, CL_SEQR7) & ~0x01);
+			break;
+
+		default:
+			dev_warn(info->device, "unknown Board\n");
+			break;
+		}
+
+		/* Extended Sequencer Mode */
+		switch (cinfo->btype) {
+
+		case BT_PICCOLO:
+		case BT_SPECTRUM:
+			/* evtl d0 bei 1 bit? avoid FIFO underruns..? */
+			vga_wseq(regbase, CL_SEQRF, 0xb0);
+			break;
+
+		case BT_PICASSO:
+			/* ## vorher d0 avoid FIFO underruns..? */
+			vga_wseq(regbase, CL_SEQRF, 0xd0);
+			break;
+
+		case BT_SD64:
+		case BT_PICASSO4:
+		case BT_ALPINE:
+		case BT_GD5480:
+		case BT_LAGUNA:
+		case BT_LAGUNAB:
+			/* do nothing */
+			break;
+
+		default:
+			dev_warn(info->device, "unknown Board\n");
+			break;
+		}
+
+		/* pixel mask: pass-through for first plane */
+		WGen(cinfo, VGA_PEL_MSK, 0x01);
+		if (cinfo->multiplexing)
+			/* hidden dac reg: 1280x1024 */
+			WHDR(cinfo, 0x4a);
+		else
+			/* hidden dac: nothing */
+			WHDR(cinfo, 0);
+		/* memory mode: odd/even, ext. memory */
+		vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
+		/* plane mask: only write to first plane */
+		vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
+	}
+
+	/******************************************************
+	 *
+	 * 8 bpp
+	 *
+	 */
+
+	else if (var->bits_per_pixel == 8) {
+		dev_dbg(info->device, "preparing for 8 bit deep display\n");
+		switch (cinfo->btype) {
+		case BT_SD64:
+		case BT_PICCOLO:
+		case BT_PICASSO:
+		case BT_SPECTRUM:
+		case BT_PICASSO4:
+		case BT_ALPINE:
+		case BT_GD5480:
+			vga_wseq(regbase, CL_SEQR7,
+				  cinfo->multiplexing ?
+					bi->sr07_8bpp_mux : bi->sr07_8bpp);
+			break;
+
+		case BT_LAGUNA:
+		case BT_LAGUNAB:
+			vga_wseq(regbase, CL_SEQR7,
+				vga_rseq(regbase, CL_SEQR7) | 0x01);
+			threshold |= 0x10;
+			break;
+
+		default:
+			dev_warn(info->device, "unknown Board\n");
+			break;
+		}
+
+		switch (cinfo->btype) {
+		case BT_PICCOLO:
+		case BT_PICASSO:
+		case BT_SPECTRUM:
+			/* Fast Page-Mode writes */
+			vga_wseq(regbase, CL_SEQRF, 0xb0);
+			break;
+
+		case BT_PICASSO4:
+#ifdef CONFIG_ZORRO
+			/* ### INCOMPLETE!! */
+			vga_wseq(regbase, CL_SEQRF, 0xb8);
+#endif
+		case BT_ALPINE:
+		case BT_SD64:
+		case BT_GD5480:
+		case BT_LAGUNA:
+		case BT_LAGUNAB:
+			/* do nothing */
+			break;
+
+		default:
+			dev_warn(info->device, "unknown board\n");
+			break;
+		}
+
+		/* mode register: 256 color mode */
+		vga_wgfx(regbase, VGA_GFX_MODE, 64);
+		if (cinfo->multiplexing)
+			/* hidden dac reg: 1280x1024 */
+			WHDR(cinfo, 0x4a);
+		else
+			/* hidden dac: nothing */
+			WHDR(cinfo, 0);
+	}
+
+	/******************************************************
+	 *
+	 * 16 bpp
+	 *
+	 */
+
+	else if (var->bits_per_pixel == 16) {
+		dev_dbg(info->device, "preparing for 16 bit deep display\n");
+		switch (cinfo->btype) {
+		case BT_PICCOLO:
+		case BT_SPECTRUM:
+			vga_wseq(regbase, CL_SEQR7, 0x87);
+			/* Fast Page-Mode writes */
+			vga_wseq(regbase, CL_SEQRF, 0xb0);
+			break;
+
+		case BT_PICASSO:
+			vga_wseq(regbase, CL_SEQR7, 0x27);
+			/* Fast Page-Mode writes */
+			vga_wseq(regbase, CL_SEQRF, 0xb0);
+			break;
+
+		case BT_SD64:
+		case BT_PICASSO4:
+		case BT_ALPINE:
+			/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq(regbase, CL_SEQR7,
+					cinfo->doubleVCLK ? 0xa3 : 0xa7);
+			break;
+
+		case BT_GD5480:
+			vga_wseq(regbase, CL_SEQR7, 0x17);
+			/* We already set SRF and SR1F */
+			break;
+
+		case BT_LAGUNA:
+		case BT_LAGUNAB:
+			vga_wseq(regbase, CL_SEQR7,
+				vga_rseq(regbase, CL_SEQR7) & ~0x01);
+			control |= 0x2000;
+			format |= 0x1400;
+			threshold |= 0x10;
+			break;
+
+		default:
+			dev_warn(info->device, "unknown Board\n");
+			break;
+		}
+
+		/* mode register: 256 color mode */
+		vga_wgfx(regbase, VGA_GFX_MODE, 64);
+#ifdef CONFIG_PCI
+		WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1);
+#elif defined(CONFIG_ZORRO)
+		/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
+		WHDR(cinfo, 0xa0);	/* hidden dac reg: nothing special */
+#endif
+	}
+
+	/******************************************************
+	 *
+	 * 24 bpp
+	 *
+	 */
+
+	else if (var->bits_per_pixel == 24) {
+		dev_dbg(info->device, "preparing for 24 bit deep display\n");
+		switch (cinfo->btype) {
+		case BT_PICCOLO:
+		case BT_SPECTRUM:
+			vga_wseq(regbase, CL_SEQR7, 0x85);
+			/* Fast Page-Mode writes */
+			vga_wseq(regbase, CL_SEQRF, 0xb0);
+			break;
+
+		case BT_PICASSO:
+			vga_wseq(regbase, CL_SEQR7, 0x25);
+			/* Fast Page-Mode writes */
+			vga_wseq(regbase, CL_SEQRF, 0xb0);
+			break;
+
+		case BT_SD64:
+		case BT_PICASSO4:
+		case BT_ALPINE:
+			/* Extended Sequencer Mode: 256c col. mode */
+			vga_wseq(regbase, CL_SEQR7, 0xa5);
+			break;
+
+		case BT_GD5480:
+			vga_wseq(regbase, CL_SEQR7, 0x15);
+			/* We already set SRF and SR1F */
+			break;
+
+		case BT_LAGUNA:
+		case BT_LAGUNAB:
+			vga_wseq(regbase, CL_SEQR7,
+				vga_rseq(regbase, CL_SEQR7) & ~0x01);
+			control |= 0x4000;
+			format |= 0x2400;
+			threshold |= 0x20;
+			break;
+
+		default:
+			dev_warn(info->device, "unknown Board\n");
+			break;
+		}
+
+		/* mode register: 256 color mode */
+		vga_wgfx(regbase, VGA_GFX_MODE, 64);
+		/* hidden dac reg: 8-8-8 mode (24 or 32) */
+		WHDR(cinfo, 0xc5);
+	}
+
+	/******************************************************
+	 *
+	 * unknown/unsupported bpp
+	 *
+	 */
+
+	else
+		dev_err(info->device,
+			"What's this? requested color depth == %d.\n",
+			var->bits_per_pixel);
+
+	pitch = info->fix.line_length >> 3;
+	vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
+	tmp = 0x22;
+	if (pitch & 0x100)
+		tmp |= 0x10;	/* offset overflow bit */
+
+	/* screen start addr #16-18, fastpagemode cycles */
+	vga_wcrt(regbase, CL_CRT1B, tmp);
+
+	/* screen start address bit 19 */
+	if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
+		vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
+
+	if (is_laguna(cinfo)) {
+		tmp = 0;
+		if ((htotal + 5) & 256)
+			tmp |= 128;
+		if (hdispend & 256)
+			tmp |= 64;
+		if (hsyncstart & 256)
+			tmp |= 48;
+		if (vtotal & 1024)
+			tmp |= 8;
+		if (vdispend & 1024)
+			tmp |= 4;
+		if (vsyncstart & 1024)
+			tmp |= 3;
+
+		vga_wcrt(regbase, CL_CRT1E, tmp);
+		dev_dbg(info->device, "CRT1e: %d\n", tmp);
+	}
+
+	/* pixel panning */
+	vga_wattr(regbase, CL_AR33, 0);
+
+	/* [ EGS: SetOffset(); ] */
+	/* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
+	AttrOn(cinfo);
+
+	if (is_laguna(cinfo)) {
+		/* no tiles */
+		fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
+		fb_writew(format, cinfo->laguna_mmio + 0xc0);
+		fb_writew(threshold, cinfo->laguna_mmio + 0xea);
+	}
+	/* finally, turn on everything - turn off "FullBandwidth" bit */
+	/* also, set "DotClock%2" bit where requested */
+	tmp = 0x01;
+
+/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
+    if (var->vmode & FB_VMODE_CLOCK_HALVE)
+	tmp |= 0x08;
+*/
+
+	vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
+	dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
+
+#ifdef CIRRUSFB_DEBUG
+	cirrusfb_dbg_reg_dump(info, NULL);
+#endif
+
+	return 0;
+}
+
+/* for some reason incomprehensible to me, cirrusfb requires that you write
+ * the registers twice for the settings to take..grr. -dte */
+static int cirrusfb_set_par(struct fb_info *info)
+{
+	cirrusfb_set_par_foo(info);
+	return cirrusfb_set_par_foo(info);
+}
+
+static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+
+	if (regno > 255)
+		return -EINVAL;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+
+		if (regno >= 16)
+			return 1;
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset);
+
+		cinfo->pseudo_palette[regno] = v;
+		return 0;
+	}
+
+	if (info->var.bits_per_pixel == 8)
+		WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
+
+	return 0;
+
+}
+
+/*************************************************************************
+	cirrusfb_pan_display()
+
+	performs display panning - provided hardware permits this
+**************************************************************************/
+static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	int xoffset;
+	unsigned long base;
+	unsigned char tmp, xpix;
+	struct cirrusfb_info *cinfo = info->par;
+
+	/* no range checks for xoffset and yoffset,   */
+	/* as fb_pan_display has already done this */
+	if (var->vmode & FB_VMODE_YWRAP)
+		return -EINVAL;
+
+	xoffset = var->xoffset * info->var.bits_per_pixel / 8;
+
+	base = var->yoffset * info->fix.line_length + xoffset;
+
+	if (info->var.bits_per_pixel == 1) {
+		/* base is already correct */
+		xpix = (unsigned char) (var->xoffset % 8);
+	} else {
+		base /= 4;
+		xpix = (unsigned char) ((xoffset % 4) * 2);
+	}
+
+	if (!is_laguna(cinfo))
+		cirrusfb_WaitBLT(cinfo->regbase);
+
+	/* lower 8 + 8 bits of screen start address */
+	vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
+	vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
+
+	/* 0xf2 is %11110010, exclude tmp bits */
+	tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
+	/* construct bits 16, 17 and 18 of screen start address */
+	if (base & 0x10000)
+		tmp |= 0x01;
+	if (base & 0x20000)
+		tmp |= 0x04;
+	if (base & 0x40000)
+		tmp |= 0x08;
+
+	vga_wcrt(cinfo->regbase, CL_CRT1B, tmp);
+
+	/* construct bit 19 of screen start address */
+	if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
+		tmp = vga_rcrt(cinfo->regbase, CL_CRT1D);
+		if (is_laguna(cinfo))
+			tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
+		else
+			tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
+		vga_wcrt(cinfo->regbase, CL_CRT1D, tmp);
+	}
+
+	/* write pixel panning value to AR33; this does not quite work in 8bpp
+	 *
+	 * ### Piccolo..? Will this work?
+	 */
+	if (info->var.bits_per_pixel == 1)
+		vga_wattr(cinfo->regbase, CL_AR33, xpix);
+
+	return 0;
+}
+
+static int cirrusfb_blank(int blank_mode, struct fb_info *info)
+{
+	/*
+	 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+	 * then the caller blanks by setting the CLUT (Color Look Up Table)
+	 * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
+	 * failed due to e.g. a video mode which doesn't support it.
+	 * Implements VESA suspend and powerdown modes on hardware that
+	 * supports disabling hsync/vsync:
+	 *   blank_mode == 2: suspend vsync
+	 *   blank_mode == 3: suspend hsync
+	 *   blank_mode == 4: powerdown
+	 */
+	unsigned char val;
+	struct cirrusfb_info *cinfo = info->par;
+	int current_mode = cinfo->blank_mode;
+
+	dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
+
+	if (info->state != FBINFO_STATE_RUNNING ||
+	    current_mode == blank_mode) {
+		dev_dbg(info->device, "EXIT, returning 0\n");
+		return 0;
+	}
+
+	/* Undo current */
+	if (current_mode == FB_BLANK_NORMAL ||
+	    current_mode == FB_BLANK_UNBLANK)
+		/* clear "FullBandwidth" bit */
+		val = 0;
+	else
+		/* set "FullBandwidth" bit */
+		val = 0x20;
+
+	val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
+	vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		val = 0x00;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		val = 0x04;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		val = 0x02;
+		break;
+	case FB_BLANK_POWERDOWN:
+		val = 0x06;
+		break;
+	default:
+		dev_dbg(info->device, "EXIT, returning 1\n");
+		return 1;
+	}
+
+	vga_wgfx(cinfo->regbase, CL_GRE, val);
+
+	cinfo->blank_mode = blank_mode;
+	dev_dbg(info->device, "EXIT, returning 0\n");
+
+	/* Let fbcon do a soft blank for us */
+	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+/**** END   Hardware specific Routines **************************************/
+/****************************************************************************/
+/**** BEGIN Internal Routines ***********************************************/
+
+static void init_vgachip(struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	const struct cirrusfb_board_info_rec *bi;
+
+	assert(cinfo != NULL);
+
+	bi = &cirrusfb_board_info[cinfo->btype];
+
+	/* reset board globally */
+	switch (cinfo->btype) {
+	case BT_PICCOLO:
+		WSFR(cinfo, 0x01);
+		udelay(500);
+		WSFR(cinfo, 0x51);
+		udelay(500);
+		break;
+	case BT_PICASSO:
+		WSFR2(cinfo, 0xff);
+		udelay(500);
+		break;
+	case BT_SD64:
+	case BT_SPECTRUM:
+		WSFR(cinfo, 0x1f);
+		udelay(500);
+		WSFR(cinfo, 0x4f);
+		udelay(500);
+		break;
+	case BT_PICASSO4:
+		/* disable flickerfixer */
+		vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
+		mdelay(100);
+		/* mode */
+		vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
+	case BT_GD5480:  /* fall through */
+		/* from Klaus' NetBSD driver: */
+		vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
+	case BT_ALPINE:  /* fall through */
+		/* put blitter into 542x compat */
+		vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
+		break;
+
+	case BT_LAGUNA:
+	case BT_LAGUNAB:
+		/* Nothing to do to reset the board. */
+		break;
+
+	default:
+		dev_err(info->device, "Warning: Unknown board type\n");
+		break;
+	}
+
+	/* make sure RAM size set by this point */
+	assert(info->screen_size > 0);
+
+	/* the P4 is not fully initialized here; I rely on it having been */
+	/* inited under AmigaOS already, which seems to work just fine    */
+	/* (Klaus advised to do it this way)			      */
+
+	if (cinfo->btype != BT_PICASSO4) {
+		WGen(cinfo, CL_VSSM, 0x10);	/* EGS: 0x16 */
+		WGen(cinfo, CL_POS102, 0x01);
+		WGen(cinfo, CL_VSSM, 0x08);	/* EGS: 0x0e */
+
+		if (cinfo->btype != BT_SD64)
+			WGen(cinfo, CL_VSSM2, 0x01);
+
+		/* reset sequencer logic */
+		vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03);
+
+		/* FullBandwidth (video off) and 8/9 dot clock */
+		vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
+
+		/* "magic cookie" - doesn't make any sense to me.. */
+/*      vga_wgfx(cinfo->regbase, CL_GRA, 0xce);   */
+		/* unlock all extension registers */
+		vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
+
+		switch (cinfo->btype) {
+		case BT_GD5480:
+			vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
+			break;
+		case BT_ALPINE:
+		case BT_LAGUNA:
+		case BT_LAGUNAB:
+			break;
+		case BT_SD64:
+#ifdef CONFIG_ZORRO
+			vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
+#endif
+			break;
+		default:
+			vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
+			vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
+			break;
+		}
+	}
+	/* plane mask: nothing */
+	vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
+	/* character map select: doesn't even matter in gx mode */
+	vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
+	/* memory mode: chain4, ext. memory */
+	vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
+
+	/* controller-internal base address of video memory */
+	if (bi->init_sr07)
+		vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
+
+	/*  vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
+	/* EEPROM control: shouldn't be necessary to write to this at all.. */
+
+	/* graphics cursor X position (incomplete; position gives rem. 3 bits */
+	vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
+	/* graphics cursor Y position (..."... ) */
+	vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
+	/* graphics cursor attributes */
+	vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
+	/* graphics cursor pattern address */
+	vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
+
+	/* writing these on a P4 might give problems..  */
+	if (cinfo->btype != BT_PICASSO4) {
+		/* configuration readback and ext. color */
+		vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
+		/* signature generator */
+		vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
+	}
+
+	/* Screen A preset row scan: none */
+	vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
+	/* Text cursor start: disable text cursor */
+	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
+	/* Text cursor end: - */
+	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
+	/* text cursor location high: 0 */
+	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
+	/* text cursor location low: 0 */
+	vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
+
+	/* Underline Row scanline: - */
+	vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
+	/* ### add 0x40 for text modes with > 30 MHz pixclock */
+	/* ext. display controls: ext.adr. wrap */
+	vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
+
+	/* Set/Reset registers: - */
+	vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
+	/* Set/Reset enable: - */
+	vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
+	/* Color Compare: - */
+	vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
+	/* Data Rotate: - */
+	vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
+	/* Read Map Select: - */
+	vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
+	/* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
+	vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
+	/* Miscellaneous: memory map base address, graphics mode */
+	vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
+	/* Color Don't care: involve all planes */
+	vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
+	/* Bit Mask: no mask at all */
+	vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
+
+	if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 ||
+	    is_laguna(cinfo))
+		/* (5434 can't have bit 3 set for bitblt) */
+		vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
+	else
+	/* Graphics controller mode extensions: finer granularity,
+	 * 8byte data latches
+	 */
+		vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
+
+	vga_wgfx(cinfo->regbase, CL_GRC, 0xff);	/* Color Key compare: - */
+	vga_wgfx(cinfo->regbase, CL_GRD, 0x00);	/* Color Key compare mask: - */
+	vga_wgfx(cinfo->regbase, CL_GRE, 0x00);	/* Miscellaneous control: - */
+	/* Background color byte 1: - */
+	/*  vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
+	/*  vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
+
+	/* Attribute Controller palette registers: "identity mapping" */
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
+	vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
+
+	/* Attribute Controller mode: graphics mode */
+	vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
+	/* Overscan color reg.: reg. 0 */
+	vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
+	/* Color Plane enable: Enable all 4 planes */
+	vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
+	/* Color Select: - */
+	vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
+
+	WGen(cinfo, VGA_PEL_MSK, 0xff);	/* Pixel mask: no mask */
+
+	/* BLT Start/status: Blitter reset */
+	vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
+	/* - " -	   : "end-of-reset" */
+	vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
+
+	/* misc... */
+	WHDR(cinfo, 0);	/* Hidden DAC register: - */
+	return;
+}
+
+static void switch_monitor(struct cirrusfb_info *cinfo, int on)
+{
+#ifdef CONFIG_ZORRO /* only works on Zorro boards */
+	static int IsOn = 0;	/* XXX not ok for multiple boards */
+
+	if (cinfo->btype == BT_PICASSO4)
+		return;		/* nothing to switch */
+	if (cinfo->btype == BT_ALPINE)
+		return;		/* nothing to switch */
+	if (cinfo->btype == BT_GD5480)
+		return;		/* nothing to switch */
+	if (cinfo->btype == BT_PICASSO) {
+		if ((on && !IsOn) || (!on && IsOn))
+			WSFR(cinfo, 0xff);
+		return;
+	}
+	if (on) {
+		switch (cinfo->btype) {
+		case BT_SD64:
+			WSFR(cinfo, cinfo->SFR | 0x21);
+			break;
+		case BT_PICCOLO:
+			WSFR(cinfo, cinfo->SFR | 0x28);
+			break;
+		case BT_SPECTRUM:
+			WSFR(cinfo, 0x6f);
+			break;
+		default: /* do nothing */ break;
+		}
+	} else {
+		switch (cinfo->btype) {
+		case BT_SD64:
+			WSFR(cinfo, cinfo->SFR & 0xde);
+			break;
+		case BT_PICCOLO:
+			WSFR(cinfo, cinfo->SFR & 0xd7);
+			break;
+		case BT_SPECTRUM:
+			WSFR(cinfo, 0x4f);
+			break;
+		default: /* do nothing */
+			break;
+		}
+	}
+#endif /* CONFIG_ZORRO */
+}
+
+/******************************************/
+/* Linux 2.6-style  accelerated functions */
+/******************************************/
+
+static int cirrusfb_sync(struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+
+	if (!is_laguna(cinfo)) {
+		while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03)
+			cpu_relax();
+	}
+	return 0;
+}
+
+static void cirrusfb_fillrect(struct fb_info *info,
+			      const struct fb_fillrect *region)
+{
+	struct fb_fillrect modded;
+	int vxres, vyres;
+	struct cirrusfb_info *cinfo = info->par;
+	int m = info->var.bits_per_pixel;
+	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+		cinfo->pseudo_palette[region->color] : region->color;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(info, region);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if (!modded.width || !modded.height ||
+	   modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.dx + modded.width  > vxres)
+		modded.width  = vxres - modded.dx;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	cirrusfb_RectFill(cinfo->regbase,
+			  info->var.bits_per_pixel,
+			  (region->dx * m) / 8, region->dy,
+			  (region->width * m) / 8, region->height,
+			  color, color,
+			  info->fix.line_length, 0x40);
+}
+
+static void cirrusfb_copyarea(struct fb_info *info,
+			      const struct fb_copyarea *area)
+{
+	struct fb_copyarea modded;
+	u32 vxres, vyres;
+	struct cirrusfb_info *cinfo = info->par;
+	int m = info->var.bits_per_pixel;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+	memcpy(&modded, area, sizeof(struct fb_copyarea));
+
+	if (!modded.width || !modded.height ||
+	   modded.sx >= vxres || modded.sy >= vyres ||
+	   modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.sx + modded.width > vxres)
+		modded.width = vxres - modded.sx;
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.sy + modded.height > vyres)
+		modded.height = vyres - modded.sy;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
+			(area->sx * m) / 8, area->sy,
+			(area->dx * m) / 8, area->dy,
+			(area->width * m) / 8, area->height,
+			info->fix.line_length);
+
+}
+
+static void cirrusfb_imageblit(struct fb_info *info,
+			       const struct fb_image *image)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	/* Alpine/SD64 does not work at 24bpp ??? */
+	if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
+		cfb_imageblit(info, image);
+	else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) &&
+		  op == 0xc)
+		cfb_imageblit(info, image);
+	else {
+		unsigned size = ((image->width + 7) >> 3) * image->height;
+		int m = info->var.bits_per_pixel;
+		u32 fg, bg;
+
+		if (info->var.bits_per_pixel == 8) {
+			fg = image->fg_color;
+			bg = image->bg_color;
+		} else {
+			fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
+			bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
+		}
+		if (info->var.bits_per_pixel == 24) {
+			/* clear background first */
+			cirrusfb_RectFill(cinfo->regbase,
+					  info->var.bits_per_pixel,
+					  (image->dx * m) / 8, image->dy,
+					  (image->width * m) / 8,
+					  image->height,
+					  bg, bg,
+					  info->fix.line_length, 0x40);
+		}
+		cirrusfb_RectFill(cinfo->regbase,
+				  info->var.bits_per_pixel,
+				  (image->dx * m) / 8, image->dy,
+				  (image->width * m) / 8, image->height,
+				  fg, bg,
+				  info->fix.line_length, op);
+		memcpy(info->screen_base, image->data, size);
+	}
+}
+
+#ifdef CONFIG_PCI
+static int release_io_ports;
+
+/* Pulled the logic from XFree86 Cirrus driver to get the memory size,
+ * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
+ * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
+ * seem to have. */
+static unsigned int cirrusfb_get_memsize(struct fb_info *info,
+					 u8 __iomem *regbase)
+{
+	unsigned long mem;
+	struct cirrusfb_info *cinfo = info->par;
+
+	if (is_laguna(cinfo)) {
+		unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
+
+		mem = ((SR14 & 7) + 1) << 20;
+	} else {
+		unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
+		switch ((SRF & 0x18)) {
+		case 0x08:
+			mem = 512 * 1024;
+			break;
+		case 0x10:
+			mem = 1024 * 1024;
+			break;
+		/* 64-bit DRAM data bus width; assume 2MB.
+		 * Also indicates 2MB memory on the 5430.
+		 */
+		case 0x18:
+			mem = 2048 * 1024;
+			break;
+		default:
+			dev_warn(info->device, "Unknown memory size!\n");
+			mem = 1024 * 1024;
+		}
+		/* If DRAM bank switching is enabled, there must be
+		 * twice as much memory installed. (4MB on the 5434)
+		 */
+		if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0)
+			mem *= 2;
+	}
+
+	/* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
+	return mem;
+}
+
+static void get_pci_addrs(const struct pci_dev *pdev,
+			  unsigned long *display, unsigned long *registers)
+{
+	assert(pdev != NULL);
+	assert(display != NULL);
+	assert(registers != NULL);
+
+	*display = 0;
+	*registers = 0;
+
+	/* This is a best-guess for now */
+
+	if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
+		*display = pci_resource_start(pdev, 1);
+		*registers = pci_resource_start(pdev, 0);
+	} else {
+		*display = pci_resource_start(pdev, 0);
+		*registers = pci_resource_start(pdev, 1);
+	}
+
+	assert(*display != 0);
+}
+
+static void cirrusfb_pci_unmap(struct fb_info *info)
+{
+	struct pci_dev *pdev = to_pci_dev(info->device);
+	struct cirrusfb_info *cinfo = info->par;
+
+	if (cinfo->laguna_mmio == NULL)
+		iounmap(cinfo->laguna_mmio);
+	iounmap(info->screen_base);
+#if 0 /* if system didn't claim this region, we would... */
+	release_mem_region(0xA0000, 65535);
+#endif
+	if (release_io_ports)
+		release_region(0x3C0, 32);
+	pci_release_regions(pdev);
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_ZORRO
+static void cirrusfb_zorro_unmap(struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	struct zorro_dev *zdev = to_zorro_dev(info->device);
+
+	if (info->fix.smem_start > 16 * MB_)
+		iounmap(info->screen_base);
+	if (info->fix.mmio_start > 16 * MB_)
+		iounmap(cinfo->regbase);
+
+	zorro_release_device(zdev);
+}
+#endif /* CONFIG_ZORRO */
+
+/* function table of the above functions */
+static struct fb_ops cirrusfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= cirrusfb_open,
+	.fb_release	= cirrusfb_release,
+	.fb_setcolreg	= cirrusfb_setcolreg,
+	.fb_check_var	= cirrusfb_check_var,
+	.fb_set_par	= cirrusfb_set_par,
+	.fb_pan_display = cirrusfb_pan_display,
+	.fb_blank	= cirrusfb_blank,
+	.fb_fillrect	= cirrusfb_fillrect,
+	.fb_copyarea	= cirrusfb_copyarea,
+	.fb_sync	= cirrusfb_sync,
+	.fb_imageblit	= cirrusfb_imageblit,
+};
+
+static int cirrusfb_set_fbinfo(struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+
+	info->pseudo_palette = cinfo->pseudo_palette;
+	info->flags = FBINFO_DEFAULT
+		    | FBINFO_HWACCEL_XPAN
+		    | FBINFO_HWACCEL_YPAN
+		    | FBINFO_HWACCEL_FILLRECT
+		    | FBINFO_HWACCEL_IMAGEBLIT
+		    | FBINFO_HWACCEL_COPYAREA;
+	if (noaccel || is_laguna(cinfo)) {
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+		info->fix.accel = FB_ACCEL_NONE;
+	} else
+		info->fix.accel = FB_ACCEL_CIRRUS_ALPINE;
+
+	info->fbops = &cirrusfb_ops;
+
+	if (cinfo->btype == BT_GD5480) {
+		if (var->bits_per_pixel == 16)
+			info->screen_base += 1 * MB_;
+		if (var->bits_per_pixel == 32)
+			info->screen_base += 2 * MB_;
+	}
+
+	/* Fill fix common fields */
+	strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
+		sizeof(info->fix.id));
+
+	/* monochrome: only 1 memory plane */
+	/* 8 bit and above: Use whole memory area */
+	info->fix.smem_len   = info->screen_size;
+	if (var->bits_per_pixel == 1)
+		info->fix.smem_len /= 4;
+	info->fix.type_aux   = 0;
+	info->fix.xpanstep   = 1;
+	info->fix.ypanstep   = 1;
+	info->fix.ywrapstep  = 0;
+
+	/* FIXME: map region at 0xB8000 if available, fill in here */
+	info->fix.mmio_len   = 0;
+
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	return 0;
+}
+
+static int cirrusfb_register(struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+	int err;
+
+	/* sanity checks */
+	assert(cinfo->btype != BT_NONE);
+
+	/* set all the vital stuff */
+	cirrusfb_set_fbinfo(info);
+
+	dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
+
+	err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+	if (!err) {
+		dev_dbg(info->device, "wrong initial video mode\n");
+		err = -EINVAL;
+		goto err_dealloc_cmap;
+	}
+
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	err = cirrusfb_check_var(&info->var, info);
+	if (err < 0) {
+		/* should never happen */
+		dev_dbg(info->device,
+			"choking on default var... umm, no good.\n");
+		goto err_dealloc_cmap;
+	}
+
+	err = register_framebuffer(info);
+	if (err < 0) {
+		dev_err(info->device,
+			"could not register fb device; err = %d!\n", err);
+		goto err_dealloc_cmap;
+	}
+
+	return 0;
+
+err_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+	return err;
+}
+
+static void cirrusfb_cleanup(struct fb_info *info)
+{
+	struct cirrusfb_info *cinfo = info->par;
+
+	switch_monitor(cinfo, 0);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+	dev_dbg(info->device, "Framebuffer unregistered\n");
+	cinfo->unmap(info);
+	framebuffer_release(info);
+}
+
+#ifdef CONFIG_PCI
+static int cirrusfb_pci_register(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct cirrusfb_info *cinfo;
+	struct fb_info *info;
+	unsigned long board_addr, board_size;
+	int ret;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0) {
+		printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
+		goto err_out;
+	}
+
+	info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
+	if (!info) {
+		printk(KERN_ERR "cirrusfb: could not allocate memory\n");
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	cinfo = info->par;
+	cinfo->btype = (enum cirrus_board) ent->driver_data;
+
+	dev_dbg(info->device,
+		" Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
+		(unsigned long long)pdev->resource[0].start,  cinfo->btype);
+	dev_dbg(info->device, " base address 1 is 0x%Lx\n",
+		(unsigned long long)pdev->resource[1].start);
+
+	dev_dbg(info->device,
+		"Attempt to get PCI info for Cirrus Graphics Card\n");
+	get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
+	/* FIXME: this forces VGA.  alternatives? */
+	cinfo->regbase = NULL;
+	cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
+
+	dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
+		board_addr, info->fix.mmio_start);
+
+	board_size = (cinfo->btype == BT_GD5480) ?
+		32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
+
+	ret = pci_request_regions(pdev, "cirrusfb");
+	if (ret < 0) {
+		dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
+			board_addr);
+		goto err_release_fb;
+	}
+#if 0 /* if the system didn't claim this region, we would... */
+	if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
+		dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
+			0xA0000L);
+		ret = -EBUSY;
+		goto err_release_regions;
+	}
+#endif
+	if (request_region(0x3C0, 32, "cirrusfb"))
+		release_io_ports = 1;
+
+	info->screen_base = ioremap(board_addr, board_size);
+	if (!info->screen_base) {
+		ret = -EIO;
+		goto err_release_legacy;
+	}
+
+	info->fix.smem_start = board_addr;
+	info->screen_size = board_size;
+	cinfo->unmap = cirrusfb_pci_unmap;
+
+	dev_info(info->device,
+		 "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
+		 info->screen_size >> 10, board_addr);
+	pci_set_drvdata(pdev, info);
+
+	ret = cirrusfb_register(info);
+	if (!ret)
+		return 0;
+
+	iounmap(info->screen_base);
+err_release_legacy:
+	if (release_io_ports)
+		release_region(0x3C0, 32);
+#if 0
+	release_mem_region(0xA0000, 65535);
+err_release_regions:
+#endif
+	pci_release_regions(pdev);
+err_release_fb:
+	if (cinfo->laguna_mmio != NULL)
+		iounmap(cinfo->laguna_mmio);
+	framebuffer_release(info);
+err_out:
+	return ret;
+}
+
+static void cirrusfb_pci_unregister(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+
+	cirrusfb_cleanup(info);
+}
+
+static struct pci_driver cirrusfb_pci_driver = {
+	.name		= "cirrusfb",
+	.id_table	= cirrusfb_pci_table,
+	.probe		= cirrusfb_pci_register,
+	.remove		= cirrusfb_pci_unregister,
+#ifdef CONFIG_PM
+#if 0
+	.suspend	= cirrusfb_pci_suspend,
+	.resume		= cirrusfb_pci_resume,
+#endif
+#endif
+};
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_ZORRO
+static int cirrusfb_zorro_register(struct zorro_dev *z,
+				   const struct zorro_device_id *ent)
+{
+	struct fb_info *info;
+	int error;
+	const struct zorrocl *zcl;
+	enum cirrus_board btype;
+	unsigned long regbase, ramsize, rambase;
+	struct cirrusfb_info *cinfo;
+
+	info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
+	if (!info) {
+		printk(KERN_ERR "cirrusfb: could not allocate memory\n");
+		return -ENOMEM;
+	}
+
+	zcl = (const struct zorrocl *)ent->driver_data;
+	btype = zcl->type;
+	regbase = zorro_resource_start(z) + zcl->regoffset;
+	ramsize = zcl->ramsize;
+	if (ramsize) {
+		rambase = zorro_resource_start(z) + zcl->ramoffset;
+		if (zorro_resource_len(z) == 64 * MB_) {
+			/* Quirk for 64 MiB Picasso IV */
+			rambase += zcl->ramoffset;
+		}
+	} else {
+		struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
+		if (!ram || !zorro_resource_len(ram)) {
+			dev_err(info->device, "No video RAM found\n");
+			error = -ENODEV;
+			goto err_release_fb;
+		}
+		rambase = zorro_resource_start(ram);
+		ramsize = zorro_resource_len(ram);
+		if (zcl->ramid2 &&
+		    (ram = zorro_find_device(zcl->ramid2, NULL))) {
+			if (zorro_resource_start(ram) != rambase + ramsize) {
+				dev_warn(info->device,
+					 "Skipping non-contiguous RAM at %pR\n",
+					 &ram->resource);
+			} else {
+				ramsize += zorro_resource_len(ram);
+			}
+		}
+	}
+
+	dev_info(info->device,
+		 "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
+		 cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
+		 rambase);
+
+	if (!zorro_request_device(z, "cirrusfb")) {
+		dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
+		error = -EBUSY;
+		goto err_release_fb;
+	}
+
+	cinfo = info->par;
+	cinfo->btype = btype;
+
+	info->fix.mmio_start = regbase;
+	cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
+					    : ZTWO_VADDR(regbase);
+	if (!cinfo->regbase) {
+		dev_err(info->device, "Cannot map registers\n");
+		error = -EIO;
+		goto err_release_dev;
+	}
+
+	info->fix.smem_start = rambase;
+	info->screen_size = ramsize;
+	info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
+					       : ZTWO_VADDR(rambase);
+	if (!info->screen_base) {
+		dev_err(info->device, "Cannot map video RAM\n");
+		error = -EIO;
+		goto err_unmap_reg;
+	}
+
+	cinfo->unmap = cirrusfb_zorro_unmap;
+
+	dev_info(info->device,
+		 "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
+		 ramsize / MB_, rambase);
+
+	/* MCLK select etc. */
+	if (cirrusfb_board_info[btype].init_sr1f)
+		vga_wseq(cinfo->regbase, CL_SEQR1F,
+			 cirrusfb_board_info[btype].sr1f);
+
+	error = cirrusfb_register(info);
+	if (error) {
+		dev_err(info->device, "Failed to register device, error %d\n",
+			error);
+		goto err_unmap_ram;
+	}
+
+	zorro_set_drvdata(z, info);
+	return 0;
+
+err_unmap_ram:
+	if (rambase > 16 * MB_)
+		iounmap(info->screen_base);
+
+err_unmap_reg:
+	if (regbase > 16 * MB_)
+		iounmap(cinfo->regbase);
+err_release_dev:
+	zorro_release_device(z);
+err_release_fb:
+	framebuffer_release(info);
+	return error;
+}
+
+void cirrusfb_zorro_unregister(struct zorro_dev *z)
+{
+	struct fb_info *info = zorro_get_drvdata(z);
+
+	cirrusfb_cleanup(info);
+	zorro_set_drvdata(z, NULL);
+}
+
+static struct zorro_driver cirrusfb_zorro_driver = {
+	.name		= "cirrusfb",
+	.id_table	= cirrusfb_zorro_table,
+	.probe		= cirrusfb_zorro_register,
+	.remove		= cirrusfb_zorro_unregister,
+};
+#endif /* CONFIG_ZORRO */
+
+#ifndef MODULE
+static int __init cirrusfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+
+		if (!strcmp(this_opt, "noaccel"))
+			noaccel = 1;
+		else if (!strncmp(this_opt, "mode:", 5))
+			mode_option = this_opt + 5;
+		else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+#endif
+
+    /*
+     *  Modularization
+     */
+
+MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
+MODULE_LICENSE("GPL");
+
+static int __init cirrusfb_init(void)
+{
+	int error = 0;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("cirrusfb", &option))
+		return -ENODEV;
+	cirrusfb_setup(option);
+#endif
+
+#ifdef CONFIG_ZORRO
+	error |= zorro_register_driver(&cirrusfb_zorro_driver);
+#endif
+#ifdef CONFIG_PCI
+	error |= pci_register_driver(&cirrusfb_pci_driver);
+#endif
+	return error;
+}
+
+static void __exit cirrusfb_exit(void)
+{
+#ifdef CONFIG_PCI
+	pci_unregister_driver(&cirrusfb_pci_driver);
+#endif
+#ifdef CONFIG_ZORRO
+	zorro_unregister_driver(&cirrusfb_zorro_driver);
+#endif
+}
+
+module_init(cirrusfb_init);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "Disable acceleration");
+
+#ifdef MODULE
+module_exit(cirrusfb_exit);
+#endif
+
+/**********************************************************************/
+/* about the following functions - I have used the same names for the */
+/* functions as Markus Wild did in his Retina driver for NetBSD as    */
+/* they just made sense for this purpose. Apart from that, I wrote    */
+/* these functions myself.					    */
+/**********************************************************************/
+
+/*** WGen() - write into one of the external/general registers ***/
+static void WGen(const struct cirrusfb_info *cinfo,
+		  int regnum, unsigned char val)
+{
+	unsigned long regofs = 0;
+
+	if (cinfo->btype == BT_PICASSO) {
+		/* Picasso II specific hack */
+/*	      if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
+		  regnum == CL_VSSM2) */
+		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
+			regofs = 0xfff;
+	}
+
+	vga_w(cinfo->regbase, regofs + regnum, val);
+}
+
+/*** RGen() - read out one of the external/general registers ***/
+static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
+{
+	unsigned long regofs = 0;
+
+	if (cinfo->btype == BT_PICASSO) {
+		/* Picasso II specific hack */
+/*	      if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
+		  regnum == CL_VSSM2) */
+		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
+			regofs = 0xfff;
+	}
+
+	return vga_r(cinfo->regbase, regofs + regnum);
+}
+
+/*** AttrOn() - turn on VideoEnable for Attribute controller ***/
+static void AttrOn(const struct cirrusfb_info *cinfo)
+{
+	assert(cinfo != NULL);
+
+	if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
+		/* if we're just in "write value" mode, write back the */
+		/* same value as before to not modify anything */
+		vga_w(cinfo->regbase, VGA_ATT_IW,
+		      vga_r(cinfo->regbase, VGA_ATT_R));
+	}
+	/* turn on video bit */
+/*      vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
+	vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
+
+	/* dummy write on Reg0 to be on "write index" mode next time */
+	vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
+}
+
+/*** WHDR() - write into the Hidden DAC register ***/
+/* as the HDR is the only extension register that requires special treatment
+ * (the other extension registers are accessible just like the "ordinary"
+ * registers of their functional group) here is a specialized routine for
+ * accessing the HDR
+ */
+static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
+{
+	unsigned char dummy;
+
+	if (is_laguna(cinfo))
+		return;
+	if (cinfo->btype == BT_PICASSO) {
+		/* Klaus' hint for correct access to HDR on some boards */
+		/* first write 0 to pixel mask (3c6) */
+		WGen(cinfo, VGA_PEL_MSK, 0x00);
+		udelay(200);
+		/* next read dummy from pixel address (3c8) */
+		dummy = RGen(cinfo, VGA_PEL_IW);
+		udelay(200);
+	}
+	/* now do the usual stuff to access the HDR */
+
+	dummy = RGen(cinfo, VGA_PEL_MSK);
+	udelay(200);
+	dummy = RGen(cinfo, VGA_PEL_MSK);
+	udelay(200);
+	dummy = RGen(cinfo, VGA_PEL_MSK);
+	udelay(200);
+	dummy = RGen(cinfo, VGA_PEL_MSK);
+	udelay(200);
+
+	WGen(cinfo, VGA_PEL_MSK, val);
+	udelay(200);
+
+	if (cinfo->btype == BT_PICASSO) {
+		/* now first reset HDR access counter */
+		dummy = RGen(cinfo, VGA_PEL_IW);
+		udelay(200);
+
+		/* and at the end, restore the mask value */
+		/* ## is this mask always 0xff? */
+		WGen(cinfo, VGA_PEL_MSK, 0xff);
+		udelay(200);
+	}
+}
+
+/*** WSFR() - write to the "special function register" (SFR) ***/
+static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
+{
+#ifdef CONFIG_ZORRO
+	assert(cinfo->regbase != NULL);
+	cinfo->SFR = val;
+	z_writeb(val, cinfo->regbase + 0x8000);
+#endif
+}
+
+/* The Picasso has a second register for switching the monitor bit */
+static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
+{
+#ifdef CONFIG_ZORRO
+	/* writing an arbitrary value to this one causes the monitor switcher */
+	/* to flip to Amiga display */
+	assert(cinfo->regbase != NULL);
+	cinfo->SFR = val;
+	z_writeb(val, cinfo->regbase + 0x9000);
+#endif
+}
+
+/*** WClut - set CLUT entry (range: 0..63) ***/
+static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
+	    unsigned char green, unsigned char blue)
+{
+	unsigned int data = VGA_PEL_D;
+
+	/* address write mode register is not translated.. */
+	vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
+
+	if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
+	    cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
+	    cinfo->btype == BT_SD64 || is_laguna(cinfo)) {
+		/* but DAC data register IS, at least for Picasso II */
+		if (cinfo->btype == BT_PICASSO)
+			data += 0xfff;
+		vga_w(cinfo->regbase, data, red);
+		vga_w(cinfo->regbase, data, green);
+		vga_w(cinfo->regbase, data, blue);
+	} else {
+		vga_w(cinfo->regbase, data, blue);
+		vga_w(cinfo->regbase, data, green);
+		vga_w(cinfo->regbase, data, red);
+	}
+}
+
+#if 0
+/*** RClut - read CLUT entry (range 0..63) ***/
+static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
+	    unsigned char *green, unsigned char *blue)
+{
+	unsigned int data = VGA_PEL_D;
+
+	vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
+
+	if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
+	    cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
+		if (cinfo->btype == BT_PICASSO)
+			data += 0xfff;
+		*red = vga_r(cinfo->regbase, data);
+		*green = vga_r(cinfo->regbase, data);
+		*blue = vga_r(cinfo->regbase, data);
+	} else {
+		*blue = vga_r(cinfo->regbase, data);
+		*green = vga_r(cinfo->regbase, data);
+		*red = vga_r(cinfo->regbase, data);
+	}
+}
+#endif
+
+/*******************************************************************
+	cirrusfb_WaitBLT()
+
+	Wait for the BitBLT engine to complete a possible earlier job
+*********************************************************************/
+
+/* FIXME: use interrupts instead */
+static void cirrusfb_WaitBLT(u8 __iomem *regbase)
+{
+	while (vga_rgfx(regbase, CL_GR31) & 0x08)
+		cpu_relax();
+}
+
+/*******************************************************************
+	cirrusfb_BitBLT()
+
+	perform accelerated "scrolling"
+********************************************************************/
+
+static void cirrusfb_set_blitter(u8 __iomem *regbase,
+			    u_short nwidth, u_short nheight,
+			    u_long nsrc, u_long ndest,
+			    u_short bltmode, u_short line_length)
+
+{
+	/* pitch: set to line_length */
+	/* dest pitch low */
+	vga_wgfx(regbase, CL_GR24, line_length & 0xff);
+	/* dest pitch hi */
+	vga_wgfx(regbase, CL_GR25, line_length >> 8);
+	/* source pitch low */
+	vga_wgfx(regbase, CL_GR26, line_length & 0xff);
+	/* source pitch hi */
+	vga_wgfx(regbase, CL_GR27, line_length >> 8);
+
+	/* BLT width: actual number of pixels - 1 */
+	/* BLT width low */
+	vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
+	/* BLT width hi */
+	vga_wgfx(regbase, CL_GR21, nwidth >> 8);
+
+	/* BLT height: actual number of lines -1 */
+	/* BLT height low */
+	vga_wgfx(regbase, CL_GR22, nheight & 0xff);
+	/* BLT width hi */
+	vga_wgfx(regbase, CL_GR23, nheight >> 8);
+
+	/* BLT destination */
+	/* BLT dest low */
+	vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
+	/* BLT dest mid */
+	vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
+	/* BLT dest hi */
+	vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
+
+	/* BLT source */
+	/* BLT src low */
+	vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
+	/* BLT src mid */
+	vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
+	/* BLT src hi */
+	vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
+
+	/* BLT mode */
+	vga_wgfx(regbase, CL_GR30, bltmode);	/* BLT mode */
+
+	/* BLT ROP: SrcCopy */
+	vga_wgfx(regbase, CL_GR32, 0x0d);	/* BLT ROP */
+
+	/* and finally: GO! */
+	vga_wgfx(regbase, CL_GR31, 0x02);	/* BLT Start/status */
+}
+
+/*******************************************************************
+	cirrusfb_BitBLT()
+
+	perform accelerated "scrolling"
+********************************************************************/
+
+static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
+			    u_short curx, u_short cury,
+			    u_short destx, u_short desty,
+			    u_short width, u_short height,
+			    u_short line_length)
+{
+	u_short nwidth = width - 1;
+	u_short nheight = height - 1;
+	u_long nsrc, ndest;
+	u_char bltmode;
+
+	bltmode = 0x00;
+	/* if source adr < dest addr, do the Blt backwards */
+	if (cury <= desty) {
+		if (cury == desty) {
+			/* if src and dest are on the same line, check x */
+			if (curx < destx)
+				bltmode |= 0x01;
+		} else
+			bltmode |= 0x01;
+	}
+	/* standard case: forward blitting */
+	nsrc = (cury * line_length) + curx;
+	ndest = (desty * line_length) + destx;
+	if (bltmode) {
+		/* this means start addresses are at the end,
+		 * counting backwards
+		 */
+		nsrc += nheight * line_length + nwidth;
+		ndest += nheight * line_length + nwidth;
+	}
+
+	cirrusfb_WaitBLT(regbase);
+
+	cirrusfb_set_blitter(regbase, nwidth, nheight,
+			    nsrc, ndest, bltmode, line_length);
+}
+
+/*******************************************************************
+	cirrusfb_RectFill()
+
+	perform accelerated rectangle fill
+********************************************************************/
+
+static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
+		     u_short x, u_short y, u_short width, u_short height,
+		     u32 fg_color, u32 bg_color, u_short line_length,
+		     u_char blitmode)
+{
+	u_long ndest = (y * line_length) + x;
+	u_char op;
+
+	cirrusfb_WaitBLT(regbase);
+
+	/* This is a ColorExpand Blt, using the */
+	/* same color for foreground and background */
+	vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color);
+	vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color);
+
+	op = 0x80;
+	if (bits_per_pixel >= 16) {
+		vga_wgfx(regbase, CL_GR10, bg_color >> 8);
+		vga_wgfx(regbase, CL_GR11, fg_color >> 8);
+		op = 0x90;
+	}
+	if (bits_per_pixel >= 24) {
+		vga_wgfx(regbase, CL_GR12, bg_color >> 16);
+		vga_wgfx(regbase, CL_GR13, fg_color >> 16);
+		op = 0xa0;
+	}
+	if (bits_per_pixel == 32) {
+		vga_wgfx(regbase, CL_GR14, bg_color >> 24);
+		vga_wgfx(regbase, CL_GR15, fg_color >> 24);
+		op = 0xb0;
+	}
+	cirrusfb_set_blitter(regbase, width - 1, height - 1,
+			    0, ndest, op | blitmode, line_length);
+}
+
+/**************************************************************************
+ * bestclock() - determine closest possible clock lower(?) than the
+ * desired pixel clock
+ **************************************************************************/
+static void bestclock(long freq, int *nom, int *den, int *div)
+{
+	int n, d;
+	long h, diff;
+
+	assert(nom != NULL);
+	assert(den != NULL);
+	assert(div != NULL);
+
+	*nom = 0;
+	*den = 0;
+	*div = 0;
+
+	if (freq < 8000)
+		freq = 8000;
+
+	diff = freq;
+
+	for (n = 32; n < 128; n++) {
+		int s = 0;
+
+		d = (14318 * n) / freq;
+		if ((d >= 7) && (d <= 63)) {
+			int temp = d;
+
+			if (temp > 31) {
+				s = 1;
+				temp >>= 1;
+			}
+			h = ((14318 * n) / temp) >> s;
+			h = h > freq ? h - freq : freq - h;
+			if (h < diff) {
+				diff = h;
+				*nom = n;
+				*den = temp;
+				*div = s;
+			}
+		}
+		d++;
+		if ((d >= 7) && (d <= 63)) {
+			if (d > 31) {
+				s = 1;
+				d >>= 1;
+			}
+			h = ((14318 * n) / d) >> s;
+			h = h > freq ? h - freq : freq - h;
+			if (h < diff) {
+				diff = h;
+				*nom = n;
+				*den = d;
+				*div = s;
+			}
+		}
+	}
+}
+
+/* -------------------------------------------------------------------------
+ *
+ * debugging functions
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifdef CIRRUSFB_DEBUG
+
+/**
+ * cirrusfb_dbg_print_regs
+ * @base: If using newmmio, the newmmio base address, otherwise %NULL
+ * @reg_class: type of registers to read: %CRT, or %SEQ
+ *
+ * DESCRIPTION:
+ * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
+ * old-style I/O ports are queried for information, otherwise MMIO is
+ * used at the given @base address to query the information.
+ */
+
+static void cirrusfb_dbg_print_regs(struct fb_info *info,
+				    caddr_t regbase,
+				    enum cirrusfb_dbg_reg_class reg_class, ...)
+{
+	va_list list;
+	unsigned char val = 0;
+	unsigned reg;
+	char *name;
+
+	va_start(list, reg_class);
+
+	name = va_arg(list, char *);
+	while (name != NULL) {
+		reg = va_arg(list, int);
+
+		switch (reg_class) {
+		case CRT:
+			val = vga_rcrt(regbase, (unsigned char) reg);
+			break;
+		case SEQ:
+			val = vga_rseq(regbase, (unsigned char) reg);
+			break;
+		default:
+			/* should never occur */
+			assert(false);
+			break;
+		}
+
+		dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
+
+		name = va_arg(list, char *);
+	}
+
+	va_end(list);
+}
+
+/**
+ * cirrusfb_dbg_reg_dump
+ * @base: If using newmmio, the newmmio base address, otherwise %NULL
+ *
+ * DESCRIPTION:
+ * Dumps a list of interesting VGA and CIRRUSFB registers.  If @base is %NULL,
+ * old-style I/O ports are queried for information, otherwise MMIO is
+ * used at the given @base address to query the information.
+ */
+
+static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
+{
+	dev_dbg(info->device, "VGA CRTC register dump:\n");
+
+	cirrusfb_dbg_print_regs(info, regbase, CRT,
+			   "CR00", 0x00,
+			   "CR01", 0x01,
+			   "CR02", 0x02,
+			   "CR03", 0x03,
+			   "CR04", 0x04,
+			   "CR05", 0x05,
+			   "CR06", 0x06,
+			   "CR07", 0x07,
+			   "CR08", 0x08,
+			   "CR09", 0x09,
+			   "CR0A", 0x0A,
+			   "CR0B", 0x0B,
+			   "CR0C", 0x0C,
+			   "CR0D", 0x0D,
+			   "CR0E", 0x0E,
+			   "CR0F", 0x0F,
+			   "CR10", 0x10,
+			   "CR11", 0x11,
+			   "CR12", 0x12,
+			   "CR13", 0x13,
+			   "CR14", 0x14,
+			   "CR15", 0x15,
+			   "CR16", 0x16,
+			   "CR17", 0x17,
+			   "CR18", 0x18,
+			   "CR22", 0x22,
+			   "CR24", 0x24,
+			   "CR26", 0x26,
+			   "CR2D", 0x2D,
+			   "CR2E", 0x2E,
+			   "CR2F", 0x2F,
+			   "CR30", 0x30,
+			   "CR31", 0x31,
+			   "CR32", 0x32,
+			   "CR33", 0x33,
+			   "CR34", 0x34,
+			   "CR35", 0x35,
+			   "CR36", 0x36,
+			   "CR37", 0x37,
+			   "CR38", 0x38,
+			   "CR39", 0x39,
+			   "CR3A", 0x3A,
+			   "CR3B", 0x3B,
+			   "CR3C", 0x3C,
+			   "CR3D", 0x3D,
+			   "CR3E", 0x3E,
+			   "CR3F", 0x3F,
+			   NULL);
+
+	dev_dbg(info->device, "\n");
+
+	dev_dbg(info->device, "VGA SEQ register dump:\n");
+
+	cirrusfb_dbg_print_regs(info, regbase, SEQ,
+			   "SR00", 0x00,
+			   "SR01", 0x01,
+			   "SR02", 0x02,
+			   "SR03", 0x03,
+			   "SR04", 0x04,
+			   "SR08", 0x08,
+			   "SR09", 0x09,
+			   "SR0A", 0x0A,
+			   "SR0B", 0x0B,
+			   "SR0D", 0x0D,
+			   "SR10", 0x10,
+			   "SR11", 0x11,
+			   "SR12", 0x12,
+			   "SR13", 0x13,
+			   "SR14", 0x14,
+			   "SR15", 0x15,
+			   "SR16", 0x16,
+			   "SR17", 0x17,
+			   "SR18", 0x18,
+			   "SR19", 0x19,
+			   "SR1A", 0x1A,
+			   "SR1B", 0x1B,
+			   "SR1C", 0x1C,
+			   "SR1D", 0x1D,
+			   "SR1E", 0x1E,
+			   "SR1F", 0x1F,
+			   NULL);
+
+	dev_dbg(info->device, "\n");
+}
+
+#endif				/* CIRRUSFB_DEBUG */
+
diff --git a/drivers/video/fbdev/clps711xfb.c b/drivers/video/fbdev/clps711xfb.c
new file mode 100644
index 000000000000..f00980607b8f
--- /dev/null
+++ b/drivers/video/fbdev/clps711xfb.c
@@ -0,0 +1,315 @@
+/*
+ *  linux/drivers/video/clps711xfb.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Framebuffer driver for the CLPS7111 and EP7212 processors.
+ */
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <linux/uaccess.h>
+
+struct fb_info	*cfb;
+
+#define CMAP_MAX_SIZE	16
+
+/*
+ * LCD AC Prescale.  This comes from the LCD panel manufacturers specifications.
+ * This determines how many clocks + 1 of CL1 before the M signal toggles.
+ * The number of lines on the display must not be divisible by this number.
+ */
+static unsigned int lcd_ac_prescale = 13;
+
+/*
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
+static int
+clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		     u_int transp, struct fb_info *info)
+{
+	unsigned int level, mask, shift, pal;
+
+	if (regno >= (1 << info->var.bits_per_pixel))
+		return 1;
+
+	/* gray = 0.30*R + 0.58*G + 0.11*B */
+	level = (red * 77 + green * 151 + blue * 28) >> 20;
+
+	/*
+	 * On an LCD, a high value is dark, while a low value is light. 
+	 * So we invert the level.
+	 *
+	 * This isn't true on all machines, so we only do it on EDB7211.
+	 *  --rmk
+	 */
+	if (machine_is_edb7211()) {
+		level = 15 - level;
+	}
+
+	shift = 4 * (regno & 7);
+	level <<= shift;
+	mask  = 15 << shift;
+	level &= mask;
+
+	regno = regno < 8 ? PALLSW : PALMSW;
+
+	pal = clps_readl(regno);
+	pal = (pal & ~mask) | level;
+	clps_writel(pal, regno);
+
+	return 0;
+}
+
+/*
+ * Validate the purposed mode.
+ */	
+static int
+clps7111fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	var->transp.msb_right	= 0;
+	var->transp.offset	= 0;
+	var->transp.length	= 0;
+	var->red.msb_right	= 0;
+	var->red.offset		= 0;
+	var->red.length		= var->bits_per_pixel;
+	var->green		= var->red;
+	var->blue		= var->red;
+
+	if (var->bits_per_pixel > 4) 
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Set the hardware state.
+ */ 
+static int 
+clps7111fb_set_par(struct fb_info *info)
+{
+	unsigned int lcdcon, syscon, pixclock;
+
+	switch (info->var.bits_per_pixel) {
+	case 1:
+		info->fix.visual = FB_VISUAL_MONO01;
+		break;
+	case 2:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 4:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+
+	info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
+
+	lcdcon = (info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel) / 128 - 1;
+	lcdcon |= ((info->var.xres_virtual / 16) - 1) << 13;
+	lcdcon |= lcd_ac_prescale << 25;
+
+	/*
+	 * Calculate pixel prescale value from the pixclock.  This is:
+	 *  36.864MHz / pixclock_mhz - 1.
+	 * However, pixclock is in picoseconds, so this ends up being:
+	 *  36864000 * pixclock_ps / 10^12 - 1
+	 * and this will overflow the 32-bit math.  We perform this as
+	 * (9 * 4096000 == 36864000):
+	 *  pixclock_ps * 9 * (4096000 / 10^12) - 1
+	 */
+	pixclock = 9 * info->var.pixclock / 244140 - 1;
+	lcdcon |= pixclock << 19;
+
+	if (info->var.bits_per_pixel == 4)
+		lcdcon |= LCDCON_GSMD;
+	if (info->var.bits_per_pixel >= 2)
+		lcdcon |= LCDCON_GSEN;
+
+	/*
+	 * LCDCON must only be changed while the LCD is disabled
+	 */
+	syscon = clps_readl(SYSCON1);
+	clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
+	clps_writel(lcdcon, LCDCON);
+	clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
+	return 0;
+}
+
+static int clps7111fb_blank(int blank, struct fb_info *info)
+{
+	/* Enable/Disable LCD controller. */
+	if (blank)
+		clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN, SYSCON1);
+	else
+		clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN, SYSCON1);
+
+	return 0;
+}
+
+static struct fb_ops clps7111fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= clps7111fb_check_var,
+	.fb_set_par	= clps7111fb_set_par,
+	.fb_setcolreg	= clps7111fb_setcolreg,
+	.fb_blank	= clps7111fb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static void clps711x_guess_lcd_params(struct fb_info *info)
+{
+	unsigned int lcdcon, syscon, size;
+	unsigned long phys_base = PAGE_OFFSET;
+	void *virt_base = (void *)PAGE_OFFSET;
+
+	info->var.xres_virtual	 = 640;
+	info->var.yres_virtual	 = 240;
+	info->var.bits_per_pixel = 4;
+	info->var.activate	 = FB_ACTIVATE_NOW;
+	info->var.height	 = -1;
+	info->var.width		 = -1;
+	info->var.pixclock	 = 93006; /* 10.752MHz pixel clock */
+
+	/*
+	 * If the LCD controller is already running, decode the values
+	 * in LCDCON to xres/yres/bpp/pixclock/acprescale
+	 */
+	syscon = clps_readl(SYSCON1);
+	if (syscon & SYSCON1_LCDEN) {
+		lcdcon = clps_readl(LCDCON);
+
+		/*
+		 * Decode GSMD and GSEN bits to bits per pixel
+		 */
+		switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
+		case LCDCON_GSMD | LCDCON_GSEN:
+			info->var.bits_per_pixel = 4;
+			break;
+
+		case LCDCON_GSEN:
+			info->var.bits_per_pixel = 2;
+			break;
+
+		default:
+			info->var.bits_per_pixel = 1;
+			break;
+		}
+
+		/*
+		 * Decode xres/yres
+		 */
+		info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
+		info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
+					  (info->var.xres_virtual *
+					   info->var.bits_per_pixel);
+
+		/*
+		 * Calculate pixclock
+		 */
+		info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
+
+		/*
+		 * Grab AC prescale
+		 */
+		lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
+	}
+
+	info->var.xres = info->var.xres_virtual;
+	info->var.yres = info->var.yres_virtual;
+	info->var.grayscale = info->var.bits_per_pixel > 1;
+
+	size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
+
+	/*
+	 * Might be worth checking to see if we can use the on-board
+	 * RAM if size here...
+	 * CLPS7110 - no on-board SRAM
+	 * EP7212   - 38400 bytes
+	 */
+	if (size <= 38400) {
+		printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
+	}
+
+	if ((syscon & SYSCON1_LCDEN) == 0) {
+		/*
+		 * The display isn't running.  Ensure that
+		 * the display memory is empty.
+		 */
+		memset(virt_base, 0, size);
+	}
+
+	info->screen_base    = virt_base;
+	info->fix.smem_start = phys_base;
+	info->fix.smem_len   = PAGE_ALIGN(size);
+	info->fix.type       = FB_TYPE_PACKED_PIXELS;
+}
+
+static int clps711x_fb_probe(struct platform_device *pdev)
+{
+	int err = -ENOMEM;
+
+	if (fb_get_options("clps711xfb", NULL))
+		return -ENODEV;
+
+	cfb = kzalloc(sizeof(*cfb), GFP_KERNEL);
+	if (!cfb)
+		goto out;
+
+	strcpy(cfb->fix.id, "clps711x");
+
+	cfb->fbops		= &clps7111fb_ops;
+	cfb->flags		= FBINFO_DEFAULT;
+
+	clps711x_guess_lcd_params(cfb);
+
+	fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
+
+	err = register_framebuffer(cfb);
+
+out:	return err;
+}
+
+static int clps711x_fb_remove(struct platform_device *pdev)
+{
+	unregister_framebuffer(cfb);
+	kfree(cfb);
+
+	return 0;
+}
+
+static struct platform_driver clps711x_fb_driver = {
+	.driver	= {
+		.name	= "video-clps711x",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= clps711x_fb_probe,
+	.remove	= clps711x_fb_remove,
+};
+module_platform_driver(clps711x_fb_driver);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("CLPS711X framebuffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/cobalt_lcdfb.c b/drivers/video/fbdev/cobalt_lcdfb.c
new file mode 100644
index 000000000000..d5533f4db1cf
--- /dev/null
+++ b/drivers/video/fbdev/cobalt_lcdfb.c
@@ -0,0 +1,401 @@
+/*
+ *  Cobalt/SEAD3 LCD frame buffer driver.
+ *
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
+ *  Copyright (C) 2012  MIPS Technologies, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+
+/*
+ * Cursor position address
+ * \X  0    1    2  ...  14   15
+ * Y+----+----+----+---+----+----+
+ * 0|0x00|0x01|0x02|...|0x0e|0x0f|
+ *  +----+----+----+---+----+----+
+ * 1|0x40|0x41|0x42|...|0x4e|0x4f|
+ *  +----+----+----+---+----+----+
+ */
+#define LCD_DATA_REG_OFFSET	0x10
+#define LCD_XRES_MAX		16
+#define LCD_YRES_MAX		2
+#define LCD_CHARS_MAX		32
+
+#define LCD_CLEAR		0x01
+#define LCD_CURSOR_MOVE_HOME	0x02
+#define LCD_RESET		0x06
+#define LCD_OFF			0x08
+#define LCD_CURSOR_OFF		0x0c
+#define LCD_CURSOR_BLINK_OFF	0x0e
+#define LCD_CURSOR_ON		0x0f
+#define LCD_ON			LCD_CURSOR_ON
+#define LCD_CURSOR_MOVE_LEFT	0x10
+#define LCD_CURSOR_MOVE_RIGHT	0x14
+#define LCD_DISPLAY_LEFT	0x18
+#define LCD_DISPLAY_RIGHT	0x1c
+#define LCD_PRERESET		0x3f	/* execute 4 times continuously */
+#define LCD_BUSY		0x80
+
+#define LCD_GRAPHIC_MODE	0x40
+#define LCD_TEXT_MODE		0x80
+#define LCD_CUR_POS_MASK	0x7f
+
+#define LCD_CUR_POS(x)		((x) & LCD_CUR_POS_MASK)
+#define LCD_TEXT_POS(x)		((x) | LCD_TEXT_MODE)
+
+#ifdef CONFIG_MIPS_COBALT
+static inline void lcd_write_control(struct fb_info *info, u8 control)
+{
+	writel((u32)control << 24, info->screen_base);
+}
+
+static inline u8 lcd_read_control(struct fb_info *info)
+{
+	return readl(info->screen_base) >> 24;
+}
+
+static inline void lcd_write_data(struct fb_info *info, u8 data)
+{
+	writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET);
+}
+
+static inline u8 lcd_read_data(struct fb_info *info)
+{
+	return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
+}
+#else
+
+#define LCD_CTL			0x00
+#define LCD_DATA		0x08
+#define CPLD_STATUS		0x10
+#define CPLD_DATA		0x18
+
+static inline void cpld_wait(struct fb_info *info)
+{
+	do {
+	} while (readl(info->screen_base + CPLD_STATUS) & 1);
+}
+
+static inline void lcd_write_control(struct fb_info *info, u8 control)
+{
+	cpld_wait(info);
+	writel(control, info->screen_base + LCD_CTL);
+}
+
+static inline u8 lcd_read_control(struct fb_info *info)
+{
+	cpld_wait(info);
+	readl(info->screen_base + LCD_CTL);
+	cpld_wait(info);
+	return readl(info->screen_base + CPLD_DATA) & 0xff;
+}
+
+static inline void lcd_write_data(struct fb_info *info, u8 data)
+{
+	cpld_wait(info);
+	writel(data, info->screen_base + LCD_DATA);
+}
+
+static inline u8 lcd_read_data(struct fb_info *info)
+{
+	cpld_wait(info);
+	readl(info->screen_base + LCD_DATA);
+	cpld_wait(info);
+	return readl(info->screen_base + CPLD_DATA) & 0xff;
+}
+#endif
+
+static int lcd_busy_wait(struct fb_info *info)
+{
+	u8 val = 0;
+	int timeout = 10, retval = 0;
+
+	do {
+		val = lcd_read_control(info);
+		val &= LCD_BUSY;
+		if (val != LCD_BUSY)
+			break;
+
+		if (msleep_interruptible(1))
+			return -EINTR;
+
+		timeout--;
+	} while (timeout);
+
+	if (val == LCD_BUSY)
+		retval = -EBUSY;
+
+	return retval;
+}
+
+static void lcd_clear(struct fb_info *info)
+{
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		udelay(150);
+
+		lcd_write_control(info, LCD_PRERESET);
+	}
+
+	udelay(150);
+
+	lcd_write_control(info, LCD_CLEAR);
+
+	udelay(150);
+
+	lcd_write_control(info, LCD_RESET);
+}
+
+static struct fb_fix_screeninfo cobalt_lcdfb_fix = {
+	.id		= "cobalt-lcd",
+	.type		= FB_TYPE_TEXT,
+	.type_aux	= FB_AUX_TEXT_MDA,
+	.visual		= FB_VISUAL_MONO01,
+	.line_length	= LCD_XRES_MAX,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	char src[LCD_CHARS_MAX];
+	unsigned long pos;
+	int len, retval = 0;
+
+	pos = *ppos;
+	if (pos >= LCD_CHARS_MAX || count == 0)
+		return 0;
+
+	if (count > LCD_CHARS_MAX)
+		count = LCD_CHARS_MAX;
+
+	if (pos + count > LCD_CHARS_MAX)
+		count = LCD_CHARS_MAX - pos;
+
+	for (len = 0; len < count; len++) {
+		retval = lcd_busy_wait(info);
+		if (retval < 0)
+			break;
+
+		lcd_write_control(info, LCD_TEXT_POS(pos));
+
+		retval = lcd_busy_wait(info);
+		if (retval < 0)
+			break;
+
+		src[len] = lcd_read_data(info);
+		if (pos == 0x0f)
+			pos = 0x40;
+		else
+			pos++;
+	}
+
+	if (retval < 0 && signal_pending(current))
+		return -ERESTARTSYS;
+
+	if (copy_to_user(buf, src, len))
+		return -EFAULT;
+
+	*ppos += len;
+
+	return len;
+}
+
+static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
+				  size_t count, loff_t *ppos)
+{
+	char dst[LCD_CHARS_MAX];
+	unsigned long pos;
+	int len, retval = 0;
+
+	pos = *ppos;
+	if (pos >= LCD_CHARS_MAX || count == 0)
+		return 0;
+
+	if (count > LCD_CHARS_MAX)
+		count = LCD_CHARS_MAX;
+
+	if (pos + count > LCD_CHARS_MAX)
+		count = LCD_CHARS_MAX - pos;
+
+	if (copy_from_user(dst, buf, count))
+		return -EFAULT;
+
+	for (len = 0; len < count; len++) {
+		retval = lcd_busy_wait(info);
+		if (retval < 0)
+			break;
+
+		lcd_write_control(info, LCD_TEXT_POS(pos));
+
+		retval = lcd_busy_wait(info);
+		if (retval < 0)
+			break;
+
+		lcd_write_data(info, dst[len]);
+		if (pos == 0x0f)
+			pos = 0x40;
+		else
+			pos++;
+	}
+
+	if (retval < 0 && signal_pending(current))
+		return -ERESTARTSYS;
+
+	*ppos += len;
+
+	return len;
+}
+
+static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info)
+{
+	int retval;
+
+	retval = lcd_busy_wait(info);
+	if (retval < 0)
+		return retval;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		lcd_write_control(info, LCD_ON);
+		break;
+	default:
+		lcd_write_control(info, LCD_OFF);
+		break;
+	}
+
+	return 0;
+}
+
+static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	u32 x, y;
+	int retval;
+
+	switch (cursor->set) {
+	case FB_CUR_SETPOS:
+		x = cursor->image.dx;
+		y = cursor->image.dy;
+		if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX)
+			return -EINVAL;
+
+		retval = lcd_busy_wait(info);
+		if (retval < 0)
+			return retval;
+
+		lcd_write_control(info,
+				  LCD_TEXT_POS(info->fix.line_length * y + x));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	retval = lcd_busy_wait(info);
+	if (retval < 0)
+		return retval;
+
+	if (cursor->enable)
+		lcd_write_control(info, LCD_CURSOR_ON);
+	else
+		lcd_write_control(info, LCD_CURSOR_OFF);
+
+	return 0;
+}
+
+static struct fb_ops cobalt_lcd_fbops = {
+	.owner		= THIS_MODULE,
+	.fb_read	= cobalt_lcdfb_read,
+	.fb_write	= cobalt_lcdfb_write,
+	.fb_blank	= cobalt_lcdfb_blank,
+	.fb_cursor	= cobalt_lcdfb_cursor,
+};
+
+static int cobalt_lcdfb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	struct resource *res;
+	int retval;
+
+	info = framebuffer_alloc(0, &dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res) {
+		framebuffer_release(info);
+		return -EBUSY;
+	}
+
+	info->screen_size = resource_size(res);
+	info->screen_base = devm_ioremap(&dev->dev, res->start,
+					 info->screen_size);
+	info->fbops = &cobalt_lcd_fbops;
+	info->fix = cobalt_lcdfb_fix;
+	info->fix.smem_start = res->start;
+	info->fix.smem_len = info->screen_size;
+	info->pseudo_palette = NULL;
+	info->par = NULL;
+	info->flags = FBINFO_DEFAULT;
+
+	retval = register_framebuffer(info);
+	if (retval < 0) {
+		framebuffer_release(info);
+		return retval;
+	}
+
+	platform_set_drvdata(dev, info);
+
+	lcd_clear(info);
+
+	fb_info(info, "Cobalt server LCD frame buffer device\n");
+
+	return 0;
+}
+
+static int cobalt_lcdfb_remove(struct platform_device *dev)
+{
+	struct fb_info *info;
+
+	info = platform_get_drvdata(dev);
+	if (info) {
+		unregister_framebuffer(info);
+		framebuffer_release(info);
+	}
+
+	return 0;
+}
+
+static struct platform_driver cobalt_lcdfb_driver = {
+	.probe	= cobalt_lcdfb_probe,
+	.remove	= cobalt_lcdfb_remove,
+	.driver	= {
+		.name	= "cobalt-lcd",
+		.owner	= THIS_MODULE,
+	},
+};
+module_platform_driver(cobalt_lcdfb_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yoichi Yuasa");
+MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver");
diff --git a/drivers/video/fbdev/controlfb.c b/drivers/video/fbdev/controlfb.c
new file mode 100644
index 000000000000..fdadef979238
--- /dev/null
+++ b/drivers/video/fbdev/controlfb.c
@@ -0,0 +1,1084 @@
+/*
+ *  controlfb.c -- frame buffer device for the PowerMac 'control' display
+ *
+ *  Created 12 July 1998 by Dan Jacobowitz <dan@debian.org>
+ *  Copyright (C) 1998 Dan Jacobowitz
+ *  Copyright (C) 2001 Takashi Oe
+ *
+ *  Mmap code by Michel Lanners <mlan@cpu.lu>
+ *
+ *  Frame buffer structure from:
+ *    drivers/video/chipsfb.c -- frame buffer device for
+ *    Chips & Technologies 65550 chip.
+ *
+ *    Copyright (C) 1998 Paul Mackerras
+ *
+ *    This file is derived from the Powermac "chips" driver:
+ *    Copyright (C) 1997 Fabio Riccardi.
+ *    And from the frame buffer device for Open Firmware-initialized devices:
+ *    Copyright (C) 1997 Geert Uytterhoeven.
+ *
+ *  Hardware information from:
+ *    control.c: Console support for PowerMac "control" display adaptor.
+ *    Copyright (C) 1996 Paul Mackerras
+ *
+ *  Updated to 2.5 framebuffer API by Ben Herrenschmidt
+ *  <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>,
+ *  and James Simmons <jsimmons@infradead.org>.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/nvram.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pgtable.h>
+#include <asm/btext.h>
+
+#include "macmodes.h"
+#include "controlfb.h"
+
+struct fb_par_control {
+	int	vmode, cmode;
+	int	xres, yres;
+	int	vxres, vyres;
+	int	xoffset, yoffset;
+	int	pitch;
+	struct control_regvals	regvals;
+	unsigned long sync;
+	unsigned char ctrl;
+};
+
+#define DIRTY(z) ((x)->z != (y)->z)
+#define DIRTY_CMAP(z) (memcmp(&((x)->z), &((y)->z), sizeof((y)->z)))
+static inline int PAR_EQUAL(struct fb_par_control *x, struct fb_par_control *y)
+{
+	int i, results;
+
+	results = 1;
+	for (i = 0; i < 3; i++)
+		results &= !DIRTY(regvals.clock_params[i]);
+	if (!results)
+		return 0;
+	for (i = 0; i < 16; i++)
+		results &= !DIRTY(regvals.regs[i]);
+	if (!results)
+		return 0;
+	return (!DIRTY(cmode) && !DIRTY(xres) && !DIRTY(yres)
+		&& !DIRTY(vxres) && !DIRTY(vyres));
+}
+static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninfo *y)
+{
+	return (!DIRTY(bits_per_pixel) && !DIRTY(xres)
+		&& !DIRTY(yres) && !DIRTY(xres_virtual)
+		&& !DIRTY(yres_virtual)
+		&& !DIRTY_CMAP(red) && !DIRTY_CMAP(green) && !DIRTY_CMAP(blue));
+}
+
+struct fb_info_control {
+	struct fb_info		info;
+	struct fb_par_control	par;
+	u32			pseudo_palette[16];
+		
+	struct cmap_regs	__iomem *cmap_regs;
+	unsigned long		cmap_regs_phys;
+	
+	struct control_regs	__iomem *control_regs;
+	unsigned long		control_regs_phys;
+	unsigned long		control_regs_size;
+	
+	__u8			__iomem *frame_buffer;
+	unsigned long		frame_buffer_phys;
+	unsigned long		fb_orig_base;
+	unsigned long		fb_orig_size;
+
+	int			control_use_bank2;
+	unsigned long		total_vram;
+	unsigned char		vram_attr;
+};
+
+/* control register access macro */
+#define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->REG).r))
+
+
+/******************** Prototypes for exported functions ********************/
+/*
+ * struct fb_ops
+ */
+static int controlfb_pan_display(struct fb_var_screeninfo *var,
+	struct fb_info *info);
+static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+	u_int transp, struct fb_info *info);
+static int controlfb_blank(int blank_mode, struct fb_info *info);
+static int controlfb_mmap(struct fb_info *info,
+	struct vm_area_struct *vma);
+static int controlfb_set_par (struct fb_info *info);
+static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
+
+/******************** Prototypes for internal functions **********************/
+
+static void set_control_clock(unsigned char *params);
+static int init_control(struct fb_info_control *p);
+static void control_set_hardware(struct fb_info_control *p,
+	struct fb_par_control *par);
+static int control_of_init(struct device_node *dp);
+static void find_vram_size(struct fb_info_control *p);
+static int read_control_sense(struct fb_info_control *p);
+static int calc_clock_params(unsigned long clk, unsigned char *param);
+static int control_var_to_par(struct fb_var_screeninfo *var,
+	struct fb_par_control *par, const struct fb_info *fb_info);
+static inline void control_par_to_var(struct fb_par_control *par,
+	struct fb_var_screeninfo *var);
+static void control_init_info(struct fb_info *info, struct fb_info_control *p);
+static void control_cleanup(void);
+
+
+/************************** Internal variables *******************************/
+
+static struct fb_info_control *control_fb;
+
+static int default_vmode __initdata = VMODE_NVRAM;
+static int default_cmode __initdata = CMODE_NVRAM;
+
+
+static struct fb_ops controlfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= controlfb_check_var,
+	.fb_set_par	= controlfb_set_par,
+	.fb_setcolreg	= controlfb_setcolreg,
+	.fb_pan_display = controlfb_pan_display,
+	.fb_blank	= controlfb_blank,
+	.fb_mmap	= controlfb_mmap,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+
+/********************  The functions for controlfb_ops ********************/
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	struct device_node *dp;
+	int ret = -ENXIO;
+
+	dp = of_find_node_by_name(NULL, "control");
+	if (dp != 0 && !control_of_init(dp))
+		ret = 0;
+	of_node_put(dp);
+
+	return ret;
+}
+
+void cleanup_module(void)
+{
+	control_cleanup();
+}
+#endif
+
+/*
+ * Checks a var structure
+ */
+static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct fb_par_control par;
+	int err;
+
+	err = control_var_to_par(var, &par, info);
+	if (err)
+		return err;	
+	control_par_to_var(&par, var);
+
+	return 0;
+}
+
+/*
+ * Applies current var to display
+ */
+static int controlfb_set_par (struct fb_info *info)
+{
+	struct fb_info_control *p = (struct fb_info_control *) info;
+	struct fb_par_control par;
+	int err;
+
+	if((err = control_var_to_par(&info->var, &par, info))) {
+		printk (KERN_ERR "controlfb_set_par: error calling"
+				 " control_var_to_par: %d.\n", err);
+		return err;
+	}
+	
+	control_set_hardware(p, &par);
+
+	info->fix.visual = (p->par.cmode == CMODE_8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	info->fix.line_length = p->par.pitch;
+	info->fix.xpanstep = 32 >> p->par.cmode;
+	info->fix.ypanstep = 1;
+
+	return 0;
+}
+
+/*
+ * Set screen start address according to var offset values
+ */
+static inline void set_screen_start(int xoffset, int yoffset,
+	struct fb_info_control *p)
+{
+	struct fb_par_control *par = &p->par;
+
+	par->xoffset = xoffset;
+	par->yoffset = yoffset;
+	out_le32(CNTRL_REG(p,start_addr),
+		 par->yoffset * par->pitch + (par->xoffset << par->cmode));
+}
+
+
+static int controlfb_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	unsigned int xoffset, hstep;
+	struct fb_info_control *p = (struct fb_info_control *)info;
+	struct fb_par_control *par = &p->par;
+
+	/*
+	 * make sure start addr will be 32-byte aligned
+	 */
+	hstep = 0x1f >> par->cmode;
+	xoffset = (var->xoffset + hstep) & ~hstep;
+
+	if (xoffset+par->xres > par->vxres ||
+	    var->yoffset+par->yres > par->vyres)
+		return -EINVAL;
+
+	set_screen_start(xoffset, var->yoffset, p);
+
+	return 0;
+}
+
+
+/*
+ * Private mmap since we want to have a different caching on the framebuffer
+ * for controlfb.
+ * Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
+ */
+static int controlfb_mmap(struct fb_info *info,
+                       struct vm_area_struct *vma)
+{
+	unsigned long mmio_pgoff;
+	unsigned long start;
+	u32 len;
+
+	start = info->fix.smem_start;
+	len = info->fix.smem_len;
+	mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+	if (vma->vm_pgoff >= mmio_pgoff) {
+		if (info->var.accel_flags)
+			return -EINVAL;
+		vma->vm_pgoff -= mmio_pgoff;
+		start = info->fix.mmio_start;
+		len = info->fix.mmio_len;
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	} else {
+		/* framebuffer */
+		vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
+	}
+
+	return vm_iomap_memory(vma, start, len);
+}
+
+static int controlfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct fb_info_control *p = (struct fb_info_control *) info;
+	unsigned ctrl;
+
+	ctrl = ld_le32(CNTRL_REG(p,ctrl));
+	if (blank_mode > 0)
+		switch (blank_mode) {
+		case FB_BLANK_VSYNC_SUSPEND:
+			ctrl &= ~3;
+			break;
+		case FB_BLANK_HSYNC_SUSPEND:
+			ctrl &= ~0x30;
+			break;
+		case FB_BLANK_POWERDOWN:
+			ctrl &= ~0x33;
+			/* fall through */
+		case FB_BLANK_NORMAL:
+			ctrl |= 0x400;
+			break;
+		default:
+			break;
+		}
+	else {
+		ctrl &= ~0x400;
+		ctrl |= 0x33;
+	}
+	out_le32(CNTRL_REG(p,ctrl), ctrl);
+
+	return 0;
+}
+
+static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info)
+{
+	struct fb_info_control *p = (struct fb_info_control *) info;
+	__u8 r, g, b;
+
+	if (regno > 255)
+		return 1;
+
+	r = red >> 8;
+	g = green >> 8;
+	b = blue >> 8;
+
+	out_8(&p->cmap_regs->addr, regno);	/* tell clut what addr to fill	*/
+	out_8(&p->cmap_regs->lut, r);		/* send one color channel at	*/
+	out_8(&p->cmap_regs->lut, g);		/* a time...			*/
+	out_8(&p->cmap_regs->lut, b);
+
+	if (regno < 16) {
+		int i;
+		switch (p->par.cmode) {
+		case CMODE_16:
+			p->pseudo_palette[regno] =
+			    (regno << 10) | (regno << 5) | regno;
+			break;
+		case CMODE_32:
+			i = (regno << 8) | regno;
+			p->pseudo_palette[regno] = (i << 16) | i;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+
+/********************  End of controlfb_ops implementation  ******************/
+
+
+
+static void set_control_clock(unsigned char *params)
+{
+#ifdef CONFIG_ADB_CUDA
+	struct adb_request req;
+	int i;
+
+	for (i = 0; i < 3; ++i) {
+		cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
+			     0x50, i + 1, params[i]);
+		while (!req.complete)
+			cuda_poll();
+	}
+#endif	
+}
+
+
+/*
+ * finish off the driver initialization and register
+ */
+static int __init init_control(struct fb_info_control *p)
+{
+	int full, sense, vmode, cmode, vyres;
+	struct fb_var_screeninfo var;
+	int rc;
+	
+	printk(KERN_INFO "controlfb: ");
+
+	full = p->total_vram == 0x400000;
+
+	/* Try to pick a video mode out of NVRAM if we have one. */
+#ifdef CONFIG_NVRAM
+	if (default_cmode == CMODE_NVRAM) {
+		cmode = nvram_read_byte(NV_CMODE);
+		if(cmode < CMODE_8 || cmode > CMODE_32)
+			cmode = CMODE_8;
+	} else
+#endif
+		cmode=default_cmode;
+#ifdef CONFIG_NVRAM
+	if (default_vmode == VMODE_NVRAM) {
+		vmode = nvram_read_byte(NV_VMODE);
+		if (vmode < 1 || vmode > VMODE_MAX ||
+		    control_mac_modes[vmode - 1].m[full] < cmode) {
+			sense = read_control_sense(p);
+			printk("Monitor sense value = 0x%x, ", sense);
+			vmode = mac_map_monitor_sense(sense);
+			if (control_mac_modes[vmode - 1].m[full] < cmode)
+				vmode = VMODE_640_480_60;
+		}
+	} else
+#endif
+	{
+		vmode=default_vmode;
+		if (control_mac_modes[vmode - 1].m[full] < cmode) {
+			if (cmode > CMODE_8)
+				cmode--;
+			else
+				vmode = VMODE_640_480_60;
+		}
+	}
+
+	/* Initialize info structure */
+	control_init_info(&p->info, p);
+
+	/* Setup default var */
+	if (mac_vmode_to_var(vmode, cmode, &var) < 0) {
+		/* This shouldn't happen! */
+		printk("mac_vmode_to_var(%d, %d,) failed\n", vmode, cmode);
+try_again:
+		vmode = VMODE_640_480_60;
+		cmode = CMODE_8;
+		if (mac_vmode_to_var(vmode, cmode, &var) < 0) {
+			printk(KERN_ERR "controlfb: mac_vmode_to_var() failed\n");
+			return -ENXIO;
+		}
+		printk(KERN_INFO "controlfb: ");
+	}
+	printk("using video mode %d and color mode %d.\n", vmode, cmode);
+
+	vyres = (p->total_vram - CTRLFB_OFF) / (var.xres << cmode);
+	if (vyres > var.yres)
+		var.yres_virtual = vyres;
+
+	/* Apply default var */
+	var.activate = FB_ACTIVATE_NOW;
+	rc = fb_set_var(&p->info, &var);
+	if (rc && (vmode != VMODE_640_480_60 || cmode != CMODE_8))
+		goto try_again;
+
+	/* Register with fbdev layer */
+	if (register_framebuffer(&p->info) < 0)
+		return -ENXIO;
+
+	fb_info(&p->info, "control display adapter\n");
+
+	return 0;
+}
+
+#define RADACAL_WRITE(a,d) \
+	out_8(&p->cmap_regs->addr, (a)); \
+	out_8(&p->cmap_regs->dat,   (d))
+
+/* Now how about actually saying, Make it so! */
+/* Some things in here probably don't need to be done each time. */
+static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par)
+{
+	struct control_regvals	*r;
+	volatile struct preg	__iomem *rp;
+	int			i, cmode;
+
+	if (PAR_EQUAL(&p->par, par)) {
+		/*
+		 * check if only xoffset or yoffset differs.
+		 * this prevents flickers in typical VT switch case.
+		 */
+		if (p->par.xoffset != par->xoffset ||
+		    p->par.yoffset != par->yoffset)
+			set_screen_start(par->xoffset, par->yoffset, p);
+			
+		return;
+	}
+	
+	p->par = *par;
+	cmode = p->par.cmode;
+	r = &par->regvals;
+	
+	/* Turn off display */
+	out_le32(CNTRL_REG(p,ctrl), 0x400 | par->ctrl);
+	
+	set_control_clock(r->clock_params);
+	
+	RADACAL_WRITE(0x20, r->radacal_ctrl);
+	RADACAL_WRITE(0x21, p->control_use_bank2 ? 0 : 1);
+	RADACAL_WRITE(0x10, 0);
+	RADACAL_WRITE(0x11, 0);
+
+	rp = &p->control_regs->vswin;
+	for (i = 0; i < 16; ++i, ++rp)
+		out_le32(&rp->r, r->regs[i]);
+	
+	out_le32(CNTRL_REG(p,pitch), par->pitch);
+	out_le32(CNTRL_REG(p,mode), r->mode);
+	out_le32(CNTRL_REG(p,vram_attr), p->vram_attr);
+	out_le32(CNTRL_REG(p,start_addr), par->yoffset * par->pitch
+		 + (par->xoffset << cmode));
+	out_le32(CNTRL_REG(p,rfrcnt), 0x1e5);
+	out_le32(CNTRL_REG(p,intr_ena), 0);
+
+	/* Turn on display */
+	out_le32(CNTRL_REG(p,ctrl), par->ctrl);
+
+#ifdef CONFIG_BOOTX_TEXT
+	btext_update_display(p->frame_buffer_phys + CTRLFB_OFF,
+			     p->par.xres, p->par.yres,
+			     (cmode == CMODE_32? 32: cmode == CMODE_16? 16: 8),
+			     p->par.pitch);
+#endif /* CONFIG_BOOTX_TEXT */
+}
+
+
+/*
+ * Parse user specified options (`video=controlfb:')
+ */
+static void __init control_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "vmode:", 6)) {
+			int vmode = simple_strtoul(this_opt+6, NULL, 0);
+			if (vmode > 0 && vmode <= VMODE_MAX &&
+			    control_mac_modes[vmode - 1].m[1] >= 0)
+				default_vmode = vmode;
+		} else if (!strncmp(this_opt, "cmode:", 6)) {
+			int depth = simple_strtoul(this_opt+6, NULL, 0);
+			switch (depth) {
+			 case CMODE_8:
+			 case CMODE_16:
+			 case CMODE_32:
+			 	default_cmode = depth;
+			 	break;
+			 case 8:
+				default_cmode = CMODE_8;
+				break;
+			 case 15:
+			 case 16:
+				default_cmode = CMODE_16;
+				break;
+			 case 24:
+			 case 32:
+				default_cmode = CMODE_32;
+				break;
+			}
+		}
+	}
+}
+
+static int __init control_init(void)
+{
+	struct device_node *dp;
+	char *option = NULL;
+	int ret = -ENXIO;
+
+	if (fb_get_options("controlfb", &option))
+		return -ENODEV;
+	control_setup(option);
+
+	dp = of_find_node_by_name(NULL, "control");
+	if (dp != 0 && !control_of_init(dp))
+		ret = 0;
+	of_node_put(dp);
+
+	return ret;
+}
+
+module_init(control_init);
+
+/* Work out which banks of VRAM we have installed. */
+/* danj: I guess the card just ignores writes to nonexistant VRAM... */
+
+static void __init find_vram_size(struct fb_info_control *p)
+{
+	int bank1, bank2;
+
+	/*
+	 * Set VRAM in 2MB (bank 1) mode
+	 * VRAM Bank 2 will be accessible through offset 0x600000 if present
+	 * and VRAM Bank 1 will not respond at that offset even if present
+	 */
+	out_le32(CNTRL_REG(p,vram_attr), 0x31);
+
+	out_8(&p->frame_buffer[0x600000], 0xb3);
+	out_8(&p->frame_buffer[0x600001], 0x71);
+	asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0x600000])
+					: "memory" );
+	mb();
+	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000])
+					: "memory" );
+	mb();
+
+	bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xb3)
+		&& (in_8(&p->frame_buffer[0x600001]) == 0x71);
+
+	/*
+	 * Set VRAM in 2MB (bank 2) mode
+	 * VRAM Bank 1 will be accessible through offset 0x000000 if present
+	 * and VRAM Bank 2 will not respond at that offset even if present
+	 */
+	out_le32(CNTRL_REG(p,vram_attr), 0x39);
+
+	out_8(&p->frame_buffer[0], 0x5a);
+	out_8(&p->frame_buffer[1], 0xc7);
+	asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0])
+					: "memory" );
+	mb();
+	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0])
+					: "memory" );
+	mb();
+
+	bank1 = (in_8(&p->frame_buffer[0]) == 0x5a)
+		&& (in_8(&p->frame_buffer[1]) == 0xc7);
+
+	if (bank2) {
+		if (!bank1) {
+			/*
+			 * vram bank 2 only
+			 */
+			p->control_use_bank2 = 1;
+			p->vram_attr = 0x39;
+			p->frame_buffer += 0x600000;
+			p->frame_buffer_phys += 0x600000;
+		} else {
+			/*
+			 * 4 MB vram
+			 */
+			p->vram_attr = 0x51;
+		}
+	} else {
+		/*
+		 * vram bank 1 only
+		 */
+		p->vram_attr = 0x31;
+	}
+
+        p->total_vram = (bank1 + bank2) * 0x200000;
+
+	printk(KERN_INFO "controlfb: VRAM Total = %dMB "
+			"(%dMB @ bank 1, %dMB @ bank 2)\n",
+			(bank1 + bank2) << 1, bank1 << 1, bank2 << 1);
+}
+
+
+/*
+ * find "control" and initialize
+ */
+static int __init control_of_init(struct device_node *dp)
+{
+	struct fb_info_control	*p;
+	struct resource		fb_res, reg_res;
+
+	if (control_fb) {
+		printk(KERN_ERR "controlfb: only one control is supported\n");
+		return -ENXIO;
+	}
+
+	if (of_pci_address_to_resource(dp, 2, &fb_res) ||
+	    of_pci_address_to_resource(dp, 1, &reg_res)) {
+		printk(KERN_ERR "can't get 2 addresses for control\n");
+		return -ENXIO;
+	}
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (p == 0)
+		return -ENXIO;
+	control_fb = p;	/* save it for cleanups */
+
+	/* Map in frame buffer and registers */
+	p->fb_orig_base = fb_res.start;
+	p->fb_orig_size = resource_size(&fb_res);
+	/* use the big-endian aperture (??) */
+	p->frame_buffer_phys = fb_res.start + 0x800000;
+	p->control_regs_phys = reg_res.start;
+	p->control_regs_size = resource_size(&reg_res);
+
+	if (!p->fb_orig_base ||
+	    !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {
+		p->fb_orig_base = 0;
+		goto error_out;
+	}
+	/* map at most 8MB for the frame buffer */
+	p->frame_buffer = __ioremap(p->frame_buffer_phys, 0x800000,
+				    _PAGE_WRITETHRU);
+
+	if (!p->control_regs_phys ||
+	    !request_mem_region(p->control_regs_phys, p->control_regs_size,
+	    "controlfb regs")) {
+		p->control_regs_phys = 0;
+		goto error_out;
+	}
+	p->control_regs = ioremap(p->control_regs_phys, p->control_regs_size);
+
+	p->cmap_regs_phys = 0xf301b000;	 /* XXX not in prom? */
+	if (!request_mem_region(p->cmap_regs_phys, 0x1000, "controlfb cmap")) {
+		p->cmap_regs_phys = 0;
+		goto error_out;
+	}
+	p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
+
+	if (!p->cmap_regs || !p->control_regs || !p->frame_buffer)
+		goto error_out;
+
+	find_vram_size(p);
+	if (!p->total_vram)
+		goto error_out;
+
+	if (init_control(p) < 0)
+		goto error_out;
+
+	return 0;
+
+error_out:
+	control_cleanup();
+	return -ENXIO;
+}
+
+/*
+ * Get the monitor sense value.
+ * Note that this can be called before calibrate_delay,
+ * so we can't use udelay.
+ */
+static int read_control_sense(struct fb_info_control *p)
+{
+	int sense;
+
+	out_le32(CNTRL_REG(p,mon_sense), 7);	/* drive all lines high */
+	__delay(200);
+	out_le32(CNTRL_REG(p,mon_sense), 077);	/* turn off drivers */
+	__delay(2000);
+	sense = (in_le32(CNTRL_REG(p,mon_sense)) & 0x1c0) << 2;
+
+	/* drive each sense line low in turn and collect the other 2 */
+	out_le32(CNTRL_REG(p,mon_sense), 033);	/* drive A low */
+	__delay(2000);
+	sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0xc0) >> 2;
+	out_le32(CNTRL_REG(p,mon_sense), 055);	/* drive B low */
+	__delay(2000);
+	sense |= ((in_le32(CNTRL_REG(p,mon_sense)) & 0x100) >> 5)
+		| ((in_le32(CNTRL_REG(p,mon_sense)) & 0x40) >> 4);
+	out_le32(CNTRL_REG(p,mon_sense), 066);	/* drive C low */
+	__delay(2000);
+	sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0x180) >> 7;
+
+	out_le32(CNTRL_REG(p,mon_sense), 077);	/* turn off drivers */
+	
+	return sense;
+}
+
+/**********************  Various translation functions  **********************/
+
+#define CONTROL_PIXCLOCK_BASE	256016
+#define CONTROL_PIXCLOCK_MIN	5000	/* ~ 200 MHz dot clock */
+
+/*
+ * calculate the clock paramaters to be sent to CUDA according to given
+ * pixclock in pico second.
+ */
+static int calc_clock_params(unsigned long clk, unsigned char *param)
+{
+	unsigned long p0, p1, p2, k, l, m, n, min;
+
+	if (clk > (CONTROL_PIXCLOCK_BASE << 3))
+		return 1;
+
+	p2 = ((clk << 4) < CONTROL_PIXCLOCK_BASE)? 3: 2;
+	l = clk << p2;
+	p0 = 0;
+	p1 = 0;
+	for (k = 1, min = l; k < 32; k++) {
+		unsigned long rem;
+
+		m = CONTROL_PIXCLOCK_BASE * k;
+		n = m / l;
+		rem = m % l;
+		if (n && (n < 128) && rem < min) {
+			p0 = k;
+			p1 = n;
+			min = rem;
+		}
+	}
+	if (!p0 || !p1)
+		return 1;
+
+	param[0] = p0;
+	param[1] = p1;
+	param[2] = p2;
+
+	return 0;
+}
+
+
+/*
+ * This routine takes a user-supplied var, and picks the best vmode/cmode
+ * from it.
+ */
+
+static int control_var_to_par(struct fb_var_screeninfo *var,
+	struct fb_par_control *par, const struct fb_info *fb_info)
+{
+	int cmode, piped_diff, hstep;
+	unsigned hperiod, hssync, hsblank, hesync, heblank, piped, heq, hlfln,
+		 hserr, vperiod, vssync, vesync, veblank, vsblank, vswin, vewin;
+	unsigned long pixclock;
+	struct fb_info_control *p = (struct fb_info_control *) fb_info;
+	struct control_regvals *r = &par->regvals;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		par->cmode = CMODE_8;
+		if (p->total_vram > 0x200000) {
+			r->mode = 3;
+			r->radacal_ctrl = 0x20;
+			piped_diff = 13;
+		} else {
+			r->mode = 2;
+			r->radacal_ctrl = 0x10;
+			piped_diff = 9;
+		}
+		break;
+	case 15:
+	case 16:
+		par->cmode = CMODE_16;
+		if (p->total_vram > 0x200000) {
+			r->mode = 2;
+			r->radacal_ctrl = 0x24;
+			piped_diff = 5;
+		} else {
+			r->mode = 1;
+			r->radacal_ctrl = 0x14;
+			piped_diff = 3;
+		}
+		break;
+	case 32:
+		par->cmode = CMODE_32;
+		if (p->total_vram > 0x200000) {
+			r->mode = 1;
+			r->radacal_ctrl = 0x28;
+		} else {
+			r->mode = 0;
+			r->radacal_ctrl = 0x18;
+		}
+		piped_diff = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * adjust xres and vxres so that the corresponding memory widths are
+	 * 32-byte aligned
+	 */
+	hstep = 31 >> par->cmode;
+	par->xres = (var->xres + hstep) & ~hstep;
+	par->vxres = (var->xres_virtual + hstep) & ~hstep;
+	par->xoffset = (var->xoffset + hstep) & ~hstep;
+	if (par->vxres < par->xres)
+		par->vxres = par->xres;
+	par->pitch = par->vxres << par->cmode;
+
+	par->yres = var->yres;
+	par->vyres = var->yres_virtual;
+	par->yoffset = var->yoffset;
+	if (par->vyres < par->yres)
+		par->vyres = par->yres;
+
+	par->sync = var->sync;
+
+	if (par->pitch * par->vyres + CTRLFB_OFF > p->total_vram)
+		return -EINVAL;
+
+	if (par->xoffset + par->xres > par->vxres)
+		par->xoffset = par->vxres - par->xres;
+	if (par->yoffset + par->yres > par->vyres)
+		par->yoffset = par->vyres - par->yres;
+
+	pixclock = (var->pixclock < CONTROL_PIXCLOCK_MIN)? CONTROL_PIXCLOCK_MIN:
+		   var->pixclock;
+	if (calc_clock_params(pixclock, r->clock_params))
+		return -EINVAL;
+
+	hperiod = ((var->left_margin + par->xres + var->right_margin
+		    + var->hsync_len) >> 1) - 2;
+	hssync = hperiod + 1;
+	hsblank = hssync - (var->right_margin >> 1);
+	hesync = (var->hsync_len >> 1) - 1;
+	heblank = (var->left_margin >> 1) + hesync;
+	piped = heblank - piped_diff;
+	heq = var->hsync_len >> 2;
+	hlfln = (hperiod+2) >> 1;
+	hserr = hssync-hesync;
+	vperiod = (var->vsync_len + var->lower_margin + par->yres
+		   + var->upper_margin) << 1;
+	vssync = vperiod - 2;
+	vesync = (var->vsync_len << 1) - vperiod + vssync;
+	veblank = (var->upper_margin << 1) + vesync;
+	vsblank = vssync - (var->lower_margin << 1);
+	vswin = (vsblank+vssync) >> 1;
+	vewin = (vesync+veblank) >> 1;
+
+	r->regs[0] = vswin;
+	r->regs[1] = vsblank;
+	r->regs[2] = veblank;
+	r->regs[3] = vewin;
+	r->regs[4] = vesync;
+	r->regs[5] = vssync;
+	r->regs[6] = vperiod;
+	r->regs[7] = piped;
+	r->regs[8] = hperiod;
+	r->regs[9] = hsblank;
+	r->regs[10] = heblank;
+	r->regs[11] = hesync;
+	r->regs[12] = hssync;
+	r->regs[13] = heq;
+	r->regs[14] = hlfln;
+	r->regs[15] = hserr;
+
+	if (par->xres >= 1280 && par->cmode >= CMODE_16)
+		par->ctrl = 0x7f;
+	else
+		par->ctrl = 0x3b;
+
+	if (mac_var_to_vmode(var, &par->vmode, &cmode))
+		par->vmode = 0;
+
+	return 0;
+}
+
+
+/*
+ * Convert hardware data in par to an fb_var_screeninfo
+ */
+
+static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
+{
+	struct control_regints *rv;
+	
+	rv = (struct control_regints *) par->regvals.regs;
+	
+	memset(var, 0, sizeof(*var));
+	var->xres = par->xres;
+	var->yres = par->yres;
+	var->xres_virtual = par->vxres;
+	var->yres_virtual = par->vyres;
+	var->xoffset = par->xoffset;
+	var->yoffset = par->yoffset;
+	
+	switch(par->cmode) {
+	default:
+	case CMODE_8:
+		var->bits_per_pixel = 8;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case CMODE_16:	/* RGB 555 */
+		var->bits_per_pixel = 16;
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		break;
+	case CMODE_32:	/* RGB 888 */
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->height = -1;
+	var->width = -1;
+	var->vmode = FB_VMODE_NONINTERLACED;
+
+	var->left_margin = (rv->heblank - rv->hesync) << 1;
+	var->right_margin = (rv->hssync - rv->hsblank) << 1;
+	var->hsync_len = (rv->hperiod + 2 - rv->hssync + rv->hesync) << 1;
+
+	var->upper_margin = (rv->veblank - rv->vesync) >> 1;
+	var->lower_margin = (rv->vssync - rv->vsblank) >> 1;
+	var->vsync_len = (rv->vperiod - rv->vssync + rv->vesync) >> 1;
+
+	var->sync = par->sync;
+
+	/*
+	 * 10^12 * clock_params[0] / (3906400 * clock_params[1]
+	 *			      * 2^clock_params[2])
+	 * (10^12 * clock_params[0] / (3906400 * clock_params[1]))
+	 * >> clock_params[2]
+	 */
+	/* (255990.17 * clock_params[0] / clock_params[1]) >> clock_params[2] */
+	var->pixclock = CONTROL_PIXCLOCK_BASE * par->regvals.clock_params[0];
+	var->pixclock /= par->regvals.clock_params[1];
+	var->pixclock >>= par->regvals.clock_params[2];
+}
+
+/*
+ * Set misc info vars for this driver
+ */
+static void __init control_init_info(struct fb_info *info, struct fb_info_control *p)
+{
+	/* Fill fb_info */
+	info->par = &p->par;
+	info->fbops = &controlfb_ops;
+	info->pseudo_palette = p->pseudo_palette;
+        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	info->screen_base = p->frame_buffer + CTRLFB_OFF;
+
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	/* Fill fix common fields */
+	strcpy(info->fix.id, "control");
+	info->fix.mmio_start = p->control_regs_phys;
+	info->fix.mmio_len = sizeof(struct control_regs);
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.smem_start = p->frame_buffer_phys + CTRLFB_OFF;
+	info->fix.smem_len = p->total_vram - CTRLFB_OFF;
+        info->fix.ywrapstep = 0;
+        info->fix.type_aux = 0;
+        info->fix.accel = FB_ACCEL_NONE;
+}
+
+
+static void control_cleanup(void)
+{
+	struct fb_info_control	*p = control_fb;
+
+	if (!p)
+		return;
+
+	if (p->cmap_regs)
+		iounmap(p->cmap_regs);
+	if (p->control_regs)
+		iounmap(p->control_regs);
+	if (p->frame_buffer) {
+		if (p->control_use_bank2)
+			p->frame_buffer -= 0x600000;
+		iounmap(p->frame_buffer);
+	}
+	if (p->cmap_regs_phys)
+		release_mem_region(p->cmap_regs_phys, 0x1000);
+	if (p->control_regs_phys)
+		release_mem_region(p->control_regs_phys, p->control_regs_size);
+	if (p->fb_orig_base)
+		release_mem_region(p->fb_orig_base, p->fb_orig_size);
+	kfree(p);
+}
+
+
diff --git a/drivers/video/fbdev/controlfb.h b/drivers/video/fbdev/controlfb.h
new file mode 100644
index 000000000000..6026c60fc100
--- /dev/null
+++ b/drivers/video/fbdev/controlfb.h
@@ -0,0 +1,145 @@
+/*
+ * controlfb_hw.h: Constants of all sorts for controlfb
+ *
+ * Copyright (C) 1998 Daniel Jacobowitz <dan@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Based on an awful lot of code, including:
+ *
+ * control.c: Console support for PowerMac "control" display adaptor.
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * The so far unpublished platinumfb.c
+ * Copyright (C) 1998 Jon Howell
+ */
+
+/*
+ * Structure of the registers for the RADACAL colormap device.
+ */
+struct cmap_regs {
+	unsigned char addr;	/* index for both cmap and misc registers */
+	char pad1[15];
+	unsigned char crsr;	/* cursor palette */
+	char pad2[15];
+	unsigned char dat;	/* RADACAL misc register data */
+	char pad3[15];
+	unsigned char lut;	/* cmap data */
+	char pad4[15];
+};
+
+/*
+ * Structure of the registers for the "control" display adaptor.
+ */
+#define PAD(x)	char x[12]
+
+struct preg {			/* padded register */
+	unsigned r;
+	char pad[12];
+};
+
+struct control_regs {
+	struct preg vcount;	/* vertical counter */
+	/* Vertical parameters are in units of 1/2 scan line */
+	struct preg vswin;	/* between vsblank and vssync */
+	struct preg vsblank;	/* vert start blank */
+	struct preg veblank;	/* vert end blank (display start) */
+	struct preg vewin;	/* between vesync and veblank */
+	struct preg vesync;	/* vert end sync */
+	struct preg vssync;	/* vert start sync */
+	struct preg vperiod;	/* vert period */
+	struct preg piped;	/* pipe delay hardware cursor */
+	/* Horizontal params are in units of 2 pixels */
+	struct preg hperiod;	/* horiz period - 2 */
+	struct preg hsblank;	/* horiz start blank */
+	struct preg heblank;	/* horiz end blank */
+	struct preg hesync;	/* horiz end sync */
+	struct preg hssync;	/* horiz start sync */
+	struct preg heq;	/* half horiz sync len */
+	struct preg hlfln;	/* half horiz period */
+	struct preg hserr;	/* horiz period - horiz sync len */
+	struct preg cnttst;
+	struct preg ctrl;	/* display control */
+	struct preg start_addr;	/* start address: 5 lsbs zero */
+	struct preg pitch;	/* addrs diff between scan lines */
+	struct preg mon_sense;	/* monitor sense bits */
+	struct preg vram_attr;	/* enable vram banks */
+	struct preg mode;
+	struct preg rfrcnt;	/* refresh count */
+	struct preg intr_ena;	/* interrupt enable */
+	struct preg intr_stat;	/* interrupt status */
+	struct preg res[5];
+};
+
+struct control_regints {
+	/* Vertical parameters are in units of 1/2 scan line */
+	unsigned vswin;	/* between vsblank and vssync */
+	unsigned vsblank;	/* vert start blank */
+	unsigned veblank;	/* vert end blank (display start) */
+	unsigned vewin;	/* between vesync and veblank */
+	unsigned vesync;	/* vert end sync */
+	unsigned vssync;	/* vert start sync */
+	unsigned vperiod;	/* vert period */
+	unsigned piped;		/* pipe delay hardware cursor */
+	/* Horizontal params are in units of 2 pixels */
+	/* Except, apparently, for hres > 1024 (or == 1280?) */
+	unsigned hperiod;	/* horiz period - 2 */
+	unsigned hsblank;	/* horiz start blank */
+	unsigned heblank;	/* horiz end blank */
+	unsigned hesync;	/* horiz end sync */
+	unsigned hssync;	/* horiz start sync */
+	unsigned heq;		/* half horiz sync len */
+	unsigned hlfln;		/* half horiz period */
+	unsigned hserr;		/* horiz period - horiz sync len */
+};
+	
+/*
+ * Dot clock rate is
+ * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0].
+ */
+struct control_regvals {
+	unsigned regs[16];		/* for vswin .. hserr */
+	unsigned char mode;
+	unsigned char radacal_ctrl;
+	unsigned char clock_params[3];
+};
+
+#define CTRLFB_OFF 16	/* position of pixel 0 in frame buffer */
+
+
+/*
+ * Best cmode supported by control
+ */
+struct max_cmodes {
+	int m[2];	/* 0: 2MB vram, 1: 4MB vram */
+};
+
+/*
+ * Video modes supported by macmodes.c
+ */
+static struct max_cmodes control_mac_modes[] = {
+	{{-1,-1}},	/* 512x384, 60Hz interlaced (NTSC) */
+	{{-1,-1}},	/* 512x384, 60Hz */
+	{{-1,-1}},	/* 640x480, 50Hz interlaced (PAL) */
+	{{-1,-1}},	/* 640x480, 60Hz interlaced (NTSC) */
+	{{ 2, 2}},	/* 640x480, 60Hz (VGA) */
+	{{ 2, 2}},	/* 640x480, 67Hz */
+	{{-1,-1}},	/* 640x870, 75Hz (portrait) */
+	{{-1,-1}},	/* 768x576, 50Hz (PAL full frame) */
+	{{ 2, 2}},	/* 800x600, 56Hz */
+	{{ 2, 2}},	/* 800x600, 60Hz */
+	{{ 2, 2}},	/* 800x600, 72Hz */
+	{{ 2, 2}},	/* 800x600, 75Hz */
+	{{ 1, 2}},	/* 832x624, 75Hz */
+	{{ 1, 2}},	/* 1024x768, 60Hz */
+	{{ 1, 2}},	/* 1024x768, 70Hz (or 72Hz?) */
+	{{ 1, 2}},	/* 1024x768, 75Hz (VESA) */
+	{{ 1, 2}},	/* 1024x768, 75Hz */
+	{{ 1, 2}},	/* 1152x870, 75Hz */
+	{{ 0, 1}},	/* 1280x960, 75Hz */
+	{{ 0, 1}},	/* 1280x1024, 75Hz */
+};
+
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
new file mode 100644
index 000000000000..fa306538dac2
--- /dev/null
+++ b/drivers/video/fbdev/core/Makefile
@@ -0,0 +1,16 @@
+obj-y                             += fb_notify.o
+obj-$(CONFIG_FB)                  += fb.o
+fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
+                                     modedb.o fbcvt.o
+fb-objs                           := $(fb-y)
+
+obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
+obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
+obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SYS_FILLRECT)  += sysfillrect.o
+obj-$(CONFIG_FB_SYS_COPYAREA)  += syscopyarea.o
+obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
+obj-$(CONFIG_FB_SYS_FOPS)      += fb_sys_fops.o
+obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
+obj-$(CONFIG_FB_DDC)           += fb_ddc.o
+obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
diff --git a/drivers/video/fbdev/core/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c
new file mode 100644
index 000000000000..bcb57235fcc7
--- /dev/null
+++ b/drivers/video/fbdev/core/cfbcopyarea.c
@@ -0,0 +1,434 @@
+/*
+ *  Generic function for frame buffer with packed pixels of any depth.
+ *
+ *      Copyright (C)  1999-2005 James Simmons <jsimmons@www.infradead.org>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ * NOTES:
+ *
+ *  This is for cfb packed pixels. Iplan and such are incorporated in the
+ *  drivers that need them.
+ *
+ *  FIXME
+ *
+ *  Also need to add code to deal with cards endians that are different than
+ *  the native cpu endians. I also need to deal with MSB position in the word.
+ *
+ *  The two functions or copying forward and backward could be split up like
+ *  the ones for filling, i.e. in aligned and unaligned versions. This would
+ *  help moving some redundant computations and branches out of the loop, too.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include "fb_draw.h"
+
+#if BITS_PER_LONG == 32
+#  define FB_WRITEL fb_writel
+#  define FB_READL  fb_readl
+#else
+#  define FB_WRITEL fb_writeq
+#  define FB_READL  fb_readq
+#endif
+
+    /*
+     *  Generic bitwise copy algorithm
+     */
+
+static void
+bitcpy(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx,
+		const unsigned long __iomem *src, unsigned src_idx, int bits,
+		unsigned n, u32 bswapmask)
+{
+	unsigned long first, last;
+	int const shift = dst_idx-src_idx;
+
+#if 0
+	/*
+	 * If you suspect bug in this function, compare it with this simple
+	 * memmove implementation.
+	 */
+	fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8,
+		   (char *)src + ((src_idx & (bits - 1))) / 8, n / 8);
+	return;
+#endif
+
+	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
+	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
+
+	if (!shift) {
+		// Same alignment for source and dest
+
+		if (dst_idx+n <= bits) {
+			// Single word
+			if (last)
+				first &= last;
+			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
+		} else {
+			// Multiple destination words
+
+			// Leading bits
+			if (first != ~0UL) {
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
+				dst++;
+				src++;
+				n -= bits - dst_idx;
+			}
+
+			// Main chunk
+			n /= bits;
+			while (n >= 8) {
+				FB_WRITEL(FB_READL(src++), dst++);
+				FB_WRITEL(FB_READL(src++), dst++);
+				FB_WRITEL(FB_READL(src++), dst++);
+				FB_WRITEL(FB_READL(src++), dst++);
+				FB_WRITEL(FB_READL(src++), dst++);
+				FB_WRITEL(FB_READL(src++), dst++);
+				FB_WRITEL(FB_READL(src++), dst++);
+				FB_WRITEL(FB_READL(src++), dst++);
+				n -= 8;
+			}
+			while (n--)
+				FB_WRITEL(FB_READL(src++), dst++);
+
+			// Trailing bits
+			if (last)
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
+		}
+	} else {
+		/* Different alignment for source and dest */
+		unsigned long d0, d1;
+		int m;
+
+		int const left = shift & (bits - 1);
+		int const right = -shift & (bits - 1);
+
+		if (dst_idx+n <= bits) {
+			// Single destination word
+			if (last)
+				first &= last;
+			d0 = FB_READL(src);
+			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+			if (shift > 0) {
+				// Single source word
+				d0 <<= left;
+			} else if (src_idx+n <= bits) {
+				// Single source word
+				d0 >>= right;
+			} else {
+				// 2 source words
+				d1 = FB_READL(src + 1);
+				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+				d0 = d0 >> right | d1 << left;
+			}
+			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+		} else {
+			// Multiple destination words
+			/** We must always remember the last value read, because in case
+			SRC and DST overlap bitwise (e.g. when moving just one pixel in
+			1bpp), we always collect one full long for DST and that might
+			overlap with the current long from SRC. We store this value in
+			'd0'. */
+			d0 = FB_READL(src++);
+			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+			// Leading bits
+			if (shift > 0) {
+				// Single source word
+				d1 = d0;
+				d0 <<= left;
+				n -= bits - dst_idx;
+			} else {
+				// 2 source words
+				d1 = FB_READL(src++);
+				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+
+				d0 = d0 >> right | d1 << left;
+				n -= bits - dst_idx;
+			}
+			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+			d0 = d1;
+			dst++;
+
+			// Main chunk
+			m = n % bits;
+			n /= bits;
+			while ((n >= 4) && !bswapmask) {
+				d1 = FB_READL(src++);
+				FB_WRITEL(d0 >> right | d1 << left, dst++);
+				d0 = d1;
+				d1 = FB_READL(src++);
+				FB_WRITEL(d0 >> right | d1 << left, dst++);
+				d0 = d1;
+				d1 = FB_READL(src++);
+				FB_WRITEL(d0 >> right | d1 << left, dst++);
+				d0 = d1;
+				d1 = FB_READL(src++);
+				FB_WRITEL(d0 >> right | d1 << left, dst++);
+				d0 = d1;
+				n -= 4;
+			}
+			while (n--) {
+				d1 = FB_READL(src++);
+				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+				d0 = d0 >> right | d1 << left;
+				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+				FB_WRITEL(d0, dst++);
+				d0 = d1;
+			}
+
+			// Trailing bits
+			if (m) {
+				if (m <= bits - right) {
+					// Single source word
+					d0 >>= right;
+				} else {
+					// 2 source words
+					d1 = FB_READL(src);
+					d1 = fb_rev_pixels_in_long(d1,
+								bswapmask);
+					d0 = d0 >> right | d1 << left;
+				}
+				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+				FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
+			}
+		}
+	}
+}
+
+    /*
+     *  Generic bitwise copy algorithm, operating backward
+     */
+
+static void
+bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx,
+		const unsigned long __iomem *src, unsigned src_idx, int bits,
+		unsigned n, u32 bswapmask)
+{
+	unsigned long first, last;
+	int shift;
+
+#if 0
+	/*
+	 * If you suspect bug in this function, compare it with this simple
+	 * memmove implementation.
+	 */
+	fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8,
+		   (char *)src + ((src_idx & (bits - 1))) / 8, n / 8);
+	return;
+#endif
+
+	dst += (dst_idx + n - 1) / bits;
+	src += (src_idx + n - 1) / bits;
+	dst_idx = (dst_idx + n - 1) % bits;
+	src_idx = (src_idx + n - 1) % bits;
+
+	shift = dst_idx-src_idx;
+
+	first = ~fb_shifted_pixels_mask_long(p, (dst_idx + 1) % bits, bswapmask);
+	last = fb_shifted_pixels_mask_long(p, (bits + dst_idx + 1 - n) % bits, bswapmask);
+
+	if (!shift) {
+		// Same alignment for source and dest
+
+		if ((unsigned long)dst_idx+1 >= n) {
+			// Single word
+			if (first)
+				last &= first;
+			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
+		} else {
+			// Multiple destination words
+
+			// Leading bits
+			if (first) {
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
+				dst--;
+				src--;
+				n -= dst_idx+1;
+			}
+
+			// Main chunk
+			n /= bits;
+			while (n >= 8) {
+				FB_WRITEL(FB_READL(src--), dst--);
+				FB_WRITEL(FB_READL(src--), dst--);
+				FB_WRITEL(FB_READL(src--), dst--);
+				FB_WRITEL(FB_READL(src--), dst--);
+				FB_WRITEL(FB_READL(src--), dst--);
+				FB_WRITEL(FB_READL(src--), dst--);
+				FB_WRITEL(FB_READL(src--), dst--);
+				FB_WRITEL(FB_READL(src--), dst--);
+				n -= 8;
+			}
+			while (n--)
+				FB_WRITEL(FB_READL(src--), dst--);
+
+			// Trailing bits
+			if (last != -1UL)
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
+		}
+	} else {
+		// Different alignment for source and dest
+		unsigned long d0, d1;
+		int m;
+
+		int const left = shift & (bits-1);
+		int const right = -shift & (bits-1);
+
+		if ((unsigned long)dst_idx+1 >= n) {
+			// Single destination word
+			if (first)
+				last &= first;
+			d0 = FB_READL(src);
+			if (shift < 0) {
+				// Single source word
+				d0 >>= right;
+			} else if (1+(unsigned long)src_idx >= n) {
+				// Single source word
+				d0 <<= left;
+			} else {
+				// 2 source words
+				d1 = FB_READL(src - 1);
+				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+				d0 = d0 << left | d1 >> right;
+			}
+			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+			FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
+		} else {
+			// Multiple destination words
+			/** We must always remember the last value read, because in case
+			SRC and DST overlap bitwise (e.g. when moving just one pixel in
+			1bpp), we always collect one full long for DST and that might
+			overlap with the current long from SRC. We store this value in
+			'd0'. */
+
+			d0 = FB_READL(src--);
+			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+			// Leading bits
+			if (shift < 0) {
+				// Single source word
+				d1 = d0;
+				d0 >>= right;
+			} else {
+				// 2 source words
+				d1 = FB_READL(src--);
+				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+				d0 = d0 << left | d1 >> right;
+			}
+			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+			d0 = d1;
+			dst--;
+			n -= dst_idx+1;
+
+			// Main chunk
+			m = n % bits;
+			n /= bits;
+			while ((n >= 4) && !bswapmask) {
+				d1 = FB_READL(src--);
+				FB_WRITEL(d0 << left | d1 >> right, dst--);
+				d0 = d1;
+				d1 = FB_READL(src--);
+				FB_WRITEL(d0 << left | d1 >> right, dst--);
+				d0 = d1;
+				d1 = FB_READL(src--);
+				FB_WRITEL(d0 << left | d1 >> right, dst--);
+				d0 = d1;
+				d1 = FB_READL(src--);
+				FB_WRITEL(d0 << left | d1 >> right, dst--);
+				d0 = d1;
+				n -= 4;
+			}
+			while (n--) {
+				d1 = FB_READL(src--);
+				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+				d0 = d0 << left | d1 >> right;
+				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+				FB_WRITEL(d0, dst--);
+				d0 = d1;
+			}
+
+			// Trailing bits
+			if (m) {
+				if (m <= bits - left) {
+					// Single source word
+					d0 <<= left;
+				} else {
+					// 2 source words
+					d1 = FB_READL(src);
+					d1 = fb_rev_pixels_in_long(d1,
+								bswapmask);
+					d0 = d0 << left | d1 >> right;
+				}
+				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+				FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
+			}
+		}
+	}
+}
+
+void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
+	u32 height = area->height, width = area->width;
+	unsigned long const bits_per_line = p->fix.line_length*8u;
+	unsigned long __iomem *base = NULL;
+	int bits = BITS_PER_LONG, bytes = bits >> 3;
+	unsigned dst_idx = 0, src_idx = 0, rev_copy = 0;
+	u32 bswapmask = fb_compute_bswapmask(p);
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	/* if the beginning of the target area might overlap with the end of
+	the source area, be have to copy the area reverse. */
+	if ((dy == sy && dx > sx) || (dy > sy)) {
+		dy += height;
+		sy += height;
+		rev_copy = 1;
+	}
+
+	// split the base of the framebuffer into a long-aligned address and the
+	// index of the first bit
+	base = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
+	dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
+	// add offset of source and target area
+	dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
+	src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	if (rev_copy) {
+		while (height--) {
+			dst_idx -= bits_per_line;
+			src_idx -= bits_per_line;
+			bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits,
+				base + (src_idx / bits), src_idx % bits, bits,
+				width*p->var.bits_per_pixel, bswapmask);
+		}
+	} else {
+		while (height--) {
+			bitcpy(p, base + (dst_idx / bits), dst_idx % bits,
+				base + (src_idx / bits), src_idx % bits, bits,
+				width*p->var.bits_per_pixel, bswapmask);
+			dst_idx += bits_per_line;
+			src_idx += bits_per_line;
+		}
+	}
+}
+
+EXPORT_SYMBOL(cfb_copyarea);
+
+MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
+MODULE_DESCRIPTION("Generic software accelerated copyarea");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/core/cfbfillrect.c b/drivers/video/fbdev/core/cfbfillrect.c
new file mode 100644
index 000000000000..ba9f58b2a5e8
--- /dev/null
+++ b/drivers/video/fbdev/core/cfbfillrect.c
@@ -0,0 +1,371 @@
+/*
+ *  Generic fillrect for frame buffers with packed pixels of any depth.
+ *
+ *      Copyright (C)  2000 James Simmons (jsimmons@linux-fbdev.org)
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ * NOTES:
+ *
+ *  Also need to add code to deal with cards endians that are different than
+ *  the native cpu endians. I also need to deal with MSB position in the word.
+ *
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+#include "fb_draw.h"
+
+#if BITS_PER_LONG == 32
+#  define FB_WRITEL fb_writel
+#  define FB_READL  fb_readl
+#else
+#  define FB_WRITEL fb_writeq
+#  define FB_READL  fb_readq
+#endif
+
+    /*
+     *  Aligned pattern fill using 32/64-bit memory accesses
+     */
+
+static void
+bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+		unsigned long pat, unsigned n, int bits, u32 bswapmask)
+{
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
+	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
+
+	if (dst_idx+n <= bits) {
+		// Single word
+		if (last)
+			first &= last;
+		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
+	} else {
+		// Multiple destination words
+
+		// Leading bits
+		if (first!= ~0UL) {
+			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
+			dst++;
+			n -= bits - dst_idx;
+		}
+
+		// Main chunk
+		n /= bits;
+		while (n >= 8) {
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			n -= 8;
+		}
+		while (n--)
+			FB_WRITEL(pat, dst++);
+
+		// Trailing bits
+		if (last)
+			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
+	}
+}
+
+
+    /*
+     *  Unaligned generic pattern fill using 32/64-bit memory accesses
+     *  The pattern must have been expanded to a full 32/64-bit value
+     *  Left/right are the appropriate shifts to convert to the pattern to be
+     *  used for the next 32/64-bit word
+     */
+
+static void
+bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+		  unsigned long pat, int left, int right, unsigned n, int bits)
+{
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
+	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
+		// Single word
+		if (last)
+			first &= last;
+		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
+	} else {
+		// Multiple destination words
+		// Leading bits
+		if (first) {
+			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
+			dst++;
+			pat = pat << left | pat >> right;
+			n -= bits - dst_idx;
+		}
+
+		// Main chunk
+		n /= bits;
+		while (n >= 4) {
+			FB_WRITEL(pat, dst++);
+			pat = pat << left | pat >> right;
+			FB_WRITEL(pat, dst++);
+			pat = pat << left | pat >> right;
+			FB_WRITEL(pat, dst++);
+			pat = pat << left | pat >> right;
+			FB_WRITEL(pat, dst++);
+			pat = pat << left | pat >> right;
+			n -= 4;
+		}
+		while (n--) {
+			FB_WRITEL(pat, dst++);
+			pat = pat << left | pat >> right;
+		}
+
+		// Trailing bits
+		if (last)
+			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
+	}
+}
+
+    /*
+     *  Aligned pattern invert using 32/64-bit memory accesses
+     */
+static void
+bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
+		    int dst_idx, unsigned long pat, unsigned n, int bits,
+		    u32 bswapmask)
+{
+	unsigned long val = pat, dat;
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
+	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
+
+	if (dst_idx+n <= bits) {
+		// Single word
+		if (last)
+			first &= last;
+		dat = FB_READL(dst);
+		FB_WRITEL(comp(dat ^ val, dat, first), dst);
+	} else {
+		// Multiple destination words
+		// Leading bits
+		if (first!=0UL) {
+			dat = FB_READL(dst);
+			FB_WRITEL(comp(dat ^ val, dat, first), dst);
+			dst++;
+			n -= bits - dst_idx;
+		}
+
+		// Main chunk
+		n /= bits;
+		while (n >= 8) {
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+			n -= 8;
+		}
+		while (n--) {
+			FB_WRITEL(FB_READL(dst) ^ val, dst);
+			dst++;
+		}
+		// Trailing bits
+		if (last) {
+			dat = FB_READL(dst);
+			FB_WRITEL(comp(dat ^ val, dat, last), dst);
+		}
+	}
+}
+
+
+    /*
+     *  Unaligned generic pattern invert using 32/64-bit memory accesses
+     *  The pattern must have been expanded to a full 32/64-bit value
+     *  Left/right are the appropriate shifts to convert to the pattern to be
+     *  used for the next 32/64-bit word
+     */
+
+static void
+bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
+		      int dst_idx, unsigned long pat, int left, int right,
+		      unsigned n, int bits)
+{
+	unsigned long first, last, dat;
+
+	if (!n)
+		return;
+
+	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
+	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
+		// Single word
+		if (last)
+			first &= last;
+		dat = FB_READL(dst);
+		FB_WRITEL(comp(dat ^ pat, dat, first), dst);
+	} else {
+		// Multiple destination words
+
+		// Leading bits
+		if (first != 0UL) {
+			dat = FB_READL(dst);
+			FB_WRITEL(comp(dat ^ pat, dat, first), dst);
+			dst++;
+			pat = pat << left | pat >> right;
+			n -= bits - dst_idx;
+		}
+
+		// Main chunk
+		n /= bits;
+		while (n >= 4) {
+			FB_WRITEL(FB_READL(dst) ^ pat, dst);
+			dst++;
+			pat = pat << left | pat >> right;
+			FB_WRITEL(FB_READL(dst) ^ pat, dst);
+			dst++;
+			pat = pat << left | pat >> right;
+			FB_WRITEL(FB_READL(dst) ^ pat, dst);
+			dst++;
+			pat = pat << left | pat >> right;
+			FB_WRITEL(FB_READL(dst) ^ pat, dst);
+			dst++;
+			pat = pat << left | pat >> right;
+			n -= 4;
+		}
+		while (n--) {
+			FB_WRITEL(FB_READL(dst) ^ pat, dst);
+			dst++;
+			pat = pat << left | pat >> right;
+		}
+
+		// Trailing bits
+		if (last) {
+			dat = FB_READL(dst);
+			FB_WRITEL(comp(dat ^ pat, dat, last), dst);
+		}
+	}
+}
+
+void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	unsigned long pat, pat2, fg;
+	unsigned long width = rect->width, height = rect->height;
+	int bits = BITS_PER_LONG, bytes = bits >> 3;
+	u32 bpp = p->var.bits_per_pixel;
+	unsigned long __iomem *dst;
+	int dst_idx, left;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
+		fg = ((u32 *) (p->pseudo_palette))[rect->color];
+	else
+		fg = rect->color;
+
+	pat = pixel_to_pat(bpp, fg);
+
+	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
+	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
+	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
+	/* FIXME For now we support 1-32 bpp only */
+	left = bits % bpp;
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+	if (!left) {
+		u32 bswapmask = fb_compute_bswapmask(p);
+		void (*fill_op32)(struct fb_info *p,
+				  unsigned long __iomem *dst, int dst_idx,
+		                  unsigned long pat, unsigned n, int bits,
+				  u32 bswapmask) = NULL;
+
+		switch (rect->rop) {
+		case ROP_XOR:
+			fill_op32 = bitfill_aligned_rev;
+			break;
+		case ROP_COPY:
+			fill_op32 = bitfill_aligned;
+			break;
+		default:
+			printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+			fill_op32 = bitfill_aligned;
+			break;
+		}
+		while (height--) {
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bits - 1);
+			fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
+				  bswapmask);
+			dst_idx += p->fix.line_length*8;
+		}
+	} else {
+		int right, r;
+		void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
+				int dst_idx, unsigned long pat, int left,
+				int right, unsigned n, int bits) = NULL;
+#ifdef __LITTLE_ENDIAN
+		right = left;
+		left = bpp - right;
+#else
+		right = bpp - left;
+#endif
+		switch (rect->rop) {
+		case ROP_XOR:
+			fill_op = bitfill_unaligned_rev;
+			break;
+		case ROP_COPY:
+			fill_op = bitfill_unaligned;
+			break;
+		default:
+			printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+			fill_op = bitfill_unaligned;
+			break;
+		}
+		while (height--) {
+			dst += dst_idx / bits;
+			dst_idx &= (bits - 1);
+			r = dst_idx % bpp;
+			/* rotate pattern to the correct start position */
+			pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
+			fill_op(p, dst, dst_idx, pat2, left, right,
+				width*bpp, bits);
+			dst_idx += p->fix.line_length*8;
+		}
+	}
+}
+
+EXPORT_SYMBOL(cfb_fillrect);
+
+MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
+MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c
new file mode 100644
index 000000000000..a2bb276a8b24
--- /dev/null
+++ b/drivers/video/fbdev/core/cfbimgblt.c
@@ -0,0 +1,313 @@
+/*
+ *  Generic BitBLT function for frame buffer with packed pixels of any depth.
+ *
+ *      Copyright (C)  June 1999 James Simmons
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ * NOTES:
+ *
+ *    This function copys a image from system memory to video memory. The
+ *  image can be a bitmap where each 0 represents the background color and
+ *  each 1 represents the foreground color. Great for font handling. It can
+ *  also be a color image. This is determined by image_depth. The color image
+ *  must be laid out exactly in the same format as the framebuffer. Yes I know
+ *  their are cards with hardware that coverts images of various depths to the
+ *  framebuffer depth. But not every card has this. All images must be rounded
+ *  up to the nearest byte. For example a bitmap 12 bits wide must be two 
+ *  bytes width. 
+ *
+ *  Tony: 
+ *  Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API.  This speeds 
+ *  up the code significantly.
+ *  
+ *  Code for depths not multiples of BITS_PER_LONG is still kludgy, which is
+ *  still processed a bit at a time.   
+ *
+ *  Also need to add code to deal with cards endians that are different than
+ *  the native cpu endians. I also need to deal with MSB position in the word.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+#include "fb_draw.h"
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static const u32 cfb_tab8_be[] = {
+    0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
+    0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
+    0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
+    0xffff0000,0xffff00ff,0xffffff00,0xffffffff
+};
+
+static const u32 cfb_tab8_le[] = {
+    0x00000000,0xff000000,0x00ff0000,0xffff0000,
+    0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
+    0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
+    0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
+};
+
+static const u32 cfb_tab16_be[] = {
+    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
+};
+
+static const u32 cfb_tab16_le[] = {
+    0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+};
+
+static const u32 cfb_tab32[] = {
+	0x00000000, 0xffffffff
+};
+
+#define FB_WRITEL fb_writel
+#define FB_READL  fb_readl
+
+static inline void color_imageblit(const struct fb_image *image, 
+				   struct fb_info *p, u8 __iomem *dst1, 
+				   u32 start_index,
+				   u32 pitch_index)
+{
+	/* Draw the penguin */
+	u32 __iomem *dst, *dst2;
+	u32 color = 0, val, shift;
+	int i, n, bpp = p->var.bits_per_pixel;
+	u32 null_bits = 32 - bpp;
+	u32 *palette = (u32 *) p->pseudo_palette;
+	const u8 *src = image->data;
+	u32 bswapmask = fb_compute_bswapmask(p);
+
+	dst2 = (u32 __iomem *) dst1;
+	for (i = image->height; i--; ) {
+		n = image->width;
+		dst = (u32 __iomem *) dst1;
+		shift = 0;
+		val = 0;
+		
+		if (start_index) {
+			u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
+						start_index, bswapmask);
+			val = FB_READL(dst) & start_mask;
+			shift = start_index;
+		}
+		while (n--) {
+			if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+			    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
+				color = palette[*src];
+			else
+				color = *src;
+			color <<= FB_LEFT_POS(p, bpp);
+			val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
+			if (shift >= null_bits) {
+				FB_WRITEL(val, dst++);
+	
+				val = (shift == null_bits) ? 0 : 
+					FB_SHIFT_LOW(p, color, 32 - shift);
+			}
+			shift += bpp;
+			shift &= (32 - 1);
+			src++;
+		}
+		if (shift) {
+			u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
+						bswapmask);
+
+			FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
+		}
+		dst1 += p->fix.line_length;
+		if (pitch_index) {
+			dst2 += p->fix.line_length;
+			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
+
+			start_index += pitch_index;
+			start_index &= 32 - 1;
+		}
+	}
+}
+
+static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, 
+				  u8 __iomem *dst1, u32 fgcolor,
+				  u32 bgcolor, 
+				  u32 start_index,
+				  u32 pitch_index)
+{
+	u32 shift, color = 0, bpp = p->var.bits_per_pixel;
+	u32 __iomem *dst, *dst2;
+	u32 val, pitch = p->fix.line_length;
+	u32 null_bits = 32 - bpp;
+	u32 spitch = (image->width+7)/8;
+	const u8 *src = image->data, *s;
+	u32 i, j, l;
+	u32 bswapmask = fb_compute_bswapmask(p);
+
+	dst2 = (u32 __iomem *) dst1;
+	fgcolor <<= FB_LEFT_POS(p, bpp);
+	bgcolor <<= FB_LEFT_POS(p, bpp);
+
+	for (i = image->height; i--; ) {
+		shift = val = 0;
+		l = 8;
+		j = image->width;
+		dst = (u32 __iomem *) dst1;
+		s = src;
+
+		/* write leading bits */
+		if (start_index) {
+			u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
+						start_index, bswapmask);
+			val = FB_READL(dst) & start_mask;
+			shift = start_index;
+		}
+
+		while (j--) {
+			l--;
+			color = (*s & (1 << l)) ? fgcolor : bgcolor;
+			val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
+			
+			/* Did the bitshift spill bits to the next long? */
+			if (shift >= null_bits) {
+				FB_WRITEL(val, dst++);
+				val = (shift == null_bits) ? 0 :
+					FB_SHIFT_LOW(p, color, 32 - shift);
+			}
+			shift += bpp;
+			shift &= (32 - 1);
+			if (!l) { l = 8; s++; }
+		}
+
+		/* write trailing bits */
+ 		if (shift) {
+			u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
+						bswapmask);
+
+			FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
+		}
+		
+		dst1 += pitch;
+		src += spitch;	
+		if (pitch_index) {
+			dst2 += pitch;
+			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
+			start_index += pitch_index;
+			start_index &= 32 - 1;
+		}
+		
+	}
+}
+
+/*
+ * fast_imageblit - optimized monochrome color expansion
+ *
+ * Only if:  bits_per_pixel == 8, 16, or 32
+ *           image->width is divisible by pixel/dword (ppw);
+ *           fix->line_legth is divisible by 4;
+ *           beginning and end of a scanline is dword aligned
+ */
+static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, 
+				  u8 __iomem *dst1, u32 fgcolor, 
+				  u32 bgcolor) 
+{
+	u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
+	u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
+	u32 bit_mask, end_mask, eorx, shift;
+	const char *s = image->data, *src;
+	u32 __iomem *dst;
+	const u32 *tab = NULL;
+	int i, j, k;
+
+	switch (bpp) {
+	case 8:
+		tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
+		break;
+	case 16:
+		tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
+		break;
+	case 32:
+	default:
+		tab = cfb_tab32;
+		break;
+	}
+
+	for (i = ppw-1; i--; ) {
+		fgx <<= bpp;
+		bgx <<= bpp;
+		fgx |= fgcolor;
+		bgx |= bgcolor;
+	}
+	
+	bit_mask = (1 << ppw) - 1;
+	eorx = fgx ^ bgx;
+	k = image->width/ppw;
+
+	for (i = image->height; i--; ) {
+		dst = (u32 __iomem *) dst1, shift = 8; src = s;
+		
+		for (j = k; j--; ) {
+			shift -= ppw;
+			end_mask = tab[(*src >> shift) & bit_mask];
+			FB_WRITEL((end_mask & eorx)^bgx, dst++);
+			if (!shift) { shift = 8; src++; }		
+		}
+		dst1 += p->fix.line_length;
+		s += spitch;
+	}
+}	
+	
+void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+	u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
+	u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
+	u32 width = image->width;
+	u32 dx = image->dx, dy = image->dy;
+	u8 __iomem *dst1;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
+	start_index = bitstart & (32 - 1);
+	pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+
+	bitstart /= 8;
+	bitstart &= ~(bpl - 1);
+	dst1 = p->screen_base + bitstart;
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	if (image->depth == 1) {
+		if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+		    p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+			fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
+			bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
+		} else {
+			fgcolor = image->fg_color;
+			bgcolor = image->bg_color;
+		}	
+		
+		if (32 % bpp == 0 && !start_index && !pitch_index && 
+		    ((width & (32/bpp-1)) == 0) &&
+		    bpp >= 8 && bpp <= 32) 			
+			fast_imageblit(image, p, dst1, fgcolor, bgcolor);
+		else 
+			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
+					start_index, pitch_index);
+	} else
+		color_imageblit(image, p, dst1, start_index, pitch_index);
+}
+
+EXPORT_SYMBOL(cfb_imageblit);
+
+MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
+MODULE_DESCRIPTION("Generic software accelerated imaging drawing");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/core/fb_ddc.c b/drivers/video/fbdev/core/fb_ddc.c
new file mode 100644
index 000000000000..94322ccfedde
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_ddc.c
@@ -0,0 +1,119 @@
+/*
+ * drivers/video/fb_ddc.c - DDC/EDID read support.
+ *
+ *  Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/slab.h>
+
+#include "../edid.h"
+
+#define DDC_ADDR	0x50
+
+static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter)
+{
+	unsigned char start = 0x0;
+	unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= DDC_ADDR,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= &start,
+		}, {
+			.addr	= DDC_ADDR,
+			.flags	= I2C_M_RD,
+			.len	= EDID_LENGTH,
+			.buf	= buf,
+		}
+	};
+
+	if (!buf) {
+		dev_warn(&adapter->dev, "unable to allocate memory for EDID "
+			 "block.\n");
+		return NULL;
+	}
+
+	if (i2c_transfer(adapter, msgs, 2) == 2)
+		return buf;
+
+	dev_warn(&adapter->dev, "unable to read EDID block.\n");
+	kfree(buf);
+	return NULL;
+}
+
+unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
+{
+	struct i2c_algo_bit_data *algo_data = adapter->algo_data;
+	unsigned char *edid = NULL;
+	int i, j;
+
+	algo_data->setscl(algo_data->data, 1);
+
+	for (i = 0; i < 3; i++) {
+		/* For some old monitors we need the
+		 * following process to initialize/stop DDC
+		 */
+		algo_data->setsda(algo_data->data, 1);
+		msleep(13);
+
+		algo_data->setscl(algo_data->data, 1);
+		for (j = 0; j < 5; j++) {
+			msleep(10);
+			if (algo_data->getscl(algo_data->data))
+				break;
+		}
+		if (j == 5)
+			continue;
+
+		algo_data->setsda(algo_data->data, 0);
+		msleep(15);
+		algo_data->setscl(algo_data->data, 0);
+		msleep(15);
+		algo_data->setsda(algo_data->data, 1);
+		msleep(15);
+
+		/* Do the real work */
+		edid = fb_do_probe_ddc_edid(adapter);
+		algo_data->setsda(algo_data->data, 0);
+		algo_data->setscl(algo_data->data, 0);
+		msleep(15);
+
+		algo_data->setscl(algo_data->data, 1);
+		for (j = 0; j < 10; j++) {
+			msleep(10);
+			if (algo_data->getscl(algo_data->data))
+				break;
+		}
+
+		algo_data->setsda(algo_data->data, 1);
+		msleep(15);
+		algo_data->setscl(algo_data->data, 0);
+		algo_data->setsda(algo_data->data, 0);
+		if (edid)
+			break;
+	}
+	/* Release the DDC lines when done or the Apple Cinema HD display
+	 * will switch off
+	 */
+	algo_data->setsda(algo_data->data, 1);
+	algo_data->setscl(algo_data->data, 1);
+
+	adapter->class |= I2C_CLASS_DDC;
+	return edid;
+}
+
+EXPORT_SYMBOL_GPL(fb_ddc_read);
+
+MODULE_AUTHOR("Dennis Munsie <dmunsie@cecropia.com>");
+MODULE_DESCRIPTION("DDC/EDID reading support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
new file mode 100644
index 000000000000..900aa4ecd617
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -0,0 +1,245 @@
+/*
+ *  linux/drivers/video/fb_defio.c
+ *
+ *  Copyright (C) 2006 Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/list.h>
+
+/* to support deferred IO */
+#include <linux/rmap.h>
+#include <linux/pagemap.h>
+
+static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs)
+{
+	void *screen_base = (void __force *) info->screen_base;
+	struct page *page;
+
+	if (is_vmalloc_addr(screen_base + offs))
+		page = vmalloc_to_page(screen_base + offs);
+	else
+		page = pfn_to_page((info->fix.smem_start + offs) >> PAGE_SHIFT);
+
+	return page;
+}
+
+/* this is to find and return the vmalloc-ed fb pages */
+static int fb_deferred_io_fault(struct vm_area_struct *vma,
+				struct vm_fault *vmf)
+{
+	unsigned long offset;
+	struct page *page;
+	struct fb_info *info = vma->vm_private_data;
+
+	offset = vmf->pgoff << PAGE_SHIFT;
+	if (offset >= info->fix.smem_len)
+		return VM_FAULT_SIGBUS;
+
+	page = fb_deferred_io_page(info, offset);
+	if (!page)
+		return VM_FAULT_SIGBUS;
+
+	get_page(page);
+
+	if (vma->vm_file)
+		page->mapping = vma->vm_file->f_mapping;
+	else
+		printk(KERN_ERR "no mapping available\n");
+
+	BUG_ON(!page->mapping);
+	page->index = vmf->pgoff;
+
+	vmf->page = page;
+	return 0;
+}
+
+int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+	struct fb_info *info = file->private_data;
+	struct inode *inode = file_inode(file);
+	int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+
+	/* Skip if deferred io is compiled-in but disabled on this fbdev */
+	if (!info->fbdefio)
+		return 0;
+
+	mutex_lock(&inode->i_mutex);
+	/* Kill off the delayed work */
+	cancel_delayed_work_sync(&info->deferred_work);
+
+	/* Run it immediately */
+	err = schedule_delayed_work(&info->deferred_work, 0);
+	mutex_unlock(&inode->i_mutex);
+	return err;
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
+
+/* vm_ops->page_mkwrite handler */
+static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
+				  struct vm_fault *vmf)
+{
+	struct page *page = vmf->page;
+	struct fb_info *info = vma->vm_private_data;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct page *cur;
+
+	/* this is a callback we get when userspace first tries to
+	write to the page. we schedule a workqueue. that workqueue
+	will eventually mkclean the touched pages and execute the
+	deferred framebuffer IO. then if userspace touches a page
+	again, we repeat the same scheme */
+
+	file_update_time(vma->vm_file);
+
+	/* protect against the workqueue changing the page list */
+	mutex_lock(&fbdefio->lock);
+
+	/* first write in this cycle, notify the driver */
+	if (fbdefio->first_io && list_empty(&fbdefio->pagelist))
+		fbdefio->first_io(info);
+
+	/*
+	 * We want the page to remain locked from ->page_mkwrite until
+	 * the PTE is marked dirty to avoid page_mkclean() being called
+	 * before the PTE is updated, which would leave the page ignored
+	 * by defio.
+	 * Do this by locking the page here and informing the caller
+	 * about it with VM_FAULT_LOCKED.
+	 */
+	lock_page(page);
+
+	/* we loop through the pagelist before adding in order
+	to keep the pagelist sorted */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+		/* this check is to catch the case where a new
+		process could start writing to the same page
+		through a new pte. this new access can cause the
+		mkwrite even when the original ps's pte is marked
+		writable */
+		if (unlikely(cur == page))
+			goto page_already_added;
+		else if (cur->index > page->index)
+			break;
+	}
+
+	list_add_tail(&page->lru, &cur->lru);
+
+page_already_added:
+	mutex_unlock(&fbdefio->lock);
+
+	/* come back after delay to process the deferred IO */
+	schedule_delayed_work(&info->deferred_work, fbdefio->delay);
+	return VM_FAULT_LOCKED;
+}
+
+static const struct vm_operations_struct fb_deferred_io_vm_ops = {
+	.fault		= fb_deferred_io_fault,
+	.page_mkwrite	= fb_deferred_io_mkwrite,
+};
+
+static int fb_deferred_io_set_page_dirty(struct page *page)
+{
+	if (!PageDirty(page))
+		SetPageDirty(page);
+	return 0;
+}
+
+static const struct address_space_operations fb_deferred_io_aops = {
+	.set_page_dirty = fb_deferred_io_set_page_dirty,
+};
+
+static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	vma->vm_ops = &fb_deferred_io_vm_ops;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+	if (!(info->flags & FBINFO_VIRTFB))
+		vma->vm_flags |= VM_IO;
+	vma->vm_private_data = info;
+	return 0;
+}
+
+/* workqueue callback */
+static void fb_deferred_io_work(struct work_struct *work)
+{
+	struct fb_info *info = container_of(work, struct fb_info,
+						deferred_work.work);
+	struct list_head *node, *next;
+	struct page *cur;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+
+	/* here we mkclean the pages, then do all deferred IO */
+	mutex_lock(&fbdefio->lock);
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+		lock_page(cur);
+		page_mkclean(cur);
+		unlock_page(cur);
+	}
+
+	/* driver's callback with pagelist */
+	fbdefio->deferred_io(info, &fbdefio->pagelist);
+
+	/* clear the list */
+	list_for_each_safe(node, next, &fbdefio->pagelist) {
+		list_del(node);
+	}
+	mutex_unlock(&fbdefio->lock);
+}
+
+void fb_deferred_io_init(struct fb_info *info)
+{
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+
+	BUG_ON(!fbdefio);
+	mutex_init(&fbdefio->lock);
+	info->fbops->fb_mmap = fb_deferred_io_mmap;
+	INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work);
+	INIT_LIST_HEAD(&fbdefio->pagelist);
+	if (fbdefio->delay == 0) /* set a default of 1 s */
+		fbdefio->delay = HZ;
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_init);
+
+void fb_deferred_io_open(struct fb_info *info,
+			 struct inode *inode,
+			 struct file *file)
+{
+	file->f_mapping->a_ops = &fb_deferred_io_aops;
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_open);
+
+void fb_deferred_io_cleanup(struct fb_info *info)
+{
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct page *page;
+	int i;
+
+	BUG_ON(!fbdefio);
+	cancel_delayed_work_sync(&info->deferred_work);
+
+	/* clear out the mapping that we setup */
+	for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
+		page = fb_deferred_io_page(info, i);
+		page->mapping = NULL;
+	}
+
+	info->fbops->fb_mmap = NULL;
+	mutex_destroy(&fbdefio->lock);
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/fb_draw.h b/drivers/video/fbdev/core/fb_draw.h
new file mode 100644
index 000000000000..624ee115f129
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_draw.h
@@ -0,0 +1,186 @@
+#ifndef _FB_DRAW_H
+#define _FB_DRAW_H
+
+#include <asm/types.h>
+#include <linux/fb.h>
+#include <linux/bug.h>
+
+    /*
+     *  Compose two values, using a bitmask as decision value
+     *  This is equivalent to (a & mask) | (b & ~mask)
+     */
+
+static inline unsigned long
+comp(unsigned long a, unsigned long b, unsigned long mask)
+{
+    return ((a ^ b) & mask) ^ b;
+}
+
+    /*
+     *  Create a pattern with the given pixel's color
+     */
+
+#if BITS_PER_LONG == 64
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
+{
+	switch (bpp) {
+	case 1:
+		return 0xfffffffffffffffful*pixel;
+	case 2:
+		return 0x5555555555555555ul*pixel;
+	case 4:
+		return 0x1111111111111111ul*pixel;
+	case 8:
+		return 0x0101010101010101ul*pixel;
+	case 12:
+		return 0x1001001001001001ul*pixel;
+	case 16:
+		return 0x0001000100010001ul*pixel;
+	case 24:
+		return 0x0001000001000001ul*pixel;
+	case 32:
+		return 0x0000000100000001ul*pixel;
+	default:
+		WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp);
+		return 0;
+    }
+}
+#else
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
+{
+	switch (bpp) {
+	case 1:
+		return 0xfffffffful*pixel;
+	case 2:
+		return 0x55555555ul*pixel;
+	case 4:
+		return 0x11111111ul*pixel;
+	case 8:
+		return 0x01010101ul*pixel;
+	case 12:
+		return 0x01001001ul*pixel;
+	case 16:
+		return 0x00010001ul*pixel;
+	case 24:
+		return 0x01000001ul*pixel;
+	case 32:
+		return 0x00000001ul*pixel;
+	default:
+		WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp);
+		return 0;
+    }
+}
+#endif
+
+#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE
+#if BITS_PER_LONG == 64
+#define REV_PIXELS_MASK1 0x5555555555555555ul
+#define REV_PIXELS_MASK2 0x3333333333333333ul
+#define REV_PIXELS_MASK4 0x0f0f0f0f0f0f0f0ful
+#else
+#define REV_PIXELS_MASK1 0x55555555ul
+#define REV_PIXELS_MASK2 0x33333333ul
+#define REV_PIXELS_MASK4 0x0f0f0f0ful
+#endif
+
+static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+						  u32 bswapmask)
+{
+	if (bswapmask & 1)
+		val = comp(val >> 1, val << 1, REV_PIXELS_MASK1);
+	if (bswapmask & 2)
+		val = comp(val >> 2, val << 2, REV_PIXELS_MASK2);
+	if (bswapmask & 3)
+		val = comp(val >> 4, val << 4, REV_PIXELS_MASK4);
+	return val;
+}
+
+static inline u32 fb_shifted_pixels_mask_u32(struct fb_info *p, u32 index,
+					     u32 bswapmask)
+{
+	u32 mask;
+
+	if (!bswapmask) {
+		mask = FB_SHIFT_HIGH(p, ~(u32)0, index);
+	} else {
+		mask = 0xff << FB_LEFT_POS(p, 8);
+		mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask;
+		mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask));
+#if defined(__i386__) || defined(__x86_64__)
+		/* Shift argument is limited to 0 - 31 on x86 based CPU's */
+		if(index + bswapmask < 32)
+#endif
+			mask |= FB_SHIFT_HIGH(p, ~(u32)0,
+					(index + bswapmask) & ~(bswapmask));
+	}
+	return mask;
+}
+
+static inline unsigned long fb_shifted_pixels_mask_long(struct fb_info *p,
+							u32 index,
+							u32 bswapmask)
+{
+	unsigned long mask;
+
+	if (!bswapmask) {
+		mask = FB_SHIFT_HIGH(p, ~0UL, index);
+	} else {
+		mask = 0xff << FB_LEFT_POS(p, 8);
+		mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask;
+		mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask));
+#if defined(__i386__) || defined(__x86_64__)
+		/* Shift argument is limited to 0 - 31 on x86 based CPU's */
+		if(index + bswapmask < BITS_PER_LONG)
+#endif
+			mask |= FB_SHIFT_HIGH(p, ~0UL,
+					(index + bswapmask) & ~(bswapmask));
+	}
+	return mask;
+}
+
+
+static inline u32 fb_compute_bswapmask(struct fb_info *info)
+{
+	u32 bswapmask = 0;
+	unsigned bpp = info->var.bits_per_pixel;
+
+	if ((bpp < 8) && (info->var.nonstd & FB_NONSTD_REV_PIX_IN_B)) {
+		/*
+		 * Reversed order of pixel layout in bytes
+		 * works only for 1, 2 and 4 bpp
+		 */
+		bswapmask = 7 - bpp + 1;
+	}
+	return bswapmask;
+}
+
+#else /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
+
+static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+						  u32 bswapmask)
+{
+	return val;
+}
+
+#define fb_shifted_pixels_mask_u32(p, i, b) FB_SHIFT_HIGH((p), ~(u32)0, (i))
+#define fb_shifted_pixels_mask_long(p, i, b) FB_SHIFT_HIGH((p), ~0UL, (i))
+#define fb_compute_bswapmask(...) 0
+
+#endif  /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
+
+#define cpu_to_le_long _cpu_to_le_long(BITS_PER_LONG)
+#define _cpu_to_le_long(x) __cpu_to_le_long(x)
+#define __cpu_to_le_long(x) cpu_to_le##x
+
+#define le_long_to_cpu _le_long_to_cpu(BITS_PER_LONG)
+#define _le_long_to_cpu(x) __le_long_to_cpu(x)
+#define __le_long_to_cpu(x) le##x##_to_cpu
+
+static inline unsigned long rolx(unsigned long word, unsigned int shift, unsigned int x)
+{
+	return (word << shift) | (word >> (x - shift));
+}
+
+#endif /* FB_DRAW_H */
diff --git a/drivers/video/fbdev/core/fb_notify.c b/drivers/video/fbdev/core/fb_notify.c
new file mode 100644
index 000000000000..74c2da528884
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_notify.c
@@ -0,0 +1,47 @@
+/*
+ *  linux/drivers/video/fb_notify.c
+ *
+ *  Copyright (C) 2006 Antonino Daplas <adaplas@pol.net>
+ *
+ *	2001 - Documented with DocBook
+ *	- Brad Douglas <brad@neruo.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+#include <linux/fb.h>
+#include <linux/notifier.h>
+#include <linux/export.h>
+
+static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
+
+/**
+ *	fb_register_client - register a client notifier
+ *	@nb: notifier block to callback on events
+ */
+int fb_register_client(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&fb_notifier_list, nb);
+}
+EXPORT_SYMBOL(fb_register_client);
+
+/**
+ *	fb_unregister_client - unregister a client notifier
+ *	@nb: notifier block to callback on events
+ */
+int fb_unregister_client(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
+}
+EXPORT_SYMBOL(fb_unregister_client);
+
+/**
+ * fb_notifier_call_chain - notify clients of fb_events
+ *
+ */
+int fb_notifier_call_chain(unsigned long val, void *v)
+{
+	return blocking_notifier_call_chain(&fb_notifier_list, val, v);
+}
+EXPORT_SYMBOL_GPL(fb_notifier_call_chain);
diff --git a/drivers/video/fbdev/core/fb_sys_fops.c b/drivers/video/fbdev/core/fb_sys_fops.c
new file mode 100644
index 000000000000..ff275d7f3eaf
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_sys_fops.c
@@ -0,0 +1,104 @@
+/*
+ * linux/drivers/video/fb_sys_read.c - Generic file operations where
+ * framebuffer is in system RAM
+ *
+ * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
+		    loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	void *src;
+	int err = 0;
+	unsigned long total_size;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->screen_size;
+
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p >= total_size)
+		return 0;
+
+	if (count >= total_size)
+		count = total_size;
+
+	if (count + p > total_size)
+		count = total_size - p;
+
+	src = (void __force *)(info->screen_base + p);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	if (copy_to_user(buf, src, count))
+		err = -EFAULT;
+
+	if  (!err)
+		*ppos += count;
+
+	return (err) ? err : count;
+}
+EXPORT_SYMBOL_GPL(fb_sys_read);
+
+ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
+		     size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	void *dst;
+	int err = 0;
+	unsigned long total_size;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->screen_size;
+
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
+		count = total_size - p;
+	}
+
+	dst = (void __force *) (info->screen_base + p);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	if (copy_from_user(dst, buf, count))
+		err = -EFAULT;
+
+	if  (!err)
+		*ppos += count;
+
+	return (err) ? err : count;
+}
+EXPORT_SYMBOL_GPL(fb_sys_write);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("Generic file read (fb in system RAM)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
new file mode 100644
index 000000000000..f89245b8ba8e
--- /dev/null
+++ b/drivers/video/fbdev/core/fbcmap.c
@@ -0,0 +1,362 @@
+/*
+ *  linux/drivers/video/fbcmap.c -- Colormap handling for frame buffer devices
+ *
+ *	Created 15 Jun 1997 by Geert Uytterhoeven
+ *
+ *	2001 - Documented with DocBook
+ *	- Brad Douglas <brad@neruo.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+static u16 red2[] __read_mostly = {
+    0x0000, 0xaaaa
+};
+static u16 green2[] __read_mostly = {
+    0x0000, 0xaaaa
+};
+static u16 blue2[] __read_mostly = {
+    0x0000, 0xaaaa
+};
+
+static u16 red4[] __read_mostly = {
+    0x0000, 0xaaaa, 0x5555, 0xffff
+};
+static u16 green4[] __read_mostly = {
+    0x0000, 0xaaaa, 0x5555, 0xffff
+};
+static u16 blue4[] __read_mostly = {
+    0x0000, 0xaaaa, 0x5555, 0xffff
+};
+
+static u16 red8[] __read_mostly = {
+    0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa
+};
+static u16 green8[] __read_mostly = {
+    0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa
+};
+static u16 blue8[] __read_mostly = {
+    0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa
+};
+
+static u16 red16[] __read_mostly = {
+    0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
+    0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
+};
+static u16 green16[] __read_mostly = {
+    0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
+    0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
+};
+static u16 blue16[] __read_mostly = {
+    0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
+    0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
+};
+
+static const struct fb_cmap default_2_colors = {
+    .len=2, .red=red2, .green=green2, .blue=blue2
+};
+static const struct fb_cmap default_8_colors = {
+    .len=8, .red=red8, .green=green8, .blue=blue8
+};
+static const struct fb_cmap default_4_colors = {
+    .len=4, .red=red4, .green=green4, .blue=blue4
+};
+static const struct fb_cmap default_16_colors = {
+    .len=16, .red=red16, .green=green16, .blue=blue16
+};
+
+
+
+/**
+ *	fb_alloc_cmap - allocate a colormap
+ *	@cmap: frame buffer colormap structure
+ *	@len: length of @cmap
+ *	@transp: boolean, 1 if there is transparency, 0 otherwise
+ *	@flags: flags for kmalloc memory allocation
+ *
+ *	Allocates memory for a colormap @cmap.  @len is the
+ *	number of entries in the palette.
+ *
+ *	Returns negative errno on error, or zero on success.
+ *
+ */
+
+int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
+{
+	int size = len * sizeof(u16);
+	int ret = -ENOMEM;
+
+	if (cmap->len != len) {
+		fb_dealloc_cmap(cmap);
+		if (!len)
+			return 0;
+
+		cmap->red = kmalloc(size, flags);
+		if (!cmap->red)
+			goto fail;
+		cmap->green = kmalloc(size, flags);
+		if (!cmap->green)
+			goto fail;
+		cmap->blue = kmalloc(size, flags);
+		if (!cmap->blue)
+			goto fail;
+		if (transp) {
+			cmap->transp = kmalloc(size, flags);
+			if (!cmap->transp)
+				goto fail;
+		} else {
+			cmap->transp = NULL;
+		}
+	}
+	cmap->start = 0;
+	cmap->len = len;
+	ret = fb_copy_cmap(fb_default_cmap(len), cmap);
+	if (ret)
+		goto fail;
+	return 0;
+
+fail:
+	fb_dealloc_cmap(cmap);
+	return ret;
+}
+
+int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+	return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
+}
+
+/**
+ *      fb_dealloc_cmap - deallocate a colormap
+ *      @cmap: frame buffer colormap structure
+ *
+ *      Deallocates a colormap that was previously allocated with
+ *      fb_alloc_cmap().
+ *
+ */
+
+void fb_dealloc_cmap(struct fb_cmap *cmap)
+{
+	kfree(cmap->red);
+	kfree(cmap->green);
+	kfree(cmap->blue);
+	kfree(cmap->transp);
+
+	cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
+	cmap->len = 0;
+}
+
+/**
+ *	fb_copy_cmap - copy a colormap
+ *	@from: frame buffer colormap structure
+ *	@to: frame buffer colormap structure
+ *
+ *	Copy contents of colormap from @from to @to.
+ */
+
+int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
+{
+	int tooff = 0, fromoff = 0;
+	int size;
+
+	if (to->start > from->start)
+		fromoff = to->start - from->start;
+	else
+		tooff = from->start - to->start;
+	size = to->len - tooff;
+	if (size > (int) (from->len - fromoff))
+		size = from->len - fromoff;
+	if (size <= 0)
+		return -EINVAL;
+	size *= sizeof(u16);
+
+	memcpy(to->red+tooff, from->red+fromoff, size);
+	memcpy(to->green+tooff, from->green+fromoff, size);
+	memcpy(to->blue+tooff, from->blue+fromoff, size);
+	if (from->transp && to->transp)
+		memcpy(to->transp+tooff, from->transp+fromoff, size);
+	return 0;
+}
+
+int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
+{
+	int tooff = 0, fromoff = 0;
+	int size;
+
+	if (to->start > from->start)
+		fromoff = to->start - from->start;
+	else
+		tooff = from->start - to->start;
+	size = to->len - tooff;
+	if (size > (int) (from->len - fromoff))
+		size = from->len - fromoff;
+	if (size <= 0)
+		return -EINVAL;
+	size *= sizeof(u16);
+
+	if (copy_to_user(to->red+tooff, from->red+fromoff, size))
+		return -EFAULT;
+	if (copy_to_user(to->green+tooff, from->green+fromoff, size))
+		return -EFAULT;
+	if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
+		return -EFAULT;
+	if (from->transp && to->transp)
+		if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
+			return -EFAULT;
+	return 0;
+}
+
+/**
+ *	fb_set_cmap - set the colormap
+ *	@cmap: frame buffer colormap structure
+ *	@info: frame buffer info structure
+ *
+ *	Sets the colormap @cmap for a screen of device @info.
+ *
+ *	Returns negative errno on error, or zero on success.
+ *
+ */
+
+int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	int i, start, rc = 0;
+	u16 *red, *green, *blue, *transp;
+	u_int hred, hgreen, hblue, htransp = 0xffff;
+
+	red = cmap->red;
+	green = cmap->green;
+	blue = cmap->blue;
+	transp = cmap->transp;
+	start = cmap->start;
+
+	if (start < 0 || (!info->fbops->fb_setcolreg &&
+			  !info->fbops->fb_setcmap))
+		return -EINVAL;
+	if (info->fbops->fb_setcmap) {
+		rc = info->fbops->fb_setcmap(cmap, info);
+	} else {
+		for (i = 0; i < cmap->len; i++) {
+			hred = *red++;
+			hgreen = *green++;
+			hblue = *blue++;
+			if (transp)
+				htransp = *transp++;
+			if (info->fbops->fb_setcolreg(start++,
+						      hred, hgreen, hblue,
+						      htransp, info))
+				break;
+		}
+	}
+	if (rc == 0)
+		fb_copy_cmap(cmap, &info->cmap);
+
+	return rc;
+}
+
+int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
+{
+	int rc, size = cmap->len * sizeof(u16);
+	struct fb_cmap umap;
+
+	if (size < 0 || size < cmap->len)
+		return -E2BIG;
+
+	memset(&umap, 0, sizeof(struct fb_cmap));
+	rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
+				GFP_KERNEL);
+	if (rc)
+		return rc;
+	if (copy_from_user(umap.red, cmap->red, size) ||
+	    copy_from_user(umap.green, cmap->green, size) ||
+	    copy_from_user(umap.blue, cmap->blue, size) ||
+	    (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
+		rc = -EFAULT;
+		goto out;
+	}
+	umap.start = cmap->start;
+	if (!lock_fb_info(info)) {
+		rc = -ENODEV;
+		goto out;
+	}
+
+	rc = fb_set_cmap(&umap, info);
+	unlock_fb_info(info);
+out:
+	fb_dealloc_cmap(&umap);
+	return rc;
+}
+
+/**
+ *	fb_default_cmap - get default colormap
+ *	@len: size of palette for a depth
+ *
+ *	Gets the default colormap for a specific screen depth.  @len
+ *	is the size of the palette for a particular screen depth.
+ *
+ *	Returns pointer to a frame buffer colormap structure.
+ *
+ */
+
+const struct fb_cmap *fb_default_cmap(int len)
+{
+    if (len <= 2)
+	return &default_2_colors;
+    if (len <= 4)
+	return &default_4_colors;
+    if (len <= 8)
+	return &default_8_colors;
+    return &default_16_colors;
+}
+
+
+/**
+ *	fb_invert_cmaps - invert all defaults colormaps
+ *
+ *	Invert all default colormaps.
+ *
+ */
+
+void fb_invert_cmaps(void)
+{
+    u_int i;
+
+    for (i = 0; i < ARRAY_SIZE(red2); i++) {
+	red2[i] = ~red2[i];
+	green2[i] = ~green2[i];
+	blue2[i] = ~blue2[i];
+    }
+    for (i = 0; i < ARRAY_SIZE(red4); i++) {
+	red4[i] = ~red4[i];
+	green4[i] = ~green4[i];
+	blue4[i] = ~blue4[i];
+    }
+    for (i = 0; i < ARRAY_SIZE(red8); i++) {
+	red8[i] = ~red8[i];
+	green8[i] = ~green8[i];
+	blue8[i] = ~blue8[i];
+    }
+    for (i = 0; i < ARRAY_SIZE(red16); i++) {
+	red16[i] = ~red16[i];
+	green16[i] = ~green16[i];
+	blue16[i] = ~blue16[i];
+    }
+}
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(fb_alloc_cmap);
+EXPORT_SYMBOL(fb_dealloc_cmap);
+EXPORT_SYMBOL(fb_copy_cmap);
+EXPORT_SYMBOL(fb_set_cmap);
+EXPORT_SYMBOL(fb_default_cmap);
+EXPORT_SYMBOL(fb_invert_cmaps);
diff --git a/drivers/video/fbdev/core/fbcvt.c b/drivers/video/fbdev/core/fbcvt.c
new file mode 100644
index 000000000000..7cb715dfc0e1
--- /dev/null
+++ b/drivers/video/fbdev/core/fbcvt.c
@@ -0,0 +1,379 @@
+/*
+ * linux/drivers/video/fbcvt.c - VESA(TM) Coordinated Video Timings
+ *
+ * Copyright (C) 2005 Antonino Daplas <adaplas@pol.net>
+ *
+ *      Based from the VESA(TM) Coordinated Video Timing Generator by
+ *      Graham Loveridge April 9, 2003 available at
+ *      http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/slab.h>
+
+#define FB_CVT_CELLSIZE               8
+#define FB_CVT_GTF_C                 40
+#define FB_CVT_GTF_J                 20
+#define FB_CVT_GTF_K                128
+#define FB_CVT_GTF_M                600
+#define FB_CVT_MIN_VSYNC_BP         550
+#define FB_CVT_MIN_VPORCH             3
+#define FB_CVT_MIN_BPORCH             6
+
+#define FB_CVT_RB_MIN_VBLANK        460
+#define FB_CVT_RB_HBLANK            160
+#define FB_CVT_RB_V_FPORCH            3
+
+#define FB_CVT_FLAG_REDUCED_BLANK 1
+#define FB_CVT_FLAG_MARGINS       2
+#define FB_CVT_FLAG_INTERLACED    4
+
+struct fb_cvt_data {
+	u32 xres;
+	u32 yres;
+	u32 refresh;
+	u32 f_refresh;
+	u32 pixclock;
+	u32 hperiod;
+	u32 hblank;
+	u32 hfreq;
+	u32 htotal;
+	u32 vtotal;
+	u32 vsync;
+	u32 hsync;
+	u32 h_front_porch;
+	u32 h_back_porch;
+	u32 v_front_porch;
+	u32 v_back_porch;
+	u32 h_margin;
+	u32 v_margin;
+	u32 interlace;
+	u32 aspect_ratio;
+	u32 active_pixels;
+	u32 flags;
+	u32 status;
+};
+
+static const unsigned char fb_cvt_vbi_tab[] = {
+	4,        /* 4:3      */
+	5,        /* 16:9     */
+	6,        /* 16:10    */
+	7,        /* 5:4      */
+	7,        /* 15:9     */
+	8,        /* reserved */
+	9,        /* reserved */
+	10        /* custom   */
+};
+
+/* returns hperiod * 1000 */
+static u32 fb_cvt_hperiod(struct fb_cvt_data *cvt)
+{
+	u32 num = 1000000000/cvt->f_refresh;
+	u32 den;
+
+	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+		num -= FB_CVT_RB_MIN_VBLANK * 1000;
+		den = 2 * (cvt->yres/cvt->interlace + 2 * cvt->v_margin);
+	} else {
+		num -= FB_CVT_MIN_VSYNC_BP * 1000;
+		den = 2 * (cvt->yres/cvt->interlace + cvt->v_margin * 2
+			   + FB_CVT_MIN_VPORCH + cvt->interlace/2);
+	}
+
+	return 2 * (num/den);
+}
+
+/* returns ideal duty cycle * 1000 */
+static u32 fb_cvt_ideal_duty_cycle(struct fb_cvt_data *cvt)
+{
+	u32 c_prime = (FB_CVT_GTF_C - FB_CVT_GTF_J) *
+		(FB_CVT_GTF_K) + 256 * FB_CVT_GTF_J;
+	u32 m_prime = (FB_CVT_GTF_K * FB_CVT_GTF_M);
+	u32 h_period_est = cvt->hperiod;
+
+	return (1000 * c_prime  - ((m_prime * h_period_est)/1000))/256;
+}
+
+static u32 fb_cvt_hblank(struct fb_cvt_data *cvt)
+{
+	u32 hblank = 0;
+
+	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+		hblank = FB_CVT_RB_HBLANK;
+	else {
+		u32 ideal_duty_cycle = fb_cvt_ideal_duty_cycle(cvt);
+		u32 active_pixels = cvt->active_pixels;
+
+		if (ideal_duty_cycle < 20000)
+			hblank = (active_pixels * 20000)/
+				(100000 - 20000);
+		else {
+			hblank = (active_pixels * ideal_duty_cycle)/
+				(100000 - ideal_duty_cycle);
+		}
+	}
+
+	hblank &= ~((2 * FB_CVT_CELLSIZE) - 1);
+
+	return hblank;
+}
+
+static u32 fb_cvt_hsync(struct fb_cvt_data *cvt)
+{
+	u32 hsync;
+
+	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+		hsync = 32;
+	else
+		hsync = (FB_CVT_CELLSIZE * cvt->htotal)/100;
+
+	hsync &= ~(FB_CVT_CELLSIZE - 1);
+	return hsync;
+}
+
+static u32 fb_cvt_vbi_lines(struct fb_cvt_data *cvt)
+{
+	u32 vbi_lines, min_vbi_lines, act_vbi_lines;
+
+	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+		vbi_lines = (1000 * FB_CVT_RB_MIN_VBLANK)/cvt->hperiod + 1;
+		min_vbi_lines =  FB_CVT_RB_V_FPORCH + cvt->vsync +
+			FB_CVT_MIN_BPORCH;
+
+	} else {
+		vbi_lines = (FB_CVT_MIN_VSYNC_BP * 1000)/cvt->hperiod + 1 +
+			 FB_CVT_MIN_VPORCH;
+		min_vbi_lines = cvt->vsync + FB_CVT_MIN_BPORCH +
+			FB_CVT_MIN_VPORCH;
+	}
+
+	if (vbi_lines < min_vbi_lines)
+		act_vbi_lines = min_vbi_lines;
+	else
+		act_vbi_lines = vbi_lines;
+
+	return act_vbi_lines;
+}
+
+static u32 fb_cvt_vtotal(struct fb_cvt_data *cvt)
+{
+	u32 vtotal = cvt->yres/cvt->interlace;
+
+	vtotal += 2 * cvt->v_margin + cvt->interlace/2 + fb_cvt_vbi_lines(cvt);
+	vtotal |= cvt->interlace/2;
+
+	return vtotal;
+}
+
+static u32 fb_cvt_pixclock(struct fb_cvt_data *cvt)
+{
+	u32 pixclock;
+
+	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+		pixclock = (cvt->f_refresh * cvt->vtotal * cvt->htotal)/1000;
+	else
+		pixclock = (cvt->htotal * 1000000)/cvt->hperiod;
+
+	pixclock /= 250;
+	pixclock *= 250;
+	pixclock *= 1000;
+
+	return pixclock;
+}
+
+static u32 fb_cvt_aspect_ratio(struct fb_cvt_data *cvt)
+{
+	u32 xres = cvt->xres;
+	u32 yres = cvt->yres;
+	u32 aspect = -1;
+
+	if (xres == (yres * 4)/3 && !((yres * 4) % 3))
+		aspect = 0;
+	else if (xres == (yres * 16)/9 && !((yres * 16) % 9))
+		aspect = 1;
+	else if (xres == (yres * 16)/10 && !((yres * 16) % 10))
+		aspect = 2;
+	else if (xres == (yres * 5)/4 && !((yres * 5) % 4))
+		aspect = 3;
+	else if (xres == (yres * 15)/9 && !((yres * 15) % 9))
+		aspect = 4;
+	else {
+		printk(KERN_INFO "fbcvt: Aspect ratio not CVT "
+		       "standard\n");
+		aspect = 7;
+		cvt->status = 1;
+	}
+
+	return aspect;
+}
+
+static void fb_cvt_print_name(struct fb_cvt_data *cvt)
+{
+	u32 pixcount, pixcount_mod;
+	int cnt = 255, offset = 0, read = 0;
+	u8 *buf = kzalloc(256, GFP_KERNEL);
+
+	if (!buf)
+		return;
+
+	pixcount = (cvt->xres * (cvt->yres/cvt->interlace))/1000000;
+	pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000;
+	pixcount_mod /= 1000;
+
+	read = snprintf(buf+offset, cnt, "fbcvt: %dx%d@%d: CVT Name - ",
+			cvt->xres, cvt->yres, cvt->refresh);
+	offset += read;
+	cnt -= read;
+
+	if (cvt->status)
+		snprintf(buf+offset, cnt, "Not a CVT standard - %d.%03d Mega "
+			 "Pixel Image\n", pixcount, pixcount_mod);
+	else {
+		if (pixcount) {
+			read = snprintf(buf+offset, cnt, "%d", pixcount);
+			cnt -= read;
+			offset += read;
+		}
+
+		read = snprintf(buf+offset, cnt, ".%03dM", pixcount_mod);
+		cnt -= read;
+		offset += read;
+
+		if (cvt->aspect_ratio == 0)
+			read = snprintf(buf+offset, cnt, "3");
+		else if (cvt->aspect_ratio == 3)
+			read = snprintf(buf+offset, cnt, "4");
+		else if (cvt->aspect_ratio == 1 || cvt->aspect_ratio == 4)
+			read = snprintf(buf+offset, cnt, "9");
+		else if (cvt->aspect_ratio == 2)
+			read = snprintf(buf+offset, cnt, "A");
+		else
+			read = 0;
+		cnt -= read;
+		offset += read;
+
+		if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+			read = snprintf(buf+offset, cnt, "-R");
+			cnt -= read;
+			offset += read;
+		}
+	}
+
+	printk(KERN_INFO "%s\n", buf);
+	kfree(buf);
+}
+
+static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt,
+				   struct fb_videomode *mode)
+{
+	mode->refresh = cvt->f_refresh;
+	mode->pixclock = KHZ2PICOS(cvt->pixclock/1000);
+	mode->left_margin = cvt->h_back_porch;
+	mode->right_margin = cvt->h_front_porch;
+	mode->hsync_len = cvt->hsync;
+	mode->upper_margin = cvt->v_back_porch;
+	mode->lower_margin = cvt->v_front_porch;
+	mode->vsync_len = cvt->vsync;
+
+	mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
+
+	if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	else
+		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+}
+
+/*
+ * fb_find_mode_cvt - calculate mode using VESA(TM) CVT
+ * @mode: pointer to fb_videomode; xres, yres, refresh and vmode must be
+ *        pre-filled with the desired values
+ * @margins: add margin to calculation (1.8% of xres and yres)
+ * @rb: compute with reduced blanking (for flatpanels)
+ *
+ * RETURNS:
+ * 0 for success
+ * @mode is filled with computed values.  If interlaced, the refresh field
+ * will be filled with the field rate (2x the frame rate)
+ *
+ * DESCRIPTION:
+ * Computes video timings using VESA(TM) Coordinated Video Timings
+ */
+int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb)
+{
+	struct fb_cvt_data cvt;
+
+	memset(&cvt, 0, sizeof(cvt));
+
+	if (margins)
+	    cvt.flags |= FB_CVT_FLAG_MARGINS;
+
+	if (rb)
+	    cvt.flags |= FB_CVT_FLAG_REDUCED_BLANK;
+
+	if (mode->vmode & FB_VMODE_INTERLACED)
+	    cvt.flags |= FB_CVT_FLAG_INTERLACED;
+
+	cvt.xres = mode->xres;
+	cvt.yres = mode->yres;
+	cvt.refresh = mode->refresh;
+	cvt.f_refresh = cvt.refresh;
+	cvt.interlace = 1;
+
+	if (!cvt.xres || !cvt.yres || !cvt.refresh) {
+		printk(KERN_INFO "fbcvt: Invalid input parameters\n");
+		return 1;
+	}
+
+	if (!(cvt.refresh == 50 || cvt.refresh == 60 || cvt.refresh == 70 ||
+	      cvt.refresh == 85)) {
+		printk(KERN_INFO "fbcvt: Refresh rate not CVT "
+		       "standard\n");
+		cvt.status = 1;
+	}
+
+	cvt.xres &= ~(FB_CVT_CELLSIZE - 1);
+
+	if (cvt.flags & FB_CVT_FLAG_INTERLACED) {
+		cvt.interlace = 2;
+		cvt.f_refresh *= 2;
+	}
+
+	if (cvt.flags & FB_CVT_FLAG_REDUCED_BLANK) {
+		if (cvt.refresh != 60) {
+			printk(KERN_INFO "fbcvt: 60Hz refresh rate "
+			       "advised for reduced blanking\n");
+			cvt.status = 1;
+		}
+	}
+
+	if (cvt.flags & FB_CVT_FLAG_MARGINS) {
+		cvt.h_margin = (cvt.xres * 18)/1000;
+		cvt.h_margin &= ~(FB_CVT_CELLSIZE - 1);
+		cvt.v_margin = ((cvt.yres/cvt.interlace)* 18)/1000;
+	}
+
+	cvt.aspect_ratio = fb_cvt_aspect_ratio(&cvt);
+	cvt.active_pixels = cvt.xres + 2 * cvt.h_margin;
+	cvt.hperiod = fb_cvt_hperiod(&cvt);
+	cvt.vsync = fb_cvt_vbi_tab[cvt.aspect_ratio];
+	cvt.vtotal = fb_cvt_vtotal(&cvt);
+	cvt.hblank = fb_cvt_hblank(&cvt);
+	cvt.htotal = cvt.active_pixels + cvt.hblank;
+	cvt.hsync = fb_cvt_hsync(&cvt);
+	cvt.pixclock = fb_cvt_pixclock(&cvt);
+	cvt.hfreq = cvt.pixclock/cvt.htotal;
+	cvt.h_back_porch = cvt.hblank/2 + cvt.h_margin;
+	cvt.h_front_porch = cvt.hblank - cvt.hsync - cvt.h_back_porch +
+		2 * cvt.h_margin;
+	cvt.v_back_porch = 3 + cvt.v_margin;
+	cvt.v_front_porch = cvt.vtotal - cvt.yres/cvt.interlace -
+	    cvt.v_back_porch - cvt.vsync;
+	fb_cvt_print_name(&cvt);
+	fb_cvt_convert_to_mode(&cvt, mode);
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
new file mode 100644
index 000000000000..b6d5008f361f
--- /dev/null
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -0,0 +1,2002 @@
+/*
+ *  linux/drivers/video/fbmem.c
+ *
+ *  Copyright (C) 1994 Martin Schaller
+ *
+ *	2001 - Documented with DocBook
+ *	- Brad Douglas <brad@neruo.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+
+#include <linux/compat.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/vt.h>
+#include <linux/init.h>
+#include <linux/linux_logo.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/kmod.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/efi.h>
+#include <linux/fb.h>
+
+#include <asm/fb.h>
+
+
+    /*
+     *  Frame buffer device initialization and setup routines
+     */
+
+#define FBPIXMAPSIZE	(1024 * 8)
+
+static DEFINE_MUTEX(registration_lock);
+
+struct fb_info *registered_fb[FB_MAX] __read_mostly;
+EXPORT_SYMBOL(registered_fb);
+
+int num_registered_fb __read_mostly;
+EXPORT_SYMBOL(num_registered_fb);
+
+static struct fb_info *get_fb_info(unsigned int idx)
+{
+	struct fb_info *fb_info;
+
+	if (idx >= FB_MAX)
+		return ERR_PTR(-ENODEV);
+
+	mutex_lock(&registration_lock);
+	fb_info = registered_fb[idx];
+	if (fb_info)
+		atomic_inc(&fb_info->count);
+	mutex_unlock(&registration_lock);
+
+	return fb_info;
+}
+
+static void put_fb_info(struct fb_info *fb_info)
+{
+	if (!atomic_dec_and_test(&fb_info->count))
+		return;
+	if (fb_info->fbops->fb_destroy)
+		fb_info->fbops->fb_destroy(fb_info);
+}
+
+int lock_fb_info(struct fb_info *info)
+{
+	mutex_lock(&info->lock);
+	if (!info->fbops) {
+		mutex_unlock(&info->lock);
+		return 0;
+	}
+	return 1;
+}
+EXPORT_SYMBOL(lock_fb_info);
+
+/*
+ * Helpers
+ */
+
+int fb_get_color_depth(struct fb_var_screeninfo *var,
+		       struct fb_fix_screeninfo *fix)
+{
+	int depth = 0;
+
+	if (fix->visual == FB_VISUAL_MONO01 ||
+	    fix->visual == FB_VISUAL_MONO10)
+		depth = 1;
+	else {
+		if (var->green.length == var->blue.length &&
+		    var->green.length == var->red.length &&
+		    var->green.offset == var->blue.offset &&
+		    var->green.offset == var->red.offset)
+			depth = var->green.length;
+		else
+			depth = var->green.length + var->red.length +
+				var->blue.length;
+	}
+
+	return depth;
+}
+EXPORT_SYMBOL(fb_get_color_depth);
+
+/*
+ * Data padding functions.
+ */
+void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
+{
+	__fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
+}
+EXPORT_SYMBOL(fb_pad_aligned_buffer);
+
+void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
+				u32 shift_high, u32 shift_low, u32 mod)
+{
+	u8 mask = (u8) (0xfff << shift_high), tmp;
+	int i, j;
+
+	for (i = height; i--; ) {
+		for (j = 0; j < idx; j++) {
+			tmp = dst[j];
+			tmp &= mask;
+			tmp |= *src >> shift_low;
+			dst[j] = tmp;
+			tmp = *src << shift_high;
+			dst[j+1] = tmp;
+			src++;
+		}
+		tmp = dst[idx];
+		tmp &= mask;
+		tmp |= *src >> shift_low;
+		dst[idx] = tmp;
+		if (shift_high < mod) {
+			tmp = *src << shift_high;
+			dst[idx+1] = tmp;
+		}
+		src++;
+		dst += d_pitch;
+	}
+}
+EXPORT_SYMBOL(fb_pad_unaligned_buffer);
+
+/*
+ * we need to lock this section since fb_cursor
+ * may use fb_imageblit()
+ */
+char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
+{
+	u32 align = buf->buf_align - 1, offset;
+	char *addr = buf->addr;
+
+	/* If IO mapped, we need to sync before access, no sharing of
+	 * the pixmap is done
+	 */
+	if (buf->flags & FB_PIXMAP_IO) {
+		if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
+			info->fbops->fb_sync(info);
+		return addr;
+	}
+
+	/* See if we fit in the remaining pixmap space */
+	offset = buf->offset + align;
+	offset &= ~align;
+	if (offset + size > buf->size) {
+		/* We do not fit. In order to be able to re-use the buffer,
+		 * we must ensure no asynchronous DMA'ing or whatever operation
+		 * is in progress, we sync for that.
+		 */
+		if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
+			info->fbops->fb_sync(info);
+		offset = 0;
+	}
+	buf->offset = offset + size;
+	addr += offset;
+
+	return addr;
+}
+EXPORT_SYMBOL(fb_get_buffer_offset);
+
+#ifdef CONFIG_LOGO
+
+static inline unsigned safe_shift(unsigned d, int n)
+{
+	return n < 0 ? d >> -n : d << n;
+}
+
+static void fb_set_logocmap(struct fb_info *info,
+				   const struct linux_logo *logo)
+{
+	struct fb_cmap palette_cmap;
+	u16 palette_green[16];
+	u16 palette_blue[16];
+	u16 palette_red[16];
+	int i, j, n;
+	const unsigned char *clut = logo->clut;
+
+	palette_cmap.start = 0;
+	palette_cmap.len = 16;
+	palette_cmap.red = palette_red;
+	palette_cmap.green = palette_green;
+	palette_cmap.blue = palette_blue;
+	palette_cmap.transp = NULL;
+
+	for (i = 0; i < logo->clutsize; i += n) {
+		n = logo->clutsize - i;
+		/* palette_cmap provides space for only 16 colors at once */
+		if (n > 16)
+			n = 16;
+		palette_cmap.start = 32 + i;
+		palette_cmap.len = n;
+		for (j = 0; j < n; ++j) {
+			palette_cmap.red[j] = clut[0] << 8 | clut[0];
+			palette_cmap.green[j] = clut[1] << 8 | clut[1];
+			palette_cmap.blue[j] = clut[2] << 8 | clut[2];
+			clut += 3;
+		}
+		fb_set_cmap(&palette_cmap, info);
+	}
+}
+
+static void  fb_set_logo_truepalette(struct fb_info *info,
+					    const struct linux_logo *logo,
+					    u32 *palette)
+{
+	static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
+	unsigned char redmask, greenmask, bluemask;
+	int redshift, greenshift, blueshift;
+	int i;
+	const unsigned char *clut = logo->clut;
+
+	/*
+	 * We have to create a temporary palette since console palette is only
+	 * 16 colors long.
+	 */
+	/* Bug: Doesn't obey msb_right ... (who needs that?) */
+	redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
+	greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
+	bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
+	redshift   = info->var.red.offset   - (8 - info->var.red.length);
+	greenshift = info->var.green.offset - (8 - info->var.green.length);
+	blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
+
+	for ( i = 0; i < logo->clutsize; i++) {
+		palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
+				 safe_shift((clut[1] & greenmask), greenshift) |
+				 safe_shift((clut[2] & bluemask), blueshift));
+		clut += 3;
+	}
+}
+
+static void fb_set_logo_directpalette(struct fb_info *info,
+					     const struct linux_logo *logo,
+					     u32 *palette)
+{
+	int redshift, greenshift, blueshift;
+	int i;
+
+	redshift = info->var.red.offset;
+	greenshift = info->var.green.offset;
+	blueshift = info->var.blue.offset;
+
+	for (i = 32; i < 32 + logo->clutsize; i++)
+		palette[i] = i << redshift | i << greenshift | i << blueshift;
+}
+
+static void fb_set_logo(struct fb_info *info,
+			       const struct linux_logo *logo, u8 *dst,
+			       int depth)
+{
+	int i, j, k;
+	const u8 *src = logo->data;
+	u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+	u8 fg = 1, d;
+
+	switch (fb_get_color_depth(&info->var, &info->fix)) {
+	case 1:
+		fg = 1;
+		break;
+	case 2:
+		fg = 3;
+		break;
+	default:
+		fg = 7;
+		break;
+	}
+
+	if (info->fix.visual == FB_VISUAL_MONO01 ||
+	    info->fix.visual == FB_VISUAL_MONO10)
+		fg = ~((u8) (0xfff << info->var.green.length));
+
+	switch (depth) {
+	case 4:
+		for (i = 0; i < logo->height; i++)
+			for (j = 0; j < logo->width; src++) {
+				*dst++ = *src >> 4;
+				j++;
+				if (j < logo->width) {
+					*dst++ = *src & 0x0f;
+					j++;
+				}
+			}
+		break;
+	case 1:
+		for (i = 0; i < logo->height; i++) {
+			for (j = 0; j < logo->width; src++) {
+				d = *src ^ xor;
+				for (k = 7; k >= 0; k--) {
+					*dst++ = ((d >> k) & 1) ? fg : 0;
+					j++;
+				}
+			}
+		}
+		break;
+	}
+}
+
+/*
+ * Three (3) kinds of logo maps exist.  linux_logo_clut224 (>16 colors),
+ * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors).  Depending on
+ * the visual format and color depth of the framebuffer, the DAC, the
+ * pseudo_palette, and the logo data will be adjusted accordingly.
+ *
+ * Case 1 - linux_logo_clut224:
+ * Color exceeds the number of console colors (16), thus we set the hardware DAC
+ * using fb_set_cmap() appropriately.  The "needs_cmapreset"  flag will be set.
+ *
+ * For visuals that require color info from the pseudo_palette, we also construct
+ * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
+ * will be set.
+ *
+ * Case 2 - linux_logo_vga16:
+ * The number of colors just matches the console colors, thus there is no need
+ * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
+ * each byte contains color information for two pixels (upper and lower nibble).
+ * To be consistent with fb_imageblit() usage, we therefore separate the two
+ * nibbles into separate bytes. The "depth" flag will be set to 4.
+ *
+ * Case 3 - linux_logo_mono:
+ * This is similar with Case 2.  Each byte contains information for 8 pixels.
+ * We isolate each bit and expand each into a byte. The "depth" flag will
+ * be set to 1.
+ */
+static struct logo_data {
+	int depth;
+	int needs_directpalette;
+	int needs_truepalette;
+	int needs_cmapreset;
+	const struct linux_logo *logo;
+} fb_logo __read_mostly;
+
+static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
+{
+	u32 size = width * height, i;
+
+	out += size - 1;
+
+	for (i = size; i--; )
+		*out-- = *in++;
+}
+
+static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
+{
+	int i, j, h = height - 1;
+
+	for (i = 0; i < height; i++)
+		for (j = 0; j < width; j++)
+				out[height * j + h - i] = *in++;
+}
+
+static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
+{
+	int i, j, w = width - 1;
+
+	for (i = 0; i < height; i++)
+		for (j = 0; j < width; j++)
+			out[height * (w - j) + i] = *in++;
+}
+
+static void fb_rotate_logo(struct fb_info *info, u8 *dst,
+			   struct fb_image *image, int rotate)
+{
+	u32 tmp;
+
+	if (rotate == FB_ROTATE_UD) {
+		fb_rotate_logo_ud(image->data, dst, image->width,
+				  image->height);
+		image->dx = info->var.xres - image->width - image->dx;
+		image->dy = info->var.yres - image->height - image->dy;
+	} else if (rotate == FB_ROTATE_CW) {
+		fb_rotate_logo_cw(image->data, dst, image->width,
+				  image->height);
+		tmp = image->width;
+		image->width = image->height;
+		image->height = tmp;
+		tmp = image->dy;
+		image->dy = image->dx;
+		image->dx = info->var.xres - image->width - tmp;
+	} else if (rotate == FB_ROTATE_CCW) {
+		fb_rotate_logo_ccw(image->data, dst, image->width,
+				   image->height);
+		tmp = image->width;
+		image->width = image->height;
+		image->height = tmp;
+		tmp = image->dx;
+		image->dx = image->dy;
+		image->dy = info->var.yres - image->height - tmp;
+	}
+
+	image->data = dst;
+}
+
+static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
+			    int rotate, unsigned int num)
+{
+	unsigned int x;
+
+	if (rotate == FB_ROTATE_UR) {
+		for (x = 0;
+		     x < num && image->dx + image->width <= info->var.xres;
+		     x++) {
+			info->fbops->fb_imageblit(info, image);
+			image->dx += image->width + 8;
+		}
+	} else if (rotate == FB_ROTATE_UD) {
+		for (x = 0; x < num && image->dx >= 0; x++) {
+			info->fbops->fb_imageblit(info, image);
+			image->dx -= image->width + 8;
+		}
+	} else if (rotate == FB_ROTATE_CW) {
+		for (x = 0;
+		     x < num && image->dy + image->height <= info->var.yres;
+		     x++) {
+			info->fbops->fb_imageblit(info, image);
+			image->dy += image->height + 8;
+		}
+	} else if (rotate == FB_ROTATE_CCW) {
+		for (x = 0; x < num && image->dy >= 0; x++) {
+			info->fbops->fb_imageblit(info, image);
+			image->dy -= image->height + 8;
+		}
+	}
+}
+
+static int fb_show_logo_line(struct fb_info *info, int rotate,
+			     const struct linux_logo *logo, int y,
+			     unsigned int n)
+{
+	u32 *palette = NULL, *saved_pseudo_palette = NULL;
+	unsigned char *logo_new = NULL, *logo_rotate = NULL;
+	struct fb_image image;
+
+	/* Return if the frame buffer is not mapped or suspended */
+	if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
+	    info->flags & FBINFO_MODULE)
+		return 0;
+
+	image.depth = 8;
+	image.data = logo->data;
+
+	if (fb_logo.needs_cmapreset)
+		fb_set_logocmap(info, logo);
+
+	if (fb_logo.needs_truepalette ||
+	    fb_logo.needs_directpalette) {
+		palette = kmalloc(256 * 4, GFP_KERNEL);
+		if (palette == NULL)
+			return 0;
+
+		if (fb_logo.needs_truepalette)
+			fb_set_logo_truepalette(info, logo, palette);
+		else
+			fb_set_logo_directpalette(info, logo, palette);
+
+		saved_pseudo_palette = info->pseudo_palette;
+		info->pseudo_palette = palette;
+	}
+
+	if (fb_logo.depth <= 4) {
+		logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
+		if (logo_new == NULL) {
+			kfree(palette);
+			if (saved_pseudo_palette)
+				info->pseudo_palette = saved_pseudo_palette;
+			return 0;
+		}
+		image.data = logo_new;
+		fb_set_logo(info, logo, logo_new, fb_logo.depth);
+	}
+
+	image.dx = 0;
+	image.dy = y;
+	image.width = logo->width;
+	image.height = logo->height;
+
+	if (rotate) {
+		logo_rotate = kmalloc(logo->width *
+				      logo->height, GFP_KERNEL);
+		if (logo_rotate)
+			fb_rotate_logo(info, logo_rotate, &image, rotate);
+	}
+
+	fb_do_show_logo(info, &image, rotate, n);
+
+	kfree(palette);
+	if (saved_pseudo_palette != NULL)
+		info->pseudo_palette = saved_pseudo_palette;
+	kfree(logo_new);
+	kfree(logo_rotate);
+	return logo->height;
+}
+
+
+#ifdef CONFIG_FB_LOGO_EXTRA
+
+#define FB_LOGO_EX_NUM_MAX 10
+static struct logo_data_extra {
+	const struct linux_logo *logo;
+	unsigned int n;
+} fb_logo_ex[FB_LOGO_EX_NUM_MAX];
+static unsigned int fb_logo_ex_num;
+
+void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
+{
+	if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
+		return;
+
+	fb_logo_ex[fb_logo_ex_num].logo = logo;
+	fb_logo_ex[fb_logo_ex_num].n = n;
+	fb_logo_ex_num++;
+}
+
+static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
+				  unsigned int yres)
+{
+	unsigned int i;
+
+	/* FIXME: logo_ex supports only truecolor fb. */
+	if (info->fix.visual != FB_VISUAL_TRUECOLOR)
+		fb_logo_ex_num = 0;
+
+	for (i = 0; i < fb_logo_ex_num; i++) {
+		if (fb_logo_ex[i].logo->type != fb_logo.logo->type) {
+			fb_logo_ex[i].logo = NULL;
+			continue;
+		}
+		height += fb_logo_ex[i].logo->height;
+		if (height > yres) {
+			height -= fb_logo_ex[i].logo->height;
+			fb_logo_ex_num = i;
+			break;
+		}
+	}
+	return height;
+}
+
+static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+	unsigned int i;
+
+	for (i = 0; i < fb_logo_ex_num; i++)
+		y += fb_show_logo_line(info, rotate,
+				       fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
+
+	return y;
+}
+
+#else /* !CONFIG_FB_LOGO_EXTRA */
+
+static inline int fb_prepare_extra_logos(struct fb_info *info,
+					 unsigned int height,
+					 unsigned int yres)
+{
+	return height;
+}
+
+static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+	return y;
+}
+
+#endif /* CONFIG_FB_LOGO_EXTRA */
+
+
+int fb_prepare_logo(struct fb_info *info, int rotate)
+{
+	int depth = fb_get_color_depth(&info->var, &info->fix);
+	unsigned int yres;
+
+	memset(&fb_logo, 0, sizeof(struct logo_data));
+
+	if (info->flags & FBINFO_MISC_TILEBLITTING ||
+	    info->flags & FBINFO_MODULE)
+		return 0;
+
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		depth = info->var.blue.length;
+		if (info->var.red.length < depth)
+			depth = info->var.red.length;
+		if (info->var.green.length < depth)
+			depth = info->var.green.length;
+	}
+
+	if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {
+		/* assume console colormap */
+		depth = 4;
+	}
+
+	/* Return if no suitable logo was found */
+	fb_logo.logo = fb_find_logo(depth);
+
+	if (!fb_logo.logo) {
+		return 0;
+	}
+
+	if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
+		yres = info->var.yres;
+	else
+		yres = info->var.xres;
+
+	if (fb_logo.logo->height > yres) {
+		fb_logo.logo = NULL;
+		return 0;
+	}
+
+	/* What depth we asked for might be different from what we get */
+	if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
+		fb_logo.depth = 8;
+	else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
+		fb_logo.depth = 4;
+	else
+		fb_logo.depth = 1;
+
+
+ 	if (fb_logo.depth > 4 && depth > 4) {
+ 		switch (info->fix.visual) {
+ 		case FB_VISUAL_TRUECOLOR:
+ 			fb_logo.needs_truepalette = 1;
+ 			break;
+ 		case FB_VISUAL_DIRECTCOLOR:
+ 			fb_logo.needs_directpalette = 1;
+ 			fb_logo.needs_cmapreset = 1;
+ 			break;
+ 		case FB_VISUAL_PSEUDOCOLOR:
+ 			fb_logo.needs_cmapreset = 1;
+ 			break;
+ 		}
+ 	}
+
+	return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
+}
+
+int fb_show_logo(struct fb_info *info, int rotate)
+{
+	int y;
+
+	y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
+			      num_online_cpus());
+	y = fb_show_extra_logos(info, y, rotate);
+
+	return y;
+}
+#else
+int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
+int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
+#endif /* CONFIG_LOGO */
+EXPORT_SYMBOL(fb_show_logo);
+
+static void *fb_seq_start(struct seq_file *m, loff_t *pos)
+{
+	mutex_lock(&registration_lock);
+	return (*pos < FB_MAX) ? pos : NULL;
+}
+
+static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return (*pos < FB_MAX) ? pos : NULL;
+}
+
+static void fb_seq_stop(struct seq_file *m, void *v)
+{
+	mutex_unlock(&registration_lock);
+}
+
+static int fb_seq_show(struct seq_file *m, void *v)
+{
+	int i = *(loff_t *)v;
+	struct fb_info *fi = registered_fb[i];
+
+	if (fi)
+		seq_printf(m, "%d %s\n", fi->node, fi->fix.id);
+	return 0;
+}
+
+static const struct seq_operations proc_fb_seq_ops = {
+	.start	= fb_seq_start,
+	.next	= fb_seq_next,
+	.stop	= fb_seq_stop,
+	.show	= fb_seq_show,
+};
+
+static int proc_fb_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &proc_fb_seq_ops);
+}
+
+static const struct file_operations fb_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_fb_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+/*
+ * We hold a reference to the fb_info in file->private_data,
+ * but if the current registered fb has changed, we don't
+ * actually want to use it.
+ *
+ * So look up the fb_info using the inode minor number,
+ * and just verify it against the reference we have.
+ */
+static struct fb_info *file_fb_info(struct file *file)
+{
+	struct inode *inode = file_inode(file);
+	int fbidx = iminor(inode);
+	struct fb_info *info = registered_fb[fbidx];
+
+	if (info != file->private_data)
+		info = NULL;
+	return info;
+}
+
+static ssize_t
+fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	struct fb_info *info = file_fb_info(file);
+	u8 *buffer, *dst;
+	u8 __iomem *src;
+	int c, cnt = 0, err = 0;
+	unsigned long total_size;
+
+	if (!info || ! info->screen_base)
+		return -ENODEV;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	if (info->fbops->fb_read)
+		return info->fbops->fb_read(info, buf, count, ppos);
+	
+	total_size = info->screen_size;
+
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p >= total_size)
+		return 0;
+
+	if (count >= total_size)
+		count = total_size;
+
+	if (count + p > total_size)
+		count = total_size - p;
+
+	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+			 GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	src = (u8 __iomem *) (info->screen_base + p);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	while (count) {
+		c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		dst = buffer;
+		fb_memcpy_fromfb(dst, src, c);
+		dst += c;
+		src += c;
+
+		if (copy_to_user(buf, buffer, c)) {
+			err = -EFAULT;
+			break;
+		}
+		*ppos += c;
+		buf += c;
+		cnt += c;
+		count -= c;
+	}
+
+	kfree(buffer);
+
+	return (err) ? err : cnt;
+}
+
+static ssize_t
+fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	struct fb_info *info = file_fb_info(file);
+	u8 *buffer, *src;
+	u8 __iomem *dst;
+	int c, cnt = 0, err = 0;
+	unsigned long total_size;
+
+	if (!info || !info->screen_base)
+		return -ENODEV;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	if (info->fbops->fb_write)
+		return info->fbops->fb_write(info, buf, count, ppos);
+	
+	total_size = info->screen_size;
+
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
+		count = total_size - p;
+	}
+
+	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+			 GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	dst = (u8 __iomem *) (info->screen_base + p);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	while (count) {
+		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		src = buffer;
+
+		if (copy_from_user(src, buf, c)) {
+			err = -EFAULT;
+			break;
+		}
+
+		fb_memcpy_tofb(dst, src, c);
+		dst += c;
+		src += c;
+		*ppos += c;
+		buf += c;
+		cnt += c;
+		count -= c;
+	}
+
+	kfree(buffer);
+
+	return (cnt) ? cnt : err;
+}
+
+int
+fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+	struct fb_fix_screeninfo *fix = &info->fix;
+	unsigned int yres = info->var.yres;
+	int err = 0;
+
+	if (var->yoffset > 0) {
+		if (var->vmode & FB_VMODE_YWRAP) {
+			if (!fix->ywrapstep || (var->yoffset % fix->ywrapstep))
+				err = -EINVAL;
+			else
+				yres = 0;
+		} else if (!fix->ypanstep || (var->yoffset % fix->ypanstep))
+			err = -EINVAL;
+	}
+
+	if (var->xoffset > 0 && (!fix->xpanstep ||
+				 (var->xoffset % fix->xpanstep)))
+		err = -EINVAL;
+
+	if (err || !info->fbops->fb_pan_display ||
+	    var->yoffset > info->var.yres_virtual - yres ||
+	    var->xoffset > info->var.xres_virtual - info->var.xres)
+		return -EINVAL;
+
+	if ((err = info->fbops->fb_pan_display(var, info)))
+		return err;
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+EXPORT_SYMBOL(fb_pan_display);
+
+static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
+			 u32 activate)
+{
+	struct fb_event event;
+	struct fb_blit_caps caps, fbcaps;
+	int err = 0;
+
+	memset(&caps, 0, sizeof(caps));
+	memset(&fbcaps, 0, sizeof(fbcaps));
+	caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
+	event.info = info;
+	event.data = &caps;
+	fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
+	info->fbops->fb_get_caps(info, &fbcaps, var);
+
+	if (((fbcaps.x ^ caps.x) & caps.x) ||
+	    ((fbcaps.y ^ caps.y) & caps.y) ||
+	    (fbcaps.len < caps.len))
+		err = -EINVAL;
+
+	return err;
+}
+
+int
+fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+	int flags = info->flags;
+	int ret = 0;
+
+	if (var->activate & FB_ACTIVATE_INV_MODE) {
+		struct fb_videomode mode1, mode2;
+
+		fb_var_to_videomode(&mode1, var);
+		fb_var_to_videomode(&mode2, &info->var);
+		/* make sure we don't delete the videomode of current var */
+		ret = fb_mode_is_equal(&mode1, &mode2);
+
+		if (!ret) {
+		    struct fb_event event;
+
+		    event.info = info;
+		    event.data = &mode1;
+		    ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event);
+		}
+
+		if (!ret)
+		    fb_delete_videomode(&mode1, &info->modelist);
+
+
+		ret = (ret) ? -EINVAL : 0;
+		goto done;
+	}
+
+	if ((var->activate & FB_ACTIVATE_FORCE) ||
+	    memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
+		u32 activate = var->activate;
+
+		/* When using FOURCC mode, make sure the red, green, blue and
+		 * transp fields are set to 0.
+		 */
+		if ((info->fix.capabilities & FB_CAP_FOURCC) &&
+		    var->grayscale > 1) {
+			if (var->red.offset     || var->green.offset    ||
+			    var->blue.offset    || var->transp.offset   ||
+			    var->red.length     || var->green.length    ||
+			    var->blue.length    || var->transp.length   ||
+			    var->red.msb_right  || var->green.msb_right ||
+			    var->blue.msb_right || var->transp.msb_right)
+				return -EINVAL;
+		}
+
+		if (!info->fbops->fb_check_var) {
+			*var = info->var;
+			goto done;
+		}
+
+		ret = info->fbops->fb_check_var(var, info);
+
+		if (ret)
+			goto done;
+
+		if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+			struct fb_var_screeninfo old_var;
+			struct fb_videomode mode;
+
+			if (info->fbops->fb_get_caps) {
+				ret = fb_check_caps(info, var, activate);
+
+				if (ret)
+					goto done;
+			}
+
+			old_var = info->var;
+			info->var = *var;
+
+			if (info->fbops->fb_set_par) {
+				ret = info->fbops->fb_set_par(info);
+
+				if (ret) {
+					info->var = old_var;
+					printk(KERN_WARNING "detected "
+						"fb_set_par error, "
+						"error code: %d\n", ret);
+					goto done;
+				}
+			}
+
+			fb_pan_display(info, &info->var);
+			fb_set_cmap(&info->cmap, info);
+			fb_var_to_videomode(&mode, &info->var);
+
+			if (info->modelist.prev && info->modelist.next &&
+			    !list_empty(&info->modelist))
+				ret = fb_add_videomode(&mode, &info->modelist);
+
+			if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
+				struct fb_event event;
+				int evnt = (activate & FB_ACTIVATE_ALL) ?
+					FB_EVENT_MODE_CHANGE_ALL :
+					FB_EVENT_MODE_CHANGE;
+
+				info->flags &= ~FBINFO_MISC_USEREVENT;
+				event.info = info;
+				event.data = &mode;
+				fb_notifier_call_chain(evnt, &event);
+			}
+		}
+	}
+
+ done:
+	return ret;
+}
+EXPORT_SYMBOL(fb_set_var);
+
+int
+fb_blank(struct fb_info *info, int blank)
+{	
+	struct fb_event event;
+	int ret = -EINVAL, early_ret;
+
+ 	if (blank > FB_BLANK_POWERDOWN)
+ 		blank = FB_BLANK_POWERDOWN;
+
+	event.info = info;
+	event.data = &blank;
+
+	early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
+
+	if (info->fbops->fb_blank)
+ 		ret = info->fbops->fb_blank(blank, info);
+
+	if (!ret)
+		fb_notifier_call_chain(FB_EVENT_BLANK, &event);
+	else {
+		/*
+		 * if fb_blank is failed then revert effects of
+		 * the early blank event.
+		 */
+		if (!early_ret)
+			fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
+	}
+
+ 	return ret;
+}
+EXPORT_SYMBOL(fb_blank);
+
+static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			unsigned long arg)
+{
+	struct fb_ops *fb;
+	struct fb_var_screeninfo var;
+	struct fb_fix_screeninfo fix;
+	struct fb_con2fbmap con2fb;
+	struct fb_cmap cmap_from;
+	struct fb_cmap_user cmap;
+	struct fb_event event;
+	void __user *argp = (void __user *)arg;
+	long ret = 0;
+
+	switch (cmd) {
+	case FBIOGET_VSCREENINFO:
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		var = info->var;
+		unlock_fb_info(info);
+
+		ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
+		break;
+	case FBIOPUT_VSCREENINFO:
+		if (copy_from_user(&var, argp, sizeof(var)))
+			return -EFAULT;
+		console_lock();
+		if (!lock_fb_info(info)) {
+			console_unlock();
+			return -ENODEV;
+		}
+		info->flags |= FBINFO_MISC_USEREVENT;
+		ret = fb_set_var(info, &var);
+		info->flags &= ~FBINFO_MISC_USEREVENT;
+		unlock_fb_info(info);
+		console_unlock();
+		if (!ret && copy_to_user(argp, &var, sizeof(var)))
+			ret = -EFAULT;
+		break;
+	case FBIOGET_FSCREENINFO:
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		fix = info->fix;
+		unlock_fb_info(info);
+
+		ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
+		break;
+	case FBIOPUTCMAP:
+		if (copy_from_user(&cmap, argp, sizeof(cmap)))
+			return -EFAULT;
+		ret = fb_set_user_cmap(&cmap, info);
+		break;
+	case FBIOGETCMAP:
+		if (copy_from_user(&cmap, argp, sizeof(cmap)))
+			return -EFAULT;
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		cmap_from = info->cmap;
+		unlock_fb_info(info);
+		ret = fb_cmap_to_user(&cmap_from, &cmap);
+		break;
+	case FBIOPAN_DISPLAY:
+		if (copy_from_user(&var, argp, sizeof(var)))
+			return -EFAULT;
+		console_lock();
+		if (!lock_fb_info(info)) {
+			console_unlock();
+			return -ENODEV;
+		}
+		ret = fb_pan_display(info, &var);
+		unlock_fb_info(info);
+		console_unlock();
+		if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+			return -EFAULT;
+		break;
+	case FBIO_CURSOR:
+		ret = -EINVAL;
+		break;
+	case FBIOGET_CON2FBMAP:
+		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
+			return -EFAULT;
+		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+			return -EINVAL;
+		con2fb.framebuffer = -1;
+		event.data = &con2fb;
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		event.info = info;
+		fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
+		unlock_fb_info(info);
+		ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
+		break;
+	case FBIOPUT_CON2FBMAP:
+		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
+			return -EFAULT;
+		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+			return -EINVAL;
+		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
+			return -EINVAL;
+		if (!registered_fb[con2fb.framebuffer])
+			request_module("fb%d", con2fb.framebuffer);
+		if (!registered_fb[con2fb.framebuffer]) {
+			ret = -EINVAL;
+			break;
+		}
+		event.data = &con2fb;
+		console_lock();
+		if (!lock_fb_info(info)) {
+			console_unlock();
+			return -ENODEV;
+		}
+		event.info = info;
+		ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
+		unlock_fb_info(info);
+		console_unlock();
+		break;
+	case FBIOBLANK:
+		console_lock();
+		if (!lock_fb_info(info)) {
+			console_unlock();
+			return -ENODEV;
+		}
+		info->flags |= FBINFO_MISC_USEREVENT;
+		ret = fb_blank(info, arg);
+		info->flags &= ~FBINFO_MISC_USEREVENT;
+		unlock_fb_info(info);
+		console_unlock();
+		break;
+	default:
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		fb = info->fbops;
+		if (fb->fb_ioctl)
+			ret = fb->fb_ioctl(info, cmd, arg);
+		else
+			ret = -ENOTTY;
+		unlock_fb_info(info);
+	}
+	return ret;
+}
+
+static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct fb_info *info = file_fb_info(file);
+
+	if (!info)
+		return -ENODEV;
+	return do_fb_ioctl(info, cmd, arg);
+}
+
+#ifdef CONFIG_COMPAT
+struct fb_fix_screeninfo32 {
+	char			id[16];
+	compat_caddr_t		smem_start;
+	u32			smem_len;
+	u32			type;
+	u32			type_aux;
+	u32			visual;
+	u16			xpanstep;
+	u16			ypanstep;
+	u16			ywrapstep;
+	u32			line_length;
+	compat_caddr_t		mmio_start;
+	u32			mmio_len;
+	u32			accel;
+	u16			reserved[3];
+};
+
+struct fb_cmap32 {
+	u32			start;
+	u32			len;
+	compat_caddr_t	red;
+	compat_caddr_t	green;
+	compat_caddr_t	blue;
+	compat_caddr_t	transp;
+};
+
+static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
+			  unsigned long arg)
+{
+	struct fb_cmap_user __user *cmap;
+	struct fb_cmap32 __user *cmap32;
+	__u32 data;
+	int err;
+
+	cmap = compat_alloc_user_space(sizeof(*cmap));
+	cmap32 = compat_ptr(arg);
+
+	if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
+		return -EFAULT;
+
+	if (get_user(data, &cmap32->red) ||
+	    put_user(compat_ptr(data), &cmap->red) ||
+	    get_user(data, &cmap32->green) ||
+	    put_user(compat_ptr(data), &cmap->green) ||
+	    get_user(data, &cmap32->blue) ||
+	    put_user(compat_ptr(data), &cmap->blue) ||
+	    get_user(data, &cmap32->transp) ||
+	    put_user(compat_ptr(data), &cmap->transp))
+		return -EFAULT;
+
+	err = do_fb_ioctl(info, cmd, (unsigned long) cmap);
+
+	if (!err) {
+		if (copy_in_user(&cmap32->start,
+				 &cmap->start,
+				 2 * sizeof(__u32)))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
+				  struct fb_fix_screeninfo32 __user *fix32)
+{
+	__u32 data;
+	int err;
+
+	err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
+
+	data = (__u32) (unsigned long) fix->smem_start;
+	err |= put_user(data, &fix32->smem_start);
+
+	err |= put_user(fix->smem_len, &fix32->smem_len);
+	err |= put_user(fix->type, &fix32->type);
+	err |= put_user(fix->type_aux, &fix32->type_aux);
+	err |= put_user(fix->visual, &fix32->visual);
+	err |= put_user(fix->xpanstep, &fix32->xpanstep);
+	err |= put_user(fix->ypanstep, &fix32->ypanstep);
+	err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
+	err |= put_user(fix->line_length, &fix32->line_length);
+
+	data = (__u32) (unsigned long) fix->mmio_start;
+	err |= put_user(data, &fix32->mmio_start);
+
+	err |= put_user(fix->mmio_len, &fix32->mmio_len);
+	err |= put_user(fix->accel, &fix32->accel);
+	err |= copy_to_user(fix32->reserved, fix->reserved,
+			    sizeof(fix->reserved));
+
+	if (err)
+		return -EFAULT;
+	return 0;
+}
+
+static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
+			      unsigned long arg)
+{
+	mm_segment_t old_fs;
+	struct fb_fix_screeninfo fix;
+	struct fb_fix_screeninfo32 __user *fix32;
+	int err;
+
+	fix32 = compat_ptr(arg);
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = do_fb_ioctl(info, cmd, (unsigned long) &fix);
+	set_fs(old_fs);
+
+	if (!err)
+		err = do_fscreeninfo_to_user(&fix, fix32);
+
+	return err;
+}
+
+static long fb_compat_ioctl(struct file *file, unsigned int cmd,
+			    unsigned long arg)
+{
+	struct fb_info *info = file_fb_info(file);
+	struct fb_ops *fb;
+	long ret = -ENOIOCTLCMD;
+
+	if (!info)
+		return -ENODEV;
+	fb = info->fbops;
+	switch(cmd) {
+	case FBIOGET_VSCREENINFO:
+	case FBIOPUT_VSCREENINFO:
+	case FBIOPAN_DISPLAY:
+	case FBIOGET_CON2FBMAP:
+	case FBIOPUT_CON2FBMAP:
+		arg = (unsigned long) compat_ptr(arg);
+	case FBIOBLANK:
+		ret = do_fb_ioctl(info, cmd, arg);
+		break;
+
+	case FBIOGET_FSCREENINFO:
+		ret = fb_get_fscreeninfo(info, cmd, arg);
+		break;
+
+	case FBIOGETCMAP:
+	case FBIOPUTCMAP:
+		ret = fb_getput_cmap(info, cmd, arg);
+		break;
+
+	default:
+		if (fb->fb_compat_ioctl)
+			ret = fb->fb_compat_ioctl(info, cmd, arg);
+		break;
+	}
+	return ret;
+}
+#endif
+
+static int
+fb_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	struct fb_info *info = file_fb_info(file);
+	struct fb_ops *fb;
+	unsigned long mmio_pgoff;
+	unsigned long start;
+	u32 len;
+
+	if (!info)
+		return -ENODEV;
+	fb = info->fbops;
+	if (!fb)
+		return -ENODEV;
+	mutex_lock(&info->mm_lock);
+	if (fb->fb_mmap) {
+		int res;
+		res = fb->fb_mmap(info, vma);
+		mutex_unlock(&info->mm_lock);
+		return res;
+	}
+
+	/*
+	 * Ugh. This can be either the frame buffer mapping, or
+	 * if pgoff points past it, the mmio mapping.
+	 */
+	start = info->fix.smem_start;
+	len = info->fix.smem_len;
+	mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+	if (vma->vm_pgoff >= mmio_pgoff) {
+		if (info->var.accel_flags) {
+			mutex_unlock(&info->mm_lock);
+			return -EINVAL;
+		}
+
+		vma->vm_pgoff -= mmio_pgoff;
+		start = info->fix.mmio_start;
+		len = info->fix.mmio_len;
+	}
+	mutex_unlock(&info->mm_lock);
+
+	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+	fb_pgprotect(file, vma, start);
+
+	return vm_iomap_memory(vma, start, len);
+}
+
+static int
+fb_open(struct inode *inode, struct file *file)
+__acquires(&info->lock)
+__releases(&info->lock)
+{
+	int fbidx = iminor(inode);
+	struct fb_info *info;
+	int res = 0;
+
+	info = get_fb_info(fbidx);
+	if (!info) {
+		request_module("fb%d", fbidx);
+		info = get_fb_info(fbidx);
+		if (!info)
+			return -ENODEV;
+	}
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	mutex_lock(&info->lock);
+	if (!try_module_get(info->fbops->owner)) {
+		res = -ENODEV;
+		goto out;
+	}
+	file->private_data = info;
+	if (info->fbops->fb_open) {
+		res = info->fbops->fb_open(info,1);
+		if (res)
+			module_put(info->fbops->owner);
+	}
+#ifdef CONFIG_FB_DEFERRED_IO
+	if (info->fbdefio)
+		fb_deferred_io_open(info, inode, file);
+#endif
+out:
+	mutex_unlock(&info->lock);
+	if (res)
+		put_fb_info(info);
+	return res;
+}
+
+static int 
+fb_release(struct inode *inode, struct file *file)
+__acquires(&info->lock)
+__releases(&info->lock)
+{
+	struct fb_info * const info = file->private_data;
+
+	mutex_lock(&info->lock);
+	if (info->fbops->fb_release)
+		info->fbops->fb_release(info,1);
+	module_put(info->fbops->owner);
+	mutex_unlock(&info->lock);
+	put_fb_info(info);
+	return 0;
+}
+
+static const struct file_operations fb_fops = {
+	.owner =	THIS_MODULE,
+	.read =		fb_read,
+	.write =	fb_write,
+	.unlocked_ioctl = fb_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = fb_compat_ioctl,
+#endif
+	.mmap =		fb_mmap,
+	.open =		fb_open,
+	.release =	fb_release,
+#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
+	.get_unmapped_area = get_fb_unmapped_area,
+#endif
+#ifdef CONFIG_FB_DEFERRED_IO
+	.fsync =	fb_deferred_io_fsync,
+#endif
+	.llseek =	default_llseek,
+};
+
+struct class *fb_class;
+EXPORT_SYMBOL(fb_class);
+
+static int fb_check_foreignness(struct fb_info *fi)
+{
+	const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
+
+	fi->flags &= ~FBINFO_FOREIGN_ENDIAN;
+
+#ifdef __BIG_ENDIAN
+	fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH;
+#else
+	fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0;
+#endif /* __BIG_ENDIAN */
+
+	if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) {
+		pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to "
+		       "support this framebuffer\n", fi->fix.id);
+		return -ENOSYS;
+	} else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) {
+		pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to "
+		       "support this framebuffer\n", fi->fix.id);
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
+{
+	/* is the generic aperture base the same as the HW one */
+	if (gen->base == hw->base)
+		return true;
+	/* is the generic aperture base inside the hw base->hw base+size */
+	if (gen->base > hw->base && gen->base < hw->base + hw->size)
+		return true;
+	return false;
+}
+
+static bool fb_do_apertures_overlap(struct apertures_struct *gena,
+				    struct apertures_struct *hwa)
+{
+	int i, j;
+	if (!hwa || !gena)
+		return false;
+
+	for (i = 0; i < hwa->count; ++i) {
+		struct aperture *h = &hwa->ranges[i];
+		for (j = 0; j < gena->count; ++j) {
+			struct aperture *g = &gena->ranges[j];
+			printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
+				(unsigned long long)g->base,
+				(unsigned long long)g->size,
+				(unsigned long long)h->base,
+				(unsigned long long)h->size);
+			if (apertures_overlap(g, h))
+				return true;
+		}
+	}
+
+	return false;
+}
+
+static int do_unregister_framebuffer(struct fb_info *fb_info);
+
+#define VGA_FB_PHYS 0xA0000
+static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
+					      const char *name, bool primary)
+{
+	int i, ret;
+
+	/* check all firmware fbs and kick off if the base addr overlaps */
+	for (i = 0 ; i < FB_MAX; i++) {
+		struct apertures_struct *gen_aper;
+		if (!registered_fb[i])
+			continue;
+
+		if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
+			continue;
+
+		gen_aper = registered_fb[i]->apertures;
+		if (fb_do_apertures_overlap(gen_aper, a) ||
+			(primary && gen_aper && gen_aper->count &&
+			 gen_aper->ranges[0].base == VGA_FB_PHYS)) {
+
+			printk(KERN_INFO "fb: switching to %s from %s\n",
+			       name, registered_fb[i]->fix.id);
+			ret = do_unregister_framebuffer(registered_fb[i]);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int do_register_framebuffer(struct fb_info *fb_info)
+{
+	int i, ret;
+	struct fb_event event;
+	struct fb_videomode mode;
+
+	if (fb_check_foreignness(fb_info))
+		return -ENOSYS;
+
+	ret = do_remove_conflicting_framebuffers(fb_info->apertures,
+						 fb_info->fix.id,
+						 fb_is_primary_device(fb_info));
+	if (ret)
+		return ret;
+
+	if (num_registered_fb == FB_MAX)
+		return -ENXIO;
+
+	num_registered_fb++;
+	for (i = 0 ; i < FB_MAX; i++)
+		if (!registered_fb[i])
+			break;
+	fb_info->node = i;
+	atomic_set(&fb_info->count, 1);
+	mutex_init(&fb_info->lock);
+	mutex_init(&fb_info->mm_lock);
+
+	fb_info->dev = device_create(fb_class, fb_info->device,
+				     MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
+	if (IS_ERR(fb_info->dev)) {
+		/* Not fatal */
+		printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
+		fb_info->dev = NULL;
+	} else
+		fb_init_device(fb_info);
+
+	if (fb_info->pixmap.addr == NULL) {
+		fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
+		if (fb_info->pixmap.addr) {
+			fb_info->pixmap.size = FBPIXMAPSIZE;
+			fb_info->pixmap.buf_align = 1;
+			fb_info->pixmap.scan_align = 1;
+			fb_info->pixmap.access_align = 32;
+			fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
+		}
+	}	
+	fb_info->pixmap.offset = 0;
+
+	if (!fb_info->pixmap.blit_x)
+		fb_info->pixmap.blit_x = ~(u32)0;
+
+	if (!fb_info->pixmap.blit_y)
+		fb_info->pixmap.blit_y = ~(u32)0;
+
+	if (!fb_info->modelist.prev || !fb_info->modelist.next)
+		INIT_LIST_HEAD(&fb_info->modelist);
+
+	if (fb_info->skip_vt_switch)
+		pm_vt_switch_required(fb_info->dev, false);
+	else
+		pm_vt_switch_required(fb_info->dev, true);
+
+	fb_var_to_videomode(&mode, &fb_info->var);
+	fb_add_videomode(&mode, &fb_info->modelist);
+	registered_fb[i] = fb_info;
+
+	event.info = fb_info;
+	console_lock();
+	if (!lock_fb_info(fb_info)) {
+		console_unlock();
+		return -ENODEV;
+	}
+
+	fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+	unlock_fb_info(fb_info);
+	console_unlock();
+	return 0;
+}
+
+static int do_unregister_framebuffer(struct fb_info *fb_info)
+{
+	struct fb_event event;
+	int i, ret = 0;
+
+	i = fb_info->node;
+	if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
+		return -EINVAL;
+
+	console_lock();
+	if (!lock_fb_info(fb_info)) {
+		console_unlock();
+		return -ENODEV;
+	}
+
+	event.info = fb_info;
+	ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+	unlock_fb_info(fb_info);
+	console_unlock();
+
+	if (ret)
+		return -EINVAL;
+
+	pm_vt_switch_unregister(fb_info->dev);
+
+	unlink_framebuffer(fb_info);
+	if (fb_info->pixmap.addr &&
+	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
+		kfree(fb_info->pixmap.addr);
+	fb_destroy_modelist(&fb_info->modelist);
+	registered_fb[i] = NULL;
+	num_registered_fb--;
+	fb_cleanup_device(fb_info);
+	event.info = fb_info;
+	console_lock();
+	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
+	console_unlock();
+
+	/* this may free fb info */
+	put_fb_info(fb_info);
+	return 0;
+}
+
+int unlink_framebuffer(struct fb_info *fb_info)
+{
+	int i;
+
+	i = fb_info->node;
+	if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
+		return -EINVAL;
+
+	if (fb_info->dev) {
+		device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+		fb_info->dev = NULL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(unlink_framebuffer);
+
+int remove_conflicting_framebuffers(struct apertures_struct *a,
+				    const char *name, bool primary)
+{
+	int ret;
+
+	mutex_lock(&registration_lock);
+	ret = do_remove_conflicting_framebuffers(a, name, primary);
+	mutex_unlock(&registration_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(remove_conflicting_framebuffers);
+
+/**
+ *	register_framebuffer - registers a frame buffer device
+ *	@fb_info: frame buffer info structure
+ *
+ *	Registers a frame buffer device @fb_info.
+ *
+ *	Returns negative errno on error, or zero for success.
+ *
+ */
+int
+register_framebuffer(struct fb_info *fb_info)
+{
+	int ret;
+
+	mutex_lock(&registration_lock);
+	ret = do_register_framebuffer(fb_info);
+	mutex_unlock(&registration_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(register_framebuffer);
+
+/**
+ *	unregister_framebuffer - releases a frame buffer device
+ *	@fb_info: frame buffer info structure
+ *
+ *	Unregisters a frame buffer device @fb_info.
+ *
+ *	Returns negative errno on error, or zero for success.
+ *
+ *      This function will also notify the framebuffer console
+ *      to release the driver.
+ *
+ *      This is meant to be called within a driver's module_exit()
+ *      function. If this is called outside module_exit(), ensure
+ *      that the driver implements fb_open() and fb_release() to
+ *      check that no processes are using the device.
+ */
+int
+unregister_framebuffer(struct fb_info *fb_info)
+{
+	int ret;
+
+	mutex_lock(&registration_lock);
+	ret = do_unregister_framebuffer(fb_info);
+	mutex_unlock(&registration_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(unregister_framebuffer);
+
+/**
+ *	fb_set_suspend - low level driver signals suspend
+ *	@info: framebuffer affected
+ *	@state: 0 = resuming, !=0 = suspending
+ *
+ *	This is meant to be used by low level drivers to
+ * 	signal suspend/resume to the core & clients.
+ *	It must be called with the console semaphore held
+ */
+void fb_set_suspend(struct fb_info *info, int state)
+{
+	struct fb_event event;
+
+	event.info = info;
+	if (state) {
+		fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
+		info->state = FBINFO_STATE_SUSPENDED;
+	} else {
+		info->state = FBINFO_STATE_RUNNING;
+		fb_notifier_call_chain(FB_EVENT_RESUME, &event);
+	}
+}
+EXPORT_SYMBOL(fb_set_suspend);
+
+/**
+ *	fbmem_init - init frame buffer subsystem
+ *
+ *	Initialize the frame buffer subsystem.
+ *
+ *	NOTE: This function is _only_ to be called by drivers/char/mem.c.
+ *
+ */
+
+static int __init
+fbmem_init(void)
+{
+	proc_create("fb", 0, NULL, &fb_proc_fops);
+
+	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
+		printk("unable to get major %d for fb devs\n", FB_MAJOR);
+
+	fb_class = class_create(THIS_MODULE, "graphics");
+	if (IS_ERR(fb_class)) {
+		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
+		fb_class = NULL;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+module_init(fbmem_init);
+static void __exit
+fbmem_exit(void)
+{
+	remove_proc_entry("fb", NULL);
+	class_destroy(fb_class);
+	unregister_chrdev(FB_MAJOR, "fb");
+}
+
+module_exit(fbmem_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Framebuffer base");
+#else
+subsys_initcall(fbmem_init);
+#endif
+
+int fb_new_modelist(struct fb_info *info)
+{
+	struct fb_event event;
+	struct fb_var_screeninfo var = info->var;
+	struct list_head *pos, *n;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m, mode;
+	int err = 1;
+
+	list_for_each_safe(pos, n, &info->modelist) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		fb_videomode_to_var(&var, m);
+		var.activate = FB_ACTIVATE_TEST;
+		err = fb_set_var(info, &var);
+		fb_var_to_videomode(&mode, &var);
+		if (err || !fb_mode_is_equal(m, &mode)) {
+			list_del(pos);
+			kfree(pos);
+		}
+	}
+
+	err = 1;
+
+	if (!list_empty(&info->modelist)) {
+		event.info = info;
+		err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
+	}
+
+	return err;
+}
+
+static char *video_options[FB_MAX] __read_mostly;
+static int ofonly __read_mostly;
+
+/**
+ * fb_get_options - get kernel boot parameters
+ * @name:   framebuffer name as it would appear in
+ *          the boot parameter line
+ *          (video=<name>:<options>)
+ * @option: the option will be stored here
+ *
+ * NOTE: Needed to maintain backwards compatibility
+ */
+int fb_get_options(const char *name, char **option)
+{
+	char *opt, *options = NULL;
+	int retval = 0;
+	int name_len = strlen(name), i;
+
+	if (name_len && ofonly && strncmp(name, "offb", 4))
+		retval = 1;
+
+	if (name_len && !retval) {
+		for (i = 0; i < FB_MAX; i++) {
+			if (video_options[i] == NULL)
+				continue;
+			if (!video_options[i][0])
+				continue;
+			opt = video_options[i];
+			if (!strncmp(name, opt, name_len) &&
+			    opt[name_len] == ':')
+				options = opt + name_len + 1;
+		}
+	}
+	/* No match, pass global option */
+	if (!options && option && fb_mode_option)
+		options = kstrdup(fb_mode_option, GFP_KERNEL);
+	if (options && !strncmp(options, "off", 3))
+		retval = 1;
+
+	if (option)
+		*option = options;
+
+	return retval;
+}
+EXPORT_SYMBOL(fb_get_options);
+
+#ifndef MODULE
+/**
+ *	video_setup - process command line options
+ *	@options: string of options
+ *
+ *	Process command line options for frame buffer subsystem.
+ *
+ *	NOTE: This function is a __setup and __init function.
+ *            It only stores the options.  Drivers have to call
+ *            fb_get_options() as necessary.
+ *
+ *	Returns zero.
+ *
+ */
+static int __init video_setup(char *options)
+{
+	int i, global = 0;
+
+	if (!options || !*options)
+ 		global = 1;
+
+ 	if (!global && !strncmp(options, "ofonly", 6)) {
+ 		ofonly = 1;
+ 		global = 1;
+ 	}
+
+ 	if (!global && !strchr(options, ':')) {
+ 		fb_mode_option = options;
+ 		global = 1;
+ 	}
+
+ 	if (!global) {
+ 		for (i = 0; i < FB_MAX; i++) {
+ 			if (video_options[i] == NULL) {
+ 				video_options[i] = options;
+ 				break;
+ 			}
+
+		}
+	}
+
+	return 1;
+}
+__setup("video=", video_setup);
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c
new file mode 100644
index 000000000000..c204ebe6187e
--- /dev/null
+++ b/drivers/video/fbdev/core/fbmon.c
@@ -0,0 +1,1592 @@
+/*
+ * linux/drivers/video/fbmon.c
+ *
+ * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
+ *
+ * Credits:
+ *
+ * The EDID Parser is a conglomeration from the following sources:
+ *
+ *   1. SciTech SNAP Graphics Architecture
+ *      Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
+ *
+ *   2. XFree86 4.3.0, interpret_edid.c
+ *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ *
+ *   3. John Fremlin <vii@users.sourceforge.net> and
+ *      Ani Joshi <ajoshi@unixbox.com>
+ *
+ * Generalized Timing Formula is derived from:
+ *
+ *      GTF Spreadsheet by Andy Morrish (1/5/97)
+ *      available at http://www.vesa.org
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <video/edid.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+#include "../edid.h"
+
+/*
+ * EDID parser
+ */
+
+#undef DEBUG  /* define this for verbose EDID parsing output */
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(fmt,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define FBMON_FIX_HEADER  1
+#define FBMON_FIX_INPUT   2
+#define FBMON_FIX_TIMINGS 3
+
+#ifdef CONFIG_FB_MODE_HELPERS
+struct broken_edid {
+	u8  manufacturer[4];
+	u32 model;
+	u32 fix;
+};
+
+static const struct broken_edid brokendb[] = {
+	/* DEC FR-PCXAV-YZ */
+	{
+		.manufacturer = "DEC",
+		.model        = 0x073a,
+		.fix          = FBMON_FIX_HEADER,
+	},
+	/* ViewSonic PF775a */
+	{
+		.manufacturer = "VSC",
+		.model        = 0x5a44,
+		.fix          = FBMON_FIX_INPUT,
+	},
+	/* Sharp UXGA? */
+	{
+		.manufacturer = "SHP",
+		.model        = 0x138e,
+		.fix          = FBMON_FIX_TIMINGS,
+	},
+};
+
+static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0x00
+};
+
+static void copy_string(unsigned char *c, unsigned char *s)
+{
+  int i;
+  c = c + 5;
+  for (i = 0; (i < 13 && *c != 0x0A); i++)
+    *(s++) = *(c++);
+  *s = 0;
+  while (i-- && (*--s == 0x20)) *s = 0;
+}
+
+static int edid_is_serial_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xff) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_ascii_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xfe) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_limits_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xfd) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_monitor_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) &&
+	    (block[2] == 0x00) && (block[3] == 0xfc) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_timing_block(unsigned char *block)
+{
+	if ((block[0] != 0x00) || (block[1] != 0x00) ||
+	    (block[2] != 0x00) || (block[4] != 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static int check_edid(unsigned char *edid)
+{
+	unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
+	unsigned char *b;
+	u32 model;
+	int i, fix = 0, ret = 0;
+
+	manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
+	manufacturer[1] = ((block[0] & 0x03) << 3) +
+		((block[1] & 0xe0) >> 5) + '@';
+	manufacturer[2] = (block[1] & 0x1f) + '@';
+	manufacturer[3] = 0;
+	model = block[2] + (block[3] << 8);
+
+	for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
+		if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
+			brokendb[i].model == model) {
+			fix = brokendb[i].fix;
+			break;
+		}
+	}
+
+	switch (fix) {
+	case FBMON_FIX_HEADER:
+		for (i = 0; i < 8; i++) {
+			if (edid[i] != edid_v1_header[i]) {
+				ret = fix;
+				break;
+			}
+		}
+		break;
+	case FBMON_FIX_INPUT:
+		b = edid + EDID_STRUCT_DISPLAY;
+		/* Only if display is GTF capable will
+		   the input type be reset to analog */
+		if (b[4] & 0x01 && b[0] & 0x80)
+			ret = fix;
+		break;
+	case FBMON_FIX_TIMINGS:
+		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+		ret = fix;
+
+		for (i = 0; i < 4; i++) {
+			if (edid_is_limits_block(b)) {
+				ret = 0;
+				break;
+			}
+
+			b += DETAILED_TIMING_DESCRIPTION_SIZE;
+		}
+
+		break;
+	}
+
+	if (ret)
+		printk("fbmon: The EDID Block of "
+		       "Manufacturer: %s Model: 0x%x is known to "
+		       "be broken,\n",  manufacturer, model);
+
+	return ret;
+}
+
+static void fix_edid(unsigned char *edid, int fix)
+{
+	int i;
+	unsigned char *b, csum = 0;
+
+	switch (fix) {
+	case FBMON_FIX_HEADER:
+		printk("fbmon: trying a header reconstruct\n");
+		memcpy(edid, edid_v1_header, 8);
+		break;
+	case FBMON_FIX_INPUT:
+		printk("fbmon: trying to fix input type\n");
+		b = edid + EDID_STRUCT_DISPLAY;
+		b[0] &= ~0x80;
+		edid[127] += 0x80;
+		break;
+	case FBMON_FIX_TIMINGS:
+		printk("fbmon: trying to fix monitor timings\n");
+		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+		for (i = 0; i < 4; i++) {
+			if (!(edid_is_serial_block(b) ||
+			      edid_is_ascii_block(b) ||
+			      edid_is_monitor_block(b) ||
+			      edid_is_timing_block(b))) {
+				b[0] = 0x00;
+				b[1] = 0x00;
+				b[2] = 0x00;
+				b[3] = 0xfd;
+				b[4] = 0x00;
+				b[5] = 60;   /* vfmin */
+				b[6] = 60;   /* vfmax */
+				b[7] = 30;   /* hfmin */
+				b[8] = 75;   /* hfmax */
+				b[9] = 17;   /* pixclock - 170 MHz*/
+				b[10] = 0;   /* GTF */
+				break;
+			}
+
+			b += DETAILED_TIMING_DESCRIPTION_SIZE;
+		}
+
+		for (i = 0; i < EDID_LENGTH - 1; i++)
+			csum += edid[i];
+
+		edid[127] = 256 - csum;
+		break;
+	}
+}
+
+static int edid_checksum(unsigned char *edid)
+{
+	unsigned char csum = 0, all_null = 0;
+	int i, err = 0, fix = check_edid(edid);
+
+	if (fix)
+		fix_edid(edid, fix);
+
+	for (i = 0; i < EDID_LENGTH; i++) {
+		csum += edid[i];
+		all_null |= edid[i];
+	}
+
+	if (csum == 0x00 && all_null) {
+		/* checksum passed, everything's good */
+		err = 1;
+	}
+
+	return err;
+}
+
+static int edid_check_header(unsigned char *edid)
+{
+	int i, err = 1, fix = check_edid(edid);
+
+	if (fix)
+		fix_edid(edid, fix);
+
+	for (i = 0; i < 8; i++) {
+		if (edid[i] != edid_v1_header[i])
+			err = 0;
+	}
+
+	return err;
+}
+
+static void parse_vendor_block(unsigned char *block, struct fb_monspecs *specs)
+{
+	specs->manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
+	specs->manufacturer[1] = ((block[0] & 0x03) << 3) +
+		((block[1] & 0xe0) >> 5) + '@';
+	specs->manufacturer[2] = (block[1] & 0x1f) + '@';
+	specs->manufacturer[3] = 0;
+	specs->model = block[2] + (block[3] << 8);
+	specs->serial = block[4] + (block[5] << 8) +
+	       (block[6] << 16) + (block[7] << 24);
+	specs->year = block[9] + 1990;
+	specs->week = block[8];
+	DPRINTK("   Manufacturer: %s\n", specs->manufacturer);
+	DPRINTK("   Model: %x\n", specs->model);
+	DPRINTK("   Serial#: %u\n", specs->serial);
+	DPRINTK("   Year: %u Week %u\n", specs->year, specs->week);
+}
+
+static void get_dpms_capabilities(unsigned char flags,
+				  struct fb_monspecs *specs)
+{
+	specs->dpms = 0;
+	if (flags & DPMS_ACTIVE_OFF)
+		specs->dpms |= FB_DPMS_ACTIVE_OFF;
+	if (flags & DPMS_SUSPEND)
+		specs->dpms |= FB_DPMS_SUSPEND;
+	if (flags & DPMS_STANDBY)
+		specs->dpms |= FB_DPMS_STANDBY;
+	DPRINTK("      DPMS: Active %s, Suspend %s, Standby %s\n",
+	       (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
+	       (flags & DPMS_SUSPEND)    ? "yes" : "no",
+	       (flags & DPMS_STANDBY)    ? "yes" : "no");
+}
+
+static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
+{
+	int tmp;
+
+	DPRINTK("      Chroma\n");
+	/* Chromaticity data */
+	tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.redx = tmp/1024;
+	DPRINTK("         RedX:     0.%03d ", specs->chroma.redx);
+
+	tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.redy = tmp/1024;
+	DPRINTK("RedY:     0.%03d\n", specs->chroma.redy);
+
+	tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.greenx = tmp/1024;
+	DPRINTK("         GreenX:   0.%03d ", specs->chroma.greenx);
+
+	tmp = (block[5] & 3) | (block[0xa] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.greeny = tmp/1024;
+	DPRINTK("GreenY:   0.%03d\n", specs->chroma.greeny);
+
+	tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.bluex = tmp/1024;
+	DPRINTK("         BlueX:    0.%03d ", specs->chroma.bluex);
+
+	tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.bluey = tmp/1024;
+	DPRINTK("BlueY:    0.%03d\n", specs->chroma.bluey);
+
+	tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.whitex = tmp/1024;
+	DPRINTK("         WhiteX:   0.%03d ", specs->chroma.whitex);
+
+	tmp = (block[6] & 3) | (block[0xe] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	specs->chroma.whitey = tmp/1024;
+	DPRINTK("WhiteY:   0.%03d\n", specs->chroma.whitey);
+}
+
+static void calc_mode_timings(int xres, int yres, int refresh,
+			      struct fb_videomode *mode)
+{
+	struct fb_var_screeninfo *var;
+
+	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+
+	if (var) {
+		var->xres = xres;
+		var->yres = yres;
+		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
+			    refresh, var, NULL);
+		mode->xres = xres;
+		mode->yres = yres;
+		mode->pixclock = var->pixclock;
+		mode->refresh = refresh;
+		mode->left_margin = var->left_margin;
+		mode->right_margin = var->right_margin;
+		mode->upper_margin = var->upper_margin;
+		mode->lower_margin = var->lower_margin;
+		mode->hsync_len = var->hsync_len;
+		mode->vsync_len = var->vsync_len;
+		mode->vmode = 0;
+		mode->sync = 0;
+		kfree(var);
+	}
+}
+
+static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
+{
+	int num = 0;
+	unsigned char c;
+
+	c = block[0];
+	if (c&0x80) {
+		calc_mode_timings(720, 400, 70, &mode[num]);
+		mode[num++].flag = FB_MODE_IS_CALCULATED;
+		DPRINTK("      720x400@70Hz\n");
+	}
+	if (c&0x40) {
+		calc_mode_timings(720, 400, 88, &mode[num]);
+		mode[num++].flag = FB_MODE_IS_CALCULATED;
+		DPRINTK("      720x400@88Hz\n");
+	}
+	if (c&0x20) {
+		mode[num++] = vesa_modes[3];
+		DPRINTK("      640x480@60Hz\n");
+	}
+	if (c&0x10) {
+		calc_mode_timings(640, 480, 67, &mode[num]);
+		mode[num++].flag = FB_MODE_IS_CALCULATED;
+		DPRINTK("      640x480@67Hz\n");
+	}
+	if (c&0x08) {
+		mode[num++] = vesa_modes[4];
+		DPRINTK("      640x480@72Hz\n");
+	}
+	if (c&0x04) {
+		mode[num++] = vesa_modes[5];
+		DPRINTK("      640x480@75Hz\n");
+	}
+	if (c&0x02) {
+		mode[num++] = vesa_modes[7];
+		DPRINTK("      800x600@56Hz\n");
+	}
+	if (c&0x01) {
+		mode[num++] = vesa_modes[8];
+		DPRINTK("      800x600@60Hz\n");
+	}
+
+	c = block[1];
+	if (c&0x80) {
+		mode[num++] = vesa_modes[9];
+		DPRINTK("      800x600@72Hz\n");
+	}
+	if (c&0x40) {
+		mode[num++] = vesa_modes[10];
+		DPRINTK("      800x600@75Hz\n");
+	}
+	if (c&0x20) {
+		calc_mode_timings(832, 624, 75, &mode[num]);
+		mode[num++].flag = FB_MODE_IS_CALCULATED;
+		DPRINTK("      832x624@75Hz\n");
+	}
+	if (c&0x10) {
+		mode[num++] = vesa_modes[12];
+		DPRINTK("      1024x768@87Hz Interlaced\n");
+	}
+	if (c&0x08) {
+		mode[num++] = vesa_modes[13];
+		DPRINTK("      1024x768@60Hz\n");
+	}
+	if (c&0x04) {
+		mode[num++] = vesa_modes[14];
+		DPRINTK("      1024x768@70Hz\n");
+	}
+	if (c&0x02) {
+		mode[num++] = vesa_modes[15];
+		DPRINTK("      1024x768@75Hz\n");
+	}
+	if (c&0x01) {
+		mode[num++] = vesa_modes[21];
+		DPRINTK("      1280x1024@75Hz\n");
+	}
+	c = block[2];
+	if (c&0x80) {
+		mode[num++] = vesa_modes[17];
+		DPRINTK("      1152x870@75Hz\n");
+	}
+	DPRINTK("      Manufacturer's mask: %x\n",c&0x7F);
+	return num;
+}
+
+static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
+		int ver, int rev)
+{
+	int xres, yres = 0, refresh, ratio, i;
+
+	xres = (block[0] + 31) * 8;
+	if (xres <= 256)
+		return 0;
+
+	ratio = (block[1] & 0xc0) >> 6;
+	switch (ratio) {
+	case 0:
+		/* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
+		if (ver < 1 || (ver == 1 && rev < 3))
+			yres = xres;
+		else
+			yres = (xres * 10)/16;
+		break;
+	case 1:
+		yres = (xres * 3)/4;
+		break;
+	case 2:
+		yres = (xres * 4)/5;
+		break;
+	case 3:
+		yres = (xres * 9)/16;
+		break;
+	}
+	refresh = (block[1] & 0x3f) + 60;
+
+	DPRINTK("      %dx%d@%dHz\n", xres, yres, refresh);
+	for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+		if (vesa_modes[i].xres == xres &&
+		    vesa_modes[i].yres == yres &&
+		    vesa_modes[i].refresh == refresh) {
+			*mode = vesa_modes[i];
+			mode->flag |= FB_MODE_IS_STANDARD;
+			return 1;
+		}
+	}
+	calc_mode_timings(xres, yres, refresh, mode);
+	return 1;
+}
+
+static int get_dst_timing(unsigned char *block,
+			  struct fb_videomode *mode, int ver, int rev)
+{
+	int j, num = 0;
+
+	for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
+		num += get_std_timing(block, &mode[num], ver, rev);
+
+	return num;
+}
+
+static void get_detailed_timing(unsigned char *block,
+				struct fb_videomode *mode)
+{
+	mode->xres = H_ACTIVE;
+	mode->yres = V_ACTIVE;
+	mode->pixclock = PIXEL_CLOCK;
+	mode->pixclock /= 1000;
+	mode->pixclock = KHZ2PICOS(mode->pixclock);
+	mode->right_margin = H_SYNC_OFFSET;
+	mode->left_margin = (H_ACTIVE + H_BLANKING) -
+		(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+	mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+		V_SYNC_WIDTH;
+	mode->lower_margin = V_SYNC_OFFSET;
+	mode->hsync_len = H_SYNC_WIDTH;
+	mode->vsync_len = V_SYNC_WIDTH;
+	if (HSYNC_POSITIVE)
+		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (VSYNC_POSITIVE)
+		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
+				     (V_ACTIVE + V_BLANKING));
+	if (INTERLACED) {
+		mode->yres *= 2;
+		mode->upper_margin *= 2;
+		mode->lower_margin *= 2;
+		mode->vsync_len *= 2;
+		mode->vmode |= FB_VMODE_INTERLACED;
+	}
+	mode->flag = FB_MODE_IS_DETAILED;
+
+	DPRINTK("      %d MHz ",  PIXEL_CLOCK/1000000);
+	DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
+	       H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+	DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
+	       V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+	DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
+	       (VSYNC_POSITIVE) ? "+" : "-");
+}
+
+/**
+ * fb_create_modedb - create video mode database
+ * @edid: EDID data
+ * @dbsize: database size
+ *
+ * RETURNS: struct fb_videomode, @dbsize contains length of database
+ *
+ * DESCRIPTION:
+ * This function builds a mode database using the contents of the EDID
+ * data
+ */
+static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+{
+	struct fb_videomode *mode, *m;
+	unsigned char *block;
+	int num = 0, i, first = 1;
+	int ver, rev;
+
+	ver = edid[EDID_STRUCT_VERSION];
+	rev = edid[EDID_STRUCT_REVISION];
+
+	mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+	if (mode == NULL)
+		return NULL;
+
+	if (edid == NULL || !edid_checksum(edid) ||
+	    !edid_check_header(edid)) {
+		kfree(mode);
+		return NULL;
+	}
+
+	*dbsize = 0;
+
+	DPRINTK("   Detailed Timings\n");
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (!(block[0] == 0x00 && block[1] == 0x00)) {
+			get_detailed_timing(block, &mode[num]);
+			if (first) {
+			        mode[num].flag |= FB_MODE_IS_FIRST;
+				first = 0;
+			}
+			num++;
+		}
+	}
+
+	DPRINTK("   Supported VESA Modes\n");
+	block = edid + ESTABLISHED_TIMING_1;
+	num += get_est_timing(block, &mode[num]);
+
+	DPRINTK("   Standard Timings\n");
+	block = edid + STD_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+		num += get_std_timing(block, &mode[num], ver, rev);
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
+			num += get_dst_timing(block + 5, &mode[num], ver, rev);
+	}
+
+	/* Yikes, EDID data is totally useless */
+	if (!num) {
+		kfree(mode);
+		return NULL;
+	}
+
+	*dbsize = num;
+	m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
+	if (!m)
+		return mode;
+	memmove(m, mode, num * sizeof(struct fb_videomode));
+	kfree(mode);
+	return m;
+}
+
+/**
+ * fb_destroy_modedb - destroys mode database
+ * @modedb: mode database to destroy
+ *
+ * DESCRIPTION:
+ * Destroy mode database created by fb_create_modedb
+ */
+void fb_destroy_modedb(struct fb_videomode *modedb)
+{
+	kfree(modedb);
+}
+
+static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+{
+	int i, retval = 1;
+	unsigned char *block;
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+	DPRINTK("      Monitor Operating Limits: ");
+
+	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (edid_is_limits_block(block)) {
+			specs->hfmin = H_MIN_RATE * 1000;
+			specs->hfmax = H_MAX_RATE * 1000;
+			specs->vfmin = V_MIN_RATE;
+			specs->vfmax = V_MAX_RATE;
+			specs->dclkmax = MAX_PIXEL_CLOCK * 1000000;
+			specs->gtf = (GTF_SUPPORT) ? 1 : 0;
+			retval = 0;
+			DPRINTK("From EDID\n");
+			break;
+		}
+	}
+
+	/* estimate monitor limits based on modes supported */
+	if (retval) {
+		struct fb_videomode *modes, *mode;
+		int num_modes, hz, hscan, pixclock;
+		int vtotal, htotal;
+
+		modes = fb_create_modedb(edid, &num_modes);
+		if (!modes) {
+			DPRINTK("None Available\n");
+			return 1;
+		}
+
+		retval = 0;
+		for (i = 0; i < num_modes; i++) {
+			mode = &modes[i];
+			pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
+			htotal = mode->xres + mode->right_margin + mode->hsync_len
+				+ mode->left_margin;
+			vtotal = mode->yres + mode->lower_margin + mode->vsync_len
+				+ mode->upper_margin;
+
+			if (mode->vmode & FB_VMODE_INTERLACED)
+				vtotal /= 2;
+
+			if (mode->vmode & FB_VMODE_DOUBLE)
+				vtotal *= 2;
+
+			hscan = (pixclock + htotal / 2) / htotal;
+			hscan = (hscan + 500) / 1000 * 1000;
+			hz = (hscan + vtotal / 2) / vtotal;
+
+			if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
+				specs->dclkmax = pixclock;
+
+			if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
+				specs->dclkmin = pixclock;
+
+			if (specs->hfmax == 0 || specs->hfmax < hscan)
+				specs->hfmax = hscan;
+
+			if (specs->hfmin == 0 || specs->hfmin > hscan)
+				specs->hfmin = hscan;
+
+			if (specs->vfmax == 0 || specs->vfmax < hz)
+				specs->vfmax = hz;
+
+			if (specs->vfmin == 0 || specs->vfmin > hz)
+				specs->vfmin = hz;
+		}
+		DPRINTK("Extrapolated\n");
+		fb_destroy_modedb(modes);
+	}
+	DPRINTK("           H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n",
+		specs->hfmin/1000, specs->hfmax/1000, specs->vfmin,
+		specs->vfmax, specs->dclkmax/1000000);
+	return retval;
+}
+
+static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+	unsigned char c, *block;
+
+	block = edid + EDID_STRUCT_DISPLAY;
+
+	fb_get_monitor_limits(edid, specs);
+
+	c = block[0] & 0x80;
+	specs->input = 0;
+	if (c) {
+		specs->input |= FB_DISP_DDI;
+		DPRINTK("      Digital Display Input");
+	} else {
+		DPRINTK("      Analog Display Input: Input Voltage - ");
+		switch ((block[0] & 0x60) >> 5) {
+		case 0:
+			DPRINTK("0.700V/0.300V");
+			specs->input |= FB_DISP_ANA_700_300;
+			break;
+		case 1:
+			DPRINTK("0.714V/0.286V");
+			specs->input |= FB_DISP_ANA_714_286;
+			break;
+		case 2:
+			DPRINTK("1.000V/0.400V");
+			specs->input |= FB_DISP_ANA_1000_400;
+			break;
+		case 3:
+			DPRINTK("0.700V/0.000V");
+			specs->input |= FB_DISP_ANA_700_000;
+			break;
+		}
+	}
+	DPRINTK("\n      Sync: ");
+	c = block[0] & 0x10;
+	if (c)
+		DPRINTK("      Configurable signal level\n");
+	c = block[0] & 0x0f;
+	specs->signal = 0;
+	if (c & 0x10) {
+		DPRINTK("Blank to Blank ");
+		specs->signal |= FB_SIGNAL_BLANK_BLANK;
+	}
+	if (c & 0x08) {
+		DPRINTK("Separate ");
+		specs->signal |= FB_SIGNAL_SEPARATE;
+	}
+	if (c & 0x04) {
+		DPRINTK("Composite ");
+		specs->signal |= FB_SIGNAL_COMPOSITE;
+	}
+	if (c & 0x02) {
+		DPRINTK("Sync on Green ");
+		specs->signal |= FB_SIGNAL_SYNC_ON_GREEN;
+	}
+	if (c & 0x01) {
+		DPRINTK("Serration on ");
+		specs->signal |= FB_SIGNAL_SERRATION_ON;
+	}
+	DPRINTK("\n");
+	specs->max_x = block[1];
+	specs->max_y = block[2];
+	DPRINTK("      Max H-size in cm: ");
+	if (specs->max_x)
+		DPRINTK("%d\n", specs->max_x);
+	else
+		DPRINTK("variable\n");
+	DPRINTK("      Max V-size in cm: ");
+	if (specs->max_y)
+		DPRINTK("%d\n", specs->max_y);
+	else
+		DPRINTK("variable\n");
+
+	c = block[3];
+	specs->gamma = c+100;
+	DPRINTK("      Gamma: ");
+	DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100);
+
+	get_dpms_capabilities(block[4], specs);
+
+	switch ((block[4] & 0x18) >> 3) {
+	case 0:
+		DPRINTK("      Monochrome/Grayscale\n");
+		specs->input |= FB_DISP_MONO;
+		break;
+	case 1:
+		DPRINTK("      RGB Color Display\n");
+		specs->input |= FB_DISP_RGB;
+		break;
+	case 2:
+		DPRINTK("      Non-RGB Multicolor Display\n");
+		specs->input |= FB_DISP_MULTI;
+		break;
+	default:
+		DPRINTK("      Unknown\n");
+		specs->input |= FB_DISP_UNKNOWN;
+		break;
+	}
+
+	get_chroma(block, specs);
+
+	specs->misc = 0;
+	c = block[4] & 0x7;
+	if (c & 0x04) {
+		DPRINTK("      Default color format is primary\n");
+		specs->misc |= FB_MISC_PRIM_COLOR;
+	}
+	if (c & 0x02) {
+		DPRINTK("      First DETAILED Timing is preferred\n");
+		specs->misc |= FB_MISC_1ST_DETAIL;
+	}
+	if (c & 0x01) {
+		printk("      Display is GTF capable\n");
+		specs->gtf = 1;
+	}
+}
+
+int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+{
+	int i;
+	unsigned char *block;
+
+	if (edid == NULL || var == NULL)
+		return 1;
+
+	if (!(edid_checksum(edid)))
+		return 1;
+
+	if (!(edid_check_header(edid)))
+		return 1;
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (edid_is_timing_block(block)) {
+			var->xres = var->xres_virtual = H_ACTIVE;
+			var->yres = var->yres_virtual = V_ACTIVE;
+			var->height = var->width = 0;
+			var->right_margin = H_SYNC_OFFSET;
+			var->left_margin = (H_ACTIVE + H_BLANKING) -
+				(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+			var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+				V_SYNC_WIDTH;
+			var->lower_margin = V_SYNC_OFFSET;
+			var->hsync_len = H_SYNC_WIDTH;
+			var->vsync_len = V_SYNC_WIDTH;
+			var->pixclock = PIXEL_CLOCK;
+			var->pixclock /= 1000;
+			var->pixclock = KHZ2PICOS(var->pixclock);
+
+			if (HSYNC_POSITIVE)
+				var->sync |= FB_SYNC_HOR_HIGH_ACT;
+			if (VSYNC_POSITIVE)
+				var->sync |= FB_SYNC_VERT_HIGH_ACT;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+	unsigned char *block;
+	int i, found = 0;
+
+	if (edid == NULL)
+		return;
+
+	if (!(edid_checksum(edid)))
+		return;
+
+	if (!(edid_check_header(edid)))
+		return;
+
+	memset(specs, 0, sizeof(struct fb_monspecs));
+
+	specs->version = edid[EDID_STRUCT_VERSION];
+	specs->revision = edid[EDID_STRUCT_REVISION];
+
+	DPRINTK("========================================\n");
+	DPRINTK("Display Information (EDID)\n");
+	DPRINTK("========================================\n");
+	DPRINTK("   EDID Version %d.%d\n", (int) specs->version,
+	       (int) specs->revision);
+
+	parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (edid_is_serial_block(block)) {
+			copy_string(block, specs->serial_no);
+			DPRINTK("   Serial Number: %s\n", specs->serial_no);
+		} else if (edid_is_ascii_block(block)) {
+			copy_string(block, specs->ascii);
+			DPRINTK("   ASCII Block: %s\n", specs->ascii);
+		} else if (edid_is_monitor_block(block)) {
+			copy_string(block, specs->monitor);
+			DPRINTK("   Monitor Name: %s\n", specs->monitor);
+		}
+	}
+
+	DPRINTK("   Display Characteristics:\n");
+	get_monspecs(edid, specs);
+
+	specs->modedb = fb_create_modedb(edid, &specs->modedb_len);
+
+	/*
+	 * Workaround for buggy EDIDs that sets that the first
+	 * detailed timing is preferred but has not detailed
+	 * timing specified
+	 */
+	for (i = 0; i < specs->modedb_len; i++) {
+		if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		specs->misc &= ~FB_MISC_1ST_DETAIL;
+
+	DPRINTK("========================================\n");
+}
+
+/**
+ * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
+ * @edid:	128 byte array with an E-EDID block
+ * @spacs:	monitor specs to be extended
+ */
+void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+	unsigned char *block;
+	struct fb_videomode *m;
+	int num = 0, i;
+	u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
+	u8 pos = 4, svd_n = 0;
+
+	if (!edid)
+		return;
+
+	if (!edid_checksum(edid))
+		return;
+
+	if (edid[0] != 0x2 ||
+	    edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
+		return;
+
+	DPRINTK("  Short Video Descriptors\n");
+
+	while (pos < edid[2]) {
+		u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
+		pr_debug("Data block %u of %u bytes\n", type, len);
+		if (type == 2)
+			for (i = pos; i < pos + len; i++) {
+				u8 idx = edid[pos + i] & 0x7f;
+				svd[svd_n++] = idx;
+				pr_debug("N%sative mode #%d\n",
+					 edid[pos + i] & 0x80 ? "" : "on-n", idx);
+			}
+		pos += len + 1;
+	}
+
+	block = edid + edid[2];
+
+	DPRINTK("  Extended Detailed Timings\n");
+
+	for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
+	     i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
+		if (PIXEL_CLOCK)
+			edt[num++] = block - edid;
+
+	/* Yikes, EDID data is totally useless */
+	if (!(num + svd_n))
+		return;
+
+	m = kzalloc((specs->modedb_len + num + svd_n) *
+		       sizeof(struct fb_videomode), GFP_KERNEL);
+
+	if (!m)
+		return;
+
+	memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
+
+	for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
+		get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
+		if (i == specs->modedb_len)
+			m[i].flag |= FB_MODE_IS_FIRST;
+		pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
+	}
+
+	for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
+		int idx = svd[i - specs->modedb_len - num];
+		if (!idx || idx > 63) {
+			pr_warning("Reserved SVD code %d\n", idx);
+		} else if (idx > ARRAY_SIZE(cea_modes) || !cea_modes[idx].xres) {
+			pr_warning("Unimplemented SVD code %d\n", idx);
+		} else {
+			memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
+			pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
+				 m[i].xres, m[i].yres, m[i].refresh);
+		}
+	}
+
+	kfree(specs->modedb);
+	specs->modedb = m;
+	specs->modedb_len = specs->modedb_len + num + svd_n;
+}
+
+/*
+ * VESA Generalized Timing Formula (GTF)
+ */
+
+#define FLYBACK                     550
+#define V_FRONTPORCH                1
+#define H_OFFSET                    40
+#define H_SCALEFACTOR               20
+#define H_BLANKSCALE                128
+#define H_GRADIENT                  600
+#define C_VAL                       30
+#define M_VAL                       300
+
+struct __fb_timings {
+	u32 dclk;
+	u32 hfreq;
+	u32 vfreq;
+	u32 hactive;
+	u32 vactive;
+	u32 hblank;
+	u32 vblank;
+	u32 htotal;
+	u32 vtotal;
+};
+
+/**
+ * fb_get_vblank - get vertical blank time
+ * @hfreq: horizontal freq
+ *
+ * DESCRIPTION:
+ * vblank = right_margin + vsync_len + left_margin
+ *
+ *    given: right_margin = 1 (V_FRONTPORCH)
+ *           vsync_len    = 3
+ *           flyback      = 550
+ *
+ *                          flyback * hfreq
+ *           left_margin  = --------------- - vsync_len
+ *                           1000000
+ */
+static u32 fb_get_vblank(u32 hfreq)
+{
+	u32 vblank;
+
+	vblank = (hfreq * FLYBACK)/1000;
+	vblank = (vblank + 500)/1000;
+	return (vblank + V_FRONTPORCH);
+}
+
+/**
+ * fb_get_hblank_by_freq - get horizontal blank time given hfreq
+ * @hfreq: horizontal freq
+ * @xres: horizontal resolution in pixels
+ *
+ * DESCRIPTION:
+ *
+ *           xres * duty_cycle
+ * hblank = ------------------
+ *           100 - duty_cycle
+ *
+ * duty cycle = percent of htotal assigned to inactive display
+ * duty cycle = C - (M/Hfreq)
+ *
+ * where: C = ((offset - scale factor) * blank_scale)
+ *            -------------------------------------- + scale factor
+ *                        256
+ *        M = blank_scale * gradient
+ *
+ */
+static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
+{
+	u32 c_val, m_val, duty_cycle, hblank;
+
+	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
+		 H_SCALEFACTOR) * 1000;
+	m_val = (H_BLANKSCALE * H_GRADIENT)/256;
+	m_val = (m_val * 1000000)/hfreq;
+	duty_cycle = c_val - m_val;
+	hblank = (xres * duty_cycle)/(100000 - duty_cycle);
+	return (hblank);
+}
+
+/**
+ * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
+ * @dclk: pixelclock in Hz
+ * @xres: horizontal resolution in pixels
+ *
+ * DESCRIPTION:
+ *
+ *           xres * duty_cycle
+ * hblank = ------------------
+ *           100 - duty_cycle
+ *
+ * duty cycle = percent of htotal assigned to inactive display
+ * duty cycle = C - (M * h_period)
+ *
+ * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
+ *                   -----------------------------------------------
+ *                                    2 * M
+ *        M = 300;
+ *        C = 30;
+
+ */
+static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
+{
+	u32 duty_cycle, h_period, hblank;
+
+	dclk /= 1000;
+	h_period = 100 - C_VAL;
+	h_period *= h_period;
+	h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
+	h_period *= 10000;
+
+	h_period = int_sqrt(h_period);
+	h_period -= (100 - C_VAL) * 100;
+	h_period *= 1000;
+	h_period /= 2 * M_VAL;
+
+	duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
+	hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
+	hblank &= ~15;
+	return (hblank);
+}
+
+/**
+ * fb_get_hfreq - estimate hsync
+ * @vfreq: vertical refresh rate
+ * @yres: vertical resolution
+ *
+ * DESCRIPTION:
+ *
+ *          (yres + front_port) * vfreq * 1000000
+ * hfreq = -------------------------------------
+ *          (1000000 - (vfreq * FLYBACK)
+ *
+ */
+
+static u32 fb_get_hfreq(u32 vfreq, u32 yres)
+{
+	u32 divisor, hfreq;
+
+	divisor = (1000000 - (vfreq * FLYBACK))/1000;
+	hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;
+	return (hfreq/divisor);
+}
+
+static void fb_timings_vfreq(struct __fb_timings *timings)
+{
+	timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
+	timings->vblank = fb_get_vblank(timings->hfreq);
+	timings->vtotal = timings->vactive + timings->vblank;
+	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
+						 timings->hactive);
+	timings->htotal = timings->hactive + timings->hblank;
+	timings->dclk = timings->htotal * timings->hfreq;
+}
+
+static void fb_timings_hfreq(struct __fb_timings *timings)
+{
+	timings->vblank = fb_get_vblank(timings->hfreq);
+	timings->vtotal = timings->vactive + timings->vblank;
+	timings->vfreq = timings->hfreq/timings->vtotal;
+	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
+						 timings->hactive);
+	timings->htotal = timings->hactive + timings->hblank;
+	timings->dclk = timings->htotal * timings->hfreq;
+}
+
+static void fb_timings_dclk(struct __fb_timings *timings)
+{
+	timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
+						timings->hactive);
+	timings->htotal = timings->hactive + timings->hblank;
+	timings->hfreq = timings->dclk/timings->htotal;
+	timings->vblank = fb_get_vblank(timings->hfreq);
+	timings->vtotal = timings->vactive + timings->vblank;
+	timings->vfreq = timings->hfreq/timings->vtotal;
+}
+
+/*
+ * fb_get_mode - calculates video mode using VESA GTF
+ * @flags: if: 0 - maximize vertical refresh rate
+ *             1 - vrefresh-driven calculation;
+ *             2 - hscan-driven calculation;
+ *             3 - pixelclock-driven calculation;
+ * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
+ * @var: pointer to fb_var_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * Calculates video mode based on monitor specs using VESA GTF.
+ * The GTF is best for VESA GTF compliant monitors but is
+ * specifically formulated to work for older monitors as well.
+ *
+ * If @flag==0, the function will attempt to maximize the
+ * refresh rate.  Otherwise, it will calculate timings based on
+ * the flag and accompanying value.
+ *
+ * If FB_IGNOREMON bit is set in @flags, monitor specs will be
+ * ignored and @var will be filled with the calculated timings.
+ *
+ * All calculations are based on the VESA GTF Spreadsheet
+ * available at VESA's public ftp (http://www.vesa.org).
+ *
+ * NOTES:
+ * The timings generated by the GTF will be different from VESA
+ * DMT.  It might be a good idea to keep a table of standard
+ * VESA modes as well.  The GTF may also not work for some displays,
+ * such as, and especially, analog TV.
+ *
+ * REQUIRES:
+ * A valid info->monspecs, otherwise 'safe numbers' will be used.
+ */
+int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct __fb_timings *timings;
+	u32 interlace = 1, dscan = 1;
+	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
+
+
+	timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
+
+	if (!timings)
+		return -ENOMEM;
+
+	/*
+	 * If monspecs are invalid, use values that are enough
+	 * for 640x480@60
+	 */
+	if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
+	    !info->monspecs.dclkmax ||
+	    info->monspecs.hfmax < info->monspecs.hfmin ||
+	    info->monspecs.vfmax < info->monspecs.vfmin ||
+	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
+		hfmin = 29000; hfmax = 30000;
+		vfmin = 60; vfmax = 60;
+		dclkmin = 0; dclkmax = 25000000;
+	} else {
+		hfmin = info->monspecs.hfmin;
+		hfmax = info->monspecs.hfmax;
+		vfmin = info->monspecs.vfmin;
+		vfmax = info->monspecs.vfmax;
+		dclkmin = info->monspecs.dclkmin;
+		dclkmax = info->monspecs.dclkmax;
+	}
+
+	timings->hactive = var->xres;
+	timings->vactive = var->yres;
+	if (var->vmode & FB_VMODE_INTERLACED) {
+		timings->vactive /= 2;
+		interlace = 2;
+	}
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		timings->vactive *= 2;
+		dscan = 2;
+	}
+
+	switch (flags & ~FB_IGNOREMON) {
+	case FB_MAXTIMINGS: /* maximize refresh rate */
+		timings->hfreq = hfmax;
+		fb_timings_hfreq(timings);
+		if (timings->vfreq > vfmax) {
+			timings->vfreq = vfmax;
+			fb_timings_vfreq(timings);
+		}
+		if (timings->dclk > dclkmax) {
+			timings->dclk = dclkmax;
+			fb_timings_dclk(timings);
+		}
+		break;
+	case FB_VSYNCTIMINGS: /* vrefresh driven */
+		timings->vfreq = val;
+		fb_timings_vfreq(timings);
+		break;
+	case FB_HSYNCTIMINGS: /* hsync driven */
+		timings->hfreq = val;
+		fb_timings_hfreq(timings);
+		break;
+	case FB_DCLKTIMINGS: /* pixelclock driven */
+		timings->dclk = PICOS2KHZ(val) * 1000;
+		fb_timings_dclk(timings);
+		break;
+	default:
+		err = -EINVAL;
+
+	}
+
+	if (err || (!(flags & FB_IGNOREMON) &&
+	    (timings->vfreq < vfmin || timings->vfreq > vfmax ||
+	     timings->hfreq < hfmin || timings->hfreq > hfmax ||
+	     timings->dclk < dclkmin || timings->dclk > dclkmax))) {
+		err = -EINVAL;
+	} else {
+		var->pixclock = KHZ2PICOS(timings->dclk/1000);
+		var->hsync_len = (timings->htotal * 8)/100;
+		var->right_margin = (timings->hblank/2) - var->hsync_len;
+		var->left_margin = timings->hblank - var->right_margin -
+			var->hsync_len;
+		var->vsync_len = (3 * interlace)/dscan;
+		var->lower_margin = (1 * interlace)/dscan;
+		var->upper_margin = (timings->vblank * interlace)/dscan -
+			(var->vsync_len + var->lower_margin);
+	}
+
+	kfree(timings);
+	return err;
+}
+
+#ifdef CONFIG_VIDEOMODE_HELPERS
+int fb_videomode_from_videomode(const struct videomode *vm,
+				struct fb_videomode *fbmode)
+{
+	unsigned int htotal, vtotal;
+
+	fbmode->xres = vm->hactive;
+	fbmode->left_margin = vm->hback_porch;
+	fbmode->right_margin = vm->hfront_porch;
+	fbmode->hsync_len = vm->hsync_len;
+
+	fbmode->yres = vm->vactive;
+	fbmode->upper_margin = vm->vback_porch;
+	fbmode->lower_margin = vm->vfront_porch;
+	fbmode->vsync_len = vm->vsync_len;
+
+	/* prevent division by zero in KHZ2PICOS macro */
+	fbmode->pixclock = vm->pixelclock ?
+			KHZ2PICOS(vm->pixelclock / 1000) : 0;
+
+	fbmode->sync = 0;
+	fbmode->vmode = 0;
+	if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
+		fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
+		fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
+		fbmode->vmode |= FB_VMODE_INTERLACED;
+	if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
+		fbmode->vmode |= FB_VMODE_DOUBLE;
+	fbmode->flag = 0;
+
+	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
+		 vm->hsync_len;
+	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
+		 vm->vsync_len;
+	/* prevent division by zero */
+	if (htotal && vtotal) {
+		fbmode->refresh = vm->pixelclock / (htotal * vtotal);
+	/* a mode must have htotal and vtotal != 0 or it is invalid */
+	} else {
+		fbmode->refresh = 0;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
+
+#ifdef CONFIG_OF
+static inline void dump_fb_videomode(const struct fb_videomode *m)
+{
+	pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
+		 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
+		 m->right_margin, m->upper_margin, m->lower_margin,
+		 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
+
+/**
+ * of_get_fb_videomode - get a fb_videomode from devicetree
+ * @np: device_node with the timing specification
+ * @fb: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * DESCRIPTION:
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings ond
+ * work with that instead.
+ */
+int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
+			int index)
+{
+	struct videomode vm;
+	int ret;
+
+	ret = of_get_videomode(np, &vm, index);
+	if (ret)
+		return ret;
+
+	fb_videomode_from_videomode(&vm, fb);
+
+	pr_debug("%s: got %dx%d display mode from %s\n",
+		of_node_full_name(np), vm.hactive, vm.vactive, np->name);
+	dump_fb_videomode(fb);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_fb_videomode);
+#endif /* CONFIG_OF */
+#endif /* CONFIG_VIDEOMODE_HELPERS */
+
+#else
+int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+{
+	return 1;
+}
+void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+	specs = NULL;
+}
+void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+}
+void fb_destroy_modedb(struct fb_videomode *modedb)
+{
+}
+int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_FB_MODE_HELPERS */
+
+/*
+ * fb_validate_mode - validates var against monitor capabilities
+ * @var: pointer to fb_var_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * Validates video mode against monitor capabilities specified in
+ * info->monspecs.
+ *
+ * REQUIRES:
+ * A valid info->monspecs.
+ */
+int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 hfreq, vfreq, htotal, vtotal, pixclock;
+	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
+
+	/*
+	 * If monspecs are invalid, use values that are enough
+	 * for 640x480@60
+	 */
+	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+	    !info->monspecs.dclkmax ||
+	    info->monspecs.hfmax < info->monspecs.hfmin ||
+	    info->monspecs.vfmax < info->monspecs.vfmin ||
+	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
+		hfmin = 29000; hfmax = 30000;
+		vfmin = 60; vfmax = 60;
+		dclkmin = 0; dclkmax = 25000000;
+	} else {
+		hfmin = info->monspecs.hfmin;
+		hfmax = info->monspecs.hfmax;
+		vfmin = info->monspecs.vfmin;
+		vfmax = info->monspecs.vfmax;
+		dclkmin = info->monspecs.dclkmin;
+		dclkmax = info->monspecs.dclkmax;
+	}
+
+	if (!var->pixclock)
+		return -EINVAL;
+	pixclock = PICOS2KHZ(var->pixclock) * 1000;
+
+	htotal = var->xres + var->right_margin + var->hsync_len +
+		var->left_margin;
+	vtotal = var->yres + var->lower_margin + var->vsync_len +
+		var->upper_margin;
+
+	if (var->vmode & FB_VMODE_INTERLACED)
+		vtotal /= 2;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		vtotal *= 2;
+
+	hfreq = pixclock/htotal;
+	hfreq = (hfreq + 500) / 1000 * 1000;
+
+	vfreq = hfreq/vtotal;
+
+	return (vfreq < vfmin || vfreq > vfmax ||
+		hfreq < hfmin || hfreq > hfmax ||
+		pixclock < dclkmin || pixclock > dclkmax) ?
+		-EINVAL : 0;
+}
+
+#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
+
+/*
+ * We need to ensure that the EDID block is only returned for
+ * the primary graphics adapter.
+ */
+
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+	struct pci_dev *dev = NULL;
+	struct resource *res = NULL;
+	unsigned char *edid = NULL;
+
+	if (device)
+		dev = to_pci_dev(device);
+
+	if (dev)
+		res = &dev->resource[PCI_ROM_RESOURCE];
+
+	if (res && res->flags & IORESOURCE_ROM_SHADOW)
+		edid = edid_info.dummy;
+
+	return edid;
+}
+#else
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+	return NULL;
+}
+#endif
+EXPORT_SYMBOL(fb_firmware_edid);
+
+EXPORT_SYMBOL(fb_parse_edid);
+EXPORT_SYMBOL(fb_edid_to_monspecs);
+EXPORT_SYMBOL(fb_edid_add_monspecs);
+EXPORT_SYMBOL(fb_get_mode);
+EXPORT_SYMBOL(fb_validate_mode);
+EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
new file mode 100644
index 000000000000..53444ac19fe0
--- /dev/null
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -0,0 +1,586 @@
+/*
+ * fbsysfs.c - framebuffer device class and attributes
+ *
+ * Copyright (c) 2004 James Simmons <jsimmons@infradead.org>
+ * 
+ *	This program is free software you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Note:  currently there's only stubs for framebuffer_alloc and
+ * framebuffer_release here.  The reson for that is that until all drivers
+ * are converted to use it a sysfsification will open OOPSable races.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/module.h>
+
+#define FB_SYSFS_FLAG_ATTR 1
+
+/**
+ * framebuffer_alloc - creates a new frame buffer info structure
+ *
+ * @size: size of driver private data, can be zero
+ * @dev: pointer to the device for this fb, this can be NULL
+ *
+ * Creates a new frame buffer info structure. Also reserves @size bytes
+ * for driver private data (info->par). info->par (if any) will be
+ * aligned to sizeof(long).
+ *
+ * Returns the new structure, or NULL if an error occurred.
+ *
+ */
+struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
+{
+#define BYTES_PER_LONG (BITS_PER_LONG/8)
+#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
+	int fb_info_size = sizeof(struct fb_info);
+	struct fb_info *info;
+	char *p;
+
+	if (size)
+		fb_info_size += PADDING;
+
+	p = kzalloc(fb_info_size + size, GFP_KERNEL);
+
+	if (!p)
+		return NULL;
+
+	info = (struct fb_info *) p;
+
+	if (size)
+		info->par = p + fb_info_size;
+
+	info->device = dev;
+
+#ifdef CONFIG_FB_BACKLIGHT
+	mutex_init(&info->bl_curve_mutex);
+#endif
+
+	return info;
+#undef PADDING
+#undef BYTES_PER_LONG
+}
+EXPORT_SYMBOL(framebuffer_alloc);
+
+/**
+ * framebuffer_release - marks the structure available for freeing
+ *
+ * @info: frame buffer info structure
+ *
+ * Drop the reference count of the device embedded in the
+ * framebuffer info structure.
+ *
+ */
+void framebuffer_release(struct fb_info *info)
+{
+	if (!info)
+		return;
+	kfree(info->apertures);
+	kfree(info);
+}
+EXPORT_SYMBOL(framebuffer_release);
+
+static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
+{
+	int err;
+
+	var->activate |= FB_ACTIVATE_FORCE;
+	console_lock();
+	fb_info->flags |= FBINFO_MISC_USEREVENT;
+	err = fb_set_var(fb_info, var);
+	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
+	console_unlock();
+	if (err)
+		return err;
+	return 0;
+}
+
+static int mode_string(char *buf, unsigned int offset,
+		       const struct fb_videomode *mode)
+{
+	char m = 'U';
+	char v = 'p';
+
+	if (mode->flag & FB_MODE_IS_DETAILED)
+		m = 'D';
+	if (mode->flag & FB_MODE_IS_VESA)
+		m = 'V';
+	if (mode->flag & FB_MODE_IS_STANDARD)
+		m = 'S';
+
+	if (mode->vmode & FB_VMODE_INTERLACED)
+		v = 'i';
+	if (mode->vmode & FB_VMODE_DOUBLE)
+		v = 'd';
+
+	return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d%c-%d\n",
+	                m, mode->xres, mode->yres, v, mode->refresh);
+}
+
+static ssize_t store_mode(struct device *device, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	char mstr[100];
+	struct fb_var_screeninfo var;
+	struct fb_modelist *modelist;
+	struct fb_videomode *mode;
+	struct list_head *pos;
+	size_t i;
+	int err;
+
+	memset(&var, 0, sizeof(var));
+
+	list_for_each(pos, &fb_info->modelist) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+		i = mode_string(mstr, 0, mode);
+		if (strncmp(mstr, buf, max(count, i)) == 0) {
+
+			var = fb_info->var;
+			fb_videomode_to_var(&var, mode);
+			if ((err = activate(fb_info, &var)))
+				return err;
+			fb_info->mode = mode;
+			return count;
+		}
+	}
+	return -EINVAL;
+}
+
+static ssize_t show_mode(struct device *device, struct device_attribute *attr,
+			 char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+
+	if (!fb_info->mode)
+		return 0;
+
+	return mode_string(buf, 0, fb_info->mode);
+}
+
+static ssize_t store_modes(struct device *device,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	LIST_HEAD(old_list);
+	int i = count / sizeof(struct fb_videomode);
+
+	if (i * sizeof(struct fb_videomode) != count)
+		return -EINVAL;
+
+	console_lock();
+	if (!lock_fb_info(fb_info)) {
+		console_unlock();
+		return -ENODEV;
+	}
+
+	list_splice(&fb_info->modelist, &old_list);
+	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
+				 &fb_info->modelist);
+	if (fb_new_modelist(fb_info)) {
+		fb_destroy_modelist(&fb_info->modelist);
+		list_splice(&old_list, &fb_info->modelist);
+	} else
+		fb_destroy_modelist(&old_list);
+
+	unlock_fb_info(fb_info);
+	console_unlock();
+
+	return 0;
+}
+
+static ssize_t show_modes(struct device *device, struct device_attribute *attr,
+			  char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	unsigned int i;
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	const struct fb_videomode *mode;
+
+	i = 0;
+	list_for_each(pos, &fb_info->modelist) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+		i += mode_string(buf, i, mode);
+	}
+	return i;
+}
+
+static ssize_t store_bpp(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	struct fb_var_screeninfo var;
+	char ** last = NULL;
+	int err;
+
+	var = fb_info->var;
+	var.bits_per_pixel = simple_strtoul(buf, last, 0);
+	if ((err = activate(fb_info, &var)))
+		return err;
+	return count;
+}
+
+static ssize_t show_bpp(struct device *device, struct device_attribute *attr,
+			char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
+}
+
+static ssize_t store_rotate(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	struct fb_var_screeninfo var;
+	char **last = NULL;
+	int err;
+
+	var = fb_info->var;
+	var.rotate = simple_strtoul(buf, last, 0);
+
+	if ((err = activate(fb_info, &var)))
+		return err;
+
+	return count;
+}
+
+
+static ssize_t show_rotate(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate);
+}
+
+static ssize_t store_virtual(struct device *device,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	struct fb_var_screeninfo var;
+	char *last = NULL;
+	int err;
+
+	var = fb_info->var;
+	var.xres_virtual = simple_strtoul(buf, &last, 0);
+	last++;
+	if (last - buf >= count)
+		return -EINVAL;
+	var.yres_virtual = simple_strtoul(last, &last, 0);
+
+	if ((err = activate(fb_info, &var)))
+		return err;
+	return count;
+}
+
+static ssize_t show_virtual(struct device *device,
+			    struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
+			fb_info->var.yres_virtual);
+}
+
+static ssize_t show_stride(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
+}
+
+static ssize_t store_blank(struct device *device,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	char *last = NULL;
+	int err;
+
+	console_lock();
+	fb_info->flags |= FBINFO_MISC_USEREVENT;
+	err = fb_blank(fb_info, simple_strtoul(buf, &last, 0));
+	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
+	console_unlock();
+	if (err < 0)
+		return err;
+	return count;
+}
+
+static ssize_t show_blank(struct device *device,
+			  struct device_attribute *attr, char *buf)
+{
+//	struct fb_info *fb_info = dev_get_drvdata(device);
+	return 0;
+}
+
+static ssize_t store_console(struct device *device,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+//	struct fb_info *fb_info = dev_get_drvdata(device);
+	return 0;
+}
+
+static ssize_t show_console(struct device *device,
+			    struct device_attribute *attr, char *buf)
+{
+//	struct fb_info *fb_info = dev_get_drvdata(device);
+	return 0;
+}
+
+static ssize_t store_cursor(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+//	struct fb_info *fb_info = dev_get_drvdata(device);
+	return 0;
+}
+
+static ssize_t show_cursor(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+//	struct fb_info *fb_info = dev_get_drvdata(device);
+	return 0;
+}
+
+static ssize_t store_pan(struct device *device,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	struct fb_var_screeninfo var;
+	char *last = NULL;
+	int err;
+
+	var = fb_info->var;
+	var.xoffset = simple_strtoul(buf, &last, 0);
+	last++;
+	if (last - buf >= count)
+		return -EINVAL;
+	var.yoffset = simple_strtoul(last, &last, 0);
+
+	console_lock();
+	err = fb_pan_display(fb_info, &var);
+	console_unlock();
+
+	if (err < 0)
+		return err;
+	return count;
+}
+
+static ssize_t show_pan(struct device *device,
+			struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
+			fb_info->var.yoffset);
+}
+
+static ssize_t show_name(struct device *device,
+			 struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
+}
+
+static ssize_t store_fbstate(struct device *device,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	u32 state;
+	char *last = NULL;
+
+	state = simple_strtoul(buf, &last, 0);
+
+	console_lock();
+	if (!lock_fb_info(fb_info)) {
+		console_unlock();
+		return -ENODEV;
+	}
+
+	fb_set_suspend(fb_info, (int)state);
+
+	unlock_fb_info(fb_info);
+	console_unlock();
+
+	return count;
+}
+
+static ssize_t show_fbstate(struct device *device,
+			    struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
+}
+
+#ifdef CONFIG_FB_BACKLIGHT
+static ssize_t store_bl_curve(struct device *device,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	u8 tmp_curve[FB_BACKLIGHT_LEVELS];
+	unsigned int i;
+
+	/* Some drivers don't use framebuffer_alloc(), but those also
+	 * don't have backlights.
+	 */
+	if (!fb_info || !fb_info->bl_dev)
+		return -ENODEV;
+
+	if (count != (FB_BACKLIGHT_LEVELS / 8 * 24))
+		return -EINVAL;
+
+	for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i)
+		if (sscanf(&buf[i * 24],
+			"%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx\n",
+			&tmp_curve[i * 8 + 0],
+			&tmp_curve[i * 8 + 1],
+			&tmp_curve[i * 8 + 2],
+			&tmp_curve[i * 8 + 3],
+			&tmp_curve[i * 8 + 4],
+			&tmp_curve[i * 8 + 5],
+			&tmp_curve[i * 8 + 6],
+			&tmp_curve[i * 8 + 7]) != 8)
+			return -EINVAL;
+
+	/* If there has been an error in the input data, we won't
+	 * reach this loop.
+	 */
+	mutex_lock(&fb_info->bl_curve_mutex);
+	for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
+		fb_info->bl_curve[i] = tmp_curve[i];
+	mutex_unlock(&fb_info->bl_curve_mutex);
+
+	return count;
+}
+
+static ssize_t show_bl_curve(struct device *device,
+			     struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fb_info = dev_get_drvdata(device);
+	ssize_t len = 0;
+	unsigned int i;
+
+	/* Some drivers don't use framebuffer_alloc(), but those also
+	 * don't have backlights.
+	 */
+	if (!fb_info || !fb_info->bl_dev)
+		return -ENODEV;
+
+	mutex_lock(&fb_info->bl_curve_mutex);
+	for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
+		len += snprintf(&buf[len], PAGE_SIZE,
+				"%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				fb_info->bl_curve[i + 0],
+				fb_info->bl_curve[i + 1],
+				fb_info->bl_curve[i + 2],
+				fb_info->bl_curve[i + 3],
+				fb_info->bl_curve[i + 4],
+				fb_info->bl_curve[i + 5],
+				fb_info->bl_curve[i + 6],
+				fb_info->bl_curve[i + 7]);
+	mutex_unlock(&fb_info->bl_curve_mutex);
+
+	return len;
+}
+#endif
+
+/* When cmap is added back in it should be a binary attribute
+ * not a text one. Consideration should also be given to converting
+ * fbdev to use configfs instead of sysfs */
+static struct device_attribute device_attrs[] = {
+	__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
+	__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
+	__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
+	__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
+	__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
+	__ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
+	__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
+	__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+	__ATTR(name, S_IRUGO, show_name, NULL),
+	__ATTR(stride, S_IRUGO, show_stride, NULL),
+	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
+	__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
+#ifdef CONFIG_FB_BACKLIGHT
+	__ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
+#endif
+};
+
+int fb_init_device(struct fb_info *fb_info)
+{
+	int i, error = 0;
+
+	dev_set_drvdata(fb_info->dev, fb_info);
+
+	fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
+
+	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+		error = device_create_file(fb_info->dev, &device_attrs[i]);
+
+		if (error)
+			break;
+	}
+
+	if (error) {
+		while (--i >= 0)
+			device_remove_file(fb_info->dev, &device_attrs[i]);
+		fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
+	}
+
+	return 0;
+}
+
+void fb_cleanup_device(struct fb_info *fb_info)
+{
+	unsigned int i;
+
+	if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
+		for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+			device_remove_file(fb_info->dev, &device_attrs[i]);
+
+		fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
+	}
+}
+
+#ifdef CONFIG_FB_BACKLIGHT
+/* This function generates a linear backlight curve
+ *
+ *     0: off
+ *   1-7: min
+ * 8-127: linear from min to max
+ */
+void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
+{
+	unsigned int i, flat, count, range = (max - min);
+
+	mutex_lock(&fb_info->bl_curve_mutex);
+
+	fb_info->bl_curve[0] = off;
+
+	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
+		fb_info->bl_curve[flat] = min;
+
+	count = FB_BACKLIGHT_LEVELS * 15 / 16;
+	for (i = 0; i < count; ++i)
+		fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
+
+	mutex_unlock(&fb_info->bl_curve_mutex);
+}
+EXPORT_SYMBOL_GPL(fb_bl_default_curve);
+#endif
diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c
new file mode 100644
index 000000000000..a9a907c440d7
--- /dev/null
+++ b/drivers/video/fbdev/core/modedb.c
@@ -0,0 +1,1137 @@
+/*
+ *  linux/drivers/video/modedb.c -- Standard video mode database management
+ *
+ *	Copyright (C) 1999 Geert Uytterhoeven
+ *
+ *	2001 - Documented with DocBook
+ *	- Brad Douglas <brad@neruo.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+
+#undef DEBUG
+
+#define name_matches(v, s, l) \
+    ((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l))
+#define res_matches(v, x, y) \
+    ((v).xres == (x) && (v).yres == (y))
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...)	printk("modedb %s: " fmt, __func__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+const char *fb_mode_option;
+EXPORT_SYMBOL_GPL(fb_mode_option);
+
+/*
+ *  Standard video mode definitions (taken from XFree86)
+ */
+
+static const struct fb_videomode modedb[] = {
+
+	/* 640x400 @ 70 Hz, 31.5 kHz hsync */
+	{ NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
+	{ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,	0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 800x600 @ 56 Hz, 35.15 kHz hsync */
+	{ NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,	0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
+	{ NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 0,
+		FB_VMODE_INTERLACED },
+
+	/* 640x400 @ 85 Hz, 37.86 kHz hsync */
+	{ NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+
+	/* 640x480 @ 72 Hz, 36.5 kHz hsync */
+	{ NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 640x480 @ 75 Hz, 37.50 kHz hsync */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,	0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 800x600 @ 60 Hz, 37.8 kHz hsync */
+	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 640x480 @ 85 Hz, 43.27 kHz hsync */
+	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
+	{ NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 0,
+		FB_VMODE_INTERLACED },
+	/* 800x600 @ 72 Hz, 48.0 kHz hsync */
+	{ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1024x768 @ 60 Hz, 48.4 kHz hsync */
+	{ NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 640x480 @ 100 Hz, 53.01 kHz hsync */
+	{ NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,	0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1152x864 @ 60 Hz, 53.5 kHz hsync */
+	{ NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 800x600 @ 85 Hz, 55.84 kHz hsync */
+	{ NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1024x768 @ 70 Hz, 56.5 kHz hsync */
+	{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
+	{ NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,	0,
+		FB_VMODE_INTERLACED },
+
+	/* 800x600 @ 100 Hz, 64.02 kHz hsync */
+	{ NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1024x768 @ 76 Hz, 62.5 kHz hsync */
+	{ NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1152x864 @ 70 Hz, 62.4 kHz hsync */
+	{ NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
+	{ NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1400x1050 @ 60Hz, 63.9 kHz hsync */
+	{ NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
+	{ NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
+	{ NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1024x768 @ 85 Hz, 70.24 kHz hsync */
+	{ NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1152x864 @ 78 Hz, 70.8 kHz hsync */
+	{ NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
+	{ NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1600x1200 @ 60Hz, 75.00 kHz hsync */
+	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1152x864 @ 84 Hz, 76.0 kHz hsync */
+	{ NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
+	{ NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1024x768 @ 100Hz, 80.21 kHz hsync */
+	{ NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
+	{ NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
+	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1152x864 @ 100 Hz, 89.62 kHz hsync */
+	{ NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
+	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
+	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
+	{ NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
+	{ NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
+	{ NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1800x1440 @ 64Hz, 96.15 kHz hsync  */
+	{ NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1800x1440 @ 70Hz, 104.52 kHz hsync  */
+	{ NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 512x384 @ 78 Hz, 31.50 kHz hsync */
+	{ NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 512x384 @ 85 Hz, 34.38 kHz hsync */
+	{ NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
+	{ NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
+	{ NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 320x240 @ 72 Hz, 36.5 kHz hsync */
+	{ NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
+	{ NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 400x300 @ 60 Hz, 37.8 kHz hsync */
+	{ NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 400x300 @ 72 Hz, 48.0 kHz hsync */
+	{ NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,	0,
+		FB_VMODE_DOUBLE },
+
+	/* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
+	{ NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 480x300 @ 60 Hz, 37.8 kHz hsync */
+	{ NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 480x300 @ 63 Hz, 39.6 kHz hsync */
+	{ NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 480x300 @ 72 Hz, 48.0 kHz hsync */
+	{ NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0,
+		FB_VMODE_DOUBLE },
+
+	/* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
+	{ NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
+	{ NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
+	{ NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */
+	{ NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 0,
+		FB_VMODE_NONINTERLACED },
+
+	/* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
+	{ NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0,
+		FB_VMODE_INTERLACED },
+
+	/* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
+	{ NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 0,
+		FB_VMODE_INTERLACED },
+
+	/* 864x480 @ 60 Hz, 35.15 kHz hsync */
+	{ NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
+		0, FB_VMODE_NONINTERLACED },
+};
+
+#ifdef CONFIG_FB_MODE_HELPERS
+const struct fb_videomode cea_modes[64] = {
+	/* #1: 640x480p@59.94/60Hz */
+	[1] = {
+		NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
+		FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #3: 720x480p@59.94/60Hz */
+	[3] = {
+		NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
+		FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #5: 1920x1080i@59.94/60Hz */
+	[5] = {
+		NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_INTERLACED, 0,
+	},
+	/* #7: 720(1440)x480iH@59.94/60Hz */
+	[7] = {
+		NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
+		FB_VMODE_INTERLACED, 0,
+	},
+	/* #9: 720(1440)x240pH@59.94/60Hz */
+	[9] = {
+		NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
+		FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #18: 720x576pH@50Hz */
+	[18] = {
+		NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
+		FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #19: 1280x720p@50Hz */
+	[19] = {
+		NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #20: 1920x1080i@50Hz */
+	[20] = {
+		NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_INTERLACED, 0,
+	},
+	/* #32: 1920x1080p@23.98/24Hz */
+	[32] = {
+		NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #35: (2880)x480p4x@59.94/60Hz */
+	[35] = {
+		NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0,
+		FB_VMODE_NONINTERLACED, 0,
+	},
+};
+
+const struct fb_videomode vesa_modes[] = {
+	/* 0 640x350-85 VESA */
+	{ NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1 640x400-85 VESA */
+	{ NULL, 85, 640, 400, 31746,  96, 32, 41, 01, 64, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 2 720x400-85 VESA */
+	{ NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 3 640x480-60 VESA */
+	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 4 640x480-72 VESA */
+	{ NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 5 640x480-75 VESA */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 6 640x480-85 VESA */
+	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 7 800x600-56 VESA */
+	{ NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 8 800x600-60 VESA */
+	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 9 800x600-72 VESA */
+	{ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 10 800x600-75 VESA */
+	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 11 800x600-85 VESA */
+	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+        /* 12 1024x768i-43 VESA */
+	{ NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
+	/* 13 1024x768-60 VESA */
+	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 14 1024x768-70 VESA */
+	{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 15 1024x768-75 VESA */
+	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 16 1024x768-85 VESA */
+	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 17 1152x864-75 VESA */
+	{ NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 18 1280x960-60 VESA */
+	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 19 1280x960-85 VESA */
+	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 20 1280x1024-60 VESA */
+	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 21 1280x1024-75 VESA */
+	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 22 1280x1024-85 VESA */
+	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 23 1600x1200-60 VESA */
+	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 24 1600x1200-65 VESA */
+	{ NULL, 65, 1600, 1200, 5698, 304,  64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 25 1600x1200-70 VESA */
+	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 26 1600x1200-75 VESA */
+	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 27 1600x1200-85 VESA */
+	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 28 1792x1344-60 VESA */
+	{ NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 29 1792x1344-75 VESA */
+	{ NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 30 1856x1392-60 VESA */
+	{ NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 31 1856x1392-75 VESA */
+	{ NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 32 1920x1440-60 VESA */
+	{ NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 33 1920x1440-75 VESA */
+	{ NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+EXPORT_SYMBOL(vesa_modes);
+#endif /* CONFIG_FB_MODE_HELPERS */
+
+/**
+ *	fb_try_mode - test a video mode
+ *	@var: frame buffer user defined part of display
+ *	@info: frame buffer info structure
+ *	@mode: frame buffer video mode structure
+ *	@bpp: color depth in bits per pixel
+ *
+ *	Tries a video mode to test it's validity for device @info.
+ *
+ *	Returns 1 on success.
+ *
+ */
+
+static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+		       const struct fb_videomode *mode, unsigned int bpp)
+{
+	int err = 0;
+
+	DPRINTK("Trying mode %s %dx%d-%d@%d\n",
+		mode->name ? mode->name : "noname",
+		mode->xres, mode->yres, bpp, mode->refresh);
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->bits_per_pixel = bpp;
+	var->activate |= FB_ACTIVATE_TEST;
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->sync = mode->sync;
+	var->vmode = mode->vmode;
+	if (info->fbops->fb_check_var)
+		err = info->fbops->fb_check_var(var, info);
+	var->activate &= ~FB_ACTIVATE_TEST;
+	return err;
+}
+
+/**
+ *     fb_find_mode - finds a valid video mode
+ *     @var: frame buffer user defined part of display
+ *     @info: frame buffer info structure
+ *     @mode_option: string video mode to find
+ *     @db: video mode database
+ *     @dbsize: size of @db
+ *     @default_mode: default video mode to fall back to
+ *     @default_bpp: default color depth in bits per pixel
+ *
+ *     Finds a suitable video mode, starting with the specified mode
+ *     in @mode_option with fallback to @default_mode.  If
+ *     @default_mode fails, all modes in the video mode database will
+ *     be tried.
+ *
+ *     Valid mode specifiers for @mode_option:
+ *
+ *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
+ *     <name>[-<bpp>][@<refresh>]
+ *
+ *     with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
+ *     <name> a string.
+ *
+ *      If 'M' is present after yres (and before refresh/bpp if present),
+ *      the function will compute the timings using VESA(tm) Coordinated
+ *      Video Timings (CVT).  If 'R' is present after 'M', will compute with
+ *      reduced blanking (for flatpanels).  If 'i' is present, compute
+ *      interlaced mode.  If 'm' is present, add margins equal to 1.8%
+ *      of xres rounded down to 8 pixels, and 1.8% of yres. The char
+ *      'i' and 'm' must be after 'M' and 'R'. Example:
+ *
+ *      1024x768MR-8@60m - Reduced blank with margins at 60Hz.
+ *
+ *     NOTE: The passed struct @var is _not_ cleared!  This allows you
+ *     to supply values for e.g. the grayscale and accel_flags fields.
+ *
+ *     Returns zero for failure, 1 if using specified @mode_option,
+ *     2 if using specified @mode_option with an ignored refresh rate,
+ *     3 if default mode is used, 4 if fall back to any valid mode.
+ *
+ */
+
+int fb_find_mode(struct fb_var_screeninfo *var,
+		 struct fb_info *info, const char *mode_option,
+		 const struct fb_videomode *db, unsigned int dbsize,
+		 const struct fb_videomode *default_mode,
+		 unsigned int default_bpp)
+{
+	int i;
+
+	/* Set up defaults */
+	if (!db) {
+		db = modedb;
+		dbsize = ARRAY_SIZE(modedb);
+	}
+
+	if (!default_mode)
+		default_mode = &db[0];
+
+	if (!default_bpp)
+		default_bpp = 8;
+
+	/* Did the user specify a video mode? */
+	if (!mode_option)
+		mode_option = fb_mode_option;
+	if (mode_option) {
+		const char *name = mode_option;
+		unsigned int namelen = strlen(name);
+		int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+		unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
+		int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
+		int margins = 0;
+		u32 best, diff, tdiff;
+
+		for (i = namelen-1; i >= 0; i--) {
+			switch (name[i]) {
+			case '@':
+				namelen = i;
+				if (!refresh_specified && !bpp_specified &&
+				    !yres_specified) {
+					refresh = simple_strtol(&name[i+1], NULL,
+								10);
+					refresh_specified = 1;
+					if (cvt || rb)
+						cvt = 0;
+				} else
+					goto done;
+				break;
+			case '-':
+				namelen = i;
+				if (!bpp_specified && !yres_specified) {
+					bpp = simple_strtol(&name[i+1], NULL,
+							    10);
+					bpp_specified = 1;
+					if (cvt || rb)
+						cvt = 0;
+				} else
+					goto done;
+				break;
+			case 'x':
+				if (!yres_specified) {
+					yres = simple_strtol(&name[i+1], NULL,
+							     10);
+					yres_specified = 1;
+				} else
+					goto done;
+				break;
+			case '0' ... '9':
+				break;
+			case 'M':
+				if (!yres_specified)
+					cvt = 1;
+				break;
+			case 'R':
+				if (!cvt)
+					rb = 1;
+				break;
+			case 'm':
+				if (!cvt)
+					margins = 1;
+				break;
+			case 'i':
+				if (!cvt)
+					interlace = 1;
+				break;
+			default:
+				goto done;
+			}
+		}
+		if (i < 0 && yres_specified) {
+			xres = simple_strtol(name, NULL, 10);
+			res_specified = 1;
+		}
+done:
+		if (cvt) {
+			struct fb_videomode cvt_mode;
+			int ret;
+
+			DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
+				(refresh) ? refresh : 60,
+				(rb) ? " reduced blanking" : "",
+				(margins) ? " with margins" : "",
+				(interlace) ? " interlaced" : "");
+
+			memset(&cvt_mode, 0, sizeof(cvt_mode));
+			cvt_mode.xres = xres;
+			cvt_mode.yres = yres;
+			cvt_mode.refresh = (refresh) ? refresh : 60;
+
+			if (interlace)
+				cvt_mode.vmode |= FB_VMODE_INTERLACED;
+			else
+				cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
+
+			ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
+
+			if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
+				DPRINTK("modedb CVT: CVT mode ok\n");
+				return 1;
+			}
+
+			DPRINTK("CVT mode invalid, getting mode from database\n");
+		}
+
+		DPRINTK("Trying specified video mode%s %ix%i\n",
+			refresh_specified ? "" : " (ignoring refresh rate)",
+			xres, yres);
+
+		if (!refresh_specified) {
+			/*
+			 * If the caller has provided a custom mode database and
+			 * a valid monspecs structure, we look for the mode with
+			 * the highest refresh rate.  Otherwise we play it safe
+			 * it and try to find a mode with a refresh rate closest
+			 * to the standard 60 Hz.
+			 */
+			if (db != modedb &&
+			    info->monspecs.vfmin && info->monspecs.vfmax &&
+			    info->monspecs.hfmin && info->monspecs.hfmax &&
+			    info->monspecs.dclkmax) {
+				refresh = 1000;
+			} else {
+				refresh = 60;
+			}
+		}
+
+		diff = -1;
+		best = -1;
+		for (i = 0; i < dbsize; i++) {
+			if ((name_matches(db[i], name, namelen) ||
+			     (res_specified && res_matches(db[i], xres, yres))) &&
+			    !fb_try_mode(var, info, &db[i], bpp)) {
+				if (refresh_specified && db[i].refresh == refresh)
+					return 1;
+
+				if (abs(db[i].refresh - refresh) < diff) {
+					diff = abs(db[i].refresh - refresh);
+					best = i;
+				}
+			}
+		}
+		if (best != -1) {
+			fb_try_mode(var, info, &db[best], bpp);
+			return (refresh_specified) ? 2 : 1;
+		}
+
+		diff = 2 * (xres + yres);
+		best = -1;
+		DPRINTK("Trying best-fit modes\n");
+		for (i = 0; i < dbsize; i++) {
+			DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
+			if (!fb_try_mode(var, info, &db[i], bpp)) {
+				tdiff = abs(db[i].xres - xres) +
+					abs(db[i].yres - yres);
+
+				/*
+				 * Penalize modes with resolutions smaller
+				 * than requested.
+				 */
+				if (xres > db[i].xres || yres > db[i].yres)
+					tdiff += xres + yres;
+
+				if (diff > tdiff) {
+					diff = tdiff;
+					best = i;
+				}
+			}
+		}
+		if (best != -1) {
+			fb_try_mode(var, info, &db[best], bpp);
+			return 5;
+		}
+	}
+
+	DPRINTK("Trying default video mode\n");
+	if (!fb_try_mode(var, info, default_mode, default_bpp))
+		return 3;
+
+	DPRINTK("Trying all modes\n");
+	for (i = 0; i < dbsize; i++)
+		if (!fb_try_mode(var, info, &db[i], default_bpp))
+			return 4;
+
+	DPRINTK("No valid mode found\n");
+	return 0;
+}
+
+/**
+ * fb_var_to_videomode - convert fb_var_screeninfo to fb_videomode
+ * @mode: pointer to struct fb_videomode
+ * @var: pointer to struct fb_var_screeninfo
+ */
+void fb_var_to_videomode(struct fb_videomode *mode,
+			 const struct fb_var_screeninfo *var)
+{
+	u32 pixclock, hfreq, htotal, vtotal;
+
+	mode->name = NULL;
+	mode->xres = var->xres;
+	mode->yres = var->yres;
+	mode->pixclock = var->pixclock;
+	mode->hsync_len = var->hsync_len;
+	mode->vsync_len = var->vsync_len;
+	mode->left_margin = var->left_margin;
+	mode->right_margin = var->right_margin;
+	mode->upper_margin = var->upper_margin;
+	mode->lower_margin = var->lower_margin;
+	mode->sync = var->sync;
+	mode->vmode = var->vmode & FB_VMODE_MASK;
+	mode->flag = FB_MODE_IS_FROM_VAR;
+	mode->refresh = 0;
+
+	if (!var->pixclock)
+		return;
+
+	pixclock = PICOS2KHZ(var->pixclock) * 1000;
+
+	htotal = var->xres + var->right_margin + var->hsync_len +
+		var->left_margin;
+	vtotal = var->yres + var->lower_margin + var->vsync_len +
+		var->upper_margin;
+
+	if (var->vmode & FB_VMODE_INTERLACED)
+		vtotal /= 2;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		vtotal *= 2;
+
+	hfreq = pixclock/htotal;
+	mode->refresh = hfreq/vtotal;
+}
+
+/**
+ * fb_videomode_to_var - convert fb_videomode to fb_var_screeninfo
+ * @var: pointer to struct fb_var_screeninfo
+ * @mode: pointer to struct fb_videomode
+ */
+void fb_videomode_to_var(struct fb_var_screeninfo *var,
+			 const struct fb_videomode *mode)
+{
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->sync = mode->sync;
+	var->vmode = mode->vmode & FB_VMODE_MASK;
+}
+
+/**
+ * fb_mode_is_equal - compare 2 videomodes
+ * @mode1: first videomode
+ * @mode2: second videomode
+ *
+ * RETURNS:
+ * 1 if equal, 0 if not
+ */
+int fb_mode_is_equal(const struct fb_videomode *mode1,
+		     const struct fb_videomode *mode2)
+{
+	return (mode1->xres         == mode2->xres &&
+		mode1->yres         == mode2->yres &&
+		mode1->pixclock     == mode2->pixclock &&
+		mode1->hsync_len    == mode2->hsync_len &&
+		mode1->vsync_len    == mode2->vsync_len &&
+		mode1->left_margin  == mode2->left_margin &&
+		mode1->right_margin == mode2->right_margin &&
+		mode1->upper_margin == mode2->upper_margin &&
+		mode1->lower_margin == mode2->lower_margin &&
+		mode1->sync         == mode2->sync &&
+		mode1->vmode        == mode2->vmode);
+}
+
+/**
+ * fb_find_best_mode - find best matching videomode
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to struct list_head of modelist
+ *
+ * RETURNS:
+ * struct fb_videomode, NULL if none found
+ *
+ * IMPORTANT:
+ * This function assumes that all modelist entries in
+ * info->modelist are valid.
+ *
+ * NOTES:
+ * Finds best matching videomode which has an equal or greater dimension than
+ * var->xres and var->yres.  If more than 1 videomode is found, will return
+ * the videomode with the highest refresh rate
+ */
+const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+					     struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *mode, *best = NULL;
+	u32 diff = -1;
+
+	list_for_each(pos, head) {
+		u32 d;
+
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+
+		if (mode->xres >= var->xres && mode->yres >= var->yres) {
+			d = (mode->xres - var->xres) +
+				(mode->yres - var->yres);
+			if (diff > d) {
+				diff = d;
+				best = mode;
+			} else if (diff == d && best &&
+				   mode->refresh > best->refresh)
+				best = mode;
+		}
+	}
+	return best;
+}
+
+/**
+ * fb_find_nearest_mode - find closest videomode
+ *
+ * @mode: pointer to struct fb_videomode
+ * @head: pointer to modelist
+ *
+ * Finds best matching videomode, smaller or greater in dimension.
+ * If more than 1 videomode is found, will return the videomode with
+ * the closest refresh rate.
+ */
+const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+					        struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *cmode, *best = NULL;
+	u32 diff = -1, diff_refresh = -1;
+
+	list_for_each(pos, head) {
+		u32 d;
+
+		modelist = list_entry(pos, struct fb_modelist, list);
+		cmode = &modelist->mode;
+
+		d = abs(cmode->xres - mode->xres) +
+			abs(cmode->yres - mode->yres);
+		if (diff > d) {
+			diff = d;
+			diff_refresh = abs(cmode->refresh - mode->refresh);
+			best = cmode;
+		} else if (diff == d) {
+			d = abs(cmode->refresh - mode->refresh);
+			if (diff_refresh > d) {
+				diff_refresh = d;
+				best = cmode;
+			}
+		}
+	}
+
+	return best;
+}
+
+/**
+ * fb_match_mode - find a videomode which exactly matches the timings in var
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to struct list_head of modelist
+ *
+ * RETURNS:
+ * struct fb_videomode, NULL if none found
+ */
+const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+					 struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m, mode;
+
+	fb_var_to_videomode(&mode, var);
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, &mode))
+			return m;
+	}
+	return NULL;
+}
+
+/**
+ * fb_add_videomode - adds videomode entry to modelist
+ * @mode: videomode to add
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will only add unmatched mode entries
+ */
+int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m;
+	int found = 0;
+
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, mode)) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		modelist = kmalloc(sizeof(struct fb_modelist),
+						  GFP_KERNEL);
+
+		if (!modelist)
+			return -ENOMEM;
+		modelist->mode = *mode;
+		list_add(&modelist->list, head);
+	}
+	return 0;
+}
+
+/**
+ * fb_delete_videomode - removed videomode entry from modelist
+ * @mode: videomode to remove
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will remove all matching mode entries
+ */
+void fb_delete_videomode(const struct fb_videomode *mode,
+			 struct list_head *head)
+{
+	struct list_head *pos, *n;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m;
+
+	list_for_each_safe(pos, n, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, mode)) {
+			list_del(pos);
+			kfree(pos);
+		}
+	}
+}
+
+/**
+ * fb_destroy_modelist - destroy modelist
+ * @head: struct list_head of modelist
+ */
+void fb_destroy_modelist(struct list_head *head)
+{
+	struct list_head *pos, *n;
+
+	list_for_each_safe(pos, n, head) {
+		list_del(pos);
+		kfree(pos);
+	}
+}
+EXPORT_SYMBOL_GPL(fb_destroy_modelist);
+
+/**
+ * fb_videomode_to_modelist - convert mode array to mode list
+ * @modedb: array of struct fb_videomode
+ * @num: number of entries in array
+ * @head: struct list_head of modelist
+ */
+void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
+			      struct list_head *head)
+{
+	int i;
+
+	INIT_LIST_HEAD(head);
+
+	for (i = 0; i < num; i++) {
+		if (fb_add_videomode(&modedb[i], head))
+			return;
+	}
+}
+
+const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+					        struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+	int first = 0;
+
+	if (!head->prev || !head->next || list_empty(head))
+		goto finished;
+
+	/* get the first detailed mode and the very first mode */
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+
+		if (!first) {
+			m1 = m;
+			first = 1;
+		}
+
+		if (m->flag & FB_MODE_IS_FIRST) {
+ 			md = m;
+			break;
+		}
+	}
+
+	/* first detailed timing is preferred */
+	if (specs->misc & FB_MISC_1ST_DETAIL) {
+		best = md;
+		goto finished;
+	}
+
+	/* find best mode based on display width and height */
+	if (specs->max_x && specs->max_y) {
+		struct fb_var_screeninfo var;
+
+		memset(&var, 0, sizeof(struct fb_var_screeninfo));
+		var.xres = (specs->max_x * 7200)/254;
+		var.yres = (specs->max_y * 7200)/254;
+		m = fb_find_best_mode(&var, head);
+		if (m) {
+			best = m;
+			goto finished;
+		}
+	}
+
+	/* use first detailed mode */
+	if (md) {
+		best = md;
+		goto finished;
+	}
+
+	/* last resort, use the very first mode */
+	best = m1;
+finished:
+	return best;
+}
+EXPORT_SYMBOL(fb_find_best_display);
+
+EXPORT_SYMBOL(fb_videomode_to_var);
+EXPORT_SYMBOL(fb_var_to_videomode);
+EXPORT_SYMBOL(fb_mode_is_equal);
+EXPORT_SYMBOL(fb_add_videomode);
+EXPORT_SYMBOL(fb_match_mode);
+EXPORT_SYMBOL(fb_find_best_mode);
+EXPORT_SYMBOL(fb_find_nearest_mode);
+EXPORT_SYMBOL(fb_videomode_to_modelist);
+EXPORT_SYMBOL(fb_find_mode);
+EXPORT_SYMBOL(fb_find_mode_cvt);
diff --git a/drivers/video/fbdev/core/svgalib.c b/drivers/video/fbdev/core/svgalib.c
new file mode 100644
index 000000000000..9e01322fabe3
--- /dev/null
+++ b/drivers/video/fbdev/core/svgalib.c
@@ -0,0 +1,672 @@
+/*
+ * Common utility functions for VGA-based graphics cards.
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Some parts are based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <asm/types.h>
+#include <asm/io.h>
+
+
+/* Write a CRT register value spread across multiple registers */
+void svga_wcrt_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value)
+{
+	u8 regval, bitval, bitnum;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		regval = vga_rcrt(regbase, regset->regnum);
+		bitnum = regset->lowbit;
+		while (bitnum <= regset->highbit) {
+			bitval = 1 << bitnum;
+			regval = regval & ~bitval;
+			if (value & 1) regval = regval | bitval;
+			bitnum ++;
+			value = value >> 1;
+		}
+		vga_wcrt(regbase, regset->regnum, regval);
+		regset ++;
+	}
+}
+
+/* Write a sequencer register value spread across multiple registers */
+void svga_wseq_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value)
+{
+	u8 regval, bitval, bitnum;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		regval = vga_rseq(regbase, regset->regnum);
+		bitnum = regset->lowbit;
+		while (bitnum <= regset->highbit) {
+			bitval = 1 << bitnum;
+			regval = regval & ~bitval;
+			if (value & 1) regval = regval | bitval;
+			bitnum ++;
+			value = value >> 1;
+		}
+		vga_wseq(regbase, regset->regnum, regval);
+		regset ++;
+	}
+}
+
+static unsigned int svga_regset_size(const struct vga_regset *regset)
+{
+	u8 count = 0;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		count += regset->highbit - regset->lowbit + 1;
+		regset ++;
+	}
+	return 1 << count;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Set graphics controller registers to sane values */
+void svga_set_default_gfx_regs(void __iomem *regbase)
+{
+	/* All standard GFX registers (GR00 - GR08) */
+	vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0x00);
+	vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0x00);
+	vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0x00);
+	vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0x00);
+	vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0x00);
+	vga_wgfx(regbase, VGA_GFX_MODE, 0x00);
+/*	vga_wgfx(regbase, VGA_GFX_MODE, 0x20); */
+/*	vga_wgfx(regbase, VGA_GFX_MODE, 0x40); */
+	vga_wgfx(regbase, VGA_GFX_MISC, 0x05);
+/*	vga_wgfx(regbase, VGA_GFX_MISC, 0x01); */
+	vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x0F);
+	vga_wgfx(regbase, VGA_GFX_BIT_MASK, 0xFF);
+}
+
+/* Set attribute controller registers to sane values */
+void svga_set_default_atc_regs(void __iomem *regbase)
+{
+	u8 count;
+
+	vga_r(regbase, 0x3DA);
+	vga_w(regbase, VGA_ATT_W, 0x00);
+
+	/* All standard ATC registers (AR00 - AR14) */
+	for (count = 0; count <= 0xF; count ++)
+		svga_wattr(regbase, count, count);
+
+	svga_wattr(regbase, VGA_ATC_MODE, 0x01);
+/*	svga_wattr(regbase, VGA_ATC_MODE, 0x41); */
+	svga_wattr(regbase, VGA_ATC_OVERSCAN, 0x00);
+	svga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 0x0F);
+	svga_wattr(regbase, VGA_ATC_PEL, 0x00);
+	svga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0x00);
+
+	vga_r(regbase, 0x3DA);
+	vga_w(regbase, VGA_ATT_W, 0x20);
+}
+
+/* Set sequencer registers to sane values */
+void svga_set_default_seq_regs(void __iomem *regbase)
+{
+	/* Standard sequencer registers (SR01 - SR04), SR00 is not set */
+	vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS);
+	vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES);
+	vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
+/*	vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */
+	vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE);
+}
+
+/* Set CRTC registers to sane values */
+void svga_set_default_crt_regs(void __iomem *regbase)
+{
+	/* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */
+	svga_wcrt_mask(regbase, 0x03, 0x80, 0x80);	/* Enable vertical retrace EVRA */
+	vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
+	svga_wcrt_mask(regbase, VGA_CRTC_MAX_SCAN, 0, 0x1F);
+	vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
+	vga_wcrt(regbase, VGA_CRTC_MODE, 0xE3);
+}
+
+void svga_set_textmode_vga_regs(void __iomem *regbase)
+{
+	/* svga_wseq_mask(regbase, 0x1, 0x00, 0x01); */   /* Switch 8/9 pixel per char */
+	vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM);
+	vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x03);
+
+	vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, 0x0f); /* 0x4f */
+	vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0x1f);
+	svga_wcrt_mask(regbase, VGA_CRTC_MODE, 0x23, 0x7f);
+
+	vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0x0d);
+	vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 0x0e);
+	vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0x00);
+	vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0x00);
+
+	vga_wgfx(regbase, VGA_GFX_MODE, 0x10); /* Odd/even memory mode */
+	vga_wgfx(regbase, VGA_GFX_MISC, 0x0E); /* Misc graphics register - text mode enable */
+	vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x00);
+
+	vga_r(regbase, 0x3DA);
+	vga_w(regbase, VGA_ATT_W, 0x00);
+
+	svga_wattr(regbase, 0x10, 0x0C);			/* Attribute Mode Control Register - text mode, blinking and line graphics */
+	svga_wattr(regbase, 0x13, 0x08);			/* Horizontal Pixel Panning Register  */
+
+	vga_r(regbase, 0x3DA);
+	vga_w(regbase, VGA_ATT_W, 0x20);
+}
+
+#if 0
+void svga_dump_var(struct fb_var_screeninfo *var, int node)
+{
+	pr_debug("fb%d: var.vmode         : 0x%X\n", node, var->vmode);
+	pr_debug("fb%d: var.xres          : %d\n", node, var->xres);
+	pr_debug("fb%d: var.yres          : %d\n", node, var->yres);
+	pr_debug("fb%d: var.bits_per_pixel: %d\n", node, var->bits_per_pixel);
+	pr_debug("fb%d: var.xres_virtual  : %d\n", node, var->xres_virtual);
+	pr_debug("fb%d: var.yres_virtual  : %d\n", node, var->yres_virtual);
+	pr_debug("fb%d: var.left_margin   : %d\n", node, var->left_margin);
+	pr_debug("fb%d: var.right_margin  : %d\n", node, var->right_margin);
+	pr_debug("fb%d: var.upper_margin  : %d\n", node, var->upper_margin);
+	pr_debug("fb%d: var.lower_margin  : %d\n", node, var->lower_margin);
+	pr_debug("fb%d: var.hsync_len     : %d\n", node, var->hsync_len);
+	pr_debug("fb%d: var.vsync_len     : %d\n", node, var->vsync_len);
+	pr_debug("fb%d: var.sync          : 0x%X\n", node, var->sync);
+	pr_debug("fb%d: var.pixclock      : %d\n\n", node, var->pixclock);
+}
+#endif  /*  0  */
+
+
+/* ------------------------------------------------------------------------- */
+
+
+void svga_settile(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+		       map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (c = 0; c < map->length; c++) {
+		for (i = 0; i < map->height; i++) {
+			fb_writeb(font[i], fb + i * 4);
+//			fb[i * 4] = font[i];
+		}
+		fb += 128;
+		font += map->height;
+	}
+}
+
+/* Copy area in text (tileblit) mode */
+void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area)
+{
+	int dx, dy;
+	/*  colstride is halved in this function because u16 are used */
+	int colstride = 1 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	u16 __iomem *fb = (u16 __iomem *) info->screen_base;
+	u16 __iomem *src, *dst;
+
+	if ((area->sy > area->dy) ||
+	    ((area->sy == area->dy) && (area->sx > area->dx))) {
+		src = fb + area->sx * colstride + area->sy * rowstride;
+		dst = fb + area->dx * colstride + area->dy * rowstride;
+	    } else {
+		src = fb + (area->sx + area->width - 1) * colstride
+			 + (area->sy + area->height - 1) * rowstride;
+		dst = fb + (area->dx + area->width - 1) * colstride
+			 + (area->dy + area->height - 1) * rowstride;
+
+		colstride = -colstride;
+		rowstride = -rowstride;
+	    }
+
+	for (dy = 0; dy < area->height; dy++) {
+		u16 __iomem *src2 = src;
+		u16 __iomem *dst2 = dst;
+		for (dx = 0; dx < area->width; dx++) {
+			fb_writew(fb_readw(src2), dst2);
+//			*dst2 = *src2;
+			src2 += colstride;
+			dst2 += colstride;
+		}
+		src += rowstride;
+		dst += rowstride;
+	}
+}
+
+/* Fill area in text (tileblit) mode */
+void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect)
+{
+	int dx, dy;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg);
+	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
+	fb += rect->sx * colstride + rect->sy * rowstride;
+
+	for (dy = 0; dy < rect->height; dy++) {
+		u8 __iomem *fb2 = fb;
+		for (dx = 0; dx < rect->width; dx++) {
+			fb_writeb(rect->index, fb2);
+			fb_writeb(attr, fb2 + 1);
+			fb2 += colstride;
+		}
+		fb += rowstride;
+	}
+}
+
+/* Write text in text (tileblit) mode */
+void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit)
+{
+	int dx, dy, i;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg);
+	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
+	fb += blit->sx * colstride + blit->sy * rowstride;
+
+	i=0;
+	for (dy=0; dy < blit->height; dy ++) {
+		u8 __iomem *fb2 = fb;
+		for (dx = 0; dx < blit->width; dx ++) {
+			fb_writeb(blit->indices[i], fb2);
+			fb_writeb(attr, fb2 + 1);
+			fb2 += colstride;
+			i ++;
+			if (i == blit->length) return;
+		}
+		fb += rowstride;
+	}
+
+}
+
+/* Set cursor in text (tileblit) mode */
+void svga_tilecursor(void __iomem *regbase, struct fb_info *info, struct fb_tilecursor *cursor)
+{
+	u8 cs = 0x0d;
+	u8 ce = 0x0e;
+	u16 pos =  cursor->sx + (info->var.xoffset /  8)
+		+ (cursor->sy + (info->var.yoffset / 16))
+		   * (info->var.xres_virtual / 8);
+
+	if (! cursor -> mode)
+		return;
+
+	svga_wcrt_mask(regbase, 0x0A, 0x20, 0x20); /* disable cursor */
+
+	if (cursor -> shape == FB_TILE_CURSOR_NONE)
+		return;
+
+	switch (cursor -> shape) {
+	case FB_TILE_CURSOR_UNDERLINE:
+		cs = 0x0d;
+		break;
+	case FB_TILE_CURSOR_LOWER_THIRD:
+		cs = 0x09;
+		break;
+	case FB_TILE_CURSOR_LOWER_HALF:
+		cs = 0x07;
+		break;
+	case FB_TILE_CURSOR_TWO_THIRDS:
+		cs = 0x05;
+		break;
+	case FB_TILE_CURSOR_BLOCK:
+		cs = 0x01;
+		break;
+	}
+
+	/* set cursor position */
+	vga_wcrt(regbase, 0x0E, pos >> 8);
+	vga_wcrt(regbase, 0x0F, pos & 0xFF);
+
+	vga_wcrt(regbase, 0x0B, ce); /* set cursor end */
+	vga_wcrt(regbase, 0x0A, cs); /* set cursor start and enable it */
+}
+
+int svga_get_tilemax(struct fb_info *info)
+{
+	return 256;
+}
+
+/* Get capabilities of accelerator based on the mode */
+
+void svga_get_caps(struct fb_info *info, struct fb_blit_caps *caps,
+		   struct fb_var_screeninfo *var)
+{
+	if (var->bits_per_pixel == 0) {
+		/* can only support 256 8x16 bitmap */
+		caps->x = 1 << (8 - 1);
+		caps->y = 1 << (16 - 1);
+		caps->len = 256;
+	} else {
+		caps->x = (var->bits_per_pixel == 4) ? 1 << (8 - 1) : ~(u32)0;
+		caps->y = ~(u32)0;
+		caps->len = ~(u32)0;
+	}
+}
+EXPORT_SYMBOL(svga_get_caps);
+
+/* ------------------------------------------------------------------------- */
+
+
+/*
+ *  Compute PLL settings (M, N, R)
+ *  F_VCO = (F_BASE * M) / N
+ *  F_OUT = F_VCO / (2^R)
+ */
+
+static inline u32 abs_diff(u32 a, u32 b)
+{
+	return (a > b) ? (a - b) : (b - a);
+}
+
+int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node)
+{
+	u16 am, an, ar;
+	u32 f_vco, f_current, delta_current, delta_best;
+
+	pr_debug("fb%d: ideal frequency: %d kHz\n", node, (unsigned int) f_wanted);
+
+	ar = pll->r_max;
+	f_vco = f_wanted << ar;
+
+	/* overflow check */
+	if ((f_vco >> ar) != f_wanted)
+		return -EINVAL;
+
+	/* It is usually better to have greater VCO clock
+	   because of better frequency stability.
+	   So first try r_max, then r smaller. */
+	while ((ar > pll->r_min) && (f_vco > pll->f_vco_max)) {
+		ar--;
+		f_vco = f_vco >> 1;
+	}
+
+	/* VCO bounds check */
+	if ((f_vco < pll->f_vco_min) || (f_vco > pll->f_vco_max))
+		return -EINVAL;
+
+	delta_best = 0xFFFFFFFF;
+	*m = 0;
+	*n = 0;
+	*r = ar;
+
+	am = pll->m_min;
+	an = pll->n_min;
+
+	while ((am <= pll->m_max) && (an <= pll->n_max)) {
+		f_current = (pll->f_base * am) / an;
+		delta_current = abs_diff (f_current, f_vco);
+
+		if (delta_current < delta_best) {
+			delta_best = delta_current;
+			*m = am;
+			*n = an;
+		}
+
+		if (f_current <= f_vco) {
+			am ++;
+		} else {
+			an ++;
+		}
+	}
+
+	f_current = (pll->f_base * *m) / *n;
+	pr_debug("fb%d: found frequency: %d kHz (VCO %d kHz)\n", node, (int) (f_current >> ar), (int) f_current);
+	pr_debug("fb%d: m = %d n = %d r = %d\n", node, (unsigned int) *m, (unsigned int) *n, (unsigned int) *r);
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Check CRT timing values */
+int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node)
+{
+	u32 value;
+
+	var->xres         = (var->xres+7)&~7;
+	var->left_margin  = (var->left_margin+7)&~7;
+	var->right_margin = (var->right_margin+7)&~7;
+	var->hsync_len    = (var->hsync_len+7)&~7;
+
+	/* Check horizontal total */
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	if (((value / 8) - 5) >= svga_regset_size (tm->h_total_regs))
+		return -EINVAL;
+
+	/* Check horizontal display and blank start */
+	value = var->xres;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_display_regs))
+		return -EINVAL;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_blank_start_regs))
+		return -EINVAL;
+
+	/* Check horizontal sync start */
+	value = var->xres + var->right_margin;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_sync_start_regs))
+		return -EINVAL;
+
+	/* Check horizontal blank end (or length) */
+	value = var->left_margin + var->right_margin + var->hsync_len;
+	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_blank_end_regs)))
+		return -EINVAL;
+
+	/* Check horizontal sync end (or length) */
+	value = var->hsync_len;
+	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_sync_end_regs)))
+		return -EINVAL;
+
+	/* Check vertical total */
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	if ((value - 1) >= svga_regset_size(tm->v_total_regs))
+		return -EINVAL;
+
+	/* Check vertical display and blank start */
+	value = var->yres;
+	if ((value - 1) >= svga_regset_size(tm->v_display_regs))
+		return -EINVAL;
+	if ((value - 1) >= svga_regset_size(tm->v_blank_start_regs))
+		return -EINVAL;
+
+	/* Check vertical sync start */
+	value = var->yres + var->lower_margin;
+	if ((value - 1) >= svga_regset_size(tm->v_sync_start_regs))
+		return -EINVAL;
+
+	/* Check vertical blank end (or length) */
+	value = var->upper_margin + var->lower_margin + var->vsync_len;
+	if ((value == 0) || (value >= svga_regset_size (tm->v_blank_end_regs)))
+		return -EINVAL;
+
+	/* Check vertical sync end  (or length) */
+	value = var->vsync_len;
+	if ((value == 0) || (value >= svga_regset_size (tm->v_sync_end_regs)))
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Set CRT timing registers */
+void svga_set_timings(void __iomem *regbase, const struct svga_timing_regs *tm,
+		      struct fb_var_screeninfo *var,
+		      u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node)
+{
+	u8 regval;
+	u32 value;
+
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal total      : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->h_total_regs, (value / 8) - 5);
+
+	value = var->xres;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal display    : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->h_display_regs, (value / 8) - 1);
+
+	value = var->xres;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal blank start: %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->h_blank_start_regs, (value / 8) - 1 + hborder);
+
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal blank end  : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->h_blank_end_regs, (value / 8) - 1 - hborder);
+
+	value = var->xres + var->right_margin;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal sync start : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->h_sync_start_regs, (value / 8));
+
+	value = var->xres + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal sync end   : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->h_sync_end_regs, (value / 8));
+
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical total        : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->v_total_regs, value - 2);
+
+	value = var->yres;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical display      : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->v_display_regs, value - 1);
+
+	value = var->yres;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical blank start  : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->v_blank_start_regs, value);
+
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical blank end    : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->v_blank_end_regs, value - 2);
+
+	value = var->yres + var->lower_margin;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical sync start   : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->v_sync_start_regs, value);
+
+	value = var->yres + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical sync end     : %d\n", node, value);
+	svga_wcrt_multi(regbase, tm->v_sync_end_regs, value);
+
+	/* Set horizontal and vertical sync pulse polarity in misc register */
+
+	regval = vga_r(regbase, VGA_MIS_R);
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT) {
+		pr_debug("fb%d: positive horizontal sync\n", node);
+		regval = regval & ~0x80;
+	} else {
+		pr_debug("fb%d: negative horizontal sync\n", node);
+		regval = regval | 0x80;
+	}
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT) {
+		pr_debug("fb%d: positive vertical sync\n", node);
+		regval = regval & ~0x40;
+	} else {
+		pr_debug("fb%d: negative vertical sync\n\n", node);
+		regval = regval | 0x40;
+	}
+	vga_w(regbase, VGA_MIS_W, regval);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static inline int match_format(const struct svga_fb_format *frm,
+			       struct fb_var_screeninfo *var)
+{
+	int i = 0;
+	int stored = -EINVAL;
+
+	while (frm->bits_per_pixel != SVGA_FORMAT_END_VAL)
+	{
+		if ((var->bits_per_pixel == frm->bits_per_pixel) &&
+		    (var->red.length     <= frm->red.length)     &&
+		    (var->green.length   <= frm->green.length)   &&
+		    (var->blue.length    <= frm->blue.length)    &&
+		    (var->transp.length  <= frm->transp.length)  &&
+		    (var->nonstd	 == frm->nonstd))
+			return i;
+		if (var->bits_per_pixel == frm->bits_per_pixel)
+			stored = i;
+		i++;
+		frm++;
+	}
+	return stored;
+}
+
+int svga_match_format(const struct svga_fb_format *frm,
+		      struct fb_var_screeninfo *var,
+		      struct fb_fix_screeninfo *fix)
+{
+	int i = match_format(frm, var);
+
+	if (i >= 0) {
+		var->bits_per_pixel = frm[i].bits_per_pixel;
+		var->red            = frm[i].red;
+		var->green          = frm[i].green;
+		var->blue           = frm[i].blue;
+		var->transp         = frm[i].transp;
+		var->nonstd         = frm[i].nonstd;
+		if (fix != NULL) {
+			fix->type      = frm[i].type;
+			fix->type_aux  = frm[i].type_aux;
+			fix->visual    = frm[i].visual;
+			fix->xpanstep  = frm[i].xpanstep;
+		}
+	}
+
+	return i;
+}
+
+
+EXPORT_SYMBOL(svga_wcrt_multi);
+EXPORT_SYMBOL(svga_wseq_multi);
+
+EXPORT_SYMBOL(svga_set_default_gfx_regs);
+EXPORT_SYMBOL(svga_set_default_atc_regs);
+EXPORT_SYMBOL(svga_set_default_seq_regs);
+EXPORT_SYMBOL(svga_set_default_crt_regs);
+EXPORT_SYMBOL(svga_set_textmode_vga_regs);
+
+EXPORT_SYMBOL(svga_settile);
+EXPORT_SYMBOL(svga_tilecopy);
+EXPORT_SYMBOL(svga_tilefill);
+EXPORT_SYMBOL(svga_tileblit);
+EXPORT_SYMBOL(svga_tilecursor);
+EXPORT_SYMBOL(svga_get_tilemax);
+
+EXPORT_SYMBOL(svga_compute_pll);
+EXPORT_SYMBOL(svga_check_timings);
+EXPORT_SYMBOL(svga_set_timings);
+EXPORT_SYMBOL(svga_match_format);
+
+MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_DESCRIPTION("Common utility functions for VGA-based graphics cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c
new file mode 100644
index 000000000000..844a32fd38ed
--- /dev/null
+++ b/drivers/video/fbdev/core/syscopyarea.c
@@ -0,0 +1,377 @@
+/*
+ *  Generic Bit Block Transfer for frame buffers located in system RAM with
+ *  packed pixels of any depth.
+ *
+ *  Based almost entirely from cfbcopyarea.c (which is based almost entirely
+ *  on Geert Uytterhoeven's copyarea routine)
+ *
+ *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include "fb_draw.h"
+
+    /*
+     *  Generic bitwise copy algorithm
+     */
+
+static void
+bitcpy(struct fb_info *p, unsigned long *dst, int dst_idx,
+		const unsigned long *src, int src_idx, int bits, unsigned n)
+{
+	unsigned long first, last;
+	int const shift = dst_idx-src_idx;
+	int left, right;
+
+	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
+	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+	if (!shift) {
+		/* Same alignment for source and dest */
+		if (dst_idx+n <= bits) {
+			/* Single word */
+			if (last)
+				first &= last;
+			*dst = comp(*src, *dst, first);
+		} else {
+			/* Multiple destination words */
+			/* Leading bits */
+ 			if (first != ~0UL) {
+				*dst = comp(*src, *dst, first);
+				dst++;
+				src++;
+				n -= bits - dst_idx;
+			}
+
+			/* Main chunk */
+			n /= bits;
+			while (n >= 8) {
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				*dst++ = *src++;
+				n -= 8;
+			}
+			while (n--)
+				*dst++ = *src++;
+
+			/* Trailing bits */
+			if (last)
+				*dst = comp(*src, *dst, last);
+		}
+	} else {
+		unsigned long d0, d1;
+		int m;
+
+		/* Different alignment for source and dest */
+		right = shift & (bits - 1);
+		left = -shift & (bits - 1);
+
+		if (dst_idx+n <= bits) {
+			/* Single destination word */
+			if (last)
+				first &= last;
+			if (shift > 0) {
+				/* Single source word */
+				*dst = comp(*src >> right, *dst, first);
+			} else if (src_idx+n <= bits) {
+				/* Single source word */
+				*dst = comp(*src << left, *dst, first);
+			} else {
+				/* 2 source words */
+				d0 = *src++;
+				d1 = *src;
+				*dst = comp(d0 << left | d1 >> right, *dst,
+					    first);
+			}
+		} else {
+			/* Multiple destination words */
+			/** We must always remember the last value read,
+			    because in case SRC and DST overlap bitwise (e.g.
+			    when moving just one pixel in 1bpp), we always
+			    collect one full long for DST and that might
+			    overlap with the current long from SRC. We store
+			    this value in 'd0'. */
+			d0 = *src++;
+			/* Leading bits */
+			if (shift > 0) {
+				/* Single source word */
+				*dst = comp(d0 >> right, *dst, first);
+				dst++;
+				n -= bits - dst_idx;
+			} else {
+				/* 2 source words */
+				d1 = *src++;
+				*dst = comp(d0 << left | *dst >> right, *dst, first);
+				d0 = d1;
+				dst++;
+				n -= bits - dst_idx;
+			}
+
+			/* Main chunk */
+			m = n % bits;
+			n /= bits;
+			while (n >= 4) {
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+				n -= 4;
+			}
+			while (n--) {
+				d1 = *src++;
+				*dst++ = d0 << left | d1 >> right;
+				d0 = d1;
+			}
+
+			/* Trailing bits */
+			if (last) {
+				if (m <= right) {
+					/* Single source word */
+					*dst = comp(d0 << left, *dst, last);
+				} else {
+					/* 2 source words */
+ 					d1 = *src;
+					*dst = comp(d0 << left | d1 >> right,
+						    *dst, last);
+				}
+			}
+		}
+	}
+}
+
+    /*
+     *  Generic bitwise copy algorithm, operating backward
+     */
+
+static void
+bitcpy_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
+		const unsigned long *src, int src_idx, int bits, unsigned n)
+{
+	unsigned long first, last;
+	int shift;
+
+	dst += (n-1)/bits;
+	src += (n-1)/bits;
+	if ((n-1) % bits) {
+		dst_idx += (n-1) % bits;
+		dst += dst_idx >> (ffs(bits) - 1);
+		dst_idx &= bits - 1;
+		src_idx += (n-1) % bits;
+		src += src_idx >> (ffs(bits) - 1);
+		src_idx &= bits - 1;
+	}
+
+	shift = dst_idx-src_idx;
+
+	first = FB_SHIFT_LOW(p, ~0UL, bits - 1 - dst_idx);
+	last = ~(FB_SHIFT_LOW(p, ~0UL, bits - 1 - ((dst_idx-n) % bits)));
+
+	if (!shift) {
+		/* Same alignment for source and dest */
+		if ((unsigned long)dst_idx+1 >= n) {
+			/* Single word */
+			if (last)
+				first &= last;
+			*dst = comp(*src, *dst, first);
+		} else {
+			/* Multiple destination words */
+
+			/* Leading bits */
+			if (first != ~0UL) {
+				*dst = comp(*src, *dst, first);
+				dst--;
+				src--;
+				n -= dst_idx+1;
+			}
+
+			/* Main chunk */
+			n /= bits;
+			while (n >= 8) {
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				*dst-- = *src--;
+				n -= 8;
+			}
+			while (n--)
+				*dst-- = *src--;
+			/* Trailing bits */
+			if (last)
+				*dst = comp(*src, *dst, last);
+		}
+	} else {
+		/* Different alignment for source and dest */
+
+		int const left = -shift & (bits-1);
+		int const right = shift & (bits-1);
+
+		if ((unsigned long)dst_idx+1 >= n) {
+			/* Single destination word */
+			if (last)
+				first &= last;
+			if (shift < 0) {
+				/* Single source word */
+				*dst = comp(*src << left, *dst, first);
+			} else if (1+(unsigned long)src_idx >= n) {
+				/* Single source word */
+				*dst = comp(*src >> right, *dst, first);
+			} else {
+				/* 2 source words */
+				*dst = comp(*src >> right | *(src-1) << left,
+					    *dst, first);
+			}
+		} else {
+			/* Multiple destination words */
+			/** We must always remember the last value read,
+			    because in case SRC and DST overlap bitwise (e.g.
+			    when moving just one pixel in 1bpp), we always
+			    collect one full long for DST and that might
+			    overlap with the current long from SRC. We store
+			    this value in 'd0'. */
+			unsigned long d0, d1;
+			int m;
+
+			d0 = *src--;
+			/* Leading bits */
+			if (shift < 0) {
+				/* Single source word */
+				*dst = comp(d0 << left, *dst, first);
+			} else {
+				/* 2 source words */
+				d1 = *src--;
+				*dst = comp(d0 >> right | d1 << left, *dst,
+					    first);
+				d0 = d1;
+			}
+			dst--;
+			n -= dst_idx+1;
+
+			/* Main chunk */
+			m = n % bits;
+			n /= bits;
+			while (n >= 4) {
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+				n -= 4;
+			}
+			while (n--) {
+				d1 = *src--;
+				*dst-- = d0 >> right | d1 << left;
+				d0 = d1;
+			}
+
+			/* Trailing bits */
+			if (last) {
+				if (m <= left) {
+					/* Single source word */
+					*dst = comp(d0 >> right, *dst, last);
+				} else {
+					/* 2 source words */
+					d1 = *src;
+					*dst = comp(d0 >> right | d1 << left,
+						    *dst, last);
+				}
+			}
+		}
+	}
+}
+
+void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
+	u32 height = area->height, width = area->width;
+	unsigned long const bits_per_line = p->fix.line_length*8u;
+	unsigned long *dst = NULL, *src = NULL;
+	int bits = BITS_PER_LONG, bytes = bits >> 3;
+	int dst_idx = 0, src_idx = 0, rev_copy = 0;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	/* if the beginning of the target area might overlap with the end of
+	the source area, be have to copy the area reverse. */
+	if ((dy == sy && dx > sx) || (dy > sy)) {
+		dy += height;
+		sy += height;
+		rev_copy = 1;
+	}
+
+	/* split the base of the framebuffer into a long-aligned address and
+	   the index of the first bit */
+	dst = src = (unsigned long *)((unsigned long)p->screen_base &
+				      ~(bytes-1));
+	dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
+	/* add offset of source and target area */
+	dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
+	src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	if (rev_copy) {
+		while (height--) {
+			dst_idx -= bits_per_line;
+			src_idx -= bits_per_line;
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bytes - 1);
+			src += src_idx >> (ffs(bits) - 1);
+			src_idx &= (bytes - 1);
+			bitcpy_rev(p, dst, dst_idx, src, src_idx, bits,
+				width*p->var.bits_per_pixel);
+		}
+	} else {
+		while (height--) {
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bytes - 1);
+			src += src_idx >> (ffs(bits) - 1);
+			src_idx &= (bytes - 1);
+			bitcpy(p, dst, dst_idx, src, src_idx, bits,
+				width*p->var.bits_per_pixel);
+			dst_idx += bits_per_line;
+			src_idx += bits_per_line;
+		}
+	}
+}
+
+EXPORT_SYMBOL(sys_copyarea);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("Generic copyarea (sys-to-sys)");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/core/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c
new file mode 100644
index 000000000000..33ee3d34f9d2
--- /dev/null
+++ b/drivers/video/fbdev/core/sysfillrect.c
@@ -0,0 +1,335 @@
+/*
+ *  Generic fillrect for frame buffers in system RAM with packed pixels of
+ *  any depth.
+ *
+ *  Based almost entirely from cfbfillrect.c (which is based almost entirely
+ *  on Geert Uytterhoeven's fillrect routine)
+ *
+ *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+#include "fb_draw.h"
+
+    /*
+     *  Aligned pattern fill using 32/64-bit memory accesses
+     */
+
+static void
+bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx,
+		unsigned long pat, unsigned n, int bits)
+{
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
+	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
+		/* Single word */
+		if (last)
+			first &= last;
+		*dst = comp(pat, *dst, first);
+	} else {
+		/* Multiple destination words */
+
+		/* Leading bits */
+ 		if (first!= ~0UL) {
+			*dst = comp(pat, *dst, first);
+			dst++;
+			n -= bits - dst_idx;
+		}
+
+		/* Main chunk */
+		n /= bits;
+		while (n >= 8) {
+			*dst++ = pat;
+			*dst++ = pat;
+			*dst++ = pat;
+			*dst++ = pat;
+			*dst++ = pat;
+			*dst++ = pat;
+			*dst++ = pat;
+			*dst++ = pat;
+			n -= 8;
+		}
+		while (n--)
+			*dst++ = pat;
+		/* Trailing bits */
+		if (last)
+			*dst = comp(pat, *dst, last);
+	}
+}
+
+
+    /*
+     *  Unaligned generic pattern fill using 32/64-bit memory accesses
+     *  The pattern must have been expanded to a full 32/64-bit value
+     *  Left/right are the appropriate shifts to convert to the pattern to be
+     *  used for the next 32/64-bit word
+     */
+
+static void
+bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx,
+		  unsigned long pat, int left, int right, unsigned n, int bits)
+{
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
+	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
+		/* Single word */
+		if (last)
+			first &= last;
+		*dst = comp(pat, *dst, first);
+	} else {
+		/* Multiple destination words */
+		/* Leading bits */
+		if (first) {
+			*dst = comp(pat, *dst, first);
+			dst++;
+			pat = pat << left | pat >> right;
+			n -= bits - dst_idx;
+		}
+
+		/* Main chunk */
+		n /= bits;
+		while (n >= 4) {
+			*dst++ = pat;
+			pat = pat << left | pat >> right;
+			*dst++ = pat;
+			pat = pat << left | pat >> right;
+			*dst++ = pat;
+			pat = pat << left | pat >> right;
+			*dst++ = pat;
+			pat = pat << left | pat >> right;
+			n -= 4;
+		}
+		while (n--) {
+			*dst++ = pat;
+			pat = pat << left | pat >> right;
+		}
+
+		/* Trailing bits */
+		if (last)
+			*dst = comp(pat, *dst, last);
+	}
+}
+
+    /*
+     *  Aligned pattern invert using 32/64-bit memory accesses
+     */
+static void
+bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
+		    unsigned long pat, unsigned n, int bits)
+{
+	unsigned long val = pat;
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
+	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
+		/* Single word */
+		if (last)
+			first &= last;
+		*dst = comp(*dst ^ val, *dst, first);
+	} else {
+		/* Multiple destination words */
+		/* Leading bits */
+		if (first!=0UL) {
+			*dst = comp(*dst ^ val, *dst, first);
+			dst++;
+			n -= bits - dst_idx;
+		}
+
+		/* Main chunk */
+		n /= bits;
+		while (n >= 8) {
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			*dst++ ^= val;
+			n -= 8;
+		}
+		while (n--)
+			*dst++ ^= val;
+		/* Trailing bits */
+		if (last)
+			*dst = comp(*dst ^ val, *dst, last);
+	}
+}
+
+
+    /*
+     *  Unaligned generic pattern invert using 32/64-bit memory accesses
+     *  The pattern must have been expanded to a full 32/64-bit value
+     *  Left/right are the appropriate shifts to convert to the pattern to be
+     *  used for the next 32/64-bit word
+     */
+
+static void
+bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
+		      unsigned long pat, int left, int right, unsigned n,
+		      int bits)
+{
+	unsigned long first, last;
+
+	if (!n)
+		return;
+
+	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
+	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
+		/* Single word */
+		if (last)
+			first &= last;
+		*dst = comp(*dst ^ pat, *dst, first);
+	} else {
+		/* Multiple destination words */
+
+		/* Leading bits */
+		if (first != 0UL) {
+			*dst = comp(*dst ^ pat, *dst, first);
+			dst++;
+			pat = pat << left | pat >> right;
+			n -= bits - dst_idx;
+		}
+
+		/* Main chunk */
+		n /= bits;
+		while (n >= 4) {
+			*dst++ ^= pat;
+			pat = pat << left | pat >> right;
+			*dst++ ^= pat;
+			pat = pat << left | pat >> right;
+			*dst++ ^= pat;
+			pat = pat << left | pat >> right;
+			*dst++ ^= pat;
+			pat = pat << left | pat >> right;
+			n -= 4;
+		}
+		while (n--) {
+			*dst ^= pat;
+			pat = pat << left | pat >> right;
+		}
+
+		/* Trailing bits */
+		if (last)
+			*dst = comp(*dst ^ pat, *dst, last);
+	}
+}
+
+void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	unsigned long pat, pat2, fg;
+	unsigned long width = rect->width, height = rect->height;
+	int bits = BITS_PER_LONG, bytes = bits >> 3;
+	u32 bpp = p->var.bits_per_pixel;
+	unsigned long *dst;
+	int dst_idx, left;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
+		fg = ((u32 *) (p->pseudo_palette))[rect->color];
+	else
+		fg = rect->color;
+
+	pat = pixel_to_pat( bpp, fg);
+
+	dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
+	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
+	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
+	/* FIXME For now we support 1-32 bpp only */
+	left = bits % bpp;
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+	if (!left) {
+		void (*fill_op32)(struct fb_info *p, unsigned long *dst,
+				  int dst_idx, unsigned long pat, unsigned n,
+				  int bits) = NULL;
+
+		switch (rect->rop) {
+		case ROP_XOR:
+			fill_op32 = bitfill_aligned_rev;
+			break;
+		case ROP_COPY:
+			fill_op32 = bitfill_aligned;
+			break;
+		default:
+			printk( KERN_ERR "cfb_fillrect(): unknown rop, "
+				"defaulting to ROP_COPY\n");
+			fill_op32 = bitfill_aligned;
+			break;
+		}
+		while (height--) {
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bits - 1);
+			fill_op32(p, dst, dst_idx, pat, width*bpp, bits);
+			dst_idx += p->fix.line_length*8;
+		}
+	} else {
+		int right, r;
+		void (*fill_op)(struct fb_info *p, unsigned long *dst,
+				int dst_idx, unsigned long pat, int left,
+				int right, unsigned n, int bits) = NULL;
+#ifdef __LITTLE_ENDIAN
+		right = left;
+		left = bpp - right;
+#else
+		right = bpp - left;
+#endif
+		switch (rect->rop) {
+		case ROP_XOR:
+			fill_op = bitfill_unaligned_rev;
+			break;
+		case ROP_COPY:
+			fill_op = bitfill_unaligned;
+			break;
+		default:
+			printk(KERN_ERR "sys_fillrect(): unknown rop, "
+				"defaulting to ROP_COPY\n");
+			fill_op = bitfill_unaligned;
+			break;
+		}
+		while (height--) {
+			dst += dst_idx / bits;
+			dst_idx &= (bits - 1);
+			r = dst_idx % bpp;
+			/* rotate pattern to the correct start position */
+			pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
+			fill_op(p, dst, dst_idx, pat2, left, right,
+				width*bpp, bits);
+			dst_idx += p->fix.line_length*8;
+		}
+	}
+}
+
+EXPORT_SYMBOL(sys_fillrect);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c
new file mode 100644
index 000000000000..a4d05b1b17d7
--- /dev/null
+++ b/drivers/video/fbdev/core/sysimgblt.c
@@ -0,0 +1,288 @@
+/*
+ *  Generic 1-bit or 8-bit source to 1-32 bit destination expansion
+ *  for frame buffer located in system RAM with packed pixels of any depth.
+ *
+ *  Based almost entirely on cfbimgblt.c
+ *
+ *      Copyright (C)  April 2007 Antonino Daplas <adaplas@pol.net>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/types.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static const u32 cfb_tab8_be[] = {
+    0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
+    0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
+    0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
+    0xffff0000,0xffff00ff,0xffffff00,0xffffffff
+};
+
+static const u32 cfb_tab8_le[] = {
+    0x00000000,0xff000000,0x00ff0000,0xffff0000,
+    0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
+    0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
+    0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
+};
+
+static const u32 cfb_tab16_be[] = {
+    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
+};
+
+static const u32 cfb_tab16_le[] = {
+    0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+};
+
+static const u32 cfb_tab32[] = {
+	0x00000000, 0xffffffff
+};
+
+static void color_imageblit(const struct fb_image *image, struct fb_info *p,
+			    void *dst1, u32 start_index, u32 pitch_index)
+{
+	/* Draw the penguin */
+	u32 *dst, *dst2;
+	u32 color = 0, val, shift;
+	int i, n, bpp = p->var.bits_per_pixel;
+	u32 null_bits = 32 - bpp;
+	u32 *palette = (u32 *) p->pseudo_palette;
+	const u8 *src = image->data;
+
+	dst2 = dst1;
+	for (i = image->height; i--; ) {
+		n = image->width;
+		dst = dst1;
+		shift = 0;
+		val = 0;
+
+		if (start_index) {
+			u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
+							 start_index));
+			val = *dst & start_mask;
+			shift = start_index;
+		}
+		while (n--) {
+			if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+			    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
+				color = palette[*src];
+			else
+				color = *src;
+			color <<= FB_LEFT_POS(p, bpp);
+			val |= FB_SHIFT_HIGH(p, color, shift);
+			if (shift >= null_bits) {
+				*dst++ = val;
+
+				val = (shift == null_bits) ? 0 :
+					FB_SHIFT_LOW(p, color, 32 - shift);
+			}
+			shift += bpp;
+			shift &= (32 - 1);
+			src++;
+		}
+		if (shift) {
+			u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
+
+			*dst &= end_mask;
+			*dst |= val;
+		}
+		dst1 += p->fix.line_length;
+		if (pitch_index) {
+			dst2 += p->fix.line_length;
+			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+
+			start_index += pitch_index;
+			start_index &= 32 - 1;
+		}
+	}
+}
+
+static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+				  void *dst1, u32 fgcolor, u32 bgcolor,
+				  u32 start_index, u32 pitch_index)
+{
+	u32 shift, color = 0, bpp = p->var.bits_per_pixel;
+	u32 *dst, *dst2;
+	u32 val, pitch = p->fix.line_length;
+	u32 null_bits = 32 - bpp;
+	u32 spitch = (image->width+7)/8;
+	const u8 *src = image->data, *s;
+	u32 i, j, l;
+
+	dst2 = dst1;
+	fgcolor <<= FB_LEFT_POS(p, bpp);
+	bgcolor <<= FB_LEFT_POS(p, bpp);
+
+	for (i = image->height; i--; ) {
+		shift = val = 0;
+		l = 8;
+		j = image->width;
+		dst = dst1;
+		s = src;
+
+		/* write leading bits */
+		if (start_index) {
+			u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
+							 start_index));
+			val = *dst & start_mask;
+			shift = start_index;
+		}
+
+		while (j--) {
+			l--;
+			color = (*s & (1 << l)) ? fgcolor : bgcolor;
+			val |= FB_SHIFT_HIGH(p, color, shift);
+
+			/* Did the bitshift spill bits to the next long? */
+			if (shift >= null_bits) {
+				*dst++ = val;
+				val = (shift == null_bits) ? 0 :
+					FB_SHIFT_LOW(p, color, 32 - shift);
+			}
+			shift += bpp;
+			shift &= (32 - 1);
+			if (!l) { l = 8; s++; }
+		}
+
+		/* write trailing bits */
+ 		if (shift) {
+			u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
+
+			*dst &= end_mask;
+			*dst |= val;
+		}
+
+		dst1 += pitch;
+		src += spitch;
+		if (pitch_index) {
+			dst2 += pitch;
+			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+			start_index += pitch_index;
+			start_index &= 32 - 1;
+		}
+
+	}
+}
+
+/*
+ * fast_imageblit - optimized monochrome color expansion
+ *
+ * Only if:  bits_per_pixel == 8, 16, or 32
+ *           image->width is divisible by pixel/dword (ppw);
+ *           fix->line_legth is divisible by 4;
+ *           beginning and end of a scanline is dword aligned
+ */
+static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
+				  void *dst1, u32 fgcolor, u32 bgcolor)
+{
+	u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
+	u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
+	u32 bit_mask, end_mask, eorx, shift;
+	const char *s = image->data, *src;
+	u32 *dst;
+	const u32 *tab = NULL;
+	int i, j, k;
+
+	switch (bpp) {
+	case 8:
+		tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
+		break;
+	case 16:
+		tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
+		break;
+	case 32:
+	default:
+		tab = cfb_tab32;
+		break;
+	}
+
+	for (i = ppw-1; i--; ) {
+		fgx <<= bpp;
+		bgx <<= bpp;
+		fgx |= fgcolor;
+		bgx |= bgcolor;
+	}
+
+	bit_mask = (1 << ppw) - 1;
+	eorx = fgx ^ bgx;
+	k = image->width/ppw;
+
+	for (i = image->height; i--; ) {
+		dst = dst1;
+		shift = 8;
+		src = s;
+
+		for (j = k; j--; ) {
+			shift -= ppw;
+			end_mask = tab[(*src >> shift) & bit_mask];
+			*dst++ = (end_mask & eorx) ^ bgx;
+			if (!shift) {
+				shift = 8;
+				src++;
+			}
+		}
+		dst1 += p->fix.line_length;
+		s += spitch;
+	}
+}
+
+void sys_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+	u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
+	u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
+	u32 width = image->width;
+	u32 dx = image->dx, dy = image->dy;
+	void *dst1;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
+	start_index = bitstart & (32 - 1);
+	pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+
+	bitstart /= 8;
+	bitstart &= ~(bpl - 1);
+	dst1 = (void __force *)p->screen_base + bitstart;
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	if (image->depth == 1) {
+		if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+		    p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+			fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
+			bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
+		} else {
+			fgcolor = image->fg_color;
+			bgcolor = image->bg_color;
+		}
+
+		if (32 % bpp == 0 && !start_index && !pitch_index &&
+		    ((width & (32/bpp-1)) == 0) &&
+		    bpp >= 8 && bpp <= 32)
+			fast_imageblit(image, p, dst1, fgcolor, bgcolor);
+		else
+			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
+					start_index, pitch_index);
+	} else
+		color_imageblit(image, p, dst1, start_index, pitch_index);
+}
+
+EXPORT_SYMBOL(sys_imageblit);
+
+MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
+MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/cyber2000fb.c b/drivers/video/fbdev/cyber2000fb.c
new file mode 100644
index 000000000000..b0a950f36970
--- /dev/null
+++ b/drivers/video/fbdev/cyber2000fb.c
@@ -0,0 +1,1901 @@
+/*
+ *  linux/drivers/video/cyber2000fb.c
+ *
+ *  Copyright (C) 1998-2002 Russell King
+ *
+ *  MIPS and 50xx clock support
+ *  Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
+ *
+ *  32 bit support, text color and panning fixes for modes != 8 bit
+ *  Copyright (C) 2002 Denis Oliver Kropp <dok@directfb.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
+ *
+ * Based on cyberfb.c.
+ *
+ * Note that we now use the new fbcon fix, var and cmap scheme.  We do
+ * still have to check which console is the currently displayed one
+ * however, especially for the colourmap stuff.
+ *
+ * We also use the new hotplug PCI subsystem.  I'm not sure if there
+ * are any such cards, but I'm erring on the side of caution.  We don't
+ * want to go pop just because someone does have one.
+ *
+ * Note that this doesn't work fully in the case of multiple CyberPro
+ * cards with grabbers.  We currently can only attach to the first
+ * CyberPro card found.
+ *
+ * When we're in truecolour mode, we power down the LUT RAM as a power
+ * saving feature.  Also, when we enter any of the powersaving modes
+ * (except soft blanking) we power down the RAMDACs.  This saves about
+ * 1W, which is roughly 8% of the power consumption of a NetWinder
+ * (which, incidentally, is about the same saving as a 2.5in hard disk
+ * entering standby mode.)
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/pgtable.h>
+
+#ifdef __arm__
+#include <asm/mach-types.h>
+#endif
+
+#include "cyber2000fb.h"
+
+struct cfb_info {
+	struct fb_info		fb;
+	struct display_switch	*dispsw;
+	struct display		*display;
+	unsigned char		__iomem *region;
+	unsigned char		__iomem *regs;
+	u_int			id;
+	u_int			irq;
+	int			func_use_count;
+	u_long			ref_ps;
+
+	/*
+	 * Clock divisors
+	 */
+	u_int			divisors[4];
+
+	struct {
+		u8 red, green, blue;
+	} palette[NR_PALETTE];
+
+	u_char			mem_ctl1;
+	u_char			mem_ctl2;
+	u_char			mclk_mult;
+	u_char			mclk_div;
+	/*
+	 * RAMDAC control register is both of these or'ed together
+	 */
+	u_char			ramdac_ctrl;
+	u_char			ramdac_powerdown;
+
+	u32			pseudo_palette[16];
+
+	spinlock_t		reg_b0_lock;
+
+#ifdef CONFIG_FB_CYBER2000_DDC
+	bool			ddc_registered;
+	struct i2c_adapter	ddc_adapter;
+	struct i2c_algo_bit_data	ddc_algo;
+#endif
+
+#ifdef CONFIG_FB_CYBER2000_I2C
+	struct i2c_adapter	i2c_adapter;
+	struct i2c_algo_bit_data i2c_algo;
+#endif
+};
+
+static char *default_font = "Acorn8x8";
+module_param(default_font, charp, 0);
+MODULE_PARM_DESC(default_font, "Default font name");
+
+/*
+ * Our access methods.
+ */
+#define cyber2000fb_writel(val, reg, cfb)	writel(val, (cfb)->regs + (reg))
+#define cyber2000fb_writew(val, reg, cfb)	writew(val, (cfb)->regs + (reg))
+#define cyber2000fb_writeb(val, reg, cfb)	writeb(val, (cfb)->regs + (reg))
+
+#define cyber2000fb_readb(reg, cfb)		readb((cfb)->regs + (reg))
+
+static inline void
+cyber2000_crtcw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+	cyber2000fb_writew((reg & 255) | val << 8, 0x3d4, cfb);
+}
+
+static inline void
+cyber2000_grphw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+	cyber2000fb_writew((reg & 255) | val << 8, 0x3ce, cfb);
+}
+
+static inline unsigned int
+cyber2000_grphr(unsigned int reg, struct cfb_info *cfb)
+{
+	cyber2000fb_writeb(reg, 0x3ce, cfb);
+	return cyber2000fb_readb(0x3cf, cfb);
+}
+
+static inline void
+cyber2000_attrw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+	cyber2000fb_readb(0x3da, cfb);
+	cyber2000fb_writeb(reg, 0x3c0, cfb);
+	cyber2000fb_readb(0x3c1, cfb);
+	cyber2000fb_writeb(val, 0x3c0, cfb);
+}
+
+static inline void
+cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+	cyber2000fb_writew((reg & 255) | val << 8, 0x3c4, cfb);
+}
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Cyber2000 Acceleration
+ */
+static void
+cyber2000fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+	unsigned long dst, col;
+
+	if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
+	cyber2000fb_writew(rect->width - 1, CO_REG_PIXWIDTH, cfb);
+	cyber2000fb_writew(rect->height - 1, CO_REG_PIXHEIGHT, cfb);
+
+	col = rect->color;
+	if (cfb->fb.var.bits_per_pixel > 8)
+		col = ((u32 *)cfb->fb.pseudo_palette)[col];
+	cyber2000fb_writel(col, CO_REG_FGCOLOUR, cfb);
+
+	dst = rect->dx + rect->dy * cfb->fb.var.xres_virtual;
+	if (cfb->fb.var.bits_per_pixel == 24) {
+		cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
+		dst *= 3;
+	}
+
+	cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
+	cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
+	cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
+	cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
+}
+
+static void
+cyber2000fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+	unsigned int cmd = CO_CMD_L_PATTERN_FGCOL;
+	unsigned long src, dst;
+
+	if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
+	cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
+	cyber2000fb_writew(region->width - 1, CO_REG_PIXWIDTH, cfb);
+	cyber2000fb_writew(region->height - 1, CO_REG_PIXHEIGHT, cfb);
+
+	src = region->sx + region->sy * cfb->fb.var.xres_virtual;
+	dst = region->dx + region->dy * cfb->fb.var.xres_virtual;
+
+	if (region->sx < region->dx) {
+		src += region->width - 1;
+		dst += region->width - 1;
+		cmd |= CO_CMD_L_INC_LEFT;
+	}
+
+	if (region->sy < region->dy) {
+		src += (region->height - 1) * cfb->fb.var.xres_virtual;
+		dst += (region->height - 1) * cfb->fb.var.xres_virtual;
+		cmd |= CO_CMD_L_INC_UP;
+	}
+
+	if (cfb->fb.var.bits_per_pixel == 24) {
+		cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
+		src *= 3;
+		dst *= 3;
+	}
+	cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
+	cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
+	cyber2000fb_writew(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
+	cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
+	cyber2000fb_writew(CO_CMD_H_FGSRCMAP | CO_CMD_H_BLITTER,
+			   CO_REG_CMD_H, cfb);
+}
+
+static void
+cyber2000fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	cfb_imageblit(info, image);
+	return;
+}
+
+static int cyber2000fb_sync(struct fb_info *info)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+	int count = 100000;
+
+	if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT))
+		return 0;
+
+	while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
+		if (!count--) {
+			debug_printf("accel_wait timed out\n");
+			cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
+			break;
+		}
+		udelay(1);
+	}
+	return 0;
+}
+
+/*
+ * ===========================================================================
+ */
+
+static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
+{
+	u_int mask = (1 << bf->length) - 1;
+
+	return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
+/*
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
+static int
+cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		      u_int transp, struct fb_info *info)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+	struct fb_var_screeninfo *var = &cfb->fb.var;
+	u32 pseudo_val;
+	int ret = 1;
+
+	switch (cfb->fb.fix.visual) {
+	default:
+		return 1;
+
+	/*
+	 * Pseudocolour:
+	 *	   8     8
+	 * pixel --/--+--/-->  red lut  --> red dac
+	 *	      |  8
+	 *	      +--/--> green lut --> green dac
+	 *	      |  8
+	 *	      +--/-->  blue lut --> blue dac
+	 */
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno >= NR_PALETTE)
+			return 1;
+
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+
+		cfb->palette[regno].red = red;
+		cfb->palette[regno].green = green;
+		cfb->palette[regno].blue = blue;
+
+		cyber2000fb_writeb(regno, 0x3c8, cfb);
+		cyber2000fb_writeb(red, 0x3c9, cfb);
+		cyber2000fb_writeb(green, 0x3c9, cfb);
+		cyber2000fb_writeb(blue, 0x3c9, cfb);
+		return 0;
+
+	/*
+	 * Direct colour:
+	 *	   n     rl
+	 * pixel --/--+--/-->  red lut  --> red dac
+	 *	      |  gl
+	 *	      +--/--> green lut --> green dac
+	 *	      |  bl
+	 *	      +--/-->  blue lut --> blue dac
+	 * n = bpp, rl = red length, gl = green length, bl = blue length
+	 */
+	case FB_VISUAL_DIRECTCOLOR:
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+
+		if (var->green.length == 6 && regno < 64) {
+			cfb->palette[regno << 2].green = green;
+
+			/*
+			 * The 6 bits of the green component are applied
+			 * to the high 6 bits of the LUT.
+			 */
+			cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
+			cyber2000fb_writeb(cfb->palette[regno >> 1].red,
+					   0x3c9, cfb);
+			cyber2000fb_writeb(green, 0x3c9, cfb);
+			cyber2000fb_writeb(cfb->palette[regno >> 1].blue,
+					   0x3c9, cfb);
+
+			green = cfb->palette[regno << 3].green;
+
+			ret = 0;
+		}
+
+		if (var->green.length >= 5 && regno < 32) {
+			cfb->palette[regno << 3].red = red;
+			cfb->palette[regno << 3].green = green;
+			cfb->palette[regno << 3].blue = blue;
+
+			/*
+			 * The 5 bits of each colour component are
+			 * applied to the high 5 bits of the LUT.
+			 */
+			cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
+			cyber2000fb_writeb(red, 0x3c9, cfb);
+			cyber2000fb_writeb(green, 0x3c9, cfb);
+			cyber2000fb_writeb(blue, 0x3c9, cfb);
+			ret = 0;
+		}
+
+		if (var->green.length == 4 && regno < 16) {
+			cfb->palette[regno << 4].red = red;
+			cfb->palette[regno << 4].green = green;
+			cfb->palette[regno << 4].blue = blue;
+
+			/*
+			 * The 5 bits of each colour component are
+			 * applied to the high 5 bits of the LUT.
+			 */
+			cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
+			cyber2000fb_writeb(red, 0x3c9, cfb);
+			cyber2000fb_writeb(green, 0x3c9, cfb);
+			cyber2000fb_writeb(blue, 0x3c9, cfb);
+			ret = 0;
+		}
+
+		/*
+		 * Since this is only used for the first 16 colours, we
+		 * don't have to care about overflowing for regno >= 32
+		 */
+		pseudo_val = regno << var->red.offset |
+			     regno << var->green.offset |
+			     regno << var->blue.offset;
+		break;
+
+	/*
+	 * True colour:
+	 *	   n     rl
+	 * pixel --/--+--/--> red dac
+	 *	      |  gl
+	 *	      +--/--> green dac
+	 *	      |  bl
+	 *	      +--/--> blue dac
+	 * n = bpp, rl = red length, gl = green length, bl = blue length
+	 */
+	case FB_VISUAL_TRUECOLOR:
+		pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
+		pseudo_val |= convert_bitfield(red, &var->red);
+		pseudo_val |= convert_bitfield(green, &var->green);
+		pseudo_val |= convert_bitfield(blue, &var->blue);
+		ret = 0;
+		break;
+	}
+
+	/*
+	 * Now set our pseudo palette for the CFB16/24/32 drivers.
+	 */
+	if (regno < 16)
+		((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
+
+	return ret;
+}
+
+struct par_info {
+	/*
+	 * Hardware
+	 */
+	u_char	clock_mult;
+	u_char	clock_div;
+	u_char	extseqmisc;
+	u_char	co_pixfmt;
+	u_char	crtc_ofl;
+	u_char	crtc[19];
+	u_int	width;
+	u_int	pitch;
+	u_int	fetch;
+
+	/*
+	 * Other
+	 */
+	u_char	ramdac;
+};
+
+static const u_char crtc_idx[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
+};
+
+static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
+{
+	unsigned int i;
+	unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
+
+	cyber2000fb_writeb(0x56, 0x3ce, cfb);
+	i = cyber2000fb_readb(0x3cf, cfb);
+	cyber2000fb_writeb(i | 4, 0x3cf, cfb);
+	cyber2000fb_writeb(val, 0x3c6, cfb);
+	cyber2000fb_writeb(i, 0x3cf, cfb);
+	/* prevent card lock-up observed on x86 with CyberPro 2000 */
+	cyber2000fb_readb(0x3cf, cfb);
+}
+
+static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
+{
+	u_int i;
+
+	/*
+	 * Blank palette
+	 */
+	for (i = 0; i < NR_PALETTE; i++) {
+		cyber2000fb_writeb(i, 0x3c8, cfb);
+		cyber2000fb_writeb(0, 0x3c9, cfb);
+		cyber2000fb_writeb(0, 0x3c9, cfb);
+		cyber2000fb_writeb(0, 0x3c9, cfb);
+	}
+
+	cyber2000fb_writeb(0xef, 0x3c2, cfb);
+	cyber2000_crtcw(0x11, 0x0b, cfb);
+	cyber2000_attrw(0x11, 0x00, cfb);
+
+	cyber2000_seqw(0x00, 0x01, cfb);
+	cyber2000_seqw(0x01, 0x01, cfb);
+	cyber2000_seqw(0x02, 0x0f, cfb);
+	cyber2000_seqw(0x03, 0x00, cfb);
+	cyber2000_seqw(0x04, 0x0e, cfb);
+	cyber2000_seqw(0x00, 0x03, cfb);
+
+	for (i = 0; i < sizeof(crtc_idx); i++)
+		cyber2000_crtcw(crtc_idx[i], hw->crtc[i], cfb);
+
+	for (i = 0x0a; i < 0x10; i++)
+		cyber2000_crtcw(i, 0, cfb);
+
+	cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
+	cyber2000_grphw(0x00, 0x00, cfb);
+	cyber2000_grphw(0x01, 0x00, cfb);
+	cyber2000_grphw(0x02, 0x00, cfb);
+	cyber2000_grphw(0x03, 0x00, cfb);
+	cyber2000_grphw(0x04, 0x00, cfb);
+	cyber2000_grphw(0x05, 0x60, cfb);
+	cyber2000_grphw(0x06, 0x05, cfb);
+	cyber2000_grphw(0x07, 0x0f, cfb);
+	cyber2000_grphw(0x08, 0xff, cfb);
+
+	/* Attribute controller registers */
+	for (i = 0; i < 16; i++)
+		cyber2000_attrw(i, i, cfb);
+
+	cyber2000_attrw(0x10, 0x01, cfb);
+	cyber2000_attrw(0x11, 0x00, cfb);
+	cyber2000_attrw(0x12, 0x0f, cfb);
+	cyber2000_attrw(0x13, 0x00, cfb);
+	cyber2000_attrw(0x14, 0x00, cfb);
+
+	/* PLL registers */
+	spin_lock(&cfb->reg_b0_lock);
+	cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
+	cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
+	cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
+	cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
+	cyber2000_grphw(0x90, 0x01, cfb);
+	cyber2000_grphw(0xb9, 0x80, cfb);
+	cyber2000_grphw(0xb9, 0x00, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
+
+	cfb->ramdac_ctrl = hw->ramdac;
+	cyber2000fb_write_ramdac_ctrl(cfb);
+
+	cyber2000fb_writeb(0x20, 0x3c0, cfb);
+	cyber2000fb_writeb(0xff, 0x3c6, cfb);
+
+	cyber2000_grphw(0x14, hw->fetch, cfb);
+	cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
+			      ((hw->pitch >> 4) & 0x30), cfb);
+	cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
+
+	/*
+	 * Set up accelerator registers
+	 */
+	cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
+	cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
+	cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
+}
+
+static inline int
+cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
+{
+	u_int base = var->yoffset * var->xres_virtual + var->xoffset;
+
+	base *= var->bits_per_pixel;
+
+	/*
+	 * Convert to bytes and shift two extra bits because DAC
+	 * can only start on 4 byte aligned data.
+	 */
+	base >>= 5;
+
+	if (base >= 1 << 20)
+		return -EINVAL;
+
+	cyber2000_grphw(0x10, base >> 16 | 0x10, cfb);
+	cyber2000_crtcw(0x0c, base >> 8, cfb);
+	cyber2000_crtcw(0x0d, base, cfb);
+
+	return 0;
+}
+
+static int
+cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
+			struct fb_var_screeninfo *var)
+{
+	u_int Htotal, Hblankend, Hsyncend;
+	u_int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
+#define ENCODE_BIT(v, b1, m, b2) ((((v) >> (b1)) & (m)) << (b2))
+
+	hw->crtc[13] = hw->pitch;
+	hw->crtc[17] = 0xe3;
+	hw->crtc[14] = 0;
+	hw->crtc[8]  = 0;
+
+	Htotal     = var->xres + var->right_margin +
+		     var->hsync_len + var->left_margin;
+
+	if (Htotal > 2080)
+		return -EINVAL;
+
+	hw->crtc[0] = (Htotal >> 3) - 5;
+	hw->crtc[1] = (var->xres >> 3) - 1;
+	hw->crtc[2] = var->xres >> 3;
+	hw->crtc[4] = (var->xres + var->right_margin) >> 3;
+
+	Hblankend   = (Htotal - 4 * 8) >> 3;
+
+	hw->crtc[3] = ENCODE_BIT(Hblankend,  0, 0x1f,  0) |
+		      ENCODE_BIT(1,          0, 0x01,  7);
+
+	Hsyncend    = (var->xres + var->right_margin + var->hsync_len) >> 3;
+
+	hw->crtc[5] = ENCODE_BIT(Hsyncend,   0, 0x1f,  0) |
+		      ENCODE_BIT(Hblankend,  5, 0x01,  7);
+
+	Vdispend    = var->yres - 1;
+	Vsyncstart  = var->yres + var->lower_margin;
+	Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
+	Vtotal      = var->yres + var->lower_margin + var->vsync_len +
+		      var->upper_margin - 2;
+
+	if (Vtotal > 2047)
+		return -EINVAL;
+
+	Vblankstart = var->yres + 6;
+	Vblankend   = Vtotal - 10;
+
+	hw->crtc[6]  = Vtotal;
+	hw->crtc[7]  = ENCODE_BIT(Vtotal,     8, 0x01,  0) |
+			ENCODE_BIT(Vdispend,   8, 0x01,  1) |
+			ENCODE_BIT(Vsyncstart, 8, 0x01,  2) |
+			ENCODE_BIT(Vblankstart, 8, 0x01,  3) |
+			ENCODE_BIT(1,          0, 0x01,  4) |
+			ENCODE_BIT(Vtotal,     9, 0x01,  5) |
+			ENCODE_BIT(Vdispend,   9, 0x01,  6) |
+			ENCODE_BIT(Vsyncstart, 9, 0x01,  7);
+	hw->crtc[9]  = ENCODE_BIT(0,          0, 0x1f,  0) |
+			ENCODE_BIT(Vblankstart, 9, 0x01,  5) |
+			ENCODE_BIT(1,          0, 0x01,  6);
+	hw->crtc[10] = Vsyncstart;
+	hw->crtc[11] = ENCODE_BIT(Vsyncend,   0, 0x0f,  0) |
+		       ENCODE_BIT(1,          0, 0x01,  7);
+	hw->crtc[12] = Vdispend;
+	hw->crtc[15] = Vblankstart;
+	hw->crtc[16] = Vblankend;
+	hw->crtc[18] = 0xff;
+
+	/*
+	 * overflow - graphics reg 0x11
+	 * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
+	 * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
+	 */
+	hw->crtc_ofl =
+		ENCODE_BIT(Vtotal, 10, 0x01, 0) |
+		ENCODE_BIT(Vdispend, 10, 0x01, 1) |
+		ENCODE_BIT(Vsyncstart, 10, 0x01, 2) |
+		ENCODE_BIT(Vblankstart, 10, 0x01, 3) |
+		EXT_CRT_VRTOFL_LINECOMP10;
+
+	/* woody: set the interlaced bit... */
+	/* FIXME: what about doublescan? */
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+		hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
+
+	return 0;
+}
+
+/*
+ * The following was discovered by a good monitor, bit twiddling, theorising
+ * and but mostly luck.  Strangely, it looks like everyone elses' PLL!
+ *
+ * Clock registers:
+ *   fclock = fpll / div2
+ *   fpll   = fref * mult / div1
+ * where:
+ *   fref = 14.318MHz (69842ps)
+ *   mult = reg0xb0.7:0
+ *   div1 = (reg0xb1.5:0 + 1)
+ *   div2 =  2^(reg0xb1.7:6)
+ *   fpll should be between 115 and 260 MHz
+ *  (8696ps and 3846ps)
+ */
+static int
+cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,
+			 struct fb_var_screeninfo *var)
+{
+	u_long pll_ps = var->pixclock;
+	const u_long ref_ps = cfb->ref_ps;
+	u_int div2, t_div1, best_div1, best_mult;
+	int best_diff;
+	int vco;
+
+	/*
+	 * Step 1:
+	 *   find div2 such that 115MHz < fpll < 260MHz
+	 *   and 0 <= div2 < 4
+	 */
+	for (div2 = 0; div2 < 4; div2++) {
+		u_long new_pll;
+
+		new_pll = pll_ps / cfb->divisors[div2];
+		if (8696 > new_pll && new_pll > 3846) {
+			pll_ps = new_pll;
+			break;
+		}
+	}
+
+	if (div2 == 4)
+		return -EINVAL;
+
+	/*
+	 * Step 2:
+	 *  Given pll_ps and ref_ps, find:
+	 *    pll_ps * 0.995 < pll_ps_calc < pll_ps * 1.005
+	 *  where { 1 < best_div1 < 32, 1 < best_mult < 256 }
+	 *    pll_ps_calc = best_div1 / (ref_ps * best_mult)
+	 */
+	best_diff = 0x7fffffff;
+	best_mult = 2;
+	best_div1 = 32;
+	for (t_div1 = 2; t_div1 < 32; t_div1 += 1) {
+		u_int rr, t_mult, t_pll_ps;
+		int diff;
+
+		/*
+		 * Find the multiplier for this divisor
+		 */
+		rr = ref_ps * t_div1;
+		t_mult = (rr + pll_ps / 2) / pll_ps;
+
+		/*
+		 * Is the multiplier within the correct range?
+		 */
+		if (t_mult > 256 || t_mult < 2)
+			continue;
+
+		/*
+		 * Calculate the actual clock period from this multiplier
+		 * and divisor, and estimate the error.
+		 */
+		t_pll_ps = (rr + t_mult / 2) / t_mult;
+		diff = pll_ps - t_pll_ps;
+		if (diff < 0)
+			diff = -diff;
+
+		if (diff < best_diff) {
+			best_diff = diff;
+			best_mult = t_mult;
+			best_div1 = t_div1;
+		}
+
+		/*
+		 * If we hit an exact value, there is no point in continuing.
+		 */
+		if (diff == 0)
+			break;
+	}
+
+	/*
+	 * Step 3:
+	 *  combine values
+	 */
+	hw->clock_mult = best_mult - 1;
+	hw->clock_div  = div2 << 6 | (best_div1 - 1);
+
+	vco = ref_ps * best_div1 / best_mult;
+	if ((ref_ps == 40690) && (vco < 5556))
+		/* Set VFSEL when VCO > 180MHz (5.556 ps). */
+		hw->clock_div |= EXT_DCLK_DIV_VFSEL;
+
+	return 0;
+}
+
+/*
+ *    Set the User Defined Part of the Display
+ */
+static int
+cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+	struct par_info hw;
+	unsigned int mem;
+	int err;
+
+	var->transp.msb_right	= 0;
+	var->red.msb_right	= 0;
+	var->green.msb_right	= 0;
+	var->blue.msb_right	= 0;
+	var->transp.offset	= 0;
+	var->transp.length	= 0;
+
+	switch (var->bits_per_pixel) {
+	case 8:	/* PSEUDOCOLOUR, 256 */
+		var->red.offset		= 0;
+		var->red.length		= 8;
+		var->green.offset	= 0;
+		var->green.length	= 8;
+		var->blue.offset	= 0;
+		var->blue.length	= 8;
+		break;
+
+	case 16:/* DIRECTCOLOUR, 64k or 32k */
+		switch (var->green.length) {
+		case 6: /* RGB565, 64k */
+			var->red.offset		= 11;
+			var->red.length		= 5;
+			var->green.offset	= 5;
+			var->green.length	= 6;
+			var->blue.offset	= 0;
+			var->blue.length	= 5;
+			break;
+
+		default:
+		case 5: /* RGB555, 32k */
+			var->red.offset		= 10;
+			var->red.length		= 5;
+			var->green.offset	= 5;
+			var->green.length	= 5;
+			var->blue.offset	= 0;
+			var->blue.length	= 5;
+			break;
+
+		case 4: /* RGB444, 4k + transparency? */
+			var->transp.offset	= 12;
+			var->transp.length	= 4;
+			var->red.offset		= 8;
+			var->red.length		= 4;
+			var->green.offset	= 4;
+			var->green.length	= 4;
+			var->blue.offset	= 0;
+			var->blue.length	= 4;
+			break;
+		}
+		break;
+
+	case 24:/* TRUECOLOUR, 16m */
+		var->red.offset		= 16;
+		var->red.length		= 8;
+		var->green.offset	= 8;
+		var->green.length	= 8;
+		var->blue.offset	= 0;
+		var->blue.length	= 8;
+		break;
+
+	case 32:/* TRUECOLOUR, 16m */
+		var->transp.offset	= 24;
+		var->transp.length	= 8;
+		var->red.offset		= 16;
+		var->red.length		= 8;
+		var->green.offset	= 8;
+		var->green.length	= 8;
+		var->blue.offset	= 0;
+		var->blue.length	= 8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
+	if (mem > cfb->fb.fix.smem_len)
+		var->yres_virtual = cfb->fb.fix.smem_len * 8 /
+				    (var->bits_per_pixel * var->xres_virtual);
+
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+	if (var->xres > var->xres_virtual)
+		var->xres = var->xres_virtual;
+
+	err = cyber2000fb_decode_clock(&hw, cfb, var);
+	if (err)
+		return err;
+
+	err = cyber2000fb_decode_crtc(&hw, cfb, var);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int cyber2000fb_set_par(struct fb_info *info)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+	struct fb_var_screeninfo *var = &cfb->fb.var;
+	struct par_info hw;
+	unsigned int mem;
+
+	hw.width = var->xres_virtual;
+	hw.ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		hw.co_pixfmt		= CO_PIXFMT_8BPP;
+		hw.pitch		= hw.width >> 3;
+		hw.extseqmisc		= EXT_SEQ_MISC_8;
+		break;
+
+	case 16:
+		hw.co_pixfmt		= CO_PIXFMT_16BPP;
+		hw.pitch		= hw.width >> 2;
+
+		switch (var->green.length) {
+		case 6: /* RGB565, 64k */
+			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB565;
+			break;
+		case 5: /* RGB555, 32k */
+			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB555;
+			break;
+		case 4: /* RGB444, 4k + transparency? */
+			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB444;
+			break;
+		default:
+			BUG();
+		}
+		break;
+
+	case 24:/* TRUECOLOUR, 16m */
+		hw.co_pixfmt		= CO_PIXFMT_24BPP;
+		hw.width		*= 3;
+		hw.pitch		= hw.width >> 3;
+		hw.ramdac		|= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
+		hw.extseqmisc		= EXT_SEQ_MISC_24_RGB888;
+		break;
+
+	case 32:/* TRUECOLOUR, 16m */
+		hw.co_pixfmt		= CO_PIXFMT_32BPP;
+		hw.pitch		= hw.width >> 1;
+		hw.ramdac		|= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
+		hw.extseqmisc		= EXT_SEQ_MISC_32;
+		break;
+
+	default:
+		BUG();
+	}
+
+	/*
+	 * Sigh, this is absolutely disgusting, but caused by
+	 * the way the fbcon developers want to separate out
+	 * the "checking" and the "setting" of the video mode.
+	 *
+	 * If the mode is not suitable for the hardware here,
+	 * we can't prevent it being set by returning an error.
+	 *
+	 * In theory, since NetWinders contain just one VGA card,
+	 * we should never end up hitting this problem.
+	 */
+	BUG_ON(cyber2000fb_decode_clock(&hw, cfb, var) != 0);
+	BUG_ON(cyber2000fb_decode_crtc(&hw, cfb, var) != 0);
+
+	hw.width -= 1;
+	hw.fetch = hw.pitch;
+	if (!(cfb->mem_ctl2 & MEM_CTL2_64BIT))
+		hw.fetch <<= 1;
+	hw.fetch += 1;
+
+	cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+	/*
+	 * Same here - if the size of the video mode exceeds the
+	 * available RAM, we can't prevent this mode being set.
+	 *
+	 * In theory, since NetWinders contain just one VGA card,
+	 * we should never end up hitting this problem.
+	 */
+	mem = cfb->fb.fix.line_length * var->yres_virtual;
+	BUG_ON(mem > cfb->fb.fix.smem_len);
+
+	/*
+	 * 8bpp displays are always pseudo colour.  16bpp and above
+	 * are direct colour or true colour, depending on whether
+	 * the RAMDAC palettes are bypassed.  (Direct colour has
+	 * palettes, true colour does not.)
+	 */
+	if (var->bits_per_pixel == 8)
+		cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else if (hw.ramdac & RAMDAC_BYPASS)
+		cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+	else
+		cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
+
+	cyber2000fb_set_timing(cfb, &hw);
+	cyber2000fb_update_start(cfb, var);
+
+	return 0;
+}
+
+/*
+ *    Pan or Wrap the Display
+ */
+static int
+cyber2000fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+
+	if (cyber2000fb_update_start(cfb, var))
+		return -EINVAL;
+
+	cfb->fb.var.xoffset = var->xoffset;
+	cfb->fb.var.yoffset = var->yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP) {
+		cfb->fb.var.vmode |= FB_VMODE_YWRAP;
+	} else {
+		cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
+	}
+
+	return 0;
+}
+
+/*
+ *    (Un)Blank the display.
+ *
+ *  Blank the screen if blank_mode != 0, else unblank. If
+ *  blank == NULL then the caller blanks by setting the CLUT
+ *  (Color Look Up Table) to all black. Return 0 if blanking
+ *  succeeded, != 0 if un-/blanking failed due to e.g. a
+ *  video mode which doesn't support it. Implements VESA
+ *  suspend and powerdown modes on hardware that supports
+ *  disabling hsync/vsync:
+ *    blank_mode == 2: suspend vsync
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ *
+ *  wms...Enable VESA DMPS compatible powerdown mode
+ *  run "setterm -powersave powerdown" to take advantage
+ */
+static int cyber2000fb_blank(int blank, struct fb_info *info)
+{
+	struct cfb_info *cfb = (struct cfb_info *)info;
+	unsigned int sync = 0;
+	int i;
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:	/* powerdown - both sync lines down */
+		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:	/* hsync off */
+		sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:	/* vsync off */
+		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
+		break;
+	case FB_BLANK_NORMAL:		/* soft blank */
+	default:			/* unblank */
+		break;
+	}
+
+	cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
+
+	if (blank <= 1) {
+		/* turn on ramdacs */
+		cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS |
+					   RAMDAC_RAMPWRDN);
+		cyber2000fb_write_ramdac_ctrl(cfb);
+	}
+
+	/*
+	 * Soft blank/unblank the display.
+	 */
+	if (blank) {	/* soft blank */
+		for (i = 0; i < NR_PALETTE; i++) {
+			cyber2000fb_writeb(i, 0x3c8, cfb);
+			cyber2000fb_writeb(0, 0x3c9, cfb);
+			cyber2000fb_writeb(0, 0x3c9, cfb);
+			cyber2000fb_writeb(0, 0x3c9, cfb);
+		}
+	} else {	/* unblank */
+		for (i = 0; i < NR_PALETTE; i++) {
+			cyber2000fb_writeb(i, 0x3c8, cfb);
+			cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
+			cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
+			cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
+		}
+	}
+
+	if (blank >= 2) {
+		/* turn off ramdacs */
+		cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS |
+					 RAMDAC_RAMPWRDN;
+		cyber2000fb_write_ramdac_ctrl(cfb);
+	}
+
+	return 0;
+}
+
+static struct fb_ops cyber2000fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= cyber2000fb_check_var,
+	.fb_set_par	= cyber2000fb_set_par,
+	.fb_setcolreg	= cyber2000fb_setcolreg,
+	.fb_blank	= cyber2000fb_blank,
+	.fb_pan_display	= cyber2000fb_pan_display,
+	.fb_fillrect	= cyber2000fb_fillrect,
+	.fb_copyarea	= cyber2000fb_copyarea,
+	.fb_imageblit	= cyber2000fb_imageblit,
+	.fb_sync	= cyber2000fb_sync,
+};
+
+/*
+ * This is the only "static" reference to the internal data structures
+ * of this driver.  It is here solely at the moment to support the other
+ * CyberPro modules external to this driver.
+ */
+static struct cfb_info *int_cfb_info;
+
+/*
+ * Enable access to the extended registers
+ */
+void cyber2000fb_enable_extregs(struct cfb_info *cfb)
+{
+	cfb->func_use_count += 1;
+
+	if (cfb->func_use_count == 1) {
+		int old;
+
+		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
+		old |= EXT_FUNC_CTL_EXTREGENBL;
+		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
+	}
+}
+EXPORT_SYMBOL(cyber2000fb_enable_extregs);
+
+/*
+ * Disable access to the extended registers
+ */
+void cyber2000fb_disable_extregs(struct cfb_info *cfb)
+{
+	if (cfb->func_use_count == 1) {
+		int old;
+
+		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
+		old &= ~EXT_FUNC_CTL_EXTREGENBL;
+		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
+	}
+
+	if (cfb->func_use_count == 0)
+		printk(KERN_ERR "disable_extregs: count = 0\n");
+	else
+		cfb->func_use_count -= 1;
+}
+EXPORT_SYMBOL(cyber2000fb_disable_extregs);
+
+/*
+ * Attach a capture/tv driver to the core CyberX0X0 driver.
+ */
+int cyber2000fb_attach(struct cyberpro_info *info, int idx)
+{
+	if (int_cfb_info != NULL) {
+		info->dev	      = int_cfb_info->fb.device;
+#ifdef CONFIG_FB_CYBER2000_I2C
+		info->i2c	      = &int_cfb_info->i2c_adapter;
+#else
+		info->i2c	      = NULL;
+#endif
+		info->regs	      = int_cfb_info->regs;
+		info->irq             = int_cfb_info->irq;
+		info->fb	      = int_cfb_info->fb.screen_base;
+		info->fb_size	      = int_cfb_info->fb.fix.smem_len;
+		info->info	      = int_cfb_info;
+
+		strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
+			sizeof(info->dev_name));
+	}
+
+	return int_cfb_info != NULL;
+}
+EXPORT_SYMBOL(cyber2000fb_attach);
+
+/*
+ * Detach a capture/tv driver from the core CyberX0X0 driver.
+ */
+void cyber2000fb_detach(int idx)
+{
+}
+EXPORT_SYMBOL(cyber2000fb_detach);
+
+#ifdef CONFIG_FB_CYBER2000_DDC
+
+#define DDC_REG		0xb0
+#define DDC_SCL_OUT	(1 << 0)
+#define DDC_SDA_OUT	(1 << 4)
+#define DDC_SCL_IN	(1 << 2)
+#define DDC_SDA_IN	(1 << 6)
+
+static void cyber2000fb_enable_ddc(struct cfb_info *cfb)
+{
+	spin_lock(&cfb->reg_b0_lock);
+	cyber2000fb_writew(0x1bf, 0x3ce, cfb);
+}
+
+static void cyber2000fb_disable_ddc(struct cfb_info *cfb)
+{
+	cyber2000fb_writew(0x0bf, 0x3ce, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
+}
+
+
+static void cyber2000fb_ddc_setscl(void *data, int val)
+{
+	struct cfb_info *cfb = data;
+	unsigned char reg;
+
+	cyber2000fb_enable_ddc(cfb);
+	reg = cyber2000_grphr(DDC_REG, cfb);
+	if (!val)	/* bit is inverted */
+		reg |= DDC_SCL_OUT;
+	else
+		reg &= ~DDC_SCL_OUT;
+	cyber2000_grphw(DDC_REG, reg, cfb);
+	cyber2000fb_disable_ddc(cfb);
+}
+
+static void cyber2000fb_ddc_setsda(void *data, int val)
+{
+	struct cfb_info *cfb = data;
+	unsigned char reg;
+
+	cyber2000fb_enable_ddc(cfb);
+	reg = cyber2000_grphr(DDC_REG, cfb);
+	if (!val)	/* bit is inverted */
+		reg |= DDC_SDA_OUT;
+	else
+		reg &= ~DDC_SDA_OUT;
+	cyber2000_grphw(DDC_REG, reg, cfb);
+	cyber2000fb_disable_ddc(cfb);
+}
+
+static int cyber2000fb_ddc_getscl(void *data)
+{
+	struct cfb_info *cfb = data;
+	int retval;
+
+	cyber2000fb_enable_ddc(cfb);
+	retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SCL_IN);
+	cyber2000fb_disable_ddc(cfb);
+
+	return retval;
+}
+
+static int cyber2000fb_ddc_getsda(void *data)
+{
+	struct cfb_info *cfb = data;
+	int retval;
+
+	cyber2000fb_enable_ddc(cfb);
+	retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SDA_IN);
+	cyber2000fb_disable_ddc(cfb);
+
+	return retval;
+}
+
+static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
+{
+	strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
+		sizeof(cfb->ddc_adapter.name));
+	cfb->ddc_adapter.owner		= THIS_MODULE;
+	cfb->ddc_adapter.class		= I2C_CLASS_DDC;
+	cfb->ddc_adapter.algo_data	= &cfb->ddc_algo;
+	cfb->ddc_adapter.dev.parent	= cfb->fb.device;
+	cfb->ddc_algo.setsda		= cyber2000fb_ddc_setsda;
+	cfb->ddc_algo.setscl		= cyber2000fb_ddc_setscl;
+	cfb->ddc_algo.getsda		= cyber2000fb_ddc_getsda;
+	cfb->ddc_algo.getscl		= cyber2000fb_ddc_getscl;
+	cfb->ddc_algo.udelay		= 10;
+	cfb->ddc_algo.timeout		= 20;
+	cfb->ddc_algo.data		= cfb;
+
+	i2c_set_adapdata(&cfb->ddc_adapter, cfb);
+
+	return i2c_bit_add_bus(&cfb->ddc_adapter);
+}
+#endif /* CONFIG_FB_CYBER2000_DDC */
+
+#ifdef CONFIG_FB_CYBER2000_I2C
+static void cyber2000fb_i2c_setsda(void *data, int state)
+{
+	struct cfb_info *cfb = data;
+	unsigned int latch2;
+
+	spin_lock(&cfb->reg_b0_lock);
+	latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
+	latch2 &= EXT_LATCH2_I2C_CLKEN;
+	if (state)
+		latch2 |= EXT_LATCH2_I2C_DATEN;
+	cyber2000_grphw(EXT_LATCH2, latch2, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
+}
+
+static void cyber2000fb_i2c_setscl(void *data, int state)
+{
+	struct cfb_info *cfb = data;
+	unsigned int latch2;
+
+	spin_lock(&cfb->reg_b0_lock);
+	latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
+	latch2 &= EXT_LATCH2_I2C_DATEN;
+	if (state)
+		latch2 |= EXT_LATCH2_I2C_CLKEN;
+	cyber2000_grphw(EXT_LATCH2, latch2, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
+}
+
+static int cyber2000fb_i2c_getsda(void *data)
+{
+	struct cfb_info *cfb = data;
+	int ret;
+
+	spin_lock(&cfb->reg_b0_lock);
+	ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
+	spin_unlock(&cfb->reg_b0_lock);
+
+	return ret;
+}
+
+static int cyber2000fb_i2c_getscl(void *data)
+{
+	struct cfb_info *cfb = data;
+	int ret;
+
+	spin_lock(&cfb->reg_b0_lock);
+	ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
+	spin_unlock(&cfb->reg_b0_lock);
+
+	return ret;
+}
+
+static int cyber2000fb_i2c_register(struct cfb_info *cfb)
+{
+	strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
+		sizeof(cfb->i2c_adapter.name));
+	cfb->i2c_adapter.owner = THIS_MODULE;
+	cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
+	cfb->i2c_adapter.dev.parent = cfb->fb.device;
+	cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
+	cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
+	cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
+	cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
+	cfb->i2c_algo.udelay = 5;
+	cfb->i2c_algo.timeout = msecs_to_jiffies(100);
+	cfb->i2c_algo.data = cfb;
+
+	return i2c_bit_add_bus(&cfb->i2c_adapter);
+}
+
+static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
+{
+	i2c_del_adapter(&cfb->i2c_adapter);
+}
+#else
+#define cyber2000fb_i2c_register(cfb)	(0)
+#define cyber2000fb_i2c_unregister(cfb)	do { } while (0)
+#endif
+
+/*
+ * These parameters give
+ * 640x480, hsync 31.5kHz, vsync 60Hz
+ */
+static struct fb_videomode cyber2000fb_default_mode = {
+	.refresh	= 60,
+	.xres		= 640,
+	.yres		= 480,
+	.pixclock	= 39722,
+	.left_margin	= 56,
+	.right_margin	= 16,
+	.upper_margin	= 34,
+	.lower_margin	= 9,
+	.hsync_len	= 88,
+	.vsync_len	= 2,
+	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
+static char igs_regs[] = {
+	EXT_CRT_IRQ,		0,
+	EXT_CRT_TEST,		0,
+	EXT_SYNC_CTL,		0,
+	EXT_SEG_WRITE_PTR,	0,
+	EXT_SEG_READ_PTR,	0,
+	EXT_BIU_MISC,		EXT_BIU_MISC_LIN_ENABLE |
+				EXT_BIU_MISC_COP_ENABLE |
+				EXT_BIU_MISC_COP_BFC,
+	EXT_FUNC_CTL,		0,
+	CURS_H_START,		0,
+	CURS_H_START + 1,	0,
+	CURS_H_PRESET,		0,
+	CURS_V_START,		0,
+	CURS_V_START + 1,	0,
+	CURS_V_PRESET,		0,
+	CURS_CTL,		0,
+	EXT_ATTRIB_CTL,		EXT_ATTRIB_CTL_EXT,
+	EXT_OVERSCAN_RED,	0,
+	EXT_OVERSCAN_GREEN,	0,
+	EXT_OVERSCAN_BLUE,	0,
+
+	/* some of these are questionable when we have a BIOS */
+	EXT_MEM_CTL0,		EXT_MEM_CTL0_7CLK |
+				EXT_MEM_CTL0_RAS_1 |
+				EXT_MEM_CTL0_MULTCAS,
+	EXT_HIDDEN_CTL1,	0x30,
+	EXT_FIFO_CTL,		0x0b,
+	EXT_FIFO_CTL + 1,	0x17,
+	0x76,			0x00,
+	EXT_HIDDEN_CTL4,	0xc8
+};
+
+/*
+ * Initialise the CyberPro hardware.  On the CyberPro5XXXX,
+ * ensure that we're using the correct PLL (5XXX's may be
+ * programmed to use an additional set of PLLs.)
+ */
+static void cyberpro_init_hw(struct cfb_info *cfb)
+{
+	int i;
+
+	for (i = 0; i < sizeof(igs_regs); i += 2)
+		cyber2000_grphw(igs_regs[i], igs_regs[i + 1], cfb);
+
+	if (cfb->id == ID_CYBERPRO_5000) {
+		unsigned char val;
+		cyber2000fb_writeb(0xba, 0x3ce, cfb);
+		val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
+		cyber2000fb_writeb(val, 0x3cf, cfb);
+	}
+}
+
+static struct cfb_info *cyberpro_alloc_fb_info(unsigned int id, char *name)
+{
+	struct cfb_info *cfb;
+
+	cfb = kzalloc(sizeof(struct cfb_info), GFP_KERNEL);
+	if (!cfb)
+		return NULL;
+
+
+	cfb->id			= id;
+
+	if (id == ID_CYBERPRO_5000)
+		cfb->ref_ps	= 40690; /* 24.576 MHz */
+	else
+		cfb->ref_ps	= 69842; /* 14.31818 MHz (69841?) */
+
+	cfb->divisors[0]	= 1;
+	cfb->divisors[1]	= 2;
+	cfb->divisors[2]	= 4;
+
+	if (id == ID_CYBERPRO_2000)
+		cfb->divisors[3] = 8;
+	else
+		cfb->divisors[3] = 6;
+
+	strcpy(cfb->fb.fix.id, name);
+
+	cfb->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	cfb->fb.fix.type_aux	= 0;
+	cfb->fb.fix.xpanstep	= 0;
+	cfb->fb.fix.ypanstep	= 1;
+	cfb->fb.fix.ywrapstep	= 0;
+
+	switch (id) {
+	case ID_IGA_1682:
+		cfb->fb.fix.accel = 0;
+		break;
+
+	case ID_CYBERPRO_2000:
+		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
+		break;
+
+	case ID_CYBERPRO_2010:
+		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
+		break;
+
+	case ID_CYBERPRO_5000:
+		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
+		break;
+	}
+
+	cfb->fb.var.nonstd	= 0;
+	cfb->fb.var.activate	= FB_ACTIVATE_NOW;
+	cfb->fb.var.height	= -1;
+	cfb->fb.var.width	= -1;
+	cfb->fb.var.accel_flags	= FB_ACCELF_TEXT;
+
+	cfb->fb.fbops		= &cyber2000fb_ops;
+	cfb->fb.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	cfb->fb.pseudo_palette	= cfb->pseudo_palette;
+
+	spin_lock_init(&cfb->reg_b0_lock);
+
+	fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
+
+	return cfb;
+}
+
+static void cyberpro_free_fb_info(struct cfb_info *cfb)
+{
+	if (cfb) {
+		/*
+		 * Free the colourmap
+		 */
+		fb_alloc_cmap(&cfb->fb.cmap, 0, 0);
+
+		kfree(cfb);
+	}
+}
+
+/*
+ * Parse Cyber2000fb options.  Usage:
+ *  video=cyber2000:font:fontname
+ */
+#ifndef MODULE
+static int cyber2000fb_setup(char *options)
+{
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+
+		if (strncmp(opt, "font:", 5) == 0) {
+			static char default_font_storage[40];
+
+			strlcpy(default_font_storage, opt + 5,
+				sizeof(default_font_storage));
+			default_font = default_font_storage;
+			continue;
+		}
+
+		printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", opt);
+	}
+	return 0;
+}
+#endif  /*  MODULE  */
+
+/*
+ * The CyberPro chips can be placed on many different bus types.
+ * This probe function is common to all bus types.  The bus-specific
+ * probe function is expected to have:
+ *  - enabled access to the linear memory region
+ *  - memory mapped access to the registers
+ *  - initialised mem_ctl1 and mem_ctl2 appropriately.
+ */
+static int cyberpro_common_probe(struct cfb_info *cfb)
+{
+	u_long smem_size;
+	u_int h_sync, v_sync;
+	int err;
+
+	cyberpro_init_hw(cfb);
+
+	/*
+	 * Get the video RAM size and width from the VGA register.
+	 * This should have been already initialised by the BIOS,
+	 * but if it's garbage, claim default 1MB VRAM (woody)
+	 */
+	cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
+	cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
+
+	/*
+	 * Determine the size of the memory.
+	 */
+	switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
+	case MEM_CTL2_SIZE_4MB:
+		smem_size = 0x00400000;
+		break;
+	case MEM_CTL2_SIZE_2MB:
+		smem_size = 0x00200000;
+		break;
+	case MEM_CTL2_SIZE_1MB:
+		smem_size = 0x00100000;
+		break;
+	default:
+		smem_size = 0x00100000;
+		break;
+	}
+
+	cfb->fb.fix.smem_len   = smem_size;
+	cfb->fb.fix.mmio_len   = MMIO_SIZE;
+	cfb->fb.screen_base    = cfb->region;
+
+#ifdef CONFIG_FB_CYBER2000_DDC
+	if (cyber2000fb_setup_ddc_bus(cfb) == 0)
+		cfb->ddc_registered = true;
+#endif
+
+	err = -EINVAL;
+	if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
+			  &cyber2000fb_default_mode, 8)) {
+		printk(KERN_ERR "%s: no valid mode found\n", cfb->fb.fix.id);
+		goto failed;
+	}
+
+	cfb->fb.var.yres_virtual = cfb->fb.fix.smem_len * 8 /
+			(cfb->fb.var.bits_per_pixel * cfb->fb.var.xres_virtual);
+
+	if (cfb->fb.var.yres_virtual < cfb->fb.var.yres)
+		cfb->fb.var.yres_virtual = cfb->fb.var.yres;
+
+/*	fb_set_var(&cfb->fb.var, -1, &cfb->fb); */
+
+	/*
+	 * Calculate the hsync and vsync frequencies.  Note that
+	 * we split the 1e12 constant up so that we can preserve
+	 * the precision and fit the results into 32-bit registers.
+	 *  (1953125000 * 512 = 1e12)
+	 */
+	h_sync = 1953125000 / cfb->fb.var.pixclock;
+	h_sync = h_sync * 512 / (cfb->fb.var.xres + cfb->fb.var.left_margin +
+		 cfb->fb.var.right_margin + cfb->fb.var.hsync_len);
+	v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
+		 cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
+
+	printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+		cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
+		cfb->fb.var.xres, cfb->fb.var.yres,
+		h_sync / 1000, h_sync % 1000, v_sync);
+
+	err = cyber2000fb_i2c_register(cfb);
+	if (err)
+		goto failed;
+
+	err = register_framebuffer(&cfb->fb);
+	if (err)
+		cyber2000fb_i2c_unregister(cfb);
+
+failed:
+#ifdef CONFIG_FB_CYBER2000_DDC
+	if (err && cfb->ddc_registered)
+		i2c_del_adapter(&cfb->ddc_adapter);
+#endif
+	return err;
+}
+
+static void cyberpro_common_remove(struct cfb_info *cfb)
+{
+	unregister_framebuffer(&cfb->fb);
+#ifdef CONFIG_FB_CYBER2000_DDC
+	if (cfb->ddc_registered)
+		i2c_del_adapter(&cfb->ddc_adapter);
+#endif
+	cyber2000fb_i2c_unregister(cfb);
+}
+
+static void cyberpro_common_resume(struct cfb_info *cfb)
+{
+	cyberpro_init_hw(cfb);
+
+	/*
+	 * Reprogram the MEM_CTL1 and MEM_CTL2 registers
+	 */
+	cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
+	cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
+
+	/*
+	 * Restore the old video mode and the palette.
+	 * We also need to tell fbcon to redraw the console.
+	 */
+	cyber2000fb_set_par(&cfb->fb);
+}
+
+/*
+ * PCI specific support.
+ */
+#ifdef CONFIG_PCI
+/*
+ * We need to wake up the CyberPro, and make sure its in linear memory
+ * mode.  Unfortunately, this is specific to the platform and card that
+ * we are running on.
+ *
+ * On x86 and ARM, should we be initialising the CyberPro first via the
+ * IO registers, and then the MMIO registers to catch all cases?  Can we
+ * end up in the situation where the chip is in MMIO mode, but not awake
+ * on an x86 system?
+ */
+static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
+{
+	unsigned char val;
+
+#if defined(__sparc_v9__)
+#error "You lose, consult DaveM."
+#elif defined(__sparc__)
+	/*
+	 * SPARC does not have an "outb" instruction, so we generate
+	 * I/O cycles storing into a reserved memory space at
+	 * physical address 0x3000000
+	 */
+	unsigned char __iomem *iop;
+
+	iop = ioremap(0x3000000, 0x5000);
+	if (iop == NULL) {
+		printk(KERN_ERR "iga5000: cannot map I/O\n");
+		return -ENOMEM;
+	}
+
+	writeb(0x18, iop + 0x46e8);
+	writeb(0x01, iop + 0x102);
+	writeb(0x08, iop + 0x46e8);
+	writeb(EXT_BIU_MISC, iop + 0x3ce);
+	writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
+
+	iounmap(iop);
+#else
+	/*
+	 * Most other machine types are "normal", so
+	 * we use the standard IO-based wakeup.
+	 */
+	outb(0x18, 0x46e8);
+	outb(0x01, 0x102);
+	outb(0x08, 0x46e8);
+	outb(EXT_BIU_MISC, 0x3ce);
+	outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
+#endif
+
+	/*
+	 * Allow the CyberPro to accept PCI burst accesses
+	 */
+	if (cfb->id == ID_CYBERPRO_2010) {
+		printk(KERN_INFO "%s: NOT enabling PCI bursts\n",
+		       cfb->fb.fix.id);
+	} else {
+		val = cyber2000_grphr(EXT_BUS_CTL, cfb);
+		if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
+			printk(KERN_INFO "%s: enabling PCI bursts\n",
+				cfb->fb.fix.id);
+
+			val |= EXT_BUS_CTL_PCIBURST_WRITE;
+
+			if (cfb->id == ID_CYBERPRO_5000)
+				val |= EXT_BUS_CTL_PCIBURST_READ;
+
+			cyber2000_grphw(EXT_BUS_CTL, val, cfb);
+		}
+	}
+
+	return 0;
+}
+
+static int cyberpro_pci_probe(struct pci_dev *dev,
+			      const struct pci_device_id *id)
+{
+	struct cfb_info *cfb;
+	char name[16];
+	int err;
+
+	sprintf(name, "CyberPro%4X", id->device);
+
+	err = pci_enable_device(dev);
+	if (err)
+		return err;
+
+	err = -ENOMEM;
+	cfb = cyberpro_alloc_fb_info(id->driver_data, name);
+	if (!cfb)
+		goto failed_release;
+
+	err = pci_request_regions(dev, cfb->fb.fix.id);
+	if (err)
+		goto failed_regions;
+
+	cfb->irq = dev->irq;
+	cfb->region = pci_ioremap_bar(dev, 0);
+	if (!cfb->region) {
+		err = -ENOMEM;
+		goto failed_ioremap;
+	}
+
+	cfb->regs = cfb->region + MMIO_OFFSET;
+	cfb->fb.device = &dev->dev;
+	cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
+	cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+
+	/*
+	 * Bring up the hardware.  This is expected to enable access
+	 * to the linear memory region, and allow access to the memory
+	 * mapped registers.  Also, mem_ctl1 and mem_ctl2 must be
+	 * initialised.
+	 */
+	err = cyberpro_pci_enable_mmio(cfb);
+	if (err)
+		goto failed;
+
+	/*
+	 * Use MCLK from BIOS. FIXME: what about hotplug?
+	 */
+	cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
+	cfb->mclk_div  = cyber2000_grphr(EXT_MCLK_DIV, cfb);
+
+#ifdef __arm__
+	/*
+	 * MCLK on the NetWinder and the Shark is fixed at 75MHz
+	 */
+	if (machine_is_netwinder()) {
+		cfb->mclk_mult = 0xdb;
+		cfb->mclk_div  = 0x54;
+	}
+#endif
+
+	err = cyberpro_common_probe(cfb);
+	if (err)
+		goto failed;
+
+	/*
+	 * Our driver data
+	 */
+	pci_set_drvdata(dev, cfb);
+	if (int_cfb_info == NULL)
+		int_cfb_info = cfb;
+
+	return 0;
+
+failed:
+	iounmap(cfb->region);
+failed_ioremap:
+	pci_release_regions(dev);
+failed_regions:
+	cyberpro_free_fb_info(cfb);
+failed_release:
+	return err;
+}
+
+static void cyberpro_pci_remove(struct pci_dev *dev)
+{
+	struct cfb_info *cfb = pci_get_drvdata(dev);
+
+	if (cfb) {
+		cyberpro_common_remove(cfb);
+		iounmap(cfb->region);
+		cyberpro_free_fb_info(cfb);
+
+		if (cfb == int_cfb_info)
+			int_cfb_info = NULL;
+
+		pci_release_regions(dev);
+	}
+}
+
+static int cyberpro_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	return 0;
+}
+
+/*
+ * Re-initialise the CyberPro hardware
+ */
+static int cyberpro_pci_resume(struct pci_dev *dev)
+{
+	struct cfb_info *cfb = pci_get_drvdata(dev);
+
+	if (cfb) {
+		cyberpro_pci_enable_mmio(cfb);
+		cyberpro_common_resume(cfb);
+	}
+
+	return 0;
+}
+
+static struct pci_device_id cyberpro_pci_table[] = {
+/*	Not yet
+ *	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
+ *		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
+ */
+	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
+	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
+	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, cyberpro_pci_table);
+
+static struct pci_driver cyberpro_driver = {
+	.name		= "CyberPro",
+	.probe		= cyberpro_pci_probe,
+	.remove		= cyberpro_pci_remove,
+	.suspend	= cyberpro_pci_suspend,
+	.resume		= cyberpro_pci_resume,
+	.id_table	= cyberpro_pci_table
+};
+#endif
+
+/*
+ * I don't think we can use the "module_init" stuff here because
+ * the fbcon stuff may not be initialised yet.  Hence the #ifdef
+ * around module_init.
+ *
+ * Tony: "module_init" is now required
+ */
+static int __init cyber2000fb_init(void)
+{
+	int ret = -1, err;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("cyber2000fb", &option))
+		return -ENODEV;
+	cyber2000fb_setup(option);
+#endif
+
+	err = pci_register_driver(&cyberpro_driver);
+	if (!err)
+		ret = 0;
+
+	return ret ? err : 0;
+}
+module_init(cyber2000fb_init);
+
+static void __exit cyberpro_exit(void)
+{
+	pci_unregister_driver(&cyberpro_driver);
+}
+module_exit(cyberpro_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/cyber2000fb.h b/drivers/video/fbdev/cyber2000fb.h
new file mode 100644
index 000000000000..bad69102e774
--- /dev/null
+++ b/drivers/video/fbdev/cyber2000fb.h
@@ -0,0 +1,497 @@
+/*
+ *  linux/drivers/video/cyber2000fb.h
+ *
+ *  Copyright (C) 1998-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Integraphics Cyber2000 frame buffer device
+ */
+
+/*
+ * Internal CyberPro sizes and offsets.
+ */
+#define MMIO_OFFSET	0x00800000
+#define MMIO_SIZE	0x000c0000
+
+#define NR_PALETTE	256
+
+#if defined(DEBUG) && defined(CONFIG_DEBUG_LL)
+static void debug_printf(char *fmt, ...)
+{
+	extern void printascii(const char *);
+	char buffer[128];
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buffer, fmt, ap);
+	va_end(ap);
+
+	printascii(buffer);
+}
+#else
+#define debug_printf(x...) do { } while (0)
+#endif
+
+#define RAMDAC_RAMPWRDN		0x01
+#define RAMDAC_DAC8BIT		0x02
+#define RAMDAC_VREFEN		0x04
+#define RAMDAC_BYPASS		0x10
+#define RAMDAC_DACPWRDN		0x40
+
+#define EXT_CRT_VRTOFL		0x11
+#define EXT_CRT_VRTOFL_LINECOMP10	0x10
+#define EXT_CRT_VRTOFL_INTERLACE	0x20
+
+#define EXT_CRT_IRQ		0x12
+#define EXT_CRT_IRQ_ENABLE		0x01
+#define EXT_CRT_IRQ_ACT_HIGH		0x04
+
+#define EXT_CRT_TEST		0x13
+
+#define EXT_SYNC_CTL		0x16
+#define EXT_SYNC_CTL_HS_NORMAL		0x00
+#define EXT_SYNC_CTL_HS_0		0x01
+#define EXT_SYNC_CTL_HS_1		0x02
+#define EXT_SYNC_CTL_HS_HSVS		0x03
+#define EXT_SYNC_CTL_VS_NORMAL		0x00
+#define EXT_SYNC_CTL_VS_0		0x04
+#define EXT_SYNC_CTL_VS_1		0x08
+#define EXT_SYNC_CTL_VS_COMP		0x0c
+
+#define EXT_BUS_CTL		0x30
+#define EXT_BUS_CTL_LIN_1MB		0x00
+#define EXT_BUS_CTL_LIN_2MB		0x01
+#define EXT_BUS_CTL_LIN_4MB		0x02
+#define EXT_BUS_CTL_ZEROWAIT		0x04
+#define EXT_BUS_CTL_PCIBURST_WRITE	0x20
+#define EXT_BUS_CTL_PCIBURST_READ	0x80	/* CyberPro 5000 only */
+
+#define EXT_SEG_WRITE_PTR	0x31
+#define EXT_SEG_READ_PTR	0x32
+#define EXT_BIU_MISC		0x33
+#define EXT_BIU_MISC_LIN_ENABLE		0x01
+#define EXT_BIU_MISC_COP_ENABLE		0x04
+#define EXT_BIU_MISC_COP_BFC		0x08
+
+#define EXT_FUNC_CTL		0x3c
+#define EXT_FUNC_CTL_EXTREGENBL		0x80	/* enable access to 0xbcxxx		*/
+
+#define PCI_BM_CTL		0x3e
+#define PCI_BM_CTL_ENABLE		0x01	/* enable bus-master			*/
+#define PCI_BM_CTL_BURST		0x02	/* enable burst				*/
+#define PCI_BM_CTL_BACK2BACK		0x04	/* enable back to back			*/
+#define PCI_BM_CTL_DUMMY		0x08	/* insert dummy cycle			*/
+
+#define X_V2_VID_MEM_START	0x40
+#define X_V2_VID_SRC_WIDTH	0x43
+#define X_V2_X_START		0x45
+#define X_V2_X_END		0x47
+#define X_V2_Y_START		0x49
+#define X_V2_Y_END		0x4b
+#define X_V2_VID_SRC_WIN_WIDTH	0x4d
+
+#define Y_V2_DDA_X_INC		0x43
+#define Y_V2_DDA_Y_INC		0x47
+#define Y_V2_VID_FIFO_CTL	0x49
+#define Y_V2_VID_FMT		0x4b
+#define Y_V2_VID_DISP_CTL1	0x4c
+#define Y_V2_VID_FIFO_CTL1	0x4d
+
+#define J_X2_VID_MEM_START	0x40
+#define J_X2_VID_SRC_WIDTH	0x43
+#define J_X2_X_START		0x47
+#define J_X2_X_END		0x49
+#define J_X2_Y_START		0x4b
+#define J_X2_Y_END		0x4d
+#define J_X2_VID_SRC_WIN_WIDTH	0x4f
+
+#define K_X2_DDA_X_INIT		0x40
+#define K_X2_DDA_X_INC		0x42
+#define K_X2_DDA_Y_INIT		0x44
+#define K_X2_DDA_Y_INC		0x46
+#define K_X2_VID_FMT		0x48
+#define K_X2_VID_DISP_CTL1	0x49
+
+#define K_CAP_X2_CTL1		0x49
+
+#define CURS_H_START		0x50
+#define CURS_H_PRESET		0x52
+#define CURS_V_START		0x53
+#define CURS_V_PRESET		0x55
+#define CURS_CTL		0x56
+
+#define EXT_ATTRIB_CTL		0x57
+#define EXT_ATTRIB_CTL_EXT		0x01
+
+#define EXT_OVERSCAN_RED	0x58
+#define EXT_OVERSCAN_GREEN	0x59
+#define EXT_OVERSCAN_BLUE	0x5a
+
+#define CAP_X_START		0x60
+#define CAP_X_END		0x62
+#define CAP_Y_START		0x64
+#define CAP_Y_END		0x66
+#define CAP_DDA_X_INIT		0x68
+#define CAP_DDA_X_INC		0x6a
+#define CAP_DDA_Y_INIT		0x6c
+#define CAP_DDA_Y_INC		0x6e
+
+#define EXT_MEM_CTL0		0x70
+#define EXT_MEM_CTL0_7CLK		0x01
+#define EXT_MEM_CTL0_RAS_1		0x02
+#define EXT_MEM_CTL0_RAS2CAS_1		0x04
+#define EXT_MEM_CTL0_MULTCAS		0x08
+#define EXT_MEM_CTL0_ASYM		0x10
+#define EXT_MEM_CTL0_CAS1ON		0x20
+#define EXT_MEM_CTL0_FIFOFLUSH		0x40
+#define EXT_MEM_CTL0_SEQRESET		0x80
+
+#define EXT_MEM_CTL1		0x71
+#define EXT_MEM_CTL1_PAR		0x00
+#define EXT_MEM_CTL1_SERPAR		0x01
+#define EXT_MEM_CTL1_SER		0x03
+#define EXT_MEM_CTL1_SYNC		0x04
+#define EXT_MEM_CTL1_VRAM		0x08
+#define EXT_MEM_CTL1_4K_REFRESH		0x10
+#define EXT_MEM_CTL1_256Kx4		0x00
+#define EXT_MEM_CTL1_512Kx8		0x40
+#define EXT_MEM_CTL1_1Mx16		0x60
+
+#define EXT_MEM_CTL2		0x72
+#define MEM_CTL2_SIZE_1MB		0x00
+#define MEM_CTL2_SIZE_2MB		0x01
+#define MEM_CTL2_SIZE_4MB		0x02
+#define MEM_CTL2_SIZE_MASK		0x03
+#define MEM_CTL2_64BIT			0x04
+
+#define EXT_HIDDEN_CTL1		0x73
+
+#define EXT_FIFO_CTL		0x74
+
+#define EXT_SEQ_MISC		0x77
+#define EXT_SEQ_MISC_8			0x01
+#define EXT_SEQ_MISC_16_RGB565		0x02
+#define EXT_SEQ_MISC_32			0x03
+#define EXT_SEQ_MISC_24_RGB888		0x04
+#define EXT_SEQ_MISC_16_RGB555		0x06
+#define EXT_SEQ_MISC_8_RGB332		0x09
+#define EXT_SEQ_MISC_16_RGB444		0x0a
+
+#define EXT_HIDDEN_CTL4		0x7a
+
+#define CURS_MEM_START		0x7e		/* bits 23..12 */
+
+#define CAP_PIP_X_START		0x80
+#define CAP_PIP_X_END		0x82
+#define CAP_PIP_Y_START		0x84
+#define CAP_PIP_Y_END		0x86
+
+#define EXT_CAP_CTL1		0x88
+
+#define EXT_CAP_CTL2		0x89
+#define EXT_CAP_CTL2_ODDFRAMEIRQ	0x01
+#define EXT_CAP_CTL2_ANYFRAMEIRQ	0x02
+
+#define BM_CTRL0		0x9c
+#define BM_CTRL1		0x9d
+
+#define EXT_CAP_MODE1		0xa4
+#define EXT_CAP_MODE1_8BIT		0x01	/* enable 8bit capture mode		*/
+#define EXT_CAP_MODE1_CCIR656		0x02	/* CCIR656 mode				*/
+#define EXT_CAP_MODE1_IGNOREVGT		0x04	/* ignore VGT				*/
+#define EXT_CAP_MODE1_ALTFIFO		0x10	/* use alternate FIFO for capture	*/
+#define EXT_CAP_MODE1_SWAPUV		0x20	/* swap UV bytes			*/
+#define EXT_CAP_MODE1_MIRRORY		0x40	/* mirror vertically			*/
+#define EXT_CAP_MODE1_MIRRORX		0x80	/* mirror horizontally			*/
+
+#define EXT_CAP_MODE2		0xa5
+#define EXT_CAP_MODE2_CCIRINVOE		0x01
+#define EXT_CAP_MODE2_CCIRINVVGT	0x02
+#define EXT_CAP_MODE2_CCIRINVHGT	0x04
+#define EXT_CAP_MODE2_CCIRINVDG		0x08
+#define EXT_CAP_MODE2_DATEND		0x10
+#define EXT_CAP_MODE2_CCIRDGH		0x20
+#define EXT_CAP_MODE2_FIXSONY		0x40
+#define EXT_CAP_MODE2_SYNCFREEZE	0x80
+
+#define EXT_TV_CTL		0xae
+
+#define EXT_DCLK_MULT		0xb0
+#define EXT_DCLK_DIV		0xb1
+#define EXT_DCLK_DIV_VFSEL		0x20
+#define EXT_MCLK_MULT		0xb2
+#define EXT_MCLK_DIV		0xb3
+
+#define EXT_LATCH1		0xb5
+#define EXT_LATCH1_VAFC_EN		0x01	/* enable VAFC				*/
+
+#define EXT_FEATURE		0xb7
+#define EXT_FEATURE_BUS_MASK		0x07	/* host bus mask			*/
+#define EXT_FEATURE_BUS_PCI		0x00
+#define EXT_FEATURE_BUS_VL_STD		0x04
+#define EXT_FEATURE_BUS_VL_LINEAR	0x05
+#define EXT_FEATURE_1682		0x20	/* IGS 1682 compatibility		*/
+
+#define EXT_LATCH2		0xb6
+#define EXT_LATCH2_I2C_CLKEN		0x10
+#define EXT_LATCH2_I2C_CLK		0x20
+#define EXT_LATCH2_I2C_DATEN		0x40
+#define EXT_LATCH2_I2C_DAT		0x80
+
+#define EXT_XT_CTL		0xbe
+#define EXT_XT_CAP16			0x04
+#define EXT_XT_LINEARFB			0x08
+#define EXT_XT_PAL			0x10
+
+#define EXT_MEM_START		0xc0		/* ext start address 21 bits		*/
+#define HOR_PHASE_SHIFT		0xc2		/* high 3 bits				*/
+#define EXT_SRC_WIDTH		0xc3		/* ext offset phase  10 bits		*/
+#define EXT_SRC_HEIGHT		0xc4		/* high 6 bits				*/
+#define EXT_X_START		0xc5		/* ext->screen, 16 bits			*/
+#define EXT_X_END		0xc7		/* ext->screen, 16 bits			*/
+#define EXT_Y_START		0xc9		/* ext->screen, 16 bits			*/
+#define EXT_Y_END		0xcb		/* ext->screen, 16 bits			*/
+#define EXT_SRC_WIN_WIDTH	0xcd		/* 8 bits				*/
+#define EXT_COLOUR_COMPARE	0xce		/* 24 bits				*/
+#define EXT_DDA_X_INIT		0xd1		/* ext->screen 16 bits			*/
+#define EXT_DDA_X_INC		0xd3		/* ext->screen 16 bits			*/
+#define EXT_DDA_Y_INIT		0xd5		/* ext->screen 16 bits			*/
+#define EXT_DDA_Y_INC		0xd7		/* ext->screen 16 bits			*/
+
+#define EXT_VID_FIFO_CTL	0xd9
+
+#define EXT_VID_FMT		0xdb
+#define EXT_VID_FMT_YUV422		0x00	/* formats - does this cause conversion? */
+#define EXT_VID_FMT_RGB555		0x01
+#define EXT_VID_FMT_RGB565		0x02
+#define EXT_VID_FMT_RGB888_24		0x03
+#define EXT_VID_FMT_RGB888_32		0x04
+#define EXT_VID_FMT_RGB8		0x05
+#define EXT_VID_FMT_RGB4444		0x06
+#define EXT_VID_FMT_RGB8T		0x07
+#define EXT_VID_FMT_DUP_PIX_ZOON	0x08	/* duplicate pixel zoom			*/
+#define EXT_VID_FMT_MOD_3RD_PIX		0x20	/* modify 3rd duplicated pixel		*/
+#define EXT_VID_FMT_DBL_H_PIX		0x40	/* double horiz pixels			*/
+#define EXT_VID_FMT_YUV128		0x80	/* YUV data offset by 128		*/
+
+#define EXT_VID_DISP_CTL1	0xdc
+#define EXT_VID_DISP_CTL1_INTRAM	0x01	/* video pixels go to internal RAM	*/
+#define EXT_VID_DISP_CTL1_IGNORE_CCOMP	0x02	/* ignore colour compare registers	*/
+#define EXT_VID_DISP_CTL1_NOCLIP	0x04	/* do not clip to 16235,16240		*/
+#define EXT_VID_DISP_CTL1_UV_AVG	0x08	/* U/V data is averaged			*/
+#define EXT_VID_DISP_CTL1_Y128		0x10	/* Y data offset by 128 (if YUV128 set)	*/
+#define EXT_VID_DISP_CTL1_VINTERPOL_OFF	0x20	/* disable vertical interpolation	*/
+#define EXT_VID_DISP_CTL1_FULL_WIN	0x40	/* video out window full		*/
+#define EXT_VID_DISP_CTL1_ENABLE_WINDOW	0x80	/* enable video window			*/
+
+#define EXT_VID_FIFO_CTL1	0xdd
+#define EXT_VID_FIFO_CTL1_OE_HIGH	0x02
+#define EXT_VID_FIFO_CTL1_INTERLEAVE	0x04	/* enable interleaved memory read	*/
+
+#define EXT_ROM_UCB4GH		0xe5
+#define EXT_ROM_UCB4GH_FREEZE		0x02	/* capture frozen			*/
+#define EXT_ROM_UCB4GH_ODDFRAME		0x04	/* 1 = odd frame captured		*/
+#define EXT_ROM_UCB4GH_1HL		0x08	/* first horizonal line after VGT falling edge */
+#define EXT_ROM_UCB4GH_ODD		0x10	/* odd frame indicator			*/
+#define EXT_ROM_UCB4GH_INTSTAT		0x20	/* video interrupt			*/
+
+#define VFAC_CTL1		0xe8
+#define VFAC_CTL1_CAPTURE		0x01	/* capture enable (only when VSYNC high)*/
+#define VFAC_CTL1_VFAC_ENABLE		0x02	/* vfac enable				*/
+#define VFAC_CTL1_FREEZE_CAPTURE	0x04	/* freeze capture			*/
+#define VFAC_CTL1_FREEZE_CAPTURE_SYNC	0x08	/* sync freeze capture			*/
+#define VFAC_CTL1_VALIDFRAME_SRC	0x10	/* select valid frame source		*/
+#define VFAC_CTL1_PHILIPS		0x40	/* select Philips mode			*/
+#define VFAC_CTL1_MODVINTERPOLCLK	0x80	/* modify vertical interpolation clocl	*/
+
+#define VFAC_CTL2		0xe9
+#define VFAC_CTL2_INVERT_VIDDATAVALID	0x01	/* invert video data valid		*/
+#define VFAC_CTL2_INVERT_GRAPHREADY	0x02	/* invert graphic ready output sig	*/
+#define VFAC_CTL2_INVERT_DATACLK	0x04	/* invert data clock signal		*/
+#define VFAC_CTL2_INVERT_HSYNC		0x08	/* invert hsync input			*/
+#define VFAC_CTL2_INVERT_VSYNC		0x10	/* invert vsync input			*/
+#define VFAC_CTL2_INVERT_FRAME		0x20	/* invert frame odd/even input		*/
+#define VFAC_CTL2_INVERT_BLANK		0x40	/* invert blank output			*/
+#define VFAC_CTL2_INVERT_OVSYNC		0x80	/* invert other vsync input		*/
+
+#define VFAC_CTL3		0xea
+#define VFAC_CTL3_CAP_LARGE_FIFO	0x01	/* large capture fifo			*/
+#define VFAC_CTL3_CAP_INTERLACE		0x02	/* capture odd and even fields		*/
+#define VFAC_CTL3_CAP_HOLD_4NS		0x00	/* hold capture data for 4ns		*/
+#define VFAC_CTL3_CAP_HOLD_2NS		0x04	/* hold capture data for 2ns		*/
+#define VFAC_CTL3_CAP_HOLD_6NS		0x08	/* hold capture data for 6ns		*/
+#define VFAC_CTL3_CAP_HOLD_0NS		0x0c	/* hold capture data for 0ns		*/
+#define VFAC_CTL3_CHROMAKEY		0x20	/* capture data will be chromakeyed	*/
+#define VFAC_CTL3_CAP_IRQ		0x40	/* enable capture interrupt		*/
+
+#define CAP_MEM_START		0xeb		/* 18 bits				*/
+#define CAP_MAP_WIDTH		0xed		/* high 6 bits				*/
+#define CAP_PITCH		0xee		/* 8 bits				*/
+
+#define CAP_CTL_MISC		0xef
+#define CAP_CTL_MISC_HDIV		0x01
+#define CAP_CTL_MISC_HDIV4		0x02
+#define CAP_CTL_MISC_ODDEVEN		0x04
+#define CAP_CTL_MISC_HSYNCDIV2		0x08
+#define CAP_CTL_MISC_SYNCTZHIGH		0x10
+#define CAP_CTL_MISC_SYNCTZOR		0x20
+#define CAP_CTL_MISC_DISPUSED		0x80
+
+#define REG_BANK		0xfa
+#define REG_BANK_X			0x00
+#define REG_BANK_Y			0x01
+#define REG_BANK_W			0x02
+#define REG_BANK_T			0x03
+#define REG_BANK_J			0x04
+#define REG_BANK_K			0x05
+
+/*
+ * Bus-master
+ */
+#define BM_VID_ADDR_LOW		0xbc040
+#define BM_VID_ADDR_HIGH	0xbc044
+#define BM_ADDRESS_LOW		0xbc080
+#define BM_ADDRESS_HIGH		0xbc084
+#define BM_LENGTH		0xbc088
+#define BM_CONTROL		0xbc08c
+#define BM_CONTROL_ENABLE		0x01	/* enable transfer			*/
+#define BM_CONTROL_IRQEN		0x02	/* enable IRQ at end of transfer	*/
+#define BM_CONTROL_INIT			0x04	/* initialise status & count		*/
+#define BM_COUNT		0xbc090		/* read-only				*/
+
+/*
+ * TV registers
+ */
+#define TV_VBLANK_EVEN_START	0xbe43c
+#define TV_VBLANK_EVEN_END	0xbe440
+#define TV_VBLANK_ODD_START	0xbe444
+#define TV_VBLANK_ODD_END	0xbe448
+#define TV_SYNC_YGAIN		0xbe44c
+#define TV_UV_GAIN		0xbe450
+#define TV_PED_UVDET		0xbe454
+#define TV_UV_BURST_AMP		0xbe458
+#define TV_HSYNC_START		0xbe45c
+#define TV_HSYNC_END		0xbe460
+#define TV_Y_DELAY1		0xbe464
+#define TV_Y_DELAY2		0xbe468
+#define TV_UV_DELAY1		0xbe46c
+#define TV_BURST_START		0xbe470
+#define TV_BURST_END		0xbe474
+#define TV_HBLANK_START		0xbe478
+#define TV_HBLANK_END		0xbe47c
+#define TV_PED_EVEN_START	0xbe480
+#define TV_PED_EVEN_END		0xbe484
+#define TV_PED_ODD_START	0xbe488
+#define TV_PED_ODD_END		0xbe48c
+#define TV_VSYNC_EVEN_START	0xbe490
+#define TV_VSYNC_EVEN_END	0xbe494
+#define TV_VSYNC_ODD_START	0xbe498
+#define TV_VSYNC_ODD_END	0xbe49c
+#define TV_SCFL			0xbe4a0
+#define TV_SCFH			0xbe4a4
+#define TV_SCP			0xbe4a8
+#define TV_DELAYBYPASS		0xbe4b4
+#define TV_EQL_END		0xbe4bc
+#define TV_SERR_START		0xbe4c0
+#define TV_SERR_END		0xbe4c4
+#define TV_CTL			0xbe4dc	/* reflects a previous register- MVFCLR, MVPCLR etc P241*/
+#define TV_VSYNC_VGA_HS		0xbe4e8
+#define TV_FLICK_XMIN		0xbe514
+#define TV_FLICK_XMAX		0xbe518
+#define TV_FLICK_YMIN		0xbe51c
+#define TV_FLICK_YMAX		0xbe520
+
+/*
+ * Graphics Co-processor
+ */
+#define CO_REG_CONTROL		0xbf011
+#define CO_CTRL_BUSY			0x80
+#define CO_CTRL_CMDFULL			0x04
+#define CO_CTRL_FIFOEMPTY		0x02
+#define CO_CTRL_READY			0x01
+
+#define CO_REG_SRC_WIDTH	0xbf018
+#define CO_REG_PIXFMT		0xbf01c
+#define CO_PIXFMT_32BPP			0x03
+#define CO_PIXFMT_24BPP			0x02
+#define CO_PIXFMT_16BPP			0x01
+#define CO_PIXFMT_8BPP			0x00
+
+#define CO_REG_FGMIX		0xbf048
+#define CO_FG_MIX_ZERO			0x00
+#define CO_FG_MIX_SRC_AND_DST		0x01
+#define CO_FG_MIX_SRC_AND_NDST		0x02
+#define CO_FG_MIX_SRC			0x03
+#define CO_FG_MIX_NSRC_AND_DST		0x04
+#define CO_FG_MIX_DST			0x05
+#define CO_FG_MIX_SRC_XOR_DST		0x06
+#define CO_FG_MIX_SRC_OR_DST		0x07
+#define CO_FG_MIX_NSRC_AND_NDST		0x08
+#define CO_FG_MIX_SRC_XOR_NDST		0x09
+#define CO_FG_MIX_NDST			0x0a
+#define CO_FG_MIX_SRC_OR_NDST		0x0b
+#define CO_FG_MIX_NSRC			0x0c
+#define CO_FG_MIX_NSRC_OR_DST		0x0d
+#define CO_FG_MIX_NSRC_OR_NDST		0x0e
+#define CO_FG_MIX_ONES			0x0f
+
+#define CO_REG_FGCOLOUR		0xbf058
+#define CO_REG_BGCOLOUR		0xbf05c
+#define CO_REG_PIXWIDTH		0xbf060
+#define CO_REG_PIXHEIGHT	0xbf062
+#define CO_REG_X_PHASE		0xbf078
+#define CO_REG_CMD_L		0xbf07c
+#define CO_CMD_L_PATTERN_FGCOL		0x8000
+#define CO_CMD_L_INC_LEFT		0x0004
+#define CO_CMD_L_INC_UP			0x0002
+
+#define CO_REG_CMD_H		0xbf07e
+#define CO_CMD_H_BGSRCMAP		0x8000	/* otherwise bg colour */
+#define CO_CMD_H_FGSRCMAP		0x2000	/* otherwise fg colour */
+#define CO_CMD_H_BLITTER		0x0800
+
+#define CO_REG_SRC1_PTR		0xbf170
+#define CO_REG_SRC2_PTR		0xbf174
+#define CO_REG_DEST_PTR		0xbf178
+#define CO_REG_DEST_WIDTH	0xbf218
+
+/*
+ * Private structure
+ */
+struct cfb_info;
+
+struct cyberpro_info {
+	struct device	*dev;
+	struct i2c_adapter *i2c;
+	unsigned char	__iomem *regs;
+	char		__iomem *fb;
+	char		dev_name[32];
+	unsigned int	fb_size;
+	unsigned int	chip_id;
+	unsigned int	irq;
+
+	/*
+	 * The following is a pointer to be passed into the
+	 * functions below.  The modules outside the main
+	 * cyber2000fb.c driver have no knowledge as to what
+	 * is within this structure.
+	 */
+	struct cfb_info *info;
+};
+
+#define ID_IGA_1682		0
+#define ID_CYBERPRO_2000	1
+#define ID_CYBERPRO_2010	2
+#define ID_CYBERPRO_5000	3
+
+/*
+ * Note! Writing to the Cyber20x0 registers from an interrupt
+ * routine is definitely a bad idea atm.
+ */
+int cyber2000fb_attach(struct cyberpro_info *info, int idx);
+void cyber2000fb_detach(int idx);
+void cyber2000fb_enable_extregs(struct cfb_info *cfb);
+void cyber2000fb_disable_extregs(struct cfb_info *cfb);
diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c
new file mode 100644
index 000000000000..6b23508ff0a5
--- /dev/null
+++ b/drivers/video/fbdev/da8xx-fb.c
@@ -0,0 +1,1659 @@
+/*
+ * Copyright (C) 2008-2009 MontaVista Software Inc.
+ * Copyright (C) 2008-2009 Texas Instruments Inc
+ *
+ * Based on the LCD driver for TI Avalanche processors written by
+ * Ajay Singh and Shalom Hai.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option)any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/console.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/lcm.h>
+#include <video/da8xx-fb.h>
+#include <asm/div64.h>
+
+#define DRIVER_NAME "da8xx_lcdc"
+
+#define LCD_VERSION_1	1
+#define LCD_VERSION_2	2
+
+/* LCD Status Register */
+#define LCD_END_OF_FRAME1		BIT(9)
+#define LCD_END_OF_FRAME0		BIT(8)
+#define LCD_PL_LOAD_DONE		BIT(6)
+#define LCD_FIFO_UNDERFLOW		BIT(5)
+#define LCD_SYNC_LOST			BIT(2)
+#define LCD_FRAME_DONE			BIT(0)
+
+/* LCD DMA Control Register */
+#define LCD_DMA_BURST_SIZE(x)		((x) << 4)
+#define LCD_DMA_BURST_1			0x0
+#define LCD_DMA_BURST_2			0x1
+#define LCD_DMA_BURST_4			0x2
+#define LCD_DMA_BURST_8			0x3
+#define LCD_DMA_BURST_16		0x4
+#define LCD_V1_END_OF_FRAME_INT_ENA	BIT(2)
+#define LCD_V2_END_OF_FRAME0_INT_ENA	BIT(8)
+#define LCD_V2_END_OF_FRAME1_INT_ENA	BIT(9)
+#define LCD_DUAL_FRAME_BUFFER_ENABLE	BIT(0)
+
+/* LCD Control Register */
+#define LCD_CLK_DIVISOR(x)		((x) << 8)
+#define LCD_RASTER_MODE			0x01
+
+/* LCD Raster Control Register */
+#define LCD_PALETTE_LOAD_MODE(x)	((x) << 20)
+#define PALETTE_AND_DATA		0x00
+#define PALETTE_ONLY			0x01
+#define DATA_ONLY			0x02
+
+#define LCD_MONO_8BIT_MODE		BIT(9)
+#define LCD_RASTER_ORDER		BIT(8)
+#define LCD_TFT_MODE			BIT(7)
+#define LCD_V1_UNDERFLOW_INT_ENA	BIT(6)
+#define LCD_V2_UNDERFLOW_INT_ENA	BIT(5)
+#define LCD_V1_PL_INT_ENA		BIT(4)
+#define LCD_V2_PL_INT_ENA		BIT(6)
+#define LCD_MONOCHROME_MODE		BIT(1)
+#define LCD_RASTER_ENABLE		BIT(0)
+#define LCD_TFT_ALT_ENABLE		BIT(23)
+#define LCD_STN_565_ENABLE		BIT(24)
+#define LCD_V2_DMA_CLK_EN		BIT(2)
+#define LCD_V2_LIDD_CLK_EN		BIT(1)
+#define LCD_V2_CORE_CLK_EN		BIT(0)
+#define LCD_V2_LPP_B10			26
+#define LCD_V2_TFT_24BPP_MODE		BIT(25)
+#define LCD_V2_TFT_24BPP_UNPACK		BIT(26)
+
+/* LCD Raster Timing 2 Register */
+#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)	((x) << 16)
+#define LCD_AC_BIAS_FREQUENCY(x)		((x) << 8)
+#define LCD_SYNC_CTRL				BIT(25)
+#define LCD_SYNC_EDGE				BIT(24)
+#define LCD_INVERT_PIXEL_CLOCK			BIT(22)
+#define LCD_INVERT_LINE_CLOCK			BIT(21)
+#define LCD_INVERT_FRAME_CLOCK			BIT(20)
+
+/* LCD Block */
+#define  LCD_PID_REG				0x0
+#define  LCD_CTRL_REG				0x4
+#define  LCD_STAT_REG				0x8
+#define  LCD_RASTER_CTRL_REG			0x28
+#define  LCD_RASTER_TIMING_0_REG		0x2C
+#define  LCD_RASTER_TIMING_1_REG		0x30
+#define  LCD_RASTER_TIMING_2_REG		0x34
+#define  LCD_DMA_CTRL_REG			0x40
+#define  LCD_DMA_FRM_BUF_BASE_ADDR_0_REG	0x44
+#define  LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG	0x48
+#define  LCD_DMA_FRM_BUF_BASE_ADDR_1_REG	0x4C
+#define  LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG	0x50
+
+/* Interrupt Registers available only in Version 2 */
+#define  LCD_RAW_STAT_REG			0x58
+#define  LCD_MASKED_STAT_REG			0x5c
+#define  LCD_INT_ENABLE_SET_REG			0x60
+#define  LCD_INT_ENABLE_CLR_REG			0x64
+#define  LCD_END_OF_INT_IND_REG			0x68
+
+/* Clock registers available only on Version 2 */
+#define  LCD_CLK_ENABLE_REG			0x6c
+#define  LCD_CLK_RESET_REG			0x70
+#define  LCD_CLK_MAIN_RESET			BIT(3)
+
+#define LCD_NUM_BUFFERS	2
+
+#define PALETTE_SIZE	256
+
+#define	CLK_MIN_DIV	2
+#define	CLK_MAX_DIV	255
+
+static void __iomem *da8xx_fb_reg_base;
+static unsigned int lcd_revision;
+static irq_handler_t lcdc_irq_handler;
+static wait_queue_head_t frame_done_wq;
+static int frame_done_flag;
+
+static unsigned int lcdc_read(unsigned int addr)
+{
+	return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
+}
+
+static void lcdc_write(unsigned int val, unsigned int addr)
+{
+	__raw_writel(val, da8xx_fb_reg_base + (addr));
+}
+
+struct da8xx_fb_par {
+	struct device		*dev;
+	resource_size_t p_palette_base;
+	unsigned char *v_palette_base;
+	dma_addr_t		vram_phys;
+	unsigned long		vram_size;
+	void			*vram_virt;
+	unsigned int		dma_start;
+	unsigned int		dma_end;
+	struct clk *lcdc_clk;
+	int irq;
+	unsigned int palette_sz;
+	int blank;
+	wait_queue_head_t	vsync_wait;
+	int			vsync_flag;
+	int			vsync_timeout;
+	spinlock_t		lock_for_chan_update;
+
+	/*
+	 * LCDC has 2 ping pong DMA channels, channel 0
+	 * and channel 1.
+	 */
+	unsigned int		which_dma_channel_done;
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+#endif
+	unsigned int		lcdc_clk_rate;
+	void (*panel_power_ctrl)(int);
+	u32 pseudo_palette[16];
+	struct fb_videomode	mode;
+	struct lcd_ctrl_config	cfg;
+};
+
+static struct fb_var_screeninfo da8xx_fb_var;
+
+static struct fb_fix_screeninfo da8xx_fb_fix = {
+	.id = "DA8xx FB Drv",
+	.type = FB_TYPE_PACKED_PIXELS,
+	.type_aux = 0,
+	.visual = FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep = 0,
+	.ypanstep = 1,
+	.ywrapstep = 0,
+	.accel = FB_ACCEL_NONE
+};
+
+static struct fb_videomode known_lcd_panels[] = {
+	/* Sharp LCD035Q3DG01 */
+	[0] = {
+		.name           = "Sharp_LCD035Q3DG01",
+		.xres           = 320,
+		.yres           = 240,
+		.pixclock       = KHZ2PICOS(4607),
+		.left_margin    = 6,
+		.right_margin   = 8,
+		.upper_margin   = 2,
+		.lower_margin   = 2,
+		.hsync_len      = 0,
+		.vsync_len      = 0,
+		.sync           = FB_SYNC_CLK_INVERT |
+			FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	},
+	/* Sharp LK043T1DG01 */
+	[1] = {
+		.name           = "Sharp_LK043T1DG01",
+		.xres           = 480,
+		.yres           = 272,
+		.pixclock       = KHZ2PICOS(7833),
+		.left_margin    = 2,
+		.right_margin   = 2,
+		.upper_margin   = 2,
+		.lower_margin   = 2,
+		.hsync_len      = 41,
+		.vsync_len      = 10,
+		.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.flag           = 0,
+	},
+	[2] = {
+		/* Hitachi SP10Q010 */
+		.name           = "SP10Q010",
+		.xres           = 320,
+		.yres           = 240,
+		.pixclock       = KHZ2PICOS(7833),
+		.left_margin    = 10,
+		.right_margin   = 10,
+		.upper_margin   = 10,
+		.lower_margin   = 10,
+		.hsync_len      = 10,
+		.vsync_len      = 10,
+		.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.flag           = 0,
+	},
+};
+
+static bool da8xx_fb_is_raster_enabled(void)
+{
+	return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE);
+}
+
+/* Enable the Raster Engine of the LCD Controller */
+static void lcd_enable_raster(void)
+{
+	u32 reg;
+
+	/* Put LCDC in reset for several cycles */
+	if (lcd_revision == LCD_VERSION_2)
+		/* Write 1 to reset LCDC */
+		lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
+	mdelay(1);
+
+	/* Bring LCDC out of reset */
+	if (lcd_revision == LCD_VERSION_2)
+		lcdc_write(0, LCD_CLK_RESET_REG);
+	mdelay(1);
+
+	/* Above reset sequence doesnot reset register context */
+	reg = lcdc_read(LCD_RASTER_CTRL_REG);
+	if (!(reg & LCD_RASTER_ENABLE))
+		lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+}
+
+/* Disable the Raster Engine of the LCD Controller */
+static void lcd_disable_raster(enum da8xx_frame_complete wait_for_frame_done)
+{
+	u32 reg;
+	int ret;
+
+	reg = lcdc_read(LCD_RASTER_CTRL_REG);
+	if (reg & LCD_RASTER_ENABLE)
+		lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+	else
+		/* return if already disabled */
+		return;
+
+	if ((wait_for_frame_done == DA8XX_FRAME_WAIT) &&
+			(lcd_revision == LCD_VERSION_2)) {
+		frame_done_flag = 0;
+		ret = wait_event_interruptible_timeout(frame_done_wq,
+				frame_done_flag != 0,
+				msecs_to_jiffies(50));
+		if (ret == 0)
+			pr_err("LCD Controller timed out\n");
+	}
+}
+
+static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
+{
+	u32 start;
+	u32 end;
+	u32 reg_ras;
+	u32 reg_dma;
+	u32 reg_int;
+
+	/* init reg to clear PLM (loading mode) fields */
+	reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
+	reg_ras &= ~(3 << 20);
+
+	reg_dma  = lcdc_read(LCD_DMA_CTRL_REG);
+
+	if (load_mode == LOAD_DATA) {
+		start    = par->dma_start;
+		end      = par->dma_end;
+
+		reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
+		if (lcd_revision == LCD_VERSION_1) {
+			reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
+		} else {
+			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+				LCD_V2_END_OF_FRAME0_INT_ENA |
+				LCD_V2_END_OF_FRAME1_INT_ENA |
+				LCD_FRAME_DONE | LCD_SYNC_LOST;
+			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+		}
+		reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
+
+		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+		lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+		lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+	} else if (load_mode == LOAD_PALETTE) {
+		start    = par->p_palette_base;
+		end      = start + par->palette_sz - 1;
+
+		reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
+
+		if (lcd_revision == LCD_VERSION_1) {
+			reg_ras |= LCD_V1_PL_INT_ENA;
+		} else {
+			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+				LCD_V2_PL_INT_ENA;
+			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+		}
+
+		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+		lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+	}
+
+	lcdc_write(reg_dma, LCD_DMA_CTRL_REG);
+	lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
+
+	/*
+	 * The Raster enable bit must be set after all other control fields are
+	 * set.
+	 */
+	lcd_enable_raster();
+}
+
+/* Configure the Burst Size and fifo threhold of DMA */
+static int lcd_cfg_dma(int burst_size, int fifo_th)
+{
+	u32 reg;
+
+	reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001;
+	switch (burst_size) {
+	case 1:
+		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1);
+		break;
+	case 2:
+		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2);
+		break;
+	case 4:
+		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4);
+		break;
+	case 8:
+		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
+		break;
+	case 16:
+	default:
+		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
+		break;
+	}
+
+	reg |= (fifo_th << 8);
+
+	lcdc_write(reg, LCD_DMA_CTRL_REG);
+
+	return 0;
+}
+
+static void lcd_cfg_ac_bias(int period, int transitions_per_int)
+{
+	u32 reg;
+
+	/* Set the AC Bias Period and Number of Transisitons per Interrupt */
+	reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000;
+	reg |= LCD_AC_BIAS_FREQUENCY(period) |
+		LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int);
+	lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
+}
+
+static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
+		int front_porch)
+{
+	u32 reg;
+
+	reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf;
+	reg |= (((back_porch-1) & 0xff) << 24)
+	    | (((front_porch-1) & 0xff) << 16)
+	    | (((pulse_width-1) & 0x3f) << 10);
+	lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
+
+	/*
+	 * LCDC Version 2 adds some extra bits that increase the allowable
+	 * size of the horizontal timing registers.
+	 * remember that the registers use 0 to represent 1 so all values
+	 * that get set into register need to be decremented by 1
+	 */
+	if (lcd_revision == LCD_VERSION_2) {
+		/* Mask off the bits we want to change */
+		reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & ~0x780000ff;
+		reg |= ((front_porch-1) & 0x300) >> 8;
+		reg |= ((back_porch-1) & 0x300) >> 4;
+		reg |= ((pulse_width-1) & 0x3c0) << 21;
+		lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
+	}
+}
+
+static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
+		int front_porch)
+{
+	u32 reg;
+
+	reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff;
+	reg |= ((back_porch & 0xff) << 24)
+	    | ((front_porch & 0xff) << 16)
+	    | (((pulse_width-1) & 0x3f) << 10);
+	lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
+}
+
+static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
+		struct fb_videomode *panel)
+{
+	u32 reg;
+	u32 reg_int;
+
+	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
+						LCD_MONO_8BIT_MODE |
+						LCD_MONOCHROME_MODE);
+
+	switch (cfg->panel_shade) {
+	case MONOCHROME:
+		reg |= LCD_MONOCHROME_MODE;
+		if (cfg->mono_8bit_mode)
+			reg |= LCD_MONO_8BIT_MODE;
+		break;
+	case COLOR_ACTIVE:
+		reg |= LCD_TFT_MODE;
+		if (cfg->tft_alt_mode)
+			reg |= LCD_TFT_ALT_ENABLE;
+		break;
+
+	case COLOR_PASSIVE:
+		/* AC bias applicable only for Pasive panels */
+		lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
+		if (cfg->bpp == 12 && cfg->stn_565_mode)
+			reg |= LCD_STN_565_ENABLE;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* enable additional interrupts here */
+	if (lcd_revision == LCD_VERSION_1) {
+		reg |= LCD_V1_UNDERFLOW_INT_ENA;
+	} else {
+		reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+			LCD_V2_UNDERFLOW_INT_ENA;
+		lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+	}
+
+	lcdc_write(reg, LCD_RASTER_CTRL_REG);
+
+	reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
+
+	reg |= LCD_SYNC_CTRL;
+
+	if (cfg->sync_edge)
+		reg |= LCD_SYNC_EDGE;
+	else
+		reg &= ~LCD_SYNC_EDGE;
+
+	if ((panel->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
+		reg |= LCD_INVERT_LINE_CLOCK;
+	else
+		reg &= ~LCD_INVERT_LINE_CLOCK;
+
+	if ((panel->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
+		reg |= LCD_INVERT_FRAME_CLOCK;
+	else
+		reg &= ~LCD_INVERT_FRAME_CLOCK;
+
+	lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
+
+	return 0;
+}
+
+static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
+		u32 bpp, u32 raster_order)
+{
+	u32 reg;
+
+	if (bpp > 16 && lcd_revision == LCD_VERSION_1)
+		return -EINVAL;
+
+	/* Set the Panel Width */
+	/* Pixels per line = (PPL + 1)*16 */
+	if (lcd_revision == LCD_VERSION_1) {
+		/*
+		 * 0x3F in bits 4..9 gives max horizontal resolution = 1024
+		 * pixels.
+		 */
+		width &= 0x3f0;
+	} else {
+		/*
+		 * 0x7F in bits 4..10 gives max horizontal resolution = 2048
+		 * pixels.
+		 */
+		width &= 0x7f0;
+	}
+
+	reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
+	reg &= 0xfffffc00;
+	if (lcd_revision == LCD_VERSION_1) {
+		reg |= ((width >> 4) - 1) << 4;
+	} else {
+		width = (width >> 4) - 1;
+		reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3);
+	}
+	lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
+
+	/* Set the Panel Height */
+	/* Set bits 9:0 of Lines Per Pixel */
+	reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
+	reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
+	lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
+
+	/* Set bit 10 of Lines Per Pixel */
+	if (lcd_revision == LCD_VERSION_2) {
+		reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
+		reg |= ((height - 1) & 0x400) << 16;
+		lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
+	}
+
+	/* Set the Raster Order of the Frame Buffer */
+	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
+	if (raster_order)
+		reg |= LCD_RASTER_ORDER;
+
+	par->palette_sz = 16 * 2;
+
+	switch (bpp) {
+	case 1:
+	case 2:
+	case 4:
+	case 16:
+		break;
+	case 24:
+		reg |= LCD_V2_TFT_24BPP_MODE;
+		break;
+	case 32:
+		reg |= LCD_V2_TFT_24BPP_MODE;
+		reg |= LCD_V2_TFT_24BPP_UNPACK;
+		break;
+	case 8:
+		par->palette_sz = 256 * 2;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	lcdc_write(reg, LCD_RASTER_CTRL_REG);
+
+	return 0;
+}
+
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
+static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *info)
+{
+	struct da8xx_fb_par *par = info->par;
+	unsigned short *palette = (unsigned short *) par->v_palette_base;
+	u_short pal;
+	int update_hw = 0;
+
+	if (regno > 255)
+		return 1;
+
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		return 1;
+
+	if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
+		return -EINVAL;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		break;
+	case FB_VISUAL_PSEUDOCOLOR:
+		switch (info->var.bits_per_pixel) {
+		case 4:
+			if (regno > 15)
+				return -EINVAL;
+
+			if (info->var.grayscale) {
+				pal = regno;
+			} else {
+				red >>= 4;
+				green >>= 8;
+				blue >>= 12;
+
+				pal = red & 0x0f00;
+				pal |= green & 0x00f0;
+				pal |= blue & 0x000f;
+			}
+			if (regno == 0)
+				pal |= 0x2000;
+			palette[regno] = pal;
+			break;
+
+		case 8:
+			red >>= 4;
+			green >>= 8;
+			blue >>= 12;
+
+			pal = (red & 0x0f00);
+			pal |= (green & 0x00f0);
+			pal |= (blue & 0x000f);
+
+			if (palette[regno] != pal) {
+				update_hw = 1;
+				palette[regno] = pal;
+			}
+			break;
+		}
+		break;
+	}
+
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno > 15)
+			return -EINVAL;
+
+		v = (red << info->var.red.offset) |
+			(green << info->var.green.offset) |
+			(blue << info->var.blue.offset);
+
+		((u32 *) (info->pseudo_palette))[regno] = v;
+		if (palette[0] != 0x4000) {
+			update_hw = 1;
+			palette[0] = 0x4000;
+		}
+	}
+
+	/* Update the palette in the h/w as needed. */
+	if (update_hw)
+		lcd_blit(LOAD_PALETTE, par);
+
+	return 0;
+}
+#undef CNVT_TOHW
+
+static void da8xx_fb_lcd_reset(void)
+{
+	/* DMA has to be disabled */
+	lcdc_write(0, LCD_DMA_CTRL_REG);
+	lcdc_write(0, LCD_RASTER_CTRL_REG);
+
+	if (lcd_revision == LCD_VERSION_2) {
+		lcdc_write(0, LCD_INT_ENABLE_SET_REG);
+		/* Write 1 to reset */
+		lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
+		lcdc_write(0, LCD_CLK_RESET_REG);
+	}
+}
+
+static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par,
+					      unsigned lcdc_clk_div,
+					      unsigned lcdc_clk_rate)
+{
+	int ret;
+
+	if (par->lcdc_clk_rate != lcdc_clk_rate) {
+		ret = clk_set_rate(par->lcdc_clk, lcdc_clk_rate);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(par->dev,
+				"unable to set clock rate at %u\n",
+				lcdc_clk_rate);
+			return ret;
+		}
+		par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
+	}
+
+	/* Configure the LCD clock divisor. */
+	lcdc_write(LCD_CLK_DIVISOR(lcdc_clk_div) |
+			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+
+	if (lcd_revision == LCD_VERSION_2)
+		lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
+				LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
+
+	return 0;
+}
+
+static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
+					      unsigned pixclock,
+					      unsigned *lcdc_clk_rate)
+{
+	unsigned lcdc_clk_div;
+
+	pixclock = PICOS2KHZ(pixclock) * 1000;
+
+	*lcdc_clk_rate = par->lcdc_clk_rate;
+
+	if (pixclock < (*lcdc_clk_rate / CLK_MAX_DIV)) {
+		*lcdc_clk_rate = clk_round_rate(par->lcdc_clk,
+						pixclock * CLK_MAX_DIV);
+		lcdc_clk_div = CLK_MAX_DIV;
+	} else if (pixclock > (*lcdc_clk_rate / CLK_MIN_DIV)) {
+		*lcdc_clk_rate = clk_round_rate(par->lcdc_clk,
+						pixclock * CLK_MIN_DIV);
+		lcdc_clk_div = CLK_MIN_DIV;
+	} else {
+		lcdc_clk_div = *lcdc_clk_rate / pixclock;
+	}
+
+	return lcdc_clk_div;
+}
+
+static int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+					    struct fb_videomode *mode)
+{
+	unsigned lcdc_clk_rate;
+	unsigned lcdc_clk_div = da8xx_fb_calc_clk_divider(par, mode->pixclock,
+							  &lcdc_clk_rate);
+
+	return da8xx_fb_config_clk_divider(par, lcdc_clk_div, lcdc_clk_rate);
+}
+
+static unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+					  unsigned pixclock)
+{
+	unsigned lcdc_clk_div, lcdc_clk_rate;
+
+	lcdc_clk_div = da8xx_fb_calc_clk_divider(par, pixclock, &lcdc_clk_rate);
+	return KHZ2PICOS(lcdc_clk_rate / (1000 * lcdc_clk_div));
+}
+
+static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
+		struct fb_videomode *panel)
+{
+	u32 bpp;
+	int ret = 0;
+
+	ret = da8xx_fb_calc_config_clk_divider(par, panel);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(par->dev, "unable to configure clock\n");
+		return ret;
+	}
+
+	if (panel->sync & FB_SYNC_CLK_INVERT)
+		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
+			LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
+	else
+		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
+			~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
+
+	/* Configure the DMA burst size and fifo threshold. */
+	ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th);
+	if (ret < 0)
+		return ret;
+
+	/* Configure the vertical and horizontal sync properties. */
+	lcd_cfg_vertical_sync(panel->upper_margin, panel->vsync_len,
+			panel->lower_margin);
+	lcd_cfg_horizontal_sync(panel->left_margin, panel->hsync_len,
+			panel->right_margin);
+
+	/* Configure for disply */
+	ret = lcd_cfg_display(cfg, panel);
+	if (ret < 0)
+		return ret;
+
+	bpp = cfg->bpp;
+
+	if (bpp == 12)
+		bpp = 16;
+	ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
+				(unsigned int)panel->yres, bpp,
+				cfg->raster_order);
+	if (ret < 0)
+		return ret;
+
+	/* Configure FDD */
+	lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) |
+		       (cfg->fdd << 12), LCD_RASTER_CTRL_REG);
+
+	return 0;
+}
+
+/* IRQ handler for version 2 of LCDC */
+static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
+{
+	struct da8xx_fb_par *par = arg;
+	u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
+
+	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
+		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
+		lcdc_write(stat, LCD_MASKED_STAT_REG);
+		lcd_enable_raster();
+	} else if (stat & LCD_PL_LOAD_DONE) {
+		/*
+		 * Must disable raster before changing state of any control bit.
+		 * And also must be disabled before clearing the PL loading
+		 * interrupt via the following write to the status register. If
+		 * this is done after then one gets multiple PL done interrupts.
+		 */
+		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
+
+		lcdc_write(stat, LCD_MASKED_STAT_REG);
+
+		/* Disable PL completion interrupt */
+		lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG);
+
+		/* Setup and start data loading mode */
+		lcd_blit(LOAD_DATA, par);
+	} else {
+		lcdc_write(stat, LCD_MASKED_STAT_REG);
+
+		if (stat & LCD_END_OF_FRAME0) {
+			par->which_dma_channel_done = 0;
+			lcdc_write(par->dma_start,
+				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+			lcdc_write(par->dma_end,
+				   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+			par->vsync_flag = 1;
+			wake_up_interruptible(&par->vsync_wait);
+		}
+
+		if (stat & LCD_END_OF_FRAME1) {
+			par->which_dma_channel_done = 1;
+			lcdc_write(par->dma_start,
+				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+			lcdc_write(par->dma_end,
+				   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+			par->vsync_flag = 1;
+			wake_up_interruptible(&par->vsync_wait);
+		}
+
+		/* Set only when controller is disabled and at the end of
+		 * active frame
+		 */
+		if (stat & BIT(0)) {
+			frame_done_flag = 1;
+			wake_up_interruptible(&frame_done_wq);
+		}
+	}
+
+	lcdc_write(0, LCD_END_OF_INT_IND_REG);
+	return IRQ_HANDLED;
+}
+
+/* IRQ handler for version 1 LCDC */
+static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
+{
+	struct da8xx_fb_par *par = arg;
+	u32 stat = lcdc_read(LCD_STAT_REG);
+	u32 reg_ras;
+
+	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
+		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
+		lcdc_write(stat, LCD_STAT_REG);
+		lcd_enable_raster();
+	} else if (stat & LCD_PL_LOAD_DONE) {
+		/*
+		 * Must disable raster before changing state of any control bit.
+		 * And also must be disabled before clearing the PL loading
+		 * interrupt via the following write to the status register. If
+		 * this is done after then one gets multiple PL done interrupts.
+		 */
+		lcd_disable_raster(DA8XX_FRAME_NOWAIT);
+
+		lcdc_write(stat, LCD_STAT_REG);
+
+		/* Disable PL completion inerrupt */
+		reg_ras  = lcdc_read(LCD_RASTER_CTRL_REG);
+		reg_ras &= ~LCD_V1_PL_INT_ENA;
+		lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
+
+		/* Setup and start data loading mode */
+		lcd_blit(LOAD_DATA, par);
+	} else {
+		lcdc_write(stat, LCD_STAT_REG);
+
+		if (stat & LCD_END_OF_FRAME0) {
+			par->which_dma_channel_done = 0;
+			lcdc_write(par->dma_start,
+				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+			lcdc_write(par->dma_end,
+				   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+			par->vsync_flag = 1;
+			wake_up_interruptible(&par->vsync_wait);
+		}
+
+		if (stat & LCD_END_OF_FRAME1) {
+			par->which_dma_channel_done = 1;
+			lcdc_write(par->dma_start,
+				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+			lcdc_write(par->dma_end,
+				   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+			par->vsync_flag = 1;
+			wake_up_interruptible(&par->vsync_wait);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int fb_check_var(struct fb_var_screeninfo *var,
+			struct fb_info *info)
+{
+	int err = 0;
+	struct da8xx_fb_par *par = info->par;
+	int bpp = var->bits_per_pixel >> 3;
+	unsigned long line_size = var->xres_virtual * bpp;
+
+	if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
+		return -EINVAL;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->nonstd = 0;
+		break;
+	case 4:
+		var->red.offset = 0;
+		var->red.length = 4;
+		var->green.offset = 0;
+		var->green.length = 4;
+		var->blue.offset = 0;
+		var->blue.length = 4;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->nonstd = FB_NONSTD_REV_PIX_IN_B;
+		break;
+	case 16:		/* RGB 565 */
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->nonstd = 0;
+		break;
+	case 24:
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->nonstd = 0;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->nonstd = 0;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	if (line_size * var->yres_virtual > par->vram_size)
+		var->yres_virtual = par->vram_size / line_size;
+
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+
+	if (var->xres > var->xres_virtual)
+		var->xres = var->xres_virtual;
+
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	var->pixclock = da8xx_fb_round_clk(par, var->pixclock);
+
+	return err;
+}
+
+#ifdef CONFIG_CPU_FREQ
+static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
+				     unsigned long val, void *data)
+{
+	struct da8xx_fb_par *par;
+
+	par = container_of(nb, struct da8xx_fb_par, freq_transition);
+	if (val == CPUFREQ_POSTCHANGE) {
+		if (par->lcdc_clk_rate != clk_get_rate(par->lcdc_clk)) {
+			par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
+			lcd_disable_raster(DA8XX_FRAME_WAIT);
+			da8xx_fb_calc_config_clk_divider(par, &par->mode);
+			if (par->blank == FB_BLANK_UNBLANK)
+				lcd_enable_raster();
+		}
+	}
+
+	return 0;
+}
+
+static int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par)
+{
+	par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition;
+
+	return cpufreq_register_notifier(&par->freq_transition,
+					 CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
+{
+	cpufreq_unregister_notifier(&par->freq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+}
+#endif
+
+static int fb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(&dev->dev);
+
+	if (info) {
+		struct da8xx_fb_par *par = info->par;
+
+#ifdef CONFIG_CPU_FREQ
+		lcd_da8xx_cpufreq_deregister(par);
+#endif
+		if (par->panel_power_ctrl)
+			par->panel_power_ctrl(0);
+
+		lcd_disable_raster(DA8XX_FRAME_WAIT);
+		lcdc_write(0, LCD_RASTER_CTRL_REG);
+
+		/* disable DMA  */
+		lcdc_write(0, LCD_DMA_CTRL_REG);
+
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
+				  par->p_palette_base);
+		dma_free_coherent(NULL, par->vram_size, par->vram_virt,
+				  par->vram_phys);
+		pm_runtime_put_sync(&dev->dev);
+		pm_runtime_disable(&dev->dev);
+		framebuffer_release(info);
+
+	}
+	return 0;
+}
+
+/*
+ * Function to wait for vertical sync which for this LCD peripheral
+ * translates into waiting for the current raster frame to complete.
+ */
+static int fb_wait_for_vsync(struct fb_info *info)
+{
+	struct da8xx_fb_par *par = info->par;
+	int ret;
+
+	/*
+	 * Set flag to 0 and wait for isr to set to 1. It would seem there is a
+	 * race condition here where the ISR could have occurred just before or
+	 * just after this set. But since we are just coarsely waiting for
+	 * a frame to complete then that's OK. i.e. if the frame completed
+	 * just before this code executed then we have to wait another full
+	 * frame time but there is no way to avoid such a situation. On the
+	 * other hand if the frame completed just after then we don't need
+	 * to wait long at all. Either way we are guaranteed to return to the
+	 * user immediately after a frame completion which is all that is
+	 * required.
+	 */
+	par->vsync_flag = 0;
+	ret = wait_event_interruptible_timeout(par->vsync_wait,
+					       par->vsync_flag != 0,
+					       par->vsync_timeout);
+	if (ret < 0)
+		return ret;
+	if (ret == 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int fb_ioctl(struct fb_info *info, unsigned int cmd,
+			  unsigned long arg)
+{
+	struct lcd_sync_arg sync_arg;
+
+	switch (cmd) {
+	case FBIOGET_CONTRAST:
+	case FBIOPUT_CONTRAST:
+	case FBIGET_BRIGHTNESS:
+	case FBIPUT_BRIGHTNESS:
+	case FBIGET_COLOR:
+	case FBIPUT_COLOR:
+		return -ENOTTY;
+	case FBIPUT_HSYNC:
+		if (copy_from_user(&sync_arg, (char *)arg,
+				sizeof(struct lcd_sync_arg)))
+			return -EFAULT;
+		lcd_cfg_horizontal_sync(sync_arg.back_porch,
+					sync_arg.pulse_width,
+					sync_arg.front_porch);
+		break;
+	case FBIPUT_VSYNC:
+		if (copy_from_user(&sync_arg, (char *)arg,
+				sizeof(struct lcd_sync_arg)))
+			return -EFAULT;
+		lcd_cfg_vertical_sync(sync_arg.back_porch,
+					sync_arg.pulse_width,
+					sync_arg.front_porch);
+		break;
+	case FBIO_WAITFORVSYNC:
+		return fb_wait_for_vsync(info);
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cfb_blank(int blank, struct fb_info *info)
+{
+	struct da8xx_fb_par *par = info->par;
+	int ret = 0;
+
+	if (par->blank == blank)
+		return 0;
+
+	par->blank = blank;
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		lcd_enable_raster();
+
+		if (par->panel_power_ctrl)
+			par->panel_power_ctrl(1);
+		break;
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		if (par->panel_power_ctrl)
+			par->panel_power_ctrl(0);
+
+		lcd_disable_raster(DA8XX_FRAME_WAIT);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/*
+ * Set new x,y offsets in the virtual display for the visible area and switch
+ * to the new mode.
+ */
+static int da8xx_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *fbi)
+{
+	int ret = 0;
+	struct fb_var_screeninfo new_var;
+	struct da8xx_fb_par         *par = fbi->par;
+	struct fb_fix_screeninfo    *fix = &fbi->fix;
+	unsigned int end;
+	unsigned int start;
+	unsigned long irq_flags;
+
+	if (var->xoffset != fbi->var.xoffset ||
+			var->yoffset != fbi->var.yoffset) {
+		memcpy(&new_var, &fbi->var, sizeof(new_var));
+		new_var.xoffset = var->xoffset;
+		new_var.yoffset = var->yoffset;
+		if (fb_check_var(&new_var, fbi))
+			ret = -EINVAL;
+		else {
+			memcpy(&fbi->var, &new_var, sizeof(new_var));
+
+			start	= fix->smem_start +
+				new_var.yoffset * fix->line_length +
+				new_var.xoffset * fbi->var.bits_per_pixel / 8;
+			end	= start + fbi->var.yres * fix->line_length - 1;
+			par->dma_start	= start;
+			par->dma_end	= end;
+			spin_lock_irqsave(&par->lock_for_chan_update,
+					irq_flags);
+			if (par->which_dma_channel_done == 0) {
+				lcdc_write(par->dma_start,
+					   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+				lcdc_write(par->dma_end,
+					   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+			} else if (par->which_dma_channel_done == 1) {
+				lcdc_write(par->dma_start,
+					   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+				lcdc_write(par->dma_end,
+					   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+			}
+			spin_unlock_irqrestore(&par->lock_for_chan_update,
+					irq_flags);
+		}
+	}
+
+	return ret;
+}
+
+static int da8xxfb_set_par(struct fb_info *info)
+{
+	struct da8xx_fb_par *par = info->par;
+	int ret;
+	bool raster = da8xx_fb_is_raster_enabled();
+
+	if (raster)
+		lcd_disable_raster(DA8XX_FRAME_WAIT);
+
+	fb_var_to_videomode(&par->mode, &info->var);
+
+	par->cfg.bpp = info->var.bits_per_pixel;
+
+	info->fix.visual = (par->cfg.bpp <= 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8;
+
+	ret = lcd_init(par, &par->cfg, &par->mode);
+	if (ret < 0) {
+		dev_err(par->dev, "lcd init failed\n");
+		return ret;
+	}
+
+	par->dma_start = info->fix.smem_start +
+			 info->var.yoffset * info->fix.line_length +
+			 info->var.xoffset * info->var.bits_per_pixel / 8;
+	par->dma_end   = par->dma_start +
+			 info->var.yres * info->fix.line_length - 1;
+
+	lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+	lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+	lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+	lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+
+	if (raster)
+		lcd_enable_raster();
+
+	return 0;
+}
+
+static struct fb_ops da8xx_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = fb_check_var,
+	.fb_set_par = da8xxfb_set_par,
+	.fb_setcolreg = fb_setcolreg,
+	.fb_pan_display = da8xx_pan_display,
+	.fb_ioctl = fb_ioctl,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_blank = cfb_blank,
+};
+
+static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
+{
+	struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev);
+	struct fb_videomode *lcdc_info;
+	int i;
+
+	for (i = 0, lcdc_info = known_lcd_panels;
+		i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
+		if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(known_lcd_panels)) {
+		dev_err(&dev->dev, "no panel found\n");
+		return NULL;
+	}
+	dev_info(&dev->dev, "found %s panel\n", lcdc_info->name);
+
+	return lcdc_info;
+}
+
+static int fb_probe(struct platform_device *device)
+{
+	struct da8xx_lcdc_platform_data *fb_pdata =
+						dev_get_platdata(&device->dev);
+	static struct resource *lcdc_regs;
+	struct lcd_ctrl_config *lcd_cfg;
+	struct fb_videomode *lcdc_info;
+	struct fb_info *da8xx_fb_info;
+	struct da8xx_fb_par *par;
+	struct clk *tmp_lcdc_clk;
+	int ret;
+	unsigned long ulcm;
+
+	if (fb_pdata == NULL) {
+		dev_err(&device->dev, "Can not get platform data\n");
+		return -ENOENT;
+	}
+
+	lcdc_info = da8xx_fb_get_videomode(device);
+	if (lcdc_info == NULL)
+		return -ENODEV;
+
+	lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
+	da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs);
+	if (IS_ERR(da8xx_fb_reg_base))
+		return PTR_ERR(da8xx_fb_reg_base);
+
+	tmp_lcdc_clk = devm_clk_get(&device->dev, "fck");
+	if (IS_ERR(tmp_lcdc_clk)) {
+		dev_err(&device->dev, "Can not get device clock\n");
+		return PTR_ERR(tmp_lcdc_clk);
+	}
+
+	pm_runtime_enable(&device->dev);
+	pm_runtime_get_sync(&device->dev);
+
+	/* Determine LCD IP Version */
+	switch (lcdc_read(LCD_PID_REG)) {
+	case 0x4C100102:
+		lcd_revision = LCD_VERSION_1;
+		break;
+	case 0x4F200800:
+	case 0x4F201000:
+		lcd_revision = LCD_VERSION_2;
+		break;
+	default:
+		dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
+				"defaulting to LCD revision 1\n",
+				lcdc_read(LCD_PID_REG));
+		lcd_revision = LCD_VERSION_1;
+		break;
+	}
+
+	lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+
+	if (!lcd_cfg) {
+		ret = -EINVAL;
+		goto err_pm_runtime_disable;
+	}
+
+	da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
+					&device->dev);
+	if (!da8xx_fb_info) {
+		dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");
+		ret = -ENOMEM;
+		goto err_pm_runtime_disable;
+	}
+
+	par = da8xx_fb_info->par;
+	par->dev = &device->dev;
+	par->lcdc_clk = tmp_lcdc_clk;
+	par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
+	if (fb_pdata->panel_power_ctrl) {
+		par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
+		par->panel_power_ctrl(1);
+	}
+
+	fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
+	par->cfg = *lcd_cfg;
+
+	da8xx_fb_lcd_reset();
+
+	/* allocate frame buffer */
+	par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
+	ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
+	par->vram_size = roundup(par->vram_size/8, ulcm);
+	par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
+
+	par->vram_virt = dma_alloc_coherent(NULL,
+					    par->vram_size,
+					    (resource_size_t *) &par->vram_phys,
+					    GFP_KERNEL | GFP_DMA);
+	if (!par->vram_virt) {
+		dev_err(&device->dev,
+			"GLCD: kmalloc for frame buffer failed\n");
+		ret = -EINVAL;
+		goto err_release_fb;
+	}
+
+	da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
+	da8xx_fb_fix.smem_start    = par->vram_phys;
+	da8xx_fb_fix.smem_len      = par->vram_size;
+	da8xx_fb_fix.line_length   = (lcdc_info->xres * lcd_cfg->bpp) / 8;
+
+	par->dma_start = par->vram_phys;
+	par->dma_end   = par->dma_start + lcdc_info->yres *
+		da8xx_fb_fix.line_length - 1;
+
+	/* allocate palette buffer */
+	par->v_palette_base = dma_alloc_coherent(NULL,
+					       PALETTE_SIZE,
+					       (resource_size_t *)
+					       &par->p_palette_base,
+					       GFP_KERNEL | GFP_DMA);
+	if (!par->v_palette_base) {
+		dev_err(&device->dev,
+			"GLCD: kmalloc for palette buffer failed\n");
+		ret = -EINVAL;
+		goto err_release_fb_mem;
+	}
+	memset(par->v_palette_base, 0, PALETTE_SIZE);
+
+	par->irq = platform_get_irq(device, 0);
+	if (par->irq < 0) {
+		ret = -ENOENT;
+		goto err_release_pl_mem;
+	}
+
+	da8xx_fb_var.grayscale =
+	    lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
+	da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
+
+	/* Initialize fbinfo */
+	da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
+	da8xx_fb_info->fix = da8xx_fb_fix;
+	da8xx_fb_info->var = da8xx_fb_var;
+	da8xx_fb_info->fbops = &da8xx_fb_ops;
+	da8xx_fb_info->pseudo_palette = par->pseudo_palette;
+	da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+
+	ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
+	if (ret)
+		goto err_release_pl_mem;
+	da8xx_fb_info->cmap.len = par->palette_sz;
+
+	/* initialize var_screeninfo */
+	da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
+	fb_set_var(da8xx_fb_info, &da8xx_fb_var);
+
+	dev_set_drvdata(&device->dev, da8xx_fb_info);
+
+	/* initialize the vsync wait queue */
+	init_waitqueue_head(&par->vsync_wait);
+	par->vsync_timeout = HZ / 5;
+	par->which_dma_channel_done = -1;
+	spin_lock_init(&par->lock_for_chan_update);
+
+	/* Register the Frame Buffer  */
+	if (register_framebuffer(da8xx_fb_info) < 0) {
+		dev_err(&device->dev,
+			"GLCD: Frame Buffer Registration Failed!\n");
+		ret = -EINVAL;
+		goto err_dealloc_cmap;
+	}
+
+#ifdef CONFIG_CPU_FREQ
+	ret = lcd_da8xx_cpufreq_register(par);
+	if (ret) {
+		dev_err(&device->dev, "failed to register cpufreq\n");
+		goto err_cpu_freq;
+	}
+#endif
+
+	if (lcd_revision == LCD_VERSION_1)
+		lcdc_irq_handler = lcdc_irq_handler_rev01;
+	else {
+		init_waitqueue_head(&frame_done_wq);
+		lcdc_irq_handler = lcdc_irq_handler_rev02;
+	}
+
+	ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
+			       DRIVER_NAME, par);
+	if (ret)
+		goto irq_freq;
+	return 0;
+
+irq_freq:
+#ifdef CONFIG_CPU_FREQ
+	lcd_da8xx_cpufreq_deregister(par);
+err_cpu_freq:
+#endif
+	unregister_framebuffer(da8xx_fb_info);
+
+err_dealloc_cmap:
+	fb_dealloc_cmap(&da8xx_fb_info->cmap);
+
+err_release_pl_mem:
+	dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
+			  par->p_palette_base);
+
+err_release_fb_mem:
+	dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys);
+
+err_release_fb:
+	framebuffer_release(da8xx_fb_info);
+
+err_pm_runtime_disable:
+	pm_runtime_put_sync(&device->dev);
+	pm_runtime_disable(&device->dev);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static struct lcdc_context {
+	u32 clk_enable;
+	u32 ctrl;
+	u32 dma_ctrl;
+	u32 raster_timing_0;
+	u32 raster_timing_1;
+	u32 raster_timing_2;
+	u32 int_enable_set;
+	u32 dma_frm_buf_base_addr_0;
+	u32 dma_frm_buf_ceiling_addr_0;
+	u32 dma_frm_buf_base_addr_1;
+	u32 dma_frm_buf_ceiling_addr_1;
+	u32 raster_ctrl;
+} reg_context;
+
+static void lcd_context_save(void)
+{
+	if (lcd_revision == LCD_VERSION_2) {
+		reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG);
+		reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG);
+	}
+
+	reg_context.ctrl = lcdc_read(LCD_CTRL_REG);
+	reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG);
+	reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG);
+	reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG);
+	reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG);
+	reg_context.dma_frm_buf_base_addr_0 =
+		lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+	reg_context.dma_frm_buf_ceiling_addr_0 =
+		lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+	reg_context.dma_frm_buf_base_addr_1 =
+		lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+	reg_context.dma_frm_buf_ceiling_addr_1 =
+		lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+	reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG);
+	return;
+}
+
+static void lcd_context_restore(void)
+{
+	if (lcd_revision == LCD_VERSION_2) {
+		lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG);
+		lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG);
+	}
+
+	lcdc_write(reg_context.ctrl, LCD_CTRL_REG);
+	lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG);
+	lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG);
+	lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG);
+	lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG);
+	lcdc_write(reg_context.dma_frm_buf_base_addr_0,
+			LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+	lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0,
+			LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+	lcdc_write(reg_context.dma_frm_buf_base_addr_1,
+			LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+	lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1,
+			LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+	lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG);
+	return;
+}
+
+static int fb_suspend(struct device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct da8xx_fb_par *par = info->par;
+
+	console_lock();
+	if (par->panel_power_ctrl)
+		par->panel_power_ctrl(0);
+
+	fb_set_suspend(info, 1);
+	lcd_disable_raster(DA8XX_FRAME_WAIT);
+	lcd_context_save();
+	pm_runtime_put_sync(dev);
+	console_unlock();
+
+	return 0;
+}
+static int fb_resume(struct device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct da8xx_fb_par *par = info->par;
+
+	console_lock();
+	pm_runtime_get_sync(dev);
+	lcd_context_restore();
+	if (par->blank == FB_BLANK_UNBLANK) {
+		lcd_enable_raster();
+
+		if (par->panel_power_ctrl)
+			par->panel_power_ctrl(1);
+	}
+
+	fb_set_suspend(info, 0);
+	console_unlock();
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(fb_pm_ops, fb_suspend, fb_resume);
+
+static struct platform_driver da8xx_fb_driver = {
+	.probe = fb_probe,
+	.remove = fb_remove,
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   .pm	= &fb_pm_ops,
+		   },
+};
+module_platform_driver(da8xx_fb_driver);
+
+MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx");
+MODULE_AUTHOR("Texas Instruments");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/dnfb.c b/drivers/video/fbdev/dnfb.c
new file mode 100644
index 000000000000..3526899da61b
--- /dev/null
+++ b/drivers/video/fbdev/dnfb.c
@@ -0,0 +1,303 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/apollohw.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+
+/* apollo video HW definitions */
+
+/*
+ * Control Registers.   IOBASE + $x
+ *
+ * Note: these are the Memory/IO BASE definitions for a mono card set to the
+ * alternate address
+ *
+ * Control 3A and 3B serve identical functions except that 3A
+ * deals with control 1 and 3b deals with Color LUT reg.
+ */
+
+#define AP_IOBASE       0x3b0	/* Base address of 1 plane board. */
+#define AP_STATUS       isaIO2mem(AP_IOBASE+0)	/* Status register.  Read */
+#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0)	/* Write Enable Register Write */
+#define AP_DEVICE_ID    isaIO2mem(AP_IOBASE+1)	/* Device ID Register. Read */
+#define AP_ROP_1        isaIO2mem(AP_IOBASE+2)	/* Raster Operation reg. Write Word */
+#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4)	/* Diagnostic Memory Request. Write Word */
+#define AP_CONTROL_0    isaIO2mem(AP_IOBASE+8)	/* Control Register 0.  Read/Write */
+#define AP_CONTROL_1    isaIO2mem(AP_IOBASE+0xa)	/* Control Register 1.  Read/Write */
+#define AP_CONTROL_3A   isaIO2mem(AP_IOBASE+0xe)	/* Control Register 3a. Read/Write */
+#define AP_CONTROL_2    isaIO2mem(AP_IOBASE+0xc)	/* Control Register 2. Read/Write */
+
+
+#define FRAME_BUFFER_START 0x0FA0000
+#define FRAME_BUFFER_LEN 0x40000
+
+/* CREG 0 */
+#define VECTOR_MODE 0x40	/* 010x.xxxx */
+#define DBLT_MODE   0x80	/* 100x.xxxx */
+#define NORMAL_MODE 0xE0	/* 111x.xxxx */
+#define SHIFT_BITS  0x1F	/* xxx1.1111 */
+	/* other bits are Shift value */
+
+/* CREG 1 */
+#define AD_BLT      0x80	/* 1xxx.xxxx */
+#define NORMAL      0x80 /* 1xxx.xxxx */	/* What is happening here ?? */
+#define INVERSE     0x00 /* 0xxx.xxxx */	/* Clearing this reverses the screen */
+#define PIX_BLT     0x00	/* 0xxx.xxxx */
+
+#define AD_HIBIT        0x40	/* xIxx.xxxx */
+
+#define ROP_EN          0x10	/* xxx1.xxxx */
+#define DST_EQ_SRC      0x00	/* xxx0.xxxx */
+#define nRESET_SYNC     0x08	/* xxxx.1xxx */
+#define SYNC_ENAB       0x02	/* xxxx.xx1x */
+
+#define BLANK_DISP      0x00	/* xxxx.xxx0 */
+#define ENAB_DISP       0x01	/* xxxx.xxx1 */
+
+#define NORM_CREG1      (nRESET_SYNC | SYNC_ENAB | ENAB_DISP)	/* no reset sync */
+
+/* CREG 2 */
+
+/*
+ * Following 3 defines are common to 1, 4 and 8 plane.
+ */
+
+#define S_DATA_1s   0x00 /* 00xx.xxxx */	/* set source to all 1's -- vector drawing */
+#define S_DATA_PIX  0x40 /* 01xx.xxxx */	/* takes source from ls-bits and replicates over 16 bits */
+#define S_DATA_PLN  0xC0 /* 11xx.xxxx */	/* normal, each data access =16-bits in
+						   one plane of image mem */
+
+/* CREG 3A/CREG 3B */
+#       define RESET_CREG 0x80	/* 1000.0000 */
+
+/* ROP REG  -  all one nibble */
+/*      ********* NOTE : this is used r0,r1,r2,r3 *********** */
+#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
+#define DEST_ZERO               0x0
+#define SRC_AND_DEST    0x1
+#define SRC_AND_nDEST   0x2
+#define SRC                             0x3
+#define nSRC_AND_DEST   0x4
+#define DEST                    0x5
+#define SRC_XOR_DEST    0x6
+#define SRC_OR_DEST             0x7
+#define SRC_NOR_DEST    0x8
+#define SRC_XNOR_DEST   0x9
+#define nDEST                   0xA
+#define SRC_OR_nDEST    0xB
+#define nSRC                    0xC
+#define nSRC_OR_DEST    0xD
+#define SRC_NAND_DEST   0xE
+#define DEST_ONE                0xF
+
+#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
+
+/* frame buffer operations */
+
+static int dnfb_blank(int blank, struct fb_info *info);
+static void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+
+static struct fb_ops dn_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_blank	= dnfb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= dnfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+struct fb_var_screeninfo dnfb_var = {
+	.xres		= 1280,
+	.yres		= 1024,
+	.xres_virtual	= 2048,
+	.yres_virtual	= 1024,
+	.bits_per_pixel	= 1,
+	.height		= -1,
+	.width		= -1,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo dnfb_fix = {
+	.id		= "Apollo Mono",
+	.smem_start	= (FRAME_BUFFER_START + IO_BASE),
+	.smem_len	= FRAME_BUFFER_LEN,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_MONO10,
+	.line_length	= 256,
+};
+
+static int dnfb_blank(int blank, struct fb_info *info)
+{
+	if (blank)
+		out_8(AP_CONTROL_3A, 0x0);
+	else
+		out_8(AP_CONTROL_3A, 0x1);
+	return 0;
+}
+
+static
+void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+
+	int incr, y_delta, pre_read = 0, x_end, x_word_count;
+	uint start_mask, end_mask, dest;
+	ushort *src, dummy;
+	short i, j;
+
+	incr = (area->dy <= area->sy) ? 1 : -1;
+
+	src = (ushort *)(info->screen_base + area->sy * info->fix.line_length +
+			(area->sx >> 4));
+	dest = area->dy * (info->fix.line_length >> 1) + (area->dx >> 4);
+
+	if (incr > 0) {
+		y_delta = (info->fix.line_length * 8) - area->sx - area->width;
+		x_end = area->dx + area->width - 1;
+		x_word_count = (x_end >> 4) - (area->dx >> 4) + 1;
+		start_mask = 0xffff0000 >> (area->dx & 0xf);
+		end_mask = 0x7ffff >> (x_end & 0xf);
+		out_8(AP_CONTROL_0,
+		     (((area->dx & 0xf) - (area->sx & 0xf)) % 16) | (0x4 << 5));
+		if ((area->dx & 0xf) < (area->sx & 0xf))
+			pre_read = 1;
+	} else {
+		y_delta = -((info->fix.line_length * 8) - area->sx - area->width);
+		x_end = area->dx - area->width + 1;
+		x_word_count = (area->dx >> 4) - (x_end >> 4) + 1;
+		start_mask = 0x7ffff >> (area->dx & 0xf);
+		end_mask = 0xffff0000 >> (x_end & 0xf);
+		out_8(AP_CONTROL_0,
+		     ((-((area->sx & 0xf) - (area->dx & 0xf))) % 16) |
+		     (0x4 << 5));
+		if ((area->dx & 0xf) > (area->sx & 0xf))
+			pre_read = 1;
+	}
+
+	for (i = 0; i < area->height; i++) {
+
+		out_8(AP_CONTROL_3A, 0xc | (dest >> 16));
+
+		if (pre_read) {
+			dummy = *src;
+			src += incr;
+		}
+
+		if (x_word_count) {
+			out_8(AP_WRITE_ENABLE, start_mask);
+			*src = dest;
+			src += incr;
+			dest += incr;
+			out_8(AP_WRITE_ENABLE, 0);
+
+			for (j = 1; j < (x_word_count - 1); j++) {
+				*src = dest;
+				src += incr;
+				dest += incr;
+			}
+
+			out_8(AP_WRITE_ENABLE, start_mask);
+			*src = dest;
+			dest += incr;
+			src += incr;
+		} else {
+			out_8(AP_WRITE_ENABLE, start_mask | end_mask);
+			*src = dest;
+			dest += incr;
+			src += incr;
+		}
+		src += (y_delta / 16);
+		dest += (y_delta / 16);
+	}
+	out_8(AP_CONTROL_0, NORMAL_MODE);
+}
+
+/*
+ * Initialization
+ */
+
+static int dnfb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int err = 0;
+
+	info = framebuffer_alloc(0, &dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	info->fbops = &dn_fb_ops;
+	info->fix = dnfb_fix;
+	info->var = dnfb_var;
+	info->var.red.length = 1;
+	info->var.red.offset = 0;
+	info->var.green = info->var.blue = info->var.red;
+	info->screen_base = (u_char *) info->fix.smem_start;
+
+	err = fb_alloc_cmap(&info->cmap, 2, 0);
+	if (err < 0) {
+		framebuffer_release(info);
+		return err;
+	}
+
+	err = register_framebuffer(info);
+	if (err < 0) {
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+		return err;
+	}
+	platform_set_drvdata(dev, info);
+
+	/* now we have registered we can safely setup the hardware */
+	out_8(AP_CONTROL_3A, RESET_CREG);
+	out_be16(AP_WRITE_ENABLE, 0x0);
+	out_8(AP_CONTROL_0, NORMAL_MODE);
+	out_8(AP_CONTROL_1, (AD_BLT | DST_EQ_SRC | NORM_CREG1));
+	out_8(AP_CONTROL_2, S_DATA_PLN);
+	out_be16(AP_ROP_1, SWAP(0x3));
+
+	printk("apollo frame buffer alive and kicking !\n");
+	return err;
+}
+
+static struct platform_driver dnfb_driver = {
+	.probe	= dnfb_probe,
+	.driver	= {
+		.name	= "dnfb",
+	},
+};
+
+static struct platform_device dnfb_device = {
+	.name	= "dnfb",
+};
+
+int __init dnfb_init(void)
+{
+	int ret;
+
+	if (!MACH_IS_APOLLO)
+		return -ENODEV;
+
+	if (fb_get_options("dnfb", NULL))
+		return -ENODEV;
+
+	ret = platform_driver_register(&dnfb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&dnfb_device);
+		if (ret)
+			platform_driver_unregister(&dnfb_driver);
+	}
+	return ret;
+}
+
+module_init(dnfb_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/edid.h b/drivers/video/fbdev/edid.h
new file mode 100644
index 000000000000..d03a232d90b2
--- /dev/null
+++ b/drivers/video/fbdev/edid.h
@@ -0,0 +1,138 @@
+/* 
+ * drivers/video/edid.h - EDID/DDC Header
+ *
+ * Based on:
+ *   1. XFree86 4.3.0, edid.h
+ *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ * 
+ *   2. John Fremlin <vii@users.sourceforge.net> and 
+ *      Ani Joshi <ajoshi@unixbox.com>
+ *
+ * DDC is a Trademark of VESA (Video Electronics Standard Association).
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+*/
+
+#ifndef __EDID_H__
+#define __EDID_H__
+
+#define EDID_LENGTH				0x80
+#define EDID_HEADER				0x00
+#define EDID_HEADER_END				0x07
+
+#define ID_MANUFACTURER_NAME			0x08
+#define ID_MANUFACTURER_NAME_END		0x09
+#define ID_MODEL				0x0a
+
+#define ID_SERIAL_NUMBER			0x0c
+
+#define MANUFACTURE_WEEK			0x10
+#define MANUFACTURE_YEAR			0x11
+
+#define EDID_STRUCT_VERSION			0x12
+#define EDID_STRUCT_REVISION			0x13
+
+#define EDID_STRUCT_DISPLAY                     0x14
+
+#define DPMS_FLAGS				0x18
+#define ESTABLISHED_TIMING_1			0x23
+#define ESTABLISHED_TIMING_2			0x24
+#define MANUFACTURERS_TIMINGS			0x25
+
+/* standard timings supported */
+#define STD_TIMING                              8
+#define STD_TIMING_DESCRIPTION_SIZE             2
+#define STD_TIMING_DESCRIPTIONS_START           0x26
+
+#define DETAILED_TIMING_DESCRIPTIONS_START	0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE	18
+#define NO_DETAILED_TIMING_DESCRIPTIONS		4
+
+#define DETAILED_TIMING_DESCRIPTION_1		0x36
+#define DETAILED_TIMING_DESCRIPTION_2		0x48
+#define DETAILED_TIMING_DESCRIPTION_3		0x5a
+#define DETAILED_TIMING_DESCRIPTION_4		0x6c
+
+#define DESCRIPTOR_DATA				5
+
+#define UPPER_NIBBLE( x ) \
+        (((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE( x ) \
+        ((1|2|4|8) & (x))
+
+#define COMBINE_HI_8LO( hi, lo ) \
+        ( (((unsigned)hi) << 8) | (unsigned)lo )
+
+#define COMBINE_HI_4LO( hi, lo ) \
+        ( (((unsigned)hi) << 4) | (unsigned)lo )
+
+#define PIXEL_CLOCK_LO     (unsigned)block[ 0 ]
+#define PIXEL_CLOCK_HI     (unsigned)block[ 1 ]
+#define PIXEL_CLOCK	   (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
+#define H_ACTIVE_LO        (unsigned)block[ 2 ]
+#define H_BLANKING_LO      (unsigned)block[ 3 ]
+#define H_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_ACTIVE           COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
+#define H_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_BLANKING         COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
+
+#define V_ACTIVE_LO        (unsigned)block[ 5 ]
+#define V_BLANKING_LO      (unsigned)block[ 6 ]
+#define V_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_ACTIVE           COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
+#define V_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_BLANKING         COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
+
+#define H_SYNC_OFFSET_LO   (unsigned)block[ 8 ]
+#define H_SYNC_WIDTH_LO    (unsigned)block[ 9 ]
+
+#define V_SYNC_OFFSET_LO   UPPER_NIBBLE( (unsigned)block[ 10 ] )
+#define V_SYNC_WIDTH_LO    LOWER_NIBBLE( (unsigned)block[ 10 ] )
+
+#define V_SYNC_WIDTH_HI    ((unsigned)block[ 11 ] & (1|2))
+#define V_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (4|8)) >> 2)
+
+#define H_SYNC_WIDTH_HI    (((unsigned)block[ 11 ] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (64|128)) >> 6)
+
+#define V_SYNC_WIDTH       COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
+#define V_SYNC_OFFSET      COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
+
+#define H_SYNC_WIDTH       COMBINE_HI_8LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
+#define H_SYNC_OFFSET      COMBINE_HI_8LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
+
+#define H_SIZE_LO          (unsigned)block[ 12 ]
+#define V_SIZE_LO          (unsigned)block[ 13 ]
+
+#define H_SIZE_HI          UPPER_NIBBLE( (unsigned)block[ 14 ] )
+#define V_SIZE_HI          LOWER_NIBBLE( (unsigned)block[ 14 ] )
+
+#define H_SIZE             COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
+#define V_SIZE             COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
+
+#define H_BORDER           (unsigned)block[ 15 ]
+#define V_BORDER           (unsigned)block[ 16 ]
+
+#define FLAGS              (unsigned)block[ 17 ]
+
+#define INTERLACED         (FLAGS&128)
+#define SYNC_TYPE          (FLAGS&3<<3)	/* bits 4,3 */
+#define SYNC_SEPARATE      (3<<3)
+#define HSYNC_POSITIVE     (FLAGS & 4)
+#define VSYNC_POSITIVE     (FLAGS & 2)
+
+#define V_MIN_RATE              block[ 5 ]
+#define V_MAX_RATE              block[ 6 ]
+#define H_MIN_RATE              block[ 7 ]
+#define H_MAX_RATE              block[ 8 ]
+#define MAX_PIXEL_CLOCK         (((int)block[ 9 ]) * 10)
+#define GTF_SUPPORT		block[10]
+
+#define DPMS_ACTIVE_OFF		(1 << 5)
+#define DPMS_SUSPEND		(1 << 6)
+#define DPMS_STANDBY		(1 << 7)
+
+#endif /* __EDID_H__ */
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
new file mode 100644
index 000000000000..ae9618ff6735
--- /dev/null
+++ b/drivers/video/fbdev/efifb.c
@@ -0,0 +1,360 @@
+/*
+ * Framebuffer driver for EFI/UEFI based system
+ *
+ * (c) 2006 Edgar Hucek <gimli@dark-green.com>
+ * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include <linux/screen_info.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+#include <video/vga.h>
+#include <asm/sysfb.h>
+
+static bool request_mem_succeeded = false;
+
+static struct pci_dev *default_vga;
+
+static struct fb_var_screeninfo efifb_defined = {
+	.activate		= FB_ACTIVATE_NOW,
+	.height			= -1,
+	.width			= -1,
+	.right_margin		= 32,
+	.upper_margin		= 16,
+	.lower_margin		= 4,
+	.vsync_len		= 4,
+	.vmode			= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo efifb_fix = {
+	.id			= "EFI VGA",
+	.type			= FB_TYPE_PACKED_PIXELS,
+	.accel			= FB_ACCEL_NONE,
+	.visual			= FB_VISUAL_TRUECOLOR,
+};
+
+static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	/*
+	 *  Set a single color register. The values supplied are
+	 *  already rounded down to the hardware's capabilities
+	 *  (according to the entries in the `var' structure). Return
+	 *  != 0 for invalid regno.
+	 */
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	if (regno < 16) {
+		red   >>= 8;
+		green >>= 8;
+		blue  >>= 8;
+		((u32 *)(info->pseudo_palette))[regno] =
+			(red   << info->var.red.offset)   |
+			(green << info->var.green.offset) |
+			(blue  << info->var.blue.offset);
+	}
+	return 0;
+}
+
+static void efifb_destroy(struct fb_info *info)
+{
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	if (request_mem_succeeded)
+		release_mem_region(info->apertures->ranges[0].base,
+				   info->apertures->ranges[0].size);
+	fb_dealloc_cmap(&info->cmap);
+}
+
+static struct fb_ops efifb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_destroy	= efifb_destroy,
+	.fb_setcolreg	= efifb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+struct pci_dev *vga_default_device(void)
+{
+	return default_vga;
+}
+
+EXPORT_SYMBOL_GPL(vga_default_device);
+
+void vga_set_default_device(struct pci_dev *pdev)
+{
+	default_vga = pdev;
+}
+
+static int efifb_setup(char *options)
+{
+	char *this_opt;
+	int i;
+	struct pci_dev *dev = NULL;
+
+	if (options && *options) {
+		while ((this_opt = strsep(&options, ",")) != NULL) {
+			if (!*this_opt) continue;
+
+			for (i = 0; i < M_UNKNOWN; i++) {
+				if (efifb_dmi_list[i].base != 0 &&
+				    !strcmp(this_opt, efifb_dmi_list[i].optname)) {
+					screen_info.lfb_base = efifb_dmi_list[i].base;
+					screen_info.lfb_linelength = efifb_dmi_list[i].stride;
+					screen_info.lfb_width = efifb_dmi_list[i].width;
+					screen_info.lfb_height = efifb_dmi_list[i].height;
+				}
+			}
+			if (!strncmp(this_opt, "base:", 5))
+				screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
+			else if (!strncmp(this_opt, "stride:", 7))
+				screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
+			else if (!strncmp(this_opt, "height:", 7))
+				screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
+			else if (!strncmp(this_opt, "width:", 6))
+				screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
+		}
+	}
+
+	for_each_pci_dev(dev) {
+		int i;
+
+		if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+			continue;
+
+		for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
+			resource_size_t start, end;
+
+			if (!(pci_resource_flags(dev, i) & IORESOURCE_MEM))
+				continue;
+
+			start = pci_resource_start(dev, i);
+			end  = pci_resource_end(dev, i);
+
+			if (!start || !end)
+				continue;
+
+			if (screen_info.lfb_base >= start &&
+			    (screen_info.lfb_base + screen_info.lfb_size) < end)
+				default_vga = dev;
+		}
+	}
+
+	return 0;
+}
+
+static int efifb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int err;
+	unsigned int size_vmode;
+	unsigned int size_remap;
+	unsigned int size_total;
+	char *option = NULL;
+
+	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+		return -ENODEV;
+
+	if (fb_get_options("efifb", &option))
+		return -ENODEV;
+	efifb_setup(option);
+
+	/* We don't get linelength from UGA Draw Protocol, only from
+	 * EFI Graphics Protocol.  So if it's not in DMI, and it's not
+	 * passed in from the user, we really can't use the framebuffer.
+	 */
+	if (!screen_info.lfb_linelength)
+		return -ENODEV;
+
+	if (!screen_info.lfb_depth)
+		screen_info.lfb_depth = 32;
+	if (!screen_info.pages)
+		screen_info.pages = 1;
+	if (!screen_info.lfb_base) {
+		printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
+		return -ENODEV;
+	}
+	printk(KERN_INFO "efifb: probing for efifb\n");
+
+	/* just assume they're all unset if any are */
+	if (!screen_info.blue_size) {
+		screen_info.blue_size = 8;
+		screen_info.blue_pos = 0;
+		screen_info.green_size = 8;
+		screen_info.green_pos = 8;
+		screen_info.red_size = 8;
+		screen_info.red_pos = 16;
+		screen_info.rsvd_size = 8;
+		screen_info.rsvd_pos = 24;
+	}
+
+	efifb_fix.smem_start = screen_info.lfb_base;
+	efifb_defined.bits_per_pixel = screen_info.lfb_depth;
+	efifb_defined.xres = screen_info.lfb_width;
+	efifb_defined.yres = screen_info.lfb_height;
+	efifb_fix.line_length = screen_info.lfb_linelength;
+
+	/*   size_vmode -- that is the amount of memory needed for the
+	 *                 used video mode, i.e. the minimum amount of
+	 *                 memory we need. */
+	size_vmode = efifb_defined.yres * efifb_fix.line_length;
+
+	/*   size_total -- all video memory we have. Used for
+	 *                 entries, ressource allocation and bounds
+	 *                 checking. */
+	size_total = screen_info.lfb_size;
+	if (size_total < size_vmode)
+		size_total = size_vmode;
+
+	/*   size_remap -- the amount of video memory we are going to
+	 *                 use for efifb.  With modern cards it is no
+	 *                 option to simply use size_total as that
+	 *                 wastes plenty of kernel address space. */
+	size_remap  = size_vmode * 2;
+	if (size_remap > size_total)
+		size_remap = size_total;
+	if (size_remap % PAGE_SIZE)
+		size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
+	efifb_fix.smem_len = size_remap;
+
+	if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
+		request_mem_succeeded = true;
+	} else {
+		/* We cannot make this fatal. Sometimes this comes from magic
+		   spaces our resource handlers simply don't know about */
+		printk(KERN_WARNING
+		       "efifb: cannot reserve video memory at 0x%lx\n",
+			efifb_fix.smem_start);
+	}
+
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (!info) {
+		printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
+		err = -ENOMEM;
+		goto err_release_mem;
+	}
+	platform_set_drvdata(dev, info);
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures) {
+		err = -ENOMEM;
+		goto err_release_fb;
+	}
+	info->apertures->ranges[0].base = efifb_fix.smem_start;
+	info->apertures->ranges[0].size = size_remap;
+
+	info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
+				"0x%x @ 0x%lx\n",
+			efifb_fix.smem_len, efifb_fix.smem_start);
+		err = -EIO;
+		goto err_release_fb;
+	}
+
+	printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
+	       "using %dk, total %dk\n",
+	       efifb_fix.smem_start, info->screen_base,
+	       size_remap/1024, size_total/1024);
+	printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+	       efifb_defined.xres, efifb_defined.yres,
+	       efifb_defined.bits_per_pixel, efifb_fix.line_length,
+	       screen_info.pages);
+
+	efifb_defined.xres_virtual = efifb_defined.xres;
+	efifb_defined.yres_virtual = efifb_fix.smem_len /
+					efifb_fix.line_length;
+	printk(KERN_INFO "efifb: scrolling: redraw\n");
+	efifb_defined.yres_virtual = efifb_defined.yres;
+
+	/* some dummy values for timing to make fbset happy */
+	efifb_defined.pixclock     = 10000000 / efifb_defined.xres *
+					1000 / efifb_defined.yres;
+	efifb_defined.left_margin  = (efifb_defined.xres / 8) & 0xf8;
+	efifb_defined.hsync_len    = (efifb_defined.xres / 8) & 0xf8;
+
+	efifb_defined.red.offset    = screen_info.red_pos;
+	efifb_defined.red.length    = screen_info.red_size;
+	efifb_defined.green.offset  = screen_info.green_pos;
+	efifb_defined.green.length  = screen_info.green_size;
+	efifb_defined.blue.offset   = screen_info.blue_pos;
+	efifb_defined.blue.length   = screen_info.blue_size;
+	efifb_defined.transp.offset = screen_info.rsvd_pos;
+	efifb_defined.transp.length = screen_info.rsvd_size;
+
+	printk(KERN_INFO "efifb: %s: "
+	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+	       "Truecolor",
+	       screen_info.rsvd_size,
+	       screen_info.red_size,
+	       screen_info.green_size,
+	       screen_info.blue_size,
+	       screen_info.rsvd_pos,
+	       screen_info.red_pos,
+	       screen_info.green_pos,
+	       screen_info.blue_pos);
+
+	efifb_fix.ypanstep  = 0;
+	efifb_fix.ywrapstep = 0;
+
+	info->fbops = &efifb_ops;
+	info->var = efifb_defined;
+	info->fix = efifb_fix;
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
+
+	if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
+		printk(KERN_ERR "efifb: cannot allocate colormap\n");
+		goto err_unmap;
+	}
+	if ((err = register_framebuffer(info)) < 0) {
+		printk(KERN_ERR "efifb: cannot register framebuffer\n");
+		goto err_fb_dealoc;
+	}
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	return 0;
+
+err_fb_dealoc:
+	fb_dealloc_cmap(&info->cmap);
+err_unmap:
+	iounmap(info->screen_base);
+err_release_fb:
+	framebuffer_release(info);
+err_release_mem:
+	if (request_mem_succeeded)
+		release_mem_region(efifb_fix.smem_start, size_total);
+	return err;
+}
+
+static int efifb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+
+	unregister_framebuffer(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver efifb_driver = {
+	.driver = {
+		.name = "efi-framebuffer",
+		.owner = THIS_MODULE,
+	},
+	.probe = efifb_probe,
+	.remove = efifb_remove,
+};
+
+module_platform_driver(efifb_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c
new file mode 100644
index 000000000000..35a0f533f1a2
--- /dev/null
+++ b/drivers/video/fbdev/ep93xx-fb.c
@@ -0,0 +1,634 @@
+/*
+ * linux/drivers/video/ep93xx-fb.c
+ *
+ * Framebuffer support for the EP93xx series.
+ *
+ * Copyright (C) 2007 Bluewater Systems Ltd
+ * Author: Ryan Mallon
+ *
+ * Copyright (c) 2009 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on the Cirrus Logic ep93xxfb driver, and various other ep93xxfb
+ * drivers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+
+#include <linux/platform_data/video-ep93xx.h>
+
+/* Vertical Frame Timing Registers */
+#define EP93XXFB_VLINES_TOTAL			0x0000	/* SW locked */
+#define EP93XXFB_VSYNC				0x0004	/* SW locked */
+#define EP93XXFB_VACTIVE			0x0008	/* SW locked */
+#define EP93XXFB_VBLANK				0x0228	/* SW locked */
+#define EP93XXFB_VCLK				0x000c	/* SW locked */
+
+/* Horizontal Frame Timing Registers */
+#define EP93XXFB_HCLKS_TOTAL			0x0010	/* SW locked */
+#define EP93XXFB_HSYNC				0x0014	/* SW locked */
+#define EP93XXFB_HACTIVE			0x0018	/* SW locked */
+#define EP93XXFB_HBLANK				0x022c	/* SW locked */
+#define EP93XXFB_HCLK				0x001c	/* SW locked */
+
+/* Frame Buffer Memory Configuration Registers */
+#define EP93XXFB_SCREEN_PAGE			0x0028
+#define EP93XXFB_SCREEN_HPAGE			0x002c
+#define EP93XXFB_SCREEN_LINES			0x0030
+#define EP93XXFB_LINE_LENGTH			0x0034
+#define EP93XXFB_VLINE_STEP			0x0038
+#define EP93XXFB_LINE_CARRY			0x003c	/* SW locked */
+#define EP93XXFB_EOL_OFFSET			0x0230
+
+/* Other Video Registers */
+#define EP93XXFB_BRIGHTNESS			0x0020
+#define EP93XXFB_ATTRIBS			0x0024	/* SW locked */
+#define EP93XXFB_SWLOCK				0x007c	/* SW locked */
+#define EP93XXFB_AC_RATE			0x0214
+#define EP93XXFB_FIFO_LEVEL			0x0234
+#define EP93XXFB_PIXELMODE			0x0054
+#define EP93XXFB_PIXELMODE_32BPP		(0x7 << 0)
+#define EP93XXFB_PIXELMODE_24BPP		(0x6 << 0)
+#define EP93XXFB_PIXELMODE_16BPP		(0x4 << 0)
+#define EP93XXFB_PIXELMODE_8BPP			(0x2 << 0)
+#define EP93XXFB_PIXELMODE_SHIFT_1P_24B		(0x0 << 3)
+#define EP93XXFB_PIXELMODE_SHIFT_1P_18B		(0x1 << 3)
+#define EP93XXFB_PIXELMODE_COLOR_LUT		(0x0 << 10)
+#define EP93XXFB_PIXELMODE_COLOR_888		(0x4 << 10)
+#define EP93XXFB_PIXELMODE_COLOR_555		(0x5 << 10)
+#define EP93XXFB_PARL_IF_OUT			0x0058
+#define EP93XXFB_PARL_IF_IN			0x005c
+
+/* Blink Control Registers */
+#define EP93XXFB_BLINK_RATE			0x0040
+#define EP93XXFB_BLINK_MASK			0x0044
+#define EP93XXFB_BLINK_PATTRN			0x0048
+#define EP93XXFB_PATTRN_MASK			0x004c
+#define EP93XXFB_BKGRND_OFFSET			0x0050
+
+/* Hardware Cursor Registers */
+#define EP93XXFB_CURSOR_ADR_START		0x0060
+#define EP93XXFB_CURSOR_ADR_RESET		0x0064
+#define EP93XXFB_CURSOR_SIZE			0x0068
+#define EP93XXFB_CURSOR_COLOR1			0x006c
+#define EP93XXFB_CURSOR_COLOR2			0x0070
+#define EP93XXFB_CURSOR_BLINK_COLOR1		0x021c
+#define EP93XXFB_CURSOR_BLINK_COLOR2		0x0220
+#define EP93XXFB_CURSOR_XY_LOC			0x0074
+#define EP93XXFB_CURSOR_DSCAN_HY_LOC		0x0078
+#define EP93XXFB_CURSOR_BLINK_RATE_CTRL		0x0224
+
+/* LUT Registers */
+#define EP93XXFB_GRY_SCL_LUTR			0x0080
+#define EP93XXFB_GRY_SCL_LUTG			0x0280
+#define EP93XXFB_GRY_SCL_LUTB			0x0300
+#define EP93XXFB_LUT_SW_CONTROL			0x0218
+#define EP93XXFB_LUT_SW_CONTROL_SWTCH		(1 << 0)
+#define EP93XXFB_LUT_SW_CONTROL_SSTAT		(1 << 1)
+#define EP93XXFB_COLOR_LUT			0x0400
+
+/* Video Signature Registers */
+#define EP93XXFB_VID_SIG_RSLT_VAL		0x0200
+#define EP93XXFB_VID_SIG_CTRL			0x0204
+#define EP93XXFB_VSIG				0x0208
+#define EP93XXFB_HSIG				0x020c
+#define EP93XXFB_SIG_CLR_STR			0x0210
+
+/* Minimum / Maximum resolutions supported */
+#define EP93XXFB_MIN_XRES			64
+#define EP93XXFB_MIN_YRES			64
+#define EP93XXFB_MAX_XRES			1024
+#define EP93XXFB_MAX_YRES			768
+
+struct ep93xx_fbi {
+	struct ep93xxfb_mach_info	*mach_info;
+	struct clk			*clk;
+	struct resource			*res;
+	void __iomem			*mmio_base;
+	unsigned int			pseudo_palette[256];
+};
+
+static int check_screenpage_bug = 1;
+module_param(check_screenpage_bug, int, 0644);
+MODULE_PARM_DESC(check_screenpage_bug,
+		 "Check for bit 27 screen page bug. Default = 1");
+
+static inline unsigned int ep93xxfb_readl(struct ep93xx_fbi *fbi,
+					  unsigned int off)
+{
+	return __raw_readl(fbi->mmio_base + off);
+}
+
+static inline void ep93xxfb_writel(struct ep93xx_fbi *fbi,
+				   unsigned int val, unsigned int off)
+{
+	__raw_writel(val, fbi->mmio_base + off);
+}
+
+/*
+ * Write to one of the locked raster registers.
+ */
+static inline void ep93xxfb_out_locked(struct ep93xx_fbi *fbi,
+				       unsigned int val, unsigned int reg)
+{
+	/*
+	 * We don't need a lock or delay here since the raster register
+	 * block will remain unlocked until the next access.
+	 */
+	ep93xxfb_writel(fbi, 0xaa, EP93XXFB_SWLOCK);
+	ep93xxfb_writel(fbi, val, reg);
+}
+
+static void ep93xxfb_set_video_attribs(struct fb_info *info)
+{
+	struct ep93xx_fbi *fbi = info->par;
+	unsigned int attribs;
+
+	attribs = EP93XXFB_ENABLE;
+	attribs |= fbi->mach_info->flags;
+	ep93xxfb_out_locked(fbi, attribs, EP93XXFB_ATTRIBS);
+}
+
+static int ep93xxfb_set_pixelmode(struct fb_info *info)
+{
+	struct ep93xx_fbi *fbi = info->par;
+	unsigned int val;
+
+	info->var.transp.offset = 0;
+	info->var.transp.length = 0;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		val = EP93XXFB_PIXELMODE_8BPP | EP93XXFB_PIXELMODE_COLOR_LUT |
+			EP93XXFB_PIXELMODE_SHIFT_1P_18B;
+
+		info->var.red.offset	= 0;
+		info->var.red.length	= 8;
+		info->var.green.offset	= 0;
+		info->var.green.length	= 8;
+		info->var.blue.offset	= 0;
+		info->var.blue.length	= 8;
+		info->fix.visual 	= FB_VISUAL_PSEUDOCOLOR;
+		break;
+
+	case 16:
+		val = EP93XXFB_PIXELMODE_16BPP | EP93XXFB_PIXELMODE_COLOR_555 |
+			EP93XXFB_PIXELMODE_SHIFT_1P_18B;
+
+		info->var.red.offset	= 11;
+		info->var.red.length	= 5;
+		info->var.green.offset	= 5;
+		info->var.green.length	= 6;
+		info->var.blue.offset	= 0;
+		info->var.blue.length	= 5;
+		info->fix.visual 	= FB_VISUAL_TRUECOLOR;
+		break;
+
+	case 24:
+		val = EP93XXFB_PIXELMODE_24BPP | EP93XXFB_PIXELMODE_COLOR_888 |
+			EP93XXFB_PIXELMODE_SHIFT_1P_24B;
+
+		info->var.red.offset	= 16;
+		info->var.red.length	= 8;
+		info->var.green.offset	= 8;
+		info->var.green.length	= 8;
+		info->var.blue.offset	= 0;
+		info->var.blue.length	= 8;
+		info->fix.visual 	= FB_VISUAL_TRUECOLOR;
+		break;
+
+	case 32:
+		val = EP93XXFB_PIXELMODE_32BPP | EP93XXFB_PIXELMODE_COLOR_888 |
+			EP93XXFB_PIXELMODE_SHIFT_1P_24B;
+
+		info->var.red.offset	= 16;
+		info->var.red.length	= 8;
+		info->var.green.offset	= 8;
+		info->var.green.length	= 8;
+		info->var.blue.offset	= 0;
+		info->var.blue.length	= 8;
+		info->fix.visual 	= FB_VISUAL_TRUECOLOR;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	ep93xxfb_writel(fbi, val, EP93XXFB_PIXELMODE);
+	return 0;
+}
+
+static void ep93xxfb_set_timing(struct fb_info *info)
+{
+	struct ep93xx_fbi *fbi = info->par;
+	unsigned int vlines_total, hclks_total, start, stop;
+
+	vlines_total = info->var.yres + info->var.upper_margin +
+		info->var.lower_margin + info->var.vsync_len - 1;
+
+	hclks_total = info->var.xres + info->var.left_margin +
+		info->var.right_margin + info->var.hsync_len - 1;
+
+	ep93xxfb_out_locked(fbi, vlines_total, EP93XXFB_VLINES_TOTAL);
+	ep93xxfb_out_locked(fbi, hclks_total, EP93XXFB_HCLKS_TOTAL);
+
+	start = vlines_total;
+	stop = vlines_total - info->var.vsync_len;
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VSYNC);
+
+	start = vlines_total - info->var.vsync_len - info->var.upper_margin;
+	stop = info->var.lower_margin - 1;
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VBLANK);
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VACTIVE);
+
+	start = vlines_total;
+	stop = vlines_total + 1;
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VCLK);
+
+	start = hclks_total;
+	stop = hclks_total - info->var.hsync_len;
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HSYNC);
+
+	start = hclks_total - info->var.hsync_len - info->var.left_margin;
+	stop = info->var.right_margin - 1;
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HBLANK);
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HACTIVE);
+
+	start = hclks_total;
+	stop = hclks_total;
+	ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HCLK);
+
+	ep93xxfb_out_locked(fbi, 0x0, EP93XXFB_LINE_CARRY);
+}
+
+static int ep93xxfb_set_par(struct fb_info *info)
+{
+	struct ep93xx_fbi *fbi = info->par;
+
+	clk_set_rate(fbi->clk, 1000 * PICOS2KHZ(info->var.pixclock));
+
+	ep93xxfb_set_timing(info);
+
+	info->fix.line_length = info->var.xres_virtual *
+		info->var.bits_per_pixel / 8;
+
+	ep93xxfb_writel(fbi, info->fix.smem_start, EP93XXFB_SCREEN_PAGE);
+	ep93xxfb_writel(fbi, info->var.yres - 1, EP93XXFB_SCREEN_LINES);
+	ep93xxfb_writel(fbi, ((info->var.xres * info->var.bits_per_pixel)
+			      / 32) - 1, EP93XXFB_LINE_LENGTH);
+	ep93xxfb_writel(fbi, info->fix.line_length / 4, EP93XXFB_VLINE_STEP);
+	ep93xxfb_set_video_attribs(info);
+	return 0;
+}
+
+static int ep93xxfb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	int err;
+
+	err = ep93xxfb_set_pixelmode(info);
+	if (err)
+		return err;
+
+	var->xres = max_t(unsigned int, var->xres, EP93XXFB_MIN_XRES);
+	var->xres = min_t(unsigned int, var->xres, EP93XXFB_MAX_XRES);
+	var->xres_virtual = max(var->xres_virtual, var->xres);
+
+	var->yres = max_t(unsigned int, var->yres, EP93XXFB_MIN_YRES);
+	var->yres = min_t(unsigned int, var->yres, EP93XXFB_MAX_YRES);
+	var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	return 0;
+}
+
+static int ep93xxfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned int offset = vma->vm_pgoff << PAGE_SHIFT;
+
+	if (offset < info->fix.smem_len) {
+		return dma_mmap_writecombine(info->dev, vma, info->screen_base,
+					     info->fix.smem_start,
+					     info->fix.smem_len);
+	}
+
+	return -EINVAL;
+}
+
+static int ep93xxfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct ep93xx_fbi *fbi = info->par;
+	unsigned int attribs = ep93xxfb_readl(fbi, EP93XXFB_ATTRIBS);
+
+	if (blank_mode) {
+		if (fbi->mach_info->blank)
+			fbi->mach_info->blank(blank_mode, info);
+		ep93xxfb_out_locked(fbi, attribs & ~EP93XXFB_ENABLE,
+				    EP93XXFB_ATTRIBS);
+		clk_disable(fbi->clk);
+	} else {
+		clk_enable(fbi->clk);
+		ep93xxfb_out_locked(fbi, attribs | EP93XXFB_ENABLE,
+				    EP93XXFB_ATTRIBS);
+		if (fbi->mach_info->blank)
+			fbi->mach_info->blank(blank_mode, info);
+	}
+
+	return 0;
+}
+
+static inline int ep93xxfb_convert_color(int val, int width)
+{
+	return ((val << width) + 0x7fff - val) >> 16;
+}
+
+static int ep93xxfb_setcolreg(unsigned int regno, unsigned int red,
+			      unsigned int green, unsigned int blue,
+			      unsigned int transp, struct fb_info *info)
+{
+	struct ep93xx_fbi *fbi = info->par;
+	unsigned int *pal = info->pseudo_palette;
+	unsigned int ctrl, i, rgb, lut_current, lut_stat;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno > 255)
+			return 1;
+		rgb = ((red & 0xff00) << 8) | (green & 0xff00) |
+			((blue & 0xff00) >> 8);
+
+		pal[regno] = rgb;
+		ep93xxfb_writel(fbi, rgb, (EP93XXFB_COLOR_LUT + (regno << 2)));
+		ctrl = ep93xxfb_readl(fbi, EP93XXFB_LUT_SW_CONTROL);
+		lut_stat = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SSTAT);
+		lut_current = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SWTCH);
+
+		if (lut_stat == lut_current) {
+			for (i = 0; i < 256; i++) {
+				ep93xxfb_writel(fbi, pal[i],
+					EP93XXFB_COLOR_LUT + (i << 2));
+			}
+
+			ep93xxfb_writel(fbi,
+					ctrl ^ EP93XXFB_LUT_SW_CONTROL_SWTCH,
+					EP93XXFB_LUT_SW_CONTROL);
+		}
+		break;
+
+	case FB_VISUAL_TRUECOLOR:
+		if (regno > 16)
+			return 1;
+
+		red = ep93xxfb_convert_color(red, info->var.red.length);
+		green = ep93xxfb_convert_color(green, info->var.green.length);
+		blue = ep93xxfb_convert_color(blue, info->var.blue.length);
+		transp = ep93xxfb_convert_color(transp,
+						info->var.transp.length);
+
+		pal[regno] = (red << info->var.red.offset) |
+			(green << info->var.green.offset) |
+			(blue << info->var.blue.offset) |
+			(transp << info->var.transp.offset);
+		break;
+
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+static struct fb_ops ep93xxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= ep93xxfb_check_var,
+	.fb_set_par	= ep93xxfb_set_par,
+	.fb_blank	= ep93xxfb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_setcolreg	= ep93xxfb_setcolreg,
+	.fb_mmap	= ep93xxfb_mmap,
+};
+
+static int ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
+{
+	int i, fb_size = 0;
+
+	if (mach_info->num_modes == EP93XXFB_USE_MODEDB) {
+		fb_size = EP93XXFB_MAX_XRES * EP93XXFB_MAX_YRES *
+			mach_info->bpp / 8;
+	} else {
+		for (i = 0; i < mach_info->num_modes; i++) {
+			const struct fb_videomode *mode;
+			int size;
+
+			mode = &mach_info->modes[i];
+			size = mode->xres * mode->yres * mach_info->bpp / 8;
+			if (size > fb_size)
+				fb_size = size;
+		}
+	}
+
+	return fb_size;
+}
+
+static int ep93xxfb_alloc_videomem(struct fb_info *info)
+{
+	struct ep93xx_fbi *fbi = info->par;
+	char __iomem *virt_addr;
+	dma_addr_t phys_addr;
+	unsigned int fb_size;
+
+	fb_size = ep93xxfb_calc_fbsize(fbi->mach_info);
+	virt_addr = dma_alloc_writecombine(info->dev, fb_size,
+					   &phys_addr, GFP_KERNEL);
+	if (!virt_addr)
+		return -ENOMEM;
+
+	/*
+	 * There is a bug in the ep93xx framebuffer which causes problems
+	 * if bit 27 of the physical address is set.
+	 * See: http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
+	 * There does not seem to be any official errata for this, but I
+	 * have confirmed the problem exists on my hardware (ep9315) at
+	 * least.
+	 */
+	if (check_screenpage_bug && phys_addr & (1 << 27)) {
+		dev_err(info->dev, "ep93xx framebuffer bug. phys addr (0x%x) "
+			"has bit 27 set: cannot init framebuffer\n",
+			phys_addr);
+
+		dma_free_coherent(info->dev, fb_size, virt_addr, phys_addr);
+		return -ENOMEM;
+	}
+
+	info->fix.smem_start = phys_addr;
+	info->fix.smem_len = fb_size;
+	info->screen_base = virt_addr;
+
+	return 0;
+}
+
+static void ep93xxfb_dealloc_videomem(struct fb_info *info)
+{
+	if (info->screen_base)
+		dma_free_coherent(info->dev, info->fix.smem_len,
+				  info->screen_base, info->fix.smem_start);
+}
+
+static int ep93xxfb_probe(struct platform_device *pdev)
+{
+	struct ep93xxfb_mach_info *mach_info = dev_get_platdata(&pdev->dev);
+	struct fb_info *info;
+	struct ep93xx_fbi *fbi;
+	struct resource *res;
+	char *video_mode;
+	int err;
+
+	if (!mach_info)
+		return -EINVAL;
+
+	info = framebuffer_alloc(sizeof(struct ep93xx_fbi), &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = &pdev->dev;
+	platform_set_drvdata(pdev, info);
+	fbi = info->par;
+	fbi->mach_info = mach_info;
+
+	err = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (err)
+		goto failed_cmap;
+
+	err = ep93xxfb_alloc_videomem(info);
+	if (err)
+		goto failed_videomem;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENXIO;
+		goto failed_resource;
+	}
+
+	/*
+	 * FIXME - We don't do a request_mem_region here because we are
+	 * sharing the register space with the backlight driver (see
+	 * drivers/video/backlight/ep93xx_bl.c) and doing so will cause
+	 * the second loaded driver to return -EBUSY.
+	 *
+	 * NOTE: No locking is required; the backlight does not touch
+	 * any of the framebuffer registers.
+	 */
+	fbi->res = res;
+	fbi->mmio_base = devm_ioremap(&pdev->dev, res->start,
+				      resource_size(res));
+	if (!fbi->mmio_base) {
+		err = -ENXIO;
+		goto failed_resource;
+	}
+
+	strcpy(info->fix.id, pdev->name);
+	info->fbops		= &ep93xxfb_ops;
+	info->fix.type		= FB_TYPE_PACKED_PIXELS;
+	info->fix.accel		= FB_ACCEL_NONE;
+	info->var.activate	= FB_ACTIVATE_NOW;
+	info->var.vmode		= FB_VMODE_NONINTERLACED;
+	info->flags		= FBINFO_DEFAULT;
+	info->node		= -1;
+	info->state		= FBINFO_STATE_RUNNING;
+	info->pseudo_palette	= &fbi->pseudo_palette;
+
+	fb_get_options("ep93xx-fb", &video_mode);
+	err = fb_find_mode(&info->var, info, video_mode,
+			   fbi->mach_info->modes, fbi->mach_info->num_modes,
+			   fbi->mach_info->default_mode, fbi->mach_info->bpp);
+	if (err == 0) {
+		dev_err(info->dev, "No suitable video mode found\n");
+		err = -EINVAL;
+		goto failed_resource;
+	}
+
+	if (mach_info->setup) {
+		err = mach_info->setup(pdev);
+		if (err)
+			goto failed_resource;
+	}
+
+	err = ep93xxfb_check_var(&info->var, info);
+	if (err)
+		goto failed_check;
+
+	fbi->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(fbi->clk)) {
+		err = PTR_ERR(fbi->clk);
+		fbi->clk = NULL;
+		goto failed_check;
+	}
+
+	ep93xxfb_set_par(info);
+	clk_enable(fbi->clk);
+
+	err = register_framebuffer(info);
+	if (err)
+		goto failed_check;
+
+	dev_info(info->dev, "registered. Mode = %dx%d-%d\n",
+		 info->var.xres, info->var.yres, info->var.bits_per_pixel);
+	return 0;
+
+failed_check:
+	if (fbi->mach_info->teardown)
+		fbi->mach_info->teardown(pdev);
+failed_resource:
+	ep93xxfb_dealloc_videomem(info);
+failed_videomem:
+	fb_dealloc_cmap(&info->cmap);
+failed_cmap:
+	kfree(info);
+
+	return err;
+}
+
+static int ep93xxfb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct ep93xx_fbi *fbi = info->par;
+
+	unregister_framebuffer(info);
+	clk_disable(fbi->clk);
+	ep93xxfb_dealloc_videomem(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	if (fbi->mach_info->teardown)
+		fbi->mach_info->teardown(pdev);
+
+	kfree(info);
+
+	return 0;
+}
+
+static struct platform_driver ep93xxfb_driver = {
+	.probe		= ep93xxfb_probe,
+	.remove		= ep93xxfb_remove,
+	.driver = {
+		.name	= "ep93xx-fb",
+		.owner	= THIS_MODULE,
+	},
+};
+module_platform_driver(ep93xxfb_driver);
+
+MODULE_DESCRIPTION("EP93XX Framebuffer Driver");
+MODULE_ALIAS("platform:ep93xx-fb");
+MODULE_AUTHOR("Ryan Mallon, "
+	      "H Hartley Sweeten <hsweeten@visionengravers.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/exynos/Kconfig b/drivers/video/fbdev/exynos/Kconfig
new file mode 100644
index 000000000000..fcf2d48ac6d1
--- /dev/null
+++ b/drivers/video/fbdev/exynos/Kconfig
@@ -0,0 +1,32 @@
+#
+# Exynos Video configuration
+#
+
+menuconfig EXYNOS_VIDEO
+	bool "Exynos Video driver support"
+	help
+	  This enables support for EXYNOS Video device.
+
+if EXYNOS_VIDEO
+
+#
+# MIPI DSI driver
+#
+
+config EXYNOS_MIPI_DSI
+	bool "EXYNOS MIPI DSI driver support."
+	depends on ARCH_S5PV210 || ARCH_EXYNOS
+	select GENERIC_PHY
+	help
+	  This enables support for MIPI-DSI device.
+
+config EXYNOS_LCD_S6E8AX0
+	bool "S6E8AX0 MIPI AMOLED LCD Driver"
+	depends on EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE
+	depends on (LCD_CLASS_DEVICE = y)
+	default n
+	help
+	  If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
+	  LCD control driver.
+
+endif # EXYNOS_VIDEO
diff --git a/drivers/video/fbdev/exynos/Makefile b/drivers/video/fbdev/exynos/Makefile
new file mode 100644
index 000000000000..b5b1bd228abb
--- /dev/null
+++ b/drivers/video/fbdev/exynos/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the exynos video drivers.
+#
+
+obj-$(CONFIG_EXYNOS_MIPI_DSI)		+= exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
+				     	exynos_mipi_dsi_lowlevel.o
+obj-$(CONFIG_EXYNOS_LCD_S6E8AX0)	+= s6e8ax0.o
diff --git a/drivers/video/fbdev/exynos/exynos_mipi_dsi.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi.c
new file mode 100644
index 000000000000..cee9602f9a7b
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi.c
@@ -0,0 +1,574 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi.c
+ *
+ * Samsung SoC MIPI-DSIM driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/ctype.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/memory.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/notifier.h>
+#include <linux/phy/phy.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/err.h>
+
+#include <video/exynos_mipi_dsim.h>
+
+#include "exynos_mipi_dsi_common.h"
+#include "exynos_mipi_dsi_lowlevel.h"
+
+struct mipi_dsim_ddi {
+	int				bus_id;
+	struct list_head		list;
+	struct mipi_dsim_lcd_device	*dsim_lcd_dev;
+	struct mipi_dsim_lcd_driver	*dsim_lcd_drv;
+};
+
+static LIST_HEAD(dsim_ddi_list);
+
+static DEFINE_MUTEX(mipi_dsim_lock);
+
+static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
+							*pdev)
+{
+	return pdev->dev.platform_data;
+}
+
+static struct regulator_bulk_data supplies[] = {
+	{ .supply = "vdd11", },
+	{ .supply = "vdd18", },
+};
+
+static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
+{
+	int ret;
+
+	mutex_lock(&dsim->lock);
+	ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
+	mutex_unlock(&dsim->lock);
+
+	return ret;
+}
+
+static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
+{
+	int ret;
+
+	mutex_lock(&dsim->lock);
+	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+	mutex_unlock(&dsim->lock);
+
+	return ret;
+}
+
+/* update all register settings to MIPI DSI controller. */
+static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
+{
+	/*
+	 * data from Display controller(FIMD) is not transferred in video mode
+	 * but in case of command mode, all settings is not updated to
+	 * registers.
+	 */
+	exynos_mipi_dsi_stand_by(dsim, 0);
+
+	exynos_mipi_dsi_init_dsim(dsim);
+	exynos_mipi_dsi_init_link(dsim);
+
+	exynos_mipi_dsi_set_hs_enable(dsim);
+
+	/* set display timing. */
+	exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
+
+	exynos_mipi_dsi_init_interrupt(dsim);
+
+	/*
+	 * data from Display controller(FIMD) is transferred in video mode
+	 * but in case of command mode, all settings are updated to registers.
+	 */
+	exynos_mipi_dsi_stand_by(dsim, 1);
+}
+
+static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
+		int power)
+{
+	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+	switch (power) {
+	case FB_BLANK_POWERDOWN:
+		if (dsim->suspended)
+			return 0;
+
+		if (client_drv && client_drv->suspend)
+			client_drv->suspend(client_dev);
+
+		clk_disable(dsim->clock);
+
+		exynos_mipi_regulator_disable(dsim);
+
+		dsim->suspended = true;
+
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
+{
+	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+	switch (power) {
+	case FB_BLANK_UNBLANK:
+		if (!dsim->suspended)
+			return 0;
+
+		/* lcd panel power on. */
+		if (client_drv && client_drv->power_on)
+			client_drv->power_on(client_dev, 1);
+
+		exynos_mipi_regulator_enable(dsim);
+
+		/* enable MIPI-DSI PHY. */
+		phy_power_on(dsim->phy);
+
+		clk_enable(dsim->clock);
+
+		exynos_mipi_update_cfg(dsim);
+
+		/* set lcd panel sequence commands. */
+		if (client_drv && client_drv->set_sequence)
+			client_drv->set_sequence(client_dev);
+
+		dsim->suspended = false;
+
+		break;
+	case FB_BLANK_NORMAL:
+		/* TODO. */
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
+{
+	struct mipi_dsim_ddi *dsim_ddi;
+
+	if (!lcd_dev->name) {
+		pr_err("dsim_lcd_device name is NULL.\n");
+		return -EFAULT;
+	}
+
+	dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
+	if (!dsim_ddi) {
+		pr_err("failed to allocate dsim_ddi object.\n");
+		return -ENOMEM;
+	}
+
+	dsim_ddi->dsim_lcd_dev = lcd_dev;
+
+	mutex_lock(&mipi_dsim_lock);
+	list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
+	mutex_unlock(&mipi_dsim_lock);
+
+	return 0;
+}
+
+static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
+					struct mipi_dsim_lcd_driver *lcd_drv)
+{
+	struct mipi_dsim_ddi *dsim_ddi, *next;
+	struct mipi_dsim_lcd_device *lcd_dev;
+
+	mutex_lock(&mipi_dsim_lock);
+
+	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
+		if (!dsim_ddi)
+			goto out;
+
+		lcd_dev = dsim_ddi->dsim_lcd_dev;
+		if (!lcd_dev)
+			continue;
+
+		if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
+			/**
+			 * bus_id would be used to identify
+			 * connected bus.
+			 */
+			dsim_ddi->bus_id = lcd_dev->bus_id;
+			mutex_unlock(&mipi_dsim_lock);
+
+			return dsim_ddi;
+		}
+
+		list_del(&dsim_ddi->list);
+		kfree(dsim_ddi);
+	}
+
+out:
+	mutex_unlock(&mipi_dsim_lock);
+
+	return NULL;
+}
+
+int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
+{
+	struct mipi_dsim_ddi *dsim_ddi;
+
+	if (!lcd_drv->name) {
+		pr_err("dsim_lcd_driver name is NULL.\n");
+		return -EFAULT;
+	}
+
+	dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
+	if (!dsim_ddi) {
+		pr_err("mipi_dsim_ddi object not found.\n");
+		return -EFAULT;
+	}
+
+	dsim_ddi->dsim_lcd_drv = lcd_drv;
+
+	pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
+		lcd_drv->name);
+
+	return 0;
+
+}
+
+static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
+						struct mipi_dsim_device *dsim,
+						const char *name)
+{
+	struct mipi_dsim_ddi *dsim_ddi, *next;
+	struct mipi_dsim_lcd_driver *lcd_drv;
+	struct mipi_dsim_lcd_device *lcd_dev;
+	int ret;
+
+	mutex_lock(&dsim->lock);
+
+	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
+		lcd_drv = dsim_ddi->dsim_lcd_drv;
+		lcd_dev = dsim_ddi->dsim_lcd_dev;
+		if (!lcd_drv || !lcd_dev ||
+			(dsim->id != dsim_ddi->bus_id))
+				continue;
+
+		dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
+				lcd_drv->id, lcd_dev->id);
+		dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
+				lcd_dev->bus_id, dsim->id);
+
+		if ((strcmp(lcd_drv->name, name) == 0)) {
+			lcd_dev->master = dsim;
+
+			lcd_dev->dev.parent = dsim->dev;
+			dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
+
+			ret = device_register(&lcd_dev->dev);
+			if (ret < 0) {
+				dev_err(dsim->dev,
+					"can't register %s, status %d\n",
+					dev_name(&lcd_dev->dev), ret);
+				mutex_unlock(&dsim->lock);
+
+				return NULL;
+			}
+
+			dsim->dsim_lcd_dev = lcd_dev;
+			dsim->dsim_lcd_drv = lcd_drv;
+
+			mutex_unlock(&dsim->lock);
+
+			return dsim_ddi;
+		}
+	}
+
+	mutex_unlock(&dsim->lock);
+
+	return NULL;
+}
+
+/* define MIPI-DSI Master operations. */
+static struct mipi_dsim_master_ops master_ops = {
+	.cmd_read			= exynos_mipi_dsi_rd_data,
+	.cmd_write			= exynos_mipi_dsi_wr_data,
+	.get_dsim_frame_done		= exynos_mipi_dsi_get_frame_done_status,
+	.clear_dsim_frame_done		= exynos_mipi_dsi_clear_frame_done,
+	.set_early_blank_mode		= exynos_mipi_dsi_early_blank_mode,
+	.set_blank_mode			= exynos_mipi_dsi_blank_mode,
+};
+
+static int exynos_mipi_dsi_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct mipi_dsim_device *dsim;
+	struct mipi_dsim_config *dsim_config;
+	struct mipi_dsim_platform_data *dsim_pd;
+	struct mipi_dsim_ddi *dsim_ddi;
+	int ret = -EINVAL;
+
+	dsim = devm_kzalloc(&pdev->dev, sizeof(struct mipi_dsim_device),
+				GFP_KERNEL);
+	if (!dsim) {
+		dev_err(&pdev->dev, "failed to allocate dsim object.\n");
+		return -ENOMEM;
+	}
+
+	dsim->pd = to_dsim_plat(pdev);
+	dsim->dev = &pdev->dev;
+	dsim->id = pdev->id;
+
+	/* get mipi_dsim_platform_data. */
+	dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
+	if (dsim_pd == NULL) {
+		dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
+		return -EINVAL;
+	}
+	/* get mipi_dsim_config. */
+	dsim_config = dsim_pd->dsim_config;
+	if (dsim_config == NULL) {
+		dev_err(&pdev->dev, "failed to get dsim config data.\n");
+		return -EINVAL;
+	}
+
+	dsim->dsim_config = dsim_config;
+	dsim->master_ops = &master_ops;
+
+	mutex_init(&dsim->lock);
+
+	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies),
+					supplies);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
+		return ret;
+	}
+
+	dsim->phy = devm_phy_get(&pdev->dev, "dsim");
+	if (IS_ERR(dsim->phy))
+		return PTR_ERR(dsim->phy);
+
+	dsim->clock = devm_clk_get(&pdev->dev, "dsim0");
+	if (IS_ERR(dsim->clock)) {
+		dev_err(&pdev->dev, "failed to get dsim clock source\n");
+		return -ENODEV;
+	}
+
+	clk_enable(dsim->clock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	dsim->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dsim->reg_base)) {
+		ret = PTR_ERR(dsim->reg_base);
+		goto error;
+	}
+
+	mutex_init(&dsim->lock);
+
+	/* bind lcd ddi matched with panel name. */
+	dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
+	if (!dsim_ddi) {
+		dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	dsim->irq = platform_get_irq(pdev, 0);
+	if (IS_ERR_VALUE(dsim->irq)) {
+		dev_err(&pdev->dev, "failed to request dsim irq resource\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	init_completion(&dsim_wr_comp);
+	init_completion(&dsim_rd_comp);
+	platform_set_drvdata(pdev, dsim);
+
+	ret = devm_request_irq(&pdev->dev, dsim->irq,
+			exynos_mipi_dsi_interrupt_handler,
+			IRQF_SHARED, dev_name(&pdev->dev), dsim);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to request dsim irq\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* enable interrupts */
+	exynos_mipi_dsi_init_interrupt(dsim);
+
+	/* initialize mipi-dsi client(lcd panel). */
+	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
+		dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
+
+	/* in case mipi-dsi has been enabled by bootloader */
+	if (dsim_pd->enabled) {
+		exynos_mipi_regulator_enable(dsim);
+		goto done;
+	}
+
+	/* lcd panel power on. */
+	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
+		dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
+
+	exynos_mipi_regulator_enable(dsim);
+
+	/* enable MIPI-DSI PHY. */
+	phy_power_on(dsim->phy);
+
+	exynos_mipi_update_cfg(dsim);
+
+	/* set lcd panel sequence commands. */
+	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
+		dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
+
+	dsim->suspended = false;
+
+done:
+	platform_set_drvdata(pdev, dsim);
+
+	dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__,
+		dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB");
+
+	return 0;
+
+error:
+	clk_disable(dsim->clock);
+	return ret;
+}
+
+static int exynos_mipi_dsi_remove(struct platform_device *pdev)
+{
+	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
+	struct mipi_dsim_ddi *dsim_ddi, *next;
+	struct mipi_dsim_lcd_driver *dsim_lcd_drv;
+
+	clk_disable(dsim->clock);
+
+	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
+		if (dsim_ddi) {
+			if (dsim->id != dsim_ddi->bus_id)
+				continue;
+
+			dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
+
+			if (dsim_lcd_drv->remove)
+				dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
+
+			kfree(dsim_ddi);
+		}
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_mipi_dsi_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
+	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+	disable_irq(dsim->irq);
+
+	if (dsim->suspended)
+		return 0;
+
+	if (client_drv && client_drv->suspend)
+		client_drv->suspend(client_dev);
+
+	/* disable MIPI-DSI PHY. */
+	phy_power_off(dsim->phy);
+
+	clk_disable(dsim->clock);
+
+	exynos_mipi_regulator_disable(dsim);
+
+	dsim->suspended = true;
+
+	return 0;
+}
+
+static int exynos_mipi_dsi_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
+	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+	enable_irq(dsim->irq);
+
+	if (!dsim->suspended)
+		return 0;
+
+	/* lcd panel power on. */
+	if (client_drv && client_drv->power_on)
+		client_drv->power_on(client_dev, 1);
+
+	exynos_mipi_regulator_enable(dsim);
+
+	/* enable MIPI-DSI PHY. */
+	phy_power_on(dsim->phy);
+
+	clk_enable(dsim->clock);
+
+	exynos_mipi_update_cfg(dsim);
+
+	/* set lcd panel sequence commands. */
+	if (client_drv && client_drv->set_sequence)
+		client_drv->set_sequence(client_dev);
+
+	dsim->suspended = false;
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume)
+};
+
+static struct platform_driver exynos_mipi_dsi_driver = {
+	.probe = exynos_mipi_dsi_probe,
+	.remove = exynos_mipi_dsi_remove,
+	.driver = {
+		   .name = "exynos-mipi-dsim",
+		   .owner = THIS_MODULE,
+		   .pm = &exynos_mipi_dsi_pm_ops,
+	},
+};
+
+module_platform_driver(exynos_mipi_dsi_driver);
+
+MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c
new file mode 100644
index 000000000000..85edabfdef5a
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c
@@ -0,0 +1,880 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi_common.c
+ *
+ * Samsung SoC MIPI-DSI common driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/ctype.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/memory.h>
+#include <linux/delay.h>
+#include <linux/irqreturn.h>
+#include <linux/kthread.h>
+
+#include <video/mipi_display.h>
+#include <video/exynos_mipi_dsim.h>
+
+#include "exynos_mipi_dsi_regs.h"
+#include "exynos_mipi_dsi_lowlevel.h"
+#include "exynos_mipi_dsi_common.h"
+
+#define MIPI_FIFO_TIMEOUT	msecs_to_jiffies(250)
+#define MIPI_RX_FIFO_READ_DONE  0x30800002
+#define MIPI_MAX_RX_FIFO        20
+#define MHZ			(1000 * 1000)
+#define FIN_HZ			(24 * MHZ)
+
+#define DFIN_PLL_MIN_HZ		(6 * MHZ)
+#define DFIN_PLL_MAX_HZ		(12 * MHZ)
+
+#define DFVCO_MIN_HZ		(500 * MHZ)
+#define DFVCO_MAX_HZ		(1000 * MHZ)
+
+#define TRY_GET_FIFO_TIMEOUT	(5000 * 2)
+#define TRY_FIFO_CLEAR		(10)
+
+/* MIPI-DSIM status types. */
+enum {
+	DSIM_STATE_INIT,	/* should be initialized. */
+	DSIM_STATE_STOP,	/* CPU and LCDC are LP mode. */
+	DSIM_STATE_HSCLKEN,	/* HS clock was enabled. */
+	DSIM_STATE_ULPS
+};
+
+/* define DSI lane types. */
+enum {
+	DSIM_LANE_CLOCK = (1 << 0),
+	DSIM_LANE_DATA0 = (1 << 1),
+	DSIM_LANE_DATA1 = (1 << 2),
+	DSIM_LANE_DATA2 = (1 << 3),
+	DSIM_LANE_DATA3 = (1 << 4)
+};
+
+static unsigned int dpll_table[15] = {
+	100, 120, 170, 220, 270,
+	320, 390, 450, 510, 560,
+	640, 690, 770, 870, 950
+};
+
+irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
+{
+	struct mipi_dsim_device *dsim = dev_id;
+	unsigned int intsrc, intmsk;
+
+	intsrc = exynos_mipi_dsi_read_interrupt(dsim);
+	intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
+	intmsk = ~intmsk & intsrc;
+
+	if (intsrc & INTMSK_RX_DONE) {
+		complete(&dsim_rd_comp);
+		dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n");
+	}
+	if (intsrc & INTMSK_FIFO_EMPTY) {
+		complete(&dsim_wr_comp);
+		dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n");
+	}
+
+	exynos_mipi_dsi_clear_interrupt(dsim, intmsk);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * write long packet to mipi dsi slave
+ * @dsim: mipi dsim device structure.
+ * @data0: packet data to send.
+ * @data1: size of packet data
+ */
+static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim,
+		const unsigned char *data0, unsigned int data_size)
+{
+	unsigned int data_cnt = 0, payload = 0;
+
+	/* in case that data count is more then 4 */
+	for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
+		/*
+		 * after sending 4bytes per one time,
+		 * send remainder data less then 4.
+		 */
+		if ((data_size - data_cnt) < 4) {
+			if ((data_size - data_cnt) == 3) {
+				payload = data0[data_cnt] |
+				    data0[data_cnt + 1] << 8 |
+					data0[data_cnt + 2] << 16;
+			dev_dbg(dsim->dev, "count = 3 payload = %x, %x %x %x\n",
+				payload, data0[data_cnt],
+				data0[data_cnt + 1],
+				data0[data_cnt + 2]);
+			} else if ((data_size - data_cnt) == 2) {
+				payload = data0[data_cnt] |
+					data0[data_cnt + 1] << 8;
+			dev_dbg(dsim->dev,
+				"count = 2 payload = %x, %x %x\n", payload,
+				data0[data_cnt],
+				data0[data_cnt + 1]);
+			} else if ((data_size - data_cnt) == 1) {
+				payload = data0[data_cnt];
+			}
+
+			exynos_mipi_dsi_wr_tx_data(dsim, payload);
+		/* send 4bytes per one time. */
+		} else {
+			payload = data0[data_cnt] |
+				data0[data_cnt + 1] << 8 |
+				data0[data_cnt + 2] << 16 |
+				data0[data_cnt + 3] << 24;
+
+			dev_dbg(dsim->dev,
+				"count = 4 payload = %x, %x %x %x %x\n",
+				payload, *(u8 *)(data0 + data_cnt),
+				data0[data_cnt + 1],
+				data0[data_cnt + 2],
+				data0[data_cnt + 3]);
+
+			exynos_mipi_dsi_wr_tx_data(dsim, payload);
+		}
+	}
+}
+
+int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+	const unsigned char *data0, unsigned int data_size)
+{
+	unsigned int check_rx_ack = 0;
+
+	if (dsim->state == DSIM_STATE_ULPS) {
+		dev_err(dsim->dev, "state is ULPS.\n");
+
+		return -EINVAL;
+	}
+
+	/* FIXME!!! why does it need this delay? */
+	msleep(20);
+
+	mutex_lock(&dsim->lock);
+
+	switch (data_id) {
+	/* short packet types of packet types for command. */
+	case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
+	case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
+	case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
+	case MIPI_DSI_DCS_SHORT_WRITE:
+	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
+		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
+		if (check_rx_ack) {
+			/* process response func should be implemented */
+			mutex_unlock(&dsim->lock);
+			return 0;
+		} else {
+			mutex_unlock(&dsim->lock);
+			return -EINVAL;
+		}
+
+	/* general command */
+	case MIPI_DSI_COLOR_MODE_OFF:
+	case MIPI_DSI_COLOR_MODE_ON:
+	case MIPI_DSI_SHUTDOWN_PERIPHERAL:
+	case MIPI_DSI_TURN_ON_PERIPHERAL:
+		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
+		if (check_rx_ack) {
+			/* process response func should be implemented. */
+			mutex_unlock(&dsim->lock);
+			return 0;
+		} else {
+			mutex_unlock(&dsim->lock);
+			return -EINVAL;
+		}
+
+	/* packet types for video data */
+	case MIPI_DSI_V_SYNC_START:
+	case MIPI_DSI_V_SYNC_END:
+	case MIPI_DSI_H_SYNC_START:
+	case MIPI_DSI_H_SYNC_END:
+	case MIPI_DSI_END_OF_TRANSMISSION:
+		mutex_unlock(&dsim->lock);
+		return 0;
+
+	/* long packet type and null packet */
+	case MIPI_DSI_NULL_PACKET:
+	case MIPI_DSI_BLANKING_PACKET:
+		mutex_unlock(&dsim->lock);
+		return 0;
+	case MIPI_DSI_GENERIC_LONG_WRITE:
+	case MIPI_DSI_DCS_LONG_WRITE:
+	{
+		unsigned int size, payload = 0;
+		reinit_completion(&dsim_wr_comp);
+
+		size = data_size * 4;
+
+		/* if data count is less then 4, then send 3bytes data.  */
+		if (data_size < 4) {
+			payload = data0[0] |
+				data0[1] << 8 |
+				data0[2] << 16;
+
+			exynos_mipi_dsi_wr_tx_data(dsim, payload);
+
+			dev_dbg(dsim->dev, "count = %d payload = %x,%x %x %x\n",
+				data_size, payload, data0[0],
+				data0[1], data0[2]);
+
+		/* in case that data count is more then 4 */
+		} else
+			exynos_mipi_dsi_long_data_wr(dsim, data0, data_size);
+
+		/* put data into header fifo */
+		exynos_mipi_dsi_wr_tx_header(dsim, data_id, data_size & 0xff,
+			(data_size & 0xff00) >> 8);
+
+		if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp,
+							MIPI_FIFO_TIMEOUT)) {
+			dev_warn(dsim->dev, "command write timeout.\n");
+			mutex_unlock(&dsim->lock);
+			return -EAGAIN;
+		}
+
+		if (check_rx_ack) {
+			/* process response func should be implemented. */
+			mutex_unlock(&dsim->lock);
+			return 0;
+		} else {
+			mutex_unlock(&dsim->lock);
+			return -EINVAL;
+		}
+	}
+
+	/* packet typo for video data */
+	case MIPI_DSI_PACKED_PIXEL_STREAM_16:
+	case MIPI_DSI_PACKED_PIXEL_STREAM_18:
+	case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
+	case MIPI_DSI_PACKED_PIXEL_STREAM_24:
+		if (check_rx_ack) {
+			/* process response func should be implemented. */
+			mutex_unlock(&dsim->lock);
+			return 0;
+		} else {
+			mutex_unlock(&dsim->lock);
+			return -EINVAL;
+		}
+	default:
+		dev_warn(dsim->dev,
+			"data id %x is not supported current DSI spec.\n",
+			data_id);
+
+		mutex_unlock(&dsim->lock);
+		return -EINVAL;
+	}
+}
+
+static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
+		unsigned int req_size, unsigned int rx_data, u8 *rx_buf)
+{
+	unsigned int rcv_pkt, i, j;
+	u16 rxsize;
+
+	/* for long packet */
+	rxsize = (u16)((rx_data & 0x00ffff00) >> 8);
+	dev_dbg(dsim->dev, "mipi dsi rx size : %d\n", rxsize);
+	if (rxsize != req_size) {
+		dev_dbg(dsim->dev,
+			"received size mismatch received: %d, requested: %d\n",
+			rxsize, req_size);
+		goto err;
+	}
+
+	for (i = 0; i < (rxsize >> 2); i++) {
+		rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+		dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
+		for (j = 0; j < 4; j++) {
+			rx_buf[(i * 4) + j] =
+					(u8)(rcv_pkt >> (j * 8)) & 0xff;
+			dev_dbg(dsim->dev, "received value : %02x\n",
+					(rcv_pkt >> (j * 8)) & 0xff);
+		}
+	}
+	if (rxsize % 4) {
+		rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+		dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
+		for (j = 0; j < (rxsize % 4); j++) {
+			rx_buf[(i * 4) + j] =
+					(u8)(rcv_pkt >> (j * 8)) & 0xff;
+			dev_dbg(dsim->dev, "received value : %02x\n",
+					(rcv_pkt >> (j * 8)) & 0xff);
+		}
+	}
+
+	return rxsize;
+
+err:
+	return -EINVAL;
+}
+
+static unsigned int exynos_mipi_dsi_response_size(unsigned int req_size)
+{
+	switch (req_size) {
+	case 1:
+		return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE;
+	case 2:
+		return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE;
+	default:
+		return MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE;
+	}
+}
+
+int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+	unsigned int data0, unsigned int req_size, u8 *rx_buf)
+{
+	unsigned int rx_data, rcv_pkt, i;
+	u8 response = 0;
+	u16 rxsize;
+
+	if (dsim->state == DSIM_STATE_ULPS) {
+		dev_err(dsim->dev, "state is ULPS.\n");
+
+		return -EINVAL;
+	}
+
+	/* FIXME!!! */
+	msleep(20);
+
+	mutex_lock(&dsim->lock);
+	reinit_completion(&dsim_rd_comp);
+	exynos_mipi_dsi_rd_tx_header(dsim,
+		MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, req_size);
+
+	response = exynos_mipi_dsi_response_size(req_size);
+
+	switch (data_id) {
+	case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
+	case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
+	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
+	case MIPI_DSI_DCS_READ:
+		exynos_mipi_dsi_rd_tx_header(dsim,
+			data_id, data0);
+		/* process response func should be implemented. */
+		break;
+	default:
+		dev_warn(dsim->dev,
+			"data id %x is not supported current DSI spec.\n",
+			data_id);
+
+		mutex_unlock(&dsim->lock);
+		return -EINVAL;
+	}
+
+	if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp,
+				MIPI_FIFO_TIMEOUT)) {
+		pr_err("RX done interrupt timeout\n");
+		mutex_unlock(&dsim->lock);
+		return 0;
+	}
+
+	msleep(20);
+
+	rx_data = exynos_mipi_dsi_rd_rx_fifo(dsim);
+
+	if ((u8)(rx_data & 0xff) != response) {
+		printk(KERN_ERR
+			"mipi dsi wrong response rx_data : %x, response:%x\n",
+			rx_data, response);
+		goto clear_rx_fifo;
+	}
+
+	if (req_size <= 2) {
+		/* for short packet */
+		for (i = 0; i < req_size; i++)
+			rx_buf[i] = (rx_data >> (8 + (i * 8))) & 0xff;
+		rxsize = req_size;
+	} else {
+		/* for long packet */
+		rxsize = exynos_mipi_dsi_long_data_rd(dsim, req_size, rx_data,
+							rx_buf);
+		if (rxsize != req_size)
+			goto clear_rx_fifo;
+	}
+
+	rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+
+	msleep(20);
+
+	if (rcv_pkt != MIPI_RX_FIFO_READ_DONE) {
+		dev_info(dsim->dev,
+			"Can't found RX FIFO READ DONE FLAG : %x\n", rcv_pkt);
+		goto clear_rx_fifo;
+	}
+
+	mutex_unlock(&dsim->lock);
+
+	return rxsize;
+
+clear_rx_fifo:
+	i = 0;
+	while (1) {
+		rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+		if ((rcv_pkt == MIPI_RX_FIFO_READ_DONE)
+				|| (i > MIPI_MAX_RX_FIFO))
+			break;
+		dev_dbg(dsim->dev,
+				"mipi dsi clear rx fifo : %08x\n", rcv_pkt);
+		i++;
+	}
+	dev_info(dsim->dev,
+		"mipi dsi rx done count : %d, rcv_pkt : %08x\n", i, rcv_pkt);
+
+	mutex_unlock(&dsim->lock);
+
+	return 0;
+}
+
+static int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim,
+				unsigned int enable)
+{
+	int sw_timeout;
+
+	if (enable) {
+		sw_timeout = 1000;
+
+		exynos_mipi_dsi_enable_pll(dsim, 1);
+		while (1) {
+			sw_timeout--;
+			if (exynos_mipi_dsi_is_pll_stable(dsim))
+				return 0;
+			if (sw_timeout == 0)
+				return -EINVAL;
+		}
+	} else
+		exynos_mipi_dsi_enable_pll(dsim, 0);
+
+	return 0;
+}
+
+static unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim,
+	unsigned int pre_divider, unsigned int main_divider,
+	unsigned int scaler)
+{
+	unsigned long dfin_pll, dfvco, dpll_out;
+	unsigned int i, freq_band = 0xf;
+
+	dfin_pll = (FIN_HZ / pre_divider);
+
+	/******************************************************
+	 *	Serial Clock(=ByteClk X 8)	FreqBand[3:0] *
+	 ******************************************************
+	 *	~ 99.99 MHz			0000
+	 *	100 ~ 119.99 MHz		0001
+	 *	120 ~ 159.99 MHz		0010
+	 *	160 ~ 199.99 MHz		0011
+	 *	200 ~ 239.99 MHz		0100
+	 *	140 ~ 319.99 MHz		0101
+	 *	320 ~ 389.99 MHz		0110
+	 *	390 ~ 449.99 MHz		0111
+	 *	450 ~ 509.99 MHz		1000
+	 *	510 ~ 559.99 MHz		1001
+	 *	560 ~ 639.99 MHz		1010
+	 *	640 ~ 689.99 MHz		1011
+	 *	690 ~ 769.99 MHz		1100
+	 *	770 ~ 869.99 MHz		1101
+	 *	870 ~ 949.99 MHz		1110
+	 *	950 ~ 1000 MHz			1111
+	 ******************************************************/
+	if (dfin_pll < DFIN_PLL_MIN_HZ || dfin_pll > DFIN_PLL_MAX_HZ) {
+		dev_warn(dsim->dev, "fin_pll range should be 6MHz ~ 12MHz\n");
+		exynos_mipi_dsi_enable_afc(dsim, 0, 0);
+	} else {
+		if (dfin_pll < 7 * MHZ)
+			exynos_mipi_dsi_enable_afc(dsim, 1, 0x1);
+		else if (dfin_pll < 8 * MHZ)
+			exynos_mipi_dsi_enable_afc(dsim, 1, 0x0);
+		else if (dfin_pll < 9 * MHZ)
+			exynos_mipi_dsi_enable_afc(dsim, 1, 0x3);
+		else if (dfin_pll < 10 * MHZ)
+			exynos_mipi_dsi_enable_afc(dsim, 1, 0x2);
+		else if (dfin_pll < 11 * MHZ)
+			exynos_mipi_dsi_enable_afc(dsim, 1, 0x5);
+		else
+			exynos_mipi_dsi_enable_afc(dsim, 1, 0x4);
+	}
+
+	dfvco = dfin_pll * main_divider;
+	dev_dbg(dsim->dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n",
+				dfvco, dfin_pll, main_divider);
+	if (dfvco < DFVCO_MIN_HZ || dfvco > DFVCO_MAX_HZ)
+		dev_warn(dsim->dev, "fvco range should be 500MHz ~ 1000MHz\n");
+
+	dpll_out = dfvco / (1 << scaler);
+	dev_dbg(dsim->dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n",
+		dpll_out, dfvco, scaler);
+
+	for (i = 0; i < ARRAY_SIZE(dpll_table); i++) {
+		if (dpll_out < dpll_table[i] * MHZ) {
+			freq_band = i;
+			break;
+		}
+	}
+
+	dev_dbg(dsim->dev, "freq_band = %d\n", freq_band);
+
+	exynos_mipi_dsi_pll_freq(dsim, pre_divider, main_divider, scaler);
+
+	exynos_mipi_dsi_hs_zero_ctrl(dsim, 0);
+	exynos_mipi_dsi_prep_ctrl(dsim, 0);
+
+	/* Freq Band */
+	exynos_mipi_dsi_pll_freq_band(dsim, freq_band);
+
+	/* Stable time */
+	exynos_mipi_dsi_pll_stable_time(dsim, dsim->dsim_config->pll_stable_time);
+
+	/* Enable PLL */
+	dev_dbg(dsim->dev, "FOUT of mipi dphy pll is %luMHz\n",
+		(dpll_out / MHZ));
+
+	return dpll_out;
+}
+
+static int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim,
+	unsigned int byte_clk_sel, unsigned int enable)
+{
+	unsigned int esc_div;
+	unsigned long esc_clk_error_rate;
+	unsigned long hs_clk = 0, byte_clk = 0, escape_clk = 0;
+
+	if (enable) {
+		dsim->e_clk_src = byte_clk_sel;
+
+		/* Escape mode clock and byte clock source */
+		exynos_mipi_dsi_set_byte_clock_src(dsim, byte_clk_sel);
+
+		/* DPHY, DSIM Link : D-PHY clock out */
+		if (byte_clk_sel == DSIM_PLL_OUT_DIV8) {
+			hs_clk = exynos_mipi_dsi_change_pll(dsim,
+				dsim->dsim_config->p, dsim->dsim_config->m,
+				dsim->dsim_config->s);
+			if (hs_clk == 0) {
+				dev_err(dsim->dev,
+					"failed to get hs clock.\n");
+				return -EINVAL;
+			}
+
+			byte_clk = hs_clk / 8;
+			exynos_mipi_dsi_enable_pll_bypass(dsim, 0);
+			exynos_mipi_dsi_pll_on(dsim, 1);
+		/* DPHY : D-PHY clock out, DSIM link : external clock out */
+		} else if (byte_clk_sel == DSIM_EXT_CLK_DIV8) {
+			dev_warn(dsim->dev, "this project is not support\n");
+			dev_warn(dsim->dev,
+				"external clock source for MIPI DSIM.\n");
+		} else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS) {
+			dev_warn(dsim->dev, "this project is not support\n");
+			dev_warn(dsim->dev,
+				"external clock source for MIPI DSIM\n");
+		}
+
+		/* escape clock divider */
+		esc_div = byte_clk / (dsim->dsim_config->esc_clk);
+		dev_dbg(dsim->dev,
+			"esc_div = %d, byte_clk = %lu, esc_clk = %lu\n",
+			esc_div, byte_clk, dsim->dsim_config->esc_clk);
+		if ((byte_clk / esc_div) >= (20 * MHZ) ||
+				(byte_clk / esc_div) >
+					dsim->dsim_config->esc_clk)
+			esc_div += 1;
+
+		escape_clk = byte_clk / esc_div;
+		dev_dbg(dsim->dev,
+			"escape_clk = %lu, byte_clk = %lu, esc_div = %d\n",
+			escape_clk, byte_clk, esc_div);
+
+		/* enable escape clock. */
+		exynos_mipi_dsi_enable_byte_clock(dsim, 1);
+
+		/* enable byte clk and escape clock */
+		exynos_mipi_dsi_set_esc_clk_prs(dsim, 1, esc_div);
+		/* escape clock on lane */
+		exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
+			(DSIM_LANE_CLOCK | dsim->data_lane), 1);
+
+		dev_dbg(dsim->dev, "byte clock is %luMHz\n",
+			(byte_clk / MHZ));
+		dev_dbg(dsim->dev, "escape clock that user's need is %lu\n",
+			(dsim->dsim_config->esc_clk / MHZ));
+		dev_dbg(dsim->dev, "escape clock divider is %x\n", esc_div);
+		dev_dbg(dsim->dev, "escape clock is %luMHz\n",
+			((byte_clk / esc_div) / MHZ));
+
+		if ((byte_clk / esc_div) > escape_clk) {
+			esc_clk_error_rate = escape_clk /
+				(byte_clk / esc_div);
+			dev_warn(dsim->dev, "error rate is %lu over.\n",
+				(esc_clk_error_rate / 100));
+		} else if ((byte_clk / esc_div) < (escape_clk)) {
+			esc_clk_error_rate = (byte_clk / esc_div) /
+				escape_clk;
+			dev_warn(dsim->dev, "error rate is %lu under.\n",
+				(esc_clk_error_rate / 100));
+		}
+	} else {
+		exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
+			(DSIM_LANE_CLOCK | dsim->data_lane), 0);
+		exynos_mipi_dsi_set_esc_clk_prs(dsim, 0, 0);
+
+		/* disable escape clock. */
+		exynos_mipi_dsi_enable_byte_clock(dsim, 0);
+
+		if (byte_clk_sel == DSIM_PLL_OUT_DIV8)
+			exynos_mipi_dsi_pll_on(dsim, 0);
+	}
+
+	return 0;
+}
+
+int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim)
+{
+	dsim->state = DSIM_STATE_INIT;
+
+	switch (dsim->dsim_config->e_no_data_lane) {
+	case DSIM_DATA_LANE_1:
+		dsim->data_lane = DSIM_LANE_DATA0;
+		break;
+	case DSIM_DATA_LANE_2:
+		dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1;
+		break;
+	case DSIM_DATA_LANE_3:
+		dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
+			DSIM_LANE_DATA2;
+		break;
+	case DSIM_DATA_LANE_4:
+		dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
+			DSIM_LANE_DATA2 | DSIM_LANE_DATA3;
+		break;
+	default:
+		dev_info(dsim->dev, "data lane is invalid.\n");
+		return -EINVAL;
+	}
+
+	exynos_mipi_dsi_sw_reset(dsim);
+	exynos_mipi_dsi_func_reset(dsim);
+
+	exynos_mipi_dsi_dp_dn_swap(dsim, 0);
+
+	return 0;
+}
+
+void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim)
+{
+	unsigned int src = 0;
+
+	src = (INTSRC_SFR_FIFO_EMPTY | INTSRC_RX_DATA_DONE);
+	exynos_mipi_dsi_set_interrupt(dsim, src, 1);
+
+	src = 0;
+	src = ~(INTMSK_RX_DONE | INTMSK_FIFO_EMPTY);
+	exynos_mipi_dsi_set_interrupt_mask(dsim, src, 1);
+}
+
+int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
+	unsigned int enable)
+{
+	/* enable only frame done interrupt */
+	exynos_mipi_dsi_set_interrupt_mask(dsim, INTMSK_FRAME_DONE, enable);
+
+	return 0;
+}
+
+void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
+		unsigned int enable)
+{
+
+	/* consider Main display and Sub display. */
+
+	exynos_mipi_dsi_set_main_stand_by(dsim, enable);
+}
+
+int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
+	struct mipi_dsim_config *dsim_config)
+{
+	struct mipi_dsim_platform_data *dsim_pd;
+	struct fb_videomode *timing;
+
+	dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
+	timing = (struct fb_videomode *)dsim_pd->lcd_panel_info;
+
+	/* in case of VIDEO MODE (RGB INTERFACE), it sets polarities. */
+	if (dsim_config->e_interface == (u32) DSIM_VIDEO) {
+		if (dsim_config->auto_vertical_cnt == 0) {
+			exynos_mipi_dsi_set_main_disp_vporch(dsim,
+				dsim_config->cmd_allow,
+				timing->lower_margin,
+				timing->upper_margin);
+			exynos_mipi_dsi_set_main_disp_hporch(dsim,
+				timing->right_margin,
+				timing->left_margin);
+			exynos_mipi_dsi_set_main_disp_sync_area(dsim,
+				timing->vsync_len,
+				timing->hsync_len);
+		}
+	}
+
+	exynos_mipi_dsi_set_main_disp_resol(dsim, timing->xres,
+			timing->yres);
+
+	exynos_mipi_dsi_display_config(dsim, dsim_config);
+
+	dev_info(dsim->dev, "lcd panel ==> width = %d, height = %d\n",
+			timing->xres, timing->yres);
+
+	return 0;
+}
+
+int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim)
+{
+	unsigned int time_out = 100;
+
+	switch (dsim->state) {
+	case DSIM_STATE_INIT:
+		exynos_mipi_dsi_init_fifo_pointer(dsim, 0x1f);
+
+		/* dsi configuration */
+		exynos_mipi_dsi_init_config(dsim);
+		exynos_mipi_dsi_enable_lane(dsim, DSIM_LANE_CLOCK, 1);
+		exynos_mipi_dsi_enable_lane(dsim, dsim->data_lane, 1);
+
+		/* set clock configuration */
+		exynos_mipi_dsi_set_clock(dsim, dsim->dsim_config->e_byte_clk, 1);
+
+		/* check clock and data lane state are stop state */
+		while (!(exynos_mipi_dsi_is_lane_state(dsim))) {
+			time_out--;
+			if (time_out == 0) {
+				dev_err(dsim->dev,
+					"DSI Master is not stop state.\n");
+				dev_err(dsim->dev,
+					"Check initialization process\n");
+
+				return -EINVAL;
+			}
+		}
+		if (time_out != 0) {
+			dev_info(dsim->dev,
+				"DSI Master driver has been completed.\n");
+			dev_info(dsim->dev, "DSI Master state is stop state\n");
+		}
+
+		dsim->state = DSIM_STATE_STOP;
+
+		/* BTA sequence counters */
+		exynos_mipi_dsi_set_stop_state_counter(dsim,
+			dsim->dsim_config->stop_holding_cnt);
+		exynos_mipi_dsi_set_bta_timeout(dsim,
+			dsim->dsim_config->bta_timeout);
+		exynos_mipi_dsi_set_lpdr_timeout(dsim,
+			dsim->dsim_config->rx_timeout);
+
+		return 0;
+	default:
+		dev_info(dsim->dev, "DSI Master is already init.\n");
+		return 0;
+	}
+
+	return 0;
+}
+
+int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim)
+{
+	if (dsim->state != DSIM_STATE_STOP) {
+		dev_warn(dsim->dev, "DSIM is not in stop state.\n");
+		return 0;
+	}
+
+	if (dsim->e_clk_src == DSIM_EXT_CLK_BYPASS) {
+		dev_warn(dsim->dev, "clock source is external bypass.\n");
+		return 0;
+	}
+
+	dsim->state = DSIM_STATE_HSCLKEN;
+
+	 /* set LCDC and CPU transfer mode to HS. */
+	exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
+	exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
+	exynos_mipi_dsi_enable_hs_clock(dsim, 1);
+
+	return 0;
+}
+
+int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
+		unsigned int mode)
+{
+	if (mode) {
+		if (dsim->state != DSIM_STATE_HSCLKEN) {
+			dev_err(dsim->dev, "HS Clock lane is not enabled.\n");
+			return -EINVAL;
+		}
+
+		exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
+	} else {
+		if (dsim->state == DSIM_STATE_INIT || dsim->state ==
+			DSIM_STATE_ULPS) {
+			dev_err(dsim->dev,
+				"DSI Master is not STOP or HSDT state.\n");
+			return -EINVAL;
+		}
+
+		exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
+	}
+
+	return 0;
+}
+
+int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
+{
+	return _exynos_mipi_dsi_get_frame_done_status(dsim);
+}
+
+int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
+{
+	_exynos_mipi_dsi_clear_frame_done(dsim);
+
+	return 0;
+}
+
+int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
+				unsigned int val)
+{
+	int try = TRY_FIFO_CLEAR;
+
+	exynos_mipi_dsi_sw_reset_release(dsim);
+	exynos_mipi_dsi_func_reset(dsim);
+
+	do {
+		if (exynos_mipi_dsi_get_sw_reset_release(dsim)) {
+			exynos_mipi_dsi_init_interrupt(dsim);
+			dev_dbg(dsim->dev, "reset release done.\n");
+			return 0;
+		}
+	} while (--try);
+
+	dev_err(dsim->dev, "failed to clear dsim fifo.\n");
+	return -EAGAIN;
+}
+
+MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samusung SoC MIPI-DSI common driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h
new file mode 100644
index 000000000000..412552274df3
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h
@@ -0,0 +1,46 @@
+/* linux/drivers/video/exynos_mipi_dsi_common.h
+ *
+ * Header file for Samsung SoC MIPI-DSI common driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _EXYNOS_MIPI_DSI_COMMON_H
+#define _EXYNOS_MIPI_DSI_COMMON_H
+
+static DECLARE_COMPLETION(dsim_rd_comp);
+static DECLARE_COMPLETION(dsim_wr_comp);
+
+int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+	const unsigned char *data0, unsigned int data_size);
+int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+	unsigned int data0, unsigned int req_size, u8 *rx_buf);
+irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id);
+void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
+		unsigned int enable);
+int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
+			struct mipi_dsim_config *dsim_info);
+int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
+		unsigned int mode);
+int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
+	unsigned int enable);
+int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
+
+extern struct fb_info *registered_fb[FB_MAX] __read_mostly;
+
+int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
+				unsigned int val);
+
+#endif /* _EXYNOS_MIPI_DSI_COMMON_H */
diff --git a/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c
new file mode 100644
index 000000000000..c148d06540c1
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c
@@ -0,0 +1,618 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
+ *
+ * Samsung SoC MIPI-DSI lowlevel driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/ctype.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <video/exynos_mipi_dsim.h>
+
+#include "exynos_mipi_dsi_regs.h"
+#include "exynos_mipi_dsi_lowlevel.h"
+
+void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
+
+	reg |= DSIM_FUNCRST;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
+}
+
+void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
+
+	reg |= DSIM_SWRST;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
+}
+
+void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+	reg |= INTSRC_SW_RST_RELEASE;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim)
+{
+	return (readl(dsim->reg_base + EXYNOS_DSIM_INTSRC)) &
+			INTSRC_SW_RST_RELEASE;
+}
+
+unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_INTMSK);
+
+	return reg;
+}
+
+void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
+		unsigned int mode, unsigned int mask)
+{
+	unsigned int reg = 0;
+
+	if (mask)
+		reg |= mode;
+	else
+		reg &= ~mode;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTMSK);
+}
+
+void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
+		unsigned int cfg)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
+
+	writel(reg & ~(cfg), dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
+	mdelay(10);
+	reg |= cfg;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
+}
+
+/*
+ * this function set PLL P, M and S value in D-PHY
+ */
+void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
+		unsigned int value)
+{
+	writel(DSIM_AFC_CTL(value), dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
+}
+
+void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
+		unsigned int enable)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+
+	reg &= ~DSIM_MAIN_STAND_BY;
+
+	if (enable)
+		reg |= DSIM_MAIN_STAND_BY;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+}
+
+void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
+	unsigned int width_resol, unsigned int height_resol)
+{
+	unsigned int reg;
+
+	/* standby should be set after configuration so set to not ready*/
+	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL)) &
+		~(DSIM_MAIN_STAND_BY);
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+
+	reg &= ~((0x7ff << 16) | (0x7ff << 0));
+	reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol);
+
+	reg |= DSIM_MAIN_STAND_BY;
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+}
+
+void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
+	unsigned int cmd_allow, unsigned int vfront, unsigned int vback)
+{
+	unsigned int reg;
+
+	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MVPORCH)) &
+		~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) |
+		(DSIM_MAIN_VBP_MASK));
+
+	reg |= (DSIM_CMD_ALLOW_SHIFT(cmd_allow & 0xf) |
+		DSIM_STABLE_VFP_SHIFT(vfront & 0x7ff) |
+		DSIM_MAIN_VBP_SHIFT(vback & 0x7ff));
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_MVPORCH);
+}
+
+void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
+	unsigned int front, unsigned int back)
+{
+	unsigned int reg;
+
+	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MHPORCH)) &
+		~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK));
+
+	reg |= DSIM_MAIN_HFP_SHIFT(front) | DSIM_MAIN_HBP_SHIFT(back);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_MHPORCH);
+}
+
+void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
+	unsigned int vert, unsigned int hori)
+{
+	unsigned int reg;
+
+	reg = (readl(dsim->reg_base + EXYNOS_DSIM_MSYNC)) &
+		~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK));
+
+	reg |= (DSIM_MAIN_VSA_SHIFT(vert & 0x3ff) |
+		DSIM_MAIN_HSA_SHIFT(hori));
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_MSYNC);
+}
+
+void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
+	unsigned int vert, unsigned int hori)
+{
+	unsigned int reg;
+
+	reg = (readl(dsim->reg_base + EXYNOS_DSIM_SDRESOL)) &
+		~(DSIM_SUB_STANDY_MASK);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
+
+	reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK);
+	reg |= (DSIM_SUB_VRESOL_SHIFT(vert & 0x7ff) |
+		DSIM_SUB_HRESOL_SHIFT(hori & 0x7ff));
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
+
+	reg |= DSIM_SUB_STANDY_SHIFT(1);
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
+}
+
+void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim)
+{
+	struct mipi_dsim_config *dsim_config = dsim->dsim_config;
+
+	unsigned int cfg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
+		~((1 << 28) | (0x1f << 20) | (0x3 << 5));
+
+	cfg =	((DSIM_AUTO_FLUSH(dsim_config->auto_flush)) |
+		(DSIM_EOT_DISABLE(dsim_config->eot_disable)) |
+		(DSIM_AUTO_MODE_SHIFT(dsim_config->auto_vertical_cnt)) |
+		(DSIM_HSE_MODE_SHIFT(dsim_config->hse)) |
+		(DSIM_HFP_MODE_SHIFT(dsim_config->hfp)) |
+		(DSIM_HBP_MODE_SHIFT(dsim_config->hbp)) |
+		(DSIM_HSA_MODE_SHIFT(dsim_config->hsa)) |
+		(DSIM_NUM_OF_DATALANE_SHIFT(dsim_config->e_no_data_lane)));
+
+	writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
+				struct mipi_dsim_config *dsim_config)
+{
+	u32 reg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
+		~((0x3 << 26) | (1 << 25) | (0x3 << 18) | (0x7 << 12) |
+		(0x3 << 16) | (0x7 << 8));
+
+	if (dsim_config->e_interface == DSIM_VIDEO)
+		reg |= (1 << 25);
+	else if (dsim_config->e_interface == DSIM_COMMAND)
+		reg &= ~(1 << 25);
+	else {
+		dev_err(dsim->dev, "unknown lcd type.\n");
+		return;
+	}
+
+	/* main lcd */
+	reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << 26 |
+		((u8) (dsim_config->e_virtual_ch) & 0x3) << 18 |
+		((u8) (dsim_config->e_pixel_format) & 0x7) << 12;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
+	unsigned int enable)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_CONFIG);
+
+	if (enable)
+		reg |= DSIM_LANE_ENx(lane);
+	else
+		reg &= ~DSIM_LANE_ENx(lane);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+
+void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
+	unsigned int count)
+{
+	unsigned int cfg;
+
+	/* get the data lane number. */
+	cfg = DSIM_NUM_OF_DATALANE_SHIFT(count);
+
+	writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
+	unsigned int afc_code)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
+
+	if (enable) {
+		reg |= (1 << 14);
+		reg &= ~(0x7 << 5);
+		reg |= (afc_code & 0x7) << 5;
+	} else
+		reg &= ~(1 << 14);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
+}
+
+void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
+	unsigned int enable)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+		~(DSIM_PLL_BYPASS_SHIFT(0x1));
+
+	reg |= DSIM_PLL_BYPASS_SHIFT(enable);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
+	unsigned int m, unsigned int s)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+
+	reg |= ((p & 0x3f) << 13) | ((m & 0x1ff) << 4) | ((s & 0x7) << 1);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
+		unsigned int freq_band)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+		~(DSIM_FREQ_BAND_SHIFT(0x1f));
+
+	reg |= DSIM_FREQ_BAND_SHIFT(freq_band & 0x1f);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
+		unsigned int pre_divider, unsigned int main_divider,
+		unsigned int scaler)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+		~(0x7ffff << 1);
+
+	reg |= (pre_divider & 0x3f) << 13 | (main_divider & 0x1ff) << 4 |
+		(scaler & 0x7) << 1;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
+	unsigned int lock_time)
+{
+	writel(lock_time, dsim->reg_base + EXYNOS_DSIM_PLLTMR);
+}
+
+void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, unsigned int enable)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+		~(DSIM_PLL_EN_SHIFT(0x1));
+
+	reg |= DSIM_PLL_EN_SHIFT(enable & 0x1);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
+		unsigned int src)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+		~(DSIM_BYTE_CLK_SRC_SHIFT(0x3));
+
+	reg |= (DSIM_BYTE_CLK_SRC_SHIFT(src));
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
+		unsigned int enable)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+		~(DSIM_BYTE_CLKEN_SHIFT(0x1));
+
+	reg |= DSIM_BYTE_CLKEN_SHIFT(enable);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
+		unsigned int enable, unsigned int prs_val)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+		~(DSIM_ESC_CLKEN_SHIFT(0x1) | 0xffff);
+
+	reg |= DSIM_ESC_CLKEN_SHIFT(enable);
+	if (enable)
+		reg |= prs_val;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
+		unsigned int lane_sel, unsigned int enable)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+
+	if (enable)
+		reg |= DSIM_LANE_ESC_CLKEN(lane_sel);
+	else
+
+		reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
+	unsigned int enable)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
+		~(DSIM_FORCE_STOP_STATE_SHIFT(0x1));
+
+	reg |= (DSIM_FORCE_STOP_STATE_SHIFT(enable & 0x1));
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
+
+	/**
+	 * check clock and data lane states.
+	 * if MIPI-DSI controller was enabled at bootloader then
+	 * TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK.
+	 * so it should be checked for two case.
+	 */
+	if ((reg & DSIM_STOP_STATE_DAT(0xf)) &&
+			((reg & DSIM_STOP_STATE_CLK) ||
+			 (reg & DSIM_TX_READY_HS_CLK)))
+		return 1;
+
+	return 0;
+}
+
+void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
+		unsigned int cnt_val)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
+		~(DSIM_STOP_STATE_CNT_SHIFT(0x7ff));
+
+	reg |= (DSIM_STOP_STATE_CNT_SHIFT(cnt_val & 0x7ff));
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
+		unsigned int timeout)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
+		~(DSIM_BTA_TOUT_SHIFT(0xff));
+
+	reg |= (DSIM_BTA_TOUT_SHIFT(timeout));
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
+}
+
+void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
+		unsigned int timeout)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
+		~(DSIM_LPDR_TOUT_SHIFT(0xffff));
+
+	reg |= (DSIM_LPDR_TOUT_SHIFT(timeout));
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
+}
+
+void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
+		unsigned int lp)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+
+	reg &= ~DSIM_CMD_LPDT_LP;
+
+	if (lp)
+		reg |= DSIM_CMD_LPDT_LP;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
+		unsigned int lp)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+
+	reg &= ~DSIM_TX_LPDT_LP;
+
+	if (lp)
+		reg |= DSIM_TX_LPDT_LP;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
+		unsigned int enable)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+		~(DSIM_TX_REQUEST_HSCLK_SHIFT(0x1));
+
+	reg |= DSIM_TX_REQUEST_HSCLK_SHIFT(enable);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
+		unsigned int swap_en)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
+
+	reg &= ~(0x3 << 0);
+	reg |= (swap_en & 0x3) << 0;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
+}
+
+void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
+		unsigned int hs_zero)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+		~(0xf << 28);
+
+	reg |= ((hs_zero & 0xf) << 28);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep)
+{
+	unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+		~(0x7 << 20);
+
+	reg |= ((prep & 0x7) << 20);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim)
+{
+	return readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
+					unsigned int src)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+	reg |= src;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
+					unsigned int src, unsigned int enable)
+{
+	unsigned int reg = 0;
+
+	if (enable)
+		reg |= src;
+	else
+		reg &= ~src;
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg;
+
+	reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
+
+	return reg & (1 << 31) ? 1 : 0;
+}
+
+unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)
+{
+	return readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL) & ~(0x1f);
+}
+
+void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim,
+	unsigned int di, unsigned int data0, unsigned int data1)
+{
+	unsigned int reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
+}
+
+void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
+	unsigned int di, unsigned int data0)
+{
+	unsigned int reg = (data0 << 8) | (di << 0);
+
+	writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
+}
+
+unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim)
+{
+	return readl(dsim->reg_base + EXYNOS_DSIM_RXFIFO);
+}
+
+unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+	return (reg & INTSRC_FRAME_DONE) ? 1 : 0;
+}
+
+void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
+{
+	unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+	writel(reg | INTSRC_FRAME_DONE, dsim->reg_base +
+		EXYNOS_DSIM_INTSRC);
+}
+
+void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
+		unsigned int tx_data)
+{
+	writel(tx_data, dsim->reg_base + EXYNOS_DSIM_PAYLOAD);
+}
diff --git a/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h
new file mode 100644
index 000000000000..85460701c7ea
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h
@@ -0,0 +1,112 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
+ *
+ * Header file for Samsung SoC MIPI-DSI lowlevel driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H
+#define _EXYNOS_MIPI_DSI_LOWLEVEL_H
+
+void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
+	unsigned int mode, unsigned int mask);
+void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
+					unsigned int count);
+void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
+					unsigned int cfg);
+void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
+				unsigned int value);
+void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
+				unsigned int value);
+void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
+		unsigned int enable);
+void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
+		unsigned int width_resol, unsigned int height_resol);
+void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
+	unsigned int cmd_allow, unsigned int vfront, unsigned int vback);
+void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
+			unsigned int front, unsigned int back);
+void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
+				unsigned int vert, unsigned int hori);
+void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
+				unsigned int vert, unsigned int hori);
+void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
+				struct mipi_dsim_config *dsim_config);
+void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
+				unsigned int count);
+void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
+				unsigned int enable);
+void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
+				unsigned int afc_code);
+void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
+				unsigned int enable);
+void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
+				unsigned int m, unsigned int s);
+void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
+				unsigned int freq_band);
+void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
+			unsigned int pre_divider, unsigned int main_divider,
+			unsigned int scaler);
+void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
+			unsigned int lock_time);
+void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim,
+					unsigned int enable);
+void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
+					unsigned int src);
+void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
+					unsigned int enable);
+void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
+				unsigned int enable, unsigned int prs_val);
+void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
+				unsigned int lane_sel, unsigned int enable);
+void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
+				unsigned int enable);
+unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
+				unsigned int cnt_val);
+void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
+				unsigned int timeout);
+void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
+				unsigned int timeout);
+void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
+					unsigned int lp);
+void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
+					unsigned int lp);
+void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
+				unsigned int enable);
+void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
+				unsigned int swap_en);
+void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
+				unsigned int hs_zero);
+void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep);
+unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim);
+unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
+					unsigned int src);
+void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
+					unsigned int src, unsigned int enable);
+unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim);
+unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim);
+unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
+void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, unsigned int di,
+				unsigned int data0, unsigned int data1);
+void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
+		unsigned int tx_data);
+void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
+		unsigned int data0, unsigned int data1);
+unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim);
+
+#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */
diff --git a/drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h
new file mode 100644
index 000000000000..4227106d3fd0
--- /dev/null
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h
@@ -0,0 +1,149 @@
+/* linux/driver/video/exynos/exynos_mipi_dsi_regs.h
+ *
+ * Register definition file for Samsung MIPI-DSIM driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _EXYNOS_MIPI_DSI_REGS_H
+#define _EXYNOS_MIPI_DSI_REGS_H
+
+#define EXYNOS_DSIM_STATUS		0x0	/* Status register */
+#define EXYNOS_DSIM_SWRST		0x4	/* Software reset register */
+#define EXYNOS_DSIM_CLKCTRL		0x8	/* Clock control register */
+#define EXYNOS_DSIM_TIMEOUT		0xc	/* Time out register */
+#define EXYNOS_DSIM_CONFIG		0x10	/* Configuration register */
+#define EXYNOS_DSIM_ESCMODE		0x14	/* Escape mode register */
+
+/* Main display image resolution register */
+#define EXYNOS_DSIM_MDRESOL		0x18
+#define EXYNOS_DSIM_MVPORCH		0x1c	/* Main display Vporch register */
+#define EXYNOS_DSIM_MHPORCH		0x20	/* Main display Hporch register */
+#define EXYNOS_DSIM_MSYNC		0x24	/* Main display sync area register */
+
+/* Sub display image resolution register */
+#define EXYNOS_DSIM_SDRESOL		0x28
+#define EXYNOS_DSIM_INTSRC		0x2c	/* Interrupt source register */
+#define EXYNOS_DSIM_INTMSK		0x30	/* Interrupt mask register */
+#define EXYNOS_DSIM_PKTHDR		0x34	/* Packet Header FIFO register */
+#define EXYNOS_DSIM_PAYLOAD		0x38	/* Payload FIFO register */
+#define EXYNOS_DSIM_RXFIFO		0x3c	/* Read FIFO register */
+#define EXYNOS_DSIM_FIFOTHLD		0x40	/* FIFO threshold level register */
+#define EXYNOS_DSIM_FIFOCTRL		0x44	/* FIFO status and control register */
+
+/* FIFO memory AC characteristic register */
+#define EXYNOS_DSIM_PLLCTRL		0x4c	/* PLL control register */
+#define EXYNOS_DSIM_PLLTMR		0x50	/* PLL timer register */
+#define EXYNOS_DSIM_PHYACCHR		0x54	/* D-PHY AC characteristic register */
+#define EXYNOS_DSIM_PHYACCHR1		0x58	/* D-PHY AC characteristic register1 */
+
+/* DSIM_STATUS */
+#define DSIM_STOP_STATE_DAT(x)		(((x) & 0xf) << 0)
+#define DSIM_STOP_STATE_CLK		(1 << 8)
+#define DSIM_TX_READY_HS_CLK		(1 << 10)
+
+/* DSIM_SWRST */
+#define DSIM_FUNCRST			(1 << 16)
+#define DSIM_SWRST			(1 << 0)
+
+/* EXYNOS_DSIM_TIMEOUT */
+#define DSIM_LPDR_TOUT_SHIFT(x)		((x) << 0)
+#define DSIM_BTA_TOUT_SHIFT(x)		((x) << 16)
+
+/* EXYNOS_DSIM_CLKCTRL */
+#define DSIM_LANE_ESC_CLKEN(x)		(((x) & 0x1f) << 19)
+#define DSIM_BYTE_CLKEN_SHIFT(x)	((x) << 24)
+#define DSIM_BYTE_CLK_SRC_SHIFT(x)	((x) <<	25)
+#define DSIM_PLL_BYPASS_SHIFT(x)	((x) <<	27)
+#define DSIM_ESC_CLKEN_SHIFT(x)		((x) << 28)
+#define DSIM_TX_REQUEST_HSCLK_SHIFT(x)	((x) << 31)
+
+/* EXYNOS_DSIM_CONFIG */
+#define DSIM_LANE_ENx(x)		(((x) & 0x1f) << 0)
+#define DSIM_NUM_OF_DATALANE_SHIFT(x)	((x) << 5)
+#define DSIM_HSA_MODE_SHIFT(x)		((x) << 20)
+#define DSIM_HBP_MODE_SHIFT(x)		((x) << 21)
+#define DSIM_HFP_MODE_SHIFT(x)		((x) << 22)
+#define DSIM_HSE_MODE_SHIFT(x)		((x) << 23)
+#define DSIM_AUTO_MODE_SHIFT(x)		((x) << 24)
+#define DSIM_EOT_DISABLE(x)		((x) << 28)
+#define DSIM_AUTO_FLUSH(x)		((x) << 29)
+
+#define DSIM_NUM_OF_DATA_LANE(x)	((x) << DSIM_NUM_OF_DATALANE_SHIFT)
+
+/* EXYNOS_DSIM_ESCMODE */
+#define DSIM_TX_LPDT_LP			(1 << 6)
+#define DSIM_CMD_LPDT_LP		(1 << 7)
+#define DSIM_FORCE_STOP_STATE_SHIFT(x)	((x) << 20)
+#define DSIM_STOP_STATE_CNT_SHIFT(x)	((x) << 21)
+
+/* EXYNOS_DSIM_MDRESOL */
+#define DSIM_MAIN_STAND_BY		(1 << 31)
+#define DSIM_MAIN_VRESOL(x)		(((x) & 0x7ff) << 16)
+#define DSIM_MAIN_HRESOL(x)		(((x) & 0X7ff) << 0)
+
+/* EXYNOS_DSIM_MVPORCH */
+#define DSIM_CMD_ALLOW_SHIFT(x)		((x) << 28)
+#define DSIM_STABLE_VFP_SHIFT(x)	((x) << 16)
+#define DSIM_MAIN_VBP_SHIFT(x)		((x) << 0)
+#define DSIM_CMD_ALLOW_MASK		(0xf << 28)
+#define DSIM_STABLE_VFP_MASK		(0x7ff << 16)
+#define DSIM_MAIN_VBP_MASK		(0x7ff << 0)
+
+/* EXYNOS_DSIM_MHPORCH */
+#define DSIM_MAIN_HFP_SHIFT(x)		((x) << 16)
+#define DSIM_MAIN_HBP_SHIFT(x)		((x) << 0)
+#define DSIM_MAIN_HFP_MASK		((0xffff) << 16)
+#define DSIM_MAIN_HBP_MASK		((0xffff) << 0)
+
+/* EXYNOS_DSIM_MSYNC */
+#define DSIM_MAIN_VSA_SHIFT(x)		((x) << 22)
+#define DSIM_MAIN_HSA_SHIFT(x)		((x) << 0)
+#define DSIM_MAIN_VSA_MASK		((0x3ff) << 22)
+#define DSIM_MAIN_HSA_MASK		((0xffff) << 0)
+
+/* EXYNOS_DSIM_SDRESOL */
+#define DSIM_SUB_STANDY_SHIFT(x)	((x) << 31)
+#define DSIM_SUB_VRESOL_SHIFT(x)	((x) << 16)
+#define DSIM_SUB_HRESOL_SHIFT(x)	((x) << 0)
+#define DSIM_SUB_STANDY_MASK		((0x1) << 31)
+#define DSIM_SUB_VRESOL_MASK		((0x7ff) << 16)
+#define DSIM_SUB_HRESOL_MASK		((0x7ff) << 0)
+
+/* EXYNOS_DSIM_INTSRC */
+#define INTSRC_PLL_STABLE		(1 << 31)
+#define INTSRC_SW_RST_RELEASE		(1 << 30)
+#define INTSRC_SFR_FIFO_EMPTY		(1 << 29)
+#define INTSRC_FRAME_DONE		(1 << 24)
+#define INTSRC_RX_DATA_DONE		(1 << 18)
+
+/* EXYNOS_DSIM_INTMSK */
+#define INTMSK_FIFO_EMPTY		(1 << 29)
+#define INTMSK_BTA			(1 << 25)
+#define INTMSK_FRAME_DONE		(1 << 24)
+#define INTMSK_RX_TIMEOUT		(1 << 21)
+#define INTMSK_BTA_TIMEOUT		(1 << 20)
+#define INTMSK_RX_DONE			(1 << 18)
+#define INTMSK_RX_TE			(1 << 17)
+#define INTMSK_RX_ACK			(1 << 16)
+#define INTMSK_RX_ECC_ERR		(1 << 15)
+#define INTMSK_RX_CRC_ERR		(1 << 14)
+
+/* EXYNOS_DSIM_FIFOCTRL */
+#define SFR_HEADER_EMPTY		(1 << 22)
+
+/* EXYNOS_DSIM_PHYACCHR */
+#define DSIM_AFC_CTL(x)			(((x) & 0x7) << 5)
+
+/* EXYNOS_DSIM_PLLCTRL */
+#define DSIM_PLL_EN_SHIFT(x)		((x) << 23)
+#define DSIM_FREQ_BAND_SHIFT(x)		((x) << 24)
+
+#endif /* _EXYNOS_MIPI_DSI_REGS_H */
diff --git a/drivers/video/fbdev/exynos/s6e8ax0.c b/drivers/video/fbdev/exynos/s6e8ax0.c
new file mode 100644
index 000000000000..29e70ed3f154
--- /dev/null
+++ b/drivers/video/fbdev/exynos/s6e8ax0.c
@@ -0,0 +1,898 @@
+/* linux/drivers/video/exynos/s6e8ax0.c
+ *
+ * MIPI-DSI based s6e8ax0 AMOLED lcd 4.65 inch panel driver.
+ *
+ * Inki Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/lcd.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+#include <video/exynos_mipi_dsim.h>
+
+#define LDI_MTP_LENGTH		24
+#define DSIM_PM_STABLE_TIME	10
+#define MIN_BRIGHTNESS		0
+#define MAX_BRIGHTNESS		24
+#define GAMMA_TABLE_COUNT	26
+
+#define POWER_IS_ON(pwr)	((pwr) == FB_BLANK_UNBLANK)
+#define POWER_IS_OFF(pwr)	((pwr) == FB_BLANK_POWERDOWN)
+#define POWER_IS_NRM(pwr)	((pwr) == FB_BLANK_NORMAL)
+
+#define lcd_to_master(a)	(a->dsim_dev->master)
+#define lcd_to_master_ops(a)	((lcd_to_master(a))->master_ops)
+
+enum {
+	DSIM_NONE_STATE = 0,
+	DSIM_RESUME_COMPLETE = 1,
+	DSIM_FRAME_DONE = 2,
+};
+
+struct s6e8ax0 {
+	struct device	*dev;
+	unsigned int			power;
+	unsigned int			id;
+	unsigned int			gamma;
+	unsigned int			acl_enable;
+	unsigned int			cur_acl;
+
+	struct lcd_device	*ld;
+	struct backlight_device	*bd;
+
+	struct mipi_dsim_lcd_device	*dsim_dev;
+	struct lcd_platform_data	*ddi_pd;
+	struct mutex			lock;
+	bool  enabled;
+};
+
+
+static struct regulator_bulk_data supplies[] = {
+	{ .supply = "vdd3", },
+	{ .supply = "vci", },
+};
+
+static void s6e8ax0_regulator_enable(struct s6e8ax0 *lcd)
+{
+	int ret = 0;
+	struct lcd_platform_data *pd = NULL;
+
+	pd = lcd->ddi_pd;
+	mutex_lock(&lcd->lock);
+	if (!lcd->enabled) {
+		ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
+		if (ret)
+			goto out;
+
+		lcd->enabled = true;
+	}
+	msleep(pd->power_on_delay);
+out:
+	mutex_unlock(&lcd->lock);
+}
+
+static void s6e8ax0_regulator_disable(struct s6e8ax0 *lcd)
+{
+	int ret = 0;
+
+	mutex_lock(&lcd->lock);
+	if (lcd->enabled) {
+		ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+		if (ret)
+			goto out;
+
+		lcd->enabled = false;
+	}
+out:
+	mutex_unlock(&lcd->lock);
+}
+
+static const unsigned char s6e8ax0_22_gamma_30[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xf5, 0x00, 0xff, 0xad, 0xaf,
+	0xbA, 0xc3, 0xd8, 0xc5, 0x9f, 0xc6, 0x9e, 0xc1, 0xdc, 0xc0,
+	0x00, 0x61, 0x00, 0x5a, 0x00, 0x74,
+};
+
+static const unsigned char s6e8ax0_22_gamma_50[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xe8, 0x1f, 0xf7, 0xad, 0xc0,
+	0xb5, 0xc4, 0xdc, 0xc4, 0x9e, 0xc6, 0x9c, 0xbb, 0xd8, 0xbb,
+	0x00, 0x70, 0x00, 0x68, 0x00, 0x86,
+};
+
+static const unsigned char s6e8ax0_22_gamma_60[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xde, 0x1f, 0xef, 0xad, 0xc4,
+	0xb3, 0xc3, 0xdd, 0xc4, 0x9e, 0xc6, 0x9c, 0xbc, 0xd6, 0xba,
+	0x00, 0x75, 0x00, 0x6e, 0x00, 0x8d,
+};
+
+static const unsigned char s6e8ax0_22_gamma_70[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xd8, 0x1f, 0xe7, 0xaf, 0xc8,
+	0xb4, 0xc4, 0xdd, 0xc3, 0x9d, 0xc6, 0x9c, 0xbb, 0xd6, 0xb9,
+	0x00, 0x7a, 0x00, 0x72, 0x00, 0x93,
+};
+
+static const unsigned char s6e8ax0_22_gamma_80[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xc9, 0x1f, 0xde, 0xae, 0xc9,
+	0xb1, 0xc3, 0xdd, 0xc2, 0x9d, 0xc5, 0x9b, 0xbc, 0xd6, 0xbb,
+	0x00, 0x7f, 0x00, 0x77, 0x00, 0x99,
+};
+
+static const unsigned char s6e8ax0_22_gamma_90[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xc7, 0x1f, 0xd9, 0xb0, 0xcc,
+	0xb2, 0xc3, 0xdc, 0xc1, 0x9c, 0xc6, 0x9c, 0xbc, 0xd4, 0xb9,
+	0x00, 0x83, 0x00, 0x7b, 0x00, 0x9e,
+};
+
+static const unsigned char s6e8ax0_22_gamma_100[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xbd, 0x80, 0xcd, 0xba, 0xce,
+	0xb3, 0xc4, 0xde, 0xc3, 0x9c, 0xc4, 0x9, 0xb8, 0xd3, 0xb6,
+	0x00, 0x88, 0x00, 0x80, 0x00, 0xa5,
+};
+
+static const unsigned char s6e8ax0_22_gamma_120[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb9, 0x95, 0xc8, 0xb1, 0xcf,
+	0xb2, 0xc6, 0xdf, 0xc5, 0x9b, 0xc3, 0x99, 0xb6, 0xd2, 0xb6,
+	0x00, 0x8f, 0x00, 0x86, 0x00, 0xac,
+};
+
+static const unsigned char s6e8ax0_22_gamma_130[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc7, 0xb1, 0xd0,
+	0xb2, 0xc4, 0xdd, 0xc3, 0x9a, 0xc3, 0x98, 0xb6, 0xd0, 0xb4,
+	0x00, 0x92, 0x00, 0x8a, 0x00, 0xb1,
+};
+
+static const unsigned char s6e8ax0_22_gamma_140[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc5, 0xb2, 0xd0,
+	0xb3, 0xc3, 0xde, 0xc3, 0x9b, 0xc2, 0x98, 0xb6, 0xd0, 0xb4,
+	0x00, 0x95, 0x00, 0x8d, 0x00, 0xb5,
+};
+
+static const unsigned char s6e8ax0_22_gamma_150[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xa0, 0xc2, 0xb2, 0xd0,
+	0xb2, 0xc1, 0xdd, 0xc2, 0x9b, 0xc2, 0x98, 0xb4, 0xcf, 0xb1,
+	0x00, 0x99, 0x00, 0x90, 0x00, 0xba,
+};
+
+static const unsigned char s6e8ax0_22_gamma_160[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xa5, 0xbf, 0xb0, 0xd0,
+	0xb1, 0xc3, 0xde, 0xc2, 0x99, 0xc1, 0x97, 0xb4, 0xce, 0xb1,
+	0x00, 0x9c, 0x00, 0x93, 0x00, 0xbe,
+};
+
+static const unsigned char s6e8ax0_22_gamma_170[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb5, 0xbf, 0xb1, 0xd1,
+	0xb1, 0xc3, 0xde, 0xc3, 0x99, 0xc0, 0x96, 0xb4, 0xce, 0xb1,
+	0x00, 0x9f, 0x00, 0x96, 0x00, 0xc2,
+};
+
+static const unsigned char s6e8ax0_22_gamma_180[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb7, 0xbe, 0xb3, 0xd2,
+	0xb3, 0xc3, 0xde, 0xc2, 0x97, 0xbf, 0x95, 0xb4, 0xcd, 0xb1,
+	0x00, 0xa2, 0x00, 0x99, 0x00, 0xc5,
+};
+
+static const unsigned char s6e8ax0_22_gamma_190[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbe, 0xb2, 0xd2,
+	0xb2, 0xc3, 0xdd, 0xc3, 0x98, 0xbf, 0x95, 0xb2, 0xcc, 0xaf,
+	0x00, 0xa5, 0x00, 0x9c, 0x00, 0xc9,
+};
+
+static const unsigned char s6e8ax0_22_gamma_200[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbc, 0xb2, 0xd2,
+	0xb1, 0xc4, 0xdd, 0xc3, 0x97, 0xbe, 0x95, 0xb1, 0xcb, 0xae,
+	0x00, 0xa8, 0x00, 0x9f, 0x00, 0xcd,
+};
+
+static const unsigned char s6e8ax0_22_gamma_210[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc1, 0xbd, 0xb1, 0xd1,
+	0xb1, 0xc2, 0xde, 0xc2, 0x97, 0xbe, 0x94, 0xB0, 0xc9, 0xad,
+	0x00, 0xae, 0x00, 0xa4, 0x00, 0xd4,
+};
+
+static const unsigned char s6e8ax0_22_gamma_220[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc7, 0xbd, 0xb1, 0xd1,
+	0xb1, 0xc2, 0xdd, 0xc2, 0x97, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
+	0x00, 0xad, 0x00, 0xa2, 0x00, 0xd3,
+};
+
+static const unsigned char s6e8ax0_22_gamma_230[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc3, 0xbd, 0xb2, 0xd1,
+	0xb1, 0xc3, 0xdd, 0xc1, 0x96, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
+	0x00, 0xb0, 0x00, 0xa7, 0x00, 0xd7,
+};
+
+static const unsigned char s6e8ax0_22_gamma_240[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xcb, 0xbd, 0xb1, 0xd2,
+	0xb1, 0xc3, 0xdD, 0xc2, 0x95, 0xbd, 0x93, 0xaf, 0xc8, 0xab,
+	0x00, 0xb3, 0x00, 0xa9, 0x00, 0xdb,
+};
+
+static const unsigned char s6e8ax0_22_gamma_250[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xcc, 0xbe, 0xb0, 0xd2,
+	0xb0, 0xc3, 0xdD, 0xc2, 0x94, 0xbc, 0x92, 0xae, 0xc8, 0xab,
+	0x00, 0xb6, 0x00, 0xab, 0x00, 0xde,
+};
+
+static const unsigned char s6e8ax0_22_gamma_260[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xd0, 0xbe, 0xaf, 0xd1,
+	0xaf, 0xc2, 0xdd, 0xc1, 0x96, 0xbc, 0x93, 0xaf, 0xc8, 0xac,
+	0x00, 0xb7, 0x00, 0xad, 0x00, 0xe0,
+};
+
+static const unsigned char s6e8ax0_22_gamma_270[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xcF, 0xbd, 0xb0, 0xd2,
+	0xaf, 0xc2, 0xdc, 0xc1, 0x95, 0xbd, 0x93, 0xae, 0xc6, 0xaa,
+	0x00, 0xba, 0x00, 0xb0, 0x00, 0xe4,
+};
+
+static const unsigned char s6e8ax0_22_gamma_280[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xd0, 0xbd, 0xaf, 0xd0,
+	0xad, 0xc4, 0xdd, 0xc3, 0x95, 0xbd, 0x93, 0xac, 0xc5, 0xa9,
+	0x00, 0xbd, 0x00, 0xb2, 0x00, 0xe7,
+};
+
+static const unsigned char s6e8ax0_22_gamma_300[] = {
+	0xfa, 0x01, 0x60, 0x10, 0x60, 0xb5, 0xd3, 0xbd, 0xb1, 0xd2,
+	0xb0, 0xc0, 0xdc, 0xc0, 0x94, 0xba, 0x91, 0xac, 0xc5, 0xa9,
+	0x00, 0xc2, 0x00, 0xb7, 0x00, 0xed,
+};
+
+static const unsigned char *s6e8ax0_22_gamma_table[] = {
+	s6e8ax0_22_gamma_30,
+	s6e8ax0_22_gamma_50,
+	s6e8ax0_22_gamma_60,
+	s6e8ax0_22_gamma_70,
+	s6e8ax0_22_gamma_80,
+	s6e8ax0_22_gamma_90,
+	s6e8ax0_22_gamma_100,
+	s6e8ax0_22_gamma_120,
+	s6e8ax0_22_gamma_130,
+	s6e8ax0_22_gamma_140,
+	s6e8ax0_22_gamma_150,
+	s6e8ax0_22_gamma_160,
+	s6e8ax0_22_gamma_170,
+	s6e8ax0_22_gamma_180,
+	s6e8ax0_22_gamma_190,
+	s6e8ax0_22_gamma_200,
+	s6e8ax0_22_gamma_210,
+	s6e8ax0_22_gamma_220,
+	s6e8ax0_22_gamma_230,
+	s6e8ax0_22_gamma_240,
+	s6e8ax0_22_gamma_250,
+	s6e8ax0_22_gamma_260,
+	s6e8ax0_22_gamma_270,
+	s6e8ax0_22_gamma_280,
+	s6e8ax0_22_gamma_300,
+};
+
+static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+
+	static const unsigned char data_to_send[] = {
+		0xf8, 0x3d, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
+		0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
+		0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
+		0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8
+	};
+	static const unsigned char data_to_send_panel_reverse[] = {
+		0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
+		0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
+		0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
+		0xc1, 0x01, 0x41, 0xc1, 0x00, 0xc1, 0xf6, 0xf6, 0xc1
+	};
+
+	if (lcd->dsim_dev->panel_reverse)
+		ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+				data_to_send_panel_reverse,
+				ARRAY_SIZE(data_to_send_panel_reverse));
+	else
+		ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+				data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_display_cond(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xf2, 0x80, 0x03, 0x0d
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+/* Gamma 2.2 Setting (200cd, 7500K, 10MPCD) */
+static void s6e8ax0_gamma_cond(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	unsigned int gamma = lcd->bd->props.brightness;
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+			s6e8ax0_22_gamma_table[gamma],
+			GAMMA_TABLE_COUNT);
+}
+
+static void s6e8ax0_gamma_update(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xf7, 0x03
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send,
+		ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond1(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xd1, 0xfe, 0x80, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x40,
+		0x0d, 0x00, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond2(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0,
+		0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond3(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xe1, 0x10, 0x1c, 0x17, 0x08, 0x1d
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond4(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xe2, 0xed, 0x07, 0xc3, 0x13, 0x0d, 0x03
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond5(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x19, 0x33, 0x02
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+static void s6e8ax0_etc_cond6(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xe3, 0x40
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE_PARAM,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond7(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xe4, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_elvss_set(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xb1, 0x04, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_elvss_nvm_set(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xd9, 0x5c, 0x20, 0x0c, 0x0f, 0x41, 0x00, 0x10, 0x11,
+		0x12, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcb, 0xed,
+		0x64, 0xaf
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_sleep_in(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0x10, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_sleep_out(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0x11, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_display_on(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0x29, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_display_off(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0x28, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_apply_level2_key(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xf0, 0x5a, 0x5a
+	};
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_acl_on(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xc0, 0x01
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_acl_off(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	static const unsigned char data_to_send[] = {
+		0xc0, 0x00
+	};
+
+	ops->cmd_write(lcd_to_master(lcd),
+		MIPI_DSI_DCS_SHORT_WRITE,
+		data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+/* Full white 50% reducing setting */
+static void s6e8ax0_acl_ctrl_set(struct s6e8ax0 *lcd)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	/* Full white 50% reducing setting */
+	static const unsigned char cutoff_50[] = {
+		0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
+		0x00, 0x00, 0x04, 0xff,	0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2a, 0x31, 0x38,
+		0x3f, 0x46
+	};
+	/* Full white 45% reducing setting */
+	static const unsigned char cutoff_45[] = {
+		0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
+		0x00, 0x00, 0x04, 0xff,	0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x07, 0x0d, 0x13, 0x19, 0x1f, 0x25, 0x2b, 0x31,
+		0x37, 0x3d
+	};
+	/* Full white 40% reducing setting */
+	static const unsigned char cutoff_40[] = {
+		0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
+		0x00, 0x00, 0x04, 0xff,	0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x06, 0x0c, 0x11, 0x16, 0x1c, 0x21, 0x26, 0x2b,
+		0x31, 0x36
+	};
+
+	if (lcd->acl_enable) {
+		if (lcd->cur_acl == 0) {
+			if (lcd->gamma == 0 || lcd->gamma == 1) {
+				s6e8ax0_acl_off(lcd);
+				dev_dbg(&lcd->ld->dev,
+					"cur_acl=%d\n", lcd->cur_acl);
+			} else
+				s6e8ax0_acl_on(lcd);
+		}
+		switch (lcd->gamma) {
+		case 0: /* 30cd */
+			s6e8ax0_acl_off(lcd);
+			lcd->cur_acl = 0;
+			break;
+		case 1 ... 3: /* 50cd ~ 90cd */
+			ops->cmd_write(lcd_to_master(lcd),
+				MIPI_DSI_DCS_LONG_WRITE,
+				cutoff_40,
+				ARRAY_SIZE(cutoff_40));
+			lcd->cur_acl = 40;
+			break;
+		case 4 ... 7: /* 120cd ~ 210cd */
+			ops->cmd_write(lcd_to_master(lcd),
+				MIPI_DSI_DCS_LONG_WRITE,
+				cutoff_45,
+				ARRAY_SIZE(cutoff_45));
+			lcd->cur_acl = 45;
+			break;
+		case 8 ... 10: /* 220cd ~ 300cd */
+			ops->cmd_write(lcd_to_master(lcd),
+				MIPI_DSI_DCS_LONG_WRITE,
+				cutoff_50,
+				ARRAY_SIZE(cutoff_50));
+			lcd->cur_acl = 50;
+			break;
+		default:
+			break;
+		}
+	} else {
+		s6e8ax0_acl_off(lcd);
+		lcd->cur_acl = 0;
+		dev_dbg(&lcd->ld->dev, "cur_acl = %d\n", lcd->cur_acl);
+	}
+}
+
+static void s6e8ax0_read_id(struct s6e8ax0 *lcd, u8 *mtp_id)
+{
+	unsigned int ret;
+	unsigned int addr = 0xd1;	/* MTP ID */
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+
+	ret = ops->cmd_read(lcd_to_master(lcd),
+			MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM,
+			addr, 3, mtp_id);
+}
+
+static int s6e8ax0_panel_init(struct s6e8ax0 *lcd)
+{
+	s6e8ax0_apply_level2_key(lcd);
+	s6e8ax0_sleep_out(lcd);
+	msleep(1);
+	s6e8ax0_panel_cond(lcd);
+	s6e8ax0_display_cond(lcd);
+	s6e8ax0_gamma_cond(lcd);
+	s6e8ax0_gamma_update(lcd);
+
+	s6e8ax0_etc_cond1(lcd);
+	s6e8ax0_etc_cond2(lcd);
+	s6e8ax0_etc_cond3(lcd);
+	s6e8ax0_etc_cond4(lcd);
+	s6e8ax0_etc_cond5(lcd);
+	s6e8ax0_etc_cond6(lcd);
+	s6e8ax0_etc_cond7(lcd);
+
+	s6e8ax0_elvss_nvm_set(lcd);
+	s6e8ax0_elvss_set(lcd);
+
+	s6e8ax0_acl_ctrl_set(lcd);
+	s6e8ax0_acl_on(lcd);
+
+	/* if ID3 value is not 33h, branch private elvss mode */
+	msleep(lcd->ddi_pd->power_on_delay);
+
+	return 0;
+}
+
+static int s6e8ax0_update_gamma_ctrl(struct s6e8ax0 *lcd, int brightness)
+{
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+
+	ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+			s6e8ax0_22_gamma_table[brightness],
+			ARRAY_SIZE(s6e8ax0_22_gamma_table));
+
+	/* update gamma table. */
+	s6e8ax0_gamma_update(lcd);
+	lcd->gamma = brightness;
+
+	return 0;
+}
+
+static int s6e8ax0_gamma_ctrl(struct s6e8ax0 *lcd, int gamma)
+{
+	s6e8ax0_update_gamma_ctrl(lcd, gamma);
+
+	return 0;
+}
+
+static int s6e8ax0_set_power(struct lcd_device *ld, int power)
+{
+	struct s6e8ax0 *lcd = lcd_get_data(ld);
+	struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+	int ret = 0;
+
+	if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
+			power != FB_BLANK_NORMAL) {
+		dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
+		return -EINVAL;
+	}
+
+	if ((power == FB_BLANK_UNBLANK) && ops->set_blank_mode) {
+		/* LCD power on */
+		if ((POWER_IS_ON(power) && POWER_IS_OFF(lcd->power))
+			|| (POWER_IS_ON(power) && POWER_IS_NRM(lcd->power))) {
+			ret = ops->set_blank_mode(lcd_to_master(lcd), power);
+			if (!ret && lcd->power != power)
+				lcd->power = power;
+		}
+	} else if ((power == FB_BLANK_POWERDOWN) && ops->set_early_blank_mode) {
+		/* LCD power off */
+		if ((POWER_IS_OFF(power) && POWER_IS_ON(lcd->power)) ||
+		(POWER_IS_ON(lcd->power) && POWER_IS_NRM(power))) {
+			ret = ops->set_early_blank_mode(lcd_to_master(lcd),
+							power);
+			if (!ret && lcd->power != power)
+				lcd->power = power;
+		}
+	}
+
+	return ret;
+}
+
+static int s6e8ax0_get_power(struct lcd_device *ld)
+{
+	struct s6e8ax0 *lcd = lcd_get_data(ld);
+
+	return lcd->power;
+}
+
+static int s6e8ax0_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static int s6e8ax0_set_brightness(struct backlight_device *bd)
+{
+	int ret = 0, brightness = bd->props.brightness;
+	struct s6e8ax0 *lcd = bl_get_data(bd);
+
+	if (brightness < MIN_BRIGHTNESS ||
+		brightness > bd->props.max_brightness) {
+		dev_err(lcd->dev, "lcd brightness should be %d to %d.\n",
+			MIN_BRIGHTNESS, MAX_BRIGHTNESS);
+		return -EINVAL;
+	}
+
+	ret = s6e8ax0_gamma_ctrl(lcd, brightness);
+	if (ret) {
+		dev_err(&bd->dev, "lcd brightness setting failed.\n");
+		return -EIO;
+	}
+
+	return ret;
+}
+
+static struct lcd_ops s6e8ax0_lcd_ops = {
+	.set_power = s6e8ax0_set_power,
+	.get_power = s6e8ax0_get_power,
+};
+
+static const struct backlight_ops s6e8ax0_backlight_ops = {
+	.get_brightness = s6e8ax0_get_brightness,
+	.update_status = s6e8ax0_set_brightness,
+};
+
+static void s6e8ax0_power_on(struct mipi_dsim_lcd_device *dsim_dev, int power)
+{
+	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+	msleep(lcd->ddi_pd->power_on_delay);
+
+	/* lcd power on */
+	if (power)
+		s6e8ax0_regulator_enable(lcd);
+	else
+		s6e8ax0_regulator_disable(lcd);
+
+	msleep(lcd->ddi_pd->reset_delay);
+
+	/* lcd reset */
+	if (lcd->ddi_pd->reset)
+		lcd->ddi_pd->reset(lcd->ld);
+	msleep(5);
+}
+
+static void s6e8ax0_set_sequence(struct mipi_dsim_lcd_device *dsim_dev)
+{
+	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+	s6e8ax0_panel_init(lcd);
+	s6e8ax0_display_on(lcd);
+
+	lcd->power = FB_BLANK_UNBLANK;
+}
+
+static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev)
+{
+	struct s6e8ax0 *lcd;
+	int ret;
+	u8 mtp_id[3] = {0, };
+
+	lcd = devm_kzalloc(&dsim_dev->dev, sizeof(struct s6e8ax0), GFP_KERNEL);
+	if (!lcd) {
+		dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n");
+		return -ENOMEM;
+	}
+
+	lcd->dsim_dev = dsim_dev;
+	lcd->ddi_pd = (struct lcd_platform_data *)dsim_dev->platform_data;
+	lcd->dev = &dsim_dev->dev;
+
+	mutex_init(&lcd->lock);
+
+	ret = devm_regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
+	if (ret) {
+		dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
+		return ret;
+	}
+
+	lcd->ld = devm_lcd_device_register(lcd->dev, "s6e8ax0", lcd->dev, lcd,
+			&s6e8ax0_lcd_ops);
+	if (IS_ERR(lcd->ld)) {
+		dev_err(lcd->dev, "failed to register lcd ops.\n");
+		return PTR_ERR(lcd->ld);
+	}
+
+	lcd->bd = devm_backlight_device_register(lcd->dev, "s6e8ax0-bl",
+				lcd->dev, lcd, &s6e8ax0_backlight_ops, NULL);
+	if (IS_ERR(lcd->bd)) {
+		dev_err(lcd->dev, "failed to register backlight ops.\n");
+		return PTR_ERR(lcd->bd);
+	}
+
+	lcd->bd->props.max_brightness = MAX_BRIGHTNESS;
+	lcd->bd->props.brightness = MAX_BRIGHTNESS;
+
+	s6e8ax0_read_id(lcd, mtp_id);
+	if (mtp_id[0] == 0x00)
+		dev_err(lcd->dev, "read id failed\n");
+
+	dev_info(lcd->dev, "Read ID : %x, %x, %x\n",
+			mtp_id[0], mtp_id[1], mtp_id[2]);
+
+	if (mtp_id[2] == 0x33)
+		dev_info(lcd->dev,
+			"ID-3 is 0xff does not support dynamic elvss\n");
+	else
+		dev_info(lcd->dev,
+			"ID-3 is 0x%x support dynamic elvss\n", mtp_id[2]);
+
+	lcd->acl_enable = 1;
+	lcd->cur_acl = 0;
+
+	dev_set_drvdata(&dsim_dev->dev, lcd);
+
+	dev_dbg(lcd->dev, "probed s6e8ax0 panel driver.\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
+{
+	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+	s6e8ax0_sleep_in(lcd);
+	msleep(lcd->ddi_pd->power_off_delay);
+	s6e8ax0_display_off(lcd);
+
+	s6e8ax0_regulator_disable(lcd);
+
+	return 0;
+}
+
+static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
+{
+	struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+	s6e8ax0_sleep_out(lcd);
+	msleep(lcd->ddi_pd->power_on_delay);
+
+	s6e8ax0_regulator_enable(lcd);
+	s6e8ax0_set_sequence(dsim_dev);
+
+	return 0;
+}
+#else
+#define s6e8ax0_suspend		NULL
+#define s6e8ax0_resume		NULL
+#endif
+
+static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = {
+	.name = "s6e8ax0",
+	.id = -1,
+
+	.power_on = s6e8ax0_power_on,
+	.set_sequence = s6e8ax0_set_sequence,
+	.probe = s6e8ax0_probe,
+	.suspend = s6e8ax0_suspend,
+	.resume = s6e8ax0_resume,
+};
+
+static int s6e8ax0_init(void)
+{
+	exynos_mipi_dsi_register_lcd_driver(&s6e8ax0_dsim_ddi_driver);
+
+	return 0;
+}
+
+static void s6e8ax0_exit(void)
+{
+	return;
+}
+
+module_init(s6e8ax0_init);
+module_exit(s6e8ax0_exit);
+
+MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("MIPI-DSI based s6e8ax0 AMOLED LCD Panel Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/fb-puv3.c b/drivers/video/fbdev/fb-puv3.c
new file mode 100644
index 000000000000..6db9ebd042a3
--- /dev/null
+++ b/drivers/video/fbdev/fb-puv3.c
@@ -0,0 +1,838 @@
+/*
+ * Frame Buffer Driver for PKUnity-v3 Unigfx
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+
+/* Platform_data reserved for unifb registers. */
+#define UNIFB_REGS_NUM		10
+/* RAM reserved for the frame buffer. */
+#define UNIFB_MEMSIZE		(SZ_4M)		/* 4 MB for 1024*768*32b */
+
+/*
+ * cause UNIGFX don not have EDID
+ * all the modes are organized as follow
+ */
+static const struct fb_videomode unifb_modes[] = {
+	/* 0 640x480-60 VESA */
+	{ "640x480@60",  60,  640, 480,  25175000,  48, 16, 34, 10,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1 640x480-75 VESA */
+	{ "640x480@75",  75,  640, 480,  31500000, 120, 16, 18,  1,  64, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 2 800x600-60 VESA */
+	{ "800x600@60",  60,  800, 600,  40000000,  88, 40, 26,  1, 128, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 3 800x600-75 VESA */
+	{ "800x600@75",  75,  800, 600,  49500000, 160, 16, 23,  1,  80, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 4 1024x768-60 VESA */
+	{ "1024x768@60", 60, 1024, 768,  65000000, 160, 24, 34,  3, 136, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 5 1024x768-75 VESA */
+	{ "1024x768@75", 75, 1024, 768,  78750000, 176, 16, 30,  1,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 6 1280x960-60 VESA */
+	{ "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38,  1, 112, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 7 1440x900-60 VESA */
+	{ "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30,  3, 152, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 8 FIXME 9 1024x600-60 VESA UNTESTED */
+	{ "1024x600@60", 60, 1024, 600,  50650000, 160, 24, 26,  1, 136, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 9 FIXME 10 1024x600-75 VESA UNTESTED */
+	{ "1024x600@75", 75, 1024, 600,  61500000, 176, 16, 23,  1,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 10 FIXME 11 1366x768-60 VESA UNTESTED */
+	{ "1366x768@60", 60, 1366, 768,  85500000, 256, 58, 18,  1,  112, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+static struct fb_var_screeninfo unifb_default = {
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual =	480,
+	.bits_per_pixel = 16,
+	.red =		{ 11, 5, 0 },
+	.green =	{ 5,  6, 0 },
+	.blue =		{ 0,  5, 0 },
+	.activate =	FB_ACTIVATE_NOW,
+	.height =	-1,
+	.width =	-1,
+	.pixclock =	25175000,
+	.left_margin =	48,
+	.right_margin =	16,
+	.upper_margin =	33,
+	.lower_margin =	10,
+	.hsync_len =	96,
+	.vsync_len =	2,
+	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo unifb_fix = {
+	.id =		"UNIGFX FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static void unifb_sync(struct fb_info *info)
+{
+	/* TODO: may, this can be replaced by interrupt */
+	int cnt;
+
+	for (cnt = 0; cnt < 0x10000000; cnt++) {
+		if (readl(UGE_COMMAND) & 0x1000000)
+			return;
+	}
+
+	if (cnt > 0x8000000)
+		dev_warn(info->device, "Warning: UniGFX GE time out ...\n");
+}
+
+static void unifb_prim_fillrect(struct fb_info *info,
+				const struct fb_fillrect *region)
+{
+	int awidth = region->width;
+	int aheight = region->height;
+	int m_iBpp = info->var.bits_per_pixel;
+	int screen_width = info->var.xres;
+	int src_sel = 1;	/* from fg_color */
+	int pat_sel = 1;
+	int src_x0 = 0;
+	int dst_x0 = region->dx;
+	int src_y0 = 0;
+	int dst_y0 = region->dy;
+	int rop_alpha_sel = 0;
+	int rop_alpha_code = 0xCC;
+	int x_dir = 1;
+	int y_dir = 1;
+	int alpha_r = 0;
+	int alpha_sel = 0;
+	int dst_pitch = screen_width * (m_iBpp / 8);
+	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+	int src_pitch = screen_width * (m_iBpp / 8);
+	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+	unsigned int command = 0;
+	int clip_region = 0;
+	int clip_en = 0;
+	int tp_en = 0;
+	int fg_color = 0;
+	int bottom = info->var.yres - 1;
+	int right = info->var.xres - 1;
+	int top = 0;
+
+	bottom = (bottom << 16) | right;
+	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
+		| (x_dir << 20) | (y_dir << 21) | (command << 24)
+		| (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+	src_pitch = (dst_pitch << 16) | src_pitch;
+	awidth = awidth | (aheight << 16);
+	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
+		| (alpha_sel << 16);
+	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+	fg_color = region->color;
+
+	unifb_sync(info);
+
+	writel(((u32 *)(info->pseudo_palette))[fg_color], UGE_FCOLOR);
+	writel(0, UGE_BCOLOR);
+	writel(src_pitch, UGE_PITCH);
+	writel(src_offset, UGE_SRCSTART);
+	writel(dst_offset, UGE_DSTSTART);
+	writel(awidth, UGE_WIDHEIGHT);
+	writel(top, UGE_CLIP0);
+	writel(bottom, UGE_CLIP1);
+	writel(alpha_r, UGE_ROPALPHA);
+	writel(src_x0, UGE_SRCXY);
+	writel(dst_x0, UGE_DSTXY);
+	writel(command, UGE_COMMAND);
+}
+
+static void unifb_fillrect(struct fb_info *info,
+		const struct fb_fillrect *region)
+{
+	struct fb_fillrect modded;
+	int vxres, vyres;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		sys_fillrect(info, region);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if (!modded.width || !modded.height ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	unifb_prim_fillrect(info, &modded);
+}
+
+static void unifb_prim_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+	int awidth = area->width;
+	int aheight = area->height;
+	int m_iBpp = info->var.bits_per_pixel;
+	int screen_width = info->var.xres;
+	int src_sel = 2;	/* from mem */
+	int pat_sel = 0;
+	int src_x0 = area->sx;
+	int dst_x0 = area->dx;
+	int src_y0 = area->sy;
+	int dst_y0 = area->dy;
+
+	int rop_alpha_sel = 0;
+	int rop_alpha_code = 0xCC;
+	int x_dir = 1;
+	int y_dir = 1;
+
+	int alpha_r = 0;
+	int alpha_sel = 0;
+	int dst_pitch = screen_width * (m_iBpp / 8);
+	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+	int src_pitch = screen_width * (m_iBpp / 8);
+	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+	unsigned int command = 0;
+	int clip_region = 0;
+	int clip_en = 1;
+	int tp_en = 0;
+	int top = 0;
+	int bottom = info->var.yres;
+	int right = info->var.xres;
+	int fg_color = 0;
+	int bg_color = 0;
+
+	if (src_x0 < 0)
+		src_x0 = 0;
+	if (src_y0 < 0)
+		src_y0 = 0;
+
+	if (src_y0 - dst_y0 > 0) {
+		y_dir = 1;
+	} else {
+		y_dir = 0;
+		src_offset = (src_y0 + aheight) * src_pitch +
+				src_x0 * (m_iBpp / 8);
+		dst_offset = (dst_y0 + aheight) * dst_pitch +
+				dst_x0 * (m_iBpp / 8);
+		src_y0 += aheight;
+		dst_y0 += aheight;
+	}
+
+	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
+		(x_dir << 20) | (y_dir << 21) | (command << 24) |
+		(clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+	src_pitch = (dst_pitch << 16) | src_pitch;
+	awidth = awidth | (aheight << 16);
+	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
+		(alpha_sel << 16);
+	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+	bottom = (bottom << 16) | right;
+
+	unifb_sync(info);
+
+	writel(src_pitch, UGE_PITCH);
+	writel(src_offset, UGE_SRCSTART);
+	writel(dst_offset, UGE_DSTSTART);
+	writel(awidth, UGE_WIDHEIGHT);
+	writel(top, UGE_CLIP0);
+	writel(bottom, UGE_CLIP1);
+	writel(bg_color, UGE_BCOLOR);
+	writel(fg_color, UGE_FCOLOR);
+	writel(alpha_r, UGE_ROPALPHA);
+	writel(src_x0, UGE_SRCXY);
+	writel(dst_x0, UGE_DSTXY);
+	writel(command, UGE_COMMAND);
+}
+
+static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct fb_copyarea modded;
+	u32 vxres, vyres;
+	modded.sx = area->sx;
+	modded.sy = area->sy;
+	modded.dx = area->dx;
+	modded.dy = area->dy;
+	modded.width = area->width;
+	modded.height = area->height;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		sys_copyarea(info, area);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!modded.width || !modded.height ||
+	    modded.sx >= vxres || modded.sy >= vyres ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.sx + modded.width > vxres)
+		modded.width = vxres - modded.sx;
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.sy + modded.height > vyres)
+		modded.height = vyres - modded.sy;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	unifb_prim_copyarea(info, &modded);
+}
+
+static void unifb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	sys_imageblit(info, image);
+}
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+	u_long length;
+
+	length = xres_virtual * bpp;
+	length = (length + 31) & ~31;
+	length >>= 3;
+	return length;
+}
+
+/*
+ *  Setting the video mode has been split into two parts.
+ *  First part, xxxfb_check_var, must not write anything
+ *  to hardware, it should only verify and adjust var.
+ *  This means it doesn't alter par but it does use hardware
+ *  data from it to check this var.
+ */
+static int unifb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	u_long line_length;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/*
+	 *  Some very basic checks
+	 */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->bits_per_pixel <= 1)
+		var->bits_per_pixel = 1;
+	else if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xoffset + var->xres)
+		var->xres_virtual = var->xoffset + var->xres;
+	if (var->yres_virtual < var->yoffset + var->yres)
+		var->yres_virtual = var->yoffset + var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length =
+	    get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > UNIFB_MEMSIZE)
+		return -ENOMEM;
+
+	/*
+	 * Now that we checked it we alter var. The reason being is that the
+	 * video mode passed in might not work but slight changes to it might
+	 * make it work. This way we let the user know what is acceptable.
+	 */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGBA 5551 */
+		if (var->transp.length) {
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 10;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {	/* RGB 565 */
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:		/* RGB 888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/*
+ * This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ */
+static int unifb_set_par(struct fb_info *info)
+{
+	int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
+	int format;
+
+#ifdef CONFIG_PUV3_PM
+	struct clk *clk_vga;
+	u32 pixclk = 0;
+	int i;
+
+	for (i = 0; i <= 10; i++) {
+		if    (info->var.xres         == unifb_modes[i].xres
+		    && info->var.yres         == unifb_modes[i].yres
+		    && info->var.upper_margin == unifb_modes[i].upper_margin
+		    && info->var.lower_margin == unifb_modes[i].lower_margin
+		    && info->var.left_margin  == unifb_modes[i].left_margin
+		    && info->var.right_margin == unifb_modes[i].right_margin
+		    && info->var.hsync_len    == unifb_modes[i].hsync_len
+		    && info->var.vsync_len    == unifb_modes[i].vsync_len) {
+			pixclk = unifb_modes[i].pixclock;
+			break;
+		}
+	}
+
+	/* set clock rate */
+	clk_vga = clk_get(info->device, "VGA_CLK");
+	if (clk_vga == ERR_PTR(-ENOENT))
+		return -ENOENT;
+
+	if (pixclk != 0) {
+		if (clk_set_rate(clk_vga, pixclk)) { /* set clock failed */
+			info->fix = unifb_fix;
+			info->var = unifb_default;
+			if (clk_set_rate(clk_vga, unifb_default.pixclock))
+				return -EINVAL;
+		}
+	}
+#endif
+
+	info->fix.line_length = get_line_length(info->var.xres_virtual,
+						info->var.bits_per_pixel);
+
+	hSyncStart = info->var.xres + info->var.right_margin;
+	hSyncEnd = hSyncStart + info->var.hsync_len;
+	hTotal = hSyncEnd + info->var.left_margin;
+
+	vSyncStart = info->var.yres + info->var.lower_margin;
+	vSyncEnd = vSyncStart + info->var.vsync_len;
+	vTotal = vSyncEnd + info->var.upper_margin;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		format = UDE_CFG_DST8;
+		break;
+	case 16:
+		format = UDE_CFG_DST16;
+		break;
+	case 24:
+		format = UDE_CFG_DST24;
+		break;
+	case 32:
+		format = UDE_CFG_DST32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(info->fix.smem_start, UDE_FSA);
+	writel(info->var.yres, UDE_LS);
+	writel(get_line_length(info->var.xres,
+			info->var.bits_per_pixel) >> 3, UDE_PS);
+			/* >> 3 for hardware required. */
+	writel((hTotal << 16) | (info->var.xres), UDE_HAT);
+	writel(((hTotal - 1) << 16) | (info->var.xres - 1), UDE_HBT);
+	writel(((hSyncEnd - 1) << 16) | (hSyncStart - 1), UDE_HST);
+	writel((vTotal << 16) | (info->var.yres), UDE_VAT);
+	writel(((vTotal - 1) << 16) | (info->var.yres - 1), UDE_VBT);
+	writel(((vSyncEnd - 1) << 16) | (vSyncStart - 1), UDE_VST);
+	writel(UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE
+			| format | 0xC0000001, UDE_CFG);
+
+	return 0;
+}
+
+/*
+ *  Set a single color register. The values supplied are already
+ *  rounded down to the hardware's capabilities (according to the
+ *  entries in the var structure). Return != 0 for invalid regno.
+ */
+static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info)
+{
+	if (regno >= 256)	/* no. of hw registers */
+		return 1;
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return 1;
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+		case 24:
+		case 32:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		default:
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+/*
+ *  Pan or Wrap the Display
+ *
+ *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int unifb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0
+		    || var->yoffset >= info->var.yres_virtual
+		    || var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+		    var->yoffset + info->var.yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+int unifb_mmap(struct fb_info *info,
+		    struct vm_area_struct *vma)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
+}
+
+static struct fb_ops unifb_ops = {
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_check_var	= unifb_check_var,
+	.fb_set_par	= unifb_set_par,
+	.fb_setcolreg	= unifb_setcolreg,
+	.fb_pan_display	= unifb_pan_display,
+	.fb_fillrect	= unifb_fillrect,
+	.fb_copyarea	= unifb_copyarea,
+	.fb_imageblit   = unifb_imageblit,
+	.fb_mmap	= unifb_mmap,
+};
+
+/*
+ *  Initialisation
+ */
+static int unifb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	u32 unifb_regs[UNIFB_REGS_NUM];
+	int retval = -ENOMEM;
+	struct resource *iomem;
+	void *videomemory;
+
+	videomemory = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP,
+				get_order(UNIFB_MEMSIZE));
+	if (!videomemory)
+		goto err;
+
+	memset(videomemory, 0, UNIFB_MEMSIZE);
+
+	unifb_fix.smem_start = virt_to_phys(videomemory);
+	unifb_fix.smem_len = UNIFB_MEMSIZE;
+
+	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	unifb_fix.mmio_start = iomem->start;
+
+	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
+	if (!info)
+		goto err;
+
+	info->screen_base = (char __iomem *)videomemory;
+	info->fbops = &unifb_ops;
+
+	retval = fb_find_mode(&info->var, info, NULL,
+			      unifb_modes, 10, &unifb_modes[0], 16);
+
+	if (!retval || (retval == 4))
+		info->var = unifb_default;
+
+	info->fix = unifb_fix;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+#ifdef FB_ACCEL_PUV3_UNIGFX
+	info->fix.accel = FB_ACCEL_PUV3_UNIGFX;
+#endif
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err1;
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err2;
+	platform_set_drvdata(dev, info);
+	platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM);
+
+	fb_info(info, "Virtual frame buffer device, using %dM of video memory\n",
+		UNIFB_MEMSIZE >> 20);
+	return 0;
+err2:
+	fb_dealloc_cmap(&info->cmap);
+err1:
+	framebuffer_release(info);
+err:
+	return retval;
+}
+
+static int unifb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int unifb_resume(struct platform_device *dev)
+{
+	int rc = 0;
+	u32 *unifb_regs = dev->dev.platform_data;
+
+	if (dev->dev.power.power_state.event == PM_EVENT_ON)
+		return 0;
+
+	console_lock();
+
+	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+		writel(unifb_regs[0], UDE_FSA);
+		writel(unifb_regs[1], UDE_LS);
+		writel(unifb_regs[2], UDE_PS);
+		writel(unifb_regs[3], UDE_HAT);
+		writel(unifb_regs[4], UDE_HBT);
+		writel(unifb_regs[5], UDE_HST);
+		writel(unifb_regs[6], UDE_VAT);
+		writel(unifb_regs[7], UDE_VBT);
+		writel(unifb_regs[8], UDE_VST);
+		writel(unifb_regs[9], UDE_CFG);
+	}
+	dev->dev.power.power_state = PMSG_ON;
+
+	console_unlock();
+
+	return rc;
+}
+
+static int unifb_suspend(struct platform_device *dev, pm_message_t mesg)
+{
+	u32 *unifb_regs = dev->dev.platform_data;
+
+	unifb_regs[0] = readl(UDE_FSA);
+	unifb_regs[1] = readl(UDE_LS);
+	unifb_regs[2] = readl(UDE_PS);
+	unifb_regs[3] = readl(UDE_HAT);
+	unifb_regs[4] = readl(UDE_HBT);
+	unifb_regs[5] = readl(UDE_HST);
+	unifb_regs[6] = readl(UDE_VAT);
+	unifb_regs[7] = readl(UDE_VBT);
+	unifb_regs[8] = readl(UDE_VST);
+	unifb_regs[9] = readl(UDE_CFG);
+
+	if (mesg.event == dev->dev.power.power_state.event)
+		return 0;
+
+	switch (mesg.event) {
+	case PM_EVENT_FREEZE:		/* about to take snapshot */
+	case PM_EVENT_PRETHAW:		/* before restoring snapshot */
+		goto done;
+	}
+
+	console_lock();
+
+	/* do nothing... */
+
+	console_unlock();
+
+done:
+	dev->dev.power.power_state = mesg;
+
+	return 0;
+}
+#else
+#define	unifb_resume	NULL
+#define unifb_suspend	NULL
+#endif
+
+static struct platform_driver unifb_driver = {
+	.probe	 = unifb_probe,
+	.remove  = unifb_remove,
+	.resume  = unifb_resume,
+	.suspend = unifb_suspend,
+	.driver  = {
+		.name	= "PKUnity-v3-UNIGFX",
+	},
+};
+
+static int __init unifb_init(void)
+{
+#ifndef MODULE
+	if (fb_get_options("unifb", NULL))
+		return -ENODEV;
+#endif
+
+	return platform_driver_register(&unifb_driver);
+}
+
+module_init(unifb_init);
+
+static void __exit unifb_exit(void)
+{
+	platform_driver_unregister(&unifb_driver);
+}
+
+module_exit(unifb_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/ffb.c b/drivers/video/fbdev/ffb.c
new file mode 100644
index 000000000000..4c4ffa61ae26
--- /dev/null
+++ b/drivers/video/fbdev/ffb.c
@@ -0,0 +1,1081 @@
+/* ffb.c: Creator/Elite3D frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/upa.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int ffb_blank(int, struct fb_info *);
+
+static void ffb_imageblit(struct fb_info *, const struct fb_image *);
+static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
+static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
+static int ffb_sync(struct fb_info *);
+static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
+static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
+static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops ffb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= ffb_setcolreg,
+	.fb_blank		= ffb_blank,
+	.fb_pan_display		= ffb_pan_display,
+	.fb_fillrect		= ffb_fillrect,
+	.fb_copyarea		= ffb_copyarea,
+	.fb_imageblit		= ffb_imageblit,
+	.fb_sync		= ffb_sync,
+	.fb_mmap		= ffb_mmap,
+	.fb_ioctl		= ffb_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+/* Register layout and definitions */
+#define	FFB_SFB8R_VOFF		0x00000000
+#define	FFB_SFB8G_VOFF		0x00400000
+#define	FFB_SFB8B_VOFF		0x00800000
+#define	FFB_SFB8X_VOFF		0x00c00000
+#define	FFB_SFB32_VOFF		0x01000000
+#define	FFB_SFB64_VOFF		0x02000000
+#define	FFB_FBC_REGS_VOFF	0x04000000
+#define	FFB_BM_FBC_REGS_VOFF	0x04002000
+#define	FFB_DFB8R_VOFF		0x04004000
+#define	FFB_DFB8G_VOFF		0x04404000
+#define	FFB_DFB8B_VOFF		0x04804000
+#define	FFB_DFB8X_VOFF		0x04c04000
+#define	FFB_DFB24_VOFF		0x05004000
+#define	FFB_DFB32_VOFF		0x06004000
+#define	FFB_DFB422A_VOFF	0x07004000	/* DFB 422 mode write to A */
+#define	FFB_DFB422AD_VOFF	0x07804000	/* DFB 422 mode with line doubling */
+#define	FFB_DFB24B_VOFF		0x08004000	/* DFB 24bit mode write to B */
+#define	FFB_DFB422B_VOFF	0x09004000	/* DFB 422 mode write to B */
+#define	FFB_DFB422BD_VOFF	0x09804000	/* DFB 422 mode with line doubling */
+#define	FFB_SFB16Z_VOFF		0x0a004000	/* 16bit mode Z planes */
+#define	FFB_SFB8Z_VOFF		0x0a404000	/* 8bit mode Z planes */
+#define	FFB_SFB422_VOFF		0x0ac04000	/* SFB 422 mode write to A/B */
+#define	FFB_SFB422D_VOFF	0x0b404000	/* SFB 422 mode with line doubling */
+#define	FFB_FBC_KREGS_VOFF	0x0bc04000
+#define	FFB_DAC_VOFF		0x0bc06000
+#define	FFB_PROM_VOFF		0x0bc08000
+#define	FFB_EXP_VOFF		0x0bc18000
+
+#define	FFB_SFB8R_POFF		0x04000000UL
+#define	FFB_SFB8G_POFF		0x04400000UL
+#define	FFB_SFB8B_POFF		0x04800000UL
+#define	FFB_SFB8X_POFF		0x04c00000UL
+#define	FFB_SFB32_POFF		0x05000000UL
+#define	FFB_SFB64_POFF		0x06000000UL
+#define	FFB_FBC_REGS_POFF	0x00600000UL
+#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
+#define	FFB_DFB8R_POFF		0x01000000UL
+#define	FFB_DFB8G_POFF		0x01400000UL
+#define	FFB_DFB8B_POFF		0x01800000UL
+#define	FFB_DFB8X_POFF		0x01c00000UL
+#define	FFB_DFB24_POFF		0x02000000UL
+#define	FFB_DFB32_POFF		0x03000000UL
+#define	FFB_FBC_KREGS_POFF	0x00610000UL
+#define	FFB_DAC_POFF		0x00400000UL
+#define	FFB_PROM_POFF		0x00000000UL
+#define	FFB_EXP_POFF		0x00200000UL
+#define FFB_DFB422A_POFF	0x09000000UL
+#define FFB_DFB422AD_POFF	0x09800000UL
+#define FFB_DFB24B_POFF		0x0a000000UL
+#define FFB_DFB422B_POFF	0x0b000000UL
+#define FFB_DFB422BD_POFF	0x0b800000UL
+#define FFB_SFB16Z_POFF		0x0c800000UL
+#define FFB_SFB8Z_POFF		0x0c000000UL
+#define FFB_SFB422_POFF		0x0d000000UL
+#define FFB_SFB422D_POFF	0x0d800000UL
+
+/* Draw operations */
+#define FFB_DRAWOP_DOT		0x00
+#define FFB_DRAWOP_AADOT	0x01
+#define FFB_DRAWOP_BRLINECAP	0x02
+#define FFB_DRAWOP_BRLINEOPEN	0x03
+#define FFB_DRAWOP_DDLINE	0x04
+#define FFB_DRAWOP_AALINE	0x05
+#define FFB_DRAWOP_TRIANGLE	0x06
+#define FFB_DRAWOP_POLYGON	0x07
+#define FFB_DRAWOP_RECTANGLE	0x08
+#define FFB_DRAWOP_FASTFILL	0x09
+#define FFB_DRAWOP_BCOPY	0x0a
+#define FFB_DRAWOP_VSCROLL	0x0b
+
+/* Pixel processor control */
+/* Force WID */
+#define FFB_PPC_FW_DISABLE	0x800000
+#define FFB_PPC_FW_ENABLE	0xc00000
+/* Auxiliary clip */
+#define FFB_PPC_ACE_DISABLE	0x040000
+#define FFB_PPC_ACE_AUX_SUB	0x080000
+#define FFB_PPC_ACE_AUX_ADD	0x0c0000
+/* Depth cue */
+#define FFB_PPC_DCE_DISABLE	0x020000
+#define FFB_PPC_DCE_ENABLE	0x030000
+/* Alpha blend */
+#define FFB_PPC_ABE_DISABLE	0x008000
+#define FFB_PPC_ABE_ENABLE	0x00c000
+/* View clip */
+#define FFB_PPC_VCE_DISABLE	0x001000
+#define FFB_PPC_VCE_2D		0x002000
+#define FFB_PPC_VCE_3D		0x003000
+/* Area pattern */
+#define FFB_PPC_APE_DISABLE	0x000800
+#define FFB_PPC_APE_ENABLE	0x000c00
+/* Transparent background */
+#define FFB_PPC_TBE_OPAQUE	0x000200
+#define FFB_PPC_TBE_TRANSPARENT	0x000300
+/* Z source */
+#define FFB_PPC_ZS_VAR		0x000080
+#define FFB_PPC_ZS_CONST	0x0000c0
+/* Y source */
+#define FFB_PPC_YS_VAR		0x000020
+#define FFB_PPC_YS_CONST	0x000030
+/* X source */
+#define FFB_PPC_XS_WID		0x000004
+#define FFB_PPC_XS_VAR		0x000008
+#define FFB_PPC_XS_CONST	0x00000c
+/* Color (BGR) source */
+#define FFB_PPC_CS_VAR		0x000002
+#define FFB_PPC_CS_CONST	0x000003
+
+#define FFB_ROP_NEW		0x83
+#define FFB_ROP_OLD		0x85
+#define FFB_ROP_NEW_XOR_OLD	0x86
+
+#define FFB_UCSR_FIFO_MASK	0x00000fff
+#define FFB_UCSR_FB_BUSY	0x01000000
+#define FFB_UCSR_RP_BUSY	0x02000000
+#define FFB_UCSR_ALL_BUSY	(FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
+#define FFB_UCSR_READ_ERR	0x40000000
+#define FFB_UCSR_FIFO_OVFL	0x80000000
+#define FFB_UCSR_ALL_ERRORS	(FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
+
+struct ffb_fbc {
+	/* Next vertex registers */
+	u32	xxx1[3];
+	u32	alpha;
+	u32	red;
+	u32	green;
+	u32	blue;
+	u32	depth;
+	u32	y;
+	u32	x;
+	u32	xxx2[2];
+	u32	ryf;
+	u32	rxf;
+	u32	xxx3[2];
+
+	u32	dmyf;
+	u32	dmxf;
+	u32	xxx4[2];
+	u32	ebyi;
+	u32	ebxi;
+	u32	xxx5[2];
+	u32	by;
+	u32	bx;
+	u32	dy;
+	u32	dx;
+	u32	bh;
+	u32	bw;
+	u32	xxx6[2];
+
+	u32	xxx7[32];
+
+	/* Setup unit vertex state register */
+	u32	suvtx;
+	u32	xxx8[63];
+
+	/* Control registers */
+	u32	ppc;
+	u32	wid;
+	u32	fg;
+	u32	bg;
+	u32	consty;
+	u32	constz;
+	u32	xclip;
+	u32	dcss;
+	u32	vclipmin;
+	u32	vclipmax;
+	u32	vclipzmin;
+	u32	vclipzmax;
+	u32	dcsf;
+	u32	dcsb;
+	u32	dczf;
+	u32	dczb;
+
+	u32	xxx9;
+	u32	blendc;
+	u32	blendc1;
+	u32	blendc2;
+	u32	fbramitc;
+	u32	fbc;
+	u32	rop;
+	u32	cmp;
+	u32	matchab;
+	u32	matchc;
+	u32	magnab;
+	u32	magnc;
+	u32	fbcfg0;
+	u32	fbcfg1;
+	u32	fbcfg2;
+	u32	fbcfg3;
+
+	u32	ppcfg;
+	u32	pick;
+	u32	fillmode;
+	u32	fbramwac;
+	u32	pmask;
+	u32	xpmask;
+	u32	ypmask;
+	u32	zpmask;
+	u32	clip0min;
+	u32	clip0max;
+	u32	clip1min;
+	u32	clip1max;
+	u32	clip2min;
+	u32	clip2max;
+	u32	clip3min;
+	u32	clip3max;
+
+	/* New 3dRAM III support regs */
+	u32	rawblend2;
+	u32	rawpreblend;
+	u32	rawstencil;
+	u32	rawstencilctl;
+	u32	threedram1;
+	u32	threedram2;
+	u32	passin;
+	u32	rawclrdepth;
+	u32	rawpmask;
+	u32	rawcsrc;
+	u32	rawmatch;
+	u32	rawmagn;
+	u32	rawropblend;
+	u32	rawcmp;
+	u32	rawwac;
+	u32	fbramid;
+
+	u32	drawop;
+	u32	xxx10[2];
+	u32	fontlpat;
+	u32	xxx11;
+	u32	fontxy;
+	u32	fontw;
+	u32	fontinc;
+	u32	font;
+	u32	xxx12[3];
+	u32	blend2;
+	u32	preblend;
+	u32	stencil;
+	u32	stencilctl;
+
+	u32	xxx13[4];
+	u32	dcss1;
+	u32	dcss2;
+	u32	dcss3;
+	u32	widpmask;
+	u32	dcs2;
+	u32	dcs3;
+	u32	dcs4;
+	u32	xxx14;
+	u32	dcd2;
+	u32	dcd3;
+	u32	dcd4;
+	u32	xxx15;
+
+	u32	pattern[32];
+
+	u32	xxx16[256];
+
+	u32	devid;
+	u32	xxx17[63];
+
+	u32	ucsr;
+	u32	xxx18[31];
+
+	u32	mer;
+};
+
+struct ffb_dac {
+	u32	type;
+	u32	value;
+	u32	type2;
+	u32	value2;
+};
+
+#define FFB_DAC_UCTRL		0x1001 /* User Control */
+#define FFB_DAC_UCTRL_MANREV	0x00000f00 /* 4-bit Manufacturing Revision */
+#define FFB_DAC_UCTRL_MANREV_SHIFT 8
+#define FFB_DAC_TGEN		0x6000 /* Timing Generator */
+#define FFB_DAC_TGEN_VIDE	0x00000001 /* Video Enable */
+#define FFB_DAC_DID		0x8000 /* Device Identification */
+#define FFB_DAC_DID_PNUM	0x0ffff000 /* Device Part Number */
+#define FFB_DAC_DID_PNUM_SHIFT	12
+#define FFB_DAC_DID_REV		0xf0000000 /* Device Revision */
+#define FFB_DAC_DID_REV_SHIFT	28
+
+#define FFB_DAC_CUR_CTRL	0x100
+#define FFB_DAC_CUR_CTRL_P0	0x00000001
+#define FFB_DAC_CUR_CTRL_P1	0x00000002
+
+struct ffb_par {
+	spinlock_t		lock;
+	struct ffb_fbc __iomem	*fbc;
+	struct ffb_dac __iomem	*dac;
+
+	u32			flags;
+#define FFB_FLAG_AFB		0x00000001 /* AFB m3 or m6 */
+#define FFB_FLAG_BLANKED	0x00000002 /* screen is blanked */
+#define FFB_FLAG_INVCURSOR	0x00000004 /* DAC has inverted cursor logic */
+
+	u32			fg_cache __attribute__((aligned (8)));
+	u32			bg_cache;
+	u32			rop_cache;
+
+	int			fifo_cache;
+
+	unsigned long		physbase;
+	unsigned long		fbsize;
+
+	int			board_type;
+
+	u32			pseudo_palette[16];
+};
+
+static void FFBFifo(struct ffb_par *par, int n)
+{
+	struct ffb_fbc __iomem *fbc;
+	int cache = par->fifo_cache;
+
+	if (cache - n < 0) {
+		fbc = par->fbc;
+		do {
+			cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK);
+			cache -= 8;
+		} while (cache - n < 0);
+	}
+	par->fifo_cache = cache - n;
+}
+
+static void FFBWait(struct ffb_par *par)
+{
+	struct ffb_fbc __iomem *fbc;
+	int limit = 10000;
+
+	fbc = par->fbc;
+	do {
+		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
+			break;
+		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
+			upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
+		}
+		udelay(10);
+	} while (--limit > 0);
+}
+
+static int ffb_sync(struct fb_info *p)
+{
+	struct ffb_par *par = (struct ffb_par *)p->par;
+
+	FFBWait(par);
+	return 0;
+}
+
+static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
+{
+	if (par->rop_cache != rop) {
+		FFBFifo(par, 1);
+		upa_writel(rop, &par->fbc->rop);
+		par->rop_cache = rop;
+	}
+}
+
+static void ffb_switch_from_graph(struct ffb_par *par)
+{
+	struct ffb_fbc __iomem *fbc = par->fbc;
+	struct ffb_dac __iomem *dac = par->dac;
+	unsigned long flags;
+
+	spin_lock_irqsave(&par->lock, flags);
+	FFBWait(par);
+	par->fifo_cache = 0;
+	FFBFifo(par, 7);
+	upa_writel(FFB_PPC_VCE_DISABLE | FFB_PPC_TBE_OPAQUE |
+		   FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+		   &fbc->ppc);
+	upa_writel(0x2000707f, &fbc->fbc);
+	upa_writel(par->rop_cache, &fbc->rop);
+	upa_writel(0xffffffff, &fbc->pmask);
+	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
+	upa_writel(par->fg_cache, &fbc->fg);
+	upa_writel(par->bg_cache, &fbc->bg);
+	FFBWait(par);
+
+	/* Disable cursor.  */
+	upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
+	if (par->flags & FFB_FLAG_INVCURSOR)
+		upa_writel(0, &dac->value2);
+	else
+		upa_writel((FFB_DAC_CUR_CTRL_P0 |
+			    FFB_DAC_CUR_CTRL_P1), &dac->value2);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+
+	/* We just use this to catch switches out of
+	 * graphics mode.
+	 */
+	ffb_switch_from_graph(par);
+
+	if (var->xoffset || var->yoffset || var->vmode)
+		return -EINVAL;
+	return 0;
+}
+
+/**
+ *	ffb_fillrect - Draws a rectangle on the screen.
+ *
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@rect: structure defining the rectagle and operation.
+ */
+static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+	struct ffb_fbc __iomem *fbc = par->fbc;
+	unsigned long flags;
+	u32 fg;
+
+	BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
+
+	fg = ((u32 *)info->pseudo_palette)[rect->color];
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	if (fg != par->fg_cache) {
+		FFBFifo(par, 1);
+		upa_writel(fg, &fbc->fg);
+		par->fg_cache = fg;
+	}
+
+	ffb_rop(par, rect->rop == ROP_COPY ?
+		     FFB_ROP_NEW :
+		     FFB_ROP_NEW_XOR_OLD);
+
+	FFBFifo(par, 5);
+	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
+	upa_writel(rect->dy, &fbc->by);
+	upa_writel(rect->dx, &fbc->bx);
+	upa_writel(rect->height, &fbc->bh);
+	upa_writel(rect->width, &fbc->bw);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *	ffb_copyarea - Copies on area of the screen to another area.
+ *
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@area: structure defining the source and destination.
+ */
+
+static void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+	struct ffb_fbc __iomem *fbc = par->fbc;
+	unsigned long flags;
+
+	if (area->dx != area->sx ||
+	    area->dy == area->sy) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	ffb_rop(par, FFB_ROP_OLD);
+
+	FFBFifo(par, 7);
+	upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
+	upa_writel(area->sy, &fbc->by);
+	upa_writel(area->sx, &fbc->bx);
+	upa_writel(area->dy, &fbc->dy);
+	upa_writel(area->dx, &fbc->dx);
+	upa_writel(area->height, &fbc->bh);
+	upa_writel(area->width, &fbc->bw);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *	ffb_imageblit - Copies a image from system memory to the screen.
+ *
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@image: structure defining the image.
+ */
+static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+	struct ffb_fbc __iomem *fbc = par->fbc;
+	const u8 *data = image->data;
+	unsigned long flags;
+	u32 fg, bg, xy;
+	u64 fgbg;
+	int i, width, stride;
+
+	if (image->depth > 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	fg = ((u32 *)info->pseudo_palette)[image->fg_color];
+	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
+	fgbg = ((u64) fg << 32) | (u64) bg;
+	xy = (image->dy << 16) | image->dx;
+	width = image->width;
+	stride = ((width + 7) >> 3);
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	if (fgbg != *(u64 *)&par->fg_cache) {
+		FFBFifo(par, 2);
+		upa_writeq(fgbg, &fbc->fg);
+		*(u64 *)&par->fg_cache = fgbg;
+	}
+
+	if (width >= 32) {
+		FFBFifo(par, 1);
+		upa_writel(32, &fbc->fontw);
+	}
+
+	while (width >= 32) {
+		const u8 *next_data = data + 4;
+
+		FFBFifo(par, 1);
+		upa_writel(xy, &fbc->fontxy);
+		xy += (32 << 0);
+
+		for (i = 0; i < image->height; i++) {
+			u32 val = (((u32)data[0] << 24) |
+				   ((u32)data[1] << 16) |
+				   ((u32)data[2] <<  8) |
+				   ((u32)data[3] <<  0));
+			FFBFifo(par, 1);
+			upa_writel(val, &fbc->font);
+
+			data += stride;
+		}
+
+		data = next_data;
+		width -= 32;
+	}
+
+	if (width) {
+		FFBFifo(par, 2);
+		upa_writel(width, &fbc->fontw);
+		upa_writel(xy, &fbc->fontxy);
+
+		for (i = 0; i < image->height; i++) {
+			u32 val = (((u32)data[0] << 24) |
+				   ((u32)data[1] << 16) |
+				   ((u32)data[2] <<  8) |
+				   ((u32)data[3] <<  0));
+			FFBFifo(par, 1);
+			upa_writel(val, &fbc->font);
+
+			data += stride;
+		}
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
+{
+	var->red.offset = 0;
+	var->red.length = 8;
+	var->green.offset = 8;
+	var->green.length = 8;
+	var->blue.offset = 16;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+}
+
+/**
+ *	ffb_setcolreg - Sets a color register.
+ *
+ *	@regno: boolean, 0 copy local, 1 get_user() function
+ *	@red: frame buffer colormap structure
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *	@info: frame buffer info structure
+ */
+static int ffb_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	u32 value;
+
+	if (regno >= 16)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	value = (blue << 16) | (green << 8) | red;
+	((u32 *)info->pseudo_palette)[regno] = value;
+
+	return 0;
+}
+
+/**
+ *	ffb_blank - Optional function.  Blanks the display.
+ *	@blank_mode: the blank mode we want.
+ *	@info: frame buffer structure that represents a single frame buffer
+ */
+static int ffb_blank(int blank, struct fb_info *info)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+	struct ffb_dac __iomem *dac = par->dac;
+	unsigned long flags;
+	u32 val;
+	int i;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	FFBWait(par);
+
+	upa_writel(FFB_DAC_TGEN, &dac->type);
+	val = upa_readl(&dac->value);
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		val |= FFB_DAC_TGEN_VIDE;
+		par->flags &= ~FFB_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		val &= ~FFB_DAC_TGEN_VIDE;
+		par->flags |= FFB_FLAG_BLANKED;
+		break;
+	}
+	upa_writel(FFB_DAC_TGEN, &dac->type);
+	upa_writel(val, &dac->value);
+	for (i = 0; i < 10; i++) {
+		upa_writel(FFB_DAC_TGEN, &dac->type);
+		upa_readl(&dac->value);
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map ffb_mmap_map[] = {
+	{
+		.voff	= FFB_SFB8R_VOFF,
+		.poff	= FFB_SFB8R_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_SFB8G_VOFF,
+		.poff	= FFB_SFB8G_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_SFB8B_VOFF,
+		.poff	= FFB_SFB8B_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_SFB8X_VOFF,
+		.poff	= FFB_SFB8X_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_SFB32_VOFF,
+		.poff	= FFB_SFB32_POFF,
+		.size	= 0x1000000
+	},
+	{
+		.voff	= FFB_SFB64_VOFF,
+		.poff	= FFB_SFB64_POFF,
+		.size	= 0x2000000
+	},
+	{
+		.voff	= FFB_FBC_REGS_VOFF,
+		.poff	= FFB_FBC_REGS_POFF,
+		.size	= 0x0002000
+	},
+	{
+		.voff	= FFB_BM_FBC_REGS_VOFF,
+		.poff	= FFB_BM_FBC_REGS_POFF,
+		.size	= 0x0002000
+	},
+	{
+		.voff	= FFB_DFB8R_VOFF,
+		.poff	= FFB_DFB8R_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_DFB8G_VOFF,
+		.poff	= FFB_DFB8G_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_DFB8B_VOFF,
+		.poff	= FFB_DFB8B_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_DFB8X_VOFF,
+		.poff	= FFB_DFB8X_POFF,
+		.size	= 0x0400000
+	},
+	{
+		.voff	= FFB_DFB24_VOFF,
+		.poff	= FFB_DFB24_POFF,
+		.size	= 0x1000000
+	},
+	{
+		.voff	= FFB_DFB32_VOFF,
+		.poff	= FFB_DFB32_POFF,
+		.size	= 0x1000000
+	},
+	{
+		.voff	= FFB_FBC_KREGS_VOFF,
+		.poff	= FFB_FBC_KREGS_POFF,
+		.size	= 0x0002000
+	},
+	{
+		.voff	= FFB_DAC_VOFF,
+		.poff	= FFB_DAC_POFF,
+		.size	= 0x0002000
+	},
+	{
+		.voff	= FFB_PROM_VOFF,
+		.poff	= FFB_PROM_POFF,
+		.size	= 0x0010000
+	},
+	{
+		.voff	= FFB_EXP_VOFF,
+		.poff	= FFB_EXP_POFF,
+		.size	= 0x0002000
+	},
+	{
+		.voff	= FFB_DFB422A_VOFF,
+		.poff	= FFB_DFB422A_POFF,
+		.size	= 0x0800000
+	},
+	{
+		.voff	= FFB_DFB422AD_VOFF,
+		.poff	= FFB_DFB422AD_POFF,
+		.size	= 0x0800000
+	},
+	{
+		.voff	= FFB_DFB24B_VOFF,
+		.poff	= FFB_DFB24B_POFF,
+		.size	= 0x1000000
+	},
+	{
+		.voff	= FFB_DFB422B_VOFF,
+		.poff	= FFB_DFB422B_POFF,
+		.size	= 0x0800000
+	},
+	{
+		.voff	= FFB_DFB422BD_VOFF,
+		.poff	= FFB_DFB422BD_POFF,
+		.size	= 0x0800000
+	},
+	{
+		.voff	= FFB_SFB16Z_VOFF,
+		.poff	= FFB_SFB16Z_POFF,
+		.size	= 0x0800000
+	},
+	{
+		.voff	= FFB_SFB8Z_VOFF,
+		.poff	= FFB_SFB8Z_POFF,
+		.size	= 0x0800000
+	},
+	{
+		.voff	= FFB_SFB422_VOFF,
+		.poff	= FFB_SFB422_POFF,
+		.size	= 0x0800000
+	},
+	{
+		.voff	= FFB_SFB422D_VOFF,
+		.poff	= FFB_SFB422D_POFF,
+		.size	= 0x0800000
+	},
+	{ .size = 0 }
+};
+
+static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+
+	return sbusfb_mmap_helper(ffb_mmap_map,
+				  par->physbase, par->fbsize,
+				  0, vma);
+}
+
+static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_CREATOR, 24, par->fbsize);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void ffb_init_fix(struct fb_info *info)
+{
+	struct ffb_par *par = (struct ffb_par *)info->par;
+	const char *ffb_type_name;
+
+	if (!(par->flags & FFB_FLAG_AFB)) {
+		if ((par->board_type & 0x7) == 0x3)
+			ffb_type_name = "Creator 3D";
+		else
+			ffb_type_name = "Creator";
+	} else
+		ffb_type_name = "Elite 3D";
+
+	strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	/* Framebuffer length is the same regardless of resolution. */
+	info->fix.line_length = 8192;
+
+	info->fix.accel = FB_ACCEL_SUN_CREATOR;
+}
+
+static int ffb_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct ffb_fbc __iomem *fbc;
+	struct ffb_dac __iomem *dac;
+	struct fb_info *info;
+	struct ffb_par *par;
+	u32 dac_pnum, dac_rev, dac_mrev;
+	int err;
+
+	info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+	par->fbc = of_ioremap(&op->resource[2], 0,
+			      sizeof(struct ffb_fbc), "ffb fbc");
+	if (!par->fbc)
+		goto out_release_fb;
+
+	par->dac = of_ioremap(&op->resource[1], 0,
+			      sizeof(struct ffb_dac), "ffb dac");
+	if (!par->dac)
+		goto out_unmap_fbc;
+
+	par->rop_cache = FFB_ROP_NEW;
+	par->physbase = op->resource[0].start;
+
+	/* Don't mention copyarea, so SCROLL_REDRAW is always
+	 * used.  It is the fastest on this chip.
+	 */
+	info->flags = (FBINFO_DEFAULT |
+		       /* FBINFO_HWACCEL_COPYAREA | */
+		       FBINFO_HWACCEL_FILLRECT |
+		       FBINFO_HWACCEL_IMAGEBLIT);
+
+	info->fbops = &ffb_ops;
+
+	info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
+	info->pseudo_palette = par->pseudo_palette;
+
+	sbusfb_fill_var(&info->var, dp, 32);
+	par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
+	ffb_fixup_var_rgb(&info->var);
+
+	info->var.accel_flags = FB_ACCELF_TEXT;
+
+	if (!strcmp(dp->name, "SUNW,afb"))
+		par->flags |= FFB_FLAG_AFB;
+
+	par->board_type = of_getintprop_default(dp, "board_type", 0);
+
+	fbc = par->fbc;
+	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
+		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
+
+	dac = par->dac;
+	upa_writel(FFB_DAC_DID, &dac->type);
+	dac_pnum = upa_readl(&dac->value);
+	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
+	dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
+
+	upa_writel(FFB_DAC_UCTRL, &dac->type);
+	dac_mrev = upa_readl(&dac->value);
+	dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
+		FFB_DAC_UCTRL_MANREV_SHIFT;
+
+	/* Elite3D has different DAC revision numbering, and no DAC revisions
+	 * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1
+	 * ramdacs with manufacturing revision less than 3 have inverted
+	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
+	 * latter having a part number value of 0x236e.
+	 */
+	if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
+		par->flags &= ~FFB_FLAG_INVCURSOR;
+	} else {
+		if (dac_mrev < 3)
+			par->flags |= FFB_FLAG_INVCURSOR;
+	}
+
+	ffb_switch_from_graph(par);
+
+	/* Unblank it just to be sure.  When there are multiple
+	 * FFB/AFB cards in the system, or it is not the OBP
+	 * chosen console, it will have video outputs off in
+	 * the DAC.
+	 */
+	ffb_blank(FB_BLANK_UNBLANK, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_dac;
+
+	ffb_init_fix(info);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: %s at %016lx, type %d, "
+	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
+	       dp->full_name,
+	       ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
+	       par->physbase, par->board_type,
+	       dac_pnum, dac_rev, dac_mrev);
+
+	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_dac:
+	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
+
+out_unmap_fbc:
+	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
+
+out_release_fb:
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int ffb_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct ffb_par *par = info->par;
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
+	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id ffb_match[] = {
+	{
+		.name = "SUNW,ffb",
+	},
+	{
+		.name = "SUNW,afb",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ffb_match);
+
+static struct platform_driver ffb_driver = {
+	.driver = {
+		.name = "ffb",
+		.owner = THIS_MODULE,
+		.of_match_table = ffb_match,
+	},
+	.probe		= ffb_probe,
+	.remove		= ffb_remove,
+};
+
+static int __init ffb_init(void)
+{
+	if (fb_get_options("ffb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&ffb_driver);
+}
+
+static void __exit ffb_exit(void)
+{
+	platform_driver_unregister(&ffb_driver);
+}
+
+module_init(ffb_init);
+module_exit(ffb_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/fm2fb.c b/drivers/video/fbdev/fm2fb.c
new file mode 100644
index 000000000000..e69d47af9932
--- /dev/null
+++ b/drivers/video/fbdev/fm2fb.c
@@ -0,0 +1,323 @@
+/*
+ *  linux/drivers/video/fm2fb.c -- BSC FrameMaster II/Rainbow II frame buffer
+ *				   device
+ *
+ *	Copyright (C) 1998 Steffen A. Mork (linux-dev@morknet.de)
+ *	Copyright (C) 1999 Geert Uytterhoeven
+ *
+ *  Written for 2.0.x by Steffen A. Mork
+ *  Ported to 2.1.x by Geert Uytterhoeven
+ *  Ported to new api by James Simmons
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/zorro.h>
+#include <asm/io.h>
+
+/*
+ *	Some technical notes:
+ *
+ *	The BSC FrameMaster II (or Rainbow II) is a simple very dumb
+ *	frame buffer which allows to display 24 bit true color images.
+ *	Each pixel is 32 bit width so it's very easy to maintain the
+ *	frame buffer. One long word has the following layout:
+ *	AARRGGBB which means: AA the alpha channel byte, RR the red
+ *	channel, GG the green channel and BB the blue channel.
+ *
+ *	The FrameMaster II supports the following video modes.
+ *	- PAL/NTSC
+ *	- interlaced/non interlaced
+ *	- composite sync/sync/sync over green
+ *
+ *	The resolution is to the following both ones:
+ *	- 768x576 (PAL)
+ *	- 768x480 (NTSC)
+ *
+ *	This means that pixel access per line is fixed due to the
+ *	fixed line width. In case of maximal resolution the frame
+ *	buffer needs an amount of memory of 1.769.472 bytes which
+ *	is near to 2 MByte (the allocated address space of Zorro2).
+ *	The memory is channel interleaved. That means every channel
+ *	owns four VRAMs. Unfortunately most FrameMasters II are
+ *	not assembled with memory for the alpha channel. In this
+ *	case it could be possible to add the frame buffer into the
+ *	normal memory pool.
+ *
+ *	At relative address 0x1ffff8 of the frame buffers base address
+ *	there exists a control register with the number of
+ *	four control bits. They have the following meaning:
+ *	bit value meaning
+ *
+ *	 0    1   0=interlaced/1=non interlaced
+ *	 1    2   0=video out disabled/1=video out enabled
+ *	 2    4   0=normal mode as jumpered via JP8/1=complement mode
+ *	 3    8   0=read  onboard ROM/1 normal operation (required)
+ *
+ *	As mentioned above there are several jumper. I think there
+ *	is not very much information about the FrameMaster II in
+ *	the world so I add these information for completeness.
+ *
+ *	JP1  interlace selection (1-2 non interlaced/2-3 interlaced)
+ *	JP2  wait state creation (leave as is!)
+ *	JP3  wait state creation (leave as is!)
+ *	JP4  modulate composite sync on green output (1-2 composite
+ *	     sync on green channel/2-3 normal composite sync)
+ *	JP5  create test signal, shorting this jumper will create
+ *	     a white screen
+ *	JP6  sync creation (1-2 composite sync/2-3 H-sync output)
+ *	JP8  video mode (1-2 PAL/2-3 NTSC)
+ *
+ *	With the following jumpering table you can connect the
+ *	FrameMaster II to a normal TV via SCART connector:
+ *	JP1:  2-3
+ *	JP4:  2-3
+ *	JP6:  2-3
+ *	JP8:  1-2 (means PAL for Europe)
+ *
+ *	NOTE:
+ *	There is no other possibility to change the video timings
+ *	except the interlaced/non interlaced, sync control and the
+ *	video mode PAL (50 Hz)/NTSC (60 Hz). Inside this
+ *	FrameMaster II driver are assumed values to avoid anomalies
+ *	to a future X server. Except the pixel clock is really
+ *	constant at 30 MHz.
+ *
+ *	9 pin female video connector:
+ *
+ *	1  analog red 0.7 Vss
+ *	2  analog green 0.7 Vss
+ *	3  analog blue 0.7 Vss
+ *	4  H-sync TTL
+ *	5  V-sync TTL
+ *	6  ground
+ *	7  ground
+ *	8  ground
+ *	9  ground
+ *
+ *	Some performance notes:
+ *	The FrameMaster II was not designed to display a console
+ *	this driver would do! It was designed to display still true
+ *	color images. Imagine: When scroll up a text line there
+ *	must copied ca. 1.7 MBytes to another place inside this
+ *	frame buffer. This means 1.7 MByte read and 1.7 MByte write
+ *	over the slow 16 bit wide Zorro2 bus! A scroll of one
+ *	line needs 1 second so do not expect to much from this
+ *	driver - he is at the limit!
+ *
+ */
+
+/*
+ *	definitions
+ */
+
+#define FRAMEMASTER_SIZE	0x200000
+#define FRAMEMASTER_REG		0x1ffff8
+
+#define FRAMEMASTER_NOLACE	1
+#define FRAMEMASTER_ENABLE	2
+#define FRAMEMASTER_COMPL	4
+#define FRAMEMASTER_ROM		8
+
+static volatile unsigned char *fm2fb_reg;
+
+static struct fb_fix_screeninfo fb_fix = {
+	.smem_len =	FRAMEMASTER_REG,
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.line_length =	(768 << 2),
+	.mmio_len =	(8),
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int fm2fb_mode = -1;
+
+#define FM2FB_MODE_PAL	0
+#define FM2FB_MODE_NTSC	1
+
+static struct fb_var_screeninfo fb_var_modes[] = {
+    {
+	/* 768 x 576, 32 bpp (PAL) */
+	768, 576, 768, 576, 0, 0, 32, 0,
+	{ 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
+	0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
+	33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
+    }, {
+	/* 768 x 480, 32 bpp (NTSC - not supported yet */
+	768, 480, 768, 480, 0, 0, 32, 0,
+	{ 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
+	0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
+	33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
+    }
+};
+
+    /*
+     *  Interface used by the world
+     */
+
+static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                           u_int transp, struct fb_info *info);
+static int fm2fb_blank(int blank, struct fb_info *info);
+
+static struct fb_ops fm2fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= fm2fb_setcolreg,
+	.fb_blank	= fm2fb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+    /*
+     *  Blank the display.
+     */
+static int fm2fb_blank(int blank, struct fb_info *info)
+{
+	unsigned char t = FRAMEMASTER_ROM;
+
+	if (!blank)
+		t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE;
+	fm2fb_reg[0] = t;
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp, struct fb_info *info)
+{
+	if (regno < 16) {
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+
+		((u32*)(info->pseudo_palette))[regno] = (red << 16) |
+			(green << 8) | blue;
+	}
+
+	return 0;
+}
+
+    /*
+     *  Initialisation
+     */
+
+static int fm2fb_probe(struct zorro_dev *z, const struct zorro_device_id *id);
+
+static struct zorro_device_id fm2fb_devices[] = {
+	{ ZORRO_PROD_BSC_FRAMEMASTER_II },
+	{ ZORRO_PROD_HELFRICH_RAINBOW_II },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, fm2fb_devices);
+
+static struct zorro_driver fm2fb_driver = {
+	.name		= "fm2fb",
+	.id_table	= fm2fb_devices,
+	.probe		= fm2fb_probe,
+};
+
+static int fm2fb_probe(struct zorro_dev *z, const struct zorro_device_id *id)
+{
+	struct fb_info *info;
+	unsigned long *ptr;
+	int is_fm;
+	int x, y;
+
+	is_fm = z->id == ZORRO_PROD_BSC_FRAMEMASTER_II;
+
+	if (!zorro_request_device(z,"fm2fb"))
+		return -ENXIO;
+
+	info = framebuffer_alloc(16 * sizeof(u32), &z->dev);
+	if (!info) {
+		zorro_release_device(z);
+		return -ENOMEM;
+	}
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		framebuffer_release(info);
+		zorro_release_device(z);
+		return -ENOMEM;
+	}
+
+	/* assigning memory to kernel space */
+	fb_fix.smem_start = zorro_resource_start(z);
+	info->screen_base = ioremap(fb_fix.smem_start, FRAMEMASTER_SIZE);
+	fb_fix.mmio_start = fb_fix.smem_start + FRAMEMASTER_REG;
+	fm2fb_reg  = (unsigned char *)(info->screen_base+FRAMEMASTER_REG);
+
+	strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II");
+
+	/* make EBU color bars on display */
+	ptr = (unsigned long *)fb_fix.smem_start;
+	for (y = 0; y < 576; y++) {
+		for (x = 0; x < 96; x++) *ptr++ = 0xffffff;/* white */
+		for (x = 0; x < 96; x++) *ptr++ = 0xffff00;/* yellow */
+		for (x = 0; x < 96; x++) *ptr++ = 0x00ffff;/* cyan */
+		for (x = 0; x < 96; x++) *ptr++ = 0x00ff00;/* green */
+		for (x = 0; x < 96; x++) *ptr++ = 0xff00ff;/* magenta */
+		for (x = 0; x < 96; x++) *ptr++ = 0xff0000;/* red */
+		for (x = 0; x < 96; x++) *ptr++ = 0x0000ff;/* blue */
+		for (x = 0; x < 96; x++) *ptr++ = 0x000000;/* black */
+	}
+	fm2fb_blank(0, info);
+
+	if (fm2fb_mode == -1)
+		fm2fb_mode = FM2FB_MODE_PAL;
+
+	info->fbops = &fm2fb_ops;
+	info->var = fb_var_modes[fm2fb_mode];
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->fix = fb_fix;
+	info->flags = FBINFO_DEFAULT;
+
+	if (register_framebuffer(info) < 0) {
+		fb_dealloc_cmap(&info->cmap);
+		iounmap(info->screen_base);
+		framebuffer_release(info);
+		zorro_release_device(z);
+		return -EINVAL;
+	}
+	fb_info(info, "%s frame buffer device\n", fb_fix.id);
+	return 0;
+}
+
+int __init fm2fb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "pal", 3))
+			fm2fb_mode = FM2FB_MODE_PAL;
+		else if (!strncmp(this_opt, "ntsc", 4))
+			fm2fb_mode = FM2FB_MODE_NTSC;
+	}
+	return 0;
+}
+
+int __init fm2fb_init(void)
+{
+	char *option = NULL;
+
+	if (fb_get_options("fm2fb", &option))
+		return -ENODEV;
+	fm2fb_setup(option);
+	return zorro_register_driver(&fm2fb_driver);
+}
+
+module_init(fm2fb_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c
new file mode 100644
index 000000000000..e8758b9c3bcc
--- /dev/null
+++ b/drivers/video/fbdev/fsl-diu-fb.c
@@ -0,0 +1,1994 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ *  Freescale DIU Frame Buffer device driver
+ *
+ *  Authors: Hongjun Chen <hong-jun.chen@freescale.com>
+ *           Paul Widmer <paul.widmer@freescale.com>
+ *           Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
+ *           York Sun <yorksun@freescale.com>
+ *
+ *   Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/spinlock.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <sysdev/fsl_soc.h>
+#include <linux/fsl-diu-fb.h>
+#include "edid.h"
+
+#define NUM_AOIS	5	/* 1 for plane 0, 2 for planes 1 & 2 each */
+
+/* HW cursor parameters */
+#define MAX_CURS		32
+
+/* INT_STATUS/INT_MASK field descriptions */
+#define INT_VSYNC	0x01	/* Vsync interrupt  */
+#define INT_VSYNC_WB	0x02	/* Vsync interrupt for write back operation */
+#define INT_UNDRUN	0x04	/* Under run exception interrupt */
+#define INT_PARERR	0x08	/* Display parameters error interrupt */
+#define INT_LS_BF_VS	0x10	/* Lines before vsync. interrupt */
+
+/*
+ * List of supported video modes
+ *
+ * The first entry is the default video mode.  The remain entries are in
+ * order if increasing resolution and frequency.  The 320x240-60 mode is
+ * the initial AOI for the second and third planes.
+ */
+static struct fb_videomode fsl_diu_mode_db[] = {
+	{
+		.refresh	= 60,
+		.xres		= 1024,
+		.yres		= 768,
+		.pixclock	= 15385,
+		.left_margin	= 160,
+		.right_margin	= 24,
+		.upper_margin	= 29,
+		.lower_margin	= 3,
+		.hsync_len	= 136,
+		.vsync_len	= 6,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 60,
+		.xres		= 320,
+		.yres		= 240,
+		.pixclock	= 79440,
+		.left_margin	= 16,
+		.right_margin	= 16,
+		.upper_margin	= 16,
+		.lower_margin	= 5,
+		.hsync_len	= 48,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh        = 60,
+		.xres           = 640,
+		.yres           = 480,
+		.pixclock       = 39722,
+		.left_margin    = 48,
+		.right_margin   = 16,
+		.upper_margin   = 33,
+		.lower_margin   = 10,
+		.hsync_len      = 96,
+		.vsync_len      = 2,
+		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode          = FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh        = 72,
+		.xres           = 640,
+		.yres           = 480,
+		.pixclock       = 32052,
+		.left_margin    = 128,
+		.right_margin   = 24,
+		.upper_margin   = 28,
+		.lower_margin   = 9,
+		.hsync_len      = 40,
+		.vsync_len      = 3,
+		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode          = FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh        = 75,
+		.xres           = 640,
+		.yres           = 480,
+		.pixclock       = 31747,
+		.left_margin    = 120,
+		.right_margin   = 16,
+		.upper_margin   = 16,
+		.lower_margin   = 1,
+		.hsync_len      = 64,
+		.vsync_len      = 3,
+		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode          = FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh        = 90,
+		.xres           = 640,
+		.yres           = 480,
+		.pixclock       = 25057,
+		.left_margin    = 120,
+		.right_margin   = 32,
+		.upper_margin   = 14,
+		.lower_margin   = 25,
+		.hsync_len      = 40,
+		.vsync_len      = 14,
+		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode          = FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh        = 100,
+		.xres           = 640,
+		.yres           = 480,
+		.pixclock       = 22272,
+		.left_margin    = 48,
+		.right_margin   = 32,
+		.upper_margin   = 17,
+		.lower_margin   = 22,
+		.hsync_len      = 128,
+		.vsync_len      = 12,
+		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode          = FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= 33805,
+		.left_margin	= 96,
+		.right_margin	= 24,
+		.upper_margin	= 10,
+		.lower_margin	= 3,
+		.hsync_len	= 72,
+		.vsync_len	= 7,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh        = 60,
+		.xres           = 800,
+		.yres           = 600,
+		.pixclock       = 25000,
+		.left_margin    = 88,
+		.right_margin   = 40,
+		.upper_margin   = 23,
+		.lower_margin   = 1,
+		.hsync_len      = 128,
+		.vsync_len      = 4,
+		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode          = FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 60,
+		.xres		= 854,
+		.yres		= 480,
+		.pixclock	= 31518,
+		.left_margin	= 104,
+		.right_margin	= 16,
+		.upper_margin	= 13,
+		.lower_margin	= 1,
+		.hsync_len	= 88,
+		.vsync_len	= 3,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 70,
+		.xres		= 1024,
+		.yres		= 768,
+		.pixclock	= 16886,
+		.left_margin	= 3,
+		.right_margin	= 3,
+		.upper_margin	= 2,
+		.lower_margin	= 2,
+		.hsync_len	= 40,
+		.vsync_len	= 18,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 75,
+		.xres		= 1024,
+		.yres		= 768,
+		.pixclock	= 15009,
+		.left_margin	= 3,
+		.right_margin	= 3,
+		.upper_margin	= 2,
+		.lower_margin	= 2,
+		.hsync_len	= 80,
+		.vsync_len	= 32,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 60,
+		.xres		= 1280,
+		.yres		= 480,
+		.pixclock	= 18939,
+		.left_margin	= 353,
+		.right_margin	= 47,
+		.upper_margin	= 39,
+		.lower_margin	= 4,
+		.hsync_len	= 8,
+		.vsync_len	= 2,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 60,
+		.xres		= 1280,
+		.yres		= 720,
+		.pixclock	= 13426,
+		.left_margin	= 192,
+		.right_margin	= 64,
+		.upper_margin	= 22,
+		.lower_margin	= 1,
+		.hsync_len	= 136,
+		.vsync_len	= 3,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 60,
+		.xres		= 1280,
+		.yres		= 1024,
+		.pixclock	= 9375,
+		.left_margin	= 38,
+		.right_margin	= 128,
+		.upper_margin	= 2,
+		.lower_margin	= 7,
+		.hsync_len	= 216,
+		.vsync_len	= 37,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 70,
+		.xres		= 1280,
+		.yres		= 1024,
+		.pixclock	= 9380,
+		.left_margin	= 6,
+		.right_margin	= 6,
+		.upper_margin	= 4,
+		.lower_margin	= 4,
+		.hsync_len	= 60,
+		.vsync_len	= 94,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 75,
+		.xres		= 1280,
+		.yres		= 1024,
+		.pixclock	= 9380,
+		.left_margin	= 6,
+		.right_margin	= 6,
+		.upper_margin	= 4,
+		.lower_margin	= 4,
+		.hsync_len	= 60,
+		.vsync_len	= 15,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+	{
+		.refresh	= 60,
+		.xres		= 1920,
+		.yres		= 1080,
+		.pixclock	= 5787,
+		.left_margin	= 328,
+		.right_margin	= 120,
+		.upper_margin	= 34,
+		.lower_margin	= 1,
+		.hsync_len	= 208,
+		.vsync_len	= 3,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
+};
+
+static char *fb_mode;
+static unsigned long default_bpp = 32;
+static enum fsl_diu_monitor_port monitor_port;
+static char *monitor_string;
+
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+static u8 *coherence_data;
+static size_t coherence_data_size;
+static unsigned int d_cache_line_size;
+#endif
+
+static DEFINE_SPINLOCK(diu_lock);
+
+enum mfb_index {
+	PLANE0 = 0,	/* Plane 0, only one AOI that fills the screen */
+	PLANE1_AOI0,	/* Plane 1, first AOI */
+	PLANE1_AOI1,	/* Plane 1, second AOI */
+	PLANE2_AOI0,	/* Plane 2, first AOI */
+	PLANE2_AOI1,	/* Plane 2, second AOI */
+};
+
+struct mfb_info {
+	enum mfb_index index;
+	char *id;
+	int registered;
+	unsigned long pseudo_palette[16];
+	struct diu_ad *ad;
+	unsigned char g_alpha;
+	unsigned int count;
+	int x_aoi_d;		/* aoi display x offset to physical screen */
+	int y_aoi_d;		/* aoi display y offset to physical screen */
+	struct fsl_diu_data *parent;
+};
+
+/**
+ * struct fsl_diu_data - per-DIU data structure
+ * @dma_addr: DMA address of this structure
+ * @fsl_diu_info: fb_info objects, one per AOI
+ * @dev_attr: sysfs structure
+ * @irq: IRQ
+ * @monitor_port: the monitor port this DIU is connected to
+ * @diu_reg: pointer to the DIU hardware registers
+ * @reg_lock: spinlock for register access
+ * @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
+ * dummy_ad: DIU Area Descriptor for the dummy AOI
+ * @ad[]: Area Descriptors for each real AOI
+ * @gamma: gamma color table
+ * @cursor: hardware cursor data
+ *
+ * This data structure must be allocated with 32-byte alignment, so that the
+ * internal fields can be aligned properly.
+ */
+struct fsl_diu_data {
+	dma_addr_t dma_addr;
+	struct fb_info fsl_diu_info[NUM_AOIS];
+	struct mfb_info mfb[NUM_AOIS];
+	struct device_attribute dev_attr;
+	unsigned int irq;
+	enum fsl_diu_monitor_port monitor_port;
+	struct diu __iomem *diu_reg;
+	spinlock_t reg_lock;
+	u8 dummy_aoi[4 * 4 * 4];
+	struct diu_ad dummy_ad __aligned(8);
+	struct diu_ad ad[NUM_AOIS] __aligned(8);
+	u8 gamma[256 * 3] __aligned(32);
+	/* It's easier to parse the cursor data as little-endian */
+	__le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
+	/* Blank cursor data -- used to hide the cursor */
+	__le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
+	uint8_t edid_data[EDID_LENGTH];
+	bool has_edid;
+} __aligned(32);
+
+/* Determine the DMA address of a member of the fsl_diu_data structure */
+#define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
+
+static struct mfb_info mfb_template[] = {
+	{
+		.index = PLANE0,
+		.id = "Panel0",
+		.registered = 0,
+		.count = 0,
+		.x_aoi_d = 0,
+		.y_aoi_d = 0,
+	},
+	{
+		.index = PLANE1_AOI0,
+		.id = "Panel1 AOI0",
+		.registered = 0,
+		.g_alpha = 0xff,
+		.count = 0,
+		.x_aoi_d = 0,
+		.y_aoi_d = 0,
+	},
+	{
+		.index = PLANE1_AOI1,
+		.id = "Panel1 AOI1",
+		.registered = 0,
+		.g_alpha = 0xff,
+		.count = 0,
+		.x_aoi_d = 0,
+		.y_aoi_d = 480,
+	},
+	{
+		.index = PLANE2_AOI0,
+		.id = "Panel2 AOI0",
+		.registered = 0,
+		.g_alpha = 0xff,
+		.count = 0,
+		.x_aoi_d = 640,
+		.y_aoi_d = 0,
+	},
+	{
+		.index = PLANE2_AOI1,
+		.id = "Panel2 AOI1",
+		.registered = 0,
+		.g_alpha = 0xff,
+		.count = 0,
+		.x_aoi_d = 640,
+		.y_aoi_d = 480,
+	},
+};
+
+#ifdef DEBUG
+static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw)
+{
+	mb();
+	pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x "
+		 "cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x "
+		 "disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x "
+		 "thresholds=%08x int_mask=%08x plut=%08x\n",
+		 hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma,
+		 hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode,
+		 hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para,
+		 hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut);
+	rmb();
+}
+#endif
+
+/**
+ * fsl_diu_name_to_port - convert a port name to a monitor port enum
+ *
+ * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
+ * the enum fsl_diu_monitor_port that corresponds to that string.
+ *
+ * For compatibility with older versions, a number ("0", "1", or "2") is also
+ * supported.
+ *
+ * If the string is unknown, DVI is assumed.
+ *
+ * If the particular port is not supported by the platform, another port
+ * (platform-specific) is chosen instead.
+ */
+static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
+{
+	enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI;
+	unsigned long val;
+
+	if (s) {
+		if (!kstrtoul(s, 10, &val) && (val <= 2))
+			port = (enum fsl_diu_monitor_port) val;
+		else if (strncmp(s, "lvds", 4) == 0)
+			port = FSL_DIU_PORT_LVDS;
+		else if (strncmp(s, "dlvds", 5) == 0)
+			port = FSL_DIU_PORT_DLVDS;
+	}
+
+	return diu_ops.valid_monitor_port(port);
+}
+
+/*
+ * Workaround for failed writing desc register of planes.
+ * Needed with MPC5121 DIU rev 2.0 silicon.
+ */
+void wr_reg_wa(u32 *reg, u32 val)
+{
+	do {
+		out_be32(reg, val);
+	} while (in_be32(reg) != val);
+}
+
+static void fsl_diu_enable_panel(struct fb_info *info)
+{
+	struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
+	struct diu_ad *ad = mfbi->ad;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu __iomem *hw = data->diu_reg;
+
+	switch (mfbi->index) {
+	case PLANE0:
+		wr_reg_wa(&hw->desc[0], ad->paddr);
+		break;
+	case PLANE1_AOI0:
+		cmfbi = &data->mfb[2];
+		if (hw->desc[1] != ad->paddr) {	/* AOI0 closed */
+			if (cmfbi->count > 0)	/* AOI1 open */
+				ad->next_ad =
+					cpu_to_le32(cmfbi->ad->paddr);
+			else
+				ad->next_ad = 0;
+			wr_reg_wa(&hw->desc[1], ad->paddr);
+		}
+		break;
+	case PLANE2_AOI0:
+		cmfbi = &data->mfb[4];
+		if (hw->desc[2] != ad->paddr) {	/* AOI0 closed */
+			if (cmfbi->count > 0)	/* AOI1 open */
+				ad->next_ad =
+					cpu_to_le32(cmfbi->ad->paddr);
+			else
+				ad->next_ad = 0;
+			wr_reg_wa(&hw->desc[2], ad->paddr);
+		}
+		break;
+	case PLANE1_AOI1:
+		pmfbi = &data->mfb[1];
+		ad->next_ad = 0;
+		if (hw->desc[1] == data->dummy_ad.paddr)
+			wr_reg_wa(&hw->desc[1], ad->paddr);
+		else					/* AOI0 open */
+			pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
+		break;
+	case PLANE2_AOI1:
+		pmfbi = &data->mfb[3];
+		ad->next_ad = 0;
+		if (hw->desc[2] == data->dummy_ad.paddr)
+			wr_reg_wa(&hw->desc[2], ad->paddr);
+		else				/* AOI0 was open */
+			pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
+		break;
+	}
+}
+
+static void fsl_diu_disable_panel(struct fb_info *info)
+{
+	struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
+	struct diu_ad *ad = mfbi->ad;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu __iomem *hw = data->diu_reg;
+
+	switch (mfbi->index) {
+	case PLANE0:
+		wr_reg_wa(&hw->desc[0], 0);
+		break;
+	case PLANE1_AOI0:
+		cmfbi = &data->mfb[2];
+		if (cmfbi->count > 0)	/* AOI1 is open */
+			wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
+					/* move AOI1 to the first */
+		else			/* AOI1 was closed */
+			wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
+					/* close AOI 0 */
+		break;
+	case PLANE2_AOI0:
+		cmfbi = &data->mfb[4];
+		if (cmfbi->count > 0)	/* AOI1 is open */
+			wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
+					/* move AOI1 to the first */
+		else			/* AOI1 was closed */
+			wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
+					/* close AOI 0 */
+		break;
+	case PLANE1_AOI1:
+		pmfbi = &data->mfb[1];
+		if (hw->desc[1] != ad->paddr) {
+				/* AOI1 is not the first in the chain */
+			if (pmfbi->count > 0)
+					/* AOI0 is open, must be the first */
+				pmfbi->ad->next_ad = 0;
+		} else			/* AOI1 is the first in the chain */
+			wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
+					/* close AOI 1 */
+		break;
+	case PLANE2_AOI1:
+		pmfbi = &data->mfb[3];
+		if (hw->desc[2] != ad->paddr) {
+				/* AOI1 is not the first in the chain */
+			if (pmfbi->count > 0)
+				/* AOI0 is open, must be the first */
+				pmfbi->ad->next_ad = 0;
+		} else		/* AOI1 is the first in the chain */
+			wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
+				/* close AOI 1 */
+		break;
+	}
+}
+
+static void enable_lcdc(struct fb_info *info)
+{
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu __iomem *hw = data->diu_reg;
+
+	out_be32(&hw->diu_mode, MFB_MODE1);
+}
+
+static void disable_lcdc(struct fb_info *info)
+{
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu __iomem *hw = data->diu_reg;
+
+	out_be32(&hw->diu_mode, 0);
+}
+
+static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	int available_height, upper_aoi_bottom;
+	enum mfb_index index = mfbi->index;
+	int lower_aoi_is_open, upper_aoi_is_open;
+	__u32 base_plane_width, base_plane_height, upper_aoi_height;
+
+	base_plane_width = data->fsl_diu_info[0].var.xres;
+	base_plane_height = data->fsl_diu_info[0].var.yres;
+
+	if (mfbi->x_aoi_d < 0)
+		mfbi->x_aoi_d = 0;
+	if (mfbi->y_aoi_d < 0)
+		mfbi->y_aoi_d = 0;
+	switch (index) {
+	case PLANE0:
+		if (mfbi->x_aoi_d != 0)
+			mfbi->x_aoi_d = 0;
+		if (mfbi->y_aoi_d != 0)
+			mfbi->y_aoi_d = 0;
+		break;
+	case PLANE1_AOI0:
+	case PLANE2_AOI0:
+		lower_aoi_mfbi = data->fsl_diu_info[index+1].par;
+		lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
+		if (var->xres > base_plane_width)
+			var->xres = base_plane_width;
+		if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
+			mfbi->x_aoi_d = base_plane_width - var->xres;
+
+		if (lower_aoi_is_open)
+			available_height = lower_aoi_mfbi->y_aoi_d;
+		else
+			available_height = base_plane_height;
+		if (var->yres > available_height)
+			var->yres = available_height;
+		if ((mfbi->y_aoi_d + var->yres) > available_height)
+			mfbi->y_aoi_d = available_height - var->yres;
+		break;
+	case PLANE1_AOI1:
+	case PLANE2_AOI1:
+		upper_aoi_mfbi = data->fsl_diu_info[index-1].par;
+		upper_aoi_height = data->fsl_diu_info[index-1].var.yres;
+		upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
+		upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
+		if (var->xres > base_plane_width)
+			var->xres = base_plane_width;
+		if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
+			mfbi->x_aoi_d = base_plane_width - var->xres;
+		if (mfbi->y_aoi_d < 0)
+			mfbi->y_aoi_d = 0;
+		if (upper_aoi_is_open) {
+			if (mfbi->y_aoi_d < upper_aoi_bottom)
+				mfbi->y_aoi_d = upper_aoi_bottom;
+			available_height = base_plane_height
+						- upper_aoi_bottom;
+		} else
+			available_height = base_plane_height;
+		if (var->yres > available_height)
+			var->yres = available_height;
+		if ((mfbi->y_aoi_d + var->yres) > base_plane_height)
+			mfbi->y_aoi_d = base_plane_height - var->yres;
+		break;
+	}
+}
+/*
+ * Checks to see if the hardware supports the state requested by var passed
+ * in. This function does not alter the hardware state! If the var passed in
+ * is slightly off by what the hardware can support then we alter the var
+ * PASSED in to what we can do. If the hardware doesn't support mode change
+ * a -EINVAL will be returned by the upper layers.
+ */
+static int fsl_diu_check_var(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->xoffset < 0)
+		var->xoffset = 0;
+
+	if (var->yoffset < 0)
+		var->yoffset = 0;
+
+	if (var->xoffset + info->var.xres > info->var.xres_virtual)
+		var->xoffset = info->var.xres_virtual - info->var.xres;
+
+	if (var->yoffset + info->var.yres > info->var.yres_virtual)
+		var->yoffset = info->var.yres_virtual - info->var.yres;
+
+	if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
+	    (var->bits_per_pixel != 16))
+		var->bits_per_pixel = default_bpp;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		var->red.length = 5;
+		var->red.offset = 11;
+		var->red.msb_right = 0;
+
+		var->green.length = 6;
+		var->green.offset = 5;
+		var->green.msb_right = 0;
+
+		var->blue.length = 5;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 24:
+		var->red.length = 8;
+		var->red.offset = 0;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 16;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 32:
+		var->red.length = 8;
+		var->red.offset = 16;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		var->transp.msb_right = 0;
+
+		break;
+	}
+
+	var->height = -1;
+	var->width = -1;
+	var->grayscale = 0;
+
+	/* Copy nonstd field to/from sync for fbset usage */
+	var->sync |= var->nonstd;
+	var->nonstd |= var->sync;
+
+	adjust_aoi_size_position(var, info);
+	return 0;
+}
+
+static void set_fix(struct fb_info *info)
+{
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct fb_var_screeninfo *var = &info->var;
+	struct mfb_info *mfbi = info->par;
+
+	strncpy(fix->id, mfbi->id, sizeof(fix->id));
+	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->accel = FB_ACCEL_NONE;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+}
+
+static void update_lcdc(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu __iomem *hw;
+	int i, j;
+	u8 *gamma_table_base;
+
+	u32 temp;
+
+	hw = data->diu_reg;
+
+	if (diu_ops.set_monitor_port)
+		diu_ops.set_monitor_port(data->monitor_port);
+	gamma_table_base = data->gamma;
+
+	/* Prep for DIU init  - gamma table, cursor table */
+
+	for (i = 0; i <= 2; i++)
+		for (j = 0; j <= 255; j++)
+			*gamma_table_base++ = j;
+
+	if (diu_ops.set_gamma_table)
+		diu_ops.set_gamma_table(data->monitor_port, data->gamma);
+
+	disable_lcdc(info);
+
+	/* Program DIU registers */
+
+	out_be32(&hw->gamma, DMA_ADDR(data, gamma));
+
+	out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
+	out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
+
+	/* Horizontal and vertical configuration register */
+	temp = var->left_margin << 22 | /* BP_H */
+	       var->hsync_len << 11 |   /* PW_H */
+	       var->right_margin;       /* FP_H */
+
+	out_be32(&hw->hsyn_para, temp);
+
+	temp = var->upper_margin << 22 | /* BP_V */
+	       var->vsync_len << 11 |    /* PW_V  */
+	       var->lower_margin;        /* FP_V  */
+
+	out_be32(&hw->vsyn_para, temp);
+
+	diu_ops.set_pixel_clock(var->pixclock);
+
+#ifndef CONFIG_PPC_MPC512x
+	/*
+	 * The PLUT register is defined differently on the MPC5121 than it
+	 * is on other SOCs.  Unfortunately, there's no documentation that
+	 * explains how it's supposed to be programmed, so for now, we leave
+	 * it at the default value on the MPC5121.
+	 *
+	 * For other SOCs, program it for the highest priority, which will
+	 * reduce the chance of underrun. Technically, we should scale the
+	 * priority to match the screen resolution, but doing that properly
+	 * requires delicate fine-tuning for each use-case.
+	 */
+	out_be32(&hw->plut, 0x01F5F666);
+#endif
+
+	/* Enable the DIU */
+	enable_lcdc(info);
+}
+
+static int map_video_memory(struct fb_info *info)
+{
+	u32 smem_len = info->fix.line_length * info->var.yres_virtual;
+	void *p;
+
+	p = alloc_pages_exact(smem_len, GFP_DMA | __GFP_ZERO);
+	if (!p) {
+		dev_err(info->dev, "unable to allocate fb memory\n");
+		return -ENOMEM;
+	}
+	mutex_lock(&info->mm_lock);
+	info->screen_base = p;
+	info->fix.smem_start = virt_to_phys(info->screen_base);
+	info->fix.smem_len = smem_len;
+	mutex_unlock(&info->mm_lock);
+	info->screen_size = info->fix.smem_len;
+
+	return 0;
+}
+
+static void unmap_video_memory(struct fb_info *info)
+{
+	void *p = info->screen_base;
+	size_t l = info->fix.smem_len;
+
+	mutex_lock(&info->mm_lock);
+	info->screen_base = NULL;
+	info->fix.smem_start = 0;
+	info->fix.smem_len = 0;
+	mutex_unlock(&info->mm_lock);
+
+	if (p)
+		free_pages_exact(p, l);
+}
+
+/*
+ * Using the fb_var_screeninfo in fb_info we set the aoi of this
+ * particular framebuffer. It is a light version of fsl_diu_set_par.
+ */
+static int fsl_diu_set_aoi(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct mfb_info *mfbi = info->par;
+	struct diu_ad *ad = mfbi->ad;
+
+	/* AOI should not be greater than display size */
+	ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
+	ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
+	return 0;
+}
+
+/**
+ * fsl_diu_get_pixel_format: return the pixel format for a given color depth
+ *
+ * The pixel format is a 32-bit value that determine which bits in each
+ * pixel are to be used for each color.  This is the default function used
+ * if the platform does not define its own version.
+ */
+static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
+{
+#define PF_BYTE_F		0x10000000
+#define PF_ALPHA_C_MASK		0x0E000000
+#define PF_ALPHA_C_SHIFT	25
+#define PF_BLUE_C_MASK		0x01800000
+#define PF_BLUE_C_SHIFT		23
+#define PF_GREEN_C_MASK		0x00600000
+#define PF_GREEN_C_SHIFT	21
+#define PF_RED_C_MASK		0x00180000
+#define PF_RED_C_SHIFT		19
+#define PF_PALETTE		0x00040000
+#define PF_PIXEL_S_MASK		0x00030000
+#define PF_PIXEL_S_SHIFT	16
+#define PF_COMP_3_MASK		0x0000F000
+#define PF_COMP_3_SHIFT		12
+#define PF_COMP_2_MASK		0x00000F00
+#define PF_COMP_2_SHIFT		8
+#define PF_COMP_1_MASK		0x000000F0
+#define PF_COMP_1_SHIFT		4
+#define PF_COMP_0_MASK		0x0000000F
+#define PF_COMP_0_SHIFT		0
+
+#define MAKE_PF(alpha, red, green, blue, size, c0, c1, c2, c3) \
+	cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
+	(blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
+	(red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
+	(c2 << PF_COMP_2_SHIFT) | (c1 << PF_COMP_1_SHIFT) | \
+	(c0 << PF_COMP_0_SHIFT) | (size << PF_PIXEL_S_SHIFT))
+
+	switch (bits_per_pixel) {
+	case 32:
+		/* 0x88883316 */
+		return MAKE_PF(3, 2, 1, 0, 3, 8, 8, 8, 8);
+	case 24:
+		/* 0x88082219 */
+		return MAKE_PF(4, 0, 1, 2, 2, 8, 8, 8, 0);
+	case 16:
+		/* 0x65053118 */
+		return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
+	default:
+		pr_err("fsl-diu: unsupported color depth %u\n", bits_per_pixel);
+		return 0;
+	}
+}
+
+/*
+ * Copies a cursor image from user space to the proper place in driver
+ * memory so that the hardware can display the cursor image.
+ *
+ * Cursor data is represented as a sequence of 'width' bits packed into bytes.
+ * That is, the first 8 bits are in the first byte, the second 8 bits in the
+ * second byte, and so on.  Therefore, the each row of the cursor is (width +
+ * 7) / 8 bytes of 'data'
+ *
+ * The DIU only supports cursors up to 32x32 (MAX_CURS).  We reject cursors
+ * larger than this, so we already know that 'width' <= 32.  Therefore, we can
+ * simplify our code by using a 32-bit big-endian integer ("line") to read in
+ * a single line of pixels, and only look at the top 'width' bits of that
+ * integer.
+ *
+ * This could result in an unaligned 32-bit read.  For example, if the cursor
+ * is 24x24, then the first three bytes of 'image' contain the pixel data for
+ * the top line of the cursor.  We do a 32-bit read of 'image', but we look
+ * only at the top 24 bits.  Then we increment 'image' by 3 bytes.  The next
+ * read is unaligned.  The only problem is that we might read past the end of
+ * 'image' by 1-3 bytes, but that should not cause any problems.
+ */
+static void fsl_diu_load_cursor_image(struct fb_info *info,
+	const void *image, uint16_t bg, uint16_t fg,
+	unsigned int width, unsigned int height)
+{
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	__le16 *cursor = data->cursor;
+	__le16 _fg = cpu_to_le16(fg);
+	__le16 _bg = cpu_to_le16(bg);
+	unsigned int h, w;
+
+	for (h = 0; h < height; h++) {
+		uint32_t mask = 1 << 31;
+		uint32_t line = be32_to_cpup(image);
+
+		for (w = 0; w < width; w++) {
+			cursor[w] = (line & mask) ? _fg : _bg;
+			mask >>= 1;
+		}
+
+		cursor += MAX_CURS;
+		image += DIV_ROUND_UP(width, 8);
+	}
+}
+
+/*
+ * Set a hardware cursor.  The image data for the cursor is passed via the
+ * fb_cursor object.
+ */
+static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu __iomem *hw = data->diu_reg;
+
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return -EINVAL;
+
+	/* The cursor size has changed */
+	if (cursor->set & FB_CUR_SETSIZE) {
+		/*
+		 * The DIU cursor is a fixed size, so when we get this
+		 * message, instead of resizing the cursor, we just clear
+		 * all the image data, in expectation of new data.  However,
+		 * in tests this control does not appear to be normally
+		 * called.
+		 */
+		memset(data->cursor, 0, sizeof(data->cursor));
+	}
+
+	/* The cursor position has changed (cursor->image.dx|dy) */
+	if (cursor->set & FB_CUR_SETPOS) {
+		uint32_t xx, yy;
+
+		yy = (cursor->image.dy - info->var.yoffset) & 0x7ff;
+		xx = (cursor->image.dx - info->var.xoffset) & 0x7ff;
+
+		out_be32(&hw->curs_pos, yy << 16 | xx);
+	}
+
+	/*
+	 * FB_CUR_SETIMAGE - the cursor image has changed
+	 * FB_CUR_SETCMAP  - the cursor colors has changed
+	 * FB_CUR_SETSHAPE - the cursor bitmask has changed
+	 */
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		unsigned int image_size =
+			DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
+		unsigned int image_words =
+			DIV_ROUND_UP(image_size, sizeof(uint32_t));
+		unsigned int bg_idx = cursor->image.bg_color;
+		unsigned int fg_idx = cursor->image.fg_color;
+		uint8_t buffer[image_size];
+		uint32_t *image, *source, *mask;
+		uint16_t fg, bg;
+		unsigned int i;
+
+		if (info->state != FBINFO_STATE_RUNNING)
+			return 0;
+
+		/*
+		 * Determine the size of the cursor image data.  Normally,
+		 * it's 8x16.
+		 */
+		image_size = DIV_ROUND_UP(cursor->image.width, 8) *
+			cursor->image.height;
+
+		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
+		     1 << 15;
+
+		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+		     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
+		     1 << 15;
+
+		/* Use 32-bit operations on the data to improve performance */
+		image = (uint32_t *)buffer;
+		source = (uint32_t *)cursor->image.data;
+		mask = (uint32_t *)cursor->mask;
+
+		if (cursor->rop == ROP_XOR)
+			for (i = 0; i < image_words; i++)
+				image[i] = source[i] ^ mask[i];
+		else
+			for (i = 0; i < image_words; i++)
+				image[i] = source[i] & mask[i];
+
+		fsl_diu_load_cursor_image(info, image, bg, fg,
+			cursor->image.width, cursor->image.height);
+	}
+
+	/*
+	 * Show or hide the cursor.  The cursor data is always stored in the
+	 * 'cursor' memory block, and the actual cursor position is always in
+	 * the DIU's CURS_POS register.  To hide the cursor, we redirect the
+	 * CURSOR register to a blank cursor.  The show the cursor, we
+	 * redirect the CURSOR register to the real cursor data.
+	 */
+	if (cursor->enable)
+		out_be32(&hw->cursor, DMA_ADDR(data, cursor));
+	else
+		out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor));
+
+	return 0;
+}
+
+/*
+ * Using the fb_var_screeninfo in fb_info we set the resolution of this
+ * particular framebuffer. This function alters the fb_fix_screeninfo stored
+ * in fb_info. It does not alter var in fb_info since we are using that
+ * data. This means we depend on the data in var inside fb_info to be
+ * supported by the hardware. fsl_diu_check_var is always called before
+ * fsl_diu_set_par to ensure this.
+ */
+static int fsl_diu_set_par(struct fb_info *info)
+{
+	unsigned long len;
+	struct fb_var_screeninfo *var = &info->var;
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	struct diu_ad *ad = mfbi->ad;
+	struct diu __iomem *hw;
+
+	hw = data->diu_reg;
+
+	set_fix(info);
+
+	len = info->var.yres_virtual * info->fix.line_length;
+	/* Alloc & dealloc each time resolution/bpp change */
+	if (len != info->fix.smem_len) {
+		if (info->fix.smem_start)
+			unmap_video_memory(info);
+
+		/* Memory allocation for framebuffer */
+		if (map_video_memory(info)) {
+			dev_err(info->dev, "unable to allocate fb memory 1\n");
+			return -ENOMEM;
+		}
+	}
+
+	if (diu_ops.get_pixel_format)
+		ad->pix_fmt = diu_ops.get_pixel_format(data->monitor_port,
+						       var->bits_per_pixel);
+	else
+		ad->pix_fmt = fsl_diu_get_pixel_format(var->bits_per_pixel);
+
+	ad->addr    = cpu_to_le32(info->fix.smem_start);
+	ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
+				var->xres_virtual) | mfbi->g_alpha;
+	/* AOI should not be greater than display size */
+	ad->aoi_size 	= cpu_to_le32((var->yres << 16) | var->xres);
+	ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
+	ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
+
+	/* Disable chroma keying function */
+	ad->ckmax_r = 0;
+	ad->ckmax_g = 0;
+	ad->ckmax_b = 0;
+
+	ad->ckmin_r = 255;
+	ad->ckmin_g = 255;
+	ad->ckmin_b = 255;
+
+	if (mfbi->index == PLANE0)
+		update_lcdc(info);
+	return 0;
+}
+
+static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
+{
+	return ((val << width) + 0x7FFF - val) >> 16;
+}
+
+/*
+ * Set a single color register. The values supplied have a 16 bit magnitude
+ * which needs to be scaled in this function for the hardware. Things to take
+ * into consideration are how many color registers, if any, are supported with
+ * the current color visual. With truecolor mode no color palettes are
+ * supported. Here a pseudo palette is created which we store the value in
+ * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
+ * color palette.
+ */
+static int fsl_diu_setcolreg(unsigned int regno, unsigned int red,
+			     unsigned int green, unsigned int blue,
+			     unsigned int transp, struct fb_info *info)
+{
+	int ret = 1;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+				      7471 * blue) >> 16;
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+			u32 v;
+
+			red = CNVT_TOHW(red, info->var.red.length);
+			green = CNVT_TOHW(green, info->var.green.length);
+			blue = CNVT_TOHW(blue, info->var.blue.length);
+			transp = CNVT_TOHW(transp, info->var.transp.length);
+
+			v = (red << info->var.red.offset) |
+			    (green << info->var.green.offset) |
+			    (blue << info->var.blue.offset) |
+			    (transp << info->var.transp.offset);
+
+			pal[regno] = v;
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values
+ * don't fit, return -EINVAL.
+ */
+static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	if ((info->var.xoffset == var->xoffset) &&
+	    (info->var.yoffset == var->yoffset))
+		return 0;	/* No change, do nothing */
+
+	if (var->xoffset < 0 || var->yoffset < 0
+	    || var->xoffset + info->var.xres > info->var.xres_virtual
+	    || var->yoffset + info->var.yres > info->var.yres_virtual)
+		return -EINVAL;
+
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+
+	fsl_diu_set_aoi(info);
+
+	return 0;
+}
+
+static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	struct mfb_info *mfbi = info->par;
+	struct diu_ad *ad = mfbi->ad;
+	struct mfb_chroma_key ck;
+	unsigned char global_alpha;
+	struct aoi_display_offset aoi_d;
+	__u32 pix_fmt;
+	void __user *buf = (void __user *)arg;
+
+	if (!arg)
+		return -EINVAL;
+
+	dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd,
+		_IOC_DIR(cmd) & _IOC_READ ? "R" : "",
+		_IOC_DIR(cmd) & _IOC_WRITE ? "W" : "",
+		_IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
+
+	switch (cmd) {
+	case MFB_SET_PIXFMT_OLD:
+		dev_warn(info->dev,
+			 "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n",
+			 MFB_SET_PIXFMT_OLD);
+	case MFB_SET_PIXFMT:
+		if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt)))
+			return -EFAULT;
+		ad->pix_fmt = pix_fmt;
+		break;
+	case MFB_GET_PIXFMT_OLD:
+		dev_warn(info->dev,
+			 "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n",
+			 MFB_GET_PIXFMT_OLD);
+	case MFB_GET_PIXFMT:
+		pix_fmt = ad->pix_fmt;
+		if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt)))
+			return -EFAULT;
+		break;
+	case MFB_SET_AOID:
+		if (copy_from_user(&aoi_d, buf, sizeof(aoi_d)))
+			return -EFAULT;
+		mfbi->x_aoi_d = aoi_d.x_aoi_d;
+		mfbi->y_aoi_d = aoi_d.y_aoi_d;
+		fsl_diu_check_var(&info->var, info);
+		fsl_diu_set_aoi(info);
+		break;
+	case MFB_GET_AOID:
+		aoi_d.x_aoi_d = mfbi->x_aoi_d;
+		aoi_d.y_aoi_d = mfbi->y_aoi_d;
+		if (copy_to_user(buf, &aoi_d, sizeof(aoi_d)))
+			return -EFAULT;
+		break;
+	case MFB_GET_ALPHA:
+		global_alpha = mfbi->g_alpha;
+		if (copy_to_user(buf, &global_alpha, sizeof(global_alpha)))
+			return -EFAULT;
+		break;
+	case MFB_SET_ALPHA:
+		/* set panel information */
+		if (copy_from_user(&global_alpha, buf, sizeof(global_alpha)))
+			return -EFAULT;
+		ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) |
+							(global_alpha & 0xff);
+		mfbi->g_alpha = global_alpha;
+		break;
+	case MFB_SET_CHROMA_KEY:
+		/* set panel winformation */
+		if (copy_from_user(&ck, buf, sizeof(ck)))
+			return -EFAULT;
+
+		if (ck.enable &&
+		   (ck.red_max < ck.red_min ||
+		    ck.green_max < ck.green_min ||
+		    ck.blue_max < ck.blue_min))
+			return -EINVAL;
+
+		if (!ck.enable) {
+			ad->ckmax_r = 0;
+			ad->ckmax_g = 0;
+			ad->ckmax_b = 0;
+			ad->ckmin_r = 255;
+			ad->ckmin_g = 255;
+			ad->ckmin_b = 255;
+		} else {
+			ad->ckmax_r = ck.red_max;
+			ad->ckmax_g = ck.green_max;
+			ad->ckmax_b = ck.blue_max;
+			ad->ckmin_r = ck.red_min;
+			ad->ckmin_g = ck.green_min;
+			ad->ckmin_b = ck.blue_min;
+		}
+		break;
+#ifdef CONFIG_PPC_MPC512x
+	case MFB_SET_GAMMA: {
+		struct fsl_diu_data *data = mfbi->parent;
+
+		if (copy_from_user(data->gamma, buf, sizeof(data->gamma)))
+			return -EFAULT;
+		setbits32(&data->diu_reg->gamma, 0); /* Force table reload */
+		break;
+	}
+	case MFB_GET_GAMMA: {
+		struct fsl_diu_data *data = mfbi->parent;
+
+		if (copy_to_user(buf, data->gamma, sizeof(data->gamma)))
+			return -EFAULT;
+		break;
+	}
+#endif
+	default:
+		dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static inline void fsl_diu_enable_interrupts(struct fsl_diu_data *data)
+{
+	u32 int_mask = INT_UNDRUN; /* enable underrun detection */
+
+	if (IS_ENABLED(CONFIG_NOT_COHERENT_CACHE))
+		int_mask |= INT_VSYNC; /* enable vertical sync */
+
+	clrbits32(&data->diu_reg->int_mask, int_mask);
+}
+
+/* turn on fb if count == 1
+ */
+static int fsl_diu_open(struct fb_info *info, int user)
+{
+	struct mfb_info *mfbi = info->par;
+	int res = 0;
+
+	/* free boot splash memory on first /dev/fb0 open */
+	if ((mfbi->index == PLANE0) && diu_ops.release_bootmem)
+		diu_ops.release_bootmem();
+
+	spin_lock(&diu_lock);
+	mfbi->count++;
+	if (mfbi->count == 1) {
+		fsl_diu_check_var(&info->var, info);
+		res = fsl_diu_set_par(info);
+		if (res < 0)
+			mfbi->count--;
+		else {
+			fsl_diu_enable_interrupts(mfbi->parent);
+			fsl_diu_enable_panel(info);
+		}
+	}
+
+	spin_unlock(&diu_lock);
+	return res;
+}
+
+/* turn off fb if count == 0
+ */
+static int fsl_diu_release(struct fb_info *info, int user)
+{
+	struct mfb_info *mfbi = info->par;
+	int res = 0;
+
+	spin_lock(&diu_lock);
+	mfbi->count--;
+	if (mfbi->count == 0) {
+		struct fsl_diu_data *data = mfbi->parent;
+		bool disable = true;
+		int i;
+
+		/* Disable interrupts only if all AOIs are closed */
+		for (i = 0; i < NUM_AOIS; i++) {
+			struct mfb_info *mi = data->fsl_diu_info[i].par;
+
+			if (mi->count)
+				disable = false;
+		}
+		if (disable)
+			out_be32(&data->diu_reg->int_mask, 0xffffffff);
+		fsl_diu_disable_panel(info);
+	}
+
+	spin_unlock(&diu_lock);
+	return res;
+}
+
+static struct fb_ops fsl_diu_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = fsl_diu_check_var,
+	.fb_set_par = fsl_diu_set_par,
+	.fb_setcolreg = fsl_diu_setcolreg,
+	.fb_pan_display = fsl_diu_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_ioctl = fsl_diu_ioctl,
+	.fb_open = fsl_diu_open,
+	.fb_release = fsl_diu_release,
+	.fb_cursor = fsl_diu_cursor,
+};
+
+static int install_fb(struct fb_info *info)
+{
+	int rc;
+	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
+	const char *aoi_mode, *init_aoi_mode = "320x240";
+	struct fb_videomode *db = fsl_diu_mode_db;
+	unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
+	int has_default_mode = 1;
+
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->fbops = &fsl_diu_ops;
+	info->flags = FBINFO_DEFAULT | FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK |
+		FBINFO_READS_FAST;
+	info->pseudo_palette = mfbi->pseudo_palette;
+
+	rc = fb_alloc_cmap(&info->cmap, 16, 0);
+	if (rc)
+		return rc;
+
+	if (mfbi->index == PLANE0) {
+		if (data->has_edid) {
+			/* Now build modedb from EDID */
+			fb_edid_to_monspecs(data->edid_data, &info->monspecs);
+			fb_videomode_to_modelist(info->monspecs.modedb,
+						 info->monspecs.modedb_len,
+						 &info->modelist);
+			db = info->monspecs.modedb;
+			dbsize = info->monspecs.modedb_len;
+		}
+		aoi_mode = fb_mode;
+	} else {
+		aoi_mode = init_aoi_mode;
+	}
+	rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, NULL,
+			  default_bpp);
+	if (!rc) {
+		/*
+		 * For plane 0 we continue and look into
+		 * driver's internal modedb.
+		 */
+		if ((mfbi->index == PLANE0) && data->has_edid)
+			has_default_mode = 0;
+		else
+			return -EINVAL;
+	}
+
+	if (!has_default_mode) {
+		rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
+			ARRAY_SIZE(fsl_diu_mode_db), NULL, default_bpp);
+		if (rc)
+			has_default_mode = 1;
+	}
+
+	/* Still not found, use preferred mode from database if any */
+	if (!has_default_mode && info->monspecs.modedb) {
+		struct fb_monspecs *specs = &info->monspecs;
+		struct fb_videomode *modedb = &specs->modedb[0];
+
+		/*
+		 * Get preferred timing. If not found,
+		 * first mode in database will be used.
+		 */
+		if (specs->misc & FB_MISC_1ST_DETAIL) {
+			int i;
+
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = &specs->modedb[i];
+					break;
+				}
+			}
+		}
+
+		info->var.bits_per_pixel = default_bpp;
+		fb_videomode_to_var(&info->var, modedb);
+	}
+
+	if (fsl_diu_check_var(&info->var, info)) {
+		dev_err(info->dev, "fsl_diu_check_var failed\n");
+		unmap_video_memory(info);
+		fb_dealloc_cmap(&info->cmap);
+		return -EINVAL;
+	}
+
+	if (register_framebuffer(info) < 0) {
+		dev_err(info->dev, "register_framebuffer failed\n");
+		unmap_video_memory(info);
+		fb_dealloc_cmap(&info->cmap);
+		return -EINVAL;
+	}
+
+	mfbi->registered = 1;
+	dev_info(info->dev, "%s registered successfully\n", mfbi->id);
+
+	return 0;
+}
+
+static void uninstall_fb(struct fb_info *info)
+{
+	struct mfb_info *mfbi = info->par;
+
+	if (!mfbi->registered)
+		return;
+
+	unregister_framebuffer(info);
+	unmap_video_memory(info);
+	if (&info->cmap)
+		fb_dealloc_cmap(&info->cmap);
+
+	mfbi->registered = 0;
+}
+
+static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
+{
+	struct diu __iomem *hw = dev_id;
+	uint32_t status = in_be32(&hw->int_status);
+
+	if (status) {
+		/* This is the workaround for underrun */
+		if (status & INT_UNDRUN) {
+			out_be32(&hw->diu_mode, 0);
+			udelay(1);
+			out_be32(&hw->diu_mode, 1);
+		}
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		else if (status & INT_VSYNC) {
+			unsigned int i;
+
+			for (i = 0; i < coherence_data_size;
+				i += d_cache_line_size)
+				__asm__ __volatile__ (
+					"dcbz 0, %[input]"
+				::[input]"r"(&coherence_data[i]));
+		}
+#endif
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks. Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
+{
+	struct fsl_diu_data *data;
+
+	data = dev_get_drvdata(&ofdev->dev);
+	disable_lcdc(data->fsl_diu_info);
+
+	return 0;
+}
+
+static int fsl_diu_resume(struct platform_device *ofdev)
+{
+	struct fsl_diu_data *data;
+
+	data = dev_get_drvdata(&ofdev->dev);
+	enable_lcdc(data->fsl_diu_info);
+
+	return 0;
+}
+
+#else
+#define fsl_diu_suspend NULL
+#define fsl_diu_resume NULL
+#endif				/* CONFIG_PM */
+
+static ssize_t store_monitor(struct device *device,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	enum fsl_diu_monitor_port old_monitor_port;
+	struct fsl_diu_data *data =
+		container_of(attr, struct fsl_diu_data, dev_attr);
+
+	old_monitor_port = data->monitor_port;
+	data->monitor_port = fsl_diu_name_to_port(buf);
+
+	if (old_monitor_port != data->monitor_port) {
+		/* All AOIs need adjust pixel format
+		 * fsl_diu_set_par only change the pixsel format here
+		 * unlikely to fail. */
+		unsigned int i;
+
+		for (i=0; i < NUM_AOIS; i++)
+			fsl_diu_set_par(&data->fsl_diu_info[i]);
+	}
+	return count;
+}
+
+static ssize_t show_monitor(struct device *device,
+	struct device_attribute *attr, char *buf)
+{
+	struct fsl_diu_data *data =
+		container_of(attr, struct fsl_diu_data, dev_attr);
+
+	switch (data->monitor_port) {
+	case FSL_DIU_PORT_DVI:
+		return sprintf(buf, "DVI\n");
+	case FSL_DIU_PORT_LVDS:
+		return sprintf(buf, "Single-link LVDS\n");
+	case FSL_DIU_PORT_DLVDS:
+		return sprintf(buf, "Dual-link LVDS\n");
+	}
+
+	return 0;
+}
+
+static int fsl_diu_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct mfb_info *mfbi;
+	struct fsl_diu_data *data;
+	dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
+	const void *prop;
+	unsigned int i;
+	int ret;
+
+	data = dmam_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
+				   &dma_addr, GFP_DMA | __GFP_ZERO);
+	if (!data)
+		return -ENOMEM;
+	data->dma_addr = dma_addr;
+
+	/*
+	 * dma_alloc_coherent() uses a page allocator, so the address is
+	 * always page-aligned.  We need the memory to be 32-byte aligned,
+	 * so that's good.  However, if one day the allocator changes, we
+	 * need to catch that.  It's not worth the effort to handle unaligned
+	 * alloctions now because it's highly unlikely to ever be a problem.
+	 */
+	if ((unsigned long)data & 31) {
+		dev_err(&pdev->dev, "misaligned allocation");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	spin_lock_init(&data->reg_lock);
+
+	for (i = 0; i < NUM_AOIS; i++) {
+		struct fb_info *info = &data->fsl_diu_info[i];
+
+		info->device = &pdev->dev;
+		info->par = &data->mfb[i];
+
+		/*
+		 * We store the physical address of the AD in the reserved
+		 * 'paddr' field of the AD itself.
+		 */
+		data->ad[i].paddr = DMA_ADDR(data, ad[i]);
+
+		info->fix.smem_start = 0;
+
+		/* Initialize the AOI data structure */
+		mfbi = info->par;
+		memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
+		mfbi->parent = data;
+		mfbi->ad = &data->ad[i];
+	}
+
+	/* Get the EDID data from the device tree, if present */
+	prop = of_get_property(np, "edid", &ret);
+	if (prop && ret == EDID_LENGTH) {
+		memcpy(data->edid_data, prop, EDID_LENGTH);
+		data->has_edid = true;
+	}
+
+	data->diu_reg = of_iomap(np, 0);
+	if (!data->diu_reg) {
+		dev_err(&pdev->dev, "cannot map DIU registers\n");
+		ret = -EFAULT;
+		goto error;
+	}
+
+	/* Get the IRQ of the DIU */
+	data->irq = irq_of_parse_and_map(np, 0);
+
+	if (!data->irq) {
+		dev_err(&pdev->dev, "could not get DIU IRQ\n");
+		ret = -EINVAL;
+		goto error;
+	}
+	data->monitor_port = monitor_port;
+
+	/* Initialize the dummy Area Descriptor */
+	data->dummy_ad.addr = cpu_to_le32(DMA_ADDR(data, dummy_aoi));
+	data->dummy_ad.pix_fmt = 0x88882317;
+	data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
+	data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) |  2);
+	data->dummy_ad.offset_xyi = 0;
+	data->dummy_ad.offset_xyd = 0;
+	data->dummy_ad.next_ad = 0;
+	data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
+
+	/*
+	 * Let DIU continue to display splash screen if it was pre-initialized
+	 * by the bootloader; otherwise, clear the display.
+	 */
+	if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0)
+		out_be32(&data->diu_reg->desc[0], 0);
+
+	out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
+	out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
+
+	/*
+	 * Older versions of U-Boot leave interrupts enabled, so disable
+	 * all of them and clear the status register.
+	 */
+	out_be32(&data->diu_reg->int_mask, 0xffffffff);
+	in_be32(&data->diu_reg->int_status);
+
+	ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
+			  data->diu_reg);
+	if (ret) {
+		dev_err(&pdev->dev, "could not claim irq\n");
+		goto error;
+	}
+
+	for (i = 0; i < NUM_AOIS; i++) {
+		ret = install_fb(&data->fsl_diu_info[i]);
+		if (ret) {
+			dev_err(&pdev->dev, "could not register fb %d\n", i);
+			free_irq(data->irq, data->diu_reg);
+			goto error;
+		}
+	}
+
+	sysfs_attr_init(&data->dev_attr.attr);
+	data->dev_attr.attr.name = "monitor";
+	data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
+	data->dev_attr.show = show_monitor;
+	data->dev_attr.store = store_monitor;
+	ret = device_create_file(&pdev->dev, &data->dev_attr);
+	if (ret) {
+		dev_err(&pdev->dev, "could not create sysfs file %s\n",
+			data->dev_attr.attr.name);
+	}
+
+	dev_set_drvdata(&pdev->dev, data);
+	return 0;
+
+error:
+	for (i = 0; i < NUM_AOIS; i++)
+		uninstall_fb(&data->fsl_diu_info[i]);
+
+	iounmap(data->diu_reg);
+
+	return ret;
+}
+
+static int fsl_diu_remove(struct platform_device *pdev)
+{
+	struct fsl_diu_data *data;
+	int i;
+
+	data = dev_get_drvdata(&pdev->dev);
+	disable_lcdc(&data->fsl_diu_info[0]);
+
+	free_irq(data->irq, data->diu_reg);
+
+	for (i = 0; i < NUM_AOIS; i++)
+		uninstall_fb(&data->fsl_diu_info[i]);
+
+	iounmap(data->diu_reg);
+
+	return 0;
+}
+
+#ifndef MODULE
+static int __init fsl_diu_setup(char *options)
+{
+	char *opt;
+	unsigned long val;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+		if (!strncmp(opt, "monitor=", 8)) {
+			monitor_port = fsl_diu_name_to_port(opt + 8);
+		} else if (!strncmp(opt, "bpp=", 4)) {
+			if (!kstrtoul(opt + 4, 10, &val))
+				default_bpp = val;
+		} else
+			fb_mode = opt;
+	}
+
+	return 0;
+}
+#endif
+
+static struct of_device_id fsl_diu_match[] = {
+#ifdef CONFIG_PPC_MPC512x
+	{
+		.compatible = "fsl,mpc5121-diu",
+	},
+#endif
+	{
+		.compatible = "fsl,diu",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, fsl_diu_match);
+
+static struct platform_driver fsl_diu_driver = {
+	.driver = {
+		.name = "fsl-diu-fb",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_diu_match,
+	},
+	.probe  	= fsl_diu_probe,
+	.remove 	= fsl_diu_remove,
+	.suspend	= fsl_diu_suspend,
+	.resume		= fsl_diu_resume,
+};
+
+static int __init fsl_diu_init(void)
+{
+#ifdef CONFIG_NOT_COHERENT_CACHE
+	struct device_node *np;
+	const u32 *prop;
+#endif
+	int ret;
+#ifndef MODULE
+	char *option;
+
+	/*
+	 * For kernel boot options (in 'video=xxxfb:<options>' format)
+	 */
+	if (fb_get_options("fslfb", &option))
+		return -ENODEV;
+	fsl_diu_setup(option);
+#else
+	monitor_port = fsl_diu_name_to_port(monitor_string);
+#endif
+	pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n");
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+	np = of_find_node_by_type(NULL, "cpu");
+	if (!np) {
+		pr_err("fsl-diu-fb: can't find 'cpu' device node\n");
+		return -ENODEV;
+	}
+
+	prop = of_get_property(np, "d-cache-size", NULL);
+	if (prop == NULL) {
+		pr_err("fsl-diu-fb: missing 'd-cache-size' property' "
+		       "in 'cpu' node\n");
+		of_node_put(np);
+		return -ENODEV;
+	}
+
+	/*
+	 * Freescale PLRU requires 13/8 times the cache size to do a proper
+	 * displacement flush
+	 */
+	coherence_data_size = be32_to_cpup(prop) * 13;
+	coherence_data_size /= 8;
+
+	pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n",
+		 coherence_data_size);
+
+	prop = of_get_property(np, "d-cache-line-size", NULL);
+	if (prop == NULL) {
+		pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
+		       "in 'cpu' node\n");
+		of_node_put(np);
+		return -ENODEV;
+	}
+	d_cache_line_size = be32_to_cpup(prop);
+
+	pr_debug("fsl-diu-fb: cache lines size is %u bytes\n",
+		 d_cache_line_size);
+
+	of_node_put(np);
+	coherence_data = vmalloc(coherence_data_size);
+	if (!coherence_data) {
+		pr_err("fsl-diu-fb: could not allocate coherence data "
+		       "(size=%zu)\n", coherence_data_size);
+		return -ENOMEM;
+	}
+
+#endif
+
+	ret = platform_driver_register(&fsl_diu_driver);
+	if (ret) {
+		pr_err("fsl-diu-fb: failed to register platform driver\n");
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		vfree(coherence_data);
+#endif
+	}
+	return ret;
+}
+
+static void __exit fsl_diu_exit(void)
+{
+	platform_driver_unregister(&fsl_diu_driver);
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+	vfree(coherence_data);
+#endif
+}
+
+module_init(fsl_diu_init);
+module_exit(fsl_diu_exit);
+
+MODULE_AUTHOR("York Sun <yorksun@freescale.com>");
+MODULE_DESCRIPTION("Freescale DIU framebuffer driver");
+MODULE_LICENSE("GPL");
+
+module_param_named(mode, fb_mode, charp, 0);
+MODULE_PARM_DESC(mode,
+	"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+module_param_named(bpp, default_bpp, ulong, 0);
+MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified in 'mode'");
+module_param_named(monitor, monitor_string, charp, 0);
+MODULE_PARM_DESC(monitor, "Specify the monitor port "
+	"(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform");
+
diff --git a/drivers/video/fbdev/g364fb.c b/drivers/video/fbdev/g364fb.c
new file mode 100644
index 000000000000..223896cc5f7d
--- /dev/null
+++ b/drivers/video/fbdev/g364fb.c
@@ -0,0 +1,255 @@
+/* $Id: g364fb.c,v 1.3 1998/08/28 22:43:00 tsbogend Exp $
+ *
+ * linux/drivers/video/g364fb.c -- Mips Magnum frame buffer device
+ *
+ * (C) 1998 Thomas Bogendoerfer
+ *
+ *  This driver is based on tgafb.c
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven 
+ *	Copyright (C) 1995  Jay Estabrook
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/jazz.h>
+
+/* 
+ * Various defines for the G364
+ */
+#define G364_MEM_BASE   0xe4400000
+#define G364_PORT_BASE  0xe4000000
+#define ID_REG 		0xe4000000	/* Read only */
+#define BOOT_REG 	0xe4080000
+#define TIMING_REG 	0xe4080108	/* to 0x080170 - DON'T TOUCH! */
+#define DISPLAY_REG 	0xe4080118
+#define VDISPLAY_REG 	0xe4080150
+#define MASK_REG 	0xe4080200
+#define CTLA_REG 	0xe4080300
+#define CURS_TOGGLE 	0x800000
+#define BIT_PER_PIX	0x700000	/* bits 22 to 20 of Control A */
+#define DELAY_SAMPLE    0x080000
+#define PORT_INTER	0x040000
+#define PIX_PIPE_DEL	0x030000	/* bits 17 and 16 of Control A */
+#define PIX_PIPE_DEL2	0x008000	/* same as above - don't ask me why */
+#define TR_CYCLE_TOG	0x004000
+#define VRAM_ADR_INC	0x003000	/* bits 13 and 12 of Control A */
+#define BLANK_OFF	0x000800
+#define FORCE_BLANK	0x000400
+#define BLK_FUN_SWTCH	0x000200
+#define BLANK_IO	0x000100
+#define BLANK_LEVEL	0x000080
+#define A_VID_FORM	0x000040
+#define D_SYNC_FORM	0x000020
+#define FRAME_FLY_PAT	0x000010
+#define OP_MODE		0x000008
+#define INTL_STAND	0x000004
+#define SCRN_FORM	0x000002
+#define ENABLE_VTG	0x000001
+#define TOP_REG 	0xe4080400
+#define CURS_PAL_REG 	0xe4080508	/* to 0x080518 */
+#define CHKSUM_REG 	0xe4080600	/* to 0x080610 - unused */
+#define CURS_POS_REG 	0xe4080638
+#define CLR_PAL_REG 	0xe4080800	/* to 0x080ff8 */
+#define CURS_PAT_REG 	0xe4081000	/* to 0x081ff8 */
+#define MON_ID_REG 	0xe4100000	/* unused */
+#define RESET_REG 	0xe4180000	/* Write only */
+
+static struct fb_info fb_info;
+
+static struct fb_fix_screeninfo fb_fix __initdata = {
+	.id 		= "G364 8plane",
+	.smem_start 	= 0x40000000,	/* physical address */
+	.type 		= FB_TYPE_PACKED_PIXELS,
+	.visual 	= FB_VISUAL_PSEUDOCOLOR,
+	.ypanstep 	= 1,
+	.accel 		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo fb_var __initdata = {
+	.bits_per_pixel = 8,
+	.red 		= { 0, 8, 0 },
+      	.green 		= { 0, 8, 0 },
+      	.blue		= { 0, 8, 0 },
+      	.activate	= FB_ACTIVATE_NOW,
+      	.height		= -1,
+      	.width		= -1,
+      	.pixclock	= 39722,
+      	.left_margin	= 40,
+      	.right_margin	= 24,
+      	.upper_margin	= 32,
+      	.lower_margin	= 11,
+      	.hsync_len 	= 96,
+      	.vsync_len 	= 2,
+      	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+/*
+ *  Interface used by the world
+ */
+int g364fb_init(void);
+
+static int g364fb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info);
+static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
+			    u_int blue, u_int transp,
+			    struct fb_info *info);
+static int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int g364fb_blank(int blank, struct fb_info *info);
+
+static struct fb_ops g364fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= g364fb_setcolreg,
+	.fb_pan_display	= g364fb_pan_display,
+	.fb_blank	= g364fb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_cursor	= g364fb_cursor,
+};
+
+int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	
+	switch (cursor->enable) {
+	case CM_ERASE:
+		*(unsigned int *) CTLA_REG |= CURS_TOGGLE;
+		break;
+
+	case CM_MOVE:
+	case CM_DRAW:
+		*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
+		*(unsigned int *) CURS_POS_REG =
+		    ((x * fontwidth(p)) << 12) | ((y * fontheight(p)) -
+						  info->var.yoffset);
+		break;
+	}
+	return 0;
+}
+
+/*
+ *  Pan or Wrap the Display
+ *
+ *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int g364fb_pan_display(struct fb_var_screeninfo *var, 
+			      struct fb_info *info)
+{
+	if (var->xoffset ||
+	    var->yoffset + info->var.yres > info->var.yres_virtual)
+		return -EINVAL;
+
+	*(unsigned int *) TOP_REG = var->yoffset * info->var.xres;
+	return 0;
+}
+
+/*
+ *  Blank the display.
+ */
+static int g364fb_blank(int blank, struct fb_info *info)
+{
+	if (blank)
+		*(unsigned int *) CTLA_REG |= FORCE_BLANK;
+	else
+		*(unsigned int *) CTLA_REG &= ~FORCE_BLANK;
+	return 0;
+}
+
+/*
+ *  Set a single color register. Return != 0 for invalid regno.
+ */
+static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
+			    u_int blue, u_int transp, struct fb_info *info)
+{
+	volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
+
+	if (regno > 255)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	ptr[regno << 1] = (red << 16) | (green << 8) | blue;
+
+	return 0;
+}
+
+/*
+ *  Initialisation
+ */
+int __init g364fb_init(void)
+{
+	volatile unsigned int *pal_ptr =
+	    (volatile unsigned int *) CLR_PAL_REG;
+	volatile unsigned int *curs_pal_ptr =
+	    (volatile unsigned int *) CURS_PAL_REG;
+	int mem, i, j;
+
+	if (fb_get_options("g364fb", NULL))
+		return -ENODEV;
+
+	/* TBD: G364 detection */
+
+	/* get the resolution set by ARC console */
+	*(volatile unsigned int *) CTLA_REG &= ~ENABLE_VTG;
+	fb_var.xres =
+	    (*((volatile unsigned int *) DISPLAY_REG) & 0x00ffffff) * 4;
+	fb_var.yres =
+	    (*((volatile unsigned int *) VDISPLAY_REG) & 0x00ffffff) / 2;
+	*(volatile unsigned int *) CTLA_REG |= ENABLE_VTG;
+
+	/* setup cursor */
+	curs_pal_ptr[0] |= 0x00ffffff;
+	curs_pal_ptr[2] |= 0x00ffffff;
+	curs_pal_ptr[4] |= 0x00ffffff;
+
+	/*
+	 * first set the whole cursor to transparent
+	 */
+	for (i = 0; i < 512; i++)
+		*(unsigned short *) (CURS_PAT_REG + i * 8) = 0;
+
+	/*
+	 * switch the last two lines to cursor palette 3
+	 * we assume here, that FONTSIZE_X is 8
+	 */
+	*(unsigned short *) (CURS_PAT_REG + 14 * 64) = 0xffff;
+	*(unsigned short *) (CURS_PAT_REG + 15 * 64) = 0xffff;
+	fb_var.xres_virtual = fbvar.xres;
+	fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
+	fb_fix.smem_start = 0x40000000;	/* physical address */
+	/* get size of video memory; this is special for the JAZZ hardware */
+	mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3;
+	fb_fix.smem_len = (1 << (mem * 2)) * 512 * 1024;
+	fb_var.yres_virtual = fb_fix.smem_len / fb_var.xres;
+
+	fb_info.fbops = &g364fb_ops;
+	fb_info.screen_base = (char *) G364_MEM_BASE;	/* virtual kernel address */
+	fb_info.var = fb_var;
+	fb_info.fix = fb_fix;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	fb_alloc_cmap(&fb_info.cmap, 255, 0);
+
+	if (register_framebuffer(&fb_info) < 0)
+		return -EINVAL;
+	return 0;
+}
+
+module_init(g364fb_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/gbefb.c b/drivers/video/fbdev/gbefb.c
new file mode 100644
index 000000000000..3ec65a878ac8
--- /dev/null
+++ b/drivers/video/fbdev/gbefb.c
@@ -0,0 +1,1309 @@
+/*
+ *  SGI GBE frame buffer driver
+ *
+ *  Copyright (C) 1999 Silicon Graphics, Inc. - Jeffrey Newquist
+ *  Copyright (C) 2002 Vivien Chappelier <vivien.chappelier@linux-mips.org>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#ifdef CONFIG_X86
+#include <asm/mtrr.h>
+#endif
+#ifdef CONFIG_MIPS
+#include <asm/addrspace.h>
+#endif
+#include <asm/byteorder.h>
+#include <asm/tlbflush.h>
+
+#include <video/gbe.h>
+
+static struct sgi_gbe *gbe;
+
+struct gbefb_par {
+	struct fb_var_screeninfo var;
+	struct gbe_timing_info timing;
+	int valid;
+};
+
+#ifdef CONFIG_SGI_IP32
+#define GBE_BASE	0x16000000 /* SGI O2 */
+#endif
+
+/* macro for fastest write-though access to the framebuffer */
+#ifdef CONFIG_MIPS
+#ifdef CONFIG_CPU_R10000
+#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_UNCACHED_ACCELERATED)
+#else
+#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA)
+#endif
+#endif
+#ifdef CONFIG_X86
+#define pgprot_fb(_prot) ((_prot) | _PAGE_PCD)
+#endif
+
+/*
+ *  RAM we reserve for the frame buffer. This defines the maximum screen
+ *  size
+ */
+#if CONFIG_FB_GBE_MEM > 8
+#error GBE Framebuffer cannot use more than 8MB of memory
+#endif
+
+#define TILE_SHIFT 16
+#define TILE_SIZE (1 << TILE_SHIFT)
+#define TILE_MASK (TILE_SIZE - 1)
+
+static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
+static void *gbe_mem;
+static dma_addr_t gbe_dma_addr;
+static unsigned long gbe_mem_phys;
+
+static struct {
+	uint16_t *cpu;
+	dma_addr_t dma;
+} gbe_tiles;
+
+static int gbe_revision;
+
+static int ypan, ywrap;
+
+static uint32_t pseudo_palette[16];
+static uint32_t gbe_cmap[256];
+static int gbe_turned_on; /* 0 turned off, 1 turned on */
+
+static char *mode_option = NULL;
+
+/* default CRT mode */
+static struct fb_var_screeninfo default_var_CRT = {
+	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+	.xres		= 640,
+	.yres		= 480,
+	.xres_virtual	= 640,
+	.yres_virtual	= 480,
+	.xoffset	= 0,
+	.yoffset	= 0,
+	.bits_per_pixel	= 8,
+	.grayscale	= 0,
+	.red		= { 0, 8, 0 },
+	.green		= { 0, 8, 0 },
+	.blue		= { 0, 8, 0 },
+	.transp		= { 0, 0, 0 },
+	.nonstd		= 0,
+	.activate	= 0,
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= 0,
+	.pixclock	= 39722,	/* picoseconds */
+	.left_margin	= 48,
+	.right_margin	= 16,
+	.upper_margin	= 33,
+	.lower_margin	= 10,
+	.hsync_len	= 96,
+	.vsync_len	= 2,
+	.sync		= 0,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+/* default LCD mode */
+static struct fb_var_screeninfo default_var_LCD = {
+	/* 1600x1024, 8 bpp */
+	.xres		= 1600,
+	.yres		= 1024,
+	.xres_virtual	= 1600,
+	.yres_virtual	= 1024,
+	.xoffset	= 0,
+	.yoffset	= 0,
+	.bits_per_pixel	= 8,
+	.grayscale	= 0,
+	.red		= { 0, 8, 0 },
+	.green		= { 0, 8, 0 },
+	.blue		= { 0, 8, 0 },
+	.transp		= { 0, 0, 0 },
+	.nonstd		= 0,
+	.activate	= 0,
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= 0,
+	.pixclock	= 9353,
+	.left_margin	= 20,
+	.right_margin	= 30,
+	.upper_margin	= 37,
+	.lower_margin	= 3,
+	.hsync_len	= 20,
+	.vsync_len	= 3,
+	.sync		= 0,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
+/* default modedb mode */
+/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
+static struct fb_videomode default_mode_CRT = {
+	.refresh	= 60,
+	.xres		= 640,
+	.yres		= 480,
+	.pixclock	= 39722,
+	.left_margin	= 48,
+	.right_margin	= 16,
+	.upper_margin	= 33,
+	.lower_margin	= 10,
+	.hsync_len	= 96,
+	.vsync_len	= 2,
+	.sync		= 0,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+/* 1600x1024 SGI flatpanel 1600sw */
+static struct fb_videomode default_mode_LCD = {
+	/* 1600x1024, 8 bpp */
+	.xres		= 1600,
+	.yres		= 1024,
+	.pixclock	= 9353,
+	.left_margin	= 20,
+	.right_margin	= 30,
+	.upper_margin	= 37,
+	.lower_margin	= 3,
+	.hsync_len	= 20,
+	.vsync_len	= 3,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_videomode *default_mode = &default_mode_CRT;
+static struct fb_var_screeninfo *default_var = &default_var_CRT;
+
+static int flat_panel_enabled = 0;
+
+static void gbe_reset(void)
+{
+	/* Turn on dotclock PLL */
+	gbe->ctrlstat = 0x300aa000;
+}
+
+
+/*
+ * Function:	gbe_turn_off
+ * Parameters:	(None)
+ * Description:	This should turn off the monitor and gbe.  This is used
+ *              when switching between the serial console and the graphics
+ *              console.
+ */
+
+static void gbe_turn_off(void)
+{
+	int i;
+	unsigned int val, x, y, vpixen_off;
+
+	gbe_turned_on = 0;
+
+	/* check if pixel counter is on */
+	val = gbe->vt_xy;
+	if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1)
+		return;
+
+	/* turn off DMA */
+	val = gbe->ovr_control;
+	SET_GBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, val, 0);
+	gbe->ovr_control = val;
+	udelay(1000);
+	val = gbe->frm_control;
+	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0);
+	gbe->frm_control = val;
+	udelay(1000);
+	val = gbe->did_control;
+	SET_GBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, val, 0);
+	gbe->did_control = val;
+	udelay(1000);
+
+	/* We have to wait through two vertical retrace periods before
+	 * the pixel DMA is turned off for sure. */
+	for (i = 0; i < 10000; i++) {
+		val = gbe->frm_inhwctrl;
+		if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val)) {
+			udelay(10);
+		} else {
+			val = gbe->ovr_inhwctrl;
+			if (GET_GBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, val)) {
+				udelay(10);
+			} else {
+				val = gbe->did_inhwctrl;
+				if (GET_GBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, val)) {
+					udelay(10);
+				} else
+					break;
+			}
+		}
+	}
+	if (i == 10000)
+		printk(KERN_ERR "gbefb: turn off DMA timed out\n");
+
+	/* wait for vpixen_off */
+	val = gbe->vt_vpixen;
+	vpixen_off = GET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val);
+
+	for (i = 0; i < 100000; i++) {
+		val = gbe->vt_xy;
+		x = GET_GBE_FIELD(VT_XY, X, val);
+		y = GET_GBE_FIELD(VT_XY, Y, val);
+		if (y < vpixen_off)
+			break;
+		udelay(1);
+	}
+	if (i == 100000)
+		printk(KERN_ERR
+		       "gbefb: wait for vpixen_off timed out\n");
+	for (i = 0; i < 10000; i++) {
+		val = gbe->vt_xy;
+		x = GET_GBE_FIELD(VT_XY, X, val);
+		y = GET_GBE_FIELD(VT_XY, Y, val);
+		if (y > vpixen_off)
+			break;
+		udelay(1);
+	}
+	if (i == 10000)
+		printk(KERN_ERR "gbefb: wait for vpixen_off timed out\n");
+
+	/* turn off pixel counter */
+	val = 0;
+	SET_GBE_FIELD(VT_XY, FREEZE, val, 1);
+	gbe->vt_xy = val;
+	udelay(10000);
+	for (i = 0; i < 10000; i++) {
+		val = gbe->vt_xy;
+		if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1)
+			udelay(10);
+		else
+			break;
+	}
+	if (i == 10000)
+		printk(KERN_ERR "gbefb: turn off pixel clock timed out\n");
+
+	/* turn off dot clock */
+	val = gbe->dotclock;
+	SET_GBE_FIELD(DOTCLK, RUN, val, 0);
+	gbe->dotclock = val;
+	udelay(10000);
+	for (i = 0; i < 10000; i++) {
+		val = gbe->dotclock;
+		if (GET_GBE_FIELD(DOTCLK, RUN, val))
+			udelay(10);
+		else
+			break;
+	}
+	if (i == 10000)
+		printk(KERN_ERR "gbefb: turn off dotclock timed out\n");
+
+	/* reset the frame DMA FIFO */
+	val = gbe->frm_size_tile;
+	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 1);
+	gbe->frm_size_tile = val;
+	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 0);
+	gbe->frm_size_tile = val;
+}
+
+static void gbe_turn_on(void)
+{
+	unsigned int val, i;
+
+	/*
+	 * Check if pixel counter is off, for unknown reason this
+	 * code hangs Visual Workstations
+	 */
+	if (gbe_revision < 2) {
+		val = gbe->vt_xy;
+		if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 0)
+			return;
+	}
+
+	/* turn on dot clock */
+	val = gbe->dotclock;
+	SET_GBE_FIELD(DOTCLK, RUN, val, 1);
+	gbe->dotclock = val;
+	udelay(10000);
+	for (i = 0; i < 10000; i++) {
+		val = gbe->dotclock;
+		if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1)
+			udelay(10);
+		else
+			break;
+	}
+	if (i == 10000)
+		printk(KERN_ERR "gbefb: turn on dotclock timed out\n");
+
+	/* turn on pixel counter */
+	val = 0;
+	SET_GBE_FIELD(VT_XY, FREEZE, val, 0);
+	gbe->vt_xy = val;
+	udelay(10000);
+	for (i = 0; i < 10000; i++) {
+		val = gbe->vt_xy;
+		if (GET_GBE_FIELD(VT_XY, FREEZE, val))
+			udelay(10);
+		else
+			break;
+	}
+	if (i == 10000)
+		printk(KERN_ERR "gbefb: turn on pixel clock timed out\n");
+
+	/* turn on DMA */
+	val = gbe->frm_control;
+	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 1);
+	gbe->frm_control = val;
+	udelay(1000);
+	for (i = 0; i < 10000; i++) {
+		val = gbe->frm_inhwctrl;
+		if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val) != 1)
+			udelay(10);
+		else
+			break;
+	}
+	if (i == 10000)
+		printk(KERN_ERR "gbefb: turn on DMA timed out\n");
+
+	gbe_turned_on = 1;
+}
+
+static void gbe_loadcmap(void)
+{
+	int i, j;
+
+	for (i = 0; i < 256; i++) {
+		for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
+			udelay(10);
+		if (j == 1000)
+			printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
+
+		gbe->cmap[i] = gbe_cmap[i];
+	}
+}
+
+/*
+ *  Blank the display.
+ */
+static int gbefb_blank(int blank, struct fb_info *info)
+{
+	/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+	switch (blank) {
+	case FB_BLANK_UNBLANK:		/* unblank */
+		gbe_turn_on();
+		gbe_loadcmap();
+		break;
+
+	case FB_BLANK_NORMAL:		/* blank */
+		gbe_turn_off();
+		break;
+
+	default:
+		/* Nothing */
+		break;
+	}
+	return 0;
+}
+
+/*
+ *  Setup flatpanel related registers.
+ */
+static void gbefb_setup_flatpanel(struct gbe_timing_info *timing)
+{
+	int fp_wid, fp_hgt, fp_vbs, fp_vbe;
+	u32 outputVal = 0;
+
+	SET_GBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal,
+		(timing->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
+	SET_GBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal,
+		(timing->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
+	gbe->vt_flags = outputVal;
+
+	/* Turn on the flat panel */
+	fp_wid = 1600;
+	fp_hgt = 1024;
+	fp_vbs = 0;
+	fp_vbe = 1600;
+	timing->pll_m = 4;
+	timing->pll_n = 1;
+	timing->pll_p = 0;
+
+	outputVal = 0;
+	SET_GBE_FIELD(FP_DE, ON, outputVal, fp_vbs);
+	SET_GBE_FIELD(FP_DE, OFF, outputVal, fp_vbe);
+	gbe->fp_de = outputVal;
+	outputVal = 0;
+	SET_GBE_FIELD(FP_HDRV, OFF, outputVal, fp_wid);
+	gbe->fp_hdrv = outputVal;
+	outputVal = 0;
+	SET_GBE_FIELD(FP_VDRV, ON, outputVal, 1);
+	SET_GBE_FIELD(FP_VDRV, OFF, outputVal, fp_hgt + 1);
+	gbe->fp_vdrv = outputVal;
+}
+
+struct gbe_pll_info {
+	int clock_rate;
+	int fvco_min;
+	int fvco_max;
+};
+
+static struct gbe_pll_info gbe_pll_table[2] = {
+	{ 20, 80, 220 },
+	{ 27, 80, 220 },
+};
+
+static int compute_gbe_timing(struct fb_var_screeninfo *var,
+			      struct gbe_timing_info *timing)
+{
+	int pll_m, pll_n, pll_p, error, best_m, best_n, best_p, best_error;
+	int pixclock;
+	struct gbe_pll_info *gbe_pll;
+
+	if (gbe_revision < 2)
+		gbe_pll = &gbe_pll_table[0];
+	else
+		gbe_pll = &gbe_pll_table[1];
+
+	/* Determine valid resolution and timing
+	 * GBE crystal runs at 20Mhz or 27Mhz
+	 * pll_m, pll_n, pll_p define the following frequencies
+	 * fvco = pll_m * 20Mhz / pll_n
+	 * fout = fvco / (2**pll_p) */
+	best_error = 1000000000;
+	best_n = best_m = best_p = 0;
+	for (pll_p = 0; pll_p < 4; pll_p++)
+		for (pll_m = 1; pll_m < 256; pll_m++)
+			for (pll_n = 1; pll_n < 64; pll_n++) {
+				pixclock = (1000000 / gbe_pll->clock_rate) *
+						(pll_n << pll_p) / pll_m;
+
+				error = var->pixclock - pixclock;
+
+				if (error < 0)
+					error = -error;
+
+				if (error < best_error &&
+				    pll_m / pll_n >
+				    gbe_pll->fvco_min / gbe_pll->clock_rate &&
+ 				    pll_m / pll_n <
+				    gbe_pll->fvco_max / gbe_pll->clock_rate) {
+					best_error = error;
+					best_m = pll_m;
+					best_n = pll_n;
+					best_p = pll_p;
+				}
+			}
+
+	if (!best_n || !best_m)
+		return -EINVAL;	/* Resolution to high */
+
+	pixclock = (1000000 / gbe_pll->clock_rate) *
+		(best_n << best_p) / best_m;
+
+	/* set video timing information */
+	if (timing) {
+		timing->width = var->xres;
+		timing->height = var->yres;
+		timing->pll_m = best_m;
+		timing->pll_n = best_n;
+		timing->pll_p = best_p;
+		timing->cfreq = gbe_pll->clock_rate * 1000 * timing->pll_m /
+			(timing->pll_n << timing->pll_p);
+		timing->htotal = var->left_margin + var->xres +
+				var->right_margin + var->hsync_len;
+		timing->vtotal = var->upper_margin + var->yres +
+				var->lower_margin + var->vsync_len;
+		timing->fields_sec = 1000 * timing->cfreq / timing->htotal *
+				1000 / timing->vtotal;
+		timing->hblank_start = var->xres;
+		timing->vblank_start = var->yres;
+		timing->hblank_end = timing->htotal;
+		timing->hsync_start = var->xres + var->right_margin + 1;
+		timing->hsync_end = timing->hsync_start + var->hsync_len;
+		timing->vblank_end = timing->vtotal;
+		timing->vsync_start = var->yres + var->lower_margin + 1;
+		timing->vsync_end = timing->vsync_start + var->vsync_len;
+	}
+
+	return pixclock;
+}
+
+static void gbe_set_timing_info(struct gbe_timing_info *timing)
+{
+	int temp;
+	unsigned int val;
+
+	/* setup dot clock PLL */
+	val = 0;
+	SET_GBE_FIELD(DOTCLK, M, val, timing->pll_m - 1);
+	SET_GBE_FIELD(DOTCLK, N, val, timing->pll_n - 1);
+	SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p);
+	SET_GBE_FIELD(DOTCLK, RUN, val, 0);	/* do not start yet */
+	gbe->dotclock = val;
+	udelay(10000);
+
+	/* setup pixel counter */
+	val = 0;
+	SET_GBE_FIELD(VT_XYMAX, MAXX, val, timing->htotal);
+	SET_GBE_FIELD(VT_XYMAX, MAXY, val, timing->vtotal);
+	gbe->vt_xymax = val;
+
+	/* setup video timing signals */
+	val = 0;
+	SET_GBE_FIELD(VT_VSYNC, VSYNC_ON, val, timing->vsync_start);
+	SET_GBE_FIELD(VT_VSYNC, VSYNC_OFF, val, timing->vsync_end);
+	gbe->vt_vsync = val;
+	val = 0;
+	SET_GBE_FIELD(VT_HSYNC, HSYNC_ON, val, timing->hsync_start);
+	SET_GBE_FIELD(VT_HSYNC, HSYNC_OFF, val, timing->hsync_end);
+	gbe->vt_hsync = val;
+	val = 0;
+	SET_GBE_FIELD(VT_VBLANK, VBLANK_ON, val, timing->vblank_start);
+	SET_GBE_FIELD(VT_VBLANK, VBLANK_OFF, val, timing->vblank_end);
+	gbe->vt_vblank = val;
+	val = 0;
+	SET_GBE_FIELD(VT_HBLANK, HBLANK_ON, val,
+		      timing->hblank_start - 5);
+	SET_GBE_FIELD(VT_HBLANK, HBLANK_OFF, val,
+		      timing->hblank_end - 3);
+	gbe->vt_hblank = val;
+
+	/* setup internal timing signals */
+	val = 0;
+	SET_GBE_FIELD(VT_VCMAP, VCMAP_ON, val, timing->vblank_start);
+	SET_GBE_FIELD(VT_VCMAP, VCMAP_OFF, val, timing->vblank_end);
+	gbe->vt_vcmap = val;
+	val = 0;
+	SET_GBE_FIELD(VT_HCMAP, HCMAP_ON, val, timing->hblank_start);
+	SET_GBE_FIELD(VT_HCMAP, HCMAP_OFF, val, timing->hblank_end);
+	gbe->vt_hcmap = val;
+
+	val = 0;
+	temp = timing->vblank_start - timing->vblank_end - 1;
+	if (temp > 0)
+		temp = -temp;
+
+	if (flat_panel_enabled)
+		gbefb_setup_flatpanel(timing);
+
+	SET_GBE_FIELD(DID_START_XY, DID_STARTY, val, (u32) temp);
+	if (timing->hblank_end >= 20)
+		SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
+			      timing->hblank_end - 20);
+	else
+		SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
+			      timing->htotal - (20 - timing->hblank_end));
+	gbe->did_start_xy = val;
+
+	val = 0;
+	SET_GBE_FIELD(CRS_START_XY, CRS_STARTY, val, (u32) (temp + 1));
+	if (timing->hblank_end >= GBE_CRS_MAGIC)
+		SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
+			      timing->hblank_end - GBE_CRS_MAGIC);
+	else
+		SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
+			      timing->htotal - (GBE_CRS_MAGIC -
+						timing->hblank_end));
+	gbe->crs_start_xy = val;
+
+	val = 0;
+	SET_GBE_FIELD(VC_START_XY, VC_STARTY, val, (u32) temp);
+	SET_GBE_FIELD(VC_START_XY, VC_STARTX, val, timing->hblank_end - 4);
+	gbe->vc_start_xy = val;
+
+	val = 0;
+	temp = timing->hblank_end - GBE_PIXEN_MAGIC_ON;
+	if (temp < 0)
+		temp += timing->htotal;	/* allow blank to wrap around */
+
+	SET_GBE_FIELD(VT_HPIXEN, HPIXEN_ON, val, temp);
+	SET_GBE_FIELD(VT_HPIXEN, HPIXEN_OFF, val,
+		      ((temp + timing->width -
+			GBE_PIXEN_MAGIC_OFF) % timing->htotal));
+	gbe->vt_hpixen = val;
+
+	val = 0;
+	SET_GBE_FIELD(VT_VPIXEN, VPIXEN_ON, val, timing->vblank_end);
+	SET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val, timing->vblank_start);
+	gbe->vt_vpixen = val;
+
+	/* turn off sync on green */
+	val = 0;
+	SET_GBE_FIELD(VT_FLAGS, SYNC_LOW, val, 1);
+	gbe->vt_flags = val;
+}
+
+/*
+ *  Set the hardware according to 'par'.
+ */
+
+static int gbefb_set_par(struct fb_info *info)
+{
+	int i;
+	unsigned int val;
+	int wholeTilesX, partTilesX, maxPixelsPerTileX;
+	int height_pix;
+	int xpmax, ypmax;	/* Monitor resolution */
+	int bytesPerPixel;	/* Bytes per pixel */
+	struct gbefb_par *par = (struct gbefb_par *) info->par;
+
+	compute_gbe_timing(&info->var, &par->timing);
+
+	bytesPerPixel = info->var.bits_per_pixel / 8;
+	info->fix.line_length = info->var.xres_virtual * bytesPerPixel;
+	xpmax = par->timing.width;
+	ypmax = par->timing.height;
+
+	/* turn off GBE */
+	gbe_turn_off();
+
+	/* set timing info */
+	gbe_set_timing_info(&par->timing);
+
+	/* initialize DIDs */
+	val = 0;
+	switch (bytesPerPixel) {
+	case 1:
+		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8);
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 2:
+		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5);
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 4:
+		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8);
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	}
+	SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH);
+
+	for (i = 0; i < 32; i++)
+		gbe->mode_regs[i] = val;
+
+	/* Initialize interrupts */
+	gbe->vt_intr01 = 0xffffffff;
+	gbe->vt_intr23 = 0xffffffff;
+
+	/* HACK:
+	   The GBE hardware uses a tiled memory to screen mapping. Tiles are
+	   blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
+	   16bit and 32 bit modes (64 kB). They cover the screen with partial
+	   tiles on the right and/or bottom of the screen if needed.
+	   For example in 640x480 8 bit mode the mapping is:
+
+	   <-------- 640 ----->
+	   <---- 512 ----><128|384 offscreen>
+	   ^  ^
+	   | 128    [tile 0]        [tile 1]
+	   |  v
+	   ^
+	   4 128    [tile 2]        [tile 3]
+	   8  v
+	   0  ^
+	   128    [tile 4]        [tile 5]
+	   |  v
+	   |  ^
+	   v  96    [tile 6]        [tile 7]
+	   32 offscreen
+
+	   Tiles have the advantage that they can be allocated individually in
+	   memory. However, this mapping is not linear at all, which is not
+	   really convenient. In order to support linear addressing, the GBE
+	   DMA hardware is fooled into thinking the screen is only one tile
+	   large and but has a greater height, so that the DMA transfer covers
+	   the same region.
+	   Tiles are still allocated as independent chunks of 64KB of
+	   continuous physical memory and remapped so that the kernel sees the
+	   framebuffer as a continuous virtual memory. The GBE tile table is
+	   set up so that each tile references one of these 64k blocks:
+
+	   GBE -> tile list    framebuffer           TLB   <------------ CPU
+	          [ tile 0 ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     ^
+	             ...           ...              ...       linear virtual FB
+	          [ tile n ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     v
+
+
+	   The GBE hardware is then told that the buffer is 512*tweaked_height,
+	   with tweaked_height = real_width*real_height/pixels_per_tile.
+	   Thus the GBE hardware will scan the first tile, filing the first 64k
+	   covered region of the screen, and then will proceed to the next
+	   tile, until the whole screen is covered.
+
+	   Here is what would happen at 640x480 8bit:
+
+	   normal tiling               linear
+	   ^   11111111111111112222    11111111111111111111  ^
+	   128 11111111111111112222    11111111111111111111 102 lines
+	       11111111111111112222    11111111111111111111  v
+	   V   11111111111111112222    11111111222222222222
+	       33333333333333334444    22222222222222222222
+	       33333333333333334444    22222222222222222222
+	       <      512     >        <  256 >               102*640+256 = 64k
+
+	   NOTE: The only mode for which this is not working is 800x600 8bit,
+	   as 800*600/512 = 937.5 which is not integer and thus causes
+	   flickering.
+	   I guess this is not so important as one can use 640x480 8bit or
+	   800x600 16bit anyway.
+	 */
+
+	/* Tell gbe about the tiles table location */
+	/* tile_ptr -> [ tile 1 ] -> FB mem */
+	/*             [ tile 2 ] -> FB mem */
+	/*               ...                */
+	val = 0;
+	SET_GBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, val, gbe_tiles.dma >> 9);
+	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0); /* do not start */
+	SET_GBE_FIELD(FRM_CONTROL, FRM_LINEAR, val, 0);
+	gbe->frm_control = val;
+
+	maxPixelsPerTileX = 512 / bytesPerPixel;
+	wholeTilesX = 1;
+	partTilesX = 0;
+
+	/* Initialize the framebuffer */
+	val = 0;
+	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, val, wholeTilesX);
+	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_RHS, val, partTilesX);
+
+	switch (bytesPerPixel) {
+	case 1:
+		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
+			      GBE_FRM_DEPTH_8);
+		break;
+	case 2:
+		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
+			      GBE_FRM_DEPTH_16);
+		break;
+	case 4:
+		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
+			      GBE_FRM_DEPTH_32);
+		break;
+	}
+	gbe->frm_size_tile = val;
+
+	/* compute tweaked height */
+	height_pix = xpmax * ypmax / maxPixelsPerTileX;
+
+	val = 0;
+	SET_GBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, val, height_pix);
+	gbe->frm_size_pixel = val;
+
+	/* turn off DID and overlay DMA */
+	gbe->did_control = 0;
+	gbe->ovr_width_tile = 0;
+
+	/* Turn off mouse cursor */
+	gbe->crs_ctl = 0;
+
+	/* Turn on GBE */
+	gbe_turn_on();
+
+	/* Initialize the gamma map */
+	udelay(10);
+	for (i = 0; i < 256; i++)
+		gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8);
+
+	/* Initialize the color map */
+	for (i = 0; i < 256; i++)
+		gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24);
+
+	gbe_loadcmap();
+
+	return 0;
+}
+
+static void gbefb_encode_fix(struct fb_fix_screeninfo *fix,
+			     struct fb_var_screeninfo *var)
+{
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strcpy(fix->id, "SGI GBE");
+	fix->smem_start = (unsigned long) gbe_mem;
+	fix->smem_len = gbe_mem_size;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+	fix->accel = FB_ACCEL_NONE;
+	switch (var->bits_per_pixel) {
+	case 8:
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	default:
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		break;
+	}
+	fix->ywrapstep = 0;
+	fix->xpanstep = 0;
+	fix->ypanstep = 0;
+	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	fix->mmio_start = GBE_BASE;
+	fix->mmio_len = sizeof(struct sgi_gbe);
+}
+
+/*
+ *  Set a single color register. The values supplied are already
+ *  rounded down to the hardware's capabilities (according to the
+ *  entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			     unsigned blue, unsigned transp,
+			     struct fb_info *info)
+{
+	int i;
+
+	if (regno > 255)
+		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	if (info->var.bits_per_pixel <= 8) {
+		gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
+		if (gbe_turned_on) {
+			/* wait for the color map FIFO to have a free entry */
+			for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
+				udelay(10);
+			if (i == 1000) {
+				printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
+				return 1;
+			}
+			gbe->cmap[regno] = gbe_cmap[regno];
+		}
+	} else if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 15:
+		case 16:
+			red >>= 3;
+			green >>= 3;
+			blue >>= 3;
+			pseudo_palette[regno] =
+				(red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue << info->var.blue.offset);
+			break;
+		case 32:
+			pseudo_palette[regno] =
+				(red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue << info->var.blue.offset);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *  Check video mode validity, eventually modify var to best match.
+ */
+static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	unsigned int line_length;
+	struct gbe_timing_info timing;
+	int ret;
+
+	/* Limit bpp to 8, 16, and 32 */
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	/* Check the mode can be mapped linearly with the tile table trick. */
+	/* This requires width x height x bytes/pixel be a multiple of 512 */
+	if ((var->xres * var->yres * var->bits_per_pixel) & 4095)
+		return -EINVAL;
+
+	var->grayscale = 0;	/* No grayscale for now */
+
+	ret = compute_gbe_timing(var, &timing);
+	var->pixclock = ret;
+	if (ret < 0)
+		return -EINVAL;
+
+	/* Adjust virtual resolution, if necessary */
+	if (var->xres > var->xres_virtual || (!ywrap && !ypan))
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual || (!ywrap && !ypan))
+		var->yres_virtual = var->yres;
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/* No grayscale for now */
+	var->grayscale = 0;
+
+	/* Memory limit */
+	line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	if (line_length * var->yres_virtual > gbe_mem_size)
+		return -ENOMEM;	/* Virtual resolution too high */
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGB 1555 */
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 5;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGB 8888 */
+		var->red.offset = 24;
+		var->red.length = 8;
+		var->green.offset = 16;
+		var->green.length = 8;
+		var->blue.offset = 8;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	var->left_margin = timing.htotal - timing.hsync_end;
+	var->right_margin = timing.hsync_start - timing.width;
+	var->upper_margin = timing.vtotal - timing.vsync_end;
+	var->lower_margin = timing.vsync_start - timing.height;
+	var->hsync_len = timing.hsync_end - timing.hsync_start;
+	var->vsync_len = timing.vsync_end - timing.vsync_start;
+
+	return 0;
+}
+
+static int gbefb_mmap(struct fb_info *info,
+			struct vm_area_struct *vma)
+{
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long addr;
+	unsigned long phys_addr, phys_size;
+	u16 *tile;
+
+	/* check range */
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	if (size > gbe_mem_size)
+		return -EINVAL;
+	if (offset > gbe_mem_size - size)
+		return -EINVAL;
+
+	/* remap using the fastest write-through mode on architecture */
+	/* try not polluting the cache when possible */
+	pgprot_val(vma->vm_page_prot) =
+		pgprot_fb(pgprot_val(vma->vm_page_prot));
+
+	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
+
+	/* look for the starting tile */
+	tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
+	addr = vma->vm_start;
+	offset &= TILE_MASK;
+
+	/* remap each tile separately */
+	do {
+		phys_addr = (((unsigned long) (*tile)) << TILE_SHIFT) + offset;
+		if ((offset + size) < TILE_SIZE)
+			phys_size = size;
+		else
+			phys_size = TILE_SIZE - offset;
+
+		if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT,
+						phys_size, vma->vm_page_prot))
+			return -EAGAIN;
+
+		offset = 0;
+		size -= phys_size;
+		addr += phys_size;
+		tile++;
+	} while (size);
+
+	return 0;
+}
+
+static struct fb_ops gbefb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= gbefb_check_var,
+	.fb_set_par	= gbefb_set_par,
+	.fb_setcolreg	= gbefb_setcolreg,
+	.fb_mmap	= gbefb_mmap,
+	.fb_blank	= gbefb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/*
+ * sysfs
+ */
+
+static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size);
+}
+
+static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
+
+static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
+}
+
+static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
+
+static void gbefb_remove_sysfs(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_size);
+	device_remove_file(dev, &dev_attr_revision);
+}
+
+static void gbefb_create_sysfs(struct device *dev)
+{
+	device_create_file(dev, &dev_attr_size);
+	device_create_file(dev, &dev_attr_revision);
+}
+
+/*
+ * Initialization
+ */
+
+static int gbefb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "monitor:", 8)) {
+			if (!strncmp(this_opt + 8, "crt", 3)) {
+				flat_panel_enabled = 0;
+				default_var = &default_var_CRT;
+				default_mode = &default_mode_CRT;
+			} else if (!strncmp(this_opt + 8, "1600sw", 6) ||
+				   !strncmp(this_opt + 8, "lcd", 3)) {
+				flat_panel_enabled = 1;
+				default_var = &default_var_LCD;
+				default_mode = &default_mode_LCD;
+			}
+		} else if (!strncmp(this_opt, "mem:", 4)) {
+			gbe_mem_size = memparse(this_opt + 4, &this_opt);
+			if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024)
+				gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024;
+			if (gbe_mem_size < TILE_SIZE)
+				gbe_mem_size = TILE_SIZE;
+		} else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+
+static int gbefb_probe(struct platform_device *p_dev)
+{
+	int i, ret = 0;
+	struct fb_info *info;
+	struct gbefb_par *par;
+#ifndef MODULE
+	char *options = NULL;
+#endif
+
+	info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+#ifndef MODULE
+	if (fb_get_options("gbefb", &options)) {
+		ret = -ENODEV;
+		goto out_release_framebuffer;
+	}
+	gbefb_setup(options);
+#endif
+
+	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
+		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
+		ret = -EBUSY;
+		goto out_release_framebuffer;
+	}
+
+	gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE,
+					      sizeof(struct sgi_gbe));
+	if (!gbe) {
+		printk(KERN_ERR "gbefb: couldn't map mmio region\n");
+		ret = -ENXIO;
+		goto out_release_mem_region;
+	}
+	gbe_revision = gbe->ctrlstat & 15;
+
+	gbe_tiles.cpu =
+		dma_alloc_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
+				   &gbe_tiles.dma, GFP_KERNEL);
+	if (!gbe_tiles.cpu) {
+		printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
+		ret = -ENOMEM;
+		goto out_release_mem_region;
+	}
+
+	if (gbe_mem_phys) {
+		/* memory was allocated at boot time */
+		gbe_mem = devm_ioremap_nocache(&p_dev->dev, gbe_mem_phys,
+					       gbe_mem_size);
+		if (!gbe_mem) {
+			printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
+			ret = -ENOMEM;
+			goto out_tiles_free;
+		}
+
+		gbe_dma_addr = 0;
+	} else {
+		/* try to allocate memory with the classical allocator
+		 * this has high chance to fail on low memory machines */
+		gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,
+					     GFP_KERNEL);
+		if (!gbe_mem) {
+			printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
+			ret = -ENOMEM;
+			goto out_tiles_free;
+		}
+
+		gbe_mem_phys = (unsigned long) gbe_dma_addr;
+	}
+
+#ifdef CONFIG_X86
+	mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);
+#endif
+
+	/* map framebuffer memory into tiles table */
+	for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
+		gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
+
+	info->fbops = &gbefb_ops;
+	info->pseudo_palette = pseudo_palette;
+	info->flags = FBINFO_DEFAULT;
+	info->screen_base = gbe_mem;
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	/* reset GBE */
+	gbe_reset();
+
+	par = info->par;
+	/* turn on default video mode */
+	if (fb_find_mode(&par->var, info, mode_option, NULL, 0,
+			 default_mode, 8) == 0)
+		par->var = *default_var;
+	info->var = par->var;
+	gbefb_check_var(&par->var, info);
+	gbefb_encode_fix(&info->fix, &info->var);
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "gbefb: couldn't register framebuffer\n");
+		ret = -ENXIO;
+		goto out_gbe_unmap;
+	}
+
+	platform_set_drvdata(p_dev, info);
+	gbefb_create_sysfs(&p_dev->dev);
+
+	fb_info(info, "%s rev %d @ 0x%08x using %dkB memory\n",
+		info->fix.id, gbe_revision, (unsigned)GBE_BASE,
+		gbe_mem_size >> 10);
+
+	return 0;
+
+out_gbe_unmap:
+	if (gbe_dma_addr)
+		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
+out_tiles_free:
+	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
+			  (void *)gbe_tiles.cpu, gbe_tiles.dma);
+out_release_mem_region:
+	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
+out_release_framebuffer:
+	framebuffer_release(info);
+
+	return ret;
+}
+
+static int gbefb_remove(struct platform_device* p_dev)
+{
+	struct fb_info *info = platform_get_drvdata(p_dev);
+
+	unregister_framebuffer(info);
+	gbe_turn_off();
+	if (gbe_dma_addr)
+		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
+	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
+			  (void *)gbe_tiles.cpu, gbe_tiles.dma);
+	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
+	gbefb_remove_sysfs(&p_dev->dev);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver gbefb_driver = {
+	.probe = gbefb_probe,
+	.remove = gbefb_remove,
+	.driver	= {
+		.name = "gbefb",
+	},
+};
+
+static struct platform_device *gbefb_device;
+
+static int __init gbefb_init(void)
+{
+	int ret = platform_driver_register(&gbefb_driver);
+	if (!ret) {
+		gbefb_device = platform_device_alloc("gbefb", 0);
+		if (gbefb_device) {
+			ret = platform_device_add(gbefb_device);
+		} else {
+			ret = -ENOMEM;
+		}
+		if (ret) {
+			platform_device_put(gbefb_device);
+			platform_driver_unregister(&gbefb_driver);
+		}
+	}
+	return ret;
+}
+
+static void __exit gbefb_exit(void)
+{
+	platform_device_unregister(gbefb_device);
+	platform_driver_unregister(&gbefb_driver);
+}
+
+module_init(gbefb_init);
+module_exit(gbefb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/geode/Kconfig b/drivers/video/fbdev/geode/Kconfig
new file mode 100644
index 000000000000..1e8555284786
--- /dev/null
+++ b/drivers/video/fbdev/geode/Kconfig
@@ -0,0 +1,54 @@
+#
+# Geode family framebuffer configuration
+#
+config FB_GEODE
+	bool "AMD Geode family framebuffer support"
+	depends on FB && PCI && (X86_32 || (X86 && COMPILE_TEST))
+	---help---
+	  Say 'Y' here to allow you to select framebuffer drivers for
+	  the AMD Geode family of processors.
+
+config FB_GEODE_LX
+	tristate "AMD Geode LX framebuffer support"
+	depends on FB && FB_GEODE
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Framebuffer driver for the display controller integrated into the
+	  AMD Geode LX processors.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called lxfb.
+
+	  If unsure, say N.
+
+config FB_GEODE_GX
+	tristate "AMD Geode GX framebuffer support"
+	depends on FB && FB_GEODE
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Framebuffer driver for the display controller integrated into the
+	  AMD Geode GX processors.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called gxfb.
+
+	  If unsure, say N.
+
+config FB_GEODE_GX1
+	tristate "AMD Geode GX1 framebuffer support"
+	depends on FB && FB_GEODE
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Framebuffer driver for the display controller integrated into the
+	  AMD Geode GX1 processor.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called gx1fb.
+
+	  If unsure, say N.
diff --git a/drivers/video/fbdev/geode/Makefile b/drivers/video/fbdev/geode/Makefile
new file mode 100644
index 000000000000..5c98da126883
--- /dev/null
+++ b/drivers/video/fbdev/geode/Makefile
@@ -0,0 +1,9 @@
+# Makefile for the Geode family framebuffer drivers
+
+obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
+obj-$(CONFIG_FB_GEODE_GX)  += gxfb.o
+obj-$(CONFIG_FB_GEODE_LX)  += lxfb.o
+
+gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
+gxfb-objs  := gxfb_core.o display_gx.o video_gx.o suspend_gx.o
+lxfb-objs  := lxfb_core.o lxfb_ops.o
diff --git a/drivers/video/fbdev/geode/display_gx.c b/drivers/video/fbdev/geode/display_gx.c
new file mode 100644
index 000000000000..f0af911a096d
--- /dev/null
+++ b/drivers/video/fbdev/geode/display_gx.c
@@ -0,0 +1,184 @@
+/*
+ * Geode GX display controller.
+ *
+ *   Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ *   Portions from AMD's original 2.4 driver:
+ *     Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License as published by * the
+ *   Free Software Foundation; either version 2 of the License, or * (at your
+ *   option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+#include <linux/cs5535.h>
+
+#include "gxfb.h"
+
+unsigned int gx_frame_buffer_size(void)
+{
+	unsigned int val;
+
+	if (!cs5535_has_vsa2()) {
+		uint32_t hi, lo;
+
+		/* The number of pages is (PMAX - PMIN)+1 */
+		rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
+
+		/* PMAX */
+		val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
+		/* PMIN */
+		val -= (lo & 0x000fffff);
+		val += 1;
+
+		/* The page size is 4k */
+		return (val << 12);
+	}
+
+	/* FB size can be obtained from the VSA II */
+	/* Virtual register class = 0x02 */
+	/* VG_MEM_SIZE(512Kb units) = 0x00 */
+
+	outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
+	outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
+
+	val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFFl;
+	return (val << 19);
+}
+
+int gx_line_delta(int xres, int bpp)
+{
+	/* Must be a multiple of 8 bytes. */
+	return (xres * (bpp >> 3) + 7) & ~0x7;
+}
+
+void gx_set_mode(struct fb_info *info)
+{
+	struct gxfb_par *par = info->par;
+	u32 gcfg, dcfg;
+	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+	/* Unlock the display controller registers. */
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+
+	gcfg = read_dc(par, DC_GENERAL_CFG);
+	dcfg = read_dc(par, DC_DISPLAY_CFG);
+
+	/* Disable the timing generator. */
+	dcfg &= ~DC_DISPLAY_CFG_TGEN;
+	write_dc(par, DC_DISPLAY_CFG, dcfg);
+
+	/* Wait for pending memory requests before disabling the FIFO load. */
+	udelay(100);
+
+	/* Disable FIFO load and compression. */
+	gcfg &= ~(DC_GENERAL_CFG_DFLE | DC_GENERAL_CFG_CMPE |
+			DC_GENERAL_CFG_DECE);
+	write_dc(par, DC_GENERAL_CFG, gcfg);
+
+	/* Setup DCLK and its divisor. */
+	gx_set_dclk_frequency(info);
+
+	/*
+	 * Setup new mode.
+	 */
+
+	/* Clear all unused feature bits. */
+	gcfg &= DC_GENERAL_CFG_YUVM | DC_GENERAL_CFG_VDSE;
+	dcfg = 0;
+
+	/* Set FIFO priority (default 6/5) and enable. */
+	/* FIXME: increase fifo priority for 1280x1024 and higher modes? */
+	gcfg |= (6 << DC_GENERAL_CFG_DFHPEL_SHIFT) |
+		(5 << DC_GENERAL_CFG_DFHPSL_SHIFT) | DC_GENERAL_CFG_DFLE;
+
+	/* Framebuffer start offset. */
+	write_dc(par, DC_FB_ST_OFFSET, 0);
+
+	/* Line delta and line buffer length. */
+	write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
+	write_dc(par, DC_LINE_SIZE,
+		((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2);
+
+
+	/* Enable graphics and video data and unmask address lines. */
+	dcfg |= DC_DISPLAY_CFG_GDEN | DC_DISPLAY_CFG_VDEN |
+		DC_DISPLAY_CFG_A20M | DC_DISPLAY_CFG_A18M;
+
+	/* Set pixel format. */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
+		break;
+	case 16:
+		dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
+		break;
+	case 32:
+		dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
+		dcfg |= DC_DISPLAY_CFG_PALB;
+		break;
+	}
+
+	/* Enable timing generator. */
+	dcfg |= DC_DISPLAY_CFG_TGEN;
+
+	/* Horizontal and vertical timings. */
+	hactive = info->var.xres;
+	hblankstart = hactive;
+	hsyncstart = hblankstart + info->var.right_margin;
+	hsyncend =  hsyncstart + info->var.hsync_len;
+	hblankend = hsyncend + info->var.left_margin;
+	htotal = hblankend;
+
+	vactive = info->var.yres;
+	vblankstart = vactive;
+	vsyncstart = vblankstart + info->var.lower_margin;
+	vsyncend =  vsyncstart + info->var.vsync_len;
+	vblankend = vsyncend + info->var.upper_margin;
+	vtotal = vblankend;
+
+	write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1)    |
+			((htotal - 1) << 16));
+	write_dc(par, DC_H_BLANK_TIMING, (hblankstart - 1) |
+			((hblankend - 1) << 16));
+	write_dc(par, DC_H_SYNC_TIMING, (hsyncstart - 1)   |
+			((hsyncend - 1) << 16));
+
+	write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1)    |
+			((vtotal - 1) << 16));
+	write_dc(par, DC_V_BLANK_TIMING, (vblankstart - 1) |
+			((vblankend - 1) << 16));
+	write_dc(par, DC_V_SYNC_TIMING, (vsyncstart - 1)   |
+			((vsyncend - 1) << 16));
+
+	/* Write final register values. */
+	write_dc(par, DC_DISPLAY_CFG, dcfg);
+	write_dc(par, DC_GENERAL_CFG, gcfg);
+
+	gx_configure_display(info);
+
+	/* Relock display controller registers */
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+}
+
+void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+		unsigned red, unsigned green, unsigned blue)
+{
+	struct gxfb_par *par = info->par;
+	int val;
+
+	/* Hardware palette is in RGB 8-8-8 format. */
+	val  = (red   << 8) & 0xff0000;
+	val |= (green)      & 0x00ff00;
+	val |= (blue  >> 8) & 0x0000ff;
+
+	write_dc(par, DC_PAL_ADDRESS, regno);
+	write_dc(par, DC_PAL_DATA, val);
+}
diff --git a/drivers/video/fbdev/geode/display_gx1.c b/drivers/video/fbdev/geode/display_gx1.c
new file mode 100644
index 000000000000..926d53eeb549
--- /dev/null
+++ b/drivers/video/fbdev/geode/display_gx1.c
@@ -0,0 +1,214 @@
+/*
+ * drivers/video/geode/display_gx1.c
+ *   -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "display_gx1.h"
+
+static DEFINE_SPINLOCK(gx1_conf_reg_lock);
+
+static u8 gx1_read_conf_reg(u8 reg)
+{
+	u8 val, ccr3;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gx1_conf_reg_lock, flags);
+
+	outb(CONFIG_CCR3, 0x22);
+	ccr3 = inb(0x23);
+	outb(CONFIG_CCR3, 0x22);
+	outb(ccr3 | CONFIG_CCR3_MAPEN, 0x23);
+	outb(reg, 0x22);
+	val = inb(0x23);
+	outb(CONFIG_CCR3, 0x22);
+	outb(ccr3, 0x23);
+
+	spin_unlock_irqrestore(&gx1_conf_reg_lock, flags);
+
+	return val;
+}
+
+unsigned gx1_gx_base(void)
+{
+	return (gx1_read_conf_reg(CONFIG_GCR) & 0x03) << 30;
+}
+
+int gx1_frame_buffer_size(void)
+{
+	void __iomem *mc_regs;
+	u32 bank_cfg;
+	int d;
+	unsigned dram_size = 0, fb_base;
+
+	mc_regs = ioremap(gx1_gx_base() + 0x8400, 0x100);
+	if (!mc_regs)
+		return -ENOMEM;
+
+
+	/* Calculate the total size of both DIMM0 and DIMM1. */
+	bank_cfg = readl(mc_regs + MC_BANK_CFG);
+
+	for (d = 0; d < 2; d++) {
+		if ((bank_cfg & MC_BCFG_DIMM0_PG_SZ_MASK) != MC_BCFG_DIMM0_PG_SZ_NO_DIMM)
+			dram_size += 0x400000 << ((bank_cfg & MC_BCFG_DIMM0_SZ_MASK) >> 8);
+		bank_cfg >>= 16; /* look at DIMM1 next */
+	}
+
+	fb_base = (readl(mc_regs + MC_GBASE_ADD) & MC_GADD_GBADD_MASK) << 19;
+
+	iounmap(mc_regs);
+
+	return dram_size - fb_base;
+}
+
+static void gx1_set_mode(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+	u32 gcfg, tcfg, ocfg, dclk_div, val;
+	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+	/* Unlock the display controller registers. */
+	readl(par->dc_regs + DC_UNLOCK);
+	writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+
+	gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+	tcfg = readl(par->dc_regs + DC_TIMING_CFG);
+
+	/* Blank the display and disable the timing generator. */
+	tcfg &= ~(DC_TCFG_BLKE | DC_TCFG_TGEN);
+	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+
+	/* Wait for pending memory requests before disabling the FIFO load. */
+	udelay(100);
+
+	/* Disable FIFO load and compression. */
+	gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	/* Setup DCLK and its divisor. */
+	gcfg &= ~DC_GCFG_DCLK_MASK;
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	par->vid_ops->set_dclk(info);
+
+	dclk_div = DC_GCFG_DCLK_DIV_1; /* FIXME: may need to divide DCLK by 2 sometimes? */
+	gcfg |= dclk_div;
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	/* Wait for the clock generatation to settle.  This is needed since
+	 * some of the register writes that follow require that clock to be
+	 * present. */
+	udelay(1000); /* FIXME: seems a little long */
+
+	/*
+	 * Setup new mode.
+	 */
+
+	/* Clear all unused feature bits. */
+	gcfg = DC_GCFG_VRDY | dclk_div;
+
+	/* Set FIFO priority (default 6/5) and enable. */
+	/* FIXME: increase fifo priority for 1280x1024 modes? */
+	gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
+
+	/* FIXME: Set pixel and line double bits if necessary. */
+
+	/* Framebuffer start offset. */
+	writel(0, par->dc_regs + DC_FB_ST_OFFSET);
+
+	/* Line delta and line buffer length. */
+	writel(info->fix.line_length >> 2, par->dc_regs + DC_LINE_DELTA);
+	writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
+	       par->dc_regs + DC_BUF_SIZE);
+
+	/* Output configuration. Enable panel data, set pixel format. */
+	ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;
+	if (info->var.bits_per_pixel == 8) ocfg |= DC_OCFG_8BPP;
+
+	/* Enable timing generator, sync and FP data. */
+	tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE
+		| DC_TCFG_TGEN;
+
+	/* Horizontal and vertical timings. */
+	hactive = info->var.xres;
+	hblankstart = hactive;
+	hsyncstart = hblankstart + info->var.right_margin;
+	hsyncend =  hsyncstart + info->var.hsync_len;
+	hblankend = hsyncend + info->var.left_margin;
+	htotal = hblankend;
+
+	vactive = info->var.yres;
+	vblankstart = vactive;
+	vsyncstart = vblankstart + info->var.lower_margin;
+	vsyncend =  vsyncstart + info->var.vsync_len;
+	vblankend = vsyncend + info->var.upper_margin;
+	vtotal = vblankend;
+
+	val = (hactive - 1) | ((htotal - 1) << 16);
+	writel(val, par->dc_regs + DC_H_TIMING_1);
+	val = (hblankstart - 1) | ((hblankend - 1) << 16);
+	writel(val, par->dc_regs + DC_H_TIMING_2);
+	val = (hsyncstart - 1) | ((hsyncend - 1) << 16);
+	writel(val, par->dc_regs + DC_H_TIMING_3);
+	writel(val, par->dc_regs + DC_FP_H_TIMING);
+	val = (vactive - 1) | ((vtotal - 1) << 16);
+	writel(val, par->dc_regs + DC_V_TIMING_1);
+	val = (vblankstart - 1) | ((vblankend - 1) << 16);
+	writel(val, par->dc_regs + DC_V_TIMING_2);
+	val = (vsyncstart - 1) | ((vsyncend - 1) << 16);
+	writel(val, par->dc_regs + DC_V_TIMING_3);
+	val = (vsyncstart - 2) | ((vsyncend - 2) << 16);
+	writel(val, par->dc_regs + DC_FP_V_TIMING);
+
+	/* Write final register values. */
+	writel(ocfg, par->dc_regs + DC_OUTPUT_CFG);
+	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+	udelay(1000); /* delay after TIMING_CFG. FIXME: perhaps a little long */
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	par->vid_ops->configure_display(info);
+
+	/* Relock display controller registers */
+	writel(0, par->dc_regs + DC_UNLOCK);
+
+	/* FIXME: write line_length and bpp to Graphics Pipeline GP_BLT_STATUS
+	 * register. */
+}
+
+static void gx1_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+				   unsigned red, unsigned green, unsigned blue)
+{
+	struct geodefb_par *par = info->par;
+	int val;
+
+	/* Hardware palette is in RGB 6-6-6 format. */
+	val  = (red   <<  2) & 0x3f000;
+	val |= (green >>  4) & 0x00fc0;
+	val |= (blue  >> 10) & 0x0003f;
+
+	writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+	writel(val, par->dc_regs + DC_PAL_DATA);
+}
+
+struct geode_dc_ops gx1_dc_ops = {
+	.set_mode	 = gx1_set_mode,
+	.set_palette_reg = gx1_set_hw_palette_reg,
+};
diff --git a/drivers/video/fbdev/geode/display_gx1.h b/drivers/video/fbdev/geode/display_gx1.h
new file mode 100644
index 000000000000..671c05558c79
--- /dev/null
+++ b/drivers/video/fbdev/geode/display_gx1.h
@@ -0,0 +1,154 @@
+/*
+ * drivers/video/geode/display_gx1.h
+ *   -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __DISPLAY_GX1_H__
+#define __DISPLAY_GX1_H__
+
+unsigned gx1_gx_base(void);
+int gx1_frame_buffer_size(void);
+
+extern struct geode_dc_ops gx1_dc_ops;
+
+/* GX1 configuration I/O registers */
+
+#define CONFIG_CCR3 0xc3
+#  define CONFIG_CCR3_MAPEN 0x10
+#define CONFIG_GCR  0xb8
+
+/* Memory controller registers */
+
+#define MC_BANK_CFG		0x08
+#  define MC_BCFG_DIMM0_SZ_MASK		0x00000700
+#  define MC_BCFG_DIMM0_PG_SZ_MASK	0x00000070
+#  define MC_BCFG_DIMM0_PG_SZ_NO_DIMM	0x00000070
+
+#define MC_GBASE_ADD		0x14
+#  define MC_GADD_GBADD_MASK		0x000003ff
+
+/* Display controller registers */
+
+#define DC_PAL_ADDRESS		0x70
+#define DC_PAL_DATA		0x74
+
+#define DC_UNLOCK		0x00
+#  define DC_UNLOCK_CODE		0x00004758
+
+#define DC_GENERAL_CFG		0x04
+#  define DC_GCFG_DFLE			0x00000001
+#  define DC_GCFG_CURE			0x00000002
+#  define DC_GCFG_VCLK_DIV		0x00000004
+#  define DC_GCFG_PLNO			0x00000004
+#  define DC_GCFG_PPC			0x00000008
+#  define DC_GCFG_CMPE			0x00000010
+#  define DC_GCFG_DECE			0x00000020
+#  define DC_GCFG_DCLK_MASK		0x000000C0
+#  define DC_GCFG_DCLK_DIV_1		0x00000080
+#  define DC_GCFG_DFHPSL_MASK		0x00000F00
+#  define DC_GCFG_DFHPSL_POS			 8
+#  define DC_GCFG_DFHPEL_MASK		0x0000F000
+#  define DC_GCFG_DFHPEL_POS			12
+#  define DC_GCFG_CIM_MASK		0x00030000
+#  define DC_GCFG_CIM_POS			16
+#  define DC_GCFG_FDTY			0x00040000
+#  define DC_GCFG_RTPM			0x00080000
+#  define DC_GCFG_DAC_RS_MASK		0x00700000
+#  define DC_GCFG_DAC_RS_POS			20
+#  define DC_GCFG_CKWR			0x00800000
+#  define DC_GCFG_LDBL			0x01000000
+#  define DC_GCFG_DIAG			0x02000000
+#  define DC_GCFG_CH4S			0x04000000
+#  define DC_GCFG_SSLC			0x08000000
+#  define DC_GCFG_VIDE			0x10000000
+#  define DC_GCFG_VRDY			0x20000000
+#  define DC_GCFG_DPCK			0x40000000
+#  define DC_GCFG_DDCK			0x80000000
+
+#define DC_TIMING_CFG		0x08
+#  define DC_TCFG_FPPE			0x00000001
+#  define DC_TCFG_HSYE			0x00000002
+#  define DC_TCFG_VSYE			0x00000004
+#  define DC_TCFG_BLKE			0x00000008
+#  define DC_TCFG_DDCK			0x00000010
+#  define DC_TCFG_TGEN			0x00000020
+#  define DC_TCFG_VIEN			0x00000040
+#  define DC_TCFG_BLNK			0x00000080
+#  define DC_TCFG_CHSP			0x00000100
+#  define DC_TCFG_CVSP			0x00000200
+#  define DC_TCFG_FHSP			0x00000400
+#  define DC_TCFG_FVSP			0x00000800
+#  define DC_TCFG_FCEN			0x00001000
+#  define DC_TCFG_CDCE			0x00002000
+#  define DC_TCFG_PLNR			0x00002000
+#  define DC_TCFG_INTL			0x00004000
+#  define DC_TCFG_PXDB			0x00008000
+#  define DC_TCFG_BKRT			0x00010000
+#  define DC_TCFG_PSD_MASK		0x000E0000
+#  define DC_TCFG_PSD_POS			17
+#  define DC_TCFG_DDCI			0x08000000
+#  define DC_TCFG_SENS			0x10000000
+#  define DC_TCFG_DNA			0x20000000
+#  define DC_TCFG_VNA			0x40000000
+#  define DC_TCFG_VINT			0x80000000
+
+#define DC_OUTPUT_CFG		0x0C
+#  define DC_OCFG_8BPP			0x00000001
+#  define DC_OCFG_555			0x00000002
+#  define DC_OCFG_PCKE			0x00000004
+#  define DC_OCFG_FRME			0x00000008
+#  define DC_OCFG_DITE			0x00000010
+#  define DC_OCFG_2PXE			0x00000020
+#  define DC_OCFG_2XCK			0x00000040
+#  define DC_OCFG_2IND			0x00000080
+#  define DC_OCFG_34ADD			0x00000100
+#  define DC_OCFG_FRMS			0x00000200
+#  define DC_OCFG_CKSL			0x00000400
+#  define DC_OCFG_PRMP			0x00000800
+#  define DC_OCFG_PDEL			0x00001000
+#  define DC_OCFG_PDEH			0x00002000
+#  define DC_OCFG_CFRW			0x00004000
+#  define DC_OCFG_DIAG			0x00008000
+
+#define DC_FB_ST_OFFSET		0x10
+#define DC_CB_ST_OFFSET		0x14
+#define DC_CURS_ST_OFFSET	0x18
+#define DC_ICON_ST_OFFSET	0x1C
+#define DC_VID_ST_OFFSET	0x20
+#define DC_LINE_DELTA		0x24
+#define DC_BUF_SIZE		0x28
+
+#define DC_H_TIMING_1		0x30
+#define DC_H_TIMING_2		0x34
+#define DC_H_TIMING_3		0x38
+#define DC_FP_H_TIMING		0x3C
+
+#define DC_V_TIMING_1		0x40
+#define DC_V_TIMING_2		0x44
+#define DC_V_TIMING_3		0x48
+#define DC_FP_V_TIMING		0x4C
+
+#define DC_CURSOR_X		0x50
+#define DC_ICON_X		0x54
+#define DC_V_LINE_CNT		0x54
+#define DC_CURSOR_Y		0x58
+#define DC_ICON_Y		0x5C
+#define DC_SS_LINE_CMP		0x5C
+#define DC_CURSOR_COLOR		0x60
+#define DC_ICON_COLOR		0x64
+#define DC_BORDER_COLOR		0x68
+#define DC_PAL_ADDRESS		0x70
+#define DC_PAL_DATA		0x74
+#define DC_DFIFO_DIAG		0x78
+#define DC_CFIFO_DIAG		0x7C
+
+#endif /* !__DISPLAY_GX1_H__ */
diff --git a/drivers/video/fbdev/geode/geodefb.h b/drivers/video/fbdev/geode/geodefb.h
new file mode 100644
index 000000000000..ae04820e0c57
--- /dev/null
+++ b/drivers/video/fbdev/geode/geodefb.h
@@ -0,0 +1,38 @@
+/*
+ * drivers/video/geode/geodefb.h
+ *   -- Geode framebuffer driver
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __GEODEFB_H__
+#define __GEODEFB_H__
+
+struct geodefb_info;
+
+struct geode_dc_ops {
+	void (*set_mode)(struct fb_info *);
+	void (*set_palette_reg)(struct fb_info *, unsigned, unsigned, unsigned, unsigned);
+};
+
+struct geode_vid_ops {
+	void (*set_dclk)(struct fb_info *);
+	void (*configure_display)(struct fb_info *);
+	int  (*blank_display)(struct fb_info *, int blank_mode);
+};
+
+struct geodefb_par {
+	int enable_crt;
+	int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
+	int panel_y;
+	void __iomem *dc_regs;
+	void __iomem *vid_regs;
+	struct geode_dc_ops  *dc_ops;
+	struct geode_vid_ops *vid_ops;
+};
+
+#endif /* !__GEODEFB_H__ */
diff --git a/drivers/video/fbdev/geode/gx1fb_core.c b/drivers/video/fbdev/geode/gx1fb_core.c
new file mode 100644
index 000000000000..2794ba11f332
--- /dev/null
+++ b/drivers/video/fbdev/geode/gx1fb_core.c
@@ -0,0 +1,476 @@
+/*
+ * drivers/video/geode/gx1fb_core.c
+ *   -- Geode GX1 framebuffer driver
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include "geodefb.h"
+#include "display_gx1.h"
+#include "video_cs5530.h"
+
+static char mode_option[32] = "640x480-16@60";
+static int  crt_option = 1;
+static char panel_option[32] = "";
+
+/* Modes relevant to the GX1 (taken from modedb.c) */
+static const struct fb_videomode gx1_modedb[] = {
+	/* 640x480-60 VESA */
+	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 640x480-75 VESA */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 640x480-85 VESA */
+	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-60 VESA */
+	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-75 VESA */
+	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-85 VESA */
+	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-60 VESA */
+	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-75 VESA */
+	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-85 VESA */
+	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x960-60 VESA */
+	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x960-85 VESA */
+	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-60 VESA */
+	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-75 VESA */
+	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-85 VESA */
+	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+static int gx1_line_delta(int xres, int bpp)
+{
+	int line_delta = xres * (bpp >> 3);
+
+	if (line_delta > 2048)
+		line_delta = 4096;
+	else if (line_delta > 1024)
+		line_delta = 2048;
+	else
+		line_delta = 1024;
+	return line_delta;
+}
+
+static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	/* Maximum resolution is 1280x1024. */
+	if (var->xres > 1280 || var->yres > 1024)
+		return -EINVAL;
+
+	if (par->panel_x && (var->xres > par->panel_x || var->yres > par->panel_y))
+		return -EINVAL;
+
+	/* Only 16 bpp and 8 bpp is supported by the hardware. */
+	if (var->bits_per_pixel == 16) {
+		var->red.offset   = 11; var->red.length   = 5;
+		var->green.offset =  5; var->green.length = 6;
+		var->blue.offset  =  0; var->blue.length  = 5;
+		var->transp.offset = 0; var->transp.length = 0;
+	} else if (var->bits_per_pixel == 8) {
+		var->red.offset   = 0; var->red.length   = 8;
+		var->green.offset = 0; var->green.length = 8;
+		var->blue.offset  = 0; var->blue.length  = 8;
+		var->transp.offset = 0; var->transp.length = 0;
+	} else
+		return -EINVAL;
+
+	/* Enough video memory? */
+	if (gx1_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
+		return -EINVAL;
+
+	/* FIXME: Check timing parameters here? */
+
+	return 0;
+}
+
+static int gx1fb_set_par(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	if (info->var.bits_per_pixel == 16)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = gx1_line_delta(info->var.xres, info->var.bits_per_pixel);
+
+	par->dc_ops->set_mode(info);
+
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int gx1fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 *pal = info->pseudo_palette;
+		u32 v;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		v  = chan_to_field(red, &info->var.red);
+		v |= chan_to_field(green, &info->var.green);
+		v |= chan_to_field(blue, &info->var.blue);
+
+		pal[regno] = v;
+	} else {
+		if (regno >= 256)
+			return -EINVAL;
+
+		par->dc_ops->set_palette_reg(info, regno, red, green, blue);
+	}
+
+	return 0;
+}
+
+static int gx1fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	return par->vid_ops->blank_display(info, blank_mode);
+}
+
+static int gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+{
+	struct geodefb_par *par = info->par;
+	unsigned gx_base;
+	int fb_len;
+	int ret;
+
+	gx_base = gx1_gx_base();
+	if (!gx_base)
+		return -ENODEV;
+
+	ret = pci_enable_device(dev);
+	if (ret < 0)
+		return ret;
+
+	ret = pci_request_region(dev, 0, "gx1fb (video)");
+	if (ret < 0)
+		return ret;
+	par->vid_regs = pci_ioremap_bar(dev, 0);
+	if (!par->vid_regs)
+		return -ENOMEM;
+
+	if (!request_mem_region(gx_base + 0x8300, 0x100, "gx1fb (display controller)"))
+		return -EBUSY;
+	par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
+	if (!par->dc_regs)
+		return -ENOMEM;
+
+	if ((fb_len = gx1_frame_buffer_size()) < 0)
+		return -ENOMEM;
+	info->fix.smem_start = gx_base + 0x800000;
+	info->fix.smem_len = fb_len;
+	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+	if (!info->screen_base)
+		return -ENOMEM;
+
+	dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
+		 info->fix.smem_len / 1024, info->fix.smem_start);
+
+	return 0;
+}
+
+static int parse_panel_option(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	if (strcmp(panel_option, "") != 0) {
+		int x, y;
+		char *s;
+		x = simple_strtol(panel_option, &s, 10);
+		if (!x)
+			return -EINVAL;
+		y = simple_strtol(s + 1, NULL, 10);
+		if (!y)
+			return -EINVAL;
+		par->panel_x = x;
+		par->panel_y = y;
+	}
+	return 0;
+}
+
+static struct fb_ops gx1fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= gx1fb_check_var,
+	.fb_set_par	= gx1fb_set_par,
+	.fb_setcolreg	= gx1fb_setcolreg,
+	.fb_blank       = gx1fb_blank,
+	/* No HW acceleration for now. */
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static struct fb_info *gx1fb_init_fbinfo(struct device *dev)
+{
+	struct geodefb_par *par;
+	struct fb_info *info;
+
+	/* Alloc enough space for the pseudo palette. */
+	info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
+	if (!info)
+		return NULL;
+
+	par = info->par;
+
+	strcpy(info->fix.id, "GX1");
+
+	info->fix.type		= FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux	= 0;
+	info->fix.xpanstep	= 0;
+	info->fix.ypanstep	= 0;
+	info->fix.ywrapstep	= 0;
+	info->fix.accel		= FB_ACCEL_NONE;
+
+	info->var.nonstd	= 0;
+	info->var.activate	= FB_ACTIVATE_NOW;
+	info->var.height	= -1;
+	info->var.width	= -1;
+	info->var.accel_flags = 0;
+	info->var.vmode	= FB_VMODE_NONINTERLACED;
+
+	info->fbops		= &gx1fb_ops;
+	info->flags		= FBINFO_DEFAULT;
+	info->node		= -1;
+
+	info->pseudo_palette	= (void *)par + sizeof(struct geodefb_par);
+
+	info->var.grayscale	= 0;
+
+	/* CRT and panel options */
+	par->enable_crt = crt_option;
+	if (parse_panel_option(info) < 0)
+		printk(KERN_WARNING "gx1fb: invalid 'panel' option -- disabling flat panel\n");
+	if (!par->panel_x)
+		par->enable_crt = 1; /* fall back to CRT if no panel is specified */
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		framebuffer_release(info);
+		return NULL;
+	}
+	return info;
+}
+
+static int gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct geodefb_par *par;
+	struct fb_info *info;
+	int ret;
+
+	info = gx1fb_init_fbinfo(&pdev->dev);
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+
+	/* GX1 display controller and CS5530 video device */
+	par->dc_ops  = &gx1_dc_ops;
+	par->vid_ops = &cs5530_vid_ops;
+
+	if ((ret = gx1fb_map_video_memory(info, pdev)) < 0) {
+		dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
+		goto err;
+	}
+
+	ret = fb_find_mode(&info->var, info, mode_option,
+			   gx1_modedb, ARRAY_SIZE(gx1_modedb), NULL, 16);
+	if (ret == 0 || ret == 4) {
+		dev_err(&pdev->dev, "could not find valid video mode\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+        /* Clear the frame buffer of garbage. */
+        memset_io(info->screen_base, 0, info->fix.smem_len);
+
+	gx1fb_check_var(&info->var, info);
+	gx1fb_set_par(info);
+
+	if (register_framebuffer(info) < 0) {
+		ret = -EINVAL;
+		goto err;
+	}
+	pci_set_drvdata(pdev, info);
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	return 0;
+
+  err:
+	if (info->screen_base) {
+		iounmap(info->screen_base);
+		pci_release_region(pdev, 0);
+	}
+	if (par->vid_regs) {
+		iounmap(par->vid_regs);
+		pci_release_region(pdev, 1);
+	}
+	if (par->dc_regs) {
+		iounmap(par->dc_regs);
+		release_mem_region(gx1_gx_base() + 0x8300, 0x100);
+	}
+
+	if (info) {
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+
+	return ret;
+}
+
+static void gx1fb_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct geodefb_par *par = info->par;
+
+	unregister_framebuffer(info);
+
+	iounmap((void __iomem *)info->screen_base);
+	pci_release_region(pdev, 0);
+
+	iounmap(par->vid_regs);
+	pci_release_region(pdev, 1);
+
+	iounmap(par->dc_regs);
+	release_mem_region(gx1_gx_base() + 0x8300, 0x100);
+
+	fb_dealloc_cmap(&info->cmap);
+
+	framebuffer_release(info);
+}
+
+#ifndef MODULE
+static void __init gx1fb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ","))) {
+		if (!*this_opt)
+			continue;
+
+		if (!strncmp(this_opt, "mode:", 5))
+			strlcpy(mode_option, this_opt + 5, sizeof(mode_option));
+		else if (!strncmp(this_opt, "crt:", 4))
+			crt_option = !!simple_strtoul(this_opt + 4, NULL, 0);
+		else if (!strncmp(this_opt, "panel:", 6))
+			strlcpy(panel_option, this_opt + 6, sizeof(panel_option));
+		else
+			strlcpy(mode_option, this_opt, sizeof(mode_option));
+	}
+}
+#endif
+
+static struct pci_device_id gx1fb_id_table[] = {
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, gx1fb_id_table);
+
+static struct pci_driver gx1fb_driver = {
+	.name		= "gx1fb",
+	.id_table	= gx1fb_id_table,
+	.probe		= gx1fb_probe,
+	.remove		= gx1fb_remove,
+};
+
+static int __init gx1fb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("gx1fb", &option))
+		return -ENODEV;
+	gx1fb_setup(option);
+#endif
+	return pci_register_driver(&gx1fb_driver);
+}
+
+static void gx1fb_cleanup(void)
+{
+	pci_unregister_driver(&gx1fb_driver);
+}
+
+module_init(gx1fb_init);
+module_exit(gx1fb_cleanup);
+
+module_param_string(mode, mode_option, sizeof(mode_option), 0444);
+MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+module_param_named(crt, crt_option, int, 0444);
+MODULE_PARM_DESC(crt, "enable CRT output. 0 = off, 1 = on (default)");
+
+module_param_string(panel, panel_option, sizeof(panel_option), 0444);
+MODULE_PARM_DESC(panel, "size of attached flat panel (<x>x<y>)");
+
+MODULE_DESCRIPTION("framebuffer driver for the AMD Geode GX1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/geode/gxfb.h b/drivers/video/fbdev/geode/gxfb.h
new file mode 100644
index 000000000000..d19e9378b0c0
--- /dev/null
+++ b/drivers/video/fbdev/geode/gxfb.h
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2008 Andres Salomon <dilinger@debian.org>
+ *
+ * Geode GX2 header information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef _GXFB_H_
+#define _GXFB_H_
+
+#include <linux/io.h>
+
+#define GP_REG_COUNT   (0x50 / 4)
+#define DC_REG_COUNT   (0x90 / 4)
+#define VP_REG_COUNT   (0x138 / 8)
+#define FP_REG_COUNT   (0x68 / 8)
+
+#define DC_PAL_COUNT   0x104
+
+struct gxfb_par {
+	int enable_crt;
+	void __iomem *dc_regs;
+	void __iomem *vid_regs;
+	void __iomem *gp_regs;
+#ifdef CONFIG_PM
+	int powered_down;
+
+	/* register state, for power management functionality */
+	struct {
+		uint64_t padsel;
+		uint64_t dotpll;
+	} msr;
+
+	uint32_t gp[GP_REG_COUNT];
+	uint32_t dc[DC_REG_COUNT];
+	uint64_t vp[VP_REG_COUNT];
+	uint64_t fp[FP_REG_COUNT];
+
+	uint32_t pal[DC_PAL_COUNT];
+#endif
+};
+
+unsigned int gx_frame_buffer_size(void);
+int gx_line_delta(int xres, int bpp);
+void gx_set_mode(struct fb_info *info);
+void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+		unsigned red, unsigned green, unsigned blue);
+
+void gx_set_dclk_frequency(struct fb_info *info);
+void gx_configure_display(struct fb_info *info);
+int gx_blank_display(struct fb_info *info, int blank_mode);
+
+#ifdef CONFIG_PM
+int gx_powerdown(struct fb_info *info);
+int gx_powerup(struct fb_info *info);
+#endif
+
+
+/* Graphics Processor registers (table 6-23 from the data book) */
+enum gp_registers {
+	GP_DST_OFFSET = 0,
+	GP_SRC_OFFSET,
+	GP_STRIDE,
+	GP_WID_HEIGHT,
+
+	GP_SRC_COLOR_FG,
+	GP_SRC_COLOR_BG,
+	GP_PAT_COLOR_0,
+	GP_PAT_COLOR_1,
+
+	GP_PAT_COLOR_2,
+	GP_PAT_COLOR_3,
+	GP_PAT_COLOR_4,
+	GP_PAT_COLOR_5,
+
+	GP_PAT_DATA_0,
+	GP_PAT_DATA_1,
+	GP_RASTER_MODE,
+	GP_VECTOR_MODE,
+
+	GP_BLT_MODE,
+	GP_BLT_STATUS,
+	GP_HST_SRC,
+	GP_BASE_OFFSET, /* 0x4c */
+};
+
+#define GP_BLT_STATUS_BLT_PENDING	(1 << 2)
+#define GP_BLT_STATUS_BLT_BUSY		(1 << 0)
+
+
+/* Display Controller registers (table 6-38 from the data book) */
+enum dc_registers {
+	DC_UNLOCK = 0,
+	DC_GENERAL_CFG,
+	DC_DISPLAY_CFG,
+	DC_RSVD_0,
+
+	DC_FB_ST_OFFSET,
+	DC_CB_ST_OFFSET,
+	DC_CURS_ST_OFFSET,
+	DC_ICON_ST_OFFSET,
+
+	DC_VID_Y_ST_OFFSET,
+	DC_VID_U_ST_OFFSET,
+	DC_VID_V_ST_OFFSET,
+	DC_RSVD_1,
+
+	DC_LINE_SIZE,
+	DC_GFX_PITCH,
+	DC_VID_YUV_PITCH,
+	DC_RSVD_2,
+
+	DC_H_ACTIVE_TIMING,
+	DC_H_BLANK_TIMING,
+	DC_H_SYNC_TIMING,
+	DC_RSVD_3,
+
+	DC_V_ACTIVE_TIMING,
+	DC_V_BLANK_TIMING,
+	DC_V_SYNC_TIMING,
+	DC_RSVD_4,
+
+	DC_CURSOR_X,
+	DC_CURSOR_Y,
+	DC_ICON_X,
+	DC_LINE_CNT,
+
+	DC_PAL_ADDRESS,
+	DC_PAL_DATA,
+	DC_DFIFO_DIAG,
+	DC_CFIFO_DIAG,
+
+	DC_VID_DS_DELTA,
+	DC_GLIU0_MEM_OFFSET,
+	DC_RSVD_5,
+	DC_DV_ACC, /* 0x8c */
+};
+
+#define DC_UNLOCK_LOCK			0x00000000
+#define DC_UNLOCK_UNLOCK		0x00004758	/* magic value */
+
+#define DC_GENERAL_CFG_YUVM		(1 << 20)
+#define DC_GENERAL_CFG_VDSE		(1 << 19)
+#define DC_GENERAL_CFG_DFHPEL_SHIFT	12
+#define DC_GENERAL_CFG_DFHPSL_SHIFT	8
+#define DC_GENERAL_CFG_DECE		(1 << 6)
+#define DC_GENERAL_CFG_CMPE		(1 << 5)
+#define DC_GENERAL_CFG_VIDE		(1 << 3)
+#define DC_GENERAL_CFG_ICNE		(1 << 2)
+#define DC_GENERAL_CFG_CURE		(1 << 1)
+#define DC_GENERAL_CFG_DFLE		(1 << 0)
+
+#define DC_DISPLAY_CFG_A20M		(1 << 31)
+#define DC_DISPLAY_CFG_A18M		(1 << 30)
+#define DC_DISPLAY_CFG_PALB		(1 << 25)
+#define DC_DISPLAY_CFG_DISP_MODE_24BPP	(1 << 9)
+#define DC_DISPLAY_CFG_DISP_MODE_16BPP	(1 << 8)
+#define DC_DISPLAY_CFG_DISP_MODE_8BPP	(0)
+#define DC_DISPLAY_CFG_VDEN		(1 << 4)
+#define DC_DISPLAY_CFG_GDEN		(1 << 3)
+#define DC_DISPLAY_CFG_TGEN		(1 << 0)
+
+
+/*
+ * Video Processor registers (table 6-54).
+ * There is space for 64 bit values, but we never use more than the
+ * lower 32 bits.  The actual register save/restore code only bothers
+ * to restore those 32 bits.
+ */
+enum vp_registers {
+	VP_VCFG = 0,
+	VP_DCFG,
+
+	VP_VX,
+	VP_VY,
+
+	VP_VS,
+	VP_VCK,
+
+	VP_VCM,
+	VP_GAR,
+
+	VP_GDR,
+	VP_RSVD_0,
+
+	VP_MISC,
+	VP_CCS,
+
+	VP_RSVD_1,
+	VP_RSVD_2,
+
+	VP_RSVD_3,
+	VP_VDC,
+
+	VP_VCO,
+	VP_CRC,
+
+	VP_CRC32,
+	VP_VDE,
+
+	VP_CCK,
+	VP_CCM,
+
+	VP_CC1,
+	VP_CC2,
+
+	VP_A1X,
+	VP_A1Y,
+
+	VP_A1C,
+	VP_A1T,
+
+	VP_A2X,
+	VP_A2Y,
+
+	VP_A2C,
+	VP_A2T,
+
+	VP_A3X,
+	VP_A3Y,
+
+	VP_A3C,
+	VP_A3T,
+
+	VP_VRR,
+	VP_AWT,
+
+	VP_VTM, /* 0x130 */
+};
+
+#define VP_VCFG_VID_EN			(1 << 0)
+
+#define VP_DCFG_DAC_VREF		(1 << 26)
+#define VP_DCFG_GV_GAM			(1 << 21)
+#define VP_DCFG_VG_CK			(1 << 20)
+#define VP_DCFG_CRT_SYNC_SKW_DEFAULT	(1 << 16)
+#define VP_DCFG_CRT_SYNC_SKW		((1 << 14) | (1 << 15) | (1 << 16))
+#define VP_DCFG_CRT_VSYNC_POL		(1 << 9)
+#define VP_DCFG_CRT_HSYNC_POL		(1 << 8)
+#define VP_DCFG_FP_DATA_EN		(1 << 7)	/* undocumented */
+#define VP_DCFG_FP_PWR_EN		(1 << 6)	/* undocumented */
+#define VP_DCFG_DAC_BL_EN		(1 << 3)
+#define VP_DCFG_VSYNC_EN		(1 << 2)
+#define VP_DCFG_HSYNC_EN		(1 << 1)
+#define VP_DCFG_CRT_EN			(1 << 0)
+
+#define VP_MISC_GAM_EN			(1 << 0)
+#define VP_MISC_DACPWRDN		(1 << 10)
+#define VP_MISC_APWRDN			(1 << 11)
+
+
+/*
+ * Flat Panel registers (table 6-55).
+ * Also 64 bit registers; see above note about 32-bit handling.
+ */
+
+/* we're actually in the VP register space, starting at address 0x400 */
+#define VP_FP_START		0x400
+
+enum fp_registers {
+	FP_PT1 = 0,
+	FP_PT2,
+
+	FP_PM,
+	FP_DFC,
+
+	FP_BLFSR,
+	FP_RLFSR,
+
+	FP_FMI,
+	FP_FMD,
+
+	FP_RSVD_0,
+	FP_DCA,
+
+	FP_DMD,
+	FP_CRC,
+
+	FP_FBB, /* 0x460 */
+};
+
+#define FP_PT1_VSIZE_SHIFT		16		/* undocumented? */
+#define FP_PT1_VSIZE_MASK		0x7FF0000	/* undocumented? */
+
+#define FP_PT2_HSP			(1 << 22)
+#define FP_PT2_VSP			(1 << 23)
+
+#define FP_PM_P				(1 << 24)       /* panel power on */
+#define FP_PM_PANEL_PWR_UP		(1 << 3)        /* r/o */
+#define FP_PM_PANEL_PWR_DOWN		(1 << 2)        /* r/o */
+#define FP_PM_PANEL_OFF			(1 << 1)        /* r/o */
+#define FP_PM_PANEL_ON			(1 << 0)        /* r/o */
+
+#define FP_DFC_NFI			((1 << 4) | (1 << 5) | (1 << 6))
+
+
+/* register access functions */
+
+static inline uint32_t read_gp(struct gxfb_par *par, int reg)
+{
+	return readl(par->gp_regs + 4*reg);
+}
+
+static inline void write_gp(struct gxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->gp_regs + 4*reg);
+}
+
+static inline uint32_t read_dc(struct gxfb_par *par, int reg)
+{
+	return readl(par->dc_regs + 4*reg);
+}
+
+static inline void write_dc(struct gxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->dc_regs + 4*reg);
+}
+
+static inline uint32_t read_vp(struct gxfb_par *par, int reg)
+{
+	return readl(par->vid_regs + 8*reg);
+}
+
+static inline void write_vp(struct gxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->vid_regs + 8*reg);
+}
+
+static inline uint32_t read_fp(struct gxfb_par *par, int reg)
+{
+	return readl(par->vid_regs + 8*reg + VP_FP_START);
+}
+
+static inline void write_fp(struct gxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->vid_regs + 8*reg + VP_FP_START);
+}
+
+
+/* MSRs are defined in linux/cs5535.h; their bitfields are here */
+
+#define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3	(1 << 3)
+#define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2	(1 << 2)
+#define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2	(1 << 1)
+
+#define MSR_GLCP_DOTPLL_LOCK		(1 << 25)	/* r/o */
+#define MSR_GLCP_DOTPLL_BYPASS		(1 << 15)
+#define MSR_GLCP_DOTPLL_DOTRESET	(1 << 0)
+
+#define MSR_GX_MSR_PADSEL_MASK		0x3FFFFFFF	/* undocumented? */
+#define MSR_GX_MSR_PADSEL_TFT		0x1FFFFFFF	/* undocumented? */
+
+#define MSR_GX_GLD_MSR_CONFIG_FP	(1 << 3)
+
+#endif
diff --git a/drivers/video/fbdev/geode/gxfb_core.c b/drivers/video/fbdev/geode/gxfb_core.c
new file mode 100644
index 000000000000..1790f14bab15
--- /dev/null
+++ b/drivers/video/fbdev/geode/gxfb_core.c
@@ -0,0 +1,547 @@
+/*
+ * Geode GX framebuffer driver.
+ *
+ *   Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License as published by the
+ *   Free Software Foundation; either version 2 of the License, or (at your
+ *   option) any later version.
+ *
+ *
+ * This driver assumes that the BIOS has created a virtual PCI device header
+ * for the video device. The PCI header is assumed to contain the following
+ * BARs:
+ *
+ *    BAR0 - framebuffer memory
+ *    BAR1 - graphics processor registers
+ *    BAR2 - display controller registers
+ *    BAR3 - video processor and flat panel control registers.
+ *
+ * 16 MiB of framebuffer memory is assumed to be available.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/suspend.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/cs5535.h>
+
+#include "gxfb.h"
+
+static char *mode_option;
+static int vram;
+static int vt_switch;
+
+/* Modes relevant to the GX (taken from modedb.c) */
+static struct fb_videomode gx_modedb[] = {
+	/* 640x480-60 VESA */
+	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 640x480-75 VESA */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 640x480-85 VESA */
+	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-60 VESA */
+	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-75 VESA */
+	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-85 VESA */
+	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-60 VESA */
+	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-75 VESA */
+	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-85 VESA */
+	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x960-60 VESA */
+	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x960-85 VESA */
+	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-60 VESA */
+	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-75 VESA */
+	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-85 VESA */
+	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1600x1200-60 VESA */
+	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1600x1200-75 VESA */
+	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1600x1200-85 VESA */
+	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+#ifdef CONFIG_OLPC
+#include <asm/olpc.h>
+
+static struct fb_videomode gx_dcon_modedb[] = {
+	/* The only mode the DCON has is 1200x900 */
+	{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 }
+};
+
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
+{
+	if (olpc_has_dcon()) {
+		*modedb = (struct fb_videomode *) gx_dcon_modedb;
+		*size = ARRAY_SIZE(gx_dcon_modedb);
+	} else {
+		*modedb = (struct fb_videomode *) gx_modedb;
+		*size = ARRAY_SIZE(gx_modedb);
+	}
+}
+
+#else
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
+{
+	*modedb = (struct fb_videomode *) gx_modedb;
+	*size = ARRAY_SIZE(gx_modedb);
+}
+#endif
+
+static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	if (var->xres > 1600 || var->yres > 1200)
+		return -EINVAL;
+	if ((var->xres > 1280 || var->yres > 1024) && var->bits_per_pixel > 16)
+		return -EINVAL;
+
+	if (var->bits_per_pixel == 32) {
+		var->red.offset   = 16; var->red.length   = 8;
+		var->green.offset =  8; var->green.length = 8;
+		var->blue.offset  =  0; var->blue.length  = 8;
+	} else if (var->bits_per_pixel == 16) {
+		var->red.offset   = 11; var->red.length   = 5;
+		var->green.offset =  5; var->green.length = 6;
+		var->blue.offset  =  0; var->blue.length  = 5;
+	} else if (var->bits_per_pixel == 8) {
+		var->red.offset   = 0; var->red.length   = 8;
+		var->green.offset = 0; var->green.length = 8;
+		var->blue.offset  = 0; var->blue.length  = 8;
+	} else
+		return -EINVAL;
+	var->transp.offset = 0; var->transp.length = 0;
+
+	/* Enough video memory? */
+	if (gx_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
+		return -EINVAL;
+
+	/* FIXME: Check timing parameters here? */
+
+	return 0;
+}
+
+static int gxfb_set_par(struct fb_info *info)
+{
+	if (info->var.bits_per_pixel > 8)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel);
+
+	gx_set_mode(info);
+
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 *pal = info->pseudo_palette;
+		u32 v;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		v  = chan_to_field(red, &info->var.red);
+		v |= chan_to_field(green, &info->var.green);
+		v |= chan_to_field(blue, &info->var.blue);
+
+		pal[regno] = v;
+	} else {
+		if (regno >= 256)
+			return -EINVAL;
+
+		gx_set_hw_palette_reg(info, regno, red, green, blue);
+	}
+
+	return 0;
+}
+
+static int gxfb_blank(int blank_mode, struct fb_info *info)
+{
+	return gx_blank_display(info, blank_mode);
+}
+
+static int gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+{
+	struct gxfb_par *par = info->par;
+	int ret;
+
+	ret = pci_enable_device(dev);
+	if (ret < 0)
+		return ret;
+
+	ret = pci_request_region(dev, 3, "gxfb (video processor)");
+	if (ret < 0)
+		return ret;
+	par->vid_regs = pci_ioremap_bar(dev, 3);
+	if (!par->vid_regs)
+		return -ENOMEM;
+
+	ret = pci_request_region(dev, 2, "gxfb (display controller)");
+	if (ret < 0)
+		return ret;
+	par->dc_regs = pci_ioremap_bar(dev, 2);
+	if (!par->dc_regs)
+		return -ENOMEM;
+
+	ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
+	if (ret < 0)
+		return ret;
+	par->gp_regs = pci_ioremap_bar(dev, 1);
+
+	if (!par->gp_regs)
+		return -ENOMEM;
+
+	ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
+	if (ret < 0)
+		return ret;
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = vram ? vram : gx_frame_buffer_size();
+	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+	if (!info->screen_base)
+		return -ENOMEM;
+
+	/* Set the 16MiB aligned base address of the graphics memory region
+	 * in the display controller */
+
+	write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000);
+
+	dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n",
+		 info->fix.smem_len / 1024, info->fix.smem_start);
+
+	return 0;
+}
+
+static struct fb_ops gxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= gxfb_check_var,
+	.fb_set_par	= gxfb_set_par,
+	.fb_setcolreg	= gxfb_setcolreg,
+	.fb_blank       = gxfb_blank,
+	/* No HW acceleration for now. */
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static struct fb_info *gxfb_init_fbinfo(struct device *dev)
+{
+	struct gxfb_par *par;
+	struct fb_info *info;
+
+	/* Alloc enough space for the pseudo palette. */
+	info = framebuffer_alloc(sizeof(struct gxfb_par) + sizeof(u32) * 16,
+			dev);
+	if (!info)
+		return NULL;
+
+	par = info->par;
+
+	strcpy(info->fix.id, "Geode GX");
+
+	info->fix.type		= FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux	= 0;
+	info->fix.xpanstep	= 0;
+	info->fix.ypanstep	= 0;
+	info->fix.ywrapstep	= 0;
+	info->fix.accel		= FB_ACCEL_NONE;
+
+	info->var.nonstd	= 0;
+	info->var.activate	= FB_ACTIVATE_NOW;
+	info->var.height	= -1;
+	info->var.width	= -1;
+	info->var.accel_flags = 0;
+	info->var.vmode	= FB_VMODE_NONINTERLACED;
+
+	info->fbops		= &gxfb_ops;
+	info->flags		= FBINFO_DEFAULT;
+	info->node		= -1;
+
+	info->pseudo_palette	= (void *)par + sizeof(struct gxfb_par);
+
+	info->var.grayscale	= 0;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		framebuffer_release(info);
+		return NULL;
+	}
+
+	return info;
+}
+
+#ifdef CONFIG_PM
+static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+
+	if (state.event == PM_EVENT_SUSPEND) {
+		console_lock();
+		gx_powerdown(info);
+		fb_set_suspend(info, 1);
+		console_unlock();
+	}
+
+	/* there's no point in setting PCI states; we emulate PCI, so
+	 * we don't end up getting power savings anyways */
+
+	return 0;
+}
+
+static int gxfb_resume(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	int ret;
+
+	console_lock();
+	ret = gx_powerup(info);
+	if (ret) {
+		printk(KERN_ERR "gxfb:  power up failed!\n");
+		return ret;
+	}
+
+	fb_set_suspend(info, 0);
+	console_unlock();
+	return 0;
+}
+#endif
+
+static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct gxfb_par *par;
+	struct fb_info *info;
+	int ret;
+	unsigned long val;
+
+	struct fb_videomode *modedb_ptr;
+	unsigned int modedb_size;
+
+	info = gxfb_init_fbinfo(&pdev->dev);
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+
+	if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
+		dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
+		goto err;
+	}
+
+	/* Figure out if this is a TFT or CRT part */
+
+	rdmsrl(MSR_GX_GLD_MSR_CONFIG, val);
+
+	if ((val & MSR_GX_GLD_MSR_CONFIG_FP) == MSR_GX_GLD_MSR_CONFIG_FP)
+		par->enable_crt = 0;
+	else
+		par->enable_crt = 1;
+
+	get_modedb(&modedb_ptr, &modedb_size);
+	ret = fb_find_mode(&info->var, info, mode_option,
+			   modedb_ptr, modedb_size, NULL, 16);
+	if (ret == 0 || ret == 4) {
+		dev_err(&pdev->dev, "could not find valid video mode\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+
+	/* Clear the frame buffer of garbage. */
+        memset_io(info->screen_base, 0, info->fix.smem_len);
+
+	gxfb_check_var(&info->var, info);
+	gxfb_set_par(info);
+
+	pm_set_vt_switch(vt_switch);
+
+	if (register_framebuffer(info) < 0) {
+		ret = -EINVAL;
+		goto err;
+	}
+	pci_set_drvdata(pdev, info);
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	return 0;
+
+  err:
+	if (info->screen_base) {
+		iounmap(info->screen_base);
+		pci_release_region(pdev, 0);
+	}
+	if (par->vid_regs) {
+		iounmap(par->vid_regs);
+		pci_release_region(pdev, 3);
+	}
+	if (par->dc_regs) {
+		iounmap(par->dc_regs);
+		pci_release_region(pdev, 2);
+	}
+	if (par->gp_regs) {
+		iounmap(par->gp_regs);
+		pci_release_region(pdev, 1);
+	}
+
+	if (info) {
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return ret;
+}
+
+static void gxfb_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct gxfb_par *par = info->par;
+
+	unregister_framebuffer(info);
+
+	iounmap((void __iomem *)info->screen_base);
+	pci_release_region(pdev, 0);
+
+	iounmap(par->vid_regs);
+	pci_release_region(pdev, 3);
+
+	iounmap(par->dc_regs);
+	pci_release_region(pdev, 2);
+
+	iounmap(par->gp_regs);
+	pci_release_region(pdev, 1);
+
+	fb_dealloc_cmap(&info->cmap);
+
+	framebuffer_release(info);
+}
+
+static struct pci_device_id gxfb_id_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, gxfb_id_table);
+
+static struct pci_driver gxfb_driver = {
+	.name		= "gxfb",
+	.id_table	= gxfb_id_table,
+	.probe		= gxfb_probe,
+	.remove		= gxfb_remove,
+#ifdef CONFIG_PM
+	.suspend	= gxfb_suspend,
+	.resume		= gxfb_resume,
+#endif
+};
+
+#ifndef MODULE
+static int __init gxfb_setup(char *options)
+{
+
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+
+		mode_option = opt;
+	}
+
+	return 0;
+}
+#endif
+
+static int __init gxfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("gxfb", &option))
+		return -ENODEV;
+
+	gxfb_setup(option);
+#endif
+	return pci_register_driver(&gxfb_driver);
+}
+
+static void __exit gxfb_cleanup(void)
+{
+	pci_unregister_driver(&gxfb_driver);
+}
+
+module_init(gxfb_init);
+module_exit(gxfb_cleanup);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram, "video memory size");
+
+module_param(vt_switch, int, 0);
+MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");
+
+MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/geode/lxfb.h b/drivers/video/fbdev/geode/lxfb.h
new file mode 100644
index 000000000000..cfcd8090f313
--- /dev/null
+++ b/drivers/video/fbdev/geode/lxfb.h
@@ -0,0 +1,452 @@
+/* Geode LX framebuffer driver
+ *
+ * Copyright (C) 2006-2007, Advanced Micro Devices,Inc.
+ * Copyright (c) 2008  Andres Salomon <dilinger@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _LXFB_H_
+#define _LXFB_H_
+
+#include <linux/fb.h>
+
+#define GP_REG_COUNT	(0x7c / 4)
+#define DC_REG_COUNT	(0xf0 / 4)
+#define VP_REG_COUNT	(0x158 / 8)
+#define FP_REG_COUNT	(0x60 / 8)
+
+#define DC_PAL_COUNT	0x104
+#define DC_HFILT_COUNT	0x100
+#define DC_VFILT_COUNT	0x100
+#define VP_COEFF_SIZE	0x1000
+#define VP_PAL_COUNT	0x100
+
+#define OUTPUT_CRT   0x01
+#define OUTPUT_PANEL 0x02
+
+struct lxfb_par {
+	int output;
+
+	void __iomem *gp_regs;
+	void __iomem *dc_regs;
+	void __iomem *vp_regs;
+#ifdef CONFIG_PM
+	int powered_down;
+
+	/* register state, for power mgmt functionality */
+	struct {
+		uint64_t padsel;
+		uint64_t dotpll;
+		uint64_t dfglcfg;
+		uint64_t dcspare;
+	} msr;
+
+	uint32_t gp[GP_REG_COUNT];
+	uint32_t dc[DC_REG_COUNT];
+	uint64_t vp[VP_REG_COUNT];
+	uint64_t fp[FP_REG_COUNT];
+
+	uint32_t dc_pal[DC_PAL_COUNT];
+	uint32_t vp_pal[VP_PAL_COUNT];
+	uint32_t hcoeff[DC_HFILT_COUNT * 2];
+	uint32_t vcoeff[DC_VFILT_COUNT];
+	uint32_t vp_coeff[VP_COEFF_SIZE / 4];
+#endif
+};
+
+static inline unsigned int lx_get_pitch(unsigned int xres, int bpp)
+{
+	return (((xres * (bpp >> 3)) + 7) & ~7);
+}
+
+void lx_set_mode(struct fb_info *);
+unsigned int lx_framebuffer_size(void);
+int lx_blank_display(struct fb_info *, int);
+void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
+			unsigned int, unsigned int);
+
+#ifdef CONFIG_PM
+int lx_powerdown(struct fb_info *info);
+int lx_powerup(struct fb_info *info);
+#endif
+
+
+/* Graphics Processor registers (table 6-29 from the data book) */
+enum gp_registers {
+	GP_DST_OFFSET = 0,
+	GP_SRC_OFFSET,
+	GP_STRIDE,
+	GP_WID_HEIGHT,
+
+	GP_SRC_COLOR_FG,
+	GP_SRC_COLOR_BG,
+	GP_PAT_COLOR_0,
+	GP_PAT_COLOR_1,
+
+	GP_PAT_COLOR_2,
+	GP_PAT_COLOR_3,
+	GP_PAT_COLOR_4,
+	GP_PAT_COLOR_5,
+
+	GP_PAT_DATA_0,
+	GP_PAT_DATA_1,
+	GP_RASTER_MODE,
+	GP_VECTOR_MODE,
+
+	GP_BLT_MODE,
+	GP_BLT_STATUS,
+	GP_HST_SRC,
+	GP_BASE_OFFSET,
+
+	GP_CMD_TOP,
+	GP_CMD_BOT,
+	GP_CMD_READ,
+	GP_CMD_WRITE,
+
+	GP_CH3_OFFSET,
+	GP_CH3_MODE_STR,
+	GP_CH3_WIDHI,
+	GP_CH3_HSRC,
+
+	GP_LUT_INDEX,
+	GP_LUT_DATA,
+	GP_INT_CNTRL, /* 0x78 */
+};
+
+#define GP_BLT_STATUS_CE		(1 << 4)	/* cmd buf empty */
+#define GP_BLT_STATUS_PB		(1 << 0)	/* primitive busy */
+
+
+/* Display Controller registers (table 6-47 from the data book) */
+enum dc_registers {
+	DC_UNLOCK = 0,
+	DC_GENERAL_CFG,
+	DC_DISPLAY_CFG,
+	DC_ARB_CFG,
+
+	DC_FB_ST_OFFSET,
+	DC_CB_ST_OFFSET,
+	DC_CURS_ST_OFFSET,
+	DC_RSVD_0,
+
+	DC_VID_Y_ST_OFFSET,
+	DC_VID_U_ST_OFFSET,
+	DC_VID_V_ST_OFFSET,
+	DC_DV_TOP,
+
+	DC_LINE_SIZE,
+	DC_GFX_PITCH,
+	DC_VID_YUV_PITCH,
+	DC_RSVD_1,
+
+	DC_H_ACTIVE_TIMING,
+	DC_H_BLANK_TIMING,
+	DC_H_SYNC_TIMING,
+	DC_RSVD_2,
+
+	DC_V_ACTIVE_TIMING,
+	DC_V_BLANK_TIMING,
+	DC_V_SYNC_TIMING,
+	DC_FB_ACTIVE,
+
+	DC_CURSOR_X,
+	DC_CURSOR_Y,
+	DC_RSVD_3,
+	DC_LINE_CNT,
+
+	DC_PAL_ADDRESS,
+	DC_PAL_DATA,
+	DC_DFIFO_DIAG,
+	DC_CFIFO_DIAG,
+
+	DC_VID_DS_DELTA,
+	DC_GLIU0_MEM_OFFSET,
+	DC_DV_CTL,
+	DC_DV_ACCESS,
+
+	DC_GFX_SCALE,
+	DC_IRQ_FILT_CTL,
+	DC_FILT_COEFF1,
+	DC_FILT_COEFF2,
+
+	DC_VBI_EVEN_CTL,
+	DC_VBI_ODD_CTL,
+	DC_VBI_HOR,
+	DC_VBI_LN_ODD,
+
+	DC_VBI_LN_EVEN,
+	DC_VBI_PITCH,
+	DC_CLR_KEY,
+	DC_CLR_KEY_MASK,
+
+	DC_CLR_KEY_X,
+	DC_CLR_KEY_Y,
+	DC_IRQ,
+	DC_RSVD_4,
+
+	DC_RSVD_5,
+	DC_GENLK_CTL,
+	DC_VID_EVEN_Y_ST_OFFSET,
+	DC_VID_EVEN_U_ST_OFFSET,
+
+	DC_VID_EVEN_V_ST_OFFSET,
+	DC_V_ACTIVE_EVEN_TIMING,
+	DC_V_BLANK_EVEN_TIMING,
+	DC_V_SYNC_EVEN_TIMING,	/* 0xec */
+};
+
+#define DC_UNLOCK_LOCK			0x00000000
+#define DC_UNLOCK_UNLOCK		0x00004758	/* magic value */
+
+#define DC_GENERAL_CFG_FDTY		(1 << 17)
+#define DC_GENERAL_CFG_DFHPEL_SHIFT	(12)
+#define DC_GENERAL_CFG_DFHPSL_SHIFT	(8)
+#define DC_GENERAL_CFG_VGAE		(1 << 7)
+#define DC_GENERAL_CFG_DECE		(1 << 6)
+#define DC_GENERAL_CFG_CMPE		(1 << 5)
+#define DC_GENERAL_CFG_VIDE		(1 << 3)
+#define DC_GENERAL_CFG_DFLE		(1 << 0)
+
+#define DC_DISPLAY_CFG_VISL		(1 << 27)
+#define DC_DISPLAY_CFG_PALB		(1 << 25)
+#define DC_DISPLAY_CFG_DCEN		(1 << 24)
+#define DC_DISPLAY_CFG_DISP_MODE_24BPP	(1 << 9)
+#define DC_DISPLAY_CFG_DISP_MODE_16BPP	(1 << 8)
+#define DC_DISPLAY_CFG_DISP_MODE_8BPP	(0)
+#define DC_DISPLAY_CFG_TRUP		(1 << 6)
+#define DC_DISPLAY_CFG_VDEN		(1 << 4)
+#define DC_DISPLAY_CFG_GDEN		(1 << 3)
+#define DC_DISPLAY_CFG_TGEN		(1 << 0)
+
+#define DC_DV_TOP_DV_TOP_EN		(1 << 0)
+
+#define DC_DV_CTL_DV_LINE_SIZE		((1 << 10) | (1 << 11))
+#define DC_DV_CTL_DV_LINE_SIZE_1K	(0)
+#define DC_DV_CTL_DV_LINE_SIZE_2K	(1 << 10)
+#define DC_DV_CTL_DV_LINE_SIZE_4K	(1 << 11)
+#define DC_DV_CTL_DV_LINE_SIZE_8K	((1 << 10) | (1 << 11))
+#define DC_DV_CTL_CLEAR_DV_RAM		(1 << 0)
+
+#define DC_IRQ_FILT_CTL_H_FILT_SEL	(1 << 10)
+
+#define DC_CLR_KEY_CLR_KEY_EN		(1 << 24)
+
+#define DC_IRQ_VIP_VSYNC_IRQ_STATUS	(1 << 21)	/* undocumented? */
+#define DC_IRQ_STATUS			(1 << 20)	/* undocumented? */
+#define DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK	(1 << 1)
+#define DC_IRQ_MASK			(1 << 0)
+
+#define DC_GENLK_CTL_FLICK_SEL_MASK	(0x0F << 28)
+#define DC_GENLK_CTL_ALPHA_FLICK_EN	(1 << 25)
+#define DC_GENLK_CTL_FLICK_EN		(1 << 24)
+#define DC_GENLK_CTL_GENLK_EN		(1 << 18)
+
+
+/*
+ * Video Processor registers (table 6-71).
+ * There is space for 64 bit values, but we never use more than the
+ * lower 32 bits.  The actual register save/restore code only bothers
+ * to restore those 32 bits.
+ */
+enum vp_registers {
+	VP_VCFG = 0,
+	VP_DCFG,
+
+	VP_VX,
+	VP_VY,
+
+	VP_SCL,
+	VP_VCK,
+
+	VP_VCM,
+	VP_PAR,
+
+	VP_PDR,
+	VP_SLR,
+
+	VP_MISC,
+	VP_CCS,
+
+	VP_VYS,
+	VP_VXS,
+
+	VP_RSVD_0,
+	VP_VDC,
+
+	VP_RSVD_1,
+	VP_CRC,
+
+	VP_CRC32,
+	VP_VDE,
+
+	VP_CCK,
+	VP_CCM,
+
+	VP_CC1,
+	VP_CC2,
+
+	VP_A1X,
+	VP_A1Y,
+
+	VP_A1C,
+	VP_A1T,
+
+	VP_A2X,
+	VP_A2Y,
+
+	VP_A2C,
+	VP_A2T,
+
+	VP_A3X,
+	VP_A3Y,
+
+	VP_A3C,
+	VP_A3T,
+
+	VP_VRR,
+	VP_AWT,
+
+	VP_VTM,
+	VP_VYE,
+
+	VP_A1YE,
+	VP_A2YE,
+
+	VP_A3YE,	/* 0x150 */
+
+	VP_VCR = 0x1000, /* 0x1000 - 0x1fff */
+};
+
+#define VP_VCFG_VID_EN			(1 << 0)
+
+#define VP_DCFG_GV_GAM			(1 << 21)
+#define VP_DCFG_PWR_SEQ_DELAY		((1 << 17) | (1 << 18) | (1 << 19))
+#define VP_DCFG_PWR_SEQ_DELAY_DEFAULT	(1 << 19)	/* undocumented */
+#define VP_DCFG_CRT_SYNC_SKW		((1 << 14) | (1 << 15) | (1 << 16))
+#define VP_DCFG_CRT_SYNC_SKW_DEFAULT	(1 << 16)
+#define VP_DCFG_CRT_VSYNC_POL		(1 << 9)
+#define VP_DCFG_CRT_HSYNC_POL		(1 << 8)
+#define VP_DCFG_DAC_BL_EN		(1 << 3)
+#define VP_DCFG_VSYNC_EN		(1 << 2)
+#define VP_DCFG_HSYNC_EN		(1 << 1)
+#define VP_DCFG_CRT_EN			(1 << 0)
+
+#define VP_MISC_APWRDN			(1 << 11)
+#define VP_MISC_DACPWRDN		(1 << 10)
+#define VP_MISC_BYP_BOTH		(1 << 0)
+
+
+/*
+ * Flat Panel registers (table 6-71).
+ * Also 64 bit registers; see above note about 32-bit handling.
+ */
+
+/* we're actually in the VP register space, starting at address 0x400 */
+#define VP_FP_START	0x400
+
+enum fp_registers {
+	FP_PT1 = 0,
+	FP_PT2,
+
+	FP_PM,
+	FP_DFC,
+
+	FP_RSVD_0,
+	FP_RSVD_1,
+
+	FP_RSVD_2,
+	FP_RSVD_3,
+
+	FP_RSVD_4,
+	FP_DCA,
+
+	FP_DMD,
+	FP_CRC, /* 0x458 */
+};
+
+#define FP_PT2_HSP			(1 << 22)
+#define FP_PT2_VSP			(1 << 23)
+#define FP_PT2_SCRC			(1 << 27)	/* shfclk free */
+
+#define FP_PM_P				(1 << 24)	/* panel power ctl */
+#define FP_PM_PANEL_PWR_UP		(1 << 3)	/* r/o */
+#define FP_PM_PANEL_PWR_DOWN		(1 << 2)	/* r/o */
+#define FP_PM_PANEL_OFF			(1 << 1)	/* r/o */
+#define FP_PM_PANEL_ON			(1 << 0)	/* r/o */
+
+#define FP_DFC_BC			((1 << 4) | (1 << 5) | (1 << 6))
+
+
+/* register access functions */
+
+static inline uint32_t read_gp(struct lxfb_par *par, int reg)
+{
+	return readl(par->gp_regs + 4*reg);
+}
+
+static inline void write_gp(struct lxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->gp_regs + 4*reg);
+}
+
+static inline uint32_t read_dc(struct lxfb_par *par, int reg)
+{
+	return readl(par->dc_regs + 4*reg);
+}
+
+static inline void write_dc(struct lxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->dc_regs + 4*reg);
+}
+
+static inline uint32_t read_vp(struct lxfb_par *par, int reg)
+{
+	return readl(par->vp_regs + 8*reg);
+}
+
+static inline void write_vp(struct lxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->vp_regs + 8*reg);
+}
+
+static inline uint32_t read_fp(struct lxfb_par *par, int reg)
+{
+	return readl(par->vp_regs + 8*reg + VP_FP_START);
+}
+
+static inline void write_fp(struct lxfb_par *par, int reg, uint32_t val)
+{
+	writel(val, par->vp_regs + 8*reg + VP_FP_START);
+}
+
+
+/* MSRs are defined in linux/cs5535.h; their bitfields are here */
+
+#define MSR_GLCP_DOTPLL_LOCK		(1 << 25)	/* r/o */
+#define MSR_GLCP_DOTPLL_HALFPIX		(1 << 24)
+#define MSR_GLCP_DOTPLL_BYPASS		(1 << 15)
+#define MSR_GLCP_DOTPLL_DOTRESET	(1 << 0)
+
+/* note: this is actually the VP's GLD_MSR_CONFIG */
+#define MSR_LX_GLD_MSR_CONFIG_FMT	((1 << 3) | (1 << 4) | (1 << 5))
+#define MSR_LX_GLD_MSR_CONFIG_FMT_FP	(1 << 3)
+#define MSR_LX_GLD_MSR_CONFIG_FMT_CRT	(0)
+#define MSR_LX_GLD_MSR_CONFIG_FPC	(1 << 15)	/* FP *and* CRT */
+
+#define MSR_LX_MSR_PADSEL_TFT_SEL_LOW	0xDFFFFFFF	/* ??? */
+#define MSR_LX_MSR_PADSEL_TFT_SEL_HIGH	0x0000003F	/* ??? */
+
+#define MSR_LX_SPARE_MSR_DIS_CFIFO_HGO	(1 << 11)	/* undocumented */
+#define MSR_LX_SPARE_MSR_VFIFO_ARB_SEL	(1 << 10)	/* undocumented */
+#define MSR_LX_SPARE_MSR_WM_LPEN_OVRD	(1 << 9)	/* undocumented */
+#define MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M	(1 << 8)	/* undocumented */
+#define MSR_LX_SPARE_MSR_DIS_INIT_V_PRI	(1 << 7)	/* undocumented */
+#define MSR_LX_SPARE_MSR_DIS_VIFO_WM	(1 << 6)
+#define MSR_LX_SPARE_MSR_DIS_CWD_CHECK	(1 << 5)	/* undocumented */
+#define MSR_LX_SPARE_MSR_PIX8_PAN_FIX	(1 << 4)	/* undocumented */
+#define MSR_LX_SPARE_MSR_FIRST_REQ_MASK	(1 << 1)	/* undocumented */
+
+#endif
diff --git a/drivers/video/fbdev/geode/lxfb_core.c b/drivers/video/fbdev/geode/lxfb_core.c
new file mode 100644
index 000000000000..9e1d19d673a1
--- /dev/null
+++ b/drivers/video/fbdev/geode/lxfb_core.c
@@ -0,0 +1,683 @@
+/*
+ * Geode LX framebuffer driver.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Built from gxfb (which is Copyright (C) 2006 Arcom Control Systems Ltd.)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/console.h>
+#include <linux/mm.h>
+#include <linux/suspend.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+
+#include "lxfb.h"
+
+static char *mode_option;
+static int noclear, nopanel, nocrt;
+static int vram;
+static int vt_switch;
+
+/* Most of these modes are sorted in ascending order, but
+ * since the first entry in this table is the "default" mode,
+ * we try to make it something sane - 640x480-60 is sane
+ */
+
+static struct fb_videomode geode_modedb[] = {
+	/* 640x480-60 */
+	{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 640x400-70 */
+	{ NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2,
+	  FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 640x480-70 */
+	{ NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 640x480-72 */
+	{ NULL, 72, 640, 480, 32102, 120, 16, 20, 1, 40, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 640x480-75 */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 640x480-85 */
+	{ NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 640x480-90 */
+	{ NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 640x480-100 */
+	{ NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 640x480-60 */
+	{ NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-56 */
+	{ NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-60 */
+	{ NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-70 */
+	{ NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-72 */
+	{ NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-75 */
+	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-85 */
+	{ NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-90 */
+	{ NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-100 */
+	{ NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 800x600-60 */
+	{ NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-60 */
+	{ NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-70 */
+	{ NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-72 */
+	{ NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-75 */
+	{ NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-85 */
+	{ NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-90 */
+	{ NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-100 */
+	{ NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1024x768-60 */
+	{ NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-60 */
+	{ NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-70 */
+	{ NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-72 */
+	{ NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-75 */
+	{ NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-85 */
+	{ NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-90 */
+	{ NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-100 */
+	{ NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1152x864-60 */
+	{ NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-60 */
+	{ NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-70 */
+	{ NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-72 */
+	{ NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-75 */
+	{ NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-85 */
+	{ NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-90 */
+	{ NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-100 */
+	{ NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1280x1024-60 */
+	{ NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-60 */
+	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-70 */
+	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-72 */
+	{ NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-75 */
+	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-85 */
+	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-90 */
+	{ NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-100 */
+	{ NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1600x1200-60 */
+	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 },
+	/* 1920x1440-60 */
+	{ NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1920x1440-70 */
+	{ NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1920x1440-72 */
+	{ NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1920x1440-75 */
+	{ NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+	/* 1920x1440-85 */
+	{ NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3,
+	  0, FB_VMODE_NONINTERLACED, 0 },
+};
+
+#ifdef CONFIG_OLPC
+#include <asm/olpc.h>
+
+static struct fb_videomode olpc_dcon_modedb[] = {
+	/* The only mode the DCON has is 1200x900 */
+	{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0 }
+};
+
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
+{
+	if (olpc_has_dcon()) {
+		*modedb = (struct fb_videomode *) olpc_dcon_modedb;
+		*size = ARRAY_SIZE(olpc_dcon_modedb);
+	} else {
+		*modedb = (struct fb_videomode *) geode_modedb;
+		*size = ARRAY_SIZE(geode_modedb);
+	}
+}
+
+#else
+static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
+{
+	*modedb = (struct fb_videomode *) geode_modedb;
+	*size = ARRAY_SIZE(geode_modedb);
+}
+#endif
+
+static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	if (var->xres > 1920 || var->yres > 1440)
+		return -EINVAL;
+
+	if (var->bits_per_pixel == 32) {
+		var->red.offset   = 16; var->red.length   = 8;
+		var->green.offset =  8; var->green.length = 8;
+		var->blue.offset  =  0; var->blue.length  = 8;
+	} else if (var->bits_per_pixel == 16) {
+		var->red.offset   = 11; var->red.length   = 5;
+		var->green.offset =  5; var->green.length = 6;
+		var->blue.offset  =  0; var->blue.length  = 5;
+	} else if (var->bits_per_pixel == 8) {
+		var->red.offset   = 0; var->red.length   = 8;
+		var->green.offset = 0; var->green.length = 8;
+		var->blue.offset  = 0; var->blue.length  = 8;
+	} else
+		return -EINVAL;
+
+	var->transp.offset = 0; var->transp.length = 0;
+
+	/* Enough video memory? */
+	if ((lx_get_pitch(var->xres, var->bits_per_pixel) * var->yres)
+	    > info->fix.smem_len)
+	  return -EINVAL;
+
+	return 0;
+}
+
+static int lxfb_set_par(struct fb_info *info)
+{
+	if (info->var.bits_per_pixel > 8)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = lx_get_pitch(info->var.xres,
+		info->var.bits_per_pixel);
+
+	lx_set_mode(info);
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int lxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 *pal = info->pseudo_palette;
+		u32 v;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		v  = chan_to_field(red, &info->var.red);
+		v |= chan_to_field(green, &info->var.green);
+		v |= chan_to_field(blue, &info->var.blue);
+
+		pal[regno] = v;
+	} else {
+		if (regno >= 256)
+			return -EINVAL;
+
+		lx_set_palette_reg(info, regno, red, green, blue);
+	}
+
+	return 0;
+}
+
+static int lxfb_blank(int blank_mode, struct fb_info *info)
+{
+	return lx_blank_display(info, blank_mode);
+}
+
+
+static int lxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+{
+	struct lxfb_par *par = info->par;
+	int ret;
+
+	ret = pci_enable_device(dev);
+
+	if (ret)
+		return ret;
+
+	ret = pci_request_region(dev, 0, "lxfb-framebuffer");
+
+	if (ret)
+		return ret;
+
+	ret = pci_request_region(dev, 1, "lxfb-gp");
+
+	if (ret)
+		return ret;
+
+	ret = pci_request_region(dev, 2, "lxfb-vg");
+
+	if (ret)
+		return ret;
+
+	ret = pci_request_region(dev, 3, "lxfb-vp");
+
+	if (ret)
+		return ret;
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = vram ? vram : lx_framebuffer_size();
+
+	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+
+	ret = -ENOMEM;
+
+	if (info->screen_base == NULL)
+		return ret;
+
+	par->gp_regs = pci_ioremap_bar(dev, 1);
+
+	if (par->gp_regs == NULL)
+		return ret;
+
+	par->dc_regs = pci_ioremap_bar(dev, 2);
+
+	if (par->dc_regs == NULL)
+		return ret;
+
+	par->vp_regs = pci_ioremap_bar(dev, 3);
+
+	if (par->vp_regs == NULL)
+		return ret;
+
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+	write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000);
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+
+	dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n",
+		 info->fix.smem_len / 1024, info->fix.smem_start);
+
+	return 0;
+}
+
+static struct fb_ops lxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= lxfb_check_var,
+	.fb_set_par	= lxfb_set_par,
+	.fb_setcolreg	= lxfb_setcolreg,
+	.fb_blank       = lxfb_blank,
+	/* No HW acceleration for now. */
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static struct fb_info *lxfb_init_fbinfo(struct device *dev)
+{
+	struct lxfb_par *par;
+	struct fb_info *info;
+
+	/* Alloc enough space for the pseudo palette. */
+	info = framebuffer_alloc(sizeof(struct lxfb_par) + sizeof(u32) * 16,
+				 dev);
+	if (!info)
+		return NULL;
+
+	par = info->par;
+
+	strcpy(info->fix.id, "Geode LX");
+
+	info->fix.type		= FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux	= 0;
+	info->fix.xpanstep	= 0;
+	info->fix.ypanstep	= 0;
+	info->fix.ywrapstep	= 0;
+	info->fix.accel		= FB_ACCEL_NONE;
+
+	info->var.nonstd	= 0;
+	info->var.activate	= FB_ACTIVATE_NOW;
+	info->var.height	= -1;
+	info->var.width	= -1;
+	info->var.accel_flags = 0;
+	info->var.vmode	= FB_VMODE_NONINTERLACED;
+
+	info->fbops		= &lxfb_ops;
+	info->flags		= FBINFO_DEFAULT;
+	info->node		= -1;
+
+	info->pseudo_palette	= (void *)par + sizeof(struct lxfb_par);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		framebuffer_release(info);
+		return NULL;
+	}
+
+	info->var.grayscale	= 0;
+
+	return info;
+}
+
+#ifdef CONFIG_PM
+static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+
+	if (state.event == PM_EVENT_SUSPEND) {
+		console_lock();
+		lx_powerdown(info);
+		fb_set_suspend(info, 1);
+		console_unlock();
+	}
+
+	/* there's no point in setting PCI states; we emulate PCI, so
+	 * we don't end up getting power savings anyways */
+
+	return 0;
+}
+
+static int lxfb_resume(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	int ret;
+
+	console_lock();
+	ret = lx_powerup(info);
+	if (ret) {
+		printk(KERN_ERR "lxfb:  power up failed!\n");
+		return ret;
+	}
+
+	fb_set_suspend(info, 0);
+	console_unlock();
+	return 0;
+}
+#else
+#define lxfb_suspend NULL
+#define lxfb_resume NULL
+#endif
+
+static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct lxfb_par *par;
+	struct fb_info *info;
+	int ret;
+
+	struct fb_videomode *modedb_ptr;
+	unsigned int modedb_size;
+
+	info = lxfb_init_fbinfo(&pdev->dev);
+
+	if (info == NULL)
+		return -ENOMEM;
+
+	par = info->par;
+
+	ret = lxfb_map_video_memory(info, pdev);
+
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"failed to map frame buffer or controller registers\n");
+		goto err;
+	}
+
+	/* Set up the desired outputs */
+
+	par->output = 0;
+	par->output |= (nopanel) ? 0 : OUTPUT_PANEL;
+	par->output |= (nocrt) ? 0 : OUTPUT_CRT;
+
+	/* Set up the mode database */
+
+	get_modedb(&modedb_ptr, &modedb_size);
+	ret = fb_find_mode(&info->var, info, mode_option,
+			   modedb_ptr, modedb_size, NULL, 16);
+
+	if (ret == 0 || ret == 4) {
+		dev_err(&pdev->dev, "could not find valid video mode\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* Clear the screen of garbage, unless noclear was specified,
+	 * in which case we assume the user knows what he is doing */
+
+	if (!noclear)
+		memset_io(info->screen_base, 0, info->fix.smem_len);
+
+	/* Set the mode */
+
+	lxfb_check_var(&info->var, info);
+	lxfb_set_par(info);
+
+	pm_set_vt_switch(vt_switch);
+
+	if (register_framebuffer(info) < 0) {
+		ret = -EINVAL;
+		goto err;
+	}
+	pci_set_drvdata(pdev, info);
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	return 0;
+
+err:
+	if (info->screen_base) {
+		iounmap(info->screen_base);
+		pci_release_region(pdev, 0);
+	}
+	if (par->gp_regs) {
+		iounmap(par->gp_regs);
+		pci_release_region(pdev, 1);
+	}
+	if (par->dc_regs) {
+		iounmap(par->dc_regs);
+		pci_release_region(pdev, 2);
+	}
+	if (par->vp_regs) {
+		iounmap(par->vp_regs);
+		pci_release_region(pdev, 3);
+	}
+
+	if (info) {
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+
+	return ret;
+}
+
+static void lxfb_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct lxfb_par *par = info->par;
+
+	unregister_framebuffer(info);
+
+	iounmap(info->screen_base);
+	pci_release_region(pdev, 0);
+
+	iounmap(par->gp_regs);
+	pci_release_region(pdev, 1);
+
+	iounmap(par->dc_regs);
+	pci_release_region(pdev, 2);
+
+	iounmap(par->vp_regs);
+	pci_release_region(pdev, 3);
+
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(info);
+}
+
+static struct pci_device_id lxfb_id_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_VIDEO) },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, lxfb_id_table);
+
+static struct pci_driver lxfb_driver = {
+	.name		= "lxfb",
+	.id_table	= lxfb_id_table,
+	.probe		= lxfb_probe,
+	.remove		= lxfb_remove,
+	.suspend	= lxfb_suspend,
+	.resume		= lxfb_resume,
+};
+
+#ifndef MODULE
+static int __init lxfb_setup(char *options)
+{
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+
+		if (!strcmp(opt, "noclear"))
+			noclear = 1;
+		else if (!strcmp(opt, "nopanel"))
+			nopanel = 1;
+		else if (!strcmp(opt, "nocrt"))
+			nocrt = 1;
+		else
+			mode_option = opt;
+	}
+
+	return 0;
+}
+#endif
+
+static int __init lxfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("lxfb", &option))
+		return -ENODEV;
+
+	lxfb_setup(option);
+#endif
+	return pci_register_driver(&lxfb_driver);
+}
+static void __exit lxfb_cleanup(void)
+{
+	pci_unregister_driver(&lxfb_driver);
+}
+
+module_init(lxfb_init);
+module_exit(lxfb_cleanup);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram, "video memory size");
+
+module_param(vt_switch, int, 0);
+MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");
+
+MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/geode/lxfb_ops.c b/drivers/video/fbdev/geode/lxfb_ops.c
new file mode 100644
index 000000000000..79e9abc72b83
--- /dev/null
+++ b/drivers/video/fbdev/geode/lxfb_ops.c
@@ -0,0 +1,845 @@
+/* Geode LX framebuffer driver
+ *
+ * Copyright (C) 2006-2007, Advanced Micro Devices,Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/cs5535.h>
+
+#include "lxfb.h"
+
+/* TODO
+ * Support panel scaling
+ * Add acceleration
+ * Add support for interlacing (TV out)
+ * Support compression
+ */
+
+/* This is the complete list of PLL frequencies that we can set -
+ * we will choose the closest match to the incoming clock.
+ * freq is the frequency of the dotclock * 1000 (for example,
+ * 24823 = 24.983 Mhz).
+ * pllval is the corresponding PLL value
+*/
+
+static const struct {
+  unsigned int pllval;
+  unsigned int freq;
+} pll_table[] = {
+  { 0x000131AC,   6231 },
+  { 0x0001215D,   6294 },
+  { 0x00011087,   6750 },
+  { 0x0001216C,   7081 },
+  { 0x0001218D,   7140 },
+  { 0x000110C9,   7800 },
+  { 0x00013147,   7875 },
+  { 0x000110A7,   8258 },
+  { 0x00012159,   8778 },
+  { 0x00014249,   8875 },
+  { 0x00010057,   9000 },
+  { 0x0001219A,   9472 },
+  { 0x00012158,   9792 },
+  { 0x00010045,  10000 },
+  { 0x00010089,  10791 },
+  { 0x000110E7,  11225 },
+  { 0x00012136,  11430 },
+  { 0x00013207,  12375 },
+  { 0x00012187,  12500 },
+  { 0x00014286,  14063 },
+  { 0x000110E5,  15016 },
+  { 0x00014214,  16250 },
+  { 0x00011105,  17045 },
+  { 0x000131E4,  18563 },
+  { 0x00013183,  18750 },
+  { 0x00014284,  19688 },
+  { 0x00011104,  20400 },
+  { 0x00016363,  23625 },
+  { 0x000031AC,  24923 },
+  { 0x0000215D,  25175 },
+  { 0x00001087,  27000 },
+  { 0x0000216C,  28322 },
+  { 0x0000218D,  28560 },
+  { 0x000010C9,  31200 },
+  { 0x00003147,  31500 },
+  { 0x000010A7,  33032 },
+  { 0x00002159,  35112 },
+  { 0x00004249,  35500 },
+  { 0x00000057,  36000 },
+  { 0x0000219A,  37889 },
+  { 0x00002158,  39168 },
+  { 0x00000045,  40000 },
+  { 0x00000089,  43163 },
+  { 0x000010E7,  44900 },
+  { 0x00002136,  45720 },
+  { 0x00003207,  49500 },
+  { 0x00002187,  50000 },
+  { 0x00004286,  56250 },
+  { 0x000010E5,  60065 },
+  { 0x00004214,  65000 },
+  { 0x00001105,  68179 },
+  { 0x000031E4,  74250 },
+  { 0x00003183,  75000 },
+  { 0x00004284,  78750 },
+  { 0x00001104,  81600 },
+  { 0x00006363,  94500 },
+  { 0x00005303,  97520 },
+  { 0x00002183, 100187 },
+  { 0x00002122, 101420 },
+  { 0x00001081, 108000 },
+  { 0x00006201, 113310 },
+  { 0x00000041, 119650 },
+  { 0x000041A1, 129600 },
+  { 0x00002182, 133500 },
+  { 0x000041B1, 135000 },
+  { 0x00000051, 144000 },
+  { 0x000041E1, 148500 },
+  { 0x000062D1, 157500 },
+  { 0x000031A1, 162000 },
+  { 0x00000061, 169203 },
+  { 0x00004231, 172800 },
+  { 0x00002151, 175500 },
+  { 0x000052E1, 189000 },
+  { 0x00000071, 192000 },
+  { 0x00003201, 198000 },
+  { 0x00004291, 202500 },
+  { 0x00001101, 204750 },
+  { 0x00007481, 218250 },
+  { 0x00004170, 229500 },
+  { 0x00006210, 234000 },
+  { 0x00003140, 251182 },
+  { 0x00006250, 261000 },
+  { 0x000041C0, 278400 },
+  { 0x00005220, 280640 },
+  { 0x00000050, 288000 },
+  { 0x000041E0, 297000 },
+  { 0x00002130, 320207 }
+};
+
+
+static void lx_set_dotpll(u32 pllval)
+{
+	u32 dotpll_lo, dotpll_hi;
+	int i;
+
+	rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+
+	if ((dotpll_lo & MSR_GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval))
+		return;
+
+	dotpll_hi = pllval;
+	dotpll_lo &= ~(MSR_GLCP_DOTPLL_BYPASS | MSR_GLCP_DOTPLL_HALFPIX);
+	dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
+
+	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+
+	/* Wait 100us for the PLL to lock */
+
+	udelay(100);
+
+	/* Now, loop for the lock bit */
+
+	for (i = 0; i < 1000; i++) {
+		rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+		if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
+			break;
+	}
+
+	/* Clear the reset bit */
+
+	dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
+	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+}
+
+/* Set the clock based on the frequency specified by the current mode */
+
+static void lx_set_clock(struct fb_info *info)
+{
+	unsigned int diff, min, best = 0;
+	unsigned int freq, i;
+
+	freq = (unsigned int) (1000000000 / info->var.pixclock);
+
+	min = abs(pll_table[0].freq - freq);
+
+	for (i = 0; i < ARRAY_SIZE(pll_table); i++) {
+		diff = abs(pll_table[i].freq - freq);
+		if (diff < min) {
+			min = diff;
+			best = i;
+		}
+	}
+
+	lx_set_dotpll(pll_table[best].pllval & 0x00017FFF);
+}
+
+static void lx_graphics_disable(struct fb_info *info)
+{
+	struct lxfb_par *par = info->par;
+	unsigned int val, gcfg;
+
+	/* Note:  This assumes that the video is in a quitet state */
+
+	write_vp(par, VP_A1T, 0);
+	write_vp(par, VP_A2T, 0);
+	write_vp(par, VP_A3T, 0);
+
+	/* Turn off the VGA and video enable */
+	val = read_dc(par, DC_GENERAL_CFG) & ~(DC_GENERAL_CFG_VGAE |
+			DC_GENERAL_CFG_VIDE);
+
+	write_dc(par, DC_GENERAL_CFG, val);
+
+	val = read_vp(par, VP_VCFG) & ~VP_VCFG_VID_EN;
+	write_vp(par, VP_VCFG, val);
+
+	write_dc(par, DC_IRQ, DC_IRQ_MASK | DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK |
+			DC_IRQ_STATUS | DC_IRQ_VIP_VSYNC_IRQ_STATUS);
+
+	val = read_dc(par, DC_GENLK_CTL) & ~DC_GENLK_CTL_GENLK_EN;
+	write_dc(par, DC_GENLK_CTL, val);
+
+	val = read_dc(par, DC_CLR_KEY);
+	write_dc(par, DC_CLR_KEY, val & ~DC_CLR_KEY_CLR_KEY_EN);
+
+	/* turn off the panel */
+	write_fp(par, FP_PM, read_fp(par, FP_PM) & ~FP_PM_P);
+
+	val = read_vp(par, VP_MISC) | VP_MISC_DACPWRDN;
+	write_vp(par, VP_MISC, val);
+
+	/* Turn off the display */
+
+	val = read_vp(par, VP_DCFG);
+	write_vp(par, VP_DCFG, val & ~(VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN |
+			VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN));
+
+	gcfg = read_dc(par, DC_GENERAL_CFG);
+	gcfg &= ~(DC_GENERAL_CFG_CMPE | DC_GENERAL_CFG_DECE);
+	write_dc(par, DC_GENERAL_CFG, gcfg);
+
+	/* Turn off the TGEN */
+	val = read_dc(par, DC_DISPLAY_CFG);
+	val &= ~DC_DISPLAY_CFG_TGEN;
+	write_dc(par, DC_DISPLAY_CFG, val);
+
+	/* Wait 1000 usecs to ensure that the TGEN is clear */
+	udelay(1000);
+
+	/* Turn off the FIFO loader */
+
+	gcfg &= ~DC_GENERAL_CFG_DFLE;
+	write_dc(par, DC_GENERAL_CFG, gcfg);
+
+	/* Lastly, wait for the GP to go idle */
+
+	do {
+		val = read_gp(par, GP_BLT_STATUS);
+	} while ((val & GP_BLT_STATUS_PB) || !(val & GP_BLT_STATUS_CE));
+}
+
+static void lx_graphics_enable(struct fb_info *info)
+{
+	struct lxfb_par *par = info->par;
+	u32 temp, config;
+
+	/* Set the video request register */
+	write_vp(par, VP_VRR, 0);
+
+	/* Set up the polarities */
+
+	config = read_vp(par, VP_DCFG);
+
+	config &= ~(VP_DCFG_CRT_SYNC_SKW | VP_DCFG_PWR_SEQ_DELAY |
+			VP_DCFG_CRT_HSYNC_POL | VP_DCFG_CRT_VSYNC_POL);
+
+	config |= (VP_DCFG_CRT_SYNC_SKW_DEFAULT | VP_DCFG_PWR_SEQ_DELAY_DEFAULT
+			| VP_DCFG_GV_GAM);
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		config |= VP_DCFG_CRT_HSYNC_POL;
+
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		config |= VP_DCFG_CRT_VSYNC_POL;
+
+	if (par->output & OUTPUT_PANEL) {
+		u32 msrlo, msrhi;
+
+		write_fp(par, FP_PT1, 0);
+		temp = FP_PT2_SCRC;
+
+		if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+			temp |= FP_PT2_HSP;
+
+		if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+			temp |= FP_PT2_VSP;
+
+		write_fp(par, FP_PT2, temp);
+		write_fp(par, FP_DFC, FP_DFC_BC);
+
+		msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW;
+		msrhi = MSR_LX_MSR_PADSEL_TFT_SEL_HIGH;
+
+		wrmsr(MSR_LX_MSR_PADSEL, msrlo, msrhi);
+	}
+
+	if (par->output & OUTPUT_CRT) {
+		config |= VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN |
+				VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN;
+	}
+
+	write_vp(par, VP_DCFG, config);
+
+	/* Turn the CRT dacs back on */
+
+	if (par->output & OUTPUT_CRT) {
+		temp = read_vp(par, VP_MISC);
+		temp &= ~(VP_MISC_DACPWRDN | VP_MISC_APWRDN);
+		write_vp(par, VP_MISC, temp);
+	}
+
+	/* Turn the panel on (if it isn't already) */
+	if (par->output & OUTPUT_PANEL)
+		write_fp(par, FP_PM, read_fp(par, FP_PM) | FP_PM_P);
+}
+
+unsigned int lx_framebuffer_size(void)
+{
+	unsigned int val;
+
+	if (!cs5535_has_vsa2()) {
+		uint32_t hi, lo;
+
+		/* The number of pages is (PMAX - PMIN)+1 */
+		rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
+
+		/* PMAX */
+		val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
+		/* PMIN */
+		val -= (lo & 0x000fffff);
+		val += 1;
+
+		/* The page size is 4k */
+		return (val << 12);
+	}
+
+	/* The frame buffer size is reported by a VSM in VSA II */
+	/* Virtual Register Class    = 0x02                     */
+	/* VG_MEM_SIZE (1MB units)   = 0x00                     */
+
+	outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
+	outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
+
+	val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFE;
+	return (val << 20);
+}
+
+void lx_set_mode(struct fb_info *info)
+{
+	struct lxfb_par *par = info->par;
+	u64 msrval;
+
+	unsigned int max, dv, val, size;
+
+	unsigned int gcfg, dcfg;
+	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+	/* Unlock the DC registers */
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+
+	lx_graphics_disable(info);
+
+	lx_set_clock(info);
+
+	/* Set output mode */
+
+	rdmsrl(MSR_LX_GLD_MSR_CONFIG, msrval);
+	msrval &= ~MSR_LX_GLD_MSR_CONFIG_FMT;
+
+	if (par->output & OUTPUT_PANEL) {
+		msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_FP;
+
+		if (par->output & OUTPUT_CRT)
+			msrval |= MSR_LX_GLD_MSR_CONFIG_FPC;
+		else
+			msrval &= ~MSR_LX_GLD_MSR_CONFIG_FPC;
+	} else
+		msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_CRT;
+
+	wrmsrl(MSR_LX_GLD_MSR_CONFIG, msrval);
+
+	/* Clear the various buffers */
+	/* FIXME:  Adjust for panning here */
+
+	write_dc(par, DC_FB_ST_OFFSET, 0);
+	write_dc(par, DC_CB_ST_OFFSET, 0);
+	write_dc(par, DC_CURS_ST_OFFSET, 0);
+
+	/* FIXME: Add support for interlacing */
+	/* FIXME: Add support for scaling */
+
+	val = read_dc(par, DC_GENLK_CTL);
+	val &= ~(DC_GENLK_CTL_ALPHA_FLICK_EN | DC_GENLK_CTL_FLICK_EN |
+			DC_GENLK_CTL_FLICK_SEL_MASK);
+
+	/* Default scaling params */
+
+	write_dc(par, DC_GFX_SCALE, (0x4000 << 16) | 0x4000);
+	write_dc(par, DC_IRQ_FILT_CTL, 0);
+	write_dc(par, DC_GENLK_CTL, val);
+
+	/* FIXME:  Support compression */
+
+	if (info->fix.line_length > 4096)
+		dv = DC_DV_CTL_DV_LINE_SIZE_8K;
+	else if (info->fix.line_length > 2048)
+		dv = DC_DV_CTL_DV_LINE_SIZE_4K;
+	else if (info->fix.line_length > 1024)
+		dv = DC_DV_CTL_DV_LINE_SIZE_2K;
+	else
+		dv = DC_DV_CTL_DV_LINE_SIZE_1K;
+
+	max = info->fix.line_length * info->var.yres;
+	max = (max + 0x3FF) & 0xFFFFFC00;
+
+	write_dc(par, DC_DV_TOP, max | DC_DV_TOP_DV_TOP_EN);
+
+	val = read_dc(par, DC_DV_CTL) & ~DC_DV_CTL_DV_LINE_SIZE;
+	write_dc(par, DC_DV_CTL, val | dv);
+
+	size = info->var.xres * (info->var.bits_per_pixel >> 3);
+
+	write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
+	write_dc(par, DC_LINE_SIZE, (size + 7) >> 3);
+
+	/* Set default watermark values */
+
+	rdmsrl(MSR_LX_SPARE_MSR, msrval);
+
+	msrval &= ~(MSR_LX_SPARE_MSR_DIS_CFIFO_HGO
+			| MSR_LX_SPARE_MSR_VFIFO_ARB_SEL
+			| MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M
+			| MSR_LX_SPARE_MSR_WM_LPEN_OVRD);
+	msrval |= MSR_LX_SPARE_MSR_DIS_VIFO_WM |
+			MSR_LX_SPARE_MSR_DIS_INIT_V_PRI;
+	wrmsrl(MSR_LX_SPARE_MSR, msrval);
+
+	gcfg = DC_GENERAL_CFG_DFLE;   /* Display fifo enable */
+	gcfg |= (0x6 << DC_GENERAL_CFG_DFHPSL_SHIFT) | /* default priority */
+			(0xb << DC_GENERAL_CFG_DFHPEL_SHIFT);
+	gcfg |= DC_GENERAL_CFG_FDTY;  /* Set the frame dirty mode */
+
+	dcfg  = DC_DISPLAY_CFG_VDEN;  /* Enable video data */
+	dcfg |= DC_DISPLAY_CFG_GDEN;  /* Enable graphics */
+	dcfg |= DC_DISPLAY_CFG_TGEN;  /* Turn on the timing generator */
+	dcfg |= DC_DISPLAY_CFG_TRUP;  /* Update timings immediately */
+	dcfg |= DC_DISPLAY_CFG_PALB;  /* Palette bypass in > 8 bpp modes */
+	dcfg |= DC_DISPLAY_CFG_VISL;
+	dcfg |= DC_DISPLAY_CFG_DCEN;  /* Always center the display */
+
+	/* Set the current BPP mode */
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
+		break;
+
+	case 16:
+		dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
+		break;
+
+	case 32:
+	case 24:
+		dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
+		break;
+	}
+
+	/* Now - set up the timings */
+
+	hactive = info->var.xres;
+	hblankstart = hactive;
+	hsyncstart = hblankstart + info->var.right_margin;
+	hsyncend =  hsyncstart + info->var.hsync_len;
+	hblankend = hsyncend + info->var.left_margin;
+	htotal = hblankend;
+
+	vactive = info->var.yres;
+	vblankstart = vactive;
+	vsyncstart = vblankstart + info->var.lower_margin;
+	vsyncend =  vsyncstart + info->var.vsync_len;
+	vblankend = vsyncend + info->var.upper_margin;
+	vtotal = vblankend;
+
+	write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) | ((htotal - 1) << 16));
+	write_dc(par, DC_H_BLANK_TIMING,
+			(hblankstart - 1) | ((hblankend - 1) << 16));
+	write_dc(par, DC_H_SYNC_TIMING,
+			(hsyncstart - 1) | ((hsyncend - 1) << 16));
+
+	write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) | ((vtotal - 1) << 16));
+	write_dc(par, DC_V_BLANK_TIMING,
+			(vblankstart - 1) | ((vblankend - 1) << 16));
+	write_dc(par, DC_V_SYNC_TIMING,
+			(vsyncstart - 1) | ((vsyncend - 1) << 16));
+
+	write_dc(par, DC_FB_ACTIVE,
+			(info->var.xres - 1) << 16 | (info->var.yres - 1));
+
+	/* And re-enable the graphics output */
+	lx_graphics_enable(info);
+
+	/* Write the two main configuration registers */
+	write_dc(par, DC_DISPLAY_CFG, dcfg);
+	write_dc(par, DC_ARB_CFG, 0);
+	write_dc(par, DC_GENERAL_CFG, gcfg);
+
+	/* Lock the DC registers */
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+}
+
+void lx_set_palette_reg(struct fb_info *info, unsigned regno,
+			unsigned red, unsigned green, unsigned blue)
+{
+	struct lxfb_par *par = info->par;
+	int val;
+
+	/* Hardware palette is in RGB 8-8-8 format. */
+
+	val  = (red   << 8) & 0xff0000;
+	val |= (green)      & 0x00ff00;
+	val |= (blue  >> 8) & 0x0000ff;
+
+	write_dc(par, DC_PAL_ADDRESS, regno);
+	write_dc(par, DC_PAL_DATA, val);
+}
+
+int lx_blank_display(struct fb_info *info, int blank_mode)
+{
+	struct lxfb_par *par = info->par;
+	u32 dcfg, misc, fp_pm;
+	int blank, hsync, vsync;
+
+	/* CRT power saving modes. */
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		blank = 0; hsync = 1; vsync = 1;
+		break;
+	case FB_BLANK_NORMAL:
+		blank = 1; hsync = 1; vsync = 1;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		blank = 1; hsync = 1; vsync = 0;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		blank = 1; hsync = 0; vsync = 1;
+		break;
+	case FB_BLANK_POWERDOWN:
+		blank = 1; hsync = 0; vsync = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dcfg = read_vp(par, VP_DCFG);
+	dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
+			VP_DCFG_CRT_EN);
+	if (!blank)
+		dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN;
+	if (hsync)
+		dcfg |= VP_DCFG_HSYNC_EN;
+	if (vsync)
+		dcfg |= VP_DCFG_VSYNC_EN;
+
+	write_vp(par, VP_DCFG, dcfg);
+
+	misc = read_vp(par, VP_MISC);
+
+	if (vsync && hsync)
+		misc &= ~VP_MISC_DACPWRDN;
+	else
+		misc |= VP_MISC_DACPWRDN;
+
+	write_vp(par, VP_MISC, misc);
+
+	/* Power on/off flat panel */
+
+	if (par->output & OUTPUT_PANEL) {
+		fp_pm = read_fp(par, FP_PM);
+		if (blank_mode == FB_BLANK_POWERDOWN)
+			fp_pm &= ~FP_PM_P;
+		else
+			fp_pm |= FP_PM_P;
+		write_fp(par, FP_PM, fp_pm);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static void lx_save_regs(struct lxfb_par *par)
+{
+	uint32_t filt;
+	int i;
+
+	/* wait for the BLT engine to stop being busy */
+	do {
+		i = read_gp(par, GP_BLT_STATUS);
+	} while ((i & GP_BLT_STATUS_PB) || !(i & GP_BLT_STATUS_CE));
+
+	/* save MSRs */
+	rdmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);
+	rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
+	rdmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);
+	rdmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);
+
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+
+	/* save registers */
+	memcpy(par->gp, par->gp_regs, sizeof(par->gp));
+	memcpy(par->dc, par->dc_regs, sizeof(par->dc));
+	memcpy(par->vp, par->vp_regs, sizeof(par->vp));
+	memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp));
+
+	/* save the display controller palette */
+	write_dc(par, DC_PAL_ADDRESS, 0);
+	for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
+		par->dc_pal[i] = read_dc(par, DC_PAL_DATA);
+
+	/* save the video processor palette */
+	write_vp(par, VP_PAR, 0);
+	for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
+		par->vp_pal[i] = read_vp(par, VP_PDR);
+
+	/* save the horizontal filter coefficients */
+	filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
+	for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
+		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
+		par->hcoeff[i] = read_dc(par, DC_FILT_COEFF1);
+		par->hcoeff[i + 1] = read_dc(par, DC_FILT_COEFF2);
+	}
+
+	/* save the vertical filter coefficients */
+	filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;
+	for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
+		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
+		par->vcoeff[i] = read_dc(par, DC_FILT_COEFF1);
+	}
+
+	/* save video coeff ram */
+	memcpy(par->vp_coeff, par->vp_regs + VP_VCR, sizeof(par->vp_coeff));
+}
+
+static void lx_restore_gfx_proc(struct lxfb_par *par)
+{
+	int i;
+
+	/* a bunch of registers require GP_RASTER_MODE to be set first */
+	write_gp(par, GP_RASTER_MODE, par->gp[GP_RASTER_MODE]);
+
+	for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
+		switch (i) {
+		case GP_RASTER_MODE:
+		case GP_VECTOR_MODE:
+		case GP_BLT_MODE:
+		case GP_BLT_STATUS:
+		case GP_HST_SRC:
+			/* FIXME: restore LUT data */
+		case GP_LUT_INDEX:
+		case GP_LUT_DATA:
+			/* don't restore these registers */
+			break;
+
+		default:
+			write_gp(par, i, par->gp[i]);
+		}
+	}
+}
+
+static void lx_restore_display_ctlr(struct lxfb_par *par)
+{
+	uint32_t filt;
+	int i;
+
+	wrmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);
+
+	for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
+		switch (i) {
+		case DC_UNLOCK:
+			/* unlock the DC; runs first */
+			write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+			break;
+
+		case DC_GENERAL_CFG:
+		case DC_DISPLAY_CFG:
+			/* disable all while restoring */
+			write_dc(par, i, 0);
+			break;
+
+		case DC_DV_CTL:
+			/* set all ram to dirty */
+			write_dc(par, i, par->dc[i] | DC_DV_CTL_CLEAR_DV_RAM);
+
+		case DC_RSVD_1:
+		case DC_RSVD_2:
+		case DC_RSVD_3:
+		case DC_LINE_CNT:
+		case DC_PAL_ADDRESS:
+		case DC_PAL_DATA:
+		case DC_DFIFO_DIAG:
+		case DC_CFIFO_DIAG:
+		case DC_FILT_COEFF1:
+		case DC_FILT_COEFF2:
+		case DC_RSVD_4:
+		case DC_RSVD_5:
+			/* don't restore these registers */
+			break;
+
+		default:
+			write_dc(par, i, par->dc[i]);
+		}
+	}
+
+	/* restore the palette */
+	write_dc(par, DC_PAL_ADDRESS, 0);
+	for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
+		write_dc(par, DC_PAL_DATA, par->dc_pal[i]);
+
+	/* restore the horizontal filter coefficients */
+	filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
+	for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
+		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
+		write_dc(par, DC_FILT_COEFF1, par->hcoeff[i]);
+		write_dc(par, DC_FILT_COEFF2, par->hcoeff[i + 1]);
+	}
+
+	/* restore the vertical filter coefficients */
+	filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;
+	for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
+		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
+		write_dc(par, DC_FILT_COEFF1, par->vcoeff[i]);
+	}
+}
+
+static void lx_restore_video_proc(struct lxfb_par *par)
+{
+	int i;
+
+	wrmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);
+	wrmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);
+
+	for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
+		switch (i) {
+		case VP_VCFG:
+		case VP_DCFG:
+		case VP_PAR:
+		case VP_PDR:
+		case VP_CCS:
+		case VP_RSVD_0:
+		/* case VP_VDC: */ /* why should this not be restored? */
+		case VP_RSVD_1:
+		case VP_CRC32:
+			/* don't restore these registers */
+			break;
+
+		default:
+			write_vp(par, i, par->vp[i]);
+		}
+	}
+
+	/* restore video processor palette */
+	write_vp(par, VP_PAR, 0);
+	for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
+		write_vp(par, VP_PDR, par->vp_pal[i]);
+
+	/* restore video coeff ram */
+	memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff));
+}
+
+static void lx_restore_regs(struct lxfb_par *par)
+{
+	int i;
+
+	lx_set_dotpll((u32) (par->msr.dotpll >> 32));
+	lx_restore_gfx_proc(par);
+	lx_restore_display_ctlr(par);
+	lx_restore_video_proc(par);
+
+	/* Flat Panel */
+	for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
+		switch (i) {
+		case FP_PM:
+		case FP_RSVD_0:
+		case FP_RSVD_1:
+		case FP_RSVD_2:
+		case FP_RSVD_3:
+		case FP_RSVD_4:
+			/* don't restore these registers */
+			break;
+
+		default:
+			write_fp(par, i, par->fp[i]);
+		}
+	}
+
+	/* control the panel */
+	if (par->fp[FP_PM] & FP_PM_P) {
+		/* power on the panel if not already power{ed,ing} on */
+		if (!(read_fp(par, FP_PM) &
+				(FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
+			write_fp(par, FP_PM, par->fp[FP_PM]);
+	} else {
+		/* power down the panel if not already power{ed,ing} down */
+		if (!(read_fp(par, FP_PM) &
+				(FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
+			write_fp(par, FP_PM, par->fp[FP_PM]);
+	}
+
+	/* turn everything on */
+	write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
+	write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
+	write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
+	/* do this last; it will enable the FIFO load */
+	write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
+
+	/* lock the door behind us */
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+}
+
+int lx_powerdown(struct fb_info *info)
+{
+	struct lxfb_par *par = info->par;
+
+	if (par->powered_down)
+		return 0;
+
+	lx_save_regs(par);
+	lx_graphics_disable(info);
+
+	par->powered_down = 1;
+	return 0;
+}
+
+int lx_powerup(struct fb_info *info)
+{
+	struct lxfb_par *par = info->par;
+
+	if (!par->powered_down)
+		return 0;
+
+	lx_restore_regs(par);
+
+	par->powered_down = 0;
+	return 0;
+}
+
+#endif
diff --git a/drivers/video/fbdev/geode/suspend_gx.c b/drivers/video/fbdev/geode/suspend_gx.c
new file mode 100644
index 000000000000..1bb043d70c64
--- /dev/null
+++ b/drivers/video/fbdev/geode/suspend_gx.c
@@ -0,0 +1,267 @@
+/*
+ *   Copyright (C) 2007 Advanced Micro Devices, Inc.
+ *   Copyright (C) 2008 Andres Salomon <dilinger@debian.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License as published by the
+ *   Free Software Foundation; either version 2 of the License, or (at your
+ *   option) any later version.
+ */
+#include <linux/fb.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <linux/cs5535.h>
+#include <asm/delay.h>
+
+#include "gxfb.h"
+
+#ifdef CONFIG_PM
+
+static void gx_save_regs(struct gxfb_par *par)
+{
+	int i;
+
+	/* wait for the BLT engine to stop being busy */
+	do {
+		i = read_gp(par, GP_BLT_STATUS);
+	} while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY));
+
+	/* save MSRs */
+	rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
+	rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
+
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+
+	/* save registers */
+	memcpy(par->gp, par->gp_regs, sizeof(par->gp));
+	memcpy(par->dc, par->dc_regs, sizeof(par->dc));
+	memcpy(par->vp, par->vid_regs, sizeof(par->vp));
+	memcpy(par->fp, par->vid_regs + VP_FP_START, sizeof(par->fp));
+
+	/* save the palette */
+	write_dc(par, DC_PAL_ADDRESS, 0);
+	for (i = 0; i < ARRAY_SIZE(par->pal); i++)
+		par->pal[i] = read_dc(par, DC_PAL_DATA);
+}
+
+static void gx_set_dotpll(uint32_t dotpll_hi)
+{
+	uint32_t dotpll_lo;
+	int i;
+
+	rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
+	dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
+	dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS;
+	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+
+	/* wait for the PLL to lock */
+	for (i = 0; i < 200; i++) {
+		rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
+		if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
+			break;
+		udelay(1);
+	}
+
+	/* PLL set, unlock */
+	dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
+	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
+}
+
+static void gx_restore_gfx_proc(struct gxfb_par *par)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
+		switch (i) {
+		case GP_VECTOR_MODE:
+		case GP_BLT_MODE:
+		case GP_BLT_STATUS:
+		case GP_HST_SRC:
+			/* don't restore these registers */
+			break;
+		default:
+			write_gp(par, i, par->gp[i]);
+		}
+	}
+}
+
+static void gx_restore_display_ctlr(struct gxfb_par *par)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
+		switch (i) {
+		case DC_UNLOCK:
+			/* unlock the DC; runs first */
+			write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+			break;
+
+		case DC_GENERAL_CFG:
+			/* write without the enables */
+			write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE |
+					DC_GENERAL_CFG_ICNE |
+					DC_GENERAL_CFG_CURE |
+					DC_GENERAL_CFG_DFLE));
+			break;
+
+		case DC_DISPLAY_CFG:
+			/* write without the enables */
+			write_dc(par, i, par->dc[i] & ~(DC_DISPLAY_CFG_VDEN |
+					DC_DISPLAY_CFG_GDEN |
+					DC_DISPLAY_CFG_TGEN));
+			break;
+
+		case DC_RSVD_0:
+		case DC_RSVD_1:
+		case DC_RSVD_2:
+		case DC_RSVD_3:
+		case DC_RSVD_4:
+		case DC_LINE_CNT:
+		case DC_PAL_ADDRESS:
+		case DC_PAL_DATA:
+		case DC_DFIFO_DIAG:
+		case DC_CFIFO_DIAG:
+		case DC_RSVD_5:
+			/* don't restore these registers */
+			break;
+		default:
+			write_dc(par, i, par->dc[i]);
+		}
+	}
+
+	/* restore the palette */
+	write_dc(par, DC_PAL_ADDRESS, 0);
+	for (i = 0; i < ARRAY_SIZE(par->pal); i++)
+		write_dc(par, DC_PAL_DATA, par->pal[i]);
+}
+
+static void gx_restore_video_proc(struct gxfb_par *par)
+{
+	int i;
+
+	wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
+
+	for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
+		switch (i) {
+		case VP_VCFG:
+			/* don't enable video yet */
+			write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);
+			break;
+
+		case VP_DCFG:
+			/* don't enable CRT yet */
+			write_vp(par, i, par->vp[i] &
+					~(VP_DCFG_DAC_BL_EN | VP_DCFG_VSYNC_EN |
+					VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
+			break;
+
+		case VP_GAR:
+		case VP_GDR:
+		case VP_RSVD_0:
+		case VP_RSVD_1:
+		case VP_RSVD_2:
+		case VP_RSVD_3:
+		case VP_CRC32:
+		case VP_AWT:
+		case VP_VTM:
+			/* don't restore these registers */
+			break;
+		default:
+			write_vp(par, i, par->vp[i]);
+		}
+	}
+}
+
+static void gx_restore_regs(struct gxfb_par *par)
+{
+	int i;
+
+	gx_set_dotpll((uint32_t) (par->msr.dotpll >> 32));
+	gx_restore_gfx_proc(par);
+	gx_restore_display_ctlr(par);
+	gx_restore_video_proc(par);
+
+	/* Flat Panel */
+	for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
+		if (i != FP_PM && i != FP_RSVD_0)
+			write_fp(par, i, par->fp[i]);
+	}
+}
+
+static void gx_disable_graphics(struct gxfb_par *par)
+{
+	/* shut down the engine */
+	write_vp(par, VP_VCFG, par->vp[VP_VCFG] & ~VP_VCFG_VID_EN);
+	write_vp(par, VP_DCFG, par->vp[VP_DCFG] & ~(VP_DCFG_DAC_BL_EN |
+			VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
+
+	/* turn off the flat panel */
+	write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);
+
+
+	/* turn off display */
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
+	write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG] &
+			~(DC_GENERAL_CFG_VIDE | DC_GENERAL_CFG_ICNE |
+			DC_GENERAL_CFG_CURE | DC_GENERAL_CFG_DFLE));
+	write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG] &
+			~(DC_DISPLAY_CFG_VDEN | DC_DISPLAY_CFG_GDEN |
+			DC_DISPLAY_CFG_TGEN));
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+}
+
+static void gx_enable_graphics(struct gxfb_par *par)
+{
+	uint32_t fp;
+
+	fp = read_fp(par, FP_PM);
+	if (par->fp[FP_PM] & FP_PM_P) {
+		/* power on the panel if not already power{ed,ing} on */
+		if (!(fp & (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
+			write_fp(par, FP_PM, par->fp[FP_PM]);
+	} else {
+		/* power down the panel if not already power{ed,ing} down */
+		if (!(fp & (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
+			write_fp(par, FP_PM, par->fp[FP_PM]);
+	}
+
+	/* turn everything on */
+	write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
+	write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
+	write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
+	/* do this last; it will enable the FIFO load */
+	write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
+
+	/* lock the door behind us */
+	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
+}
+
+int gx_powerdown(struct fb_info *info)
+{
+	struct gxfb_par *par = info->par;
+
+	if (par->powered_down)
+		return 0;
+
+	gx_save_regs(par);
+	gx_disable_graphics(par);
+
+	par->powered_down = 1;
+	return 0;
+}
+
+int gx_powerup(struct fb_info *info)
+{
+	struct gxfb_par *par = info->par;
+
+	if (!par->powered_down)
+		return 0;
+
+	gx_restore_regs(par);
+	gx_enable_graphics(par);
+
+	par->powered_down  = 0;
+	return 0;
+}
+
+#endif
diff --git a/drivers/video/fbdev/geode/video_cs5530.c b/drivers/video/fbdev/geode/video_cs5530.c
new file mode 100644
index 000000000000..649c3943d431
--- /dev/null
+++ b/drivers/video/fbdev/geode/video_cs5530.c
@@ -0,0 +1,193 @@
+/*
+ * drivers/video/geode/video_cs5530.c
+ *   -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "video_cs5530.h"
+
+/*
+ * CS5530 PLL table. This maps pixclocks to the appropriate PLL register
+ * value.
+ */
+struct cs5530_pll_entry {
+	long pixclock; /* ps */
+	u32 pll_value;
+};
+
+static const struct cs5530_pll_entry cs5530_pll_table[] = {
+	{ 39721, 0x31C45801, }, /*  25.1750 MHz */
+	{ 35308, 0x20E36802, }, /*  28.3220 */
+	{ 31746, 0x33915801, }, /*  31.5000 */
+	{ 27777, 0x31EC4801, }, /*  36.0000 */
+	{ 26666, 0x21E22801, }, /*  37.5000 */
+	{ 25000, 0x33088801, }, /*  40.0000 */
+	{ 22271, 0x33E22801, }, /*  44.9000 */
+	{ 20202, 0x336C4801, }, /*  49.5000 */
+	{ 20000, 0x23088801, }, /*  50.0000 */
+	{ 19860, 0x23088801, }, /*  50.3500 */
+	{ 18518, 0x3708A801, }, /*  54.0000 */
+	{ 17777, 0x23E36802, }, /*  56.2500 */
+	{ 17733, 0x23E36802, }, /*  56.3916 */
+	{ 17653, 0x23E36802, }, /*  56.6444 */
+	{ 16949, 0x37C45801, }, /*  59.0000 */
+	{ 15873, 0x23EC4801, }, /*  63.0000 */
+	{ 15384, 0x37911801, }, /*  65.0000 */
+	{ 14814, 0x37963803, }, /*  67.5000 */
+	{ 14124, 0x37058803, }, /*  70.8000 */
+	{ 13888, 0x3710C805, }, /*  72.0000 */
+	{ 13333, 0x37E22801, }, /*  75.0000 */
+	{ 12698, 0x27915801, }, /*  78.7500 */
+	{ 12500, 0x37D8D802, }, /*  80.0000 */
+	{ 11135, 0x27588802, }, /*  89.8000 */
+	{ 10582, 0x27EC4802, }, /*  94.5000 */
+	{ 10101, 0x27AC6803, }, /*  99.0000 */
+	{ 10000, 0x27088801, }, /* 100.0000 */
+	{  9259, 0x2710C805, }, /* 108.0000 */
+	{  8888, 0x27E36802, }, /* 112.5000 */
+	{  7692, 0x27C58803, }, /* 130.0000 */
+	{  7407, 0x27316803, }, /* 135.0000 */
+	{  6349, 0x2F915801, }, /* 157.5000 */
+	{  6172, 0x2F08A801, }, /* 162.0000 */
+	{  5714, 0x2FB11802, }, /* 175.0000 */
+	{  5291, 0x2FEC4802, }, /* 189.0000 */
+	{  4950, 0x2F963803, }, /* 202.0000 */
+	{  4310, 0x2FB1B802, }, /* 232.0000 */
+};
+
+static void cs5530_set_dclk_frequency(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+	int i;
+	u32 value;
+	long min, diff;
+
+	/* Search the table for the closest pixclock. */
+	value = cs5530_pll_table[0].pll_value;
+	min = cs5530_pll_table[0].pixclock - info->var.pixclock;
+	if (min < 0) min = -min;
+	for (i = 1; i < ARRAY_SIZE(cs5530_pll_table); i++) {
+		diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
+		if (diff < 0L) diff = -diff;
+		if (diff < min) {
+			min = diff;
+			value = cs5530_pll_table[i].pll_value;
+		}
+	}
+
+	writel(value, par->vid_regs + CS5530_DOT_CLK_CONFIG);
+	writel(value | 0x80000100, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* set reset and bypass */
+	udelay(500); /* wait for PLL to settle */
+	writel(value & 0x7FFFFFFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear reset */
+	writel(value & 0x7FFFFEFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear bypass */
+}
+
+static void cs5530_configure_display(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+	u32 dcfg;
+
+	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+	/* Clear bits from existing mode. */
+	dcfg &= ~(CS5530_DCFG_CRT_SYNC_SKW_MASK | CS5530_DCFG_PWR_SEQ_DLY_MASK
+		  | CS5530_DCFG_CRT_HSYNC_POL   | CS5530_DCFG_CRT_VSYNC_POL
+		  | CS5530_DCFG_FP_PWR_EN       | CS5530_DCFG_FP_DATA_EN
+		  | CS5530_DCFG_DAC_PWR_EN      | CS5530_DCFG_VSYNC_EN
+		  | CS5530_DCFG_HSYNC_EN);
+
+	/* Set default sync skew and power sequence delays.  */
+	dcfg |= (CS5530_DCFG_CRT_SYNC_SKW_INIT | CS5530_DCFG_PWR_SEQ_DLY_INIT
+		 | CS5530_DCFG_GV_PAL_BYP);
+
+	/* Enable DACs, hsync and vsync for CRTs */
+	if (par->enable_crt) {
+		dcfg |= CS5530_DCFG_DAC_PWR_EN;
+		dcfg |= CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN;
+	}
+	/* Enable panel power and data if using a flat panel. */
+	if (par->panel_x > 0) {
+		dcfg |= CS5530_DCFG_FP_PWR_EN;
+		dcfg |= CS5530_DCFG_FP_DATA_EN;
+	}
+
+	/* Sync polarities. */
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		dcfg |= CS5530_DCFG_CRT_HSYNC_POL;
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		dcfg |= CS5530_DCFG_CRT_VSYNC_POL;
+
+	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+}
+
+static int cs5530_blank_display(struct fb_info *info, int blank_mode)
+{
+	struct geodefb_par *par = info->par;
+	u32 dcfg;
+	int blank, hsync, vsync;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		blank = 0; hsync = 1; vsync = 1;
+		break;
+	case FB_BLANK_NORMAL:
+		blank = 1; hsync = 1; vsync = 1;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		blank = 1; hsync = 1; vsync = 0;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		blank = 1; hsync = 0; vsync = 1;
+		break;
+	case FB_BLANK_POWERDOWN:
+		blank = 1; hsync = 0; vsync = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+	dcfg &= ~(CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN
+		  | CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN
+		  | CS5530_DCFG_FP_DATA_EN | CS5530_DCFG_FP_PWR_EN);
+
+	if (par->enable_crt) {
+		if (!blank)
+			dcfg |= CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN;
+		if (hsync)
+			dcfg |= CS5530_DCFG_HSYNC_EN;
+		if (vsync)
+			dcfg |= CS5530_DCFG_VSYNC_EN;
+	}
+	if (par->panel_x > 0) {
+		if (!blank)
+			dcfg |= CS5530_DCFG_FP_DATA_EN;
+		if (hsync && vsync)
+			dcfg |= CS5530_DCFG_FP_PWR_EN;
+	}
+
+	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+	return 0;
+}
+
+struct geode_vid_ops cs5530_vid_ops = {
+	.set_dclk          = cs5530_set_dclk_frequency,
+	.configure_display = cs5530_configure_display,
+	.blank_display     = cs5530_blank_display,
+};
diff --git a/drivers/video/fbdev/geode/video_cs5530.h b/drivers/video/fbdev/geode/video_cs5530.h
new file mode 100644
index 000000000000..56cecca7f1ce
--- /dev/null
+++ b/drivers/video/fbdev/geode/video_cs5530.h
@@ -0,0 +1,75 @@
+/*
+ * drivers/video/geode/video_cs5530.h
+ *   -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VIDEO_CS5530_H__
+#define __VIDEO_CS5530_H__
+
+extern struct geode_vid_ops cs5530_vid_ops;
+
+/* CS5530 Video device registers */
+
+#define CS5530_VIDEO_CONFIG	0x0000
+#  define CS5530_VCFG_VID_EN			0x00000001
+#  define CS5530_VCFG_VID_REG_UPDATE		0x00000002
+#  define CS5530_VCFG_VID_INP_FORMAT		0x0000000C
+#  define CS5530_VCFG_8_BIT_4_2_0		0x00000004
+#  define CS5530_VCFG_16_BIT_4_2_0		0x00000008
+#  define CS5530_VCFG_GV_SEL			0x00000010
+#  define CS5530_VCFG_CSC_BYPASS		0x00000020
+#  define CS5530_VCFG_X_FILTER_EN		0x00000040
+#  define CS5530_VCFG_Y_FILTER_EN		0x00000080
+#  define CS5530_VCFG_LINE_SIZE_LOWER_MASK	0x0000FF00
+#  define CS5530_VCFG_INIT_READ_MASK		0x01FF0000
+#  define CS5530_VCFG_EARLY_VID_RDY		0x02000000
+#  define CS5530_VCFG_LINE_SIZE_UPPER		0x08000000
+#  define CS5530_VCFG_4_2_0_MODE		0x10000000
+#  define CS5530_VCFG_16_BIT_EN			0x20000000
+#  define CS5530_VCFG_HIGH_SPD_INT		0x40000000
+
+#define CS5530_DISPLAY_CONFIG	0x0004
+#  define CS5530_DCFG_DIS_EN			0x00000001
+#  define CS5530_DCFG_HSYNC_EN			0x00000002
+#  define CS5530_DCFG_VSYNC_EN			0x00000004
+#  define CS5530_DCFG_DAC_BL_EN			0x00000008
+#  define CS5530_DCFG_DAC_PWR_EN		0x00000020
+#  define CS5530_DCFG_FP_PWR_EN			0x00000040
+#  define CS5530_DCFG_FP_DATA_EN		0x00000080
+#  define CS5530_DCFG_CRT_HSYNC_POL		0x00000100
+#  define CS5530_DCFG_CRT_VSYNC_POL		0x00000200
+#  define CS5530_DCFG_FP_HSYNC_POL		0x00000400
+#  define CS5530_DCFG_FP_VSYNC_POL		0x00000800
+#  define CS5530_DCFG_XGA_FP			0x00001000
+#  define CS5530_DCFG_FP_DITH_EN		0x00002000
+#  define CS5530_DCFG_CRT_SYNC_SKW_MASK		0x0001C000
+#  define CS5530_DCFG_CRT_SYNC_SKW_INIT		0x00010000
+#  define CS5530_DCFG_PWR_SEQ_DLY_MASK		0x000E0000
+#  define CS5530_DCFG_PWR_SEQ_DLY_INIT		0x00080000
+#  define CS5530_DCFG_VG_CK			0x00100000
+#  define CS5530_DCFG_GV_PAL_BYP		0x00200000
+#  define CS5530_DCFG_DDC_SCL			0x00400000
+#  define CS5530_DCFG_DDC_SDA			0x00800000
+#  define CS5530_DCFG_DDC_OE			0x01000000
+#  define CS5530_DCFG_16_BIT_EN			0x02000000
+
+#define CS5530_VIDEO_X_POS	0x0008
+#define CS5530_VIDEO_Y_POS	0x000C
+#define CS5530_VIDEO_SCALE	0x0010
+#define CS5530_VIDEO_COLOR_KEY	0x0014
+#define CS5530_VIDEO_COLOR_MASK 0x0018
+#define CS5530_PALETTE_ADDRESS	0x001C
+#define CS5530_PALETTE_DATA	0x0020
+#define CS5530_DOT_CLK_CONFIG	0x0024
+#define CS5530_CRCSIG_TFT_TV	0x0028
+
+#endif /* !__VIDEO_CS5530_H__ */
diff --git a/drivers/video/fbdev/geode/video_gx.c b/drivers/video/fbdev/geode/video_gx.c
new file mode 100644
index 000000000000..6082f653c68a
--- /dev/null
+++ b/drivers/video/fbdev/geode/video_gx.c
@@ -0,0 +1,349 @@
+/*
+ * Geode GX video processor device.
+ *
+ *   Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ *   Portions from AMD's original 2.4 driver:
+ *     Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License as published by the
+ *   Free Software Foundation; either version 2 of the License, or (at your
+ *   option) any later version.
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/msr.h>
+#include <linux/cs5535.h>
+
+#include "gxfb.h"
+
+
+/*
+ * Tables of register settings for various DOTCLKs.
+ */
+struct gx_pll_entry {
+	long pixclock; /* ps */
+	u32 sys_rstpll_bits;
+	u32 dotpll_value;
+};
+
+#define POSTDIV3 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
+#define PREMULT2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPREMULT2)
+#define PREDIV2  ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
+
+static const struct gx_pll_entry gx_pll_table_48MHz[] = {
+	{ 40123, POSTDIV3,	    0x00000BF2 },	/*  24.9230 */
+	{ 39721, 0,		    0x00000037 },	/*  25.1750 */
+	{ 35308, POSTDIV3|PREMULT2, 0x00000B1A },	/*  28.3220 */
+	{ 31746, POSTDIV3,	    0x000002D2 },	/*  31.5000 */
+	{ 27777, POSTDIV3|PREMULT2, 0x00000FE2 },	/*  36.0000 */
+	{ 26666, POSTDIV3,	    0x0000057A },	/*  37.5000 */
+	{ 25000, POSTDIV3,	    0x0000030A },	/*  40.0000 */
+	{ 22271, 0,		    0x00000063 },	/*  44.9000 */
+	{ 20202, 0,		    0x0000054B },	/*  49.5000 */
+	{ 20000, 0,		    0x0000026E },	/*  50.0000 */
+	{ 19860, PREMULT2,	    0x00000037 },	/*  50.3500 */
+	{ 18518, POSTDIV3|PREMULT2, 0x00000B0D },	/*  54.0000 */
+	{ 17777, 0,		    0x00000577 },	/*  56.2500 */
+	{ 17733, 0,		    0x000007F7 },	/*  56.3916 */
+	{ 17653, 0,		    0x0000057B },	/*  56.6444 */
+	{ 16949, PREMULT2,	    0x00000707 },	/*  59.0000 */
+	{ 15873, POSTDIV3|PREMULT2, 0x00000B39 },	/*  63.0000 */
+	{ 15384, POSTDIV3|PREMULT2, 0x00000B45 },	/*  65.0000 */
+	{ 14814, POSTDIV3|PREMULT2, 0x00000FC1 },	/*  67.5000 */
+	{ 14124, POSTDIV3,	    0x00000561 },	/*  70.8000 */
+	{ 13888, POSTDIV3,	    0x000007E1 },	/*  72.0000 */
+	{ 13426, PREMULT2,	    0x00000F4A },	/*  74.4810 */
+	{ 13333, 0,		    0x00000052 },	/*  75.0000 */
+	{ 12698, 0,		    0x00000056 },	/*  78.7500 */
+	{ 12500, POSTDIV3|PREMULT2, 0x00000709 },	/*  80.0000 */
+	{ 11135, PREMULT2,	    0x00000262 },	/*  89.8000 */
+	{ 10582, 0,		    0x000002D2 },	/*  94.5000 */
+	{ 10101, PREMULT2,	    0x00000B4A },	/*  99.0000 */
+	{ 10000, PREMULT2,	    0x00000036 },	/* 100.0000 */
+	{  9259, 0,		    0x000007E2 },	/* 108.0000 */
+	{  8888, 0,		    0x000007F6 },	/* 112.5000 */
+	{  7692, POSTDIV3|PREMULT2, 0x00000FB0 },	/* 130.0000 */
+	{  7407, POSTDIV3|PREMULT2, 0x00000B50 },	/* 135.0000 */
+	{  6349, 0,		    0x00000055 },	/* 157.5000 */
+	{  6172, 0,		    0x000009C1 },	/* 162.0000 */
+	{  5787, PREMULT2,	    0x0000002D },	/* 172.798  */
+	{  5698, 0,		    0x000002C1 },	/* 175.5000 */
+	{  5291, 0,		    0x000002D1 },	/* 189.0000 */
+	{  4938, 0,		    0x00000551 },	/* 202.5000 */
+	{  4357, 0,		    0x0000057D },	/* 229.5000 */
+};
+
+static const struct gx_pll_entry gx_pll_table_14MHz[] = {
+	{ 39721, 0, 0x00000037 },	/*  25.1750 */
+	{ 35308, 0, 0x00000B7B },	/*  28.3220 */
+	{ 31746, 0, 0x000004D3 },	/*  31.5000 */
+	{ 27777, 0, 0x00000BE3 },	/*  36.0000 */
+	{ 26666, 0, 0x0000074F },	/*  37.5000 */
+	{ 25000, 0, 0x0000050B },	/*  40.0000 */
+	{ 22271, 0, 0x00000063 },	/*  44.9000 */
+	{ 20202, 0, 0x0000054B },	/*  49.5000 */
+	{ 20000, 0, 0x0000026E },	/*  50.0000 */
+	{ 19860, 0, 0x000007C3 },	/*  50.3500 */
+	{ 18518, 0, 0x000007E3 },	/*  54.0000 */
+	{ 17777, 0, 0x00000577 },	/*  56.2500 */
+	{ 17733, 0, 0x000002FB },	/*  56.3916 */
+	{ 17653, 0, 0x0000057B },	/*  56.6444 */
+	{ 16949, 0, 0x0000058B },	/*  59.0000 */
+	{ 15873, 0, 0x0000095E },	/*  63.0000 */
+	{ 15384, 0, 0x0000096A },	/*  65.0000 */
+	{ 14814, 0, 0x00000BC2 },	/*  67.5000 */
+	{ 14124, 0, 0x0000098A },	/*  70.8000 */
+	{ 13888, 0, 0x00000BE2 },	/*  72.0000 */
+	{ 13333, 0, 0x00000052 },	/*  75.0000 */
+	{ 12698, 0, 0x00000056 },	/*  78.7500 */
+	{ 12500, 0, 0x0000050A },	/*  80.0000 */
+	{ 11135, 0, 0x0000078E },	/*  89.8000 */
+	{ 10582, 0, 0x000002D2 },	/*  94.5000 */
+	{ 10101, 0, 0x000011F6 },	/*  99.0000 */
+	{ 10000, 0, 0x0000054E },	/* 100.0000 */
+	{  9259, 0, 0x000007E2 },	/* 108.0000 */
+	{  8888, 0, 0x000002FA },	/* 112.5000 */
+	{  7692, 0, 0x00000BB1 },	/* 130.0000 */
+	{  7407, 0, 0x00000975 },	/* 135.0000 */
+	{  6349, 0, 0x00000055 },	/* 157.5000 */
+	{  6172, 0, 0x000009C1 },	/* 162.0000 */
+	{  5698, 0, 0x000002C1 },	/* 175.5000 */
+	{  5291, 0, 0x00000539 },	/* 189.0000 */
+	{  4938, 0, 0x00000551 },	/* 202.5000 */
+	{  4357, 0, 0x0000057D },	/* 229.5000 */
+};
+
+void gx_set_dclk_frequency(struct fb_info *info)
+{
+	const struct gx_pll_entry *pll_table;
+	int pll_table_len;
+	int i, best_i;
+	long min, diff;
+	u64 dotpll, sys_rstpll;
+	int timeout = 1000;
+
+	/* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
+	if (cpu_data(0).x86_mask == 1) {
+		pll_table = gx_pll_table_14MHz;
+		pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
+	} else {
+		pll_table = gx_pll_table_48MHz;
+		pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
+	}
+
+	/* Search the table for the closest pixclock. */
+	best_i = 0;
+	min = abs(pll_table[0].pixclock - info->var.pixclock);
+	for (i = 1; i < pll_table_len; i++) {
+		diff = abs(pll_table[i].pixclock - info->var.pixclock);
+		if (diff < min) {
+			min = diff;
+			best_i = i;
+		}
+	}
+
+	rdmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
+	rdmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+	/* Program new M, N and P. */
+	dotpll &= 0x00000000ffffffffull;
+	dotpll |= (u64)pll_table[best_i].dotpll_value << 32;
+	dotpll |= MSR_GLCP_DOTPLL_DOTRESET;
+	dotpll &= ~MSR_GLCP_DOTPLL_BYPASS;
+
+	wrmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+	/* Program dividers. */
+	sys_rstpll &= ~( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2
+			 | MSR_GLCP_SYS_RSTPLL_DOTPREMULT2
+			 | MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 );
+	sys_rstpll |= pll_table[best_i].sys_rstpll_bits;
+
+	wrmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
+
+	/* Clear reset bit to start PLL. */
+	dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET);
+	wrmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+	/* Wait for LOCK bit. */
+	do {
+		rdmsrl(MSR_GLCP_DOTPLL, dotpll);
+	} while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
+}
+
+static void
+gx_configure_tft(struct fb_info *info)
+{
+	struct gxfb_par *par = info->par;
+	unsigned long val;
+	unsigned long fp;
+
+	/* Set up the DF pad select MSR */
+
+	rdmsrl(MSR_GX_MSR_PADSEL, val);
+	val &= ~MSR_GX_MSR_PADSEL_MASK;
+	val |= MSR_GX_MSR_PADSEL_TFT;
+	wrmsrl(MSR_GX_MSR_PADSEL, val);
+
+	/* Turn off the panel */
+
+	fp = read_fp(par, FP_PM);
+	fp &= ~FP_PM_P;
+	write_fp(par, FP_PM, fp);
+
+	/* Set timing 1 */
+
+	fp = read_fp(par, FP_PT1);
+	fp &= FP_PT1_VSIZE_MASK;
+	fp |= info->var.yres << FP_PT1_VSIZE_SHIFT;
+	write_fp(par, FP_PT1, fp);
+
+	/* Timing 2 */
+	/* Set bits that are always on for TFT */
+
+	fp = 0x0F100000;
+
+	/* Configure sync polarity */
+
+	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+		fp |= FP_PT2_VSP;
+
+	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+		fp |= FP_PT2_HSP;
+
+	write_fp(par, FP_PT2, fp);
+
+	/*  Set the dither control */
+	write_fp(par, FP_DFC, FP_DFC_NFI);
+
+	/* Enable the FP data and power (in case the BIOS didn't) */
+
+	fp = read_vp(par, VP_DCFG);
+	fp |= VP_DCFG_FP_PWR_EN | VP_DCFG_FP_DATA_EN;
+	write_vp(par, VP_DCFG, fp);
+
+	/* Unblank the panel */
+
+	fp = read_fp(par, FP_PM);
+	fp |= FP_PM_P;
+	write_fp(par, FP_PM, fp);
+}
+
+void gx_configure_display(struct fb_info *info)
+{
+	struct gxfb_par *par = info->par;
+	u32 dcfg, misc;
+
+	/* Write the display configuration */
+	dcfg = read_vp(par, VP_DCFG);
+
+	/* Disable hsync and vsync */
+	dcfg &= ~(VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN);
+	write_vp(par, VP_DCFG, dcfg);
+
+	/* Clear bits from existing mode. */
+	dcfg &= ~(VP_DCFG_CRT_SYNC_SKW
+		  | VP_DCFG_CRT_HSYNC_POL   | VP_DCFG_CRT_VSYNC_POL
+		  | VP_DCFG_VSYNC_EN        | VP_DCFG_HSYNC_EN);
+
+	/* Set default sync skew.  */
+	dcfg |= VP_DCFG_CRT_SYNC_SKW_DEFAULT;
+
+	/* Enable hsync and vsync. */
+	dcfg |= VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN;
+
+	misc = read_vp(par, VP_MISC);
+
+	/* Disable gamma correction */
+	misc |= VP_MISC_GAM_EN;
+
+	if (par->enable_crt) {
+
+		/* Power up the CRT DACs */
+		misc &= ~(VP_MISC_APWRDN | VP_MISC_DACPWRDN);
+		write_vp(par, VP_MISC, misc);
+
+		/* Only change the sync polarities if we are running
+		 * in CRT mode.  The FP polarities will be handled in
+		 * gxfb_configure_tft */
+		if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+			dcfg |= VP_DCFG_CRT_HSYNC_POL;
+		if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+			dcfg |= VP_DCFG_CRT_VSYNC_POL;
+	} else {
+		/* Power down the CRT DACs if in FP mode */
+		misc |= (VP_MISC_APWRDN | VP_MISC_DACPWRDN);
+		write_vp(par, VP_MISC, misc);
+	}
+
+	/* Enable the display logic */
+	/* Set up the DACS to blank normally */
+
+	dcfg |= VP_DCFG_CRT_EN | VP_DCFG_DAC_BL_EN;
+
+	/* Enable the external DAC VREF? */
+
+	write_vp(par, VP_DCFG, dcfg);
+
+	/* Set up the flat panel (if it is enabled) */
+
+	if (par->enable_crt == 0)
+		gx_configure_tft(info);
+}
+
+int gx_blank_display(struct fb_info *info, int blank_mode)
+{
+	struct gxfb_par *par = info->par;
+	u32 dcfg, fp_pm;
+	int blank, hsync, vsync, crt;
+
+	/* CRT power saving modes. */
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		blank = 0; hsync = 1; vsync = 1; crt = 1;
+		break;
+	case FB_BLANK_NORMAL:
+		blank = 1; hsync = 1; vsync = 1; crt = 1;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		blank = 1; hsync = 1; vsync = 0; crt = 1;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		blank = 1; hsync = 0; vsync = 1; crt = 1;
+		break;
+	case FB_BLANK_POWERDOWN:
+		blank = 1; hsync = 0; vsync = 0; crt = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	dcfg = read_vp(par, VP_DCFG);
+	dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
+			VP_DCFG_CRT_EN);
+	if (!blank)
+		dcfg |= VP_DCFG_DAC_BL_EN;
+	if (hsync)
+		dcfg |= VP_DCFG_HSYNC_EN;
+	if (vsync)
+		dcfg |= VP_DCFG_VSYNC_EN;
+	if (crt)
+		dcfg |= VP_DCFG_CRT_EN;
+	write_vp(par, VP_DCFG, dcfg);
+
+	/* Power on/off flat panel. */
+
+	if (par->enable_crt == 0) {
+		fp_pm = read_fp(par, FP_PM);
+		if (blank_mode == FB_BLANK_POWERDOWN)
+			fp_pm &= ~FP_PM_P;
+		else
+			fp_pm |= FP_PM_P;
+		write_fp(par, FP_PM, fp_pm);
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
new file mode 100644
index 000000000000..7f6c9e6cfc6c
--- /dev/null
+++ b/drivers/video/fbdev/goldfishfb.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (C) 2012 Intel, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+enum {
+	FB_GET_WIDTH        = 0x00,
+	FB_GET_HEIGHT       = 0x04,
+	FB_INT_STATUS       = 0x08,
+	FB_INT_ENABLE       = 0x0c,
+	FB_SET_BASE         = 0x10,
+	FB_SET_ROTATION     = 0x14,
+	FB_SET_BLANK        = 0x18,
+	FB_GET_PHYS_WIDTH   = 0x1c,
+	FB_GET_PHYS_HEIGHT  = 0x20,
+
+	FB_INT_VSYNC             = 1U << 0,
+	FB_INT_BASE_UPDATE_DONE  = 1U << 1
+};
+
+struct goldfish_fb {
+	void __iomem *reg_base;
+	int irq;
+	spinlock_t lock;
+	wait_queue_head_t wait;
+	int base_update_count;
+	int rotation;
+	struct fb_info fb;
+	u32 cmap[16];
+};
+
+static irqreturn_t goldfish_fb_interrupt(int irq, void *dev_id)
+{
+	unsigned long irq_flags;
+	struct goldfish_fb *fb = dev_id;
+	u32 status;
+
+	spin_lock_irqsave(&fb->lock, irq_flags);
+	status = readl(fb->reg_base + FB_INT_STATUS);
+	if (status & FB_INT_BASE_UPDATE_DONE) {
+		fb->base_update_count++;
+		wake_up(&fb->wait);
+	}
+	spin_unlock_irqrestore(&fb->lock, irq_flags);
+	return status ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
+{
+	unsigned int mask = (1 << bf->length) - 1;
+
+	return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
+static int
+goldfish_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+		 unsigned int blue, unsigned int transp, struct fb_info *info)
+{
+	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+
+	if (regno < 16) {
+		fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+				  convert_bitfield(blue, &fb->fb.var.blue) |
+				  convert_bitfield(green, &fb->fb.var.green) |
+				  convert_bitfield(red, &fb->fb.var.red);
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+static int goldfish_fb_check_var(struct fb_var_screeninfo *var,
+							struct fb_info *info)
+{
+	if ((var->rotate & 1) != (info->var.rotate & 1)) {
+		if ((var->xres != info->var.yres) ||
+				(var->yres != info->var.xres) ||
+				(var->xres_virtual != info->var.yres) ||
+				(var->yres_virtual > info->var.xres * 2) ||
+				(var->yres_virtual < info->var.xres)) {
+			return -EINVAL;
+		}
+	} else {
+		if ((var->xres != info->var.xres) ||
+		   (var->yres != info->var.yres) ||
+		   (var->xres_virtual != info->var.xres) ||
+		   (var->yres_virtual > info->var.yres * 2) ||
+		   (var->yres_virtual < info->var.yres)) {
+			return -EINVAL;
+		}
+	}
+	if ((var->xoffset != info->var.xoffset) ||
+			(var->bits_per_pixel != info->var.bits_per_pixel) ||
+			(var->grayscale != info->var.grayscale)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int goldfish_fb_set_par(struct fb_info *info)
+{
+	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+	if (fb->rotation != fb->fb.var.rotate) {
+		info->fix.line_length = info->var.xres * 2;
+		fb->rotation = fb->fb.var.rotate;
+		writel(fb->rotation, fb->reg_base + FB_SET_ROTATION);
+	}
+	return 0;
+}
+
+
+static int goldfish_fb_pan_display(struct fb_var_screeninfo *var,
+							struct fb_info *info)
+{
+	unsigned long irq_flags;
+	int base_update_count;
+	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+
+	spin_lock_irqsave(&fb->lock, irq_flags);
+	base_update_count = fb->base_update_count;
+	writel(fb->fb.fix.smem_start + fb->fb.var.xres * 2 * var->yoffset,
+						fb->reg_base + FB_SET_BASE);
+	spin_unlock_irqrestore(&fb->lock, irq_flags);
+	wait_event_timeout(fb->wait,
+			fb->base_update_count != base_update_count, HZ / 15);
+	if (fb->base_update_count == base_update_count)
+		pr_err("goldfish_fb_pan_display: timeout waiting for base update\n");
+	return 0;
+}
+
+static int goldfish_fb_blank(int blank, struct fb_info *info)
+{
+	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+	switch (blank) {
+	case FB_BLANK_NORMAL:
+		writel(1, fb->reg_base + FB_SET_BLANK);
+		break;
+	case FB_BLANK_UNBLANK:
+		writel(0, fb->reg_base + FB_SET_BLANK);
+		break;
+	}
+	return 0;
+}
+
+static struct fb_ops goldfish_fb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_check_var   = goldfish_fb_check_var,
+	.fb_set_par     = goldfish_fb_set_par,
+	.fb_setcolreg   = goldfish_fb_setcolreg,
+	.fb_pan_display = goldfish_fb_pan_display,
+	.fb_blank	= goldfish_fb_blank,
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+};
+
+
+static int goldfish_fb_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *r;
+	struct goldfish_fb *fb;
+	size_t framesize;
+	u32 width, height;
+	dma_addr_t fbpaddr;
+
+	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+	if (fb == NULL) {
+		ret = -ENOMEM;
+		goto err_fb_alloc_failed;
+	}
+	spin_lock_init(&fb->lock);
+	init_waitqueue_head(&fb->wait);
+	platform_set_drvdata(pdev, fb);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENODEV;
+		goto err_no_io_base;
+	}
+	fb->reg_base = ioremap(r->start, PAGE_SIZE);
+	if (fb->reg_base == NULL) {
+		ret = -ENOMEM;
+		goto err_no_io_base;
+	}
+
+	fb->irq = platform_get_irq(pdev, 0);
+	if (fb->irq <= 0) {
+		ret = -ENODEV;
+		goto err_no_irq;
+	}
+
+	width = readl(fb->reg_base + FB_GET_WIDTH);
+	height = readl(fb->reg_base + FB_GET_HEIGHT);
+
+	fb->fb.fbops		= &goldfish_fb_ops;
+	fb->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fb->fb.pseudo_palette	= fb->cmap;
+	fb->fb.fix.type		= FB_TYPE_PACKED_PIXELS;
+	fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+	fb->fb.fix.line_length = width * 2;
+	fb->fb.fix.accel	= FB_ACCEL_NONE;
+	fb->fb.fix.ypanstep = 1;
+
+	fb->fb.var.xres		= width;
+	fb->fb.var.yres		= height;
+	fb->fb.var.xres_virtual	= width;
+	fb->fb.var.yres_virtual	= height * 2;
+	fb->fb.var.bits_per_pixel = 16;
+	fb->fb.var.activate	= FB_ACTIVATE_NOW;
+	fb->fb.var.height	= readl(fb->reg_base + FB_GET_PHYS_HEIGHT);
+	fb->fb.var.width	= readl(fb->reg_base + FB_GET_PHYS_WIDTH);
+	fb->fb.var.pixclock	= 10000;
+
+	fb->fb.var.red.offset = 11;
+	fb->fb.var.red.length = 5;
+	fb->fb.var.green.offset = 5;
+	fb->fb.var.green.length = 6;
+	fb->fb.var.blue.offset = 0;
+	fb->fb.var.blue.length = 5;
+
+	framesize = width * height * 2 * 2;
+	fb->fb.screen_base = (char __force __iomem *)dma_alloc_coherent(
+						&pdev->dev, framesize,
+						&fbpaddr, GFP_KERNEL);
+	pr_debug("allocating frame buffer %d * %d, got %p\n",
+					width, height, fb->fb.screen_base);
+	if (fb->fb.screen_base == NULL) {
+		ret = -ENOMEM;
+		goto err_alloc_screen_base_failed;
+	}
+	fb->fb.fix.smem_start = fbpaddr;
+	fb->fb.fix.smem_len = framesize;
+
+	ret = fb_set_var(&fb->fb, &fb->fb.var);
+	if (ret)
+		goto err_fb_set_var_failed;
+
+	ret = request_irq(fb->irq, goldfish_fb_interrupt, IRQF_SHARED,
+							pdev->name, fb);
+	if (ret)
+		goto err_request_irq_failed;
+
+	writel(FB_INT_BASE_UPDATE_DONE, fb->reg_base + FB_INT_ENABLE);
+	goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */
+
+	ret = register_framebuffer(&fb->fb);
+	if (ret)
+		goto err_register_framebuffer_failed;
+	return 0;
+
+err_register_framebuffer_failed:
+	free_irq(fb->irq, fb);
+err_request_irq_failed:
+err_fb_set_var_failed:
+	dma_free_coherent(&pdev->dev, framesize,
+				(void *)fb->fb.screen_base,
+				fb->fb.fix.smem_start);
+err_alloc_screen_base_failed:
+err_no_irq:
+	iounmap(fb->reg_base);
+err_no_io_base:
+	kfree(fb);
+err_fb_alloc_failed:
+	return ret;
+}
+
+static int goldfish_fb_remove(struct platform_device *pdev)
+{
+	size_t framesize;
+	struct goldfish_fb *fb = platform_get_drvdata(pdev);
+
+	framesize = fb->fb.var.xres_virtual * fb->fb.var.yres_virtual * 2;
+	unregister_framebuffer(&fb->fb);
+	free_irq(fb->irq, fb);
+
+	dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base,
+						fb->fb.fix.smem_start);
+	iounmap(fb->reg_base);
+	return 0;
+}
+
+
+static struct platform_driver goldfish_fb_driver = {
+	.probe		= goldfish_fb_probe,
+	.remove		= goldfish_fb_remove,
+	.driver = {
+		.name = "goldfish_fb"
+	}
+};
+
+module_platform_driver(goldfish_fb_driver);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/grvga.c b/drivers/video/fbdev/grvga.c
new file mode 100644
index 000000000000..c078701f15f6
--- /dev/null
+++ b/drivers/video/fbdev/grvga.c
@@ -0,0 +1,562 @@
+/*
+ * Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
+ *
+ * 2011 (c) Aeroflex Gaisler AB
+ *
+ * Full documentation of the core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+
+struct grvga_regs {
+	u32 status; 		/* 0x00 */
+	u32 video_length; 	/* 0x04 */
+	u32 front_porch;	/* 0x08 */
+	u32 sync_length;	/* 0x0C */
+	u32 line_length;	/* 0x10 */
+	u32 fb_pos;		/* 0x14 */
+	u32 clk_vector[4];	/* 0x18 */
+	u32 clut;	        /* 0x20 */
+};
+
+struct grvga_par {
+	struct grvga_regs *regs;
+	u32 color_palette[16];  /* 16 entry pseudo palette used by fbcon in true color mode */
+	int clk_sel;
+	int fb_alloced;         /* = 1 if framebuffer is allocated in main memory */
+};
+
+
+static const struct fb_videomode grvga_modedb[] = {
+    {
+	/* 640x480 @ 60 Hz */
+	NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600 @ 60 Hz */
+	NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600 @ 72 Hz */
+	NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768 @ 60 Hz */
+	NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    }
+ };
+
+static struct fb_fix_screeninfo grvga_fix = {
+	.id =		"AG SVGACTRL",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =       FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	0,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int grvga_check_var(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	struct grvga_par *par = info->par;
+	int i;
+
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = 2*var->yres;
+
+	if (info->fix.smem_len) {
+		if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
+			return -ENOMEM;
+	}
+
+	/* Which clocks that are available can be read out in these registers */
+	for (i = 0; i <= 3 ; i++) {
+		if (var->pixclock == par->regs->clk_vector[i])
+			break;
+	}
+	if (i <= 3)
+		par->clk_sel = i;
+	else
+		return -EINVAL;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		var->red   = (struct fb_bitfield) {0, 8, 0};      /* offset, length, msb-right */
+		var->green = (struct fb_bitfield) {0, 8, 0};
+		var->blue  = (struct fb_bitfield) {0, 8, 0};
+		var->transp = (struct fb_bitfield) {0, 0, 0};
+		break;
+	case 16:
+		var->red   = (struct fb_bitfield) {11, 5, 0};
+		var->green = (struct fb_bitfield) {5, 6, 0};
+		var->blue  = (struct fb_bitfield) {0, 5, 0};
+		var->transp = (struct fb_bitfield) {0, 0, 0};
+		break;
+	case 24:
+	case 32:
+		var->red   = (struct fb_bitfield) {16, 8, 0};
+		var->green = (struct fb_bitfield) {8, 8, 0};
+		var->blue  = (struct fb_bitfield) {0, 8, 0};
+		var->transp = (struct fb_bitfield) {24, 8, 0};
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int grvga_set_par(struct fb_info *info)
+{
+
+	u32 func = 0;
+	struct grvga_par *par = info->par;
+
+	__raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1),
+		     &par->regs->video_length);
+
+	__raw_writel((info->var.lower_margin << 16) | (info->var.right_margin),
+		     &par->regs->front_porch);
+
+	__raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len),
+		     &par->regs->sync_length);
+
+	__raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
+		     (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1),
+		     &par->regs->line_length);
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		func = 1;
+		break;
+	case 16:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		func = 2;
+		break;
+	case 24:
+	case 32:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		func = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	__raw_writel((par->clk_sel << 6) | (func << 4) | 1,
+		     &par->regs->status);
+
+	info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
+	return 0;
+}
+
+static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
+{
+	struct grvga_par *par;
+	par = info->par;
+
+	if (regno >= 256)	/* Size of CLUT */
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+
+	red    = CNVT_TOHW(red,   info->var.red.length);
+	green  = CNVT_TOHW(green, info->var.green.length);
+	blue   = CNVT_TOHW(blue,  info->var.blue.length);
+	transp = CNVT_TOHW(transp, info->var.transp.length);
+
+#undef CNVT_TOHW
+
+	/* In PSEUDOCOLOR we use the hardware CLUT */
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+		__raw_writel((regno << 24) | (red << 16) | (green << 8) | blue,
+			     &par->regs->clut);
+
+	/* Truecolor uses the pseudo palette */
+	else if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+		if (regno >= 16)
+			return -EINVAL;
+
+
+		v =     (red    << info->var.red.offset)   |
+			(green  << info->var.green.offset) |
+			(blue   << info->var.blue.offset)  |
+			(transp << info->var.transp.offset);
+
+		((u32 *) (info->pseudo_palette))[regno] = v;
+	}
+	return 0;
+}
+
+static int grvga_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct grvga_par *par = info->par;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	u32 base_addr;
+
+	if (var->xoffset != 0)
+		return -EINVAL;
+
+	base_addr = fix->smem_start + (var->yoffset * fix->line_length);
+	base_addr &= ~3UL;
+
+	/* Set framebuffer base address  */
+	__raw_writel(base_addr,
+		     &par->regs->fb_pos);
+
+	return 0;
+}
+
+static struct fb_ops grvga_ops = {
+	.owner          = THIS_MODULE,
+	.fb_check_var   = grvga_check_var,
+	.fb_set_par	= grvga_set_par,
+	.fb_setcolreg   = grvga_setcolreg,
+	.fb_pan_display = grvga_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit
+};
+
+static int grvga_parse_custom(char *options,
+			      struct fb_var_screeninfo *screendata)
+{
+	char *this_opt;
+	int count = 0;
+	if (!options || !*options)
+		return -1;
+
+	while ((this_opt = strsep(&options, " ")) != NULL) {
+		if (!*this_opt)
+			continue;
+
+		switch (count) {
+		case 0:
+			screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 1:
+			screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 2:
+			screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 3:
+			screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 4:
+			screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 5:
+			screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 6:
+			screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 7:
+			screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 8:
+			screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 9:
+			screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		default:
+			return -1;
+		}
+	}
+	screendata->activate  = FB_ACTIVATE_NOW;
+	screendata->vmode     = FB_VMODE_NONINTERLACED;
+	return 0;
+}
+
+static int grvga_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	unsigned long virtual_start;
+	unsigned long grvga_fix_addr = 0;
+	unsigned long physical_start = 0;
+	unsigned long grvga_mem_size = 0;
+	struct grvga_par *par = NULL;
+	char *options = NULL, *mode_opt = NULL;
+
+	info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
+	if (!info) {
+		dev_err(&dev->dev, "framebuffer_alloc failed\n");
+		return -ENOMEM;
+	}
+
+	/* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
+	 *
+	 * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
+	 * If address is left out, we allocate memory,
+	 * if size is left out we only allocate enough to support the given mode.
+	 */
+	if (fb_get_options("grvga", &options)) {
+		retval = -ENODEV;
+		goto free_fb;
+	}
+
+	if (!options || !*options)
+		options =  "640x480-8@60";
+
+	while (1) {
+		char *this_opt = strsep(&options, ",");
+
+		if (!this_opt)
+			break;
+
+		if (!strncmp(this_opt, "custom", 6)) {
+			if (grvga_parse_custom(this_opt, &info->var) < 0) {
+				dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt);
+				retval = -EINVAL;
+				goto free_fb;
+			}
+		} else if (!strncmp(this_opt, "addr", 4))
+			grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
+		else if (!strncmp(this_opt, "size", 4))
+			grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_opt = this_opt;
+	}
+
+	par = info->par;
+	info->fbops = &grvga_ops;
+	info->fix = grvga_fix;
+	info->pseudo_palette = par->color_palette;
+	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+	info->fix.smem_len = grvga_mem_size;
+
+	if (!devm_request_mem_region(&dev->dev, dev->resource[0].start,
+		    resource_size(&dev->resource[0]), "grlib-svgactrl regs")) {
+		dev_err(&dev->dev, "registers already mapped\n");
+		retval = -EBUSY;
+		goto free_fb;
+	}
+
+	par->regs = of_ioremap(&dev->resource[0], 0,
+			       resource_size(&dev->resource[0]),
+			       "grlib-svgactrl regs");
+
+	if (!par->regs) {
+		dev_err(&dev->dev, "failed to map registers\n");
+		retval = -ENOMEM;
+		goto free_fb;
+	}
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0) {
+		dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
+		retval = -ENOMEM;
+		goto unmap_regs;
+	}
+
+	if (mode_opt) {
+		retval = fb_find_mode(&info->var, info, mode_opt,
+				      grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
+		if (!retval || retval == 4) {
+			retval = -EINVAL;
+			goto dealloc_cmap;
+		}
+	}
+
+	if (!grvga_mem_size)
+		grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
+
+	if (grvga_fix_addr) {
+		/* Got framebuffer base address from argument list */
+
+		physical_start = grvga_fix_addr;
+
+		if (!devm_request_mem_region(&dev->dev, physical_start,
+					     grvga_mem_size, dev->name)) {
+			dev_err(&dev->dev, "failed to request memory region\n");
+			retval = -ENOMEM;
+			goto dealloc_cmap;
+		}
+
+		virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
+
+		if (!virtual_start) {
+			dev_err(&dev->dev, "error mapping framebuffer memory\n");
+			retval = -ENOMEM;
+			goto dealloc_cmap;
+		}
+	} else {	/* Allocate frambuffer memory */
+
+		unsigned long page;
+
+		virtual_start = (unsigned long) __get_free_pages(GFP_DMA,
+								 get_order(grvga_mem_size));
+		if (!virtual_start) {
+			dev_err(&dev->dev,
+				"unable to allocate framebuffer memory (%lu bytes)\n",
+				grvga_mem_size);
+			retval = -ENOMEM;
+			goto dealloc_cmap;
+		}
+
+		physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE);
+
+		/* Set page reserved so that mmap will work. This is necessary
+		 * since we'll be remapping normal memory.
+		 */
+		for (page = virtual_start;
+		     page < PAGE_ALIGN(virtual_start + grvga_mem_size);
+		     page += PAGE_SIZE) {
+			SetPageReserved(virt_to_page(page));
+		}
+
+		par->fb_alloced = 1;
+	}
+
+	memset((unsigned long *) virtual_start, 0, grvga_mem_size);
+
+	info->screen_base = (char __iomem *) virtual_start;
+	info->fix.smem_start = physical_start;
+	info->fix.smem_len   = grvga_mem_size;
+
+	dev_set_drvdata(&dev->dev, info);
+
+	dev_info(&dev->dev,
+		 "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n",
+		 info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
+		 grvga_mem_size >> 10, info->screen_base);
+
+	retval = register_framebuffer(info);
+	if (retval < 0) {
+		dev_err(&dev->dev, "failed to register framebuffer\n");
+		goto free_mem;
+	}
+
+	__raw_writel(physical_start, &par->regs->fb_pos);
+	__raw_writel(__raw_readl(&par->regs->status) | 1,  /* Enable framebuffer */
+		     &par->regs->status);
+
+	return 0;
+
+free_mem:
+	if (grvga_fix_addr)
+		iounmap((void *)virtual_start);
+	else
+		kfree((void *)virtual_start);
+dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+unmap_regs:
+	of_iounmap(&dev->resource[0], par->regs,
+		   resource_size(&dev->resource[0]));
+free_fb:
+	framebuffer_release(info);
+
+	return retval;
+}
+
+static int grvga_remove(struct platform_device *device)
+{
+	struct fb_info *info = dev_get_drvdata(&device->dev);
+	struct grvga_par *par = info->par;
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+		of_iounmap(&device->resource[0], par->regs,
+			   resource_size(&device->resource[0]));
+
+		if (!par->fb_alloced)
+			iounmap(info->screen_base);
+		else
+			kfree((void *)info->screen_base);
+
+		framebuffer_release(info);
+	}
+
+	return 0;
+}
+
+static struct of_device_id svgactrl_of_match[] = {
+	{
+		.name = "GAISLER_SVGACTRL",
+	},
+	{
+		.name = "01_063",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, svgactrl_of_match);
+
+static struct platform_driver grvga_driver = {
+	.driver = {
+		.name = "grlib-svgactrl",
+		.owner = THIS_MODULE,
+		.of_match_table = svgactrl_of_match,
+	},
+	.probe		= grvga_probe,
+	.remove		= grvga_remove,
+};
+
+module_platform_driver(grvga_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Aeroflex Gaisler");
+MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");
diff --git a/drivers/video/fbdev/gxt4500.c b/drivers/video/fbdev/gxt4500.c
new file mode 100644
index 000000000000..135d78a02588
--- /dev/null
+++ b/drivers/video/fbdev/gxt4500.c
@@ -0,0 +1,783 @@
+/*
+ * Frame buffer device for IBM GXT4500P/6500P and GXT4000P/6000P
+ * display adaptors
+ *
+ * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+
+#define PCI_DEVICE_ID_IBM_GXT4500P	0x21c
+#define PCI_DEVICE_ID_IBM_GXT6500P	0x21b
+#define PCI_DEVICE_ID_IBM_GXT4000P	0x16e
+#define PCI_DEVICE_ID_IBM_GXT6000P	0x170
+
+/* GXT4500P registers */
+
+/* Registers in PCI config space */
+#define CFG_ENDIAN0		0x40
+
+/* Misc control/status registers */
+#define STATUS			0x1000
+#define CTRL_REG0		0x1004
+#define   CR0_HALT_DMA			0x4
+#define   CR0_RASTER_RESET		0x8
+#define   CR0_GEOM_RESET		0x10
+#define   CR0_MEM_CTRLER_RESET		0x20
+
+/* Framebuffer control registers */
+#define FB_AB_CTRL		0x1100
+#define FB_CD_CTRL		0x1104
+#define FB_WID_CTRL		0x1108
+#define FB_Z_CTRL		0x110c
+#define FB_VGA_CTRL		0x1110
+#define REFRESH_AB_CTRL		0x1114
+#define REFRESH_CD_CTRL		0x1118
+#define FB_OVL_CTRL		0x111c
+#define   FB_CTRL_TYPE			0x80000000
+#define   FB_CTRL_WIDTH_MASK		0x007f0000
+#define   FB_CTRL_WIDTH_SHIFT		16
+#define   FB_CTRL_START_SEG_MASK	0x00003fff
+
+#define REFRESH_START		0x1098
+#define REFRESH_SIZE		0x109c
+
+/* "Direct" framebuffer access registers */
+#define DFA_FB_A		0x11e0
+#define DFA_FB_B		0x11e4
+#define DFA_FB_C		0x11e8
+#define DFA_FB_D		0x11ec
+#define   DFA_FB_ENABLE			0x80000000
+#define   DFA_FB_BASE_MASK		0x03f00000
+#define   DFA_FB_STRIDE_1k		0x00000000
+#define   DFA_FB_STRIDE_2k		0x00000010
+#define   DFA_FB_STRIDE_4k		0x00000020
+#define   DFA_PIX_8BIT			0x00000000
+#define   DFA_PIX_16BIT_565		0x00000001
+#define   DFA_PIX_16BIT_1555		0x00000002
+#define   DFA_PIX_24BIT			0x00000004
+#define   DFA_PIX_32BIT			0x00000005
+
+/* maps DFA_PIX_* to pixel size in bytes */
+static const unsigned char pixsize[] = {
+	1, 2, 2, 2, 4, 4
+};
+
+/* Display timing generator registers */
+#define DTG_CONTROL		0x1900
+#define   DTG_CTL_SCREEN_REFRESH	2
+#define   DTG_CTL_ENABLE		1
+#define DTG_HORIZ_EXTENT	0x1904
+#define DTG_HORIZ_DISPLAY	0x1908
+#define DTG_HSYNC_START		0x190c
+#define DTG_HSYNC_END		0x1910
+#define DTG_HSYNC_END_COMP	0x1914
+#define DTG_VERT_EXTENT		0x1918
+#define DTG_VERT_DISPLAY	0x191c
+#define DTG_VSYNC_START		0x1920
+#define DTG_VSYNC_END		0x1924
+#define DTG_VERT_SHORT		0x1928
+
+/* PLL/RAMDAC registers */
+#define DISP_CTL		0x402c
+#define   DISP_CTL_OFF			2
+#define SYNC_CTL		0x4034
+#define   SYNC_CTL_SYNC_ON_RGB		1
+#define   SYNC_CTL_SYNC_OFF		2
+#define   SYNC_CTL_HSYNC_INV		8
+#define   SYNC_CTL_VSYNC_INV		0x10
+#define   SYNC_CTL_HSYNC_OFF		0x20
+#define   SYNC_CTL_VSYNC_OFF		0x40
+
+#define PLL_M			0x4040
+#define PLL_N			0x4044
+#define PLL_POSTDIV		0x4048
+#define PLL_C			0x404c
+
+/* Hardware cursor */
+#define CURSOR_X		0x4078
+#define CURSOR_Y		0x407c
+#define CURSOR_HOTSPOT		0x4080
+#define CURSOR_MODE		0x4084
+#define   CURSOR_MODE_OFF		0
+#define   CURSOR_MODE_4BPP		1
+#define CURSOR_PIXMAP		0x5000
+#define CURSOR_CMAP		0x7400
+
+/* Window attribute table */
+#define WAT_FMT			0x4100
+#define   WAT_FMT_24BIT			0
+#define   WAT_FMT_16BIT_565		1
+#define   WAT_FMT_16BIT_1555		2
+#define   WAT_FMT_32BIT			3	/* 0 vs. 3 is a guess */
+#define   WAT_FMT_8BIT_332		9
+#define   WAT_FMT_8BIT			0xa
+#define   WAT_FMT_NO_CMAP		4	/* ORd in to other values */
+#define WAT_CMAP_OFFSET		0x4104		/* 4-bit value gets << 6 */
+#define WAT_CTRL		0x4108
+#define   WAT_CTRL_SEL_B		1	/* select B buffer if 1 */
+#define   WAT_CTRL_NO_INC		2
+#define WAT_GAMMA_CTRL		0x410c
+#define   WAT_GAMMA_DISABLE		1	/* disables gamma cmap */
+#define WAT_OVL_CTRL		0x430c		/* controls overlay */
+
+/* Indexed by DFA_PIX_* values */
+static const unsigned char watfmt[] = {
+	WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0,
+	WAT_FMT_24BIT, WAT_FMT_32BIT
+};
+
+/* Colormap array; 1k entries of 4 bytes each */
+#define CMAP			0x6000
+
+#define readreg(par, reg)	readl((par)->regs + (reg))
+#define writereg(par, reg, val)	writel((val), (par)->regs + (reg))
+
+struct gxt4500_par {
+	void __iomem *regs;
+
+	int pixfmt;		/* pixel format, see DFA_PIX_* values */
+
+	/* PLL parameters */
+	int refclk_ps;		/* ref clock period in picoseconds */
+	int pll_m;		/* ref clock divisor */
+	int pll_n;		/* VCO divisor */
+	int pll_pd1;		/* first post-divisor */
+	int pll_pd2;		/* second post-divisor */
+
+	u32 pseudo_palette[16];	/* used in color blits */
+};
+
+/* mode requested by user */
+static char *mode_option;
+
+/* default mode: 1280x1024 @ 60 Hz, 8 bpp */
+static const struct fb_videomode defaultmode = {
+	.refresh = 60,
+	.xres = 1280,
+	.yres = 1024,
+	.pixclock = 9295,
+	.left_margin = 248,
+	.right_margin = 48,
+	.upper_margin = 38,
+	.lower_margin = 1,
+	.hsync_len = 112,
+	.vsync_len = 3,
+	.vmode = FB_VMODE_NONINTERLACED
+};
+
+/* List of supported cards */
+enum gxt_cards {
+	GXT4500P,
+	GXT6500P,
+	GXT4000P,
+	GXT6000P
+};
+
+/* Card-specific information */
+static const struct cardinfo {
+	int	refclk_ps;	/* period of PLL reference clock in ps */
+	const char *cardname;
+} cardinfo[] = {
+	[GXT4500P] = { .refclk_ps = 9259, .cardname = "IBM GXT4500P" },
+	[GXT6500P] = { .refclk_ps = 9259, .cardname = "IBM GXT6500P" },
+	[GXT4000P] = { .refclk_ps = 40000, .cardname = "IBM GXT4000P" },
+	[GXT6000P] = { .refclk_ps = 40000, .cardname = "IBM GXT6000P" },
+};
+
+/*
+ * The refclk and VCO dividers appear to use a linear feedback shift
+ * register, which gets reloaded when it reaches a terminal value, at
+ * which point the divider output is toggled.  Thus one can obtain
+ * whatever divisor is required by putting the appropriate value into
+ * the reload register.  For a divisor of N, one puts the value from
+ * the LFSR sequence that comes N-1 places before the terminal value
+ * into the reload register.
+ */
+
+static const unsigned char mdivtab[] = {
+/* 1 */		      0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a,
+/* 10 */	0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11,
+/* 20 */	0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d,
+/* 30 */	0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02,
+/* 40 */	0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e,
+/* 50 */	0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e,
+/* 60 */	0x1f, 0x0f, 0x07, 0x03, 0x01,
+};
+
+static const unsigned char ndivtab[] = {
+/* 2 */		            0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e,
+/* 10 */	0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e,
+/* 20 */	0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf,
+/* 30 */	0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc,
+/* 40 */	0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8,
+/* 50 */	0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6,
+/* 60 */	0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62,
+/* 70 */	0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57,
+/* 80 */	0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94,
+/* 90 */	0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79,
+/* 100 */	0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24,
+/* 110 */	0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45,
+/* 120 */	0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d,
+/* 130 */	0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e,
+/* 140 */	0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98,
+/* 150 */	0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2,
+/* 160 */	0x69,
+};
+
+static int calc_pll(int period_ps, struct gxt4500_par *par)
+{
+	int m, n, pdiv1, pdiv2, postdiv;
+	int pll_period, best_error, t, intf;
+
+	/* only deal with range 5MHz - 300MHz */
+	if (period_ps < 3333 || period_ps > 200000)
+		return -1;
+
+	best_error = 1000000;
+	for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) {
+		for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) {
+			postdiv = pdiv1 * pdiv2;
+			pll_period = DIV_ROUND_UP(period_ps, postdiv);
+			/* keep pll in range 350..600 MHz */
+			if (pll_period < 1666 || pll_period > 2857)
+				continue;
+			for (m = 1; m <= 64; ++m) {
+				intf = m * par->refclk_ps;
+				if (intf > 500000)
+					break;
+				n = intf * postdiv / period_ps;
+				if (n < 3 || n > 160)
+					continue;
+				t = par->refclk_ps * m * postdiv / n;
+				t -= period_ps;
+				if (t >= 0 && t < best_error) {
+					par->pll_m = m;
+					par->pll_n = n;
+					par->pll_pd1 = pdiv1;
+					par->pll_pd2 = pdiv2;
+					best_error = t;
+				}
+			}
+		}
+	}
+	if (best_error == 1000000)
+		return -1;
+	return 0;
+}
+
+static int calc_pixclock(struct gxt4500_par *par)
+{
+	return par->refclk_ps * par->pll_m * par->pll_pd1 * par->pll_pd2
+		/ par->pll_n;
+}
+
+static int gxt4500_var_to_par(struct fb_var_screeninfo *var,
+			      struct gxt4500_par *par)
+{
+	if (var->xres + var->xoffset > var->xres_virtual ||
+	    var->yres + var->yoffset > var->yres_virtual ||
+	    var->xres_virtual > 4096)
+		return -EINVAL;
+	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	if (calc_pll(var->pixclock, par) < 0)
+		return -EINVAL;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+		if (var->transp.length)
+			par->pixfmt = DFA_PIX_32BIT;
+		else
+			par->pixfmt = DFA_PIX_24BIT;
+		break;
+	case 24:
+		par->pixfmt = DFA_PIX_24BIT;
+		break;
+	case 16:
+		if (var->green.length == 5)
+			par->pixfmt = DFA_PIX_16BIT_1555;
+		else
+			par->pixfmt = DFA_PIX_16BIT_565;
+		break;
+	case 8:
+		par->pixfmt = DFA_PIX_8BIT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct fb_bitfield eightbits = {0, 8};
+static const struct fb_bitfield nobits = {0, 0};
+
+static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var,
+				  int pixfmt)
+{
+	var->bits_per_pixel = pixsize[pixfmt] * 8;
+	var->red = eightbits;
+	var->green = eightbits;
+	var->blue = eightbits;
+	var->transp = nobits;
+
+	switch (pixfmt) {
+	case DFA_PIX_16BIT_565:
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case DFA_PIX_16BIT_1555:
+		var->red.length = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		var->transp.length = 1;
+		break;
+	case DFA_PIX_32BIT:
+		var->transp.length = 8;
+		break;
+	}
+	if (pixfmt != DFA_PIX_8BIT) {
+		var->green.offset = var->red.length;
+		var->blue.offset = var->green.offset + var->green.length;
+		if (var->transp.length)
+			var->transp.offset =
+				var->blue.offset + var->blue.length;
+	}
+}
+
+static int gxt4500_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct gxt4500_par par;
+	int err;
+
+	par = *(struct gxt4500_par *)info->par;
+	err = gxt4500_var_to_par(var, &par);
+	if (!err) {
+		var->pixclock = calc_pixclock(&par);
+		gxt4500_unpack_pixfmt(var, par.pixfmt);
+	}
+	return err;
+}
+
+static int gxt4500_set_par(struct fb_info *info)
+{
+	struct gxt4500_par *par = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int err;
+	u32 ctrlreg, tmp;
+	unsigned int dfa_ctl, pixfmt, stride;
+	unsigned int wid_tiles, i;
+	unsigned int prefetch_pix, htot;
+	struct gxt4500_par save_par;
+
+	save_par = *par;
+	err = gxt4500_var_to_par(var, par);
+	if (err) {
+		*par = save_par;
+		return err;
+	}
+
+	/* turn off DTG for now */
+	ctrlreg = readreg(par, DTG_CONTROL);
+	ctrlreg &= ~(DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH);
+	writereg(par, DTG_CONTROL, ctrlreg);
+
+	/* set PLL registers */
+	tmp = readreg(par, PLL_C) & ~0x7f;
+	if (par->pll_n < 38)
+		tmp |= 0x29;
+	if (par->pll_n < 69)
+		tmp |= 0x35;
+	else if (par->pll_n < 100)
+		tmp |= 0x76;
+	else
+		tmp |= 0x7e;
+	writereg(par, PLL_C, tmp);
+	writereg(par, PLL_M, mdivtab[par->pll_m - 1]);
+	writereg(par, PLL_N, ndivtab[par->pll_n - 2]);
+	tmp = ((8 - par->pll_pd2) << 3) | (8 - par->pll_pd1);
+	if (par->pll_pd1 == 8 || par->pll_pd2 == 8) {
+		/* work around erratum */
+		writereg(par, PLL_POSTDIV, tmp | 0x9);
+		udelay(1);
+	}
+	writereg(par, PLL_POSTDIV, tmp);
+	msleep(20);
+
+	/* turn off hardware cursor */
+	writereg(par, CURSOR_MODE, CURSOR_MODE_OFF);
+
+	/* reset raster engine */
+	writereg(par, CTRL_REG0, CR0_RASTER_RESET | (CR0_RASTER_RESET << 16));
+	udelay(10);
+	writereg(par, CTRL_REG0, CR0_RASTER_RESET << 16);
+
+	/* set display timing generator registers */
+	htot = var->xres + var->left_margin + var->right_margin +
+		var->hsync_len;
+	writereg(par, DTG_HORIZ_EXTENT, htot - 1);
+	writereg(par, DTG_HORIZ_DISPLAY, var->xres - 1);
+	writereg(par, DTG_HSYNC_START, var->xres + var->right_margin - 1);
+	writereg(par, DTG_HSYNC_END,
+		 var->xres + var->right_margin + var->hsync_len - 1);
+	writereg(par, DTG_HSYNC_END_COMP,
+		 var->xres + var->right_margin + var->hsync_len - 1);
+	writereg(par, DTG_VERT_EXTENT,
+		 var->yres + var->upper_margin + var->lower_margin +
+		 var->vsync_len - 1);
+	writereg(par, DTG_VERT_DISPLAY, var->yres - 1);
+	writereg(par, DTG_VSYNC_START, var->yres + var->lower_margin - 1);
+	writereg(par, DTG_VSYNC_END,
+		 var->yres + var->lower_margin + var->vsync_len - 1);
+	prefetch_pix = 3300000 / var->pixclock;
+	if (prefetch_pix >= htot)
+		prefetch_pix = htot - 1;
+	writereg(par, DTG_VERT_SHORT, htot - prefetch_pix - 1);
+	ctrlreg |= DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH;
+	writereg(par, DTG_CONTROL, ctrlreg);
+
+	/* calculate stride in DFA aperture */
+	if (var->xres_virtual > 2048) {
+		stride = 4096;
+		dfa_ctl = DFA_FB_STRIDE_4k;
+	} else if (var->xres_virtual > 1024) {
+		stride = 2048;
+		dfa_ctl = DFA_FB_STRIDE_2k;
+	} else {
+		stride = 1024;
+		dfa_ctl = DFA_FB_STRIDE_1k;
+	}
+
+	/* Set up framebuffer definition */
+	wid_tiles = (var->xres_virtual + 63) >> 6;
+
+	/* XXX add proper FB allocation here someday */
+	writereg(par, FB_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+	writereg(par, REFRESH_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+	writereg(par, FB_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+	writereg(par, REFRESH_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+	writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
+	writereg(par, REFRESH_SIZE, (var->xres << 16) | var->yres);
+
+	/* Set up framebuffer access by CPU */
+
+	pixfmt = par->pixfmt;
+	dfa_ctl |= DFA_FB_ENABLE | pixfmt;
+	writereg(par, DFA_FB_A, dfa_ctl);
+
+	/*
+	 * Set up window attribute table.
+	 * We set all WAT entries the same so it doesn't matter what the
+	 * window ID (WID) plane contains.
+	 */
+	for (i = 0; i < 32; ++i) {
+		writereg(par, WAT_FMT + (i << 4), watfmt[pixfmt]);
+		writereg(par, WAT_CMAP_OFFSET + (i << 4), 0);
+		writereg(par, WAT_CTRL + (i << 4), 0);
+		writereg(par, WAT_GAMMA_CTRL + (i << 4), WAT_GAMMA_DISABLE);
+	}
+
+	/* Set sync polarity etc. */
+	ctrlreg = readreg(par, SYNC_CTL) &
+		~(SYNC_CTL_SYNC_ON_RGB | SYNC_CTL_HSYNC_INV |
+		  SYNC_CTL_VSYNC_INV);
+	if (var->sync & FB_SYNC_ON_GREEN)
+		ctrlreg |= SYNC_CTL_SYNC_ON_RGB;
+	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+		ctrlreg |= SYNC_CTL_HSYNC_INV;
+	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+		ctrlreg |= SYNC_CTL_VSYNC_INV;
+	writereg(par, SYNC_CTL, ctrlreg);
+
+	info->fix.line_length = stride * pixsize[pixfmt];
+	info->fix.visual = (pixfmt == DFA_PIX_8BIT)? FB_VISUAL_PSEUDOCOLOR:
+		FB_VISUAL_DIRECTCOLOR;
+
+	return 0;
+}
+
+static int gxt4500_setcolreg(unsigned int reg, unsigned int red,
+			     unsigned int green, unsigned int blue,
+			     unsigned int transp, struct fb_info *info)
+{
+	u32 cmap_entry;
+	struct gxt4500_par *par = info->par;
+
+	if (reg > 1023)
+		return 1;
+	cmap_entry = ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
+		(green & 0xff00) | (blue >> 8);
+	writereg(par, CMAP + reg * 4, cmap_entry);
+
+	if (reg < 16 && par->pixfmt != DFA_PIX_8BIT) {
+		u32 *pal = info->pseudo_palette;
+		u32 val = reg;
+		switch (par->pixfmt) {
+		case DFA_PIX_16BIT_565:
+			val |= (reg << 11) | (reg << 6);
+			break;
+		case DFA_PIX_16BIT_1555:
+			val |= (reg << 10) | (reg << 5);
+			break;
+		case DFA_PIX_32BIT:
+			val |= (reg << 24);
+			/* fall through */
+		case DFA_PIX_24BIT:
+			val |= (reg << 16) | (reg << 8);
+			break;
+		}
+		pal[reg] = val;
+	}
+
+	return 0;
+}
+
+static int gxt4500_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	struct gxt4500_par *par = info->par;
+
+	if (var->xoffset & 7)
+		return -EINVAL;
+	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+	    var->yoffset + info->var.yres > info->var.yres_virtual)
+		return -EINVAL;
+
+	writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
+	return 0;
+}
+
+static int gxt4500_blank(int blank, struct fb_info *info)
+{
+	struct gxt4500_par *par = info->par;
+	int ctrl, dctl;
+
+	ctrl = readreg(par, SYNC_CTL);
+	ctrl &= ~(SYNC_CTL_SYNC_OFF | SYNC_CTL_HSYNC_OFF | SYNC_CTL_VSYNC_OFF);
+	dctl = readreg(par, DISP_CTL);
+	dctl |= DISP_CTL_OFF;
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		dctl &= ~DISP_CTL_OFF;
+		break;
+	case FB_BLANK_POWERDOWN:
+		ctrl |= SYNC_CTL_SYNC_OFF;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		ctrl |= SYNC_CTL_HSYNC_OFF;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		ctrl |= SYNC_CTL_VSYNC_OFF;
+		break;
+	default: ;
+	}
+	writereg(par, SYNC_CTL, ctrl);
+	writereg(par, DISP_CTL, dctl);
+
+	return 0;
+}
+
+static const struct fb_fix_screeninfo gxt4500_fix = {
+	.id = "IBM GXT4500P",
+	.type = FB_TYPE_PACKED_PIXELS,
+	.visual = FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep = 8,
+	.ypanstep = 1,
+	.mmio_len = 0x20000,
+};
+
+static struct fb_ops gxt4500_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = gxt4500_check_var,
+	.fb_set_par = gxt4500_set_par,
+	.fb_setcolreg = gxt4500_setcolreg,
+	.fb_pan_display = gxt4500_pan_display,
+	.fb_blank = gxt4500_blank,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+};
+
+/* PCI functions */
+static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int err;
+	unsigned long reg_phys, fb_phys;
+	struct gxt4500_par *par;
+	struct fb_info *info;
+	struct fb_var_screeninfo var;
+	enum gxt_cards cardtype;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n",
+			err);
+		return err;
+	}
+
+	reg_phys = pci_resource_start(pdev, 0);
+	if (!request_mem_region(reg_phys, pci_resource_len(pdev, 0),
+				"gxt4500 regs")) {
+		dev_err(&pdev->dev, "gxt4500: cannot get registers\n");
+		goto err_nodev;
+	}
+
+	fb_phys = pci_resource_start(pdev, 1);
+	if (!request_mem_region(fb_phys, pci_resource_len(pdev, 1),
+				"gxt4500 FB")) {
+		dev_err(&pdev->dev, "gxt4500: cannot get framebuffer\n");
+		goto err_free_regs;
+	}
+
+	info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev);
+	if (!info) {
+		dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record\n");
+		goto err_free_fb;
+	}
+	par = info->par;
+	cardtype = ent->driver_data;
+	par->refclk_ps = cardinfo[cardtype].refclk_ps;
+	info->fix = gxt4500_fix;
+	strlcpy(info->fix.id, cardinfo[cardtype].cardname,
+		sizeof(info->fix.id));
+	info->pseudo_palette = par->pseudo_palette;
+
+	info->fix.mmio_start = reg_phys;
+	par->regs = pci_ioremap_bar(pdev, 0);
+	if (!par->regs) {
+		dev_err(&pdev->dev, "gxt4500: cannot map registers\n");
+		goto err_free_all;
+	}
+
+	info->fix.smem_start = fb_phys;
+	info->fix.smem_len = pci_resource_len(pdev, 1);
+	info->screen_base = pci_ioremap_bar(pdev, 1);
+	if (!info->screen_base) {
+		dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n");
+		goto err_unmap_regs;
+	}
+
+	pci_set_drvdata(pdev, info);
+
+	/* Set byte-swapping for DFA aperture for all pixel sizes */
+	pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300);
+
+	info->fbops = &gxt4500_ops;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	err = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (err) {
+		dev_err(&pdev->dev, "gxt4500: cannot allocate cmap\n");
+		goto err_unmap_all;
+	}
+
+	gxt4500_blank(FB_BLANK_UNBLANK, info);
+
+	if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8)) {
+		dev_err(&pdev->dev, "gxt4500: cannot find valid video mode\n");
+		goto err_free_cmap;
+	}
+	info->var = var;
+	if (gxt4500_set_par(info)) {
+		printk(KERN_ERR "gxt4500: cannot set video mode\n");
+		goto err_free_cmap;
+	}
+
+	if (register_framebuffer(info) < 0) {
+		dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n");
+		goto err_free_cmap;
+	}
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	return 0;
+
+ err_free_cmap:
+	fb_dealloc_cmap(&info->cmap);
+ err_unmap_all:
+	iounmap(info->screen_base);
+ err_unmap_regs:
+	iounmap(par->regs);
+ err_free_all:
+	framebuffer_release(info);
+ err_free_fb:
+	release_mem_region(fb_phys, pci_resource_len(pdev, 1));
+ err_free_regs:
+	release_mem_region(reg_phys, pci_resource_len(pdev, 0));
+ err_nodev:
+	return -ENODEV;
+}
+
+static void gxt4500_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct gxt4500_par *par;
+
+	if (!info)
+		return;
+	par = info->par;
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+	iounmap(par->regs);
+	iounmap(info->screen_base);
+	release_mem_region(pci_resource_start(pdev, 0),
+			   pci_resource_len(pdev, 0));
+	release_mem_region(pci_resource_start(pdev, 1),
+			   pci_resource_len(pdev, 1));
+	framebuffer_release(info);
+}
+
+/* supported chipsets */
+static const struct pci_device_id gxt4500_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P),
+	  .driver_data = GXT4500P },
+	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT6500P),
+	  .driver_data = GXT6500P },
+	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4000P),
+	  .driver_data = GXT4000P },
+	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT6000P),
+	  .driver_data = GXT6000P },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, gxt4500_pci_tbl);
+
+static struct pci_driver gxt4500_driver = {
+	.name = "gxt4500",
+	.id_table = gxt4500_pci_tbl,
+	.probe = gxt4500_probe,
+	.remove = gxt4500_remove,
+};
+
+static int gxt4500_init(void)
+{
+#ifndef MODULE
+	if (fb_get_options("gxt4500", &mode_option))
+		return -ENODEV;
+#endif
+
+	return pci_register_driver(&gxt4500_driver);
+}
+module_init(gxt4500_init);
+
+static void __exit gxt4500_exit(void)
+{
+	pci_unregister_driver(&gxt4500_driver);
+}
+module_exit(gxt4500_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P/6500P and GXT4000P/6000P");
+MODULE_LICENSE("GPL");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
diff --git a/drivers/video/fbdev/hecubafb.c b/drivers/video/fbdev/hecubafb.c
new file mode 100644
index 000000000000..f64120ec9192
--- /dev/null
+++ b/drivers/video/fbdev/hecubafb.c
@@ -0,0 +1,311 @@
+/*
+ * linux/drivers/video/hecubafb.c -- FB driver for Hecuba/Apollo controller
+ *
+ * Copyright (C) 2006, Jaya Kumar
+ * This work was sponsored by CIS(M) Sdn Bhd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ * This work was possible because of apollo display code from E-Ink's website
+ * http://support.eink.com/community
+ * All information used to write this code is from public material made
+ * available by E-Ink on its support site. Some commands such as 0xA4
+ * were found by looping through cmd=0x00 thru 0xFF and supplying random
+ * values. There are other commands that the display is capable of,
+ * beyond the 5 used here but they are more complex.
+ *
+ * This driver is written to be used with the Hecuba display architecture.
+ * The actual display chip is called Apollo and the interface electronics
+ * it needs is called Hecuba.
+ *
+ * It is intended to be architecture independent. A board specific driver
+ * must be used to perform all the physical IO interactions. An example
+ * is provided as n411.c
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+
+#include <video/hecubafb.h>
+
+/* Display specific information */
+#define DPY_W 600
+#define DPY_H 800
+
+static struct fb_fix_screeninfo hecubafb_fix = {
+	.id =		"hecubafb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_MONO01,
+	.xpanstep =	0,
+	.ypanstep =	0,
+	.ywrapstep =	0,
+	.line_length =	DPY_W,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo hecubafb_var = {
+	.xres		= DPY_W,
+	.yres		= DPY_H,
+	.xres_virtual	= DPY_W,
+	.yres_virtual	= DPY_H,
+	.bits_per_pixel	= 1,
+	.nonstd		= 1,
+};
+
+/* main hecubafb functions */
+
+static void apollo_send_data(struct hecubafb_par *par, unsigned char data)
+{
+	/* set data */
+	par->board->set_data(par, data);
+
+	/* set DS low */
+	par->board->set_ctl(par, HCB_DS_BIT, 0);
+
+	/* wait for ack */
+	par->board->wait_for_ack(par, 0);
+
+	/* set DS hi */
+	par->board->set_ctl(par, HCB_DS_BIT, 1);
+
+	/* wait for ack to clear */
+	par->board->wait_for_ack(par, 1);
+}
+
+static void apollo_send_command(struct hecubafb_par *par, unsigned char data)
+{
+	/* command so set CD to high */
+	par->board->set_ctl(par, HCB_CD_BIT, 1);
+
+	/* actually strobe with command */
+	apollo_send_data(par, data);
+
+	/* clear CD back to low */
+	par->board->set_ctl(par, HCB_CD_BIT, 0);
+}
+
+static void hecubafb_dpy_update(struct hecubafb_par *par)
+{
+	int i;
+	unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+
+	apollo_send_command(par, APOLLO_START_NEW_IMG);
+
+	for (i=0; i < (DPY_W*DPY_H/8); i++) {
+		apollo_send_data(par, *(buf++));
+	}
+
+	apollo_send_command(par, APOLLO_STOP_IMG_DATA);
+	apollo_send_command(par, APOLLO_DISPLAY_IMG);
+}
+
+/* this is called back from the deferred io workqueue */
+static void hecubafb_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	hecubafb_dpy_update(info->par);
+}
+
+static void hecubafb_fillrect(struct fb_info *info,
+				   const struct fb_fillrect *rect)
+{
+	struct hecubafb_par *par = info->par;
+
+	sys_fillrect(info, rect);
+
+	hecubafb_dpy_update(par);
+}
+
+static void hecubafb_copyarea(struct fb_info *info,
+				   const struct fb_copyarea *area)
+{
+	struct hecubafb_par *par = info->par;
+
+	sys_copyarea(info, area);
+
+	hecubafb_dpy_update(par);
+}
+
+static void hecubafb_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	struct hecubafb_par *par = info->par;
+
+	sys_imageblit(info, image);
+
+	hecubafb_dpy_update(par);
+}
+
+/*
+ * this is the slow path from userspace. they can seek and write to
+ * the fb. it's inefficient to do anything less than a full screen draw
+ */
+static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct hecubafb_par *par = info->par;
+	unsigned long p = *ppos;
+	void *dst;
+	int err = 0;
+	unsigned long total_size;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
+		count = total_size - p;
+	}
+
+	dst = (void __force *) (info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		err = -EFAULT;
+
+	if  (!err)
+		*ppos += count;
+
+	hecubafb_dpy_update(par);
+
+	return (err) ? err : count;
+}
+
+static struct fb_ops hecubafb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read        = fb_sys_read,
+	.fb_write	= hecubafb_write,
+	.fb_fillrect	= hecubafb_fillrect,
+	.fb_copyarea	= hecubafb_copyarea,
+	.fb_imageblit	= hecubafb_imageblit,
+};
+
+static struct fb_deferred_io hecubafb_defio = {
+	.delay		= HZ,
+	.deferred_io	= hecubafb_dpy_deferred_io,
+};
+
+static int hecubafb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	struct hecuba_board *board;
+	int retval = -ENOMEM;
+	int videomemorysize;
+	unsigned char *videomemory;
+	struct hecubafb_par *par;
+
+	/* pick up board specific routines */
+	board = dev->dev.platform_data;
+	if (!board)
+		return -EINVAL;
+
+	/* try to count device specific driver, if can't, platform recalls */
+	if (!try_module_get(board->owner))
+		return -ENODEV;
+
+	videomemorysize = (DPY_W*DPY_H)/8;
+
+	videomemory = vzalloc(videomemorysize);
+	if (!videomemory)
+		goto err_videomem_alloc;
+
+	info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
+	if (!info)
+		goto err_fballoc;
+
+	info->screen_base = (char __force __iomem *)videomemory;
+	info->fbops = &hecubafb_ops;
+
+	info->var = hecubafb_var;
+	info->fix = hecubafb_fix;
+	info->fix.smem_len = videomemorysize;
+	par = info->par;
+	par->info = info;
+	par->board = board;
+	par->send_command = apollo_send_command;
+	par->send_data = apollo_send_data;
+
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+
+	info->fbdefio = &hecubafb_defio;
+	fb_deferred_io_init(info);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_fbreg;
+	platform_set_drvdata(dev, info);
+
+	fb_info(info, "Hecuba frame buffer device, using %dK of video memory\n",
+		videomemorysize >> 10);
+
+	/* this inits the dpy */
+	retval = par->board->init(par);
+	if (retval < 0)
+		goto err_fbreg;
+
+	return 0;
+err_fbreg:
+	framebuffer_release(info);
+err_fballoc:
+	vfree(videomemory);
+err_videomem_alloc:
+	module_put(board->owner);
+	return retval;
+}
+
+static int hecubafb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		struct hecubafb_par *par = info->par;
+		fb_deferred_io_cleanup(info);
+		unregister_framebuffer(info);
+		vfree((void __force *)info->screen_base);
+		if (par->board->remove)
+			par->board->remove(par);
+		module_put(par->board->owner);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct platform_driver hecubafb_driver = {
+	.probe	= hecubafb_probe,
+	.remove = hecubafb_remove,
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "hecubafb",
+	},
+};
+module_platform_driver(hecubafb_driver);
+
+MODULE_DESCRIPTION("fbdev driver for Hecuba/Apollo controller");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/hgafb.c b/drivers/video/fbdev/hgafb.c
new file mode 100644
index 000000000000..5ff9fe2116a4
--- /dev/null
+++ b/drivers/video/fbdev/hgafb.c
@@ -0,0 +1,667 @@
+/*
+ * linux/drivers/video/hgafb.c -- Hercules graphics adaptor frame buffer device
+ * 
+ *      Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu)
+ *      Based on skeletonfb.c by Geert Uytterhoeven and
+ *               mdacon.c by Andrew Apted
+ *
+ * History:
+ *
+ * - Revision 0.1.8 (23 Oct 2002): Ported to new framebuffer api.
+ * 
+ * - Revision 0.1.7 (23 Jan 2001): fix crash resulting from MDA only cards 
+ *				   being detected as Hercules.	 (Paul G.)
+ * - Revision 0.1.6 (17 Aug 2000): new style structs
+ *                                 documentation
+ * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
+ *                                 minor fixes
+ * - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for 
+ *                                  HGA-only systems
+ * - Revision 0.1.3 (22 Jan 2000): modified for the new fb_info structure
+ *                                 screen is cleared after rmmod
+ *                                 virtual resolutions
+ *                                 module parameter 'nologo={0|1}'
+ *                                 the most important: boot logo :)
+ * - Revision 0.1.0  (6 Dec 1999): faster scrolling and minor fixes
+ * - First release  (25 Nov 1999)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/vga.h>
+
+#if 0
+#define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args)
+#else
+#define DPRINTK(args...)
+#endif
+
+#if 0
+#define CHKINFO(ret) if (info != &fb_info) { printk(KERN_DEBUG __FILE__": This should never happen, line:%d \n", __LINE__); return ret; }
+#else
+#define CHKINFO(ret)
+#endif
+
+/* Description of the hardware layout */
+
+static void __iomem *hga_vram;			/* Base of video memory */
+static unsigned long hga_vram_len;		/* Size of video memory */
+
+#define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90)
+#define HGA_TXT			0
+#define HGA_GFX			1
+
+static inline u8 __iomem * rowaddr(struct fb_info *info, u_int row)
+{
+	return info->screen_base + HGA_ROWADDR(row);
+}
+
+static int hga_mode = -1;			/* 0 = txt, 1 = gfx mode */
+
+static enum { TYPE_HERC, TYPE_HERCPLUS, TYPE_HERCCOLOR } hga_type;
+static char *hga_type_name;
+
+#define HGA_INDEX_PORT		0x3b4		/* Register select port */
+#define HGA_VALUE_PORT		0x3b5		/* Register value port */
+#define HGA_MODE_PORT		0x3b8		/* Mode control port */
+#define HGA_STATUS_PORT		0x3ba		/* Status and Config port */
+#define HGA_GFX_PORT		0x3bf		/* Graphics control port */
+
+/* HGA register values */
+
+#define HGA_CURSOR_BLINKING	0x00
+#define HGA_CURSOR_OFF		0x20
+#define HGA_CURSOR_SLOWBLINK	0x60
+
+#define HGA_MODE_GRAPHICS	0x02
+#define HGA_MODE_VIDEO_EN	0x08
+#define HGA_MODE_BLINK_EN	0x20
+#define HGA_MODE_GFX_PAGE1	0x80
+
+#define HGA_STATUS_HSYNC	0x01
+#define HGA_STATUS_VSYNC	0x80
+#define HGA_STATUS_VIDEO	0x08
+
+#define HGA_CONFIG_COL132	0x08
+#define HGA_GFX_MODE_EN		0x01
+#define HGA_GFX_PAGE_EN		0x02
+
+/* Global locks */
+
+static DEFINE_SPINLOCK(hga_reg_lock);
+
+/* Framebuffer driver structures */
+
+static struct fb_var_screeninfo hga_default_var = {
+	.xres		= 720,
+	.yres 		= 348,
+	.xres_virtual 	= 720,
+	.yres_virtual	= 348,
+	.bits_per_pixel = 1,
+	.red 		= {0, 1, 0},
+	.green 		= {0, 1, 0},
+	.blue 		= {0, 1, 0},
+	.transp 	= {0, 0, 0},
+	.height 	= -1,
+	.width 		= -1,
+};
+
+static struct fb_fix_screeninfo hga_fix = {
+	.id 		= "HGA",
+	.type 		= FB_TYPE_PACKED_PIXELS,	/* (not sure) */
+	.visual 	= FB_VISUAL_MONO10,
+	.xpanstep 	= 8,
+	.ypanstep 	= 8,
+	.line_length 	= 90,
+	.accel 		= FB_ACCEL_NONE
+};
+
+/* Don't assume that tty1 will be the initial current console. */
+static int release_io_port = 0;
+static int release_io_ports = 0;
+static bool nologo = 0;
+
+/* -------------------------------------------------------------------------
+ *
+ * Low level hardware functions
+ *
+ * ------------------------------------------------------------------------- */
+
+static void write_hga_b(unsigned int val, unsigned char reg)
+{
+	outb_p(reg, HGA_INDEX_PORT); 
+	outb_p(val, HGA_VALUE_PORT);
+}
+
+static void write_hga_w(unsigned int val, unsigned char reg)
+{
+	outb_p(reg,   HGA_INDEX_PORT); outb_p(val >> 8,   HGA_VALUE_PORT);
+	outb_p(reg+1, HGA_INDEX_PORT); outb_p(val & 0xff, HGA_VALUE_PORT);
+}
+
+static int test_hga_b(unsigned char val, unsigned char reg)
+{
+	outb_p(reg, HGA_INDEX_PORT); 
+	outb  (val, HGA_VALUE_PORT);
+	udelay(20); val = (inb_p(HGA_VALUE_PORT) == val);
+	return val;
+}
+
+static void hga_clear_screen(void)
+{
+	unsigned char fillchar = 0xbf; /* magic */
+	unsigned long flags;
+
+	spin_lock_irqsave(&hga_reg_lock, flags);
+	if (hga_mode == HGA_TXT)
+		fillchar = ' ';
+	else if (hga_mode == HGA_GFX)
+		fillchar = 0x00;
+	spin_unlock_irqrestore(&hga_reg_lock, flags);
+	if (fillchar != 0xbf)
+		memset_io(hga_vram, fillchar, hga_vram_len);
+}
+
+static void hga_txt_mode(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hga_reg_lock, flags);
+	outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_BLINK_EN, HGA_MODE_PORT);
+	outb_p(0x00, HGA_GFX_PORT);
+	outb_p(0x00, HGA_STATUS_PORT);
+
+	write_hga_b(0x61, 0x00);	/* horizontal total */
+	write_hga_b(0x50, 0x01);	/* horizontal displayed */
+	write_hga_b(0x52, 0x02);	/* horizontal sync pos */
+	write_hga_b(0x0f, 0x03);	/* horizontal sync width */
+
+	write_hga_b(0x19, 0x04);	/* vertical total */
+	write_hga_b(0x06, 0x05);	/* vertical total adjust */
+	write_hga_b(0x19, 0x06);	/* vertical displayed */
+	write_hga_b(0x19, 0x07);	/* vertical sync pos */
+
+	write_hga_b(0x02, 0x08);	/* interlace mode */
+	write_hga_b(0x0d, 0x09);	/* maximum scanline */
+	write_hga_b(0x0c, 0x0a);	/* cursor start */
+	write_hga_b(0x0d, 0x0b);	/* cursor end */
+
+	write_hga_w(0x0000, 0x0c);	/* start address */
+	write_hga_w(0x0000, 0x0e);	/* cursor location */
+
+	hga_mode = HGA_TXT;
+	spin_unlock_irqrestore(&hga_reg_lock, flags);
+}
+
+static void hga_gfx_mode(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hga_reg_lock, flags);
+	outb_p(0x00, HGA_STATUS_PORT);
+	outb_p(HGA_GFX_MODE_EN, HGA_GFX_PORT);
+	outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
+
+	write_hga_b(0x35, 0x00);	/* horizontal total */
+	write_hga_b(0x2d, 0x01);	/* horizontal displayed */
+	write_hga_b(0x2e, 0x02);	/* horizontal sync pos */
+	write_hga_b(0x07, 0x03);	/* horizontal sync width */
+
+	write_hga_b(0x5b, 0x04);	/* vertical total */
+	write_hga_b(0x02, 0x05);	/* vertical total adjust */
+	write_hga_b(0x57, 0x06);	/* vertical displayed */
+	write_hga_b(0x57, 0x07);	/* vertical sync pos */
+
+	write_hga_b(0x02, 0x08);	/* interlace mode */
+	write_hga_b(0x03, 0x09);	/* maximum scanline */
+	write_hga_b(0x00, 0x0a);	/* cursor start */
+	write_hga_b(0x00, 0x0b);	/* cursor end */
+
+	write_hga_w(0x0000, 0x0c);	/* start address */
+	write_hga_w(0x0000, 0x0e);	/* cursor location */
+
+	hga_mode = HGA_GFX;
+	spin_unlock_irqrestore(&hga_reg_lock, flags);
+}
+
+static void hga_show_logo(struct fb_info *info)
+{
+/*
+	void __iomem *dest = hga_vram;
+	char *logo = linux_logo_bw;
+	int x, y;
+	
+	for (y = 134; y < 134 + 80 ; y++) * this needs some cleanup *
+		for (x = 0; x < 10 ; x++)
+			writeb(~*(logo++),(dest + HGA_ROWADDR(y) + x + 40));
+*/
+}
+
+static void hga_pan(unsigned int xoffset, unsigned int yoffset)
+{
+	unsigned int base;
+	unsigned long flags;
+	
+	base = (yoffset / 8) * 90 + xoffset;
+	spin_lock_irqsave(&hga_reg_lock, flags);
+	write_hga_w(base, 0x0c);	/* start address */
+	spin_unlock_irqrestore(&hga_reg_lock, flags);
+	DPRINTK("hga_pan: base:%d\n", base);
+}
+
+static void hga_blank(int blank_mode)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hga_reg_lock, flags);
+	if (blank_mode) {
+		outb_p(0x00, HGA_MODE_PORT);	/* disable video */
+	} else {
+		outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
+	}
+	spin_unlock_irqrestore(&hga_reg_lock, flags);
+}
+
+static int hga_card_detect(void)
+{
+	int count = 0;
+	void __iomem *p, *q;
+	unsigned short p_save, q_save;
+
+	hga_vram_len  = 0x08000;
+
+	hga_vram = ioremap(0xb0000, hga_vram_len);
+
+	if (request_region(0x3b0, 12, "hgafb"))
+		release_io_ports = 1;
+	if (request_region(0x3bf, 1, "hgafb"))
+		release_io_port = 1;
+
+	/* do a memory check */
+
+	p = hga_vram;
+	q = hga_vram + 0x01000;
+
+	p_save = readw(p); q_save = readw(q);
+
+	writew(0xaa55, p); if (readw(p) == 0xaa55) count++;
+	writew(0x55aa, p); if (readw(p) == 0x55aa) count++;
+	writew(p_save, p);
+
+	if (count != 2)
+		goto error;
+
+	/* Ok, there is definitely a card registering at the correct
+	 * memory location, so now we do an I/O port test.
+	 */
+	
+	if (!test_hga_b(0x66, 0x0f))	    /* cursor low register */
+		goto error;
+
+	if (!test_hga_b(0x99, 0x0f))     /* cursor low register */
+		goto error;
+
+	/* See if the card is a Hercules, by checking whether the vsync
+	 * bit of the status register is changing.  This test lasts for
+	 * approximately 1/10th of a second.
+	 */
+	
+	p_save = q_save = inb_p(HGA_STATUS_PORT) & HGA_STATUS_VSYNC;
+
+	for (count=0; count < 50000 && p_save == q_save; count++) {
+		q_save = inb(HGA_STATUS_PORT) & HGA_STATUS_VSYNC;
+		udelay(2);
+	}
+
+	if (p_save == q_save) 
+		goto error;
+
+	switch (inb_p(HGA_STATUS_PORT) & 0x70) {
+		case 0x10:
+			hga_type = TYPE_HERCPLUS;
+			hga_type_name = "HerculesPlus";
+			break;
+		case 0x50:
+			hga_type = TYPE_HERCCOLOR;
+			hga_type_name = "HerculesColor";
+			break;
+		default:
+			hga_type = TYPE_HERC;
+			hga_type_name = "Hercules";
+			break;
+	}
+	return 1;
+error:
+	if (release_io_ports)
+		release_region(0x3b0, 12);
+	if (release_io_port)
+		release_region(0x3bf, 1);
+	return 0;
+}
+
+/**
+ *	hgafb_open - open the framebuffer device
+ *	@info:pointer to fb_info object containing info for current hga board
+ *	@int:open by console system or userland.
+ */
+
+static int hgafb_open(struct fb_info *info, int init)
+{
+	hga_gfx_mode();
+	hga_clear_screen();
+	if (!nologo) hga_show_logo(info);
+	return 0;
+}
+
+/**
+ *	hgafb_open - open the framebuffer device
+ *	@info:pointer to fb_info object containing info for current hga board
+ *	@int:open by console system or userland.
+ */
+
+static int hgafb_release(struct fb_info *info, int init)
+{
+	hga_txt_mode();
+	hga_clear_screen();
+	return 0;
+}
+
+/**
+ *	hgafb_setcolreg - set color registers
+ *	@regno:register index to set
+ *	@red:red value, unused
+ *	@green:green value, unused
+ *	@blue:blue value, unused
+ *	@transp:transparency value, unused
+ *	@info:unused
+ *
+ *	This callback function is used to set the color registers of a HGA
+ *	board. Since we have only two fixed colors only @regno is checked.
+ *	A zero is returned on success and 1 for failure.
+ */
+
+static int hgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info)
+{
+	if (regno > 1)
+		return 1;
+	return 0;
+}
+
+/**
+ *	hga_pan_display - pan or wrap the display
+ *	@var:contains new xoffset, yoffset and vmode values
+ *	@info:pointer to fb_info object containing info for current hga board
+ *
+ *	This function looks only at xoffset, yoffset and the %FB_VMODE_YWRAP
+ *	flag in @var. If input parameters are correct it calls hga_pan() to 
+ *	program the hardware. @info->var is updated to the new values.
+ *	A zero is returned on success and %-EINVAL for failure.
+ */
+
+static int hgafb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0 || 
+		    var->yoffset >= info->var.yres_virtual ||
+		    var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + info->var.xres > info->var.xres_virtual
+		 || var->yoffset + info->var.yres > info->var.yres_virtual
+		 || var->yoffset % 8)
+			return -EINVAL;
+	}
+
+	hga_pan(var->xoffset, var->yoffset);
+	return 0;
+}
+
+/**
+ *	hgafb_blank - (un)blank the screen
+ *	@blank_mode:blanking method to use
+ *	@info:unused
+ *	
+ *	Blank the screen if blank_mode != 0, else unblank. 
+ *	Implements VESA suspend and powerdown modes on hardware that supports 
+ *	disabling hsync/vsync:
+ *		@blank_mode == 2 means suspend vsync,
+ *		@blank_mode == 3 means suspend hsync,
+ *		@blank_mode == 4 means powerdown.
+ */
+
+static int hgafb_blank(int blank_mode, struct fb_info *info)
+{
+	hga_blank(blank_mode);
+	return 0;
+}
+
+/*
+ * Accel functions
+ */
+static void hgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u_int rows, y;
+	u8 __iomem *dest;
+
+	y = rect->dy;
+
+	for (rows = rect->height; rows--; y++) {
+		dest = rowaddr(info, y) + (rect->dx >> 3);
+		switch (rect->rop) {
+		case ROP_COPY:
+			memset_io(dest, rect->color, (rect->width >> 3));
+			break;
+		case ROP_XOR:
+			fb_writeb(~(fb_readb(dest)), dest);
+			break;
+		}
+	}
+}
+
+static void hgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	u_int rows, y1, y2;
+	u8 __iomem *src;
+	u8 __iomem *dest;
+
+	if (area->dy <= area->sy) {
+		y1 = area->sy;
+		y2 = area->dy;
+
+		for (rows = area->height; rows--; ) {
+			src = rowaddr(info, y1) + (area->sx >> 3);
+			dest = rowaddr(info, y2) + (area->dx >> 3);
+			memmove(dest, src, (area->width >> 3));
+			y1++;
+			y2++;
+		}
+	} else {
+		y1 = area->sy + area->height - 1;
+		y2 = area->dy + area->height - 1;
+
+		for (rows = area->height; rows--;) {
+			src = rowaddr(info, y1) + (area->sx >> 3);
+			dest = rowaddr(info, y2) + (area->dx >> 3);
+			memmove(dest, src, (area->width >> 3));
+			y1--;
+			y2--;
+		}
+	}
+}
+
+static void hgafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u8 __iomem *dest;
+	u8 *cdat = (u8 *) image->data;
+	u_int rows, y = image->dy;
+	u_int x;
+	u8 d;
+
+	for (rows = image->height; rows--; y++) {
+		for (x = 0; x < image->width; x+= 8) {
+			d = *cdat++;
+			dest = rowaddr(info, y) + ((image->dx + x)>> 3);
+			fb_writeb(d, dest);
+		}
+	}
+}
+
+static struct fb_ops hgafb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= hgafb_open,
+	.fb_release	= hgafb_release,
+	.fb_setcolreg	= hgafb_setcolreg,
+	.fb_pan_display	= hgafb_pan_display,
+	.fb_blank	= hgafb_blank,
+	.fb_fillrect	= hgafb_fillrect,
+	.fb_copyarea	= hgafb_copyarea,
+	.fb_imageblit	= hgafb_imageblit,
+};
+		
+/* ------------------------------------------------------------------------- *
+ *
+ * Functions in fb_info
+ * 
+ * ------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------------------- */
+    
+	/*
+	 *  Initialization
+	 */
+
+static int hgafb_probe(struct platform_device *pdev)
+{
+	struct fb_info *info;
+
+	if (! hga_card_detect()) {
+		printk(KERN_INFO "hgafb: HGA card not detected.\n");
+		if (hga_vram)
+			iounmap(hga_vram);
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
+		hga_type_name, hga_vram_len/1024);
+
+	info = framebuffer_alloc(0, &pdev->dev);
+	if (!info) {
+		iounmap(hga_vram);
+		return -ENOMEM;
+	}
+
+	hga_fix.smem_start = (unsigned long)hga_vram;
+	hga_fix.smem_len = hga_vram_len;
+
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	info->var = hga_default_var;
+	info->fix = hga_fix;
+	info->monspecs.hfmin = 0;
+	info->monspecs.hfmax = 0;
+	info->monspecs.vfmin = 10000;
+	info->monspecs.vfmax = 10000;
+	info->monspecs.dpms = 0;
+	info->fbops = &hgafb_ops;
+	info->screen_base = hga_vram;
+
+        if (register_framebuffer(info) < 0) {
+		framebuffer_release(info);
+		iounmap(hga_vram);
+		return -EINVAL;
+	}
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	platform_set_drvdata(pdev, info);
+	return 0;
+}
+
+static int hgafb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+
+	hga_txt_mode();
+	hga_clear_screen();
+
+	if (info) {
+		unregister_framebuffer(info);
+		framebuffer_release(info);
+	}
+
+	iounmap(hga_vram);
+
+	if (release_io_ports)
+		release_region(0x3b0, 12);
+
+	if (release_io_port)
+		release_region(0x3bf, 1);
+
+	return 0;
+}
+
+static struct platform_driver hgafb_driver = {
+	.probe = hgafb_probe,
+	.remove = hgafb_remove,
+	.driver = {
+		.name = "hgafb",
+	},
+};
+
+static struct platform_device *hgafb_device;
+
+static int __init hgafb_init(void)
+{
+	int ret;
+
+	if (fb_get_options("hgafb", NULL))
+		return -ENODEV;
+
+	ret = platform_driver_register(&hgafb_driver);
+
+	if (!ret) {
+		hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0);
+
+		if (IS_ERR(hgafb_device)) {
+			platform_driver_unregister(&hgafb_driver);
+			ret = PTR_ERR(hgafb_device);
+		}
+	}
+
+	return ret;
+}
+
+static void __exit hgafb_exit(void)
+{
+	platform_device_unregister(hgafb_device);
+	platform_driver_unregister(&hgafb_driver);
+}
+
+/* -------------------------------------------------------------------------
+ *
+ *  Modularization
+ *
+ * ------------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Ferenc Bakonyi (fero@drama.obuda.kando.hu)");
+MODULE_DESCRIPTION("FBDev driver for Hercules Graphics Adaptor");
+MODULE_LICENSE("GPL");
+
+module_param(nologo, bool, 0);
+MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
+module_init(hgafb_init);
+module_exit(hgafb_exit);
diff --git a/drivers/video/fbdev/hitfb.c b/drivers/video/fbdev/hitfb.c
new file mode 100644
index 000000000000..a648d5186c6e
--- /dev/null
+++ b/drivers/video/fbdev/hitfb.c
@@ -0,0 +1,500 @@
+/*
+ * linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device
+ *
+ * (C) 1999 Mihai Spatar
+ * (C) 2000 YAEGASHI Takeshi
+ * (C) 2003, 2004 Paul Mundt
+ * (C) 2003, 2004, 2006 Andriy Skulysh
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+
+#include <asm/machvec.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/hd64461.h>
+#include <cpu/dac.h>
+
+#define	WIDTH 640
+
+static struct fb_var_screeninfo hitfb_var = {
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo hitfb_fix = {
+	.id		= "Hitachi HD64461",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static inline void hitfb_accel_wait(void)
+{
+	while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ;
+}
+
+static inline void hitfb_accel_start(int truecolor)
+{
+	if (truecolor) {
+		fb_writew(6, HD64461_GRCFGR);
+	} else {
+		fb_writew(7, HD64461_GRCFGR);
+	}
+}
+
+static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy,
+					u16 width, u16 height)
+{
+	u32 saddr = WIDTH * dy + dx;
+	if (truecolor)
+		saddr <<= 1;
+
+	fb_writew(width-1, HD64461_BBTDWR);
+	fb_writew(height-1, HD64461_BBTDHR);
+
+	fb_writew(saddr & 0xffff, HD64461_BBTDSARL);
+	fb_writew(saddr >> 16, HD64461_BBTDSARH);
+
+}
+
+static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
+				      u16 dy, u16 width, u16 height, u16 rop,
+				      u32 mask_addr)
+{
+	u32 saddr, daddr;
+	u32 maddr = 0;
+
+	height--;
+	width--;
+	fb_writew(rop, HD64461_BBTROPR);
+	if ((sy < dy) || ((sy == dy) && (sx <= dx))) {
+		saddr = WIDTH * (sy + height) + sx + width;
+		daddr = WIDTH * (dy + height) + dx + width;
+		if (mask_addr) {
+			if (truecolor)
+				maddr = ((width >> 3) + 1) * (height + 1) - 1;
+			else
+				maddr =
+				    (((width >> 4) + 1) * (height + 1) - 1) * 2;
+
+			fb_writew((1 << 5) | 1, HD64461_BBTMDR);
+		} else
+			fb_writew(1, HD64461_BBTMDR);
+	} else {
+		saddr = WIDTH * sy + sx;
+		daddr = WIDTH * dy + dx;
+		if (mask_addr) {
+			fb_writew((1 << 5), HD64461_BBTMDR);
+		} else {
+			fb_writew(0, HD64461_BBTMDR);
+		}
+	}
+	if (truecolor) {
+		saddr <<= 1;
+		daddr <<= 1;
+	}
+	fb_writew(width, HD64461_BBTDWR);
+	fb_writew(height, HD64461_BBTDHR);
+	fb_writew(saddr & 0xffff, HD64461_BBTSSARL);
+	fb_writew(saddr >> 16, HD64461_BBTSSARH);
+	fb_writew(daddr & 0xffff, HD64461_BBTDSARL);
+	fb_writew(daddr >> 16, HD64461_BBTDSARH);
+	if (mask_addr) {
+		maddr += mask_addr;
+		fb_writew(maddr & 0xffff, HD64461_BBTMARL);
+		fb_writew(maddr >> 16, HD64461_BBTMARH);
+	}
+	hitfb_accel_start(truecolor);
+}
+
+static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	if (rect->rop != ROP_COPY)
+		cfb_fillrect(p, rect);
+	else {
+		hitfb_accel_wait();
+		fb_writew(0x00f0, HD64461_BBTROPR);
+		fb_writew(16, HD64461_BBTMDR);
+
+		if (p->var.bits_per_pixel == 16) {
+			fb_writew(((u32 *) (p->pseudo_palette))[rect->color],
+				  HD64461_GRSCR);
+			hitfb_accel_set_dest(1, rect->dx, rect->dy, rect->width,
+					     rect->height);
+			hitfb_accel_start(1);
+		} else {
+			fb_writew(rect->color, HD64461_GRSCR);
+			hitfb_accel_set_dest(0, rect->dx, rect->dy, rect->width,
+					     rect->height);
+			hitfb_accel_start(0);
+		}
+	}
+}
+
+static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	hitfb_accel_wait();
+	hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy,
+			   area->dx, area->dy, area->width, area->height,
+			   0x00cc, 0);
+}
+
+static int hitfb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	int xoffset = var->xoffset;
+	int yoffset = var->yoffset;
+
+	if (xoffset != 0)
+		return -EINVAL;
+
+	fb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR);
+
+	return 0;
+}
+
+int hitfb_blank(int blank_mode, struct fb_info *info)
+{
+	unsigned short v;
+
+	if (blank_mode) {
+		v = fb_readw(HD64461_LDR1);
+		v &= ~HD64461_LDR1_DON;
+		fb_writew(v, HD64461_LDR1);
+
+		v = fb_readw(HD64461_LCDCCR);
+		v |= HD64461_LCDCCR_MOFF;
+		fb_writew(v, HD64461_LCDCCR);
+
+		v = fb_readw(HD64461_STBCR);
+		v |= HD64461_STBCR_SLCDST;
+		fb_writew(v, HD64461_STBCR);
+	} else {
+		v = fb_readw(HD64461_STBCR);
+		v &= ~HD64461_STBCR_SLCDST;
+		fb_writew(v, HD64461_STBCR);
+
+		v = fb_readw(HD64461_LCDCCR);
+		v &= ~(HD64461_LCDCCR_MOFF | HD64461_LCDCCR_STREQ);
+		fb_writew(v, HD64461_LCDCCR);
+
+		do {
+		    v = fb_readw(HD64461_LCDCCR);
+		} while(v&HD64461_LCDCCR_STBACK);
+
+		v = fb_readw(HD64461_LDR1);
+		v |= HD64461_LDR1_DON;
+		fb_writew(v, HD64461_LDR1);
+	}
+	return 0;
+}
+
+static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp, struct fb_info *info)
+{
+	if (regno >= 256)
+		return 1;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		fb_writew(regno << 8, HD64461_CPTWAR);
+		fb_writew(red >> 10, HD64461_CPTWDR);
+		fb_writew(green >> 10, HD64461_CPTWDR);
+		fb_writew(blue >> 10, HD64461_CPTWDR);
+		break;
+	case 16:
+		if (regno >= 16)
+			return 1;
+		((u32 *) (info->pseudo_palette))[regno] =
+		    ((red & 0xf800)) |
+		    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+		break;
+	}
+	return 0;
+}
+
+static int hitfb_sync(struct fb_info *info)
+{
+	hitfb_accel_wait();
+
+	return 0;
+}
+
+static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int maxy;
+
+	var->xres = info->var.xres;
+	var->xres_virtual = info->var.xres;
+	var->yres = info->var.yres;
+
+	if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16))
+		var->bits_per_pixel = info->var.bits_per_pixel;
+
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	maxy = info->fix.smem_len / var->xres;
+
+	if (var->bits_per_pixel == 16)
+		maxy /= 2;
+
+	if (var->yres_virtual > maxy)
+		var->yres_virtual = maxy;
+
+	var->xoffset = 0;
+	var->yoffset = 0;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGB 565 */
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	}
+
+	return 0;
+}
+
+static int hitfb_set_par(struct fb_info *info)
+{
+	unsigned short ldr3;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		info->fix.line_length = info->var.xres;
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		info->fix.ypanstep = 16;
+		break;
+	case 16:
+		info->fix.line_length = info->var.xres*2;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.ypanstep = 8;
+		break;
+	}
+
+	fb_writew(info->fix.line_length, HD64461_LCDCLOR);
+	ldr3 = fb_readw(HD64461_LDR3);
+	ldr3 &= ~15;
+	ldr3 |= (info->var.bits_per_pixel == 8) ? 4 : 8;
+	fb_writew(ldr3, HD64461_LDR3);
+	return 0;
+}
+
+static struct fb_ops hitfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= hitfb_check_var,
+	.fb_set_par		= hitfb_set_par,
+	.fb_setcolreg	= hitfb_setcolreg,
+	.fb_blank	= hitfb_blank,
+	.fb_sync	= hitfb_sync,
+	.fb_pan_display = hitfb_pan_display,
+	.fb_fillrect	= hitfb_fillrect,
+	.fb_copyarea	= hitfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int hitfb_probe(struct platform_device *dev)
+{
+	unsigned short lcdclor, ldr3, ldvndr;
+	struct fb_info *info;
+	int ret;
+
+	if (fb_get_options("hitfb", NULL))
+		return -ENODEV;
+
+	hitfb_fix.mmio_start = HD64461_IO_OFFSET(0x1000);
+	hitfb_fix.mmio_len = 0x1000;
+	hitfb_fix.smem_start = HD64461_IO_OFFSET(0x02000000);
+	hitfb_fix.smem_len = 512 * 1024;
+
+	lcdclor = fb_readw(HD64461_LCDCLOR);
+	ldvndr = fb_readw(HD64461_LDVNDR);
+	ldr3 = fb_readw(HD64461_LDR3);
+
+	switch (ldr3 & 15) {
+	default:
+	case 4:
+		hitfb_var.bits_per_pixel = 8;
+		hitfb_var.xres = lcdclor;
+		break;
+	case 8:
+		hitfb_var.bits_per_pixel = 16;
+		hitfb_var.xres = lcdclor / 2;
+		break;
+	}
+	hitfb_fix.line_length = lcdclor;
+	hitfb_fix.visual = (hitfb_var.bits_per_pixel == 8) ?
+	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	hitfb_var.yres = ldvndr + 1;
+	hitfb_var.xres_virtual = hitfb_var.xres;
+	hitfb_var.yres_virtual = hitfb_fix.smem_len / lcdclor;
+	switch (hitfb_var.bits_per_pixel) {
+	case 8:
+		hitfb_var.red.offset = 0;
+		hitfb_var.red.length = 8;
+		hitfb_var.green.offset = 0;
+		hitfb_var.green.length = 8;
+		hitfb_var.blue.offset = 0;
+		hitfb_var.blue.length = 8;
+		hitfb_var.transp.offset = 0;
+		hitfb_var.transp.length = 0;
+		break;
+	case 16:		/* RGB 565 */
+		hitfb_var.red.offset = 11;
+		hitfb_var.red.length = 5;
+		hitfb_var.green.offset = 5;
+		hitfb_var.green.length = 6;
+		hitfb_var.blue.offset = 0;
+		hitfb_var.blue.length = 5;
+		hitfb_var.transp.offset = 0;
+		hitfb_var.transp.length = 0;
+		break;
+	}
+
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (unlikely(!info))
+		return -ENOMEM;
+
+	info->fbops = &hitfb_ops;
+	info->var = hitfb_var;
+	info->fix = hitfb_fix;
+	info->pseudo_palette = info->par;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+		FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
+
+	info->screen_base = (void *)hitfb_fix.smem_start;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (unlikely(ret < 0))
+		goto err_fb;
+
+	ret = register_framebuffer(info);
+	if (unlikely(ret < 0))
+		goto err;
+
+	platform_set_drvdata(dev, info);
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	return 0;
+
+err:
+	fb_dealloc_cmap(&info->cmap);
+err_fb:
+	framebuffer_release(info);
+	return ret;
+}
+
+static int hitfb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static int hitfb_suspend(struct device *dev)
+{
+	u16 v;
+
+	hitfb_blank(1,0);
+	v = fb_readw(HD64461_STBCR);
+	v |= HD64461_STBCR_SLCKE_IST;
+	fb_writew(v, HD64461_STBCR);
+
+	return 0;
+}
+
+static int hitfb_resume(struct device *dev)
+{
+	u16 v;
+
+	v = fb_readw(HD64461_STBCR);
+	v &= ~HD64461_STBCR_SLCKE_OST;
+	msleep(100);
+	v = fb_readw(HD64461_STBCR);
+	v &= ~HD64461_STBCR_SLCKE_IST;
+	fb_writew(v, HD64461_STBCR);
+	hitfb_blank(0,0);
+
+	return 0;
+}
+
+static const struct dev_pm_ops hitfb_dev_pm_ops = {
+	.suspend	= hitfb_suspend,
+	.resume		= hitfb_resume,
+};
+
+static struct platform_driver hitfb_driver = {
+	.probe		= hitfb_probe,
+	.remove		= hitfb_remove,
+	.driver		= {
+		.name	= "hitfb",
+		.owner	= THIS_MODULE,
+		.pm	= &hitfb_dev_pm_ops,
+	},
+};
+
+static struct platform_device hitfb_device = {
+	.name	= "hitfb",
+	.id	= -1,
+};
+
+static int __init hitfb_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&hitfb_driver);
+	if (!ret) {
+		ret = platform_device_register(&hitfb_device);
+		if (ret)
+			platform_driver_unregister(&hitfb_driver);
+	}
+	return ret;
+}
+
+
+static void __exit hitfb_exit(void)
+{
+	platform_device_unregister(&hitfb_device);
+	platform_driver_unregister(&hitfb_driver);
+}
+
+module_init(hitfb_init);
+module_exit(hitfb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/hpfb.c b/drivers/video/fbdev/hpfb.c
new file mode 100644
index 000000000000..a1b7e5fa9b09
--- /dev/null
+++ b/drivers/video/fbdev/hpfb.c
@@ -0,0 +1,429 @@
+/*
+ *	HP300 Topcat framebuffer support (derived from macfb of all things)
+ *	Phil Blundell <philb@gnu.org> 1998
+ *	DIO-II, colour map and Catseye support by
+ *	Kars de Jong <jongk@linux-m68k.org>, May 2004.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/dio.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+static struct fb_info fb_info = {
+	.fix = {
+		.id		= "HP300 ",
+		.type		= FB_TYPE_PACKED_PIXELS,
+		.visual		= FB_VISUAL_PSEUDOCOLOR,
+		.accel		= FB_ACCEL_NONE,
+	}
+};
+
+static unsigned long fb_regs;
+static unsigned char fb_bitmask;
+
+#define TC_NBLANK	0x4080
+#define TC_WEN		0x4088
+#define TC_REN		0x408c
+#define TC_FBEN		0x4090
+#define TC_PRR		0x40ea
+
+/* These defines match the X window system */
+#define RR_CLEAR	0x0
+#define RR_COPY		0x3
+#define RR_NOOP		0x5
+#define RR_XOR		0x6
+#define RR_INVERT	0xa
+#define RR_COPYINVERTED 0xc
+#define RR_SET		0xf
+
+/* blitter regs */
+#define BUSY		0x4044
+#define WMRR		0x40ef
+#define SOURCE_X	0x40f2
+#define SOURCE_Y	0x40f6
+#define DEST_X		0x40fa
+#define DEST_Y		0x40fe
+#define WHEIGHT		0x4106
+#define WWIDTH		0x4102
+#define WMOVE		0x409c
+
+static struct fb_var_screeninfo hpfb_defined = {
+	.red		= {
+		.length = 8,
+	},
+	.green		= {
+		.length = 8,
+	},
+	.blue		= {
+		.length = 8,
+	},
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static int hpfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp,
+			  struct fb_info *info)
+{
+	/* use MSBs */
+	unsigned char _red  =red>>8;
+	unsigned char _green=green>>8;
+	unsigned char _blue =blue>>8;
+	unsigned char _regno=regno;
+
+	/*
+	 *  Set a single color register. The values supplied are
+	 *  already rounded down to the hardware's capabilities
+	 *  (according to the entries in the `var' structure). Return
+	 *  != 0 for invalid regno.
+	 */
+
+	if (regno >= info->cmap.len)
+		return 1;
+	
+	while (in_be16(fb_regs + 0x6002) & 0x4) udelay(1);
+
+	out_be16(fb_regs + 0x60ba, 0xff);
+
+	out_be16(fb_regs + 0x60b2, _red);
+	out_be16(fb_regs + 0x60b4, _green);
+	out_be16(fb_regs + 0x60b6, _blue);
+	out_be16(fb_regs + 0x60b8, ~_regno);
+	out_be16(fb_regs + 0x60f0, 0xff);
+
+	udelay(100);
+
+	while (in_be16(fb_regs + 0x6002) & 0x4) udelay(1);
+	out_be16(fb_regs + 0x60b2, 0);
+	out_be16(fb_regs + 0x60b4, 0);
+	out_be16(fb_regs + 0x60b6, 0);
+	out_be16(fb_regs + 0x60b8, 0);
+
+	return 0;
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+
+static int hpfb_blank(int blank, struct fb_info *info)
+{
+	out_8(fb_regs + TC_NBLANK, (blank ? 0x00 : fb_bitmask));
+
+	return 0;
+}
+
+static void topcat_blit(int x0, int y0, int x1, int y1, int w, int h, int rr)
+{
+	if (rr >= 0) {
+		while (in_8(fb_regs + BUSY) & fb_bitmask)
+			;
+	}
+	out_8(fb_regs + TC_FBEN, fb_bitmask);
+	if (rr >= 0) {
+		out_8(fb_regs + TC_WEN, fb_bitmask);
+		out_8(fb_regs + WMRR, rr);
+	}
+	out_be16(fb_regs + SOURCE_X, x0);
+	out_be16(fb_regs + SOURCE_Y, y0);
+	out_be16(fb_regs + DEST_X, x1);
+	out_be16(fb_regs + DEST_Y, y1);
+	out_be16(fb_regs + WWIDTH, w);
+	out_be16(fb_regs + WHEIGHT, h);
+	out_8(fb_regs + WMOVE, fb_bitmask);
+}
+
+static void hpfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 
+{
+	topcat_blit(area->sx, area->sy, area->dx, area->dy, area->width, area->height, RR_COPY);
+}
+
+static void hpfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
+{
+	u8 clr;
+
+	clr = region->color & 0xff;
+
+	while (in_8(fb_regs + BUSY) & fb_bitmask)
+		;
+
+	/* Foreground */
+	out_8(fb_regs + TC_WEN, fb_bitmask & clr);
+	out_8(fb_regs + WMRR, (region->rop == ROP_COPY ? RR_SET : RR_INVERT));
+
+	/* Background */
+	out_8(fb_regs + TC_WEN, fb_bitmask & ~clr);
+	out_8(fb_regs + WMRR, (region->rop == ROP_COPY ? RR_CLEAR : RR_NOOP));
+
+	topcat_blit(region->dx, region->dy, region->dx, region->dy, region->width, region->height, -1);
+}
+
+static int hpfb_sync(struct fb_info *info)
+{
+	/*
+	 * Since we also access the framebuffer directly, we have to wait
+	 * until the block mover is finished
+	 */
+	while (in_8(fb_regs + BUSY) & fb_bitmask)
+		;
+
+	out_8(fb_regs + TC_WEN, fb_bitmask);
+	out_8(fb_regs + TC_PRR, RR_COPY);
+	out_8(fb_regs + TC_FBEN, fb_bitmask);
+
+	return 0;
+}
+
+static struct fb_ops hpfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= hpfb_setcolreg,
+	.fb_blank	= hpfb_blank,
+	.fb_fillrect	= hpfb_fillrect,
+	.fb_copyarea	= hpfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_sync	= hpfb_sync,
+};
+
+/* Common to all HP framebuffers */
+#define HPFB_FBWMSB	0x05	/* Frame buffer width 		*/
+#define HPFB_FBWLSB	0x07
+#define HPFB_FBHMSB	0x09	/* Frame buffer height		*/
+#define HPFB_FBHLSB	0x0b
+#define HPFB_DWMSB	0x0d	/* Display width		*/
+#define HPFB_DWLSB	0x0f
+#define HPFB_DHMSB	0x11	/* Display height		*/
+#define HPFB_DHLSB	0x13
+#define HPFB_NUMPLANES	0x5b	/* Number of colour planes	*/
+#define HPFB_FBOMSB	0x5d	/* Frame buffer offset		*/
+#define HPFB_FBOLSB	0x5f
+
+static int hpfb_init_one(unsigned long phys_base, unsigned long virt_base)
+{
+	unsigned long fboff, fb_width, fb_height, fb_start;
+	int ret;
+
+	fb_regs = virt_base;
+	fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB);
+
+	fb_info.fix.smem_start = (in_8(fb_regs + fboff) << 16);
+
+	if (phys_base >= DIOII_BASE) {
+		fb_info.fix.smem_start += phys_base;
+	}
+
+	if (DIO_SECID(fb_regs) != DIO_ID2_TOPCAT) {
+		/* This is the magic incantation the HP X server uses to make Catseye boards work. */
+		while (in_be16(fb_regs+0x4800) & 1)
+			;
+		out_be16(fb_regs+0x4800, 0);	/* Catseye status */
+		out_be16(fb_regs+0x4510, 0);	/* VB */
+		out_be16(fb_regs+0x4512, 0);	/* TCNTRL */
+		out_be16(fb_regs+0x4514, 0);	/* ACNTRL */
+		out_be16(fb_regs+0x4516, 0);	/* PNCNTRL */
+		out_be16(fb_regs+0x4206, 0x90);	/* RUG Command/Status */
+		out_be16(fb_regs+0x60a2, 0);	/* Overlay Mask */
+		out_be16(fb_regs+0x60bc, 0);	/* Ram Select */
+	}
+
+	/*
+	 *	Fill in the available video resolution
+	 */
+	fb_width = (in_8(fb_regs + HPFB_FBWMSB) << 8) | in_8(fb_regs + HPFB_FBWLSB);
+	fb_info.fix.line_length = fb_width;
+	fb_height = (in_8(fb_regs + HPFB_FBHMSB) << 8) | in_8(fb_regs + HPFB_FBHLSB);
+	fb_info.fix.smem_len = fb_width * fb_height;
+	fb_start = (unsigned long)ioremap_writethrough(fb_info.fix.smem_start,
+						       fb_info.fix.smem_len);
+	hpfb_defined.xres = (in_8(fb_regs + HPFB_DWMSB) << 8) | in_8(fb_regs + HPFB_DWLSB);
+	hpfb_defined.yres = (in_8(fb_regs + HPFB_DHMSB) << 8) | in_8(fb_regs + HPFB_DHLSB);
+	hpfb_defined.xres_virtual = hpfb_defined.xres;
+	hpfb_defined.yres_virtual = hpfb_defined.yres;
+	hpfb_defined.bits_per_pixel = in_8(fb_regs + HPFB_NUMPLANES);
+
+	printk(KERN_INFO "hpfb: framebuffer at 0x%lx, mapped to 0x%lx, size %dk\n",
+	       fb_info.fix.smem_start, fb_start, fb_info.fix.smem_len/1024);
+	printk(KERN_INFO "hpfb: mode is %dx%dx%d, linelength=%d\n",
+	       hpfb_defined.xres, hpfb_defined.yres, hpfb_defined.bits_per_pixel, fb_info.fix.line_length);
+
+	/*
+	 *	Give the hardware a bit of a prod and work out how many bits per
+	 *	pixel are supported.
+	 */
+	out_8(fb_regs + TC_WEN, 0xff);
+	out_8(fb_regs + TC_PRR, RR_COPY);
+	out_8(fb_regs + TC_FBEN, 0xff);
+	out_8(fb_start, 0xff);
+	fb_bitmask = in_8(fb_start);
+	out_8(fb_start, 0);
+
+	/*
+	 *	Enable reading/writing of all the planes.
+	 */
+	out_8(fb_regs + TC_WEN, fb_bitmask);
+	out_8(fb_regs + TC_PRR, RR_COPY);
+	out_8(fb_regs + TC_REN, fb_bitmask);
+	out_8(fb_regs + TC_FBEN, fb_bitmask);
+
+	/*
+	 *	Clear the screen.
+	 */
+	topcat_blit(0, 0, 0, 0, fb_width, fb_height, RR_CLEAR);
+
+	/*
+	 *	Let there be consoles..
+	 */
+	if (DIO_SECID(fb_regs) == DIO_ID2_TOPCAT)
+		strcat(fb_info.fix.id, "Topcat");
+	else
+		strcat(fb_info.fix.id, "Catseye");
+	fb_info.fbops = &hpfb_ops;
+	fb_info.flags = FBINFO_DEFAULT;
+	fb_info.var   = hpfb_defined;
+	fb_info.screen_base = (char *)fb_start;
+
+	ret = fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);
+	if (ret < 0)
+		goto unmap_screen_base;
+
+	ret = register_framebuffer(&fb_info);
+	if (ret < 0)
+		goto dealloc_cmap;
+
+	fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
+
+	return 0;
+
+dealloc_cmap:
+	fb_dealloc_cmap(&fb_info.cmap);
+
+unmap_screen_base:
+	if (fb_info.screen_base) {
+		iounmap(fb_info.screen_base);
+		fb_info.screen_base = NULL;
+	}
+
+	return ret;
+}
+
+/* 
+ * Check that the secondary ID indicates that we have some hope of working with this
+ * framebuffer.  The catseye boards are pretty much like topcats and we can muddle through.
+ */
+
+#define topcat_sid_ok(x)  (((x) == DIO_ID2_LRCATSEYE) || ((x) == DIO_ID2_HRCCATSEYE)    \
+			   || ((x) == DIO_ID2_HRMCATSEYE) || ((x) == DIO_ID2_TOPCAT))
+
+/* 
+ * Initialise the framebuffer
+ */
+static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent)
+{
+	unsigned long paddr, vaddr;
+
+	paddr = d->resource.start;
+	if (!request_mem_region(d->resource.start, resource_size(&d->resource), d->name))
+                return -EBUSY;
+
+	if (d->scode >= DIOII_SCBASE) {
+		vaddr = (unsigned long)ioremap(paddr, resource_size(&d->resource));
+	} else {
+		vaddr = paddr + DIO_VIRADDRBASE;
+	}
+	printk(KERN_INFO "Topcat found at DIO select code %d "
+	       "(secondary id %02x)\n", d->scode, (d->id >> 8) & 0xff);
+	if (hpfb_init_one(paddr, vaddr)) {
+		if (d->scode >= DIOII_SCBASE)
+			iounmap((void *)vaddr);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void hpfb_remove_one(struct dio_dev *d)
+{
+	unregister_framebuffer(&fb_info);
+	if (d->scode >= DIOII_SCBASE)
+		iounmap((void *)fb_regs);
+	release_mem_region(d->resource.start, resource_size(&d->resource));
+	fb_dealloc_cmap(&fb_info.cmap);
+	if (fb_info.screen_base)
+		iounmap(fb_info.screen_base);
+}
+
+static struct dio_device_id hpfb_dio_tbl[] = {
+    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_LRCATSEYE) },
+    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRCCATSEYE) },
+    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRMCATSEYE) },
+    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_TOPCAT) },
+    { 0 }
+};
+
+static struct dio_driver hpfb_driver = {
+    .name      = "hpfb",
+    .id_table  = hpfb_dio_tbl,
+    .probe     = hpfb_dio_probe,
+    .remove    = hpfb_remove_one,
+};
+
+int __init hpfb_init(void)
+{
+	unsigned int sid;
+	mm_segment_t fs;
+	unsigned char i;
+	int err;
+
+	/* Topcats can be on the internal IO bus or real DIO devices.
+	 * The internal variant sits at 0x560000; it has primary
+	 * and secondary ID registers just like the DIO version.
+	 * So we merge the two detection routines.
+	 *
+	 * Perhaps this #define should be in a global header file:
+	 * I believe it's common to all internal fbs, not just topcat.
+	 */
+#define INTFBVADDR 0xf0560000
+#define INTFBPADDR 0x560000
+
+	if (!MACH_IS_HP300)
+		return -ENODEV;
+
+	if (fb_get_options("hpfb", NULL))
+		return -ENODEV;
+
+	err = dio_register_driver(&hpfb_driver);
+	if (err)
+		return err;
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = get_user(i, (unsigned char *)INTFBVADDR + DIO_IDOFF);
+	set_fs(fs);
+
+	if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) {
+		if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat"))
+			return -EBUSY;
+		printk(KERN_INFO "Internal Topcat found (secondary id %02x)\n", sid);
+		if (hpfb_init_one(INTFBPADDR, INTFBVADDR)) {
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+void __exit hpfb_cleanup_module(void)
+{
+	dio_unregister_driver(&hpfb_driver);
+}
+
+module_init(hpfb_init);
+module_exit(hpfb_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
new file mode 100644
index 000000000000..e23392ec5af3
--- /dev/null
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -0,0 +1,907 @@
+/*
+ * Copyright (c) 2012, Microsoft Corporation.
+ *
+ * Author:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ * Hyper-V Synthetic Video Frame Buffer Driver
+ *
+ * This is the driver for the Hyper-V Synthetic Video, which supports
+ * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows
+ * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2
+ * or earlier.
+ *
+ * It also solves the double mouse cursor issue of the emulated video mode.
+ *
+ * The default screen resolution is 1152x864, which may be changed by a
+ * kernel parameter:
+ *     video=hyperv_fb:<width>x<height>
+ *     For example: video=hyperv_fb:1280x1024
+ *
+ * Portrait orientation is also supported:
+ *     For example: video=hyperv_fb:864x1152
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/efi.h>
+
+#include <linux/hyperv.h>
+
+
+/* Hyper-V Synthetic Video Protocol definitions and structures */
+#define MAX_VMBUS_PKT_SIZE 0x4000
+
+#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
+#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
+#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
+
+#define SYNTHVID_DEPTH_WIN7 16
+#define SYNTHVID_DEPTH_WIN8 32
+
+#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024)
+#define SYNTHVID_WIDTH_MAX_WIN7 1600
+#define SYNTHVID_HEIGHT_MAX_WIN7 1200
+
+#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
+
+#define PCI_VENDOR_ID_MICROSOFT 0x1414
+#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353
+
+
+enum pipe_msg_type {
+	PIPE_MSG_INVALID,
+	PIPE_MSG_DATA,
+	PIPE_MSG_MAX
+};
+
+struct pipe_msg_hdr {
+	u32 type;
+	u32 size; /* size of message after this field */
+} __packed;
+
+
+enum synthvid_msg_type {
+	SYNTHVID_ERROR			= 0,
+	SYNTHVID_VERSION_REQUEST	= 1,
+	SYNTHVID_VERSION_RESPONSE	= 2,
+	SYNTHVID_VRAM_LOCATION		= 3,
+	SYNTHVID_VRAM_LOCATION_ACK	= 4,
+	SYNTHVID_SITUATION_UPDATE	= 5,
+	SYNTHVID_SITUATION_UPDATE_ACK	= 6,
+	SYNTHVID_POINTER_POSITION	= 7,
+	SYNTHVID_POINTER_SHAPE		= 8,
+	SYNTHVID_FEATURE_CHANGE		= 9,
+	SYNTHVID_DIRT			= 10,
+
+	SYNTHVID_MAX			= 11
+};
+
+struct synthvid_msg_hdr {
+	u32 type;
+	u32 size;  /* size of this header + payload after this field*/
+} __packed;
+
+
+struct synthvid_version_req {
+	u32 version;
+} __packed;
+
+struct synthvid_version_resp {
+	u32 version;
+	u8 is_accepted;
+	u8 max_video_outputs;
+} __packed;
+
+struct synthvid_vram_location {
+	u64 user_ctx;
+	u8 is_vram_gpa_specified;
+	u64 vram_gpa;
+} __packed;
+
+struct synthvid_vram_location_ack {
+	u64 user_ctx;
+} __packed;
+
+struct video_output_situation {
+	u8 active;
+	u32 vram_offset;
+	u8 depth_bits;
+	u32 width_pixels;
+	u32 height_pixels;
+	u32 pitch_bytes;
+} __packed;
+
+struct synthvid_situation_update {
+	u64 user_ctx;
+	u8 video_output_count;
+	struct video_output_situation video_output[1];
+} __packed;
+
+struct synthvid_situation_update_ack {
+	u64 user_ctx;
+} __packed;
+
+struct synthvid_pointer_position {
+	u8 is_visible;
+	u8 video_output;
+	s32 image_x;
+	s32 image_y;
+} __packed;
+
+
+#define CURSOR_MAX_X 96
+#define CURSOR_MAX_Y 96
+#define CURSOR_ARGB_PIXEL_SIZE 4
+#define CURSOR_MAX_SIZE (CURSOR_MAX_X * CURSOR_MAX_Y * CURSOR_ARGB_PIXEL_SIZE)
+#define CURSOR_COMPLETE (-1)
+
+struct synthvid_pointer_shape {
+	u8 part_idx;
+	u8 is_argb;
+	u32 width; /* CURSOR_MAX_X at most */
+	u32 height; /* CURSOR_MAX_Y at most */
+	u32 hot_x; /* hotspot relative to upper-left of pointer image */
+	u32 hot_y;
+	u8 data[4];
+} __packed;
+
+struct synthvid_feature_change {
+	u8 is_dirt_needed;
+	u8 is_ptr_pos_needed;
+	u8 is_ptr_shape_needed;
+	u8 is_situ_needed;
+} __packed;
+
+struct rect {
+	s32 x1, y1; /* top left corner */
+	s32 x2, y2; /* bottom right corner, exclusive */
+} __packed;
+
+struct synthvid_dirt {
+	u8 video_output;
+	u8 dirt_count;
+	struct rect rect[1];
+} __packed;
+
+struct synthvid_msg {
+	struct pipe_msg_hdr pipe_hdr;
+	struct synthvid_msg_hdr vid_hdr;
+	union {
+		struct synthvid_version_req ver_req;
+		struct synthvid_version_resp ver_resp;
+		struct synthvid_vram_location vram;
+		struct synthvid_vram_location_ack vram_ack;
+		struct synthvid_situation_update situ;
+		struct synthvid_situation_update_ack situ_ack;
+		struct synthvid_pointer_position ptr_pos;
+		struct synthvid_pointer_shape ptr_shape;
+		struct synthvid_feature_change feature_chg;
+		struct synthvid_dirt dirt;
+	};
+} __packed;
+
+
+
+/* FB driver definitions and structures */
+#define HVFB_WIDTH 1152 /* default screen width */
+#define HVFB_HEIGHT 864 /* default screen height */
+#define HVFB_WIDTH_MIN 640
+#define HVFB_HEIGHT_MIN 480
+
+#define RING_BUFSIZE (256 * 1024)
+#define VSP_TIMEOUT (10 * HZ)
+#define HVFB_UPDATE_DELAY (HZ / 20)
+
+struct hvfb_par {
+	struct fb_info *info;
+	struct resource mem;
+	bool fb_ready; /* fb device is ready */
+	struct completion wait;
+	u32 synthvid_version;
+
+	struct delayed_work dwork;
+	bool update;
+
+	u32 pseudo_palette[16];
+	u8 init_buf[MAX_VMBUS_PKT_SIZE];
+	u8 recv_buf[MAX_VMBUS_PKT_SIZE];
+};
+
+static uint screen_width = HVFB_WIDTH;
+static uint screen_height = HVFB_HEIGHT;
+static uint screen_depth;
+static uint screen_fb_size;
+
+/* Send message to Hyper-V host */
+static inline int synthvid_send(struct hv_device *hdev,
+				struct synthvid_msg *msg)
+{
+	static atomic64_t request_id = ATOMIC64_INIT(0);
+	int ret;
+
+	msg->pipe_hdr.type = PIPE_MSG_DATA;
+	msg->pipe_hdr.size = msg->vid_hdr.size;
+
+	ret = vmbus_sendpacket(hdev->channel, msg,
+			       msg->vid_hdr.size + sizeof(struct pipe_msg_hdr),
+			       atomic64_inc_return(&request_id),
+			       VM_PKT_DATA_INBAND, 0);
+
+	if (ret)
+		pr_err("Unable to send packet via vmbus\n");
+
+	return ret;
+}
+
+
+/* Send screen resolution info to host */
+static int synthvid_send_situ(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct synthvid_msg msg;
+
+	if (!info)
+		return -ENODEV;
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+
+	msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_situation_update);
+	msg.situ.user_ctx = 0;
+	msg.situ.video_output_count = 1;
+	msg.situ.video_output[0].active = 1;
+	msg.situ.video_output[0].vram_offset = 0;
+	msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel;
+	msg.situ.video_output[0].width_pixels = info->var.xres;
+	msg.situ.video_output[0].height_pixels = info->var.yres;
+	msg.situ.video_output[0].pitch_bytes = info->fix.line_length;
+
+	synthvid_send(hdev, &msg);
+
+	return 0;
+}
+
+/* Send mouse pointer info to host */
+static int synthvid_send_ptr(struct hv_device *hdev)
+{
+	struct synthvid_msg msg;
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+	msg.vid_hdr.type = SYNTHVID_POINTER_POSITION;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_pointer_position);
+	msg.ptr_pos.is_visible = 1;
+	msg.ptr_pos.video_output = 0;
+	msg.ptr_pos.image_x = 0;
+	msg.ptr_pos.image_y = 0;
+	synthvid_send(hdev, &msg);
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+	msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_pointer_shape);
+	msg.ptr_shape.part_idx = CURSOR_COMPLETE;
+	msg.ptr_shape.is_argb = 1;
+	msg.ptr_shape.width = 1;
+	msg.ptr_shape.height = 1;
+	msg.ptr_shape.hot_x = 0;
+	msg.ptr_shape.hot_y = 0;
+	msg.ptr_shape.data[0] = 0;
+	msg.ptr_shape.data[1] = 1;
+	msg.ptr_shape.data[2] = 1;
+	msg.ptr_shape.data[3] = 1;
+	synthvid_send(hdev, &msg);
+
+	return 0;
+}
+
+/* Send updated screen area (dirty rectangle) location to host */
+static int synthvid_update(struct fb_info *info)
+{
+	struct hv_device *hdev = device_to_hv_device(info->device);
+	struct synthvid_msg msg;
+
+	memset(&msg, 0, sizeof(struct synthvid_msg));
+
+	msg.vid_hdr.type = SYNTHVID_DIRT;
+	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_dirt);
+	msg.dirt.video_output = 0;
+	msg.dirt.dirt_count = 1;
+	msg.dirt.rect[0].x1 = 0;
+	msg.dirt.rect[0].y1 = 0;
+	msg.dirt.rect[0].x2 = info->var.xres;
+	msg.dirt.rect[0].y2 = info->var.yres;
+
+	synthvid_send(hdev, &msg);
+
+	return 0;
+}
+
+
+/*
+ * Actions on received messages from host:
+ * Complete the wait event.
+ * Or, reply with screen and cursor info.
+ */
+static void synthvid_recv_sub(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par;
+	struct synthvid_msg *msg;
+
+	if (!info)
+		return;
+
+	par = info->par;
+	msg = (struct synthvid_msg *)par->recv_buf;
+
+	/* Complete the wait event */
+	if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||
+	    msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {
+		memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE);
+		complete(&par->wait);
+		return;
+	}
+
+	/* Reply with screen and cursor info */
+	if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {
+		if (par->fb_ready) {
+			synthvid_send_ptr(hdev);
+			synthvid_send_situ(hdev);
+		}
+
+		par->update = msg->feature_chg.is_dirt_needed;
+		if (par->update)
+			schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
+	}
+}
+
+/* Receive callback for messages from the host */
+static void synthvid_receive(void *ctx)
+{
+	struct hv_device *hdev = ctx;
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par;
+	struct synthvid_msg *recv_buf;
+	u32 bytes_recvd;
+	u64 req_id;
+	int ret;
+
+	if (!info)
+		return;
+
+	par = info->par;
+	recv_buf = (struct synthvid_msg *)par->recv_buf;
+
+	do {
+		ret = vmbus_recvpacket(hdev->channel, recv_buf,
+				       MAX_VMBUS_PKT_SIZE,
+				       &bytes_recvd, &req_id);
+		if (bytes_recvd > 0 &&
+		    recv_buf->pipe_hdr.type == PIPE_MSG_DATA)
+			synthvid_recv_sub(hdev);
+	} while (bytes_recvd > 0 && ret == 0);
+}
+
+/* Check synthetic video protocol version with the host */
+static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
+	int t, ret = 0;
+
+	memset(msg, 0, sizeof(struct synthvid_msg));
+	msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST;
+	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_version_req);
+	msg->ver_req.version = ver;
+	synthvid_send(hdev, msg);
+
+	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
+	if (!t) {
+		pr_err("Time out on waiting version response\n");
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+	if (!msg->ver_resp.is_accepted) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	par->synthvid_version = ver;
+
+out:
+	return ret;
+}
+
+/* Connect to VSP (Virtual Service Provider) on host */
+static int synthvid_connect_vsp(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+	int ret;
+
+	ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,
+			 NULL, 0, synthvid_receive, hdev);
+	if (ret) {
+		pr_err("Unable to open vmbus channel\n");
+		return ret;
+	}
+
+	/* Negotiate the protocol version with host */
+	if (vmbus_proto_version == VERSION_WS2008 ||
+	    vmbus_proto_version == VERSION_WIN7)
+		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7);
+	else
+		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8);
+
+	if (ret) {
+		pr_err("Synthetic video device version not accepted\n");
+		goto error;
+	}
+
+	if (par->synthvid_version == SYNTHVID_VERSION_WIN7)
+		screen_depth = SYNTHVID_DEPTH_WIN7;
+	else
+		screen_depth = SYNTHVID_DEPTH_WIN8;
+
+	screen_fb_size = hdev->channel->offermsg.offer.
+				mmio_megabytes * 1024 * 1024;
+
+	return 0;
+
+error:
+	vmbus_close(hdev->channel);
+	return ret;
+}
+
+/* Send VRAM and Situation messages to the host */
+static int synthvid_send_config(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
+	int t, ret = 0;
+
+	/* Send VRAM location */
+	memset(msg, 0, sizeof(struct synthvid_msg));
+	msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION;
+	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
+		sizeof(struct synthvid_vram_location);
+	msg->vram.user_ctx = msg->vram.vram_gpa = info->fix.smem_start;
+	msg->vram.is_vram_gpa_specified = 1;
+	synthvid_send(hdev, msg);
+
+	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
+	if (!t) {
+		pr_err("Time out on waiting vram location ack\n");
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+	if (msg->vram_ack.user_ctx != info->fix.smem_start) {
+		pr_err("Unable to set VRAM location\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Send pointer and situation update */
+	synthvid_send_ptr(hdev);
+	synthvid_send_situ(hdev);
+
+out:
+	return ret;
+}
+
+
+/*
+ * Delayed work callback:
+ * It is called at HVFB_UPDATE_DELAY or longer time interval to process
+ * screen updates. It is re-scheduled if further update is necessary.
+ */
+static void hvfb_update_work(struct work_struct *w)
+{
+	struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work);
+	struct fb_info *info = par->info;
+
+	if (par->fb_ready)
+		synthvid_update(info);
+
+	if (par->update)
+		schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
+}
+
+
+/* Framebuffer operation handlers */
+
+static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN ||
+	    var->xres > screen_width || var->yres >  screen_height ||
+	    var->bits_per_pixel != screen_depth)
+		return -EINVAL;
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	return 0;
+}
+
+static int hvfb_set_par(struct fb_info *info)
+{
+	struct hv_device *hdev = device_to_hv_device(info->device);
+
+	return synthvid_send_situ(hdev);
+}
+
+
+static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)
+{
+	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
+}
+
+static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp, struct fb_info *info)
+{
+	u32 *pal = info->pseudo_palette;
+
+	if (regno > 15)
+		return -EINVAL;
+
+	pal[regno] = chan_to_field(red, &info->var.red)
+		| chan_to_field(green, &info->var.green)
+		| chan_to_field(blue, &info->var.blue)
+		| chan_to_field(transp, &info->var.transp);
+
+	return 0;
+}
+
+static int hvfb_blank(int blank, struct fb_info *info)
+{
+	return 1;	/* get fb_blank to set the colormap to all black */
+}
+
+static struct fb_ops hvfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = hvfb_check_var,
+	.fb_set_par = hvfb_set_par,
+	.fb_setcolreg = hvfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_blank = hvfb_blank,
+};
+
+
+/* Get options from kernel paramenter "video=" */
+static void hvfb_get_option(struct fb_info *info)
+{
+	struct hvfb_par *par = info->par;
+	char *opt = NULL, *p;
+	uint x = 0, y = 0;
+
+	if (fb_get_options(KBUILD_MODNAME, &opt) || !opt || !*opt)
+		return;
+
+	p = strsep(&opt, "x");
+	if (!*p || kstrtouint(p, 0, &x) ||
+	    !opt || !*opt || kstrtouint(opt, 0, &y)) {
+		pr_err("Screen option is invalid: skipped\n");
+		return;
+	}
+
+	if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||
+	    (par->synthvid_version == SYNTHVID_VERSION_WIN8 &&
+	     x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) ||
+	    (par->synthvid_version == SYNTHVID_VERSION_WIN7 &&
+	     (x > SYNTHVID_WIDTH_MAX_WIN7 || y > SYNTHVID_HEIGHT_MAX_WIN7))) {
+		pr_err("Screen resolution option is out of range: skipped\n");
+		return;
+	}
+
+	screen_width = x;
+	screen_height = y;
+	return;
+}
+
+
+/* Get framebuffer memory from Hyper-V video pci space */
+static int hvfb_getmem(struct fb_info *info)
+{
+	struct hvfb_par *par = info->par;
+	struct pci_dev *pdev  = NULL;
+	void __iomem *fb_virt;
+	int gen2vm = efi_enabled(EFI_BOOT);
+	int ret;
+
+	par->mem.name = KBUILD_MODNAME;
+	par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (gen2vm) {
+		ret = allocate_resource(&hyperv_mmio, &par->mem,
+					screen_fb_size,
+					0, -1,
+					screen_fb_size,
+					NULL, NULL);
+		if (ret != 0) {
+			pr_err("Unable to allocate framebuffer memory\n");
+			return -ENODEV;
+		}
+	} else {
+		pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
+			      PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
+		if (!pdev) {
+			pr_err("Unable to find PCI Hyper-V video\n");
+			return -ENODEV;
+		}
+
+		if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
+		    pci_resource_len(pdev, 0) < screen_fb_size)
+			goto err1;
+
+		par->mem.end = pci_resource_end(pdev, 0);
+		par->mem.start = par->mem.end - screen_fb_size + 1;
+		ret = request_resource(&pdev->resource[0], &par->mem);
+		if (ret != 0) {
+			pr_err("Unable to request framebuffer memory\n");
+			goto err1;
+		}
+	}
+
+	fb_virt = ioremap(par->mem.start, screen_fb_size);
+	if (!fb_virt)
+		goto err2;
+
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures)
+		goto err3;
+
+	if (gen2vm) {
+		info->apertures->ranges[0].base = screen_info.lfb_base;
+		info->apertures->ranges[0].size = screen_info.lfb_size;
+		remove_conflicting_framebuffers(info->apertures,
+						KBUILD_MODNAME, false);
+	} else {
+		info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
+		info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
+	}
+
+	info->fix.smem_start = par->mem.start;
+	info->fix.smem_len = screen_fb_size;
+	info->screen_base = fb_virt;
+	info->screen_size = screen_fb_size;
+
+	if (!gen2vm)
+		pci_dev_put(pdev);
+
+	return 0;
+
+err3:
+	iounmap(fb_virt);
+err2:
+	release_resource(&par->mem);
+err1:
+	if (!gen2vm)
+		pci_dev_put(pdev);
+
+	return -ENOMEM;
+}
+
+/* Release the framebuffer */
+static void hvfb_putmem(struct fb_info *info)
+{
+	struct hvfb_par *par = info->par;
+
+	iounmap(info->screen_base);
+	release_resource(&par->mem);
+}
+
+
+static int hvfb_probe(struct hv_device *hdev,
+		      const struct hv_vmbus_device_id *dev_id)
+{
+	struct fb_info *info;
+	struct hvfb_par *par;
+	int ret;
+
+	info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);
+	if (!info) {
+		pr_err("No memory for framebuffer info\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	par->info = info;
+	par->fb_ready = false;
+	init_completion(&par->wait);
+	INIT_DELAYED_WORK(&par->dwork, hvfb_update_work);
+
+	/* Connect to VSP */
+	hv_set_drvdata(hdev, info);
+	ret = synthvid_connect_vsp(hdev);
+	if (ret) {
+		pr_err("Unable to connect to VSP\n");
+		goto error1;
+	}
+
+	ret = hvfb_getmem(info);
+	if (ret) {
+		pr_err("No memory for framebuffer\n");
+		goto error2;
+	}
+
+	hvfb_get_option(info);
+	pr_info("Screen resolution: %dx%d, Color depth: %d\n",
+		screen_width, screen_height, screen_depth);
+
+
+	/* Set up fb_info */
+	info->flags = FBINFO_DEFAULT;
+
+	info->var.xres_virtual = info->var.xres = screen_width;
+	info->var.yres_virtual = info->var.yres = screen_height;
+	info->var.bits_per_pixel = screen_depth;
+
+	if (info->var.bits_per_pixel == 16) {
+		info->var.red = (struct fb_bitfield){11, 5, 0};
+		info->var.green = (struct fb_bitfield){5, 6, 0};
+		info->var.blue = (struct fb_bitfield){0, 5, 0};
+		info->var.transp = (struct fb_bitfield){0, 0, 0};
+	} else {
+		info->var.red = (struct fb_bitfield){16, 8, 0};
+		info->var.green = (struct fb_bitfield){8, 8, 0};
+		info->var.blue = (struct fb_bitfield){0, 8, 0};
+		info->var.transp = (struct fb_bitfield){24, 8, 0};
+	}
+
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->var.height = -1;
+	info->var.width = -1;
+	info->var.vmode = FB_VMODE_NONINTERLACED;
+
+	strcpy(info->fix.id, KBUILD_MODNAME);
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = screen_width * screen_depth / 8;
+	info->fix.accel = FB_ACCEL_NONE;
+
+	info->fbops = &hvfb_ops;
+	info->pseudo_palette = par->pseudo_palette;
+
+	/* Send config to host */
+	ret = synthvid_send_config(hdev);
+	if (ret)
+		goto error;
+
+	ret = register_framebuffer(info);
+	if (ret) {
+		pr_err("Unable to register framebuffer\n");
+		goto error;
+	}
+
+	par->fb_ready = true;
+
+	return 0;
+
+error:
+	hvfb_putmem(info);
+error2:
+	vmbus_close(hdev->channel);
+error1:
+	cancel_delayed_work_sync(&par->dwork);
+	hv_set_drvdata(hdev, NULL);
+	framebuffer_release(info);
+	return ret;
+}
+
+
+static int hvfb_remove(struct hv_device *hdev)
+{
+	struct fb_info *info = hv_get_drvdata(hdev);
+	struct hvfb_par *par = info->par;
+
+	par->update = false;
+	par->fb_ready = false;
+
+	unregister_framebuffer(info);
+	cancel_delayed_work_sync(&par->dwork);
+
+	vmbus_close(hdev->channel);
+	hv_set_drvdata(hdev, NULL);
+
+	hvfb_putmem(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+
+static DEFINE_PCI_DEVICE_TABLE(pci_stub_id_table) = {
+	{
+		.vendor      = PCI_VENDOR_ID_MICROSOFT,
+		.device      = PCI_DEVICE_ID_HYPERV_VIDEO,
+	},
+	{ /* end of list */ }
+};
+
+static const struct hv_vmbus_device_id id_table[] = {
+	/* Synthetic Video Device GUID */
+	{HV_SYNTHVID_GUID},
+	{}
+};
+
+MODULE_DEVICE_TABLE(pci, pci_stub_id_table);
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
+static struct hv_driver hvfb_drv = {
+	.name = KBUILD_MODNAME,
+	.id_table = id_table,
+	.probe = hvfb_probe,
+	.remove = hvfb_remove,
+};
+
+static int hvfb_pci_stub_probe(struct pci_dev *pdev,
+			       const struct pci_device_id *ent)
+{
+	return 0;
+}
+
+static void hvfb_pci_stub_remove(struct pci_dev *pdev)
+{
+}
+
+static struct pci_driver hvfb_pci_stub_driver = {
+	.name =		KBUILD_MODNAME,
+	.id_table =	pci_stub_id_table,
+	.probe =	hvfb_pci_stub_probe,
+	.remove =	hvfb_pci_stub_remove,
+};
+
+static int __init hvfb_drv_init(void)
+{
+	int ret;
+
+	ret = vmbus_driver_register(&hvfb_drv);
+	if (ret != 0)
+		return ret;
+
+	ret = pci_register_driver(&hvfb_pci_stub_driver);
+	if (ret != 0) {
+		vmbus_driver_unregister(&hvfb_drv);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit hvfb_drv_exit(void)
+{
+	pci_unregister_driver(&hvfb_pci_stub_driver);
+	vmbus_driver_unregister(&hvfb_drv);
+}
+
+module_init(hvfb_drv_init);
+module_exit(hvfb_drv_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");
diff --git a/drivers/video/fbdev/i740_reg.h b/drivers/video/fbdev/i740_reg.h
new file mode 100644
index 000000000000..91bac76549d7
--- /dev/null
+++ b/drivers/video/fbdev/i740_reg.h
@@ -0,0 +1,309 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ */
+
+/* I/O register offsets */
+#define SRX VGA_SEQ_I
+#define GRX VGA_GFX_I
+#define ARX VGA_ATT_IW
+#define XRX 0x3D6
+#define MRX 0x3D2
+
+/* VGA Color Palette Registers */
+#define DACMASK		0x3C6
+#define DACSTATE	0x3C7
+#define DACRX		0x3C7
+#define DACWX		0x3C8
+#define DACDATA		0x3C9
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI		0x0C
+#define START_ADDR_LO		0x0D
+#define VERT_SYNC_END		0x11
+#define EXT_VERT_TOTAL		0x30
+#define EXT_VERT_DISPLAY	0x31
+#define EXT_VERT_SYNC_START	0x32
+#define EXT_VERT_BLANK_START	0x33
+#define EXT_HORIZ_TOTAL		0x35
+#define EXT_HORIZ_BLANK		0x39
+#define EXT_START_ADDR		0x40
+#define EXT_START_ADDR_ENABLE	0x80
+#define EXT_OFFSET		0x41
+#define EXT_START_ADDR_HI	0x42
+#define INTERLACE_CNTL		0x70
+#define INTERLACE_ENABLE	0x80
+#define INTERLACE_DISABLE	0x00
+
+/* Miscellaneous Output Register */
+#define MSR_R		0x3CC
+#define MSR_W		0x3C2
+#define IO_ADDR_SELECT	0x01
+
+#define MDA_BASE	0x3B0
+#define CGA_BASE	0x3D0
+
+/* System Configuration Extension Registers (XRX) */
+#define IO_CTNL		0x09
+#define EXTENDED_ATTR_CNTL	0x02
+#define EXTENDED_CRTC_CNTL	0x01
+
+#define ADDRESS_MAPPING	0x0A
+#define PACKED_MODE_ENABLE	0x04
+#define LINEAR_MODE_ENABLE	0x02
+#define PAGE_MAPPING_ENABLE	0x01
+
+#define BITBLT_CNTL	0x20
+#define COLEXP_MODE		0x30
+#define COLEXP_8BPP		0x00
+#define COLEXP_16BPP		0x10
+#define COLEXP_24BPP		0x20
+#define COLEXP_RESERVED		0x30
+#define CHIP_RESET		0x02
+#define BITBLT_STATUS		0x01
+
+#define DISPLAY_CNTL	0x40
+#define VGA_WRAP_MODE		0x02
+#define VGA_WRAP_AT_256KB	0x00
+#define VGA_NO_WRAP		0x02
+#define GUI_MODE		0x01
+#define STANDARD_VGA_MODE	0x00
+#define HIRES_MODE		0x01
+
+#define DRAM_ROW_TYPE	0x50
+#define DRAM_ROW_0		0x07
+#define DRAM_ROW_0_SDRAM	0x00
+#define DRAM_ROW_0_EMPTY	0x07
+#define DRAM_ROW_1		0x38
+#define DRAM_ROW_1_SDRAM	0x00
+#define DRAM_ROW_1_EMPTY	0x38
+#define DRAM_ROW_CNTL_LO 0x51
+#define DRAM_CAS_LATENCY	0x10
+#define DRAM_RAS_TIMING		0x08
+#define DRAM_RAS_PRECHARGE	0x04
+#define DRAM_ROW_CNTL_HI 0x52
+#define DRAM_EXT_CNTL	0x53
+#define DRAM_REFRESH_RATE	0x03
+#define DRAM_REFRESH_DISABLE	0x00
+#define DRAM_REFRESH_60HZ	0x01
+#define DRAM_REFRESH_FAST_TEST	0x02
+#define DRAM_REFRESH_RESERVED	0x03
+#define DRAM_TIMING	0x54
+#define DRAM_ROW_BNDRY_0 0x55
+#define DRAM_ROW_BNDRY_1 0x56
+
+#define DPMS_SYNC_SELECT 0x61
+#define VSYNC_CNTL		0x08
+#define VSYNC_ON		0x00
+#define VSYNC_OFF		0x08
+#define HSYNC_CNTL		0x02
+#define HSYNC_ON		0x00
+#define HSYNC_OFF		0x02
+
+#define PIXPIPE_CONFIG_0 0x80
+#define DAC_8_BIT		0x80
+#define DAC_6_BIT		0x00
+#define HW_CURSOR_ENABLE	0x10
+#define EXTENDED_PALETTE	0x01
+
+#define PIXPIPE_CONFIG_1 0x81
+#define DISPLAY_COLOR_MODE	0x0F
+#define DISPLAY_VGA_MODE	0x00
+#define DISPLAY_8BPP_MODE	0x02
+#define DISPLAY_15BPP_MODE	0x04
+#define DISPLAY_16BPP_MODE	0x05
+#define DISPLAY_24BPP_MODE	0x06
+#define DISPLAY_32BPP_MODE	0x07
+
+#define PIXPIPE_CONFIG_2 0x82
+#define DISPLAY_GAMMA_ENABLE	0x08
+#define DISPLAY_GAMMA_DISABLE	0x00
+#define OVERLAY_GAMMA_ENABLE	0x04
+#define OVERLAY_GAMMA_DISABLE	0x00
+
+#define CURSOR_CONTROL	0xA0
+#define CURSOR_ORIGIN_SCREEN	0x00
+#define CURSOR_ORIGIN_DISPLAY	0x10
+#define CURSOR_MODE		0x07
+#define CURSOR_MODE_DISABLE	0x00
+#define CURSOR_MODE_32_4C_AX	0x01
+#define CURSOR_MODE_128_2C	0x02
+#define CURSOR_MODE_128_1C	0x03
+#define CURSOR_MODE_64_3C	0x04
+#define CURSOR_MODE_64_4C_AX	0x05
+#define CURSOR_MODE_64_4C	0x06
+#define CURSOR_MODE_RESERVED	0x07
+#define CURSOR_BASEADDR_LO 0xA2
+#define CURSOR_BASEADDR_HI 0xA3
+#define CURSOR_X_LO	0xA4
+#define CURSOR_X_HI	0xA5
+#define CURSOR_X_POS		0x00
+#define CURSOR_X_NEG		0x80
+#define CURSOR_Y_LO	0xA6
+#define CURSOR_Y_HI	0xA7
+#define CURSOR_Y_POS		0x00
+#define CURSOR_Y_NEG		0x80
+
+#define VCLK2_VCO_M	0xC8
+#define VCLK2_VCO_N	0xC9
+#define VCLK2_VCO_MN_MSBS 0xCA
+#define VCO_N_MSBS		0x30
+#define VCO_M_MSBS		0x03
+#define VCLK2_VCO_DIV_SEL 0xCB
+#define POST_DIV_SELECT		0x70
+#define POST_DIV_1		0x00
+#define POST_DIV_2		0x10
+#define POST_DIV_4		0x20
+#define POST_DIV_8		0x30
+#define POST_DIV_16		0x40
+#define POST_DIV_32		0x50
+#define VCO_LOOP_DIV_BY_4M	0x00
+#define VCO_LOOP_DIV_BY_16M	0x04
+#define REF_CLK_DIV_BY_5	0x02
+#define REF_DIV_4		0x00
+#define REF_DIV_1		0x01
+
+#define PLL_CNTL	0xCE
+#define PLL_MEMCLK_SEL		0x03
+#define PLL_MEMCLK__66667KHZ	0x00
+#define PLL_MEMCLK__75000KHZ	0x01
+#define PLL_MEMCLK__88889KHZ	0x02
+#define PLL_MEMCLK_100000KHZ	0x03
+
+/* Multimedia Extension Registers (MRX) */
+#define ACQ_CNTL_1	0x02
+#define ACQ_CNTL_2	0x03
+#define FRAME_CAP_MODE		0x01
+#define CONT_CAP_MODE		0x00
+#define SINGLE_CAP_MODE		0x01
+#define ACQ_CNTL_3	0x04
+#define COL_KEY_CNTL_1		0x3C
+#define BLANK_DISP_OVERLAY	0x20
+
+/* FIFOs */
+#define LP_FIFO		0x1000
+#define HP_FIFO		0x2000
+#define INSTPNT		0x3040
+#define LP_FIFO_COUNT	0x3040
+#define HP_FIFO_COUNT	0x3041
+
+/* FIFO Commands */
+#define CLIENT		0xE0000000
+#define CLIENT_2D	0x60000000
+
+/* Command Parser Mode Register */
+#define COMPARS		0x3038
+#define TWO_D_INST_DISABLE		0x08
+#define THREE_D_INST_DISABLE		0x04
+#define STATE_VAR_UPDATE_DISABLE	0x02
+#define PAL_STIP_DISABLE		0x01
+
+/* Interrupt Control Registers */
+#define IER		0x3030
+#define IIR		0x3032
+#define IMR		0x3034
+#define ISR		0x3036
+#define VMIINTB_EVENT		0x2000
+#define GPIO4_INT		0x1000
+#define DISP_FLIP_EVENT		0x0800
+#define DVD_PORT_DMA		0x0400
+#define DISP_VBLANK		0x0200
+#define FIFO_EMPTY_DMA_DONE	0x0100
+#define INST_PARSER_ERROR	0x0080
+#define USER_DEFINED		0x0040
+#define BREAKPOINT		0x0020
+#define DISP_HORIZ_COUNT	0x0010
+#define DISP_VSYNC		0x0008
+#define CAPTURE_HORIZ_COUNT	0x0004
+#define CAPTURE_VSYNC		0x0002
+#define THREE_D_PIPE_FLUSHED	0x0001
+
+/* FIFO Watermark and Burst Length Control Register */
+#define FWATER_BLC	0x00006000
+#define LMI_BURST_LENGTH	0x7F000000
+#define LMI_FIFO_WATERMARK	0x003F0000
+#define AGP_BURST_LENGTH	0x00007F00
+#define AGP_FIFO_WATERMARK	0x0000003F
+
+/* BitBLT Registers */
+#define SRC_DST_PITCH	0x00040000
+#define DST_PITCH		0x1FFF0000
+#define SRC_PITCH		0x00001FFF
+#define COLEXP_BG_COLOR	0x00040004
+#define COLEXP_FG_COLOR	0x00040008
+#define MONO_SRC_CNTL	0x0004000C
+#define MONO_USE_COLEXP		0x00000000
+#define MONO_USE_SRCEXP		0x08000000
+#define MONO_DATA_ALIGN		0x07000000
+#define MONO_BIT_ALIGN		0x01000000
+#define MONO_BYTE_ALIGN		0x02000000
+#define MONO_WORD_ALIGN		0x03000000
+#define MONO_DWORD_ALIGN	0x04000000
+#define MONO_QWORD_ALIGN	0x05000000
+#define MONO_SRC_INIT_DSCRD	0x003F0000
+#define MONO_SRC_RIGHT_CLIP	0x00003F00
+#define MONO_SRC_LEFT_CLIP	0x0000003F
+#define BITBLT_CONTROL	0x00040010
+#define BLTR_STATUS		0x80000000
+#define DYN_DEPTH		0x03000000
+#define DYN_DEPTH_8BPP		0x00000000
+#define DYN_DEPTH_16BPP		0x01000000
+#define DYN_DEPTH_24BPP		0x02000000
+#define DYN_DEPTH_32BPP		0x03000000	/* Unimplemented on the i740 */
+#define DYN_DEPTH_ENABLE	0x00800000
+#define PAT_VERT_ALIGN		0x00700000
+#define SOLID_PAT_SELECT	0x00080000
+#define PAT_IS_IN_COLOR		0x00000000
+#define PAT_IS_MONO		0x00040000
+#define MONO_PAT_TRANSP		0x00020000
+#define COLOR_TRANSP_ROP	0x00000000
+#define COLOR_TRANSP_DST	0x00008000
+#define COLOR_TRANSP_EQ		0x00000000
+#define COLOR_TRANSP_NOT_EQ	0x00010000
+#define COLOR_TRANSP_ENABLE	0x00004000
+#define MONO_SRC_TRANSP		0x00002000
+#define SRC_IS_IN_COLOR		0x00000000
+#define SRC_IS_MONO		0x00001000
+#define SRC_USE_SRC_ADDR	0x00000000
+#define SRC_USE_BLTDATA		0x00000400
+#define BLT_TOP_TO_BOT		0x00000000
+#define BLT_BOT_TO_TOP		0x00000200
+#define BLT_LEFT_TO_RIGHT	0x00000000
+#define BLT_RIGHT_TO_LEFT	0x00000100
+#define BLT_ROP			0x000000FF
+#define BLT_PAT_ADDR	0x00040014
+#define BLT_SRC_ADDR	0x00040018
+#define BLT_DST_ADDR	0x0004001C
+#define BLT_DST_H_W	0x00040020
+#define BLT_DST_HEIGHT		0x1FFF0000
+#define BLT_DST_WIDTH		0x00001FFF
+#define SRCEXP_BG_COLOR	0x00040024
+#define SRCEXP_FG_COLOR	0x00040028
+#define BLTDATA		0x00050000
diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c
new file mode 100644
index 000000000000..ca7c9df193b0
--- /dev/null
+++ b/drivers/video/fbdev/i740fb.c
@@ -0,0 +1,1333 @@
+/*
+ * i740fb - framebuffer driver for Intel740
+ * Copyright (c) 2011 Ondrej Zary
+ *
+ * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
+ * which was partially based on:
+ *  VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
+ *	and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ *  i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
+ *	Texas.
+ *  i740fb by Patrick LERDA, v0.9
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/console.h>
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "i740_reg.h"
+
+static char *mode_option;
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+struct i740fb_par {
+	unsigned char __iomem *regs;
+	bool has_sgram;
+#ifdef CONFIG_MTRR
+	int mtrr_reg;
+#endif
+	bool ddc_registered;
+	struct i2c_adapter ddc_adapter;
+	struct i2c_algo_bit_data ddc_algo;
+	u32 pseudo_palette[16];
+	struct mutex open_lock;
+	unsigned int ref_count;
+
+	u8 crtc[VGA_CRT_C];
+	u8 atc[VGA_ATT_C];
+	u8 gdc[VGA_GFX_C];
+	u8 seq[VGA_SEQ_C];
+	u8 misc;
+	u8 vss;
+
+	/* i740 specific registers */
+	u8 display_cntl;
+	u8 pixelpipe_cfg0;
+	u8 pixelpipe_cfg1;
+	u8 pixelpipe_cfg2;
+	u8 video_clk2_m;
+	u8 video_clk2_n;
+	u8 video_clk2_mn_msbs;
+	u8 video_clk2_div_sel;
+	u8 pll_cntl;
+	u8 address_mapping;
+	u8 io_cntl;
+	u8 bitblt_cntl;
+	u8 ext_vert_total;
+	u8 ext_vert_disp_end;
+	u8 ext_vert_sync_start;
+	u8 ext_vert_blank_start;
+	u8 ext_horiz_total;
+	u8 ext_horiz_blank;
+	u8 ext_offset;
+	u8 interlace_cntl;
+	u32 lmi_fifo_watermark;
+	u8 ext_start_addr;
+	u8 ext_start_addr_hi;
+};
+
+#define DACSPEED8	203
+#define DACSPEED16	163
+#define DACSPEED24_SG	136
+#define DACSPEED24_SD	128
+#define DACSPEED32	86
+
+static struct fb_fix_screeninfo i740fb_fix = {
+	.id =		"i740fb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.xpanstep =	8,
+	.ypanstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
+{
+	vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb(struct i740fb_par *par, u16 port)
+{
+	return vga_mm_r(par->regs, port);
+}
+static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
+{
+	vga_mm_w_fast(par->regs, port, reg, val);
+}
+static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
+{
+	vga_mm_w(par->regs, port, reg);
+	return vga_mm_r(par->regs, port+1);
+}
+static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
+				   u8 val, u8 mask)
+{
+	vga_mm_w_fast(par->regs, port, reg, (val & mask)
+		| (i740inreg(par, port, reg) & ~mask));
+}
+
+#define REG_DDC_DRIVE	0x62
+#define REG_DDC_STATE	0x63
+#define DDC_SCL		(1 << 3)
+#define DDC_SDA		(1 << 2)
+
+static void i740fb_ddc_setscl(void *data, int val)
+{
+	struct i740fb_par *par = data;
+
+	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
+	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
+}
+
+static void i740fb_ddc_setsda(void *data, int val)
+{
+	struct i740fb_par *par = data;
+
+	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
+	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
+}
+
+static int i740fb_ddc_getscl(void *data)
+{
+	struct i740fb_par *par = data;
+
+	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
+
+	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
+}
+
+static int i740fb_ddc_getsda(void *data)
+{
+	struct i740fb_par *par = data;
+
+	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
+
+	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
+}
+
+static int i740fb_setup_ddc_bus(struct fb_info *info)
+{
+	struct i740fb_par *par = info->par;
+
+	strlcpy(par->ddc_adapter.name, info->fix.id,
+		sizeof(par->ddc_adapter.name));
+	par->ddc_adapter.owner		= THIS_MODULE;
+	par->ddc_adapter.class		= I2C_CLASS_DDC;
+	par->ddc_adapter.algo_data	= &par->ddc_algo;
+	par->ddc_adapter.dev.parent	= info->device;
+	par->ddc_algo.setsda		= i740fb_ddc_setsda;
+	par->ddc_algo.setscl		= i740fb_ddc_setscl;
+	par->ddc_algo.getsda		= i740fb_ddc_getsda;
+	par->ddc_algo.getscl		= i740fb_ddc_getscl;
+	par->ddc_algo.udelay		= 10;
+	par->ddc_algo.timeout		= 20;
+	par->ddc_algo.data		= par;
+
+	i2c_set_adapdata(&par->ddc_adapter, par);
+
+	return i2c_bit_add_bus(&par->ddc_adapter);
+}
+
+static int i740fb_open(struct fb_info *info, int user)
+{
+	struct i740fb_par *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	par->ref_count++;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+static int i740fb_release(struct fb_info *info, int user)
+{
+	struct i740fb_par *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		fb_err(info, "release called with zero refcount\n");
+		mutex_unlock(&(par->open_lock));
+		return -EINVAL;
+	}
+
+	par->ref_count--;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
+{
+	/*
+	 * Would like to calculate these values automatically, but a generic
+	 * algorithm does not seem possible.  Note: These FIFO water mark
+	 * values were tested on several cards and seem to eliminate the
+	 * all of the snow and vertical banding, but fine adjustments will
+	 * probably be required for other cards.
+	 */
+
+	u32 wm;
+
+	switch (bpp) {
+	case 8:
+		if	(freq > 200)
+			wm = 0x18120000;
+		else if (freq > 175)
+			wm = 0x16110000;
+		else if (freq > 135)
+			wm = 0x120E0000;
+		else
+			wm = 0x100D0000;
+		break;
+	case 15:
+	case 16:
+		if (par->has_sgram) {
+			if	(freq > 140)
+				wm = 0x2C1D0000;
+			else if (freq > 120)
+				wm = 0x2C180000;
+			else if (freq > 100)
+				wm = 0x24160000;
+			else if (freq >  90)
+				wm = 0x18120000;
+			else if (freq >  50)
+				wm = 0x16110000;
+			else if (freq >  32)
+				wm = 0x13100000;
+			else
+				wm = 0x120E0000;
+		} else {
+			if	(freq > 160)
+				wm = 0x28200000;
+			else if (freq > 140)
+				wm = 0x2A1E0000;
+			else if (freq > 130)
+				wm = 0x2B1A0000;
+			else if (freq > 120)
+				wm = 0x2C180000;
+			else if (freq > 100)
+				wm = 0x24180000;
+			else if (freq >  90)
+				wm = 0x18120000;
+			else if (freq >  50)
+				wm = 0x16110000;
+			else if (freq >  32)
+				wm = 0x13100000;
+			else
+				wm = 0x120E0000;
+		}
+		break;
+	case 24:
+		if (par->has_sgram) {
+			if	(freq > 130)
+				wm = 0x31200000;
+			else if (freq > 120)
+				wm = 0x2E200000;
+			else if (freq > 100)
+				wm = 0x2C1D0000;
+			else if (freq >  80)
+				wm = 0x25180000;
+			else if (freq >  64)
+				wm = 0x24160000;
+			else if (freq >  49)
+				wm = 0x18120000;
+			else if (freq >  32)
+				wm = 0x16110000;
+			else
+				wm = 0x13100000;
+		} else {
+			if	(freq > 120)
+				wm = 0x311F0000;
+			else if (freq > 100)
+				wm = 0x2C1D0000;
+			else if (freq >  80)
+				wm = 0x25180000;
+			else if (freq >  64)
+				wm = 0x24160000;
+			else if (freq >  49)
+				wm = 0x18120000;
+			else if (freq >  32)
+				wm = 0x16110000;
+			else
+				wm = 0x13100000;
+		}
+		break;
+	case 32:
+		if (par->has_sgram) {
+			if	(freq >  80)
+				wm = 0x2A200000;
+			else if (freq >  60)
+				wm = 0x281A0000;
+			else if (freq >  49)
+				wm = 0x25180000;
+			else if (freq >  32)
+				wm = 0x18120000;
+			else
+				wm = 0x16110000;
+		} else {
+			if	(freq >  80)
+				wm = 0x29200000;
+			else if (freq >  60)
+				wm = 0x281A0000;
+			else if (freq >  49)
+				wm = 0x25180000;
+			else if (freq >  32)
+				wm = 0x18120000;
+			else
+				wm = 0x16110000;
+		}
+		break;
+	}
+
+	return wm;
+}
+
+/* clock calculation from i740fb by Patrick LERDA */
+
+#define I740_RFREQ		1000000
+#define TARGET_MAX_N		30
+#define I740_FFIX		(1 << 8)
+#define I740_RFREQ_FIX		(I740_RFREQ / I740_FFIX)
+#define I740_REF_FREQ		(6667 * I740_FFIX / 100)	/* 66.67 MHz */
+#define I740_MAX_VCO_FREQ	(450 * I740_FFIX)		/* 450 MHz */
+
+static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
+{
+	const u32 err_max    = freq / (200  * I740_RFREQ / I740_FFIX);
+	const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
+	u32 err_best = 512 * I740_FFIX;
+	u32 f_err, f_vco;
+	int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
+	int m, n;
+
+	p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
+	d_best = 0;
+	f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
+	freq = freq / I740_RFREQ_FIX;
+
+	n = 2;
+	do {
+		n++;
+		m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
+
+		if (m < 3)
+			m = 3;
+
+		{
+			u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best))
+				 / n) + ((1 << p_best) / 2)) / (1 << p_best);
+
+			f_err = (freq - f_out);
+
+			if (abs(f_err) < err_max) {
+				m_best = m;
+				n_best = n;
+				err_best = f_err;
+			}
+		}
+	} while ((abs(f_err) >= err_target) &&
+		 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
+
+	if (abs(f_err) < err_target) {
+		m_best = m;
+		n_best = n;
+	}
+
+	par->video_clk2_m = (m_best - 2) & 0xFF;
+	par->video_clk2_n = (n_best - 2) & 0xFF;
+	par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
+				 | (((m_best - 2) >> 8) & VCO_M_MSBS));
+	par->video_clk2_div_sel =
+		((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
+}
+
+static int i740fb_decode_var(const struct fb_var_screeninfo *var,
+			     struct i740fb_par *par, struct fb_info *info)
+{
+	/*
+	 * Get the video params out of 'var'.
+	 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
+	 */
+
+	u32 xres, right, hslen, left, xtotal;
+	u32 yres, lower, vslen, upper, ytotal;
+	u32 vxres, xoffset, vyres, yoffset;
+	u32 bpp, base, dacspeed24, mem;
+	u8 r7;
+	int i;
+
+	dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
+		  var->xres, var->yres, var->xres_virtual, var->xres_virtual);
+	dev_dbg(info->device, "	xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
+		  var->xoffset, var->yoffset, var->bits_per_pixel,
+		  var->grayscale);
+	dev_dbg(info->device, "	activate: %i, nonstd: %i, vmode: %i\n",
+		  var->activate, var->nonstd, var->vmode);
+	dev_dbg(info->device, "	pixclock: %i, hsynclen:%i, vsynclen:%i\n",
+		  var->pixclock, var->hsync_len, var->vsync_len);
+	dev_dbg(info->device, "	left: %i, right: %i, up:%i, lower:%i\n",
+		  var->left_margin, var->right_margin, var->upper_margin,
+		  var->lower_margin);
+
+
+	bpp = var->bits_per_pixel;
+	switch (bpp) {
+	case 1 ... 8:
+		bpp = 8;
+		if ((1000000 / var->pixclock) > DACSPEED8) {
+			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
+				1000000 / var->pixclock, DACSPEED8);
+			return -EINVAL;
+		}
+		break;
+	case 9 ... 15:
+		bpp = 15;
+	case 16:
+		if ((1000000 / var->pixclock) > DACSPEED16) {
+			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
+				1000000 / var->pixclock, DACSPEED16);
+			return -EINVAL;
+		}
+		break;
+	case 17 ... 24:
+		bpp = 24;
+		dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
+		if ((1000000 / var->pixclock) > dacspeed24) {
+			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
+				1000000 / var->pixclock, dacspeed24);
+			return -EINVAL;
+		}
+		break;
+	case 25 ... 32:
+		bpp = 32;
+		if ((1000000 / var->pixclock) > DACSPEED32) {
+			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
+				1000000 / var->pixclock, DACSPEED32);
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	xres = ALIGN(var->xres, 8);
+	vxres = ALIGN(var->xres_virtual, 16);
+	if (vxres < xres)
+		vxres = xres;
+
+	xoffset = ALIGN(var->xoffset, 8);
+	if (xres + xoffset > vxres)
+		xoffset = vxres - xres;
+
+	left = ALIGN(var->left_margin, 8);
+	right = ALIGN(var->right_margin, 8);
+	hslen = ALIGN(var->hsync_len, 8);
+
+	yres = var->yres;
+	vyres = var->yres_virtual;
+	if (yres > vyres)
+		vyres = yres;
+
+	yoffset = var->yoffset;
+	if (yres + yoffset > vyres)
+		yoffset = vyres - yres;
+
+	lower = var->lower_margin;
+	vslen = var->vsync_len;
+	upper = var->upper_margin;
+
+	mem = vxres * vyres * ((bpp + 1) / 8);
+	if (mem > info->screen_size) {
+		dev_err(info->device, "not enough video memory (%d KB requested, %ld KB available)\n",
+			mem >> 10, info->screen_size >> 10);
+		return -ENOMEM;
+	}
+
+	if (yoffset + yres > vyres)
+		yoffset = vyres - yres;
+
+	xtotal = xres + right + hslen + left;
+	ytotal = yres + lower + vslen + upper;
+
+	par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
+	par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
+	par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
+	par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
+	par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
+		| ((((xres + right + hslen) >> 3) & 0x20) << 2);
+	par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
+		| 0x80;
+
+	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
+
+	r7 = 0x10;	/* disable linecompare */
+	if (ytotal & 0x100)
+		r7 |= 0x01;
+	if (ytotal & 0x200)
+		r7 |= 0x20;
+
+	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
+	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
+	if (var->vmode & FB_VMODE_DOUBLE)
+		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
+	par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
+	par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
+	par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
+	par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
+	par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
+	if ((yres-1) & 0x100)
+		r7 |= 0x02;
+	if ((yres-1) & 0x200)
+		r7 |= 0x40;
+
+	par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
+	par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
+	if ((yres + lower - 1) & 0x100)
+		r7 |= 0x0C;
+	if ((yres + lower - 1) & 0x200) {
+		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
+		r7 |= 0x80;
+	}
+
+	/* disabled IRQ */
+	par->crtc[VGA_CRTC_V_SYNC_END] =
+		((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
+	/* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
+	par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
+
+	par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
+	par->crtc[VGA_CRTC_MODE] = 0xC3 ;
+	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
+	par->crtc[VGA_CRTC_OVERFLOW] = r7;
+
+	par->vss = 0x00;	/* 3DA */
+
+	for (i = 0x00; i < 0x10; i++)
+		par->atc[i] = i;
+	par->atc[VGA_ATC_MODE] = 0x81;
+	par->atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
+	par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
+	par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
+
+	par->misc = 0xC3;
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		par->misc &= ~0x40;
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		par->misc &= ~0x80;
+
+	par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
+	par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
+	par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+	par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
+
+	par->gdc[VGA_GFX_SR_VALUE] = 0x00;
+	par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
+	par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
+	par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
+	par->gdc[VGA_GFX_PLANE_READ] = 0;
+	par->gdc[VGA_GFX_MODE] = 0x02;
+	par->gdc[VGA_GFX_MISC] = 0x05;
+	par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
+	par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
+
+	base = (yoffset * vxres + (xoffset & ~7)) >> 2;
+	switch (bpp) {
+	case 8:
+		par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
+		par->ext_offset = vxres >> 11;
+		par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
+		par->bitblt_cntl = COLEXP_8BPP;
+		break;
+	case 15: /* 0rrrrrgg gggbbbbb */
+	case 16: /* rrrrrggg gggbbbbb */
+		par->pixelpipe_cfg1 = (var->green.length == 6) ?
+			DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
+		par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
+		par->ext_offset = vxres >> 10;
+		par->bitblt_cntl = COLEXP_16BPP;
+		base *= 2;
+		break;
+	case 24:
+		par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
+		par->ext_offset = (vxres * 3) >> 11;
+		par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
+		par->bitblt_cntl = COLEXP_24BPP;
+		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+		base *= 3;
+		break;
+	case 32:
+		par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
+		par->ext_offset = vxres >> 9;
+		par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
+		par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
+		base *= 4;
+		break;
+	}
+
+	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
+	par->ext_start_addr =
+		((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+
+	par->pixelpipe_cfg0 = DAC_8_BIT;
+
+	par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
+	par->io_cntl = EXTENDED_CRTC_CNTL;
+	par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
+	par->display_cntl = HIRES_MODE;
+
+	/* Set the MCLK freq */
+	par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
+
+	/* Calculate the extended CRTC regs */
+	par->ext_vert_total = (ytotal - 2) >> 8;
+	par->ext_vert_disp_end = (yres - 1) >> 8;
+	par->ext_vert_sync_start = (yres + lower) >> 8;
+	par->ext_vert_blank_start = (yres + lower) >> 8;
+	par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
+	par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
+
+	par->interlace_cntl = INTERLACE_DISABLE;
+
+	/* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
+	par->atc[VGA_ATC_OVERSCAN] = 0;
+
+	/* Calculate VCLK that most closely matches the requested dot clock */
+	i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
+
+	/* Since we program the clocks ourselves, always use VCLK2. */
+	par->misc |= 0x0C;
+
+	/* Calculate the FIFO Watermark and Burst Length. */
+	par->lmi_fifo_watermark =
+		i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
+
+	return 0;
+}
+
+static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset	= var->green.offset = var->blue.offset = 0;
+		var->red.length	= var->green.length = var->blue.length = 8;
+		break;
+	case 16:
+		switch (var->green.length) {
+		default:
+		case 5:
+			var->red.offset = 10;
+			var->green.offset = 5;
+			var->blue.offset = 0;
+			var->red.length	= 5;
+			var->green.length = 5;
+			var->blue.length = 5;
+			break;
+		case 6:
+			var->red.offset = 11;
+			var->green.offset = 5;
+			var->blue.offset = 0;
+			var->red.length = var->blue.length = 5;
+			break;
+		}
+		break;
+	case 24:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length	= var->green.length = var->blue.length = 8;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->transp.length = 8;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	if (info->monspecs.hfmax && info->monspecs.vfmax &&
+	    info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void vga_protect(struct i740fb_par *par)
+{
+	/* disable the display */
+	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
+
+	i740inb(par, 0x3DA);
+	i740outb(par, VGA_ATT_W, 0x00);	/* enable palette access */
+}
+
+static void vga_unprotect(struct i740fb_par *par)
+{
+	/* reenable display */
+	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
+
+	i740inb(par, 0x3DA);
+	i740outb(par, VGA_ATT_W, 0x20);	/* disable palette access */
+}
+
+static int i740fb_set_par(struct fb_info *info)
+{
+	struct i740fb_par *par = info->par;
+	u32 itemp;
+	int i;
+
+	i = i740fb_decode_var(&info->var, par, info);
+	if (i)
+		return i;
+
+	memset(info->screen_base, 0, info->screen_size);
+
+	vga_protect(par);
+
+	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
+
+	mdelay(1);
+
+	i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
+	i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
+	i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
+	i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
+
+	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
+			par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
+
+	i740inb(par, 0x3DA);
+	i740outb(par, 0x3C0, 0x00);
+
+	/* update misc output register */
+	i740outb(par, VGA_MIS_W, par->misc | 0x01);
+
+	/* synchronous reset on */
+	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
+	/* write sequencer registers */
+	i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
+			par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
+	for (i = 2; i < VGA_SEQ_C; i++)
+		i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
+
+	/* synchronous reset off */
+	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
+
+	/* deprotect CRT registers 0-7 */
+	i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
+			par->crtc[VGA_CRTC_V_SYNC_END]);
+
+	/* write CRT registers */
+	for (i = 0; i < VGA_CRT_C; i++)
+		i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
+
+	/* write graphics controller registers */
+	for (i = 0; i < VGA_GFX_C; i++)
+		i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
+
+	/* write attribute controller registers */
+	for (i = 0; i < VGA_ATT_C; i++) {
+		i740inb(par, VGA_IS1_RC);		/* reset flip-flop */
+		i740outb(par, VGA_ATT_IW, i);
+		i740outb(par, VGA_ATT_IW, par->atc[i]);
+	}
+
+	i740inb(par, VGA_IS1_RC);
+	i740outb(par, VGA_ATT_IW, 0x20);
+
+	i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
+	i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
+	i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
+			par->ext_vert_sync_start);
+	i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
+			par->ext_vert_blank_start);
+	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
+	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
+	i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
+	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
+	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
+
+	i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
+			par->interlace_cntl, INTERLACE_ENABLE);
+	i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
+	i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
+	i740outreg_mask(par, XRX, DISPLAY_CNTL,
+			par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
+	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
+	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
+
+	i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
+
+	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
+			par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
+
+	itemp = readl(par->regs + FWATER_BLC);
+	itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
+	itemp |= par->lmi_fifo_watermark;
+	writel(itemp, par->regs + FWATER_BLC);
+
+	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
+
+	i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
+	i740outreg_mask(par, XRX, IO_CTNL,
+			par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+
+	if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
+		i740outb(par, VGA_PEL_MSK, 0xFF);
+		i740outb(par, VGA_PEL_IW, 0x00);
+		for (i = 0; i < 256; i++) {
+			itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
+			i740outb(par, VGA_PEL_D, itemp);
+			i740outb(par, VGA_PEL_D, itemp);
+			i740outb(par, VGA_PEL_D, itemp);
+		}
+	}
+
+	/* Wait for screen to stabilize. */
+	mdelay(50);
+	vga_unprotect(par);
+
+	info->fix.line_length =
+			info->var.xres_virtual * info->var.bits_per_pixel / 8;
+	if (info->var.bits_per_pixel == 8)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	return 0;
+}
+
+static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	u32 r, g, b;
+
+	dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
+		regno, red, green, blue, transp, info->var.bits_per_pixel);
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno >= 256)
+			return -EINVAL;
+		i740outb(info->par, VGA_PEL_IW, regno);
+		i740outb(info->par, VGA_PEL_D, red >> 8);
+		i740outb(info->par, VGA_PEL_D, green >> 8);
+		i740outb(info->par, VGA_PEL_D, blue >> 8);
+		break;
+	case FB_VISUAL_TRUECOLOR:
+		if (regno >= 16)
+			return -EINVAL;
+		r = (red >> (16 - info->var.red.length))
+			<< info->var.red.offset;
+		b = (blue >> (16 - info->var.blue.length))
+			<< info->var.blue.offset;
+		g = (green >> (16 - info->var.green.length))
+			<< info->var.green.offset;
+		((u32 *) info->pseudo_palette)[regno] = r | g | b;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int i740fb_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	struct i740fb_par *par = info->par;
+	u32 base = (var->yoffset * info->var.xres_virtual
+		 + (var->xoffset & ~7)) >> 2;
+
+	dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
+		var->xoffset, var->yoffset, base);
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		break;
+	case 15:
+	case 16:
+		base *= 2;
+		break;
+	case 24:
+		/*
+		 * The last bit does not seem to have any effect on the start
+		 * address register in 24bpp mode, so...
+		 */
+		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+		base *= 3;
+		break;
+	case 32:
+		base *= 4;
+		break;
+	}
+
+	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
+	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+	par->ext_start_addr =
+			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+
+	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO,  base & 0x000000FF);
+	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
+			(base & 0x0000FF00) >> 8);
+	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
+			(base & 0x3FC00000) >> 22);
+	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
+			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
+
+	return 0;
+}
+
+static int i740fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct i740fb_par *par = info->par;
+
+	unsigned char SEQ01;
+	int DPMSSyncSelect;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		SEQ01 = 0x00;
+		DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		SEQ01 = 0x20;
+		DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		SEQ01 = 0x20;
+		DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+		break;
+	case FB_BLANK_POWERDOWN:
+		SEQ01 = 0x20;
+		DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+		break;
+	default:
+		return -EINVAL;
+	}
+	/* Turn the screen on/off */
+	i740outb(par, SRX, 0x01);
+	SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
+	i740outb(par, SRX, 0x01);
+	i740outb(par, SRX + 1, SEQ01);
+
+	/* Set the DPMS mode */
+	i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
+
+	/* Let fbcon do a soft blank for us */
+	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops i740fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= i740fb_open,
+	.fb_release	= i740fb_release,
+	.fb_check_var	= i740fb_check_var,
+	.fb_set_par	= i740fb_set_par,
+	.fb_setcolreg	= i740fb_setcolreg,
+	.fb_blank	= i740fb_blank,
+	.fb_pan_display	= i740fb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct i740fb_par *par;
+	int ret, tmp;
+	bool found = false;
+	u8 *edid;
+
+	info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
+	if (!info) {
+		dev_err(&(dev->dev), "cannot allocate framebuffer\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	mutex_init(&par->open_lock);
+
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->var.bits_per_pixel = 8;
+	info->fbops = &i740fb_ops;
+	info->pseudo_palette = par->pseudo_palette;
+
+	ret = pci_enable_device(dev);
+	if (ret) {
+		dev_err(info->device, "cannot enable PCI device\n");
+		goto err_enable_device;
+	}
+
+	ret = pci_request_regions(dev, info->fix.id);
+	if (ret) {
+		dev_err(info->device, "error requesting regions\n");
+		goto err_request_regions;
+	}
+
+	info->screen_base = pci_ioremap_bar(dev, 0);
+	if (!info->screen_base) {
+		dev_err(info->device, "error remapping base\n");
+		ret = -ENOMEM;
+		goto err_ioremap_1;
+	}
+
+	par->regs = pci_ioremap_bar(dev, 1);
+	if (!par->regs) {
+		dev_err(info->device, "error remapping MMIO\n");
+		ret = -ENOMEM;
+		goto err_ioremap_2;
+	}
+
+	/* detect memory size */
+	if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
+							== DRAM_ROW_1_SDRAM)
+		i740outb(par, XRX, DRAM_ROW_BNDRY_1);
+	else
+		i740outb(par, XRX, DRAM_ROW_BNDRY_0);
+	info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
+	/* detect memory type */
+	tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
+	par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
+			   (tmp & DRAM_RAS_PRECHARGE));
+
+	fb_info(info, "Intel740 on %s, %ld KB %s\n",
+		pci_name(dev), info->screen_size >> 10,
+		par->has_sgram ? "SGRAM" : "SDRAM");
+
+	info->fix = i740fb_fix;
+	info->fix.mmio_start = pci_resource_start(dev, 1);
+	info->fix.mmio_len = pci_resource_len(dev, 1);
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = info->screen_size;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	if (i740fb_setup_ddc_bus(info) == 0) {
+		par->ddc_registered = true;
+		edid = fb_ddc_read(&par->ddc_adapter);
+		if (edid) {
+			fb_edid_to_monspecs(edid, &info->monspecs);
+			kfree(edid);
+			if (!info->monspecs.modedb)
+				dev_err(info->device,
+					"error getting mode database\n");
+			else {
+				const struct fb_videomode *m;
+
+				fb_videomode_to_modelist(
+					info->monspecs.modedb,
+					info->monspecs.modedb_len,
+					&info->modelist);
+				m = fb_find_best_display(&info->monspecs,
+							 &info->modelist);
+				if (m) {
+					fb_videomode_to_var(&info->var, m);
+					/* fill all other info->var's fields */
+					if (!i740fb_check_var(&info->var, info))
+						found = true;
+				}
+			}
+		}
+	}
+
+	if (!mode_option && !found)
+		mode_option = "640x480-8@60";
+
+	if (mode_option) {
+		ret = fb_find_mode(&info->var, info, mode_option,
+				   info->monspecs.modedb,
+				   info->monspecs.modedb_len,
+				   NULL, info->var.bits_per_pixel);
+		if (!ret || ret == 4) {
+			dev_err(info->device, "mode %s not found\n",
+				mode_option);
+			ret = -EINVAL;
+		}
+	}
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	/* maximize virtual vertical size for fast scrolling */
+	info->var.yres_virtual = info->fix.smem_len * 8 /
+			(info->var.bits_per_pixel * info->var.xres_virtual);
+
+	if (ret == -EINVAL)
+		goto err_find_mode;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		dev_err(info->device, "cannot allocate colormap\n");
+		goto err_alloc_cmap;
+	}
+
+	ret = register_framebuffer(info);
+	if (ret) {
+		dev_err(info->device, "error registering framebuffer\n");
+		goto err_reg_framebuffer;
+	}
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	pci_set_drvdata(dev, info);
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		par->mtrr_reg = -1;
+		par->mtrr_reg = mtrr_add(info->fix.smem_start,
+				info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+	}
+#endif
+	return 0;
+
+err_reg_framebuffer:
+	fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+	if (par->ddc_registered)
+		i2c_del_adapter(&par->ddc_adapter);
+	pci_iounmap(dev, par->regs);
+err_ioremap_2:
+	pci_iounmap(dev, info->screen_base);
+err_ioremap_1:
+	pci_release_regions(dev);
+err_request_regions:
+/*	pci_disable_device(dev); */
+err_enable_device:
+	framebuffer_release(info);
+	return ret;
+}
+
+static void i740fb_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+
+	if (info) {
+		struct i740fb_par *par = info->par;
+
+#ifdef CONFIG_MTRR
+		if (par->mtrr_reg >= 0) {
+			mtrr_del(par->mtrr_reg, 0, 0);
+			par->mtrr_reg = -1;
+		}
+#endif
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		if (par->ddc_registered)
+			i2c_del_adapter(&par->ddc_adapter);
+		pci_iounmap(dev, par->regs);
+		pci_iounmap(dev, info->screen_base);
+		pci_release_regions(dev);
+/*		pci_disable_device(dev); */
+		framebuffer_release(info);
+	}
+}
+
+#ifdef CONFIG_PM
+static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct i740fb_par *par = info->par;
+
+	/* don't disable console during hibernation and wakeup from it */
+	if (state.event == PM_EVENT_FREEZE || state.event == PM_EVENT_PRETHAW)
+		return 0;
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	/* do nothing if framebuffer is not active */
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		console_unlock();
+		return 0;
+	}
+
+	fb_set_suspend(info, 1);
+
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
+
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+
+	return 0;
+}
+
+static int i740fb_resume(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct i740fb_par *par = info->par;
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	if (par->ref_count == 0)
+		goto fail;
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+	if (pci_enable_device(dev))
+		goto fail;
+
+	i740fb_set_par(info);
+	fb_set_suspend(info, 0);
+
+fail:
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+	return 0;
+}
+#else
+#define i740fb_suspend NULL
+#define i740fb_resume NULL
+#endif /* CONFIG_PM */
+
+#define I740_ID_PCI 0x00d1
+#define I740_ID_AGP 0x7800
+
+static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, i740fb_id_table);
+
+static struct pci_driver i740fb_driver = {
+	.name		= "i740fb",
+	.id_table	= i740fb_id_table,
+	.probe		= i740fb_probe,
+	.remove		= i740fb_remove,
+	.suspend	= i740fb_suspend,
+	.resume		= i740fb_resume,
+};
+
+#ifndef MODULE
+static int  __init i740fb_setup(char *options)
+{
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+#ifdef CONFIG_MTRR
+		else if (!strncmp(opt, "mtrr:", 5))
+			mtrr = simple_strtoul(opt + 5, NULL, 0);
+#endif
+		else
+			mode_option = opt;
+	}
+
+	return 0;
+}
+#endif
+
+static int __init i740fb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("i740fb", &option))
+		return -ENODEV;
+	i740fb_setup(option);
+#endif
+
+	return pci_register_driver(&i740fb_driver);
+}
+
+static void __exit i740fb_exit(void)
+{
+	pci_unregister_driver(&i740fb_driver);
+}
+
+module_init(i740fb_init);
+module_exit(i740fb_exit);
+
+MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for Intel740");
+
+module_param(mode_option, charp, 0444);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
diff --git a/drivers/video/fbdev/i810/Makefile b/drivers/video/fbdev/i810/Makefile
new file mode 100644
index 000000000000..96e08c8ded97
--- /dev/null
+++ b/drivers/video/fbdev/i810/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the Intel 810/815 framebuffer driver
+#
+
+obj-$(CONFIG_FB_I810)		+= i810fb.o
+
+i810fb-objs                     := i810_main.o i810_accel.o
+
+ifdef CONFIG_FB_I810_GTF
+i810fb-objs                     += i810_gtf.o
+else
+i810fb-objs                     += i810_dvt.o
+endif
+
+ifdef CONFIG_FB_I810_I2C
+i810fb-objs += i810-i2c.o
+endif
diff --git a/drivers/video/fbdev/i810/i810-i2c.c b/drivers/video/fbdev/i810/i810-i2c.c
new file mode 100644
index 000000000000..7db17d0d8a8c
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810-i2c.c
@@ -0,0 +1,175 @@
+ /*-*- linux-c -*-
+ *  linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support
+ *
+ *      Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+#include "i810.h"
+#include "i810_regs.h"
+#include "i810_main.h"
+#include "../edid.h"
+
+/* bit locations in the registers */
+#define SCL_DIR_MASK		0x0001
+#define SCL_DIR			0x0002
+#define SCL_VAL_MASK		0x0004
+#define SCL_VAL_OUT		0x0008
+#define SCL_VAL_IN		0x0010
+#define SDA_DIR_MASK		0x0100
+#define SDA_DIR			0x0200
+#define SDA_VAL_MASK		0x0400
+#define SDA_VAL_OUT		0x0800
+#define SDA_VAL_IN		0x1000
+
+#define DEBUG  /* define this for verbose EDID parsing output */
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(fmt,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static void i810i2c_setscl(void *data, int state)
+{
+        struct i810fb_i2c_chan    *chan = data;
+        struct i810fb_par         *par = chan->par;
+	u8                        __iomem *mmio = par->mmio_start_virtual;
+
+	if (state)
+		i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK);
+	else
+		i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
+	i810_readl(mmio, chan->ddc_base);	/* flush posted write */
+}
+
+static void i810i2c_setsda(void *data, int state)
+{
+        struct i810fb_i2c_chan    *chan = data;
+        struct i810fb_par         *par = chan->par;
+	u8                        __iomem *mmio = par->mmio_start_virtual;
+
+	if (state)
+		i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK);
+	else
+		i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
+	i810_readl(mmio, chan->ddc_base);	/* flush posted write */
+}
+
+static int i810i2c_getscl(void *data)
+{
+        struct i810fb_i2c_chan    *chan = data;
+        struct i810fb_par         *par = chan->par;
+	u8                        __iomem *mmio = par->mmio_start_virtual;
+
+	i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK);
+	i810_writel(mmio, chan->ddc_base, 0);
+	return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0);
+}
+
+static int i810i2c_getsda(void *data)
+{
+        struct i810fb_i2c_chan    *chan = data;
+        struct i810fb_par         *par = chan->par;
+	u8                        __iomem *mmio = par->mmio_start_virtual;
+
+	i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK);
+	i810_writel(mmio, chan->ddc_base, 0);
+	return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0);
+}
+
+static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
+{
+        int rc;
+
+        strcpy(chan->adapter.name, name);
+        chan->adapter.owner             = THIS_MODULE;
+        chan->adapter.algo_data         = &chan->algo;
+        chan->adapter.dev.parent        = &chan->par->dev->dev;
+	chan->algo.setsda               = i810i2c_setsda;
+	chan->algo.setscl               = i810i2c_setscl;
+	chan->algo.getsda               = i810i2c_getsda;
+	chan->algo.getscl               = i810i2c_getscl;
+	chan->algo.udelay               = 10;
+        chan->algo.timeout              = (HZ/2);
+        chan->algo.data                 = chan;
+
+        i2c_set_adapdata(&chan->adapter, chan);
+
+        /* Raise SCL and SDA */
+        chan->algo.setsda(chan, 1);
+        chan->algo.setscl(chan, 1);
+        udelay(20);
+
+        rc = i2c_bit_add_bus(&chan->adapter);
+
+        if (rc == 0)
+                dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name);
+        else {
+                dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
+			 "%s.\n", name);
+		chan->par = NULL;
+	}
+
+        return rc;
+}
+
+void i810_create_i2c_busses(struct i810fb_par *par)
+{
+        par->chan[0].par        = par;
+	par->chan[1].par        = par;
+	par->chan[2].par        = par;
+
+	par->chan[0].ddc_base = GPIOA;
+	i810_setup_i2c_bus(&par->chan[0], "I810-DDC");
+	par->chan[1].ddc_base = GPIOB;
+	i810_setup_i2c_bus(&par->chan[1], "I810-I2C");
+	par->chan[2].ddc_base = GPIOC;
+	i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC");
+}
+
+void i810_delete_i2c_busses(struct i810fb_par *par)
+{
+        if (par->chan[0].par)
+		i2c_del_adapter(&par->chan[0].adapter);
+        par->chan[0].par = NULL;
+
+	if (par->chan[1].par)
+		i2c_del_adapter(&par->chan[1].adapter);
+	par->chan[1].par = NULL;
+
+	if (par->chan[2].par)
+		i2c_del_adapter(&par->chan[2].adapter);
+	par->chan[2].par = NULL;
+}
+
+int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
+{
+	struct i810fb_par *par = info->par;
+        u8 *edid = NULL;
+
+	DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1);
+	if (conn < par->ddc_num) {
+		edid = fb_ddc_read(&par->chan[conn].adapter);
+	} else {
+		const u8 *e = fb_firmware_edid(info->device);
+
+		if (e != NULL) {
+			DPRINTK("i810-i2c: Getting EDID from BIOS\n");
+			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
+		}
+	}
+
+	*out_edid = edid;
+
+        return (edid) ? 0 : 1;
+}
diff --git a/drivers/video/fbdev/i810/i810.h b/drivers/video/fbdev/i810/i810.h
new file mode 100644
index 000000000000..1414b73ac55b
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810.h
@@ -0,0 +1,299 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/i810.h -- Intel 810 General Definitions/Declarations
+ *
+ *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved      
+ *
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef __I810_H__
+#define __I810_H__
+
+#include <linux/list.h>
+#include <linux/agp_backend.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <video/vga.h>
+
+/* Fence */
+#define TILEWALK_X            (0 << 12)
+#define TILEWALK_Y            (1 << 12)
+
+/* Raster ops */
+#define COLOR_COPY_ROP        0xF0
+#define PAT_COPY_ROP          0xCC
+#define CLEAR_ROP             0x00
+#define WHITE_ROP             0xFF
+#define INVERT_ROP            0x55
+#define XOR_ROP               0x5A
+
+/* 2D Engine definitions */
+#define SOLIDPATTERN          0x80000000
+#define NONSOLID              0x00000000
+#define BPP8                  (0 << 24)
+#define BPP16                 (1 << 24)
+#define BPP24                 (2 << 24)
+
+#define PIXCONF8              (2 << 16)
+#define PIXCONF15             (4 << 16)
+#define PIXCONF16             (5 << 16)
+#define PIXCONF24             (6 << 16)
+#define PIXCONF32             (7 << 16)
+
+#define DYN_COLOR_EN          (1 << 26)
+#define DYN_COLOR_DIS         (0 << 26)
+#define INCREMENT             0x00000000
+#define DECREMENT             (0x01 << 30)
+#define ARB_ON                0x00000001
+#define ARB_OFF               0x00000000
+#define SYNC_FLIP             0x00000000
+#define ASYNC_FLIP            0x00000040
+#define OPTYPE_MASK           0xE0000000
+#define PARSER_MASK           0x001F8000 
+#define D2_MASK               0x001FC000         /* 2D mask */
+
+/* Instruction type */
+/* There are more but pertains to 3D */
+#define PARSER                0x00000000
+#define BLIT                  (0x02 << 29)
+#define RENDER                (0x03 << 29)
+            
+/* Parser */
+#define NOP                   0x00               /* No operation, padding */
+#define BP_INT                (0x01 << 23)         /* Breakpoint interrupt */
+#define USR_INT               (0x02 << 23)         /* User interrupt */
+#define WAIT_FOR_EVNT         (0x03 << 23)         /* Wait for event */
+#define FLUSH                 (0x04 << 23)              
+#define CONTEXT_SEL           (0x05 << 23)
+#define REPORT_HEAD           (0x07 << 23)
+#define ARB_ON_OFF            (0x08 << 23)
+#define OVERLAY_FLIP          (0x11 << 23)
+#define LOAD_SCAN_INC         (0x12 << 23)
+#define LOAD_SCAN_EX          (0x13 << 23)
+#define FRONT_BUFFER          (0x14 << 23)
+#define DEST_BUFFER           (0x15 << 23)
+#define Z_BUFFER              (0x16 << 23)       
+
+#define STORE_DWORD_IMM       (0x20 << 23)
+#define STORE_DWORD_IDX       (0x21 << 23)
+#define BATCH_BUFFER          (0x30 << 23)
+
+/* Blit */
+#define SETUP_BLIT                      0x00
+#define SETUP_MONO_PATTERN_SL_BLT       (0x10 << 22)
+#define PIXEL_BLT                       (0x20 << 22)
+#define SCANLINE_BLT                    (0x21 << 22)
+#define TEXT_BLT                        (0x22 << 22)
+#define TEXT_IMM_BLT                    (0x30 << 22)
+#define COLOR_BLT                       (0x40 << 22)
+#define MONO_PAT_BLIT                   (0x42 << 22)
+#define SOURCE_COPY_BLIT                (0x43 << 22)
+#define MONO_SOURCE_COPY_BLIT           (0x44 << 22)
+#define SOURCE_COPY_IMMEDIATE           (0x60 << 22)
+#define MONO_SOURCE_COPY_IMMEDIATE      (0x61 << 22)
+
+#define VERSION_MAJOR            0
+#define VERSION_MINOR            9
+#define VERSION_TEENIE           0
+#define BRANCH_VERSION           ""
+
+
+/* mvo: intel i815 */
+#ifndef PCI_DEVICE_ID_INTEL_82815_100
+  #define PCI_DEVICE_ID_INTEL_82815_100           0x1102
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_82815_NOAGP
+  #define PCI_DEVICE_ID_INTEL_82815_NOAGP         0x1112
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_82815_FULL_CTRL
+  #define PCI_DEVICE_ID_INTEL_82815_FULL_CTRL     0x1130
+#endif 
+
+/* General Defines */
+#define I810_PAGESIZE               4096
+#define MAX_DMA_SIZE                (1024 * 4096)
+#define SAREA_SIZE                  4096
+#define PCI_I810_MISCC              0x72
+#define MMIO_SIZE                   (512*1024)
+#define GTT_SIZE                    (16*1024) 
+#define RINGBUFFER_SIZE             (64*1024)
+#define CURSOR_SIZE                 4096 
+#define OFF                         0
+#define ON                          1
+#define MAX_KEY                     256
+#define WAIT_COUNT                  10000000
+#define IRING_PAD                   8
+#define FONTDATAMAX                 8192
+/* Masks (AND ops) and OR's */
+#define FB_START_MASK               (0x3f << (32 - 6))
+#define MMIO_ADDR_MASK              (0x1FFF << (32 - 13))
+#define FREQ_MASK                   (1 << 4)
+#define SCR_OFF                     0x20
+#define DRAM_ON                     0x08            
+#define DRAM_OFF                    0xE7
+#define PG_ENABLE_MASK              0x01
+#define RING_SIZE_MASK              (RINGBUFFER_SIZE - 1)
+
+/* defines for restoring registers partially */
+#define ADDR_MAP_MASK               (0x07 << 5)
+#define DISP_CTRL                   ~0
+#define PIXCONF_0                   (0x64 << 8)
+#define PIXCONF_2                   (0xF3 << 24)
+#define PIXCONF_1                   (0xF0 << 16)
+#define MN_MASK                     0x3FF03FF
+#define P_OR                        (0x7 << 4)                    
+#define DAC_BIT                     (1 << 16)
+#define INTERLACE_BIT               (1 << 7)
+#define IER_MASK                    (3 << 13)
+#define IMR_MASK                    (3 << 13)
+
+/* Power Management */
+#define DPMS_MASK                   0xF0000
+#define POWERON                     0x00000
+#define STANDBY                     0x20000
+#define SUSPEND                     0x80000
+#define POWERDOWN                   0xA0000
+#define EMR_MASK                    ~0x3F
+#define FW_BLC_MASK                 ~(0x3F|(7 << 8)|(0x3F << 12)|(7 << 20))
+
+/* Ringbuffer */
+#define RBUFFER_START_MASK          0xFFFFF000
+#define RBUFFER_SIZE_MASK           0x001FF000
+#define RBUFFER_HEAD_MASK           0x001FFFFC
+#define RBUFFER_TAIL_MASK           0x001FFFF8
+
+/* Video Timings */
+#define REF_FREQ                    24000000
+#define TARGET_N_MAX                30
+
+#define MAX_PIXELCLOCK              230000000
+#define MIN_PIXELCLOCK               15000000
+#define VFMAX                       60
+#define VFMIN                       60
+#define HFMAX                       30000
+#define HFMIN                       29000
+
+/* Cursor */
+#define CURSOR_ENABLE_MASK          0x1000             
+#define CURSOR_MODE_64_TRANS        4
+#define CURSOR_MODE_64_XOR	    5
+#define CURSOR_MODE_64_3C	    6	
+#define COORD_INACTIVE              0
+#define COORD_ACTIVE                (1 << 4)
+#define EXTENDED_PALETTE	    1
+  
+/* AGP Memory Types*/
+#define AGP_NORMAL_MEMORY           0
+#define AGP_DCACHE_MEMORY	    1
+#define AGP_PHYSICAL_MEMORY         2
+
+/* Allocated resource Flags */
+#define FRAMEBUFFER_REQ             1
+#define MMIO_REQ                    2
+#define PCI_DEVICE_ENABLED          4
+#define HAS_FONTCACHE               8 
+
+/* driver flags */
+#define HAS_MTRR                    1
+#define HAS_ACCELERATION            2
+#define ALWAYS_SYNC                 4
+#define LOCKUP                      8
+
+struct gtt_data {
+	struct agp_memory *i810_fb_memory;
+	struct agp_memory *i810_cursor_memory;
+};
+
+struct mode_registers {
+	u32 pixclock, M, N, P;
+	u8 cr00, cr01, cr02, cr03;
+	u8 cr04, cr05, cr06, cr07;
+	u8 cr09, cr10, cr11, cr12;
+	u8 cr13, cr15, cr16, cr30;
+	u8 cr31, cr32, cr33, cr35, cr39;
+	u32 bpp8_100, bpp16_100;
+	u32 bpp24_100, bpp8_133;
+	u32 bpp16_133, bpp24_133;
+	u8 msr;
+};
+
+struct heap_data {
+        unsigned long physical;
+	__u8 __iomem *virtual;
+	u32 offset;
+	u32 size;
+};	
+
+struct state_registers {
+	u32 dclk_1d, dclk_2d, dclk_0ds;
+	u32 pixconf, fw_blc, pgtbl_ctl;
+	u32 fence0, hws_pga, dplystas;
+	u16 bltcntl, hwstam, ier, iir, imr;
+	u8 cr00, cr01, cr02, cr03, cr04;
+	u8 cr05, cr06, cr07, cr08, cr09;
+	u8 cr10, cr11, cr12, cr13, cr14;
+	u8 cr15, cr16, cr17, cr80, gr10;
+	u8 cr30, cr31, cr32, cr33, cr35;
+	u8 cr39, cr41, cr70, sr01, msr;
+};
+
+struct i810fb_par;
+
+struct i810fb_i2c_chan {
+	struct i810fb_par *par;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+	unsigned long ddc_base;
+};
+
+struct i810fb_par {
+	struct mode_registers    regs;
+	struct state_registers   hw_state;
+	struct gtt_data          i810_gtt;
+	struct fb_ops            i810fb_ops;
+	struct pci_dev           *dev;
+	struct heap_data         aperture;
+	struct heap_data         fb;
+	struct heap_data         iring;
+	struct heap_data         cursor_heap;
+	struct vgastate          state;
+	struct i810fb_i2c_chan   chan[3];
+	struct mutex		 open_lock;
+	unsigned int		 use_count;
+	u32 pseudo_palette[16];
+	unsigned long mmio_start_phys;
+	u8 __iomem *mmio_start_virtual;
+	u8 *edid;
+	u32 pitch;
+	u32 pixconf;
+	u32 watermark;
+	u32 mem_freq;
+	u32 res_flags;
+	u32 dev_flags;
+	u32 cur_tail;
+	u32 depth;
+	u32 blit_bpp;
+	u32 ovract;
+	u32 cur_state;
+	u32 ddc_num;
+	int mtrr_reg;
+	u16 bltcntl;
+	u8 interlace;
+};
+
+/* 
+ * Register I/O
+ */
+#define i810_readb(where, mmio) readb(mmio + where)
+#define i810_readw(where, mmio) readw(mmio + where)
+#define i810_readl(where, mmio) readl(mmio + where)
+#define i810_writeb(where, mmio, val) writeb(val, mmio + where) 
+#define i810_writew(where, mmio, val) writew(val, mmio + where)
+#define i810_writel(where, mmio, val) writel(val, mmio + where)
+
+#endif /* __I810_H__ */
diff --git a/drivers/video/fbdev/i810/i810_accel.c b/drivers/video/fbdev/i810/i810_accel.c
new file mode 100644
index 000000000000..7672d2ea9b35
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810_accel.c
@@ -0,0 +1,456 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/i810_accel.c -- Hardware Acceleration
+ *
+ *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved      
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+#include "i810_main.h"
+
+static u32 i810fb_rop[] = {
+	COLOR_COPY_ROP, /* ROP_COPY */
+	XOR_ROP         /* ROP_XOR  */
+};
+
+/* Macros */
+#define PUT_RING(n) {                                        \
+	i810_writel(par->cur_tail, par->iring.virtual, n);   \
+        par->cur_tail += 4;                                  \
+        par->cur_tail &= RING_SIZE_MASK;                     \
+}                                                                      
+
+extern void flush_cache(void);
+
+/************************************************************/
+
+/* BLT Engine Routines */
+static inline void i810_report_error(u8 __iomem *mmio)
+{
+	printk("IIR     : 0x%04x\n"
+	       "EIR     : 0x%04x\n"
+	       "PGTBL_ER: 0x%04x\n"
+	       "IPEIR   : 0x%04x\n"
+	       "IPEHR   : 0x%04x\n",
+	       i810_readw(IIR, mmio),
+	       i810_readb(EIR, mmio),
+	       i810_readl(PGTBL_ER, mmio),
+	       i810_readl(IPEIR, mmio), 
+	       i810_readl(IPEHR, mmio));
+}
+
+/**
+ * wait_for_space - check ring buffer free space
+ * @space: amount of ringbuffer space needed in bytes
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * The function waits until a free space from the ringbuffer
+ * is available 
+ */	
+static inline int wait_for_space(struct fb_info *info, u32 space)
+{
+	struct i810fb_par *par = info->par;
+	u32 head, count = WAIT_COUNT, tail;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	tail = par->cur_tail;
+	while (count--) {
+		head = i810_readl(IRING + 4, mmio) & RBUFFER_HEAD_MASK;	
+		if ((tail == head) || 
+		    (tail > head && 
+		     (par->iring.size - tail + head) >= space) || 
+		    (tail < head && (head - tail) >= space)) {
+			return 0;	
+		}
+	}
+	printk("ringbuffer lockup!!!\n");
+	i810_report_error(mmio); 
+	par->dev_flags |= LOCKUP;
+	info->pixmap.scan_align = 1;
+	return 1;
+}
+
+/** 
+ * wait_for_engine_idle - waits for all hardware engines to finish
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * This waits for lring(0), iring(1), and batch(3), etc to finish and
+ * waits until ringbuffer is empty.
+ */
+static inline int wait_for_engine_idle(struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	int count = WAIT_COUNT;
+
+	if (wait_for_space(info, par->iring.size)) /* flush */
+		return 1;
+
+	while((i810_readw(INSTDONE, mmio) & 0x7B) != 0x7B && --count); 
+	if (count) return 0;
+
+	printk("accel engine lockup!!!\n");
+	printk("INSTDONE: 0x%04x\n", i810_readl(INSTDONE, mmio));
+	i810_report_error(mmio); 
+	par->dev_flags |= LOCKUP;
+	info->pixmap.scan_align = 1;
+	return 1;
+}
+
+/* begin_iring - prepares the ringbuffer 
+ * @space: length of sequence in dwords
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Checks/waits for sufficient space in ringbuffer of size
+ * space.  Returns the tail of the buffer
+ */ 
+static inline u32 begin_iring(struct fb_info *info, u32 space)
+{
+	struct i810fb_par *par = info->par;
+
+	if (par->dev_flags & ALWAYS_SYNC) 
+		wait_for_engine_idle(info);
+	return wait_for_space(info, space);
+}
+
+/**
+ * end_iring - advances the buffer
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * This advances the tail of the ringbuffer, effectively
+ * beginning the execution of the graphics instruction sequence.
+ */
+static inline void end_iring(struct i810fb_par *par)
+{
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	i810_writel(IRING, mmio, par->cur_tail);
+}
+
+/**
+ * source_copy_blit - BLIT transfer operation
+ * @dwidth: width of rectangular graphics data
+ * @dheight: height of rectangular graphics data
+ * @dpitch: bytes per line of destination buffer
+ * @xdir: direction of copy (left to right or right to left)
+ * @src: address of first pixel to read from
+ * @dest: address of first pixel to write to
+ * @from: source address
+ * @where: destination address
+ * @rop: raster operation
+ * @blit_bpp: pixel format which can be different from the 
+ *            framebuffer's pixelformat
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * This is a BLIT operation typically used when doing
+ * a 'Copy and Paste'
+ */
+static inline void source_copy_blit(int dwidth, int dheight, int dpitch, 
+				    int xdir, int src, int dest, int rop, 
+				    int blit_bpp, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+
+	if (begin_iring(info, 24 + IRING_PAD)) return;
+
+	PUT_RING(BLIT | SOURCE_COPY_BLIT | 4);
+	PUT_RING(xdir | rop << 16 | dpitch | DYN_COLOR_EN | blit_bpp);
+	PUT_RING(dheight << 16 | dwidth);
+	PUT_RING(dest);
+	PUT_RING(dpitch);
+	PUT_RING(src);
+
+	end_iring(par);
+}	
+
+/**
+ * color_blit - solid color BLIT operation
+ * @width: width of destination
+ * @height: height of destination
+ * @pitch: pixels per line of the buffer
+ * @dest: address of first pixel to write to
+ * @where: destination
+ * @rop: raster operation
+ * @what: color to transfer
+ * @blit_bpp: pixel format which can be different from the 
+ *            framebuffer's pixelformat
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * A BLIT operation which can be used for  color fill/rectangular fill
+ */
+static inline void color_blit(int width, int height, int pitch,  int dest, 
+			      int rop, int what, int blit_bpp, 
+			      struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+
+	if (begin_iring(info, 24 + IRING_PAD)) return;
+
+	PUT_RING(BLIT | COLOR_BLT | 3);
+	PUT_RING(rop << 16 | pitch | SOLIDPATTERN | DYN_COLOR_EN | blit_bpp);
+	PUT_RING(height << 16 | width);
+	PUT_RING(dest);
+	PUT_RING(what);
+	PUT_RING(NOP);
+
+	end_iring(par);
+}
+ 
+/**
+ * mono_src_copy_imm_blit - color expand from system memory to framebuffer
+ * @dwidth: width of destination
+ * @dheight: height of destination
+ * @dpitch: pixels per line of the buffer
+ * @dsize: size of bitmap in double words
+ * @dest: address of first byte of pixel;
+ * @rop: raster operation
+ * @blit_bpp: pixelformat to use which can be different from the 
+ *            framebuffer's pixelformat
+ * @src: address of image data
+ * @bg: backgound color
+ * @fg: forground color
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * A color expand operation where the  source data is placed in the 
+ * ringbuffer itself. Useful for drawing text. 
+ *
+ * REQUIREMENT:
+ * The end of a scanline must be padded to the next word.
+ */
+static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
+					  int dsize, int blit_bpp, int rop,
+					  int dest, const u32 *src, int bg,
+					  int fg, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+
+	if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
+
+	PUT_RING(BLIT | MONO_SOURCE_COPY_IMMEDIATE | (4 + dsize));
+	PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch);
+	PUT_RING(dheight << 16 | dwidth);
+	PUT_RING(dest);
+	PUT_RING(bg);
+	PUT_RING(fg);
+	while (dsize--) 
+		PUT_RING(*src++);
+
+	end_iring(par);
+}
+
+static inline void load_front(int offset, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+
+	if (begin_iring(info, 8 + IRING_PAD)) return;
+
+	PUT_RING(PARSER | FLUSH);
+	PUT_RING(NOP);
+
+	end_iring(par);
+
+	if (begin_iring(info, 8 + IRING_PAD)) return;
+
+	PUT_RING(PARSER | FRONT_BUFFER | ((par->pitch >> 3) << 8));
+	PUT_RING((par->fb.offset << 12) + offset);
+
+	end_iring(par);
+}
+
+/**
+ * i810fb_iring_enable - enables/disables the ringbuffer
+ * @mode: enable or disable
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Enables or disables the ringbuffer, effectively enabling or
+ * disabling the instruction/acceleration engine.
+ */
+static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
+{
+	u32 tmp;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	tmp = i810_readl(IRING + 12, mmio);
+	if (mode == OFF) 
+		tmp &= ~1;
+	else 
+		tmp |= 1;
+	flush_cache();
+	i810_writel(IRING + 12, mmio, tmp);
+}       
+
+void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct i810fb_par *par = info->par;
+	u32 dx, dy, width, height, dest, rop = 0, color = 0;
+
+	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
+	    par->depth == 4) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if (par->depth == 1) 
+		color = rect->color;
+	else 
+		color = ((u32 *) (info->pseudo_palette))[rect->color];
+
+	rop = i810fb_rop[rect->rop];
+
+	dx = rect->dx * par->depth;
+	width = rect->width * par->depth;
+	dy = rect->dy;
+	height = rect->height;
+
+	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
+	color_blit(width, height, info->fix.line_length, dest, rop, color, 
+		   par->blit_bpp, info);
+}
+	
+void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) 
+{
+	struct i810fb_par *par = info->par;
+	u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
+
+	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
+	    par->depth == 4) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
+	dx = region->dx * par->depth;
+	sx = region->sx * par->depth;
+	width = region->width * par->depth;
+	sy = region->sy;
+	dy = region->dy;
+	height = region->height;
+
+	if (dx <= sx) {
+		xdir = INCREMENT;
+	}
+	else {
+		xdir = DECREMENT;
+		sx += width - 1;
+		dx += width - 1;
+	}
+	if (dy <= sy) {
+		pitch = info->fix.line_length;
+	}
+	else {
+		pitch = (-(info->fix.line_length)) & 0xFFFF;
+		sy += height - 1;
+		dy += height - 1;
+	}
+	src = info->fix.smem_start + (sy * info->fix.line_length) + sx;
+	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
+
+	source_copy_blit(width, height, pitch, xdir, src, dest,
+			 PAT_COPY_ROP, par->blit_bpp, info);
+}
+
+void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct i810fb_par *par = info->par;
+	u32 fg = 0, bg = 0, size, dst;
+	
+	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
+	    par->depth == 4 || image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		fg = image->fg_color;
+		bg = image->bg_color;
+		break;
+	case 16:
+	case 24:
+		fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
+		bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
+		break;
+	}	
+	
+	dst = info->fix.smem_start + (image->dy * info->fix.line_length) + 
+		(image->dx * par->depth);
+
+	size = (image->width+7)/8 + 1;
+	size &= ~1;
+	size *= image->height;
+	size += 7;
+	size &= ~7;
+	mono_src_copy_imm_blit(image->width * par->depth, 
+			       image->height, info->fix.line_length, 
+			       size/4, par->blit_bpp,
+			       PAT_COPY_ROP, dst, (u32 *) image->data, 
+			       bg, fg, info);
+} 
+
+int i810fb_sync(struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	
+	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
+		return 0;
+
+	return wait_for_engine_idle(info);
+}
+
+void i810fb_load_front(u32 offset, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
+		i810_writel(DPLYBASE, mmio, par->fb.physical + offset);
+	else 
+		load_front(offset, info);
+}
+
+/**
+ * i810fb_init_ringbuffer - initialize the ringbuffer
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Initializes the ringbuffer by telling the device the
+ * size and location of the ringbuffer.  It also sets 
+ * the head and tail pointers = 0
+ */
+void i810fb_init_ringbuffer(struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u32 tmp1, tmp2;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	
+	wait_for_engine_idle(info);
+	i810fb_iring_enable(par, OFF);
+	i810_writel(IRING, mmio, 0);
+	i810_writel(IRING + 4, mmio, 0);
+	par->cur_tail = 0;
+
+	tmp2 = i810_readl(IRING + 8, mmio) & ~RBUFFER_START_MASK; 
+	tmp1 = par->iring.physical;
+	i810_writel(IRING + 8, mmio, tmp2 | tmp1);
+
+	tmp1 = i810_readl(IRING + 12, mmio);
+	tmp1 &= ~RBUFFER_SIZE_MASK;
+	tmp2 = (par->iring.size - I810_PAGESIZE) & RBUFFER_SIZE_MASK;
+	i810_writel(IRING + 12, mmio, tmp1 | tmp2);
+	i810fb_iring_enable(par, ON);
+}
diff --git a/drivers/video/fbdev/i810/i810_dvt.c b/drivers/video/fbdev/i810/i810_dvt.c
new file mode 100644
index 000000000000..b4b3670667ab
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810_dvt.c
@@ -0,0 +1,312 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/i810_dvt.c -- Intel 810 Discrete Video Timings (Intel)
+ *
+ *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved      
+ *
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/kernel.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+
+struct mode_registers std_modes[] = {
+	/* 640x480 @ 60Hz */
+	{ 25000, 0x0013, 0x0003, 0x40, 0x5F, 0x4F, 0x50, 0x82, 0x51, 0x9D,
+	  0x0B, 0x10, 0x40, 0xE9, 0x0B, 0xDF, 0x50, 0xE7, 0x04, 0x02,
+	  0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22006000,
+	  0x22002000, 0x22004000, 0x22006000, 0xC0 }, 
+	  
+	/* 640x480 @ 70Hz */
+	{ 28000, 0x0053, 0x0010, 0x40, 0x61, 0x4F, 0x4F, 0x85, 0x52, 0x9A,
+	  0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01, 
+	  0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22005000,
+          0x22002000, 0x22004000, 0x22005000, 0xC0 },
+          
+        /* 640x480 @ 72Hz */
+        { 31000, 0x0013, 0x0002, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x52, 0x97,
+          0x06, 0x0F, 0x40, 0xE8, 0x0B, 0xDF, 0x50, 0xDF, 0x07, 0x02, 
+          0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000,
+          0x22003000, 0x22005000, 0x22007000, 0xC0 },
+          
+        /* 640x480 @ 75Hz */
+        { 31000, 0x0013, 0x0002, 0x40, 0x64, 0x4F, 0x4F, 0x88, 0x51, 0x99, 
+          0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01, 
+          0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000, 
+          0x22003000, 0x22005000, 0x22007000, 0xC0 },
+          
+        /* 640x480 @ 85Hz */
+        { 36000, 0x0010, 0x0001, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x56, 0x9D,
+          0xFB, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xFC, 0x01,
+          0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
+          0x22003000, 0x22005000, 0x22107000, 0xC0 },
+          
+        /* 800x600 @ 56Hz */
+        { 36000, 0x0010, 0x0001, 0x40, 0x7B, 0x63, 0x63, 0x9F, 0x66, 0x8F,
+          0x6F, 0x10, 0x40, 0x58, 0x0A, 0x57, 0xC8, 0x57, 0x70, 0x02, 
+          0x02, 0x02, 0x02, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
+          0x22003000, 0x22005000, 0x22107000, 0x00 },
+          
+        /* 800x600 @ 60Hz */
+        { 40000, 0x0008, 0x0001, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x68, 0x18, 
+          0x72, 0x10, 0x40, 0x58, 0x0C, 0x57, 0xC8, 0x57, 0x73, 0x02,
+          0x02, 0x02, 0x02, 0x00, 0x00, 0x22003000, 0x22006000, 0x22108000,
+          0x22003000, 0x22006000, 0x22108000, 0x00 },
+          
+        /* 800x600 @ 70Hz */
+        { 45000, 0x0054, 0x0015, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x68, 0x12,
+          0x6f, 0x10, 0x40, 0x58, 0x0b, 0x57, 0x64, 0x57, 0x70, 0x02, 
+          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000, 
+          0x22004000, 0x22007000, 0x2210A000, 0x00 },
+          
+        /* 800x600 @ 72Hz */
+        { 50000, 0x0017, 0x0004, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x6A, 0x19,
+          0x98, 0x10, 0x40, 0x7C, 0x02, 0x57, 0xC8, 0x57, 0x99, 0x02, 
+          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000,
+          0x22004000, 0x22007000, 0x2210A000, 0x00 }, 
+          
+        /* 800x600 @ 75Hz */
+        { 49000, 0x001F, 0x0006, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x65, 0x0F,
+          0x6F, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x70, 0x02, 
+          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210B000,
+          0x22004000, 0x22007000, 0x2210B000, 0x00 },
+          
+        /* 800x600 @ 85Hz */
+        { 56000, 0x0049, 0x000E, 0x30, 0x7E, 0x63, 0x63, 0x82, 0x67, 0x0F,
+          0x75, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x76, 0x02,
+          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22108000, 0x2210b000, 
+          0x22004000, 0x22108000, 0x2210b000, 0x00 },
+          
+        /* 1024x768 @ 60Hz */
+        { 65000, 0x003F, 0x000A, 0x30, 0xA3, 0x7F, 0x7F, 0x87, 0x83, 0x94,
+          0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
+          0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x22109000, 0x2220D000,
+          0x22005000, 0x22109000, 0x2220D000, 0xC0 },
+          
+        /* 1024x768 @ 70Hz */
+	{ 75000, 0x0017, 0x0002, 0x30, 0xA1, 0x7F, 0x7F, 0x85, 0x82, 0x93,
+	  0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
+	  0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x2210A000, 0x2220F000,
+	  0x22005000, 0x2210A000, 0x2220F000, 0xC0 }, 
+	  
+	/* 1024x768 @ 75Hz */          
+	{ 78000, 0x0050, 0x0017, 0x20, 0x9F, 0x7F, 0x7F, 0x83, 0x81, 0x8D,
+	  0x1E, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x1F, 0x03,
+	  0x02, 0x03, 0x02, 0x00, 0x00, 0x22006000, 0x2210B000, 0x22210000,
+	  0x22006000, 0x2210B000, 0x22210000, 0x00 },
+	  
+	/* 1024x768 @ 85Hz */
+	{ 94000, 0x003D, 0x000E, 0x20, 0xA7, 0x7F, 0x7F, 0x8B, 0x85, 0x91,
+	  0x26, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x27, 0x03,
+	  0x02, 0x03, 0x02, 0x00, 0x00, 0x22007000, 0x2220E000, 0x22212000,
+	  0x22007000, 0x2220E000, 0x22212000, 0x00 },
+	  
+	/* 1152x864 @ 60Hz */ 
+	{ 80000, 0x0008, 0x0001, 0x20, 0xB3, 0x8F, 0x8F, 0x97, 0x93, 0x9f,
+	  0x87, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5f, 0x88, 0x03,
+	  0x03, 0x03, 0x03, 0x00, 0x00, 0x2220C000, 0x22210000, 0x22415000,   
+	  0x2220C000, 0x22210000, 0x22415000, 0x00 },
+	  
+	/* 1152x864 @ 70Hz */
+	{ 96000, 0x000a, 0x0001, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87, 
+	  0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03,
+	  0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
+	  0x22107000, 0x22210000, 0x22415000, 0x00 },
+	  
+	/* 1152x864 @ 72Hz */
+	{ 99000, 0x001f, 0x0006, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87,
+	  0x83, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x84, 0x03,
+	  0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
+	  0x22107000, 0x22210000, 0x22415000, 0x00 },
+	  
+	/* 1152x864 @ 75Hz */
+	{ 108000, 0x0010, 0x0002, 0x20, 0xC3, 0x8F, 0x8F, 0x87, 0x97, 0x07,
+	  0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03, 
+	  0x03, 0x03, 0x03, 0x00, 0x01, 0x22107000, 0x22210000, 0x22415000,
+	  0x22107000, 0x22210000, 0x22415000, 0x00 },
+	  
+	/* 1152x864 @ 85Hz */
+	{ 121000, 0x006D, 0x0014, 0x20, 0xc0, 0x8F, 0x8F, 0x84, 0x97, 0x07,
+	  0x93, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x94, 0x03, 
+	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2220C000, 0x22210000, 0x22415000,
+	  0x2220C000, 0x22210000, 0x22415000, 0x0 },
+	  
+	/* 1280x960 @ 60Hz */
+	{ 108000, 0x0010, 0x0002, 0x20, 0xDC, 0x9F, 0x9F, 0x80, 0xAB, 0x99,
+	  0xE6, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE7, 0x03,
+	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x22415000,
+	  0x2210A000, 0x22210000, 0x22415000, 0x00 },
+	  
+	/* 1280x960 @ 75Hz */
+	{ 129000, 0x0029, 0x0006, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xaa, 0x1b,
+	  0xE8, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE9, 0x03,
+	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x2241B000,
+	  0x2210A000, 0x22210000, 0x2241B000, 0x00 },
+	  
+	/* 1280x960 @ 85Hz */
+	{ 148000, 0x0042, 0x0009, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xA7, 0x1B,
+	  0xF1, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xF2, 0x03,
+	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22220000, 0x2241D000,       
+	  0x2210A000, 0x22220000, 0x2241D000, 0x00 },
+	  
+	/* 1600x1200 @ 60Hz */
+	{ 162000, 0x0019, 0x0006, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
+	  0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04, 
+	  0x04, 0x04, 0x04, 0x01, 0x00, 0x2210b000, 0x22416000, 0x44419000,
+	  0x2210b000, 0x22416000, 0x44419000, 0x00 },
+	  
+	/* 1600x1200 @ 65 Hz */
+	{ 175000, 0x005d, 0x0018, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
+	  0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04, 
+	  0x04, 0x04, 0x04, 0x01, 0x00, 0x2210c000, 0x22416000, 0x44419000,
+	  0x2210c000, 0x22416000, 0x44419000, 0x00 },
+	  
+	/* 1600x1200 @ 70 Hz */
+	{ 189000, 0x003D, 0x000e, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
+	  0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 
+	  0x04, 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
+	  0x2220e000, 0x22416000, 0x44419000, 0x00 },
+	  
+ 	/* 1600x1200 @ 72 Hz */
+ 	{ 195000, 0x003f, 0x000e, 0x10, 0x0b, 0xC7, 0xC7, 0x8f, 0xd5, 0x0b,
+ 	  0xE1, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xe2, 0x04, 0x04,
+ 	  0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
+ 	  0x2220e000, 0x22416000, 0x44419000, 0x00 }, 
+ 	  
+ 	/* 1600x1200 @ 75 Hz */
+ 	{ 202000, 0x0024, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
+ 	  0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
+ 	  0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,      
+ 	  0x2220e000, 0x22416000, 0x44419000,  0x00 },
+ 	  
+ 	/* 1600x1200 @ 85 Hz */
+	{ 229000, 0x0029, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
+	  0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
+	  0x04, 0x04, 0x01, 0x00, 0x22210000, 0x22416000, 0x0,
+	  0x22210000, 0x22416000, 0x0, 0x00 },
+};	 
+
+void round_off_xres(u32 *xres) 
+{
+	if (*xres <= 640)
+		*xres = 640;
+	else if (*xres <= 800)
+		*xres = 800;
+	else if (*xres <= 1024)
+		*xres = 1024;
+	else if (*xres <= 1152)
+		*xres = 1152;
+	else if (*xres <= 1280)
+		*xres = 1280;
+	else
+		*xres = 1600;
+}
+
+inline void round_off_yres(u32 *xres, u32 *yres)
+{
+	*yres = (*xres * 3) >> 2;
+}
+
+static int i810fb_find_best_mode(u32 xres, u32 yres, u32 pixclock)
+{ 
+	u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0; 
+	u8 hfl = (u8) ((xres >> 3) - 1);
+
+	for (i = 0; i < ARRAY_SIZE(std_modes); i++) { 
+		if (std_modes[i].cr01 == hfl) { 
+			if (std_modes[i].pixclock <= pixclock)
+				diff = pixclock - std_modes[i].pixclock;
+			if (diff < diff_best) {	 
+		    		i_best = i;
+		    		diff_best = diff;
+			}
+		}
+	}
+	return i_best;
+}
+
+void i810fb_encode_registers(const struct fb_var_screeninfo *var,
+			     struct i810fb_par *par, u32 xres, u32 yres)
+{
+	u32 i_best = i810fb_find_best_mode(xres, yres, par->regs.pixclock);
+
+	par->regs = std_modes[i_best];
+
+	/* overlay */
+	par->ovract = ((xres + var->right_margin + var->hsync_len + 
+			var->left_margin - 32) | ((xres - 32) << 16));
+}
+
+void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
+{
+	u32 total, xres, yres;
+	u32 mode, pixclock;
+
+	xres = var->xres;
+	yres = var->yres;
+	
+	pixclock = 1000000000 / var->pixclock;
+	mode = i810fb_find_best_mode(xres, yres, pixclock);
+	
+	total = (std_modes[mode].cr00 | (std_modes[mode].cr35 & 1) << 8) + 3;
+	total <<= 3;
+	
+	var->pixclock = 1000000000 / std_modes[mode].pixclock;
+	var->right_margin = (std_modes[mode].cr04 << 3) - xres;
+	var->hsync_len = ((std_modes[mode].cr05 & 0x1F) -
+			 (std_modes[mode].cr04 & 0x1F)) << 3;
+	var->left_margin = (total - (xres + var->right_margin + 
+				     var->hsync_len));
+	var->sync = FB_SYNC_ON_GREEN;
+	if (~(std_modes[mode].msr & (1 << 6)))
+		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (~(std_modes[mode].msr & (1 << 7)))
+		var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+	total = (std_modes[mode].cr06 | (std_modes[mode].cr30 & 0xF)  << 8) + 2;
+	var->lower_margin = (std_modes[mode].cr10 |
+			    (std_modes[mode].cr32 & 0x0F) << 8) - yres;
+	var->vsync_len = (std_modes[mode].cr11 & 0x0F) -
+			 (var->lower_margin & 0x0F);
+	var->upper_margin = total - (yres + var->lower_margin + var->vsync_len);
+}
+
+u32 i810_get_watermark(struct fb_var_screeninfo *var,
+		       struct i810fb_par *par)
+{
+	struct mode_registers *params = &par->regs;
+	u32 wmark = 0;
+	
+	if (par->mem_freq == 100) {
+		switch (var->bits_per_pixel) {
+		case 8:
+			wmark = params->bpp8_100;
+			break;
+		case 16:
+			wmark = params->bpp16_100;
+			break;
+		case 24:
+		case 32:
+			wmark = params->bpp24_100;
+		}
+	} else {					
+		switch (var->bits_per_pixel) {
+		case 8:
+			wmark = params->bpp8_133;
+			break;
+		case 16:
+			wmark = params->bpp16_133;
+			break;
+		case 24:
+		case 32:
+			wmark = params->bpp24_133;
+		}
+	}
+	return wmark;
+}	
+
diff --git a/drivers/video/fbdev/i810/i810_gtf.c b/drivers/video/fbdev/i810/i810_gtf.c
new file mode 100644
index 000000000000..9743d51e7f8c
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810_gtf.c
@@ -0,0 +1,276 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/i810_main.h -- Intel 810 Non-discrete Video Timings 
+ *                                     (VESA GTF)
+ *
+ *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved      
+ *
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/kernel.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+#include "i810_main.h"
+
+/*
+ * FIFO and Watermark tables - based almost wholly on i810_wmark.c in 
+ * XFree86 v4.03 by Precision Insight.  Slightly modified for integer 
+ * operation, instead of float
+ */
+
+struct wm_info {
+   u32 freq;
+   u32  wm;
+};
+
+static struct wm_info i810_wm_8_100[] = {
+	{ 15, 0x0070c000 },  { 19, 0x0070c000 },  { 25, 0x22003000 },
+	{ 28, 0x22003000 },  { 31, 0x22003000 },  { 36, 0x22007000 },
+	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22008000 },
+	{ 50, 0x22008000 },  { 56, 0x22008000 },  { 65, 0x22008000 },
+	{ 75, 0x22008000 },  { 78, 0x22008000 },  { 80, 0x22008000 },
+	{ 94, 0x22008000 },  { 96, 0x22107000 },  { 99, 0x22107000 },
+	{ 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
+	{ 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
+	{ 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
+	{ 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
+	{ 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 }, 
+};
+
+static struct wm_info i810_wm_16_100[] = {
+	{ 15, 0x0070c000 },  { 19, 0x0020c000 },  { 25, 0x22006000 },
+	{ 28, 0x22006000 },  { 31, 0x22007000 },  { 36, 0x22007000 },
+	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22009000 },
+	{ 50, 0x22009000 },  { 56, 0x22108000 },  { 65, 0x2210e000 },
+	{ 75, 0x2210e000 },  { 78, 0x2210e000 },  { 80, 0x22210000 },
+	{ 94, 0x22210000 },  { 96, 0x22210000 },  { 99, 0x22210000 },
+	{ 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
+	{ 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
+	{ 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
+	{ 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
+	{ 218, 0x22416000 }, { 229, 0x22416000 },
+};
+
+static struct wm_info i810_wm_24_100[] = {
+	{ 15, 0x0020c000 },  { 19, 0x0040c000 },  { 25, 0x22009000 },
+	{ 28, 0x22009000 },  { 31, 0x2200a000 },  { 36, 0x2210c000 },
+	{ 40, 0x2210c000 },  { 45, 0x2210c000 },  { 49, 0x22111000 },
+	{ 50, 0x22111000 },  { 56, 0x22111000 },  { 65, 0x22214000 },
+	{ 75, 0x22214000 },  { 78, 0x22215000 },  { 80, 0x22216000 },
+	{ 94, 0x22218000 },  { 96, 0x22418000 },  { 99, 0x22418000 },
+	{ 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
+	{ 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
+	{ 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
+	{ 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
+};
+
+static struct wm_info i810_wm_8_133[] = {
+	{ 15, 0x0070c000 },  { 19, 0x0070c000 },  { 25, 0x22003000 },
+	{ 28, 0x22003000 },  { 31, 0x22003000 },  { 36, 0x22007000 },
+	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22008000 },
+	{ 50, 0x22008000 },  { 56, 0x22008000 },  { 65, 0x22008000 },
+	{ 75, 0x22008000 },  { 78, 0x22008000 },  { 80, 0x22008000 },
+	{ 94, 0x22008000 },  { 96, 0x22107000 },  { 99, 0x22107000 },
+	{ 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
+	{ 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
+	{ 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
+	{ 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
+	{ 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 }, 
+};
+
+static struct wm_info i810_wm_16_133[] = {
+	{ 15, 0x0020c000 },  { 19, 0x0020c000 },  { 25, 0x22006000 },
+	{ 28, 0x22006000 },  { 31, 0x22007000 },  { 36, 0x22007000 },
+	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22009000 },
+	{ 50, 0x22009000 },  { 56, 0x22108000 },  { 65, 0x2210e000 },
+	{ 75, 0x2210e000 },  { 78, 0x2210e000 },  { 80, 0x22210000 },
+	{ 94, 0x22210000 },  { 96, 0x22210000 },  { 99, 0x22210000 },
+	{ 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
+	{ 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
+	{ 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
+	{ 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
+	{ 218, 0x22416000 }, { 229, 0x22416000 },
+};
+
+static struct wm_info i810_wm_24_133[] = {
+	{ 15, 0x0020c000 },  { 19, 0x00408000 },  { 25, 0x22009000 },
+	{ 28, 0x22009000 },  { 31, 0x2200a000 },  { 36, 0x2210c000 },
+	{ 40, 0x2210c000 },  { 45, 0x2210c000 },  { 49, 0x22111000 },
+	{ 50, 0x22111000 },  { 56, 0x22111000 },  { 65, 0x22214000 },
+	{ 75, 0x22214000 },  { 78, 0x22215000 },  { 80, 0x22216000 },
+	{ 94, 0x22218000 },  { 96, 0x22418000 },  { 99, 0x22418000 },
+	{ 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
+	{ 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
+	{ 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
+	{ 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
+};
+
+void round_off_xres(u32 *xres) { }
+void round_off_yres(u32 *xres, u32 *yres) { }
+
+/**
+ * i810fb_encode_registers - encode @var to hardware register values
+ * @var: pointer to var structure
+ * @par: pointer to hardware par structure
+ * 
+ * DESCRIPTION: 
+ * Timing values in @var will be converted to appropriate
+ * register values of @par.  
+ */
+void i810fb_encode_registers(const struct fb_var_screeninfo *var,
+			     struct i810fb_par *par, u32 xres, u32 yres)
+{
+	int n, blank_s, blank_e;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	u8 msr = 0;
+
+	/* Horizontal */
+	/* htotal */
+	n = ((xres + var->right_margin + var->hsync_len + 
+	      var->left_margin) >> 3) - 5;
+	par->regs.cr00 =  (u8) n;
+	par->regs.cr35 = (u8) ((n >> 8) & 1);
+	
+	/* xres */
+	par->regs.cr01 = (u8) ((xres >> 3) - 1);
+
+	/* hblank */
+	blank_e = (xres + var->right_margin + var->hsync_len + 
+		   var->left_margin) >> 3;
+	blank_e--;
+	blank_s = blank_e - 127;
+	if (blank_s < (xres >> 3))
+		blank_s = xres >> 3;
+	par->regs.cr02 = (u8) blank_s;
+	par->regs.cr03 = (u8) (blank_e & 0x1F);
+	par->regs.cr05 = (u8) ((blank_e & (1 << 5)) << 2);
+	par->regs.cr39 = (u8) ((blank_e >> 6) & 1);
+
+	/* hsync */
+	par->regs.cr04 = (u8) ((xres + var->right_margin) >> 3);
+	par->regs.cr05 |= (u8) (((xres + var->right_margin + 
+				  var->hsync_len) >> 3) & 0x1F);
+	
+       	/* Vertical */
+	/* vtotal */
+	n = yres + var->lower_margin + var->vsync_len + var->upper_margin - 2;
+	par->regs.cr06 = (u8) (n & 0xFF);
+	par->regs.cr30 = (u8) ((n >> 8) & 0x0F);
+
+	/* vsync */ 
+	n = yres + var->lower_margin;
+	par->regs.cr10 = (u8) (n & 0xFF);
+	par->regs.cr32 = (u8) ((n >> 8) & 0x0F);
+	par->regs.cr11 = i810_readb(CR11, mmio) & ~0x0F;
+	par->regs.cr11 |= (u8) ((yres + var->lower_margin + 
+				 var->vsync_len) & 0x0F);
+
+	/* yres */
+	n = yres - 1;
+	par->regs.cr12 = (u8) (n & 0xFF);
+	par->regs.cr31 = (u8) ((n >> 8) & 0x0F);
+	
+	/* vblank */
+	blank_e = yres + var->lower_margin + var->vsync_len + 
+		var->upper_margin;
+	blank_e--;
+	blank_s = blank_e - 127;
+	if (blank_s < yres)
+		blank_s = yres;
+	par->regs.cr15 = (u8) (blank_s & 0xFF);
+	par->regs.cr33 = (u8) ((blank_s >> 8) & 0x0F);
+	par->regs.cr16 = (u8) (blank_e & 0xFF);
+	par->regs.cr09 = 0;	
+
+	/* sync polarity */
+	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+		msr |= 1 << 6;
+	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+		msr |= 1 << 7;
+	par->regs.msr = msr;
+
+	/* interlace */
+	if (var->vmode & FB_VMODE_INTERLACED) 
+		par->interlace = (1 << 7) | ((u8) (var->yres >> 4));
+	else 
+		par->interlace = 0;
+
+	if (var->vmode & FB_VMODE_DOUBLE)
+		par->regs.cr09 |= 1 << 7;
+
+	/* overlay */
+	par->ovract = ((var->xres + var->right_margin + var->hsync_len + 
+			var->left_margin - 32) | ((var->xres - 32) << 16));
+}	
+
+void i810fb_fill_var_timings(struct fb_var_screeninfo *var) { }
+
+/**
+ * i810_get_watermark - gets watermark
+ * @var: pointer to fb_var_screeninfo
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Gets the required watermark based on 
+ * pixelclock and RAMBUS frequency.
+ * 
+ * RETURNS:
+ * watermark
+ */
+u32 i810_get_watermark(const struct fb_var_screeninfo *var,
+		       struct i810fb_par *par)
+{
+	struct wm_info *wmark = NULL;
+	u32 i, size = 0, pixclock, wm_best = 0, min, diff;
+
+	if (par->mem_freq == 100) {
+		switch (var->bits_per_pixel) { 
+		case 8:
+			wmark = i810_wm_8_100;
+			size = ARRAY_SIZE(i810_wm_8_100);
+			break;
+		case 16:
+			wmark = i810_wm_16_100;
+			size = ARRAY_SIZE(i810_wm_16_100);
+			break;
+		case 24:
+		case 32:
+			wmark = i810_wm_24_100;
+			size = ARRAY_SIZE(i810_wm_24_100);
+		}
+	} else {
+		switch(var->bits_per_pixel) {
+		case 8:
+			wmark = i810_wm_8_133;
+			size = ARRAY_SIZE(i810_wm_8_133);
+			break;
+		case 16:
+			wmark = i810_wm_16_133;
+			size = ARRAY_SIZE(i810_wm_16_133);
+			break;
+		case 24:
+		case 32:
+			wmark = i810_wm_24_133;
+			size = ARRAY_SIZE(i810_wm_24_133);
+		}
+	}
+
+	pixclock = 1000000/var->pixclock;
+	min = ~0;
+	for (i = 0; i < size; i++) {
+		if (pixclock <= wmark[i].freq) 
+			diff = wmark[i].freq - pixclock;
+		else 
+			diff = pixclock - wmark[i].freq;
+		if (diff < min) {
+			wm_best = wmark[i].wm;
+			min = diff;
+		}
+	}
+	return wm_best;		
+}	
+
diff --git a/drivers/video/fbdev/i810/i810_main.c b/drivers/video/fbdev/i810/i810_main.c
new file mode 100644
index 000000000000..bb674e431741
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810_main.c
@@ -0,0 +1,2218 @@
+ /*-*- linux-c -*-
+ *  linux/drivers/video/i810_main.c -- Intel 810 frame buffer device
+ *
+ *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved      
+ *
+ *      Contributors:
+ *         Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets
+ *                                        and enabling the power-on state of 
+ *                                        external VGA connectors for 
+ *                                        secondary displays
+ *
+ *         Fredrik Andersson <krueger@shell.linux.se> - alpha testing of
+ *                                        the VESA GTF
+ *
+ *         Brad Corrion <bcorrion@web-co.com> - alpha testing of customized
+ *                                        timings support
+ *
+ *	The code framework is a modification of vfb.c by Geert Uytterhoeven.
+ *      DotClock and PLL calculations are partly based on i810_driver.c 
+ *              in xfree86 v4.0.3 by Precision Insight.
+ *      Watermark calculation and tables are based on i810_wmark.c 
+ *              in xfre86 v4.0.3 by Precision Insight.  Slight modifications 
+ *              only to allow for integer operations instead of floating point.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/resource.h>
+#include <linux/unistd.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/page.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+#include "i810_main.h"
+
+/*
+ * voffset - framebuffer offset in MiB from aperture start address.  In order for
+ * the driver to work with X, we must try to use memory holes left untouched by X. The
+ * following table lists where X's different surfaces start at.
+ *
+ * ---------------------------------------------
+ * :                :  64 MiB     : 32 MiB      :
+ * ----------------------------------------------
+ * : FrontBuffer    :   0         :  0          :
+ * : DepthBuffer    :   48        :  16         :
+ * : BackBuffer     :   56        :  24         :
+ * ----------------------------------------------
+ *
+ * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
+ * 15 + 1 MiB of Framebuffer memory.  For 32 MiB Aperture sizes, a v_offset of 8 MiB should
+ * work, allowing 7 + 1 MiB of Framebuffer memory.
+ * Note, the size of the hole may change depending on how much memory you allocate to X,
+ * and how the memory is split up between these surfaces.
+ *
+ * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
+ * DRI disabled.  But if the Frontbuffer is overlapped, X will fail to load.
+ *
+ * Experiment with v_offset to find out which works best for you.
+ */
+static u32 v_offset_default; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset;
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int i810fb_init_pci(struct pci_dev *dev,
+			   const struct pci_device_id *entry);
+static void __exit i810fb_remove_pci(struct pci_dev *dev);
+static int i810fb_resume(struct pci_dev *dev);
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
+
+/* Chipset Specific Functions */
+static int i810fb_set_par    (struct fb_info *info);
+static int i810fb_getcolreg  (u8 regno, u8 *red, u8 *green, u8 *blue,
+			      u8 *transp, struct fb_info *info);
+static int i810fb_setcolreg  (unsigned regno, unsigned red, unsigned green, unsigned blue,
+			      unsigned transp, struct fb_info *info);
+static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int i810fb_blank      (int blank_mode, struct fb_info *info);
+
+/* Initialization */
+static void i810fb_release_resource       (struct fb_info *info, struct i810fb_par *par);
+
+/* PCI */
+static const char * const i810_pci_list[] = {
+	"Intel(R) 810 Framebuffer Device"                                 ,
+	"Intel(R) 810-DC100 Framebuffer Device"                           ,
+	"Intel(R) 810E Framebuffer Device"                                ,
+	"Intel(R) 815 (Internal Graphics 100Mhz FSB) Framebuffer Device"  ,
+	"Intel(R) 815 (Internal Graphics only) Framebuffer Device"        ,
+	"Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device"
+};
+
+static struct pci_device_id i810fb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1  },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
+	/* mvo: added i815 PCI-ID */
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_100,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_NOAGP,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
+	{ 0 },
+};
+
+static struct pci_driver i810fb_driver = {
+	.name     =	"i810fb",
+	.id_table =	i810fb_pci_tbl,
+	.probe    =	i810fb_init_pci,
+	.remove   =	__exit_p(i810fb_remove_pci),
+	.suspend  =     i810fb_suspend,
+	.resume   =     i810fb_resume,
+};
+
+static char *mode_option = NULL;
+static int vram = 4;
+static int bpp = 8;
+static bool mtrr;
+static bool accel;
+static int hsync1;
+static int hsync2;
+static int vsync1;
+static int vsync2;
+static int xres;
+static int yres;
+static int vyres;
+static bool sync;
+static bool extvga;
+static bool dcolor;
+static bool ddc3;
+
+/*------------------------------------------------------------*/
+
+/**************************************************************
+ *                Hardware Low Level Routines                 *
+ **************************************************************/
+
+/**
+ * i810_screen_off - turns off/on display
+ * @mmio: address of register space
+ * @mode: on or off
+ *
+ * DESCRIPTION:
+ * Blanks/unblanks the display
+ */
+static void i810_screen_off(u8 __iomem *mmio, u8 mode)
+{
+	u32 count = WAIT_COUNT;
+	u8 val;
+
+	i810_writeb(SR_INDEX, mmio, SR01);
+	val = i810_readb(SR_DATA, mmio);
+	val = (mode == OFF) ? val | SCR_OFF :
+		val & ~SCR_OFF;
+
+	while((i810_readw(DISP_SL, mmio) & 0xFFF) && count--);
+	i810_writeb(SR_INDEX, mmio, SR01);
+	i810_writeb(SR_DATA, mmio, val);
+}
+
+/**
+ * i810_dram_off - turns off/on dram refresh
+ * @mmio: address of register space
+ * @mode: on or off
+ *
+ * DESCRIPTION:
+ * Turns off DRAM refresh.  Must be off for only 2 vsyncs
+ * before data becomes corrupt
+ */
+static void i810_dram_off(u8 __iomem *mmio, u8 mode)
+{
+	u8 val;
+
+	val = i810_readb(DRAMCH, mmio);
+	val &= DRAM_OFF;
+	val = (mode == OFF) ? val : val | DRAM_ON;
+	i810_writeb(DRAMCH, mmio, val);
+}
+
+/**
+ * i810_protect_regs - allows rw/ro mode of certain VGA registers
+ * @mmio: address of register space
+ * @mode: protect/unprotect
+ *
+ * DESCRIPTION:
+ * The IBM VGA standard allows protection of certain VGA registers.  
+ * This will  protect or unprotect them. 
+ */
+static void i810_protect_regs(u8 __iomem *mmio, int mode)
+{
+	u8 reg;
+
+	i810_writeb(CR_INDEX_CGA, mmio, CR11);
+	reg = i810_readb(CR_DATA_CGA, mmio);
+	reg = (mode == OFF) ? reg & ~0x80 :
+		reg | 0x80;
+ 		
+	i810_writeb(CR_INDEX_CGA, mmio, CR11);
+	i810_writeb(CR_DATA_CGA, mmio, reg);
+}
+
+/**
+ * i810_load_pll - loads values for the hardware PLL clock
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Loads the P, M, and N registers.  
+ */
+static void i810_load_pll(struct i810fb_par *par)
+{
+	u32 tmp1, tmp2;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	
+	tmp1 = par->regs.M | par->regs.N << 16;
+	tmp2 = i810_readl(DCLK_2D, mmio);
+	tmp2 &= ~MN_MASK;
+	i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
+	
+	tmp1 = par->regs.P;
+	tmp2 = i810_readl(DCLK_0DS, mmio);
+	tmp2 &= ~(P_OR << 16);
+	i810_writel(DCLK_0DS, mmio, (tmp1 << 16) | tmp2);
+
+	i810_writeb(MSR_WRITE, mmio, par->regs.msr | 0xC8 | 1);
+
+}
+
+/**
+ * i810_load_vga - load standard VGA registers
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Load values to VGA registers
+ */
+static void i810_load_vga(struct i810fb_par *par)
+{	
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	/* interlace */
+	i810_writeb(CR_INDEX_CGA, mmio, CR70);
+	i810_writeb(CR_DATA_CGA, mmio, par->interlace);
+
+	i810_writeb(CR_INDEX_CGA, mmio, CR00);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr00);
+	i810_writeb(CR_INDEX_CGA, mmio, CR01);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr01);
+	i810_writeb(CR_INDEX_CGA, mmio, CR02);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr02);
+	i810_writeb(CR_INDEX_CGA, mmio, CR03);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr03);
+	i810_writeb(CR_INDEX_CGA, mmio, CR04);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr04);
+	i810_writeb(CR_INDEX_CGA, mmio, CR05);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr05);
+	i810_writeb(CR_INDEX_CGA, mmio, CR06);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr06);
+	i810_writeb(CR_INDEX_CGA, mmio, CR09);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr09);
+	i810_writeb(CR_INDEX_CGA, mmio, CR10);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr10);
+	i810_writeb(CR_INDEX_CGA, mmio, CR11);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr11);
+	i810_writeb(CR_INDEX_CGA, mmio, CR12);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr12);
+	i810_writeb(CR_INDEX_CGA, mmio, CR15);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr15);
+	i810_writeb(CR_INDEX_CGA, mmio, CR16);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr16);
+}
+
+/**
+ * i810_load_vgax - load extended VGA registers
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Load values to extended VGA registers
+ */
+static void i810_load_vgax(struct i810fb_par *par)
+{
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	i810_writeb(CR_INDEX_CGA, mmio, CR30);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30);
+	i810_writeb(CR_INDEX_CGA, mmio, CR31);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr31);
+	i810_writeb(CR_INDEX_CGA, mmio, CR32);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr32);
+	i810_writeb(CR_INDEX_CGA, mmio, CR33);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr33);
+	i810_writeb(CR_INDEX_CGA, mmio, CR35);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr35);
+	i810_writeb(CR_INDEX_CGA, mmio, CR39);
+	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr39);
+}
+
+/**
+ * i810_load_2d - load grahics registers
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Load values to graphics registers
+ */
+static void i810_load_2d(struct i810fb_par *par)
+{
+	u32 tmp;
+	u8 tmp8;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+  	i810_writel(FW_BLC, mmio, par->watermark); 
+	tmp = i810_readl(PIXCONF, mmio);
+	tmp |= 1 | 1 << 20;
+	i810_writel(PIXCONF, mmio, tmp);
+
+	i810_writel(OVRACT, mmio, par->ovract);
+
+	i810_writeb(GR_INDEX, mmio, GR10);
+	tmp8 = i810_readb(GR_DATA, mmio);
+	tmp8 |= 2;
+	i810_writeb(GR_INDEX, mmio, GR10);
+	i810_writeb(GR_DATA, mmio, tmp8);
+}	
+
+/**
+ * i810_hires - enables high resolution mode
+ * @mmio: address of register space
+ */
+static void i810_hires(u8 __iomem *mmio)
+{
+	u8 val;
+	
+	i810_writeb(CR_INDEX_CGA, mmio, CR80);
+	val = i810_readb(CR_DATA_CGA, mmio);
+	i810_writeb(CR_INDEX_CGA, mmio, CR80);
+	i810_writeb(CR_DATA_CGA, mmio, val | 1);
+	/* Stop LCD displays from flickering */
+	i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4);
+}
+
+/**
+ * i810_load_pitch - loads the characters per line of the display
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Loads the characters per line
+ */	
+static void i810_load_pitch(struct i810fb_par *par)
+{
+	u32 tmp, pitch;
+	u8 val;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+			
+	pitch = par->pitch >> 3;
+	i810_writeb(SR_INDEX, mmio, SR01);
+	val = i810_readb(SR_DATA, mmio);
+	val &= 0xE0;
+	val |= 1 | 1 << 2;
+	i810_writeb(SR_INDEX, mmio, SR01);
+	i810_writeb(SR_DATA, mmio, val);
+
+	tmp = pitch & 0xFF;
+	i810_writeb(CR_INDEX_CGA, mmio, CR13);
+	i810_writeb(CR_DATA_CGA, mmio, (u8) tmp);
+	
+	tmp = pitch >> 8;
+	i810_writeb(CR_INDEX_CGA, mmio, CR41);
+	val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F;
+	i810_writeb(CR_INDEX_CGA, mmio, CR41);
+	i810_writeb(CR_DATA_CGA, mmio, (u8) tmp | val);
+}
+
+/**
+ * i810_load_color - loads the color depth of the display
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Loads the color depth of the display and the graphics engine
+ */
+static void i810_load_color(struct i810fb_par *par)
+{
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	u32 reg1;
+	u16 reg2;
+
+	reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27);
+	reg2 = i810_readw(BLTCNTL, mmio) & ~0x30;
+
+	reg1 |= 0x8000 | par->pixconf;
+	reg2 |= par->bltcntl;
+	i810_writel(PIXCONF, mmio, reg1);
+	i810_writew(BLTCNTL, mmio, reg2);
+}
+
+/**
+ * i810_load_regs - loads all registers for the mode
+ * @par: pointer to i810fb_par structure
+ * 
+ * DESCRIPTION:
+ * Loads registers
+ */
+static void i810_load_regs(struct i810fb_par *par)
+{
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	i810_screen_off(mmio, OFF);
+	i810_protect_regs(mmio, OFF);
+	i810_dram_off(mmio, OFF);
+	i810_load_pll(par);
+	i810_load_vga(par);
+	i810_load_vgax(par);
+	i810_dram_off(mmio, ON);	
+	i810_load_2d(par);
+	i810_hires(mmio);
+	i810_screen_off(mmio, ON);
+	i810_protect_regs(mmio, ON);
+	i810_load_color(par);
+	i810_load_pitch(par);
+}
+
+static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue,
+			  u8 __iomem *mmio)
+{
+	i810_writeb(CLUT_INDEX_WRITE, mmio, regno);
+	i810_writeb(CLUT_DATA, mmio, red);
+	i810_writeb(CLUT_DATA, mmio, green);
+	i810_writeb(CLUT_DATA, mmio, blue); 	
+}
+
+static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue,
+			  u8 __iomem *mmio)
+{
+	i810_writeb(CLUT_INDEX_READ, mmio, regno);
+	*red = i810_readb(CLUT_DATA, mmio);
+	*green = i810_readb(CLUT_DATA, mmio);
+	*blue = i810_readb(CLUT_DATA, mmio);
+}
+
+/************************************************************
+ *                   VGA State Restore                      * 
+ ************************************************************/
+static void i810_restore_pll(struct i810fb_par *par)
+{
+	u32 tmp1, tmp2;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	
+	tmp1 = par->hw_state.dclk_2d;
+	tmp2 = i810_readl(DCLK_2D, mmio);
+	tmp1 &= ~MN_MASK;
+	tmp2 &= MN_MASK;
+	i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
+
+	tmp1 = par->hw_state.dclk_1d;
+	tmp2 = i810_readl(DCLK_1D, mmio);
+	tmp1 &= ~MN_MASK;
+	tmp2 &= MN_MASK;
+	i810_writel(DCLK_1D, mmio, tmp1 | tmp2);
+
+	i810_writel(DCLK_0DS, mmio, par->hw_state.dclk_0ds);
+}
+
+static void i810_restore_dac(struct i810fb_par *par)
+{
+	u32 tmp1, tmp2;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	tmp1 = par->hw_state.pixconf;
+	tmp2 = i810_readl(PIXCONF, mmio);
+	tmp1 &= DAC_BIT;
+	tmp2 &= ~DAC_BIT;
+	i810_writel(PIXCONF, mmio, tmp1 | tmp2);
+}
+
+static void i810_restore_vgax(struct i810fb_par *par)
+{
+	u8 i, j;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	
+	for (i = 0; i < 4; i++) {
+		i810_writeb(CR_INDEX_CGA, mmio, CR30+i);
+		i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i));
+	}
+	i810_writeb(CR_INDEX_CGA, mmio, CR35);
+	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr35);
+	i810_writeb(CR_INDEX_CGA, mmio, CR39);
+	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
+	i810_writeb(CR_INDEX_CGA, mmio, CR41);
+	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
+
+	/*restore interlace*/
+	i810_writeb(CR_INDEX_CGA, mmio, CR70);
+	i = par->hw_state.cr70;
+	i &= INTERLACE_BIT;
+	j = i810_readb(CR_DATA_CGA, mmio);
+	i810_writeb(CR_INDEX_CGA, mmio, CR70);
+	i810_writeb(CR_DATA_CGA, mmio, j | i);
+
+	i810_writeb(CR_INDEX_CGA, mmio, CR80);
+	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr80);
+	i810_writeb(MSR_WRITE, mmio, par->hw_state.msr);
+	i810_writeb(SR_INDEX, mmio, SR01);
+	i = (par->hw_state.sr01) & ~0xE0 ;
+	j = i810_readb(SR_DATA, mmio) & 0xE0;
+	i810_writeb(SR_INDEX, mmio, SR01);
+	i810_writeb(SR_DATA, mmio, i | j);
+}
+
+static void i810_restore_vga(struct i810fb_par *par)
+{
+	u8 i;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	
+	for (i = 0; i < 10; i++) {
+		i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
+		i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i));
+	}
+	for (i = 0; i < 8; i++) {
+		i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
+		i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr10) + i));
+	}
+}
+
+static void i810_restore_addr_map(struct i810fb_par *par)
+{
+	u8 tmp;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	i810_writeb(GR_INDEX, mmio, GR10);
+	tmp = i810_readb(GR_DATA, mmio);
+	tmp &= ADDR_MAP_MASK;
+	tmp |= par->hw_state.gr10;
+	i810_writeb(GR_INDEX, mmio, GR10);
+	i810_writeb(GR_DATA, mmio, tmp);
+}
+
+static void i810_restore_2d(struct i810fb_par *par)
+{
+	u32 tmp_long;
+	u16 tmp_word;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	tmp_word = i810_readw(BLTCNTL, mmio);
+	tmp_word &= ~(3 << 4); 
+	tmp_word |= par->hw_state.bltcntl;
+	i810_writew(BLTCNTL, mmio, tmp_word);
+       
+	i810_dram_off(mmio, OFF);
+	i810_writel(PIXCONF, mmio, par->hw_state.pixconf);
+	i810_dram_off(mmio, ON);
+
+	tmp_word = i810_readw(HWSTAM, mmio);
+	tmp_word &= 3 << 13;
+	tmp_word |= par->hw_state.hwstam;
+	i810_writew(HWSTAM, mmio, tmp_word);
+
+	tmp_long = i810_readl(FW_BLC, mmio);
+	tmp_long &= FW_BLC_MASK;
+	tmp_long |= par->hw_state.fw_blc;
+	i810_writel(FW_BLC, mmio, tmp_long);
+
+	i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga); 
+	i810_writew(IER, mmio, par->hw_state.ier);
+	i810_writew(IMR, mmio, par->hw_state.imr);
+	i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas);
+}
+
+static void i810_restore_vga_state(struct i810fb_par *par)
+{
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	i810_screen_off(mmio, OFF);
+	i810_protect_regs(mmio, OFF);
+	i810_dram_off(mmio, OFF);
+	i810_restore_pll(par);
+	i810_restore_dac(par);
+	i810_restore_vga(par);
+	i810_restore_vgax(par);
+	i810_restore_addr_map(par);
+	i810_dram_off(mmio, ON);
+	i810_restore_2d(par);
+	i810_screen_off(mmio, ON);
+	i810_protect_regs(mmio, ON);
+}
+
+/***********************************************************************
+ *                         VGA State Save                              *
+ ***********************************************************************/
+
+static void i810_save_vgax(struct i810fb_par *par)
+{
+	u8 i;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	for (i = 0; i < 4; i++) {
+		i810_writeb(CR_INDEX_CGA, mmio, CR30 + i);
+		*(&(par->hw_state.cr30) + i) = i810_readb(CR_DATA_CGA, mmio);
+	}
+	i810_writeb(CR_INDEX_CGA, mmio, CR35);
+	par->hw_state.cr35 = i810_readb(CR_DATA_CGA, mmio);
+	i810_writeb(CR_INDEX_CGA, mmio, CR39);
+	par->hw_state.cr39 = i810_readb(CR_DATA_CGA, mmio);
+	i810_writeb(CR_INDEX_CGA, mmio, CR41);
+	par->hw_state.cr41 = i810_readb(CR_DATA_CGA, mmio);
+	i810_writeb(CR_INDEX_CGA, mmio, CR70);
+	par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio);	
+	par->hw_state.msr = i810_readb(MSR_READ, mmio);
+	i810_writeb(CR_INDEX_CGA, mmio, CR80);
+	par->hw_state.cr80 = i810_readb(CR_DATA_CGA, mmio);
+	i810_writeb(SR_INDEX, mmio, SR01);
+	par->hw_state.sr01 = i810_readb(SR_DATA, mmio);
+}
+
+static void i810_save_vga(struct i810fb_par *par)
+{
+	u8 i;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	for (i = 0; i < 10; i++) {
+		i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
+		*((&par->hw_state.cr00) + i) = i810_readb(CR_DATA_CGA, mmio);
+	}
+	for (i = 0; i < 8; i++) {
+		i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
+		*((&par->hw_state.cr10) + i) = i810_readb(CR_DATA_CGA, mmio);
+	}
+}
+
+static void i810_save_2d(struct i810fb_par *par)
+{
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	par->hw_state.dclk_2d = i810_readl(DCLK_2D, mmio);
+	par->hw_state.dclk_1d = i810_readl(DCLK_1D, mmio);
+	par->hw_state.dclk_0ds = i810_readl(DCLK_0DS, mmio);
+	par->hw_state.pixconf = i810_readl(PIXCONF, mmio);
+	par->hw_state.fw_blc = i810_readl(FW_BLC, mmio);
+	par->hw_state.bltcntl = i810_readw(BLTCNTL, mmio);
+	par->hw_state.hwstam = i810_readw(HWSTAM, mmio); 
+	par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio); 
+	par->hw_state.ier = i810_readw(IER, mmio);
+	par->hw_state.imr = i810_readw(IMR, mmio);
+	par->hw_state.dplystas = i810_readl(DPLYSTAS, mmio);
+}
+
+static void i810_save_vga_state(struct i810fb_par *par)
+{
+	i810_save_vga(par);
+	i810_save_vgax(par);
+	i810_save_2d(par);
+}
+
+/************************************************************
+ *                    Helpers                               * 
+ ************************************************************/
+/**
+ * get_line_length - calculates buffer pitch in bytes
+ * @par: pointer to i810fb_par structure
+ * @xres_virtual: virtual resolution of the frame
+ * @bpp: bits per pixel
+ *
+ * DESCRIPTION:
+ * Calculates buffer pitch in bytes.  
+ */
+static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
+{
+   	u32 length;
+	
+	length = xres_virtual*bpp;
+	length = (length+31)&-32;
+	length >>= 3;
+	return length;
+}
+
+/**
+ * i810_calc_dclk - calculates the P, M, and N values of a pixelclock value
+ * @freq: target pixelclock in picoseconds
+ * @m: where to write M register
+ * @n: where to write N register
+ * @p: where to write P register
+ *
+ * DESCRIPTION:
+ * Based on the formula Freq_actual = (4*M*Freq_ref)/(N^P)
+ * Repeatedly computes the Freq until the actual Freq is equal to
+ * the target Freq or until the loop count is zero.  In the latter
+ * case, the actual frequency nearest the target will be used.
+ */
+static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
+{
+	u32 m_reg, n_reg, p_divisor, n_target_max;
+	u32 m_target, n_target, p_target, n_best, m_best, mod;
+	u32 f_out, target_freq, diff = 0, mod_min, diff_min;
+
+	diff_min = mod_min = 0xFFFFFFFF;
+	n_best = m_best = m_target = f_out = 0;
+
+	target_freq =  freq;
+	n_target_max = 30;
+
+	/*
+	 * find P such that target freq is 16x reference freq (Hz). 
+	 */
+	p_divisor = 1;
+	p_target = 0;
+	while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) && 
+	      p_divisor <= 32) {
+		p_divisor <<= 1;
+		p_target++;
+	}
+
+	n_reg = m_reg = n_target = 3;	
+	while (diff_min && mod_min && (n_target < n_target_max)) {
+		f_out = (p_divisor * n_reg * 1000000)/(4 * 24 * m_reg);
+		mod = (p_divisor * n_reg * 1000000) % (4 * 24 * m_reg);
+		m_target = m_reg;
+		n_target = n_reg;
+		if (f_out <= target_freq) {
+			n_reg++;
+			diff = target_freq - f_out;
+		} else {
+			m_reg++;
+			diff = f_out - target_freq;
+		}
+
+		if (diff_min > diff) {
+			diff_min = diff;
+			n_best = n_target;
+			m_best = m_target;
+		}		 
+
+		if (!diff && mod_min > mod) {
+			mod_min = mod;
+			n_best = n_target;
+			m_best = m_target;
+		}
+	} 
+	if (m) *m = (m_best - 2) & 0x3FF;
+	if (n) *n = (n_best - 2) & 0x3FF;
+	if (p) *p = (p_target << 4);
+}
+
+/*************************************************************
+ *                Hardware Cursor Routines                   *
+ *************************************************************/
+
+/**
+ * i810_enable_cursor - show or hide the hardware cursor
+ * @mmio: address of register space
+ * @mode: show (1) or hide (0)
+ *
+ * Description:
+ * Shows or hides the hardware cursor
+ */
+static void i810_enable_cursor(u8 __iomem *mmio, int mode)
+{
+	u32 temp;
+	
+	temp = i810_readl(PIXCONF, mmio);
+	temp = (mode == ON) ? temp | CURSOR_ENABLE_MASK :
+		temp & ~CURSOR_ENABLE_MASK;
+
+	i810_writel(PIXCONF, mmio, temp);
+}
+
+static void i810_reset_cursor_image(struct i810fb_par *par)
+{
+	u8 __iomem *addr = par->cursor_heap.virtual;
+	int i, j;
+
+	for (i = 64; i--; ) {
+		for (j = 0; j < 8; j++) {             
+			i810_writeb(j, addr, 0xff);   
+			i810_writeb(j+8, addr, 0x00); 
+		}	
+		addr +=16;
+	}
+}
+
+static void i810_load_cursor_image(int width, int height, u8 *data,
+				   struct i810fb_par *par)
+{
+	u8 __iomem *addr = par->cursor_heap.virtual;
+	int i, j, w = width/8;
+	int mod = width % 8, t_mask, d_mask;
+	
+	t_mask = 0xff >> mod;
+	d_mask = ~(0xff >> mod); 
+	for (i = height; i--; ) {
+		for (j = 0; j < w; j++) {
+			i810_writeb(j+0, addr, 0x00);
+			i810_writeb(j+8, addr, *data++);
+		}
+		if (mod) {
+			i810_writeb(j+0, addr, t_mask);
+			i810_writeb(j+8, addr, *data++ & d_mask);
+		}
+		addr += 16;
+	}
+}
+
+static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	u8 red, green, blue, trans, temp;
+
+	i810fb_getcolreg(bg, &red, &green, &blue, &trans, info);
+
+	temp = i810_readb(PIXCONF1, mmio);
+	i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
+
+	i810_write_dac(4, red, green, blue, mmio);
+
+	i810_writeb(PIXCONF1, mmio, temp);
+
+	i810fb_getcolreg(fg, &red, &green, &blue, &trans, info);
+	temp = i810_readb(PIXCONF1, mmio);
+	i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
+
+	i810_write_dac(5, red, green, blue, mmio);
+
+	i810_writeb(PIXCONF1, mmio, temp);
+}
+
+/**
+ * i810_init_cursor - initializes the cursor
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Initializes the cursor registers
+ */
+static void i810_init_cursor(struct i810fb_par *par)
+{
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	i810_enable_cursor(mmio, OFF);
+	i810_writel(CURBASE, mmio, par->cursor_heap.physical);
+	i810_writew(CURCNTR, mmio, COORD_ACTIVE | CURSOR_MODE_64_XOR);
+}	
+
+/*********************************************************************
+ *                    Framebuffer hook helpers                       *
+ *********************************************************************/
+/**
+ * i810_round_off -  Round off values to capability of hardware
+ * @var: pointer to fb_var_screeninfo structure
+ *
+ * DESCRIPTION:
+ * @var contains user-defined information for the mode to be set.
+ * This will try modify those values to ones nearest the
+ * capability of the hardware
+ */
+static void i810_round_off(struct fb_var_screeninfo *var)
+{
+	u32 xres, yres, vxres, vyres;
+
+	/*
+	 *  Presently supports only these configurations 
+	 */
+
+	xres = var->xres;
+	yres = var->yres;
+	vxres = var->xres_virtual;
+	vyres = var->yres_virtual;
+
+	var->bits_per_pixel += 7;
+	var->bits_per_pixel &= ~7;
+	
+	if (var->bits_per_pixel < 8)
+		var->bits_per_pixel = 8;
+	if (var->bits_per_pixel > 32) 
+		var->bits_per_pixel = 32;
+
+	round_off_xres(&xres);
+	if (xres < 40)
+		xres = 40;
+	if (xres > 2048) 
+		xres = 2048;
+	xres = (xres + 7) & ~7;
+
+	if (vxres < xres) 
+		vxres = xres;
+
+	round_off_yres(&xres, &yres);
+	if (yres < 1)
+		yres = 1;
+	if (yres >= 2048)
+		yres = 2048;
+
+	if (vyres < yres) 
+		vyres = yres;
+
+	if (var->bits_per_pixel == 32)
+		var->accel_flags = 0;
+
+	/* round of horizontal timings to nearest 8 pixels */
+	var->left_margin = (var->left_margin + 4) & ~7;
+	var->right_margin = (var->right_margin + 4) & ~7;
+	var->hsync_len = (var->hsync_len + 4) & ~7;
+
+	if (var->vmode & FB_VMODE_INTERLACED) {
+		if (!((yres + var->upper_margin + var->vsync_len + 
+		       var->lower_margin) & 1))
+			var->upper_margin++;
+	}
+	
+	var->xres = xres;
+	var->yres = yres;
+	var->xres_virtual = vxres;
+	var->yres_virtual = vyres;
+}	
+
+/**
+ * set_color_bitfields - sets rgba fields
+ * @var: pointer to fb_var_screeninfo
+ *
+ * DESCRIPTION:
+ * The length, offset and ordering  for each color field 
+ * (red, green, blue)  will be set as specified 
+ * by the hardware
+ */  
+static void set_color_bitfields(struct fb_var_screeninfo *var)
+{
+	switch (var->bits_per_pixel) {
+	case 8:       
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:
+		var->green.length = (var->green.length == 5) ? 5 : 6;
+		var->red.length = 5;
+		var->blue.length = 5;
+		var->transp.length = 6 - var->green.length;
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 5 + var->green.length;
+		var->transp.offset =  (5 + var->red.offset) & 15;
+		break;
+	case 24:	/* RGB 888   */
+	case 32:	/* RGBA 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.length = var->bits_per_pixel - 24;
+		var->transp.offset = (var->transp.length) ? 24 : 0;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+}
+
+/**
+ * i810_check_params - check if contents in var are valid
+ * @var: pointer to fb_var_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * This will check if the framebuffer size is sufficient 
+ * for the current mode and if the user's monitor has the 
+ * required specifications to display the current mode.
+ */
+static int i810_check_params(struct fb_var_screeninfo *var, 
+			     struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	int line_length, vidmem, mode_valid = 0, retval = 0;
+	u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length = get_line_length(par, vxres, var->bits_per_pixel);
+	vidmem = line_length*vyres;
+
+	if (vidmem > par->fb.size) {
+		vyres = par->fb.size/line_length;
+		if (vyres < var->yres) {
+			vyres = info->var.yres;
+			vxres = par->fb.size/vyres;
+			vxres /= var->bits_per_pixel >> 3;
+			line_length = get_line_length(par, vxres, 
+						      var->bits_per_pixel);
+			vidmem = line_length * info->var.yres;
+			if (vxres < var->xres) {
+				printk("i810fb: required video memory, "
+				       "%d bytes, for %dx%d-%d (virtual) "
+				       "is out of range\n", 
+				       vidmem, vxres, vyres, 
+				       var->bits_per_pixel);
+				return -ENOMEM;
+			}
+		}
+	}
+
+	var->xres_virtual = vxres;
+	var->yres_virtual = vyres;
+
+	/*
+	 * Monitor limit
+	 */
+	switch (var->bits_per_pixel) {
+	case 8:
+		info->monspecs.dclkmax = 234000000;
+		break;
+	case 16:
+		info->monspecs.dclkmax = 229000000;
+		break;
+	case 24:
+	case 32:
+		info->monspecs.dclkmax = 204000000;
+		break;
+	}
+
+	info->monspecs.dclkmin = 15000000;
+
+	if (!fb_validate_mode(var, info))
+		mode_valid = 1;
+
+#ifdef CONFIG_FB_I810_I2C
+	if (!mode_valid && info->monspecs.gtf &&
+	    !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+		mode_valid = 1;
+
+	if (!mode_valid && info->monspecs.modedb_len) {
+		const struct fb_videomode *mode;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			fb_videomode_to_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+#endif
+	if (!mode_valid && info->monspecs.modedb_len == 0) {
+		if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) {
+			int default_sync = (info->monspecs.hfmin-HFMIN)
+				|(info->monspecs.hfmax-HFMAX)
+				|(info->monspecs.vfmin-VFMIN)
+				|(info->monspecs.vfmax-VFMAX);
+			printk("i810fb: invalid video mode%s\n",
+			       default_sync ? "" : ". Specifying "
+			       "vsyncN/hsyncN parameters may help");
+			retval = -EINVAL;
+		}
+	}
+
+	return retval;
+}	
+
+/**
+ * encode_fix - fill up fb_fix_screeninfo structure
+ * @fix: pointer to fb_fix_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * This will set up parameters that are unmodifiable by the user.
+ */
+static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+
+    	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+    	strcpy(fix->id, "I810");
+	mutex_lock(&info->mm_lock);
+    	fix->smem_start = par->fb.physical;
+    	fix->smem_len = par->fb.size;
+	mutex_unlock(&info->mm_lock);
+    	fix->type = FB_TYPE_PACKED_PIXELS;
+    	fix->type_aux = 0;
+	fix->xpanstep = 8;
+	fix->ypanstep = 1;
+
+    	switch (info->var.bits_per_pixel) {
+	case 8:
+	    	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	    	break;
+	case 16:
+	case 24:
+	case 32:
+		if (info->var.nonstd)
+			fix->visual = FB_VISUAL_DIRECTCOLOR;
+		else
+			fix->visual = FB_VISUAL_TRUECOLOR;
+	    	break;
+	default:
+		return -EINVAL;
+	}
+    	fix->ywrapstep = 0;
+	fix->line_length = par->pitch;
+	fix->mmio_start = par->mmio_start_phys;
+	fix->mmio_len = MMIO_SIZE;
+	fix->accel = FB_ACCEL_I810;
+
+	return 0;
+}
+
+/**
+ * decode_var - modify par according to contents of var
+ * @var: pointer to fb_var_screeninfo
+ * @par: pointer to i810fb_par
+ *
+ * DESCRIPTION:
+ * Based on the contents of @var, @par will be dynamically filled up.
+ * @par contains all information necessary to modify the hardware. 
+*/
+static void decode_var(const struct fb_var_screeninfo *var, 
+		       struct i810fb_par *par)
+{
+	u32 xres, yres, vxres, vyres;
+
+	xres = var->xres;
+	yres = var->yres;
+	vxres = var->xres_virtual;
+	vyres = var->yres_virtual;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		par->pixconf = PIXCONF8;
+		par->bltcntl = 0;
+		par->depth = 1;
+		par->blit_bpp = BPP8;
+		break;
+	case 16:
+		if (var->green.length == 5)
+			par->pixconf = PIXCONF15;
+		else
+			par->pixconf = PIXCONF16;
+		par->bltcntl = 16;
+		par->depth = 2;
+		par->blit_bpp = BPP16;
+		break;
+	case 24:
+		par->pixconf = PIXCONF24;
+		par->bltcntl = 32;
+		par->depth = 3;
+		par->blit_bpp = BPP24;
+		break;
+	case 32:
+		par->pixconf = PIXCONF32;
+		par->bltcntl = 0;
+		par->depth = 4;
+		par->blit_bpp = 3 << 24;
+		break;
+	}
+	if (var->nonstd && var->bits_per_pixel != 8)
+		par->pixconf |= 1 << 27;
+
+	i810_calc_dclk(var->pixclock, &par->regs.M, 
+		       &par->regs.N, &par->regs.P);
+	i810fb_encode_registers(var, par, xres, yres);
+
+	par->watermark = i810_get_watermark(var, par);
+	par->pitch = get_line_length(par, vxres, var->bits_per_pixel);
+}	
+
+/**
+ * i810fb_getcolreg - gets red, green and blue values of the hardware DAC
+ * @regno: DAC index
+ * @red: red
+ * @green: green
+ * @blue: blue
+ * @transp: transparency (alpha)
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * Gets the red, green and blue values of the hardware DAC as pointed by @regno
+ * and writes them to @red, @green and @blue respectively
+ */
+static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, 
+			    u8 *transp, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	u8 temp;
+
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		if ((info->var.green.length == 5 && regno > 31) ||
+		    (info->var.green.length == 6 && regno > 63))
+			return 1;
+	}
+
+	temp = i810_readb(PIXCONF1, mmio);
+	i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
+
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+	    info->var.green.length == 5) 
+		i810_read_dac(regno * 8, red, green, blue, mmio);
+
+	else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+		 info->var.green.length == 6) {
+		u8 tmp;
+
+		i810_read_dac(regno * 8, red, &tmp, blue, mmio);
+		i810_read_dac(regno * 4, &tmp, green, &tmp, mmio);
+	}
+	else 
+		i810_read_dac(regno, red, green, blue, mmio);
+
+    	*transp = 0;
+	i810_writeb(PIXCONF1, mmio, temp);
+
+    	return 0;
+}
+
+/****************************************************************** 
+ *           Framebuffer device-specific hooks                    *
+ ******************************************************************/
+
+static int i810fb_open(struct fb_info *info, int user)
+{
+	struct i810fb_par *par = info->par;
+
+	mutex_lock(&par->open_lock);
+	if (par->use_count == 0) {
+		memset(&par->state, 0, sizeof(struct vgastate));
+		par->state.flags = VGA_SAVE_CMAP;
+		par->state.vgabase = par->mmio_start_virtual;
+		save_vga(&par->state);
+
+		i810_save_vga_state(par);
+	}
+
+	par->use_count++;
+	mutex_unlock(&par->open_lock);
+	
+	return 0;
+}
+
+static int i810fb_release(struct fb_info *info, int user)
+{
+	struct i810fb_par *par = info->par;
+
+	mutex_lock(&par->open_lock);
+	if (par->use_count == 0) {
+		mutex_unlock(&par->open_lock);
+		return -EINVAL;
+	}
+
+	if (par->use_count == 1) {
+		i810_restore_vga_state(par);
+		restore_vga(&par->state);
+	}
+
+	par->use_count--;
+	mutex_unlock(&par->open_lock);
+	
+	return 0;
+}
+
+
+static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, 
+			    unsigned blue, unsigned transp, 
+			    struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	u8 temp;
+	int i;
+
+ 	if (regno > 255) return 1;
+
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		if ((info->var.green.length == 5 && regno > 31) ||
+		    (info->var.green.length == 6 && regno > 63))
+			return 1;
+	}
+
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+				      7471 * blue) >> 16;
+
+	temp = i810_readb(PIXCONF1, mmio);
+	i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
+
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+	    info->var.green.length == 5) {
+		for (i = 0; i < 8; i++) 
+			i810_write_dac((u8) (regno * 8) + i, (u8) red, 
+				       (u8) green, (u8) blue, mmio);
+	} else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+		 info->var.green.length == 6) {
+		u8 r, g, b;
+
+		if (regno < 32) {
+			for (i = 0; i < 8; i++) 
+				i810_write_dac((u8) (regno * 8) + i,
+					       (u8) red, (u8) green, 
+					       (u8) blue, mmio);
+		}
+		i810_read_dac((u8) (regno*4), &r, &g, &b, mmio);
+		for (i = 0; i < 4; i++) 
+			i810_write_dac((u8) (regno*4) + i, r, (u8) green, 
+				       b, mmio);
+	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		i810_write_dac((u8) regno, (u8) red, (u8) green,
+			       (u8) blue, mmio);
+	}
+
+	i810_writeb(PIXCONF1, mmio, temp);
+
+	if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 16:	
+			if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+				if (info->var.green.length == 5) 
+					((u32 *)info->pseudo_palette)[regno] = 
+						(regno << 10) | (regno << 5) |
+						regno;
+				else
+					((u32 *)info->pseudo_palette)[regno] = 
+						(regno << 11) | (regno << 5) |
+						regno;
+			} else {
+				if (info->var.green.length == 5) {
+					/* RGB 555 */
+					((u32 *)info->pseudo_palette)[regno] = 
+						((red & 0xf800) >> 1) |
+						((green & 0xf800) >> 6) |
+						((blue & 0xf800) >> 11);
+				} else {
+					/* RGB 565 */
+					((u32 *)info->pseudo_palette)[regno] =
+						(red & 0xf800) |
+						((green & 0xf800) >> 5) |
+						((blue & 0xf800) >> 11);
+				}
+			}
+			break;
+		case 24:	/* RGB 888 */
+		case 32:	/* RGBA 8888 */
+			if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 
+				((u32 *)info->pseudo_palette)[regno] = 
+					(regno << 16) | (regno << 8) |
+					regno;
+			else 
+				((u32 *)info->pseudo_palette)[regno] = 
+					((red & 0xff00) << 8) |
+					(green & 0xff00) |
+					((blue & 0xff00) >> 8);
+			break;
+		}
+	}
+	return 0;
+}
+
+static int i810fb_pan_display(struct fb_var_screeninfo *var, 
+			      struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u32 total;
+	
+	total = var->xoffset * par->depth + 
+		var->yoffset * info->fix.line_length;
+	i810fb_load_front(total, info);
+
+	return 0;
+}
+
+static int i810fb_blank (int blank_mode, struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+	int mode = 0, pwr, scr_off = 0;
+	
+	pwr = i810_readl(PWR_CLKC, mmio);
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		mode = POWERON;
+		pwr |= 1;
+		scr_off = ON;
+		break;
+	case FB_BLANK_NORMAL:
+		mode = POWERON;
+		pwr |= 1;
+		scr_off = OFF;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		mode = STANDBY;
+		pwr |= 1;
+		scr_off = OFF;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		mode = SUSPEND;
+		pwr |= 1;
+		scr_off = OFF;
+		break;
+	case FB_BLANK_POWERDOWN:
+		mode = POWERDOWN;
+		pwr &= ~1;
+		scr_off = OFF;
+		break;
+	default:
+		return -EINVAL; 
+	}
+
+	i810_screen_off(mmio, scr_off);
+	i810_writel(HVSYNC, mmio, mode);
+	i810_writel(PWR_CLKC, mmio, pwr);
+
+	return 0;
+}
+
+static int i810fb_set_par(struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+
+	decode_var(&info->var, par);
+	i810_load_regs(par);
+	i810_init_cursor(par);
+	encode_fix(&info->fix, info);
+
+	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_IMAGEBLIT;
+		info->pixmap.scan_align = 2;
+	} else {
+		info->pixmap.scan_align = 1;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	}
+	return 0;
+}
+
+static int i810fb_check_var(struct fb_var_screeninfo *var, 
+			    struct fb_info *info)
+{
+	int err;
+
+	if (IS_DVT) {
+		var->vmode &= ~FB_VMODE_MASK;
+		var->vmode |= FB_VMODE_NONINTERLACED;
+	}
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		var->vmode &= ~FB_VMODE_MASK;
+		var->vmode |= FB_VMODE_NONINTERLACED;
+	}
+
+	i810_round_off(var);
+	if ((err = i810_check_params(var, info)))
+		return err;
+
+	i810fb_fill_var_timings(var);
+	set_color_bitfields(var);
+	return 0;
+}
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct i810fb_par *par = info->par;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	if (par->dev_flags & LOCKUP)
+		return -ENXIO;
+
+	if (cursor->image.width > 64 || cursor->image.height > 64)
+		return -ENXIO;
+
+	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
+		i810_init_cursor(par);
+		cursor->set |= FB_CUR_SETALL;
+	}
+
+	i810_enable_cursor(mmio, OFF);
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		u32 tmp;
+
+		tmp = (cursor->image.dx - info->var.xoffset) & 0xffff;
+		tmp |= (cursor->image.dy - info->var.yoffset) << 16;
+		i810_writel(CURPOS, mmio, tmp);
+	}
+
+	if (cursor->set & FB_CUR_SETSIZE)
+		i810_reset_cursor_image(par);
+
+	if (cursor->set & FB_CUR_SETCMAP)
+		i810_load_cursor_colors(cursor->image.fg_color,
+					cursor->image.bg_color,
+					info);
+
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+		int size = ((cursor->image.width + 7) >> 3) *
+			cursor->image.height;
+		int i;
+		u8 *data = kmalloc(64 * 8, GFP_ATOMIC);
+
+		if (data == NULL)
+			return -ENOMEM;
+
+		switch (cursor->rop) {
+		case ROP_XOR:
+			for (i = 0; i < size; i++)
+				data[i] = cursor->image.data[i] ^ cursor->mask[i];
+			break;
+		case ROP_COPY:
+		default:
+			for (i = 0; i < size; i++)
+				data[i] = cursor->image.data[i] & cursor->mask[i];
+			break;
+		}
+
+		i810_load_cursor_image(cursor->image.width,
+				       cursor->image.height, data,
+				       par);
+		kfree(data);
+	}
+
+	if (cursor->enable)
+		i810_enable_cursor(mmio, ON);
+
+	return 0;
+}
+
+static struct fb_ops i810fb_ops = {
+	.owner =             THIS_MODULE,
+	.fb_open =           i810fb_open,
+	.fb_release =        i810fb_release,
+	.fb_check_var =      i810fb_check_var,
+	.fb_set_par =        i810fb_set_par,
+	.fb_setcolreg =      i810fb_setcolreg,
+	.fb_blank =          i810fb_blank,
+	.fb_pan_display =    i810fb_pan_display, 
+	.fb_fillrect =       i810fb_fillrect,
+	.fb_copyarea =       i810fb_copyarea,
+	.fb_imageblit =      i810fb_imageblit,
+	.fb_cursor =         i810fb_cursor,
+	.fb_sync =           i810fb_sync,
+};
+
+/***********************************************************************
+ *                         Power Management                            *
+ ***********************************************************************/
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct i810fb_par *par = info->par;
+
+	par->cur_state = mesg.event;
+
+	switch (mesg.event) {
+	case PM_EVENT_FREEZE:
+	case PM_EVENT_PRETHAW:
+		dev->dev.power.power_state = mesg;
+		return 0;
+	}
+
+	console_lock();
+	fb_set_suspend(info, 1);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	i810fb_blank(FB_BLANK_POWERDOWN, info);
+	agp_unbind_memory(par->i810_gtt.i810_fb_memory);
+	agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
+
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, mesg));
+	console_unlock();
+
+	return 0;
+}
+
+static int i810fb_resume(struct pci_dev *dev) 
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct i810fb_par *par = info->par;
+	int cur_state = par->cur_state;
+
+	par->cur_state = PM_EVENT_ON;
+
+	if (cur_state == PM_EVENT_FREEZE) {
+		pci_set_power_state(dev, PCI_D0);
+		return 0;
+	}
+
+	console_lock();
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+
+	if (pci_enable_device(dev))
+		goto fail;
+
+	pci_set_master(dev);
+	agp_bind_memory(par->i810_gtt.i810_fb_memory,
+			par->fb.offset);
+	agp_bind_memory(par->i810_gtt.i810_cursor_memory,
+			par->cursor_heap.offset);
+	i810fb_set_par(info);
+	fb_set_suspend (info, 0);
+	info->fbops->fb_blank(VESA_NO_BLANKING, info);
+fail:
+	console_unlock();
+	return 0;
+}
+/***********************************************************************
+ *                  AGP resource allocation                            *
+ ***********************************************************************/
+  
+static void i810_fix_pointers(struct i810fb_par *par)
+{
+      	par->fb.physical = par->aperture.physical+(par->fb.offset << 12);
+	par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);
+	par->iring.physical = par->aperture.physical + 
+		(par->iring.offset << 12);
+	par->iring.virtual = par->aperture.virtual + 
+		(par->iring.offset << 12);
+	par->cursor_heap.virtual = par->aperture.virtual+
+		(par->cursor_heap.offset << 12);
+}
+
+static void i810_fix_offsets(struct i810fb_par *par)
+{
+	if (vram + 1 > par->aperture.size >> 20)
+		vram = (par->aperture.size >> 20) - 1;
+	if (v_offset_default > (par->aperture.size >> 20))
+		v_offset_default = (par->aperture.size >> 20);
+	if (vram + v_offset_default + 1 > par->aperture.size >> 20)
+		v_offset_default = (par->aperture.size >> 20) - (vram + 1);
+
+	par->fb.size = vram << 20;
+	par->fb.offset = v_offset_default << 20;
+	par->fb.offset >>= 12;
+
+	par->iring.offset = par->fb.offset + (par->fb.size >> 12);
+	par->iring.size = RINGBUFFER_SIZE;
+
+	par->cursor_heap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12);
+	par->cursor_heap.size = 4096;
+}
+
+static int i810_alloc_agp_mem(struct fb_info *info)
+{
+	struct i810fb_par *par = info->par;
+	int size;
+	struct agp_bridge_data *bridge;
+	
+	i810_fix_offsets(par);
+	size = par->fb.size + par->iring.size;
+
+	if (!(bridge = agp_backend_acquire(par->dev))) {
+		printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
+		return -ENODEV;
+	}
+	if (!(par->i810_gtt.i810_fb_memory = 
+	      agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
+		printk("i810fb_alloc_fbmem: can't allocate framebuffer "
+		       "memory\n");
+		agp_backend_release(bridge);
+		return -ENOMEM;
+	}
+	if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
+			    par->fb.offset)) {
+		printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
+		agp_backend_release(bridge);
+		return -EBUSY;
+	}	
+	
+	if (!(par->i810_gtt.i810_cursor_memory = 
+	      agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
+				  AGP_PHYSICAL_MEMORY))) {
+		printk("i810fb_alloc_cursormem:  can't allocate" 
+		       "cursor memory\n");
+		agp_backend_release(bridge);
+		return -ENOMEM;
+	}
+	if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
+			    par->cursor_heap.offset)) {
+		printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
+		agp_backend_release(bridge);
+		return -EBUSY;
+	}	
+
+	par->cursor_heap.physical = par->i810_gtt.i810_cursor_memory->physical;
+
+	i810_fix_pointers(par);
+
+	agp_backend_release(bridge);
+
+	return 0;
+}
+
+/*************************************************************** 
+ *                    Initialization                           * 
+ ***************************************************************/
+
+/**
+ * i810_init_monspecs
+ * @info: pointer to device specific info structure
+ *
+ * DESCRIPTION:
+ * Sets the user monitor's horizontal and vertical
+ * frequency limits
+ */
+static void i810_init_monspecs(struct fb_info *info)
+{
+	if (!hsync1)
+		hsync1 = HFMIN;
+	if (!hsync2) 
+		hsync2 = HFMAX;
+	if (!info->monspecs.hfmax)
+		info->monspecs.hfmax = hsync2;
+	if (!info->monspecs.hfmin)
+		info->monspecs.hfmin = hsync1;
+	if (hsync2 < hsync1)
+		info->monspecs.hfmin = hsync2;
+
+	if (!vsync1)
+		vsync1 = VFMIN;
+	if (!vsync2) 
+		vsync2 = VFMAX;
+	if (IS_DVT && vsync1 < 60)
+		vsync1 = 60;
+	if (!info->monspecs.vfmax)
+		info->monspecs.vfmax = vsync2;
+	if (!info->monspecs.vfmin)
+		info->monspecs.vfmin = vsync1;
+	if (vsync2 < vsync1) 
+		info->monspecs.vfmin = vsync2;
+}
+
+/**
+ * i810_init_defaults - initializes default values to use
+ * @par: pointer to i810fb_par structure
+ * @info: pointer to current fb_info structure
+ */
+static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info)
+{
+	mutex_init(&par->open_lock);
+
+	if (voffset) 
+		v_offset_default = voffset;
+	else if (par->aperture.size > 32 * 1024 * 1024)
+		v_offset_default = 16;
+	else
+		v_offset_default = 8;
+
+	if (!vram) 
+		vram = 1;
+
+	if (accel) 
+		par->dev_flags |= HAS_ACCELERATION;
+
+	if (sync) 
+		par->dev_flags |= ALWAYS_SYNC;
+
+	par->ddc_num = (ddc3 ? 3 : 2);
+
+	if (bpp < 8)
+		bpp = 8;
+	
+	par->i810fb_ops = i810fb_ops;
+
+	if (xres)
+		info->var.xres = xres;
+	else
+		info->var.xres = 640;
+
+	if (yres)
+		info->var.yres = yres;
+	else
+		info->var.yres = 480;
+
+	if (!vyres) 
+		vyres = (vram << 20)/(info->var.xres*bpp >> 3);
+
+	info->var.yres_virtual = vyres;
+	info->var.bits_per_pixel = bpp;
+
+	if (dcolor)
+		info->var.nonstd = 1;
+
+	if (par->dev_flags & HAS_ACCELERATION) 
+		info->var.accel_flags = 1;
+
+	i810_init_monspecs(info);
+}
+	
+/**
+ * i810_init_device - initialize device
+ * @par: pointer to i810fb_par structure
+ */
+static void i810_init_device(struct i810fb_par *par)
+{
+	u8 reg;
+	u8 __iomem *mmio = par->mmio_start_virtual;
+
+	if (mtrr) set_mtrr(par);
+
+	i810_init_cursor(par);
+
+	/* mvo: enable external vga-connector (for laptops) */
+	if (extvga) {
+		i810_writel(HVSYNC, mmio, 0);
+		i810_writel(PWR_CLKC, mmio, 3);
+	}
+
+	pci_read_config_byte(par->dev, 0x50, &reg);
+	reg &= FREQ_MASK;
+	par->mem_freq = (reg) ? 133 : 100;
+
+}
+
+static int i810_allocate_pci_resource(struct i810fb_par *par,
+				      const struct pci_device_id *entry)
+{
+	int err;
+
+	if ((err = pci_enable_device(par->dev))) { 
+		printk("i810fb_init: cannot enable device\n");
+		return err;		
+	}
+	par->res_flags |= PCI_DEVICE_ENABLED;
+
+	if (pci_resource_len(par->dev, 0) > 512 * 1024) {
+		par->aperture.physical = pci_resource_start(par->dev, 0);
+		par->aperture.size = pci_resource_len(par->dev, 0);
+		par->mmio_start_phys = pci_resource_start(par->dev, 1);
+	} else {
+		par->aperture.physical = pci_resource_start(par->dev, 1);
+		par->aperture.size = pci_resource_len(par->dev, 1);
+		par->mmio_start_phys = pci_resource_start(par->dev, 0);
+	}
+	if (!par->aperture.size) {
+		printk("i810fb_init: device is disabled\n");
+		return -ENOMEM;
+	}
+
+	if (!request_mem_region(par->aperture.physical, 
+				par->aperture.size, 
+				i810_pci_list[entry->driver_data])) {
+		printk("i810fb_init: cannot request framebuffer region\n");
+		return -ENODEV;
+	}
+	par->res_flags |= FRAMEBUFFER_REQ;
+
+	par->aperture.virtual = ioremap_nocache(par->aperture.physical, 
+					par->aperture.size);
+	if (!par->aperture.virtual) {
+		printk("i810fb_init: cannot remap framebuffer region\n");
+		return -ENODEV;
+	}
+  
+	if (!request_mem_region(par->mmio_start_phys, 
+				MMIO_SIZE, 
+				i810_pci_list[entry->driver_data])) {
+		printk("i810fb_init: cannot request mmio region\n");
+		return -ENODEV;
+	}
+	par->res_flags |= MMIO_REQ;
+
+	par->mmio_start_virtual = ioremap_nocache(par->mmio_start_phys, 
+						  MMIO_SIZE);
+	if (!par->mmio_start_virtual) {
+		printk("i810fb_init: cannot remap mmio region\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void i810fb_find_init_mode(struct fb_info *info)
+{
+	struct fb_videomode mode;
+	struct fb_var_screeninfo var;
+	struct fb_monspecs *specs = &info->monspecs;
+	int found = 0;
+#ifdef CONFIG_FB_I810_I2C
+	int i;
+	int err = 1;
+	struct i810fb_par *par = info->par;
+#endif
+
+	INIT_LIST_HEAD(&info->modelist);
+	memset(&mode, 0, sizeof(struct fb_videomode));
+	var = info->var;
+#ifdef CONFIG_FB_I810_I2C
+	i810_create_i2c_busses(par);
+
+	for (i = 0; i < par->ddc_num + 1; i++) {
+		err = i810_probe_i2c_connector(info, &par->edid, i);
+		if (!err)
+			break;
+	}
+
+	if (!err)
+		printk("i810fb_init_pci: DDC probe successful\n");
+
+	fb_edid_to_monspecs(par->edid, specs);
+
+	if (specs->modedb == NULL)
+		printk("i810fb_init_pci: Unable to get Mode Database\n");
+
+	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
+				 &info->modelist);
+	if (specs->modedb != NULL) {
+		const struct fb_videomode *m;
+
+		if (xres && yres) {
+			if ((m = fb_find_best_mode(&var, &info->modelist))) {
+				mode = *m;
+				found  = 1;
+			}
+		}
+
+		if (!found) {
+			m = fb_find_best_display(&info->monspecs, &info->modelist);
+			mode = *m;
+			found = 1;
+		}
+
+		fb_videomode_to_var(&var, &mode);
+	}
+#endif
+	if (mode_option)
+		fb_find_mode(&var, info, mode_option, specs->modedb,
+			     specs->modedb_len, (found) ? &mode : NULL,
+			     info->var.bits_per_pixel);
+
+	info->var = var;
+	fb_destroy_modedb(specs->modedb);
+	specs->modedb = NULL;
+}
+
+#ifndef MODULE
+static int i810fb_setup(char *options)
+{
+	char *this_opt, *suffix = NULL;
+
+	if (!options || !*options)
+		return 0;
+	
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "mtrr", 4))
+			mtrr = 1;
+		else if (!strncmp(this_opt, "accel", 5))
+			accel = 1;
+		else if (!strncmp(this_opt, "extvga", 6))
+			extvga = 1;
+		else if (!strncmp(this_opt, "sync", 4))
+			sync = 1;
+		else if (!strncmp(this_opt, "vram:", 5))
+			vram = (simple_strtoul(this_opt+5, NULL, 0));
+		else if (!strncmp(this_opt, "voffset:", 8))
+			voffset = (simple_strtoul(this_opt+8, NULL, 0));
+		else if (!strncmp(this_opt, "xres:", 5))
+			xres = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "yres:", 5))
+			yres = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "vyres:", 6))
+			vyres = simple_strtoul(this_opt+6, NULL, 0);
+		else if (!strncmp(this_opt, "bpp:", 4))
+			bpp = simple_strtoul(this_opt+4, NULL, 0);
+		else if (!strncmp(this_opt, "hsync1:", 7)) {
+			hsync1 = simple_strtoul(this_opt+7, &suffix, 0);
+			if (strncmp(suffix, "H", 1)) 
+				hsync1 *= 1000;
+		} else if (!strncmp(this_opt, "hsync2:", 7)) {
+			hsync2 = simple_strtoul(this_opt+7, &suffix, 0);
+			if (strncmp(suffix, "H", 1)) 
+				hsync2 *= 1000;
+		} else if (!strncmp(this_opt, "vsync1:", 7)) 
+			vsync1 = simple_strtoul(this_opt+7, NULL, 0);
+		else if (!strncmp(this_opt, "vsync2:", 7))
+			vsync2 = simple_strtoul(this_opt+7, NULL, 0);
+		else if (!strncmp(this_opt, "dcolor", 6))
+			dcolor = 1;
+		else if (!strncmp(this_opt, "ddc3", 4))
+			ddc3 = true;
+		else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+#endif
+
+static int i810fb_init_pci(struct pci_dev *dev,
+			   const struct pci_device_id *entry)
+{
+	struct fb_info    *info;
+	struct i810fb_par *par = NULL;
+	struct fb_videomode mode;
+	int err = -1, vfreq, hfreq, pixclock;
+
+	info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	par = info->par;
+	par->dev = dev;
+
+	if (!(info->pixmap.addr = kzalloc(8*1024, GFP_KERNEL))) {
+		i810fb_release_resource(info, par);
+		return -ENOMEM;
+	}
+	info->pixmap.size = 8*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if ((err = i810_allocate_pci_resource(par, entry))) {
+		i810fb_release_resource(info, par);
+		return err;
+	}
+
+	i810_init_defaults(par, info);
+
+	if ((err = i810_alloc_agp_mem(info))) {
+		i810fb_release_resource(info, par);
+		return err;
+	}
+
+	i810_init_device(par);        
+
+	info->screen_base = par->fb.virtual;
+	info->fbops = &par->i810fb_ops;
+	info->pseudo_palette = par->pseudo_palette;
+	fb_alloc_cmap(&info->cmap, 256, 0);
+	i810fb_find_init_mode(info);
+
+	if ((err = info->fbops->fb_check_var(&info->var, info))) {
+		i810fb_release_resource(info, par);
+		return err;
+	}
+
+	fb_var_to_videomode(&mode, &info->var);
+	fb_add_videomode(&mode, &info->modelist);
+
+	i810fb_init_ringbuffer(info);
+	err = register_framebuffer(info);
+
+	if (err < 0) {
+    		i810fb_release_resource(info, par); 
+		printk("i810fb_init: cannot register framebuffer device\n");
+    		return err;  
+    	}   
+
+	pci_set_drvdata(dev, info);
+	pixclock = 1000000000/(info->var.pixclock);
+	pixclock *= 1000;
+	hfreq = pixclock/(info->var.xres + info->var.left_margin + 
+			  info->var.hsync_len + info->var.right_margin);
+	vfreq = hfreq/(info->var.yres + info->var.upper_margin +
+		       info->var.vsync_len + info->var.lower_margin);
+
+      	printk("I810FB: fb%d         : %s v%d.%d.%d%s\n"
+      	       "I810FB: Video RAM   : %dK\n" 
+	       "I810FB: Monitor     : H: %d-%d KHz V: %d-%d Hz\n"
+	       "I810FB: Mode        : %dx%d-%dbpp@%dHz\n",
+	       info->node,
+	       i810_pci_list[entry->driver_data],
+	       VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION,
+	       (int) par->fb.size>>10, info->monspecs.hfmin/1000,
+	       info->monspecs.hfmax/1000, info->monspecs.vfmin,
+	       info->monspecs.vfmax, info->var.xres, 
+	       info->var.yres, info->var.bits_per_pixel, vfreq);
+	return 0;
+}
+
+/***************************************************************
+ *                     De-initialization                        *
+ ***************************************************************/
+
+static void i810fb_release_resource(struct fb_info *info, 
+				    struct i810fb_par *par)
+{
+	struct gtt_data *gtt = &par->i810_gtt;
+	unset_mtrr(par);
+
+	i810_delete_i2c_busses(par);
+
+	if (par->i810_gtt.i810_cursor_memory)
+		agp_free_memory(gtt->i810_cursor_memory);
+	if (par->i810_gtt.i810_fb_memory)
+		agp_free_memory(gtt->i810_fb_memory);
+
+	if (par->mmio_start_virtual)
+		iounmap(par->mmio_start_virtual);
+	if (par->aperture.virtual)
+		iounmap(par->aperture.virtual);
+	kfree(par->edid);
+	if (par->res_flags & FRAMEBUFFER_REQ)
+		release_mem_region(par->aperture.physical,
+				   par->aperture.size);
+	if (par->res_flags & MMIO_REQ)
+		release_mem_region(par->mmio_start_phys, MMIO_SIZE);
+
+	framebuffer_release(info);
+
+}
+
+static void __exit i810fb_remove_pci(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct i810fb_par *par = info->par;
+
+	unregister_framebuffer(info);  
+	i810fb_release_resource(info, par);
+	printk("cleanup_module:  unloaded i810 framebuffer device\n");
+}                                                	
+
+#ifndef MODULE
+static int i810fb_init(void)
+{
+	char *option = NULL;
+
+	if (fb_get_options("i810fb", &option))
+		return -ENODEV;
+	i810fb_setup(option);
+
+	return pci_register_driver(&i810fb_driver);
+}
+#endif 
+
+/*********************************************************************
+ *                          Modularization                           *
+ *********************************************************************/
+
+#ifdef MODULE
+
+static int i810fb_init(void)
+{
+	hsync1 *= 1000;
+	hsync2 *= 1000;
+
+	return pci_register_driver(&i810fb_driver);
+}
+
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB" 
+		 " (default=4)");
+module_param(voffset, int, 0);
+MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer "
+                 "memory (0 to maximum aperture size), in MiB (default = 48)");
+module_param(bpp, int, 0);
+MODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel"
+		 " (default = 8)");
+module_param(xres, int, 0);
+MODULE_PARM_DESC(xres, "Horizontal resolution in pixels (default = 640)");
+module_param(yres, int, 0);
+MODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)");
+module_param(vyres,int, 0);
+MODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines"
+		 " (default = 480)");
+module_param(hsync1, int, 0);
+MODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz"
+		 " (default = 29)");
+module_param(hsync2, int, 0);
+MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz"
+		 " (default = 30)");
+module_param(vsync1, int, 0);
+MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz"
+		 " (default = 50)");
+module_param(vsync2, int, 0);
+MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz" 
+		 " (default = 60)");
+module_param(accel, bool, 0);
+MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
+module_param(mtrr, bool, 0);
+MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
+module_param(sync, bool, 0);
+MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
+		 " (default = 0)");
+module_param(dcolor, bool, 0);
+MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
+		 " (default = 0 = TrueColor)");
+module_param(ddc3, bool, 0);
+MODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
+
+MODULE_AUTHOR("Tony A. Daplas");
+MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
+		   " compatible cards");
+MODULE_LICENSE("GPL"); 
+
+static void __exit i810fb_exit(void)
+{
+	pci_unregister_driver(&i810fb_driver);
+}
+module_exit(i810fb_exit);
+
+#endif /* MODULE */
+
+module_init(i810fb_init);
diff --git a/drivers/video/fbdev/i810/i810_main.h b/drivers/video/fbdev/i810/i810_main.h
new file mode 100644
index 000000000000..a25afaa534ba
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810_main.h
@@ -0,0 +1,95 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/i810fb_main.h -- Intel 810 frame buffer device 
+ *                                       main header file
+ *
+ *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved      
+ *
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef __I810_MAIN_H__
+#define __I810_MAIN_H__
+
+/* Video Timings */
+extern void round_off_xres         (u32 *xres);
+extern void round_off_yres         (u32 *xres, u32 *yres);
+extern u32 i810_get_watermark      (const struct fb_var_screeninfo *var,
+			            struct i810fb_par *par);
+extern void i810fb_encode_registers(const struct fb_var_screeninfo *var,
+				    struct i810fb_par *par, u32 xres, u32 yres);
+extern void i810fb_fill_var_timings(struct fb_var_screeninfo *var);
+				    
+/* Accelerated Functions */
+extern void i810fb_fillrect (struct fb_info *p, 
+			     const struct fb_fillrect *rect);
+extern void i810fb_copyarea (struct fb_info *p, 
+			     const struct fb_copyarea *region);
+extern void i810fb_imageblit(struct fb_info *p, const struct fb_image *image);
+extern int  i810fb_sync     (struct fb_info *p);
+
+extern void i810fb_init_ringbuffer(struct fb_info *info);
+extern void i810fb_load_front     (u32 offset, struct fb_info *info);
+
+#ifdef CONFIG_FB_I810_I2C
+/* I2C */
+extern int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+				    int conn);
+extern void i810_create_i2c_busses(struct i810fb_par *par);
+extern void i810_delete_i2c_busses(struct i810fb_par *par);
+#else
+static inline int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+				    int conn)
+{
+	return 1;
+}
+static inline void i810_create_i2c_busses(struct i810fb_par *par) { }
+static inline void i810_delete_i2c_busses(struct i810fb_par *par) { }
+#endif
+
+/* Conditionals */
+#ifdef CONFIG_X86
+static inline void flush_cache(void)
+{
+	asm volatile ("wbinvd":::"memory");
+}
+#else
+#define flush_cache() do { } while(0)
+#endif 
+
+#ifdef CONFIG_MTRR
+
+#include <asm/mtrr.h>
+
+static inline void set_mtrr(struct i810fb_par *par)
+{
+	par->mtrr_reg = mtrr_add((u32) par->aperture.physical, 
+		 par->aperture.size, MTRR_TYPE_WRCOMB, 1);
+	if (par->mtrr_reg < 0) {
+		printk(KERN_ERR "set_mtrr: unable to set MTRR\n");
+		return;
+	}
+	par->dev_flags |= HAS_MTRR;
+}
+static inline void unset_mtrr(struct i810fb_par *par)
+{
+  	if (par->dev_flags & HAS_MTRR) 
+  		mtrr_del(par->mtrr_reg, (u32) par->aperture.physical, 
+			 par->aperture.size); 
+}
+#else
+#define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n")
+
+#define unset_mtrr(x) do { } while (0)
+#endif /* CONFIG_MTRR */
+
+#ifdef CONFIG_FB_I810_GTF
+#define IS_DVT (0)
+#else
+#define IS_DVT (1)
+#endif
+
+#endif /* __I810_MAIN_H__ */
diff --git a/drivers/video/fbdev/i810/i810_regs.h b/drivers/video/fbdev/i810/i810_regs.h
new file mode 100644
index 000000000000..91c6bd9d0d0d
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810_regs.h
@@ -0,0 +1,275 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/i810_regs.h -- Intel 810/815 Register List
+ *
+ *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved      
+ *
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+
+/*
+ * Intel 810 Chipset Family PRM 15 3.1 
+ * GC Register Memory Address Map 
+ *
+ * Based on:
+ * Intel (R) 810 Chipset Family 
+ * Programmer s Reference Manual 
+ * November 1999 
+ * Revision 1.0 
+ * Order Number: 298026-001 R
+ *
+ * All GC registers are memory-mapped. In addition, the VGA and extended VGA registers 
+ * are I/O mapped. 
+ */
+ 
+#ifndef __I810_REGS_H__
+#define __I810_REGS_H__
+
+/*  Instruction and Interrupt Control Registers (01000h 02FFFh) */
+#define FENCE                 0x02000                
+#define PGTBL_CTL             0x02020 
+#define PGTBL_ER              0x02024               
+#define    LRING              0x02030
+#define    IRING              0x02040
+#define HWS_PGA               0x02080 
+#define IPEIR                 0x02088
+#define IPEHR                 0x0208C 
+#define INSTDONE              0x02090 
+#define NOPID                 0x02094
+#define HWSTAM                0x02098 
+#define IER                   0x020A0
+#define IIR                   0x020A4
+#define IMR                   0x020A8 
+#define ISR                   0x020AC 
+#define EIR                   0x020B0 
+#define EMR                   0x020B4 
+#define ESR                   0x020B8 
+#define INSTPM                0x020C0
+#define INSTPS                0x020C4 
+#define BBP_PTR               0x020C8 
+#define ABB_SRT               0x020CC
+#define ABB_END               0x020D0
+#define DMA_FADD              0x020D4 
+#define FW_BLC                0x020D8
+#define MEM_MODE              0x020DC        
+
+/*  Memory Control Registers (03000h 03FFFh) */
+#define DRT                   0x03000
+#define DRAMCL                0x03001
+#define DRAMCH                0x03002
+ 
+
+/* Span Cursor Registers (04000h 04FFFh) */
+#define UI_SC_CTL             0x04008 
+
+/* I/O Control Registers (05000h 05FFFh) */
+#define HVSYNC                0x05000 
+#define GPIOA                 0x05010
+#define GPIOB                 0x05014 
+#define GPIOC                 0x0501C
+
+/* Clock Control and Power Management Registers (06000h 06FFFh) */
+#define DCLK_0D               0x06000
+#define DCLK_1D               0x06004
+#define DCLK_2D               0x06008
+#define LCD_CLKD              0x0600C
+#define DCLK_0DS              0x06010
+#define PWR_CLKC              0x06014
+
+/* Graphics Translation Table Range Definition (10000h 1FFFFh) */
+#define GTT                   0x10000  
+
+/*  Overlay Registers (30000h 03FFFFh) */
+#define OVOADDR               0x30000
+#define DOVOSTA               0x30008
+#define GAMMA                 0x30010
+#define OBUF_0Y               0x30100
+#define OBUF_1Y               0x30104
+#define OBUF_0U               0x30108
+#define OBUF_0V               0x3010C
+#define OBUF_1U               0x30110
+#define OBUF_1V               0x30114 
+#define OVOSTRIDE             0x30118
+#define YRGB_VPH              0x3011C
+#define UV_VPH                0x30120
+#define HORZ_PH               0x30124
+#define INIT_PH               0x30128
+#define DWINPOS               0x3012C 
+#define DWINSZ                0x30130
+#define SWID                  0x30134
+#define SWIDQW                0x30138
+#define SHEIGHT               0x3013F
+#define YRGBSCALE             0x30140 
+#define UVSCALE               0x30144
+#define OVOCLRCO              0x30148
+#define OVOCLRC1              0x3014C
+#define DCLRKV                0x30150
+#define DLCRKM                0x30154
+#define SCLRKVH               0x30158
+#define SCLRKVL               0x3015C
+#define SCLRKM                0x30160
+#define OVOCONF               0x30164
+#define OVOCMD                0x30168
+#define AWINPOS               0x30170
+#define AWINZ                 0x30174
+
+/*  BLT Engine Status (40000h 4FFFFh) (Software Debug) */
+#define BR00                  0x40000
+#define BRO1                  0x40004
+#define BR02                  0x40008
+#define BR03                  0x4000C
+#define BR04                  0x40010
+#define BR05                  0x40014
+#define BR06                  0x40018
+#define BR07                  0x4001C
+#define BR08                  0x40020
+#define BR09                  0x40024
+#define BR10                  0x40028
+#define BR11                  0x4002C
+#define BR12                  0x40030
+#define BR13                  0x40034
+#define BR14                  0x40038
+#define BR15                  0x4003C
+#define BR16                  0x40040
+#define BR17                  0x40044
+#define BR18                  0x40048
+#define BR19                  0x4004C
+#define SSLADD                0x40074
+#define DSLH                  0x40078
+#define DSLRADD               0x4007C
+
+
+/* LCD/TV-Out and HW DVD Registers (60000h 6FFFFh) */
+/* LCD/TV-Out */
+#define HTOTAL                0x60000
+#define HBLANK                0x60004
+#define HSYNC                 0x60008
+#define VTOTAL                0x6000C
+#define VBLANK                0x60010
+#define VSYNC                 0x60014
+#define LCDTV_C               0x60018
+#define OVRACT                0x6001C
+#define BCLRPAT               0x60020
+
+/*  Display and Cursor Control Registers (70000h 7FFFFh) */
+#define DISP_SL               0x70000
+#define DISP_SLC              0x70004
+#define PIXCONF               0x70008
+#define PIXCONF1              0x70009
+#define BLTCNTL               0x7000C
+#define SWF                   0x70014
+#define DPLYBASE              0x70020
+#define DPLYSTAS              0x70024
+#define CURCNTR               0x70080
+#define CURBASE               0x70084
+#define CURPOS                0x70088
+
+
+/* VGA Registers */
+
+/* SMRAM Registers */
+#define SMRAM                 0x10
+
+/* Graphics Control Registers */
+#define GR_INDEX              0x3CE
+#define GR_DATA               0x3CF
+
+#define GR10                  0x10
+#define GR11                  0x11
+
+/* CRT Controller Registers */
+#define CR_INDEX_MDA          0x3B4
+#define CR_INDEX_CGA          0x3D4
+#define CR_DATA_MDA           0x3B5
+#define CR_DATA_CGA           0x3D5
+
+#define CR30                  0x30
+#define CR31                  0x31
+#define CR32                  0x32
+#define CR33                  0x33
+#define CR35                  0x35
+#define CR39                  0x39
+#define CR40                  0x40
+#define CR41                  0x41
+#define CR42                  0x42
+#define CR70                  0x70
+#define CR80                  0x80 
+#define CR81                  0x82
+
+/* Extended VGA Registers */
+
+/* General Control and Status Registers */
+#define ST00                  0x3C2
+#define ST01_MDA              0x3BA
+#define ST01_CGA              0x3DA
+#define FRC_READ              0x3CA
+#define FRC_WRITE_MDA         0x3BA
+#define FRC_WRITE_CGA         0x3DA
+#define MSR_READ              0x3CC
+#define MSR_WRITE             0x3C2
+
+/* Sequencer Registers */
+#define SR_INDEX              0x3C4
+#define SR_DATA               0x3C5
+
+#define SR01                  0x01
+#define SR02                  0x02
+#define SR03                  0x03
+#define SR04                  0x04
+#define SR07                  0x07
+
+/* Graphics Controller Registers */
+#define GR00                  0x00   
+#define GR01                  0x01
+#define GR02                  0x02
+#define GR03                  0x03
+#define GR04                  0x04
+#define GR05                  0x05
+#define GR06                  0x06
+#define GR07                  0x07
+#define GR08                  0x08  
+
+/* Attribute Controller Registers */
+#define ATTR_WRITE              0x3C0
+#define ATTR_READ               0x3C1
+
+/* VGA Color Palette Registers */
+
+/* CLUT */
+#define CLUT_DATA             0x3C9        /* DACDATA */
+#define CLUT_INDEX_READ       0x3C7        /* DACRX */
+#define CLUT_INDEX_WRITE      0x3C8        /* DACWX */
+#define DACMASK               0x3C6
+
+/* CRT Controller Registers */
+#define CR00                  0x00
+#define CR01                  0x01
+#define CR02                  0x02
+#define CR03                  0x03
+#define CR04                  0x04
+#define CR05                  0x05
+#define CR06                  0x06
+#define CR07                  0x07
+#define CR08                  0x08
+#define CR09                  0x09
+#define CR0A                  0x0A
+#define CR0B                  0x0B
+#define CR0C                  0x0C
+#define CR0D                  0x0D
+#define CR0E                  0x0E
+#define CR0F                  0x0F
+#define CR10                  0x10
+#define CR11                  0x11
+#define CR12                  0x12
+#define CR13                  0x13
+#define CR14                  0x14
+#define CR15                  0x15
+#define CR16                  0x16
+#define CR17                  0x17
+#define CR18                  0x18
+
+#endif /* __I810_REGS_H__ */
diff --git a/drivers/video/fbdev/igafb.c b/drivers/video/fbdev/igafb.c
new file mode 100644
index 000000000000..486f18897414
--- /dev/null
+++ b/drivers/video/fbdev/igafb.c
@@ -0,0 +1,579 @@
+/*
+ *  linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
+ *
+ *      Copyright (C) 1998  Vladimir Roganov and Gleb Raiko
+ *
+ *  This driver is partly based on the Frame buffer device for ATI Mach64
+ *  and partially on VESA-related code.
+ *
+ *      Copyright (C) 1997-1998  Geert Uytterhoeven
+ *      Copyright (C) 1998  Bernd Harries
+ *      Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+/******************************************************************************
+
+  TODO:
+       Despite of IGA Card has advanced graphic acceleration, 
+       initial version is almost dummy and does not support it.
+       Support for video modes and acceleration must be added
+       together with accelerated X-Windows driver implementation.
+
+       Most important thing at this moment is that we have working
+       JavaEngine1  console & X  with new console interface.
+
+******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/nvram.h>
+
+#include <asm/io.h>
+
+#ifdef CONFIG_SPARC
+#include <asm/prom.h>
+#include <asm/pcic.h>
+#endif
+
+#include <video/iga.h>
+
+struct pci_mmap_map {
+    unsigned long voff;
+    unsigned long poff;
+    unsigned long size;
+    unsigned long prot_flag;
+    unsigned long prot_mask;
+};
+
+struct iga_par {
+	struct pci_mmap_map *mmap_map;
+	unsigned long frame_buffer_phys;
+	unsigned long io_base;
+};
+
+struct fb_info fb_info;
+
+struct fb_fix_screeninfo igafb_fix __initdata = {
+        .id		= "IGA 1682",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.mmio_len 	= 1000
+};
+
+struct fb_var_screeninfo default_var = {
+	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+	.xres		= 640,
+	.yres		= 480,
+	.xres_virtual	= 640,
+	.yres_virtual	= 480,
+	.bits_per_pixel	= 8,
+	.red		= {0, 8, 0 },
+	.green		= {0, 8, 0 },
+	.blue		= {0, 8, 0 },
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= FB_ACCEL_NONE,
+	.pixclock	= 39722,
+	.left_margin	= 48,
+	.right_margin	= 16,
+	.upper_margin	= 33,
+	.lower_margin	= 10,
+	.hsync_len	= 96,
+	.vsync_len	= 2,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
+#ifdef CONFIG_SPARC
+struct fb_var_screeninfo default_var_1024x768 __initdata = {
+	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+	.xres		= 1024,
+	.yres		= 768,
+	.xres_virtual	= 1024,
+	.yres_virtual	= 768,
+	.bits_per_pixel	= 8,
+	.red		= {0, 8, 0 },
+	.green		= {0, 8, 0 },
+	.blue		= {0, 8, 0 },
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= FB_ACCEL_NONE,
+	.pixclock	= 12699,
+	.left_margin	= 176,
+	.right_margin	= 16,
+	.upper_margin	= 28,
+	.lower_margin	= 1,
+	.hsync_len	= 96,
+	.vsync_len	= 3,
+	.vmode		= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+struct fb_var_screeninfo default_var_1152x900 __initdata = {
+	/* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
+	.xres		= 1152,
+	.yres		= 900,
+	.xres_virtual	= 1152,
+	.yres_virtual	= 900,
+	.bits_per_pixel	= 8,
+	.red		= { 0, 8, 0 },
+	.green		= { 0, 8, 0 },
+	.blue		= { 0, 8, 0 },
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= FB_ACCEL_NONE,
+	.pixclock	= 9091,
+	.left_margin	= 234,
+	.right_margin	= 24,
+	.upper_margin	= 34,
+	.lower_margin	= 3,
+	.hsync_len	= 100,
+	.vsync_len	= 3,
+	.vmode		= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+struct fb_var_screeninfo default_var_1280x1024 __initdata = {
+	/* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
+	.xres		= 1280,
+	.yres		= 1024,
+	.xres_virtual	= 1280,
+	.yres_virtual	= 1024,
+	.bits_per_pixel	= 8,
+	.red		= {0, 8, 0 }, 
+	.green		= {0, 8, 0 },
+	.blue		= {0, 8, 0 },
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= 0,
+	.pixclock	= 7408,
+	.left_margin	= 248,
+	.right_margin	= 16,
+	.upper_margin	= 38,
+	.lower_margin	= 1,
+	.hsync_len	= 144,
+	.vsync_len	= 3,
+	.vmode		= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+/*
+ *   Memory-mapped I/O functions for Sparc PCI
+ *
+ * On sparc we happen to access I/O with memory mapped functions too.
+ */ 
+#define pci_inb(par, reg)        readb(par->io_base+(reg))
+#define pci_outb(par, val, reg)  writeb(val, par->io_base+(reg))
+
+static inline unsigned int iga_inb(struct iga_par *par, unsigned int reg,
+				   unsigned int idx)
+{
+        pci_outb(par, idx, reg);
+        return pci_inb(par, reg + 1);
+}
+
+static inline void iga_outb(struct iga_par *par, unsigned char val,
+			    unsigned int reg, unsigned int idx )
+{
+        pci_outb(par, idx, reg);
+        pci_outb(par, val, reg+1);
+}
+
+#endif /* CONFIG_SPARC */
+
+/*
+ *  Very important functionality for the JavaEngine1 computer:
+ *  make screen border black (usign special IGA registers) 
+ */
+static void iga_blank_border(struct iga_par *par)
+{
+        int i;
+#if 0
+	/*
+	 * PROM does this for us, so keep this code as a reminder
+	 * about required read from 0x3DA and writing of 0x20 in the end.
+	 */
+	(void) pci_inb(par, 0x3DA);		/* required for every access */
+	pci_outb(par, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
+	(void) pci_inb(par, IGA_ATTR_CTL+1);
+	pci_outb(par, 0x38, IGA_ATTR_CTL);
+	pci_outb(par, 0x20, IGA_ATTR_CTL);	/* re-enable visual */
+#endif
+	/*
+	 * This does not work as it was designed because the overscan
+	 * color is looked up in the palette. Therefore, under X11
+	 * overscan changes color.
+	 */
+	for (i=0; i < 3; i++)
+		iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
+}
+
+#ifdef CONFIG_SPARC
+static int igafb_mmap(struct fb_info *info,
+		      struct vm_area_struct *vma)
+{
+	struct iga_par *par = (struct iga_par *)info->par;
+	unsigned int size, page, map_size = 0;
+	unsigned long map_offset = 0;
+	int i;
+
+	if (!par->mmap_map)
+		return -ENXIO;
+
+	size = vma->vm_end - vma->vm_start;
+
+	/* Each page, see which map applies */
+	for (page = 0; page < size; ) {
+		map_size = 0;
+		for (i = 0; par->mmap_map[i].size; i++) {
+			unsigned long start = par->mmap_map[i].voff;
+			unsigned long end = start + par->mmap_map[i].size;
+			unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
+
+			if (start > offset)
+				continue;
+			if (offset >= end)
+				continue;
+
+			map_size = par->mmap_map[i].size - (offset - start);
+			map_offset = par->mmap_map[i].poff + (offset - start);
+			break;
+		}
+		if (!map_size) {
+			page += PAGE_SIZE;
+			continue;
+		}
+		if (page + map_size > size)
+			map_size = size - page;
+
+		pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
+		pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
+
+		if (remap_pfn_range(vma, vma->vm_start + page,
+			map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
+			return -EAGAIN;
+
+		page += map_size;
+	}
+
+	if (!map_size)
+		return -EINVAL;
+
+	vma->vm_flags |= VM_IO;
+	return 0;
+}
+#endif /* CONFIG_SPARC */
+
+static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                           unsigned blue, unsigned transp,
+                           struct fb_info *info)
+{
+        /*
+         *  Set a single color register. The values supplied are
+         *  already rounded down to the hardware's capabilities
+         *  (according to the entries in the `var' structure). Return
+         *  != 0 for invalid regno.
+         */
+	struct iga_par *par = (struct iga_par *)info->par;
+
+        if (regno >= info->cmap.len)
+                return 1;
+
+	pci_outb(par, regno, DAC_W_INDEX);
+	pci_outb(par, red,   DAC_DATA);
+	pci_outb(par, green, DAC_DATA);
+	pci_outb(par, blue,  DAC_DATA);
+
+	if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 16:
+			((u16*)(info->pseudo_palette))[regno] = 
+				(regno << 10) | (regno << 5) | regno;
+			break;
+		case 24:
+			((u32*)(info->pseudo_palette))[regno] = 
+				(regno << 16) | (regno << 8) | regno;
+		break;
+		case 32:
+			{ int i;
+			i = (regno << 8) | regno;
+			((u32*)(info->pseudo_palette))[regno] = (i << 16) | i;
+			}
+			break;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Framebuffer option structure
+ */
+static struct fb_ops igafb_ops = {
+	.owner 		= THIS_MODULE,
+	.fb_setcolreg 	= igafb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+#ifdef CONFIG_SPARC
+	.fb_mmap 	= igafb_mmap,
+#endif
+};
+
+static int __init iga_init(struct fb_info *info, struct iga_par *par)
+{
+        char vramsz = iga_inb(par, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) 
+		                                         & MEM_SIZE_ALIAS;
+	int video_cmap_len;
+
+        switch (vramsz) {
+        case MEM_SIZE_1M:
+                info->fix.smem_len = 0x100000;
+                break;
+        case MEM_SIZE_2M:
+                info->fix.smem_len = 0x200000;
+                break;
+        case MEM_SIZE_4M:
+        case MEM_SIZE_RESERVED:
+                info->fix.smem_len = 0x400000;
+                break;
+        }
+
+        if (info->var.bits_per_pixel > 8) 
+                video_cmap_len = 16;
+        else 
+                video_cmap_len = 256;
+
+	info->fbops = &igafb_ops;
+	info->flags = FBINFO_DEFAULT;
+
+	fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
+
+	if (register_framebuffer(info) < 0)
+		return 0;
+
+	fb_info(info, "%s frame buffer device at 0x%08lx [%dMB VRAM]\n",
+		info->fix.id, par->frame_buffer_phys, info->fix.smem_len >> 20);
+
+	iga_blank_border(par); 
+	return 1;
+}
+
+static int __init igafb_init(void)
+{
+        struct fb_info *info;
+        struct pci_dev *pdev;
+        struct iga_par *par;
+	unsigned long addr;
+	int size, iga2000 = 0;
+
+	if (fb_get_options("igafb", NULL))
+		return -ENODEV;
+
+        pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
+                               PCI_DEVICE_ID_INTERG_1682, 0);
+	if (pdev == NULL) {
+		/*
+		 * XXX We tried to use cyber2000fb.c for IGS 2000.
+		 * But it does not initialize the chip in JavaStation-E, alas.
+		 */
+        	pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
+        	if(pdev == NULL) {
+        	        return -ENXIO;
+		}
+		iga2000 = 1;
+	}
+	/* We leak a reference here but as it cannot be unloaded this is
+	   fine. If you write unload code remember to free it in unload */
+	
+	size = sizeof(struct iga_par) + sizeof(u32)*16;
+
+	info = framebuffer_alloc(size, &pdev->dev);
+        if (!info) {
+                printk("igafb_init: can't alloc fb_info\n");
+		 pci_dev_put(pdev);
+                return -ENOMEM;
+        }
+
+	par = info->par;
+
+	if ((addr = pdev->resource[0].start) == 0) {
+                printk("igafb_init: no memory start\n");
+		kfree(info);
+		pci_dev_put(pdev);
+		return -ENXIO;
+	}
+
+	if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) {
+                printk("igafb_init: can't remap %lx[2M]\n", addr);
+		kfree(info);
+		pci_dev_put(pdev);
+		return -ENXIO;
+	}
+
+	par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
+
+#ifdef CONFIG_SPARC
+	/*
+	 * The following is sparc specific and this is why:
+	 *
+	 * IGS2000 has its I/O memory mapped and we want
+	 * to generate memory cycles on PCI, e.g. do ioremap(),
+	 * then readb/writeb() as in Documentation/io-mapping.txt.
+	 *
+	 * IGS1682 is more traditional, it responds to PCI I/O
+	 * cycles, so we want to access it with inb()/outb().
+	 *
+	 * On sparc, PCIC converts CPU memory access within
+	 * phys window 0x3000xxxx into PCI I/O cycles. Therefore
+	 * we may use readb/writeb to access them with IGS1682.
+	 *
+	 * We do not take io_base_phys from resource[n].start
+	 * on IGS1682 because that chip is BROKEN. It does not
+	 * have a base register for I/O. We just "know" what its
+	 * I/O addresses are.
+	 */
+	if (iga2000) {
+		igafb_fix.mmio_start = par->frame_buffer_phys | 0x00800000;
+	} else {
+		igafb_fix.mmio_start = 0x30000000;	/* XXX */
+	}
+	if ((par->io_base = (int) ioremap(igafb_fix.mmio_start, igafb_fix.smem_len)) == 0) {
+                printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start);
+		iounmap((void *)info->screen_base);
+		kfree(info);
+		pci_dev_put(pdev);
+		return -ENXIO;
+	}
+
+	/*
+	 * Figure mmap addresses from PCI config space.
+	 * We need two regions: for video memory and for I/O ports.
+	 * Later one can add region for video coprocessor registers.
+	 * However, mmap routine loops until size != 0, so we put
+	 * one additional region with size == 0. 
+	 */
+
+	par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
+	if (!par->mmap_map) {
+		printk("igafb_init: can't alloc mmap_map\n");
+		iounmap((void *)par->io_base);
+		iounmap(info->screen_base);
+		kfree(info);
+		pci_dev_put(pdev);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Set default vmode and cmode from PROM properties.
+	 */
+	{
+		struct device_node *dp = pci_device_to_OF_node(pdev);
+                int node = dp->node;
+                int width = prom_getintdefault(node, "width", 1024);
+                int height = prom_getintdefault(node, "height", 768);
+                int depth = prom_getintdefault(node, "depth", 8);
+                switch (width) {
+                    case 1024:
+                        if (height == 768)
+                            default_var = default_var_1024x768;
+                        break;
+                    case 1152:
+                        if (height == 900)
+                            default_var = default_var_1152x900;
+                        break;
+                    case 1280:
+                        if (height == 1024)
+                            default_var = default_var_1280x1024;
+                        break;
+                    default:
+                        break;
+                }
+
+                switch (depth) {
+                    case 8:
+                        default_var.bits_per_pixel = 8;
+                        break;
+                    case 16:
+                        default_var.bits_per_pixel = 16;
+                        break;
+                    case 24:
+                        default_var.bits_per_pixel = 24;
+                        break;
+                    case 32:
+                        default_var.bits_per_pixel = 32;
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+#endif
+	igafb_fix.smem_start = (unsigned long) info->screen_base;
+	igafb_fix.line_length = default_var.xres*(default_var.bits_per_pixel/8);
+	igafb_fix.visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+	info->var = default_var;
+	info->fix = igafb_fix;
+	info->pseudo_palette = (void *)(par + 1);
+
+	if (!iga_init(info, par)) {
+		iounmap((void *)par->io_base);
+		iounmap(info->screen_base);
+		kfree(par->mmap_map);
+		kfree(info);
+		return -ENODEV;
+        }
+
+#ifdef CONFIG_SPARC
+	    /*
+	     * Add /dev/fb mmap values.
+	     */
+	    
+	    /* First region is for video memory */
+	    par->mmap_map[0].voff = 0x0;  
+	    par->mmap_map[0].poff = par->frame_buffer_phys & PAGE_MASK;
+	    par->mmap_map[0].size = info->fix.smem_len & PAGE_MASK;
+	    par->mmap_map[0].prot_mask = SRMMU_CACHE;
+	    par->mmap_map[0].prot_flag = SRMMU_WRITE;
+
+	    /* Second region is for I/O ports */
+	    par->mmap_map[1].voff = par->frame_buffer_phys & PAGE_MASK;
+	    par->mmap_map[1].poff = info->fix.smem_start & PAGE_MASK;
+	    par->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
+	    par->mmap_map[1].prot_mask = SRMMU_CACHE;
+	    par->mmap_map[1].prot_flag = SRMMU_WRITE;
+#endif /* CONFIG_SPARC */
+
+	return 0;
+}
+
+static int __init igafb_setup(char *options)
+{
+    char *this_opt;
+
+    if (!options || !*options)
+        return 0;
+
+    while ((this_opt = strsep(&options, ",")) != NULL) {
+    }
+    return 0;
+}
+
+module_init(igafb_init);
+MODULE_LICENSE("GPL");
+static struct pci_device_id igafb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, igafb_pci_tbl);
diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c
new file mode 100644
index 000000000000..aae10ce74f14
--- /dev/null
+++ b/drivers/video/fbdev/imsttfb.c
@@ -0,0 +1,1626 @@
+/*
+ *  drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo
+ *
+ *  This file is derived from the powermac console "imstt" driver:
+ *  Copyright (C) 1997 Sigurdur Asgeirsson
+ *  With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu)
+ *  Modified by Danilo Beuche 1998
+ *  Some register values added by Damien Doligez, INRIA Rocquencourt
+ *  Various cleanups by Paul Mundt (lethal@chaoticdreams.org)
+ *
+ *  This file was written by Ryan Nielsen (ran@krazynet.com)
+ *  Most of the frame buffer device stuff was copied from atyfb.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/uaccess.h>
+
+#if defined(CONFIG_PPC)
+#include <linux/nvram.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include "macmodes.h"
+#endif
+
+#ifndef __powerpc__
+#define eieio()		/* Enforce In-order Execution of I/O */
+#endif
+
+/* TwinTurbo (Cosmo) registers */
+enum {
+	S1SA	=  0, /* 0x00 */
+	S2SA	=  1, /* 0x04 */
+	SP	=  2, /* 0x08 */
+	DSA	=  3, /* 0x0C */
+	CNT	=  4, /* 0x10 */
+	DP_OCTL	=  5, /* 0x14 */
+	CLR	=  6, /* 0x18 */
+	BI	=  8, /* 0x20 */
+	MBC	=  9, /* 0x24 */
+	BLTCTL	= 10, /* 0x28 */
+
+	/* Scan Timing Generator Registers */
+	HES	= 12, /* 0x30 */
+	HEB	= 13, /* 0x34 */
+	HSB	= 14, /* 0x38 */
+	HT	= 15, /* 0x3C */
+	VES	= 16, /* 0x40 */
+	VEB	= 17, /* 0x44 */
+	VSB	= 18, /* 0x48 */
+	VT	= 19, /* 0x4C */
+	HCIV	= 20, /* 0x50 */
+	VCIV	= 21, /* 0x54 */
+	TCDR	= 22, /* 0x58 */
+	VIL	= 23, /* 0x5C */
+	STGCTL	= 24, /* 0x60 */
+
+	/* Screen Refresh Generator Registers */
+	SSR	= 25, /* 0x64 */
+	HRIR	= 26, /* 0x68 */
+	SPR	= 27, /* 0x6C */
+	CMR	= 28, /* 0x70 */
+	SRGCTL	= 29, /* 0x74 */
+
+	/* RAM Refresh Generator Registers */
+	RRCIV	= 30, /* 0x78 */
+	RRSC	= 31, /* 0x7C */
+	RRCR	= 34, /* 0x88 */
+
+	/* System Registers */
+	GIOE	= 32, /* 0x80 */
+	GIO	= 33, /* 0x84 */
+	SCR	= 35, /* 0x8C */
+	SSTATUS	= 36, /* 0x90 */
+	PRC	= 37, /* 0x94 */
+
+#if 0	
+	/* PCI Registers */
+	DVID	= 0x00000000L,
+	SC	= 0x00000004L,
+	CCR	= 0x00000008L,
+	OG	= 0x0000000CL,
+	BARM	= 0x00000010L,
+	BARER	= 0x00000030L,
+#endif
+};
+
+/* IBM 624 RAMDAC Direct Registers */
+enum {
+	PADDRW	= 0x00,
+	PDATA	= 0x04,
+	PPMASK	= 0x08,
+	PADDRR	= 0x0c,
+	PIDXLO	= 0x10,	
+	PIDXHI	= 0x14,	
+	PIDXDATA= 0x18,
+	PIDXCTL	= 0x1c
+};
+
+/* IBM 624 RAMDAC Indirect Registers */
+enum {
+	CLKCTL		= 0x02,	/* (0x01) Miscellaneous Clock Control */
+	SYNCCTL		= 0x03,	/* (0x00) Sync Control */
+	HSYNCPOS	= 0x04,	/* (0x00) Horizontal Sync Position */
+	PWRMNGMT	= 0x05,	/* (0x00) Power Management */
+	DACOP		= 0x06,	/* (0x02) DAC Operation */
+	PALETCTL	= 0x07,	/* (0x00) Palette Control */
+	SYSCLKCTL	= 0x08,	/* (0x01) System Clock Control */
+	PIXFMT		= 0x0a,	/* () Pixel Format  [bpp >> 3 + 2] */
+	BPP8		= 0x0b,	/* () 8 Bits/Pixel Control */
+	BPP16		= 0x0c, /* () 16 Bits/Pixel Control  [bit 1=1 for 565] */
+	BPP24		= 0x0d,	/* () 24 Bits/Pixel Control */
+	BPP32		= 0x0e,	/* () 32 Bits/Pixel Control */
+	PIXCTL1		= 0x10, /* (0x05) Pixel PLL Control 1 */
+	PIXCTL2		= 0x11,	/* (0x00) Pixel PLL Control 2 */
+	SYSCLKN		= 0x15,	/* () System Clock N (System PLL Reference Divider) */
+	SYSCLKM		= 0x16,	/* () System Clock M (System PLL VCO Divider) */
+	SYSCLKP		= 0x17,	/* () System Clock P */
+	SYSCLKC		= 0x18,	/* () System Clock C */
+	/*
+	 * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
+	 * c is charge pump bias which depends on the VCO frequency  
+	 */
+	PIXM0		= 0x20,	/* () Pixel M 0 */
+	PIXN0		= 0x21,	/* () Pixel N 0 */
+	PIXP0		= 0x22,	/* () Pixel P 0 */
+	PIXC0		= 0x23,	/* () Pixel C 0 */
+	CURSCTL		= 0x30,	/* (0x00) Cursor Control */
+	CURSXLO		= 0x31,	/* () Cursor X position, low 8 bits */
+	CURSXHI		= 0x32,	/* () Cursor X position, high 8 bits */
+	CURSYLO		= 0x33,	/* () Cursor Y position, low 8 bits */
+	CURSYHI		= 0x34,	/* () Cursor Y position, high 8 bits */
+	CURSHOTX	= 0x35,	/* () Cursor Hot Spot X */
+	CURSHOTY	= 0x36,	/* () Cursor Hot Spot Y */
+	CURSACCTL	= 0x37,	/* () Advanced Cursor Control Enable */
+	CURSACATTR	= 0x38,	/* () Advanced Cursor Attribute */
+	CURS1R		= 0x40,	/* () Cursor 1 Red */
+	CURS1G		= 0x41,	/* () Cursor 1 Green */
+	CURS1B		= 0x42,	/* () Cursor 1 Blue */
+	CURS2R		= 0x43,	/* () Cursor 2 Red */
+	CURS2G		= 0x44,	/* () Cursor 2 Green */
+	CURS2B		= 0x45,	/* () Cursor 2 Blue */
+	CURS3R		= 0x46,	/* () Cursor 3 Red */
+	CURS3G		= 0x47,	/* () Cursor 3 Green */
+	CURS3B		= 0x48,	/* () Cursor 3 Blue */
+	BORDR		= 0x60,	/* () Border Color Red */
+	BORDG		= 0x61,	/* () Border Color Green */
+	BORDB		= 0x62,	/* () Border Color Blue */
+	MISCTL1		= 0x70,	/* (0x00) Miscellaneous Control 1 */
+	MISCTL2		= 0x71,	/* (0x00) Miscellaneous Control 2 */
+	MISCTL3		= 0x72,	/* (0x00) Miscellaneous Control 3 */
+	KEYCTL		= 0x78	/* (0x00) Key Control/DB Operation */
+};
+
+/* TI TVP 3030 RAMDAC Direct Registers */
+enum {
+	TVPADDRW = 0x00,	/* 0  Palette/Cursor RAM Write Address/Index */
+	TVPPDATA = 0x04,	/* 1  Palette Data RAM Data */
+	TVPPMASK = 0x08,	/* 2  Pixel Read-Mask */
+	TVPPADRR = 0x0c,	/* 3  Palette/Cursor RAM Read Address */
+	TVPCADRW = 0x10,	/* 4  Cursor/Overscan Color Write Address */
+	TVPCDATA = 0x14,	/* 5  Cursor/Overscan Color Data */
+				/* 6  reserved */
+	TVPCADRR = 0x1c,	/* 7  Cursor/Overscan Color Read Address */
+				/* 8  reserved */
+	TVPDCCTL = 0x24,	/* 9  Direct Cursor Control */
+	TVPIDATA = 0x28,	/* 10 Index Data */
+	TVPCRDAT = 0x2c,	/* 11 Cursor RAM Data */
+	TVPCXPOL = 0x30,	/* 12 Cursor-Position X LSB */
+	TVPCXPOH = 0x34,	/* 13 Cursor-Position X MSB */
+	TVPCYPOL = 0x38,	/* 14 Cursor-Position Y LSB */
+	TVPCYPOH = 0x3c,	/* 15 Cursor-Position Y MSB */
+};
+
+/* TI TVP 3030 RAMDAC Indirect Registers */
+enum {
+	TVPIRREV = 0x01,	/* Silicon Revision [RO] */
+	TVPIRICC = 0x06,	/* Indirect Cursor Control 	(0x00) */
+	TVPIRBRC = 0x07,	/* Byte Router Control 	(0xe4) */
+	TVPIRLAC = 0x0f,	/* Latch Control 		(0x06) */
+	TVPIRTCC = 0x18,	/* True Color Control  	(0x80) */
+	TVPIRMXC = 0x19,	/* Multiplex Control		(0x98) */
+	TVPIRCLS = 0x1a,	/* Clock Selection		(0x07) */
+	TVPIRPPG = 0x1c,	/* Palette Page		(0x00) */
+	TVPIRGEC = 0x1d,	/* General Control 		(0x00) */
+	TVPIRMIC = 0x1e,	/* Miscellaneous Control	(0x00) */
+	TVPIRPLA = 0x2c,	/* PLL Address */
+	TVPIRPPD = 0x2d,	/* Pixel Clock PLL Data */
+	TVPIRMPD = 0x2e,	/* Memory Clock PLL Data */
+	TVPIRLPD = 0x2f,	/* Loop Clock PLL Data */
+	TVPIRCKL = 0x30,	/* Color-Key Overlay Low */
+	TVPIRCKH = 0x31,	/* Color-Key Overlay High */
+	TVPIRCRL = 0x32,	/* Color-Key Red Low */
+	TVPIRCRH = 0x33,	/* Color-Key Red High */
+	TVPIRCGL = 0x34,	/* Color-Key Green Low */
+	TVPIRCGH = 0x35,	/* Color-Key Green High */
+	TVPIRCBL = 0x36,	/* Color-Key Blue Low */
+	TVPIRCBH = 0x37,	/* Color-Key Blue High */
+	TVPIRCKC = 0x38,	/* Color-Key Control 		(0x00) */
+	TVPIRMLC = 0x39,	/* MCLK/Loop Clock Control	(0x18) */
+	TVPIRSEN = 0x3a,	/* Sense Test			(0x00) */
+	TVPIRTMD = 0x3b,	/* Test Mode Data */
+	TVPIRRML = 0x3c,	/* CRC Remainder LSB [RO] */
+	TVPIRRMM = 0x3d,	/* CRC Remainder MSB [RO] */
+	TVPIRRMS = 0x3e,	/* CRC  Bit Select [WO] */
+	TVPIRDID = 0x3f,	/* Device ID [RO] 		(0x30) */
+	TVPIRRES = 0xff		/* Software Reset [WO] */
+};
+
+struct initvalues {
+	__u8 addr, value;
+};
+
+static struct initvalues ibm_initregs[] = {
+	{ CLKCTL,	0x21 },
+	{ SYNCCTL,	0x00 },
+	{ HSYNCPOS,	0x00 },
+	{ PWRMNGMT,	0x00 },
+	{ DACOP,	0x02 },
+	{ PALETCTL,	0x00 },
+	{ SYSCLKCTL,	0x01 },
+
+	/*
+	 * Note that colors in X are correct only if all video data is
+	 * passed through the palette in the DAC.  That is, "indirect
+	 * color" must be configured.  This is the case for the IBM DAC
+	 * used in the 2MB and 4MB cards, at least.
+	 */
+	{ BPP8,		0x00 },
+	{ BPP16,	0x01 },
+	{ BPP24,	0x00 },
+	{ BPP32,	0x00 },
+
+	{ PIXCTL1,	0x05 },
+	{ PIXCTL2,	0x00 },
+	{ SYSCLKN,	0x08 },
+	{ SYSCLKM,	0x4f },
+	{ SYSCLKP,	0x00 },
+	{ SYSCLKC,	0x00 },
+	{ CURSCTL,	0x00 },
+	{ CURSACCTL,	0x01 },
+	{ CURSACATTR,	0xa8 },
+	{ CURS1R,	0xff },
+	{ CURS1G,	0xff },
+	{ CURS1B,	0xff },
+	{ CURS2R,	0xff },
+	{ CURS2G,	0xff },
+	{ CURS2B,	0xff },
+	{ CURS3R,	0xff },
+	{ CURS3G,	0xff },
+	{ CURS3B,	0xff },
+	{ BORDR,	0xff },
+	{ BORDG,	0xff },
+	{ BORDB,	0xff },
+	{ MISCTL1,	0x01 },
+	{ MISCTL2,	0x45 },
+	{ MISCTL3,	0x00 },
+	{ KEYCTL,	0x00 }
+};
+
+static struct initvalues tvp_initregs[] = {
+	{ TVPIRICC,	0x00 },
+	{ TVPIRBRC,	0xe4 },
+	{ TVPIRLAC,	0x06 },
+	{ TVPIRTCC,	0x80 },
+	{ TVPIRMXC,	0x4d },
+	{ TVPIRCLS,	0x05 },
+	{ TVPIRPPG,	0x00 },
+	{ TVPIRGEC,	0x00 },
+	{ TVPIRMIC,	0x08 },
+	{ TVPIRCKL,	0xff },
+	{ TVPIRCKH,	0xff },
+	{ TVPIRCRL,	0xff },
+	{ TVPIRCRH,	0xff },
+	{ TVPIRCGL,	0xff },
+	{ TVPIRCGH,	0xff },
+	{ TVPIRCBL,	0xff },
+	{ TVPIRCBH,	0xff },
+	{ TVPIRCKC,	0x00 },
+	{ TVPIRPLA,	0x00 },
+	{ TVPIRPPD,	0xc0 },
+	{ TVPIRPPD,	0xd5 },
+	{ TVPIRPPD,	0xea },
+	{ TVPIRPLA,	0x00 },
+	{ TVPIRMPD,	0xb9 },
+	{ TVPIRMPD,	0x3a },
+	{ TVPIRMPD,	0xb1 },
+	{ TVPIRPLA,	0x00 },
+	{ TVPIRLPD,	0xc1 },
+	{ TVPIRLPD,	0x3d },
+	{ TVPIRLPD,	0xf3 },
+};
+
+struct imstt_regvals {
+	__u32 pitch;
+	__u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
+	__u8 pclk_m, pclk_n, pclk_p;
+	/* Values of the tvp which change depending on colormode x resolution */
+	__u8 mlc[3];	/* Memory Loop Config 0x39 */
+	__u8 lckl_p[3];	/* P value of LCKL PLL */
+};
+
+struct imstt_par {
+	struct imstt_regvals init;
+	__u32 __iomem *dc_regs;
+	unsigned long cmap_regs_phys;
+	__u8 *cmap_regs;
+	__u32 ramdac;
+	__u32 palette[16];
+};
+ 
+enum {
+	IBM = 0,
+	TVP = 1
+};
+
+#define USE_NV_MODES		1
+#define INIT_BPP		8
+#define INIT_XRES		640
+#define INIT_YRES		480
+
+static int inverse = 0;
+static char fontname[40] __initdata = { 0 };
+#if defined(CONFIG_PPC)
+static signed char init_vmode = -1, init_cmode = -1;
+#endif
+
+static struct imstt_regvals tvp_reg_init_2 = {
+	512,
+	0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
+	0xec, 0x2a, 0xf3,
+	{ 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_6 = {
+	640,
+	0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
+	0xef, 0x2e, 0xb2,
+	{ 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_12 = {
+	800,
+	0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
+	0xf6, 0x2e, 0xf2,
+	{ 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_13 = {
+	832,
+	0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
+	0xfe, 0x3e, 0xf1,
+	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_17 = {
+	1024,
+	0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
+	0xfc, 0x3a, 0xf1,
+	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_18 = {
+	1152,
+  	0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 
+	0xfd, 0x3a, 0xf1,
+	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_19 = {
+	1280,
+	0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
+	0xf7, 0x36, 0xf0,
+	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
+};
+
+static struct imstt_regvals tvp_reg_init_20 = {
+	1280,
+	0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
+	0xf0, 0x2d, 0xf0,
+	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
+};
+
+/*
+ * PCI driver prototypes
+ */
+static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void imsttfb_remove(struct pci_dev *pdev);
+
+/*
+ * Register access
+ */
+static inline u32 read_reg_le32(volatile u32 __iomem *base, int regindex)
+{
+#ifdef __powerpc__
+	return in_le32(base + regindex);
+#else
+	return readl(base + regindex);
+#endif
+}
+
+static inline void write_reg_le32(volatile u32 __iomem *base, int regindex, u32 val)
+{
+#ifdef __powerpc__
+	out_le32(base + regindex, val);
+#else
+	writel(val, base + regindex);
+#endif
+}
+
+static __u32
+getclkMHz(struct imstt_par *par)
+{
+	__u32 clk_m, clk_n, clk_p;
+
+	clk_m = par->init.pclk_m;
+	clk_n = par->init.pclk_n;
+	clk_p = par->init.pclk_p;
+
+	return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
+}
+
+static void
+setclkMHz(struct imstt_par *par, __u32 MHz)
+{
+	__u32 clk_m, clk_n, x, stage, spilled;
+
+	clk_m = clk_n = 0;
+	stage = spilled = 0;
+	for (;;) {
+		switch (stage) {
+			case 0:
+				clk_m++;
+				break;
+			case 1:
+				clk_n++;
+				break;
+		}
+		x = 20 * (clk_m + 1) / (clk_n + 1);
+		if (x == MHz)
+			break;
+		if (x > MHz) {
+			spilled = 1;
+			stage = 1;
+		} else if (spilled && x < MHz) {
+			stage = 0;
+		}
+	}
+
+	par->init.pclk_m = clk_m;
+	par->init.pclk_n = clk_n;
+	par->init.pclk_p = 0;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals_ibm(struct imstt_par *par, int xres, int yres)
+{
+	struct imstt_regvals *init = &par->init;
+	__u32 MHz, hes, heb, veb, htp, vtp;
+
+	switch (xres) {
+		case 640:
+			hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2;
+			MHz = 30 /* .25 */ ;
+			break;
+		case 832:
+			hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3;
+			MHz = 57 /* .27_ */ ;
+			break;
+		case 1024:
+			hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3;
+			MHz = 80;
+			break;
+		case 1152:
+			hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3;
+			MHz = 101 /* .6_ */ ;
+			break;
+		case 1280:
+			hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1;
+			MHz = yres == 960 ? 126 : 135;
+			break;
+		case 1600:
+			hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3;
+			MHz = 200;
+			break;
+		default:
+			return NULL;
+	}
+
+	setclkMHz(par, MHz);
+
+	init->hes = hes;
+	init->heb = heb;
+	init->hsb = init->heb + (xres >> 3);
+	init->ht = init->hsb + htp;
+	init->ves = 0x0003;
+	init->veb = veb;
+	init->vsb = init->veb + yres;
+	init->vt = init->vsb + vtp;
+	init->vil = init->vsb;
+
+	init->pitch = xres;
+	return init;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals_tvp(struct imstt_par *par, int xres, int yres)
+{
+	struct imstt_regvals *init;
+
+	switch (xres) {
+		case 512:
+			init = &tvp_reg_init_2;
+			break;
+		case 640:
+			init = &tvp_reg_init_6;
+			break;
+		case 800:
+			init = &tvp_reg_init_12;
+			break;
+		case 832:
+			init = &tvp_reg_init_13;
+			break;
+		case 1024:
+			init = &tvp_reg_init_17;
+			break;
+		case 1152:
+			init = &tvp_reg_init_18;
+			break;
+		case 1280:
+			init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
+			break;
+		default:
+			return NULL;
+	}
+	par->init = *init;
+	return init;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals (struct imstt_par *par, u_int xres, u_int yres)
+{
+	if (par->ramdac == IBM)
+		return compute_imstt_regvals_ibm(par, xres, yres);
+	else
+		return compute_imstt_regvals_tvp(par, xres, yres);
+}
+
+static void
+set_imstt_regvals_ibm (struct imstt_par *par, u_int bpp)
+{
+	struct imstt_regvals *init = &par->init;
+	__u8 pformat = (bpp >> 3) + 2;
+
+	par->cmap_regs[PIDXHI] = 0;		eieio();
+	par->cmap_regs[PIDXLO] = PIXM0;		eieio();
+	par->cmap_regs[PIDXDATA] = init->pclk_m;eieio();
+	par->cmap_regs[PIDXLO] = PIXN0;		eieio();
+	par->cmap_regs[PIDXDATA] = init->pclk_n;eieio();
+	par->cmap_regs[PIDXLO] = PIXP0;		eieio();
+	par->cmap_regs[PIDXDATA] = init->pclk_p;eieio();
+	par->cmap_regs[PIDXLO] = PIXC0;		eieio();
+	par->cmap_regs[PIDXDATA] = 0x02;	eieio();
+
+	par->cmap_regs[PIDXLO] = PIXFMT;	eieio();
+	par->cmap_regs[PIDXDATA] = pformat;	eieio();
+}
+
+static void
+set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp)
+{
+	struct imstt_regvals *init = &par->init;
+	__u8 tcc, mxc, lckl_n, mic;
+	__u8 mlc, lckl_p;
+
+	switch (bpp) {
+		default:
+		case 8:
+			tcc = 0x80;
+			mxc = 0x4d;
+			lckl_n = 0xc1;
+			mlc = init->mlc[0];
+			lckl_p = init->lckl_p[0];
+			break;
+		case 16:
+			tcc = 0x44;
+			mxc = 0x55;
+			lckl_n = 0xe1;
+			mlc = init->mlc[1];
+			lckl_p = init->lckl_p[1];
+			break;
+		case 24:
+			tcc = 0x5e;
+			mxc = 0x5d;
+			lckl_n = 0xf1;
+			mlc = init->mlc[2];
+			lckl_p = init->lckl_p[2];
+			break;
+		case 32:
+			tcc = 0x46;
+			mxc = 0x5d;
+			lckl_n = 0xf1;
+			mlc = init->mlc[2];
+			lckl_p = init->lckl_p[2];
+			break;
+	}
+	mic = 0x08;
+
+	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
+	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
+	par->cmap_regs[TVPIDATA] = init->pclk_m;	eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
+	par->cmap_regs[TVPIDATA] = init->pclk_n;	eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
+	par->cmap_regs[TVPIDATA] = init->pclk_p;	eieio();
+
+	par->cmap_regs[TVPADDRW] = TVPIRTCC;		eieio();
+	par->cmap_regs[TVPIDATA] = tcc;			eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRMXC;		eieio();
+	par->cmap_regs[TVPIDATA] = mxc;			eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRMIC;		eieio();
+	par->cmap_regs[TVPIDATA] = mic;			eieio();
+
+	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
+	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
+	par->cmap_regs[TVPIDATA] = lckl_n;		eieio();
+
+	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
+	par->cmap_regs[TVPIDATA] = 0x15;		eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRMLC;		eieio();
+	par->cmap_regs[TVPIDATA] = mlc;			eieio();
+
+	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
+	par->cmap_regs[TVPIDATA] = 0x2a;		eieio();
+	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
+	par->cmap_regs[TVPIDATA] = lckl_p;		eieio();
+}
+
+static void
+set_imstt_regvals (struct fb_info *info, u_int bpp)
+{
+	struct imstt_par *par = info->par;
+	struct imstt_regvals *init = &par->init;
+	__u32 ctl, pitch, byteswap, scr;
+
+	if (par->ramdac == IBM)
+		set_imstt_regvals_ibm(par, bpp);
+	else
+		set_imstt_regvals_tvp(par, bpp);
+
+  /*
+   * From what I (jsk) can gather poking around with MacsBug,
+   * bits 8 and 9 in the SCR register control endianness
+   * correction (byte swapping).  These bits must be set according
+   * to the color depth as follows:
+   *     Color depth    Bit 9   Bit 8
+   *     ==========     =====   =====
+   *        8bpp          0       0
+   *       16bpp          0       1
+   *       32bpp          1       1
+   */
+	switch (bpp) {
+		default:
+		case 8:
+			ctl = 0x17b1;
+			pitch = init->pitch >> 2;
+			byteswap = 0x000;
+			break;
+		case 16:
+			ctl = 0x17b3;
+			pitch = init->pitch >> 1;
+			byteswap = 0x100;
+			break;
+		case 24:
+			ctl = 0x17b9;
+			pitch = init->pitch - (init->pitch >> 2);
+			byteswap = 0x200;
+			break;
+		case 32:
+			ctl = 0x17b5;
+			pitch = init->pitch;
+			byteswap = 0x300;
+			break;
+	}
+	if (par->ramdac == TVP)
+		ctl -= 0x30;
+
+	write_reg_le32(par->dc_regs, HES, init->hes);
+	write_reg_le32(par->dc_regs, HEB, init->heb);
+	write_reg_le32(par->dc_regs, HSB, init->hsb);
+	write_reg_le32(par->dc_regs, HT, init->ht);
+	write_reg_le32(par->dc_regs, VES, init->ves);
+	write_reg_le32(par->dc_regs, VEB, init->veb);
+	write_reg_le32(par->dc_regs, VSB, init->vsb);
+	write_reg_le32(par->dc_regs, VT, init->vt);
+	write_reg_le32(par->dc_regs, VIL, init->vil);
+	write_reg_le32(par->dc_regs, HCIV, 1);
+	write_reg_le32(par->dc_regs, VCIV, 1);
+	write_reg_le32(par->dc_regs, TCDR, 4);
+	write_reg_le32(par->dc_regs, RRCIV, 1);
+	write_reg_le32(par->dc_regs, RRSC, 0x980);
+	write_reg_le32(par->dc_regs, RRCR, 0x11);
+
+	if (par->ramdac == IBM) {
+		write_reg_le32(par->dc_regs, HRIR, 0x0100);
+		write_reg_le32(par->dc_regs, CMR, 0x00ff);
+		write_reg_le32(par->dc_regs, SRGCTL, 0x0073);
+	} else {
+		write_reg_le32(par->dc_regs, HRIR, 0x0200);
+		write_reg_le32(par->dc_regs, CMR, 0x01ff);
+		write_reg_le32(par->dc_regs, SRGCTL, 0x0003);
+	}
+
+	switch (info->fix.smem_len) {
+		case 0x200000:
+			scr = 0x059d | byteswap;
+			break;
+		/* case 0x400000:
+		   case 0x800000: */
+		default:
+			pitch >>= 1;
+			scr = 0x150dd | byteswap;
+			break;
+	}
+
+	write_reg_le32(par->dc_regs, SCR, scr);
+	write_reg_le32(par->dc_regs, SPR, pitch);
+	write_reg_le32(par->dc_regs, STGCTL, ctl);
+}
+
+static inline void
+set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct imstt_par *par = info->par;
+	__u32 off = var->yoffset * (info->fix.line_length >> 3)
+		    + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
+	write_reg_le32(par->dc_regs, SSR, off);
+}
+
+static inline void
+set_555 (struct imstt_par *par)
+{
+	if (par->ramdac == IBM) {
+		par->cmap_regs[PIDXHI] = 0;		eieio();
+		par->cmap_regs[PIDXLO] = BPP16;		eieio();
+		par->cmap_regs[PIDXDATA] = 0x01;	eieio();
+	} else {
+		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
+		par->cmap_regs[TVPIDATA] = 0x44;	eieio();
+	}
+}
+
+static inline void
+set_565 (struct imstt_par *par)
+{
+	if (par->ramdac == IBM) {
+		par->cmap_regs[PIDXHI] = 0;		eieio();
+		par->cmap_regs[PIDXLO] = BPP16;		eieio();
+		par->cmap_regs[PIDXDATA] = 0x03;	eieio();
+	} else {
+		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
+		par->cmap_regs[TVPIDATA] = 0x45;	eieio();
+	}
+}
+
+static int
+imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16
+	    && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)
+	    || var->xres_virtual < var->xres || var->yres_virtual < var->yres
+	    || var->nonstd
+	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > info->fix.smem_len
+	    || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > info->fix.smem_len)
+		return -EINVAL;
+
+	switch (var->bits_per_pixel) {
+		case 8:
+			var->red.offset = 0;
+			var->red.length = 8;
+			var->green.offset = 0;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+			break;
+		case 16:	/* RGB 555 or 565 */
+			if (var->green.length != 6)
+				var->red.offset = 10;
+			var->red.length = 5;
+			var->green.offset = 5;
+			if (var->green.length != 6)
+				var->green.length = 5;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+			break;
+		case 24:	/* RGB 888 */
+			var->red.offset = 16;
+			var->red.length = 8;
+			var->green.offset = 8;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+			break;
+		case 32:	/* RGBA 8888 */
+			var->red.offset = 16;
+			var->red.length = 8;
+			var->green.offset = 8;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 24;
+			var->transp.length = 8;
+			break;
+	}
+
+	if (var->yres == var->yres_virtual) {
+		__u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));
+		var->yres_virtual = ((vram << 3) / var->bits_per_pixel) / var->xres_virtual;
+		if (var->yres_virtual < var->yres)
+			var->yres_virtual = var->yres;
+	}
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+	var->height = -1;
+	var->width = -1;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	var->left_margin = var->right_margin = 16;
+	var->upper_margin = var->lower_margin = 16;
+	var->hsync_len = var->vsync_len = 8;
+	return 0;
+}
+
+static int
+imsttfb_set_par(struct fb_info *info) 
+{
+	struct imstt_par *par = info->par;
+		
+	if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
+		return -EINVAL;
+
+	if (info->var.green.length == 6)
+		set_565(par);
+	else
+		set_555(par);
+	set_imstt_regvals(info, info->var.bits_per_pixel);
+	info->var.pixclock = 1000000 / getclkMHz(par);
+	return 0;
+}
+
+static int
+imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
+		   u_int transp, struct fb_info *info)
+{
+	struct imstt_par *par = info->par;
+	u_int bpp = info->var.bits_per_pixel;
+
+	if (regno > 255)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
+	if (0 && bpp == 16)	/* screws up X */
+		par->cmap_regs[PADDRW] = regno << 3;
+	else
+		par->cmap_regs[PADDRW] = regno;
+	eieio();
+
+	par->cmap_regs[PDATA] = red;	eieio();
+	par->cmap_regs[PDATA] = green;	eieio();
+	par->cmap_regs[PDATA] = blue;	eieio();
+
+	if (regno < 16)
+		switch (bpp) {
+			case 16:
+				par->palette[regno] =
+					(regno << (info->var.green.length ==
+					5 ? 10 : 11)) | (regno << 5) | regno;
+				break;
+			case 24:
+				par->palette[regno] =
+					(regno << 16) | (regno << 8) | regno;
+				break;
+			case 32: {
+				int i = (regno << 8) | regno;
+				par->palette[regno] = (i << 16) |i;
+				break;
+			}
+		}
+	return 0;
+}
+
+static int
+imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	if (var->xoffset + info->var.xres > info->var.xres_virtual
+	    || var->yoffset + info->var.yres > info->var.yres_virtual)
+		return -EINVAL;
+
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	set_offset(var, info);
+	return 0;
+}
+
+static int 
+imsttfb_blank(int blank, struct fb_info *info)
+{
+	struct imstt_par *par = info->par;
+	__u32 ctrl;
+
+	ctrl = read_reg_le32(par->dc_regs, STGCTL);
+	if (blank > 0) {
+		switch (blank) {
+		case FB_BLANK_NORMAL:
+		case FB_BLANK_POWERDOWN:
+			ctrl &= ~0x00000380;
+			if (par->ramdac == IBM) {
+				par->cmap_regs[PIDXHI] = 0;		eieio();
+				par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
+				par->cmap_regs[PIDXDATA] = 0x55;	eieio();
+				par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
+				par->cmap_regs[PIDXDATA] = 0x11;	eieio();
+				par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
+				par->cmap_regs[PIDXDATA] = 0x0f;	eieio();
+				par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
+				par->cmap_regs[PIDXDATA] = 0x1f;	eieio();
+				par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
+				par->cmap_regs[PIDXDATA] = 0xc0;
+			}
+			break;
+		case FB_BLANK_VSYNC_SUSPEND:
+			ctrl &= ~0x00000020;
+			break;
+		case FB_BLANK_HSYNC_SUSPEND:
+			ctrl &= ~0x00000010;
+			break;
+		}
+	} else {
+		if (par->ramdac == IBM) {
+			ctrl |= 0x000017b0;
+			par->cmap_regs[PIDXHI] = 0;		eieio();
+			par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
+			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
+			par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
+			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
+			par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
+			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
+			par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
+			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
+			par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
+			par->cmap_regs[PIDXDATA] = 0x45;	eieio();
+		} else
+			ctrl |= 0x00001780;
+	}
+	write_reg_le32(par->dc_regs, STGCTL, ctrl);
+	return 0;
+}
+
+static void
+imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{ 
+	struct imstt_par *par = info->par;
+	__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
+
+	bgc = rect->color;
+	bgc |= (bgc << 8);
+	bgc |= (bgc << 16);
+
+	Bpp = info->var.bits_per_pixel >> 3,
+	line_pitch = info->fix.line_length;
+
+	dy = rect->dy * line_pitch;
+	dx = rect->dx * Bpp;
+	height = rect->height;
+	height--;
+	width = rect->width * Bpp;
+	width--;
+
+	if (rect->rop == ROP_COPY) {
+		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
+		write_reg_le32(par->dc_regs, DSA, dy + dx);
+		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
+		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
+		write_reg_le32(par->dc_regs, BI, 0xffffffff);
+		write_reg_le32(par->dc_regs, MBC, 0xffffffff);
+		write_reg_le32(par->dc_regs, CLR, bgc);
+		write_reg_le32(par->dc_regs, BLTCTL, 0x840); /* 0x200000 */
+		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
+		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
+	} else {
+		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
+		write_reg_le32(par->dc_regs, DSA, dy + dx);
+		write_reg_le32(par->dc_regs, S1SA, dy + dx);
+		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
+		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
+		write_reg_le32(par->dc_regs, SP, line_pitch);
+		write_reg_le32(par->dc_regs, BLTCTL, 0x40005);
+		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
+		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
+	}
+}
+
+static void
+imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct imstt_par *par = info->par;
+	__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
+ 	__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
+
+	Bpp = info->var.bits_per_pixel >> 3,
+
+	sx = area->sx * Bpp;
+	sy = area->sy;
+	dx = area->dx * Bpp;
+	dy = area->dy;
+	height = area->height;
+	height--;
+	width = area->width * Bpp;
+	width--;
+
+	line_pitch = info->fix.line_length;
+	bltctl = 0x05;
+	sp = line_pitch << 16;
+	cnt = height << 16;
+
+	if (sy < dy) {
+		sy += height;
+		dy += height;
+		sp |= -(line_pitch) & 0xffff;
+		dp_octl = -(line_pitch) & 0xffff;
+	} else {
+		sp |= line_pitch;
+		dp_octl = line_pitch;
+	}
+	if (sx < dx) {
+		sx += width;
+		dx += width;
+		bltctl |= 0x80;
+		cnt |= -(width) & 0xffff;
+	} else {
+		cnt |= width;
+	}
+	fb_offset_old = sy * line_pitch + sx;
+	fb_offset_new = dy * line_pitch + dx;
+
+	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
+	write_reg_le32(par->dc_regs, S1SA, fb_offset_old);
+	write_reg_le32(par->dc_regs, SP, sp);
+	write_reg_le32(par->dc_regs, DSA, fb_offset_new);
+	write_reg_le32(par->dc_regs, CNT, cnt);
+	write_reg_le32(par->dc_regs, DP_OCTL, dp_octl);
+	write_reg_le32(par->dc_regs, BLTCTL, bltctl);
+	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
+	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
+}
+
+#if 0
+static int
+imsttfb_load_cursor_image(struct imstt_par *par, int width, int height, __u8 fgc)
+{
+	u_int x, y;
+
+	if (width > 32 || height > 32)
+		return -EINVAL;
+
+	if (par->ramdac == IBM) {
+		par->cmap_regs[PIDXHI] = 1;	eieio();
+		for (x = 0; x < 0x100; x++) {
+			par->cmap_regs[PIDXLO] = x;		eieio();
+			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
+		}
+		par->cmap_regs[PIDXHI] = 1;	eieio();
+		for (y = 0; y < height; y++)
+			for (x = 0; x < width >> 2; x++) {
+				par->cmap_regs[PIDXLO] = x + y * 8;	eieio();
+				par->cmap_regs[PIDXDATA] = 0xff;	eieio();
+			}
+		par->cmap_regs[PIDXHI] = 0;		eieio();
+		par->cmap_regs[PIDXLO] = CURS1R;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS1G;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS1B;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS2R;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS2G;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS2B;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS3R;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS3G;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+		par->cmap_regs[PIDXLO] = CURS3B;	eieio();
+		par->cmap_regs[PIDXDATA] = fgc;		eieio();
+	} else {
+		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
+		par->cmap_regs[TVPADDRW] = 0;		eieio();
+		for (x = 0; x < 0x200; x++) {
+			par->cmap_regs[TVPCRDAT] = 0x00;	eieio();
+		}
+		for (x = 0; x < 0x200; x++) {
+			par->cmap_regs[TVPCRDAT] = 0xff;	eieio();
+		}
+		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
+		for (y = 0; y < height; y++)
+			for (x = 0; x < width >> 3; x++) {
+				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
+				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
+			}
+		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+		par->cmap_regs[TVPIDATA] |= 0x08;	eieio();
+		for (y = 0; y < height; y++)
+			for (x = 0; x < width >> 3; x++) {
+				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
+				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
+			}
+		par->cmap_regs[TVPCADRW] = 0x00;	eieio();
+		for (x = 0; x < 12; x++) {
+			par->cmap_regs[TVPCDATA] = fgc;
+			eieio();
+		}
+	}
+	return 1;
+}
+
+static void
+imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
+{
+	if (par->ramdac == IBM) {
+		par->cmap_regs[PIDXHI] = 0;	eieio();
+		if (!on) {
+			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
+			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
+		} else {
+			par->cmap_regs[PIDXLO] = CURSXHI;	eieio();
+			par->cmap_regs[PIDXDATA] = d->dx >> 8;	eieio();
+			par->cmap_regs[PIDXLO] = CURSXLO;	eieio();
+			par->cmap_regs[PIDXDATA] = d->dx & 0xff;eieio();
+			par->cmap_regs[PIDXLO] = CURSYHI;	eieio();
+			par->cmap_regs[PIDXDATA] = d->dy >> 8;	eieio();
+			par->cmap_regs[PIDXLO] = CURSYLO;	eieio();
+			par->cmap_regs[PIDXDATA] = d->dy & 0xff;eieio();
+			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
+			par->cmap_regs[PIDXDATA] = 0x02;	eieio();
+		}
+	} else {
+		if (!on) {
+			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+			par->cmap_regs[TVPIDATA] = 0x00;	eieio();
+		} else {
+			__u16 x = d->dx + 0x40, y = d->dy + 0x40;
+
+			par->cmap_regs[TVPCXPOH] = x >> 8;	eieio();
+			par->cmap_regs[TVPCXPOL] = x & 0xff;	eieio();
+			par->cmap_regs[TVPCYPOH] = y >> 8;	eieio();
+			par->cmap_regs[TVPCYPOL] = y & 0xff;	eieio();
+			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+			par->cmap_regs[TVPIDATA] = 0x02;	eieio();
+		}
+	}
+}
+
+static int 
+imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct imstt_par *par = info->par;
+        u32 flags = cursor->set, fg, bg, xx, yy;
+
+	if (cursor->dest == NULL && cursor->rop == ROP_XOR)
+		return 1;
+	
+	imstt_set_cursor(info, cursor, 0);
+
+	if (flags & FB_CUR_SETPOS) {
+		xx = cursor->image.dx - info->var.xoffset;
+		yy = cursor->image.dy - info->var.yoffset;
+	}
+
+	if (flags & FB_CUR_SETSIZE) {
+        }
+
+        if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
+                int fg_idx = cursor->image.fg_color;
+                int width = (cursor->image.width+7)/8;
+                u8 *dat = (u8 *) cursor->image.data;
+                u8 *dst = (u8 *) cursor->dest;
+                u8 *msk = (u8 *) cursor->mask;
+
+                switch (cursor->rop) {
+                case ROP_XOR:
+                        for (i = 0; i < cursor->image.height; i++) {
+                                for (j = 0; j < width; j++) {
+                                        d_idx = i * MAX_CURS/8  + j;
+                                        data[d_idx] =  byte_rev[dat[s_idx] ^
+                                                                dst[s_idx]];
+                                        mask[d_idx] = byte_rev[msk[s_idx]];
+                                        s_idx++;
+                                }
+                        }
+                        break;
+                case ROP_COPY:
+                default:
+                        for (i = 0; i < cursor->image.height; i++) {
+                                for (j = 0; j < width; j++) {
+                                        d_idx = i * MAX_CURS/8 + j;
+                                        data[d_idx] = byte_rev[dat[s_idx]];
+                                        mask[d_idx] = byte_rev[msk[s_idx]];
+                                        s_idx++;
+                                }
+			}
+			break;
+		}
+
+		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+                     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+                     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
+
+		imsttfb_load_cursor_image(par, xx, yy, fgc);
+	}
+	if (cursor->enable)
+		imstt_set_cursor(info, cursor, 1);
+	return 0;
+}
+#endif
+
+#define FBIMSTT_SETREG		0x545401
+#define FBIMSTT_GETREG		0x545402
+#define FBIMSTT_SETCMAPREG	0x545403
+#define FBIMSTT_GETCMAPREG	0x545404
+#define FBIMSTT_SETIDXREG	0x545405
+#define FBIMSTT_GETIDXREG	0x545406
+
+static int
+imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+{
+	struct imstt_par *par = info->par;
+	void __user *argp = (void __user *)arg;
+	__u32 reg[2];
+	__u8 idx[2];
+
+	switch (cmd) {
+		case FBIMSTT_SETREG:
+			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			write_reg_le32(par->dc_regs, reg[0], reg[1]);
+			return 0;
+		case FBIMSTT_GETREG:
+			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			reg[1] = read_reg_le32(par->dc_regs, reg[0]);
+			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
+				return -EFAULT;
+			return 0;
+		case FBIMSTT_SETCMAPREG:
+			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			write_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0], reg[1]);
+			return 0;
+		case FBIMSTT_GETCMAPREG:
+			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			reg[1] = read_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0]);
+			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
+				return -EFAULT;
+			return 0;
+		case FBIMSTT_SETIDXREG:
+			if (copy_from_user(idx, argp, 2))
+				return -EFAULT;
+			par->cmap_regs[PIDXHI] = 0;		eieio();
+			par->cmap_regs[PIDXLO] = idx[0];	eieio();
+			par->cmap_regs[PIDXDATA] = idx[1];	eieio();
+			return 0;
+		case FBIMSTT_GETIDXREG:
+			if (copy_from_user(idx, argp, 1))
+				return -EFAULT;
+			par->cmap_regs[PIDXHI] = 0;		eieio();
+			par->cmap_regs[PIDXLO] = idx[0];	eieio();
+			idx[1] = par->cmap_regs[PIDXDATA];
+			if (copy_to_user((void __user *)(arg + 1), &idx[1], 1))
+				return -EFAULT;
+			return 0;
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+static struct pci_device_id imsttfb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT128,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, IBM },
+	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT3D,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TVP },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, imsttfb_pci_tbl);
+
+static struct pci_driver imsttfb_pci_driver = {
+	.name =		"imsttfb",
+	.id_table =	imsttfb_pci_tbl,
+	.probe =	imsttfb_probe,
+	.remove =	imsttfb_remove,
+};
+
+static struct fb_ops imsttfb_ops = {
+	.owner 		= THIS_MODULE,
+	.fb_check_var	= imsttfb_check_var,
+	.fb_set_par 	= imsttfb_set_par,
+	.fb_setcolreg 	= imsttfb_setcolreg,
+	.fb_pan_display = imsttfb_pan_display,
+	.fb_blank 	= imsttfb_blank,
+	.fb_fillrect	= imsttfb_fillrect,
+	.fb_copyarea	= imsttfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_ioctl 	= imsttfb_ioctl,
+};
+
+static void init_imstt(struct fb_info *info)
+{
+	struct imstt_par *par = info->par;
+	__u32 i, tmp, *ip, *end;
+
+	tmp = read_reg_le32(par->dc_regs, PRC);
+	if (par->ramdac == IBM)
+		info->fix.smem_len = (tmp & 0x0004) ? 0x400000 : 0x200000;
+	else
+		info->fix.smem_len = 0x800000;
+
+	ip = (__u32 *)info->screen_base;
+	end = (__u32 *)(info->screen_base + info->fix.smem_len);
+	while (ip < end)
+		*ip++ = 0;
+
+	/* initialize the card */
+	tmp = read_reg_le32(par->dc_regs, STGCTL);
+	write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
+	write_reg_le32(par->dc_regs, SSR, 0);
+
+	/* set default values for DAC registers */
+	if (par->ramdac == IBM) {
+		par->cmap_regs[PPMASK] = 0xff;
+		eieio();
+		par->cmap_regs[PIDXHI] = 0;
+		eieio();
+		for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) {
+			par->cmap_regs[PIDXLO] = ibm_initregs[i].addr;
+			eieio();
+			par->cmap_regs[PIDXDATA] = ibm_initregs[i].value;
+			eieio();
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) {
+			par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;
+			eieio();
+			par->cmap_regs[TVPIDATA] = tvp_initregs[i].value;
+			eieio();
+		}
+	}
+
+#if USE_NV_MODES && defined(CONFIG_PPC32)
+	{
+		int vmode = init_vmode, cmode = init_cmode;
+
+		if (vmode == -1) {
+			vmode = nvram_read_byte(NV_VMODE);
+			if (vmode <= 0 || vmode > VMODE_MAX)
+				vmode = VMODE_640_480_67;
+		}
+		if (cmode == -1) {
+			cmode = nvram_read_byte(NV_CMODE);
+			if (cmode < CMODE_8 || cmode > CMODE_32)
+				cmode = CMODE_8;
+		}
+		if (mac_vmode_to_var(vmode, cmode, &info->var)) {
+			info->var.xres = info->var.xres_virtual = INIT_XRES;
+			info->var.yres = info->var.yres_virtual = INIT_YRES;
+			info->var.bits_per_pixel = INIT_BPP;
+		}
+	}
+#else
+	info->var.xres = info->var.xres_virtual = INIT_XRES;
+	info->var.yres = info->var.yres_virtual = INIT_YRES;
+	info->var.bits_per_pixel = INIT_BPP;
+#endif
+
+	if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
+	    || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
+		printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
+		framebuffer_release(info);
+		return;
+	}
+
+	sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP");
+	info->fix.mmio_len = 0x1000;
+	info->fix.accel = FB_ACCEL_IMS_TWINTURBO;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = info->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+							: FB_VISUAL_DIRECTCOLOR;
+	info->fix.line_length = info->var.xres * (info->var.bits_per_pixel >> 3);
+	info->fix.xpanstep = 8;
+	info->fix.ypanstep = 1;
+	info->fix.ywrapstep = 0;
+
+	info->var.accel_flags = FB_ACCELF_TEXT;
+
+//	if (par->ramdac == IBM)
+//		imstt_cursor_init(info);
+	if (info->var.green.length == 6)
+		set_565(par);
+	else
+		set_555(par);
+	set_imstt_regvals(info, info->var.bits_per_pixel);
+
+	info->var.pixclock = 1000000 / getclkMHz(par);
+
+	info->fbops = &imsttfb_ops;
+	info->flags = FBINFO_DEFAULT |
+                      FBINFO_HWACCEL_COPYAREA |
+	              FBINFO_HWACCEL_FILLRECT |
+	              FBINFO_HWACCEL_YPAN;
+
+	fb_alloc_cmap(&info->cmap, 0, 0);
+
+	if (register_framebuffer(info) < 0) {
+		framebuffer_release(info);
+		return;
+	}
+
+	tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8;
+	fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n",
+		info->fix.id, info->fix.smem_len >> 20, tmp);
+}
+
+static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	unsigned long addr, size;
+	struct imstt_par *par;
+	struct fb_info *info;
+#ifdef CONFIG_PPC_OF
+	struct device_node *dp;
+	
+	dp = pci_device_to_OF_node(pdev);
+	if(dp)
+		printk(KERN_INFO "%s: OF name %s\n",__func__, dp->name);
+	else
+		printk(KERN_ERR "imsttfb: no OF node for pci device\n");
+#endif /* CONFIG_PPC_OF */
+
+	info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
+
+	if (!info) {
+		printk(KERN_ERR "imsttfb: Can't allocate memory\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+
+	addr = pci_resource_start (pdev, 0);
+	size = pci_resource_len (pdev, 0);
+
+	if (!request_mem_region(addr, size, "imsttfb")) {
+		printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
+		framebuffer_release(info);
+		return -ENODEV;
+	}
+
+	switch (pdev->device) {
+		case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */
+			par->ramdac = IBM;
+#ifdef CONFIG_PPC_OF
+			if (dp && ((strcmp(dp->name, "IMS,tt128mb8") == 0) ||
+				   (strcmp(dp->name, "IMS,tt128mb8A") == 0)))
+				par->ramdac = TVP;
+#endif /* CONFIG_PPC_OF */
+			break;
+		case PCI_DEVICE_ID_IMS_TT3D:  /* IMS,tt3d */
+			par->ramdac = TVP;
+			break;
+		default:
+			printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
+					 "contact maintainer.\n", pdev->device);
+			release_mem_region(addr, size);
+			framebuffer_release(info);
+			return -ENODEV;
+	}
+
+	info->fix.smem_start = addr;
+	info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
+					    0x400000 : 0x800000);
+	info->fix.mmio_start = addr + 0x800000;
+	par->dc_regs = ioremap(addr + 0x800000, 0x1000);
+	par->cmap_regs_phys = addr + 0x840000;
+	par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
+	info->pseudo_palette = par->palette;
+	init_imstt(info);
+
+	pci_set_drvdata(pdev, info);
+	return 0;
+}
+
+static void imsttfb_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct imstt_par *par = info->par;
+	int size = pci_resource_len(pdev, 0);
+
+	unregister_framebuffer(info);
+	iounmap(par->cmap_regs);
+	iounmap(par->dc_regs);
+	iounmap(info->screen_base);
+	release_mem_region(info->fix.smem_start, size);
+	framebuffer_release(info);
+}
+
+#ifndef MODULE
+static int __init
+imsttfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "font:", 5)) {
+			char *p;
+			int i;
+
+			p = this_opt + 5;
+			for (i = 0; i < sizeof(fontname) - 1; i++)
+				if (!*p || *p == ' ' || *p == ',')
+					break;
+			memcpy(fontname, this_opt + 5, i);
+			fontname[i] = 0;
+		} else if (!strncmp(this_opt, "inverse", 7)) {
+			inverse = 1;
+			fb_invert_cmaps();
+		}
+#if defined(CONFIG_PPC)
+		else if (!strncmp(this_opt, "vmode:", 6)) {
+			int vmode = simple_strtoul(this_opt+6, NULL, 0);
+			if (vmode > 0 && vmode <= VMODE_MAX)
+				init_vmode = vmode;
+		} else if (!strncmp(this_opt, "cmode:", 6)) {
+			int cmode = simple_strtoul(this_opt+6, NULL, 0);
+			switch (cmode) {
+				case CMODE_8:
+				case 8:
+					init_cmode = CMODE_8;
+					break;
+				case CMODE_16:
+				case 15:
+				case 16:
+					init_cmode = CMODE_16;
+					break;
+				case CMODE_32:
+				case 24:
+				case 32:
+					init_cmode = CMODE_32;
+					break;
+			}
+		}
+#endif
+	}
+	return 0;
+}
+
+#endif /* MODULE */
+
+static int __init imsttfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("imsttfb", &option))
+		return -ENODEV;
+
+	imsttfb_setup(option);
+#endif
+	return pci_register_driver(&imsttfb_pci_driver);
+}
+ 
+static void __exit imsttfb_exit(void)
+{
+	pci_unregister_driver(&imsttfb_pci_driver);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(imsttfb_init);
+module_exit(imsttfb_exit);
+
diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
new file mode 100644
index 000000000000..f6e621684953
--- /dev/null
+++ b/drivers/video/fbdev/imxfb.c
@@ -0,0 +1,1075 @@
+/*
+ *  Freescale i.MX Frame Buffer device driver
+ *
+ *  Copyright (C) 2004 Sascha Hauer, Pengutronix
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Please direct your questions and comments on this driver to the following
+ * email address:
+ *
+ *	linux-arm-kernel@lists.arm.linux.org.uk
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/lcd.h>
+#include <linux/math64.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <linux/regulator/consumer.h>
+
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include <linux/platform_data/video-imxfb.h>
+
+/*
+ * Complain if VAR is out of range.
+ */
+#define DEBUG_VAR 1
+
+#define DRIVER_NAME "imx-fb"
+
+#define LCDC_SSA	0x00
+
+#define LCDC_SIZE	0x04
+#define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20)
+
+#define YMAX_MASK_IMX1	0x1ff
+#define YMAX_MASK_IMX21	0x3ff
+
+#define LCDC_VPW	0x08
+#define VPW_VPW(x)	((x) & 0x3ff)
+
+#define LCDC_CPOS	0x0C
+#define CPOS_CC1	(1<<31)
+#define CPOS_CC0	(1<<30)
+#define CPOS_OP		(1<<28)
+#define CPOS_CXP(x)	(((x) & 3ff) << 16)
+
+#define LCDC_LCWHB	0x10
+#define LCWHB_BK_EN	(1<<31)
+#define LCWHB_CW(w)	(((w) & 0x1f) << 24)
+#define LCWHB_CH(h)	(((h) & 0x1f) << 16)
+#define LCWHB_BD(x)	((x) & 0xff)
+
+#define LCDC_LCHCC	0x14
+
+#define LCDC_PCR	0x18
+
+#define LCDC_HCR	0x1C
+#define HCR_H_WIDTH(x)	(((x) & 0x3f) << 26)
+#define HCR_H_WAIT_1(x)	(((x) & 0xff) << 8)
+#define HCR_H_WAIT_2(x)	((x) & 0xff)
+
+#define LCDC_VCR	0x20
+#define VCR_V_WIDTH(x)	(((x) & 0x3f) << 26)
+#define VCR_V_WAIT_1(x)	(((x) & 0xff) << 8)
+#define VCR_V_WAIT_2(x)	((x) & 0xff)
+
+#define LCDC_POS	0x24
+#define POS_POS(x)	((x) & 1f)
+
+#define LCDC_LSCR1	0x28
+/* bit fields in imxfb.h */
+
+#define LCDC_PWMR	0x2C
+/* bit fields in imxfb.h */
+
+#define LCDC_DMACR	0x30
+/* bit fields in imxfb.h */
+
+#define LCDC_RMCR	0x34
+
+#define RMCR_LCDC_EN_MX1	(1<<1)
+
+#define RMCR_SELF_REF	(1<<0)
+
+#define LCDC_LCDICR	0x38
+#define LCDICR_INT_SYN	(1<<2)
+#define LCDICR_INT_CON	(1)
+
+#define LCDC_LCDISR	0x40
+#define LCDISR_UDR_ERR	(1<<3)
+#define LCDISR_ERR_RES	(1<<2)
+#define LCDISR_EOF	(1<<1)
+#define LCDISR_BOF	(1<<0)
+
+#define IMXFB_LSCR1_DEFAULT 0x00120300
+
+/* Used fb-mode. Can be set on kernel command line, therefore file-static. */
+static const char *fb_mode;
+
+/*
+ * These are the bitfields for each
+ * display depth that we support.
+ */
+struct imxfb_rgb {
+	struct fb_bitfield	red;
+	struct fb_bitfield	green;
+	struct fb_bitfield	blue;
+	struct fb_bitfield	transp;
+};
+
+enum imxfb_type {
+	IMX1_FB,
+	IMX21_FB,
+};
+
+struct imxfb_info {
+	struct platform_device  *pdev;
+	void __iomem		*regs;
+	struct clk		*clk_ipg;
+	struct clk		*clk_ahb;
+	struct clk		*clk_per;
+	enum imxfb_type		devtype;
+	bool			enabled;
+
+	/*
+	 * These are the addresses we mapped
+	 * the framebuffer memory region to.
+	 */
+	dma_addr_t		map_dma;
+	u_int			map_size;
+
+	u_int			palette_size;
+
+	dma_addr_t		dbar1;
+	dma_addr_t		dbar2;
+
+	u_int			pcr;
+	u_int			pwmr;
+	u_int			lscr1;
+	u_int			dmacr;
+	bool			cmap_inverse;
+	bool			cmap_static;
+
+	struct imx_fb_videomode *mode;
+	int			num_modes;
+
+	struct regulator	*lcd_pwr;
+};
+
+static struct platform_device_id imxfb_devtype[] = {
+	{
+		.name = "imx1-fb",
+		.driver_data = IMX1_FB,
+	}, {
+		.name = "imx21-fb",
+		.driver_data = IMX21_FB,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imxfb_devtype);
+
+static struct of_device_id imxfb_of_dev_id[] = {
+	{
+		.compatible = "fsl,imx1-fb",
+		.data = &imxfb_devtype[IMX1_FB],
+	}, {
+		.compatible = "fsl,imx21-fb",
+		.data = &imxfb_devtype[IMX21_FB],
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, imxfb_of_dev_id);
+
+static inline int is_imx1_fb(struct imxfb_info *fbi)
+{
+	return fbi->devtype == IMX1_FB;
+}
+
+#define IMX_NAME	"IMX"
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES	64
+#define MIN_YRES	64
+
+/* Actually this really is 18bit support, the lowest 2 bits of each colour
+ * are unused in hardware. We claim to have 24bit support to make software
+ * like X work, which does not support 18bit.
+ */
+static struct imxfb_rgb def_rgb_18 = {
+	.red	= {.offset = 16, .length = 8,},
+	.green	= {.offset = 8, .length = 8,},
+	.blue	= {.offset = 0, .length = 8,},
+	.transp = {.offset = 0, .length = 0,},
+};
+
+static struct imxfb_rgb def_rgb_16_tft = {
+	.red	= {.offset = 11, .length = 5,},
+	.green	= {.offset = 5, .length = 6,},
+	.blue	= {.offset = 0, .length = 5,},
+	.transp = {.offset = 0, .length = 0,},
+};
+
+static struct imxfb_rgb def_rgb_16_stn = {
+	.red	= {.offset = 8, .length = 4,},
+	.green	= {.offset = 4, .length = 4,},
+	.blue	= {.offset = 0, .length = 4,},
+	.transp = {.offset = 0, .length = 0,},
+};
+
+static struct imxfb_rgb def_rgb_8 = {
+	.red	= {.offset = 0, .length = 8,},
+	.green	= {.offset = 0, .length = 8,},
+	.blue	= {.offset = 0, .length = 8,},
+	.transp = {.offset = 0, .length = 0,},
+};
+
+static int imxfb_activate_var(struct fb_var_screeninfo *var,
+		struct fb_info *info);
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int imxfb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
+		u_int trans, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	u_int val, ret = 1;
+
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	if (regno < fbi->palette_size) {
+		val = (CNVT_TOHW(red, 4) << 8) |
+		      (CNVT_TOHW(green,4) << 4) |
+		      CNVT_TOHW(blue,  4);
+
+		writel(val, fbi->regs + 0x800 + (regno << 2));
+		ret = 0;
+	}
+	return ret;
+}
+
+static int imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		   u_int trans, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	unsigned int val;
+	int ret = 1;
+
+	/*
+	 * If inverse mode was selected, invert all the colours
+	 * rather than the register number.  The register number
+	 * is what you poke into the framebuffer to produce the
+	 * colour you requested.
+	 */
+	if (fbi->cmap_inverse) {
+		red   = 0xffff - red;
+		green = 0xffff - green;
+		blue  = 0xffff - blue;
+	}
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no mater what visual we are using.
+	 */
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 12 or 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		ret = imxfb_setpalettereg(regno, red, green, blue, trans, info);
+		break;
+	}
+
+	return ret;
+}
+
+static const struct imx_fb_videomode *imxfb_find_mode(struct imxfb_info *fbi)
+{
+	struct imx_fb_videomode *m;
+	int i;
+
+	if (!fb_mode)
+		return &fbi->mode[0];
+
+	for (i = 0, m = &fbi->mode[0]; i < fbi->num_modes; i++, m++) {
+		if (!strcmp(m->mode.name, fb_mode))
+			return m;
+	}
+	return NULL;
+}
+
+/*
+ *  imxfb_check_var():
+ *    Round up in the following order: bits_per_pixel, xres,
+ *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+ *    bitfields, horizontal timing, vertical timing.
+ */
+static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	struct imxfb_rgb *rgb;
+	const struct imx_fb_videomode *imxfb_mode;
+	unsigned long lcd_clk;
+	unsigned long long tmp;
+	u32 pcr = 0;
+
+	if (var->xres < MIN_XRES)
+		var->xres = MIN_XRES;
+	if (var->yres < MIN_YRES)
+		var->yres = MIN_YRES;
+
+	imxfb_mode = imxfb_find_mode(fbi);
+	if (!imxfb_mode)
+		return -EINVAL;
+
+	var->xres		= imxfb_mode->mode.xres;
+	var->yres		= imxfb_mode->mode.yres;
+	var->bits_per_pixel	= imxfb_mode->bpp;
+	var->pixclock		= imxfb_mode->mode.pixclock;
+	var->hsync_len		= imxfb_mode->mode.hsync_len;
+	var->left_margin	= imxfb_mode->mode.left_margin;
+	var->right_margin	= imxfb_mode->mode.right_margin;
+	var->vsync_len		= imxfb_mode->mode.vsync_len;
+	var->upper_margin	= imxfb_mode->mode.upper_margin;
+	var->lower_margin	= imxfb_mode->mode.lower_margin;
+	var->sync		= imxfb_mode->mode.sync;
+	var->xres_virtual	= max(var->xres_virtual, var->xres);
+	var->yres_virtual	= max(var->yres_virtual, var->yres);
+
+	pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
+
+	lcd_clk = clk_get_rate(fbi->clk_per);
+
+	tmp = var->pixclock * (unsigned long long)lcd_clk;
+
+	do_div(tmp, 1000000);
+
+	if (do_div(tmp, 1000000) > 500000)
+		tmp++;
+
+	pcr = (unsigned int)tmp;
+
+	if (--pcr > 0x3F) {
+		pcr = 0x3F;
+		printk(KERN_WARNING "Must limit pixel clock to %luHz\n",
+				lcd_clk / pcr);
+	}
+
+	switch (var->bits_per_pixel) {
+	case 32:
+		pcr |= PCR_BPIX_18;
+		rgb = &def_rgb_18;
+		break;
+	case 16:
+	default:
+		if (is_imx1_fb(fbi))
+			pcr |= PCR_BPIX_12;
+		else
+			pcr |= PCR_BPIX_16;
+
+		if (imxfb_mode->pcr & PCR_TFT)
+			rgb = &def_rgb_16_tft;
+		else
+			rgb = &def_rgb_16_stn;
+		break;
+	case 8:
+		pcr |= PCR_BPIX_8;
+		rgb = &def_rgb_8;
+		break;
+	}
+
+	/* add sync polarities */
+	pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
+
+	fbi->pcr = pcr;
+
+	/*
+	 * Copy the RGB parameters for this display
+	 * from the machine specific parameters.
+	 */
+	var->red    = rgb->red;
+	var->green  = rgb->green;
+	var->blue   = rgb->blue;
+	var->transp = rgb->transp;
+
+	pr_debug("RGBT length = %d:%d:%d:%d\n",
+		var->red.length, var->green.length, var->blue.length,
+		var->transp.length);
+
+	pr_debug("RGBT offset = %d:%d:%d:%d\n",
+		var->red.offset, var->green.offset, var->blue.offset,
+		var->transp.offset);
+
+	return 0;
+}
+
+/*
+ * imxfb_set_par():
+ *	Set the user defined part of the display for the specified console
+ */
+static int imxfb_set_par(struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+
+	if (var->bits_per_pixel == 16 || var->bits_per_pixel == 32)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else if (!fbi->cmap_static)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else {
+		/*
+		 * Some people have weird ideas about wanting static
+		 * pseudocolor maps.  I suspect their user space
+		 * applications are broken.
+		 */
+		info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+	}
+
+	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
+
+	imxfb_activate_var(var, info);
+
+	return 0;
+}
+
+static void imxfb_enable_controller(struct imxfb_info *fbi)
+{
+
+	if (fbi->enabled)
+		return;
+
+	pr_debug("Enabling LCD controller\n");
+
+	writel(fbi->map_dma, fbi->regs + LCDC_SSA);
+
+	/* panning offset 0 (0 pixel offset)        */
+	writel(0x00000000, fbi->regs + LCDC_POS);
+
+	/* disable hardware cursor */
+	writel(readl(fbi->regs + LCDC_CPOS) & ~(CPOS_CC0 | CPOS_CC1),
+		fbi->regs + LCDC_CPOS);
+
+	/*
+	 * RMCR_LCDC_EN_MX1 is present on i.MX1 only, but doesn't hurt
+	 * on other SoCs
+	 */
+	writel(RMCR_LCDC_EN_MX1, fbi->regs + LCDC_RMCR);
+
+	clk_prepare_enable(fbi->clk_ipg);
+	clk_prepare_enable(fbi->clk_ahb);
+	clk_prepare_enable(fbi->clk_per);
+	fbi->enabled = true;
+}
+
+static void imxfb_disable_controller(struct imxfb_info *fbi)
+{
+	if (!fbi->enabled)
+		return;
+
+	pr_debug("Disabling LCD controller\n");
+
+	clk_disable_unprepare(fbi->clk_per);
+	clk_disable_unprepare(fbi->clk_ipg);
+	clk_disable_unprepare(fbi->clk_ahb);
+	fbi->enabled = false;
+
+	writel(0, fbi->regs + LCDC_RMCR);
+}
+
+static int imxfb_blank(int blank, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+
+	pr_debug("imxfb_blank: blank=%d\n", blank);
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		imxfb_disable_controller(fbi);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		imxfb_enable_controller(fbi);
+		break;
+	}
+	return 0;
+}
+
+static struct fb_ops imxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= imxfb_check_var,
+	.fb_set_par	= imxfb_set_par,
+	.fb_setcolreg	= imxfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_blank	= imxfb_blank,
+};
+
+/*
+ * imxfb_activate_var():
+ *	Configures LCD Controller based on entries in var parameter.  Settings are
+ *	only written to the controller if changes were made.
+ */
+static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21;
+
+	pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
+		var->xres, var->hsync_len,
+		var->left_margin, var->right_margin);
+	pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
+		var->yres, var->vsync_len,
+		var->upper_margin, var->lower_margin);
+
+#if DEBUG_VAR
+	if (var->xres < 16        || var->xres > 1024)
+		printk(KERN_ERR "%s: invalid xres %d\n",
+			info->fix.id, var->xres);
+	if (var->hsync_len < 1    || var->hsync_len > 64)
+		printk(KERN_ERR "%s: invalid hsync_len %d\n",
+			info->fix.id, var->hsync_len);
+	if (var->left_margin > 255)
+		printk(KERN_ERR "%s: invalid left_margin %d\n",
+			info->fix.id, var->left_margin);
+	if (var->right_margin > 255)
+		printk(KERN_ERR "%s: invalid right_margin %d\n",
+			info->fix.id, var->right_margin);
+	if (var->yres < 1 || var->yres > ymax_mask)
+		printk(KERN_ERR "%s: invalid yres %d\n",
+			info->fix.id, var->yres);
+	if (var->vsync_len > 100)
+		printk(KERN_ERR "%s: invalid vsync_len %d\n",
+			info->fix.id, var->vsync_len);
+	if (var->upper_margin > 63)
+		printk(KERN_ERR "%s: invalid upper_margin %d\n",
+			info->fix.id, var->upper_margin);
+	if (var->lower_margin > 255)
+		printk(KERN_ERR "%s: invalid lower_margin %d\n",
+			info->fix.id, var->lower_margin);
+#endif
+
+	/* physical screen start address	    */
+	writel(VPW_VPW(var->xres * var->bits_per_pixel / 8 / 4),
+		fbi->regs + LCDC_VPW);
+
+	writel(HCR_H_WIDTH(var->hsync_len - 1) |
+		HCR_H_WAIT_1(var->right_margin - 1) |
+		HCR_H_WAIT_2(var->left_margin - 3),
+		fbi->regs + LCDC_HCR);
+
+	writel(VCR_V_WIDTH(var->vsync_len) |
+		VCR_V_WAIT_1(var->lower_margin) |
+		VCR_V_WAIT_2(var->upper_margin),
+		fbi->regs + LCDC_VCR);
+
+	writel(SIZE_XMAX(var->xres) | (var->yres & ymax_mask),
+			fbi->regs + LCDC_SIZE);
+
+	writel(fbi->pcr, fbi->regs + LCDC_PCR);
+	if (fbi->pwmr)
+		writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
+	writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
+
+	/* dmacr = 0 is no valid value, as we need DMA control marks. */
+	if (fbi->dmacr)
+		writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
+
+	return 0;
+}
+
+static int imxfb_init_fbinfo(struct platform_device *pdev)
+{
+	struct imx_fb_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct fb_info *info = dev_get_drvdata(&pdev->dev);
+	struct imxfb_info *fbi = info->par;
+	struct device_node *np;
+
+	pr_debug("%s\n",__func__);
+
+	info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+	if (!info->pseudo_palette)
+		return -ENOMEM;
+
+	memset(fbi, 0, sizeof(struct imxfb_info));
+
+	fbi->devtype = pdev->id_entry->driver_data;
+
+	strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
+
+	info->fix.type			= FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux		= 0;
+	info->fix.xpanstep		= 0;
+	info->fix.ypanstep		= 0;
+	info->fix.ywrapstep		= 0;
+	info->fix.accel			= FB_ACCEL_NONE;
+
+	info->var.nonstd		= 0;
+	info->var.activate		= FB_ACTIVATE_NOW;
+	info->var.height		= -1;
+	info->var.width	= -1;
+	info->var.accel_flags		= 0;
+	info->var.vmode			= FB_VMODE_NONINTERLACED;
+
+	info->fbops			= &imxfb_ops;
+	info->flags			= FBINFO_FLAG_DEFAULT |
+					  FBINFO_READS_FAST;
+	if (pdata) {
+		fbi->lscr1			= pdata->lscr1;
+		fbi->dmacr			= pdata->dmacr;
+		fbi->pwmr			= pdata->pwmr;
+	} else {
+		np = pdev->dev.of_node;
+		info->var.grayscale = of_property_read_bool(np,
+						"cmap-greyscale");
+		fbi->cmap_inverse = of_property_read_bool(np, "cmap-inverse");
+		fbi->cmap_static = of_property_read_bool(np, "cmap-static");
+
+		fbi->lscr1 = IMXFB_LSCR1_DEFAULT;
+
+		of_property_read_u32(np, "fsl,lpccr", &fbi->pwmr);
+
+		of_property_read_u32(np, "fsl,lscr1", &fbi->lscr1);
+
+		of_property_read_u32(np, "fsl,dmacr", &fbi->dmacr);
+	}
+
+	return 0;
+}
+
+static int imxfb_of_read_mode(struct device *dev, struct device_node *np,
+		struct imx_fb_videomode *imxfb_mode)
+{
+	int ret;
+	struct fb_videomode *of_mode = &imxfb_mode->mode;
+	u32 bpp;
+	u32 pcr;
+
+	ret = of_property_read_string(np, "model", &of_mode->name);
+	if (ret)
+		of_mode->name = NULL;
+
+	ret = of_get_fb_videomode(np, of_mode, OF_USE_NATIVE_MODE);
+	if (ret) {
+		dev_err(dev, "Failed to get videomode from DT\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(np, "bits-per-pixel", &bpp);
+	ret |= of_property_read_u32(np, "fsl,pcr", &pcr);
+
+	if (ret) {
+		dev_err(dev, "Failed to read bpp and pcr from DT\n");
+		return -EINVAL;
+	}
+
+	if (bpp < 1 || bpp > 255) {
+		dev_err(dev, "Bits per pixel have to be between 1 and 255\n");
+		return -EINVAL;
+	}
+
+	imxfb_mode->bpp = bpp;
+	imxfb_mode->pcr = pcr;
+
+	return 0;
+}
+
+static int imxfb_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi)
+{
+	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
+
+	if (!fi || fi->par == fbi)
+		return 1;
+
+	return 0;
+}
+
+static int imxfb_lcd_get_contrast(struct lcd_device *lcddev)
+{
+	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
+
+	return fbi->pwmr & 0xff;
+}
+
+static int imxfb_lcd_set_contrast(struct lcd_device *lcddev, int contrast)
+{
+	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
+
+	if (fbi->pwmr && fbi->enabled) {
+		if (contrast > 255)
+			contrast = 255;
+		else if (contrast < 0)
+			contrast = 0;
+
+		fbi->pwmr &= ~0xff;
+		fbi->pwmr |= contrast;
+
+		writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
+	}
+
+	return 0;
+}
+
+static int imxfb_lcd_get_power(struct lcd_device *lcddev)
+{
+	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
+
+	if (!IS_ERR(fbi->lcd_pwr))
+		return regulator_is_enabled(fbi->lcd_pwr);
+
+	return 1;
+}
+
+static int imxfb_lcd_set_power(struct lcd_device *lcddev, int power)
+{
+	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
+
+	if (!IS_ERR(fbi->lcd_pwr)) {
+		if (power)
+			return regulator_enable(fbi->lcd_pwr);
+		else
+			return regulator_disable(fbi->lcd_pwr);
+	}
+
+	return 0;
+}
+
+static struct lcd_ops imxfb_lcd_ops = {
+	.check_fb	= imxfb_lcd_check_fb,
+	.get_contrast	= imxfb_lcd_get_contrast,
+	.set_contrast	= imxfb_lcd_set_contrast,
+	.get_power	= imxfb_lcd_get_power,
+	.set_power	= imxfb_lcd_set_power,
+};
+
+static int imxfb_setup(void)
+{
+	char *opt, *options = NULL;
+
+	if (fb_get_options("imxfb", &options))
+		return -ENODEV;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+		else
+			fb_mode = opt;
+	}
+
+	return 0;
+}
+
+static int imxfb_probe(struct platform_device *pdev)
+{
+	struct imxfb_info *fbi;
+	struct lcd_device *lcd;
+	struct fb_info *info;
+	struct imx_fb_platform_data *pdata;
+	struct resource *res;
+	struct imx_fb_videomode *m;
+	const struct of_device_id *of_id;
+	int ret, i;
+	int bytes_per_pixel;
+
+	dev_info(&pdev->dev, "i.MX Framebuffer driver\n");
+
+	ret = imxfb_setup();
+	if (ret < 0)
+		return ret;
+
+	of_id = of_match_device(imxfb_of_dev_id, &pdev->dev);
+	if (of_id)
+		pdev->id_entry = of_id->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	fbi = info->par;
+
+	platform_set_drvdata(pdev, info);
+
+	ret = imxfb_init_fbinfo(pdev);
+	if (ret < 0)
+		goto failed_init;
+
+	if (pdata) {
+		if (!fb_mode)
+			fb_mode = pdata->mode[0].mode.name;
+
+		fbi->mode = pdata->mode;
+		fbi->num_modes = pdata->num_modes;
+	} else {
+		struct device_node *display_np;
+		fb_mode = NULL;
+
+		display_np = of_parse_phandle(pdev->dev.of_node, "display", 0);
+		if (!display_np) {
+			dev_err(&pdev->dev, "No display defined in devicetree\n");
+			ret = -EINVAL;
+			goto failed_of_parse;
+		}
+
+		/*
+		 * imxfb does not support more modes, we choose only the native
+		 * mode.
+		 */
+		fbi->num_modes = 1;
+
+		fbi->mode = devm_kzalloc(&pdev->dev,
+				sizeof(struct imx_fb_videomode), GFP_KERNEL);
+		if (!fbi->mode) {
+			ret = -ENOMEM;
+			goto failed_of_parse;
+		}
+
+		ret = imxfb_of_read_mode(&pdev->dev, display_np, fbi->mode);
+		if (ret)
+			goto failed_of_parse;
+	}
+
+	/* Calculate maximum bytes used per pixel. In most cases this should
+	 * be the same as m->bpp/8 */
+	m = &fbi->mode[0];
+	bytes_per_pixel = (m->bpp + 7) / 8;
+	for (i = 0; i < fbi->num_modes; i++, m++)
+		info->fix.smem_len = max_t(size_t, info->fix.smem_len,
+				m->mode.xres * m->mode.yres * bytes_per_pixel);
+
+	res = request_mem_region(res->start, resource_size(res),
+				DRIVER_NAME);
+	if (!res) {
+		ret = -EBUSY;
+		goto failed_req;
+	}
+
+	fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(fbi->clk_ipg)) {
+		ret = PTR_ERR(fbi->clk_ipg);
+		goto failed_getclock;
+	}
+
+	fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(fbi->clk_ahb)) {
+		ret = PTR_ERR(fbi->clk_ahb);
+		goto failed_getclock;
+	}
+
+	fbi->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(fbi->clk_per)) {
+		ret = PTR_ERR(fbi->clk_per);
+		goto failed_getclock;
+	}
+
+	fbi->regs = ioremap(res->start, resource_size(res));
+	if (fbi->regs == NULL) {
+		dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
+		ret = -ENOMEM;
+		goto failed_ioremap;
+	}
+
+	fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
+	info->screen_base = dma_alloc_writecombine(&pdev->dev, fbi->map_size,
+						   &fbi->map_dma, GFP_KERNEL);
+
+	if (!info->screen_base) {
+		dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
+		ret = -ENOMEM;
+		goto failed_map;
+	}
+
+	info->fix.smem_start = fbi->map_dma;
+
+	if (pdata && pdata->init) {
+		ret = pdata->init(fbi->pdev);
+		if (ret)
+			goto failed_platform_init;
+	}
+
+
+	INIT_LIST_HEAD(&info->modelist);
+	for (i = 0; i < fbi->num_modes; i++)
+		fb_add_videomode(&fbi->mode[i].mode, &info->modelist);
+
+	/*
+	 * This makes sure that our colour bitfield
+	 * descriptors are correctly initialised.
+	 */
+	imxfb_check_var(&info->var, info);
+
+	ret = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
+	if (ret < 0)
+		goto failed_cmap;
+
+	imxfb_set_par(info);
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register framebuffer\n");
+		goto failed_register;
+	}
+
+	fbi->lcd_pwr = devm_regulator_get(&pdev->dev, "lcd");
+	if (IS_ERR(fbi->lcd_pwr) && (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER)) {
+		ret = -EPROBE_DEFER;
+		goto failed_lcd;
+	}
+
+	lcd = devm_lcd_device_register(&pdev->dev, "imxfb-lcd", &pdev->dev, fbi,
+				       &imxfb_lcd_ops);
+	if (IS_ERR(lcd)) {
+		ret = PTR_ERR(lcd);
+		goto failed_lcd;
+	}
+
+	lcd->props.max_contrast = 0xff;
+
+	imxfb_enable_controller(fbi);
+	fbi->pdev = pdev;
+
+	return 0;
+
+failed_lcd:
+	unregister_framebuffer(info);
+
+failed_register:
+	fb_dealloc_cmap(&info->cmap);
+failed_cmap:
+	if (pdata && pdata->exit)
+		pdata->exit(fbi->pdev);
+failed_platform_init:
+	dma_free_writecombine(&pdev->dev, fbi->map_size, info->screen_base,
+			      fbi->map_dma);
+failed_map:
+	iounmap(fbi->regs);
+failed_ioremap:
+failed_getclock:
+	release_mem_region(res->start, resource_size(res));
+failed_req:
+failed_of_parse:
+	kfree(info->pseudo_palette);
+failed_init:
+	framebuffer_release(info);
+	return ret;
+}
+
+static int imxfb_remove(struct platform_device *pdev)
+{
+	struct imx_fb_platform_data *pdata;
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct imxfb_info *fbi = info->par;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	imxfb_disable_controller(fbi);
+
+	unregister_framebuffer(info);
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata && pdata->exit)
+		pdata->exit(fbi->pdev);
+
+	fb_dealloc_cmap(&info->cmap);
+	kfree(info->pseudo_palette);
+	framebuffer_release(info);
+
+	dma_free_writecombine(&pdev->dev, fbi->map_size, info->screen_base,
+			      fbi->map_dma);
+
+	iounmap(fbi->regs);
+	release_mem_region(res->start, resource_size(res));
+
+	return 0;
+}
+
+static int __maybe_unused imxfb_suspend(struct device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct imxfb_info *fbi = info->par;
+
+	imxfb_disable_controller(fbi);
+
+	return 0;
+}
+
+static int __maybe_unused imxfb_resume(struct device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct imxfb_info *fbi = info->par;
+
+	imxfb_enable_controller(fbi);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
+
+static struct platform_driver imxfb_driver = {
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.of_match_table = imxfb_of_dev_id,
+		.owner	= THIS_MODULE,
+		.pm	= &imxfb_pm_ops,
+	},
+	.probe		= imxfb_probe,
+	.remove		= imxfb_remove,
+	.id_table	= imxfb_devtype,
+};
+module_platform_driver(imxfb_driver);
+
+MODULE_DESCRIPTION("Freescale i.MX framebuffer driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/intelfb/Makefile b/drivers/video/fbdev/intelfb/Makefile
new file mode 100644
index 000000000000..f7d631ebee8e
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_FB_INTEL) += intelfb.o
+
+intelfb-y := intelfbdrv.o intelfbhw.o
+intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
+intelfb-objs := $(intelfb-y)
+
+ccflags-$(CONFIG_FB_INTEL_DEBUG) := -DDEBUG -DREGDUMP
diff --git a/drivers/video/fbdev/intelfb/intelfb.h b/drivers/video/fbdev/intelfb/intelfb.h
new file mode 100644
index 000000000000..6b51175629c7
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfb.h
@@ -0,0 +1,383 @@
+#ifndef _INTELFB_H
+#define _INTELFB_H
+
+/* $DHD: intelfb/intelfb.h,v 1.40 2003/06/27 15:06:25 dawes Exp $ */
+
+#include <linux/agp_backend.h>
+#include <linux/fb.h>
+
+#ifdef CONFIG_FB_INTEL_I2C
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#endif
+
+/*** Version/name ***/
+#define INTELFB_VERSION			"0.9.6"
+#define INTELFB_MODULE_NAME		"intelfb"
+#define SUPPORTED_CHIPSETS		"830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
+
+
+/*** Debug/feature defines ***/
+
+#ifndef DEBUG
+#define DEBUG				0
+#endif
+
+#ifndef VERBOSE
+#define VERBOSE				0
+#endif
+
+#ifndef REGDUMP
+#define REGDUMP				0
+#endif
+
+#ifndef DETECT_VGA_CLASS_ONLY
+#define DETECT_VGA_CLASS_ONLY		1
+#endif
+
+#ifndef ALLOCATE_FOR_PANNING
+#define ALLOCATE_FOR_PANNING		1
+#endif
+
+#ifndef PREFERRED_MODE
+#define PREFERRED_MODE			"1024x768-32@70"
+#endif
+
+/*** hw-related values ***/
+
+/* Resource Allocation */
+#define INTELFB_FB_ACQUIRED                 1
+#define INTELFB_MMIO_ACQUIRED               2
+
+/* PCI ids for supported devices */
+#define PCI_DEVICE_ID_INTEL_830M	0x3577
+#define PCI_DEVICE_ID_INTEL_845G	0x2562
+#define PCI_DEVICE_ID_INTEL_85XGM	0x3582
+#define PCI_DEVICE_ID_INTEL_854		0x358E
+#define PCI_DEVICE_ID_INTEL_865G	0x2572
+#define PCI_DEVICE_ID_INTEL_915G	0x2582
+#define PCI_DEVICE_ID_INTEL_915GM	0x2592
+#define PCI_DEVICE_ID_INTEL_945G	0x2772
+#define PCI_DEVICE_ID_INTEL_945GM	0x27A2
+#define PCI_DEVICE_ID_INTEL_945GME	0x27AE
+#define PCI_DEVICE_ID_INTEL_965G	0x29A2
+#define PCI_DEVICE_ID_INTEL_965GM	0x2A02
+
+/* Size of MMIO region */
+#define INTEL_REG_SIZE			0x80000
+
+#define STRIDE_ALIGNMENT		16
+#define STRIDE_ALIGNMENT_I9XX		64
+
+#define PALETTE_8_ENTRIES		256
+
+
+/*** Macros ***/
+
+/* basic arithmetic */
+#define KB(x)			((x) * 1024)
+#define MB(x)			((x) * 1024 * 1024)
+#define BtoKB(x)		((x) / 1024)
+#define BtoMB(x)		((x) / 1024 / 1024)
+
+#define GTT_PAGE_SIZE           KB(4)
+
+#define ROUND_UP_TO(x, y)	(((x) + (y) - 1) / (y) * (y))
+#define ROUND_DOWN_TO(x, y)	((x) / (y) * (y))
+#define ROUND_UP_TO_PAGE(x)	ROUND_UP_TO((x), GTT_PAGE_SIZE)
+#define ROUND_DOWN_TO_PAGE(x)	ROUND_DOWN_TO((x), GTT_PAGE_SIZE)
+
+/* messages */
+#define PFX			INTELFB_MODULE_NAME ": "
+
+#define ERR_MSG(fmt, args...)	printk(KERN_ERR PFX fmt, ## args)
+#define WRN_MSG(fmt, args...)	printk(KERN_WARNING PFX fmt, ## args)
+#define NOT_MSG(fmt, args...)	printk(KERN_NOTICE PFX fmt, ## args)
+#define INF_MSG(fmt, args...)	printk(KERN_INFO PFX fmt, ## args)
+#if DEBUG
+#define DBG_MSG(fmt, args...)	printk(KERN_DEBUG PFX fmt, ## args)
+#else
+#define DBG_MSG(fmt, args...)	while (0) printk(fmt, ## args)
+#endif
+
+/* get commonly used pointers */
+#define GET_DINFO(info)		(info)->par
+
+/* misc macros */
+#define ACCEL(d, i)                                                     \
+	((d)->accel && !(d)->ring_lockup &&                             \
+	 ((i)->var.accel_flags & FB_ACCELF_TEXT))
+
+/*#define NOACCEL_CHIPSET(d)						\
+	((d)->chipset != INTEL_865G)*/
+#define NOACCEL_CHIPSET(d)						\
+	(0)
+
+#define FIXED_MODE(d) ((d)->fixed_mode)
+
+/*** Driver parameters ***/
+
+#define RINGBUFFER_SIZE		KB(64)
+#define HW_CURSOR_SIZE		KB(4)
+
+/* Intel agpgart driver */
+#define AGP_PHYSICAL_MEMORY     2
+
+/* store information about an Ixxx DVO */
+/* The i830->i865 use multiple DVOs with multiple i2cs */
+/* the i915, i945 have a single sDVO i2c bus - which is different */
+#define MAX_OUTPUTS 6
+
+/* these are outputs from the chip - integrated only
+   external chips are via DVO or SDVO output */
+#define INTELFB_OUTPUT_UNUSED 0
+#define INTELFB_OUTPUT_ANALOG 1
+#define INTELFB_OUTPUT_DVO 2
+#define INTELFB_OUTPUT_SDVO 3
+#define INTELFB_OUTPUT_LVDS 4
+#define INTELFB_OUTPUT_TVOUT 5
+
+#define INTELFB_DVO_CHIP_NONE 0
+#define INTELFB_DVO_CHIP_LVDS 1
+#define INTELFB_DVO_CHIP_TMDS 2
+#define INTELFB_DVO_CHIP_TVOUT 4
+
+#define INTELFB_OUTPUT_PIPE_NC  0
+#define INTELFB_OUTPUT_PIPE_A   1
+#define INTELFB_OUTPUT_PIPE_B   2
+
+/*** Data Types ***/
+
+/* supported chipsets */
+enum intel_chips {
+	INTEL_830M,
+	INTEL_845G,
+	INTEL_85XGM,
+	INTEL_852GM,
+	INTEL_852GME,
+	INTEL_854,
+	INTEL_855GM,
+	INTEL_855GME,
+	INTEL_865G,
+	INTEL_915G,
+	INTEL_915GM,
+	INTEL_945G,
+	INTEL_945GM,
+	INTEL_945GME,
+	INTEL_965G,
+	INTEL_965GM,
+};
+
+struct intelfb_hwstate {
+	u32 vga0_divisor;
+	u32 vga1_divisor;
+	u32 vga_pd;
+	u32 dpll_a;
+	u32 dpll_b;
+	u32 fpa0;
+	u32 fpa1;
+	u32 fpb0;
+	u32 fpb1;
+	u32 palette_a[PALETTE_8_ENTRIES];
+	u32 palette_b[PALETTE_8_ENTRIES];
+	u32 htotal_a;
+	u32 hblank_a;
+	u32 hsync_a;
+	u32 vtotal_a;
+	u32 vblank_a;
+	u32 vsync_a;
+	u32 src_size_a;
+	u32 bclrpat_a;
+	u32 htotal_b;
+	u32 hblank_b;
+	u32 hsync_b;
+	u32 vtotal_b;
+	u32 vblank_b;
+	u32 vsync_b;
+	u32 src_size_b;
+	u32 bclrpat_b;
+	u32 adpa;
+	u32 dvoa;
+	u32 dvob;
+	u32 dvoc;
+	u32 dvoa_srcdim;
+	u32 dvob_srcdim;
+	u32 dvoc_srcdim;
+	u32 lvds;
+	u32 pipe_a_conf;
+	u32 pipe_b_conf;
+	u32 disp_arb;
+	u32 cursor_a_control;
+	u32 cursor_b_control;
+	u32 cursor_a_base;
+	u32 cursor_b_base;
+	u32 cursor_size;
+	u32 disp_a_ctrl;
+	u32 disp_b_ctrl;
+	u32 disp_a_base;
+	u32 disp_b_base;
+	u32 cursor_a_palette[4];
+	u32 cursor_b_palette[4];
+	u32 disp_a_stride;
+	u32 disp_b_stride;
+	u32 vgacntrl;
+	u32 add_id;
+	u32 swf0x[7];
+	u32 swf1x[7];
+	u32 swf3x[3];
+	u32 fence[8];
+	u32 instpm;
+	u32 mem_mode;
+	u32 fw_blc_0;
+	u32 fw_blc_1;
+	u16 hwstam;
+	u16 ier;
+	u16 iir;
+	u16 imr;
+};
+
+struct intelfb_heap_data {
+	u32 physical;
+	u8 __iomem *virtual;
+	u32 offset;		/* in GATT pages */
+	u32 size;		/* in bytes */
+};
+
+#ifdef CONFIG_FB_INTEL_I2C
+struct intelfb_i2c_chan {
+    struct intelfb_info *dinfo;
+    u32 reg;
+    struct i2c_adapter adapter;
+    struct i2c_algo_bit_data algo;
+};
+#endif
+
+struct intelfb_output_rec {
+    int type;
+    int pipe;
+    int flags;
+
+#ifdef CONFIG_FB_INTEL_I2C
+    struct intelfb_i2c_chan i2c_bus;
+    struct intelfb_i2c_chan ddc_bus;
+#endif
+};
+
+struct intelfb_vsync {
+	wait_queue_head_t wait;
+	unsigned int count;
+	int pan_display;
+	u32 pan_offset;
+};
+
+struct intelfb_info {
+	struct fb_info *info;
+	struct fb_ops  *fbops;
+	struct pci_dev *pdev;
+
+	struct intelfb_hwstate save_state;
+
+	/* agpgart structs */
+	struct agp_memory *gtt_fb_mem;     /* use all stolen memory or vram */
+	struct agp_memory *gtt_ring_mem;   /* ring buffer */
+	struct agp_memory *gtt_cursor_mem; /* hw cursor */
+
+	/* use a gart reserved fb mem */
+	u8 fbmem_gart;
+
+	/* mtrr support */
+	int mtrr_reg;
+	u32 has_mtrr;
+
+	/* heap data */
+	struct intelfb_heap_data aperture;
+	struct intelfb_heap_data fb;
+	struct intelfb_heap_data ring;
+	struct intelfb_heap_data cursor;
+
+	/* mmio regs */
+	u32 mmio_base_phys;
+	u8 __iomem *mmio_base;
+
+	/* fb start offset (in bytes) */
+	u32 fb_start;
+
+	/* ring buffer */
+	u32 ring_head;
+	u32 ring_tail;
+	u32 ring_tail_mask;
+	u32 ring_space;
+	u32 ring_lockup;
+
+	/* palette */
+	u32 pseudo_palette[16];
+
+	/* chip info */
+	int pci_chipset;
+	int chipset;
+	const char *name;
+	int mobile;
+
+	/* current mode */
+	int bpp, depth;
+	u32 visual;
+	int xres, yres, pitch;
+	int pixclock;
+
+	/* current pipe */
+	int pipe;
+
+	/* some flags */
+	int accel;
+	int hwcursor;
+	int fixed_mode;
+	int ring_active;
+	int flag;
+	unsigned long irq_flags;
+	int open;
+
+	/* vsync */
+	struct intelfb_vsync vsync;
+	spinlock_t int_lock;
+
+	/* hw cursor */
+	int cursor_on;
+	int cursor_blanked;
+	u8  cursor_src[64];
+
+	/* initial parameters */
+	int initial_vga;
+	struct fb_var_screeninfo initial_var;
+	u32 initial_fb_base;
+	u32 initial_video_ram;
+	u32 initial_pitch;
+
+	/* driver registered */
+	int registered;
+
+	/* index into plls */
+	int pll_index;
+
+	/* outputs */
+	int num_outputs;
+	struct intelfb_output_rec output[MAX_OUTPUTS];
+};
+
+#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G) ||	\
+			((dinfo)->chipset == INTEL_915GM) ||	\
+			((dinfo)->chipset == INTEL_945G) ||	\
+			((dinfo)->chipset == INTEL_945GM) ||	\
+			((dinfo)->chipset == INTEL_945GME) ||	\
+			((dinfo)->chipset == INTEL_965G) ||	\
+			((dinfo)->chipset == INTEL_965GM))
+
+/*** function prototypes ***/
+
+extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
+
+#ifdef CONFIG_FB_INTEL_I2C
+extern void intelfb_create_i2c_busses(struct intelfb_info *dinfo);
+extern void intelfb_delete_i2c_busses(struct intelfb_info *dinfo);
+#endif
+
+#endif /* _INTELFB_H */
diff --git a/drivers/video/fbdev/intelfb/intelfb_i2c.c b/drivers/video/fbdev/intelfb/intelfb_i2c.c
new file mode 100644
index 000000000000..3300bd31d9d7
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfb_i2c.c
@@ -0,0 +1,209 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/io.h>
+
+#include "intelfb.h"
+#include "intelfbhw.h"
+
+/* bit locations in the registers */
+#define SCL_DIR_MASK		0x0001
+#define SCL_DIR			0x0002
+#define SCL_VAL_MASK		0x0004
+#define SCL_VAL_OUT		0x0008
+#define SCL_VAL_IN		0x0010
+#define SDA_DIR_MASK		0x0100
+#define SDA_DIR			0x0200
+#define SDA_VAL_MASK		0x0400
+#define SDA_VAL_OUT		0x0800
+#define SDA_VAL_IN		0x1000
+
+static void intelfb_gpio_setscl(void *data, int state)
+{
+	struct intelfb_i2c_chan *chan = data;
+	struct intelfb_info *dinfo = chan->dinfo;
+	u32 val;
+
+	OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) |
+	       SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
+	val = INREG(chan->reg);
+}
+
+static void intelfb_gpio_setsda(void *data, int state)
+{
+	struct intelfb_i2c_chan *chan = data;
+	struct intelfb_info *dinfo = chan->dinfo;
+	u32 val;
+
+	OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) |
+	       SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
+	val = INREG(chan->reg);
+}
+
+static int intelfb_gpio_getscl(void *data)
+{
+	struct intelfb_i2c_chan *chan = data;
+	struct intelfb_info *dinfo = chan->dinfo;
+	u32 val;
+
+	OUTREG(chan->reg, SCL_DIR_MASK);
+	OUTREG(chan->reg, 0);
+	val = INREG(chan->reg);
+	return ((val & SCL_VAL_IN) != 0);
+}
+
+static int intelfb_gpio_getsda(void *data)
+{
+	struct intelfb_i2c_chan *chan = data;
+	struct intelfb_info *dinfo = chan->dinfo;
+	u32 val;
+
+	OUTREG(chan->reg, SDA_DIR_MASK);
+	OUTREG(chan->reg, 0);
+	val = INREG(chan->reg);
+	return ((val & SDA_VAL_IN) != 0);
+}
+
+static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
+				 struct intelfb_i2c_chan *chan,
+				 const u32 reg, const char *name,
+				 int class)
+{
+	int rc;
+
+	chan->dinfo			= dinfo;
+	chan->reg			= reg;
+	snprintf(chan->adapter.name, sizeof(chan->adapter.name),
+		 "intelfb %s", name);
+	chan->adapter.class		= class;
+	chan->adapter.owner		= THIS_MODULE;
+	chan->adapter.algo_data		= &chan->algo;
+	chan->adapter.dev.parent	= &chan->dinfo->pdev->dev;
+	chan->algo.setsda		= intelfb_gpio_setsda;
+	chan->algo.setscl		= intelfb_gpio_setscl;
+	chan->algo.getsda		= intelfb_gpio_getsda;
+	chan->algo.getscl		= intelfb_gpio_getscl;
+	chan->algo.udelay		= 40;
+	chan->algo.timeout		= 20;
+	chan->algo.data			= chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	/* Raise SCL and SDA */
+	intelfb_gpio_setsda(chan, 1);
+	intelfb_gpio_setscl(chan, 1);
+	udelay(20);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		DBG_MSG("I2C bus %s registered.\n", name);
+	else
+		WRN_MSG("Failed to register I2C bus %s.\n", name);
+	return rc;
+}
+
+void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
+{
+	int i = 0;
+
+	/* everyone has at least a single analog output */
+	dinfo->num_outputs = 1;
+	dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;
+
+	/* setup the DDC bus for analog output */
+	intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
+			      "CRTDDC_A", I2C_CLASS_DDC);
+	i++;
+
+	/* need to add the output busses for each device
+	   - this function is very incomplete
+	   - i915GM has LVDS and TVOUT for example
+	*/
+	switch(dinfo->chipset) {
+	case INTEL_830M:
+	case INTEL_845G:
+	case INTEL_854:
+	case INTEL_855GM:
+	case INTEL_865G:
+		dinfo->output[i].type = INTELFB_OUTPUT_DVO;
+		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
+				      GPIOD, "DVODDC_D", I2C_CLASS_DDC);
+		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
+				      GPIOE, "DVOI2C_E", 0);
+		i++;
+		break;
+	case INTEL_915G:
+	case INTEL_915GM:
+		/* has some LVDS + tv-out */
+	case INTEL_945G:
+	case INTEL_945GM:
+	case INTEL_945GME:
+	case INTEL_965G:
+	case INTEL_965GM:
+		/* SDVO ports have a single control bus - 2 devices */
+		dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
+		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
+				      GPIOE, "SDVOCTRL_E", 0);
+		/* TODO: initialize the SDVO */
+		/* I830SDVOInit(pScrn, i, DVOB); */
+		i++;
+
+		/* set up SDVOC */
+		dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
+		dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
+		/* TODO: initialize the SDVO */
+		/* I830SDVOInit(pScrn, i, DVOC); */
+		i++;
+		break;
+	}
+	dinfo->num_outputs = i;
+}
+
+void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
+{
+	int i;
+
+	for (i = 0; i < MAX_OUTPUTS; i++) {
+		if (dinfo->output[i].i2c_bus.dinfo) {
+			i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
+			dinfo->output[i].i2c_bus.dinfo = NULL;
+		}
+		if (dinfo->output[i].ddc_bus.dinfo) {
+			i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
+			dinfo->output[i].ddc_bus.dinfo = NULL;
+		}
+	}
+}
diff --git a/drivers/video/fbdev/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c
new file mode 100644
index 000000000000..b847d530471a
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfbdrv.c
@@ -0,0 +1,1704 @@
+/*
+ * intelfb
+ *
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
+ * 945G/945GM/945GME/965G/965GM integrated graphics chips.
+ *
+ * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+ *                   2004 Sylvain Meyer
+ *                   2006 David Airlie
+ *
+ * This driver consists of two parts.  The first part (intelfbdrv.c) provides
+ * the basic fbdev interfaces, is derived in part from the radeonfb and
+ * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c)
+ * provides the code to program the hardware.  Most of it is derived from
+ * the i810/i830 XFree86 driver.  The HW-specific code is covered here
+ * under a dual license (GPL and MIT/XFree86 license).
+ *
+ * Author: David Dawes
+ *
+ */
+
+/* $DHD: intelfb/intelfbdrv.c,v 1.20 2003/06/27 15:17:40 dawes Exp $ */
+
+/*
+ * Changes:
+ *    01/2003 - Initial driver (0.1.0), no mode switching, no acceleration.
+ *		This initial version is a basic core that works a lot like
+ *		the vesafb driver.  It must be built-in to the kernel,
+ *		and the initial video mode must be set with vga=XXX at
+ *		boot time.  (David Dawes)
+ *
+ *    01/2003 - Version 0.2.0: Mode switching added, colormap support
+ *		implemented, Y panning, and soft screen blanking implemented.
+ *		No acceleration yet.  (David Dawes)
+ *
+ *    01/2003 - Version 0.3.0: fbcon acceleration support added.  Module
+ *		option handling added.  (David Dawes)
+ *
+ *    01/2003 - Version 0.4.0: fbcon HW cursor support added.  (David Dawes)
+ *
+ *    01/2003 - Version 0.4.1: Add auto-generation of built-in modes.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.4.2: Add check for active non-CRT devices, and
+ *		mode validation checks.  (David Dawes)
+ *
+ *    02/2003 - Version 0.4.3: Check when the VC is in graphics mode so that
+ *		acceleration is disabled while an XFree86 server is running.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.4.4: Monitor DPMS support.  (David Dawes)
+ *
+ *    02/2003 - Version 0.4.5: Basic XFree86 + fbdev working.  (David Dawes)
+ *
+ *    02/2003 - Version 0.5.0: Modify to work with the 2.5.32 kernel as well
+ *		as 2.4.x kernels.  (David Dawes)
+ *
+ *    02/2003 - Version 0.6.0: Split out HW-specifics into a separate file.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.7.0: Test on 852GM/855GM.  Acceleration and HW
+ *		cursor are disabled on this platform.  (David Dawes)
+ *
+ *    02/2003 - Version 0.7.1: Test on 845G.  Acceleration is disabled
+ *		on this platform.  (David Dawes)
+ *
+ *    02/2003 - Version 0.7.2: Test on 830M.  Acceleration and HW
+ *		cursor are disabled on this platform.  (David Dawes)
+ *
+ *    02/2003 - Version 0.7.3: Fix 8-bit modes for mobile platforms
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.7.4: Add checks for FB and FBCON_HAS_CFB* configured
+ *		in the kernel, and add mode bpp verification and default
+ *		bpp selection based on which FBCON_HAS_CFB* are configured.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.7.5: Add basic package/install scripts based on the
+ *		DRI packaging scripts.  (David Dawes)
+ *
+ *    04/2003 - Version 0.7.6: Fix typo that affects builds with SMP-enabled
+ *		kernels.  (David Dawes, reported by Anupam).
+ *
+ *    06/2003 - Version 0.7.7:
+ *              Fix Makefile.kernel build problem (Tsutomu Yasuda).
+ *		Fix mis-placed #endif (2.4.21 kernel).
+ *
+ *    09/2004 - Version 0.9.0 - by Sylvain Meyer
+ *              Port to linux 2.6 kernel fbdev
+ *              Fix HW accel and HW cursor on i845G
+ *              Use of agpgart for fb memory reservation
+ *              Add mtrr support
+ *
+ *    10/2004 - Version 0.9.1
+ *              Use module_param instead of old MODULE_PARM
+ *              Some cleanup
+ *
+ *    11/2004 - Version 0.9.2
+ *              Add vram option to reserve more memory than stolen by BIOS
+ *              Fix intelfbhw_pan_display typo
+ *              Add __initdata annotations
+ *
+ *    04/2008 - Version 0.9.5
+ *              Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
+ *
+ *    08/2008 - Version 0.9.6
+ *              Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/screen_info.h>
+
+#include <asm/io.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "intelfb.h"
+#include "intelfbhw.h"
+#include "../edid.h"
+
+static void get_initial_mode(struct intelfb_info *dinfo);
+static void update_dinfo(struct intelfb_info *dinfo,
+			 struct fb_var_screeninfo *var);
+static int intelfb_open(struct fb_info *info, int user);
+static int intelfb_release(struct fb_info *info, int user);
+static int intelfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static int intelfb_set_par(struct fb_info *info);
+static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			     unsigned blue, unsigned transp,
+			     struct fb_info *info);
+
+static int intelfb_blank(int blank, struct fb_info *info);
+static int intelfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info);
+
+static void intelfb_fillrect(struct fb_info *info,
+			     const struct fb_fillrect *rect);
+static void intelfb_copyarea(struct fb_info *info,
+			     const struct fb_copyarea *region);
+static void intelfb_imageblit(struct fb_info *info,
+			      const struct fb_image *image);
+static int intelfb_cursor(struct fb_info *info,
+			   struct fb_cursor *cursor);
+
+static int intelfb_sync(struct fb_info *info);
+
+static int intelfb_ioctl(struct fb_info *info,
+			 unsigned int cmd, unsigned long arg);
+
+static int intelfb_pci_register(struct pci_dev *pdev,
+				const struct pci_device_id *ent);
+static void intelfb_pci_unregister(struct pci_dev *pdev);
+static int intelfb_set_fbinfo(struct intelfb_info *dinfo);
+
+/*
+ * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
+ * mobile chipsets from being registered.
+ */
+#if DETECT_VGA_CLASS_ONLY
+#define INTELFB_CLASS_MASK ~0 << 8
+#else
+#define INTELFB_CLASS_MASK 0
+#endif
+
+static struct pci_device_id intelfb_pci_table[] = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_854, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_854 },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
+	{ 0, }
+};
+
+/* Global data */
+static int num_registered = 0;
+
+/* fb ops */
+static struct fb_ops intel_fb_ops = {
+	.owner =		THIS_MODULE,
+	.fb_open =              intelfb_open,
+	.fb_release =           intelfb_release,
+	.fb_check_var =         intelfb_check_var,
+	.fb_set_par =           intelfb_set_par,
+	.fb_setcolreg =		intelfb_setcolreg,
+	.fb_blank =		intelfb_blank,
+	.fb_pan_display =       intelfb_pan_display,
+	.fb_fillrect  =         intelfb_fillrect,
+	.fb_copyarea  =         intelfb_copyarea,
+	.fb_imageblit =         intelfb_imageblit,
+	.fb_cursor =            intelfb_cursor,
+	.fb_sync =              intelfb_sync,
+	.fb_ioctl =		intelfb_ioctl
+};
+
+/* PCI driver module table */
+static struct pci_driver intelfb_driver = {
+	.name =		"intelfb",
+	.id_table =	intelfb_pci_table,
+	.probe =	intelfb_pci_register,
+	.remove =	intelfb_pci_unregister,
+};
+
+/* Module description/parameters */
+MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
+	      "Sylvain Meyer <sylvain.meyer@worldonline.fr>");
+MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS
+		   " chipsets");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
+
+static bool accel       = 1;
+static int vram         = 4;
+static bool hwcursor    = 0;
+static bool mtrr        = 1;
+static bool fixed       = 0;
+static bool noinit      = 0;
+static bool noregister  = 0;
+static bool probeonly   = 0;
+static bool idonly      = 0;
+static int bailearly    = 0;
+static int voffset	= 48;
+static char *mode       = NULL;
+
+module_param(accel, bool, S_IRUGO);
+MODULE_PARM_DESC(accel, "Enable hardware acceleration");
+module_param(vram, int, S_IRUGO);
+MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
+module_param(voffset, int, S_IRUGO);
+MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
+module_param(hwcursor, bool, S_IRUGO);
+MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
+module_param(mtrr, bool, S_IRUGO);
+MODULE_PARM_DESC(mtrr, "Enable MTRR support");
+module_param(fixed, bool, S_IRUGO);
+MODULE_PARM_DESC(fixed, "Disable mode switching");
+module_param(noinit, bool, 0);
+MODULE_PARM_DESC(noinit, "Don't initialise graphics mode when loading");
+module_param(noregister, bool, 0);
+MODULE_PARM_DESC(noregister, "Don't register, just probe and exit (debug)");
+module_param(probeonly, bool, 0);
+MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");
+module_param(idonly, bool, 0);
+MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");
+module_param(bailearly, int, 0);
+MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
+module_param(mode, charp, S_IRUGO);
+MODULE_PARM_DESC(mode,
+		 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
+
+#ifndef MODULE
+#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
+#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
+#define OPT_STRVAL(opt, name) (opt + strlen(name))
+
+static __inline__ char * get_opt_string(const char *this_opt, const char *name)
+{
+	const char *p;
+	int i;
+	char *ret;
+
+	p = OPT_STRVAL(this_opt, name);
+	i = 0;
+	while (p[i] && p[i] != ' ' && p[i] != ',')
+		i++;
+	ret = kmalloc(i + 1, GFP_KERNEL);
+	if (ret) {
+		strncpy(ret, p, i);
+		ret[i] = '\0';
+	}
+	return ret;
+}
+
+static __inline__ int get_opt_int(const char *this_opt, const char *name,
+				  int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (!OPT_EQUAL(this_opt, name))
+		return 0;
+
+	*ret = OPT_INTVAL(this_opt, name);
+	return 1;
+}
+
+static __inline__ int get_opt_bool(const char *this_opt, const char *name,
+				   int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (OPT_EQUAL(this_opt, name)) {
+		if (this_opt[strlen(name)] == '=')
+			*ret = simple_strtoul(this_opt + strlen(name) + 1,
+					      NULL, 0);
+		else
+			*ret = 1;
+	} else {
+		if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
+			*ret = 0;
+		else
+			return 0;
+	}
+	return 1;
+}
+
+static int __init intelfb_setup(char *options)
+{
+	char *this_opt;
+
+	DBG_MSG("intelfb_setup\n");
+
+	if (!options || !*options) {
+		DBG_MSG("no options\n");
+		return 0;
+	} else
+		DBG_MSG("options: %s\n", options);
+
+	/*
+	 * These are the built-in options analogous to the module parameters
+	 * defined above.
+	 *
+	 * The syntax is:
+	 *
+	 *    video=intelfb:[mode][,<param>=<val>] ...
+	 *
+	 * e.g.,
+	 *
+	 *    video=intelfb:1024x768-16@75,accel=0
+	 */
+
+	while ((this_opt = strsep(&options, ","))) {
+		if (!*this_opt)
+			continue;
+		if (get_opt_bool(this_opt, "accel", &accel))
+			;
+		else if (get_opt_int(this_opt, "vram", &vram))
+			;
+		else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
+			;
+		else if (get_opt_bool(this_opt, "mtrr", &mtrr))
+			;
+		else if (get_opt_bool(this_opt, "fixed", &fixed))
+			;
+		else if (get_opt_bool(this_opt, "init", &noinit))
+			noinit = !noinit;
+		else if (OPT_EQUAL(this_opt, "mode="))
+			mode = get_opt_string(this_opt, "mode=");
+		else
+			mode = this_opt;
+	}
+
+	return 0;
+}
+
+#endif
+
+static int __init intelfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+#endif
+
+	DBG_MSG("intelfb_init\n");
+
+	INF_MSG("Framebuffer driver for "
+		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
+	INF_MSG("Version " INTELFB_VERSION "\n");
+
+	if (idonly)
+		return -ENODEV;
+
+#ifndef MODULE
+	if (fb_get_options("intelfb", &option))
+		return -ENODEV;
+	intelfb_setup(option);
+#endif
+
+	return pci_register_driver(&intelfb_driver);
+}
+
+static void __exit intelfb_exit(void)
+{
+	DBG_MSG("intelfb_exit\n");
+	pci_unregister_driver(&intelfb_driver);
+}
+
+module_init(intelfb_init);
+module_exit(intelfb_exit);
+
+/***************************************************************
+ *                     mtrr support functions                  *
+ ***************************************************************/
+
+#ifdef CONFIG_MTRR
+static inline void set_mtrr(struct intelfb_info *dinfo)
+{
+	dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,
+				   dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);
+	if (dinfo->mtrr_reg < 0) {
+		ERR_MSG("unable to set MTRR\n");
+		return;
+	}
+	dinfo->has_mtrr = 1;
+}
+static inline void unset_mtrr(struct intelfb_info *dinfo)
+{
+	if (dinfo->has_mtrr)
+		mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
+			 dinfo->aperture.size);
+}
+#else
+#define set_mtrr(x) WRN_MSG("MTRR is disabled in the kernel\n")
+
+#define unset_mtrr(x) do { } while (0)
+#endif /* CONFIG_MTRR */
+
+/***************************************************************
+ *                        driver init / cleanup                *
+ ***************************************************************/
+
+static void cleanup(struct intelfb_info *dinfo)
+{
+	DBG_MSG("cleanup\n");
+
+	if (!dinfo)
+		return;
+
+	intelfbhw_disable_irq(dinfo);
+
+	fb_dealloc_cmap(&dinfo->info->cmap);
+	kfree(dinfo->info->pixmap.addr);
+
+	if (dinfo->registered)
+		unregister_framebuffer(dinfo->info);
+
+	unset_mtrr(dinfo);
+
+	if (dinfo->fbmem_gart && dinfo->gtt_fb_mem) {
+		agp_unbind_memory(dinfo->gtt_fb_mem);
+		agp_free_memory(dinfo->gtt_fb_mem);
+	}
+	if (dinfo->gtt_cursor_mem) {
+		agp_unbind_memory(dinfo->gtt_cursor_mem);
+		agp_free_memory(dinfo->gtt_cursor_mem);
+	}
+	if (dinfo->gtt_ring_mem) {
+		agp_unbind_memory(dinfo->gtt_ring_mem);
+		agp_free_memory(dinfo->gtt_ring_mem);
+	}
+
+#ifdef CONFIG_FB_INTEL_I2C
+	/* un-register I2C bus */
+	intelfb_delete_i2c_busses(dinfo);
+#endif
+
+	if (dinfo->mmio_base)
+		iounmap((void __iomem *)dinfo->mmio_base);
+	if (dinfo->aperture.virtual)
+		iounmap((void __iomem *)dinfo->aperture.virtual);
+
+	if (dinfo->flag & INTELFB_MMIO_ACQUIRED)
+		release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
+	if (dinfo->flag & INTELFB_FB_ACQUIRED)
+		release_mem_region(dinfo->aperture.physical,
+				   dinfo->aperture.size);
+	framebuffer_release(dinfo->info);
+}
+
+#define bailout(dinfo) do {						\
+	DBG_MSG("bailout\n");						\
+	cleanup(dinfo);							\
+	INF_MSG("Not going to register framebuffer, exiting...\n");	\
+	return -ENODEV;							\
+} while (0)
+
+
+static int intelfb_pci_register(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct intelfb_info *dinfo;
+	int i, err, dvo;
+	int aperture_size, stolen_size;
+	struct agp_kern_info gtt_info;
+	int agp_memtype;
+	const char *s;
+	struct agp_bridge_data *bridge;
+	int aperture_bar = 0;
+	int mmio_bar = 1;
+	int offset;
+
+	DBG_MSG("intelfb_pci_register\n");
+
+	num_registered++;
+	if (num_registered != 1) {
+		ERR_MSG("Attempted to register %d devices "
+			"(should be only 1).\n", num_registered);
+		return -ENODEV;
+	}
+
+	info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);
+	if (!info) {
+		ERR_MSG("Could not allocate memory for intelfb_info.\n");
+		return -ENODEV;
+	}
+	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
+		ERR_MSG("Could not allocate cmap for intelfb_info.\n");
+		goto err_out_cmap;
+	}
+
+	dinfo = info->par;
+	dinfo->info  = info;
+	dinfo->fbops = &intel_fb_ops;
+	dinfo->pdev  = pdev;
+
+	/* Reserve pixmap space. */
+	info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);
+	if (info->pixmap.addr == NULL) {
+		ERR_MSG("Cannot reserve pixmap memory.\n");
+		goto err_out_pixmap;
+	}
+
+	/* set early this option because it could be changed by tv encoder
+	   driver */
+	dinfo->fixed_mode = fixed;
+
+	/* Enable device. */
+	if ((err = pci_enable_device(pdev))) {
+		ERR_MSG("Cannot enable device.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	/* Set base addresses. */
+	if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
+
+		aperture_bar = 2;
+		mmio_bar = 0;
+	}
+	dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
+	dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);
+	dinfo->mmio_base_phys    = pci_resource_start(pdev, mmio_bar);
+	DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
+		(unsigned long long)pci_resource_start(pdev, aperture_bar),
+		(unsigned long long)pci_resource_len(pdev, aperture_bar),
+		(unsigned long long)pci_resource_start(pdev, mmio_bar),
+		(unsigned long long)pci_resource_len(pdev, mmio_bar));
+
+	/* Reserve the fb and MMIO regions */
+	if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
+				INTELFB_MODULE_NAME)) {
+		ERR_MSG("Cannot reserve FB region.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	dinfo->flag |= INTELFB_FB_ACQUIRED;
+
+	if (!request_mem_region(dinfo->mmio_base_phys,
+				INTEL_REG_SIZE,
+				INTELFB_MODULE_NAME)) {
+		ERR_MSG("Cannot reserve MMIO region.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	dinfo->flag |= INTELFB_MMIO_ACQUIRED;
+
+	/* Get the chipset info. */
+	dinfo->pci_chipset = pdev->device;
+
+	if (intelfbhw_get_chipset(pdev, dinfo)) {
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) {
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "
+		"stolen memory %dkB\n",
+		pdev->bus->number, PCI_SLOT(pdev->devfn),
+		PCI_FUNC(pdev->devfn), dinfo->name,
+		BtoMB(aperture_size), BtoKB(stolen_size));
+
+	/* Set these from the options. */
+	dinfo->accel    = accel;
+	dinfo->hwcursor = hwcursor;
+
+	if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {
+		INF_MSG("Acceleration is not supported for the %s chipset.\n",
+			dinfo->name);
+		dinfo->accel = 0;
+	}
+
+	/* Framebuffer parameters - Use all the stolen memory if >= vram */
+	if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
+		dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
+		dinfo->fbmem_gart = 0;
+	} else {
+		dinfo->fb.size =  MB(vram);
+		dinfo->fbmem_gart = 1;
+	}
+
+	/* Allocate space for the ring buffer and HW cursor if enabled. */
+	if (dinfo->accel) {
+		dinfo->ring.size = RINGBUFFER_SIZE;
+		dinfo->ring_tail_mask = dinfo->ring.size - 1;
+	}
+	if (dinfo->hwcursor)
+		dinfo->cursor.size = HW_CURSOR_SIZE;
+
+	/* Use agpgart to manage the GATT */
+	if (!(bridge = agp_backend_acquire(pdev))) {
+		ERR_MSG("cannot acquire agp\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	/* get the current gatt info */
+	if (agp_copy_info(bridge, &gtt_info)) {
+		ERR_MSG("cannot get agp info\n");
+		agp_backend_release(bridge);
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (MB(voffset) < stolen_size)
+		offset = (stolen_size >> 12);
+	else
+		offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
+
+	/* set the mem offsets - set them after the already used pages */
+	if (dinfo->accel)
+		dinfo->ring.offset = offset + gtt_info.current_memory;
+	if (dinfo->hwcursor)
+		dinfo->cursor.offset = offset +
+			+ gtt_info.current_memory + (dinfo->ring.size >> 12);
+	if (dinfo->fbmem_gart)
+		dinfo->fb.offset = offset +
+			+ gtt_info.current_memory + (dinfo->ring.size >> 12)
+			+ (dinfo->cursor.size >> 12);
+
+	/* Allocate memories (which aren't stolen) */
+	/* Map the fb and MMIO regions */
+	/* ioremap only up to the end of used aperture */
+	dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
+		(dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
+		 + dinfo->fb.size);
+	if (!dinfo->aperture.virtual) {
+		ERR_MSG("Cannot remap FB region.\n");
+		agp_backend_release(bridge);
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	dinfo->mmio_base =
+		(u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
+					      INTEL_REG_SIZE);
+	if (!dinfo->mmio_base) {
+		ERR_MSG("Cannot remap MMIO region.\n");
+		agp_backend_release(bridge);
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (dinfo->accel) {
+		if (!(dinfo->gtt_ring_mem =
+		      agp_allocate_memory(bridge, dinfo->ring.size >> 12,
+					  AGP_NORMAL_MEMORY))) {
+			ERR_MSG("cannot allocate ring buffer memory\n");
+			agp_backend_release(bridge);
+			cleanup(dinfo);
+			return -ENOMEM;
+		}
+		if (agp_bind_memory(dinfo->gtt_ring_mem,
+				    dinfo->ring.offset)) {
+			ERR_MSG("cannot bind ring buffer memory\n");
+			agp_backend_release(bridge);
+			cleanup(dinfo);
+			return -EBUSY;
+		}
+		dinfo->ring.physical = dinfo->aperture.physical
+			+ (dinfo->ring.offset << 12);
+		dinfo->ring.virtual  = dinfo->aperture.virtual
+			+ (dinfo->ring.offset << 12);
+		dinfo->ring_head = 0;
+	}
+	if (dinfo->hwcursor) {
+		agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
+			: AGP_NORMAL_MEMORY;
+		if (!(dinfo->gtt_cursor_mem =
+		      agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
+					  agp_memtype))) {
+			ERR_MSG("cannot allocate cursor memory\n");
+			agp_backend_release(bridge);
+			cleanup(dinfo);
+			return -ENOMEM;
+		}
+		if (agp_bind_memory(dinfo->gtt_cursor_mem,
+				    dinfo->cursor.offset)) {
+			ERR_MSG("cannot bind cursor memory\n");
+			agp_backend_release(bridge);
+			cleanup(dinfo);
+			return -EBUSY;
+		}
+		if (dinfo->mobile)
+			dinfo->cursor.physical
+				= dinfo->gtt_cursor_mem->physical;
+		else
+			dinfo->cursor.physical = dinfo->aperture.physical
+				+ (dinfo->cursor.offset << 12);
+		dinfo->cursor.virtual = dinfo->aperture.virtual
+			+ (dinfo->cursor.offset << 12);
+	}
+	if (dinfo->fbmem_gart) {
+		if (!(dinfo->gtt_fb_mem =
+		      agp_allocate_memory(bridge, dinfo->fb.size >> 12,
+					  AGP_NORMAL_MEMORY))) {
+			WRN_MSG("cannot allocate framebuffer memory - use "
+				"the stolen one\n");
+			dinfo->fbmem_gart = 0;
+		}
+		if (agp_bind_memory(dinfo->gtt_fb_mem,
+				    dinfo->fb.offset)) {
+			WRN_MSG("cannot bind framebuffer memory - use "
+				"the stolen one\n");
+			dinfo->fbmem_gart = 0;
+		}
+	}
+
+	/* update framebuffer memory parameters */
+	if (!dinfo->fbmem_gart)
+		dinfo->fb.offset = 0;   /* starts at offset 0 */
+	dinfo->fb.physical = dinfo->aperture.physical
+		+ (dinfo->fb.offset << 12);
+	dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);
+	dinfo->fb_start = dinfo->fb.offset << 12;
+
+	/* release agpgart */
+	agp_backend_release(bridge);
+
+	if (mtrr)
+		set_mtrr(dinfo);
+
+	DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",
+		dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
+		dinfo->fb.virtual);
+	DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",
+		dinfo->mmio_base_phys, INTEL_REG_SIZE,
+		dinfo->mmio_base);
+	DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",
+		dinfo->ring.physical, dinfo->ring.size,
+		dinfo->ring.virtual);
+	DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",
+		dinfo->cursor.physical, dinfo->cursor.size,
+		dinfo->cursor.virtual, dinfo->cursor.offset,
+		dinfo->cursor.physical);
+
+	DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
+		"noinit = %d\n", vram, accel, hwcursor, fixed, noinit);
+	DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");
+
+	if (probeonly)
+		bailout(dinfo);
+
+	/*
+	 * Check if the LVDS port or any DVO ports are enabled.  If so,
+	 * don't allow mode switching
+	 */
+	dvo = intelfbhw_check_non_crt(dinfo);
+	if (dvo) {
+		dinfo->fixed_mode = 1;
+		WRN_MSG("Non-CRT device is enabled ( ");
+		i = 0;
+		while (dvo) {
+			if (dvo & 1) {
+				s = intelfbhw_dvo_to_string(1 << i);
+				if (s)
+					printk("%s ", s);
+			}
+			dvo >>= 1;
+			++i;
+		}
+		printk(").  Disabling mode switching.\n");
+	}
+
+	if (bailearly == 1)
+		bailout(dinfo);
+
+	if (FIXED_MODE(dinfo) &&
+	    screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) {
+		ERR_MSG("Video mode must be programmed at boot time.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (bailearly == 2)
+		bailout(dinfo);
+
+	/* Initialise dinfo and related data. */
+	/* If an initial mode was programmed at boot time, get its details. */
+	if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
+		get_initial_mode(dinfo);
+
+	if (bailearly == 3)
+		bailout(dinfo);
+
+	if (FIXED_MODE(dinfo))	/* remap fb address */
+		update_dinfo(dinfo, &dinfo->initial_var);
+
+	if (bailearly == 4)
+		bailout(dinfo);
+
+
+	if (intelfb_set_fbinfo(dinfo)) {
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (bailearly == 5)
+		bailout(dinfo);
+
+#ifdef CONFIG_FB_INTEL_I2C
+	/* register I2C bus */
+	intelfb_create_i2c_busses(dinfo);
+#endif
+
+	if (bailearly == 6)
+		bailout(dinfo);
+
+	pci_set_drvdata(pdev, dinfo);
+
+	/* Save the initial register state. */
+	i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,
+				    bailearly > 6 ? bailearly - 6 : 0);
+	if (i != 0) {
+		DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);
+		bailout(dinfo);
+	}
+
+	intelfbhw_print_hw_state(dinfo, &dinfo->save_state);
+
+	if (bailearly == 18)
+		bailout(dinfo);
+
+	/* read active pipe */
+	dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
+
+	/* Cursor initialisation */
+	if (dinfo->hwcursor) {
+		intelfbhw_cursor_init(dinfo);
+		intelfbhw_cursor_reset(dinfo);
+	}
+
+	if (bailearly == 19)
+		bailout(dinfo);
+
+	/* 2d acceleration init */
+	if (dinfo->accel)
+		intelfbhw_2d_start(dinfo);
+
+	if (bailearly == 20)
+		bailout(dinfo);
+
+	if (noregister)
+		bailout(dinfo);
+
+	if (register_framebuffer(dinfo->info) < 0) {
+		ERR_MSG("Cannot register framebuffer.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	dinfo->registered = 1;
+	dinfo->open = 0;
+
+	init_waitqueue_head(&dinfo->vsync.wait);
+	spin_lock_init(&dinfo->int_lock);
+	dinfo->irq_flags = 0;
+	dinfo->vsync.pan_display = 0;
+	dinfo->vsync.pan_offset = 0;
+
+	return 0;
+
+err_out_pixmap:
+	fb_dealloc_cmap(&info->cmap);
+err_out_cmap:
+	framebuffer_release(info);
+	return -ENODEV;
+}
+
+static void intelfb_pci_unregister(struct pci_dev *pdev)
+{
+	struct intelfb_info *dinfo = pci_get_drvdata(pdev);
+
+	DBG_MSG("intelfb_pci_unregister\n");
+
+	if (!dinfo)
+		return;
+
+	cleanup(dinfo);
+}
+
+/***************************************************************
+ *                       helper functions                      *
+ ***************************************************************/
+
+int __inline__ intelfb_var_to_depth(const struct fb_var_screeninfo *var)
+{
+	DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
+		var->bits_per_pixel, var->green.length);
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		return (var->green.length == 6) ? 16 : 15;
+	case 32:
+		return 24;
+	default:
+		return var->bits_per_pixel;
+	}
+}
+
+
+static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
+{
+	int xtot = var->xres + var->left_margin + var->right_margin +
+		   var->hsync_len;
+	int ytot = var->yres + var->upper_margin + var->lower_margin +
+		   var->vsync_len;
+
+	return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
+}
+
+/***************************************************************
+ *                Various intialisation functions              *
+ ***************************************************************/
+
+static void get_initial_mode(struct intelfb_info *dinfo)
+{
+	struct fb_var_screeninfo *var;
+	int xtot, ytot;
+
+	DBG_MSG("get_initial_mode\n");
+
+	dinfo->initial_vga = 1;
+	dinfo->initial_fb_base = screen_info.lfb_base;
+	dinfo->initial_video_ram = screen_info.lfb_size * KB(64);
+	dinfo->initial_pitch = screen_info.lfb_linelength;
+
+	var = &dinfo->initial_var;
+	memset(var, 0, sizeof(*var));
+	var->xres = screen_info.lfb_width;
+	var->yres = screen_info.lfb_height;
+	var->bits_per_pixel = screen_info.lfb_depth;
+	switch (screen_info.lfb_depth) {
+	case 15:
+		var->bits_per_pixel = 16;
+		break;
+	case 24:
+		var->bits_per_pixel = 32;
+		break;
+	}
+
+	DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",
+		dinfo->initial_fb_base, dinfo->initial_video_ram,
+		BtoKB(dinfo->initial_video_ram));
+
+	DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",
+		var->xres, var->yres, var->bits_per_pixel,
+		dinfo->initial_pitch);
+
+	/* Dummy timing values (assume 60Hz) */
+	var->left_margin = (var->xres / 8) & 0xf8;
+	var->right_margin = 32;
+	var->upper_margin = 16;
+	var->lower_margin = 4;
+	var->hsync_len = (var->xres / 8) & 0xf8;
+	var->vsync_len = 4;
+
+	xtot = var->xres + var->left_margin +
+		var->right_margin + var->hsync_len;
+	ytot = var->yres + var->upper_margin +
+		var->lower_margin + var->vsync_len;
+	var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;
+
+	var->height = -1;
+	var->width = -1;
+
+	if (var->bits_per_pixel > 8) {
+		var->red.offset = screen_info.red_pos;
+		var->red.length = screen_info.red_size;
+		var->green.offset = screen_info.green_pos;
+		var->green.length = screen_info.green_size;
+		var->blue.offset = screen_info.blue_pos;
+		var->blue.length = screen_info.blue_size;
+		var->transp.offset = screen_info.rsvd_pos;
+		var->transp.length = screen_info.rsvd_size;
+	} else {
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+	}
+}
+
+static int intelfb_init_var(struct intelfb_info *dinfo)
+{
+	struct fb_var_screeninfo *var;
+	int msrc = 0;
+
+	DBG_MSG("intelfb_init_var\n");
+
+	var = &dinfo->info->var;
+	if (FIXED_MODE(dinfo)) {
+	        memcpy(var, &dinfo->initial_var,
+		       sizeof(struct fb_var_screeninfo));
+		msrc = 5;
+	} else {
+		const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
+		u8 *edid_d = NULL;
+
+		if (edid_s) {
+			edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);
+
+			if (edid_d) {
+				fb_edid_to_monspecs(edid_d,
+						    &dinfo->info->monspecs);
+				kfree(edid_d);
+			}
+		}
+
+		if (mode) {
+			printk("intelfb: Looking for mode in private "
+			       "database\n");
+			msrc = fb_find_mode(var, dinfo->info, mode,
+					    dinfo->info->monspecs.modedb,
+					    dinfo->info->monspecs.modedb_len,
+					    NULL, 0);
+
+			if (msrc && msrc > 1) {
+				printk("intelfb: No mode in private database, "
+				       "intelfb: looking for mode in global "
+				       "database ");
+				msrc = fb_find_mode(var, dinfo->info, mode,
+						    NULL, 0, NULL, 0);
+
+				if (msrc)
+					msrc |= 8;
+			}
+
+		}
+
+		if (!msrc)
+			msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
+					    NULL, 0, NULL, 0);
+	}
+
+	if (!msrc) {
+		ERR_MSG("Cannot find a suitable video mode.\n");
+		return 1;
+	}
+
+	INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres,
+		var->bits_per_pixel, var_to_refresh(var));
+
+	DBG_MSG("Initial video mode is from %d.\n", msrc);
+
+#if ALLOCATE_FOR_PANNING
+	/* Allow use of half of the video ram for panning */
+	var->xres_virtual = var->xres;
+	var->yres_virtual =
+		dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres);
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+#else
+	var->yres_virtual = var->yres;
+#endif
+
+	if (dinfo->accel)
+		var->accel_flags |= FB_ACCELF_TEXT;
+	else
+		var->accel_flags &= ~FB_ACCELF_TEXT;
+
+	return 0;
+}
+
+static int intelfb_set_fbinfo(struct intelfb_info *dinfo)
+{
+	struct fb_info *info = dinfo->info;
+
+	DBG_MSG("intelfb_set_fbinfo\n");
+
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &intel_fb_ops;
+	info->pseudo_palette = dinfo->pseudo_palette;
+
+	info->pixmap.size = 64*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if (intelfb_init_var(dinfo))
+		return 1;
+
+	info->pixmap.scan_align = 1;
+	strcpy(info->fix.id, dinfo->name);
+	info->fix.smem_start = dinfo->fb.physical;
+	info->fix.smem_len = dinfo->fb.size;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 8;
+	info->fix.ypanstep = 1;
+	info->fix.ywrapstep = 0;
+	info->fix.mmio_start = dinfo->mmio_base_phys;
+	info->fix.mmio_len = INTEL_REG_SIZE;
+	info->fix.accel = FB_ACCEL_I830;
+	update_dinfo(dinfo, &info->var);
+
+	return 0;
+}
+
+/* Update dinfo to match the active video mode. */
+static void update_dinfo(struct intelfb_info *dinfo,
+			 struct fb_var_screeninfo *var)
+{
+	DBG_MSG("update_dinfo\n");
+
+	dinfo->bpp = var->bits_per_pixel;
+	dinfo->depth = intelfb_var_to_depth(var);
+	dinfo->xres = var->xres;
+	dinfo->yres = var->xres;
+	dinfo->pixclock = var->pixclock;
+
+	dinfo->info->fix.visual = dinfo->visual;
+	dinfo->info->fix.line_length = dinfo->pitch;
+
+	switch (dinfo->bpp) {
+	case 8:
+		dinfo->visual = FB_VISUAL_PSEUDOCOLOR;
+		dinfo->pitch = var->xres_virtual;
+		break;
+	case 16:
+		dinfo->visual = FB_VISUAL_TRUECOLOR;
+		dinfo->pitch = var->xres_virtual * 2;
+		break;
+	case 32:
+		dinfo->visual = FB_VISUAL_TRUECOLOR;
+		dinfo->pitch = var->xres_virtual * 4;
+		break;
+	}
+
+	/* Make sure the line length is a aligned correctly. */
+	if (IS_I9XX(dinfo))
+		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
+	else
+		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
+
+	if (FIXED_MODE(dinfo))
+		dinfo->pitch = dinfo->initial_pitch;
+
+	dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual;
+	dinfo->info->fix.line_length = dinfo->pitch;
+	dinfo->info->fix.visual = dinfo->visual;
+}
+
+/* fbops functions */
+
+/***************************************************************
+ *                       fbdev interface                       *
+ ***************************************************************/
+
+static int intelfb_open(struct fb_info *info, int user)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+
+	if (user)
+		dinfo->open++;
+
+	return 0;
+}
+
+static int intelfb_release(struct fb_info *info, int user)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+
+	if (user) {
+		dinfo->open--;
+		msleep(1);
+		if (!dinfo->open)
+			intelfbhw_disable_irq(dinfo);
+	}
+
+	return 0;
+}
+
+static int intelfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	int change_var = 0;
+	struct fb_var_screeninfo v;
+	struct intelfb_info *dinfo;
+	static int first = 1;
+	int i;
+	/* Good pitches to allow tiling.  Don't care about pitches < 1024. */
+	static const int pitches[] = {
+		128 * 8,
+		128 * 16,
+		128 * 32,
+		128 * 64,
+		0
+	};
+
+	DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
+
+	dinfo = GET_DINFO(info);
+
+	/* update the pitch */
+	if (intelfbhw_validate_mode(dinfo, var) != 0)
+		return -EINVAL;
+
+	v = *var;
+
+	for (i = 0; pitches[i] != 0; i++) {
+		if (pitches[i] >= v.xres_virtual) {
+			v.xres_virtual = pitches[i];
+			break;
+		}
+	}
+
+	/* Check for a supported bpp. */
+	if (v.bits_per_pixel <= 8)
+		v.bits_per_pixel = 8;
+	else if (v.bits_per_pixel <= 16) {
+		if (v.bits_per_pixel == 16)
+			v.green.length = 6;
+		v.bits_per_pixel = 16;
+	} else if (v.bits_per_pixel <= 32)
+		v.bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	change_var = ((info->var.xres != var->xres) ||
+		      (info->var.yres != var->yres) ||
+		      (info->var.xres_virtual != var->xres_virtual) ||
+		      (info->var.yres_virtual != var->yres_virtual) ||
+		      (info->var.bits_per_pixel != var->bits_per_pixel) ||
+		      memcmp(&info->var.red, &var->red, sizeof(var->red)) ||
+		      memcmp(&info->var.green, &var->green,
+			     sizeof(var->green)) ||
+		      memcmp(&info->var.blue, &var->blue, sizeof(var->blue)));
+
+	if (FIXED_MODE(dinfo) &&
+	    (change_var ||
+	     var->yres_virtual > dinfo->initial_var.yres_virtual ||
+	     var->yres_virtual < dinfo->initial_var.yres ||
+	     var->xoffset || var->nonstd)) {
+		if (first) {
+			ERR_MSG("Changing the video mode is not supported.\n");
+			first = 0;
+		}
+		return -EINVAL;
+	}
+
+	switch (intelfb_var_to_depth(&v)) {
+	case 8:
+		v.red.offset = v.green.offset = v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 8;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 15:
+		v.red.offset = 10;
+		v.green.offset = 5;
+		v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 5;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 16:
+		v.red.offset = 11;
+		v.green.offset = 5;
+		v.blue.offset = 0;
+		v.red.length = 5;
+		v.green.length = 6;
+		v.blue.length = 5;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 24:
+		v.red.offset = 16;
+		v.green.offset = 8;
+		v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 8;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 32:
+		v.red.offset = 16;
+		v.green.offset = 8;
+		v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 8;
+		v.transp.offset = 24;
+		v.transp.length = 8;
+		break;
+	}
+
+	if (v.xoffset < 0)
+		v.xoffset = 0;
+	if (v.yoffset < 0)
+		v.yoffset = 0;
+
+	if (v.xoffset > v.xres_virtual - v.xres)
+		v.xoffset = v.xres_virtual - v.xres;
+	if (v.yoffset > v.yres_virtual - v.yres)
+		v.yoffset = v.yres_virtual - v.yres;
+
+	v.red.msb_right = v.green.msb_right = v.blue.msb_right =
+			  v.transp.msb_right = 0;
+
+        *var = v;
+
+	return 0;
+}
+
+static int intelfb_set_par(struct fb_info *info)
+{
+	struct intelfb_hwstate *hw;
+        struct intelfb_info *dinfo = GET_DINFO(info);
+
+	if (FIXED_MODE(dinfo)) {
+		ERR_MSG("Changing the video mode is not supported.\n");
+		return -EINVAL;
+	}
+
+	hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
+	if (!hw)
+		return -ENOMEM;
+
+	DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
+		info->var.yres, info->var.bits_per_pixel);
+
+	/*
+	 * Disable VCO prior to timing register change.
+	 */
+	OUTREG(DPLL_A, INREG(DPLL_A) & ~DPLL_VCO_ENABLE);
+
+	intelfb_blank(FB_BLANK_POWERDOWN, info);
+
+	if (ACCEL(dinfo, info))
+		intelfbhw_2d_stop(dinfo);
+
+	memcpy(hw, &dinfo->save_state, sizeof(*hw));
+	if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
+		goto invalid_mode;
+	if (intelfbhw_program_mode(dinfo, hw, 0))
+		goto invalid_mode;
+
+#if REGDUMP > 0
+	intelfbhw_read_hw_state(dinfo, hw, 0);
+	intelfbhw_print_hw_state(dinfo, hw);
+#endif
+
+	update_dinfo(dinfo, &info->var);
+
+	if (ACCEL(dinfo, info))
+		intelfbhw_2d_start(dinfo);
+
+	intelfb_pan_display(&info->var, info);
+
+	intelfb_blank(FB_BLANK_UNBLANK, info);
+
+	if (ACCEL(dinfo, info)) {
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_IMAGEBLIT;
+	} else
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	kfree(hw);
+	return 0;
+invalid_mode:
+	kfree(hw);
+	return -EINVAL;
+}
+
+static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			     unsigned blue, unsigned transp,
+			     struct fb_info *info)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);
+#endif
+
+	if (regno > 255)
+		return 1;
+
+	if (dinfo->depth == 8) {
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+
+		intelfbhw_setcolreg(dinfo, regno, red, green, blue,
+				    transp);
+	}
+
+	if (regno < 16) {
+		switch (dinfo->depth) {
+		case 15:
+			dinfo->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
+				((green & 0xf800) >>  6) |
+				((blue & 0xf800) >> 11);
+			break;
+		case 16:
+			dinfo->pseudo_palette[regno] = (red & 0xf800) |
+				((green & 0xfc00) >>  5) |
+				((blue  & 0xf800) >> 11);
+			break;
+		case 24:
+			dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
+				(green & 0xff00) |
+				((blue  & 0xff00) >> 8);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int intelfb_blank(int blank, struct fb_info *info)
+{
+	intelfbhw_do_blank(blank, info);
+	return 0;
+}
+
+static int intelfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	intelfbhw_pan_display(var, info);
+	return 0;
+}
+
+/* When/if we have our own ioctls. */
+static int intelfb_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg)
+{
+	int retval = 0;
+	struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 pipe = 0;
+
+	switch (cmd) {
+		case FBIO_WAITFORVSYNC:
+			if (get_user(pipe, (__u32 __user *)arg))
+				return -EFAULT;
+
+			retval = intelfbhw_wait_for_vsync(dinfo, pipe);
+			break;
+		default:
+			break;
+	}
+
+	return retval;
+}
+
+static void intelfb_fillrect (struct fb_info *info,
+			      const struct fb_fillrect *rect)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 rop, color;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_fillrect\n");
+#endif
+
+	if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if (rect->rop == ROP_COPY)
+		rop = PAT_ROP_GXCOPY;
+	else /* ROP_XOR */
+		rop = PAT_ROP_GXXOR;
+
+	if (dinfo->depth != 8)
+		color = dinfo->pseudo_palette[rect->color];
+	else
+		color = rect->color;
+
+	intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy,
+			      rect->width, rect->height, color,
+			      dinfo->pitch, info->var.bits_per_pixel,
+			      rop);
+}
+
+static void intelfb_copyarea(struct fb_info *info,
+			     const struct fb_copyarea *region)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_copyarea\n");
+#endif
+
+	if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
+	intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
+			    region->dy, region->width, region->height,
+			    dinfo->pitch, info->var.bits_per_pixel);
+}
+
+static void intelfb_imageblit(struct fb_info *info,
+			      const struct fb_image *image)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 fgcolor, bgcolor;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_imageblit\n");
+#endif
+
+	if (!ACCEL(dinfo, info) || dinfo->depth == 4
+	    || image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	if (dinfo->depth != 8) {
+		fgcolor = dinfo->pseudo_palette[image->fg_color];
+		bgcolor = dinfo->pseudo_palette[image->bg_color];
+	} else {
+		fgcolor = image->fg_color;
+		bgcolor = image->bg_color;
+	}
+
+	if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width,
+				    image->height, image->data,
+				    image->dx, image->dy,
+				    dinfo->pitch, info->var.bits_per_pixel)) {
+		cfb_imageblit(info, image);
+		return;
+	}
+}
+
+static int intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 physical;
+#if VERBOSE > 0
+	DBG_MSG("intelfb_cursor\n");
+#endif
+
+	if (!dinfo->hwcursor)
+		return -ENODEV;
+
+	intelfbhw_cursor_hide(dinfo);
+
+	/* If XFree killed the cursor - restore it */
+	physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
+		   (dinfo->cursor.offset << 12);
+
+	if (INREG(CURSOR_A_BASEADDR) != physical) {
+		u32 fg, bg;
+
+		DBG_MSG("the cursor was killed - restore it !!\n");
+		DBG_MSG("size %d, %d   pos %d, %d\n",
+			cursor->image.width, cursor->image.height,
+			cursor->image.dx, cursor->image.dy);
+
+		intelfbhw_cursor_init(dinfo);
+		intelfbhw_cursor_reset(dinfo);
+		intelfbhw_cursor_setpos(dinfo, cursor->image.dx,
+					cursor->image.dy);
+
+		if (dinfo->depth != 8) {
+			fg =dinfo->pseudo_palette[cursor->image.fg_color];
+			bg =dinfo->pseudo_palette[cursor->image.bg_color];
+		} else {
+			fg = cursor->image.fg_color;
+			bg = cursor->image.bg_color;
+		}
+		intelfbhw_cursor_setcolor(dinfo, bg, fg);
+		intelfbhw_cursor_load(dinfo, cursor->image.width,
+				      cursor->image.height,
+				      dinfo->cursor_src);
+
+		if (cursor->enable)
+			intelfbhw_cursor_show(dinfo);
+		return 0;
+	}
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		u32 dx, dy;
+
+		dx = cursor->image.dx - info->var.xoffset;
+		dy = cursor->image.dy - info->var.yoffset;
+
+		intelfbhw_cursor_setpos(dinfo, dx, dy);
+	}
+
+	if (cursor->set & FB_CUR_SETSIZE) {
+		if (cursor->image.width > 64 || cursor->image.height > 64)
+			return -ENXIO;
+
+		intelfbhw_cursor_reset(dinfo);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		u32 fg, bg;
+
+		if (dinfo->depth != 8) {
+			fg = dinfo->pseudo_palette[cursor->image.fg_color];
+			bg = dinfo->pseudo_palette[cursor->image.bg_color];
+		} else {
+			fg = cursor->image.fg_color;
+			bg = cursor->image.bg_color;
+		}
+
+		intelfbhw_cursor_setcolor(dinfo, bg, fg);
+	}
+
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+		u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8);
+		u32 size = s_pitch * cursor->image.height;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) cursor->mask;
+		u8 src[64];
+		u32 i;
+
+		if (cursor->image.depth != 1)
+			return -ENXIO;
+
+		switch (cursor->rop) {
+		case ROP_XOR:
+			for (i = 0; i < size; i++)
+				src[i] = dat[i] ^ msk[i];
+			break;
+		case ROP_COPY:
+		default:
+			for (i = 0; i < size; i++)
+				src[i] = dat[i] & msk[i];
+			break;
+		}
+
+		/* save the bitmap to restore it when XFree will
+		   make the cursor dirty */
+		memcpy(dinfo->cursor_src, src, size);
+
+		intelfbhw_cursor_load(dinfo, cursor->image.width,
+				      cursor->image.height, src);
+	}
+
+	if (cursor->enable)
+		intelfbhw_cursor_show(dinfo);
+
+	return 0;
+}
+
+static int intelfb_sync(struct fb_info *info)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_sync\n");
+#endif
+
+	if (dinfo->ring_lockup)
+		return 0;
+
+	intelfbhw_do_sync(dinfo);
+	return 0;
+}
+
diff --git a/drivers/video/fbdev/intelfb/intelfbhw.c b/drivers/video/fbdev/intelfb/intelfbhw.c
new file mode 100644
index 000000000000..fbad61da359f
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfbhw.c
@@ -0,0 +1,2121 @@
+/*
+ * intelfb
+ *
+ * Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
+ *
+ * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+ *                   2004 Sylvain Meyer
+ *
+ * This driver consists of two parts.  The first part (intelfbdrv.c) provides
+ * the basic fbdev interfaces, is derived in part from the radeonfb and
+ * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c)
+ * provides the code to program the hardware.  Most of it is derived from
+ * the i810/i830 XFree86 driver.  The HW-specific code is covered here
+ * under a dual license (GPL and MIT/XFree86 license).
+ *
+ * Author: David Dawes
+ *
+ */
+
+/* $DHD: intelfb/intelfbhw.c,v 1.9 2003/06/27 15:06:25 dawes Exp $ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+
+#include "intelfb.h"
+#include "intelfbhw.h"
+
+struct pll_min_max {
+	int min_m, max_m, min_m1, max_m1;
+	int min_m2, max_m2, min_n, max_n;
+	int min_p, max_p, min_p1, max_p1;
+	int min_vco, max_vco, p_transition_clk, ref_clk;
+	int p_inc_lo, p_inc_hi;
+};
+
+#define PLLS_I8xx 0
+#define PLLS_I9xx 1
+#define PLLS_MAX 2
+
+static struct pll_min_max plls[PLLS_MAX] = {
+	{ 108, 140, 18, 26,
+	  6, 16, 3, 16,
+	  4, 128, 0, 31,
+	  930000, 1400000, 165000, 48000,
+	  4, 2 },		/* I8xx */
+
+	{ 75, 120, 10, 20,
+	  5, 9, 4, 7,
+	  5, 80, 1, 8,
+	  1400000, 2800000, 200000, 96000,
+	  10, 5 }		/* I9xx */
+};
+
+int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
+{
+	u32 tmp;
+	if (!pdev || !dinfo)
+		return 1;
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_830M:
+		dinfo->name = "Intel(R) 830M";
+		dinfo->chipset = INTEL_830M;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I8xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_845G:
+		dinfo->name = "Intel(R) 845G";
+		dinfo->chipset = INTEL_845G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I8xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_854:
+		dinfo->mobile = 1;
+		dinfo->name = "Intel(R) 854";
+		dinfo->chipset = INTEL_854;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_85XGM:
+		tmp = 0;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I8xx;
+		pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
+		switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
+			INTEL_85X_VARIANT_MASK) {
+		case INTEL_VAR_855GME:
+			dinfo->name = "Intel(R) 855GME";
+			dinfo->chipset = INTEL_855GME;
+			return 0;
+		case INTEL_VAR_855GM:
+			dinfo->name = "Intel(R) 855GM";
+			dinfo->chipset = INTEL_855GM;
+			return 0;
+		case INTEL_VAR_852GME:
+			dinfo->name = "Intel(R) 852GME";
+			dinfo->chipset = INTEL_852GME;
+			return 0;
+		case INTEL_VAR_852GM:
+			dinfo->name = "Intel(R) 852GM";
+			dinfo->chipset = INTEL_852GM;
+			return 0;
+		default:
+			dinfo->name = "Intel(R) 852GM/855GM";
+			dinfo->chipset = INTEL_85XGM;
+			return 0;
+		}
+		break;
+	case PCI_DEVICE_ID_INTEL_865G:
+		dinfo->name = "Intel(R) 865G";
+		dinfo->chipset = INTEL_865G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I8xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_915G:
+		dinfo->name = "Intel(R) 915G";
+		dinfo->chipset = INTEL_915G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_915GM:
+		dinfo->name = "Intel(R) 915GM";
+		dinfo->chipset = INTEL_915GM;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_945G:
+		dinfo->name = "Intel(R) 945G";
+		dinfo->chipset = INTEL_945G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_945GM:
+		dinfo->name = "Intel(R) 945GM";
+		dinfo->chipset = INTEL_945GM;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_945GME:
+		dinfo->name = "Intel(R) 945GME";
+		dinfo->chipset = INTEL_945GME;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_965G:
+		dinfo->name = "Intel(R) 965G";
+		dinfo->chipset = INTEL_965G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_965GM:
+		dinfo->name = "Intel(R) 965GM";
+		dinfo->chipset = INTEL_965GM;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	default:
+		return 1;
+	}
+}
+
+int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
+			 int *stolen_size)
+{
+	struct pci_dev *bridge_dev;
+	u16 tmp;
+	int stolen_overhead;
+
+	if (!pdev || !aperture_size || !stolen_size)
+		return 1;
+
+	/* Find the bridge device.  It is always 0:0.0 */
+	if (!(bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)))) {
+		ERR_MSG("cannot find bridge device\n");
+		return 1;
+	}
+
+	/* Get the fb aperture size and "stolen" memory amount. */
+	tmp = 0;
+	pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
+	pci_dev_put(bridge_dev);
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_915G:
+	case PCI_DEVICE_ID_INTEL_915GM:
+	case PCI_DEVICE_ID_INTEL_945G:
+	case PCI_DEVICE_ID_INTEL_945GM:
+	case PCI_DEVICE_ID_INTEL_945GME:
+	case PCI_DEVICE_ID_INTEL_965G:
+	case PCI_DEVICE_ID_INTEL_965GM:
+		/* 915, 945 and 965 chipsets support a 256MB aperture.
+		   Aperture size is determined by inspected the
+		   base address of the aperture. */
+		if (pci_resource_start(pdev, 2) & 0x08000000)
+			*aperture_size = MB(128);
+		else
+			*aperture_size = MB(256);
+		break;
+	default:
+		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
+			*aperture_size = MB(64);
+		else
+			*aperture_size = MB(128);
+		break;
+	}
+
+	/* Stolen memory size is reduced by the GTT and the popup.
+	   GTT is 1K per MB of aperture size, and popup is 4K. */
+	stolen_overhead = (*aperture_size / MB(1)) + 4;
+	switch(pdev->device) {
+	case PCI_DEVICE_ID_INTEL_830M:
+	case PCI_DEVICE_ID_INTEL_845G:
+		switch (tmp & INTEL_830_GMCH_GMS_MASK) {
+		case INTEL_830_GMCH_GMS_STOLEN_512:
+			*stolen_size = KB(512) - KB(stolen_overhead);
+			return 0;
+		case INTEL_830_GMCH_GMS_STOLEN_1024:
+			*stolen_size = MB(1) - KB(stolen_overhead);
+			return 0;
+		case INTEL_830_GMCH_GMS_STOLEN_8192:
+			*stolen_size = MB(8) - KB(stolen_overhead);
+			return 0;
+		case INTEL_830_GMCH_GMS_LOCAL:
+			ERR_MSG("only local memory found\n");
+			return 1;
+		case INTEL_830_GMCH_GMS_DISABLED:
+			ERR_MSG("video memory is disabled\n");
+			return 1;
+		default:
+			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
+				tmp & INTEL_830_GMCH_GMS_MASK);
+			return 1;
+		}
+		break;
+	default:
+		switch (tmp & INTEL_855_GMCH_GMS_MASK) {
+		case INTEL_855_GMCH_GMS_STOLEN_1M:
+			*stolen_size = MB(1) - KB(stolen_overhead);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_4M:
+			*stolen_size = MB(4) - KB(stolen_overhead);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_8M:
+			*stolen_size = MB(8) - KB(stolen_overhead);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_16M:
+			*stolen_size = MB(16) - KB(stolen_overhead);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_32M:
+			*stolen_size = MB(32) - KB(stolen_overhead);
+			return 0;
+		case INTEL_915G_GMCH_GMS_STOLEN_48M:
+			*stolen_size = MB(48) - KB(stolen_overhead);
+			return 0;
+		case INTEL_915G_GMCH_GMS_STOLEN_64M:
+			*stolen_size = MB(64) - KB(stolen_overhead);
+			return 0;
+		case INTEL_855_GMCH_GMS_DISABLED:
+			ERR_MSG("video memory is disabled\n");
+			return 0;
+		default:
+			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
+				tmp & INTEL_855_GMCH_GMS_MASK);
+			return 1;
+		}
+	}
+}
+
+int intelfbhw_check_non_crt(struct intelfb_info *dinfo)
+{
+	int dvo = 0;
+
+	if (INREG(LVDS) & PORT_ENABLE)
+		dvo |= LVDS_PORT;
+	if (INREG(DVOA) & PORT_ENABLE)
+		dvo |= DVOA_PORT;
+	if (INREG(DVOB) & PORT_ENABLE)
+		dvo |= DVOB_PORT;
+	if (INREG(DVOC) & PORT_ENABLE)
+		dvo |= DVOC_PORT;
+
+	return dvo;
+}
+
+const char * intelfbhw_dvo_to_string(int dvo)
+{
+	if (dvo & DVOA_PORT)
+		return "DVO port A";
+	else if (dvo & DVOB_PORT)
+		return "DVO port B";
+	else if (dvo & DVOC_PORT)
+		return "DVO port C";
+	else if (dvo & LVDS_PORT)
+		return "LVDS port";
+	else
+		return NULL;
+}
+
+
+int intelfbhw_validate_mode(struct intelfb_info *dinfo,
+			    struct fb_var_screeninfo *var)
+{
+	int bytes_per_pixel;
+	int tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_validate_mode\n");
+#endif
+
+	bytes_per_pixel = var->bits_per_pixel / 8;
+	if (bytes_per_pixel == 3)
+		bytes_per_pixel = 4;
+
+	/* Check if enough video memory. */
+	tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;
+	if (tmp > dinfo->fb.size) {
+		WRN_MSG("Not enough video ram for mode "
+			"(%d KByte vs %d KByte).\n",
+			BtoKB(tmp), BtoKB(dinfo->fb.size));
+		return 1;
+	}
+
+	/* Check if x/y limits are OK. */
+	if (var->xres - 1 > HACTIVE_MASK) {
+		WRN_MSG("X resolution too large (%d vs %d).\n",
+			var->xres, HACTIVE_MASK + 1);
+		return 1;
+	}
+	if (var->yres - 1 > VACTIVE_MASK) {
+		WRN_MSG("Y resolution too large (%d vs %d).\n",
+			var->yres, VACTIVE_MASK + 1);
+		return 1;
+	}
+	if (var->xres < 4) {
+		WRN_MSG("X resolution too small (%d vs 4).\n", var->xres);
+		return 1;
+	}
+	if (var->yres < 4) {
+		WRN_MSG("Y resolution too small (%d vs 4).\n", var->yres);
+		return 1;
+	}
+
+	/* Check for doublescan modes. */
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		WRN_MSG("Mode is double-scan.\n");
+		return 1;
+	}
+
+	if ((var->vmode & FB_VMODE_INTERLACED) && (var->yres & 1)) {
+		WRN_MSG("Odd number of lines in interlaced mode\n");
+		return 1;
+	}
+
+	/* Check if clock is OK. */
+	tmp = 1000000000 / var->pixclock;
+	if (tmp < MIN_CLOCK) {
+		WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",
+			(tmp + 500) / 1000, MIN_CLOCK / 1000);
+		return 1;
+	}
+	if (tmp > MAX_CLOCK) {
+		WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",
+			(tmp + 500) / 1000, MAX_CLOCK / 1000);
+		return 1;
+	}
+
+	return 0;
+}
+
+int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 offset, xoffset, yoffset;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_pan_display\n");
+#endif
+
+	xoffset = ROUND_DOWN_TO(var->xoffset, 8);
+	yoffset = var->yoffset;
+
+	if ((xoffset + info->var.xres > info->var.xres_virtual) ||
+	    (yoffset + info->var.yres > info->var.yres_virtual))
+		return -EINVAL;
+
+	offset = (yoffset * dinfo->pitch) +
+		 (xoffset * info->var.bits_per_pixel) / 8;
+
+	offset += dinfo->fb.offset << 12;
+
+	dinfo->vsync.pan_offset = offset;
+	if ((var->activate & FB_ACTIVATE_VBL) &&
+	    !intelfbhw_enable_irq(dinfo))
+		dinfo->vsync.pan_display = 1;
+	else {
+		dinfo->vsync.pan_display = 0;
+		OUTREG(DSPABASE, offset);
+	}
+
+	return 0;
+}
+
+/* Blank the screen. */
+void intelfbhw_do_blank(int blank, struct fb_info *info)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);
+#endif
+
+	/* Turn plane A on or off */
+	tmp = INREG(DSPACNTR);
+	if (blank)
+		tmp &= ~DISPPLANE_PLANE_ENABLE;
+	else
+		tmp |= DISPPLANE_PLANE_ENABLE;
+	OUTREG(DSPACNTR, tmp);
+	/* Flush */
+	tmp = INREG(DSPABASE);
+	OUTREG(DSPABASE, tmp);
+
+	/* Turn off/on the HW cursor */
+#if VERBOSE > 0
+	DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
+#endif
+	if (dinfo->cursor_on) {
+		if (blank)
+			intelfbhw_cursor_hide(dinfo);
+		else
+			intelfbhw_cursor_show(dinfo);
+		dinfo->cursor_on = 1;
+	}
+	dinfo->cursor_blanked = blank;
+
+	/* Set DPMS level */
+	tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		tmp |= ADPA_DPMS_D0;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		tmp |= ADPA_DPMS_D1;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		tmp |= ADPA_DPMS_D2;
+		break;
+	case FB_BLANK_POWERDOWN:
+		tmp |= ADPA_DPMS_D3;
+		break;
+	}
+	OUTREG(ADPA, tmp);
+
+	return;
+}
+
+
+/* Check which pipe is connected to an active display plane. */
+int intelfbhw_active_pipe(const struct intelfb_hwstate *hw)
+{
+	int pipe = -1;
+
+	/* keep old default behaviour - prefer PIPE_A */
+	if (hw->disp_b_ctrl & DISPPLANE_PLANE_ENABLE) {
+		pipe = (hw->disp_b_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
+		pipe &= PIPE_MASK;
+		if (unlikely(pipe == PIPE_A))
+			return PIPE_A;
+	}
+	if (hw->disp_a_ctrl & DISPPLANE_PLANE_ENABLE) {
+		pipe = (hw->disp_a_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
+		pipe &= PIPE_MASK;
+		if (likely(pipe == PIPE_A))
+			return PIPE_A;
+	}
+	/* Impossible that no pipe is selected - return PIPE_A */
+	WARN_ON(pipe == -1);
+	if (unlikely(pipe == -1))
+		pipe = PIPE_A;
+
+	return pipe;
+}
+
+void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp)
+{
+	u32 palette_reg = (dinfo->pipe == PIPE_A) ?
+			  PALETTE_A : PALETTE_B;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
+		regno, red, green, blue);
+#endif
+
+	OUTREG(palette_reg + (regno << 2),
+	       (red << PALETTE_8_RED_SHIFT) |
+	       (green << PALETTE_8_GREEN_SHIFT) |
+	       (blue << PALETTE_8_BLUE_SHIFT));
+}
+
+
+int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
+			    struct intelfb_hwstate *hw, int flag)
+{
+	int i;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_read_hw_state\n");
+#endif
+
+	if (!hw || !dinfo)
+		return -1;
+
+	/* Read in as much of the HW state as possible. */
+	hw->vga0_divisor = INREG(VGA0_DIVISOR);
+	hw->vga1_divisor = INREG(VGA1_DIVISOR);
+	hw->vga_pd = INREG(VGAPD);
+	hw->dpll_a = INREG(DPLL_A);
+	hw->dpll_b = INREG(DPLL_B);
+	hw->fpa0 = INREG(FPA0);
+	hw->fpa1 = INREG(FPA1);
+	hw->fpb0 = INREG(FPB0);
+	hw->fpb1 = INREG(FPB1);
+
+	if (flag == 1)
+		return flag;
+
+#if 0
+	/* This seems to be a problem with the 852GM/855GM */
+	for (i = 0; i < PALETTE_8_ENTRIES; i++) {
+		hw->palette_a[i] = INREG(PALETTE_A + (i << 2));
+		hw->palette_b[i] = INREG(PALETTE_B + (i << 2));
+	}
+#endif
+
+	if (flag == 2)
+		return flag;
+
+	hw->htotal_a = INREG(HTOTAL_A);
+	hw->hblank_a = INREG(HBLANK_A);
+	hw->hsync_a = INREG(HSYNC_A);
+	hw->vtotal_a = INREG(VTOTAL_A);
+	hw->vblank_a = INREG(VBLANK_A);
+	hw->vsync_a = INREG(VSYNC_A);
+	hw->src_size_a = INREG(SRC_SIZE_A);
+	hw->bclrpat_a = INREG(BCLRPAT_A);
+	hw->htotal_b = INREG(HTOTAL_B);
+	hw->hblank_b = INREG(HBLANK_B);
+	hw->hsync_b = INREG(HSYNC_B);
+	hw->vtotal_b = INREG(VTOTAL_B);
+	hw->vblank_b = INREG(VBLANK_B);
+	hw->vsync_b = INREG(VSYNC_B);
+	hw->src_size_b = INREG(SRC_SIZE_B);
+	hw->bclrpat_b = INREG(BCLRPAT_B);
+
+	if (flag == 3)
+		return flag;
+
+	hw->adpa = INREG(ADPA);
+	hw->dvoa = INREG(DVOA);
+	hw->dvob = INREG(DVOB);
+	hw->dvoc = INREG(DVOC);
+	hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
+	hw->dvob_srcdim = INREG(DVOB_SRCDIM);
+	hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
+	hw->lvds = INREG(LVDS);
+
+	if (flag == 4)
+		return flag;
+
+	hw->pipe_a_conf = INREG(PIPEACONF);
+	hw->pipe_b_conf = INREG(PIPEBCONF);
+	hw->disp_arb = INREG(DISPARB);
+
+	if (flag == 5)
+		return flag;
+
+	hw->cursor_a_control = INREG(CURSOR_A_CONTROL);
+	hw->cursor_b_control = INREG(CURSOR_B_CONTROL);
+	hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);
+	hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);
+
+	if (flag == 6)
+		return flag;
+
+	for (i = 0; i < 4; i++) {
+		hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));
+		hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));
+	}
+
+	if (flag == 7)
+		return flag;
+
+	hw->cursor_size = INREG(CURSOR_SIZE);
+
+	if (flag == 8)
+		return flag;
+
+	hw->disp_a_ctrl = INREG(DSPACNTR);
+	hw->disp_b_ctrl = INREG(DSPBCNTR);
+	hw->disp_a_base = INREG(DSPABASE);
+	hw->disp_b_base = INREG(DSPBBASE);
+	hw->disp_a_stride = INREG(DSPASTRIDE);
+	hw->disp_b_stride = INREG(DSPBSTRIDE);
+
+	if (flag == 9)
+		return flag;
+
+	hw->vgacntrl = INREG(VGACNTRL);
+
+	if (flag == 10)
+		return flag;
+
+	hw->add_id = INREG(ADD_ID);
+
+	if (flag == 11)
+		return flag;
+
+	for (i = 0; i < 7; i++) {
+		hw->swf0x[i] = INREG(SWF00 + (i << 2));
+		hw->swf1x[i] = INREG(SWF10 + (i << 2));
+		if (i < 3)
+			hw->swf3x[i] = INREG(SWF30 + (i << 2));
+	}
+
+	for (i = 0; i < 8; i++)
+		hw->fence[i] = INREG(FENCE + (i << 2));
+
+	hw->instpm = INREG(INSTPM);
+	hw->mem_mode = INREG(MEM_MODE);
+	hw->fw_blc_0 = INREG(FW_BLC_0);
+	hw->fw_blc_1 = INREG(FW_BLC_1);
+
+	hw->hwstam = INREG16(HWSTAM);
+	hw->ier = INREG16(IER);
+	hw->iir = INREG16(IIR);
+	hw->imr = INREG16(IMR);
+
+	return 0;
+}
+
+
+static int calc_vclock3(int index, int m, int n, int p)
+{
+	if (p == 0 || n == 0)
+		return 0;
+	return plls[index].ref_clk * m / n / p;
+}
+
+static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2,
+		       int lvds)
+{
+	struct pll_min_max *pll = &plls[index];
+	u32 m, vco, p;
+
+	m = (5 * (m1 + 2)) + (m2 + 2);
+	n += 2;
+	vco = pll->ref_clk * m / n;
+
+	if (index == PLLS_I8xx)
+		p = ((p1 + 2) * (1 << (p2 + 1)));
+	else
+		p = ((p1) * (p2 ? 5 : 10));
+	return vco / p;
+}
+
+#if REGDUMP
+static void intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll,
+			       int *o_p1, int *o_p2)
+{
+	int p1, p2;
+
+	if (IS_I9XX(dinfo)) {
+		if (dpll & DPLL_P1_FORCE_DIV2)
+			p1 = 1;
+		else
+			p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
+
+		p1 = ffs(p1);
+
+		p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
+	} else {
+		if (dpll & DPLL_P1_FORCE_DIV2)
+			p1 = 0;
+		else
+			p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
+		p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+	}
+
+	*o_p1 = p1;
+	*o_p2 = p2;
+}
+#endif
+
+
+void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
+			      struct intelfb_hwstate *hw)
+{
+#if REGDUMP
+	int i, m1, m2, n, p1, p2;
+	int index = dinfo->pll_index;
+	DBG_MSG("intelfbhw_print_hw_state\n");
+
+	if (!hw)
+		return;
+	/* Read in as much of the HW state as possible. */
+	printk("hw state dump start\n");
+	printk("	VGA0_DIVISOR:		0x%08x\n", hw->vga0_divisor);
+	printk("	VGA1_DIVISOR:		0x%08x\n", hw->vga1_divisor);
+	printk("	VGAPD:			0x%08x\n", hw->vga_pd);
+	n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
+
+	printk("	VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+	       m1, m2, n, p1, p2);
+	printk("	VGA0: clock is %d\n",
+	       calc_vclock(index, m1, m2, n, p1, p2, 0));
+
+	n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
+	printk("	VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+	       m1, m2, n, p1, p2);
+	printk("	VGA1: clock is %d\n",
+	       calc_vclock(index, m1, m2, n, p1, p2, 0));
+
+	printk("	DPLL_A:			0x%08x\n", hw->dpll_a);
+	printk("	DPLL_B:			0x%08x\n", hw->dpll_b);
+	printk("	FPA0:			0x%08x\n", hw->fpa0);
+	printk("	FPA1:			0x%08x\n", hw->fpa1);
+	printk("	FPB0:			0x%08x\n", hw->fpb0);
+	printk("	FPB1:			0x%08x\n", hw->fpb1);
+
+	n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
+
+	printk("	PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+	       m1, m2, n, p1, p2);
+	printk("	PLLA0: clock is %d\n",
+	       calc_vclock(index, m1, m2, n, p1, p2, 0));
+
+	n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
+
+	printk("	PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+	       m1, m2, n, p1, p2);
+	printk("	PLLA1: clock is %d\n",
+	       calc_vclock(index, m1, m2, n, p1, p2, 0));
+
+#if 0
+	printk("	PALETTE_A:\n");
+	for (i = 0; i < PALETTE_8_ENTRIES)
+		printk("	%3d:	0x%08x\n", i, hw->palette_a[i]);
+	printk("	PALETTE_B:\n");
+	for (i = 0; i < PALETTE_8_ENTRIES)
+		printk("	%3d:	0x%08x\n", i, hw->palette_b[i]);
+#endif
+
+	printk("	HTOTAL_A:		0x%08x\n", hw->htotal_a);
+	printk("	HBLANK_A:		0x%08x\n", hw->hblank_a);
+	printk("	HSYNC_A:		0x%08x\n", hw->hsync_a);
+	printk("	VTOTAL_A:		0x%08x\n", hw->vtotal_a);
+	printk("	VBLANK_A:		0x%08x\n", hw->vblank_a);
+	printk("	VSYNC_A:		0x%08x\n", hw->vsync_a);
+	printk("	SRC_SIZE_A:		0x%08x\n", hw->src_size_a);
+	printk("	BCLRPAT_A:		0x%08x\n", hw->bclrpat_a);
+	printk("	HTOTAL_B:		0x%08x\n", hw->htotal_b);
+	printk("	HBLANK_B:		0x%08x\n", hw->hblank_b);
+	printk("	HSYNC_B:		0x%08x\n", hw->hsync_b);
+	printk("	VTOTAL_B:		0x%08x\n", hw->vtotal_b);
+	printk("	VBLANK_B:		0x%08x\n", hw->vblank_b);
+	printk("	VSYNC_B:		0x%08x\n", hw->vsync_b);
+	printk("	SRC_SIZE_B:		0x%08x\n", hw->src_size_b);
+	printk("	BCLRPAT_B:		0x%08x\n", hw->bclrpat_b);
+
+	printk("	ADPA:			0x%08x\n", hw->adpa);
+	printk("	DVOA:			0x%08x\n", hw->dvoa);
+	printk("	DVOB:			0x%08x\n", hw->dvob);
+	printk("	DVOC:			0x%08x\n", hw->dvoc);
+	printk("	DVOA_SRCDIM:		0x%08x\n", hw->dvoa_srcdim);
+	printk("	DVOB_SRCDIM:		0x%08x\n", hw->dvob_srcdim);
+	printk("	DVOC_SRCDIM:		0x%08x\n", hw->dvoc_srcdim);
+	printk("	LVDS:			0x%08x\n", hw->lvds);
+
+	printk("	PIPEACONF:		0x%08x\n", hw->pipe_a_conf);
+	printk("	PIPEBCONF:		0x%08x\n", hw->pipe_b_conf);
+	printk("	DISPARB:		0x%08x\n", hw->disp_arb);
+
+	printk("	CURSOR_A_CONTROL:	0x%08x\n", hw->cursor_a_control);
+	printk("	CURSOR_B_CONTROL:	0x%08x\n", hw->cursor_b_control);
+	printk("	CURSOR_A_BASEADDR:	0x%08x\n", hw->cursor_a_base);
+	printk("	CURSOR_B_BASEADDR:	0x%08x\n", hw->cursor_b_base);
+
+	printk("	CURSOR_A_PALETTE:	");
+	for (i = 0; i < 4; i++) {
+		printk("0x%08x", hw->cursor_a_palette[i]);
+		if (i < 3)
+			printk(", ");
+	}
+	printk("\n");
+	printk("	CURSOR_B_PALETTE:	");
+	for (i = 0; i < 4; i++) {
+		printk("0x%08x", hw->cursor_b_palette[i]);
+		if (i < 3)
+			printk(", ");
+	}
+	printk("\n");
+
+	printk("	CURSOR_SIZE:		0x%08x\n", hw->cursor_size);
+
+	printk("	DSPACNTR:		0x%08x\n", hw->disp_a_ctrl);
+	printk("	DSPBCNTR:		0x%08x\n", hw->disp_b_ctrl);
+	printk("	DSPABASE:		0x%08x\n", hw->disp_a_base);
+	printk("	DSPBBASE:		0x%08x\n", hw->disp_b_base);
+	printk("	DSPASTRIDE:		0x%08x\n", hw->disp_a_stride);
+	printk("	DSPBSTRIDE:		0x%08x\n", hw->disp_b_stride);
+
+	printk("	VGACNTRL:		0x%08x\n", hw->vgacntrl);
+	printk("	ADD_ID:			0x%08x\n", hw->add_id);
+
+	for (i = 0; i < 7; i++) {
+		printk("	SWF0%d			0x%08x\n", i,
+			hw->swf0x[i]);
+	}
+	for (i = 0; i < 7; i++) {
+		printk("	SWF1%d			0x%08x\n", i,
+			hw->swf1x[i]);
+	}
+	for (i = 0; i < 3; i++) {
+		printk("	SWF3%d			0x%08x\n", i,
+		       hw->swf3x[i]);
+	}
+	for (i = 0; i < 8; i++)
+		printk("	FENCE%d			0x%08x\n", i,
+		       hw->fence[i]);
+
+	printk("	INSTPM			0x%08x\n", hw->instpm);
+	printk("	MEM_MODE		0x%08x\n", hw->mem_mode);
+	printk("	FW_BLC_0		0x%08x\n", hw->fw_blc_0);
+	printk("	FW_BLC_1		0x%08x\n", hw->fw_blc_1);
+
+	printk("	HWSTAM			0x%04x\n", hw->hwstam);
+	printk("	IER			0x%04x\n", hw->ier);
+	printk("	IIR			0x%04x\n", hw->iir);
+	printk("	IMR			0x%04x\n", hw->imr);
+	printk("hw state dump end\n");
+#endif
+}
+
+
+
+/* Split the M parameter into M1 and M2. */
+static int splitm(int index, unsigned int m, unsigned int *retm1,
+		  unsigned int *retm2)
+{
+	int m1, m2;
+	int testm;
+	struct pll_min_max *pll = &plls[index];
+
+	/* no point optimising too much - brute force m */
+	for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {
+		for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {
+			testm = (5 * (m1 + 2)) + (m2 + 2);
+			if (testm == m) {
+				*retm1 = (unsigned int)m1;
+				*retm2 = (unsigned int)m2;
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+/* Split the P parameter into P1 and P2. */
+static int splitp(int index, unsigned int p, unsigned int *retp1,
+		  unsigned int *retp2)
+{
+	int p1, p2;
+	struct pll_min_max *pll = &plls[index];
+
+	if (index == PLLS_I9xx) {
+		p2 = (p % 10) ? 1 : 0;
+
+		p1 = p / (p2 ? 5 : 10);
+
+		*retp1 = (unsigned int)p1;
+		*retp2 = (unsigned int)p2;
+		return 0;
+	}
+
+	if (p % 4 == 0)
+		p2 = 1;
+	else
+		p2 = 0;
+	p1 = (p / (1 << (p2 + 1))) - 2;
+	if (p % 4 == 0 && p1 < pll->min_p1) {
+		p2 = 0;
+		p1 = (p / (1 << (p2 + 1))) - 2;
+	}
+	if (p1 < pll->min_p1 || p1 > pll->max_p1 ||
+	    (p1 + 2) * (1 << (p2 + 1)) != p) {
+		return 1;
+	} else {
+		*retp1 = (unsigned int)p1;
+		*retp2 = (unsigned int)p2;
+		return 0;
+	}
+}
+
+static int calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2,
+			   u32 *retn, u32 *retp1, u32 *retp2, u32 *retclock)
+{
+	u32 m1, m2, n, p1, p2, n1, testm;
+	u32 f_vco, p, p_best = 0, m, f_out = 0;
+	u32 err_max, err_target, err_best = 10000000;
+	u32 n_best = 0, m_best = 0, f_best, f_err;
+	u32 p_min, p_max, p_inc, div_max;
+	struct pll_min_max *pll = &plls[index];
+
+	/* Accept 0.5% difference, but aim for 0.1% */
+	err_max = 5 * clock / 1000;
+	err_target = clock / 1000;
+
+	DBG_MSG("Clock is %d\n", clock);
+
+	div_max = pll->max_vco / clock;
+
+	p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;
+	p_min = p_inc;
+	p_max = ROUND_DOWN_TO(div_max, p_inc);
+	if (p_min < pll->min_p)
+		p_min = pll->min_p;
+	if (p_max > pll->max_p)
+		p_max = pll->max_p;
+
+	DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
+
+	p = p_min;
+	do {
+		if (splitp(index, p, &p1, &p2)) {
+			WRN_MSG("cannot split p = %d\n", p);
+			p += p_inc;
+			continue;
+		}
+		n = pll->min_n;
+		f_vco = clock * p;
+
+		do {
+			m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;
+			if (m < pll->min_m)
+				m = pll->min_m + 1;
+			if (m > pll->max_m)
+				m = pll->max_m - 1;
+			for (testm = m - 1; testm <= m; testm++) {
+				f_out = calc_vclock3(index, testm, n, p);
+				if (splitm(index, testm, &m1, &m2)) {
+					WRN_MSG("cannot split m = %d\n",
+						testm);
+					continue;
+				}
+				if (clock > f_out)
+					f_err = clock - f_out;
+				else/* slightly bias the error for bigger clocks */
+					f_err = f_out - clock + 1;
+
+				if (f_err < err_best) {
+					m_best = testm;
+					n_best = n;
+					p_best = p;
+					f_best = f_out;
+					err_best = f_err;
+				}
+			}
+			n++;
+		} while ((n <= pll->max_n) && (f_out >= clock));
+		p += p_inc;
+	} while ((p <= p_max));
+
+	if (!m_best) {
+		WRN_MSG("cannot find parameters for clock %d\n", clock);
+		return 1;
+	}
+	m = m_best;
+	n = n_best;
+	p = p_best;
+	splitm(index, m, &m1, &m2);
+	splitp(index, p, &p1, &p2);
+	n1 = n - 2;
+
+	DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
+		"f: %d (%d), VCO: %d\n",
+		m, m1, m2, n, n1, p, p1, p2,
+		calc_vclock3(index, m, n, p),
+		calc_vclock(index, m1, m2, n1, p1, p2, 0),
+		calc_vclock3(index, m, n, p) * p);
+	*retm1 = m1;
+	*retm2 = m2;
+	*retn = n1;
+	*retp1 = p1;
+	*retp2 = p2;
+	*retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);
+
+	return 0;
+}
+
+static __inline__ int check_overflow(u32 value, u32 limit,
+				     const char *description)
+{
+	if (value > limit) {
+		WRN_MSG("%s value %d exceeds limit %d\n",
+			description, value, limit);
+		return 1;
+	}
+	return 0;
+}
+
+/* It is assumed that hw is filled in with the initial state information. */
+int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
+			 struct intelfb_hwstate *hw,
+			 struct fb_var_screeninfo *var)
+{
+	int pipe = intelfbhw_active_pipe(hw);
+	u32 *dpll, *fp0, *fp1;
+	u32 m1, m2, n, p1, p2, clock_target, clock;
+	u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
+	u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
+	u32 vsync_pol, hsync_pol;
+	u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
+	u32 stride_alignment;
+
+	DBG_MSG("intelfbhw_mode_to_hw\n");
+
+	/* Disable VGA */
+	hw->vgacntrl |= VGA_DISABLE;
+
+	/* Set which pipe's registers will be set. */
+	if (pipe == PIPE_B) {
+		dpll = &hw->dpll_b;
+		fp0 = &hw->fpb0;
+		fp1 = &hw->fpb1;
+		hs = &hw->hsync_b;
+		hb = &hw->hblank_b;
+		ht = &hw->htotal_b;
+		vs = &hw->vsync_b;
+		vb = &hw->vblank_b;
+		vt = &hw->vtotal_b;
+		ss = &hw->src_size_b;
+		pipe_conf = &hw->pipe_b_conf;
+	} else {
+		dpll = &hw->dpll_a;
+		fp0 = &hw->fpa0;
+		fp1 = &hw->fpa1;
+		hs = &hw->hsync_a;
+		hb = &hw->hblank_a;
+		ht = &hw->htotal_a;
+		vs = &hw->vsync_a;
+		vb = &hw->vblank_a;
+		vt = &hw->vtotal_a;
+		ss = &hw->src_size_a;
+		pipe_conf = &hw->pipe_a_conf;
+	}
+
+	/* Use ADPA register for sync control. */
+	hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
+
+	/* sync polarity */
+	hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ?
+			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
+	vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ?
+			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
+	hw->adpa &= ~((ADPA_SYNC_ACTIVE_MASK << ADPA_VSYNC_ACTIVE_SHIFT) |
+		      (ADPA_SYNC_ACTIVE_MASK << ADPA_HSYNC_ACTIVE_SHIFT));
+	hw->adpa |= (hsync_pol << ADPA_HSYNC_ACTIVE_SHIFT) |
+		    (vsync_pol << ADPA_VSYNC_ACTIVE_SHIFT);
+
+	/* Connect correct pipe to the analog port DAC */
+	hw->adpa &= ~(PIPE_MASK << ADPA_PIPE_SELECT_SHIFT);
+	hw->adpa |= (pipe << ADPA_PIPE_SELECT_SHIFT);
+
+	/* Set DPMS state to D0 (on) */
+	hw->adpa &= ~ADPA_DPMS_CONTROL_MASK;
+	hw->adpa |= ADPA_DPMS_D0;
+
+	hw->adpa |= ADPA_DAC_ENABLE;
+
+	*dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
+	*dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
+	*dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
+
+	/* Desired clock in kHz */
+	clock_target = 1000000000 / var->pixclock;
+
+	if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2,
+			    &n, &p1, &p2, &clock)) {
+		WRN_MSG("calc_pll_params failed\n");
+		return 1;
+	}
+
+	/* Check for overflow. */
+	if (check_overflow(p1, DPLL_P1_MASK, "PLL P1 parameter"))
+		return 1;
+	if (check_overflow(p2, DPLL_P2_MASK, "PLL P2 parameter"))
+		return 1;
+	if (check_overflow(m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
+		return 1;
+	if (check_overflow(m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
+		return 1;
+	if (check_overflow(n, FP_DIVISOR_MASK, "PLL N parameter"))
+		return 1;
+
+	*dpll &= ~DPLL_P1_FORCE_DIV2;
+	*dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
+		   (DPLL_P1_MASK << DPLL_P1_SHIFT));
+
+	if (IS_I9XX(dinfo)) {
+		*dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
+		*dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
+	} else
+		*dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
+
+	*fp0 = (n << FP_N_DIVISOR_SHIFT) |
+	       (m1 << FP_M1_DIVISOR_SHIFT) |
+	       (m2 << FP_M2_DIVISOR_SHIFT);
+	*fp1 = *fp0;
+
+	hw->dvob &= ~PORT_ENABLE;
+	hw->dvoc &= ~PORT_ENABLE;
+
+	/* Use display plane A. */
+	hw->disp_a_ctrl |= DISPPLANE_PLANE_ENABLE;
+	hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
+	hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
+	switch (intelfb_var_to_depth(var)) {
+	case 8:
+		hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
+		break;
+	case 15:
+		hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
+		break;
+	case 16:
+		hw->disp_a_ctrl |= DISPPLANE_16BPP;
+		break;
+	case 24:
+		hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
+		break;
+	}
+	hw->disp_a_ctrl &= ~(PIPE_MASK << DISPPLANE_SEL_PIPE_SHIFT);
+	hw->disp_a_ctrl |= (pipe << DISPPLANE_SEL_PIPE_SHIFT);
+
+	/* Set CRTC registers. */
+	hactive = var->xres;
+	hsync_start = hactive + var->right_margin;
+	hsync_end = hsync_start + var->hsync_len;
+	htotal = hsync_end + var->left_margin;
+	hblank_start = hactive;
+	hblank_end = htotal;
+
+	DBG_MSG("H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
+		hactive, hsync_start, hsync_end, htotal, hblank_start,
+		hblank_end);
+
+	vactive = var->yres;
+	if (var->vmode & FB_VMODE_INTERLACED)
+		vactive--; /* the chip adds 2 halflines automatically */
+	vsync_start = vactive + var->lower_margin;
+	vsync_end = vsync_start + var->vsync_len;
+	vtotal = vsync_end + var->upper_margin;
+	vblank_start = vactive;
+	vblank_end = vtotal;
+	vblank_end = vsync_end + 1;
+
+	DBG_MSG("V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
+		vactive, vsync_start, vsync_end, vtotal, vblank_start,
+		vblank_end);
+
+	/* Adjust for register values, and check for overflow. */
+	hactive--;
+	if (check_overflow(hactive, HACTIVE_MASK, "CRTC hactive"))
+		return 1;
+	hsync_start--;
+	if (check_overflow(hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
+		return 1;
+	hsync_end--;
+	if (check_overflow(hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
+		return 1;
+	htotal--;
+	if (check_overflow(htotal, HTOTAL_MASK, "CRTC htotal"))
+		return 1;
+	hblank_start--;
+	if (check_overflow(hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
+		return 1;
+	hblank_end--;
+	if (check_overflow(hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
+		return 1;
+
+	vactive--;
+	if (check_overflow(vactive, VACTIVE_MASK, "CRTC vactive"))
+		return 1;
+	vsync_start--;
+	if (check_overflow(vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
+		return 1;
+	vsync_end--;
+	if (check_overflow(vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
+		return 1;
+	vtotal--;
+	if (check_overflow(vtotal, VTOTAL_MASK, "CRTC vtotal"))
+		return 1;
+	vblank_start--;
+	if (check_overflow(vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
+		return 1;
+	vblank_end--;
+	if (check_overflow(vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
+		return 1;
+
+	*ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
+	*hb = (hblank_start << HBLANKSTART_SHIFT) |
+	      (hblank_end << HSYNCEND_SHIFT);
+	*hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
+
+	*vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
+	*vb = (vblank_start << VBLANKSTART_SHIFT) |
+	      (vblank_end << VSYNCEND_SHIFT);
+	*vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
+	*ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
+	      (vactive << SRC_SIZE_VERT_SHIFT);
+
+	hw->disp_a_stride = dinfo->pitch;
+	DBG_MSG("pitch is %d\n", hw->disp_a_stride);
+
+	hw->disp_a_base = hw->disp_a_stride * var->yoffset +
+			  var->xoffset * var->bits_per_pixel / 8;
+
+	hw->disp_a_base += dinfo->fb.offset << 12;
+
+	/* Check stride alignment. */
+	stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX :
+					    STRIDE_ALIGNMENT;
+	if (hw->disp_a_stride % stride_alignment != 0) {
+		WRN_MSG("display stride %d has bad alignment %d\n",
+			hw->disp_a_stride, stride_alignment);
+		return 1;
+	}
+
+	/* Set the palette to 8-bit mode. */
+	*pipe_conf &= ~PIPECONF_GAMMA;
+
+	if (var->vmode & FB_VMODE_INTERLACED)
+		*pipe_conf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+	else
+		*pipe_conf &= ~PIPECONF_INTERLACE_MASK;
+
+	return 0;
+}
+
+/* Program a (non-VGA) video mode. */
+int intelfbhw_program_mode(struct intelfb_info *dinfo,
+			   const struct intelfb_hwstate *hw, int blank)
+{
+	u32 tmp;
+	const u32 *dpll, *fp0, *fp1, *pipe_conf;
+	const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
+	u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg, pipe_stat_reg;
+	u32 hsync_reg, htotal_reg, hblank_reg;
+	u32 vsync_reg, vtotal_reg, vblank_reg;
+	u32 src_size_reg;
+	u32 count, tmp_val[3];
+
+	/* Assume single pipe */
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_program_mode\n");
+#endif
+
+	/* Disable VGA */
+	tmp = INREG(VGACNTRL);
+	tmp |= VGA_DISABLE;
+	OUTREG(VGACNTRL, tmp);
+
+	dinfo->pipe = intelfbhw_active_pipe(hw);
+
+	if (dinfo->pipe == PIPE_B) {
+		dpll = &hw->dpll_b;
+		fp0 = &hw->fpb0;
+		fp1 = &hw->fpb1;
+		pipe_conf = &hw->pipe_b_conf;
+		hs = &hw->hsync_b;
+		hb = &hw->hblank_b;
+		ht = &hw->htotal_b;
+		vs = &hw->vsync_b;
+		vb = &hw->vblank_b;
+		vt = &hw->vtotal_b;
+		ss = &hw->src_size_b;
+		dpll_reg = DPLL_B;
+		fp0_reg = FPB0;
+		fp1_reg = FPB1;
+		pipe_conf_reg = PIPEBCONF;
+		pipe_stat_reg = PIPEBSTAT;
+		hsync_reg = HSYNC_B;
+		htotal_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		vsync_reg = VSYNC_B;
+		vtotal_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		src_size_reg = SRC_SIZE_B;
+	} else {
+		dpll = &hw->dpll_a;
+		fp0 = &hw->fpa0;
+		fp1 = &hw->fpa1;
+		pipe_conf = &hw->pipe_a_conf;
+		hs = &hw->hsync_a;
+		hb = &hw->hblank_a;
+		ht = &hw->htotal_a;
+		vs = &hw->vsync_a;
+		vb = &hw->vblank_a;
+		vt = &hw->vtotal_a;
+		ss = &hw->src_size_a;
+		dpll_reg = DPLL_A;
+		fp0_reg = FPA0;
+		fp1_reg = FPA1;
+		pipe_conf_reg = PIPEACONF;
+		pipe_stat_reg = PIPEASTAT;
+		hsync_reg = HSYNC_A;
+		htotal_reg = HTOTAL_A;
+		hblank_reg = HBLANK_A;
+		vsync_reg = VSYNC_A;
+		vtotal_reg = VTOTAL_A;
+		vblank_reg = VBLANK_A;
+		src_size_reg = SRC_SIZE_A;
+	}
+
+	/* turn off pipe */
+	tmp = INREG(pipe_conf_reg);
+	tmp &= ~PIPECONF_ENABLE;
+	OUTREG(pipe_conf_reg, tmp);
+
+	count = 0;
+	do {
+		tmp_val[count % 3] = INREG(PIPEA_DSL);
+		if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1] == tmp_val[2]))
+			break;
+		count++;
+		udelay(1);
+		if (count % 200 == 0) {
+			tmp = INREG(pipe_conf_reg);
+			tmp &= ~PIPECONF_ENABLE;
+			OUTREG(pipe_conf_reg, tmp);
+		}
+	} while (count < 2000);
+
+	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
+
+	/* Disable planes A and B. */
+	tmp = INREG(DSPACNTR);
+	tmp &= ~DISPPLANE_PLANE_ENABLE;
+	OUTREG(DSPACNTR, tmp);
+	tmp = INREG(DSPBCNTR);
+	tmp &= ~DISPPLANE_PLANE_ENABLE;
+	OUTREG(DSPBCNTR, tmp);
+
+	/* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
+	mdelay(20);
+
+	OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE);
+	OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE);
+	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
+
+	/* Disable Sync */
+	tmp = INREG(ADPA);
+	tmp &= ~ADPA_DPMS_CONTROL_MASK;
+	tmp |= ADPA_DPMS_D3;
+	OUTREG(ADPA, tmp);
+
+	/* do some funky magic - xyzzy */
+	OUTREG(0x61204, 0xabcd0000);
+
+	/* turn off PLL */
+	tmp = INREG(dpll_reg);
+	tmp &= ~DPLL_VCO_ENABLE;
+	OUTREG(dpll_reg, tmp);
+
+	/* Set PLL parameters */
+	OUTREG(fp0_reg, *fp0);
+	OUTREG(fp1_reg, *fp1);
+
+	/* Enable PLL */
+	OUTREG(dpll_reg, *dpll);
+
+	/* Set DVOs B/C */
+	OUTREG(DVOB, hw->dvob);
+	OUTREG(DVOC, hw->dvoc);
+
+	/* undo funky magic */
+	OUTREG(0x61204, 0x00000000);
+
+	/* Set ADPA */
+	OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE);
+	OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
+
+	/* Set pipe parameters */
+	OUTREG(hsync_reg, *hs);
+	OUTREG(hblank_reg, *hb);
+	OUTREG(htotal_reg, *ht);
+	OUTREG(vsync_reg, *vs);
+	OUTREG(vblank_reg, *vb);
+	OUTREG(vtotal_reg, *vt);
+	OUTREG(src_size_reg, *ss);
+
+	switch (dinfo->info->var.vmode & (FB_VMODE_INTERLACED |
+					  FB_VMODE_ODD_FLD_FIRST)) {
+	case FB_VMODE_INTERLACED | FB_VMODE_ODD_FLD_FIRST:
+		OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_ODD_EN);
+		break;
+	case FB_VMODE_INTERLACED: /* even lines first */
+		OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_EVEN_EN);
+		break;
+	default:		/* non-interlaced */
+		OUTREG(pipe_stat_reg, 0xFFFF); /* clear all status bits only */
+	}
+	/* Enable pipe */
+	OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
+
+	/* Enable sync */
+	tmp = INREG(ADPA);
+	tmp &= ~ADPA_DPMS_CONTROL_MASK;
+	tmp |= ADPA_DPMS_D0;
+	OUTREG(ADPA, tmp);
+
+	/* setup display plane */
+	if (dinfo->pdev->device == PCI_DEVICE_ID_INTEL_830M) {
+		/*
+		 *      i830M errata: the display plane must be enabled
+		 *      to allow writes to the other bits in the plane
+		 *      control register.
+		 */
+		tmp = INREG(DSPACNTR);
+		if ((tmp & DISPPLANE_PLANE_ENABLE) != DISPPLANE_PLANE_ENABLE) {
+			tmp |= DISPPLANE_PLANE_ENABLE;
+			OUTREG(DSPACNTR, tmp);
+			OUTREG(DSPACNTR,
+			       hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
+			mdelay(1);
+		}
+	}
+
+	OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
+	OUTREG(DSPASTRIDE, hw->disp_a_stride);
+	OUTREG(DSPABASE, hw->disp_a_base);
+
+	/* Enable plane */
+	if (!blank) {
+		tmp = INREG(DSPACNTR);
+		tmp |= DISPPLANE_PLANE_ENABLE;
+		OUTREG(DSPACNTR, tmp);
+		OUTREG(DSPABASE, hw->disp_a_base);
+	}
+
+	return 0;
+}
+
+/* forward declarations */
+static void refresh_ring(struct intelfb_info *dinfo);
+static void reset_state(struct intelfb_info *dinfo);
+static void do_flush(struct intelfb_info *dinfo);
+
+static  u32 get_ring_space(struct intelfb_info *dinfo)
+{
+	u32 ring_space;
+
+	if (dinfo->ring_tail >= dinfo->ring_head)
+		ring_space = dinfo->ring.size -
+			(dinfo->ring_tail - dinfo->ring_head);
+	else
+		ring_space = dinfo->ring_head - dinfo->ring_tail;
+
+	if (ring_space > RING_MIN_FREE)
+		ring_space -= RING_MIN_FREE;
+	else
+		ring_space = 0;
+
+	return ring_space;
+}
+
+static int wait_ring(struct intelfb_info *dinfo, int n)
+{
+	int i = 0;
+	unsigned long end;
+	u32 last_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
+
+#if VERBOSE > 0
+	DBG_MSG("wait_ring: %d\n", n);
+#endif
+
+	end = jiffies + (HZ * 3);
+	while (dinfo->ring_space < n) {
+		dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
+		dinfo->ring_space = get_ring_space(dinfo);
+
+		if (dinfo->ring_head != last_head) {
+			end = jiffies + (HZ * 3);
+			last_head = dinfo->ring_head;
+		}
+		i++;
+		if (time_before(end, jiffies)) {
+			if (!i) {
+				/* Try again */
+				reset_state(dinfo);
+				refresh_ring(dinfo);
+				do_flush(dinfo);
+				end = jiffies + (HZ * 3);
+				i = 1;
+			} else {
+				WRN_MSG("ring buffer : space: %d wanted %d\n",
+					dinfo->ring_space, n);
+				WRN_MSG("lockup - turning off hardware "
+					"acceleration\n");
+				dinfo->ring_lockup = 1;
+				break;
+			}
+		}
+		udelay(1);
+	}
+	return i;
+}
+
+static void do_flush(struct intelfb_info *dinfo)
+{
+	START_RING(2);
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+	OUT_RING(MI_NOOP);
+	ADVANCE_RING();
+}
+
+void intelfbhw_do_sync(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_sync\n");
+#endif
+
+	if (!dinfo->accel)
+		return;
+
+	/*
+	 * Send a flush, then wait until the ring is empty.  This is what
+	 * the XFree86 driver does, and actually it doesn't seem a lot worse
+	 * than the recommended method (both have problems).
+	 */
+	do_flush(dinfo);
+	wait_ring(dinfo, dinfo->ring.size - RING_MIN_FREE);
+	dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
+}
+
+static void refresh_ring(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("refresh_ring\n");
+#endif
+
+	dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
+	dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
+	dinfo->ring_space = get_ring_space(dinfo);
+}
+
+static void reset_state(struct intelfb_info *dinfo)
+{
+	int i;
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("reset_state\n");
+#endif
+
+	for (i = 0; i < FENCE_NUM; i++)
+		OUTREG(FENCE + (i << 2), 0);
+
+	/* Flush the ring buffer if it's enabled. */
+	tmp = INREG(PRI_RING_LENGTH);
+	if (tmp & RING_ENABLE) {
+#if VERBOSE > 0
+		DBG_MSG("reset_state: ring was enabled\n");
+#endif
+		refresh_ring(dinfo);
+		intelfbhw_do_sync(dinfo);
+		DO_RING_IDLE();
+	}
+
+	OUTREG(PRI_RING_LENGTH, 0);
+	OUTREG(PRI_RING_HEAD, 0);
+	OUTREG(PRI_RING_TAIL, 0);
+	OUTREG(PRI_RING_START, 0);
+}
+
+/* Stop the 2D engine, and turn off the ring buffer. */
+void intelfbhw_2d_stop(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n",
+		dinfo->accel, dinfo->ring_active);
+#endif
+
+	if (!dinfo->accel)
+		return;
+
+	dinfo->ring_active = 0;
+	reset_state(dinfo);
+}
+
+/*
+ * Enable the ring buffer, and initialise the 2D engine.
+ * It is assumed that the graphics engine has been stopped by previously
+ * calling intelfb_2d_stop().
+ */
+void intelfbhw_2d_start(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
+		dinfo->accel, dinfo->ring_active);
+#endif
+
+	if (!dinfo->accel)
+		return;
+
+	/* Initialise the primary ring buffer. */
+	OUTREG(PRI_RING_LENGTH, 0);
+	OUTREG(PRI_RING_TAIL, 0);
+	OUTREG(PRI_RING_HEAD, 0);
+
+	OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);
+	OUTREG(PRI_RING_LENGTH,
+		((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |
+		RING_NO_REPORT | RING_ENABLE);
+	refresh_ring(dinfo);
+	dinfo->ring_active = 1;
+}
+
+/* 2D fillrect (solid fill or invert) */
+void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w,
+			   u32 h, u32 color, u32 pitch, u32 bpp, u32 rop)
+{
+	u32 br00, br09, br13, br14, br16;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "
+		"rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);
+#endif
+
+	br00 = COLOR_BLT_CMD;
+	br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));
+	br13 = (rop << ROP_SHIFT) | pitch;
+	br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);
+	br16 = color;
+
+	switch (bpp) {
+	case 8:
+		br13 |= COLOR_DEPTH_8;
+		break;
+	case 16:
+		br13 |= COLOR_DEPTH_16;
+		break;
+	case 32:
+		br13 |= COLOR_DEPTH_32;
+		br00 |= WRITE_ALPHA | WRITE_RGB;
+		break;
+	}
+
+	START_RING(6);
+	OUT_RING(br00);
+	OUT_RING(br13);
+	OUT_RING(br14);
+	OUT_RING(br09);
+	OUT_RING(br16);
+	OUT_RING(MI_NOOP);
+	ADVANCE_RING();
+
+#if VERBOSE > 0
+	DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,
+		dinfo->ring_tail, dinfo->ring_space);
+#endif
+}
+
+void
+intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
+		    u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp)
+{
+	u32 br00, br09, br11, br12, br13, br22, br23, br26;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",
+		curx, cury, dstx, dsty, w, h, pitch, bpp);
+#endif
+
+	br00 = XY_SRC_COPY_BLT_CMD;
+	br09 = dinfo->fb_start;
+	br11 = (pitch << PITCH_SHIFT);
+	br12 = dinfo->fb_start;
+	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
+	br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);
+	br23 = ((dstx + w) << WIDTH_SHIFT) |
+	       ((dsty + h) << HEIGHT_SHIFT);
+	br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);
+
+	switch (bpp) {
+	case 8:
+		br13 |= COLOR_DEPTH_8;
+		break;
+	case 16:
+		br13 |= COLOR_DEPTH_16;
+		break;
+	case 32:
+		br13 |= COLOR_DEPTH_32;
+		br00 |= WRITE_ALPHA | WRITE_RGB;
+		break;
+	}
+
+	START_RING(8);
+	OUT_RING(br00);
+	OUT_RING(br13);
+	OUT_RING(br22);
+	OUT_RING(br23);
+	OUT_RING(br09);
+	OUT_RING(br26);
+	OUT_RING(br11);
+	OUT_RING(br12);
+	ADVANCE_RING();
+}
+
+int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
+			   u32 h, const u8* cdat, u32 x, u32 y, u32 pitch,
+			   u32 bpp)
+{
+	int nbytes, ndwords, pad, tmp;
+	u32 br00, br09, br13, br18, br19, br22, br23;
+	int dat, ix, iy, iw;
+	int i, j;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);
+#endif
+
+	/* size in bytes of a padded scanline */
+	nbytes = ROUND_UP_TO(w, 16) / 8;
+
+	/* Total bytes of padded scanline data to write out. */
+	nbytes = nbytes * h;
+
+	/*
+	 * Check if the glyph data exceeds the immediate mode limit.
+	 * It would take a large font (1K pixels) to hit this limit.
+	 */
+	if (nbytes > MAX_MONO_IMM_SIZE)
+		return 0;
+
+	/* Src data is packaged a dword (32-bit) at a time. */
+	ndwords = ROUND_UP_TO(nbytes, 4) / 4;
+
+	/*
+	 * Ring has to be padded to a quad word. But because the command starts
+	   with 7 bytes, pad only if there is an even number of ndwords
+	 */
+	pad = !(ndwords % 2);
+
+	tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;
+	br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;
+	br09 = dinfo->fb_start;
+	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
+	br18 = bg;
+	br19 = fg;
+	br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);
+	br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);
+
+	switch (bpp) {
+	case 8:
+		br13 |= COLOR_DEPTH_8;
+		break;
+	case 16:
+		br13 |= COLOR_DEPTH_16;
+		break;
+	case 32:
+		br13 |= COLOR_DEPTH_32;
+		br00 |= WRITE_ALPHA | WRITE_RGB;
+		break;
+	}
+
+	START_RING(8 + ndwords);
+	OUT_RING(br00);
+	OUT_RING(br13);
+	OUT_RING(br22);
+	OUT_RING(br23);
+	OUT_RING(br09);
+	OUT_RING(br18);
+	OUT_RING(br19);
+	ix = iy = 0;
+	iw = ROUND_UP_TO(w, 8) / 8;
+	while (ndwords--) {
+		dat = 0;
+		for (j = 0; j < 2; ++j) {
+			for (i = 0; i < 2; ++i) {
+				if (ix != iw || i == 0)
+					dat |= cdat[iy*iw + ix++] << (i+j*2)*8;
+			}
+			if (ix == iw && iy != (h-1)) {
+				ix = 0;
+				++iy;
+			}
+		}
+		OUT_RING(dat);
+	}
+	if (pad)
+		OUT_RING(MI_NOOP);
+	ADVANCE_RING();
+
+	return 1;
+}
+
+/* HW cursor functions. */
+void intelfbhw_cursor_init(struct intelfb_info *dinfo)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_init\n");
+#endif
+
+	if (dinfo->mobile || IS_I9XX(dinfo)) {
+		if (!dinfo->cursor.physical)
+			return;
+		tmp = INREG(CURSOR_A_CONTROL);
+		tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |
+			 CURSOR_MEM_TYPE_LOCAL |
+			 (1 << CURSOR_PIPE_SELECT_SHIFT));
+		tmp |= CURSOR_MODE_DISABLE;
+		OUTREG(CURSOR_A_CONTROL, tmp);
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+	} else {
+		tmp = INREG(CURSOR_CONTROL);
+		tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
+			 CURSOR_ENABLE | CURSOR_STRIDE_MASK);
+		tmp = CURSOR_FORMAT_3C;
+		OUTREG(CURSOR_CONTROL, tmp);
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.offset << 12);
+		tmp = (64 << CURSOR_SIZE_H_SHIFT) |
+		      (64 << CURSOR_SIZE_V_SHIFT);
+		OUTREG(CURSOR_SIZE, tmp);
+	}
+}
+
+void intelfbhw_cursor_hide(struct intelfb_info *dinfo)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_hide\n");
+#endif
+
+	dinfo->cursor_on = 0;
+	if (dinfo->mobile || IS_I9XX(dinfo)) {
+		if (!dinfo->cursor.physical)
+			return;
+		tmp = INREG(CURSOR_A_CONTROL);
+		tmp &= ~CURSOR_MODE_MASK;
+		tmp |= CURSOR_MODE_DISABLE;
+		OUTREG(CURSOR_A_CONTROL, tmp);
+		/* Flush changes */
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+	} else {
+		tmp = INREG(CURSOR_CONTROL);
+		tmp &= ~CURSOR_ENABLE;
+		OUTREG(CURSOR_CONTROL, tmp);
+	}
+}
+
+void intelfbhw_cursor_show(struct intelfb_info *dinfo)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_show\n");
+#endif
+
+	dinfo->cursor_on = 1;
+
+	if (dinfo->cursor_blanked)
+		return;
+
+	if (dinfo->mobile || IS_I9XX(dinfo)) {
+		if (!dinfo->cursor.physical)
+			return;
+		tmp = INREG(CURSOR_A_CONTROL);
+		tmp &= ~CURSOR_MODE_MASK;
+		tmp |= CURSOR_MODE_64_4C_AX;
+		OUTREG(CURSOR_A_CONTROL, tmp);
+		/* Flush changes */
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+	} else {
+		tmp = INREG(CURSOR_CONTROL);
+		tmp |= CURSOR_ENABLE;
+		OUTREG(CURSOR_CONTROL, tmp);
+	}
+}
+
+void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);
+#endif
+
+	/*
+	 * Sets the position. The coordinates are assumed to already
+	 * have any offset adjusted. Assume that the cursor is never
+	 * completely off-screen, and that x, y are always >= 0.
+	 */
+
+	tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
+	      ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+	OUTREG(CURSOR_A_POSITION, tmp);
+
+	if (IS_I9XX(dinfo))
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+}
+
+void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_setcolor\n");
+#endif
+
+	OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);
+	OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);
+	OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);
+	OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
+}
+
+void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
+			   u8 *data)
+{
+	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
+	int i, j, w = width / 8;
+	int mod = width % 8, t_mask, d_mask;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_load\n");
+#endif
+
+	if (!dinfo->cursor.virtual)
+		return;
+
+	t_mask = 0xff >> mod;
+	d_mask = ~(0xff >> mod);
+	for (i = height; i--; ) {
+		for (j = 0; j < w; j++) {
+			writeb(0x00, addr + j);
+			writeb(*(data++), addr + j+8);
+		}
+		if (mod) {
+			writeb(t_mask, addr + j);
+			writeb(*(data++) & d_mask, addr + j+8);
+		}
+		addr += 16;
+	}
+}
+
+void intelfbhw_cursor_reset(struct intelfb_info *dinfo)
+{
+	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
+	int i, j;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_reset\n");
+#endif
+
+	if (!dinfo->cursor.virtual)
+		return;
+
+	for (i = 64; i--; ) {
+		for (j = 0; j < 8; j++) {
+			writeb(0xff, addr + j+0);
+			writeb(0x00, addr + j+8);
+		}
+		addr += 16;
+	}
+}
+
+static irqreturn_t intelfbhw_irq(int irq, void *dev_id)
+{
+	u16 tmp;
+	struct intelfb_info *dinfo = dev_id;
+
+	spin_lock(&dinfo->int_lock);
+
+	tmp = INREG16(IIR);
+	if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
+		tmp &= PIPE_A_EVENT_INTERRUPT;
+	else
+		tmp &= VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
+
+	if (tmp == 0) {
+		spin_unlock(&dinfo->int_lock);
+		return IRQ_RETVAL(0); /* not us */
+	}
+
+	/* clear status bits 0-15 ASAP and don't touch bits 16-31 */
+	OUTREG(PIPEASTAT, INREG(PIPEASTAT));
+
+	OUTREG16(IIR, tmp);
+	if (dinfo->vsync.pan_display) {
+		dinfo->vsync.pan_display = 0;
+		OUTREG(DSPABASE, dinfo->vsync.pan_offset);
+	}
+
+	dinfo->vsync.count++;
+	wake_up_interruptible(&dinfo->vsync.wait);
+
+	spin_unlock(&dinfo->int_lock);
+
+	return IRQ_RETVAL(1);
+}
+
+int intelfbhw_enable_irq(struct intelfb_info *dinfo)
+{
+	u16 tmp;
+	if (!test_and_set_bit(0, &dinfo->irq_flags)) {
+		if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,
+				"intelfb", dinfo)) {
+			clear_bit(0, &dinfo->irq_flags);
+			return -EINVAL;
+		}
+
+		spin_lock_irq(&dinfo->int_lock);
+		OUTREG16(HWSTAM, 0xfffe); /* i830 DRM uses ffff */
+		OUTREG16(IMR, 0);
+	} else
+		spin_lock_irq(&dinfo->int_lock);
+
+	if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
+		tmp = PIPE_A_EVENT_INTERRUPT;
+	else
+		tmp = VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
+	if (tmp != INREG16(IER)) {
+		DBG_MSG("changing IER to 0x%X\n", tmp);
+		OUTREG16(IER, tmp);
+	}
+
+	spin_unlock_irq(&dinfo->int_lock);
+	return 0;
+}
+
+void intelfbhw_disable_irq(struct intelfb_info *dinfo)
+{
+	if (test_and_clear_bit(0, &dinfo->irq_flags)) {
+		if (dinfo->vsync.pan_display) {
+			dinfo->vsync.pan_display = 0;
+			OUTREG(DSPABASE, dinfo->vsync.pan_offset);
+		}
+		spin_lock_irq(&dinfo->int_lock);
+		OUTREG16(HWSTAM, 0xffff);
+		OUTREG16(IMR, 0xffff);
+		OUTREG16(IER, 0x0);
+
+		OUTREG16(IIR, INREG16(IIR)); /* clear IRQ requests */
+		spin_unlock_irq(&dinfo->int_lock);
+
+		free_irq(dinfo->pdev->irq, dinfo);
+	}
+}
+
+int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe)
+{
+	struct intelfb_vsync *vsync;
+	unsigned int count;
+	int ret;
+
+	switch (pipe) {
+		case 0:
+			vsync = &dinfo->vsync;
+			break;
+		default:
+			return -ENODEV;
+	}
+
+	ret = intelfbhw_enable_irq(dinfo);
+	if (ret)
+		return ret;
+
+	count = vsync->count;
+	ret = wait_event_interruptible_timeout(vsync->wait,
+					       count != vsync->count, HZ / 10);
+	if (ret < 0)
+		return ret;
+	if (ret == 0) {
+		DBG_MSG("wait_for_vsync timed out!\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/intelfb/intelfbhw.h b/drivers/video/fbdev/intelfb/intelfbhw.h
new file mode 100644
index 000000000000..216ca20f259f
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfbhw.h
@@ -0,0 +1,609 @@
+#ifndef _INTELFBHW_H
+#define _INTELFBHW_H
+
+/* $DHD: intelfb/intelfbhw.h,v 1.5 2003/06/27 15:06:25 dawes Exp $ */
+
+
+/*** HW-specific data ***/
+
+/* Information about the 852GM/855GM variants */
+#define INTEL_85X_CAPID		0x44
+#define INTEL_85X_VARIANT_MASK		0x7
+#define INTEL_85X_VARIANT_SHIFT		5
+#define INTEL_VAR_855GME		0x0
+#define INTEL_VAR_855GM			0x4
+#define INTEL_VAR_852GME		0x2
+#define INTEL_VAR_852GM			0x5
+
+/* Information about DVO/LVDS Ports */
+#define DVOA_PORT  0x1
+#define DVOB_PORT  0x2
+#define DVOC_PORT  0x4
+#define LVDS_PORT  0x8
+
+/*
+ * The Bridge device's PCI config space has information about the
+ * fb aperture size and the amount of pre-reserved memory.
+ */
+#define INTEL_GMCH_CTRL		0x52
+#define INTEL_GMCH_ENABLED		0x4
+#define INTEL_GMCH_MEM_MASK		0x1
+#define INTEL_GMCH_MEM_64M		0x1
+#define INTEL_GMCH_MEM_128M		0
+
+#define INTEL_830_GMCH_GMS_MASK		(0x7 << 4)
+#define INTEL_830_GMCH_GMS_DISABLED	(0x0 << 4)
+#define INTEL_830_GMCH_GMS_LOCAL	(0x1 << 4)
+#define INTEL_830_GMCH_GMS_STOLEN_512	(0x2 << 4)
+#define INTEL_830_GMCH_GMS_STOLEN_1024	(0x3 << 4)
+#define INTEL_830_GMCH_GMS_STOLEN_8192	(0x4 << 4)
+
+#define INTEL_855_GMCH_GMS_MASK		(0x7 << 4)
+#define INTEL_855_GMCH_GMS_DISABLED	(0x0 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_1M	(0x1 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_4M	(0x2 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_8M	(0x3 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_16M	(0x4 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_32M	(0x5 << 4)
+
+#define INTEL_915G_GMCH_GMS_STOLEN_48M	(0x6 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_64M	(0x7 << 4)
+
+/* HW registers */
+
+/* Fence registers */
+#define FENCE			0x2000
+#define FENCE_NUM			8
+
+/* Primary ring buffer */
+#define PRI_RING_TAIL		0x2030
+#define RING_TAIL_MASK			0x001ffff8
+#define RING_INUSE			0x1
+
+#define PRI_RING_HEAD		0x2034
+#define RING_HEAD_WRAP_MASK		0x7ff
+#define RING_HEAD_WRAP_SHIFT		21
+#define RING_HEAD_MASK			0x001ffffc
+
+#define PRI_RING_START		0x2038
+#define RING_START_MASK			0xfffff000
+
+#define PRI_RING_LENGTH		0x203c
+#define RING_LENGTH_MASK		0x001ff000
+#define RING_REPORT_MASK		(0x3 << 1)
+#define RING_NO_REPORT			(0x0 << 1)
+#define RING_REPORT_64K			(0x1 << 1)
+#define RING_REPORT_4K			(0x2 << 1)
+#define RING_REPORT_128K		(0x3 << 1)
+#define RING_ENABLE			0x1
+
+/*
+ * Tail can't wrap to any closer than RING_MIN_FREE bytes of the head,
+ * and the last RING_MIN_FREE bytes need to be padded with MI_NOOP
+ */
+#define RING_MIN_FREE			64
+
+#define IPEHR			0x2088
+
+#define INSTDONE		0x2090
+#define PRI_RING_EMPTY			1
+
+#define HWSTAM			0x2098
+#define IER			0x20A0
+#define IIR			0x20A4
+#define IMR			0x20A8
+#define VSYNC_PIPE_A_INTERRUPT		(1 << 7)
+#define PIPE_A_EVENT_INTERRUPT		(1 << 6)
+#define VSYNC_PIPE_B_INTERRUPT		(1 << 5)
+#define PIPE_B_EVENT_INTERRUPT		(1 << 4)
+#define HOST_PORT_EVENT_INTERRUPT	(1 << 3)
+#define CAPTURE_EVENT_INTERRUPT		(1 << 2)
+#define USER_DEFINED_INTERRUPT		(1 << 1)
+#define BREAKPOINT_INTERRUPT		1
+
+#define INSTPM			0x20c0
+#define SYNC_FLUSH_ENABLE		(1 << 5)
+
+#define INSTPS			0x20c4
+
+#define MEM_MODE		0x20cc
+
+#define MASK_SHIFT			16
+
+#define FW_BLC_0		0x20d8
+#define FW_DISPA_WM_SHIFT		0
+#define FW_DISPA_WM_MASK		0x3f
+#define FW_DISPA_BL_SHIFT		8
+#define FW_DISPA_BL_MASK		0xf
+#define FW_DISPB_WM_SHIFT		16
+#define FW_DISPB_WM_MASK		0x1f
+#define FW_DISPB_BL_SHIFT		24
+#define FW_DISPB_BL_MASK		0x7
+
+#define FW_BLC_1		0x20dc
+#define FW_DISPC_WM_SHIFT		0
+#define FW_DISPC_WM_MASK		0x1f
+#define FW_DISPC_BL_SHIFT		8
+#define FW_DISPC_BL_MASK		0x7
+
+#define GPIOA             0x5010
+#define GPIOB             0x5014
+#define GPIOC             0x5018 /* this may be external DDC on i830 */
+#define GPIOD             0x501C /* this is DVO DDC */
+#define GPIOE             0x5020 /* this is DVO i2C */
+#define GPIOF             0x5024
+
+/* PLL registers */
+#define VGA0_DIVISOR		0x06000
+#define VGA1_DIVISOR		0x06004
+#define VGAPD			0x06010
+#define VGAPD_0_P1_SHIFT		0
+#define VGAPD_0_P1_FORCE_DIV2		(1 << 5)
+#define VGAPD_0_P2_SHIFT		7
+#define VGAPD_1_P1_SHIFT		8
+#define VGAPD_1_P1_FORCE_DIV2		(1 << 13)
+#define VGAPD_1_P2_SHIFT		15
+
+#define DPLL_A			0x06014
+#define DPLL_B			0x06018
+#define DPLL_VCO_ENABLE			(1 << 31)
+#define DPLL_2X_CLOCK_ENABLE		(1 << 30)
+#define DPLL_SYNCLOCK_ENABLE		(1 << 29)
+#define DPLL_VGA_MODE_DISABLE		(1 << 28)
+#define DPLL_P2_MASK			1
+#define DPLL_P2_SHIFT			23
+#define DPLL_I9XX_P2_SHIFT              24
+#define DPLL_P1_FORCE_DIV2		(1 << 21)
+#define DPLL_P1_MASK			0x1f
+#define DPLL_P1_SHIFT			16
+#define DPLL_REFERENCE_SELECT_MASK	(0x3 << 13)
+#define DPLL_REFERENCE_DEFAULT		(0x0 << 13)
+#define DPLL_REFERENCE_TVCLK		(0x2 << 13)
+#define DPLL_RATE_SELECT_MASK		(1 << 8)
+#define DPLL_RATE_SELECT_FP0		(0 << 8)
+#define DPLL_RATE_SELECT_FP1		(1 << 8)
+
+#define FPA0			0x06040
+#define FPA1			0x06044
+#define FPB0			0x06048
+#define FPB1			0x0604c
+#define FP_DIVISOR_MASK			0x3f
+#define FP_N_DIVISOR_SHIFT		16
+#define FP_M1_DIVISOR_SHIFT		8
+#define FP_M2_DIVISOR_SHIFT		0
+
+/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
+/* Clock values are in units of kHz */
+#define PLL_REFCLK		48000
+#define MIN_CLOCK		25000
+#define MAX_CLOCK		350000
+
+/* Two pipes */
+#define PIPE_A			0
+#define PIPE_B			1
+#define PIPE_MASK		1
+
+/* palette registers */
+#define PALETTE_A		0x0a000
+#define PALETTE_B		0x0a800
+#ifndef PALETTE_8_ENTRIES
+#define PALETTE_8_ENTRIES		256
+#endif
+#define PALETTE_8_SIZE			(PALETTE_8_ENTRIES * 4)
+#define PALETTE_10_ENTRIES		128
+#define PALETTE_10_SIZE			(PALETTE_10_ENTRIES * 8)
+#define PALETTE_8_MASK			0xff
+#define PALETTE_8_RED_SHIFT		16
+#define PALETTE_8_GREEN_SHIFT		8
+#define PALETTE_8_BLUE_SHIFT		0
+
+/* CRTC registers */
+#define HTOTAL_A		0x60000
+#define HBLANK_A		0x60004
+#define HSYNC_A			0x60008
+#define VTOTAL_A		0x6000c
+#define VBLANK_A		0x60010
+#define VSYNC_A			0x60014
+#define SRC_SIZE_A		0x6001c
+#define BCLRPAT_A		0x60020
+
+#define HTOTAL_B		0x61000
+#define HBLANK_B		0x61004
+#define HSYNC_B			0x61008
+#define VTOTAL_B		0x6100c
+#define VBLANK_B		0x61010
+#define VSYNC_B			0x61014
+#define SRC_SIZE_B		0x6101c
+#define BCLRPAT_B		0x61020
+
+#define HTOTAL_MASK			0xfff
+#define HTOTAL_SHIFT			16
+#define HACTIVE_MASK			0x7ff
+#define HACTIVE_SHIFT			0
+#define HBLANKEND_MASK			0xfff
+#define HBLANKEND_SHIFT			16
+#define HBLANKSTART_MASK		0xfff
+#define HBLANKSTART_SHIFT		0
+#define HSYNCEND_MASK			0xfff
+#define HSYNCEND_SHIFT			16
+#define HSYNCSTART_MASK			0xfff
+#define HSYNCSTART_SHIFT		0
+#define VTOTAL_MASK			0xfff
+#define VTOTAL_SHIFT			16
+#define VACTIVE_MASK			0x7ff
+#define VACTIVE_SHIFT			0
+#define VBLANKEND_MASK			0xfff
+#define VBLANKEND_SHIFT			16
+#define VBLANKSTART_MASK		0xfff
+#define VBLANKSTART_SHIFT		0
+#define VSYNCEND_MASK			0xfff
+#define VSYNCEND_SHIFT			16
+#define VSYNCSTART_MASK			0xfff
+#define VSYNCSTART_SHIFT		0
+#define SRC_SIZE_HORIZ_MASK		0x7ff
+#define SRC_SIZE_HORIZ_SHIFT		16
+#define SRC_SIZE_VERT_MASK		0x7ff
+#define SRC_SIZE_VERT_SHIFT		0
+
+#define ADPA			0x61100
+#define ADPA_DAC_ENABLE			(1 << 31)
+#define ADPA_DAC_DISABLE		0
+#define ADPA_PIPE_SELECT_SHIFT		30
+#define ADPA_USE_VGA_HVPOLARITY		(1 << 15)
+#define ADPA_SETS_HVPOLARITY		0
+#define ADPA_DPMS_CONTROL_MASK		(0x3 << 10)
+#define ADPA_DPMS_D0			(0x0 << 10)
+#define ADPA_DPMS_D2			(0x1 << 10)
+#define ADPA_DPMS_D1			(0x2 << 10)
+#define ADPA_DPMS_D3			(0x3 << 10)
+#define ADPA_VSYNC_ACTIVE_SHIFT		4
+#define ADPA_HSYNC_ACTIVE_SHIFT		3
+#define ADPA_SYNC_ACTIVE_MASK		1
+#define ADPA_SYNC_ACTIVE_HIGH		1
+#define ADPA_SYNC_ACTIVE_LOW		0
+
+#define DVOA			0x61120
+#define DVOB			0x61140
+#define DVOC			0x61160
+#define LVDS			0x61180
+#define PORT_ENABLE		        (1 << 31)
+#define PORT_PIPE_SELECT_SHIFT	        30
+#define PORT_TV_FLAGS_MASK              0xFF
+#define PORT_TV_FLAGS                   0xC4	/* ripped from my BIOS
+						   to understand and correct */
+
+#define DVOA_SRCDIM		0x61124
+#define DVOB_SRCDIM		0x61144
+#define DVOC_SRCDIM		0x61164
+
+#define PIPEA_DSL		0x70000
+#define PIPEB_DSL		0x71000
+#define PIPEACONF		0x70008
+#define PIPEBCONF		0x71008
+#define PIPEASTAT		0x70024 /* bits 0-15 are "write 1 to clear" */
+#define PIPEBSTAT		0x71024
+
+#define PIPECONF_ENABLE			(1 << 31)
+#define PIPECONF_DISABLE		0
+#define PIPECONF_DOUBLE_WIDE		(1 << 30)
+#define PIPECONF_SINGLE_WIDE		0
+#define PIPECONF_LOCKED			(1 << 25)
+#define PIPECONF_UNLOCKED		0
+#define PIPECONF_GAMMA			(1 << 24)
+#define PIPECONF_PALETTE		0
+#define PIPECONF_PROGRESSIVE			(0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
+#define PIPECONF_INTERLACE_MASK			(7 << 21)
+
+/* enable bits, write 1 to enable */
+#define PIPESTAT_FIFO_UNDERRUN		(1 << 31)
+#define PIPESTAT_CRC_ERROR_EN		(1 << 29)
+#define PIPESTAT_CRC_DONE_EN		(1 << 28)
+#define PIPESTAT_HOTPLUG_EN		(1 << 26)
+#define PIPESTAT_VERTICAL_SYNC_EN	(1 << 25)
+#define PIPESTAT_DISPLINE_COMP_EN	(1 << 24)
+#define PIPESTAT_FLD_EVT_ODD_EN		(1 << 21)
+#define PIPESTAT_FLD_EVT_EVEN_EN	(1 << 20)
+#define PIPESTAT_TV_HOTPLUG_EN		(1 << 18)
+#define PIPESTAT_VBLANK_EN		(1 << 17)
+#define PIPESTAT_OVL_UPDATE_EN		(1 << 16)
+/* status bits, write 1 to clear */
+#define PIPESTAT_HOTPLUG_STATE		(1 << 15)
+#define PIPESTAT_CRC_ERROR		(1 << 13)
+#define PIPESTAT_CRC_DONE		(1 << 12)
+#define PIPESTAT_HOTPLUG		(1 << 10)
+#define PIPESTAT_VSYNC			(1 << 9)
+#define PIPESTAT_DISPLINE_COMP		(1 << 8)
+#define PIPESTAT_FLD_EVT_ODD		(1 << 5)
+#define PIPESTAT_FLD_EVT_EVEN		(1 << 4)
+#define PIPESTAT_TV_HOTPLUG		(1 << 2)
+#define PIPESTAT_VBLANK			(1 << 1)
+#define PIPESTAT_OVL_UPDATE		(1 << 0)
+
+#define DISPARB			0x70030
+#define DISPARB_AEND_MASK		0x1ff
+#define DISPARB_AEND_SHIFT		0
+#define DISPARB_BEND_MASK		0x3ff
+#define DISPARB_BEND_SHIFT		9
+
+/* Desktop HW cursor */
+#define CURSOR_CONTROL		0x70080
+#define CURSOR_ENABLE			(1 << 31)
+#define CURSOR_GAMMA_ENABLE		(1 << 30)
+#define CURSOR_STRIDE_MASK		(0x3 << 28)
+#define CURSOR_STRIDE_256		(0x0 << 28)
+#define CURSOR_STRIDE_512		(0x1 << 28)
+#define CURSOR_STRIDE_1K		(0x2 << 28)
+#define CURSOR_STRIDE_2K		(0x3 << 28)
+#define CURSOR_FORMAT_MASK		(0x7 << 24)
+#define CURSOR_FORMAT_2C		(0x0 << 24)
+#define CURSOR_FORMAT_3C		(0x1 << 24)
+#define CURSOR_FORMAT_4C		(0x2 << 24)
+#define CURSOR_FORMAT_ARGB		(0x4 << 24)
+#define CURSOR_FORMAT_XRGB		(0x5 << 24)
+
+/* Mobile HW cursor (and i810) */
+#define CURSOR_A_CONTROL	CURSOR_CONTROL
+#define CURSOR_B_CONTROL	0x700c0
+#define CURSOR_MODE_MASK		0x27
+#define CURSOR_MODE_DISABLE		0
+#define CURSOR_MODE_64_3C		0x04
+#define CURSOR_MODE_64_4C_AX		0x05
+#define CURSOR_MODE_64_4C		0x06
+#define CURSOR_MODE_64_32B_AX		0x07
+#define CURSOR_MODE_64_ARGB_AX		0x27
+#define CURSOR_PIPE_SELECT_SHIFT	28
+#define CURSOR_MOBILE_GAMMA_ENABLE	(1 << 26)
+#define CURSOR_MEM_TYPE_LOCAL		(1 << 25)
+
+/* All platforms (desktop has no pipe B) */
+#define CURSOR_A_BASEADDR	0x70084
+#define CURSOR_B_BASEADDR	0x700c4
+#define CURSOR_BASE_MASK		0xffffff00
+
+#define CURSOR_A_POSITION	0x70088
+#define CURSOR_B_POSITION	0x700c8
+#define CURSOR_POS_SIGN			(1 << 15)
+#define CURSOR_POS_MASK			0x7ff
+#define CURSOR_X_SHIFT			0
+#define CURSOR_Y_SHIFT			16
+
+#define CURSOR_A_PALETTE0	0x70090
+#define CURSOR_A_PALETTE1	0x70094
+#define CURSOR_A_PALETTE2	0x70098
+#define CURSOR_A_PALETTE3	0x7009c
+#define CURSOR_B_PALETTE0	0x700d0
+#define CURSOR_B_PALETTE1	0x700d4
+#define CURSOR_B_PALETTE2	0x700d8
+#define CURSOR_B_PALETTE3	0x700dc
+#define CURSOR_COLOR_MASK			0xff
+#define CURSOR_RED_SHIFT			16
+#define CURSOR_GREEN_SHIFT			8
+#define CURSOR_BLUE_SHIFT			0
+#define CURSOR_PALETTE_MASK			0xffffff
+
+/* Desktop only */
+#define CURSOR_SIZE		0x700a0
+#define CURSOR_SIZE_MASK		0x3ff
+#define CURSOR_SIZE_H_SHIFT		0
+#define CURSOR_SIZE_V_SHIFT		12
+
+#define DSPACNTR		0x70180
+#define DSPBCNTR		0x71180
+#define DISPPLANE_PLANE_ENABLE		(1 << 31)
+#define DISPPLANE_PLANE_DISABLE		0
+#define DISPPLANE_GAMMA_ENABLE		(1<<30)
+#define DISPPLANE_GAMMA_DISABLE		0
+#define DISPPLANE_PIXFORMAT_MASK	(0xf<<26)
+#define DISPPLANE_8BPP			(0x2<<26)
+#define DISPPLANE_15_16BPP		(0x4<<26)
+#define DISPPLANE_16BPP			(0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA	(0x6<<26)
+#define DISPPLANE_32BPP			(0x7<<26)
+#define DISPPLANE_STEREO_ENABLE		(1<<25)
+#define DISPPLANE_STEREO_DISABLE	0
+#define DISPPLANE_SEL_PIPE_SHIFT	24
+#define DISPPLANE_SRC_KEY_ENABLE	(1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE	0
+#define DISPPLANE_LINE_DOUBLE		(1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE	0
+#define DISPPLANE_STEREO_POLARITY_FIRST	0
+#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE	(1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE	0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA	0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY	1
+
+#define DSPABASE		0x70184
+#define DSPASTRIDE		0x70188
+
+#define DSPBBASE		0x71184
+#define DSPBSTRIDE		0x71188
+
+#define VGACNTRL		0x71400
+#define VGA_DISABLE			(1 << 31)
+#define VGA_ENABLE			0
+#define VGA_PIPE_SELECT_SHIFT		29
+#define VGA_PALETTE_READ_SELECT		23
+#define VGA_PALETTE_A_WRITE_DISABLE	(1 << 22)
+#define VGA_PALETTE_B_WRITE_DISABLE	(1 << 21)
+#define VGA_LEGACY_PALETTE		(1 << 20)
+#define VGA_6BIT_DAC			0
+#define VGA_8BIT_DAC			(1 << 20)
+
+#define ADD_ID			0x71408
+#define ADD_ID_MASK			0xff
+
+/* BIOS scratch area registers (830M and 845G). */
+#define SWF0			0x71410
+#define SWF1			0x71414
+#define SWF2			0x71418
+#define SWF3			0x7141c
+#define SWF4			0x71420
+#define SWF5			0x71424
+#define SWF6			0x71428
+
+/* BIOS scratch area registers (852GM, 855GM, 865G). */
+#define SWF00			0x70410
+#define SWF01			0x70414
+#define SWF02			0x70418
+#define SWF03			0x7041c
+#define SWF04			0x70420
+#define SWF05			0x70424
+#define SWF06			0x70428
+
+#define SWF10			SWF0
+#define SWF11			SWF1
+#define SWF12			SWF2
+#define SWF13			SWF3
+#define SWF14			SWF4
+#define SWF15			SWF5
+#define SWF16			SWF6
+
+#define SWF30			0x72414
+#define SWF31			0x72418
+#define SWF32			0x7241c
+
+/* Memory Commands */
+#define MI_NOOP			(0x00 << 23)
+#define MI_NOOP_WRITE_ID		(1 << 22)
+#define MI_NOOP_ID_MASK			((1 << 22) - 1)
+
+#define MI_FLUSH		(0x04 << 23)
+#define MI_WRITE_DIRTY_STATE		(1 << 4)
+#define MI_END_SCENE			(1 << 3)
+#define MI_INHIBIT_RENDER_CACHE_FLUSH	(1 << 2)
+#define MI_INVALIDATE_MAP_CACHE		(1 << 0)
+
+#define MI_STORE_DWORD_IMM	((0x20 << 23) | 1)
+
+/* 2D Commands */
+#define COLOR_BLT_CMD		((2 << 29) | (0x40 << 22) | 3)
+#define XY_COLOR_BLT_CMD	((2 << 29) | (0x50 << 22) | 4)
+#define XY_SETUP_CLIP_BLT_CMD	((2 << 29) | (0x03 << 22) | 1)
+#define XY_SRC_COPY_BLT_CMD	((2 << 29) | (0x53 << 22) | 6)
+#define SRC_COPY_BLT_CMD	((2 << 29) | (0x43 << 22) | 4)
+#define XY_MONO_PAT_BLT_CMD	((2 << 29) | (0x52 << 22) | 7)
+#define XY_MONO_SRC_BLT_CMD	((2 << 29) | (0x54 << 22) | 6)
+#define XY_MONO_SRC_IMM_BLT_CMD	((2 << 29) | (0x71 << 22) | 5)
+#define TXT_IMM_BLT_CMD	        ((2 << 29) | (0x30 << 22) | 2)
+#define SETUP_BLT_CMD	        ((2 << 29) | (0x00 << 22) | 6)
+
+#define DW_LENGTH_MASK			0xff
+
+#define WRITE_ALPHA			(1 << 21)
+#define WRITE_RGB			(1 << 20)
+#define VERT_SEED			(3 << 8)
+#define HORIZ_SEED			(3 << 12)
+
+#define COLOR_DEPTH_8			(0 << 24)
+#define COLOR_DEPTH_16			(1 << 24)
+#define COLOR_DEPTH_32			(3 << 24)
+
+#define SRC_ROP_GXCOPY			0xcc
+#define SRC_ROP_GXXOR			0x66
+
+#define PAT_ROP_GXCOPY                  0xf0
+#define PAT_ROP_GXXOR                   0x5a
+
+#define PITCH_SHIFT			0
+#define ROP_SHIFT			16
+#define WIDTH_SHIFT			0
+#define HEIGHT_SHIFT			16
+
+/* in bytes */
+#define MAX_MONO_IMM_SIZE		128
+
+
+/*** Macros ***/
+
+/* I/O macros */
+#define INREG8(addr)	      readb((u8 __iomem *)(dinfo->mmio_base + (addr)))
+#define INREG16(addr)	      readw((u16 __iomem *)(dinfo->mmio_base + (addr)))
+#define INREG(addr)	      readl((u32 __iomem *)(dinfo->mmio_base + (addr)))
+#define OUTREG8(addr, val)    writeb((val),(u8 __iomem *)(dinfo->mmio_base + \
+							   (addr)))
+#define OUTREG16(addr, val)    writew((val),(u16 __iomem *)(dinfo->mmio_base + \
+							   (addr)))
+#define OUTREG(addr, val)     writel((val),(u32 __iomem *)(dinfo->mmio_base + \
+                                     (addr)))
+
+/* Ring buffer macros */
+#define OUT_RING(n)	do {						\
+	writel((n), (u32 __iomem *)(dinfo->ring.virtual + dinfo->ring_tail));\
+	dinfo->ring_tail += 4;						\
+	dinfo->ring_tail &= dinfo->ring_tail_mask;			\
+} while (0)
+
+#define START_RING(n)	do {						\
+	if (dinfo->ring_space < (n) * 4)				\
+		wait_ring(dinfo,(n) * 4);				\
+	dinfo->ring_space -= (n) * 4;					\
+} while (0)
+
+#define ADVANCE_RING()	do {						\
+	OUTREG(PRI_RING_TAIL, dinfo->ring_tail);                        \
+} while (0)
+
+#define DO_RING_IDLE()	do {						\
+	u32 head, tail;							\
+	do {								\
+		head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;		\
+		tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;		\
+		udelay(10);						\
+	} while (head != tail);						\
+} while (0)
+
+
+/* function protoypes */
+extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo);
+extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
+				int *stolen_size);
+extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
+extern const char *intelfbhw_dvo_to_string(int dvo);
+extern int intelfbhw_validate_mode(struct intelfb_info *dinfo,
+				   struct fb_var_screeninfo *var);
+extern int intelfbhw_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info);
+extern void intelfbhw_do_blank(int blank, struct fb_info *info);
+extern void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
+				unsigned red, unsigned green, unsigned blue,
+				unsigned transp);
+extern int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
+				   struct intelfb_hwstate *hw, int flag);
+extern void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
+				     struct intelfb_hwstate *hw);
+extern int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
+				struct intelfb_hwstate *hw,
+				struct fb_var_screeninfo *var);
+extern int intelfbhw_program_mode(struct intelfb_info *dinfo,
+				  const struct intelfb_hwstate *hw, int blank);
+extern void intelfbhw_do_sync(struct intelfb_info *dinfo);
+extern void intelfbhw_2d_stop(struct intelfb_info *dinfo);
+extern void intelfbhw_2d_start(struct intelfb_info *dinfo);
+extern void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y,
+				  u32 w, u32 h, u32 color, u32 pitch, u32 bpp,
+				  u32 rop);
+extern void intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
+				u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch,
+				u32 bpp);
+extern int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg,
+				  u32 w, u32 h, const u8* cdat, u32 x, u32 y,
+				  u32 pitch, u32 bpp);
+extern void intelfbhw_cursor_init(struct intelfb_info *dinfo);
+extern void intelfbhw_cursor_hide(struct intelfb_info *dinfo);
+extern void intelfbhw_cursor_show(struct intelfb_info *dinfo);
+extern void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y);
+extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,
+				      u32 fg);
+extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width,
+				  int height, u8 *data);
+extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
+extern int intelfbhw_enable_irq(struct intelfb_info *dinfo);
+extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
+extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
+extern int intelfbhw_active_pipe(const struct intelfb_hwstate *hw);
+
+#endif /* _INTELFBHW_H */
diff --git a/drivers/video/fbdev/jz4740_fb.c b/drivers/video/fbdev/jz4740_fb.c
new file mode 100644
index 000000000000..87790e9644d0
--- /dev/null
+++ b/drivers/video/fbdev/jz4740_fb.c
@@ -0,0 +1,806 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *	JZ4740 SoC LCD framebuffer driver
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of  the GNU General Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <linux/console.h>
+#include <linux/fb.h>
+
+#include <linux/dma-mapping.h>
+
+#include <asm/mach-jz4740/jz4740_fb.h>
+#include <asm/mach-jz4740/gpio.h>
+
+#define JZ_REG_LCD_CFG		0x00
+#define JZ_REG_LCD_VSYNC	0x04
+#define JZ_REG_LCD_HSYNC	0x08
+#define JZ_REG_LCD_VAT		0x0C
+#define JZ_REG_LCD_DAH		0x10
+#define JZ_REG_LCD_DAV		0x14
+#define JZ_REG_LCD_PS		0x18
+#define JZ_REG_LCD_CLS		0x1C
+#define JZ_REG_LCD_SPL		0x20
+#define JZ_REG_LCD_REV		0x24
+#define JZ_REG_LCD_CTRL		0x30
+#define JZ_REG_LCD_STATE	0x34
+#define JZ_REG_LCD_IID		0x38
+#define JZ_REG_LCD_DA0		0x40
+#define JZ_REG_LCD_SA0		0x44
+#define JZ_REG_LCD_FID0		0x48
+#define JZ_REG_LCD_CMD0		0x4C
+#define JZ_REG_LCD_DA1		0x50
+#define JZ_REG_LCD_SA1		0x54
+#define JZ_REG_LCD_FID1		0x58
+#define JZ_REG_LCD_CMD1		0x5C
+
+#define JZ_LCD_CFG_SLCD			BIT(31)
+#define JZ_LCD_CFG_PS_DISABLE		BIT(23)
+#define JZ_LCD_CFG_CLS_DISABLE		BIT(22)
+#define JZ_LCD_CFG_SPL_DISABLE		BIT(21)
+#define JZ_LCD_CFG_REV_DISABLE		BIT(20)
+#define JZ_LCD_CFG_HSYNCM		BIT(19)
+#define JZ_LCD_CFG_PCLKM		BIT(18)
+#define JZ_LCD_CFG_INV			BIT(17)
+#define JZ_LCD_CFG_SYNC_DIR		BIT(16)
+#define JZ_LCD_CFG_PS_POLARITY		BIT(15)
+#define JZ_LCD_CFG_CLS_POLARITY		BIT(14)
+#define JZ_LCD_CFG_SPL_POLARITY		BIT(13)
+#define JZ_LCD_CFG_REV_POLARITY		BIT(12)
+#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW	BIT(11)
+#define JZ_LCD_CFG_PCLK_FALLING_EDGE	BIT(10)
+#define JZ_LCD_CFG_DE_ACTIVE_LOW	BIT(9)
+#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW	BIT(8)
+#define JZ_LCD_CFG_18_BIT		BIT(7)
+#define JZ_LCD_CFG_PDW			(BIT(5) | BIT(4))
+#define JZ_LCD_CFG_MODE_MASK 0xf
+
+#define JZ_LCD_CTRL_BURST_4		(0x0 << 28)
+#define JZ_LCD_CTRL_BURST_8		(0x1 << 28)
+#define JZ_LCD_CTRL_BURST_16		(0x2 << 28)
+#define JZ_LCD_CTRL_RGB555		BIT(27)
+#define JZ_LCD_CTRL_OFUP		BIT(26)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_16	(0x0 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_4	(0x1 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_2	(0x2 << 24)
+#define JZ_LCD_CTRL_PDD_MASK		(0xff << 16)
+#define JZ_LCD_CTRL_EOF_IRQ		BIT(13)
+#define JZ_LCD_CTRL_SOF_IRQ		BIT(12)
+#define JZ_LCD_CTRL_OFU_IRQ		BIT(11)
+#define JZ_LCD_CTRL_IFU0_IRQ		BIT(10)
+#define JZ_LCD_CTRL_IFU1_IRQ		BIT(9)
+#define JZ_LCD_CTRL_DD_IRQ		BIT(8)
+#define JZ_LCD_CTRL_QDD_IRQ		BIT(7)
+#define JZ_LCD_CTRL_REVERSE_ENDIAN	BIT(6)
+#define JZ_LCD_CTRL_LSB_FISRT		BIT(5)
+#define JZ_LCD_CTRL_DISABLE		BIT(4)
+#define JZ_LCD_CTRL_ENABLE		BIT(3)
+#define JZ_LCD_CTRL_BPP_1		0x0
+#define JZ_LCD_CTRL_BPP_2		0x1
+#define JZ_LCD_CTRL_BPP_4		0x2
+#define JZ_LCD_CTRL_BPP_8		0x3
+#define JZ_LCD_CTRL_BPP_15_16		0x4
+#define JZ_LCD_CTRL_BPP_18_24		0x5
+
+#define JZ_LCD_CMD_SOF_IRQ BIT(31)
+#define JZ_LCD_CMD_EOF_IRQ BIT(30)
+#define JZ_LCD_CMD_ENABLE_PAL BIT(28)
+
+#define JZ_LCD_SYNC_MASK 0x3ff
+
+#define JZ_LCD_STATE_DISABLED BIT(0)
+
+struct jzfb_framedesc {
+	uint32_t next;
+	uint32_t addr;
+	uint32_t id;
+	uint32_t cmd;
+} __packed;
+
+struct jzfb {
+	struct fb_info *fb;
+	struct platform_device *pdev;
+	void __iomem *base;
+	struct resource *mem;
+	struct jz4740_fb_platform_data *pdata;
+
+	size_t vidmem_size;
+	void *vidmem;
+	dma_addr_t vidmem_phys;
+	struct jzfb_framedesc *framedesc;
+	dma_addr_t framedesc_phys;
+
+	struct clk *ldclk;
+	struct clk *lpclk;
+
+	unsigned is_enabled:1;
+	struct mutex lock;
+
+	uint32_t pseudo_palette[16];
+};
+
+static const struct fb_fix_screeninfo jzfb_fix = {
+	.id		= "JZ4740 FB",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
+	JZ_GPIO_BULK_PIN(LCD_PCLK),
+	JZ_GPIO_BULK_PIN(LCD_HSYNC),
+	JZ_GPIO_BULK_PIN(LCD_VSYNC),
+	JZ_GPIO_BULK_PIN(LCD_DE),
+	JZ_GPIO_BULK_PIN(LCD_PS),
+	JZ_GPIO_BULK_PIN(LCD_REV),
+	JZ_GPIO_BULK_PIN(LCD_CLS),
+	JZ_GPIO_BULK_PIN(LCD_SPL),
+};
+
+static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
+	JZ_GPIO_BULK_PIN(LCD_DATA0),
+	JZ_GPIO_BULK_PIN(LCD_DATA1),
+	JZ_GPIO_BULK_PIN(LCD_DATA2),
+	JZ_GPIO_BULK_PIN(LCD_DATA3),
+	JZ_GPIO_BULK_PIN(LCD_DATA4),
+	JZ_GPIO_BULK_PIN(LCD_DATA5),
+	JZ_GPIO_BULK_PIN(LCD_DATA6),
+	JZ_GPIO_BULK_PIN(LCD_DATA7),
+	JZ_GPIO_BULK_PIN(LCD_DATA8),
+	JZ_GPIO_BULK_PIN(LCD_DATA9),
+	JZ_GPIO_BULK_PIN(LCD_DATA10),
+	JZ_GPIO_BULK_PIN(LCD_DATA11),
+	JZ_GPIO_BULK_PIN(LCD_DATA12),
+	JZ_GPIO_BULK_PIN(LCD_DATA13),
+	JZ_GPIO_BULK_PIN(LCD_DATA14),
+	JZ_GPIO_BULK_PIN(LCD_DATA15),
+	JZ_GPIO_BULK_PIN(LCD_DATA16),
+	JZ_GPIO_BULK_PIN(LCD_DATA17),
+};
+
+static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
+{
+	unsigned int num;
+
+	switch (jzfb->pdata->lcd_type) {
+	case JZ_LCD_TYPE_GENERIC_16_BIT:
+		num = 4;
+		break;
+	case JZ_LCD_TYPE_GENERIC_18_BIT:
+		num = 4;
+		break;
+	case JZ_LCD_TYPE_8BIT_SERIAL:
+		num = 3;
+		break;
+	case JZ_LCD_TYPE_SPECIAL_TFT_1:
+	case JZ_LCD_TYPE_SPECIAL_TFT_2:
+	case JZ_LCD_TYPE_SPECIAL_TFT_3:
+		num = 8;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+	return num;
+}
+
+static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
+{
+	unsigned int num;
+
+	switch (jzfb->pdata->lcd_type) {
+	case JZ_LCD_TYPE_GENERIC_16_BIT:
+		num = 16;
+		break;
+	case JZ_LCD_TYPE_GENERIC_18_BIT:
+		num = 18;
+		break;
+	case JZ_LCD_TYPE_8BIT_SERIAL:
+		num = 8;
+		break;
+	case JZ_LCD_TYPE_SPECIAL_TFT_1:
+	case JZ_LCD_TYPE_SPECIAL_TFT_2:
+	case JZ_LCD_TYPE_SPECIAL_TFT_3:
+		if (jzfb->pdata->bpp == 18)
+			num = 18;
+		else
+			num = 16;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+	return num;
+}
+
+/* Based on CNVT_TOHW macro from skeletonfb.c */
+static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
+	struct fb_bitfield *bf)
+{
+	return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset;
+}
+
+static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			unsigned blue, unsigned transp, struct fb_info *fb)
+{
+	uint32_t color;
+
+	if (regno >= 16)
+		return -EINVAL;
+
+	color = jzfb_convert_color_to_hw(red, &fb->var.red);
+	color |= jzfb_convert_color_to_hw(green, &fb->var.green);
+	color |= jzfb_convert_color_to_hw(blue, &fb->var.blue);
+	color |= jzfb_convert_color_to_hw(transp, &fb->var.transp);
+
+	((uint32_t *)(fb->pseudo_palette))[regno] = color;
+
+	return 0;
+}
+
+static int jzfb_get_controller_bpp(struct jzfb *jzfb)
+{
+	switch (jzfb->pdata->bpp) {
+	case 18:
+	case 24:
+		return 32;
+	case 15:
+		return 16;
+	default:
+		return jzfb->pdata->bpp;
+	}
+}
+
+static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb,
+	struct fb_var_screeninfo *var)
+{
+	size_t i;
+	struct fb_videomode *mode = jzfb->pdata->modes;
+
+	for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
+		if (mode->xres == var->xres && mode->yres == var->yres)
+			return mode;
+	}
+
+	return NULL;
+}
+
+static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
+{
+	struct jzfb *jzfb = fb->par;
+	struct fb_videomode *mode;
+
+	if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
+		var->bits_per_pixel != jzfb->pdata->bpp)
+		return -EINVAL;
+
+	mode = jzfb_get_mode(jzfb, var);
+	if (mode == NULL)
+		return -EINVAL;
+
+	fb_videomode_to_var(var, mode);
+
+	switch (jzfb->pdata->bpp) {
+	case 8:
+		break;
+	case 15:
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->green.offset = 6;
+		var->green.length = 5;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+	case 18:
+		var->red.offset = 16;
+		var->red.length = 6;
+		var->green.offset = 8;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 6;
+		var->bits_per_pixel = 32;
+		break;
+	case 32:
+	case 24:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->bits_per_pixel = 32;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int jzfb_set_par(struct fb_info *info)
+{
+	struct jzfb *jzfb = info->par;
+	struct jz4740_fb_platform_data *pdata = jzfb->pdata;
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_videomode *mode;
+	uint16_t hds, vds;
+	uint16_t hde, vde;
+	uint16_t ht, vt;
+	uint32_t ctrl;
+	uint32_t cfg;
+	unsigned long rate;
+
+	mode = jzfb_get_mode(jzfb, var);
+	if (mode == NULL)
+		return -EINVAL;
+
+	if (mode == info->mode)
+		return 0;
+
+	info->mode = mode;
+
+	hds = mode->hsync_len + mode->left_margin;
+	hde = hds + mode->xres;
+	ht = hde + mode->right_margin;
+
+	vds = mode->vsync_len + mode->upper_margin;
+	vde = vds + mode->yres;
+	vt = vde + mode->lower_margin;
+
+	ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
+
+	switch (pdata->bpp) {
+	case 1:
+		ctrl |= JZ_LCD_CTRL_BPP_1;
+		break;
+	case 2:
+		ctrl |= JZ_LCD_CTRL_BPP_2;
+		break;
+	case 4:
+		ctrl |= JZ_LCD_CTRL_BPP_4;
+		break;
+	case 8:
+		ctrl |= JZ_LCD_CTRL_BPP_8;
+	break;
+	case 15:
+		ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
+	case 16:
+		ctrl |= JZ_LCD_CTRL_BPP_15_16;
+		break;
+	case 18:
+	case 24:
+	case 32:
+		ctrl |= JZ_LCD_CTRL_BPP_18_24;
+		break;
+	default:
+		break;
+	}
+
+	cfg = pdata->lcd_type & 0xf;
+
+	if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
+		cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
+
+	if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
+		cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
+
+	if (pdata->pixclk_falling_edge)
+		cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
+
+	if (pdata->date_enable_active_low)
+		cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
+
+	if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
+		cfg |= JZ_LCD_CFG_18_BIT;
+
+	if (mode->pixclock) {
+		rate = PICOS2KHZ(mode->pixclock) * 1000;
+		mode->refresh = rate / vt / ht;
+	} else {
+		if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
+			rate = mode->refresh * (vt + 2 * mode->xres) * ht;
+		else
+			rate = mode->refresh * vt * ht;
+
+		mode->pixclock = KHZ2PICOS(rate / 1000);
+	}
+
+	mutex_lock(&jzfb->lock);
+	if (!jzfb->is_enabled)
+		clk_enable(jzfb->ldclk);
+	else
+		ctrl |= JZ_LCD_CTRL_ENABLE;
+
+	switch (pdata->lcd_type) {
+	case JZ_LCD_TYPE_SPECIAL_TFT_1:
+	case JZ_LCD_TYPE_SPECIAL_TFT_2:
+	case JZ_LCD_TYPE_SPECIAL_TFT_3:
+		writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL);
+		writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS);
+		writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS);
+		writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV);
+		break;
+	default:
+		cfg |= JZ_LCD_CFG_PS_DISABLE;
+		cfg |= JZ_LCD_CFG_CLS_DISABLE;
+		cfg |= JZ_LCD_CFG_SPL_DISABLE;
+		cfg |= JZ_LCD_CFG_REV_DISABLE;
+		break;
+	}
+
+	writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
+	writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
+
+	writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
+
+	writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
+	writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
+
+	writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
+
+	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
+
+	if (!jzfb->is_enabled)
+		clk_disable_unprepare(jzfb->ldclk);
+
+	mutex_unlock(&jzfb->lock);
+
+	clk_set_rate(jzfb->lpclk, rate);
+	clk_set_rate(jzfb->ldclk, rate * 3);
+
+	return 0;
+}
+
+static void jzfb_enable(struct jzfb *jzfb)
+{
+	uint32_t ctrl;
+
+	clk_prepare_enable(jzfb->ldclk);
+
+	jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	writel(0, jzfb->base + JZ_REG_LCD_STATE);
+
+	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
+
+	ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
+	ctrl |= JZ_LCD_CTRL_ENABLE;
+	ctrl &= ~JZ_LCD_CTRL_DISABLE;
+	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
+}
+
+static void jzfb_disable(struct jzfb *jzfb)
+{
+	uint32_t ctrl;
+
+	ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
+	ctrl |= JZ_LCD_CTRL_DISABLE;
+	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
+	do {
+		ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
+	} while (!(ctrl & JZ_LCD_STATE_DISABLED));
+
+	jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	clk_disable_unprepare(jzfb->ldclk);
+}
+
+static int jzfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct jzfb *jzfb = info->par;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		mutex_lock(&jzfb->lock);
+		if (jzfb->is_enabled) {
+			mutex_unlock(&jzfb->lock);
+			return 0;
+		}
+
+		jzfb_enable(jzfb);
+		jzfb->is_enabled = 1;
+
+		mutex_unlock(&jzfb->lock);
+		break;
+	default:
+		mutex_lock(&jzfb->lock);
+		if (!jzfb->is_enabled) {
+			mutex_unlock(&jzfb->lock);
+			return 0;
+		}
+
+		jzfb_disable(jzfb);
+		jzfb->is_enabled = 0;
+
+		mutex_unlock(&jzfb->lock);
+		break;
+	}
+
+	return 0;
+}
+
+static int jzfb_alloc_devmem(struct jzfb *jzfb)
+{
+	int max_videosize = 0;
+	struct fb_videomode *mode = jzfb->pdata->modes;
+	void *page;
+	int i;
+
+	for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
+		if (max_videosize < mode->xres * mode->yres)
+			max_videosize = mode->xres * mode->yres;
+	}
+
+	max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
+
+	jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
+					sizeof(*jzfb->framedesc),
+					&jzfb->framedesc_phys, GFP_KERNEL);
+
+	if (!jzfb->framedesc)
+		return -ENOMEM;
+
+	jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
+	jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
+					jzfb->vidmem_size,
+					&jzfb->vidmem_phys, GFP_KERNEL);
+
+	if (!jzfb->vidmem)
+		goto err_free_framedesc;
+
+	for (page = jzfb->vidmem;
+		 page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
+		 page += PAGE_SIZE) {
+		SetPageReserved(virt_to_page(page));
+	}
+
+	jzfb->framedesc->next = jzfb->framedesc_phys;
+	jzfb->framedesc->addr = jzfb->vidmem_phys;
+	jzfb->framedesc->id = 0xdeafbead;
+	jzfb->framedesc->cmd = 0;
+	jzfb->framedesc->cmd |= max_videosize / 4;
+
+	return 0;
+
+err_free_framedesc:
+	dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
+				jzfb->framedesc, jzfb->framedesc_phys);
+	return -ENOMEM;
+}
+
+static void jzfb_free_devmem(struct jzfb *jzfb)
+{
+	dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
+				jzfb->vidmem, jzfb->vidmem_phys);
+	dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
+				jzfb->framedesc, jzfb->framedesc_phys);
+}
+
+static struct  fb_ops jzfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = jzfb_check_var,
+	.fb_set_par = jzfb_set_par,
+	.fb_blank = jzfb_blank,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_setcolreg = jzfb_setcolreg,
+};
+
+static int jzfb_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jzfb *jzfb;
+	struct fb_info *fb;
+	struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *mem;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Missing platform data\n");
+		return -ENXIO;
+	}
+
+	fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
+	if (!fb) {
+		dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
+		return -ENOMEM;
+	}
+
+	fb->fbops = &jzfb_ops;
+	fb->flags = FBINFO_DEFAULT;
+
+	jzfb = fb->par;
+	jzfb->pdev = pdev;
+	jzfb->pdata = pdata;
+
+	jzfb->ldclk = devm_clk_get(&pdev->dev, "lcd");
+	if (IS_ERR(jzfb->ldclk)) {
+		ret = PTR_ERR(jzfb->ldclk);
+		dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
+		goto err_framebuffer_release;
+	}
+
+	jzfb->lpclk = devm_clk_get(&pdev->dev, "lcd_pclk");
+	if (IS_ERR(jzfb->lpclk)) {
+		ret = PTR_ERR(jzfb->lpclk);
+		dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
+		goto err_framebuffer_release;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	jzfb->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(jzfb->base)) {
+		ret = PTR_ERR(jzfb->base);
+		goto err_framebuffer_release;
+	}
+
+	platform_set_drvdata(pdev, jzfb);
+
+	mutex_init(&jzfb->lock);
+
+	fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
+				 &fb->modelist);
+	fb_videomode_to_var(&fb->var, pdata->modes);
+	fb->var.bits_per_pixel = pdata->bpp;
+	jzfb_check_var(&fb->var, fb);
+
+	ret = jzfb_alloc_devmem(jzfb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to allocate video memory\n");
+		goto err_framebuffer_release;
+	}
+
+	fb->fix = jzfb_fix;
+	fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
+	fb->fix.mmio_start = mem->start;
+	fb->fix.mmio_len = resource_size(mem);
+	fb->fix.smem_start = jzfb->vidmem_phys;
+	fb->fix.smem_len =  fb->fix.line_length * fb->var.yres;
+	fb->screen_base = jzfb->vidmem;
+	fb->pseudo_palette = jzfb->pseudo_palette;
+
+	fb_alloc_cmap(&fb->cmap, 256, 0);
+
+	clk_prepare_enable(jzfb->ldclk);
+	jzfb->is_enabled = 1;
+
+	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
+
+	fb->mode = NULL;
+	jzfb_set_par(fb);
+
+	jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	ret = register_framebuffer(fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
+		goto err_free_devmem;
+	}
+
+	jzfb->fb = fb;
+
+	return 0;
+
+err_free_devmem:
+	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	fb_dealloc_cmap(&fb->cmap);
+	jzfb_free_devmem(jzfb);
+err_framebuffer_release:
+	framebuffer_release(fb);
+	return ret;
+}
+
+static int jzfb_remove(struct platform_device *pdev)
+{
+	struct jzfb *jzfb = platform_get_drvdata(pdev);
+
+	jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
+
+	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	fb_dealloc_cmap(&jzfb->fb->cmap);
+	jzfb_free_devmem(jzfb);
+
+	framebuffer_release(jzfb->fb);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int jzfb_suspend(struct device *dev)
+{
+	struct jzfb *jzfb = dev_get_drvdata(dev);
+
+	console_lock();
+	fb_set_suspend(jzfb->fb, 1);
+	console_unlock();
+
+	mutex_lock(&jzfb->lock);
+	if (jzfb->is_enabled)
+		jzfb_disable(jzfb);
+	mutex_unlock(&jzfb->lock);
+
+	return 0;
+}
+
+static int jzfb_resume(struct device *dev)
+{
+	struct jzfb *jzfb = dev_get_drvdata(dev);
+	clk_prepare_enable(jzfb->ldclk);
+
+	mutex_lock(&jzfb->lock);
+	if (jzfb->is_enabled)
+		jzfb_enable(jzfb);
+	mutex_unlock(&jzfb->lock);
+
+	console_lock();
+	fb_set_suspend(jzfb->fb, 0);
+	console_unlock();
+
+	return 0;
+}
+
+static const struct dev_pm_ops jzfb_pm_ops = {
+	.suspend	= jzfb_suspend,
+	.resume		= jzfb_resume,
+	.poweroff	= jzfb_suspend,
+	.restore	= jzfb_resume,
+};
+
+#define JZFB_PM_OPS (&jzfb_pm_ops)
+
+#else
+#define JZFB_PM_OPS NULL
+#endif
+
+static struct platform_driver jzfb_driver = {
+	.probe = jzfb_probe,
+	.remove = jzfb_remove,
+	.driver = {
+		.name = "jz4740-fb",
+		.pm = JZFB_PM_OPS,
+	},
+};
+module_platform_driver(jzfb_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver");
+MODULE_ALIAS("platform:jz4740-fb");
diff --git a/drivers/video/fbdev/kyro/Makefile b/drivers/video/fbdev/kyro/Makefile
new file mode 100644
index 000000000000..2fd66f551bae
--- /dev/null
+++ b/drivers/video/fbdev/kyro/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Kyro framebuffer driver
+#
+
+obj-$(CONFIG_FB_KYRO)	+= kyrofb.o
+
+kyrofb-objs	:= STG4000Ramdac.o STG4000VTG.o STG4000OverlayDevice.o \
+		   STG4000InitDevice.o fbdev.o
diff --git a/drivers/video/fbdev/kyro/STG4000InitDevice.c b/drivers/video/fbdev/kyro/STG4000InitDevice.c
new file mode 100644
index 000000000000..1d3f2080aa6f
--- /dev/null
+++ b/drivers/video/fbdev/kyro/STG4000InitDevice.c
@@ -0,0 +1,326 @@
+/*
+ *  linux/drivers/video/kyro/STG4000InitDevice.c
+ *
+ *  Copyright (C) 2000 Imagination Technologies Ltd
+ *  Copyright (C) 2002 STMicroelectronics
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include "STG4000Reg.h"
+#include "STG4000Interface.h"
+
+/* SDRAM fixed settings */
+#define SDRAM_CFG_0   0x49A1
+#define SDRAM_CFG_1   0xA732
+#define SDRAM_CFG_2   0x31
+#define SDRAM_ARB_CFG 0xA0
+#define SDRAM_REFRESH 0x20
+
+/* Reset values */
+#define PMX2_SOFTRESET_DAC_RST		0x0001
+#define PMX2_SOFTRESET_C1_RST		0x0004
+#define PMX2_SOFTRESET_C2_RST		0x0008
+#define PMX2_SOFTRESET_3D_RST		0x0010
+#define PMX2_SOFTRESET_VIDIN_RST	0x0020
+#define PMX2_SOFTRESET_TLB_RST		0x0040
+#define PMX2_SOFTRESET_SD_RST		0x0080
+#define PMX2_SOFTRESET_VGA_RST		0x0100
+#define PMX2_SOFTRESET_ROM_RST		0x0200	/* reserved bit, do not reset */
+#define PMX2_SOFTRESET_TA_RST		0x0400
+#define PMX2_SOFTRESET_REG_RST		0x4000
+#define PMX2_SOFTRESET_ALL		0x7fff
+
+/* Core clock freq */
+#define CORE_PLL_FREQ 1000000
+
+/* Reference Clock freq */
+#define REF_FREQ 14318
+
+/* PCI Registers */
+static u16 CorePllControl = 0x70;
+
+#define	PCI_CONFIG_SUBSYS_ID	0x2e
+
+/* Misc */
+#define CORE_PLL_MODE_REG_0_7      3
+#define CORE_PLL_MODE_REG_8_15     2
+#define CORE_PLL_MODE_CONFIG_REG   1
+#define DAC_PLL_CONFIG_REG         0
+
+#define STG_MAX_VCO 500000
+#define STG_MIN_VCO 100000
+
+/* PLL Clock */
+#define    STG4K3_PLL_SCALER      8	/* scale numbers by 2^8 for fixed point calc */
+#define    STG4K3_PLL_MIN_R       2	/* Minimum multiplier */
+#define    STG4K3_PLL_MAX_R       33	/* Max */
+#define    STG4K3_PLL_MIN_F       2	/* Minimum divisor */
+#define    STG4K3_PLL_MAX_F       513	/* Max */
+#define    STG4K3_PLL_MIN_OD      0	/* Min output divider (shift) */
+#define    STG4K3_PLL_MAX_OD      2	/* Max */
+#define    STG4K3_PLL_MIN_VCO_SC  (100000000 >> STG4K3_PLL_SCALER)	/* Min VCO rate */
+#define    STG4K3_PLL_MAX_VCO_SC  (500000000 >> STG4K3_PLL_SCALER)	/* Max VCO rate */
+#define    STG4K3_PLL_MINR_VCO_SC (100000000 >> STG4K3_PLL_SCALER)	/* Min VCO rate (restricted) */
+#define    STG4K3_PLL_MAXR_VCO_SC (500000000 >> STG4K3_PLL_SCALER)	/* Max VCO rate (restricted) */
+#define    STG4K3_PLL_MINR_VCO    100000000	/* Min VCO rate (restricted) */
+#define    STG4K3_PLL_MAX_VCO     500000000	/* Max VCO rate */
+#define    STG4K3_PLL_MAXR_VCO    500000000	/* Max VCO rate (restricted) */
+
+#define OS_DELAY(X) \
+{ \
+volatile u32 i,count=0; \
+    for(i=0;i<X;i++) count++; \
+}
+
+static u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg,
+			      u32 dwSubSysID, u32 dwRevID)
+{
+	u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
+	u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
+	u32 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
+	u32 adwSDRAMRsh[] = { 36, 39, 40 };
+	u32 adwChipSpeed[] = { 110, 120, 125 };
+	u32 dwMemTypeIdx;
+	u32 dwChipSpeedIdx;
+
+	/* Get memory tpye and chip speed indexs from the SubSysDevID */
+	dwMemTypeIdx = (dwSubSysID & 0x70) >> 4;
+	dwChipSpeedIdx = (dwSubSysID & 0x180) >> 7;
+
+	if (dwMemTypeIdx > 4 || dwChipSpeedIdx > 2)
+		return 0;
+
+	/* Program SD-RAM interface */
+	STG_WRITE_REG(SDRAMArbiterConf, adwSDRAMArgCfg0[dwMemTypeIdx]);
+	if (dwRevID < 5) {
+		STG_WRITE_REG(SDRAMConf0, 0x49A1);
+		STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg1[dwMemTypeIdx]);
+	} else {
+		STG_WRITE_REG(SDRAMConf0, 0x4DF1);
+		STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg2[dwMemTypeIdx]);
+	}
+
+	STG_WRITE_REG(SDRAMConf2, 0x31);
+	STG_WRITE_REG(SDRAMRefresh, adwSDRAMRsh[dwChipSpeedIdx]);
+
+	return adwChipSpeed[dwChipSpeedIdx] * 10000;
+}
+
+u32 ProgramClock(u32 refClock,
+		   u32 coreClock,
+		   u32 * FOut, u32 * ROut, u32 * POut)
+{
+	u32 R = 0, F = 0, OD = 0, ODIndex = 0;
+	u32 ulBestR = 0, ulBestF = 0, ulBestOD = 0;
+	u32 ulBestVCO = 0, ulBestClk = 0, ulBestScore = 0;
+	u32 ulScore, ulPhaseScore, ulVcoScore;
+	u32 ulTmp = 0, ulVCO;
+	u32 ulScaleClockReq, ulMinClock, ulMaxClock;
+	u32 ODValues[] = { 1, 2, 0 };
+
+	/* Translate clock in Hz */
+	coreClock *= 100;	/* in Hz */
+	refClock *= 1000;	/* in Hz */
+
+	/* Work out acceptable clock
+	 * The method calculates ~ +- 0.4% (1/256)
+	 */
+	ulMinClock = coreClock - (coreClock >> 8);
+	ulMaxClock = coreClock + (coreClock >> 8);
+
+	/* Scale clock required for use in calculations */
+	ulScaleClockReq = coreClock >> STG4K3_PLL_SCALER;
+
+	/* Iterate through post divider values */
+	for (ODIndex = 0; ODIndex < 3; ODIndex++) {
+		OD = ODValues[ODIndex];
+		R = STG4K3_PLL_MIN_R;
+
+		/* loop for pre-divider from min to max  */
+		while (R <= STG4K3_PLL_MAX_R) {
+			/* estimate required feedback multiplier */
+			ulTmp = R * (ulScaleClockReq << OD);
+
+			/* F = ClkRequired * R * (2^OD) / Fref */
+			F = (u32)(ulTmp / (refClock >> STG4K3_PLL_SCALER));
+
+			/* compensate for accuracy */
+			if (F > STG4K3_PLL_MIN_F)
+				F--;
+
+
+			/*
+			 * We should be close to our target frequency (if it's
+			 * achievable with current OD & R) let's iterate
+			 * through F for best fit
+			 */
+			while ((F >= STG4K3_PLL_MIN_F) &&
+			       (F <= STG4K3_PLL_MAX_F)) {
+				/* Calc VCO at full accuracy */
+				ulVCO = refClock / R;
+				ulVCO = F * ulVCO;
+
+				/*
+				 * Check it's within restricted VCO range
+				 * unless of course the desired frequency is
+				 * above the restricted range, then test
+				 * against VCO limit
+				 */
+				if ((ulVCO >= STG4K3_PLL_MINR_VCO) &&
+				    ((ulVCO <= STG4K3_PLL_MAXR_VCO) ||
+				     ((coreClock > STG4K3_PLL_MAXR_VCO)
+				      && (ulVCO <= STG4K3_PLL_MAX_VCO)))) {
+					ulTmp = (ulVCO >> OD);	/* Clock = VCO / (2^OD) */
+
+					/* Is this clock good enough? */
+					if ((ulTmp >= ulMinClock)
+					    && (ulTmp <= ulMaxClock)) {
+						ulPhaseScore = (((refClock / R) - (refClock / STG4K3_PLL_MAX_R))) / ((refClock - (refClock / STG4K3_PLL_MAX_R)) >> 10);
+
+						ulVcoScore = ((ulVCO - STG4K3_PLL_MINR_VCO)) / ((STG4K3_PLL_MAXR_VCO - STG4K3_PLL_MINR_VCO) >> 10);
+						ulScore = ulPhaseScore + ulVcoScore;
+
+						if (!ulBestScore) {
+							ulBestVCO = ulVCO;
+							ulBestOD = OD;
+							ulBestF = F;
+							ulBestR = R;
+							ulBestClk = ulTmp;
+							ulBestScore =
+							    ulScore;
+						}
+						/* is this better, ( aim for highest Score) */
+			/*--------------------------------------------------------------------------
+                             Here we want to use a scoring system which will take account of both the
+                            value at the phase comparater and the VCO output
+                             to do this we will use a cumulative score between the two
+                          The way this ends up is that we choose the first value in the loop anyway
+                          but we shall keep this code in case new restrictions come into play
+                          --------------------------------------------------------------------------*/
+						if ((ulScore >= ulBestScore) && (OD > 0)) {
+							ulBestVCO = ulVCO;
+							ulBestOD = OD;
+							ulBestF = F;
+							ulBestR = R;
+							ulBestClk = ulTmp;
+							ulBestScore =
+							    ulScore;
+						}
+					}
+				}
+				F++;
+			}
+			R++;
+		}
+	}
+
+	/*
+	   did we find anything?
+	   Then return RFOD
+	 */
+	if (ulBestScore) {
+		*ROut = ulBestR;
+		*FOut = ulBestF;
+
+		if ((ulBestOD == 2) || (ulBestOD == 3)) {
+			*POut = 3;
+		} else
+			*POut = ulBestOD;
+
+	}
+
+	return (ulBestClk);
+}
+
+int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev)
+{
+	u32 F, R, P;
+	u16 core_pll = 0, sub;
+	u32 ulCoreClock;
+	u32 tmp;
+	u32 ulChipSpeed;
+
+	STG_WRITE_REG(IntMask, 0xFFFF);
+
+	/* Disable Primary Core Thread0 */
+	tmp = STG_READ_REG(Thread0Enable);
+	CLEAR_BIT(0);
+	STG_WRITE_REG(Thread0Enable, tmp);
+
+	/* Disable Primary Core Thread1 */
+	tmp = STG_READ_REG(Thread1Enable);
+	CLEAR_BIT(0);
+	STG_WRITE_REG(Thread1Enable, tmp);
+
+	STG_WRITE_REG(SoftwareReset,
+		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
+	STG_WRITE_REG(SoftwareReset,
+		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
+		      PMX2_SOFTRESET_ROM_RST);
+
+	/* Need to play around to reset TA */
+	STG_WRITE_REG(TAConfiguration, 0);
+	STG_WRITE_REG(SoftwareReset,
+		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
+	STG_WRITE_REG(SoftwareReset,
+		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
+		      PMX2_SOFTRESET_ROM_RST);
+
+	pci_read_config_word(pDev, PCI_CONFIG_SUBSYS_ID, &sub);
+
+	ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub,
+		                         (u32)pDev->revision);
+
+	if (ulChipSpeed == 0)
+		return -EINVAL;
+
+	ulCoreClock = ProgramClock(REF_FREQ, CORE_PLL_FREQ, &F, &R, &P);
+
+	core_pll |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
+
+	/* Set Core PLL Control to Core PLL Mode  */
+
+	/* Send bits 0:7 of the Core PLL Mode register */
+	tmp = ((CORE_PLL_MODE_REG_0_7 << 8) | (core_pll & 0x00FF));
+	pci_write_config_word(pDev, CorePllControl, tmp);
+	/* Without some delay between the PCI config writes the clock does
+	   not reliably set when the code is compiled -O3
+	 */
+	OS_DELAY(1000000);
+
+	tmp |= SET_BIT(14);
+	pci_write_config_word(pDev, CorePllControl, tmp);
+	OS_DELAY(1000000);
+
+	/* Send bits 8:15 of the Core PLL Mode register */
+	tmp =
+	    ((CORE_PLL_MODE_REG_8_15 << 8) | ((core_pll & 0xFF00) >> 8));
+	pci_write_config_word(pDev, CorePllControl, tmp);
+	OS_DELAY(1000000);
+
+	tmp |= SET_BIT(14);
+	pci_write_config_word(pDev, CorePllControl, tmp);
+	OS_DELAY(1000000);
+
+	STG_WRITE_REG(SoftwareReset, PMX2_SOFTRESET_ALL);
+
+#if 0
+	/* Enable Primary Core Thread0 */
+	tmp = ((STG_READ_REG(Thread0Enable)) | SET_BIT(0));
+	STG_WRITE_REG(Thread0Enable, tmp);
+
+	/* Enable Primary Core Thread1 */
+	tmp = ((STG_READ_REG(Thread1Enable)) | SET_BIT(0));
+	STG_WRITE_REG(Thread1Enable, tmp);
+#endif
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/kyro/STG4000Interface.h b/drivers/video/fbdev/kyro/STG4000Interface.h
new file mode 100644
index 000000000000..b7c83d5dfb13
--- /dev/null
+++ b/drivers/video/fbdev/kyro/STG4000Interface.h
@@ -0,0 +1,61 @@
+/*
+ *  linux/drivers/video/kyro/STG4000Interface.h
+ *
+ *  Copyright (C) 2002 STMicroelectronics
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _STG4000INTERFACE_H
+#define _STG4000INTERFACE_H
+
+#include <linux/pci.h>
+#include <video/kyro.h>
+
+/*
+ * Ramdac Setup
+ */
+extern int InitialiseRamdac(volatile STG4000REG __iomem *pSTGReg, u32 displayDepth,
+			    u32 displayWidth, u32 displayHeight,
+			    s32 HSyncPolarity, s32 VSyncPolarity,
+			    u32 *pixelClock);
+
+extern void DisableRamdacOutput(volatile STG4000REG __iomem *pSTGReg);
+extern void EnableRamdacOutput(volatile STG4000REG __iomem *pSTGReg);
+
+/*
+ * Timing generator setup
+ */
+extern void DisableVGA(volatile STG4000REG __iomem *pSTGReg);
+extern void StopVTG(volatile STG4000REG __iomem *pSTGReg);
+extern void StartVTG(volatile STG4000REG __iomem *pSTGReg);
+extern void SetupVTG(volatile STG4000REG __iomem *pSTGReg,
+		     const struct kyrofb_info * pTiming);
+
+extern u32 ProgramClock(u32 refClock, u32 coreClock, u32 *FOut, u32 *ROut, u32 *POut);
+extern int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev);
+
+/*
+ * Overlay setup
+ */
+extern void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg);
+
+extern int CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg,
+				u32 ulWidth, u32 ulHeight,
+				int bLinear,
+				u32 ulOverlayOffset,
+				u32 * retStride, u32 * retUVStride);
+
+extern int SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg,
+			       OVRL_BLEND_MODE mode,
+			       u32 ulAlpha, u32 ulColorKey);
+
+extern int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
+			      u32 left, u32 top,
+			      u32 right, u32 bottom);
+
+extern void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg);
+
+#endif /* _STG4000INTERFACE_H */
diff --git a/drivers/video/fbdev/kyro/STG4000OverlayDevice.c b/drivers/video/fbdev/kyro/STG4000OverlayDevice.c
new file mode 100644
index 000000000000..0aeeaa10708b
--- /dev/null
+++ b/drivers/video/fbdev/kyro/STG4000OverlayDevice.c
@@ -0,0 +1,601 @@
+/*
+ *  linux/drivers/video/kyro/STG4000OverlayDevice.c
+ *
+ *  Copyright (C) 2000 Imagination Technologies Ltd
+ *  Copyright (C) 2002 STMicroelectronics
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#include "STG4000Reg.h"
+#include "STG4000Interface.h"
+
+/* HW Defines */
+
+#define STG4000_NO_SCALING    0x800
+#define STG4000_NO_DECIMATION 0xFFFFFFFF
+
+/* Primary surface */
+#define STG4000_PRIM_NUM_PIX   5
+#define STG4000_PRIM_ALIGN     4
+#define STG4000_PRIM_ADDR_BITS 20
+
+#define STG4000_PRIM_MIN_WIDTH  640
+#define STG4000_PRIM_MAX_WIDTH  1600
+#define STG4000_PRIM_MIN_HEIGHT 480
+#define STG4000_PRIM_MAX_HEIGHT 1200
+
+/* Overlay surface */
+#define STG4000_OVRL_NUM_PIX   4
+#define STG4000_OVRL_ALIGN     2
+#define STG4000_OVRL_ADDR_BITS 20
+#define STG4000_OVRL_NUM_MODES 5
+
+#define STG4000_OVRL_MIN_WIDTH  0
+#define STG4000_OVRL_MAX_WIDTH  720
+#define STG4000_OVRL_MIN_HEIGHT 0
+#define STG4000_OVRL_MAX_HEIGHT 576
+
+/* Decimation and Scaling */
+static u32 adwDecim8[33] = {
+	    0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf,
+	    0xfbdf7bdf, 0xf7bbddef, 0xeeeeeeef, 0xeeddbb77, 0xedb76db7,
+	    0xdb6db6db, 0xdb5b5b5b, 0xdab5ad6b, 0xd5ab55ab, 0xd555aaab,
+	    0xaaaaaaab, 0xaaaa5555, 0xaa952a55, 0xa94a5295, 0xa5252525,
+	    0xa4924925, 0x92491249, 0x91224489, 0x91111111, 0x90884211,
+	    0x88410821, 0x88102041, 0x81010101, 0x80800801, 0x80010001,
+	    0x80000001, 0x00000001, 0x00000000
+};
+
+typedef struct _OVRL_SRC_DEST {
+	/*clipped on-screen pixel position of overlay */
+	u32 ulDstX1;
+	u32 ulDstY1;
+	u32 ulDstX2;
+	u32 ulDstY2;
+
+	/*clipped pixel pos of source data within buffer thses need to be 128 bit word aligned */
+	u32 ulSrcX1;
+	u32 ulSrcY1;
+	u32 ulSrcX2;
+	u32 ulSrcY2;
+
+	/* on-screen pixel position of overlay */
+	s32 lDstX1;
+	s32 lDstY1;
+	s32 lDstX2;
+	s32 lDstY2;
+} OVRL_SRC_DEST;
+
+static u32 ovlWidth, ovlHeight, ovlStride;
+static int ovlLinear;
+
+void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg)
+{
+	u32 tmp;
+
+	/* Set Overlay address to default */
+	tmp = STG_READ_REG(DACOverlayAddr);
+	CLEAR_BITS_FRM_TO(0, 20);
+	CLEAR_BIT(31);
+	STG_WRITE_REG(DACOverlayAddr, tmp);
+
+	/* Set Overlay U address */
+	tmp = STG_READ_REG(DACOverlayUAddr);
+	CLEAR_BITS_FRM_TO(0, 20);
+	STG_WRITE_REG(DACOverlayUAddr, tmp);
+
+	/* Set Overlay V address */
+	tmp = STG_READ_REG(DACOverlayVAddr);
+	CLEAR_BITS_FRM_TO(0, 20);
+	STG_WRITE_REG(DACOverlayVAddr, tmp);
+
+	/* Set Overlay Size */
+	tmp = STG_READ_REG(DACOverlaySize);
+	CLEAR_BITS_FRM_TO(0, 10);
+	CLEAR_BITS_FRM_TO(12, 31);
+	STG_WRITE_REG(DACOverlaySize, tmp);
+
+	/* Set Overlay Vt Decimation */
+	tmp = STG4000_NO_DECIMATION;
+	STG_WRITE_REG(DACOverlayVtDec, tmp);
+
+	/* Set Overlay format to default value */
+	tmp = STG_READ_REG(DACPixelFormat);
+	CLEAR_BITS_FRM_TO(4, 7);
+	CLEAR_BITS_FRM_TO(16, 22);
+	STG_WRITE_REG(DACPixelFormat, tmp);
+
+	/* Set Vertical scaling to default */
+	tmp = STG_READ_REG(DACVerticalScal);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 22);
+	tmp |= STG4000_NO_SCALING;	/* Set to no scaling */
+	STG_WRITE_REG(DACVerticalScal, tmp);
+
+	/* Set Horizontal Scaling to default */
+	tmp = STG_READ_REG(DACHorizontalScal);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 17);
+	tmp |= STG4000_NO_SCALING;	/* Set to no scaling */
+	STG_WRITE_REG(DACHorizontalScal, tmp);
+
+	/* Set Blend mode to Alpha Blend */
+	/* ????? SG 08/11/2001 Surely this isn't the alpha blend mode,
+	   hopefully its overwrite
+	 */
+	tmp = STG_READ_REG(DACBlendCtrl);
+	CLEAR_BITS_FRM_TO(0, 30);
+	tmp = (GRAPHICS_MODE << 28);
+	STG_WRITE_REG(DACBlendCtrl, tmp);
+
+}
+
+int CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg,
+			 u32 inWidth,
+			 u32 inHeight,
+			 int bLinear,
+			 u32 ulOverlayOffset,
+			 u32 * retStride, u32 * retUVStride)
+{
+	u32 tmp;
+	u32 ulStride;
+
+	if (inWidth > STG4000_OVRL_MAX_WIDTH ||
+	    inHeight > STG4000_OVRL_MAX_HEIGHT) {
+		return -EINVAL;
+	}
+
+	/* Stride in 16 byte words - 16Bpp */
+	if (bLinear) {
+		/* Format is 16bits so num 16 byte words is width/8 */
+		if ((inWidth & 0x7) == 0) {	/* inWidth % 8 */
+			ulStride = (inWidth / 8);
+		} else {
+			/* Round up to next 16byte boundary */
+			ulStride = ((inWidth + 8) / 8);
+		}
+	} else {
+		/* Y component is 8bits so num 16 byte words is width/16 */
+		if ((inWidth & 0xf) == 0) {	/* inWidth % 16 */
+			ulStride = (inWidth / 16);
+		} else {
+			/* Round up to next 16byte boundary */
+			ulStride = ((inWidth + 16) / 16);
+		}
+	}
+
+
+	/* Set Overlay address and Format mode */
+	tmp = STG_READ_REG(DACOverlayAddr);
+	CLEAR_BITS_FRM_TO(0, 20);
+	if (bLinear) {
+		CLEAR_BIT(31);	/* Overlay format to Linear */
+	} else {
+		tmp |= SET_BIT(31);	/* Overlay format to Planer */
+	}
+
+	/* Only bits 24:4 of the Overlay address */
+	tmp |= (ulOverlayOffset >> 4);
+	STG_WRITE_REG(DACOverlayAddr, tmp);
+
+	if (!bLinear) {
+		u32 uvSize =
+		    (inWidth & 0x1) ? (inWidth + 1 / 2) : (inWidth / 2);
+		u32 uvStride;
+		u32 ulOffset;
+		/* Y component is 8bits so num 32 byte words is width/32 */
+		if ((uvSize & 0xf) == 0) {	/* inWidth % 16 */
+			uvStride = (uvSize / 16);
+		} else {
+			/* Round up to next 32byte boundary */
+			uvStride = ((uvSize + 16) / 16);
+		}
+
+		ulOffset = ulOverlayOffset + (inHeight * (ulStride * 16));
+		/* Align U,V data to 32byte boundary */
+		if ((ulOffset & 0x1f) != 0)
+			ulOffset = (ulOffset + 32L) & 0xffffffE0L;
+
+		tmp = STG_READ_REG(DACOverlayUAddr);
+		CLEAR_BITS_FRM_TO(0, 20);
+		tmp |= (ulOffset >> 4);
+		STG_WRITE_REG(DACOverlayUAddr, tmp);
+
+		ulOffset += (inHeight / 2) * (uvStride * 16);
+		/* Align U,V data to 32byte boundary */
+		if ((ulOffset & 0x1f) != 0)
+			ulOffset = (ulOffset + 32L) & 0xffffffE0L;
+
+		tmp = STG_READ_REG(DACOverlayVAddr);
+		CLEAR_BITS_FRM_TO(0, 20);
+		tmp |= (ulOffset >> 4);
+		STG_WRITE_REG(DACOverlayVAddr, tmp);
+
+		*retUVStride = uvStride * 16;
+	}
+
+
+	/* Set Overlay YUV pixel format
+	 * Make sure that LUT not used - ??????
+	 */
+	tmp = STG_READ_REG(DACPixelFormat);
+	/* Only support Planer or UYVY linear formats */
+	CLEAR_BITS_FRM_TO(4, 9);
+	STG_WRITE_REG(DACPixelFormat, tmp);
+
+	ovlWidth = inWidth;
+	ovlHeight = inHeight;
+	ovlStride = ulStride;
+	ovlLinear = bLinear;
+	*retStride = ulStride << 4;	/* In bytes */
+
+	return 0;
+}
+
+int SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg,
+			OVRL_BLEND_MODE mode,
+			u32 ulAlpha, u32 ulColorKey)
+{
+	u32 tmp;
+
+	tmp = STG_READ_REG(DACBlendCtrl);
+	CLEAR_BITS_FRM_TO(28, 30);
+	tmp |= (mode << 28);
+
+	switch (mode) {
+	case COLOR_KEY:
+		CLEAR_BITS_FRM_TO(0, 23);
+		tmp |= (ulColorKey & 0x00FFFFFF);
+		break;
+
+	case GLOBAL_ALPHA:
+		CLEAR_BITS_FRM_TO(24, 27);
+		tmp |= ((ulAlpha & 0xF) << 24);
+		break;
+
+	case CK_PIXEL_ALPHA:
+		CLEAR_BITS_FRM_TO(0, 23);
+		tmp |= (ulColorKey & 0x00FFFFFF);
+		break;
+
+	case CK_GLOBAL_ALPHA:
+		CLEAR_BITS_FRM_TO(0, 23);
+		tmp |= (ulColorKey & 0x00FFFFFF);
+		CLEAR_BITS_FRM_TO(24, 27);
+		tmp |= ((ulAlpha & 0xF) << 24);
+		break;
+
+	case GRAPHICS_MODE:
+	case PER_PIXEL_ALPHA:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	STG_WRITE_REG(DACBlendCtrl, tmp);
+
+	return 0;
+}
+
+void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg)
+{
+	u32 tmp;
+	/* Enable Overlay */
+	tmp = STG_READ_REG(DACPixelFormat);
+	tmp |= SET_BIT(7);
+	STG_WRITE_REG(DACPixelFormat, tmp);
+
+	/* Set video stream control */
+	tmp = STG_READ_REG(DACStreamCtrl);
+	tmp |= SET_BIT(1);	/* video stream */
+	STG_WRITE_REG(DACStreamCtrl, tmp);
+}
+
+static u32 Overlap(u32 ulBits, u32 ulPattern)
+{
+	u32 ulCount = 0;
+
+	while (ulBits) {
+		if (!(ulPattern & 1))
+			ulCount++;
+		ulBits--;
+		ulPattern = ulPattern >> 1;
+	}
+
+	return ulCount;
+
+}
+
+int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
+		       u32 left, u32 top,
+		       u32 right, u32 bottom)
+{
+	OVRL_SRC_DEST srcDest;
+
+	u32 ulSrcTop, ulSrcBottom;
+	u32 ulSrc, ulDest;
+	u32 ulFxScale, ulFxOffset;
+	u32 ulHeight, ulWidth;
+	u32 ulPattern;
+	u32 ulDecimate, ulDecimated;
+	u32 ulApplied;
+	u32 ulDacXScale, ulDacYScale;
+	u32 ulScale;
+	u32 ulLeft, ulRight;
+	u32 ulSrcLeft, ulSrcRight;
+	u32 ulScaleLeft, ulScaleRight;
+	u32 ulhDecim;
+	u32 ulsVal;
+	u32 ulVertDecFactor;
+	int bResult;
+	u32 ulClipOff = 0;
+	u32 ulBits = 0;
+	u32 ulsAdd = 0;
+	u32 tmp, ulStride;
+	u32 ulExcessPixels, ulClip, ulExtraLines;
+
+
+	srcDest.ulSrcX1 = 0;
+	srcDest.ulSrcY1 = 0;
+	srcDest.ulSrcX2 = ovlWidth - 1;
+	srcDest.ulSrcY2 = ovlHeight - 1;
+
+	srcDest.ulDstX1 = left;
+	srcDest.ulDstY1 = top;
+	srcDest.ulDstX2 = right;
+	srcDest.ulDstY2 = bottom;
+
+	srcDest.lDstX1 = srcDest.ulDstX1;
+	srcDest.lDstY1 = srcDest.ulDstY1;
+	srcDest.lDstX2 = srcDest.ulDstX2;
+	srcDest.lDstY2 = srcDest.ulDstY2;
+
+    /************* Vertical decimation/scaling ******************/
+
+	/* Get Src Top and Bottom */
+	ulSrcTop = srcDest.ulSrcY1;
+	ulSrcBottom = srcDest.ulSrcY2;
+
+	ulSrc = ulSrcBottom - ulSrcTop;
+	ulDest = srcDest.lDstY2 - srcDest.lDstY1;	/* on-screen overlay */
+
+	if (ulSrc <= 1)
+		return -EINVAL;
+
+	/* First work out the position we are to display as offset from the
+	 * source of the buffer
+	 */
+	ulFxScale = (ulDest << 11) / ulSrc;	/* fixed point scale factor */
+	ulFxOffset = (srcDest.lDstY2 - srcDest.ulDstY2) << 11;
+
+	ulSrcBottom = ulSrcBottom - (ulFxOffset / ulFxScale);
+	ulSrc = ulSrcBottom - ulSrcTop;
+	ulHeight = ulSrc;
+
+	ulDest = srcDest.ulDstY2 - (srcDest.ulDstY1 - 1);
+	ulPattern = adwDecim8[ulBits];
+
+	/* At this point ulSrc represents the input decimator */
+	if (ulSrc > ulDest) {
+		ulDecimate = ulSrc - ulDest;
+		ulBits = 0;
+		ulApplied = ulSrc / 32;
+
+		while (((ulBits * ulApplied) +
+			Overlap((ulSrc % 32),
+				adwDecim8[ulBits])) < ulDecimate)
+			ulBits++;
+
+		ulPattern = adwDecim8[ulBits];
+		ulDecimated =
+		    (ulBits * ulApplied) + Overlap((ulSrc % 32),
+						   ulPattern);
+		ulSrc = ulSrc - ulDecimated;	/* the number number of lines that will go into the scaler */
+	}
+
+	if (ulBits && (ulBits != 32)) {
+		ulVertDecFactor = (63 - ulBits) / (32 - ulBits);	/* vertical decimation factor scaled up to nearest integer */
+	} else {
+		ulVertDecFactor = 1;
+	}
+
+	ulDacYScale = ((ulSrc - 1) * 2048) / (ulDest + 1);
+
+	tmp = STG_READ_REG(DACOverlayVtDec);	/* Decimation */
+	CLEAR_BITS_FRM_TO(0, 31);
+	tmp = ulPattern;
+	STG_WRITE_REG(DACOverlayVtDec, tmp);
+
+	/***************** Horizontal decimation/scaling ***************************/
+
+	/*
+	 * Now we handle the horizontal case, this is a simplified version of
+	 * the vertical case in that we decimate by factors of 2.  as we are
+	 * working in words we should always be able to decimate by these
+	 * factors.  as we always have to have a buffer which is aligned to a
+	 * whole number of 128 bit words, we must align the left side to the
+	 * lowest to the next lowest 128 bit boundary, and the right hand edge
+	 * to the next largets boundary, (in a similar way to how we didi it in
+	 * PMX1) as the left and right hand edges are aligned to these
+	 * boundaries normally this only becomes an issue when we are chopping
+	 * of one of the sides We shall work out vertical stuff first
+	 */
+	ulSrc = srcDest.ulSrcX2 - srcDest.ulSrcX1;
+	ulDest = srcDest.lDstX2 - srcDest.lDstX1;
+#ifdef _OLDCODE
+	ulLeft = srcDest.ulDstX1;
+	ulRight = srcDest.ulDstX2;
+#else
+	if (srcDest.ulDstX1 > 2) {
+		ulLeft = srcDest.ulDstX1 + 2;
+		ulRight = srcDest.ulDstX2 + 1;
+	} else {
+		ulLeft = srcDest.ulDstX1;
+		ulRight = srcDest.ulDstX2 + 1;
+	}
+#endif
+	/* first work out the position we are to display as offset from the source of the buffer */
+	bResult = 1;
+
+	do {
+		if (ulDest == 0)
+			return -EINVAL;
+
+		/* source pixels per dest pixel <<11 */
+		ulFxScale = ((ulSrc - 1) << 11) / (ulDest);
+
+		/* then number of destination pixels out we are */
+		ulFxOffset = ulFxScale * ((srcDest.ulDstX1 - srcDest.lDstX1) + ulClipOff);
+		ulFxOffset >>= 11;
+
+		/* this replaces the code which was making a decision as to use either ulFxOffset or ulSrcX1 */
+		ulSrcLeft = srcDest.ulSrcX1 + ulFxOffset;
+
+		/* then number of destination pixels out we are */
+		ulFxOffset = ulFxScale * (srcDest.lDstX2 - srcDest.ulDstX2);
+		ulFxOffset >>= 11;
+
+		ulSrcRight = srcDest.ulSrcX2 - ulFxOffset;
+
+		/*
+		 * we must align these to our 128 bit boundaries. we shall
+		 * round down the pixel pos to the nearest 8 pixels.
+		 */
+		ulScaleLeft = ulSrcLeft;
+		ulScaleRight = ulSrcRight;
+
+		/* shift fxscale until it is in the range of the scaler */
+		ulhDecim = 0;
+		ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
+
+		while (ulScale > 0x800) {
+			ulhDecim++;
+			ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
+		}
+
+		/*
+		 * to try and get the best values We first try and use
+		 * src/dwdest for the scale factor, then we move onto src-1
+		 *
+		 * we want to check to see if we will need to clip data, if so
+		 * then we should clip our source so that we don't need to
+		 */
+		if (!ovlLinear) {
+			ulSrcLeft &= ~0x1f;
+
+			/*
+			 * we must align the right hand edge to the next 32
+			 * pixel` boundary, must be on a 256 boundary so u, and
+			 * v are 128 bit aligned
+			 */
+			ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f;
+		} else {
+			ulSrcLeft &= ~0x7;
+
+			/*
+			 * we must align the right hand edge to the next
+			 * 8pixel` boundary
+			 */
+			ulSrcRight = (ulSrcRight + 0x7) & ~0x7;
+		}
+
+		/* this is the input size line store needs to cope with */
+		ulWidth = ulSrcRight - ulSrcLeft;
+
+		/*
+		 * use unclipped value to work out scale factror this is the
+		 * scale factor we want we shall now work out the horizonal
+		 * decimation and scaling
+		 */
+		ulsVal = ((ulWidth / 8) >> ulhDecim);
+
+		if ((ulWidth != (ulsVal << ulhDecim) * 8))
+			ulsAdd = 1;
+
+		/* input pixels to scaler; */
+		ulSrc = ulWidth >> ulhDecim;
+
+		if (ulSrc <= 2)
+			return -EINVAL;
+
+		ulExcessPixels = ((((ulScaleLeft - ulSrcLeft)) << (11 - ulhDecim)) / ulScale);
+
+		ulClip = (ulSrc << 11) / ulScale;
+		ulClip -= (ulRight - ulLeft);
+		ulClip += ulExcessPixels;
+
+		if (ulClip)
+			ulClip--;
+
+		/* We may need to do more here if we really have a HW rev < 5 */
+	} while (!bResult);
+
+	ulExtraLines = (1 << ulhDecim) * ulVertDecFactor;
+	ulExtraLines += 64;
+	ulHeight += ulExtraLines;
+
+	ulDacXScale = ulScale;
+
+
+	tmp = STG_READ_REG(DACVerticalScal);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 22);	/* Vertical Scaling */
+
+	/* Calculate new output line stride, this is always the number of 422
+	   words in the line buffer, so it doesn't matter if the
+	   mode is 420. Then set the vertical scale register.
+	 */
+	ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd;
+	tmp |= ((ulStride << 16) | (ulDacYScale));	/* DAC_LS_CTRL = stride */
+	STG_WRITE_REG(DACVerticalScal, tmp);
+
+	/* Now set up the overlay size using the modified width and height
+	   from decimate and scaling calculations
+	 */
+	tmp = STG_READ_REG(DACOverlaySize);
+	CLEAR_BITS_FRM_TO(0, 10);
+	CLEAR_BITS_FRM_TO(12, 31);
+
+	if (ovlLinear) {
+		tmp |=
+		    (ovlStride | ((ulHeight + 1) << 12) |
+		     (((ulWidth / 8) - 1) << 23));
+	} else {
+		tmp |=
+		    (ovlStride | ((ulHeight + 1) << 12) |
+		     (((ulWidth / 32) - 1) << 23));
+	}
+
+	STG_WRITE_REG(DACOverlaySize, tmp);
+
+	/* Set Video Window Start */
+	tmp = ((ulLeft << 16)) | (srcDest.ulDstY1);
+	STG_WRITE_REG(DACVidWinStart, tmp);
+
+	/* Set Video Window End */
+	tmp = ((ulRight) << 16) | (srcDest.ulDstY2);
+	STG_WRITE_REG(DACVidWinEnd, tmp);
+
+	/* Finally set up the rest of the overlay regs in the order
+	   done in the IMG driver
+	 */
+	tmp = STG_READ_REG(DACPixelFormat);
+	tmp = ((ulExcessPixels << 16) | tmp) & 0x7fffffff;
+	STG_WRITE_REG(DACPixelFormat, tmp);
+
+	tmp = STG_READ_REG(DACHorizontalScal);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 17);
+	tmp |= ((ulhDecim << 16) | (ulDacXScale));
+	STG_WRITE_REG(DACHorizontalScal, tmp);
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/kyro/STG4000Ramdac.c b/drivers/video/fbdev/kyro/STG4000Ramdac.c
new file mode 100644
index 000000000000..e6ad037e4396
--- /dev/null
+++ b/drivers/video/fbdev/kyro/STG4000Ramdac.c
@@ -0,0 +1,163 @@
+/*
+ *  linux/drivers/video/kyro/STG4000Ramdac.c
+ *
+ *  Copyright (C) 2002 STMicroelectronics
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <video/kyro.h>
+
+#include "STG4000Reg.h"
+#include "STG4000Interface.h"
+
+static u32 STG_PIXEL_BUS_WIDTH = 128;	/* 128 bit bus width      */
+static u32 REF_CLOCK = 14318;
+
+int InitialiseRamdac(volatile STG4000REG __iomem * pSTGReg,
+		     u32 displayDepth,
+		     u32 displayWidth,
+		     u32 displayHeight,
+		     s32 HSyncPolarity,
+		     s32 VSyncPolarity, u32 * pixelClock)
+{
+	u32 tmp = 0;
+	u32 F = 0, R = 0, P = 0;
+	u32 stride = 0;
+	u32 ulPdiv = 0;
+	u32 physicalPixelDepth = 0;
+	/* Make sure DAC is in Reset */
+	tmp = STG_READ_REG(SoftwareReset);
+
+	if (tmp & 0x1) {
+		CLEAR_BIT(1);
+		STG_WRITE_REG(SoftwareReset, tmp);
+	}
+
+	/* Set Pixel Format */
+	tmp = STG_READ_REG(DACPixelFormat);
+	CLEAR_BITS_FRM_TO(0, 2);
+
+	/* Set LUT not used from 16bpp to 32 bpp ??? */
+	CLEAR_BITS_FRM_TO(8, 9);
+
+	switch (displayDepth) {
+	case 16:
+		{
+			physicalPixelDepth = 16;
+			tmp |= _16BPP;
+			break;
+		}
+	case 32:
+		{
+			/* Set for 32 bits per pixel */
+			physicalPixelDepth = 32;
+			tmp |= _32BPP;
+			break;
+		}
+	default:
+		return -EINVAL;
+	}
+
+	STG_WRITE_REG(DACPixelFormat, tmp);
+
+	/* Workout Bus transfer bandwidth according to pixel format */
+	ulPdiv = STG_PIXEL_BUS_WIDTH / physicalPixelDepth;
+
+	/* Get Screen Stride in pixels */
+	stride = displayWidth;
+
+	/* Set Primary size info */
+	tmp = STG_READ_REG(DACPrimSize);
+	CLEAR_BITS_FRM_TO(0, 10);
+	CLEAR_BITS_FRM_TO(12, 31);
+	tmp |=
+	    ((((displayHeight - 1) << 12) | (((displayWidth / ulPdiv) -
+					      1) << 23))
+	     | (stride / ulPdiv));
+	STG_WRITE_REG(DACPrimSize, tmp);
+
+
+	/* Set Pixel Clock */
+	*pixelClock = ProgramClock(REF_CLOCK, *pixelClock, &F, &R, &P);
+
+	/* Set DAC PLL Mode */
+	tmp = STG_READ_REG(DACPLLMode);
+	CLEAR_BITS_FRM_TO(0, 15);
+	/* tmp |= ((P-1) | ((F-2) << 2) | ((R-2) << 11)); */
+	tmp |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
+	STG_WRITE_REG(DACPLLMode, tmp);
+
+	/* Set Prim Address */
+	tmp = STG_READ_REG(DACPrimAddress);
+	CLEAR_BITS_FRM_TO(0, 20);
+	CLEAR_BITS_FRM_TO(20, 31);
+	STG_WRITE_REG(DACPrimAddress, tmp);
+
+	/* Set Cursor details with HW Cursor disabled */
+	tmp = STG_READ_REG(DACCursorCtrl);
+	tmp &= ~SET_BIT(31);
+	STG_WRITE_REG(DACCursorCtrl, tmp);
+
+	tmp = STG_READ_REG(DACCursorAddr);
+	CLEAR_BITS_FRM_TO(0, 20);
+	STG_WRITE_REG(DACCursorAddr, tmp);
+
+	/* Set Video Window */
+	tmp = STG_READ_REG(DACVidWinStart);
+	CLEAR_BITS_FRM_TO(0, 10);
+	CLEAR_BITS_FRM_TO(16, 26);
+	STG_WRITE_REG(DACVidWinStart, tmp);
+
+	tmp = STG_READ_REG(DACVidWinEnd);
+	CLEAR_BITS_FRM_TO(0, 10);
+	CLEAR_BITS_FRM_TO(16, 26);
+	STG_WRITE_REG(DACVidWinEnd, tmp);
+
+	/* Set DAC Border Color to default */
+	tmp = STG_READ_REG(DACBorderColor);
+	CLEAR_BITS_FRM_TO(0, 23);
+	STG_WRITE_REG(DACBorderColor, tmp);
+
+	/* Set Graphics and Overlay Burst Control */
+	STG_WRITE_REG(DACBurstCtrl, 0x0404);
+
+	/* Set CRC Trigger to default */
+	tmp = STG_READ_REG(DACCrcTrigger);
+	CLEAR_BIT(0);
+	STG_WRITE_REG(DACCrcTrigger, tmp);
+
+	/* Set Video Port Control to default */
+	tmp = STG_READ_REG(DigVidPortCtrl);
+	CLEAR_BIT(8);
+	CLEAR_BITS_FRM_TO(16, 27);
+	CLEAR_BITS_FRM_TO(1, 3);
+	CLEAR_BITS_FRM_TO(10, 11);
+	STG_WRITE_REG(DigVidPortCtrl, tmp);
+
+	return 0;
+}
+
+/* Ramdac control, turning output to the screen on and off */
+void DisableRamdacOutput(volatile STG4000REG __iomem * pSTGReg)
+{
+	u32 tmp;
+
+	/* Disable DAC for Graphics Stream Control */
+	tmp = (STG_READ_REG(DACStreamCtrl)) & ~SET_BIT(0);
+	STG_WRITE_REG(DACStreamCtrl, tmp);
+}
+
+void EnableRamdacOutput(volatile STG4000REG __iomem * pSTGReg)
+{
+	u32 tmp;
+
+	/* Enable DAC for Graphics Stream Control */
+	tmp = (STG_READ_REG(DACStreamCtrl)) | SET_BIT(0);
+	STG_WRITE_REG(DACStreamCtrl, tmp);
+}
diff --git a/drivers/video/fbdev/kyro/STG4000Reg.h b/drivers/video/fbdev/kyro/STG4000Reg.h
new file mode 100644
index 000000000000..50f4670e9252
--- /dev/null
+++ b/drivers/video/fbdev/kyro/STG4000Reg.h
@@ -0,0 +1,283 @@
+/*
+ *  linux/drivers/video/kyro/STG4000Reg.h
+ *
+ *  Copyright (C) 2002 STMicroelectronics
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _STG4000REG_H
+#define _STG4000REG_H
+
+#define DWFILL unsigned long :32
+#define WFILL unsigned short :16
+
+/*
+ * Macros that access memory mapped card registers in PCI space
+ * Add an appropriate section for your OS or processor architecture.
+ */
+#if defined(__KERNEL__)
+#include <asm/page.h>
+#include <asm/io.h>
+#define STG_WRITE_REG(reg,data) (writel(data,&pSTGReg->reg))
+#define STG_READ_REG(reg)      (readl(&pSTGReg->reg))
+#else
+#define STG_WRITE_REG(reg,data) (pSTGReg->reg = data)
+#define STG_READ_REG(reg)      (pSTGReg->reg)
+#endif /* __KERNEL__ */
+
+#define SET_BIT(n) (1<<(n))
+#define CLEAR_BIT(n) (tmp &= ~(1<<n))
+#define CLEAR_BITS_FRM_TO(frm, to) \
+{\
+int i; \
+    for(i = frm; i<= to; i++) \
+	{ \
+	    tmp &= ~(1<<i); \
+	} \
+}
+
+#define CLEAR_BIT_2(n) (usTemp &= ~(1<<n))
+#define CLEAR_BITS_FRM_TO_2(frm, to) \
+{\
+int i; \
+    for(i = frm; i<= to; i++) \
+	{ \
+	    usTemp &= ~(1<<i); \
+	} \
+}
+
+/* LUT select */
+typedef enum _LUT_USES {
+	NO_LUT = 0, RESERVED, GRAPHICS, OVERLAY
+} LUT_USES;
+
+/* Primary surface pixel format select */
+typedef enum _PIXEL_FORMAT {
+	_8BPP = 0, _15BPP, _16BPP, _24BPP, _32BPP
+} PIXEL_FORMAT;
+
+/* Overlay blending mode select */
+typedef enum _BLEND_MODE {
+	GRAPHICS_MODE = 0, COLOR_KEY, PER_PIXEL_ALPHA, GLOBAL_ALPHA,
+	CK_PIXEL_ALPHA, CK_GLOBAL_ALPHA
+} OVRL_BLEND_MODE;
+
+/* Overlay Pixel format select */
+typedef enum _OVRL_PIX_FORMAT {
+	UYVY, VYUY, YUYV, YVYU
+} OVRL_PIX_FORMAT;
+
+/* Register Table */
+typedef struct {
+	/* 0h  */
+	volatile u32 Thread0Enable;	/* 0x0000 */
+	volatile u32 Thread1Enable;	/* 0x0004 */
+	volatile u32 Thread0Recover;	/* 0x0008 */
+	volatile u32 Thread1Recover;	/* 0x000C */
+	volatile u32 Thread0Step;	/* 0x0010 */
+	volatile u32 Thread1Step;	/* 0x0014 */
+	volatile u32 VideoInStatus;	/* 0x0018 */
+	volatile u32 Core2InSignStart;	/* 0x001C */
+	volatile u32 Core1ResetVector;	/* 0x0020 */
+	volatile u32 Core1ROMOffset;	/* 0x0024 */
+	volatile u32 Core1ArbiterPriority;	/* 0x0028 */
+	volatile u32 VideoInControl;	/* 0x002C */
+	volatile u32 VideoInReg0CtrlA;	/* 0x0030 */
+	volatile u32 VideoInReg0CtrlB;	/* 0x0034 */
+	volatile u32 VideoInReg1CtrlA;	/* 0x0038 */
+	volatile u32 VideoInReg1CtrlB;	/* 0x003C */
+	volatile u32 Thread0Kicker;	/* 0x0040 */
+	volatile u32 Core2InputSign;	/* 0x0044 */
+	volatile u32 Thread0ProgCtr;	/* 0x0048 */
+	volatile u32 Thread1ProgCtr;	/* 0x004C */
+	volatile u32 Thread1Kicker;	/* 0x0050 */
+	volatile u32 GPRegister1;	/* 0x0054 */
+	volatile u32 GPRegister2;	/* 0x0058 */
+	volatile u32 GPRegister3;	/* 0x005C */
+	volatile u32 GPRegister4;	/* 0x0060 */
+	volatile u32 SerialIntA;	/* 0x0064 */
+
+	volatile u32 Fill0[6];	/* GAP 0x0068 - 0x007C */
+
+	volatile u32 SoftwareReset;	/* 0x0080 */
+	volatile u32 SerialIntB;	/* 0x0084 */
+
+	volatile u32 Fill1[37];	/* GAP 0x0088 - 0x011C */
+
+	volatile u32 ROMELQV;	/* 0x011C */
+	volatile u32 WLWH;	/* 0x0120 */
+	volatile u32 ROMELWL;	/* 0x0124 */
+
+	volatile u32 dwFill_1;	/* GAP 0x0128 */
+
+	volatile u32 IntStatus;	/* 0x012C */
+	volatile u32 IntMask;	/* 0x0130 */
+	volatile u32 IntClear;	/* 0x0134 */
+
+	volatile u32 Fill2[6];	/* GAP 0x0138 - 0x014C */
+
+	volatile u32 ROMGPIOA;	/* 0x0150 */
+	volatile u32 ROMGPIOB;	/* 0x0154 */
+	volatile u32 ROMGPIOC;	/* 0x0158 */
+	volatile u32 ROMGPIOD;	/* 0x015C */
+
+	volatile u32 Fill3[2];	/* GAP 0x0160 - 0x0168 */
+
+	volatile u32 AGPIntID;	/* 0x0168 */
+	volatile u32 AGPIntClassCode;	/* 0x016C */
+	volatile u32 AGPIntBIST;	/* 0x0170 */
+	volatile u32 AGPIntSSID;	/* 0x0174 */
+	volatile u32 AGPIntPMCSR;	/* 0x0178 */
+	volatile u32 VGAFrameBufBase;	/* 0x017C */
+	volatile u32 VGANotify;	/* 0x0180 */
+	volatile u32 DACPLLMode;	/* 0x0184 */
+	volatile u32 Core1VideoClockDiv;	/* 0x0188 */
+	volatile u32 AGPIntStat;	/* 0x018C */
+
+	/*
+	   volatile u32 Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400
+	   volatile u32 Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table
+	   volatile u32 Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604
+	   volatile u32 Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680
+	   volatile u32 Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC
+	 */
+	volatile u32 Fill4[412];	/* 0x0190 - 0x07FC */
+
+	volatile u32 TACtrlStreamBase;	/* 0x0800 */
+	volatile u32 TAObjDataBase;	/* 0x0804 */
+	volatile u32 TAPtrDataBase;	/* 0x0808 */
+	volatile u32 TARegionDataBase;	/* 0x080C */
+	volatile u32 TATailPtrBase;	/* 0x0810 */
+	volatile u32 TAPtrRegionSize;	/* 0x0814 */
+	volatile u32 TAConfiguration;	/* 0x0818 */
+	volatile u32 TAObjDataStartAddr;	/* 0x081C */
+	volatile u32 TAObjDataEndAddr;	/* 0x0820 */
+	volatile u32 TAXScreenClip;	/* 0x0824 */
+	volatile u32 TAYScreenClip;	/* 0x0828 */
+	volatile u32 TARHWClamp;	/* 0x082C */
+	volatile u32 TARHWCompare;	/* 0x0830 */
+	volatile u32 TAStart;	/* 0x0834 */
+	volatile u32 TAObjReStart;	/* 0x0838 */
+	volatile u32 TAPtrReStart;	/* 0x083C */
+	volatile u32 TAStatus1;	/* 0x0840 */
+	volatile u32 TAStatus2;	/* 0x0844 */
+	volatile u32 TAIntStatus;	/* 0x0848 */
+	volatile u32 TAIntMask;	/* 0x084C */
+
+	volatile u32 Fill5[235];	/* GAP 0x0850 - 0x0BF8 */
+
+	volatile u32 TextureAddrThresh;	/* 0x0BFC */
+	volatile u32 Core1Translation;	/* 0x0C00 */
+	volatile u32 TextureAddrReMap;	/* 0x0C04 */
+	volatile u32 RenderOutAGPRemap;	/* 0x0C08 */
+	volatile u32 _3DRegionReadTrans;	/* 0x0C0C */
+	volatile u32 _3DPtrReadTrans;	/* 0x0C10 */
+	volatile u32 _3DParamReadTrans;	/* 0x0C14 */
+	volatile u32 _3DRegionReadThresh;	/* 0x0C18 */
+	volatile u32 _3DPtrReadThresh;	/* 0x0C1C */
+	volatile u32 _3DParamReadThresh;	/* 0x0C20 */
+	volatile u32 _3DRegionReadAGPRemap;	/* 0x0C24 */
+	volatile u32 _3DPtrReadAGPRemap;	/* 0x0C28 */
+	volatile u32 _3DParamReadAGPRemap;	/* 0x0C2C */
+	volatile u32 ZBufferAGPRemap;	/* 0x0C30 */
+	volatile u32 TAIndexAGPRemap;	/* 0x0C34 */
+	volatile u32 TAVertexAGPRemap;	/* 0x0C38 */
+	volatile u32 TAUVAddrTrans;	/* 0x0C3C */
+	volatile u32 TATailPtrCacheTrans;	/* 0x0C40 */
+	volatile u32 TAParamWriteTrans;	/* 0x0C44 */
+	volatile u32 TAPtrWriteTrans;	/* 0x0C48 */
+	volatile u32 TAParamWriteThresh;	/* 0x0C4C */
+	volatile u32 TAPtrWriteThresh;	/* 0x0C50 */
+	volatile u32 TATailPtrCacheAGPRe;	/* 0x0C54 */
+	volatile u32 TAParamWriteAGPRe;	/* 0x0C58 */
+	volatile u32 TAPtrWriteAGPRe;	/* 0x0C5C */
+	volatile u32 SDRAMArbiterConf;	/* 0x0C60 */
+	volatile u32 SDRAMConf0;	/* 0x0C64 */
+	volatile u32 SDRAMConf1;	/* 0x0C68 */
+	volatile u32 SDRAMConf2;	/* 0x0C6C */
+	volatile u32 SDRAMRefresh;	/* 0x0C70 */
+	volatile u32 SDRAMPowerStat;	/* 0x0C74 */
+
+	volatile u32 Fill6[2];	/* GAP 0x0C78 - 0x0C7C */
+
+	volatile u32 RAMBistData;	/* 0x0C80 */
+	volatile u32 RAMBistCtrl;	/* 0x0C84 */
+	volatile u32 FIFOBistKey;	/* 0x0C88 */
+	volatile u32 RAMBistResult;	/* 0x0C8C */
+	volatile u32 FIFOBistResult;	/* 0x0C90 */
+
+	/*
+	   volatile u32 Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC
+	   volatile u32 Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters
+	 */
+
+	volatile u32 Fill7[16];	/* 0x0c94 - 0x0cd0 */
+
+	volatile u32 SDRAMAddrSign;	/* 0x0CD4 */
+	volatile u32 SDRAMDataSign;	/* 0x0CD8 */
+	volatile u32 SDRAMSignConf;	/* 0x0CDC */
+
+	/* DWFILL; //GAP 0x0CE0 */
+	volatile u32 dwFill_2;
+
+	volatile u32 ISPSignature;	/* 0x0CE4 */
+
+	volatile u32 Fill8[454];	/*GAP 0x0CE8 - 0x13FC */
+
+	volatile u32 DACPrimAddress;	/* 0x1400 */
+	volatile u32 DACPrimSize;	/* 0x1404 */
+	volatile u32 DACCursorAddr;	/* 0x1408 */
+	volatile u32 DACCursorCtrl;	/* 0x140C */
+	volatile u32 DACOverlayAddr;	/* 0x1410 */
+	volatile u32 DACOverlayUAddr;	/* 0x1414 */
+	volatile u32 DACOverlayVAddr;	/* 0x1418 */
+	volatile u32 DACOverlaySize;	/* 0x141C */
+	volatile u32 DACOverlayVtDec;	/* 0x1420 */
+
+	volatile u32 Fill9[9];	/* GAP 0x1424 - 0x1444 */
+
+	volatile u32 DACVerticalScal;	/* 0x1448 */
+	volatile u32 DACPixelFormat;	/* 0x144C */
+	volatile u32 DACHorizontalScal;	/* 0x1450 */
+	volatile u32 DACVidWinStart;	/* 0x1454 */
+	volatile u32 DACVidWinEnd;	/* 0x1458 */
+	volatile u32 DACBlendCtrl;	/* 0x145C */
+	volatile u32 DACHorTim1;	/* 0x1460 */
+	volatile u32 DACHorTim2;	/* 0x1464 */
+	volatile u32 DACHorTim3;	/* 0x1468 */
+	volatile u32 DACVerTim1;	/* 0x146C */
+	volatile u32 DACVerTim2;	/* 0x1470 */
+	volatile u32 DACVerTim3;	/* 0x1474 */
+	volatile u32 DACBorderColor;	/* 0x1478 */
+	volatile u32 DACSyncCtrl;	/* 0x147C */
+	volatile u32 DACStreamCtrl;	/* 0x1480 */
+	volatile u32 DACLUTAddress;	/* 0x1484 */
+	volatile u32 DACLUTData;	/* 0x1488 */
+	volatile u32 DACBurstCtrl;	/* 0x148C */
+	volatile u32 DACCrcTrigger;	/* 0x1490 */
+	volatile u32 DACCrcDone;	/* 0x1494 */
+	volatile u32 DACCrcResult1;	/* 0x1498 */
+	volatile u32 DACCrcResult2;	/* 0x149C */
+	volatile u32 DACLinecount;	/* 0x14A0 */
+
+	volatile u32 Fill10[151];	/*GAP 0x14A4 - 0x16FC */
+
+	volatile u32 DigVidPortCtrl;	/* 0x1700 */
+	volatile u32 DigVidPortStat;	/* 0x1704 */
+
+	/*
+	   volatile u32 Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC
+	   volatile u32 Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT
+	 */
+
+	volatile u32 Fill11[1598];
+
+	/* DWFILL; //GAP 0x3000          ALUT 256MB offset */
+	volatile u32 Fill_3;
+
+} STG4000REG;
+
+#endif /* _STG4000REG_H */
diff --git a/drivers/video/fbdev/kyro/STG4000VTG.c b/drivers/video/fbdev/kyro/STG4000VTG.c
new file mode 100644
index 000000000000..bd389709d234
--- /dev/null
+++ b/drivers/video/fbdev/kyro/STG4000VTG.c
@@ -0,0 +1,170 @@
+/*
+ *  linux/drivers/video/kyro/STG4000VTG.c
+ *
+ *  Copyright (C) 2002 STMicroelectronics
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/types.h>
+#include <video/kyro.h>
+
+#include "STG4000Reg.h"
+#include "STG4000Interface.h"
+
+void DisableVGA(volatile STG4000REG __iomem *pSTGReg)
+{
+	u32 tmp;
+	volatile u32 count = 0, i;
+
+	/* Reset the VGA registers */
+	tmp = STG_READ_REG(SoftwareReset);
+	CLEAR_BIT(8);
+	STG_WRITE_REG(SoftwareReset, tmp);
+
+	/* Just for Delay */
+	for (i = 0; i < 1000; i++) {
+		count++;
+	}
+
+	/* Pull-out the VGA registers from reset */
+	tmp = STG_READ_REG(SoftwareReset);
+	tmp |= SET_BIT(8);
+	STG_WRITE_REG(SoftwareReset, tmp);
+}
+
+void StopVTG(volatile STG4000REG __iomem *pSTGReg)
+{
+	u32 tmp = 0;
+
+	/* Stop Ver and Hor Sync Generator */
+	tmp = (STG_READ_REG(DACSyncCtrl)) | SET_BIT(0) | SET_BIT(2);
+	CLEAR_BIT(31);
+	STG_WRITE_REG(DACSyncCtrl, tmp);
+}
+
+void StartVTG(volatile STG4000REG __iomem *pSTGReg)
+{
+	u32 tmp = 0;
+
+	/* Start Ver and Hor Sync Generator */
+	tmp = ((STG_READ_REG(DACSyncCtrl)) | SET_BIT(31));
+	CLEAR_BIT(0);
+	CLEAR_BIT(2);
+	STG_WRITE_REG(DACSyncCtrl, tmp);
+}
+
+void SetupVTG(volatile STG4000REG __iomem *pSTGReg,
+	      const struct kyrofb_info * pTiming)
+{
+	u32 tmp = 0;
+	u32 margins = 0;
+	u32 ulBorder;
+	u32 xRes = pTiming->XRES;
+	u32 yRes = pTiming->YRES;
+
+	/* Horizontal */
+	u32 HAddrTime, HRightBorder, HLeftBorder;
+	u32 HBackPorcStrt, HFrontPorchStrt, HTotal,
+	    HLeftBorderStrt, HRightBorderStrt, HDisplayStrt;
+
+	/* Vertical */
+	u32 VDisplayStrt, VBottomBorder, VTopBorder;
+	u32 VBackPorchStrt, VTotal, VTopBorderStrt,
+	    VFrontPorchStrt, VBottomBorderStrt, VAddrTime;
+
+	/* Need to calculate the right border */
+	if ((xRes == 640) && (yRes == 480)) {
+		if ((pTiming->VFREQ == 60) || (pTiming->VFREQ == 72)) {
+			margins = 8;
+		}
+	}
+
+	/* Work out the Border */
+	ulBorder =
+	    (pTiming->HTot -
+	     (pTiming->HST + (pTiming->HBP - margins) + xRes +
+	      (pTiming->HFP - margins))) >> 1;
+
+	/* Border the same for Vertical and Horizontal */
+	VBottomBorder = HLeftBorder = VTopBorder = HRightBorder = ulBorder;
+
+    /************ Get Timing values for Horizontal ******************/
+	HAddrTime = xRes;
+	HBackPorcStrt = pTiming->HST;
+	HTotal = pTiming->HTot;
+	HDisplayStrt =
+	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder;
+	HLeftBorderStrt = HDisplayStrt - HLeftBorder;
+	HFrontPorchStrt =
+	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder +
+	    HAddrTime + HRightBorder;
+	HRightBorderStrt = HFrontPorchStrt - HRightBorder;
+
+    /************ Get Timing values for Vertical ******************/
+	VAddrTime = yRes;
+	VBackPorchStrt = pTiming->VST;
+	VTotal = pTiming->VTot;
+	VDisplayStrt =
+	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder;
+	VTopBorderStrt = VDisplayStrt - VTopBorder;
+	VFrontPorchStrt =
+	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder +
+	    VAddrTime + VBottomBorder;
+	VBottomBorderStrt = VFrontPorchStrt - VBottomBorder;
+
+	/* Set Hor Timing 1, 2, 3 */
+	tmp = STG_READ_REG(DACHorTim1);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 27);
+	tmp |= (HTotal) | (HBackPorcStrt << 16);
+	STG_WRITE_REG(DACHorTim1, tmp);
+
+	tmp = STG_READ_REG(DACHorTim2);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 27);
+	tmp |= (HDisplayStrt << 16) | HLeftBorderStrt;
+	STG_WRITE_REG(DACHorTim2, tmp);
+
+	tmp = STG_READ_REG(DACHorTim3);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 27);
+	tmp |= (HFrontPorchStrt << 16) | HRightBorderStrt;
+	STG_WRITE_REG(DACHorTim3, tmp);
+
+	/* Set Ver Timing 1, 2, 3 */
+	tmp = STG_READ_REG(DACVerTim1);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 27);
+	tmp |= (VBackPorchStrt << 16) | (VTotal);
+	STG_WRITE_REG(DACVerTim1, tmp);
+
+	tmp = STG_READ_REG(DACVerTim2);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 27);
+	tmp |= (VDisplayStrt << 16) | VTopBorderStrt;
+	STG_WRITE_REG(DACVerTim2, tmp);
+
+	tmp = STG_READ_REG(DACVerTim3);
+	CLEAR_BITS_FRM_TO(0, 11);
+	CLEAR_BITS_FRM_TO(16, 27);
+	tmp |= (VFrontPorchStrt << 16) | VBottomBorderStrt;
+	STG_WRITE_REG(DACVerTim3, tmp);
+
+	/* Set Verical and Horizontal Polarity */
+	tmp = STG_READ_REG(DACSyncCtrl) | SET_BIT(3) | SET_BIT(1);
+
+	if ((pTiming->HSP > 0) && (pTiming->VSP < 0)) {	/* +hsync -vsync */
+		tmp &= ~0x8;
+	} else if ((pTiming->HSP < 0) && (pTiming->VSP > 0)) {	/* -hsync +vsync */
+		tmp &= ~0x2;
+	} else if ((pTiming->HSP < 0) && (pTiming->VSP < 0)) {	/* -hsync -vsync */
+		tmp &= ~0xA;
+	} else if ((pTiming->HSP > 0) && (pTiming->VSP > 0)) {	/* +hsync -vsync */
+		tmp &= ~0x0;
+	}
+
+	STG_WRITE_REG(DACSyncCtrl, tmp);
+}
diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c
new file mode 100644
index 000000000000..65041e15fd59
--- /dev/null
+++ b/drivers/video/fbdev/kyro/fbdev.c
@@ -0,0 +1,808 @@
+/*
+ *  linux/drivers/video/kyro/fbdev.c
+ *
+ *  Copyright (C) 2002 STMicroelectronics
+ *  Copyright (C) 2003, 2004 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioctl.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/uaccess.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/kyro.h>
+
+#include "STG4000Reg.h"
+#include "STG4000Interface.h"
+
+/*
+ * PCI Definitions
+ */
+#define PCI_VENDOR_ID_ST	0x104a
+#define PCI_DEVICE_ID_STG4000	0x0010
+
+#define KHZ2PICOS(a) (1000000000UL/(a))
+
+/****************************************************************************/
+static struct fb_fix_screeninfo kyro_fix = {
+	.id		= "ST Kyro",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo kyro_var = {
+	/* 640x480, 16bpp @ 60 Hz */
+	.xres		= 640,
+	.yres		= 480,
+	.xres_virtual	= 640,
+	.yres_virtual	= 480,
+	.bits_per_pixel	= 16,
+	.red		= { 11, 5, 0 },
+	.green		= {  5, 6, 0 },
+	.blue		= {  0, 5, 0 },
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.pixclock	= KHZ2PICOS(25175),
+	.left_margin	= 48,
+	.right_margin	= 16,
+	.upper_margin	= 33,
+	.lower_margin	= 10,
+	.hsync_len	= 96,
+	.vsync_len	= 2,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+typedef struct {
+	STG4000REG __iomem *pSTGReg;	/* Virtual address of PCI register region */
+	u32 ulNextFreeVidMem;	/* Offset from start of vid mem to next free region */
+	u32 ulOverlayOffset;	/* Offset from start of vid mem to overlay */
+	u32 ulOverlayStride;	/* Interleaved YUV and 422 mode Y stride */
+	u32 ulOverlayUVStride;	/* 422 mode U & V stride */
+} device_info_t;
+
+/* global graphics card info structure (one per card) */
+static device_info_t deviceInfo;
+
+static char *mode_option = NULL;
+static int nopan = 0;
+static int nowrap = 1;
+#ifdef CONFIG_MTRR
+static int nomtrr = 0;
+#endif
+
+/* PCI driver prototypes */
+static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void kyrofb_remove(struct pci_dev *pdev);
+
+static struct fb_videomode kyro_modedb[] = {
+	{
+		/* 640x350 @ 85Hz */
+		NULL, 85, 640, 350, KHZ2PICOS(31500),
+		96, 32, 60, 32, 64, 3,
+		FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 640x400 @ 85Hz */
+		NULL, 85, 640, 400, KHZ2PICOS(31500),
+		96, 32, 41, 1, 64, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 720x400 @ 85Hz */
+		NULL, 85, 720, 400, KHZ2PICOS(35500),
+		108, 36, 42, 1, 72, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 640x480 @ 60Hz */
+		NULL, 60, 640, 480, KHZ2PICOS(25175),
+		48, 16, 33, 10, 96, 2,
+		0, FB_VMODE_NONINTERLACED
+	}, {
+		/* 640x480 @ 72Hz */
+		NULL, 72, 640, 480, KHZ2PICOS(31500),
+		128, 24, 28, 9, 40, 3,
+		0, FB_VMODE_NONINTERLACED
+	}, {
+		/* 640x480 @ 75Hz */
+		NULL, 75, 640, 480, KHZ2PICOS(31500),
+		120, 16, 16, 1, 64, 3,
+		0, FB_VMODE_NONINTERLACED
+	}, {
+		/* 640x480 @ 85Hz */
+		NULL, 85, 640, 480, KHZ2PICOS(36000),
+		80, 56, 25, 1, 56, 3,
+		0, FB_VMODE_NONINTERLACED
+	}, {
+		/* 800x600 @ 56Hz */
+		NULL, 56, 800, 600, KHZ2PICOS(36000),
+		128, 24, 22, 1, 72, 2,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 800x600 @ 60Hz */
+		NULL, 60, 800, 600, KHZ2PICOS(40000),
+		88, 40, 23, 1, 128, 4,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 800x600 @ 72Hz */
+		NULL, 72, 800, 600, KHZ2PICOS(50000),
+		64, 56, 23, 37, 120, 6,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 800x600 @ 75Hz */
+		NULL, 75, 800, 600, KHZ2PICOS(49500),
+		160, 16, 21, 1, 80, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 800x600 @ 85Hz */
+		NULL, 85, 800, 600, KHZ2PICOS(56250),
+		152, 32, 27, 1, 64, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1024x768 @ 60Hz */
+		NULL, 60, 1024, 768, KHZ2PICOS(65000),
+		160, 24, 29, 3, 136, 6,
+		0, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1024x768 @ 70Hz */
+		NULL, 70, 1024, 768, KHZ2PICOS(75000),
+		144, 24, 29, 3, 136, 6,
+		0, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1024x768 @ 75Hz */
+		NULL, 75, 1024, 768, KHZ2PICOS(78750),
+		176, 16, 28, 1, 96, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1024x768 @ 85Hz */
+		NULL, 85, 1024, 768, KHZ2PICOS(94500),
+		208, 48, 36, 1, 96, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1152x864 @ 75Hz */
+		NULL, 75, 1152, 864, KHZ2PICOS(108000),
+		256, 64, 32, 1, 128, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1280x960 @ 60Hz */
+		NULL, 60, 1280, 960, KHZ2PICOS(108000),
+		312, 96, 36, 1, 112, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1280x960 @ 85Hz */
+		NULL, 85, 1280, 960, KHZ2PICOS(148500),
+		224, 64, 47, 1, 160, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1280x1024 @ 60Hz */
+		NULL, 60, 1280, 1024, KHZ2PICOS(108000),
+		248, 48, 38, 1, 112, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1280x1024 @ 75Hz */
+		NULL, 75, 1280, 1024, KHZ2PICOS(135000),
+		248, 16, 38, 1, 144, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1280x1024 @ 85Hz */
+		NULL, 85, 1280, 1024, KHZ2PICOS(157500),
+		224, 64, 44, 1, 160, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1600x1200 @ 60Hz */
+		NULL, 60, 1600, 1200, KHZ2PICOS(162000),
+		304, 64, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1600x1200 @ 65Hz */
+		NULL, 65, 1600, 1200, KHZ2PICOS(175500),
+		304, 64, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1600x1200 @ 70Hz */
+		NULL, 70, 1600, 1200, KHZ2PICOS(189000),
+		304, 64, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1600x1200 @ 75Hz */
+		NULL, 75, 1600, 1200, KHZ2PICOS(202500),
+		304, 64, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1600x1200 @ 85Hz */
+		NULL, 85, 1600, 1200, KHZ2PICOS(229500),
+		304, 64, 46, 1, 192, 3,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1792x1344 @ 60Hz */
+		NULL, 60, 1792, 1344, KHZ2PICOS(204750),
+		328, 128, 46, 1, 200, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1792x1344 @ 75Hz */
+		NULL, 75, 1792, 1344, KHZ2PICOS(261000),
+		352, 96, 69, 1, 216, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1856x1392 @ 60Hz */
+		NULL, 60, 1856, 1392, KHZ2PICOS(218250),
+		352, 96, 43, 1, 224, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1856x1392 @ 75Hz */
+		NULL, 75, 1856, 1392, KHZ2PICOS(288000),
+		352, 128, 104, 1, 224, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1920x1440 @ 60Hz */
+		NULL, 60, 1920, 1440, KHZ2PICOS(234000),
+		344, 128, 56, 1, 208, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}, {
+		/* 1920x1440 @ 75Hz */
+		NULL, 75, 1920, 1440, KHZ2PICOS(297000),
+		352, 144, 56, 1, 224, 3,
+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	},
+};
+#define NUM_TOTAL_MODES	ARRAY_SIZE(kyro_modedb)
+
+/*
+ * This needs to be kept ordered corresponding to kyro_modedb.
+ */
+enum {
+	VMODE_640_350_85,
+	VMODE_640_400_85,
+	VMODE_720_400_85,
+	VMODE_640_480_60,
+	VMODE_640_480_72,
+	VMODE_640_480_75,
+	VMODE_640_480_85,
+	VMODE_800_600_56,
+	VMODE_800_600_60,
+	VMODE_800_600_72,
+	VMODE_800_600_75,
+	VMODE_800_600_85,
+	VMODE_1024_768_60,
+	VMODE_1024_768_70,
+	VMODE_1024_768_75,
+	VMODE_1024_768_85,
+	VMODE_1152_864_75,
+	VMODE_1280_960_60,
+	VMODE_1280_960_85,
+	VMODE_1280_1024_60,
+	VMODE_1280_1024_75,
+	VMODE_1280_1024_85,
+	VMODE_1600_1200_60,
+	VMODE_1600_1200_65,
+	VMODE_1600_1200_70,
+	VMODE_1600_1200_75,
+	VMODE_1600_1200_85,
+	VMODE_1792_1344_60,
+	VMODE_1792_1344_75,
+	VMODE_1856_1392_60,
+	VMODE_1856_1392_75,
+	VMODE_1920_1440_60,
+	VMODE_1920_1440_75,
+};
+
+/* Accessors */
+static int kyro_dev_video_mode_set(struct fb_info *info)
+{
+	struct kyrofb_info *par = info->par;
+
+	/* Turn off display */
+	StopVTG(deviceInfo.pSTGReg);
+	DisableRamdacOutput(deviceInfo.pSTGReg);
+
+	/* Bring us out of VGA and into Hi-Res mode, if not already. */
+	DisableVGA(deviceInfo.pSTGReg);
+
+	if (InitialiseRamdac(deviceInfo.pSTGReg,
+			     info->var.bits_per_pixel,
+			     info->var.xres, info->var.yres,
+			     par->HSP, par->VSP, &par->PIXCLK) < 0)
+		return -EINVAL;
+
+	SetupVTG(deviceInfo.pSTGReg, par);
+
+	ResetOverlayRegisters(deviceInfo.pSTGReg);
+
+	/* Turn on display in new mode */
+	EnableRamdacOutput(deviceInfo.pSTGReg);
+	StartVTG(deviceInfo.pSTGReg);
+
+	deviceInfo.ulNextFreeVidMem = info->var.xres * info->var.yres *
+				      info->var.bits_per_pixel;
+	deviceInfo.ulOverlayOffset = 0;
+
+	return 0;
+}
+
+static int kyro_dev_overlay_create(u32 ulWidth,
+				   u32 ulHeight, int bLinear)
+{
+	u32 offset;
+	u32 stride, uvStride;
+
+	if (deviceInfo.ulOverlayOffset != 0)
+		/*
+		 * Can only create one overlay without resetting the card or
+		 * changing display mode
+		 */
+		return -EINVAL;
+
+	ResetOverlayRegisters(deviceInfo.pSTGReg);
+
+	/* Overlays are addressed in multiples of 16bytes or 32bytes, so make
+	 * sure the start offset is on an appropriate boundary.
+	 */
+	offset = deviceInfo.ulNextFreeVidMem;
+	if ((offset & 0x1f) != 0) {
+		offset = (offset + 32L) & 0xffffffE0L;
+	}
+
+	if (CreateOverlaySurface(deviceInfo.pSTGReg, ulWidth, ulHeight,
+				 bLinear, offset, &stride, &uvStride) < 0)
+		return -EINVAL;
+
+	deviceInfo.ulOverlayOffset = offset;
+	deviceInfo.ulOverlayStride = stride;
+	deviceInfo.ulOverlayUVStride = uvStride;
+	deviceInfo.ulNextFreeVidMem = offset + (ulHeight * stride) + (ulHeight * 2 * uvStride);
+
+	SetOverlayBlendMode(deviceInfo.pSTGReg, GLOBAL_ALPHA, 0xf, 0x0);
+
+	return 0;
+}
+
+static int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight)
+{
+	if (deviceInfo.ulOverlayOffset == 0)
+		/* probably haven't called CreateOverlay yet */
+		return -EINVAL;
+
+	/* Stop Ramdac Output */
+	DisableRamdacOutput(deviceInfo.pSTGReg);
+
+	SetOverlayViewPort(deviceInfo.pSTGReg,
+			   x, y, x + ulWidth - 1, y + ulHeight - 1);
+
+	EnableOverlayPlane(deviceInfo.pSTGReg);
+	/* Start Ramdac Output */
+	EnableRamdacOutput(deviceInfo.pSTGReg);
+
+	return 0;
+}
+
+static inline unsigned long get_line_length(int x, int bpp)
+{
+	return (unsigned long)((((x*bpp)+31)&~31) >> 3);
+}
+
+static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct kyrofb_info *par = info->par;
+
+	if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
+		printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 8;
+		break;
+	}
+
+	/* Height/Width of picture in mm */
+	var->height = var->width = -1;
+
+	/* Timing information. All values are in picoseconds */
+
+	/* par->PIXCLK is in 100Hz units. Convert to picoseconds -
+	 * ensuring we do not exceed 32 bit precision
+	 */
+	/*
+	 * XXX: Enabling this really screws over the pixclock value when we
+	 * read it back with fbset. As such, leaving this commented out appears
+	 * to do the right thing (at least for now) .. bearing in mind that we
+	 * have infact already done the KHZ2PICOS conversion in both the modedb
+	 * and kyro_var. -- PFM.
+	 */
+//	var->pixclock = 1000000000 / (par->PIXCLK / 10);
+
+	/* the header file claims we should use picoseconds
+	 * - nobody else does though, the all use pixels and lines
+	 * of h and v sizes. Both options here.
+	 */
+
+	/*
+	 * If we're being called by __fb_try_mode(), then we don't want to
+	 * override any of the var settings that we've already parsed
+	 * from our modedb. -- PFM.
+	 */
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
+		return 0;
+
+	var->left_margin = par->HBP;
+	var->hsync_len = par->HST;
+	var->right_margin = par->HFP;
+
+	var->upper_margin = par->VBP;
+	var->vsync_len = par->VST;
+	var->lower_margin = par->VFP;
+
+	if (par->HSP == 1)
+		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (par->VSP == 1)
+		var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+	return 0;
+}
+
+static int kyrofb_set_par(struct fb_info *info)
+{
+	struct kyrofb_info *par = info->par;
+	unsigned long lineclock;
+	unsigned long frameclock;
+
+	/* Actual resolution */
+	par->XRES = info->var.xres;
+	par->YRES = info->var.yres;
+
+	/* pixel depth */
+	par->PIXDEPTH = info->var.bits_per_pixel;
+
+	/* Refresh rate */
+	/* time for a line in ns */
+	lineclock = (info->var.pixclock * (info->var.xres +
+				    info->var.right_margin +
+				    info->var.hsync_len +
+				    info->var.left_margin)) / 1000;
+
+
+	/* time for a frame in ns (precision in 32bpp) */
+	frameclock = lineclock * (info->var.yres +
+				  info->var.lower_margin +
+				  info->var.vsync_len +
+				  info->var.upper_margin);
+
+	/* Calculate refresh rate and horrizontal clocks */
+	par->VFREQ = (1000000000 + (frameclock / 2)) / frameclock;
+	par->HCLK = (1000000000 + (lineclock / 2)) / lineclock;
+	par->PIXCLK = ((1000000000 + (info->var.pixclock / 2))
+					/ info->var.pixclock) * 10;
+
+	/* calculate horizontal timings */
+	par->HFP = info->var.right_margin;
+	par->HST = info->var.hsync_len;
+	par->HBP = info->var.left_margin;
+	par->HTot = par->XRES + par->HBP + par->HST + par->HFP;
+
+	/* calculate vertical timings */
+	par->VFP = info->var.lower_margin;
+	par->VST = info->var.vsync_len;
+	par->VBP = info->var.upper_margin;
+	par->VTot = par->YRES + par->VBP + par->VST + par->VFP;
+
+	par->HSP = (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0;
+	par->VSP = (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0;
+
+	kyro_dev_video_mode_set(info);
+
+	/* length of a line in bytes    */
+	info->fix.line_length = get_line_length(par->XRES, par->PIXDEPTH);
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	return 0;
+}
+
+static int kyrofb_setcolreg(u_int regno, u_int red, u_int green,
+			    u_int blue, u_int transp, struct fb_info *info)
+{
+	struct kyrofb_info *par = info->par;
+
+	if (regno > 255)
+		return 1;	/* Invalid register */
+
+	if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 16:
+			par->palette[regno] =
+			     (red   & 0xf800) |
+			    ((green & 0xfc00) >> 5) |
+			    ((blue  & 0xf800) >> 11);
+			break;
+		case 32:
+			red >>= 8; green >>= 8; blue >>= 8; transp >>= 8;
+			par->palette[regno] =
+			    (transp << 24) | (red << 16) | (green << 8) | blue;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#ifndef MODULE
+static int __init kyrofb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ","))) {
+		if (!*this_opt)
+			continue;
+		if (strcmp(this_opt, "nopan") == 0) {
+			nopan = 1;
+		} else if (strcmp(this_opt, "nowrap") == 0) {
+			nowrap = 1;
+#ifdef CONFIG_MTRR
+		} else if (strcmp(this_opt, "nomtrr") == 0) {
+			nomtrr = 1;
+#endif
+		} else {
+			mode_option = this_opt;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+static int kyrofb_ioctl(struct fb_info *info,
+			unsigned int cmd, unsigned long arg)
+{
+	overlay_create ol_create;
+	overlay_viewport_set ol_viewport_set;
+	void __user *argp = (void __user *)arg;
+
+	switch (cmd) {
+	case KYRO_IOCTL_OVERLAY_CREATE:
+		if (copy_from_user(&ol_create, argp, sizeof(overlay_create)))
+			return -EFAULT;
+
+		if (kyro_dev_overlay_create(ol_create.ulWidth,
+					    ol_create.ulHeight, 0) < 0) {
+			printk(KERN_ERR "Kyro FB: failed to create overlay surface.\n");
+
+			return -EINVAL;
+		}
+		break;
+	case KYRO_IOCTL_OVERLAY_VIEWPORT_SET:
+		if (copy_from_user(&ol_viewport_set, argp,
+			       sizeof(overlay_viewport_set)))
+			return -EFAULT;
+
+		if (kyro_dev_overlay_viewport_set(ol_viewport_set.xOrgin,
+						  ol_viewport_set.yOrgin,
+						  ol_viewport_set.xSize,
+						  ol_viewport_set.ySize) != 0)
+		{
+			printk(KERN_ERR "Kyro FB: failed to create overlay viewport.\n");
+			return -EINVAL;
+		}
+		break;
+	case KYRO_IOCTL_SET_VIDEO_MODE:
+		{
+			printk(KERN_ERR "Kyro FB: KYRO_IOCTL_SET_VIDEO_MODE is"
+				"obsolete, use the appropriate fb_ioctl()"
+				"command instead.\n");
+			return -EINVAL;
+		}
+	case KYRO_IOCTL_UVSTRIDE:
+		if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
+			return -EFAULT;
+		break;
+	case KYRO_IOCTL_STRIDE:
+		if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
+			return -EFAULT;
+		break;
+	case KYRO_IOCTL_OVERLAY_OFFSET:
+		if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
+			return -EFAULT;
+		break;
+	}
+
+	return 0;
+}
+
+static struct pci_device_id kyrofb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ST, PCI_DEVICE_ID_STG4000,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, kyrofb_pci_tbl);
+
+static struct pci_driver kyrofb_pci_driver = {
+	.name		= "kyrofb",
+	.id_table	= kyrofb_pci_tbl,
+	.probe		= kyrofb_probe,
+	.remove		= kyrofb_remove,
+};
+
+static struct fb_ops kyrofb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= kyrofb_check_var,
+	.fb_set_par	= kyrofb_set_par,
+	.fb_setcolreg	= kyrofb_setcolreg,
+	.fb_ioctl	= kyrofb_ioctl,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct kyrofb_info *currentpar;
+	unsigned long size;
+	int err;
+
+	if ((err = pci_enable_device(pdev))) {
+		printk(KERN_WARNING "kyrofb: Can't enable pdev: %d\n", err);
+		return err;
+	}
+
+	info = framebuffer_alloc(sizeof(struct kyrofb_info), &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	currentpar = info->par;
+
+	kyro_fix.smem_start = pci_resource_start(pdev, 0);
+	kyro_fix.smem_len   = pci_resource_len(pdev, 0);
+	kyro_fix.mmio_start = pci_resource_start(pdev, 1);
+	kyro_fix.mmio_len   = pci_resource_len(pdev, 1);
+
+	currentpar->regbase = deviceInfo.pSTGReg =
+		ioremap_nocache(kyro_fix.mmio_start, kyro_fix.mmio_len);
+
+	info->screen_base = ioremap_nocache(kyro_fix.smem_start,
+					    kyro_fix.smem_len);
+
+#ifdef CONFIG_MTRR
+	if (!nomtrr)
+		currentpar->mtrr_handle =
+			mtrr_add(kyro_fix.smem_start,
+				 kyro_fix.smem_len,
+				 MTRR_TYPE_WRCOMB, 1);
+#endif
+
+	kyro_fix.ypanstep	= nopan ? 0 : 1;
+	kyro_fix.ywrapstep	= nowrap ? 0 : 1;
+
+	info->fbops		= &kyrofb_ops;
+	info->fix		= kyro_fix;
+	info->pseudo_palette	= currentpar->palette;
+	info->flags		= FBINFO_DEFAULT;
+
+	SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
+
+	deviceInfo.ulNextFreeVidMem = 0;
+	deviceInfo.ulOverlayOffset = 0;
+
+	/* This should give a reasonable default video mode */
+	if (!fb_find_mode(&info->var, info, mode_option, kyro_modedb,
+			  NUM_TOTAL_MODES, &kyro_modedb[VMODE_1024_768_75], 32))
+		info->var = kyro_var;
+
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	kyrofb_set_par(info);
+	kyrofb_check_var(&info->var, info);
+
+	size = get_line_length(info->var.xres_virtual,
+			       info->var.bits_per_pixel);
+	size *= info->var.yres_virtual;
+
+	fb_memset(info->screen_base, 0, size);
+
+	if (register_framebuffer(info) < 0)
+		goto out_unmap;
+
+	fb_info(info, "%s frame buffer device, at %dx%d@%d using %ldk/%ldk of VRAM\n",
+		info->fix.id,
+		info->var.xres, info->var.yres, info->var.bits_per_pixel,
+		size >> 10, (unsigned long)info->fix.smem_len >> 10);
+
+	pci_set_drvdata(pdev, info);
+
+	return 0;
+
+out_unmap:
+	iounmap(currentpar->regbase);
+	iounmap(info->screen_base);
+	framebuffer_release(info);
+
+	return -EINVAL;
+}
+
+static void kyrofb_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct kyrofb_info *par = info->par;
+
+	/* Reset the board */
+	StopVTG(deviceInfo.pSTGReg);
+	DisableRamdacOutput(deviceInfo.pSTGReg);
+
+	/* Sync up the PLL */
+	SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
+
+	deviceInfo.ulNextFreeVidMem = 0;
+	deviceInfo.ulOverlayOffset = 0;
+
+	iounmap(info->screen_base);
+	iounmap(par->regbase);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr_handle)
+		mtrr_del(par->mtrr_handle,
+			 info->fix.smem_start,
+			 info->fix.smem_len);
+#endif
+
+	unregister_framebuffer(info);
+	framebuffer_release(info);
+}
+
+static int __init kyrofb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("kyrofb", &option))
+		return -ENODEV;
+	kyrofb_setup(option);
+#endif
+	return pci_register_driver(&kyrofb_pci_driver);
+}
+
+static void __exit kyrofb_exit(void)
+{
+	pci_unregister_driver(&kyrofb_pci_driver);
+}
+
+module_init(kyrofb_init);
+
+#ifdef MODULE
+module_exit(kyrofb_exit);
+#endif
+
+MODULE_AUTHOR("STMicroelectronics; Paul Mundt <lethal@linux-sh.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/leo.c b/drivers/video/fbdev/leo.c
new file mode 100644
index 000000000000..2c7f7d479fe2
--- /dev/null
+++ b/drivers/video/fbdev/leo.c
@@ -0,0 +1,691 @@
+/* leo.c: LEO frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/of_device.h>
+#include <linux/io.h>
+
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int leo_blank(int, struct fb_info *);
+
+static int leo_mmap(struct fb_info *, struct vm_area_struct *);
+static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
+static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops leo_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= leo_setcolreg,
+	.fb_blank		= leo_blank,
+	.fb_pan_display		= leo_pan_display,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= leo_mmap,
+	.fb_ioctl		= leo_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+#define LEO_OFF_LC_SS0_KRN	0x00200000UL
+#define LEO_OFF_LC_SS0_USR	0x00201000UL
+#define LEO_OFF_LC_SS1_KRN	0x01200000UL
+#define LEO_OFF_LC_SS1_USR	0x01201000UL
+#define LEO_OFF_LD_SS0		0x00400000UL
+#define LEO_OFF_LD_SS1		0x01400000UL
+#define LEO_OFF_LD_GBL		0x00401000UL
+#define LEO_OFF_LX_KRN		0x00600000UL
+#define LEO_OFF_LX_CURSOR	0x00601000UL
+#define LEO_OFF_SS0		0x00800000UL
+#define LEO_OFF_SS1		0x01800000UL
+#define LEO_OFF_UNK		0x00602000UL
+#define LEO_OFF_UNK2		0x00000000UL
+
+#define LEO_CUR_ENABLE		0x00000080
+#define LEO_CUR_UPDATE		0x00000030
+#define LEO_CUR_PROGRESS	0x00000006
+#define LEO_CUR_UPDATECMAP	0x00000003
+
+#define LEO_CUR_TYPE_MASK	0x00000000
+#define LEO_CUR_TYPE_IMAGE	0x00000020
+#define LEO_CUR_TYPE_CMAP	0x00000050
+
+struct leo_cursor {
+	u8	xxx0[16];
+	u32	cur_type;
+	u32	cur_misc;
+	u32	cur_cursxy;
+	u32	cur_data;
+};
+
+#define LEO_KRN_TYPE_CLUT0	0x00001000
+#define LEO_KRN_TYPE_CLUT1	0x00001001
+#define LEO_KRN_TYPE_CLUT2	0x00001002
+#define LEO_KRN_TYPE_WID	0x00001003
+#define LEO_KRN_TYPE_UNK	0x00001006
+#define LEO_KRN_TYPE_VIDEO	0x00002003
+#define LEO_KRN_TYPE_CLUTDATA	0x00004000
+#define LEO_KRN_CSR_ENABLE	0x00000008
+#define LEO_KRN_CSR_PROGRESS	0x00000004
+#define LEO_KRN_CSR_UNK		0x00000002
+#define LEO_KRN_CSR_UNK2	0x00000001
+
+struct leo_lx_krn {
+	u32	krn_type;
+	u32	krn_csr;
+	u32	krn_value;
+};
+
+struct leo_lc_ss0_krn {
+	u32 	misc;
+	u8	xxx0[0x800-4];
+	u32	rev;
+};
+
+struct leo_lc_ss0_usr {
+	u32	csr;
+	u32	addrspace;
+	u32 	fontmsk;
+	u32	fontt;
+	u32	extent;
+	u32	src;
+	u32	dst;
+	u32	copy;
+	u32	fill;
+};
+
+struct leo_lc_ss1_krn {
+	u8	unknown;
+};
+
+struct leo_lc_ss1_usr {
+	u8	unknown;
+};
+
+struct leo_ld_ss0 {
+	u8	xxx0[0xe00];
+	u32	csr;
+	u32	wid;
+	u32	wmask;
+	u32	widclip;
+	u32	vclipmin;
+	u32	vclipmax;
+	u32	pickmin;	/* SS1 only */
+	u32	pickmax;	/* SS1 only */
+	u32	fg;
+	u32	bg;
+	u32	src;		/* Copy/Scroll (SS0 only) */
+	u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
+	u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
+	u32	xxx1[3];
+	u32	setsem;		/* SS1 only */
+	u32	clrsem;		/* SS1 only */
+	u32	clrpick;	/* SS1 only */
+	u32	clrdat;		/* SS1 only */
+	u32	alpha;		/* SS1 only */
+	u8	xxx2[0x2c];
+	u32	winbg;
+	u32	planemask;
+	u32	rop;
+	u32	z;
+	u32	dczf;		/* SS1 only */
+	u32	dczb;		/* SS1 only */
+	u32	dcs;		/* SS1 only */
+	u32	dczs;		/* SS1 only */
+	u32	pickfb;		/* SS1 only */
+	u32	pickbb;		/* SS1 only */
+	u32	dcfc;		/* SS1 only */
+	u32	forcecol;	/* SS1 only */
+	u32	door[8];	/* SS1 only */
+	u32	pick[5];	/* SS1 only */
+};
+
+#define LEO_SS1_MISC_ENABLE	0x00000001
+#define LEO_SS1_MISC_STEREO	0x00000002
+struct leo_ld_ss1 {
+	u8	xxx0[0xef4];
+	u32	ss1_misc;
+};
+
+struct leo_ld_gbl {
+	u8	unknown;
+};
+
+struct leo_par {
+	spinlock_t		lock;
+	struct leo_lx_krn	__iomem *lx_krn;
+	struct leo_lc_ss0_usr	__iomem *lc_ss0_usr;
+	struct leo_ld_ss0	__iomem *ld_ss0;
+	struct leo_ld_ss1	__iomem *ld_ss1;
+	struct leo_cursor	__iomem *cursor;
+	u32			extent;
+	u32			clut_data[256];
+
+	u32			flags;
+#define LEO_FLAG_BLANKED	0x00000001
+
+	unsigned long		which_io;
+};
+
+static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
+{
+	int i;
+
+	for (i = 0;
+	     (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) &&
+	     i < 300000;
+	     i++)
+		udelay(1); /* Busy wait at most 0.3 sec */
+	return;
+}
+
+static void leo_switch_from_graph(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
+	struct leo_cursor __iomem *cursor = par->cursor;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	par->extent = ((info->var.xres - 1) |
+		       ((info->var.yres - 1) << 16));
+
+	sbus_writel(0xffffffff, &ss->wid);
+	sbus_writel(0xffff, &ss->wmask);
+	sbus_writel(0, &ss->vclipmin);
+	sbus_writel(par->extent, &ss->vclipmax);
+	sbus_writel(0, &ss->fg);
+	sbus_writel(0xff000000, &ss->planemask);
+	sbus_writel(0x310850, &ss->rop);
+	sbus_writel(0, &ss->widclip);
+	sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
+		    &par->lc_ss0_usr->extent);
+	sbus_writel(4, &par->lc_ss0_usr->addrspace);
+	sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
+	sbus_writel(0, &par->lc_ss0_usr->fontt);
+	do {
+		val = sbus_readl(&par->lc_ss0_usr->csr);
+	} while (val & 0x20000000);
+
+	/* setup screen buffer for cfb_* functions */
+	sbus_writel(1, &ss->wid);
+	sbus_writel(0x00ffffff, &ss->planemask);
+	sbus_writel(0x310b90, &ss->rop);
+	sbus_writel(0, &par->lc_ss0_usr->addrspace);
+
+	/* hide cursor */
+	sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	/* We just use this to catch switches out of
+	 * graphics mode.
+	 */
+	leo_switch_from_graph(info);
+
+	if (var->xoffset || var->yoffset || var->vmode)
+		return -EINVAL;
+	return 0;
+}
+
+/**
+ *      leo_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int leo_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+	int i;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	par->clut_data[regno] = red | (green << 8) | (blue << 16);
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
+	for (i = 0; i < 256; i++)
+		sbus_writel(par->clut_data[i], &lx_krn->krn_value);
+	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *      leo_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int leo_blank(int blank, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val |= LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags &= ~LEO_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val &= ~LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags |= LEO_FLAG_BLANKED;
+		break;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map leo_mmap_map[] = {
+	{
+		.voff	= LEO_SS0_MAP,
+		.poff	= LEO_OFF_SS0,
+		.size	= 0x800000
+	},
+	{
+		.voff	= LEO_LC_SS0_USR_MAP,
+		.poff	= LEO_OFF_LC_SS0_USR,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_LD_SS0_MAP,
+		.poff	= LEO_OFF_LD_SS0,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_LX_CURSOR_MAP,
+		.poff	= LEO_OFF_LX_CURSOR,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_SS1_MAP,
+		.poff	= LEO_OFF_SS1,
+		.size	= 0x800000
+	},
+	{
+		.voff	= LEO_LC_SS1_USR_MAP,
+		.poff	= LEO_OFF_LC_SS1_USR,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_LD_SS1_MAP,
+		.poff	= LEO_OFF_LD_SS1,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_UNK_MAP,
+		.poff	= LEO_OFF_UNK,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_LX_KRN_MAP,
+		.poff	= LEO_OFF_LX_KRN,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_LC_SS0_KRN_MAP,
+		.poff	= LEO_OFF_LC_SS0_KRN,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_LC_SS1_KRN_MAP,
+		.poff	= LEO_OFF_LC_SS1_KRN,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_LD_GBL_MAP,
+		.poff	= LEO_OFF_LD_GBL,
+		.size	= 0x1000
+	},
+	{
+		.voff	= LEO_UNK2_MAP,
+		.poff	= LEO_OFF_UNK2,
+		.size	= 0x100000
+	},
+	{ .size = 0 }
+};
+
+static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct leo_par *par = (struct leo_par *)info->par;
+
+	return sbusfb_mmap_helper(leo_mmap_map,
+				  info->fix.smem_start, info->fix.smem_len,
+				  par->which_io, vma);
+}
+
+static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUNLEO, 32, info->fix.smem_len);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+leo_init_fix(struct fb_info *info, struct device_node *dp)
+{
+	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	info->fix.line_length = 8192;
+
+	info->fix.accel = FB_ACCEL_SUN_LEO;
+}
+
+static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
+	struct fb_wid_item *wi;
+	unsigned long flags;
+	u32 val;
+	int i, j;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
+		switch (wi->wi_type) {
+		case FB_WID_DBL_8:
+			j = (wi->wi_index & 0xf) + 0x40;
+			break;
+
+		case FB_WID_DBL_24:
+			j = wi->wi_index & 0x3f;
+			break;
+
+		default:
+			continue;
+		}
+		sbus_writel(0x5800 + j, &lx_krn->krn_type);
+		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
+	}
+	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static void leo_init_wids(struct fb_info *info)
+{
+	struct fb_wid_item wi;
+	struct fb_wid_list wl;
+
+	wl.wl_count = 1;
+	wl.wl_list = &wi;
+	wi.wi_type = FB_WID_DBL_8;
+	wi.wi_index = 0;
+	wi.wi_values [0] = 0x2c0;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 2;
+	wi.wi_values [0] = 0x20;
+	leo_wid_put(info, &wl);
+	wi.wi_type = FB_WID_DBL_24;
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+}
+
+static void leo_init_hw(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	u32 val;
+
+	val = sbus_readl(&par->ld_ss1->ss1_misc);
+	val |= LEO_SS1_MISC_ENABLE;
+	sbus_writel(val, &par->ld_ss1->ss1_misc);
+
+	leo_switch_from_graph(info);
+}
+
+static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
+{
+	var->red.offset = 0;
+	var->red.length = 8;
+	var->green.offset = 8;
+	var->green.length = 8;
+	var->blue.offset = 16;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+}
+
+static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
+			   struct leo_par *par)
+{
+	if (par->lc_ss0_usr)
+		of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000);
+	if (par->ld_ss0)
+		of_iounmap(&op->resource[0], par->ld_ss0, 0x1000);
+	if (par->ld_ss1)
+		of_iounmap(&op->resource[0], par->ld_ss1, 0x1000);
+	if (par->lx_krn)
+		of_iounmap(&op->resource[0], par->lx_krn, 0x1000);
+	if (par->cursor)
+		of_iounmap(&op->resource[0],
+			   par->cursor, sizeof(struct leo_cursor));
+	if (info->screen_base)
+		of_iounmap(&op->resource[0], info->screen_base, 0x800000);
+}
+
+static int leo_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct leo_par *par;
+	int linebytes, err;
+
+	info = framebuffer_alloc(sizeof(struct leo_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+
+	info->fix.smem_start = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+	sbusfb_fill_var(&info->var, dp, 32);
+	leo_fixup_var_rgb(&info->var);
+
+	linebytes = of_getintprop_default(dp, "linebytes",
+					  info->var.xres);
+	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
+
+	par->lc_ss0_usr =
+		of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
+			   0x1000, "leolc ss0usr");
+	par->ld_ss0 =
+		of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
+			   0x1000, "leold ss0");
+	par->ld_ss1 =
+		of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
+			   0x1000, "leold ss1");
+	par->lx_krn =
+		of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
+			   0x1000, "leolx krn");
+	par->cursor =
+		of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
+			   sizeof(struct leo_cursor), "leolx cursor");
+	info->screen_base =
+		of_ioremap(&op->resource[0], LEO_OFF_SS0,
+			   0x800000, "leo ram");
+	if (!par->lc_ss0_usr ||
+	    !par->ld_ss0 ||
+	    !par->ld_ss1 ||
+	    !par->lx_krn ||
+	    !par->cursor ||
+	    !info->screen_base)
+		goto out_unmap_regs;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &leo_ops;
+	info->pseudo_palette = par->clut_data;
+
+	leo_init_wids(info);
+	leo_init_hw(info);
+
+	leo_blank(FB_BLANK_UNBLANK, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
+
+	leo_init_fix(info, dp);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: leo at %lx:%lx\n",
+	       dp->full_name,
+	       par->which_io, info->fix.smem_start);
+
+	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	leo_unmap_regs(op, info, par);
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int leo_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct leo_par *par = info->par;
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	leo_unmap_regs(op, info, par);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id leo_match[] = {
+	{
+		.name = "SUNW,leo",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, leo_match);
+
+static struct platform_driver leo_driver = {
+	.driver = {
+		.name = "leo",
+		.owner = THIS_MODULE,
+		.of_match_table = leo_match,
+	},
+	.probe		= leo_probe,
+	.remove		= leo_remove,
+};
+
+static int __init leo_init(void)
+{
+	if (fb_get_options("leofb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&leo_driver);
+}
+
+static void __exit leo_exit(void)
+{
+	platform_driver_unregister(&leo_driver);
+}
+
+module_init(leo_init);
+module_exit(leo_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/macfb.c b/drivers/video/fbdev/macfb.c
new file mode 100644
index 000000000000..cda7587cbc86
--- /dev/null
+++ b/drivers/video/fbdev/macfb.c
@@ -0,0 +1,928 @@
+/*
+ * macfb.c: Generic framebuffer for Macs whose colourmaps/modes we
+ * don't know how to set.
+ *
+ * (c) 1999 David Huggins-Daines <dhd@debian.org>
+ *
+ * Primarily based on vesafb.c, by Gerd Knorr
+ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * Also uses information and code from:
+ *
+ * The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen
+ * Mellinger, Mikael Forselius, Michael Schmitz, and others.
+ *
+ * valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan
+ * Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven.
+ *
+ * The VideoToolbox "Bugs" web page at
+ * http://rajsky.psych.nyu.edu/Tips/VideoBugs.html
+ *
+ * This code is free software.  You may copy, modify, and distribute
+ * it subject to the terms and conditions of the GNU General Public
+ * License, version 2, or any later version, at your convenience.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/nubus.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+#include <asm/macintosh.h>
+#include <asm/io.h>
+
+/* Common DAC base address for the LC, RBV, Valkyrie, and IIvx */
+#define DAC_BASE 0x50f24000
+
+/* Some addresses for the DAFB */
+#define DAFB_BASE 0xf9800200
+
+/* Address for the built-in Civic framebuffer in Quadra AVs */
+#define CIVIC_BASE 0x50f30800
+
+/* GSC (Gray Scale Controller) base address */
+#define GSC_BASE 0x50F20000
+
+/* CSC (Color Screen Controller) base address */
+#define CSC_BASE 0x50F20000
+
+static int (*macfb_setpalette)(unsigned int regno, unsigned int red,
+			       unsigned int green, unsigned int blue,
+			       struct fb_info *info);
+
+static struct {
+	unsigned char addr;
+	unsigned char lut;
+} __iomem *v8_brazil_cmap_regs;
+
+static struct {
+	unsigned char addr;
+	char pad1[3]; /* word aligned */
+	unsigned char lut;
+	char pad2[3]; /* word aligned */
+	unsigned char cntl; /* a guess as to purpose */
+} __iomem *rbv_cmap_regs;
+
+static struct {
+	unsigned long reset;
+	unsigned long pad1[3];
+	unsigned char pad2[3];
+	unsigned char lut;
+} __iomem *dafb_cmap_regs;
+
+static struct {
+	unsigned char addr;	/* OFFSET: 0x00 */
+	unsigned char pad1[15];
+	unsigned char lut;	/* OFFSET: 0x10 */
+	unsigned char pad2[15];
+	unsigned char status;	/* OFFSET: 0x20 */
+	unsigned char pad3[7];
+	unsigned long vbl_addr;	/* OFFSET: 0x28 */
+	unsigned int  status2;	/* OFFSET: 0x2C */
+} __iomem *civic_cmap_regs;
+
+static struct {
+	char pad1[0x40];
+	unsigned char clut_waddr;	/* 0x40 */
+	char pad2;
+	unsigned char clut_data;	/* 0x42 */
+	char pad3[0x3];
+	unsigned char clut_raddr;	/* 0x46 */
+} __iomem *csc_cmap_regs;
+
+/* The registers in these structs are in NuBus slot space */
+struct mdc_cmap_regs {
+	char pad1[0x200200];
+	unsigned char addr;
+	char pad2[6];
+	unsigned char lut;
+};
+
+struct toby_cmap_regs {
+	char pad1[0x90018];
+	unsigned char lut; /* TFBClutWDataReg, offset 0x90018 */
+	char pad2[3];
+	unsigned char addr; /* TFBClutAddrReg, offset 0x9001C */
+};
+
+struct jet_cmap_regs {
+	char pad1[0xe0e000];
+	unsigned char addr;
+	unsigned char lut;
+};
+
+#define PIXEL_TO_MM(a)	(((a)*10)/28)	/* width in mm at 72 dpi */
+
+static struct fb_var_screeninfo macfb_defined = {
+	.bits_per_pixel	= 8,
+	.activate	= FB_ACTIVATE_NOW,
+	.width		= -1,
+	.height		= -1,
+	.right_margin	= 32,
+	.upper_margin	= 16,
+	.lower_margin	= 4,
+	.vsync_len	= 4,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo macfb_fix = {
+	.type	= FB_TYPE_PACKED_PIXELS,
+	.accel	= FB_ACCEL_NONE,
+};
+
+static void *slot_addr;
+static struct fb_info fb_info;
+static u32 pseudo_palette[16];
+static int inverse;
+static int vidtest;
+
+/*
+ * Unlike the Valkyrie, the DAFB cannot set individual colormap
+ * registers.  Therefore, we do what the MacOS driver does (no
+ * kidding!) and simply set them one by one until we hit the one we
+ * want.
+ */
+static int dafb_setpalette(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   struct fb_info *info)
+{
+	static int lastreg = -1;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/*
+	 * fbdev will set an entire colourmap, but X won't.  Hopefully
+	 * this should accommodate both of them
+	 */
+	if (regno != lastreg + 1) {
+		int i;
+
+		/* Stab in the dark trying to reset the CLUT pointer */
+		nubus_writel(0, &dafb_cmap_regs->reset);
+		nop();
+
+		/* Loop until we get to the register we want */
+		for (i = 0; i < regno; i++) {
+			nubus_writeb(info->cmap.red[i] >> 8,
+				     &dafb_cmap_regs->lut);
+			nop();
+			nubus_writeb(info->cmap.green[i] >> 8,
+				     &dafb_cmap_regs->lut);
+			nop();
+			nubus_writeb(info->cmap.blue[i] >> 8,
+				     &dafb_cmap_regs->lut);
+			nop();
+		}
+	}
+
+	nubus_writeb(red, &dafb_cmap_regs->lut);
+	nop();
+	nubus_writeb(green, &dafb_cmap_regs->lut);
+	nop();
+	nubus_writeb(blue, &dafb_cmap_regs->lut);
+
+	local_irq_restore(flags);
+	lastreg = regno;
+	return 0;
+}
+
+/* V8 and Brazil seem to use the same DAC.  Sonora does as well. */
+static int v8_brazil_setpalette(unsigned int regno, unsigned int red,
+				unsigned int green, unsigned int blue,
+				struct fb_info *info)
+{
+	unsigned int bpp = info->var.bits_per_pixel;
+	unsigned long flags;
+
+	if (bpp > 8)
+		return 1; /* failsafe */
+
+	local_irq_save(flags);
+
+	/* On these chips, the CLUT register numbers are spread out
+	 * across the register space.  Thus:
+	 * In 8bpp, all regnos are valid.
+	 * In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc
+	 * In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff
+	 */
+	regno = (regno << (8 - bpp)) | (0xFF >> bpp);
+	nubus_writeb(regno, &v8_brazil_cmap_regs->addr);
+	nop();
+
+	/* send one color channel at a time */
+	nubus_writeb(red, &v8_brazil_cmap_regs->lut);
+	nop();
+	nubus_writeb(green, &v8_brazil_cmap_regs->lut);
+	nop();
+	nubus_writeb(blue, &v8_brazil_cmap_regs->lut);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* RAM-Based Video */
+static int rbv_setpalette(unsigned int regno, unsigned int red,
+			  unsigned int green, unsigned int blue,
+			  struct fb_info *info)
+{
+	unsigned long flags;
+
+	if (info->var.bits_per_pixel > 8)
+		return 1; /* failsafe */
+
+	local_irq_save(flags);
+
+	/* From the VideoToolbox driver.  Seems to be saying that
+	 * regno #254 and #255 are the important ones for 1-bit color,
+	 * regno #252-255 are the important ones for 2-bit color, etc.
+	 */
+	regno += 256 - (1 << info->var.bits_per_pixel);
+
+	/* reset clut? (VideoToolbox sez "not necessary") */
+	nubus_writeb(0xFF, &rbv_cmap_regs->cntl);
+	nop();
+
+	/* tell clut which address to use. */
+	nubus_writeb(regno, &rbv_cmap_regs->addr);
+	nop();
+
+	/* send one color channel at a time. */
+	nubus_writeb(red, &rbv_cmap_regs->lut);
+	nop();
+	nubus_writeb(green, &rbv_cmap_regs->lut);
+	nop();
+	nubus_writeb(blue, &rbv_cmap_regs->lut);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* Macintosh Display Card (8*24) */
+static int mdc_setpalette(unsigned int regno, unsigned int red,
+			  unsigned int green, unsigned int blue,
+			  struct fb_info *info)
+{
+	struct mdc_cmap_regs *cmap_regs = slot_addr;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* the nop's are there to order writes. */
+	nubus_writeb(regno, &cmap_regs->addr);
+	nop();
+	nubus_writeb(red, &cmap_regs->lut);
+	nop();
+	nubus_writeb(green, &cmap_regs->lut);
+	nop();
+	nubus_writeb(blue, &cmap_regs->lut);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* Toby frame buffer */
+static int toby_setpalette(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   struct fb_info *info)
+{
+	struct toby_cmap_regs *cmap_regs = slot_addr;
+	unsigned int bpp = info->var.bits_per_pixel;
+	unsigned long flags;
+
+	red = ~red;
+	green = ~green;
+	blue = ~blue;
+	regno = (regno << (8 - bpp)) | (0xFF >> bpp);
+
+	local_irq_save(flags);
+
+	nubus_writeb(regno, &cmap_regs->addr);
+	nop();
+	nubus_writeb(red, &cmap_regs->lut);
+	nop();
+	nubus_writeb(green, &cmap_regs->lut);
+	nop();
+	nubus_writeb(blue, &cmap_regs->lut);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* Jet frame buffer */
+static int jet_setpalette(unsigned int regno, unsigned int red,
+			  unsigned int green, unsigned int blue,
+			  struct fb_info *info)
+{
+	struct jet_cmap_regs *cmap_regs = slot_addr;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	nubus_writeb(regno, &cmap_regs->addr);
+	nop();
+	nubus_writeb(red, &cmap_regs->lut);
+	nop();
+	nubus_writeb(green, &cmap_regs->lut);
+	nop();
+	nubus_writeb(blue, &cmap_regs->lut);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/*
+ * Civic framebuffer -- Quadra AV built-in video.  A chip
+ * called Sebastian holds the actual color palettes, and
+ * apparently, there are two different banks of 512K RAM
+ * which can act as separate framebuffers for doing video
+ * input and viewing the screen at the same time!  The 840AV
+ * Can add another 1MB RAM to give the two framebuffers
+ * 1MB RAM apiece.
+ */
+static int civic_setpalette(unsigned int regno, unsigned int red,
+			    unsigned int green, unsigned int blue,
+			    struct fb_info *info)
+{
+	unsigned long flags;
+	int clut_status;
+	
+	if (info->var.bits_per_pixel > 8)
+		return 1; /* failsafe */
+
+	local_irq_save(flags);
+
+	/* Set the register address */
+	nubus_writeb(regno, &civic_cmap_regs->addr);
+	nop();
+
+	/*
+	 * Grab a status word and do some checking;
+	 * Then finally write the clut!
+	 */
+	clut_status =  nubus_readb(&civic_cmap_regs->status2);
+
+	if ((clut_status & 0x0008) == 0)
+	{
+#if 0
+		if ((clut_status & 0x000D) != 0)
+		{
+			nubus_writeb(0x00, &civic_cmap_regs->lut);
+			nop();
+			nubus_writeb(0x00, &civic_cmap_regs->lut);
+			nop();
+		}
+#endif
+
+		nubus_writeb(red, &civic_cmap_regs->lut);
+		nop();
+		nubus_writeb(green, &civic_cmap_regs->lut);
+		nop();
+		nubus_writeb(blue, &civic_cmap_regs->lut);
+		nop();
+		nubus_writeb(0x00, &civic_cmap_regs->lut);
+	}
+	else
+	{
+		unsigned char junk;
+
+		junk = nubus_readb(&civic_cmap_regs->lut);
+		nop();
+		junk = nubus_readb(&civic_cmap_regs->lut);
+		nop();
+		junk = nubus_readb(&civic_cmap_regs->lut);
+		nop();
+		junk = nubus_readb(&civic_cmap_regs->lut);
+		nop();
+
+		if ((clut_status & 0x000D) != 0)
+		{
+			nubus_writeb(0x00, &civic_cmap_regs->lut);
+			nop();
+			nubus_writeb(0x00, &civic_cmap_regs->lut);
+			nop();
+		}
+
+		nubus_writeb(red, &civic_cmap_regs->lut);
+		nop();
+		nubus_writeb(green, &civic_cmap_regs->lut);
+		nop();
+		nubus_writeb(blue, &civic_cmap_regs->lut);
+		nop();
+		nubus_writeb(junk, &civic_cmap_regs->lut);
+	}
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/*
+ * The CSC is the framebuffer on the PowerBook 190 series
+ * (and the 5300 too, but that's a PowerMac). This function
+ * brought to you in part by the ECSC driver for MkLinux.
+ */
+static int csc_setpalette(unsigned int regno, unsigned int red,
+			  unsigned int green, unsigned int blue,
+			  struct fb_info *info)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	udelay(1); /* mklinux on PB 5300 waits for 260 ns */
+	nubus_writeb(regno, &csc_cmap_regs->clut_waddr);
+	nubus_writeb(red, &csc_cmap_regs->clut_data);
+	nubus_writeb(green, &csc_cmap_regs->clut_data);
+	nubus_writeb(blue, &csc_cmap_regs->clut_data);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *fb_info)
+{
+	/*
+	 * Set a single color register. The values supplied are
+	 * already rounded down to the hardware's capabilities
+	 * (according to the entries in the `var' structure).
+	 * Return non-zero for invalid regno.
+	 */
+	
+	if (regno >= fb_info->cmap.len)
+		return 1;
+
+	if (fb_info->var.bits_per_pixel <= 8) {
+		switch (fb_info->var.bits_per_pixel) {
+		case 1:
+			/* We shouldn't get here */
+			break;
+		case 2:
+		case 4:
+		case 8:
+			if (macfb_setpalette)
+				macfb_setpalette(regno, red >> 8, green >> 8,
+						 blue >> 8, fb_info);
+			else
+				return 1;
+			break;
+		}
+	} else if (regno < 16) {
+		switch (fb_info->var.bits_per_pixel) {
+		case 16:
+			if (fb_info->var.red.offset == 10) {
+				/* 1:5:5:5 */
+				((u32*) (fb_info->pseudo_palette))[regno] =
+					((red   & 0xf800) >>  1) |
+					((green & 0xf800) >>  6) |
+					((blue  & 0xf800) >> 11) |
+					((transp != 0) << 15);
+			} else {
+				/* 0:5:6:5 */
+				((u32*) (fb_info->pseudo_palette))[regno] =
+					((red   & 0xf800) >>  0) |
+					((green & 0xfc00) >>  5) |
+					((blue  & 0xf800) >> 11);
+			}
+			break;
+		/*
+		 * 24-bit colour almost doesn't exist on 68k Macs --
+		 * http://support.apple.com/kb/TA28634 (Old Article: 10992)
+		 */
+		case 24:
+		case 32:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((u32 *)(fb_info->pseudo_palette))[regno] =
+				(red   << fb_info->var.red.offset) |
+				(green << fb_info->var.green.offset) |
+				(blue  << fb_info->var.blue.offset);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static struct fb_ops macfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= macfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static void __init macfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+
+		if (!strcmp(this_opt, "inverse"))
+			inverse = 1;
+		else
+			if (!strcmp(this_opt, "vidtest"))
+				vidtest = 1; /* enable experimental CLUT code */
+	}
+}
+
+static void __init iounmap_macfb(void)
+{
+	if (dafb_cmap_regs)
+		iounmap(dafb_cmap_regs);
+	if (v8_brazil_cmap_regs)
+		iounmap(v8_brazil_cmap_regs);
+	if (rbv_cmap_regs)
+		iounmap(rbv_cmap_regs);
+	if (civic_cmap_regs)
+		iounmap(civic_cmap_regs);
+	if (csc_cmap_regs)
+		iounmap(csc_cmap_regs);
+}
+
+static int __init macfb_init(void)
+{
+	int video_cmap_len, video_is_nubus = 0;
+	struct nubus_dev* ndev = NULL;
+	char *option = NULL;
+	int err;
+
+	if (fb_get_options("macfb", &option))
+		return -ENODEV;
+	macfb_setup(option);
+
+	if (!MACH_IS_MAC) 
+		return -ENODEV;
+
+	if (mac_bi_data.id == MAC_MODEL_Q630 ||
+	    mac_bi_data.id == MAC_MODEL_P588)
+		return -ENODEV; /* See valkyriefb.c */
+
+	macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF;
+	macfb_defined.yres = mac_bi_data.dimensions >> 16;
+	macfb_defined.bits_per_pixel = mac_bi_data.videodepth;
+
+	macfb_fix.line_length = mac_bi_data.videorow;
+	macfb_fix.smem_len    = macfb_fix.line_length * macfb_defined.yres;
+	/* Note: physical address (since 2.1.127) */
+	macfb_fix.smem_start  = mac_bi_data.videoaddr;
+
+	/*
+	 * This is actually redundant with the initial mappings.
+	 * However, there are some non-obvious aspects to the way
+	 * those mappings are set up, so this is in fact the safest
+	 * way to ensure that this driver will work on every possible Mac
+	 */
+	fb_info.screen_base = ioremap(mac_bi_data.videoaddr,
+				      macfb_fix.smem_len);
+	if (!fb_info.screen_base)
+		return -ENODEV;
+
+	pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
+	        macfb_fix.smem_start, fb_info.screen_base,
+	        macfb_fix.smem_len / 1024);
+	pr_info("macfb: mode is %dx%dx%d, linelength=%d\n",
+	        macfb_defined.xres, macfb_defined.yres,
+	        macfb_defined.bits_per_pixel, macfb_fix.line_length);
+
+	/* Fill in the available video resolution */
+	macfb_defined.xres_virtual = macfb_defined.xres;
+	macfb_defined.yres_virtual = macfb_defined.yres;
+	macfb_defined.height       = PIXEL_TO_MM(macfb_defined.yres);
+	macfb_defined.width        = PIXEL_TO_MM(macfb_defined.xres);
+
+	/* Some dummy values for timing to make fbset happy */
+	macfb_defined.pixclock     = 10000000 / macfb_defined.xres *
+				     1000 / macfb_defined.yres;
+	macfb_defined.left_margin  = (macfb_defined.xres / 8) & 0xf8;
+	macfb_defined.hsync_len    = (macfb_defined.xres / 8) & 0xf8;
+
+	switch (macfb_defined.bits_per_pixel) {
+	case 1:
+		macfb_defined.red.length = macfb_defined.bits_per_pixel;
+		macfb_defined.green.length = macfb_defined.bits_per_pixel;
+		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
+		video_cmap_len = 2;
+		macfb_fix.visual = FB_VISUAL_MONO01;
+		break;
+	case 2:
+	case 4:
+	case 8:
+		macfb_defined.red.length = macfb_defined.bits_per_pixel;
+		macfb_defined.green.length = macfb_defined.bits_per_pixel;
+		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
+		video_cmap_len = 1 << macfb_defined.bits_per_pixel;
+		macfb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 16:
+		macfb_defined.transp.offset = 15;
+		macfb_defined.transp.length = 1;
+		macfb_defined.red.offset = 10;
+		macfb_defined.red.length = 5;
+		macfb_defined.green.offset = 5;
+		macfb_defined.green.length = 5;
+		macfb_defined.blue.offset = 0;
+		macfb_defined.blue.length = 5;
+		video_cmap_len = 16;
+		/*
+		 * Should actually be FB_VISUAL_DIRECTCOLOR, but this
+		 * works too
+		 */
+		macfb_fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 24:
+	case 32:
+		macfb_defined.red.offset = 16;
+		macfb_defined.red.length = 8;
+		macfb_defined.green.offset = 8;
+		macfb_defined.green.length = 8;
+		macfb_defined.blue.offset = 0;
+		macfb_defined.blue.length = 8;
+		video_cmap_len = 16;
+		macfb_fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	default:
+		pr_err("macfb: unknown or unsupported bit depth: %d\n",
+		       macfb_defined.bits_per_pixel);
+		err = -EINVAL;
+		goto fail_unmap;
+	}
+	
+	/*
+	 * We take a wild guess that if the video physical address is
+	 * in nubus slot space, that the nubus card is driving video.
+	 * Penguin really ought to tell us whether we are using internal
+	 * video or not.
+	 * Hopefully we only find one of them.  Otherwise our NuBus
+	 * code is really broken :-)
+	 */
+
+	while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY,
+				       NUBUS_TYPE_VIDEO, ndev)))
+	{
+		unsigned long base = ndev->board->slot_addr;
+
+		if (mac_bi_data.videoaddr < base ||
+		    mac_bi_data.videoaddr - base > 0xFFFFFF)
+			continue;
+
+		video_is_nubus = 1;
+		slot_addr = (unsigned char *)base;
+
+		switch(ndev->dr_hw) {
+		case NUBUS_DRHW_APPLE_MDC:
+			strcpy(macfb_fix.id, "Mac Disp. Card");
+			macfb_setpalette = mdc_setpalette;
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+		case NUBUS_DRHW_APPLE_TFB:
+			strcpy(macfb_fix.id, "Toby");
+			macfb_setpalette = toby_setpalette;
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+		case NUBUS_DRHW_APPLE_JET:
+			strcpy(macfb_fix.id, "Jet");
+			macfb_setpalette = jet_setpalette;
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+		default:
+			strcpy(macfb_fix.id, "Generic NuBus");
+			break;
+		}
+	}
+
+	/* If it's not a NuBus card, it must be internal video */
+	if (!video_is_nubus)
+		switch (mac_bi_data.id) {
+		/*
+		 * DAFB Quadras
+		 * Note: these first four have the v7 DAFB, which is
+		 * known to be rather unlike the ones used in the
+		 * other models
+		 */
+		case MAC_MODEL_P475:
+		case MAC_MODEL_P475F:
+		case MAC_MODEL_P575:
+		case MAC_MODEL_Q605:
+
+		case MAC_MODEL_Q800:
+		case MAC_MODEL_Q650:
+		case MAC_MODEL_Q610:
+		case MAC_MODEL_C650:
+		case MAC_MODEL_C610:
+		case MAC_MODEL_Q700:
+		case MAC_MODEL_Q900:
+		case MAC_MODEL_Q950:
+			strcpy(macfb_fix.id, "DAFB");
+			macfb_setpalette = dafb_setpalette;
+			dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+
+		/*
+		 * LC II uses the V8 framebuffer
+		 */
+		case MAC_MODEL_LCII:
+			strcpy(macfb_fix.id, "V8");
+			macfb_setpalette = v8_brazil_setpalette;
+			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+
+		/*
+		 * IIvi, IIvx use the "Brazil" framebuffer (which is
+		 * very much like the V8, it seems, and probably uses
+		 * the same DAC)
+		 */
+		case MAC_MODEL_IIVI:
+		case MAC_MODEL_IIVX:
+		case MAC_MODEL_P600:
+			strcpy(macfb_fix.id, "Brazil");
+			macfb_setpalette = v8_brazil_setpalette;
+			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+
+		/*
+		 * LC III (and friends) use the Sonora framebuffer
+		 * Incidentally this is also used in the non-AV models
+		 * of the x100 PowerMacs
+		 * These do in fact seem to use the same DAC interface
+		 * as the LC II.
+		 */
+		case MAC_MODEL_LCIII:
+		case MAC_MODEL_P520:
+		case MAC_MODEL_P550:
+		case MAC_MODEL_P460:
+			strcpy(macfb_fix.id, "Sonora");
+			macfb_setpalette = v8_brazil_setpalette;
+			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+
+		/*
+		 * IIci and IIsi use the infamous RBV chip
+		 * (the IIsi is just a rebadged and crippled
+		 * IIci in a different case, BTW)
+		 */
+		case MAC_MODEL_IICI:
+		case MAC_MODEL_IISI:
+			strcpy(macfb_fix.id, "RBV");
+			macfb_setpalette = rbv_setpalette;
+			rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+
+		/*
+		 * AVs use the Civic framebuffer
+		 */
+		case MAC_MODEL_Q840:
+		case MAC_MODEL_C660:
+			strcpy(macfb_fix.id, "Civic");
+			macfb_setpalette = civic_setpalette;
+			civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+
+		
+		/*
+		 * Assorted weirdos
+		 * We think this may be like the LC II
+		 */
+		case MAC_MODEL_LC:
+			strcpy(macfb_fix.id, "LC");
+			if (vidtest) {
+				macfb_setpalette = v8_brazil_setpalette;
+				v8_brazil_cmap_regs =
+					ioremap(DAC_BASE, 0x1000);
+				macfb_defined.activate = FB_ACTIVATE_NOW;
+			}
+			break;
+
+		/*
+		 * We think this may be like the LC II
+		 */
+		case MAC_MODEL_CCL:
+			strcpy(macfb_fix.id, "Color Classic");
+			if (vidtest) {
+				macfb_setpalette = v8_brazil_setpalette;
+				v8_brazil_cmap_regs =
+					ioremap(DAC_BASE, 0x1000);
+				macfb_defined.activate = FB_ACTIVATE_NOW;
+			}
+			break;
+
+		/*
+		 * And we *do* mean "weirdos"
+		 */
+		case MAC_MODEL_TV:
+			strcpy(macfb_fix.id, "Mac TV");
+			break;
+
+		/*
+		 * These don't have colour, so no need to worry
+		 */
+		case MAC_MODEL_SE30:
+		case MAC_MODEL_CLII:
+			strcpy(macfb_fix.id, "Monochrome");
+			break;
+
+		/*
+		 * Powerbooks are particularly difficult.  Many of
+		 * them have separate framebuffers for external and
+		 * internal video, which is admittedly pretty cool,
+		 * but will be a bit of a headache to support here.
+		 * Also, many of them are grayscale, and we don't
+		 * really support that.
+		 */
+
+		/*
+		 * Slot 0 ROM says TIM. No external video. B&W.
+		 */
+		case MAC_MODEL_PB140:
+		case MAC_MODEL_PB145:
+		case MAC_MODEL_PB170:
+			strcpy(macfb_fix.id, "DDC");
+			break;
+
+		/*
+		 * Internal is GSC, External (if present) is ViSC
+		 */
+		case MAC_MODEL_PB150:	/* no external video */
+		case MAC_MODEL_PB160:
+		case MAC_MODEL_PB165:
+		case MAC_MODEL_PB180:
+		case MAC_MODEL_PB210:
+		case MAC_MODEL_PB230:
+			strcpy(macfb_fix.id, "GSC");
+			break;
+
+		/*
+		 * Internal is TIM, External is ViSC
+		 */
+		case MAC_MODEL_PB165C:
+		case MAC_MODEL_PB180C:
+			strcpy(macfb_fix.id, "TIM");
+			break;
+
+		/*
+		 * Internal is CSC, External is Keystone+Ariel.
+		 */
+		case MAC_MODEL_PB190:	/* external video is optional */
+		case MAC_MODEL_PB520:
+		case MAC_MODEL_PB250:
+		case MAC_MODEL_PB270C:
+		case MAC_MODEL_PB280:
+		case MAC_MODEL_PB280C:
+			strcpy(macfb_fix.id, "CSC");
+			macfb_setpalette = csc_setpalette;
+			csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
+			macfb_defined.activate = FB_ACTIVATE_NOW;
+			break;
+
+		default:
+			strcpy(macfb_fix.id, "Unknown");
+			break;
+		}
+
+	fb_info.fbops		= &macfb_ops;
+	fb_info.var		= macfb_defined;
+	fb_info.fix		= macfb_fix;
+	fb_info.pseudo_palette	= pseudo_palette;
+	fb_info.flags		= FBINFO_DEFAULT;
+
+	err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
+	if (err)
+		goto fail_unmap;
+
+	err = register_framebuffer(&fb_info);
+	if (err)
+		goto fail_dealloc;
+
+	fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
+
+	return 0;
+
+fail_dealloc:
+	fb_dealloc_cmap(&fb_info.cmap);
+fail_unmap:
+	iounmap(fb_info.screen_base);
+	iounmap_macfb();
+	return err;
+}
+
+module_init(macfb_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/macmodes.c b/drivers/video/fbdev/macmodes.c
new file mode 100644
index 000000000000..af86c081d2be
--- /dev/null
+++ b/drivers/video/fbdev/macmodes.c
@@ -0,0 +1,414 @@
+/*
+ *  linux/drivers/video/macmodes.c -- Standard MacOS video modes
+ *
+ *	Copyright (C) 1998 Geert Uytterhoeven
+ *
+ *      2000 - Removal of OpenFirmware dependencies by:
+ *      - Ani Joshi
+ *      - Brad Douglas <brad@neruo.com>
+ *
+ *	2001 - Documented with DocBook
+ *	- Brad Douglas <brad@neruo.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+#include "macmodes.h"
+
+    /*
+     *  MacOS video mode definitions
+     *
+     *  Order IS important! If you change these, don't forget to update
+     *  mac_modes[] below!
+     */
+
+#define DEFAULT_MODEDB_INDEX	0
+
+static const struct fb_videomode mac_modedb[] = {
+    {
+	/* 512x384, 60Hz, Non-Interlaced (15.67 MHz dot clock) */
+	"mac2", 60, 512, 384, 63828, 80, 16, 19, 1, 32, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+	"mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */
+	"mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 640x870, 75Hz (portrait), Non-Interlaced (57.28 MHz dot clock) */
+	"mac7", 75, 640, 870, 17457, 80, 32, 42, 3, 80, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
+	"mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */
+	"mac10", 60, 800, 600, 25000, 72, 56, 23, 1, 128, 4,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */
+	"mac11", 72, 800, 600, 20000, 48, 72, 23, 37, 120, 6,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */
+	"mac12", 75, 800, 600, 20203, 144, 32, 21, 1, 80, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 832x624, 75Hz, Non-Interlaced (57.6 MHz dotclock) */
+	"mac13", 75, 832, 624, 17362, 208, 48, 39, 1, 64, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */
+	"mac14", 60, 1024, 768, 15385, 144, 40, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */
+	"mac15", 72, 1024, 768, 13334, 128, 40, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+	"mac16", 75, 1024, 768, 12699, 176, 16, 28, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+	"mac17", 75, 1024, 768, 12699, 160, 32, 28, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */
+	"mac18", 75, 1152, 870, 10000, 128, 48, 39, 3, 128, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */
+	"mac19", 75, 1280, 960, 7937, 224, 32, 36, 1, 144, 3,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
+	"mac20", 75, 1280, 1024, 7408, 232, 64, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1152x768, 60 Hz, Titanium PowerBook */
+	"mac21", 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1600x1024, 60 Hz, Non-Interlaced (112.27 MHz dotclock) */
+	"mac22", 60, 1600, 1024, 8908, 88, 104, 1, 10, 16, 1,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }
+
+#if 0
+    /* Anyone who has timings for these? */
+    {
+	/* VMODE_512_384_60I: 512x384, 60Hz, Interlaced (NTSC) */
+	"mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    }, {
+	/* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */
+	"mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    }, {
+	/* VMODE_640_480_60I: 640x480, 60Hz, Interlaced (NTSC) */
+	"mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    }, {
+	/* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */
+	"mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen,
+	sync, FB_VMODE_INTERLACED
+    },
+#endif
+};
+
+
+    /*
+     *  Mapping between MacOS video mode numbers and video mode definitions
+     *
+     *  These MUST be ordered in
+     *    - increasing resolution
+     *    - decreasing pixel clock period
+     */
+
+static const struct mode_map {
+    int vmode;
+    const struct fb_videomode *mode;
+} mac_modes[] = {
+    /* 512x384 */
+    { VMODE_512_384_60, &mac_modedb[0] },
+    /* 640x480 */
+    { VMODE_640_480_60, &mac_modedb[1] },
+    { VMODE_640_480_67, &mac_modedb[2] },
+    /* 640x870 */
+    { VMODE_640_870_75P, &mac_modedb[3] },
+    /* 800x600 */
+    { VMODE_800_600_56, &mac_modedb[4] },
+    { VMODE_800_600_60, &mac_modedb[5] },
+    { VMODE_800_600_75, &mac_modedb[7] },
+    { VMODE_800_600_72, &mac_modedb[6] },
+    /* 832x624 */
+    { VMODE_832_624_75, &mac_modedb[8] },
+    /* 1024x768 */
+    { VMODE_1024_768_60, &mac_modedb[9] },
+    { VMODE_1024_768_70, &mac_modedb[10] },
+    { VMODE_1024_768_75V, &mac_modedb[11] },
+    { VMODE_1024_768_75, &mac_modedb[12] },
+    /* 1152x768 */
+    { VMODE_1152_768_60, &mac_modedb[16] },
+    /* 1152x870 */
+    { VMODE_1152_870_75, &mac_modedb[13] },
+    /* 1280x960 */
+    { VMODE_1280_960_75, &mac_modedb[14] },
+    /* 1280x1024 */
+    { VMODE_1280_1024_75, &mac_modedb[15] },
+    /* 1600x1024 */
+    { VMODE_1600_1024_60, &mac_modedb[17] },
+    { -1, NULL }
+};
+
+
+    /*
+     *  Mapping between monitor sense values and MacOS video mode numbers
+     */
+
+static const struct monitor_map {
+    int sense;
+    int vmode;
+} mac_monitors[] = {
+    { 0x000, VMODE_1280_1024_75 },	/* 21" RGB */
+    { 0x114, VMODE_640_870_75P },	/* Portrait Monochrome */
+    { 0x221, VMODE_512_384_60 },	/* 12" RGB*/
+    { 0x331, VMODE_1280_1024_75 },	/* 21" RGB (Radius) */
+    { 0x334, VMODE_1280_1024_75 },	/* 21" mono (Radius) */
+    { 0x335, VMODE_1280_1024_75 },	/* 21" mono */
+    { 0x40A, VMODE_640_480_60I },	/* NTSC */
+    { 0x51E, VMODE_640_870_75P },	/* Portrait RGB */
+    { 0x603, VMODE_832_624_75 },	/* 12"-16" multiscan */
+    { 0x60b, VMODE_1024_768_70 },	/* 13"-19" multiscan */
+    { 0x623, VMODE_1152_870_75 },	/* 13"-21" multiscan */
+    { 0x62b, VMODE_640_480_67 },	/* 13"/14" RGB */
+    { 0x700, VMODE_640_480_50I },	/* PAL */
+    { 0x714, VMODE_640_480_60I },	/* NTSC */
+    { 0x717, VMODE_800_600_75 },	/* VGA */
+    { 0x72d, VMODE_832_624_75 },	/* 16" RGB (Goldfish) */
+    { 0x730, VMODE_768_576_50I },	/* PAL (Alternate) */
+    { 0x73a, VMODE_1152_870_75 },	/* 3rd party 19" */
+    { 0x73f, VMODE_640_480_67 },	/* no sense lines connected at all */
+    { 0xBEEF, VMODE_1600_1024_60 },	/* 22" Apple Cinema Display */
+    { -1,    VMODE_640_480_60 },	/* catch-all, must be last */
+};
+
+/**
+ *	mac_vmode_to_var - converts vmode/cmode pair to var structure
+ *	@vmode: MacOS video mode
+ *	@cmode: MacOS color mode
+ *	@var: frame buffer video mode structure
+ *
+ *	Converts a MacOS vmode/cmode pair to a frame buffer video
+ *	mode structure.
+ *
+ *	Returns negative errno on error, or zero for success.
+ *
+ */
+
+int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
+{
+    const struct fb_videomode *mode = NULL;
+    const struct mode_map *map;
+
+    for (map = mac_modes; map->vmode != -1; map++)
+	if (map->vmode == vmode) {
+	    mode = map->mode;
+	    break;
+	}
+    if (!mode)
+	return -EINVAL;
+
+    memset(var, 0, sizeof(struct fb_var_screeninfo));
+    switch (cmode) {
+	case CMODE_8:
+	    var->bits_per_pixel = 8;
+	    var->red.offset = 0;
+	    var->red.length = 8;   
+	    var->green.offset = 0;
+	    var->green.length = 8;
+	    var->blue.offset = 0;
+	    var->blue.length = 8;
+	    break;
+
+	case CMODE_16:
+	    var->bits_per_pixel = 16;
+	    var->red.offset = 10;
+	    var->red.length = 5;
+	    var->green.offset = 5;
+	    var->green.length = 5;
+	    var->blue.offset = 0;
+	    var->blue.length = 5;
+	    break;
+
+	case CMODE_32:
+	    var->bits_per_pixel = 32;
+	    var->red.offset = 16;
+	    var->red.length = 8;
+	    var->green.offset = 8;
+	    var->green.length = 8;
+	    var->blue.offset = 0;
+	    var->blue.length = 8;
+	    var->transp.offset = 24;
+	    var->transp.length = 8;
+	    break;
+
+	default:
+	    return -EINVAL;
+    }
+    var->xres = mode->xres;
+    var->yres = mode->yres;
+    var->xres_virtual = mode->xres;
+    var->yres_virtual = mode->yres;
+    var->height = -1;
+    var->width = -1;
+    var->pixclock = mode->pixclock;
+    var->left_margin = mode->left_margin;
+    var->right_margin = mode->right_margin;
+    var->upper_margin = mode->upper_margin;
+    var->lower_margin = mode->lower_margin;
+    var->hsync_len = mode->hsync_len;
+    var->vsync_len = mode->vsync_len;
+    var->sync = mode->sync;
+    var->vmode = mode->vmode;
+    return 0;
+}
+EXPORT_SYMBOL(mac_vmode_to_var);
+
+/**
+ *	mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair
+ *	@var: frame buffer video mode structure
+ *	@vmode: MacOS video mode
+ *	@cmode: MacOS color mode
+ *
+ *	Converts a frame buffer video mode structure to a MacOS
+ *	vmode/cmode pair.
+ *
+ *	Returns negative errno on error, or zero for success.
+ *
+ */
+
+int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
+		     int *cmode)
+{
+    const struct mode_map *map;
+
+    if (var->bits_per_pixel <= 8)
+	*cmode = CMODE_8;
+    else if (var->bits_per_pixel <= 16)
+	*cmode = CMODE_16;
+    else if (var->bits_per_pixel <= 32)
+	*cmode = CMODE_32;
+    else
+	return -EINVAL;
+
+    /*
+     * Find the mac_mode with a matching resolution or failing that, the
+     * closest larger resolution. Skip modes with a shorter pixel clock period.
+     */
+    for (map = mac_modes; map->vmode != -1; map++) {
+	const struct fb_videomode *mode = map->mode;
+
+	if (var->xres > mode->xres || var->yres > mode->yres)
+	    continue;
+	if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)
+	    continue;
+	if (var->pixclock > mode->pixclock)
+	    continue;
+	if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
+	    continue;
+	*vmode = map->vmode;
+
+	/*
+	 * Having found a good resolution, find the matching pixel clock
+	 * or failing that, the closest longer pixel clock period.
+	 */
+	map++;
+	while (map->vmode != -1) {
+	    const struct fb_videomode *clk_mode = map->mode;
+
+	    if (mode->xres != clk_mode->xres || mode->yres != clk_mode->yres)
+		break;
+	    if (var->pixclock > mode->pixclock)
+	        break;
+	    if (mode->vmode != clk_mode->vmode)
+		continue;
+	    *vmode = map->vmode;
+	    map++;
+	}
+	return 0;
+    }
+    return -EINVAL;
+}
+
+/**
+ *	mac_map_monitor_sense - Convert monitor sense to vmode
+ *	@sense: Macintosh monitor sense number
+ *
+ *	Converts a Macintosh monitor sense number to a MacOS
+ *	vmode number.
+ *
+ *	Returns MacOS vmode video mode number.
+ *
+ */
+
+int mac_map_monitor_sense(int sense)
+{
+    const struct monitor_map *map;
+
+    for (map = mac_monitors; map->sense != -1; map++)
+	if (map->sense == sense)
+	    break;
+    return map->vmode;
+}
+EXPORT_SYMBOL(mac_map_monitor_sense);
+
+/**
+ *	mac_find_mode - find a video mode
+ *	@var: frame buffer user defined part of display
+ *	@info: frame buffer info structure
+ *	@mode_option: video mode name (see mac_modedb[])
+ *	@default_bpp: default color depth in bits per pixel
+ *
+ *	Finds a suitable video mode.  Tries to set mode specified
+ *	by @mode_option.  If the name of the wanted mode begins with
+ *	'mac', the Mac video mode database will be used, otherwise it
+ *	will fall back to the standard video mode database.
+ *
+ *	Note: Function marked as __init and can only be used during
+ *	system boot.
+ *
+ *	Returns error code from fb_find_mode (see fb_find_mode
+ *	function).
+ *
+ */
+
+int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+		  const char *mode_option, unsigned int default_bpp)
+{
+    const struct fb_videomode *db = NULL;
+    unsigned int dbsize = 0;
+
+    if (mode_option && !strncmp(mode_option, "mac", 3)) {
+	mode_option += 3;
+	db = mac_modedb;
+	dbsize = ARRAY_SIZE(mac_modedb);
+    }
+    return fb_find_mode(var, info, mode_option, db, dbsize,
+			&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
+}
+EXPORT_SYMBOL(mac_find_mode);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/macmodes.h b/drivers/video/fbdev/macmodes.h
new file mode 100644
index 000000000000..b86ba08aac9e
--- /dev/null
+++ b/drivers/video/fbdev/macmodes.h
@@ -0,0 +1,71 @@
+/*
+ *  linux/drivers/video/macmodes.h -- Standard MacOS video modes
+ *
+ *	Copyright (C) 1998 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef _VIDEO_MACMODES_H
+#define _VIDEO_MACMODES_H
+
+    /*
+     *  Video mode values.
+     *  These are supposed to be the same as the values that Apple uses in
+     *  MacOS.
+     */
+
+#define VMODE_NVRAM		0
+#define VMODE_512_384_60I	1	/* 512x384, 60Hz interlaced (NTSC) */
+#define VMODE_512_384_60	2	/* 512x384, 60Hz */
+#define VMODE_640_480_50I	3	/* 640x480, 50Hz interlaced (PAL) */
+#define VMODE_640_480_60I	4	/* 640x480, 60Hz interlaced (NTSC) */
+#define VMODE_640_480_60	5	/* 640x480, 60Hz (VGA) */
+#define VMODE_640_480_67	6	/* 640x480, 67Hz */
+#define VMODE_640_870_75P	7	/* 640x870, 75Hz (portrait) */
+#define VMODE_768_576_50I	8	/* 768x576, 50Hz (PAL full frame) */
+#define VMODE_800_600_56	9	/* 800x600, 56Hz */
+#define VMODE_800_600_60	10	/* 800x600, 60Hz */
+#define VMODE_800_600_72	11	/* 800x600, 72Hz */
+#define VMODE_800_600_75	12	/* 800x600, 75Hz */
+#define VMODE_832_624_75	13	/* 832x624, 75Hz */
+#define VMODE_1024_768_60	14	/* 1024x768, 60Hz */
+#define VMODE_1024_768_70	15	/* 1024x768, 70Hz (or 72Hz?) */
+#define VMODE_1024_768_75V	16	/* 1024x768, 75Hz (VESA) */
+#define VMODE_1024_768_75	17	/* 1024x768, 75Hz */
+#define VMODE_1152_870_75	18	/* 1152x870, 75Hz */
+#define VMODE_1280_960_75	19	/* 1280x960, 75Hz */
+#define VMODE_1280_1024_75	20	/* 1280x1024, 75Hz */
+#define VMODE_1152_768_60	21	/* 1152x768, 60Hz     Titanium PowerBook */
+#define VMODE_1600_1024_60	22	/* 1600x1024, 60Hz 22" Cinema Display */
+#define VMODE_MAX		22
+#define VMODE_CHOOSE		99
+
+#define CMODE_NVRAM		-1
+#define CMODE_CHOOSE		-2
+#define CMODE_8			0	/* 8 bits/pixel */
+#define CMODE_16		1	/* 16 (actually 15) bits/pixel */
+#define CMODE_32		2	/* 32 (actually 24) bits/pixel */
+
+
+extern int mac_vmode_to_var(int vmode, int cmode,
+			    struct fb_var_screeninfo *var);
+extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
+			    int *cmode);
+extern int mac_map_monitor_sense(int sense);
+extern int mac_find_mode(struct fb_var_screeninfo *var,
+			 struct fb_info *info,
+			 const char *mode_option,
+			 unsigned int default_bpp);
+
+
+    /*
+     *  Addresses in NVRAM where video mode and pixel size are stored.
+     */
+
+#define NV_VMODE		0x140f
+#define NV_CMODE		0x1410
+
+#endif /* _VIDEO_MACMODES_H */
diff --git a/drivers/video/fbdev/matrox/Makefile b/drivers/video/fbdev/matrox/Makefile
new file mode 100644
index 000000000000..f9c00ebe2530
--- /dev/null
+++ b/drivers/video/fbdev/matrox/Makefile
@@ -0,0 +1,11 @@
+# Makefile for the Linux video drivers.
+# 5 Aug 1999, James Simmons, <mailto:jsimmons@edgeglobal.com>
+# Rewritten to use lists instead of if-statements.
+
+# Each configuration option enables a list of files.
+
+my-obj-$(CONFIG_FB_MATROX_G)      += g450_pll.o matroxfb_g450.o matroxfb_crtc2.o
+
+obj-$(CONFIG_FB_MATROX)           += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o $(my-obj-y)
+obj-$(CONFIG_FB_MATROX_I2C)       += i2c-matroxfb.o
+obj-$(CONFIG_FB_MATROX_MAVEN)     += matroxfb_maven.o matroxfb_crtc2.o
diff --git a/drivers/video/fbdev/matrox/g450_pll.c b/drivers/video/fbdev/matrox/g450_pll.c
new file mode 100644
index 000000000000..c15f8a57498e
--- /dev/null
+++ b/drivers/video/fbdev/matrox/g450_pll.c
@@ -0,0 +1,539 @@
+/*
+ *
+ * Hardware accelerated Matrox PCI cards - G450/G550 PLL control.
+ *
+ * (c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.64 2002/06/10
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ */
+
+#include "g450_pll.h"
+#include "matroxfb_DAC1064.h"
+
+static inline unsigned int g450_vco2f(unsigned char p, unsigned int fvco) {
+	return (p & 0x40) ? fvco : fvco >> ((p & 3) + 1);
+}
+
+static inline unsigned int g450_f2vco(unsigned char p, unsigned int fin) {
+	return (p & 0x40) ? fin : fin << ((p & 3) + 1);
+}
+
+static unsigned int g450_mnp2vco(const struct matrox_fb_info *minfo,
+				 unsigned int mnp)
+{
+	unsigned int m, n;
+
+	m = ((mnp >> 16) & 0x0FF) + 1;
+	n = ((mnp >>  7) & 0x1FE) + 4;
+	return (minfo->features.pll.ref_freq * n + (m >> 1)) / m;
+}
+
+unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp)
+{
+	return g450_vco2f(mnp, g450_mnp2vco(minfo, mnp));
+}
+
+static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) {
+	if (f2 < f1) {
+    		f2 = f1 - f2;
+	} else {
+		f2 = f2 - f1;
+	}
+	return f2;
+}
+
+#define NO_MORE_MNP	0x01FFFFFF
+#define G450_MNP_FREQBITS	(0xFFFFFF43)	/* do not mask high byte so we'll catch NO_MORE_MNP */
+
+static unsigned int g450_nextpll(const struct matrox_fb_info *minfo,
+				 const struct matrox_pll_limits *pi,
+				 unsigned int *fvco, unsigned int mnp)
+{
+	unsigned int m, n, p;
+	unsigned int tvco = *fvco;
+
+	m = (mnp >> 16) & 0xFF;
+	p = mnp & 0xFF;
+
+	do {
+		if (m == 0 || m == 0xFF) {
+			if (m == 0) {
+				if (p & 0x40) {
+					return NO_MORE_MNP;
+				}
+			        if (p & 3) {
+					p--;
+				} else {
+					p = 0x40;
+				}
+				tvco >>= 1;
+				if (tvco < pi->vcomin) {
+					return NO_MORE_MNP;
+				}
+				*fvco = tvco;
+			}
+
+			p &= 0x43;
+			if (tvco < 550000) {
+/*				p |= 0x00; */
+			} else if (tvco < 700000) {
+				p |= 0x08;
+			} else if (tvco < 1000000) {
+				p |= 0x10;
+			} else if (tvco < 1150000) {
+				p |= 0x18;
+			} else {
+				p |= 0x20;
+			}
+			m = 9;
+		} else {
+			m--;
+		}
+		n = ((tvco * (m+1) + minfo->features.pll.ref_freq) / (minfo->features.pll.ref_freq * 2)) - 2;
+	} while (n < 0x03 || n > 0x7A);
+	return (m << 16) | (n << 8) | p;
+}
+
+static unsigned int g450_firstpll(const struct matrox_fb_info *minfo,
+				  const struct matrox_pll_limits *pi,
+				  unsigned int *vco, unsigned int fout)
+{
+	unsigned int p;
+	unsigned int vcomax;
+
+	vcomax = pi->vcomax;
+	if (fout > (vcomax / 2)) {
+		if (fout > vcomax) {
+			*vco = vcomax;
+		} else {
+			*vco = fout;
+		}
+		p = 0x40;
+	} else {
+		unsigned int tvco;
+
+		p = 3;
+		tvco = g450_f2vco(p, fout);
+		while (p && (tvco > vcomax)) {
+			p--;
+			tvco >>= 1;
+		}
+		if (tvco < pi->vcomin) {
+			tvco = pi->vcomin;
+		}
+		*vco = tvco;
+	}
+	return g450_nextpll(minfo, pi, vco, 0xFF0000 | p);
+}
+
+static inline unsigned int g450_setpll(const struct matrox_fb_info *minfo,
+				       unsigned int mnp, unsigned int pll)
+{
+	switch (pll) {
+		case M_PIXEL_PLL_A:
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLAM, mnp >> 16);
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLAN, mnp >> 8);
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLAP, mnp);
+			return M1064_XPIXPLLSTAT;
+
+		case M_PIXEL_PLL_B:
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLBM, mnp >> 16);
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLBN, mnp >> 8);
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLBP, mnp);
+			return M1064_XPIXPLLSTAT;
+
+		case M_PIXEL_PLL_C:
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLCM, mnp >> 16);
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLCN, mnp >> 8);
+			matroxfb_DAC_out(minfo, M1064_XPIXPLLCP, mnp);
+			return M1064_XPIXPLLSTAT;
+
+		case M_SYSTEM_PLL:
+			matroxfb_DAC_out(minfo, DAC1064_XSYSPLLM, mnp >> 16);
+			matroxfb_DAC_out(minfo, DAC1064_XSYSPLLN, mnp >> 8);
+			matroxfb_DAC_out(minfo, DAC1064_XSYSPLLP, mnp);
+			return DAC1064_XSYSPLLSTAT;
+
+		case M_VIDEO_PLL:
+			matroxfb_DAC_out(minfo, M1064_XVIDPLLM, mnp >> 16);
+			matroxfb_DAC_out(minfo, M1064_XVIDPLLN, mnp >> 8);
+			matroxfb_DAC_out(minfo, M1064_XVIDPLLP, mnp);
+			return M1064_XVIDPLLSTAT;
+	}
+	return 0;
+}
+
+static inline unsigned int g450_cmppll(const struct matrox_fb_info *minfo,
+				       unsigned int mnp, unsigned int pll)
+{
+	unsigned char m = mnp >> 16;
+	unsigned char n = mnp >> 8;
+	unsigned char p = mnp;
+
+	switch (pll) {
+		case M_PIXEL_PLL_A:
+			return (matroxfb_DAC_in(minfo, M1064_XPIXPLLAM) != m ||
+				matroxfb_DAC_in(minfo, M1064_XPIXPLLAN) != n ||
+				matroxfb_DAC_in(minfo, M1064_XPIXPLLAP) != p);
+
+		case M_PIXEL_PLL_B:
+			return (matroxfb_DAC_in(minfo, M1064_XPIXPLLBM) != m ||
+				matroxfb_DAC_in(minfo, M1064_XPIXPLLBN) != n ||
+				matroxfb_DAC_in(minfo, M1064_XPIXPLLBP) != p);
+
+		case M_PIXEL_PLL_C:
+			return (matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) != m ||
+				matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) != n ||
+				matroxfb_DAC_in(minfo, M1064_XPIXPLLCP) != p);
+
+		case M_SYSTEM_PLL:
+			return (matroxfb_DAC_in(minfo, DAC1064_XSYSPLLM) != m ||
+				matroxfb_DAC_in(minfo, DAC1064_XSYSPLLN) != n ||
+				matroxfb_DAC_in(minfo, DAC1064_XSYSPLLP) != p);
+
+		case M_VIDEO_PLL:
+			return (matroxfb_DAC_in(minfo, M1064_XVIDPLLM) != m ||
+				matroxfb_DAC_in(minfo, M1064_XVIDPLLN) != n ||
+				matroxfb_DAC_in(minfo, M1064_XVIDPLLP) != p);
+	}
+	return 1;
+}
+
+static inline int g450_isplllocked(const struct matrox_fb_info *minfo,
+				   unsigned int regidx)
+{
+	unsigned int j;
+
+	for (j = 0; j < 1000; j++) {
+		if (matroxfb_DAC_in(minfo, regidx) & 0x40) {
+			unsigned int r = 0;
+			int i;
+
+			for (i = 0; i < 100; i++) {
+				r += matroxfb_DAC_in(minfo, regidx) & 0x40;
+			}
+			return r >= (90 * 0x40);
+		}
+		/* udelay(1)... but DAC_in is much slower... */
+	}
+	return 0;
+}
+
+static int g450_testpll(const struct matrox_fb_info *minfo, unsigned int mnp,
+			unsigned int pll)
+{
+	return g450_isplllocked(minfo, g450_setpll(minfo, mnp, pll));
+}
+
+static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) {
+	switch (pll) {
+		case M_SYSTEM_PLL:
+			hw->DACclk[3] = mnp >> 16;
+			hw->DACclk[4] = mnp >> 8;
+			hw->DACclk[5] = mnp;
+			break;
+	}
+}
+
+void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
+			       unsigned int pll)
+{
+	if (g450_cmppll(minfo, mnp, pll)) {
+		g450_setpll(minfo, mnp, pll);
+	}
+}
+
+static inline unsigned int g450_findworkingpll(struct matrox_fb_info *minfo,
+					       unsigned int pll,
+					       unsigned int *mnparray,
+					       unsigned int mnpcount)
+{
+	unsigned int found = 0;
+	unsigned int idx;
+	unsigned int mnpfound = mnparray[0];
+		
+	for (idx = 0; idx < mnpcount; idx++) {
+		unsigned int sarray[3];
+		unsigned int *sptr;
+		{
+			unsigned int mnp;
+		
+			sptr = sarray;
+			mnp = mnparray[idx];
+			if (mnp & 0x38) {
+				*sptr++ = mnp - 8;
+			}
+			if ((mnp & 0x38) != 0x38) {
+				*sptr++ = mnp + 8;
+			}
+			*sptr = mnp;
+		}
+		while (sptr >= sarray) {
+			unsigned int mnp = *sptr--;
+		
+			if (g450_testpll(minfo, mnp - 0x0300, pll) &&
+			    g450_testpll(minfo, mnp + 0x0300, pll) &&
+			    g450_testpll(minfo, mnp - 0x0200, pll) &&
+			    g450_testpll(minfo, mnp + 0x0200, pll) &&
+			    g450_testpll(minfo, mnp - 0x0100, pll) &&
+			    g450_testpll(minfo, mnp + 0x0100, pll)) {
+				if (g450_testpll(minfo, mnp, pll)) {
+					return mnp;
+				}
+			} else if (!found && g450_testpll(minfo, mnp, pll)) {
+				mnpfound = mnp;
+				found = 1;
+			}
+		}
+	}
+	g450_setpll(minfo, mnpfound, pll);
+	return mnpfound;
+}
+
+static void g450_addcache(struct matrox_pll_cache* ci, unsigned int mnp_key, unsigned int mnp_value) {
+	if (++ci->valid > ARRAY_SIZE(ci->data)) {
+		ci->valid = ARRAY_SIZE(ci->data);
+	}
+	memmove(ci->data + 1, ci->data, (ci->valid - 1) * sizeof(*ci->data));
+	ci->data[0].mnp_key = mnp_key & G450_MNP_FREQBITS;
+	ci->data[0].mnp_value = mnp_value;
+}
+
+static int g450_checkcache(struct matrox_fb_info *minfo,
+			   struct matrox_pll_cache *ci, unsigned int mnp_key)
+{
+	unsigned int i;
+	
+	mnp_key &= G450_MNP_FREQBITS;
+	for (i = 0; i < ci->valid; i++) {
+		if (ci->data[i].mnp_key == mnp_key) {
+			unsigned int mnp;
+			
+			mnp = ci->data[i].mnp_value;
+			if (i) {
+				memmove(ci->data + 1, ci->data, i * sizeof(*ci->data));
+				ci->data[0].mnp_key = mnp_key;
+				ci->data[0].mnp_value = mnp;
+			}
+			return mnp;
+		}
+	}
+	return NO_MORE_MNP;
+}
+
+static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
+			 unsigned int pll, unsigned int *mnparray,
+			 unsigned int *deltaarray)
+{
+	unsigned int mnpcount;
+	unsigned int pixel_vco;
+	const struct matrox_pll_limits* pi;
+	struct matrox_pll_cache* ci;
+
+	pixel_vco = 0;
+	switch (pll) {
+		case M_PIXEL_PLL_A:
+		case M_PIXEL_PLL_B:
+		case M_PIXEL_PLL_C:
+			{
+				u_int8_t tmp, xpwrctrl;
+				unsigned long flags;
+				
+				matroxfb_DAC_lock_irqsave(flags);
+
+				xpwrctrl = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
+				matroxfb_DAC_out(minfo, M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN);
+				mga_outb(M_SEQ_INDEX, M_SEQ1);
+				mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF);
+				tmp = matroxfb_DAC_in(minfo, M1064_XPIXCLKCTRL);
+				tmp |= M1064_XPIXCLKCTRL_DIS;
+				if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) {
+					tmp |= M1064_XPIXCLKCTRL_PLL_UP;
+				}
+				matroxfb_DAC_out(minfo, M1064_XPIXCLKCTRL, tmp);
+				/* DVI PLL preferred for frequencies up to
+				   panel link max, standard PLL otherwise */
+				if (fout >= minfo->max_pixel_clock_panellink)
+					tmp = 0;
+				else tmp =
+					M1064_XDVICLKCTRL_DVIDATAPATHSEL |
+					M1064_XDVICLKCTRL_C1DVICLKSEL |
+					M1064_XDVICLKCTRL_C1DVICLKEN |
+					M1064_XDVICLKCTRL_DVILOOPCTL |
+					M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
+                                /* Setting this breaks PC systems so don't do it */
+				/* matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); */
+				matroxfb_DAC_out(minfo, M1064_XPWRCTRL,
+						 xpwrctrl);
+
+				matroxfb_DAC_unlock_irqrestore(flags);
+			}
+			{
+				u_int8_t misc;
+		
+				misc = mga_inb(M_MISC_REG_READ) & ~0x0C;
+				switch (pll) {
+					case M_PIXEL_PLL_A:
+						break;
+					case M_PIXEL_PLL_B:
+						misc |=  0x04;
+						break;
+					default:
+						misc |=  0x0C;
+						break;
+				}
+				mga_outb(M_MISC_REG, misc);
+			}
+			pi = &minfo->limits.pixel;
+			ci = &minfo->cache.pixel;
+			break;
+		case M_SYSTEM_PLL:
+			{
+				u_int32_t opt;
+
+				pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &opt);
+				if (!(opt & 0x20)) {
+					pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, opt | 0x20);
+				}
+			}
+			pi = &minfo->limits.system;
+			ci = &minfo->cache.system;
+			break;
+		case M_VIDEO_PLL:
+			{
+				u_int8_t tmp;
+				unsigned int mnp;
+				unsigned long flags;
+				
+				matroxfb_DAC_lock_irqsave(flags);
+				tmp = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
+				if (!(tmp & 2)) {
+					matroxfb_DAC_out(minfo, M1064_XPWRCTRL, tmp | 2);
+				}
+				
+				mnp = matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) << 16;
+				mnp |= matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) << 8;
+				pixel_vco = g450_mnp2vco(minfo, mnp);
+				matroxfb_DAC_unlock_irqrestore(flags);
+			}
+			pi = &minfo->limits.video;
+			ci = &minfo->cache.video;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	mnpcount = 0;
+	{
+		unsigned int mnp;
+		unsigned int xvco;
+
+		for (mnp = g450_firstpll(minfo, pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(minfo, pi, &xvco, mnp)) {
+			unsigned int idx;
+			unsigned int vco;
+			unsigned int delta;
+
+			vco = g450_mnp2vco(minfo, mnp);
+#if 0			
+			if (pll == M_VIDEO_PLL) {
+				unsigned int big, small;
+
+				if (vco < pixel_vco) {
+					small = vco;
+					big = pixel_vco;
+				} else {
+					small = pixel_vco;
+					big = vco;
+				}
+				while (big > small) {
+					big >>= 1;
+				}
+				if (big == small) {
+					continue;
+				}
+			}
+#endif			
+			delta = pll_freq_delta(fout, g450_vco2f(mnp, vco));
+			for (idx = mnpcount; idx > 0; idx--) {
+				/* == is important; due to nextpll algorithm we get
+				   sorted equally good frequencies from lower VCO 
+				   frequency to higher - with <= lowest wins, while
+				   with < highest one wins */
+				if (delta <= deltaarray[idx-1]) {
+					/* all else being equal except VCO,
+					 * choose VCO not near (within 1/16th or so) VCOmin
+					 * (freqs near VCOmin aren't as stable)
+					 */
+					if (delta == deltaarray[idx-1]
+					    && vco != g450_mnp2vco(minfo, mnparray[idx-1])
+					    && vco < (pi->vcomin * 17 / 16)) {
+						break;
+					}
+					mnparray[idx] = mnparray[idx-1];
+					deltaarray[idx] = deltaarray[idx-1];
+				} else {
+					break;
+				}
+			}
+			mnparray[idx] = mnp;
+			deltaarray[idx] = delta;
+			mnpcount++;
+		}
+	}
+	/* VideoPLL and PixelPLL matched: do nothing... In all other cases we should get at least one frequency */
+	if (!mnpcount) {
+		return -EBUSY;
+	}
+	{
+		unsigned long flags;
+		unsigned int mnp;
+		
+		matroxfb_DAC_lock_irqsave(flags);
+		mnp = g450_checkcache(minfo, ci, mnparray[0]);
+		if (mnp != NO_MORE_MNP) {
+			matroxfb_g450_setpll_cond(minfo, mnp, pll);
+		} else {
+			mnp = g450_findworkingpll(minfo, pll, mnparray, mnpcount);
+			g450_addcache(ci, mnparray[0], mnp);
+		}
+		updatehwstate_clk(&minfo->hw, mnp, pll);
+		matroxfb_DAC_unlock_irqrestore(flags);
+		return mnp;
+	}
+}
+
+/* It must be greater than number of possible PLL values.
+ * Currently there is 5(p) * 10(m) = 50 possible values. */
+#define MNP_TABLE_SIZE  64
+
+int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
+			 unsigned int pll)
+{
+	unsigned int* arr;
+	
+	arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL);
+	if (arr) {
+		int r;
+
+		r = __g450_setclk(minfo, fout, pll, arr, arr + MNP_TABLE_SIZE);
+		kfree(arr);
+		return r;
+	}
+	return -ENOMEM;
+}
+
+EXPORT_SYMBOL(matroxfb_g450_setclk);
+EXPORT_SYMBOL(g450_mnp2f);
+EXPORT_SYMBOL(matroxfb_g450_setpll_cond);
+
+MODULE_AUTHOR("(c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Matrox G450/G550 PLL driver");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/g450_pll.h b/drivers/video/fbdev/matrox/g450_pll.h
new file mode 100644
index 000000000000..aac615d18440
--- /dev/null
+++ b/drivers/video/fbdev/matrox/g450_pll.h
@@ -0,0 +1,12 @@
+#ifndef __G450_PLL_H__
+#define __G450_PLL_H__
+
+#include "matroxfb_base.h"
+
+int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
+			 unsigned int pll);
+unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp);
+void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
+			       unsigned int pll);
+
+#endif	/* __G450_PLL_H__ */
diff --git a/drivers/video/fbdev/matrox/i2c-matroxfb.c b/drivers/video/fbdev/matrox/i2c-matroxfb.c
new file mode 100644
index 000000000000..0fb280ead3dc
--- /dev/null
+++ b/drivers/video/fbdev/matrox/i2c-matroxfb.c
@@ -0,0 +1,238 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Version: 1.64 2002/06/10
+ *
+ * See matroxfb_base.c for contributors.
+ *
+ */
+
+#include "matroxfb_base.h"
+#include "matroxfb_maven.h"
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/i2c-algo-bit.h>
+
+/* MGA-TVO I2C for G200, G400 */
+#define MAT_CLK		0x20
+#define MAT_DATA	0x10
+/* primary head DDC for Mystique(?), G100, G200, G400 */
+#define DDC1_CLK	0x08
+#define DDC1_DATA	0x02
+/* primary head DDC for Millennium, Millennium II */
+#define DDC1B_CLK	0x10
+#define DDC1B_DATA	0x04
+/* secondary head DDC for G400 */
+#define DDC2_CLK	0x04
+#define DDC2_DATA	0x01
+
+/******************************************************/
+
+struct matroxfb_dh_maven_info {
+	struct i2c_bit_adapter	maven;
+	struct i2c_bit_adapter	ddc1;
+	struct i2c_bit_adapter	ddc2;
+};
+
+static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
+	unsigned long flags;
+	int v;
+
+	matroxfb_DAC_lock_irqsave(flags);
+	v = matroxfb_DAC_in(minfo, DAC_XGENIODATA);
+	matroxfb_DAC_unlock_irqrestore(flags);
+	return v;
+}
+
+static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
+	unsigned long flags;
+	int v;
+
+	matroxfb_DAC_lock_irqsave(flags);
+	v = (matroxfb_DAC_in(minfo, DAC_XGENIOCTRL) & mask) | val;
+	matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, v);
+	/* We must reset GENIODATA very often... XFree plays with this register */
+	matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0x00);
+	matroxfb_DAC_unlock_irqrestore(flags);
+}
+
+/* software I2C functions */
+static inline void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
+	if (state)
+		state = 0;
+	else
+		state = mask;
+	matroxfb_set_gpio(minfo, ~mask, state);
+}
+
+static void matroxfb_gpio_setsda(void* data, int state) {
+	struct i2c_bit_adapter* b = data;
+	matroxfb_i2c_set(b->minfo, b->mask.data, state);
+}
+
+static void matroxfb_gpio_setscl(void* data, int state) {
+	struct i2c_bit_adapter* b = data;
+	matroxfb_i2c_set(b->minfo, b->mask.clock, state);
+}
+
+static int matroxfb_gpio_getsda(void* data) {
+	struct i2c_bit_adapter* b = data;
+	return (matroxfb_read_gpio(b->minfo) & b->mask.data) ? 1 : 0;
+}
+
+static int matroxfb_gpio_getscl(void* data) {
+	struct i2c_bit_adapter* b = data;
+	return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
+}
+
+static const struct i2c_algo_bit_data matrox_i2c_algo_template =
+{
+	.setsda		= matroxfb_gpio_setsda,
+	.setscl		= matroxfb_gpio_setscl,
+	.getsda		= matroxfb_gpio_getsda,
+	.getscl		= matroxfb_gpio_getscl,
+	.udelay		= 10,
+	.timeout	= 100,
+};
+
+static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 
+		unsigned int data, unsigned int clock, const char *name,
+		int class)
+{
+	int err;
+
+	b->minfo = minfo;
+	b->mask.data = data;
+	b->mask.clock = clock;
+	b->adapter.owner = THIS_MODULE;
+	snprintf(b->adapter.name, sizeof(b->adapter.name), name,
+		minfo->fbcon.node);
+	i2c_set_adapdata(&b->adapter, b);
+	b->adapter.class = class;
+	b->adapter.algo_data = &b->bac;
+	b->adapter.dev.parent = &minfo->pcidev->dev;
+	b->bac = matrox_i2c_algo_template;
+	b->bac.data = b;
+	err = i2c_bit_add_bus(&b->adapter);
+	b->initialized = !err;
+	return err;
+}
+
+static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
+	if (b->initialized) {
+		i2c_del_adapter(&b->adapter);
+		b->initialized = 0;
+	}
+}
+
+static inline void i2c_maven_done(struct matroxfb_dh_maven_info* minfo2) {
+	i2c_bit_bus_del(&minfo2->maven);
+}
+
+static inline void i2c_ddc1_done(struct matroxfb_dh_maven_info* minfo2) {
+	i2c_bit_bus_del(&minfo2->ddc1);
+}
+
+static inline void i2c_ddc2_done(struct matroxfb_dh_maven_info* minfo2) {
+	i2c_bit_bus_del(&minfo2->ddc2);
+}
+
+static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
+	int err;
+	unsigned long flags;
+	struct matroxfb_dh_maven_info* m2info;
+
+	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
+	if (!m2info)
+		return NULL;
+
+	matroxfb_DAC_lock_irqsave(flags);
+	matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0xFF);
+	matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, 0x00);
+	matroxfb_DAC_unlock_irqrestore(flags);
+
+	switch (minfo->chip) {
+		case MGA_2064:
+		case MGA_2164:
+			err = i2c_bus_reg(&m2info->ddc1, minfo,
+					  DDC1B_DATA, DDC1B_CLK,
+					  "DDC:fb%u #0", I2C_CLASS_DDC);
+			break;
+		default:
+			err = i2c_bus_reg(&m2info->ddc1, minfo,
+					  DDC1_DATA, DDC1_CLK,
+					  "DDC:fb%u #0", I2C_CLASS_DDC);
+			break;
+	}
+	if (err)
+		goto fail_ddc1;
+	if (minfo->devflags.dualhead) {
+		err = i2c_bus_reg(&m2info->ddc2, minfo,
+				  DDC2_DATA, DDC2_CLK,
+				  "DDC:fb%u #1", I2C_CLASS_DDC);
+		if (err == -ENODEV) {
+			printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
+		} else if (err)
+			printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
+		/* Register maven bus even on G450/G550 */
+		err = i2c_bus_reg(&m2info->maven, minfo,
+				  MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
+		if (err)
+			printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
+		else {
+			struct i2c_board_info maven_info = {
+				I2C_BOARD_INFO("maven", 0x1b),
+			};
+			unsigned short const addr_list[2] = {
+				0x1b, I2C_CLIENT_END
+			};
+
+			i2c_new_probed_device(&m2info->maven.adapter,
+					      &maven_info, addr_list, NULL);
+		}
+	}
+	return m2info;
+fail_ddc1:;
+	kfree(m2info);
+	printk(KERN_ERR "i2c-matroxfb: Could not register primary adapter DDC bus.\n");
+	return NULL;
+}
+
+static void i2c_matroxfb_remove(struct matrox_fb_info* minfo, void* data) {
+	struct matroxfb_dh_maven_info* m2info = data;
+
+	i2c_maven_done(m2info);
+	i2c_ddc2_done(m2info);
+	i2c_ddc1_done(m2info);
+	kfree(m2info);
+}
+
+static struct matroxfb_driver i2c_matroxfb = {
+	.node =		LIST_HEAD_INIT(i2c_matroxfb.node),
+	.name =		"i2c-matroxfb",
+	.probe = 	i2c_matroxfb_probe,
+	.remove =	i2c_matroxfb_remove,
+};
+
+static int __init i2c_matroxfb_init(void) {
+	if (matroxfb_register_driver(&i2c_matroxfb)) {
+		printk(KERN_ERR "i2c-matroxfb: failed to register driver\n");
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static void __exit i2c_matroxfb_exit(void) {
+	matroxfb_unregister_driver(&i2c_matroxfb);
+}
+
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards");
+
+module_init(i2c_matroxfb_init);
+module_exit(i2c_matroxfb_exit);
+/* no __setup required */
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_DAC1064.c b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c
new file mode 100644
index 000000000000..a01147fdf270
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c
@@ -0,0 +1,1107 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * See matroxfb_base.c for contributors.
+ *
+ */
+
+
+#include "matroxfb_DAC1064.h"
+#include "matroxfb_misc.h"
+#include "matroxfb_accel.h"
+#include "g450_pll.h"
+#include <linux/matroxfb.h>
+
+#ifdef NEED_DAC1064
+#define outDAC1064 matroxfb_DAC_out
+#define inDAC1064 matroxfb_DAC_in
+
+#define DAC1064_OPT_SCLK_PCI	0x00
+#define DAC1064_OPT_SCLK_PLL	0x01
+#define DAC1064_OPT_SCLK_EXT	0x02
+#define DAC1064_OPT_SCLK_MASK	0x03
+#define DAC1064_OPT_GDIV1	0x04	/* maybe it is GDIV2 on G100 ?! */
+#define DAC1064_OPT_GDIV3	0x00
+#define DAC1064_OPT_MDIV1	0x08
+#define DAC1064_OPT_MDIV2	0x00
+#define DAC1064_OPT_RESERVED	0x10
+
+static void DAC1064_calcclock(const struct matrox_fb_info *minfo,
+			      unsigned int freq, unsigned int fmax,
+			      unsigned int *in, unsigned int *feed,
+			      unsigned int *post)
+{
+	unsigned int fvco;
+	unsigned int p;
+
+	DBG(__func__)
+	
+	/* only for devices older than G450 */
+
+	fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p);
+	
+	p = (1 << p) - 1;
+	if (fvco <= 100000)
+		;
+	else if (fvco <= 140000)
+		p |= 0x08;
+	else if (fvco <= 180000)
+		p |= 0x10;
+	else
+		p |= 0x18;
+	*post = p;
+}
+
+/* they must be in POS order */
+static const unsigned char MGA1064_DAC_regs[] = {
+		M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL,
+		M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE,
+		M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE,
+		M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE,
+		DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL,
+		M1064_XMISCCTRL,
+		M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST,
+		M1064_XCRCBITSEL,
+		M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
+
+static const unsigned char MGA1064_DAC[] = {
+		0x00, 0x00, M1064_XCURCTRL_DIS,
+		0x00, 0x00, 0x00, 	/* black */
+		0xFF, 0xFF, 0xFF,	/* white */
+		0xFF, 0x00, 0x00,	/* red */
+		0x00, 0,
+		M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
+		M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
+		M1064_XMISCCTRL_DAC_8BIT,
+		0x00, 0x00, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
+		0x00,
+		0x00, 0x00, 0xFF, 0xFF};
+
+static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout)
+{
+	unsigned int m, n, p;
+
+	DBG(__func__)
+
+	DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p);
+	minfo->hw.DACclk[0] = m;
+	minfo->hw.DACclk[1] = n;
+	minfo->hw.DACclk[2] = p;
+}
+
+static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo,
+			    unsigned long fmem)
+{
+	u_int32_t mx;
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	if (minfo->devflags.noinit) {
+		/* read MCLK and give up... */
+		hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
+		hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
+		hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
+		return;
+	}
+	mx = hw->MXoptionReg | 0x00000004;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
+	mx &= ~0x000000BB;
+	if (oscinfo & DAC1064_OPT_GDIV1)
+		mx |= 0x00000008;
+	if (oscinfo & DAC1064_OPT_MDIV1)
+		mx |= 0x00000010;
+	if (oscinfo & DAC1064_OPT_RESERVED)
+		mx |= 0x00000080;
+	if ((oscinfo & DAC1064_OPT_SCLK_MASK) == DAC1064_OPT_SCLK_PLL) {
+		/* select PCI clock until we have setup oscilator... */
+		int clk;
+		unsigned int m, n, p;
+
+		/* powerup system PLL, select PCI clock */
+		mx |= 0x00000020;
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
+		mx &= ~0x00000004;
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
+
+		/* !!! you must not access device if MCLK is not running !!!
+		   Doing so cause immediate PCI lockup :-( Maybe they should
+		   generate ABORT or I/O (parity...) error and Linux should
+		   recover from this... (kill driver/process). But world is not
+		   perfect... */
+		/* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
+		   select PLL... because of PLL can be stopped at this time) */
+		DAC1064_calcclock(minfo, fmem, minfo->max_pixel_clock, &m, &n, &p);
+		outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3] = m);
+		outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4] = n);
+		outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5] = p);
+		for (clk = 65536; clk; --clk) {
+			if (inDAC1064(minfo, DAC1064_XSYSPLLSTAT) & 0x40)
+				break;
+		}
+		if (!clk)
+			printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n");
+		/* select PLL */
+		mx |= 0x00000005;
+	} else {
+		/* select specified system clock source */
+		mx |= oscinfo & DAC1064_OPT_SCLK_MASK;
+	}
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
+	mx &= ~0x00000004;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
+	hw->MXoptionReg = mx;
+}
+
+#ifdef CONFIG_FB_MATROX_G
+static void g450_set_plls(struct matrox_fb_info *minfo)
+{
+	u_int32_t c2_ctl;
+	unsigned int pxc;
+	struct matrox_hw_state *hw = &minfo->hw;
+	int pixelmnp;
+	int videomnp;
+	
+	c2_ctl = hw->crtc2.ctl & ~0x4007;	/* Clear PLL + enable for CRTC2 */
+	c2_ctl |= 0x0001;			/* Enable CRTC2 */
+	hw->DACreg[POS1064_XPWRCTRL] &= ~0x02;	/* Stop VIDEO PLL */
+	pixelmnp = minfo->crtc1.mnp;
+	videomnp = minfo->crtc2.mnp;
+	if (videomnp < 0) {
+		c2_ctl &= ~0x0001;			/* Disable CRTC2 */
+		hw->DACreg[POS1064_XPWRCTRL] &= ~0x10;	/* Powerdown CRTC2 */
+	} else if (minfo->crtc2.pixclock == minfo->features.pll.ref_freq) {
+		c2_ctl |=  0x4002;	/* Use reference directly */
+	} else if (videomnp == pixelmnp) {
+		c2_ctl |=  0x0004;	/* Use pixel PLL */
+	} else {
+		if (0 == ((videomnp ^ pixelmnp) & 0xFFFFFF00)) {
+			/* PIXEL and VIDEO PLL must not use same frequency. We modify N
+			   of PIXEL PLL in such case because of VIDEO PLL may be source
+			   of TVO clocks, and chroma subcarrier is derived from its
+			   pixel clocks */
+			pixelmnp += 0x000100;
+		}
+		c2_ctl |=  0x0006;	/* Use video PLL */
+		hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
+		
+		outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
+		matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL);
+	}
+
+	hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
+	if (pixelmnp >= 0) {
+		hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
+		
+		outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
+		matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C);
+	}
+	if (c2_ctl != hw->crtc2.ctl) {
+		hw->crtc2.ctl = c2_ctl;
+		mga_outl(0x3C10, c2_ctl);
+	}
+
+	pxc = minfo->crtc1.pixclock;
+	if (pxc == 0 || minfo->outputs[2].src == MATROXFB_SRC_CRTC2) {
+		pxc = minfo->crtc2.pixclock;
+	}
+	if (minfo->chip == MGA_G550) {
+		if (pxc < 45000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x00;	/* 0-50 */
+		} else if (pxc < 55000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x08;	/* 34-62 */
+		} else if (pxc < 70000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x10;	/* 42-78 */
+		} else if (pxc < 85000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x18;	/* 62-92 */
+		} else if (pxc < 100000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x20;	/* 74-108 */
+		} else if (pxc < 115000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x28;	/* 94-122 */
+		} else if (pxc < 125000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x30;	/* 108-132 */
+		} else {
+			hw->DACreg[POS1064_XPANMODE] = 0x38;	/* 120-168 */
+		}
+	} else {
+		/* G450 */
+		if (pxc < 45000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x00;	/* 0-54 */
+		} else if (pxc < 65000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x08;	/* 38-70 */
+		} else if (pxc < 85000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x10;	/* 56-96 */
+		} else if (pxc < 105000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x18;	/* 80-114 */
+		} else if (pxc < 135000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x20;	/* 102-144 */
+		} else if (pxc < 160000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x28;	/* 132-166 */
+		} else if (pxc < 175000) {
+			hw->DACreg[POS1064_XPANMODE] = 0x30;	/* 154-182 */
+		} else {
+			hw->DACreg[POS1064_XPANMODE] = 0x38;	/* 170-204 */
+		}
+	}
+}
+#endif
+
+void DAC1064_global_init(struct matrox_fb_info *minfo)
+{
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
+	hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
+	hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
+#ifdef CONFIG_FB_MATROX_G
+	if (minfo->devflags.g450dac) {
+		hw->DACreg[POS1064_XPWRCTRL] = 0x1F;	/* powerup everything */
+		hw->DACreg[POS1064_XOUTPUTCONN] = 0x00;	/* disable outputs */
+		hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
+		switch (minfo->outputs[0].src) {
+			case MATROXFB_SRC_CRTC1:
+			case MATROXFB_SRC_CRTC2:
+				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01;	/* enable output; CRTC1/2 selection is in CRTC2 ctl */
+				break;
+			case MATROXFB_SRC_NONE:
+				hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN;
+				break;
+		}
+		switch (minfo->outputs[1].src) {
+			case MATROXFB_SRC_CRTC1:
+				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
+				break;
+			case MATROXFB_SRC_CRTC2:
+				if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_MONITOR) {
+					hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08;
+				} else {
+					hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C;
+				}
+				break;
+			case MATROXFB_SRC_NONE:
+				hw->DACreg[POS1064_XPWRCTRL] &= ~0x01;		/* Poweroff DAC2 */
+				break;
+		}
+		switch (minfo->outputs[2].src) {
+			case MATROXFB_SRC_CRTC1:
+				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20;
+				break;
+			case MATROXFB_SRC_CRTC2:
+				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x40;
+				break;
+			case MATROXFB_SRC_NONE:
+#if 0
+				/* HELP! If we boot without DFP connected to DVI, we can
+				   poweroff TMDS. But if we boot with DFP connected,
+				   TMDS generated clocks are used instead of ALL pixclocks
+				   available... If someone knows which register
+				   handles it, please reveal this secret to me... */			
+				hw->DACreg[POS1064_XPWRCTRL] &= ~0x04;		/* Poweroff TMDS */
+#endif				
+				break;
+		}
+		/* Now set timming related variables... */
+		g450_set_plls(minfo);
+	} else
+#endif
+	{
+		if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) {
+			hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
+			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
+		} else if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
+			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
+		} else if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1)
+			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
+		else
+			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
+
+		if (minfo->outputs[0].src != MATROXFB_SRC_NONE)
+			hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
+	}
+}
+
+void DAC1064_global_restore(struct matrox_fb_info *minfo)
+{
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
+	outDAC1064(minfo, M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
+	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
+		outDAC1064(minfo, 0x20, 0x04);
+		outDAC1064(minfo, 0x1F, minfo->devflags.dfp_type);
+		if (minfo->devflags.g450dac) {
+			outDAC1064(minfo, M1064_XSYNCCTRL, 0xCC);
+			outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
+			outDAC1064(minfo, M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]);
+			outDAC1064(minfo, M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
+		}
+	}
+}
+
+static int DAC1064_init_1(struct matrox_fb_info *minfo, struct my_timming *m)
+{
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
+	switch (minfo->fbcon.var.bits_per_pixel) {
+		/* case 4: not supported by MGA1064 DAC */
+		case 8:
+			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+			break;
+		case 16:
+			if (minfo->fbcon.var.green.length == 5)
+				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+			else
+				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+			break;
+		case 24:
+			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_24BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+			break;
+		case 32:
+			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_32BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+			break;
+		default:
+			return 1;	/* unsupported depth */
+	}
+	hw->DACreg[POS1064_XVREFCTRL] = minfo->features.DAC1064.xvrefctrl;
+	hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
+	hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
+	hw->DACreg[POS1064_XCURADDL] = 0;
+	hw->DACreg[POS1064_XCURADDH] = 0;
+
+	DAC1064_global_init(minfo);
+	return 0;
+}
+
+static int DAC1064_init_2(struct matrox_fb_info *minfo, struct my_timming *m)
+{
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	if (minfo->fbcon.var.bits_per_pixel > 16) {	/* 256 entries */
+		int i;
+
+		for (i = 0; i < 256; i++) {
+			hw->DACpal[i * 3 + 0] = i;
+			hw->DACpal[i * 3 + 1] = i;
+			hw->DACpal[i * 3 + 2] = i;
+		}
+	} else if (minfo->fbcon.var.bits_per_pixel > 8) {
+		if (minfo->fbcon.var.green.length == 5) {	/* 0..31, 128..159 */
+			int i;
+
+			for (i = 0; i < 32; i++) {
+				/* with p15 == 0 */
+				hw->DACpal[i * 3 + 0] = i << 3;
+				hw->DACpal[i * 3 + 1] = i << 3;
+				hw->DACpal[i * 3 + 2] = i << 3;
+				/* with p15 == 1 */
+				hw->DACpal[(i + 128) * 3 + 0] = i << 3;
+				hw->DACpal[(i + 128) * 3 + 1] = i << 3;
+				hw->DACpal[(i + 128) * 3 + 2] = i << 3;
+			}
+		} else {
+			int i;
+
+			for (i = 0; i < 64; i++) {		/* 0..63 */
+				hw->DACpal[i * 3 + 0] = i << 3;
+				hw->DACpal[i * 3 + 1] = i << 2;
+				hw->DACpal[i * 3 + 2] = i << 3;
+			}
+		}
+	} else {
+		memset(hw->DACpal, 0, 768);
+	}
+	return 0;
+}
+
+static void DAC1064_restore_1(struct matrox_fb_info *minfo)
+{
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	CRITFLAGS
+
+	DBG(__func__)
+
+	CRITBEGIN
+
+	if ((inDAC1064(minfo, DAC1064_XSYSPLLM) != hw->DACclk[3]) ||
+	    (inDAC1064(minfo, DAC1064_XSYSPLLN) != hw->DACclk[4]) ||
+	    (inDAC1064(minfo, DAC1064_XSYSPLLP) != hw->DACclk[5])) {
+		outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3]);
+		outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4]);
+		outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5]);
+	}
+	{
+		unsigned int i;
+
+		for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
+			if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL))
+				outDAC1064(minfo, MGA1064_DAC_regs[i], hw->DACreg[i]);
+		}
+	}
+
+	DAC1064_global_restore(minfo);
+
+	CRITEND
+};
+
+static void DAC1064_restore_2(struct matrox_fb_info *minfo)
+{
+#ifdef DEBUG
+	unsigned int i;
+#endif
+
+	DBG(__func__)
+
+#ifdef DEBUG
+	dprintk(KERN_DEBUG "DAC1064regs ");
+	for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
+		dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], minfo->hw.DACreg[i]);
+		if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
+	}
+	dprintk(KERN_DEBUG "DAC1064clk ");
+	for (i = 0; i < 6; i++)
+		dprintk("C%02X=%02X ", i, minfo->hw.DACclk[i]);
+	dprintk("\n");
+#endif
+}
+
+static int m1064_compute(void* out, struct my_timming* m) {
+#define minfo ((struct matrox_fb_info*)out)
+	{
+		int i;
+		int tmout;
+		CRITFLAGS
+
+		DAC1064_setpclk(minfo, m->pixclock);
+
+		CRITBEGIN
+
+		for (i = 0; i < 3; i++)
+			outDAC1064(minfo, M1064_XPIXPLLCM + i, minfo->hw.DACclk[i]);
+		for (tmout = 500000; tmout; tmout--) {
+			if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
+				break;
+			udelay(10);
+		}
+
+		CRITEND
+
+		if (!tmout)
+			printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+	}
+#undef minfo
+	return 0;
+}
+
+static struct matrox_altout m1064 = {
+	.name	 = "Primary output",
+	.compute = m1064_compute,
+};
+
+#ifdef CONFIG_FB_MATROX_G
+static int g450_compute(void* out, struct my_timming* m) {
+#define minfo ((struct matrox_fb_info*)out)
+	if (m->mnp < 0) {
+		m->mnp = matroxfb_g450_setclk(minfo, m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
+		if (m->mnp >= 0) {
+			m->pixclock = g450_mnp2f(minfo, m->mnp);
+		}
+	}
+#undef minfo
+	return 0;
+}
+
+static struct matrox_altout g450out = {
+	.name	 = "Primary output",
+	.compute = g450_compute,
+};
+#endif
+
+#endif /* NEED_DAC1064 */
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static int MGA1064_init(struct matrox_fb_info *minfo, struct my_timming *m)
+{
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	if (DAC1064_init_1(minfo, m)) return 1;
+	if (matroxfb_vgaHWinit(minfo, m)) return 1;
+
+	hw->MiscOutReg = 0xCB;
+	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
+		hw->MiscOutReg &= ~0x40;
+	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
+		hw->MiscOutReg &= ~0x80;
+	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
+		hw->CRTCEXT[3] |= 0x40;
+
+	if (DAC1064_init_2(minfo, m)) return 1;
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_G
+static int MGAG100_init(struct matrox_fb_info *minfo, struct my_timming *m)
+{
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	if (DAC1064_init_1(minfo, m)) return 1;
+	hw->MXoptionReg &= ~0x2000;
+	if (matroxfb_vgaHWinit(minfo, m)) return 1;
+
+	hw->MiscOutReg = 0xEF;
+	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
+		hw->MiscOutReg &= ~0x40;
+	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
+		hw->MiscOutReg &= ~0x80;
+	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
+		hw->CRTCEXT[3] |= 0x40;
+
+	if (DAC1064_init_2(minfo, m)) return 1;
+	return 0;
+}
+#endif	/* G */
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static void MGA1064_ramdac_init(struct matrox_fb_info *minfo)
+{
+
+	DBG(__func__)
+
+	/* minfo->features.DAC1064.vco_freq_min = 120000; */
+	minfo->features.pll.vco_freq_min = 62000;
+	minfo->features.pll.ref_freq	 = 14318;
+	minfo->features.pll.feed_div_min = 100;
+	minfo->features.pll.feed_div_max = 127;
+	minfo->features.pll.in_div_min	 = 1;
+	minfo->features.pll.in_div_max	 = 31;
+	minfo->features.pll.post_shift_max = 3;
+	minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_EXTERNAL;
+	/* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
+	DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_G
+/* BIOS environ */
+static int x7AF4 = 0x10;	/* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
+				/* G100 wants 0x10, G200 SGRAM does not care... */
+#if 0
+static int def50 = 0;	/* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
+#endif
+
+static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags,
+				 int m, int n, int p)
+{
+	int reg;
+	int selClk;
+	int clk;
+
+	DBG(__func__)
+
+	outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
+		   M1064_XPIXCLKCTRL_PLL_UP);
+	switch (flags & 3) {
+		case 0:		reg = M1064_XPIXPLLAM; break;
+		case 1:		reg = M1064_XPIXPLLBM; break;
+		default:	reg = M1064_XPIXPLLCM; break;
+	}
+	outDAC1064(minfo, reg++, m);
+	outDAC1064(minfo, reg++, n);
+	outDAC1064(minfo, reg, p);
+	selClk = mga_inb(M_MISC_REG_READ) & ~0xC;
+	/* there should be flags & 0x03 & case 0/1/else */
+	/* and we should first select source and after that we should wait for PLL */
+	/* and we are waiting for PLL with oscilator disabled... Is it right? */
+	switch (flags & 0x03) {
+		case 0x00:	break;
+		case 0x01:	selClk |= 4; break;
+		default:	selClk |= 0x0C; break;
+	}
+	mga_outb(M_MISC_REG, selClk);
+	for (clk = 500000; clk; clk--) {
+		if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
+			break;
+		udelay(10);
+	}
+	if (!clk)
+		printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
+	selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
+	switch (flags & 0x0C) {
+		case 0x00:	selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break;
+		case 0x04:	selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break;
+		default:	selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break;
+	}
+	outDAC1064(minfo, M1064_XPIXCLKCTRL, selClk);
+	outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
+}
+
+static void MGAG100_setPixClock(const struct matrox_fb_info *minfo, int flags,
+				int freq)
+{
+	unsigned int m, n, p;
+
+	DBG(__func__)
+
+	DAC1064_calcclock(minfo, freq, minfo->max_pixel_clock, &m, &n, &p);
+	MGAG100_progPixClock(minfo, flags, m, n, p);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static int MGA1064_preinit(struct matrox_fb_info *minfo)
+{
+	static const int vxres_mystique[] = { 512,        640, 768,  800,  832,  960,
+					     1024, 1152, 1280,      1600, 1664, 1920,
+					     2048,    0};
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	/* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
+	minfo->capable.text = 1;
+	minfo->capable.vxres = vxres_mystique;
+
+	minfo->outputs[0].output = &m1064;
+	minfo->outputs[0].src = minfo->outputs[0].default_src;
+	minfo->outputs[0].data = minfo;
+	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+
+	if (minfo->devflags.noinit)
+		return 0;	/* do not modify settings */
+	hw->MXoptionReg &= 0xC0000100;
+	hw->MXoptionReg |= 0x00094E20;
+	if (minfo->devflags.novga)
+		hw->MXoptionReg &= ~0x00000100;
+	if (minfo->devflags.nobios)
+		hw->MXoptionReg &= ~0x40000000;
+	if (minfo->devflags.nopciretry)
+		hw->MXoptionReg |=  0x20000000;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+	mga_setr(M_SEQ_INDEX, 0x01, 0x20);
+	mga_outl(M_CTLWTST, 0x00000000);
+	udelay(200);
+	mga_outl(M_MACCESS, 0x00008000);
+	udelay(100);
+	mga_outl(M_MACCESS, 0x0000C000);
+	return 0;
+}
+
+static void MGA1064_reset(struct matrox_fb_info *minfo)
+{
+
+	DBG(__func__);
+
+	MGA1064_ramdac_init(minfo);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_G
+static void g450_mclk_init(struct matrox_fb_info *minfo)
+{
+	/* switch all clocks to PCI source */
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3 & ~0x00300C03);
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
+
+	if (((minfo->values.reg.opt3 & 0x000003) == 0x000003) ||
+	    ((minfo->values.reg.opt3 & 0x000C00) == 0x000C00) ||
+	    ((minfo->values.reg.opt3 & 0x300000) == 0x300000)) {
+		matroxfb_g450_setclk(minfo, minfo->values.pll.video, M_VIDEO_PLL);
+	} else {
+		unsigned long flags;
+		unsigned int pwr;
+		
+		matroxfb_DAC_lock_irqsave(flags);
+		pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02;
+		outDAC1064(minfo, M1064_XPWRCTRL, pwr);
+		matroxfb_DAC_unlock_irqrestore(flags);
+	}
+	matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL);
+	
+	/* switch clocks to their real PLL source(s) */
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3);
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
+
+}
+
+static void g450_memory_init(struct matrox_fb_info *minfo)
+{
+	/* disable memory refresh */
+	minfo->hw.MXoptionReg &= ~0x001F8000;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
+	
+	/* set memory interface parameters */
+	minfo->hw.MXoptionReg &= ~0x00207E00;
+	minfo->hw.MXoptionReg |= 0x00207E00 & minfo->values.reg.opt;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, minfo->values.reg.opt2);
+	
+	mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
+	
+	/* first set up memory interface with disabled memory interface clocks */
+	pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc & ~0x80000000U);
+	mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
+	mga_outl(M_MACCESS, minfo->values.reg.maccess);
+	/* start memory clocks */
+	pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U);
+
+	udelay(200);
+	
+	if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) {
+		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000);
+	}
+	mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000);
+	
+	udelay(200);
+	
+	minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
+	
+	/* value is written to memory chips only if old != new */
+	mga_outl(M_PLNWT, 0);
+	mga_outl(M_PLNWT, ~0);
+	
+	if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) {
+		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core);
+	}
+	
+}
+
+static void g450_preinit(struct matrox_fb_info *minfo)
+{
+	u_int32_t c2ctl;
+	u_int8_t curctl;
+	u_int8_t c1ctl;
+	
+	/* minfo->hw.MXoptionReg = minfo->values.reg.opt; */
+	minfo->hw.MXoptionReg &= 0xC0000100;
+	minfo->hw.MXoptionReg |= 0x00000020;
+	if (minfo->devflags.novga)
+		minfo->hw.MXoptionReg &= ~0x00000100;
+	if (minfo->devflags.nobios)
+		minfo->hw.MXoptionReg &= ~0x40000000;
+	if (minfo->devflags.nopciretry)
+		minfo->hw.MXoptionReg |=  0x20000000;
+	minfo->hw.MXoptionReg |= minfo->values.reg.opt & 0x03400040;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
+
+	/* Init system clocks */
+		
+	/* stop crtc2 */
+	c2ctl = mga_inl(M_C2CTL);
+	mga_outl(M_C2CTL, c2ctl & ~1);
+	/* stop cursor */
+	curctl = inDAC1064(minfo, M1064_XCURCTRL);
+	outDAC1064(minfo, M1064_XCURCTRL, 0);
+	/* stop crtc1 */
+	c1ctl = mga_readr(M_SEQ_INDEX, 1);
+	mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
+
+	g450_mclk_init(minfo);
+	g450_memory_init(minfo);
+	
+	/* set legacy VGA clock sources for DOSEmu or VMware... */
+	matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A);
+	matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B);
+
+	/* restore crtc1 */
+	mga_setr(M_SEQ_INDEX, 1, c1ctl);
+	
+	/* restore cursor */
+	outDAC1064(minfo, M1064_XCURCTRL, curctl);
+
+	/* restore crtc2 */
+	mga_outl(M_C2CTL, c2ctl);
+	
+	return;
+}
+
+static int MGAG100_preinit(struct matrox_fb_info *minfo)
+{
+	static const int vxres_g100[] = {  512,        640, 768,  800,  832,  960,
+                                          1024, 1152, 1280,      1600, 1664, 1920,
+                                          2048, 0};
+	struct matrox_hw_state *hw = &minfo->hw;
+
+        u_int32_t reg50;
+#if 0
+	u_int32_t q;
+#endif
+
+	DBG(__func__)
+
+	/* there are some instabilities if in_div > 19 && vco < 61000 */
+	if (minfo->devflags.g450dac) {
+		minfo->features.pll.vco_freq_min = 130000;	/* my sample: >118 */
+	} else {
+		minfo->features.pll.vco_freq_min = 62000;
+	}
+	if (!minfo->features.pll.ref_freq) {
+		minfo->features.pll.ref_freq	 = 27000;
+	}
+	minfo->features.pll.feed_div_min = 7;
+	minfo->features.pll.feed_div_max = 127;
+	minfo->features.pll.in_div_min	 = 1;
+	minfo->features.pll.in_div_max	 = 31;
+	minfo->features.pll.post_shift_max = 3;
+	minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_G100_DEFAULT;
+	/* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
+	minfo->capable.text = 1;
+	minfo->capable.vxres = vxres_g100;
+	minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100
+			? minfo->devflags.sgram : 1;
+
+	if (minfo->devflags.g450dac) {
+		minfo->outputs[0].output = &g450out;
+	} else {
+		minfo->outputs[0].output = &m1064;
+	}
+	minfo->outputs[0].src = minfo->outputs[0].default_src;
+	minfo->outputs[0].data = minfo;
+	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+
+	if (minfo->devflags.g450dac) {
+		/* we must do this always, BIOS does not do it for us
+		   and accelerator dies without it */
+		mga_outl(0x1C0C, 0);
+	}
+	if (minfo->devflags.noinit)
+		return 0;
+	if (minfo->devflags.g450dac) {
+		g450_preinit(minfo);
+		return 0;
+	}
+	hw->MXoptionReg &= 0xC0000100;
+	hw->MXoptionReg |= 0x00000020;
+	if (minfo->devflags.novga)
+		hw->MXoptionReg &= ~0x00000100;
+	if (minfo->devflags.nobios)
+		hw->MXoptionReg &= ~0x40000000;
+	if (minfo->devflags.nopciretry)
+		hw->MXoptionReg |=  0x20000000;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+	DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
+
+	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) {
+		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
+		reg50 &= ~0x3000;
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
+
+		hw->MXoptionReg |= 0x1080;
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
+		udelay(100);
+		mga_outb(0x1C05, 0x00);
+		mga_outb(0x1C05, 0x80);
+		udelay(100);
+		mga_outb(0x1C05, 0x40);
+		mga_outb(0x1C05, 0xC0);
+		udelay(100);
+		reg50 &= ~0xFF;
+		reg50 |=  0x07;
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
+		/* it should help with G100 */
+		mga_outb(M_GRAPHICS_INDEX, 6);
+		mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
+		mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
+		mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
+		mga_writeb(minfo->video.vbase, 0x0000, 0xAA);
+		mga_writeb(minfo->video.vbase, 0x0800, 0x55);
+		mga_writeb(minfo->video.vbase, 0x4000, 0x55);
+#if 0
+		if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {
+			hw->MXoptionReg &= ~0x1000;
+		}
+#endif
+		hw->MXoptionReg |= 0x00078020;
+	} else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) {
+		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
+		reg50 &= ~0x3000;
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
+
+		if (minfo->devflags.memtype == -1)
+			hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
+		else
+			hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
+		if (minfo->devflags.sgram)
+			hw->MXoptionReg |= 0x4000;
+		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
+		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
+		udelay(200);
+		mga_outl(M_MACCESS, 0x00000000);
+		mga_outl(M_MACCESS, 0x00008000);
+		udelay(100);
+		mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk);
+		hw->MXoptionReg |= 0x00078020;
+	} else {
+		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
+		reg50 &= ~0x00000100;
+		reg50 |=  0x00000000;
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
+
+		if (minfo->devflags.memtype == -1)
+			hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
+		else
+			hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
+		if (minfo->devflags.sgram)
+			hw->MXoptionReg |= 0x4000;
+		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
+		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
+		udelay(200);
+		mga_outl(M_MACCESS, 0x00000000);
+		mga_outl(M_MACCESS, 0x00008000);
+		udelay(100);
+		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
+		hw->MXoptionReg |= 0x00040020;
+	}
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+	return 0;
+}
+
+static void MGAG100_reset(struct matrox_fb_info *minfo)
+{
+	u_int8_t b;
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	{
+#ifdef G100_BROKEN_IBM_82351
+		u_int32_t d;
+
+		find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
+		pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
+		if (b == minfo->pcidev->bus->number) {
+			pci_write_config_byte(ibm, PCI_COMMAND+1, 0);	/* disable back-to-back & SERR */
+			pci_write_config_byte(ibm, 0x41, 0xF4);		/* ??? */
+			pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0);	/* ??? */
+			pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00);	/* ??? */
+		}
+#endif
+		if (!minfo->devflags.noinit) {
+			if (x7AF4 & 8) {
+				hw->MXoptionReg |= 0x40;	/* FIXME... */
+				pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+			}
+			mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
+		}
+	}
+	if (minfo->devflags.g450dac) {
+		/* either leave MCLK as is... or they were set in preinit */
+		hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
+		hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
+		hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
+	} else {
+		DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
+	}
+	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
+		if (minfo->devflags.dfp_type == -1) {
+			minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F);
+		}
+	}
+	if (minfo->devflags.noinit)
+		return;
+	if (minfo->devflags.g450dac) {
+	} else {
+		MGAG100_setPixClock(minfo, 4, 25175);
+		MGAG100_setPixClock(minfo, 5, 28322);
+		if (x7AF4 & 0x10) {
+			b = inDAC1064(minfo, M1064_XGENIODATA) & ~1;
+			outDAC1064(minfo, M1064_XGENIODATA, b);
+			b = inDAC1064(minfo, M1064_XGENIOCTRL) | 1;
+			outDAC1064(minfo, M1064_XGENIOCTRL, b);
+		}
+	}
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static void MGA1064_restore(struct matrox_fb_info *minfo)
+{
+	int i;
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	CRITFLAGS
+
+	DBG(__func__)
+
+	CRITBEGIN
+
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+	mga_outb(M_IEN, 0x00);
+	mga_outb(M_CACHEFLUSH, 0x00);
+
+	CRITEND
+
+	DAC1064_restore_1(minfo);
+	matroxfb_vgaHWrestore(minfo);
+	minfo->crtc1.panpos = -1;
+	for (i = 0; i < 6; i++)
+		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
+	DAC1064_restore_2(minfo);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_G
+static void MGAG100_restore(struct matrox_fb_info *minfo)
+{
+	int i;
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	CRITFLAGS
+
+	DBG(__func__)
+
+	CRITBEGIN
+
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+	CRITEND
+
+	DAC1064_restore_1(minfo);
+	matroxfb_vgaHWrestore(minfo);
+	if (minfo->devflags.support32MB)
+		mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
+	minfo->crtc1.panpos = -1;
+	for (i = 0; i < 6; i++)
+		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
+	DAC1064_restore_2(minfo);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+struct matrox_switch matrox_mystique = {
+	MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore,
+};
+EXPORT_SYMBOL(matrox_mystique);
+#endif
+
+#ifdef CONFIG_FB_MATROX_G
+struct matrox_switch matrox_G100 = {
+	MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore,
+};
+EXPORT_SYMBOL(matrox_G100);
+#endif
+
+#ifdef NEED_DAC1064
+EXPORT_SYMBOL(DAC1064_global_init);
+EXPORT_SYMBOL(DAC1064_global_restore);
+#endif
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_DAC1064.h b/drivers/video/fbdev/matrox/matroxfb_DAC1064.h
new file mode 100644
index 000000000000..1e6e45b57b78
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.h
@@ -0,0 +1,179 @@
+#ifndef __MATROXFB_DAC1064_H__
+#define __MATROXFB_DAC1064_H__
+
+
+#include "matroxfb_base.h"
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+extern struct matrox_switch matrox_mystique;
+#endif
+#ifdef CONFIG_FB_MATROX_G
+extern struct matrox_switch matrox_G100;
+#endif
+#ifdef NEED_DAC1064
+void DAC1064_global_init(struct matrox_fb_info *minfo);
+void DAC1064_global_restore(struct matrox_fb_info *minfo);
+#endif
+
+#define M1064_INDEX	0x00
+#define M1064_PALWRADD	0x00
+#define M1064_PALDATA	0x01
+#define M1064_PIXRDMSK	0x02
+#define M1064_PALRDADD	0x03
+#define M1064_X_DATAREG	0x0A
+#define M1064_CURPOSXL	0x0C	/* can be accessed as DWORD */
+#define M1064_CURPOSXH	0x0D
+#define M1064_CURPOSYL	0x0E
+#define M1064_CURPOSYH	0x0F
+
+#define M1064_XCURADDL		0x04
+#define M1064_XCURADDH		0x05
+#define M1064_XCURCTRL		0x06
+#define     M1064_XCURCTRL_DIS		0x00	/* transparent, transparent, transparent, transparent */
+#define     M1064_XCURCTRL_3COLOR	0x01	/* transparent, 0, 1, 2 */
+#define     M1064_XCURCTRL_XGA		0x02	/* 0, 1, transparent, complement */
+#define     M1064_XCURCTRL_XWIN		0x03	/* transparent, transparent, 0, 1 */
+	/* drive DVI by standard(0)/DVI(1) PLL */
+	/* if set(1), C?DVICLKEN and C?DVICLKSEL must be set(1) */
+#define      M1064_XDVICLKCTRL_DVIDATAPATHSEL   0x01
+	/* drive CRTC1 by standard(0)/DVI(1) PLL */
+#define      M1064_XDVICLKCTRL_C1DVICLKSEL      0x02
+	/* drive CRTC2 by standard(0)/DVI(1) PLL */
+#define      M1064_XDVICLKCTRL_C2DVICLKSEL      0x04
+	/* pixel clock allowed to(0)/blocked from(1) driving CRTC1 */
+#define      M1064_XDVICLKCTRL_C1DVICLKEN       0x08
+	/* DVI PLL loop filter bandwidth selection bits */
+#define      M1064_XDVICLKCTRL_DVILOOPCTL       0x30
+	/* CRTC2 pixel clock allowed to(0)/blocked from(1) driving CRTC2 */
+#define      M1064_XDVICLKCTRL_C2DVICLKEN       0x40
+	/* P1PLL loop filter bandwidth selection */
+#define      M1064_XDVICLKCTRL_P1LOOPBWDTCTL    0x80
+#define M1064_XCURCOL0RED	0x08
+#define M1064_XCURCOL0GREEN	0x09
+#define M1064_XCURCOL0BLUE	0x0A
+#define M1064_XCURCOL1RED	0x0C
+#define M1064_XCURCOL1GREEN	0x0D
+#define M1064_XCURCOL1BLUE	0x0E
+#define M1064_XDVICLKCTRL	0x0F
+#define M1064_XCURCOL2RED	0x10
+#define M1064_XCURCOL2GREEN	0x11
+#define M1064_XCURCOL2BLUE	0x12
+#define DAC1064_XVREFCTRL	0x18
+#define      DAC1064_XVREFCTRL_INTERNAL		0x3F
+#define      DAC1064_XVREFCTRL_EXTERNAL		0x00
+#define      DAC1064_XVREFCTRL_G100_DEFAULT	0x03
+#define M1064_XMULCTRL		0x19
+#define      M1064_XMULCTRL_DEPTH_8BPP		0x00	/* 8 bpp paletized */
+#define      M1064_XMULCTRL_DEPTH_15BPP_1BPP	0x01	/* 15 bpp paletized + 1 bpp overlay */
+#define      M1064_XMULCTRL_DEPTH_16BPP		0x02	/* 16 bpp paletized */
+#define      M1064_XMULCTRL_DEPTH_24BPP		0x03	/* 24 bpp paletized */
+#define      M1064_XMULCTRL_DEPTH_24BPP_8BPP	0x04	/* 24 bpp direct + 8 bpp overlay paletized */
+#define      M1064_XMULCTRL_2G8V16		0x05	/* 15 bpp video direct, half xres, 8bpp paletized */
+#define      M1064_XMULCTRL_G16V16		0x06	/* 15 bpp video, 15bpp graphics, one of them paletized */
+#define      M1064_XMULCTRL_DEPTH_32BPP		0x07	/* 24 bpp paletized + 8 bpp unused */
+#define      M1064_XMULCTRL_GRAPHICS_PALETIZED	0x00
+#define      M1064_XMULCTRL_VIDEO_PALETIZED	0x08
+#define M1064_XPIXCLKCTRL	0x1A
+#define      M1064_XPIXCLKCTRL_SRC_PCI		0x00
+#define      M1064_XPIXCLKCTRL_SRC_PLL		0x01
+#define      M1064_XPIXCLKCTRL_SRC_EXT		0x02
+#define	     M1064_XPIXCLKCTRL_SRC_SYS		0x03	/* G200/G400 */
+#define      M1064_XPIXCLKCTRL_SRC_PLL2		0x03	/* G450 */
+#define      M1064_XPIXCLKCTRL_SRC_MASK		0x03
+#define      M1064_XPIXCLKCTRL_EN		0x00
+#define      M1064_XPIXCLKCTRL_DIS		0x04
+#define      M1064_XPIXCLKCTRL_PLL_DOWN		0x00
+#define      M1064_XPIXCLKCTRL_PLL_UP		0x08
+#define M1064_XGENCTRL		0x1D
+#define      M1064_XGENCTRL_VS_0		0x00
+#define      M1064_XGENCTRL_VS_1		0x01
+#define      M1064_XGENCTRL_ALPHA_DIS		0x00
+#define      M1064_XGENCTRL_ALPHA_EN		0x02
+#define      M1064_XGENCTRL_BLACK_0IRE		0x00
+#define      M1064_XGENCTRL_BLACK_75IRE		0x10
+#define      M1064_XGENCTRL_SYNC_ON_GREEN	0x00
+#define      M1064_XGENCTRL_NO_SYNC_ON_GREEN	0x20
+#define      M1064_XGENCTRL_SYNC_ON_GREEN_MASK	0x20
+#define M1064_XMISCCTRL		0x1E
+#define      M1064_XMISCCTRL_DAC_DIS		0x00
+#define      M1064_XMISCCTRL_DAC_EN		0x01
+#define      M1064_XMISCCTRL_MFC_VGA		0x00
+#define      M1064_XMISCCTRL_MFC_MAFC		0x02
+#define      M1064_XMISCCTRL_MFC_DIS		0x06
+#define      GX00_XMISCCTRL_MFC_MAFC		0x02
+#define      GX00_XMISCCTRL_MFC_PANELLINK	0x04
+#define      GX00_XMISCCTRL_MFC_DIS		0x06
+#define      GX00_XMISCCTRL_MFC_MASK		0x06
+#define      M1064_XMISCCTRL_DAC_6BIT		0x00
+#define      M1064_XMISCCTRL_DAC_8BIT		0x08
+#define      M1064_XMISCCTRL_DAC_WIDTHMASK	0x08
+#define      M1064_XMISCCTRL_LUT_DIS		0x00
+#define      M1064_XMISCCTRL_LUT_EN		0x10
+#define      G400_XMISCCTRL_VDO_MAFC12		0x00
+#define      G400_XMISCCTRL_VDO_BYPASS656	0x40
+#define      G400_XMISCCTRL_VDO_C2_MAFC12	0x80
+#define      G400_XMISCCTRL_VDO_C2_BYPASS656	0xC0
+#define      G400_XMISCCTRL_VDO_MASK		0xE0
+#define M1064_XGENIOCTRL	0x2A
+#define M1064_XGENIODATA	0x2B
+#define DAC1064_XSYSPLLM	0x2C
+#define DAC1064_XSYSPLLN	0x2D
+#define DAC1064_XSYSPLLP	0x2E
+#define DAC1064_XSYSPLLSTAT	0x2F
+#define M1064_XZOOMCTRL		0x38
+#define      M1064_XZOOMCTRL_1			0x00
+#define      M1064_XZOOMCTRL_2			0x01
+#define      M1064_XZOOMCTRL_4			0x03
+#define M1064_XSENSETEST	0x3A
+#define      M1064_XSENSETEST_BCOMP		0x01
+#define      M1064_XSENSETEST_GCOMP		0x02
+#define      M1064_XSENSETEST_RCOMP		0x04
+#define      M1064_XSENSETEST_PDOWN		0x00
+#define      M1064_XSENSETEST_PUP		0x80
+#define M1064_XCRCREML		0x3C
+#define M1064_XCRCREMH		0x3D
+#define M1064_XCRCBITSEL	0x3E
+#define M1064_XCOLKEYMASKL	0x40
+#define M1064_XCOLKEYMASKH	0x41
+#define M1064_XCOLKEYL		0x42
+#define M1064_XCOLKEYH		0x43
+#define M1064_XPIXPLLAM		0x44
+#define M1064_XPIXPLLAN		0x45
+#define M1064_XPIXPLLAP		0x46
+#define M1064_XPIXPLLBM		0x48
+#define M1064_XPIXPLLBN		0x49
+#define M1064_XPIXPLLBP		0x4A
+#define M1064_XPIXPLLCM		0x4C
+#define M1064_XPIXPLLCN		0x4D
+#define M1064_XPIXPLLCP		0x4E
+#define M1064_XPIXPLLSTAT	0x4F
+
+#define M1064_XTVO_IDX		0x87
+#define M1064_XTVO_DATA		0x88
+
+#define M1064_XOUTPUTCONN	0x8A
+#define M1064_XSYNCCTRL		0x8B
+#define M1064_XVIDPLLSTAT	0x8C
+#define M1064_XVIDPLLP		0x8D
+#define M1064_XVIDPLLM		0x8E
+#define M1064_XVIDPLLN		0x8F
+
+#define M1064_XPWRCTRL		0xA0
+#define     M1064_XPWRCTRL_PANELPDN	0x04
+
+#define M1064_XPANMODE		0xA2
+
+enum POS1064 {
+	POS1064_XCURADDL=0, POS1064_XCURADDH, POS1064_XCURCTRL,
+	POS1064_XCURCOL0RED, POS1064_XCURCOL0GREEN, POS1064_XCURCOL0BLUE,
+	POS1064_XCURCOL1RED, POS1064_XCURCOL1GREEN, POS1064_XCURCOL1BLUE,
+	POS1064_XCURCOL2RED, POS1064_XCURCOL2GREEN, POS1064_XCURCOL2BLUE,
+	POS1064_XVREFCTRL, POS1064_XMULCTRL, POS1064_XPIXCLKCTRL, POS1064_XGENCTRL,
+	POS1064_XMISCCTRL,
+	POS1064_XGENIOCTRL, POS1064_XGENIODATA, POS1064_XZOOMCTRL, POS1064_XSENSETEST,
+	POS1064_XCRCBITSEL,
+	POS1064_XCOLKEYMASKL, POS1064_XCOLKEYMASKH, POS1064_XCOLKEYL, POS1064_XCOLKEYH,
+	POS1064_XOUTPUTCONN, POS1064_XPANMODE, POS1064_XPWRCTRL };
+
+
+#endif	/* __MATROXFB_DAC1064_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
new file mode 100644
index 000000000000..195ad7cac1ba
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
@@ -0,0 +1,745 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
+ *
+ * Contributors: "menion?" <menion@mindless.com>
+ *                     Betatesting, fixes, ideas
+ *
+ *               "Kurt Garloff" <garloff@suse.de>
+ *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
+ *
+ *               "Tom Rini" <trini@kernel.crashing.org>
+ *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
+ *
+ *               "Bibek Sahu" <scorpio@dodds.net>
+ *                     Access device through readb|w|l and write b|w|l
+ *                     Extensive debugging stuff
+ *
+ *               "Daniel Haun" <haund@usa.net>
+ *                     Testing, hardware cursor fixes
+ *
+ *               "Scott Wood" <sawst46+@pitt.edu>
+ *                     Fixes
+ *
+ *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
+ *                     Betatesting
+ *
+ *               "Kelly French" <targon@hazmat.com>
+ *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
+ *                     Betatesting, bug reporting
+ *
+ *               "Pablo Bianucci" <pbian@pccp.com.ar>
+ *                     Fixes, ideas, betatesting
+ *
+ *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
+ *                     Fixes, enhandcements, ideas, betatesting
+ *
+ *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
+ *                     PPC betatesting, PPC support, backward compatibility
+ *
+ *               "Paul Womar" <Paul@pwomar.demon.co.uk>
+ *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
+ *                     PPC betatesting
+ *
+ *               "Thomas Pornin" <pornin@bolet.ens.fr>
+ *                     Alpha betatesting
+ *
+ *               "Pieter van Leuven" <pvl@iae.nl>
+ *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
+ *                     G100 testing
+ *
+ *               "H. Peter Arvin" <hpa@transmeta.com>
+ *                     Ideas
+ *
+ *               "Cort Dougan" <cort@cs.nmt.edu>
+ *                     CHRP fixes and PReP cleanup
+ *
+ *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
+ *                     G400 support
+ *
+ * (following author is not in any relation with this code, but his code
+ *  is included in this driver)
+ *
+ * Based on framebuffer driver for VBE 2.0 compliant graphic boards
+ *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * (following author is not in any relation with this code, but his ideas
+ *  were used when writing this driver)
+ *
+ *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
+ *
+ */
+
+
+#include "matroxfb_Ti3026.h"
+#include "matroxfb_misc.h"
+#include "matroxfb_accel.h"
+#include <linux/matroxfb.h>
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+#define outTi3026 matroxfb_DAC_out
+#define inTi3026 matroxfb_DAC_in
+
+#define TVP3026_INDEX		0x00
+#define TVP3026_PALWRADD	0x00
+#define TVP3026_PALDATA		0x01
+#define TVP3026_PIXRDMSK	0x02
+#define TVP3026_PALRDADD	0x03
+#define TVP3026_CURCOLWRADD	0x04
+#define     TVP3026_CLOVERSCAN		0x00
+#define     TVP3026_CLCOLOR0		0x01
+#define     TVP3026_CLCOLOR1		0x02
+#define     TVP3026_CLCOLOR2		0x03
+#define TVP3026_CURCOLDATA	0x05
+#define TVP3026_CURCOLRDADD	0x07
+#define TVP3026_CURCTRL		0x09
+#define TVP3026_X_DATAREG	0x0A
+#define TVP3026_CURRAMDATA	0x0B
+#define TVP3026_CURPOSXL	0x0C
+#define TVP3026_CURPOSXH	0x0D
+#define TVP3026_CURPOSYL	0x0E
+#define TVP3026_CURPOSYH	0x0F
+
+#define TVP3026_XSILICONREV	0x01
+#define TVP3026_XCURCTRL	0x06
+#define     TVP3026_XCURCTRL_DIS	0x00	/* transparent, transparent, transparent, transparent */
+#define     TVP3026_XCURCTRL_3COLOR	0x01	/* transparent, 0, 1, 2 */
+#define     TVP3026_XCURCTRL_XGA	0x02	/* 0, 1, transparent, complement */
+#define     TVP3026_XCURCTRL_XWIN	0x03	/* transparent, transparent, 0, 1 */
+#define     TVP3026_XCURCTRL_BLANK2048	0x00
+#define     TVP3026_XCURCTRL_BLANK4096	0x10
+#define     TVP3026_XCURCTRL_INTERLACED	0x20
+#define     TVP3026_XCURCTRL_ODD	0x00 /* ext.signal ODD/\EVEN */
+#define     TVP3026_XCURCTRL_EVEN	0x40 /* ext.signal EVEN/\ODD */
+#define     TVP3026_XCURCTRL_INDIRECT	0x00
+#define     TVP3026_XCURCTRL_DIRECT	0x80
+#define TVP3026_XLATCHCTRL	0x0F
+#define     TVP3026_XLATCHCTRL_1_1	0x06
+#define     TVP3026_XLATCHCTRL_2_1	0x07
+#define     TVP3026_XLATCHCTRL_4_1	0x06
+#define     TVP3026_XLATCHCTRL_8_1	0x06
+#define     TVP3026_XLATCHCTRL_16_1	0x06
+#define     TVP3026A_XLATCHCTRL_4_3	0x06	/* ??? do not understand... but it works... !!! */
+#define     TVP3026A_XLATCHCTRL_8_3	0x07
+#define     TVP3026B_XLATCHCTRL_4_3	0x08
+#define     TVP3026B_XLATCHCTRL_8_3	0x06	/* ??? do not understand... but it works... !!! */
+#define TVP3026_XTRUECOLORCTRL	0x18
+#define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL	0x00
+#define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP	0x20
+#define     TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR		0x80
+#define     TVP3026_XTRUECOLORCTRL_TRUECOLOR		0x40 /* paletized */
+#define     TVP3026_XTRUECOLORCTRL_DIRECTCOLOR		0x00
+#define     TVP3026_XTRUECOLORCTRL_24_ALTERNATE		0x08 /* 5:4/5:2 instead of 4:3/8:3 */
+#define     TVP3026_XTRUECOLORCTRL_RGB_888		0x16 /* 4:3/8:3 (or 5:4/5:2) */
+#define	    TVP3026_XTRUECOLORCTRL_BGR_888		0x17
+#define     TVP3026_XTRUECOLORCTRL_ORGB_8888		0x06
+#define     TVP3026_XTRUECOLORCTRL_BGRO_8888		0x07
+#define     TVP3026_XTRUECOLORCTRL_RGB_565		0x05
+#define     TVP3026_XTRUECOLORCTRL_ORGB_1555		0x04
+#define     TVP3026_XTRUECOLORCTRL_RGB_664		0x03
+#define     TVP3026_XTRUECOLORCTRL_RGBO_4444		0x01
+#define TVP3026_XMUXCTRL	0x19
+#define     TVP3026_XMUXCTRL_MEMORY_8BIT			0x01 /* - */
+#define     TVP3026_XMUXCTRL_MEMORY_16BIT			0x02 /* - */
+#define     TVP3026_XMUXCTRL_MEMORY_32BIT			0x03 /* 2MB RAM, 512K * 4 */
+#define     TVP3026_XMUXCTRL_MEMORY_64BIT			0x04 /* >2MB RAM, 512K * 8 & more */
+#define     TVP3026_XMUXCTRL_PIXEL_4BIT				0x40 /* L0,H0,L1,H1... */
+#define     TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED			0x60 /* H0,L0,H1,L1... */
+#define     TVP3026_XMUXCTRL_PIXEL_8BIT				0x48
+#define     TVP3026_XMUXCTRL_PIXEL_16BIT			0x50
+#define     TVP3026_XMUXCTRL_PIXEL_32BIT			0x58
+#define     TVP3026_XMUXCTRL_VGA				0x98 /* VGA MEMORY, 8BIT PIXEL */
+#define TVP3026_XCLKCTRL	0x1A
+#define     TVP3026_XCLKCTRL_DIV1	0x00
+#define     TVP3026_XCLKCTRL_DIV2	0x10
+#define     TVP3026_XCLKCTRL_DIV4	0x20
+#define     TVP3026_XCLKCTRL_DIV8	0x30
+#define     TVP3026_XCLKCTRL_DIV16	0x40
+#define     TVP3026_XCLKCTRL_DIV32	0x50
+#define     TVP3026_XCLKCTRL_DIV64	0x60
+#define     TVP3026_XCLKCTRL_CLKSTOPPED	0x70
+#define     TVP3026_XCLKCTRL_SRC_CLK0	0x00
+#define     TVP3026_XCLKCTRL_SRC_CLK1   0x01
+#define     TVP3026_XCLKCTRL_SRC_CLK2	0x02	/* CLK2 is TTL source*/
+#define     TVP3026_XCLKCTRL_SRC_NCLK2	0x03	/* not CLK2 is TTL source */
+#define     TVP3026_XCLKCTRL_SRC_ECLK2	0x04	/* CLK2 and not CLK2 is ECL source */
+#define     TVP3026_XCLKCTRL_SRC_PLL	0x05
+#define     TVP3026_XCLKCTRL_SRC_DIS	0x06	/* disable & poweroff internal clock */
+#define     TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07
+#define TVP3026_XPALETTEPAGE	0x1C
+#define TVP3026_XGENCTRL	0x1D
+#define     TVP3026_XGENCTRL_HSYNC_POS	0x00
+#define     TVP3026_XGENCTRL_HSYNC_NEG	0x01
+#define     TVP3026_XGENCTRL_VSYNC_POS	0x00
+#define     TVP3026_XGENCTRL_VSYNC_NEG	0x02
+#define     TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00
+#define     TVP3026_XGENCTRL_BIG_ENDIAN    0x08
+#define     TVP3026_XGENCTRL_BLACK_0IRE		0x00
+#define     TVP3026_XGENCTRL_BLACK_75IRE	0x10
+#define     TVP3026_XGENCTRL_NO_SYNC_ON_GREEN	0x00
+#define     TVP3026_XGENCTRL_SYNC_ON_GREEN	0x20
+#define     TVP3026_XGENCTRL_OVERSCAN_DIS	0x00
+#define     TVP3026_XGENCTRL_OVERSCAN_EN	0x40
+#define TVP3026_XMISCCTRL	0x1E
+#define     TVP3026_XMISCCTRL_DAC_PUP	0x00
+#define     TVP3026_XMISCCTRL_DAC_PDOWN	0x01
+#define     TVP3026_XMISCCTRL_DAC_EXT	0x00 /* or 8, bit 3 is ignored */
+#define     TVP3026_XMISCCTRL_DAC_6BIT	0x04
+#define     TVP3026_XMISCCTRL_DAC_8BIT	0x0C
+#define     TVP3026_XMISCCTRL_PSEL_DIS	0x00
+#define     TVP3026_XMISCCTRL_PSEL_EN	0x10
+#define     TVP3026_XMISCCTRL_PSEL_LOW	0x00 /* PSEL high selects directcolor */
+#define     TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */
+#define TVP3026_XGENIOCTRL	0x2A
+#define TVP3026_XGENIODATA	0x2B
+#define TVP3026_XPLLADDR	0x2C
+#define     TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX))
+#define     TVP3026_XPLLDATA_N		0x00
+#define     TVP3026_XPLLDATA_M		0x01
+#define     TVP3026_XPLLDATA_P		0x02
+#define     TVP3026_XPLLDATA_STAT	0x03
+#define TVP3026_XPIXPLLDATA	0x2D
+#define TVP3026_XMEMPLLDATA	0x2E
+#define TVP3026_XLOOPPLLDATA	0x2F
+#define TVP3026_XCOLKEYOVRMIN	0x30
+#define TVP3026_XCOLKEYOVRMAX	0x31
+#define TVP3026_XCOLKEYREDMIN	0x32
+#define TVP3026_XCOLKEYREDMAX	0x33
+#define TVP3026_XCOLKEYGREENMIN	0x34
+#define TVP3026_XCOLKEYGREENMAX	0x35
+#define TVP3026_XCOLKEYBLUEMIN	0x36
+#define TVP3026_XCOLKEYBLUEMAX	0x37
+#define TVP3026_XCOLKEYCTRL	0x38
+#define     TVP3026_XCOLKEYCTRL_OVR_EN	0x01
+#define     TVP3026_XCOLKEYCTRL_RED_EN	0x02
+#define     TVP3026_XCOLKEYCTRL_GREEN_EN 0x04
+#define     TVP3026_XCOLKEYCTRL_BLUE_EN	0x08
+#define     TVP3026_XCOLKEYCTRL_NEGATE	0x10
+#define     TVP3026_XCOLKEYCTRL_ZOOM1	0x00
+#define     TVP3026_XCOLKEYCTRL_ZOOM2	0x20
+#define     TVP3026_XCOLKEYCTRL_ZOOM4	0x40
+#define     TVP3026_XCOLKEYCTRL_ZOOM8	0x60
+#define     TVP3026_XCOLKEYCTRL_ZOOM16	0x80
+#define     TVP3026_XCOLKEYCTRL_ZOOM32	0xA0
+#define TVP3026_XMEMPLLCTRL	0x39
+#define     TVP3026_XMEMPLLCTRL_DIV(X)	(((X)-1)>>1)	/* 2,4,6,8,10,12,14,16, division applied to LOOP PLL after divide by 2^P */
+#define     TVP3026_XMEMPLLCTRL_STROBEMKC4	0x08
+#define     TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK	0x00	/* MKC4 */
+#define     TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL	0x10	/* MKC4 */
+#define     TVP3026_XMEMPLLCTRL_RCLK_PIXPLL	0x00
+#define     TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL	0x20
+#define     TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN	0x40	/* dot clock divided by loop pclk N prescaler */
+#define TVP3026_XSENSETEST	0x3A
+#define TVP3026_XTESTMODEDATA	0x3B
+#define TVP3026_XCRCREML	0x3C
+#define TVP3026_XCRCREMH	0x3D
+#define TVP3026_XCRCBITSEL	0x3E
+#define TVP3026_XID		0x3F
+
+static const unsigned char DACseq[] =
+{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL,
+  TVP3026_XMUXCTRL, TVP3026_XCLKCTRL,
+  TVP3026_XPALETTEPAGE,
+  TVP3026_XGENCTRL,
+  TVP3026_XMISCCTRL,
+  TVP3026_XGENIOCTRL,
+  TVP3026_XGENIODATA,
+  TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX,
+  TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX,
+  TVP3026_XCOLKEYCTRL,
+  TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL };
+
+#define POS3026_XLATCHCTRL	0
+#define POS3026_XTRUECOLORCTRL	1
+#define POS3026_XMUXCTRL	2
+#define POS3026_XCLKCTRL	3
+#define POS3026_XGENCTRL	5
+#define POS3026_XMISCCTRL	6
+#define POS3026_XMEMPLLCTRL	18
+#define POS3026_XCURCTRL	20
+
+static const unsigned char MGADACbpp32[] =
+{ TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888,
+  0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL,
+  0x00,
+  TVP3026_XGENCTRL_HSYNC_POS | TVP3026_XGENCTRL_VSYNC_POS | TVP3026_XGENCTRL_LITTLE_ENDIAN | TVP3026_XGENCTRL_BLACK_0IRE | TVP3026_XGENCTRL_NO_SYNC_ON_GREEN | TVP3026_XGENCTRL_OVERSCAN_DIS,
+  TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH,
+  0x00,
+  0x1E,
+  0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF,
+  TVP3026_XCOLKEYCTRL_ZOOM1,
+  0x00, 0x00, TVP3026_XCURCTRL_DIS };
+
+static int Ti3026_calcclock(const struct matrox_fb_info *minfo,
+			    unsigned int freq, unsigned int fmax, int *in,
+			    int *feed, int *post)
+{
+	unsigned int fvco;
+	unsigned int lin, lfeed, lpost;
+
+	DBG(__func__)
+
+	fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost);
+	fvco >>= (*post = lpost);
+	*in = 64 - lin;
+	*feed = 64 - lfeed;
+	return fvco;
+}
+
+static int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk)
+{
+	unsigned int f_pll;
+	unsigned int pixfeed, pixin, pixpost;
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost);
+
+	hw->DACclk[0] = pixin | 0xC0;
+	hw->DACclk[1] = pixfeed;
+	hw->DACclk[2] = pixpost | 0xB0;
+
+	{
+		unsigned int loopfeed, loopin, looppost, loopdiv, z;
+		unsigned int Bpp;
+
+		Bpp = minfo->curr.final_bppShift;
+
+		if (minfo->fbcon.var.bits_per_pixel == 24) {
+			loopfeed = 3;		/* set lm to any possible value */
+			loopin = 3 * 32 / Bpp;
+		} else {
+			loopfeed = 4;
+			loopin = 4 * 32 / Bpp;
+		}
+		z = (110000 * loopin) / (f_pll * loopfeed);
+		loopdiv = 0; /* div 2 */
+		if (z < 2)
+			looppost = 0;
+		else if (z < 4)
+			looppost = 1;
+		else if (z < 8)
+			looppost = 2;
+		else {
+			looppost = 3;
+			loopdiv = z/16;
+		}
+		if (minfo->fbcon.var.bits_per_pixel == 24) {
+			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+			hw->DACclk[4] = (65 - loopfeed) | 0x80;
+			if (minfo->accel.ramdac_rev > 0x20) {
+				if (isInterleave(minfo))
+					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
+				else {
+					hw->DACclk[4] &= ~0xC0;
+					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
+				}
+			} else {
+				if (isInterleave(minfo))
+					;	/* default... */
+				else {
+					hw->DACclk[4] ^= 0xC0;	/* change from 0x80 to 0x40 */
+					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
+				}
+			}
+			hw->DACclk[5] = looppost | 0xF8;
+			if (minfo->devflags.mga_24bpp_fix)
+				hw->DACclk[5] ^= 0x40;
+		} else {
+			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+			hw->DACclk[4] = 65 - loopfeed;
+			hw->DACclk[5] = looppost | 0xF0;
+		}
+		hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
+	}
+	return 0;
+}
+
+static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
+{
+	u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
+	switch (minfo->fbcon.var.bits_per_pixel) {
+		case 4:	hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1;	/* or _8_1, they are same */
+			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
+			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
+			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8;
+			hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
+			break;
+		case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1;	/* or _4_1, they are same */
+			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
+			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT;
+			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
+			hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
+			break;
+		case 16:
+			/* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */
+			hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
+			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
+			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
+			break;
+		case 24:
+			/* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */
+			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888;
+			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
+			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
+			break;
+		case 32:
+			/* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */
+			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
+			break;
+		default:
+			return 1;	/* TODO: failed */
+	}
+	if (matroxfb_vgaHWinit(minfo, m)) return 1;
+
+	/* set SYNC */
+	hw->MiscOutReg = 0xCB;
+	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
+		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG;
+	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
+		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG;
+	if (m->sync & FB_SYNC_ON_GREEN)
+		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
+
+	/* set DELAY */
+	if (minfo->video.len < 0x400000)
+		hw->CRTCEXT[3] |= 0x08;
+	else if (minfo->video.len > 0x400000)
+		hw->CRTCEXT[3] |= 0x10;
+
+	/* set HWCURSOR */
+	if (m->interlaced) {
+		hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED;
+	}
+	if (m->HTotal >= 1536)
+		hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096;
+
+	/* set interleaving */
+	hw->MXoptionReg &= ~0x00001000;
+	if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000;
+
+	/* set DAC */
+	Ti3026_setpclk(minfo, m->pixclock);
+	return 0;
+}
+
+static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout)
+{
+	unsigned int f_pll;
+	unsigned int pclk_m, pclk_n, pclk_p;
+	unsigned int mclk_m, mclk_n, mclk_p;
+	unsigned int rfhcnt, mclk_ctl;
+	int tmout;
+
+	DBG(__func__)
+
+	f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p);
+
+	/* save pclk */
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
+	pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA);
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFD);
+	pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA);
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
+	pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA);
+
+	/* stop pclk */
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
+
+	/* set pclk to new mclk */
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0);
+
+	/* wait for PLL to lock */
+	for (tmout = 500000; tmout; tmout--) {
+		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
+			break;
+		udelay(10);
+	}
+	if (!tmout)
+		printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");
+
+	/* output pclk on mclk pin */
+	mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL);
+	outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
+	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);
+
+	/* stop MCLK */
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFB);
+	outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00);
+
+	/* set mclk to new freq */
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xF3);
+	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
+	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m);
+	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0);
+
+	/* wait for PLL to lock */
+	for (tmout = 500000; tmout; tmout--) {
+		if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40)
+			break;
+		udelay(10);
+	}
+	if (!tmout)
+		printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");
+
+	f_pll = f_pll * 333 / (10000 << mclk_p);
+	if (isMilleniumII(minfo)) {
+		rfhcnt = (f_pll - 128) / 256;
+		if (rfhcnt > 15)
+			rfhcnt = 15;
+	} else {
+		rfhcnt = (f_pll - 64) / 128;
+		if (rfhcnt > 15)
+			rfhcnt = 0;
+	}
+	minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
+
+	/* output MCLK to MCLK pin */
+	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
+	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl       ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);
+
+	/* stop PCLK */
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
+
+	/* restore pclk */
+	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p);
+
+	/* wait for PLL to lock */
+	for (tmout = 500000; tmout; tmout--) {
+		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
+			break;
+		udelay(10);
+	}
+	if (!tmout)
+		printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+}
+
+static void ti3026_ramdac_init(struct matrox_fb_info *minfo)
+{
+	DBG(__func__)
+
+	minfo->features.pll.vco_freq_min = 110000;
+	minfo->features.pll.ref_freq	 = 114545;
+	minfo->features.pll.feed_div_min = 2;
+	minfo->features.pll.feed_div_max = 24;
+	minfo->features.pll.in_div_min	 = 2;
+	minfo->features.pll.in_div_max	 = 63;
+	minfo->features.pll.post_shift_max = 3;
+	if (minfo->devflags.noinit)
+		return;
+	ti3026_setMCLK(minfo, 60000);
+}
+
+static void Ti3026_restore(struct matrox_fb_info *minfo)
+{
+	int i;
+	unsigned char progdac[6];
+	struct matrox_hw_state *hw = &minfo->hw;
+	CRITFLAGS
+
+	DBG(__func__)
+
+#ifdef DEBUG
+	dprintk(KERN_INFO "EXTVGA regs: ");
+	for (i = 0; i < 6; i++)
+		dprintk("%02X:", hw->CRTCEXT[i]);
+	dprintk("\n");
+#endif
+
+	CRITBEGIN
+
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+
+	CRITEND
+
+	matroxfb_vgaHWrestore(minfo);
+
+	CRITBEGIN
+
+	minfo->crtc1.panpos = -1;
+	for (i = 0; i < 6; i++)
+		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
+
+	for (i = 0; i < 21; i++) {
+		outTi3026(minfo, DACseq[i], hw->DACreg[i]);
+	}
+
+	outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
+	progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
+	progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
+	outTi3026(minfo, TVP3026_XPLLADDR, 0x15);
+	progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
+	progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
+	outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
+	progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
+	progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
+
+	CRITEND
+	if (memcmp(hw->DACclk, progdac, 6)) {
+		/* agrhh... setting up PLL is very slow on Millennium... */
+		/* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
+		/* Maybe even we should call schedule() ? */
+
+		CRITBEGIN
+		outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
+		outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
+		outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0);
+		outTi3026(minfo, TVP3026_XPIXPLLDATA, 0);
+
+		outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
+		for (i = 0; i < 3; i++)
+			outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]);
+		/* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
+		if (hw->MiscOutReg & 0x08) {
+			int tmout;
+			outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
+			for (tmout = 500000; tmout; --tmout) {
+				if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
+					break;
+				udelay(10);
+			}
+
+			CRITEND
+
+			if (!tmout)
+				printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+			else
+				dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
+			CRITBEGIN
+		}
+		outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
+		outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
+		for (i = 3; i < 6; i++)
+			outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
+		CRITEND
+		if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
+			int tmout;
+
+			CRITBEGIN
+			outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
+			for (tmout = 500000; tmout; --tmout) {
+				if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40)
+					break;
+				udelay(10);
+			}
+			CRITEND
+			if (!tmout)
+				printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
+			else
+				dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout);
+		}
+	}
+
+#ifdef DEBUG
+	dprintk(KERN_DEBUG "3026DACregs ");
+	for (i = 0; i < 21; i++) {
+		dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
+		if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
+	}
+	dprintk(KERN_DEBUG "DACclk ");
+	for (i = 0; i < 6; i++)
+		dprintk("C%02X=%02X ", i, hw->DACclk[i]);
+	dprintk("\n");
+#endif
+}
+
+static void Ti3026_reset(struct matrox_fb_info *minfo)
+{
+	DBG(__func__)
+
+	ti3026_ramdac_init(minfo);
+}
+
+static struct matrox_altout ti3026_output = {
+	.name	 = "Primary output",
+};
+
+static int Ti3026_preinit(struct matrox_fb_info *minfo)
+{
+	static const int vxres_mill2[] = { 512,        640, 768,  800,  832,  960,
+					  1024, 1152, 1280,      1600, 1664, 1920,
+					  2048, 0};
+	static const int vxres_mill1[] = {             640, 768,  800,        960,
+					  1024, 1152, 1280,      1600,       1920,
+					  2048, 0};
+	struct matrox_hw_state *hw = &minfo->hw;
+
+	DBG(__func__)
+
+	minfo->millenium = 1;
+	minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL);
+	minfo->capable.cfb4 = 1;
+	minfo->capable.text = 1; /* isMilleniumII(minfo); */
+	minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1;
+
+	minfo->outputs[0].data = minfo;
+	minfo->outputs[0].output = &ti3026_output;
+	minfo->outputs[0].src = minfo->outputs[0].default_src;
+	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+
+	if (minfo->devflags.noinit)
+		return 0;
+	/* preserve VGA I/O, BIOS and PPC */
+	hw->MXoptionReg &= 0xC0000100;
+	hw->MXoptionReg |= 0x002C0000;
+	if (minfo->devflags.novga)
+		hw->MXoptionReg &= ~0x00000100;
+	if (minfo->devflags.nobios)
+		hw->MXoptionReg &= ~0x40000000;
+	if (minfo->devflags.nopciretry)
+		hw->MXoptionReg |=  0x20000000;
+	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
+
+	minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV);
+
+	outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
+	outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR);
+	outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA);
+
+	outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
+	outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00);
+	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
+
+	mga_outb(M_MISC_REG, 0x67);
+
+	outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
+
+	mga_outl(M_RESET, 1);
+	udelay(250);
+	mga_outl(M_RESET, 0);
+	udelay(250);
+	mga_outl(M_MACCESS, 0x00008000);
+	udelay(10);
+	return 0;
+}
+
+struct matrox_switch matrox_millennium = {
+	Ti3026_preinit, Ti3026_reset, Ti3026_init, Ti3026_restore
+};
+EXPORT_SYMBOL(matrox_millennium);
+#endif
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_Ti3026.h b/drivers/video/fbdev/matrox/matroxfb_Ti3026.h
new file mode 100644
index 000000000000..27872aaa0a17
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.h
@@ -0,0 +1,11 @@
+#ifndef __MATROXFB_TI3026_H__
+#define __MATROXFB_TI3026_H__
+
+
+#include "matroxfb_base.h"
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+extern struct matrox_switch matrox_millennium;
+#endif
+
+#endif	/* __MATROXFB_TI3026_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_accel.c b/drivers/video/fbdev/matrox/matroxfb_accel.c
new file mode 100644
index 000000000000..0d5cb85d071a
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_accel.c
@@ -0,0 +1,519 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
+ *
+ * Contributors: "menion?" <menion@mindless.com>
+ *                     Betatesting, fixes, ideas
+ *
+ *               "Kurt Garloff" <garloff@suse.de>
+ *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
+ *
+ *               "Tom Rini" <trini@kernel.crashing.org>
+ *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
+ *
+ *               "Bibek Sahu" <scorpio@dodds.net>
+ *                     Access device through readb|w|l and write b|w|l
+ *                     Extensive debugging stuff
+ *
+ *               "Daniel Haun" <haund@usa.net>
+ *                     Testing, hardware cursor fixes
+ *
+ *               "Scott Wood" <sawst46+@pitt.edu>
+ *                     Fixes
+ *
+ *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
+ *                     Betatesting
+ *
+ *               "Kelly French" <targon@hazmat.com>
+ *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
+ *                     Betatesting, bug reporting
+ *
+ *               "Pablo Bianucci" <pbian@pccp.com.ar>
+ *                     Fixes, ideas, betatesting
+ *
+ *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
+ *                     Fixes, enhandcements, ideas, betatesting
+ *
+ *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
+ *                     PPC betatesting, PPC support, backward compatibility
+ *
+ *               "Paul Womar" <Paul@pwomar.demon.co.uk>
+ *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
+ *                     PPC betatesting
+ *
+ *               "Thomas Pornin" <pornin@bolet.ens.fr>
+ *                     Alpha betatesting
+ *
+ *               "Pieter van Leuven" <pvl@iae.nl>
+ *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
+ *                     G100 testing
+ *
+ *               "H. Peter Arvin" <hpa@transmeta.com>
+ *                     Ideas
+ *
+ *               "Cort Dougan" <cort@cs.nmt.edu>
+ *                     CHRP fixes and PReP cleanup
+ *
+ *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
+ *                     G400 support
+ *
+ * (following author is not in any relation with this code, but his code
+ *  is included in this driver)
+ *
+ * Based on framebuffer driver for VBE 2.0 compliant graphic boards
+ *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * (following author is not in any relation with this code, but his ideas
+ *  were used when writing this driver)
+ *
+ *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
+ *
+ */
+
+#include "matroxfb_accel.h"
+#include "matroxfb_DAC1064.h"
+#include "matroxfb_Ti3026.h"
+#include "matroxfb_misc.h"
+
+#define curr_ydstorg(x)	((x)->curr.ydstorg.pixels)
+
+#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
+
+static inline void matrox_cfb4_pal(u_int32_t* pal) {
+	unsigned int i;
+	
+	for (i = 0; i < 16; i++) {
+		pal[i] = i * 0x11111111U;
+	}
+}
+
+static inline void matrox_cfb8_pal(u_int32_t* pal) {
+	unsigned int i;
+	
+	for (i = 0; i < 16; i++) {
+		pal[i] = i * 0x01010101U;
+	}
+}
+
+static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area);
+static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
+static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image);
+static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
+static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area);
+
+void matrox_cfbX_init(struct matrox_fb_info *minfo)
+{
+	u_int32_t maccess;
+	u_int32_t mpitch;
+	u_int32_t mopmode;
+	int accel;
+
+	DBG(__func__)
+
+	mpitch = minfo->fbcon.var.xres_virtual;
+
+	minfo->fbops.fb_copyarea = cfb_copyarea;
+	minfo->fbops.fb_fillrect = cfb_fillrect;
+	minfo->fbops.fb_imageblit = cfb_imageblit;
+	minfo->fbops.fb_cursor = NULL;
+
+	accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT;
+
+	switch (minfo->fbcon.var.bits_per_pixel) {
+		case 4:		maccess = 0x00000000;	/* accelerate as 8bpp video */
+				mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
+				mopmode = M_OPMODE_4BPP;
+				matrox_cfb4_pal(minfo->cmap);
+				if (accel && !(mpitch & 1)) {
+					minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea;
+					minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect;
+				}
+				break;
+		case 8:		maccess = 0x00000000;
+				mopmode = M_OPMODE_8BPP;
+				matrox_cfb8_pal(minfo->cmap);
+				if (accel) {
+					minfo->fbops.fb_copyarea = matroxfb_copyarea;
+					minfo->fbops.fb_fillrect = matroxfb_fillrect;
+					minfo->fbops.fb_imageblit = matroxfb_imageblit;
+				}
+				break;
+		case 16:	if (minfo->fbcon.var.green.length == 5)
+					maccess = 0xC0000001;
+				else
+					maccess = 0x40000001;
+				mopmode = M_OPMODE_16BPP;
+				if (accel) {
+					minfo->fbops.fb_copyarea = matroxfb_copyarea;
+					minfo->fbops.fb_fillrect = matroxfb_fillrect;
+					minfo->fbops.fb_imageblit = matroxfb_imageblit;
+				}
+				break;
+		case 24:	maccess = 0x00000003;
+				mopmode = M_OPMODE_24BPP;
+				if (accel) {
+					minfo->fbops.fb_copyarea = matroxfb_copyarea;
+					minfo->fbops.fb_fillrect = matroxfb_fillrect;
+					minfo->fbops.fb_imageblit = matroxfb_imageblit;
+				}
+				break;
+		case 32:	maccess = 0x00000002;
+				mopmode = M_OPMODE_32BPP;
+				if (accel) {
+					minfo->fbops.fb_copyarea = matroxfb_copyarea;
+					minfo->fbops.fb_fillrect = matroxfb_fillrect;
+					minfo->fbops.fb_imageblit = matroxfb_imageblit;
+				}
+				break;
+		default:	maccess = 0x00000000;
+				mopmode = 0x00000000;
+				break;	/* turn off acceleration!!! */
+	}
+	mga_fifo(8);
+	mga_outl(M_PITCH, mpitch);
+	mga_outl(M_YDSTORG, curr_ydstorg(minfo));
+	if (minfo->capable.plnwt)
+		mga_outl(M_PLNWT, -1);
+	if (minfo->capable.srcorg) {
+		mga_outl(M_SRCORG, 0);
+		mga_outl(M_DSTORG, 0);
+	}
+	mga_outl(M_OPMODE, mopmode);
+	mga_outl(M_CXBNDRY, 0xFFFF0000);
+	mga_outl(M_YTOP, 0);
+	mga_outl(M_YBOT, 0x01FFFFFF);
+	mga_outl(M_MACCESS, maccess);
+	minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
+	if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
+	minfo->accel.m_opmode = mopmode;
+	minfo->accel.m_access = maccess;
+	minfo->accel.m_pitch = mpitch;
+}
+
+EXPORT_SYMBOL(matrox_cfbX_init);
+
+static void matrox_accel_restore_maccess(struct matrox_fb_info *minfo)
+{
+	mga_outl(M_MACCESS, minfo->accel.m_access);
+	mga_outl(M_PITCH, minfo->accel.m_pitch);
+}
+
+static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
+			       int sx, int dy, int dx, int height, int width)
+{
+	int start, end;
+	CRITFLAGS
+
+	DBG(__func__)
+
+	CRITBEGIN
+
+	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
+		mga_fifo(4);
+		matrox_accel_restore_maccess(minfo);
+		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
+			 M_DWG_BFCOL | M_DWG_REPLACE);
+		mga_outl(M_AR5, vxres);
+		width--;
+		start = sy*vxres+sx+curr_ydstorg(minfo);
+		end = start+width;
+	} else {
+		mga_fifo(5);
+		matrox_accel_restore_maccess(minfo);
+		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
+		mga_outl(M_SGN, 5);
+		mga_outl(M_AR5, -vxres);
+		width--;
+		end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
+		start = end+width;
+		dy += height-1;
+	}
+	mga_fifo(6);
+	matrox_accel_restore_maccess(minfo);
+	mga_outl(M_AR0, end);
+	mga_outl(M_AR3, start);
+	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
+	mga_ydstlen(dy, height);
+	WaitTillIdle();
+
+	CRITEND
+}
+
+static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
+				   int sy, int sx, int dy, int dx, int height,
+				   int width)
+{
+	int start, end;
+	CRITFLAGS
+
+	DBG(__func__)
+
+	CRITBEGIN
+
+	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
+		mga_fifo(4);
+		matrox_accel_restore_maccess(minfo);
+		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
+			M_DWG_BFCOL | M_DWG_REPLACE);
+		mga_outl(M_AR5, vxres);
+		width--;
+		start = sy*vxres+sx+curr_ydstorg(minfo);
+		end = start+width;
+	} else {
+		mga_fifo(5);
+		matrox_accel_restore_maccess(minfo);
+		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
+		mga_outl(M_SGN, 5);
+		mga_outl(M_AR5, -vxres);
+		width--;
+		end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
+		start = end+width;
+		dy += height-1;
+	}
+	mga_fifo(7);
+	matrox_accel_restore_maccess(minfo);
+	mga_outl(M_AR0, end);
+	mga_outl(M_AR3, start);
+	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
+	mga_outl(M_YDST, dy*vxres >> 5);
+	mga_outl(M_LEN | M_EXEC, height);
+	WaitTillIdle();
+
+	CRITEND
+}
+
+static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	if ((area->sx | area->dx | area->width) & 1)
+		cfb_copyarea(info, area);
+	else
+		matrox_accel_bmove_lin(minfo, minfo->fbcon.var.xres_virtual >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1);
+}
+
+static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width);
+}
+
+static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
+				 int sy, int sx, int height, int width)
+{
+	CRITFLAGS
+
+	DBG(__func__)
+
+	CRITBEGIN
+
+	mga_fifo(7);
+	matrox_accel_restore_maccess(minfo);
+	mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
+	mga_outl(M_FCOL, color);
+	mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
+	mga_ydstlen(sy, height);
+	WaitTillIdle();
+
+	CRITEND
+}
+
+static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	switch (rect->rop) {
+		case ROP_COPY:
+			matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
+			break;
+	}
+}
+
+static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
+				int sy, int sx, int height, int width)
+{
+	int whattodo;
+	CRITFLAGS
+
+	DBG(__func__)
+
+	CRITBEGIN
+
+	whattodo = 0;
+	if (sx & 1) {
+		sx ++;
+		if (!width) return;
+		width --;
+		whattodo = 1;
+	}
+	if (width & 1) {
+		whattodo |= 2;
+	}
+	width >>= 1;
+	sx >>= 1;
+	if (width) {
+		mga_fifo(7);
+		matrox_accel_restore_maccess(minfo);
+		mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
+		mga_outl(M_FCOL, bgx);
+		mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
+		mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6);
+		mga_outl(M_LEN | M_EXEC, height);
+		WaitTillIdle();
+	}
+	if (whattodo) {
+		u_int32_t step = minfo->fbcon.var.xres_virtual >> 1;
+		vaddr_t vbase = minfo->video.vbase;
+		if (whattodo & 1) {
+			unsigned int uaddr = sy * step + sx - 1;
+			u_int32_t loop;
+			u_int8_t bgx2 = bgx & 0xF0;
+			for (loop = height; loop > 0; loop --) {
+				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
+				uaddr += step;
+			}
+		}
+		if (whattodo & 2) {
+			unsigned int uaddr = sy * step + sx + width;
+			u_int32_t loop;
+			u_int8_t bgx2 = bgx & 0x0F;
+			for (loop = height; loop > 0; loop --) {
+				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
+				uaddr += step;
+			}
+		}
+	}
+
+	CRITEND
+}
+
+static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	switch (rect->rop) {
+		case ROP_COPY:
+			matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
+			break;
+	}
+}
+
+static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
+				    u_int32_t bgx, const u_int8_t *chardata,
+				    int width, int height, int yy, int xx)
+{
+	u_int32_t step;
+	u_int32_t ydstlen;
+	u_int32_t xlen;
+	u_int32_t ar0;
+	u_int32_t charcell;
+	u_int32_t fxbndry;
+	vaddr_t mmio;
+	int easy;
+	CRITFLAGS
+
+	DBG_HEAVY(__func__);
+
+	step = (width + 7) >> 3;
+	charcell = height * step;
+	xlen = (charcell + 3) & ~3;
+	ydstlen = (yy << 16) | height;
+	if (width == step << 3) {
+		ar0 = height * width - 1;
+		easy = 1;
+	} else {
+		ar0 = width - 1;
+		easy = 0;
+	}
+
+	CRITBEGIN
+
+	mga_fifo(5);
+	matrox_accel_restore_maccess(minfo);
+	if (easy)
+		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+	else
+		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
+	mga_outl(M_FCOL, fgx);
+	mga_outl(M_BCOL, bgx);
+	fxbndry = ((xx + width - 1) << 16) | xx;
+	mmio = minfo->mmio.vbase;
+
+	mga_fifo(8);
+	matrox_accel_restore_maccess(minfo);
+	mga_writel(mmio, M_FXBNDRY, fxbndry);
+	mga_writel(mmio, M_AR0, ar0);
+	mga_writel(mmio, M_AR3, 0);
+	if (easy) {
+		mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
+		mga_memcpy_toio(mmio, chardata, xlen);
+	} else {
+		mga_writel(mmio, M_AR5, 0);
+		mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
+		if ((step & 3) == 0) {
+			/* Great. Source has 32bit aligned lines, so we can feed them
+			   directly to the accelerator. */
+			mga_memcpy_toio(mmio, chardata, charcell);
+		} else if (step == 1) {
+			/* Special case for 1..8bit widths */
+			while (height--) {
+#if defined(__BIG_ENDIAN)
+				fb_writel((*chardata) << 24, mmio.vaddr);
+#else
+				fb_writel(*chardata, mmio.vaddr);
+#endif
+				chardata++;
+			}
+		} else if (step == 2) {
+			/* Special case for 9..15bit widths */
+			while (height--) {
+#if defined(__BIG_ENDIAN)
+				fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr);
+#else
+				fb_writel(*(u_int16_t*)chardata, mmio.vaddr);
+#endif
+				chardata += 2;
+			}
+		} else {
+			/* Tell... well, why bother... */
+			while (height--) {
+				size_t i;
+				
+				for (i = 0; i < step; i += 4) {
+					/* Hope that there are at least three readable bytes beyond the end of bitmap */
+					fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
+				}
+				chardata += step;
+			}
+		}
+	}
+	WaitTillIdle();
+	CRITEND
+}
+
+
+static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) {
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	DBG_HEAVY(__func__);
+
+	if (image->depth == 1) {
+		u_int32_t fgx, bgx;
+
+		fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color];
+		bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color];
+		matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx);
+	} else {
+		/* Danger! image->depth is useless: logo painting code always
+		   passes framebuffer color depth here, although logo data are
+		   always 8bpp and info->pseudo_palette is changed to contain
+		   logo palette to be used (but only for true/direct-color... sic...).
+		   So do it completely in software... */
+		cfb_imageblit(info, image);
+	}
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_accel.h b/drivers/video/fbdev/matrox/matroxfb_accel.h
new file mode 100644
index 000000000000..1e418e62c22d
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_accel.h
@@ -0,0 +1,8 @@
+#ifndef __MATROXFB_ACCEL_H__
+#define __MATROXFB_ACCEL_H__
+
+#include "matroxfb_base.h"
+
+void matrox_cfbX_init(struct matrox_fb_info *minfo);
+
+#endif
diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
new file mode 100644
index 000000000000..7116c5309c7d
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_base.c
@@ -0,0 +1,2584 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
+ *
+ * Contributors: "menion?" <menion@mindless.com>
+ *                     Betatesting, fixes, ideas
+ *
+ *               "Kurt Garloff" <garloff@suse.de>
+ *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
+ *
+ *               "Tom Rini" <trini@kernel.crashing.org>
+ *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
+ *
+ *               "Bibek Sahu" <scorpio@dodds.net>
+ *                     Access device through readb|w|l and write b|w|l
+ *                     Extensive debugging stuff
+ *
+ *               "Daniel Haun" <haund@usa.net>
+ *                     Testing, hardware cursor fixes
+ *
+ *               "Scott Wood" <sawst46+@pitt.edu>
+ *                     Fixes
+ *
+ *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
+ *                     Betatesting
+ *
+ *               "Kelly French" <targon@hazmat.com>
+ *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
+ *                     Betatesting, bug reporting
+ *
+ *               "Pablo Bianucci" <pbian@pccp.com.ar>
+ *                     Fixes, ideas, betatesting
+ *
+ *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
+ *                     Fixes, enhandcements, ideas, betatesting
+ *
+ *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
+ *                     PPC betatesting, PPC support, backward compatibility
+ *
+ *               "Paul Womar" <Paul@pwomar.demon.co.uk>
+ *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
+ *                     PPC betatesting
+ *
+ *               "Thomas Pornin" <pornin@bolet.ens.fr>
+ *                     Alpha betatesting
+ *
+ *               "Pieter van Leuven" <pvl@iae.nl>
+ *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
+ *                     G100 testing
+ *
+ *               "H. Peter Arvin" <hpa@transmeta.com>
+ *                     Ideas
+ *
+ *               "Cort Dougan" <cort@cs.nmt.edu>
+ *                     CHRP fixes and PReP cleanup
+ *
+ *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
+ *                     G400 support
+ *
+ *               "Samuel Hocevar" <sam@via.ecp.fr>
+ *                     Fixes
+ *
+ *               "Anton Altaparmakov" <AntonA@bigfoot.com>
+ *                     G400 MAX/non-MAX distinction
+ *
+ *               "Ken Aaker" <kdaaker@rchland.vnet.ibm.com>
+ *                     memtype extension (needed for GXT130P RS/6000 adapter)
+ *
+ *               "Uns Lider" <unslider@miranda.org>
+ *                     G100 PLNWT fixes
+ *
+ *               "Denis Zaitsev" <zzz@cd-club.ru>
+ *                     Fixes
+ *
+ *               "Mike Pieper" <mike@pieper-family.de>
+ *                     TVOut enhandcements, V4L2 control interface.
+ *
+ *               "Diego Biurrun" <diego@biurrun.de>
+ *                     DFP testing
+ *
+ * (following author is not in any relation with this code, but his code
+ *  is included in this driver)
+ *
+ * Based on framebuffer driver for VBE 2.0 compliant graphic boards
+ *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * (following author is not in any relation with this code, but his ideas
+ *  were used when writing this driver)
+ *
+ *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
+ *
+ */
+
+#include <linux/version.h>
+
+#include "matroxfb_base.h"
+#include "matroxfb_misc.h"
+#include "matroxfb_accel.h"
+#include "matroxfb_DAC1064.h"
+#include "matroxfb_Ti3026.h"
+#include "matroxfb_maven.h"
+#include "matroxfb_crtc2.h"
+#include "matroxfb_g450.h"
+#include <linux/matroxfb.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+unsigned char nvram_read_byte(int);
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+#endif
+
+static void matroxfb_unregister_device(struct matrox_fb_info* minfo);
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * card parameters
+ */
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo vesafb_defined = {
+	640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/
+	0,0,		/* virtual -> visible no offset */
+	8,		/* depth -> load bits_per_pixel */
+	0,		/* greyscale ? */
+	{0,0,0},	/* R */
+	{0,0,0},	/* G */
+	{0,0,0},	/* B */
+	{0,0,0},	/* transparency */
+	0,		/* standard pixel format */
+	FB_ACTIVATE_NOW,
+	-1,-1,
+	FB_ACCELF_TEXT,	/* accel flags */
+	39721L,48L,16L,33L,10L,
+	96L,2L,~0,	/* No sync info */
+	FB_VMODE_NONINTERLACED,
+};
+
+
+
+/* --------------------------------------------------------------------- */
+static void update_crtc2(struct matrox_fb_info *minfo, unsigned int pos)
+{
+	struct matroxfb_dh_fb_info *info = minfo->crtc2.info;
+
+	/* Make sure that displays are compatible */
+	if (info && (info->fbcon.var.bits_per_pixel == minfo->fbcon.var.bits_per_pixel)
+		 && (info->fbcon.var.xres_virtual == minfo->fbcon.var.xres_virtual)
+		 && (info->fbcon.var.green.length == minfo->fbcon.var.green.length)
+		 ) {
+		switch (minfo->fbcon.var.bits_per_pixel) {
+			case 16:
+			case 32:
+				pos = pos * 8;
+				if (info->interlaced) {
+					mga_outl(0x3C2C, pos);
+					mga_outl(0x3C28, pos + minfo->fbcon.var.xres_virtual * minfo->fbcon.var.bits_per_pixel / 8);
+				} else {
+					mga_outl(0x3C28, pos);
+				}
+				break;
+		}
+	}
+}
+
+static void matroxfb_crtc1_panpos(struct matrox_fb_info *minfo)
+{
+	if (minfo->crtc1.panpos >= 0) {
+		unsigned long flags;
+		int panpos;
+
+		matroxfb_DAC_lock_irqsave(flags);
+		panpos = minfo->crtc1.panpos;
+		if (panpos >= 0) {
+			unsigned int extvga_reg;
+
+			minfo->crtc1.panpos = -1; /* No update pending anymore */
+			extvga_reg = mga_inb(M_EXTVGA_INDEX);
+			mga_setr(M_EXTVGA_INDEX, 0x00, panpos);
+			if (extvga_reg != 0x00) {
+				mga_outb(M_EXTVGA_INDEX, extvga_reg);
+			}
+		}
+		matroxfb_DAC_unlock_irqrestore(flags);
+	}
+}
+
+static irqreturn_t matrox_irq(int irq, void *dev_id)
+{
+	u_int32_t status;
+	int handled = 0;
+	struct matrox_fb_info *minfo = dev_id;
+
+	status = mga_inl(M_STATUS);
+
+	if (status & 0x20) {
+		mga_outl(M_ICLEAR, 0x20);
+		minfo->crtc1.vsync.cnt++;
+		matroxfb_crtc1_panpos(minfo);
+		wake_up_interruptible(&minfo->crtc1.vsync.wait);
+		handled = 1;
+	}
+	if (status & 0x200) {
+		mga_outl(M_ICLEAR, 0x200);
+		minfo->crtc2.vsync.cnt++;
+		wake_up_interruptible(&minfo->crtc2.vsync.wait);
+		handled = 1;
+	}
+	return IRQ_RETVAL(handled);
+}
+
+int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable)
+{
+	u_int32_t bm;
+
+	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
+		bm = 0x220;
+	else
+		bm = 0x020;
+
+	if (!test_and_set_bit(0, &minfo->irq_flags)) {
+		if (request_irq(minfo->pcidev->irq, matrox_irq,
+				IRQF_SHARED, "matroxfb", minfo)) {
+			clear_bit(0, &minfo->irq_flags);
+			return -EINVAL;
+		}
+		/* Clear any pending field interrupts */
+		mga_outl(M_ICLEAR, bm);
+		mga_outl(M_IEN, mga_inl(M_IEN) | bm);
+	} else if (reenable) {
+		u_int32_t ien;
+
+		ien = mga_inl(M_IEN);
+		if ((ien & bm) != bm) {
+			printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
+			mga_outl(M_IEN, ien | bm);
+		}
+	}
+	return 0;
+}
+
+static void matroxfb_disable_irq(struct matrox_fb_info *minfo)
+{
+	if (test_and_clear_bit(0, &minfo->irq_flags)) {
+		/* Flush pending pan-at-vbl request... */
+		matroxfb_crtc1_panpos(minfo);
+		if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
+			mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220);
+		else
+			mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20);
+		free_irq(minfo->pcidev->irq, minfo);
+	}
+}
+
+int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc)
+{
+	struct matrox_vsync *vs;
+	unsigned int cnt;
+	int ret;
+
+	switch (crtc) {
+		case 0:
+			vs = &minfo->crtc1.vsync;
+			break;
+		case 1:
+			if (minfo->devflags.accelerator != FB_ACCEL_MATROX_MGAG400) {
+				return -ENODEV;
+			}
+			vs = &minfo->crtc2.vsync;
+			break;
+		default:
+			return -ENODEV;
+	}
+	ret = matroxfb_enable_irq(minfo, 0);
+	if (ret) {
+		return ret;
+	}
+
+	cnt = vs->cnt;
+	ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10);
+	if (ret < 0) {
+		return ret;
+	}
+	if (ret == 0) {
+		matroxfb_enable_irq(minfo, 1);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static void matrox_pan_var(struct matrox_fb_info *minfo,
+			   struct fb_var_screeninfo *var)
+{
+	unsigned int pos;
+	unsigned short p0, p1, p2;
+	unsigned int p3;
+	int vbl;
+	unsigned long flags;
+
+	CRITFLAGS
+
+	DBG(__func__)
+
+	if (minfo->dead)
+		return;
+
+	minfo->fbcon.var.xoffset = var->xoffset;
+	minfo->fbcon.var.yoffset = var->yoffset;
+	pos = (minfo->fbcon.var.yoffset * minfo->fbcon.var.xres_virtual + minfo->fbcon.var.xoffset) * minfo->curr.final_bppShift / 32;
+	pos += minfo->curr.ydstorg.chunks;
+	p0 = minfo->hw.CRTC[0x0D] = pos & 0xFF;
+	p1 = minfo->hw.CRTC[0x0C] = (pos & 0xFF00) >> 8;
+	p2 = minfo->hw.CRTCEXT[0] = (minfo->hw.CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
+	p3 = minfo->hw.CRTCEXT[8] = pos >> 21;
+
+	/* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */
+	vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(minfo, 0) == 0);
+
+	CRITBEGIN
+
+	matroxfb_DAC_lock_irqsave(flags);
+	mga_setr(M_CRTC_INDEX, 0x0D, p0);
+	mga_setr(M_CRTC_INDEX, 0x0C, p1);
+	if (minfo->devflags.support32MB)
+		mga_setr(M_EXTVGA_INDEX, 0x08, p3);
+	if (vbl) {
+		minfo->crtc1.panpos = p2;
+	} else {
+		/* Abort any pending change */
+		minfo->crtc1.panpos = -1;
+		mga_setr(M_EXTVGA_INDEX, 0x00, p2);
+	}
+	matroxfb_DAC_unlock_irqrestore(flags);
+
+	update_crtc2(minfo, pos);
+
+	CRITEND
+}
+
+static void matroxfb_remove(struct matrox_fb_info *minfo, int dummy)
+{
+	/* Currently we are holding big kernel lock on all dead & usecount updates.
+	 * Destroy everything after all users release it. Especially do not unregister
+	 * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check
+	 * for device unplugged when in use.
+	 * In future we should point mmio.vbase & video.vbase somewhere where we can
+	 * write data without causing too much damage...
+	 */
+
+	minfo->dead = 1;
+	if (minfo->usecount) {
+		/* destroy it later */
+		return;
+	}
+	matroxfb_unregister_device(minfo);
+	unregister_framebuffer(&minfo->fbcon);
+	matroxfb_g450_shutdown(minfo);
+#ifdef CONFIG_MTRR
+	if (minfo->mtrr.vram_valid)
+		mtrr_del(minfo->mtrr.vram, minfo->video.base, minfo->video.len);
+#endif
+	mga_iounmap(minfo->mmio.vbase);
+	mga_iounmap(minfo->video.vbase);
+	release_mem_region(minfo->video.base, minfo->video.len_maximum);
+	release_mem_region(minfo->mmio.base, 16384);
+	kfree(minfo);
+}
+
+	/*
+	 * Open/Release the frame buffer device
+	 */
+
+static int matroxfb_open(struct fb_info *info, int user)
+{
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	DBG_LOOP(__func__)
+
+	if (minfo->dead) {
+		return -ENXIO;
+	}
+	minfo->usecount++;
+	if (user) {
+		minfo->userusecount++;
+	}
+	return(0);
+}
+
+static int matroxfb_release(struct fb_info *info, int user)
+{
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	DBG_LOOP(__func__)
+
+	if (user) {
+		if (0 == --minfo->userusecount) {
+			matroxfb_disable_irq(minfo);
+		}
+	}
+	if (!(--minfo->usecount) && minfo->dead) {
+		matroxfb_remove(minfo, 0);
+	}
+	return(0);
+}
+
+static int matroxfb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info* info) {
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	DBG(__func__)
+
+	matrox_pan_var(minfo, var);
+	return 0;
+}
+
+static int matroxfb_get_final_bppShift(const struct matrox_fb_info *minfo,
+				       int bpp)
+{
+	int bppshft2;
+
+	DBG(__func__)
+
+	bppshft2 = bpp;
+	if (!bppshft2) {
+		return 8;
+	}
+	if (isInterleave(minfo))
+		bppshft2 >>= 1;
+	if (minfo->devflags.video64bits)
+		bppshft2 >>= 1;
+	return bppshft2;
+}
+
+static int matroxfb_test_and_set_rounding(const struct matrox_fb_info *minfo,
+					  int xres, int bpp)
+{
+	int over;
+	int rounding;
+
+	DBG(__func__)
+
+	switch (bpp) {
+		case 0:		return xres;
+		case 4:		rounding = 128;
+				break;
+		case 8:		rounding = 64;	/* doc says 64; 32 is OK for G400 */
+				break;
+		case 16:	rounding = 32;
+				break;
+		case 24:	rounding = 64;	/* doc says 64; 32 is OK for G400 */
+				break;
+		default:	rounding = 16;
+				/* on G400, 16 really does not work */
+				if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
+					rounding = 32;
+				break;
+	}
+	if (isInterleave(minfo)) {
+		rounding *= 2;
+	}
+	over = xres % rounding;
+	if (over)
+		xres += rounding-over;
+	return xres;
+}
+
+static int matroxfb_pitch_adjust(const struct matrox_fb_info *minfo, int xres,
+				 int bpp)
+{
+	const int* width;
+	int xres_new;
+
+	DBG(__func__)
+
+	if (!bpp) return xres;
+
+	width = minfo->capable.vxres;
+
+	if (minfo->devflags.precise_width) {
+		while (*width) {
+			if ((*width >= xres) && (matroxfb_test_and_set_rounding(minfo, *width, bpp) == *width)) {
+				break;
+			}
+			width++;
+		}
+		xres_new = *width;
+	} else {
+		xres_new = matroxfb_test_and_set_rounding(minfo, xres, bpp);
+	}
+	return xres_new;
+}
+
+static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
+
+	DBG(__func__)
+
+	switch (var->bits_per_pixel) {
+		case 4:
+			return 16;	/* pseudocolor... 16 entries HW palette */
+		case 8:
+			return 256;	/* pseudocolor... 256 entries HW palette */
+		case 16:
+			return 16;	/* directcolor... 16 entries SW palette */
+					/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+		case 24:
+			return 16;	/* directcolor... 16 entries SW palette */
+					/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+		case 32:
+			return 16;	/* directcolor... 16 entries SW palette */
+					/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+	}
+	return 16;	/* return something reasonable... or panic()? */
+}
+
+static int matroxfb_decode_var(const struct matrox_fb_info *minfo,
+			       struct fb_var_screeninfo *var, int *visual,
+			       int *video_cmap_len, unsigned int* ydstorg)
+{
+	struct RGBT {
+		unsigned char bpp;
+		struct {
+			unsigned char offset,
+				      length;
+		} red,
+		  green,
+		  blue,
+		  transp;
+		signed char visual;
+	};
+	static const struct RGBT table[]= {
+		{ 8,{ 0,8},{0,8},{0,8},{ 0,0},MX_VISUAL_PSEUDOCOLOR},
+		{15,{10,5},{5,5},{0,5},{15,1},MX_VISUAL_DIRECTCOLOR},
+		{16,{11,5},{5,6},{0,5},{ 0,0},MX_VISUAL_DIRECTCOLOR},
+		{24,{16,8},{8,8},{0,8},{ 0,0},MX_VISUAL_DIRECTCOLOR},
+		{32,{16,8},{8,8},{0,8},{24,8},MX_VISUAL_DIRECTCOLOR}
+	};
+	struct RGBT const *rgbt;
+	unsigned int bpp = var->bits_per_pixel;
+	unsigned int vramlen;
+	unsigned int memlen;
+
+	DBG(__func__)
+
+	switch (bpp) {
+		case 4:	 if (!minfo->capable.cfb4) return -EINVAL;
+			 break;
+		case 8:	 break;
+		case 16: break;
+		case 24: break;
+		case 32: break;
+		default: return -EINVAL;
+	}
+	*ydstorg = 0;
+	vramlen = minfo->video.len_usable;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	var->xres_virtual = matroxfb_pitch_adjust(minfo, var->xres_virtual, bpp);
+	memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
+	if (memlen > vramlen) {
+		var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp);
+		memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
+	}
+	/* There is hardware bug that no line can cross 4MB boundary */
+	/* give up for CFB24, it is impossible to easy workaround it */
+	/* for other try to do something */
+	if (!minfo->capable.cross4MB && (memlen > 0x400000)) {
+		if (bpp == 24) {
+			/* sorry */
+		} else {
+			unsigned int linelen;
+			unsigned int m1 = linelen = var->xres_virtual * bpp / 8;
+			unsigned int m2 = PAGE_SIZE;	/* or 128 if you do not need PAGE ALIGNED address */
+			unsigned int max_yres;
+
+			while (m1) {
+				int t;
+
+				while (m2 >= m1) m2 -= m1;
+				t = m1;
+				m1 = m2;
+				m2 = t;
+			}
+			m2 = linelen * PAGE_SIZE / m2;
+			*ydstorg = m2 = 0x400000 % m2;
+			max_yres = (vramlen - m2) / linelen;
+			if (var->yres_virtual > max_yres)
+				var->yres_virtual = max_yres;
+		}
+	}
+	/* YDSTLEN contains only signed 16bit value */
+	if (var->yres_virtual > 32767)
+		var->yres_virtual = 32767;
+	/* we must round yres/xres down, we already rounded y/xres_virtual up
+	   if it was possible. We should return -EINVAL, but I disagree */
+	if (var->yres_virtual < var->yres)
+		var->yres = var->yres_virtual;
+	if (var->xres_virtual < var->xres)
+		var->xres = var->xres_virtual;
+	if (var->xoffset + var->xres > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	if (bpp == 16 && var->green.length == 5) {
+		bpp--; /* an artificial value - 15 */
+	}
+
+	for (rgbt = table; rgbt->bpp < bpp; rgbt++);
+#define	SETCLR(clr)\
+	var->clr.offset = rgbt->clr.offset;\
+	var->clr.length = rgbt->clr.length
+	SETCLR(red);
+	SETCLR(green);
+	SETCLR(blue);
+	SETCLR(transp);
+#undef	SETCLR
+	*visual = rgbt->visual;
+
+	if (bpp > 8)
+		dprintk("matroxfb: truecolor: "
+			"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+			var->transp.length, var->red.length, var->green.length, var->blue.length,
+			var->transp.offset, var->red.offset, var->green.offset, var->blue.offset);
+
+	*video_cmap_len = matroxfb_get_cmap_len(var);
+	dprintk(KERN_INFO "requested %d*%d/%dbpp (%d*%d)\n", var->xres, var->yres, var->bits_per_pixel,
+				var->xres_virtual, var->yres_virtual);
+	return 0;
+}
+
+static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *fb_info)
+{
+	struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon);
+
+	DBG(__func__)
+
+	/*
+	 *  Set a single color register. The values supplied are
+	 *  already rounded down to the hardware's capabilities
+	 *  (according to the entries in the `var' structure). Return
+	 *  != 0 for invalid regno.
+	 */
+
+	if (regno >= minfo->curr.cmap_len)
+		return 1;
+
+	if (minfo->fbcon.var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	red = CNVT_TOHW(red, minfo->fbcon.var.red.length);
+	green = CNVT_TOHW(green, minfo->fbcon.var.green.length);
+	blue = CNVT_TOHW(blue, minfo->fbcon.var.blue.length);
+	transp = CNVT_TOHW(transp, minfo->fbcon.var.transp.length);
+
+	switch (minfo->fbcon.var.bits_per_pixel) {
+	case 4:
+	case 8:
+		mga_outb(M_DAC_REG, regno);
+		mga_outb(M_DAC_VAL, red);
+		mga_outb(M_DAC_VAL, green);
+		mga_outb(M_DAC_VAL, blue);
+		break;
+	case 16:
+		if (regno >= 16)
+			break;
+		{
+			u_int16_t col =
+				(red << minfo->fbcon.var.red.offset)     |
+				(green << minfo->fbcon.var.green.offset) |
+				(blue << minfo->fbcon.var.blue.offset)   |
+				(transp << minfo->fbcon.var.transp.offset); /* for 1:5:5:5 */
+			minfo->cmap[regno] = col | (col << 16);
+		}
+		break;
+	case 24:
+	case 32:
+		if (regno >= 16)
+			break;
+		minfo->cmap[regno] =
+			(red   << minfo->fbcon.var.red.offset)   |
+			(green << minfo->fbcon.var.green.offset) |
+			(blue  << minfo->fbcon.var.blue.offset)  |
+			(transp << minfo->fbcon.var.transp.offset);	/* 8:8:8:8 */
+		break;
+	}
+	return 0;
+}
+
+static void matroxfb_init_fix(struct matrox_fb_info *minfo)
+{
+	struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
+	DBG(__func__)
+
+	strcpy(fix->id,"MATROX");
+
+	fix->xpanstep = 8;	/* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->mmio_start = minfo->mmio.base;
+	fix->mmio_len = minfo->mmio.len;
+	fix->accel = minfo->devflags.accelerator;
+}
+
+static void matroxfb_update_fix(struct matrox_fb_info *minfo)
+{
+	struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
+	DBG(__func__)
+
+	mutex_lock(&minfo->fbcon.mm_lock);
+	fix->smem_start = minfo->video.base + minfo->curr.ydstorg.bytes;
+	fix->smem_len = minfo->video.len_usable - minfo->curr.ydstorg.bytes;
+	mutex_unlock(&minfo->fbcon.mm_lock);
+}
+
+static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int err;
+	int visual;
+	int cmap_len;
+	unsigned int ydstorg;
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	if (minfo->dead) {
+		return -ENXIO;
+	}
+	if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
+		return err;
+	return 0;
+}
+
+static int matroxfb_set_par(struct fb_info *info)
+{
+	int err;
+	int visual;
+	int cmap_len;
+	unsigned int ydstorg;
+	struct fb_var_screeninfo *var;
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	DBG(__func__)
+
+	if (minfo->dead) {
+		return -ENXIO;
+	}
+
+	var = &info->var;
+	if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
+		return err;
+	minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase) + ydstorg;
+	matroxfb_update_fix(minfo);
+	minfo->fbcon.fix.visual = visual;
+	minfo->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
+	minfo->fbcon.fix.type_aux = 0;
+	minfo->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+	{
+		unsigned int pos;
+
+		minfo->curr.cmap_len = cmap_len;
+		ydstorg += minfo->devflags.ydstorg;
+		minfo->curr.ydstorg.bytes = ydstorg;
+		minfo->curr.ydstorg.chunks = ydstorg >> (isInterleave(minfo) ? 3 : 2);
+		if (var->bits_per_pixel == 4)
+			minfo->curr.ydstorg.pixels = ydstorg;
+		else
+			minfo->curr.ydstorg.pixels = (ydstorg * 8) / var->bits_per_pixel;
+		minfo->curr.final_bppShift = matroxfb_get_final_bppShift(minfo, var->bits_per_pixel);
+		{	struct my_timming mt;
+			struct matrox_hw_state* hw;
+			int out;
+
+			matroxfb_var2my(var, &mt);
+			mt.crtc = MATROXFB_SRC_CRTC1;
+			/* CRTC1 delays */
+			switch (var->bits_per_pixel) {
+				case  0:	mt.delay = 31 + 0; break;
+				case 16:	mt.delay = 21 + 8; break;
+				case 24:	mt.delay = 17 + 8; break;
+				case 32:	mt.delay = 16 + 8; break;
+				default:	mt.delay = 31 + 8; break;
+			}
+
+			hw = &minfo->hw;
+
+			down_read(&minfo->altout.lock);
+			for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+				if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
+				    minfo->outputs[out].output->compute) {
+					minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
+				}
+			}
+			up_read(&minfo->altout.lock);
+			minfo->crtc1.pixclock = mt.pixclock;
+			minfo->crtc1.mnp = mt.mnp;
+			minfo->hw_switch->init(minfo, &mt);
+			pos = (var->yoffset * var->xres_virtual + var->xoffset) * minfo->curr.final_bppShift / 32;
+			pos += minfo->curr.ydstorg.chunks;
+
+			hw->CRTC[0x0D] = pos & 0xFF;
+			hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
+			hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
+			hw->CRTCEXT[8] = pos >> 21;
+			minfo->hw_switch->restore(minfo);
+			update_crtc2(minfo, pos);
+			down_read(&minfo->altout.lock);
+			for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+				if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
+				    minfo->outputs[out].output->program) {
+					minfo->outputs[out].output->program(minfo->outputs[out].data);
+				}
+			}
+			for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+				if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
+				    minfo->outputs[out].output->start) {
+					minfo->outputs[out].output->start(minfo->outputs[out].data);
+				}
+			}
+			up_read(&minfo->altout.lock);
+			matrox_cfbX_init(minfo);
+		}
+	}
+	minfo->initialized = 1;
+	return 0;
+}
+
+static int matroxfb_get_vblank(struct matrox_fb_info *minfo,
+			       struct fb_vblank *vblank)
+{
+	unsigned int sts1;
+
+	matroxfb_enable_irq(minfo, 0);
+	memset(vblank, 0, sizeof(*vblank));
+	vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC |
+			FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK;
+	sts1 = mga_inb(M_INSTS1);
+	vblank->vcount = mga_inl(M_VCOUNT);
+	/* BTW, on my PIII/450 with G400, reading M_INSTS1
+	   byte makes this call about 12% slower (1.70 vs. 2.05 us
+	   per ioctl()) */
+	if (sts1 & 1)
+		vblank->flags |= FB_VBLANK_HBLANKING;
+	if (sts1 & 8)
+		vblank->flags |= FB_VBLANK_VSYNCING;
+	if (vblank->vcount >= minfo->fbcon.var.yres)
+		vblank->flags |= FB_VBLANK_VBLANKING;
+	if (test_bit(0, &minfo->irq_flags)) {
+		vblank->flags |= FB_VBLANK_HAVE_COUNT;
+		/* Only one writer, aligned int value...
+		   it should work without lock and without atomic_t */
+		vblank->count = minfo->crtc1.vsync.cnt;
+	}
+	return 0;
+}
+
+static struct matrox_altout panellink_output = {
+	.name	 = "Panellink output",
+};
+
+static int matroxfb_ioctl(struct fb_info *info,
+			  unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	DBG(__func__)
+
+	if (minfo->dead) {
+		return -ENXIO;
+	}
+
+	switch (cmd) {
+		case FBIOGET_VBLANK:
+			{
+				struct fb_vblank vblank;
+				int err;
+
+				err = matroxfb_get_vblank(minfo, &vblank);
+				if (err)
+					return err;
+				if (copy_to_user(argp, &vblank, sizeof(vblank)))
+					return -EFAULT;
+				return 0;
+			}
+		case FBIO_WAITFORVSYNC:
+			{
+				u_int32_t crt;
+
+				if (get_user(crt, (u_int32_t __user *)arg))
+					return -EFAULT;
+
+				return matroxfb_wait_for_sync(minfo, crt);
+			}
+		case MATROXFB_SET_OUTPUT_MODE:
+			{
+				struct matroxioc_output_mode mom;
+				struct matrox_altout *oproc;
+				int val;
+
+				if (copy_from_user(&mom, argp, sizeof(mom)))
+					return -EFAULT;
+				if (mom.output >= MATROXFB_MAX_OUTPUTS)
+					return -ENXIO;
+				down_read(&minfo->altout.lock);
+				oproc = minfo->outputs[mom.output].output;
+				if (!oproc) {
+					val = -ENXIO;
+				} else if (!oproc->verifymode) {
+					if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) {
+						val = 0;
+					} else {
+						val = -EINVAL;
+					}
+				} else {
+					val = oproc->verifymode(minfo->outputs[mom.output].data, mom.mode);
+				}
+				if (!val) {
+					if (minfo->outputs[mom.output].mode != mom.mode) {
+						minfo->outputs[mom.output].mode = mom.mode;
+						val = 1;
+					}
+				}
+				up_read(&minfo->altout.lock);
+				if (val != 1)
+					return val;
+				switch (minfo->outputs[mom.output].src) {
+					case MATROXFB_SRC_CRTC1:
+						matroxfb_set_par(info);
+						break;
+					case MATROXFB_SRC_CRTC2:
+						{
+							struct matroxfb_dh_fb_info* crtc2;
+
+							down_read(&minfo->crtc2.lock);
+							crtc2 = minfo->crtc2.info;
+							if (crtc2)
+								crtc2->fbcon.fbops->fb_set_par(&crtc2->fbcon);
+							up_read(&minfo->crtc2.lock);
+						}
+						break;
+				}
+				return 0;
+			}
+		case MATROXFB_GET_OUTPUT_MODE:
+			{
+				struct matroxioc_output_mode mom;
+				struct matrox_altout *oproc;
+				int val;
+
+				if (copy_from_user(&mom, argp, sizeof(mom)))
+					return -EFAULT;
+				if (mom.output >= MATROXFB_MAX_OUTPUTS)
+					return -ENXIO;
+				down_read(&minfo->altout.lock);
+				oproc = minfo->outputs[mom.output].output;
+				if (!oproc) {
+					val = -ENXIO;
+				} else {
+					mom.mode = minfo->outputs[mom.output].mode;
+					val = 0;
+				}
+				up_read(&minfo->altout.lock);
+				if (val)
+					return val;
+				if (copy_to_user(argp, &mom, sizeof(mom)))
+					return -EFAULT;
+				return 0;
+			}
+		case MATROXFB_SET_OUTPUT_CONNECTION:
+			{
+				u_int32_t tmp;
+				int i;
+				int changes;
+
+				if (copy_from_user(&tmp, argp, sizeof(tmp)))
+					return -EFAULT;
+				for (i = 0; i < 32; i++) {
+					if (tmp & (1 << i)) {
+						if (i >= MATROXFB_MAX_OUTPUTS)
+							return -ENXIO;
+						if (!minfo->outputs[i].output)
+							return -ENXIO;
+						switch (minfo->outputs[i].src) {
+							case MATROXFB_SRC_NONE:
+							case MATROXFB_SRC_CRTC1:
+								break;
+							default:
+								return -EBUSY;
+						}
+					}
+				}
+				if (minfo->devflags.panellink) {
+					if (tmp & MATROXFB_OUTPUT_CONN_DFP) {
+						if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY)
+							return -EINVAL;
+						for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+							if (minfo->outputs[i].src == MATROXFB_SRC_CRTC2) {
+								return -EBUSY;
+							}
+						}
+					}
+				}
+				changes = 0;
+				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+					if (tmp & (1 << i)) {
+						if (minfo->outputs[i].src != MATROXFB_SRC_CRTC1) {
+							changes = 1;
+							minfo->outputs[i].src = MATROXFB_SRC_CRTC1;
+						}
+					} else if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
+						changes = 1;
+						minfo->outputs[i].src = MATROXFB_SRC_NONE;
+					}
+				}
+				if (!changes)
+					return 0;
+				matroxfb_set_par(info);
+				return 0;
+			}
+		case MATROXFB_GET_OUTPUT_CONNECTION:
+			{
+				u_int32_t conn = 0;
+				int i;
+
+				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+					if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
+						conn |= 1 << i;
+					}
+				}
+				if (put_user(conn, (u_int32_t __user *)arg))
+					return -EFAULT;
+				return 0;
+			}
+		case MATROXFB_GET_AVAILABLE_OUTPUTS:
+			{
+				u_int32_t conn = 0;
+				int i;
+
+				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+					if (minfo->outputs[i].output) {
+						switch (minfo->outputs[i].src) {
+							case MATROXFB_SRC_NONE:
+							case MATROXFB_SRC_CRTC1:
+								conn |= 1 << i;
+								break;
+						}
+					}
+				}
+				if (minfo->devflags.panellink) {
+					if (conn & MATROXFB_OUTPUT_CONN_DFP)
+						conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
+					if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
+						conn &= ~MATROXFB_OUTPUT_CONN_DFP;
+				}
+				if (put_user(conn, (u_int32_t __user *)arg))
+					return -EFAULT;
+				return 0;
+			}
+		case MATROXFB_GET_ALL_OUTPUTS:
+			{
+				u_int32_t conn = 0;
+				int i;
+
+				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+					if (minfo->outputs[i].output) {
+						conn |= 1 << i;
+					}
+				}
+				if (put_user(conn, (u_int32_t __user *)arg))
+					return -EFAULT;
+				return 0;
+			}
+		case VIDIOC_QUERYCAP:
+			{
+				struct v4l2_capability r;
+
+				memset(&r, 0, sizeof(r));
+				strcpy(r.driver, "matroxfb");
+				strcpy(r.card, "Matrox");
+				sprintf(r.bus_info, "PCI:%s", pci_name(minfo->pcidev));
+				r.version = KERNEL_VERSION(1,0,0);
+				r.capabilities = V4L2_CAP_VIDEO_OUTPUT;
+				if (copy_to_user(argp, &r, sizeof(r)))
+					return -EFAULT;
+				return 0;
+
+			}
+		case VIDIOC_QUERYCTRL:
+			{
+				struct v4l2_queryctrl qctrl;
+				int err;
+
+				if (copy_from_user(&qctrl, argp, sizeof(qctrl)))
+					return -EFAULT;
+
+				down_read(&minfo->altout.lock);
+				if (!minfo->outputs[1].output) {
+					err = -ENXIO;
+				} else if (minfo->outputs[1].output->getqueryctrl) {
+					err = minfo->outputs[1].output->getqueryctrl(minfo->outputs[1].data, &qctrl);
+				} else {
+					err = -EINVAL;
+				}
+				up_read(&minfo->altout.lock);
+				if (err >= 0 &&
+				    copy_to_user(argp, &qctrl, sizeof(qctrl)))
+					return -EFAULT;
+				return err;
+			}
+		case VIDIOC_G_CTRL:
+			{
+				struct v4l2_control ctrl;
+				int err;
+
+				if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
+					return -EFAULT;
+
+				down_read(&minfo->altout.lock);
+				if (!minfo->outputs[1].output) {
+					err = -ENXIO;
+				} else if (minfo->outputs[1].output->getctrl) {
+					err = minfo->outputs[1].output->getctrl(minfo->outputs[1].data, &ctrl);
+				} else {
+					err = -EINVAL;
+				}
+				up_read(&minfo->altout.lock);
+				if (err >= 0 &&
+				    copy_to_user(argp, &ctrl, sizeof(ctrl)))
+					return -EFAULT;
+				return err;
+			}
+		case VIDIOC_S_CTRL:
+			{
+				struct v4l2_control ctrl;
+				int err;
+
+				if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
+					return -EFAULT;
+
+				down_read(&minfo->altout.lock);
+				if (!minfo->outputs[1].output) {
+					err = -ENXIO;
+				} else if (minfo->outputs[1].output->setctrl) {
+					err = minfo->outputs[1].output->setctrl(minfo->outputs[1].data, &ctrl);
+				} else {
+					err = -EINVAL;
+				}
+				up_read(&minfo->altout.lock);
+				return err;
+			}
+	}
+	return -ENOTTY;
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+
+static int matroxfb_blank(int blank, struct fb_info *info)
+{
+	int seq;
+	int crtc;
+	CRITFLAGS
+	struct matrox_fb_info *minfo = info2minfo(info);
+
+	DBG(__func__)
+
+	if (minfo->dead)
+		return 1;
+
+	switch (blank) {
+	case FB_BLANK_NORMAL:  seq = 0x20; crtc = 0x00; break; /* works ??? */
+	case FB_BLANK_VSYNC_SUSPEND:  seq = 0x20; crtc = 0x10; break;
+	case FB_BLANK_HSYNC_SUSPEND:  seq = 0x20; crtc = 0x20; break;
+	case FB_BLANK_POWERDOWN:  seq = 0x20; crtc = 0x30; break;
+	default: seq = 0x00; crtc = 0x00; break;
+	}
+
+	CRITBEGIN
+
+	mga_outb(M_SEQ_INDEX, 1);
+	mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq);
+	mga_outb(M_EXTVGA_INDEX, 1);
+	mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc);
+
+	CRITEND
+	return 0;
+}
+
+static struct fb_ops matroxfb_ops = {
+	.owner =	THIS_MODULE,
+	.fb_open =	matroxfb_open,
+	.fb_release =	matroxfb_release,
+	.fb_check_var =	matroxfb_check_var,
+	.fb_set_par =	matroxfb_set_par,
+	.fb_setcolreg =	matroxfb_setcolreg,
+	.fb_pan_display =matroxfb_pan_display,
+	.fb_blank =	matroxfb_blank,
+	.fb_ioctl =	matroxfb_ioctl,
+/*	.fb_fillrect =	<set by matrox_cfbX_init>, */
+/*	.fb_copyarea =	<set by matrox_cfbX_init>, */
+/*	.fb_imageblit =	<set by matrox_cfbX_init>, */
+/*	.fb_cursor =	<set by matrox_cfbX_init>, */
+};
+
+#define RSDepth(X)	(((X) >> 8) & 0x0F)
+#define RS8bpp		0x1
+#define RS15bpp		0x2
+#define RS16bpp		0x3
+#define RS32bpp		0x4
+#define RS4bpp		0x5
+#define RS24bpp		0x6
+#define RSText		0x7
+#define RSText8		0x8
+/* 9-F */
+static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; } colors[] = {
+	{ {  0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, {  0, 0, 0},  8 },
+	{ { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
+	{ { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0}, {  0, 0, 0}, 16 },
+	{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
+	{ {  0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, {  0, 0, 0},  4 },
+	{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {  0, 0, 0}, 24 },
+	{ {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 },	/* textmode with (default) VGA8x16 */
+	{ {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 },	/* textmode hardwired to VGA8x8 */
+};
+
+/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
+static unsigned int mem;		/* "matroxfb:mem:xxxxxM" */
+static int option_precise_width = 1;	/* cannot be changed, option_precise_width==0 must imply noaccel */
+static int inv24;			/* "matroxfb:inv24" */
+static int cross4MB = -1;		/* "matroxfb:cross4MB" */
+static int disabled;			/* "matroxfb:disabled" */
+static int noaccel;			/* "matroxfb:noaccel" */
+static int nopan;			/* "matroxfb:nopan" */
+static int no_pci_retry;		/* "matroxfb:nopciretry" */
+static int novga;			/* "matroxfb:novga" */
+static int nobios;			/* "matroxfb:nobios" */
+static int noinit = 1;			/* "matroxfb:init" */
+static int inverse;			/* "matroxfb:inverse" */
+static int sgram;			/* "matroxfb:sgram" */
+#ifdef CONFIG_MTRR
+static int mtrr = 1;			/* "matroxfb:nomtrr" */
+#endif
+static int grayscale;			/* "matroxfb:grayscale" */
+static int dev = -1;			/* "matroxfb:dev:xxxxx" */
+static unsigned int vesa = ~0;		/* "matroxfb:vesa:xxxxx" */
+static int depth = -1;			/* "matroxfb:depth:xxxxx" */
+static unsigned int xres;		/* "matroxfb:xres:xxxxx" */
+static unsigned int yres;		/* "matroxfb:yres:xxxxx" */
+static unsigned int upper = ~0;		/* "matroxfb:upper:xxxxx" */
+static unsigned int lower = ~0;		/* "matroxfb:lower:xxxxx" */
+static unsigned int vslen;		/* "matroxfb:vslen:xxxxx" */
+static unsigned int left = ~0;		/* "matroxfb:left:xxxxx" */
+static unsigned int right = ~0;		/* "matroxfb:right:xxxxx" */
+static unsigned int hslen;		/* "matroxfb:hslen:xxxxx" */
+static unsigned int pixclock;		/* "matroxfb:pixclock:xxxxx" */
+static int sync = -1;			/* "matroxfb:sync:xxxxx" */
+static unsigned int fv;			/* "matroxfb:fv:xxxxx" */
+static unsigned int fh;			/* "matroxfb:fh:xxxxxk" */
+static unsigned int maxclk;		/* "matroxfb:maxclk:xxxxM" */
+static int dfp;				/* "matroxfb:dfp */
+static int dfp_type = -1;		/* "matroxfb:dfp:xxx */
+static int memtype = -1;		/* "matroxfb:memtype:xxx" */
+static char outputs[8];			/* "matroxfb:outputs:xxx" */
+
+#ifndef MODULE
+static char videomode[64];		/* "matroxfb:mode:xxxxx" or "matroxfb:xxxxx" */
+#endif
+
+static int matroxfb_getmemory(struct matrox_fb_info *minfo,
+			      unsigned int maxSize, unsigned int *realSize)
+{
+	vaddr_t vm;
+	unsigned int offs;
+	unsigned int offs2;
+	unsigned char orig;
+	unsigned char bytes[32];
+	unsigned char* tmp;
+
+	DBG(__func__)
+
+	vm = minfo->video.vbase;
+	maxSize &= ~0x1FFFFF;	/* must be X*2MB (really it must be 2 or X*4MB) */
+	/* at least 2MB */
+	if (maxSize < 0x0200000) return 0;
+	if (maxSize > 0x2000000) maxSize = 0x2000000;
+
+	mga_outb(M_EXTVGA_INDEX, 0x03);
+	orig = mga_inb(M_EXTVGA_DATA);
+	mga_outb(M_EXTVGA_DATA, orig | 0x80);
+
+	tmp = bytes;
+	for (offs = 0x100000; offs < maxSize; offs += 0x200000)
+		*tmp++ = mga_readb(vm, offs);
+	for (offs = 0x100000; offs < maxSize; offs += 0x200000)
+		mga_writeb(vm, offs, 0x02);
+	mga_outb(M_CACHEFLUSH, 0x00);
+	for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
+		if (mga_readb(vm, offs) != 0x02)
+			break;
+		mga_writeb(vm, offs, mga_readb(vm, offs) - 0x02);
+		if (mga_readb(vm, offs))
+			break;
+	}
+	tmp = bytes;
+	for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
+		mga_writeb(vm, offs2, *tmp++);
+
+	mga_outb(M_EXTVGA_INDEX, 0x03);
+	mga_outb(M_EXTVGA_DATA, orig);
+
+	*realSize = offs - 0x100000;
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+	minfo->interleave = !(!isMillenium(minfo) || ((offs - 0x100000) & 0x3FFFFF));
+#endif
+	return 1;
+}
+
+struct video_board {
+	int maxvram;
+	int maxdisplayable;
+	int accelID;
+	struct matrox_switch* lowlevel;
+		 };
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static struct video_board vbMillennium		= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA2064W,	&matrox_millennium};
+static struct video_board vbMillennium2		= {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W,	&matrox_millennium};
+static struct video_board vbMillennium2A	= {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W_AGP,	&matrox_millennium};
+#endif	/* CONFIG_FB_MATROX_MILLENIUM */
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static struct video_board vbMystique		= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG,	&matrox_mystique};
+#endif	/* CONFIG_FB_MATROX_MYSTIQUE */
+#ifdef CONFIG_FB_MATROX_G
+static struct video_board vbG100		= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100,	&matrox_G100};
+static struct video_board vbG200		= {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200,	&matrox_G100};
+/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
+   whole 32MB */
+static struct video_board vbG400		= {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400,	&matrox_G100};
+#endif
+
+#define DEVF_VIDEO64BIT		0x0001
+#define	DEVF_SWAPS		0x0002
+#define DEVF_SRCORG		0x0004
+#define DEVF_DUALHEAD		0x0008
+#define DEVF_CROSS4MB		0x0010
+#define DEVF_TEXT4B		0x0020
+/* #define DEVF_recycled	0x0040	*/
+/* #define DEVF_recycled	0x0080	*/
+#define DEVF_SUPPORT32MB	0x0100
+#define DEVF_ANY_VXRES		0x0200
+#define DEVF_TEXT16B		0x0400
+#define DEVF_CRTC2		0x0800
+#define DEVF_MAVEN_CAPABLE	0x1000
+#define DEVF_PANELLINK_CAPABLE	0x2000
+#define DEVF_G450DAC		0x4000
+
+#define DEVF_GCORE	(DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB)
+#define DEVF_G2CORE	(DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE | DEVF_SRCORG | DEVF_DUALHEAD)
+#define DEVF_G100	(DEVF_GCORE) /* no doc, no vxres... */
+#define DEVF_G200	(DEVF_G2CORE)
+#define DEVF_G400	(DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2)
+/* if you'll find how to drive DFP... */
+#define DEVF_G450	(DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG | DEVF_DUALHEAD)
+#define DEVF_G550	(DEVF_G450)
+
+static struct board {
+	unsigned short vendor, device, rev, svid, sid;
+	unsigned int flags;
+	unsigned int maxclk;
+	enum mga_chip chip;
+	struct video_board* base;
+	const char* name;
+		} dev_list[] = {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL,	0xFF,
+		0,			0,
+		DEVF_TEXT4B,
+		230000,
+		MGA_2064,
+		&vbMillennium,
+		"Millennium (PCI)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2,	0xFF,
+		0,			0,
+		DEVF_SWAPS,
+		220000,
+		MGA_2164,
+		&vbMillennium2,
+		"Millennium II (PCI)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2_AGP,	0xFF,
+		0,			0,
+		DEVF_SWAPS,
+		250000,
+		MGA_2164,
+		&vbMillennium2A,
+		"Millennium II (AGP)"},
+#endif
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,	0x02,
+		0,			0,
+		DEVF_VIDEO64BIT | DEVF_CROSS4MB,
+		180000,
+		MGA_1064,
+		&vbMystique,
+		"Mystique (PCI)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,	0xFF,
+		0,			0,
+		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+		220000,
+		MGA_1164,
+		&vbMystique,
+		"Mystique 220 (PCI)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS_AGP,	0x02,
+		0,			0,
+		DEVF_VIDEO64BIT | DEVF_CROSS4MB,
+		180000,
+		MGA_1064,
+		&vbMystique,
+		"Mystique (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS_AGP,	0xFF,
+		0,			0,
+		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+		220000,
+		MGA_1164,
+		&vbMystique,
+		"Mystique 220 (AGP)"},
+#endif
+#ifdef CONFIG_FB_MATROX_G
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_MM,	0xFF,
+		0,			0,
+		DEVF_G100,
+		230000,
+		MGA_G100,
+		&vbG100,
+		"MGA-G100 (PCI)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,	0xFF,
+		0,			0,
+		DEVF_G100,
+		230000,
+		MGA_G100,
+		&vbG100,
+		"MGA-G100 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_PCI,	0xFF,
+		0,			0,
+		DEVF_G200,
+		250000,
+		MGA_G200,
+		&vbG200,
+		"MGA-G200 (PCI)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
+		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_GENERIC,
+		DEVF_G200,
+		220000,
+		MGA_G200,
+		&vbG200,
+		"MGA-G200 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
+		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
+		DEVF_G200,
+		230000,
+		MGA_G200,
+		&vbG200,
+		"Mystique G200 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
+		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MILLENIUM_G200_AGP,
+		DEVF_G200,
+		250000,
+		MGA_G200,
+		&vbG200,
+		"Millennium G200 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
+		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MARVEL_G200_AGP,
+		DEVF_G200,
+		230000,
+		MGA_G200,
+		&vbG200,
+		"Marvel G200 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
+		PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,	PCI_SS_ID_SIEMENS_MGA_G200_AGP,
+		DEVF_G200,
+		230000,
+		MGA_G200,
+		&vbG200,
+		"MGA-G200 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
+		0,			0,
+		DEVF_G200,
+		230000,
+		MGA_G200,
+		&vbG200,
+		"G200 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,	0x80,
+		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP,
+		DEVF_G400,
+		360000,
+		MGA_G400,
+		&vbG400,
+		"Millennium G400 MAX (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,	0x80,
+		0,			0,
+		DEVF_G400,
+		300000,
+		MGA_G400,
+		&vbG400,
+		"G400 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,	0xFF,
+		0,			0,
+		DEVF_G450,
+		360000,
+		MGA_G450,
+		&vbG400,
+		"G450"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G550,	0xFF,
+		0,			0,
+		DEVF_G550,
+		360000,
+		MGA_G550,
+		&vbG400,
+		"G550"},
+#endif
+	{0,			0,				0xFF,
+		0,			0,
+		0,
+		0,
+		0,
+		NULL,
+		NULL}};
+
+#ifndef MODULE
+static struct fb_videomode defaultmode = {
+	/* 640x480 @ 60Hz, 31.5 kHz */
+	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+};
+#endif /* !MODULE */
+
+static int hotplug = 0;
+
+static void setDefaultOutputs(struct matrox_fb_info *minfo)
+{
+	unsigned int i;
+	const char* ptr;
+
+	minfo->outputs[0].default_src = MATROXFB_SRC_CRTC1;
+	if (minfo->devflags.g450dac) {
+		minfo->outputs[1].default_src = MATROXFB_SRC_CRTC1;
+		minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
+	} else if (dfp) {
+		minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
+	}
+	ptr = outputs;
+	for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+		char c = *ptr++;
+
+		if (c == 0) {
+			break;
+		}
+		if (c == '0') {
+			minfo->outputs[i].default_src = MATROXFB_SRC_NONE;
+		} else if (c == '1') {
+			minfo->outputs[i].default_src = MATROXFB_SRC_CRTC1;
+		} else if (c == '2' && minfo->devflags.crtc2) {
+			minfo->outputs[i].default_src = MATROXFB_SRC_CRTC2;
+		} else {
+			printk(KERN_ERR "matroxfb: Unknown outputs setting\n");
+			break;
+		}
+	}
+	/* Nullify this option for subsequent adapters */
+	outputs[0] = 0;
+}
+
+static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
+{
+	unsigned long ctrlptr_phys = 0;
+	unsigned long video_base_phys = 0;
+	unsigned int memsize;
+	int err;
+
+	static struct pci_device_id intel_82437[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437) },
+		{ },
+	};
+
+	DBG(__func__)
+
+	/* set default values... */
+	vesafb_defined.accel_flags = FB_ACCELF_TEXT;
+
+	minfo->hw_switch = b->base->lowlevel;
+	minfo->devflags.accelerator = b->base->accelID;
+	minfo->max_pixel_clock = b->maxclk;
+
+	printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
+	minfo->capable.plnwt = 1;
+	minfo->chip = b->chip;
+	minfo->capable.srcorg = b->flags & DEVF_SRCORG;
+	minfo->devflags.video64bits = b->flags & DEVF_VIDEO64BIT;
+	if (b->flags & DEVF_TEXT4B) {
+		minfo->devflags.vgastep = 4;
+		minfo->devflags.textmode = 4;
+		minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
+	} else if (b->flags & DEVF_TEXT16B) {
+		minfo->devflags.vgastep = 16;
+		minfo->devflags.textmode = 1;
+		minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
+	} else {
+		minfo->devflags.vgastep = 8;
+		minfo->devflags.textmode = 1;
+		minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP8;
+	}
+	minfo->devflags.support32MB = (b->flags & DEVF_SUPPORT32MB) != 0;
+	minfo->devflags.precise_width = !(b->flags & DEVF_ANY_VXRES);
+	minfo->devflags.crtc2 = (b->flags & DEVF_CRTC2) != 0;
+	minfo->devflags.maven_capable = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
+	minfo->devflags.dualhead = (b->flags & DEVF_DUALHEAD) != 0;
+	minfo->devflags.dfp_type = dfp_type;
+	minfo->devflags.g450dac = (b->flags & DEVF_G450DAC) != 0;
+	minfo->devflags.textstep = minfo->devflags.vgastep * minfo->devflags.textmode;
+	minfo->devflags.textvram = 65536 / minfo->devflags.textmode;
+	setDefaultOutputs(minfo);
+	if (b->flags & DEVF_PANELLINK_CAPABLE) {
+		minfo->outputs[2].data = minfo;
+		minfo->outputs[2].output = &panellink_output;
+		minfo->outputs[2].src = minfo->outputs[2].default_src;
+		minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+		minfo->devflags.panellink = 1;
+	}
+
+	if (minfo->capable.cross4MB < 0)
+		minfo->capable.cross4MB = b->flags & DEVF_CROSS4MB;
+	if (b->flags & DEVF_SWAPS) {
+		ctrlptr_phys = pci_resource_start(minfo->pcidev, 1);
+		video_base_phys = pci_resource_start(minfo->pcidev, 0);
+		minfo->devflags.fbResource = PCI_BASE_ADDRESS_0;
+	} else {
+		ctrlptr_phys = pci_resource_start(minfo->pcidev, 0);
+		video_base_phys = pci_resource_start(minfo->pcidev, 1);
+		minfo->devflags.fbResource = PCI_BASE_ADDRESS_1;
+	}
+	err = -EINVAL;
+	if (!ctrlptr_phys) {
+		printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n");
+		goto fail;
+	}
+	if (!video_base_phys) {
+		printk(KERN_ERR "matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
+		goto fail;
+	}
+	memsize = b->base->maxvram;
+	if (!request_mem_region(ctrlptr_phys, 16384, "matroxfb MMIO")) {
+		goto fail;
+	}
+	if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) {
+		goto failCtrlMR;
+	}
+	minfo->video.len_maximum = memsize;
+	/* convert mem (autodetect k, M) */
+	if (mem < 1024) mem *= 1024;
+	if (mem < 0x00100000) mem *= 1024;
+
+	if (mem && (mem < memsize))
+		memsize = mem;
+	err = -ENOMEM;
+	if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &minfo->mmio.vbase)) {
+		printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
+		goto failVideoMR;
+	}
+	minfo->mmio.base = ctrlptr_phys;
+	minfo->mmio.len = 16384;
+	minfo->video.base = video_base_phys;
+	if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &minfo->video.vbase)) {
+		printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
+			video_base_phys, memsize);
+		goto failCtrlIO;
+	}
+	{
+		u_int32_t cmd;
+		u_int32_t mga_option;
+
+		pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &mga_option);
+		pci_read_config_dword(minfo->pcidev, PCI_COMMAND, &cmd);
+		mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
+		mga_option |= MX_OPTION_BSWAP;
+		/* disable palette snooping */
+		cmd &= ~PCI_COMMAND_VGA_PALETTE;
+		if (pci_dev_present(intel_82437)) {
+			if (!(mga_option & 0x20000000) && !minfo->devflags.nopciretry) {
+				printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
+			}
+			mga_option |= 0x20000000;
+			minfo->devflags.nopciretry = 1;
+		}
+		pci_write_config_dword(minfo->pcidev, PCI_COMMAND, cmd);
+		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mga_option);
+		minfo->hw.MXoptionReg = mga_option;
+
+		/* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
+		/* maybe preinit() candidate, but it is same... for all devices... at this time... */
+		pci_write_config_dword(minfo->pcidev, PCI_MGA_INDEX, 0x00003C00);
+	}
+
+	err = -ENXIO;
+	matroxfb_read_pins(minfo);
+	if (minfo->hw_switch->preinit(minfo)) {
+		goto failVideoIO;
+	}
+
+	err = -ENOMEM;
+	if (!matroxfb_getmemory(minfo, memsize, &minfo->video.len) || !minfo->video.len) {
+		printk(KERN_ERR "matroxfb: cannot determine memory size\n");
+		goto failVideoIO;
+	}
+	minfo->devflags.ydstorg = 0;
+
+	minfo->video.base = video_base_phys;
+	minfo->video.len_usable = minfo->video.len;
+	if (minfo->video.len_usable > b->base->maxdisplayable)
+		minfo->video.len_usable = b->base->maxdisplayable;
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		minfo->mtrr.vram = mtrr_add(video_base_phys, minfo->video.len, MTRR_TYPE_WRCOMB, 1);
+		minfo->mtrr.vram_valid = 1;
+		printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+	}
+#endif	/* CONFIG_MTRR */
+
+	if (!minfo->devflags.novga)
+		request_region(0x3C0, 32, "matrox");
+	matroxfb_g450_connect(minfo);
+	minfo->hw_switch->reset(minfo);
+
+	minfo->fbcon.monspecs.hfmin = 0;
+	minfo->fbcon.monspecs.hfmax = fh;
+	minfo->fbcon.monspecs.vfmin = 0;
+	minfo->fbcon.monspecs.vfmax = fv;
+	minfo->fbcon.monspecs.dpms = 0;	/* TBD */
+
+	/* static settings */
+	vesafb_defined.red = colors[depth-1].red;
+	vesafb_defined.green = colors[depth-1].green;
+	vesafb_defined.blue = colors[depth-1].blue;
+	vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel;
+	vesafb_defined.grayscale = grayscale;
+	vesafb_defined.vmode = 0;
+	if (noaccel)
+		vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
+
+	minfo->fbops = matroxfb_ops;
+	minfo->fbcon.fbops = &minfo->fbops;
+	minfo->fbcon.pseudo_palette = minfo->cmap;
+	/* after __init time we are like module... no logo */
+	minfo->fbcon.flags = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT;
+	minfo->fbcon.flags |= FBINFO_PARTIAL_PAN_OK | 	 /* Prefer panning for scroll under MC viewer/edit */
+				      FBINFO_HWACCEL_COPYAREA |  /* We have hw-assisted bmove */
+				      FBINFO_HWACCEL_FILLRECT |  /* And fillrect */
+				      FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */
+				      FBINFO_HWACCEL_XPAN |      /* And we support both horizontal */
+				      FBINFO_HWACCEL_YPAN |      /* And vertical panning */
+				      FBINFO_READS_FAST;
+	minfo->video.len_usable &= PAGE_MASK;
+	fb_alloc_cmap(&minfo->fbcon.cmap, 256, 1);
+
+#ifndef MODULE
+	/* mode database is marked __init!!! */
+	if (!hotplug) {
+		fb_find_mode(&vesafb_defined, &minfo->fbcon, videomode[0] ? videomode : NULL,
+			NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
+	}
+#endif /* !MODULE */
+
+	/* mode modifiers */
+	if (hslen)
+		vesafb_defined.hsync_len = hslen;
+	if (vslen)
+		vesafb_defined.vsync_len = vslen;
+	if (left != ~0)
+		vesafb_defined.left_margin = left;
+	if (right != ~0)
+		vesafb_defined.right_margin = right;
+	if (upper != ~0)
+		vesafb_defined.upper_margin = upper;
+	if (lower != ~0)
+		vesafb_defined.lower_margin = lower;
+	if (xres)
+		vesafb_defined.xres = xres;
+	if (yres)
+		vesafb_defined.yres = yres;
+	if (sync != -1)
+		vesafb_defined.sync = sync;
+	else if (vesafb_defined.sync == ~0) {
+		vesafb_defined.sync = 0;
+		if (yres < 400)
+			vesafb_defined.sync |= FB_SYNC_HOR_HIGH_ACT;
+		else if (yres < 480)
+			vesafb_defined.sync |= FB_SYNC_VERT_HIGH_ACT;
+	}
+
+	/* fv, fh, maxclk limits was specified */
+	{
+		unsigned int tmp;
+
+		if (fv) {
+			tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
+				  + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
+			if ((tmp < fh) || (fh == 0)) fh = tmp;
+		}
+		if (fh) {
+			tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
+				  + vesafb_defined.right_margin + vesafb_defined.hsync_len);
+			if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
+		}
+		tmp = (maxclk + 499) / 500;
+		if (tmp) {
+			tmp = (2000000000 + tmp) / tmp;
+			if (tmp > pixclock) pixclock = tmp;
+		}
+	}
+	if (pixclock) {
+		if (pixclock < 2000)		/* > 500MHz */
+			pixclock = 4000;	/* 250MHz */
+		if (pixclock > 1000000)
+			pixclock = 1000000;	/* 1MHz */
+		vesafb_defined.pixclock = pixclock;
+	}
+
+	/* FIXME: Where to move this?! */
+#if defined(CONFIG_PPC_PMAC)
+#ifndef MODULE
+	if (machine_is(powermac)) {
+		struct fb_var_screeninfo var;
+		if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+			default_vmode = VMODE_640_480_60;
+#ifdef CONFIG_NVRAM
+		if (default_cmode == CMODE_NVRAM)
+			default_cmode = nvram_read_byte(NV_CMODE);
+#endif
+		if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+			default_cmode = CMODE_8;
+		if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
+			var.accel_flags = vesafb_defined.accel_flags;
+			var.xoffset = var.yoffset = 0;
+			/* Note: mac_vmode_to_var() does not set all parameters */
+			vesafb_defined = var;
+		}
+	}
+#endif /* !MODULE */
+#endif /* CONFIG_PPC_PMAC */
+	vesafb_defined.xres_virtual = vesafb_defined.xres;
+	if (nopan) {
+		vesafb_defined.yres_virtual = vesafb_defined.yres;
+	} else {
+		vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
+							to yres_virtual * xres_virtual < 2^32 */
+	}
+	matroxfb_init_fix(minfo);
+	minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase);
+	/* Normalize values (namely yres_virtual) */
+	matroxfb_check_var(&vesafb_defined, &minfo->fbcon);
+	/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
+	 * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
+	 * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
+	 * anyway. But we at least tried... */
+	minfo->fbcon.var = vesafb_defined;
+	err = -EINVAL;
+
+	printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
+		vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
+		vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
+	printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
+		minfo->video.base, vaddr_va(minfo->video.vbase), minfo->video.len);
+
+/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
+ * and we do not want currcon == 0 for subsequent framebuffers */
+
+	minfo->fbcon.device = &minfo->pcidev->dev;
+	if (register_framebuffer(&minfo->fbcon) < 0) {
+		goto failVideoIO;
+	}
+	fb_info(&minfo->fbcon, "%s frame buffer device\n", minfo->fbcon.fix.id);
+
+	/* there is no console on this fb... but we have to initialize hardware
+	 * until someone tells me what is proper thing to do */
+	if (!minfo->initialized) {
+		fb_info(&minfo->fbcon, "initializing hardware\n");
+		/* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
+		 * already before, so register_framebuffer works correctly. */
+		vesafb_defined.activate |= FB_ACTIVATE_FORCE;
+		fb_set_var(&minfo->fbcon, &vesafb_defined);
+	}
+
+	return 0;
+failVideoIO:;
+	matroxfb_g450_shutdown(minfo);
+	mga_iounmap(minfo->video.vbase);
+failCtrlIO:;
+	mga_iounmap(minfo->mmio.vbase);
+failVideoMR:;
+	release_mem_region(video_base_phys, minfo->video.len_maximum);
+failCtrlMR:;
+	release_mem_region(ctrlptr_phys, 16384);
+fail:;
+	return err;
+}
+
+static LIST_HEAD(matroxfb_list);
+static LIST_HEAD(matroxfb_driver_list);
+
+#define matroxfb_l(x) list_entry(x, struct matrox_fb_info, next_fb)
+#define matroxfb_driver_l(x) list_entry(x, struct matroxfb_driver, node)
+int matroxfb_register_driver(struct matroxfb_driver* drv) {
+	struct matrox_fb_info* minfo;
+
+	list_add(&drv->node, &matroxfb_driver_list);
+	for (minfo = matroxfb_l(matroxfb_list.next);
+	     minfo != matroxfb_l(&matroxfb_list);
+	     minfo = matroxfb_l(minfo->next_fb.next)) {
+		void* p;
+
+		if (minfo->drivers_count == MATROXFB_MAX_FB_DRIVERS)
+			continue;
+		p = drv->probe(minfo);
+		if (p) {
+			minfo->drivers_data[minfo->drivers_count] = p;
+			minfo->drivers[minfo->drivers_count++] = drv;
+		}
+	}
+	return 0;
+}
+
+void matroxfb_unregister_driver(struct matroxfb_driver* drv) {
+	struct matrox_fb_info* minfo;
+
+	list_del(&drv->node);
+	for (minfo = matroxfb_l(matroxfb_list.next);
+	     minfo != matroxfb_l(&matroxfb_list);
+	     minfo = matroxfb_l(minfo->next_fb.next)) {
+		int i;
+
+		for (i = 0; i < minfo->drivers_count; ) {
+			if (minfo->drivers[i] == drv) {
+				if (drv && drv->remove)
+					drv->remove(minfo, minfo->drivers_data[i]);
+				minfo->drivers[i] = minfo->drivers[--minfo->drivers_count];
+				minfo->drivers_data[i] = minfo->drivers_data[minfo->drivers_count];
+			} else
+				i++;
+		}
+	}
+}
+
+static void matroxfb_register_device(struct matrox_fb_info* minfo) {
+	struct matroxfb_driver* drv;
+	int i = 0;
+	list_add(&minfo->next_fb, &matroxfb_list);
+	for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
+	     drv != matroxfb_driver_l(&matroxfb_driver_list);
+	     drv = matroxfb_driver_l(drv->node.next)) {
+		if (drv && drv->probe) {
+			void *p = drv->probe(minfo);
+			if (p) {
+				minfo->drivers_data[i] = p;
+				minfo->drivers[i++] = drv;
+				if (i == MATROXFB_MAX_FB_DRIVERS)
+					break;
+			}
+		}
+	}
+	minfo->drivers_count = i;
+}
+
+static void matroxfb_unregister_device(struct matrox_fb_info* minfo) {
+	int i;
+
+	list_del(&minfo->next_fb);
+	for (i = 0; i < minfo->drivers_count; i++) {
+		struct matroxfb_driver* drv = minfo->drivers[i];
+
+		if (drv && drv->remove)
+			drv->remove(minfo, minfo->drivers_data[i]);
+	}
+}
+
+static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dummy) {
+	struct board* b;
+	u_int16_t svid;
+	u_int16_t sid;
+	struct matrox_fb_info* minfo;
+	int err;
+	u_int32_t cmd;
+	DBG(__func__)
+
+	svid = pdev->subsystem_vendor;
+	sid = pdev->subsystem_device;
+	for (b = dev_list; b->vendor; b++) {
+		if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < pdev->revision)) continue;
+		if (b->svid)
+			if ((b->svid != svid) || (b->sid != sid)) continue;
+		break;
+	}
+	/* not match... */
+	if (!b->vendor)
+		return -ENODEV;
+	if (dev > 0) {
+		/* not requested one... */
+		dev--;
+		return -ENODEV;
+	}
+	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+	if (pci_enable_device(pdev)) {
+		return -1;
+	}
+
+	minfo = kzalloc(sizeof(*minfo), GFP_KERNEL);
+	if (!minfo)
+		return -1;
+
+	minfo->pcidev = pdev;
+	minfo->dead = 0;
+	minfo->usecount = 0;
+	minfo->userusecount = 0;
+
+	pci_set_drvdata(pdev, minfo);
+	/* DEVFLAGS */
+	minfo->devflags.memtype = memtype;
+	if (memtype != -1)
+		noinit = 0;
+	if (cmd & PCI_COMMAND_MEMORY) {
+		minfo->devflags.novga = novga;
+		minfo->devflags.nobios = nobios;
+		minfo->devflags.noinit = noinit;
+		/* subsequent heads always needs initialization and must not enable BIOS */
+		novga = 1;
+		nobios = 1;
+		noinit = 0;
+	} else {
+		minfo->devflags.novga = 1;
+		minfo->devflags.nobios = 1;
+		minfo->devflags.noinit = 0;
+	}
+
+	minfo->devflags.nopciretry = no_pci_retry;
+	minfo->devflags.mga_24bpp_fix = inv24;
+	minfo->devflags.precise_width = option_precise_width;
+	minfo->devflags.sgram = sgram;
+	minfo->capable.cross4MB = cross4MB;
+
+	spin_lock_init(&minfo->lock.DAC);
+	spin_lock_init(&minfo->lock.accel);
+	init_rwsem(&minfo->crtc2.lock);
+	init_rwsem(&minfo->altout.lock);
+	mutex_init(&minfo->fbcon.mm_lock);
+	minfo->irq_flags = 0;
+	init_waitqueue_head(&minfo->crtc1.vsync.wait);
+	init_waitqueue_head(&minfo->crtc2.vsync.wait);
+	minfo->crtc1.panpos = -1;
+
+	err = initMatrox2(minfo, b);
+	if (!err) {
+		matroxfb_register_device(minfo);
+		return 0;
+	}
+	kfree(minfo);
+	return -1;
+}
+
+static void pci_remove_matrox(struct pci_dev* pdev) {
+	struct matrox_fb_info* minfo;
+
+	minfo = pci_get_drvdata(pdev);
+	matroxfb_remove(minfo, 1);
+}
+
+static struct pci_device_id matroxfb_devices[] = {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2_AGP,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+#endif
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+#endif
+#ifdef CONFIG_FB_MATROX_G
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_MM,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_PCI,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G550,
+		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
+#endif
+	{0,			0,
+		0,		0,		0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, matroxfb_devices);
+
+
+static struct pci_driver matroxfb_driver = {
+	.name =		"matroxfb",
+	.id_table =	matroxfb_devices,
+	.probe =	matroxfb_probe,
+	.remove =	pci_remove_matrox,
+};
+
+/* **************************** init-time only **************************** */
+
+#define RSResolution(X)	((X) & 0x0F)
+#define RS640x400	1
+#define RS640x480	2
+#define RS800x600	3
+#define RS1024x768	4
+#define RS1280x1024	5
+#define RS1600x1200	6
+#define RS768x576	7
+#define RS960x720	8
+#define RS1152x864	9
+#define RS1408x1056	10
+#define RS640x350	11
+#define RS1056x344	12	/* 132 x 43 text */
+#define RS1056x400	13	/* 132 x 50 text */
+#define RS1056x480	14	/* 132 x 60 text */
+#define RSNoxNo		15
+/* 10-FF */
+static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
+	{  640,  400,  48, 16, 39,  8,  96, 2, 70 },
+	{  640,  480,  48, 16, 33, 10,  96, 2, 60 },
+	{  800,  600, 144, 24, 28,  8, 112, 6, 60 },
+	{ 1024,  768, 160, 32, 30,  4, 128, 4, 60 },
+	{ 1280, 1024, 224, 32, 32,  4, 136, 4, 60 },
+	{ 1600, 1200, 272, 48, 32,  5, 152, 5, 60 },
+	{  768,  576, 144, 16, 28,  6, 112, 4, 60 },
+	{  960,  720, 144, 24, 28,  8, 112, 4, 60 },
+	{ 1152,  864, 192, 32, 30,  4, 128, 4, 60 },
+	{ 1408, 1056, 256, 40, 32,  5, 144, 5, 60 },
+	{  640,  350,  48, 16, 39,  8,  96, 2, 70 },
+	{ 1056,  344,  96, 24, 59, 44, 160, 2, 70 },
+	{ 1056,  400,  96, 24, 39,  8, 160, 2, 70 },
+	{ 1056,  480,  96, 24, 36, 12, 160, 3, 60 },
+	{    0,    0,  ~0, ~0, ~0, ~0,   0, 0,  0 }
+};
+
+#define RSCreate(X,Y)	((X) | ((Y) << 8))
+static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
+/* default must be first */
+	{    ~0, RSCreate(RSNoxNo,     RS8bpp ) },
+	{ 0x101, RSCreate(RS640x480,   RS8bpp ) },
+	{ 0x100, RSCreate(RS640x400,   RS8bpp ) },
+	{ 0x180, RSCreate(RS768x576,   RS8bpp ) },
+	{ 0x103, RSCreate(RS800x600,   RS8bpp ) },
+	{ 0x188, RSCreate(RS960x720,   RS8bpp ) },
+	{ 0x105, RSCreate(RS1024x768,  RS8bpp ) },
+	{ 0x190, RSCreate(RS1152x864,  RS8bpp ) },
+	{ 0x107, RSCreate(RS1280x1024, RS8bpp ) },
+	{ 0x198, RSCreate(RS1408x1056, RS8bpp ) },
+	{ 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
+	{ 0x110, RSCreate(RS640x480,   RS15bpp) },
+	{ 0x181, RSCreate(RS768x576,   RS15bpp) },
+	{ 0x113, RSCreate(RS800x600,   RS15bpp) },
+	{ 0x189, RSCreate(RS960x720,   RS15bpp) },
+	{ 0x116, RSCreate(RS1024x768,  RS15bpp) },
+	{ 0x191, RSCreate(RS1152x864,  RS15bpp) },
+	{ 0x119, RSCreate(RS1280x1024, RS15bpp) },
+	{ 0x199, RSCreate(RS1408x1056, RS15bpp) },
+	{ 0x11D, RSCreate(RS1600x1200, RS15bpp) },
+	{ 0x111, RSCreate(RS640x480,   RS16bpp) },
+	{ 0x182, RSCreate(RS768x576,   RS16bpp) },
+	{ 0x114, RSCreate(RS800x600,   RS16bpp) },
+	{ 0x18A, RSCreate(RS960x720,   RS16bpp) },
+	{ 0x117, RSCreate(RS1024x768,  RS16bpp) },
+	{ 0x192, RSCreate(RS1152x864,  RS16bpp) },
+	{ 0x11A, RSCreate(RS1280x1024, RS16bpp) },
+	{ 0x19A, RSCreate(RS1408x1056, RS16bpp) },
+	{ 0x11E, RSCreate(RS1600x1200, RS16bpp) },
+	{ 0x1B2, RSCreate(RS640x480,   RS24bpp) },
+	{ 0x184, RSCreate(RS768x576,   RS24bpp) },
+	{ 0x1B5, RSCreate(RS800x600,   RS24bpp) },
+	{ 0x18C, RSCreate(RS960x720,   RS24bpp) },
+	{ 0x1B8, RSCreate(RS1024x768,  RS24bpp) },
+	{ 0x194, RSCreate(RS1152x864,  RS24bpp) },
+	{ 0x1BB, RSCreate(RS1280x1024, RS24bpp) },
+	{ 0x19C, RSCreate(RS1408x1056, RS24bpp) },
+	{ 0x1BF, RSCreate(RS1600x1200, RS24bpp) },
+	{ 0x112, RSCreate(RS640x480,   RS32bpp) },
+	{ 0x183, RSCreate(RS768x576,   RS32bpp) },
+	{ 0x115, RSCreate(RS800x600,   RS32bpp) },
+	{ 0x18B, RSCreate(RS960x720,   RS32bpp) },
+	{ 0x118, RSCreate(RS1024x768,  RS32bpp) },
+	{ 0x193, RSCreate(RS1152x864,  RS32bpp) },
+	{ 0x11B, RSCreate(RS1280x1024, RS32bpp) },
+	{ 0x19B, RSCreate(RS1408x1056, RS32bpp) },
+	{ 0x11F, RSCreate(RS1600x1200, RS32bpp) },
+	{ 0x010, RSCreate(RS640x350,   RS4bpp ) },
+	{ 0x012, RSCreate(RS640x480,   RS4bpp ) },
+	{ 0x102, RSCreate(RS800x600,   RS4bpp ) },
+	{ 0x104, RSCreate(RS1024x768,  RS4bpp ) },
+	{ 0x106, RSCreate(RS1280x1024, RS4bpp ) },
+	{     0, 0				}};
+
+static void __init matroxfb_init_params(void) {
+	/* fh from kHz to Hz */
+	if (fh < 1000)
+		fh *= 1000;	/* 1kHz minimum */
+	/* maxclk */
+	if (maxclk < 1000) maxclk *= 1000;	/* kHz -> Hz, MHz -> kHz */
+	if (maxclk < 1000000) maxclk *= 1000;	/* kHz -> Hz, 1MHz minimum */
+	/* fix VESA number */
+	if (vesa != ~0)
+		vesa &= 0x1DFF;		/* mask out clearscreen, acceleration and so on */
+
+	/* static settings */
+	for (RSptr = vesamap; RSptr->vesa; RSptr++) {
+		if (RSptr->vesa == vesa) break;
+	}
+	if (!RSptr->vesa) {
+		printk(KERN_ERR "Invalid vesa mode 0x%04X\n", vesa);
+		RSptr = vesamap;
+	}
+	{
+		int res = RSResolution(RSptr->info)-1;
+		if (left == ~0)
+			left = timmings[res].left;
+		if (!xres)
+			xres = timmings[res].xres;
+		if (right == ~0)
+			right = timmings[res].right;
+		if (!hslen)
+			hslen = timmings[res].hslen;
+		if (upper == ~0)
+			upper = timmings[res].upper;
+		if (!yres)
+			yres = timmings[res].yres;
+		if (lower == ~0)
+			lower = timmings[res].lower;
+		if (!vslen)
+			vslen = timmings[res].vslen;
+		if (!(fv||fh||maxclk||pixclock))
+			fv = timmings[res].vfreq;
+		if (depth == -1)
+			depth = RSDepth(RSptr->info);
+	}
+}
+
+static int __init matrox_init(void) {
+	int err;
+
+	matroxfb_init_params();
+	err = pci_register_driver(&matroxfb_driver);
+	dev = -1;	/* accept all new devices... */
+	return err;
+}
+
+/* **************************** exit-time only **************************** */
+
+static void __exit matrox_done(void) {
+	pci_unregister_driver(&matroxfb_driver);
+}
+
+#ifndef MODULE
+
+/* ************************* init in-kernel code ************************** */
+
+static int __init matroxfb_setup(char *options) {
+	char *this_opt;
+
+	DBG(__func__)
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt) continue;
+
+		dprintk("matroxfb_setup: option %s\n", this_opt);
+
+		if (!strncmp(this_opt, "dev:", 4))
+			dev = simple_strtoul(this_opt+4, NULL, 0);
+		else if (!strncmp(this_opt, "depth:", 6)) {
+			switch (simple_strtoul(this_opt+6, NULL, 0)) {
+				case 0: depth = RSText; break;
+				case 4: depth = RS4bpp; break;
+				case 8: depth = RS8bpp; break;
+				case 15:depth = RS15bpp; break;
+				case 16:depth = RS16bpp; break;
+				case 24:depth = RS24bpp; break;
+				case 32:depth = RS32bpp; break;
+				default:
+					printk(KERN_ERR "matroxfb: unsupported color depth\n");
+			}
+		} else if (!strncmp(this_opt, "xres:", 5))
+			xres = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "yres:", 5))
+			yres = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "vslen:", 6))
+			vslen = simple_strtoul(this_opt+6, NULL, 0);
+		else if (!strncmp(this_opt, "hslen:", 6))
+			hslen = simple_strtoul(this_opt+6, NULL, 0);
+		else if (!strncmp(this_opt, "left:", 5))
+			left = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "right:", 6))
+			right = simple_strtoul(this_opt+6, NULL, 0);
+		else if (!strncmp(this_opt, "upper:", 6))
+			upper = simple_strtoul(this_opt+6, NULL, 0);
+		else if (!strncmp(this_opt, "lower:", 6))
+			lower = simple_strtoul(this_opt+6, NULL, 0);
+		else if (!strncmp(this_opt, "pixclock:", 9))
+			pixclock = simple_strtoul(this_opt+9, NULL, 0);
+		else if (!strncmp(this_opt, "sync:", 5))
+			sync = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "vesa:", 5))
+			vesa = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strncmp(this_opt, "maxclk:", 7))
+			maxclk = simple_strtoul(this_opt+7, NULL, 0);
+		else if (!strncmp(this_opt, "fh:", 3))
+			fh = simple_strtoul(this_opt+3, NULL, 0);
+		else if (!strncmp(this_opt, "fv:", 3))
+			fv = simple_strtoul(this_opt+3, NULL, 0);
+		else if (!strncmp(this_opt, "mem:", 4))
+			mem = simple_strtoul(this_opt+4, NULL, 0);
+		else if (!strncmp(this_opt, "mode:", 5))
+			strlcpy(videomode, this_opt+5, sizeof(videomode));
+		else if (!strncmp(this_opt, "outputs:", 8))
+			strlcpy(outputs, this_opt+8, sizeof(outputs));
+		else if (!strncmp(this_opt, "dfp:", 4)) {
+			dfp_type = simple_strtoul(this_opt+4, NULL, 0);
+			dfp = 1;
+		}
+#ifdef CONFIG_PPC_PMAC
+		else if (!strncmp(this_opt, "vmode:", 6)) {
+			unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
+			if (vmode > 0 && vmode <= VMODE_MAX)
+				default_vmode = vmode;
+		} else if (!strncmp(this_opt, "cmode:", 6)) {
+			unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+			switch (cmode) {
+				case 0:
+				case 8:
+					default_cmode = CMODE_8;
+					break;
+				case 15:
+				case 16:
+					default_cmode = CMODE_16;
+					break;
+				case 24:
+				case 32:
+					default_cmode = CMODE_32;
+					break;
+			}
+		}
+#endif
+		else if (!strcmp(this_opt, "disabled"))	/* nodisabled does not exist */
+			disabled = 1;
+		else if (!strcmp(this_opt, "enabled"))	/* noenabled does not exist */
+			disabled = 0;
+		else if (!strcmp(this_opt, "sgram"))	/* nosgram == sdram */
+			sgram = 1;
+		else if (!strcmp(this_opt, "sdram"))
+			sgram = 0;
+		else if (!strncmp(this_opt, "memtype:", 8))
+			memtype = simple_strtoul(this_opt+8, NULL, 0);
+		else {
+			int value = 1;
+
+			if (!strncmp(this_opt, "no", 2)) {
+				value = 0;
+				this_opt += 2;
+			}
+			if (! strcmp(this_opt, "inverse"))
+				inverse = value;
+			else if (!strcmp(this_opt, "accel"))
+				noaccel = !value;
+			else if (!strcmp(this_opt, "pan"))
+				nopan = !value;
+			else if (!strcmp(this_opt, "pciretry"))
+				no_pci_retry = !value;
+			else if (!strcmp(this_opt, "vga"))
+				novga = !value;
+			else if (!strcmp(this_opt, "bios"))
+				nobios = !value;
+			else if (!strcmp(this_opt, "init"))
+				noinit = !value;
+#ifdef CONFIG_MTRR
+			else if (!strcmp(this_opt, "mtrr"))
+				mtrr = value;
+#endif
+			else if (!strcmp(this_opt, "inv24"))
+				inv24 = value;
+			else if (!strcmp(this_opt, "cross4MB"))
+				cross4MB = value;
+			else if (!strcmp(this_opt, "grayscale"))
+				grayscale = value;
+			else if (!strcmp(this_opt, "dfp"))
+				dfp = value;
+			else {
+				strlcpy(videomode, this_opt, sizeof(videomode));
+			}
+		}
+	}
+	return 0;
+}
+
+static int __initdata initialized = 0;
+
+static int __init matroxfb_init(void)
+{
+	char *option = NULL;
+	int err = 0;
+
+	DBG(__func__)
+
+	if (fb_get_options("matroxfb", &option))
+		return -ENODEV;
+	matroxfb_setup(option);
+
+	if (disabled)
+		return -ENXIO;
+	if (!initialized) {
+		initialized = 1;
+		err = matrox_init();
+	}
+	hotplug = 1;
+	/* never return failure, user can hotplug matrox later... */
+	return err;
+}
+
+module_init(matroxfb_init);
+
+#else
+
+/* *************************** init module code **************************** */
+
+MODULE_AUTHOR("(c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450/G550");
+MODULE_LICENSE("GPL");
+
+module_param(mem, int, 0);
+MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
+module_param(disabled, int, 0);
+MODULE_PARM_DESC(disabled, "Disabled (0 or 1=disabled) (default=0)");
+module_param(noaccel, int, 0);
+MODULE_PARM_DESC(noaccel, "Do not use accelerating engine (0 or 1=disabled) (default=0)");
+module_param(nopan, int, 0);
+MODULE_PARM_DESC(nopan, "Disable pan on startup (0 or 1=disabled) (default=0)");
+module_param(no_pci_retry, int, 0);
+MODULE_PARM_DESC(no_pci_retry, "PCI retries enabled (0 or 1=disabled) (default=0)");
+module_param(novga, int, 0);
+MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
+module_param(nobios, int, 0);
+MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
+module_param(noinit, int, 0);
+MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
+module_param(memtype, int, 0);
+MODULE_PARM_DESC(memtype, "Memory type for G200/G400 (see Documentation/fb/matroxfb.txt for explanation) (default=3 for G200, 0 for G400)");
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0);
+MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
+#endif
+module_param(sgram, int, 0);
+MODULE_PARM_DESC(sgram, "Indicates that G100/G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
+module_param(inv24, int, 0);
+MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
+module_param(inverse, int, 0);
+MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)");
+module_param(dev, int, 0);
+MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)");
+module_param(vesa, int, 0);
+MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
+module_param(xres, int, 0);
+MODULE_PARM_DESC(xres, "Horizontal resolution (px), overrides xres from vesa (default=vesa)");
+module_param(yres, int, 0);
+MODULE_PARM_DESC(yres, "Vertical resolution (scans), overrides yres from vesa (default=vesa)");
+module_param(upper, int, 0);
+MODULE_PARM_DESC(upper, "Upper blank space (scans), overrides upper from vesa (default=vesa)");
+module_param(lower, int, 0);
+MODULE_PARM_DESC(lower, "Lower blank space (scans), overrides lower from vesa (default=vesa)");
+module_param(vslen, int, 0);
+MODULE_PARM_DESC(vslen, "Vertical sync length (scans), overrides lower from vesa (default=vesa)");
+module_param(left, int, 0);
+MODULE_PARM_DESC(left, "Left blank space (px), overrides left from vesa (default=vesa)");
+module_param(right, int, 0);
+MODULE_PARM_DESC(right, "Right blank space (px), overrides right from vesa (default=vesa)");
+module_param(hslen, int, 0);
+MODULE_PARM_DESC(hslen, "Horizontal sync length (px), overrides hslen from vesa (default=vesa)");
+module_param(pixclock, int, 0);
+MODULE_PARM_DESC(pixclock, "Pixelclock (ns), overrides pixclock from vesa (default=vesa)");
+module_param(sync, int, 0);
+MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
+module_param(depth, int, 0);
+MODULE_PARM_DESC(depth, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
+module_param(maxclk, int, 0);
+MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
+module_param(fh, int, 0);
+MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
+module_param(fv, int, 0);
+MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
+"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"");
+module_param(grayscale, int, 0);
+MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
+module_param(cross4MB, int, 0);
+MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
+module_param(dfp, int, 0);
+MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)");
+module_param(dfp_type, int, 0);
+MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)");
+module_param_string(outputs, outputs, sizeof(outputs), 0);
+MODULE_PARM_DESC(outputs, "Specifies which CRTC is mapped to which output (string of up to three letters, consisting of 0 (disabled), 1 (CRTC1), 2 (CRTC2)) (default=111 for Gx50, 101 for G200/G400 with DFP, and 100 for all other devices)");
+#ifdef CONFIG_PPC_PMAC
+module_param_named(vmode, default_vmode, int, 0);
+MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
+module_param_named(cmode, default_cmode, int, 0);
+MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit default)");
+#endif
+
+int __init init_module(void){
+
+	DBG(__func__)
+
+	if (disabled)
+		return -ENXIO;
+
+	if (depth == 0)
+		depth = RSText;
+	else if (depth == 4)
+		depth = RS4bpp;
+	else if (depth == 8)
+		depth = RS8bpp;
+	else if (depth == 15)
+		depth = RS15bpp;
+	else if (depth == 16)
+		depth = RS16bpp;
+	else if (depth == 24)
+		depth = RS24bpp;
+	else if (depth == 32)
+		depth = RS32bpp;
+	else if (depth != -1) {
+		printk(KERN_ERR "matroxfb: depth %d is not supported, using default\n", depth);
+		depth = -1;
+	}
+	matrox_init();
+	/* never return failure; user can hotplug matrox later... */
+	return 0;
+}
+#endif	/* MODULE */
+
+module_exit(matrox_done);
+EXPORT_SYMBOL(matroxfb_register_driver);
+EXPORT_SYMBOL(matroxfb_unregister_driver);
+EXPORT_SYMBOL(matroxfb_wait_for_sync);
+EXPORT_SYMBOL(matroxfb_enable_irq);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/drivers/video/fbdev/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h
new file mode 100644
index 000000000000..556d96ce40bf
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_base.h
@@ -0,0 +1,735 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ */
+#ifndef __MATROXFB_H__
+#define __MATROXFB_H__
+
+/* general, but fairly heavy, debugging */
+#undef MATROXFB_DEBUG
+
+/* heavy debugging: */
+/* -- logs putc[s], so every time a char is displayed, it's logged */
+#undef MATROXFB_DEBUG_HEAVY
+
+/* This one _could_ cause infinite loops */
+/* It _does_ cause lots and lots of messages during idle loops */
+#undef MATROXFB_DEBUG_LOOP
+
+/* Debug register calls, too? */
+#undef MATROXFB_DEBUG_REG
+
+/* Guard accelerator accesses with spin_lock_irqsave... */
+#undef MATROXFB_USE_SPINLOCKS
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/kd.h>
+
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#if defined(CONFIG_PPC_PMAC)
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include "../macmodes.h"
+#endif
+
+#ifdef MATROXFB_DEBUG
+
+#define DEBUG
+#define DBG(x)		printk(KERN_DEBUG "matroxfb: %s\n", (x));
+
+#ifdef MATROXFB_DEBUG_HEAVY
+#define DBG_HEAVY(x)	DBG(x)
+#else /* MATROXFB_DEBUG_HEAVY */
+#define DBG_HEAVY(x)	/* DBG_HEAVY */
+#endif /* MATROXFB_DEBUG_HEAVY */
+
+#ifdef MATROXFB_DEBUG_LOOP
+#define DBG_LOOP(x)	DBG(x)
+#else /* MATROXFB_DEBUG_LOOP */
+#define DBG_LOOP(x)	/* DBG_LOOP */
+#endif /* MATROXFB_DEBUG_LOOP */
+
+#ifdef MATROXFB_DEBUG_REG
+#define DBG_REG(x)	DBG(x)
+#else /* MATROXFB_DEBUG_REG */
+#define DBG_REG(x)	/* DBG_REG */
+#endif /* MATROXFB_DEBUG_REG */
+
+#else /* MATROXFB_DEBUG */
+
+#define DBG(x)		/* DBG */
+#define DBG_HEAVY(x)	/* DBG_HEAVY */
+#define DBG_REG(x)	/* DBG_REG */
+#define DBG_LOOP(x)	/* DBG_LOOP */
+
+#endif /* MATROXFB_DEBUG */
+
+#ifdef DEBUG
+#define dprintk(X...)	printk(X)
+#else
+#define dprintk(X...)
+#endif
+
+#ifndef PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
+#define PCI_SS_VENDOR_ID_SIEMENS_NIXDORF	0x110A
+#endif
+#ifndef PCI_SS_VENDOR_ID_MATROX
+#define PCI_SS_VENDOR_ID_MATROX		PCI_VENDOR_ID_MATROX
+#endif
+
+#ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
+#define PCI_SS_ID_MATROX_GENERIC		0xFF00
+#define PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP	0xFF01
+#define PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP	0xFF02
+#define PCI_SS_ID_MATROX_MILLENIUM_G200_AGP	0xFF03
+#define PCI_SS_ID_MATROX_MARVEL_G200_AGP	0xFF04
+#define PCI_SS_ID_MATROX_MGA_G100_PCI		0xFF05
+#define PCI_SS_ID_MATROX_MGA_G100_AGP		0x1001
+#define PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP	0x2179
+#define PCI_SS_ID_SIEMENS_MGA_G100_AGP		0x001E /* 30 */
+#define PCI_SS_ID_SIEMENS_MGA_G200_AGP		0x0032 /* 50 */
+#endif
+
+#define MX_VISUAL_TRUECOLOR	FB_VISUAL_DIRECTCOLOR
+#define MX_VISUAL_DIRECTCOLOR	FB_VISUAL_TRUECOLOR
+#define MX_VISUAL_PSEUDOCOLOR	FB_VISUAL_PSEUDOCOLOR
+
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+
+/* G-series and Mystique have (almost) same DAC */
+#undef NEED_DAC1064
+#if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G)
+#define NEED_DAC1064 1
+#endif
+
+typedef struct {
+	void __iomem*	vaddr;
+} vaddr_t;
+
+static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
+	return readb(va.vaddr + offs);
+}
+
+static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
+	writeb(value, va.vaddr + offs);
+}
+
+static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
+	writew(value, va.vaddr + offs);
+}
+
+static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
+	return readl(va.vaddr + offs);
+}
+
+static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
+	writel(value, va.vaddr + offs);
+}
+
+static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
+#if defined(__alpha__) || defined(__i386__) || defined(__x86_64__)
+	/*
+	 * iowrite32_rep works for us if:
+	 *  (1) Copies data as 32bit quantities, not byte after byte,
+	 *  (2) Performs LE ordered stores, and
+	 *  (3) It copes with unaligned source (destination is guaranteed to be page
+	 *      aligned and length is guaranteed to be multiple of 4).
+	 */
+	iowrite32_rep(va.vaddr, src, len >> 2);
+#else
+        u_int32_t __iomem* addr = va.vaddr;
+
+	if ((unsigned long)src & 3) {
+		while (len >= 4) {
+			fb_writel(get_unaligned((u32 *)src), addr);
+			addr++;
+			len -= 4;
+			src += 4;
+		}
+	} else {
+		while (len >= 4) {
+			fb_writel(*(u32 *)src, addr);
+			addr++;
+			len -= 4;
+			src += 4;
+		}
+	}
+#endif
+}
+
+static inline void vaddr_add(vaddr_t* va, unsigned long offs) {
+	va->vaddr += offs;
+}
+
+static inline void __iomem* vaddr_va(vaddr_t va) {
+	return va.vaddr;
+}
+
+#define MGA_IOREMAP_NORMAL	0
+#define MGA_IOREMAP_NOCACHE	1
+
+#define MGA_IOREMAP_FB		MGA_IOREMAP_NOCACHE
+#define MGA_IOREMAP_MMIO	MGA_IOREMAP_NOCACHE
+static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags, vaddr_t* virt) {
+	if (flags & MGA_IOREMAP_NOCACHE)
+		virt->vaddr = ioremap_nocache(phys, size);
+	else
+		virt->vaddr = ioremap(phys, size);
+	return (virt->vaddr == NULL); /* 0, !0... 0, error_code in future */
+}
+
+static inline void mga_iounmap(vaddr_t va) {
+	iounmap(va.vaddr);
+}
+
+struct my_timming {
+	unsigned int pixclock;
+	int mnp;
+	unsigned int crtc;
+	unsigned int HDisplay;
+	unsigned int HSyncStart;
+	unsigned int HSyncEnd;
+	unsigned int HTotal;
+	unsigned int VDisplay;
+	unsigned int VSyncStart;
+	unsigned int VSyncEnd;
+	unsigned int VTotal;
+	unsigned int sync;
+	int	     dblscan;
+	int	     interlaced;
+	unsigned int delay;	/* CRTC delay */
+};
+
+enum { M_SYSTEM_PLL, M_PIXEL_PLL_A, M_PIXEL_PLL_B, M_PIXEL_PLL_C, M_VIDEO_PLL };
+
+struct matrox_pll_cache {
+	unsigned int	valid;
+	struct {
+		unsigned int	mnp_key;
+		unsigned int	mnp_value;
+		      } data[4];
+};
+
+struct matrox_pll_limits {
+	unsigned int	vcomin;
+	unsigned int	vcomax;
+};
+
+struct matrox_pll_features {
+	unsigned int	vco_freq_min;
+	unsigned int	ref_freq;
+	unsigned int	feed_div_min;
+	unsigned int	feed_div_max;
+	unsigned int	in_div_min;
+	unsigned int	in_div_max;
+	unsigned int	post_shift_max;
+};
+
+struct matroxfb_par
+{
+	unsigned int	final_bppShift;
+	unsigned int	cmap_len;
+	struct {
+		unsigned int bytes;
+		unsigned int pixels;
+		unsigned int chunks;
+		      } ydstorg;
+};
+
+struct matrox_fb_info;
+
+struct matrox_DAC1064_features {
+	u_int8_t	xvrefctrl;
+	u_int8_t	xmiscctrl;
+};
+
+/* current hardware status */
+struct mavenregs {
+	u_int8_t regs[256];
+	int	 mode;
+	int	 vlines;
+	int	 xtal;
+	int	 fv;
+
+	u_int16_t htotal;
+	u_int16_t hcorr;
+};
+
+struct matrox_crtc2 {
+	u_int32_t ctl;
+};
+
+struct matrox_hw_state {
+	u_int32_t	MXoptionReg;
+	unsigned char	DACclk[6];
+	unsigned char	DACreg[80];
+	unsigned char	MiscOutReg;
+	unsigned char	DACpal[768];
+	unsigned char	CRTC[25];
+	unsigned char	CRTCEXT[9];
+	unsigned char	SEQ[5];
+	/* unused for MGA mode, but who knows... */
+	unsigned char	GCTL[9];
+	/* unused for MGA mode, but who knows... */
+	unsigned char	ATTR[21];
+
+	/* TVOut only */
+	struct mavenregs	maven;
+
+	struct matrox_crtc2	crtc2;
+};
+
+struct matrox_accel_data {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+	unsigned char	ramdac_rev;
+#endif
+	u_int32_t	m_dwg_rect;
+	u_int32_t	m_opmode;
+	u_int32_t	m_access;
+	u_int32_t	m_pitch;
+};
+
+struct v4l2_queryctrl;
+struct v4l2_control;
+
+struct matrox_altout {
+	const char	*name;
+	int		(*compute)(void* altout_dev, struct my_timming* input);
+	int		(*program)(void* altout_dev);
+	int		(*start)(void* altout_dev);
+	int		(*verifymode)(void* altout_dev, u_int32_t mode);
+	int		(*getqueryctrl)(void* altout_dev,
+					struct v4l2_queryctrl* ctrl);
+	int		(*getctrl)(void* altout_dev, 
+				   struct v4l2_control* ctrl);
+	int		(*setctrl)(void* altout_dev, 
+				   struct v4l2_control* ctrl);
+};
+
+#define MATROXFB_SRC_NONE	0
+#define MATROXFB_SRC_CRTC1	1
+#define MATROXFB_SRC_CRTC2	2
+
+enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 };
+
+struct matrox_bios {
+	unsigned int	bios_valid : 1;
+	unsigned int	pins_len;
+	unsigned char	pins[128];
+	struct {
+		unsigned char vMaj, vMin, vRev;
+		      } version;
+	struct {
+		unsigned char state, tvout;
+		      } output;
+};
+
+struct matrox_switch;
+struct matroxfb_driver;
+struct matroxfb_dh_fb_info;
+
+struct matrox_vsync {
+	wait_queue_head_t	wait;
+	unsigned int		cnt;
+};
+
+struct matrox_fb_info {
+	struct fb_info		fbcon;
+
+	struct list_head	next_fb;
+
+	int			dead;
+	int                     initialized;
+	unsigned int		usecount;
+
+	unsigned int		userusecount;
+	unsigned long		irq_flags;
+
+	struct matroxfb_par	curr;
+	struct matrox_hw_state	hw;
+
+	struct matrox_accel_data accel;
+
+	struct pci_dev*		pcidev;
+
+	struct {
+		struct matrox_vsync	vsync;
+		unsigned int	pixclock;
+		int		mnp;
+		int		panpos;
+			      } crtc1;
+	struct {
+		struct matrox_vsync	vsync;
+		unsigned int 	pixclock;
+		int		mnp;
+	struct matroxfb_dh_fb_info*	info;
+	struct rw_semaphore	lock;
+			      } crtc2;
+	struct {
+	struct rw_semaphore	lock;
+	struct {
+		int brightness, contrast, saturation, hue, gamma;
+		int testout, deflicker;
+				} tvo_params;
+			      } altout;
+#define MATROXFB_MAX_OUTPUTS		3
+	struct {
+	unsigned int		src;
+	struct matrox_altout*	output;
+	void*			data;
+	unsigned int		mode;
+	unsigned int		default_src;
+			      } outputs[MATROXFB_MAX_OUTPUTS];
+
+#define MATROXFB_MAX_FB_DRIVERS		5
+	struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]);
+	void*			(drivers_data[MATROXFB_MAX_FB_DRIVERS]);
+	unsigned int		drivers_count;
+
+	struct {
+	unsigned long	base;	/* physical */
+	vaddr_t		vbase;	/* CPU view */
+	unsigned int	len;
+	unsigned int	len_usable;
+	unsigned int	len_maximum;
+		      } video;
+
+	struct {
+	unsigned long	base;	/* physical */
+	vaddr_t		vbase;	/* CPU view */
+	unsigned int	len;
+		      } mmio;
+
+	unsigned int	max_pixel_clock;
+	unsigned int	max_pixel_clock_panellink;
+
+	struct matrox_switch*	hw_switch;
+
+	struct {
+		struct matrox_pll_features pll;
+		struct matrox_DAC1064_features DAC1064;
+			      } features;
+	struct {
+		spinlock_t	DAC;
+		spinlock_t	accel;
+			      } lock;
+
+	enum mga_chip		chip;
+
+	int			interleave;
+	int			millenium;
+	int			milleniumII;
+	struct {
+		int		cfb4;
+		const int*	vxres;
+		int		cross4MB;
+		int		text;
+		int		plnwt;
+		int		srcorg;
+			      } capable;
+#ifdef CONFIG_MTRR
+	struct {
+		int		vram;
+		int		vram_valid;
+			      } mtrr;
+#endif
+	struct {
+		int		precise_width;
+		int		mga_24bpp_fix;
+		int		novga;
+		int		nobios;
+		int		nopciretry;
+		int		noinit;
+		int		sgram;
+		int		support32MB;
+
+		int		accelerator;
+		int		text_type_aux;
+		int		video64bits;
+		int		crtc2;
+		int		maven_capable;
+		unsigned int	vgastep;
+		unsigned int	textmode;
+		unsigned int	textstep;
+		unsigned int	textvram;	/* character cells */
+		unsigned int	ydstorg;	/* offset in bytes from video start to usable memory */
+						/* 0 except for 6MB Millenium */
+		int		memtype;
+		int		g450dac;
+		int		dfp_type;
+		int		panellink;	/* G400 DFP possible (not G450/G550) */
+		int		dualhead;
+		unsigned int	fbResource;
+			      } devflags;
+	struct fb_ops		fbops;
+	struct matrox_bios	bios;
+	struct {
+		struct matrox_pll_limits	pixel;
+		struct matrox_pll_limits	system;
+		struct matrox_pll_limits	video;
+			      } limits;
+	struct {
+		struct matrox_pll_cache	pixel;
+		struct matrox_pll_cache	system;
+		struct matrox_pll_cache	video;
+				      } cache;
+	struct {
+		struct {
+			unsigned int	video;
+			unsigned int	system;
+				      } pll;
+		struct {
+			u_int32_t	opt;
+			u_int32_t	opt2;
+			u_int32_t	opt3;
+			u_int32_t	mctlwtst;
+			u_int32_t	mctlwtst_core;
+			u_int32_t	memmisc;
+			u_int32_t	memrdbk;
+			u_int32_t	maccess;
+				      } reg;
+		struct {
+			unsigned int	ddr:1,
+			                emrswen:1,
+					dll:1;
+				      } memory;
+			      } values;
+	u_int32_t cmap[16];
+};
+
+#define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
+
+struct matrox_switch {
+	int	(*preinit)(struct matrox_fb_info *minfo);
+	void	(*reset)(struct matrox_fb_info *minfo);
+	int	(*init)(struct matrox_fb_info *minfo, struct my_timming*);
+	void	(*restore)(struct matrox_fb_info *minfo);
+};
+
+struct matroxfb_driver {
+	struct list_head	node;
+	char*			name;
+	void*			(*probe)(struct matrox_fb_info* info);
+	void			(*remove)(struct matrox_fb_info* info, void* data);
+};
+
+int matroxfb_register_driver(struct matroxfb_driver* drv);
+void matroxfb_unregister_driver(struct matroxfb_driver* drv);
+
+#define PCI_OPTION_REG	0x40
+#define   PCI_OPTION_ENABLE_ROM		0x40000000
+
+#define PCI_MGA_INDEX	0x44
+#define PCI_MGA_DATA	0x48
+#define PCI_OPTION2_REG	0x50
+#define PCI_OPTION3_REG	0x54
+#define PCI_MEMMISC_REG	0x58
+
+#define M_DWGCTL	0x1C00
+#define M_MACCESS	0x1C04
+#define M_CTLWTST	0x1C08
+
+#define M_PLNWT		0x1C1C
+
+#define M_BCOL		0x1C20
+#define M_FCOL		0x1C24
+
+#define M_SGN		0x1C58
+#define M_LEN		0x1C5C
+#define M_AR0		0x1C60
+#define M_AR1		0x1C64
+#define M_AR2		0x1C68
+#define M_AR3		0x1C6C
+#define M_AR4		0x1C70
+#define M_AR5		0x1C74
+#define M_AR6		0x1C78
+
+#define M_CXBNDRY	0x1C80
+#define M_FXBNDRY	0x1C84
+#define M_YDSTLEN	0x1C88
+#define M_PITCH		0x1C8C
+#define M_YDST		0x1C90
+#define M_YDSTORG	0x1C94
+#define M_YTOP		0x1C98
+#define M_YBOT		0x1C9C
+
+/* mystique only */
+#define M_CACHEFLUSH	0x1FFF
+
+#define M_EXEC		0x0100
+
+#define M_DWG_TRAP	0x04
+#define M_DWG_BITBLT	0x08
+#define M_DWG_ILOAD	0x09
+
+#define M_DWG_LINEAR	0x0080
+#define M_DWG_SOLID	0x0800
+#define M_DWG_ARZERO	0x1000
+#define M_DWG_SGNZERO	0x2000
+#define M_DWG_SHIFTZERO	0x4000
+
+#define M_DWG_REPLACE	0x000C0000
+#define M_DWG_REPLACE2	(M_DWG_REPLACE | 0x40)
+#define M_DWG_XOR	0x00060010
+
+#define M_DWG_BFCOL	0x04000000
+#define M_DWG_BMONOWF	0x08000000
+
+#define M_DWG_TRANSC	0x40000000
+
+#define M_FIFOSTATUS	0x1E10
+#define M_STATUS	0x1E14
+#define M_ICLEAR	0x1E18
+#define M_IEN		0x1E1C
+
+#define M_VCOUNT	0x1E20
+
+#define M_RESET		0x1E40
+#define M_MEMRDBK	0x1E44
+
+#define M_AGP2PLL	0x1E4C
+
+#define M_OPMODE	0x1E54
+#define     M_OPMODE_DMA_GEN_WRITE	0x00
+#define     M_OPMODE_DMA_BLIT		0x04
+#define     M_OPMODE_DMA_VECTOR_WRITE	0x08
+#define     M_OPMODE_DMA_LE		0x0000		/* little endian - no transformation */
+#define     M_OPMODE_DMA_BE_8BPP	0x0000
+#define     M_OPMODE_DMA_BE_16BPP	0x0100
+#define     M_OPMODE_DMA_BE_32BPP	0x0200
+#define     M_OPMODE_DIR_LE		0x000000	/* little endian - no transformation */
+#define     M_OPMODE_DIR_BE_8BPP	0x000000
+#define     M_OPMODE_DIR_BE_16BPP	0x010000
+#define     M_OPMODE_DIR_BE_32BPP	0x020000
+
+#define M_ATTR_INDEX	0x1FC0
+#define M_ATTR_DATA	0x1FC1
+
+#define M_MISC_REG	0x1FC2
+#define M_3C2_RD	0x1FC2
+
+#define M_SEQ_INDEX	0x1FC4
+#define M_SEQ_DATA	0x1FC5
+#define     M_SEQ1		0x01
+#define        M_SEQ1_SCROFF		0x20
+
+#define M_MISC_REG_READ	0x1FCC
+
+#define M_GRAPHICS_INDEX 0x1FCE
+#define M_GRAPHICS_DATA	0x1FCF
+
+#define M_CRTC_INDEX	0x1FD4
+
+#define M_ATTR_RESET	0x1FDA
+#define M_3DA_WR	0x1FDA
+#define M_INSTS1	0x1FDA
+
+#define M_EXTVGA_INDEX	0x1FDE
+#define M_EXTVGA_DATA	0x1FDF
+
+/* G200 only */
+#define M_SRCORG	0x2CB4
+#define M_DSTORG	0x2CB8
+
+#define M_RAMDAC_BASE	0x3C00
+
+/* fortunately, same on TVP3026 and MGA1064 */
+#define M_DAC_REG	(M_RAMDAC_BASE+0)
+#define M_DAC_VAL	(M_RAMDAC_BASE+1)
+#define M_PALETTE_MASK	(M_RAMDAC_BASE+2)
+
+#define M_X_INDEX	0x00
+#define M_X_DATAREG	0x0A
+
+#define DAC_XGENIOCTRL		0x2A
+#define DAC_XGENIODATA		0x2B
+
+#define M_C2CTL		0x3C10
+
+#define MX_OPTION_BSWAP         0x00000000
+
+#ifdef __LITTLE_ENDIAN
+#define M_OPMODE_4BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_8BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_16BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_24BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_32BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#else
+#ifdef __BIG_ENDIAN
+#define M_OPMODE_4BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE       | M_OPMODE_DMA_BLIT)	/* TODO */
+#define M_OPMODE_8BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP  | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_16BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_16BPP | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_24BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP  | M_OPMODE_DMA_BLIT)	/* TODO, ?32 */
+#define M_OPMODE_32BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_32BPP | M_OPMODE_DMA_BLIT)
+#else
+#error "Byte ordering have to be defined. Cannot continue."
+#endif
+#endif
+
+#define mga_inb(addr)		mga_readb(minfo->mmio.vbase, (addr))
+#define mga_inl(addr)		mga_readl(minfo->mmio.vbase, (addr))
+#define mga_outb(addr,val)	mga_writeb(minfo->mmio.vbase, (addr), (val))
+#define mga_outw(addr,val)	mga_writew(minfo->mmio.vbase, (addr), (val))
+#define mga_outl(addr,val)	mga_writel(minfo->mmio.vbase, (addr), (val))
+#define mga_readr(port,idx)	(mga_outb((port),(idx)), mga_inb((port)+1))
+#define mga_setr(addr,port,val)	mga_outw(addr, ((val)<<8) | (port))
+
+#define mga_fifo(n)	do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
+
+#define WaitTillIdle()	do {} while (mga_inl(M_STATUS) & 0x10000)
+
+/* code speedup */
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+#define isInterleave(x)	 (x->interleave)
+#define isMillenium(x)	 (x->millenium)
+#define isMilleniumII(x) (x->milleniumII)
+#else
+#define isInterleave(x)  (0)
+#define isMillenium(x)	 (0)
+#define isMilleniumII(x) (0)
+#endif
+
+#define matroxfb_DAC_lock()                   spin_lock(&minfo->lock.DAC)
+#define matroxfb_DAC_unlock()                 spin_unlock(&minfo->lock.DAC)
+#define matroxfb_DAC_lock_irqsave(flags)      spin_lock_irqsave(&minfo->lock.DAC, flags)
+#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&minfo->lock.DAC, flags)
+extern void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg,
+			     int val);
+extern int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg);
+extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
+extern int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc);
+extern int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable);
+
+#ifdef MATROXFB_USE_SPINLOCKS
+#define CRITBEGIN  spin_lock_irqsave(&minfo->lock.accel, critflags);
+#define CRITEND	   spin_unlock_irqrestore(&minfo->lock.accel, critflags);
+#define CRITFLAGS  unsigned long critflags;
+#else
+#define CRITBEGIN
+#define CRITEND
+#define CRITFLAGS
+#endif
+
+#endif	/* __MATROXFB_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_crtc2.c b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
new file mode 100644
index 000000000000..02796a4317a9
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
@@ -0,0 +1,739 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ */
+
+#include "matroxfb_maven.h"
+#include "matroxfb_crtc2.h"
+#include "matroxfb_misc.h"
+#include "matroxfb_DAC1064.h"
+#include <linux/matroxfb.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+/* **************************************************** */
+
+static int mem = 8192;
+
+module_param(mem, int, 0);
+MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)");
+
+/* **************************************************** */
+
+static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,
+		unsigned blue, unsigned transp, struct fb_info* info) {
+	u_int32_t col;
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+
+	if (regno >= 16)
+		return 1;
+	if (m2info->fbcon.var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+	red = CNVT_TOHW(red, m2info->fbcon.var.red.length);
+	green = CNVT_TOHW(green, m2info->fbcon.var.green.length);
+	blue = CNVT_TOHW(blue, m2info->fbcon.var.blue.length);
+	transp = CNVT_TOHW(transp, m2info->fbcon.var.transp.length);
+
+	col = (red << m2info->fbcon.var.red.offset)     |
+	      (green << m2info->fbcon.var.green.offset) |
+	      (blue << m2info->fbcon.var.blue.offset)   |
+	      (transp << m2info->fbcon.var.transp.offset);
+
+	switch (m2info->fbcon.var.bits_per_pixel) {
+		case 16:
+			m2info->cmap[regno] = col | (col << 16);
+			break;
+		case 32:
+			m2info->cmap[regno] = col;
+			break;
+	}
+	return 0;
+#undef m2info
+}
+
+static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
+		struct my_timming* mt,
+		int mode,
+		unsigned int pos) {
+	u_int32_t tmp;
+	u_int32_t datactl;
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	switch (mode) {
+		case 15:
+			tmp = 0x00200000;
+			break;
+		case 16:
+			tmp = 0x00400000;
+			break;
+/*		case 32: */
+		default:
+			tmp = 0x00800000;
+			break;
+	}
+	tmp |= 0x00000001;	/* enable CRTC2 */
+	datactl = 0;
+	if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
+		if (minfo->devflags.g450dac) {
+			tmp |= 0x00000006; /* source from secondary pixel PLL */
+			/* no vidrst when in monitor mode */
+			if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
+				tmp |=  0xC0001000; /* Enable H/V vidrst */
+			}
+		} else {
+			tmp |= 0x00000002; /* source from VDOCLK */
+			tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
+			/* MGA TVO is our clock source */
+		}
+	} else if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
+		tmp |= 0x00000004; /* source from pixclock */
+		/* PIXPLL is our clock source */
+	}
+	if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
+		tmp |= 0x00100000;	/* connect CRTC2 to DAC */
+	}
+	if (mt->interlaced) {
+		tmp |= 0x02000000;	/* interlaced, second field is bigger, as G450 apparently ignores it */
+		mt->VDisplay >>= 1;
+		mt->VSyncStart >>= 1;
+		mt->VSyncEnd >>= 1;
+		mt->VTotal >>= 1;
+	}
+	if ((mt->HTotal & 7) == 2) {
+		datactl |= 0x00000010;
+		mt->HTotal &= ~7;
+	}
+	tmp |= 0x10000000;	/* 0x10000000 is VIDRST polarity */
+	mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8));
+	mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8));
+	mga_outl(0x3C1C, ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1));
+	mga_outl(0x3C20, ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1));
+	mga_outl(0x3C24, ((mt->VSyncStart) << 16) | (mt->HSyncStart));	/* preload */
+	{
+		u_int32_t linelen = m2info->fbcon.var.xres_virtual * (m2info->fbcon.var.bits_per_pixel >> 3);
+		if (tmp & 0x02000000) {
+			/* field #0 is smaller, so... */
+			mga_outl(0x3C2C, pos);			/* field #1 vmemory start */
+			mga_outl(0x3C28, pos + linelen);	/* field #0 vmemory start */
+			linelen <<= 1;
+			m2info->interlaced = 1;
+		} else {
+			mga_outl(0x3C28, pos);		/* vmemory start */
+			m2info->interlaced = 0;
+		}
+		mga_outl(0x3C40, linelen);
+	}
+	mga_outl(0x3C4C, datactl);	/* data control */
+	if (tmp & 0x02000000) {
+		int i;
+
+		mga_outl(0x3C10, tmp & ~0x02000000);
+		for (i = 0; i < 2; i++) {
+			unsigned int nl;
+			unsigned int lastl = 0;
+
+			while ((nl = mga_inl(0x3C48) & 0xFFF) >= lastl) {
+				lastl = nl;
+			}
+		}
+	}
+	mga_outl(0x3C10, tmp);
+	minfo->hw.crtc2.ctl = tmp;
+
+	tmp = mt->VDisplay << 16;	/* line compare */
+	if (mt->sync & FB_SYNC_HOR_HIGH_ACT)
+		tmp |= 0x00000100;
+	if (mt->sync & FB_SYNC_VERT_HIGH_ACT)
+		tmp |= 0x00000200;
+	mga_outl(0x3C44, tmp);
+}
+
+static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	mga_outl(0x3C10, 0x00000004);	/* disable CRTC2, CRTC1->DAC1, PLL as clock source */
+	minfo->hw.crtc2.ctl = 0x00000004;
+}
+
+static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
+		struct fb_var_screeninfo* var) {
+	unsigned int pos;
+	unsigned int linelen;
+	unsigned int pixelsize;
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	m2info->fbcon.var.xoffset = var->xoffset;
+	m2info->fbcon.var.yoffset = var->yoffset;
+	pixelsize = m2info->fbcon.var.bits_per_pixel >> 3;
+	linelen = m2info->fbcon.var.xres_virtual * pixelsize;
+	pos = m2info->fbcon.var.yoffset * linelen + m2info->fbcon.var.xoffset * pixelsize;
+	pos += m2info->video.offbase;
+	if (m2info->interlaced) {
+		mga_outl(0x3C2C, pos);
+		mga_outl(0x3C28, pos + linelen);
+	} else {
+		mga_outl(0x3C28, pos);
+	}
+}
+
+static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info,
+		struct fb_var_screeninfo* var,
+		int *visual,
+		int *video_cmap_len,
+		int *mode) {
+	unsigned int mask;
+	unsigned int memlen;
+	unsigned int vramlen;
+
+	switch (var->bits_per_pixel) {
+		case 16:	mask = 0x1F;
+				break;
+		case 32:	mask = 0x0F;
+				break;
+		default:	return -EINVAL;
+	}
+	vramlen = m2info->video.len_usable;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	var->xres_virtual = (var->xres_virtual + mask) & ~mask;
+	if (var->yres_virtual > 32767)
+		return -EINVAL;
+	memlen = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel >> 3);
+	if (memlen > vramlen)
+		return -EINVAL;
+	if (var->xoffset + var->xres > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	var->xres &= ~7;
+	var->left_margin &= ~7;
+	var->right_margin &= ~7;
+	var->hsync_len &= ~7;
+
+	*mode = var->bits_per_pixel;
+	if (var->bits_per_pixel == 16) {
+		if (var->green.length == 5) {
+			var->red.offset = 10;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+			*mode = 15;
+		} else {
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+	} else {
+			var->red.offset = 16;
+			var->red.length = 8;
+			var->green.offset = 8;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 24;
+			var->transp.length = 8;
+	}
+	*visual = FB_VISUAL_TRUECOLOR;
+	*video_cmap_len = 16;
+	return 0;
+}
+
+static int matroxfb_dh_open(struct fb_info* info, int user) {
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	if (minfo) {
+		int err;
+
+		if (minfo->dead) {
+			return -ENXIO;
+		}
+		err = minfo->fbops.fb_open(&minfo->fbcon, user);
+		if (err) {
+			return err;
+		}
+	}
+	return 0;
+#undef m2info
+}
+
+static int matroxfb_dh_release(struct fb_info* info, int user) {
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+	int err = 0;
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	if (minfo) {
+		err = minfo->fbops.fb_release(&minfo->fbcon, user);
+	}
+	return err;
+#undef m2info
+}
+
+/*
+ * This function is called before the register_framebuffer so
+ * no locking is needed.
+ */
+static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info)
+{
+	struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;
+
+	strcpy(fix->id, "MATROX DH");
+
+	fix->smem_start = m2info->video.base;
+	fix->smem_len = m2info->video.len_usable;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->xpanstep = 8;	/* TBD */
+	fix->mmio_start = m2info->mmio.base;
+	fix->mmio_len = m2info->mmio.len;
+	fix->accel = 0;		/* no accel... */
+}
+
+static int matroxfb_dh_check_var(struct fb_var_screeninfo* var, struct fb_info* info) {
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+	int visual;
+	int cmap_len;
+	int mode;
+
+	return matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode);
+#undef m2info
+}
+
+static int matroxfb_dh_set_par(struct fb_info* info) {
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+	int visual;
+	int cmap_len;
+	int mode;
+	int err;
+	struct fb_var_screeninfo* var = &info->var;
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0)
+		return err;
+	/* cmap */
+	{
+		m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase);
+		m2info->fbcon.fix.visual = visual;
+		m2info->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
+		m2info->fbcon.fix.type_aux = 0;
+		m2info->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+	}
+	{
+		struct my_timming mt;
+		unsigned int pos;
+		int out;
+		int cnt;
+
+		matroxfb_var2my(&m2info->fbcon.var, &mt);
+		mt.crtc = MATROXFB_SRC_CRTC2;
+		/* CRTC2 delay */
+		mt.delay = 34;
+
+		pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3;
+		pos += m2info->video.offbase;
+		cnt = 0;
+		down_read(&minfo->altout.lock);
+		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+			if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
+				cnt++;
+				if (minfo->outputs[out].output->compute) {
+					minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
+				}
+			}
+		}
+		minfo->crtc2.pixclock = mt.pixclock;
+		minfo->crtc2.mnp = mt.mnp;
+		up_read(&minfo->altout.lock);
+		if (cnt) {
+			matroxfb_dh_restore(m2info, &mt, mode, pos);
+		} else {
+			matroxfb_dh_disable(m2info);
+		}
+		DAC1064_global_init(minfo);
+		DAC1064_global_restore(minfo);
+		down_read(&minfo->altout.lock);
+		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+			if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
+			    minfo->outputs[out].output->program) {
+				minfo->outputs[out].output->program(minfo->outputs[out].data);
+			}
+		}
+		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+			if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
+			    minfo->outputs[out].output->start) {
+				minfo->outputs[out].output->start(minfo->outputs[out].data);
+			}
+		}
+		up_read(&minfo->altout.lock);
+	}
+	m2info->initialized = 1;
+	return 0;
+#undef m2info
+}
+
+static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, struct fb_info* info) {
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+	matroxfb_dh_pan_var(m2info, var);
+	return 0;
+#undef m2info
+}
+
+static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	matroxfb_enable_irq(minfo, 0);
+	memset(vblank, 0, sizeof(*vblank));
+	vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
+	/* mask out reserved bits + field number (odd/even) */
+	vblank->vcount = mga_inl(0x3C48) & 0x000007FF;
+	/* compatibility stuff */
+	if (vblank->vcount >= m2info->fbcon.var.yres)
+		vblank->flags |= FB_VBLANK_VBLANKING;
+	if (test_bit(0, &minfo->irq_flags)) {
+                vblank->flags |= FB_VBLANK_HAVE_COUNT;
+                /* Only one writer, aligned int value...
+                   it should work without lock and without atomic_t */
+		vblank->count = minfo->crtc2.vsync.cnt;
+        }
+	return 0;
+}
+
+static int matroxfb_dh_ioctl(struct fb_info *info,
+		unsigned int cmd,
+		unsigned long arg)
+{
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+	struct matrox_fb_info *minfo = m2info->primary_dev;
+
+	DBG(__func__)
+
+	switch (cmd) {
+		case FBIOGET_VBLANK:
+			{
+				struct fb_vblank vblank;
+				int err;
+
+				err = matroxfb_dh_get_vblank(m2info, &vblank);
+				if (err)
+					return err;
+				if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
+					return -EFAULT;
+				return 0;
+			}
+		case FBIO_WAITFORVSYNC:
+			{
+				u_int32_t crt;
+
+				if (get_user(crt, (u_int32_t __user *)arg))
+					return -EFAULT;
+
+				if (crt != 0)
+					return -ENODEV;
+				return matroxfb_wait_for_sync(minfo, 1);
+			}
+		case MATROXFB_SET_OUTPUT_MODE:
+		case MATROXFB_GET_OUTPUT_MODE:
+		case MATROXFB_GET_ALL_OUTPUTS:
+			{
+				return minfo->fbcon.fbops->fb_ioctl(&minfo->fbcon, cmd, arg);
+			}
+		case MATROXFB_SET_OUTPUT_CONNECTION:
+			{
+				u_int32_t tmp;
+				int out;
+				int changes;
+
+				if (get_user(tmp, (u_int32_t __user *)arg))
+					return -EFAULT;
+				for (out = 0; out < 32; out++) {
+					if (tmp & (1 << out)) {
+						if (out >= MATROXFB_MAX_OUTPUTS)
+							return -ENXIO;
+						if (!minfo->outputs[out].output)
+							return -ENXIO;
+						switch (minfo->outputs[out].src) {
+							case MATROXFB_SRC_NONE:
+							case MATROXFB_SRC_CRTC2:
+								break;
+							default:
+								return -EBUSY;
+						}
+					}
+				}
+				if (minfo->devflags.panellink) {
+					if (tmp & MATROXFB_OUTPUT_CONN_DFP)
+						return -EINVAL;
+					if ((minfo->outputs[2].src == MATROXFB_SRC_CRTC1) && tmp)
+						return -EBUSY;
+				}
+				changes = 0;
+				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+					if (tmp & (1 << out)) {
+						if (minfo->outputs[out].src != MATROXFB_SRC_CRTC2) {
+							changes = 1;
+							minfo->outputs[out].src = MATROXFB_SRC_CRTC2;
+						}
+					} else if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
+						changes = 1;
+						minfo->outputs[out].src = MATROXFB_SRC_NONE;
+					}
+				}
+				if (!changes)
+					return 0;
+				matroxfb_dh_set_par(info);
+				return 0;
+			}
+		case MATROXFB_GET_OUTPUT_CONNECTION:
+			{
+				u_int32_t conn = 0;
+				int out;
+
+				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+					if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
+						conn |= 1 << out;
+					}
+				}
+				if (put_user(conn, (u_int32_t __user *)arg))
+					return -EFAULT;
+				return 0;
+			}
+		case MATROXFB_GET_AVAILABLE_OUTPUTS:
+			{
+				u_int32_t tmp = 0;
+				int out;
+
+				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+					if (minfo->outputs[out].output) {
+						switch (minfo->outputs[out].src) {
+							case MATROXFB_SRC_NONE:
+							case MATROXFB_SRC_CRTC2:
+								tmp |= 1 << out;
+								break;
+						}
+					}
+				}
+				if (minfo->devflags.panellink) {
+					tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
+					if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1) {
+						tmp = 0;
+					}
+				}
+				if (put_user(tmp, (u_int32_t __user *)arg))
+					return -EFAULT;
+				return 0;
+			}
+	}
+	return -ENOTTY;
+#undef m2info
+}
+
+static int matroxfb_dh_blank(int blank, struct fb_info* info) {
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
+	switch (blank) {
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		default:;
+	}
+	/* do something... */
+	return 0;
+#undef m2info
+}
+
+static struct fb_ops matroxfb_dh_ops = {
+	.owner =	THIS_MODULE,
+	.fb_open =	matroxfb_dh_open,
+	.fb_release =	matroxfb_dh_release,
+	.fb_check_var =	matroxfb_dh_check_var,
+	.fb_set_par =	matroxfb_dh_set_par,
+	.fb_setcolreg =	matroxfb_dh_setcolreg,
+	.fb_pan_display =matroxfb_dh_pan_display,
+	.fb_blank =	matroxfb_dh_blank,
+	.fb_ioctl =	matroxfb_dh_ioctl,
+	.fb_fillrect =	cfb_fillrect,
+	.fb_copyarea =	cfb_copyarea,
+	.fb_imageblit =	cfb_imageblit,
+};
+
+static struct fb_var_screeninfo matroxfb_dh_defined = {
+		640,480,640,480,/* W,H, virtual W,H */
+		0,0,		/* offset */
+		32,		/* depth */
+		0,		/* gray */
+		{0,0,0},	/* R */
+		{0,0,0},	/* G */
+		{0,0,0},	/* B */
+		{0,0,0},	/* alpha */
+		0,		/* nonstd */
+		FB_ACTIVATE_NOW,
+		-1,-1,		/* display size */
+		0,		/* accel flags */
+		39721L,48L,16L,33L,10L,
+		96L,2,0,	/* no sync info */
+		FB_VMODE_NONINTERLACED,
+};
+
+static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
+			     struct matroxfb_dh_fb_info *m2info)
+{
+#define minfo (m2info->primary_dev)
+	void* oldcrtc2;
+
+	m2info->fbcon.fbops = &matroxfb_dh_ops;
+	m2info->fbcon.flags = FBINFO_FLAG_DEFAULT;
+	m2info->fbcon.flags |= FBINFO_HWACCEL_XPAN |
+			       FBINFO_HWACCEL_YPAN;
+	m2info->fbcon.pseudo_palette = m2info->cmap;
+	fb_alloc_cmap(&m2info->fbcon.cmap, 256, 1);
+
+	if (mem < 64)
+		mem *= 1024;
+	if (mem < 64*1024)
+		mem *= 1024;
+	mem &= ~0x00000FFF;	/* PAGE_MASK? */
+	if (minfo->video.len_usable + mem <= minfo->video.len)
+		m2info->video.offbase = minfo->video.len - mem;
+	else if (minfo->video.len < mem) {
+		return -ENOMEM;
+	} else { /* check yres on first head... */
+		m2info->video.borrowed = mem;
+		minfo->video.len_usable -= mem;
+		m2info->video.offbase = minfo->video.len_usable;
+	}
+	m2info->video.base = minfo->video.base + m2info->video.offbase;
+	m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;
+	m2info->video.vbase.vaddr = vaddr_va(minfo->video.vbase) + m2info->video.offbase;
+	m2info->mmio.base = minfo->mmio.base;
+	m2info->mmio.vbase = minfo->mmio.vbase;
+	m2info->mmio.len = minfo->mmio.len;
+
+	matroxfb_dh_init_fix(m2info);
+	if (register_framebuffer(&m2info->fbcon)) {
+		return -ENXIO;
+	}
+	if (!m2info->initialized)
+		fb_set_var(&m2info->fbcon, &matroxfb_dh_defined);
+	down_write(&minfo->crtc2.lock);
+	oldcrtc2 = minfo->crtc2.info;
+	minfo->crtc2.info = m2info;
+	up_write(&minfo->crtc2.lock);
+	if (oldcrtc2) {
+		printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
+			oldcrtc2);
+	}
+	return 0;
+#undef minfo
+}
+
+/* ************************** */
+
+static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) {
+#define minfo (m2info->primary_dev)
+	if (matroxfb_dh_regit(minfo, m2info)) {
+		printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n");
+		return -1;
+	}
+	printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n",
+		minfo->fbcon.node, m2info->fbcon.node);
+	m2info->fbcon_registered = 1;
+	return 0;
+#undef minfo
+}
+
+static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
+#define minfo (m2info->primary_dev)
+	if (m2info->fbcon_registered) {
+		int id;
+		struct matroxfb_dh_fb_info* crtc2;
+
+		down_write(&minfo->crtc2.lock);
+		crtc2 = minfo->crtc2.info;
+		if (crtc2 == m2info)
+			minfo->crtc2.info = NULL;
+		up_write(&minfo->crtc2.lock);
+		if (crtc2 != m2info) {
+			printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
+				crtc2, m2info);
+			printk(KERN_ERR "matroxfb_crtc2: Expect kernel crash after module unload.\n");
+			return;
+		}
+		id = m2info->fbcon.node;
+		unregister_framebuffer(&m2info->fbcon);
+		/* return memory back to primary head */
+		minfo->video.len_usable += m2info->video.borrowed;
+		printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id);
+		m2info->fbcon_registered = 0;
+	}
+#undef minfo
+}
+
+static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
+	struct matroxfb_dh_fb_info* m2info;
+
+	/* hardware is CRTC2 incapable... */
+	if (!minfo->devflags.crtc2)
+		return NULL;
+	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
+	if (!m2info) {
+		printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
+		return NULL;
+	}
+	m2info->primary_dev = minfo;
+	if (matroxfb_dh_registerfb(m2info)) {
+		kfree(m2info);
+		printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");
+		return NULL;
+	}
+	return m2info;
+}
+
+static void matroxfb_crtc2_remove(struct matrox_fb_info* minfo, void* crtc2) {
+	matroxfb_dh_deregisterfb(crtc2);
+	kfree(crtc2);
+}
+
+static struct matroxfb_driver crtc2 = {
+		.name =		"Matrox G400 CRTC2",
+		.probe =	matroxfb_crtc2_probe,
+		.remove =	matroxfb_crtc2_remove };
+
+static int matroxfb_crtc2_init(void) {
+	if (fb_get_options("matrox_crtc2fb", NULL))
+		return -ENODEV;
+
+	matroxfb_register_driver(&crtc2);
+	return 0;
+}
+
+static void matroxfb_crtc2_exit(void) {
+	matroxfb_unregister_driver(&crtc2);
+}
+
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Matrox G400 CRTC2 driver");
+MODULE_LICENSE("GPL");
+module_init(matroxfb_crtc2_init);
+module_exit(matroxfb_crtc2_exit);
+/* we do not have __setup() yet */
diff --git a/drivers/video/fbdev/matrox/matroxfb_crtc2.h b/drivers/video/fbdev/matrox/matroxfb_crtc2.h
new file mode 100644
index 000000000000..1005582e843e
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_crtc2.h
@@ -0,0 +1,34 @@
+#ifndef __MATROXFB_CRTC2_H__
+#define __MATROXFB_CRTC2_H__
+
+#include <linux/ioctl.h>
+#include "matroxfb_base.h"
+
+struct matroxfb_dh_fb_info {
+	struct fb_info		fbcon;
+	int			fbcon_registered;
+	int                     initialized;
+
+	struct matrox_fb_info*	primary_dev;
+
+	struct {
+		unsigned long	base;	/* physical */
+		vaddr_t		vbase;	/* virtual */
+		unsigned int	len;
+		unsigned int	len_usable;
+		unsigned int	len_maximum;
+		unsigned int 	offbase;
+		unsigned int	borrowed;
+			      } video;
+	struct {
+		unsigned long	base;
+		vaddr_t		vbase;
+		unsigned int	len;
+			      } mmio;
+
+	unsigned int		interlaced:1;
+
+	u_int32_t cmap[16];
+};
+
+#endif /* __MATROXFB_CRTC2_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_g450.c b/drivers/video/fbdev/matrox/matroxfb_g450.c
new file mode 100644
index 000000000000..cff0546ea6fd
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_g450.c
@@ -0,0 +1,640 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * See matroxfb_base.c for contributors.
+ *
+ */
+
+#include "matroxfb_base.h"
+#include "matroxfb_misc.h"
+#include "matroxfb_DAC1064.h"
+#include "g450_pll.h"
+#include <linux/matroxfb.h>
+#include <asm/div64.h>
+
+#include "matroxfb_g450.h"
+
+/* Definition of the various controls */
+struct mctl {
+	struct v4l2_queryctrl desc;
+	size_t control;
+};
+
+#define BLMIN	0xF3
+#define WLMAX	0x3FF
+
+static const struct mctl g450_controls[] =
+{	{ { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, 
+	  "brightness",
+	  0, WLMAX-BLMIN, 1, 370-BLMIN, 
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
+	{ { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, 
+	  "contrast",
+	  0, 1023, 1, 127, 
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
+	{ { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
+	  "saturation",
+	  0, 255, 1, 165, 
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
+	{ { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
+	  "hue",
+	  0, 255, 1, 0, 
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
+	{ { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
+	  "test output",
+	  0, 1, 1, 0, 
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
+};
+
+#define G450CTRLS ARRAY_SIZE(g450_controls)
+
+/* Return: positive number: id found
+           -EINVAL:         id not found, return failure
+	   -ENOENT:         id not found, create fake disabled control */
+static int get_ctrl_id(__u32 v4l2_id) {
+	int i;
+
+	for (i = 0; i < G450CTRLS; i++) {
+		if (v4l2_id < g450_controls[i].desc.id) {
+			if (g450_controls[i].desc.id == 0x08000000) {
+				return -EINVAL;
+			}
+			return -ENOENT;
+		}
+		if (v4l2_id == g450_controls[i].desc.id) {
+			return i;
+		}
+	}
+	return -EINVAL;
+}
+
+static inline int *get_ctrl_ptr(struct matrox_fb_info *minfo, unsigned int idx)
+{
+	return (int*)((char*)minfo + g450_controls[idx].control);
+}
+
+static void tvo_fill_defaults(struct matrox_fb_info *minfo)
+{
+	unsigned int i;
+	
+	for (i = 0; i < G450CTRLS; i++) {
+		*get_ctrl_ptr(minfo, i) = g450_controls[i].desc.default_value;
+	}
+}
+
+static int cve2_get_reg(struct matrox_fb_info *minfo, int reg)
+{
+	unsigned long flags;
+	int val;
+	
+	matroxfb_DAC_lock_irqsave(flags);
+	matroxfb_DAC_out(minfo, 0x87, reg);
+	val = matroxfb_DAC_in(minfo, 0x88);
+	matroxfb_DAC_unlock_irqrestore(flags);
+	return val;
+}
+
+static void cve2_set_reg(struct matrox_fb_info *minfo, int reg, int val)
+{
+	unsigned long flags;
+
+	matroxfb_DAC_lock_irqsave(flags);
+	matroxfb_DAC_out(minfo, 0x87, reg);
+	matroxfb_DAC_out(minfo, 0x88, val);
+	matroxfb_DAC_unlock_irqrestore(flags);
+}
+
+static void cve2_set_reg10(struct matrox_fb_info *minfo, int reg, int val)
+{
+	unsigned long flags;
+
+	matroxfb_DAC_lock_irqsave(flags);
+	matroxfb_DAC_out(minfo, 0x87, reg);
+	matroxfb_DAC_out(minfo, 0x88, val >> 2);
+	matroxfb_DAC_out(minfo, 0x87, reg + 1);
+	matroxfb_DAC_out(minfo, 0x88, val & 3);
+	matroxfb_DAC_unlock_irqrestore(flags);
+}
+
+static void g450_compute_bwlevel(const struct matrox_fb_info *minfo, int *bl,
+				 int *wl)
+{
+	const int b = minfo->altout.tvo_params.brightness + BLMIN;
+	const int c = minfo->altout.tvo_params.contrast;
+
+	*bl = max(b - c, BLMIN);
+	*wl = min(b + c, WLMAX);
+}
+
+static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) {
+	int i;
+	
+	i = get_ctrl_id(p->id);
+	if (i >= 0) {
+		*p = g450_controls[i].desc;
+		return 0;
+	}
+	if (i == -ENOENT) {
+		static const struct v4l2_queryctrl disctrl = 
+			{ .flags = V4L2_CTRL_FLAG_DISABLED };
+			
+		i = p->id;
+		*p = disctrl;
+		p->id = i;
+		sprintf(p->name, "Ctrl #%08X", i);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int g450_set_ctrl(void* md, struct v4l2_control *p) {
+	int i;
+	struct matrox_fb_info *minfo = md;
+	
+	i = get_ctrl_id(p->id);
+	if (i < 0) return -EINVAL;
+
+	/*
+	 * Check if changed.
+	 */
+	if (p->value == *get_ctrl_ptr(minfo, i)) return 0;
+
+	/*
+	 * Check limits.
+	 */
+	if (p->value > g450_controls[i].desc.maximum) return -EINVAL;
+	if (p->value < g450_controls[i].desc.minimum) return -EINVAL;
+
+	/*
+	 * Store new value.
+	 */
+	*get_ctrl_ptr(minfo, i) = p->value;
+
+	switch (p->id) {
+		case V4L2_CID_BRIGHTNESS:
+		case V4L2_CID_CONTRAST:
+			{
+				int blacklevel, whitelevel;
+				g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
+				cve2_set_reg10(minfo, 0x0e, blacklevel);
+				cve2_set_reg10(minfo, 0x1e, whitelevel);
+			}
+			break;
+		case V4L2_CID_SATURATION:
+			cve2_set_reg(minfo, 0x20, p->value);
+			cve2_set_reg(minfo, 0x22, p->value);
+			break;
+		case V4L2_CID_HUE:
+			cve2_set_reg(minfo, 0x25, p->value);
+			break;
+		case MATROXFB_CID_TESTOUT:
+			{
+				unsigned char val = cve2_get_reg(minfo, 0x05);
+				if (p->value) val |=  0x02;
+				else          val &= ~0x02;
+				cve2_set_reg(minfo, 0x05, val);
+			}
+			break;
+	}
+	
+
+	return 0;
+}
+
+static int g450_get_ctrl(void* md, struct v4l2_control *p) {
+	int i;
+	struct matrox_fb_info *minfo = md;
+	
+	i = get_ctrl_id(p->id);
+	if (i < 0) return -EINVAL;
+	p->value = *get_ctrl_ptr(minfo, i);
+	return 0;
+}
+
+struct output_desc {
+	unsigned int	h_vis;
+	unsigned int	h_f_porch;
+	unsigned int	h_sync;
+	unsigned int	h_b_porch;
+	unsigned long long int	chromasc;
+	unsigned int	burst;
+	unsigned int	v_total;
+};
+
+static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r,
+			struct my_timming *mt, const struct output_desc *outd)
+{
+	u_int32_t chromasc;
+	u_int32_t hlen;
+	u_int32_t hsl;
+	u_int32_t hbp;
+	u_int32_t hfp;
+	u_int32_t hvis;
+	unsigned int pixclock;
+	unsigned long long piic;
+	int mnp;
+	int over;
+	
+	r->regs[0x80] = 0x03;	/* | 0x40 for SCART */
+
+	hvis = ((mt->HDisplay << 1) + 3) & ~3;
+	
+	if (hvis >= 2048) {
+		hvis = 2044;
+	}
+	
+	piic = 1000000000ULL * hvis;
+	do_div(piic, outd->h_vis);
+
+	dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic);
+	
+	mnp = matroxfb_g450_setclk(minfo, piic, M_VIDEO_PLL);
+	
+	mt->mnp = mnp;
+	mt->pixclock = g450_mnp2f(minfo, mnp);
+
+	dprintk(KERN_DEBUG "MNP=%08X\n", mnp);
+
+	pixclock = 1000000000U / mt->pixclock;
+
+	dprintk(KERN_DEBUG "Got %u ps pixclock\n", pixclock);
+
+	piic = outd->chromasc;
+	do_div(piic, mt->pixclock);
+	chromasc = piic;
+	
+	dprintk(KERN_DEBUG "Chroma is %08X\n", chromasc);
+
+	r->regs[0] = piic >> 24;
+	r->regs[1] = piic >> 16;
+	r->regs[2] = piic >>  8;
+	r->regs[3] = piic >>  0;
+	hbp = (((outd->h_b_porch + pixclock) / pixclock)) & ~1;
+	hfp = (((outd->h_f_porch + pixclock) / pixclock)) & ~1;
+	hsl = (((outd->h_sync + pixclock) / pixclock)) & ~1;
+	hlen = hvis + hfp + hsl + hbp;
+	over = hlen & 0x0F;
+	
+	dprintk(KERN_DEBUG "WL: vis=%u, hf=%u, hs=%u, hb=%u, total=%u\n", hvis, hfp, hsl, hbp, hlen);
+
+	if (over) {
+		hfp -= over;
+		hlen -= over;
+		if (over <= 2) {
+		} else if (over < 10) {
+			hfp += 4;
+			hlen += 4;
+		} else {
+			hfp += 16;
+			hlen += 16;
+		}
+	}
+
+	/* maybe cve2 has requirement 800 < hlen < 1184 */
+	r->regs[0x08] = hsl;
+	r->regs[0x09] = (outd->burst + pixclock - 1) / pixclock;	/* burst length */
+	r->regs[0x0A] = hbp;
+	r->regs[0x2C] = hfp;
+	r->regs[0x31] = hvis / 8;
+	r->regs[0x32] = hvis & 7;
+	
+	dprintk(KERN_DEBUG "PG: vis=%04X, hf=%02X, hs=%02X, hb=%02X, total=%04X\n", hvis, hfp, hsl, hbp, hlen);
+
+	r->regs[0x84] = 1;	/* x sync point */
+	r->regs[0x85] = 0;
+	hvis = hvis >> 1;
+	hlen = hlen >> 1;
+	
+	dprintk(KERN_DEBUG "hlen=%u hvis=%u\n", hlen, hvis);
+
+	mt->interlaced = 1;
+
+	mt->HDisplay = hvis & ~7;
+	mt->HSyncStart = mt->HDisplay + 8;
+	mt->HSyncEnd = (hlen & ~7) - 8;
+	mt->HTotal = hlen;
+
+	{
+		int upper;
+		unsigned int vtotal;
+		unsigned int vsyncend;
+		unsigned int vdisplay;
+		
+		vtotal = mt->VTotal;
+		vsyncend = mt->VSyncEnd;
+		vdisplay = mt->VDisplay;
+		if (vtotal < outd->v_total) {
+			unsigned int yovr = outd->v_total - vtotal;
+			
+			vsyncend += yovr >> 1;
+		} else if (vtotal > outd->v_total) {
+			vdisplay = outd->v_total - 4;
+			vsyncend = outd->v_total;
+		}
+		upper = (outd->v_total - vsyncend) >> 1;	/* in field lines */
+		r->regs[0x17] = outd->v_total / 4;
+		r->regs[0x18] = outd->v_total & 3;
+		r->regs[0x33] = upper - 1;	/* upper blanking */
+		r->regs[0x82] = upper;		/* y sync point */
+		r->regs[0x83] = upper >> 8;
+		
+		mt->VDisplay = vdisplay;
+		mt->VSyncStart = outd->v_total - 2;
+		mt->VSyncEnd = outd->v_total;
+		mt->VTotal = outd->v_total;
+	}
+}
+
+static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct output_desc** outd) {
+	static const struct output_desc paloutd = {
+		.h_vis	   = 52148148,	// ps
+		.h_f_porch =  1407407,	// ps
+		.h_sync    =  4666667,	// ps
+		.h_b_porch =  5777778,	// ps
+		.chromasc  = 19042247534182ULL,	// 4433618.750 Hz
+		.burst     =  2518518,	// ps
+		.v_total   =      625,
+	};
+	static const struct output_desc ntscoutd = {
+		.h_vis     = 52888889,	// ps
+		.h_f_porch =  1333333,	// ps
+		.h_sync    =  4666667,	// ps
+		.h_b_porch =  4666667,	// ps
+		.chromasc  = 15374030659475ULL,	// 3579545.454 Hz
+		.burst     =  2418418,	// ps
+		.v_total   =      525,	// lines
+	};
+
+	static const struct mavenregs palregs = { {
+		0x2A, 0x09, 0x8A, 0xCB,	/* 00: chroma subcarrier */
+		0x00,
+		0x00,	/* test */
+		0xF9,	/* modified by code (F9 written...) */
+		0x00,	/* ? not written */
+		0x7E,	/* 08 */
+		0x44,	/* 09 */
+		0x9C,	/* 0A */
+		0x2E,	/* 0B */
+		0x21,	/* 0C */
+		0x00,	/* ? not written */
+//		0x3F, 0x03, /* 0E-0F */
+		0x3C, 0x03,
+		0x3C, 0x03, /* 10-11 */
+		0x1A,	/* 12 */
+		0x2A,	/* 13 */
+		0x1C, 0x3D, 0x14, /* 14-16 */
+		0x9C, 0x01, /* 17-18 */
+		0x00,	/* 19 */
+		0xFE,	/* 1A */
+		0x7E,	/* 1B */
+		0x60,	/* 1C */
+		0x05,	/* 1D */
+//		0x89, 0x03, /* 1E-1F */
+		0xAD, 0x03,
+//		0x72,	/* 20 */
+		0xA5,
+		0x07,	/* 21 */
+//		0x72,	/* 22 */
+		0xA5,
+		0x00,	/* 23 */
+		0x00,	/* 24 */
+		0x00,	/* 25 */
+		0x08,	/* 26 */
+		0x04,	/* 27 */
+		0x00,	/* 28 */
+		0x1A,	/* 29 */
+		0x55, 0x01, /* 2A-2B */
+		0x26,	/* 2C */
+		0x07, 0x7E, /* 2D-2E */
+		0x02, 0x54, /* 2F-30 */
+		0xB0, 0x00, /* 31-32 */
+		0x14,	/* 33 */
+		0x49,	/* 34 */
+		0x00,	/* 35 written multiple times */
+		0x00,	/* 36 not written */
+		0xA3,	/* 37 */
+		0xC8,	/* 38 */
+		0x22,	/* 39 */
+		0x02,	/* 3A */
+		0x22,	/* 3B */
+		0x3F, 0x03, /* 3C-3D */
+		0x00,	/* 3E written multiple times */
+		0x00,	/* 3F not written */
+	} };
+	static struct mavenregs ntscregs = { {
+		0x21, 0xF0, 0x7C, 0x1F,	/* 00: chroma subcarrier */
+		0x00,
+		0x00,	/* test */
+		0xF9,	/* modified by code (F9 written...) */
+		0x00,	/* ? not written */
+		0x7E,	/* 08 */
+		0x43,	/* 09 */
+		0x7E,	/* 0A */
+		0x3D,	/* 0B */
+		0x00,	/* 0C */
+		0x00,	/* ? not written */
+		0x41, 0x00, /* 0E-0F */
+		0x3C, 0x00, /* 10-11 */
+		0x17,	/* 12 */
+		0x21,	/* 13 */
+		0x1B, 0x1B, 0x24, /* 14-16 */
+		0x83, 0x01, /* 17-18 */
+		0x00,	/* 19 */
+		0x0F,	/* 1A */
+		0x0F,	/* 1B */
+		0x60,	/* 1C */
+		0x05,	/* 1D */
+		//0x89, 0x02, /* 1E-1F */
+		0xC0, 0x02, /* 1E-1F */
+		//0x5F,	/* 20 */
+		0x9C,	/* 20 */
+		0x04,	/* 21 */
+		//0x5F,	/* 22 */
+		0x9C,	/* 22 */
+		0x01,	/* 23 */
+		0x02,	/* 24 */
+		0x00,	/* 25 */
+		0x0A,	/* 26 */
+		0x05,	/* 27 */
+		0x00,	/* 28 */
+		0x10,	/* 29 */
+		0xFF, 0x03, /* 2A-2B */
+		0x24,	/* 2C */
+		0x0F, 0x78, /* 2D-2E */
+		0x00, 0x00, /* 2F-30 */
+		0xB2, 0x04, /* 31-32 */
+		0x14,	/* 33 */
+		0x02,	/* 34 */
+		0x00,	/* 35 written multiple times */
+		0x00,	/* 36 not written */
+		0xA3,	/* 37 */
+		0xC8,	/* 38 */
+		0x15,	/* 39 */
+		0x05,	/* 3A */
+		0x3B,	/* 3B */
+		0x3C, 0x00, /* 3C-3D */
+		0x00,	/* 3E written multiple times */
+		0x00,	/* never written */
+	} };
+
+	if (norm == MATROXFB_OUTPUT_MODE_PAL) {
+		*data = palregs;
+		*outd = &paloutd;
+	} else {
+  		*data = ntscregs;
+		*outd = &ntscoutd;
+	}
+ 	return;
+}
+
+#define LR(x) cve2_set_reg(minfo, (x), m->regs[(x)])
+static void cve2_init_TV(struct matrox_fb_info *minfo,
+			 const struct mavenregs *m)
+{
+	int i;
+
+	LR(0x80);
+	LR(0x82); LR(0x83);
+	LR(0x84); LR(0x85);
+	
+	cve2_set_reg(minfo, 0x3E, 0x01);
+	
+	for (i = 0; i < 0x3E; i++) {
+		LR(i);
+	}
+	cve2_set_reg(minfo, 0x3E, 0x00);
+}
+
+static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
+	struct matrox_fb_info *minfo = md;
+
+	dprintk(KERN_DEBUG "Computing, mode=%u\n", minfo->outputs[1].mode);
+
+	if (mt->crtc == MATROXFB_SRC_CRTC2 &&
+	    minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
+		const struct output_desc* outd;
+
+		cve2_init_TVdata(minfo->outputs[1].mode, &minfo->hw.maven, &outd);
+		{
+			int blacklevel, whitelevel;
+			g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
+			minfo->hw.maven.regs[0x0E] = blacklevel >> 2;
+			minfo->hw.maven.regs[0x0F] = blacklevel & 3;
+			minfo->hw.maven.regs[0x1E] = whitelevel >> 2;
+			minfo->hw.maven.regs[0x1F] = whitelevel & 3;
+
+			minfo->hw.maven.regs[0x20] =
+			minfo->hw.maven.regs[0x22] = minfo->altout.tvo_params.saturation;
+
+			minfo->hw.maven.regs[0x25] = minfo->altout.tvo_params.hue;
+
+			if (minfo->altout.tvo_params.testout) {
+				minfo->hw.maven.regs[0x05] |= 0x02;
+			}
+		}
+		computeRegs(minfo, &minfo->hw.maven, mt, outd);
+	} else if (mt->mnp < 0) {
+		/* We must program clocks before CRTC2, otherwise interlaced mode
+		   startup may fail */
+		mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
+		mt->pixclock = g450_mnp2f(minfo, mt->mnp);
+	}
+	dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock);
+	return 0;
+}
+
+static int matroxfb_g450_program(void* md) {
+	struct matrox_fb_info *minfo = md;
+	
+	if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
+		cve2_init_TV(minfo, &minfo->hw.maven);
+	}
+	return 0;
+}
+
+static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) {
+	switch (arg) {
+		case MATROXFB_OUTPUT_MODE_PAL:
+		case MATROXFB_OUTPUT_MODE_NTSC:
+		case MATROXFB_OUTPUT_MODE_MONITOR:
+			return 0;
+	}
+	return -EINVAL;
+}
+
+static int g450_dvi_compute(void* md, struct my_timming* mt) {
+	struct matrox_fb_info *minfo = md;
+
+	if (mt->mnp < 0) {
+		mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
+		mt->pixclock = g450_mnp2f(minfo, mt->mnp);
+	}
+	return 0;
+}
+
+static struct matrox_altout matroxfb_g450_altout = {
+	.name		= "Secondary output",
+	.compute	= matroxfb_g450_compute,
+	.program	= matroxfb_g450_program,
+	.verifymode	= matroxfb_g450_verify_mode,
+	.getqueryctrl	= g450_query_ctrl,
+	.getctrl	= g450_get_ctrl,
+	.setctrl	= g450_set_ctrl,
+};
+
+static struct matrox_altout matroxfb_g450_dvi = {
+	.name		= "DVI output",
+	.compute	= g450_dvi_compute,
+};
+
+void matroxfb_g450_connect(struct matrox_fb_info *minfo)
+{
+	if (minfo->devflags.g450dac) {
+		down_write(&minfo->altout.lock);
+		tvo_fill_defaults(minfo);
+		minfo->outputs[1].src = minfo->outputs[1].default_src;
+		minfo->outputs[1].data = minfo;
+		minfo->outputs[1].output = &matroxfb_g450_altout;
+		minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+		minfo->outputs[2].src = minfo->outputs[2].default_src;
+		minfo->outputs[2].data = minfo;
+		minfo->outputs[2].output = &matroxfb_g450_dvi;
+		minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+		up_write(&minfo->altout.lock);
+	}
+}
+
+void matroxfb_g450_shutdown(struct matrox_fb_info *minfo)
+{
+	if (minfo->devflags.g450dac) {
+		down_write(&minfo->altout.lock);
+		minfo->outputs[1].src = MATROXFB_SRC_NONE;
+		minfo->outputs[1].output = NULL;
+		minfo->outputs[1].data = NULL;
+		minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+		minfo->outputs[2].src = MATROXFB_SRC_NONE;
+		minfo->outputs[2].output = NULL;
+		minfo->outputs[2].data = NULL;
+		minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+		up_write(&minfo->altout.lock);
+	}
+}
+
+EXPORT_SYMBOL(matroxfb_g450_connect);
+EXPORT_SYMBOL(matroxfb_g450_shutdown);
+
+MODULE_AUTHOR("(c) 2000-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Matrox G450/G550 output driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_g450.h b/drivers/video/fbdev/matrox/matroxfb_g450.h
new file mode 100644
index 000000000000..3a3e654444b8
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_g450.h
@@ -0,0 +1,14 @@
+#ifndef __MATROXFB_G450_H__
+#define __MATROXFB_G450_H__
+
+#include "matroxfb_base.h"
+
+#ifdef CONFIG_FB_MATROX_G
+void matroxfb_g450_connect(struct matrox_fb_info *minfo);
+void matroxfb_g450_shutdown(struct matrox_fb_info *minfo);
+#else
+static inline void matroxfb_g450_connect(struct matrox_fb_info *minfo) { };
+static inline void matroxfb_g450_shutdown(struct matrox_fb_info *minfo) { };
+#endif
+
+#endif /* __MATROXFB_G450_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_maven.c b/drivers/video/fbdev/matrox/matroxfb_maven.c
new file mode 100644
index 000000000000..ee41a0f276b2
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_maven.c
@@ -0,0 +1,1301 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * See matroxfb_base.c for contributors.
+ *
+ */
+
+#include "matroxfb_maven.h"
+#include "matroxfb_misc.h"
+#include "matroxfb_DAC1064.h"
+#include <linux/i2c.h>
+#include <linux/matroxfb.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+
+#define MGATVO_B	1
+#define MGATVO_C	2
+
+static const struct maven_gamma {
+  unsigned char reg83;
+  unsigned char reg84;
+  unsigned char reg85;
+  unsigned char reg86;
+  unsigned char reg87;
+  unsigned char reg88;
+  unsigned char reg89;
+  unsigned char reg8a;
+  unsigned char reg8b;
+} maven_gamma[] = {
+  { 131, 57, 223, 15, 117, 212, 251, 91, 156},
+  { 133, 61, 128, 63, 180, 147, 195, 100, 180},
+  { 131, 19, 63, 31, 50, 66, 171, 64, 176},
+  { 0, 0, 0, 31, 16, 16, 16, 100, 200},
+  { 8, 23, 47, 73, 147, 244, 220, 80, 195},
+  { 22, 43, 64, 80, 147, 115, 58, 85, 168},
+  { 34, 60, 80, 214, 147, 212, 188, 85, 167},
+  { 45, 77, 96, 216, 147, 99, 91, 85, 159},
+  { 56, 76, 112, 107, 147, 212, 148, 64, 144},
+  { 65, 91, 128, 137, 147, 196, 17, 69, 148},
+  { 72, 104, 136, 138, 147, 180, 245, 73, 147},
+  { 87, 116, 143, 126, 16, 83, 229, 77, 144},
+  { 95, 119, 152, 254, 244, 83, 221, 77, 151},
+  { 100, 129, 159, 156, 244, 148, 197, 77, 160},
+  { 105, 141, 167, 247, 244, 132, 181, 84, 166},
+  { 105, 147, 168, 247, 244, 245, 181, 90, 170},
+  { 120, 153, 175, 248, 212, 229, 165, 90, 180},
+  { 119, 156, 176, 248, 244, 229, 84, 74, 160},
+  { 119, 158, 183, 248, 244, 229, 149, 78, 165}
+};
+
+/* Definition of the various controls */
+struct mctl {
+	struct v4l2_queryctrl desc;
+	size_t control;
+};
+
+#define BLMIN	0x0FF
+#define WLMAX	0x3FF
+
+static const struct mctl maven_controls[] =
+{	{ { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
+	  "brightness",
+	  0, WLMAX - BLMIN, 1, 379 - BLMIN, 
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
+	{ { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
+	  "contrast",
+	  0, 1023, 1, 127,
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
+	{ { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
+	  "saturation",
+	  0, 255, 1, 155,
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
+	{ { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
+	  "hue",
+	  0, 255, 1, 0,
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
+	{ { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER,
+	  "gamma",
+	  0, ARRAY_SIZE(maven_gamma) - 1, 1, 3,
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) },
+	{ { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
+	  "test output",
+	  0, 1, 1, 0,
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
+	{ { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER,
+	  "deflicker mode",
+	  0, 2, 1, 0,
+	  0,
+	}, offsetof(struct matrox_fb_info, altout.tvo_params.deflicker) },
+
+};
+
+#define MAVCTRLS ARRAY_SIZE(maven_controls)
+
+/* Return: positive number: id found
+           -EINVAL:         id not found, return failure
+	   -ENOENT:         id not found, create fake disabled control */
+static int get_ctrl_id(__u32 v4l2_id) {
+	int i;
+
+	for (i = 0; i < MAVCTRLS; i++) {
+		if (v4l2_id < maven_controls[i].desc.id) {
+			if (maven_controls[i].desc.id == 0x08000000) {
+				return -EINVAL;
+			}
+			return -ENOENT;
+		}
+		if (v4l2_id == maven_controls[i].desc.id) {
+			return i;
+		}
+	}
+	return -EINVAL;
+}
+
+struct maven_data {
+	struct matrox_fb_info*		primary_head;
+	struct i2c_client		*client;
+	int				version;
+};
+
+static int* get_ctrl_ptr(struct maven_data* md, int idx) {
+	return (int*)((char*)(md->primary_head) + maven_controls[idx].control);
+}
+
+static int maven_get_reg(struct i2c_client* c, char reg) {
+	char dst;
+	struct i2c_msg msgs[] = {
+		{
+			.addr = c->addr,
+			.flags = I2C_M_REV_DIR_ADDR,
+			.len = sizeof(reg),
+			.buf = &reg
+		},
+		{
+			.addr = c->addr,
+			.flags = I2C_M_RD | I2C_M_NOSTART,
+			.len = sizeof(dst),
+			.buf = &dst
+		}
+	};
+	s32 err;
+
+	err = i2c_transfer(c->adapter, msgs, 2);
+	if (err < 0)
+		printk(KERN_INFO "ReadReg(%d) failed\n", reg);
+	return dst & 0xFF;
+}
+
+static int maven_set_reg(struct i2c_client* c, int reg, int val) {
+	s32 err;
+
+	err = i2c_smbus_write_byte_data(c, reg, val);
+	if (err)
+		printk(KERN_INFO "WriteReg(%d) failed\n", reg);
+	return err;
+}
+
+static int maven_set_reg_pair(struct i2c_client* c, int reg, int val) {
+	s32 err;
+
+	err = i2c_smbus_write_word_data(c, reg, val);
+	if (err)
+		printk(KERN_INFO "WriteRegPair(%d) failed\n", reg);
+	return err;
+}
+
+static const struct matrox_pll_features maven_pll = {
+	50000,
+	27000,
+	4, 127,
+	2, 31,
+	3
+};
+
+struct matrox_pll_features2 {
+	unsigned int	vco_freq_min;
+	unsigned int	vco_freq_max;
+	unsigned int	feed_div_min;
+	unsigned int	feed_div_max;
+	unsigned int	in_div_min;
+	unsigned int	in_div_max;
+	unsigned int	post_shift_max;
+};
+
+struct matrox_pll_ctl {
+	unsigned int	ref_freq;
+	unsigned int	den;
+};
+
+static const struct matrox_pll_features2 maven1000_pll = {
+	 50000000,
+	300000000,
+	 5, 128,
+	 3,  32,
+	 3
+};
+
+static const struct matrox_pll_ctl maven_PAL = {
+	540000,
+	    50
+};
+
+static const struct matrox_pll_ctl maven_NTSC = {
+	450450,	/* 27027000/60 == 27000000/59.94005994 */
+	    60
+};
+
+static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
+		const struct matrox_pll_ctl* ctl,
+		unsigned int htotal, unsigned int vtotal,
+		unsigned int* in, unsigned int* feed, unsigned int* post,
+		unsigned int* h2) {
+	unsigned int besth2 = 0;
+	unsigned int fxtal = ctl->ref_freq;
+	unsigned int fmin = pll->vco_freq_min / ctl->den;
+	unsigned int fwant;
+	unsigned int p;
+	unsigned int scrlen;
+	unsigned int fmax;
+
+	DBG(__func__)
+
+	scrlen = htotal * (vtotal - 1);
+	fwant = htotal * vtotal;
+	fmax = pll->vco_freq_max / ctl->den;
+
+	dprintk(KERN_DEBUG "want: %u, xtal: %u, h: %u, v: %u, fmax: %u\n",
+		fwant, fxtal, htotal, vtotal, fmax);
+	for (p = 1; p <= pll->post_shift_max; p++) {
+		if (fwant * 2 > fmax)
+			break;
+		fwant *= 2;
+	}
+	if (fwant > fmax)
+		return 0;
+	for (; p-- > 0; fwant >>= 1) {
+		unsigned int m;
+
+		if (fwant < fmin) break;
+		for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
+			unsigned int n;
+			unsigned int dvd;
+			unsigned int ln;
+
+			n = (fwant * m) / fxtal;
+			if (n < pll->feed_div_min)
+				continue;
+			if (n > pll->feed_div_max)
+				break;
+
+			ln = fxtal * n;
+			dvd = m << p;
+
+			if (ln % dvd)
+				continue;
+			ln = ln / dvd;
+
+			if (ln < scrlen + 2)
+				continue;
+			ln = ln - scrlen;
+			if (ln > htotal)
+				continue;
+			dprintk(KERN_DEBUG "Match: %u / %u / %u / %u\n", n, m, p, ln);
+			if (ln > besth2) {
+				dprintk(KERN_DEBUG "Better...\n");
+				*h2 = besth2 = ln;
+				*post = p;
+				*in = m;
+				*feed = n;
+			}
+		}
+	}
+
+	/* if h2/post/in/feed have not been assigned, return zero (error) */
+	if (besth2 < 2)
+		return 0;
+
+	dprintk(KERN_ERR "clk: %02X %02X %02X %d %d\n", *in, *feed, *post, fxtal, fwant);
+	return fxtal * (*feed) / (*in) * ctl->den;
+}
+
+static int matroxfb_mavenclock(const struct matrox_pll_ctl *ctl,
+		unsigned int htotal, unsigned int vtotal,
+		unsigned int* in, unsigned int* feed, unsigned int* post,
+		unsigned int* htotal2) {
+	unsigned int fvco;
+	unsigned int uninitialized_var(p);
+
+	fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
+	if (!fvco)
+		return -EINVAL;
+	p = (1 << p) - 1;
+	if (fvco <= 100000000)
+		;
+	else if (fvco <= 140000000)
+		p |= 0x08;
+	else if (fvco <= 180000000)
+		p |= 0x10;
+	else
+		p |= 0x18;
+	*post = p;
+	return 0;
+}
+
+static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
+		unsigned int* in, unsigned int* feed, unsigned int* post) {
+	unsigned int fvco;
+	unsigned int p;
+
+	fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
+	p = (1 << p) - 1;
+	if (fvco <= 100000)
+		;
+	else if (fvco <= 140000)
+		p |= 0x08;
+	else if (fvco <= 180000)
+		p |= 0x10;
+	else
+		p |= 0x18;
+	*post = p;
+	return;
+}
+
+static unsigned char maven_compute_deflicker (const struct maven_data* md) {
+	unsigned char df;
+	
+	df = (md->version == MGATVO_B?0x40:0x00);
+	switch (md->primary_head->altout.tvo_params.deflicker) {
+		case 0:
+/*			df |= 0x00; */
+			break;
+		case 1:
+			df |= 0xB1;
+			break;
+		case 2:
+			df |= 0xA2;
+			break;
+	}
+	return df;
+}
+
+static void maven_compute_bwlevel (const struct maven_data* md,
+				   int *bl, int *wl) {
+	const int b = md->primary_head->altout.tvo_params.brightness + BLMIN;
+	const int c = md->primary_head->altout.tvo_params.contrast;
+
+	*bl = max(b - c, BLMIN);
+	*wl = min(b + c, WLMAX);
+}
+
+static const struct maven_gamma* maven_compute_gamma (const struct maven_data* md) {
+ 	return maven_gamma + md->primary_head->altout.tvo_params.gamma;
+}
+
+
+static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* data) {
+	static struct mavenregs palregs = { {
+		0x2A, 0x09, 0x8A, 0xCB,	/* 00: chroma subcarrier */
+		0x00,
+		0x00,	/* ? not written */
+		0x00,	/* modified by code (F9 written...) */
+		0x00,	/* ? not written */
+		0x7E,	/* 08 */
+		0x44,	/* 09 */
+		0x9C,	/* 0A */
+		0x2E,	/* 0B */
+		0x21,	/* 0C */
+		0x00,	/* ? not written */
+		0x3F, 0x03, /* 0E-0F */
+		0x3F, 0x03, /* 10-11 */
+		0x1A,	/* 12 */
+		0x2A,	/* 13 */
+		0x1C, 0x3D, 0x14, /* 14-16 */
+		0x9C, 0x01, /* 17-18 */
+		0x00,	/* 19 */
+		0xFE,	/* 1A */
+		0x7E,	/* 1B */
+		0x60,	/* 1C */
+		0x05,	/* 1D */
+		0x89, 0x03, /* 1E-1F */
+		0x72,	/* 20 */
+		0x07,	/* 21 */
+		0x72,	/* 22 */
+		0x00,	/* 23 */
+		0x00,	/* 24 */
+		0x00,	/* 25 */
+		0x08,	/* 26 */
+		0x04,	/* 27 */
+		0x00,	/* 28 */
+		0x1A,	/* 29 */
+		0x55, 0x01, /* 2A-2B */
+		0x26,	/* 2C */
+		0x07, 0x7E, /* 2D-2E */
+		0x02, 0x54, /* 2F-30 */
+		0xB0, 0x00, /* 31-32 */
+		0x14,	/* 33 */
+		0x49,	/* 34 */
+		0x00,	/* 35 written multiple times */
+		0x00,	/* 36 not written */
+		0xA3,	/* 37 */
+		0xC8,	/* 38 */
+		0x22,	/* 39 */
+		0x02,	/* 3A */
+		0x22,	/* 3B */
+		0x3F, 0x03, /* 3C-3D */
+		0x00,	/* 3E written multiple times */
+		0x00,	/* 3F not written */
+	}, MATROXFB_OUTPUT_MODE_PAL, 625, 50 };
+	static struct mavenregs ntscregs = { {
+		0x21, 0xF0, 0x7C, 0x1F,	/* 00: chroma subcarrier */
+		0x00,
+		0x00,	/* ? not written */
+		0x00,	/* modified by code (F9 written...) */
+		0x00,	/* ? not written */
+		0x7E,	/* 08 */
+		0x43,	/* 09 */
+		0x7E,	/* 0A */
+		0x3D,	/* 0B */
+		0x00,	/* 0C */
+		0x00,	/* ? not written */
+		0x41, 0x00, /* 0E-0F */
+		0x3C, 0x00, /* 10-11 */
+		0x17,	/* 12 */
+		0x21,	/* 13 */
+		0x1B, 0x1B, 0x24, /* 14-16 */
+		0x83, 0x01, /* 17-18 */
+		0x00,	/* 19 */
+		0x0F,	/* 1A */
+		0x0F,	/* 1B */
+		0x60,	/* 1C */
+		0x05,	/* 1D */
+		0x89, 0x02, /* 1E-1F */
+		0x5F,	/* 20 */
+		0x04,	/* 21 */
+		0x5F,	/* 22 */
+		0x01,	/* 23 */
+		0x02,	/* 24 */
+		0x00,	/* 25 */
+		0x0A,	/* 26 */
+		0x05,	/* 27 */
+		0x00,	/* 28 */
+		0x10,	/* 29 */
+		0xFF, 0x03, /* 2A-2B */
+		0x24,	/* 2C */
+		0x0F, 0x78, /* 2D-2E */
+		0x00, 0x00, /* 2F-30 */
+		0xB2, 0x04, /* 31-32 */
+		0x14,	/* 33 */
+		0x02,	/* 34 */
+		0x00,	/* 35 written multiple times */
+		0x00,	/* 36 not written */
+		0xA3,	/* 37 */
+		0xC8,	/* 38 */
+		0x15,	/* 39 */
+		0x05,	/* 3A */
+		0x3B,	/* 3B */
+		0x3C, 0x00, /* 3C-3D */
+		0x00,	/* 3E written multiple times */
+		0x00,	/* never written */
+	}, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 };
+	struct matrox_fb_info *minfo = md->primary_head;
+
+	if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_PAL)
+		*data = palregs;
+	else
+		*data = ntscregs;
+
+	/* Set deflicker */
+	data->regs[0x93] = maven_compute_deflicker(md);
+ 
+	/* set gamma */
+	{
+		const struct maven_gamma* g;
+		g = maven_compute_gamma(md);
+		data->regs[0x83] = g->reg83;
+		data->regs[0x84] = g->reg84;
+		data->regs[0x85] = g->reg85;
+		data->regs[0x86] = g->reg86;
+		data->regs[0x87] = g->reg87;
+		data->regs[0x88] = g->reg88;
+		data->regs[0x89] = g->reg89;
+		data->regs[0x8A] = g->reg8a;
+		data->regs[0x8B] = g->reg8b;
+	}
+ 
+	/* Set contrast / brightness */
+	{
+		int bl, wl;
+		maven_compute_bwlevel (md, &bl, &wl);
+		data->regs[0x0e] = bl >> 2;
+		data->regs[0x0f] = bl & 3;
+		data->regs[0x1e] = wl >> 2;
+		data->regs[0x1f] = wl & 3;
+	}
+
+	/* Set saturation */
+	{
+		data->regs[0x20] =
+		data->regs[0x22] = minfo->altout.tvo_params.saturation;
+	}
+ 
+	/* Set HUE */
+	data->regs[0x25] = minfo->altout.tvo_params.hue;
+	return;
+}
+
+#define LR(x) maven_set_reg(c, (x), m->regs[(x)])
+#define LRP(x) maven_set_reg_pair(c, (x), m->regs[(x)] | (m->regs[(x)+1] << 8))
+static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
+	int val;
+
+
+	maven_set_reg(c, 0x3E, 0x01);
+	maven_get_reg(c, 0x82);	/* fetch oscillator state? */
+	maven_set_reg(c, 0x8C, 0x00);
+	maven_get_reg(c, 0x94);	/* get 0x82 */
+	maven_set_reg(c, 0x94, 0xA2);
+	/* xmiscctrl */
+
+	maven_set_reg_pair(c, 0x8E, 0x1EFF);
+	maven_set_reg(c, 0xC6, 0x01);
+
+	/* removed code... */
+
+	maven_get_reg(c, 0x06);
+	maven_set_reg(c, 0x06, 0xF9);	/* or read |= 0xF0 ? */
+
+	/* removed code here... */
+
+	/* real code begins here? */
+	/* chroma subcarrier */
+	LR(0x00); LR(0x01); LR(0x02); LR(0x03);
+
+	LR(0x04);
+
+	LR(0x2C);
+	LR(0x08);
+	LR(0x0A);
+	LR(0x09);
+	LR(0x29);
+	LRP(0x31);
+	LRP(0x17);
+	LR(0x0B);
+	LR(0x0C);
+	if (m->mode == MATROXFB_OUTPUT_MODE_PAL) {
+		maven_set_reg(c, 0x35, 0x10); /* ... */
+	} else {
+		maven_set_reg(c, 0x35, 0x0F); /* ... */
+	}
+
+	LRP(0x10);
+
+	LRP(0x0E);
+	LRP(0x1E);
+
+	LR(0x20);	/* saturation #1 */
+	LR(0x22);	/* saturation #2 */
+	LR(0x25);	/* hue */
+	LR(0x34);
+	LR(0x33);
+	LR(0x19);
+	LR(0x12);
+	LR(0x3B);
+	LR(0x13);
+	LR(0x39);
+	LR(0x1D);
+	LR(0x3A);
+	LR(0x24);
+	LR(0x14);
+	LR(0x15);
+	LR(0x16);
+	LRP(0x2D);
+	LRP(0x2F);
+	LR(0x1A);
+	LR(0x1B);
+	LR(0x1C);
+	LR(0x23);
+	LR(0x26);
+	LR(0x28);
+	LR(0x27);
+	LR(0x21);
+	LRP(0x2A);
+	if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
+		maven_set_reg(c, 0x35, 0x1D);	/* ... */
+	else
+		maven_set_reg(c, 0x35, 0x1C);
+
+	LRP(0x3C);
+	LR(0x37);
+	LR(0x38);
+	maven_set_reg(c, 0xB3, 0x01);
+
+	maven_get_reg(c, 0xB0);	/* read 0x80 */
+	maven_set_reg(c, 0xB0, 0x08);	/* ugh... */
+	maven_get_reg(c, 0xB9);	/* read 0x7C */
+	maven_set_reg(c, 0xB9, 0x78);
+	maven_get_reg(c, 0xBF);	/* read 0x00 */
+	maven_set_reg(c, 0xBF, 0x02);
+	maven_get_reg(c, 0x94);	/* read 0x82 */
+	maven_set_reg(c, 0x94, 0xB3);
+
+	LR(0x80); /* 04 1A 91 or 05 21 91 */
+	LR(0x81);
+	LR(0x82);
+
+	maven_set_reg(c, 0x8C, 0x20);
+	maven_get_reg(c, 0x8D);
+	maven_set_reg(c, 0x8D, 0x10);
+
+	LR(0x90); /* 4D 50 52 or 4E 05 45 */
+	LR(0x91);
+	LR(0x92);
+
+	LRP(0x9A); /* 0049 or 004F */
+	LRP(0x9C); /* 0004 or 0004 */
+	LRP(0x9E); /* 0458 or 045E */
+	LRP(0xA0); /* 05DA or 051B */
+	LRP(0xA2); /* 00CC or 00CF */
+	LRP(0xA4); /* 007D or 007F */
+	LRP(0xA6); /* 007C or 007E */
+	LRP(0xA8); /* 03CB or 03CE */
+	LRP(0x98); /* 0000 or 0000 */
+	LRP(0xAE); /* 0044 or 003A */
+	LRP(0x96); /* 05DA or 051B */
+	LRP(0xAA); /* 04BC or 046A */
+	LRP(0xAC); /* 004D or 004E */
+
+	LR(0xBE);
+	LR(0xC2);
+
+	maven_get_reg(c, 0x8D);
+	maven_set_reg(c, 0x8D, 0x04);
+
+	LR(0x20);	/* saturation #1 */
+	LR(0x22);	/* saturation #2 */
+	LR(0x93);	/* whoops */
+	LR(0x20);	/* oh, saturation #1 again */
+	LR(0x22);	/* oh, saturation #2 again */
+	LR(0x25);	/* hue */
+	LRP(0x0E);
+	LRP(0x1E);
+	LRP(0x0E);	/* problems with memory? */
+	LRP(0x1E);	/* yes, matrox must have problems in memory area... */
+
+	/* load gamma correction stuff */
+	LR(0x83);
+	LR(0x84);
+	LR(0x85);
+	LR(0x86);
+	LR(0x87);
+	LR(0x88);
+	LR(0x89);
+	LR(0x8A);
+	LR(0x8B);
+
+	val = maven_get_reg(c, 0x8D);
+	val &= 0x14;			/* 0x10 or anything ored with it */
+	maven_set_reg(c, 0x8D, val);
+
+	LR(0x33);
+	LR(0x19);
+	LR(0x12);
+	LR(0x3B);
+	LR(0x13);
+	LR(0x39);
+	LR(0x1D);
+	LR(0x3A);
+	LR(0x24);
+	LR(0x14);
+	LR(0x15);
+	LR(0x16);
+	LRP(0x2D);
+	LRP(0x2F);
+	LR(0x1A);
+	LR(0x1B);
+	LR(0x1C);
+	LR(0x23);
+	LR(0x26);
+	LR(0x28);
+	LR(0x27);
+	LR(0x21);
+	LRP(0x2A);
+	if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
+		maven_set_reg(c, 0x35, 0x1D);
+	else
+		maven_set_reg(c, 0x35, 0x1C);
+	LRP(0x3C);
+	LR(0x37);
+	LR(0x38);
+
+	maven_get_reg(c, 0xB0);
+	LR(0xB0);	/* output mode */
+	LR(0x90);
+	LR(0xBE);
+	LR(0xC2);
+
+	LRP(0x9A);
+	LRP(0xA2);
+	LRP(0x9E);
+	LRP(0xA6);
+	LRP(0xAA);
+	LRP(0xAC);
+	maven_set_reg(c, 0x3E, 0x00);
+	maven_set_reg(c, 0x95, 0x20);
+}
+
+static int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
+		struct mavenregs* m) {
+	unsigned int x;
+	unsigned int err = ~0;
+
+	/* 1:1 */
+	m->regs[0x80] = 0x0F;
+	m->regs[0x81] = 0x07;
+	m->regs[0x82] = 0x81;
+
+	for (x = 0; x < 8; x++) {
+		unsigned int c;
+		unsigned int uninitialized_var(a), uninitialized_var(b),
+			     uninitialized_var(h2);
+		unsigned int h = ht + 2 + x;
+
+		if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
+			unsigned int diff = h - h2;
+
+			if (diff < err) {
+				err = diff;
+				m->regs[0x80] = a - 1;
+				m->regs[0x81] = b - 1;
+				m->regs[0x82] = c | 0x80;
+				m->hcorr = h2 - 2;
+				m->htotal = h - 2;
+			}
+		}
+	}
+	return err != ~0U;
+}
+
+static inline int maven_compute_timming(struct maven_data* md,
+		struct my_timming* mt,
+		struct mavenregs* m) {
+	unsigned int tmpi;
+	unsigned int a, bv, c;
+	struct matrox_fb_info *minfo = md->primary_head;
+
+	m->mode = minfo->outputs[1].mode;
+	if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) {
+		unsigned int lmargin;
+		unsigned int umargin;
+		unsigned int vslen;
+		unsigned int hcrt;
+		unsigned int slen;
+
+		maven_init_TVdata(md, m);
+
+		if (maven_find_exact_clocks(mt->HTotal, mt->VTotal, m) == 0)
+			return -EINVAL;
+
+		lmargin = mt->HTotal - mt->HSyncEnd;
+		slen = mt->HSyncEnd - mt->HSyncStart;
+		hcrt = mt->HTotal - slen - mt->delay;
+		umargin = mt->VTotal - mt->VSyncEnd;
+		vslen = mt->VSyncEnd - mt->VSyncStart;
+
+		if (m->hcorr < mt->HTotal)
+			hcrt += m->hcorr;
+		if (hcrt > mt->HTotal)
+			hcrt -= mt->HTotal;
+		if (hcrt + 2 > mt->HTotal)
+			hcrt = 0;	/* or issue warning? */
+
+		/* last (first? middle?) line in picture can have different length */
+		/* hlen - 2 */
+		m->regs[0x96] = m->hcorr;
+		m->regs[0x97] = m->hcorr >> 8;
+		/* ... */
+		m->regs[0x98] = 0x00; m->regs[0x99] = 0x00;
+		/* hblanking end */
+		m->regs[0x9A] = lmargin;	/* 100% */
+		m->regs[0x9B] = lmargin >> 8;	/* 100% */
+		/* who knows */
+		m->regs[0x9C] = 0x04;
+		m->regs[0x9D] = 0x00;
+		/* htotal - 2 */
+		m->regs[0xA0] = m->htotal;
+		m->regs[0xA1] = m->htotal >> 8;
+		/* vblanking end */
+		m->regs[0xA2] = mt->VTotal - mt->VSyncStart - 1;	/* stop vblanking */
+		m->regs[0xA3] = (mt->VTotal - mt->VSyncStart - 1) >> 8;
+		/* something end... [A6]+1..[A8] */
+		if (md->version == MGATVO_B) {
+			m->regs[0xA4] = 0x04;
+			m->regs[0xA5] = 0x00;
+		} else {
+			m->regs[0xA4] = 0x01;
+			m->regs[0xA5] = 0x00;
+		}
+		/* something start... 0..[A4]-1 */
+		m->regs[0xA6] = 0x00;
+		m->regs[0xA7] = 0x00;
+		/* vertical line count - 1 */
+		m->regs[0xA8] = mt->VTotal - 1;
+		m->regs[0xA9] = (mt->VTotal - 1) >> 8;
+		/* horizontal vidrst pos */
+		m->regs[0xAA] = hcrt;		/* 0 <= hcrt <= htotal - 2 */
+		m->regs[0xAB] = hcrt >> 8;
+		/* vertical vidrst pos */
+		m->regs[0xAC] = mt->VTotal - 2;
+		m->regs[0xAD] = (mt->VTotal - 2) >> 8;
+		/* moves picture up/down and so on... */
+		m->regs[0xAE] = 0x01; /* Fix this... 0..VTotal */
+		m->regs[0xAF] = 0x00;
+		{
+			int hdec;
+			int hlen;
+			unsigned int ibmin = 4 + lmargin + mt->HDisplay;
+			unsigned int ib;
+			int i;
+
+			/* Verify! */
+			/* Where 94208 came from? */
+			if (mt->HTotal)
+				hdec = 94208 / (mt->HTotal);
+			else
+				hdec = 0x81;
+			if (hdec > 0x81)
+				hdec = 0x81;
+			if (hdec < 0x41)
+				hdec = 0x41;
+			hdec--;
+			hlen = 98304 - 128 - ((lmargin + mt->HDisplay - 8) * hdec);
+			if (hlen < 0)
+				hlen = 0;
+			hlen = hlen >> 8;
+			if (hlen > 0xFF)
+				hlen = 0xFF;
+			/* Now we have to compute input buffer length.
+			   If you want any picture, it must be between
+			     4 + lmargin + xres
+			   and
+			     94208 / hdec
+			   If you want perfect picture even on the top
+			   of screen, it must be also
+			     0x3C0000 * i / hdec + Q - R / hdec
+			   where
+			        R      Qmin   Qmax
+			     0x07000   0x5AE  0x5BF
+			     0x08000   0x5CF  0x5FF
+			     0x0C000   0x653  0x67F
+			     0x10000   0x6F8  0x6FF
+			 */
+			i = 1;
+			do {
+				ib = ((0x3C0000 * i - 0x8000)/ hdec + 0x05E7) >> 8;
+				i++;
+			} while (ib < ibmin);
+			if (ib >= m->htotal + 2) {
+				ib = ibmin;
+			}
+
+			m->regs[0x90] = hdec;	/* < 0x40 || > 0x80 is bad... 0x80 is questionable */
+			m->regs[0xC2] = hlen;
+			/* 'valid' input line length */
+			m->regs[0x9E] = ib;
+			m->regs[0x9F] = ib >> 8;
+		}
+		{
+			int vdec;
+			int vlen;
+
+#define MATROX_USE64BIT_DIVIDE
+			if (mt->VTotal) {
+#ifdef MATROX_USE64BIT_DIVIDE
+				u64 f1;
+				u32 a;
+				u32 b;
+
+				a = m->vlines * (m->htotal + 2);
+				b = (mt->VTotal - 1) * (m->htotal + 2) + m->hcorr + 2;
+
+				f1 = ((u64)a) << 15;	/* *32768 */
+				do_div(f1, b);
+				vdec = f1;
+#else
+				vdec = m->vlines * 32768 / mt->VTotal;
+#endif
+			} else
+				vdec = 0x8000;
+			if (vdec > 0x8000)
+				vdec = 0x8000;
+			vlen = (vslen + umargin + mt->VDisplay) * vdec;
+			vlen = (vlen >> 16) - 146; /* FIXME: 146?! */
+			if (vlen < 0)
+				vlen = 0;
+			if (vlen > 0xFF)
+				vlen = 0xFF;
+			vdec--;
+			m->regs[0x91] = vdec;
+			m->regs[0x92] = vdec >> 8;
+			m->regs[0xBE] = vlen;
+		}
+		m->regs[0xB0] = 0x08;	/* output: SVideo/Composite */
+		return 0;
+	}
+
+	DAC1064_calcclock(mt->pixclock, 450000, &a, &bv, &c);
+	m->regs[0x80] = a;
+	m->regs[0x81] = bv;
+	m->regs[0x82] = c | 0x80;
+
+	m->regs[0xB3] = 0x01;
+	m->regs[0x94] = 0xB2;
+
+	/* htotal... */
+	m->regs[0x96] = mt->HTotal;
+	m->regs[0x97] = mt->HTotal >> 8;
+	/* ?? */
+	m->regs[0x98] = 0x00;
+	m->regs[0x99] = 0x00;
+	/* hsync len */
+	tmpi = mt->HSyncEnd - mt->HSyncStart;
+	m->regs[0x9A] = tmpi;
+	m->regs[0x9B] = tmpi >> 8;
+	/* hblank end */
+	tmpi = mt->HTotal - mt->HSyncStart;
+	m->regs[0x9C] = tmpi;
+	m->regs[0x9D] = tmpi >> 8;
+	/* hblank start */
+	tmpi += mt->HDisplay;
+	m->regs[0x9E] = tmpi;
+	m->regs[0x9F] = tmpi >> 8;
+	/* htotal + 1 */
+	tmpi = mt->HTotal + 1;
+	m->regs[0xA0] = tmpi;
+	m->regs[0xA1] = tmpi >> 8;
+	/* vsync?! */
+	tmpi = mt->VSyncEnd - mt->VSyncStart - 1;
+	m->regs[0xA2] = tmpi;
+	m->regs[0xA3] = tmpi >> 8;
+	/* ignored? */
+	tmpi = mt->VTotal - mt->VSyncStart;
+	m->regs[0xA4] = tmpi;
+	m->regs[0xA5] = tmpi >> 8;
+	/* ignored? */
+	tmpi = mt->VTotal - 1;
+	m->regs[0xA6] = tmpi;
+	m->regs[0xA7] = tmpi >> 8;
+	/* vtotal - 1 */
+	m->regs[0xA8] = tmpi;
+	m->regs[0xA9] = tmpi >> 8;
+	/* hor vidrst */
+	tmpi = mt->HTotal - mt->delay;
+	m->regs[0xAA] = tmpi;
+	m->regs[0xAB] = tmpi >> 8;
+	/* vert vidrst */
+	tmpi = mt->VTotal - 2;
+	m->regs[0xAC] = tmpi;
+	m->regs[0xAD] = tmpi >> 8;
+	/* ignored? */
+	m->regs[0xAE] = 0x00;
+	m->regs[0xAF] = 0x00;
+
+	m->regs[0xB0] = 0x03;	/* output: monitor */
+	m->regs[0xB1] = 0xA0;	/* ??? */
+	m->regs[0x8C] = 0x20;	/* must be set... */
+	m->regs[0x8D] = 0x04;	/* defaults to 0x10: test signal */
+	m->regs[0xB9] = 0x1A;	/* defaults to 0x2C: too bright */
+	m->regs[0xBF] = 0x22;	/* makes picture stable */
+
+	return 0;
+}
+
+static int maven_program_timming(struct maven_data* md,
+		const struct mavenregs* m) {
+	struct i2c_client *c = md->client;
+
+	if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
+		LR(0x80);
+		LR(0x81);
+		LR(0x82);
+
+		LR(0xB3);
+		LR(0x94);
+
+		LRP(0x96);
+		LRP(0x98);
+		LRP(0x9A);
+		LRP(0x9C);
+		LRP(0x9E);
+		LRP(0xA0);
+		LRP(0xA2);
+		LRP(0xA4);
+		LRP(0xA6);
+		LRP(0xA8);
+		LRP(0xAA);
+		LRP(0xAC);
+		LRP(0xAE);
+
+		LR(0xB0);	/* output: monitor */
+		LR(0xB1);	/* ??? */
+		LR(0x8C);	/* must be set... */
+		LR(0x8D);	/* defaults to 0x10: test signal */
+		LR(0xB9);	/* defaults to 0x2C: too bright */
+		LR(0xBF);	/* makes picture stable */
+	} else {
+		maven_init_TV(c, m);
+	}
+	return 0;
+}
+
+static inline int maven_resync(struct maven_data* md) {
+	struct i2c_client *c = md->client;
+	maven_set_reg(c, 0x95, 0x20);	/* start whole thing */
+	return 0;
+}
+
+static int maven_get_queryctrl (struct maven_data* md, 
+				struct v4l2_queryctrl *p) {
+	int i;
+	
+	i = get_ctrl_id(p->id);
+	if (i >= 0) {
+		*p = maven_controls[i].desc;
+		return 0;
+	}
+	if (i == -ENOENT) {
+		static const struct v4l2_queryctrl disctrl = 
+			{ .flags = V4L2_CTRL_FLAG_DISABLED };
+			
+		i = p->id;
+		*p = disctrl;
+		p->id = i;
+		sprintf(p->name, "Ctrl #%08X", i);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int maven_set_control (struct maven_data* md, 
+			      struct v4l2_control *p) {
+	int i;
+	
+	i = get_ctrl_id(p->id);
+	if (i < 0) return -EINVAL;
+
+	/*
+	 * Check if changed.
+	 */
+	if (p->value == *get_ctrl_ptr(md, i)) return 0;
+
+	/*
+	 * Check limits.
+	 */
+	if (p->value > maven_controls[i].desc.maximum) return -EINVAL;
+	if (p->value < maven_controls[i].desc.minimum) return -EINVAL;
+
+	/*
+	 * Store new value.
+	 */
+	*get_ctrl_ptr(md, i) = p->value;
+
+	switch (p->id) {
+		case V4L2_CID_BRIGHTNESS:
+		case V4L2_CID_CONTRAST:
+		{
+		  int blacklevel, whitelevel;
+		  maven_compute_bwlevel(md, &blacklevel, &whitelevel);
+		  blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
+		  whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
+		  maven_set_reg_pair(md->client, 0x0e, blacklevel);
+		  maven_set_reg_pair(md->client, 0x1e, whitelevel);
+		}
+		break;
+		case V4L2_CID_SATURATION:
+		{
+		  maven_set_reg(md->client, 0x20, p->value);
+		  maven_set_reg(md->client, 0x22, p->value);
+		}
+		break;
+		case V4L2_CID_HUE:
+		{
+		  maven_set_reg(md->client, 0x25, p->value);
+		}
+		break;
+		case V4L2_CID_GAMMA:
+		{
+		  const struct maven_gamma* g;
+		  g = maven_compute_gamma(md);
+		  maven_set_reg(md->client, 0x83, g->reg83);
+		  maven_set_reg(md->client, 0x84, g->reg84);
+		  maven_set_reg(md->client, 0x85, g->reg85);
+		  maven_set_reg(md->client, 0x86, g->reg86);
+		  maven_set_reg(md->client, 0x87, g->reg87);
+		  maven_set_reg(md->client, 0x88, g->reg88);
+		  maven_set_reg(md->client, 0x89, g->reg89);
+		  maven_set_reg(md->client, 0x8a, g->reg8a);
+		  maven_set_reg(md->client, 0x8b, g->reg8b);
+		}
+		break;
+		case MATROXFB_CID_TESTOUT:
+		{
+			unsigned char val 
+			  = maven_get_reg(md->client, 0x8d);
+			if (p->value) val |= 0x10;
+			else          val &= ~0x10;
+			maven_set_reg(md->client, 0x8d, val);
+		}
+		break;
+		case MATROXFB_CID_DEFLICKER:
+		{
+		  maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
+		}
+		break;
+	}
+	
+
+	return 0;
+}
+
+static int maven_get_control (struct maven_data* md, 
+			      struct v4l2_control *p) {
+	int i;
+	
+	i = get_ctrl_id(p->id);
+	if (i < 0) return -EINVAL;
+	p->value = *get_ctrl_ptr(md, i);
+	return 0;
+}
+
+/******************************************************/
+
+static int maven_out_compute(void* md, struct my_timming* mt) {
+#define mdinfo ((struct maven_data*)md)
+#define minfo (mdinfo->primary_head)
+	return maven_compute_timming(md, mt, &minfo->hw.maven);
+#undef minfo
+#undef mdinfo
+}
+
+static int maven_out_program(void* md) {
+#define mdinfo ((struct maven_data*)md)
+#define minfo (mdinfo->primary_head)
+	return maven_program_timming(md, &minfo->hw.maven);
+#undef minfo
+#undef mdinfo
+}
+
+static int maven_out_start(void* md) {
+	return maven_resync(md);
+}
+
+static int maven_out_verify_mode(void* md, u_int32_t arg) {
+	switch (arg) {
+		case MATROXFB_OUTPUT_MODE_PAL:
+		case MATROXFB_OUTPUT_MODE_NTSC:
+		case MATROXFB_OUTPUT_MODE_MONITOR:
+			return 0;
+	}
+	return -EINVAL;
+}
+
+static int maven_out_get_queryctrl(void* md, struct v4l2_queryctrl* p) {
+        return maven_get_queryctrl(md, p);
+}
+
+static int maven_out_get_ctrl(void* md, struct v4l2_control* p) {
+	return maven_get_control(md, p);
+}
+
+static int maven_out_set_ctrl(void* md, struct v4l2_control* p) {
+	return maven_set_control(md, p);
+}
+
+static struct matrox_altout maven_altout = {
+	.name		= "Secondary output",
+	.compute	= maven_out_compute,
+	.program	= maven_out_program,
+	.start		= maven_out_start,
+	.verifymode	= maven_out_verify_mode,
+	.getqueryctrl	= maven_out_get_queryctrl,
+	.getctrl	= maven_out_get_ctrl,
+	.setctrl	= maven_out_set_ctrl,
+};
+
+static int maven_init_client(struct i2c_client* clnt) {
+	struct maven_data* md = i2c_get_clientdata(clnt);
+	struct matrox_fb_info *minfo = container_of(clnt->adapter,
+						    struct i2c_bit_adapter,
+						    adapter)->minfo;
+
+	md->primary_head = minfo;
+	md->client = clnt;
+	down_write(&minfo->altout.lock);
+	minfo->outputs[1].output = &maven_altout;
+	minfo->outputs[1].src = minfo->outputs[1].default_src;
+	minfo->outputs[1].data = md;
+	minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+	up_write(&minfo->altout.lock);
+	if (maven_get_reg(clnt, 0xB2) < 0x14) {
+		md->version = MGATVO_B;
+		/* Tweak some things for this old chip */
+	} else {
+		md->version = MGATVO_C;
+	}
+	/*
+	 * Set all parameters to its initial values.
+	 */
+	{
+		unsigned int i;
+
+		for (i = 0; i < MAVCTRLS; ++i) {
+			*get_ctrl_ptr(md, i) = maven_controls[i].desc.default_value;
+		}
+	}
+
+	return 0;
+}
+
+static int maven_shutdown_client(struct i2c_client* clnt) {
+	struct maven_data* md = i2c_get_clientdata(clnt);
+
+	if (md->primary_head) {
+		struct matrox_fb_info *minfo = md->primary_head;
+
+		down_write(&minfo->altout.lock);
+		minfo->outputs[1].src = MATROXFB_SRC_NONE;
+		minfo->outputs[1].output = NULL;
+		minfo->outputs[1].data = NULL;
+		minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
+		up_write(&minfo->altout.lock);
+		md->primary_head = NULL;
+	}
+	return 0;
+}
+
+static int maven_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int err = -ENODEV;
+	struct maven_data* data;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA |
+					      I2C_FUNC_SMBUS_BYTE_DATA |
+					      I2C_FUNC_NOSTART |
+					      I2C_FUNC_PROTOCOL_MANGLING))
+		goto ERROR0;
+	if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto ERROR0;
+	}
+	i2c_set_clientdata(client, data);
+	err = maven_init_client(client);
+	if (err)
+		goto ERROR4;
+	return 0;
+ERROR4:;
+	kfree(data);
+ERROR0:;
+	return err;
+}
+
+static int maven_remove(struct i2c_client *client)
+{
+	maven_shutdown_client(client);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id maven_id[] = {
+	{ "maven", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, maven_id);
+
+static struct i2c_driver maven_driver={
+	.driver = {
+		.name	= "maven",
+	},
+	.probe		= maven_probe,
+	.remove		= maven_remove,
+	.id_table	= maven_id,
+};
+
+module_i2c_driver(maven_driver);
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_maven.h b/drivers/video/fbdev/matrox/matroxfb_maven.h
new file mode 100644
index 000000000000..99eddec9f30c
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_maven.h
@@ -0,0 +1,20 @@
+#ifndef __MATROXFB_MAVEN_H__
+#define __MATROXFB_MAVEN_H__
+
+#include <linux/ioctl.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include "matroxfb_base.h"
+
+struct i2c_bit_adapter {
+	struct i2c_adapter		adapter;
+	int				initialized;
+	struct i2c_algo_bit_data	bac;
+	struct matrox_fb_info*		minfo;
+	struct {
+		unsigned int		data;
+		unsigned int		clock;
+				      } mask;
+};
+
+#endif /* __MATROXFB_MAVEN_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_misc.c b/drivers/video/fbdev/matrox/matroxfb_misc.c
new file mode 100644
index 000000000000..9948ca2a3046
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_misc.c
@@ -0,0 +1,815 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
+ *
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Portions Copyright (c) 2001 Matrox Graphics Inc.
+ *
+ * Version: 1.65 2002/08/14
+ *
+ * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
+ *
+ * Contributors: "menion?" <menion@mindless.com>
+ *                     Betatesting, fixes, ideas
+ *
+ *               "Kurt Garloff" <garloff@suse.de>
+ *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
+ *
+ *               "Tom Rini" <trini@kernel.crashing.org>
+ *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
+ *
+ *               "Bibek Sahu" <scorpio@dodds.net>
+ *                     Access device through readb|w|l and write b|w|l
+ *                     Extensive debugging stuff
+ *
+ *               "Daniel Haun" <haund@usa.net>
+ *                     Testing, hardware cursor fixes
+ *
+ *               "Scott Wood" <sawst46+@pitt.edu>
+ *                     Fixes
+ *
+ *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
+ *                     Betatesting
+ *
+ *               "Kelly French" <targon@hazmat.com>
+ *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
+ *                     Betatesting, bug reporting
+ *
+ *               "Pablo Bianucci" <pbian@pccp.com.ar>
+ *                     Fixes, ideas, betatesting
+ *
+ *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
+ *                     Fixes, enhandcements, ideas, betatesting
+ *
+ *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
+ *                     PPC betatesting, PPC support, backward compatibility
+ *
+ *               "Paul Womar" <Paul@pwomar.demon.co.uk>
+ *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
+ *                     PPC betatesting
+ *
+ *               "Thomas Pornin" <pornin@bolet.ens.fr>
+ *                     Alpha betatesting
+ *
+ *               "Pieter van Leuven" <pvl@iae.nl>
+ *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
+ *                     G100 testing
+ *
+ *               "H. Peter Arvin" <hpa@transmeta.com>
+ *                     Ideas
+ *
+ *               "Cort Dougan" <cort@cs.nmt.edu>
+ *                     CHRP fixes and PReP cleanup
+ *
+ *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
+ *                     G400 support
+ *
+ *               "David C. Hansen" <haveblue@us.ibm.com>
+ *                     Fixes
+ *
+ *               "Ian Romanick" <idr@us.ibm.com>
+ *                     Find PInS data in BIOS on PowerPC systems.
+ *
+ * (following author is not in any relation with this code, but his code
+ *  is included in this driver)
+ *
+ * Based on framebuffer driver for VBE 2.0 compliant graphic boards
+ *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * (following author is not in any relation with this code, but his ideas
+ *  were used when writing this driver)
+ *
+ *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
+ *
+ */
+
+
+#include "matroxfb_misc.h"
+#include <linux/interrupt.h>
+#include <linux/matroxfb.h>
+
+void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg, int val)
+{
+	DBG_REG(__func__)
+	mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+	mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
+}
+
+int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg)
+{
+	DBG_REG(__func__)
+	mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+	return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
+}
+
+void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
+	unsigned int pixclock = var->pixclock;
+
+	DBG(__func__)
+
+	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
+	mt->pixclock = 1000000000 / pixclock;
+	if (mt->pixclock < 1) mt->pixclock = 1;
+	mt->mnp = -1;
+	mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
+	mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
+	mt->HDisplay = var->xres;
+	mt->HSyncStart = mt->HDisplay + var->right_margin;
+	mt->HSyncEnd = mt->HSyncStart + var->hsync_len;
+	mt->HTotal = mt->HSyncEnd + var->left_margin;
+	mt->VDisplay = var->yres;
+	mt->VSyncStart = mt->VDisplay + var->lower_margin;
+	mt->VSyncEnd = mt->VSyncStart + var->vsync_len;
+	mt->VTotal = mt->VSyncEnd + var->upper_margin;
+	mt->sync = var->sync;
+}
+
+int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
+		unsigned int* in, unsigned int* feed, unsigned int* post) {
+	unsigned int bestdiff = ~0;
+	unsigned int bestvco = 0;
+	unsigned int fxtal = pll->ref_freq;
+	unsigned int fwant;
+	unsigned int p;
+
+	DBG(__func__)
+
+	fwant = freq;
+
+#ifdef DEBUG
+	printk(KERN_ERR "post_shift_max: %d\n", pll->post_shift_max);
+	printk(KERN_ERR "ref_freq: %d\n", pll->ref_freq);
+	printk(KERN_ERR "freq: %d\n", freq);
+	printk(KERN_ERR "vco_freq_min: %d\n", pll->vco_freq_min);
+	printk(KERN_ERR "in_div_min: %d\n", pll->in_div_min);
+	printk(KERN_ERR "in_div_max: %d\n", pll->in_div_max);
+	printk(KERN_ERR "feed_div_min: %d\n", pll->feed_div_min);
+	printk(KERN_ERR "feed_div_max: %d\n", pll->feed_div_max);
+	printk(KERN_ERR "fmax: %d\n", fmax);
+#endif
+	for (p = 1; p <= pll->post_shift_max; p++) {
+		if (fwant * 2 > fmax)
+			break;
+		fwant *= 2;
+	}
+	if (fwant < pll->vco_freq_min) fwant = pll->vco_freq_min;
+	if (fwant > fmax) fwant = fmax;
+	for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
+		unsigned int m;
+
+		if (fwant < pll->vco_freq_min) break;
+		for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
+			unsigned int diff, fvco;
+			unsigned int n;
+
+			n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
+			if (n > pll->feed_div_max)
+				break;
+			if (n < pll->feed_div_min)
+				n = pll->feed_div_min;
+			fvco = (fxtal * (n + 1)) / (m + 1);
+			if (fvco < fwant)
+				diff = fwant - fvco;
+			else
+				diff = fvco - fwant;
+			if (diff < bestdiff) {
+				bestdiff = diff;
+				*post = p;
+				*in = m;
+				*feed = n;
+				bestvco = fvco;
+			}
+		}
+	}
+	dprintk(KERN_ERR "clk: %02X %02X %02X %d %d %d\n", *in, *feed, *post, fxtal, bestvco, fwant);
+	return bestvco;
+}
+
+int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming *m)
+{
+	unsigned int hd, hs, he, hbe, ht;
+	unsigned int vd, vs, ve, vt, lc;
+	unsigned int wd;
+	unsigned int divider;
+	int i;
+	struct matrox_hw_state * const hw = &minfo->hw;
+
+	DBG(__func__)
+
+	hw->SEQ[0] = 0x00;
+	hw->SEQ[1] = 0x01;	/* or 0x09 */
+	hw->SEQ[2] = 0x0F;	/* bitplanes */
+	hw->SEQ[3] = 0x00;
+	hw->SEQ[4] = 0x0E;
+	/* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millennium code... Hope that by MGA1064 too */
+	if (m->dblscan) {
+		m->VTotal <<= 1;
+		m->VDisplay <<= 1;
+		m->VSyncStart <<= 1;
+		m->VSyncEnd <<= 1;
+	}
+	if (m->interlaced) {
+		m->VTotal >>= 1;
+		m->VDisplay >>= 1;
+		m->VSyncStart >>= 1;
+		m->VSyncEnd >>= 1;
+	}
+
+	/* GCTL is ignored when not using 0xA0000 aperture */
+	hw->GCTL[0] = 0x00;
+	hw->GCTL[1] = 0x00;
+	hw->GCTL[2] = 0x00;
+	hw->GCTL[3] = 0x00;
+	hw->GCTL[4] = 0x00;
+	hw->GCTL[5] = 0x40;
+	hw->GCTL[6] = 0x05;
+	hw->GCTL[7] = 0x0F;
+	hw->GCTL[8] = 0xFF;
+
+	/* Whole ATTR is ignored in PowerGraphics mode */
+	for (i = 0; i < 16; i++)
+		hw->ATTR[i] = i;
+	hw->ATTR[16] = 0x41;
+	hw->ATTR[17] = 0xFF;
+	hw->ATTR[18] = 0x0F;
+	hw->ATTR[19] = 0x00;
+	hw->ATTR[20] = 0x00;
+
+	hd = m->HDisplay >> 3;
+	hs = m->HSyncStart >> 3;
+	he = m->HSyncEnd >> 3;
+	ht = m->HTotal >> 3;
+	/* standard timmings are in 8pixels, but for interleaved we cannot */
+	/* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
+	/* using 16 or more pixels per unit can save us */
+	divider = minfo->curr.final_bppShift;
+	while (divider & 3) {
+		hd >>= 1;
+		hs >>= 1;
+		he >>= 1;
+		ht >>= 1;
+		divider <<= 1;
+	}
+	divider = divider / 4;
+	/* divider can be from 1 to 8 */
+	while (divider > 8) {
+		hd <<= 1;
+		hs <<= 1;
+		he <<= 1;
+		ht <<= 1;
+		divider >>= 1;
+	}
+	hd = hd - 1;
+	hs = hs - 1;
+	he = he - 1;
+	ht = ht - 1;
+	vd = m->VDisplay - 1;
+	vs = m->VSyncStart - 1;
+	ve = m->VSyncEnd - 1;
+	vt = m->VTotal - 2;
+	lc = vd;
+	/* G200 cannot work with (ht & 7) == 6 */
+	if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
+		ht++;
+	hbe = ht;
+	wd = minfo->fbcon.var.xres_virtual * minfo->curr.final_bppShift / 64;
+
+	hw->CRTCEXT[0] = 0;
+	hw->CRTCEXT[5] = 0;
+	if (m->interlaced) {
+		hw->CRTCEXT[0] = 0x80;
+		hw->CRTCEXT[5] = (hs + he - ht) >> 1;
+		if (!m->dblscan)
+			wd <<= 1;
+		vt &= ~1;
+	}
+	hw->CRTCEXT[0] |=  (wd & 0x300) >> 4;
+	hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
+			  ((hd      & 0x100) >> 7) | /* blanking */
+			  ((hs      & 0x100) >> 6) | /* sync start */
+			   (hbe     & 0x040);	 /* end hor. blanking */
+	/* FIXME: Enable vidrst only on G400, and only if TV-out is used */
+	if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1)
+		hw->CRTCEXT[1] |= 0x88;		/* enable horizontal and vertical vidrst */
+	hw->CRTCEXT[2] =  ((vt & 0xC00) >> 10) |
+			  ((vd & 0x400) >>  8) |	/* disp end */
+			  ((vd & 0xC00) >>  7) |	/* vblanking start */
+			  ((vs & 0xC00) >>  5) |
+			  ((lc & 0x400) >>  3);
+	hw->CRTCEXT[3] = (divider - 1) | 0x80;
+	hw->CRTCEXT[4] = 0;
+
+	hw->CRTC[0] = ht-4;
+	hw->CRTC[1] = hd;
+	hw->CRTC[2] = hd;
+	hw->CRTC[3] = (hbe & 0x1F) | 0x80;
+	hw->CRTC[4] = hs;
+	hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
+	hw->CRTC[6] = vt & 0xFF;
+	hw->CRTC[7] = ((vt & 0x100) >> 8) |
+		      ((vd & 0x100) >> 7) |
+		      ((vs & 0x100) >> 6) |
+		      ((vd & 0x100) >> 5) |
+		      ((lc & 0x100) >> 4) |
+		      ((vt & 0x200) >> 4) |
+		      ((vd & 0x200) >> 3) |
+		      ((vs & 0x200) >> 2);
+	hw->CRTC[8] = 0x00;
+	hw->CRTC[9] = ((vd & 0x200) >> 4) |
+		      ((lc & 0x200) >> 3);
+	if (m->dblscan && !m->interlaced)
+		hw->CRTC[9] |= 0x80;
+	for (i = 10; i < 16; i++)
+		hw->CRTC[i] = 0x00;
+	hw->CRTC[16] = vs /* & 0xFF */;
+	hw->CRTC[17] = (ve & 0x0F) | 0x20;
+	hw->CRTC[18] = vd /* & 0xFF */;
+	hw->CRTC[19] = wd /* & 0xFF */;
+	hw->CRTC[20] = 0x00;
+	hw->CRTC[21] = vd /* & 0xFF */;
+	hw->CRTC[22] = (vt + 1) /* & 0xFF */;
+	hw->CRTC[23] = 0xC3;
+	hw->CRTC[24] = lc;
+	return 0;
+};
+
+void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo)
+{
+	int i;
+	struct matrox_hw_state * const hw = &minfo->hw;
+	CRITFLAGS
+
+	DBG(__func__)
+
+	dprintk(KERN_INFO "MiscOutReg: %02X\n", hw->MiscOutReg);
+	dprintk(KERN_INFO "SEQ regs:   ");
+	for (i = 0; i < 5; i++)
+		dprintk("%02X:", hw->SEQ[i]);
+	dprintk("\n");
+	dprintk(KERN_INFO "GDC regs:   ");
+	for (i = 0; i < 9; i++)
+		dprintk("%02X:", hw->GCTL[i]);
+	dprintk("\n");
+	dprintk(KERN_INFO "CRTC regs: ");
+	for (i = 0; i < 25; i++)
+		dprintk("%02X:", hw->CRTC[i]);
+	dprintk("\n");
+	dprintk(KERN_INFO "ATTR regs: ");
+	for (i = 0; i < 21; i++)
+		dprintk("%02X:", hw->ATTR[i]);
+	dprintk("\n");
+
+	CRITBEGIN
+
+	mga_inb(M_ATTR_RESET);
+	mga_outb(M_ATTR_INDEX, 0);
+	mga_outb(M_MISC_REG, hw->MiscOutReg);
+	for (i = 1; i < 5; i++)
+		mga_setr(M_SEQ_INDEX, i, hw->SEQ[i]);
+	mga_setr(M_CRTC_INDEX, 17, hw->CRTC[17] & 0x7F);
+	for (i = 0; i < 25; i++)
+		mga_setr(M_CRTC_INDEX, i, hw->CRTC[i]);
+	for (i = 0; i < 9; i++)
+		mga_setr(M_GRAPHICS_INDEX, i, hw->GCTL[i]);
+	for (i = 0; i < 21; i++) {
+		mga_inb(M_ATTR_RESET);
+		mga_outb(M_ATTR_INDEX, i);
+		mga_outb(M_ATTR_INDEX, hw->ATTR[i]);
+	}
+	mga_outb(M_PALETTE_MASK, 0xFF);
+	mga_outb(M_DAC_REG, 0x00);
+	for (i = 0; i < 768; i++)
+		mga_outb(M_DAC_VAL, hw->DACpal[i]);
+	mga_inb(M_ATTR_RESET);
+	mga_outb(M_ATTR_INDEX, 0x20);
+
+	CRITEND
+}
+
+static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) {
+	unsigned int b0 = readb(pins);
+	
+	if (b0 == 0x2E && readb(pins+1) == 0x41) {
+		unsigned int pins_len = readb(pins+2);
+		unsigned int i;
+		unsigned char cksum;
+		unsigned char* dst = bd->pins;
+
+		if (pins_len < 3 || pins_len > 128) {
+			return;
+		}
+		*dst++ = 0x2E;
+		*dst++ = 0x41;
+		*dst++ = pins_len;
+		cksum = 0x2E + 0x41 + pins_len;
+		for (i = 3; i < pins_len; i++) {
+			cksum += *dst++ = readb(pins+i);
+		}
+		if (cksum) {
+			return;
+		}
+		bd->pins_len = pins_len;
+	} else if (b0 == 0x40 && readb(pins+1) == 0x00) {
+		unsigned int i;
+		unsigned char* dst = bd->pins;
+
+		*dst++ = 0x40;
+		*dst++ = 0;
+		for (i = 2; i < 0x40; i++) {
+			*dst++ = readb(pins+i);
+		}
+		bd->pins_len = 0x40;
+	}
+}
+
+static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) {
+	unsigned int pcir_offset;
+	
+	pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
+	if (pcir_offset >= 26 && pcir_offset < 0xFFE0 &&
+	    readb(vbios + pcir_offset    ) == 'P' &&
+	    readb(vbios + pcir_offset + 1) == 'C' &&
+	    readb(vbios + pcir_offset + 2) == 'I' &&
+	    readb(vbios + pcir_offset + 3) == 'R') {
+		unsigned char h;
+
+		h = readb(vbios + pcir_offset + 0x12);
+		bd->version.vMaj = (h >> 4) & 0xF;
+		bd->version.vMin = h & 0xF;
+		bd->version.vRev = readb(vbios + pcir_offset + 0x13);
+	} else {
+		unsigned char h;
+
+		h = readb(vbios + 5);
+		bd->version.vMaj = (h >> 4) & 0xF;
+		bd->version.vMin = h & 0xF;
+		bd->version.vRev = 0;
+	}
+}
+
+static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) {
+	unsigned char b;
+	
+	b = readb(vbios + 0x7FF1);
+	if (b == 0xFF) {
+		b = 0;
+	}
+	bd->output.state = b;
+}
+
+static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) {
+	unsigned int i;
+	
+	/* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
+	bd->output.tvout = 0;
+	if (readb(vbios + 0x1D) != 'I' ||
+	    readb(vbios + 0x1E) != 'B' ||
+	    readb(vbios + 0x1F) != 'M' ||
+	    readb(vbios + 0x20) != ' ') {
+	    	return;
+	}
+	for (i = 0x2D; i < 0x2D + 128; i++) {
+		unsigned char b = readb(vbios + i);
+		
+		if (b == '(' && readb(vbios + i + 1) == 'V') {
+			if (readb(vbios + i + 6) == 'T' &&
+			    readb(vbios + i + 7) == 'V' &&
+			    readb(vbios + i + 8) == 'O') {
+				bd->output.tvout = 1;
+			}
+			return;
+		}
+		if (b == 0)
+			break;
+	}
+}
+
+static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
+	unsigned int pins_offset;
+	
+	if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
+		return;
+	}
+	bd->bios_valid = 1;
+	get_bios_version(vbios, bd);
+	get_bios_output(vbios, bd);
+	get_bios_tvout(vbios, bd);
+#if defined(__powerpc__)
+	/* On PowerPC cards, the PInS offset isn't stored at the end of the
+	 * BIOS image.  Instead, you must search the entire BIOS image for
+	 * the magic PInS signature.
+	 *
+	 * This actually applies to all OpenFirmware base cards.  Since these
+	 * cards could be put in a MIPS or SPARC system, should the condition
+	 * be something different?
+	 */
+	for ( pins_offset = 0 ; pins_offset <= 0xFF80 ; pins_offset++ ) {
+		unsigned char header[3];
+
+		header[0] = readb(vbios + pins_offset);
+		header[1] = readb(vbios + pins_offset + 1);
+		header[2] = readb(vbios + pins_offset + 2);
+		if ( (header[0] == 0x2E) && (header[1] == 0x41)
+		     && ((header[2] == 0x40) || (header[2] == 0x80)) ) {
+			printk(KERN_INFO "PInS data found at offset %u\n",
+			       pins_offset);
+			get_pins(vbios + pins_offset, bd);
+			break;
+		}
+	}
+#else
+	pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
+	if (pins_offset <= 0xFF80) {
+		get_pins(vbios + pins_offset, bd);
+	}
+#endif
+}
+
+static int parse_pins1(struct matrox_fb_info *minfo,
+		       const struct matrox_bios *bd)
+{
+	unsigned int maxdac;
+
+	switch (bd->pins[22]) {
+		case 0:		maxdac = 175000; break;
+		case 1:		maxdac = 220000; break;
+		default:	maxdac = 240000; break;
+	}
+	if (get_unaligned_le16(bd->pins + 24)) {
+		maxdac = get_unaligned_le16(bd->pins + 24) * 10;
+	}
+	minfo->limits.pixel.vcomax = maxdac;
+	minfo->values.pll.system = get_unaligned_le16(bd->pins + 28) ?
+		get_unaligned_le16(bd->pins + 28) * 10 : 50000;
+	/* ignore 4MB, 8MB, module clocks */
+	minfo->features.pll.ref_freq = 14318;
+	minfo->values.reg.mctlwtst	= 0x00030101;
+	return 0;
+}
+
+static void default_pins1(struct matrox_fb_info *minfo)
+{
+	/* Millennium */
+	minfo->limits.pixel.vcomax	= 220000;
+	minfo->values.pll.system	=  50000;
+	minfo->features.pll.ref_freq	=  14318;
+	minfo->values.reg.mctlwtst	= 0x00030101;
+}
+
+static int parse_pins2(struct matrox_fb_info *minfo,
+		       const struct matrox_bios *bd)
+{
+	minfo->limits.pixel.vcomax	=
+	minfo->limits.system.vcomax	= (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000);
+	minfo->values.reg.mctlwtst	= ((bd->pins[51] & 0x01) ? 0x00000001 : 0) |
+					  ((bd->pins[51] & 0x02) ? 0x00000100 : 0) |
+					  ((bd->pins[51] & 0x04) ? 0x00010000 : 0) |
+					  ((bd->pins[51] & 0x08) ? 0x00020000 : 0);
+	minfo->values.pll.system	= (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000);
+	minfo->features.pll.ref_freq	= 14318;
+	return 0;
+}
+
+static void default_pins2(struct matrox_fb_info *minfo)
+{
+	/* Millennium II, Mystique */
+	minfo->limits.pixel.vcomax	=
+	minfo->limits.system.vcomax	= 230000;
+	minfo->values.reg.mctlwtst	= 0x00030101;
+	minfo->values.pll.system	=  50000;
+	minfo->features.pll.ref_freq	=  14318;
+}
+
+static int parse_pins3(struct matrox_fb_info *minfo,
+		       const struct matrox_bios *bd)
+{
+	minfo->limits.pixel.vcomax	=
+	minfo->limits.system.vcomax	= (bd->pins[36] == 0xFF) ? 230000			: ((bd->pins[36] + 100) * 1000);
+	minfo->values.reg.mctlwtst	= get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ?
+		0x01250A21 : get_unaligned_le32(bd->pins + 48);
+	/* memory config */
+	minfo->values.reg.memrdbk	= ((bd->pins[57] << 21) & 0x1E000000) |
+					  ((bd->pins[57] << 22) & 0x00C00000) |
+					  ((bd->pins[56] <<  1) & 0x000001E0) |
+					  ( bd->pins[56]        & 0x0000000F);
+	minfo->values.reg.opt		= (bd->pins[54] & 7) << 10;
+	minfo->values.reg.opt2		= bd->pins[58] << 12;
+	minfo->features.pll.ref_freq	= (bd->pins[52] & 0x20) ? 14318 : 27000;
+	return 0;
+}
+
+static void default_pins3(struct matrox_fb_info *minfo)
+{
+	/* G100, G200 */
+	minfo->limits.pixel.vcomax	=
+	minfo->limits.system.vcomax	= 230000;
+	minfo->values.reg.mctlwtst	= 0x01250A21;
+	minfo->values.reg.memrdbk	= 0x00000000;
+	minfo->values.reg.opt		= 0x00000C00;
+	minfo->values.reg.opt2		= 0x00000000;
+	minfo->features.pll.ref_freq	=  27000;
+}
+
+static int parse_pins4(struct matrox_fb_info *minfo,
+		       const struct matrox_bios *bd)
+{
+	minfo->limits.pixel.vcomax	= (bd->pins[ 39] == 0xFF) ? 230000			: bd->pins[ 39] * 4000;
+	minfo->limits.system.vcomax	= (bd->pins[ 38] == 0xFF) ? minfo->limits.pixel.vcomax	: bd->pins[ 38] * 4000;
+	minfo->values.reg.mctlwtst	= get_unaligned_le32(bd->pins + 71);
+	minfo->values.reg.memrdbk	= ((bd->pins[87] << 21) & 0x1E000000) |
+					  ((bd->pins[87] << 22) & 0x00C00000) |
+					  ((bd->pins[86] <<  1) & 0x000001E0) |
+					  ( bd->pins[86]        & 0x0000000F);
+	minfo->values.reg.opt		= ((bd->pins[53] << 15) & 0x00400000) |
+					  ((bd->pins[53] << 22) & 0x10000000) |
+					  ((bd->pins[53] <<  7) & 0x00001C00);
+	minfo->values.reg.opt3		= get_unaligned_le32(bd->pins + 67);
+	minfo->values.pll.system	= (bd->pins[ 65] == 0xFF) ? 200000 			: bd->pins[ 65] * 4000;
+	minfo->features.pll.ref_freq	= (bd->pins[ 92] & 0x01) ? 14318 : 27000;
+	return 0;
+}
+
+static void default_pins4(struct matrox_fb_info *minfo)
+{
+	/* G400 */
+	minfo->limits.pixel.vcomax	=
+	minfo->limits.system.vcomax	= 252000;
+	minfo->values.reg.mctlwtst	= 0x04A450A1;
+	minfo->values.reg.memrdbk	= 0x000000E7;
+	minfo->values.reg.opt		= 0x10000400;
+	minfo->values.reg.opt3		= 0x0190A419;
+	minfo->values.pll.system	= 200000;
+	minfo->features.pll.ref_freq	= 27000;
+}
+
+static int parse_pins5(struct matrox_fb_info *minfo,
+		       const struct matrox_bios *bd)
+{
+	unsigned int mult;
+	
+	mult = bd->pins[4]?8000:6000;
+	
+	minfo->limits.pixel.vcomax	= (bd->pins[ 38] == 0xFF) ? 600000			: bd->pins[ 38] * mult;
+	minfo->limits.system.vcomax	= (bd->pins[ 36] == 0xFF) ? minfo->limits.pixel.vcomax	: bd->pins[ 36] * mult;
+	minfo->limits.video.vcomax	= (bd->pins[ 37] == 0xFF) ? minfo->limits.system.vcomax	: bd->pins[ 37] * mult;
+	minfo->limits.pixel.vcomin	= (bd->pins[123] == 0xFF) ? 256000			: bd->pins[123] * mult;
+	minfo->limits.system.vcomin	= (bd->pins[121] == 0xFF) ? minfo->limits.pixel.vcomin	: bd->pins[121] * mult;
+	minfo->limits.video.vcomin	= (bd->pins[122] == 0xFF) ? minfo->limits.system.vcomin	: bd->pins[122] * mult;
+	minfo->values.pll.system	=
+	minfo->values.pll.video		= (bd->pins[ 92] == 0xFF) ? 284000			: bd->pins[ 92] * 4000;
+	minfo->values.reg.opt		= get_unaligned_le32(bd->pins + 48);
+	minfo->values.reg.opt2		= get_unaligned_le32(bd->pins + 52);
+	minfo->values.reg.opt3		= get_unaligned_le32(bd->pins + 94);
+	minfo->values.reg.mctlwtst	= get_unaligned_le32(bd->pins + 98);
+	minfo->values.reg.memmisc	= get_unaligned_le32(bd->pins + 102);
+	minfo->values.reg.memrdbk	= get_unaligned_le32(bd->pins + 106);
+	minfo->features.pll.ref_freq	= (bd->pins[110] & 0x01) ? 14318 : 27000;
+	minfo->values.memory.ddr	= (bd->pins[114] & 0x60) == 0x20;
+	minfo->values.memory.dll	= (bd->pins[115] & 0x02) != 0;
+	minfo->values.memory.emrswen	= (bd->pins[115] & 0x01) != 0;
+	minfo->values.reg.maccess	= minfo->values.memory.emrswen ? 0x00004000 : 0x00000000;
+	if (bd->pins[115] & 4) {
+		minfo->values.reg.mctlwtst_core = minfo->values.reg.mctlwtst;
+	} else {
+		u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 };
+		minfo->values.reg.mctlwtst_core = (minfo->values.reg.mctlwtst & ~7) |
+						  wtst_xlat[minfo->values.reg.mctlwtst & 7];
+	}
+	minfo->max_pixel_clock_panellink = bd->pins[47] * 4000;
+	return 0;
+}
+
+static void default_pins5(struct matrox_fb_info *minfo)
+{
+	/* Mine 16MB G450 with SDRAM DDR */
+	minfo->limits.pixel.vcomax	=
+	minfo->limits.system.vcomax	=
+	minfo->limits.video.vcomax	= 600000;
+	minfo->limits.pixel.vcomin	=
+	minfo->limits.system.vcomin	=
+	minfo->limits.video.vcomin	= 256000;
+	minfo->values.pll.system	=
+	minfo->values.pll.video		= 284000;
+	minfo->values.reg.opt		= 0x404A1160;
+	minfo->values.reg.opt2		= 0x0000AC00;
+	minfo->values.reg.opt3		= 0x0090A409;
+	minfo->values.reg.mctlwtst_core	=
+	minfo->values.reg.mctlwtst	= 0x0C81462B;
+	minfo->values.reg.memmisc	= 0x80000004;
+	minfo->values.reg.memrdbk	= 0x01001103;
+	minfo->features.pll.ref_freq	= 27000;
+	minfo->values.memory.ddr	= 1;
+	minfo->values.memory.dll	= 1;
+	minfo->values.memory.emrswen	= 1;
+	minfo->values.reg.maccess	= 0x00004000;
+}
+
+static int matroxfb_set_limits(struct matrox_fb_info *minfo,
+			       const struct matrox_bios *bd)
+{
+	unsigned int pins_version;
+	static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 };
+
+	switch (minfo->chip) {
+		case MGA_2064:	default_pins1(minfo); break;
+		case MGA_2164:
+		case MGA_1064:
+		case MGA_1164:	default_pins2(minfo); break;
+		case MGA_G100:
+		case MGA_G200:	default_pins3(minfo); break;
+		case MGA_G400:	default_pins4(minfo); break;
+		case MGA_G450:
+		case MGA_G550:	default_pins5(minfo); break;
+	}
+	if (!bd->bios_valid) {
+		printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n");
+		return -1;
+	}
+	if (bd->pins_len < 64) {
+		printk(KERN_INFO "matroxfb: BIOS on your Matrox device does not contain powerup info\n");
+		return -1;
+	}
+	if (bd->pins[0] == 0x2E && bd->pins[1] == 0x41) {
+		pins_version = bd->pins[5];
+		if (pins_version < 2 || pins_version > 5) {
+			printk(KERN_INFO "matroxfb: Unknown version (%u) of powerup info\n", pins_version);
+			return -1;
+		}
+	} else {
+		pins_version = 1;
+	}
+	if (bd->pins_len != pinslen[pins_version - 1]) {
+		printk(KERN_INFO "matroxfb: Invalid powerup info\n");
+		return -1;
+	}
+	switch (pins_version) {
+		case 1:
+			return parse_pins1(minfo, bd);
+		case 2:
+			return parse_pins2(minfo, bd);
+		case 3:
+			return parse_pins3(minfo, bd);
+		case 4:
+			return parse_pins4(minfo, bd);
+		case 5:
+			return parse_pins5(minfo, bd);
+		default:
+			printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version);
+			return -1;
+	}
+}
+
+void matroxfb_read_pins(struct matrox_fb_info *minfo)
+{
+	u32 opt;
+	u32 biosbase;
+	u32 fbbase;
+	struct pci_dev *pdev = minfo->pcidev;
+	
+	memset(&minfo->bios, 0, sizeof(minfo->bios));
+	pci_read_config_dword(pdev, PCI_OPTION_REG, &opt);
+	pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM);
+	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase);
+	pci_read_config_dword(pdev, minfo->devflags.fbResource, &fbbase);
+	pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+	parse_bios(vaddr_va(minfo->video.vbase), &minfo->bios);
+	pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase);
+	pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
+#ifdef CONFIG_X86
+	if (!minfo->bios.bios_valid) {
+		unsigned char __iomem* b;
+
+		b = ioremap(0x000C0000, 65536);
+		if (!b) {
+			printk(KERN_INFO "matroxfb: Unable to map legacy BIOS\n");
+		} else {
+			unsigned int ven = readb(b+0x64+0) | (readb(b+0x64+1) << 8);
+			unsigned int dev = readb(b+0x64+2) | (readb(b+0x64+3) << 8);
+			
+			if (ven != pdev->vendor || dev != pdev->device) {
+				printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n",
+					ven, dev, pdev->vendor, pdev->device);
+			} else {
+				parse_bios(b, &minfo->bios);
+			}
+			iounmap(b);
+		}
+	}
+#endif
+	matroxfb_set_limits(minfo, &minfo->bios);
+	printk(KERN_INFO "PInS memtype = %u\n",
+	       (minfo->values.reg.opt & 0x1C00) >> 10);
+}
+
+EXPORT_SYMBOL(matroxfb_DAC_in);
+EXPORT_SYMBOL(matroxfb_DAC_out);
+EXPORT_SYMBOL(matroxfb_var2my);
+EXPORT_SYMBOL(matroxfb_PLL_calcclock);
+EXPORT_SYMBOL(matroxfb_vgaHWinit);		/* DAC1064, Ti3026 */
+EXPORT_SYMBOL(matroxfb_vgaHWrestore);		/* DAC1064, Ti3026 */
+EXPORT_SYMBOL(matroxfb_read_pins);
+
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_misc.h b/drivers/video/fbdev/matrox/matroxfb_misc.h
new file mode 100644
index 000000000000..351c823f1f74
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_misc.h
@@ -0,0 +1,21 @@
+#ifndef __MATROXFB_MISC_H__
+#define __MATROXFB_MISC_H__
+
+#include "matroxfb_base.h"
+
+/* also for modules */
+int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
+	unsigned int* in, unsigned int* feed, unsigned int* post);
+static inline int PLL_calcclock(const struct matrox_fb_info *minfo,
+				unsigned int freq, unsigned int fmax,
+				unsigned int *in, unsigned int *feed,
+				unsigned int *post)
+{
+	return matroxfb_PLL_calcclock(&minfo->features.pll, freq, fmax, in, feed, post);
+}
+
+int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming* m);
+void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo);
+void matroxfb_read_pins(struct matrox_fb_info *minfo);
+
+#endif	/* __MATROXFB_MISC_H__ */
diff --git a/drivers/video/fbdev/maxinefb.c b/drivers/video/fbdev/maxinefb.c
new file mode 100644
index 000000000000..5cf52d3c8e75
--- /dev/null
+++ b/drivers/video/fbdev/maxinefb.c
@@ -0,0 +1,177 @@
+/*
+ *      linux/drivers/video/maxinefb.c
+ *
+ *	DECstation 5000/xx onboard framebuffer support ... derived from:
+ *	"HP300 Topcat framebuffer support (derived from macfb of all things)
+ *	Phil Blundell <philb@gnu.org> 1998", the original code can be
+ *      found in the file hpfb.c in the same directory.
+ *
+ *      DECstation related code Copyright (C) 1999,2000,2001 by
+ *      Michael Engel <engel@unix-ag.org> and
+ *      Karsten Merker <merker@linuxtag.org>.
+ *      This file is subject to the terms and conditions of the GNU General
+ *      Public License.  See the file COPYING in the main directory of this
+ *      archive for more details.
+ *
+ */
+
+/*
+ * Changes:
+ * 2001/01/27 removed debugging and testing code, fixed fb_ops
+ *            initialization which had caused a crash before,
+ *            general cleanup, first official release (KM)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <video/maxinefb.h>
+
+/* bootinfo.h defines the machine type values, needed when checking */
+/* whether are really running on a maxine, KM                       */
+#include <asm/bootinfo.h>
+
+static struct fb_info fb_info;
+
+static struct fb_var_screeninfo maxinefb_defined = {
+	.xres =		1024,
+	.yres =		768,
+	.xres_virtual =	1024,
+	.yres_virtual =	768,
+	.bits_per_pixel =8,
+	.activate =	FB_ACTIVATE_NOW,
+	.height =	-1,
+	.width =	-1,
+	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo maxinefb_fix = {
+	.id =		"Maxine",
+	.smem_len =	(1024*768),
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.line_length =	1024,
+};
+
+/* Handle the funny Inmos RamDAC/video controller ... */
+
+void maxinefb_ims332_write_register(int regno, register unsigned int val)
+{
+	register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
+	unsigned char *wptr;
+
+	wptr = regs + 0xa0000 + (regno << 4);
+	*((volatile unsigned int *) (regs)) = (val >> 8) & 0xff00;
+	*((volatile unsigned short *) (wptr)) = val;
+}
+
+unsigned int maxinefb_ims332_read_register(int regno)
+{
+	register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
+	unsigned char *rptr;
+	register unsigned int j, k;
+
+	rptr = regs + 0x80000 + (regno << 4);
+	j = *((volatile unsigned short *) rptr);
+	k = *((volatile unsigned short *) regs);
+
+	return (j & 0xffff) | ((k & 0xff00) << 8);
+}
+
+/* Set the palette */
+static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp, struct fb_info *info)
+{
+	/* value to be written into the palette reg. */
+	unsigned long hw_colorvalue = 0;
+
+	if (regno > 255)
+		return 1;
+
+	red   >>= 8;    /* The cmap fields are 16 bits    */
+	green >>= 8;    /* wide, but the harware colormap */
+	blue  >>= 8;    /* registers are only 8 bits wide */
+
+	hw_colorvalue = (blue << 16) + (green << 8) + (red);
+
+	maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE + regno,
+				       hw_colorvalue);
+	return 0;
+}
+
+static struct fb_ops maxinefb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= maxinefb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+int __init maxinefb_init(void)
+{
+	unsigned long fboff;
+	unsigned long fb_start;
+	int i;
+
+	if (fb_get_options("maxinefb", NULL))
+		return -ENODEV;
+
+	/* Validate we're on the proper machine type */
+	if (mips_machtype != MACH_DS5000_XX) {
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "Maxinefb: Personal DECstation detected\n");
+	printk(KERN_INFO "Maxinefb: initializing onboard framebuffer\n");
+
+	/* Framebuffer display memory base address */
+	fb_start = DS5000_xx_ONBOARD_FBMEM_START;
+
+	/* Clear screen */
+	for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++)
+		*(volatile unsigned char *)fboff = 0x0;
+
+	maxinefb_fix.smem_start = fb_start;
+	
+	/* erase hardware cursor */
+	for (i = 0; i < 512; i++) {
+		maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i,
+					       0);
+		/*
+		   if (i&0x8 == 0)
+		   maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0x0f);
+		   else
+		   maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0xf0);
+		 */
+	}
+
+	fb_info.fbops = &maxinefb_ops;
+	fb_info.screen_base = (char *)maxinefb_fix.smem_start;
+	fb_info.var = maxinefb_defined;
+	fb_info.fix = maxinefb_fix;
+	fb_info.flags = FBINFO_DEFAULT;
+
+	fb_alloc_cmap(&fb_info.cmap, 256, 0);
+
+	if (register_framebuffer(&fb_info) < 0)
+		return 1;
+	return 0;
+}
+
+static void __exit maxinefb_exit(void)
+{
+	unregister_framebuffer(&fb_info);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+#endif
+module_init(maxinefb_init);
+module_exit(maxinefb_exit);
+
diff --git a/drivers/video/fbdev/mb862xx/Makefile b/drivers/video/fbdev/mb862xx/Makefile
new file mode 100644
index 000000000000..5707ed0e31a7
--- /dev/null
+++ b/drivers/video/fbdev/mb862xx/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the MB862xx framebuffer driver
+#
+
+obj-$(CONFIG_FB_MB862XX) += mb862xxfb.o
+
+mb862xxfb-y := mb862xxfbdrv.o mb862xxfb_accel.o
+mb862xxfb-$(CONFIG_FB_MB862XX_I2C) += mb862xx-i2c.o
diff --git a/drivers/video/fbdev/mb862xx/mb862xx-i2c.c b/drivers/video/fbdev/mb862xx/mb862xx-i2c.c
new file mode 100644
index 000000000000..c87e17afb3e2
--- /dev/null
+++ b/drivers/video/fbdev/mb862xx/mb862xx-i2c.c
@@ -0,0 +1,179 @@
+/*
+ * Coral-P(A)/Lime I2C adapter driver
+ *
+ * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+
+#include "mb862xxfb.h"
+#include "mb862xx_reg.h"
+
+static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+	u32 reg;
+
+	do {
+		udelay(10);
+		reg = inreg(i2c, GC_I2C_BCR);
+		if (reg & (I2C_INT | I2C_BER))
+			break;
+	} while (1);
+
+	return (reg & I2C_BER) ? 0 : 1;
+}
+
+static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_DAR, addr);
+	outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE);
+	outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START);
+	if (!mb862xx_i2c_wait_event(adap))
+		return -EIO;
+	par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
+	return par->i2c_rs;
+}
+
+static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_DAR, byte);
+	outreg(i2c, GC_I2C_BCR, I2C_START);
+	if (!mb862xx_i2c_wait_event(adap))
+		return -EIO;
+	return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
+}
+
+static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK));
+	if (!mb862xx_i2c_wait_event(adap))
+		return 0;
+	*byte = inreg(i2c, GC_I2C_DAR);
+	return 1;
+}
+
+static void mb862xx_i2c_stop(struct i2c_adapter *adap)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_BCR, I2C_STOP);
+	outreg(i2c, GC_I2C_CCR, I2C_DISABLE);
+	par->i2c_rs = 0;
+}
+
+static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m)
+{
+	int i, ret = 0;
+	int last = m->len - 1;
+
+	for (i = 0; i < m->len; i++) {
+		if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i == last)) {
+			ret = -EIO;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < m->len; i++) {
+		if (!mb862xx_i2c_write_byte(adap, m->buf[i])) {
+			ret = -EIO;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			int num)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+	struct i2c_msg *m;
+	int addr;
+	int i = 0, err = 0;
+
+	dev_dbg(par->dev, "%s: %d msgs\n", __func__, num);
+
+	for (i = 0; i < num; i++) {
+		m = &msgs[i];
+		if (!m->len) {
+			dev_dbg(par->dev, "%s: null msgs\n", __func__);
+			continue;
+		}
+		addr = m->addr;
+		if (m->flags & I2C_M_RD)
+			addr |= 1;
+
+		err = mb862xx_i2c_do_address(adap, addr);
+		if (err < 0)
+			break;
+		if (m->flags & I2C_M_RD)
+			err = mb862xx_i2c_read(adap, m);
+		else
+			err = mb862xx_i2c_write(adap, m);
+	}
+
+	if (i)
+		mb862xx_i2c_stop(adap);
+
+	return (err < 0) ? err : i;
+}
+
+static u32 mb862xx_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static const struct i2c_algorithm mb862xx_algo = {
+	.master_xfer	= mb862xx_xfer,
+	.functionality	= mb862xx_func,
+};
+
+static struct i2c_adapter mb862xx_i2c_adapter = {
+	.name		= "MB862xx I2C adapter",
+	.algo		= &mb862xx_algo,
+	.owner		= THIS_MODULE,
+};
+
+int mb862xx_i2c_init(struct mb862xxfb_par *par)
+{
+	int ret;
+
+	mb862xx_i2c_adapter.algo_data = par;
+	par->adap = &mb862xx_i2c_adapter;
+
+	ret = i2c_add_adapter(par->adap);
+	if (ret < 0) {
+		dev_err(par->dev, "failed to add %s\n",
+			mb862xx_i2c_adapter.name);
+	}
+	return ret;
+}
+
+void mb862xx_i2c_exit(struct mb862xxfb_par *par)
+{
+	if (par->adap) {
+		i2c_del_adapter(par->adap);
+		par->adap = NULL;
+	}
+}
diff --git a/drivers/video/fbdev/mb862xx/mb862xx_reg.h b/drivers/video/fbdev/mb862xx/mb862xx_reg.h
new file mode 100644
index 000000000000..9df48b8edc94
--- /dev/null
+++ b/drivers/video/fbdev/mb862xx/mb862xx_reg.h
@@ -0,0 +1,188 @@
+/*
+ * Fujitsu MB862xx Graphics Controller Registers/Bits
+ */
+
+#ifndef _MB862XX_REG_H
+#define _MB862XX_REG_H
+
+#define MB862XX_MMIO_BASE	0x01fc0000
+#define MB862XX_MMIO_HIGH_BASE	0x03fc0000
+#define MB862XX_I2C_BASE	0x0000c000
+#define MB862XX_DISP_BASE	0x00010000
+#define MB862XX_CAP_BASE	0x00018000
+#define MB862XX_DRAW_BASE	0x00030000
+#define MB862XX_GEO_BASE	0x00038000
+#define MB862XX_PIO_BASE	0x00038000
+#define MB862XX_MMIO_SIZE	0x40000
+
+/* Host interface/pio registers */
+#define GC_IST			0x00000020
+#define GC_IMASK		0x00000024
+#define GC_SRST			0x0000002c
+#define GC_CCF			0x00000038
+#define GC_RSW			0x0000005c
+#define GC_CID			0x000000f0
+#define GC_REVISION		0x00000084
+
+#define GC_CCF_CGE_100		0x00000000
+#define GC_CCF_CGE_133		0x00040000
+#define GC_CCF_CGE_166		0x00080000
+#define GC_CCF_COT_100		0x00000000
+#define GC_CCF_COT_133		0x00010000
+#define GC_CID_CNAME_MSK	0x0000ff00
+#define GC_CID_VERSION_MSK	0x000000ff
+
+/* define enabled interrupts hereby */
+#define GC_INT_EN		0x00000000
+
+/* Memory interface mode register */
+#define GC_MMR			0x0000fffc
+
+/* Display Controller registers */
+#define GC_DCM0			0x00000000
+#define GC_HTP			0x00000004
+#define GC_HDB_HDP		0x00000008
+#define GC_VSW_HSW_HSP		0x0000000c
+#define GC_VTR			0x00000010
+#define GC_VDP_VSP		0x00000014
+#define GC_WY_WX		0x00000018
+#define GC_WH_WW		0x0000001c
+#define GC_L0M			0x00000020
+#define GC_L0OA0		0x00000024
+#define GC_L0DA0		0x00000028
+#define GC_L0DY_L0DX		0x0000002c
+#define GC_L1M			0x00000030
+#define GC_L1DA			0x00000034
+#define GC_DCM1			0x00000100
+#define GC_L0EM			0x00000110
+#define GC_L0WY_L0WX		0x00000114
+#define GC_L0WH_L0WW		0x00000118
+#define GC_L1EM			0x00000120
+#define GC_L1WY_L1WX		0x00000124
+#define GC_L1WH_L1WW		0x00000128
+#define GC_DLS			0x00000180
+#define GC_DCM2			0x00000104
+#define GC_DCM3			0x00000108
+#define GC_CPM_CUTC		0x000000a0
+#define GC_CUOA0		0x000000a4
+#define GC_CUY0_CUX0		0x000000a8
+#define GC_CUOA1		0x000000ac
+#define GC_CUY1_CUX1		0x000000b0
+#define GC_L0PAL0		0x00000400
+
+#define GC_CPM_CEN0		0x00100000
+#define GC_CPM_CEN1		0x00200000
+#define GC_DCM1_DEN		0x80000000
+#define GC_DCM1_L1E		0x00020000
+#define GC_L1M_16		0x80000000
+#define GC_L1M_YC		0x40000000
+#define GC_L1M_CS		0x20000000
+
+#define GC_DCM01_ESY		0x00000004
+#define GC_DCM01_SC		0x00003f00
+#define GC_DCM01_RESV		0x00004000
+#define GC_DCM01_CKS		0x00008000
+#define GC_DCM01_L0E		0x00010000
+#define GC_DCM01_DEN		0x80000000
+#define GC_L0M_L0C_8		0x00000000
+#define GC_L0M_L0C_16		0x80000000
+#define GC_L0EM_L0EC_24		0x40000000
+#define GC_L0M_L0W_UNIT		64
+#define GC_L1EM_DM		0x02000000
+
+#define GC_DISP_REFCLK_400	400
+
+/* I2C */
+#define GC_I2C_BSR		0x00000000	/* BSR */
+#define GC_I2C_BCR		0x00000004	/* BCR */
+#define GC_I2C_CCR		0x00000008	/* CCR */
+#define GC_I2C_ADR		0x0000000C	/* ADR */
+#define GC_I2C_DAR		0x00000010	/* DAR */
+
+#define I2C_DISABLE		0x00000000
+#define I2C_STOP		0x00000000
+#define I2C_START		0x00000010
+#define I2C_REPEATED_START	0x00000030
+#define I2C_CLOCK_AND_ENABLE	0x0000003f
+#define I2C_READY		0x01
+#define I2C_INT			0x01
+#define I2C_INTE		0x02
+#define I2C_ACK			0x08
+#define I2C_BER			0x80
+#define I2C_BEIE		0x40
+#define I2C_TRX			0x80
+#define I2C_LRB			0x10
+
+/* Capture registers and bits */
+#define GC_CAP_VCM		0x00000000
+#define GC_CAP_CSC		0x00000004
+#define GC_CAP_VCS		0x00000008
+#define GC_CAP_CBM		0x00000010
+#define GC_CAP_CBOA		0x00000014
+#define GC_CAP_CBLA		0x00000018
+#define GC_CAP_IMG_START	0x0000001C
+#define GC_CAP_IMG_END		0x00000020
+#define GC_CAP_CMSS		0x00000048
+#define GC_CAP_CMDS		0x0000004C
+
+#define GC_VCM_VIE		0x80000000
+#define GC_VCM_CM		0x03000000
+#define GC_VCM_VS_PAL		0x00000002
+#define GC_CBM_OO		0x80000000
+#define GC_CBM_HRV		0x00000010
+#define GC_CBM_CBST		0x00000001
+
+/* Carmine specific */
+#define MB86297_DRAW_BASE		0x00020000
+#define MB86297_DISP0_BASE		0x00100000
+#define MB86297_DISP1_BASE		0x00140000
+#define MB86297_WRBACK_BASE		0x00180000
+#define MB86297_CAP0_BASE		0x00200000
+#define MB86297_CAP1_BASE		0x00280000
+#define MB86297_DRAMCTRL_BASE		0x00300000
+#define MB86297_CTRL_BASE		0x00400000
+#define MB86297_I2C_BASE		0x00500000
+
+#define GC_CTRL_STATUS			0x00000000
+#define GC_CTRL_INT_MASK		0x00000004
+#define GC_CTRL_CLK_ENABLE		0x0000000c
+#define GC_CTRL_SOFT_RST		0x00000010
+
+#define GC_CTRL_CLK_EN_DRAM		0x00000001
+#define GC_CTRL_CLK_EN_2D3D		0x00000002
+#define GC_CTRL_CLK_EN_DISP0		0x00000020
+#define GC_CTRL_CLK_EN_DISP1		0x00000040
+
+#define GC_2D3D_REV			0x000004b4
+#define GC_RE_REVISION			0x24240200
+
+/* define enabled interrupts hereby */
+#define GC_CARMINE_INT_EN		0x00000004
+
+/* DRAM controller */
+#define GC_DCTL_MODE_ADD		0x00000000
+#define GC_DCTL_SETTIME1_EMODE		0x00000004
+#define GC_DCTL_REFRESH_SETTIME2	0x00000008
+#define GC_DCTL_RSV0_STATES		0x0000000C
+#define GC_DCTL_RSV2_RSV1		0x00000010
+#define GC_DCTL_DDRIF2_DDRIF1		0x00000014
+#define GC_DCTL_IOCONT1_IOCONT0		0x00000024
+
+#define GC_DCTL_STATES_MSK		0x0000000f
+#define GC_DCTL_INIT_WAIT_CNT		3000
+#define GC_DCTL_INIT_WAIT_INTERVAL	1
+
+/* DRAM ctrl values for Carmine PCI Eval. board */
+#define GC_EVB_DCTL_MODE_ADD		0x012105c3
+#define GC_EVB_DCTL_MODE_ADD_AFT_RST	0x002105c3
+#define GC_EVB_DCTL_SETTIME1_EMODE	0x47498000
+#define GC_EVB_DCTL_REFRESH_SETTIME2	0x00422a22
+#define GC_EVB_DCTL_RSV0_STATES		0x00200003
+#define GC_EVB_DCTL_RSV0_STATES_AFT_RST	0x00200002
+#define GC_EVB_DCTL_RSV2_RSV1		0x0000000f
+#define GC_EVB_DCTL_DDRIF2_DDRIF1	0x00556646
+#define GC_EVB_DCTL_IOCONT1_IOCONT0	0x05550555
+
+#define GC_DISP_REFCLK_533		533
+
+#endif
diff --git a/drivers/video/fbdev/mb862xx/mb862xxfb.h b/drivers/video/fbdev/mb862xx/mb862xxfb.h
new file mode 100644
index 000000000000..8550630c1e01
--- /dev/null
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb.h
@@ -0,0 +1,121 @@
+#ifndef __MB862XX_H__
+#define __MB862XX_H__
+
+struct mb862xx_l1_cfg {
+	unsigned short sx;
+	unsigned short sy;
+	unsigned short sw;
+	unsigned short sh;
+	unsigned short dx;
+	unsigned short dy;
+	unsigned short dw;
+	unsigned short dh;
+	int mirror;
+};
+
+#define MB862XX_BASE		'M'
+#define MB862XX_L1_GET_CFG	_IOR(MB862XX_BASE, 0, struct mb862xx_l1_cfg*)
+#define MB862XX_L1_SET_CFG	_IOW(MB862XX_BASE, 1, struct mb862xx_l1_cfg*)
+#define MB862XX_L1_ENABLE	_IOW(MB862XX_BASE, 2, int)
+#define MB862XX_L1_CAP_CTL	_IOW(MB862XX_BASE, 3, int)
+
+#ifdef __KERNEL__
+
+#define PCI_VENDOR_ID_FUJITSU_LIMITED	0x10cf
+#define PCI_DEVICE_ID_FUJITSU_CORALP	0x2019
+#define PCI_DEVICE_ID_FUJITSU_CORALPA	0x201e
+#define PCI_DEVICE_ID_FUJITSU_CARMINE	0x202b
+
+#define GC_MMR_CORALP_EVB_VAL		0x11d7fa13
+
+enum gdctype {
+	BT_NONE,
+	BT_LIME,
+	BT_MINT,
+	BT_CORAL,
+	BT_CORALP,
+	BT_CARMINE,
+};
+
+struct mb862xx_gc_mode {
+	struct fb_videomode	def_mode;	/* mode of connected display */
+	unsigned int		def_bpp;	/* default depth */
+	unsigned long		max_vram;	/* connected SDRAM size */
+	unsigned long		ccf;		/* gdc clk */
+	unsigned long		mmr;		/* memory mode for SDRAM */
+};
+
+/* private data */
+struct mb862xxfb_par {
+	struct fb_info		*info;		/* fb info head */
+	struct device		*dev;
+	struct pci_dev		*pdev;
+	struct resource		*res;		/* framebuffer/mmio resource */
+
+	resource_size_t		fb_base_phys;	/* fb base, 36-bit PPC440EPx */
+	resource_size_t		mmio_base_phys;	/* io base addr */
+	void __iomem		*fb_base;	/* remapped framebuffer */
+	void __iomem		*mmio_base;	/* remapped registers */
+	size_t			mapped_vram;	/* length of remapped vram */
+	size_t			mmio_len;	/* length of register region */
+	unsigned long		cap_buf;	/* capture buffers offset */
+	size_t			cap_len;	/* length of capture buffers */
+
+	void __iomem		*host;		/* relocatable reg. bases */
+	void __iomem		*i2c;
+	void __iomem		*disp;
+	void __iomem		*disp1;
+	void __iomem		*cap;
+	void __iomem		*cap1;
+	void __iomem		*draw;
+	void __iomem		*geo;
+	void __iomem		*pio;
+	void __iomem		*ctrl;
+	void __iomem		*dram_ctrl;
+	void __iomem		*wrback;
+
+	unsigned int		irq;
+	unsigned int		type;		/* GDC type */
+	unsigned int		refclk;		/* disp. reference clock */
+	struct mb862xx_gc_mode	*gc_mode;	/* GDC mode init data */
+	int			pre_init;	/* don't init display if 1 */
+	struct i2c_adapter	*adap;		/* GDC I2C bus adapter */
+	int			i2c_rs;
+
+	struct mb862xx_l1_cfg	l1_cfg;
+	int			l1_stride;
+
+	u32			pseudo_palette[16];
+};
+
+extern void mb862xxfb_init_accel(struct fb_info *info, int xres);
+#ifdef CONFIG_FB_MB862XX_I2C
+extern int mb862xx_i2c_init(struct mb862xxfb_par *par);
+extern void mb862xx_i2c_exit(struct mb862xxfb_par *par);
+#else
+static inline int mb862xx_i2c_init(struct mb862xxfb_par *par) { return 0; }
+static inline void mb862xx_i2c_exit(struct mb862xxfb_par *par) { }
+#endif
+
+#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC)
+#error	"Select Lime GDC or CoralP/Carmine support, but not both together"
+#endif
+#if defined(CONFIG_FB_MB862XX_LIME)
+#define gdc_read	__raw_readl
+#define gdc_write	__raw_writel
+#else
+#define gdc_read	readl
+#define gdc_write	writel
+#endif
+
+#define inreg(type, off)	\
+	gdc_read((par->type + (off)))
+
+#define outreg(type, off, val)	\
+	gdc_write((val), (par->type + (off)))
+
+#define pack(a, b)	(((a) << 16) | (b))
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
new file mode 100644
index 000000000000..fe92eed6da70
--- /dev/null
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
@@ -0,0 +1,335 @@
+/*
+ * drivers/mb862xx/mb862xxfb_accel.c
+ *
+ * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
+ *
+ * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
+ * (C) 2009 Valentin Sitdikov <v.sitdikov@gmail.com>
+ * (C) 2009 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#if defined(CONFIG_OF)
+#include <linux/of_platform.h>
+#endif
+#include "mb862xxfb.h"
+#include "mb862xx_reg.h"
+#include "mb862xxfb_accel.h"
+
+static void mb862xxfb_write_fifo(u32 count, u32 *data, struct fb_info *info)
+{
+	struct mb862xxfb_par *par = info->par;
+	static u32 free;
+
+	u32 total = 0;
+	while (total < count) {
+		if (free) {
+			outreg(geo, GDC_GEO_REG_INPUT_FIFO, data[total]);
+			total++;
+			free--;
+		} else {
+			free = (u32) inreg(draw, GDC_REG_FIFO_COUNT);
+		}
+	}
+}
+
+static void mb86290fb_copyarea(struct fb_info *info,
+			       const struct fb_copyarea *area)
+{
+	__u32 cmd[6];
+
+	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
+	/* Set raster operation */
+	cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
+	cmd[2] = GDC_TYPE_BLTCOPYP << 24;
+
+	if (area->sx >= area->dx && area->sy >= area->dy)
+		cmd[2] |= GDC_CMD_BLTCOPY_TOP_LEFT << 16;
+	else if (area->sx >= area->dx && area->sy <= area->dy)
+		cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT << 16;
+	else if (area->sx <= area->dx && area->sy >= area->dy)
+		cmd[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT << 16;
+	else
+		cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT << 16;
+
+	cmd[3] = (area->sy << 16) | area->sx;
+	cmd[4] = (area->dy << 16) | area->dx;
+	cmd[5] = (area->height << 16) | area->width;
+	mb862xxfb_write_fifo(6, cmd, info);
+}
+
+/*
+ * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
+ * Make sure cmd has enough room!
+ */
+static void mb86290fb_imageblit1(u32 *cmd, u16 step, u16 dx, u16 dy,
+				 u16 width, u16 height, u32 fgcolor,
+				 u32 bgcolor, const struct fb_image *image,
+				 struct fb_info *info)
+{
+	int i;
+	unsigned const char *line;
+	u16 bytes;
+
+	/* set colors and raster operation regs */
+	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
+	/* Set raster operation */
+	cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
+	cmd[2] =
+	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
+	cmd[3] = fgcolor;
+	cmd[4] =
+	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_BACK_COLOR << 16);
+	cmd[5] = bgcolor;
+
+	i = 0;
+	line = image->data;
+	bytes = (image->width + 7) >> 3;
+
+	/* and the image */
+	cmd[6] = (GDC_TYPE_DRAWBITMAPP << 24) |
+	    (GDC_CMD_BITMAP << 16) | (2 + (step * height));
+	cmd[7] = (dy << 16) | dx;
+	cmd[8] = (height << 16) | width;
+
+	while (i < height) {
+		memcpy(&cmd[9 + i * step], line, step << 2);
+#ifdef __LITTLE_ENDIAN
+		{
+			int k = 0;
+			for (k = 0; k < step; k++)
+				cmd[9 + i * step + k] =
+				    cpu_to_be32(cmd[9 + i * step + k]);
+		}
+#endif
+		line += bytes;
+		i++;
+	}
+}
+
+/*
+ * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
+ * Make sure cmd has enough room!
+ */
+static void mb86290fb_imageblit8(u32 *cmd, u16 step, u16 dx, u16 dy,
+				 u16 width, u16 height, u32 fgcolor,
+				 u32 bgcolor, const struct fb_image *image,
+				 struct fb_info *info)
+{
+	int i, j;
+	unsigned const char *line, *ptr;
+	u16 bytes;
+
+	cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
+	    (GDC_CMD_BLT_DRAW << 16) | (2 + (height * step));
+	cmd[1] = (dy << 16) | dx;
+	cmd[2] = (height << 16) | width;
+
+	i = 0;
+	line = ptr = image->data;
+	bytes = image->width;
+
+	while (i < height) {
+		ptr = line;
+		for (j = 0; j < step; j++) {
+			cmd[3 + i * step + j] =
+			    (((u32 *) (info->pseudo_palette))[*ptr]) & 0xffff;
+			ptr++;
+			cmd[3 + i * step + j] |=
+			    ((((u32 *) (info->
+					pseudo_palette))[*ptr]) & 0xffff) << 16;
+			ptr++;
+		}
+
+		line += bytes;
+		i++;
+	}
+}
+
+/*
+ * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
+ * Make sure cmd has enough room!
+ */
+static void mb86290fb_imageblit16(u32 *cmd, u16 step, u16 dx, u16 dy,
+				  u16 width, u16 height, u32 fgcolor,
+				  u32 bgcolor, const struct fb_image *image,
+				  struct fb_info *info)
+{
+	int i;
+	unsigned const char *line;
+	u16 bytes;
+
+	i = 0;
+	line = image->data;
+	bytes = image->width << 1;
+
+	cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
+	    (GDC_CMD_BLT_DRAW << 16) | (2 + step * height);
+	cmd[1] = (dy << 16) | dx;
+	cmd[2] = (height << 16) | width;
+
+	while (i < height) {
+		memcpy(&cmd[3 + i * step], line, step);
+		line += bytes;
+		i++;
+	}
+}
+
+static void mb86290fb_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	int mdr;
+	u32 *cmd = NULL;
+	void (*cmdfn) (u32 *, u16, u16, u16, u16, u16, u32, u32,
+		       const struct fb_image *, struct fb_info *) = NULL;
+	u32 cmdlen;
+	u32 fgcolor = 0, bgcolor = 0;
+	u16 step;
+
+	u16 width = image->width, height = image->height;
+	u16 dx = image->dx, dy = image->dy;
+	int x2, y2, vxres, vyres;
+
+	mdr = (GDC_ROP_COPY << 9);
+	x2 = image->dx + image->width;
+	y2 = image->dy + image->height;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+	x2 = min(x2, vxres);
+	y2 = min(y2, vyres);
+	width = x2 - dx;
+	height = y2 - dy;
+
+	switch (image->depth) {
+	case 1:
+		step = (width + 31) >> 5;
+		cmdlen = 9 + height * step;
+		cmdfn = mb86290fb_imageblit1;
+		if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+		    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+			fgcolor =
+			    ((u32 *) (info->pseudo_palette))[image->fg_color];
+			bgcolor =
+			    ((u32 *) (info->pseudo_palette))[image->bg_color];
+		} else {
+			fgcolor = image->fg_color;
+			bgcolor = image->bg_color;
+		}
+
+		break;
+
+	case 8:
+		step = (width + 1) >> 1;
+		cmdlen = 3 + height * step;
+		cmdfn = mb86290fb_imageblit8;
+		break;
+
+	case 16:
+		step = (width + 1) >> 1;
+		cmdlen = 3 + height * step;
+		cmdfn = mb86290fb_imageblit16;
+		break;
+
+	default:
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	cmd = kmalloc(cmdlen * 4, GFP_DMA);
+	if (!cmd)
+		return cfb_imageblit(info, image);
+	cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
+	mb862xxfb_write_fifo(cmdlen, cmd, info);
+	kfree(cmd);
+}
+
+static void mb86290fb_fillrect(struct fb_info *info,
+			       const struct fb_fillrect *rect)
+{
+
+	u32 x2, y2, vxres, vyres, height, width, fg;
+	u32 cmd[7];
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!rect->width || !rect->height || rect->dx > vxres
+	    || rect->dy > vyres)
+		return;
+
+	/* We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly. */
+	x2 = rect->dx + rect->width;
+	y2 = rect->dy + rect->height;
+	x2 = min(x2, vxres);
+	y2 = min(y2, vyres);
+	width = x2 - rect->dx;
+	height = y2 - rect->dy;
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		fg = ((u32 *) (info->pseudo_palette))[rect->color];
+	else
+		fg = rect->color;
+
+	switch (rect->rop) {
+
+	case ROP_XOR:
+		/* Set raster operation */
+		cmd[1] = (2 << 7) | (GDC_ROP_XOR << 9);
+		break;
+
+	case ROP_COPY:
+		/* Set raster operation */
+		cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
+		break;
+
+	}
+
+	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
+	/* cmd[1] set earlier */
+	cmd[2] =
+	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
+	cmd[3] = fg;
+	cmd[4] = (GDC_TYPE_DRAWRECTP << 24) | (GDC_CMD_BLT_FILL << 16);
+	cmd[5] = (rect->dy << 16) | (rect->dx);
+	cmd[6] = (height << 16) | width;
+
+	mb862xxfb_write_fifo(7, cmd, info);
+}
+
+void mb862xxfb_init_accel(struct fb_info *info, int xres)
+{
+	struct mb862xxfb_par *par = info->par;
+
+	if (info->var.bits_per_pixel == 32) {
+		info->fbops->fb_fillrect = cfb_fillrect;
+		info->fbops->fb_copyarea = cfb_copyarea;
+		info->fbops->fb_imageblit = cfb_imageblit;
+	} else {
+		outreg(disp, GC_L0EM, 3);
+		info->fbops->fb_fillrect = mb86290fb_fillrect;
+		info->fbops->fb_copyarea = mb86290fb_copyarea;
+		info->fbops->fb_imageblit = mb86290fb_imageblit;
+	}
+	outreg(draw, GDC_REG_DRAW_BASE, 0);
+	outreg(draw, GDC_REG_MODE_MISC, 0x8000);
+	outreg(draw, GDC_REG_X_RESOLUTION, xres);
+
+	info->flags |=
+	    FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+	    FBINFO_HWACCEL_IMAGEBLIT;
+	info->fix.accel = 0xff;	/*FIXME: add right define */
+}
+EXPORT_SYMBOL(mb862xxfb_init_accel);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.h b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.h
new file mode 100644
index 000000000000..96a2dfef0f60
--- /dev/null
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.h
@@ -0,0 +1,203 @@
+#ifndef __MB826XXFB_ACCEL_H__
+#define __MB826XXFB_ACCEL_H__
+
+/* registers */
+#define GDC_GEO_REG_INPUT_FIFO 0x00000400L
+
+/* Special Registers */
+#define GDC_REG_CTRL                0x00000400L
+#define GDC_REG_FIFO_STATUS         0x00000404L
+#define GDC_REG_FIFO_COUNT          0x00000408L
+#define GDC_REG_SETUP_STATUS        0x0000040CL
+#define GDC_REG_DDA_STATUS          0x00000410L
+#define GDC_REG_ENGINE_STATUS       0x00000414L
+#define GDC_REG_ERROR_STATUS        0x00000418L
+#define GDC_REG_MODE_MISC           0x00000420L	/* MDR0 */
+#define GDC_REG_MODE_LINE           0x00000424L	/* MDR1 */
+#define GDC_REG_MODE_POLYGON        0x00000428L	/* MDR2 */
+#define GDC_REG_MODE_TEXTURE        0x0000042CL	/* MDR3 */
+#define GDC_REG_MODE_BITMAP         0x00000430L	/* MDR4 */
+#define GDC_REG_MODE_EXTENSION      0x0000043CL	/* MDR7 */
+
+/* Configuration Registers */
+#define GDC_REG_DRAW_BASE           0x00000440L
+#define GDC_REG_X_RESOLUTION        0x00000444L
+#define GDC_REG_Z_BASE              0x00000448L
+#define GDC_REG_TEXTURE_BASE        0x0000044CL
+#define GDC_REG_POLYGON_FLAG_BASE   0x00000450L
+#define GDC_REG_CLIP_XMIN           0x00000454L
+#define GDC_REG_CLIP_XMAX           0x00000458L
+#define GDC_REG_CLIP_YMIN           0x0000045CL
+#define GDC_REG_CLIP_YMAX           0x00000460L
+#define GDC_REG_TEXURE_SIZE         0x00000464L
+#define GDC_REG_TILE_SIZE           0x00000468L
+#define GDC_REG_TEX_BUF_OFFSET      0x0000046CL
+
+/* for MB86293 or later */
+#define GDC_REG_ALPHA_MAP_BASE      0x00000474L	/* ABR */
+
+/* Constant Registers */
+#define GDC_REG_FOREGROUND_COLOR    0x00000480L
+#define GDC_REG_BACKGROUND_COLOR    0x00000484L
+#define GDC_REG_ALPHA               0x00000488L
+#define GDC_REG_LINE_PATTERN        0x0000048CL
+#define GDC_REG_TEX_BORDER_COLOR    0x00000494L
+#define GDC_REG_LINE_PATTERN_OFFSET 0x000003E0L
+
+/* Coomand Code */
+#define GDC_CMD_PIXEL                   0x00000000L
+#define GDC_CMD_PIXEL_Z                 0x00000001L
+
+#define GDC_CMD_X_VECTOR                0x00000020L
+#define GDC_CMD_Y_VECTOR                0x00000021L
+#define GDC_CMD_X_VECTOR_NOEND          0x00000022L
+#define GDC_CMD_Y_VECTOR_NOEND          0x00000023L
+#define GDC_CMD_X_VECTOR_BLPO           0x00000024L
+#define GDC_CMD_Y_VECTOR_BLPO           0x00000025L
+#define GDC_CMD_X_VECTOR_NOEND_BLPO     0x00000026L
+#define GDC_CMD_Y_VECTOR_NOEND_BLPO     0x00000027L
+#define GDC_CMD_AA_X_VECTOR             0x00000028L
+#define GDC_CMD_AA_Y_VECTOR             0x00000029L
+#define GDC_CMD_AA_X_VECTOR_NOEND       0x0000002AL
+#define GDC_CMD_AA_Y_VECTOR_NOEND       0x0000002BL
+#define GDC_CMD_AA_X_VECTOR_BLPO        0x0000002CL
+#define GDC_CMD_AA_Y_VECTOR_BLPO        0x0000002DL
+#define GDC_CMD_AA_X_VECTOR_NOEND_BLPO  0x0000002EL
+#define GDC_CMD_AA_Y_VECTOR_NOEND_BLPO  0x0000002FL
+
+#define GDC_CMD_0_VECTOR                0x00000030L
+#define GDC_CMD_1_VECTOR                0x00000031L
+#define GDC_CMD_0_VECTOR_NOEND          0x00000032L
+#define GDC_CMD_1_VECTOR_NOEND          0x00000033L
+#define GDC_CMD_0_VECTOR_BLPO           0x00000034L
+#define GDC_CMD_1_VECTOR_BLPO           0x00000035L
+#define GDC_CMD_0_VECTOR_NOEND_BLPO     0x00000036L
+#define GDC_CMD_1_VECTOR_NOEND_BLPO     0x00000037L
+#define GDC_CMD_AA_0_VECTOR             0x00000038L
+#define GDC_CMD_AA_1_VECTOR             0x00000039L
+#define GDC_CMD_AA_0_VECTOR_NOEND       0x0000003AL
+#define GDC_CMD_AA_1_VECTOR_NOEND       0x0000003BL
+#define GDC_CMD_AA_0_VECTOR_BLPO        0x0000003CL
+#define GDC_CMD_AA_1_VECTOR_BLPO        0x0000003DL
+#define GDC_CMD_AA_0_VECTOR_NOEND_BLPO  0x0000003EL
+#define GDC_CMD_AA_1_VECTOR_NOEND_BLPO  0x0000003FL
+
+#define GDC_CMD_BLT_FILL                0x00000041L
+#define GDC_CMD_BLT_DRAW                0x00000042L
+#define GDC_CMD_BITMAP                  0x00000043L
+#define GDC_CMD_BLTCOPY_TOP_LEFT        0x00000044L
+#define GDC_CMD_BLTCOPY_TOP_RIGHT       0x00000045L
+#define GDC_CMD_BLTCOPY_BOTTOM_LEFT     0x00000046L
+#define GDC_CMD_BLTCOPY_BOTTOM_RIGHT    0x00000047L
+#define GDC_CMD_LOAD_TEXTURE            0x00000048L
+#define GDC_CMD_LOAD_TILE               0x00000049L
+
+#define GDC_CMD_TRAP_RIGHT              0x00000060L
+#define GDC_CMD_TRAP_LEFT               0x00000061L
+#define GDC_CMD_TRIANGLE_FAN            0x00000062L
+#define GDC_CMD_FLAG_TRIANGLE_FAN       0x00000063L
+
+#define GDC_CMD_FLUSH_FB                0x000000C1L
+#define GDC_CMD_FLUSH_Z                 0x000000C2L
+
+#define GDC_CMD_POLYGON_BEGIN           0x000000E0L
+#define GDC_CMD_POLYGON_END             0x000000E1L
+#define GDC_CMD_CLEAR_POLY_FLAG         0x000000E2L
+#define GDC_CMD_NORMAL                  0x000000FFL
+
+#define GDC_CMD_VECTOR_BLPO_FLAG        0x00040000L
+#define GDC_CMD_FAST_VECTOR_BLPO_FLAG   0x00000004L
+
+/* for MB86293 or later */
+#define GDC_CMD_MDR1                            0x00000000L
+#define GDC_CMD_MDR1S                           0x00000002L
+#define GDC_CMD_MDR1B                           0x00000004L
+#define GDC_CMD_MDR2                            0x00000001L
+#define GDC_CMD_MDR2S                           0x00000003L
+#define GDC_CMD_MDR2TL                          0x00000007L
+#define GDC_CMD_GMDR1E                          0x00000010L
+#define GDC_CMD_GMDR2E                          0x00000020L
+#define GDC_CMD_OVERLAP_SHADOW_XY               0x00000000L
+#define GDC_CMD_OVERLAP_SHADOW_XY_COMPOSITION   0x00000001L
+#define GDC_CMD_OVERLAP_Z_PACKED_ONBS           0x00000007L
+#define GDC_CMD_OVERLAP_Z_ORIGIN                0x00000000L
+#define GDC_CMD_OVERLAP_Z_NON_TOPLEFT           0x00000001L
+#define GDC_CMD_OVERLAP_Z_BORDER                0x00000002L
+#define GDC_CMD_OVERLAP_Z_SHADOW                0x00000003L
+#define GDC_CMD_BLTCOPY_ALT_ALPHA               0x00000000L	/* Reserverd */
+#define GDC_CMD_DC_LOGOUT                       0x00000000L	/* Reserverd */
+#define GDC_CMD_BODY_FORE_COLOR                 0x00000000L
+#define GDC_CMD_BODY_BACK_COLOR                 0x00000001L
+#define GDC_CMD_SHADOW_FORE_COLOR               0x00000002L
+#define GDC_CMD_SHADOW_BACK_COLOR               0x00000003L
+#define GDC_CMD_BORDER_FORE_COLOR               0x00000004L
+#define GDC_CMD_BORDER_BACK_COLOR               0x00000005L
+
+/* Type Code Table */
+#define GDC_TYPE_G_NOP                                  0x00000020L
+#define GDC_TYPE_G_BEGIN                                0x00000021L
+#define GDC_TYPE_G_BEGINCONT                            0x00000022L
+#define GDC_TYPE_G_END                                  0x00000023L
+#define GDC_TYPE_G_VERTEX                               0x00000030L
+#define GDC_TYPE_G_VERTEXLOG                            0x00000032L
+#define GDC_TYPE_G_VERTEXNOPLOG                         0x00000033L
+#define GDC_TYPE_G_INIT                                 0x00000040L
+#define GDC_TYPE_G_VIEWPORT                             0x00000041L
+#define GDC_TYPE_G_DEPTHRANGE                           0x00000042L
+#define GDC_TYPE_G_LOADMATRIX                           0x00000043L
+#define GDC_TYPE_G_VIEWVOLUMEXYCLIP                     0x00000044L
+#define GDC_TYPE_G_VIEWVOLUMEZCLIP                      0x00000045L
+#define GDC_TYPE_G_VIEWVOLUMEWCLIP                      0x00000046L
+#define GDC_TYPE_SETLVERTEX2I                           0x00000072L
+#define GDC_TYPE_SETLVERTEX2IP                          0x00000073L
+#define GDC_TYPE_SETMODEREGISTER                        0x000000C0L
+#define GDC_TYPE_SETGMODEREGISTER                       0x000000C1L
+#define GDC_TYPE_OVERLAPXYOFFT                          0x000000C8L
+#define GDC_TYPE_OVERLAPZOFFT                           0x000000C9L
+#define GDC_TYPE_DC_LOGOUTADDR                          0x000000CCL
+#define GDC_TYPE_SETCOLORREGISTER                       0x000000CEL
+#define GDC_TYPE_G_BEGINE                               0x000000E1L
+#define GDC_TYPE_G_BEGINCONTE                           0x000000E2L
+#define GDC_TYPE_G_ENDE                                 0x000000E3L
+#define GDC_TYPE_DRAWPIXEL                              0x00000000L
+#define GDC_TYPE_DRAWPIXELZ                             0x00000001L
+#define GDC_TYPE_DRAWLINE                               0x00000002L
+#define GDC_TYPE_DRAWLINE2I                             0x00000003L
+#define GDC_TYPE_DRAWLINE2IP                            0x00000004L
+#define GDC_TYPE_DRAWTRAP                               0x00000005L
+#define GDC_TYPE_DRAWVERTEX2I                           0x00000006L
+#define GDC_TYPE_DRAWVERTEX2IP                          0x00000007L
+#define GDC_TYPE_DRAWRECTP                              0x00000009L
+#define GDC_TYPE_DRAWBITMAPP                            0x0000000BL
+#define GDC_TYPE_BLTCOPYP                               0x0000000DL
+#define GDC_TYPE_BLTCOPYALTERNATEP                      0x0000000FL
+#define GDC_TYPE_LOADTEXTUREP                           0x00000011L
+#define GDC_TYPE_BLTTEXTUREP                            0x00000013L
+#define GDC_TYPE_BLTCOPYALTALPHABLENDP                  0x0000001FL
+#define GDC_TYPE_SETVERTEX2I                            0x00000070L
+#define GDC_TYPE_SETVERTEX2IP                           0x00000071L
+#define GDC_TYPE_DRAW                                   0x000000F0L
+#define GDC_TYPE_SETREGISTER                            0x000000F1L
+#define GDC_TYPE_SYNC                                   0x000000FCL
+#define GDC_TYPE_INTERRUPT                              0x000000FDL
+#define GDC_TYPE_NOP                                    0x0
+
+/* Raster operation */
+#define GDC_ROP_CLEAR                   0x0000
+#define GDC_ROP_AND                     0x0001
+#define GDC_ROP_AND_REVERSE             0x0002
+#define GDC_ROP_COPY                    0x0003
+#define GDC_ROP_AND_INVERTED            0x0004
+#define GDC_ROP_NOP                     0x0005
+#define GDC_ROP_XOR                     0x0006
+#define GDC_ROP_OR                      0x0007
+#define GDC_ROP_NOR                     0x0008
+#define GDC_ROP_EQUIV                   0x0009
+#define GDC_ROP_INVERT                  0x000A
+#define GDC_ROP_OR_REVERSE              0x000B
+#define GDC_ROP_COPY_INVERTED           0x000C
+#define GDC_ROP_OR_INVERTED             0x000D
+#define GDC_ROP_NAND                    0x000E
+#define GDC_ROP_SET                     0x000F
+
+#endif
diff --git a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
new file mode 100644
index 000000000000..0cd4c3318511
--- /dev/null
+++ b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
@@ -0,0 +1,1206 @@
+/*
+ * drivers/mb862xx/mb862xxfb.c
+ *
+ * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver
+ *
+ * (C) 2008 Anatolij Gustschin <agust@denx.de>
+ * DENX Software Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#if defined(CONFIG_OF)
+#include <linux/of_platform.h>
+#endif
+#include "mb862xxfb.h"
+#include "mb862xx_reg.h"
+
+#define NR_PALETTE		256
+#define MB862XX_MEM_SIZE	0x1000000
+#define CORALP_MEM_SIZE		0x2000000
+#define CARMINE_MEM_SIZE	0x8000000
+#define DRV_NAME		"mb862xxfb"
+
+#if defined(CONFIG_SOCRATES)
+static struct mb862xx_gc_mode socrates_gc_mode = {
+	/* Mode for Prime View PM070WL4 TFT LCD Panel */
+	{ "800x480", 45, 800, 480, 40000, 86, 42, 33, 10, 128, 2, 0, 0, 0 },
+	/* 16 bits/pixel, 16MB, 133MHz, SDRAM memory mode value */
+	16, 0x1000000, GC_CCF_COT_133, 0x4157ba63
+};
+#endif
+
+/* Helpers */
+static inline int h_total(struct fb_var_screeninfo *var)
+{
+	return var->xres + var->left_margin +
+		var->right_margin + var->hsync_len;
+}
+
+static inline int v_total(struct fb_var_screeninfo *var)
+{
+	return var->yres + var->upper_margin +
+		var->lower_margin + var->vsync_len;
+}
+
+static inline int hsp(struct fb_var_screeninfo *var)
+{
+	return var->xres + var->right_margin - 1;
+}
+
+static inline int vsp(struct fb_var_screeninfo *var)
+{
+	return var->yres + var->lower_margin - 1;
+}
+
+static inline int d_pitch(struct fb_var_screeninfo *var)
+{
+	return var->xres * var->bits_per_pixel / 8;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan,
+					 struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int mb862xxfb_setcolreg(unsigned regno,
+			       unsigned red, unsigned green, unsigned blue,
+			       unsigned transp, struct fb_info *info)
+{
+	struct mb862xxfb_par *par = info->par;
+	unsigned int val;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			val  = chan_to_field(red,   &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue,  &info->var.blue);
+			par->pseudo_palette[regno] = val;
+		}
+		break;
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			val = (red >> 8) << 16;
+			val |= (green >> 8) << 8;
+			val |= blue >> 8;
+			outreg(disp, GC_L0PAL0 + (regno * 4), val);
+		}
+		break;
+	default:
+		return 1;   /* unsupported type */
+	}
+	return 0;
+}
+
+static int mb862xxfb_check_var(struct fb_var_screeninfo *var,
+			       struct fb_info *fbi)
+{
+	unsigned long tmp;
+
+	if (fbi->dev)
+		dev_dbg(fbi->dev, "%s\n", __func__);
+
+	/* check if these values fit into the registers */
+	if (var->hsync_len > 255 || var->vsync_len > 255)
+		return -EINVAL;
+
+	if ((var->xres + var->right_margin) >= 4096)
+		return -EINVAL;
+
+	if ((var->yres + var->lower_margin) > 4096)
+		return -EINVAL;
+
+	if (h_total(var) > 4096 || v_total(var) > 4096)
+		return -EINVAL;
+
+	if (var->xres_virtual > 4096 || var->yres_virtual > 4096)
+		return -EINVAL;
+
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+
+	/*
+	 * can cope with 8,16 or 24/32bpp if resulting
+	 * pitch is divisible by 64 without remainder
+	 */
+	if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) {
+		int r;
+
+		var->bits_per_pixel = 0;
+		do {
+			var->bits_per_pixel += 8;
+			r = d_pitch(&fbi->var) % GC_L0M_L0W_UNIT;
+		} while (r && var->bits_per_pixel <= 32);
+
+		if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT)
+			return -EINVAL;
+	}
+
+	/* line length is going to be 128 bit aligned */
+	tmp = (var->xres * var->bits_per_pixel) / 8;
+	if ((tmp & 15) != 0)
+		return -EINVAL;
+
+	/* set r/g/b positions and validate bpp */
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.length		= var->bits_per_pixel;
+		var->green.length	= var->bits_per_pixel;
+		var->blue.length	= var->bits_per_pixel;
+		var->red.offset		= 0;
+		var->green.offset	= 0;
+		var->blue.offset	= 0;
+		var->transp.length	= 0;
+		break;
+	case 16:
+		var->red.length		= 5;
+		var->green.length	= 5;
+		var->blue.length	= 5;
+		var->red.offset		= 10;
+		var->green.offset	= 5;
+		var->blue.offset	= 0;
+		var->transp.length	= 0;
+		break;
+	case 24:
+	case 32:
+		var->transp.length	= 8;
+		var->red.length		= 8;
+		var->green.length	= 8;
+		var->blue.length	= 8;
+		var->transp.offset	= 24;
+		var->red.offset		= 16;
+		var->green.offset	= 8;
+		var->blue.offset	= 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * set display parameters
+ */
+static int mb862xxfb_set_par(struct fb_info *fbi)
+{
+	struct mb862xxfb_par *par = fbi->par;
+	unsigned long reg, sc;
+
+	dev_dbg(par->dev, "%s\n", __func__);
+	if (par->type == BT_CORALP)
+		mb862xxfb_init_accel(fbi, fbi->var.xres);
+
+	if (par->pre_init)
+		return 0;
+
+	/* disp off */
+	reg = inreg(disp, GC_DCM1);
+	reg &= ~GC_DCM01_DEN;
+	outreg(disp, GC_DCM1, reg);
+
+	/* set display reference clock div. */
+	sc = par->refclk / (1000000 / fbi->var.pixclock) - 1;
+	reg = inreg(disp, GC_DCM1);
+	reg &= ~(GC_DCM01_CKS | GC_DCM01_RESV | GC_DCM01_SC);
+	reg |= sc << 8;
+	outreg(disp, GC_DCM1, reg);
+	dev_dbg(par->dev, "SC 0x%lx\n", sc);
+
+	/* disp dimension, format */
+	reg =  pack(d_pitch(&fbi->var) / GC_L0M_L0W_UNIT,
+		    (fbi->var.yres - 1));
+	if (fbi->var.bits_per_pixel == 16)
+		reg |= GC_L0M_L0C_16;
+	outreg(disp, GC_L0M, reg);
+
+	if (fbi->var.bits_per_pixel == 32) {
+		reg = inreg(disp, GC_L0EM);
+		outreg(disp, GC_L0EM, reg | GC_L0EM_L0EC_24);
+	}
+	outreg(disp, GC_WY_WX, 0);
+	reg = pack(fbi->var.yres - 1, fbi->var.xres);
+	outreg(disp, GC_WH_WW, reg);
+	outreg(disp, GC_L0OA0, 0);
+	outreg(disp, GC_L0DA0, 0);
+	outreg(disp, GC_L0DY_L0DX, 0);
+	outreg(disp, GC_L0WY_L0WX, 0);
+	outreg(disp, GC_L0WH_L0WW, reg);
+
+	/* both HW-cursors off */
+	reg = inreg(disp, GC_CPM_CUTC);
+	reg &= ~(GC_CPM_CEN0 | GC_CPM_CEN1);
+	outreg(disp, GC_CPM_CUTC, reg);
+
+	/* timings */
+	reg = pack(fbi->var.xres - 1, fbi->var.xres - 1);
+	outreg(disp, GC_HDB_HDP, reg);
+	reg = pack((fbi->var.yres - 1), vsp(&fbi->var));
+	outreg(disp, GC_VDP_VSP, reg);
+	reg = ((fbi->var.vsync_len - 1) << 24) |
+	      pack((fbi->var.hsync_len - 1), hsp(&fbi->var));
+	outreg(disp, GC_VSW_HSW_HSP, reg);
+	outreg(disp, GC_HTP, pack(h_total(&fbi->var) - 1, 0));
+	outreg(disp, GC_VTR, pack(v_total(&fbi->var) - 1, 0));
+
+	/* display on */
+	reg = inreg(disp, GC_DCM1);
+	reg |= GC_DCM01_DEN | GC_DCM01_L0E;
+	reg &= ~GC_DCM01_ESY;
+	outreg(disp, GC_DCM1, reg);
+	return 0;
+}
+
+static int mb862xxfb_pan(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	struct mb862xxfb_par *par = info->par;
+	unsigned long reg;
+
+	reg = pack(var->yoffset, var->xoffset);
+	outreg(disp, GC_L0WY_L0WX, reg);
+
+	reg = pack(info->var.yres_virtual, info->var.xres_virtual);
+	outreg(disp, GC_L0WH_L0WW, reg);
+	return 0;
+}
+
+static int mb862xxfb_blank(int mode, struct fb_info *fbi)
+{
+	struct mb862xxfb_par  *par = fbi->par;
+	unsigned long reg;
+
+	dev_dbg(fbi->dev, "blank mode=%d\n", mode);
+
+	switch (mode) {
+	case FB_BLANK_POWERDOWN:
+		reg = inreg(disp, GC_DCM1);
+		reg &= ~GC_DCM01_DEN;
+		outreg(disp, GC_DCM1, reg);
+		break;
+	case FB_BLANK_UNBLANK:
+		reg = inreg(disp, GC_DCM1);
+		reg |= GC_DCM01_DEN;
+		outreg(disp, GC_DCM1, reg);
+		break;
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	default:
+		return 1;
+	}
+	return 0;
+}
+
+static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd,
+			   unsigned long arg)
+{
+	struct mb862xxfb_par *par = fbi->par;
+	struct mb862xx_l1_cfg *l1_cfg = &par->l1_cfg;
+	void __user *argp = (void __user *)arg;
+	int *enable;
+	u32 l1em = 0;
+
+	switch (cmd) {
+	case MB862XX_L1_GET_CFG:
+		if (copy_to_user(argp, l1_cfg, sizeof(*l1_cfg)))
+			return -EFAULT;
+		break;
+	case MB862XX_L1_SET_CFG:
+		if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
+			return -EFAULT;
+		if (l1_cfg->dh == 0 || l1_cfg->dw == 0)
+			return -EINVAL;
+		if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
+			/* downscaling */
+			outreg(cap, GC_CAP_CSC,
+				pack((l1_cfg->sh << 11) / l1_cfg->dh,
+				     (l1_cfg->sw << 11) / l1_cfg->dw));
+			l1em = inreg(disp, GC_L1EM);
+			l1em &= ~GC_L1EM_DM;
+		} else if ((l1_cfg->sw <= l1_cfg->dw) &&
+			   (l1_cfg->sh <= l1_cfg->dh)) {
+			/* upscaling */
+			outreg(cap, GC_CAP_CSC,
+				pack((l1_cfg->sh << 11) / l1_cfg->dh,
+				     (l1_cfg->sw << 11) / l1_cfg->dw));
+			outreg(cap, GC_CAP_CMSS,
+				pack(l1_cfg->sw >> 1, l1_cfg->sh));
+			outreg(cap, GC_CAP_CMDS,
+				pack(l1_cfg->dw >> 1, l1_cfg->dh));
+			l1em = inreg(disp, GC_L1EM);
+			l1em |= GC_L1EM_DM;
+		}
+
+		if (l1_cfg->mirror) {
+			outreg(cap, GC_CAP_CBM,
+				inreg(cap, GC_CAP_CBM) | GC_CBM_HRV);
+			l1em |= l1_cfg->dw * 2 - 8;
+		} else {
+			outreg(cap, GC_CAP_CBM,
+				inreg(cap, GC_CAP_CBM) & ~GC_CBM_HRV);
+			l1em &= 0xffff0000;
+		}
+		outreg(disp, GC_L1EM, l1em);
+		break;
+	case MB862XX_L1_ENABLE:
+		enable = (int *)arg;
+		if (*enable) {
+			outreg(disp, GC_L1DA, par->cap_buf);
+			outreg(cap, GC_CAP_IMG_START,
+				pack(l1_cfg->sy >> 1, l1_cfg->sx));
+			outreg(cap, GC_CAP_IMG_END,
+				pack(l1_cfg->sh, l1_cfg->sw));
+			outreg(disp, GC_L1M, GC_L1M_16 | GC_L1M_YC | GC_L1M_CS |
+					     (par->l1_stride << 16));
+			outreg(disp, GC_L1WY_L1WX,
+				pack(l1_cfg->dy, l1_cfg->dx));
+			outreg(disp, GC_L1WH_L1WW,
+				pack(l1_cfg->dh - 1, l1_cfg->dw));
+			outreg(disp, GC_DLS, 1);
+			outreg(cap, GC_CAP_VCM,
+				GC_VCM_VIE | GC_VCM_CM | GC_VCM_VS_PAL);
+			outreg(disp, GC_DCM1, inreg(disp, GC_DCM1) |
+					      GC_DCM1_DEN | GC_DCM1_L1E);
+		} else {
+			outreg(cap, GC_CAP_VCM,
+				inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
+			outreg(disp, GC_DCM1,
+				inreg(disp, GC_DCM1) & ~GC_DCM1_L1E);
+		}
+		break;
+	case MB862XX_L1_CAP_CTL:
+		enable = (int *)arg;
+		if (*enable) {
+			outreg(cap, GC_CAP_VCM,
+				inreg(cap, GC_CAP_VCM) | GC_VCM_VIE);
+		} else {
+			outreg(cap, GC_CAP_VCM,
+				inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* framebuffer ops */
+static struct fb_ops mb862xxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= mb862xxfb_check_var,
+	.fb_set_par	= mb862xxfb_set_par,
+	.fb_setcolreg	= mb862xxfb_setcolreg,
+	.fb_blank	= mb862xxfb_blank,
+	.fb_pan_display	= mb862xxfb_pan,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_ioctl	= mb862xxfb_ioctl,
+};
+
+/* initialize fb_info data */
+static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
+{
+	struct mb862xxfb_par *par = fbi->par;
+	struct mb862xx_gc_mode *mode = par->gc_mode;
+	unsigned long reg;
+	int stride;
+
+	fbi->fbops = &mb862xxfb_ops;
+	fbi->pseudo_palette = par->pseudo_palette;
+	fbi->screen_base = par->fb_base;
+	fbi->screen_size = par->mapped_vram;
+
+	strcpy(fbi->fix.id, DRV_NAME);
+	fbi->fix.smem_start = (unsigned long)par->fb_base_phys;
+	fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys;
+	fbi->fix.mmio_len = par->mmio_len;
+	fbi->fix.accel = FB_ACCEL_NONE;
+	fbi->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbi->fix.type_aux = 0;
+	fbi->fix.xpanstep = 1;
+	fbi->fix.ypanstep = 1;
+	fbi->fix.ywrapstep = 0;
+
+	reg = inreg(disp, GC_DCM1);
+	if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) {
+		/* get the disp mode from active display cfg */
+		unsigned long sc = ((reg & GC_DCM01_SC) >> 8) + 1;
+		unsigned long hsp, vsp, ht, vt;
+
+		dev_dbg(par->dev, "using bootloader's disp. mode\n");
+		fbi->var.pixclock = (sc * 1000000) / par->refclk;
+		fbi->var.xres = (inreg(disp, GC_HDB_HDP) & 0x0fff) + 1;
+		reg = inreg(disp, GC_VDP_VSP);
+		fbi->var.yres = ((reg >> 16) & 0x0fff) + 1;
+		vsp = (reg & 0x0fff) + 1;
+		fbi->var.xres_virtual = fbi->var.xres;
+		fbi->var.yres_virtual = fbi->var.yres;
+		reg = inreg(disp, GC_L0EM);
+		if (reg & GC_L0EM_L0EC_24) {
+			fbi->var.bits_per_pixel = 32;
+		} else {
+			reg = inreg(disp, GC_L0M);
+			if (reg & GC_L0M_L0C_16)
+				fbi->var.bits_per_pixel = 16;
+			else
+				fbi->var.bits_per_pixel = 8;
+		}
+		reg = inreg(disp, GC_VSW_HSW_HSP);
+		fbi->var.hsync_len = ((reg & 0xff0000) >> 16) + 1;
+		fbi->var.vsync_len = ((reg & 0x3f000000) >> 24) + 1;
+		hsp = (reg & 0xffff) + 1;
+		ht = ((inreg(disp, GC_HTP) & 0xfff0000) >> 16) + 1;
+		fbi->var.right_margin = hsp - fbi->var.xres;
+		fbi->var.left_margin = ht - hsp - fbi->var.hsync_len;
+		vt = ((inreg(disp, GC_VTR) & 0xfff0000) >> 16) + 1;
+		fbi->var.lower_margin = vsp - fbi->var.yres;
+		fbi->var.upper_margin = vt - vsp - fbi->var.vsync_len;
+	} else if (mode) {
+		dev_dbg(par->dev, "using supplied mode\n");
+		fb_videomode_to_var(&fbi->var, (struct fb_videomode *)mode);
+		fbi->var.bits_per_pixel = mode->def_bpp ? mode->def_bpp : 8;
+	} else {
+		int ret;
+
+		ret = fb_find_mode(&fbi->var, fbi, "640x480-16@60",
+				   NULL, 0, NULL, 16);
+		if (ret == 0 || ret == 4) {
+			dev_err(par->dev,
+				"failed to get initial mode\n");
+			return -EINVAL;
+		}
+	}
+
+	fbi->var.xoffset = 0;
+	fbi->var.yoffset = 0;
+	fbi->var.grayscale = 0;
+	fbi->var.nonstd = 0;
+	fbi->var.height = -1;
+	fbi->var.width = -1;
+	fbi->var.accel_flags = 0;
+	fbi->var.vmode = FB_VMODE_NONINTERLACED;
+	fbi->var.activate = FB_ACTIVATE_NOW;
+	fbi->flags = FBINFO_DEFAULT |
+#ifdef __BIG_ENDIAN
+		     FBINFO_FOREIGN_ENDIAN |
+#endif
+		     FBINFO_HWACCEL_XPAN |
+		     FBINFO_HWACCEL_YPAN;
+
+	/* check and possibly fix bpp */
+	if ((fbi->fbops->fb_check_var)(&fbi->var, fbi))
+		dev_err(par->dev, "check_var() failed on initial setup?\n");
+
+	fbi->fix.visual = fbi->var.bits_per_pixel == 8 ?
+			 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	fbi->fix.line_length = (fbi->var.xres_virtual *
+				fbi->var.bits_per_pixel) / 8;
+	fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual;
+
+	/*
+	 * reserve space for capture buffers and two cursors
+	 * at the end of vram: 720x576 * 2 * 2.2 + 64x64 * 16.
+	 */
+	par->cap_buf = par->mapped_vram - 0x1bd800 - 0x10000;
+	par->cap_len = 0x1bd800;
+	par->l1_cfg.sx = 0;
+	par->l1_cfg.sy = 0;
+	par->l1_cfg.sw = 720;
+	par->l1_cfg.sh = 576;
+	par->l1_cfg.dx = 0;
+	par->l1_cfg.dy = 0;
+	par->l1_cfg.dw = 720;
+	par->l1_cfg.dh = 576;
+	stride = par->l1_cfg.sw * (fbi->var.bits_per_pixel / 8);
+	par->l1_stride = stride / 64 + ((stride % 64) ? 1 : 0);
+	outreg(cap, GC_CAP_CBM, GC_CBM_OO | GC_CBM_CBST |
+				(par->l1_stride << 16));
+	outreg(cap, GC_CAP_CBOA, par->cap_buf);
+	outreg(cap, GC_CAP_CBLA, par->cap_buf + par->cap_len);
+	return 0;
+}
+
+/*
+ * show some display controller and cursor registers
+ */
+static ssize_t mb862xxfb_show_dispregs(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct mb862xxfb_par *par = fbi->par;
+	char *ptr = buf;
+	unsigned int reg;
+
+	for (reg = GC_DCM0; reg <= GC_L0DY_L0DX; reg += 4)
+		ptr += sprintf(ptr, "%08x = %08x\n",
+			       reg, inreg(disp, reg));
+
+	for (reg = GC_CPM_CUTC; reg <= GC_CUY1_CUX1; reg += 4)
+		ptr += sprintf(ptr, "%08x = %08x\n",
+			       reg, inreg(disp, reg));
+
+	for (reg = GC_DCM1; reg <= GC_L0WH_L0WW; reg += 4)
+		ptr += sprintf(ptr, "%08x = %08x\n",
+			       reg, inreg(disp, reg));
+
+	for (reg = 0x400; reg <= 0x410; reg += 4)
+		ptr += sprintf(ptr, "geo %08x = %08x\n",
+			       reg, inreg(geo, reg));
+
+	for (reg = 0x400; reg <= 0x410; reg += 4)
+		ptr += sprintf(ptr, "draw %08x = %08x\n",
+			       reg, inreg(draw, reg));
+
+	for (reg = 0x440; reg <= 0x450; reg += 4)
+		ptr += sprintf(ptr, "draw %08x = %08x\n",
+			       reg, inreg(draw, reg));
+
+	return ptr - buf;
+}
+
+static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL);
+
+static irqreturn_t mb862xx_intr(int irq, void *dev_id)
+{
+	struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id;
+	unsigned long reg_ist, mask;
+
+	if (!par)
+		return IRQ_NONE;
+
+	if (par->type == BT_CARMINE) {
+		/* Get Interrupt Status */
+		reg_ist = inreg(ctrl, GC_CTRL_STATUS);
+		mask = inreg(ctrl, GC_CTRL_INT_MASK);
+		if (reg_ist == 0)
+			return IRQ_HANDLED;
+
+		reg_ist &= mask;
+		if (reg_ist == 0)
+			return IRQ_HANDLED;
+
+		/* Clear interrupt status */
+		outreg(ctrl, 0x0, reg_ist);
+	} else {
+		/* Get status */
+		reg_ist = inreg(host, GC_IST);
+		mask = inreg(host, GC_IMASK);
+
+		reg_ist &= mask;
+		if (reg_ist == 0)
+			return IRQ_HANDLED;
+
+		/* Clear status */
+		outreg(host, GC_IST, ~reg_ist);
+	}
+	return IRQ_HANDLED;
+}
+
+#if defined(CONFIG_FB_MB862XX_LIME)
+/*
+ * GDC (Lime, Coral(B/Q), Mint, ...) on host bus
+ */
+static int mb862xx_gdc_init(struct mb862xxfb_par *par)
+{
+	unsigned long ccf, mmr;
+	unsigned long ver, rev;
+
+	if (!par)
+		return -ENODEV;
+
+#if defined(CONFIG_FB_PRE_INIT_FB)
+	par->pre_init = 1;
+#endif
+	par->host = par->mmio_base;
+	par->i2c = par->mmio_base + MB862XX_I2C_BASE;
+	par->disp = par->mmio_base + MB862XX_DISP_BASE;
+	par->cap = par->mmio_base + MB862XX_CAP_BASE;
+	par->draw = par->mmio_base + MB862XX_DRAW_BASE;
+	par->geo = par->mmio_base + MB862XX_GEO_BASE;
+	par->pio = par->mmio_base + MB862XX_PIO_BASE;
+
+	par->refclk = GC_DISP_REFCLK_400;
+
+	ver = inreg(host, GC_CID);
+	rev = inreg(pio, GC_REVISION);
+	if ((ver == 0x303) && (rev & 0xffffff00) == 0x20050100) {
+		dev_info(par->dev, "Fujitsu Lime v1.%d found\n",
+			 (int)rev & 0xff);
+		par->type = BT_LIME;
+		ccf = par->gc_mode ? par->gc_mode->ccf : GC_CCF_COT_100;
+		mmr = par->gc_mode ? par->gc_mode->mmr : 0x414fb7f2;
+	} else {
+		dev_info(par->dev, "? GDC, CID/Rev.: 0x%lx/0x%lx \n", ver, rev);
+		return -ENODEV;
+	}
+
+	if (!par->pre_init) {
+		outreg(host, GC_CCF, ccf);
+		udelay(200);
+		outreg(host, GC_MMR, mmr);
+		udelay(10);
+	}
+
+	/* interrupt status */
+	outreg(host, GC_IST, 0);
+	outreg(host, GC_IMASK, GC_INT_EN);
+	return 0;
+}
+
+static int of_platform_mb862xx_probe(struct platform_device *ofdev)
+{
+	struct device_node *np = ofdev->dev.of_node;
+	struct device *dev = &ofdev->dev;
+	struct mb862xxfb_par *par;
+	struct fb_info *info;
+	struct resource res;
+	resource_size_t res_size;
+	unsigned long ret = -ENODEV;
+
+	if (of_address_to_resource(np, 0, &res)) {
+		dev_err(dev, "Invalid address\n");
+		return -ENXIO;
+	}
+
+	info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
+	if (info == NULL) {
+		dev_err(dev, "cannot allocate framebuffer\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	par->info = info;
+	par->dev = dev;
+
+	par->irq = irq_of_parse_and_map(np, 0);
+	if (par->irq == NO_IRQ) {
+		dev_err(dev, "failed to map irq\n");
+		ret = -ENODEV;
+		goto fbrel;
+	}
+
+	res_size = resource_size(&res);
+	par->res = request_mem_region(res.start, res_size, DRV_NAME);
+	if (par->res == NULL) {
+		dev_err(dev, "Cannot claim framebuffer/mmio\n");
+		ret = -ENXIO;
+		goto irqdisp;
+	}
+
+#if defined(CONFIG_SOCRATES)
+	par->gc_mode = &socrates_gc_mode;
+#endif
+
+	par->fb_base_phys = res.start;
+	par->mmio_base_phys = res.start + MB862XX_MMIO_BASE;
+	par->mmio_len = MB862XX_MMIO_SIZE;
+	if (par->gc_mode)
+		par->mapped_vram = par->gc_mode->max_vram;
+	else
+		par->mapped_vram = MB862XX_MEM_SIZE;
+
+	par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
+	if (par->fb_base == NULL) {
+		dev_err(dev, "Cannot map framebuffer\n");
+		goto rel_reg;
+	}
+
+	par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
+	if (par->mmio_base == NULL) {
+		dev_err(dev, "Cannot map registers\n");
+		goto fb_unmap;
+	}
+
+	dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
+		(u64)par->fb_base_phys, (ulong)par->mapped_vram);
+	dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n",
+		(u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq);
+
+	if (mb862xx_gdc_init(par))
+		goto io_unmap;
+
+	if (request_irq(par->irq, mb862xx_intr, 0,
+			DRV_NAME, (void *)par)) {
+		dev_err(dev, "Cannot request irq\n");
+		goto io_unmap;
+	}
+
+	mb862xxfb_init_fbinfo(info);
+
+	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
+		dev_err(dev, "Could not allocate cmap for fb_info.\n");
+		goto free_irq;
+	}
+
+	if ((info->fbops->fb_set_par)(info))
+		dev_err(dev, "set_var() failed on initial setup?\n");
+
+	if (register_framebuffer(info)) {
+		dev_err(dev, "failed to register framebuffer\n");
+		goto rel_cmap;
+	}
+
+	dev_set_drvdata(dev, info);
+
+	if (device_create_file(dev, &dev_attr_dispregs))
+		dev_err(dev, "Can't create sysfs regdump file\n");
+	return 0;
+
+rel_cmap:
+	fb_dealloc_cmap(&info->cmap);
+free_irq:
+	outreg(host, GC_IMASK, 0);
+	free_irq(par->irq, (void *)par);
+io_unmap:
+	iounmap(par->mmio_base);
+fb_unmap:
+	iounmap(par->fb_base);
+rel_reg:
+	release_mem_region(res.start, res_size);
+irqdisp:
+	irq_dispose_mapping(par->irq);
+fbrel:
+	framebuffer_release(info);
+	return ret;
+}
+
+static int of_platform_mb862xx_remove(struct platform_device *ofdev)
+{
+	struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
+	struct mb862xxfb_par *par = fbi->par;
+	resource_size_t res_size = resource_size(par->res);
+	unsigned long reg;
+
+	dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
+
+	/* display off */
+	reg = inreg(disp, GC_DCM1);
+	reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
+	outreg(disp, GC_DCM1, reg);
+
+	/* disable interrupts */
+	outreg(host, GC_IMASK, 0);
+
+	free_irq(par->irq, (void *)par);
+	irq_dispose_mapping(par->irq);
+
+	device_remove_file(&ofdev->dev, &dev_attr_dispregs);
+
+	unregister_framebuffer(fbi);
+	fb_dealloc_cmap(&fbi->cmap);
+
+	iounmap(par->mmio_base);
+	iounmap(par->fb_base);
+
+	release_mem_region(par->res->start, res_size);
+	framebuffer_release(fbi);
+	return 0;
+}
+
+/*
+ * common types
+ */
+static struct of_device_id of_platform_mb862xx_tbl[] = {
+	{ .compatible = "fujitsu,MB86276", },
+	{ .compatible = "fujitsu,lime", },
+	{ .compatible = "fujitsu,MB86277", },
+	{ .compatible = "fujitsu,mint", },
+	{ .compatible = "fujitsu,MB86293", },
+	{ .compatible = "fujitsu,MB86294", },
+	{ .compatible = "fujitsu,coral", },
+	{ /* end */ }
+};
+
+static struct platform_driver of_platform_mb862xxfb_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_platform_mb862xx_tbl,
+	},
+	.probe		= of_platform_mb862xx_probe,
+	.remove		= of_platform_mb862xx_remove,
+};
+#endif
+
+#if defined(CONFIG_FB_MB862XX_PCI_GDC)
+static int coralp_init(struct mb862xxfb_par *par)
+{
+	int cn, ver;
+
+	par->host = par->mmio_base;
+	par->i2c = par->mmio_base + MB862XX_I2C_BASE;
+	par->disp = par->mmio_base + MB862XX_DISP_BASE;
+	par->cap = par->mmio_base + MB862XX_CAP_BASE;
+	par->draw = par->mmio_base + MB862XX_DRAW_BASE;
+	par->geo = par->mmio_base + MB862XX_GEO_BASE;
+	par->pio = par->mmio_base + MB862XX_PIO_BASE;
+
+	par->refclk = GC_DISP_REFCLK_400;
+
+	if (par->mapped_vram >= 0x2000000) {
+		/* relocate gdc registers space */
+		writel(1, par->fb_base + MB862XX_MMIO_BASE + GC_RSW);
+		udelay(1); /* wait at least 20 bus cycles */
+	}
+
+	ver = inreg(host, GC_CID);
+	cn = (ver & GC_CID_CNAME_MSK) >> 8;
+	ver = ver & GC_CID_VERSION_MSK;
+	if (cn == 3) {
+		unsigned long reg;
+
+		dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\
+			 (ver == 6) ? "P" : (ver == 8) ? "PA" : "?",
+			 par->pdev->revision);
+		reg = inreg(disp, GC_DCM1);
+		if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E)
+			par->pre_init = 1;
+
+		if (!par->pre_init) {
+			outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133);
+			udelay(200);
+			outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL);
+			udelay(10);
+		}
+		/* Clear interrupt status */
+		outreg(host, GC_IST, 0);
+	} else {
+		return -ENODEV;
+	}
+
+	mb862xx_i2c_init(par);
+	return 0;
+}
+
+static int init_dram_ctrl(struct mb862xxfb_par *par)
+{
+	unsigned long i = 0;
+
+	/*
+	 * Set io mode first! Spec. says IC may be destroyed
+	 * if not set to SSTL2/LVCMOS before init.
+	 */
+	outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0);
+
+	/* DRAM init */
+	outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD);
+	outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE);
+	outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2,
+	       GC_EVB_DCTL_REFRESH_SETTIME2);
+	outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1);
+	outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1);
+	outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES);
+
+	/* DLL reset done? */
+	while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) {
+		udelay(GC_DCTL_INIT_WAIT_INTERVAL);
+		if (i++ > GC_DCTL_INIT_WAIT_CNT) {
+			dev_err(par->dev, "VRAM init failed.\n");
+			return -EINVAL;
+		}
+	}
+	outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST);
+	outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST);
+	return 0;
+}
+
+static int carmine_init(struct mb862xxfb_par *par)
+{
+	unsigned long reg;
+
+	par->ctrl = par->mmio_base + MB86297_CTRL_BASE;
+	par->i2c = par->mmio_base + MB86297_I2C_BASE;
+	par->disp = par->mmio_base + MB86297_DISP0_BASE;
+	par->disp1 = par->mmio_base + MB86297_DISP1_BASE;
+	par->cap = par->mmio_base + MB86297_CAP0_BASE;
+	par->cap1 = par->mmio_base + MB86297_CAP1_BASE;
+	par->draw = par->mmio_base + MB86297_DRAW_BASE;
+	par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE;
+	par->wrback = par->mmio_base + MB86297_WRBACK_BASE;
+
+	par->refclk = GC_DISP_REFCLK_533;
+
+	/* warm up */
+	reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0;
+	outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
+
+	/* check for engine module revision */
+	if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION)
+		dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n",
+			 par->pdev->revision);
+	else
+		goto err_init;
+
+	reg &= ~GC_CTRL_CLK_EN_2D3D;
+	outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
+
+	/* set up vram */
+	if (init_dram_ctrl(par) < 0)
+		goto err_init;
+
+	outreg(ctrl, GC_CTRL_INT_MASK, 0);
+	return 0;
+
+err_init:
+	outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
+	return -EINVAL;
+}
+
+static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par)
+{
+	switch (par->type) {
+	case BT_CORALP:
+		return coralp_init(par);
+	case BT_CARMINE:
+		return carmine_init(par);
+	default:
+		return -ENODEV;
+	}
+}
+
+#define CHIP_ID(id)	\
+	{ PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) }
+
+static struct pci_device_id mb862xx_pci_tbl[] = {
+	/* MB86295/MB86296 */
+	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP),
+	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA),
+	/* MB86297 */
+	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE),
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl);
+
+static int mb862xx_pci_probe(struct pci_dev *pdev,
+			     const struct pci_device_id *ent)
+{
+	struct mb862xxfb_par *par;
+	struct fb_info *info;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0) {
+		dev_err(dev, "Cannot enable PCI device\n");
+		goto out;
+	}
+
+	info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
+	if (!info) {
+		dev_err(dev, "framebuffer alloc failed\n");
+		ret = -ENOMEM;
+		goto dis_dev;
+	}
+
+	par = info->par;
+	par->info = info;
+	par->dev = dev;
+	par->pdev = pdev;
+	par->irq = pdev->irq;
+
+	ret = pci_request_regions(pdev, DRV_NAME);
+	if (ret < 0) {
+		dev_err(dev, "Cannot reserve region(s) for PCI device\n");
+		goto rel_fb;
+	}
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_FUJITSU_CORALP:
+	case PCI_DEVICE_ID_FUJITSU_CORALPA:
+		par->fb_base_phys = pci_resource_start(par->pdev, 0);
+		par->mapped_vram = CORALP_MEM_SIZE;
+		if (par->mapped_vram >= 0x2000000) {
+			par->mmio_base_phys = par->fb_base_phys +
+					      MB862XX_MMIO_HIGH_BASE;
+		} else {
+			par->mmio_base_phys = par->fb_base_phys +
+					      MB862XX_MMIO_BASE;
+		}
+		par->mmio_len = MB862XX_MMIO_SIZE;
+		par->type = BT_CORALP;
+		break;
+	case PCI_DEVICE_ID_FUJITSU_CARMINE:
+		par->fb_base_phys = pci_resource_start(par->pdev, 2);
+		par->mmio_base_phys = pci_resource_start(par->pdev, 3);
+		par->mmio_len = pci_resource_len(par->pdev, 3);
+		par->mapped_vram = CARMINE_MEM_SIZE;
+		par->type = BT_CARMINE;
+		break;
+	default:
+		/* should never occur */
+		ret = -EIO;
+		goto rel_reg;
+	}
+
+	par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
+	if (par->fb_base == NULL) {
+		dev_err(dev, "Cannot map framebuffer\n");
+		ret = -EIO;
+		goto rel_reg;
+	}
+
+	par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
+	if (par->mmio_base == NULL) {
+		dev_err(dev, "Cannot map registers\n");
+		ret = -EIO;
+		goto fb_unmap;
+	}
+
+	dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
+		(unsigned long long)par->fb_base_phys, (ulong)par->mapped_vram);
+	dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
+		(unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
+
+	ret = mb862xx_pci_gdc_init(par);
+	if (ret)
+		goto io_unmap;
+
+	ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
+			  DRV_NAME, (void *)par);
+	if (ret) {
+		dev_err(dev, "Cannot request irq\n");
+		goto io_unmap;
+	}
+
+	mb862xxfb_init_fbinfo(info);
+
+	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
+		dev_err(dev, "Could not allocate cmap for fb_info.\n");
+		ret = -ENOMEM;
+		goto free_irq;
+	}
+
+	if ((info->fbops->fb_set_par)(info))
+		dev_err(dev, "set_var() failed on initial setup?\n");
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(dev, "failed to register framebuffer\n");
+		goto rel_cmap;
+	}
+
+	pci_set_drvdata(pdev, info);
+
+	if (device_create_file(dev, &dev_attr_dispregs))
+		dev_err(dev, "Can't create sysfs regdump file\n");
+
+	if (par->type == BT_CARMINE)
+		outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN);
+	else
+		outreg(host, GC_IMASK, GC_INT_EN);
+
+	return 0;
+
+rel_cmap:
+	fb_dealloc_cmap(&info->cmap);
+free_irq:
+	free_irq(par->irq, (void *)par);
+io_unmap:
+	iounmap(par->mmio_base);
+fb_unmap:
+	iounmap(par->fb_base);
+rel_reg:
+	pci_release_regions(pdev);
+rel_fb:
+	framebuffer_release(info);
+dis_dev:
+	pci_disable_device(pdev);
+out:
+	return ret;
+}
+
+static void mb862xx_pci_remove(struct pci_dev *pdev)
+{
+	struct fb_info *fbi = pci_get_drvdata(pdev);
+	struct mb862xxfb_par *par = fbi->par;
+	unsigned long reg;
+
+	dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
+
+	/* display off */
+	reg = inreg(disp, GC_DCM1);
+	reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
+	outreg(disp, GC_DCM1, reg);
+
+	if (par->type == BT_CARMINE) {
+		outreg(ctrl, GC_CTRL_INT_MASK, 0);
+		outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
+	} else {
+		outreg(host, GC_IMASK, 0);
+	}
+
+	mb862xx_i2c_exit(par);
+
+	device_remove_file(&pdev->dev, &dev_attr_dispregs);
+
+	unregister_framebuffer(fbi);
+	fb_dealloc_cmap(&fbi->cmap);
+
+	free_irq(par->irq, (void *)par);
+	iounmap(par->mmio_base);
+	iounmap(par->fb_base);
+
+	pci_release_regions(pdev);
+	framebuffer_release(fbi);
+	pci_disable_device(pdev);
+}
+
+static struct pci_driver mb862xxfb_pci_driver = {
+	.name		= DRV_NAME,
+	.id_table	= mb862xx_pci_tbl,
+	.probe		= mb862xx_pci_probe,
+	.remove		= mb862xx_pci_remove,
+};
+#endif
+
+static int mb862xxfb_init(void)
+{
+	int ret = -ENODEV;
+
+#if defined(CONFIG_FB_MB862XX_LIME)
+	ret = platform_driver_register(&of_platform_mb862xxfb_driver);
+#endif
+#if defined(CONFIG_FB_MB862XX_PCI_GDC)
+	ret = pci_register_driver(&mb862xxfb_pci_driver);
+#endif
+	return ret;
+}
+
+static void __exit mb862xxfb_exit(void)
+{
+#if defined(CONFIG_FB_MB862XX_LIME)
+	platform_driver_unregister(&of_platform_mb862xxfb_driver);
+#endif
+#if defined(CONFIG_FB_MB862XX_PCI_GDC)
+	pci_unregister_driver(&mb862xxfb_pci_driver);
+#endif
+}
+
+module_init(mb862xxfb_init);
+module_exit(mb862xxfb_exit);
+
+MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/mbx/Makefile b/drivers/video/fbdev/mbx/Makefile
new file mode 100644
index 000000000000..16c1165cf9c7
--- /dev/null
+++ b/drivers/video/fbdev/mbx/Makefile
@@ -0,0 +1,4 @@
+# Makefile for the 2700G controller driver.
+
+obj-$(CONFIG_FB_MBX)	   += mbxfb.o
+obj-$(CONFIG_FB_MBX_DEBUG) += mbxfbdebugfs.o
diff --git a/drivers/video/fbdev/mbx/mbxdebugfs.c b/drivers/video/fbdev/mbx/mbxdebugfs.c
new file mode 100644
index 000000000000..4449f249b0e7
--- /dev/null
+++ b/drivers/video/fbdev/mbx/mbxdebugfs.c
@@ -0,0 +1,251 @@
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+
+#define BIG_BUFFER_SIZE	(1024)
+
+static char big_buffer[BIG_BUFFER_SIZE];
+
+struct mbxfb_debugfs_data {
+	struct dentry *dir;
+	struct dentry *sysconf;
+	struct dentry *clock;
+	struct dentry *display;
+	struct dentry *gsctl;
+	struct dentry *sdram;
+	struct dentry *misc;
+};
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->u.generic_ip;
+	return 0;
+}
+
+static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	return count;
+}
+
+static ssize_t sysconf_read_file(struct file *file, char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	char * s = big_buffer;
+
+	s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG));
+	s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE));
+	s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL));
+	s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG));
+	s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST));
+
+	return  simple_read_from_buffer(userbuf, count, ppos,
+					big_buffer, s-big_buffer);
+}
+
+
+static ssize_t gsctl_read_file(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	char * s = big_buffer;
+
+	s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL));
+	s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL));
+	s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE));
+	s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE));
+	s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL));
+	s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK));
+	s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR));
+	s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR));
+	s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE));
+	s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE));
+	s += sprintf(s, "GSADR = %08x\n", readl(GSADR));
+	s += sprintf(s, "VSADR = %08x\n", readl(VSADR));
+	s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL));
+	s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE));
+	s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS));
+	s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR));
+	s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK));
+	s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT));
+
+	return  simple_read_from_buffer(userbuf, count, ppos,
+					big_buffer, s-big_buffer);
+}
+
+static ssize_t display_read_file(struct file *file, char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	char * s = big_buffer;
+
+	s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL));
+	s += sprintf(s, "DHT01 = %08x\n", readl(DHT01));
+	s += sprintf(s, "DHT02 = %08x\n", readl(DHT02));
+	s += sprintf(s, "DHT03 = %08x\n", readl(DHT03));
+	s += sprintf(s, "DVT01 = %08x\n", readl(DVT01));
+	s += sprintf(s, "DVT02 = %08x\n", readl(DVT02));
+	s += sprintf(s, "DVT03 = %08x\n", readl(DVT03));
+	s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL));
+	s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR));
+	s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS));
+	s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE));
+	s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT));
+	s += sprintf(s, "DSIG = %08x\n", readl(DSIG));
+	s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL));
+	s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL));
+	s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL));
+	s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL));
+	s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS));
+	s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL));
+	s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM));
+	s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL));
+	s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL));
+	s += sprintf(s, "DHDET = %08x\n", readl(DHDET));
+	s += sprintf(s, "DVDET = %08x\n", readl(DVDET));
+	s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK));
+	s += sprintf(s, "CSC01 = %08x\n", readl(CSC01));
+	s += sprintf(s, "CSC02 = %08x\n", readl(CSC02));
+	s += sprintf(s, "CSC03 = %08x\n", readl(CSC03));
+	s += sprintf(s, "CSC04 = %08x\n", readl(CSC04));
+	s += sprintf(s, "CSC05 = %08x\n", readl(CSC05));
+
+	return  simple_read_from_buffer(userbuf, count, ppos,
+					big_buffer, s-big_buffer);
+}
+
+static ssize_t clock_read_file(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	char * s = big_buffer;
+
+	s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC));
+	s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC));
+	s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP));
+	s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL));
+	s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL));
+	s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT));
+	s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK));
+	s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK));
+	s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK));
+	s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK));
+	s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK));
+	s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK));
+	s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV));
+
+	return  simple_read_from_buffer(userbuf, count, ppos,
+					big_buffer, s-big_buffer);
+}
+
+static ssize_t sdram_read_file(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	char * s = big_buffer;
+
+	s += sprintf(s, "LMRST = %08x\n", readl(LMRST));
+	s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG));
+	s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR));
+	s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT));
+	s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR));
+	s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE));
+	s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM));
+	s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH));
+	s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN));
+	s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX));
+	s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG));
+	s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR));
+
+	return  simple_read_from_buffer(userbuf, count, ppos,
+					big_buffer, s-big_buffer);
+}
+
+static ssize_t misc_read_file(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	char * s = big_buffer;
+
+	s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG));
+	s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR));
+	s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT));
+	s += sprintf(s, "ID = %08x\n", readl(ID));
+
+	return  simple_read_from_buffer(userbuf, count, ppos,
+					big_buffer, s-big_buffer);
+}
+
+
+static const struct file_operations sysconf_fops = {
+	.read = sysconf_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+	.llseek = default_llseek,
+};
+
+static const struct file_operations clock_fops = {
+	.read = clock_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+	.llseek = default_llseek,
+};
+
+static const struct file_operations display_fops = {
+	.read = display_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+	.llseek = default_llseek,
+};
+
+static const struct file_operations gsctl_fops = {
+	.read = gsctl_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+	.llseek = default_llseek,
+};
+
+static const struct file_operations sdram_fops = {
+	.read = sdram_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+	.llseek = default_llseek,
+};
+
+static const struct file_operations misc_fops = {
+	.read = misc_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+	.llseek = default_llseek,
+};
+
+static void mbxfb_debugfs_init(struct fb_info *fbi)
+{
+	struct mbxfb_info *mfbi = fbi->par;
+	struct mbxfb_debugfs_data *dbg;
+
+	dbg = kzalloc(sizeof(struct mbxfb_debugfs_data), GFP_KERNEL);
+	mfbi->debugfs_data = dbg;
+
+	dbg->dir = debugfs_create_dir("mbxfb", NULL);
+	dbg->sysconf = debugfs_create_file("sysconf", 0444, dbg->dir,
+				      fbi, &sysconf_fops);
+	dbg->clock = debugfs_create_file("clock", 0444, dbg->dir,
+				    fbi, &clock_fops);
+	dbg->display = debugfs_create_file("display", 0444, dbg->dir,
+				      fbi, &display_fops);
+	dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir,
+				    fbi, &gsctl_fops);
+	dbg->sdram = debugfs_create_file("sdram", 0444, dbg->dir,
+					fbi, &sdram_fops);
+	dbg->misc = debugfs_create_file("misc", 0444, dbg->dir,
+					fbi, &misc_fops);
+}
+
+static void mbxfb_debugfs_remove(struct fb_info *fbi)
+{
+	struct mbxfb_info *mfbi = fbi->par;
+	struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data;
+
+	debugfs_remove(dbg->misc);
+	debugfs_remove(dbg->sdram);
+	debugfs_remove(dbg->gsctl);
+	debugfs_remove(dbg->display);
+	debugfs_remove(dbg->clock);
+	debugfs_remove(dbg->sysconf);
+	debugfs_remove(dbg->dir);
+}
diff --git a/drivers/video/fbdev/mbx/mbxfb.c b/drivers/video/fbdev/mbx/mbxfb.c
new file mode 100644
index 000000000000..f0a5392f5fd3
--- /dev/null
+++ b/drivers/video/fbdev/mbx/mbxfb.c
@@ -0,0 +1,1053 @@
+/*
+ *  linux/drivers/video/mbx/mbxfb.c
+ *
+ *  Copyright (C) 2006-2007 8D Technologies inc
+ *  Raphael Assenat <raph@8d.com>
+ *  	- Added video overlay support
+ *  	- Various improvements
+ *
+ *  Copyright (C) 2006 Compulab, Ltd.
+ *  Mike Rapoport <mike@compulab.co.il>
+ *  	- Creation of driver
+ *
+ *   Based on pxafb.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *   Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <video/mbxfb.h>
+
+#include "regs.h"
+#include "reg_bits.h"
+
+static void __iomem *virt_base_2700;
+
+#define write_reg(val, reg) do { writel((val), (reg)); } while(0)
+
+/* Without this delay, the graphics appears somehow scaled and
+ * there is a lot of jitter in scanlines. This delay is probably
+ * needed only after setting some specific register(s) somewhere,
+ * not all over the place... */
+#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0)
+
+#define MIN_XRES	16
+#define MIN_YRES	16
+#define MAX_XRES	2048
+#define MAX_YRES	2048
+
+#define MAX_PALETTES	16
+
+/* FIXME: take care of different chip revisions with different sizes
+   of ODFB */
+#define MEMORY_OFFSET	0x60000
+
+struct mbxfb_info {
+	struct device *dev;
+
+	struct resource *fb_res;
+	struct resource *fb_req;
+
+	struct resource *reg_res;
+	struct resource *reg_req;
+
+	void __iomem *fb_virt_addr;
+	unsigned long fb_phys_addr;
+
+	void __iomem *reg_virt_addr;
+	unsigned long reg_phys_addr;
+
+	int (*platform_probe) (struct fb_info * fb);
+	int (*platform_remove) (struct fb_info * fb);
+
+	u32 pseudo_palette[MAX_PALETTES];
+#ifdef CONFIG_FB_MBX_DEBUG
+	void *debugfs_data;
+#endif
+
+};
+
+static struct fb_var_screeninfo mbxfb_default = {
+	.xres = 640,
+	.yres = 480,
+	.xres_virtual = 640,
+	.yres_virtual = 480,
+	.bits_per_pixel = 16,
+	.red = {11, 5, 0},
+	.green = {5, 6, 0},
+	.blue = {0, 5, 0},
+	.activate = FB_ACTIVATE_TEST,
+	.height = -1,
+	.width = -1,
+	.pixclock = 40000,
+	.left_margin = 48,
+	.right_margin = 16,
+	.upper_margin = 33,
+	.lower_margin = 10,
+	.hsync_len = 96,
+	.vsync_len = 2,
+	.vmode = FB_VMODE_NONINTERLACED,
+	.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct fb_fix_screeninfo mbxfb_fix = {
+	.id = "MBX",
+	.type = FB_TYPE_PACKED_PIXELS,
+	.visual = FB_VISUAL_TRUECOLOR,
+	.xpanstep = 0,
+	.ypanstep = 0,
+	.ywrapstep = 0,
+	.accel = FB_ACCEL_NONE,
+};
+
+struct pixclock_div {
+	u8 m;
+	u8 n;
+	u8 p;
+};
+
+static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps,
+				       struct pixclock_div *div)
+{
+	u8 m, n, p;
+	unsigned int err = 0;
+	unsigned int min_err = ~0x0;
+	unsigned int clk;
+	unsigned int best_clk = 0;
+	unsigned int ref_clk = 13000;	/* FIXME: take from platform data */
+	unsigned int pixclock;
+
+	/* convert pixclock to KHz */
+	pixclock = PICOS2KHZ(pixclock_ps);
+
+	/* PLL output freq = (ref_clk * M) / (N * 2^P)
+	 *
+	 * M: 1 to 63
+	 * N: 1 to 7
+	 * P: 0 to 7
+	 */
+
+	/* RAPH: When N==1, the resulting pixel clock appears to
+	 * get divided by 2. Preventing N=1 by starting the following
+	 * loop at 2 prevents this. Is this a bug with my chip
+	 * revision or something I dont understand? */
+	for (m = 1; m < 64; m++) {
+		for (n = 2; n < 8; n++) {
+			for (p = 0; p < 8; p++) {
+				clk = (ref_clk * m) / (n * (1 << p));
+				err = (clk > pixclock) ? (clk - pixclock) :
+					(pixclock - clk);
+				if (err < min_err) {
+					min_err = err;
+					best_clk = clk;
+					div->m = m;
+					div->n = n;
+					div->p = p;
+				}
+			}
+		}
+	}
+	return KHZ2PICOS(best_clk);
+}
+
+static int mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int trans, struct fb_info *info)
+{
+	u32 val, ret = 1;
+
+	if (regno < MAX_PALETTES) {
+		u32 *pal = info->pseudo_palette;
+
+		val = (red & 0xf800) | ((green & 0xfc00) >> 5) |
+			((blue & 0xf800) >> 11);
+		pal[regno] = val;
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct pixclock_div div;
+
+	var->pixclock = mbxfb_get_pixclock(var->pixclock, &div);
+
+	if (var->xres < MIN_XRES)
+		var->xres = MIN_XRES;
+	if (var->yres < MIN_YRES)
+		var->yres = MIN_YRES;
+	if (var->xres > MAX_XRES)
+		return -EINVAL;
+	if (var->yres > MAX_YRES)
+		return -EINVAL;
+	var->xres_virtual = max(var->xres_virtual, var->xres);
+	var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	switch (var->bits_per_pixel) {
+		/* 8 bits-per-pixel is not supported yet */
+	case 8:
+		return -EINVAL;
+	case 16:
+		var->green.length = (var->green.length == 5) ? 5 : 6;
+		var->red.length = 5;
+		var->blue.length = 5;
+		var->transp.length = 6 - var->green.length;
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 5 + var->green.length;
+		var->transp.offset = (5 + var->red.offset) & 15;
+		break;
+	case 24:		/* RGB 888   */
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.length = var->bits_per_pixel - 24;
+		var->transp.offset = (var->transp.length) ? 24 : 0;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+static int mbxfb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct pixclock_div div;
+	ushort hbps, ht, hfps, has;
+	ushort vbps, vt, vfps, vas;
+	u32 gsctrl = readl(GSCTRL);
+	u32 gsadr = readl(GSADR);
+
+	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+	/* setup color mode */
+	gsctrl &= ~(FMsk(GSCTRL_GPIXFMT));
+	/* FIXME: add *WORKING* support for 8-bits per color */
+	if (info->var.bits_per_pixel == 8) {
+		return -EINVAL;
+	} else {
+		fb_dealloc_cmap(&info->cmap);
+		gsctrl &= ~GSCTRL_LUT_EN;
+
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		switch (info->var.bits_per_pixel) {
+		case 16:
+			if (info->var.green.length == 5)
+				gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
+			else
+				gsctrl |= GSCTRL_GPIXFMT_RGB565;
+			break;
+		case 24:
+			gsctrl |= GSCTRL_GPIXFMT_RGB888;
+			break;
+		case 32:
+			gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
+			break;
+		}
+	}
+
+	/* setup resolution */
+	gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT));
+	gsctrl |= Gsctrl_Width(info->var.xres) |
+		Gsctrl_Height(info->var.yres);
+	write_reg_dly(gsctrl, GSCTRL);
+
+	gsadr &= ~(FMsk(GSADR_SRCSTRIDE));
+	gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel /
+				 (8 * 16) - 1);
+	write_reg_dly(gsadr, GSADR);
+
+	/* setup timings */
+	var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div);
+
+	write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
+		Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL);
+
+	hbps = var->hsync_len;
+	has = hbps + var->left_margin;
+	hfps = has + var->xres;
+	ht = hfps + var->right_margin;
+
+	vbps = var->vsync_len;
+	vas = vbps + var->upper_margin;
+	vfps = vas + var->yres;
+	vt = vfps + var->lower_margin;
+
+	write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
+	write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
+	write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
+	write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
+
+	write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
+	write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
+	write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
+	write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
+	write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
+
+	write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+
+	write_reg_dly(DINTRE_VEVENT0_EN, DINTRE);
+
+	return 0;
+}
+
+static int mbxfb_blank(int blank, struct fb_info *info)
+{
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
+		write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
+		write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
+		break;
+	case FB_BLANK_UNBLANK:
+		write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+		write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
+		break;
+	}
+	return 0;
+}
+
+static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
+{
+	u32 vsctrl, vscadr, vsadr;
+	u32 sssize, spoctrl, shctrl;
+	u32 vubase, vvbase;
+	u32 vovrclk;
+
+	if (set->scaled_width==0 || set->scaled_height==0)
+		return -EINVAL;
+
+	/* read registers which have reserved bits
+	 * so we can write them back as-is. */
+	vovrclk = readl(VOVRCLK);
+	vsctrl = readl(VSCTRL);
+	vscadr = readl(VSCADR);
+	vubase = readl(VUBASE);
+	vvbase = readl(VVBASE);
+	shctrl = readl(SHCTRL);
+
+	spoctrl = readl(SPOCTRL);
+	sssize = readl(SSSIZE);
+
+	vsctrl &= ~(	FMsk(VSCTRL_VSWIDTH) |
+					FMsk(VSCTRL_VSHEIGHT) |
+					FMsk(VSCTRL_VPIXFMT) |
+					VSCTRL_GAMMA_EN | VSCTRL_CSC_EN |
+					VSCTRL_COSITED );
+	vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) |
+				VSCTRL_CSC_EN;
+
+	vscadr &= ~(VSCADR_STR_EN | FMsk(VSCADR_VBASE_ADR) );
+	vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR));
+	vvbase &= ~(FMsk(VVBASE_VBASE_ADR));
+
+	switch (set->fmt) {
+	case MBXFB_FMT_YUV16:
+		vsctrl |= VSCTRL_VPIXFMT_YUV12;
+
+		set->Y_stride = ((set->width) + 0xf ) & ~0xf;
+		break;
+	case MBXFB_FMT_YUV12:
+		vsctrl |= VSCTRL_VPIXFMT_YUV12;
+
+		set->Y_stride = ((set->width) + 0xf ) & ~0xf;
+		vubase |= VUBASE_UVHALFSTR;
+
+		break;
+	case MBXFB_FMT_UY0VY1:
+		vsctrl |= VSCTRL_VPIXFMT_UY0VY1;
+		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+		break;
+	case MBXFB_FMT_VY0UY1:
+		vsctrl |= VSCTRL_VPIXFMT_VY0UY1;
+		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+		break;
+	case MBXFB_FMT_Y0UY1V:
+		vsctrl |= VSCTRL_VPIXFMT_Y0UY1V;
+		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+		break;
+	case MBXFB_FMT_Y0VY1U:
+		vsctrl |= VSCTRL_VPIXFMT_Y0VY1U;
+		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+			break;
+	default:
+		return -EINVAL;
+	}
+
+	/* VSCTRL has the bits which sets the Video Pixel Format.
+	 * When passing from a packed to planar format,
+	 * if we write VSCTRL first, VVBASE and VUBASE would
+	 * be zero if we would not set them here. (And then,
+	 * the chips hangs and only a reset seems to fix it).
+	 *
+	 * If course, the values calculated here have no meaning
+	 * for packed formats.
+	 */
+	set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7;
+		set->U_offset = set->height * set->Y_stride;
+		set->V_offset = set->U_offset +
+						set->height * set->UV_stride;
+	vubase |= Vubase_Ubase_Adr(
+			(0x60000 + set->mem_offset + set->U_offset)>>3);
+	vvbase |= Vvbase_Vbase_Adr(
+			(0x60000 + set->mem_offset + set->V_offset)>>3);
+
+
+	vscadr |= Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4);
+
+	if (set->enable)
+		vscadr |= VSCADR_STR_EN;
+
+
+	vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) |
+		Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y);
+
+	sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT));
+	sssize = Sssize_Sc_Width(set->scaled_width-1) |
+			Sssize_Sc_Height(set->scaled_height-1);
+
+	spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP |
+			SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C |
+			FMsk(SPOCTRL_VPITCH));
+	spoctrl |= Spoctrl_Vpitch((set->height<<11)/set->scaled_height);
+
+	/* Bypass horiz/vert scaler when same size */
+	if (set->scaled_width == set->width)
+		spoctrl |= SPOCTRL_H_SC_BP;
+	if (set->scaled_height == set->height)
+		spoctrl |= SPOCTRL_V_SC_BP;
+
+	shctrl &= ~(FMsk(SHCTRL_HPITCH) | SHCTRL_HDECIM);
+	shctrl |= Shctrl_Hpitch((set->width<<11)/set->scaled_width);
+
+	/* Video plane registers */
+	write_reg(vsctrl, VSCTRL);
+	write_reg(vscadr, VSCADR);
+	write_reg(vubase, VUBASE);
+	write_reg(vvbase, VVBASE);
+	write_reg(vsadr, VSADR);
+
+	/* Video scaler registers */
+	write_reg(sssize, SSSIZE);
+	write_reg(spoctrl, SPOCTRL);
+	write_reg(shctrl, SHCTRL);
+
+	/* Clock */
+	if (set->enable)
+		vovrclk |= 1;
+	else
+		vovrclk &= ~1;
+
+	write_reg(vovrclk, VOVRCLK);
+
+	return 0;
+}
+
+static int mbxfb_ioctl_planeorder(struct mbxfb_planeorder *porder)
+{
+	unsigned long gscadr, vscadr;
+
+	if (porder->bottom == porder->top)
+		return -EINVAL;
+
+	gscadr = readl(GSCADR);
+	vscadr = readl(VSCADR);
+
+	gscadr &= ~(FMsk(GSCADR_BLEND_POS));
+	vscadr &= ~(FMsk(VSCADR_BLEND_POS));
+
+	switch (porder->bottom) {
+	case MBXFB_PLANE_GRAPHICS:
+		gscadr |= GSCADR_BLEND_GFX;
+		break;
+	case MBXFB_PLANE_VIDEO:
+		vscadr |= VSCADR_BLEND_GFX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (porder->top) {
+	case MBXFB_PLANE_GRAPHICS:
+		gscadr |= GSCADR_BLEND_VID;
+		break;
+	case MBXFB_PLANE_VIDEO:
+		vscadr |= GSCADR_BLEND_VID;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	write_reg_dly(vscadr, VSCADR);
+	write_reg_dly(gscadr, GSCADR);
+
+	return 0;
+
+}
+
+static int mbxfb_ioctl_alphactl(struct mbxfb_alphaCtl *alpha)
+{
+	unsigned long vscadr, vbbase, vcmsk;
+	unsigned long gscadr, gbbase, gdrctrl;
+
+	vbbase = Vbbase_Glalpha(alpha->overlay_global_alpha) |
+				Vbbase_Colkey(alpha->overlay_colorkey);
+
+	gbbase = Gbbase_Glalpha(alpha->graphics_global_alpha) |
+				Gbbase_Colkey(alpha->graphics_colorkey);
+
+	vcmsk = readl(VCMSK);
+	vcmsk &= ~(FMsk(VCMSK_COLKEY_M));
+	vcmsk |= Vcmsk_colkey_m(alpha->overlay_colorkey_mask);
+
+	gdrctrl = readl(GDRCTRL);
+	gdrctrl &= ~(FMsk(GDRCTRL_COLKEYM));
+	gdrctrl |= Gdrctrl_Colkeym(alpha->graphics_colorkey_mask);
+
+	vscadr = readl(VSCADR);
+	vscadr &= ~(FMsk(VSCADR_BLEND_M) | VSCADR_COLKEYSRC | VSCADR_COLKEY_EN);
+
+	gscadr = readl(GSCADR);
+	gscadr &= ~(FMsk(GSCADR_BLEND_M) | GSCADR_COLKEY_EN | GSCADR_COLKEYSRC);
+
+	switch (alpha->overlay_colorkey_mode) {
+	case MBXFB_COLORKEY_DISABLED:
+		break;
+	case MBXFB_COLORKEY_PREVIOUS:
+		vscadr |= VSCADR_COLKEY_EN;
+		break;
+	case MBXFB_COLORKEY_CURRENT:
+		vscadr |= VSCADR_COLKEY_EN | VSCADR_COLKEYSRC;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (alpha->overlay_blend_mode) {
+	case MBXFB_ALPHABLEND_NONE:
+		vscadr |= VSCADR_BLEND_NONE;
+		break;
+	case MBXFB_ALPHABLEND_GLOBAL:
+		vscadr |= VSCADR_BLEND_GLOB;
+		break;
+	case MBXFB_ALPHABLEND_PIXEL:
+		vscadr |= VSCADR_BLEND_PIX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (alpha->graphics_colorkey_mode) {
+	case MBXFB_COLORKEY_DISABLED:
+		break;
+	case MBXFB_COLORKEY_PREVIOUS:
+		gscadr |= GSCADR_COLKEY_EN;
+		break;
+	case MBXFB_COLORKEY_CURRENT:
+		gscadr |= GSCADR_COLKEY_EN | GSCADR_COLKEYSRC;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (alpha->graphics_blend_mode) {
+	case MBXFB_ALPHABLEND_NONE:
+		gscadr |= GSCADR_BLEND_NONE;
+		break;
+	case MBXFB_ALPHABLEND_GLOBAL:
+		gscadr |= GSCADR_BLEND_GLOB;
+		break;
+	case MBXFB_ALPHABLEND_PIXEL:
+		gscadr |= GSCADR_BLEND_PIX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	write_reg_dly(vbbase, VBBASE);
+	write_reg_dly(gbbase, GBBASE);
+	write_reg_dly(vcmsk, VCMSK);
+	write_reg_dly(gdrctrl, GDRCTRL);
+	write_reg_dly(gscadr, GSCADR);
+	write_reg_dly(vscadr, VSCADR);
+
+	return 0;
+}
+
+static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd,
+				unsigned long arg)
+{
+	struct mbxfb_overlaySetup	setup;
+	struct mbxfb_planeorder 	porder;
+	struct mbxfb_alphaCtl 		alpha;
+	struct mbxfb_reg			reg;
+	int res;
+	__u32 tmp;
+
+	switch (cmd)
+	{
+		case MBXFB_IOCX_OVERLAY:
+			if (copy_from_user(&setup, (void __user*)arg,
+						sizeof(struct mbxfb_overlaySetup)))
+				return -EFAULT;
+
+			res = mbxfb_setupOverlay(&setup);
+			if (res)
+				return res;
+
+			if (copy_to_user((void __user*)arg, &setup,
+						sizeof(struct mbxfb_overlaySetup)))
+				return -EFAULT;
+
+			return 0;
+
+		case MBXFB_IOCS_PLANEORDER:
+			if (copy_from_user(&porder, (void __user*)arg,
+					sizeof(struct mbxfb_planeorder)))
+			return -EFAULT;
+
+			return mbxfb_ioctl_planeorder(&porder);
+
+		case MBXFB_IOCS_ALPHA:
+			if (copy_from_user(&alpha, (void __user*)arg,
+					sizeof(struct mbxfb_alphaCtl)))
+			return -EFAULT;
+
+			return mbxfb_ioctl_alphactl(&alpha);
+
+		case MBXFB_IOCS_REG:
+			if (copy_from_user(&reg, (void __user*)arg,
+						sizeof(struct mbxfb_reg)))
+				return -EFAULT;
+
+			if (reg.addr >= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
+				return -EINVAL;
+
+			tmp = readl(virt_base_2700 + reg.addr);
+			tmp &= ~reg.mask;
+			tmp |= reg.val & reg.mask;
+			writel(tmp, virt_base_2700 + reg.addr);
+
+			return 0;
+		case MBXFB_IOCX_REG:
+			if (copy_from_user(&reg, (void __user*)arg,
+						sizeof(struct mbxfb_reg)))
+				return -EFAULT;
+
+			if (reg.addr >= 0x10000)	/* regs are from 0x3fe0000 to 0x3feffff */
+				return -EINVAL;
+			reg.val = readl(virt_base_2700 + reg.addr);
+
+			if (copy_to_user((void __user*)arg, &reg,
+						sizeof(struct mbxfb_reg)))
+				return -EFAULT;
+
+			return 0;
+	}
+	return -EINVAL;
+}
+
+static struct fb_ops mbxfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = mbxfb_check_var,
+	.fb_set_par = mbxfb_set_par,
+	.fb_setcolreg = mbxfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_blank = mbxfb_blank,
+	.fb_ioctl = mbxfb_ioctl,
+};
+
+/*
+  Enable external SDRAM controller. Assume that all clocks are active
+  by now.
+*/
+static void setup_memc(struct fb_info *fbi)
+{
+	unsigned long tmp;
+	int i;
+
+	/* FIXME: use platform specific parameters */
+	/* setup SDRAM controller */
+	write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
+		LMCFG_LMA_TS),
+	       LMCFG);
+
+	write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
+
+	/* setup SDRAM timings */
+	write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
+		Lmtim_Trc(9) | Lmtim_Tdpl(2)),
+	       LMTIM);
+	/* setup SDRAM refresh rate */
+	write_reg_dly(0xc2b, LMREFRESH);
+	/* setup SDRAM type parameters */
+	write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
+		LMTYPE_COLSZ_8),
+	       LMTYPE);
+	/* enable memory controller */
+	write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
+	/* perform dummy reads */
+	for ( i = 0; i < 16; i++ ) {
+		tmp = readl(fbi->screen_base);
+	}
+}
+
+static void enable_clocks(struct fb_info *fbi)
+{
+	/* enable clocks */
+	write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC);
+	write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC);
+	write_reg_dly(0x00000000, CLKSLEEP);
+
+	/* PLL output = (Frefclk * M) / (N * 2^P )
+	 *
+	 * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
+	 * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
+	 * */
+	write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
+		CORE_PLL_EN),
+	       COREPLL);
+
+	write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
+		DISP_PLL_EN),
+	       DISPPLL);
+
+	write_reg_dly(0x00000000, VOVRCLK);
+	write_reg_dly(PIXCLK_EN, PIXCLK);
+	write_reg_dly(MEMCLK_EN, MEMCLK);
+	write_reg_dly(0x00000001, M24CLK);
+	write_reg_dly(0x00000001, MBXCLK);
+	write_reg_dly(SDCLK_EN, SDCLK);
+	write_reg_dly(0x00000001, PIXCLKDIV);
+}
+
+static void setup_graphics(struct fb_info *fbi)
+{
+	unsigned long gsctrl;
+	unsigned long vscadr;
+
+	gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres) |
+		Gsctrl_Height(fbi->var.yres);
+	switch (fbi->var.bits_per_pixel) {
+	case 16:
+		if (fbi->var.green.length == 5)
+			gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
+		else
+			gsctrl |= GSCTRL_GPIXFMT_RGB565;
+		break;
+	case 24:
+		gsctrl |= GSCTRL_GPIXFMT_RGB888;
+		break;
+	case 32:
+		gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
+		break;
+	}
+
+	write_reg_dly(gsctrl, GSCTRL);
+	write_reg_dly(0x00000000, GBBASE);
+	write_reg_dly(0x00ffffff, GDRCTRL);
+	write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
+	write_reg_dly(0x00000000, GPLUT);
+
+	vscadr = readl(VSCADR);
+	vscadr &= ~(FMsk(VSCADR_BLEND_POS) | FMsk(VSCADR_BLEND_M));
+	vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_NONE;
+	write_reg_dly(vscadr, VSCADR);
+}
+
+static void setup_display(struct fb_info *fbi)
+{
+	unsigned long dsctrl = 0;
+
+	dsctrl = DSCTRL_BLNK_POL;
+	if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		dsctrl |= DSCTRL_HS_POL;
+	if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		dsctrl |= DSCTRL_VS_POL;
+	write_reg_dly(dsctrl, DSCTRL);
+	write_reg_dly(0xd0303010, DMCTRL);
+	write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+}
+
+static void enable_controller(struct fb_info *fbi)
+{
+	u32 svctrl, shctrl;
+
+	write_reg_dly(SYSRST_RST, SYSRST);
+
+	/* setup a timeout, raise drive strength */
+	write_reg_dly(0xffffff0c, SYSCFG);
+
+	enable_clocks(fbi);
+	setup_memc(fbi);
+	setup_graphics(fbi);
+	setup_display(fbi);
+
+	shctrl = readl(SHCTRL);
+	shctrl &= ~(FMsk(SHCTRL_HINITIAL));
+	shctrl |= Shctrl_Hinitial(4<<11);
+	writel(shctrl, SHCTRL);
+
+	svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
+	writel(svctrl, SVCTRL);
+
+	writel(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | SPOCTRL_VORDER_4TAP
+			, SPOCTRL);
+
+	/* Those coefficients are good for scaling up. For scaling
+	 * down, the application has to calculate them. */
+	write_reg(0xff000100, VSCOEFF0);
+	write_reg(0xfdfcfdfe, VSCOEFF1);
+	write_reg(0x170d0500, VSCOEFF2);
+	write_reg(0x3d372d22, VSCOEFF3);
+	write_reg(0x00000040, VSCOEFF4);
+
+	write_reg(0xff010100, HSCOEFF0);
+	write_reg(0x00000000, HSCOEFF1);
+	write_reg(0x02010000, HSCOEFF2);
+	write_reg(0x01020302, HSCOEFF3);
+	write_reg(0xf9fbfe00, HSCOEFF4);
+	write_reg(0xfbf7f6f7, HSCOEFF5);
+	write_reg(0x1c110700, HSCOEFF6);
+	write_reg(0x3e393127, HSCOEFF7);
+	write_reg(0x00000040, HSCOEFF8);
+
+}
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks.  Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	/* make frame buffer memory enter self-refresh mode */
+	write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
+	while (readl(LMPWRSTAT) != LMPWRSTAT_MC_PWR_SRM)
+		; /* empty statement */
+
+	/* reset the device, since it's initial state is 'mostly sleeping' */
+	write_reg_dly(SYSRST_RST, SYSRST);
+	return 0;
+}
+
+static int mbxfb_resume(struct platform_device *dev)
+{
+	struct fb_info *fbi = platform_get_drvdata(dev);
+
+	enable_clocks(fbi);
+/* 	setup_graphics(fbi); */
+/* 	setup_display(fbi); */
+
+	write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+	return 0;
+}
+#else
+#define mbxfb_suspend	NULL
+#define mbxfb_resume	NULL
+#endif
+
+/* debugfs entries */
+#ifndef CONFIG_FB_MBX_DEBUG
+#define mbxfb_debugfs_init(x)	do {} while(0)
+#define mbxfb_debugfs_remove(x)	do {} while(0)
+#endif
+
+#define res_size(_r) (((_r)->end - (_r)->start) + 1)
+
+static int mbxfb_probe(struct platform_device *dev)
+{
+	int ret;
+	struct fb_info *fbi;
+	struct mbxfb_info *mfbi;
+	struct mbxfb_platform_data *pdata;
+
+	dev_dbg(&dev->dev, "mbxfb_probe\n");
+
+	pdata = dev_get_platdata(&dev->dev);
+	if (!pdata) {
+		dev_err(&dev->dev, "platform data is required\n");
+		return -EINVAL;
+	}
+
+	fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev);
+	if (fbi == NULL) {
+		dev_err(&dev->dev, "framebuffer_alloc failed\n");
+		return -ENOMEM;
+	}
+
+	mfbi = fbi->par;
+	fbi->pseudo_palette = mfbi->pseudo_palette;
+
+
+	if (pdata->probe)
+		mfbi->platform_probe = pdata->probe;
+	if (pdata->remove)
+		mfbi->platform_remove = pdata->remove;
+
+	mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+
+	if (!mfbi->fb_res || !mfbi->reg_res) {
+		dev_err(&dev->dev, "no resources found\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	mfbi->fb_req = request_mem_region(mfbi->fb_res->start,
+					  res_size(mfbi->fb_res), dev->name);
+	if (mfbi->fb_req == NULL) {
+		dev_err(&dev->dev, "failed to claim framebuffer memory\n");
+		ret = -EINVAL;
+		goto err1;
+	}
+	mfbi->fb_phys_addr = mfbi->fb_res->start;
+
+	mfbi->reg_req = request_mem_region(mfbi->reg_res->start,
+					   res_size(mfbi->reg_res), dev->name);
+	if (mfbi->reg_req == NULL) {
+		dev_err(&dev->dev, "failed to claim Marathon registers\n");
+		ret = -EINVAL;
+		goto err2;
+	}
+	mfbi->reg_phys_addr = mfbi->reg_res->start;
+
+	mfbi->reg_virt_addr = devm_ioremap_nocache(&dev->dev,
+						   mfbi->reg_phys_addr,
+						   res_size(mfbi->reg_req));
+	if (!mfbi->reg_virt_addr) {
+		dev_err(&dev->dev, "failed to ioremap Marathon registers\n");
+		ret = -EINVAL;
+		goto err3;
+	}
+	virt_base_2700 = mfbi->reg_virt_addr;
+
+	mfbi->fb_virt_addr = devm_ioremap_nocache(&dev->dev, mfbi->fb_phys_addr,
+						  res_size(mfbi->fb_req));
+	if (!mfbi->fb_virt_addr) {
+		dev_err(&dev->dev, "failed to ioremap frame buffer\n");
+		ret = -EINVAL;
+		goto err3;
+	}
+
+	fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
+	fbi->screen_size = pdata->memsize;
+	fbi->fbops = &mbxfb_ops;
+
+	fbi->var = mbxfb_default;
+	fbi->fix = mbxfb_fix;
+	fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000;
+	fbi->fix.smem_len = pdata->memsize;
+	fbi->fix.line_length = mbxfb_default.xres_virtual *
+					mbxfb_default.bits_per_pixel / 8;
+
+	ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (ret < 0) {
+		dev_err(&dev->dev, "fb_alloc_cmap failed\n");
+		ret = -EINVAL;
+		goto err3;
+	}
+
+	platform_set_drvdata(dev, fbi);
+
+	fb_info(fbi, "mbx frame buffer device\n");
+
+	if (mfbi->platform_probe)
+		mfbi->platform_probe(fbi);
+
+	enable_controller(fbi);
+
+	mbxfb_debugfs_init(fbi);
+
+	ret = register_framebuffer(fbi);
+	if (ret < 0) {
+		dev_err(&dev->dev, "register_framebuffer failed\n");
+		ret = -EINVAL;
+		goto err6;
+	}
+
+	return 0;
+
+err6:
+	fb_dealloc_cmap(&fbi->cmap);
+err3:
+	release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));
+err2:
+	release_mem_region(mfbi->fb_res->start, res_size(mfbi->fb_res));
+err1:
+	framebuffer_release(fbi);
+
+	return ret;
+}
+
+static int mbxfb_remove(struct platform_device *dev)
+{
+	struct fb_info *fbi = platform_get_drvdata(dev);
+
+	write_reg_dly(SYSRST_RST, SYSRST);
+
+	mbxfb_debugfs_remove(fbi);
+
+	if (fbi) {
+		struct mbxfb_info *mfbi = fbi->par;
+
+		unregister_framebuffer(fbi);
+		if (mfbi) {
+			if (mfbi->platform_remove)
+				mfbi->platform_remove(fbi);
+
+
+			if (mfbi->reg_req)
+				release_mem_region(mfbi->reg_req->start,
+						   res_size(mfbi->reg_req));
+			if (mfbi->fb_req)
+				release_mem_region(mfbi->fb_req->start,
+						   res_size(mfbi->fb_req));
+		}
+		framebuffer_release(fbi);
+	}
+
+	return 0;
+}
+
+static struct platform_driver mbxfb_driver = {
+	.probe = mbxfb_probe,
+	.remove = mbxfb_remove,
+	.suspend = mbxfb_suspend,
+	.resume = mbxfb_resume,
+	.driver = {
+		.name = "mbx-fb",
+	},
+};
+
+module_platform_driver(mbxfb_driver);
+
+MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
+MODULE_AUTHOR("Mike Rapoport, Compulab");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mbx/reg_bits.h b/drivers/video/fbdev/mbx/reg_bits.h
new file mode 100644
index 000000000000..5f14b4befd71
--- /dev/null
+++ b/drivers/video/fbdev/mbx/reg_bits.h
@@ -0,0 +1,613 @@
+#ifndef __REG_BITS_2700G_
+#define __REG_BITS_2700G_
+
+/* use defines from asm-arm/arch-pxa/bitfields.h for bit fields access */
+#define UData(Data)	((unsigned long) (Data))
+#define Fld(Size, Shft)	(((Size) << 16) + (Shft))
+#define FSize(Field)	((Field) >> 16)
+#define FShft(Field)	((Field) & 0x0000FFFF)
+#define FMsk(Field)	(((UData (1) << FSize (Field)) - 1) << FShft (Field))
+#define FAlnMsk(Field)	((UData (1) << FSize (Field)) - 1)
+#define F1stBit(Field)	(UData (1) << FShft (Field))
+
+#define SYSRST_RST	(1 << 0)
+
+/* SYSCLKSRC - SYSCLK Source Control Register */
+#define SYSCLKSRC_SEL	Fld(2,0)
+#define SYSCLKSRC_REF	((0x0) << FShft(SYSCLKSRC_SEL))
+#define SYSCLKSRC_PLL_1	((0x1) << FShft(SYSCLKSRC_SEL))
+#define SYSCLKSRC_PLL_2	((0x2) << FShft(SYSCLKSRC_SEL))
+
+/* PIXCLKSRC - PIXCLK Source Control Register */
+#define PIXCLKSRC_SEL	Fld(2,0)
+#define PIXCLKSRC_REF	((0x0) << FShft(PIXCLKSRC_SEL))
+#define PIXCLKSRC_PLL_1	((0x1) << FShft(PIXCLKSRC_SEL))
+#define PIXCLKSRC_PLL_2	((0x2) << FShft(PIXCLKSRC_SEL))
+
+/* Clock Disable Register */
+#define CLKSLEEP_SLP	(1 << 0)
+
+/* Core PLL Control Register */
+#define CORE_PLL_M	Fld(6,7)
+#define Core_Pll_M(x)	((x) << FShft(CORE_PLL_M))
+#define CORE_PLL_N	Fld(3,4)
+#define Core_Pll_N(x)	((x) << FShft(CORE_PLL_N))
+#define CORE_PLL_P	Fld(3,1)
+#define Core_Pll_P(x)	((x) << FShft(CORE_PLL_P))
+#define CORE_PLL_EN	(1 << 0)
+
+/* Display PLL Control Register */
+#define DISP_PLL_M	Fld(6,7)
+#define Disp_Pll_M(x)	((x) << FShft(DISP_PLL_M))
+#define DISP_PLL_N	Fld(3,4)
+#define Disp_Pll_N(x)	((x) << FShft(DISP_PLL_N))
+#define DISP_PLL_P	Fld(3,1)
+#define Disp_Pll_P(x)	((x) << FShft(DISP_PLL_P))
+#define DISP_PLL_EN	(1 << 0)
+
+/* PLL status register */
+#define PLLSTAT_CORE_PLL_LOST_L	(1 << 3)
+#define PLLSTAT_CORE_PLL_LSTS	(1 << 2)
+#define PLLSTAT_DISP_PLL_LOST_L	(1 << 1)
+#define PLLSTAT_DISP_PLL_LSTS	(1 << 0)
+
+/* Video and scale clock control register */
+#define VOVRCLK_EN	(1 << 0)
+
+/* Pixel clock control register */
+#define PIXCLK_EN	(1 << 0)
+
+/* Memory clock control register */
+#define MEMCLK_EN	(1 << 0)
+
+/* MBX clock control register */
+#define MBXCLK_DIV	Fld(2,2)
+#define MBXCLK_DIV_1	((0x0) << FShft(MBXCLK_DIV))
+#define MBXCLK_DIV_2	((0x1) << FShft(MBXCLK_DIV))
+#define MBXCLK_DIV_3	((0x2) << FShft(MBXCLK_DIV))
+#define MBXCLK_DIV_4	((0x3) << FShft(MBXCLK_DIV))
+#define MBXCLK_EN	Fld(2,0)
+#define MBXCLK_EN_NONE	((0x0) << FShft(MBXCLK_EN))
+#define MBXCLK_EN_2D	((0x1) << FShft(MBXCLK_EN))
+#define MBXCLK_EN_BOTH	((0x2) << FShft(MBXCLK_EN))
+
+/* M24 clock control register */
+#define M24CLK_DIV	Fld(2,1)
+#define M24CLK_DIV_1	((0x0) << FShft(M24CLK_DIV))
+#define M24CLK_DIV_2	((0x1) << FShft(M24CLK_DIV))
+#define M24CLK_DIV_3	((0x2) << FShft(M24CLK_DIV))
+#define M24CLK_DIV_4	((0x3) << FShft(M24CLK_DIV))
+#define M24CLK_EN	(1 << 0)
+
+/* SDRAM clock control register */
+#define SDCLK_EN	(1 << 0)
+
+/* PixClk Divisor Register */
+#define PIXCLKDIV_PD	Fld(9,0)
+#define Pixclkdiv_Pd(x)	((x) << FShft(PIXCLKDIV_PD))
+
+/* LCD Config control register */
+#define LCDCFG_IN_FMT	Fld(3,28)
+#define Lcdcfg_In_Fmt(x)	((x) << FShft(LCDCFG_IN_FMT))
+#define LCDCFG_LCD1DEN_POL	(1 << 27)
+#define LCDCFG_LCD1FCLK_POL	(1 << 26)
+#define LCDCFG_LCD1LCLK_POL	(1 << 25)
+#define LCDCFG_LCD1D_POL	(1 << 24)
+#define LCDCFG_LCD2DEN_POL	(1 << 23)
+#define LCDCFG_LCD2FCLK_POL	(1 << 22)
+#define LCDCFG_LCD2LCLK_POL	(1 << 21)
+#define LCDCFG_LCD2D_POL	(1 << 20)
+#define LCDCFG_LCD1_TS		(1 << 19)
+#define LCDCFG_LCD1D_DS		(1 << 18)
+#define LCDCFG_LCD1C_DS		(1 << 17)
+#define LCDCFG_LCD1_IS_IN	(1 << 16)
+#define LCDCFG_LCD2_TS		(1 << 3)
+#define LCDCFG_LCD2D_DS		(1 << 2)
+#define LCDCFG_LCD2C_DS		(1 << 1)
+#define LCDCFG_LCD2_IS_IN	(1 << 0)
+
+/* On-Die Frame Buffer Power Control Register */
+#define ODFBPWR_SLOW	(1 << 2)
+#define ODFBPWR_MODE	Fld(2,0)
+#define ODFBPWR_MODE_ACT	((0x0) << FShft(ODFBPWR_MODE))
+#define ODFBPWR_MODE_ACT_LP	((0x1) << FShft(ODFBPWR_MODE))
+#define ODFBPWR_MODE_SLEEP	((0x2) << FShft(ODFBPWR_MODE))
+#define ODFBPWR_MODE_SHUTD	((0x3) << FShft(ODFBPWR_MODE))
+
+/* On-Die Frame Buffer Power State Status Register */
+#define ODFBSTAT_ACT	(1 << 2)
+#define ODFBSTAT_SLP	(1 << 1)
+#define ODFBSTAT_SDN	(1 << 0)
+
+/* LMRST - Local Memory (SDRAM) Reset */
+#define LMRST_MC_RST	(1 << 0)
+
+/* LMCFG - Local Memory (SDRAM) Configuration Register */
+#define LMCFG_LMC_DS	(1 << 5)
+#define LMCFG_LMD_DS	(1 << 4)
+#define LMCFG_LMA_DS	(1 << 3)
+#define LMCFG_LMC_TS	(1 << 2)
+#define LMCFG_LMD_TS	(1 << 1)
+#define LMCFG_LMA_TS	(1 << 0)
+
+/* LMPWR - Local Memory (SDRAM) Power Control Register */
+#define LMPWR_MC_PWR_CNT	Fld(2,0)
+#define LMPWR_MC_PWR_ACT	((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */
+#define LMPWR_MC_PWR_SRM	((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */
+#define LMPWR_MC_PWR_DPD	((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */
+
+/* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */
+#define LMPWRSTAT_MC_PWR_CNT	Fld(2,0)
+#define LMPWRSTAT_MC_PWR_ACT	((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */
+#define LMPWRSTAT_MC_PWR_SRM	((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */
+#define LMPWRSTAT_MC_PWR_DPD	((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */
+
+/* LMTYPE - Local Memory (SDRAM) Type Register */
+#define LMTYPE_CASLAT	Fld(3,10)
+#define LMTYPE_CASLAT_1	((0x1) << FShft(LMTYPE_CASLAT))
+#define LMTYPE_CASLAT_2	((0x2) << FShft(LMTYPE_CASLAT))
+#define LMTYPE_CASLAT_3	((0x3) << FShft(LMTYPE_CASLAT))
+#define LMTYPE_BKSZ	Fld(2,8)
+#define LMTYPE_BKSZ_1	((0x1) << FShft(LMTYPE_BKSZ))
+#define LMTYPE_BKSZ_2	((0x2) << FShft(LMTYPE_BKSZ))
+#define LMTYPE_ROWSZ	Fld(4,4)
+#define LMTYPE_ROWSZ_11	((0xb) << FShft(LMTYPE_ROWSZ))
+#define LMTYPE_ROWSZ_12	((0xc) << FShft(LMTYPE_ROWSZ))
+#define LMTYPE_ROWSZ_13	((0xd) << FShft(LMTYPE_ROWSZ))
+#define LMTYPE_COLSZ	Fld(4,0)
+#define LMTYPE_COLSZ_7	((0x7) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_8	((0x8) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_9	((0x9) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_10	((0xa) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_11	((0xb) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_12	((0xc) << FShft(LMTYPE_COLSZ))
+
+/* LMTIM - Local Memory (SDRAM) Timing Register */
+#define LMTIM_TRAS	Fld(4,16)
+#define Lmtim_Tras(x)	((x) << FShft(LMTIM_TRAS))
+#define LMTIM_TRP	Fld(4,12)
+#define Lmtim_Trp(x)	((x) << FShft(LMTIM_TRP))
+#define LMTIM_TRCD	Fld(4,8)
+#define Lmtim_Trcd(x)	((x) << FShft(LMTIM_TRCD))
+#define LMTIM_TRC	Fld(4,4)
+#define Lmtim_Trc(x)	((x) << FShft(LMTIM_TRC))
+#define LMTIM_TDPL	Fld(4,0)
+#define Lmtim_Tdpl(x)	((x) << FShft(LMTIM_TDPL))
+
+/* LMREFRESH - Local Memory (SDRAM) tREF Control Register */
+#define LMREFRESH_TREF	Fld(2,0)
+#define Lmrefresh_Tref(x)	((x) << FShft(LMREFRESH_TREF))
+
+/* GSCTRL - Graphics surface control register */
+#define GSCTRL_LUT_EN	(1 << 31)
+#define GSCTRL_GPIXFMT	Fld(4,27)
+#define GSCTRL_GPIXFMT_INDEXED	((0x0) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_ARGB4444	((0x4) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_ARGB1555	((0x5) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_RGB888	((0x6) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_RGB565	((0x7) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_ARGB8888	((0x8) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GAMMA_EN	(1 << 26)
+
+#define GSCTRL_GSWIDTH Fld(11,11)
+#define Gsctrl_Width(Pixel)	/* Display Width [1..2048 pix.]  */ \
+                        (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH))
+
+#define GSCTRL_GSHEIGHT Fld(11,0)
+#define Gsctrl_Height(Pixel)	/* Display Height [1..2048 pix.]  */ \
+                        (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT))
+
+/* GBBASE fileds */
+#define GBBASE_GLALPHA Fld(8,24)
+#define Gbbase_Glalpha(x)	((x) << FShft(GBBASE_GLALPHA))
+
+#define GBBASE_COLKEY Fld(24,0)
+#define Gbbase_Colkey(x)	((x) << FShft(GBBASE_COLKEY))
+
+/* GDRCTRL fields */
+#define GDRCTRL_PIXDBL	(1 << 31)
+#define GDRCTRL_PIXHLV	(1 << 30)
+#define GDRCTRL_LNDBL	(1 << 29)
+#define GDRCTRL_LNHLV	(1 << 28)
+#define GDRCTRL_COLKEYM	Fld(24,0)
+#define Gdrctrl_Colkeym(x)	((x) << FShft(GDRCTRL_COLKEYM))
+
+/* GSCADR graphics stream control address register fields */
+#define GSCADR_STR_EN	(1 << 31)
+#define GSCADR_COLKEY_EN	(1 << 30)
+#define GSCADR_COLKEYSRC	(1 << 29)
+#define GSCADR_BLEND_M	Fld(2,27)
+#define GSCADR_BLEND_NONE	((0x0) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_INV	((0x1) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_GLOB	((0x2) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_PIX	((0x3) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_POS	Fld(2,24)
+#define GSCADR_BLEND_GFX	((0x0) << FShft(GSCADR_BLEND_POS))
+#define GSCADR_BLEND_VID	((0x1) << FShft(GSCADR_BLEND_POS))
+#define GSCADR_BLEND_CUR	((0x2) << FShft(GSCADR_BLEND_POS))
+#define GSCADR_GBASE_ADR	Fld(23,0)
+#define Gscadr_Gbase_Adr(x)	((x) << FShft(GSCADR_GBASE_ADR))
+
+/* GSADR graphics stride address register fields */
+#define GSADR_SRCSTRIDE	Fld(10,22)
+#define Gsadr_Srcstride(x)	((x) << FShft(GSADR_SRCSTRIDE))
+#define GSADR_XSTART	Fld(11,11)
+#define Gsadr_Xstart(x)		((x) << FShft(GSADR_XSTART))
+#define GSADR_YSTART	Fld(11,0)
+#define Gsadr_Ystart(y)		((y) << FShft(GSADR_YSTART))
+
+/* GPLUT graphics palette register fields */
+#define GPLUT_LUTADR	Fld(8,24)
+#define Gplut_Lutadr(x)	((x) << FShft(GPLUT_LUTADR))
+#define GPLUT_LUTDATA	Fld(24,0)
+#define Gplut_Lutdata(x)	((x) << FShft(GPLUT_LUTDATA))
+
+/* VSCTRL - Video Surface Control Register */
+#define VSCTRL_VPIXFMT		Fld(4,27)
+#define VSCTRL_VPIXFMT_YUV12	((0x9) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_UY0VY1	((0xc) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_VY0UY1	((0xd) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0UY1V	((0xe) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0VY1U	((0xf) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_GAMMA_EN		(1 << 26)
+#define VSCTRL_CSC_EN		(1 << 25)
+#define VSCTRL_COSITED		(1 << 22)
+#define VSCTRL_VSWIDTH		Fld(11,11)
+#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \
+			(((Pixels) - 1) << FShft(VSCTRL_VSWIDTH))
+#define VSCTRL_VSHEIGHT		Fld(11,0)
+#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \
+			(((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT))
+
+/* VBBASE - Video Blending Base Register */
+#define VBBASE_GLALPHA		Fld(8,24)
+#define Vbbase_Glalpha(x)	((x) << FShft(VBBASE_GLALPHA))
+
+#define VBBASE_COLKEY		Fld(24,0)
+#define Vbbase_Colkey(x)	((x) << FShft(VBBASE_COLKEY))
+
+/* VCMSK - Video Color Key Mask Register */
+#define VCMSK_COLKEY_M		Fld(24,0)
+#define Vcmsk_colkey_m(x)	((x) << FShft(VCMSK_COLKEY_M))
+
+/* VSCADR - Video Stream Control Rddress Register */
+#define VSCADR_STR_EN		(1 << 31)
+#define VSCADR_COLKEY_EN	(1 << 30)
+#define VSCADR_COLKEYSRC	(1 << 29)
+#define VSCADR_BLEND_M		Fld(2,27)
+#define VSCADR_BLEND_NONE	((0x0) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_INV	((0x1) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_GLOB	((0x2) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_PIX	((0x3) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_POS	Fld(2,24)
+#define VSCADR_BLEND_GFX	((0x0) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_VID	((0x1) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_CUR	((0x2) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_VBASE_ADR	Fld(23,0)
+#define Vscadr_Vbase_Adr(x)	((x) << FShft(VSCADR_VBASE_ADR))
+
+/* VUBASE - Video U Base Register */
+#define VUBASE_UVHALFSTR	(1 << 31)
+#define VUBASE_UBASE_ADR	Fld(24,0)
+#define Vubase_Ubase_Adr(x)	((x) << FShft(VUBASE_UBASE_ADR))
+
+/* VVBASE - Video V Base Register */
+#define VVBASE_VBASE_ADR	Fld(24,0)
+#define Vvbase_Vbase_Adr(x)	((x) << FShft(VVBASE_VBASE_ADR))
+
+/* VSADR - Video Stride Address Register */
+#define VSADR_SRCSTRIDE		Fld(10,22)
+#define Vsadr_Srcstride(x)	((x) << FShft(VSADR_SRCSTRIDE))
+#define VSADR_XSTART		Fld(11,11)
+#define Vsadr_Xstart(x)		((x) << FShft(VSADR_XSTART))
+#define VSADR_YSTART		Fld(11,0)
+#define Vsadr_Ystart(x)		((x) << FShft(VSADR_YSTART))
+
+/* VSCTRL - Video Surface Control Register */
+#define VSCTRL_VPIXFMT		Fld(4,27)
+#define VSCTRL_VPIXFMT_YUV12	((0x9) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_UY0VY1	((0xc) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_VY0UY1	((0xd) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0UY1V	((0xe) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0VY1U	((0xf) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_GAMMA_EN		(1 << 26)
+#define VSCTRL_CSC_EN		(1 << 25)
+#define VSCTRL_COSITED		(1 << 22)
+#define VSCTRL_VSWIDTH		Fld(11,11)
+#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \
+			(((Pixels) - 1) << FShft(VSCTRL_VSWIDTH))
+#define VSCTRL_VSHEIGHT		Fld(11,0)
+#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \
+			(((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT))
+
+/* VBBASE - Video Blending Base Register */
+#define VBBASE_GLALPHA		Fld(8,24)
+#define Vbbase_Glalpha(x)	((x) << FShft(VBBASE_GLALPHA))
+
+#define VBBASE_COLKEY		Fld(24,0)
+#define Vbbase_Colkey(x)	((x) << FShft(VBBASE_COLKEY))
+
+/* VCMSK - Video Color Key Mask Register */
+#define VCMSK_COLKEY_M		Fld(24,0)
+#define Vcmsk_colkey_m(x)	((x) << FShft(VCMSK_COLKEY_M))
+
+/* VSCADR - Video Stream Control Rddress Register */
+#define VSCADR_STR_EN		(1 << 31)
+#define VSCADR_COLKEY_EN	(1 << 30)
+#define VSCADR_COLKEYSRC	(1 << 29)
+#define VSCADR_BLEND_M		Fld(2,27)
+#define VSCADR_BLEND_NONE	((0x0) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_INV	((0x1) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_GLOB	((0x2) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_PIX	((0x3) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_POS	Fld(2,24)
+#define VSCADR_BLEND_GFX	((0x0) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_VID	((0x1) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_CUR	((0x2) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_VBASE_ADR	Fld(23,0)
+#define Vscadr_Vbase_Adr(x)	((x) << FShft(VSCADR_VBASE_ADR))
+
+/* VUBASE - Video U Base Register */
+#define VUBASE_UVHALFSTR	(1 << 31)
+#define VUBASE_UBASE_ADR	Fld(24,0)
+#define Vubase_Ubase_Adr(x)	((x) << FShft(VUBASE_UBASE_ADR))
+
+/* VVBASE - Video V Base Register */
+#define VVBASE_VBASE_ADR	Fld(24,0)
+#define Vvbase_Vbase_Adr(x)	((x) << FShft(VVBASE_VBASE_ADR))
+
+/* VSADR - Video Stride Address Register */
+#define VSADR_SRCSTRIDE		Fld(10,22)
+#define Vsadr_Srcstride(x)	((x) << FShft(VSADR_SRCSTRIDE))
+#define VSADR_XSTART		Fld(11,11)
+#define Vsadr_Xstart(x)		((x) << FShft(VSADR_XSTART))
+#define VSADR_YSTART		Fld(11,0)
+#define Vsadr_Ystart(x)		((x) << FShft(VSADR_YSTART))
+
+/* HCCTRL - Hardware Cursor Register fields */
+#define HCCTRL_CUR_EN	(1 << 31)
+#define HCCTRL_COLKEY_EN	(1 << 29)
+#define HCCTRL_COLKEYSRC	(1 << 28)
+#define HCCTRL_BLEND_M	Fld(2,26)
+#define HCCTRL_BLEND_NONE	((0x0) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_BLEND_INV	((0x1) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_BLEND_GLOB	((0x2) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_BLEND_PIX	((0x3) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_CPIXFMT	Fld(3,23)
+#define HCCTRL_CPIXFMT_RGB332	((0x3) << FShft(HCCTRL_CPIXFMT))
+#define HCCTRL_CPIXFMT_ARGB4444	((0x4) << FShft(HCCTRL_CPIXFMT))
+#define HCCTRL_CPIXFMT_ARGB1555	((0x5) << FShft(HCCTRL_CPIXFMT))
+#define HCCTRL_CBASE_ADR	Fld(23,0)
+#define Hcctrl_Cbase_Adr(x)	((x) << FShft(HCCTRL_CBASE_ADR))
+
+/* HCSIZE Hardware Cursor Size Register fields */
+#define HCSIZE_BLEND_POS	Fld(2,29)
+#define HCSIZE_BLEND_GFX	((0x0) << FShft(HCSIZE_BLEND_POS))
+#define HCSIZE_BLEND_VID	((0x1) << FShft(HCSIZE_BLEND_POS))
+#define HCSIZE_BLEND_CUR	((0x2) << FShft(HCSIZE_BLEND_POS))
+#define HCSIZE_CWIDTH	Fld(3,16)
+#define Hcsize_Cwidth(x)	((x) << FShft(HCSIZE_CWIDTH))
+#define HCSIZE_CHEIGHT	Fld(3,0)
+#define Hcsize_Cheight(x)	((x) << FShft(HCSIZE_CHEIGHT))
+
+/* HCPOS Hardware Cursor Position Register fields */
+#define HCPOS_SWITCHSRC	(1 << 30)
+#define HCPOS_CURBLINK	Fld(6,24)
+#define Hcpos_Curblink(x)	((x) << FShft(HCPOS_CURBLINK))
+#define HCPOS_XSTART	Fld(12,12)
+#define Hcpos_Xstart(x)	((x) << FShft(HCPOS_XSTART))
+#define HCPOS_YSTART	Fld(12,0)
+#define Hcpos_Ystart(y)	((y) << FShft(HCPOS_YSTART))
+
+/* HCBADR Hardware Cursor Blend Address Register */
+#define HCBADR_GLALPHA	Fld(8,24)
+#define Hcbadr_Glalpha(x)	((x) << FShft(HCBADR_GLALPHA))
+#define HCBADR_COLKEY	Fld(24,0)
+#define Hcbadr_Colkey(x)	((x) << FShft(HCBADR_COLKEY))
+
+/* HCCKMSK - Hardware Cursor Color Key Mask Register */
+#define HCCKMSK_COLKEY_M	Fld(24,0)
+#define Hcckmsk_Colkey_M(x)	((x) << FShft(HCCKMSK_COLKEY_M))
+
+/* DSCTRL - Display sync control register */
+#define DSCTRL_SYNCGEN_EN	(1 << 31)
+#define DSCTRL_DPL_RST		(1 << 29)
+#define DSCTRL_PWRDN_M		(1 << 28)
+#define DSCTRL_UPDSYNCCNT	(1 << 26)
+#define DSCTRL_UPDINTCNT	(1 << 25)
+#define DSCTRL_UPDCNT		(1 << 24)
+#define DSCTRL_UPDWAIT	Fld(4,16)
+#define Dsctrl_Updwait(x)	((x) << FShft(DSCTRL_UPDWAIT))
+#define DSCTRL_CLKPOL		(1 << 11)
+#define DSCTRL_CSYNC_EN		(1 << 10)
+#define DSCTRL_VS_SLAVE		(1 << 7)
+#define DSCTRL_HS_SLAVE		(1 << 6)
+#define DSCTRL_BLNK_POL		(1 << 5)
+#define DSCTRL_BLNK_DIS		(1 << 4)
+#define DSCTRL_VS_POL		(1 << 3)
+#define DSCTRL_VS_DIS		(1 << 2)
+#define DSCTRL_HS_POL		(1 << 1)
+#define DSCTRL_HS_DIS		(1 << 0)
+
+/* DHT01 - Display horizontal timing register 01 */
+#define DHT01_HBPS	Fld(12,16)
+#define Dht01_Hbps(x)	((x) << FShft(DHT01_HBPS))
+#define DHT01_HT	Fld(12,0)
+#define Dht01_Ht(x)	((x) << FShft(DHT01_HT))
+
+/* DHT02 - Display horizontal timing register 02 */
+#define DHT02_HAS	Fld(12,16)
+#define Dht02_Has(x)	((x) << FShft(DHT02_HAS))
+#define DHT02_HLBS	Fld(12,0)
+#define Dht02_Hlbs(x)	((x) << FShft(DHT02_HLBS))
+
+/* DHT03 - Display horizontal timing register 03 */
+#define DHT03_HFPS	Fld(12,16)
+#define Dht03_Hfps(x)	((x) << FShft(DHT03_HFPS))
+#define DHT03_HRBS	Fld(12,0)
+#define Dht03_Hrbs(x)	((x) << FShft(DHT03_HRBS))
+
+/* DVT01 - Display vertical timing register 01 */
+#define DVT01_VBPS	Fld(12,16)
+#define Dvt01_Vbps(x)	((x) << FShft(DVT01_VBPS))
+#define DVT01_VT	Fld(12,0)
+#define Dvt01_Vt(x)	((x) << FShft(DVT01_VT))
+
+/* DVT02 - Display vertical timing register 02 */
+#define DVT02_VAS	Fld(12,16)
+#define Dvt02_Vas(x)	((x) << FShft(DVT02_VAS))
+#define DVT02_VTBS	Fld(12,0)
+#define Dvt02_Vtbs(x)	((x) << FShft(DVT02_VTBS))
+
+/* DVT03 - Display vertical timing register 03 */
+#define DVT03_VFPS	Fld(12,16)
+#define Dvt03_Vfps(x)	((x) << FShft(DVT03_VFPS))
+#define DVT03_VBBS	Fld(12,0)
+#define Dvt03_Vbbs(x)	((x) << FShft(DVT03_VBBS))
+
+/* DVECTRL - display vertical event control register */
+#define DVECTRL_VEVENT	Fld(12,16)
+#define Dvectrl_Vevent(x)	((x) << FShft(DVECTRL_VEVENT))
+#define DVECTRL_VFETCH	Fld(12,0)
+#define Dvectrl_Vfetch(x)	((x) << FShft(DVECTRL_VFETCH))
+
+/* DHDET - display horizontal DE timing register */
+#define DHDET_HDES	Fld(12,16)
+#define Dhdet_Hdes(x)	((x) << FShft(DHDET_HDES))
+#define DHDET_HDEF	Fld(12,0)
+#define Dhdet_Hdef(x)	((x) << FShft(DHDET_HDEF))
+
+/* DVDET - display vertical DE timing register */
+#define DVDET_VDES	Fld(12,16)
+#define Dvdet_Vdes(x)	((x) << FShft(DVDET_VDES))
+#define DVDET_VDEF	Fld(12,0)
+#define Dvdet_Vdef(x)	((x) << FShft(DVDET_VDEF))
+
+/* DODMSK - display output data mask register */
+#define DODMSK_MASK_LVL	(1 << 31)
+#define DODMSK_BLNK_LVL	(1 << 30)
+#define DODMSK_MASK_B	Fld(8,16)
+#define Dodmsk_Mask_B(x)	((x) << FShft(DODMSK_MASK_B))
+#define DODMSK_MASK_G	Fld(8,8)
+#define Dodmsk_Mask_G(x)	((x) << FShft(DODMSK_MASK_G))
+#define DODMSK_MASK_R	Fld(8,0)
+#define Dodmsk_Mask_R(x)	((x) << FShft(DODMSK_MASK_R))
+
+/* DBCOL - display border color control register */
+#define DBCOL_BORDCOL	Fld(24,0)
+#define Dbcol_Bordcol(x)	((x) << FShft(DBCOL_BORDCOL))
+
+/* DVLNUM - display vertical line number register */
+#define DVLNUM_VLINE	Fld(12,0)
+#define Dvlnum_Vline(x)	((x) << FShft(DVLNUM_VLINE))
+
+/* DMCTRL - Display Memory Control Register */
+#define DMCTRL_MEM_REF	Fld(2,30)
+#define DMCTRL_MEM_REF_ACT	((0x0) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_MEM_REF_HB	((0x1) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_MEM_REF_VB	((0x2) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_MEM_REF_BOTH	((0x3) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_UV_THRHLD	Fld(6,24)
+#define Dmctrl_Uv_Thrhld(x)	((x) << FShft(DMCTRL_UV_THRHLD))
+#define DMCTRL_V_THRHLD		Fld(7,16)
+#define Dmctrl_V_Thrhld(x)	((x) << FShft(DMCTRL_V_THRHLD))
+#define DMCTRL_D_THRHLD		Fld(7,8)
+#define Dmctrl_D_Thrhld(x)	((x) << FShft(DMCTRL_D_THRHLD))
+#define DMCTRL_BURSTLEN	Fld(6,0)
+#define Dmctrl_Burstlen(x)	((x) << FShft(DMCTRL_BURSTLEN))
+
+/* DINTRS - Display Interrupt Status Register */
+#define DINTRS_CUR_OR_S		(1 << 18)
+#define DINTRS_STR2_OR_S	(1 << 17)
+#define DINTRS_STR1_OR_S	(1 << 16)
+#define DINTRS_CUR_UR_S		(1 << 6)
+#define DINTRS_STR2_UR_S	(1 << 5)
+#define DINTRS_STR1_UR_S	(1 << 4)
+#define DINTRS_VEVENT1_S	(1 << 3)
+#define DINTRS_VEVENT0_S	(1 << 2)
+#define DINTRS_HBLNK1_S		(1 << 1)
+#define DINTRS_HBLNK0_S		(1 << 0)
+
+/* DINTRE - Display Interrupt Enable Register */
+#define DINTRE_CUR_OR_EN	(1 << 18)
+#define DINTRE_STR2_OR_EN	(1 << 17)
+#define DINTRE_STR1_OR_EN	(1 << 16)
+#define DINTRE_CUR_UR_EN	(1 << 6)
+#define DINTRE_STR2_UR_EN	(1 << 5)
+#define DINTRE_STR1_UR_EN	(1 << 4)
+#define DINTRE_VEVENT1_EN	(1 << 3)
+#define DINTRE_VEVENT0_EN	(1 << 2)
+#define DINTRE_HBLNK1_EN	(1 << 1)
+#define DINTRE_HBLNK0_EN	(1 << 0)
+
+/* DINTRS - Display Interrupt Status Register */
+#define DINTRS_CUR_OR_S		(1 << 18)
+#define DINTRS_STR2_OR_S	(1 << 17)
+#define DINTRS_STR1_OR_S	(1 << 16)
+#define DINTRS_CUR_UR_S		(1 << 6)
+#define DINTRS_STR2_UR_S	(1 << 5)
+#define DINTRS_STR1_UR_S	(1 << 4)
+#define DINTRS_VEVENT1_S	(1 << 3)
+#define DINTRS_VEVENT0_S	(1 << 2)
+#define DINTRS_HBLNK1_S		(1 << 1)
+#define DINTRS_HBLNK0_S		(1 << 0)
+
+/* DINTRE - Display Interrupt Enable Register */
+#define DINTRE_CUR_OR_EN	(1 << 18)
+#define DINTRE_STR2_OR_EN	(1 << 17)
+#define DINTRE_STR1_OR_EN	(1 << 16)
+#define DINTRE_CUR_UR_EN	(1 << 6)
+#define DINTRE_STR2_UR_EN	(1 << 5)
+#define DINTRE_STR1_UR_EN	(1 << 4)
+#define DINTRE_VEVENT1_EN	(1 << 3)
+#define DINTRE_VEVENT0_EN	(1 << 2)
+#define DINTRE_HBLNK1_EN	(1 << 1)
+#define DINTRE_HBLNK0_EN	(1 << 0)
+
+
+/* DLSTS - display load status register */
+#define DLSTS_RLD_ADONE	(1 << 23)
+/* #define DLSTS_RLD_ADOUT	Fld(23,0) */
+
+/* DLLCTRL - display list load control register */
+#define DLLCTRL_RLD_ADRLN	Fld(8,24)
+#define Dllctrl_Rld_Adrln(x)	((x) << FShft(DLLCTRL_RLD_ADRLN))
+
+/* CLIPCTRL - Clipping Control Register */
+#define CLIPCTRL_HSKIP		Fld(11,16)
+#define Clipctrl_Hskip		((x) << FShft(CLIPCTRL_HSKIP))
+#define CLIPCTRL_VSKIP		Fld(11,0)
+#define Clipctrl_Vskip		((x) << FShft(CLIPCTRL_VSKIP))
+
+/* SPOCTRL - Scale Pitch/Order Control Register */
+#define SPOCTRL_H_SC_BP		(1 << 31)
+#define SPOCTRL_V_SC_BP		(1 << 30)
+#define SPOCTRL_HV_SC_OR	(1 << 29)
+#define SPOCTRL_VS_UR_C		(1 << 27)
+#define SPOCTRL_VORDER		Fld(2,16)
+#define SPOCTRL_VORDER_1TAP	((0x0) << FShft(SPOCTRL_VORDER))
+#define SPOCTRL_VORDER_2TAP	((0x1) << FShft(SPOCTRL_VORDER))
+#define SPOCTRL_VORDER_4TAP	((0x3) << FShft(SPOCTRL_VORDER))
+#define SPOCTRL_VPITCH		Fld(16,0)
+#define Spoctrl_Vpitch(x)	((x) << FShft(SPOCTRL_VPITCH))
+
+/* SVCTRL - Scale Vertical Control Register */
+#define SVCTRL_INITIAL1		Fld(16,16)
+#define Svctrl_Initial1(x)	((x) << FShft(SVCTRL_INITIAL1))
+#define SVCTRL_INITIAL2		Fld(16,0)
+#define Svctrl_Initial2(x)	((x) << FShft(SVCTRL_INITIAL2))
+
+/* SHCTRL - Scale Horizontal Control Register */
+#define SHCTRL_HINITIAL		Fld(16,16)
+#define Shctrl_Hinitial(x)	((x) << FShft(SHCTRL_HINITIAL))
+#define SHCTRL_HDECIM		(1 << 15)
+#define SHCTRL_HPITCH		Fld(15,0)
+#define Shctrl_Hpitch(x)	((x) << FShft(SHCTRL_HPITCH))
+
+/* SSSIZE - Scale Surface Size Register */
+#define SSSIZE_SC_WIDTH		Fld(11,16)
+#define Sssize_Sc_Width(x)	((x) << FShft(SSSIZE_SC_WIDTH))
+#define SSSIZE_SC_HEIGHT	Fld(11,0)
+#define Sssize_Sc_Height(x)	((x) << FShft(SSSIZE_SC_HEIGHT))
+
+#endif /* __REG_BITS_2700G_ */
diff --git a/drivers/video/fbdev/mbx/regs.h b/drivers/video/fbdev/mbx/regs.h
new file mode 100644
index 000000000000..063099d48839
--- /dev/null
+++ b/drivers/video/fbdev/mbx/regs.h
@@ -0,0 +1,195 @@
+#ifndef __REGS_2700G_
+#define __REGS_2700G_
+
+/* extern unsigned long virt_base_2700; */
+/* #define __REG_2700G(x)	(*(volatile unsigned long*)((x)+virt_base_2700)) */
+#define __REG_2700G(x)	((x)+virt_base_2700)
+
+/* System Configuration Registers (0x0000_0000  0x0000_0010) */
+#define SYSCFG		__REG_2700G(0x00000000)
+#define PFBASE		__REG_2700G(0x00000004)
+#define PFCEIL		__REG_2700G(0x00000008)
+#define POLLFLAG	__REG_2700G(0x0000000c)
+#define SYSRST		__REG_2700G(0x00000010)
+
+/* Interrupt Control Registers (0x0000_0014  0x0000_002F) */
+#define NINTPW		__REG_2700G(0x00000014)
+#define MINTENABLE	__REG_2700G(0x00000018)
+#define MINTSTAT	__REG_2700G(0x0000001c)
+#define SINTENABLE	__REG_2700G(0x00000020)
+#define SINTSTAT	__REG_2700G(0x00000024)
+#define SINTCLR		__REG_2700G(0x00000028)
+
+/* Clock Control Registers (0x0000_002C  0x0000_005F) */
+#define SYSCLKSRC	__REG_2700G(0x0000002c)
+#define PIXCLKSRC	__REG_2700G(0x00000030)
+#define CLKSLEEP	__REG_2700G(0x00000034)
+#define COREPLL		__REG_2700G(0x00000038)
+#define DISPPLL		__REG_2700G(0x0000003c)
+#define PLLSTAT		__REG_2700G(0x00000040)
+#define VOVRCLK		__REG_2700G(0x00000044)
+#define PIXCLK		__REG_2700G(0x00000048)
+#define MEMCLK		__REG_2700G(0x0000004c)
+#define M24CLK		__REG_2700G(0x00000050)
+#define MBXCLK		__REG_2700G(0x00000054)
+#define SDCLK		__REG_2700G(0x00000058)
+#define PIXCLKDIV	__REG_2700G(0x0000005c)
+
+/* LCD Port Control Register (0x0000_0060  0x0000_006F) */
+#define LCD_CONFIG	__REG_2700G(0x00000060)
+
+/* On-Die Frame Buffer Registers (0x0000_0064  0x0000_006B) */
+#define ODFBPWR		__REG_2700G(0x00000064)
+#define ODFBSTAT	__REG_2700G(0x00000068)
+
+/* GPIO Registers (0x0000_006C  0x0000_007F) */
+#define GPIOCGF		__REG_2700G(0x0000006c)
+#define GPIOHI		__REG_2700G(0x00000070)
+#define GPIOLO		__REG_2700G(0x00000074)
+#define GPIOSTAT	__REG_2700G(0x00000078)
+
+/* Pulse Width Modulator (PWM) Registers (0x0000_0200  0x0000_02FF) */
+#define PWMRST		__REG_2700G(0x00000200)
+#define PWMCFG		__REG_2700G(0x00000204)
+#define PWM0DIV		__REG_2700G(0x00000210)
+#define PWM0DUTY	__REG_2700G(0x00000214)
+#define PWM0PER		__REG_2700G(0x00000218)
+#define PWM1DIV		__REG_2700G(0x00000220)
+#define PWM1DUTY	__REG_2700G(0x00000224)
+#define PWM1PER		__REG_2700G(0x00000228)
+
+/* Identification (ID) Registers (0x0000_0300  0x0000_0FFF) */
+#define ID		__REG_2700G(0x00000FF0)
+
+/* Local Memory (SDRAM) Interface Registers (0x0000_1000  0x0000_1FFF) */
+#define LMRST		__REG_2700G(0x00001000)
+#define LMCFG		__REG_2700G(0x00001004)
+#define LMPWR		__REG_2700G(0x00001008)
+#define LMPWRSTAT	__REG_2700G(0x0000100c)
+#define LMCEMR		__REG_2700G(0x00001010)
+#define LMTYPE		__REG_2700G(0x00001014)
+#define LMTIM		__REG_2700G(0x00001018)
+#define LMREFRESH	__REG_2700G(0x0000101c)
+#define LMPROTMIN	__REG_2700G(0x00001020)
+#define LMPROTMAX	__REG_2700G(0x00001024)
+#define LMPROTCFG	__REG_2700G(0x00001028)
+#define LMPROTERR	__REG_2700G(0x0000102c)
+
+/* Plane Controller Registers (0x0000_2000  0x0000_2FFF) */
+#define GSCTRL		__REG_2700G(0x00002000)
+#define VSCTRL		__REG_2700G(0x00002004)
+#define GBBASE		__REG_2700G(0x00002020)
+#define VBBASE		__REG_2700G(0x00002024)
+#define GDRCTRL		__REG_2700G(0x00002040)
+#define VCMSK		__REG_2700G(0x00002044)
+#define GSCADR		__REG_2700G(0x00002060)
+#define VSCADR		__REG_2700G(0x00002064)
+#define VUBASE		__REG_2700G(0x00002084)
+#define VVBASE		__REG_2700G(0x000020a4)
+#define GSADR		__REG_2700G(0x000020c0)
+#define VSADR		__REG_2700G(0x000020c4)
+#define HCCTRL		__REG_2700G(0x00002100)
+#define HCSIZE		__REG_2700G(0x00002110)
+#define HCPOS		__REG_2700G(0x00002120)
+#define HCBADR		__REG_2700G(0x00002130)
+#define HCCKMSK		__REG_2700G(0x00002140)
+#define GPLUT		__REG_2700G(0x00002150)
+#define DSCTRL		__REG_2700G(0x00002154)
+#define DHT01		__REG_2700G(0x00002158)
+#define DHT02		__REG_2700G(0x0000215c)
+#define DHT03		__REG_2700G(0x00002160)
+#define DVT01		__REG_2700G(0x00002164)
+#define DVT02		__REG_2700G(0x00002168)
+#define DVT03		__REG_2700G(0x0000216c)
+#define DBCOL		__REG_2700G(0x00002170)
+#define BGCOLOR		__REG_2700G(0x00002174)
+#define DINTRS		__REG_2700G(0x00002178)
+#define DINTRE		__REG_2700G(0x0000217c)
+#define DINTRCNT	__REG_2700G(0x00002180)
+#define DSIG		__REG_2700G(0x00002184)
+#define DMCTRL		__REG_2700G(0x00002188)
+#define CLIPCTRL	__REG_2700G(0x0000218c)
+#define SPOCTRL		__REG_2700G(0x00002190)
+#define SVCTRL		__REG_2700G(0x00002194)
+
+/* 0x0000_2198 */
+/* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */
+#define VSCOEFF0	__REG_2700G(0x00002198)
+#define VSCOEFF1	__REG_2700G(0x0000219c)
+#define VSCOEFF2	__REG_2700G(0x000021a0)
+#define VSCOEFF3	__REG_2700G(0x000021a4)
+#define VSCOEFF4	__REG_2700G(0x000021a8)
+
+#define SHCTRL		__REG_2700G(0x000021b0)
+
+/* 0x0000_21B4 */
+/* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */
+#define HSCOEFF0	__REG_2700G(0x000021b4)
+#define HSCOEFF1	__REG_2700G(0x000021b8)
+#define HSCOEFF2	__REG_2700G(0x000021bc)
+#define HSCOEFF3	__REG_2700G(0x000021c0)
+#define HSCOEFF4	__REG_2700G(0x000021c4)
+#define HSCOEFF5	__REG_2700G(0x000021c8)
+#define HSCOEFF6	__REG_2700G(0x000021cc)
+#define HSCOEFF7	__REG_2700G(0x000021d0)
+#define HSCOEFF8	__REG_2700G(0x000021d4)
+
+#define SSSIZE		__REG_2700G(0x000021D8)
+
+/* 0x0000_2200 */
+/* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */
+#define VIDGAM0		__REG_2700G(0x00002200)
+#define VIDGAM1		__REG_2700G(0x00002204)
+#define VIDGAM2		__REG_2700G(0x00002208)
+#define VIDGAM3		__REG_2700G(0x0000220c)
+#define VIDGAM4		__REG_2700G(0x00002210)
+#define VIDGAM5		__REG_2700G(0x00002214)
+#define VIDGAM6		__REG_2700G(0x00002218)
+#define VIDGAM7		__REG_2700G(0x0000221c)
+#define VIDGAM8		__REG_2700G(0x00002220)
+#define VIDGAM9		__REG_2700G(0x00002224)
+#define VIDGAM10	__REG_2700G(0x00002228)
+#define VIDGAM11	__REG_2700G(0x0000222c)
+#define VIDGAM12	__REG_2700G(0x00002230)
+#define VIDGAM13	__REG_2700G(0x00002234)
+#define VIDGAM14	__REG_2700G(0x00002238)
+#define VIDGAM15	__REG_2700G(0x0000223c)
+#define VIDGAM16	__REG_2700G(0x00002240)
+
+/* 0x0000_2250 */
+/* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */
+#define GFXGAM0		__REG_2700G(0x00002250)
+#define GFXGAM1		__REG_2700G(0x00002254)
+#define GFXGAM2		__REG_2700G(0x00002258)
+#define GFXGAM3		__REG_2700G(0x0000225c)
+#define GFXGAM4		__REG_2700G(0x00002260)
+#define GFXGAM5		__REG_2700G(0x00002264)
+#define GFXGAM6		__REG_2700G(0x00002268)
+#define GFXGAM7		__REG_2700G(0x0000226c)
+#define GFXGAM8		__REG_2700G(0x00002270)
+#define GFXGAM9		__REG_2700G(0x00002274)
+#define GFXGAM10	__REG_2700G(0x00002278)
+#define GFXGAM11	__REG_2700G(0x0000227c)
+#define GFXGAM12	__REG_2700G(0x00002280)
+#define GFXGAM13	__REG_2700G(0x00002284)
+#define GFXGAM14	__REG_2700G(0x00002288)
+#define GFXGAM15	__REG_2700G(0x0000228c)
+#define GFXGAM16	__REG_2700G(0x00002290)
+
+#define DLSTS		__REG_2700G(0x00002300)
+#define DLLCTRL		__REG_2700G(0x00002304)
+#define DVLNUM		__REG_2700G(0x00002308)
+#define DUCTRL		__REG_2700G(0x0000230c)
+#define DVECTRL		__REG_2700G(0x00002310)
+#define DHDET		__REG_2700G(0x00002314)
+#define DVDET		__REG_2700G(0x00002318)
+#define DODMSK		__REG_2700G(0x0000231c)
+#define CSC01		__REG_2700G(0x00002330)
+#define CSC02		__REG_2700G(0x00002334)
+#define CSC03		__REG_2700G(0x00002338)
+#define CSC04		__REG_2700G(0x0000233c)
+#define CSC05		__REG_2700G(0x00002340)
+
+#define FB_MEMORY_START	__REG_2700G(0x00060000)
+
+#endif /* __REGS_2700G_ */
diff --git a/drivers/video/fbdev/metronomefb.c b/drivers/video/fbdev/metronomefb.c
new file mode 100644
index 000000000000..195cc2db4c2c
--- /dev/null
+++ b/drivers/video/fbdev/metronomefb.c
@@ -0,0 +1,780 @@
+/*
+ * linux/drivers/video/metronomefb.c -- FB driver for Metronome controller
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This work was made possible by help and equipment support from E-Ink
+ * Corporation. http://www.eink.com/
+ *
+ * This driver is written to be used with the Metronome display controller.
+ * It is intended to be architecture independent. A board specific driver
+ * must be used to perform all the physical IO interactions. An example
+ * is provided as am200epd.c
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/irq.h>
+
+#include <video/metronomefb.h>
+
+#include <asm/unaligned.h>
+
+/* Display specific information */
+#define DPY_W 832
+#define DPY_H 622
+
+static int user_wfm_size;
+
+/* frame differs from image. frame includes non-visible pixels */
+struct epd_frame {
+	int fw; /* frame width */
+	int fh; /* frame height */
+	u16 config[4];
+	int wfm_size;
+};
+
+static struct epd_frame epd_frame_table[] = {
+	{
+		.fw = 832,
+		.fh = 622,
+		.config = {
+			15 /* sdlew */
+			| 2 << 8 /* sdosz */
+			| 0 << 11 /* sdor */
+			| 0 << 12 /* sdces */
+			| 0 << 15, /* sdcer */
+			42 /* gdspl */
+			| 1 << 8 /* gdr1 */
+			| 1 << 9 /* sdshr */
+			| 0 << 15, /* gdspp */
+			18 /* gdspw */
+			| 0 << 15, /* dispc */
+			599 /* vdlc */
+			| 0 << 11 /* dsi */
+			| 0 << 12, /* dsic */
+		},
+		.wfm_size = 47001,
+	},
+	{
+		.fw = 1088,
+		.fh = 791,
+		.config = {
+			0x0104,
+			0x031f,
+			0x0088,
+			0x02ff,
+		},
+		.wfm_size = 46770,
+	},
+	{
+		.fw = 1200,
+		.fh = 842,
+		.config = {
+			0x0101,
+			0x030e,
+			0x0012,
+			0x0280,
+		},
+		.wfm_size = 46770,
+	},
+};
+
+static struct fb_fix_screeninfo metronomefb_fix = {
+	.id =		"metronomefb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_STATIC_PSEUDOCOLOR,
+	.xpanstep =	0,
+	.ypanstep =	0,
+	.ywrapstep =	0,
+	.line_length =	DPY_W,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo metronomefb_var = {
+	.xres		= DPY_W,
+	.yres		= DPY_H,
+	.xres_virtual	= DPY_W,
+	.yres_virtual	= DPY_H,
+	.bits_per_pixel	= 8,
+	.grayscale	= 1,
+	.nonstd		= 1,
+	.red =		{ 4, 3, 0 },
+	.green =	{ 0, 0, 0 },
+	.blue =		{ 0, 0, 0 },
+	.transp =	{ 0, 0, 0 },
+};
+
+/* the waveform structure that is coming from userspace firmware */
+struct waveform_hdr {
+	u8 stuff[32];
+
+	u8 wmta[3];
+	u8 fvsn;
+
+	u8 luts;
+	u8 mc;
+	u8 trc;
+	u8 stuff3;
+
+	u8 endb;
+	u8 swtb;
+	u8 stuff2a[2];
+
+	u8 stuff2b[3];
+	u8 wfm_cs;
+} __attribute__ ((packed));
+
+/* main metronomefb functions */
+static u8 calc_cksum(int start, int end, u8 *mem)
+{
+	u8 tmp = 0;
+	int i;
+
+	for (i = start; i < end; i++)
+		tmp += mem[i];
+
+	return tmp;
+}
+
+static u16 calc_img_cksum(u16 *start, int length)
+{
+	u16 tmp = 0;
+
+	while (length--)
+		tmp += *start++;
+
+	return tmp;
+}
+
+/* here we decode the incoming waveform file and populate metromem */
+static int load_waveform(u8 *mem, size_t size, int m, int t,
+			 struct metronomefb_par *par)
+{
+	int tta;
+	int wmta;
+	int trn = 0;
+	int i;
+	unsigned char v;
+	u8 cksum;
+	int cksum_idx;
+	int wfm_idx, owfm_idx;
+	int mem_idx = 0;
+	struct waveform_hdr *wfm_hdr;
+	u8 *metromem = par->metromem_wfm;
+	struct device *dev = par->info->dev;
+
+	if (user_wfm_size)
+		epd_frame_table[par->dt].wfm_size = user_wfm_size;
+
+	if (size != epd_frame_table[par->dt].wfm_size) {
+		dev_err(dev, "Error: unexpected size %Zd != %d\n", size,
+					epd_frame_table[par->dt].wfm_size);
+		return -EINVAL;
+	}
+
+	wfm_hdr = (struct waveform_hdr *) mem;
+
+	if (wfm_hdr->fvsn != 1) {
+		dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
+		return -EINVAL;
+	}
+	if (wfm_hdr->luts != 0) {
+		dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
+		return -EINVAL;
+	}
+	cksum = calc_cksum(32, 47, mem);
+	if (cksum != wfm_hdr->wfm_cs) {
+		dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
+					wfm_hdr->wfm_cs);
+		return -EINVAL;
+	}
+	wfm_hdr->mc += 1;
+	wfm_hdr->trc += 1;
+	for (i = 0; i < 5; i++) {
+		if (*(wfm_hdr->stuff2a + i) != 0) {
+			dev_err(dev, "Error: unexpected value in padding\n");
+			return -EINVAL;
+		}
+	}
+
+	/* calculating trn. trn is something used to index into
+	the waveform. presumably selecting the right one for the
+	desired temperature. it works out the offset of the first
+	v that exceeds the specified temperature */
+	if ((sizeof(*wfm_hdr) + wfm_hdr->trc) > size)
+		return -EINVAL;
+
+	for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + wfm_hdr->trc; i++) {
+		if (mem[i] > t) {
+			trn = i - sizeof(*wfm_hdr) - 1;
+			break;
+		}
+	}
+
+	/* check temperature range table checksum */
+	cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1;
+	if (cksum_idx > size)
+		return -EINVAL;
+	cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
+	if (cksum != mem[cksum_idx]) {
+		dev_err(dev, "Error: bad temperature range table cksum"
+				" %x != %x\n", cksum, mem[cksum_idx]);
+		return -EINVAL;
+	}
+
+	/* check waveform mode table address checksum */
+	wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
+	cksum_idx = wmta + m*4 + 3;
+	if (cksum_idx > size)
+		return -EINVAL;
+	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
+	if (cksum != mem[cksum_idx]) {
+		dev_err(dev, "Error: bad mode table address cksum"
+				" %x != %x\n", cksum, mem[cksum_idx]);
+		return -EINVAL;
+	}
+
+	/* check waveform temperature table address checksum */
+	tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
+	cksum_idx = tta + trn*4 + 3;
+	if (cksum_idx > size)
+		return -EINVAL;
+	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
+	if (cksum != mem[cksum_idx]) {
+		dev_err(dev, "Error: bad temperature table address cksum"
+			" %x != %x\n", cksum, mem[cksum_idx]);
+		return -EINVAL;
+	}
+
+	/* here we do the real work of putting the waveform into the
+	metromem buffer. this does runlength decoding of the waveform */
+	wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
+	owfm_idx = wfm_idx;
+	if (wfm_idx > size)
+		return -EINVAL;
+	while (wfm_idx < size) {
+		unsigned char rl;
+		v = mem[wfm_idx++];
+		if (v == wfm_hdr->swtb) {
+			while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) &&
+				wfm_idx < size)
+				metromem[mem_idx++] = v;
+
+			continue;
+		}
+
+		if (v == wfm_hdr->endb)
+			break;
+
+		rl = mem[wfm_idx++];
+		for (i = 0; i <= rl; i++)
+			metromem[mem_idx++] = v;
+	}
+
+	cksum_idx = wfm_idx;
+	if (cksum_idx > size)
+		return -EINVAL;
+	cksum = calc_cksum(owfm_idx, cksum_idx, mem);
+	if (cksum != mem[cksum_idx]) {
+		dev_err(dev, "Error: bad waveform data cksum"
+				" %x != %x\n", cksum, mem[cksum_idx]);
+		return -EINVAL;
+	}
+	par->frame_count = (mem_idx/64);
+
+	return 0;
+}
+
+static int metronome_display_cmd(struct metronomefb_par *par)
+{
+	int i;
+	u16 cs;
+	u16 opcode;
+	static u8 borderval;
+
+	/* setup display command
+	we can't immediately set the opcode since the controller
+	will try parse the command before we've set it all up
+	so we just set cs here and set the opcode at the end */
+
+	if (par->metromem_cmd->opcode == 0xCC40)
+		opcode = cs = 0xCC41;
+	else
+		opcode = cs = 0xCC40;
+
+	/* set the args ( 2 bytes ) for display */
+	i = 0;
+	par->metromem_cmd->args[i] = 	1 << 3 /* border update */
+					| ((borderval++ % 4) & 0x0F) << 4
+					| (par->frame_count - 1) << 8;
+	cs += par->metromem_cmd->args[i++];
+
+	/* the rest are 0 */
+	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
+
+	par->metromem_cmd->csum = cs;
+	par->metromem_cmd->opcode = opcode; /* display cmd */
+
+	return par->board->met_wait_event_intr(par);
+}
+
+static int metronome_powerup_cmd(struct metronomefb_par *par)
+{
+	int i;
+	u16 cs;
+
+	/* setup power up command */
+	par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */
+	cs = par->metromem_cmd->opcode;
+
+	/* set pwr1,2,3 to 1024 */
+	for (i = 0; i < 3; i++) {
+		par->metromem_cmd->args[i] = 1024;
+		cs += par->metromem_cmd->args[i];
+	}
+
+	/* the rest are 0 */
+	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
+
+	par->metromem_cmd->csum = cs;
+
+	msleep(1);
+	par->board->set_rst(par, 1);
+
+	msleep(1);
+	par->board->set_stdby(par, 1);
+
+	return par->board->met_wait_event(par);
+}
+
+static int metronome_config_cmd(struct metronomefb_par *par)
+{
+	/* setup config command
+	we can't immediately set the opcode since the controller
+	will try parse the command before we've set it all up */
+
+	memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
+		sizeof(epd_frame_table[par->dt].config));
+	/* the rest are 0 */
+	memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
+
+	par->metromem_cmd->csum = 0xCC10;
+	par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
+	par->metromem_cmd->opcode = 0xCC10; /* config cmd */
+
+	return par->board->met_wait_event(par);
+}
+
+static int metronome_init_cmd(struct metronomefb_par *par)
+{
+	int i;
+	u16 cs;
+
+	/* setup init command
+	we can't immediately set the opcode since the controller
+	will try parse the command before we've set it all up
+	so we just set cs here and set the opcode at the end */
+
+	cs = 0xCC20;
+
+	/* set the args ( 2 bytes ) for init */
+	i = 0;
+	par->metromem_cmd->args[i] = 0;
+	cs += par->metromem_cmd->args[i++];
+
+	/* the rest are 0 */
+	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
+
+	par->metromem_cmd->csum = cs;
+	par->metromem_cmd->opcode = 0xCC20; /* init cmd */
+
+	return par->board->met_wait_event(par);
+}
+
+static int metronome_init_regs(struct metronomefb_par *par)
+{
+	int res;
+
+	res = par->board->setup_io(par);
+	if (res)
+		return res;
+
+	res = metronome_powerup_cmd(par);
+	if (res)
+		return res;
+
+	res = metronome_config_cmd(par);
+	if (res)
+		return res;
+
+	res = metronome_init_cmd(par);
+
+	return res;
+}
+
+static void metronomefb_dpy_update(struct metronomefb_par *par)
+{
+	int fbsize;
+	u16 cksum;
+	unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+
+	fbsize = par->info->fix.smem_len;
+	/* copy from vm to metromem */
+	memcpy(par->metromem_img, buf, fbsize);
+
+	cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
+	*((u16 *)(par->metromem_img) + fbsize/2) = cksum;
+	metronome_display_cmd(par);
+}
+
+static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
+{
+	int i;
+	u16 csum = 0;
+	u16 *buf = (u16 __force *)(par->info->screen_base + index);
+	u16 *img = (u16 *)(par->metromem_img + index);
+
+	/* swizzle from vm to metromem and recalc cksum at the same time*/
+	for (i = 0; i < PAGE_SIZE/2; i++) {
+		*(img + i) = (buf[i] << 5) & 0xE0E0;
+		csum += *(img + i);
+	}
+	return csum;
+}
+
+/* this is called back from the deferred io workqueue */
+static void metronomefb_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	u16 cksum;
+	struct page *cur;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct metronomefb_par *par = info->par;
+
+	/* walk the written page list and swizzle the data */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+		cksum = metronomefb_dpy_update_page(par,
+					(cur->index << PAGE_SHIFT));
+		par->metromem_img_csum -= par->csum_table[cur->index];
+		par->csum_table[cur->index] = cksum;
+		par->metromem_img_csum += cksum;
+	}
+
+	metronome_display_cmd(par);
+}
+
+static void metronomefb_fillrect(struct fb_info *info,
+				   const struct fb_fillrect *rect)
+{
+	struct metronomefb_par *par = info->par;
+
+	sys_fillrect(info, rect);
+	metronomefb_dpy_update(par);
+}
+
+static void metronomefb_copyarea(struct fb_info *info,
+				   const struct fb_copyarea *area)
+{
+	struct metronomefb_par *par = info->par;
+
+	sys_copyarea(info, area);
+	metronomefb_dpy_update(par);
+}
+
+static void metronomefb_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	struct metronomefb_par *par = info->par;
+
+	sys_imageblit(info, image);
+	metronomefb_dpy_update(par);
+}
+
+/*
+ * this is the slow path from userspace. they can seek and write to
+ * the fb. it is based on fb_sys_write
+ */
+static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct metronomefb_par *par = info->par;
+	unsigned long p = *ppos;
+	void *dst;
+	int err = 0;
+	unsigned long total_size;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
+		count = total_size - p;
+	}
+
+	dst = (void __force *)(info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		err = -EFAULT;
+
+	if  (!err)
+		*ppos += count;
+
+	metronomefb_dpy_update(par);
+
+	return (err) ? err : count;
+}
+
+static struct fb_ops metronomefb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_write	= metronomefb_write,
+	.fb_fillrect	= metronomefb_fillrect,
+	.fb_copyarea	= metronomefb_copyarea,
+	.fb_imageblit	= metronomefb_imageblit,
+};
+
+static struct fb_deferred_io metronomefb_defio = {
+	.delay		= HZ,
+	.deferred_io	= metronomefb_dpy_deferred_io,
+};
+
+static int metronomefb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	struct metronome_board *board;
+	int retval = -ENOMEM;
+	int videomemorysize;
+	unsigned char *videomemory;
+	struct metronomefb_par *par;
+	const struct firmware *fw_entry;
+	int i;
+	int panel_type;
+	int fw, fh;
+	int epd_dt_index;
+
+	/* pick up board specific routines */
+	board = dev->dev.platform_data;
+	if (!board)
+		return -EINVAL;
+
+	/* try to count device specific driver, if can't, platform recalls */
+	if (!try_module_get(board->owner))
+		return -ENODEV;
+
+	info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
+	if (!info)
+		goto err;
+
+	/* we have two blocks of memory.
+	info->screen_base which is vm, and is the fb used by apps.
+	par->metromem which is physically contiguous memory and
+	contains the display controller commands, waveform,
+	processed image data and padding. this is the data pulled
+	by the device's LCD controller and pushed to Metronome.
+	the metromem memory is allocated by the board driver and
+	is provided to us */
+
+	panel_type = board->get_panel_type();
+	switch (panel_type) {
+	case 6:
+		epd_dt_index = 0;
+		break;
+	case 8:
+		epd_dt_index = 1;
+		break;
+	case 97:
+		epd_dt_index = 2;
+		break;
+	default:
+		dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
+		epd_dt_index = 0;
+		break;
+	}
+
+	fw = epd_frame_table[epd_dt_index].fw;
+	fh = epd_frame_table[epd_dt_index].fh;
+
+	/* we need to add a spare page because our csum caching scheme walks
+	 * to the end of the page */
+	videomemorysize = PAGE_SIZE + (fw * fh);
+	videomemory = vzalloc(videomemorysize);
+	if (!videomemory)
+		goto err_fb_rel;
+
+	info->screen_base = (char __force __iomem *)videomemory;
+	info->fbops = &metronomefb_ops;
+
+	metronomefb_fix.line_length = fw;
+	metronomefb_var.xres = fw;
+	metronomefb_var.yres = fh;
+	metronomefb_var.xres_virtual = fw;
+	metronomefb_var.yres_virtual = fh;
+	info->var = metronomefb_var;
+	info->fix = metronomefb_fix;
+	info->fix.smem_len = videomemorysize;
+	par = info->par;
+	par->info = info;
+	par->board = board;
+	par->dt = epd_dt_index;
+	init_waitqueue_head(&par->waitq);
+
+	/* this table caches per page csum values. */
+	par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
+	if (!par->csum_table)
+		goto err_vfree;
+
+	/* the physical framebuffer that we use is setup by
+	 * the platform device driver. It will provide us
+	 * with cmd, wfm and image memory in a contiguous area. */
+	retval = board->setup_fb(par);
+	if (retval) {
+		dev_err(&dev->dev, "Failed to setup fb\n");
+		goto err_csum_table;
+	}
+
+	/* after this point we should have a framebuffer */
+	if ((!par->metromem_wfm) ||  (!par->metromem_img) ||
+		(!par->metromem_dma)) {
+		dev_err(&dev->dev, "fb access failure\n");
+		retval = -EINVAL;
+		goto err_csum_table;
+	}
+
+	info->fix.smem_start = par->metromem_dma;
+
+	/* load the waveform in. assume mode 3, temp 31 for now
+		a) request the waveform file from userspace
+		b) process waveform and decode into metromem */
+	retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
+	if (retval < 0) {
+		dev_err(&dev->dev, "Failed to get waveform\n");
+		goto err_csum_table;
+	}
+
+	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
+				par);
+	release_firmware(fw_entry);
+	if (retval < 0) {
+		dev_err(&dev->dev, "Failed processing waveform\n");
+		goto err_csum_table;
+	}
+
+	retval = board->setup_irq(info);
+	if (retval)
+		goto err_csum_table;
+
+	retval = metronome_init_regs(par);
+	if (retval < 0)
+		goto err_free_irq;
+
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+
+	info->fbdefio = &metronomefb_defio;
+	fb_deferred_io_init(info);
+
+	retval = fb_alloc_cmap(&info->cmap, 8, 0);
+	if (retval < 0) {
+		dev_err(&dev->dev, "Failed to allocate colormap\n");
+		goto err_free_irq;
+	}
+
+	/* set cmap */
+	for (i = 0; i < 8; i++)
+		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/16;
+	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
+	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_cmap;
+
+	platform_set_drvdata(dev, info);
+
+	dev_dbg(&dev->dev,
+		"fb%d: Metronome frame buffer device, using %dK of video"
+		" memory\n", info->node, videomemorysize >> 10);
+
+	return 0;
+
+err_cmap:
+	fb_dealloc_cmap(&info->cmap);
+err_free_irq:
+	board->cleanup(par);
+err_csum_table:
+	vfree(par->csum_table);
+err_vfree:
+	vfree(videomemory);
+err_fb_rel:
+	framebuffer_release(info);
+err:
+	module_put(board->owner);
+	return retval;
+}
+
+static int metronomefb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		struct metronomefb_par *par = info->par;
+
+		unregister_framebuffer(info);
+		fb_deferred_io_cleanup(info);
+		fb_dealloc_cmap(&info->cmap);
+		par->board->cleanup(par);
+		vfree(par->csum_table);
+		vfree((void __force *)info->screen_base);
+		module_put(par->board->owner);
+		dev_dbg(&dev->dev, "calling release\n");
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct platform_driver metronomefb_driver = {
+	.probe	= metronomefb_probe,
+	.remove = metronomefb_remove,
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "metronomefb",
+	},
+};
+module_platform_driver(metronomefb_driver);
+
+module_param(user_wfm_size, uint, 0);
+MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
+
+MODULE_DESCRIPTION("fbdev driver for Metronome controller");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mmp/Kconfig b/drivers/video/fbdev/mmp/Kconfig
new file mode 100644
index 000000000000..d4a4ffc24749
--- /dev/null
+++ b/drivers/video/fbdev/mmp/Kconfig
@@ -0,0 +1,11 @@
+menuconfig MMP_DISP
+        tristate "Marvell MMP Display Subsystem support"
+        depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988
+        help
+	  Marvell Display Subsystem support.
+
+if MMP_DISP
+source "drivers/video/fbdev/mmp/hw/Kconfig"
+source "drivers/video/fbdev/mmp/panel/Kconfig"
+source "drivers/video/fbdev/mmp/fb/Kconfig"
+endif
diff --git a/drivers/video/fbdev/mmp/Makefile b/drivers/video/fbdev/mmp/Makefile
new file mode 100644
index 000000000000..a014cb358bf8
--- /dev/null
+++ b/drivers/video/fbdev/mmp/Makefile
@@ -0,0 +1 @@
+obj-y += core.o hw/ panel/ fb/
diff --git a/drivers/video/fbdev/mmp/core.c b/drivers/video/fbdev/mmp/core.c
new file mode 100644
index 000000000000..b563b920f159
--- /dev/null
+++ b/drivers/video/fbdev/mmp/core.c
@@ -0,0 +1,251 @@
+/*
+ * linux/drivers/video/mmp/common.c
+ * This driver is a common framework for Marvell Display Controller
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Authors: Zhou Zhu <zzhu3@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <video/mmp_disp.h>
+
+static struct mmp_overlay *path_get_overlay(struct mmp_path *path,
+		int overlay_id)
+{
+	if (path && overlay_id < path->overlay_num)
+		return &path->overlays[overlay_id];
+	return NULL;
+}
+
+static int path_check_status(struct mmp_path *path)
+{
+	int i;
+	for (i = 0; i < path->overlay_num; i++)
+		if (path->overlays[i].status)
+			return 1;
+
+	return 0;
+}
+
+/*
+ * Get modelist write pointer of modelist.
+ * It also returns modelist number
+ * this function fetches modelist from phy/panel:
+ *   for HDMI/parallel or dsi to hdmi cases, get from phy
+ *   or get from panel
+ */
+static int path_get_modelist(struct mmp_path *path,
+		struct mmp_mode **modelist)
+{
+	BUG_ON(!path || !modelist);
+
+	if (path->panel && path->panel->get_modelist)
+		return path->panel->get_modelist(path->panel, modelist);
+
+	return 0;
+}
+
+/*
+ * panel list is used to pair panel/path when path/panel registered
+ * path list is used for both buffer driver and platdriver
+ * plat driver do path register/unregister
+ * panel driver do panel register/unregister
+ * buffer driver get registered path
+ */
+static LIST_HEAD(panel_list);
+static LIST_HEAD(path_list);
+static DEFINE_MUTEX(disp_lock);
+
+/*
+ * mmp_register_panel - register panel to panel_list and connect to path
+ * @p: panel to be registered
+ *
+ * this function provides interface for panel drivers to register panel
+ * to panel_list and connect to path which matchs panel->plat_path_name.
+ * no error returns when no matching path is found as path register after
+ * panel register is permitted.
+ */
+void mmp_register_panel(struct mmp_panel *panel)
+{
+	struct mmp_path *path;
+
+	mutex_lock(&disp_lock);
+
+	/* add */
+	list_add_tail(&panel->node, &panel_list);
+
+	/* try to register to path */
+	list_for_each_entry(path, &path_list, node) {
+		if (!strcmp(panel->plat_path_name, path->name)) {
+			dev_info(panel->dev, "connect to path %s\n",
+				path->name);
+			path->panel = panel;
+			break;
+		}
+	}
+
+	mutex_unlock(&disp_lock);
+}
+EXPORT_SYMBOL_GPL(mmp_register_panel);
+
+/*
+ * mmp_unregister_panel - unregister panel from panel_list and disconnect
+ * @p: panel to be unregistered
+ *
+ * this function provides interface for panel drivers to unregister panel
+ * from panel_list and disconnect from path.
+ */
+void mmp_unregister_panel(struct mmp_panel *panel)
+{
+	struct mmp_path *path;
+
+	mutex_lock(&disp_lock);
+	list_del(&panel->node);
+
+	list_for_each_entry(path, &path_list, node) {
+		if (path->panel && path->panel == panel) {
+			dev_info(panel->dev, "disconnect from path %s\n",
+				path->name);
+			path->panel = NULL;
+			break;
+		}
+	}
+	mutex_unlock(&disp_lock);
+}
+EXPORT_SYMBOL_GPL(mmp_unregister_panel);
+
+/*
+ * mmp_get_path - get path by name
+ * @p: path name
+ *
+ * this function checks path name in path_list and return matching path
+ * return NULL if no matching path
+ */
+struct mmp_path *mmp_get_path(const char *name)
+{
+	struct mmp_path *path;
+	int found = 0;
+
+	mutex_lock(&disp_lock);
+	list_for_each_entry(path, &path_list, node) {
+		if (!strcmp(name, path->name)) {
+			found = 1;
+			break;
+		}
+	}
+	mutex_unlock(&disp_lock);
+
+	return found ? path : NULL;
+}
+EXPORT_SYMBOL_GPL(mmp_get_path);
+
+/*
+ * mmp_register_path - init and register path by path_info
+ * @p: path info provided by display controller
+ *
+ * this function init by path info and register path to path_list
+ * this function also try to connect path with panel by name
+ */
+struct mmp_path *mmp_register_path(struct mmp_path_info *info)
+{
+	int i;
+	size_t size;
+	struct mmp_path *path = NULL;
+	struct mmp_panel *panel;
+
+	size = sizeof(struct mmp_path)
+		+ sizeof(struct mmp_overlay) * info->overlay_num;
+	path = kzalloc(size, GFP_KERNEL);
+	if (!path)
+		return NULL;
+
+	/* path set */
+	mutex_init(&path->access_ok);
+	path->dev = info->dev;
+	path->id = info->id;
+	path->name = info->name;
+	path->output_type = info->output_type;
+	path->overlay_num = info->overlay_num;
+	path->plat_data = info->plat_data;
+	path->ops.set_mode = info->set_mode;
+
+	mutex_lock(&disp_lock);
+	/* get panel */
+	list_for_each_entry(panel, &panel_list, node) {
+		if (!strcmp(info->name, panel->plat_path_name)) {
+			dev_info(path->dev, "get panel %s\n", panel->name);
+			path->panel = panel;
+			break;
+		}
+	}
+
+	dev_info(path->dev, "register %s, overlay_num %d\n",
+			path->name, path->overlay_num);
+
+	/* default op set: if already set by driver, never cover it */
+	if (!path->ops.check_status)
+		path->ops.check_status = path_check_status;
+	if (!path->ops.get_overlay)
+		path->ops.get_overlay = path_get_overlay;
+	if (!path->ops.get_modelist)
+		path->ops.get_modelist = path_get_modelist;
+
+	/* step3: init overlays */
+	for (i = 0; i < path->overlay_num; i++) {
+		path->overlays[i].path = path;
+		path->overlays[i].id = i;
+		mutex_init(&path->overlays[i].access_ok);
+		path->overlays[i].ops = info->overlay_ops;
+	}
+
+	/* add to pathlist */
+	list_add_tail(&path->node, &path_list);
+
+	mutex_unlock(&disp_lock);
+	return path;
+}
+EXPORT_SYMBOL_GPL(mmp_register_path);
+
+/*
+ * mmp_unregister_path - unregister and destory path
+ * @p: path to be destoried.
+ *
+ * this function registers path and destorys it.
+ */
+void mmp_unregister_path(struct mmp_path *path)
+{
+	int i;
+
+	if (!path)
+		return;
+
+	mutex_lock(&disp_lock);
+	/* del from pathlist */
+	list_del(&path->node);
+
+	/* deinit overlays */
+	for (i = 0; i < path->overlay_num; i++)
+		mutex_destroy(&path->overlays[i].access_ok);
+
+	mutex_destroy(&path->access_ok);
+
+	kfree(path);
+	mutex_unlock(&disp_lock);
+}
+EXPORT_SYMBOL_GPL(mmp_unregister_path);
diff --git a/drivers/video/fbdev/mmp/fb/Kconfig b/drivers/video/fbdev/mmp/fb/Kconfig
new file mode 100644
index 000000000000..9b0141f105f5
--- /dev/null
+++ b/drivers/video/fbdev/mmp/fb/Kconfig
@@ -0,0 +1,13 @@
+if MMP_DISP
+
+config MMP_FB
+	bool "fb driver for Marvell MMP Display Subsystem"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	default y
+	help
+		fb driver for Marvell MMP Display Subsystem
+
+endif
diff --git a/drivers/video/fbdev/mmp/fb/Makefile b/drivers/video/fbdev/mmp/fb/Makefile
new file mode 100644
index 000000000000..709fd1f76abe
--- /dev/null
+++ b/drivers/video/fbdev/mmp/fb/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MMP_FB)  += mmpfb.o
diff --git a/drivers/video/fbdev/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c
new file mode 100644
index 000000000000..7ab31eb76a8c
--- /dev/null
+++ b/drivers/video/fbdev/mmp/fb/mmpfb.c
@@ -0,0 +1,694 @@
+/*
+ * linux/drivers/video/mmp/fb/mmpfb.c
+ * Framebuffer driver for Marvell Display controller.
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Authors: Zhou Zhu <zzhu3@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include "mmpfb.h"
+
+static int var_to_pixfmt(struct fb_var_screeninfo *var)
+{
+	/*
+	 * Pseudocolor mode?
+	 */
+	if (var->bits_per_pixel == 8)
+		return PIXFMT_PSEUDOCOLOR;
+
+	/*
+	 * Check for YUV422PLANAR.
+	 */
+	if (var->bits_per_pixel == 16 && var->red.length == 8 &&
+			var->green.length == 4 && var->blue.length == 4) {
+		if (var->green.offset >= var->blue.offset)
+			return PIXFMT_YUV422P;
+		else
+			return PIXFMT_YVU422P;
+	}
+
+	/*
+	 * Check for YUV420PLANAR.
+	 */
+	if (var->bits_per_pixel == 12 && var->red.length == 8 &&
+			var->green.length == 2 && var->blue.length == 2) {
+		if (var->green.offset >= var->blue.offset)
+			return PIXFMT_YUV420P;
+		else
+			return PIXFMT_YVU420P;
+	}
+
+	/*
+	 * Check for YUV422PACK.
+	 */
+	if (var->bits_per_pixel == 16 && var->red.length == 16 &&
+			var->green.length == 16 && var->blue.length == 16) {
+		if (var->red.offset == 0)
+			return PIXFMT_YUYV;
+		else if (var->green.offset >= var->blue.offset)
+			return PIXFMT_UYVY;
+		else
+			return PIXFMT_VYUY;
+	}
+
+	/*
+	 * Check for 565/1555.
+	 */
+	if (var->bits_per_pixel == 16 && var->red.length <= 5 &&
+			var->green.length <= 6 && var->blue.length <= 5) {
+		if (var->transp.length == 0) {
+			if (var->red.offset >= var->blue.offset)
+				return PIXFMT_RGB565;
+			else
+				return PIXFMT_BGR565;
+		}
+	}
+
+	/*
+	 * Check for 888/A888.
+	 */
+	if (var->bits_per_pixel <= 32 && var->red.length <= 8 &&
+			var->green.length <= 8 && var->blue.length <= 8) {
+		if (var->bits_per_pixel == 24 && var->transp.length == 0) {
+			if (var->red.offset >= var->blue.offset)
+				return PIXFMT_RGB888PACK;
+			else
+				return PIXFMT_BGR888PACK;
+		}
+
+		if (var->bits_per_pixel == 32 && var->transp.offset == 24) {
+			if (var->red.offset >= var->blue.offset)
+				return PIXFMT_RGBA888;
+			else
+				return PIXFMT_BGRA888;
+		} else {
+			if (var->red.offset >= var->blue.offset)
+				return PIXFMT_RGB888UNPACK;
+			else
+				return PIXFMT_BGR888UNPACK;
+		}
+
+		/* fall through */
+	}
+
+	return -EINVAL;
+}
+
+static void pixfmt_to_var(struct fb_var_screeninfo *var, int pix_fmt)
+{
+	switch (pix_fmt) {
+	case PIXFMT_RGB565:
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;	var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 6;
+		var->blue.offset = 0;	var->blue.length = 5;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_BGR565:
+		var->bits_per_pixel = 16;
+		var->red.offset = 0;	var->red.length = 5;
+		var->green.offset = 5;	 var->green.length = 6;
+		var->blue.offset = 11;	var->blue.length = 5;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_RGB888UNPACK:
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;	var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;	var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_BGR888UNPACK:
+		var->bits_per_pixel = 32;
+		var->red.offset = 0;	var->red.length = 8;
+		var->green.offset = 8;	 var->green.length = 8;
+		var->blue.offset = 16;	var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_RGBA888:
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;	var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;	var->blue.length = 8;
+		var->transp.offset = 24; var->transp.length = 8;
+		break;
+	case PIXFMT_BGRA888:
+		var->bits_per_pixel = 32;
+		var->red.offset = 0;	var->red.length = 8;
+		var->green.offset = 8;	 var->green.length = 8;
+		var->blue.offset = 16;	var->blue.length = 8;
+		var->transp.offset = 24; var->transp.length = 8;
+		break;
+	case PIXFMT_RGB888PACK:
+		var->bits_per_pixel = 24;
+		var->red.offset = 16;	var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;	var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_BGR888PACK:
+		var->bits_per_pixel = 24;
+		var->red.offset = 0;	var->red.length = 8;
+		var->green.offset = 8;	 var->green.length = 8;
+		var->blue.offset = 16;	var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_YUV420P:
+		var->bits_per_pixel = 12;
+		var->red.offset = 4;	 var->red.length = 8;
+		var->green.offset = 2;   var->green.length = 2;
+		var->blue.offset = 0;   var->blue.length = 2;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_YVU420P:
+		var->bits_per_pixel = 12;
+		var->red.offset = 4;	 var->red.length = 8;
+		var->green.offset = 0;	 var->green.length = 2;
+		var->blue.offset = 2;	var->blue.length = 2;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_YUV422P:
+		var->bits_per_pixel = 16;
+		var->red.offset = 8;	 var->red.length = 8;
+		var->green.offset = 4;   var->green.length = 4;
+		var->blue.offset = 0;   var->blue.length = 4;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_YVU422P:
+		var->bits_per_pixel = 16;
+		var->red.offset = 8;	 var->red.length = 8;
+		var->green.offset = 0;	 var->green.length = 4;
+		var->blue.offset = 4;	var->blue.length = 4;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_UYVY:
+		var->bits_per_pixel = 16;
+		var->red.offset = 8;	 var->red.length = 16;
+		var->green.offset = 4;   var->green.length = 16;
+		var->blue.offset = 0;   var->blue.length = 16;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_VYUY:
+		var->bits_per_pixel = 16;
+		var->red.offset = 8;	 var->red.length = 16;
+		var->green.offset = 0;	 var->green.length = 16;
+		var->blue.offset = 4;	var->blue.length = 16;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_YUYV:
+		var->bits_per_pixel = 16;
+		var->red.offset = 0;	 var->red.length = 16;
+		var->green.offset = 4;	 var->green.length = 16;
+		var->blue.offset = 8;	var->blue.length = 16;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIXFMT_PSEUDOCOLOR:
+		var->bits_per_pixel = 8;
+		var->red.offset = 0;	 var->red.length = 8;
+		var->green.offset = 0;   var->green.length = 8;
+		var->blue.offset = 0;	var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	}
+}
+
+/*
+ * fb framework has its limitation:
+ * 1. input color/output color is not seprated
+ * 2. fb_videomode not include output color
+ * so for fb usage, we keep a output format which is not changed
+ *  then it's added for mmpmode
+ */
+static void fbmode_to_mmpmode(struct mmp_mode *mode,
+		struct fb_videomode *videomode, int output_fmt)
+{
+	u64 div_result = 1000000000000ll;
+	mode->name = videomode->name;
+	mode->refresh = videomode->refresh;
+	mode->xres = videomode->xres;
+	mode->yres = videomode->yres;
+
+	do_div(div_result, videomode->pixclock);
+	mode->pixclock_freq = (u32)div_result;
+
+	mode->left_margin = videomode->left_margin;
+	mode->right_margin = videomode->right_margin;
+	mode->upper_margin = videomode->upper_margin;
+	mode->lower_margin = videomode->lower_margin;
+	mode->hsync_len = videomode->hsync_len;
+	mode->vsync_len = videomode->vsync_len;
+	mode->hsync_invert = !!(videomode->sync & FB_SYNC_HOR_HIGH_ACT);
+	mode->vsync_invert = !!(videomode->sync & FB_SYNC_VERT_HIGH_ACT);
+	/* no defined flag in fb, use vmode>>3*/
+	mode->invert_pixclock = !!(videomode->vmode & 8);
+	mode->pix_fmt_out = output_fmt;
+}
+
+static void mmpmode_to_fbmode(struct fb_videomode *videomode,
+		struct mmp_mode *mode)
+{
+	u64 div_result = 1000000000000ll;
+
+	videomode->name = mode->name;
+	videomode->refresh = mode->refresh;
+	videomode->xres = mode->xres;
+	videomode->yres = mode->yres;
+
+	do_div(div_result, mode->pixclock_freq);
+	videomode->pixclock = (u32)div_result;
+
+	videomode->left_margin = mode->left_margin;
+	videomode->right_margin = mode->right_margin;
+	videomode->upper_margin = mode->upper_margin;
+	videomode->lower_margin = mode->lower_margin;
+	videomode->hsync_len = mode->hsync_len;
+	videomode->vsync_len = mode->vsync_len;
+	videomode->sync = (mode->hsync_invert ? FB_SYNC_HOR_HIGH_ACT : 0)
+		| (mode->vsync_invert ? FB_SYNC_VERT_HIGH_ACT : 0);
+	videomode->vmode = mode->invert_pixclock ? 8 : 0;
+}
+
+static int mmpfb_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	struct mmpfb_info *fbi = info->par;
+
+	if (var->bits_per_pixel == 8)
+		return -EINVAL;
+	/*
+	 * Basic geometry sanity checks.
+	 */
+	if (var->xoffset + var->xres > var->xres_virtual)
+		return -EINVAL;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		return -EINVAL;
+
+	/*
+	 * Check size of framebuffer.
+	 */
+	if (var->xres_virtual * var->yres_virtual *
+			(var->bits_per_pixel >> 3) > fbi->fb_size)
+		return -EINVAL;
+
+	return 0;
+}
+
+static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
+}
+
+static u32 to_rgb(u16 red, u16 green, u16 blue)
+{
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	return (red << 16) | (green << 8) | blue;
+}
+
+static int mmpfb_setcolreg(unsigned int regno, unsigned int red,
+		unsigned int green, unsigned int blue,
+		unsigned int trans, struct fb_info *info)
+{
+	struct mmpfb_info *fbi = info->par;
+	u32 val;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) {
+		val =  chan_to_field(red,   &info->var.red);
+		val |= chan_to_field(green, &info->var.green);
+		val |= chan_to_field(blue , &info->var.blue);
+		fbi->pseudo_palette[regno] = val;
+	}
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
+		val = to_rgb(red, green, blue);
+		/* TODO */
+	}
+
+	return 0;
+}
+
+static int mmpfb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	struct mmpfb_info *fbi = info->par;
+	struct mmp_addr addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.phys[0] = (var->yoffset * var->xres_virtual + var->xoffset)
+		* var->bits_per_pixel / 8 + fbi->fb_start_dma;
+	mmp_overlay_set_addr(fbi->overlay, &addr);
+
+	return 0;
+}
+
+static int var_update(struct fb_info *info)
+{
+	struct mmpfb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_videomode *m;
+	int pix_fmt;
+
+	/* set pix_fmt */
+	pix_fmt = var_to_pixfmt(var);
+	if (pix_fmt < 0)
+		return -EINVAL;
+	pixfmt_to_var(var, pix_fmt);
+	fbi->pix_fmt = pix_fmt;
+
+	/* set var according to best video mode*/
+	m = (struct fb_videomode *)fb_match_mode(var, &info->modelist);
+	if (!m) {
+		dev_err(fbi->dev, "set par: no match mode, use best mode\n");
+		m = (struct fb_videomode *)fb_find_best_mode(var,
+				&info->modelist);
+		fb_videomode_to_var(var, m);
+	}
+	memcpy(&fbi->mode, m, sizeof(struct fb_videomode));
+
+	/* fix to 2* yres */
+	var->yres_virtual = var->yres * 2;
+	info->fix.visual = (pix_fmt == PIXFMT_PSEUDOCOLOR) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	info->fix.ypanstep = var->yres;
+	return 0;
+}
+
+static void mmpfb_set_win(struct fb_info *info)
+{
+	struct mmpfb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	struct mmp_win win;
+	u32 stride;
+
+	memset(&win, 0, sizeof(win));
+	win.xsrc = win.xdst = fbi->mode.xres;
+	win.ysrc = win.ydst = fbi->mode.yres;
+	win.pix_fmt = fbi->pix_fmt;
+	stride = pixfmt_to_stride(win.pix_fmt);
+	win.pitch[0] = var->xres_virtual * stride;
+	win.pitch[1] = win.pitch[2] =
+		(stride == 1) ? (var->xres_virtual >> 1) : 0;
+	mmp_overlay_set_win(fbi->overlay, &win);
+}
+
+static int mmpfb_set_par(struct fb_info *info)
+{
+	struct mmpfb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	struct mmp_addr addr;
+	struct mmp_mode mode;
+	int ret;
+
+	ret = var_update(info);
+	if (ret != 0)
+		return ret;
+
+	/* set window/path according to new videomode */
+	fbmode_to_mmpmode(&mode, &fbi->mode, fbi->output_fmt);
+	mmp_path_set_mode(fbi->path, &mode);
+
+	/* set window related info */
+	mmpfb_set_win(info);
+
+	/* set address always */
+	memset(&addr, 0, sizeof(addr));
+	addr.phys[0] = (var->yoffset * var->xres_virtual + var->xoffset)
+		* var->bits_per_pixel / 8 + fbi->fb_start_dma;
+	mmp_overlay_set_addr(fbi->overlay, &addr);
+
+	return 0;
+}
+
+static void mmpfb_power(struct mmpfb_info *fbi, int power)
+{
+	struct mmp_addr addr;
+	struct fb_var_screeninfo *var = &fbi->fb_info->var;
+
+	/* for power on, always set address/window again */
+	if (power) {
+		/* set window related info */
+		mmpfb_set_win(fbi->fb_info);
+
+		/* set address always */
+		memset(&addr, 0, sizeof(addr));
+		addr.phys[0] = fbi->fb_start_dma +
+			(var->yoffset * var->xres_virtual + var->xoffset)
+			* var->bits_per_pixel / 8;
+		mmp_overlay_set_addr(fbi->overlay, &addr);
+	}
+	mmp_overlay_set_onoff(fbi->overlay, power);
+}
+
+static int mmpfb_blank(int blank, struct fb_info *info)
+{
+	struct mmpfb_info *fbi = info->par;
+
+	mmpfb_power(fbi, (blank == FB_BLANK_UNBLANK));
+
+	return 0;
+}
+
+static struct fb_ops mmpfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_blank	= mmpfb_blank,
+	.fb_check_var	= mmpfb_check_var,
+	.fb_set_par	= mmpfb_set_par,
+	.fb_setcolreg	= mmpfb_setcolreg,
+	.fb_pan_display	= mmpfb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int modes_setup(struct mmpfb_info *fbi)
+{
+	struct fb_videomode *videomodes;
+	struct mmp_mode *mmp_modes;
+	struct fb_info *info = fbi->fb_info;
+	int videomode_num, i;
+
+	/* get videomodes from path */
+	videomode_num = mmp_path_get_modelist(fbi->path, &mmp_modes);
+	if (!videomode_num) {
+		dev_warn(fbi->dev, "can't get videomode num\n");
+		return 0;
+	}
+	/* put videomode list to info structure */
+	videomodes = kzalloc(sizeof(struct fb_videomode) * videomode_num,
+			GFP_KERNEL);
+	if (!videomodes) {
+		dev_err(fbi->dev, "can't malloc video modes\n");
+		return -ENOMEM;
+	}
+	for (i = 0; i < videomode_num; i++)
+		mmpmode_to_fbmode(&videomodes[i], &mmp_modes[i]);
+	fb_videomode_to_modelist(videomodes, videomode_num, &info->modelist);
+
+	/* set videomode[0] as default mode */
+	memcpy(&fbi->mode, &videomodes[0], sizeof(struct fb_videomode));
+	fbi->output_fmt = mmp_modes[0].pix_fmt_out;
+	fb_videomode_to_var(&info->var, &fbi->mode);
+	mmp_path_set_mode(fbi->path, &mmp_modes[0]);
+
+	kfree(videomodes);
+	return videomode_num;
+}
+
+static int fb_info_setup(struct fb_info *info,
+			struct mmpfb_info *fbi)
+{
+	int ret = 0;
+	/* Initialise static fb parameters.*/
+	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
+		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+	info->node = -1;
+	strcpy(info->fix.id, fbi->name);
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 0;
+	info->fix.ypanstep = info->var.yres;
+	info->fix.ywrapstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->fix.smem_start = fbi->fb_start_dma;
+	info->fix.smem_len = fbi->fb_size;
+	info->fix.visual = (fbi->pix_fmt == PIXFMT_PSEUDOCOLOR) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = info->var.xres_virtual *
+		info->var.bits_per_pixel / 8;
+	info->fbops = &mmpfb_ops;
+	info->pseudo_palette = fbi->pseudo_palette;
+	info->screen_base = fbi->fb_start;
+	info->screen_size = fbi->fb_size;
+
+	/* For FB framework: Allocate color map and Register framebuffer*/
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+		ret = -ENOMEM;
+
+	return ret;
+}
+
+static void fb_info_clear(struct fb_info *info)
+{
+	fb_dealloc_cmap(&info->cmap);
+}
+
+static int mmpfb_probe(struct platform_device *pdev)
+{
+	struct mmp_buffer_driver_mach_info *mi;
+	struct fb_info *info = 0;
+	struct mmpfb_info *fbi = 0;
+	int ret, modes_num;
+
+	mi = pdev->dev.platform_data;
+	if (mi == NULL) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
+
+	/* initialize fb */
+	info = framebuffer_alloc(sizeof(struct mmpfb_info), &pdev->dev);
+	if (info == NULL)
+		return -ENOMEM;
+	fbi = info->par;
+	if (!fbi) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	/* init fb */
+	fbi->fb_info = info;
+	platform_set_drvdata(pdev, fbi);
+	fbi->dev = &pdev->dev;
+	fbi->name = mi->name;
+	fbi->pix_fmt = mi->default_pixfmt;
+	pixfmt_to_var(&info->var, fbi->pix_fmt);
+	mutex_init(&fbi->access_ok);
+
+	/* get display path by name */
+	fbi->path = mmp_get_path(mi->path_name);
+	if (!fbi->path) {
+		dev_err(&pdev->dev, "can't get the path %s\n", mi->path_name);
+		ret = -EINVAL;
+		goto failed_destroy_mutex;
+	}
+
+	dev_info(fbi->dev, "path %s get\n", fbi->path->name);
+
+	/* get overlay */
+	fbi->overlay = mmp_path_get_overlay(fbi->path, mi->overlay_id);
+	if (!fbi->overlay) {
+		ret = -EINVAL;
+		goto failed_destroy_mutex;
+	}
+	/* set fetch used */
+	mmp_overlay_set_fetch(fbi->overlay, mi->dmafetch_id);
+
+	modes_num = modes_setup(fbi);
+	if (modes_num < 0) {
+		ret = modes_num;
+		goto failed_destroy_mutex;
+	}
+
+	/*
+	 * if get modes success, means not hotplug panels, use caculated buffer
+	 * or use default size
+	 */
+	if (modes_num > 0) {
+		/* fix to 2* yres */
+		info->var.yres_virtual = info->var.yres * 2;
+
+		/* Allocate framebuffer memory: size = modes xy *4 */
+		fbi->fb_size = info->var.xres_virtual * info->var.yres_virtual
+				* info->var.bits_per_pixel / 8;
+	} else {
+		fbi->fb_size = MMPFB_DEFAULT_SIZE;
+	}
+
+	fbi->fb_start = dma_alloc_coherent(&pdev->dev, PAGE_ALIGN(fbi->fb_size),
+				&fbi->fb_start_dma, GFP_KERNEL);
+	if (fbi->fb_start == NULL) {
+		dev_err(&pdev->dev, "can't alloc framebuffer\n");
+		ret = -ENOMEM;
+		goto failed_destroy_mutex;
+	}
+	memset(fbi->fb_start, 0, fbi->fb_size);
+	dev_info(fbi->dev, "fb %dk allocated\n", fbi->fb_size/1024);
+
+	/* fb power on */
+	if (modes_num > 0)
+		mmpfb_power(fbi, 1);
+
+	ret = fb_info_setup(info, fbi);
+	if (ret < 0)
+		goto failed_free_buff;
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register fb: %d\n", ret);
+		ret = -ENXIO;
+		goto failed_clear_info;
+	}
+
+	dev_info(fbi->dev, "loaded to /dev/fb%d <%s>.\n",
+		info->node, info->fix.id);
+
+#ifdef CONFIG_LOGO
+	if (fbi->fb_start) {
+		fb_prepare_logo(info, 0);
+		fb_show_logo(info, 0);
+	}
+#endif
+
+	return 0;
+
+failed_clear_info:
+	fb_info_clear(info);
+failed_free_buff:
+	dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbi->fb_size), fbi->fb_start,
+		fbi->fb_start_dma);
+failed_destroy_mutex:
+	mutex_destroy(&fbi->access_ok);
+failed:
+	dev_err(fbi->dev, "mmp-fb: frame buffer device init failed\n");
+
+	framebuffer_release(info);
+
+	return ret;
+}
+
+static struct platform_driver mmpfb_driver = {
+	.driver		= {
+		.name	= "mmp-fb",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= mmpfb_probe,
+};
+
+static int mmpfb_init(void)
+{
+	return platform_driver_register(&mmpfb_driver);
+}
+module_init(mmpfb_init);
+
+MODULE_AUTHOR("Zhou Zhu <zhou.zhu@marvell.com>");
+MODULE_DESCRIPTION("Framebuffer driver for Marvell displays");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mmp/fb/mmpfb.h b/drivers/video/fbdev/mmp/fb/mmpfb.h
new file mode 100644
index 000000000000..88c23c10a9ec
--- /dev/null
+++ b/drivers/video/fbdev/mmp/fb/mmpfb.h
@@ -0,0 +1,54 @@
+/*
+ * linux/drivers/video/mmp/fb/mmpfb.h
+ * Framebuffer driver for Marvell Display controller.
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Authors: Zhou Zhu <zzhu3@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _MMP_FB_H_
+#define _MMP_FB_H_
+
+#include <video/mmp_disp.h>
+#include <linux/fb.h>
+
+/* LCD controller private state. */
+struct mmpfb_info {
+	struct device	*dev;
+	int	id;
+	const char	*name;
+
+	struct fb_info	*fb_info;
+	/* basicaly videomode is for output */
+	struct fb_videomode	mode;
+	int	pix_fmt;
+
+	void	*fb_start;
+	int	fb_size;
+	dma_addr_t	fb_start_dma;
+
+	struct mmp_overlay	*overlay;
+	struct mmp_path	*path;
+
+	struct mutex	access_ok;
+
+	unsigned int		pseudo_palette[16];
+	int output_fmt;
+};
+
+#define MMPFB_DEFAULT_SIZE (PAGE_ALIGN(1920 * 1080 * 4 * 2))
+#endif /* _MMP_FB_H_ */
diff --git a/drivers/video/fbdev/mmp/hw/Kconfig b/drivers/video/fbdev/mmp/hw/Kconfig
new file mode 100644
index 000000000000..02f109a20cd0
--- /dev/null
+++ b/drivers/video/fbdev/mmp/hw/Kconfig
@@ -0,0 +1,20 @@
+if MMP_DISP
+
+config MMP_DISP_CONTROLLER
+	bool "mmp display controller hw support"
+	depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988
+	default n
+	help
+		Marvell MMP display hw controller support
+		this controller is used on Marvell PXA910,
+		MMP2, MMP3, PXA988 chips
+
+config MMP_DISP_SPI
+	bool "mmp display controller spi port"
+	depends on MMP_DISP_CONTROLLER && SPI_MASTER
+	default y
+	help
+		Marvell MMP display hw controller spi port support
+		will register as a spi master for panel usage
+
+endif
diff --git a/drivers/video/fbdev/mmp/hw/Makefile b/drivers/video/fbdev/mmp/hw/Makefile
new file mode 100644
index 000000000000..0000a714fedf
--- /dev/null
+++ b/drivers/video/fbdev/mmp/hw/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MMP_DISP_CONTROLLER)  += mmp_ctrl.o
+obj-$(CONFIG_MMP_DISP_SPI)	   += mmp_spi.o
diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
new file mode 100644
index 000000000000..8621a9f2bdcc
--- /dev/null
+++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
@@ -0,0 +1,588 @@
+/*
+ * linux/drivers/video/mmp/hw/mmp_ctrl.c
+ * Marvell MMP series Display Controller support
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Authors:  Guoqing Li <ligq@marvell.com>
+ *          Lisa Du <cldu@marvell.com>
+ *          Zhou Zhu <zzhu3@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
+#include <linux/kthread.h>
+#include <linux/io.h>
+
+#include "mmp_ctrl.h"
+
+static irqreturn_t ctrl_handle_irq(int irq, void *dev_id)
+{
+	struct mmphw_ctrl *ctrl = (struct mmphw_ctrl *)dev_id;
+	u32 isr, imask, tmp;
+
+	isr = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR);
+	imask = readl_relaxed(ctrl->reg_base + SPU_IRQ_ENA);
+
+	do {
+		/* clear clock only */
+		tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR);
+		if (tmp & isr)
+			writel_relaxed(~isr, ctrl->reg_base + SPU_IRQ_ISR);
+	} while ((isr = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR)) & imask);
+
+	return IRQ_HANDLED;
+}
+
+static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt)
+{
+	u32 rbswap = 0, uvswap = 0, yuvswap = 0,
+		csc_en = 0, val = 0,
+		vid = overlay_is_vid(overlay);
+
+	switch (pix_fmt) {
+	case PIXFMT_RGB565:
+	case PIXFMT_RGB1555:
+	case PIXFMT_RGB888PACK:
+	case PIXFMT_RGB888UNPACK:
+	case PIXFMT_RGBA888:
+		rbswap = 1;
+		break;
+	case PIXFMT_VYUY:
+	case PIXFMT_YVU422P:
+	case PIXFMT_YVU420P:
+		uvswap = 1;
+		break;
+	case PIXFMT_YUYV:
+		yuvswap = 1;
+		break;
+	default:
+		break;
+	}
+
+	switch (pix_fmt) {
+	case PIXFMT_RGB565:
+	case PIXFMT_BGR565:
+		break;
+	case PIXFMT_RGB1555:
+	case PIXFMT_BGR1555:
+		val = 0x1;
+		break;
+	case PIXFMT_RGB888PACK:
+	case PIXFMT_BGR888PACK:
+		val = 0x2;
+		break;
+	case PIXFMT_RGB888UNPACK:
+	case PIXFMT_BGR888UNPACK:
+		val = 0x3;
+		break;
+	case PIXFMT_RGBA888:
+	case PIXFMT_BGRA888:
+		val = 0x4;
+		break;
+	case PIXFMT_UYVY:
+	case PIXFMT_VYUY:
+	case PIXFMT_YUYV:
+		val = 0x5;
+		csc_en = 1;
+		break;
+	case PIXFMT_YUV422P:
+	case PIXFMT_YVU422P:
+		val = 0x6;
+		csc_en = 1;
+		break;
+	case PIXFMT_YUV420P:
+	case PIXFMT_YVU420P:
+		val = 0x7;
+		csc_en = 1;
+		break;
+	default:
+		break;
+	}
+
+	return (dma_palette(0) | dma_fmt(vid, val) |
+		dma_swaprb(vid, rbswap) | dma_swapuv(vid, uvswap) |
+		dma_swapyuv(vid, yuvswap) | dma_csc(vid, csc_en));
+}
+
+static void dmafetch_set_fmt(struct mmp_overlay *overlay)
+{
+	u32 tmp;
+	struct mmp_path *path = overlay->path;
+	tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
+	tmp &= ~dma_mask(overlay_is_vid(overlay));
+	tmp |= fmt_to_reg(overlay, overlay->win.pix_fmt);
+	writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
+}
+
+static void overlay_set_win(struct mmp_overlay *overlay, struct mmp_win *win)
+{
+	struct lcd_regs *regs = path_regs(overlay->path);
+
+	/* assert win supported */
+	memcpy(&overlay->win, win, sizeof(struct mmp_win));
+
+	mutex_lock(&overlay->access_ok);
+
+	if (overlay_is_vid(overlay)) {
+		writel_relaxed(win->pitch[0], &regs->v_pitch_yc);
+		writel_relaxed(win->pitch[2] << 16 |
+				win->pitch[1], &regs->v_pitch_uv);
+
+		writel_relaxed((win->ysrc << 16) | win->xsrc, &regs->v_size);
+		writel_relaxed((win->ydst << 16) | win->xdst, &regs->v_size_z);
+		writel_relaxed(win->ypos << 16 | win->xpos, &regs->v_start);
+	} else {
+		writel_relaxed(win->pitch[0], &regs->g_pitch);
+
+		writel_relaxed((win->ysrc << 16) | win->xsrc, &regs->g_size);
+		writel_relaxed((win->ydst << 16) | win->xdst, &regs->g_size_z);
+		writel_relaxed(win->ypos << 16 | win->xpos, &regs->g_start);
+	}
+
+	dmafetch_set_fmt(overlay);
+	mutex_unlock(&overlay->access_ok);
+}
+
+static void dmafetch_onoff(struct mmp_overlay *overlay, int on)
+{
+	u32 mask = overlay_is_vid(overlay) ? CFG_DMA_ENA_MASK :
+		   CFG_GRA_ENA_MASK;
+	u32 enable = overlay_is_vid(overlay) ? CFG_DMA_ENA(1) : CFG_GRA_ENA(1);
+	u32 tmp;
+	struct mmp_path *path = overlay->path;
+
+	mutex_lock(&overlay->access_ok);
+	tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
+	tmp &= ~mask;
+	tmp |= (on ? enable : 0);
+	writel(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
+	mutex_unlock(&overlay->access_ok);
+}
+
+static void path_enabledisable(struct mmp_path *path, int on)
+{
+	u32 tmp;
+	mutex_lock(&path->access_ok);
+	tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path));
+	if (on)
+		tmp &= ~SCLK_DISABLE;
+	else
+		tmp |= SCLK_DISABLE;
+	writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path));
+	mutex_unlock(&path->access_ok);
+}
+
+static void path_onoff(struct mmp_path *path, int on)
+{
+	if (path->status == on) {
+		dev_info(path->dev, "path %s is already %s\n",
+				path->name, stat_name(path->status));
+		return;
+	}
+
+	if (on) {
+		path_enabledisable(path, 1);
+
+		if (path->panel && path->panel->set_onoff)
+			path->panel->set_onoff(path->panel, 1);
+	} else {
+		if (path->panel && path->panel->set_onoff)
+			path->panel->set_onoff(path->panel, 0);
+
+		path_enabledisable(path, 0);
+	}
+	path->status = on;
+}
+
+static void overlay_set_onoff(struct mmp_overlay *overlay, int on)
+{
+	if (overlay->status == on) {
+		dev_info(overlay_to_ctrl(overlay)->dev, "overlay %s is already %s\n",
+			overlay->path->name, stat_name(overlay->status));
+		return;
+	}
+	overlay->status = on;
+	dmafetch_onoff(overlay, on);
+	if (overlay->path->ops.check_status(overlay->path)
+			!= overlay->path->status)
+		path_onoff(overlay->path, on);
+}
+
+static void overlay_set_fetch(struct mmp_overlay *overlay, int fetch_id)
+{
+	overlay->dmafetch_id = fetch_id;
+}
+
+static int overlay_set_addr(struct mmp_overlay *overlay, struct mmp_addr *addr)
+{
+	struct lcd_regs *regs = path_regs(overlay->path);
+
+	/* FIXME: assert addr supported */
+	memcpy(&overlay->addr, addr, sizeof(struct mmp_addr));
+
+	if (overlay_is_vid(overlay)) {
+		writel_relaxed(addr->phys[0], &regs->v_y0);
+		writel_relaxed(addr->phys[1], &regs->v_u0);
+		writel_relaxed(addr->phys[2], &regs->v_v0);
+	} else
+		writel_relaxed(addr->phys[0], &regs->g_0);
+
+	return overlay->addr.phys[0];
+}
+
+static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode)
+{
+	struct lcd_regs *regs = path_regs(path);
+	u32 total_x, total_y, vsync_ctrl, tmp, sclk_src, sclk_div,
+		link_config = path_to_path_plat(path)->link_config,
+		dsi_rbswap = path_to_path_plat(path)->link_config;
+
+	/* FIXME: assert videomode supported */
+	memcpy(&path->mode, mode, sizeof(struct mmp_mode));
+
+	mutex_lock(&path->access_ok);
+
+	/* polarity of timing signals */
+	tmp = readl_relaxed(ctrl_regs(path) + intf_ctrl(path->id)) & 0x1;
+	tmp |= mode->vsync_invert ? 0 : 0x8;
+	tmp |= mode->hsync_invert ? 0 : 0x4;
+	tmp |= link_config & CFG_DUMBMODE_MASK;
+	tmp |= CFG_DUMB_ENA(1);
+	writel_relaxed(tmp, ctrl_regs(path) + intf_ctrl(path->id));
+
+	/* interface rb_swap setting */
+	tmp = readl_relaxed(ctrl_regs(path) + intf_rbswap_ctrl(path->id)) &
+		(~(CFG_INTFRBSWAP_MASK));
+	tmp |= dsi_rbswap & CFG_INTFRBSWAP_MASK;
+	writel_relaxed(tmp, ctrl_regs(path) + intf_rbswap_ctrl(path->id));
+
+	writel_relaxed((mode->yres << 16) | mode->xres, &regs->screen_active);
+	writel_relaxed((mode->left_margin << 16) | mode->right_margin,
+		&regs->screen_h_porch);
+	writel_relaxed((mode->upper_margin << 16) | mode->lower_margin,
+		&regs->screen_v_porch);
+	total_x = mode->xres + mode->left_margin + mode->right_margin +
+		mode->hsync_len;
+	total_y = mode->yres + mode->upper_margin + mode->lower_margin +
+		mode->vsync_len;
+	writel_relaxed((total_y << 16) | total_x, &regs->screen_size);
+
+	/* vsync ctrl */
+	if (path->output_type == PATH_OUT_DSI)
+		vsync_ctrl = 0x01330133;
+	else
+		vsync_ctrl = ((mode->xres + mode->right_margin) << 16)
+					| (mode->xres + mode->right_margin);
+	writel_relaxed(vsync_ctrl, &regs->vsync_ctrl);
+
+	/* set pixclock div */
+	sclk_src = clk_get_rate(path_to_ctrl(path)->clk);
+	sclk_div = sclk_src / mode->pixclock_freq;
+	if (sclk_div * mode->pixclock_freq < sclk_src)
+		sclk_div++;
+
+	dev_info(path->dev, "%s sclk_src %d sclk_div 0x%x pclk %d\n",
+			__func__, sclk_src, sclk_div, mode->pixclock_freq);
+
+	tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path));
+	tmp &= ~CLK_INT_DIV_MASK;
+	tmp |= sclk_div;
+	writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path));
+
+	mutex_unlock(&path->access_ok);
+}
+
+static struct mmp_overlay_ops mmphw_overlay_ops = {
+	.set_fetch = overlay_set_fetch,
+	.set_onoff = overlay_set_onoff,
+	.set_win = overlay_set_win,
+	.set_addr = overlay_set_addr,
+};
+
+static void ctrl_set_default(struct mmphw_ctrl *ctrl)
+{
+	u32 tmp, irq_mask;
+
+	/*
+	 * LCD Global control(LCD_TOP_CTRL) should be configed before
+	 * any other LCD registers read/write, or there maybe issues.
+	 */
+	tmp = readl_relaxed(ctrl->reg_base + LCD_TOP_CTRL);
+	tmp |= 0xfff0;
+	writel_relaxed(tmp, ctrl->reg_base + LCD_TOP_CTRL);
+
+
+	/* disable all interrupts */
+	irq_mask = path_imasks(0) | err_imask(0) |
+		   path_imasks(1) | err_imask(1);
+	tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ENA);
+	tmp &= ~irq_mask;
+	tmp |= irq_mask;
+	writel_relaxed(tmp, ctrl->reg_base + SPU_IRQ_ENA);
+}
+
+static void path_set_default(struct mmp_path *path)
+{
+	struct lcd_regs *regs = path_regs(path);
+	u32 dma_ctrl1, mask, tmp, path_config;
+
+	path_config = path_to_path_plat(path)->path_config;
+
+	/* Configure IOPAD: should be parallel only */
+	if (PATH_OUT_PARALLEL == path->output_type) {
+		mask = CFG_IOPADMODE_MASK | CFG_BURST_MASK | CFG_BOUNDARY_MASK;
+		tmp = readl_relaxed(ctrl_regs(path) + SPU_IOPAD_CONTROL);
+		tmp &= ~mask;
+		tmp |= path_config;
+		writel_relaxed(tmp, ctrl_regs(path) + SPU_IOPAD_CONTROL);
+	}
+
+	/* Select path clock source */
+	tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path));
+	tmp &= ~SCLK_SRC_SEL_MASK;
+	tmp |= path_config;
+	writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path));
+
+	/*
+	 * Configure default bits: vsync triggers DMA,
+	 * power save enable, configure alpha registers to
+	 * display 100% graphics, and set pixel command.
+	 */
+	dma_ctrl1 = 0x2032ff81;
+
+	dma_ctrl1 |= CFG_VSYNC_INV_MASK;
+	writel_relaxed(dma_ctrl1, ctrl_regs(path) + dma_ctrl(1, path->id));
+
+	/* Configure default register values */
+	writel_relaxed(0x00000000, &regs->blank_color);
+	writel_relaxed(0x00000000, &regs->g_1);
+	writel_relaxed(0x00000000, &regs->g_start);
+
+	/*
+	 * 1.enable multiple burst request in DMA AXI
+	 * bus arbiter for faster read if not tv path;
+	 * 2.enable horizontal smooth filter;
+	 */
+	mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK | CFG_ARBFAST_ENA(1);
+	tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
+	tmp |= mask;
+	if (PATH_TV == path->id)
+		tmp &= ~CFG_ARBFAST_ENA(1);
+	writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
+}
+
+static int path_init(struct mmphw_path_plat *path_plat,
+		struct mmp_mach_path_config *config)
+{
+	struct mmphw_ctrl *ctrl = path_plat->ctrl;
+	struct mmp_path_info *path_info;
+	struct mmp_path *path = NULL;
+
+	dev_info(ctrl->dev, "%s: %s\n", __func__, config->name);
+
+	/* init driver data */
+	path_info = kzalloc(sizeof(struct mmp_path_info), GFP_KERNEL);
+	if (!path_info) {
+		dev_err(ctrl->dev, "%s: unable to alloc path_info for %s\n",
+				__func__, config->name);
+		return 0;
+	}
+	path_info->name = config->name;
+	path_info->id = path_plat->id;
+	path_info->dev = ctrl->dev;
+	path_info->overlay_num = config->overlay_num;
+	path_info->overlay_ops = &mmphw_overlay_ops;
+	path_info->set_mode = path_set_mode;
+	path_info->plat_data = path_plat;
+
+	/* create/register platform device */
+	path = mmp_register_path(path_info);
+	if (!path) {
+		kfree(path_info);
+		return 0;
+	}
+	path_plat->path = path;
+	path_plat->path_config = config->path_config;
+	path_plat->link_config = config->link_config;
+	path_plat->dsi_rbswap = config->dsi_rbswap;
+	path_set_default(path);
+
+	kfree(path_info);
+	return 1;
+}
+
+static void path_deinit(struct mmphw_path_plat *path_plat)
+{
+	if (!path_plat)
+		return;
+
+	if (path_plat->path)
+		mmp_unregister_path(path_plat->path);
+}
+
+static int mmphw_probe(struct platform_device *pdev)
+{
+	struct mmp_mach_plat_info *mi;
+	struct resource *res;
+	int ret, i, size, irq;
+	struct mmphw_path_plat *path_plat;
+	struct mmphw_ctrl *ctrl = NULL;
+
+	/* get resources from platform data */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "%s: no IO memory defined\n", __func__);
+		ret = -ENOENT;
+		goto failed;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "%s: no IRQ defined\n", __func__);
+		ret = -ENOENT;
+		goto failed;
+	}
+
+	/* get configs from platform data */
+	mi = pdev->dev.platform_data;
+	if (mi == NULL || !mi->path_num || !mi->paths) {
+		dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	/* allocate */
+	size = sizeof(struct mmphw_ctrl) + sizeof(struct mmphw_path_plat) *
+	       mi->path_num;
+	ctrl = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	if (!ctrl) {
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	ctrl->name = mi->name;
+	ctrl->path_num = mi->path_num;
+	ctrl->dev = &pdev->dev;
+	ctrl->irq = irq;
+	platform_set_drvdata(pdev, ctrl);
+	mutex_init(&ctrl->access_ok);
+
+	/* map registers.*/
+	if (!devm_request_mem_region(ctrl->dev, res->start,
+			resource_size(res), ctrl->name)) {
+		dev_err(ctrl->dev,
+			"can't request region for resource %pR\n", res);
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	ctrl->reg_base = devm_ioremap_nocache(ctrl->dev,
+			res->start, resource_size(res));
+	if (ctrl->reg_base == NULL) {
+		dev_err(ctrl->dev, "%s: res %x - %x map failed\n", __func__,
+			res->start, res->end);
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	/* request irq */
+	ret = devm_request_irq(ctrl->dev, ctrl->irq, ctrl_handle_irq,
+		IRQF_SHARED, "lcd_controller", ctrl);
+	if (ret < 0) {
+		dev_err(ctrl->dev, "%s unable to request IRQ %d\n",
+				__func__, ctrl->irq);
+		ret = -ENXIO;
+		goto failed;
+	}
+
+	/* get clock */
+	ctrl->clk = devm_clk_get(ctrl->dev, mi->clk_name);
+	if (IS_ERR(ctrl->clk)) {
+		dev_err(ctrl->dev, "unable to get clk %s\n", mi->clk_name);
+		ret = -ENOENT;
+		goto failed;
+	}
+	clk_prepare_enable(ctrl->clk);
+
+	/* init global regs */
+	ctrl_set_default(ctrl);
+
+	/* init pathes from machine info and register them */
+	for (i = 0; i < ctrl->path_num; i++) {
+		/* get from config and machine info */
+		path_plat = &ctrl->path_plats[i];
+		path_plat->id = i;
+		path_plat->ctrl = ctrl;
+
+		/* path init */
+		if (!path_init(path_plat, &mi->paths[i])) {
+			ret = -EINVAL;
+			goto failed_path_init;
+		}
+	}
+
+#ifdef CONFIG_MMP_DISP_SPI
+	ret = lcd_spi_register(ctrl);
+	if (ret < 0)
+		goto failed_path_init;
+#endif
+
+	dev_info(ctrl->dev, "device init done\n");
+
+	return 0;
+
+failed_path_init:
+	for (i = 0; i < ctrl->path_num; i++) {
+		path_plat = &ctrl->path_plats[i];
+		path_deinit(path_plat);
+	}
+
+	clk_disable_unprepare(ctrl->clk);
+failed:
+	dev_err(&pdev->dev, "device init failed\n");
+
+	return ret;
+}
+
+static struct platform_driver mmphw_driver = {
+	.driver		= {
+		.name	= "mmp-disp",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= mmphw_probe,
+};
+
+static int mmphw_init(void)
+{
+	return platform_driver_register(&mmphw_driver);
+}
+module_init(mmphw_init);
+
+MODULE_AUTHOR("Li Guoqing<ligq@marvell.com>");
+MODULE_DESCRIPTION("Framebuffer driver for mmp");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.h b/drivers/video/fbdev/mmp/hw/mmp_ctrl.h
new file mode 100644
index 000000000000..53301cfdb1ae
--- /dev/null
+++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.h
@@ -0,0 +1,1502 @@
+/*
+ * drivers/video/mmp/hw/mmp_ctrl.h
+ *
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Authors:  Guoqing Li <ligq@marvell.com>
+ *          Lisa Du <cldu@marvell.com>
+ *          Zhou Zhu <zzhu3@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _MMP_CTRL_H_
+#define _MMP_CTRL_H_
+
+#include <video/mmp_disp.h>
+
+/* ------------< LCD register >------------ */
+struct lcd_regs {
+/* TV patch register for MMP2 */
+/* 32 bit		TV Video Frame0 Y Starting Address */
+#define LCD_TVD_START_ADDR_Y0			(0x0000)
+/* 32 bit		TV Video Frame0 U Starting Address */
+#define LCD_TVD_START_ADDR_U0			(0x0004)
+/* 32 bit		TV Video Frame0 V Starting Address */
+#define LCD_TVD_START_ADDR_V0			(0x0008)
+/* 32 bit		TV Video Frame0 Command Starting Address */
+#define LCD_TVD_START_ADDR_C0			(0x000C)
+/* 32 bit		TV Video Frame1 Y Starting Address Register*/
+#define LCD_TVD_START_ADDR_Y1			(0x0010)
+/* 32 bit		TV Video Frame1 U Starting Address Register*/
+#define LCD_TVD_START_ADDR_U1			(0x0014)
+/* 32 bit		TV Video Frame1 V Starting Address Register*/
+#define LCD_TVD_START_ADDR_V1			(0x0018)
+/* 32 bit		TV Video Frame1 Command Starting Address Register*/
+#define LCD_TVD_START_ADDR_C1			(0x001C)
+/* 32 bit		TV Video Y andC Line Length(Pitch)Register*/
+#define LCD_TVD_PITCH_YC			(0x0020)
+/* 32 bit		TV Video U andV Line Length(Pitch)Register*/
+#define LCD_TVD_PITCH_UV			(0x0024)
+/* 32 bit	  TV Video Starting Point on Screen Register*/
+#define LCD_TVD_OVSA_HPXL_VLN			(0x0028)
+/* 32 bit		TV Video Source Size Register*/
+#define LCD_TVD_HPXL_VLN			(0x002C)
+/* 32 bit	  TV Video Destination Size (After Zooming)Register*/
+#define LCD_TVDZM_HPXL_VLN			(0x0030)
+	u32 v_y0;
+	u32 v_u0;
+	u32 v_v0;
+	u32 v_c0;
+	u32 v_y1;
+	u32 v_u1;
+	u32 v_v1;
+	u32 v_c1;
+	u32 v_pitch_yc;		/* Video Y and C Line Length (Pitch) */
+	u32 v_pitch_uv;		/* Video U and V Line Length (Pitch) */
+	u32 v_start;		/* Video Starting Point on Screen */
+	u32 v_size;			/* Video Source Size */
+	u32 v_size_z;		/* Video Destination Size (After Zooming) */
+
+/* 32 bit	   TV Graphic Frame 0 Starting Address Register*/
+#define LCD_TVG_START_ADDR0				(0x0034)
+/* 32 bit	  TV Graphic Frame 1 Starting Address Register*/
+#define LCD_TVG_START_ADDR1				(0x0038)
+/* 32 bit		TV Graphic Line Length(Pitch)Register*/
+#define LCD_TVG_PITCH					(0x003C)
+/* 32 bit		TV Graphic Starting Point on Screen Register*/
+#define LCD_TVG_OVSA_HPXL_VLN				(0x0040)
+/* 32 bit		TV Graphic Source Size Register*/
+#define LCD_TVG_HPXL_VLN				(0x0044)
+/* 32 bit		TV Graphic Destination size (after Zooming)Register*/
+#define LCD_TVGZM_HPXL_VLN				(0x0048)
+	u32 g_0;			/* Graphic Frame 0/1 Starting Address */
+	u32 g_1;
+	u32 g_pitch;		/* Graphic Line Length (Pitch) */
+	u32 g_start;		/* Graphic Starting Point on Screen */
+	u32 g_size;			/* Graphic Source Size */
+	u32 g_size_z;		/* Graphic Destination Size (After Zooming) */
+
+/* 32 bit	  TV Hardware Cursor Starting Point on screen Register*/
+#define LCD_TVC_OVSA_HPXL_VLN				(0x004C)
+/* 32 bit		TV Hardware Cursor Size Register */
+#define LCD_TVC_HPXL_VLN				(0x0050)
+	u32 hc_start;			/* Hardware Cursor */
+	u32 hc_size;			/* Hardware Cursor */
+
+/* 32 bit		TV Total Screen Size Register*/
+#define LCD_TV_V_H_TOTAL				(0x0054)
+/* 32 bit		TV Screen Active Size Register*/
+#define LCD_TV_V_H_ACTIVE				(0x0058)
+/* 32 bit		TV Screen Horizontal Porch Register*/
+#define LCD_TV_H_PORCH					(0x005C)
+/* 32 bit		TV Screen Vertical Porch Register*/
+#define LCD_TV_V_PORCH					(0x0060)
+	u32 screen_size;		/* Screen Total Size */
+	u32 screen_active;		/* Screen Active Size */
+	u32 screen_h_porch;		/* Screen Horizontal Porch */
+	u32 screen_v_porch;		/* Screen Vertical Porch */
+
+/* 32 bit		TV Screen Blank Color Register*/
+#define LCD_TV_BLANKCOLOR				(0x0064)
+/* 32 bit		TV Hardware Cursor Color1 Register*/
+#define LCD_TV_ALPHA_COLOR1				(0x0068)
+/* 32 bit		TV Hardware Cursor Color2 Register*/
+#define LCD_TV_ALPHA_COLOR2				(0x006C)
+	u32 blank_color;		/* Screen Blank Color */
+	u32 hc_Alpha_color1;	/* Hardware Cursor Color1 */
+	u32 hc_Alpha_color2;	/* Hardware Cursor Color2 */
+
+/* 32 bit		TV Video Y Color Key Control*/
+#define LCD_TV_COLORKEY_Y				(0x0070)
+/* 32 bit		TV Video U Color Key Control*/
+#define LCD_TV_COLORKEY_U				(0x0074)
+/* 32 bit		TV Video V Color Key Control*/
+#define LCD_TV_COLORKEY_V				(0x0078)
+	u32 v_colorkey_y;		/* Video Y Color Key Control */
+	u32 v_colorkey_u;		/* Video U Color Key Control */
+	u32 v_colorkey_v;		/* Video V Color Key Control */
+
+/* 32 bit		TV VSYNC PulsePixel Edge Control Register*/
+#define LCD_TV_SEPXLCNT					(0x007C)
+	u32 vsync_ctrl;			/* VSYNC PulsePixel Edge Control */
+};
+
+#define intf_ctrl(id)		((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \
+				LCD_DUMB2_CTRL) : LCD_SPU_DUMB_CTRL)
+#define dma_ctrl0(id)	   ((id) ? (((id) & 1) ? LCD_TV_CTRL0 : \
+				LCD_PN2_CTRL0) : LCD_SPU_DMA_CTRL0)
+#define dma_ctrl1(id)	   ((id) ? (((id) & 1) ? LCD_TV_CTRL1 : \
+				LCD_PN2_CTRL1) : LCD_SPU_DMA_CTRL1)
+#define dma_ctrl(ctrl1, id)	 (ctrl1 ? dma_ctrl1(id) : dma_ctrl0(id))
+
+/* 32 bit		TV Path DMA Control 0*/
+#define LCD_TV_CTRL0					(0x0080)
+/* 32 bit		TV Path DMA Control 1*/
+#define LCD_TV_CTRL1					(0x0084)
+/* 32 bit		TV Path Video Contrast*/
+#define LCD_TV_CONTRAST					(0x0088)
+/* 32 bit		TV Path Video Saturation*/
+#define LCD_TV_SATURATION				(0x008C)
+/* 32 bit		TV Path Video Hue Adjust*/
+#define LCD_TV_CBSH_HUE					(0x0090)
+/* 32 bit TV Path TVIF Control	Register */
+#define LCD_TVIF_CTRL					(0x0094)
+#define TV_VBLNK_VALID_EN				(1 << 12)
+
+/* 32 bit TV Path I/O Pad Control*/
+#define LCD_TVIOPAD_CTRL				(0x0098)
+/* 32 bit TV Path Cloc	Divider  */
+#define LCD_TCLK_DIV					(0x009C)
+
+#define LCD_SCLK(path) ((PATH_PN == path->id) ? LCD_CFG_SCLK_DIV :\
+	((PATH_TV == path->id) ? LCD_TCLK_DIV : LCD_PN2_SCLK_DIV))
+#define intf_rbswap_ctrl(id)	((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \
+				PN2_IOPAD_CONTROL) : LCD_TOP_CTRL)
+
+/* dither configure */
+#ifdef CONFIG_CPU_PXA988
+#define LCD_DITHER_CTRL				(0x01EC)
+#else
+#define LCD_DITHER_CTRL				(0x00A0)
+#endif
+
+#define DITHER_TBL_INDEX_SEL(s)		((s) << 16)
+#define DITHER_MODE2(m)				((m) << 12)
+#define DITHER_MODE2_SHIFT			(12)
+#define DITHER_4X8_EN2				(1 << 9)
+#define DITHER_4X8_EN2_SHIFT		(9)
+#define DITHER_EN2					(1 << 8)
+#define DITHER_MODE1(m)				((m) << 4)
+#define DITHER_MODE1_SHIFT			(4)
+#define DITHER_4X8_EN1				(1 << 1)
+#define DITHER_4X8_EN1_SHIFT		(1)
+#define DITHER_EN1					(1)
+
+/* dither table data was fixed by video bpp of input and output*/
+#ifdef CONFIG_CPU_PXA988
+#define DITHER_TB_4X4_INDEX0		(0x6e4ca280)
+#define DITHER_TB_4X4_INDEX1		(0x5d7f91b3)
+#define DITHER_TB_4X8_INDEX0		(0xb391a280)
+#define DITHER_TB_4X8_INDEX1		(0x7f5d6e4c)
+#define DITHER_TB_4X8_INDEX2		(0x80a291b3)
+#define DITHER_TB_4X8_INDEX3		(0x4c6e5d7f)
+#define LCD_DITHER_TBL_DATA		(0x01F0)
+#else
+#define DITHER_TB_4X4_INDEX0		(0x3b19f7d5)
+#define DITHER_TB_4X4_INDEX1		(0x082ac4e6)
+#define DITHER_TB_4X8_INDEX0		(0xf7d508e6)
+#define DITHER_TB_4X8_INDEX1		(0x3b194c2a)
+#define DITHER_TB_4X8_INDEX2		(0xc4e6d5f7)
+#define DITHER_TB_4X8_INDEX3		(0x082a193b)
+#define LCD_DITHER_TBL_DATA		(0x00A4)
+#endif
+
+/* Video Frame 0&1 start address registers */
+#define	LCD_SPU_DMA_START_ADDR_Y0	0x00C0
+#define	LCD_SPU_DMA_START_ADDR_U0	0x00C4
+#define	LCD_SPU_DMA_START_ADDR_V0	0x00C8
+#define LCD_CFG_DMA_START_ADDR_0	0x00CC /* Cmd address */
+#define	LCD_SPU_DMA_START_ADDR_Y1	0x00D0
+#define	LCD_SPU_DMA_START_ADDR_U1	0x00D4
+#define	LCD_SPU_DMA_START_ADDR_V1	0x00D8
+#define LCD_CFG_DMA_START_ADDR_1	0x00DC /* Cmd address */
+
+/* YC & UV Pitch */
+#define LCD_SPU_DMA_PITCH_YC		0x00E0
+#define	 SPU_DMA_PITCH_C(c)		((c)<<16)
+#define	 SPU_DMA_PITCH_Y(y)		(y)
+#define LCD_SPU_DMA_PITCH_UV		0x00E4
+#define	 SPU_DMA_PITCH_V(v)		((v)<<16)
+#define	 SPU_DMA_PITCH_U(u)		(u)
+
+/* Video Starting Point on Screen Register */
+#define LCD_SPUT_DMA_OVSA_HPXL_VLN		0x00E8
+#define	 CFG_DMA_OVSA_VLN(y)			((y)<<16) /* 0~0xfff */
+#define	 CFG_DMA_OVSA_HPXL(x)			(x)	 /* 0~0xfff */
+
+/* Video Size Register */
+#define LCD_SPU_DMA_HPXL_VLN			0x00EC
+#define	 CFG_DMA_VLN(y)				((y)<<16)
+#define	 CFG_DMA_HPXL(x)			(x)
+
+/* Video Size After zooming Register */
+#define LCD_SPU_DZM_HPXL_VLN			0x00F0
+#define	 CFG_DZM_VLN(y)				((y)<<16)
+#define	 CFG_DZM_HPXL(x)			(x)
+
+/* Graphic Frame 0&1 Starting Address Register */
+#define LCD_CFG_GRA_START_ADDR0			0x00F4
+#define LCD_CFG_GRA_START_ADDR1			0x00F8
+
+/* Graphic Frame Pitch */
+#define LCD_CFG_GRA_PITCH			0x00FC
+
+/* Graphic Starting Point on Screen Register */
+#define LCD_SPU_GRA_OVSA_HPXL_VLN		0x0100
+#define	 CFG_GRA_OVSA_VLN(y)			((y)<<16)
+#define	 CFG_GRA_OVSA_HPXL(x)			(x)
+
+/* Graphic Size Register */
+#define LCD_SPU_GRA_HPXL_VLN			0x0104
+#define	 CFG_GRA_VLN(y)				((y)<<16)
+#define	 CFG_GRA_HPXL(x)			(x)
+
+/* Graphic Size after Zooming Register */
+#define LCD_SPU_GZM_HPXL_VLN			0x0108
+#define	 CFG_GZM_VLN(y)				((y)<<16)
+#define	 CFG_GZM_HPXL(x)			(x)
+
+/* HW Cursor Starting Point on Screen Register */
+#define LCD_SPU_HWC_OVSA_HPXL_VLN		0x010C
+#define	 CFG_HWC_OVSA_VLN(y)			((y)<<16)
+#define	 CFG_HWC_OVSA_HPXL(x)			(x)
+
+/* HW Cursor Size */
+#define LCD_SPU_HWC_HPXL_VLN			0x0110
+#define	 CFG_HWC_VLN(y)				((y)<<16)
+#define	 CFG_HWC_HPXL(x)			(x)
+
+/* Total Screen Size Register */
+#define LCD_SPUT_V_H_TOTAL			0x0114
+#define	 CFG_V_TOTAL(y)				((y)<<16)
+#define	 CFG_H_TOTAL(x)				(x)
+
+/* Total Screen Active Size Register */
+#define LCD_SPU_V_H_ACTIVE			0x0118
+#define	 CFG_V_ACTIVE(y)			((y)<<16)
+#define	 CFG_H_ACTIVE(x)			(x)
+
+/* Screen H&V Porch Register */
+#define LCD_SPU_H_PORCH				0x011C
+#define	 CFG_H_BACK_PORCH(b)			((b)<<16)
+#define	 CFG_H_FRONT_PORCH(f)			(f)
+#define LCD_SPU_V_PORCH				0x0120
+#define	 CFG_V_BACK_PORCH(b)			((b)<<16)
+#define	 CFG_V_FRONT_PORCH(f)			(f)
+
+/* Screen Blank Color Register */
+#define LCD_SPU_BLANKCOLOR			0x0124
+#define  CFG_BLANKCOLOR_MASK			0x00FFFFFF
+#define  CFG_BLANKCOLOR_R_MASK			0x000000FF
+#define  CFG_BLANKCOLOR_G_MASK			0x0000FF00
+#define  CFG_BLANKCOLOR_B_MASK			0x00FF0000
+
+/* HW Cursor Color 1&2 Register */
+#define LCD_SPU_ALPHA_COLOR1			0x0128
+#define	 CFG_HWC_COLOR1				0x00FFFFFF
+#define	 CFG_HWC_COLOR1_R(red)			((red)<<16)
+#define	 CFG_HWC_COLOR1_G(green)		((green)<<8)
+#define	 CFG_HWC_COLOR1_B(blue)			(blue)
+#define	 CFG_HWC_COLOR1_R_MASK			0x000000FF
+#define	 CFG_HWC_COLOR1_G_MASK			0x0000FF00
+#define	 CFG_HWC_COLOR1_B_MASK			0x00FF0000
+#define LCD_SPU_ALPHA_COLOR2			0x012C
+#define	 CFG_HWC_COLOR2				0x00FFFFFF
+#define	 CFG_HWC_COLOR2_R_MASK			0x000000FF
+#define	 CFG_HWC_COLOR2_G_MASK			0x0000FF00
+#define	 CFG_HWC_COLOR2_B_MASK			0x00FF0000
+
+/* Video YUV Color Key Control */
+#define LCD_SPU_COLORKEY_Y			0x0130
+#define	 CFG_CKEY_Y2(y2)			((y2)<<24)
+#define	 CFG_CKEY_Y2_MASK			0xFF000000
+#define	 CFG_CKEY_Y1(y1)			((y1)<<16)
+#define	 CFG_CKEY_Y1_MASK			0x00FF0000
+#define	 CFG_CKEY_Y(y)				((y)<<8)
+#define	 CFG_CKEY_Y_MASK			0x0000FF00
+#define	 CFG_ALPHA_Y(y)				(y)
+#define	 CFG_ALPHA_Y_MASK			0x000000FF
+#define LCD_SPU_COLORKEY_U			0x0134
+#define	 CFG_CKEY_U2(u2)			((u2)<<24)
+#define	 CFG_CKEY_U2_MASK			0xFF000000
+#define	 CFG_CKEY_U1(u1)			((u1)<<16)
+#define	 CFG_CKEY_U1_MASK			0x00FF0000
+#define	 CFG_CKEY_U(u)				((u)<<8)
+#define	 CFG_CKEY_U_MASK			0x0000FF00
+#define	 CFG_ALPHA_U(u)				(u)
+#define	 CFG_ALPHA_U_MASK			0x000000FF
+#define LCD_SPU_COLORKEY_V			0x0138
+#define	 CFG_CKEY_V2(v2)			((v2)<<24)
+#define	 CFG_CKEY_V2_MASK			0xFF000000
+#define	 CFG_CKEY_V1(v1)			((v1)<<16)
+#define	 CFG_CKEY_V1_MASK			0x00FF0000
+#define	 CFG_CKEY_V(v)				((v)<<8)
+#define	 CFG_CKEY_V_MASK			0x0000FF00
+#define	 CFG_ALPHA_V(v)				(v)
+#define	 CFG_ALPHA_V_MASK			0x000000FF
+
+/* Graphics/Video DMA color key enable bits in LCD_TV_CTRL1 */
+#define	 CFG_CKEY_GRA				0x2
+#define	 CFG_CKEY_DMA				0x1
+
+/* Interlace mode enable bits in LCD_TV_CTRL1 */
+#define     CFG_TV_INTERLACE_EN                 (1 << 22)
+#define     CFG_TV_NIB                          (1 << 0)
+
+#define LCD_PN_SEPXLCNT				0x013c /* MMP2 */
+
+/* SPI Read Data Register */
+#define LCD_SPU_SPI_RXDATA			0x0140
+
+/* Smart Panel Read Data Register */
+#define LCD_SPU_ISA_RSDATA			0x0144
+#define	 ISA_RXDATA_16BIT_1_DATA_MASK		0x000000FF
+#define	 ISA_RXDATA_16BIT_2_DATA_MASK		0x0000FF00
+#define	 ISA_RXDATA_16BIT_3_DATA_MASK		0x00FF0000
+#define	 ISA_RXDATA_16BIT_4_DATA_MASK		0xFF000000
+#define	 ISA_RXDATA_32BIT_1_DATA_MASK		0x00FFFFFF
+
+#define LCD_SPU_DBG_ISA				(0x0148) /* TTC */
+#define LCD_SPU_DMAVLD_YC			(0x014C)
+#define LCD_SPU_DMAVLD_UV			(0x0150)
+#define LCD_SPU_DMAVLD_UVSPU_GRAVLD		(0x0154)
+
+#define LCD_READ_IOPAD				(0x0148) /* MMP2*/
+#define LCD_DMAVLD_YC				(0x014C)
+#define LCD_DMAVLD_UV				(0x0150)
+#define LCD_TVGGRAVLD_HLEN			(0x0154)
+
+/* HWC SRAM Read Data Register */
+#define LCD_SPU_HWC_RDDAT			0x0158
+
+/* Gamma Table SRAM Read Data Register */
+#define LCD_SPU_GAMMA_RDDAT			0x015c
+#define	 CFG_GAMMA_RDDAT_MASK			0x000000FF
+
+/* Palette Table SRAM Read Data Register */
+#define LCD_SPU_PALETTE_RDDAT			0x0160
+#define	 CFG_PALETTE_RDDAT_MASK			0x00FFFFFF
+
+#define LCD_SPU_DBG_DMATOP			(0x0164) /* TTC */
+#define LCD_SPU_DBG_GRATOP			(0x0168)
+#define LCD_SPU_DBG_TXCTRL			(0x016C)
+#define LCD_SPU_DBG_SLVTOP			(0x0170)
+#define LCD_SPU_DBG_MUXTOP			(0x0174)
+
+#define LCD_SLV_DBG				(0x0164) /* MMP2 */
+#define LCD_TVDVLD_YC				(0x0168)
+#define LCD_TVDVLD_UV				(0x016C)
+#define LCD_TVC_RDDAT				(0x0170)
+#define LCD_TV_GAMMA_RDDAT			(0x0174)
+
+/* I/O Pads Input Read Only Register */
+#define LCD_SPU_IOPAD_IN			0x0178
+#define	 CFG_IOPAD_IN_MASK			0x0FFFFFFF
+
+#define LCD_TV_PALETTE_RDDAT			(0x0178) /* MMP2 */
+
+/* Reserved Read Only Registers */
+#define LCD_CFG_RDREG5F				0x017C
+#define	 IRE_FRAME_CNT_MASK			0x000000C0
+#define	 IPE_FRAME_CNT_MASK			0x00000030
+#define	 GRA_FRAME_CNT_MASK			0x0000000C /* Graphic */
+#define	 DMA_FRAME_CNT_MASK			0x00000003 /* Video */
+
+#define LCD_FRAME_CNT				(0x017C) /* MMP2 */
+
+/* SPI Control Register. */
+#define LCD_SPU_SPI_CTRL			0x0180
+#define	 CFG_SCLKCNT(div)			((div)<<24) /* 0xFF~0x2 */
+#define	 CFG_SCLKCNT_MASK			0xFF000000
+#define	 CFG_RXBITS(rx)				(((rx) - 1)<<16) /* 0x1F~0x1 */
+#define	 CFG_RXBITS_MASK			0x00FF0000
+#define	 CFG_TXBITS(tx)				(((tx) - 1)<<8) /* 0x1F~0x1 */
+#define	 CFG_TXBITS_MASK			0x0000FF00
+#define	 CFG_CLKINV(clk)			((clk)<<7)
+#define	 CFG_CLKINV_MASK			0x00000080
+#define	 CFG_KEEPXFER(transfer)			((transfer)<<6)
+#define	 CFG_KEEPXFER_MASK			0x00000040
+#define	 CFG_RXBITSTO0(rx)			((rx)<<5)
+#define	 CFG_RXBITSTO0_MASK			0x00000020
+#define	 CFG_TXBITSTO0(tx)			((tx)<<4)
+#define	 CFG_TXBITSTO0_MASK			0x00000010
+#define	 CFG_SPI_ENA(spi)			((spi)<<3)
+#define	 CFG_SPI_ENA_MASK			0x00000008
+#define	 CFG_SPI_SEL(spi)			((spi)<<2)
+#define	 CFG_SPI_SEL_MASK			0x00000004
+#define	 CFG_SPI_3W4WB(wire)			((wire)<<1)
+#define	 CFG_SPI_3W4WB_MASK			0x00000002
+#define	 CFG_SPI_START(start)			(start)
+#define	 CFG_SPI_START_MASK			0x00000001
+
+/* SPI Tx Data Register */
+#define LCD_SPU_SPI_TXDATA			0x0184
+
+/*
+   1. Smart Pannel 8-bit Bus Control Register.
+   2. AHB Slave Path Data Port Register
+*/
+#define LCD_SPU_SMPN_CTRL			0x0188
+
+/* DMA Control 0 Register */
+#define LCD_SPU_DMA_CTRL0			0x0190
+#define	 CFG_NOBLENDING(nb)			((nb)<<31)
+#define	 CFG_NOBLENDING_MASK			0x80000000
+#define	 CFG_GAMMA_ENA(gn)			((gn)<<30)
+#define	 CFG_GAMMA_ENA_MASK			0x40000000
+#define	 CFG_CBSH_ENA(cn)			((cn)<<29)
+#define	 CFG_CBSH_ENA_MASK			0x20000000
+#define	 CFG_PALETTE_ENA(pn)			((pn)<<28)
+#define	 CFG_PALETTE_ENA_MASK			0x10000000
+#define	 CFG_ARBFAST_ENA(an)			((an)<<27)
+#define	 CFG_ARBFAST_ENA_MASK			0x08000000
+#define	 CFG_HWC_1BITMOD(mode)			((mode)<<26)
+#define	 CFG_HWC_1BITMOD_MASK			0x04000000
+#define	 CFG_HWC_1BITENA(mn)			((mn)<<25)
+#define	 CFG_HWC_1BITENA_MASK			0x02000000
+#define	 CFG_HWC_ENA(cn)			((cn)<<24)
+#define	 CFG_HWC_ENA_MASK			0x01000000
+#define	 CFG_DMAFORMAT(dmaformat)		((dmaformat)<<20)
+#define	 CFG_DMAFORMAT_MASK			0x00F00000
+#define	 CFG_GRAFORMAT(graformat)		((graformat)<<16)
+#define	 CFG_GRAFORMAT_MASK			0x000F0000
+/* for graphic part */
+#define	 CFG_GRA_FTOGGLE(toggle)		((toggle)<<15)
+#define	 CFG_GRA_FTOGGLE_MASK			0x00008000
+#define	 CFG_GRA_HSMOOTH(smooth)		((smooth)<<14)
+#define	 CFG_GRA_HSMOOTH_MASK			0x00004000
+#define	 CFG_GRA_TSTMODE(test)			((test)<<13)
+#define	 CFG_GRA_TSTMODE_MASK			0x00002000
+#define	 CFG_GRA_SWAPRB(swap)			((swap)<<12)
+#define	 CFG_GRA_SWAPRB_MASK			0x00001000
+#define	 CFG_GRA_SWAPUV(swap)			((swap)<<11)
+#define	 CFG_GRA_SWAPUV_MASK			0x00000800
+#define	 CFG_GRA_SWAPYU(swap)			((swap)<<10)
+#define	 CFG_GRA_SWAPYU_MASK			0x00000400
+#define	 CFG_GRA_SWAP_MASK			0x00001C00
+#define	 CFG_YUV2RGB_GRA(cvrt)			((cvrt)<<9)
+#define	 CFG_YUV2RGB_GRA_MASK			0x00000200
+#define	 CFG_GRA_ENA(gra)			((gra)<<8)
+#define	 CFG_GRA_ENA_MASK			0x00000100
+#define dma0_gfx_masks	(CFG_GRAFORMAT_MASK | CFG_GRA_FTOGGLE_MASK | \
+	CFG_GRA_HSMOOTH_MASK | CFG_GRA_TSTMODE_MASK | CFG_GRA_SWAP_MASK | \
+	CFG_YUV2RGB_GRA_MASK | CFG_GRA_ENA_MASK)
+/* for video part */
+#define	 CFG_DMA_FTOGGLE(toggle)		((toggle)<<7)
+#define	 CFG_DMA_FTOGGLE_MASK			0x00000080
+#define	 CFG_DMA_HSMOOTH(smooth)		((smooth)<<6)
+#define	 CFG_DMA_HSMOOTH_MASK			0x00000040
+#define	 CFG_DMA_TSTMODE(test)			((test)<<5)
+#define	 CFG_DMA_TSTMODE_MASK			0x00000020
+#define	 CFG_DMA_SWAPRB(swap)			((swap)<<4)
+#define	 CFG_DMA_SWAPRB_MASK			0x00000010
+#define	 CFG_DMA_SWAPUV(swap)			((swap)<<3)
+#define	 CFG_DMA_SWAPUV_MASK			0x00000008
+#define	 CFG_DMA_SWAPYU(swap)			((swap)<<2)
+#define	 CFG_DMA_SWAPYU_MASK			0x00000004
+#define	 CFG_DMA_SWAP_MASK			0x0000001C
+#define	 CFG_YUV2RGB_DMA(cvrt)			((cvrt)<<1)
+#define	 CFG_YUV2RGB_DMA_MASK			0x00000002
+#define	 CFG_DMA_ENA(video)			(video)
+#define	 CFG_DMA_ENA_MASK			0x00000001
+#define dma0_vid_masks	(CFG_DMAFORMAT_MASK | CFG_DMA_FTOGGLE_MASK | \
+	CFG_DMA_HSMOOTH_MASK | CFG_DMA_TSTMODE_MASK | CFG_DMA_SWAP_MASK | \
+	CFG_YUV2RGB_DMA_MASK | CFG_DMA_ENA_MASK)
+#define dma_palette(val)		((val ? 1 : 0) << 28)
+#define dma_fmt(vid, val)		((val & 0xf) << ((vid) ? 20 : 16))
+#define dma_swaprb(vid, val)		((val ? 1 : 0) << ((vid) ? 4 : 12))
+#define dma_swapuv(vid, val)		((val ? 1 : 0) << ((vid) ? 3 : 11))
+#define dma_swapyuv(vid, val)		((val ? 1 : 0) << ((vid) ? 2 : 10))
+#define dma_csc(vid, val)		((val ? 1 : 0) << ((vid) ? 1 : 9))
+#define dma_hsmooth(vid, val)		((val ? 1 : 0) << ((vid) ? 6 : 14))
+#define dma_mask(vid)	(dma_palette(1) | dma_fmt(vid, 0xf) | dma_csc(vid, 1) \
+	| dma_swaprb(vid, 1) | dma_swapuv(vid, 1) | dma_swapyuv(vid, 1))
+
+/* DMA Control 1 Register */
+#define LCD_SPU_DMA_CTRL1			0x0194
+#define	 CFG_FRAME_TRIG(trig)			((trig)<<31)
+#define	 CFG_FRAME_TRIG_MASK			0x80000000
+#define	 CFG_VSYNC_TRIG(trig)			((trig)<<28)
+#define	 CFG_VSYNC_TRIG_MASK			0x70000000
+#define	 CFG_VSYNC_INV(inv)			((inv)<<27)
+#define	 CFG_VSYNC_INV_MASK			0x08000000
+#define	 CFG_COLOR_KEY_MODE(cmode)		((cmode)<<24)
+#define	 CFG_COLOR_KEY_MASK			0x07000000
+#define	 CFG_CARRY(carry)			((carry)<<23)
+#define	 CFG_CARRY_MASK				0x00800000
+#define	 CFG_LNBUF_ENA(lnbuf)			((lnbuf)<<22)
+#define	 CFG_LNBUF_ENA_MASK			0x00400000
+#define	 CFG_GATED_ENA(gated)			((gated)<<21)
+#define	 CFG_GATED_ENA_MASK			0x00200000
+#define	 CFG_PWRDN_ENA(power)			((power)<<20)
+#define	 CFG_PWRDN_ENA_MASK			0x00100000
+#define	 CFG_DSCALE(dscale)			((dscale)<<18)
+#define	 CFG_DSCALE_MASK			0x000C0000
+#define	 CFG_ALPHA_MODE(amode)			((amode)<<16)
+#define	 CFG_ALPHA_MODE_MASK			0x00030000
+#define	 CFG_ALPHA(alpha)			((alpha)<<8)
+#define	 CFG_ALPHA_MASK				0x0000FF00
+#define	 CFG_PXLCMD(pxlcmd)			(pxlcmd)
+#define	 CFG_PXLCMD_MASK			0x000000FF
+
+/* SRAM Control Register */
+#define LCD_SPU_SRAM_CTRL			0x0198
+#define	 CFG_SRAM_INIT_WR_RD(mode)		((mode)<<14)
+#define	 CFG_SRAM_INIT_WR_RD_MASK		0x0000C000
+#define	 CFG_SRAM_ADDR_LCDID(id)		((id)<<8)
+#define	 CFG_SRAM_ADDR_LCDID_MASK		0x00000F00
+#define	 CFG_SRAM_ADDR(addr)			(addr)
+#define	 CFG_SRAM_ADDR_MASK			0x000000FF
+
+/* SRAM Write Data Register */
+#define LCD_SPU_SRAM_WRDAT			0x019C
+
+/* SRAM RTC/WTC Control Register */
+#define LCD_SPU_SRAM_PARA0			0x01A0
+
+/* SRAM Power Down Control Register */
+#define LCD_SPU_SRAM_PARA1			0x01A4
+#define	 CFG_CSB_256x32(hwc)			((hwc)<<15)	/* HWC */
+#define	 CFG_CSB_256x32_MASK			0x00008000
+#define	 CFG_CSB_256x24(palette)		((palette)<<14)	/* Palette */
+#define	 CFG_CSB_256x24_MASK			0x00004000
+#define	 CFG_CSB_256x8(gamma)			((gamma)<<13)	/* Gamma */
+#define	 CFG_CSB_256x8_MASK			0x00002000
+#define	 CFG_PDWN256x32(pdwn)			((pdwn)<<7)	/* HWC */
+#define	 CFG_PDWN256x32_MASK			0x00000080
+#define	 CFG_PDWN256x24(pdwn)			((pdwn)<<6)	/* Palette */
+#define	 CFG_PDWN256x24_MASK			0x00000040
+#define	 CFG_PDWN256x8(pdwn)			((pdwn)<<5)	/* Gamma */
+#define	 CFG_PDWN256x8_MASK			0x00000020
+#define	 CFG_PDWN32x32(pdwn)			((pdwn)<<3)
+#define	 CFG_PDWN32x32_MASK			0x00000008
+#define	 CFG_PDWN16x66(pdwn)			((pdwn)<<2)
+#define	 CFG_PDWN16x66_MASK			0x00000004
+#define	 CFG_PDWN32x66(pdwn)			((pdwn)<<1)
+#define	 CFG_PDWN32x66_MASK			0x00000002
+#define	 CFG_PDWN64x66(pdwn)			(pdwn)
+#define	 CFG_PDWN64x66_MASK			0x00000001
+
+/* Smart or Dumb Panel Clock Divider */
+#define LCD_CFG_SCLK_DIV			0x01A8
+#define	 SCLK_SRC_SEL(src)		((src)<<31)
+#define	 SCLK_SRC_SEL_MASK		0x80000000
+#define  SCLK_DISABLE				(1<<28)
+#define	 CLK_FRACDIV(frac)			((frac)<<16)
+#define	 CLK_FRACDIV_MASK			0x0FFF0000
+#define	 DSI1_BITCLK_DIV(div)			(div<<8)
+#define	 DSI1_BITCLK_DIV_MASK			0x00000F00
+#define	 CLK_INT_DIV(div)			(div)
+#define	 CLK_INT_DIV_MASK			0x000000FF
+
+/* Video Contrast Register */
+#define LCD_SPU_CONTRAST			0x01AC
+#define	 CFG_BRIGHTNESS(bright)			((bright)<<16)
+#define	 CFG_BRIGHTNESS_MASK			0xFFFF0000
+#define	 CFG_CONTRAST(contrast)			(contrast)
+#define	 CFG_CONTRAST_MASK			0x0000FFFF
+
+/* Video Saturation Register */
+#define LCD_SPU_SATURATION			0x01B0
+#define	 CFG_C_MULTS(mult)			((mult)<<16)
+#define	 CFG_C_MULTS_MASK			0xFFFF0000
+#define	 CFG_SATURATION(sat)			(sat)
+#define	 CFG_SATURATION_MASK			0x0000FFFF
+
+/* Video Hue Adjust Register */
+#define LCD_SPU_CBSH_HUE			0x01B4
+#define	 CFG_SIN0(sin0)				((sin0)<<16)
+#define	 CFG_SIN0_MASK				0xFFFF0000
+#define	 CFG_COS0(con0)				(con0)
+#define	 CFG_COS0_MASK				0x0000FFFF
+
+/* Dump LCD Panel Control Register */
+#define LCD_SPU_DUMB_CTRL			0x01B8
+#define	 CFG_DUMBMODE(mode)			((mode)<<28)
+#define	 CFG_DUMBMODE_MASK			0xF0000000
+#define	 CFG_INTFRBSWAP(mode)			((mode)<<24)
+#define	 CFG_INTFRBSWAP_MASK			0x0F000000
+#define	 CFG_LCDGPIO_O(data)			((data)<<20)
+#define	 CFG_LCDGPIO_O_MASK			0x0FF00000
+#define	 CFG_LCDGPIO_ENA(gpio)			((gpio)<<12)
+#define	 CFG_LCDGPIO_ENA_MASK			0x000FF000
+#define	 CFG_BIAS_OUT(bias)			((bias)<<8)
+#define	 CFG_BIAS_OUT_MASK			0x00000100
+#define	 CFG_REVERSE_RGB(RGB)			((RGB)<<7)
+#define	 CFG_REVERSE_RGB_MASK			0x00000080
+#define	 CFG_INV_COMPBLANK(blank)		((blank)<<6)
+#define	 CFG_INV_COMPBLANK_MASK			0x00000040
+#define	 CFG_INV_COMPSYNC(sync)			((sync)<<5)
+#define	 CFG_INV_COMPSYNC_MASK			0x00000020
+#define	 CFG_INV_HENA(hena)			((hena)<<4)
+#define	 CFG_INV_HENA_MASK			0x00000010
+#define	 CFG_INV_VSYNC(vsync)			((vsync)<<3)
+#define	 CFG_INV_VSYNC_MASK			0x00000008
+#define	 CFG_INV_HSYNC(hsync)			((hsync)<<2)
+#define	 CFG_INV_HSYNC_MASK			0x00000004
+#define	 CFG_INV_PCLK(pclk)			((pclk)<<1)
+#define	 CFG_INV_PCLK_MASK			0x00000002
+#define	 CFG_DUMB_ENA(dumb)			(dumb)
+#define	 CFG_DUMB_ENA_MASK			0x00000001
+
+/* LCD I/O Pads Control Register */
+#define SPU_IOPAD_CONTROL			0x01BC
+#define	 CFG_GRA_VM_ENA(vm)			((vm)<<15)
+#define	 CFG_GRA_VM_ENA_MASK			0x00008000
+#define	 CFG_DMA_VM_ENA(vm)			((vm)<<13)
+#define	 CFG_DMA_VM_ENA_MASK			0x00002000
+#define	 CFG_CMD_VM_ENA(vm)			((vm)<<12)
+#define	 CFG_CMD_VM_ENA_MASK			0x00001000
+#define	 CFG_CSC(csc)				((csc)<<8)
+#define	 CFG_CSC_MASK				0x00000300
+#define	 CFG_BOUNDARY(size)			((size)<<5)
+#define	 CFG_BOUNDARY_MASK			0x00000020
+#define	 CFG_BURST(len)				((len)<<4)
+#define	 CFG_BURST_MASK				0x00000010
+#define	 CFG_IOPADMODE(iopad)			(iopad)
+#define	 CFG_IOPADMODE_MASK			0x0000000F
+
+/* LCD Interrupt Control Register */
+#define SPU_IRQ_ENA				0x01C0
+#define	 DMA_FRAME_IRQ0_ENA(irq)		((irq)<<31)
+#define	 DMA_FRAME_IRQ0_ENA_MASK		0x80000000
+#define	 DMA_FRAME_IRQ1_ENA(irq)		((irq)<<30)
+#define	 DMA_FRAME_IRQ1_ENA_MASK		0x40000000
+#define	 DMA_FF_UNDERFLOW_ENA(ff)		((ff)<<29)
+#define	 DMA_FF_UNDERFLOW_ENA_MASK		0x20000000
+#define	 AXI_BUS_ERROR_IRQ_ENA(irq)		((irq)<<28)
+#define	 AXI_BUS_ERROR_IRQ_ENA_MASK		0x10000000
+#define	 GRA_FRAME_IRQ0_ENA(irq)		((irq)<<27)
+#define	 GRA_FRAME_IRQ0_ENA_MASK		0x08000000
+#define	 GRA_FRAME_IRQ1_ENA(irq)		((irq)<<26)
+#define	 GRA_FRAME_IRQ1_ENA_MASK		0x04000000
+#define	 GRA_FF_UNDERFLOW_ENA(ff)		((ff)<<25)
+#define	 GRA_FF_UNDERFLOW_ENA_MASK		0x02000000
+#define	 VSYNC_IRQ_ENA(vsync_irq)		((vsync_irq)<<23)
+#define	 VSYNC_IRQ_ENA_MASK			0x00800000
+#define	 DUMB_FRAMEDONE_ENA(fdone)		((fdone)<<22)
+#define	 DUMB_FRAMEDONE_ENA_MASK		0x00400000
+#define	 TWC_FRAMEDONE_ENA(fdone)		((fdone)<<21)
+#define	 TWC_FRAMEDONE_ENA_MASK			0x00200000
+#define	 HWC_FRAMEDONE_ENA(fdone)		((fdone)<<20)
+#define	 HWC_FRAMEDONE_ENA_MASK			0x00100000
+#define	 SLV_IRQ_ENA(irq)			((irq)<<19)
+#define	 SLV_IRQ_ENA_MASK			0x00080000
+#define	 SPI_IRQ_ENA(irq)			((irq)<<18)
+#define	 SPI_IRQ_ENA_MASK			0x00040000
+#define	 PWRDN_IRQ_ENA(irq)			((irq)<<17)
+#define	 PWRDN_IRQ_ENA_MASK			0x00020000
+#define	 AXI_LATENCY_TOO_LONG_IRQ_ENA(irq)	((irq)<<16)
+#define  AXI_LATENCY_TOO_LONG_IRQ_ENA_MASK	0x00010000
+#define	 CLEAN_SPU_IRQ_ISR(irq)			(irq)
+#define	 CLEAN_SPU_IRQ_ISR_MASK			0x0000FFFF
+#define	 TV_DMA_FRAME_IRQ0_ENA(irq)		((irq)<<15)
+#define	 TV_DMA_FRAME_IRQ0_ENA_MASK		0x00008000
+#define	 TV_DMA_FRAME_IRQ1_ENA(irq)		((irq)<<14)
+#define	 TV_DMA_FRAME_IRQ1_ENA_MASK		0x00004000
+#define	 TV_DMA_FF_UNDERFLOW_ENA(unerrun)	((unerrun)<<13)
+#define	 TV_DMA_FF_UNDERFLOW_ENA_MASK		0x00002000
+#define	 TVSYNC_IRQ_ENA(irq)			((irq)<<12)
+#define	 TVSYNC_IRQ_ENA_MASK			0x00001000
+#define	 TV_FRAME_IRQ0_ENA(irq)			((irq)<<11)
+#define	 TV_FRAME_IRQ0_ENA_MASK			0x00000800
+#define	 TV_FRAME_IRQ1_ENA(irq)			((irq)<<10)
+#define	 TV_FRAME_IRQ1_ENA_MASK			0x00000400
+#define	 TV_GRA_FF_UNDERFLOW_ENA(unerrun)	((unerrun)<<9)
+#define	 TV_GRA_FF_UNDERFLOW_ENA_MASK		0x00000200
+#define	 TV_FRAMEDONE_ENA(irq)			((irq)<<8)
+#define	 TV_FRAMEDONE_ENA_MASK			0x00000100
+
+/* FIXME - JUST GUESS */
+#define	 PN2_DMA_FRAME_IRQ0_ENA(irq)		((irq)<<7)
+#define	 PN2_DMA_FRAME_IRQ0_ENA_MASK		0x00000080
+#define	 PN2_DMA_FRAME_IRQ1_ENA(irq)		((irq)<<6)
+#define	 PN2_DMA_FRAME_IRQ1_ENA_MASK		0x00000040
+#define	 PN2_DMA_FF_UNDERFLOW_ENA(ff)		((ff)<<5)
+#define	 PN2_DMA_FF_UNDERFLOW_ENA_MASK		0x00000020
+#define	 PN2_GRA_FRAME_IRQ0_ENA(irq)		((irq)<<3)
+#define	 PN2_GRA_FRAME_IRQ0_ENA_MASK		0x00000008
+#define	 PN2_GRA_FRAME_IRQ1_ENA(irq)		((irq)<<2)
+#define	 PN2_GRA_FRAME_IRQ1_ENA_MASK		0x04000004
+#define	 PN2_GRA_FF_UNDERFLOW_ENA(ff)		((ff)<<1)
+#define	 PN2_GRA_FF_UNDERFLOW_ENA_MASK		0x00000002
+#define	 PN2_VSYNC_IRQ_ENA(irq)			((irq)<<0)
+#define	 PN2_SYNC_IRQ_ENA_MASK			0x00000001
+
+#define gf0_imask(id)	((id) ? (((id) & 1) ? TV_FRAME_IRQ0_ENA_MASK \
+		: PN2_GRA_FRAME_IRQ0_ENA_MASK) : GRA_FRAME_IRQ0_ENA_MASK)
+#define gf1_imask(id)	((id) ? (((id) & 1) ? TV_FRAME_IRQ1_ENA_MASK \
+		: PN2_GRA_FRAME_IRQ1_ENA_MASK) : GRA_FRAME_IRQ1_ENA_MASK)
+#define vsync_imask(id)	((id) ? (((id) & 1) ? TVSYNC_IRQ_ENA_MASK \
+		: PN2_SYNC_IRQ_ENA_MASK) : VSYNC_IRQ_ENA_MASK)
+#define vsync_imasks	(vsync_imask(0) | vsync_imask(1))
+
+#define display_done_imask(id)	((id) ? (((id) & 1) ? TV_FRAMEDONE_ENA_MASK\
+	: (PN2_DMA_FRAME_IRQ0_ENA_MASK | PN2_DMA_FRAME_IRQ1_ENA_MASK))\
+	: DUMB_FRAMEDONE_ENA_MASK)
+
+#define display_done_imasks	(display_done_imask(0) | display_done_imask(1))
+
+#define vf0_imask(id)	((id) ? (((id) & 1) ? TV_DMA_FRAME_IRQ0_ENA_MASK \
+		: PN2_DMA_FRAME_IRQ0_ENA_MASK) : DMA_FRAME_IRQ0_ENA_MASK)
+#define vf1_imask(id)	((id) ? (((id) & 1) ? TV_DMA_FRAME_IRQ1_ENA_MASK \
+		: PN2_DMA_FRAME_IRQ1_ENA_MASK) : DMA_FRAME_IRQ1_ENA_MASK)
+
+#define gfx_imasks	(gf0_imask(0) | gf1_imask(0) | gf0_imask(1) | \
+		gf1_imask(1))
+#define vid_imasks	(vf0_imask(0) | vf1_imask(0) | vf0_imask(1) | \
+		vf1_imask(1))
+#define vid_imask(id)	(display_done_imask(id))
+
+#define pn1_imasks	(gf0_imask(0) | gf1_imask(0) | vsync_imask(0) | \
+		display_done_imask(0) | vf0_imask(0) | vf1_imask(0))
+#define tv_imasks	(gf0_imask(1) | gf1_imask(1) | vsync_imask(1) | \
+		display_done_imask(1) | vf0_imask(1) | vf1_imask(1))
+#define path_imasks(id)	((id) ? (tv_imasks) : (pn1_imasks))
+
+/* error indications */
+#define vid_udflow_imask(id)	((id) ? (((id) & 1) ? \
+	(TV_DMA_FF_UNDERFLOW_ENA_MASK) : (PN2_DMA_FF_UNDERFLOW_ENA_MASK)) : \
+	(DMA_FF_UNDERFLOW_ENA_MASK))
+#define gfx_udflow_imask(id)	((id) ? (((id) & 1) ? \
+	(TV_GRA_FF_UNDERFLOW_ENA_MASK) : (PN2_GRA_FF_UNDERFLOW_ENA_MASK)) : \
+	(GRA_FF_UNDERFLOW_ENA_MASK))
+
+#define err_imask(id) (vid_udflow_imask(id) | gfx_udflow_imask(id) | \
+	AXI_BUS_ERROR_IRQ_ENA_MASK | AXI_LATENCY_TOO_LONG_IRQ_ENA_MASK)
+#define err_imasks (err_imask(0) | err_imask(1) | err_imask(2))
+/* LCD Interrupt Status Register */
+#define SPU_IRQ_ISR			0x01C4
+#define	 DMA_FRAME_IRQ0(irq)		((irq)<<31)
+#define	 DMA_FRAME_IRQ0_MASK		0x80000000
+#define	 DMA_FRAME_IRQ1(irq)		((irq)<<30)
+#define	 DMA_FRAME_IRQ1_MASK		0x40000000
+#define	 DMA_FF_UNDERFLOW(ff)		((ff)<<29)
+#define	 DMA_FF_UNDERFLOW_MASK		0x20000000
+#define	 AXI_BUS_ERROR_IRQ(irq)		((irq)<<28)
+#define	 AXI_BUS_ERROR_IRQ_MASK		0x10000000
+#define	 GRA_FRAME_IRQ0(irq)		((irq)<<27)
+#define	 GRA_FRAME_IRQ0_MASK		0x08000000
+#define	 GRA_FRAME_IRQ1(irq)		((irq)<<26)
+#define	 GRA_FRAME_IRQ1_MASK		0x04000000
+#define	 GRA_FF_UNDERFLOW(ff)		((ff)<<25)
+#define	 GRA_FF_UNDERFLOW_MASK		0x02000000
+#define	 VSYNC_IRQ(vsync_irq)		((vsync_irq)<<23)
+#define	 VSYNC_IRQ_MASK			0x00800000
+#define	 DUMB_FRAMEDONE(fdone)		((fdone)<<22)
+#define	 DUMB_FRAMEDONE_MASK		0x00400000
+#define	 TWC_FRAMEDONE(fdone)		((fdone)<<21)
+#define	 TWC_FRAMEDONE_MASK		0x00200000
+#define	 HWC_FRAMEDONE(fdone)		((fdone)<<20)
+#define	 HWC_FRAMEDONE_MASK		0x00100000
+#define	 SLV_IRQ(irq)			((irq)<<19)
+#define	 SLV_IRQ_MASK			0x00080000
+#define	 SPI_IRQ(irq)			((irq)<<18)
+#define	 SPI_IRQ_MASK			0x00040000
+#define	 PWRDN_IRQ(irq)			((irq)<<17)
+#define	 PWRDN_IRQ_MASK			0x00020000
+#define	 AXI_LATENCY_TOO_LONGR_IRQ(irq)	((irq)<<16)
+#define	 AXI_LATENCY_TOO_LONGR_IRQ_MASK	0x00010000
+#define	 TV_DMA_FRAME_IRQ0(irq)		((irq)<<15)
+#define	 TV_DMA_FRAME_IRQ0_MASK		0x00008000
+#define	 TV_DMA_FRAME_IRQ1(irq)		((irq)<<14)
+#define	 TV_DMA_FRAME_IRQ1_MASK		0x00004000
+#define	 TV_DMA_FF_UNDERFLOW(unerrun)	((unerrun)<<13)
+#define	 TV_DMA_FF_UNDERFLOW_MASK	0x00002000
+#define	 TVSYNC_IRQ(irq)		((irq)<<12)
+#define	 TVSYNC_IRQ_MASK		0x00001000
+#define	 TV_FRAME_IRQ0(irq)		((irq)<<11)
+#define	 TV_FRAME_IRQ0_MASK		0x00000800
+#define	 TV_FRAME_IRQ1(irq)		((irq)<<10)
+#define	 TV_FRAME_IRQ1_MASK		0x00000400
+#define	 TV_GRA_FF_UNDERFLOW(unerrun)	((unerrun)<<9)
+#define	 TV_GRA_FF_UNDERFLOW_MASK	0x00000200
+#define	 PN2_DMA_FRAME_IRQ0(irq)	((irq)<<7)
+#define	 PN2_DMA_FRAME_IRQ0_MASK	0x00000080
+#define	 PN2_DMA_FRAME_IRQ1(irq)	((irq)<<6)
+#define	 PN2_DMA_FRAME_IRQ1_MASK	0x00000040
+#define	 PN2_DMA_FF_UNDERFLOW(ff)	((ff)<<5)
+#define	 PN2_DMA_FF_UNDERFLOW_MASK	0x00000020
+#define	 PN2_GRA_FRAME_IRQ0(irq)	((irq)<<3)
+#define	 PN2_GRA_FRAME_IRQ0_MASK	0x00000008
+#define	 PN2_GRA_FRAME_IRQ1(irq)	((irq)<<2)
+#define	 PN2_GRA_FRAME_IRQ1_MASK	0x04000004
+#define	 PN2_GRA_FF_UNDERFLOW(ff)	((ff)<<1)
+#define	 PN2_GRA_FF_UNDERFLOW_MASK	0x00000002
+#define	 PN2_VSYNC_IRQ(irq)		((irq)<<0)
+#define	 PN2_SYNC_IRQ_MASK		0x00000001
+
+/* LCD FIFO Depth register */
+#define LCD_FIFO_DEPTH			0x01c8
+#define	 VIDEO_FIFO(fi)			((fi) << 0)
+#define	 VIDEO_FIFO_MASK		0x00000003
+#define	 GRAPHIC_FIFO(fi)		((fi) << 2)
+#define	 GRAPHIC_FIFO_MASK		0x0000000c
+
+/* read-only */
+#define	 DMA_FRAME_IRQ0_LEVEL_MASK		0x00008000
+#define	 DMA_FRAME_IRQ1_LEVEL_MASK		0x00004000
+#define	 DMA_FRAME_CNT_ISR_MASK			0x00003000
+#define	 GRA_FRAME_IRQ0_LEVEL_MASK		0x00000800
+#define	 GRA_FRAME_IRQ1_LEVEL_MASK		0x00000400
+#define	 GRA_FRAME_CNT_ISR_MASK			0x00000300
+#define	 VSYNC_IRQ_LEVEL_MASK			0x00000080
+#define	 DUMB_FRAMEDONE_LEVEL_MASK		0x00000040
+#define	 TWC_FRAMEDONE_LEVEL_MASK		0x00000020
+#define	 HWC_FRAMEDONE_LEVEL_MASK		0x00000010
+#define	 SLV_FF_EMPTY_MASK			0x00000008
+#define	 DMA_FF_ALLEMPTY_MASK			0x00000004
+#define	 GRA_FF_ALLEMPTY_MASK			0x00000002
+#define	 PWRDN_IRQ_LEVEL_MASK			0x00000001
+
+/* 32 bit LCD Interrupt Reset Status*/
+#define SPU_IRQ_RSR				(0x01C8)
+/* 32 bit Panel Path Graphic Partial Display Horizontal Control Register*/
+#define LCD_GRA_CUTHPXL				(0x01CC)
+/* 32 bit Panel Path Graphic Partial Display Vertical Control Register*/
+#define LCD_GRA_CUTVLN				(0x01D0)
+/* 32 bit TV Path Graphic Partial Display	  Horizontal Control Register*/
+#define LCD_TVG_CUTHPXL				(0x01D4)
+/* 32 bit TV Path Graphic Partial Display Vertical Control Register*/
+#define LCD_TVG_CUTVLN				(0x01D8)
+/* 32 bit LCD Global Control Register*/
+#define LCD_TOP_CTRL				(0x01DC)
+/* 32 bit LCD SQU Line Buffer Control Register 1*/
+#define LCD_SQULN1_CTRL				(0x01E0)
+/* 32 bit LCD SQU Line Buffer Control Register 2*/
+#define LCD_SQULN2_CTRL				(0x01E4)
+#define squln_ctrl(id)	((id) ? (((id) & 1) ? LCD_SQULN2_CTRL : \
+			LCD_PN2_SQULN1_CTRL) : LCD_SQULN1_CTRL)
+
+/* 32 bit LCD Mixed Overlay Control Register */
+#define LCD_AFA_ALL2ONE				(0x01E8)
+
+#define LCD_PN2_SCLK_DIV			(0x01EC)
+#define LCD_PN2_TCLK_DIV			(0x01F0)
+#define LCD_LVDS_SCLK_DIV_WR			(0x01F4)
+#define LCD_LVDS_SCLK_DIV_RD			(0x01FC)
+#define PN2_LCD_DMA_START_ADDR_Y0		(0x0200)
+#define PN2_LCD_DMA_START_ADDR_U0		(0x0204)
+#define PN2_LCD_DMA_START_ADDR_V0		(0x0208)
+#define PN2_LCD_DMA_START_ADDR_C0		(0x020C)
+#define PN2_LCD_DMA_START_ADDR_Y1		(0x0210)
+#define PN2_LCD_DMA_START_ADDR_U1		(0x0214)
+#define PN2_LCD_DMA_START_ADDR_V1		(0x0218)
+#define PN2_LCD_DMA_START_ADDR_C1		(0x021C)
+#define PN2_LCD_DMA_PITCH_YC			(0x0220)
+#define PN2_LCD_DMA_PITCH_UV			(0x0224)
+#define PN2_LCD_DMA_OVSA_HPXL_VLN		(0x0228)
+#define PN2_LCD_DMA_HPXL_VLN			(0x022C)
+#define PN2_LCD_DMAZM_HPXL_VLN			(0x0230)
+#define PN2_LCD_GRA_START_ADDR0			(0x0234)
+#define PN2_LCD_GRA_START_ADDR1			(0x0238)
+#define PN2_LCD_GRA_PITCH			(0x023C)
+#define PN2_LCD_GRA_OVSA_HPXL_VLN		(0x0240)
+#define PN2_LCD_GRA_HPXL_VLN			(0x0244)
+#define PN2_LCD_GRAZM_HPXL_VLN			(0x0248)
+#define PN2_LCD_HWC_OVSA_HPXL_VLN		(0x024C)
+#define PN2_LCD_HWC_HPXL_VLN			(0x0250)
+#define LCD_PN2_V_H_TOTAL			(0x0254)
+#define LCD_PN2_V_H_ACTIVE			(0x0258)
+#define LCD_PN2_H_PORCH				(0x025C)
+#define LCD_PN2_V_PORCH				(0x0260)
+#define LCD_PN2_BLANKCOLOR			(0x0264)
+#define LCD_PN2_ALPHA_COLOR1			(0x0268)
+#define LCD_PN2_ALPHA_COLOR2			(0x026C)
+#define LCD_PN2_COLORKEY_Y			(0x0270)
+#define LCD_PN2_COLORKEY_U			(0x0274)
+#define LCD_PN2_COLORKEY_V			(0x0278)
+#define LCD_PN2_SEPXLCNT			(0x027C)
+#define LCD_TV_V_H_TOTAL_FLD			(0x0280)
+#define LCD_TV_V_PORCH_FLD			(0x0284)
+#define LCD_TV_SEPXLCNT_FLD			(0x0288)
+
+#define LCD_2ND_ALPHA				(0x0294)
+#define LCD_PN2_CONTRAST			(0x0298)
+#define LCD_PN2_SATURATION			(0x029c)
+#define LCD_PN2_CBSH_HUE			(0x02a0)
+#define LCD_TIMING_EXT				(0x02C0)
+#define LCD_PN2_LAYER_ALPHA_SEL1		(0x02c4)
+#define LCD_PN2_CTRL0				(0x02C8)
+#define TV_LAYER_ALPHA_SEL1			(0x02cc)
+#define LCD_SMPN2_CTRL				(0x02D0)
+#define LCD_IO_OVERL_MAP_CTRL			(0x02D4)
+#define LCD_DUMB2_CTRL				(0x02d8)
+#define LCD_PN2_CTRL1				(0x02DC)
+#define PN2_IOPAD_CONTROL			(0x02E0)
+#define LCD_PN2_SQULN1_CTRL			(0x02E4)
+#define PN2_LCD_GRA_CUTHPXL			(0x02e8)
+#define PN2_LCD_GRA_CUTVLN			(0x02ec)
+#define LCD_PN2_SQULN2_CTRL			(0x02F0)
+#define ALL_LAYER_ALPHA_SEL			(0x02F4)
+
+/* pxa988 has different MASTER_CTRL from MMP3/MMP2 */
+#ifdef CONFIG_CPU_PXA988
+#define TIMING_MASTER_CONTROL			(0x01F4)
+#define MASTER_ENH(id)				(1 << ((id) + 5))
+#define MASTER_ENV(id)				(1 << ((id) + 6))
+#else
+#define TIMING_MASTER_CONTROL			(0x02F8)
+#define MASTER_ENH(id)				(1 << (id))
+#define MASTER_ENV(id)				(1 << ((id) + 4))
+#endif
+
+#define DSI_START_SEL_SHIFT(id)		(((id) << 1) + 8)
+#define timing_master_config(path, dsi_id, lcd_id) \
+	(MASTER_ENH(path) | MASTER_ENV(path) | \
+	(((lcd_id) + ((dsi_id) << 1)) << DSI_START_SEL_SHIFT(path)))
+
+#define LCD_2ND_BLD_CTL				(0x02Fc)
+#define LVDS_SRC_MASK				(3 << 30)
+#define LVDS_SRC_SHIFT				(30)
+#define LVDS_FMT_MASK				(1 << 28)
+#define LVDS_FMT_SHIFT				(28)
+
+#define CLK_SCLK	(1 << 0)
+#define CLK_LVDS_RD	(1 << 1)
+#define CLK_LVDS_WR	(1 << 2)
+
+#define gra_partdisp_ctrl_hor(id)	((id) ? (((id) & 1) ? \
+	LCD_TVG_CUTHPXL : PN2_LCD_GRA_CUTHPXL) : LCD_GRA_CUTHPXL)
+#define gra_partdisp_ctrl_ver(id)	((id) ? (((id) & 1) ? \
+	LCD_TVG_CUTVLN : PN2_LCD_GRA_CUTVLN) : LCD_GRA_CUTVLN)
+
+/*
+ * defined for Configure Dumb Mode
+ * defined for Configure Dumb Mode
+ * DUMB LCD Panel bit[31:28]
+ */
+#define DUMB16_RGB565_0		0x0
+#define DUMB16_RGB565_1		0x1
+#define DUMB18_RGB666_0		0x2
+#define DUMB18_RGB666_1		0x3
+#define DUMB12_RGB444_0		0x4
+#define DUMB12_RGB444_1		0x5
+#define DUMB24_RGB888_0		0x6
+#define DUMB_BLANK		0x7
+
+/*
+ * defined for Configure I/O Pin Allocation Mode
+ * LCD LCD I/O Pads control register bit[3:0]
+ */
+#define IOPAD_DUMB24		0x0
+#define IOPAD_DUMB18SPI		0x1
+#define IOPAD_DUMB18GPIO	0x2
+#define IOPAD_DUMB16SPI		0x3
+#define IOPAD_DUMB16GPIO	0x4
+#define IOPAD_DUMB12		0x5
+#define IOPAD_SMART18SPI	0x6
+#define IOPAD_SMART16SPI	0x7
+#define IOPAD_SMART8BOTH	0x8
+#define IOPAD_DUMB18_SMART8	0x9
+#define IOPAD_DUMB16_SMART8SPI	0xa
+#define IOPAD_DUMB16_SMART8GPIO	0xb
+#define IOPAD_DUMB16_DUMB16	0xc
+#define IOPAD_SMART8_SMART8	0xc
+
+/*
+ *defined for indicating boundary and cycle burst length
+ */
+#define  CFG_BOUNDARY_1KB			(1<<5)
+#define  CFG_BOUNDARY_4KB			(0<<5)
+#define	 CFG_CYC_BURST_LEN16			(1<<4)
+#define	 CFG_CYC_BURST_LEN8			(0<<4)
+
+/* SRAM ID */
+#define SRAMID_GAMMA_YR			0x0
+#define SRAMID_GAMMA_UG			0x1
+#define SRAMID_GAMMA_VB			0x2
+#define SRAMID_PALATTE			0x3
+#define SRAMID_HWC			0xf
+
+/* SRAM INIT Read/Write */
+#define SRAMID_INIT_READ		0x0
+#define SRAMID_INIT_WRITE		0x2
+#define SRAMID_INIT_DEFAULT		0x3
+
+/*
+ * defined VSYNC selection mode for DMA control 1 register
+ * DMA1 bit[30:28]
+ */
+#define VMODE_SMPN			0x0
+#define VMODE_SMPNIRQ			0x1
+#define VMODE_DUMB			0x2
+#define VMODE_IPE			0x3
+#define VMODE_IRE			0x4
+
+/*
+ * defined Configure Alpha and Alpha mode for DMA control 1 register
+ * DMA1 bit[15:08](alpha) / bit[17:16](alpha mode)
+ */
+/* ALPHA mode */
+#define MODE_ALPHA_DMA			0x0
+#define MODE_ALPHA_GRA			0x1
+#define MODE_ALPHA_CFG			0x2
+
+/* alpha value */
+#define ALPHA_NOGRAPHIC			0xFF	  /* all video, no graphic */
+#define ALPHA_NOVIDEO			0x00	  /* all graphic, no video */
+#define ALPHA_GRAPHNVIDEO		0x0F	  /* Selects graphic & video */
+
+/*
+ * defined Pixel Command for DMA control 1 register
+ * DMA1 bit[07:00]
+ */
+#define PIXEL_CMD			0x81
+
+/* DSI */
+/* DSI1 - 4 Lane Controller base */
+#define DSI1_REGS_PHYSICAL_BASE		0xD420B800
+/* DSI2 - 3 Lane Controller base */
+#define DSI2_REGS_PHYSICAL_BASE		0xD420BA00
+
+/*	   DSI Controller Registers	   */
+struct dsi_lcd_regs {
+#define DSI_LCD1_CTRL_0  0x100   /* DSI Active Panel 1 Control register 0 */
+#define DSI_LCD1_CTRL_1  0x104   /* DSI Active Panel 1 Control register 1 */
+	u32 ctrl0;
+	u32 ctrl1;
+	u32 reserved1[2];
+
+#define DSI_LCD1_TIMING_0		0x110   /* Timing register 0 */
+#define DSI_LCD1_TIMING_1		0x114   /* Timing register 1 */
+#define DSI_LCD1_TIMING_2		0x118   /* Timing register 2 */
+#define DSI_LCD1_TIMING_3		0x11C   /* Timing register 3 */
+#define DSI_LCD1_WC_0			0x120   /* Word Count register 0 */
+#define DSI_LCD1_WC_1			0x124   /* Word Count register 1 */
+#define DSI_LCD1_WC_2			0x128	 /* Word Count register 2 */
+	u32 timing0;
+	u32 timing1;
+	u32 timing2;
+	u32 timing3;
+	u32 wc0;
+	u32 wc1;
+	u32 wc2;
+	u32 reserved2[1];
+	u32 slot_cnt0;
+	u32 slot_cnt1;
+	u32 reserved3[2];
+	u32 status_0;
+	u32 status_1;
+	u32 status_2;
+	u32 status_3;
+	u32 status_4;
+};
+
+struct dsi_regs {
+#define DSI_CTRL_0	  0x000   /* DSI control register 0 */
+#define DSI_CTRL_1	  0x004   /* DSI control register 1 */
+	u32 ctrl0;
+	u32 ctrl1;
+	u32 reserved1[2];
+	u32 irq_status;
+	u32 irq_mask;
+	u32 reserved2[2];
+
+#define DSI_CPU_CMD_0   0x020   /* DSI CPU packet command register 0 */
+#define DSI_CPU_CMD_1   0x024   /* DSU CPU Packet Command Register 1 */
+#define DSI_CPU_CMD_3	0x02C   /* DSU CPU Packet Command Register 3 */
+#define DSI_CPU_WDAT_0	0x030   /* DSI CUP */
+	u32 cmd0;
+	u32 cmd1;
+	u32 cmd2;
+	u32 cmd3;
+	u32 dat0;
+	u32 status0;
+	u32 status1;
+	u32 status2;
+	u32 status3;
+	u32 status4;
+	u32 reserved3[2];
+
+	u32 smt_cmd;
+	u32 smt_ctrl0;
+	u32 smt_ctrl1;
+	u32 reserved4[1];
+
+	u32 rx0_status;
+
+/* Rx Packet Header - data from slave device */
+#define DSI_RX_PKT_HDR_0 0x064
+	u32 rx0_header;
+	u32 rx1_status;
+	u32 rx1_header;
+	u32 rx_ctrl;
+	u32 rx_ctrl1;
+	u32 rx2_status;
+	u32 rx2_header;
+	u32 reserved5[1];
+
+	u32 phy_ctrl1;
+#define DSI_PHY_CTRL_2		0x088   /* DSI DPHI Control Register 2 */
+#define DSI_PHY_CTRL_3		0x08C   /* DPHY Control Register 3 */
+	u32 phy_ctrl2;
+	u32 phy_ctrl3;
+	u32 phy_status0;
+	u32 phy_status1;
+	u32 reserved6[5];
+	u32 phy_status2;
+
+#define DSI_PHY_RCOMP_0		0x0B0   /* DPHY Rcomp Control Register */
+	u32 phy_rcomp0;
+	u32 reserved7[3];
+#define DSI_PHY_TIME_0		0x0C0   /* DPHY Timing Control Register 0 */
+#define DSI_PHY_TIME_1		0x0C4   /* DPHY Timing Control Register 1 */
+#define DSI_PHY_TIME_2		0x0C8   /* DPHY Timing Control Register 2 */
+#define DSI_PHY_TIME_3		0x0CC   /* DPHY Timing Control Register 3 */
+#define DSI_PHY_TIME_4		0x0D0   /* DPHY Timing Control Register 4 */
+#define DSI_PHY_TIME_5		0x0D4   /* DPHY Timing Control Register 5 */
+	u32 phy_timing0;
+	u32 phy_timing1;
+	u32 phy_timing2;
+	u32 phy_timing3;
+	u32 phy_code_0;
+	u32 phy_code_1;
+	u32 reserved8[2];
+	u32 mem_ctrl;
+	u32 tx_timer;
+	u32 rx_timer;
+	u32 turn_timer;
+	u32 reserved9[4];
+
+#define DSI_LCD1_CTRL_0  0x100   /* DSI Active Panel 1 Control register 0 */
+#define DSI_LCD1_CTRL_1  0x104   /* DSI Active Panel 1 Control register 1 */
+#define DSI_LCD1_TIMING_0		0x110   /* Timing register 0 */
+#define DSI_LCD1_TIMING_1		0x114   /* Timing register 1 */
+#define DSI_LCD1_TIMING_2		0x118   /* Timing register 2 */
+#define DSI_LCD1_TIMING_3		0x11C   /* Timing register 3 */
+#define DSI_LCD1_WC_0			0x120   /* Word Count register 0 */
+#define DSI_LCD1_WC_1			0x124   /* Word Count register 1 */
+#define DSI_LCD1_WC_2			0x128   /* Word Count register 2 */
+	struct dsi_lcd_regs lcd1;
+	u32 reserved10[11];
+	struct dsi_lcd_regs lcd2;
+};
+
+#define DSI_LCD2_CTRL_0  0x180   /* DSI Active Panel 2 Control register 0 */
+#define DSI_LCD2_CTRL_1  0x184   /* DSI Active Panel 2 Control register 1 */
+#define DSI_LCD2_TIMING_0		0x190   /* Timing register 0 */
+#define DSI_LCD2_TIMING_1		0x194   /* Timing register 1 */
+#define DSI_LCD2_TIMING_2		0x198   /* Timing register 2 */
+#define DSI_LCD2_TIMING_3		0x19C   /* Timing register 3 */
+#define DSI_LCD2_WC_0			0x1A0   /* Word Count register 0 */
+#define DSI_LCD2_WC_1			0x1A4   /* Word Count register 1 */
+#define DSI_LCD2_WC_2			0x1A8	 /* Word Count register 2 */
+
+/*	DSI_CTRL_0		0x0000	DSI Control Register 0 */
+#define DSI_CTRL_0_CFG_SOFT_RST			(1<<31)
+#define DSI_CTRL_0_CFG_SOFT_RST_REG		(1<<30)
+#define DSI_CTRL_0_CFG_LCD1_TX_EN		(1<<8)
+#define DSI_CTRL_0_CFG_LCD1_SLV			(1<<4)
+#define DSI_CTRL_0_CFG_LCD1_EN			(1<<0)
+
+/*	DSI_CTRL_1		0x0004	DSI Control Register 1 */
+#define DSI_CTRL_1_CFG_EOTP			(1<<8)
+#define DSI_CTRL_1_CFG_RSVD			(2<<4)
+#define DSI_CTRL_1_CFG_LCD2_VCH_NO_MASK		(3<<2)
+#define DSI_CTRL_1_CFG_LCD2_VCH_NO_SHIFT	2
+#define DSI_CTRL_1_CFG_LCD1_VCH_NO_MASK		(3<<0)
+#define DSI_CTRL_1_CFG_LCD1_VCH_NO_SHIFT	0
+
+/*	DSI_LCD1_CTRL_1	0x0104	DSI Active Panel 1 Control Register 1 */
+/* LCD 1 Vsync Reset Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_VSYNC_RST_EN	(1<<31)
+/* LCD 1 2K Pixel Buffer Mode Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_M2K_EN		(1<<30)
+/*		Bit(s) DSI_LCD1_CTRL_1_RSRV_29_23 reserved */
+/* Long Blanking Packet Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HLP_PKT_EN	(1<<22)
+/* Extra Long Blanking Packet Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HEX_PKT_EN	(1<<21)
+/* Front Porch Packet Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HFP_PKT_EN	(1<<20)
+/* hact Packet Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HACT_PKT_EN	(1<<19)
+/* Back Porch Packet Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HBP_PKT_EN	(1<<18)
+/* hse Packet Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HSE_PKT_EN	(1<<17)
+/* hsa Packet Enable */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HSA_PKT_EN	(1<<16)
+/* All Item Enable after Pixel Data */
+#define	DSI_LCD1_CTRL_1_CFG_L1_ALL_SLOT_EN	(1<<15)
+/* Extra Long Packet Enable after Pixel Data */
+#define	DSI_LCD1_CTRL_1_CFG_L1_HEX_SLOT_EN	(1<<14)
+/*		Bit(s) DSI_LCD1_CTRL_1_RSRV_13_11 reserved */
+/* Turn Around Bus at Last h Line */
+#define	DSI_LCD1_CTRL_1_CFG_L1_LAST_LINE_TURN	(1<<10)
+/* Go to Low Power Every Frame */
+#define	DSI_LCD1_CTRL_1_CFG_L1_LPM_FRAME_EN	(1<<9)
+/* Go to Low Power Every Line */
+#define	DSI_LCD1_CTRL_1_CFG_L1_LPM_LINE_EN	(1<<8)
+/*		Bit(s) DSI_LCD1_CTRL_1_RSRV_7_4 reserved */
+/* DSI Transmission Mode for LCD 1 */
+#define DSI_LCD1_CTRL_1_CFG_L1_BURST_MODE_SHIFT	2
+#define DSI_LCD1_CTRL_1_CFG_L1_BURST_MODE_MASK	(3<<2)
+/* LCD 1 Input Data RGB Mode for LCD 1 */
+#define DSI_LCD2_CTRL_1_CFG_L1_RGB_TYPE_SHIFT	0
+#define DSI_LCD2_CTRL_1_CFG_L1_RGB_TYPE_MASK	(3<<2)
+
+/*	DSI_PHY_CTRL_2		0x0088	DPHY Control Register 2 */
+/*		Bit(s) DSI_PHY_CTRL_2_RSRV_31_12 reserved */
+/* DPHY LP Receiver Enable */
+#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_RESC_EN_MASK	(0xf<<8)
+#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_RESC_EN_SHIFT	8
+/* DPHY Data Lane Enable */
+#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_EN_MASK		(0xf<<4)
+#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_EN_SHIFT		4
+/* DPHY Bus Turn Around */
+#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_TURN_MASK		(0xf)
+#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_TURN_SHIFT		0
+
+/*	DSI_CPU_CMD_1		0x0024	DSI CPU Packet Command Register 1 */
+/*		Bit(s) DSI_CPU_CMD_1_RSRV_31_24 reserved */
+/* LPDT TX Enable */
+#define	DSI_CPU_CMD_1_CFG_TXLP_LPDT_MASK		(0xf<<20)
+#define	DSI_CPU_CMD_1_CFG_TXLP_LPDT_SHIFT		20
+/* ULPS TX Enable */
+#define	DSI_CPU_CMD_1_CFG_TXLP_ULPS_MASK		(0xf<<16)
+#define	DSI_CPU_CMD_1_CFG_TXLP_ULPS_SHIFT		16
+/* Low Power TX Trigger Code */
+#define	DSI_CPU_CMD_1_CFG_TXLP_TRIGGER_CODE_MASK	(0xffff)
+#define	DSI_CPU_CMD_1_CFG_TXLP_TRIGGER_CODE_SHIFT	0
+
+/*	DSI_PHY_TIME_0	0x00c0	DPHY Timing Control Register 0 */
+/* Length of HS Exit Period in tx_clk_esc Cycles */
+#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_EXIT_MASK	(0xff<<24)
+#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_EXIT_SHIFT	24
+/* DPHY HS Trail Period Length */
+#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_TRAIL_MASK	(0xff<<16)
+#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_TRAIL_SHIFT	16
+/* DPHY HS Zero State Length */
+#define	DSI_PHY_TIME_0_CDG_CSR_TIME_HS_ZERO_MASK	(0xff<<8)
+#define	DSI_PHY_TIME_0_CDG_CSR_TIME_HS_ZERO_SHIFT	8
+/* DPHY HS Prepare State Length */
+#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_PREP_MASK	(0xff)
+#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_PREP_SHIFT	0
+
+/*	DSI_PHY_TIME_1		0x00c4	DPHY Timing Control Register 1 */
+/* Time to Drive LP-00 by New Transmitter */
+#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GET_MASK		(0xff<<24)
+#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GET_SHIFT	24
+/* Time to Drive LP-00 after Turn Request */
+#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GO_MASK		(0xff<<16)
+#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GO_SHIFT		16
+/* DPHY HS Wakeup Period Length */
+#define	DSI_PHY_TIME_1_CFG_CSR_TIME_WAKEUP_MASK		(0xffff)
+#define	DSI_PHY_TIME_1_CFG_CSR_TIME_WAKEUP_SHIFT	0
+
+/*	DSI_PHY_TIME_2		0x00c8	DPHY Timing Control Register 2 */
+/* DPHY CLK Exit Period Length */
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_EXIT_MASK	(0xff<<24)
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_EXIT_SHIFT	24
+/* DPHY CLK Trail Period Length */
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_TRAIL_MASK	(0xff<<16)
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_TRAIL_SHIFT	16
+/* DPHY CLK Zero State Length */
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_ZERO_MASK	(0xff<<8)
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_ZERO_SHIFT	8
+/* DPHY CLK LP Length */
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_LPX_MASK		(0xff)
+#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_LPX_SHIFT	0
+
+/*	DSI_PHY_TIME_3		0x00cc	DPHY Timing Control Register 3 */
+/*		Bit(s) DSI_PHY_TIME_3_RSRV_31_16 reserved */
+/* DPHY LP Length */
+#define	DSI_PHY_TIME_3_CFG_CSR_TIME_LPX_MASK		(0xff<<8)
+#define	DSI_PHY_TIME_3_CFG_CSR_TIME_LPX_SHIFT		8
+/* DPHY HS req to rdy Length */
+#define	DSI_PHY_TIME_3_CFG_CSR_TIME_REQRDY_MASK		(0xff)
+#define	DSI_PHY_TIME_3_CFG_CSR_TIME_REQRDY_SHIFT	0
+
+/*
+ * DSI timings
+ * PXA988 has diffrent ESC CLK with MMP2/MMP3
+ * it will be used in dsi_set_dphy() in pxa688_phy.c
+ * as low power mode clock.
+ */
+#ifdef CONFIG_CPU_PXA988
+#define DSI_ESC_CLK				52  /* Unit: Mhz */
+#define DSI_ESC_CLK_T				19  /* Unit: ns */
+#else
+#define DSI_ESC_CLK				66  /* Unit: Mhz */
+#define DSI_ESC_CLK_T				15  /* Unit: ns */
+#endif
+
+/* LVDS */
+/* LVDS_PHY_CTRL */
+#define LVDS_PHY_CTL				0x2A4
+#define LVDS_PLL_LOCK				(1 << 31)
+#define LVDS_PHY_EXT_MASK			(7 << 28)
+#define LVDS_PHY_EXT_SHIFT			(28)
+#define LVDS_CLK_PHASE_MASK			(0x7f << 16)
+#define LVDS_CLK_PHASE_SHIFT			(16)
+#define LVDS_SSC_RESET_EXT			(1 << 13)
+#define LVDS_SSC_MODE_DOWN_SPREAD		(1 << 12)
+#define LVDS_SSC_EN				(1 << 11)
+#define LVDS_PU_PLL				(1 << 10)
+#define LVDS_PU_TX				(1 << 9)
+#define LVDS_PU_IVREF				(1 << 8)
+#define LVDS_CLK_SEL				(1 << 7)
+#define LVDS_CLK_SEL_LVDS_PCLK			(1 << 7)
+#define LVDS_PD_CH_MASK				(0x3f << 1)
+#define LVDS_PD_CH(ch)				((ch) << 1)
+#define LVDS_RST				(1 << 0)
+
+#define LVDS_PHY_CTL_EXT	0x2A8
+
+/* LVDS_PHY_CTRL_EXT1 */
+#define LVDS_SSC_RNGE_MASK			(0x7ff << 16)
+#define LVDS_SSC_RNGE_SHIFT			(16)
+#define LVDS_RESERVE_IN_MASK			(0xf << 12)
+#define LVDS_RESERVE_IN_SHIFT			(12)
+#define LVDS_TEST_MON_MASK			(0x7 << 8)
+#define LVDS_TEST_MON_SHIFT			(8)
+#define LVDS_POL_SWAP_MASK			(0x3f << 0)
+#define LVDS_POL_SWAP_SHIFT			(0)
+
+/* LVDS_PHY_CTRL_EXT2 */
+#define LVDS_TX_DIF_AMP_MASK			(0xf << 24)
+#define LVDS_TX_DIF_AMP_SHIFT			(24)
+#define LVDS_TX_DIF_CM_MASK			(0x3 << 22)
+#define LVDS_TX_DIF_CM_SHIFT			(22)
+#define LVDS_SELLV_TXCLK_MASK			(0x1f << 16)
+#define LVDS_SELLV_TXCLK_SHIFT			(16)
+#define LVDS_TX_CMFB_EN				(0x1 << 15)
+#define LVDS_TX_TERM_EN				(0x1 << 14)
+#define LVDS_SELLV_TXDATA_MASK			(0x1f << 8)
+#define LVDS_SELLV_TXDATA_SHIFT			(8)
+#define LVDS_SELLV_OP7_MASK			(0x3 << 6)
+#define LVDS_SELLV_OP7_SHIFT			(6)
+#define LVDS_SELLV_OP6_MASK			(0x3 << 4)
+#define LVDS_SELLV_OP6_SHIFT			(4)
+#define LVDS_SELLV_OP9_MASK			(0x3 << 2)
+#define LVDS_SELLV_OP9_SHIFT			(2)
+#define LVDS_STRESSTST_EN			(0x1 << 0)
+
+/* LVDS_PHY_CTRL_EXT3 */
+#define LVDS_KVCO_MASK				(0xf << 28)
+#define LVDS_KVCO_SHIFT				(28)
+#define LVDS_CTUNE_MASK				(0x3 << 26)
+#define LVDS_CTUNE_SHIFT			(26)
+#define LVDS_VREG_IVREF_MASK			(0x3 << 24)
+#define LVDS_VREG_IVREF_SHIFT			(24)
+#define LVDS_VDDL_MASK				(0xf << 20)
+#define LVDS_VDDL_SHIFT				(20)
+#define LVDS_VDDM_MASK				(0x3 << 18)
+#define LVDS_VDDM_SHIFT				(18)
+#define LVDS_FBDIV_MASK				(0xf << 8)
+#define LVDS_FBDIV_SHIFT			(8)
+#define LVDS_REFDIV_MASK			(0x7f << 0)
+#define LVDS_REFDIV_SHIFT			(0)
+
+/* LVDS_PHY_CTRL_EXT4 */
+#define LVDS_SSC_FREQ_DIV_MASK			(0xffff << 16)
+#define LVDS_SSC_FREQ_DIV_SHIFT			(16)
+#define LVDS_INTPI_MASK				(0xf << 12)
+#define LVDS_INTPI_SHIFT			(12)
+#define LVDS_VCODIV_SEL_SE_MASK			(0xf << 8)
+#define LVDS_VCODIV_SEL_SE_SHIFT		(8)
+#define LVDS_RESET_INTP_EXT			(0x1 << 7)
+#define LVDS_VCO_VRNG_MASK			(0x7 << 4)
+#define LVDS_VCO_VRNG_SHIFT			(4)
+#define LVDS_PI_EN				(0x1 << 3)
+#define LVDS_ICP_MASK				(0x7 << 0)
+#define LVDS_ICP_SHIFT				(0)
+
+/* LVDS_PHY_CTRL_EXT5 */
+#define LVDS_FREQ_OFFSET_MASK			(0x1ffff << 15)
+#define LVDS_FREQ_OFFSET_SHIFT			(15)
+#define LVDS_FREQ_OFFSET_VALID			(0x1 << 2)
+#define LVDS_FREQ_OFFSET_MODE_CK_DIV4_OUT	(0x1 << 1)
+#define LVDS_FREQ_OFFSET_MODE_EN		(0x1 << 0)
+
+enum {
+	PATH_PN = 0,
+	PATH_TV,
+	PATH_P2,
+};
+
+/*
+ * mmp path describes part of mmp path related info:
+ * which is hiden in display driver and not exported to buffer driver
+ */
+struct mmphw_ctrl;
+struct mmphw_path_plat {
+	int id;
+	struct mmphw_ctrl *ctrl;
+	struct mmp_path *path;
+	u32 path_config;
+	u32 link_config;
+	u32 dsi_rbswap;
+};
+
+/* mmp ctrl describes mmp controller related info */
+struct mmphw_ctrl {
+	/* platform related, get from config */
+	const char *name;
+	int irq;
+	void *reg_base;
+	struct clk *clk;
+
+	/* sys info */
+	struct device *dev;
+
+	/* state */
+	int open_count;
+	int status;
+	struct mutex access_ok;
+
+	/*pathes*/
+	int path_num;
+	struct mmphw_path_plat path_plats[0];
+};
+
+static inline int overlay_is_vid(struct mmp_overlay *overlay)
+{
+	return overlay->dmafetch_id & 1;
+}
+
+static inline struct mmphw_path_plat *path_to_path_plat(struct mmp_path *path)
+{
+	return (struct mmphw_path_plat *)path->plat_data;
+}
+
+static inline struct mmphw_ctrl *path_to_ctrl(struct mmp_path *path)
+{
+	return path_to_path_plat(path)->ctrl;
+}
+
+static inline struct mmphw_ctrl *overlay_to_ctrl(struct mmp_overlay *overlay)
+{
+	return path_to_ctrl(overlay->path);
+}
+
+static inline void *ctrl_regs(struct mmp_path *path)
+{
+	return path_to_ctrl(path)->reg_base;
+}
+
+/* path regs, for regs symmetrical for both pathes */
+static inline struct lcd_regs *path_regs(struct mmp_path *path)
+{
+	if (path->id == PATH_PN)
+		return (struct lcd_regs *)(ctrl_regs(path) + 0xc0);
+	else if (path->id == PATH_TV)
+		return (struct lcd_regs *)ctrl_regs(path);
+	else if (path->id == PATH_P2)
+		return (struct lcd_regs *)(ctrl_regs(path) + 0x200);
+	else {
+		dev_err(path->dev, "path id %d invalid\n", path->id);
+		BUG_ON(1);
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_MMP_DISP_SPI
+extern int lcd_spi_register(struct mmphw_ctrl *ctrl);
+#endif
+#endif	/* _MMP_CTRL_H_ */
diff --git a/drivers/video/fbdev/mmp/hw/mmp_spi.c b/drivers/video/fbdev/mmp/hw/mmp_spi.c
new file mode 100644
index 000000000000..e62ca7bf0d5e
--- /dev/null
+++ b/drivers/video/fbdev/mmp/hw/mmp_spi.c
@@ -0,0 +1,180 @@
+/*
+ * linux/drivers/video/mmp/hw/mmp_spi.c
+ * using the spi in LCD controler for commands send
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Authors:  Guoqing Li <ligq@marvell.com>
+ *          Lisa Du <cldu@marvell.com>
+ *          Zhou Zhu <zzhu3@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include "mmp_ctrl.h"
+
+/**
+ * spi_write - write command to the SPI port
+ * @data: can be 8/16/32-bit, MSB justified data to write.
+ * @len:  data length.
+ *
+ * Wait bus transfer complete IRQ.
+ * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ *   %-ETIMEDOUT	timeout occurred
+ *   0			success
+ */
+static inline int lcd_spi_write(struct spi_device *spi, u32 data)
+{
+	int timeout = 100000, isr, ret = 0;
+	u32 tmp;
+	void *reg_base =
+		*(void **)spi_master_get_devdata(spi->master);
+
+	/* clear ISR */
+	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
+
+	switch (spi->bits_per_word) {
+	case 8:
+		writel_relaxed((u8)data, reg_base + LCD_SPU_SPI_TXDATA);
+		break;
+	case 16:
+		writel_relaxed((u16)data, reg_base + LCD_SPU_SPI_TXDATA);
+		break;
+	case 32:
+		writel_relaxed((u32)data, reg_base + LCD_SPU_SPI_TXDATA);
+		break;
+	default:
+		dev_err(&spi->dev, "Wrong spi bit length\n");
+	}
+
+	/* SPI start to send command */
+	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
+	tmp &= ~CFG_SPI_START_MASK;
+	tmp |= CFG_SPI_START(1);
+	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
+
+	isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
+	while (!(isr & SPI_IRQ_ENA_MASK)) {
+		udelay(100);
+		isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
+		if (!--timeout) {
+			ret = -ETIMEDOUT;
+			dev_err(&spi->dev, "spi cmd send time out\n");
+			break;
+		}
+	}
+
+	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
+	tmp &= ~CFG_SPI_START_MASK;
+	tmp |= CFG_SPI_START(0);
+	writel_relaxed(tmp, reg_base + LCD_SPU_SPI_CTRL);
+
+	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
+
+	return ret;
+}
+
+static int lcd_spi_setup(struct spi_device *spi)
+{
+	void *reg_base =
+		*(void **)spi_master_get_devdata(spi->master);
+	u32 tmp;
+
+	tmp = CFG_SCLKCNT(16) |
+		CFG_TXBITS(spi->bits_per_word) |
+		CFG_SPI_SEL(1) | CFG_SPI_ENA(1) |
+		CFG_SPI_3W4WB(1);
+	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
+
+	/*
+	 * After set mode it need a time to pull up the spi singals,
+	 * or it would cause the wrong waveform when send spi command,
+	 * especially on pxa910h
+	 */
+	tmp = readl_relaxed(reg_base + SPU_IOPAD_CONTROL);
+	if ((tmp & CFG_IOPADMODE_MASK) != IOPAD_DUMB18SPI)
+		writel_relaxed(IOPAD_DUMB18SPI |
+			(tmp & ~CFG_IOPADMODE_MASK),
+			reg_base + SPU_IOPAD_CONTROL);
+	udelay(20);
+	return 0;
+}
+
+static int lcd_spi_one_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct spi_transfer *t;
+	int i;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		switch (spi->bits_per_word) {
+		case 8:
+			for (i = 0; i < t->len; i++)
+				lcd_spi_write(spi, ((u8 *)t->tx_buf)[i]);
+			break;
+		case 16:
+			for (i = 0; i < t->len/2; i++)
+				lcd_spi_write(spi, ((u16 *)t->tx_buf)[i]);
+			break;
+		case 32:
+			for (i = 0; i < t->len/4; i++)
+				lcd_spi_write(spi, ((u32 *)t->tx_buf)[i]);
+			break;
+		default:
+			dev_err(&spi->dev, "Wrong spi bit length\n");
+		}
+	}
+
+	m->status = 0;
+	if (m->complete)
+		m->complete(m->context);
+	return 0;
+}
+
+int lcd_spi_register(struct mmphw_ctrl *ctrl)
+{
+	struct spi_master *master;
+	void **p_regbase;
+	int err;
+
+	master = spi_alloc_master(ctrl->dev, sizeof(void *));
+	if (!master) {
+		dev_err(ctrl->dev, "unable to allocate SPI master\n");
+		return -ENOMEM;
+	}
+	p_regbase = spi_master_get_devdata(master);
+	*p_regbase = ctrl->reg_base;
+
+	/* set bus num to 5 to avoid conflict with other spi hosts */
+	master->bus_num = 5;
+	master->num_chipselect = 1;
+	master->setup = lcd_spi_setup;
+	master->transfer = lcd_spi_one_transfer;
+
+	err = spi_register_master(master);
+	if (err < 0) {
+		dev_err(ctrl->dev, "unable to register SPI master\n");
+		spi_master_put(master);
+		return err;
+	}
+
+	dev_info(&master->dev, "registered\n");
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/mmp/panel/Kconfig b/drivers/video/fbdev/mmp/panel/Kconfig
new file mode 100644
index 000000000000..4b2c4f457b11
--- /dev/null
+++ b/drivers/video/fbdev/mmp/panel/Kconfig
@@ -0,0 +1,6 @@
+config MMP_PANEL_TPOHVGA
+	bool "tpohvga panel TJ032MD01BW support"
+	depends on SPI_MASTER
+	default n
+	help
+		tpohvga panel support
diff --git a/drivers/video/fbdev/mmp/panel/Makefile b/drivers/video/fbdev/mmp/panel/Makefile
new file mode 100644
index 000000000000..2f91611c7e5e
--- /dev/null
+++ b/drivers/video/fbdev/mmp/panel/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MMP_PANEL_TPOHVGA)    += tpo_tj032md01bw.o
diff --git a/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c b/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
new file mode 100644
index 000000000000..998978b08f5e
--- /dev/null
+++ b/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
@@ -0,0 +1,186 @@
+/*
+ * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c
+ * active panel using spi interface to do init
+ *
+ * Copyright (C) 2012 Marvell Technology Group Ltd.
+ * Authors:  Guoqing Li <ligq@marvell.com>
+ *          Lisa Du <cldu@marvell.com>
+ *          Zhou Zhu <zzhu3@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/spi/spi.h>
+#include <video/mmp_disp.h>
+
+static u16 init[] = {
+	0x0801,
+	0x0800,
+	0x0200,
+	0x0304,
+	0x040e,
+	0x0903,
+	0x0b18,
+	0x0c53,
+	0x0d01,
+	0x0ee0,
+	0x0f01,
+	0x1058,
+	0x201e,
+	0x210a,
+	0x220a,
+	0x231e,
+	0x2400,
+	0x2532,
+	0x2600,
+	0x27ac,
+	0x2904,
+	0x2aa2,
+	0x2b45,
+	0x2c45,
+	0x2d15,
+	0x2e5a,
+	0x2fff,
+	0x306b,
+	0x310d,
+	0x3248,
+	0x3382,
+	0x34bd,
+	0x35e7,
+	0x3618,
+	0x3794,
+	0x3801,
+	0x395d,
+	0x3aae,
+	0x3bff,
+	0x07c9,
+};
+
+static u16 poweroff[] = {
+	0x07d9,
+};
+
+struct tpohvga_plat_data {
+	void (*plat_onoff)(int status);
+	struct spi_device *spi;
+};
+
+static void tpohvga_onoff(struct mmp_panel *panel, int status)
+{
+	struct tpohvga_plat_data *plat = panel->plat_data;
+	int ret;
+
+	if (status) {
+		plat->plat_onoff(1);
+
+		ret = spi_write(plat->spi, init, sizeof(init));
+		if (ret < 0)
+			dev_warn(panel->dev, "init cmd failed(%d)\n", ret);
+	} else {
+		ret = spi_write(plat->spi, poweroff, sizeof(poweroff));
+		if (ret < 0)
+			dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret);
+
+		plat->plat_onoff(0);
+	}
+}
+
+static struct mmp_mode mmp_modes_tpohvga[] = {
+	[0] = {
+		.pixclock_freq = 10394400,
+		.refresh = 60,
+		.xres = 320,
+		.yres = 480,
+		.hsync_len = 10,
+		.left_margin = 15,
+		.right_margin = 10,
+		.vsync_len = 2,
+		.upper_margin = 4,
+		.lower_margin = 2,
+		.invert_pixclock = 1,
+		.pix_fmt_out = PIXFMT_RGB565,
+	},
+};
+
+static int tpohvga_get_modelist(struct mmp_panel *panel,
+		struct mmp_mode **modelist)
+{
+	*modelist = mmp_modes_tpohvga;
+	return 1;
+}
+
+static struct mmp_panel panel_tpohvga = {
+	.name = "tpohvga",
+	.panel_type = PANELTYPE_ACTIVE,
+	.get_modelist = tpohvga_get_modelist,
+	.set_onoff = tpohvga_onoff,
+};
+
+static int tpohvga_probe(struct spi_device *spi)
+{
+	struct mmp_mach_panel_info *mi;
+	int ret;
+	struct tpohvga_plat_data *plat_data;
+
+	/* get configs from platform data */
+	mi = spi->dev.platform_data;
+	if (mi == NULL) {
+		dev_err(&spi->dev, "%s: no platform data defined\n", __func__);
+		return -EINVAL;
+	}
+
+	/* setup spi related info */
+	spi->bits_per_word = 16;
+	ret = spi_setup(spi);
+	if (ret < 0) {
+		dev_err(&spi->dev, "spi setup failed %d", ret);
+		return ret;
+	}
+
+	plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL);
+	if (plat_data == NULL)
+		return -ENOMEM;
+
+	plat_data->spi = spi;
+	plat_data->plat_onoff = mi->plat_set_onoff;
+	panel_tpohvga.plat_data = plat_data;
+	panel_tpohvga.plat_path_name = mi->plat_path_name;
+	panel_tpohvga.dev = &spi->dev;
+
+	mmp_register_panel(&panel_tpohvga);
+
+	return 0;
+}
+
+static struct spi_driver panel_tpohvga_driver = {
+	.driver		= {
+		.name	= "tpo-hvga",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tpohvga_probe,
+};
+module_spi_driver(panel_tpohvga_driver);
+
+MODULE_AUTHOR("Lisa Du<cldu@marvell.com>");
+MODULE_DESCRIPTION("Panel driver for tpohvga");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile
new file mode 100644
index 000000000000..802d6ae523fb
--- /dev/null
+++ b/drivers/video/fbdev/msm/Makefile
@@ -0,0 +1,19 @@
+
+# core framebuffer
+#
+obj-y := msm_fb.o
+
+# MDP DMA/PPP engine
+#
+obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
+
+# MDDI interface
+#
+obj-y += mddi.o
+
+# MDDI client/panel drivers
+#
+obj-y += mddi_client_dummy.o
+obj-y += mddi_client_toshiba.o
+obj-y += mddi_client_nt35399.o
+
diff --git a/drivers/video/fbdev/msm/mddi.c b/drivers/video/fbdev/msm/mddi.c
new file mode 100644
index 000000000000..e0f8011a3c4b
--- /dev/null
+++ b/drivers/video/fbdev/msm/mddi.c
@@ -0,0 +1,821 @@
+/*
+ * MSM MDDI Transport
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/platform_data/video-msm_fb.h>
+#include "mddi_hw.h"
+
+#define FLAG_DISABLE_HIBERNATION 0x0001
+#define FLAG_HAVE_CAPS		 0x0002
+#define FLAG_HAS_VSYNC_IRQ	 0x0004
+#define FLAG_HAVE_STATUS	 0x0008
+
+#define CMD_GET_CLIENT_CAP     0x0601
+#define CMD_GET_CLIENT_STATUS  0x0602
+
+union mddi_rev {
+	unsigned char raw[MDDI_REV_BUFFER_SIZE];
+	struct mddi_rev_packet hdr;
+	struct mddi_client_status status;
+	struct mddi_client_caps caps;
+	struct mddi_register_access reg;
+};
+
+struct reg_read_info {
+	struct completion done;
+	uint32_t reg;
+	uint32_t status;
+	uint32_t result;
+};
+
+struct mddi_info {
+	uint16_t flags;
+	uint16_t version;
+	char __iomem *base;
+	int irq;
+	struct clk *clk;
+	struct msm_mddi_client_data client_data;
+
+	/* buffer for rev encap packets */
+	void *rev_data;
+	dma_addr_t rev_addr;
+	struct mddi_llentry *reg_write_data;
+	dma_addr_t reg_write_addr;
+	struct mddi_llentry *reg_read_data;
+	dma_addr_t reg_read_addr;
+	size_t rev_data_curr;
+
+	spinlock_t int_lock;
+	uint32_t int_enable;
+	uint32_t got_int;
+	wait_queue_head_t int_wait;
+
+	struct mutex reg_write_lock;
+	struct mutex reg_read_lock;
+	struct reg_read_info *reg_read;
+
+	struct mddi_client_caps caps;
+	struct mddi_client_status status;
+
+	void (*power_client)(struct msm_mddi_client_data *, int);
+
+	/* client device published to bind us to the
+	 * appropriate mddi_client driver
+	 */
+	char client_name[20];
+
+	struct platform_device client_pdev;
+};
+
+static void mddi_init_rev_encap(struct mddi_info *mddi);
+
+#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
+#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
+
+void mddi_activate_link(struct msm_mddi_client_data *cdata)
+{
+	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
+					      client_data);
+
+	mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
+}
+
+static void mddi_handle_link_list_done(struct mddi_info *mddi)
+{
+}
+
+static void mddi_reset_rev_encap_ptr(struct mddi_info *mddi)
+{
+	printk(KERN_INFO "mddi: resetting rev ptr\n");
+	mddi->rev_data_curr = 0;
+	mddi_writel(mddi->rev_addr, REV_PTR);
+	mddi_writel(mddi->rev_addr, REV_PTR);
+	mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
+}
+
+static void mddi_handle_rev_data(struct mddi_info *mddi, union mddi_rev *rev)
+{
+	int i;
+	struct reg_read_info *ri;
+
+	if ((rev->hdr.length <= MDDI_REV_BUFFER_SIZE - 2) &&
+	   (rev->hdr.length >= sizeof(struct mddi_rev_packet) - 2)) {
+
+		switch (rev->hdr.type) {
+		case TYPE_CLIENT_CAPS:
+			memcpy(&mddi->caps, &rev->caps,
+			       sizeof(struct mddi_client_caps));
+			mddi->flags |= FLAG_HAVE_CAPS;
+			wake_up(&mddi->int_wait);
+			break;
+		case TYPE_CLIENT_STATUS:
+			memcpy(&mddi->status, &rev->status,
+			       sizeof(struct mddi_client_status));
+			mddi->flags |= FLAG_HAVE_STATUS;
+			wake_up(&mddi->int_wait);
+			break;
+		case TYPE_REGISTER_ACCESS:
+			ri = mddi->reg_read;
+			if (ri == 0) {
+				printk(KERN_INFO "rev: got reg %x = %x without "
+						 " pending read\n",
+				       rev->reg.register_address,
+				       rev->reg.register_data_list);
+				break;
+			}
+			if (ri->reg != rev->reg.register_address) {
+				printk(KERN_INFO "rev: got reg %x = %x for "
+						 "wrong register, expected "
+						 "%x\n",
+				       rev->reg.register_address,
+				       rev->reg.register_data_list, ri->reg);
+				break;
+			}
+			mddi->reg_read = NULL;
+			ri->status = 0;
+			ri->result = rev->reg.register_data_list;
+			complete(&ri->done);
+			break;
+		default:
+			printk(KERN_INFO "rev: unknown reverse packet: "
+					 "len=%04x type=%04x CURR_REV_PTR=%x\n",
+			       rev->hdr.length, rev->hdr.type,
+			       mddi_readl(CURR_REV_PTR));
+			for (i = 0; i < rev->hdr.length + 2; i++) {
+				if ((i % 16) == 0)
+					printk(KERN_INFO "\n");
+				printk(KERN_INFO " %02x", rev->raw[i]);
+			}
+			printk(KERN_INFO "\n");
+			mddi_reset_rev_encap_ptr(mddi);
+		}
+	} else {
+		printk(KERN_INFO "bad rev length, %d, CURR_REV_PTR %x\n",
+		       rev->hdr.length, mddi_readl(CURR_REV_PTR));
+		mddi_reset_rev_encap_ptr(mddi);
+	}
+}
+
+static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
+
+static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
+{
+	uint32_t rev_data_count;
+	uint32_t rev_crc_err_count;
+	struct reg_read_info *ri;
+	size_t prev_offset;
+	uint16_t length;
+
+	union mddi_rev *crev = mddi->rev_data + mddi->rev_data_curr;
+
+	/* clear the interrupt */
+	mddi_writel(MDDI_INT_REV_DATA_AVAIL, INT);
+	rev_data_count = mddi_readl(REV_PKT_CNT);
+	rev_crc_err_count = mddi_readl(REV_CRC_ERR);
+	if (rev_data_count > 1)
+		printk(KERN_INFO "rev_data_count %d\n", rev_data_count);
+
+	if (rev_crc_err_count) {
+		printk(KERN_INFO "rev_crc_err_count %d, INT %x\n",
+		       rev_crc_err_count,  mddi_readl(INT));
+		ri = mddi->reg_read;
+		if (ri == 0) {
+			printk(KERN_INFO "rev: got crc error without pending "
+			       "read\n");
+		} else {
+			mddi->reg_read = NULL;
+			ri->status = -EIO;
+			ri->result = -1;
+			complete(&ri->done);
+		}
+	}
+
+	if (rev_data_count == 0)
+		return;
+
+	prev_offset = mddi->rev_data_curr;
+
+	length = *((uint8_t *)mddi->rev_data + mddi->rev_data_curr);
+	mddi->rev_data_curr++;
+	if (mddi->rev_data_curr == MDDI_REV_BUFFER_SIZE)
+		mddi->rev_data_curr = 0;
+	length += *((uint8_t *)mddi->rev_data + mddi->rev_data_curr) << 8;
+	mddi->rev_data_curr += 1 + length;
+	if (mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE)
+		mddi->rev_data_curr =
+			mddi->rev_data_curr % MDDI_REV_BUFFER_SIZE;
+
+	if (length > MDDI_REV_BUFFER_SIZE - 2) {
+		printk(KERN_INFO "mddi: rev data length greater than buffer"
+			"size\n");
+		mddi_reset_rev_encap_ptr(mddi);
+		return;
+	}
+
+	if (prev_offset + 2 + length >= MDDI_REV_BUFFER_SIZE) {
+		union mddi_rev tmprev;
+		size_t rem = MDDI_REV_BUFFER_SIZE - prev_offset;
+		memcpy(&tmprev.raw[0], mddi->rev_data + prev_offset, rem);
+		memcpy(&tmprev.raw[rem], mddi->rev_data, 2 + length - rem);
+		mddi_handle_rev_data(mddi, &tmprev);
+	} else {
+		mddi_handle_rev_data(mddi, crev);
+	}
+
+	if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 &&
+	    mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) {
+		mddi_writel(mddi->rev_addr, REV_PTR);
+	}
+}
+
+static irqreturn_t mddi_isr(int irq, void *data)
+{
+	struct msm_mddi_client_data *cdata = data;
+	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
+					      client_data);
+	uint32_t active, status;
+
+	spin_lock(&mddi->int_lock);
+
+	active = mddi_readl(INT);
+	status = mddi_readl(STAT);
+
+	mddi_writel(active, INT);
+
+	/* ignore any interrupts we have disabled */
+	active &= mddi->int_enable;
+
+	mddi->got_int |= active;
+	wake_up(&mddi->int_wait);
+
+	if (active & MDDI_INT_PRI_LINK_LIST_DONE) {
+		mddi->int_enable &= (~MDDI_INT_PRI_LINK_LIST_DONE);
+		mddi_handle_link_list_done(mddi);
+	}
+	if (active & MDDI_INT_REV_DATA_AVAIL)
+		mddi_handle_rev_data_avail(mddi);
+
+	if (active & ~MDDI_INT_NEED_CLEAR)
+		mddi->int_enable &= ~(active & ~MDDI_INT_NEED_CLEAR);
+
+	if (active & MDDI_INT_LINK_ACTIVE) {
+		mddi->int_enable &= (~MDDI_INT_LINK_ACTIVE);
+		mddi->int_enable |= MDDI_INT_IN_HIBERNATION;
+	}
+
+	if (active & MDDI_INT_IN_HIBERNATION) {
+		mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION);
+		mddi->int_enable |= MDDI_INT_LINK_ACTIVE;
+	}
+
+	mddi_writel(mddi->int_enable, INTEN);
+	spin_unlock(&mddi->int_lock);
+
+	return IRQ_HANDLED;
+}
+
+static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
+					uint32_t intmask, int timeout)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&mddi->int_lock, irq_flags);
+	mddi->got_int &= ~intmask;
+	mddi->int_enable |= intmask;
+	mddi_writel(mddi->int_enable, INTEN);
+	spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
+	return wait_event_timeout(mddi->int_wait, mddi->got_int & intmask,
+				  timeout);
+}
+
+static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
+{
+	if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
+		printk(KERN_INFO "mddi_wait_interrupt %d, timeout "
+		       "waiting for %x, INT = %x, STAT = %x gotint = %x\n",
+		       current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
+		       mddi->got_int);
+}
+
+static void mddi_init_rev_encap(struct mddi_info *mddi)
+{
+	memset(mddi->rev_data, 0xee, MDDI_REV_BUFFER_SIZE);
+	mddi_writel(mddi->rev_addr, REV_PTR);
+	mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+}
+
+void mddi_set_auto_hibernate(struct msm_mddi_client_data *cdata, int on)
+{
+	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
+					      client_data);
+	mddi_writel(MDDI_CMD_POWERDOWN, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_IN_HIBERNATION);
+	mddi_writel(MDDI_CMD_HIBERNATE | !!on, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+}
+
+
+static uint16_t mddi_init_registers(struct mddi_info *mddi)
+{
+	mddi_writel(0x0001, VERSION);
+	mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
+	mddi_writel(0x0003, SPM); /* subframes per media */
+	mddi_writel(0x0005, TA1_LEN);
+	mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
+	mddi_writel(0x0096, DRIVE_HI);
+	/* 0x32 normal, 0x50 for Toshiba display */
+	mddi_writel(0x0050, DRIVE_LO);
+	mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
+	mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
+
+	mddi_writel(MDDI_REV_BUFFER_SIZE, REV_SIZE);
+	mddi_writel(MDDI_MAX_REV_PKT_SIZE, REV_ENCAP_SZ);
+
+	/* disable periodic rev encap */
+	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+
+	if (mddi_readl(PAD_CTL) == 0) {
+		/* If we are turning on band gap, need to wait 5us before
+		 * turning on the rest of the PAD */
+		mddi_writel(0x08000, PAD_CTL);
+		udelay(5);
+	}
+
+	/* Recommendation from PAD hw team */
+	mddi_writel(0xa850f, PAD_CTL);
+
+
+	/* Need an even number for counts */
+	mddi_writel(0x60006, DRIVER_START_CNT);
+
+	mddi_set_auto_hibernate(&mddi->client_data, 0);
+
+	mddi_writel(MDDI_CMD_DISP_IGNORE, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+
+	mddi_init_rev_encap(mddi);
+	return mddi_readl(CORE_VER) & 0xffff;
+}
+
+static void mddi_suspend(struct msm_mddi_client_data *cdata)
+{
+	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
+					      client_data);
+	/* turn off the client */
+	if (mddi->power_client)
+		mddi->power_client(&mddi->client_data, 0);
+	/* turn off the link */
+	mddi_writel(MDDI_CMD_RESET, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+	/* turn off the clock */
+	clk_disable(mddi->clk);
+}
+
+static void mddi_resume(struct msm_mddi_client_data *cdata)
+{
+	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
+					      client_data);
+	mddi_set_auto_hibernate(&mddi->client_data, 0);
+	/* turn on the client */
+	if (mddi->power_client)
+		mddi->power_client(&mddi->client_data, 1);
+	/* turn on the clock */
+	clk_enable(mddi->clk);
+	/* set up the local registers */
+	mddi->rev_data_curr = 0;
+	mddi_init_registers(mddi);
+	mddi_writel(mddi->int_enable, INTEN);
+	mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
+	mddi_writel(MDDI_CMD_SEND_RTD, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+	mddi_set_auto_hibernate(&mddi->client_data, 1);
+}
+
+static int mddi_get_client_caps(struct mddi_info *mddi)
+{
+	int i, j;
+
+	/* clear any stale interrupts */
+	mddi_writel(0xffffffff, INT);
+
+	mddi->int_enable = MDDI_INT_LINK_ACTIVE |
+			   MDDI_INT_IN_HIBERNATION |
+			   MDDI_INT_PRI_LINK_LIST_DONE |
+			   MDDI_INT_REV_DATA_AVAIL |
+			   MDDI_INT_REV_OVERFLOW |
+			   MDDI_INT_REV_OVERWRITE |
+			   MDDI_INT_RTD_FAILURE;
+	mddi_writel(mddi->int_enable, INTEN);
+
+	mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+
+	for (j = 0; j < 3; j++) {
+		/* the toshiba vga panel does not respond to get
+		 * caps unless you SEND_RTD, but the first SEND_RTD
+		 * will fail...
+		 */
+		for (i = 0; i < 4; i++) {
+			uint32_t stat;
+
+			mddi_writel(MDDI_CMD_SEND_RTD, CMD);
+			mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+			stat = mddi_readl(STAT);
+			printk(KERN_INFO "mddi cmd send rtd: int %x, stat %x, "
+					"rtd val %x\n", mddi_readl(INT), stat,
+					mddi_readl(RTD_VAL));
+			if ((stat & MDDI_STAT_RTD_MEAS_FAIL) == 0)
+				break;
+			msleep(1);
+		}
+
+		mddi_writel(CMD_GET_CLIENT_CAP, CMD);
+		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+		wait_event_timeout(mddi->int_wait, mddi->flags & FLAG_HAVE_CAPS,
+				   HZ / 100);
+
+		if (mddi->flags & FLAG_HAVE_CAPS)
+			break;
+		printk(KERN_INFO "mddi_init, timeout waiting for caps\n");
+	}
+	return mddi->flags & FLAG_HAVE_CAPS;
+}
+
+/* link must be active when this is called */
+int mddi_check_status(struct mddi_info *mddi)
+{
+	int ret = -1, retry = 3;
+	mutex_lock(&mddi->reg_read_lock);
+	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+
+	do {
+		mddi->flags &= ~FLAG_HAVE_STATUS;
+		mddi_writel(CMD_GET_CLIENT_STATUS, CMD);
+		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+		wait_event_timeout(mddi->int_wait,
+				   mddi->flags & FLAG_HAVE_STATUS,
+				   HZ / 100);
+
+		if (mddi->flags & FLAG_HAVE_STATUS) {
+			if (mddi->status.crc_error_count)
+				printk(KERN_INFO "mddi status: crc_error "
+					"count: %d\n",
+					mddi->status.crc_error_count);
+			else
+				ret = 0;
+			break;
+		} else
+			printk(KERN_INFO "mddi status: failed to get client "
+				"status\n");
+		mddi_writel(MDDI_CMD_SEND_RTD, CMD);
+		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+	} while (--retry);
+
+	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+	mutex_unlock(&mddi->reg_read_lock);
+	return ret;
+}
+
+
+void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val,
+		       uint32_t reg)
+{
+	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
+					      client_data);
+	struct mddi_llentry *ll;
+	struct mddi_register_access *ra;
+
+	mutex_lock(&mddi->reg_write_lock);
+
+	ll = mddi->reg_write_data;
+
+	ra = &(ll->u.r);
+	ra->length = 14 + 4;
+	ra->type = TYPE_REGISTER_ACCESS;
+	ra->client_id = 0;
+	ra->read_write_info = MDDI_WRITE | 1;
+	ra->crc16 = 0;
+
+	ra->register_address = reg;
+	ra->register_data_list = val;
+
+	ll->flags = 1;
+	ll->header_count = 14;
+	ll->data_count = 4;
+	ll->data = mddi->reg_write_addr + offsetof(struct mddi_llentry,
+						   u.r.register_data_list);
+	ll->next = 0;
+	ll->reserved = 0;
+
+	mddi_writel(mddi->reg_write_addr, PRI_PTR);
+
+	mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
+	mutex_unlock(&mddi->reg_write_lock);
+}
+
+uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
+{
+	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
+					      client_data);
+	struct mddi_llentry *ll;
+	struct mddi_register_access *ra;
+	struct reg_read_info ri;
+	unsigned s;
+	int retry_count = 2;
+	unsigned long irq_flags;
+
+	mutex_lock(&mddi->reg_read_lock);
+
+	ll = mddi->reg_read_data;
+
+	ra = &(ll->u.r);
+	ra->length = 14;
+	ra->type = TYPE_REGISTER_ACCESS;
+	ra->client_id = 0;
+	ra->read_write_info = MDDI_READ | 1;
+	ra->crc16 = 0;
+
+	ra->register_address = reg;
+
+	ll->flags = 0x11;
+	ll->header_count = 14;
+	ll->data_count = 0;
+	ll->data = 0;
+	ll->next = 0;
+	ll->reserved = 0;
+
+	s = mddi_readl(STAT);
+
+	ri.reg = reg;
+	ri.status = -1;
+
+	do {
+		init_completion(&ri.done);
+		mddi->reg_read = &ri;
+		mddi_writel(mddi->reg_read_addr, PRI_PTR);
+
+		mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
+
+		/* Enable Periodic Reverse Encapsulation. */
+		mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
+		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+		if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
+		    !ri.done.done) {
+			printk(KERN_INFO "mddi_remote_read(%x) timeout "
+					 "(%d %d %d)\n",
+			       reg, ri.status, ri.result, ri.done.done);
+			spin_lock_irqsave(&mddi->int_lock, irq_flags);
+			mddi->reg_read = NULL;
+			spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
+			ri.status = -1;
+			ri.result = -1;
+		}
+		if (ri.status == 0)
+			break;
+
+		mddi_writel(MDDI_CMD_SEND_RTD, CMD);
+		mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
+		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+		printk(KERN_INFO "mddi_remote_read: failed, sent "
+		       "MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
+		       "curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
+		       mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
+	} while (retry_count-- > 0);
+	/* Disable Periodic Reverse Encapsulation. */
+	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+	mddi->reg_read = NULL;
+	mutex_unlock(&mddi->reg_read_lock);
+	return ri.result;
+}
+
+static struct mddi_info mddi_info[2];
+
+static int mddi_clk_setup(struct platform_device *pdev, struct mddi_info *mddi,
+			  unsigned long clk_rate)
+{
+	int ret;
+
+	/* set up the clocks */
+	mddi->clk = clk_get(&pdev->dev, "mddi_clk");
+	if (IS_ERR(mddi->clk)) {
+		printk(KERN_INFO "mddi: failed to get clock\n");
+		return PTR_ERR(mddi->clk);
+	}
+	ret =  clk_enable(mddi->clk);
+	if (ret)
+		goto fail;
+	ret = clk_set_rate(mddi->clk, clk_rate);
+	if (ret)
+		goto fail;
+	return 0;
+
+fail:
+	clk_put(mddi->clk);
+	return ret;
+}
+
+static int __init mddi_rev_data_setup(struct mddi_info *mddi)
+{
+	void *dma;
+	dma_addr_t dma_addr;
+
+	/* set up dma buffer */
+	dma = dma_alloc_coherent(NULL, 0x1000, &dma_addr, GFP_KERNEL);
+	if (dma == 0)
+		return -ENOMEM;
+	mddi->rev_data = dma;
+	mddi->rev_data_curr = 0;
+	mddi->rev_addr = dma_addr;
+	mddi->reg_write_data = dma + MDDI_REV_BUFFER_SIZE;
+	mddi->reg_write_addr = dma_addr + MDDI_REV_BUFFER_SIZE;
+	mddi->reg_read_data = mddi->reg_write_data + 1;
+	mddi->reg_read_addr = mddi->reg_write_addr +
+			      sizeof(*mddi->reg_write_data);
+	return 0;
+}
+
+static int mddi_probe(struct platform_device *pdev)
+{
+	struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
+	struct mddi_info *mddi = &mddi_info[pdev->id];
+	struct resource *resource;
+	int ret, i;
+
+	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!resource) {
+		printk(KERN_ERR "mddi: no associated mem resource!\n");
+		return -ENOMEM;
+	}
+	mddi->base = ioremap(resource->start, resource_size(resource));
+	if (!mddi->base) {
+		printk(KERN_ERR "mddi: failed to remap base!\n");
+		ret = -EINVAL;
+		goto error_ioremap;
+	}
+	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!resource) {
+		printk(KERN_ERR "mddi: no associated irq resource!\n");
+		ret = -EINVAL;
+		goto error_get_irq_resource;
+	}
+	mddi->irq = resource->start;
+	printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
+	       mddi->irq);
+	mddi->power_client = pdata->power_client;
+
+	mutex_init(&mddi->reg_write_lock);
+	mutex_init(&mddi->reg_read_lock);
+	spin_lock_init(&mddi->int_lock);
+	init_waitqueue_head(&mddi->int_wait);
+
+	ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate);
+	if (ret) {
+		printk(KERN_ERR "mddi: failed to setup clock!\n");
+		goto error_clk_setup;
+	}
+
+	ret = mddi_rev_data_setup(mddi);
+	if (ret) {
+		printk(KERN_ERR "mddi: failed to setup rev data!\n");
+		goto error_rev_data;
+	}
+
+	mddi->int_enable = 0;
+	mddi_writel(mddi->int_enable, INTEN);
+	ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
+			  &mddi->client_data);
+	if (ret) {
+		printk(KERN_ERR "mddi: failed to request enable irq!\n");
+		goto error_request_irq;
+	}
+
+	/* turn on the mddi client bridge chip */
+	if (mddi->power_client)
+		mddi->power_client(&mddi->client_data, 1);
+
+	/* initialize the mddi registers */
+	mddi_set_auto_hibernate(&mddi->client_data, 0);
+	mddi_writel(MDDI_CMD_RESET, CMD);
+	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
+	mddi->version = mddi_init_registers(mddi);
+	if (mddi->version < 0x20) {
+		printk(KERN_ERR "mddi: unsupported version 0x%x\n",
+		       mddi->version);
+		ret = -ENODEV;
+		goto error_mddi_version;
+	}
+
+	/* read the capabilities off the client */
+	if (!mddi_get_client_caps(mddi)) {
+		printk(KERN_INFO "mddi: no client found\n");
+		/* power down the panel */
+		mddi_writel(MDDI_CMD_POWERDOWN, CMD);
+		printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
+		msleep(100);
+		printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
+		return 0;
+	}
+	mddi_set_auto_hibernate(&mddi->client_data, 1);
+
+	if (mddi->caps.Mfr_Name == 0 && mddi->caps.Product_Code == 0)
+		pdata->fixup(&mddi->caps.Mfr_Name, &mddi->caps.Product_Code);
+
+	mddi->client_pdev.id = 0;
+	for (i = 0; i < pdata->num_clients; i++) {
+		if (pdata->client_platform_data[i].product_id ==
+		    (mddi->caps.Mfr_Name << 16 | mddi->caps.Product_Code)) {
+			mddi->client_data.private_client_data =
+				pdata->client_platform_data[i].client_data;
+			mddi->client_pdev.name =
+				pdata->client_platform_data[i].name;
+			mddi->client_pdev.id =
+				pdata->client_platform_data[i].id;
+			/* XXX: possibly set clock */
+			break;
+		}
+	}
+
+	if (i >= pdata->num_clients)
+		mddi->client_pdev.name = "mddi_c_dummy";
+	printk(KERN_INFO "mddi: registering panel %s\n",
+		mddi->client_pdev.name);
+
+	mddi->client_data.suspend = mddi_suspend;
+	mddi->client_data.resume = mddi_resume;
+	mddi->client_data.activate_link = mddi_activate_link;
+	mddi->client_data.remote_write = mddi_remote_write;
+	mddi->client_data.remote_read = mddi_remote_read;
+	mddi->client_data.auto_hibernate = mddi_set_auto_hibernate;
+	mddi->client_data.fb_resource = pdata->fb_resource;
+	if (pdev->id == 0)
+		mddi->client_data.interface_type = MSM_MDDI_PMDH_INTERFACE;
+	else if (pdev->id == 1)
+		mddi->client_data.interface_type = MSM_MDDI_EMDH_INTERFACE;
+	else {
+		printk(KERN_ERR "mddi: can not determine interface %d!\n",
+		       pdev->id);
+		ret = -EINVAL;
+		goto error_mddi_interface;
+	}
+
+	mddi->client_pdev.dev.platform_data = &mddi->client_data;
+	printk(KERN_INFO "mddi: publish: %s\n", mddi->client_name);
+	platform_device_register(&mddi->client_pdev);
+	return 0;
+
+error_mddi_interface:
+error_mddi_version:
+	free_irq(mddi->irq, 0);
+error_request_irq:
+	dma_free_coherent(NULL, 0x1000, mddi->rev_data, mddi->rev_addr);
+error_rev_data:
+error_clk_setup:
+error_get_irq_resource:
+	iounmap(mddi->base);
+error_ioremap:
+
+	printk(KERN_INFO "mddi: mddi_init() failed (%d)\n", ret);
+	return ret;
+}
+
+
+static struct platform_driver mddi_driver = {
+	.probe = mddi_probe,
+	.driver = { .name = "msm_mddi" },
+};
+
+static int __init _mddi_init(void)
+{
+	return platform_driver_register(&mddi_driver);
+}
+
+module_init(_mddi_init);
diff --git a/drivers/video/fbdev/msm/mddi_client_dummy.c b/drivers/video/fbdev/msm/mddi_client_dummy.c
new file mode 100644
index 000000000000..f1b0dfcc9717
--- /dev/null
+++ b/drivers/video/fbdev/msm/mddi_client_dummy.c
@@ -0,0 +1,98 @@
+/* drivers/video/msm_fb/mddi_client_dummy.c
+ *
+ * Support for "dummy" mddi client devices which require no
+ * special initialization code.
+ *
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <linux/platform_data/video-msm_fb.h>
+
+struct panel_info {
+	struct platform_device pdev;
+	struct msm_panel_data panel_data;
+};
+
+static int mddi_dummy_suspend(struct msm_panel_data *panel_data)
+{
+	return 0;
+}
+
+static int mddi_dummy_resume(struct msm_panel_data *panel_data)
+{
+	return 0;
+}
+
+static int mddi_dummy_blank(struct msm_panel_data *panel_data)
+{
+	return 0;
+}
+
+static int mddi_dummy_unblank(struct msm_panel_data *panel_data)
+{
+	return 0;
+}
+
+static int mddi_dummy_probe(struct platform_device *pdev)
+{
+	struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
+	struct panel_info *panel =
+		kzalloc(sizeof(struct panel_info), GFP_KERNEL);
+	int ret;
+	if (!panel)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, panel);
+	panel->panel_data.suspend = mddi_dummy_suspend;
+	panel->panel_data.resume = mddi_dummy_resume;
+	panel->panel_data.blank = mddi_dummy_blank;
+	panel->panel_data.unblank = mddi_dummy_unblank;
+	panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
+	panel->pdev.name = "msm_panel";
+	panel->pdev.id = pdev->id;
+	platform_device_add_resources(&panel->pdev,
+				      client_data->fb_resource, 1);
+	panel->panel_data.fb_data = client_data->private_client_data;
+	panel->pdev.dev.platform_data = &panel->panel_data;
+	ret = platform_device_register(&panel->pdev);
+	if (ret) {
+		kfree(panel);
+		return ret;
+	}
+	return 0;
+}
+
+static int mddi_dummy_remove(struct platform_device *pdev)
+{
+	struct panel_info *panel = platform_get_drvdata(pdev);
+	kfree(panel);
+	return 0;
+}
+
+static struct platform_driver mddi_client_dummy = {
+	.probe = mddi_dummy_probe,
+	.remove = mddi_dummy_remove,
+	.driver = { .name = "mddi_c_dummy" },
+};
+
+static int __init mddi_client_dummy_init(void)
+{
+	platform_driver_register(&mddi_client_dummy);
+	return 0;
+}
+
+module_init(mddi_client_dummy_init);
+
diff --git a/drivers/video/fbdev/msm/mddi_client_nt35399.c b/drivers/video/fbdev/msm/mddi_client_nt35399.c
new file mode 100644
index 000000000000..f96df32e5509
--- /dev/null
+++ b/drivers/video/fbdev/msm/mddi_client_nt35399.c
@@ -0,0 +1,252 @@
+/* drivers/video/msm_fb/mddi_client_nt35399.c
+ *
+ * Support for Novatek NT35399 MDDI client of Sapphire
+ *
+ * Copyright (C) 2008 HTC Incorporated
+ * Author: Solomon Chiu (solomon_chiu@htc.com)
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_data/video-msm_fb.h>
+
+static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
+
+struct panel_info {
+	struct msm_mddi_client_data *client_data;
+	struct platform_device pdev;
+	struct msm_panel_data panel_data;
+	struct msmfb_callback *fb_callback;
+	struct work_struct panel_work;
+	struct workqueue_struct *fb_wq;
+	int nt35399_got_int;
+};
+
+static void
+nt35399_request_vsync(struct msm_panel_data *panel_data,
+		      struct msmfb_callback *callback)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	panel->fb_callback = callback;
+	if (panel->nt35399_got_int) {
+		panel->nt35399_got_int = 0;
+		client_data->activate_link(client_data); /* clears interrupt */
+	}
+}
+
+static void nt35399_wait_vsync(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	if (panel->nt35399_got_int) {
+		panel->nt35399_got_int = 0;
+		client_data->activate_link(client_data); /* clears interrupt */
+	}
+
+	if (wait_event_timeout(nt35399_vsync_wait, panel->nt35399_got_int,
+				HZ/2) == 0)
+		printk(KERN_ERR "timeout waiting for VSYNC\n");
+
+	panel->nt35399_got_int = 0;
+	/* interrupt clears when screen dma starts */
+}
+
+static int nt35399_suspend(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+	int ret;
+
+	ret = bridge_data->uninit(bridge_data, client_data);
+	if (ret) {
+		printk(KERN_INFO "mddi nt35399 client: non zero return from "
+			"uninit\n");
+		return ret;
+	}
+	client_data->suspend(client_data);
+	return 0;
+}
+
+static int nt35399_resume(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+	int ret;
+
+	client_data->resume(client_data);
+	ret = bridge_data->init(bridge_data, client_data);
+	if (ret)
+		return ret;
+	return 0;
+}
+
+static int nt35399_blank(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+
+	return bridge_data->blank(bridge_data, client_data);
+}
+
+static int nt35399_unblank(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+
+	return bridge_data->unblank(bridge_data, client_data);
+}
+
+irqreturn_t nt35399_vsync_interrupt(int irq, void *data)
+{
+	struct panel_info *panel = data;
+
+	panel->nt35399_got_int = 1;
+
+	if (panel->fb_callback) {
+		panel->fb_callback->func(panel->fb_callback);
+		panel->fb_callback = NULL;
+	}
+
+	wake_up(&nt35399_vsync_wait);
+
+	return IRQ_HANDLED;
+}
+
+static int setup_vsync(struct panel_info *panel, int init)
+{
+	int ret;
+	int gpio = 97;
+	unsigned int irq;
+
+	if (!init) {
+		ret = 0;
+		goto uninit;
+	}
+	ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
+	if (ret)
+		goto err_request_gpio_failed;
+
+	ret = irq = gpio_to_irq(gpio);
+	if (ret < 0)
+		goto err_get_irq_num_failed;
+
+	ret = request_irq(irq, nt35399_vsync_interrupt, IRQF_TRIGGER_RISING,
+			  "vsync", panel);
+	if (ret)
+		goto err_request_irq_failed;
+
+	printk(KERN_INFO "vsync on gpio %d now %d\n",
+	       gpio, gpio_get_value(gpio));
+	return 0;
+
+uninit:
+	free_irq(gpio_to_irq(gpio), panel->client_data);
+err_request_irq_failed:
+err_get_irq_num_failed:
+	gpio_free(gpio);
+err_request_gpio_failed:
+	return ret;
+}
+
+static int mddi_nt35399_probe(struct platform_device *pdev)
+{
+	struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+
+	int ret;
+
+	struct panel_info *panel = devm_kzalloc(&pdev->dev,
+						sizeof(struct panel_info),
+						GFP_KERNEL);
+
+	printk(KERN_DEBUG "%s: enter.\n", __func__);
+
+	if (!panel)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, panel);
+
+	ret = setup_vsync(panel, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "mddi_nt35399_setup_vsync failed\n");
+		return ret;
+	}
+
+	panel->client_data = client_data;
+	panel->panel_data.suspend = nt35399_suspend;
+	panel->panel_data.resume = nt35399_resume;
+	panel->panel_data.wait_vsync = nt35399_wait_vsync;
+	panel->panel_data.request_vsync = nt35399_request_vsync;
+	panel->panel_data.blank = nt35399_blank;
+	panel->panel_data.unblank = nt35399_unblank;
+	panel->panel_data.fb_data = &bridge_data->fb_data;
+	panel->panel_data.caps = 0;
+
+	panel->pdev.name = "msm_panel";
+	panel->pdev.id = pdev->id;
+	panel->pdev.resource = client_data->fb_resource;
+	panel->pdev.num_resources = 1;
+	panel->pdev.dev.platform_data = &panel->panel_data;
+
+	if (bridge_data->init)
+		bridge_data->init(bridge_data, client_data);
+
+	platform_device_register(&panel->pdev);
+
+	return 0;
+}
+
+static int mddi_nt35399_remove(struct platform_device *pdev)
+{
+	struct panel_info *panel = platform_get_drvdata(pdev);
+
+	setup_vsync(panel, 0);
+	return 0;
+}
+
+static struct platform_driver mddi_client_0bda_8a47 = {
+	.probe = mddi_nt35399_probe,
+	.remove = mddi_nt35399_remove,
+	.driver = { .name = "mddi_c_0bda_8a47" },
+};
+
+static int __init mddi_client_nt35399_init(void)
+{
+	return platform_driver_register(&mddi_client_0bda_8a47);
+}
+
+module_init(mddi_client_nt35399_init);
+
diff --git a/drivers/video/fbdev/msm/mddi_client_toshiba.c b/drivers/video/fbdev/msm/mddi_client_toshiba.c
new file mode 100644
index 000000000000..061d7dfebbf3
--- /dev/null
+++ b/drivers/video/fbdev/msm/mddi_client_toshiba.c
@@ -0,0 +1,280 @@
+/* drivers/video/msm_fb/mddi_client_toshiba.c
+ *
+ * Support for Toshiba TC358720XBG mddi client devices which require no
+ * special initialization code.
+ *
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/platform_data/video-msm_fb.h>
+
+
+#define LCD_CONTROL_BLOCK_BASE 0x110000
+#define CMN         (LCD_CONTROL_BLOCK_BASE|0x10)
+#define INTFLG      (LCD_CONTROL_BLOCK_BASE|0x18)
+#define HCYCLE      (LCD_CONTROL_BLOCK_BASE|0x34)
+#define HDE_START   (LCD_CONTROL_BLOCK_BASE|0x3C)
+#define VPOS        (LCD_CONTROL_BLOCK_BASE|0xC0)
+#define MPLFBUF     (LCD_CONTROL_BLOCK_BASE|0x20)
+#define WAKEUP      (LCD_CONTROL_BLOCK_BASE|0x54)
+#define WSYN_DLY    (LCD_CONTROL_BLOCK_BASE|0x58)
+#define REGENB      (LCD_CONTROL_BLOCK_BASE|0x5C)
+
+#define BASE5 0x150000
+#define BASE6 0x160000
+#define BASE7 0x170000
+
+#define GPIOIEV     (BASE5 + 0x10)
+#define GPIOIE      (BASE5 + 0x14)
+#define GPIORIS     (BASE5 + 0x18)
+#define GPIOMIS     (BASE5 + 0x1C)
+#define GPIOIC      (BASE5 + 0x20)
+
+#define INTMASK     (BASE6 + 0x0C)
+#define INTMASK_VWAKEOUT (1U << 0)
+#define INTMASK_VWAKEOUT_ACTIVE_LOW (1U << 8)
+#define GPIOSEL     (BASE7 + 0x00)
+#define GPIOSEL_VWAKEINT (1U << 0)
+
+static DECLARE_WAIT_QUEUE_HEAD(toshiba_vsync_wait);
+
+struct panel_info {
+	struct msm_mddi_client_data *client_data;
+	struct platform_device pdev;
+	struct msm_panel_data panel_data;
+	struct msmfb_callback *toshiba_callback;
+	int toshiba_got_int;
+};
+
+
+static void toshiba_request_vsync(struct msm_panel_data *panel_data,
+				  struct msmfb_callback *callback)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	panel->toshiba_callback = callback;
+	if (panel->toshiba_got_int) {
+		panel->toshiba_got_int = 0;
+		client_data->activate_link(client_data);
+	}
+}
+
+static void toshiba_clear_vsync(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	client_data->activate_link(client_data);
+}
+
+static void toshiba_wait_vsync(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	if (panel->toshiba_got_int) {
+		panel->toshiba_got_int = 0;
+		client_data->activate_link(client_data); /* clears interrupt */
+	}
+	if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int,
+				HZ/2) == 0)
+		printk(KERN_ERR "timeout waiting for VSYNC\n");
+	panel->toshiba_got_int = 0;
+	/* interrupt clears when screen dma starts */
+}
+
+static int toshiba_suspend(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+	int ret;
+
+	ret = bridge_data->uninit(bridge_data, client_data);
+	if (ret) {
+		printk(KERN_INFO "mddi toshiba client: non zero return from "
+			"uninit\n");
+		return ret;
+	}
+	client_data->suspend(client_data);
+	return 0;
+}
+
+static int toshiba_resume(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+	int ret;
+
+	client_data->resume(client_data);
+	ret = bridge_data->init(bridge_data, client_data);
+	if (ret)
+		return ret;
+	return 0;
+}
+
+static int toshiba_blank(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+
+	return bridge_data->blank(bridge_data, client_data);
+}
+
+static int toshiba_unblank(struct msm_panel_data *panel_data)
+{
+	struct panel_info *panel = container_of(panel_data, struct panel_info,
+						panel_data);
+	struct msm_mddi_client_data *client_data = panel->client_data;
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+
+	return bridge_data->unblank(bridge_data, client_data);
+}
+
+irqreturn_t toshiba_vsync_interrupt(int irq, void *data)
+{
+	struct panel_info *panel = data;
+
+	panel->toshiba_got_int = 1;
+	if (panel->toshiba_callback) {
+		panel->toshiba_callback->func(panel->toshiba_callback);
+		panel->toshiba_callback = 0;
+	}
+	wake_up(&toshiba_vsync_wait);
+	return IRQ_HANDLED;
+}
+
+static int setup_vsync(struct panel_info *panel,
+		       int init)
+{
+	int ret;
+	int gpio = 97;
+	unsigned int irq;
+
+	if (!init) {
+		ret = 0;
+		goto uninit;
+	}
+	ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
+	if (ret)
+		goto err_request_gpio_failed;
+
+	ret = irq = gpio_to_irq(gpio);
+	if (ret < 0)
+		goto err_get_irq_num_failed;
+
+	ret = request_irq(irq, toshiba_vsync_interrupt, IRQF_TRIGGER_RISING,
+			  "vsync", panel);
+	if (ret)
+		goto err_request_irq_failed;
+	printk(KERN_INFO "vsync on gpio %d now %d\n",
+	       gpio, gpio_get_value(gpio));
+	return 0;
+
+uninit:
+	free_irq(gpio_to_irq(gpio), panel);
+err_request_irq_failed:
+err_get_irq_num_failed:
+	gpio_free(gpio);
+err_request_gpio_failed:
+	return ret;
+}
+
+static int mddi_toshiba_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
+	struct msm_mddi_bridge_platform_data *bridge_data =
+		client_data->private_client_data;
+	struct panel_info *panel =
+		kzalloc(sizeof(struct panel_info), GFP_KERNEL);
+	if (!panel)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, panel);
+
+	/* mddi_remote_write(mddi, 0, WAKEUP); */
+	client_data->remote_write(client_data, GPIOSEL_VWAKEINT, GPIOSEL);
+	client_data->remote_write(client_data, INTMASK_VWAKEOUT, INTMASK);
+
+	ret = setup_vsync(panel, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
+		return ret;
+	}
+
+	panel->client_data = client_data;
+	panel->panel_data.suspend = toshiba_suspend;
+	panel->panel_data.resume = toshiba_resume;
+	panel->panel_data.wait_vsync = toshiba_wait_vsync;
+	panel->panel_data.request_vsync = toshiba_request_vsync;
+	panel->panel_data.clear_vsync = toshiba_clear_vsync;
+	panel->panel_data.blank = toshiba_blank;
+	panel->panel_data.unblank = toshiba_unblank;
+	panel->panel_data.fb_data =  &bridge_data->fb_data;
+	panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
+
+	panel->pdev.name = "msm_panel";
+	panel->pdev.id = pdev->id;
+	panel->pdev.resource = client_data->fb_resource;
+	panel->pdev.num_resources = 1;
+	panel->pdev.dev.platform_data = &panel->panel_data;
+	bridge_data->init(bridge_data, client_data);
+	platform_device_register(&panel->pdev);
+
+	return 0;
+}
+
+static int mddi_toshiba_remove(struct platform_device *pdev)
+{
+	struct panel_info *panel = platform_get_drvdata(pdev);
+
+	setup_vsync(panel, 0);
+	kfree(panel);
+	return 0;
+}
+
+static struct platform_driver mddi_client_d263_0000 = {
+	.probe = mddi_toshiba_probe,
+	.remove = mddi_toshiba_remove,
+	.driver = { .name = "mddi_c_d263_0000" },
+};
+
+static int __init mddi_client_toshiba_init(void)
+{
+	platform_driver_register(&mddi_client_d263_0000);
+	return 0;
+}
+
+module_init(mddi_client_toshiba_init);
+
diff --git a/drivers/video/fbdev/msm/mddi_hw.h b/drivers/video/fbdev/msm/mddi_hw.h
new file mode 100644
index 000000000000..45cc01fc1e7f
--- /dev/null
+++ b/drivers/video/fbdev/msm/mddi_hw.h
@@ -0,0 +1,305 @@
+/* drivers/video/msm_fb/mddi_hw.h
+ *
+ * MSM MDDI Hardware Registers and Structures
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MDDI_HW_H_
+#define _MDDI_HW_H_
+
+#include <linux/types.h>
+
+#define MDDI_CMD                0x0000
+#define MDDI_VERSION            0x0004
+#define MDDI_PRI_PTR            0x0008
+#define MDDI_SEC_PTR            0x000c
+#define MDDI_BPS                0x0010
+#define MDDI_SPM                0x0014
+#define MDDI_INT                0x0018
+#define MDDI_INTEN              0x001c
+#define MDDI_REV_PTR            0x0020
+#define MDDI_REV_SIZE           0x0024
+#define MDDI_STAT               0x0028
+#define MDDI_REV_RATE_DIV       0x002c
+#define MDDI_REV_CRC_ERR        0x0030
+#define MDDI_TA1_LEN            0x0034
+#define MDDI_TA2_LEN            0x0038
+#define MDDI_TEST_BUS           0x003c
+#define MDDI_TEST               0x0040
+#define MDDI_REV_PKT_CNT        0x0044
+#define MDDI_DRIVE_HI           0x0048
+#define MDDI_DRIVE_LO           0x004c
+#define MDDI_DISP_WAKE          0x0050
+#define MDDI_REV_ENCAP_SZ       0x0054
+#define MDDI_RTD_VAL            0x0058
+#define MDDI_PAD_CTL            0x0068
+#define MDDI_DRIVER_START_CNT   0x006c
+#define MDDI_NEXT_PRI_PTR       0x0070
+#define MDDI_NEXT_SEC_PTR       0x0074
+#define MDDI_MISR_CTL           0x0078
+#define MDDI_MISR_DATA          0x007c
+#define MDDI_SF_CNT             0x0080
+#define MDDI_MF_CNT             0x0084
+#define MDDI_CURR_REV_PTR       0x0088
+#define MDDI_CORE_VER           0x008c
+
+#define MDDI_INT_PRI_PTR_READ       0x0001
+#define MDDI_INT_SEC_PTR_READ       0x0002
+#define MDDI_INT_REV_DATA_AVAIL     0x0004
+#define MDDI_INT_DISP_REQ           0x0008
+#define MDDI_INT_PRI_UNDERFLOW      0x0010
+#define MDDI_INT_SEC_UNDERFLOW      0x0020
+#define MDDI_INT_REV_OVERFLOW       0x0040
+#define MDDI_INT_CRC_ERROR          0x0080
+#define MDDI_INT_MDDI_IN            0x0100
+#define MDDI_INT_PRI_OVERWRITE      0x0200
+#define MDDI_INT_SEC_OVERWRITE      0x0400
+#define MDDI_INT_REV_OVERWRITE      0x0800
+#define MDDI_INT_DMA_FAILURE        0x1000
+#define MDDI_INT_LINK_ACTIVE        0x2000
+#define MDDI_INT_IN_HIBERNATION     0x4000
+#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
+#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
+#define MDDI_INT_NO_CMD_PKTS_PEND   0x20000
+#define MDDI_INT_RTD_FAILURE        0x40000
+#define MDDI_INT_REV_PKT_RECEIVED   0x80000
+#define MDDI_INT_REV_PKTS_AVAIL     0x100000
+
+#define MDDI_INT_NEED_CLEAR ( \
+	MDDI_INT_REV_DATA_AVAIL | \
+	MDDI_INT_PRI_UNDERFLOW | \
+	MDDI_INT_SEC_UNDERFLOW | \
+	MDDI_INT_REV_OVERFLOW | \
+	MDDI_INT_CRC_ERROR | \
+	MDDI_INT_REV_PKT_RECEIVED)
+
+
+#define MDDI_STAT_LINK_ACTIVE        0x0001
+#define MDDI_STAT_NEW_REV_PTR        0x0002
+#define MDDI_STAT_NEW_PRI_PTR        0x0004
+#define MDDI_STAT_NEW_SEC_PTR        0x0008
+#define MDDI_STAT_IN_HIBERNATION     0x0010
+#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
+#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
+#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
+#define MDDI_STAT_PENDING_REV_ENCAP  0x0100
+#define MDDI_STAT_PENDING_POWERDOWN  0x0200
+#define MDDI_STAT_RTD_MEAS_FAIL      0x0800
+#define MDDI_STAT_CLIENT_WAKEUP_REQ  0x1000
+
+
+#define MDDI_CMD_POWERDOWN           0x0100
+#define MDDI_CMD_POWERUP             0x0200
+#define MDDI_CMD_HIBERNATE           0x0300
+#define MDDI_CMD_RESET               0x0400
+#define MDDI_CMD_DISP_IGNORE         0x0501
+#define MDDI_CMD_DISP_LISTEN         0x0500
+#define MDDI_CMD_SEND_REV_ENCAP      0x0600
+#define MDDI_CMD_GET_CLIENT_CAP      0x0601
+#define MDDI_CMD_GET_CLIENT_STATUS   0x0602
+#define MDDI_CMD_SEND_RTD            0x0700
+#define MDDI_CMD_LINK_ACTIVE         0x0900
+#define MDDI_CMD_PERIODIC_REV_ENCAP  0x0A00
+#define MDDI_CMD_FORCE_NEW_REV_PTR   0x0C00
+
+
+
+#define MDDI_VIDEO_REV_PKT_SIZE              0x40
+#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE  0x60
+#define MDDI_MAX_REV_PKT_SIZE                0x60
+
+/* #define MDDI_REV_BUFFER_SIZE 128 */
+#define MDDI_REV_BUFFER_SIZE (MDDI_MAX_REV_PKT_SIZE * 4)
+
+/* MDP sends 256 pixel packets, so lower value hibernates more without
+ * significantly increasing latency of waiting for next subframe */
+#define MDDI_HOST_BYTES_PER_SUBFRAME  0x3C00
+#define MDDI_HOST_TA2_LEN       0x000c
+#define MDDI_HOST_REV_RATE_DIV  0x0002
+
+
+struct __attribute__((packed)) mddi_rev_packet {
+	uint16_t length;
+	uint16_t type;
+	uint16_t client_id;
+};
+
+struct __attribute__((packed)) mddi_client_status {
+	uint16_t length;
+	uint16_t type;
+	uint16_t client_id;
+	uint16_t reverse_link_request;  /* bytes needed in rev encap message */
+	uint8_t  crc_error_count;
+	uint8_t  capability_change;
+	uint16_t graphics_busy_flags;
+	uint16_t crc16;
+};
+
+struct __attribute__((packed)) mddi_client_caps {
+	uint16_t length; /* length, exclusive of this field */
+	uint16_t type; /* 66 */
+	uint16_t client_id;
+
+	uint16_t Protocol_Version;
+	uint16_t Minimum_Protocol_Version;
+	uint16_t Data_Rate_Capability;
+	uint8_t  Interface_Type_Capability;
+	uint8_t  Number_of_Alt_Displays;
+	uint16_t PostCal_Data_Rate;
+	uint16_t Bitmap_Width;
+	uint16_t Bitmap_Height;
+	uint16_t Display_Window_Width;
+	uint16_t Display_Window_Height;
+	uint32_t Color_Map_Size;
+	uint16_t Color_Map_RGB_Width;
+	uint16_t RGB_Capability;
+	uint8_t  Monochrome_Capability;
+	uint8_t  Reserved_1;
+	uint16_t Y_Cb_Cr_Capability;
+	uint16_t Bayer_Capability;
+	uint16_t Alpha_Cursor_Image_Planes;
+	uint32_t Client_Feature_Capability_Indicators;
+	uint8_t  Maximum_Video_Frame_Rate_Capability;
+	uint8_t  Minimum_Video_Frame_Rate_Capability;
+	uint16_t Minimum_Sub_frame_Rate;
+	uint16_t Audio_Buffer_Depth;
+	uint16_t Audio_Channel_Capability;
+	uint16_t Audio_Sample_Rate_Capability;
+	uint8_t  Audio_Sample_Resolution;
+	uint8_t  Mic_Audio_Sample_Resolution;
+	uint16_t Mic_Sample_Rate_Capability;
+	uint8_t  Keyboard_Data_Format;
+	uint8_t  pointing_device_data_format;
+	uint16_t content_protection_type;
+	uint16_t Mfr_Name;
+	uint16_t Product_Code;
+	uint16_t Reserved_3;
+	uint32_t Serial_Number;
+	uint8_t  Week_of_Manufacture;
+	uint8_t  Year_of_Manufacture;
+
+	uint16_t crc16;
+} mddi_client_capability_type;
+
+
+struct __attribute__((packed)) mddi_video_stream {
+	uint16_t length;
+	uint16_t type; /* 16 */
+	uint16_t client_id; /* 0 */
+
+	uint16_t video_data_format_descriptor;
+/* format of each pixel in the Pixel Data in the present stream in the
+ * present packet.
+ * If bits [15:13] = 000 monochrome
+ * If bits [15:13] = 001 color pixels (palette).
+ * If bits [15:13] = 010 color pixels in raw RGB
+ * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
+ * If bits [15:13] = 100 Bayer pixels
+ */
+
+	uint16_t pixel_data_attributes;
+/* interpreted as follows:
+ * Bits [1:0] = 11  pixel data is displayed to both eyes
+ * Bits [1:0] = 10  pixel data is routed to the left eye only.
+ * Bits [1:0] = 01  pixel data is routed to the right eye only.
+ * Bits [1:0] = 00  pixel data is routed to the alternate display.
+ * Bit 2 is 0  Pixel Data is in the standard progressive format.
+ * Bit 2 is 1  Pixel Data is in interlace format.
+ * Bit 3 is 0  Pixel Data is in the standard progressive format.
+ * Bit 3 is 1  Pixel Data is in alternate pixel format.
+ * Bit 4 is 0  Pixel Data is to or from the display frame buffer.
+ * Bit 4 is 1  Pixel Data is to or from the camera.
+ * Bit 5 is 0  pixel data contains the next consecutive row of pixels.
+ * Bit 5 is 1  X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
+ *             X Start, and Y Start parameters are not defined and
+ *             shall be ignored by the client.
+ * Bits [7:6] = 01  Pixel data is written to the offline image buffer.
+ * Bits [7:6] = 00  Pixel data is written to the buffer to refresh display.
+ * Bits [7:6] = 11  Pixel data is written to all image buffers.
+ * Bits [7:6] = 10  Invalid. Reserved for future use.
+ * Bits 8 through 11 alternate display number.
+ * Bits 12 through 14 are reserved for future use and shall be set to zero.
+ * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
+ */
+
+	uint16_t x_left_edge;
+	uint16_t y_top_edge;
+	/* X,Y coordinate of the top left edge of the screen window */
+
+	uint16_t x_right_edge;
+	uint16_t y_bottom_edge;
+	/* X,Y coordinate of the bottom right edge of the window being
+	 * updated. */
+
+	uint16_t x_start;
+	uint16_t y_start;
+	/* (X Start, Y Start) is the first pixel in the Pixel Data field
+	 * below. */
+
+	uint16_t pixel_count;
+	/* number of pixels in the Pixel Data field below. */
+
+	uint16_t parameter_CRC;
+	/* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
+
+	uint16_t reserved;
+	/* 16-bit variable to make structure align on 4 byte boundary */
+};
+
+#define TYPE_VIDEO_STREAM      16
+#define TYPE_CLIENT_CAPS       66
+#define TYPE_REGISTER_ACCESS   146
+#define TYPE_CLIENT_STATUS     70
+
+struct __attribute__((packed)) mddi_register_access {
+	uint16_t length;
+	uint16_t type; /* 146 */
+	uint16_t client_id;
+
+	uint16_t read_write_info;
+	/* Bits 13:0  a 14-bit unsigned integer that specifies the number of
+	 *            32-bit Register Data List items to be transferred in the
+	 *            Register Data List field.
+	 * Bits[15:14] = 00  Write to register(s);
+	 * Bits[15:14] = 10  Read from register(s);
+	 * Bits[15:14] = 11  Response to a Read.
+	 * Bits[15:14] = 01  this value is reserved for future use. */
+#define MDDI_WRITE     (0 << 14)
+#define MDDI_READ      (2 << 14)
+#define MDDI_READ_RESP (3 << 14)
+
+	uint32_t register_address;
+	/* the register address that is to be written to or read from. */
+
+	uint16_t crc16;
+
+	uint32_t register_data_list;
+	/* list of 4-byte register data values for/from client registers */
+};
+
+struct __attribute__((packed)) mddi_llentry {
+	uint16_t flags;
+	uint16_t header_count;
+	uint16_t data_count;
+	dma_addr_t data; /* 32 bit */
+	struct mddi_llentry *next;
+	uint16_t reserved;
+	union {
+		struct mddi_video_stream v;
+		struct mddi_register_access r;
+		uint32_t _[12];
+	} u;
+};
+
+#endif
diff --git a/drivers/video/fbdev/msm/mdp.c b/drivers/video/fbdev/msm/mdp.c
new file mode 100644
index 000000000000..113c7876c855
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdp.c
@@ -0,0 +1,520 @@
+/* drivers/video/msm_fb/mdp.c
+ *
+ * MSM MDP Interface (used by framebuffer core)
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/clk.h>
+#include <linux/file.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+
+#include <linux/platform_data/video-msm_fb.h>
+#include <linux/platform_device.h>
+#include <linux/export.h>
+
+#include "mdp_hw.h"
+
+struct class *mdp_class;
+
+#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
+
+static uint16_t mdp_default_ccs[] = {
+	0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
+	0x010, 0x080, 0x080
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
+static struct msmfb_callback *dma_callback;
+static struct clk *clk;
+static unsigned int mdp_irq_mask;
+static DEFINE_SPINLOCK(mdp_lock);
+DEFINE_MUTEX(mdp_mutex);
+
+static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
+{
+	unsigned long irq_flags;
+	int ret = 0;
+
+	BUG_ON(!mask);
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	/* if the mask bits are already set return an error, this interrupt
+	 * is already enabled */
+	if (mdp_irq_mask & mask) {
+		printk(KERN_ERR "mdp irq already on already on %x %x\n",
+		       mdp_irq_mask, mask);
+		ret = -1;
+	}
+	/* if the mdp irq is not already enabled enable it */
+	if (!mdp_irq_mask) {
+		if (clk)
+			clk_enable(clk);
+		enable_irq(mdp->irq);
+	}
+
+	/* update the irq mask to reflect the fact that the interrupt is
+	 * enabled */
+	mdp_irq_mask |= mask;
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+	return ret;
+}
+
+static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
+{
+	/* this interrupt is already disabled! */
+	if (!(mdp_irq_mask & mask)) {
+		printk(KERN_ERR "mdp irq already off %x %x\n",
+		       mdp_irq_mask, mask);
+		return -1;
+	}
+	/* update the irq mask to reflect the fact that the interrupt is
+	 * disabled */
+	mdp_irq_mask &= ~(mask);
+	/* if no one is waiting on the interrupt, disable it */
+	if (!mdp_irq_mask) {
+		disable_irq_nosync(mdp->irq);
+		if (clk)
+			clk_disable(clk);
+	}
+	return 0;
+}
+
+static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
+{
+	unsigned long irq_flags;
+	int ret;
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	ret = locked_disable_mdp_irq(mdp, mask);
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+	return ret;
+}
+
+static irqreturn_t mdp_isr(int irq, void *data)
+{
+	uint32_t status;
+	unsigned long irq_flags;
+	struct mdp_info *mdp = data;
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+
+	status = mdp_readl(mdp, MDP_INTR_STATUS);
+	mdp_writel(mdp, status, MDP_INTR_CLEAR);
+
+	status &= mdp_irq_mask;
+	if (status & DL0_DMA2_TERM_DONE) {
+		if (dma_callback) {
+			dma_callback->func(dma_callback);
+			dma_callback = NULL;
+		}
+		wake_up(&mdp_dma2_waitqueue);
+	}
+
+	if (status & DL0_ROI_DONE)
+		wake_up(&mdp_ppp_waitqueue);
+
+	if (status)
+		locked_disable_mdp_irq(mdp, status);
+
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+	return IRQ_HANDLED;
+}
+
+static uint32_t mdp_check_mask(uint32_t mask)
+{
+	uint32_t ret;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	ret = mdp_irq_mask & mask;
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+	return ret;
+}
+
+static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
+{
+	int ret = 0;
+	unsigned long irq_flags;
+
+	wait_event_timeout(*wq, !mdp_check_mask(mask), HZ);
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	if (mdp_irq_mask & mask) {
+		locked_disable_mdp_irq(mdp, mask);
+		printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
+		       mask);
+		ret = -ETIMEDOUT;
+	}
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+
+	return ret;
+}
+
+void mdp_dma_wait(struct mdp_device *mdp_dev)
+{
+#define MDP_MAX_TIMEOUTS 20
+	static int timeout_count;
+	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+
+	if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT)
+		timeout_count++;
+	else
+		timeout_count = 0;
+
+	if (timeout_count > MDP_MAX_TIMEOUTS) {
+		printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n",
+		       MDP_MAX_TIMEOUTS);
+		BUG();
+	}
+}
+
+static int mdp_ppp_wait(struct mdp_info *mdp)
+{
+	return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
+}
+
+void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
+		     uint32_t width, uint32_t height, uint32_t x, uint32_t y,
+		     struct msmfb_callback *callback)
+{
+	uint32_t dma2_cfg;
+	uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
+
+	if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) {
+		printk(KERN_ERR "mdp_dma_to_mddi: busy\n");
+		return;
+	}
+
+	dma_callback = callback;
+
+	dma2_cfg = DMA_PACK_TIGHT |
+		DMA_PACK_ALIGN_LSB |
+		DMA_PACK_PATTERN_RGB |
+		DMA_OUT_SEL_AHB |
+		DMA_IBUF_NONCONTIGUOUS;
+
+	dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
+
+	dma2_cfg |= DMA_OUT_SEL_MDDI;
+
+	dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
+
+	dma2_cfg |= DMA_DITHER_EN;
+
+	/* setup size, address, and stride */
+	mdp_writel(mdp, (height << 16) | (width),
+		   MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
+	mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
+	mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
+
+	/* 666 18BPP */
+	dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+
+	/* set y & x offset and MDDI transaction parameters */
+	mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
+	mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
+	mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
+		   MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
+
+	mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
+
+	/* start DMA2 */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
+}
+
+void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
+	     uint32_t width, uint32_t height, uint32_t x, uint32_t y,
+	     struct msmfb_callback *callback, int interface)
+{
+	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+
+	if (interface == MSM_MDDI_PMDH_INTERFACE) {
+		mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y,
+				callback);
+	}
+}
+
+int get_img(struct mdp_img *img, struct fb_info *info,
+	    unsigned long *start, unsigned long *len,
+	    struct file **filep)
+{
+	int ret = 0;
+	struct fd f = fdget(img->memory_id);
+	if (f.file == NULL)
+		return -1;
+
+	if (MAJOR(file_inode(f.file)->i_rdev) == FB_MAJOR) {
+		*start = info->fix.smem_start;
+		*len = info->fix.smem_len;
+	} else
+		ret = -1;
+	fdput(f);
+
+	return ret;
+}
+
+void put_img(struct file *src_file, struct file *dst_file)
+{
+}
+
+int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
+	     struct mdp_blit_req *req)
+{
+	int ret;
+	unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
+	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+	struct file *src_file = 0, *dst_file = 0;
+
+	/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
+	if (unlikely(req->src_rect.h == 0 ||
+		     req->src_rect.w == 0)) {
+		printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
+		return -EINVAL;
+	}
+	if (unlikely(req->dst_rect.h == 0 ||
+		     req->dst_rect.w == 0))
+		return -EINVAL;
+
+	/* do this first so that if this fails, the caller can always
+	 * safely call put_img */
+	if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
+		printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
+				"memory\n");
+		return -EINVAL;
+	}
+
+	if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
+		printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
+				"memory\n");
+		return -EINVAL;
+	}
+	mutex_lock(&mdp_mutex);
+
+	/* transp_masking unimplemented */
+	req->transp_mask = MDP_TRANSP_NOP;
+	if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
+		      req->alpha != MDP_ALPHA_NOP ||
+		      HAS_ALPHA(req->src.format)) &&
+		     (req->flags & MDP_ROT_90 &&
+		      req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
+		int i;
+		unsigned int tiles = req->dst_rect.h / 16;
+		unsigned int remainder = req->dst_rect.h % 16;
+		req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
+		req->dst_rect.h = 16;
+		for (i = 0; i < tiles; i++) {
+			enable_mdp_irq(mdp, DL0_ROI_DONE);
+			ret = mdp_ppp_blit(mdp, req, src_file, src_start,
+					   src_len, dst_file, dst_start,
+					   dst_len);
+			if (ret)
+				goto err_bad_blit;
+			ret = mdp_ppp_wait(mdp);
+			if (ret)
+				goto err_wait_failed;
+			req->dst_rect.y += 16;
+			req->src_rect.x += req->src_rect.w;
+		}
+		if (!remainder)
+			goto end;
+		req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
+		req->dst_rect.h = remainder;
+	}
+	enable_mdp_irq(mdp, DL0_ROI_DONE);
+	ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
+			   dst_start,
+			   dst_len);
+	if (ret)
+		goto err_bad_blit;
+	ret = mdp_ppp_wait(mdp);
+	if (ret)
+		goto err_wait_failed;
+end:
+	put_img(src_file, dst_file);
+	mutex_unlock(&mdp_mutex);
+	return 0;
+err_bad_blit:
+	disable_mdp_irq(mdp, DL0_ROI_DONE);
+err_wait_failed:
+	put_img(src_file, dst_file);
+	mutex_unlock(&mdp_mutex);
+	return ret;
+}
+
+void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
+{
+	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+
+	disp_id &= 0xf;
+	mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43);
+}
+
+int register_mdp_client(struct class_interface *cint)
+{
+	if (!mdp_class) {
+		pr_err("mdp: no mdp_class when registering mdp client\n");
+		return -ENODEV;
+	}
+	cint->class = mdp_class;
+	return class_interface_register(cint);
+}
+
+#include "mdp_csc_table.h"
+#include "mdp_scale_tables.h"
+
+int mdp_probe(struct platform_device *pdev)
+{
+	struct resource *resource;
+	int ret;
+	int n;
+	struct mdp_info *mdp;
+
+	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!resource) {
+		pr_err("mdp: can not get mdp mem resource!\n");
+		return -ENOMEM;
+	}
+
+	mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
+	if (!mdp)
+		return -ENOMEM;
+
+	mdp->irq = platform_get_irq(pdev, 0);
+	if (mdp->irq < 0) {
+		pr_err("mdp: can not get mdp irq\n");
+		ret = mdp->irq;
+		goto error_get_irq;
+	}
+
+	mdp->base = ioremap(resource->start, resource_size(resource));
+	if (mdp->base == 0) {
+		printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
+		ret = -ENOMEM;
+		goto error_ioremap;
+	}
+
+	mdp->mdp_dev.dma = mdp_dma;
+	mdp->mdp_dev.dma_wait = mdp_dma_wait;
+	mdp->mdp_dev.blit = mdp_blit;
+	mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
+
+	clk = clk_get(&pdev->dev, "mdp_clk");
+	if (IS_ERR(clk)) {
+		printk(KERN_INFO "mdp: failed to get mdp clk");
+		ret = PTR_ERR(clk);
+		goto error_get_clk;
+	}
+
+	ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
+	if (ret)
+		goto error_request_irq;
+	disable_irq(mdp->irq);
+	mdp_irq_mask = 0;
+
+	/* debug interface write access */
+	mdp_writel(mdp, 1, 0x60);
+
+	mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
+	mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
+
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
+
+	for (n = 0; n < ARRAY_SIZE(csc_table); n++)
+		mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
+
+	/* clear up unused fg/main registers */
+	/* comp.plane 2&3 ystride */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
+
+	/* unpacked pattern */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
+
+	/* comp.plane 2 & 3 */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
+
+	/* clear unused bg registers */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
+
+	for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
+		mdp_writel(mdp, mdp_upscale_table[n].val,
+		       mdp_upscale_table[n].reg);
+
+	for (n = 0; n < 9; n++)
+		mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
+	mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
+	mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
+	mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
+
+	/* register mdp device */
+	mdp->mdp_dev.dev.parent = &pdev->dev;
+	mdp->mdp_dev.dev.class = mdp_class;
+	dev_set_name(&mdp->mdp_dev.dev, "mdp%d", pdev->id);
+
+	/* if you can remove the platform device you'd have to implement
+	 * this:
+	mdp_dev.release = mdp_class; */
+
+	ret = device_register(&mdp->mdp_dev.dev);
+	if (ret)
+		goto error_device_register;
+	return 0;
+
+error_device_register:
+	free_irq(mdp->irq, mdp);
+error_request_irq:
+error_get_clk:
+	iounmap(mdp->base);
+error_get_irq:
+error_ioremap:
+	kfree(mdp);
+	return ret;
+}
+
+static struct platform_driver msm_mdp_driver = {
+	.probe = mdp_probe,
+	.driver = {.name = "msm_mdp"},
+};
+
+static int __init mdp_init(void)
+{
+	mdp_class = class_create(THIS_MODULE, "msm_mdp");
+	if (IS_ERR(mdp_class)) {
+		printk(KERN_ERR "Error creating mdp class\n");
+		return PTR_ERR(mdp_class);
+	}
+	return platform_driver_register(&msm_mdp_driver);
+}
+
+subsys_initcall(mdp_init);
diff --git a/drivers/video/fbdev/msm/mdp_csc_table.h b/drivers/video/fbdev/msm/mdp_csc_table.h
new file mode 100644
index 000000000000..d1cde30ead52
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdp_csc_table.h
@@ -0,0 +1,582 @@
+/* drivers/video/msm_fb/mdp_csc_table.h
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+static struct {
+	uint32_t reg;
+	uint32_t val;
+} csc_table[] = {
+	{ 0x40400, 0x83 },
+	{ 0x40404, 0x102 },
+	{ 0x40408, 0x32 },
+	{ 0x4040c, 0xffffffb5 },
+	{ 0x40410, 0xffffff6c },
+	{ 0x40414, 0xe1 },
+	{ 0x40418, 0xe1 },
+	{ 0x4041c, 0xffffff45 },
+	{ 0x40420, 0xffffffdc },
+	{ 0x40440, 0x254 },
+	{ 0x40444, 0x0 },
+	{ 0x40448, 0x331 },
+	{ 0x4044c, 0x254 },
+	{ 0x40450, 0xffffff38 },
+	{ 0x40454, 0xfffffe61 },
+	{ 0x40458, 0x254 },
+	{ 0x4045c, 0x409 },
+	{ 0x40460, 0x0 },
+	{ 0x40480, 0x5d },
+	{ 0x40484, 0x13a },
+	{ 0x40488, 0x20 },
+	{ 0x4048c, 0xffffffcd },
+	{ 0x40490, 0xffffff54 },
+	{ 0x40494, 0xe1 },
+	{ 0x40498, 0xe1 },
+	{ 0x4049c, 0xffffff35 },
+	{ 0x404a0, 0xffffffec },
+	{ 0x404c0, 0x254 },
+	{ 0x404c4, 0x0 },
+	{ 0x404c8, 0x396 },
+	{ 0x404cc, 0x254 },
+	{ 0x404d0, 0xffffff94 },
+	{ 0x404d4, 0xfffffef0 },
+	{ 0x404d8, 0x254 },
+	{ 0x404dc, 0x43a },
+	{ 0x404e0, 0x0 },
+	{ 0x40500, 0x10 },
+	{ 0x40504, 0x80 },
+	{ 0x40508, 0x80 },
+	{ 0x40540, 0x10 },
+	{ 0x40544, 0x80 },
+	{ 0x40548, 0x80 },
+	{ 0x40580, 0x10 },
+	{ 0x40584, 0xeb },
+	{ 0x40588, 0x10 },
+	{ 0x4058c, 0xf0 },
+	{ 0x405c0, 0x10 },
+	{ 0x405c4, 0xeb },
+	{ 0x405c8, 0x10 },
+	{ 0x405cc, 0xf0 },
+	{ 0x40800, 0x0 },
+	{ 0x40804, 0x151515 },
+	{ 0x40808, 0x1d1d1d },
+	{ 0x4080c, 0x232323 },
+	{ 0x40810, 0x272727 },
+	{ 0x40814, 0x2b2b2b },
+	{ 0x40818, 0x2f2f2f },
+	{ 0x4081c, 0x333333 },
+	{ 0x40820, 0x363636 },
+	{ 0x40824, 0x393939 },
+	{ 0x40828, 0x3b3b3b },
+	{ 0x4082c, 0x3e3e3e },
+	{ 0x40830, 0x404040 },
+	{ 0x40834, 0x434343 },
+	{ 0x40838, 0x454545 },
+	{ 0x4083c, 0x474747 },
+	{ 0x40840, 0x494949 },
+	{ 0x40844, 0x4b4b4b },
+	{ 0x40848, 0x4d4d4d },
+	{ 0x4084c, 0x4f4f4f },
+	{ 0x40850, 0x515151 },
+	{ 0x40854, 0x535353 },
+	{ 0x40858, 0x555555 },
+	{ 0x4085c, 0x565656 },
+	{ 0x40860, 0x585858 },
+	{ 0x40864, 0x5a5a5a },
+	{ 0x40868, 0x5b5b5b },
+	{ 0x4086c, 0x5d5d5d },
+	{ 0x40870, 0x5e5e5e },
+	{ 0x40874, 0x606060 },
+	{ 0x40878, 0x616161 },
+	{ 0x4087c, 0x636363 },
+	{ 0x40880, 0x646464 },
+	{ 0x40884, 0x666666 },
+	{ 0x40888, 0x676767 },
+	{ 0x4088c, 0x686868 },
+	{ 0x40890, 0x6a6a6a },
+	{ 0x40894, 0x6b6b6b },
+	{ 0x40898, 0x6c6c6c },
+	{ 0x4089c, 0x6e6e6e },
+	{ 0x408a0, 0x6f6f6f },
+	{ 0x408a4, 0x707070 },
+	{ 0x408a8, 0x717171 },
+	{ 0x408ac, 0x727272 },
+	{ 0x408b0, 0x747474 },
+	{ 0x408b4, 0x757575 },
+	{ 0x408b8, 0x767676 },
+	{ 0x408bc, 0x777777 },
+	{ 0x408c0, 0x787878 },
+	{ 0x408c4, 0x797979 },
+	{ 0x408c8, 0x7a7a7a },
+	{ 0x408cc, 0x7c7c7c },
+	{ 0x408d0, 0x7d7d7d },
+	{ 0x408d4, 0x7e7e7e },
+	{ 0x408d8, 0x7f7f7f },
+	{ 0x408dc, 0x808080 },
+	{ 0x408e0, 0x818181 },
+	{ 0x408e4, 0x828282 },
+	{ 0x408e8, 0x838383 },
+	{ 0x408ec, 0x848484 },
+	{ 0x408f0, 0x858585 },
+	{ 0x408f4, 0x868686 },
+	{ 0x408f8, 0x878787 },
+	{ 0x408fc, 0x888888 },
+	{ 0x40900, 0x898989 },
+	{ 0x40904, 0x8a8a8a },
+	{ 0x40908, 0x8b8b8b },
+	{ 0x4090c, 0x8c8c8c },
+	{ 0x40910, 0x8d8d8d },
+	{ 0x40914, 0x8e8e8e },
+	{ 0x40918, 0x8f8f8f },
+	{ 0x4091c, 0x8f8f8f },
+	{ 0x40920, 0x909090 },
+	{ 0x40924, 0x919191 },
+	{ 0x40928, 0x929292 },
+	{ 0x4092c, 0x939393 },
+	{ 0x40930, 0x949494 },
+	{ 0x40934, 0x959595 },
+	{ 0x40938, 0x969696 },
+	{ 0x4093c, 0x969696 },
+	{ 0x40940, 0x979797 },
+	{ 0x40944, 0x989898 },
+	{ 0x40948, 0x999999 },
+	{ 0x4094c, 0x9a9a9a },
+	{ 0x40950, 0x9b9b9b },
+	{ 0x40954, 0x9c9c9c },
+	{ 0x40958, 0x9c9c9c },
+	{ 0x4095c, 0x9d9d9d },
+	{ 0x40960, 0x9e9e9e },
+	{ 0x40964, 0x9f9f9f },
+	{ 0x40968, 0xa0a0a0 },
+	{ 0x4096c, 0xa0a0a0 },
+	{ 0x40970, 0xa1a1a1 },
+	{ 0x40974, 0xa2a2a2 },
+	{ 0x40978, 0xa3a3a3 },
+	{ 0x4097c, 0xa4a4a4 },
+	{ 0x40980, 0xa4a4a4 },
+	{ 0x40984, 0xa5a5a5 },
+	{ 0x40988, 0xa6a6a6 },
+	{ 0x4098c, 0xa7a7a7 },
+	{ 0x40990, 0xa7a7a7 },
+	{ 0x40994, 0xa8a8a8 },
+	{ 0x40998, 0xa9a9a9 },
+	{ 0x4099c, 0xaaaaaa },
+	{ 0x409a0, 0xaaaaaa },
+	{ 0x409a4, 0xababab },
+	{ 0x409a8, 0xacacac },
+	{ 0x409ac, 0xadadad },
+	{ 0x409b0, 0xadadad },
+	{ 0x409b4, 0xaeaeae },
+	{ 0x409b8, 0xafafaf },
+	{ 0x409bc, 0xafafaf },
+	{ 0x409c0, 0xb0b0b0 },
+	{ 0x409c4, 0xb1b1b1 },
+	{ 0x409c8, 0xb2b2b2 },
+	{ 0x409cc, 0xb2b2b2 },
+	{ 0x409d0, 0xb3b3b3 },
+	{ 0x409d4, 0xb4b4b4 },
+	{ 0x409d8, 0xb4b4b4 },
+	{ 0x409dc, 0xb5b5b5 },
+	{ 0x409e0, 0xb6b6b6 },
+	{ 0x409e4, 0xb6b6b6 },
+	{ 0x409e8, 0xb7b7b7 },
+	{ 0x409ec, 0xb8b8b8 },
+	{ 0x409f0, 0xb8b8b8 },
+	{ 0x409f4, 0xb9b9b9 },
+	{ 0x409f8, 0xbababa },
+	{ 0x409fc, 0xbababa },
+	{ 0x40a00, 0xbbbbbb },
+	{ 0x40a04, 0xbcbcbc },
+	{ 0x40a08, 0xbcbcbc },
+	{ 0x40a0c, 0xbdbdbd },
+	{ 0x40a10, 0xbebebe },
+	{ 0x40a14, 0xbebebe },
+	{ 0x40a18, 0xbfbfbf },
+	{ 0x40a1c, 0xc0c0c0 },
+	{ 0x40a20, 0xc0c0c0 },
+	{ 0x40a24, 0xc1c1c1 },
+	{ 0x40a28, 0xc1c1c1 },
+	{ 0x40a2c, 0xc2c2c2 },
+	{ 0x40a30, 0xc3c3c3 },
+	{ 0x40a34, 0xc3c3c3 },
+	{ 0x40a38, 0xc4c4c4 },
+	{ 0x40a3c, 0xc5c5c5 },
+	{ 0x40a40, 0xc5c5c5 },
+	{ 0x40a44, 0xc6c6c6 },
+	{ 0x40a48, 0xc6c6c6 },
+	{ 0x40a4c, 0xc7c7c7 },
+	{ 0x40a50, 0xc8c8c8 },
+	{ 0x40a54, 0xc8c8c8 },
+	{ 0x40a58, 0xc9c9c9 },
+	{ 0x40a5c, 0xc9c9c9 },
+	{ 0x40a60, 0xcacaca },
+	{ 0x40a64, 0xcbcbcb },
+	{ 0x40a68, 0xcbcbcb },
+	{ 0x40a6c, 0xcccccc },
+	{ 0x40a70, 0xcccccc },
+	{ 0x40a74, 0xcdcdcd },
+	{ 0x40a78, 0xcecece },
+	{ 0x40a7c, 0xcecece },
+	{ 0x40a80, 0xcfcfcf },
+	{ 0x40a84, 0xcfcfcf },
+	{ 0x40a88, 0xd0d0d0 },
+	{ 0x40a8c, 0xd0d0d0 },
+	{ 0x40a90, 0xd1d1d1 },
+	{ 0x40a94, 0xd2d2d2 },
+	{ 0x40a98, 0xd2d2d2 },
+	{ 0x40a9c, 0xd3d3d3 },
+	{ 0x40aa0, 0xd3d3d3 },
+	{ 0x40aa4, 0xd4d4d4 },
+	{ 0x40aa8, 0xd4d4d4 },
+	{ 0x40aac, 0xd5d5d5 },
+	{ 0x40ab0, 0xd6d6d6 },
+	{ 0x40ab4, 0xd6d6d6 },
+	{ 0x40ab8, 0xd7d7d7 },
+	{ 0x40abc, 0xd7d7d7 },
+	{ 0x40ac0, 0xd8d8d8 },
+	{ 0x40ac4, 0xd8d8d8 },
+	{ 0x40ac8, 0xd9d9d9 },
+	{ 0x40acc, 0xd9d9d9 },
+	{ 0x40ad0, 0xdadada },
+	{ 0x40ad4, 0xdbdbdb },
+	{ 0x40ad8, 0xdbdbdb },
+	{ 0x40adc, 0xdcdcdc },
+	{ 0x40ae0, 0xdcdcdc },
+	{ 0x40ae4, 0xdddddd },
+	{ 0x40ae8, 0xdddddd },
+	{ 0x40aec, 0xdedede },
+	{ 0x40af0, 0xdedede },
+	{ 0x40af4, 0xdfdfdf },
+	{ 0x40af8, 0xdfdfdf },
+	{ 0x40afc, 0xe0e0e0 },
+	{ 0x40b00, 0xe0e0e0 },
+	{ 0x40b04, 0xe1e1e1 },
+	{ 0x40b08, 0xe1e1e1 },
+	{ 0x40b0c, 0xe2e2e2 },
+	{ 0x40b10, 0xe3e3e3 },
+	{ 0x40b14, 0xe3e3e3 },
+	{ 0x40b18, 0xe4e4e4 },
+	{ 0x40b1c, 0xe4e4e4 },
+	{ 0x40b20, 0xe5e5e5 },
+	{ 0x40b24, 0xe5e5e5 },
+	{ 0x40b28, 0xe6e6e6 },
+	{ 0x40b2c, 0xe6e6e6 },
+	{ 0x40b30, 0xe7e7e7 },
+	{ 0x40b34, 0xe7e7e7 },
+	{ 0x40b38, 0xe8e8e8 },
+	{ 0x40b3c, 0xe8e8e8 },
+	{ 0x40b40, 0xe9e9e9 },
+	{ 0x40b44, 0xe9e9e9 },
+	{ 0x40b48, 0xeaeaea },
+	{ 0x40b4c, 0xeaeaea },
+	{ 0x40b50, 0xebebeb },
+	{ 0x40b54, 0xebebeb },
+	{ 0x40b58, 0xececec },
+	{ 0x40b5c, 0xececec },
+	{ 0x40b60, 0xededed },
+	{ 0x40b64, 0xededed },
+	{ 0x40b68, 0xeeeeee },
+	{ 0x40b6c, 0xeeeeee },
+	{ 0x40b70, 0xefefef },
+	{ 0x40b74, 0xefefef },
+	{ 0x40b78, 0xf0f0f0 },
+	{ 0x40b7c, 0xf0f0f0 },
+	{ 0x40b80, 0xf1f1f1 },
+	{ 0x40b84, 0xf1f1f1 },
+	{ 0x40b88, 0xf2f2f2 },
+	{ 0x40b8c, 0xf2f2f2 },
+	{ 0x40b90, 0xf2f2f2 },
+	{ 0x40b94, 0xf3f3f3 },
+	{ 0x40b98, 0xf3f3f3 },
+	{ 0x40b9c, 0xf4f4f4 },
+	{ 0x40ba0, 0xf4f4f4 },
+	{ 0x40ba4, 0xf5f5f5 },
+	{ 0x40ba8, 0xf5f5f5 },
+	{ 0x40bac, 0xf6f6f6 },
+	{ 0x40bb0, 0xf6f6f6 },
+	{ 0x40bb4, 0xf7f7f7 },
+	{ 0x40bb8, 0xf7f7f7 },
+	{ 0x40bbc, 0xf8f8f8 },
+	{ 0x40bc0, 0xf8f8f8 },
+	{ 0x40bc4, 0xf9f9f9 },
+	{ 0x40bc8, 0xf9f9f9 },
+	{ 0x40bcc, 0xfafafa },
+	{ 0x40bd0, 0xfafafa },
+	{ 0x40bd4, 0xfafafa },
+	{ 0x40bd8, 0xfbfbfb },
+	{ 0x40bdc, 0xfbfbfb },
+	{ 0x40be0, 0xfcfcfc },
+	{ 0x40be4, 0xfcfcfc },
+	{ 0x40be8, 0xfdfdfd },
+	{ 0x40bec, 0xfdfdfd },
+	{ 0x40bf0, 0xfefefe },
+	{ 0x40bf4, 0xfefefe },
+	{ 0x40bf8, 0xffffff },
+	{ 0x40bfc, 0xffffff },
+	{ 0x40c00, 0x0 },
+	{ 0x40c04, 0x0 },
+	{ 0x40c08, 0x0 },
+	{ 0x40c0c, 0x0 },
+	{ 0x40c10, 0x0 },
+	{ 0x40c14, 0x0 },
+	{ 0x40c18, 0x0 },
+	{ 0x40c1c, 0x0 },
+	{ 0x40c20, 0x0 },
+	{ 0x40c24, 0x0 },
+	{ 0x40c28, 0x0 },
+	{ 0x40c2c, 0x0 },
+	{ 0x40c30, 0x0 },
+	{ 0x40c34, 0x0 },
+	{ 0x40c38, 0x0 },
+	{ 0x40c3c, 0x0 },
+	{ 0x40c40, 0x10101 },
+	{ 0x40c44, 0x10101 },
+	{ 0x40c48, 0x10101 },
+	{ 0x40c4c, 0x10101 },
+	{ 0x40c50, 0x10101 },
+	{ 0x40c54, 0x10101 },
+	{ 0x40c58, 0x10101 },
+	{ 0x40c5c, 0x10101 },
+	{ 0x40c60, 0x10101 },
+	{ 0x40c64, 0x10101 },
+	{ 0x40c68, 0x20202 },
+	{ 0x40c6c, 0x20202 },
+	{ 0x40c70, 0x20202 },
+	{ 0x40c74, 0x20202 },
+	{ 0x40c78, 0x20202 },
+	{ 0x40c7c, 0x20202 },
+	{ 0x40c80, 0x30303 },
+	{ 0x40c84, 0x30303 },
+	{ 0x40c88, 0x30303 },
+	{ 0x40c8c, 0x30303 },
+	{ 0x40c90, 0x30303 },
+	{ 0x40c94, 0x40404 },
+	{ 0x40c98, 0x40404 },
+	{ 0x40c9c, 0x40404 },
+	{ 0x40ca0, 0x40404 },
+	{ 0x40ca4, 0x40404 },
+	{ 0x40ca8, 0x50505 },
+	{ 0x40cac, 0x50505 },
+	{ 0x40cb0, 0x50505 },
+	{ 0x40cb4, 0x50505 },
+	{ 0x40cb8, 0x60606 },
+	{ 0x40cbc, 0x60606 },
+	{ 0x40cc0, 0x60606 },
+	{ 0x40cc4, 0x70707 },
+	{ 0x40cc8, 0x70707 },
+	{ 0x40ccc, 0x70707 },
+	{ 0x40cd0, 0x70707 },
+	{ 0x40cd4, 0x80808 },
+	{ 0x40cd8, 0x80808 },
+	{ 0x40cdc, 0x80808 },
+	{ 0x40ce0, 0x90909 },
+	{ 0x40ce4, 0x90909 },
+	{ 0x40ce8, 0xa0a0a },
+	{ 0x40cec, 0xa0a0a },
+	{ 0x40cf0, 0xa0a0a },
+	{ 0x40cf4, 0xb0b0b },
+	{ 0x40cf8, 0xb0b0b },
+	{ 0x40cfc, 0xb0b0b },
+	{ 0x40d00, 0xc0c0c },
+	{ 0x40d04, 0xc0c0c },
+	{ 0x40d08, 0xd0d0d },
+	{ 0x40d0c, 0xd0d0d },
+	{ 0x40d10, 0xe0e0e },
+	{ 0x40d14, 0xe0e0e },
+	{ 0x40d18, 0xe0e0e },
+	{ 0x40d1c, 0xf0f0f },
+	{ 0x40d20, 0xf0f0f },
+	{ 0x40d24, 0x101010 },
+	{ 0x40d28, 0x101010 },
+	{ 0x40d2c, 0x111111 },
+	{ 0x40d30, 0x111111 },
+	{ 0x40d34, 0x121212 },
+	{ 0x40d38, 0x121212 },
+	{ 0x40d3c, 0x131313 },
+	{ 0x40d40, 0x131313 },
+	{ 0x40d44, 0x141414 },
+	{ 0x40d48, 0x151515 },
+	{ 0x40d4c, 0x151515 },
+	{ 0x40d50, 0x161616 },
+	{ 0x40d54, 0x161616 },
+	{ 0x40d58, 0x171717 },
+	{ 0x40d5c, 0x171717 },
+	{ 0x40d60, 0x181818 },
+	{ 0x40d64, 0x191919 },
+	{ 0x40d68, 0x191919 },
+	{ 0x40d6c, 0x1a1a1a },
+	{ 0x40d70, 0x1b1b1b },
+	{ 0x40d74, 0x1b1b1b },
+	{ 0x40d78, 0x1c1c1c },
+	{ 0x40d7c, 0x1c1c1c },
+	{ 0x40d80, 0x1d1d1d },
+	{ 0x40d84, 0x1e1e1e },
+	{ 0x40d88, 0x1f1f1f },
+	{ 0x40d8c, 0x1f1f1f },
+	{ 0x40d90, 0x202020 },
+	{ 0x40d94, 0x212121 },
+	{ 0x40d98, 0x212121 },
+	{ 0x40d9c, 0x222222 },
+	{ 0x40da0, 0x232323 },
+	{ 0x40da4, 0x242424 },
+	{ 0x40da8, 0x242424 },
+	{ 0x40dac, 0x252525 },
+	{ 0x40db0, 0x262626 },
+	{ 0x40db4, 0x272727 },
+	{ 0x40db8, 0x272727 },
+	{ 0x40dbc, 0x282828 },
+	{ 0x40dc0, 0x292929 },
+	{ 0x40dc4, 0x2a2a2a },
+	{ 0x40dc8, 0x2b2b2b },
+	{ 0x40dcc, 0x2c2c2c },
+	{ 0x40dd0, 0x2c2c2c },
+	{ 0x40dd4, 0x2d2d2d },
+	{ 0x40dd8, 0x2e2e2e },
+	{ 0x40ddc, 0x2f2f2f },
+	{ 0x40de0, 0x303030 },
+	{ 0x40de4, 0x313131 },
+	{ 0x40de8, 0x323232 },
+	{ 0x40dec, 0x333333 },
+	{ 0x40df0, 0x333333 },
+	{ 0x40df4, 0x343434 },
+	{ 0x40df8, 0x353535 },
+	{ 0x40dfc, 0x363636 },
+	{ 0x40e00, 0x373737 },
+	{ 0x40e04, 0x383838 },
+	{ 0x40e08, 0x393939 },
+	{ 0x40e0c, 0x3a3a3a },
+	{ 0x40e10, 0x3b3b3b },
+	{ 0x40e14, 0x3c3c3c },
+	{ 0x40e18, 0x3d3d3d },
+	{ 0x40e1c, 0x3e3e3e },
+	{ 0x40e20, 0x3f3f3f },
+	{ 0x40e24, 0x404040 },
+	{ 0x40e28, 0x414141 },
+	{ 0x40e2c, 0x424242 },
+	{ 0x40e30, 0x434343 },
+	{ 0x40e34, 0x444444 },
+	{ 0x40e38, 0x464646 },
+	{ 0x40e3c, 0x474747 },
+	{ 0x40e40, 0x484848 },
+	{ 0x40e44, 0x494949 },
+	{ 0x40e48, 0x4a4a4a },
+	{ 0x40e4c, 0x4b4b4b },
+	{ 0x40e50, 0x4c4c4c },
+	{ 0x40e54, 0x4d4d4d },
+	{ 0x40e58, 0x4f4f4f },
+	{ 0x40e5c, 0x505050 },
+	{ 0x40e60, 0x515151 },
+	{ 0x40e64, 0x525252 },
+	{ 0x40e68, 0x535353 },
+	{ 0x40e6c, 0x545454 },
+	{ 0x40e70, 0x565656 },
+	{ 0x40e74, 0x575757 },
+	{ 0x40e78, 0x585858 },
+	{ 0x40e7c, 0x595959 },
+	{ 0x40e80, 0x5b5b5b },
+	{ 0x40e84, 0x5c5c5c },
+	{ 0x40e88, 0x5d5d5d },
+	{ 0x40e8c, 0x5e5e5e },
+	{ 0x40e90, 0x606060 },
+	{ 0x40e94, 0x616161 },
+	{ 0x40e98, 0x626262 },
+	{ 0x40e9c, 0x646464 },
+	{ 0x40ea0, 0x656565 },
+	{ 0x40ea4, 0x666666 },
+	{ 0x40ea8, 0x686868 },
+	{ 0x40eac, 0x696969 },
+	{ 0x40eb0, 0x6a6a6a },
+	{ 0x40eb4, 0x6c6c6c },
+	{ 0x40eb8, 0x6d6d6d },
+	{ 0x40ebc, 0x6f6f6f },
+	{ 0x40ec0, 0x707070 },
+	{ 0x40ec4, 0x717171 },
+	{ 0x40ec8, 0x737373 },
+	{ 0x40ecc, 0x747474 },
+	{ 0x40ed0, 0x767676 },
+	{ 0x40ed4, 0x777777 },
+	{ 0x40ed8, 0x797979 },
+	{ 0x40edc, 0x7a7a7a },
+	{ 0x40ee0, 0x7c7c7c },
+	{ 0x40ee4, 0x7d7d7d },
+	{ 0x40ee8, 0x7f7f7f },
+	{ 0x40eec, 0x808080 },
+	{ 0x40ef0, 0x828282 },
+	{ 0x40ef4, 0x838383 },
+	{ 0x40ef8, 0x858585 },
+	{ 0x40efc, 0x868686 },
+	{ 0x40f00, 0x888888 },
+	{ 0x40f04, 0x898989 },
+	{ 0x40f08, 0x8b8b8b },
+	{ 0x40f0c, 0x8d8d8d },
+	{ 0x40f10, 0x8e8e8e },
+	{ 0x40f14, 0x909090 },
+	{ 0x40f18, 0x919191 },
+	{ 0x40f1c, 0x939393 },
+	{ 0x40f20, 0x959595 },
+	{ 0x40f24, 0x969696 },
+	{ 0x40f28, 0x989898 },
+	{ 0x40f2c, 0x9a9a9a },
+	{ 0x40f30, 0x9b9b9b },
+	{ 0x40f34, 0x9d9d9d },
+	{ 0x40f38, 0x9f9f9f },
+	{ 0x40f3c, 0xa1a1a1 },
+	{ 0x40f40, 0xa2a2a2 },
+	{ 0x40f44, 0xa4a4a4 },
+	{ 0x40f48, 0xa6a6a6 },
+	{ 0x40f4c, 0xa7a7a7 },
+	{ 0x40f50, 0xa9a9a9 },
+	{ 0x40f54, 0xababab },
+	{ 0x40f58, 0xadadad },
+	{ 0x40f5c, 0xafafaf },
+	{ 0x40f60, 0xb0b0b0 },
+	{ 0x40f64, 0xb2b2b2 },
+	{ 0x40f68, 0xb4b4b4 },
+	{ 0x40f6c, 0xb6b6b6 },
+	{ 0x40f70, 0xb8b8b8 },
+	{ 0x40f74, 0xbababa },
+	{ 0x40f78, 0xbbbbbb },
+	{ 0x40f7c, 0xbdbdbd },
+	{ 0x40f80, 0xbfbfbf },
+	{ 0x40f84, 0xc1c1c1 },
+	{ 0x40f88, 0xc3c3c3 },
+	{ 0x40f8c, 0xc5c5c5 },
+	{ 0x40f90, 0xc7c7c7 },
+	{ 0x40f94, 0xc9c9c9 },
+	{ 0x40f98, 0xcbcbcb },
+	{ 0x40f9c, 0xcdcdcd },
+	{ 0x40fa0, 0xcfcfcf },
+	{ 0x40fa4, 0xd1d1d1 },
+	{ 0x40fa8, 0xd3d3d3 },
+	{ 0x40fac, 0xd5d5d5 },
+	{ 0x40fb0, 0xd7d7d7 },
+	{ 0x40fb4, 0xd9d9d9 },
+	{ 0x40fb8, 0xdbdbdb },
+	{ 0x40fbc, 0xdddddd },
+	{ 0x40fc0, 0xdfdfdf },
+	{ 0x40fc4, 0xe1e1e1 },
+	{ 0x40fc8, 0xe3e3e3 },
+	{ 0x40fcc, 0xe5e5e5 },
+	{ 0x40fd0, 0xe7e7e7 },
+	{ 0x40fd4, 0xe9e9e9 },
+	{ 0x40fd8, 0xebebeb },
+	{ 0x40fdc, 0xeeeeee },
+	{ 0x40fe0, 0xf0f0f0 },
+	{ 0x40fe4, 0xf2f2f2 },
+	{ 0x40fe8, 0xf4f4f4 },
+	{ 0x40fec, 0xf6f6f6 },
+	{ 0x40ff0, 0xf8f8f8 },
+	{ 0x40ff4, 0xfbfbfb },
+	{ 0x40ff8, 0xfdfdfd },
+	{ 0x40ffc, 0xffffff },
+};
diff --git a/drivers/video/fbdev/msm/mdp_hw.h b/drivers/video/fbdev/msm/mdp_hw.h
new file mode 100644
index 000000000000..35848d741001
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdp_hw.h
@@ -0,0 +1,627 @@
+/* drivers/video/msm_fb/mdp_hw.h
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _MDP_HW_H_
+#define _MDP_HW_H_
+
+#include <linux/platform_data/video-msm_fb.h>
+
+struct mdp_info {
+	struct mdp_device mdp_dev;
+	char * __iomem base;
+	int irq;
+};
+struct mdp_blit_req;
+struct mdp_device;
+int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
+		 struct file *src_file, unsigned long src_start,
+		 unsigned long src_len, struct file *dst_file,
+		 unsigned long dst_start, unsigned long dst_len);
+#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
+#define mdp_readl(mdp, offset) readl(mdp->base + offset)
+
+#define MDP_SYNC_CONFIG_0                (0x00000)
+#define MDP_SYNC_CONFIG_1                (0x00004)
+#define MDP_SYNC_CONFIG_2                (0x00008)
+#define MDP_SYNC_STATUS_0                (0x0000c)
+#define MDP_SYNC_STATUS_1                (0x00010)
+#define MDP_SYNC_STATUS_2                (0x00014)
+#define MDP_SYNC_THRESH_0                (0x00018)
+#define MDP_SYNC_THRESH_1                (0x0001c)
+#define MDP_INTR_ENABLE                  (0x00020)
+#define MDP_INTR_STATUS                  (0x00024)
+#define MDP_INTR_CLEAR                   (0x00028)
+#define MDP_DISPLAY0_START               (0x00030)
+#define MDP_DISPLAY1_START               (0x00034)
+#define MDP_DISPLAY_STATUS               (0x00038)
+#define MDP_EBI2_LCD0                    (0x0003c)
+#define MDP_EBI2_LCD1                    (0x00040)
+#define MDP_DISPLAY0_ADDR                (0x00054)
+#define MDP_DISPLAY1_ADDR                (0x00058)
+#define MDP_EBI2_PORTMAP_MODE            (0x0005c)
+#define MDP_MODE                         (0x00060)
+#define MDP_TV_OUT_STATUS                (0x00064)
+#define MDP_HW_VERSION                   (0x00070)
+#define MDP_SW_RESET                     (0x00074)
+#define MDP_AXI_ERROR_MASTER_STOP        (0x00078)
+#define MDP_SEL_CLK_OR_HCLK_TEST_BUS     (0x0007c)
+#define MDP_PRIMARY_VSYNC_OUT_CTRL       (0x00080)
+#define MDP_SECONDARY_VSYNC_OUT_CTRL     (0x00084)
+#define MDP_EXTERNAL_VSYNC_OUT_CTRL      (0x00088)
+#define MDP_VSYNC_CTRL                   (0x0008c)
+#define MDP_CGC_EN                       (0x00100)
+#define MDP_CMD_STATUS                   (0x10008)
+#define MDP_PROFILE_EN                   (0x10010)
+#define MDP_PROFILE_COUNT                (0x10014)
+#define MDP_DMA_START                    (0x10044)
+#define MDP_FULL_BYPASS_WORD0            (0x10100)
+#define MDP_FULL_BYPASS_WORD1            (0x10104)
+#define MDP_COMMAND_CONFIG               (0x10104)
+#define MDP_FULL_BYPASS_WORD2            (0x10108)
+#define MDP_FULL_BYPASS_WORD3            (0x1010c)
+#define MDP_FULL_BYPASS_WORD4            (0x10110)
+#define MDP_FULL_BYPASS_WORD6            (0x10118)
+#define MDP_FULL_BYPASS_WORD7            (0x1011c)
+#define MDP_FULL_BYPASS_WORD8            (0x10120)
+#define MDP_FULL_BYPASS_WORD9            (0x10124)
+#define MDP_PPP_SOURCE_CONFIG            (0x10124)
+#define MDP_FULL_BYPASS_WORD10           (0x10128)
+#define MDP_FULL_BYPASS_WORD11           (0x1012c)
+#define MDP_FULL_BYPASS_WORD12           (0x10130)
+#define MDP_FULL_BYPASS_WORD13           (0x10134)
+#define MDP_FULL_BYPASS_WORD14           (0x10138)
+#define MDP_PPP_OPERATION_CONFIG         (0x10138)
+#define MDP_FULL_BYPASS_WORD15           (0x1013c)
+#define MDP_FULL_BYPASS_WORD16           (0x10140)
+#define MDP_FULL_BYPASS_WORD17           (0x10144)
+#define MDP_FULL_BYPASS_WORD18           (0x10148)
+#define MDP_FULL_BYPASS_WORD19           (0x1014c)
+#define MDP_FULL_BYPASS_WORD20           (0x10150)
+#define MDP_PPP_DESTINATION_CONFIG       (0x10150)
+#define MDP_FULL_BYPASS_WORD21           (0x10154)
+#define MDP_FULL_BYPASS_WORD22           (0x10158)
+#define MDP_FULL_BYPASS_WORD23           (0x1015c)
+#define MDP_FULL_BYPASS_WORD24           (0x10160)
+#define MDP_FULL_BYPASS_WORD25           (0x10164)
+#define MDP_FULL_BYPASS_WORD26           (0x10168)
+#define MDP_FULL_BYPASS_WORD27           (0x1016c)
+#define MDP_FULL_BYPASS_WORD29           (0x10174)
+#define MDP_FULL_BYPASS_WORD30           (0x10178)
+#define MDP_FULL_BYPASS_WORD31           (0x1017c)
+#define MDP_FULL_BYPASS_WORD32           (0x10180)
+#define MDP_DMA_CONFIG                   (0x10180)
+#define MDP_FULL_BYPASS_WORD33           (0x10184)
+#define MDP_FULL_BYPASS_WORD34           (0x10188)
+#define MDP_FULL_BYPASS_WORD35           (0x1018c)
+#define MDP_FULL_BYPASS_WORD37           (0x10194)
+#define MDP_FULL_BYPASS_WORD39           (0x1019c)
+#define MDP_FULL_BYPASS_WORD40           (0x101a0)
+#define MDP_FULL_BYPASS_WORD41           (0x101a4)
+#define MDP_FULL_BYPASS_WORD43           (0x101ac)
+#define MDP_FULL_BYPASS_WORD46           (0x101b8)
+#define MDP_FULL_BYPASS_WORD47           (0x101bc)
+#define MDP_FULL_BYPASS_WORD48           (0x101c0)
+#define MDP_FULL_BYPASS_WORD49           (0x101c4)
+#define MDP_FULL_BYPASS_WORD50           (0x101c8)
+#define MDP_FULL_BYPASS_WORD51           (0x101cc)
+#define MDP_FULL_BYPASS_WORD52           (0x101d0)
+#define MDP_FULL_BYPASS_WORD53           (0x101d4)
+#define MDP_FULL_BYPASS_WORD54           (0x101d8)
+#define MDP_FULL_BYPASS_WORD55           (0x101dc)
+#define MDP_FULL_BYPASS_WORD56           (0x101e0)
+#define MDP_FULL_BYPASS_WORD57           (0x101e4)
+#define MDP_FULL_BYPASS_WORD58           (0x101e8)
+#define MDP_FULL_BYPASS_WORD59           (0x101ec)
+#define MDP_FULL_BYPASS_WORD60           (0x101f0)
+#define MDP_VSYNC_THRESHOLD              (0x101f0)
+#define MDP_FULL_BYPASS_WORD61           (0x101f4)
+#define MDP_FULL_BYPASS_WORD62           (0x101f8)
+#define MDP_FULL_BYPASS_WORD63           (0x101fc)
+#define MDP_TFETCH_TEST_MODE             (0x20004)
+#define MDP_TFETCH_STATUS                (0x20008)
+#define MDP_TFETCH_TILE_COUNT            (0x20010)
+#define MDP_TFETCH_FETCH_COUNT           (0x20014)
+#define MDP_TFETCH_CONSTANT_COLOR        (0x20040)
+#define MDP_CSC_BYPASS                   (0x40004)
+#define MDP_SCALE_COEFF_LSB              (0x5fffc)
+#define MDP_TV_OUT_CTL                   (0xc0000)
+#define MDP_TV_OUT_FIR_COEFF             (0xc0004)
+#define MDP_TV_OUT_BUF_ADDR              (0xc0008)
+#define MDP_TV_OUT_CC_DATA               (0xc000c)
+#define MDP_TV_OUT_SOBEL                 (0xc0010)
+#define MDP_TV_OUT_Y_CLAMP               (0xc0018)
+#define MDP_TV_OUT_CB_CLAMP              (0xc001c)
+#define MDP_TV_OUT_CR_CLAMP              (0xc0020)
+#define MDP_TEST_MODE_CLK                (0xd0000)
+#define MDP_TEST_MISR_RESET_CLK          (0xd0004)
+#define MDP_TEST_EXPORT_MISR_CLK         (0xd0008)
+#define MDP_TEST_MISR_CURR_VAL_CLK       (0xd000c)
+#define MDP_TEST_MODE_HCLK               (0xd0100)
+#define MDP_TEST_MISR_RESET_HCLK         (0xd0104)
+#define MDP_TEST_EXPORT_MISR_HCLK        (0xd0108)
+#define MDP_TEST_MISR_CURR_VAL_HCLK      (0xd010c)
+#define MDP_TEST_MODE_DCLK               (0xd0200)
+#define MDP_TEST_MISR_RESET_DCLK         (0xd0204)
+#define MDP_TEST_EXPORT_MISR_DCLK        (0xd0208)
+#define MDP_TEST_MISR_CURR_VAL_DCLK      (0xd020c)
+#define MDP_TEST_CAPTURED_DCLK           (0xd0210)
+#define MDP_TEST_MISR_CAPT_VAL_DCLK      (0xd0214)
+#define MDP_LCDC_CTL                     (0xe0000)
+#define MDP_LCDC_HSYNC_CTL               (0xe0004)
+#define MDP_LCDC_VSYNC_CTL               (0xe0008)
+#define MDP_LCDC_ACTIVE_HCTL             (0xe000c)
+#define MDP_LCDC_ACTIVE_VCTL             (0xe0010)
+#define MDP_LCDC_BORDER_CLR              (0xe0014)
+#define MDP_LCDC_H_BLANK                 (0xe0018)
+#define MDP_LCDC_V_BLANK                 (0xe001c)
+#define MDP_LCDC_UNDERFLOW_CLR           (0xe0020)
+#define MDP_LCDC_HSYNC_SKEW              (0xe0024)
+#define MDP_LCDC_TEST_CTL                (0xe0028)
+#define MDP_LCDC_LINE_IRQ                (0xe002c)
+#define MDP_LCDC_CTL_POLARITY            (0xe0030)
+#define MDP_LCDC_DMA_CONFIG              (0xe1000)
+#define MDP_LCDC_DMA_SIZE                (0xe1004)
+#define MDP_LCDC_DMA_IBUF_ADDR           (0xe1008)
+#define MDP_LCDC_DMA_IBUF_Y_STRIDE       (0xe100c)
+
+
+#define MDP_DMA2_TERM 0x1
+#define MDP_DMA3_TERM 0x2
+#define MDP_PPP_TERM 0x3
+
+/* MDP_INTR_ENABLE */
+#define DL0_ROI_DONE           (1<<0)
+#define DL1_ROI_DONE           (1<<1)
+#define DL0_DMA2_TERM_DONE     (1<<2)
+#define DL1_DMA2_TERM_DONE     (1<<3)
+#define DL0_PPP_TERM_DONE      (1<<4)
+#define DL1_PPP_TERM_DONE      (1<<5)
+#define TV_OUT_DMA3_DONE       (1<<6)
+#define TV_ENC_UNDERRUN        (1<<7)
+#define DL0_FETCH_DONE         (1<<11)
+#define DL1_FETCH_DONE         (1<<12)
+
+#define MDP_PPP_BUSY_STATUS (DL0_ROI_DONE| \
+			   DL1_ROI_DONE| \
+			   DL0_PPP_TERM_DONE| \
+			   DL1_PPP_TERM_DONE)
+
+#define MDP_ANY_INTR_MASK (DL0_ROI_DONE| \
+			   DL1_ROI_DONE| \
+			   DL0_DMA2_TERM_DONE| \
+			   DL1_DMA2_TERM_DONE| \
+			   DL0_PPP_TERM_DONE| \
+			   DL1_PPP_TERM_DONE| \
+			   DL0_FETCH_DONE| \
+			   DL1_FETCH_DONE| \
+			   TV_ENC_UNDERRUN)
+
+#define MDP_TOP_LUMA       16
+#define MDP_TOP_CHROMA     0
+#define MDP_BOTTOM_LUMA    19
+#define MDP_BOTTOM_CHROMA  3
+#define MDP_LEFT_LUMA      22
+#define MDP_LEFT_CHROMA    6
+#define MDP_RIGHT_LUMA     25
+#define MDP_RIGHT_CHROMA   9
+
+#define CLR_G 0x0
+#define CLR_B 0x1
+#define CLR_R 0x2
+#define CLR_ALPHA 0x3
+
+#define CLR_Y  CLR_G
+#define CLR_CB CLR_B
+#define CLR_CR CLR_R
+
+/* from lsb to msb */
+#define MDP_GET_PACK_PATTERN(a, x, y, z, bit) \
+	(((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
+
+/* MDP_SYNC_CONFIG_0/1/2 */
+#define MDP_SYNCFG_HGT_LOC 22
+#define MDP_SYNCFG_VSYNC_EXT_EN (1<<21)
+#define MDP_SYNCFG_VSYNC_INT_EN (1<<20)
+
+/* MDP_SYNC_THRESH_0 */
+#define MDP_PRIM_BELOW_LOC 0
+#define MDP_PRIM_ABOVE_LOC 8
+
+/* MDP_{PRIMARY,SECONDARY,EXTERNAL}_VSYNC_OUT_CRL */
+#define VSYNC_PULSE_EN (1<<31)
+#define VSYNC_PULSE_INV (1<<30)
+
+/* MDP_VSYNC_CTRL */
+#define DISP0_VSYNC_MAP_VSYNC0 0
+#define DISP0_VSYNC_MAP_VSYNC1 (1<<0)
+#define DISP0_VSYNC_MAP_VSYNC2 ((1<<0)|(1<<1))
+
+#define DISP1_VSYNC_MAP_VSYNC0 0
+#define DISP1_VSYNC_MAP_VSYNC1 (1<<2)
+#define DISP1_VSYNC_MAP_VSYNC2 ((1<<2)|(1<<3))
+
+#define PRIMARY_LCD_SYNC_EN (1<<4)
+#define PRIMARY_LCD_SYNC_DISABLE 0
+
+#define SECONDARY_LCD_SYNC_EN (1<<5)
+#define SECONDARY_LCD_SYNC_DISABLE 0
+
+#define EXTERNAL_LCD_SYNC_EN (1<<6)
+#define EXTERNAL_LCD_SYNC_DISABLE 0
+
+/* MDP_VSYNC_THRESHOLD / MDP_FULL_BYPASS_WORD60 */
+#define VSYNC_THRESHOLD_ABOVE_LOC 0
+#define VSYNC_THRESHOLD_BELOW_LOC 16
+#define VSYNC_ANTI_TEAR_EN (1<<31)
+
+/* MDP_COMMAND_CONFIG / MDP_FULL_BYPASS_WORD1 */
+#define MDP_CMD_DBGBUS_EN (1<<0)
+
+/* MDP_PPP_SOURCE_CONFIG / MDP_FULL_BYPASS_WORD9&53 */
+#define PPP_SRC_C0G_8BIT ((1<<1)|(1<<0))
+#define PPP_SRC_C1B_8BIT ((1<<3)|(1<<2))
+#define PPP_SRC_C2R_8BIT ((1<<5)|(1<<4))
+#define PPP_SRC_C3A_8BIT ((1<<7)|(1<<6))
+
+#define PPP_SRC_C0G_6BIT (1<<1)
+#define PPP_SRC_C1B_6BIT (1<<3)
+#define PPP_SRC_C2R_6BIT (1<<5)
+
+#define PPP_SRC_C0G_5BIT (1<<0)
+#define PPP_SRC_C1B_5BIT (1<<2)
+#define PPP_SRC_C2R_5BIT (1<<4)
+
+#define PPP_SRC_C3ALPHA_EN (1<<8)
+
+#define PPP_SRC_BPP_1BYTES 0
+#define PPP_SRC_BPP_2BYTES (1<<9)
+#define PPP_SRC_BPP_3BYTES (1<<10)
+#define PPP_SRC_BPP_4BYTES ((1<<10)|(1<<9))
+
+#define PPP_SRC_BPP_ROI_ODD_X (1<<11)
+#define PPP_SRC_BPP_ROI_ODD_Y (1<<12)
+#define PPP_SRC_INTERLVD_2COMPONENTS (1<<13)
+#define PPP_SRC_INTERLVD_3COMPONENTS (1<<14)
+#define PPP_SRC_INTERLVD_4COMPONENTS ((1<<14)|(1<<13))
+
+
+/* RGB666 unpack format
+** TIGHT means R6+G6+B6 together
+** LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
+**          or 2+R6 +2+G6 +2+B6 (with LSB)
+*/
+#define PPP_SRC_PACK_TIGHT (1<<17)
+#define PPP_SRC_PACK_LOOSE 0
+#define PPP_SRC_PACK_ALIGN_LSB 0
+#define PPP_SRC_PACK_ALIGN_MSB (1<<18)
+
+#define PPP_SRC_PLANE_INTERLVD 0
+#define PPP_SRC_PLANE_PSEUDOPLNR (1<<20)
+
+#define PPP_SRC_WMV9_MODE (1<<21)
+
+/* MDP_PPP_OPERATION_CONFIG / MDP_FULL_BYPASS_WORD14 */
+#define PPP_OP_SCALE_X_ON (1<<0)
+#define PPP_OP_SCALE_Y_ON (1<<1)
+
+#define PPP_OP_CONVERT_RGB2YCBCR 0
+#define PPP_OP_CONVERT_YCBCR2RGB (1<<2)
+#define PPP_OP_CONVERT_ON (1<<3)
+
+#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
+#define PPP_OP_CONVERT_MATRIX_SECONDARY (1<<4)
+
+#define PPP_OP_LUT_C0_ON (1<<5)
+#define PPP_OP_LUT_C1_ON (1<<6)
+#define PPP_OP_LUT_C2_ON (1<<7)
+
+/* rotate or blend enable */
+#define PPP_OP_ROT_ON (1<<8)
+
+#define PPP_OP_ROT_90 (1<<9)
+#define PPP_OP_FLIP_LR (1<<10)
+#define PPP_OP_FLIP_UD (1<<11)
+
+#define PPP_OP_BLEND_ON (1<<12)
+
+#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
+#define PPP_OP_BLEND_DSTPIXEL_ALPHA (1<<13)
+#define PPP_OP_BLEND_CONSTANT_ALPHA (1<<14)
+#define PPP_OP_BLEND_SRCPIXEL_TRANSP ((1<<13)|(1<<14))
+
+#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
+#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE (1<<15)
+
+#define PPP_OP_DITHER_EN (1<<16)
+
+#define PPP_OP_COLOR_SPACE_RGB 0
+#define PPP_OP_COLOR_SPACE_YCBCR (1<<17)
+
+#define PPP_OP_SRC_CHROMA_RGB 0
+#define PPP_OP_SRC_CHROMA_H2V1 (1<<18)
+#define PPP_OP_SRC_CHROMA_H1V2 (1<<19)
+#define PPP_OP_SRC_CHROMA_420 ((1<<18)|(1<<19))
+#define PPP_OP_SRC_CHROMA_COSITE 0
+#define PPP_OP_SRC_CHROMA_OFFSITE (1<<20)
+
+#define PPP_OP_DST_CHROMA_RGB 0
+#define PPP_OP_DST_CHROMA_H2V1 (1<<21)
+#define PPP_OP_DST_CHROMA_H1V2 (1<<22)
+#define PPP_OP_DST_CHROMA_420 ((1<<21)|(1<<22))
+#define PPP_OP_DST_CHROMA_COSITE 0
+#define PPP_OP_DST_CHROMA_OFFSITE (1<<23)
+
+#define PPP_BLEND_ALPHA_TRANSP (1<<24)
+
+#define PPP_OP_BG_CHROMA_RGB 0
+#define PPP_OP_BG_CHROMA_H2V1 (1<<25)
+#define PPP_OP_BG_CHROMA_H1V2 (1<<26)
+#define PPP_OP_BG_CHROMA_420 ((1<<25)|(1<<26))
+#define PPP_OP_BG_CHROMA_SITE_COSITE 0
+#define PPP_OP_BG_CHROMA_SITE_OFFSITE (1<<27)
+
+/* MDP_PPP_DESTINATION_CONFIG / MDP_FULL_BYPASS_WORD20 */
+#define PPP_DST_C0G_8BIT ((1<<0)|(1<<1))
+#define PPP_DST_C1B_8BIT ((1<<3)|(1<<2))
+#define PPP_DST_C2R_8BIT ((1<<5)|(1<<4))
+#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
+
+#define PPP_DST_C0G_6BIT (1<<1)
+#define PPP_DST_C1B_6BIT (1<<3)
+#define PPP_DST_C2R_6BIT (1<<5)
+
+#define PPP_DST_C0G_5BIT (1<<0)
+#define PPP_DST_C1B_5BIT (1<<2)
+#define PPP_DST_C2R_5BIT (1<<4)
+
+#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
+#define PPP_DST_C3ALPHA_EN (1<<8)
+
+#define PPP_DST_INTERLVD_2COMPONENTS (1<<9)
+#define PPP_DST_INTERLVD_3COMPONENTS (1<<10)
+#define PPP_DST_INTERLVD_4COMPONENTS ((1<<10)|(1<<9))
+#define PPP_DST_INTERLVD_6COMPONENTS ((1<<11)|(1<<9))
+
+#define PPP_DST_PACK_LOOSE 0
+#define PPP_DST_PACK_TIGHT (1<<13)
+#define PPP_DST_PACK_ALIGN_LSB 0
+#define PPP_DST_PACK_ALIGN_MSB (1<<14)
+
+#define PPP_DST_OUT_SEL_AXI 0
+#define PPP_DST_OUT_SEL_MDDI (1<<15)
+
+#define PPP_DST_BPP_2BYTES (1<<16)
+#define PPP_DST_BPP_3BYTES (1<<17)
+#define PPP_DST_BPP_4BYTES ((1<<17)|(1<<16))
+
+#define PPP_DST_PLANE_INTERLVD 0
+#define PPP_DST_PLANE_PLANAR (1<<18)
+#define PPP_DST_PLANE_PSEUDOPLNR (1<<19)
+
+#define PPP_DST_TO_TV (1<<20)
+
+#define PPP_DST_MDDI_PRIMARY 0
+#define PPP_DST_MDDI_SECONDARY (1<<21)
+#define PPP_DST_MDDI_EXTERNAL (1<<22)
+
+/* image configurations by image type */
+#define PPP_CFG_MDP_RGB_565(dir)       (PPP_##dir##_C2R_5BIT | \
+					PPP_##dir##_C0G_6BIT | \
+					PPP_##dir##_C1B_5BIT | \
+					PPP_##dir##_BPP_2BYTES | \
+					PPP_##dir##_INTERLVD_3COMPONENTS | \
+					PPP_##dir##_PACK_TIGHT | \
+					PPP_##dir##_PACK_ALIGN_LSB | \
+					PPP_##dir##_PLANE_INTERLVD)
+
+#define PPP_CFG_MDP_RGB_888(dir)       (PPP_##dir##_C2R_8BIT | \
+					PPP_##dir##_C0G_8BIT | \
+					PPP_##dir##_C1B_8BIT | \
+					PPP_##dir##_BPP_3BYTES | \
+					PPP_##dir##_INTERLVD_3COMPONENTS | \
+					PPP_##dir##_PACK_TIGHT | \
+					PPP_##dir##_PACK_ALIGN_LSB | \
+					PPP_##dir##_PLANE_INTERLVD)
+
+#define PPP_CFG_MDP_ARGB_8888(dir)     (PPP_##dir##_C2R_8BIT | \
+					PPP_##dir##_C0G_8BIT | \
+					PPP_##dir##_C1B_8BIT | \
+					PPP_##dir##_C3A_8BIT | \
+					PPP_##dir##_C3ALPHA_EN | \
+					PPP_##dir##_BPP_4BYTES | \
+					PPP_##dir##_INTERLVD_4COMPONENTS | \
+					PPP_##dir##_PACK_TIGHT | \
+					PPP_##dir##_PACK_ALIGN_LSB | \
+					PPP_##dir##_PLANE_INTERLVD)
+
+#define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
+#define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
+#define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
+#define PPP_CFG_MDP_RGBX_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
+
+#define PPP_CFG_MDP_Y_CBCR_H2V2(dir)   (PPP_##dir##_C2R_8BIT | \
+					PPP_##dir##_C0G_8BIT | \
+					PPP_##dir##_C1B_8BIT | \
+					PPP_##dir##_C3A_8BIT | \
+					PPP_##dir##_BPP_2BYTES | \
+					PPP_##dir##_INTERLVD_2COMPONENTS | \
+					PPP_##dir##_PACK_TIGHT | \
+					PPP_##dir##_PACK_ALIGN_LSB | \
+					PPP_##dir##_PLANE_PSEUDOPLNR)
+
+#define PPP_CFG_MDP_Y_CRCB_H2V2(dir)	PPP_CFG_MDP_Y_CBCR_H2V2(dir)
+
+#define PPP_CFG_MDP_YCRYCB_H2V1(dir)   (PPP_##dir##_C2R_8BIT | \
+					PPP_##dir##_C0G_8BIT | \
+					PPP_##dir##_C1B_8BIT | \
+					PPP_##dir##_C3A_8BIT | \
+					PPP_##dir##_BPP_2BYTES | \
+					PPP_##dir##_INTERLVD_4COMPONENTS | \
+					PPP_##dir##_PACK_TIGHT | \
+					PPP_##dir##_PACK_ALIGN_LSB |\
+					PPP_##dir##_PLANE_INTERLVD)
+
+#define PPP_CFG_MDP_Y_CBCR_H2V1(dir)   (PPP_##dir##_C2R_8BIT | \
+					PPP_##dir##_C0G_8BIT | \
+					PPP_##dir##_C1B_8BIT | \
+					PPP_##dir##_C3A_8BIT | \
+					PPP_##dir##_BPP_2BYTES |   \
+					PPP_##dir##_INTERLVD_2COMPONENTS |  \
+					PPP_##dir##_PACK_TIGHT | \
+					PPP_##dir##_PACK_ALIGN_LSB | \
+					PPP_##dir##_PLANE_PSEUDOPLNR)
+
+#define PPP_CFG_MDP_Y_CRCB_H2V1(dir)	PPP_CFG_MDP_Y_CBCR_H2V1(dir)
+
+#define PPP_PACK_PATTERN_MDP_RGB_565 \
+	MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8)
+#define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565
+#define PPP_PACK_PATTERN_MDP_XRGB_8888 \
+	MDP_GET_PACK_PATTERN(CLR_B, CLR_G, CLR_R, CLR_ALPHA, 8)
+#define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888
+#define PPP_PACK_PATTERN_MDP_RGBA_8888 \
+	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
+#define PPP_PACK_PATTERN_MDP_BGRA_8888 \
+	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
+#define PPP_PACK_PATTERN_MDP_RGBX_8888 \
+	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
+#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \
+	MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8)
+#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1
+#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1 \
+	MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8)
+#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V2 PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1
+#define PPP_PACK_PATTERN_MDP_YCRYCB_H2V1 \
+	MDP_GET_PACK_PATTERN(CLR_Y, CLR_R, CLR_Y, CLR_B, 8)
+
+#define PPP_CHROMA_SAMP_MDP_RGB_565(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_RGB_888(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_XRGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_RGBX_8888(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
+#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420
+#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
+#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V2(dir) PPP_OP_##dir##_CHROMA_420
+#define PPP_CHROMA_SAMP_MDP_YCRYCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
+
+/* Helpful array generation macros */
+#define PPP_ARRAY0(name) \
+	[MDP_RGB_565] = PPP_##name##_MDP_RGB_565,\
+	[MDP_RGB_888] = PPP_##name##_MDP_RGB_888,\
+	[MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888,\
+	[MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\
+	[MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\
+	[MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\
+	[MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888,\
+	[MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\
+	[MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\
+	[MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\
+	[MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2,\
+	[MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1
+
+#define PPP_ARRAY1(name, dir) \
+	[MDP_RGB_565] = PPP_##name##_MDP_RGB_565(dir),\
+	[MDP_RGB_888] = PPP_##name##_MDP_RGB_888(dir),\
+	[MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888(dir),\
+	[MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\
+	[MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\
+	[MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\
+	[MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888(dir),\
+	[MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\
+	[MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\
+	[MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\
+	[MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2(dir),\
+	[MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1(dir)
+
+#define IS_YCRCB(img) ((img == MDP_Y_CRCB_H2V2) | (img == MDP_Y_CBCR_H2V2) | \
+		       (img == MDP_Y_CRCB_H2V1) | (img == MDP_Y_CBCR_H2V1) | \
+		       (img == MDP_YCRYCB_H2V1))
+#define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \
+		     (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
+		     (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888) | \
+		     (img == MDP_RGBX_8888))
+#define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
+			(img == MDP_BGRA_8888))
+
+#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
+			    (img == MDP_Y_CBCR_H2V2) | \
+			    (img == MDP_Y_CRCB_H2V1) | \
+			    (img == MDP_Y_CBCR_H2V1))
+
+/* Mappings from addr to purpose */
+#define PPP_ADDR_SRC_ROI		MDP_FULL_BYPASS_WORD2
+#define PPP_ADDR_SRC0			MDP_FULL_BYPASS_WORD3
+#define PPP_ADDR_SRC1			MDP_FULL_BYPASS_WORD4
+#define PPP_ADDR_SRC_YSTRIDE		MDP_FULL_BYPASS_WORD7
+#define PPP_ADDR_SRC_CFG		MDP_FULL_BYPASS_WORD9
+#define PPP_ADDR_SRC_PACK_PATTERN	MDP_FULL_BYPASS_WORD10
+#define PPP_ADDR_OPERATION		MDP_FULL_BYPASS_WORD14
+#define PPP_ADDR_PHASEX_INIT		MDP_FULL_BYPASS_WORD15
+#define PPP_ADDR_PHASEY_INIT		MDP_FULL_BYPASS_WORD16
+#define PPP_ADDR_PHASEX_STEP		MDP_FULL_BYPASS_WORD17
+#define PPP_ADDR_PHASEY_STEP		MDP_FULL_BYPASS_WORD18
+#define PPP_ADDR_ALPHA_TRANSP		MDP_FULL_BYPASS_WORD19
+#define PPP_ADDR_DST_CFG		MDP_FULL_BYPASS_WORD20
+#define PPP_ADDR_DST_PACK_PATTERN	MDP_FULL_BYPASS_WORD21
+#define PPP_ADDR_DST_ROI		MDP_FULL_BYPASS_WORD25
+#define PPP_ADDR_DST0			MDP_FULL_BYPASS_WORD26
+#define PPP_ADDR_DST1			MDP_FULL_BYPASS_WORD27
+#define PPP_ADDR_DST_YSTRIDE		MDP_FULL_BYPASS_WORD30
+#define PPP_ADDR_EDGE			MDP_FULL_BYPASS_WORD46
+#define PPP_ADDR_BG0			MDP_FULL_BYPASS_WORD48
+#define PPP_ADDR_BG1			MDP_FULL_BYPASS_WORD49
+#define PPP_ADDR_BG_YSTRIDE		MDP_FULL_BYPASS_WORD51
+#define PPP_ADDR_BG_CFG			MDP_FULL_BYPASS_WORD53
+#define PPP_ADDR_BG_PACK_PATTERN	MDP_FULL_BYPASS_WORD54
+
+/* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */
+#define DMA_DSTC0G_6BITS (1<<1)
+#define DMA_DSTC1B_6BITS (1<<3)
+#define DMA_DSTC2R_6BITS (1<<5)
+#define DMA_DSTC0G_5BITS (1<<0)
+#define DMA_DSTC1B_5BITS (1<<2)
+#define DMA_DSTC2R_5BITS (1<<4)
+
+#define DMA_PACK_TIGHT (1<<6)
+#define DMA_PACK_LOOSE 0
+#define DMA_PACK_ALIGN_LSB 0
+#define DMA_PACK_ALIGN_MSB (1<<7)
+#define DMA_PACK_PATTERN_RGB \
+	(MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
+
+#define DMA_OUT_SEL_AHB  0
+#define DMA_OUT_SEL_MDDI (1<<14)
+#define DMA_AHBM_LCD_SEL_PRIMARY 0
+#define DMA_AHBM_LCD_SEL_SECONDARY (1<<15)
+#define DMA_IBUF_C3ALPHA_EN (1<<16)
+#define DMA_DITHER_EN (1<<17)
+
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (1<<18)
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (1<<19)
+
+#define DMA_IBUF_FORMAT_RGB565 (1<<20)
+#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
+
+#define DMA_IBUF_NONCONTIGUOUS (1<<21)
+
+/* MDDI REGISTER ? */
+#define MDDI_VDO_PACKET_DESC  0x5666
+#define MDDI_VDO_PACKET_PRIM  0xC3
+#define MDDI_VDO_PACKET_SECD  0xC0
+
+#endif
diff --git a/drivers/video/fbdev/msm/mdp_ppp.c b/drivers/video/fbdev/msm/mdp_ppp.c
new file mode 100644
index 000000000000..be6079cdfbb6
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdp_ppp.c
@@ -0,0 +1,731 @@
+/* drivers/video/msm/mdp_ppp.c
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/fb.h>
+#include <linux/file.h>
+#include <linux/delay.h>
+#include <linux/msm_mdp.h>
+#include <linux/platform_data/video-msm_fb.h>
+
+#include "mdp_hw.h"
+#include "mdp_scale_tables.h"
+
+#define DLOG(x...) do {} while (0)
+
+#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1)
+static int downscale_y_table = MDP_DOWNSCALE_MAX;
+static int downscale_x_table = MDP_DOWNSCALE_MAX;
+
+struct mdp_regs {
+	uint32_t src0;
+	uint32_t src1;
+	uint32_t dst0;
+	uint32_t dst1;
+	uint32_t src_cfg;
+	uint32_t dst_cfg;
+	uint32_t src_pack;
+	uint32_t dst_pack;
+	uint32_t src_rect;
+	uint32_t dst_rect;
+	uint32_t src_ystride;
+	uint32_t dst_ystride;
+	uint32_t op;
+	uint32_t src_bpp;
+	uint32_t dst_bpp;
+	uint32_t edge;
+	uint32_t phasex_init;
+	uint32_t phasey_init;
+	uint32_t phasex_step;
+	uint32_t phasey_step;
+};
+
+static uint32_t pack_pattern[] = {
+	PPP_ARRAY0(PACK_PATTERN)
+};
+
+static uint32_t src_img_cfg[] = {
+	PPP_ARRAY1(CFG, SRC)
+};
+
+static uint32_t dst_img_cfg[] = {
+	PPP_ARRAY1(CFG, DST)
+};
+
+static uint32_t bytes_per_pixel[] = {
+	[MDP_RGB_565] = 2,
+	[MDP_RGB_888] = 3,
+	[MDP_XRGB_8888] = 4,
+	[MDP_ARGB_8888] = 4,
+	[MDP_RGBA_8888] = 4,
+	[MDP_BGRA_8888] = 4,
+	[MDP_RGBX_8888] = 4,
+	[MDP_Y_CBCR_H2V1] = 1,
+	[MDP_Y_CBCR_H2V2] = 1,
+	[MDP_Y_CRCB_H2V1] = 1,
+	[MDP_Y_CRCB_H2V2] = 1,
+	[MDP_YCRYCB_H2V1] = 2
+};
+
+static uint32_t dst_op_chroma[] = {
+	PPP_ARRAY1(CHROMA_SAMP, DST)
+};
+
+static uint32_t src_op_chroma[] = {
+	PPP_ARRAY1(CHROMA_SAMP, SRC)
+};
+
+static uint32_t bg_op_chroma[] = {
+	PPP_ARRAY1(CHROMA_SAMP, BG)
+};
+
+static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs)
+{
+	regs->dst0 += (req->dst_rect.w -
+		       min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
+	regs->dst1 += (req->dst_rect.w -
+		       min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
+}
+
+static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs)
+{
+	regs->dst0 += (req->dst_rect.h -
+		       min((uint32_t)16, req->dst_rect.h)) *
+		       regs->dst_ystride;
+	regs->dst1 += (req->dst_rect.h -
+		       min((uint32_t)16, req->dst_rect.h)) *
+		       regs->dst_ystride;
+}
+
+static void blit_rotate(struct mdp_blit_req *req,
+			struct mdp_regs *regs)
+{
+	if (req->flags == MDP_ROT_NOP)
+		return;
+
+	regs->op |= PPP_OP_ROT_ON;
+	if ((req->flags & MDP_ROT_90 || req->flags & MDP_FLIP_LR) &&
+	    !(req->flags & MDP_ROT_90 && req->flags & MDP_FLIP_LR))
+		rotate_dst_addr_x(req, regs);
+	if (req->flags & MDP_ROT_90)
+		regs->op |= PPP_OP_ROT_90;
+	if (req->flags & MDP_FLIP_UD) {
+		regs->op |= PPP_OP_FLIP_UD;
+		rotate_dst_addr_y(req, regs);
+	}
+	if (req->flags & MDP_FLIP_LR)
+		regs->op |= PPP_OP_FLIP_LR;
+}
+
+static void blit_convert(struct mdp_blit_req *req, struct mdp_regs *regs)
+{
+	if (req->src.format == req->dst.format)
+		return;
+	if (IS_RGB(req->src.format) && IS_YCRCB(req->dst.format)) {
+		regs->op |= PPP_OP_CONVERT_RGB2YCBCR | PPP_OP_CONVERT_ON;
+	} else if (IS_YCRCB(req->src.format) && IS_RGB(req->dst.format)) {
+		regs->op |= PPP_OP_CONVERT_YCBCR2RGB | PPP_OP_CONVERT_ON;
+		if (req->dst.format == MDP_RGB_565)
+			regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY;
+	}
+}
+
+#define GET_BIT_RANGE(value, high, low) \
+	(((1 << (high - low + 1)) - 1) & (value >> low))
+static uint32_t transp_convert(struct mdp_blit_req *req)
+{
+	uint32_t transp = 0;
+	if (req->src.format == MDP_RGB_565) {
+		/* pad each value to 8 bits by copying the high bits into the
+		 * low end, convert RGB to RBG by switching low 2 components */
+		transp |= ((GET_BIT_RANGE(req->transp_mask, 15, 11) << 3) |
+			   (GET_BIT_RANGE(req->transp_mask, 15, 13))) << 16;
+
+		transp |= ((GET_BIT_RANGE(req->transp_mask, 4, 0) << 3) |
+			   (GET_BIT_RANGE(req->transp_mask, 4, 2))) << 8;
+
+		transp |= (GET_BIT_RANGE(req->transp_mask, 10, 5) << 2) |
+			  (GET_BIT_RANGE(req->transp_mask, 10, 9));
+	} else {
+		/* convert RGB to RBG */
+		transp |= (GET_BIT_RANGE(req->transp_mask, 15, 8)) |
+			  (GET_BIT_RANGE(req->transp_mask, 23, 16) << 16) |
+			  (GET_BIT_RANGE(req->transp_mask, 7, 0) << 8);
+	}
+	return transp;
+}
+#undef GET_BIT_RANGE
+
+static void blit_blend(struct mdp_blit_req *req, struct mdp_regs *regs)
+{
+	/* TRANSP BLEND */
+	if (req->transp_mask != MDP_TRANSP_NOP) {
+		req->transp_mask = transp_convert(req);
+		if (req->alpha != MDP_ALPHA_NOP) {
+			/* use blended transparancy mode
+			 * pixel = (src == transp) ? dst : blend
+			 * blend is combo of blend_eq_sel and
+			 * blend_alpha_sel */
+			regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+				PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+				PPP_OP_BLEND_CONSTANT_ALPHA |
+				PPP_BLEND_ALPHA_TRANSP;
+		} else {
+			/* simple transparancy mode
+			 * pixel = (src == transp) ? dst : src */
+			regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+				PPP_OP_BLEND_SRCPIXEL_TRANSP;
+		}
+	}
+
+	req->alpha &= 0xff;
+	/* ALPHA BLEND */
+	if (HAS_ALPHA(req->src.format)) {
+		regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+			PPP_OP_BLEND_SRCPIXEL_ALPHA;
+	} else if (req->alpha < MDP_ALPHA_NOP) {
+		/* just blend by alpha */
+		regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+			PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+			PPP_OP_BLEND_CONSTANT_ALPHA;
+	}
+
+	regs->op |= bg_op_chroma[req->dst.format];
+}
+
+#define ONE_HALF	(1LL << 32)
+#define ONE		(1LL << 33)
+#define TWO		(2LL << 33)
+#define THREE		(3LL << 33)
+#define FRAC_MASK (ONE - 1)
+#define INT_MASK (~FRAC_MASK)
+
+static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
+			uint32_t *phase_init, uint32_t *phase_step)
+{
+	/* to improve precicsion calculations are done in U31.33 and converted
+	 * to U3.29 at the end */
+	int64_t k1, k2, k3, k4, tmp;
+	uint64_t n, d, os, os_p, od, od_p, oreq;
+	unsigned rpa = 0;
+	int64_t ip64, delta;
+
+	if (dim_out % 3 == 0)
+		rpa = !(dim_in % (dim_out / 3));
+
+	n = ((uint64_t)dim_out) << 34;
+	d = dim_in;
+	if (!d)
+		return -1;
+	do_div(n, d);
+	k3 = (n + 1) >> 1;
+	if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) {
+		DLOG("crap bad scale\n");
+		return -1;
+	}
+	n = ((uint64_t)dim_in) << 34;
+	d = (uint64_t)dim_out;
+	if (!d)
+		return -1;
+	do_div(n, d);
+	k1 = (n + 1) >> 1;
+	k2 = (k1 - ONE) >> 1;
+
+	*phase_init = (int)(k2 >> 4);
+	k4 = (k3 - ONE) >> 1;
+
+	if (rpa) {
+		os = ((uint64_t)origin << 33) - ONE_HALF;
+		tmp = (dim_out * os) + ONE_HALF;
+		if (!dim_in)
+			return -1;
+		do_div(tmp, dim_in);
+		od = tmp - ONE_HALF;
+	} else {
+		os = ((uint64_t)origin << 1) - 1;
+		od = (((k3 * os) >> 1) + k4);
+	}
+
+	od_p = od & INT_MASK;
+	if (od_p != od)
+		od_p += ONE;
+
+	if (rpa) {
+		tmp = (dim_in * od_p) + ONE_HALF;
+		if (!dim_in)
+			return -1;
+		do_div(tmp, dim_in);
+		os_p = tmp - ONE_HALF;
+	} else {
+		os_p = ((k1 * (od_p >> 33)) + k2);
+	}
+
+	oreq = (os_p & INT_MASK) - ONE;
+
+	ip64 = os_p - oreq;
+	delta = ((int64_t)(origin) << 33) - oreq;
+	ip64 -= delta;
+	/* limit to valid range before the left shift */
+	delta = (ip64 & (1LL << 63)) ? 4 : -4;
+	delta <<= 33;
+	while (abs((int)(ip64 >> 33)) > 4)
+		ip64 += delta;
+	*phase_init = (int)(ip64 >> 4);
+	*phase_step = (uint32_t)(k1 >> 4);
+	return 0;
+}
+
+static void load_scale_table(const struct mdp_info *mdp,
+			     struct mdp_table_entry *table, int len)
+{
+	int i;
+	for (i = 0; i < len; i++)
+		mdp_writel(mdp, table[i].val, table[i].reg);
+}
+
+enum {
+IMG_LEFT,
+IMG_RIGHT,
+IMG_TOP,
+IMG_BOTTOM,
+};
+
+static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
+			  uint32_t *interp1, uint32_t *interp2,
+			  uint32_t *repeat1, uint32_t *repeat2) {
+	if (src > 3 * dst) {
+		*interp1 = 0;
+		*interp2 = src - 1;
+		*repeat1 = 0;
+		*repeat2 = 0;
+	} else if (src == 3 * dst) {
+		*interp1 = 0;
+		*interp2 = src;
+		*repeat1 = 0;
+		*repeat2 = 1;
+	} else if (src > dst && src < 3 * dst) {
+		*interp1 = -1;
+		*interp2 = src;
+		*repeat1 = 1;
+		*repeat2 = 1;
+	} else if (src == dst) {
+		*interp1 = -1;
+		*interp2 = src + 1;
+		*repeat1 = 1;
+		*repeat2 = 2;
+	} else {
+		*interp1 = -2;
+		*interp2 = src + 1;
+		*repeat1 = 2;
+		*repeat2 = 2;
+	}
+	*interp1 += src_coord;
+	*interp2 += src_coord;
+}
+
+static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs)
+{
+	int32_t luma_interp[4];
+	int32_t luma_repeat[4];
+	int32_t chroma_interp[4];
+	int32_t chroma_bound[4];
+	int32_t chroma_repeat[4];
+	uint32_t dst_w, dst_h;
+
+	memset(&luma_interp, 0, sizeof(int32_t) * 4);
+	memset(&luma_repeat, 0, sizeof(int32_t) * 4);
+	memset(&chroma_interp, 0, sizeof(int32_t) * 4);
+	memset(&chroma_bound, 0, sizeof(int32_t) * 4);
+	memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
+	regs->edge = 0;
+
+	if (req->flags & MDP_ROT_90) {
+		dst_w = req->dst_rect.h;
+		dst_h = req->dst_rect.w;
+	} else {
+		dst_w = req->dst_rect.w;
+		dst_h = req->dst_rect.h;
+	}
+
+	if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
+		get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
+			      &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
+			      &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
+		get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
+			      &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
+			      &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
+	} else {
+		luma_interp[IMG_LEFT] = req->src_rect.x;
+		luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
+		luma_interp[IMG_TOP] = req->src_rect.y;
+		luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
+		luma_repeat[IMG_LEFT] = 0;
+		luma_repeat[IMG_TOP] = 0;
+		luma_repeat[IMG_RIGHT] = 0;
+		luma_repeat[IMG_BOTTOM] = 0;
+	}
+
+	chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
+	chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
+	chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
+	chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
+
+	chroma_bound[IMG_LEFT] = req->src_rect.x;
+	chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
+	chroma_bound[IMG_TOP] = req->src_rect.y;
+	chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
+
+	if (IS_YCRCB(req->src.format)) {
+		chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
+		chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
+
+		chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
+		chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
+	}
+
+	if (req->src.format == MDP_Y_CBCR_H2V2 ||
+	    req->src.format == MDP_Y_CRCB_H2V2) {
+		chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
+		chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
+					    >> 1;
+		chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
+		chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
+	}
+
+	chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
+				  chroma_interp[IMG_LEFT];
+	chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
+				  chroma_bound[IMG_RIGHT];
+	chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
+				  chroma_interp[IMG_TOP];
+	chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
+				  chroma_bound[IMG_BOTTOM];
+
+	if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
+	    chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
+	    chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
+	    chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
+	    luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
+	    luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
+	    luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
+	    luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
+		return -1;
+
+	regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
+	regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
+	regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
+	regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
+	regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
+	regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
+	regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
+	regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
+	return 0;
+}
+
+static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
+		      struct mdp_regs *regs)
+{
+	uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
+	uint32_t scale_factor_x, scale_factor_y;
+	uint32_t downscale;
+	uint32_t dst_w, dst_h;
+
+	if (req->flags & MDP_ROT_90) {
+		dst_w = req->dst_rect.h;
+		dst_h = req->dst_rect.w;
+	} else {
+		dst_w = req->dst_rect.w;
+		dst_h = req->dst_rect.h;
+	}
+	if ((req->src_rect.w == dst_w)  && (req->src_rect.h == dst_h) &&
+	    !(req->flags & MDP_BLUR)) {
+		regs->phasex_init = 0;
+		regs->phasey_init = 0;
+		regs->phasex_step = 0;
+		regs->phasey_step = 0;
+		return 0;
+	}
+
+	if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x,
+			 &phase_step_x) ||
+	    scale_params(req->src_rect.h, dst_h, 1, &phase_init_y,
+			 &phase_step_y))
+		return -1;
+
+	scale_factor_x = (dst_w * 10) / req->src_rect.w;
+	scale_factor_y = (dst_h * 10) / req->src_rect.h;
+
+	if (scale_factor_x > 8)
+		downscale = MDP_DOWNSCALE_PT8TO1;
+	else if (scale_factor_x > 6)
+		downscale = MDP_DOWNSCALE_PT6TOPT8;
+	else if (scale_factor_x > 4)
+		downscale = MDP_DOWNSCALE_PT4TOPT6;
+	else
+		downscale = MDP_DOWNSCALE_PT2TOPT4;
+	if (downscale != downscale_x_table) {
+		load_scale_table(mdp, mdp_downscale_x_table[downscale], 64);
+		downscale_x_table = downscale;
+	}
+
+	if (scale_factor_y > 8)
+		downscale = MDP_DOWNSCALE_PT8TO1;
+	else if (scale_factor_y > 6)
+		downscale = MDP_DOWNSCALE_PT6TOPT8;
+	else if (scale_factor_y > 4)
+		downscale = MDP_DOWNSCALE_PT4TOPT6;
+	else
+		downscale = MDP_DOWNSCALE_PT2TOPT4;
+	if (downscale != downscale_y_table) {
+		load_scale_table(mdp, mdp_downscale_y_table[downscale], 64);
+		downscale_y_table = downscale;
+	}
+
+	regs->phasex_init = phase_init_x;
+	regs->phasey_init = phase_init_y;
+	regs->phasex_step = phase_step_x;
+	regs->phasey_step = phase_step_y;
+	regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+	return 0;
+
+}
+
+static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
+		      struct mdp_regs *regs)
+{
+	if (!(req->flags & MDP_BLUR))
+		return;
+
+	if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
+	      downscale_y_table == MDP_DOWNSCALE_BLUR)) {
+		load_scale_table(mdp, mdp_gaussian_blur_table, 128);
+		downscale_x_table = MDP_DOWNSCALE_BLUR;
+		downscale_y_table = MDP_DOWNSCALE_BLUR;
+	}
+
+	regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+}
+
+
+#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
+
+#define Y_TO_CRCB_RATIO(format) \
+	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
+	 (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
+
+static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
+		    uint32_t *len0, uint32_t *len1)
+{
+	*len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
+	if (IS_PSEUDOPLNR(img->format))
+		*len1 = *len0/Y_TO_CRCB_RATIO(img->format);
+	else
+		*len1 = 0;
+}
+
+static int valid_src_dst(unsigned long src_start, unsigned long src_len,
+			 unsigned long dst_start, unsigned long dst_len,
+			 struct mdp_blit_req *req, struct mdp_regs *regs)
+{
+	unsigned long src_min_ok = src_start;
+	unsigned long src_max_ok = src_start + src_len;
+	unsigned long dst_min_ok = dst_start;
+	unsigned long dst_max_ok = dst_start + dst_len;
+	uint32_t src0_len, src1_len, dst0_len, dst1_len;
+	get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
+		 &src1_len);
+	get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
+		 &dst1_len);
+
+	if (regs->src0 < src_min_ok || regs->src0 > src_max_ok ||
+	    regs->src0 + src0_len > src_max_ok) {
+		DLOG("invalid_src %x %x %lx %lx\n", regs->src0,
+		      src0_len, src_min_ok, src_max_ok);
+		return 0;
+	}
+	if (regs->src_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
+		if (regs->src1 < src_min_ok || regs->src1 > src_max_ok ||
+		    regs->src1 + src1_len > src_max_ok) {
+			DLOG("invalid_src1");
+			return 0;
+		}
+	}
+	if (regs->dst0 < dst_min_ok || regs->dst0 > dst_max_ok ||
+	    regs->dst0 + dst0_len > dst_max_ok) {
+		DLOG("invalid_dst");
+		return 0;
+	}
+	if (regs->dst_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
+		if (regs->dst1 < dst_min_ok || regs->dst1 > dst_max_ok ||
+		    regs->dst1 + dst1_len > dst_max_ok) {
+			DLOG("invalid_dst1");
+			return 0;
+		}
+	}
+	return 1;
+}
+
+
+static void flush_imgs(struct mdp_blit_req *req, struct mdp_regs *regs,
+		       struct file *src_file, struct file *dst_file)
+{
+}
+
+static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
+			    uint32_t base, uint32_t bpp, uint32_t cfg,
+			    uint32_t *addr, uint32_t *ystride)
+{
+	uint32_t compress_v = Y_TO_CRCB_RATIO(img->format);
+	uint32_t compress_h = 2;
+	uint32_t  offset;
+
+	if (IS_PSEUDOPLNR(img->format)) {
+		offset = (rect->x / compress_h) * compress_h;
+		offset += rect->y == 0 ? 0 :
+			  ((rect->y + 1) / compress_v) * img->width;
+		*addr = base + (img->width * img->height * bpp);
+		*addr += offset * bpp;
+		*ystride |= *ystride << 16;
+	} else {
+		*addr = 0;
+	}
+}
+
+static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
+		     struct mdp_regs *regs, struct file *src_file,
+		     struct file *dst_file)
+{
+	mdp_writel(mdp, 1, 0x060);
+	mdp_writel(mdp, regs->src_rect, PPP_ADDR_SRC_ROI);
+	mdp_writel(mdp, regs->src0, PPP_ADDR_SRC0);
+	mdp_writel(mdp, regs->src1, PPP_ADDR_SRC1);
+	mdp_writel(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE);
+	mdp_writel(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG);
+	mdp_writel(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN);
+
+	mdp_writel(mdp, regs->op, PPP_ADDR_OPERATION);
+	mdp_writel(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT);
+	mdp_writel(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT);
+	mdp_writel(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
+	mdp_writel(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);
+
+	mdp_writel(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
+	       PPP_ADDR_ALPHA_TRANSP);
+
+	mdp_writel(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG);
+	mdp_writel(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN);
+	mdp_writel(mdp, regs->dst_rect, PPP_ADDR_DST_ROI);
+	mdp_writel(mdp, regs->dst0, PPP_ADDR_DST0);
+	mdp_writel(mdp, regs->dst1, PPP_ADDR_DST1);
+	mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE);
+
+	mdp_writel(mdp, regs->edge, PPP_ADDR_EDGE);
+	if (regs->op & PPP_OP_BLEND_ON) {
+		mdp_writel(mdp, regs->dst0, PPP_ADDR_BG0);
+		mdp_writel(mdp, regs->dst1, PPP_ADDR_BG1);
+		mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_BG_YSTRIDE);
+		mdp_writel(mdp, src_img_cfg[req->dst.format], PPP_ADDR_BG_CFG);
+		mdp_writel(mdp, pack_pattern[req->dst.format],
+			   PPP_ADDR_BG_PACK_PATTERN);
+	}
+	flush_imgs(req, regs, src_file, dst_file);
+	mdp_writel(mdp, 0x1000, MDP_DISPLAY0_START);
+	return 0;
+}
+
+int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
+		 struct file *src_file, unsigned long src_start, unsigned long src_len,
+		 struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
+{
+	struct mdp_regs regs = {0};
+
+	if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
+		     req->dst.format >= MDP_IMGTYPE_LIMIT)) {
+		printk(KERN_ERR "mpd_ppp: img is of wrong format\n");
+		return -EINVAL;
+	}
+
+	if (unlikely(req->src_rect.x > req->src.width ||
+		     req->src_rect.y > req->src.height ||
+		     req->dst_rect.x > req->dst.width ||
+		     req->dst_rect.y > req->dst.height)) {
+		printk(KERN_ERR "mpd_ppp: img rect is outside of img!\n");
+		return -EINVAL;
+	}
+
+	/* set the src image configuration */
+	regs.src_cfg = src_img_cfg[req->src.format];
+	regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0;
+	regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
+	regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w;
+	regs.src_pack = pack_pattern[req->src.format];
+
+	/* set the dest image configuration */
+	regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI;
+	regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w;
+	regs.dst_pack = pack_pattern[req->dst.format];
+
+	/* set src, bpp, start pixel and ystride */
+	regs.src_bpp = bytes_per_pixel[req->src.format];
+	regs.src0 = src_start + req->src.offset;
+	regs.src_ystride = req->src.width * regs.src_bpp;
+	get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
+			regs.src_cfg, &regs.src1, &regs.src_ystride);
+	regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) *
+		      regs.src_bpp;
+
+	/* set dst, bpp, start pixel and ystride */
+	regs.dst_bpp = bytes_per_pixel[req->dst.format];
+	regs.dst0 = dst_start + req->dst.offset;
+	regs.dst_ystride = req->dst.width * regs.dst_bpp;
+	get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
+			regs.dst_cfg, &regs.dst1, &regs.dst_ystride);
+	regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) *
+		      regs.dst_bpp;
+
+	if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
+			   &regs)) {
+		printk(KERN_ERR "mpd_ppp: final src or dst location is "
+			"invalid, are you trying to make an image too large "
+			"or to place it outside the screen?\n");
+		return -EINVAL;
+	}
+
+	/* set up operation register */
+	regs.op = 0;
+	blit_rotate(req, &regs);
+	blit_convert(req, &regs);
+	if (req->flags & MDP_DITHER)
+		regs.op |= PPP_OP_DITHER_EN;
+	blit_blend(req, &regs);
+	if (blit_scale(mdp, req, &regs)) {
+		printk(KERN_ERR "mpd_ppp: error computing scale for img.\n");
+		return -EINVAL;
+	}
+	blit_blur(mdp, req, &regs);
+	regs.op |= dst_op_chroma[req->dst.format] |
+		   src_op_chroma[req->src.format];
+
+	/* if the image is YCRYCB, the x and w must be even */
+	if (unlikely(req->src.format == MDP_YCRYCB_H2V1)) {
+		req->src_rect.x = req->src_rect.x & (~0x1);
+		req->src_rect.w = req->src_rect.w & (~0x1);
+		req->dst_rect.x = req->dst_rect.x & (~0x1);
+		req->dst_rect.w = req->dst_rect.w & (~0x1);
+	}
+	if (get_edge_cond(req, &regs))
+		return -EINVAL;
+
+	send_blit(mdp, req, &regs, src_file, dst_file);
+	return 0;
+}
diff --git a/drivers/video/fbdev/msm/mdp_scale_tables.c b/drivers/video/fbdev/msm/mdp_scale_tables.c
new file mode 100644
index 000000000000..604783b2e17c
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdp_scale_tables.c
@@ -0,0 +1,766 @@
+/* drivers/video/msm_fb/mdp_scale_tables.c
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "mdp_scale_tables.h"
+#include "mdp_hw.h"
+
+struct mdp_table_entry mdp_upscale_table[] = {
+	{ 0x5fffc, 0x0 },
+	{ 0x50200, 0x7fc00000 },
+	{ 0x5fffc, 0xff80000d },
+	{ 0x50204, 0x7ec003f9 },
+	{ 0x5fffc, 0xfec0001c },
+	{ 0x50208, 0x7d4003f3 },
+	{ 0x5fffc, 0xfe40002b },
+	{ 0x5020c, 0x7b8003ed },
+	{ 0x5fffc, 0xfd80003c },
+	{ 0x50210, 0x794003e8 },
+	{ 0x5fffc, 0xfcc0004d },
+	{ 0x50214, 0x76c003e4 },
+	{ 0x5fffc, 0xfc40005f },
+	{ 0x50218, 0x73c003e0 },
+	{ 0x5fffc, 0xfb800071 },
+	{ 0x5021c, 0x708003de },
+	{ 0x5fffc, 0xfac00085 },
+	{ 0x50220, 0x6d0003db },
+	{ 0x5fffc, 0xfa000098 },
+	{ 0x50224, 0x698003d9 },
+	{ 0x5fffc, 0xf98000ac },
+	{ 0x50228, 0x654003d8 },
+	{ 0x5fffc, 0xf8c000c1 },
+	{ 0x5022c, 0x610003d7 },
+	{ 0x5fffc, 0xf84000d5 },
+	{ 0x50230, 0x5c8003d7 },
+	{ 0x5fffc, 0xf7c000e9 },
+	{ 0x50234, 0x580003d7 },
+	{ 0x5fffc, 0xf74000fd },
+	{ 0x50238, 0x534003d8 },
+	{ 0x5fffc, 0xf6c00112 },
+	{ 0x5023c, 0x4e8003d8 },
+	{ 0x5fffc, 0xf6800126 },
+	{ 0x50240, 0x494003da },
+	{ 0x5fffc, 0xf600013a },
+	{ 0x50244, 0x448003db },
+	{ 0x5fffc, 0xf600014d },
+	{ 0x50248, 0x3f4003dd },
+	{ 0x5fffc, 0xf5c00160 },
+	{ 0x5024c, 0x3a4003df },
+	{ 0x5fffc, 0xf5c00172 },
+	{ 0x50250, 0x354003e1 },
+	{ 0x5fffc, 0xf5c00184 },
+	{ 0x50254, 0x304003e3 },
+	{ 0x5fffc, 0xf6000195 },
+	{ 0x50258, 0x2b0003e6 },
+	{ 0x5fffc, 0xf64001a6 },
+	{ 0x5025c, 0x260003e8 },
+	{ 0x5fffc, 0xf6c001b4 },
+	{ 0x50260, 0x214003eb },
+	{ 0x5fffc, 0xf78001c2 },
+	{ 0x50264, 0x1c4003ee },
+	{ 0x5fffc, 0xf80001cf },
+	{ 0x50268, 0x17c003f1 },
+	{ 0x5fffc, 0xf90001db },
+	{ 0x5026c, 0x134003f3 },
+	{ 0x5fffc, 0xfa0001e5 },
+	{ 0x50270, 0xf0003f6 },
+	{ 0x5fffc, 0xfb4001ee },
+	{ 0x50274, 0xac003f9 },
+	{ 0x5fffc, 0xfcc001f5 },
+	{ 0x50278, 0x70003fb },
+	{ 0x5fffc, 0xfe4001fb },
+	{ 0x5027c, 0x34003fe },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT2TOPT4[] = {
+	{ 0x5fffc, 0x740008c },
+	{ 0x50280, 0x33800088 },
+	{ 0x5fffc, 0x800008e },
+	{ 0x50284, 0x33400084 },
+	{ 0x5fffc, 0x8400092 },
+	{ 0x50288, 0x33000080 },
+	{ 0x5fffc, 0x9000094 },
+	{ 0x5028c, 0x3300007b },
+	{ 0x5fffc, 0x9c00098 },
+	{ 0x50290, 0x32400077 },
+	{ 0x5fffc, 0xa40009b },
+	{ 0x50294, 0x32000073 },
+	{ 0x5fffc, 0xb00009d },
+	{ 0x50298,  0x31c0006f },
+	{ 0x5fffc,  0xbc000a0 },
+	{ 0x5029c,  0x3140006b },
+	{ 0x5fffc,  0xc8000a2 },
+	{ 0x502a0,  0x31000067 },
+	{ 0x5fffc,  0xd8000a5 },
+	{ 0x502a4,  0x30800062 },
+	{ 0x5fffc,  0xe4000a8 },
+	{ 0x502a8,  0x2fc0005f },
+	{ 0x5fffc,  0xec000aa },
+	{ 0x502ac,  0x2fc0005b },
+	{ 0x5fffc,  0xf8000ad },
+	{ 0x502b0,  0x2f400057 },
+	{ 0x5fffc,  0x108000b0 },
+	{ 0x502b4,  0x2e400054 },
+	{ 0x5fffc,  0x114000b2 },
+	{ 0x502b8,  0x2e000050 },
+	{ 0x5fffc,  0x124000b4 },
+	{ 0x502bc,  0x2d80004c },
+	{ 0x5fffc,  0x130000b6 },
+	{ 0x502c0,  0x2d000049 },
+	{ 0x5fffc,  0x140000b8 },
+	{ 0x502c4,  0x2c800045 },
+	{ 0x5fffc,  0x150000b9 },
+	{ 0x502c8,  0x2c000042 },
+	{ 0x5fffc,  0x15c000bd },
+	{ 0x502cc,  0x2b40003e },
+	{ 0x5fffc,  0x16c000bf },
+	{ 0x502d0,  0x2a80003b },
+	{ 0x5fffc,  0x17c000bf },
+	{ 0x502d4,  0x2a000039 },
+	{ 0x5fffc,  0x188000c2 },
+	{ 0x502d8,  0x29400036 },
+	{ 0x5fffc,  0x19c000c4 },
+	{ 0x502dc,  0x28800032 },
+	{ 0x5fffc,  0x1ac000c5 },
+	{ 0x502e0,  0x2800002f },
+	{ 0x5fffc,  0x1bc000c7 },
+	{ 0x502e4,  0x2740002c },
+	{ 0x5fffc,  0x1cc000c8 },
+	{ 0x502e8,  0x26c00029 },
+	{ 0x5fffc,  0x1dc000c9 },
+	{ 0x502ec,  0x26000027 },
+	{ 0x5fffc,  0x1ec000cc },
+	{ 0x502f0,  0x25000024 },
+	{ 0x5fffc,  0x200000cc },
+	{ 0x502f4,  0x24800021 },
+	{ 0x5fffc,  0x210000cd },
+	{ 0x502f8,  0x23800020 },
+	{ 0x5fffc,  0x220000ce },
+	{ 0x502fc,  0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT4TOPT6[] = {
+	{ 0x5fffc,  0x740008c },
+	{ 0x50280,  0x33800088 },
+	{ 0x5fffc,  0x800008e },
+	{ 0x50284,  0x33400084 },
+	{ 0x5fffc,  0x8400092 },
+	{ 0x50288,  0x33000080 },
+	{ 0x5fffc,  0x9000094 },
+	{ 0x5028c,  0x3300007b },
+	{ 0x5fffc,  0x9c00098 },
+	{ 0x50290,  0x32400077 },
+	{ 0x5fffc,  0xa40009b },
+	{ 0x50294,  0x32000073 },
+	{ 0x5fffc,  0xb00009d },
+	{ 0x50298,  0x31c0006f },
+	{ 0x5fffc,  0xbc000a0 },
+	{ 0x5029c,  0x3140006b },
+	{ 0x5fffc,  0xc8000a2 },
+	{ 0x502a0,  0x31000067 },
+	{ 0x5fffc,  0xd8000a5 },
+	{ 0x502a4,  0x30800062 },
+	{ 0x5fffc,  0xe4000a8 },
+	{ 0x502a8,  0x2fc0005f },
+	{ 0x5fffc,  0xec000aa },
+	{ 0x502ac,  0x2fc0005b },
+	{ 0x5fffc,  0xf8000ad },
+	{ 0x502b0,  0x2f400057 },
+	{ 0x5fffc,  0x108000b0 },
+	{ 0x502b4,  0x2e400054 },
+	{ 0x5fffc,  0x114000b2 },
+	{ 0x502b8,  0x2e000050 },
+	{ 0x5fffc,  0x124000b4 },
+	{ 0x502bc,  0x2d80004c },
+	{ 0x5fffc,  0x130000b6 },
+	{ 0x502c0,  0x2d000049 },
+	{ 0x5fffc,  0x140000b8 },
+	{ 0x502c4,  0x2c800045 },
+	{ 0x5fffc,  0x150000b9 },
+	{ 0x502c8,  0x2c000042 },
+	{ 0x5fffc,  0x15c000bd },
+	{ 0x502cc,  0x2b40003e },
+	{ 0x5fffc,  0x16c000bf },
+	{ 0x502d0,  0x2a80003b },
+	{ 0x5fffc,  0x17c000bf },
+	{ 0x502d4,  0x2a000039 },
+	{ 0x5fffc,  0x188000c2 },
+	{ 0x502d8,  0x29400036 },
+	{ 0x5fffc,  0x19c000c4 },
+	{ 0x502dc,  0x28800032 },
+	{ 0x5fffc,  0x1ac000c5 },
+	{ 0x502e0,  0x2800002f },
+	{ 0x5fffc,  0x1bc000c7 },
+	{ 0x502e4,  0x2740002c },
+	{ 0x5fffc,  0x1cc000c8 },
+	{ 0x502e8,  0x26c00029 },
+	{ 0x5fffc,  0x1dc000c9 },
+	{ 0x502ec,  0x26000027 },
+	{ 0x5fffc,  0x1ec000cc },
+	{ 0x502f0,  0x25000024 },
+	{ 0x5fffc,  0x200000cc },
+	{ 0x502f4,  0x24800021 },
+	{ 0x5fffc,  0x210000cd },
+	{ 0x502f8,  0x23800020 },
+	{ 0x5fffc,  0x220000ce },
+	{ 0x502fc,  0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT6TOPT8[] = {
+	{ 0x5fffc,  0xfe000070 },
+	{ 0x50280,  0x4bc00068 },
+	{ 0x5fffc,  0xfe000078 },
+	{ 0x50284,  0x4bc00060 },
+	{ 0x5fffc,  0xfe000080 },
+	{ 0x50288,  0x4b800059 },
+	{ 0x5fffc,  0xfe000089 },
+	{ 0x5028c,  0x4b000052 },
+	{ 0x5fffc,  0xfe400091 },
+	{ 0x50290,  0x4a80004b },
+	{ 0x5fffc,  0xfe40009a },
+	{ 0x50294,  0x4a000044 },
+	{ 0x5fffc,  0xfe8000a3 },
+	{ 0x50298,  0x4940003d },
+	{ 0x5fffc,  0xfec000ac },
+	{ 0x5029c,  0x48400037 },
+	{ 0x5fffc,  0xff0000b4 },
+	{ 0x502a0,  0x47800031 },
+	{ 0x5fffc,  0xff8000bd },
+	{ 0x502a4,  0x4640002b },
+	{ 0x5fffc,  0xc5 },
+	{ 0x502a8,  0x45000026 },
+	{ 0x5fffc,  0x8000ce },
+	{ 0x502ac,  0x43800021 },
+	{ 0x5fffc,  0x10000d6 },
+	{ 0x502b0,  0x4240001c },
+	{ 0x5fffc,  0x18000df },
+	{ 0x502b4,  0x40800018 },
+	{ 0x5fffc,  0x24000e6 },
+	{ 0x502b8,  0x3f000014 },
+	{ 0x5fffc,  0x30000ee },
+	{ 0x502bc,  0x3d400010 },
+	{ 0x5fffc,  0x40000f5 },
+	{ 0x502c0,  0x3b80000c },
+	{ 0x5fffc,  0x50000fc },
+	{ 0x502c4,  0x39800009 },
+	{ 0x5fffc,  0x6000102 },
+	{ 0x502c8,  0x37c00006 },
+	{ 0x5fffc,  0x7000109 },
+	{ 0x502cc,  0x35800004 },
+	{ 0x5fffc,  0x840010e },
+	{ 0x502d0,  0x33800002 },
+	{ 0x5fffc,  0x9800114 },
+	{ 0x502d4,  0x31400000 },
+	{ 0x5fffc,  0xac00119 },
+	{ 0x502d8,  0x2f4003fe },
+	{ 0x5fffc,  0xc40011e },
+	{ 0x502dc,  0x2d0003fc },
+	{ 0x5fffc,  0xdc00121 },
+	{ 0x502e0,  0x2b0003fb },
+	{ 0x5fffc,  0xf400125 },
+	{ 0x502e4,  0x28c003fa },
+	{ 0x5fffc,  0x11000128 },
+	{ 0x502e8,  0x268003f9 },
+	{ 0x5fffc,  0x12c0012a },
+	{ 0x502ec,  0x244003f9 },
+	{ 0x5fffc,  0x1480012c },
+	{ 0x502f0,  0x224003f8 },
+	{ 0x5fffc,  0x1640012e },
+	{ 0x502f4,  0x200003f8 },
+	{ 0x5fffc,  0x1800012f },
+	{ 0x502f8,  0x1e0003f8 },
+	{ 0x5fffc,  0x1a00012f },
+	{ 0x502fc,  0x1c0003f8 },
+};
+
+static struct mdp_table_entry mdp_downscale_x_table_PT8TO1[] = {
+	{ 0x5fffc,  0x0 },
+	{ 0x50280,  0x7fc00000 },
+	{ 0x5fffc,  0xff80000d },
+	{ 0x50284,  0x7ec003f9 },
+	{ 0x5fffc,  0xfec0001c },
+	{ 0x50288,  0x7d4003f3 },
+	{ 0x5fffc,  0xfe40002b },
+	{ 0x5028c,  0x7b8003ed },
+	{ 0x5fffc,  0xfd80003c },
+	{ 0x50290,  0x794003e8 },
+	{ 0x5fffc,  0xfcc0004d },
+	{ 0x50294,  0x76c003e4 },
+	{ 0x5fffc,  0xfc40005f },
+	{ 0x50298,  0x73c003e0 },
+	{ 0x5fffc,  0xfb800071 },
+	{ 0x5029c,  0x708003de },
+	{ 0x5fffc,  0xfac00085 },
+	{ 0x502a0,  0x6d0003db },
+	{ 0x5fffc,  0xfa000098 },
+	{ 0x502a4,  0x698003d9 },
+	{ 0x5fffc,  0xf98000ac },
+	{ 0x502a8,  0x654003d8 },
+	{ 0x5fffc,  0xf8c000c1 },
+	{ 0x502ac,  0x610003d7 },
+	{ 0x5fffc,  0xf84000d5 },
+	{ 0x502b0,  0x5c8003d7 },
+	{ 0x5fffc,  0xf7c000e9 },
+	{ 0x502b4,  0x580003d7 },
+	{ 0x5fffc,  0xf74000fd },
+	{ 0x502b8,  0x534003d8 },
+	{ 0x5fffc,  0xf6c00112 },
+	{ 0x502bc,  0x4e8003d8 },
+	{ 0x5fffc,  0xf6800126 },
+	{ 0x502c0,  0x494003da },
+	{ 0x5fffc,  0xf600013a },
+	{ 0x502c4,  0x448003db },
+	{ 0x5fffc,  0xf600014d },
+	{ 0x502c8,  0x3f4003dd },
+	{ 0x5fffc,  0xf5c00160 },
+	{ 0x502cc,  0x3a4003df },
+	{ 0x5fffc,  0xf5c00172 },
+	{ 0x502d0,  0x354003e1 },
+	{ 0x5fffc,  0xf5c00184 },
+	{ 0x502d4,  0x304003e3 },
+	{ 0x5fffc,  0xf6000195 },
+	{ 0x502d8,  0x2b0003e6 },
+	{ 0x5fffc,  0xf64001a6 },
+	{ 0x502dc,  0x260003e8 },
+	{ 0x5fffc,  0xf6c001b4 },
+	{ 0x502e0,  0x214003eb },
+	{ 0x5fffc,  0xf78001c2 },
+	{ 0x502e4,  0x1c4003ee },
+	{ 0x5fffc,  0xf80001cf },
+	{ 0x502e8,  0x17c003f1 },
+	{ 0x5fffc,  0xf90001db },
+	{ 0x502ec,  0x134003f3 },
+	{ 0x5fffc,  0xfa0001e5 },
+	{ 0x502f0,  0xf0003f6 },
+	{ 0x5fffc,  0xfb4001ee },
+	{ 0x502f4,  0xac003f9 },
+	{ 0x5fffc,  0xfcc001f5 },
+	{ 0x502f8,  0x70003fb },
+	{ 0x5fffc,  0xfe4001fb },
+	{ 0x502fc,  0x34003fe },
+};
+
+struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX] = {
+	[MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_x_table_PT2TOPT4,
+	[MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_x_table_PT4TOPT6,
+	[MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_x_table_PT6TOPT8,
+	[MDP_DOWNSCALE_PT8TO1]  = mdp_downscale_x_table_PT8TO1,
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT2TOPT4[] = {
+	{ 0x5fffc,  0x740008c },
+	{ 0x50300,  0x33800088 },
+	{ 0x5fffc,  0x800008e },
+	{ 0x50304,  0x33400084 },
+	{ 0x5fffc,  0x8400092 },
+	{ 0x50308,  0x33000080 },
+	{ 0x5fffc,  0x9000094 },
+	{ 0x5030c,  0x3300007b },
+	{ 0x5fffc,  0x9c00098 },
+	{ 0x50310,  0x32400077 },
+	{ 0x5fffc,  0xa40009b },
+	{ 0x50314,  0x32000073 },
+	{ 0x5fffc,  0xb00009d },
+	{ 0x50318,  0x31c0006f },
+	{ 0x5fffc,  0xbc000a0 },
+	{ 0x5031c,  0x3140006b },
+	{ 0x5fffc,  0xc8000a2 },
+	{ 0x50320,  0x31000067 },
+	{ 0x5fffc,  0xd8000a5 },
+	{ 0x50324,  0x30800062 },
+	{ 0x5fffc,  0xe4000a8 },
+	{ 0x50328,  0x2fc0005f },
+	{ 0x5fffc,  0xec000aa },
+	{ 0x5032c,  0x2fc0005b },
+	{ 0x5fffc,  0xf8000ad },
+	{ 0x50330,  0x2f400057 },
+	{ 0x5fffc,  0x108000b0 },
+	{ 0x50334,  0x2e400054 },
+	{ 0x5fffc,  0x114000b2 },
+	{ 0x50338,  0x2e000050 },
+	{ 0x5fffc,  0x124000b4 },
+	{ 0x5033c,  0x2d80004c },
+	{ 0x5fffc,  0x130000b6 },
+	{ 0x50340,  0x2d000049 },
+	{ 0x5fffc,  0x140000b8 },
+	{ 0x50344,  0x2c800045 },
+	{ 0x5fffc,  0x150000b9 },
+	{ 0x50348,  0x2c000042 },
+	{ 0x5fffc,  0x15c000bd },
+	{ 0x5034c,  0x2b40003e },
+	{ 0x5fffc,  0x16c000bf },
+	{ 0x50350,  0x2a80003b },
+	{ 0x5fffc,  0x17c000bf },
+	{ 0x50354,  0x2a000039 },
+	{ 0x5fffc,  0x188000c2 },
+	{ 0x50358,  0x29400036 },
+	{ 0x5fffc,  0x19c000c4 },
+	{ 0x5035c,  0x28800032 },
+	{ 0x5fffc,  0x1ac000c5 },
+	{ 0x50360,  0x2800002f },
+	{ 0x5fffc,  0x1bc000c7 },
+	{ 0x50364,  0x2740002c },
+	{ 0x5fffc,  0x1cc000c8 },
+	{ 0x50368,  0x26c00029 },
+	{ 0x5fffc,  0x1dc000c9 },
+	{ 0x5036c,  0x26000027 },
+	{ 0x5fffc,  0x1ec000cc },
+	{ 0x50370,  0x25000024 },
+	{ 0x5fffc,  0x200000cc },
+	{ 0x50374,  0x24800021 },
+	{ 0x5fffc,  0x210000cd },
+	{ 0x50378,  0x23800020 },
+	{ 0x5fffc,  0x220000ce },
+	{ 0x5037c,  0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT4TOPT6[] = {
+	{ 0x5fffc,  0x740008c },
+	{ 0x50300,  0x33800088 },
+	{ 0x5fffc,  0x800008e },
+	{ 0x50304,  0x33400084 },
+	{ 0x5fffc,  0x8400092 },
+	{ 0x50308,  0x33000080 },
+	{ 0x5fffc,  0x9000094 },
+	{ 0x5030c,  0x3300007b },
+	{ 0x5fffc,  0x9c00098 },
+	{ 0x50310,  0x32400077 },
+	{ 0x5fffc,  0xa40009b },
+	{ 0x50314,  0x32000073 },
+	{ 0x5fffc,  0xb00009d },
+	{ 0x50318,  0x31c0006f },
+	{ 0x5fffc,  0xbc000a0 },
+	{ 0x5031c,  0x3140006b },
+	{ 0x5fffc,  0xc8000a2 },
+	{ 0x50320,  0x31000067 },
+	{ 0x5fffc,  0xd8000a5 },
+	{ 0x50324,  0x30800062 },
+	{ 0x5fffc,  0xe4000a8 },
+	{ 0x50328,  0x2fc0005f },
+	{ 0x5fffc,  0xec000aa },
+	{ 0x5032c,  0x2fc0005b },
+	{ 0x5fffc,  0xf8000ad },
+	{ 0x50330,  0x2f400057 },
+	{ 0x5fffc,  0x108000b0 },
+	{ 0x50334,  0x2e400054 },
+	{ 0x5fffc,  0x114000b2 },
+	{ 0x50338,  0x2e000050 },
+	{ 0x5fffc,  0x124000b4 },
+	{ 0x5033c,  0x2d80004c },
+	{ 0x5fffc,  0x130000b6 },
+	{ 0x50340,  0x2d000049 },
+	{ 0x5fffc,  0x140000b8 },
+	{ 0x50344,  0x2c800045 },
+	{ 0x5fffc,  0x150000b9 },
+	{ 0x50348,  0x2c000042 },
+	{ 0x5fffc,  0x15c000bd },
+	{ 0x5034c,  0x2b40003e },
+	{ 0x5fffc,  0x16c000bf },
+	{ 0x50350,  0x2a80003b },
+	{ 0x5fffc,  0x17c000bf },
+	{ 0x50354,  0x2a000039 },
+	{ 0x5fffc,  0x188000c2 },
+	{ 0x50358,  0x29400036 },
+	{ 0x5fffc,  0x19c000c4 },
+	{ 0x5035c,  0x28800032 },
+	{ 0x5fffc,  0x1ac000c5 },
+	{ 0x50360,  0x2800002f },
+	{ 0x5fffc,  0x1bc000c7 },
+	{ 0x50364,  0x2740002c },
+	{ 0x5fffc,  0x1cc000c8 },
+	{ 0x50368,  0x26c00029 },
+	{ 0x5fffc,  0x1dc000c9 },
+	{ 0x5036c,  0x26000027 },
+	{ 0x5fffc,  0x1ec000cc },
+	{ 0x50370,  0x25000024 },
+	{ 0x5fffc,  0x200000cc },
+	{ 0x50374,  0x24800021 },
+	{ 0x5fffc,  0x210000cd },
+	{ 0x50378,  0x23800020 },
+	{ 0x5fffc,  0x220000ce },
+	{ 0x5037c,  0x2300001d },
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT6TOPT8[] = {
+	{ 0x5fffc,  0xfe000070 },
+	{ 0x50300,  0x4bc00068 },
+	{ 0x5fffc,  0xfe000078 },
+	{ 0x50304,  0x4bc00060 },
+	{ 0x5fffc,  0xfe000080 },
+	{ 0x50308,  0x4b800059 },
+	{ 0x5fffc,  0xfe000089 },
+	{ 0x5030c,  0x4b000052 },
+	{ 0x5fffc,  0xfe400091 },
+	{ 0x50310,  0x4a80004b },
+	{ 0x5fffc,  0xfe40009a },
+	{ 0x50314,  0x4a000044 },
+	{ 0x5fffc,  0xfe8000a3 },
+	{ 0x50318,  0x4940003d },
+	{ 0x5fffc,  0xfec000ac },
+	{ 0x5031c,  0x48400037 },
+	{ 0x5fffc,  0xff0000b4 },
+	{ 0x50320,  0x47800031 },
+	{ 0x5fffc,  0xff8000bd },
+	{ 0x50324,  0x4640002b },
+	{ 0x5fffc,  0xc5 },
+	{ 0x50328,  0x45000026 },
+	{ 0x5fffc,  0x8000ce },
+	{ 0x5032c,  0x43800021 },
+	{ 0x5fffc,  0x10000d6 },
+	{ 0x50330,  0x4240001c },
+	{ 0x5fffc,  0x18000df },
+	{ 0x50334,  0x40800018 },
+	{ 0x5fffc,  0x24000e6 },
+	{ 0x50338,  0x3f000014 },
+	{ 0x5fffc,  0x30000ee },
+	{ 0x5033c,  0x3d400010 },
+	{ 0x5fffc,  0x40000f5 },
+	{ 0x50340,  0x3b80000c },
+	{ 0x5fffc,  0x50000fc },
+	{ 0x50344,  0x39800009 },
+	{ 0x5fffc,  0x6000102 },
+	{ 0x50348,  0x37c00006 },
+	{ 0x5fffc,  0x7000109 },
+	{ 0x5034c,  0x35800004 },
+	{ 0x5fffc,  0x840010e },
+	{ 0x50350,  0x33800002 },
+	{ 0x5fffc,  0x9800114 },
+	{ 0x50354,  0x31400000 },
+	{ 0x5fffc,  0xac00119 },
+	{ 0x50358,  0x2f4003fe },
+	{ 0x5fffc,  0xc40011e },
+	{ 0x5035c,  0x2d0003fc },
+	{ 0x5fffc,  0xdc00121 },
+	{ 0x50360,  0x2b0003fb },
+	{ 0x5fffc,  0xf400125 },
+	{ 0x50364,  0x28c003fa },
+	{ 0x5fffc,  0x11000128 },
+	{ 0x50368,  0x268003f9 },
+	{ 0x5fffc,  0x12c0012a },
+	{ 0x5036c,  0x244003f9 },
+	{ 0x5fffc,  0x1480012c },
+	{ 0x50370,  0x224003f8 },
+	{ 0x5fffc,  0x1640012e },
+	{ 0x50374,  0x200003f8 },
+	{ 0x5fffc,  0x1800012f },
+	{ 0x50378,  0x1e0003f8 },
+	{ 0x5fffc,  0x1a00012f },
+	{ 0x5037c,  0x1c0003f8 },
+};
+
+static struct mdp_table_entry mdp_downscale_y_table_PT8TO1[] = {
+	{ 0x5fffc,  0x0 },
+	{ 0x50300,  0x7fc00000 },
+	{ 0x5fffc,  0xff80000d },
+	{ 0x50304,  0x7ec003f9 },
+	{ 0x5fffc,  0xfec0001c },
+	{ 0x50308,  0x7d4003f3 },
+	{ 0x5fffc,  0xfe40002b },
+	{ 0x5030c,  0x7b8003ed },
+	{ 0x5fffc,  0xfd80003c },
+	{ 0x50310,  0x794003e8 },
+	{ 0x5fffc,  0xfcc0004d },
+	{ 0x50314,  0x76c003e4 },
+	{ 0x5fffc,  0xfc40005f },
+	{ 0x50318,  0x73c003e0 },
+	{ 0x5fffc,  0xfb800071 },
+	{ 0x5031c,  0x708003de },
+	{ 0x5fffc,  0xfac00085 },
+	{ 0x50320,  0x6d0003db },
+	{ 0x5fffc,  0xfa000098 },
+	{ 0x50324,  0x698003d9 },
+	{ 0x5fffc,  0xf98000ac },
+	{ 0x50328,  0x654003d8 },
+	{ 0x5fffc,  0xf8c000c1 },
+	{ 0x5032c,  0x610003d7 },
+	{ 0x5fffc,  0xf84000d5 },
+	{ 0x50330,  0x5c8003d7 },
+	{ 0x5fffc,  0xf7c000e9 },
+	{ 0x50334,  0x580003d7 },
+	{ 0x5fffc,  0xf74000fd },
+	{ 0x50338,  0x534003d8 },
+	{ 0x5fffc,  0xf6c00112 },
+	{ 0x5033c,  0x4e8003d8 },
+	{ 0x5fffc,  0xf6800126 },
+	{ 0x50340,  0x494003da },
+	{ 0x5fffc,  0xf600013a },
+	{ 0x50344,  0x448003db },
+	{ 0x5fffc,  0xf600014d },
+	{ 0x50348,  0x3f4003dd },
+	{ 0x5fffc,  0xf5c00160 },
+	{ 0x5034c,  0x3a4003df },
+	{ 0x5fffc,  0xf5c00172 },
+	{ 0x50350,  0x354003e1 },
+	{ 0x5fffc,  0xf5c00184 },
+	{ 0x50354,  0x304003e3 },
+	{ 0x5fffc,  0xf6000195 },
+	{ 0x50358,  0x2b0003e6 },
+	{ 0x5fffc,  0xf64001a6 },
+	{ 0x5035c,  0x260003e8 },
+	{ 0x5fffc,  0xf6c001b4 },
+	{ 0x50360,  0x214003eb },
+	{ 0x5fffc,  0xf78001c2 },
+	{ 0x50364,  0x1c4003ee },
+	{ 0x5fffc,  0xf80001cf },
+	{ 0x50368,  0x17c003f1 },
+	{ 0x5fffc,  0xf90001db },
+	{ 0x5036c,  0x134003f3 },
+	{ 0x5fffc,  0xfa0001e5 },
+	{ 0x50370,  0xf0003f6 },
+	{ 0x5fffc,  0xfb4001ee },
+	{ 0x50374,  0xac003f9 },
+	{ 0x5fffc,  0xfcc001f5 },
+	{ 0x50378,  0x70003fb },
+	{ 0x5fffc,  0xfe4001fb },
+	{ 0x5037c,  0x34003fe },
+};
+
+struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX] = {
+	[MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_y_table_PT2TOPT4,
+	[MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_y_table_PT4TOPT6,
+	[MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_y_table_PT6TOPT8,
+	[MDP_DOWNSCALE_PT8TO1]  = mdp_downscale_y_table_PT8TO1,
+};
+
+struct mdp_table_entry mdp_gaussian_blur_table[] = {
+	/* max variance */
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50280, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50284, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50288, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5028c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50290, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50294, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50298, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5029c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502ac, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502bc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502cc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502dc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502ec, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502fc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50300, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50304, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50308, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5030c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50310, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50314, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50318, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5031c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50320, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50324, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50328, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5032c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50330, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50334, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50338, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5033c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50340, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50344, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50348, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5034c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50350, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50354, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50358, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5035c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50360, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50364, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50368, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5036c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50370, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50374, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50378, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5037c, 0x20000080 },
+};
diff --git a/drivers/video/fbdev/msm/mdp_scale_tables.h b/drivers/video/fbdev/msm/mdp_scale_tables.h
new file mode 100644
index 000000000000..34077b1af603
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdp_scale_tables.h
@@ -0,0 +1,38 @@
+/* drivers/video/msm_fb/mdp_scale_tables.h
+ *
+ * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _MDP_SCALE_TABLES_H_
+#define _MDP_SCALE_TABLES_H_
+
+#include <linux/types.h>
+struct mdp_table_entry {
+	uint32_t reg;
+	uint32_t val;
+};
+
+extern struct mdp_table_entry mdp_upscale_table[64];
+
+enum {
+	MDP_DOWNSCALE_PT2TOPT4,
+	MDP_DOWNSCALE_PT4TOPT6,
+	MDP_DOWNSCALE_PT6TOPT8,
+	MDP_DOWNSCALE_PT8TO1,
+	MDP_DOWNSCALE_MAX,
+};
+
+extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
+extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
+extern struct mdp_table_entry mdp_gaussian_blur_table[];
+
+#endif
diff --git a/drivers/video/fbdev/msm/msm_fb.c b/drivers/video/fbdev/msm/msm_fb.c
new file mode 100644
index 000000000000..1374803fbcd9
--- /dev/null
+++ b/drivers/video/fbdev/msm/msm_fb.c
@@ -0,0 +1,638 @@
+/* drivers/video/msm/msm_fb.c
+ *
+ * Core MSM framebuffer driver.
+ *
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/freezer.h>
+#include <linux/wait.h>
+#include <linux/msm_mdp.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/platform_data/video-msm_fb.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
+
+#define PRINT_FPS 0
+#define PRINT_BLIT_TIME 0
+
+#define SLEEPING 0x4
+#define UPDATING 0x3
+#define FULL_UPDATE_DONE 0x2
+#define WAKING 0x1
+#define AWAKE 0x0
+
+#define NONE 0
+#define SUSPEND_RESUME 0x1
+#define FPS 0x2
+#define BLIT_TIME 0x4
+#define SHOW_UPDATES 0x8
+
+#define DLOG(mask, fmt, args...) \
+do { \
+	if (msmfb_debug_mask & mask) \
+		printk(KERN_INFO "msmfb: "fmt, ##args); \
+} while (0)
+
+static int msmfb_debug_mask;
+module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
+		   S_IRUGO | S_IWUSR | S_IWGRP);
+
+struct mdp_device *mdp;
+
+struct msmfb_info {
+	struct fb_info *fb;
+	struct msm_panel_data *panel;
+	int xres;
+	int yres;
+	unsigned output_format;
+	unsigned yoffset;
+	unsigned frame_requested;
+	unsigned frame_done;
+	int sleeping;
+	unsigned update_frame;
+	struct {
+		int left;
+		int top;
+		int eright; /* exclusive */
+		int ebottom; /* exclusive */
+	} update_info;
+	char *black;
+
+	spinlock_t update_lock;
+	struct mutex panel_init_lock;
+	wait_queue_head_t frame_wq;
+	struct work_struct resume_work;
+	struct msmfb_callback dma_callback;
+	struct msmfb_callback vsync_callback;
+	struct hrtimer fake_vsync;
+	ktime_t vsync_request_time;
+};
+
+static int msmfb_open(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+static int msmfb_release(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+/* Called from dma interrupt handler, must not sleep */
+static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
+{
+	unsigned long irq_flags;
+	struct msmfb_info *msmfb  = container_of(callback, struct msmfb_info,
+					       dma_callback);
+
+	spin_lock_irqsave(&msmfb->update_lock, irq_flags);
+	msmfb->frame_done = msmfb->frame_requested;
+	if (msmfb->sleeping == UPDATING &&
+	    msmfb->frame_done == msmfb->update_frame) {
+		DLOG(SUSPEND_RESUME, "full update completed\n");
+		schedule_work(&msmfb->resume_work);
+	}
+	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+	wake_up(&msmfb->frame_wq);
+}
+
+static int msmfb_start_dma(struct msmfb_info *msmfb)
+{
+	uint32_t x, y, w, h;
+	unsigned addr;
+	unsigned long irq_flags;
+	uint32_t yoffset;
+	s64 time_since_request;
+	struct msm_panel_data *panel = msmfb->panel;
+
+	spin_lock_irqsave(&msmfb->update_lock, irq_flags);
+	time_since_request = ktime_to_ns(ktime_sub(ktime_get(),
+			     msmfb->vsync_request_time));
+	if (time_since_request > 20 * NSEC_PER_MSEC) {
+		uint32_t us;
+		us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC;
+		printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync "
+			"request\n", time_since_request, us);
+	}
+	if (msmfb->frame_done == msmfb->frame_requested) {
+		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+		return -1;
+	}
+	if (msmfb->sleeping == SLEEPING) {
+		DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
+		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+		return -1;
+	}
+	x = msmfb->update_info.left;
+	y = msmfb->update_info.top;
+	w = msmfb->update_info.eright - x;
+	h = msmfb->update_info.ebottom - y;
+	yoffset = msmfb->yoffset;
+	msmfb->update_info.left = msmfb->xres + 1;
+	msmfb->update_info.top = msmfb->yres + 1;
+	msmfb->update_info.eright = 0;
+	msmfb->update_info.ebottom = 0;
+	if (unlikely(w > msmfb->xres || h > msmfb->yres ||
+		     w == 0 || h == 0)) {
+		printk(KERN_INFO "invalid update: %d %d %d "
+				"%d\n", x, y, w, h);
+		msmfb->frame_done = msmfb->frame_requested;
+		goto error;
+	}
+	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+
+	addr = ((msmfb->xres * (yoffset + y) + x) * 2);
+	mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
+		 msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
+		 panel->interface_type);
+	return 0;
+error:
+	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+	/* some clients need to clear their vsync interrupt */
+	if (panel->clear_vsync)
+		panel->clear_vsync(panel);
+	wake_up(&msmfb->frame_wq);
+	return 0;
+}
+
+/* Called from esync interrupt handler, must not sleep */
+static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback)
+{
+	struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
+					       vsync_callback);
+	msmfb_start_dma(msmfb);
+}
+
+static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer)
+{
+	struct msmfb_info *msmfb  = container_of(timer, struct msmfb_info,
+					       fake_vsync);
+	msmfb_start_dma(msmfb);
+	return HRTIMER_NORESTART;
+}
+
+static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
+			     uint32_t eright, uint32_t ebottom,
+			     uint32_t yoffset, int pan_display)
+{
+	struct msmfb_info *msmfb = info->par;
+	struct msm_panel_data *panel = msmfb->panel;
+	unsigned long irq_flags;
+	int sleeping;
+	int retry = 1;
+
+	DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
+		left, top, eright, ebottom, yoffset, pan_display);
+restart:
+	spin_lock_irqsave(&msmfb->update_lock, irq_flags);
+
+	/* if we are sleeping, on a pan_display wait 10ms (to throttle back
+	 * drawing otherwise return */
+	if (msmfb->sleeping == SLEEPING) {
+		DLOG(SUSPEND_RESUME, "drawing while asleep\n");
+		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+		if (pan_display)
+			wait_event_interruptible_timeout(msmfb->frame_wq,
+				msmfb->sleeping != SLEEPING, HZ/10);
+		return;
+	}
+
+	sleeping = msmfb->sleeping;
+	/* on a full update, if the last frame has not completed, wait for it */
+	if ((pan_display && msmfb->frame_requested != msmfb->frame_done) ||
+			    sleeping == UPDATING) {
+		int ret;
+		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+		ret = wait_event_interruptible_timeout(msmfb->frame_wq,
+			msmfb->frame_done == msmfb->frame_requested &&
+			msmfb->sleeping != UPDATING, 5 * HZ);
+		if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done ||
+				 msmfb->sleeping == UPDATING)) {
+			if (retry && panel->request_vsync &&
+			    (sleeping == AWAKE)) {
+				panel->request_vsync(panel,
+					&msmfb->vsync_callback);
+				retry = 0;
+				printk(KERN_WARNING "msmfb_pan_display timeout "
+					"rerequest vsync\n");
+			} else {
+				printk(KERN_WARNING "msmfb_pan_display timeout "
+					"waiting for frame start, %d %d\n",
+					msmfb->frame_requested,
+					msmfb->frame_done);
+				return;
+			}
+		}
+		goto restart;
+	}
+
+
+	msmfb->frame_requested++;
+	/* if necessary, update the y offset, if this is the
+	 * first full update on resume, set the sleeping state */
+	if (pan_display) {
+		msmfb->yoffset = yoffset;
+		if (left == 0 && top == 0 && eright == info->var.xres &&
+		    ebottom == info->var.yres) {
+			if (sleeping == WAKING) {
+				msmfb->update_frame = msmfb->frame_requested;
+				DLOG(SUSPEND_RESUME, "full update starting\n");
+				msmfb->sleeping = UPDATING;
+			}
+		}
+	}
+
+	/* set the update request */
+	if (left < msmfb->update_info.left)
+		msmfb->update_info.left = left;
+	if (top < msmfb->update_info.top)
+		msmfb->update_info.top = top;
+	if (eright > msmfb->update_info.eright)
+		msmfb->update_info.eright = eright;
+	if (ebottom > msmfb->update_info.ebottom)
+		msmfb->update_info.ebottom = ebottom;
+	DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n",
+		msmfb->update_info.left, msmfb->update_info.top,
+		msmfb->update_info.eright, msmfb->update_info.ebottom,
+		msmfb->yoffset);
+	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+
+	/* if the panel is all the way on wait for vsync, otherwise sleep
+	 * for 16 ms (long enough for the dma to panel) and then begin dma */
+	msmfb->vsync_request_time = ktime_get();
+	if (panel->request_vsync && (sleeping == AWAKE)) {
+		panel->request_vsync(panel, &msmfb->vsync_callback);
+	} else {
+		if (!hrtimer_active(&msmfb->fake_vsync)) {
+			hrtimer_start(&msmfb->fake_vsync,
+				      ktime_set(0, NSEC_PER_SEC/60),
+				      HRTIMER_MODE_REL);
+		}
+	}
+}
+
+static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
+			 uint32_t eright, uint32_t ebottom)
+{
+	msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
+}
+
+static void power_on_panel(struct work_struct *work)
+{
+	struct msmfb_info *msmfb =
+		container_of(work, struct msmfb_info, resume_work);
+	struct msm_panel_data *panel = msmfb->panel;
+	unsigned long irq_flags;
+
+	mutex_lock(&msmfb->panel_init_lock);
+	DLOG(SUSPEND_RESUME, "turning on panel\n");
+	if (msmfb->sleeping == UPDATING) {
+		if (panel->unblank(panel)) {
+			printk(KERN_INFO "msmfb: panel unblank failed,"
+			       "not starting drawing\n");
+			goto error;
+		}
+		spin_lock_irqsave(&msmfb->update_lock, irq_flags);
+		msmfb->sleeping = AWAKE;
+		wake_up(&msmfb->frame_wq);
+		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
+	}
+error:
+	mutex_unlock(&msmfb->panel_init_lock);
+}
+
+
+static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	if ((var->xres != info->var.xres) ||
+	    (var->yres != info->var.yres) ||
+	    (var->xres_virtual != info->var.xres_virtual) ||
+	    (var->yres_virtual != info->var.yres_virtual) ||
+	    (var->xoffset != info->var.xoffset) ||
+	    (var->bits_per_pixel != info->var.bits_per_pixel) ||
+	    (var->grayscale != info->var.grayscale))
+		 return -EINVAL;
+	return 0;
+}
+
+int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct msmfb_info *msmfb = info->par;
+	struct msm_panel_data *panel = msmfb->panel;
+
+	/* "UPDT" */
+	if ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
+	    (var->reserved[0] == 0x54445055)) {
+		msmfb_pan_update(info, var->reserved[1] & 0xffff,
+				 var->reserved[1] >> 16,
+				 var->reserved[2] & 0xffff,
+				 var->reserved[2] >> 16, var->yoffset, 1);
+	} else {
+		msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres,
+				 var->yoffset, 1);
+	}
+	return 0;
+}
+
+static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	cfb_fillrect(p, rect);
+	msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
+		     rect->dy + rect->height);
+}
+
+static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	cfb_copyarea(p, area);
+	msmfb_update(p, area->dx, area->dy, area->dx + area->width,
+		     area->dy + area->height);
+}
+
+static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+	cfb_imageblit(p, image);
+	msmfb_update(p, image->dx, image->dy, image->dx + image->width,
+		     image->dy + image->height);
+}
+
+
+static int msmfb_blit(struct fb_info *info,
+		      void __user *p)
+{
+	struct mdp_blit_req req;
+	struct mdp_blit_req_list req_list;
+	int i;
+	int ret;
+
+	if (copy_from_user(&req_list, p, sizeof(req_list)))
+		return -EFAULT;
+
+	for (i = 0; i < req_list.count; i++) {
+		struct mdp_blit_req_list *list =
+			(struct mdp_blit_req_list *)p;
+		if (copy_from_user(&req, &list->req[i], sizeof(req)))
+			return -EFAULT;
+		ret = mdp->blit(mdp, info, &req);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+
+DEFINE_MUTEX(mdp_ppp_lock);
+
+static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	int ret;
+
+	switch (cmd) {
+	case MSMFB_GRP_DISP:
+		mdp->set_grp_disp(mdp, arg);
+		break;
+	case MSMFB_BLIT:
+		ret = msmfb_blit(p, argp);
+		if (ret)
+			return ret;
+		break;
+	default:
+			printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static struct fb_ops msmfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = msmfb_open,
+	.fb_release = msmfb_release,
+	.fb_check_var = msmfb_check_var,
+	.fb_pan_display = msmfb_pan_display,
+	.fb_fillrect = msmfb_fillrect,
+	.fb_copyarea = msmfb_copyarea,
+	.fb_imageblit = msmfb_imageblit,
+	.fb_ioctl = msmfb_ioctl,
+};
+
+static unsigned PP[16];
+
+
+
+#define BITS_PER_PIXEL 16
+
+static void setup_fb_info(struct msmfb_info *msmfb)
+{
+	struct fb_info *fb_info = msmfb->fb;
+	int r;
+
+	/* finish setting up the fb_info struct */
+	strncpy(fb_info->fix.id, "msmfb", 16);
+	fb_info->fix.ypanstep = 1;
+
+	fb_info->fbops = &msmfb_ops;
+	fb_info->flags = FBINFO_DEFAULT;
+
+	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
+	fb_info->fix.line_length = msmfb->xres * 2;
+
+	fb_info->var.xres = msmfb->xres;
+	fb_info->var.yres = msmfb->yres;
+	fb_info->var.width = msmfb->panel->fb_data->width;
+	fb_info->var.height = msmfb->panel->fb_data->height;
+	fb_info->var.xres_virtual = msmfb->xres;
+	fb_info->var.yres_virtual = msmfb->yres * 2;
+	fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
+	fb_info->var.accel_flags = 0;
+
+	fb_info->var.yoffset = 0;
+
+	if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
+		/*
+		 * Set the param in the fixed screen, so userspace can't
+		 * change it. This will be used to check for the
+		 * capability.
+		 */
+		fb_info->fix.reserved[0] = 0x5444;
+		fb_info->fix.reserved[1] = 0x5055;
+
+		/*
+		 * This preloads the value so that if userspace doesn't
+		 * change it, it will be a full update
+		 */
+		fb_info->var.reserved[0] = 0x54445055;
+		fb_info->var.reserved[1] = 0;
+		fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
+					   ((uint32_t)msmfb->yres << 16);
+	}
+
+	fb_info->var.red.offset = 11;
+	fb_info->var.red.length = 5;
+	fb_info->var.red.msb_right = 0;
+	fb_info->var.green.offset = 5;
+	fb_info->var.green.length = 6;
+	fb_info->var.green.msb_right = 0;
+	fb_info->var.blue.offset = 0;
+	fb_info->var.blue.length = 5;
+	fb_info->var.blue.msb_right = 0;
+
+	r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
+	fb_info->pseudo_palette = PP;
+
+	PP[0] = 0;
+	for (r = 1; r < 16; r++)
+		PP[r] = 0xffffffff;
+}
+
+static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
+{
+	struct fb_info *fb = msmfb->fb;
+	struct resource *resource;
+	unsigned long size = msmfb->xres * msmfb->yres *
+			     (BITS_PER_PIXEL >> 3) * 2;
+	unsigned char *fbram;
+
+	/* board file might have attached a resource describing an fb */
+	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!resource)
+		return -EINVAL;
+
+	/* check the resource is large enough to fit the fb */
+	if (resource->end - resource->start < size) {
+		printk(KERN_ERR "allocated resource is too small for "
+				"fb\n");
+		return -ENOMEM;
+	}
+	fb->fix.smem_start = resource->start;
+	fb->fix.smem_len = resource_size(resource);
+	fbram = ioremap(resource->start, resource_size(resource));
+	if (fbram == NULL) {
+		printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
+		return -ENOMEM;
+	}
+	fb->screen_base = fbram;
+	return 0;
+}
+
+static int msmfb_probe(struct platform_device *pdev)
+{
+	struct fb_info *fb;
+	struct msmfb_info *msmfb;
+	struct msm_panel_data *panel = pdev->dev.platform_data;
+	int ret;
+
+	if (!panel) {
+		pr_err("msmfb_probe: no platform data\n");
+		return -EINVAL;
+	}
+	if (!panel->fb_data) {
+		pr_err("msmfb_probe: no fb_data\n");
+		return -EINVAL;
+	}
+
+	fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev);
+	if (!fb)
+		return -ENOMEM;
+	msmfb = fb->par;
+	msmfb->fb = fb;
+	msmfb->panel = panel;
+	msmfb->xres = panel->fb_data->xres;
+	msmfb->yres = panel->fb_data->yres;
+
+	ret = setup_fbmem(msmfb, pdev);
+	if (ret)
+		goto error_setup_fbmem;
+
+	setup_fb_info(msmfb);
+
+	spin_lock_init(&msmfb->update_lock);
+	mutex_init(&msmfb->panel_init_lock);
+	init_waitqueue_head(&msmfb->frame_wq);
+	INIT_WORK(&msmfb->resume_work, power_on_panel);
+	msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
+			       GFP_KERNEL);
+
+	printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n",
+	       msmfb->xres, msmfb->yres);
+
+	msmfb->dma_callback.func = msmfb_handle_dma_interrupt;
+	msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt;
+	hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+
+
+	msmfb->fake_vsync.function = msmfb_fake_vsync;
+
+	ret = register_framebuffer(fb);
+	if (ret)
+		goto error_register_framebuffer;
+
+	msmfb->sleeping = WAKING;
+
+	return 0;
+
+error_register_framebuffer:
+	iounmap(fb->screen_base);
+error_setup_fbmem:
+	framebuffer_release(msmfb->fb);
+	return ret;
+}
+
+static struct platform_driver msm_panel_driver = {
+	/* need to write remove */
+	.probe = msmfb_probe,
+	.driver = {.name = "msm_panel"},
+};
+
+
+static int msmfb_add_mdp_device(struct device *dev,
+				struct class_interface *class_intf)
+{
+	/* might need locking if mulitple mdp devices */
+	if (mdp)
+		return 0;
+	mdp = container_of(dev, struct mdp_device, dev);
+	return platform_driver_register(&msm_panel_driver);
+}
+
+static void msmfb_remove_mdp_device(struct device *dev,
+				struct class_interface *class_intf)
+{
+	/* might need locking if mulitple mdp devices */
+	if (dev != &mdp->dev)
+		return;
+	platform_driver_unregister(&msm_panel_driver);
+	mdp = NULL;
+}
+
+static struct class_interface msm_fb_interface = {
+	.add_dev = &msmfb_add_mdp_device,
+	.remove_dev = &msmfb_remove_mdp_device,
+};
+
+static int __init msmfb_init(void)
+{
+	return register_mdp_client(&msm_fb_interface);
+}
+
+module_init(msmfb_init);
diff --git a/drivers/video/fbdev/mx3fb.c b/drivers/video/fbdev/mx3fb.c
new file mode 100644
index 000000000000..142e860fb527
--- /dev/null
+++ b/drivers/video/fbdev/mx3fb.c
@@ -0,0 +1,1630 @@
+/*
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/console.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/dma/ipu-dma.h>
+
+#include <linux/platform_data/dma-imx.h>
+#include <linux/platform_data/video-mx3fb.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define MX3FB_NAME		"mx3_sdc_fb"
+
+#define MX3FB_REG_OFFSET	0xB4
+
+/* SDC Registers */
+#define SDC_COM_CONF		(0xB4 - MX3FB_REG_OFFSET)
+#define SDC_GW_CTRL		(0xB8 - MX3FB_REG_OFFSET)
+#define SDC_FG_POS		(0xBC - MX3FB_REG_OFFSET)
+#define SDC_BG_POS		(0xC0 - MX3FB_REG_OFFSET)
+#define SDC_CUR_POS		(0xC4 - MX3FB_REG_OFFSET)
+#define SDC_PWM_CTRL		(0xC8 - MX3FB_REG_OFFSET)
+#define SDC_CUR_MAP		(0xCC - MX3FB_REG_OFFSET)
+#define SDC_HOR_CONF		(0xD0 - MX3FB_REG_OFFSET)
+#define SDC_VER_CONF		(0xD4 - MX3FB_REG_OFFSET)
+#define SDC_SHARP_CONF_1	(0xD8 - MX3FB_REG_OFFSET)
+#define SDC_SHARP_CONF_2	(0xDC - MX3FB_REG_OFFSET)
+
+/* Register bits */
+#define SDC_COM_TFT_COLOR	0x00000001UL
+#define SDC_COM_FG_EN		0x00000010UL
+#define SDC_COM_GWSEL		0x00000020UL
+#define SDC_COM_GLB_A		0x00000040UL
+#define SDC_COM_KEY_COLOR_G	0x00000080UL
+#define SDC_COM_BG_EN		0x00000200UL
+#define SDC_COM_SHARP		0x00001000UL
+
+#define SDC_V_SYNC_WIDTH_L	0x00000001UL
+
+/* Display Interface registers */
+#define DI_DISP_IF_CONF		(0x0124 - MX3FB_REG_OFFSET)
+#define DI_DISP_SIG_POL		(0x0128 - MX3FB_REG_OFFSET)
+#define DI_SER_DISP1_CONF	(0x012C - MX3FB_REG_OFFSET)
+#define DI_SER_DISP2_CONF	(0x0130 - MX3FB_REG_OFFSET)
+#define DI_HSP_CLK_PER		(0x0134 - MX3FB_REG_OFFSET)
+#define DI_DISP0_TIME_CONF_1	(0x0138 - MX3FB_REG_OFFSET)
+#define DI_DISP0_TIME_CONF_2	(0x013C - MX3FB_REG_OFFSET)
+#define DI_DISP0_TIME_CONF_3	(0x0140 - MX3FB_REG_OFFSET)
+#define DI_DISP1_TIME_CONF_1	(0x0144 - MX3FB_REG_OFFSET)
+#define DI_DISP1_TIME_CONF_2	(0x0148 - MX3FB_REG_OFFSET)
+#define DI_DISP1_TIME_CONF_3	(0x014C - MX3FB_REG_OFFSET)
+#define DI_DISP2_TIME_CONF_1	(0x0150 - MX3FB_REG_OFFSET)
+#define DI_DISP2_TIME_CONF_2	(0x0154 - MX3FB_REG_OFFSET)
+#define DI_DISP2_TIME_CONF_3	(0x0158 - MX3FB_REG_OFFSET)
+#define DI_DISP3_TIME_CONF	(0x015C - MX3FB_REG_OFFSET)
+#define DI_DISP0_DB0_MAP	(0x0160 - MX3FB_REG_OFFSET)
+#define DI_DISP0_DB1_MAP	(0x0164 - MX3FB_REG_OFFSET)
+#define DI_DISP0_DB2_MAP	(0x0168 - MX3FB_REG_OFFSET)
+#define DI_DISP0_CB0_MAP	(0x016C - MX3FB_REG_OFFSET)
+#define DI_DISP0_CB1_MAP	(0x0170 - MX3FB_REG_OFFSET)
+#define DI_DISP0_CB2_MAP	(0x0174 - MX3FB_REG_OFFSET)
+#define DI_DISP1_DB0_MAP	(0x0178 - MX3FB_REG_OFFSET)
+#define DI_DISP1_DB1_MAP	(0x017C - MX3FB_REG_OFFSET)
+#define DI_DISP1_DB2_MAP	(0x0180 - MX3FB_REG_OFFSET)
+#define DI_DISP1_CB0_MAP	(0x0184 - MX3FB_REG_OFFSET)
+#define DI_DISP1_CB1_MAP	(0x0188 - MX3FB_REG_OFFSET)
+#define DI_DISP1_CB2_MAP	(0x018C - MX3FB_REG_OFFSET)
+#define DI_DISP2_DB0_MAP	(0x0190 - MX3FB_REG_OFFSET)
+#define DI_DISP2_DB1_MAP	(0x0194 - MX3FB_REG_OFFSET)
+#define DI_DISP2_DB2_MAP	(0x0198 - MX3FB_REG_OFFSET)
+#define DI_DISP2_CB0_MAP	(0x019C - MX3FB_REG_OFFSET)
+#define DI_DISP2_CB1_MAP	(0x01A0 - MX3FB_REG_OFFSET)
+#define DI_DISP2_CB2_MAP	(0x01A4 - MX3FB_REG_OFFSET)
+#define DI_DISP3_B0_MAP		(0x01A8 - MX3FB_REG_OFFSET)
+#define DI_DISP3_B1_MAP		(0x01AC - MX3FB_REG_OFFSET)
+#define DI_DISP3_B2_MAP		(0x01B0 - MX3FB_REG_OFFSET)
+#define DI_DISP_ACC_CC		(0x01B4 - MX3FB_REG_OFFSET)
+#define DI_DISP_LLA_CONF	(0x01B8 - MX3FB_REG_OFFSET)
+#define DI_DISP_LLA_DATA	(0x01BC - MX3FB_REG_OFFSET)
+
+/* DI_DISP_SIG_POL bits */
+#define DI_D3_VSYNC_POL_SHIFT		28
+#define DI_D3_HSYNC_POL_SHIFT		27
+#define DI_D3_DRDY_SHARP_POL_SHIFT	26
+#define DI_D3_CLK_POL_SHIFT		25
+#define DI_D3_DATA_POL_SHIFT		24
+
+/* DI_DISP_IF_CONF bits */
+#define DI_D3_CLK_IDLE_SHIFT		26
+#define DI_D3_CLK_SEL_SHIFT		25
+#define DI_D3_DATAMSK_SHIFT		24
+
+enum ipu_panel {
+	IPU_PANEL_SHARP_TFT,
+	IPU_PANEL_TFT,
+};
+
+struct ipu_di_signal_cfg {
+	unsigned datamask_en:1;
+	unsigned clksel_en:1;
+	unsigned clkidle_en:1;
+	unsigned data_pol:1;	/* true = inverted */
+	unsigned clk_pol:1;	/* true = rising edge */
+	unsigned enable_pol:1;
+	unsigned Hsync_pol:1;	/* true = active high */
+	unsigned Vsync_pol:1;
+};
+
+static const struct fb_videomode mx3fb_modedb[] = {
+	{
+		/* 240x320 @ 60 Hz */
+		.name		= "Sharp-QVGA",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
+				  FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT |
+				  FB_SYNC_CLK_IDLE_EN,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 240x33 @ 60 Hz */
+		.name		= "Sharp-CLI",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 33,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9 + 287,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
+				  FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT |
+				  FB_SYNC_CLK_IDLE_EN,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 640x480 @ 60 Hz */
+		.name		= "NEC-VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 38255,
+		.left_margin	= 144,
+		.right_margin	= 0,
+		.upper_margin	= 34,
+		.lower_margin	= 40,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* NTSC TV output */
+		.name		= "TV-NTSC",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 37538,
+		.left_margin	= 38,
+		.right_margin	= 858 - 640 - 38 - 3,
+		.upper_margin	= 36,
+		.lower_margin	= 518 - 480 - 36 - 1,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* PAL TV output */
+		.name		= "TV-PAL",
+		.refresh	= 50,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 37538,
+		.left_margin	= 38,
+		.right_margin	= 960 - 640 - 38 - 32,
+		.upper_margin	= 32,
+		.lower_margin	= 555 - 480 - 32 - 3,
+		.hsync_len	= 32,
+		.vsync_len	= 3,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* TV output VGA mode, 640x480 @ 65 Hz */
+		.name		= "TV-VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 40574,
+		.left_margin	= 35,
+		.right_margin	= 45,
+		.upper_margin	= 9,
+		.lower_margin	= 1,
+		.hsync_len	= 46,
+		.vsync_len	= 5,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+struct mx3fb_data {
+	struct fb_info		*fbi;
+	int			backlight_level;
+	void __iomem		*reg_base;
+	spinlock_t		lock;
+	struct device		*dev;
+
+	uint32_t		h_start_width;
+	uint32_t		v_start_width;
+	enum disp_data_mapping	disp_data_fmt;
+};
+
+struct dma_chan_request {
+	struct mx3fb_data	*mx3fb;
+	enum ipu_channel	id;
+};
+
+/* MX3 specific framebuffer information. */
+struct mx3fb_info {
+	int				blank;
+	enum ipu_channel		ipu_ch;
+	uint32_t			cur_ipu_buf;
+
+	u32				pseudo_palette[16];
+
+	struct completion		flip_cmpl;
+	struct mutex			mutex;	/* Protects fb-ops */
+	struct mx3fb_data		*mx3fb;
+	struct idmac_channel		*idmac_channel;
+	struct dma_async_tx_descriptor	*txd;
+	dma_cookie_t			cookie;
+	struct scatterlist		sg[2];
+
+	struct fb_var_screeninfo	cur_var; /* current var info */
+};
+
+static void mx3fb_dma_done(void *);
+
+/* Used fb-mode and bpp. Can be set on kernel command line, therefore file-static. */
+static const char *fb_mode;
+static unsigned long default_bpp = 16;
+
+static u32 mx3fb_read_reg(struct mx3fb_data *mx3fb, unsigned long reg)
+{
+	return __raw_readl(mx3fb->reg_base + reg);
+}
+
+static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long reg)
+{
+	__raw_writel(value, mx3fb->reg_base + reg);
+}
+
+struct di_mapping {
+	uint32_t b0, b1, b2;
+};
+
+static const struct di_mapping di_mappings[] = {
+	[IPU_DISP_DATA_MAPPING_RGB666] = { 0x0005000f, 0x000b000f, 0x0011000f },
+	[IPU_DISP_DATA_MAPPING_RGB565] = { 0x0004003f, 0x000a000f, 0x000f003f },
+	[IPU_DISP_DATA_MAPPING_RGB888] = { 0x00070000, 0x000f0000, 0x00170000 },
+};
+
+static void sdc_fb_init(struct mx3fb_info *fbi)
+{
+	struct mx3fb_data *mx3fb = fbi->mx3fb;
+	uint32_t reg;
+
+	reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
+
+	mx3fb_write_reg(mx3fb, reg | SDC_COM_BG_EN, SDC_COM_CONF);
+}
+
+/* Returns enabled flag before uninit */
+static uint32_t sdc_fb_uninit(struct mx3fb_info *fbi)
+{
+	struct mx3fb_data *mx3fb = fbi->mx3fb;
+	uint32_t reg;
+
+	reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
+
+	mx3fb_write_reg(mx3fb, reg & ~SDC_COM_BG_EN, SDC_COM_CONF);
+
+	return reg & SDC_COM_BG_EN;
+}
+
+static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
+{
+	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+	struct idmac_channel *ichan = mx3_fbi->idmac_channel;
+	struct dma_chan *dma_chan = &ichan->dma_chan;
+	unsigned long flags;
+	dma_cookie_t cookie;
+
+	if (mx3_fbi->txd)
+		dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
+			to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
+	else
+		dev_dbg(mx3fb->dev, "mx3fbi %p, txd = NULL\n", mx3_fbi);
+
+	/* This enables the channel */
+	if (mx3_fbi->cookie < 0) {
+		mx3_fbi->txd = dmaengine_prep_slave_sg(dma_chan,
+		      &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
+		if (!mx3_fbi->txd) {
+			dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n",
+				dma_chan->chan_id);
+			return;
+		}
+
+		mx3_fbi->txd->callback_param	= mx3_fbi->txd;
+		mx3_fbi->txd->callback		= mx3fb_dma_done;
+
+		cookie = mx3_fbi->txd->tx_submit(mx3_fbi->txd);
+		dev_dbg(mx3fb->dev, "%d: Submit %p #%d [%c]\n", __LINE__,
+		       mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+');
+	} else {
+		if (!mx3_fbi->txd || !mx3_fbi->txd->tx_submit) {
+			dev_err(mx3fb->dev, "Cannot enable channel %d\n",
+				dma_chan->chan_id);
+			return;
+		}
+
+		/* Just re-activate the same buffer */
+		dma_async_issue_pending(dma_chan);
+		cookie = mx3_fbi->cookie;
+		dev_dbg(mx3fb->dev, "%d: Re-submit %p #%d [%c]\n", __LINE__,
+		       mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+');
+	}
+
+	if (cookie >= 0) {
+		spin_lock_irqsave(&mx3fb->lock, flags);
+		sdc_fb_init(mx3_fbi);
+		mx3_fbi->cookie = cookie;
+		spin_unlock_irqrestore(&mx3fb->lock, flags);
+	}
+
+	/*
+	 * Attention! Without this msleep the channel keeps generating
+	 * interrupts. Next sdc_set_brightness() is going to be called
+	 * from mx3fb_blank().
+	 */
+	msleep(2);
+}
+
+static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
+{
+	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+	uint32_t enabled;
+	unsigned long flags;
+
+	if (mx3_fbi->txd == NULL)
+		return;
+
+	spin_lock_irqsave(&mx3fb->lock, flags);
+
+	enabled = sdc_fb_uninit(mx3_fbi);
+
+	spin_unlock_irqrestore(&mx3fb->lock, flags);
+
+	mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan,
+						   DMA_TERMINATE_ALL, 0);
+	mx3_fbi->txd = NULL;
+	mx3_fbi->cookie = -EINVAL;
+}
+
+/**
+ * sdc_set_window_pos() - set window position of the respective plane.
+ * @mx3fb:	mx3fb context.
+ * @channel:	IPU DMAC channel ID.
+ * @x_pos:	X coordinate relative to the top left corner to place window at.
+ * @y_pos:	Y coordinate relative to the top left corner to place window at.
+ * @return:	0 on success or negative error code on failure.
+ */
+static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel,
+			      int16_t x_pos, int16_t y_pos)
+{
+	if (channel != IDMAC_SDC_0)
+		return -EINVAL;
+
+	x_pos += mx3fb->h_start_width;
+	y_pos += mx3fb->v_start_width;
+
+	mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS);
+	return 0;
+}
+
+/**
+ * sdc_init_panel() - initialize a synchronous LCD panel.
+ * @mx3fb:		mx3fb context.
+ * @panel:		panel type.
+ * @pixel_clk:		desired pixel clock frequency in Hz.
+ * @width:		width of panel in pixels.
+ * @height:		height of panel in pixels.
+ * @h_start_width:	number of pixel clocks between the HSYNC signal pulse
+ *			and the start of valid data.
+ * @h_sync_width:	width of the HSYNC signal in units of pixel clocks.
+ * @h_end_width:	number of pixel clocks between the end of valid data
+ *			and the HSYNC signal for next line.
+ * @v_start_width:	number of lines between the VSYNC signal pulse and the
+ *			start of valid data.
+ * @v_sync_width:	width of the VSYNC signal in units of lines
+ * @v_end_width:	number of lines between the end of valid data and the
+ *			VSYNC signal for next frame.
+ * @sig:		bitfield of signal polarities for LCD interface.
+ * @return:		0 on success or negative error code on failure.
+ */
+static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
+			  uint32_t pixel_clk,
+			  uint16_t width, uint16_t height,
+			  uint16_t h_start_width, uint16_t h_sync_width,
+			  uint16_t h_end_width, uint16_t v_start_width,
+			  uint16_t v_sync_width, uint16_t v_end_width,
+			  struct ipu_di_signal_cfg sig)
+{
+	unsigned long lock_flags;
+	uint32_t reg;
+	uint32_t old_conf;
+	uint32_t div;
+	struct clk *ipu_clk;
+	const struct di_mapping *map;
+
+	dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
+
+	if (v_sync_width == 0 || h_sync_width == 0)
+		return -EINVAL;
+
+	/* Init panel size and blanking periods */
+	reg = ((uint32_t) (h_sync_width - 1) << 26) |
+		((uint32_t) (width + h_start_width + h_end_width - 1) << 16);
+	mx3fb_write_reg(mx3fb, reg, SDC_HOR_CONF);
+
+#ifdef DEBUG
+	printk(KERN_CONT " hor_conf %x,", reg);
+#endif
+
+	reg = ((uint32_t) (v_sync_width - 1) << 26) | SDC_V_SYNC_WIDTH_L |
+	    ((uint32_t) (height + v_start_width + v_end_width - 1) << 16);
+	mx3fb_write_reg(mx3fb, reg, SDC_VER_CONF);
+
+#ifdef DEBUG
+	printk(KERN_CONT " ver_conf %x\n", reg);
+#endif
+
+	mx3fb->h_start_width = h_start_width;
+	mx3fb->v_start_width = v_start_width;
+
+	switch (panel) {
+	case IPU_PANEL_SHARP_TFT:
+		mx3fb_write_reg(mx3fb, 0x00FD0102L, SDC_SHARP_CONF_1);
+		mx3fb_write_reg(mx3fb, 0x00F500F4L, SDC_SHARP_CONF_2);
+		mx3fb_write_reg(mx3fb, SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF);
+		break;
+	case IPU_PANEL_TFT:
+		mx3fb_write_reg(mx3fb, SDC_COM_TFT_COLOR, SDC_COM_CONF);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Init clocking */
+
+	/*
+	 * Calculate divider: fractional part is 4 bits so simply multiple by
+	 * 2^4 to get fractional part, as long as we stay under ~250MHz and on
+	 * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
+	 */
+	ipu_clk = clk_get(mx3fb->dev, NULL);
+	if (!IS_ERR(ipu_clk)) {
+		div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
+		clk_put(ipu_clk);
+	} else {
+		div = 0;
+	}
+
+	if (div < 0x40) {	/* Divider less than 4 */
+		dev_dbg(mx3fb->dev,
+			"InitPanel() - Pixel clock divider less than 4\n");
+		div = 0x40;
+	}
+
+	dev_dbg(mx3fb->dev, "pixel clk = %u, divider %u.%u\n",
+		pixel_clk, div >> 4, (div & 7) * 125);
+
+	spin_lock_irqsave(&mx3fb->lock, lock_flags);
+
+	/*
+	 * DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits
+	 * fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing
+	 * debug. DISP3_IF_CLK_UP_WR is 0
+	 */
+	mx3fb_write_reg(mx3fb, (((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF);
+
+	/* DI settings */
+	old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF;
+	old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT |
+		sig.clksel_en << DI_D3_CLK_SEL_SHIFT |
+		sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT;
+	mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF);
+
+	old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF;
+	old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT |
+		sig.clk_pol << DI_D3_CLK_POL_SHIFT |
+		sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT |
+		sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT |
+		sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
+	mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
+
+	map = &di_mappings[mx3fb->disp_data_fmt];
+	mx3fb_write_reg(mx3fb, map->b0, DI_DISP3_B0_MAP);
+	mx3fb_write_reg(mx3fb, map->b1, DI_DISP3_B1_MAP);
+	mx3fb_write_reg(mx3fb, map->b2, DI_DISP3_B2_MAP);
+
+	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
+
+	dev_dbg(mx3fb->dev, "DI_DISP_IF_CONF = 0x%08X\n",
+		mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF));
+	dev_dbg(mx3fb->dev, "DI_DISP_SIG_POL = 0x%08X\n",
+		mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL));
+	dev_dbg(mx3fb->dev, "DI_DISP3_TIME_CONF = 0x%08X\n",
+		mx3fb_read_reg(mx3fb, DI_DISP3_TIME_CONF));
+
+	return 0;
+}
+
+/**
+ * sdc_set_color_key() - set the transparent color key for SDC graphic plane.
+ * @mx3fb:	mx3fb context.
+ * @channel:	IPU DMAC channel ID.
+ * @enable:	boolean to enable or disable color keyl.
+ * @color_key:	24-bit RGB color to use as transparent color key.
+ * @return:	0 on success or negative error code on failure.
+ */
+static int sdc_set_color_key(struct mx3fb_data *mx3fb, enum ipu_channel channel,
+			     bool enable, uint32_t color_key)
+{
+	uint32_t reg, sdc_conf;
+	unsigned long lock_flags;
+
+	spin_lock_irqsave(&mx3fb->lock, lock_flags);
+
+	sdc_conf = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
+	if (channel == IDMAC_SDC_0)
+		sdc_conf &= ~SDC_COM_GWSEL;
+	else
+		sdc_conf |= SDC_COM_GWSEL;
+
+	if (enable) {
+		reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0xFF000000L;
+		mx3fb_write_reg(mx3fb, reg | (color_key & 0x00FFFFFFL),
+			     SDC_GW_CTRL);
+
+		sdc_conf |= SDC_COM_KEY_COLOR_G;
+	} else {
+		sdc_conf &= ~SDC_COM_KEY_COLOR_G;
+	}
+	mx3fb_write_reg(mx3fb, sdc_conf, SDC_COM_CONF);
+
+	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
+
+	return 0;
+}
+
+/**
+ * sdc_set_global_alpha() - set global alpha blending modes.
+ * @mx3fb:	mx3fb context.
+ * @enable:	boolean to enable or disable global alpha blending. If disabled,
+ *		per pixel blending is used.
+ * @alpha:	global alpha value.
+ * @return:	0 on success or negative error code on failure.
+ */
+static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t alpha)
+{
+	uint32_t reg;
+	unsigned long lock_flags;
+
+	spin_lock_irqsave(&mx3fb->lock, lock_flags);
+
+	if (enable) {
+		reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0x00FFFFFFL;
+		mx3fb_write_reg(mx3fb, reg | ((uint32_t) alpha << 24), SDC_GW_CTRL);
+
+		reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
+		mx3fb_write_reg(mx3fb, reg | SDC_COM_GLB_A, SDC_COM_CONF);
+	} else {
+		reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
+		mx3fb_write_reg(mx3fb, reg & ~SDC_COM_GLB_A, SDC_COM_CONF);
+	}
+
+	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
+
+	return 0;
+}
+
+static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
+{
+	dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value);
+	/* This might be board-specific */
+	mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
+	return;
+}
+
+static uint32_t bpp_to_pixfmt(int bpp)
+{
+	uint32_t pixfmt = 0;
+	switch (bpp) {
+	case 24:
+		pixfmt = IPU_PIX_FMT_BGR24;
+		break;
+	case 32:
+		pixfmt = IPU_PIX_FMT_BGR32;
+		break;
+	case 16:
+		pixfmt = IPU_PIX_FMT_RGB565;
+		break;
+	}
+	return pixfmt;
+}
+
+static int mx3fb_blank(int blank, struct fb_info *fbi);
+static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
+				  bool lock);
+static int mx3fb_unmap_video_memory(struct fb_info *fbi);
+
+/**
+ * mx3fb_set_fix() - set fixed framebuffer parameters from variable settings.
+ * @info:	framebuffer information pointer
+ * @return:	0 on success or negative error code on failure.
+ */
+static int mx3fb_set_fix(struct fb_info *fbi)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
+
+	strncpy(fix->id, "DISP3 BG", 8);
+
+	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->accel = FB_ACCEL_NONE;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+
+	return 0;
+}
+
+static void mx3fb_dma_done(void *arg)
+{
+	struct idmac_tx_desc *tx_desc = to_tx_desc(arg);
+	struct dma_chan *chan = tx_desc->txd.chan;
+	struct idmac_channel *ichannel = to_idmac_chan(chan);
+	struct mx3fb_data *mx3fb = ichannel->client;
+	struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
+
+	dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq);
+
+	/* We only need one interrupt, it will be re-enabled as needed */
+	disable_irq_nosync(ichannel->eof_irq);
+
+	complete(&mx3_fbi->flip_cmpl);
+}
+
+static bool mx3fb_must_set_par(struct fb_info *fbi)
+{
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	struct fb_var_screeninfo old_var = mx3_fbi->cur_var;
+	struct fb_var_screeninfo new_var = fbi->var;
+
+	if ((fbi->var.activate & FB_ACTIVATE_FORCE) &&
+	    (fbi->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+		return true;
+
+	/*
+	 * Ignore xoffset and yoffset update,
+	 * because pan display handles this case.
+	 */
+	old_var.xoffset = new_var.xoffset;
+	old_var.yoffset = new_var.yoffset;
+
+	return !!memcmp(&old_var, &new_var, sizeof(struct fb_var_screeninfo));
+}
+
+static int __set_par(struct fb_info *fbi, bool lock)
+{
+	u32 mem_len, cur_xoffset, cur_yoffset;
+	struct ipu_di_signal_cfg sig_cfg;
+	enum ipu_panel mode = IPU_PANEL_TFT;
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+	struct idmac_channel *ichan = mx3_fbi->idmac_channel;
+	struct idmac_video_param *video = &ichan->params.video;
+	struct scatterlist *sg = mx3_fbi->sg;
+
+	/* Total cleanup */
+	if (mx3_fbi->txd)
+		sdc_disable_channel(mx3_fbi);
+
+	mx3fb_set_fix(fbi);
+
+	mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
+	if (mem_len > fbi->fix.smem_len) {
+		if (fbi->fix.smem_start)
+			mx3fb_unmap_video_memory(fbi);
+
+		if (mx3fb_map_video_memory(fbi, mem_len, lock) < 0)
+			return -ENOMEM;
+	}
+
+	sg_init_table(&sg[0], 1);
+	sg_init_table(&sg[1], 1);
+
+	sg_dma_address(&sg[0]) = fbi->fix.smem_start;
+	sg_set_page(&sg[0], virt_to_page(fbi->screen_base),
+		    fbi->fix.smem_len,
+		    offset_in_page(fbi->screen_base));
+
+	if (mx3_fbi->ipu_ch == IDMAC_SDC_0) {
+		memset(&sig_cfg, 0, sizeof(sig_cfg));
+		if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
+			sig_cfg.Hsync_pol = true;
+		if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
+			sig_cfg.Vsync_pol = true;
+		if (fbi->var.sync & FB_SYNC_CLK_INVERT)
+			sig_cfg.clk_pol = true;
+		if (fbi->var.sync & FB_SYNC_DATA_INVERT)
+			sig_cfg.data_pol = true;
+		if (fbi->var.sync & FB_SYNC_OE_ACT_HIGH)
+			sig_cfg.enable_pol = true;
+		if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
+			sig_cfg.clkidle_en = true;
+		if (fbi->var.sync & FB_SYNC_CLK_SEL_EN)
+			sig_cfg.clksel_en = true;
+		if (fbi->var.sync & FB_SYNC_SHARP_MODE)
+			mode = IPU_PANEL_SHARP_TFT;
+
+		dev_dbg(fbi->device, "pixclock = %ul Hz\n",
+			(u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
+
+		if (sdc_init_panel(mx3fb, mode,
+				   (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
+				   fbi->var.xres, fbi->var.yres,
+				   fbi->var.left_margin,
+				   fbi->var.hsync_len,
+				   fbi->var.right_margin +
+				   fbi->var.hsync_len,
+				   fbi->var.upper_margin,
+				   fbi->var.vsync_len,
+				   fbi->var.lower_margin +
+				   fbi->var.vsync_len, sig_cfg) != 0) {
+			dev_err(fbi->device,
+				"mx3fb: Error initializing panel.\n");
+			return -EINVAL;
+		}
+	}
+
+	sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0);
+
+	mx3_fbi->cur_ipu_buf	= 0;
+
+	video->out_pixel_fmt	= bpp_to_pixfmt(fbi->var.bits_per_pixel);
+	video->out_width	= fbi->var.xres;
+	video->out_height	= fbi->var.yres;
+	video->out_stride	= fbi->var.xres_virtual;
+
+	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
+		sdc_enable_channel(mx3_fbi);
+		/*
+		 * sg[0] points to fb smem_start address
+		 * and is actually active in controller.
+		 */
+		mx3_fbi->cur_var.xoffset = 0;
+		mx3_fbi->cur_var.yoffset = 0;
+	}
+
+	/*
+	 * Preserve xoffset and yoffest in case they are
+	 * inactive in controller as fb is blanked.
+	 */
+	cur_xoffset = mx3_fbi->cur_var.xoffset;
+	cur_yoffset = mx3_fbi->cur_var.yoffset;
+	mx3_fbi->cur_var = fbi->var;
+	mx3_fbi->cur_var.xoffset = cur_xoffset;
+	mx3_fbi->cur_var.yoffset = cur_yoffset;
+
+	return 0;
+}
+
+/**
+ * mx3fb_set_par() - set framebuffer parameters and change the operating mode.
+ * @fbi:	framebuffer information pointer.
+ * @return:	0 on success or negative error code on failure.
+ */
+static int mx3fb_set_par(struct fb_info *fbi)
+{
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+	struct idmac_channel *ichan = mx3_fbi->idmac_channel;
+	int ret;
+
+	dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
+
+	mutex_lock(&mx3_fbi->mutex);
+
+	ret = mx3fb_must_set_par(fbi) ? __set_par(fbi, true) : 0;
+
+	mutex_unlock(&mx3_fbi->mutex);
+
+	return ret;
+}
+
+/**
+ * mx3fb_check_var() - check and adjust framebuffer variable parameters.
+ * @var:	framebuffer variable parameters
+ * @fbi:	framebuffer information pointer
+ */
+static int mx3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	u32 vtotal;
+	u32 htotal;
+
+	dev_dbg(fbi->device, "%s\n", __func__);
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
+	    (var->bits_per_pixel != 16))
+		var->bits_per_pixel = default_bpp;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		var->red.length = 5;
+		var->red.offset = 11;
+		var->red.msb_right = 0;
+
+		var->green.length = 6;
+		var->green.offset = 5;
+		var->green.msb_right = 0;
+
+		var->blue.length = 5;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 24:
+		var->red.length = 8;
+		var->red.offset = 16;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		var->transp.msb_right = 0;
+		break;
+	case 32:
+		var->red.length = 8;
+		var->red.offset = 16;
+		var->red.msb_right = 0;
+
+		var->green.length = 8;
+		var->green.offset = 8;
+		var->green.msb_right = 0;
+
+		var->blue.length = 8;
+		var->blue.offset = 0;
+		var->blue.msb_right = 0;
+
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		var->transp.msb_right = 0;
+		break;
+	}
+
+	if (var->pixclock < 1000) {
+		htotal = var->xres + var->right_margin + var->hsync_len +
+		    var->left_margin;
+		vtotal = var->yres + var->lower_margin + var->vsync_len +
+		    var->upper_margin;
+		var->pixclock = (vtotal * htotal * 6UL) / 100UL;
+		var->pixclock = KHZ2PICOS(var->pixclock);
+		dev_dbg(fbi->device, "pixclock set for 60Hz refresh = %u ps\n",
+			var->pixclock);
+	}
+
+	var->height = -1;
+	var->width = -1;
+	var->grayscale = 0;
+
+	/* Preserve sync flags */
+	var->sync |= mx3_fbi->cur_var.sync;
+	mx3_fbi->cur_var.sync |= var->sync;
+
+	return 0;
+}
+
+static u32 chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int trans, struct fb_info *fbi)
+{
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	u32 val;
+	int ret = 1;
+
+	dev_dbg(fbi->device, "%s, regno = %u\n", __func__, regno);
+
+	mutex_lock(&mx3_fbi->mutex);
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (fbi->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+				      7471 * blue) >> 16;
+	switch (fbi->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = fbi->pseudo_palette;
+
+			val = chan_to_field(red, &fbi->var.red);
+			val |= chan_to_field(green, &fbi->var.green);
+			val |= chan_to_field(blue, &fbi->var.blue);
+
+			pal[regno] = val;
+
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		break;
+	}
+	mutex_unlock(&mx3_fbi->mutex);
+
+	return ret;
+}
+
+static void __blank(int blank, struct fb_info *fbi)
+{
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+	int was_blank = mx3_fbi->blank;
+
+	mx3_fbi->blank = blank;
+
+	/* Attention!
+	 * Do not call sdc_disable_channel() for a channel that is disabled
+	 * already! This will result in a kernel NULL pointer dereference
+	 * (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are
+	 * handled equally by this driver.
+	 */
+	if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK)
+		return;
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		sdc_set_brightness(mx3fb, 0);
+		memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
+		/* Give LCD time to update - enough for 50 and 60 Hz */
+		msleep(25);
+		sdc_disable_channel(mx3_fbi);
+		break;
+	case FB_BLANK_UNBLANK:
+		sdc_enable_channel(mx3_fbi);
+		sdc_set_brightness(mx3fb, mx3fb->backlight_level);
+		break;
+	}
+}
+
+/**
+ * mx3fb_blank() - blank the display.
+ */
+static int mx3fb_blank(int blank, struct fb_info *fbi)
+{
+	struct mx3fb_info *mx3_fbi = fbi->par;
+
+	dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
+		blank, fbi->screen_base, fbi->fix.smem_len);
+
+	if (mx3_fbi->blank == blank)
+		return 0;
+
+	mutex_lock(&mx3_fbi->mutex);
+	__blank(blank, fbi);
+	mutex_unlock(&mx3_fbi->mutex);
+
+	return 0;
+}
+
+/**
+ * mx3fb_pan_display() - pan or wrap the display
+ * @var:	variable screen buffer information.
+ * @info:	framebuffer information pointer.
+ *
+ * We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int mx3fb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *fbi)
+{
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	u32 y_bottom;
+	unsigned long base;
+	off_t offset;
+	dma_cookie_t cookie;
+	struct scatterlist *sg = mx3_fbi->sg;
+	struct dma_chan *dma_chan = &mx3_fbi->idmac_channel->dma_chan;
+	struct dma_async_tx_descriptor *txd;
+	int ret;
+
+	dev_dbg(fbi->device, "%s [%c]\n", __func__,
+		list_empty(&mx3_fbi->idmac_channel->queue) ? '-' : '+');
+
+	if (var->xoffset > 0) {
+		dev_dbg(fbi->device, "x panning not supported\n");
+		return -EINVAL;
+	}
+
+	if (mx3_fbi->cur_var.xoffset == var->xoffset &&
+	    mx3_fbi->cur_var.yoffset == var->yoffset)
+		return 0;	/* No change, do nothing */
+
+	y_bottom = var->yoffset;
+
+	if (!(var->vmode & FB_VMODE_YWRAP))
+		y_bottom += fbi->var.yres;
+
+	if (y_bottom > fbi->var.yres_virtual)
+		return -EINVAL;
+
+	mutex_lock(&mx3_fbi->mutex);
+
+	offset = var->yoffset * fbi->fix.line_length
+	       + var->xoffset * (fbi->var.bits_per_pixel / 8);
+	base = fbi->fix.smem_start + offset;
+
+	dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n",
+		mx3_fbi->cur_ipu_buf, base);
+
+	/*
+	 * We enable the End of Frame interrupt, which will free a tx-descriptor,
+	 * which we will need for the next device_prep_slave_sg(). The
+	 * IRQ-handler will disable the IRQ again.
+	 */
+	init_completion(&mx3_fbi->flip_cmpl);
+	enable_irq(mx3_fbi->idmac_channel->eof_irq);
+
+	ret = wait_for_completion_timeout(&mx3_fbi->flip_cmpl, HZ / 10);
+	if (ret <= 0) {
+		mutex_unlock(&mx3_fbi->mutex);
+		dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ?
+			 "user interrupt" : "timeout");
+		disable_irq(mx3_fbi->idmac_channel->eof_irq);
+		return ret ? : -ETIMEDOUT;
+	}
+
+	mx3_fbi->cur_ipu_buf = !mx3_fbi->cur_ipu_buf;
+
+	sg_dma_address(&sg[mx3_fbi->cur_ipu_buf]) = base;
+	sg_set_page(&sg[mx3_fbi->cur_ipu_buf],
+		    virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len,
+		    offset_in_page(fbi->screen_base + offset));
+
+	if (mx3_fbi->txd)
+		async_tx_ack(mx3_fbi->txd);
+
+	txd = dmaengine_prep_slave_sg(dma_chan, sg +
+		mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
+	if (!txd) {
+		dev_err(fbi->device,
+			"Error preparing a DMA transaction descriptor.\n");
+		mutex_unlock(&mx3_fbi->mutex);
+		return -EIO;
+	}
+
+	txd->callback_param	= txd;
+	txd->callback		= mx3fb_dma_done;
+
+	/*
+	 * Emulate original mx3fb behaviour: each new call to idmac_tx_submit()
+	 * should switch to another buffer
+	 */
+	cookie = txd->tx_submit(txd);
+	dev_dbg(fbi->device, "%d: Submit %p #%d\n", __LINE__, txd, cookie);
+	if (cookie < 0) {
+		dev_err(fbi->device,
+			"Error updating SDC buf %d to address=0x%08lX\n",
+			mx3_fbi->cur_ipu_buf, base);
+		mutex_unlock(&mx3_fbi->mutex);
+		return -EIO;
+	}
+
+	mx3_fbi->txd = txd;
+
+	fbi->var.xoffset = var->xoffset;
+	fbi->var.yoffset = var->yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		fbi->var.vmode |= FB_VMODE_YWRAP;
+	else
+		fbi->var.vmode &= ~FB_VMODE_YWRAP;
+
+	mx3_fbi->cur_var = fbi->var;
+
+	mutex_unlock(&mx3_fbi->mutex);
+
+	dev_dbg(fbi->device, "Update complete\n");
+
+	return 0;
+}
+
+/*
+ * This structure contains the pointers to the control functions that are
+ * invoked by the core framebuffer driver to perform operations like
+ * blitting, rectangle filling, copy regions and cursor definition.
+ */
+static struct fb_ops mx3fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_set_par = mx3fb_set_par,
+	.fb_check_var = mx3fb_check_var,
+	.fb_setcolreg = mx3fb_setcolreg,
+	.fb_pan_display = mx3fb_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_blank = mx3fb_blank,
+};
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks.      Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+
+/*
+ * Suspends the framebuffer and blanks the screen. Power management support
+ */
+static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
+	struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
+
+	console_lock();
+	fb_set_suspend(mx3fb->fbi, 1);
+	console_unlock();
+
+	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
+		sdc_disable_channel(mx3_fbi);
+		sdc_set_brightness(mx3fb, 0);
+
+	}
+	return 0;
+}
+
+/*
+ * Resumes the framebuffer and unblanks the screen. Power management support
+ */
+static int mx3fb_resume(struct platform_device *pdev)
+{
+	struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
+	struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
+
+	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
+		sdc_enable_channel(mx3_fbi);
+		sdc_set_brightness(mx3fb, mx3fb->backlight_level);
+	}
+
+	console_lock();
+	fb_set_suspend(mx3fb->fbi, 0);
+	console_unlock();
+
+	return 0;
+}
+#else
+#define mx3fb_suspend   NULL
+#define mx3fb_resume    NULL
+#endif
+
+/*
+ * Main framebuffer functions
+ */
+
+/**
+ * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
+ * @fbi:	framebuffer information pointer
+ * @mem_len:	length of mapped memory
+ * @lock:	do not lock during initialisation
+ * @return:	Error code indicating success or failure
+ *
+ * This buffer is remapped into a non-cached, non-buffered, memory region to
+ * allow palette and pixel writes to occur without flushing the cache. Once this
+ * area is remapped, all virtual memory access to the video memory should occur
+ * at the new region.
+ */
+static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
+				  bool lock)
+{
+	int retval = 0;
+	dma_addr_t addr;
+
+	fbi->screen_base = dma_alloc_writecombine(fbi->device,
+						  mem_len,
+						  &addr, GFP_DMA | GFP_KERNEL);
+
+	if (!fbi->screen_base) {
+		dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
+			mem_len);
+		retval = -EBUSY;
+		goto err0;
+	}
+
+	if (lock)
+		mutex_lock(&fbi->mm_lock);
+	fbi->fix.smem_start = addr;
+	fbi->fix.smem_len = mem_len;
+	if (lock)
+		mutex_unlock(&fbi->mm_lock);
+
+	dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n",
+		(uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
+
+	fbi->screen_size = fbi->fix.smem_len;
+
+	/* Clear the screen */
+	memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
+
+	return 0;
+
+err0:
+	fbi->fix.smem_len = 0;
+	fbi->fix.smem_start = 0;
+	fbi->screen_base = NULL;
+	return retval;
+}
+
+/**
+ * mx3fb_unmap_video_memory() - de-allocate frame buffer memory.
+ * @fbi:	framebuffer information pointer
+ * @return:	error code indicating success or failure
+ */
+static int mx3fb_unmap_video_memory(struct fb_info *fbi)
+{
+	dma_free_writecombine(fbi->device, fbi->fix.smem_len,
+			      fbi->screen_base, fbi->fix.smem_start);
+
+	fbi->screen_base = NULL;
+	mutex_lock(&fbi->mm_lock);
+	fbi->fix.smem_start = 0;
+	fbi->fix.smem_len = 0;
+	mutex_unlock(&fbi->mm_lock);
+	return 0;
+}
+
+/**
+ * mx3fb_init_fbinfo() - initialize framebuffer information object.
+ * @return:	initialized framebuffer structure.
+ */
+static struct fb_info *mx3fb_init_fbinfo(struct device *dev, struct fb_ops *ops)
+{
+	struct fb_info *fbi;
+	struct mx3fb_info *mx3fbi;
+	int ret;
+
+	/* Allocate sufficient memory for the fb structure */
+	fbi = framebuffer_alloc(sizeof(struct mx3fb_info), dev);
+	if (!fbi)
+		return NULL;
+
+	mx3fbi			= fbi->par;
+	mx3fbi->cookie		= -EINVAL;
+	mx3fbi->cur_ipu_buf	= 0;
+
+	fbi->var.activate	= FB_ACTIVATE_NOW;
+
+	fbi->fbops		= ops;
+	fbi->flags		= FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette	= mx3fbi->pseudo_palette;
+
+	mutex_init(&mx3fbi->mutex);
+
+	/* Allocate colormap */
+	ret = fb_alloc_cmap(&fbi->cmap, 16, 0);
+	if (ret < 0) {
+		framebuffer_release(fbi);
+		return NULL;
+	}
+
+	return fbi;
+}
+
+static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
+{
+	struct device *dev = mx3fb->dev;
+	struct mx3fb_platform_data *mx3fb_pdata = dev_get_platdata(dev);
+	const char *name = mx3fb_pdata->name;
+	unsigned int irq;
+	struct fb_info *fbi;
+	struct mx3fb_info *mx3fbi;
+	const struct fb_videomode *mode;
+	int ret, num_modes;
+
+	if (mx3fb_pdata->disp_data_fmt >= ARRAY_SIZE(di_mappings)) {
+		dev_err(dev, "Illegal display data format %d\n",
+				mx3fb_pdata->disp_data_fmt);
+		return -EINVAL;
+	}
+
+	ichan->client = mx3fb;
+	irq = ichan->eof_irq;
+
+	if (ichan->dma_chan.chan_id != IDMAC_SDC_0)
+		return -EINVAL;
+
+	fbi = mx3fb_init_fbinfo(dev, &mx3fb_ops);
+	if (!fbi)
+		return -ENOMEM;
+
+	if (!fb_mode)
+		fb_mode = name;
+
+	if (!fb_mode) {
+		ret = -EINVAL;
+		goto emode;
+	}
+
+	if (mx3fb_pdata->mode && mx3fb_pdata->num_modes) {
+		mode = mx3fb_pdata->mode;
+		num_modes = mx3fb_pdata->num_modes;
+	} else {
+		mode = mx3fb_modedb;
+		num_modes = ARRAY_SIZE(mx3fb_modedb);
+	}
+
+	if (!fb_find_mode(&fbi->var, fbi, fb_mode, mode,
+			  num_modes, NULL, default_bpp)) {
+		ret = -EBUSY;
+		goto emode;
+	}
+
+	fb_videomode_to_modelist(mode, num_modes, &fbi->modelist);
+
+	/* Default Y virtual size is 2x panel size */
+	fbi->var.yres_virtual = fbi->var.yres * 2;
+
+	mx3fb->fbi = fbi;
+
+	/* set Display Interface clock period */
+	mx3fb_write_reg(mx3fb, 0x00100010L, DI_HSP_CLK_PER);
+	/* Might need to trigger HSP clock change - see 44.3.3.8.5 */
+
+	sdc_set_brightness(mx3fb, 255);
+	sdc_set_global_alpha(mx3fb, true, 0xFF);
+	sdc_set_color_key(mx3fb, IDMAC_SDC_0, false, 0);
+
+	mx3fbi			= fbi->par;
+	mx3fbi->idmac_channel	= ichan;
+	mx3fbi->ipu_ch		= ichan->dma_chan.chan_id;
+	mx3fbi->mx3fb		= mx3fb;
+	mx3fbi->blank		= FB_BLANK_NORMAL;
+
+	mx3fb->disp_data_fmt	= mx3fb_pdata->disp_data_fmt;
+
+	init_completion(&mx3fbi->flip_cmpl);
+	disable_irq(ichan->eof_irq);
+	dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
+	ret = __set_par(fbi, false);
+	if (ret < 0)
+		goto esetpar;
+
+	__blank(FB_BLANK_UNBLANK, fbi);
+
+	dev_info(dev, "registered, using mode %s\n", fb_mode);
+
+	ret = register_framebuffer(fbi);
+	if (ret < 0)
+		goto erfb;
+
+	return 0;
+
+erfb:
+esetpar:
+emode:
+	fb_dealloc_cmap(&fbi->cmap);
+	framebuffer_release(fbi);
+
+	return ret;
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+	struct dma_chan_request *rq = arg;
+	struct device *dev;
+	struct mx3fb_platform_data *mx3fb_pdata;
+
+	if (!imx_dma_is_ipu(chan))
+		return false;
+
+	if (!rq)
+		return false;
+
+	dev = rq->mx3fb->dev;
+	mx3fb_pdata = dev_get_platdata(dev);
+
+	return rq->id == chan->chan_id &&
+		mx3fb_pdata->dma_dev == chan->device->dev;
+}
+
+static void release_fbi(struct fb_info *fbi)
+{
+	mx3fb_unmap_video_memory(fbi);
+
+	fb_dealloc_cmap(&fbi->cmap);
+
+	unregister_framebuffer(fbi);
+	framebuffer_release(fbi);
+}
+
+static int mx3fb_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int ret;
+	struct resource *sdc_reg;
+	struct mx3fb_data *mx3fb;
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct dma_chan_request rq;
+
+	/*
+	 * Display Interface (DI) and Synchronous Display Controller (SDC)
+	 * registers
+	 */
+	sdc_reg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!sdc_reg)
+		return -EINVAL;
+
+	mx3fb = kzalloc(sizeof(*mx3fb), GFP_KERNEL);
+	if (!mx3fb)
+		return -ENOMEM;
+
+	spin_lock_init(&mx3fb->lock);
+
+	mx3fb->reg_base = ioremap(sdc_reg->start, resource_size(sdc_reg));
+	if (!mx3fb->reg_base) {
+		ret = -ENOMEM;
+		goto eremap;
+	}
+
+	pr_debug("Remapped %pR at %p\n", sdc_reg, mx3fb->reg_base);
+
+	/* IDMAC interface */
+	dmaengine_get();
+
+	mx3fb->dev = dev;
+	platform_set_drvdata(pdev, mx3fb);
+
+	rq.mx3fb = mx3fb;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_cap_set(DMA_PRIVATE, mask);
+	rq.id = IDMAC_SDC_0;
+	chan = dma_request_channel(mask, chan_filter, &rq);
+	if (!chan) {
+		ret = -EBUSY;
+		goto ersdc0;
+	}
+
+	mx3fb->backlight_level = 255;
+
+	ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
+	if (ret < 0)
+		goto eisdc0;
+
+	return 0;
+
+eisdc0:
+	dma_release_channel(chan);
+ersdc0:
+	dmaengine_put();
+	iounmap(mx3fb->reg_base);
+eremap:
+	kfree(mx3fb);
+	dev_err(dev, "mx3fb: failed to register fb\n");
+	return ret;
+}
+
+static int mx3fb_remove(struct platform_device *dev)
+{
+	struct mx3fb_data *mx3fb = platform_get_drvdata(dev);
+	struct fb_info *fbi = mx3fb->fbi;
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	struct dma_chan *chan;
+
+	chan = &mx3_fbi->idmac_channel->dma_chan;
+	release_fbi(fbi);
+
+	dma_release_channel(chan);
+	dmaengine_put();
+
+	iounmap(mx3fb->reg_base);
+	kfree(mx3fb);
+	return 0;
+}
+
+static struct platform_driver mx3fb_driver = {
+	.driver = {
+		.name = MX3FB_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = mx3fb_probe,
+	.remove = mx3fb_remove,
+	.suspend = mx3fb_suspend,
+	.resume = mx3fb_resume,
+};
+
+/*
+ * Parse user specified options (`video=mx3fb:')
+ * example:
+ * 	video=mx3fb:bpp=16
+ */
+static int __init mx3fb_setup(void)
+{
+#ifndef MODULE
+	char *opt, *options = NULL;
+
+	if (fb_get_options("mx3fb", &options))
+		return -ENODEV;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+		if (!strncmp(opt, "bpp=", 4))
+			default_bpp = simple_strtoul(opt + 4, NULL, 0);
+		else
+			fb_mode = opt;
+	}
+#endif
+
+	return 0;
+}
+
+static int __init mx3fb_init(void)
+{
+	int ret = mx3fb_setup();
+
+	if (ret < 0)
+		return ret;
+
+	ret = platform_driver_register(&mx3fb_driver);
+	return ret;
+}
+
+static void __exit mx3fb_exit(void)
+{
+	platform_driver_unregister(&mx3fb_driver);
+}
+
+module_init(mx3fb_init);
+module_exit(mx3fb_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MX3 framebuffer driver");
+MODULE_ALIAS("platform:" MX3FB_NAME);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
new file mode 100644
index 000000000000..accf48a2cce4
--- /dev/null
+++ b/drivers/video/fbdev/mxsfb.c
@@ -0,0 +1,960 @@
+/*
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ *
+ * This code is based on:
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define DRIVER_NAME "mxsfb"
+
+/**
+ * @file
+ * @brief LCDIF driver for i.MX23 and i.MX28
+ *
+ * The LCDIF support four modes of operation
+ * - MPU interface (to drive smart displays) -> not supported yet
+ * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
+ * - Dotclock interface (to drive LC displays with RGB data and sync signals)
+ * - DVI (to drive ITU-R BT656)  -> not supported yet
+ *
+ * This driver depends on a correct setup of the pins used for this purpose
+ * (platform specific).
+ *
+ * For the developer: Don't forget to set the data bus width to the display
+ * in the imx_fb_videomode structure. You will else end up with ugly colours.
+ * If you fight against jitter you can vary the clock delay. This is a feature
+ * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
+ * the required value in the imx_fb_videomode structure.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <linux/regulator/consumer.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#define REG_SET	4
+#define REG_CLR	8
+
+#define LCDC_CTRL			0x00
+#define LCDC_CTRL1			0x10
+#define LCDC_V4_CTRL2			0x20
+#define LCDC_V3_TRANSFER_COUNT		0x20
+#define LCDC_V4_TRANSFER_COUNT		0x30
+#define LCDC_V4_CUR_BUF			0x40
+#define LCDC_V4_NEXT_BUF		0x50
+#define LCDC_V3_CUR_BUF			0x30
+#define LCDC_V3_NEXT_BUF		0x40
+#define LCDC_TIMING			0x60
+#define LCDC_VDCTRL0			0x70
+#define LCDC_VDCTRL1			0x80
+#define LCDC_VDCTRL2			0x90
+#define LCDC_VDCTRL3			0xa0
+#define LCDC_VDCTRL4			0xb0
+#define LCDC_DVICTRL0			0xc0
+#define LCDC_DVICTRL1			0xd0
+#define LCDC_DVICTRL2			0xe0
+#define LCDC_DVICTRL3			0xf0
+#define LCDC_DVICTRL4			0x100
+#define LCDC_V4_DATA			0x180
+#define LCDC_V3_DATA			0x1b0
+#define LCDC_V4_DEBUG0			0x1d0
+#define LCDC_V3_DEBUG0			0x1f0
+
+#define CTRL_SFTRST			(1 << 31)
+#define CTRL_CLKGATE			(1 << 30)
+#define CTRL_BYPASS_COUNT		(1 << 19)
+#define CTRL_VSYNC_MODE			(1 << 18)
+#define CTRL_DOTCLK_MODE		(1 << 17)
+#define CTRL_DATA_SELECT		(1 << 16)
+#define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
+#define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
+#define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
+#define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
+#define CTRL_MASTER			(1 << 5)
+#define CTRL_DF16			(1 << 3)
+#define CTRL_DF18			(1 << 2)
+#define CTRL_DF24			(1 << 1)
+#define CTRL_RUN			(1 << 0)
+
+#define CTRL1_FIFO_CLEAR		(1 << 21)
+#define CTRL1_SET_BYTE_PACKAGING(x)	(((x) & 0xf) << 16)
+#define CTRL1_GET_BYTE_PACKAGING(x)	(((x) >> 16) & 0xf)
+
+#define TRANSFER_COUNT_SET_VCOUNT(x)	(((x) & 0xffff) << 16)
+#define TRANSFER_COUNT_GET_VCOUNT(x)	(((x) >> 16) & 0xffff)
+#define TRANSFER_COUNT_SET_HCOUNT(x)	((x) & 0xffff)
+#define TRANSFER_COUNT_GET_HCOUNT(x)	((x) & 0xffff)
+
+
+#define VDCTRL0_ENABLE_PRESENT		(1 << 28)
+#define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
+#define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
+#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
+#define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
+#define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
+#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
+#define VDCTRL0_HALF_LINE		(1 << 19)
+#define VDCTRL0_HALF_LINE_MODE		(1 << 18)
+#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+
+#define VDCTRL2_SET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
+#define VDCTRL2_GET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
+
+#define VDCTRL3_MUX_SYNC_SIGNALS	(1 << 29)
+#define VDCTRL3_VSYNC_ONLY		(1 << 28)
+#define SET_HOR_WAIT_CNT(x)		(((x) & 0xfff) << 16)
+#define GET_HOR_WAIT_CNT(x)		(((x) >> 16) & 0xfff)
+#define SET_VERT_WAIT_CNT(x)		((x) & 0xffff)
+#define GET_VERT_WAIT_CNT(x)		((x) & 0xffff)
+
+#define VDCTRL4_SET_DOTCLK_DLY(x)	(((x) & 0x7) << 29) /* v4 only */
+#define VDCTRL4_GET_DOTCLK_DLY(x)	(((x) >> 29) & 0x7) /* v4 only */
+#define VDCTRL4_SYNC_SIGNALS_ON		(1 << 18)
+#define SET_DOTCLK_H_VALID_DATA_CNT(x)	((x) & 0x3ffff)
+
+#define DEBUG0_HSYNC			(1 < 26)
+#define DEBUG0_VSYNC			(1 < 25)
+
+#define MIN_XRES			120
+#define MIN_YRES			120
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define TRANSP 3
+
+#define STMLCDIF_8BIT  1 /** pixel data bus to the display is of 8 bit width */
+#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
+#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
+#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
+
+#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
+#define MXSFB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* negtive edge sampling */
+
+enum mxsfb_devtype {
+	MXSFB_V3,
+	MXSFB_V4,
+};
+
+/* CPU dependent register offsets */
+struct mxsfb_devdata {
+	unsigned transfer_count;
+	unsigned cur_buf;
+	unsigned next_buf;
+	unsigned debug0;
+	unsigned hs_wdth_mask;
+	unsigned hs_wdth_shift;
+	unsigned ipversion;
+};
+
+struct mxsfb_info {
+	struct fb_info fb_info;
+	struct platform_device *pdev;
+	struct clk *clk;
+	void __iomem *base;	/* registers */
+	unsigned allocated_size;
+	int enabled;
+	unsigned ld_intf_width;
+	unsigned dotclk_delay;
+	const struct mxsfb_devdata *devdata;
+	u32 sync;
+	struct regulator *reg_lcd;
+};
+
+#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
+#define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
+
+static const struct mxsfb_devdata mxsfb_devdata[] = {
+	[MXSFB_V3] = {
+		.transfer_count = LCDC_V3_TRANSFER_COUNT,
+		.cur_buf = LCDC_V3_CUR_BUF,
+		.next_buf = LCDC_V3_NEXT_BUF,
+		.debug0 = LCDC_V3_DEBUG0,
+		.hs_wdth_mask = 0xff,
+		.hs_wdth_shift = 24,
+		.ipversion = 3,
+	},
+	[MXSFB_V4] = {
+		.transfer_count = LCDC_V4_TRANSFER_COUNT,
+		.cur_buf = LCDC_V4_CUR_BUF,
+		.next_buf = LCDC_V4_NEXT_BUF,
+		.debug0 = LCDC_V4_DEBUG0,
+		.hs_wdth_mask = 0x3fff,
+		.hs_wdth_shift = 18,
+		.ipversion = 4,
+	},
+};
+
+#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
+
+/* mask and shift depends on architecture */
+static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
+{
+	return (val & host->devdata->hs_wdth_mask) <<
+		host->devdata->hs_wdth_shift;
+}
+
+static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
+{
+	return (val >> host->devdata->hs_wdth_shift) &
+		host->devdata->hs_wdth_mask;
+}
+
+static const struct fb_bitfield def_rgb565[] = {
+	[RED] = {
+		.offset = 11,
+		.length = 5,
+	},
+	[GREEN] = {
+		.offset = 5,
+		.length = 6,
+	},
+	[BLUE] = {
+		.offset = 0,
+		.length = 5,
+	},
+	[TRANSP] = {	/* no support for transparency */
+		.length = 0,
+	}
+};
+
+static const struct fb_bitfield def_rgb888[] = {
+	[RED] = {
+		.offset = 16,
+		.length = 8,
+	},
+	[GREEN] = {
+		.offset = 8,
+		.length = 8,
+	},
+	[BLUE] = {
+		.offset = 0,
+		.length = 8,
+	},
+	[TRANSP] = {	/* no support for transparency */
+		.length = 0,
+	}
+};
+
+static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int mxsfb_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	const struct fb_bitfield *rgb = NULL;
+
+	if (var->xres < MIN_XRES)
+		var->xres = MIN_XRES;
+	if (var->yres < MIN_YRES)
+		var->yres = MIN_YRES;
+
+	var->xres_virtual = var->xres;
+
+	var->yres_virtual = var->yres;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		/* always expect RGB 565 */
+		rgb = def_rgb565;
+		break;
+	case 32:
+		switch (host->ld_intf_width) {
+		case STMLCDIF_8BIT:
+			pr_debug("Unsupported LCD bus width mapping\n");
+			break;
+		case STMLCDIF_16BIT:
+		case STMLCDIF_18BIT:
+		case STMLCDIF_24BIT:
+			/* real 24 bit */
+			rgb = def_rgb888;
+			break;
+		}
+		break;
+	default:
+		pr_err("Unsupported colour depth: %u\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/*
+	 * Copy the RGB parameters for this display
+	 * from the machine specific parameters.
+	 */
+	var->red    = rgb[RED];
+	var->green  = rgb[GREEN];
+	var->blue   = rgb[BLUE];
+	var->transp = rgb[TRANSP];
+
+	return 0;
+}
+
+static void mxsfb_enable_controller(struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	u32 reg;
+	int ret;
+
+	dev_dbg(&host->pdev->dev, "%s\n", __func__);
+
+	if (host->reg_lcd) {
+		ret = regulator_enable(host->reg_lcd);
+		if (ret) {
+			dev_err(&host->pdev->dev,
+				"lcd regulator enable failed:	%d\n", ret);
+			return;
+		}
+	}
+
+	clk_prepare_enable(host->clk);
+	clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
+
+	/* if it was disabled, re-enable the mode again */
+	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
+
+	/* enable the SYNC signals first, then the DMA engine */
+	reg = readl(host->base + LCDC_VDCTRL4);
+	reg |= VDCTRL4_SYNC_SIGNALS_ON;
+	writel(reg, host->base + LCDC_VDCTRL4);
+
+	writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
+
+	host->enabled = 1;
+}
+
+static void mxsfb_disable_controller(struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	unsigned loop;
+	u32 reg;
+	int ret;
+
+	dev_dbg(&host->pdev->dev, "%s\n", __func__);
+
+	/*
+	 * Even if we disable the controller here, it will still continue
+	 * until its FIFOs are running out of data
+	 */
+	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR);
+
+	loop = 1000;
+	while (loop) {
+		reg = readl(host->base + LCDC_CTRL);
+		if (!(reg & CTRL_RUN))
+			break;
+		loop--;
+	}
+
+	reg = readl(host->base + LCDC_VDCTRL4);
+	writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
+
+	clk_disable_unprepare(host->clk);
+
+	host->enabled = 0;
+
+	if (host->reg_lcd) {
+		ret = regulator_disable(host->reg_lcd);
+		if (ret)
+			dev_err(&host->pdev->dev,
+				"lcd regulator disable failed: %d\n", ret);
+	}
+}
+
+static int mxsfb_set_par(struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	u32 ctrl, vdctrl0, vdctrl4;
+	int line_size, fb_size;
+	int reenable = 0;
+
+	line_size =  fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
+	fb_size = fb_info->var.yres_virtual * line_size;
+
+	if (fb_size > fb_info->fix.smem_len)
+		return -ENOMEM;
+
+	fb_info->fix.line_length = line_size;
+
+	/*
+	 * It seems, you can't re-program the controller if it is still running.
+	 * This may lead into shifted pictures (FIFO issue?).
+	 * So, first stop the controller and drain its FIFOs
+	 */
+	if (host->enabled) {
+		reenable = 1;
+		mxsfb_disable_controller(fb_info);
+	}
+
+	/* clear the FIFOs */
+	writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
+
+	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
+		CTRL_SET_BUS_WIDTH(host->ld_intf_width);
+
+	switch (fb_info->var.bits_per_pixel) {
+	case 16:
+		dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
+		ctrl |= CTRL_SET_WORD_LENGTH(0);
+		writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
+		break;
+	case 32:
+		dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
+		ctrl |= CTRL_SET_WORD_LENGTH(3);
+		switch (host->ld_intf_width) {
+		case STMLCDIF_8BIT:
+			dev_err(&host->pdev->dev,
+					"Unsupported LCD bus width mapping\n");
+			return -EINVAL;
+		case STMLCDIF_16BIT:
+		case STMLCDIF_18BIT:
+		case STMLCDIF_24BIT:
+			/* real 24 bit */
+			break;
+		}
+		/* do not use packed pixels = one pixel per word instead */
+		writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
+		break;
+	default:
+		dev_err(&host->pdev->dev, "Unhandled color depth of %u\n",
+				fb_info->var.bits_per_pixel);
+		return -EINVAL;
+	}
+
+	writel(ctrl, host->base + LCDC_CTRL);
+
+	writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
+			TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
+			host->base + host->devdata->transfer_count);
+
+	vdctrl0 = VDCTRL0_ENABLE_PRESENT |	/* always in DOTCLOCK mode */
+		VDCTRL0_VSYNC_PERIOD_UNIT |
+		VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
+		VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
+	if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
+	if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
+	if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
+		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
+	if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT)
+		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
+
+	writel(vdctrl0, host->base + LCDC_VDCTRL0);
+
+	/* frame length in lines */
+	writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
+		fb_info->var.lower_margin + fb_info->var.yres,
+		host->base + LCDC_VDCTRL1);
+
+	/* line length in units of clocks or pixels */
+	writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
+		VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
+		fb_info->var.hsync_len + fb_info->var.right_margin +
+		fb_info->var.xres),
+		host->base + LCDC_VDCTRL2);
+
+	writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
+		fb_info->var.hsync_len) |
+		SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
+			fb_info->var.vsync_len),
+		host->base + LCDC_VDCTRL3);
+
+	vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
+	if (mxsfb_is_v4(host))
+		vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
+	writel(vdctrl4, host->base + LCDC_VDCTRL4);
+
+	writel(fb_info->fix.smem_start +
+			fb_info->fix.line_length * fb_info->var.yoffset,
+			host->base + host->devdata->next_buf);
+
+	if (reenable)
+		mxsfb_enable_controller(fb_info);
+
+	return 0;
+}
+
+static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		u_int transp, struct fb_info *fb_info)
+{
+	unsigned int val;
+	int ret = -EINVAL;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (fb_info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	switch (fb_info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 12 or 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = fb_info->pseudo_palette;
+
+			val  = chan_to_field(red, &fb_info->var.red);
+			val |= chan_to_field(green, &fb_info->var.green);
+			val |= chan_to_field(blue, &fb_info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		break;
+	}
+
+	return ret;
+}
+
+static int mxsfb_blank(int blank, struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		if (host->enabled)
+			mxsfb_disable_controller(fb_info);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		if (!host->enabled)
+			mxsfb_enable_controller(fb_info);
+		break;
+	}
+	return 0;
+}
+
+static int mxsfb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	unsigned offset;
+
+	if (var->xoffset != 0)
+		return -EINVAL;
+
+	offset = fb_info->fix.line_length * var->yoffset;
+
+	/* update on next VSYNC */
+	writel(fb_info->fix.smem_start + offset,
+			host->base + host->devdata->next_buf);
+
+	return 0;
+}
+
+static struct fb_ops mxsfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = mxsfb_check_var,
+	.fb_set_par = mxsfb_set_par,
+	.fb_setcolreg = mxsfb_setcolreg,
+	.fb_blank = mxsfb_blank,
+	.fb_pan_display = mxsfb_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+};
+
+static int mxsfb_restore_mode(struct mxsfb_info *host,
+			struct fb_videomode *vmode)
+{
+	struct fb_info *fb_info = &host->fb_info;
+	unsigned line_count;
+	unsigned period;
+	unsigned long pa, fbsize;
+	int bits_per_pixel, ofs;
+	u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
+
+	/* Only restore the mode when the controller is running */
+	ctrl = readl(host->base + LCDC_CTRL);
+	if (!(ctrl & CTRL_RUN))
+		return -EINVAL;
+
+	vdctrl0 = readl(host->base + LCDC_VDCTRL0);
+	vdctrl2 = readl(host->base + LCDC_VDCTRL2);
+	vdctrl3 = readl(host->base + LCDC_VDCTRL3);
+	vdctrl4 = readl(host->base + LCDC_VDCTRL4);
+
+	transfer_count = readl(host->base + host->devdata->transfer_count);
+
+	vmode->xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+	vmode->yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
+
+	switch (CTRL_GET_WORD_LENGTH(ctrl)) {
+	case 0:
+		bits_per_pixel = 16;
+		break;
+	case 3:
+		bits_per_pixel = 32;
+		break;
+	case 1:
+	default:
+		return -EINVAL;
+	}
+
+	fb_info->var.bits_per_pixel = bits_per_pixel;
+
+	vmode->pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U);
+	vmode->hsync_len = get_hsync_pulse_width(host, vdctrl2);
+	vmode->left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode->hsync_len;
+	vmode->right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) -
+		vmode->hsync_len - vmode->left_margin - vmode->xres;
+	vmode->vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
+	period = readl(host->base + LCDC_VDCTRL1);
+	vmode->upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode->vsync_len;
+	vmode->lower_margin = period - vmode->vsync_len -
+		vmode->upper_margin - vmode->yres;
+
+	vmode->vmode = FB_VMODE_NONINTERLACED;
+
+	vmode->sync = 0;
+	if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
+		vmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
+		vmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+	pr_debug("Reconstructed video mode:\n");
+	pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
+		vmode->xres, vmode->yres, vmode->hsync_len, vmode->left_margin,
+		vmode->right_margin, vmode->vsync_len, vmode->upper_margin,
+		vmode->lower_margin);
+	pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode->pixclock));
+
+	host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
+	host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
+
+	fb_info->fix.line_length = vmode->xres * (bits_per_pixel >> 3);
+
+	pa = readl(host->base + host->devdata->cur_buf);
+	fbsize = fb_info->fix.line_length * vmode->yres;
+	if (pa < fb_info->fix.smem_start)
+		return -EINVAL;
+	if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
+		return -EINVAL;
+	ofs = pa - fb_info->fix.smem_start;
+	if (ofs) {
+		memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
+		writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
+	}
+
+	line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
+	fb_info->fix.ypanstep = 1;
+
+	clk_prepare_enable(host->clk);
+	host->enabled = 1;
+
+	return 0;
+}
+
+static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host,
+				struct fb_videomode *vmode)
+{
+	struct fb_info *fb_info = &host->fb_info;
+	struct fb_var_screeninfo *var = &fb_info->var;
+	struct device *dev = &host->pdev->dev;
+	struct device_node *np = host->pdev->dev.of_node;
+	struct device_node *display_np;
+	struct videomode vm;
+	u32 width;
+	int ret;
+
+	display_np = of_parse_phandle(np, "display", 0);
+	if (!display_np) {
+		dev_err(dev, "failed to find display phandle\n");
+		return -ENOENT;
+	}
+
+	ret = of_property_read_u32(display_np, "bus-width", &width);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bus-width\n");
+		goto put_display_node;
+	}
+
+	switch (width) {
+	case 8:
+		host->ld_intf_width = STMLCDIF_8BIT;
+		break;
+	case 16:
+		host->ld_intf_width = STMLCDIF_16BIT;
+		break;
+	case 18:
+		host->ld_intf_width = STMLCDIF_18BIT;
+		break;
+	case 24:
+		host->ld_intf_width = STMLCDIF_24BIT;
+		break;
+	default:
+		dev_err(dev, "invalid bus-width value\n");
+		ret = -EINVAL;
+		goto put_display_node;
+	}
+
+	ret = of_property_read_u32(display_np, "bits-per-pixel",
+				   &var->bits_per_pixel);
+	if (ret < 0) {
+		dev_err(dev, "failed to get property bits-per-pixel\n");
+		goto put_display_node;
+	}
+
+	ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE);
+	if (ret) {
+		dev_err(dev, "failed to get videomode from DT\n");
+		goto put_display_node;
+	}
+
+	ret = fb_videomode_from_videomode(&vm, vmode);
+	if (ret < 0)
+		goto put_display_node;
+
+	if (vm.flags & DISPLAY_FLAGS_DE_HIGH)
+		host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
+	if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+		host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT;
+
+put_display_node:
+	of_node_put(display_np);
+	return ret;
+}
+
+static int mxsfb_init_fbinfo(struct mxsfb_info *host,
+			struct fb_videomode *vmode)
+{
+	int ret;
+	struct fb_info *fb_info = &host->fb_info;
+	struct fb_var_screeninfo *var = &fb_info->var;
+	dma_addr_t fb_phys;
+	void *fb_virt;
+	unsigned fb_size;
+
+	fb_info->fbops = &mxsfb_ops;
+	fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
+	strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id));
+	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+	fb_info->fix.ypanstep = 1;
+	fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
+	fb_info->fix.accel = FB_ACCEL_NONE;
+
+	ret = mxsfb_init_fbinfo_dt(host, vmode);
+	if (ret)
+		return ret;
+
+	var->nonstd = 0;
+	var->activate = FB_ACTIVATE_NOW;
+	var->accel_flags = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
+
+	/* Memory allocation for framebuffer */
+	fb_size = SZ_2M;
+	fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
+	if (!fb_virt)
+		return -ENOMEM;
+
+	fb_phys = virt_to_phys(fb_virt);
+
+	fb_info->fix.smem_start = fb_phys;
+	fb_info->screen_base = fb_virt;
+	fb_info->screen_size = fb_info->fix.smem_len = fb_size;
+
+	if (mxsfb_restore_mode(host, vmode))
+		memset(fb_virt, 0, fb_size);
+
+	return 0;
+}
+
+static void mxsfb_free_videomem(struct mxsfb_info *host)
+{
+	struct fb_info *fb_info = &host->fb_info;
+
+	free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
+}
+
+static struct platform_device_id mxsfb_devtype[] = {
+	{
+		.name = "imx23-fb",
+		.driver_data = MXSFB_V3,
+	}, {
+		.name = "imx28-fb",
+		.driver_data = MXSFB_V4,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
+
+static const struct of_device_id mxsfb_dt_ids[] = {
+	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
+	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
+
+static int mxsfb_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+			of_match_device(mxsfb_dt_ids, &pdev->dev);
+	struct resource *res;
+	struct mxsfb_info *host;
+	struct fb_info *fb_info;
+	struct fb_videomode *mode;
+	int ret;
+
+	if (of_id)
+		pdev->id_entry = of_id->data;
+
+	fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
+	if (!fb_info) {
+		dev_err(&pdev->dev, "Failed to allocate fbdev\n");
+		return -ENOMEM;
+	}
+
+	mode = devm_kzalloc(&pdev->dev, sizeof(struct fb_videomode),
+			GFP_KERNEL);
+	if (mode == NULL)
+		return -ENOMEM;
+
+	host = to_imxfb_host(fb_info);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->base)) {
+		ret = PTR_ERR(host->base);
+		goto fb_release;
+	}
+
+	host->pdev = pdev;
+	platform_set_drvdata(pdev, host);
+
+	host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
+
+	host->clk = devm_clk_get(&host->pdev->dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		goto fb_release;
+	}
+
+	host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");
+	if (IS_ERR(host->reg_lcd))
+		host->reg_lcd = NULL;
+
+	fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
+					       GFP_KERNEL);
+	if (!fb_info->pseudo_palette) {
+		ret = -ENOMEM;
+		goto fb_release;
+	}
+
+	ret = mxsfb_init_fbinfo(host, mode);
+	if (ret != 0)
+		goto fb_release;
+
+	fb_videomode_to_var(&fb_info->var, mode);
+
+	/* init the color fields */
+	mxsfb_check_var(&fb_info->var, fb_info);
+
+	platform_set_drvdata(pdev, fb_info);
+
+	ret = register_framebuffer(fb_info);
+	if (ret != 0) {
+		dev_err(&pdev->dev,"Failed to register framebuffer\n");
+		goto fb_destroy;
+	}
+
+	if (!host->enabled) {
+		writel(0, host->base + LCDC_CTRL);
+		mxsfb_set_par(fb_info);
+		mxsfb_enable_controller(fb_info);
+	}
+
+	dev_info(&pdev->dev, "initialized\n");
+
+	return 0;
+
+fb_destroy:
+	if (host->enabled)
+		clk_disable_unprepare(host->clk);
+fb_release:
+	framebuffer_release(fb_info);
+
+	return ret;
+}
+
+static int mxsfb_remove(struct platform_device *pdev)
+{
+	struct fb_info *fb_info = platform_get_drvdata(pdev);
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+
+	if (host->enabled)
+		mxsfb_disable_controller(fb_info);
+
+	unregister_framebuffer(fb_info);
+	mxsfb_free_videomem(host);
+
+	framebuffer_release(fb_info);
+
+	return 0;
+}
+
+static void mxsfb_shutdown(struct platform_device *pdev)
+{
+	struct fb_info *fb_info = platform_get_drvdata(pdev);
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+
+	/*
+	 * Force stop the LCD controller as keeping it running during reboot
+	 * might interfere with the BootROM's boot mode pads sampling.
+	 */
+	writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
+}
+
+static struct platform_driver mxsfb_driver = {
+	.probe = mxsfb_probe,
+	.remove = mxsfb_remove,
+	.shutdown = mxsfb_shutdown,
+	.id_table = mxsfb_devtype,
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .of_match_table = mxsfb_dt_ids,
+	},
+};
+
+module_platform_driver(mxsfb_driver);
+
+MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/n411.c b/drivers/video/fbdev/n411.c
new file mode 100644
index 000000000000..935830fea7b6
--- /dev/null
+++ b/drivers/video/fbdev/n411.c
@@ -0,0 +1,202 @@
+/*
+ * linux/drivers/video/n411.c -- Platform device for N411 EPD kit
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver is written to be used with the Hecuba display controller
+ * board, and tested with the EInk 800x600 display in 1 bit mode.
+ * The interface between Hecuba and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 6 lines for control.
+ * Only 4 of the controls are actually used here but 6 for future use.
+ * The driver requires the IO addresses for data and control GPIO at
+ * load time. It is also possible to use this display with a standard
+ * PC parallel port.
+ *
+ * General notes:
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+#include <linux/irq.h>
+
+#include <video/hecubafb.h>
+
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned int nosplash;
+static unsigned char ctl;
+
+static void n411_set_ctl(struct hecubafb_par *par, unsigned char bit, unsigned
+							char state)
+{
+	switch (bit) {
+	case HCB_CD_BIT:
+		if (state)
+			ctl &= ~(HCB_CD_BIT);
+		else
+			ctl |= HCB_CD_BIT;
+		break;
+	case HCB_DS_BIT:
+		if (state)
+			ctl &= ~(HCB_DS_BIT);
+		else
+			ctl |= HCB_DS_BIT;
+		break;
+	}
+	outb(ctl, cio_addr);
+}
+
+static unsigned char n411_get_ctl(struct hecubafb_par *par)
+{
+	return inb(c2io_addr);
+}
+
+static void n411_set_data(struct hecubafb_par *par, unsigned char value)
+{
+	outb(value, dio_addr);
+}
+
+static void n411_wait_for_ack(struct hecubafb_par *par, int clear)
+{
+	int timeout;
+	unsigned char tmp;
+
+	timeout = 500;
+	do {
+		tmp = n411_get_ctl(par);
+		if ((tmp & HCB_ACK_BIT) && (!clear))
+			return;
+		else if (!(tmp & HCB_ACK_BIT) && (clear))
+			return;
+		udelay(1);
+	} while (timeout--);
+	printk(KERN_ERR "timed out waiting for ack\n");
+}
+
+static int n411_init_control(struct hecubafb_par *par)
+{
+	unsigned char tmp;
+	/* for init, we want the following setup to be set:
+	WUP = lo
+	ACK = hi
+	DS = hi
+	RW = hi
+	CD = lo
+	*/
+
+	/* write WUP to lo, DS to hi, RW to hi, CD to lo */
+	ctl = HCB_WUP_BIT | HCB_RW_BIT | HCB_CD_BIT ;
+	n411_set_ctl(par, HCB_DS_BIT, 1);
+
+	/* check ACK is not lo */
+	tmp = n411_get_ctl(par);
+	if (tmp & HCB_ACK_BIT) {
+		printk(KERN_ERR "Fail because ACK is already low\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+
+static int n411_init_board(struct hecubafb_par *par)
+{
+	int retval;
+
+	retval = n411_init_control(par);
+	if (retval)
+		return retval;
+
+	par->send_command(par, APOLLO_INIT_DISPLAY);
+	par->send_data(par, 0x81);
+
+	/* have to wait while display resets */
+	udelay(1000);
+
+	/* if we were told to splash the screen, we just clear it */
+	if (!nosplash) {
+		par->send_command(par, APOLLO_ERASE_DISPLAY);
+		par->send_data(par, splashval);
+	}
+
+	return 0;
+}
+
+static struct hecuba_board n411_board = {
+	.owner			= THIS_MODULE,
+	.init			= n411_init_board,
+	.set_ctl		= n411_set_ctl,
+	.set_data		= n411_set_data,
+	.wait_for_ack		= n411_wait_for_ack,
+};
+
+static struct platform_device *n411_device;
+static int __init n411_init(void)
+{
+	int ret;
+	if (!dio_addr || !cio_addr || !c2io_addr) {
+		printk(KERN_WARNING "no IO addresses supplied\n");
+		return -EINVAL;
+	}
+
+	/* request our platform independent driver */
+	request_module("hecubafb");
+
+	n411_device = platform_device_alloc("hecubafb", -1);
+	if (!n411_device)
+		return -ENOMEM;
+
+	platform_device_add_data(n411_device, &n411_board, sizeof(n411_board));
+
+	/* this _add binds hecubafb to n411. hecubafb refcounts n411 */
+	ret = platform_device_add(n411_device);
+
+	if (ret)
+		platform_device_put(n411_device);
+
+	return ret;
+
+}
+
+static void __exit n411_exit(void)
+{
+	platform_device_unregister(n411_device);
+}
+
+module_init(n411_init);
+module_exit(n411_exit);
+
+module_param(nosplash, uint, 0);
+MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
+module_param(dio_addr, ulong, 0);
+MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
+module_param(cio_addr, ulong, 0);
+MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
+module_param(c2io_addr, ulong, 0);
+MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
+module_param(splashval, ulong, 0);
+MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
+
+MODULE_DESCRIPTION("board driver for n411 hecuba/apollo epd kit");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/neofb.c b/drivers/video/fbdev/neofb.c
new file mode 100644
index 000000000000..44f99a60bb9b
--- /dev/null
+++ b/drivers/video/fbdev/neofb.c
@@ -0,0 +1,2247 @@
+/*
+ * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
+ *
+ * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
+ *
+ *
+ * Card specific code is based on XFree86's neomagic driver.
+ * Framebuffer framework code is based on code of cyber2000fb.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ *
+ * 0.4.1
+ *  - Cosmetic changes (dok)
+ *
+ * 0.4
+ *  - Toshiba Libretto support, allow modes larger than LCD size if
+ *    LCD is disabled, keep BIOS settings if internal/external display
+ *    haven't been enabled explicitly
+ *                          (Thomas J. Moore <dark@mama.indstate.edu>)
+ *
+ * 0.3.3
+ *  - Porting over to new fbdev api. (jsimmons)
+ *  
+ * 0.3.2
+ *  - got rid of all floating point (dok) 
+ *
+ * 0.3.1
+ *  - added module license (dok)
+ *
+ * 0.3
+ *  - hardware accelerated clear and move for 2200 and above (dok)
+ *  - maximum allowed dotclock is handled now (dok)
+ *
+ * 0.2.1
+ *  - correct panning after X usage (dok)
+ *  - added module and kernel parameters (dok)
+ *  - no stretching if external display is enabled (dok)
+ *
+ * 0.2
+ *  - initial version (dok)
+ *
+ *
+ * TODO
+ * - ioctl for internal/external switching
+ * - blanking
+ * - 32bit depth support, maybe impossible
+ * - disable pan-on-sync, need specs
+ *
+ * BUGS
+ * - white margin on bootup like with tdfxfb (colormap problem?)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#ifdef CONFIG_TOSHIBA
+#include <linux/toshiba.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/vga.h>
+#include <video/neomagic.h>
+
+#define NEOFB_VERSION "0.4.2"
+
+/* --------------------------------------------------------------------- */
+
+static bool internal;
+static bool external;
+static bool libretto;
+static bool nostretch;
+static bool nopciburst;
+static char *mode_option = NULL;
+
+#ifdef MODULE
+
+MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@convergence.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
+module_param(internal, bool, 0);
+MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
+module_param(external, bool, 0);
+MODULE_PARM_DESC(external, "Enable output on external CRT.");
+module_param(libretto, bool, 0);
+MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD.");
+module_param(nostretch, bool, 0);
+MODULE_PARM_DESC(nostretch,
+		 "Disable stretching of modes smaller than LCD.");
+module_param(nopciburst, bool, 0);
+MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
+
+#endif
+
+
+/* --------------------------------------------------------------------- */
+
+static biosMode bios8[] = {
+	{320, 240, 0x40},
+	{300, 400, 0x42},
+	{640, 400, 0x20},
+	{640, 480, 0x21},
+	{800, 600, 0x23},
+	{1024, 768, 0x25},
+};
+
+static biosMode bios16[] = {
+	{320, 200, 0x2e},
+	{320, 240, 0x41},
+	{300, 400, 0x43},
+	{640, 480, 0x31},
+	{800, 600, 0x34},
+	{1024, 768, 0x37},
+};
+
+static biosMode bios24[] = {
+	{640, 480, 0x32},
+	{800, 600, 0x35},
+	{1024, 768, 0x38}
+};
+
+#ifdef NO_32BIT_SUPPORT_YET
+/* FIXME: guessed values, wrong */
+static biosMode bios32[] = {
+	{640, 480, 0x33},
+	{800, 600, 0x36},
+	{1024, 768, 0x39}
+};
+#endif
+
+static inline void write_le32(int regindex, u32 val, const struct neofb_par *par)
+{
+	writel(val, par->neo2200 + par->cursorOff + regindex);
+}
+
+static int neoFindMode(int xres, int yres, int depth)
+{
+	int xres_s;
+	int i, size;
+	biosMode *mode;
+
+	switch (depth) {
+	case 8:
+		size = ARRAY_SIZE(bios8);
+		mode = bios8;
+		break;
+	case 16:
+		size = ARRAY_SIZE(bios16);
+		mode = bios16;
+		break;
+	case 24:
+		size = ARRAY_SIZE(bios24);
+		mode = bios24;
+		break;
+#ifdef NO_32BIT_SUPPORT_YET
+	case 32:
+		size = ARRAY_SIZE(bios32);
+		mode = bios32;
+		break;
+#endif
+	default:
+		return 0;
+	}
+
+	for (i = 0; i < size; i++) {
+		if (xres <= mode[i].x_res) {
+			xres_s = mode[i].x_res;
+			for (; i < size; i++) {
+				if (mode[i].x_res != xres_s)
+					return mode[i - 1].mode;
+				if (yres <= mode[i].y_res)
+					return mode[i].mode;
+			}
+		}
+	}
+	return mode[size - 1].mode;
+}
+
+/*
+ * neoCalcVCLK --
+ *
+ * Determine the closest clock frequency to the one requested.
+ */
+#define MAX_N 127
+#define MAX_D 31
+#define MAX_F 1
+
+static void neoCalcVCLK(const struct fb_info *info,
+			struct neofb_par *par, long freq)
+{
+	int n, d, f;
+	int n_best = 0, d_best = 0, f_best = 0;
+	long f_best_diff = 0x7ffff;
+
+	for (f = 0; f <= MAX_F; f++)
+		for (d = 0; d <= MAX_D; d++)
+			for (n = 0; n <= MAX_N; n++) {
+				long f_out;
+				long f_diff;
+
+				f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
+				f_diff = abs(f_out - freq);
+				if (f_diff <= f_best_diff) {
+					f_best_diff = f_diff;
+					n_best = n;
+					d_best = d;
+					f_best = f;
+				}
+				if (f_out > freq)
+					break;
+			}
+
+	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
+		/* NOT_DONE:  We are trying the full range of the 2200 clock.
+		   We should be able to try n up to 2047 */
+		par->VCLK3NumeratorLow = n_best;
+		par->VCLK3NumeratorHigh = (f_best << 7);
+	} else
+		par->VCLK3NumeratorLow = n_best | (f_best << 7);
+
+	par->VCLK3Denominator = d_best;
+
+#ifdef NEOFB_DEBUG
+	printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
+	       freq,
+	       par->VCLK3NumeratorLow,
+	       par->VCLK3NumeratorHigh,
+	       par->VCLK3Denominator, f_best_diff);
+#endif
+}
+
+/*
+ * vgaHWInit --
+ *      Handle the initialization, etc. of a screen.
+ *      Return FALSE on failure.
+ */
+
+static int vgaHWInit(const struct fb_var_screeninfo *var,
+		     struct neofb_par *par)
+{
+	int hsync_end = var->xres + var->right_margin + var->hsync_len;
+	int htotal = (hsync_end + var->left_margin) >> 3;
+	int vsync_start = var->yres + var->lower_margin;
+	int vsync_end = vsync_start + var->vsync_len;
+	int vtotal = vsync_end + var->upper_margin;
+
+	par->MiscOutReg = 0x23;
+
+	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+		par->MiscOutReg |= 0x40;
+
+	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+		par->MiscOutReg |= 0x80;
+
+	/*
+	 * Time Sequencer
+	 */
+	par->Sequencer[0] = 0x00;
+	par->Sequencer[1] = 0x01;
+	par->Sequencer[2] = 0x0F;
+	par->Sequencer[3] = 0x00;	/* Font select */
+	par->Sequencer[4] = 0x0E;	/* Misc */
+
+	/*
+	 * CRTC Controller
+	 */
+	par->CRTC[0] = htotal - 5;
+	par->CRTC[1] = (var->xres >> 3) - 1;
+	par->CRTC[2] = (var->xres >> 3) - 1;
+	par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
+	par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
+	par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
+	    | (((hsync_end >> 3)) & 0x1F);
+	par->CRTC[6] = (vtotal - 2) & 0xFF;
+	par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
+	    | (((var->yres - 1) & 0x100) >> 7)
+	    | ((vsync_start & 0x100) >> 6)
+	    | (((var->yres - 1) & 0x100) >> 5)
+	    | 0x10 | (((vtotal - 2) & 0x200) >> 4)
+	    | (((var->yres - 1) & 0x200) >> 3)
+	    | ((vsync_start & 0x200) >> 2);
+	par->CRTC[8] = 0x00;
+	par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
+
+	if (var->vmode & FB_VMODE_DOUBLE)
+		par->CRTC[9] |= 0x80;
+
+	par->CRTC[10] = 0x00;
+	par->CRTC[11] = 0x00;
+	par->CRTC[12] = 0x00;
+	par->CRTC[13] = 0x00;
+	par->CRTC[14] = 0x00;
+	par->CRTC[15] = 0x00;
+	par->CRTC[16] = vsync_start & 0xFF;
+	par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
+	par->CRTC[18] = (var->yres - 1) & 0xFF;
+	par->CRTC[19] = var->xres_virtual >> 4;
+	par->CRTC[20] = 0x00;
+	par->CRTC[21] = (var->yres - 1) & 0xFF;
+	par->CRTC[22] = (vtotal - 1) & 0xFF;
+	par->CRTC[23] = 0xC3;
+	par->CRTC[24] = 0xFF;
+
+	/*
+	 * are these unnecessary?
+	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
+	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
+	 */
+
+	/*
+	 * Graphics Display Controller
+	 */
+	par->Graphics[0] = 0x00;
+	par->Graphics[1] = 0x00;
+	par->Graphics[2] = 0x00;
+	par->Graphics[3] = 0x00;
+	par->Graphics[4] = 0x00;
+	par->Graphics[5] = 0x40;
+	par->Graphics[6] = 0x05;	/* only map 64k VGA memory !!!! */
+	par->Graphics[7] = 0x0F;
+	par->Graphics[8] = 0xFF;
+
+
+	par->Attribute[0] = 0x00;	/* standard colormap translation */
+	par->Attribute[1] = 0x01;
+	par->Attribute[2] = 0x02;
+	par->Attribute[3] = 0x03;
+	par->Attribute[4] = 0x04;
+	par->Attribute[5] = 0x05;
+	par->Attribute[6] = 0x06;
+	par->Attribute[7] = 0x07;
+	par->Attribute[8] = 0x08;
+	par->Attribute[9] = 0x09;
+	par->Attribute[10] = 0x0A;
+	par->Attribute[11] = 0x0B;
+	par->Attribute[12] = 0x0C;
+	par->Attribute[13] = 0x0D;
+	par->Attribute[14] = 0x0E;
+	par->Attribute[15] = 0x0F;
+	par->Attribute[16] = 0x41;
+	par->Attribute[17] = 0xFF;
+	par->Attribute[18] = 0x0F;
+	par->Attribute[19] = 0x00;
+	par->Attribute[20] = 0x00;
+	return 0;
+}
+
+static void vgaHWLock(struct vgastate *state)
+{
+	/* Protect CRTC[0-7] */
+	vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80);
+}
+
+static void vgaHWUnlock(void)
+{
+	/* Unprotect CRTC[0-7] */
+	vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80);
+}
+
+static void neoLock(struct vgastate *state)
+{
+	vga_wgfx(state->vgabase, 0x09, 0x00);
+	vgaHWLock(state);
+}
+
+static void neoUnlock(void)
+{
+	vgaHWUnlock();
+	vga_wgfx(NULL, 0x09, 0x26);
+}
+
+/*
+ * VGA Palette management
+ */
+static int paletteEnabled = 0;
+
+static inline void VGAenablePalette(void)
+{
+	vga_r(NULL, VGA_IS1_RC);
+	vga_w(NULL, VGA_ATT_W, 0x00);
+	paletteEnabled = 1;
+}
+
+static inline void VGAdisablePalette(void)
+{
+	vga_r(NULL, VGA_IS1_RC);
+	vga_w(NULL, VGA_ATT_W, 0x20);
+	paletteEnabled = 0;
+}
+
+static inline void VGAwATTR(u8 index, u8 value)
+{
+	if (paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+
+	vga_r(NULL, VGA_IS1_RC);
+	vga_wattr(NULL, index, value);
+}
+
+static void vgaHWProtect(int on)
+{
+	unsigned char tmp;
+
+	tmp = vga_rseq(NULL, 0x01);
+	if (on) {
+		/*
+		 * Turn off screen and disable sequencer.
+		 */
+		vga_wseq(NULL, 0x00, 0x01);		/* Synchronous Reset */
+		vga_wseq(NULL, 0x01, tmp | 0x20);	/* disable the display */
+
+		VGAenablePalette();
+	} else {
+		/*
+		 * Reenable sequencer, then turn on screen.
+		 */
+		vga_wseq(NULL, 0x01, tmp & ~0x20);	/* reenable display */
+		vga_wseq(NULL, 0x00, 0x03);		/* clear synchronousreset */
+
+		VGAdisablePalette();
+	}
+}
+
+static void vgaHWRestore(const struct fb_info *info,
+			 const struct neofb_par *par)
+{
+	int i;
+
+	vga_w(NULL, VGA_MIS_W, par->MiscOutReg);
+
+	for (i = 1; i < 5; i++)
+		vga_wseq(NULL, i, par->Sequencer[i]);
+
+	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
+	vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80);
+
+	for (i = 0; i < 25; i++)
+		vga_wcrt(NULL, i, par->CRTC[i]);
+
+	for (i = 0; i < 9; i++)
+		vga_wgfx(NULL, i, par->Graphics[i]);
+
+	VGAenablePalette();
+
+	for (i = 0; i < 21; i++)
+		VGAwATTR(i, par->Attribute[i]);
+
+	VGAdisablePalette();
+}
+
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Acceleration for Neo2200+
+ */
+static inline int neo2200_sync(struct fb_info *info)
+{
+	struct neofb_par *par = info->par;
+
+	while (readl(&par->neo2200->bltStat) & 1)
+		cpu_relax();
+	return 0;
+}
+
+static inline void neo2200_wait_fifo(struct fb_info *info,
+				     int requested_fifo_space)
+{
+	//  ndev->neo.waitfifo_calls++;
+	//  ndev->neo.waitfifo_sum += requested_fifo_space;
+
+	/* FIXME: does not work
+	   if (neo_fifo_space < requested_fifo_space)
+	   {
+	   neo_fifo_waitcycles++;
+
+	   while (1)
+	   {
+	   neo_fifo_space = (neo2200->bltStat >> 8);
+	   if (neo_fifo_space >= requested_fifo_space)
+	   break;
+	   }
+	   }
+	   else
+	   {
+	   neo_fifo_cache_hits++;
+	   }
+
+	   neo_fifo_space -= requested_fifo_space;
+	 */
+
+	neo2200_sync(info);
+}
+
+static inline void neo2200_accel_init(struct fb_info *info,
+				      struct fb_var_screeninfo *var)
+{
+	struct neofb_par *par = info->par;
+	Neo2200 __iomem *neo2200 = par->neo2200;
+	u32 bltMod, pitch;
+
+	neo2200_sync(info);
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		bltMod = NEO_MODE1_DEPTH8;
+		pitch = var->xres_virtual;
+		break;
+	case 15:
+	case 16:
+		bltMod = NEO_MODE1_DEPTH16;
+		pitch = var->xres_virtual * 2;
+		break;
+	case 24:
+		bltMod = NEO_MODE1_DEPTH24;
+		pitch = var->xres_virtual * 3;
+		break;
+	default:
+		printk(KERN_ERR
+		       "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
+		return;
+	}
+
+	writel(bltMod << 16, &neo2200->bltStat);
+	writel((pitch << 16) | pitch, &neo2200->pitch);
+}
+
+/* --------------------------------------------------------------------- */
+
+static int
+neofb_open(struct fb_info *info, int user)
+{
+	struct neofb_par *par = info->par;
+
+	if (!par->ref_count) {
+		memset(&par->state, 0, sizeof(struct vgastate));
+		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
+		save_vga(&par->state);
+	}
+	par->ref_count++;
+
+	return 0;
+}
+
+static int
+neofb_release(struct fb_info *info, int user)
+{
+	struct neofb_par *par = info->par;
+
+	if (!par->ref_count)
+		return -EINVAL;
+
+	if (par->ref_count == 1) {
+		restore_vga(&par->state);
+	}
+	par->ref_count--;
+
+	return 0;
+}
+
+static int
+neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct neofb_par *par = info->par;
+	int memlen, vramlen;
+	int mode_ok = 0;
+
+	DBG("neofb_check_var");
+
+	if (PICOS2KHZ(var->pixclock) > par->maxClock)
+		return -EINVAL;
+
+	/* Is the mode larger than the LCD panel? */
+	if (par->internal_display &&
+            ((var->xres > par->NeoPanelWidth) ||
+	     (var->yres > par->NeoPanelHeight))) {
+		printk(KERN_INFO
+		       "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
+		       var->xres, var->yres, par->NeoPanelWidth,
+		       par->NeoPanelHeight);
+		return -EINVAL;
+	}
+
+	/* Is the mode one of the acceptable sizes? */
+	if (!par->internal_display)
+		mode_ok = 1;
+	else {
+		switch (var->xres) {
+		case 1280:
+			if (var->yres == 1024)
+				mode_ok = 1;
+			break;
+		case 1024:
+			if (var->yres == 768)
+				mode_ok = 1;
+			break;
+		case 800:
+			if (var->yres == (par->libretto ? 480 : 600))
+				mode_ok = 1;
+			break;
+		case 640:
+			if (var->yres == 480)
+				mode_ok = 1;
+			break;
+		}
+	}
+
+	if (!mode_ok) {
+		printk(KERN_INFO
+		       "Mode (%dx%d) won't display properly on LCD\n",
+		       var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	switch (var->bits_per_pixel) {
+	case 8:		/* PSEUDOCOLOUR, 256 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+
+	case 16:		/* DIRECTCOLOUR, 64k */
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+
+	case 24:		/* TRUECOLOUR, 16m */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+
+#ifdef NO_32BIT_SUPPORT_YET
+	case 32:		/* TRUECOLOUR, 16m */
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+#endif
+	default:
+		printk(KERN_WARNING "neofb: no support for %dbpp\n",
+		       var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	vramlen = info->fix.smem_len;
+	if (vramlen > 4 * 1024 * 1024)
+		vramlen = 4 * 1024 * 1024;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3;
+
+	if (memlen > vramlen) {
+		var->yres_virtual =  vramlen * 8 / (var->xres_virtual *
+				   	var->bits_per_pixel);
+		memlen = var->xres_virtual * var->bits_per_pixel *
+				var->yres_virtual / 8;
+	}
+
+	/* we must round yres/xres down, we already rounded y/xres_virtual up
+	   if it was possible. We should return -EINVAL, but I disagree */
+	if (var->yres_virtual < var->yres)
+		var->yres = var->yres_virtual;
+	if (var->xoffset + var->xres > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	var->nonstd = 0;
+	var->height = -1;
+	var->width = -1;
+
+	if (var->bits_per_pixel >= 24 || !par->neo2200)
+		var->accel_flags &= ~FB_ACCELF_TEXT;
+	return 0;
+}
+
+static int neofb_set_par(struct fb_info *info)
+{
+	struct neofb_par *par = info->par;
+	unsigned char temp;
+	int i, clock_hi = 0;
+	int lcd_stretch;
+	int hoffset, voffset;
+	int vsync_start, vtotal;
+
+	DBG("neofb_set_par");
+
+	neoUnlock();
+
+	vgaHWProtect(1);	/* Blank the screen */
+
+	vsync_start = info->var.yres + info->var.lower_margin;
+	vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
+
+	/*
+	 * This will allocate the datastructure and initialize all of the
+	 * generic VGA registers.
+	 */
+
+	if (vgaHWInit(&info->var, par))
+		return -EINVAL;
+
+	/*
+	 * The default value assigned by vgaHW.c is 0x41, but this does
+	 * not work for NeoMagic.
+	 */
+	par->Attribute[16] = 0x01;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		par->CRTC[0x13] = info->var.xres_virtual >> 3;
+		par->ExtCRTOffset = info->var.xres_virtual >> 11;
+		par->ExtColorModeSelect = 0x11;
+		break;
+	case 16:
+		par->CRTC[0x13] = info->var.xres_virtual >> 2;
+		par->ExtCRTOffset = info->var.xres_virtual >> 10;
+		par->ExtColorModeSelect = 0x13;
+		break;
+	case 24:
+		par->CRTC[0x13] = (info->var.xres_virtual * 3) >> 3;
+		par->ExtCRTOffset = (info->var.xres_virtual * 3) >> 11;
+		par->ExtColorModeSelect = 0x14;
+		break;
+#ifdef NO_32BIT_SUPPORT_YET
+	case 32:		/* FIXME: guessed values */
+		par->CRTC[0x13] = info->var.xres_virtual >> 1;
+		par->ExtCRTOffset = info->var.xres_virtual >> 9;
+		par->ExtColorModeSelect = 0x15;
+		break;
+#endif
+	default:
+		break;
+	}
+
+	par->ExtCRTDispAddr = 0x10;
+
+	/* Vertical Extension */
+	par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
+	    | (((info->var.yres - 1) & 0x400) >> 9)
+	    | (((vsync_start) & 0x400) >> 8)
+	    | (((vsync_start) & 0x400) >> 7);
+
+	/* Fast write bursts on unless disabled. */
+	if (par->pci_burst)
+		par->SysIfaceCntl1 = 0x30;
+	else
+		par->SysIfaceCntl1 = 0x00;
+
+	par->SysIfaceCntl2 = 0xc0;	/* VESA Bios sets this to 0x80! */
+
+	/* Initialize: by default, we want display config register to be read */
+	par->PanelDispCntlRegRead = 1;
+
+	/* Enable any user specified display devices. */
+	par->PanelDispCntlReg1 = 0x00;
+	if (par->internal_display)
+		par->PanelDispCntlReg1 |= 0x02;
+	if (par->external_display)
+		par->PanelDispCntlReg1 |= 0x01;
+
+	/* If the user did not specify any display devices, then... */
+	if (par->PanelDispCntlReg1 == 0x00) {
+		/* Default to internal (i.e., LCD) only. */
+		par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
+	}
+
+	/* If we are using a fixed mode, then tell the chip we are. */
+	switch (info->var.xres) {
+	case 1280:
+		par->PanelDispCntlReg1 |= 0x60;
+		break;
+	case 1024:
+		par->PanelDispCntlReg1 |= 0x40;
+		break;
+	case 800:
+		par->PanelDispCntlReg1 |= 0x20;
+		break;
+	case 640:
+	default:
+		break;
+	}
+
+	/* Setup shadow register locking. */
+	switch (par->PanelDispCntlReg1 & 0x03) {
+	case 0x01:		/* External CRT only mode: */
+		par->GeneralLockReg = 0x00;
+		/* We need to program the VCLK for external display only mode. */
+		par->ProgramVCLK = 1;
+		break;
+	case 0x02:		/* Internal LCD only mode: */
+	case 0x03:		/* Simultaneous internal/external (LCD/CRT) mode: */
+		par->GeneralLockReg = 0x01;
+		/* Don't program the VCLK when using the LCD. */
+		par->ProgramVCLK = 0;
+		break;
+	}
+
+	/*
+	 * If the screen is to be stretched, turn on stretching for the
+	 * various modes.
+	 *
+	 * OPTION_LCD_STRETCH means stretching should be turned off!
+	 */
+	par->PanelDispCntlReg2 = 0x00;
+	par->PanelDispCntlReg3 = 0x00;
+
+	if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) &&	/* LCD only */
+	    (info->var.xres != par->NeoPanelWidth)) {
+		switch (info->var.xres) {
+		case 320:	/* Needs testing.  KEM -- 24 May 98 */
+		case 400:	/* Needs testing.  KEM -- 24 May 98 */
+		case 640:
+		case 800:
+		case 1024:
+			lcd_stretch = 1;
+			par->PanelDispCntlReg2 |= 0xC6;
+			break;
+		default:
+			lcd_stretch = 0;
+			/* No stretching in these modes. */
+		}
+	} else
+		lcd_stretch = 0;
+
+	/*
+	 * If the screen is to be centerd, turn on the centering for the
+	 * various modes.
+	 */
+	par->PanelVertCenterReg1 = 0x00;
+	par->PanelVertCenterReg2 = 0x00;
+	par->PanelVertCenterReg3 = 0x00;
+	par->PanelVertCenterReg4 = 0x00;
+	par->PanelVertCenterReg5 = 0x00;
+	par->PanelHorizCenterReg1 = 0x00;
+	par->PanelHorizCenterReg2 = 0x00;
+	par->PanelHorizCenterReg3 = 0x00;
+	par->PanelHorizCenterReg4 = 0x00;
+	par->PanelHorizCenterReg5 = 0x00;
+
+
+	if (par->PanelDispCntlReg1 & 0x02) {
+		if (info->var.xres == par->NeoPanelWidth) {
+			/*
+			 * No centering required when the requested display width
+			 * equals the panel width.
+			 */
+		} else {
+			par->PanelDispCntlReg2 |= 0x01;
+			par->PanelDispCntlReg3 |= 0x10;
+
+			/* Calculate the horizontal and vertical offsets. */
+			if (!lcd_stretch) {
+				hoffset =
+				    ((par->NeoPanelWidth -
+				      info->var.xres) >> 4) - 1;
+				voffset =
+				    ((par->NeoPanelHeight -
+				      info->var.yres) >> 1) - 2;
+			} else {
+				/* Stretched modes cannot be centered. */
+				hoffset = 0;
+				voffset = 0;
+			}
+
+			switch (info->var.xres) {
+			case 320:	/* Needs testing.  KEM -- 24 May 98 */
+				par->PanelHorizCenterReg3 = hoffset;
+				par->PanelVertCenterReg2 = voffset;
+				break;
+			case 400:	/* Needs testing.  KEM -- 24 May 98 */
+				par->PanelHorizCenterReg4 = hoffset;
+				par->PanelVertCenterReg1 = voffset;
+				break;
+			case 640:
+				par->PanelHorizCenterReg1 = hoffset;
+				par->PanelVertCenterReg3 = voffset;
+				break;
+			case 800:
+				par->PanelHorizCenterReg2 = hoffset;
+				par->PanelVertCenterReg4 = voffset;
+				break;
+			case 1024:
+				par->PanelHorizCenterReg5 = hoffset;
+				par->PanelVertCenterReg5 = voffset;
+				break;
+			case 1280:
+			default:
+				/* No centering in these modes. */
+				break;
+			}
+		}
+	}
+
+	par->biosMode =
+	    neoFindMode(info->var.xres, info->var.yres,
+			info->var.bits_per_pixel);
+
+	/*
+	 * Calculate the VCLK that most closely matches the requested dot
+	 * clock.
+	 */
+	neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
+
+	/* Since we program the clocks ourselves, always use VCLK3. */
+	par->MiscOutReg |= 0x0C;
+
+	/* alread unlocked above */
+	/* BOGUS  vga_wgfx(NULL, 0x09, 0x26); */
+
+	/* don't know what this is, but it's 0 from bootup anyway */
+	vga_wgfx(NULL, 0x15, 0x00);
+
+	/* was set to 0x01 by my bios in text and vesa modes */
+	vga_wgfx(NULL, 0x0A, par->GeneralLockReg);
+
+	/*
+	 * The color mode needs to be set before calling vgaHWRestore
+	 * to ensure the DAC is initialized properly.
+	 *
+	 * NOTE: Make sure we don't change bits make sure we don't change
+	 * any reserved bits.
+	 */
+	temp = vga_rgfx(NULL, 0x90);
+	switch (info->fix.accel) {
+	case FB_ACCEL_NEOMAGIC_NM2070:
+		temp &= 0xF0;	/* Save bits 7:4 */
+		temp |= (par->ExtColorModeSelect & ~0xF0);
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2090:
+	case FB_ACCEL_NEOMAGIC_NM2093:
+	case FB_ACCEL_NEOMAGIC_NM2097:
+	case FB_ACCEL_NEOMAGIC_NM2160:
+	case FB_ACCEL_NEOMAGIC_NM2200:
+	case FB_ACCEL_NEOMAGIC_NM2230:
+	case FB_ACCEL_NEOMAGIC_NM2360:
+	case FB_ACCEL_NEOMAGIC_NM2380:
+		temp &= 0x70;	/* Save bits 6:4 */
+		temp |= (par->ExtColorModeSelect & ~0x70);
+		break;
+	}
+
+	vga_wgfx(NULL, 0x90, temp);
+
+	/*
+	 * In some rare cases a lockup might occur if we don't delay
+	 * here. (Reported by Miles Lane)
+	 */
+	//mdelay(200);
+
+	/*
+	 * Disable horizontal and vertical graphics and text expansions so
+	 * that vgaHWRestore works properly.
+	 */
+	temp = vga_rgfx(NULL, 0x25);
+	temp &= 0x39;
+	vga_wgfx(NULL, 0x25, temp);
+
+	/*
+	 * Sleep for 200ms to make sure that the two operations above have
+	 * had time to take effect.
+	 */
+	mdelay(200);
+
+	/*
+	 * This function handles restoring the generic VGA registers.  */
+	vgaHWRestore(info, par);
+
+	/* linear colormap for non palettized modes */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		/* PseudoColor, 256 */
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 16:
+		/* TrueColor, 64k */
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+		for (i = 0; i < 64; i++) {
+			outb(i, 0x3c8);
+
+			outb(i << 1, 0x3c9);
+			outb(i, 0x3c9);
+			outb(i << 1, 0x3c9);
+		}
+		break;
+	case 24:
+#ifdef NO_32BIT_SUPPORT_YET
+	case 32:
+#endif
+		/* TrueColor, 16m */
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+		for (i = 0; i < 256; i++) {
+			outb(i, 0x3c8);
+
+			outb(i, 0x3c9);
+			outb(i, 0x3c9);
+			outb(i, 0x3c9);
+		}
+		break;
+	}
+
+	vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
+	vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
+	temp = vga_rgfx(NULL, 0x10);
+	temp &= 0x0F;		/* Save bits 3:0 */
+	temp |= (par->SysIfaceCntl1 & ~0x0F);	/* VESA Bios sets bit 1! */
+	vga_wgfx(NULL, 0x10, temp);
+
+	vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);
+	vga_wgfx(NULL, 0x15, 0 /*par->SingleAddrPage */ );
+	vga_wgfx(NULL, 0x16, 0 /*par->DualAddrPage */ );
+
+	temp = vga_rgfx(NULL, 0x20);
+	switch (info->fix.accel) {
+	case FB_ACCEL_NEOMAGIC_NM2070:
+		temp &= 0xFC;	/* Save bits 7:2 */
+		temp |= (par->PanelDispCntlReg1 & ~0xFC);
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2090:
+	case FB_ACCEL_NEOMAGIC_NM2093:
+	case FB_ACCEL_NEOMAGIC_NM2097:
+	case FB_ACCEL_NEOMAGIC_NM2160:
+		temp &= 0xDC;	/* Save bits 7:6,4:2 */
+		temp |= (par->PanelDispCntlReg1 & ~0xDC);
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2200:
+	case FB_ACCEL_NEOMAGIC_NM2230:
+	case FB_ACCEL_NEOMAGIC_NM2360:
+	case FB_ACCEL_NEOMAGIC_NM2380:
+		temp &= 0x98;	/* Save bits 7,4:3 */
+		temp |= (par->PanelDispCntlReg1 & ~0x98);
+		break;
+	}
+	vga_wgfx(NULL, 0x20, temp);
+
+	temp = vga_rgfx(NULL, 0x25);
+	temp &= 0x38;		/* Save bits 5:3 */
+	temp |= (par->PanelDispCntlReg2 & ~0x38);
+	vga_wgfx(NULL, 0x25, temp);
+
+	if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
+		temp = vga_rgfx(NULL, 0x30);
+		temp &= 0xEF;	/* Save bits 7:5 and bits 3:0 */
+		temp |= (par->PanelDispCntlReg3 & ~0xEF);
+		vga_wgfx(NULL, 0x30, temp);
+	}
+
+	vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);
+	vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);
+	vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);
+
+	if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
+		vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);
+		vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);
+		vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);
+		vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);
+	}
+
+	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)
+		vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
+
+	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
+		vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
+		vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);
+		vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);
+
+		clock_hi = 1;
+	}
+
+	/* Program VCLK3 if needed. */
+	if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)
+				 || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)
+				 || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)
+						  != (par->VCLK3NumeratorHigh &
+						      ~0x0F))))) {
+		vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);
+		if (clock_hi) {
+			temp = vga_rgfx(NULL, 0x8F);
+			temp &= 0x0F;	/* Save bits 3:0 */
+			temp |= (par->VCLK3NumeratorHigh & ~0x0F);
+			vga_wgfx(NULL, 0x8F, temp);
+		}
+		vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);
+	}
+
+	if (par->biosMode)
+		vga_wcrt(NULL, 0x23, par->biosMode);
+
+	vga_wgfx(NULL, 0x93, 0xc0);	/* Gives 5x faster framebuffer writes !!! */
+
+	/* Program vertical extension register */
+	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
+		vga_wcrt(NULL, 0x70, par->VerticalExt);
+	}
+
+	vgaHWProtect(0);	/* Turn on screen */
+
+	/* Calling this also locks offset registers required in update_start */
+	neoLock(&par->state);
+
+	info->fix.line_length =
+	    info->var.xres_virtual * (info->var.bits_per_pixel >> 3);
+
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230: 
+		case FB_ACCEL_NEOMAGIC_NM2360: 
+		case FB_ACCEL_NEOMAGIC_NM2380: 
+			neo2200_accel_init(info, &info->var);
+			break;
+		default:
+			break;
+	}	
+	return 0;
+}
+
+/*
+ *    Pan or Wrap the Display
+ */
+static int neofb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct neofb_par *par = info->par;
+	struct vgastate *state = &par->state;
+	int oldExtCRTDispAddr;
+	int Base;
+
+	DBG("neofb_update_start");
+
+	Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
+	Base *= (info->var.bits_per_pixel + 7) / 8;
+
+	neoUnlock();
+
+	/*
+	 * These are the generic starting address registers.
+	 */
+	vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);
+	vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));
+
+	/*
+	 * Make sure we don't clobber some other bits that might already
+	 * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
+	 * be needed.
+	 */
+	oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);
+	vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
+
+	neoLock(state);
+
+	return 0;
+}
+
+static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *fb)
+{
+	if (regno >= fb->cmap.len || regno > 255)
+		return -EINVAL;
+
+	if (fb->var.bits_per_pixel <= 8) {
+		outb(regno, 0x3c8);
+
+		outb(red >> 10, 0x3c9);
+		outb(green >> 10, 0x3c9);
+		outb(blue >> 10, 0x3c9);
+	} else if (regno < 16) {
+		switch (fb->var.bits_per_pixel) {
+		case 16:
+			((u32 *) fb->pseudo_palette)[regno] =
+				((red & 0xf800)) | ((green & 0xfc00) >> 5) |
+				((blue & 0xf800) >> 11);
+			break;
+		case 24:
+			((u32 *) fb->pseudo_palette)[regno] =
+				((red & 0xff00) << 8) | ((green & 0xff00)) |
+				((blue & 0xff00) >> 8);
+			break;
+#ifdef NO_32BIT_SUPPORT_YET
+		case 32:
+			((u32 *) fb->pseudo_palette)[regno] =
+				((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
+				((green & 0xff00)) | ((blue & 0xff00) >> 8);
+			break;
+#endif
+		default:
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *    (Un)Blank the display.
+ */
+static int neofb_blank(int blank_mode, struct fb_info *info)
+{
+	/*
+	 *  Blank the screen if blank_mode != 0, else unblank.
+	 *  Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
+	 *  e.g. a video mode which doesn't support it. Implements VESA suspend
+	 *  and powerdown modes for monitors, and backlight control on LCDs.
+	 *    blank_mode == 0: unblanked (backlight on)
+	 *    blank_mode == 1: blank (backlight on)
+	 *    blank_mode == 2: suspend vsync (backlight off)
+	 *    blank_mode == 3: suspend hsync (backlight off)
+	 *    blank_mode == 4: powerdown (backlight off)
+	 *
+	 *  wms...Enable VESA DPMS compatible powerdown mode
+	 *  run "setterm -powersave powerdown" to take advantage
+	 */
+	struct neofb_par *par = info->par;
+	int seqflags, lcdflags, dpmsflags, reg, tmpdisp;
+
+	/*
+	 * Read back the register bits related to display configuration. They might
+	 * have been changed underneath the driver via Fn key stroke.
+	 */
+	neoUnlock();
+	tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;
+	neoLock(&par->state);
+
+	/* In case we blank the screen, we want to store the possibly new
+	 * configuration in the driver. During un-blank, we re-apply this setting,
+	 * since the LCD bit will be cleared in order to switch off the backlight.
+	 */
+	if (par->PanelDispCntlRegRead) {
+		par->PanelDispCntlReg1 = tmpdisp;
+	}
+	par->PanelDispCntlRegRead = !blank_mode;
+
+	switch (blank_mode) {
+	case FB_BLANK_POWERDOWN:	/* powerdown - both sync lines down */
+		seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
+			    NEO_GR01_SUPPRESS_VSYNC;
+#ifdef CONFIG_TOSHIBA
+		/* Do we still need this ? */
+		/* attempt to turn off backlight on toshiba; also turns off external */
+		{
+			SMMRegisters regs;
+
+			regs.eax = 0xff00; /* HCI_SET */
+			regs.ebx = 0x0002; /* HCI_BACKLIGHT */
+			regs.ecx = 0x0000; /* HCI_DISABLE */
+			tosh_smm(&regs);
+		}
+#endif
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:		/* hsync off */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:		/* vsync off */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
+		break;
+	case FB_BLANK_NORMAL:		/* just blank screen (backlight stays on) */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		/*
+		 * During a blank operation with the LID shut, we might store "LCD off"
+		 * by mistake. Due to timing issues, the BIOS may switch the lights
+		 * back on, and we turn it back off once we "unblank".
+		 *
+		 * So here is an attempt to implement ">=" - if we are in the process
+		 * of unblanking, and the LCD bit is unset in the driver but set in the
+		 * register, we must keep it.
+		 */
+		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
+		dpmsflags = 0x00;	/* no hsync/vsync suppression */
+		break;
+	case FB_BLANK_UNBLANK:		/* unblank */
+		seqflags = 0;			/* Enable sequencer */
+		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
+		dpmsflags = 0x00;	/* no hsync/vsync suppression */
+#ifdef CONFIG_TOSHIBA
+		/* Do we still need this ? */
+		/* attempt to re-enable backlight/external on toshiba */
+		{
+			SMMRegisters regs;
+
+			regs.eax = 0xff00; /* HCI_SET */
+			regs.ebx = 0x0002; /* HCI_BACKLIGHT */
+			regs.ecx = 0x0001; /* HCI_ENABLE */
+			tosh_smm(&regs);
+		}
+#endif
+		break;
+	default:	/* Anything else we don't understand; return 1 to tell
+			 * fb_blank we didn't aactually do anything */
+		return 1;
+	}
+
+	neoUnlock();
+	reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
+	vga_wseq(NULL, 0x01, reg);
+	reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
+	vga_wgfx(NULL, 0x20, reg);
+	reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
+	vga_wgfx(NULL, 0x01, reg);
+	neoLock(&par->state);
+	return 0;
+}
+
+static void
+neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct neofb_par *par = info->par;
+	u_long dst, rop;
+
+	dst = rect->dx + rect->dy * info->var.xres_virtual;
+	rop = rect->rop ? 0x060000 : 0x0c0000;
+
+	neo2200_wait_fifo(info, 4);
+
+	/* set blt control */
+	writel(NEO_BC3_FIFO_EN |
+	       NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |
+	       //               NEO_BC3_DST_XY_ADDR  |
+	       //               NEO_BC3_SRC_XY_ADDR  |
+	       rop, &par->neo2200->bltCntl);
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		writel(rect->color, &par->neo2200->fgColor);
+		break;
+	case 16:
+	case 24:
+		writel(((u32 *) (info->pseudo_palette))[rect->color],
+		       &par->neo2200->fgColor);
+		break;
+	}
+
+	writel(dst * ((info->var.bits_per_pixel + 7) >> 3),
+	       &par->neo2200->dstStart);
+	writel((rect->height << 16) | (rect->width & 0xffff),
+	       &par->neo2200->xyExt);
+}
+
+static void
+neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
+	struct neofb_par *par = info->par;
+	u_long src, dst, bltCntl;
+
+	bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
+
+	if ((dy > sy) || ((dy == sy) && (dx > sx))) {
+		/* Start with the lower right corner */
+		sy += (area->height - 1);
+		dy += (area->height - 1);
+		sx += (area->width - 1);
+		dx += (area->width - 1);
+
+		bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
+	}
+
+	src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;
+	dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length;
+
+	neo2200_wait_fifo(info, 4);
+
+	/* set blt control */
+	writel(bltCntl, &par->neo2200->bltCntl);
+
+	writel(src, &par->neo2200->srcStart);
+	writel(dst, &par->neo2200->dstStart);
+	writel((area->height << 16) | (area->width & 0xffff),
+	       &par->neo2200->xyExt);
+}
+
+static void
+neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct neofb_par *par = info->par;
+	int s_pitch = (image->width * image->depth + 7) >> 3;
+	int scan_align = info->pixmap.scan_align - 1;
+	int buf_align = info->pixmap.buf_align - 1;
+	int bltCntl_flags, d_pitch, data_len;
+
+	// The data is padded for the hardware
+	d_pitch = (s_pitch + scan_align) & ~scan_align;
+	data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
+
+	neo2200_sync(info);
+
+	if (image->depth == 1) {
+		if (info->var.bits_per_pixel == 24 && image->width < 16) {
+			/* FIXME. There is a bug with accelerated color-expanded
+			 * transfers in 24 bit mode if the image being transferred
+			 * is less than 16 bits wide. This is due to insufficient
+			 * padding when writing the image. We need to adjust
+			 * struct fb_pixmap. Not yet done. */
+			cfb_imageblit(info, image);
+			return;
+		}
+		bltCntl_flags = NEO_BC0_SRC_MONO;
+	} else if (image->depth == info->var.bits_per_pixel) {
+		bltCntl_flags = 0;
+	} else {
+		/* We don't currently support hardware acceleration if image
+		 * depth is different from display */
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		writel(image->fg_color, &par->neo2200->fgColor);
+		writel(image->bg_color, &par->neo2200->bgColor);
+		break;
+	case 16:
+	case 24:
+		writel(((u32 *) (info->pseudo_palette))[image->fg_color],
+		       &par->neo2200->fgColor);
+		writel(((u32 *) (info->pseudo_palette))[image->bg_color],
+		       &par->neo2200->bgColor);
+		break;
+	}
+
+	writel(NEO_BC0_SYS_TO_VID |
+		NEO_BC3_SKIP_MAPPING | bltCntl_flags |
+		// NEO_BC3_DST_XY_ADDR |
+		0x0c0000, &par->neo2200->bltCntl);
+
+	writel(0, &par->neo2200->srcStart);
+//      par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
+	writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +
+		image->dy * info->fix.line_length), &par->neo2200->dstStart);
+	writel((image->height << 16) | (image->width & 0xffff),
+	       &par->neo2200->xyExt);
+
+	memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);
+}
+
+static void
+neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230: 
+		case FB_ACCEL_NEOMAGIC_NM2360: 
+		case FB_ACCEL_NEOMAGIC_NM2380:
+			neo2200_fillrect(info, rect);
+			break;
+		default:
+			cfb_fillrect(info, rect);
+			break;
+	}	
+}
+
+static void
+neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230: 
+		case FB_ACCEL_NEOMAGIC_NM2360: 
+		case FB_ACCEL_NEOMAGIC_NM2380: 
+			neo2200_copyarea(info, area);
+			break;
+		default:
+			cfb_copyarea(info, area);
+			break;
+	}	
+}
+
+static void
+neofb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230:
+		case FB_ACCEL_NEOMAGIC_NM2360:
+		case FB_ACCEL_NEOMAGIC_NM2380:
+			neo2200_imageblit(info, image);
+			break;
+		default:
+			cfb_imageblit(info, image);
+			break;
+	}
+}
+
+static int 
+neofb_sync(struct fb_info *info)
+{
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230: 
+		case FB_ACCEL_NEOMAGIC_NM2360: 
+		case FB_ACCEL_NEOMAGIC_NM2380: 
+			neo2200_sync(info);
+			break;
+		default:
+			break;
+	}
+	return 0;		
+}
+
+/*
+static void
+neofb_draw_cursor(struct fb_info *info, u8 *dst, u8 *src, unsigned int width)
+{
+	//memset_io(info->sprite.addr, 0xff, 1);
+}
+
+static int
+neofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct neofb_par *par = (struct neofb_par *) info->par;
+
+	* Disable cursor *
+	write_le32(NEOREG_CURSCNTL, ~NEO_CURS_ENABLE, par);
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		u32 x = cursor->image.dx;
+		u32 y = cursor->image.dy;
+
+		info->cursor.image.dx = x;
+		info->cursor.image.dy = y;
+		write_le32(NEOREG_CURSX, x, par);
+		write_le32(NEOREG_CURSY, y, par);
+	}
+
+	if (cursor->set & FB_CUR_SETSIZE) {
+		info->cursor.image.height = cursor->image.height;
+		info->cursor.image.width = cursor->image.width;
+	}
+
+	if (cursor->set & FB_CUR_SETHOT)
+		info->cursor.hot = cursor->hot;
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		if (cursor->image.depth == 1) {
+			u32 fg = cursor->image.fg_color;
+			u32 bg = cursor->image.bg_color;
+
+			info->cursor.image.fg_color = fg;
+			info->cursor.image.bg_color = bg;
+
+			fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
+			bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
+			write_le32(NEOREG_CURSFGCOLOR, fg, par);
+			write_le32(NEOREG_CURSBGCOLOR, bg, par);
+		}
+	}
+
+	if (cursor->set & FB_CUR_SETSHAPE)
+		fb_load_cursor_image(info);
+
+	if (info->cursor.enable)
+		write_le32(NEOREG_CURSCNTL, NEO_CURS_ENABLE, par);
+	return 0;
+}
+*/
+
+static struct fb_ops neofb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= neofb_open,
+	.fb_release	= neofb_release,
+	.fb_check_var	= neofb_check_var,
+	.fb_set_par	= neofb_set_par,
+	.fb_setcolreg	= neofb_setcolreg,
+	.fb_pan_display	= neofb_pan_display,
+	.fb_blank	= neofb_blank,
+	.fb_sync	= neofb_sync,
+	.fb_fillrect	= neofb_fillrect,
+	.fb_copyarea	= neofb_copyarea,
+	.fb_imageblit	= neofb_imageblit,
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_videomode mode800x480 = {
+	.xres           = 800,
+	.yres           = 480,
+	.pixclock       = 25000,
+	.left_margin    = 88,
+	.right_margin   = 40,
+	.upper_margin   = 23,
+	.lower_margin   = 1,
+	.hsync_len      = 128,
+	.vsync_len      = 4,
+	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode          = FB_VMODE_NONINTERLACED
+};
+
+static int neo_map_mmio(struct fb_info *info, struct pci_dev *dev)
+{
+	struct neofb_par *par = info->par;
+
+	DBG("neo_map_mmio");
+
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2070:
+			info->fix.mmio_start = pci_resource_start(dev, 0)+
+				0x100000;
+			break;
+		case FB_ACCEL_NEOMAGIC_NM2090:
+		case FB_ACCEL_NEOMAGIC_NM2093:
+			info->fix.mmio_start = pci_resource_start(dev, 0)+
+				0x200000;
+			break;
+		case FB_ACCEL_NEOMAGIC_NM2160:
+		case FB_ACCEL_NEOMAGIC_NM2097:
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230:
+		case FB_ACCEL_NEOMAGIC_NM2360:
+		case FB_ACCEL_NEOMAGIC_NM2380:
+			info->fix.mmio_start = pci_resource_start(dev, 1);
+			break;
+		default:
+			info->fix.mmio_start = pci_resource_start(dev, 0);
+	}
+	info->fix.mmio_len = MMIO_SIZE;
+
+	if (!request_mem_region
+	    (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) {
+		printk("neofb: memory mapped IO in use\n");
+		return -EBUSY;
+	}
+
+	par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE);
+	if (!par->mmio_vbase) {
+		printk("neofb: unable to map memory mapped IO\n");
+		release_mem_region(info->fix.mmio_start,
+				   info->fix.mmio_len);
+		return -ENOMEM;
+	} else
+		printk(KERN_INFO "neofb: mapped io at %p\n",
+		       par->mmio_vbase);
+	return 0;
+}
+
+static void neo_unmap_mmio(struct fb_info *info)
+{
+	struct neofb_par *par = info->par;
+
+	DBG("neo_unmap_mmio");
+
+	iounmap(par->mmio_vbase);
+	par->mmio_vbase = NULL;
+
+	release_mem_region(info->fix.mmio_start,
+			   info->fix.mmio_len);
+}
+
+static int neo_map_video(struct fb_info *info, struct pci_dev *dev,
+			 int video_len)
+{
+	//unsigned long addr;
+
+	DBG("neo_map_video");
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = video_len;
+
+	if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
+				"frame buffer")) {
+		printk("neofb: frame buffer in use\n");
+		return -EBUSY;
+	}
+
+	info->screen_base =
+	    ioremap(info->fix.smem_start, info->fix.smem_len);
+	if (!info->screen_base) {
+		printk("neofb: unable to map screen memory\n");
+		release_mem_region(info->fix.smem_start,
+				   info->fix.smem_len);
+		return -ENOMEM;
+	} else
+		printk(KERN_INFO "neofb: mapped framebuffer at %p\n",
+		       info->screen_base);
+
+#ifdef CONFIG_MTRR
+	((struct neofb_par *)(info->par))->mtrr =
+		mtrr_add(info->fix.smem_start, pci_resource_len(dev, 0),
+				MTRR_TYPE_WRCOMB, 1);
+#endif
+
+	/* Clear framebuffer, it's all white in memory after boot */
+	memset_io(info->screen_base, 0, info->fix.smem_len);
+
+	/* Allocate Cursor drawing pad.
+	info->fix.smem_len -= PAGE_SIZE;
+	addr = info->fix.smem_start + info->fix.smem_len;
+	write_le32(NEOREG_CURSMEMPOS, ((0x000f & (addr >> 10)) << 8) |
+					((0x0ff0 & (addr >> 10)) >> 4), par);
+	addr = (unsigned long) info->screen_base + info->fix.smem_len;
+	info->sprite.addr = (u8 *) addr; */
+	return 0;
+}
+
+static void neo_unmap_video(struct fb_info *info)
+{
+	DBG("neo_unmap_video");
+
+#ifdef CONFIG_MTRR
+	{
+		struct neofb_par *par = info->par;
+
+		mtrr_del(par->mtrr, info->fix.smem_start,
+			 info->fix.smem_len);
+	}
+#endif
+	iounmap(info->screen_base);
+	info->screen_base = NULL;
+
+	release_mem_region(info->fix.smem_start,
+			   info->fix.smem_len);
+}
+
+static int neo_scan_monitor(struct fb_info *info)
+{
+	struct neofb_par *par = info->par;
+	unsigned char type, display;
+	int w;
+
+	// Eventually we will have i2c support.
+	info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
+	if (!info->monspecs.modedb)
+		return -ENOMEM;
+	info->monspecs.modedb_len = 1;
+
+	/* Determine the panel type */
+	vga_wgfx(NULL, 0x09, 0x26);
+	type = vga_rgfx(NULL, 0x21);
+	display = vga_rgfx(NULL, 0x20);
+	if (!par->internal_display && !par->external_display) {
+		par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
+		par->external_display = display & 1;
+		printk (KERN_INFO "Autodetected %s display\n",
+			par->internal_display && par->external_display ? "simultaneous" :
+			par->internal_display ? "internal" : "external");
+	}
+
+	/* Determine panel width -- used in NeoValidMode. */
+	w = vga_rgfx(NULL, 0x20);
+	vga_wgfx(NULL, 0x09, 0x00);
+	switch ((w & 0x18) >> 3) {
+	case 0x00:
+		// 640x480@60
+		par->NeoPanelWidth = 640;
+		par->NeoPanelHeight = 480;
+		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
+		break;
+	case 0x01:
+		par->NeoPanelWidth = 800;
+		if (par->libretto) {
+			par->NeoPanelHeight = 480;
+			memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
+		} else {
+			// 800x600@60
+			par->NeoPanelHeight = 600;
+			memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
+		}
+		break;
+	case 0x02:
+		// 1024x768@60
+		par->NeoPanelWidth = 1024;
+		par->NeoPanelHeight = 768;
+		memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
+		break;
+	case 0x03:
+		/* 1280x1024@60 panel support needs to be added */
+#ifdef NOT_DONE
+		par->NeoPanelWidth = 1280;
+		par->NeoPanelHeight = 1024;
+		memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
+		break;
+#else
+		printk(KERN_ERR
+		       "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
+		return -1;
+#endif
+	default:
+		// 640x480@60
+		par->NeoPanelWidth = 640;
+		par->NeoPanelHeight = 480;
+		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
+		break;
+	}
+
+	printk(KERN_INFO "Panel is a %dx%d %s %s display\n",
+	       par->NeoPanelWidth,
+	       par->NeoPanelHeight,
+	       (type & 0x02) ? "color" : "monochrome",
+	       (type & 0x10) ? "TFT" : "dual scan");
+	return 0;
+}
+
+static int neo_init_hw(struct fb_info *info)
+{
+	struct neofb_par *par = info->par;
+	int videoRam = 896;
+	int maxClock = 65000;
+	int CursorMem = 1024;
+	int CursorOff = 0x100;
+
+	DBG("neo_init_hw");
+
+	neoUnlock();
+
+#if 0
+	printk(KERN_DEBUG "--- Neo extended register dump ---\n");
+	for (int w = 0; w < 0x85; w++)
+		printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
+		       (void *) vga_rcrt(NULL, w));
+	for (int w = 0; w < 0xC7; w++)
+		printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
+		       (void *) vga_rgfx(NULL, w));
+#endif
+	switch (info->fix.accel) {
+	case FB_ACCEL_NEOMAGIC_NM2070:
+		videoRam = 896;
+		maxClock = 65000;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2090:
+	case FB_ACCEL_NEOMAGIC_NM2093:
+	case FB_ACCEL_NEOMAGIC_NM2097:
+		videoRam = 1152;
+		maxClock = 80000;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2160:
+		videoRam = 2048;
+		maxClock = 90000;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2200:
+		videoRam = 2560;
+		maxClock = 110000;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2230:
+		videoRam = 3008;
+		maxClock = 110000;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2360:
+		videoRam = 4096;
+		maxClock = 110000;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2380:
+		videoRam = 6144;
+		maxClock = 110000;
+		break;
+	}
+	switch (info->fix.accel) {
+	case FB_ACCEL_NEOMAGIC_NM2070:
+	case FB_ACCEL_NEOMAGIC_NM2090:
+	case FB_ACCEL_NEOMAGIC_NM2093:
+		CursorMem = 2048;
+		CursorOff = 0x100;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2097:
+	case FB_ACCEL_NEOMAGIC_NM2160:
+		CursorMem = 1024;
+		CursorOff = 0x100;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2200:
+	case FB_ACCEL_NEOMAGIC_NM2230:
+	case FB_ACCEL_NEOMAGIC_NM2360:
+	case FB_ACCEL_NEOMAGIC_NM2380:
+		CursorMem = 1024;
+		CursorOff = 0x1000;
+
+		par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
+		break;
+	}
+/*
+	info->sprite.size = CursorMem;
+	info->sprite.scan_align = 1;
+	info->sprite.buf_align = 1;
+	info->sprite.flags = FB_PIXMAP_IO;
+	info->sprite.outbuf = neofb_draw_cursor;
+*/
+	par->maxClock = maxClock;
+	par->cursorOff = CursorOff;
+	return videoRam * 1024;
+}
+
+
+static struct fb_info *neo_alloc_fb_info(struct pci_dev *dev,
+					 const struct pci_device_id *id)
+{
+	struct fb_info *info;
+	struct neofb_par *par;
+
+	info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
+
+	if (!info)
+		return NULL;
+
+	par = info->par;
+
+	info->fix.accel = id->driver_data;
+
+	par->pci_burst = !nopciburst;
+	par->lcd_stretch = !nostretch;
+	par->libretto = libretto;
+
+	par->internal_display = internal;
+	par->external_display = external;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	switch (info->fix.accel) {
+	case FB_ACCEL_NEOMAGIC_NM2070:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128");
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2090:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128V");
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2093:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128ZV");
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2097:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128ZV+");
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2160:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128XD");
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2200:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256AV");
+		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+		               FBINFO_HWACCEL_COPYAREA |
+                	       FBINFO_HWACCEL_FILLRECT;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2230:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256AV+");
+		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+		               FBINFO_HWACCEL_COPYAREA |
+                	       FBINFO_HWACCEL_FILLRECT;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2360:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256ZX");
+		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+		               FBINFO_HWACCEL_COPYAREA |
+                	       FBINFO_HWACCEL_FILLRECT;
+		break;
+	case FB_ACCEL_NEOMAGIC_NM2380:
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256XL+");
+		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+		               FBINFO_HWACCEL_COPYAREA |
+                	       FBINFO_HWACCEL_FILLRECT;
+		break;
+	}
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 0;
+	info->fix.ypanstep = 4;
+	info->fix.ywrapstep = 0;
+	info->fix.accel = id->driver_data;
+
+	info->fbops = &neofb_ops;
+	info->pseudo_palette = par->palette;
+	return info;
+}
+
+static void neo_free_fb_info(struct fb_info *info)
+{
+	if (info) {
+		/*
+		 * Free the colourmap
+		 */
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+}
+
+/* --------------------------------------------------------------------- */
+
+static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct fb_info *info;
+	u_int h_sync, v_sync;
+	int video_len, err;
+
+	DBG("neofb_probe");
+
+	err = pci_enable_device(dev);
+	if (err)
+		return err;
+
+	err = -ENOMEM;
+	info = neo_alloc_fb_info(dev, id);
+	if (!info)
+		return err;
+
+	err = neo_map_mmio(info, dev);
+	if (err)
+		goto err_map_mmio;
+
+	err = neo_scan_monitor(info);
+	if (err)
+		goto err_scan_monitor;
+
+	video_len = neo_init_hw(info);
+	if (video_len < 0) {
+		err = video_len;
+		goto err_init_hw;
+	}
+
+	err = neo_map_video(info, dev, video_len);
+	if (err)
+		goto err_init_hw;
+
+	if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
+			info->monspecs.modedb, 16)) {
+		printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
+		err = -EINVAL;
+		goto err_map_video;
+	}
+
+	/*
+	 * Calculate the hsync and vsync frequencies.  Note that
+	 * we split the 1e12 constant up so that we can preserve
+	 * the precision and fit the results into 32-bit registers.
+	 *  (1953125000 * 512 = 1e12)
+	 */
+	h_sync = 1953125000 / info->var.pixclock;
+	h_sync =
+	    h_sync * 512 / (info->var.xres + info->var.left_margin +
+			    info->var.right_margin + info->var.hsync_len);
+	v_sync =
+	    h_sync / (info->var.yres + info->var.upper_margin +
+		      info->var.lower_margin + info->var.vsync_len);
+
+	printk(KERN_INFO "neofb v" NEOFB_VERSION
+	       ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+	       info->fix.smem_len >> 10, info->var.xres,
+	       info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);
+
+	err = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (err < 0)
+		goto err_map_video;
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto err_reg_fb;
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	/*
+	 * Our driver data
+	 */
+	pci_set_drvdata(dev, info);
+	return 0;
+
+err_reg_fb:
+	fb_dealloc_cmap(&info->cmap);
+err_map_video:
+	neo_unmap_video(info);
+err_init_hw:
+	fb_destroy_modedb(info->monspecs.modedb);
+err_scan_monitor:
+	neo_unmap_mmio(info);
+err_map_mmio:
+	neo_free_fb_info(info);
+	return err;
+}
+
+static void neofb_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+
+	DBG("neofb_remove");
+
+	if (info) {
+		/*
+		 * If unregister_framebuffer fails, then
+		 * we will be leaving hooks that could cause
+		 * oopsen laying around.
+		 */
+		if (unregister_framebuffer(info))
+			printk(KERN_WARNING
+			       "neofb: danger danger!  Oopsen imminent!\n");
+
+		neo_unmap_video(info);
+		fb_destroy_modedb(info->monspecs.modedb);
+		neo_unmap_mmio(info);
+		neo_free_fb_info(info);
+	}
+}
+
+static struct pci_device_id neofb_devices[] = {
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
+
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
+
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, neofb_devices);
+
+static struct pci_driver neofb_driver = {
+	.name =		"neofb",
+	.id_table =	neofb_devices,
+	.probe =	neofb_probe,
+	.remove =	neofb_remove,
+};
+
+/* ************************* init in-kernel code ************************** */
+
+#ifndef MODULE
+static int __init neofb_setup(char *options)
+{
+	char *this_opt;
+
+	DBG("neofb_setup");
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+
+		if (!strncmp(this_opt, "internal", 8))
+			internal = 1;
+		else if (!strncmp(this_opt, "external", 8))
+			external = 1;
+		else if (!strncmp(this_opt, "nostretch", 9))
+			nostretch = 1;
+		else if (!strncmp(this_opt, "nopciburst", 10))
+			nopciburst = 1;
+		else if (!strncmp(this_opt, "libretto", 8))
+			libretto = 1;
+		else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+#endif  /*  MODULE  */
+
+static int __init neofb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("neofb", &option))
+		return -ENODEV;
+	neofb_setup(option);
+#endif
+	return pci_register_driver(&neofb_driver);
+}
+
+module_init(neofb_init);
+
+#ifdef MODULE
+static void __exit neofb_exit(void)
+{
+	pci_unregister_driver(&neofb_driver);
+}
+
+module_exit(neofb_exit);
+#endif				/* MODULE */
diff --git a/drivers/video/fbdev/nuc900fb.c b/drivers/video/fbdev/nuc900fb.c
new file mode 100644
index 000000000000..478f9808dee4
--- /dev/null
+++ b/drivers/video/fbdev/nuc900fb.c
@@ -0,0 +1,765 @@
+/*
+ *
+ * Copyright (c) 2009 Nuvoton technology corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *  Description:
+ *    Nuvoton LCD Controller Driver
+ *  Author:
+ *    Wang Qiang (rurality.linux@gmail.com) 2009/12/11
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-ldm.h>
+#include <linux/platform_data/video-nuc900fb.h>
+
+#include "nuc900fb.h"
+
+
+/*
+ *  Initialize the nuc900 video (dual) buffer address
+ */
+static void nuc900fb_set_lcdaddr(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+	unsigned long vbaddr1, vbaddr2;
+
+	vbaddr1  = info->fix.smem_start;
+	vbaddr2  = info->fix.smem_start;
+	vbaddr2 += info->fix.line_length * info->var.yres;
+
+	/* set frambuffer start phy addr*/
+	writel(vbaddr1, regs + REG_LCM_VA_BADDR0);
+	writel(vbaddr2, regs + REG_LCM_VA_BADDR1);
+
+	writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL);
+	writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE);
+}
+
+/*
+ *	calculate divider for lcd div
+ */
+static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi,
+					 unsigned long pixclk)
+{
+	unsigned long clk = fbi->clk_rate;
+	unsigned long long div;
+
+	/* pixclk is in picseconds. our clock is in Hz*/
+	/* div = (clk * pixclk)/10^12 */
+	div = (unsigned long long)clk * pixclk;
+	div >>= 12;
+	do_div(div, 625 * 625UL * 625);
+
+	dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div);
+
+	return div;
+}
+
+/*
+ *	Check the video params of 'var'.
+ */
+static int nuc900fb_check_var(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
+	struct nuc900fb_display *display = NULL;
+	struct nuc900fb_display *default_display = mach_info->displays +
+						   mach_info->default_display;
+	int i;
+
+	dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info);
+
+	/* validate x/y resolution */
+	/* choose default mode if possible */
+	if (var->xres == default_display->xres &&
+	    var->yres == default_display->yres &&
+	    var->bits_per_pixel == default_display->bpp)
+		display = default_display;
+	else
+		for (i = 0; i < mach_info->num_displays; i++)
+			if (var->xres == mach_info->displays[i].xres &&
+			    var->yres == mach_info->displays[i].yres &&
+			    var->bits_per_pixel == mach_info->displays[i].bpp) {
+				display = mach_info->displays + i;
+				break;
+			}
+
+	if (display == NULL) {
+		printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* it should be the same size as the display */
+	var->xres_virtual	= display->xres;
+	var->yres_virtual	= display->yres;
+	var->height		= display->height;
+	var->width		= display->width;
+
+	/* copy lcd settings */
+	var->pixclock		= display->pixclock;
+	var->left_margin	= display->left_margin;
+	var->right_margin	= display->right_margin;
+	var->upper_margin	= display->upper_margin;
+	var->lower_margin	= display->lower_margin;
+	var->vsync_len		= display->vsync_len;
+	var->hsync_len		= display->hsync_len;
+
+	var->transp.offset	= 0;
+	var->transp.length	= 0;
+
+	fbi->regs.lcd_dccs = display->dccs;
+	fbi->regs.lcd_device_ctrl = display->devctl;
+	fbi->regs.lcd_va_fbctrl = display->fbctrl;
+	fbi->regs.lcd_va_scale = display->scale;
+
+	/* set R/G/B possions */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+	default:
+		var->red.offset 	= 0;
+		var->red.length 	= var->bits_per_pixel;
+		var->green 		= var->red;
+		var->blue		= var->red;
+		break;
+	case 12:
+		var->red.length		= 4;
+		var->green.length	= 4;
+		var->blue.length	= 4;
+		var->red.offset		= 8;
+		var->green.offset	= 4;
+		var->blue.offset	= 0;
+		break;
+	case 16:
+		var->red.length		= 5;
+		var->green.length	= 6;
+		var->blue.length	= 5;
+		var->red.offset		= 11;
+		var->green.offset	= 5;
+		var->blue.offset	= 0;
+		break;
+	case 18:
+		var->red.length		= 6;
+		var->green.length	= 6;
+		var->blue.length	= 6;
+		var->red.offset		= 12;
+		var->green.offset	= 6;
+		var->blue.offset	= 0;
+		break;
+	case 32:
+		var->red.length		= 8;
+		var->green.length	= 8;
+		var->blue.length	= 8;
+		var->red.offset		= 16;
+		var->green.offset	= 8;
+		var->blue.offset	= 0;
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ *	Calculate lcd register values from var setting & save into hw
+ */
+static void nuc900fb_calculate_lcd_regs(const struct fb_info *info,
+					struct nuc900fb_hw *regs)
+{
+	const struct fb_var_screeninfo *var = &info->var;
+	int vtt = var->height + var->upper_margin + var->lower_margin;
+	int htt = var->width + var->left_margin + var->right_margin;
+	int hsync = var->width + var->right_margin;
+	int vsync = var->height + var->lower_margin;
+
+	regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) |
+			      LCM_CRTC_SIZE_HTTVAL(htt);
+	regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) |
+			      LCM_CRTC_DEND_HDENDVAL(var->width);
+	regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) |
+			    LCM_CRTC_HR_SVAL(var->width + 1);
+	regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) |
+			       LCM_CRTC_HSYNC_SVAL(hsync);
+	regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) |
+			    LCM_CRTC_VR_SVAL(vsync);
+
+}
+
+/*
+ *	Activate (set) the controller from the given framebuffer
+ *	information
+ */
+static void nuc900fb_activate_var(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+	struct fb_var_screeninfo *var = &info->var;
+	int clkdiv;
+
+	clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1;
+	if (clkdiv < 0)
+		clkdiv = 0;
+
+	nuc900fb_calculate_lcd_regs(info, &fbi->regs);
+
+	/* set the new lcd registers*/
+
+	dev_dbg(fbi->dev, "new lcd register set:\n");
+	dev_dbg(fbi->dev, "dccs       = 0x%08x\n", fbi->regs.lcd_dccs);
+	dev_dbg(fbi->dev, "dev_ctl    = 0x%08x\n", fbi->regs.lcd_device_ctrl);
+	dev_dbg(fbi->dev, "crtc_size  = 0x%08x\n", fbi->regs.lcd_crtc_size);
+	dev_dbg(fbi->dev, "crtc_dend  = 0x%08x\n", fbi->regs.lcd_crtc_dend);
+	dev_dbg(fbi->dev, "crtc_hr    = 0x%08x\n", fbi->regs.lcd_crtc_hr);
+	dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync);
+	dev_dbg(fbi->dev, "crtc_vr    = 0x%08x\n", fbi->regs.lcd_crtc_vr);
+
+	writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL);
+	writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE);
+	writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND);
+	writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR);
+	writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC);
+	writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR);
+
+	/* set lcd address pointers */
+	nuc900fb_set_lcdaddr(info);
+
+	writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS);
+}
+
+/*
+ *      Alters the hardware state.
+ *
+ */
+static int nuc900fb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+	case 24:
+	case 18:
+	case 16:
+	case 12:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 1:
+		info->fix.visual = FB_VISUAL_MONO01;
+		break;
+	default:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
+
+	/* activate this new configuration */
+	nuc900fb_activate_var(info);
+	return 0;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan,
+					 struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int nuc900fb_setcolreg(unsigned regno,
+			       unsigned red, unsigned green, unsigned blue,
+			       unsigned transp, struct fb_info *info)
+{
+	unsigned int val;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/* true-colour, use pseuo-palette */
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+			pal[regno] = val;
+		}
+		break;
+
+	default:
+		return 1;   /* unknown type */
+	}
+	return 0;
+}
+
+/**
+ *      nuc900fb_blank
+ *
+ */
+static int nuc900fb_blank(int blank_mode, struct fb_info *info)
+{
+
+	return 0;
+}
+
+static struct fb_ops nuc900fb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_check_var		= nuc900fb_check_var,
+	.fb_set_par		= nuc900fb_set_par,
+	.fb_blank		= nuc900fb_blank,
+	.fb_setcolreg		= nuc900fb_setcolreg,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+};
+
+
+static inline void modify_gpio(void __iomem *reg,
+			       unsigned long set, unsigned long mask)
+{
+	unsigned long tmp;
+	tmp = readl(reg) & ~mask;
+	writel(tmp | set, reg);
+}
+
+/*
+ * Initialise LCD-related registers
+ */
+static int nuc900fb_init_registers(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
+	void __iomem *regs = fbi->io;
+
+	/*reset the display engine*/
+	writel(0, regs + REG_LCM_DCCS);
+	writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST,
+	       regs + REG_LCM_DCCS);
+	ndelay(100);
+	writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST),
+	       regs + REG_LCM_DCCS);
+	ndelay(100);
+
+	writel(0, regs + REG_LCM_DEV_CTRL);
+
+	/* config gpio output */
+	modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir,
+		    mach_info->gpio_dir_mask);
+	modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data,
+		    mach_info->gpio_data_mask);
+
+	return 0;
+}
+
+
+/*
+ *    Alloc the SDRAM region of NUC900 for the frame buffer.
+ *    The buffer should be a non-cached, non-buffered, memory region
+ *    to allow palette and pixel writes without flushing the cache.
+ */
+static int nuc900fb_map_video_memory(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	dma_addr_t map_dma;
+	unsigned long map_size = PAGE_ALIGN(info->fix.smem_len);
+
+	dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n",
+		fbi, map_size);
+
+	info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
+							&map_dma, GFP_KERNEL);
+
+	if (!info->screen_base)
+		return -ENOMEM;
+
+	memset(info->screen_base, 0x00, map_size);
+	info->fix.smem_start = map_dma;
+
+	return 0;
+}
+
+static inline void nuc900fb_unmap_video_memory(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+			      info->screen_base, info->fix.smem_start);
+}
+
+static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id)
+{
+	struct nuc900fb_info *fbi = dev_id;
+	void __iomem *regs = fbi->io;
+	void __iomem *irq_base = fbi->irq_base;
+	unsigned long lcdirq = readl(regs + REG_LCM_INT_CS);
+
+	if (lcdirq & LCM_INT_CS_DISP_F_STATUS) {
+		writel(readl(irq_base) | 1<<30, irq_base);
+
+		/* wait VA_EN low */
+		if ((readl(regs + REG_LCM_DCCS) &
+		    LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE)
+			while ((readl(regs + REG_LCM_DCCS) &
+			       LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN)
+				;
+		/* display_out-enable */
+		writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN,
+			regs + REG_LCM_DCCS);
+		/* va-enable*/
+		writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN,
+			regs + REG_LCM_DCCS);
+	} else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) {
+		writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base);
+	} else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) {
+		writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+static int nuc900fb_cpufreq_transition(struct notifier_block *nb,
+				       unsigned long val, void *data)
+{
+	struct nuc900fb_info *info;
+	struct fb_info *fbinfo;
+	long delta_f;
+	info = container_of(nb, struct nuc900fb_info, freq_transition);
+	fbinfo = platform_get_drvdata(to_platform_device(info->dev));
+
+	delta_f = info->clk_rate - clk_get_rate(info->clk);
+
+	if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
+	   (val == CPUFREQ_PRECHANGE && delta_f < 0)) {
+		info->clk_rate = clk_get_rate(info->clk);
+		nuc900fb_activate_var(fbinfo);
+	}
+
+	return 0;
+}
+
+static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
+{
+	fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition;
+	return cpufreq_register_notifier(&fbi->freq_transition,
+				  CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi)
+{
+	cpufreq_unregister_notifier(&fbi->freq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+}
+#else
+static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb,
+				       unsigned long val, void *data)
+{
+	return 0;
+}
+
+static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
+{
+	return 0;
+}
+
+static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info)
+{
+}
+#endif
+
+static char driver_name[] = "nuc900fb";
+
+static int nuc900fb_probe(struct platform_device *pdev)
+{
+	struct nuc900fb_info *fbi;
+	struct nuc900fb_display *display;
+	struct fb_info	   *fbinfo;
+	struct nuc900fb_mach_info *mach_info;
+	struct resource *res;
+	int ret;
+	int irq;
+	int i;
+	int size;
+
+	dev_dbg(&pdev->dev, "devinit\n");
+	mach_info = dev_get_platdata(&pdev->dev);
+	if (mach_info == NULL) {
+		dev_err(&pdev->dev,
+			"no platform data for lcd, cannot attach\n");
+		return -EINVAL;
+	}
+
+	if (mach_info->default_display > mach_info->num_displays) {
+		dev_err(&pdev->dev,
+			"default display No. is %d but only %d displays \n",
+			mach_info->default_display, mach_info->num_displays);
+		return -EINVAL;
+	}
+
+
+	display = mach_info->displays + mach_info->default_display;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq for device\n");
+		return -ENOENT;
+	}
+
+	fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev);
+	if (!fbinfo)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	fbi = fbinfo->par;
+	fbi->dev = &pdev->dev;
+
+#ifdef CONFIG_CPU_NUC950
+	fbi->drv_type = LCDDRV_NUC950;
+#endif
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	size = resource_size(res);
+	fbi->mem = request_mem_region(res->start, size, pdev->name);
+	if (fbi->mem == NULL) {
+		dev_err(&pdev->dev, "failed to alloc memory region\n");
+		ret = -ENOENT;
+		goto free_fb;
+	}
+
+	fbi->io = ioremap(res->start, size);
+	if (fbi->io == NULL) {
+		dev_err(&pdev->dev, "ioremap() of lcd registers failed\n");
+		ret = -ENXIO;
+		goto release_mem_region;
+	}
+
+	fbi->irq_base = fbi->io + REG_LCM_INT_CS;
+
+
+	/* Stop the LCD */
+	writel(0, fbi->io + REG_LCM_DCCS);
+
+	/* fill the fbinfo*/
+	strcpy(fbinfo->fix.id, driver_name);
+	fbinfo->fix.type		= FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux		= 0;
+	fbinfo->fix.xpanstep		= 0;
+	fbinfo->fix.ypanstep		= 0;
+	fbinfo->fix.ywrapstep		= 0;
+	fbinfo->fix.accel		= FB_ACCEL_NONE;
+	fbinfo->var.nonstd		= 0;
+	fbinfo->var.activate		= FB_ACTIVATE_NOW;
+	fbinfo->var.accel_flags		= 0;
+	fbinfo->var.vmode		= FB_VMODE_NONINTERLACED;
+	fbinfo->fbops			= &nuc900fb_ops;
+	fbinfo->flags			= FBINFO_FLAG_DEFAULT;
+	fbinfo->pseudo_palette		= &fbi->pseudo_pal;
+
+	ret = request_irq(irq, nuc900fb_irqhandler, 0, pdev->name, fbi);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
+			irq, ret);
+		ret = -EBUSY;
+		goto release_regs;
+	}
+
+	fbi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(fbi->clk)) {
+		printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
+		ret = PTR_ERR(fbi->clk);
+		goto release_irq;
+	}
+
+	clk_enable(fbi->clk);
+	dev_dbg(&pdev->dev, "got and enabled clock\n");
+
+	fbi->clk_rate = clk_get_rate(fbi->clk);
+
+	/* calutate the video buffer size */
+	for (i = 0; i < mach_info->num_displays; i++) {
+		unsigned long smem_len = mach_info->displays[i].xres;
+		smem_len *= mach_info->displays[i].yres;
+		smem_len *= mach_info->displays[i].bpp;
+		smem_len >>= 3;
+		if (fbinfo->fix.smem_len < smem_len)
+			fbinfo->fix.smem_len = smem_len;
+	}
+
+	/* Initialize Video Memory */
+	ret = nuc900fb_map_video_memory(fbinfo);
+	if (ret) {
+		printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret);
+		goto release_clock;
+	}
+
+	dev_dbg(&pdev->dev, "got video memory\n");
+
+	fbinfo->var.xres = display->xres;
+	fbinfo->var.yres = display->yres;
+	fbinfo->var.bits_per_pixel = display->bpp;
+
+	nuc900fb_init_registers(fbinfo);
+
+	nuc900fb_check_var(&fbinfo->var, fbinfo);
+
+	ret = nuc900fb_cpufreq_register(fbi);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register cpufreq\n");
+		goto free_video_memory;
+	}
+
+	ret = register_framebuffer(fbinfo);
+	if (ret) {
+		printk(KERN_ERR "failed to register framebuffer device: %d\n",
+			ret);
+		goto free_cpufreq;
+	}
+
+	fb_info(fbinfo, "%s frame buffer device\n", fbinfo->fix.id);
+
+	return 0;
+
+free_cpufreq:
+	nuc900fb_cpufreq_deregister(fbi);
+free_video_memory:
+	nuc900fb_unmap_video_memory(fbinfo);
+release_clock:
+	clk_disable(fbi->clk);
+	clk_put(fbi->clk);
+release_irq:
+	free_irq(irq, fbi);
+release_regs:
+	iounmap(fbi->io);
+release_mem_region:
+	release_mem_region(res->start, size);
+free_fb:
+	framebuffer_release(fbinfo);
+	return ret;
+}
+
+/*
+ * shutdown the lcd controller
+ */
+static void nuc900fb_stop_lcd(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+
+	writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN),
+		regs + REG_LCM_DCCS);
+}
+
+/*
+ *  Cleanup
+ */
+static int nuc900fb_remove(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct nuc900fb_info *fbi = fbinfo->par;
+	int irq;
+
+	nuc900fb_stop_lcd(fbinfo);
+	msleep(1);
+
+	unregister_framebuffer(fbinfo);
+	nuc900fb_cpufreq_deregister(fbi);
+	nuc900fb_unmap_video_memory(fbinfo);
+
+	iounmap(fbi->io);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, fbi);
+
+	release_resource(fbi->mem);
+	kfree(fbi->mem);
+
+	framebuffer_release(fbinfo);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+/*
+ *	suspend and resume support for the lcd controller
+ */
+
+static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
+	struct nuc900fb_info *info = fbinfo->par;
+
+	nuc900fb_stop_lcd(fbinfo);
+	msleep(1);
+	clk_disable(info->clk);
+	return 0;
+}
+
+static int nuc900fb_resume(struct platform_device *dev)
+{
+	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
+	struct nuc900fb_info *fbi = fbinfo->par;
+
+	printk(KERN_INFO "nuc900fb resume\n");
+
+	clk_enable(fbi->clk);
+	msleep(1);
+
+	nuc900fb_init_registers(fbinfo);
+	nuc900fb_activate_var(fbinfo);
+
+	return 0;
+}
+
+#else
+#define nuc900fb_suspend NULL
+#define nuc900fb_resume  NULL
+#endif
+
+static struct platform_driver nuc900fb_driver = {
+	.probe		= nuc900fb_probe,
+	.remove		= nuc900fb_remove,
+	.suspend	= nuc900fb_suspend,
+	.resume		= nuc900fb_resume,
+	.driver		= {
+		.name	= "nuc900-lcd",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(nuc900fb_driver);
+
+MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/nuc900fb.h b/drivers/video/fbdev/nuc900fb.h
new file mode 100644
index 000000000000..9a1ca6dbb6b2
--- /dev/null
+++ b/drivers/video/fbdev/nuc900fb.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2009 Nuvoton technology corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *   Author:
+ *        Wang Qiang(rurality.linux@gmail.com)  2009/12/16
+ */
+
+#ifndef __NUC900FB_H
+#define __NUC900FB_H
+
+#include <mach/map.h>
+#include <linux/platform_data/video-nuc900fb.h>
+
+enum nuc900_lcddrv_type {
+	LCDDRV_NUC910,
+	LCDDRV_NUC930,
+	LCDDRV_NUC932,
+	LCDDRV_NUC950,
+	LCDDRV_NUC960,
+};
+
+
+#define PALETTE_BUFFER_SIZE	256
+#define PALETTE_BUFF_CLEAR 	(0x80000000) /* entry is clear/invalid */
+
+struct nuc900fb_info {
+	struct device		*dev;
+	struct clk		*clk;
+
+	struct resource		*mem;
+	void __iomem		*io;
+	void __iomem		*irq_base;
+	int 			drv_type;
+	struct nuc900fb_hw	regs;
+	unsigned long		clk_rate;
+
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+#endif
+
+	/* keep these registers in case we need to re-write palette */
+	u32			palette_buffer[PALETTE_BUFFER_SIZE];
+	u32			pseudo_pal[16];
+};
+
+int nuc900fb_init(void);
+
+#endif /* __NUC900FB_H */
diff --git a/drivers/video/fbdev/nvidia/Makefile b/drivers/video/fbdev/nvidia/Makefile
new file mode 100644
index 000000000000..ca47432113e0
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the nVidia framebuffer driver
+#
+
+obj-$(CONFIG_FB_NVIDIA)          += nvidiafb.o
+
+nvidiafb-y                       := nvidia.o nv_hw.o nv_setup.o \
+			            nv_accel.o
+nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
+nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT)  += nv_backlight.o
+nvidiafb-$(CONFIG_PPC_OF)	 += nv_of.o
+
+nvidiafb-objs                    := $(nvidiafb-y)
diff --git a/drivers/video/fbdev/nvidia/nv_accel.c b/drivers/video/fbdev/nvidia/nv_accel.c
new file mode 100644
index 000000000000..ad6472a894ea
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_accel.c
@@ -0,0 +1,416 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#include <linux/fb.h>
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+#include "nv_local.h"
+
+/* There is a HW race condition with videoram command buffers.
+   You can't jump to the location of your put offset.  We write put
+   at the jump offset + SKIPS dwords with noop padding in between
+   to solve this problem */
+#define SKIPS  8
+
+static const int NVCopyROP[16] = {
+	0xCC,			/* copy   */
+	0x55			/* invert */
+};
+
+static const int NVCopyROP_PM[16] = {
+	0xCA,			/* copy  */
+	0x5A,			/* invert */
+};
+
+static inline void nvidiafb_safe_mode(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+
+	touch_softlockup_watchdog();
+	info->pixmap.scan_align = 1;
+	par->lockup = 1;
+}
+
+static inline void NVFlush(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int count = 1000000000;
+
+	while (--count && READ_GET(par) != par->dmaPut) ;
+
+	if (!count) {
+		printk("nvidiafb: DMA Flush lockup\n");
+		nvidiafb_safe_mode(info);
+	}
+}
+
+static inline void NVSync(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int count = 1000000000;
+
+	while (--count && NV_RD32(par->PGRAPH, 0x0700)) ;
+
+	if (!count) {
+		printk("nvidiafb: DMA Sync lockup\n");
+		nvidiafb_safe_mode(info);
+	}
+}
+
+static void NVDmaKickoff(struct nvidia_par *par)
+{
+	if (par->dmaCurrent != par->dmaPut) {
+		par->dmaPut = par->dmaCurrent;
+		WRITE_PUT(par, par->dmaPut);
+	}
+}
+
+static void NVDmaWait(struct fb_info *info, int size)
+{
+	struct nvidia_par *par = info->par;
+	int dmaGet;
+	int count = 1000000000, cnt;
+	size++;
+
+	while (par->dmaFree < size && --count && !par->lockup) {
+		dmaGet = READ_GET(par);
+
+		if (par->dmaPut >= dmaGet) {
+			par->dmaFree = par->dmaMax - par->dmaCurrent;
+			if (par->dmaFree < size) {
+				NVDmaNext(par, 0x20000000);
+				if (dmaGet <= SKIPS) {
+					if (par->dmaPut <= SKIPS)
+						WRITE_PUT(par, SKIPS + 1);
+					cnt = 1000000000;
+					do {
+						dmaGet = READ_GET(par);
+					} while (--cnt && dmaGet <= SKIPS);
+					if (!cnt) {
+						printk("DMA Get lockup\n");
+						par->lockup = 1;
+					}
+				}
+				WRITE_PUT(par, SKIPS);
+				par->dmaCurrent = par->dmaPut = SKIPS;
+				par->dmaFree = dmaGet - (SKIPS + 1);
+			}
+		} else
+			par->dmaFree = dmaGet - par->dmaCurrent - 1;
+	}
+
+	if (!count) {
+		printk("nvidiafb: DMA Wait Lockup\n");
+		nvidiafb_safe_mode(info);
+	}
+}
+
+static void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1,
+			 u32 pat0, u32 pat1)
+{
+	struct nvidia_par *par = info->par;
+
+	NVDmaStart(info, par, PATTERN_COLOR_0, 4);
+	NVDmaNext(par, clr0);
+	NVDmaNext(par, clr1);
+	NVDmaNext(par, pat0);
+	NVDmaNext(par, pat1);
+}
+
+static void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask)
+{
+	struct nvidia_par *par = info->par;
+
+	if (planemask != ~0) {
+		NVSetPattern(info, 0, planemask, ~0, ~0);
+		if (par->currentRop != (rop + 32)) {
+			NVDmaStart(info, par, ROP_SET, 1);
+			NVDmaNext(par, NVCopyROP_PM[rop]);
+			par->currentRop = rop + 32;
+		}
+	} else if (par->currentRop != rop) {
+		if (par->currentRop >= 16)
+			NVSetPattern(info, ~0, ~0, ~0, ~0);
+		NVDmaStart(info, par, ROP_SET, 1);
+		NVDmaNext(par, NVCopyROP[rop]);
+		par->currentRop = rop;
+	}
+}
+
+static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1,
+				   int x2, int y2)
+{
+	struct nvidia_par *par = info->par;
+	int h = y2 - y1 + 1;
+	int w = x2 - x1 + 1;
+
+	NVDmaStart(info, par, CLIP_POINT, 2);
+	NVDmaNext(par, (y1 << 16) | x1);
+	NVDmaNext(par, (h << 16) | w);
+}
+
+void NVResetGraphics(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 surfaceFormat, patternFormat, rectFormat, lineFormat;
+	int pitch, i;
+
+	pitch = info->fix.line_length;
+
+	par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]);
+
+	for (i = 0; i < SKIPS; i++)
+		NV_WR32(&par->dmaBase[i], 0, 0x00000000);
+
+	NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000);
+	NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010);
+	NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000);
+	NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011);
+	NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000);
+	NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012);
+	NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000);
+	NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013);
+	NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000);
+	NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014);
+	NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000);
+	NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015);
+	NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000);
+	NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016);
+	NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000);
+	NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017);
+
+	par->dmaPut = 0;
+	par->dmaCurrent = 16 + SKIPS;
+	par->dmaMax = 8191;
+	par->dmaFree = par->dmaMax - par->dmaCurrent;
+
+	switch (info->var.bits_per_pixel) {
+	case 32:
+	case 24:
+		surfaceFormat = SURFACE_FORMAT_DEPTH24;
+		patternFormat = PATTERN_FORMAT_DEPTH24;
+		rectFormat = RECT_FORMAT_DEPTH24;
+		lineFormat = LINE_FORMAT_DEPTH24;
+		break;
+	case 16:
+		surfaceFormat = SURFACE_FORMAT_DEPTH16;
+		patternFormat = PATTERN_FORMAT_DEPTH16;
+		rectFormat = RECT_FORMAT_DEPTH16;
+		lineFormat = LINE_FORMAT_DEPTH16;
+		break;
+	default:
+		surfaceFormat = SURFACE_FORMAT_DEPTH8;
+		patternFormat = PATTERN_FORMAT_DEPTH8;
+		rectFormat = RECT_FORMAT_DEPTH8;
+		lineFormat = LINE_FORMAT_DEPTH8;
+		break;
+	}
+
+	NVDmaStart(info, par, SURFACE_FORMAT, 4);
+	NVDmaNext(par, surfaceFormat);
+	NVDmaNext(par, pitch | (pitch << 16));
+	NVDmaNext(par, 0);
+	NVDmaNext(par, 0);
+
+	NVDmaStart(info, par, PATTERN_FORMAT, 1);
+	NVDmaNext(par, patternFormat);
+
+	NVDmaStart(info, par, RECT_FORMAT, 1);
+	NVDmaNext(par, rectFormat);
+
+	NVDmaStart(info, par, LINE_FORMAT, 1);
+	NVDmaNext(par, lineFormat);
+
+	par->currentRop = ~0;	/* set to something invalid */
+	NVSetRopSolid(info, ROP_COPY, ~0);
+
+	NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual,
+			       info->var.yres_virtual);
+
+	NVDmaKickoff(par);
+}
+
+int nvidiafb_sync(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return 0;
+
+	if (!par->lockup)
+		NVFlush(info);
+
+	if (!par->lockup)
+		NVSync(info);
+
+	return 0;
+}
+
+void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct nvidia_par *par = info->par;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (par->lockup) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
+	NVDmaStart(info, par, BLIT_POINT_SRC, 3);
+	NVDmaNext(par, (region->sy << 16) | region->sx);
+	NVDmaNext(par, (region->dy << 16) | region->dx);
+	NVDmaNext(par, (region->height << 16) | region->width);
+
+	NVDmaKickoff(par);
+}
+
+void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct nvidia_par *par = info->par;
+	u32 color;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (par->lockup) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if (info->var.bits_per_pixel == 8)
+		color = rect->color;
+	else
+		color = ((u32 *) info->pseudo_palette)[rect->color];
+
+	if (rect->rop != ROP_COPY)
+		NVSetRopSolid(info, rect->rop, ~0);
+
+	NVDmaStart(info, par, RECT_SOLID_COLOR, 1);
+	NVDmaNext(par, color);
+
+	NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2);
+	NVDmaNext(par, (rect->dx << 16) | rect->dy);
+	NVDmaNext(par, (rect->width << 16) | rect->height);
+
+	NVDmaKickoff(par);
+
+	if (rect->rop != ROP_COPY)
+		NVSetRopSolid(info, ROP_COPY, ~0);
+}
+
+static void nvidiafb_mono_color_expand(struct fb_info *info,
+				       const struct fb_image *image)
+{
+	struct nvidia_par *par = info->par;
+	u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
+	u32 dsize, width, *data = (u32 *) image->data, tmp;
+	int j, k = 0;
+
+	width = (image->width + 31) & ~31;
+	dsize = (width * image->height) >> 5;
+
+	if (info->var.bits_per_pixel == 8) {
+		fg = image->fg_color | mask;
+		bg = image->bg_color | mask;
+	} else {
+		fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask;
+		bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask;
+	}
+
+	NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
+	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+	NVDmaNext(par, ((image->dy + image->height) << 16) |
+		  ((image->dx + image->width) & 0xffff));
+	NVDmaNext(par, bg);
+	NVDmaNext(par, fg);
+	NVDmaNext(par, (image->height << 16) | width);
+	NVDmaNext(par, (image->height << 16) | width);
+	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+
+	while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
+		NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0),
+			   RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
+
+		for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
+			tmp = data[k++];
+			reverse_order(&tmp);
+			NVDmaNext(par, tmp);
+		}
+
+		dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS;
+	}
+
+	if (dsize) {
+		NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
+
+		for (j = dsize; j--;) {
+			tmp = data[k++];
+			reverse_order(&tmp);
+			NVDmaNext(par, tmp);
+		}
+	}
+
+	NVDmaKickoff(par);
+}
+
+void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct nvidia_par *par = info->par;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (image->depth == 1 && !par->lockup)
+		nvidiafb_mono_color_expand(info, image);
+	else
+		cfb_imageblit(info, image);
+}
diff --git a/drivers/video/fbdev/nvidia/nv_backlight.c b/drivers/video/fbdev/nvidia/nv_backlight.c
new file mode 100644
index 000000000000..8471008aa6ff
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_backlight.c
@@ -0,0 +1,148 @@
+/*
+ * Backlight code for nVidia based graphic cards
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
+#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
+
+static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
+		int level)
+{
+	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+	int nlevel;
+
+	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
+	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
+
+	if (nlevel < 0)
+		nlevel = 0;
+	else if (nlevel < MIN_LEVEL)
+		nlevel = MIN_LEVEL;
+	else if (nlevel > MAX_LEVEL)
+		nlevel = MAX_LEVEL;
+
+	return nlevel;
+}
+
+static int nvidia_bl_update_status(struct backlight_device *bd)
+{
+	struct nvidia_par *par = bl_get_data(bd);
+	u32 tmp_pcrt, tmp_pmc, fpcontrol;
+	int level;
+
+	if (!par->FlatPanel)
+		return 0;
+
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props.brightness;
+
+	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
+	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
+	fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
+
+	if (level > 0) {
+		tmp_pcrt |= 0x1;
+		tmp_pmc |= (1 << 31); /* backlight bit */
+		tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
+		fpcontrol |= par->fpSyncs;
+	} else
+		fpcontrol |= 0x20000022;
+
+	NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
+	NV_WR32(par->PMC, 0x10F0, tmp_pmc);
+	NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
+
+	return 0;
+}
+
+static int nvidia_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops nvidia_bl_ops = {
+	.get_brightness = nvidia_bl_get_brightness,
+	.update_status	= nvidia_bl_update_status,
+};
+
+void nvidia_bl_init(struct nvidia_par *par)
+{
+	struct backlight_properties props;
+	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+	struct backlight_device *bd;
+	char name[12];
+
+	if (!par->FlatPanel)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!machine_is(powermac) ||
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	snprintf(name, sizeof(name), "nvidiabl%d", info->node);
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
+				       &props);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk(KERN_WARNING "nvidia: Backlight registration failed\n");
+		goto error;
+	}
+
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+		0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	printk("nvidia: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+void nvidia_bl_exit(struct nvidia_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+	struct backlight_device *bd = info->bl_dev;
+
+	backlight_device_unregister(bd);
+	printk("nvidia: Backlight unloaded\n");
+}
diff --git a/drivers/video/fbdev/nvidia/nv_dma.h b/drivers/video/fbdev/nvidia/nv_dma.h
new file mode 100644
index 000000000000..a7ed1c0acbbb
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_dma.h
@@ -0,0 +1,188 @@
+
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#define SURFACE_FORMAT                                              0x00000300
+#define SURFACE_FORMAT_DEPTH8                                       0x00000001
+#define SURFACE_FORMAT_DEPTH15                                      0x00000002
+#define SURFACE_FORMAT_DEPTH16                                      0x00000004
+#define SURFACE_FORMAT_DEPTH24                                      0x00000006
+#define SURFACE_PITCH                                               0x00000304
+#define SURFACE_PITCH_SRC                                           15:0
+#define SURFACE_PITCH_DST                                           31:16
+#define SURFACE_OFFSET_SRC                                          0x00000308
+#define SURFACE_OFFSET_DST                                          0x0000030C
+
+#define ROP_SET                                                     0x00002300
+
+#define PATTERN_FORMAT                                              0x00004300
+#define PATTERN_FORMAT_DEPTH8                                       0x00000003
+#define PATTERN_FORMAT_DEPTH16                                      0x00000001
+#define PATTERN_FORMAT_DEPTH24                                      0x00000003
+#define PATTERN_COLOR_0                                             0x00004310
+#define PATTERN_COLOR_1                                             0x00004314
+#define PATTERN_PATTERN_0                                           0x00004318
+#define PATTERN_PATTERN_1                                           0x0000431C
+
+#define CLIP_POINT                                                  0x00006300
+#define CLIP_POINT_X                                                15:0
+#define CLIP_POINT_Y                                                31:16
+#define CLIP_SIZE                                                   0x00006304
+#define CLIP_SIZE_WIDTH                                             15:0
+#define CLIP_SIZE_HEIGHT                                            31:16
+
+#define LINE_FORMAT                                                 0x00008300
+#define LINE_FORMAT_DEPTH8                                          0x00000003
+#define LINE_FORMAT_DEPTH16                                         0x00000001
+#define LINE_FORMAT_DEPTH24                                         0x00000003
+#define LINE_COLOR                                                  0x00008304
+#define LINE_MAX_LINES                                              16
+#define LINE_LINES(i)                                               0x00008400\
+                                                                    +(i)*8
+#define LINE_LINES_POINT0_X                                         15:0
+#define LINE_LINES_POINT0_Y                                         31:16
+#define LINE_LINES_POINT1_X                                         47:32
+#define LINE_LINES_POINT1_Y                                         63:48
+
+#define BLIT_POINT_SRC                                              0x0000A300
+#define BLIT_POINT_SRC_X                                            15:0
+#define BLIT_POINT_SRC_Y                                            31:16
+#define BLIT_POINT_DST                                              0x0000A304
+#define BLIT_POINT_DST_X                                            15:0
+#define BLIT_POINT_DST_Y                                            31:16
+#define BLIT_SIZE                                                   0x0000A308
+#define BLIT_SIZE_WIDTH                                             15:0
+#define BLIT_SIZE_HEIGHT                                            31:16
+
+#define RECT_FORMAT                                                 0x0000C300
+#define RECT_FORMAT_DEPTH8                                          0x00000003
+#define RECT_FORMAT_DEPTH16                                         0x00000001
+#define RECT_FORMAT_DEPTH24                                         0x00000003
+#define RECT_SOLID_COLOR                                            0x0000C3FC
+#define RECT_SOLID_RECTS_MAX_RECTS                                  32
+#define RECT_SOLID_RECTS(i)                                         0x0000C400\
+                                                                    +(i)*8
+#define RECT_SOLID_RECTS_Y                                          15:0
+#define RECT_SOLID_RECTS_X                                          31:16
+#define RECT_SOLID_RECTS_HEIGHT                                     47:32
+#define RECT_SOLID_RECTS_WIDTH                                      63:48
+
+#define RECT_EXPAND_ONE_COLOR_CLIP                                  0x0000C7EC
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_ONE_COLOR_COLOR                                 0x0000C7F4
+#define RECT_EXPAND_ONE_COLOR_SIZE                                  0x0000C7F8
+#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH                            15:0
+#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT                           31:16
+#define RECT_EXPAND_ONE_COLOR_POINT                                 0x0000C7FC
+#define RECT_EXPAND_ONE_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_ONE_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_ONE_COLOR_DATA(i)                               0x0000C800\
+                                                                    +(i)*4
+
+#define RECT_EXPAND_TWO_COLOR_CLIP                                  0x0000CBE4
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_TWO_COLOR_COLOR_0                               0x0000CBEC
+#define RECT_EXPAND_TWO_COLOR_COLOR_1                               0x0000CBF0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN                               0x0000CBF4
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH                         15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT                        31:16
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT                              0x0000CBF8
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH                        15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT                       31:16
+#define RECT_EXPAND_TWO_COLOR_POINT                                 0x0000CBFC
+#define RECT_EXPAND_TWO_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_TWO_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_TWO_COLOR_DATA(i)                               0x0000CC00\
+                                                                    +(i)*4
+
+#define STRETCH_BLIT_FORMAT                                         0x0000E300
+#define STRETCH_BLIT_FORMAT_DEPTH8                                  0x00000004
+#define STRETCH_BLIT_FORMAT_DEPTH16                                 0x00000007
+#define STRETCH_BLIT_FORMAT_DEPTH24                                 0x00000004
+#define STRETCH_BLIT_FORMAT_X8R8G8B8                                0x00000004
+#define STRETCH_BLIT_FORMAT_YUYV                                    0x00000005
+#define STRETCH_BLIT_FORMAT_UYVY                                    0x00000006
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_POINT_X                                   15:0
+#define STRETCH_BLIT_CLIP_POINT_Y                                   31:16
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_SIZE                                      0x0000E30C
+#define STRETCH_BLIT_CLIP_SIZE_WIDTH                                15:0
+#define STRETCH_BLIT_CLIP_SIZE_HEIGHT                               31:16
+#define STRETCH_BLIT_DST_POINT                                      0x0000E310
+#define STRETCH_BLIT_DST_POINT_X                                    15:0
+#define STRETCH_BLIT_DST_POINT_Y                                    31:16
+#define STRETCH_BLIT_DST_SIZE                                       0x0000E314
+#define STRETCH_BLIT_DST_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_DST_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_DU_DX                                          0x0000E318
+#define STRETCH_BLIT_DV_DY                                          0x0000E31C
+#define STRETCH_BLIT_SRC_SIZE                                       0x0000E400
+#define STRETCH_BLIT_SRC_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_SRC_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_SRC_FORMAT                                     0x0000E404
+#define STRETCH_BLIT_SRC_FORMAT_PITCH                               15:0
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN                              23:16
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER                       0x00000001
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER                       0x00000002
+#define STRETCH_BLIT_SRC_FORMAT_FILTER                              31:24
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE                 0x00000000
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR                     0x00000001
+#define STRETCH_BLIT_SRC_OFFSET                                     0x0000E408
+#define STRETCH_BLIT_SRC_POINT                                      0x0000E40C
+#define STRETCH_BLIT_SRC_POINT_U                                    15:0
+#define STRETCH_BLIT_SRC_POINT_V                                    31:16
diff --git a/drivers/video/fbdev/nvidia/nv_hw.c b/drivers/video/fbdev/nvidia/nv_hw.c
new file mode 100644
index 000000000000..81c80ac3c76f
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_hw.c
@@ -0,0 +1,1687 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */
+
+#include <linux/pci.h>
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+void NVLockUnlock(struct nvidia_par *par, int Lock)
+{
+	u8 cr11;
+
+	VGA_WR08(par->PCIO, 0x3D4, 0x1F);
+	VGA_WR08(par->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
+
+	VGA_WR08(par->PCIO, 0x3D4, 0x11);
+	cr11 = VGA_RD08(par->PCIO, 0x3D5);
+	if (Lock)
+		cr11 |= 0x80;
+	else
+		cr11 &= ~0x80;
+	VGA_WR08(par->PCIO, 0x3D5, cr11);
+}
+
+int NVShowHideCursor(struct nvidia_par *par, int ShowHide)
+{
+	int cur = par->CurrentState->cursor1;
+
+	par->CurrentState->cursor1 = (par->CurrentState->cursor1 & 0xFE) |
+	    (ShowHide & 0x01);
+	VGA_WR08(par->PCIO, 0x3D4, 0x31);
+	VGA_WR08(par->PCIO, 0x3D5, par->CurrentState->cursor1);
+
+	if (par->Architecture == NV_ARCH_40)
+		NV_WR32(par->PRAMDAC, 0x0300, NV_RD32(par->PRAMDAC, 0x0300));
+
+	return (cur & 0x01);
+}
+
+/****************************************************************************\
+*                                                                            *
+* The video arbitration routines calculate some "magic" numbers.  Fixes      *
+* the snow seen when accessing the framebuffer without it.                   *
+* It just works (I hope).                                                    *
+*                                                                            *
+\****************************************************************************/
+
+typedef struct {
+	int graphics_lwm;
+	int video_lwm;
+	int graphics_burst_size;
+	int video_burst_size;
+	int valid;
+} nv4_fifo_info;
+
+typedef struct {
+	int pclk_khz;
+	int mclk_khz;
+	int nvclk_khz;
+	char mem_page_miss;
+	char mem_latency;
+	int memory_width;
+	char enable_video;
+	char gr_during_vid;
+	char pix_bpp;
+	char mem_aligned;
+	char enable_mp;
+} nv4_sim_state;
+
+typedef struct {
+	int graphics_lwm;
+	int video_lwm;
+	int graphics_burst_size;
+	int video_burst_size;
+	int valid;
+} nv10_fifo_info;
+
+typedef struct {
+	int pclk_khz;
+	int mclk_khz;
+	int nvclk_khz;
+	char mem_page_miss;
+	char mem_latency;
+	u32 memory_type;
+	int memory_width;
+	char enable_video;
+	char gr_during_vid;
+	char pix_bpp;
+	char mem_aligned;
+	char enable_mp;
+} nv10_sim_state;
+
+static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
+			unsigned int *NVClk)
+{
+	unsigned int pll, N, M, MB, NB, P;
+
+	if (par->Architecture >= NV_ARCH_40) {
+		pll = NV_RD32(par->PMC, 0x4020);
+		P = (pll >> 16) & 0x07;
+		pll = NV_RD32(par->PMC, 0x4024);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		if (((par->Chipset & 0xfff0) == 0x0290) ||
+		    ((par->Chipset & 0xfff0) == 0x0390)) {
+			MB = 1;
+			NB = 1;
+		} else {
+			MB = (pll >> 16) & 0xFF;
+			NB = (pll >> 24) & 0xFF;
+		}
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PMC, 0x4000);
+		P = (pll >> 16) & 0x07;
+		pll = NV_RD32(par->PMC, 0x4004);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		MB = (pll >> 16) & 0xFF;
+		NB = (pll >> 24) & 0xFF;
+
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else if (par->twoStagePLL) {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		pll = NV_RD32(par->PRAMDAC0, 0x0574);
+		if (pll & 0x80000000) {
+			MB = pll & 0xFF;
+			NB = (pll >> 8) & 0xFF;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		pll = NV_RD32(par->PRAMDAC0, 0x0570);
+		if (pll & 0x80000000) {
+			MB = pll & 0xFF;
+			NB = (pll >> 8) & 0xFF;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else
+	    if (((par->Chipset & 0x0ff0) == 0x0300) ||
+		((par->Chipset & 0x0ff0) == 0x0330)) {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0x0F;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x07;
+		if (pll & 0x00000080) {
+			MB = (pll >> 4) & 0x07;
+			NB = (pll >> 19) & 0x1f;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0x0F;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x07;
+		if (pll & 0x00000080) {
+			MB = (pll >> 4) & 0x07;
+			NB = (pll >> 19) & 0x1f;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		*MClk = (N * par->CrystalFreqKHz / M) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		*NVClk = (N * par->CrystalFreqKHz / M) >> P;
+	}
+}
+
+static void nv4CalcArbitration(nv4_fifo_info * fifo, nv4_sim_state * arb)
+{
+	int data, pagemiss, cas, width, video_enable, bpp;
+	int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+	int found, mclk_extra, mclk_loop, cbs, m1, p1;
+	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+	int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
+	int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
+
+	fifo->valid = 1;
+	pclk_freq = arb->pclk_khz;
+	mclk_freq = arb->mclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	pagemiss = arb->mem_page_miss;
+	cas = arb->mem_latency;
+	width = arb->memory_width >> 6;
+	video_enable = arb->enable_video;
+	bpp = arb->pix_bpp;
+	mp_enable = arb->enable_mp;
+	clwm = 0;
+	vlwm = 0;
+	cbs = 128;
+	pclks = 2;
+	nvclks = 2;
+	nvclks += 2;
+	nvclks += 1;
+	mclks = 5;
+	mclks += 3;
+	mclks += 1;
+	mclks += cas;
+	mclks += 1;
+	mclks += 1;
+	mclks += 1;
+	mclks += 1;
+	mclk_extra = 3;
+	nvclks += 2;
+	nvclks += 1;
+	nvclks += 1;
+	nvclks += 1;
+	if (mp_enable)
+		mclks += 4;
+	nvclks += 0;
+	pclks += 0;
+	found = 0;
+	vbs = 0;
+	while (found != 1) {
+		fifo->valid = 1;
+		found = 1;
+		mclk_loop = mclks + mclk_extra;
+		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+		us_n = nvclks * 1000 * 1000 / nvclk_freq;
+		us_p = nvclks * 1000 * 1000 / pclk_freq;
+		if (video_enable) {
+			video_drain_rate = pclk_freq * 2;
+			crtc_drain_rate = pclk_freq * bpp / 8;
+			vpagemiss = 2;
+			vpagemiss += 1;
+			crtpagemiss = 2;
+			vpm_us =
+			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+			if (nvclk_freq * 2 > mclk_freq * width)
+				video_fill_us =
+				    cbs * 1000 * 1000 / 16 / nvclk_freq;
+			else
+				video_fill_us =
+				    cbs * 1000 * 1000 / (8 * width) /
+				    mclk_freq;
+			us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
+			vlwm = us_video * video_drain_rate / (1000 * 1000);
+			vlwm++;
+			vbs = 128;
+			if (vlwm > 128)
+				vbs = 64;
+			if (vlwm > (256 - 64))
+				vbs = 32;
+			if (nvclk_freq * 2 > mclk_freq * width)
+				video_fill_us =
+				    vbs * 1000 * 1000 / 16 / nvclk_freq;
+			else
+				video_fill_us =
+				    vbs * 1000 * 1000 / (8 * width) /
+				    mclk_freq;
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt =
+			    us_video + video_fill_us + cpm_us + us_m + us_n +
+			    us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			clwm++;
+		} else {
+			crtc_drain_rate = pclk_freq * bpp / 8;
+			crtpagemiss = 2;
+			crtpagemiss += 1;
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt = cpm_us + us_m + us_n + us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			clwm++;
+		}
+		m1 = clwm + cbs - 512;
+		p1 = m1 * pclk_freq / mclk_freq;
+		p1 = p1 * bpp / 8;
+		if ((p1 < m1) && (m1 > 0)) {
+			fifo->valid = 0;
+			found = 0;
+			if (mclk_extra == 0)
+				found = 1;
+			mclk_extra--;
+		} else if (video_enable) {
+			if ((clwm > 511) || (vlwm > 255)) {
+				fifo->valid = 0;
+				found = 0;
+				if (mclk_extra == 0)
+					found = 1;
+				mclk_extra--;
+			}
+		} else {
+			if (clwm > 519) {
+				fifo->valid = 0;
+				found = 0;
+				if (mclk_extra == 0)
+					found = 1;
+				mclk_extra--;
+			}
+		}
+		if (clwm < 384)
+			clwm = 384;
+		if (vlwm < 128)
+			vlwm = 128;
+		data = (int)(clwm);
+		fifo->graphics_lwm = data;
+		fifo->graphics_burst_size = 128;
+		data = (int)((vlwm + 15));
+		fifo->video_lwm = data;
+		fifo->video_burst_size = vbs;
+	}
+}
+
+static void nv4UpdateArbitrationSettings(unsigned VClk,
+					 unsigned pixelDepth,
+					 unsigned *burst,
+					 unsigned *lwm, struct nvidia_par *par)
+{
+	nv4_fifo_info fifo_data;
+	nv4_sim_state sim_data;
+	unsigned int MClk, NVClk, cfg1;
+
+	nvGetClocks(par, &MClk, &NVClk);
+
+	cfg1 = NV_RD32(par->PFB, 0x00000204);
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 0;
+	sim_data.enable_mp = 0;
+	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+	    128 : 64;
+	sim_data.mem_latency = (char)cfg1 & 0x0F;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss =
+	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv4CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+static void nv10CalcArbitration(nv10_fifo_info * fifo, nv10_sim_state * arb)
+{
+	int data, pagemiss, width, video_enable, bpp;
+	int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
+	int nvclk_fill;
+	int found, mclk_extra, mclk_loop, cbs, m1;
+	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+	int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
+	int vus_m;
+	int vpm_us, us_video, cpm_us, us_crt, clwm;
+	int clwm_rnd_down;
+	int m2us, us_pipe_min, p1clk, p2;
+	int min_mclk_extra;
+	int us_min_mclk_extra;
+
+	fifo->valid = 1;
+	pclk_freq = arb->pclk_khz;	/* freq in KHz */
+	mclk_freq = arb->mclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	pagemiss = arb->mem_page_miss;
+	width = arb->memory_width / 64;
+	video_enable = arb->enable_video;
+	bpp = arb->pix_bpp;
+	mp_enable = arb->enable_mp;
+	clwm = 0;
+
+	cbs = 512;
+
+	pclks = 4;	/* lwm detect. */
+
+	nvclks = 3;	/* lwm -> sync. */
+	nvclks += 2;	/* fbi bus cycles (1 req + 1 busy) */
+	/* 2 edge sync.  may be very close to edge so just put one. */
+	mclks = 1;
+	mclks += 1;	/* arb_hp_req */
+	mclks += 5;	/* ap_hp_req   tiling pipeline */
+
+	mclks += 2;	/* tc_req     latency fifo */
+	mclks += 2;	/* fb_cas_n_  memory request to fbio block */
+	mclks += 7;	/* sm_d_rdv   data returned from fbio block */
+
+	/* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
+	if (arb->memory_type == 0)
+		if (arb->memory_width == 64)	/* 64 bit bus */
+			mclks += 4;
+		else
+			mclks += 2;
+	else if (arb->memory_width == 64)	/* 64 bit bus */
+		mclks += 2;
+	else
+		mclks += 1;
+
+	if ((!video_enable) && (arb->memory_width == 128)) {
+		mclk_extra = (bpp == 32) ? 31 : 42;	/* Margin of error */
+		min_mclk_extra = 17;
+	} else {
+		mclk_extra = (bpp == 32) ? 8 : 4;	/* Margin of error */
+		/* mclk_extra = 4; *//* Margin of error */
+		min_mclk_extra = 18;
+	}
+
+	/* 2 edge sync.  may be very close to edge so just put one. */
+	nvclks += 1;
+	nvclks += 1;		/* fbi_d_rdv_n */
+	nvclks += 1;		/* Fbi_d_rdata */
+	nvclks += 1;		/* crtfifo load */
+
+	if (mp_enable)
+		mclks += 4;	/* Mp can get in with a burst of 8. */
+	/* Extra clocks determined by heuristics */
+
+	nvclks += 0;
+	pclks += 0;
+	found = 0;
+	while (found != 1) {
+		fifo->valid = 1;
+		found = 1;
+		mclk_loop = mclks + mclk_extra;
+		/* Mclk latency in us */
+		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+		/* Minimum Mclk latency in us */
+		us_m_min = mclks * 1000 * 1000 / mclk_freq;
+		us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
+		/* nvclk latency in us */
+		us_n = nvclks * 1000 * 1000 / nvclk_freq;
+		/* nvclk latency in us */
+		us_p = pclks * 1000 * 1000 / pclk_freq;
+		us_pipe_min = us_m_min + us_n + us_p;
+
+		/* Mclk latency in us */
+		vus_m = mclk_loop * 1000 * 1000 / mclk_freq;
+
+		if (video_enable) {
+			crtc_drain_rate = pclk_freq * bpp / 8;	/* MB/s */
+
+			vpagemiss = 1;	/* self generating page miss */
+			vpagemiss += 1;	/* One higher priority before */
+
+			crtpagemiss = 2;	/* self generating page miss */
+			if (mp_enable)
+				crtpagemiss += 1;	/* if MA0 conflict */
+
+			vpm_us =
+			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+
+			/* Video has separate read return path */
+			us_video = vpm_us + vus_m;
+
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			/* Wait for video */
+			us_crt = us_video
+			    + cpm_us	/* CRT Page miss */
+			    + us_m + us_n + us_p	/* other latency */
+			    ;
+
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			/* fixed point <= float_point - 1.  Fixes that */
+			clwm++;
+		} else {
+		    /* bpp * pclk/8 */
+			crtc_drain_rate = pclk_freq * bpp / 8;
+
+			crtpagemiss = 1;	/* self generating page miss */
+			crtpagemiss += 1;	/* MA0 page miss */
+			if (mp_enable)
+				crtpagemiss += 1;	/* if MA0 conflict */
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt = cpm_us + us_m + us_n + us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			/* fixed point <= float_point - 1.  Fixes that */
+			clwm++;
+
+			/* Finally, a heuristic check when width == 64 bits */
+			if (width == 1) {
+				nvclk_fill = nvclk_freq * 8;
+				if (crtc_drain_rate * 100 >= nvclk_fill * 102)
+					/*Large number to fail */
+					clwm = 0xfff;
+
+				else if (crtc_drain_rate * 100 >=
+					 nvclk_fill * 98) {
+					clwm = 1024;
+					cbs = 512;
+				}
+			}
+		}
+
+		/*
+		   Overfill check:
+		 */
+
+		clwm_rnd_down = ((int)clwm / 8) * 8;
+		if (clwm_rnd_down < clwm)
+			clwm += 8;
+
+		m1 = clwm + cbs - 1024;	/* Amount of overfill */
+		m2us = us_pipe_min + us_min_mclk_extra;
+
+		/* pclk cycles to drain */
+		p1clk = m2us * pclk_freq / (1000 * 1000);
+		p2 = p1clk * bpp / 8;	/* bytes drained. */
+
+		if ((p2 < m1) && (m1 > 0)) {
+			fifo->valid = 0;
+			found = 0;
+			if (min_mclk_extra == 0) {
+				if (cbs <= 32) {
+					/* Can't adjust anymore! */
+					found = 1;
+				} else {
+					/* reduce the burst size */
+					cbs = cbs / 2;
+				}
+			} else {
+				min_mclk_extra--;
+			}
+		} else {
+			if (clwm > 1023) {	/* Have some margin */
+				fifo->valid = 0;
+				found = 0;
+				if (min_mclk_extra == 0)
+					/* Can't adjust anymore! */
+					found = 1;
+				else
+					min_mclk_extra--;
+			}
+		}
+
+		if (clwm < (1024 - cbs + 8))
+			clwm = 1024 - cbs + 8;
+		data = (int)(clwm);
+		/*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n",
+		    clwm, data ); */
+		fifo->graphics_lwm = data;
+		fifo->graphics_burst_size = cbs;
+
+		fifo->video_lwm = 1024;
+		fifo->video_burst_size = 512;
+	}
+}
+
+static void nv10UpdateArbitrationSettings(unsigned VClk,
+					  unsigned pixelDepth,
+					  unsigned *burst,
+					  unsigned *lwm,
+					  struct nvidia_par *par)
+{
+	nv10_fifo_info fifo_data;
+	nv10_sim_state sim_data;
+	unsigned int MClk, NVClk, cfg1;
+
+	nvGetClocks(par, &MClk, &NVClk);
+
+	cfg1 = NV_RD32(par->PFB, 0x0204);
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 1;
+	sim_data.enable_mp = 0;
+	sim_data.memory_type = (NV_RD32(par->PFB, 0x0200) & 0x01) ? 1 : 0;
+	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+	    128 : 64;
+	sim_data.mem_latency = (char)cfg1 & 0x0F;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss =
+	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv10CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+static void nv30UpdateArbitrationSettings (
+    struct nvidia_par *par,
+    unsigned int      *burst,
+    unsigned int      *lwm
+)
+{
+    unsigned int MClk, NVClk;
+    unsigned int fifo_size, burst_size, graphics_lwm;
+
+    fifo_size = 2048;
+    burst_size = 512;
+    graphics_lwm = fifo_size - burst_size;
+
+    nvGetClocks(par, &MClk, &NVClk);
+
+    *burst = 0;
+    burst_size >>= 5;
+    while(burst_size >>= 1) (*burst)++;
+    *lwm = graphics_lwm >> 3;
+}
+
+static void nForceUpdateArbitrationSettings(unsigned VClk,
+					    unsigned pixelDepth,
+					    unsigned *burst,
+					    unsigned *lwm,
+					    struct nvidia_par *par)
+{
+	nv10_fifo_info fifo_data;
+	nv10_sim_state sim_data;
+	unsigned int M, N, P, pll, MClk, NVClk, memctrl;
+	struct pci_dev *dev;
+
+	if ((par->Chipset & 0x0FF0) == 0x01A0) {
+		unsigned int uMClkPostDiv;
+		dev = pci_get_bus_and_slot(0, 3);
+		pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
+		uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
+
+		if (!uMClkPostDiv)
+			uMClkPostDiv = 4;
+		MClk = 400000 / uMClkPostDiv;
+	} else {
+		dev = pci_get_bus_and_slot(0, 5);
+		pci_read_config_dword(dev, 0x4c, &MClk);
+		MClk /= 1000;
+	}
+	pci_dev_put(dev);
+	pll = NV_RD32(par->PRAMDAC0, 0x0500);
+	M = (pll >> 0) & 0xFF;
+	N = (pll >> 8) & 0xFF;
+	P = (pll >> 16) & 0x0F;
+	NVClk = (N * par->CrystalFreqKHz / M) >> P;
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 0;
+	sim_data.enable_mp = 0;
+	dev = pci_get_bus_and_slot(0, 1);
+	pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+	pci_dev_put(dev);
+	sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
+	sim_data.memory_width = 64;
+
+	dev = pci_get_bus_and_slot(0, 3);
+	pci_read_config_dword(dev, 0, &memctrl);
+	pci_dev_put(dev);
+	memctrl >>= 16;
+
+	if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
+		u32 dimm[3];
+
+		dev = pci_get_bus_and_slot(0, 2);
+		pci_read_config_dword(dev, 0x40, &dimm[0]);
+		dimm[0] = (dimm[0] >> 8) & 0x4f;
+		pci_read_config_dword(dev, 0x44, &dimm[1]);
+		dimm[1] = (dimm[1] >> 8) & 0x4f;
+		pci_read_config_dword(dev, 0x48, &dimm[2]);
+		dimm[2] = (dimm[2] >> 8) & 0x4f;
+
+		if ((dimm[0] + dimm[1]) != dimm[2]) {
+			printk("nvidiafb: your nForce DIMMs are not arranged "
+			       "in optimal banks!\n");
+		}
+		pci_dev_put(dev);
+	}
+
+	sim_data.mem_latency = 3;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss = 10;
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv10CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+/****************************************************************************\
+*                                                                            *
+*                          RIVA Mode State Routines                          *
+*                                                                            *
+\****************************************************************************/
+
+/*
+ * Calculate the Video Clock parameters for the PLL.
+ */
+static void CalcVClock(int clockIn,
+		       int *clockOut, u32 * pllOut, struct nvidia_par *par)
+{
+	unsigned lowM, highM;
+	unsigned DeltaNew, DeltaOld;
+	unsigned VClk, Freq;
+	unsigned M, N, P;
+
+	DeltaOld = 0xFFFFFFFF;
+
+	VClk = (unsigned)clockIn;
+
+	if (par->CrystalFreqKHz == 13500) {
+		lowM = 7;
+		highM = 13;
+	} else {
+		lowM = 8;
+		highM = 14;
+	}
+
+	for (P = 0; P <= 4; P++) {
+		Freq = VClk << P;
+		if ((Freq >= 128000) && (Freq <= 350000)) {
+			for (M = lowM; M <= highM; M++) {
+				N = ((VClk << P) * M) / par->CrystalFreqKHz;
+				if (N <= 255) {
+					Freq =
+					    ((par->CrystalFreqKHz * N) /
+					     M) >> P;
+					if (Freq > VClk)
+						DeltaNew = Freq - VClk;
+					else
+						DeltaNew = VClk - Freq;
+					if (DeltaNew < DeltaOld) {
+						*pllOut =
+						    (P << 16) | (N << 8) | M;
+						*clockOut = Freq;
+						DeltaOld = DeltaNew;
+					}
+				}
+			}
+		}
+	}
+}
+
+static void CalcVClock2Stage(int clockIn,
+			     int *clockOut,
+			     u32 * pllOut,
+			     u32 * pllBOut, struct nvidia_par *par)
+{
+	unsigned DeltaNew, DeltaOld;
+	unsigned VClk, Freq;
+	unsigned M, N, P;
+
+	DeltaOld = 0xFFFFFFFF;
+
+	*pllBOut = 0x80000401;	/* fixed at x4 for now */
+
+	VClk = (unsigned)clockIn;
+
+	for (P = 0; P <= 6; P++) {
+		Freq = VClk << P;
+		if ((Freq >= 400000) && (Freq <= 1000000)) {
+			for (M = 1; M <= 13; M++) {
+				N = ((VClk << P) * M) /
+				    (par->CrystalFreqKHz << 2);
+				if ((N >= 5) && (N <= 255)) {
+					Freq =
+					    (((par->CrystalFreqKHz << 2) * N) /
+					     M) >> P;
+					if (Freq > VClk)
+						DeltaNew = Freq - VClk;
+					else
+						DeltaNew = VClk - Freq;
+					if (DeltaNew < DeltaOld) {
+						*pllOut =
+						    (P << 16) | (N << 8) | M;
+						*clockOut = Freq;
+						DeltaOld = DeltaNew;
+					}
+				}
+			}
+		}
+	}
+}
+
+/*
+ * Calculate extended mode parameters (SVGA) and save in a
+ * mode state structure.
+ */
+void NVCalcStateExt(struct nvidia_par *par,
+		    RIVA_HW_STATE * state,
+		    int bpp,
+		    int width,
+		    int hDisplaySize, int height, int dotClock, int flags)
+{
+	int pixelDepth, VClk = 0;
+	/*
+	 * Save mode parameters.
+	 */
+	state->bpp = bpp;	/* this is not bitsPerPixel, it's 8,15,16,32 */
+	state->width = width;
+	state->height = height;
+	/*
+	 * Extended RIVA registers.
+	 */
+	pixelDepth = (bpp + 1) / 8;
+	if (par->twoStagePLL)
+		CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB,
+				 par);
+	else
+		CalcVClock(dotClock, &VClk, &state->pll, par);
+
+	switch (par->Architecture) {
+	case NV_ARCH_04:
+		nv4UpdateArbitrationSettings(VClk,
+					     pixelDepth * 8,
+					     &(state->arbitration0),
+					     &(state->arbitration1), par);
+		state->cursor0 = 0x00;
+		state->cursor1 = 0xbC;
+		if (flags & FB_VMODE_DOUBLE)
+			state->cursor1 |= 2;
+		state->cursor2 = 0x00000000;
+		state->pllsel = 0x10000700;
+		state->config = 0x00001114;
+		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+		break;
+	case NV_ARCH_40:
+		if (!par->FlatPanel)
+			state->control = NV_RD32(par->PRAMDAC0, 0x0580) &
+				0xeffffeff;
+		/* fallthrough */
+	case NV_ARCH_10:
+	case NV_ARCH_20:
+	case NV_ARCH_30:
+	default:
+		if ((par->Chipset & 0xfff0) == 0x0240 ||
+		    (par->Chipset & 0xfff0) == 0x03d0) {
+			state->arbitration0 = 256;
+			state->arbitration1 = 0x0480;
+		} else if (((par->Chipset & 0xffff) == 0x01A0) ||
+		    ((par->Chipset & 0xffff) == 0x01f0)) {
+			nForceUpdateArbitrationSettings(VClk,
+							pixelDepth * 8,
+							&(state->arbitration0),
+							&(state->arbitration1),
+							par);
+		} else if (par->Architecture < NV_ARCH_30) {
+			nv10UpdateArbitrationSettings(VClk,
+						      pixelDepth * 8,
+						      &(state->arbitration0),
+						      &(state->arbitration1),
+						      par);
+		} else {
+			nv30UpdateArbitrationSettings(par,
+						      &(state->arbitration0),
+						      &(state->arbitration1));
+		}
+
+		state->cursor0 = 0x80 | (par->CursorStart >> 17);
+		state->cursor1 = (par->CursorStart >> 11) << 2;
+		state->cursor2 = par->CursorStart >> 24;
+		if (flags & FB_VMODE_DOUBLE)
+			state->cursor1 |= 2;
+		state->pllsel = 0x10000700;
+		state->config = NV_RD32(par->PFB, 0x00000200);
+		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+		break;
+	}
+
+	if (bpp != 8)		/* DirectColor */
+		state->general |= 0x00000030;
+
+	state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
+	state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
+}
+
+void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
+{
+	int i, j;
+
+	NV_WR32(par->PMC, 0x0140, 0x00000000);
+	NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
+	NV_WR32(par->PMC, 0x0200, 0xFFFFFFFF);
+
+	NV_WR32(par->PTIMER, 0x0200 * 4, 0x00000008);
+	NV_WR32(par->PTIMER, 0x0210 * 4, 0x00000003);
+	NV_WR32(par->PTIMER, 0x0140 * 4, 0x00000000);
+	NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
+
+	if (par->Architecture == NV_ARCH_04) {
+		if (state)
+			NV_WR32(par->PFB, 0x0200, state->config);
+	} else if ((par->Architecture < NV_ARCH_40) ||
+		   (par->Chipset & 0xfff0) == 0x0040) {
+		for (i = 0; i < 8; i++) {
+			NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0244 + (i * 0x10),
+				par->FbMapSize - 1);
+		}
+	} else {
+		int regions = 12;
+
+		if (((par->Chipset & 0xfff0) == 0x0090) ||
+		    ((par->Chipset & 0xfff0) == 0x01D0) ||
+		    ((par->Chipset & 0xfff0) == 0x0290) ||
+		    ((par->Chipset & 0xfff0) == 0x0390) ||
+		    ((par->Chipset & 0xfff0) == 0x03D0))
+			regions = 15;
+		for(i = 0; i < regions; i++) {
+			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0604 + (i * 0x10),
+				par->FbMapSize - 1);
+		}
+	}
+
+	if (par->Architecture >= NV_ARCH_40) {
+		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x00101202);
+		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x00101204);
+		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x00101206);
+		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x00101208);
+		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x0010120A);
+		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+		NV_WR32(par->PRAMIN, 0x000B * 4, 0x0010120C);
+		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+		NV_WR32(par->PRAMIN, 0x000D * 4, 0x0010120E);
+		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+		NV_WR32(par->PRAMIN, 0x000F * 4, 0x00101210);
+		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x02080062);
+		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x080C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x02080043);
+		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0818 * 4, 0x02080044);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x02000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x02080019);
+		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0828 * 4, 0x020A005C);
+		NV_WR32(par->PRAMIN, 0x0829 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0830 * 4, 0x0208009F);
+		NV_WR32(par->PRAMIN, 0x0831 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0832 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0833 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0834 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0835 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0838 * 4, 0x0208004A);
+		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x02000000);
+		NV_WR32(par->PRAMIN, 0x083A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0840 * 4, 0x02080077);
+		NV_WR32(par->PRAMIN, 0x0841 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0842 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0843 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0844 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0845 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x084C * 4, 0x00003002);
+		NV_WR32(par->PRAMIN, 0x084D * 4, 0x00007FFF);
+		NV_WR32(par->PRAMIN, 0x084E * 4,
+			par->FbUsableSize | 0x00000002);
+
+#ifdef __BIG_ENDIAN
+		NV_WR32(par->PRAMIN, 0x080A * 4,
+			NV_RD32(par->PRAMIN, 0x080A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4,
+			NV_RD32(par->PRAMIN, 0x0812 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4,
+			NV_RD32(par->PRAMIN, 0x081A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4,
+			NV_RD32(par->PRAMIN, 0x0822 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x082A * 4,
+			NV_RD32(par->PRAMIN, 0x082A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0832 * 4,
+			NV_RD32(par->PRAMIN, 0x0832 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x083A * 4,
+			NV_RD32(par->PRAMIN, 0x083A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0842 * 4,
+			NV_RD32(par->PRAMIN, 0x0842 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x01000000);
+#endif
+	} else {
+		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x80011201);
+		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x80011202);
+		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x80011203);
+		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x80011204);
+		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x80011205);
+		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+		NV_WR32(par->PRAMIN, 0x000B * 4, 0x80011206);
+		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+		NV_WR32(par->PRAMIN, 0x000D * 4, 0x80011207);
+		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+		NV_WR32(par->PRAMIN, 0x000F * 4, 0x80011208);
+		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0803 * 4, 0x00000002);
+		if (par->Architecture >= NV_ARCH_10)
+			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008062);
+		else
+			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008042);
+		NV_WR32(par->PRAMIN, 0x0805 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0806 * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x0807 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x01008043);
+		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080C * 4, 0x01008044);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x080E * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080F * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x01008019);
+		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x0100A05C);
+		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0816 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0817 * 4, 0x00000000);
+		if (par->WaitVSyncPossible)
+			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100809F);
+		else
+			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100805F);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081C * 4, 0x0100804A);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x081E * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081F * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x01018077);
+		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00003002);
+		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00007FFF);
+		NV_WR32(par->PRAMIN, 0x0826 * 4,
+			par->FbUsableSize | 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0827 * 4, 0x00000002);
+#ifdef __BIG_ENDIAN
+		NV_WR32(par->PRAMIN, 0x0804 * 4,
+			NV_RD32(par->PRAMIN, 0x0804 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0808 * 4,
+			NV_RD32(par->PRAMIN, 0x0808 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x080C * 4,
+			NV_RD32(par->PRAMIN, 0x080C * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4,
+			NV_RD32(par->PRAMIN, 0x0810 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4,
+			NV_RD32(par->PRAMIN, 0x0814 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0818 * 4,
+			NV_RD32(par->PRAMIN, 0x0818 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x081C * 4,
+			NV_RD32(par->PRAMIN, 0x081C * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4,
+			NV_RD32(par->PRAMIN, 0x0820 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000001);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000001);
+#endif
+	}
+	if (par->Architecture < NV_ARCH_10) {
+		if ((par->Chipset & 0x0fff) == 0x0020) {
+			NV_WR32(par->PRAMIN, 0x0824 * 4,
+				NV_RD32(par->PRAMIN, 0x0824 * 4) | 0x00020000);
+			NV_WR32(par->PRAMIN, 0x0826 * 4,
+				NV_RD32(par->PRAMIN,
+					0x0826 * 4) + par->FbAddress);
+		}
+		NV_WR32(par->PGRAPH, 0x0080, 0x000001FF);
+		NV_WR32(par->PGRAPH, 0x0080, 0x1230C000);
+		NV_WR32(par->PGRAPH, 0x0084, 0x72111101);
+		NV_WR32(par->PGRAPH, 0x0088, 0x11D5F071);
+		NV_WR32(par->PGRAPH, 0x008C, 0x0004FF31);
+		NV_WR32(par->PGRAPH, 0x008C, 0x4004FF31);
+		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0170, 0x10010100);
+		NV_WR32(par->PGRAPH, 0x0710, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+		NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+	} else {
+		NV_WR32(par->PGRAPH, 0x0080, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0080, 0x00000000);
+
+		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0144, 0x10010100);
+		NV_WR32(par->PGRAPH, 0x0714, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+		NV_WR32(par->PGRAPH, 0x0710,
+			NV_RD32(par->PGRAPH, 0x0710) & 0x0007ff00);
+		NV_WR32(par->PGRAPH, 0x0710,
+			NV_RD32(par->PGRAPH, 0x0710) | 0x00020100);
+
+		if (par->Architecture == NV_ARCH_10) {
+			NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+			NV_WR32(par->PGRAPH, 0x0088, 0x24E00810);
+			NV_WR32(par->PGRAPH, 0x008C, 0x55DE0030);
+
+			for (i = 0; i < 32; i++)
+				NV_WR32(&par->PGRAPH[(0x0B00 / 4) + i], 0,
+					NV_RD32(&par->PFB[(0x0240 / 4) + i],
+						0));
+
+			NV_WR32(par->PGRAPH, 0x640, 0);
+			NV_WR32(par->PGRAPH, 0x644, 0);
+			NV_WR32(par->PGRAPH, 0x684, par->FbMapSize - 1);
+			NV_WR32(par->PGRAPH, 0x688, par->FbMapSize - 1);
+
+			NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+		} else {
+			if (par->Architecture >= NV_ARCH_40) {
+				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
+				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+				NV_WR32(par->PGRAPH, 0x0bc4,
+					NV_RD32(par->PGRAPH, 0x0bc4) |
+					0x00008000);
+
+				j = NV_RD32(par->REGS, 0x1540) & 0xff;
+
+				if (j) {
+					for (i = 0; !(j & 1); j >>= 1, i++);
+					NV_WR32(par->PGRAPH, 0x5000, i);
+				}
+
+				if ((par->Chipset & 0xfff0) == 0x0040) {
+					NV_WR32(par->PGRAPH, 0x09b0,
+						0x83280fff);
+					NV_WR32(par->PGRAPH, 0x09b4,
+						0x000000a0);
+				} else {
+					NV_WR32(par->PGRAPH, 0x0820,
+						0x83280eff);
+					NV_WR32(par->PGRAPH, 0x0824,
+						0x000000a0);
+				}
+
+				switch (par->Chipset & 0xfff0) {
+				case 0x0040:
+				case 0x0210:
+					NV_WR32(par->PGRAPH, 0x09b8,
+						0x0078e366);
+					NV_WR32(par->PGRAPH, 0x09bc,
+						0x0000014c);
+					NV_WR32(par->PFB, 0x033C,
+						NV_RD32(par->PFB, 0x33C) &
+						0xffff7fff);
+					break;
+				case 0x00C0:
+				case 0x0120:
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x007596ff);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x00000108);
+					break;
+				case 0x0160:
+				case 0x01D0:
+				case 0x0240:
+				case 0x03D0:
+					NV_WR32(par->PMC, 0x1700,
+						NV_RD32(par->PFB, 0x020C));
+					NV_WR32(par->PMC, 0x1704, 0);
+					NV_WR32(par->PMC, 0x1708, 0);
+					NV_WR32(par->PMC, 0x170C,
+						NV_RD32(par->PFB, 0x020C));
+					NV_WR32(par->PGRAPH, 0x0860, 0);
+					NV_WR32(par->PGRAPH, 0x0864, 0);
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC,
+							0x0608) | 0x00100000);
+					break;
+				case 0x0140:
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x0072cb77);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x00000108);
+					break;
+				case 0x0220:
+					NV_WR32(par->PGRAPH, 0x0860, 0);
+					NV_WR32(par->PGRAPH, 0x0864, 0);
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC, 0x0608) |
+						0x00100000);
+					break;
+				case 0x0090:
+				case 0x0290:
+				case 0x0390:
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC, 0x0608) |
+						0x00100000);
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x07830610);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x0000016A);
+					break;
+				default:
+					break;
+				}
+
+				NV_WR32(par->PGRAPH, 0x0b38, 0x2ffff800);
+				NV_WR32(par->PGRAPH, 0x0b3c, 0x00006000);
+				NV_WR32(par->PGRAPH, 0x032C, 0x01000000);
+				NV_WR32(par->PGRAPH, 0x0220, 0x00001200);
+			} else if (par->Architecture == NV_ARCH_30) {
+				NV_WR32(par->PGRAPH, 0x0084, 0x40108700);
+				NV_WR32(par->PGRAPH, 0x0890, 0x00140000);
+				NV_WR32(par->PGRAPH, 0x008C, 0xf00e0431);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+				NV_WR32(par->PGRAPH, 0x0610, 0xf04b1f36);
+				NV_WR32(par->PGRAPH, 0x0B80, 0x1002d888);
+				NV_WR32(par->PGRAPH, 0x0B88, 0x62ff007f);
+			} else {
+				NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+				NV_WR32(par->PGRAPH, 0x008C, 0xF20E0431);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00000000);
+				NV_WR32(par->PGRAPH, 0x009C, 0x00000040);
+
+				if ((par->Chipset & 0x0ff0) >= 0x0250) {
+					NV_WR32(par->PGRAPH, 0x0890,
+						0x00080000);
+					NV_WR32(par->PGRAPH, 0x0610,
+						0x304B1FB6);
+					NV_WR32(par->PGRAPH, 0x0B80,
+						0x18B82880);
+					NV_WR32(par->PGRAPH, 0x0B84,
+						0x44000000);
+					NV_WR32(par->PGRAPH, 0x0098,
+						0x40000080);
+					NV_WR32(par->PGRAPH, 0x0B88,
+						0x000000ff);
+				} else {
+					NV_WR32(par->PGRAPH, 0x0880,
+						0x00080000);
+					NV_WR32(par->PGRAPH, 0x0094,
+						0x00000005);
+					NV_WR32(par->PGRAPH, 0x0B80,
+						0x45CAA208);
+					NV_WR32(par->PGRAPH, 0x0B84,
+						0x24000000);
+					NV_WR32(par->PGRAPH, 0x0098,
+						0x00000040);
+					NV_WR32(par->PGRAPH, 0x0750,
+						0x00E00038);
+					NV_WR32(par->PGRAPH, 0x0754,
+						0x00000030);
+					NV_WR32(par->PGRAPH, 0x0750,
+						0x00E10038);
+					NV_WR32(par->PGRAPH, 0x0754,
+						0x00000030);
+				}
+			}
+
+			if ((par->Architecture < NV_ARCH_40) ||
+			    ((par->Chipset & 0xfff0) == 0x0040)) {
+				for (i = 0; i < 32; i++) {
+					NV_WR32(par->PGRAPH, 0x0900 + i*4,
+						NV_RD32(par->PFB, 0x0240 +i*4));
+					NV_WR32(par->PGRAPH, 0x6900 + i*4,
+						NV_RD32(par->PFB, 0x0240 +i*4));
+				}
+			} else {
+				if (((par->Chipset & 0xfff0) == 0x0090) ||
+				    ((par->Chipset & 0xfff0) == 0x01D0) ||
+				    ((par->Chipset & 0xfff0) == 0x0290) ||
+				    ((par->Chipset & 0xfff0) == 0x0390) ||
+				    ((par->Chipset & 0xfff0) == 0x03D0)) {
+					for (i = 0; i < 60; i++) {
+						NV_WR32(par->PGRAPH,
+							0x0D00 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+						NV_WR32(par->PGRAPH,
+							0x6900 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+					}
+				} else {
+					for (i = 0; i < 48; i++) {
+						NV_WR32(par->PGRAPH,
+							0x0900 + i*4,
+							NV_RD32(par->PFB,
+								0x0600 + i*4));
+						if(((par->Chipset & 0xfff0)
+						    != 0x0160) &&
+						   ((par->Chipset & 0xfff0)
+						    != 0x0220) &&
+						   ((par->Chipset & 0xfff0)
+						    != 0x240))
+							NV_WR32(par->PGRAPH,
+								0x6900 + i*4,
+								NV_RD32(par->PFB,
+									0x0600 + i*4));
+					}
+				}
+			}
+
+			if (par->Architecture >= NV_ARCH_40) {
+				if ((par->Chipset & 0xfff0) == 0x0040) {
+					NV_WR32(par->PGRAPH, 0x09A4,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x09A8,
+						NV_RD32(par->PFB, 0x0204));
+					NV_WR32(par->PGRAPH, 0x69A4,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x69A8,
+						NV_RD32(par->PFB, 0x0204));
+
+					NV_WR32(par->PGRAPH, 0x0820, 0);
+					NV_WR32(par->PGRAPH, 0x0824, 0);
+					NV_WR32(par->PGRAPH, 0x0864,
+						par->FbMapSize - 1);
+					NV_WR32(par->PGRAPH, 0x0868,
+						par->FbMapSize - 1);
+				} else {
+					if ((par->Chipset & 0xfff0) == 0x0090 ||
+					    (par->Chipset & 0xfff0) == 0x01D0 ||
+					    (par->Chipset & 0xfff0) == 0x0290 ||
+					    (par->Chipset & 0xfff0) == 0x0390) {
+						NV_WR32(par->PGRAPH, 0x0DF0,
+							NV_RD32(par->PFB, 0x0200));
+						NV_WR32(par->PGRAPH, 0x0DF4,
+							NV_RD32(par->PFB, 0x0204));
+					} else {
+						NV_WR32(par->PGRAPH, 0x09F0,
+							NV_RD32(par->PFB, 0x0200));
+						NV_WR32(par->PGRAPH, 0x09F4,
+							NV_RD32(par->PFB, 0x0204));
+					}
+					NV_WR32(par->PGRAPH, 0x69F0,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x69F4,
+						NV_RD32(par->PFB, 0x0204));
+
+					NV_WR32(par->PGRAPH, 0x0840, 0);
+					NV_WR32(par->PGRAPH, 0x0844, 0);
+					NV_WR32(par->PGRAPH, 0x08a0,
+						par->FbMapSize - 1);
+					NV_WR32(par->PGRAPH, 0x08a4,
+						par->FbMapSize - 1);
+				}
+			} else {
+				NV_WR32(par->PGRAPH, 0x09A4,
+					NV_RD32(par->PFB, 0x0200));
+				NV_WR32(par->PGRAPH, 0x09A8,
+					NV_RD32(par->PFB, 0x0204));
+				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0000);
+				NV_WR32(par->PGRAPH, 0x0754,
+					NV_RD32(par->PFB, 0x0200));
+				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0004);
+				NV_WR32(par->PGRAPH, 0x0754,
+					NV_RD32(par->PFB, 0x0204));
+
+				NV_WR32(par->PGRAPH, 0x0820, 0);
+				NV_WR32(par->PGRAPH, 0x0824, 0);
+				NV_WR32(par->PGRAPH, 0x0864,
+					par->FbMapSize - 1);
+				NV_WR32(par->PGRAPH, 0x0868,
+					par->FbMapSize - 1);
+			}
+			NV_WR32(par->PGRAPH, 0x0B20, 0x00000000);
+			NV_WR32(par->PGRAPH, 0x0B04, 0xFFFFFFFF);
+		}
+	}
+	NV_WR32(par->PGRAPH, 0x053C, 0);
+	NV_WR32(par->PGRAPH, 0x0540, 0);
+	NV_WR32(par->PGRAPH, 0x0544, 0x00007FFF);
+	NV_WR32(par->PGRAPH, 0x0548, 0x00007FFF);
+
+	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0141 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000000);
+	if (par->Architecture >= NV_ARCH_40)
+		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00010000);
+	else
+		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00000100);
+	NV_WR32(par->PFIFO, 0x0490 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0491 * 4, 0x00000000);
+	if (par->Architecture >= NV_ARCH_40)
+		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001213);
+	else
+		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001209);
+	NV_WR32(par->PFIFO, 0x0400 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0414 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0084 * 4, 0x03000100);
+	NV_WR32(par->PFIFO, 0x0085 * 4, 0x00000110);
+	NV_WR32(par->PFIFO, 0x0086 * 4, 0x00000112);
+	NV_WR32(par->PFIFO, 0x0143 * 4, 0x0000FFFF);
+	NV_WR32(par->PFIFO, 0x0496 * 4, 0x0000FFFF);
+	NV_WR32(par->PFIFO, 0x0050 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0040 * 4, 0xFFFFFFFF);
+	NV_WR32(par->PFIFO, 0x0415 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x048C * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x04A0 * 4, 0x00000000);
+#ifdef __BIG_ENDIAN
+	NV_WR32(par->PFIFO, 0x0489 * 4, 0x800F0078);
+#else
+	NV_WR32(par->PFIFO, 0x0489 * 4, 0x000F0078);
+#endif
+	NV_WR32(par->PFIFO, 0x0488 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
+
+    if (!state) {
+	    par->CurrentState = NULL;
+	    return;
+    }
+
+	if (par->Architecture >= NV_ARCH_10) {
+		if (par->twoHeads) {
+			NV_WR32(par->PCRTC0, 0x0860, state->head);
+			NV_WR32(par->PCRTC0, 0x2860, state->head2);
+		}
+		NV_WR32(par->PRAMDAC, 0x0404, NV_RD32(par->PRAMDAC, 0x0404) |
+			(1 << 25));
+
+		NV_WR32(par->PMC, 0x8704, 1);
+		NV_WR32(par->PMC, 0x8140, 0);
+		NV_WR32(par->PMC, 0x8920, 0);
+		NV_WR32(par->PMC, 0x8924, 0);
+		NV_WR32(par->PMC, 0x8908, par->FbMapSize - 1);
+		NV_WR32(par->PMC, 0x890C, par->FbMapSize - 1);
+		NV_WR32(par->PMC, 0x1588, 0);
+
+		NV_WR32(par->PCRTC, 0x0810, state->cursorConfig);
+		NV_WR32(par->PCRTC, 0x0830, state->displayV - 3);
+		NV_WR32(par->PCRTC, 0x0834, state->displayV - 1);
+
+		if (par->FlatPanel) {
+			if ((par->Chipset & 0x0ff0) == 0x0110) {
+				NV_WR32(par->PRAMDAC, 0x0528, state->dither);
+			} else if (par->twoHeads) {
+				NV_WR32(par->PRAMDAC, 0x083C, state->dither);
+			}
+
+			VGA_WR08(par->PCIO, 0x03D4, 0x53);
+			VGA_WR08(par->PCIO, 0x03D5, state->timingH);
+			VGA_WR08(par->PCIO, 0x03D4, 0x54);
+			VGA_WR08(par->PCIO, 0x03D5, state->timingV);
+			VGA_WR08(par->PCIO, 0x03D4, 0x21);
+			VGA_WR08(par->PCIO, 0x03D5, 0xfa);
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x41);
+		VGA_WR08(par->PCIO, 0x03D5, state->extra);
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x19);
+	VGA_WR08(par->PCIO, 0x03D5, state->repaint0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+	VGA_WR08(par->PCIO, 0x03D5, state->repaint1);
+	VGA_WR08(par->PCIO, 0x03D4, 0x25);
+	VGA_WR08(par->PCIO, 0x03D5, state->screen);
+	VGA_WR08(par->PCIO, 0x03D4, 0x28);
+	VGA_WR08(par->PCIO, 0x03D5, state->pixel);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+	VGA_WR08(par->PCIO, 0x03D5, state->horiz);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	VGA_WR08(par->PCIO, 0x03D5, state->fifo);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+	VGA_WR08(par->PCIO, 0x03D5, state->arbitration0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x20);
+	VGA_WR08(par->PCIO, 0x03D5, state->arbitration1);
+
+	if(par->Architecture >= NV_ARCH_30) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x47);
+		VGA_WR08(par->PCIO, 0x03D5, state->arbitration1 >> 8);
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x30);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x31);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor1);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor2);
+	VGA_WR08(par->PCIO, 0x03D4, 0x39);
+	VGA_WR08(par->PCIO, 0x03D5, state->interlace);
+
+	if (!par->FlatPanel) {
+		if (par->Architecture >= NV_ARCH_40)
+			NV_WR32(par->PRAMDAC0, 0x0580, state->control);
+
+		NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
+		NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
+		if (par->twoHeads)
+			NV_WR32(par->PRAMDAC0, 0x0520, state->vpll2);
+		if (par->twoStagePLL) {
+			NV_WR32(par->PRAMDAC0, 0x0578, state->vpllB);
+			NV_WR32(par->PRAMDAC0, 0x057C, state->vpll2B);
+		}
+	} else {
+		NV_WR32(par->PRAMDAC, 0x0848, state->scale);
+		NV_WR32(par->PRAMDAC, 0x0828, state->crtcSync +
+			par->PanelTweak);
+	}
+
+	NV_WR32(par->PRAMDAC, 0x0600, state->general);
+
+	NV_WR32(par->PCRTC, 0x0140, 0);
+	NV_WR32(par->PCRTC, 0x0100, 1);
+
+	par->CurrentState = state;
+}
+
+void NVUnloadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) {
+	VGA_WR08(par->PCIO, 0x03D4, 0x19);
+	state->repaint0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+	state->repaint1 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x25);
+	state->screen = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x28);
+	state->pixel = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+	state->horiz = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	state->fifo         = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+	state->arbitration0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x20);
+	state->arbitration1 = VGA_RD08(par->PCIO, 0x03D5);
+
+	if(par->Architecture >= NV_ARCH_30) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x47);
+		state->arbitration1 |= (VGA_RD08(par->PCIO, 0x03D5) & 1) << 8;
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x30);
+	state->cursor0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x31);
+	state->cursor1 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+	state->cursor2 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x39);
+	state->interlace = VGA_RD08(par->PCIO, 0x03D5);
+	state->vpll = NV_RD32(par->PRAMDAC0, 0x0508);
+	if (par->twoHeads)
+		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+	if (par->twoStagePLL) {
+		state->vpllB = NV_RD32(par->PRAMDAC0, 0x0578);
+		state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+	}
+	state->pllsel = NV_RD32(par->PRAMDAC0, 0x050C);
+	state->general = NV_RD32(par->PRAMDAC, 0x0600);
+	state->scale = NV_RD32(par->PRAMDAC, 0x0848);
+	state->config = NV_RD32(par->PFB, 0x0200);
+
+	if (par->Architecture >= NV_ARCH_40 && !par->FlatPanel)
+		state->control  = NV_RD32(par->PRAMDAC0, 0x0580);
+
+	if (par->Architecture >= NV_ARCH_10) {
+		if (par->twoHeads) {
+			state->head = NV_RD32(par->PCRTC0, 0x0860);
+			state->head2 = NV_RD32(par->PCRTC0, 0x2860);
+			VGA_WR08(par->PCIO, 0x03D4, 0x44);
+			state->crtcOwner = VGA_RD08(par->PCIO, 0x03D5);
+		}
+		VGA_WR08(par->PCIO, 0x03D4, 0x41);
+		state->extra = VGA_RD08(par->PCIO, 0x03D5);
+		state->cursorConfig = NV_RD32(par->PCRTC, 0x0810);
+
+		if ((par->Chipset & 0x0ff0) == 0x0110) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x0528);
+		} else if (par->twoHeads) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x083C);
+		}
+
+		if (par->FlatPanel) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x53);
+			state->timingH = VGA_RD08(par->PCIO, 0x03D5);
+			VGA_WR08(par->PCIO, 0x03D4, 0x54);
+			state->timingV = VGA_RD08(par->PCIO, 0x03D5);
+		}
+	}
+}
+
+void NVSetStartAddress(struct nvidia_par *par, u32 start)
+{
+	NV_WR32(par->PCRTC, 0x800, start);
+}
diff --git a/drivers/video/fbdev/nvidia/nv_i2c.c b/drivers/video/fbdev/nvidia/nv_i2c.c
new file mode 100644
index 000000000000..d7994a173245
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_i2c.c
@@ -0,0 +1,171 @@
+/*
+ * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+#include "../edid.h"
+
+static void nvidia_gpio_setscl(void *data, int state)
+{
+	struct nvidia_i2c_chan *chan = data;
+	struct nvidia_par *par = chan->par;
+	u32 val;
+
+	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
+
+	if (state)
+		val |= 0x20;
+	else
+		val &= ~0x20;
+
+	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
+}
+
+static void nvidia_gpio_setsda(void *data, int state)
+{
+	struct nvidia_i2c_chan *chan = data;
+	struct nvidia_par *par = chan->par;
+	u32 val;
+
+	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
+
+	if (state)
+		val |= 0x10;
+	else
+		val &= ~0x10;
+
+	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
+}
+
+static int nvidia_gpio_getscl(void *data)
+{
+	struct nvidia_i2c_chan *chan = data;
+	struct nvidia_par *par = chan->par;
+	u32 val = 0;
+
+	if (NVReadCrtc(par, chan->ddc_base) & 0x04)
+		val = 1;
+
+	return val;
+}
+
+static int nvidia_gpio_getsda(void *data)
+{
+	struct nvidia_i2c_chan *chan = data;
+	struct nvidia_par *par = chan->par;
+	u32 val = 0;
+
+	if (NVReadCrtc(par, chan->ddc_base) & 0x08)
+		val = 1;
+
+	return val;
+}
+
+static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,
+				unsigned int i2c_class)
+{
+	int rc;
+
+	strcpy(chan->adapter.name, name);
+	chan->adapter.owner = THIS_MODULE;
+	chan->adapter.class = i2c_class;
+	chan->adapter.algo_data = &chan->algo;
+	chan->adapter.dev.parent = &chan->par->pci_dev->dev;
+	chan->algo.setsda = nvidia_gpio_setsda;
+	chan->algo.setscl = nvidia_gpio_setscl;
+	chan->algo.getsda = nvidia_gpio_getsda;
+	chan->algo.getscl = nvidia_gpio_getscl;
+	chan->algo.udelay = 40;
+	chan->algo.timeout = msecs_to_jiffies(2);
+	chan->algo.data = chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	/* Raise SCL and SDA */
+	nvidia_gpio_setsda(chan, 1);
+	nvidia_gpio_setscl(chan, 1);
+	udelay(20);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		dev_dbg(&chan->par->pci_dev->dev,
+			"I2C bus %s registered.\n", name);
+	else {
+		dev_warn(&chan->par->pci_dev->dev,
+			 "Failed to register I2C bus %s.\n", name);
+		chan->par = NULL;
+	}
+
+	return rc;
+}
+
+void nvidia_create_i2c_busses(struct nvidia_par *par)
+{
+	par->chan[0].par = par;
+	par->chan[1].par = par;
+	par->chan[2].par = par;
+
+	par->chan[0].ddc_base = (par->reverse_i2c) ? 0x36 : 0x3e;
+ 	nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0",
+			     (par->reverse_i2c) ? I2C_CLASS_HWMON : 0);
+
+	par->chan[1].ddc_base = (par->reverse_i2c) ? 0x3e : 0x36;
+ 	nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1",
+			     (par->reverse_i2c) ? 0 : I2C_CLASS_HWMON);
+
+	par->chan[2].ddc_base = 0x50;
+ 	nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0);
+}
+
+void nvidia_delete_i2c_busses(struct nvidia_par *par)
+{
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		if (!par->chan[i].par)
+			continue;
+		i2c_del_adapter(&par->chan[i].adapter);
+		par->chan[i].par = NULL;
+	}
+}
+
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
+{
+	struct nvidia_par *par = info->par;
+	u8 *edid = NULL;
+
+	if (par->chan[conn - 1].par)
+		edid = fb_ddc_read(&par->chan[conn - 1].adapter);
+
+	if (!edid && conn == 1) {
+		/* try to get from firmware */
+		const u8 *e = fb_firmware_edid(info->device);
+
+		if (e != NULL)
+			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
+	}
+
+	*out_edid = edid;
+
+	return (edid) ? 0 : 1;
+}
diff --git a/drivers/video/fbdev/nvidia/nv_local.h b/drivers/video/fbdev/nvidia/nv_local.h
new file mode 100644
index 000000000000..68e508daa417
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_local.h
@@ -0,0 +1,114 @@
+/***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#ifndef __NV_LOCAL_H__
+#define __NV_LOCAL_H__
+
+/*
+ * This file includes any environment or machine specific values to access the
+ * HW.  Put all affected includes, typdefs, etc. here so the riva_hw.* files
+ * can stay generic in nature.
+ */
+
+/*
+ * HW access macros.  These assume memory-mapped I/O, and not normal I/O space.
+ */
+#define NV_WR08(p,i,d)  (__raw_writeb((d), (void __iomem *)(p) + (i)))
+#define NV_RD08(p,i)    (__raw_readb((void __iomem *)(p) + (i)))
+#define NV_WR16(p,i,d)  (__raw_writew((d), (void __iomem *)(p) + (i)))
+#define NV_RD16(p,i)    (__raw_readw((void __iomem *)(p) + (i)))
+#define NV_WR32(p,i,d)  (__raw_writel((d), (void __iomem *)(p) + (i)))
+#define NV_RD32(p,i)    (__raw_readl((void __iomem *)(p) + (i)))
+
+/* VGA I/O is now always done through MMIO */
+#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
+#define VGA_RD08(p,i)   (readb((void __iomem *)(p) + (i)))
+
+#define NVDmaNext(par, data) \
+     NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data))
+
+#define NVDmaStart(info, par, tag, size) {    \
+     if((par)->dmaFree <= (size))             \
+        NVDmaWait(info, size);                \
+     NVDmaNext(par, ((size) << 18) | (tag));  \
+     (par)->dmaFree -= ((size) + 1);          \
+}
+
+#if defined(__i386__)
+#define _NV_FENCE() outb(0, 0x3D0);
+#else
+#define _NV_FENCE() mb();
+#endif
+
+#define WRITE_PUT(par, data) {                   \
+  _NV_FENCE()                                    \
+  NV_RD08((par)->FbStart, 0);                    \
+  NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \
+  mb();                                          \
+}
+
+#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
+
+#ifdef __LITTLE_ENDIAN
+
+#include <linux/bitrev.h>
+
+#define reverse_order(l)        \
+do {                            \
+	u8 *a = (u8 *)(l);      \
+	a[0] = bitrev8(a[0]);   \
+	a[1] = bitrev8(a[1]);   \
+	a[2] = bitrev8(a[2]);   \
+	a[3] = bitrev8(a[3]);   \
+} while(0)
+#else
+#define reverse_order(l) do { } while(0)
+#endif                          /* __LITTLE_ENDIAN */
+
+#endif				/* __NV_LOCAL_H__ */
diff --git a/drivers/video/fbdev/nvidia/nv_of.c b/drivers/video/fbdev/nvidia/nv_of.c
new file mode 100644
index 000000000000..3bc13df4b120
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_of.c
@@ -0,0 +1,82 @@
+/*
+ * linux/drivers/video/nvidia/nv_of.c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+#include "../edid.h"
+
+int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
+{
+	struct nvidia_par *par = info->par;
+	struct device_node *parent, *dp;
+	const unsigned char *pedid = NULL;
+	static char *propnames[] = {
+		"DFP,EDID", "LCD,EDID", "EDID", "EDID1",
+		"EDID,B", "EDID,A", NULL };
+	int i;
+
+	parent = pci_device_to_OF_node(par->pci_dev);
+	if (parent == NULL)
+		return -1;
+	if (par->twoHeads) {
+		const char *pname;
+		int len;
+
+		for (dp = NULL;
+		     (dp = of_get_next_child(parent, dp)) != NULL;) {
+			pname = of_get_property(dp, "name", NULL);
+			if (!pname)
+				continue;
+			len = strlen(pname);
+			if ((pname[len-1] == 'A' && conn == 1) ||
+			    (pname[len-1] == 'B' && conn == 2)) {
+				for (i = 0; propnames[i] != NULL; ++i) {
+					pedid = of_get_property(dp,
+							propnames[i], NULL);
+					if (pedid != NULL)
+						break;
+				}
+				of_node_put(dp);
+				break;
+			}
+		}
+	}
+	if (pedid == NULL) {
+		for (i = 0; propnames[i] != NULL; ++i) {
+			pedid = of_get_property(parent, propnames[i], NULL);
+			if (pedid != NULL)
+				break;
+		}
+	}
+	if (pedid) {
+		*out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
+		if (*out_edid == NULL)
+			return -1;
+		printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
+		return 0;
+	}
+	return -1;
+}
diff --git a/drivers/video/fbdev/nvidia/nv_proto.h b/drivers/video/fbdev/nvidia/nv_proto.h
new file mode 100644
index 000000000000..ff5c410355ea
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_proto.h
@@ -0,0 +1,75 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_proto.h,v 1.10 2003/07/31 20:24:29 mvojkovi Exp $ */
+
+#ifndef __NV_PROTO_H__
+#define __NV_PROTO_H__
+
+/* in nv_setup.c */
+int NVCommonSetup(struct fb_info *info);
+void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadCrtc(struct nvidia_par *par, u8 index);
+void NVWriteGr(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadGr(struct nvidia_par *par, u8 index);
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadSeq(struct nvidia_par *par, u8 index);
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadAttr(struct nvidia_par *par, u8 index);
+void NVWriteMiscOut(struct nvidia_par *par, u8 value);
+u8 NVReadMiscOut(struct nvidia_par *par);
+void NVWriteDacMask(struct nvidia_par *par, u8 value);
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacData(struct nvidia_par *par, u8 value);
+u8 NVReadDacData(struct nvidia_par *par);
+
+/* in nv_hw.c */
+void NVCalcStateExt(struct nvidia_par *par, struct _riva_hw_state *,
+		    int, int, int, int, int, int);
+void NVLoadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVUnloadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVSetStartAddress(struct nvidia_par *par, u32);
+int NVShowHideCursor(struct nvidia_par *par, int);
+void NVLockUnlock(struct nvidia_par *par, int);
+
+/* in nvidia-i2c.c */
+#ifdef CONFIG_FB_NVIDIA_I2C
+void nvidia_create_i2c_busses(struct nvidia_par *par);
+void nvidia_delete_i2c_busses(struct nvidia_par *par);
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
+			       u8 ** out_edid);
+#else
+#define nvidia_create_i2c_busses(...)
+#define nvidia_delete_i2c_busses(...)
+#define nvidia_probe_i2c_connector(p, c, edid) (-1)
+#endif
+
+#ifdef CONFIG_PPC_OF
+int nvidia_probe_of_connector(struct fb_info *info, int conn,
+			      u8 ** out_edid);
+#else
+static inline int nvidia_probe_of_connector(struct fb_info *info, int conn,
+				      u8 ** out_edid)
+{
+	return -1;
+}
+#endif
+
+/* in nv_accel.c */
+extern void NVResetGraphics(struct fb_info *info);
+extern void nvidiafb_copyarea(struct fb_info *info,
+			      const struct fb_copyarea *region);
+extern void nvidiafb_fillrect(struct fb_info *info,
+			      const struct fb_fillrect *rect);
+extern void nvidiafb_imageblit(struct fb_info *info,
+			       const struct fb_image *image);
+extern int nvidiafb_sync(struct fb_info *info);
+
+/* in nv_backlight.h */
+#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
+extern void nvidia_bl_init(struct nvidia_par *par);
+extern void nvidia_bl_exit(struct nvidia_par *par);
+#else
+static inline void nvidia_bl_init(struct nvidia_par *par) {}
+static inline void nvidia_bl_exit(struct nvidia_par *par) {}
+#endif
+
+#endif				/* __NV_PROTO_H__ */
diff --git a/drivers/video/fbdev/nvidia/nv_setup.c b/drivers/video/fbdev/nvidia/nv_setup.c
new file mode 100644
index 000000000000..2f2e162134fa
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_setup.c
@@ -0,0 +1,675 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#include <video/vga.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+/*
+ * Override VGA I/O routines.
+ */
+void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+	VGA_WR08(par->PCIO, par->IOBase + 0x05, value);
+}
+u8 NVReadCrtc(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+	return (VGA_RD08(par->PCIO, par->IOBase + 0x05));
+}
+void NVWriteGr(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_GFX_I, index);
+	VGA_WR08(par->PVIO, VGA_GFX_D, value);
+}
+u8 NVReadGr(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PVIO, VGA_GFX_I, index);
+	return (VGA_RD08(par->PVIO, VGA_GFX_D));
+}
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+	VGA_WR08(par->PVIO, VGA_SEQ_D, value);
+}
+u8 NVReadSeq(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+	return (VGA_RD08(par->PVIO, VGA_SEQ_D));
+}
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	if (par->paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+	VGA_WR08(par->PCIO, VGA_ATT_W, value);
+}
+u8 NVReadAttr(struct nvidia_par *par, u8 index)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	if (par->paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+	return (VGA_RD08(par->PCIO, VGA_ATT_R));
+}
+void NVWriteMiscOut(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_MIS_W, value);
+}
+u8 NVReadMiscOut(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PVIO, VGA_MIS_R));
+}
+#if 0
+void NVEnablePalette(struct nvidia_par *par)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x00);
+	par->paletteEnabled = 1;
+}
+void NVDisablePalette(struct nvidia_par *par)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x20);
+	par->paletteEnabled = 0;
+}
+#endif  /*  0  */
+void NVWriteDacMask(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
+}
+#if 0
+u8 NVReadDacMask(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PDIO, VGA_PEL_MSK));
+}
+#endif  /*  0  */
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_IR, value);
+}
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_IW, value);
+}
+void NVWriteDacData(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_D, value);
+}
+u8 NVReadDacData(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PDIO, VGA_PEL_D));
+}
+
+static int NVIsConnected(struct nvidia_par *par, int output)
+{
+	volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
+	u32 reg52C, reg608, dac0_reg608 = 0;
+	int present;
+
+	if (output) {
+	    dac0_reg608 = NV_RD32(PRAMDAC, 0x0608);
+	    PRAMDAC += 0x800;
+	}
+
+	reg52C = NV_RD32(PRAMDAC, 0x052C);
+	reg608 = NV_RD32(PRAMDAC, 0x0608);
+
+	NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
+	msleep(1);
+	NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
+
+	NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140);
+	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) |
+		0x00001000);
+
+	msleep(1);
+
+	present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
+
+	if (present)
+		printk("nvidiafb: CRTC%i analog found\n", output);
+	else
+		printk("nvidiafb: CRTC%i analog not found\n", output);
+
+	if (output)
+	    NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C);
+	NV_WR32(PRAMDAC, 0x0608, reg608);
+
+	return present;
+}
+
+static void NVSelectHeadRegisters(struct nvidia_par *par, int head)
+{
+	if (head) {
+		par->PCIO = par->PCIO0 + 0x2000;
+		par->PCRTC = par->PCRTC0 + 0x800;
+		par->PRAMDAC = par->PRAMDAC0 + 0x800;
+		par->PDIO = par->PDIO0 + 0x2000;
+	} else {
+		par->PCIO = par->PCIO0;
+		par->PCRTC = par->PCRTC0;
+		par->PRAMDAC = par->PRAMDAC0;
+		par->PDIO = par->PDIO0;
+	}
+}
+
+static void nv4GetConfig(struct nvidia_par *par)
+{
+	if (NV_RD32(par->PFB, 0x0000) & 0x00000100) {
+		par->RamAmountKBytes =
+		    ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 +
+		    1024 * 2;
+	} else {
+		switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) {
+		case 0:
+			par->RamAmountKBytes = 1024 * 32;
+			break;
+		case 1:
+			par->RamAmountKBytes = 1024 * 4;
+			break;
+		case 2:
+			par->RamAmountKBytes = 1024 * 8;
+			break;
+		case 3:
+		default:
+			par->RamAmountKBytes = 1024 * 16;
+			break;
+		}
+	}
+	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ?
+	    14318 : 13500;
+	par->CURSOR = &par->PRAMIN[0x1E00];
+	par->MinVClockFreqKHz = 12000;
+	par->MaxVClockFreqKHz = 350000;
+}
+
+static void nv10GetConfig(struct nvidia_par *par)
+{
+	struct pci_dev *dev;
+	u32 implementation = par->Chipset & 0x0ff0;
+
+#ifdef __BIG_ENDIAN
+	/* turn on big endian register access */
+	if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) {
+		NV_WR32(par->PMC, 0x0004, 0x01000001);
+		mb();
+	}
+#endif
+
+	dev = pci_get_bus_and_slot(0, 1);
+	if ((par->Chipset & 0xffff) == 0x01a0) {
+		u32 amt;
+
+		pci_read_config_dword(dev, 0x7c, &amt);
+		par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+	} else if ((par->Chipset & 0xffff) == 0x01f0) {
+		u32 amt;
+
+		pci_read_config_dword(dev, 0x84, &amt);
+		par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+	} else {
+		par->RamAmountKBytes =
+		    (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
+	}
+	pci_dev_put(dev);
+
+	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
+	    14318 : 13500;
+
+	if (par->twoHeads && (implementation != 0x0110)) {
+		if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22))
+			par->CrystalFreqKHz = 27000;
+	}
+
+	par->CURSOR = NULL;	/* can't set this here */
+	par->MinVClockFreqKHz = 12000;
+	par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
+}
+
+int NVCommonSetup(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct fb_var_screeninfo *var;
+	u16 implementation = par->Chipset & 0x0ff0;
+	u8 *edidA = NULL, *edidB = NULL;
+	struct fb_monspecs *monitorA, *monitorB;
+	struct fb_monspecs *monA = NULL, *monB = NULL;
+	int mobile = 0;
+	int tvA = 0;
+	int tvB = 0;
+	int FlatPanel = -1;	/* really means the CRTC is slaved */
+	int Television = 0;
+	int err = 0;
+
+	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+	monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+	monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+
+	if (!var || !monitorA || !monitorB) {
+		err = -ENOMEM;
+		goto done;
+	}
+
+	par->PRAMIN = par->REGS + (0x00710000 / 4);
+	par->PCRTC0 = par->REGS + (0x00600000 / 4);
+	par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
+	par->PFB = par->REGS + (0x00100000 / 4);
+	par->PFIFO = par->REGS + (0x00002000 / 4);
+	par->PGRAPH = par->REGS + (0x00400000 / 4);
+	par->PEXTDEV = par->REGS + (0x00101000 / 4);
+	par->PTIMER = par->REGS + (0x00009000 / 4);
+	par->PMC = par->REGS + (0x00000000 / 4);
+	par->FIFO = par->REGS + (0x00800000 / 4);
+
+	/* 8 bit registers */
+	par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000;
+	par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000;
+	par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000;
+
+	par->twoHeads = (par->Architecture >= NV_ARCH_10) &&
+	    (implementation != 0x0100) &&
+	    (implementation != 0x0150) &&
+	    (implementation != 0x01A0) && (implementation != 0x0200);
+
+	par->fpScaler = (par->FpScale && par->twoHeads &&
+			 (implementation != 0x0110));
+
+	par->twoStagePLL = (implementation == 0x0310) ||
+	    (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40);
+
+	par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) &&
+	    (implementation != 0x0100);
+
+	par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020);
+
+	/* look for known laptop chips */
+	switch (par->Chipset & 0xffff) {
+	case 0x0112:
+	case 0x0174:
+	case 0x0175:
+	case 0x0176:
+	case 0x0177:
+	case 0x0179:
+	case 0x017C:
+	case 0x017D:
+	case 0x0186:
+	case 0x0187:
+	case 0x018D:
+	case 0x01D7:
+	case 0x0228:
+	case 0x0286:
+	case 0x028C:
+	case 0x0316:
+	case 0x0317:
+	case 0x031A:
+	case 0x031B:
+	case 0x031C:
+	case 0x031D:
+	case 0x031E:
+	case 0x031F:
+	case 0x0324:
+	case 0x0325:
+	case 0x0328:
+	case 0x0329:
+	case 0x032C:
+	case 0x032D:
+	case 0x0347:
+	case 0x0348:
+	case 0x0349:
+	case 0x034B:
+	case 0x034C:
+	case 0x0160:
+	case 0x0166:
+	case 0x0169:
+	case 0x016B:
+	case 0x016C:
+	case 0x016D:
+	case 0x00C8:
+	case 0x00CC:
+	case 0x0144:
+	case 0x0146:
+	case 0x0147:
+	case 0x0148:
+	case 0x0098:
+	case 0x0099:
+		mobile = 1;
+		break;
+	default:
+		break;
+	}
+
+	if (par->Architecture == NV_ARCH_04)
+		nv4GetConfig(par);
+	else
+		nv10GetConfig(par);
+
+	NVSelectHeadRegisters(par, 0);
+
+	NVLockUnlock(par, 0);
+
+	par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0;
+
+	par->Television = 0;
+
+	nvidia_create_i2c_busses(par);
+	if (!par->twoHeads) {
+		par->CRTCnumber = 0;
+		if (nvidia_probe_i2c_connector(info, 1, &edidA))
+			nvidia_probe_of_connector(info, 1, &edidA);
+		if (edidA && !fb_parse_edid(edidA, var)) {
+			printk("nvidiafb: EDID found from BUS1\n");
+			monA = monitorA;
+			fb_edid_to_monspecs(edidA, monA);
+			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+
+			/* NV4 doesn't support FlatPanels */
+			if ((par->Chipset & 0x0fff) <= 0x0020)
+				FlatPanel = 0;
+		} else {
+			VGA_WR08(par->PCIO, 0x03D4, 0x28);
+			if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) {
+				VGA_WR08(par->PCIO, 0x03D4, 0x33);
+				if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01))
+					Television = 1;
+				FlatPanel = 1;
+			} else {
+				FlatPanel = 0;
+			}
+			printk("nvidiafb: HW is currently programmed for %s\n",
+			       FlatPanel ? (Television ? "TV" : "DFP") :
+			       "CRT");
+		}
+
+		if (par->FlatPanel == -1) {
+			par->FlatPanel = FlatPanel;
+			par->Television = Television;
+		} else {
+			printk("nvidiafb: Forcing display type to %s as "
+			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
+		}
+	} else {
+		u8 outputAfromCRTC, outputBfromCRTC;
+		int CRTCnumber = -1;
+		u8 slaved_on_A, slaved_on_B;
+		int analog_on_A, analog_on_B;
+		u32 oldhead;
+		u8 cr44;
+
+		if (implementation != 0x0110) {
+			if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100)
+				outputAfromCRTC = 1;
+			else
+				outputAfromCRTC = 0;
+			if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100)
+				outputBfromCRTC = 1;
+			else
+				outputBfromCRTC = 0;
+			analog_on_A = NVIsConnected(par, 0);
+			analog_on_B = NVIsConnected(par, 1);
+		} else {
+			outputAfromCRTC = 0;
+			outputBfromCRTC = 1;
+			analog_on_A = 0;
+			analog_on_B = 0;
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		cr44 = VGA_RD08(par->PCIO, 0x03D5);
+
+		VGA_WR08(par->PCIO, 0x03D5, 3);
+		NVSelectHeadRegisters(par, 1);
+		NVLockUnlock(par, 0);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x28);
+		slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+		if (slaved_on_B) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x33);
+			tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, 0);
+		NVSelectHeadRegisters(par, 0);
+		NVLockUnlock(par, 0);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x28);
+		slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+		if (slaved_on_A) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x33);
+			tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+		}
+
+		oldhead = NV_RD32(par->PCRTC0, 0x00000860);
+		NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
+
+		if (nvidia_probe_i2c_connector(info, 1, &edidA))
+			nvidia_probe_of_connector(info, 1, &edidA);
+		if (edidA && !fb_parse_edid(edidA, var)) {
+			printk("nvidiafb: EDID found from BUS1\n");
+			monA = monitorA;
+			fb_edid_to_monspecs(edidA, monA);
+		}
+
+		if (nvidia_probe_i2c_connector(info, 2, &edidB))
+			nvidia_probe_of_connector(info, 2, &edidB);
+		if (edidB && !fb_parse_edid(edidB, var)) {
+			printk("nvidiafb: EDID found from BUS2\n");
+			monB = monitorB;
+			fb_edid_to_monspecs(edidB, monB);
+		}
+
+		if (slaved_on_A && !tvA) {
+			CRTCnumber = 0;
+			FlatPanel = 1;
+			printk("nvidiafb: CRTC 0 is currently programmed for "
+			       "DFP\n");
+		} else if (slaved_on_B && !tvB) {
+			CRTCnumber = 1;
+			FlatPanel = 1;
+			printk("nvidiafb: CRTC 1 is currently programmed "
+			       "for DFP\n");
+		} else if (analog_on_A) {
+			CRTCnumber = outputAfromCRTC;
+			FlatPanel = 0;
+			printk("nvidiafb: CRTC %i appears to have a "
+			       "CRT attached\n", CRTCnumber);
+		} else if (analog_on_B) {
+			CRTCnumber = outputBfromCRTC;
+			FlatPanel = 0;
+			printk("nvidiafb: CRTC %i appears to have a "
+			       "CRT attached\n", CRTCnumber);
+		} else if (slaved_on_A) {
+			CRTCnumber = 0;
+			FlatPanel = 1;
+			Television = 1;
+			printk("nvidiafb: CRTC 0 is currently programmed "
+			       "for TV\n");
+		} else if (slaved_on_B) {
+			CRTCnumber = 1;
+			FlatPanel = 1;
+			Television = 1;
+			printk("nvidiafb: CRTC 1 is currently programmed for "
+			       "TV\n");
+		} else if (monA) {
+			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+		} else if (monB) {
+			FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0;
+		}
+
+		if (par->FlatPanel == -1) {
+			if (FlatPanel != -1) {
+				par->FlatPanel = FlatPanel;
+				par->Television = Television;
+			} else {
+				printk("nvidiafb: Unable to detect display "
+				       "type...\n");
+				if (mobile) {
+					printk("...On a laptop, assuming "
+					       "DFP\n");
+					par->FlatPanel = 1;
+				} else {
+					printk("...Using default of CRT\n");
+					par->FlatPanel = 0;
+				}
+			}
+		} else {
+			printk("nvidiafb: Forcing display type to %s as "
+			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
+		}
+
+		if (par->CRTCnumber == -1) {
+			if (CRTCnumber != -1)
+				par->CRTCnumber = CRTCnumber;
+			else {
+				printk("nvidiafb: Unable to detect which "
+				       "CRTCNumber...\n");
+				if (par->FlatPanel)
+					par->CRTCnumber = 1;
+				else
+					par->CRTCnumber = 0;
+				printk("...Defaulting to CRTCNumber %i\n",
+				       par->CRTCnumber);
+			}
+		} else {
+			printk("nvidiafb: Forcing CRTCNumber %i as "
+			       "specified\n", par->CRTCnumber);
+		}
+
+		if (monA) {
+			if (((monA->input & FB_DISP_DDI) &&
+			     par->FlatPanel) ||
+			    ((!(monA->input & FB_DISP_DDI)) &&
+			     !par->FlatPanel)) {
+				if (monB) {
+					fb_destroy_modedb(monB->modedb);
+					monB = NULL;
+				}
+			} else {
+				fb_destroy_modedb(monA->modedb);
+				monA = NULL;
+			}
+		}
+
+		if (monB) {
+			if (((monB->input & FB_DISP_DDI) &&
+			     !par->FlatPanel) ||
+			    ((!(monB->input & FB_DISP_DDI)) &&
+			     par->FlatPanel)) {
+				fb_destroy_modedb(monB->modedb);
+				monB = NULL;
+			} else
+				monA = monB;
+		}
+
+		if (implementation == 0x0110)
+			cr44 = par->CRTCnumber * 0x3;
+
+		NV_WR32(par->PCRTC0, 0x00000860, oldhead);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, cr44);
+		NVSelectHeadRegisters(par, par->CRTCnumber);
+	}
+
+	printk("nvidiafb: Using %s on CRTC %i\n",
+	       par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT",
+	       par->CRTCnumber);
+
+	if (par->FlatPanel && !par->Television) {
+		par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1;
+		par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1;
+		par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033;
+
+		printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight);
+	}
+
+	if (monA)
+		info->monspecs = *monA;
+
+	if (!par->FlatPanel || !par->twoHeads)
+		par->FPDither = 0;
+
+	par->LVDS = 0;
+	if (par->FlatPanel && par->twoHeads) {
+		NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004);
+		if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1)
+			par->LVDS = 1;
+		printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS");
+	}
+
+	kfree(edidA);
+	kfree(edidB);
+done:
+	kfree(var);
+	kfree(monitorA);
+	kfree(monitorB);
+	return err;
+}
diff --git a/drivers/video/fbdev/nvidia/nv_type.h b/drivers/video/fbdev/nvidia/nv_type.h
new file mode 100644
index 000000000000..c03f7f55c76d
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nv_type.h
@@ -0,0 +1,180 @@
+#ifndef __NV_TYPE_H__
+#define __NV_TYPE_H__
+
+#include <linux/fb.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <video/vga.h>
+
+#define NV_ARCH_04  0x04
+#define NV_ARCH_10  0x10
+#define NV_ARCH_20  0x20
+#define NV_ARCH_30  0x30
+#define NV_ARCH_40  0x40
+
+#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1)  << (b))
+#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
+#define SetBF(mask,value) ((value) << (0?mask))
+#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
+#define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
+#define SetBit(n) (1<<(n))
+#define Set8Bits(value) ((value)&0xff)
+
+#define V_DBLSCAN  1
+
+typedef struct {
+	int bitsPerPixel;
+	int depth;
+	int displayWidth;
+	int weight;
+} NVFBLayout;
+
+#define NUM_SEQ_REGS		0x05
+#define NUM_CRT_REGS		0x41
+#define NUM_GRC_REGS		0x09
+#define NUM_ATC_REGS		0x15
+
+struct nvidia_par;
+
+struct nvidia_i2c_chan {
+	struct nvidia_par *par;
+	unsigned long ddc_base;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+};
+
+typedef struct _riva_hw_state {
+	u8 attr[NUM_ATC_REGS];
+	u8 crtc[NUM_CRT_REGS];
+	u8 gra[NUM_GRC_REGS];
+	u8 seq[NUM_SEQ_REGS];
+	u8 misc_output;
+	u32 bpp;
+	u32 width;
+	u32 height;
+	u32 interlace;
+	u32 repaint0;
+	u32 repaint1;
+	u32 screen;
+	u32 scale;
+	u32 dither;
+	u32 extra;
+	u32 fifo;
+	u32 pixel;
+	u32 horiz;
+	u32 arbitration0;
+	u32 arbitration1;
+	u32 pll;
+	u32 pllB;
+	u32 vpll;
+	u32 vpll2;
+	u32 vpllB;
+	u32 vpll2B;
+	u32 pllsel;
+	u32 general;
+	u32 crtcOwner;
+	u32 head;
+	u32 head2;
+	u32 config;
+	u32 cursorConfig;
+	u32 cursor0;
+	u32 cursor1;
+	u32 cursor2;
+	u32 timingH;
+	u32 timingV;
+	u32 displayV;
+	u32 crtcSync;
+	u32 control;
+} RIVA_HW_STATE;
+
+struct riva_regs {
+	RIVA_HW_STATE ext;
+};
+
+struct nvidia_par {
+	RIVA_HW_STATE SavedReg;
+	RIVA_HW_STATE ModeReg;
+	RIVA_HW_STATE initial_state;
+	RIVA_HW_STATE *CurrentState;
+	struct vgastate vgastate;
+	u32 pseudo_palette[16];
+	struct pci_dev *pci_dev;
+	u32 Architecture;
+	u32 CursorStart;
+	int Chipset;
+	unsigned long FbAddress;
+	u8 __iomem *FbStart;
+	u32 FbMapSize;
+	u32 FbUsableSize;
+	u32 ScratchBufferSize;
+	u32 ScratchBufferStart;
+	int FpScale;
+	u32 MinVClockFreqKHz;
+	u32 MaxVClockFreqKHz;
+	u32 CrystalFreqKHz;
+	u32 RamAmountKBytes;
+	u32 IOBase;
+	NVFBLayout CurrentLayout;
+	int cursor_reset;
+	int lockup;
+	int videoKey;
+	int FlatPanel;
+	int FPDither;
+	int Television;
+	int CRTCnumber;
+	int alphaCursor;
+	int twoHeads;
+	int twoStagePLL;
+	int fpScaler;
+	int fpWidth;
+	int fpHeight;
+	int PanelTweak;
+	int paneltweak;
+	int LVDS;
+	int pm_state;
+	int reverse_i2c;
+	u32 crtcSync_read;
+	u32 fpSyncs;
+	u32 dmaPut;
+	u32 dmaCurrent;
+	u32 dmaFree;
+	u32 dmaMax;
+	u32 __iomem *dmaBase;
+	u32 currentRop;
+	int WaitVSyncPossible;
+	int BlendingPossible;
+	u32 paletteEnabled;
+	u32 forceCRTC;
+	u32 open_count;
+	u8 DDCBase;
+#ifdef CONFIG_MTRR
+	struct {
+		int vram;
+		int vram_valid;
+	} mtrr;
+#endif
+	struct nvidia_i2c_chan chan[3];
+
+	volatile u32 __iomem *REGS;
+	volatile u32 __iomem *PCRTC0;
+	volatile u32 __iomem *PCRTC;
+	volatile u32 __iomem *PRAMDAC0;
+	volatile u32 __iomem *PFB;
+	volatile u32 __iomem *PFIFO;
+	volatile u32 __iomem *PGRAPH;
+	volatile u32 __iomem *PEXTDEV;
+	volatile u32 __iomem *PTIMER;
+	volatile u32 __iomem *PMC;
+	volatile u32 __iomem *PRAMIN;
+	volatile u32 __iomem *FIFO;
+	volatile u32 __iomem *CURSOR;
+	volatile u8 __iomem *PCIO0;
+	volatile u8 __iomem *PCIO;
+	volatile u8 __iomem *PVIO;
+	volatile u8 __iomem *PDIO0;
+	volatile u8 __iomem *PDIO;
+	volatile u32 __iomem *PRAMDAC;
+};
+
+#endif				/* __NV_TYPE_H__ */
diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c
new file mode 100644
index 000000000000..def041204676
--- /dev/null
+++ b/drivers/video/fbdev/nvidia/nvidia.c
@@ -0,0 +1,1607 @@
+/*
+ * linux/drivers/video/nvidia/nvidia.c - nVidia fb driver
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h>
+#include <linux/backlight.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+#ifdef CONFIG_BOOTX_TEXT
+#include <asm/btext.h>
+#endif
+
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define NVTRACE          printk
+#else
+#define NVTRACE          if (0) printk
+#endif
+
+#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __func__)
+#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __func__)
+
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define assert(expr) \
+	if (!(expr)) { \
+	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+	#expr,__FILE__,__func__,__LINE__); \
+	BUG(); \
+	}
+#else
+#define assert(expr)
+#endif
+
+#define PFX "nvidiafb: "
+
+/* HW cursor parameters */
+#define MAX_CURS		32
+
+static struct pci_device_id nvidiafb_pci_tbl[] = {
+	{PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+	 PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0},
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
+
+/* command line data, set in nvidiafb_setup() */
+static int flatpanel = -1;	/* Autodetect later */
+static int fpdither = -1;
+static int forceCRTC = -1;
+static int hwcur = 0;
+static int noaccel = 0;
+static int noscale = 0;
+static int paneltweak = 0;
+static int vram = 0;
+static int bpp = 8;
+static int reverse_i2c;
+#ifdef CONFIG_MTRR
+static bool nomtrr = false;
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight = 1;
+#else
+static int backlight = 0;
+#endif
+
+static char *mode_option = NULL;
+
+static struct fb_fix_screeninfo nvidiafb_fix = {
+	.type = FB_TYPE_PACKED_PIXELS,
+	.xpanstep = 8,
+	.ypanstep = 1,
+};
+
+static struct fb_var_screeninfo nvidiafb_default_var = {
+	.xres = 640,
+	.yres = 480,
+	.xres_virtual = 640,
+	.yres_virtual = 480,
+	.bits_per_pixel = 8,
+	.red = {0, 8, 0},
+	.green = {0, 8, 0},
+	.blue = {0, 8, 0},
+	.transp = {0, 0, 0},
+	.activate = FB_ACTIVATE_NOW,
+	.height = -1,
+	.width = -1,
+	.pixclock = 39721,
+	.left_margin = 40,
+	.right_margin = 24,
+	.upper_margin = 32,
+	.lower_margin = 11,
+	.hsync_len = 96,
+	.vsync_len = 2,
+	.vmode = FB_VMODE_NONINTERLACED
+};
+
+static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
+				       u16 bg, u16 fg, u32 w, u32 h)
+{
+	u32 *data = (u32 *) data8;
+	int i, j, k = 0;
+	u32 b, tmp;
+
+	w = (w + 1) & ~1;
+
+	for (i = 0; i < h; i++) {
+		b = *data++;
+		reverse_order(&b);
+
+		for (j = 0; j < w / 2; j++) {
+			tmp = 0;
+#if defined (__BIG_ENDIAN)
+			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
+			b <<= 1;
+			tmp |= (b & (1 << 31)) ? fg : bg;
+			b <<= 1;
+#else
+			tmp = (b & 1) ? fg : bg;
+			b >>= 1;
+			tmp |= (b & 1) ? fg << 16 : bg << 16;
+			b >>= 1;
+#endif
+			NV_WR32(&par->CURSOR[k++], 0, tmp);
+		}
+		k += (MAX_CURS - w) / 2;
+	}
+}
+
+static void nvidia_write_clut(struct nvidia_par *par,
+			      u8 regnum, u8 red, u8 green, u8 blue)
+{
+	NVWriteDacMask(par, 0xff);
+	NVWriteDacWriteAddr(par, regnum);
+	NVWriteDacData(par, red);
+	NVWriteDacData(par, green);
+	NVWriteDacData(par, blue);
+}
+
+static void nvidia_read_clut(struct nvidia_par *par,
+			     u8 regnum, u8 * red, u8 * green, u8 * blue)
+{
+	NVWriteDacMask(par, 0xff);
+	NVWriteDacReadAddr(par, regnum);
+	*red = NVReadDacData(par);
+	*green = NVReadDacData(par);
+	*blue = NVReadDacData(par);
+}
+
+static int nvidia_panel_tweak(struct nvidia_par *par,
+			      struct _riva_hw_state *state)
+{
+	int tweak = 0;
+
+   if (par->paneltweak) {
+	   tweak = par->paneltweak;
+   } else {
+	   /* begin flat panel hacks */
+	   /* This is unfortunate, but some chips need this register
+	      tweaked or else you get artifacts where adjacent pixels are
+	      swapped.  There are no hard rules for what to set here so all
+	      we can do is experiment and apply hacks. */
+
+	   if(((par->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
+		   /* At least one NV34 laptop needs this workaround. */
+		   tweak = -1;
+	   }
+
+	   if((par->Chipset & 0xfff0) == 0x0310) {
+		   tweak = 1;
+	   }
+	   /* end flat panel hacks */
+   }
+
+   return tweak;
+}
+
+static void nvidia_screen_off(struct nvidia_par *par, int on)
+{
+	unsigned char tmp;
+
+	if (on) {
+		/*
+		 * Turn off screen and disable sequencer.
+		 */
+		tmp = NVReadSeq(par, 0x01);
+
+		NVWriteSeq(par, 0x00, 0x01);		/* Synchronous Reset */
+		NVWriteSeq(par, 0x01, tmp | 0x20);	/* disable the display */
+	} else {
+		/*
+		 * Reenable sequencer, then turn on screen.
+		 */
+
+		tmp = NVReadSeq(par, 0x01);
+
+		NVWriteSeq(par, 0x01, tmp & ~0x20);	/* reenable display */
+		NVWriteSeq(par, 0x00, 0x03);		/* End Reset */
+	}
+}
+
+static void nvidia_save_vga(struct nvidia_par *par,
+			    struct _riva_hw_state *state)
+{
+	int i;
+
+	NVTRACE_ENTER();
+	NVLockUnlock(par, 0);
+
+	NVUnloadStateExt(par, state);
+
+	state->misc_output = NVReadMiscOut(par);
+
+	for (i = 0; i < NUM_CRT_REGS; i++)
+		state->crtc[i] = NVReadCrtc(par, i);
+
+	for (i = 0; i < NUM_ATC_REGS; i++)
+		state->attr[i] = NVReadAttr(par, i);
+
+	for (i = 0; i < NUM_GRC_REGS; i++)
+		state->gra[i] = NVReadGr(par, i);
+
+	for (i = 0; i < NUM_SEQ_REGS; i++)
+		state->seq[i] = NVReadSeq(par, i);
+	NVTRACE_LEAVE();
+}
+
+#undef DUMP_REG
+
+static void nvidia_write_regs(struct nvidia_par *par,
+			      struct _riva_hw_state *state)
+{
+	int i;
+
+	NVTRACE_ENTER();
+
+	NVLoadStateExt(par, state);
+
+	NVWriteMiscOut(par, state->misc_output);
+
+	for (i = 1; i < NUM_SEQ_REGS; i++) {
+#ifdef DUMP_REG
+		printk(" SEQ[%02x] = %08x\n", i, state->seq[i]);
+#endif
+		NVWriteSeq(par, i, state->seq[i]);
+	}
+
+	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
+	NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80);
+
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		switch (i) {
+		case 0x19:
+		case 0x20 ... 0x40:
+			break;
+		default:
+#ifdef DUMP_REG
+			printk("CRTC[%02x] = %08x\n", i, state->crtc[i]);
+#endif
+			NVWriteCrtc(par, i, state->crtc[i]);
+		}
+	}
+
+	for (i = 0; i < NUM_GRC_REGS; i++) {
+#ifdef DUMP_REG
+		printk(" GRA[%02x] = %08x\n", i, state->gra[i]);
+#endif
+		NVWriteGr(par, i, state->gra[i]);
+	}
+
+	for (i = 0; i < NUM_ATC_REGS; i++) {
+#ifdef DUMP_REG
+		printk("ATTR[%02x] = %08x\n", i, state->attr[i]);
+#endif
+		NVWriteAttr(par, i, state->attr[i]);
+	}
+
+	NVTRACE_LEAVE();
+}
+
+static int nvidia_calc_regs(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i, depth = fb_get_color_depth(&info->var, &info->fix);
+	int h_display = info->var.xres / 8 - 1;
+	int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
+	int h_end = (info->var.xres + info->var.right_margin +
+		     info->var.hsync_len) / 8 - 1;
+	int h_total = (info->var.xres + info->var.right_margin +
+		       info->var.hsync_len + info->var.left_margin) / 8 - 5;
+	int h_blank_s = h_display;
+	int h_blank_e = h_total + 4;
+	int v_display = info->var.yres - 1;
+	int v_start = info->var.yres + info->var.lower_margin - 1;
+	int v_end = (info->var.yres + info->var.lower_margin +
+		     info->var.vsync_len) - 1;
+	int v_total = (info->var.yres + info->var.lower_margin +
+		       info->var.vsync_len + info->var.upper_margin) - 2;
+	int v_blank_s = v_display;
+	int v_blank_e = v_total + 1;
+
+	/*
+	 * Set all CRTC values.
+	 */
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		v_total |= 1;
+
+	if (par->FlatPanel == 1) {
+		v_start = v_total - 3;
+		v_end = v_total - 2;
+		v_blank_s = v_start;
+		h_start = h_total - 5;
+		h_end = h_total - 2;
+		h_blank_e = h_total + 4;
+	}
+
+	state->crtc[0x0] = Set8Bits(h_total);
+	state->crtc[0x1] = Set8Bits(h_display);
+	state->crtc[0x2] = Set8Bits(h_blank_s);
+	state->crtc[0x3] = SetBitField(h_blank_e, 4: 0, 4:0)
+		| SetBit(7);
+	state->crtc[0x4] = Set8Bits(h_start);
+	state->crtc[0x5] = SetBitField(h_blank_e, 5: 5, 7:7)
+		| SetBitField(h_end, 4: 0, 4:0);
+	state->crtc[0x6] = SetBitField(v_total, 7: 0, 7:0);
+	state->crtc[0x7] = SetBitField(v_total, 8: 8, 0:0)
+		| SetBitField(v_display, 8: 8, 1:1)
+		| SetBitField(v_start, 8: 8, 2:2)
+		| SetBitField(v_blank_s, 8: 8, 3:3)
+		| SetBit(4)
+		| SetBitField(v_total, 9: 9, 5:5)
+		| SetBitField(v_display, 9: 9, 6:6)
+		| SetBitField(v_start, 9: 9, 7:7);
+	state->crtc[0x9] = SetBitField(v_blank_s, 9: 9, 5:5)
+		| SetBit(6)
+		| ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0x00);
+	state->crtc[0x10] = Set8Bits(v_start);
+	state->crtc[0x11] = SetBitField(v_end, 3: 0, 3:0) | SetBit(5);
+	state->crtc[0x12] = Set8Bits(v_display);
+	state->crtc[0x13] = ((info->var.xres_virtual / 8) *
+			     (info->var.bits_per_pixel / 8));
+	state->crtc[0x15] = Set8Bits(v_blank_s);
+	state->crtc[0x16] = Set8Bits(v_blank_e);
+
+	state->attr[0x10] = 0x01;
+
+	if (par->Television)
+		state->attr[0x11] = 0x00;
+
+	state->screen = SetBitField(h_blank_e, 6: 6, 4:4)
+		| SetBitField(v_blank_s, 10: 10, 3:3)
+		| SetBitField(v_start, 10: 10, 2:2)
+		| SetBitField(v_display, 10: 10, 1:1)
+		| SetBitField(v_total, 10: 10, 0:0);
+
+	state->horiz = SetBitField(h_total, 8: 8, 0:0)
+		| SetBitField(h_display, 8: 8, 1:1)
+		| SetBitField(h_blank_s, 8: 8, 2:2)
+		| SetBitField(h_start, 8: 8, 3:3);
+
+	state->extra = SetBitField(v_total, 11: 11, 0:0)
+		| SetBitField(v_display, 11: 11, 2:2)
+		| SetBitField(v_start, 11: 11, 4:4)
+		| SetBitField(v_blank_s, 11: 11, 6:6);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED) {
+		h_total = (h_total >> 1) & ~1;
+		state->interlace = Set8Bits(h_total);
+		state->horiz |= SetBitField(h_total, 8: 8, 4:4);
+	} else {
+		state->interlace = 0xff;	/* interlace off */
+	}
+
+	/*
+	 * Calculate the extended registers.
+	 */
+
+	if (depth < 24)
+		i = depth;
+	else
+		i = 32;
+
+	if (par->Architecture >= NV_ARCH_10)
+		par->CURSOR = (volatile u32 __iomem *)(info->screen_base +
+						       par->CursorStart);
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		state->misc_output &= ~0x40;
+	else
+		state->misc_output |= 0x40;
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		state->misc_output &= ~0x80;
+	else
+		state->misc_output |= 0x80;
+
+	NVCalcStateExt(par, state, i, info->var.xres_virtual,
+		       info->var.xres, info->var.yres_virtual,
+		       1000000000 / info->var.pixclock, info->var.vmode);
+
+	state->scale = NV_RD32(par->PRAMDAC, 0x00000848) & 0xfff000ff;
+	if (par->FlatPanel == 1) {
+		state->pixel |= (1 << 7);
+
+		if (!par->fpScaler || (par->fpWidth <= info->var.xres)
+		    || (par->fpHeight <= info->var.yres)) {
+			state->scale |= (1 << 8);
+		}
+
+		if (!par->crtcSync_read) {
+			state->crtcSync = NV_RD32(par->PRAMDAC, 0x0828);
+			par->crtcSync_read = 1;
+		}
+
+		par->PanelTweak = nvidia_panel_tweak(par, state);
+	}
+
+	state->vpll = state->pll;
+	state->vpll2 = state->pll;
+	state->vpllB = state->pllB;
+	state->vpll2B = state->pllB;
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	state->fifo = VGA_RD08(par->PCIO, 0x03D5) & ~(1<<5);
+
+	if (par->CRTCnumber) {
+		state->head = NV_RD32(par->PCRTC0, 0x00000860) & ~0x00001000;
+		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) | 0x00001000;
+		state->crtcOwner = 3;
+		state->pllsel |= 0x20000800;
+		state->vpll = NV_RD32(par->PRAMDAC0, 0x00000508);
+		if (par->twoStagePLL)
+			state->vpllB = NV_RD32(par->PRAMDAC0, 0x00000578);
+	} else if (par->twoHeads) {
+		state->head = NV_RD32(par->PCRTC0, 0x00000860) | 0x00001000;
+		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) & ~0x00001000;
+		state->crtcOwner = 0;
+		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+		if (par->twoStagePLL)
+			state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+	}
+
+	state->cursorConfig = 0x00000100;
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		state->cursorConfig |= (1 << 4);
+
+	if (par->alphaCursor) {
+		if ((par->Chipset & 0x0ff0) != 0x0110)
+			state->cursorConfig |= 0x04011000;
+		else
+			state->cursorConfig |= 0x14011000;
+		state->general |= (1 << 29);
+	} else
+		state->cursorConfig |= 0x02000000;
+
+	if (par->twoHeads) {
+		if ((par->Chipset & 0x0ff0) == 0x0110) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x0528) &
+			    ~0x00010000;
+			if (par->FPDither)
+				state->dither |= 0x00010000;
+		} else {
+			state->dither = NV_RD32(par->PRAMDAC, 0x083C) & ~1;
+			if (par->FPDither)
+				state->dither |= 1;
+		}
+	}
+
+	state->timingH = 0;
+	state->timingV = 0;
+	state->displayV = info->var.xres;
+
+	return 0;
+}
+
+static void nvidia_init_vga(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i;
+
+	for (i = 0; i < 0x10; i++)
+		state->attr[i] = i;
+	state->attr[0x10] = 0x41;
+	state->attr[0x11] = 0xff;
+	state->attr[0x12] = 0x0f;
+	state->attr[0x13] = 0x00;
+	state->attr[0x14] = 0x00;
+
+	memset(state->crtc, 0x00, NUM_CRT_REGS);
+	state->crtc[0x0a] = 0x20;
+	state->crtc[0x17] = 0xe3;
+	state->crtc[0x18] = 0xff;
+	state->crtc[0x28] = 0x40;
+
+	memset(state->gra, 0x00, NUM_GRC_REGS);
+	state->gra[0x05] = 0x40;
+	state->gra[0x06] = 0x05;
+	state->gra[0x07] = 0x0f;
+	state->gra[0x08] = 0xff;
+
+	state->seq[0x00] = 0x03;
+	state->seq[0x01] = 0x01;
+	state->seq[0x02] = 0x0f;
+	state->seq[0x03] = 0x00;
+	state->seq[0x04] = 0x0e;
+
+	state->misc_output = 0xeb;
+}
+
+static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct nvidia_par *par = info->par;
+	u8 data[MAX_CURS * MAX_CURS / 8];
+	int i, set = cursor->set;
+	u16 fg, bg;
+
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return -ENXIO;
+
+	NVShowHideCursor(par, 0);
+
+	if (par->cursor_reset) {
+		set = FB_CUR_SETALL;
+		par->cursor_reset = 0;
+	}
+
+	if (set & FB_CUR_SETSIZE)
+		memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+
+	if (set & FB_CUR_SETPOS) {
+		u32 xx, yy, temp;
+
+		yy = cursor->image.dy - info->var.yoffset;
+		xx = cursor->image.dx - info->var.xoffset;
+		temp = xx & 0xFFFF;
+		temp |= yy << 16;
+
+		NV_WR32(par->PRAMDAC, 0x0000300, temp);
+	}
+
+	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		u32 bg_idx = cursor->image.bg_color;
+		u32 fg_idx = cursor->image.fg_color;
+		u32 s_pitch = (cursor->image.width + 7) >> 3;
+		u32 d_pitch = MAX_CURS / 8;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) cursor->mask;
+		u8 *src;
+
+		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+
+		if (src) {
+			switch (cursor->rop) {
+			case ROP_XOR:
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
+					src[i] = dat[i] ^ msk[i];
+				break;
+			case ROP_COPY:
+			default:
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
+					src[i] = dat[i] & msk[i];
+				break;
+			}
+
+			fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+						cursor->image.height);
+
+			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+			    ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+			    ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
+
+			fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+			    ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+			    ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
+
+			NVLockUnlock(par, 0);
+
+			nvidiafb_load_cursor_image(par, data, bg, fg,
+						   cursor->image.width,
+						   cursor->image.height);
+			kfree(src);
+		}
+	}
+
+	if (cursor->enable)
+		NVShowHideCursor(par, 1);
+
+	return 0;
+}
+
+static int nvidiafb_set_par(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+
+	NVTRACE_ENTER();
+
+	NVLockUnlock(par, 1);
+	if (!par->FlatPanel || !par->twoHeads)
+		par->FPDither = 0;
+
+	if (par->FPDither < 0) {
+		if ((par->Chipset & 0x0ff0) == 0x0110)
+			par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528)
+					   & 0x00010000);
+		else
+			par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1);
+		printk(KERN_INFO PFX "Flat panel dithering %s\n",
+		       par->FPDither ? "enabled" : "disabled");
+	}
+
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+	nvidia_init_vga(info);
+	nvidia_calc_regs(info);
+
+	NVLockUnlock(par, 0);
+	if (par->twoHeads) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);
+		NVLockUnlock(par, 0);
+	}
+
+	nvidia_screen_off(par, 1);
+
+	nvidia_write_regs(par, &par->ModeReg);
+	NVSetStartAddress(par, 0);
+
+#if defined (__BIG_ENDIAN)
+	/* turn on LFB swapping */
+	{
+		unsigned char tmp;
+
+		VGA_WR08(par->PCIO, 0x3d4, 0x46);
+		tmp = VGA_RD08(par->PCIO, 0x3d5);
+		tmp |= (1 << 7);
+		VGA_WR08(par->PCIO, 0x3d5, tmp);
+    }
+#endif
+
+	info->fix.line_length = (info->var.xres_virtual *
+				 info->var.bits_per_pixel) >> 3;
+	if (info->var.accel_flags) {
+		info->fbops->fb_imageblit = nvidiafb_imageblit;
+		info->fbops->fb_fillrect = nvidiafb_fillrect;
+		info->fbops->fb_copyarea = nvidiafb_copyarea;
+		info->fbops->fb_sync = nvidiafb_sync;
+		info->pixmap.scan_align = 4;
+		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		info->flags |= FBINFO_READS_FAST;
+		NVResetGraphics(info);
+	} else {
+		info->fbops->fb_imageblit = cfb_imageblit;
+		info->fbops->fb_fillrect = cfb_fillrect;
+		info->fbops->fb_copyarea = cfb_copyarea;
+		info->fbops->fb_sync = NULL;
+		info->pixmap.scan_align = 1;
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+		info->flags &= ~FBINFO_READS_FAST;
+	}
+
+	par->cursor_reset = 1;
+
+	nvidia_screen_off(par, 0);
+
+#ifdef CONFIG_BOOTX_TEXT
+	/* Update debug text engine */
+	btext_update_display(info->fix.smem_start,
+			     info->var.xres, info->var.yres,
+			     info->var.bits_per_pixel, info->fix.line_length);
+#endif
+
+	NVLockUnlock(par, 0);
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int i;
+
+	NVTRACE_ENTER();
+	if (regno >= (1 << info->var.green.length))
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		((u32 *) info->pseudo_palette)[regno] =
+		    (regno << info->var.red.offset) |
+		    (regno << info->var.green.offset) |
+		    (regno << info->var.blue.offset);
+	}
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	case 16:
+		if (info->var.green.length == 5) {
+			for (i = 0; i < 8; i++) {
+				nvidia_write_clut(par, regno * 8 + i, red >> 8,
+						  green >> 8, blue >> 8);
+			}
+		} else {
+			u8 r, g, b;
+
+			if (regno < 32) {
+				for (i = 0; i < 8; i++) {
+					nvidia_write_clut(par, regno * 8 + i,
+							  red >> 8, green >> 8,
+							  blue >> 8);
+				}
+			}
+
+			nvidia_read_clut(par, regno * 4, &r, &g, &b);
+
+			for (i = 0; i < 4; i++)
+				nvidia_write_clut(par, regno * 4 + i, r,
+						  green >> 8, b);
+		}
+		break;
+	case 32:
+		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int nvidiafb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int memlen, vramlen, mode_valid = 0;
+	int pitch, err = 0;
+
+	NVTRACE_ENTER();
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+
+	var->xres &= ~7;
+
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else
+		var->bits_per_pixel = 32;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:
+		var->green.length = (var->green.length < 6) ? 5 : 6;
+		var->red.length = 5;
+		var->blue.length = 5;
+		var->transp.length = 6 - var->green.length;
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 5 + var->green.length;
+		var->transp.offset = (5 + var->red.offset) & 15;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		break;
+	}
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
+		mode_valid = 1;
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+
+	if (!mode_valid) {
+		const struct fb_videomode *mode;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			fb_videomode_to_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	/*
+	 * If we're on a flat panel, check if the mode is outside of the
+	 * panel dimensions. If so, cap it and try for the next best mode
+	 * before bailing out.
+	 */
+	if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
+					      par->fpHeight < var->yres)) {
+		const struct fb_videomode *mode;
+
+		var->xres = par->fpWidth;
+		var->yres = par->fpHeight;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (!mode) {
+			printk(KERN_ERR PFX "mode out of range of flat "
+			       "panel dimensions\n");
+			return -EINVAL;
+		}
+
+		fb_videomode_to_var(var, mode);
+	}
+
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	var->xres_virtual = (var->xres_virtual + 63) & ~63;
+
+	vramlen = info->screen_size;
+	pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
+	memlen = pitch * var->yres_virtual;
+
+	if (memlen > vramlen) {
+		var->yres_virtual = vramlen / pitch;
+
+		if (var->yres_virtual < var->yres) {
+			var->yres_virtual = var->yres;
+			var->xres_virtual = vramlen / var->yres_virtual;
+			var->xres_virtual /= var->bits_per_pixel / 8;
+			var->xres_virtual &= ~63;
+			pitch = (var->xres_virtual *
+				 var->bits_per_pixel + 7) / 8;
+			memlen = pitch * var->yres;
+
+			if (var->xres_virtual < var->xres) {
+				printk("nvidiafb: required video memory, "
+				       "%d bytes, for %dx%d-%d (virtual) "
+				       "is out of range\n",
+				       memlen, var->xres_virtual,
+				       var->yres_virtual, var->bits_per_pixel);
+				err = -ENOMEM;
+			}
+		}
+	}
+
+	if (var->accel_flags) {
+		if (var->yres_virtual > 0x7fff)
+			var->yres_virtual = 0x7fff;
+		if (var->xres_virtual > 0x7fff)
+			var->xres_virtual = 0x7fff;
+	}
+
+	var->xres_virtual &= ~63;
+
+	NVTRACE_LEAVE();
+
+	return err;
+}
+
+static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 total;
+
+	total = var->yoffset * info->fix.line_length + var->xoffset;
+
+	NVSetStartAddress(par, total);
+
+	return 0;
+}
+
+static int nvidiafb_blank(int blank, struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	unsigned char tmp, vesa;
+
+	tmp = NVReadSeq(par, 0x01) & ~0x20;	/* screen on/off */
+	vesa = NVReadCrtc(par, 0x1a) & ~0xc0;	/* sync on/off */
+
+	NVTRACE_ENTER();
+
+	if (blank)
+		tmp |= 0x20;
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		vesa |= 0x80;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		vesa |= 0x40;
+		break;
+	case FB_BLANK_POWERDOWN:
+		vesa |= 0xc0;
+		break;
+	}
+
+	NVWriteSeq(par, 0x01, tmp);
+	NVWriteCrtc(par, 0x1a, vesa);
+
+	NVTRACE_LEAVE();
+
+	return 0;
+}
+
+/*
+ * Because the VGA registers are not mapped linearly in its MMIO space,
+ * restrict VGA register saving and restore to x86 only, where legacy VGA IO
+ * access is legal. Consequently, we must also check if the device is the
+ * primary display.
+ */
+#ifdef CONFIG_X86
+static void save_vga_x86(struct nvidia_par *par)
+{
+	struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
+
+	if (res && res->flags & IORESOURCE_ROM_SHADOW) {
+		memset(&par->vgastate, 0, sizeof(par->vgastate));
+		par->vgastate.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS |
+			VGA_SAVE_CMAP;
+		save_vga(&par->vgastate);
+	}
+}
+
+static void restore_vga_x86(struct nvidia_par *par)
+{
+	struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
+
+	if (res && res->flags & IORESOURCE_ROM_SHADOW)
+		restore_vga(&par->vgastate);
+}
+#else
+#define save_vga_x86(x) do {} while (0)
+#define restore_vga_x86(x) do {} while (0)
+#endif /* X86 */
+
+static int nvidiafb_open(struct fb_info *info, int user)
+{
+	struct nvidia_par *par = info->par;
+
+	if (!par->open_count) {
+		save_vga_x86(par);
+		nvidia_save_vga(par, &par->initial_state);
+	}
+
+	par->open_count++;
+	return 0;
+}
+
+static int nvidiafb_release(struct fb_info *info, int user)
+{
+	struct nvidia_par *par = info->par;
+	int err = 0;
+
+	if (!par->open_count) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	if (par->open_count == 1) {
+		nvidia_write_regs(par, &par->initial_state);
+		restore_vga_x86(par);
+	}
+
+	par->open_count--;
+done:
+	return err;
+}
+
+static struct fb_ops nvidia_fb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_open        = nvidiafb_open,
+	.fb_release     = nvidiafb_release,
+	.fb_check_var   = nvidiafb_check_var,
+	.fb_set_par     = nvidiafb_set_par,
+	.fb_setcolreg   = nvidiafb_setcolreg,
+	.fb_pan_display = nvidiafb_pan_display,
+	.fb_blank       = nvidiafb_blank,
+	.fb_fillrect    = nvidiafb_fillrect,
+	.fb_copyarea    = nvidiafb_copyarea,
+	.fb_imageblit   = nvidiafb_imageblit,
+	.fb_cursor      = nvidiafb_cursor,
+	.fb_sync        = nvidiafb_sync,
+};
+
+#ifdef CONFIG_PM
+static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t mesg)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct nvidia_par *par = info->par;
+
+	if (mesg.event == PM_EVENT_PRETHAW)
+		mesg.event = PM_EVENT_FREEZE;
+	console_lock();
+	par->pm_state = mesg.event;
+
+	if (mesg.event & PM_EVENT_SLEEP) {
+		fb_set_suspend(info, 1);
+		nvidiafb_blank(FB_BLANK_POWERDOWN, info);
+		nvidia_write_regs(par, &par->SavedReg);
+		pci_save_state(dev);
+		pci_disable_device(dev);
+		pci_set_power_state(dev, pci_choose_state(dev, mesg));
+	}
+	dev->dev.power.power_state = mesg;
+
+	console_unlock();
+	return 0;
+}
+
+static int nvidiafb_resume(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct nvidia_par *par = info->par;
+
+	console_lock();
+	pci_set_power_state(dev, PCI_D0);
+
+	if (par->pm_state != PM_EVENT_FREEZE) {
+		pci_restore_state(dev);
+
+		if (pci_enable_device(dev))
+			goto fail;
+
+		pci_set_master(dev);
+	}
+
+	par->pm_state = PM_EVENT_ON;
+	nvidiafb_set_par(info);
+	fb_set_suspend (info, 0);
+	nvidiafb_blank(FB_BLANK_UNBLANK, info);
+
+fail:
+	console_unlock();
+	return 0;
+}
+#else
+#define nvidiafb_suspend NULL
+#define nvidiafb_resume NULL
+#endif
+
+static int nvidia_set_fbinfo(struct fb_info *info)
+{
+	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode modedb;
+	struct nvidia_par *par = info->par;
+	int lpitch;
+
+	NVTRACE_ENTER();
+	info->flags = FBINFO_DEFAULT
+	    | FBINFO_HWACCEL_IMAGEBLIT
+	    | FBINFO_HWACCEL_FILLRECT
+	    | FBINFO_HWACCEL_COPYAREA
+	    | FBINFO_HWACCEL_YPAN;
+
+	fb_videomode_to_modelist(info->monspecs.modedb,
+				 info->monspecs.modedb_len, &info->modelist);
+	fb_var_to_videomode(&modedb, &nvidiafb_default_var);
+
+	switch (bpp) {
+	case 0 ... 8:
+		bpp = 8;
+		break;
+	case 9 ... 16:
+		bpp = 16;
+		break;
+	default:
+		bpp = 32;
+		break;
+	}
+
+	if (specs->modedb != NULL) {
+		const struct fb_videomode *mode;
+
+		mode = fb_find_best_display(specs, &info->modelist);
+		fb_videomode_to_var(&nvidiafb_default_var, mode);
+		nvidiafb_default_var.bits_per_pixel = bpp;
+	} else if (par->fpWidth && par->fpHeight) {
+		char buf[16];
+
+		memset(buf, 0, 16);
+		snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
+		fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
+			     specs->modedb_len, &modedb, bpp);
+	}
+
+	if (mode_option)
+		fb_find_mode(&nvidiafb_default_var, info, mode_option,
+			     specs->modedb, specs->modedb_len, &modedb, bpp);
+
+	info->var = nvidiafb_default_var;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	info->pseudo_palette = par->pseudo_palette;
+	fb_alloc_cmap(&info->cmap, 256, 0);
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual *
+		((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->screen_size / lpitch;
+
+	info->pixmap.scan_align = 4;
+	info->pixmap.buf_align = 4;
+	info->pixmap.access_align = 32;
+	info->pixmap.size = 8 * 1024;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if (!hwcur)
+	    info->fbops->fb_cursor = NULL;
+
+	info->var.accel_flags = (!noaccel);
+
+	switch (par->Architecture) {
+	case NV_ARCH_04:
+		info->fix.accel = FB_ACCEL_NV4;
+		break;
+	case NV_ARCH_10:
+		info->fix.accel = FB_ACCEL_NV_10;
+		break;
+	case NV_ARCH_20:
+		info->fix.accel = FB_ACCEL_NV_20;
+		break;
+	case NV_ARCH_30:
+		info->fix.accel = FB_ACCEL_NV_30;
+		break;
+	case NV_ARCH_40:
+		info->fix.accel = FB_ACCEL_NV_40;
+		break;
+	}
+
+	NVTRACE_LEAVE();
+
+	return nvidiafb_check_var(&info->var, info);
+}
+
+static u32 nvidia_get_chipset(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
+
+	printk(KERN_INFO PFX "Device ID: %x \n", id);
+
+	if ((id & 0xfff0) == 0x00f0 ||
+	    (id & 0xfff0) == 0x02e0) {
+		/* pci-e */
+		id = NV_RD32(par->REGS, 0x1800);
+
+		if ((id & 0x0000ffff) == 0x000010DE)
+			id = 0x10DE0000 | (id >> 16);
+		else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
+			id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
+                            ((id >> 8) & 0x000000ff);
+		printk(KERN_INFO PFX "Subsystem ID: %x \n", id);
+	}
+
+	return id;
+}
+
+static u32 nvidia_get_arch(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 arch = 0;
+
+	switch (par->Chipset & 0x0ff0) {
+	case 0x0100:		/* GeForce 256 */
+	case 0x0110:		/* GeForce2 MX */
+	case 0x0150:		/* GeForce2 */
+	case 0x0170:		/* GeForce4 MX */
+	case 0x0180:		/* GeForce4 MX (8x AGP) */
+	case 0x01A0:		/* nForce */
+	case 0x01F0:		/* nForce2 */
+		arch = NV_ARCH_10;
+		break;
+	case 0x0200:		/* GeForce3 */
+	case 0x0250:		/* GeForce4 Ti */
+	case 0x0280:		/* GeForce4 Ti (8x AGP) */
+		arch = NV_ARCH_20;
+		break;
+	case 0x0300:		/* GeForceFX 5800 */
+	case 0x0310:		/* GeForceFX 5600 */
+	case 0x0320:		/* GeForceFX 5200 */
+	case 0x0330:		/* GeForceFX 5900 */
+	case 0x0340:		/* GeForceFX 5700 */
+		arch = NV_ARCH_30;
+		break;
+	case 0x0040:		/* GeForce 6800 */
+	case 0x00C0:		/* GeForce 6800 */
+	case 0x0120:		/* GeForce 6800 */
+	case 0x0140:		/* GeForce 6600 */
+	case 0x0160:		/* GeForce 6200 */
+	case 0x01D0:		/* GeForce 7200, 7300, 7400 */
+	case 0x0090:		/* GeForce 7800 */
+	case 0x0210:		/* GeForce 6800 */
+	case 0x0220:		/* GeForce 6200 */
+	case 0x0240:		/* GeForce 6100 */
+	case 0x0290:		/* GeForce 7900 */
+	case 0x0390:		/* GeForce 7600 */
+	case 0x03D0:
+		arch = NV_ARCH_40;
+		break;
+	case 0x0020:		/* TNT, TNT2 */
+		arch = NV_ARCH_04;
+		break;
+	default:		/* unknown architecture */
+		break;
+	}
+
+	return arch;
+}
+
+static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
+{
+	struct nvidia_par *par;
+	struct fb_info *info;
+	unsigned short cmd;
+
+
+	NVTRACE_ENTER();
+	assert(pd != NULL);
+
+	info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
+
+	if (!info)
+		goto err_out;
+
+	par = info->par;
+	par->pci_dev = pd;
+	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
+
+	if (info->pixmap.addr == NULL)
+		goto err_out_kfree;
+
+	if (pci_enable_device(pd)) {
+		printk(KERN_ERR PFX "cannot enable PCI device\n");
+		goto err_out_enable;
+	}
+
+	if (pci_request_regions(pd, "nvidiafb")) {
+		printk(KERN_ERR PFX "cannot request PCI regions\n");
+		goto err_out_enable;
+	}
+
+	par->FlatPanel = flatpanel;
+	if (flatpanel == 1)
+		printk(KERN_INFO PFX "flatpanel support enabled\n");
+	par->FPDither = fpdither;
+
+	par->CRTCnumber = forceCRTC;
+	par->FpScale = (!noscale);
+	par->paneltweak = paneltweak;
+	par->reverse_i2c = reverse_i2c;
+
+	/* enable IO and mem if not already done */
+	pci_read_config_word(pd, PCI_COMMAND, &cmd);
+	cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+	pci_write_config_word(pd, PCI_COMMAND, cmd);
+
+	nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
+	nvidiafb_fix.smem_start = pci_resource_start(pd, 1);
+	nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
+
+	par->REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
+
+	if (!par->REGS) {
+		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+		goto err_out_free_base0;
+	}
+
+	par->Chipset = nvidia_get_chipset(info);
+	par->Architecture = nvidia_get_arch(info);
+
+	if (par->Architecture == 0) {
+		printk(KERN_ERR PFX "unknown NV_ARCH\n");
+		goto err_out_arch;
+	}
+
+	sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+	if (NVCommonSetup(info))
+		goto err_out_arch;
+
+	par->FbAddress = nvidiafb_fix.smem_start;
+	par->FbMapSize = par->RamAmountKBytes * 1024;
+	if (vram && vram * 1024 * 1024 < par->FbMapSize)
+		par->FbMapSize = vram * 1024 * 1024;
+
+	/* Limit amount of vram to 64 MB */
+	if (par->FbMapSize > 64 * 1024 * 1024)
+		par->FbMapSize = 64 * 1024 * 1024;
+
+	if(par->Architecture >= NV_ARCH_40)
+  	        par->FbUsableSize = par->FbMapSize - (560 * 1024);
+	else
+		par->FbUsableSize = par->FbMapSize - (128 * 1024);
+	par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
+	    16 * 1024;
+	par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+	par->CursorStart = par->FbUsableSize + (32 * 1024);
+
+	info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
+	info->screen_size = par->FbUsableSize;
+	nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
+
+	if (!info->screen_base) {
+		printk(KERN_ERR PFX "cannot ioremap FB base\n");
+		goto err_out_free_base1;
+	}
+
+	par->FbStart = info->screen_base;
+
+#ifdef CONFIG_MTRR
+	if (!nomtrr) {
+		par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
+					  par->RamAmountKBytes * 1024,
+					  MTRR_TYPE_WRCOMB, 1);
+		if (par->mtrr.vram < 0) {
+			printk(KERN_ERR PFX "unable to setup MTRR\n");
+		} else {
+			par->mtrr.vram_valid = 1;
+			/* let there be speed */
+			printk(KERN_INFO PFX "MTRR set to ON\n");
+		}
+	}
+#endif				/* CONFIG_MTRR */
+
+	info->fbops = &nvidia_fb_ops;
+	info->fix = nvidiafb_fix;
+
+	if (nvidia_set_fbinfo(info) < 0) {
+		printk(KERN_ERR PFX "error setting initial video mode\n");
+		goto err_out_iounmap_fb;
+	}
+
+	nvidia_save_vga(par, &par->SavedReg);
+
+	pci_set_drvdata(pd, info);
+
+	if (backlight)
+		nvidia_bl_init(par);
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
+		goto err_out_iounmap_fb;
+	}
+
+
+	printk(KERN_INFO PFX
+	       "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
+	       info->fix.id,
+	       par->FbMapSize / (1024 * 1024), info->fix.smem_start);
+
+	NVTRACE_LEAVE();
+	return 0;
+
+err_out_iounmap_fb:
+	iounmap(info->screen_base);
+err_out_free_base1:
+	fb_destroy_modedb(info->monspecs.modedb);
+	nvidia_delete_i2c_busses(par);
+err_out_arch:
+	iounmap(par->REGS);
+ err_out_free_base0:
+	pci_release_regions(pd);
+err_out_enable:
+	kfree(info->pixmap.addr);
+err_out_kfree:
+	framebuffer_release(info);
+err_out:
+	return -ENODEV;
+}
+
+static void nvidiafb_remove(struct pci_dev *pd)
+{
+	struct fb_info *info = pci_get_drvdata(pd);
+	struct nvidia_par *par = info->par;
+
+	NVTRACE_ENTER();
+
+	unregister_framebuffer(info);
+
+	nvidia_bl_exit(par);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr.vram_valid)
+		mtrr_del(par->mtrr.vram, info->fix.smem_start,
+			 info->fix.smem_len);
+#endif				/* CONFIG_MTRR */
+
+	iounmap(info->screen_base);
+	fb_destroy_modedb(info->monspecs.modedb);
+	nvidia_delete_i2c_busses(par);
+	iounmap(par->REGS);
+	pci_release_regions(pd);
+	kfree(info->pixmap.addr);
+	framebuffer_release(info);
+	NVTRACE_LEAVE();
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+static int nvidiafb_setup(char *options)
+{
+	char *this_opt;
+
+	NVTRACE_ENTER();
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "forceCRTC", 9)) {
+			char *p;
+
+			p = this_opt + 9;
+			if (!*p || !*(++p))
+				continue;
+			forceCRTC = *p - '0';
+			if (forceCRTC < 0 || forceCRTC > 1)
+				forceCRTC = -1;
+		} else if (!strncmp(this_opt, "flatpanel", 9)) {
+			flatpanel = 1;
+		} else if (!strncmp(this_opt, "hwcur", 5)) {
+			hwcur = 1;
+		} else if (!strncmp(this_opt, "noaccel", 6)) {
+			noaccel = 1;
+		} else if (!strncmp(this_opt, "noscale", 7)) {
+			noscale = 1;
+		} else if (!strncmp(this_opt, "reverse_i2c", 11)) {
+			reverse_i2c = 1;
+		} else if (!strncmp(this_opt, "paneltweak:", 11)) {
+			paneltweak = simple_strtoul(this_opt+11, NULL, 0);
+		} else if (!strncmp(this_opt, "vram:", 5)) {
+			vram = simple_strtoul(this_opt+5, NULL, 0);
+		} else if (!strncmp(this_opt, "backlight:", 10)) {
+			backlight = simple_strtoul(this_opt+10, NULL, 0);
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = true;
+#endif
+		} else if (!strncmp(this_opt, "fpdither:", 9)) {
+			fpdither = simple_strtol(this_opt+9, NULL, 0);
+		} else if (!strncmp(this_opt, "bpp:", 4)) {
+			bpp = simple_strtoul(this_opt+4, NULL, 0);
+		} else
+			mode_option = this_opt;
+	}
+	NVTRACE_LEAVE();
+	return 0;
+}
+#endif				/* !MODULE */
+
+static struct pci_driver nvidiafb_driver = {
+	.name = "nvidiafb",
+	.id_table = nvidiafb_pci_tbl,
+	.probe    = nvidiafb_probe,
+	.suspend  = nvidiafb_suspend,
+	.resume   = nvidiafb_resume,
+	.remove   = nvidiafb_remove,
+};
+
+/* ------------------------------------------------------------------------- *
+ *
+ * modularization
+ *
+ * ------------------------------------------------------------------------- */
+
+static int nvidiafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("nvidiafb", &option))
+		return -ENODEV;
+	nvidiafb_setup(option);
+#endif
+	return pci_register_driver(&nvidiafb_driver);
+}
+
+module_init(nvidiafb_init);
+
+static void __exit nvidiafb_exit(void)
+{
+	pci_unregister_driver(&nvidiafb_driver);
+}
+
+module_exit(nvidiafb_exit);
+
+module_param(flatpanel, int, 0);
+MODULE_PARM_DESC(flatpanel,
+		 "Enables experimental flat panel support for some chipsets. "
+		 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
+module_param(fpdither, int, 0);
+MODULE_PARM_DESC(fpdither,
+		 "Enables dithering of flat panel for 6 bits panels. "
+		 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
+module_param(hwcur, int, 0);
+MODULE_PARM_DESC(hwcur,
+		 "Enables hardware cursor implementation. (0 or 1=enabled) "
+		 "(default=0)");
+module_param(noaccel, int, 0);
+MODULE_PARM_DESC(noaccel,
+		 "Disables hardware acceleration. (0 or 1=disable) "
+		 "(default=0)");
+module_param(noscale, int, 0);
+MODULE_PARM_DESC(noscale,
+		 "Disables screen scaleing. (0 or 1=disable) "
+		 "(default=0, do scaling)");
+module_param(paneltweak, int, 0);
+MODULE_PARM_DESC(paneltweak,
+		 "Tweak display settings for flatpanels. "
+		 "(default=0, no tweaks)");
+module_param(forceCRTC, int, 0);
+MODULE_PARM_DESC(forceCRTC,
+		 "Forces usage of a particular CRTC in case autodetection "
+		 "fails. (0 or 1) (default=autodetect)");
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram,
+		 "amount of framebuffer memory to remap in MiB"
+		 "(default=0 - remap entire memory)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
+module_param(bpp, int, 0);
+MODULE_PARM_DESC(bpp, "pixel width in bits"
+		 "(default=8)");
+module_param(reverse_i2c, int, 0);
+MODULE_PARM_DESC(reverse_i2c, "reverse port assignment of the i2c bus");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, false);
+MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
+		 "(default=0)");
+#endif
+
+MODULE_AUTHOR("Antonino Daplas");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/ocfb.c b/drivers/video/fbdev/ocfb.c
new file mode 100644
index 000000000000..7f9dc9bec309
--- /dev/null
+++ b/drivers/video/fbdev/ocfb.c
@@ -0,0 +1,440 @@
+/*
+ * OpenCores VGA/LCD 2.0 core frame buffer driver
+ *
+ * Copyright (C) 2013 Stefan Kristiansson, stefan.kristiansson@saunalahti.fi
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* OCFB register defines */
+#define OCFB_CTRL	0x000
+#define OCFB_STAT	0x004
+#define OCFB_HTIM	0x008
+#define OCFB_VTIM	0x00c
+#define OCFB_HVLEN	0x010
+#define OCFB_VBARA	0x014
+#define OCFB_PALETTE	0x800
+
+#define OCFB_CTRL_VEN	0x00000001 /* Video Enable */
+#define OCFB_CTRL_HIE	0x00000002 /* HSync Interrupt Enable */
+#define OCFB_CTRL_PC	0x00000800 /* 8-bit Pseudo Color Enable*/
+#define OCFB_CTRL_CD8	0x00000000 /* Color Depth 8 */
+#define OCFB_CTRL_CD16	0x00000200 /* Color Depth 16 */
+#define OCFB_CTRL_CD24	0x00000400 /* Color Depth 24 */
+#define OCFB_CTRL_CD32	0x00000600 /* Color Depth 32 */
+#define OCFB_CTRL_VBL1	0x00000000 /* Burst Length 1 */
+#define OCFB_CTRL_VBL2	0x00000080 /* Burst Length 2 */
+#define OCFB_CTRL_VBL4	0x00000100 /* Burst Length 4 */
+#define OCFB_CTRL_VBL8	0x00000180 /* Burst Length 8 */
+
+#define PALETTE_SIZE	256
+
+#define OCFB_NAME	"OC VGA/LCD"
+
+static char *mode_option;
+
+static const struct fb_videomode default_mode = {
+	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
+	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+};
+
+struct ocfb_dev {
+	struct fb_info info;
+	void __iomem *regs;
+	/* flag indicating whether the regs are little endian accessed */
+	int little_endian;
+	/* Physical and virtual addresses of framebuffer */
+	phys_addr_t fb_phys;
+	void __iomem *fb_virt;
+	u32 pseudo_palette[PALETTE_SIZE];
+};
+
+#ifndef MODULE
+static int __init ocfb_setup(char *options)
+{
+	char *curr_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((curr_opt = strsep(&options, ",")) != NULL) {
+		if (!*curr_opt)
+			continue;
+		mode_option = curr_opt;
+	}
+
+	return 0;
+}
+#endif
+
+static inline u32 ocfb_readreg(struct ocfb_dev *fbdev, loff_t offset)
+{
+	if (fbdev->little_endian)
+		return ioread32(fbdev->regs + offset);
+	else
+		return ioread32be(fbdev->regs + offset);
+}
+
+static void ocfb_writereg(struct ocfb_dev *fbdev, loff_t offset, u32 data)
+{
+	if (fbdev->little_endian)
+		iowrite32(data, fbdev->regs + offset);
+	else
+		iowrite32be(data, fbdev->regs + offset);
+}
+
+static int ocfb_setupfb(struct ocfb_dev *fbdev)
+{
+	unsigned long bpp_config;
+	struct fb_var_screeninfo *var = &fbdev->info.var;
+	struct device *dev = fbdev->info.device;
+	u32 hlen;
+	u32 vlen;
+
+	/* Disable display */
+	ocfb_writereg(fbdev, OCFB_CTRL, 0);
+
+	/* Register framebuffer address */
+	fbdev->little_endian = 0;
+	ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys);
+
+	/* Detect endianess */
+	if (ocfb_readreg(fbdev, OCFB_VBARA) != fbdev->fb_phys) {
+		fbdev->little_endian = 1;
+		ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys);
+	}
+
+	/* Horizontal timings */
+	ocfb_writereg(fbdev, OCFB_HTIM, (var->hsync_len - 1) << 24 |
+		      (var->right_margin - 1) << 16 | (var->xres - 1));
+
+	/* Vertical timings */
+	ocfb_writereg(fbdev, OCFB_VTIM, (var->vsync_len - 1) << 24 |
+		      (var->lower_margin - 1) << 16 | (var->yres - 1));
+
+	/* Total length of frame */
+	hlen = var->left_margin + var->right_margin + var->hsync_len +
+		var->xres;
+
+	vlen = var->upper_margin + var->lower_margin + var->vsync_len +
+		var->yres;
+
+	ocfb_writereg(fbdev, OCFB_HVLEN, (hlen - 1) << 16 | (vlen - 1));
+
+	bpp_config = OCFB_CTRL_CD8;
+	switch (var->bits_per_pixel) {
+	case 8:
+		if (!var->grayscale)
+			bpp_config |= OCFB_CTRL_PC;  /* enable palette */
+		break;
+
+	case 16:
+		bpp_config |= OCFB_CTRL_CD16;
+		break;
+
+	case 24:
+		bpp_config |= OCFB_CTRL_CD24;
+		break;
+
+	case 32:
+		bpp_config |= OCFB_CTRL_CD32;
+		break;
+
+	default:
+		dev_err(dev, "no bpp specified\n");
+		break;
+	}
+
+	/* maximum (8) VBL (video memory burst length) */
+	bpp_config |= OCFB_CTRL_VBL8;
+
+	/* Enable output */
+	ocfb_writereg(fbdev, OCFB_CTRL, (OCFB_CTRL_VEN | bpp_config));
+
+	return 0;
+}
+
+static int ocfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp,
+			  struct fb_info *info)
+{
+	struct ocfb_dev *fbdev = (struct ocfb_dev *)info->par;
+	u32 color;
+
+	if (regno >= info->cmap.len) {
+		dev_err(info->device, "regno >= cmap.len\n");
+		return 1;
+	}
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	red >>= (16 - info->var.red.length);
+	green >>= (16 - info->var.green.length);
+	blue >>= (16 - info->var.blue.length);
+	transp >>= (16 - info->var.transp.length);
+
+	if (info->var.bits_per_pixel == 8 && !info->var.grayscale) {
+		regno <<= 2;
+		color = (red << 16) | (green << 8) | blue;
+		ocfb_writereg(fbdev, OCFB_PALETTE + regno, color);
+	} else {
+		((u32 *)(info->pseudo_palette))[regno] =
+			(red << info->var.red.offset) |
+			(green << info->var.green.offset) |
+			(blue << info->var.blue.offset) |
+			(transp << info->var.transp.offset);
+	}
+
+	return 0;
+}
+
+static int ocfb_init_fix(struct ocfb_dev *fbdev)
+{
+	struct fb_var_screeninfo *var = &fbdev->info.var;
+	struct fb_fix_screeninfo *fix = &fbdev->info.fix;
+
+	strcpy(fix->id, OCFB_NAME);
+
+	fix->line_length = var->xres * var->bits_per_pixel/8;
+	fix->smem_len = fix->line_length * var->yres;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	if (var->bits_per_pixel == 8 && !var->grayscale)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		fix->visual = FB_VISUAL_TRUECOLOR;
+
+	return 0;
+}
+
+static int ocfb_init_var(struct ocfb_dev *fbdev)
+{
+	struct fb_var_screeninfo *var = &fbdev->info.var;
+
+	var->accel_flags = FB_ACCEL_NONE;
+	var->activate = FB_ACTIVATE_NOW;
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+
+	case 16:
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length  = 5;
+		break;
+
+	case 24:
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+	}
+
+	return 0;
+}
+
+static struct fb_ops ocfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= ocfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int ocfb_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct ocfb_dev *fbdev;
+	struct resource *res;
+	int fbsize;
+
+	fbdev = devm_kzalloc(&pdev->dev, sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, fbdev);
+
+	fbdev->info.fbops = &ocfb_ops;
+	fbdev->info.device = &pdev->dev;
+	fbdev->info.par = fbdev;
+
+	/* Video mode setup */
+	if (!fb_find_mode(&fbdev->info.var, &fbdev->info, mode_option,
+			  NULL, 0, &default_mode, 16)) {
+		dev_err(&pdev->dev, "No valid video modes found\n");
+		return -EINVAL;
+	}
+	ocfb_init_var(fbdev);
+	ocfb_init_fix(fbdev);
+
+	/* Request I/O resource */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "I/O resource request failed\n");
+		return -ENXIO;
+	}
+	res->flags &= ~IORESOURCE_CACHEABLE;
+	fbdev->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fbdev->regs))
+		return PTR_ERR(fbdev->regs);
+
+	/* Allocate framebuffer memory */
+	fbsize = fbdev->info.fix.smem_len;
+	fbdev->fb_virt = dma_alloc_coherent(&pdev->dev, PAGE_ALIGN(fbsize),
+					    &fbdev->fb_phys, GFP_KERNEL);
+	if (!fbdev->fb_virt) {
+		dev_err(&pdev->dev,
+			"Frame buffer memory allocation failed\n");
+		return -ENOMEM;
+	}
+	fbdev->info.fix.smem_start = fbdev->fb_phys;
+	fbdev->info.screen_base = fbdev->fb_virt;
+	fbdev->info.pseudo_palette = fbdev->pseudo_palette;
+
+	/* Clear framebuffer */
+	memset_io(fbdev->fb_virt, 0, fbsize);
+
+	/* Setup and enable the framebuffer */
+	ocfb_setupfb(fbdev);
+
+	if (fbdev->little_endian)
+		fbdev->info.flags |= FBINFO_FOREIGN_ENDIAN;
+
+	/* Allocate color map */
+	ret = fb_alloc_cmap(&fbdev->info.cmap, PALETTE_SIZE, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "Color map allocation failed\n");
+		goto err_dma_free;
+	}
+
+	/* Register framebuffer */
+	ret = register_framebuffer(&fbdev->info);
+	if (ret) {
+		dev_err(&pdev->dev, "Framebuffer registration failed\n");
+		goto err_dealloc_cmap;
+	}
+
+	return 0;
+
+err_dealloc_cmap:
+	fb_dealloc_cmap(&fbdev->info.cmap);
+
+err_dma_free:
+	dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbsize), fbdev->fb_virt,
+			  fbdev->fb_phys);
+
+	return ret;
+}
+
+static int ocfb_remove(struct platform_device *pdev)
+{
+	struct ocfb_dev *fbdev = platform_get_drvdata(pdev);
+
+	unregister_framebuffer(&fbdev->info);
+	fb_dealloc_cmap(&fbdev->info.cmap);
+	dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbdev->info.fix.smem_len),
+			  fbdev->fb_virt, fbdev->fb_phys);
+
+	/* Disable display */
+	ocfb_writereg(fbdev, OCFB_CTRL, 0);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct of_device_id ocfb_match[] = {
+	{ .compatible = "opencores,ocfb", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ocfb_match);
+
+static struct platform_driver ocfb_driver = {
+	.probe  = ocfb_probe,
+	.remove	= ocfb_remove,
+	.driver = {
+		.name = "ocfb_fb",
+		.of_match_table = ocfb_match,
+	}
+};
+
+/*
+ * Init and exit routines
+ */
+static int __init ocfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("ocfb", &option))
+		return -ENODEV;
+	ocfb_setup(option);
+#endif
+	return platform_driver_register(&ocfb_driver);
+}
+
+static void __exit ocfb_exit(void)
+{
+	platform_driver_unregister(&ocfb_driver);
+}
+
+module_init(ocfb_init);
+module_exit(ocfb_exit);
+
+MODULE_AUTHOR("Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>");
+MODULE_DESCRIPTION("OpenCores VGA/LCD 2.0 frame buffer driver");
+MODULE_LICENSE("GPL v2");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Video mode ('<xres>x<yres>[-<bpp>][@refresh]')");
diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c
new file mode 100644
index 000000000000..7d44d669d5b6
--- /dev/null
+++ b/drivers/video/fbdev/offb.c
@@ -0,0 +1,687 @@
+/*
+ *  linux/drivers/video/offb.c -- Open Firmware based frame buffer device
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This driver is partly based on the PowerMac console driver:
+ *
+ *	Copyright (C) 1996 Paul Mackerras
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_PPC64
+#include <asm/pci-bridge.h>
+#endif
+
+#ifdef CONFIG_PPC32
+#include <asm/bootx.h>
+#endif
+
+#include "macmodes.h"
+
+/* Supported palette hacks */
+enum {
+	cmap_unknown,
+	cmap_simple,		/* ATI Mach64 */
+	cmap_r128,		/* ATI Rage128 */
+	cmap_M3A,		/* ATI Rage Mobility M3 Head A */
+	cmap_M3B,		/* ATI Rage Mobility M3 Head B */
+	cmap_radeon,		/* ATI Radeon */
+	cmap_gxt2000,		/* IBM GXT2000 */
+	cmap_avivo,		/* ATI R5xx */
+	cmap_qemu,		/* qemu vga */
+};
+
+struct offb_par {
+	volatile void __iomem *cmap_adr;
+	volatile void __iomem *cmap_data;
+	int cmap_type;
+	int blanked;
+};
+
+struct offb_par default_par;
+
+#ifdef CONFIG_PPC32
+extern boot_infos_t *boot_infos;
+#endif
+
+/* Definitions used by the Avivo palette hack */
+#define AVIVO_DC_LUT_RW_SELECT                  0x6480
+#define AVIVO_DC_LUT_RW_MODE                    0x6484
+#define AVIVO_DC_LUT_RW_INDEX                   0x6488
+#define AVIVO_DC_LUT_SEQ_COLOR                  0x648c
+#define AVIVO_DC_LUT_PWL_DATA                   0x6490
+#define AVIVO_DC_LUT_30_COLOR                   0x6494
+#define AVIVO_DC_LUT_READ_PIPE_SELECT           0x6498
+#define AVIVO_DC_LUT_WRITE_EN_MASK              0x649c
+#define AVIVO_DC_LUT_AUTOFILL                   0x64a0
+
+#define AVIVO_DC_LUTA_CONTROL                   0x64c0
+#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE         0x64c4
+#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN        0x64c8
+#define AVIVO_DC_LUTA_BLACK_OFFSET_RED          0x64cc
+#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE         0x64d0
+#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN        0x64d4
+#define AVIVO_DC_LUTA_WHITE_OFFSET_RED          0x64d8
+
+#define AVIVO_DC_LUTB_CONTROL                   0x6cc0
+#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE         0x6cc4
+#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN        0x6cc8
+#define AVIVO_DC_LUTB_BLACK_OFFSET_RED          0x6ccc
+#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE         0x6cd0
+#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4
+#define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8
+
+#define FB_RIGHT_POS(p, bpp)         (fb_be_math(p) ? 0 : (32 - (bpp)))
+
+static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value)
+{
+	u32 bpp = info->var.bits_per_pixel;
+
+	return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp);
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			  u_int transp, struct fb_info *info)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 *pal = info->pseudo_palette;
+		u32 cr = red >> (16 - info->var.red.length);
+		u32 cg = green >> (16 - info->var.green.length);
+		u32 cb = blue >> (16 - info->var.blue.length);
+		u32 value;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		value = (cr << info->var.red.offset) |
+			(cg << info->var.green.offset) |
+			(cb << info->var.blue.offset);
+		if (info->var.transp.length > 0) {
+			u32 mask = (1 << info->var.transp.length) - 1;
+			mask <<= info->var.transp.offset;
+			value |= mask;
+		}
+		pal[regno] = offb_cmap_byteswap(info, value);
+		return 0;
+	}
+
+	if (regno > 255)
+		return -EINVAL;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	if (!par->cmap_adr)
+		return 0;
+
+	switch (par->cmap_type) {
+	case cmap_simple:
+		writeb(regno, par->cmap_adr);
+		writeb(red, par->cmap_data);
+		writeb(green, par->cmap_data);
+		writeb(blue, par->cmap_data);
+		break;
+	case cmap_M3A:
+		/* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
+		out_le32(par->cmap_adr + 0x58,
+			 in_le32(par->cmap_adr + 0x58) & ~0x20);
+	case cmap_r128:
+		/* Set palette index & data */
+		out_8(par->cmap_adr + 0xb0, regno);
+		out_le32(par->cmap_adr + 0xb4,
+			 (red << 16 | green << 8 | blue));
+		break;
+	case cmap_M3B:
+		/* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
+		out_le32(par->cmap_adr + 0x58,
+			 in_le32(par->cmap_adr + 0x58) | 0x20);
+		/* Set palette index & data */
+		out_8(par->cmap_adr + 0xb0, regno);
+		out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue));
+		break;
+	case cmap_radeon:
+		/* Set palette index & data (could be smarter) */
+		out_8(par->cmap_adr + 0xb0, regno);
+		out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue));
+		break;
+	case cmap_gxt2000:
+		out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
+			 (red << 16 | green << 8 | blue));
+		break;
+	case cmap_avivo:
+		/* Write to both LUTs for now */
+		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+		break;
+	}
+
+	return 0;
+}
+
+    /*
+     *  Blank the display.
+     */
+
+static int offb_blank(int blank, struct fb_info *info)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+	int i, j;
+
+	if (!par->cmap_adr)
+		return 0;
+
+	if (!par->blanked)
+		if (!blank)
+			return 0;
+
+	par->blanked = blank;
+
+	if (blank)
+		for (i = 0; i < 256; i++) {
+			switch (par->cmap_type) {
+			case cmap_simple:
+				writeb(i, par->cmap_adr);
+				for (j = 0; j < 3; j++)
+					writeb(0, par->cmap_data);
+				break;
+			case cmap_M3A:
+				/* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
+				out_le32(par->cmap_adr + 0x58,
+					 in_le32(par->cmap_adr + 0x58) & ~0x20);
+			case cmap_r128:
+				/* Set palette index & data */
+				out_8(par->cmap_adr + 0xb0, i);
+				out_le32(par->cmap_adr + 0xb4, 0);
+				break;
+			case cmap_M3B:
+				/* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
+				out_le32(par->cmap_adr + 0x58,
+					 in_le32(par->cmap_adr + 0x58) | 0x20);
+				/* Set palette index & data */
+				out_8(par->cmap_adr + 0xb0, i);
+				out_le32(par->cmap_adr + 0xb4, 0);
+				break;
+			case cmap_radeon:
+				out_8(par->cmap_adr + 0xb0, i);
+				out_le32(par->cmap_adr + 0xb4, 0);
+				break;
+			case cmap_gxt2000:
+				out_le32(((unsigned __iomem *) par->cmap_adr) + i,
+					 0);
+				break;
+			case cmap_avivo:
+				writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+				break;
+			}
+	} else
+		fb_set_cmap(&info->cmap, info);
+	return 0;
+}
+
+static int offb_set_par(struct fb_info *info)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+
+	/* On avivo, initialize palette control */
+	if (par->cmap_type == cmap_avivo) {
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);
+		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+	}
+	return 0;
+}
+
+static void offb_destroy(struct fb_info *info)
+{
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
+	framebuffer_release(info);
+}
+
+static struct fb_ops offb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_destroy	= offb_destroy,
+	.fb_setcolreg	= offb_setcolreg,
+	.fb_set_par	= offb_set_par,
+	.fb_blank	= offb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static void __iomem *offb_map_reg(struct device_node *np, int index,
+				  unsigned long offset, unsigned long size)
+{
+	const __be32 *addrp;
+	u64 asize, taddr;
+	unsigned int flags;
+
+	addrp = of_get_pci_address(np, index, &asize, &flags);
+	if (addrp == NULL)
+		addrp = of_get_address(np, index, &asize, &flags);
+	if (addrp == NULL)
+		return NULL;
+	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+		return NULL;
+	if ((offset + size) > asize)
+		return NULL;
+	taddr = of_translate_address(np, addrp);
+	if (taddr == OF_BAD_ADDR)
+		return NULL;
+	return ioremap(taddr + offset, size);
+}
+
+static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
+				    const char *name, unsigned long address)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+
+	if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_r128;
+	} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
+			  || !strncmp(name, "ATY,RageM3p12A", 14))) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_M3A;
+	} else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_M3B;
+	} else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+		par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_radeon;
+	} else if (!strncmp(name, "ATY,", 4)) {
+		unsigned long base = address & 0xff000000UL;
+		par->cmap_adr =
+			ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
+		par->cmap_data = par->cmap_adr + 1;
+		par->cmap_type = cmap_simple;
+	} else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
+			  of_device_is_compatible(dp, "pci1014,21c"))) {
+		par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_gxt2000;
+	} else if (dp && !strncmp(name, "vga,Display-", 12)) {
+		/* Look for AVIVO initialized by SLOF */
+		struct device_node *pciparent = of_get_parent(dp);
+		const u32 *vid, *did;
+		vid = of_get_property(pciparent, "vendor-id", NULL);
+		did = of_get_property(pciparent, "device-id", NULL);
+		/* This will match most R5xx */
+		if (vid && did && *vid == 0x1002 &&
+		    ((*did >= 0x7100 && *did < 0x7800) ||
+		     (*did >= 0x9400))) {
+			par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_avivo;
+		}
+		of_node_put(pciparent);
+	} else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) {
+#ifdef __BIG_ENDIAN
+		const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
+#else
+		const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 };
+#endif
+		u64 io_addr = of_translate_address(dp, io_of_addr);
+		if (io_addr != OF_BAD_ADDR) {
+			par->cmap_adr = ioremap(io_addr + 0x3c8, 2);
+			if (par->cmap_adr) {
+				par->cmap_type = cmap_simple;
+				par->cmap_data = par->cmap_adr + 1;
+			}
+		}
+	}
+	info->fix.visual = (par->cmap_type != cmap_unknown) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
+}
+
+static void __init offb_init_fb(const char *name, const char *full_name,
+				int width, int height, int depth,
+				int pitch, unsigned long address,
+				int foreign_endian, struct device_node *dp)
+{
+	unsigned long res_size = pitch * height;
+	struct offb_par *par = &default_par;
+	unsigned long res_start = address;
+	struct fb_fix_screeninfo *fix;
+	struct fb_var_screeninfo *var;
+	struct fb_info *info;
+
+	if (!request_mem_region(res_start, res_size, "offb"))
+		return;
+
+	printk(KERN_INFO
+	       "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
+	       width, height, name, address, depth, pitch);
+	if (depth != 8 && depth != 15 && depth != 16 && depth != 32) {
+		printk(KERN_ERR "%s: can't use depth = %d\n", full_name,
+		       depth);
+		release_mem_region(res_start, res_size);
+		return;
+	}
+
+	info = framebuffer_alloc(sizeof(u32) * 16, NULL);
+	
+	if (info == 0) {
+		release_mem_region(res_start, res_size);
+		return;
+	}
+
+	fix = &info->fix;
+	var = &info->var;
+	info->par = par;
+
+	strcpy(fix->id, "OFfb ");
+	strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
+	fix->id[sizeof(fix->id) - 1] = '\0';
+
+	var->xres = var->xres_virtual = width;
+	var->yres = var->yres_virtual = height;
+	fix->line_length = pitch;
+
+	fix->smem_start = address;
+	fix->smem_len = pitch * height;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+
+	par->cmap_type = cmap_unknown;
+	if (depth == 8)
+		offb_init_palette_hacks(info, dp, name, address);
+	else
+		fix->visual = FB_VISUAL_TRUECOLOR;
+
+	var->xoffset = var->yoffset = 0;
+	switch (depth) {
+	case 8:
+		var->bits_per_pixel = 8;
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 15:		/* RGB 555 */
+		var->bits_per_pixel = 16;
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 5;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGB 565 */
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGB 888 */
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = var->green.msb_right = var->blue.msb_right =
+	    var->transp.msb_right = 0;
+	var->grayscale = 0;
+	var->nonstd = 0;
+	var->activate = 0;
+	var->height = var->width = -1;
+	var->pixclock = 10000;
+	var->left_margin = var->right_margin = 16;
+	var->upper_margin = var->lower_margin = 16;
+	var->hsync_len = var->vsync_len = 8;
+	var->sync = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
+
+	/* set offb aperture size for generic probing */
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures)
+		goto out_aper;
+	info->apertures->ranges[0].base = address;
+	info->apertures->ranges[0].size = fix->smem_len;
+
+	info->fbops = &offb_ops;
+	info->screen_base = ioremap(address, fix->smem_len);
+	info->pseudo_palette = (void *) (info + 1);
+	info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian;
+
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	if (register_framebuffer(info) < 0)
+		goto out_err;
+
+	fb_info(info, "Open Firmware frame buffer device on %s\n", full_name);
+	return;
+
+out_err:
+	iounmap(info->screen_base);
+out_aper:
+	iounmap(par->cmap_adr);
+	par->cmap_adr = NULL;
+	framebuffer_release(info);
+	release_mem_region(res_start, res_size);
+}
+
+
+static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
+{
+	unsigned int len;
+	int i, width = 640, height = 480, depth = 8, pitch = 640;
+	unsigned int flags, rsize, addr_prop = 0;
+	unsigned long max_size = 0;
+	u64 rstart, address = OF_BAD_ADDR;
+	const __be32 *pp, *addrp, *up;
+	u64 asize;
+	int foreign_endian = 0;
+
+#ifdef __BIG_ENDIAN
+	if (of_get_property(dp, "little-endian", NULL))
+		foreign_endian = FBINFO_FOREIGN_ENDIAN;
+#else
+	if (of_get_property(dp, "big-endian", NULL))
+		foreign_endian = FBINFO_FOREIGN_ENDIAN;
+#endif
+
+	pp = of_get_property(dp, "linux,bootx-depth", &len);
+	if (pp == NULL)
+		pp = of_get_property(dp, "depth", &len);
+	if (pp && len == sizeof(u32))
+		depth = be32_to_cpup(pp);
+
+	pp = of_get_property(dp, "linux,bootx-width", &len);
+	if (pp == NULL)
+		pp = of_get_property(dp, "width", &len);
+	if (pp && len == sizeof(u32))
+		width = be32_to_cpup(pp);
+
+	pp = of_get_property(dp, "linux,bootx-height", &len);
+	if (pp == NULL)
+		pp = of_get_property(dp, "height", &len);
+	if (pp && len == sizeof(u32))
+		height = be32_to_cpup(pp);
+
+	pp = of_get_property(dp, "linux,bootx-linebytes", &len);
+	if (pp == NULL)
+		pp = of_get_property(dp, "linebytes", &len);
+	if (pp && len == sizeof(u32) && (*pp != 0xffffffffu))
+		pitch = be32_to_cpup(pp);
+	else
+		pitch = width * ((depth + 7) / 8);
+
+	rsize = (unsigned long)pitch * (unsigned long)height;
+
+	/* Ok, now we try to figure out the address of the framebuffer.
+	 *
+	 * Unfortunately, Open Firmware doesn't provide a standard way to do
+	 * so. All we can do is a dodgy heuristic that happens to work in
+	 * practice. On most machines, the "address" property contains what
+	 * we need, though not on Matrox cards found in IBM machines. What I've
+	 * found that appears to give good results is to go through the PCI
+	 * ranges and pick one that is both big enough and if possible encloses
+	 * the "address" property. If none match, we pick the biggest
+	 */
+	up = of_get_property(dp, "linux,bootx-addr", &len);
+	if (up == NULL)
+		up = of_get_property(dp, "address", &len);
+	if (up && len == sizeof(u32))
+		addr_prop = *up;
+
+	/* Hack for when BootX is passing us */
+	if (no_real_node)
+		goto skip_addr;
+
+	for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
+		     != NULL; i++) {
+		int match_addrp = 0;
+
+		if (!(flags & IORESOURCE_MEM))
+			continue;
+		if (asize < rsize)
+			continue;
+		rstart = of_translate_address(dp, addrp);
+		if (rstart == OF_BAD_ADDR)
+			continue;
+		if (addr_prop && (rstart <= addr_prop) &&
+		    ((rstart + asize) >= (addr_prop + rsize)))
+			match_addrp = 1;
+		if (match_addrp) {
+			address = addr_prop;
+			break;
+		}
+		if (rsize > max_size) {
+			max_size = rsize;
+			address = OF_BAD_ADDR;
+ 		}
+
+		if (address == OF_BAD_ADDR)
+			address = rstart;
+	}
+ skip_addr:
+	if (address == OF_BAD_ADDR && addr_prop)
+		address = (u64)addr_prop;
+	if (address != OF_BAD_ADDR) {
+		/* kludge for valkyrie */
+		if (strcmp(dp->name, "valkyrie") == 0)
+			address += 0x1000;
+		offb_init_fb(no_real_node ? "bootx" : dp->name,
+			     no_real_node ? "display" : dp->full_name,
+			     width, height, depth, pitch, address,
+			     foreign_endian, no_real_node ? NULL : dp);
+	}
+}
+
+static int __init offb_init(void)
+{
+	struct device_node *dp = NULL, *boot_disp = NULL;
+
+	if (fb_get_options("offb", NULL))
+		return -ENODEV;
+
+	/* Check if we have a MacOS display without a node spec */
+	if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) {
+		/* The old code tried to work out which node was the MacOS
+		 * display based on the address. I'm dropping that since the
+		 * lack of a node spec only happens with old BootX versions
+		 * (users can update) and with this code, they'll still get
+		 * a display (just not the palette hacks).
+		 */
+		offb_init_nodriver(of_chosen, 1);
+	}
+
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (of_get_property(dp, "linux,opened", NULL) &&
+		    of_get_property(dp, "linux,boot-display", NULL)) {
+			boot_disp = dp;
+			offb_init_nodriver(dp, 0);
+		}
+	}
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (of_get_property(dp, "linux,opened", NULL) &&
+		    dp != boot_disp)
+			offb_init_nodriver(dp, 0);
+	}
+
+	return 0;
+}
+
+
+module_init(offb_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/Kconfig b/drivers/video/fbdev/omap/Kconfig
new file mode 100644
index 000000000000..0bc3a936ce2b
--- /dev/null
+++ b/drivers/video/fbdev/omap/Kconfig
@@ -0,0 +1,52 @@
+config FB_OMAP
+	tristate "OMAP frame buffer support"
+	depends on FB
+	depends on ARCH_OMAP1
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+          Frame buffer driver for OMAP based boards.
+
+config FB_OMAP_LCDC_EXTERNAL
+	bool "External LCD controller support"
+	depends on FB_OMAP
+	help
+	  Say Y here, if you want to have support for boards with an
+	  external LCD controller connected to the SoSSI/RFBI interface.
+
+config FB_OMAP_LCDC_HWA742
+	bool "Epson HWA742 LCD controller support"
+	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+	help
+	  Say Y here if you want to have support for the external
+	  Epson HWA742 LCD controller.
+
+config FB_OMAP_MANUAL_UPDATE
+	bool "Default to manual update mode"
+	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+	help
+	  Say Y here, if your user-space applications are capable of
+	  notifying the frame buffer driver when a change has occurred in
+	  the frame buffer content and thus a reload of the image data to
+	  the external frame buffer is required. If unsure, say N.
+
+config FB_OMAP_LCD_MIPID
+	bool "MIPI DBI-C/DCS compatible LCD support"
+	depends on FB_OMAP && SPI_MASTER
+	help
+	  Say Y here if you want to have support for LCDs compatible with
+	  the Mobile Industry Processor Interface DBI-C/DCS
+	  specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
+
+config FB_OMAP_DMA_TUNE
+        bool "Set DMA SDRAM access priority high"
+        depends on FB_OMAP
+        help
+          On systems in which video memory is in system memory
+          (SDRAM) this will speed up graphics DMA operations.
+          If you have such a system and want to use rotation
+          answer yes. Answer no if you have a dedicated video
+          memory, or don't use any of the accelerated features.
+
+
diff --git a/drivers/video/fbdev/omap/Makefile b/drivers/video/fbdev/omap/Makefile
new file mode 100644
index 000000000000..1927faffb5bc
--- /dev/null
+++ b/drivers/video/fbdev/omap/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the OMAP1 framebuffer device driver
+#
+
+obj-$(CONFIG_FB_OMAP) += omapfb.o
+
+objs-yy := omapfb_main.o lcdc.o
+
+objs-y$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
+
+objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
+
+objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
+objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
+objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
+objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
+objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
+objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
+
+objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
+objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o
+
+omapfb-objs := $(objs-yy)
+
diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c
new file mode 100644
index 000000000000..a4ee65b8f918
--- /dev/null
+++ b/drivers/video/fbdev/omap/hwa742.c
@@ -0,0 +1,1059 @@
+/*
+ * Epson HWA742 LCD controller driver
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Authors:     Juha Yrjölä   <juha.yrjola@nokia.com>
+ *	        Imre Deak     <imre.deak@nokia.com>
+ * YUV support: Jussi Laako   <jussi.laako@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+
+#include "omapfb.h"
+
+#define HWA742_REV_CODE_REG       0x0
+#define HWA742_CONFIG_REG         0x2
+#define HWA742_PLL_DIV_REG        0x4
+#define HWA742_PLL_0_REG          0x6
+#define HWA742_PLL_1_REG          0x8
+#define HWA742_PLL_2_REG          0xa
+#define HWA742_PLL_3_REG          0xc
+#define HWA742_PLL_4_REG          0xe
+#define HWA742_CLK_SRC_REG        0x12
+#define HWA742_PANEL_TYPE_REG     0x14
+#define HWA742_H_DISP_REG         0x16
+#define HWA742_H_NDP_REG          0x18
+#define HWA742_V_DISP_1_REG       0x1a
+#define HWA742_V_DISP_2_REG       0x1c
+#define HWA742_V_NDP_REG          0x1e
+#define HWA742_HS_W_REG           0x20
+#define HWA742_HP_S_REG           0x22
+#define HWA742_VS_W_REG           0x24
+#define HWA742_VP_S_REG           0x26
+#define HWA742_PCLK_POL_REG       0x28
+#define HWA742_INPUT_MODE_REG     0x2a
+#define HWA742_TRANSL_MODE_REG1   0x2e
+#define HWA742_DISP_MODE_REG      0x34
+#define HWA742_WINDOW_TYPE        0x36
+#define HWA742_WINDOW_X_START_0   0x38
+#define HWA742_WINDOW_X_START_1   0x3a
+#define HWA742_WINDOW_Y_START_0   0x3c
+#define HWA742_WINDOW_Y_START_1   0x3e
+#define HWA742_WINDOW_X_END_0     0x40
+#define HWA742_WINDOW_X_END_1     0x42
+#define HWA742_WINDOW_Y_END_0     0x44
+#define HWA742_WINDOW_Y_END_1     0x46
+#define HWA742_MEMORY_WRITE_LSB   0x48
+#define HWA742_MEMORY_WRITE_MSB   0x49
+#define HWA742_MEMORY_READ_0      0x4a
+#define HWA742_MEMORY_READ_1      0x4c
+#define HWA742_MEMORY_READ_2      0x4e
+#define HWA742_POWER_SAVE         0x56
+#define HWA742_NDP_CTRL           0x58
+
+#define HWA742_AUTO_UPDATE_TIME		(HZ / 20)
+
+/* Reserve 4 request slots for requests in irq context */
+#define REQ_POOL_SIZE			24
+#define IRQ_REQ_POOL_SIZE		4
+
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE	0
+#define REQ_PENDING	1
+
+struct update_param {
+	int	x, y, width, height;
+	int	color_mode;
+	int	flags;
+};
+
+struct hwa742_request {
+	struct list_head entry;
+	unsigned int	 flags;
+
+	int		 (*handler)(struct hwa742_request *req);
+	void		 (*complete)(void *data);
+	void		 *complete_data;
+
+	union {
+		struct update_param	update;
+		struct completion	*sync;
+	} par;
+};
+
+struct {
+	enum omapfb_update_mode	update_mode;
+	enum omapfb_update_mode	update_mode_before_suspend;
+
+	struct timer_list	auto_update_timer;
+	int			stop_auto_update;
+	struct omapfb_update_window	auto_update_window;
+	unsigned		te_connected:1;
+	unsigned		vsync_only:1;
+
+	struct hwa742_request	req_pool[REQ_POOL_SIZE];
+	struct list_head	pending_req_list;
+	struct list_head	free_req_list;
+	struct semaphore	req_sema;
+	spinlock_t		req_lock;
+
+	struct extif_timings	reg_timings, lut_timings;
+
+	int			prev_color_mode;
+	int			prev_flags;
+	int			window_type;
+
+	u32			max_transmit_size;
+	u32			extif_clk_period;
+	unsigned long		pix_tx_time;
+	unsigned long		line_upd_time;
+
+
+	struct omapfb_device	*fbdev;
+	struct lcd_ctrl_extif	*extif;
+	const struct lcd_ctrl	*int_ctrl;
+
+	struct clk		*sys_ck;
+} hwa742;
+
+struct lcd_ctrl hwa742_ctrl;
+
+static u8 hwa742_read_reg(u8 reg)
+{
+	u8 data;
+
+	hwa742.extif->set_bits_per_cycle(8);
+	hwa742.extif->write_command(&reg, 1);
+	hwa742.extif->read_data(&data, 1);
+
+	return data;
+}
+
+static void hwa742_write_reg(u8 reg, u8 data)
+{
+	hwa742.extif->set_bits_per_cycle(8);
+	hwa742.extif->write_command(&reg, 1);
+	hwa742.extif->write_data(&data, 1);
+}
+
+static void set_window_regs(int x_start, int y_start, int x_end, int y_end)
+{
+	u8 tmp[8];
+	u8 cmd;
+
+	x_end--;
+	y_end--;
+	tmp[0] = x_start;
+	tmp[1] = x_start >> 8;
+	tmp[2] = y_start;
+	tmp[3] = y_start >> 8;
+	tmp[4] = x_end;
+	tmp[5] = x_end >> 8;
+	tmp[6] = y_end;
+	tmp[7] = y_end >> 8;
+
+	hwa742.extif->set_bits_per_cycle(8);
+	cmd = HWA742_WINDOW_X_START_0;
+
+	hwa742.extif->write_command(&cmd, 1);
+
+	hwa742.extif->write_data(tmp, 8);
+}
+
+static void set_format_regs(int conv, int transl, int flags)
+{
+	if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
+		hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
+#ifdef VERBOSE
+		dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n");
+#endif
+	} else {
+		hwa742.window_type = (hwa742.window_type & 0xfc);
+#ifdef VERBOSE
+		dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n");
+#endif
+	}
+
+	hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
+	hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl);
+	hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type);
+}
+
+static void enable_tearsync(int y, int width, int height, int screen_height,
+			    int force_vsync)
+{
+	u8 b;
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b |= 1 << 2;
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+	if (likely(hwa742.vsync_only || force_vsync)) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if (width * hwa742.pix_tx_time < hwa742.line_upd_time) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	if ((width * hwa742.pix_tx_time / 1000) * height <
+	    (y + height) * (hwa742.line_upd_time / 1000)) {
+		hwa742.extif->enable_tearsync(1, 0);
+		return;
+	}
+
+	hwa742.extif->enable_tearsync(1, y + 1);
+}
+
+static void disable_tearsync(void)
+{
+	u8 b;
+
+	hwa742.extif->enable_tearsync(0, 0);
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b &= ~(1 << 2);
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+}
+
+static inline struct hwa742_request *alloc_req(void)
+{
+	unsigned long flags;
+	struct hwa742_request *req;
+	int req_flags = 0;
+
+	if (!in_interrupt())
+		down(&hwa742.req_sema);
+	else
+		req_flags = REQ_FROM_IRQ_POOL;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+	BUG_ON(list_empty(&hwa742.free_req_list));
+	req = list_entry(hwa742.free_req_list.next,
+			 struct hwa742_request, entry);
+	list_del(&req->entry);
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+	INIT_LIST_HEAD(&req->entry);
+	req->flags = req_flags;
+
+	return req;
+}
+
+static inline void free_req(struct hwa742_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+
+	list_move(&req->entry, &hwa742.free_req_list);
+	if (!(req->flags & REQ_FROM_IRQ_POOL))
+		up(&hwa742.req_sema);
+
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void process_pending_requests(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+
+	while (!list_empty(&hwa742.pending_req_list)) {
+		struct hwa742_request *req;
+		void (*complete)(void *);
+		void *complete_data;
+
+		req = list_entry(hwa742.pending_req_list.next,
+				 struct hwa742_request, entry);
+		spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+		if (req->handler(req) == REQ_PENDING)
+			return;
+
+		complete = req->complete;
+		complete_data = req->complete_data;
+		free_req(req);
+
+		if (complete)
+			complete(complete_data);
+
+		spin_lock_irqsave(&hwa742.req_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void submit_req_list(struct list_head *head)
+{
+	unsigned long flags;
+	int process = 1;
+
+	spin_lock_irqsave(&hwa742.req_lock, flags);
+	if (likely(!list_empty(&hwa742.pending_req_list)))
+		process = 0;
+	list_splice_init(head, hwa742.pending_req_list.prev);
+	spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+	if (process)
+		process_pending_requests();
+}
+
+static void request_complete(void *data)
+{
+	struct hwa742_request	*req = (struct hwa742_request *)data;
+	void			(*complete)(void *);
+	void			*complete_data;
+
+	complete = req->complete;
+	complete_data = req->complete_data;
+
+	free_req(req);
+
+	if (complete)
+		complete(complete_data);
+
+	process_pending_requests();
+}
+
+static int send_frame_handler(struct hwa742_request *req)
+{
+	struct update_param *par = &req->par.update;
+	int x = par->x;
+	int y = par->y;
+	int w = par->width;
+	int h = par->height;
+	int bpp;
+	int conv, transl;
+	unsigned long offset;
+	int color_mode = par->color_mode;
+	int flags = par->flags;
+	int scr_width = hwa742.fbdev->panel->x_res;
+	int scr_height = hwa742.fbdev->panel->y_res;
+
+#ifdef VERBOSE
+	dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d "
+		"color_mode %d flags %d\n",
+		x, y, w, h, scr_width, color_mode, flags);
+#endif
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_YUV422:
+		bpp = 16;
+		conv = 0x08;
+		transl = 0x25;
+		break;
+	case OMAPFB_COLOR_YUV420:
+		bpp = 12;
+		conv = 0x09;
+		transl = 0x25;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		bpp = 16;
+		conv = 0x01;
+		transl = 0x05;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (hwa742.prev_flags != flags ||
+	    hwa742.prev_color_mode != color_mode) {
+		set_format_regs(conv, transl, flags);
+		hwa742.prev_color_mode = color_mode;
+		hwa742.prev_flags = flags;
+	}
+	flags = req->par.update.flags;
+	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+		enable_tearsync(y, scr_width, h, scr_height,
+				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+	else
+		disable_tearsync();
+
+	set_window_regs(x, y, x + w, y + h);
+
+	offset = (scr_width * y + x) * bpp / 8;
+
+	hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX,
+			OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h,
+			color_mode);
+
+	hwa742.extif->set_bits_per_cycle(16);
+
+	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+	hwa742.extif->transfer_area(w, h, request_complete, req);
+
+	return REQ_PENDING;
+}
+
+static void send_frame_complete(void *data)
+{
+	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
+}
+
+#define ADD_PREQ(_x, _y, _w, _h) do {		\
+	req = alloc_req();			\
+	req->handler	= send_frame_handler;	\
+	req->complete	= send_frame_complete;	\
+	req->par.update.x = _x;			\
+	req->par.update.y = _y;			\
+	req->par.update.width  = _w;		\
+	req->par.update.height = _h;		\
+	req->par.update.color_mode = color_mode;\
+	req->par.update.flags	  = flags;	\
+	list_add_tail(&req->entry, req_head);	\
+} while(0)
+
+static void create_req_list(struct omapfb_update_window *win,
+			    struct list_head *req_head)
+{
+	struct hwa742_request *req;
+	int x = win->x;
+	int y = win->y;
+	int width = win->width;
+	int height = win->height;
+	int color_mode;
+	int flags;
+
+	flags = win->format & ~OMAPFB_FORMAT_MASK;
+	color_mode = win->format & OMAPFB_FORMAT_MASK;
+
+	if (x & 1) {
+		ADD_PREQ(x, y, 1, height);
+		width--;
+		x++;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+	if (width & ~1) {
+		unsigned int xspan = width & ~1;
+		unsigned int ystart = y;
+		unsigned int yspan = height;
+
+		if (xspan * height * 2 > hwa742.max_transmit_size) {
+			yspan = hwa742.max_transmit_size / (xspan * 2);
+			ADD_PREQ(x, ystart, xspan, yspan);
+			ystart += yspan;
+			yspan = height - yspan;
+			flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+		}
+
+		ADD_PREQ(x, ystart, xspan, yspan);
+		x += xspan;
+		width -= xspan;
+		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+	}
+	if (width)
+		ADD_PREQ(x, y, 1, height);
+}
+
+static void auto_update_complete(void *data)
+{
+	if (!hwa742.stop_auto_update)
+		mod_timer(&hwa742.auto_update_timer,
+			  jiffies + HWA742_AUTO_UPDATE_TIME);
+}
+
+static void hwa742_update_window_auto(unsigned long arg)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *last;
+
+	create_req_list(&hwa742.auto_update_window, &req_list);
+	last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+	last->complete = auto_update_complete;
+	last->complete_data = NULL;
+
+	submit_req_list(&req_list);
+}
+
+int hwa742_update_window_async(struct fb_info *fbi,
+				 struct omapfb_update_window *win,
+				 void (*complete_callback)(void *arg),
+				 void *complete_callback_data)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *last;
+	int r = 0;
+
+	if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
+		dev_dbg(hwa742.fbdev->dev, "invalid update mode\n");
+		r = -EINVAL;
+		goto out;
+	}
+	if (unlikely(win->format &
+	    ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE |
+	    OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) {
+		dev_dbg(hwa742.fbdev->dev, "invalid window flag\n");
+		r = -EINVAL;
+		goto out;
+	}
+
+	create_req_list(win, &req_list);
+	last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+	last->complete = complete_callback;
+	last->complete_data = (void *)complete_callback_data;
+
+	submit_req_list(&req_list);
+
+out:
+	return r;
+}
+EXPORT_SYMBOL(hwa742_update_window_async);
+
+static int hwa742_setup_plane(int plane, int channel_out,
+				  unsigned long offset, int screen_width,
+				  int pos_x, int pos_y, int width, int height,
+				  int color_mode)
+{
+	if (plane != OMAPFB_PLANE_GFX ||
+	    channel_out != OMAPFB_CHANNEL_OUT_LCD)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int hwa742_enable_plane(int plane, int enable)
+{
+	if (plane != 0)
+		return -EINVAL;
+
+	hwa742.int_ctrl->enable_plane(plane, enable);
+
+	return 0;
+}
+
+static int sync_handler(struct hwa742_request *req)
+{
+	complete(req->par.sync);
+	return REQ_COMPLETE;
+}
+
+static void hwa742_sync(void)
+{
+	LIST_HEAD(req_list);
+	struct hwa742_request *req;
+	struct completion comp;
+
+	req = alloc_req();
+
+	req->handler = sync_handler;
+	req->complete = NULL;
+	init_completion(&comp);
+	req->par.sync = &comp;
+
+	list_add(&req->entry, &req_list);
+	submit_req_list(&req_list);
+
+	wait_for_completion(&comp);
+}
+
+static void hwa742_bind_client(struct omapfb_notifier_block *nb)
+{
+	dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode);
+	if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+	}
+}
+
+static int hwa742_set_update_mode(enum omapfb_update_mode mode)
+{
+	if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
+	    mode != OMAPFB_UPDATE_DISABLED)
+		return -EINVAL;
+
+	if (mode == hwa742.update_mode)
+		return 0;
+
+	dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n",
+			mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
+			(mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
+
+	switch (hwa742.update_mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		hwa742.stop_auto_update = 1;
+		del_timer_sync(&hwa742.auto_update_timer);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	hwa742.update_mode = mode;
+	hwa742_sync();
+	hwa742.stop_auto_update = 0;
+
+	switch (mode) {
+	case OMAPFB_MANUAL_UPDATE:
+		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+		break;
+	case OMAPFB_AUTO_UPDATE:
+		hwa742_update_window_auto(0);
+		break;
+	case OMAPFB_UPDATE_DISABLED:
+		break;
+	}
+
+	return 0;
+}
+
+static enum omapfb_update_mode hwa742_get_update_mode(void)
+{
+	return hwa742.update_mode;
+}
+
+static unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+	int bus_tick = hwa742.extif_clk_period * div;
+	return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 12.2 ns (regs),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 16 ns (regs),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 2*SYSCLK  (regs),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns */
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+	t = &hwa742.reg_timings;
+	memset(t, 0, sizeof(*t));
+	t->clk_div = div;
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return hwa742.extif->convert_timings(t);
+}
+
+static int calc_lut_timing(unsigned long sysclk, int div)
+{
+	struct extif_timings *t;
+	unsigned long systim;
+
+	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+	 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
+	 * WEOffTime = WEOnTime + 1 ns,
+	 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
+	 * CSOffTime = REOffTime + 1 ns
+	 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
+	 * WriteCycle = 2*SYSCLK + 2 ns,
+	 * CSPulseWidth = 10 ns
+	 */
+	systim = 1000000000 / (sysclk / 1000);
+	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+	t = &hwa742.lut_timings;
+	memset(t, 0, sizeof(*t));
+
+	t->clk_div = div;
+
+	t->cs_on_time = 0;
+	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+	t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+	t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+					      26000, div);
+	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+	if (t->we_cycle_time < t->we_off_time)
+		t->we_cycle_time = t->we_off_time;
+	t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
+	if (t->re_cycle_time < t->re_off_time)
+		t->re_cycle_time = t->re_off_time;
+	t->cs_pulse_width = 0;
+
+	dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n",
+		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+		 t->we_on_time, t->we_off_time, t->re_cycle_time,
+		 t->we_cycle_time);
+	dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
+		 t->access_time, t->cs_pulse_width);
+
+	return hwa742.extif->convert_timings(t);
+}
+
+static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
+{
+	int max_clk_div;
+	int div;
+
+	hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div);
+	for (div = 1; div < max_clk_div; div++) {
+		if (calc_reg_timing(sysclk, div) == 0)
+			break;
+	}
+	if (div >= max_clk_div)
+		goto err;
+
+	*extif_mem_div = div;
+
+	for (div = 1; div < max_clk_div; div++) {
+		if (calc_lut_timing(sysclk, div) == 0)
+			break;
+	}
+
+	if (div >= max_clk_div)
+		goto err;
+
+	return 0;
+
+err:
+	dev_err(hwa742.fbdev->dev, "can't setup timings\n");
+	return -1;
+}
+
+static void calc_hwa742_clk_rates(unsigned long ext_clk,
+				unsigned long *sys_clk, unsigned long *pix_clk)
+{
+	int pix_clk_src;
+	int sys_div = 0, sys_mul = 0;
+	int pix_div;
+
+	pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG);
+	pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
+	if ((pix_clk_src & (0x3 << 1)) == 0) {
+		/* Source is the PLL */
+		sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1;
+		sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1;
+		*sys_clk = ext_clk * sys_mul / sys_div;
+	} else	/* else source is ext clk, or oscillator */
+		*sys_clk = ext_clk;
+
+	*pix_clk = *sys_clk / pix_div;			/* HZ */
+	dev_dbg(hwa742.fbdev->dev,
+		"ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
+		ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
+	dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
+		*sys_clk, *pix_clk);
+}
+
+
+static int setup_tearsync(unsigned long pix_clk, int extif_div)
+{
+	int hdisp, vdisp;
+	int hndp, vndp;
+	int hsw, vsw;
+	int hs, vs;
+	int hs_pol_inv, vs_pol_inv;
+	int use_hsvs, use_ndp;
+	u8  b;
+
+	hsw = hwa742_read_reg(HWA742_HS_W_REG);
+	vsw = hwa742_read_reg(HWA742_VS_W_REG);
+	hs_pol_inv = !(hsw & 0x80);
+	vs_pol_inv = !(vsw & 0x80);
+	hsw = hsw & 0x7f;
+	vsw = vsw & 0x3f;
+
+	hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8;
+	vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) +
+		((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8);
+
+	hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f;
+	vndp = hwa742_read_reg(HWA742_V_NDP_REG);
+
+	/* time to transfer one pixel (16bpp) in ps */
+	hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time;
+	if (hwa742.extif->get_max_tx_rate != NULL) {
+		/*
+		 * The external interface might have a rate limitation,
+		 * if so, we have to maximize our transfer rate.
+		 */
+		unsigned long min_tx_time;
+		unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate();
+
+		dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n",
+			max_tx_rate);
+		min_tx_time = 1000000000 / (max_tx_rate / 1000);  /* ps */
+		if (hwa742.pix_tx_time < min_tx_time)
+			hwa742.pix_tx_time = min_tx_time;
+	}
+
+	/* time to update one line in ps */
+	hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
+	hwa742.line_upd_time *= 1000;
+	if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time)
+		/*
+		 * transfer speed too low, we might have to use both
+		 * HS and VS
+		 */
+		use_hsvs = 1;
+	else
+		/* decent transfer speed, we'll always use only VS */
+		use_hsvs = 0;
+
+	if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
+		/*
+		 * HS or'ed with VS doesn't work, use the active high
+		 * TE signal based on HNDP / VNDP
+		 */
+		use_ndp = 1;
+		hs_pol_inv = 0;
+		vs_pol_inv = 0;
+		hs = hndp;
+		vs = vndp;
+	} else {
+		/*
+		 * Use HS or'ed with VS as a TE signal if both are needed
+		 * or VNDP if only vsync is needed.
+		 */
+		use_ndp = 0;
+		hs = hsw;
+		vs = vsw;
+		if (!use_hsvs) {
+			hs_pol_inv = 0;
+			vs_pol_inv = 0;
+		}
+	}
+
+	hs = hs * 1000000 / (pix_clk / 1000);			/* ps */
+	hs *= 1000;
+
+	vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000);	/* ps */
+	vs *= 1000;
+
+	if (vs <= hs)
+		return -EDOM;
+	/* set VS to 120% of HS to minimize VS detection time */
+	vs = hs * 12 / 10;
+	/* minimize HS too */
+	hs = 10000;
+
+	b = hwa742_read_reg(HWA742_NDP_CTRL);
+	b &= ~0x3;
+	b |= use_hsvs ? 1 : 0;
+	b |= (use_ndp && use_hsvs) ? 0 : 2;
+	hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+	hwa742.vsync_only = !use_hsvs;
+
+	dev_dbg(hwa742.fbdev->dev,
+		"pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
+		pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time);
+	dev_dbg(hwa742.fbdev->dev,
+		"hs %d ps vs %d ps mode %d vsync_only %d\n",
+		hs, vs, (b & 0x3), !use_hsvs);
+
+	return hwa742.extif->setup_tearsync(1, hs, vs,
+					    hs_pol_inv, vs_pol_inv, extif_div);
+}
+
+static void hwa742_get_caps(int plane, struct omapfb_caps *caps)
+{
+	hwa742.int_ctrl->get_caps(plane, caps);
+	caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
+		      OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE;
+	if (hwa742.te_connected)
+		caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
+	caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
+			   (1 << OMAPFB_COLOR_YUV420);
+}
+
+static void hwa742_suspend(void)
+{
+	hwa742.update_mode_before_suspend = hwa742.update_mode;
+	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	/* Enable sleep mode */
+	hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1);
+	clk_disable(hwa742.sys_ck);
+}
+
+static void hwa742_resume(void)
+{
+	clk_enable(hwa742.sys_ck);
+
+	/* Disable sleep mode */
+	hwa742_write_reg(HWA742_POWER_SAVE, 0);
+	while (1) {
+		/* Loop until PLL output is stabilized */
+		if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7))
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(msecs_to_jiffies(5));
+	}
+	hwa742_set_update_mode(hwa742.update_mode_before_suspend);
+}
+
+static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
+		       struct omapfb_mem_desc *req_vram)
+{
+	int r = 0, i;
+	u8 rev, conf;
+	unsigned long ext_clk;
+	unsigned long sys_clk, pix_clk;
+	int extif_mem_div;
+	struct omapfb_platform_data *omapfb_conf;
+
+	BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
+
+	hwa742.fbdev = fbdev;
+	hwa742.extif = fbdev->ext_if;
+	hwa742.int_ctrl = fbdev->int_ctrl;
+
+	omapfb_conf = dev_get_platdata(fbdev->dev);
+
+	hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck");
+
+	spin_lock_init(&hwa742.req_lock);
+
+	if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0)
+		goto err1;
+
+	if ((r = hwa742.extif->init(fbdev)) < 0)
+		goto err2;
+
+	ext_clk = clk_get_rate(hwa742.sys_ck);
+	if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
+		goto err3;
+	hwa742.extif->set_timings(&hwa742.reg_timings);
+	clk_enable(hwa742.sys_ck);
+
+	calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
+	if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
+		goto err4;
+	hwa742.extif->set_timings(&hwa742.reg_timings);
+
+	rev = hwa742_read_reg(HWA742_REV_CODE_REG);
+	if ((rev & 0xfc) != 0x80) {
+		dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev);
+		r = -ENODEV;
+		goto err4;
+	}
+
+
+	if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
+		dev_err(fbdev->dev,
+		      "HWA742: controller not initialized by the bootloader\n");
+		r = -ENODEV;
+		goto err4;
+	}
+
+	if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
+		dev_err(hwa742.fbdev->dev,
+			"HWA742: can't setup tearing synchronization\n");
+		goto err4;
+	}
+	hwa742.te_connected = 1;
+
+	hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
+
+	hwa742.update_mode = OMAPFB_UPDATE_DISABLED;
+
+	hwa742.auto_update_window.x = 0;
+	hwa742.auto_update_window.y = 0;
+	hwa742.auto_update_window.width = fbdev->panel->x_res;
+	hwa742.auto_update_window.height = fbdev->panel->y_res;
+	hwa742.auto_update_window.format = 0;
+
+	init_timer(&hwa742.auto_update_timer);
+	hwa742.auto_update_timer.function = hwa742_update_window_auto;
+	hwa742.auto_update_timer.data = 0;
+
+	hwa742.prev_color_mode = -1;
+	hwa742.prev_flags = 0;
+
+	hwa742.fbdev = fbdev;
+
+	INIT_LIST_HEAD(&hwa742.free_req_list);
+	INIT_LIST_HEAD(&hwa742.pending_req_list);
+	for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
+		list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list);
+	BUG_ON(i <= IRQ_REQ_POOL_SIZE);
+	sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
+
+	conf = hwa742_read_reg(HWA742_CONFIG_REG);
+	dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+
+	return 0;
+err4:
+	clk_disable(hwa742.sys_ck);
+err3:
+	hwa742.extif->cleanup();
+err2:
+	hwa742.int_ctrl->cleanup();
+err1:
+	return r;
+}
+
+static void hwa742_cleanup(void)
+{
+	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+	hwa742.extif->cleanup();
+	hwa742.int_ctrl->cleanup();
+	clk_disable(hwa742.sys_ck);
+}
+
+struct lcd_ctrl hwa742_ctrl = {
+	.name			= "hwa742",
+	.init			= hwa742_init,
+	.cleanup		= hwa742_cleanup,
+	.bind_client		= hwa742_bind_client,
+	.get_caps		= hwa742_get_caps,
+	.set_update_mode	= hwa742_set_update_mode,
+	.get_update_mode	= hwa742_get_update_mode,
+	.setup_plane		= hwa742_setup_plane,
+	.enable_plane		= hwa742_enable_plane,
+	.update_window		= hwa742_update_window_async,
+	.sync			= hwa742_sync,
+	.suspend		= hwa742_suspend,
+	.resume			= hwa742_resume,
+};
+
diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c
new file mode 100644
index 000000000000..4a5f2cd3d3bf
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_ams_delta.c
@@ -0,0 +1,225 @@
+/*
+ * Based on drivers/video/omap/lcd_inn1510.c
+ *
+ * LCD panel support for the Amstrad E3 (Delta) videophone.
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/lcd.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/board-ams-delta.h>
+
+#include "omapfb.h"
+
+#define AMS_DELTA_DEFAULT_CONTRAST	112
+
+#define AMS_DELTA_MAX_CONTRAST		0x00FF
+#define AMS_DELTA_LCD_POWER		0x0100
+
+
+/* LCD class device section */
+
+static int ams_delta_lcd;
+
+static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
+{
+	if (power == FB_BLANK_UNBLANK) {
+		if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) {
+			omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST,
+					OMAP_PWL_ENABLE);
+			omap_writeb(1, OMAP_PWL_CLK_ENABLE);
+			ams_delta_lcd |= AMS_DELTA_LCD_POWER;
+		}
+	} else {
+		if (ams_delta_lcd & AMS_DELTA_LCD_POWER) {
+			omap_writeb(0, OMAP_PWL_ENABLE);
+			omap_writeb(0, OMAP_PWL_CLK_ENABLE);
+			ams_delta_lcd &= ~AMS_DELTA_LCD_POWER;
+		}
+	}
+	return 0;
+}
+
+static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value)
+{
+	if ((value >= 0) && (value <= AMS_DELTA_MAX_CONTRAST)) {
+		omap_writeb(value, OMAP_PWL_ENABLE);
+		ams_delta_lcd &= ~AMS_DELTA_MAX_CONTRAST;
+		ams_delta_lcd |= value;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_LCD_CLASS_DEVICE
+static int ams_delta_lcd_get_power(struct lcd_device *dev)
+{
+	if (ams_delta_lcd & AMS_DELTA_LCD_POWER)
+		return FB_BLANK_UNBLANK;
+	else
+		return FB_BLANK_POWERDOWN;
+}
+
+static int ams_delta_lcd_get_contrast(struct lcd_device *dev)
+{
+	if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER))
+		return 0;
+
+	return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST;
+}
+
+static struct lcd_ops ams_delta_lcd_ops = {
+	.get_power = ams_delta_lcd_get_power,
+	.set_power = ams_delta_lcd_set_power,
+	.get_contrast = ams_delta_lcd_get_contrast,
+	.set_contrast = ams_delta_lcd_set_contrast,
+};
+#endif
+
+
+/* omapfb panel section */
+
+static const struct gpio _gpios[] = {
+	{
+		.gpio	= AMS_DELTA_GPIO_PIN_LCD_VBLEN,
+		.flags	= GPIOF_OUT_INIT_LOW,
+		.label	= "lcd_vblen",
+	},
+	{
+		.gpio	= AMS_DELTA_GPIO_PIN_LCD_NDISP,
+		.flags	= GPIOF_OUT_INIT_LOW,
+		.label	= "lcd_ndisp",
+	},
+};
+
+static int ams_delta_panel_init(struct lcd_panel *panel,
+		struct omapfb_device *fbdev)
+{
+	return gpio_request_array(_gpios, ARRAY_SIZE(_gpios));
+}
+
+static void ams_delta_panel_cleanup(struct lcd_panel *panel)
+{
+	gpio_free_array(_gpios, ARRAY_SIZE(_gpios));
+}
+
+static int ams_delta_panel_enable(struct lcd_panel *panel)
+{
+	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 1);
+	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 1);
+	return 0;
+}
+
+static void ams_delta_panel_disable(struct lcd_panel *panel)
+{
+	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 0);
+	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 0);
+}
+
+static unsigned long ams_delta_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static struct lcd_panel ams_delta_panel = {
+	.name		= "ams-delta",
+	.config		= 0,
+
+	.bpp		= 12,
+	.data_lines	= 16,
+	.x_res		= 480,
+	.y_res		= 320,
+	.pixel_clock	= 4687,
+	.hsw		= 3,
+	.hfp		= 1,
+	.hbp		= 1,
+	.vsw		= 1,
+	.vfp		= 0,
+	.vbp		= 0,
+	.pcd		= 0,
+	.acb		= 37,
+
+	.init		= ams_delta_panel_init,
+	.cleanup	= ams_delta_panel_cleanup,
+	.enable		= ams_delta_panel_enable,
+	.disable	= ams_delta_panel_disable,
+	.get_caps	= ams_delta_panel_get_caps,
+};
+
+
+/* platform driver section */
+
+static int ams_delta_panel_probe(struct platform_device *pdev)
+{
+	struct lcd_device *lcd_device = NULL;
+#ifdef CONFIG_LCD_CLASS_DEVICE
+	int ret;
+
+	lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
+						&ams_delta_lcd_ops);
+
+	if (IS_ERR(lcd_device)) {
+		ret = PTR_ERR(lcd_device);
+		dev_err(&pdev->dev, "failed to register device\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, lcd_device);
+	lcd_device->props.max_contrast = AMS_DELTA_MAX_CONTRAST;
+#endif
+
+	ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST);
+	ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
+
+	omapfb_register_panel(&ams_delta_panel);
+	return 0;
+}
+
+static int ams_delta_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int ams_delta_panel_suspend(struct platform_device *pdev,
+		pm_message_t mesg)
+{
+	return 0;
+}
+
+static int ams_delta_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver ams_delta_panel_driver = {
+	.probe		= ams_delta_panel_probe,
+	.remove		= ams_delta_panel_remove,
+	.suspend	= ams_delta_panel_suspend,
+	.resume		= ams_delta_panel_resume,
+	.driver		= {
+		.name	= "lcd_ams_delta",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(ams_delta_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_h3.c b/drivers/video/fbdev/omap/lcd_h3.c
new file mode 100644
index 000000000000..49bdeca81e50
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_h3.c
@@ -0,0 +1,127 @@
+/*
+ * LCD panel support for the TI OMAP H3 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/tps65010.h>
+
+#include <asm/gpio.h>
+#include "omapfb.h"
+
+#define MODULE_NAME	"omapfb-lcd_h3"
+
+static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void h3_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int h3_panel_enable(struct lcd_panel *panel)
+{
+	int r = 0;
+
+	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+	r = tps65010_set_gpio_out_value(GPIO1, HIGH);
+	if (!r)
+		r = tps65010_set_gpio_out_value(GPIO2, HIGH);
+	if (r)
+		pr_err(MODULE_NAME ": Unable to turn on LCD panel\n");
+
+	return r;
+}
+
+static void h3_panel_disable(struct lcd_panel *panel)
+{
+	int r = 0;
+
+	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+	r = tps65010_set_gpio_out_value(GPIO1, LOW);
+	if (!r)
+		tps65010_set_gpio_out_value(GPIO2, LOW);
+	if (r)
+		pr_err(MODULE_NAME ": Unable to turn off LCD panel\n");
+}
+
+static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel h3_panel = {
+	.name		= "h3",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.data_lines	= 16,
+	.bpp		= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12000,
+	.hsw		= 12,
+	.hfp		= 14,
+	.hbp		= 72 - 12,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 0,
+
+	.init		= h3_panel_init,
+	.cleanup	= h3_panel_cleanup,
+	.enable		= h3_panel_enable,
+	.disable	= h3_panel_disable,
+	.get_caps	= h3_panel_get_caps,
+};
+
+static int h3_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&h3_panel);
+	return 0;
+}
+
+static int h3_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int h3_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int h3_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver h3_panel_driver = {
+	.probe		= h3_panel_probe,
+	.remove		= h3_panel_remove,
+	.suspend	= h3_panel_suspend,
+	.resume		= h3_panel_resume,
+	.driver		= {
+		.name	= "lcd_h3",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(h3_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_htcherald.c b/drivers/video/fbdev/omap/lcd_htcherald.c
new file mode 100644
index 000000000000..20f477851d54
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_htcherald.c
@@ -0,0 +1,118 @@
+/*
+ * File: drivers/video/omap/lcd-htcherald.c
+ *
+ * LCD panel support for the HTC Herald
+ *
+ * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
+ * Copyright (C) 2009 Wing Linux
+ *
+ * Based on the lcd_htcwizard.c file from the linwizard project:
+ * Copyright (C) linwizard.sourceforge.net
+ * Author: Angelo Arrifano <miknix@gmail.com>
+ * Based on lcd_h4 by Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "omapfb.h"
+
+static int htcherald_panel_init(struct lcd_panel *panel,
+					struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void htcherald_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int htcherald_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void htcherald_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long htcherald_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+/* Found on WIZ200 (miknix) and some HERA110 models (darkstar62) */
+struct lcd_panel htcherald_panel_1 = {
+	.name		= "lcd_herald",
+	.config		= OMAP_LCDC_PANEL_TFT |
+			  OMAP_LCDC_INV_HSYNC |
+			  OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_PIX_CLOCK,
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 6093,
+	.pcd		= 0, /* 15 */
+	.hsw		= 10,
+	.hfp		= 10,
+	.hbp		= 20,
+	.vsw		= 3,
+	.vfp		= 2,
+	.vbp		= 2,
+
+	.init		= htcherald_panel_init,
+	.cleanup	= htcherald_panel_cleanup,
+	.enable		= htcherald_panel_enable,
+	.disable	= htcherald_panel_disable,
+	.get_caps	= htcherald_panel_get_caps,
+};
+
+static int htcherald_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&htcherald_panel_1);
+	return 0;
+}
+
+static int htcherald_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int htcherald_panel_suspend(struct platform_device *pdev,
+						pm_message_t mesg)
+{
+	return 0;
+}
+
+static int htcherald_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver htcherald_panel_driver = {
+	.probe		= htcherald_panel_probe,
+	.remove		= htcherald_panel_remove,
+	.suspend	= htcherald_panel_suspend,
+	.resume		= htcherald_panel_resume,
+	.driver		= {
+		.name	= "lcd_htcherald",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(htcherald_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_inn1510.c b/drivers/video/fbdev/omap/lcd_inn1510.c
new file mode 100644
index 000000000000..2ee423279e35
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_inn1510.c
@@ -0,0 +1,113 @@
+/*
+ * LCD panel support for the TI OMAP1510 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#include "omapfb.h"
+
+static int innovator1510_panel_init(struct lcd_panel *panel,
+				    struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void innovator1510_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int innovator1510_panel_enable(struct lcd_panel *panel)
+{
+	__raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+	return 0;
+}
+
+static void innovator1510_panel_disable(struct lcd_panel *panel)
+{
+	__raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+}
+
+static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel innovator1510_panel = {
+	.name		= "inn1510",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= innovator1510_panel_init,
+	.cleanup	= innovator1510_panel_cleanup,
+	.enable		= innovator1510_panel_enable,
+	.disable	= innovator1510_panel_disable,
+	.get_caps	= innovator1510_panel_get_caps,
+};
+
+static int innovator1510_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&innovator1510_panel);
+	return 0;
+}
+
+static int innovator1510_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int innovator1510_panel_suspend(struct platform_device *pdev,
+				       pm_message_t mesg)
+{
+	return 0;
+}
+
+static int innovator1510_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver innovator1510_panel_driver = {
+	.probe		= innovator1510_panel_probe,
+	.remove		= innovator1510_panel_remove,
+	.suspend	= innovator1510_panel_suspend,
+	.resume		= innovator1510_panel_resume,
+	.driver		= {
+		.name	= "lcd_inn1510",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(innovator1510_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_inn1610.c b/drivers/video/fbdev/omap/lcd_inn1610.c
new file mode 100644
index 000000000000..e3d3d135aa48
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_inn1610.c
@@ -0,0 +1,134 @@
+/*
+ * LCD panel support for the TI OMAP1610 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/gpio.h>
+#include "omapfb.h"
+
+#define MODULE_NAME	"omapfb-lcd_h3"
+
+static int innovator1610_panel_init(struct lcd_panel *panel,
+				    struct omapfb_device *fbdev)
+{
+	int r = 0;
+
+	/* configure GPIO(14, 15) as outputs */
+	if (gpio_request_one(14, GPIOF_OUT_INIT_LOW, "lcd_en0")) {
+		pr_err(MODULE_NAME ": can't request GPIO 14\n");
+		r = -1;
+		goto exit;
+	}
+	if (gpio_request_one(15, GPIOF_OUT_INIT_LOW, "lcd_en1")) {
+		pr_err(MODULE_NAME ": can't request GPIO 15\n");
+		gpio_free(14);
+		r = -1;
+		goto exit;
+	}
+exit:
+	return r;
+}
+
+static void innovator1610_panel_cleanup(struct lcd_panel *panel)
+{
+	gpio_free(15);
+	gpio_free(14);
+}
+
+static int innovator1610_panel_enable(struct lcd_panel *panel)
+{
+	/* set GPIO14 and GPIO15 high */
+	gpio_set_value(14, 1);
+	gpio_set_value(15, 1);
+	return 0;
+}
+
+static void innovator1610_panel_disable(struct lcd_panel *panel)
+{
+	/* set GPIO13, GPIO14 and GPIO15 low */
+	gpio_set_value(14, 0);
+	gpio_set_value(15, 0);
+}
+
+static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel innovator1610_panel = {
+	.name		= "inn1610",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 320,
+	.y_res		= 240,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= innovator1610_panel_init,
+	.cleanup	= innovator1610_panel_cleanup,
+	.enable		= innovator1610_panel_enable,
+	.disable	= innovator1610_panel_disable,
+	.get_caps	= innovator1610_panel_get_caps,
+};
+
+static int innovator1610_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&innovator1610_panel);
+	return 0;
+}
+
+static int innovator1610_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int innovator1610_panel_suspend(struct platform_device *pdev,
+				       pm_message_t mesg)
+{
+	return 0;
+}
+
+static int innovator1610_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver innovator1610_panel_driver = {
+	.probe		= innovator1610_panel_probe,
+	.remove		= innovator1610_panel_remove,
+	.suspend	= innovator1610_panel_suspend,
+	.resume		= innovator1610_panel_resume,
+	.driver		= {
+		.name	= "lcd_inn1610",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(innovator1610_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c
new file mode 100644
index 000000000000..803fee618d57
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_mipid.c
@@ -0,0 +1,615 @@
+/*
+ * LCD driver for MIPI DBI-C / DCS compatible LCDs
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+
+#include <linux/platform_data/lcd-mipid.h>
+
+#include "omapfb.h"
+
+#define MIPID_MODULE_NAME		"lcd_mipid"
+
+#define MIPID_CMD_READ_DISP_ID		0x04
+#define MIPID_CMD_READ_RED		0x06
+#define MIPID_CMD_READ_GREEN		0x07
+#define MIPID_CMD_READ_BLUE		0x08
+#define MIPID_CMD_READ_DISP_STATUS	0x09
+#define MIPID_CMD_RDDSDR		0x0F
+#define MIPID_CMD_SLEEP_IN		0x10
+#define MIPID_CMD_SLEEP_OUT		0x11
+#define MIPID_CMD_DISP_OFF		0x28
+#define MIPID_CMD_DISP_ON		0x29
+
+#define MIPID_ESD_CHECK_PERIOD		msecs_to_jiffies(5000)
+
+#define to_mipid_device(p)		container_of(p, struct mipid_device, \
+						panel)
+struct mipid_device {
+	int		enabled;
+	int		revision;
+	unsigned int	saved_bklight_level;
+	unsigned long	hw_guard_end;		/* next value of jiffies
+						   when we can issue the
+						   next sleep in/out command */
+	unsigned long	hw_guard_wait;		/* max guard time in jiffies */
+
+	struct omapfb_device	*fbdev;
+	struct spi_device	*spi;
+	struct mutex		mutex;
+	struct lcd_panel	panel;
+
+	struct workqueue_struct	*esd_wq;
+	struct delayed_work	esd_work;
+	void			(*esd_check)(struct mipid_device *m);
+};
+
+static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf,
+			   int wlen, u8 *rbuf, int rlen)
+{
+	struct spi_message	m;
+	struct spi_transfer	*x, xfer[4];
+	u16			w;
+	int			r;
+
+	BUG_ON(md->spi == NULL);
+
+	spi_message_init(&m);
+
+	memset(xfer, 0, sizeof(xfer));
+	x = &xfer[0];
+
+	cmd &=  0xff;
+	x->tx_buf		= &cmd;
+	x->bits_per_word	= 9;
+	x->len			= 2;
+	spi_message_add_tail(x, &m);
+
+	if (wlen) {
+		x++;
+		x->tx_buf		= wbuf;
+		x->len			= wlen;
+		x->bits_per_word	= 9;
+		spi_message_add_tail(x, &m);
+	}
+
+	if (rlen) {
+		x++;
+		x->rx_buf	= &w;
+		x->len		= 1;
+		spi_message_add_tail(x, &m);
+
+		if (rlen > 1) {
+			/* Arrange for the extra clock before the first
+			 * data bit.
+			 */
+			x->bits_per_word = 9;
+			x->len		 = 2;
+
+			x++;
+			x->rx_buf	 = &rbuf[1];
+			x->len		 = rlen - 1;
+			spi_message_add_tail(x, &m);
+		}
+	}
+
+	r = spi_sync(md->spi, &m);
+	if (r < 0)
+		dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
+
+	if (rlen)
+		rbuf[0] = w & 0xff;
+}
+
+static inline void mipid_cmd(struct mipid_device *md, int cmd)
+{
+	mipid_transfer(md, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void mipid_write(struct mipid_device *md,
+			       int reg, const u8 *buf, int len)
+{
+	mipid_transfer(md, reg, buf, len, NULL, 0);
+}
+
+static inline void mipid_read(struct mipid_device *md,
+			      int reg, u8 *buf, int len)
+{
+	mipid_transfer(md, reg, NULL, 0, buf, len);
+}
+
+static void set_data_lines(struct mipid_device *md, int data_lines)
+{
+	u16 par;
+
+	switch (data_lines) {
+	case 16:
+		par = 0x150;
+		break;
+	case 18:
+		par = 0x160;
+		break;
+	case 24:
+		par = 0x170;
+		break;
+	}
+	mipid_write(md, 0x3a, (u8 *)&par, 2);
+}
+
+static void send_init_string(struct mipid_device *md)
+{
+	u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
+
+	mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
+	set_data_lines(md, md->panel.data_lines);
+}
+
+static void hw_guard_start(struct mipid_device *md, int guard_msec)
+{
+	md->hw_guard_wait = msecs_to_jiffies(guard_msec);
+	md->hw_guard_end = jiffies + md->hw_guard_wait;
+}
+
+static void hw_guard_wait(struct mipid_device *md)
+{
+	unsigned long wait = md->hw_guard_end - jiffies;
+
+	if ((long)wait > 0 && wait <= md->hw_guard_wait) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(wait);
+	}
+}
+
+static void set_sleep_mode(struct mipid_device *md, int on)
+{
+	int cmd, sleep_time = 50;
+
+	if (on)
+		cmd = MIPID_CMD_SLEEP_IN;
+	else
+		cmd = MIPID_CMD_SLEEP_OUT;
+	hw_guard_wait(md);
+	mipid_cmd(md, cmd);
+	hw_guard_start(md, 120);
+	/*
+	 * When we enable the panel, it seems we _have_ to sleep
+	 * 120 ms before sending the init string. When disabling the
+	 * panel we'll sleep for the duration of 2 frames, so that the
+	 * controller can still provide the PCLK,HS,VS signals.
+	 */
+	if (!on)
+		sleep_time = 120;
+	msleep(sleep_time);
+}
+
+static void set_display_state(struct mipid_device *md, int enabled)
+{
+	int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
+
+	mipid_cmd(md, cmd);
+}
+
+static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+	struct mipid_platform_data *pd = md->spi->dev.platform_data;
+
+	if (pd->get_bklight_max == NULL || pd->set_bklight_level == NULL)
+		return -ENODEV;
+	if (level > pd->get_bklight_max(pd))
+		return -EINVAL;
+	if (!md->enabled) {
+		md->saved_bklight_level = level;
+		return 0;
+	}
+	pd->set_bklight_level(pd, level);
+
+	return 0;
+}
+
+static unsigned int mipid_get_bklight_level(struct lcd_panel *panel)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+	struct mipid_platform_data *pd = md->spi->dev.platform_data;
+
+	if (pd->get_bklight_level == NULL)
+		return -ENODEV;
+	return pd->get_bklight_level(pd);
+}
+
+static unsigned int mipid_get_bklight_max(struct lcd_panel *panel)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+	struct mipid_platform_data *pd = md->spi->dev.platform_data;
+
+	if (pd->get_bklight_max == NULL)
+		return -ENODEV;
+
+	return pd->get_bklight_max(pd);
+}
+
+static unsigned long mipid_get_caps(struct lcd_panel *panel)
+{
+	return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+static u16 read_first_pixel(struct mipid_device *md)
+{
+	u16 pixel;
+	u8 red, green, blue;
+
+	mutex_lock(&md->mutex);
+	mipid_read(md, MIPID_CMD_READ_RED, &red, 1);
+	mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1);
+	mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1);
+	mutex_unlock(&md->mutex);
+
+	switch (md->panel.data_lines) {
+	case 16:
+		pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1);
+		break;
+	case 24:
+		/* 24 bit -> 16 bit */
+		pixel = ((red >> 3) << 11) | ((green >> 2) << 5) |
+			(blue >> 3);
+		break;
+	default:
+		pixel = 0;
+		BUG();
+	}
+
+	return pixel;
+}
+
+static int mipid_run_test(struct lcd_panel *panel, int test_num)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+	static const u16 test_values[4] = {
+		0x0000, 0xffff, 0xaaaa, 0x5555,
+	};
+	int i;
+
+	if (test_num != MIPID_TEST_RGB_LINES)
+		return MIPID_TEST_INVALID;
+
+	for (i = 0; i < ARRAY_SIZE(test_values); i++) {
+		int delay;
+		unsigned long tmo;
+
+		omapfb_write_first_pixel(md->fbdev, test_values[i]);
+		tmo = jiffies + msecs_to_jiffies(100);
+		delay = 25;
+		while (1) {
+			u16 pixel;
+
+			msleep(delay);
+			pixel = read_first_pixel(md);
+			if (pixel == test_values[i])
+				break;
+			if (time_after(jiffies, tmo)) {
+				dev_err(&md->spi->dev,
+					"MIPI LCD RGB I/F test failed: "
+					"expecting %04x, got %04x\n",
+					test_values[i], pixel);
+				return MIPID_TEST_FAILED;
+			}
+			delay = 10;
+		}
+	}
+
+	return 0;
+}
+
+static void ls041y3_esd_recover(struct mipid_device *md)
+{
+	dev_err(&md->spi->dev, "performing LCD ESD recovery\n");
+	set_sleep_mode(md, 1);
+	set_sleep_mode(md, 0);
+}
+
+static void ls041y3_esd_check_mode1(struct mipid_device *md)
+{
+	u8 state1, state2;
+
+	mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1);
+	set_sleep_mode(md, 0);
+	mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1);
+	dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n",
+		state1, state2);
+	/* Each sleep out command will trigger a self diagnostic and flip
+	* Bit6 if the test passes.
+	*/
+	if (!((state1 ^ state2) & (1 << 6)))
+		ls041y3_esd_recover(md);
+}
+
+static void ls041y3_esd_check_mode2(struct mipid_device *md)
+{
+	int i;
+	u8 rbuf[2];
+	static const struct {
+		int	cmd;
+		int	wlen;
+		u16	wbuf[3];
+	} *rd, rd_ctrl[7] = {
+		{ 0xb0, 4, { 0x0101, 0x01fe, } },
+		{ 0xb1, 4, { 0x01de, 0x0121, } },
+		{ 0xc2, 4, { 0x0100, 0x0100, } },
+		{ 0xbd, 2, { 0x0100, } },
+		{ 0xc2, 4, { 0x01fc, 0x0103, } },
+		{ 0xb4, 0, },
+		{ 0x00, 0, },
+	};
+
+	rd = rd_ctrl;
+	for (i = 0; i < 3; i++, rd++)
+		mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
+
+	udelay(10);
+	mipid_read(md, rd->cmd, rbuf, 2);
+	rd++;
+
+	for (i = 0; i < 3; i++, rd++) {
+		udelay(10);
+		mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
+	}
+
+	dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]);
+	if (rbuf[1] == 0x00)
+		ls041y3_esd_recover(md);
+}
+
+static void ls041y3_esd_check(struct mipid_device *md)
+{
+	ls041y3_esd_check_mode1(md);
+	if (md->revision >= 0x88)
+		ls041y3_esd_check_mode2(md);
+}
+
+static void mipid_esd_start_check(struct mipid_device *md)
+{
+	if (md->esd_check != NULL)
+		queue_delayed_work(md->esd_wq, &md->esd_work,
+				   MIPID_ESD_CHECK_PERIOD);
+}
+
+static void mipid_esd_stop_check(struct mipid_device *md)
+{
+	if (md->esd_check != NULL)
+		cancel_delayed_work_sync(&md->esd_work);
+}
+
+static void mipid_esd_work(struct work_struct *work)
+{
+	struct mipid_device *md = container_of(work, struct mipid_device,
+					       esd_work.work);
+
+	mutex_lock(&md->mutex);
+	md->esd_check(md);
+	mutex_unlock(&md->mutex);
+	mipid_esd_start_check(md);
+}
+
+static int mipid_enable(struct lcd_panel *panel)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+
+	mutex_lock(&md->mutex);
+
+	if (md->enabled) {
+		mutex_unlock(&md->mutex);
+		return 0;
+	}
+	set_sleep_mode(md, 0);
+	md->enabled = 1;
+	send_init_string(md);
+	set_display_state(md, 1);
+	mipid_set_bklight_level(panel, md->saved_bklight_level);
+	mipid_esd_start_check(md);
+
+	mutex_unlock(&md->mutex);
+	return 0;
+}
+
+static void mipid_disable(struct lcd_panel *panel)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+
+	/*
+	 * A final ESD work might be called before returning,
+	 * so do this without holding the lock.
+	 */
+	mipid_esd_stop_check(md);
+	mutex_lock(&md->mutex);
+
+	if (!md->enabled) {
+		mutex_unlock(&md->mutex);
+		return;
+	}
+	md->saved_bklight_level = mipid_get_bklight_level(panel);
+	mipid_set_bklight_level(panel, 0);
+	set_display_state(md, 0);
+	set_sleep_mode(md, 1);
+	md->enabled = 0;
+
+	mutex_unlock(&md->mutex);
+}
+
+static int panel_enabled(struct mipid_device *md)
+{
+	u32 disp_status;
+	int enabled;
+
+	mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
+	disp_status = __be32_to_cpu(disp_status);
+	enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
+	dev_dbg(&md->spi->dev,
+		"LCD panel %senabled by bootloader (status 0x%04x)\n",
+		enabled ? "" : "not ", disp_status);
+	return enabled;
+}
+
+static int mipid_init(struct lcd_panel *panel,
+			    struct omapfb_device *fbdev)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+
+	md->fbdev = fbdev;
+	md->esd_wq = create_singlethread_workqueue("mipid_esd");
+	if (md->esd_wq == NULL) {
+		dev_err(&md->spi->dev, "can't create ESD workqueue\n");
+		return -ENOMEM;
+	}
+	INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work);
+	mutex_init(&md->mutex);
+
+	md->enabled = panel_enabled(md);
+
+	if (md->enabled)
+		mipid_esd_start_check(md);
+	else
+		md->saved_bklight_level = mipid_get_bklight_level(panel);
+
+	return 0;
+}
+
+static void mipid_cleanup(struct lcd_panel *panel)
+{
+	struct mipid_device *md = to_mipid_device(panel);
+
+	if (md->enabled)
+		mipid_esd_stop_check(md);
+	destroy_workqueue(md->esd_wq);
+}
+
+static struct lcd_panel mipid_panel = {
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.x_res		= 800,
+	.y_res		= 480,
+	.pixel_clock	= 21940,
+	.hsw		= 50,
+	.hfp		= 20,
+	.hbp		= 15,
+	.vsw		= 2,
+	.vfp		= 1,
+	.vbp		= 3,
+
+	.init			= mipid_init,
+	.cleanup		= mipid_cleanup,
+	.enable			= mipid_enable,
+	.disable		= mipid_disable,
+	.get_caps		= mipid_get_caps,
+	.set_bklight_level	= mipid_set_bklight_level,
+	.get_bklight_level	= mipid_get_bklight_level,
+	.get_bklight_max	= mipid_get_bklight_max,
+	.run_test		= mipid_run_test,
+};
+
+static int mipid_detect(struct mipid_device *md)
+{
+	struct mipid_platform_data *pdata;
+	u8 display_id[3];
+
+	pdata = md->spi->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&md->spi->dev, "missing platform data\n");
+		return -ENOENT;
+	}
+
+	mipid_read(md, MIPID_CMD_READ_DISP_ID, display_id, 3);
+	dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
+		display_id[0], display_id[1], display_id[2]);
+
+	switch (display_id[0]) {
+	case 0x45:
+		md->panel.name = "lph8923";
+		break;
+	case 0x83:
+		md->panel.name = "ls041y3";
+		md->esd_check = ls041y3_esd_check;
+		break;
+	default:
+		md->panel.name = "unknown";
+		dev_err(&md->spi->dev, "invalid display ID\n");
+		return -ENODEV;
+	}
+
+	md->revision = display_id[1];
+	md->panel.data_lines = pdata->data_lines;
+	pr_info("omapfb: %s rev %02x LCD detected, %d data lines\n",
+			md->panel.name, md->revision, md->panel.data_lines);
+
+	return 0;
+}
+
+static int mipid_spi_probe(struct spi_device *spi)
+{
+	struct mipid_device *md;
+	int r;
+
+	md = kzalloc(sizeof(*md), GFP_KERNEL);
+	if (md == NULL) {
+		dev_err(&spi->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+
+	spi->mode = SPI_MODE_0;
+	md->spi = spi;
+	dev_set_drvdata(&spi->dev, md);
+	md->panel = mipid_panel;
+
+	r = mipid_detect(md);
+	if (r < 0)
+		return r;
+
+	omapfb_register_panel(&md->panel);
+
+	return 0;
+}
+
+static int mipid_spi_remove(struct spi_device *spi)
+{
+	struct mipid_device *md = dev_get_drvdata(&spi->dev);
+
+	mipid_disable(&md->panel);
+	kfree(md);
+
+	return 0;
+}
+
+static struct spi_driver mipid_spi_driver = {
+	.driver = {
+		.name	= MIPID_MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= mipid_spi_probe,
+	.remove	= mipid_spi_remove,
+};
+
+module_spi_driver(mipid_spi_driver);
+
+MODULE_DESCRIPTION("MIPI display driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c
new file mode 100644
index 000000000000..7fbe04bce0ed
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_osk.c
@@ -0,0 +1,133 @@
+/*
+ * LCD panel support for the TI OMAP OSK board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ * Adapted for OSK by <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/mux.h>
+
+#include "omapfb.h"
+
+static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+	/* gpio2 was allocated in board init */
+	return 0;
+}
+
+static void osk_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int osk_panel_enable(struct lcd_panel *panel)
+{
+	/* configure PWL pin */
+	omap_cfg_reg(PWL);
+
+	/* Enable PWL unit */
+	omap_writeb(0x01, OMAP_PWL_CLK_ENABLE);
+
+	/* Set PWL level */
+	omap_writeb(0xFF, OMAP_PWL_ENABLE);
+
+	/* set GPIO2 high (lcd power enabled) */
+	gpio_set_value(2, 1);
+
+	return 0;
+}
+
+static void osk_panel_disable(struct lcd_panel *panel)
+{
+	/* Set PWL level to zero */
+	omap_writeb(0x00, OMAP_PWL_ENABLE);
+
+	/* Disable PWL unit */
+	omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
+
+	/* set GPIO2 low */
+	gpio_set_value(2, 0);
+}
+
+static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel osk_panel = {
+	.name		= "osk",
+	.config		= OMAP_LCDC_PANEL_TFT,
+
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 240,
+	.y_res		= 320,
+	.pixel_clock	= 12500,
+	.hsw		= 40,
+	.hfp		= 40,
+	.hbp		= 72,
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 0,
+	.pcd		= 12,
+
+	.init		= osk_panel_init,
+	.cleanup	= osk_panel_cleanup,
+	.enable		= osk_panel_enable,
+	.disable	= osk_panel_disable,
+	.get_caps	= osk_panel_get_caps,
+};
+
+static int osk_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&osk_panel);
+	return 0;
+}
+
+static int osk_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int osk_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int osk_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver osk_panel_driver = {
+	.probe		= osk_panel_probe,
+	.remove		= osk_panel_remove,
+	.suspend	= osk_panel_suspend,
+	.resume		= osk_panel_resume,
+	.driver		= {
+		.name	= "lcd_osk",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(osk_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_palmte.c b/drivers/video/fbdev/omap/lcd_palmte.c
new file mode 100644
index 000000000000..ff4fb624b904
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_palmte.c
@@ -0,0 +1,110 @@
+/*
+ * LCD panel support for the Palm Tungsten E
+ *
+ * Original version : Romain Goyet <r.goyet@gmail.com>
+ * Current version : Laurent Gonzalez <palmte.linux@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include "omapfb.h"
+
+static int palmte_panel_init(struct lcd_panel *panel,
+				struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmte_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmte_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmte_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmte_panel_get_caps(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+struct lcd_panel palmte_panel = {
+	.name		= "palmte",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			  OMAP_LCDC_HSVS_OPPOSITE,
+
+	.data_lines	= 16,
+	.bpp		= 8,
+	.pixel_clock	= 12000,
+	.x_res		= 320,
+	.y_res		= 320,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmte_panel_init,
+	.cleanup	= palmte_panel_cleanup,
+	.enable		= palmte_panel_enable,
+	.disable	= palmte_panel_disable,
+	.get_caps	= palmte_panel_get_caps,
+};
+
+static int palmte_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmte_panel);
+	return 0;
+}
+
+static int palmte_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmte_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmte_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver palmte_panel_driver = {
+	.probe		= palmte_panel_probe,
+	.remove		= palmte_panel_remove,
+	.suspend	= palmte_panel_suspend,
+	.resume		= palmte_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmte",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(palmte_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_palmtt.c b/drivers/video/fbdev/omap/lcd_palmtt.c
new file mode 100644
index 000000000000..aaf3c8ba1243
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_palmtt.c
@@ -0,0 +1,116 @@
+/*
+ * LCD panel support for Palm Tungsten|T
+ * Current version : Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Modified from lcd_inn1510.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+GPIO11 - backlight
+GPIO12 - screen blanking
+GPIO13 - screen blanking
+*/
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <asm/gpio.h>
+#include "omapfb.h"
+
+static int palmtt_panel_init(struct lcd_panel *panel,
+	struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmtt_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmtt_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmtt_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmtt_panel_get_caps(struct lcd_panel *panel)
+{
+	return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmtt_panel = {
+	.name		= "palmtt",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			OMAP_LCDC_HSVS_OPPOSITE,
+	.bpp		= 16,
+	.data_lines	= 16,
+	.x_res		= 320,
+	.y_res		= 320,
+	.pixel_clock	= 10000,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmtt_panel_init,
+	.cleanup	= palmtt_panel_cleanup,
+	.enable		= palmtt_panel_enable,
+	.disable	= palmtt_panel_disable,
+	.get_caps	= palmtt_panel_get_caps,
+};
+
+static int palmtt_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmtt_panel);
+	return 0;
+}
+
+static int palmtt_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmtt_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmtt_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver palmtt_panel_driver = {
+	.probe		= palmtt_panel_probe,
+	.remove		= palmtt_panel_remove,
+	.suspend	= palmtt_panel_suspend,
+	.resume		= palmtt_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmtt",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(palmtt_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcd_palmz71.c b/drivers/video/fbdev/omap/lcd_palmz71.c
new file mode 100644
index 000000000000..3b7d8aa1cf34
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcd_palmz71.c
@@ -0,0 +1,112 @@
+/*
+ * LCD panel support for the Palm Zire71
+ *
+ * Original version : Romain Goyet
+ * Current version : Laurent Gonzalez
+ * Modified for zire71 : Marek Vasut
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include "omapfb.h"
+
+static int palmz71_panel_init(struct lcd_panel *panel,
+			      struct omapfb_device *fbdev)
+{
+	return 0;
+}
+
+static void palmz71_panel_cleanup(struct lcd_panel *panel)
+{
+
+}
+
+static int palmz71_panel_enable(struct lcd_panel *panel)
+{
+	return 0;
+}
+
+static void palmz71_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmz71_panel_get_caps(struct lcd_panel *panel)
+{
+	return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmz71_panel = {
+	.name		= "palmz71",
+	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+			  OMAP_LCDC_HSVS_OPPOSITE,
+	.data_lines	= 16,
+	.bpp		= 16,
+	.pixel_clock	= 24000,
+	.x_res		= 320,
+	.y_res		= 320,
+	.hsw		= 4,
+	.hfp		= 8,
+	.hbp		= 28,
+	.vsw		= 1,
+	.vfp		= 8,
+	.vbp		= 7,
+	.pcd		= 0,
+
+	.init		= palmz71_panel_init,
+	.cleanup	= palmz71_panel_cleanup,
+	.enable		= palmz71_panel_enable,
+	.disable	= palmz71_panel_disable,
+	.get_caps	= palmz71_panel_get_caps,
+};
+
+static int palmz71_panel_probe(struct platform_device *pdev)
+{
+	omapfb_register_panel(&palmz71_panel);
+	return 0;
+}
+
+static int palmz71_panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int palmz71_panel_suspend(struct platform_device *pdev,
+				 pm_message_t mesg)
+{
+	return 0;
+}
+
+static int palmz71_panel_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver palmz71_panel_driver = {
+	.probe		= palmz71_panel_probe,
+	.remove		= palmz71_panel_remove,
+	.suspend	= palmz71_panel_suspend,
+	.resume		= palmz71_panel_resume,
+	.driver		= {
+		.name	= "lcd_palmz71",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(palmz71_panel_driver);
diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c
new file mode 100644
index 000000000000..b52f62595f65
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcdc.c
@@ -0,0 +1,856 @@
+/*
+ * OMAP1 internal LCD controller
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/gfp.h>
+
+#include <mach/lcdc.h>
+#include <linux/omap-dma.h>
+
+#include <asm/mach-types.h>
+
+#include "omapfb.h"
+
+#include "lcdc.h"
+
+#define MODULE_NAME			"lcdc"
+
+#define MAX_PALETTE_SIZE		PAGE_SIZE
+
+enum lcdc_load_mode {
+	OMAP_LCDC_LOAD_PALETTE,
+	OMAP_LCDC_LOAD_FRAME,
+	OMAP_LCDC_LOAD_PALETTE_AND_FRAME
+};
+
+static struct omap_lcd_controller {
+	enum omapfb_update_mode	update_mode;
+	int			ext_mode;
+
+	unsigned long		frame_offset;
+	int			screen_width;
+	int			xres;
+	int			yres;
+
+	enum omapfb_color_format	color_mode;
+	int			bpp;
+	void			*palette_virt;
+	dma_addr_t		palette_phys;
+	int			palette_code;
+	int			palette_size;
+
+	unsigned int		irq_mask;
+	struct completion	last_frame_complete;
+	struct completion	palette_load_complete;
+	struct clk		*lcd_ck;
+	struct omapfb_device	*fbdev;
+
+	void			(*dma_callback)(void *data);
+	void			*dma_callback_data;
+
+	int			fbmem_allocated;
+	dma_addr_t		vram_phys;
+	void			*vram_virt;
+	unsigned long		vram_size;
+} lcdc;
+
+static void inline enable_irqs(int mask)
+{
+	lcdc.irq_mask |= mask;
+}
+
+static void inline disable_irqs(int mask)
+{
+	lcdc.irq_mask &= ~mask;
+}
+
+static void set_load_mode(enum lcdc_load_mode mode)
+{
+	u32 l;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l &= ~(3 << 20);
+	switch (mode) {
+	case OMAP_LCDC_LOAD_PALETTE:
+		l |= 1 << 20;
+		break;
+	case OMAP_LCDC_LOAD_FRAME:
+		l |= 2 << 20;
+		break;
+	case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:
+		break;
+	default:
+		BUG();
+	}
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void enable_controller(void)
+{
+	u32 l;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l |= OMAP_LCDC_CTRL_LCD_EN;
+	l &= ~OMAP_LCDC_IRQ_MASK;
+	l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;	/* enabled IRQs */
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller_async(void)
+{
+	u32 l;
+	u32 mask;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;
+	/*
+	 * Preserve the DONE mask, since we still want to get the
+	 * final DONE irq. It will be disabled in the IRQ handler.
+	 */
+	mask &= ~OMAP_LCDC_IRQ_DONE;
+	l &= ~mask;
+	omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller(void)
+{
+	init_completion(&lcdc.last_frame_complete);
+	disable_controller_async();
+	if (!wait_for_completion_timeout(&lcdc.last_frame_complete,
+				msecs_to_jiffies(500)))
+		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+}
+
+static void reset_controller(u32 status)
+{
+	static unsigned long reset_count;
+	static unsigned long last_jiffies;
+
+	disable_controller_async();
+	reset_count++;
+	if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
+		dev_err(lcdc.fbdev->dev,
+			  "resetting (status %#010x,reset count %lu)\n",
+			  status, reset_count);
+		last_jiffies = jiffies;
+	}
+	if (reset_count < 100) {
+		enable_controller();
+	} else {
+		reset_count = 0;
+		dev_err(lcdc.fbdev->dev,
+			"too many reset attempts, giving up.\n");
+	}
+}
+
+/*
+ * Configure the LCD DMA according to the current mode specified by parameters
+ * in lcdc.fbdev and fbdev->var.
+ */
+static void setup_lcd_dma(void)
+{
+	static const int dma_elem_type[] = {
+		0,
+		OMAP_DMA_DATA_TYPE_S8,
+		OMAP_DMA_DATA_TYPE_S16,
+		0,
+		OMAP_DMA_DATA_TYPE_S32,
+	};
+	struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;
+	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+	unsigned long	src;
+	int		esize, xelem, yelem;
+
+	src = lcdc.vram_phys + lcdc.frame_offset;
+
+	switch (var->rotate) {
+	case 0:
+		if (plane->info.mirror || (src & 3) ||
+		    lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
+		    (lcdc.xres & 1))
+			esize = 2;
+		else
+			esize = 4;
+		xelem = lcdc.xres * lcdc.bpp / 8 / esize;
+		yelem = lcdc.yres;
+		break;
+	case 90:
+	case 180:
+	case 270:
+		if (cpu_is_omap15xx()) {
+			BUG();
+		}
+		esize = 2;
+		xelem = lcdc.yres * lcdc.bpp / 16;
+		yelem = lcdc.xres;
+		break;
+	default:
+		BUG();
+		return;
+	}
+#ifdef VERBOSE
+	dev_dbg(lcdc.fbdev->dev,
+		 "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
+		 src, esize, xelem, yelem);
+#endif
+	omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
+	if (!cpu_is_omap15xx()) {
+		int bpp = lcdc.bpp;
+
+		/*
+		 * YUV support is only for external mode when we have the
+		 * YUV window embedded in a 16bpp frame buffer.
+		 */
+		if (lcdc.color_mode == OMAPFB_COLOR_YUV420)
+			bpp = 16;
+		/* Set virtual xres elem size */
+		omap_set_lcd_dma_b1_vxres(
+			lcdc.screen_width * bpp / 8 / esize);
+		/* Setup transformations */
+		omap_set_lcd_dma_b1_rotation(var->rotate);
+		omap_set_lcd_dma_b1_mirror(plane->info.mirror);
+	}
+	omap_setup_lcd_dma();
+}
+
+static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)
+{
+	u32 status;
+
+	status = omap_readl(OMAP_LCDC_STATUS);
+
+	if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))
+		reset_controller(status);
+	else {
+		if (status & OMAP_LCDC_STAT_DONE) {
+			u32 l;
+
+			/*
+			 * Disable IRQ_DONE. The status bit will be cleared
+			 * only when the controller is reenabled and we don't
+			 * want to get more interrupts.
+			 */
+			l = omap_readl(OMAP_LCDC_CONTROL);
+			l &= ~OMAP_LCDC_IRQ_DONE;
+			omap_writel(l, OMAP_LCDC_CONTROL);
+			complete(&lcdc.last_frame_complete);
+		}
+		if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
+			disable_controller_async();
+			complete(&lcdc.palette_load_complete);
+		}
+	}
+
+	/*
+	 * Clear these interrupt status bits.
+	 * Sync_lost, FUF bits were cleared by disabling the LCD controller
+	 * LOADED_PALETTE can be cleared this way only in palette only
+	 * load mode. In other load modes it's cleared by disabling the
+	 * controller.
+	 */
+	status &= ~(OMAP_LCDC_STAT_VSYNC |
+		    OMAP_LCDC_STAT_LOADED_PALETTE |
+		    OMAP_LCDC_STAT_ABC |
+		    OMAP_LCDC_STAT_LINE_INT);
+	omap_writel(status, OMAP_LCDC_STATUS);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Change to a new video mode. We defer this to a later time to avoid any
+ * flicker and not to mess up the current LCD DMA context. For this we disable
+ * the LCD controller, which will generate a DONE irq after the last frame has
+ * been transferred. Then it'll be safe to reconfigure both the LCD controller
+ * as well as the LCD DMA.
+ */
+static int omap_lcdc_setup_plane(int plane, int channel_out,
+				 unsigned long offset, int screen_width,
+				 int pos_x, int pos_y, int width, int height,
+				 int color_mode)
+{
+	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+	int rot_x, rot_y;
+
+	if (var->rotate == 0) {
+		rot_x = panel->x_res;
+		rot_y = panel->y_res;
+	} else {
+		rot_x = panel->y_res;
+		rot_y = panel->x_res;
+	}
+	if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
+	    width > rot_x || height > rot_y) {
+#ifdef VERBOSE
+		dev_dbg(lcdc.fbdev->dev,
+			"invalid plane params plane %d pos_x %d pos_y %d "
+			"w %d h %d\n", plane, pos_x, pos_y, width, height);
+#endif
+		return -EINVAL;
+	}
+
+	lcdc.frame_offset = offset;
+	lcdc.xres = width;
+	lcdc.yres = height;
+	lcdc.screen_width = screen_width;
+	lcdc.color_mode = color_mode;
+
+	switch (color_mode) {
+	case OMAPFB_COLOR_CLUT_8BPP:
+		lcdc.bpp = 8;
+		lcdc.palette_code = 0x3000;
+		lcdc.palette_size = 512;
+		break;
+	case OMAPFB_COLOR_RGB565:
+		lcdc.bpp = 16;
+		lcdc.palette_code = 0x4000;
+		lcdc.palette_size = 32;
+		break;
+	case OMAPFB_COLOR_RGB444:
+		lcdc.bpp = 16;
+		lcdc.palette_code = 0x4000;
+		lcdc.palette_size = 32;
+		break;
+	case OMAPFB_COLOR_YUV420:
+		if (lcdc.ext_mode) {
+			lcdc.bpp = 12;
+			break;
+		}
+		/* fallthrough */
+	case OMAPFB_COLOR_YUV422:
+		if (lcdc.ext_mode) {
+			lcdc.bpp = 16;
+			break;
+		}
+		/* fallthrough */
+	default:
+		/* FIXME: other BPPs.
+		 * bpp1: code  0,     size 256
+		 * bpp2: code  0x1000 size 256
+		 * bpp4: code  0x2000 size 256
+		 * bpp12: code 0x4000 size 32
+		 */
+		dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);
+		BUG();
+		return -1;
+	}
+
+	if (lcdc.ext_mode) {
+		setup_lcd_dma();
+		return 0;
+	}
+
+	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+		disable_controller();
+		omap_stop_lcd_dma();
+		setup_lcd_dma();
+		enable_controller();
+	}
+
+	return 0;
+}
+
+static int omap_lcdc_enable_plane(int plane, int enable)
+{
+	dev_dbg(lcdc.fbdev->dev,
+		"plane %d enable %d update_mode %d ext_mode %d\n",
+		plane, enable, lcdc.update_mode, lcdc.ext_mode);
+	if (plane != OMAPFB_PLANE_GFX)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Configure the LCD DMA for a palette load operation and do the palette
+ * downloading synchronously. We don't use the frame+palette load mode of
+ * the controller, since the palette can always be downloaded separately.
+ */
+static void load_palette(void)
+{
+	u16	*palette;
+
+	palette = (u16 *)lcdc.palette_virt;
+
+	*(u16 *)palette &= 0x0fff;
+	*(u16 *)palette |= lcdc.palette_code;
+
+	omap_set_lcd_dma_b1(lcdc.palette_phys,
+		lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
+
+	omap_set_lcd_dma_single_transfer(1);
+	omap_setup_lcd_dma();
+
+	init_completion(&lcdc.palette_load_complete);
+	enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+	set_load_mode(OMAP_LCDC_LOAD_PALETTE);
+	enable_controller();
+	if (!wait_for_completion_timeout(&lcdc.palette_load_complete,
+				msecs_to_jiffies(500)))
+		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+	/* The controller gets disabled in the irq handler */
+	disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+	omap_stop_lcd_dma();
+
+	omap_set_lcd_dma_single_transfer(lcdc.ext_mode);
+}
+
+/* Used only in internal controller mode */
+static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
+			       u16 transp, int update_hw_pal)
+{
+	u16 *palette;
+
+	if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
+		return -EINVAL;
+
+	palette = (u16 *)lcdc.palette_virt;
+
+	palette[regno] &= ~0x0fff;
+	palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
+			   (blue >> 12);
+
+	if (update_hw_pal) {
+		disable_controller();
+		omap_stop_lcd_dma();
+		load_palette();
+		setup_lcd_dma();
+		set_load_mode(OMAP_LCDC_LOAD_FRAME);
+		enable_controller();
+	}
+
+	return 0;
+}
+
+static void calc_ck_div(int is_tft, int pck, int *pck_div)
+{
+	unsigned long lck;
+
+	pck = max(1, pck);
+	lck = clk_get_rate(lcdc.lcd_ck);
+	*pck_div = (lck + pck - 1) / pck;
+	if (is_tft)
+		*pck_div = max(2, *pck_div);
+	else
+		*pck_div = max(3, *pck_div);
+	if (*pck_div > 255) {
+		/* FIXME: try to adjust logic clock divider as well */
+		*pck_div = 255;
+		dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",
+			 pck / 1000);
+	}
+}
+
+static void inline setup_regs(void)
+{
+	u32 l;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+	int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+	unsigned long lck;
+	int pcd;
+
+	l = omap_readl(OMAP_LCDC_CONTROL);
+	l &= ~OMAP_LCDC_CTRL_LCD_TFT;
+	l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;
+#ifdef CONFIG_MACH_OMAP_PALMTE
+/* FIXME:if (machine_is_omap_palmte()) { */
+		/* PalmTE uses alternate TFT setting in 8BPP mode */
+		l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0;
+/*	} */
+#endif
+	omap_writel(l, OMAP_LCDC_CONTROL);
+
+	l = omap_readl(OMAP_LCDC_TIMING2);
+	l &= ~(((1 << 6) - 1) << 20);
+	l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;
+	omap_writel(l, OMAP_LCDC_TIMING2);
+
+	l = panel->x_res - 1;
+	l |= (panel->hsw - 1) << 10;
+	l |= (panel->hfp - 1) << 16;
+	l |= (panel->hbp - 1) << 24;
+	omap_writel(l, OMAP_LCDC_TIMING0);
+
+	l = panel->y_res - 1;
+	l |= (panel->vsw - 1) << 10;
+	l |= panel->vfp << 16;
+	l |= panel->vbp << 24;
+	omap_writel(l, OMAP_LCDC_TIMING1);
+
+	l = omap_readl(OMAP_LCDC_TIMING2);
+	l &= ~0xff;
+
+	lck = clk_get_rate(lcdc.lcd_ck);
+
+	if (!panel->pcd)
+		calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
+	else {
+		dev_warn(lcdc.fbdev->dev,
+		    "Pixel clock divider value is obsolete.\n"
+		    "Try to set pixel_clock to %lu and pcd to 0 "
+		    "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
+			lck / panel->pcd / 1000, panel->name);
+
+		pcd = panel->pcd;
+	}
+	l |= pcd & 0xff;
+	l |= panel->acb << 8;
+	omap_writel(l, OMAP_LCDC_TIMING2);
+
+	/* update panel info with the exact clock */
+	panel->pixel_clock = lck / pcd / 1000;
+}
+
+/*
+ * Configure the LCD controller, download the color palette and start a looped
+ * DMA transfer of the frame image data. Called only in internal
+ * controller mode.
+ */
+static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
+{
+	int r = 0;
+
+	if (mode != lcdc.update_mode) {
+		switch (mode) {
+		case OMAPFB_AUTO_UPDATE:
+			setup_regs();
+			load_palette();
+
+			/* Setup and start LCD DMA */
+			setup_lcd_dma();
+
+			set_load_mode(OMAP_LCDC_LOAD_FRAME);
+			enable_irqs(OMAP_LCDC_IRQ_DONE);
+			/* This will start the actual DMA transfer */
+			enable_controller();
+			lcdc.update_mode = mode;
+			break;
+		case OMAPFB_UPDATE_DISABLED:
+			disable_controller();
+			omap_stop_lcd_dma();
+			lcdc.update_mode = mode;
+			break;
+		default:
+			r = -EINVAL;
+		}
+	}
+
+	return r;
+}
+
+static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
+{
+	return lcdc.update_mode;
+}
+
+/* PM code called only in internal controller mode */
+static void omap_lcdc_suspend(void)
+{
+	omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);
+}
+
+static void omap_lcdc_resume(void)
+{
+	omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);
+}
+
+static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
+{
+	return;
+}
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)
+{
+	BUG_ON(callback == NULL);
+
+	if (lcdc.dma_callback)
+		return -EBUSY;
+	else {
+		lcdc.dma_callback = callback;
+		lcdc.dma_callback_data = data;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(omap_lcdc_set_dma_callback);
+
+void omap_lcdc_free_dma_callback(void)
+{
+	lcdc.dma_callback = NULL;
+}
+EXPORT_SYMBOL(omap_lcdc_free_dma_callback);
+
+static void lcdc_dma_handler(u16 status, void *data)
+{
+	if (lcdc.dma_callback)
+		lcdc.dma_callback(lcdc.dma_callback_data);
+}
+
+static int mmap_kern(void)
+{
+	struct vm_struct	*kvma;
+	struct vm_area_struct	vma;
+	pgprot_t		pgprot;
+	unsigned long		vaddr;
+
+	kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP);
+	if (kvma == NULL) {
+		dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n");
+		return -ENOMEM;
+	}
+	vma.vm_mm = &init_mm;
+
+	vaddr = (unsigned long)kvma->addr;
+	vma.vm_start = vaddr;
+	vma.vm_end = vaddr + lcdc.vram_size;
+
+	pgprot = pgprot_writecombine(pgprot_kernel);
+	if (io_remap_pfn_range(&vma, vaddr,
+			   lcdc.vram_phys >> PAGE_SHIFT,
+			   lcdc.vram_size, pgprot) < 0) {
+		dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n");
+		return -EAGAIN;
+	}
+
+	lcdc.vram_virt = (void *)vaddr;
+
+	return 0;
+}
+
+static void unmap_kern(void)
+{
+	vunmap(lcdc.vram_virt);
+}
+
+static int alloc_palette_ram(void)
+{
+	lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+		MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL);
+	if (lcdc.palette_virt == NULL) {
+		dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
+		return -ENOMEM;
+	}
+	memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
+
+	return 0;
+}
+
+static void free_palette_ram(void)
+{
+	dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
+			lcdc.palette_virt, lcdc.palette_phys);
+}
+
+static int alloc_fbmem(struct omapfb_mem_region *region)
+{
+	int bpp;
+	int frame_size;
+	struct lcd_panel *panel = lcdc.fbdev->panel;
+
+	bpp = panel->bpp;
+	if (bpp == 12)
+		bpp = 16;
+	frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);
+	if (region->size > frame_size)
+		frame_size = region->size;
+	lcdc.vram_size = frame_size;
+	lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+			lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL);
+	if (lcdc.vram_virt == NULL) {
+		dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
+		return -ENOMEM;
+	}
+	region->size = frame_size;
+	region->paddr = lcdc.vram_phys;
+	region->vaddr = lcdc.vram_virt;
+	region->alloc = 1;
+
+	memset(lcdc.vram_virt, 0, lcdc.vram_size);
+
+	return 0;
+}
+
+static void free_fbmem(void)
+{
+	dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size,
+			      lcdc.vram_virt, lcdc.vram_phys);
+}
+
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
+{
+	int r;
+
+	if (!req_md->region_cnt) {
+		dev_err(lcdc.fbdev->dev, "no memory regions defined\n");
+		return -EINVAL;
+	}
+
+	if (req_md->region_cnt > 1) {
+		dev_err(lcdc.fbdev->dev, "only one plane is supported\n");
+		req_md->region_cnt = 1;
+	}
+
+	if (req_md->region[0].paddr == 0) {
+		lcdc.fbmem_allocated = 1;
+		if ((r = alloc_fbmem(&req_md->region[0])) < 0)
+			return r;
+		return 0;
+	}
+
+	lcdc.vram_phys = req_md->region[0].paddr;
+	lcdc.vram_size = req_md->region[0].size;
+
+	if ((r = mmap_kern()) < 0)
+		return r;
+
+	dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n",
+		 lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt);
+
+	return 0;
+}
+
+static void cleanup_fbmem(void)
+{
+	if (lcdc.fbmem_allocated)
+		free_fbmem();
+	else
+		unmap_kern();
+}
+
+static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
+			  struct omapfb_mem_desc *req_vram)
+{
+	int r;
+	u32 l;
+	int rate;
+	struct clk *tc_ck;
+
+	lcdc.irq_mask = 0;
+
+	lcdc.fbdev = fbdev;
+	lcdc.ext_mode = ext_mode;
+
+	l = 0;
+	omap_writel(l, OMAP_LCDC_CONTROL);
+
+	/* FIXME:
+	 * According to errata some platforms have a clock rate limitiation
+	 */
+	lcdc.lcd_ck = clk_get(fbdev->dev, "lcd_ck");
+	if (IS_ERR(lcdc.lcd_ck)) {
+		dev_err(fbdev->dev, "unable to access LCD clock\n");
+		r = PTR_ERR(lcdc.lcd_ck);
+		goto fail0;
+	}
+
+	tc_ck = clk_get(fbdev->dev, "tc_ck");
+	if (IS_ERR(tc_ck)) {
+		dev_err(fbdev->dev, "unable to access TC clock\n");
+		r = PTR_ERR(tc_ck);
+		goto fail1;
+	}
+
+	rate = clk_get_rate(tc_ck);
+	clk_put(tc_ck);
+
+	if (machine_is_ams_delta())
+		rate /= 4;
+	if (machine_is_omap_h3())
+		rate /= 3;
+	r = clk_set_rate(lcdc.lcd_ck, rate);
+	if (r) {
+		dev_err(fbdev->dev, "failed to adjust LCD rate\n");
+		goto fail1;
+	}
+	clk_enable(lcdc.lcd_ck);
+
+	r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "unable to get IRQ\n");
+		goto fail2;
+	}
+
+	r = omap_request_lcd_dma(lcdc_dma_handler, NULL);
+	if (r) {
+		dev_err(fbdev->dev, "unable to get LCD DMA\n");
+		goto fail3;
+	}
+
+	omap_set_lcd_dma_single_transfer(ext_mode);
+	omap_set_lcd_dma_ext_controller(ext_mode);
+
+	if (!ext_mode)
+		if ((r = alloc_palette_ram()) < 0)
+			goto fail4;
+
+	if ((r = setup_fbmem(req_vram)) < 0)
+		goto fail5;
+
+	pr_info("omapfb: LCDC initialized\n");
+
+	return 0;
+fail5:
+	if (!ext_mode)
+		free_palette_ram();
+fail4:
+	omap_free_lcd_dma();
+fail3:
+	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+fail2:
+	clk_disable(lcdc.lcd_ck);
+fail1:
+	clk_put(lcdc.lcd_ck);
+fail0:
+	return r;
+}
+
+static void omap_lcdc_cleanup(void)
+{
+	if (!lcdc.ext_mode)
+		free_palette_ram();
+	cleanup_fbmem();
+	omap_free_lcd_dma();
+	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+	clk_disable(lcdc.lcd_ck);
+	clk_put(lcdc.lcd_ck);
+}
+
+const struct lcd_ctrl omap1_int_ctrl = {
+	.name			= "internal",
+	.init			= omap_lcdc_init,
+	.cleanup		= omap_lcdc_cleanup,
+	.get_caps		= omap_lcdc_get_caps,
+	.set_update_mode	= omap_lcdc_set_update_mode,
+	.get_update_mode	= omap_lcdc_get_update_mode,
+	.update_window		= NULL,
+	.suspend		= omap_lcdc_suspend,
+	.resume			= omap_lcdc_resume,
+	.setup_plane		= omap_lcdc_setup_plane,
+	.enable_plane		= omap_lcdc_enable_plane,
+	.setcolreg		= omap_lcdc_setcolreg,
+};
diff --git a/drivers/video/fbdev/omap/lcdc.h b/drivers/video/fbdev/omap/lcdc.h
new file mode 100644
index 000000000000..845222270db3
--- /dev/null
+++ b/drivers/video/fbdev/omap/lcdc.h
@@ -0,0 +1,9 @@
+#ifndef LCDC_H
+#define LCDC_H
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
+void omap_lcdc_free_dma_callback(void);
+
+extern const struct lcd_ctrl omap1_int_ctrl;
+
+#endif
diff --git a/drivers/video/fbdev/omap/omapfb.h b/drivers/video/fbdev/omap/omapfb.h
new file mode 100644
index 000000000000..2921d20e4fba
--- /dev/null
+++ b/drivers/video/fbdev/omap/omapfb.h
@@ -0,0 +1,246 @@
+/*
+ * File: drivers/video/omap/omapfb.h
+ *
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __OMAPFB_H
+#define __OMAPFB_H
+
+#include <linux/fb.h>
+#include <linux/mutex.h>
+#include <linux/omapfb.h>
+
+#define OMAPFB_EVENT_READY	1
+#define OMAPFB_EVENT_DISABLED	2
+
+#define OMAP_LCDC_INV_VSYNC             0x0001
+#define OMAP_LCDC_INV_HSYNC             0x0002
+#define OMAP_LCDC_INV_PIX_CLOCK         0x0004
+#define OMAP_LCDC_INV_OUTPUT_EN         0x0008
+#define OMAP_LCDC_HSVS_RISING_EDGE      0x0010
+#define OMAP_LCDC_HSVS_OPPOSITE         0x0020
+
+#define OMAP_LCDC_SIGNAL_MASK		0x003f
+
+#define OMAP_LCDC_PANEL_TFT		0x0100
+
+#define OMAPFB_PLANE_XRES_MIN		8
+#define OMAPFB_PLANE_YRES_MIN		8
+
+struct omapfb_device;
+
+#define OMAPFB_PLANE_NUM		1
+
+struct omapfb_mem_region {
+	u32		paddr;
+	void __iomem	*vaddr;
+	unsigned long	size;
+	u8		type;		/* OMAPFB_PLANE_MEM_* */
+	enum omapfb_color_format format;/* OMAPFB_COLOR_* */
+	unsigned	format_used:1;	/* Must be set when format is set.
+					 * Needed b/c of the badly chosen 0
+					 * base for OMAPFB_COLOR_* values
+					 */
+	unsigned	alloc:1;	/* allocated by the driver */
+	unsigned	map:1;		/* kernel mapped by the driver */
+};
+
+struct omapfb_mem_desc {
+	int				region_cnt;
+	struct omapfb_mem_region	region[OMAPFB_PLANE_NUM];
+};
+
+struct lcd_panel {
+	const char	*name;
+	int		config;		/* TFT/STN, signal inversion */
+	int		bpp;		/* Pixel format in fb mem */
+	int		data_lines;	/* Lines on LCD HW interface */
+
+	int		x_res, y_res;
+	int		pixel_clock;	/* In kHz */
+	int		hsw;		/* Horizontal synchronization
+					   pulse width */
+	int		hfp;		/* Horizontal front porch */
+	int		hbp;		/* Horizontal back porch */
+	int		vsw;		/* Vertical synchronization
+					   pulse width */
+	int		vfp;		/* Vertical front porch */
+	int		vbp;		/* Vertical back porch */
+	int		acb;		/* ac-bias pin frequency */
+	int		pcd;		/* pixel clock divider.
+					   Obsolete use pixel_clock instead */
+
+	int		(*init)		(struct lcd_panel *panel,
+					 struct omapfb_device *fbdev);
+	void		(*cleanup)	(struct lcd_panel *panel);
+	int		(*enable)	(struct lcd_panel *panel);
+	void		(*disable)	(struct lcd_panel *panel);
+	unsigned long	(*get_caps)	(struct lcd_panel *panel);
+	int		(*set_bklight_level)(struct lcd_panel *panel,
+					     unsigned int level);
+	unsigned int	(*get_bklight_level)(struct lcd_panel *panel);
+	unsigned int	(*get_bklight_max)  (struct lcd_panel *panel);
+	int		(*run_test)	(struct lcd_panel *panel, int test_num);
+};
+
+struct extif_timings {
+	int cs_on_time;
+	int cs_off_time;
+	int we_on_time;
+	int we_off_time;
+	int re_on_time;
+	int re_off_time;
+	int we_cycle_time;
+	int re_cycle_time;
+	int cs_pulse_width;
+	int access_time;
+
+	int clk_div;
+
+	u32 tim[5];		/* set by extif->convert_timings */
+
+	int converted;
+};
+
+struct lcd_ctrl_extif {
+	int  (*init)		(struct omapfb_device *fbdev);
+	void (*cleanup)		(void);
+	void (*get_clk_info)	(u32 *clk_period, u32 *max_clk_div);
+	unsigned long (*get_max_tx_rate)(void);
+	int  (*convert_timings)	(struct extif_timings *timings);
+	void (*set_timings)	(const struct extif_timings *timings);
+	void (*set_bits_per_cycle)(int bpc);
+	void (*write_command)	(const void *buf, unsigned int len);
+	void (*read_data)	(void *buf, unsigned int len);
+	void (*write_data)	(const void *buf, unsigned int len);
+	void (*transfer_area)	(int width, int height,
+				 void (callback)(void *data), void *data);
+	int  (*setup_tearsync)	(unsigned pin_cnt,
+				 unsigned hs_pulse_time, unsigned vs_pulse_time,
+				 int hs_pol_inv, int vs_pol_inv, int div);
+	int  (*enable_tearsync) (int enable, unsigned line);
+
+	unsigned long		max_transmit_size;
+};
+
+struct omapfb_notifier_block {
+	struct notifier_block	nb;
+	void			*data;
+	int			plane_idx;
+};
+
+typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
+					  unsigned long event,
+					  void *fbi);
+
+struct lcd_ctrl {
+	const char	*name;
+	void		*data;
+
+	int		(*init)		  (struct omapfb_device *fbdev,
+					   int ext_mode,
+					   struct omapfb_mem_desc *req_md);
+	void		(*cleanup)	  (void);
+	void		(*bind_client)	  (struct omapfb_notifier_block *nb);
+	void		(*get_caps)	  (int plane, struct omapfb_caps *caps);
+	int		(*set_update_mode)(enum omapfb_update_mode mode);
+	enum omapfb_update_mode (*get_update_mode)(void);
+	int		(*setup_plane)	  (int plane, int channel_out,
+					   unsigned long offset,
+					   int screen_width,
+					   int pos_x, int pos_y, int width,
+					   int height, int color_mode);
+	int		(*set_rotate)	  (int angle);
+	int		(*setup_mem)	  (int plane, size_t size,
+					   int mem_type, unsigned long *paddr);
+	int		(*mmap)		  (struct fb_info *info,
+					   struct vm_area_struct *vma);
+	int		(*set_scale)	  (int plane,
+					   int orig_width, int orig_height,
+					   int out_width, int out_height);
+	int		(*enable_plane)	  (int plane, int enable);
+	int		(*update_window)  (struct fb_info *fbi,
+					   struct omapfb_update_window *win,
+					   void (*callback)(void *),
+					   void *callback_data);
+	void		(*sync)		  (void);
+	void		(*suspend)	  (void);
+	void		(*resume)	  (void);
+	int		(*run_test)	  (int test_num);
+	int		(*setcolreg)	  (u_int regno, u16 red, u16 green,
+					   u16 blue, u16 transp,
+					   int update_hw_mem);
+	int		(*set_color_key)  (struct omapfb_color_key *ck);
+	int		(*get_color_key)  (struct omapfb_color_key *ck);
+};
+
+enum omapfb_state {
+	OMAPFB_DISABLED		= 0,
+	OMAPFB_SUSPENDED	= 99,
+	OMAPFB_ACTIVE		= 100
+};
+
+struct omapfb_plane_struct {
+	int				idx;
+	struct omapfb_plane_info	info;
+	enum omapfb_color_format	color_mode;
+	struct omapfb_device		*fbdev;
+};
+
+struct omapfb_device {
+	int			state;
+	int                     ext_lcdc;		/* Using external
+							   LCD controller */
+	struct mutex		rqueue_mutex;
+
+	int			palette_size;
+	u32			pseudo_palette[17];
+
+	struct lcd_panel	*panel;			/* LCD panel */
+	const struct lcd_ctrl	*ctrl;			/* LCD controller */
+	const struct lcd_ctrl	*int_ctrl;		/* internal LCD ctrl */
+	struct lcd_ctrl_extif	*ext_if;		/* LCD ctrl external
+							   interface */
+	struct device		*dev;
+	struct fb_var_screeninfo	new_var;	/* for mode changes */
+
+	struct omapfb_mem_desc		mem_desc;
+	struct fb_info			*fb_info[OMAPFB_PLANE_NUM];
+
+	struct platform_device	*dssdev;	/* dummy dev for clocks */
+};
+
+extern struct lcd_ctrl omap1_lcd_ctrl;
+
+extern void omapfb_register_panel(struct lcd_panel *panel);
+extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+				  unsigned long event);
+extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
+				   omapfb_notifier_callback_t callback,
+				   void *callback_data);
+extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
+extern int  omapfb_update_window_async(struct fb_info *fbi,
+				       struct omapfb_update_window *win,
+				       void (*callback)(void *),
+				       void *callback_data);
+
+#endif /* __OMAPFB_H */
diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
new file mode 100644
index 000000000000..e4fc6d9b5371
--- /dev/null
+++ b/drivers/video/fbdev/omap/omapfb_main.c
@@ -0,0 +1,1971 @@
+/*
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * Acknowledgements:
+ *   Alex McMains <aam@ridgerun.com>       - Original driver
+ *   Juha Yrjola <juha.yrjola@nokia.com>   - Original driver and improvements
+ *   Dirk Behme <dirk.behme@de.bosch.com>  - changes for 2.6 kernel API
+ *   Texas Instruments                     - H3 support
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+
+#include <linux/omap-dma.h>
+
+#include <mach/hardware.h>
+
+#include "omapfb.h"
+#include "lcdc.h"
+
+#define MODULE_NAME	"omapfb"
+
+static unsigned int	def_accel;
+static unsigned long	def_vram[OMAPFB_PLANE_NUM];
+static unsigned int	def_vram_cnt;
+static unsigned long	def_vxres;
+static unsigned long	def_vyres;
+static unsigned int	def_rotate;
+static unsigned int	def_mirror;
+
+#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
+static bool		manual_update = 1;
+#else
+static bool		manual_update;
+#endif
+
+static struct platform_device	*fbdev_pdev;
+static struct lcd_panel		*fbdev_panel;
+static struct omapfb_device	*omapfb_dev;
+
+struct caps_table_struct {
+	unsigned long flag;
+	const char *name;
+};
+
+static struct caps_table_struct ctrl_caps[] = {
+	{ OMAPFB_CAPS_MANUAL_UPDATE,  "manual update" },
+	{ OMAPFB_CAPS_TEARSYNC,       "tearing synchronization" },
+	{ OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" },
+	{ OMAPFB_CAPS_PLANE_SCALE,    "scale plane" },
+	{ OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
+	{ OMAPFB_CAPS_WINDOW_SCALE,   "scale window" },
+	{ OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
+	{ OMAPFB_CAPS_WINDOW_ROTATE,  "rotate window" },
+	{ OMAPFB_CAPS_SET_BACKLIGHT,  "backlight setting" },
+};
+
+static struct caps_table_struct color_caps[] = {
+	{ 1 << OMAPFB_COLOR_RGB565,	"RGB565", },
+	{ 1 << OMAPFB_COLOR_YUV422,	"YUV422", },
+	{ 1 << OMAPFB_COLOR_YUV420,	"YUV420", },
+	{ 1 << OMAPFB_COLOR_CLUT_8BPP,	"CLUT8", },
+	{ 1 << OMAPFB_COLOR_CLUT_4BPP,	"CLUT4", },
+	{ 1 << OMAPFB_COLOR_CLUT_2BPP,	"CLUT2", },
+	{ 1 << OMAPFB_COLOR_CLUT_1BPP,	"CLUT1", },
+	{ 1 << OMAPFB_COLOR_RGB444,	"RGB444", },
+	{ 1 << OMAPFB_COLOR_YUY422,	"YUY422", },
+};
+
+static void omapdss_release(struct device *dev)
+{
+}
+
+/* dummy device for clocks */
+static struct platform_device omapdss_device = {
+	.name		= "omapdss_dss",
+	.id		= -1,
+	.dev            = {
+		.release = omapdss_release,
+	},
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD panel
+ * ---------------------------------------------------------------------------
+ */
+extern struct lcd_ctrl hwa742_ctrl;
+
+static const struct lcd_ctrl *ctrls[] = {
+	&omap1_int_ctrl,
+
+#ifdef CONFIG_FB_OMAP_LCDC_HWA742
+	&hwa742_ctrl,
+#endif
+};
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+extern struct lcd_ctrl_extif omap1_ext_if;
+#endif
+
+static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
+{
+	mutex_lock(&fbdev->rqueue_mutex);
+}
+
+static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
+{
+	mutex_unlock(&fbdev->rqueue_mutex);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD controller and LCD DMA
+ * ---------------------------------------------------------------------------
+ */
+/*
+ * Allocate resources needed for LCD controller and LCD DMA operations. Video
+ * memory is allocated from system memory according to the virtual display
+ * size, except if a bigger memory size is specified explicitly as a kernel
+ * parameter.
+ */
+static int ctrl_init(struct omapfb_device *fbdev)
+{
+	int r;
+	int i;
+
+	/* kernel/module vram parameters override boot tags/board config */
+	if (def_vram_cnt) {
+		for (i = 0; i < def_vram_cnt; i++)
+			fbdev->mem_desc.region[i].size =
+				PAGE_ALIGN(def_vram[i]);
+		fbdev->mem_desc.region_cnt = i;
+	}
+
+	if (!fbdev->mem_desc.region_cnt) {
+		struct lcd_panel *panel = fbdev->panel;
+		int def_size;
+		int bpp = panel->bpp;
+
+		/* 12 bpp is packed in 16 bits */
+		if (bpp == 12)
+			bpp = 16;
+		def_size = def_vxres * def_vyres * bpp / 8;
+		fbdev->mem_desc.region_cnt = 1;
+		fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size);
+	}
+	r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc);
+	if (r < 0) {
+		dev_err(fbdev->dev, "controller initialization failed (%d)\n",
+			r);
+		return r;
+	}
+
+#ifdef DEBUG
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n",
+			 i,
+			 fbdev->mem_desc.region[i].paddr,
+			 fbdev->mem_desc.region[i].vaddr,
+			 fbdev->mem_desc.region[i].size);
+	}
+#endif
+	return 0;
+}
+
+static void ctrl_cleanup(struct omapfb_device *fbdev)
+{
+	fbdev->ctrl->cleanup();
+}
+
+/* Must be called with fbdev->rqueue_mutex held. */
+static int ctrl_change_mode(struct fb_info *fbi)
+{
+	int r;
+	unsigned long offset;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var = &fbi->var;
+
+	offset = var->yoffset * fbi->fix.line_length +
+		 var->xoffset * var->bits_per_pixel / 8;
+
+	if (fbdev->ctrl->sync)
+		fbdev->ctrl->sync();
+	r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out,
+				 offset, var->xres_virtual,
+				 plane->info.pos_x, plane->info.pos_y,
+				 var->xres, var->yres, plane->color_mode);
+	if (r < 0)
+		return r;
+
+	if (fbdev->ctrl->set_rotate != NULL) {
+		r = fbdev->ctrl->set_rotate(var->rotate);
+		if (r < 0)
+			return r;
+	}
+
+	if (fbdev->ctrl->set_scale != NULL)
+		r = fbdev->ctrl->set_scale(plane->idx,
+				   var->xres, var->yres,
+				   plane->info.out_width,
+				   plane->info.out_height);
+
+	return r;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks and the ioctl interface
+ * ---------------------------------------------------------------------------
+ */
+/* Called each time the omapfb device is opened */
+static int omapfb_open(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+static void omapfb_sync(struct fb_info *info);
+
+/* Called when the omapfb device is closed. We make sure that any pending
+ * gfx DMA operations are ended, before we return. */
+static int omapfb_release(struct fb_info *info, int user)
+{
+	omapfb_sync(info);
+	return 0;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
+			u_int blue, u_int transp, int update_hw_pal)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var = &info->var;
+	int r = 0;
+
+	switch (plane->color_mode) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUV420:
+	case OMAPFB_COLOR_YUY422:
+		r = -EINVAL;
+		break;
+	case OMAPFB_COLOR_CLUT_8BPP:
+	case OMAPFB_COLOR_CLUT_4BPP:
+	case OMAPFB_COLOR_CLUT_2BPP:
+	case OMAPFB_COLOR_CLUT_1BPP:
+		if (fbdev->ctrl->setcolreg)
+			r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+							transp, update_hw_pal);
+		/* Fallthrough */
+	case OMAPFB_COLOR_RGB565:
+	case OMAPFB_COLOR_RGB444:
+		if (r != 0)
+			break;
+
+		if (regno < 0) {
+			r = -EINVAL;
+			break;
+		}
+
+		if (regno < 16) {
+			u16 pal;
+			pal = ((red >> (16 - var->red.length)) <<
+					var->red.offset) |
+			      ((green >> (16 - var->green.length)) <<
+					var->green.offset) |
+			      (blue >> (16 - var->blue.length));
+			((u32 *)(info->pseudo_palette))[regno] = pal;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			    u_int transp, struct fb_info *info)
+{
+	return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	int count, index, r;
+	u16 *red, *green, *blue, *transp;
+	u16 trans = 0xffff;
+
+	red     = cmap->red;
+	green   = cmap->green;
+	blue    = cmap->blue;
+	transp  = cmap->transp;
+	index   = cmap->start;
+
+	for (count = 0; count < cmap->len; count++) {
+		if (transp)
+			trans = *transp++;
+		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+				count == cmap->len - 1);
+		if (r != 0)
+			return r;
+	}
+
+	return 0;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi);
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int do_update = 0;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		if (fbdev->state == OMAPFB_SUSPENDED) {
+			if (fbdev->ctrl->resume)
+				fbdev->ctrl->resume();
+			fbdev->panel->enable(fbdev->panel);
+			fbdev->state = OMAPFB_ACTIVE;
+			if (fbdev->ctrl->get_update_mode() ==
+					OMAPFB_MANUAL_UPDATE)
+				do_update = 1;
+		}
+		break;
+	case FB_BLANK_POWERDOWN:
+		if (fbdev->state == OMAPFB_ACTIVE) {
+			fbdev->panel->disable(fbdev->panel);
+			if (fbdev->ctrl->suspend)
+				fbdev->ctrl->suspend();
+			fbdev->state = OMAPFB_SUSPENDED;
+		}
+		break;
+	default:
+		r = -EINVAL;
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	if (r == 0 && do_update)
+		r = omapfb_update_full_screen(fbi);
+
+	return r;
+}
+
+static void omapfb_sync(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+
+	omapfb_rqueue_lock(fbdev);
+	if (fbdev->ctrl->sync)
+		fbdev->ctrl->sync();
+	omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set fb_info.fix fields and also updates fbdev.
+ * When calling this fb_info.var must be set up already.
+ */
+static void set_fb_fix(struct fb_info *fbi, int from_init)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_mem_region *rg;
+	int bpp;
+
+	rg = &plane->fbdev->mem_desc.region[plane->idx];
+	fbi->screen_base	= rg->vaddr;
+
+	if (!from_init) {
+		mutex_lock(&fbi->mm_lock);
+		fix->smem_start		= rg->paddr;
+		fix->smem_len		= rg->size;
+		mutex_unlock(&fbi->mm_lock);
+	} else {
+		fix->smem_start		= rg->paddr;
+		fix->smem_len		= rg->size;
+	}
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	bpp = var->bits_per_pixel;
+	if (var->nonstd)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else switch (var->bits_per_pixel) {
+	case 16:
+	case 12:
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		/* 12bpp is stored in 16 bits */
+		bpp = 16;
+		break;
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+	fix->accel		= FB_ACCEL_OMAP1610;
+	fix->line_length	= var->xres_virtual * bpp / 8;
+}
+
+static int set_color_mode(struct omapfb_plane_struct *plane,
+			  struct fb_var_screeninfo *var)
+{
+	switch (var->nonstd) {
+	case 0:
+		break;
+	case OMAPFB_COLOR_YUV422:
+		var->bits_per_pixel = 16;
+		plane->color_mode = var->nonstd;
+		return 0;
+	case OMAPFB_COLOR_YUV420:
+		var->bits_per_pixel = 12;
+		plane->color_mode = var->nonstd;
+		return 0;
+	case OMAPFB_COLOR_YUY422:
+		var->bits_per_pixel = 16;
+		plane->color_mode = var->nonstd;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		plane->color_mode = OMAPFB_COLOR_CLUT_1BPP;
+		return 0;
+	case 2:
+		plane->color_mode = OMAPFB_COLOR_CLUT_2BPP;
+		return 0;
+	case 4:
+		plane->color_mode = OMAPFB_COLOR_CLUT_4BPP;
+		return 0;
+	case 8:
+		plane->color_mode = OMAPFB_COLOR_CLUT_8BPP;
+		return 0;
+	case 12:
+		var->bits_per_pixel = 16;
+	case 16:
+		if (plane->fbdev->panel->bpp == 12)
+			plane->color_mode = OMAPFB_COLOR_RGB444;
+		else
+			plane->color_mode = OMAPFB_COLOR_RGB565;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/*
+ * Check the values in var against our capabilities and in case of out of
+ * bound values try to adjust them.
+ */
+static int set_fb_var(struct fb_info *fbi,
+		      struct fb_var_screeninfo *var)
+{
+	int		bpp;
+	unsigned long	max_frame_size;
+	unsigned long	line_size;
+	int		xres_min, xres_max;
+	int		yres_min, yres_max;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct lcd_panel *panel = fbdev->panel;
+
+	if (set_color_mode(plane, var) < 0)
+		return -EINVAL;
+
+	bpp = var->bits_per_pixel;
+	if (plane->color_mode == OMAPFB_COLOR_RGB444)
+		bpp = 16;
+
+	switch (var->rotate) {
+	case 0:
+	case 180:
+		xres_min = OMAPFB_PLANE_XRES_MIN;
+		xres_max = panel->x_res;
+		yres_min = OMAPFB_PLANE_YRES_MIN;
+		yres_max = panel->y_res;
+		if (cpu_is_omap15xx()) {
+			var->xres = panel->x_res;
+			var->yres = panel->y_res;
+		}
+		break;
+	case 90:
+	case 270:
+		xres_min = OMAPFB_PLANE_YRES_MIN;
+		xres_max = panel->y_res;
+		yres_min = OMAPFB_PLANE_XRES_MIN;
+		yres_max = panel->x_res;
+		if (cpu_is_omap15xx()) {
+			var->xres = panel->y_res;
+			var->yres = panel->x_res;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (var->xres < xres_min)
+		var->xres = xres_min;
+	if (var->yres < yres_min)
+		var->yres = yres_min;
+	if (var->xres > xres_max)
+		var->xres = xres_max;
+	if (var->yres > yres_max)
+		var->yres = yres_max;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	max_frame_size = fbdev->mem_desc.region[plane->idx].size;
+	line_size = var->xres_virtual * bpp / 8;
+	if (line_size * var->yres_virtual > max_frame_size) {
+		/* Try to keep yres_virtual first */
+		line_size = max_frame_size / var->yres_virtual;
+		var->xres_virtual = line_size * 8 / bpp;
+		if (var->xres_virtual < var->xres) {
+			/* Still doesn't fit. Shrink yres_virtual too */
+			var->xres_virtual = var->xres;
+			line_size = var->xres * bpp / 8;
+			var->yres_virtual = max_frame_size / line_size;
+		}
+		/* Recheck this, as the virtual size changed. */
+		if (var->xres_virtual < var->xres)
+			var->xres = var->xres_virtual;
+		if (var->yres_virtual < var->yres)
+			var->yres = var->yres_virtual;
+		if (var->xres < xres_min || var->yres < yres_min)
+			return -EINVAL;
+	}
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	if (plane->color_mode == OMAPFB_COLOR_RGB444) {
+		var->red.offset	  = 8; var->red.length	 = 4;
+						var->red.msb_right   = 0;
+		var->green.offset = 4; var->green.length = 4;
+						var->green.msb_right = 0;
+		var->blue.offset  = 0; var->blue.length  = 4;
+						var->blue.msb_right  = 0;
+	} else {
+		var->red.offset	 = 11; var->red.length	 = 5;
+						var->red.msb_right   = 0;
+		var->green.offset = 5;  var->green.length = 6;
+						var->green.msb_right = 0;
+		var->blue.offset = 0;  var->blue.length  = 5;
+						var->blue.msb_right  = 0;
+	}
+
+	var->height		= -1;
+	var->width		= -1;
+	var->grayscale		= 0;
+
+	/* pixclock in ps, the rest in pixclock */
+	var->pixclock		= 10000000 / (panel->pixel_clock / 100);
+	var->left_margin	= panel->hfp;
+	var->right_margin	= panel->hbp;
+	var->upper_margin	= panel->vfp;
+	var->lower_margin	= panel->vbp;
+	var->hsync_len		= panel->hsw;
+	var->vsync_len		= panel->vsw;
+
+	/* TODO: get these from panel->config */
+	var->vmode		= FB_VMODE_NONINTERLACED;
+	var->sync		= 0;
+
+	return 0;
+}
+
+
+/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
+static void omapfb_rotate(struct fb_info *fbi, int rotate)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+
+	omapfb_rqueue_lock(fbdev);
+	if (rotate != fbi->var.rotate) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+		memcpy(new_var, &fbi->var, sizeof(*new_var));
+		new_var->rotate = rotate;
+		if (set_fb_var(fbi, new_var) == 0 &&
+		    memcmp(new_var, &fbi->var, sizeof(*new_var))) {
+			memcpy(&fbi->var, new_var, sizeof(*new_var));
+			ctrl_change_mode(fbi);
+		}
+	}
+	omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set new x,y offsets in the virtual display for the visible area and switch
+ * to the new mode.
+ */
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	if (var->xoffset != fbi->var.xoffset ||
+	    var->yoffset != fbi->var.yoffset) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+		memcpy(new_var, &fbi->var, sizeof(*new_var));
+		new_var->xoffset = var->xoffset;
+		new_var->yoffset = var->yoffset;
+		if (set_fb_var(fbi, new_var))
+			r = -EINVAL;
+		else {
+			memcpy(&fbi->var, new_var, sizeof(*new_var));
+			ctrl_change_mode(fbi);
+		}
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/* Set mirror to vertical axis and switch to the new mode. */
+static int omapfb_mirror(struct fb_info *fbi, int mirror)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	mirror = mirror ? 1 : 0;
+	if (cpu_is_omap15xx())
+		r = -EINVAL;
+	else if (mirror != plane->info.mirror) {
+		plane->info.mirror = mirror;
+		r = ctrl_change_mode(fbi);
+	}
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Check values in var, try to adjust them in case of out of bound values if
+ * possible, or return error.
+ */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	if (fbdev->ctrl->sync != NULL)
+		fbdev->ctrl->sync();
+	r = set_fb_var(fbi, var);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Switch to a new mode. The parameters for it has been check already by
+ * omapfb_check_var.
+ */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	set_fb_fix(fbi, 0);
+	r = ctrl_change_mode(fbi);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+int omapfb_update_window_async(struct fb_info *fbi,
+				struct omapfb_update_window *win,
+				void (*callback)(void *),
+				void *callback_data)
+{
+	int xres, yres;
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct fb_var_screeninfo *var = &fbi->var;
+
+	switch (var->rotate) {
+	case 0:
+	case 180:
+		xres = fbdev->panel->x_res;
+		yres = fbdev->panel->y_res;
+		break;
+	case 90:
+	case 270:
+		xres = fbdev->panel->y_res;
+		yres = fbdev->panel->x_res;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (win->x >= xres || win->y >= yres ||
+	    win->out_x > xres || win->out_y > yres)
+		return -EINVAL;
+
+	if (!fbdev->ctrl->update_window ||
+	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+		return -ENODEV;
+
+	if (win->x + win->width > xres)
+		win->width = xres - win->x;
+	if (win->y + win->height > yres)
+		win->height = yres - win->y;
+	if (win->out_x + win->out_width > xres)
+		win->out_width = xres - win->out_x;
+	if (win->out_y + win->out_height > yres)
+		win->out_height = yres - win->out_y;
+	if (!win->width || !win->height || !win->out_width || !win->out_height)
+		return 0;
+
+	return fbdev->ctrl->update_window(fbi, win, callback, callback_data);
+}
+EXPORT_SYMBOL(omapfb_update_window_async);
+
+static int omapfb_update_win(struct fb_info *fbi,
+				struct omapfb_update_window *win)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	int ret;
+
+	omapfb_rqueue_lock(plane->fbdev);
+	ret = omapfb_update_window_async(fbi, win, NULL, NULL);
+	omapfb_rqueue_unlock(plane->fbdev);
+
+	return ret;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_update_window win;
+	int r;
+
+	if (!fbdev->ctrl->update_window ||
+	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+		return -ENODEV;
+
+	win.x = 0;
+	win.y = 0;
+	win.width = fbi->var.xres;
+	win.height = fbi->var.yres;
+	win.out_x = 0;
+	win.out_y = 0;
+	win.out_width = fbi->var.xres;
+	win.out_height = fbi->var.yres;
+	win.format = 0;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct lcd_panel *panel = fbdev->panel;
+	struct omapfb_plane_info old_info;
+	int r = 0;
+
+	if (pi->pos_x + pi->out_width > panel->x_res ||
+	    pi->pos_y + pi->out_height > panel->y_res)
+		return -EINVAL;
+
+	omapfb_rqueue_lock(fbdev);
+	if (pi->enabled && !fbdev->mem_desc.region[plane->idx].size) {
+		/*
+		 * This plane's memory was freed, can't enable it
+		 * until it's reallocated.
+		 */
+		r = -EINVAL;
+		goto out;
+	}
+	old_info = plane->info;
+	plane->info = *pi;
+	if (pi->enabled) {
+		r = ctrl_change_mode(fbi);
+		if (r < 0) {
+			plane->info = old_info;
+			goto out;
+		}
+	}
+	r = fbdev->ctrl->enable_plane(plane->idx, pi->enabled);
+	if (r < 0) {
+		plane->info = old_info;
+		goto out;
+	}
+out:
+	omapfb_rqueue_unlock(fbdev);
+	return r;
+}
+
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+
+	*pi = plane->info;
+	return 0;
+}
+
+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_mem_region *rg = &fbdev->mem_desc.region[plane->idx];
+	size_t size;
+	int r = 0;
+
+	if (fbdev->ctrl->setup_mem == NULL)
+		return -ENODEV;
+	if (mi->type != OMAPFB_MEMTYPE_SDRAM)
+		return -EINVAL;
+
+	size = PAGE_ALIGN(mi->size);
+	omapfb_rqueue_lock(fbdev);
+	if (plane->info.enabled) {
+		r = -EBUSY;
+		goto out;
+	}
+	if (rg->size != size || rg->type != mi->type) {
+		struct fb_var_screeninfo *new_var = &fbdev->new_var;
+		unsigned long old_size = rg->size;
+		u8	      old_type = rg->type;
+		unsigned long paddr;
+
+		rg->size = size;
+		rg->type = mi->type;
+		/*
+		 * size == 0 is a special case, for which we
+		 * don't check / adjust the screen parameters.
+		 * This isn't a problem since the plane can't
+		 * be reenabled unless its size is > 0.
+		 */
+		if (old_size != size && size) {
+			if (size) {
+				memcpy(new_var, &fbi->var, sizeof(*new_var));
+				r = set_fb_var(fbi, new_var);
+				if (r < 0)
+					goto out;
+			}
+		}
+
+		if (fbdev->ctrl->sync)
+			fbdev->ctrl->sync();
+		r = fbdev->ctrl->setup_mem(plane->idx, size, mi->type, &paddr);
+		if (r < 0) {
+			/* Revert changes. */
+			rg->size = old_size;
+			rg->type = old_type;
+			goto out;
+		}
+		rg->paddr = paddr;
+
+		if (old_size != size) {
+			if (size) {
+				memcpy(&fbi->var, new_var, sizeof(fbi->var));
+				set_fb_fix(fbi, 0);
+			} else {
+				/*
+				 * Set these explicitly to indicate that the
+				 * plane memory is dealloce'd, the other
+				 * screen parameters in var / fix are invalid.
+				 */
+				mutex_lock(&fbi->mm_lock);
+				fbi->fix.smem_start = 0;
+				fbi->fix.smem_len = 0;
+				mutex_unlock(&fbi->mm_lock);
+			}
+		}
+	}
+out:
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	struct omapfb_mem_region *rg;
+
+	rg = &fbdev->mem_desc.region[plane->idx];
+	memset(mi, 0, sizeof(*mi));
+	mi->size = rg->size;
+	mi->type = rg->type;
+
+	return 0;
+}
+
+static int omapfb_set_color_key(struct omapfb_device *fbdev,
+				struct omapfb_color_key *ck)
+{
+	int r;
+
+	if (!fbdev->ctrl->set_color_key)
+		return -ENODEV;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->set_color_key(ck);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_get_color_key(struct omapfb_device *fbdev,
+				struct omapfb_color_key *ck)
+{
+	int r;
+
+	if (!fbdev->ctrl->get_color_key)
+		return -ENODEV;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->get_color_key(ck);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM];
+static int notifier_inited;
+
+static void omapfb_init_notifier(void)
+{
+	int i;
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+		BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]);
+}
+
+int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
+				omapfb_notifier_callback_t callback,
+				void *callback_data)
+{
+	int r;
+
+	if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+		return -EINVAL;
+
+	if (!notifier_inited) {
+		omapfb_init_notifier();
+		notifier_inited = 1;
+	}
+
+	omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,
+					unsigned long, void *))callback;
+	omapfb_nb->data = callback_data;
+	r = blocking_notifier_chain_register(
+				&omapfb_client_list[omapfb_nb->plane_idx],
+				&omapfb_nb->nb);
+	if (r)
+		return r;
+	if (omapfb_dev != NULL &&
+	    omapfb_dev->ctrl && omapfb_dev->ctrl->bind_client) {
+		omapfb_dev->ctrl->bind_client(omapfb_nb);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omapfb_register_client);
+
+int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb)
+{
+	return blocking_notifier_chain_unregister(
+		&omapfb_client_list[omapfb_nb->plane_idx], &omapfb_nb->nb);
+}
+EXPORT_SYMBOL(omapfb_unregister_client);
+
+void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event)
+{
+	int i;
+
+	if (!notifier_inited)
+		/* no client registered yet */
+		return;
+
+	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+		blocking_notifier_call_chain(&omapfb_client_list[i], event,
+				    fbdev->fb_info[i]);
+}
+EXPORT_SYMBOL(omapfb_notify_clients);
+
+static int omapfb_set_update_mode(struct omapfb_device *fbdev,
+				   enum omapfb_update_mode mode)
+{
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->set_update_mode(mode);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
+{
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->get_update_mode();
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+static void omapfb_get_caps(struct omapfb_device *fbdev, int plane,
+				     struct omapfb_caps *caps)
+{
+	memset(caps, 0, sizeof(*caps));
+	fbdev->ctrl->get_caps(plane, caps);
+	caps->ctrl |= fbdev->panel->get_caps(fbdev->panel);
+}
+
+/* For lcd testing */
+void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
+{
+	omapfb_rqueue_lock(fbdev);
+	*(u16 *)fbdev->mem_desc.region[0].vaddr = pixval;
+	if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
+		struct omapfb_update_window win;
+
+		memset(&win, 0, sizeof(win));
+		win.width = 2;
+		win.height = 2;
+		win.out_width = 2;
+		win.out_height = 2;
+		fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL);
+	}
+	omapfb_rqueue_unlock(fbdev);
+}
+EXPORT_SYMBOL(omapfb_write_first_pixel);
+
+/*
+ * Ioctl interface. Part of the kernel mode frame buffer API is duplicated
+ * here to be accessible by user mode code.
+ */
+static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
+			unsigned long arg)
+{
+	struct omapfb_plane_struct *plane = fbi->par;
+	struct omapfb_device	*fbdev = plane->fbdev;
+	struct fb_ops		*ops = fbi->fbops;
+	union {
+		struct omapfb_update_window	update_window;
+		struct omapfb_plane_info	plane_info;
+		struct omapfb_mem_info		mem_info;
+		struct omapfb_color_key		color_key;
+		enum omapfb_update_mode		update_mode;
+		struct omapfb_caps		caps;
+		unsigned int		mirror;
+		int			plane_out;
+		int			enable_plane;
+	} p;
+	int r = 0;
+
+	BUG_ON(!ops);
+	switch (cmd) {
+	case OMAPFB_MIRROR:
+		if (get_user(p.mirror, (int __user *)arg))
+			r = -EFAULT;
+		else
+			omapfb_mirror(fbi, p.mirror);
+		break;
+	case OMAPFB_SYNC_GFX:
+		omapfb_sync(fbi);
+		break;
+	case OMAPFB_VSYNC:
+		break;
+	case OMAPFB_SET_UPDATE_MODE:
+		if (get_user(p.update_mode, (int __user *)arg))
+			r = -EFAULT;
+		else
+			r = omapfb_set_update_mode(fbdev, p.update_mode);
+		break;
+	case OMAPFB_GET_UPDATE_MODE:
+		p.update_mode = omapfb_get_update_mode(fbdev);
+		if (put_user(p.update_mode,
+					(enum omapfb_update_mode __user *)arg))
+			r = -EFAULT;
+		break;
+	case OMAPFB_UPDATE_WINDOW_OLD:
+		if (copy_from_user(&p.update_window, (void __user *)arg,
+				   sizeof(struct omapfb_update_window_old)))
+			r = -EFAULT;
+		else {
+			struct omapfb_update_window *u = &p.update_window;
+			u->out_x = u->x;
+			u->out_y = u->y;
+			u->out_width = u->width;
+			u->out_height = u->height;
+			memset(u->reserved, 0, sizeof(u->reserved));
+			r = omapfb_update_win(fbi, u);
+		}
+		break;
+	case OMAPFB_UPDATE_WINDOW:
+		if (copy_from_user(&p.update_window, (void __user *)arg,
+				   sizeof(p.update_window)))
+			r = -EFAULT;
+		else
+			r = omapfb_update_win(fbi, &p.update_window);
+		break;
+	case OMAPFB_SETUP_PLANE:
+		if (copy_from_user(&p.plane_info, (void __user *)arg,
+				   sizeof(p.plane_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_plane(fbi, &p.plane_info);
+		break;
+	case OMAPFB_QUERY_PLANE:
+		if ((r = omapfb_query_plane(fbi, &p.plane_info)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.plane_info,
+				   sizeof(p.plane_info)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_SETUP_MEM:
+		if (copy_from_user(&p.mem_info, (void __user *)arg,
+				   sizeof(p.mem_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_mem(fbi, &p.mem_info);
+		break;
+	case OMAPFB_QUERY_MEM:
+		if ((r = omapfb_query_mem(fbi, &p.mem_info)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.mem_info,
+				   sizeof(p.mem_info)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_SET_COLOR_KEY:
+		if (copy_from_user(&p.color_key, (void __user *)arg,
+				   sizeof(p.color_key)))
+			r = -EFAULT;
+		else
+			r = omapfb_set_color_key(fbdev, &p.color_key);
+		break;
+	case OMAPFB_GET_COLOR_KEY:
+		if ((r = omapfb_get_color_key(fbdev, &p.color_key)) < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.color_key,
+				 sizeof(p.color_key)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_GET_CAPS:
+		omapfb_get_caps(fbdev, plane->idx, &p.caps);
+		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+			r = -EFAULT;
+		break;
+	case OMAPFB_LCD_TEST:
+		{
+			int test_num;
+
+			if (get_user(test_num, (int __user *)arg)) {
+				r = -EFAULT;
+				break;
+			}
+			if (!fbdev->panel->run_test) {
+				r = -EINVAL;
+				break;
+			}
+			r = fbdev->panel->run_test(fbdev->panel, test_num);
+			break;
+		}
+	case OMAPFB_CTRL_TEST:
+		{
+			int test_num;
+
+			if (get_user(test_num, (int __user *)arg)) {
+				r = -EFAULT;
+				break;
+			}
+			if (!fbdev->ctrl->run_test) {
+				r = -EINVAL;
+				break;
+			}
+			r = fbdev->ctrl->run_test(test_num);
+			break;
+		}
+	default:
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct omapfb_plane_struct *plane = info->par;
+	struct omapfb_device *fbdev = plane->fbdev;
+	int r;
+
+	omapfb_rqueue_lock(fbdev);
+	r = fbdev->ctrl->mmap(info, vma);
+	omapfb_rqueue_unlock(fbdev);
+
+	return r;
+}
+
+/*
+ * Callback table for the frame buffer framework. Some of these pointers
+ * will be changed according to the current setting of fb_info->accel_flags.
+ */
+static struct fb_ops omapfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open        = omapfb_open,
+	.fb_release     = omapfb_release,
+	.fb_setcolreg	= omapfb_setcolreg,
+	.fb_setcmap	= omapfb_setcmap,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_blank       = omapfb_blank,
+	.fb_ioctl	= omapfb_ioctl,
+	.fb_check_var	= omapfb_check_var,
+	.fb_set_par	= omapfb_set_par,
+	.fb_rotate	= omapfb_rotate,
+	.fb_pan_display = omapfb_pan_display,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Sysfs interface
+ * ---------------------------------------------------------------------------
+ */
+/* omapfbX sysfs entries */
+static ssize_t omapfb_show_caps_num(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = dev_get_drvdata(dev);
+	int plane;
+	size_t size;
+	struct omapfb_caps caps;
+
+	plane = 0;
+	size = 0;
+	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+		omapfb_get_caps(fbdev, plane, &caps);
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+			"plane#%d %#010x %#010x %#010x\n",
+			plane, caps.ctrl, caps.plane_color, caps.wnd_color);
+		plane++;
+	}
+	return size;
+}
+
+static ssize_t omapfb_show_caps_text(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = dev_get_drvdata(dev);
+	int i;
+	struct omapfb_caps caps;
+	int plane;
+	size_t size;
+
+	plane = 0;
+	size = 0;
+	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+		omapfb_get_caps(fbdev, plane, &caps);
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 "plane#%d:\n", plane);
+		for (i = 0; i < ARRAY_SIZE(ctrl_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (ctrl_caps[i].flag & caps.ctrl)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					" %s\n", ctrl_caps[i].name);
+		}
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 " plane colors:\n");
+		for (i = 0; i < ARRAY_SIZE(color_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (color_caps[i].flag & caps.plane_color)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					"  %s\n", color_caps[i].name);
+		}
+		size += snprintf(&buf[size], PAGE_SIZE - size,
+				 " window colors:\n");
+		for (i = 0; i < ARRAY_SIZE(color_caps) &&
+		     size < PAGE_SIZE; i++) {
+			if (color_caps[i].flag & caps.wnd_color)
+				size += snprintf(&buf[size], PAGE_SIZE - size,
+					"  %s\n", color_caps[i].name);
+		}
+
+		plane++;
+	}
+	return size;
+}
+
+static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
+static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
+
+/* panel sysfs entries */
+static ssize_t omapfb_show_panel_name(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
+}
+
+static ssize_t omapfb_show_bklight_level(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct omapfb_device *fbdev = dev_get_drvdata(dev);
+	int r;
+
+	if (fbdev->panel->get_bklight_level) {
+		r = snprintf(buf, PAGE_SIZE, "%d\n",
+			     fbdev->panel->get_bklight_level(fbdev->panel));
+	} else
+		r = -ENODEV;
+	return r;
+}
+
+static ssize_t omapfb_store_bklight_level(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t size)
+{
+	struct omapfb_device *fbdev = dev_get_drvdata(dev);
+	int r;
+
+	if (fbdev->panel->set_bklight_level) {
+		unsigned int level;
+
+		if (sscanf(buf, "%10d", &level) == 1) {
+			r = fbdev->panel->set_bklight_level(fbdev->panel,
+							    level);
+		} else
+			r = -EINVAL;
+	} else
+		r = -ENODEV;
+	return r ? r : size;
+}
+
+static ssize_t omapfb_show_bklight_max(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = dev_get_drvdata(dev);
+	int r;
+
+	if (fbdev->panel->get_bklight_level) {
+		r = snprintf(buf, PAGE_SIZE, "%d\n",
+			     fbdev->panel->get_bklight_max(fbdev->panel));
+	} else
+		r = -ENODEV;
+	return r;
+}
+
+static struct device_attribute dev_attr_panel_name =
+	__ATTR(name, 0444, omapfb_show_panel_name, NULL);
+static DEVICE_ATTR(backlight_level, 0664,
+		   omapfb_show_bklight_level, omapfb_store_bklight_level);
+static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
+
+static struct attribute *panel_attrs[] = {
+	&dev_attr_panel_name.attr,
+	&dev_attr_backlight_level.attr,
+	&dev_attr_backlight_max.attr,
+	NULL,
+};
+
+static struct attribute_group panel_attr_grp = {
+	.name  = "panel",
+	.attrs = panel_attrs,
+};
+
+/* ctrl sysfs entries */
+static ssize_t omapfb_show_ctrl_name(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct omapfb_device *fbdev = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
+}
+
+static struct device_attribute dev_attr_ctrl_name =
+	__ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
+
+static struct attribute *ctrl_attrs[] = {
+	&dev_attr_ctrl_name.attr,
+	NULL,
+};
+
+static struct attribute_group ctrl_attr_grp = {
+	.name  = "ctrl",
+	.attrs = ctrl_attrs,
+};
+
+static int omapfb_register_sysfs(struct omapfb_device *fbdev)
+{
+	int r;
+
+	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
+		goto fail0;
+
+	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
+		goto fail1;
+
+	if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
+		goto fail2;
+
+	if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
+		goto fail3;
+
+	return 0;
+fail3:
+	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+fail2:
+	device_remove_file(fbdev->dev, &dev_attr_caps_text);
+fail1:
+	device_remove_file(fbdev->dev, &dev_attr_caps_num);
+fail0:
+	dev_err(fbdev->dev, "unable to register sysfs interface\n");
+	return r;
+}
+
+static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
+{
+	sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
+	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+	device_remove_file(fbdev->dev, &dev_attr_caps_num);
+	device_remove_file(fbdev->dev, &dev_attr_caps_text);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LDM callbacks
+ * ---------------------------------------------------------------------------
+ */
+/* Initialize system fb_info object and set the default video mode.
+ * The frame buffer memory already allocated by lcddma_init
+ */
+static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
+{
+	struct fb_var_screeninfo	*var = &info->var;
+	struct fb_fix_screeninfo	*fix = &info->fix;
+	int				r = 0;
+
+	info->fbops = &omapfb_ops;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
+
+	info->pseudo_palette = fbdev->pseudo_palette;
+
+	var->accel_flags  = def_accel ? FB_ACCELF_TEXT : 0;
+	var->xres = def_vxres;
+	var->yres = def_vyres;
+	var->xres_virtual = def_vxres;
+	var->yres_virtual = def_vyres;
+	var->rotate	  = def_rotate;
+	var->bits_per_pixel = fbdev->panel->bpp;
+
+	set_fb_var(info, var);
+	set_fb_fix(info, 1);
+
+	r = fb_alloc_cmap(&info->cmap, 16, 0);
+	if (r != 0)
+		dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
+	return r;
+}
+
+/* Release the fb_info object */
+static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi)
+{
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+static void planes_cleanup(struct omapfb_device *fbdev)
+{
+	int i;
+
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		if (fbdev->fb_info[i] == NULL)
+			break;
+		fbinfo_cleanup(fbdev, fbdev->fb_info[i]);
+		framebuffer_release(fbdev->fb_info[i]);
+	}
+}
+
+static int planes_init(struct omapfb_device *fbdev)
+{
+	struct fb_info *fbi;
+	int i;
+	int r;
+
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		struct omapfb_plane_struct *plane;
+		fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct),
+					fbdev->dev);
+		if (fbi == NULL) {
+			dev_err(fbdev->dev,
+				"unable to allocate memory for plane info\n");
+			planes_cleanup(fbdev);
+			return -ENOMEM;
+		}
+		plane = fbi->par;
+		plane->idx = i;
+		plane->fbdev = fbdev;
+		plane->info.mirror = def_mirror;
+		fbdev->fb_info[i] = fbi;
+
+		if ((r = fbinfo_init(fbdev, fbi)) < 0) {
+			framebuffer_release(fbi);
+			planes_cleanup(fbdev);
+			return r;
+		}
+		plane->info.out_width = fbi->var.xres;
+		plane->info.out_height = fbi->var.yres;
+	}
+	return 0;
+}
+
+/*
+ * Free driver resources. Can be called to rollback an aborted initialization
+ * sequence.
+ */
+static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
+{
+	int i;
+
+	switch (state) {
+	case OMAPFB_ACTIVE:
+		for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
+			unregister_framebuffer(fbdev->fb_info[i]);
+	case 7:
+		omapfb_unregister_sysfs(fbdev);
+	case 6:
+		fbdev->panel->disable(fbdev->panel);
+	case 5:
+		omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+	case 4:
+		planes_cleanup(fbdev);
+	case 3:
+		ctrl_cleanup(fbdev);
+	case 2:
+		fbdev->panel->cleanup(fbdev->panel);
+	case 1:
+		dev_set_drvdata(fbdev->dev, NULL);
+		kfree(fbdev);
+	case 0:
+		/* nothing to free */
+		break;
+	default:
+		BUG();
+	}
+}
+
+static int omapfb_find_ctrl(struct omapfb_device *fbdev)
+{
+	struct omapfb_platform_data *conf;
+	char name[17];
+	int i;
+
+	conf = dev_get_platdata(fbdev->dev);
+
+	fbdev->ctrl = NULL;
+
+	strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1);
+	name[sizeof(name) - 1] = '\0';
+
+	if (strcmp(name, "internal") == 0) {
+		fbdev->ctrl = fbdev->int_ctrl;
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
+		dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name);
+		if (strcmp(ctrls[i]->name, name) == 0) {
+			fbdev->ctrl = ctrls[i];
+			break;
+		}
+	}
+
+	if (fbdev->ctrl == NULL) {
+		dev_dbg(fbdev->dev, "ctrl %s not supported\n", name);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void check_required_callbacks(struct omapfb_device *fbdev)
+{
+#define _C(x) (fbdev->ctrl->x != NULL)
+#define _P(x) (fbdev->panel->x != NULL)
+	BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL);
+	BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
+		 _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) &&
+		 _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
+		 _P(get_caps)));
+#undef _P
+#undef _C
+}
+
+/*
+ * Called by LDM binding to probe and attach a new device.
+ * Initialization sequence:
+ *   1. allocate system omapfb_device structure
+ *   2. select controller type according to platform configuration
+ *      init LCD panel
+ *   3. init LCD controller and LCD DMA
+ *   4. init system fb_info structure for all planes
+ *   5. setup video mode for first plane and enable it
+ *   6. enable LCD panel
+ *   7. register sysfs attributes
+ *   OMAPFB_ACTIVE: register system fb_info structure for all planes
+ */
+static int omapfb_do_probe(struct platform_device *pdev,
+				struct lcd_panel *panel)
+{
+	struct omapfb_device	*fbdev = NULL;
+	int			init_state;
+	unsigned long		phz, hhz, vhz;
+	unsigned long		vram;
+	int			i;
+	int			r = 0;
+
+	init_state = 0;
+
+	if (pdev->num_resources != 0) {
+		dev_err(&pdev->dev, "probed for an unknown device\n");
+		r = -ENODEV;
+		goto cleanup;
+	}
+
+	if (dev_get_platdata(&pdev->dev) == NULL) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		r = -ENOENT;
+		goto cleanup;
+	}
+
+	fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL);
+	if (fbdev == NULL) {
+		dev_err(&pdev->dev,
+			"unable to allocate memory for device info\n");
+		r = -ENOMEM;
+		goto cleanup;
+	}
+	init_state++;
+
+	fbdev->dev = &pdev->dev;
+	fbdev->panel = panel;
+	fbdev->dssdev = &omapdss_device;
+	platform_set_drvdata(pdev, fbdev);
+
+	mutex_init(&fbdev->rqueue_mutex);
+
+	fbdev->int_ctrl = &omap1_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+	fbdev->ext_if = &omap1_ext_if;
+#endif
+	if (omapfb_find_ctrl(fbdev) < 0) {
+		dev_err(fbdev->dev,
+			"LCD controller not found, board not supported\n");
+		r = -ENODEV;
+		goto cleanup;
+	}
+
+	r = fbdev->panel->init(fbdev->panel, fbdev);
+	if (r)
+		goto cleanup;
+
+	pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
+
+	def_vxres = def_vxres ? def_vxres : fbdev->panel->x_res;
+	def_vyres = def_vyres ? def_vyres : fbdev->panel->y_res;
+
+	init_state++;
+
+	r = ctrl_init(fbdev);
+	if (r)
+		goto cleanup;
+	if (fbdev->ctrl->mmap != NULL)
+		omapfb_ops.fb_mmap = omapfb_mmap;
+	init_state++;
+
+	check_required_callbacks(fbdev);
+
+	r = planes_init(fbdev);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+#ifdef CONFIG_FB_OMAP_DMA_TUNE
+	/* Set DMA priority for EMIFF access to highest */
+	omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
+#endif
+
+	r = ctrl_change_mode(fbdev->fb_info[0]);
+	if (r) {
+		dev_err(fbdev->dev, "mode setting failed\n");
+		goto cleanup;
+	}
+
+	/* GFX plane is enabled by default */
+	r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+	if (r)
+		goto cleanup;
+
+	omapfb_set_update_mode(fbdev, manual_update ?
+				   OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
+	init_state++;
+
+	r = fbdev->panel->enable(fbdev->panel);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+	r = omapfb_register_sysfs(fbdev);
+	if (r)
+		goto cleanup;
+	init_state++;
+
+	vram = 0;
+	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+		r = register_framebuffer(fbdev->fb_info[i]);
+		if (r != 0) {
+			dev_err(fbdev->dev,
+				"registering framebuffer %d failed\n", i);
+			goto cleanup;
+		}
+		vram += fbdev->mem_desc.region[i].size;
+	}
+
+	fbdev->state = OMAPFB_ACTIVE;
+
+	panel = fbdev->panel;
+	phz = panel->pixel_clock * 1000;
+	hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
+	vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
+
+	omapfb_dev = fbdev;
+
+	pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n",
+			vram, fbdev->mem_desc.region_cnt);
+	pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz "
+			"vfreq %lu.%lu Hz\n",
+			phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
+
+	return 0;
+
+cleanup:
+	omapfb_free_resources(fbdev, init_state);
+
+	return r;
+}
+
+static int omapfb_probe(struct platform_device *pdev)
+{
+	int r;
+
+	BUG_ON(fbdev_pdev != NULL);
+
+	r = platform_device_register(&omapdss_device);
+	if (r) {
+		dev_err(&pdev->dev, "can't register omapdss device\n");
+		return r;
+	}
+
+	/* Delay actual initialization until the LCD is registered */
+	fbdev_pdev = pdev;
+	if (fbdev_panel != NULL)
+		omapfb_do_probe(fbdev_pdev, fbdev_panel);
+	return 0;
+}
+
+void omapfb_register_panel(struct lcd_panel *panel)
+{
+	BUG_ON(fbdev_panel != NULL);
+
+	fbdev_panel = panel;
+	if (fbdev_pdev != NULL)
+		omapfb_do_probe(fbdev_pdev, fbdev_panel);
+}
+
+/* Called when the device is being detached from the driver */
+static int omapfb_remove(struct platform_device *pdev)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+	enum omapfb_state saved_state = fbdev->state;
+
+	/* FIXME: wait till completion of pending events */
+
+	fbdev->state = OMAPFB_DISABLED;
+	omapfb_free_resources(fbdev, saved_state);
+
+	platform_device_unregister(&omapdss_device);
+	fbdev->dssdev = NULL;
+
+	return 0;
+}
+
+/* PM suspend */
+static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+	if (fbdev != NULL)
+		omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]);
+	return 0;
+}
+
+/* PM resume */
+static int omapfb_resume(struct platform_device *pdev)
+{
+	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+	if (fbdev != NULL)
+		omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]);
+	return 0;
+}
+
+static struct platform_driver omapfb_driver = {
+	.probe		= omapfb_probe,
+	.remove		= omapfb_remove,
+	.suspend	= omapfb_suspend,
+	.resume		= omapfb_resume,
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+#ifndef MODULE
+
+/* Process kernel command line parameters */
+static int __init omapfb_setup(char *options)
+{
+	char *this_opt = NULL;
+	int r = 0;
+
+	pr_debug("omapfb: options %s\n", options);
+
+	if (!options || !*options)
+		return 0;
+
+	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "accel", 5))
+			def_accel = 1;
+		else if (!strncmp(this_opt, "vram:", 5)) {
+			char *suffix;
+			unsigned long vram;
+			vram = (simple_strtoul(this_opt + 5, &suffix, 0));
+			switch (suffix[0]) {
+			case '\0':
+				break;
+			case 'm':
+			case 'M':
+				vram *= 1024;
+				/* Fall through */
+			case 'k':
+			case 'K':
+				vram *= 1024;
+				break;
+			default:
+				pr_debug("omapfb: invalid vram suffix %c\n",
+					 suffix[0]);
+				r = -1;
+			}
+			def_vram[def_vram_cnt++] = vram;
+		}
+		else if (!strncmp(this_opt, "vxres:", 6))
+			def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "vyres:", 6))
+			def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "rotate:", 7))
+			def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
+		else if (!strncmp(this_opt, "mirror:", 7))
+			def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
+		else if (!strncmp(this_opt, "manual_update", 13))
+			manual_update = 1;
+		else {
+			pr_debug("omapfb: invalid option\n");
+			r = -1;
+		}
+	}
+
+	return r;
+}
+
+#endif
+
+/* Register both the driver and the device */
+static int __init omapfb_init(void)
+{
+#ifndef MODULE
+	char *option;
+
+	if (fb_get_options("omapfb", &option))
+		return -ENODEV;
+	omapfb_setup(option);
+#endif
+	/* Register the driver with LDM */
+	if (platform_driver_register(&omapfb_driver)) {
+		pr_debug("failed to register omapfb driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit omapfb_cleanup(void)
+{
+	platform_driver_unregister(&omapfb_driver);
+}
+
+module_param_named(accel, def_accel, uint, 0664);
+module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664);
+module_param_named(vxres, def_vxres, long, 0664);
+module_param_named(vyres, def_vyres, long, 0664);
+module_param_named(rotate, def_rotate, uint, 0664);
+module_param_named(mirror, def_mirror, uint, 0664);
+module_param_named(manual_update, manual_update, bool, 0664);
+
+module_init(omapfb_init);
+module_exit(omapfb_cleanup);
+
+MODULE_DESCRIPTION("TI OMAP framebuffer driver");
+MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c
new file mode 100644
index 000000000000..d4e7684e7045
--- /dev/null
+++ b/drivers/video/fbdev/omap/sossi.c
@@ -0,0 +1,693 @@
+/*
+ * OMAP1 Special OptimiSed Screen Interface support
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#include <linux/omap-dma.h>
+
+#include "omapfb.h"
+#include "lcdc.h"
+
+#define MODULE_NAME		"omapfb-sossi"
+
+#define OMAP_SOSSI_BASE         0xfffbac00
+#define SOSSI_ID_REG		0x00
+#define SOSSI_INIT1_REG		0x04
+#define SOSSI_INIT2_REG		0x08
+#define SOSSI_INIT3_REG		0x0c
+#define SOSSI_FIFO_REG		0x10
+#define SOSSI_REOTABLE_REG	0x14
+#define SOSSI_TEARING_REG	0x18
+#define SOSSI_INIT1B_REG	0x1c
+#define SOSSI_FIFOB_REG		0x20
+
+#define DMA_GSCR          0xfffedc04
+#define DMA_LCD_CCR       0xfffee3c2
+#define DMA_LCD_CTRL      0xfffee3c4
+#define DMA_LCD_LCH_CTRL  0xfffee3ea
+
+#define CONF_SOSSI_RESET_R      (1 << 23)
+
+#define RD_ACCESS		0
+#define WR_ACCESS		1
+
+#define SOSSI_MAX_XMIT_BYTES	(512 * 1024)
+
+static struct {
+	void __iomem	*base;
+	struct clk	*fck;
+	unsigned long	fck_hz;
+	spinlock_t	lock;
+	int		bus_pick_count;
+	int		bus_pick_width;
+	int		tearsync_mode;
+	int		tearsync_line;
+	void		(*lcdc_callback)(void *data);
+	void		*lcdc_callback_data;
+	int		vsync_dma_pending;
+	/* timing for read and write access */
+	int		clk_div;
+	u8		clk_tw0[2];
+	u8		clk_tw1[2];
+	/*
+	 * if last_access is the same as current we don't have to change
+	 * the timings
+	 */
+	int		last_access;
+
+	struct omapfb_device	*fbdev;
+} sossi;
+
+static inline u32 sossi_read_reg(int reg)
+{
+	return readl(sossi.base + reg);
+}
+
+static inline u16 sossi_read_reg16(int reg)
+{
+	return readw(sossi.base + reg);
+}
+
+static inline u8 sossi_read_reg8(int reg)
+{
+	return readb(sossi.base + reg);
+}
+
+static inline void sossi_write_reg(int reg, u32 value)
+{
+	writel(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg16(int reg, u16 value)
+{
+	writew(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg8(int reg, u8 value)
+{
+	writeb(value, sossi.base + reg);
+}
+
+static void sossi_set_bits(int reg, u32 bits)
+{
+	sossi_write_reg(reg, sossi_read_reg(reg) | bits);
+}
+
+static void sossi_clear_bits(int reg, u32 bits)
+{
+	sossi_write_reg(reg, sossi_read_reg(reg) & ~bits);
+}
+
+#define HZ_TO_PS(x)	(1000000000 / (x / 1000))
+
+static u32 ps_to_sossi_ticks(u32 ps, int div)
+{
+	u32 clk_period = HZ_TO_PS(sossi.fck_hz) * div;
+	return (clk_period + ps - 1) / clk_period;
+}
+
+static int calc_rd_timings(struct extif_timings *t)
+{
+	u32 tw0, tw1;
+	int reon, reoff, recyc, actim;
+	int div = t->clk_div;
+
+	/*
+	 * Make sure that after conversion it still holds that:
+	 * reoff > reon, recyc >= reoff, actim > reon
+	 */
+	reon = ps_to_sossi_ticks(t->re_on_time, div);
+	/* reon will be exactly one sossi tick */
+	if (reon > 1)
+		return -1;
+
+	reoff = ps_to_sossi_ticks(t->re_off_time, div);
+
+	if (reoff <= reon)
+		reoff = reon + 1;
+
+	tw0 = reoff - reon;
+	if (tw0 > 0x10)
+		return -1;
+
+	recyc = ps_to_sossi_ticks(t->re_cycle_time, div);
+	if (recyc <= reoff)
+		recyc = reoff + 1;
+
+	tw1 = recyc - tw0;
+	/* values less then 3 result in the SOSSI block resetting itself */
+	if (tw1 < 3)
+		tw1 = 3;
+	if (tw1 > 0x40)
+		return -1;
+
+	actim = ps_to_sossi_ticks(t->access_time, div);
+	if (actim < reoff)
+		actim++;
+	/*
+	 * access time (data hold time) will be exactly one sossi
+	 * tick
+	 */
+	if (actim - reoff > 1)
+		return -1;
+
+	t->tim[0] = tw0 - 1;
+	t->tim[1] = tw1 - 1;
+
+	return 0;
+}
+
+static int calc_wr_timings(struct extif_timings *t)
+{
+	u32 tw0, tw1;
+	int weon, weoff, wecyc;
+	int div = t->clk_div;
+
+	/*
+	 * Make sure that after conversion it still holds that:
+	 * weoff > weon, wecyc >= weoff
+	 */
+	weon = ps_to_sossi_ticks(t->we_on_time, div);
+	/* weon will be exactly one sossi tick */
+	if (weon > 1)
+		return -1;
+
+	weoff = ps_to_sossi_ticks(t->we_off_time, div);
+	if (weoff <= weon)
+		weoff = weon + 1;
+	tw0 = weoff - weon;
+	if (tw0 > 0x10)
+		return -1;
+
+	wecyc = ps_to_sossi_ticks(t->we_cycle_time, div);
+	if (wecyc <= weoff)
+		wecyc = weoff + 1;
+
+	tw1 = wecyc - tw0;
+	/* values less then 3 result in the SOSSI block resetting itself */
+	if (tw1 < 3)
+		tw1 = 3;
+	if (tw1 > 0x40)
+		return -1;
+
+	t->tim[2] = tw0 - 1;
+	t->tim[3] = tw1 - 1;
+
+	return 0;
+}
+
+static void _set_timing(int div, int tw0, int tw1)
+{
+	u32 l;
+
+#ifdef VERBOSE
+	dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n",
+		 tw0 + 1, tw1 + 1, div);
+#endif
+
+	clk_set_rate(sossi.fck, sossi.fck_hz / div);
+	clk_enable(sossi.fck);
+	l = sossi_read_reg(SOSSI_INIT1_REG);
+	l &= ~((0x0f << 20) | (0x3f << 24));
+	l |= (tw0 << 20) | (tw1 << 24);
+	sossi_write_reg(SOSSI_INIT1_REG, l);
+	clk_disable(sossi.fck);
+}
+
+static void _set_bits_per_cycle(int bus_pick_count, int bus_pick_width)
+{
+	u32 l;
+
+	l = sossi_read_reg(SOSSI_INIT3_REG);
+	l &= ~0x3ff;
+	l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
+	sossi_write_reg(SOSSI_INIT3_REG, l);
+}
+
+static void _set_tearsync_mode(int mode, unsigned line)
+{
+	u32 l;
+
+	l = sossi_read_reg(SOSSI_TEARING_REG);
+	l &= ~(((1 << 11) - 1) << 15);
+	l |= line << 15;
+	l &= ~(0x3 << 26);
+	l |= mode << 26;
+	sossi_write_reg(SOSSI_TEARING_REG, l);
+	if (mode)
+		sossi_set_bits(SOSSI_INIT2_REG, 1 << 6);	/* TE logic */
+	else
+		sossi_clear_bits(SOSSI_INIT2_REG, 1 << 6);
+}
+
+static inline void set_timing(int access)
+{
+	if (access != sossi.last_access) {
+		sossi.last_access = access;
+		_set_timing(sossi.clk_div,
+			    sossi.clk_tw0[access], sossi.clk_tw1[access]);
+	}
+}
+
+static void sossi_start_transfer(void)
+{
+	/* WE */
+	sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4);
+	/* CS active low */
+	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void sossi_stop_transfer(void)
+{
+	/* WE */
+	sossi_set_bits(SOSSI_INIT2_REG, 1 << 4);
+	/* CS active low */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void wait_end_of_write(void)
+{
+	/* Before reading we must check if some writings are going on */
+	while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3)));
+}
+
+static void send_data(const void *data, unsigned int len)
+{
+	while (len >= 4) {
+		sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data);
+		len -= 4;
+		data += 4;
+	}
+	while (len >= 2) {
+		sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data);
+		len -= 2;
+		data += 2;
+	}
+	while (len) {
+		sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data);
+		len--;
+		data++;
+	}
+}
+
+static void set_cycles(unsigned int len)
+{
+	unsigned long nr_cycles = len / (sossi.bus_pick_width / 8);
+
+	BUG_ON((nr_cycles - 1) & ~0x3ffff);
+
+	sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff);
+	sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
+}
+
+static int sossi_convert_timings(struct extif_timings *t)
+{
+	int r = 0;
+	int div = t->clk_div;
+
+	t->converted = 0;
+
+	if (div <= 0 || div > 8)
+		return -1;
+
+	/* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */
+	if ((r = calc_rd_timings(t)) < 0)
+		return r;
+
+	if ((r = calc_wr_timings(t)) < 0)
+		return r;
+
+	t->tim[4] = div;
+
+	t->converted = 1;
+
+	return 0;
+}
+
+static void sossi_set_timings(const struct extif_timings *t)
+{
+	BUG_ON(!t->converted);
+
+	sossi.clk_tw0[RD_ACCESS] = t->tim[0];
+	sossi.clk_tw1[RD_ACCESS] = t->tim[1];
+
+	sossi.clk_tw0[WR_ACCESS] = t->tim[2];
+	sossi.clk_tw1[WR_ACCESS] = t->tim[3];
+
+	sossi.clk_div = t->tim[4];
+}
+
+static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+	*clk_period = HZ_TO_PS(sossi.fck_hz);
+	*max_clk_div = 8;
+}
+
+static void sossi_set_bits_per_cycle(int bpc)
+{
+	int bus_pick_count, bus_pick_width;
+
+	/*
+	 * We set explicitly the the bus_pick_count as well, although
+	 * with remapping/reordering disabled it will be calculated by HW
+	 * as (32 / bus_pick_width).
+	 */
+	switch (bpc) {
+	case 8:
+		bus_pick_count = 4;
+		bus_pick_width = 8;
+		break;
+	case 16:
+		bus_pick_count = 2;
+		bus_pick_width = 16;
+		break;
+	default:
+		BUG();
+		return;
+	}
+	sossi.bus_pick_width = bus_pick_width;
+	sossi.bus_pick_count = bus_pick_count;
+}
+
+static int sossi_setup_tearsync(unsigned pin_cnt,
+				unsigned hs_pulse_time, unsigned vs_pulse_time,
+				int hs_pol_inv, int vs_pol_inv, int div)
+{
+	int hs, vs;
+	u32 l;
+
+	if (pin_cnt != 1 || div < 1 || div > 8)
+		return -EINVAL;
+
+	hs = ps_to_sossi_ticks(hs_pulse_time, div);
+	vs = ps_to_sossi_ticks(vs_pulse_time, div);
+	if (vs < 8 || vs <= hs || vs >= (1 << 12))
+		return -EDOM;
+	vs /= 8;
+	vs--;
+	if (hs > 8)
+		hs = 8;
+	if (hs)
+		hs--;
+
+	dev_dbg(sossi.fbdev->dev,
+		"setup_tearsync: hs %d vs %d hs_inv %d vs_inv %d\n",
+		hs, vs, hs_pol_inv, vs_pol_inv);
+
+	clk_enable(sossi.fck);
+	l = sossi_read_reg(SOSSI_TEARING_REG);
+	l &= ~((1 << 15) - 1);
+	l |= vs << 3;
+	l |= hs;
+	if (hs_pol_inv)
+		l |= 1 << 29;
+	else
+		l &= ~(1 << 29);
+	if (vs_pol_inv)
+		l |= 1 << 28;
+	else
+		l &= ~(1 << 28);
+	sossi_write_reg(SOSSI_TEARING_REG, l);
+	clk_disable(sossi.fck);
+
+	return 0;
+}
+
+static int sossi_enable_tearsync(int enable, unsigned line)
+{
+	int mode;
+
+	dev_dbg(sossi.fbdev->dev, "tearsync %d line %d\n", enable, line);
+	if (line >= 1 << 11)
+		return -EINVAL;
+	if (enable) {
+		if (line)
+			mode = 2;		/* HS or VS */
+		else
+			mode = 3;		/* VS only */
+	} else
+		mode = 0;
+	sossi.tearsync_line = line;
+	sossi.tearsync_mode = mode;
+
+	return 0;
+}
+
+static void sossi_write_command(const void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	send_data(data, len);
+	sossi_stop_transfer();
+	wait_end_of_write();
+	clk_disable(sossi.fck);
+}
+
+static void sossi_write_data(const void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	send_data(data, len);
+	sossi_stop_transfer();
+	wait_end_of_write();
+	clk_disable(sossi.fck);
+}
+
+static void sossi_transfer_area(int width, int height,
+				void (callback)(void *data), void *data)
+{
+	BUG_ON(callback == NULL);
+
+	sossi.lcdc_callback = callback;
+	sossi.lcdc_callback_data = data;
+
+	clk_enable(sossi.fck);
+	set_timing(WR_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	_set_tearsync_mode(sossi.tearsync_mode, sossi.tearsync_line);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(width * height * sossi.bus_pick_width / 8);
+
+	sossi_start_transfer();
+	if (sossi.tearsync_mode) {
+		/*
+		 * Wait for the sync signal and start the transfer only
+		 * then. We can't seem to be able to use HW sync DMA for
+		 * this since LCD DMA shows huge latencies, as if it
+		 * would ignore some of the DMA requests from SoSSI.
+		 */
+		unsigned long flags;
+
+		spin_lock_irqsave(&sossi.lock, flags);
+		sossi.vsync_dma_pending++;
+		spin_unlock_irqrestore(&sossi.lock, flags);
+	} else
+		/* Just start the transfer right away. */
+		omap_enable_lcd_dma();
+}
+
+static void sossi_dma_callback(void *data)
+{
+	omap_stop_lcd_dma();
+	sossi_stop_transfer();
+	clk_disable(sossi.fck);
+	sossi.lcdc_callback(sossi.lcdc_callback_data);
+}
+
+static void sossi_read_data(void *data, unsigned int len)
+{
+	clk_enable(sossi.fck);
+	set_timing(RD_ACCESS);
+	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+	/* CMD#/DATA */
+	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+	set_cycles(len);
+	sossi_start_transfer();
+	while (len >= 4) {
+		*(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG);
+		len -= 4;
+		data += 4;
+	}
+	while (len >= 2) {
+		*(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG);
+		len -= 2;
+		data += 2;
+	}
+	while (len) {
+		*(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG);
+		len--;
+		data++;
+	}
+	sossi_stop_transfer();
+	clk_disable(sossi.fck);
+}
+
+static irqreturn_t sossi_match_irq(int irq, void *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sossi.lock, flags);
+	if (sossi.vsync_dma_pending) {
+		sossi.vsync_dma_pending--;
+		omap_enable_lcd_dma();
+	}
+	spin_unlock_irqrestore(&sossi.lock, flags);
+	return IRQ_HANDLED;
+}
+
+static int sossi_init(struct omapfb_device *fbdev)
+{
+	u32 l, k;
+	struct clk *fck;
+	struct clk *dpll1out_ck;
+	int r;
+
+	sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K);
+	if (!sossi.base) {
+		dev_err(fbdev->dev, "can't ioremap SoSSI\n");
+		return -ENOMEM;
+	}
+
+	sossi.fbdev = fbdev;
+	spin_lock_init(&sossi.lock);
+
+	dpll1out_ck = clk_get(fbdev->dev, "ck_dpll1out");
+	if (IS_ERR(dpll1out_ck)) {
+		dev_err(fbdev->dev, "can't get DPLL1OUT clock\n");
+		return PTR_ERR(dpll1out_ck);
+	}
+	/*
+	 * We need the parent clock rate, which we might divide further
+	 * depending on the timing requirements of the controller. See
+	 * _set_timings.
+	 */
+	sossi.fck_hz = clk_get_rate(dpll1out_ck);
+	clk_put(dpll1out_ck);
+
+	fck = clk_get(fbdev->dev, "ck_sossi");
+	if (IS_ERR(fck)) {
+		dev_err(fbdev->dev, "can't get SoSSI functional clock\n");
+		return PTR_ERR(fck);
+	}
+	sossi.fck = fck;
+
+	/* Reset and enable the SoSSI module */
+	l = omap_readl(MOD_CONF_CTRL_1);
+	l |= CONF_SOSSI_RESET_R;
+	omap_writel(l, MOD_CONF_CTRL_1);
+	l &= ~CONF_SOSSI_RESET_R;
+	omap_writel(l, MOD_CONF_CTRL_1);
+
+	clk_enable(sossi.fck);
+	l = omap_readl(ARM_IDLECT2);
+	l &= ~(1 << 8);			/* DMACK_REQ */
+	omap_writel(l, ARM_IDLECT2);
+
+	l = sossi_read_reg(SOSSI_INIT2_REG);
+	/* Enable and reset the SoSSI block */
+	l |= (1 << 0) | (1 << 1);
+	sossi_write_reg(SOSSI_INIT2_REG, l);
+	/* Take SoSSI out of reset */
+	l &= ~(1 << 1);
+	sossi_write_reg(SOSSI_INIT2_REG, l);
+
+	sossi_write_reg(SOSSI_ID_REG, 0);
+	l = sossi_read_reg(SOSSI_ID_REG);
+	k = sossi_read_reg(SOSSI_ID_REG);
+
+	if (l != 0x55555555 || k != 0xaaaaaaaa) {
+		dev_err(fbdev->dev,
+			"invalid SoSSI sync pattern: %08x, %08x\n", l, k);
+		r = -ENODEV;
+		goto err;
+	}
+
+	if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) {
+		dev_err(fbdev->dev, "can't get LCDC IRQ\n");
+		r = -ENODEV;
+		goto err;
+	}
+
+	l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
+	l = sossi_read_reg(SOSSI_ID_REG);
+	dev_info(fbdev->dev, "SoSSI version %d.%d initialized\n",
+		l >> 16, l & 0xffff);
+
+	l = sossi_read_reg(SOSSI_INIT1_REG);
+	l |= (1 << 19); /* DMA_MODE */
+	l &= ~(1 << 31); /* REORDERING */
+	sossi_write_reg(SOSSI_INIT1_REG, l);
+
+	if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
+			     IRQ_TYPE_EDGE_FALLING,
+	     "sossi_match", sossi.fbdev->dev)) < 0) {
+		dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
+		goto err;
+	}
+
+	clk_disable(sossi.fck);
+	return 0;
+
+err:
+	clk_disable(sossi.fck);
+	clk_put(sossi.fck);
+	return r;
+}
+
+static void sossi_cleanup(void)
+{
+	omap_lcdc_free_dma_callback();
+	clk_put(sossi.fck);
+	iounmap(sossi.base);
+}
+
+struct lcd_ctrl_extif omap1_ext_if = {
+	.init			= sossi_init,
+	.cleanup		= sossi_cleanup,
+	.get_clk_info		= sossi_get_clk_info,
+	.convert_timings	= sossi_convert_timings,
+	.set_timings		= sossi_set_timings,
+	.set_bits_per_cycle	= sossi_set_bits_per_cycle,
+	.setup_tearsync		= sossi_setup_tearsync,
+	.enable_tearsync	= sossi_enable_tearsync,
+	.write_command		= sossi_write_command,
+	.read_data		= sossi_read_data,
+	.write_data		= sossi_write_data,
+	.transfer_area		= sossi_transfer_area,
+
+	.max_transmit_size	= SOSSI_MAX_XMIT_BYTES,
+};
+
diff --git a/drivers/video/fbdev/omap2/Kconfig b/drivers/video/fbdev/omap2/Kconfig
new file mode 100644
index 000000000000..c22955d2de9a
--- /dev/null
+++ b/drivers/video/fbdev/omap2/Kconfig
@@ -0,0 +1,10 @@
+config OMAP2_VRFB
+	bool
+
+if ARCH_OMAP2PLUS
+
+source "drivers/video/fbdev/omap2/dss/Kconfig"
+source "drivers/video/fbdev/omap2/omapfb/Kconfig"
+source "drivers/video/fbdev/omap2/displays-new/Kconfig"
+
+endif
diff --git a/drivers/video/fbdev/omap2/Makefile b/drivers/video/fbdev/omap2/Makefile
new file mode 100644
index 000000000000..bf8127df8c71
--- /dev/null
+++ b/drivers/video/fbdev/omap2/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
+
+obj-$(CONFIG_OMAP2_DSS) += dss/
+obj-y += displays-new/
+obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/fbdev/omap2/displays-new/Kconfig b/drivers/video/fbdev/omap2/displays-new/Kconfig
new file mode 100644
index 000000000000..e6cfc38160d3
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/Kconfig
@@ -0,0 +1,80 @@
+menu "OMAP Display Device Drivers (new device model)"
+        depends on OMAP2_DSS
+
+config DISPLAY_ENCODER_TFP410
+        tristate "TFP410 DPI to DVI Encoder"
+	help
+	  Driver for TFP410 DPI to DVI encoder.
+
+config DISPLAY_ENCODER_TPD12S015
+        tristate "TPD12S015 HDMI ESD protection and level shifter"
+	help
+	  Driver for TPD12S015, which offers HDMI ESD protection and level
+	  shifting.
+
+config DISPLAY_CONNECTOR_DVI
+        tristate "DVI Connector"
+	depends on I2C
+	help
+	  Driver for a generic DVI connector.
+
+config DISPLAY_CONNECTOR_HDMI
+        tristate "HDMI Connector"
+	help
+	  Driver for a generic HDMI connector.
+
+config DISPLAY_CONNECTOR_ANALOG_TV
+        tristate "Analog TV Connector"
+	help
+	  Driver for a generic analog TV connector.
+
+config DISPLAY_PANEL_DPI
+	tristate "Generic DPI panel"
+	help
+	  Driver for generic DPI panels.
+
+config DISPLAY_PANEL_DSI_CM
+	tristate "Generic DSI Command Mode Panel"
+	depends on BACKLIGHT_CLASS_DEVICE
+	help
+	  Driver for generic DSI command mode panels.
+
+config DISPLAY_PANEL_SONY_ACX565AKM
+	tristate "ACX565AKM Panel"
+	depends on SPI && BACKLIGHT_CLASS_DEVICE
+	help
+	  This is the LCD panel used on Nokia N900
+
+config DISPLAY_PANEL_LGPHILIPS_LB035Q02
+	tristate "LG.Philips LB035Q02 LCD Panel"
+	depends on SPI
+	help
+	  LCD Panel used on the Gumstix Overo Palo35
+
+config DISPLAY_PANEL_SHARP_LS037V7DW01
+        tristate "Sharp LS037V7DW01 LCD Panel"
+        depends on BACKLIGHT_CLASS_DEVICE
+        help
+          LCD Panel used in TI's SDP3430 and EVM boards
+
+config DISPLAY_PANEL_TPO_TD028TTEC1
+        tristate "TPO TD028TTEC1 LCD Panel"
+        depends on SPI
+        help
+          LCD panel used in Openmoko.
+
+config DISPLAY_PANEL_TPO_TD043MTEA1
+        tristate "TPO TD043MTEA1 LCD Panel"
+        depends on SPI
+        help
+          LCD Panel used in OMAP3 Pandora
+
+config DISPLAY_PANEL_NEC_NL8048HL11
+	tristate "NEC NL8048HL11 Panel"
+	depends on SPI
+	depends on BACKLIGHT_CLASS_DEVICE
+	help
+		This NEC NL8048HL11 panel is TFT LCD used in the
+		Zoom2/3/3630 sdp boards.
+
+endmenu
diff --git a/drivers/video/fbdev/omap2/displays-new/Makefile b/drivers/video/fbdev/omap2/displays-new/Makefile
new file mode 100644
index 000000000000..0323a8a1c682
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/Makefile
@@ -0,0 +1,13 @@
+obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o
+obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o
+obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o
+obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o
+obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
+obj-$(CONFIG_DISPLAY_PANEL_DPI) += panel-dpi.o
+obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o
+obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
+obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
+obj-$(CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+obj-$(CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
+obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
+obj-$(CONFIG_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
diff --git a/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c
new file mode 100644
index 000000000000..5ee3b5505f7f
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c
@@ -0,0 +1,318 @@
+/*
+ * Analog TV Connector driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	struct device *dev;
+
+	struct omap_video_timings timings;
+
+	enum omap_dss_venc_type connector_type;
+	bool invert_polarity;
+};
+
+static const struct omap_video_timings tvc_pal_timings = {
+	.x_res		= 720,
+	.y_res		= 574,
+	.pixelclock	= 13500000,
+	.hsw		= 64,
+	.hfp		= 12,
+	.hbp		= 68,
+	.vsw		= 5,
+	.vfp		= 5,
+	.vbp		= 41,
+
+	.interlace	= true,
+};
+
+static const struct of_device_id tvc_of_match[];
+
+struct tvc_of_data {
+	enum omap_dss_venc_type connector_type;
+};
+
+#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
+
+static int tvc_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(ddata->dev, "connect\n");
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.atv->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void tvc_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(ddata->dev, "disconnect\n");
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.atv->disconnect(in, dssdev);
+}
+
+static int tvc_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(ddata->dev, "enable\n");
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.atv->set_timings(in, &ddata->timings);
+
+	if (!ddata->dev->of_node) {
+		in->ops.atv->set_type(in, ddata->connector_type);
+
+		in->ops.atv->invert_vid_out_polarity(in,
+			ddata->invert_polarity);
+	}
+
+	r = in->ops.atv->enable(in);
+	if (r)
+		return r;
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return r;
+}
+
+static void tvc_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(ddata->dev, "disable\n");
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	in->ops.atv->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void tvc_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->timings = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.atv->set_timings(in, timings);
+}
+
+static void tvc_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->timings;
+}
+
+static int tvc_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.atv->check_timings(in, timings);
+}
+
+static u32 tvc_get_wss(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.atv->get_wss(in);
+}
+
+static int tvc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.atv->set_wss(in, wss);
+}
+
+static struct omap_dss_driver tvc_driver = {
+	.connect		= tvc_connect,
+	.disconnect		= tvc_disconnect,
+
+	.enable			= tvc_enable,
+	.disable		= tvc_disable,
+
+	.set_timings		= tvc_set_timings,
+	.get_timings		= tvc_get_timings,
+	.check_timings		= tvc_check_timings,
+
+	.get_resolution		= omapdss_default_get_resolution,
+
+	.get_wss		= tvc_get_wss,
+	.set_wss		= tvc_set_wss,
+};
+
+static int tvc_probe_pdata(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct connector_atv_platform_data *pdata;
+	struct omap_dss_device *in, *dssdev;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&pdev->dev, "Failed to find video source\n");
+		return -EPROBE_DEFER;
+	}
+
+	ddata->in = in;
+
+	ddata->connector_type = pdata->connector_type;
+	ddata->invert_polarity = ddata->invert_polarity;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int tvc_probe_of(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+	struct omap_dss_device *in;
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&pdev->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	return 0;
+}
+
+static int tvc_probe(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+	ddata->dev = &pdev->dev;
+
+	if (dev_get_platdata(&pdev->dev)) {
+		r = tvc_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else if (pdev->dev.of_node) {
+		r = tvc_probe_of(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	ddata->timings = tvc_pal_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->driver = &tvc_driver;
+	dssdev->dev = &pdev->dev;
+	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = tvc_pal_timings;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+err_reg:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int __exit tvc_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_display(&ddata->dssdev);
+
+	tvc_disable(dssdev);
+	tvc_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static const struct of_device_id tvc_of_match[] = {
+	{ .compatible = "omapdss,svideo-connector", },
+	{ .compatible = "omapdss,composite-video-connector", },
+	{},
+};
+
+static struct platform_driver tvc_connector_driver = {
+	.probe	= tvc_probe,
+	.remove	= __exit_p(tvc_remove),
+	.driver	= {
+		.name	= "connector-analog-tv",
+		.owner	= THIS_MODULE,
+		.of_match_table = tvc_of_match,
+	},
+};
+
+module_platform_driver(tvc_connector_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("Analog TV Connector driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/connector-dvi.c b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c
new file mode 100644
index 000000000000..74de2bc50c4f
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c
@@ -0,0 +1,401 @@
+/*
+ * Generic DVI Connector driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <drm/drm_edid.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+static const struct omap_video_timings dvic_default_timings = {
+	.x_res		= 640,
+	.y_res		= 480,
+
+	.pixelclock	= 23500000,
+
+	.hfp		= 48,
+	.hsw		= 32,
+	.hbp		= 80,
+
+	.vfp		= 3,
+	.vsw		= 4,
+	.vbp		= 7,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+};
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	struct omap_video_timings timings;
+
+	struct i2c_adapter *i2c_adapter;
+};
+
+#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
+
+static int dvic_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dvi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void dvic_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dvi->disconnect(in, dssdev);
+}
+
+static int dvic_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dvi->set_timings(in, &ddata->timings);
+
+	r = in->ops.dvi->enable(in);
+	if (r)
+		return r;
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void dvic_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	in->ops.dvi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void dvic_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->timings = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dvi->set_timings(in, timings);
+}
+
+static void dvic_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->timings;
+}
+
+static int dvic_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dvi->check_timings(in, timings);
+}
+
+static int dvic_ddc_read(struct i2c_adapter *adapter,
+		unsigned char *buf, u16 count, u8 offset)
+{
+	int r, retries;
+
+	for (retries = 3; retries > 0; retries--) {
+		struct i2c_msg msgs[] = {
+			{
+				.addr   = DDC_ADDR,
+				.flags  = 0,
+				.len    = 1,
+				.buf    = &offset,
+			}, {
+				.addr   = DDC_ADDR,
+				.flags  = I2C_M_RD,
+				.len    = count,
+				.buf    = buf,
+			}
+		};
+
+		r = i2c_transfer(adapter, msgs, 2);
+		if (r == 2)
+			return 0;
+
+		if (r != -EAGAIN)
+			break;
+	}
+
+	return r < 0 ? r : -EIO;
+}
+
+static int dvic_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	int r, l, bytes_read;
+
+	if (!ddata->i2c_adapter)
+		return -ENODEV;
+
+	l = min(EDID_LENGTH, len);
+	r = dvic_ddc_read(ddata->i2c_adapter, edid, l, 0);
+	if (r)
+		return r;
+
+	bytes_read = l;
+
+	/* if there are extensions, read second block */
+	if (len > EDID_LENGTH && edid[0x7e] > 0) {
+		l = min(EDID_LENGTH, len - EDID_LENGTH);
+
+		r = dvic_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
+				l, EDID_LENGTH);
+		if (r)
+			return r;
+
+		bytes_read += l;
+	}
+
+	return bytes_read;
+}
+
+static bool dvic_detect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	unsigned char out;
+	int r;
+
+	if (!ddata->i2c_adapter)
+		return true;
+
+	r = dvic_ddc_read(ddata->i2c_adapter, &out, 1, 0);
+
+	return r == 0;
+}
+
+static struct omap_dss_driver dvic_driver = {
+	.connect	= dvic_connect,
+	.disconnect	= dvic_disconnect,
+
+	.enable		= dvic_enable,
+	.disable	= dvic_disable,
+
+	.set_timings	= dvic_set_timings,
+	.get_timings	= dvic_get_timings,
+	.check_timings	= dvic_check_timings,
+
+	.get_resolution	= omapdss_default_get_resolution,
+
+	.read_edid	= dvic_read_edid,
+	.detect		= dvic_detect,
+};
+
+static int dvic_probe_pdata(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct connector_dvi_platform_data *pdata;
+	struct omap_dss_device *in, *dssdev;
+	int i2c_bus_num;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	i2c_bus_num = pdata->i2c_bus_num;
+
+	if (i2c_bus_num != -1) {
+		struct i2c_adapter *adapter;
+
+		adapter = i2c_get_adapter(i2c_bus_num);
+		if (!adapter) {
+			dev_err(&pdev->dev,
+					"Failed to get I2C adapter, bus %d\n",
+					i2c_bus_num);
+			return -EPROBE_DEFER;
+		}
+
+		ddata->i2c_adapter = adapter;
+	}
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		if (ddata->i2c_adapter)
+			i2c_put_adapter(ddata->i2c_adapter);
+
+		dev_err(&pdev->dev, "Failed to find video source\n");
+		return -EPROBE_DEFER;
+	}
+
+	ddata->in = in;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int dvic_probe_of(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+	struct omap_dss_device *in;
+	struct device_node *adapter_node;
+	struct i2c_adapter *adapter;
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&pdev->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0);
+	if (adapter_node) {
+		adapter = of_find_i2c_adapter_by_node(adapter_node);
+		if (adapter == NULL) {
+			dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n");
+			omap_dss_put_device(ddata->in);
+			return -EPROBE_DEFER;
+		}
+
+		ddata->i2c_adapter = adapter;
+	}
+
+	return 0;
+}
+
+static int dvic_probe(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+
+	if (dev_get_platdata(&pdev->dev)) {
+		r = dvic_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else if (pdev->dev.of_node) {
+		r = dvic_probe_of(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	ddata->timings = dvic_default_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->driver = &dvic_driver;
+	dssdev->dev = &pdev->dev;
+	dssdev->type = OMAP_DISPLAY_TYPE_DVI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = dvic_default_timings;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+	omap_dss_put_device(ddata->in);
+
+	if (ddata->i2c_adapter)
+		i2c_put_adapter(ddata->i2c_adapter);
+
+	return r;
+}
+
+static int __exit dvic_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_display(&ddata->dssdev);
+
+	dvic_disable(dssdev);
+	dvic_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	if (ddata->i2c_adapter)
+		i2c_put_adapter(ddata->i2c_adapter);
+
+	return 0;
+}
+
+static const struct of_device_id dvic_of_match[] = {
+	{ .compatible = "omapdss,dvi-connector", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, dvic_of_match);
+
+static struct platform_driver dvi_connector_driver = {
+	.probe	= dvic_probe,
+	.remove	= __exit_p(dvic_remove),
+	.driver	= {
+		.name	= "connector-dvi",
+		.owner	= THIS_MODULE,
+		.of_match_table = dvic_of_match,
+	},
+};
+
+module_platform_driver(dvi_connector_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("Generic DVI Connector driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
new file mode 100644
index 000000000000..29ed21b9dce5
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
@@ -0,0 +1,405 @@
+/*
+ * HDMI Connector driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <drm/drm_edid.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+static const struct omap_video_timings hdmic_default_timings = {
+	.x_res		= 640,
+	.y_res		= 480,
+	.pixelclock	= 25175000,
+	.hsw		= 96,
+	.hfp		= 16,
+	.hbp		= 48,
+	.vsw		= 2,
+	.vfp		= 11,
+	.vbp		= 31,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+
+	.interlace	= false,
+};
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	struct device *dev;
+
+	struct omap_video_timings timings;
+};
+
+#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
+
+static int hdmic_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(ddata->dev, "connect\n");
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.hdmi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void hdmic_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(ddata->dev, "disconnect\n");
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.hdmi->disconnect(in, dssdev);
+}
+
+static int hdmic_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(ddata->dev, "enable\n");
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.hdmi->set_timings(in, &ddata->timings);
+
+	r = in->ops.hdmi->enable(in);
+	if (r)
+		return r;
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return r;
+}
+
+static void hdmic_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(ddata->dev, "disable\n");
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	in->ops.hdmi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void hdmic_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->timings = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.hdmi->set_timings(in, timings);
+}
+
+static void hdmic_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->timings;
+}
+
+static int hdmic_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.hdmi->check_timings(in, timings);
+}
+
+static int hdmic_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.hdmi->read_edid(in, edid, len);
+}
+
+static bool hdmic_detect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.hdmi->detect(in);
+}
+
+static int hdmic_audio_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	/* enable audio only if the display is active */
+	if (!omapdss_device_is_enabled(dssdev))
+		return -EPERM;
+
+	r = in->ops.hdmi->audio_enable(in);
+	if (r)
+		return r;
+
+	dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
+
+	return 0;
+}
+
+static void hdmic_audio_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	in->ops.hdmi->audio_disable(in);
+
+	dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
+}
+
+static int hdmic_audio_start(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	/*
+	 * No need to check the panel state. It was checked when trasitioning
+	 * to AUDIO_ENABLED.
+	 */
+	if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED)
+		return -EPERM;
+
+	r = in->ops.hdmi->audio_start(in);
+	if (r)
+		return r;
+
+	dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
+
+	return 0;
+}
+
+static void hdmic_audio_stop(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	in->ops.hdmi->audio_stop(in);
+
+	dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
+}
+
+static bool hdmic_audio_supported(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return false;
+
+	return in->ops.hdmi->audio_supported(in);
+}
+
+static int hdmic_audio_config(struct omap_dss_device *dssdev,
+		struct omap_dss_audio *audio)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	/* config audio only if the display is active */
+	if (!omapdss_device_is_enabled(dssdev))
+		return -EPERM;
+
+	r = in->ops.hdmi->audio_config(in, audio);
+	if (r)
+		return r;
+
+	dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
+
+	return 0;
+}
+
+static struct omap_dss_driver hdmic_driver = {
+	.connect		= hdmic_connect,
+	.disconnect		= hdmic_disconnect,
+
+	.enable			= hdmic_enable,
+	.disable		= hdmic_disable,
+
+	.set_timings		= hdmic_set_timings,
+	.get_timings		= hdmic_get_timings,
+	.check_timings		= hdmic_check_timings,
+
+	.get_resolution		= omapdss_default_get_resolution,
+
+	.read_edid		= hdmic_read_edid,
+	.detect			= hdmic_detect,
+
+	.audio_enable		= hdmic_audio_enable,
+	.audio_disable		= hdmic_audio_disable,
+	.audio_start		= hdmic_audio_start,
+	.audio_stop		= hdmic_audio_stop,
+	.audio_supported	= hdmic_audio_supported,
+	.audio_config		= hdmic_audio_config,
+};
+
+static int hdmic_probe_pdata(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct connector_hdmi_platform_data *pdata;
+	struct omap_dss_device *in, *dssdev;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&pdev->dev, "Failed to find video source\n");
+		return -EPROBE_DEFER;
+	}
+
+	ddata->in = in;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int hdmic_probe_of(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+	struct omap_dss_device *in;
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&pdev->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	return 0;
+}
+
+static int hdmic_probe(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+	ddata->dev = &pdev->dev;
+
+	if (dev_get_platdata(&pdev->dev)) {
+		r = hdmic_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else if (pdev->dev.of_node) {
+		r = hdmic_probe_of(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	ddata->timings = hdmic_default_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->driver = &hdmic_driver;
+	dssdev->dev = &pdev->dev;
+	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = hdmic_default_timings;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+err_reg:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int __exit hdmic_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_display(&ddata->dssdev);
+
+	hdmic_disable(dssdev);
+	hdmic_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static const struct of_device_id hdmic_of_match[] = {
+	{ .compatible = "omapdss,hdmi-connector", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, hdmic_of_match);
+
+static struct platform_driver hdmi_connector_driver = {
+	.probe	= hdmic_probe,
+	.remove	= __exit_p(hdmic_remove),
+	.driver	= {
+		.name	= "connector-hdmi",
+		.owner	= THIS_MODULE,
+		.of_match_table = hdmic_of_match,
+	},
+};
+
+module_platform_driver(hdmi_connector_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("HDMI Connector driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
new file mode 100644
index 000000000000..b4e9a42a79e6
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
@@ -0,0 +1,308 @@
+/*
+ * TFP410 DPI-to-DVI encoder driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	int pd_gpio;
+	int data_lines;
+
+	struct omap_video_timings timings;
+};
+
+#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
+
+static int tfp410_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return -EBUSY;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	dst->src = dssdev;
+	dssdev->dst = dst;
+
+	return 0;
+}
+
+static void tfp410_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	WARN_ON(!omapdss_device_is_connected(dssdev));
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	WARN_ON(dst != dssdev->dst);
+	if (dst != dssdev->dst)
+		return;
+
+	dst->src = NULL;
+	dssdev->dst = NULL;
+
+	in->ops.dpi->disconnect(in, &ddata->dssdev);
+}
+
+static int tfp410_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_timings(in, &ddata->timings);
+	if (ddata->data_lines)
+		in->ops.dpi->set_data_lines(in, ddata->data_lines);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	if (gpio_is_valid(ddata->pd_gpio))
+		gpio_set_value_cansleep(ddata->pd_gpio, 1);
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void tfp410_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	if (gpio_is_valid(ddata->pd_gpio))
+		gpio_set_value_cansleep(ddata->pd_gpio, 0);
+
+	in->ops.dpi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void tfp410_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->timings = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dpi->set_timings(in, timings);
+}
+
+static void tfp410_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->timings;
+}
+
+static int tfp410_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static const struct omapdss_dvi_ops tfp410_dvi_ops = {
+	.connect	= tfp410_connect,
+	.disconnect	= tfp410_disconnect,
+
+	.enable		= tfp410_enable,
+	.disable	= tfp410_disable,
+
+	.check_timings	= tfp410_check_timings,
+	.set_timings	= tfp410_set_timings,
+	.get_timings	= tfp410_get_timings,
+};
+
+static int tfp410_probe_pdata(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct encoder_tfp410_platform_data *pdata;
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	ddata->pd_gpio = pdata->power_down_gpio;
+
+	ddata->data_lines = pdata->data_lines;
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&pdev->dev, "Failed to find video source\n");
+		return -ENODEV;
+	}
+
+	ddata->in = in;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int tfp410_probe_of(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+	struct omap_dss_device *in;
+	int gpio;
+
+	gpio = of_get_named_gpio(node, "powerdown-gpios", 0);
+
+	if (gpio_is_valid(gpio) || gpio == -ENOENT) {
+		ddata->pd_gpio = gpio;
+	} else {
+		dev_err(&pdev->dev, "failed to parse PD gpio\n");
+		return gpio;
+	}
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&pdev->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	return 0;
+}
+
+static int tfp410_probe(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+
+	if (dev_get_platdata(&pdev->dev)) {
+		r = tfp410_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else if (pdev->dev.of_node) {
+		r = tfp410_probe_of(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	if (gpio_is_valid(ddata->pd_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->pd_gpio,
+				GPIOF_OUT_INIT_LOW, "tfp410 PD");
+		if (r) {
+			dev_err(&pdev->dev, "Failed to request PD GPIO %d\n",
+					ddata->pd_gpio);
+			goto err_gpio;
+		}
+	}
+
+	dssdev = &ddata->dssdev;
+	dssdev->ops.dvi = &tfp410_dvi_ops;
+	dssdev->dev = &pdev->dev;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->phy.dpi.data_lines = ddata->data_lines;
+
+	r = omapdss_register_output(dssdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to register output\n");
+		goto err_reg;
+	}
+
+	return 0;
+err_reg:
+err_gpio:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int __exit tfp410_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_output(&ddata->dssdev);
+
+	WARN_ON(omapdss_device_is_enabled(dssdev));
+	if (omapdss_device_is_enabled(dssdev))
+		tfp410_disable(dssdev);
+
+	WARN_ON(omapdss_device_is_connected(dssdev));
+	if (omapdss_device_is_connected(dssdev))
+		tfp410_disconnect(dssdev, dssdev->dst);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static const struct of_device_id tfp410_of_match[] = {
+	{ .compatible = "omapdss,ti,tfp410", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, tfp410_of_match);
+
+static struct platform_driver tfp410_driver = {
+	.probe	= tfp410_probe,
+	.remove	= __exit_p(tfp410_remove),
+	.driver	= {
+		.name	= "tfp410",
+		.owner	= THIS_MODULE,
+		.of_match_table = tfp410_of_match,
+	},
+};
+
+module_platform_driver(tfp410_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
new file mode 100644
index 000000000000..7e33686171e3
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
@@ -0,0 +1,451 @@
+/*
+ * TPD12S015 HDMI ESD protection & level shifter chip driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/of_gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	int ct_cp_hpd_gpio;
+	int ls_oe_gpio;
+	int hpd_gpio;
+
+	struct omap_video_timings timings;
+
+	struct completion hpd_completion;
+};
+
+#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
+
+static irqreturn_t tpd_hpd_irq_handler(int irq, void *data)
+{
+	struct panel_drv_data *ddata = data;
+	bool hpd;
+
+	hpd = gpio_get_value_cansleep(ddata->hpd_gpio);
+
+	dev_dbg(ddata->dssdev.dev, "hpd %d\n", hpd);
+
+	if (gpio_is_valid(ddata->ls_oe_gpio)) {
+		if (hpd)
+			gpio_set_value_cansleep(ddata->ls_oe_gpio, 1);
+		else
+			gpio_set_value_cansleep(ddata->ls_oe_gpio, 0);
+	}
+
+	complete_all(&ddata->hpd_completion);
+
+	return IRQ_HANDLED;
+}
+
+static int tpd_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	r = in->ops.hdmi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	dst->src = dssdev;
+	dssdev->dst = dst;
+
+	reinit_completion(&ddata->hpd_completion);
+
+	gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1);
+	/* DC-DC converter needs at max 300us to get to 90% of 5V */
+	udelay(300);
+
+	/*
+	 * If there's a cable connected, wait for the hpd irq to trigger,
+	 * which turns on the level shifters.
+	 */
+	if (gpio_get_value_cansleep(ddata->hpd_gpio)) {
+		unsigned long to;
+		to = wait_for_completion_timeout(&ddata->hpd_completion,
+				msecs_to_jiffies(250));
+		WARN_ON_ONCE(to == 0);
+	}
+
+	return 0;
+}
+
+static void tpd_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	WARN_ON(dst != dssdev->dst);
+
+	if (dst != dssdev->dst)
+		return;
+
+	gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0);
+
+	dst->src = NULL;
+	dssdev->dst = NULL;
+
+	in->ops.hdmi->disconnect(in, &ddata->dssdev);
+}
+
+static int tpd_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
+	in->ops.hdmi->set_timings(in, &ddata->timings);
+
+	r = in->ops.hdmi->enable(in);
+	if (r)
+		return r;
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return r;
+}
+
+static void tpd_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return;
+
+	in->ops.hdmi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void tpd_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->timings = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.hdmi->set_timings(in, timings);
+}
+
+static void tpd_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->timings;
+}
+
+static int tpd_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	r = in->ops.hdmi->check_timings(in, timings);
+
+	return r;
+}
+
+static int tpd_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!gpio_get_value_cansleep(ddata->hpd_gpio))
+		return -ENODEV;
+
+	return in->ops.hdmi->read_edid(in, edid, len);
+}
+
+static bool tpd_detect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	return gpio_get_value_cansleep(ddata->hpd_gpio);
+}
+
+static int tpd_audio_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.hdmi->audio_enable(in);
+}
+
+static void tpd_audio_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	in->ops.hdmi->audio_disable(in);
+}
+
+static int tpd_audio_start(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.hdmi->audio_start(in);
+}
+
+static void tpd_audio_stop(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	in->ops.hdmi->audio_stop(in);
+}
+
+static bool tpd_audio_supported(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.hdmi->audio_supported(in);
+}
+
+static int tpd_audio_config(struct omap_dss_device *dssdev,
+		struct omap_dss_audio *audio)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.hdmi->audio_config(in, audio);
+}
+
+static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
+	.connect		= tpd_connect,
+	.disconnect		= tpd_disconnect,
+
+	.enable			= tpd_enable,
+	.disable		= tpd_disable,
+
+	.check_timings		= tpd_check_timings,
+	.set_timings		= tpd_set_timings,
+	.get_timings		= tpd_get_timings,
+
+	.read_edid		= tpd_read_edid,
+	.detect			= tpd_detect,
+
+	.audio_enable		= tpd_audio_enable,
+	.audio_disable		= tpd_audio_disable,
+	.audio_start		= tpd_audio_start,
+	.audio_stop		= tpd_audio_stop,
+	.audio_supported	= tpd_audio_supported,
+	.audio_config		= tpd_audio_config,
+};
+
+static int tpd_probe_pdata(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct encoder_tpd12s015_platform_data *pdata;
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	ddata->ct_cp_hpd_gpio = pdata->ct_cp_hpd_gpio;
+	ddata->ls_oe_gpio = pdata->ls_oe_gpio;
+	ddata->hpd_gpio = pdata->hpd_gpio;
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&pdev->dev, "Failed to find video source\n");
+		return -ENODEV;
+	}
+
+	ddata->in = in;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int tpd_probe_of(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
+	struct omap_dss_device *in;
+	int gpio;
+
+	/* CT CP HPD GPIO */
+	gpio = of_get_gpio(node, 0);
+	if (!gpio_is_valid(gpio)) {
+		dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n");
+		return gpio;
+	}
+	ddata->ct_cp_hpd_gpio = gpio;
+
+	/* LS OE GPIO */
+	gpio = of_get_gpio(node, 1);
+	if (gpio_is_valid(gpio) || gpio == -ENOENT) {
+		ddata->ls_oe_gpio = gpio;
+	} else {
+		dev_err(&pdev->dev, "failed to parse LS OE gpio\n");
+		return gpio;
+	}
+
+	/* HPD GPIO */
+	gpio = of_get_gpio(node, 2);
+	if (!gpio_is_valid(gpio)) {
+		dev_err(&pdev->dev, "failed to parse HPD gpio\n");
+		return gpio;
+	}
+	ddata->hpd_gpio = gpio;
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&pdev->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	return 0;
+}
+
+static int tpd_probe(struct platform_device *pdev)
+{
+	struct omap_dss_device *in, *dssdev;
+	struct panel_drv_data *ddata;
+	int r;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+
+	init_completion(&ddata->hpd_completion);
+
+	if (dev_get_platdata(&pdev->dev)) {
+		r = tpd_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else if (pdev->dev.of_node) {
+		r = tpd_probe_of(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	r = devm_gpio_request_one(&pdev->dev, ddata->ct_cp_hpd_gpio,
+			GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd");
+	if (r)
+		goto err_gpio;
+
+	if (gpio_is_valid(ddata->ls_oe_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->ls_oe_gpio,
+				GPIOF_OUT_INIT_LOW, "hdmi_ls_oe");
+		if (r)
+			goto err_gpio;
+	}
+
+	r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
+			GPIOF_DIR_IN, "hdmi_hpd");
+	if (r)
+		goto err_gpio;
+
+	r = devm_request_threaded_irq(&pdev->dev, gpio_to_irq(ddata->hpd_gpio),
+				 NULL, tpd_hpd_irq_handler,
+				 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+				 IRQF_ONESHOT, "hpd", ddata);
+	if (r)
+		goto err_irq;
+
+	dssdev = &ddata->dssdev;
+	dssdev->ops.hdmi = &tpd_hdmi_ops;
+	dssdev->dev = &pdev->dev;
+	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
+	dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
+	dssdev->owner = THIS_MODULE;
+
+	in = ddata->in;
+
+	r = omapdss_register_output(dssdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to register output\n");
+		goto err_reg;
+	}
+
+	return 0;
+err_reg:
+err_irq:
+err_gpio:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int __exit tpd_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_output(&ddata->dssdev);
+
+	WARN_ON(omapdss_device_is_enabled(dssdev));
+	if (omapdss_device_is_enabled(dssdev))
+		tpd_disable(dssdev);
+
+	WARN_ON(omapdss_device_is_connected(dssdev));
+	if (omapdss_device_is_connected(dssdev))
+		tpd_disconnect(dssdev, dssdev->dst);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static const struct of_device_id tpd_of_match[] = {
+	{ .compatible = "omapdss,ti,tpd12s015", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, tpd_of_match);
+
+static struct platform_driver tpd_driver = {
+	.probe	= tpd_probe,
+	.remove	= __exit_p(tpd_remove),
+	.driver	= {
+		.name	= "tpd12s015",
+		.owner	= THIS_MODULE,
+		.of_match_table = tpd_of_match,
+	},
+};
+
+module_platform_driver(tpd_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("TPD12S015 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-dpi.c b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c
new file mode 100644
index 000000000000..5f8f7e7c81ef
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c
@@ -0,0 +1,270 @@
+/*
+ * Generic MIPI DPI Panel Driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	int data_lines;
+
+	struct omap_video_timings videomode;
+
+	int backlight_gpio;
+	int enable_gpio;
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static int panel_dpi_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void panel_dpi_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dpi->disconnect(in, dssdev);
+}
+
+static int panel_dpi_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_data_lines(in, ddata->data_lines);
+	in->ops.dpi->set_timings(in, &ddata->videomode);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	if (gpio_is_valid(ddata->enable_gpio))
+		gpio_set_value_cansleep(ddata->enable_gpio, 1);
+
+	if (gpio_is_valid(ddata->backlight_gpio))
+		gpio_set_value_cansleep(ddata->backlight_gpio, 1);
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void panel_dpi_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	if (gpio_is_valid(ddata->enable_gpio))
+		gpio_set_value_cansleep(ddata->enable_gpio, 0);
+
+	if (gpio_is_valid(ddata->backlight_gpio))
+		gpio_set_value_cansleep(ddata->backlight_gpio, 0);
+
+	in->ops.dpi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void panel_dpi_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->videomode = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dpi->set_timings(in, timings);
+}
+
+static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->videomode;
+}
+
+static int panel_dpi_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static struct omap_dss_driver panel_dpi_ops = {
+	.connect	= panel_dpi_connect,
+	.disconnect	= panel_dpi_disconnect,
+
+	.enable		= panel_dpi_enable,
+	.disable	= panel_dpi_disable,
+
+	.set_timings	= panel_dpi_set_timings,
+	.get_timings	= panel_dpi_get_timings,
+	.check_timings	= panel_dpi_check_timings,
+
+	.get_resolution	= omapdss_default_get_resolution,
+};
+
+static int panel_dpi_probe_pdata(struct platform_device *pdev)
+{
+	const struct panel_dpi_platform_data *pdata;
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev, *in;
+	struct videomode vm;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&pdev->dev, "failed to find video source '%s'\n",
+				pdata->source);
+		return -EPROBE_DEFER;
+	}
+
+	ddata->in = in;
+
+	ddata->data_lines = pdata->data_lines;
+
+	videomode_from_timing(pdata->display_timing, &vm);
+	videomode_to_omap_video_timings(&vm, &ddata->videomode);
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	ddata->enable_gpio = pdata->enable_gpio;
+	ddata->backlight_gpio = pdata->backlight_gpio;
+
+	return 0;
+}
+
+static int panel_dpi_probe(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+
+	if (dev_get_platdata(&pdev->dev)) {
+		r = panel_dpi_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	if (gpio_is_valid(ddata->enable_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->enable_gpio,
+				GPIOF_OUT_INIT_LOW, "panel enable");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->backlight_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->backlight_gpio,
+				GPIOF_OUT_INIT_LOW, "panel backlight");
+		if (r)
+			goto err_gpio;
+	}
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &pdev->dev;
+	dssdev->driver = &panel_dpi_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = ddata->videomode;
+	dssdev->phy.dpi.data_lines = ddata->data_lines;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+err_gpio:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int __exit panel_dpi_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_display(dssdev);
+
+	panel_dpi_disable(dssdev);
+	panel_dpi_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static struct platform_driver panel_dpi_driver = {
+	.probe = panel_dpi_probe,
+	.remove = __exit_p(panel_dpi_remove),
+	.driver = {
+		.name = "panel-dpi",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(panel_dpi_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("Generic MIPI DPI Panel Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c b/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c
new file mode 100644
index 000000000000..d6f14e8717e8
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c
@@ -0,0 +1,1388 @@
+/*
+ * Generic DSI Command Mode panel driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/* #define DEBUG */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+#include <video/mipi_display.h>
+
+/* DSI Virtual channel. Hardcoded for now. */
+#define TCH 0
+
+#define DCS_READ_NUM_ERRORS	0x05
+#define DCS_BRIGHTNESS		0x51
+#define DCS_CTRL_DISPLAY	0x53
+#define DCS_GET_ID1		0xda
+#define DCS_GET_ID2		0xdb
+#define DCS_GET_ID3		0xdc
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	struct omap_video_timings timings;
+
+	struct platform_device *pdev;
+
+	struct mutex lock;
+
+	struct backlight_device *bldev;
+
+	unsigned long	hw_guard_end;	/* next value of jiffies when we can
+					 * issue the next sleep in/out command
+					 */
+	unsigned long	hw_guard_wait;	/* max guard time in jiffies */
+
+	/* panel HW configuration from DT or platform data */
+	int reset_gpio;
+	int ext_te_gpio;
+
+	bool use_dsi_backlight;
+
+	struct omap_dsi_pin_config pin_config;
+
+	/* runtime variables */
+	bool enabled;
+
+	bool te_enabled;
+
+	atomic_t do_update;
+	int channel;
+
+	struct delayed_work te_timeout_work;
+
+	bool intro_printed;
+
+	struct workqueue_struct *workqueue;
+
+	bool ulps_enabled;
+	unsigned ulps_timeout;
+	struct delayed_work ulps_work;
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static irqreturn_t dsicm_te_isr(int irq, void *data);
+static void dsicm_te_timeout_work_callback(struct work_struct *work);
+static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
+
+static int dsicm_panel_reset(struct panel_drv_data *ddata);
+
+static void dsicm_ulps_work(struct work_struct *work);
+
+static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
+{
+	ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
+	ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
+}
+
+static void hw_guard_wait(struct panel_drv_data *ddata)
+{
+	unsigned long wait = ddata->hw_guard_end - jiffies;
+
+	if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(wait);
+	}
+}
+
+static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
+{
+	struct omap_dss_device *in = ddata->in;
+	int r;
+	u8 buf[1];
+
+	r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd, buf, 1);
+
+	if (r < 0)
+		return r;
+
+	*data = buf[0];
+
+	return 0;
+}
+
+static int dsicm_dcs_write_0(struct panel_drv_data *ddata, u8 dcs_cmd)
+{
+	struct omap_dss_device *in = ddata->in;
+	return in->ops.dsi->dcs_write(in, ddata->channel, &dcs_cmd, 1);
+}
+
+static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
+{
+	struct omap_dss_device *in = ddata->in;
+	u8 buf[2] = { dcs_cmd, param };
+
+	return in->ops.dsi->dcs_write(in, ddata->channel, buf, 2);
+}
+
+static int dsicm_sleep_in(struct panel_drv_data *ddata)
+
+{
+	struct omap_dss_device *in = ddata->in;
+	u8 cmd;
+	int r;
+
+	hw_guard_wait(ddata);
+
+	cmd = MIPI_DCS_ENTER_SLEEP_MODE;
+	r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, &cmd, 1);
+	if (r)
+		return r;
+
+	hw_guard_start(ddata, 120);
+
+	usleep_range(5000, 10000);
+
+	return 0;
+}
+
+static int dsicm_sleep_out(struct panel_drv_data *ddata)
+{
+	int r;
+
+	hw_guard_wait(ddata);
+
+	r = dsicm_dcs_write_0(ddata, MIPI_DCS_EXIT_SLEEP_MODE);
+	if (r)
+		return r;
+
+	hw_guard_start(ddata, 120);
+
+	usleep_range(5000, 10000);
+
+	return 0;
+}
+
+static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
+{
+	int r;
+
+	r = dsicm_dcs_read_1(ddata, DCS_GET_ID1, id1);
+	if (r)
+		return r;
+	r = dsicm_dcs_read_1(ddata, DCS_GET_ID2, id2);
+	if (r)
+		return r;
+	r = dsicm_dcs_read_1(ddata, DCS_GET_ID3, id3);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int dsicm_set_update_window(struct panel_drv_data *ddata,
+		u16 x, u16 y, u16 w, u16 h)
+{
+	struct omap_dss_device *in = ddata->in;
+	int r;
+	u16 x1 = x;
+	u16 x2 = x + w - 1;
+	u16 y1 = y;
+	u16 y2 = y + h - 1;
+
+	u8 buf[5];
+	buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
+	buf[1] = (x1 >> 8) & 0xff;
+	buf[2] = (x1 >> 0) & 0xff;
+	buf[3] = (x2 >> 8) & 0xff;
+	buf[4] = (x2 >> 0) & 0xff;
+
+	r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
+	if (r)
+		return r;
+
+	buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
+	buf[1] = (y1 >> 8) & 0xff;
+	buf[2] = (y1 >> 0) & 0xff;
+	buf[3] = (y2 >> 8) & 0xff;
+	buf[4] = (y2 >> 0) & 0xff;
+
+	r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
+	if (r)
+		return r;
+
+	in->ops.dsi->bta_sync(in, ddata->channel);
+
+	return r;
+}
+
+static void dsicm_queue_ulps_work(struct panel_drv_data *ddata)
+{
+	if (ddata->ulps_timeout > 0)
+		queue_delayed_work(ddata->workqueue, &ddata->ulps_work,
+				msecs_to_jiffies(ddata->ulps_timeout));
+}
+
+static void dsicm_cancel_ulps_work(struct panel_drv_data *ddata)
+{
+	cancel_delayed_work(&ddata->ulps_work);
+}
+
+static int dsicm_enter_ulps(struct panel_drv_data *ddata)
+{
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (ddata->ulps_enabled)
+		return 0;
+
+	dsicm_cancel_ulps_work(ddata);
+
+	r = _dsicm_enable_te(ddata, false);
+	if (r)
+		goto err;
+
+	if (gpio_is_valid(ddata->ext_te_gpio))
+		disable_irq(gpio_to_irq(ddata->ext_te_gpio));
+
+	in->ops.dsi->disable(in, false, true);
+
+	ddata->ulps_enabled = true;
+
+	return 0;
+
+err:
+	dev_err(&ddata->pdev->dev, "enter ULPS failed");
+	dsicm_panel_reset(ddata);
+
+	ddata->ulps_enabled = false;
+
+	dsicm_queue_ulps_work(ddata);
+
+	return r;
+}
+
+static int dsicm_exit_ulps(struct panel_drv_data *ddata)
+{
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!ddata->ulps_enabled)
+		return 0;
+
+	r = in->ops.dsi->enable(in);
+	if (r) {
+		dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
+		goto err1;
+	}
+
+	in->ops.dsi->enable_hs(in, ddata->channel, true);
+
+	r = _dsicm_enable_te(ddata, true);
+	if (r) {
+		dev_err(&ddata->pdev->dev, "failed to re-enable TE");
+		goto err2;
+	}
+
+	if (gpio_is_valid(ddata->ext_te_gpio))
+		enable_irq(gpio_to_irq(ddata->ext_te_gpio));
+
+	dsicm_queue_ulps_work(ddata);
+
+	ddata->ulps_enabled = false;
+
+	return 0;
+
+err2:
+	dev_err(&ddata->pdev->dev, "failed to exit ULPS");
+
+	r = dsicm_panel_reset(ddata);
+	if (!r) {
+		if (gpio_is_valid(ddata->ext_te_gpio))
+			enable_irq(gpio_to_irq(ddata->ext_te_gpio));
+		ddata->ulps_enabled = false;
+	}
+err1:
+	dsicm_queue_ulps_work(ddata);
+
+	return r;
+}
+
+static int dsicm_wake_up(struct panel_drv_data *ddata)
+{
+	if (ddata->ulps_enabled)
+		return dsicm_exit_ulps(ddata);
+
+	dsicm_cancel_ulps_work(ddata);
+	dsicm_queue_ulps_work(ddata);
+	return 0;
+}
+
+static int dsicm_bl_update_status(struct backlight_device *dev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+	int level;
+
+	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+			dev->props.power == FB_BLANK_UNBLANK)
+		level = dev->props.brightness;
+	else
+		level = 0;
+
+	dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level);
+
+	mutex_lock(&ddata->lock);
+
+	if (ddata->enabled) {
+		in->ops.dsi->bus_lock(in);
+
+		r = dsicm_wake_up(ddata);
+		if (!r)
+			r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level);
+
+		in->ops.dsi->bus_unlock(in);
+	} else {
+		r = 0;
+	}
+
+	mutex_unlock(&ddata->lock);
+
+	return r;
+}
+
+static int dsicm_bl_get_intensity(struct backlight_device *dev)
+{
+	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+			dev->props.power == FB_BLANK_UNBLANK)
+		return dev->props.brightness;
+
+	return 0;
+}
+
+static const struct backlight_ops dsicm_bl_ops = {
+	.get_brightness = dsicm_bl_get_intensity,
+	.update_status  = dsicm_bl_update_status,
+};
+
+static void dsicm_get_resolution(struct omap_dss_device *dssdev,
+		u16 *xres, u16 *yres)
+{
+	*xres = dssdev->panel.timings.x_res;
+	*yres = dssdev->panel.timings.y_res;
+}
+
+static ssize_t dsicm_num_errors_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *in = ddata->in;
+	u8 errors = 0;
+	int r;
+
+	mutex_lock(&ddata->lock);
+
+	if (ddata->enabled) {
+		in->ops.dsi->bus_lock(in);
+
+		r = dsicm_wake_up(ddata);
+		if (!r)
+			r = dsicm_dcs_read_1(ddata, DCS_READ_NUM_ERRORS,
+					&errors);
+
+		in->ops.dsi->bus_unlock(in);
+	} else {
+		r = -ENODEV;
+	}
+
+	mutex_unlock(&ddata->lock);
+
+	if (r)
+		return r;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", errors);
+}
+
+static ssize_t dsicm_hw_revision_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *in = ddata->in;
+	u8 id1, id2, id3;
+	int r;
+
+	mutex_lock(&ddata->lock);
+
+	if (ddata->enabled) {
+		in->ops.dsi->bus_lock(in);
+
+		r = dsicm_wake_up(ddata);
+		if (!r)
+			r = dsicm_get_id(ddata, &id1, &id2, &id3);
+
+		in->ops.dsi->bus_unlock(in);
+	} else {
+		r = -ENODEV;
+	}
+
+	mutex_unlock(&ddata->lock);
+
+	if (r)
+		return r;
+
+	return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
+}
+
+static ssize_t dsicm_store_ulps(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *in = ddata->in;
+	unsigned long t;
+	int r;
+
+	r = kstrtoul(buf, 0, &t);
+	if (r)
+		return r;
+
+	mutex_lock(&ddata->lock);
+
+	if (ddata->enabled) {
+		in->ops.dsi->bus_lock(in);
+
+		if (t)
+			r = dsicm_enter_ulps(ddata);
+		else
+			r = dsicm_wake_up(ddata);
+
+		in->ops.dsi->bus_unlock(in);
+	}
+
+	mutex_unlock(&ddata->lock);
+
+	if (r)
+		return r;
+
+	return count;
+}
+
+static ssize_t dsicm_show_ulps(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	unsigned t;
+
+	mutex_lock(&ddata->lock);
+	t = ddata->ulps_enabled;
+	mutex_unlock(&ddata->lock);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", t);
+}
+
+static ssize_t dsicm_store_ulps_timeout(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *in = ddata->in;
+	unsigned long t;
+	int r;
+
+	r = kstrtoul(buf, 0, &t);
+	if (r)
+		return r;
+
+	mutex_lock(&ddata->lock);
+	ddata->ulps_timeout = t;
+
+	if (ddata->enabled) {
+		/* dsicm_wake_up will restart the timer */
+		in->ops.dsi->bus_lock(in);
+		r = dsicm_wake_up(ddata);
+		in->ops.dsi->bus_unlock(in);
+	}
+
+	mutex_unlock(&ddata->lock);
+
+	if (r)
+		return r;
+
+	return count;
+}
+
+static ssize_t dsicm_show_ulps_timeout(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	unsigned t;
+
+	mutex_lock(&ddata->lock);
+	t = ddata->ulps_timeout;
+	mutex_unlock(&ddata->lock);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", t);
+}
+
+static DEVICE_ATTR(num_dsi_errors, S_IRUGO, dsicm_num_errors_show, NULL);
+static DEVICE_ATTR(hw_revision, S_IRUGO, dsicm_hw_revision_show, NULL);
+static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
+		dsicm_show_ulps, dsicm_store_ulps);
+static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
+		dsicm_show_ulps_timeout, dsicm_store_ulps_timeout);
+
+static struct attribute *dsicm_attrs[] = {
+	&dev_attr_num_dsi_errors.attr,
+	&dev_attr_hw_revision.attr,
+	&dev_attr_ulps.attr,
+	&dev_attr_ulps_timeout.attr,
+	NULL,
+};
+
+static struct attribute_group dsicm_attr_group = {
+	.attrs = dsicm_attrs,
+};
+
+static void dsicm_hw_reset(struct panel_drv_data *ddata)
+{
+	if (!gpio_is_valid(ddata->reset_gpio))
+		return;
+
+	gpio_set_value(ddata->reset_gpio, 1);
+	udelay(10);
+	/* reset the panel */
+	gpio_set_value(ddata->reset_gpio, 0);
+	/* assert reset */
+	udelay(10);
+	gpio_set_value(ddata->reset_gpio, 1);
+	/* wait after releasing reset */
+	usleep_range(5000, 10000);
+}
+
+static int dsicm_power_on(struct panel_drv_data *ddata)
+{
+	struct omap_dss_device *in = ddata->in;
+	u8 id1, id2, id3;
+	int r;
+	struct omap_dss_dsi_config dsi_config = {
+		.mode = OMAP_DSS_DSI_CMD_MODE,
+		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
+		.timings = &ddata->timings,
+		.hs_clk_min = 150000000,
+		.hs_clk_max = 300000000,
+		.lp_clk_min = 7000000,
+		.lp_clk_max = 10000000,
+	};
+
+	if (ddata->pin_config.num_pins > 0) {
+		r = in->ops.dsi->configure_pins(in, &ddata->pin_config);
+		if (r) {
+			dev_err(&ddata->pdev->dev,
+				"failed to configure DSI pins\n");
+			goto err0;
+		}
+	}
+
+	r = in->ops.dsi->set_config(in, &dsi_config);
+	if (r) {
+		dev_err(&ddata->pdev->dev, "failed to configure DSI\n");
+		goto err0;
+	}
+
+	r = in->ops.dsi->enable(in);
+	if (r) {
+		dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
+		goto err0;
+	}
+
+	dsicm_hw_reset(ddata);
+
+	in->ops.dsi->enable_hs(in, ddata->channel, false);
+
+	r = dsicm_sleep_out(ddata);
+	if (r)
+		goto err;
+
+	r = dsicm_get_id(ddata, &id1, &id2, &id3);
+	if (r)
+		goto err;
+
+	r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, 0xff);
+	if (r)
+		goto err;
+
+	r = dsicm_dcs_write_1(ddata, DCS_CTRL_DISPLAY,
+			(1<<2) | (1<<5));	/* BL | BCTRL */
+	if (r)
+		goto err;
+
+	r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_PIXEL_FORMAT,
+		MIPI_DCS_PIXEL_FMT_24BIT);
+	if (r)
+		goto err;
+
+	r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_ON);
+	if (r)
+		goto err;
+
+	r = _dsicm_enable_te(ddata, ddata->te_enabled);
+	if (r)
+		goto err;
+
+	r = in->ops.dsi->enable_video_output(in, ddata->channel);
+	if (r)
+		goto err;
+
+	ddata->enabled = 1;
+
+	if (!ddata->intro_printed) {
+		dev_info(&ddata->pdev->dev, "panel revision %02x.%02x.%02x\n",
+			id1, id2, id3);
+		ddata->intro_printed = true;
+	}
+
+	in->ops.dsi->enable_hs(in, ddata->channel, true);
+
+	return 0;
+err:
+	dev_err(&ddata->pdev->dev, "error while enabling panel, issuing HW reset\n");
+
+	dsicm_hw_reset(ddata);
+
+	in->ops.dsi->disable(in, true, false);
+err0:
+	return r;
+}
+
+static void dsicm_power_off(struct panel_drv_data *ddata)
+{
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	in->ops.dsi->disable_video_output(in, ddata->channel);
+
+	r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_OFF);
+	if (!r)
+		r = dsicm_sleep_in(ddata);
+
+	if (r) {
+		dev_err(&ddata->pdev->dev,
+				"error disabling panel, issuing HW reset\n");
+		dsicm_hw_reset(ddata);
+	}
+
+	in->ops.dsi->disable(in, true, false);
+
+	ddata->enabled = 0;
+}
+
+static int dsicm_panel_reset(struct panel_drv_data *ddata)
+{
+	dev_err(&ddata->pdev->dev, "performing LCD reset\n");
+
+	dsicm_power_off(ddata);
+	dsicm_hw_reset(ddata);
+	return dsicm_power_on(ddata);
+}
+
+static int dsicm_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	struct device *dev = &ddata->pdev->dev;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dsi->connect(in, dssdev);
+	if (r) {
+		dev_err(dev, "Failed to connect to video source\n");
+		return r;
+	}
+
+	r = in->ops.dsi->request_vc(ddata->in, &ddata->channel);
+	if (r) {
+		dev_err(dev, "failed to get virtual channel\n");
+		goto err_req_vc;
+	}
+
+	r = in->ops.dsi->set_vc_id(ddata->in, ddata->channel, TCH);
+	if (r) {
+		dev_err(dev, "failed to set VC_ID\n");
+		goto err_vc_id;
+	}
+
+	return 0;
+
+err_vc_id:
+	in->ops.dsi->release_vc(ddata->in, ddata->channel);
+err_req_vc:
+	in->ops.dsi->disconnect(in, dssdev);
+	return r;
+}
+
+static void dsicm_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dsi->release_vc(in, ddata->channel);
+	in->ops.dsi->disconnect(in, dssdev);
+}
+
+static int dsicm_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(&ddata->pdev->dev, "enable\n");
+
+	mutex_lock(&ddata->lock);
+
+	if (!omapdss_device_is_connected(dssdev)) {
+		r = -ENODEV;
+		goto err;
+	}
+
+	if (omapdss_device_is_enabled(dssdev)) {
+		r = 0;
+		goto err;
+	}
+
+	in->ops.dsi->bus_lock(in);
+
+	r = dsicm_power_on(ddata);
+
+	in->ops.dsi->bus_unlock(in);
+
+	if (r)
+		goto err;
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	mutex_unlock(&ddata->lock);
+
+	return 0;
+err:
+	dev_dbg(&ddata->pdev->dev, "enable failed\n");
+	mutex_unlock(&ddata->lock);
+	return r;
+}
+
+static void dsicm_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(&ddata->pdev->dev, "disable\n");
+
+	mutex_lock(&ddata->lock);
+
+	dsicm_cancel_ulps_work(ddata);
+
+	in->ops.dsi->bus_lock(in);
+
+	if (omapdss_device_is_enabled(dssdev)) {
+		r = dsicm_wake_up(ddata);
+		if (!r)
+			dsicm_power_off(ddata);
+	}
+
+	in->ops.dsi->bus_unlock(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+	mutex_unlock(&ddata->lock);
+}
+
+static void dsicm_framedone_cb(int err, void *data)
+{
+	struct panel_drv_data *ddata = data;
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(&ddata->pdev->dev, "framedone, err %d\n", err);
+	in->ops.dsi->bus_unlock(ddata->in);
+}
+
+static irqreturn_t dsicm_te_isr(int irq, void *data)
+{
+	struct panel_drv_data *ddata = data;
+	struct omap_dss_device *in = ddata->in;
+	int old;
+	int r;
+
+	old = atomic_cmpxchg(&ddata->do_update, 1, 0);
+
+	if (old) {
+		cancel_delayed_work(&ddata->te_timeout_work);
+
+		r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
+				ddata);
+		if (r)
+			goto err;
+	}
+
+	return IRQ_HANDLED;
+err:
+	dev_err(&ddata->pdev->dev, "start update failed\n");
+	in->ops.dsi->bus_unlock(in);
+	return IRQ_HANDLED;
+}
+
+static void dsicm_te_timeout_work_callback(struct work_struct *work)
+{
+	struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
+					te_timeout_work.work);
+	struct omap_dss_device *in = ddata->in;
+
+	dev_err(&ddata->pdev->dev, "TE not received for 250ms!\n");
+
+	atomic_set(&ddata->do_update, 0);
+	in->ops.dsi->bus_unlock(in);
+}
+
+static int dsicm_update(struct omap_dss_device *dssdev,
+				    u16 x, u16 y, u16 w, u16 h)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(&ddata->pdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
+
+	mutex_lock(&ddata->lock);
+	in->ops.dsi->bus_lock(in);
+
+	r = dsicm_wake_up(ddata);
+	if (r)
+		goto err;
+
+	if (!ddata->enabled) {
+		r = 0;
+		goto err;
+	}
+
+	/* XXX no need to send this every frame, but dsi break if not done */
+	r = dsicm_set_update_window(ddata, 0, 0,
+			dssdev->panel.timings.x_res,
+			dssdev->panel.timings.y_res);
+	if (r)
+		goto err;
+
+	if (ddata->te_enabled && gpio_is_valid(ddata->ext_te_gpio)) {
+		schedule_delayed_work(&ddata->te_timeout_work,
+				msecs_to_jiffies(250));
+		atomic_set(&ddata->do_update, 1);
+	} else {
+		r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
+				ddata);
+		if (r)
+			goto err;
+	}
+
+	/* note: no bus_unlock here. unlock is in framedone_cb */
+	mutex_unlock(&ddata->lock);
+	return 0;
+err:
+	in->ops.dsi->bus_unlock(in);
+	mutex_unlock(&ddata->lock);
+	return r;
+}
+
+static int dsicm_sync(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(&ddata->pdev->dev, "sync\n");
+
+	mutex_lock(&ddata->lock);
+	in->ops.dsi->bus_lock(in);
+	in->ops.dsi->bus_unlock(in);
+	mutex_unlock(&ddata->lock);
+
+	dev_dbg(&ddata->pdev->dev, "sync done\n");
+
+	return 0;
+}
+
+static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
+{
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (enable)
+		r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_TEAR_ON, 0);
+	else
+		r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF);
+
+	if (!gpio_is_valid(ddata->ext_te_gpio))
+		in->ops.dsi->enable_te(in, enable);
+
+	/* possible panel bug */
+	msleep(100);
+
+	return r;
+}
+
+static int dsicm_enable_te(struct omap_dss_device *dssdev, bool enable)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	mutex_lock(&ddata->lock);
+
+	if (ddata->te_enabled == enable)
+		goto end;
+
+	in->ops.dsi->bus_lock(in);
+
+	if (ddata->enabled) {
+		r = dsicm_wake_up(ddata);
+		if (r)
+			goto err;
+
+		r = _dsicm_enable_te(ddata, enable);
+		if (r)
+			goto err;
+	}
+
+	ddata->te_enabled = enable;
+
+	in->ops.dsi->bus_unlock(in);
+end:
+	mutex_unlock(&ddata->lock);
+
+	return 0;
+err:
+	in->ops.dsi->bus_unlock(in);
+	mutex_unlock(&ddata->lock);
+
+	return r;
+}
+
+static int dsicm_get_te(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	int r;
+
+	mutex_lock(&ddata->lock);
+	r = ddata->te_enabled;
+	mutex_unlock(&ddata->lock);
+
+	return r;
+}
+
+static int dsicm_memory_read(struct omap_dss_device *dssdev,
+		void *buf, size_t size,
+		u16 x, u16 y, u16 w, u16 h)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+	int first = 1;
+	int plen;
+	unsigned buf_used = 0;
+
+	if (size < w * h * 3)
+		return -ENOMEM;
+
+	mutex_lock(&ddata->lock);
+
+	if (!ddata->enabled) {
+		r = -ENODEV;
+		goto err1;
+	}
+
+	size = min(w * h * 3,
+			dssdev->panel.timings.x_res *
+			dssdev->panel.timings.y_res * 3);
+
+	in->ops.dsi->bus_lock(in);
+
+	r = dsicm_wake_up(ddata);
+	if (r)
+		goto err2;
+
+	/* plen 1 or 2 goes into short packet. until checksum error is fixed,
+	 * use short packets. plen 32 works, but bigger packets seem to cause
+	 * an error. */
+	if (size % 2)
+		plen = 1;
+	else
+		plen = 2;
+
+	dsicm_set_update_window(ddata, x, y, w, h);
+
+	r = in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, plen);
+	if (r)
+		goto err2;
+
+	while (buf_used < size) {
+		u8 dcs_cmd = first ? 0x2e : 0x3e;
+		first = 0;
+
+		r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd,
+				buf + buf_used, size - buf_used);
+
+		if (r < 0) {
+			dev_err(dssdev->dev, "read error\n");
+			goto err3;
+		}
+
+		buf_used += r;
+
+		if (r < plen) {
+			dev_err(&ddata->pdev->dev, "short read\n");
+			break;
+		}
+
+		if (signal_pending(current)) {
+			dev_err(&ddata->pdev->dev, "signal pending, "
+					"aborting memory read\n");
+			r = -ERESTARTSYS;
+			goto err3;
+		}
+	}
+
+	r = buf_used;
+
+err3:
+	in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, 1);
+err2:
+	in->ops.dsi->bus_unlock(in);
+err1:
+	mutex_unlock(&ddata->lock);
+	return r;
+}
+
+static void dsicm_ulps_work(struct work_struct *work)
+{
+	struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
+			ulps_work.work);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	mutex_lock(&ddata->lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !ddata->enabled) {
+		mutex_unlock(&ddata->lock);
+		return;
+	}
+
+	in->ops.dsi->bus_lock(in);
+
+	dsicm_enter_ulps(ddata);
+
+	in->ops.dsi->bus_unlock(in);
+	mutex_unlock(&ddata->lock);
+}
+
+static struct omap_dss_driver dsicm_ops = {
+	.connect	= dsicm_connect,
+	.disconnect	= dsicm_disconnect,
+
+	.enable		= dsicm_enable,
+	.disable	= dsicm_disable,
+
+	.update		= dsicm_update,
+	.sync		= dsicm_sync,
+
+	.get_resolution	= dsicm_get_resolution,
+	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
+	.enable_te	= dsicm_enable_te,
+	.get_te		= dsicm_get_te,
+
+	.memory_read	= dsicm_memory_read,
+};
+
+static int dsicm_probe_pdata(struct platform_device *pdev)
+{
+	const struct panel_dsicm_platform_data *pdata;
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&pdev->dev, "failed to find video source\n");
+		return -EPROBE_DEFER;
+	}
+	ddata->in = in;
+
+	ddata->reset_gpio = pdata->reset_gpio;
+
+	if (pdata->use_ext_te)
+		ddata->ext_te_gpio = pdata->ext_te_gpio;
+	else
+		ddata->ext_te_gpio = -1;
+
+	ddata->ulps_timeout = pdata->ulps_timeout;
+
+	ddata->use_dsi_backlight = pdata->use_dsi_backlight;
+
+	ddata->pin_config = pdata->pin_config;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int dsicm_probe_of(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *in;
+	int gpio;
+
+	gpio = of_get_named_gpio(node, "reset-gpios", 0);
+	if (!gpio_is_valid(gpio)) {
+		dev_err(&pdev->dev, "failed to parse reset gpio\n");
+		return gpio;
+	}
+	ddata->reset_gpio = gpio;
+
+	gpio = of_get_named_gpio(node, "te-gpios", 0);
+	if (gpio_is_valid(gpio) || gpio == -ENOENT) {
+		ddata->ext_te_gpio = gpio;
+	} else {
+		dev_err(&pdev->dev, "failed to parse TE gpio\n");
+		return gpio;
+	}
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&pdev->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	/* TODO: ulps, backlight */
+
+	return 0;
+}
+
+static int dsicm_probe(struct platform_device *pdev)
+{
+	struct backlight_properties props;
+	struct panel_drv_data *ddata;
+	struct backlight_device *bldev = NULL;
+	struct device *dev = &pdev->dev;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	dev_dbg(dev, "probe\n");
+
+	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+	ddata->pdev = pdev;
+
+	if (dev_get_platdata(dev)) {
+		r = dsicm_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else if (pdev->dev.of_node) {
+		r = dsicm_probe_of(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	ddata->timings.x_res = 864;
+	ddata->timings.y_res = 480;
+	ddata->timings.pixelclock = 864 * 480 * 60;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = dev;
+	dssdev->driver = &dsicm_ops;
+	dssdev->panel.timings = ddata->timings;
+	dssdev->type = OMAP_DISPLAY_TYPE_DSI;
+	dssdev->owner = THIS_MODULE;
+
+	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
+	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
+		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	mutex_init(&ddata->lock);
+
+	atomic_set(&ddata->do_update, 0);
+
+	if (gpio_is_valid(ddata->reset_gpio)) {
+		r = devm_gpio_request_one(dev, ddata->reset_gpio,
+				GPIOF_OUT_INIT_LOW, "taal rst");
+		if (r) {
+			dev_err(dev, "failed to request reset gpio\n");
+			return r;
+		}
+	}
+
+	if (gpio_is_valid(ddata->ext_te_gpio)) {
+		r = devm_gpio_request_one(dev, ddata->ext_te_gpio,
+				GPIOF_IN, "taal irq");
+		if (r) {
+			dev_err(dev, "GPIO request failed\n");
+			return r;
+		}
+
+		r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio),
+				dsicm_te_isr,
+				IRQF_TRIGGER_RISING,
+				"taal vsync", ddata);
+
+		if (r) {
+			dev_err(dev, "IRQ request failed\n");
+			return r;
+		}
+
+		INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
+					dsicm_te_timeout_work_callback);
+
+		dev_dbg(dev, "Using GPIO TE\n");
+	}
+
+	ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
+	if (ddata->workqueue == NULL) {
+		dev_err(dev, "can't create workqueue\n");
+		return -ENOMEM;
+	}
+	INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
+
+	dsicm_hw_reset(ddata);
+
+	if (ddata->use_dsi_backlight) {
+		memset(&props, 0, sizeof(struct backlight_properties));
+		props.max_brightness = 255;
+
+		props.type = BACKLIGHT_RAW;
+		bldev = backlight_device_register(dev_name(dev),
+				dev, ddata, &dsicm_bl_ops, &props);
+		if (IS_ERR(bldev)) {
+			r = PTR_ERR(bldev);
+			goto err_bl;
+		}
+
+		ddata->bldev = bldev;
+
+		bldev->props.fb_blank = FB_BLANK_UNBLANK;
+		bldev->props.power = FB_BLANK_UNBLANK;
+		bldev->props.brightness = 255;
+
+		dsicm_bl_update_status(bldev);
+	}
+
+	r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
+	if (r) {
+		dev_err(dev, "failed to create sysfs files\n");
+		goto err_sysfs_create;
+	}
+
+	return 0;
+
+err_sysfs_create:
+	if (bldev != NULL)
+		backlight_device_unregister(bldev);
+err_bl:
+	destroy_workqueue(ddata->workqueue);
+err_reg:
+	return r;
+}
+
+static int __exit dsicm_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct backlight_device *bldev;
+
+	dev_dbg(&pdev->dev, "remove\n");
+
+	omapdss_unregister_display(dssdev);
+
+	dsicm_disable(dssdev);
+	dsicm_disconnect(dssdev);
+
+	sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
+
+	bldev = ddata->bldev;
+	if (bldev != NULL) {
+		bldev->props.power = FB_BLANK_POWERDOWN;
+		dsicm_bl_update_status(bldev);
+		backlight_device_unregister(bldev);
+	}
+
+	omap_dss_put_device(ddata->in);
+
+	dsicm_cancel_ulps_work(ddata);
+	destroy_workqueue(ddata->workqueue);
+
+	/* reset, to be sure that the panel is in a valid state */
+	dsicm_hw_reset(ddata);
+
+	return 0;
+}
+
+static const struct of_device_id dsicm_of_match[] = {
+	{ .compatible = "omapdss,panel-dsi-cm", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, dsicm_of_match);
+
+static struct platform_driver dsicm_driver = {
+	.probe = dsicm_probe,
+	.remove = __exit_p(dsicm_remove),
+	.driver = {
+		.name = "panel-dsi-cm",
+		.owner = THIS_MODULE,
+		.of_match_table = dsicm_of_match,
+	},
+};
+
+module_platform_driver(dsicm_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
new file mode 100644
index 000000000000..2e6b513222d9
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
@@ -0,0 +1,358 @@
+/*
+ * LG.Philips LB035Q02 LCD Panel driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ * Based on a driver by: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+static struct omap_video_timings lb035q02_timings = {
+	.x_res = 320,
+	.y_res = 240,
+
+	.pixelclock	= 6500000,
+
+	.hsw		= 2,
+	.hfp		= 20,
+	.hbp		= 68,
+
+	.vsw		= 2,
+	.vfp		= 4,
+	.vbp		= 18,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+};
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	struct spi_device *spi;
+
+	int data_lines;
+
+	struct omap_video_timings videomode;
+
+	int reset_gpio;
+	int backlight_gpio;
+	int enable_gpio;
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val)
+{
+	struct spi_message msg;
+	struct spi_transfer index_xfer = {
+		.len		= 3,
+		.cs_change	= 1,
+	};
+	struct spi_transfer value_xfer = {
+		.len		= 3,
+	};
+	u8	buffer[16];
+
+	spi_message_init(&msg);
+
+	/* register index */
+	buffer[0] = 0x70;
+	buffer[1] = 0x00;
+	buffer[2] = reg & 0x7f;
+	index_xfer.tx_buf = buffer;
+	spi_message_add_tail(&index_xfer, &msg);
+
+	/* register value */
+	buffer[4] = 0x72;
+	buffer[5] = val >> 8;
+	buffer[6] = val;
+	value_xfer.tx_buf = buffer + 4;
+	spi_message_add_tail(&value_xfer, &msg);
+
+	return spi_sync(spi, &msg);
+}
+
+static void init_lb035q02_panel(struct spi_device *spi)
+{
+	/* Init sequence from page 28 of the lb035q02 spec */
+	lb035q02_write_reg(spi, 0x01, 0x6300);
+	lb035q02_write_reg(spi, 0x02, 0x0200);
+	lb035q02_write_reg(spi, 0x03, 0x0177);
+	lb035q02_write_reg(spi, 0x04, 0x04c7);
+	lb035q02_write_reg(spi, 0x05, 0xffc0);
+	lb035q02_write_reg(spi, 0x06, 0xe806);
+	lb035q02_write_reg(spi, 0x0a, 0x4008);
+	lb035q02_write_reg(spi, 0x0b, 0x0000);
+	lb035q02_write_reg(spi, 0x0d, 0x0030);
+	lb035q02_write_reg(spi, 0x0e, 0x2800);
+	lb035q02_write_reg(spi, 0x0f, 0x0000);
+	lb035q02_write_reg(spi, 0x16, 0x9f80);
+	lb035q02_write_reg(spi, 0x17, 0x0a0f);
+	lb035q02_write_reg(spi, 0x1e, 0x00c1);
+	lb035q02_write_reg(spi, 0x30, 0x0300);
+	lb035q02_write_reg(spi, 0x31, 0x0007);
+	lb035q02_write_reg(spi, 0x32, 0x0000);
+	lb035q02_write_reg(spi, 0x33, 0x0000);
+	lb035q02_write_reg(spi, 0x34, 0x0707);
+	lb035q02_write_reg(spi, 0x35, 0x0004);
+	lb035q02_write_reg(spi, 0x36, 0x0302);
+	lb035q02_write_reg(spi, 0x37, 0x0202);
+	lb035q02_write_reg(spi, 0x3a, 0x0a0d);
+	lb035q02_write_reg(spi, 0x3b, 0x0806);
+}
+
+static int lb035q02_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	init_lb035q02_panel(ddata->spi);
+
+	return 0;
+}
+
+static void lb035q02_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dpi->disconnect(in, dssdev);
+}
+
+static int lb035q02_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_data_lines(in, ddata->data_lines);
+	in->ops.dpi->set_timings(in, &ddata->videomode);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	if (gpio_is_valid(ddata->enable_gpio))
+		gpio_set_value_cansleep(ddata->enable_gpio, 1);
+
+	if (gpio_is_valid(ddata->backlight_gpio))
+		gpio_set_value_cansleep(ddata->backlight_gpio, 1);
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void lb035q02_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	if (gpio_is_valid(ddata->enable_gpio))
+		gpio_set_value_cansleep(ddata->enable_gpio, 0);
+
+	if (gpio_is_valid(ddata->backlight_gpio))
+		gpio_set_value_cansleep(ddata->backlight_gpio, 0);
+
+	in->ops.dpi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void lb035q02_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->videomode = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dpi->set_timings(in, timings);
+}
+
+static void lb035q02_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->videomode;
+}
+
+static int lb035q02_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static struct omap_dss_driver lb035q02_ops = {
+	.connect	= lb035q02_connect,
+	.disconnect	= lb035q02_disconnect,
+
+	.enable		= lb035q02_enable,
+	.disable	= lb035q02_disable,
+
+	.set_timings	= lb035q02_set_timings,
+	.get_timings	= lb035q02_get_timings,
+	.check_timings	= lb035q02_check_timings,
+
+	.get_resolution	= omapdss_default_get_resolution,
+};
+
+static int lb035q02_probe_pdata(struct spi_device *spi)
+{
+	const struct panel_lb035q02_platform_data *pdata;
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&spi->dev);
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&spi->dev, "failed to find video source '%s'\n",
+				pdata->source);
+		return -EPROBE_DEFER;
+	}
+
+	ddata->in = in;
+
+	ddata->data_lines = pdata->data_lines;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	ddata->enable_gpio = pdata->enable_gpio;
+	ddata->backlight_gpio = pdata->backlight_gpio;
+
+	return 0;
+}
+
+static int lb035q02_panel_spi_probe(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&spi->dev, ddata);
+
+	ddata->spi = spi;
+
+	if (dev_get_platdata(&spi->dev)) {
+		r = lb035q02_probe_pdata(spi);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	if (gpio_is_valid(ddata->enable_gpio)) {
+		r = devm_gpio_request_one(&spi->dev, ddata->enable_gpio,
+				GPIOF_OUT_INIT_LOW, "panel enable");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->backlight_gpio)) {
+		r = devm_gpio_request_one(&spi->dev, ddata->backlight_gpio,
+				GPIOF_OUT_INIT_LOW, "panel backlight");
+		if (r)
+			goto err_gpio;
+	}
+
+	ddata->videomode = lb035q02_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &spi->dev;
+	dssdev->driver = &lb035q02_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = ddata->videomode;
+	dssdev->phy.dpi.data_lines = ddata->data_lines;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&spi->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+err_gpio:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int lb035q02_panel_spi_remove(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_display(dssdev);
+
+	lb035q02_disable(dssdev);
+	lb035q02_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static struct spi_driver lb035q02_spi_driver = {
+	.probe		= lb035q02_panel_spi_probe,
+	.remove		= lb035q02_panel_spi_remove,
+	.driver		= {
+		.name	= "panel_lgphilips_lb035q02",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_spi_driver(lb035q02_spi_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("LG.Philips LB035Q02 LCD Panel driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
new file mode 100644
index 000000000000..996fa004b48c
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
@@ -0,0 +1,394 @@
+/*
+ * NEC NL8048HL11 Panel driver
+ *
+ * Copyright (C) 2010 Texas Instruments Inc.
+ * Author: Erik Gilling <konkers@android.com>
+ * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+struct panel_drv_data {
+	struct omap_dss_device	dssdev;
+	struct omap_dss_device *in;
+
+	struct omap_video_timings videomode;
+
+	int data_lines;
+
+	int res_gpio;
+	int qvga_gpio;
+
+	struct spi_device *spi;
+};
+
+#define LCD_XRES		800
+#define LCD_YRES		480
+/*
+ * NEC PIX Clock Ratings
+ * MIN:21.8MHz TYP:23.8MHz MAX:25.7MHz
+ */
+#define LCD_PIXEL_CLOCK		23800000
+
+static const struct {
+	unsigned char addr;
+	unsigned char dat;
+} nec_8048_init_seq[] = {
+	{ 3, 0x01 }, { 0, 0x00 }, { 1, 0x01 }, { 4, 0x00 }, { 5, 0x14 },
+	{ 6, 0x24 }, { 16, 0xD7 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x55 },
+	{ 20, 0x01 }, { 21, 0x70 }, { 22, 0x1E }, { 23, 0x25 },	{ 24, 0x25 },
+	{ 25, 0x02 }, { 26, 0x02 }, { 27, 0xA0 }, { 32, 0x2F }, { 33, 0x0F },
+	{ 34, 0x0F }, { 35, 0x0F }, { 36, 0x0F }, { 37, 0x0F },	{ 38, 0x0F },
+	{ 39, 0x00 }, { 40, 0x02 }, { 41, 0x02 }, { 42, 0x02 },	{ 43, 0x0F },
+	{ 44, 0x0F }, { 45, 0x0F }, { 46, 0x0F }, { 47, 0x0F },	{ 48, 0x0F },
+	{ 49, 0x0F }, { 50, 0x00 }, { 51, 0x02 }, { 52, 0x02 }, { 53, 0x02 },
+	{ 80, 0x0C }, { 83, 0x42 }, { 84, 0x42 }, { 85, 0x41 },	{ 86, 0x14 },
+	{ 89, 0x88 }, { 90, 0x01 }, { 91, 0x00 }, { 92, 0x02 },	{ 93, 0x0C },
+	{ 94, 0x1C }, { 95, 0x27 }, { 98, 0x49 }, { 99, 0x27 }, { 102, 0x76 },
+	{ 103, 0x27 }, { 112, 0x01 }, { 113, 0x0E }, { 114, 0x02 },
+	{ 115, 0x0C }, { 118, 0x0C }, { 121, 0x30 }, { 130, 0x00 },
+	{ 131, 0x00 }, { 132, 0xFC }, { 134, 0x00 }, { 136, 0x00 },
+	{ 138, 0x00 }, { 139, 0x00 }, { 140, 0x00 }, { 141, 0xFC },
+	{ 143, 0x00 }, { 145, 0x00 }, { 147, 0x00 }, { 148, 0x00 },
+	{ 149, 0x00 }, { 150, 0xFC }, { 152, 0x00 }, { 154, 0x00 },
+	{ 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
+};
+
+static const struct omap_video_timings nec_8048_panel_timings = {
+	.x_res		= LCD_XRES,
+	.y_res		= LCD_YRES,
+	.pixelclock	= LCD_PIXEL_CLOCK,
+	.hfp		= 6,
+	.hsw		= 1,
+	.hbp		= 4,
+	.vfp		= 3,
+	.vsw		= 1,
+	.vbp		= 4,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static int nec_8048_spi_send(struct spi_device *spi, unsigned char reg_addr,
+			unsigned char reg_data)
+{
+	int ret = 0;
+	unsigned int cmd = 0, data = 0;
+
+	cmd = 0x0000 | reg_addr; /* register address write */
+	data = 0x0100 | reg_data; /* register data write */
+	data = (cmd << 16) | data;
+
+	ret = spi_write(spi, (unsigned char *)&data, 4);
+	if (ret)
+		pr_err("error in spi_write %x\n", data);
+
+	return ret;
+}
+
+static int init_nec_8048_wvga_lcd(struct spi_device *spi)
+{
+	unsigned int i;
+	/* Initialization Sequence */
+	/* nec_8048_spi_send(spi, REG, VAL) */
+	for (i = 0; i < (ARRAY_SIZE(nec_8048_init_seq) - 1); i++)
+		nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
+				nec_8048_init_seq[i].dat);
+	udelay(20);
+	nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
+				nec_8048_init_seq[i].dat);
+	return 0;
+}
+
+static int nec_8048_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void nec_8048_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dpi->disconnect(in, dssdev);
+}
+
+static int nec_8048_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_data_lines(in, ddata->data_lines);
+	in->ops.dpi->set_timings(in, &ddata->videomode);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	if (gpio_is_valid(ddata->res_gpio))
+		gpio_set_value_cansleep(ddata->res_gpio, 1);
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void nec_8048_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	if (gpio_is_valid(ddata->res_gpio))
+		gpio_set_value_cansleep(ddata->res_gpio, 0);
+
+	in->ops.dpi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void nec_8048_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->videomode = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dpi->set_timings(in, timings);
+}
+
+static void nec_8048_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->videomode;
+}
+
+static int nec_8048_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static struct omap_dss_driver nec_8048_ops = {
+	.connect	= nec_8048_connect,
+	.disconnect	= nec_8048_disconnect,
+
+	.enable		= nec_8048_enable,
+	.disable	= nec_8048_disable,
+
+	.set_timings	= nec_8048_set_timings,
+	.get_timings	= nec_8048_get_timings,
+	.check_timings	= nec_8048_check_timings,
+
+	.get_resolution	= omapdss_default_get_resolution,
+};
+
+
+static int nec_8048_probe_pdata(struct spi_device *spi)
+{
+	const struct panel_nec_nl8048hl11_platform_data *pdata;
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&spi->dev);
+
+	ddata->qvga_gpio = pdata->qvga_gpio;
+	ddata->res_gpio = pdata->res_gpio;
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&spi->dev, "failed to find video source '%s'\n",
+				pdata->source);
+		return -EPROBE_DEFER;
+	}
+	ddata->in = in;
+
+	ddata->data_lines = pdata->data_lines;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int nec_8048_probe(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	dev_dbg(&spi->dev, "%s\n", __func__);
+
+	spi->mode = SPI_MODE_0;
+	spi->bits_per_word = 32;
+
+	r = spi_setup(spi);
+	if (r < 0) {
+		dev_err(&spi->dev, "spi_setup failed: %d\n", r);
+		return r;
+	}
+
+	init_nec_8048_wvga_lcd(spi);
+
+	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&spi->dev, ddata);
+
+	ddata->spi = spi;
+
+	if (dev_get_platdata(&spi->dev)) {
+		r = nec_8048_probe_pdata(spi);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	if (gpio_is_valid(ddata->qvga_gpio)) {
+		r = devm_gpio_request_one(&spi->dev, ddata->qvga_gpio,
+				GPIOF_OUT_INIT_HIGH, "lcd QVGA");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->res_gpio)) {
+		r = devm_gpio_request_one(&spi->dev, ddata->res_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd RES");
+		if (r)
+			goto err_gpio;
+	}
+
+	ddata->videomode = nec_8048_panel_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &spi->dev;
+	dssdev->driver = &nec_8048_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = ddata->videomode;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&spi->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+err_gpio:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int nec_8048_remove(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
+
+	omapdss_unregister_display(dssdev);
+
+	nec_8048_disable(dssdev);
+	nec_8048_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int nec_8048_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+
+	nec_8048_spi_send(spi, 2, 0x01);
+	mdelay(40);
+
+	return 0;
+}
+
+static int nec_8048_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+
+	/* reinitialize the panel */
+	spi_setup(spi);
+	nec_8048_spi_send(spi, 2, 0x00);
+	init_nec_8048_wvga_lcd(spi);
+
+	return 0;
+}
+static SIMPLE_DEV_PM_OPS(nec_8048_pm_ops, nec_8048_suspend,
+		nec_8048_resume);
+#define NEC_8048_PM_OPS (&nec_8048_pm_ops)
+#else
+#define NEC_8048_PM_OPS NULL
+#endif
+
+static struct spi_driver nec_8048_driver = {
+	.driver = {
+		.name	= "panel-nec-nl8048hl11",
+		.owner	= THIS_MODULE,
+		.pm	= NEC_8048_PM_OPS,
+	},
+	.probe	= nec_8048_probe,
+	.remove	= nec_8048_remove,
+};
+
+module_spi_driver(nec_8048_driver);
+
+MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
+MODULE_DESCRIPTION("NEC-NL8048HL11 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
new file mode 100644
index 000000000000..b2f710be565d
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
@@ -0,0 +1,324 @@
+/*
+ * LCD panel driver for Sharp LS037V7DW01
+ *
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	int data_lines;
+
+	struct omap_video_timings videomode;
+
+	int resb_gpio;
+	int ini_gpio;
+	int mo_gpio;
+	int lr_gpio;
+	int ud_gpio;
+};
+
+static const struct omap_video_timings sharp_ls_timings = {
+	.x_res = 480,
+	.y_res = 640,
+
+	.pixelclock	= 19200000,
+
+	.hsw		= 2,
+	.hfp		= 1,
+	.hbp		= 28,
+
+	.vsw		= 1,
+	.vfp		= 1,
+	.vbp		= 1,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static int sharp_ls_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void sharp_ls_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dpi->disconnect(in, dssdev);
+}
+
+static int sharp_ls_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_data_lines(in, ddata->data_lines);
+	in->ops.dpi->set_timings(in, &ddata->videomode);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	/* wait couple of vsyncs until enabling the LCD */
+	msleep(50);
+
+	if (gpio_is_valid(ddata->resb_gpio))
+		gpio_set_value_cansleep(ddata->resb_gpio, 1);
+
+	if (gpio_is_valid(ddata->ini_gpio))
+		gpio_set_value_cansleep(ddata->ini_gpio, 1);
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void sharp_ls_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	if (gpio_is_valid(ddata->ini_gpio))
+		gpio_set_value_cansleep(ddata->ini_gpio, 0);
+
+	if (gpio_is_valid(ddata->resb_gpio))
+		gpio_set_value_cansleep(ddata->resb_gpio, 0);
+
+	/* wait at least 5 vsyncs after disabling the LCD */
+
+	msleep(100);
+
+	in->ops.dpi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void sharp_ls_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->videomode = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dpi->set_timings(in, timings);
+}
+
+static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->videomode;
+}
+
+static int sharp_ls_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static struct omap_dss_driver sharp_ls_ops = {
+	.connect	= sharp_ls_connect,
+	.disconnect	= sharp_ls_disconnect,
+
+	.enable		= sharp_ls_enable,
+	.disable	= sharp_ls_disable,
+
+	.set_timings	= sharp_ls_set_timings,
+	.get_timings	= sharp_ls_get_timings,
+	.check_timings	= sharp_ls_check_timings,
+
+	.get_resolution	= omapdss_default_get_resolution,
+};
+
+static int sharp_ls_probe_pdata(struct platform_device *pdev)
+{
+	const struct panel_sharp_ls037v7dw01_platform_data *pdata;
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&pdev->dev, "failed to find video source '%s'\n",
+				pdata->source);
+		return -EPROBE_DEFER;
+	}
+
+	ddata->in = in;
+
+	ddata->data_lines = pdata->data_lines;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	ddata->resb_gpio = pdata->resb_gpio;
+	ddata->ini_gpio = pdata->ini_gpio;
+	ddata->mo_gpio = pdata->mo_gpio;
+	ddata->lr_gpio = pdata->lr_gpio;
+	ddata->ud_gpio = pdata->ud_gpio;
+
+	return 0;
+}
+
+static int sharp_ls_probe(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ddata);
+
+	if (dev_get_platdata(&pdev->dev)) {
+		r = sharp_ls_probe_pdata(pdev);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	if (gpio_is_valid(ddata->mo_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->mo_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd MO");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->lr_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->lr_gpio,
+				GPIOF_OUT_INIT_HIGH, "lcd LR");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->ud_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->ud_gpio,
+				GPIOF_OUT_INIT_HIGH, "lcd UD");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->resb_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->resb_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd RESB");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->ini_gpio)) {
+		r = devm_gpio_request_one(&pdev->dev, ddata->ini_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd INI");
+		if (r)
+			goto err_gpio;
+	}
+
+	ddata->videomode = sharp_ls_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &pdev->dev;
+	dssdev->driver = &sharp_ls_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = ddata->videomode;
+	dssdev->phy.dpi.data_lines = ddata->data_lines;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+err_gpio:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int __exit sharp_ls_remove(struct platform_device *pdev)
+{
+	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	omapdss_unregister_display(dssdev);
+
+	sharp_ls_disable(dssdev);
+	sharp_ls_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static struct platform_driver sharp_ls_driver = {
+	.probe = sharp_ls_probe,
+	.remove = __exit_p(sharp_ls_remove),
+	.driver = {
+		.name = "panel-sharp-ls037v7dw01",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(sharp_ls_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
new file mode 100644
index 000000000000..c7ba4d8b928a
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
@@ -0,0 +1,911 @@
+/*
+ * Sony ACX565AKM LCD Panel driver
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Original Driver Author: Imre Deak <imre.deak@nokia.com>
+ * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+#define MIPID_CMD_READ_DISP_ID		0x04
+#define MIPID_CMD_READ_RED		0x06
+#define MIPID_CMD_READ_GREEN		0x07
+#define MIPID_CMD_READ_BLUE		0x08
+#define MIPID_CMD_READ_DISP_STATUS	0x09
+#define MIPID_CMD_RDDSDR		0x0F
+#define MIPID_CMD_SLEEP_IN		0x10
+#define MIPID_CMD_SLEEP_OUT		0x11
+#define MIPID_CMD_DISP_OFF		0x28
+#define MIPID_CMD_DISP_ON		0x29
+#define MIPID_CMD_WRITE_DISP_BRIGHTNESS	0x51
+#define MIPID_CMD_READ_DISP_BRIGHTNESS	0x52
+#define MIPID_CMD_WRITE_CTRL_DISP	0x53
+
+#define CTRL_DISP_BRIGHTNESS_CTRL_ON	(1 << 5)
+#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON	(1 << 4)
+#define CTRL_DISP_BACKLIGHT_ON		(1 << 2)
+#define CTRL_DISP_AUTO_BRIGHTNESS_ON	(1 << 1)
+
+#define MIPID_CMD_READ_CTRL_DISP	0x54
+#define MIPID_CMD_WRITE_CABC		0x55
+#define MIPID_CMD_READ_CABC		0x56
+
+#define MIPID_VER_LPH8923		3
+#define MIPID_VER_LS041Y3		4
+#define MIPID_VER_L4F00311		8
+#define MIPID_VER_ACX565AKM		9
+
+struct panel_drv_data {
+	struct omap_dss_device	dssdev;
+	struct omap_dss_device *in;
+
+	int reset_gpio;
+	int datapairs;
+
+	struct omap_video_timings videomode;
+
+	char		*name;
+	int		enabled;
+	int		model;
+	int		revision;
+	u8		display_id[3];
+	unsigned	has_bc:1;
+	unsigned	has_cabc:1;
+	unsigned	cabc_mode;
+	unsigned long	hw_guard_end;		/* next value of jiffies
+						   when we can issue the
+						   next sleep in/out command */
+	unsigned long	hw_guard_wait;		/* max guard time in jiffies */
+
+	struct spi_device	*spi;
+	struct mutex		mutex;
+
+	struct backlight_device *bl_dev;
+};
+
+static const struct omap_video_timings acx565akm_panel_timings = {
+	.x_res		= 800,
+	.y_res		= 480,
+	.pixelclock	= 24000000,
+	.hfp		= 28,
+	.hsw		= 4,
+	.hbp		= 24,
+	.vfp		= 3,
+	.vsw		= 3,
+	.vbp		= 4,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd,
+			      const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+	struct spi_message	m;
+	struct spi_transfer	*x, xfer[5];
+	int			r;
+
+	BUG_ON(ddata->spi == NULL);
+
+	spi_message_init(&m);
+
+	memset(xfer, 0, sizeof(xfer));
+	x = &xfer[0];
+
+	cmd &=  0xff;
+	x->tx_buf = &cmd;
+	x->bits_per_word = 9;
+	x->len = 2;
+
+	if (rlen > 1 && wlen == 0) {
+		/*
+		 * Between the command and the response data there is a
+		 * dummy clock cycle. Add an extra bit after the command
+		 * word to account for this.
+		 */
+		x->bits_per_word = 10;
+		cmd <<= 1;
+	}
+	spi_message_add_tail(x, &m);
+
+	if (wlen) {
+		x++;
+		x->tx_buf = wbuf;
+		x->len = wlen;
+		x->bits_per_word = 9;
+		spi_message_add_tail(x, &m);
+	}
+
+	if (rlen) {
+		x++;
+		x->rx_buf	= rbuf;
+		x->len		= rlen;
+		spi_message_add_tail(x, &m);
+	}
+
+	r = spi_sync(ddata->spi, &m);
+	if (r < 0)
+		dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r);
+}
+
+static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd)
+{
+	acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void acx565akm_write(struct panel_drv_data *ddata,
+			       int reg, const u8 *buf, int len)
+{
+	acx565akm_transfer(ddata, reg, buf, len, NULL, 0);
+}
+
+static inline void acx565akm_read(struct panel_drv_data *ddata,
+			      int reg, u8 *buf, int len)
+{
+	acx565akm_transfer(ddata, reg, NULL, 0, buf, len);
+}
+
+static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
+{
+	ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
+	ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
+}
+
+static void hw_guard_wait(struct panel_drv_data *ddata)
+{
+	unsigned long wait = ddata->hw_guard_end - jiffies;
+
+	if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(wait);
+	}
+}
+
+static void set_sleep_mode(struct panel_drv_data *ddata, int on)
+{
+	int cmd;
+
+	if (on)
+		cmd = MIPID_CMD_SLEEP_IN;
+	else
+		cmd = MIPID_CMD_SLEEP_OUT;
+	/*
+	 * We have to keep 120msec between sleep in/out commands.
+	 * (8.2.15, 8.2.16).
+	 */
+	hw_guard_wait(ddata);
+	acx565akm_cmd(ddata, cmd);
+	hw_guard_start(ddata, 120);
+}
+
+static void set_display_state(struct panel_drv_data *ddata, int enabled)
+{
+	int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
+
+	acx565akm_cmd(ddata, cmd);
+}
+
+static int panel_enabled(struct panel_drv_data *ddata)
+{
+	u32 disp_status;
+	int enabled;
+
+	acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS,
+			(u8 *)&disp_status, 4);
+	disp_status = __be32_to_cpu(disp_status);
+	enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
+	dev_dbg(&ddata->spi->dev,
+		"LCD panel %senabled by bootloader (status 0x%04x)\n",
+		enabled ? "" : "not ", disp_status);
+	return enabled;
+}
+
+static int panel_detect(struct panel_drv_data *ddata)
+{
+	acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3);
+	dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n",
+		ddata->display_id[0],
+		ddata->display_id[1],
+		ddata->display_id[2]);
+
+	switch (ddata->display_id[0]) {
+	case 0x10:
+		ddata->model = MIPID_VER_ACX565AKM;
+		ddata->name = "acx565akm";
+		ddata->has_bc = 1;
+		ddata->has_cabc = 1;
+		break;
+	case 0x29:
+		ddata->model = MIPID_VER_L4F00311;
+		ddata->name = "l4f00311";
+		break;
+	case 0x45:
+		ddata->model = MIPID_VER_LPH8923;
+		ddata->name = "lph8923";
+		break;
+	case 0x83:
+		ddata->model = MIPID_VER_LS041Y3;
+		ddata->name = "ls041y3";
+		break;
+	default:
+		ddata->name = "unknown";
+		dev_err(&ddata->spi->dev, "invalid display ID\n");
+		return -ENODEV;
+	}
+
+	ddata->revision = ddata->display_id[1];
+
+	dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n",
+			ddata->name, ddata->revision);
+
+	return 0;
+}
+
+/*----------------------Backlight Control-------------------------*/
+
+static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable)
+{
+	u16 ctrl;
+
+	acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
+	if (enable) {
+		ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
+			CTRL_DISP_BACKLIGHT_ON;
+	} else {
+		ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
+			  CTRL_DISP_BACKLIGHT_ON);
+	}
+
+	ctrl |= 1 << 8;
+	acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
+}
+
+static void set_cabc_mode(struct panel_drv_data *ddata, unsigned mode)
+{
+	u16 cabc_ctrl;
+
+	ddata->cabc_mode = mode;
+	if (!ddata->enabled)
+		return;
+	cabc_ctrl = 0;
+	acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
+	cabc_ctrl &= ~3;
+	cabc_ctrl |= (1 << 8) | (mode & 3);
+	acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
+}
+
+static unsigned get_cabc_mode(struct panel_drv_data *ddata)
+{
+	return ddata->cabc_mode;
+}
+
+static unsigned get_hw_cabc_mode(struct panel_drv_data *ddata)
+{
+	u8 cabc_ctrl;
+
+	acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
+	return cabc_ctrl & 3;
+}
+
+static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level)
+{
+	int bv;
+
+	bv = level | (1 << 8);
+	acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
+
+	if (level)
+		enable_backlight_ctrl(ddata, 1);
+	else
+		enable_backlight_ctrl(ddata, 0);
+}
+
+static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata)
+{
+	u8 bv;
+
+	acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
+
+	return bv;
+}
+
+
+static int acx565akm_bl_update_status(struct backlight_device *dev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
+	int level;
+
+	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
+
+	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+			dev->props.power == FB_BLANK_UNBLANK)
+		level = dev->props.brightness;
+	else
+		level = 0;
+
+	if (ddata->has_bc)
+		acx565akm_set_brightness(ddata, level);
+	else
+		return -ENODEV;
+
+	return 0;
+}
+
+static int acx565akm_bl_get_intensity(struct backlight_device *dev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
+
+	dev_dbg(&dev->dev, "%s\n", __func__);
+
+	if (!ddata->has_bc)
+		return -ENODEV;
+
+	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+			dev->props.power == FB_BLANK_UNBLANK) {
+		if (ddata->has_bc)
+			return acx565akm_get_actual_brightness(ddata);
+		else
+			return dev->props.brightness;
+	}
+
+	return 0;
+}
+
+static int acx565akm_bl_update_status_locked(struct backlight_device *dev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
+	int r;
+
+	mutex_lock(&ddata->mutex);
+	r = acx565akm_bl_update_status(dev);
+	mutex_unlock(&ddata->mutex);
+
+	return r;
+}
+
+static int acx565akm_bl_get_intensity_locked(struct backlight_device *dev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
+	int r;
+
+	mutex_lock(&ddata->mutex);
+	r = acx565akm_bl_get_intensity(dev);
+	mutex_unlock(&ddata->mutex);
+
+	return r;
+}
+
+static const struct backlight_ops acx565akm_bl_ops = {
+	.get_brightness = acx565akm_bl_get_intensity_locked,
+	.update_status  = acx565akm_bl_update_status_locked,
+};
+
+/*--------------------Auto Brightness control via Sysfs---------------------*/
+
+static const char * const cabc_modes[] = {
+	"off",		/* always used when CABC is not supported */
+	"ui",
+	"still-image",
+	"moving-image",
+};
+
+static ssize_t show_cabc_mode(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	const char *mode_str;
+	int mode;
+	int len;
+
+	if (!ddata->has_cabc)
+		mode = 0;
+	else
+		mode = get_cabc_mode(ddata);
+	mode_str = "unknown";
+	if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
+		mode_str = cabc_modes[mode];
+	len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
+
+	return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
+}
+
+static ssize_t store_cabc_mode(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
+		const char *mode_str = cabc_modes[i];
+		int cmp_len = strlen(mode_str);
+
+		if (count > 0 && buf[count - 1] == '\n')
+			count--;
+		if (count != cmp_len)
+			continue;
+
+		if (strncmp(buf, mode_str, cmp_len) == 0)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(cabc_modes))
+		return -EINVAL;
+
+	if (!ddata->has_cabc && i != 0)
+		return -EINVAL;
+
+	mutex_lock(&ddata->mutex);
+	set_cabc_mode(ddata, i);
+	mutex_unlock(&ddata->mutex);
+
+	return count;
+}
+
+static ssize_t show_cabc_available_modes(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	int len;
+	int i;
+
+	if (!ddata->has_cabc)
+		return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
+
+	for (i = 0, len = 0;
+	     len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
+		len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
+			i ? " " : "", cabc_modes[i],
+			i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
+
+	return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
+}
+
+static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
+		show_cabc_mode, store_cabc_mode);
+static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
+		show_cabc_available_modes, NULL);
+
+static struct attribute *bldev_attrs[] = {
+	&dev_attr_cabc_mode.attr,
+	&dev_attr_cabc_available_modes.attr,
+	NULL,
+};
+
+static struct attribute_group bldev_attr_group = {
+	.attrs = bldev_attrs,
+};
+
+static int acx565akm_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.sdi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void acx565akm_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.sdi->disconnect(in, dssdev);
+}
+
+static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
+
+	in->ops.sdi->set_timings(in, &ddata->videomode);
+
+	if (ddata->datapairs > 0)
+		in->ops.sdi->set_datapairs(in, ddata->datapairs);
+
+	r = in->ops.sdi->enable(in);
+	if (r) {
+		pr_err("%s sdi enable failed\n", __func__);
+		return r;
+	}
+
+	/*FIXME tweak me */
+	msleep(50);
+
+	if (gpio_is_valid(ddata->reset_gpio))
+		gpio_set_value(ddata->reset_gpio, 1);
+
+	if (ddata->enabled) {
+		dev_dbg(&ddata->spi->dev, "panel already enabled\n");
+		return 0;
+	}
+
+	/*
+	 * We have to meet all the following delay requirements:
+	 * 1. tRW: reset pulse width 10usec (7.12.1)
+	 * 2. tRT: reset cancel time 5msec (7.12.1)
+	 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
+	 *    case (7.6.2)
+	 * 4. 120msec before the sleep out command (7.12.1)
+	 */
+	msleep(120);
+
+	set_sleep_mode(ddata, 0);
+	ddata->enabled = 1;
+
+	/* 5msec between sleep out and the next command. (8.2.16) */
+	usleep_range(5000, 10000);
+	set_display_state(ddata, 1);
+	set_cabc_mode(ddata, ddata->cabc_mode);
+
+	return acx565akm_bl_update_status(ddata->bl_dev);
+}
+
+static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(dssdev->dev, "%s\n", __func__);
+
+	if (!ddata->enabled)
+		return;
+
+	set_display_state(ddata, 0);
+	set_sleep_mode(ddata, 1);
+	ddata->enabled = 0;
+	/*
+	 * We have to provide PCLK,HS,VS signals for 2 frames (worst case
+	 * ~50msec) after sending the sleep in command and asserting the
+	 * reset signal. We probably could assert the reset w/o the delay
+	 * but we still delay to avoid possible artifacts. (7.6.1)
+	 */
+	msleep(50);
+
+	if (gpio_is_valid(ddata->reset_gpio))
+		gpio_set_value(ddata->reset_gpio, 0);
+
+	/* FIXME need to tweak this delay */
+	msleep(100);
+
+	in->ops.sdi->disable(in);
+}
+
+static int acx565akm_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	int r;
+
+	dev_dbg(dssdev->dev, "%s\n", __func__);
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	mutex_lock(&ddata->mutex);
+	r = acx565akm_panel_power_on(dssdev);
+	mutex_unlock(&ddata->mutex);
+	if (r)
+		return r;
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void acx565akm_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	dev_dbg(dssdev->dev, "%s\n", __func__);
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	mutex_lock(&ddata->mutex);
+	acx565akm_panel_power_off(dssdev);
+	mutex_unlock(&ddata->mutex);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void acx565akm_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->videomode = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.sdi->set_timings(in, timings);
+}
+
+static void acx565akm_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->videomode;
+}
+
+static int acx565akm_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.sdi->check_timings(in, timings);
+}
+
+static struct omap_dss_driver acx565akm_ops = {
+	.connect	= acx565akm_connect,
+	.disconnect	= acx565akm_disconnect,
+
+	.enable		= acx565akm_enable,
+	.disable	= acx565akm_disable,
+
+	.set_timings	= acx565akm_set_timings,
+	.get_timings	= acx565akm_get_timings,
+	.check_timings	= acx565akm_check_timings,
+
+	.get_resolution	= omapdss_default_get_resolution,
+};
+
+static int acx565akm_probe_pdata(struct spi_device *spi)
+{
+	const struct panel_acx565akm_platform_data *pdata;
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&spi->dev);
+
+	ddata->reset_gpio = pdata->reset_gpio;
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&spi->dev, "failed to find video source '%s'\n",
+				pdata->source);
+		return -EPROBE_DEFER;
+	}
+	ddata->in = in;
+
+	ddata->datapairs = pdata->datapairs;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int acx565akm_probe_of(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct device_node *np = spi->dev.of_node;
+
+	ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+
+	ddata->in = omapdss_of_find_source_for_first_ep(np);
+	if (IS_ERR(ddata->in)) {
+		dev_err(&spi->dev, "failed to find video source\n");
+		return PTR_ERR(ddata->in);
+	}
+
+	return 0;
+}
+
+static int acx565akm_probe(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	struct backlight_device *bldev;
+	int max_brightness, brightness;
+	struct backlight_properties props;
+	int r;
+
+	dev_dbg(&spi->dev, "%s\n", __func__);
+
+	spi->mode = SPI_MODE_3;
+
+	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&spi->dev, ddata);
+
+	ddata->spi = spi;
+
+	mutex_init(&ddata->mutex);
+
+	if (dev_get_platdata(&spi->dev)) {
+		r = acx565akm_probe_pdata(spi);
+		if (r)
+			return r;
+	} else if (spi->dev.of_node) {
+		r = acx565akm_probe_of(spi);
+		if (r)
+			return r;
+	} else {
+		dev_err(&spi->dev, "platform data missing!\n");
+		return -ENODEV;
+	}
+
+	if (gpio_is_valid(ddata->reset_gpio)) {
+		r = devm_gpio_request_one(&spi->dev, ddata->reset_gpio,
+				GPIOF_OUT_INIT_LOW, "lcd reset");
+		if (r)
+			goto err_gpio;
+	}
+
+	if (gpio_is_valid(ddata->reset_gpio))
+		gpio_set_value(ddata->reset_gpio, 1);
+
+	/*
+	 * After reset we have to wait 5 msec before the first
+	 * command can be sent.
+	 */
+	usleep_range(5000, 10000);
+
+	ddata->enabled = panel_enabled(ddata);
+
+	r = panel_detect(ddata);
+
+	if (!ddata->enabled && gpio_is_valid(ddata->reset_gpio))
+		gpio_set_value(ddata->reset_gpio, 0);
+
+	if (r) {
+		dev_err(&spi->dev, "%s panel detect error\n", __func__);
+		goto err_detect;
+	}
+
+	memset(&props, 0, sizeof(props));
+	props.fb_blank = FB_BLANK_UNBLANK;
+	props.power = FB_BLANK_UNBLANK;
+	props.type = BACKLIGHT_RAW;
+
+	bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
+			ddata, &acx565akm_bl_ops, &props);
+	ddata->bl_dev = bldev;
+	if (ddata->has_cabc) {
+		r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
+		if (r) {
+			dev_err(&bldev->dev,
+				"%s failed to create sysfs files\n", __func__);
+			goto err_sysfs;
+		}
+		ddata->cabc_mode = get_hw_cabc_mode(ddata);
+	}
+
+	max_brightness = 255;
+
+	if (ddata->has_bc)
+		brightness = acx565akm_get_actual_brightness(ddata);
+	else
+		brightness = 0;
+
+	bldev->props.max_brightness = max_brightness;
+	bldev->props.brightness = brightness;
+
+	acx565akm_bl_update_status(bldev);
+
+
+	ddata->videomode = acx565akm_panel_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &spi->dev;
+	dssdev->driver = &acx565akm_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_SDI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = ddata->videomode;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&spi->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+	sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group);
+err_sysfs:
+	backlight_device_unregister(bldev);
+err_detect:
+err_gpio:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int acx565akm_remove(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
+
+	sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group);
+	backlight_device_unregister(ddata->bl_dev);
+
+	omapdss_unregister_display(dssdev);
+
+	acx565akm_disable(dssdev);
+	acx565akm_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static const struct of_device_id acx565akm_of_match[] = {
+	{ .compatible = "omapdss,sony,acx565akm", },
+	{},
+};
+
+static struct spi_driver acx565akm_driver = {
+	.driver = {
+		.name	= "acx565akm",
+		.owner	= THIS_MODULE,
+		.of_match_table = acx565akm_of_match,
+	},
+	.probe	= acx565akm_probe,
+	.remove	= acx565akm_remove,
+};
+
+module_spi_driver(acx565akm_driver);
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("acx565akm LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
new file mode 100644
index 000000000000..fae6adc005a7
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
@@ -0,0 +1,480 @@
+/*
+ * Toppoly TD028TTEC1 panel support
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Neo 1973 code (jbt6k74.c):
+ * Copyright (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ *
+ * Ported and adapted from Neo 1973 U-Boot by:
+ * H. Nikolaus Schaller <hns@goldelico.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+
+	int data_lines;
+
+	struct omap_video_timings videomode;
+
+	struct spi_device *spi_dev;
+};
+
+static struct omap_video_timings td028ttec1_panel_timings = {
+	.x_res		= 480,
+	.y_res		= 640,
+	.pixelclock	= 22153000,
+	.hfp		= 24,
+	.hsw		= 8,
+	.hbp		= 8,
+	.vfp		= 4,
+	.vsw		= 2,
+	.vbp		= 2,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+};
+
+#define JBT_COMMAND	0x000
+#define JBT_DATA	0x100
+
+static int jbt_ret_write_0(struct panel_drv_data *ddata, u8 reg)
+{
+	int rc;
+	u16 tx_buf = JBT_COMMAND | reg;
+
+	rc = spi_write(ddata->spi_dev, (u8 *)&tx_buf,
+			1*sizeof(u16));
+	if (rc != 0)
+		dev_err(&ddata->spi_dev->dev,
+			"jbt_ret_write_0 spi_write ret %d\n", rc);
+
+	return rc;
+}
+
+static int jbt_reg_write_1(struct panel_drv_data *ddata, u8 reg, u8 data)
+{
+	int rc;
+	u16 tx_buf[2];
+
+	tx_buf[0] = JBT_COMMAND | reg;
+	tx_buf[1] = JBT_DATA | data;
+	rc = spi_write(ddata->spi_dev, (u8 *)tx_buf,
+			2*sizeof(u16));
+	if (rc != 0)
+		dev_err(&ddata->spi_dev->dev,
+			"jbt_reg_write_1 spi_write ret %d\n", rc);
+
+	return rc;
+}
+
+static int jbt_reg_write_2(struct panel_drv_data *ddata, u8 reg, u16 data)
+{
+	int rc;
+	u16 tx_buf[3];
+
+	tx_buf[0] = JBT_COMMAND | reg;
+	tx_buf[1] = JBT_DATA | (data >> 8);
+	tx_buf[2] = JBT_DATA | (data & 0xff);
+
+	rc = spi_write(ddata->spi_dev, (u8 *)tx_buf,
+			3*sizeof(u16));
+
+	if (rc != 0)
+		dev_err(&ddata->spi_dev->dev,
+			"jbt_reg_write_2 spi_write ret %d\n", rc);
+
+	return rc;
+}
+
+enum jbt_register {
+	JBT_REG_SLEEP_IN		= 0x10,
+	JBT_REG_SLEEP_OUT		= 0x11,
+
+	JBT_REG_DISPLAY_OFF		= 0x28,
+	JBT_REG_DISPLAY_ON		= 0x29,
+
+	JBT_REG_RGB_FORMAT		= 0x3a,
+	JBT_REG_QUAD_RATE		= 0x3b,
+
+	JBT_REG_POWER_ON_OFF		= 0xb0,
+	JBT_REG_BOOSTER_OP		= 0xb1,
+	JBT_REG_BOOSTER_MODE		= 0xb2,
+	JBT_REG_BOOSTER_FREQ		= 0xb3,
+	JBT_REG_OPAMP_SYSCLK		= 0xb4,
+	JBT_REG_VSC_VOLTAGE		= 0xb5,
+	JBT_REG_VCOM_VOLTAGE		= 0xb6,
+	JBT_REG_EXT_DISPL		= 0xb7,
+	JBT_REG_OUTPUT_CONTROL		= 0xb8,
+	JBT_REG_DCCLK_DCEV		= 0xb9,
+	JBT_REG_DISPLAY_MODE1		= 0xba,
+	JBT_REG_DISPLAY_MODE2		= 0xbb,
+	JBT_REG_DISPLAY_MODE		= 0xbc,
+	JBT_REG_ASW_SLEW		= 0xbd,
+	JBT_REG_DUMMY_DISPLAY		= 0xbe,
+	JBT_REG_DRIVE_SYSTEM		= 0xbf,
+
+	JBT_REG_SLEEP_OUT_FR_A		= 0xc0,
+	JBT_REG_SLEEP_OUT_FR_B		= 0xc1,
+	JBT_REG_SLEEP_OUT_FR_C		= 0xc2,
+	JBT_REG_SLEEP_IN_LCCNT_D	= 0xc3,
+	JBT_REG_SLEEP_IN_LCCNT_E	= 0xc4,
+	JBT_REG_SLEEP_IN_LCCNT_F	= 0xc5,
+	JBT_REG_SLEEP_IN_LCCNT_G	= 0xc6,
+
+	JBT_REG_GAMMA1_FINE_1		= 0xc7,
+	JBT_REG_GAMMA1_FINE_2		= 0xc8,
+	JBT_REG_GAMMA1_INCLINATION	= 0xc9,
+	JBT_REG_GAMMA1_BLUE_OFFSET	= 0xca,
+
+	JBT_REG_BLANK_CONTROL		= 0xcf,
+	JBT_REG_BLANK_TH_TV		= 0xd0,
+	JBT_REG_CKV_ON_OFF		= 0xd1,
+	JBT_REG_CKV_1_2			= 0xd2,
+	JBT_REG_OEV_TIMING		= 0xd3,
+	JBT_REG_ASW_TIMING_1		= 0xd4,
+	JBT_REG_ASW_TIMING_2		= 0xd5,
+
+	JBT_REG_HCLOCK_VGA		= 0xec,
+	JBT_REG_HCLOCK_QVGA		= 0xed,
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static int td028ttec1_panel_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void td028ttec1_panel_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dpi->disconnect(in, dssdev);
+}
+
+static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_data_lines(in, ddata->data_lines);
+	in->ops.dpi->set_timings(in, &ddata->videomode);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	dev_dbg(dssdev->dev, "td028ttec1_panel_enable() - state %d\n",
+		dssdev->state);
+
+	/* three times command zero */
+	r |= jbt_ret_write_0(ddata, 0x00);
+	usleep_range(1000, 2000);
+	r |= jbt_ret_write_0(ddata, 0x00);
+	usleep_range(1000, 2000);
+	r |= jbt_ret_write_0(ddata, 0x00);
+	usleep_range(1000, 2000);
+
+	if (r) {
+		dev_warn(dssdev->dev, "transfer error\n");
+		goto transfer_err;
+	}
+
+	/* deep standby out */
+	r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x17);
+
+	/* RGB I/F on, RAM write off, QVGA through, SIGCON enable */
+	r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE, 0x80);
+
+	/* Quad mode off */
+	r |= jbt_reg_write_1(ddata, JBT_REG_QUAD_RATE, 0x00);
+
+	/* AVDD on, XVDD on */
+	r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x16);
+
+	/* Output control */
+	r |= jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0xfff9);
+
+	/* Sleep mode off */
+	r |= jbt_ret_write_0(ddata, JBT_REG_SLEEP_OUT);
+
+	/* at this point we have like 50% grey */
+
+	/* initialize register set */
+	r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE1, 0x01);
+	r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE2, 0x00);
+	r |= jbt_reg_write_1(ddata, JBT_REG_RGB_FORMAT, 0x60);
+	r |= jbt_reg_write_1(ddata, JBT_REG_DRIVE_SYSTEM, 0x10);
+	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_OP, 0x56);
+	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_MODE, 0x33);
+	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11);
+	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11);
+	r |= jbt_reg_write_1(ddata, JBT_REG_OPAMP_SYSCLK, 0x02);
+	r |= jbt_reg_write_1(ddata, JBT_REG_VSC_VOLTAGE, 0x2b);
+	r |= jbt_reg_write_1(ddata, JBT_REG_VCOM_VOLTAGE, 0x40);
+	r |= jbt_reg_write_1(ddata, JBT_REG_EXT_DISPL, 0x03);
+	r |= jbt_reg_write_1(ddata, JBT_REG_DCCLK_DCEV, 0x04);
+	/*
+	 * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement
+	 * to avoid red / blue flicker
+	 */
+	r |= jbt_reg_write_1(ddata, JBT_REG_ASW_SLEW, 0x04);
+	r |= jbt_reg_write_1(ddata, JBT_REG_DUMMY_DISPLAY, 0x00);
+
+	r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_A, 0x11);
+	r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_B, 0x11);
+	r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_C, 0x11);
+	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040);
+	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0);
+	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020);
+	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0);
+
+	r |= jbt_reg_write_2(ddata, JBT_REG_GAMMA1_FINE_1, 0x5533);
+	r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_FINE_2, 0x00);
+	r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_INCLINATION, 0x00);
+	r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
+
+	r |= jbt_reg_write_2(ddata, JBT_REG_HCLOCK_VGA, 0x1f0);
+	r |= jbt_reg_write_1(ddata, JBT_REG_BLANK_CONTROL, 0x02);
+	r |= jbt_reg_write_2(ddata, JBT_REG_BLANK_TH_TV, 0x0804);
+
+	r |= jbt_reg_write_1(ddata, JBT_REG_CKV_ON_OFF, 0x01);
+	r |= jbt_reg_write_2(ddata, JBT_REG_CKV_1_2, 0x0000);
+
+	r |= jbt_reg_write_2(ddata, JBT_REG_OEV_TIMING, 0x0d0e);
+	r |= jbt_reg_write_2(ddata, JBT_REG_ASW_TIMING_1, 0x11a4);
+	r |= jbt_reg_write_1(ddata, JBT_REG_ASW_TIMING_2, 0x0e);
+
+	r |= jbt_ret_write_0(ddata, JBT_REG_DISPLAY_ON);
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+transfer_err:
+
+	return r ? -EIO : 0;
+}
+
+static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	dev_dbg(dssdev->dev, "td028ttec1_panel_disable()\n");
+
+	jbt_ret_write_0(ddata, JBT_REG_DISPLAY_OFF);
+	jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0x8002);
+	jbt_ret_write_0(ddata, JBT_REG_SLEEP_IN);
+	jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00);
+
+	in->ops.dpi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->videomode = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dpi->set_timings(in, timings);
+}
+
+static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->videomode;
+}
+
+static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static struct omap_dss_driver td028ttec1_ops = {
+	.connect	= td028ttec1_panel_connect,
+	.disconnect	= td028ttec1_panel_disconnect,
+
+	.enable		= td028ttec1_panel_enable,
+	.disable	= td028ttec1_panel_disable,
+
+	.set_timings	= td028ttec1_panel_set_timings,
+	.get_timings	= td028ttec1_panel_get_timings,
+	.check_timings	= td028ttec1_panel_check_timings,
+};
+
+static int td028ttec1_panel_probe_pdata(struct spi_device *spi)
+{
+	const struct panel_tpo_td028ttec1_platform_data *pdata;
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&spi->dev);
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&spi->dev, "failed to find video source '%s'\n",
+				pdata->source);
+		return -EPROBE_DEFER;
+	}
+
+	ddata->in = in;
+
+	ddata->data_lines = pdata->data_lines;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int td028ttec1_panel_probe(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	dev_dbg(&spi->dev, "%s\n", __func__);
+
+	spi->bits_per_word = 9;
+	spi->mode = SPI_MODE_3;
+
+	r = spi_setup(spi);
+	if (r < 0) {
+		dev_err(&spi->dev, "spi_setup failed: %d\n", r);
+		return r;
+	}
+
+	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&spi->dev, ddata);
+
+	ddata->spi_dev = spi;
+
+	if (dev_get_platdata(&spi->dev)) {
+		r = td028ttec1_panel_probe_pdata(spi);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	ddata->videomode = td028ttec1_panel_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &spi->dev;
+	dssdev->driver = &td028ttec1_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = ddata->videomode;
+	dssdev->phy.dpi.data_lines = ddata->data_lines;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&spi->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int td028ttec1_panel_remove(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(&ddata->spi_dev->dev, "%s\n", __func__);
+
+	omapdss_unregister_display(dssdev);
+
+	td028ttec1_panel_disable(dssdev);
+	td028ttec1_panel_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	return 0;
+}
+
+static struct spi_driver td028ttec1_spi_driver = {
+	.probe		= td028ttec1_panel_probe,
+	.remove		= td028ttec1_panel_remove,
+
+	.driver         = {
+		.name   = "panel-tpo-td028ttec1",
+		.owner  = THIS_MODULE,
+	},
+};
+
+module_spi_driver(td028ttec1_spi_driver);
+
+MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
+MODULE_DESCRIPTION("Toppoly TD028TTEC1 panel driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
new file mode 100644
index 000000000000..875b40263b33
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
@@ -0,0 +1,646 @@
+/*
+ * TPO TD043MTEA1 Panel driver
+ *
+ * Author: Gražvydas Ignotas <notasas@gmail.com>
+ * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+#define TPO_R02_MODE(x)		((x) & 7)
+#define TPO_R02_MODE_800x480	7
+#define TPO_R02_NCLK_RISING	BIT(3)
+#define TPO_R02_HSYNC_HIGH	BIT(4)
+#define TPO_R02_VSYNC_HIGH	BIT(5)
+
+#define TPO_R03_NSTANDBY	BIT(0)
+#define TPO_R03_EN_CP_CLK	BIT(1)
+#define TPO_R03_EN_VGL_PUMP	BIT(2)
+#define TPO_R03_EN_PWM		BIT(3)
+#define TPO_R03_DRIVING_CAP_100	BIT(4)
+#define TPO_R03_EN_PRE_CHARGE	BIT(6)
+#define TPO_R03_SOFTWARE_CTL	BIT(7)
+
+#define TPO_R04_NFLIP_H		BIT(0)
+#define TPO_R04_NFLIP_V		BIT(1)
+#define TPO_R04_CP_CLK_FREQ_1H	BIT(2)
+#define TPO_R04_VGL_FREQ_1H	BIT(4)
+
+#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
+			TPO_R03_EN_VGL_PUMP |  TPO_R03_EN_PWM | \
+			TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
+			TPO_R03_SOFTWARE_CTL)
+
+#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
+			TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
+
+static const u16 tpo_td043_def_gamma[12] = {
+	105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
+};
+
+struct panel_drv_data {
+	struct omap_dss_device	dssdev;
+	struct omap_dss_device *in;
+
+	struct omap_video_timings videomode;
+
+	int data_lines;
+
+	struct spi_device *spi;
+	struct regulator *vcc_reg;
+	int nreset_gpio;
+	u16 gamma[12];
+	u32 mode;
+	u32 hmirror:1;
+	u32 vmirror:1;
+	u32 powered_on:1;
+	u32 spi_suspended:1;
+	u32 power_on_resume:1;
+};
+
+static const struct omap_video_timings tpo_td043_timings = {
+	.x_res		= 800,
+	.y_res		= 480,
+
+	.pixelclock	= 36000000,
+
+	.hsw		= 1,
+	.hfp		= 68,
+	.hbp		= 214,
+
+	.vsw		= 1,
+	.vfp		= 39,
+	.vbp		= 34,
+
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+};
+
+#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
+{
+	struct spi_message	m;
+	struct spi_transfer	xfer;
+	u16			w;
+	int			r;
+
+	spi_message_init(&m);
+
+	memset(&xfer, 0, sizeof(xfer));
+
+	w = ((u16)addr << 10) | (1 << 8) | data;
+	xfer.tx_buf = &w;
+	xfer.bits_per_word = 16;
+	xfer.len = 2;
+	spi_message_add_tail(&xfer, &m);
+
+	r = spi_sync(spi, &m);
+	if (r < 0)
+		dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
+	return r;
+}
+
+static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
+{
+	u8 i, val;
+
+	/* gamma bits [9:8] */
+	for (val = i = 0; i < 4; i++)
+		val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
+	tpo_td043_write(spi, 0x11, val);
+
+	for (val = i = 0; i < 4; i++)
+		val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
+	tpo_td043_write(spi, 0x12, val);
+
+	for (val = i = 0; i < 4; i++)
+		val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
+	tpo_td043_write(spi, 0x13, val);
+
+	/* gamma bits [7:0] */
+	for (val = i = 0; i < 12; i++)
+		tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
+}
+
+static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
+{
+	u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V |
+		TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
+	if (h)
+		reg4 &= ~TPO_R04_NFLIP_H;
+	if (v)
+		reg4 &= ~TPO_R04_NFLIP_V;
+
+	return tpo_td043_write(spi, 4, reg4);
+}
+
+static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
+
+	ddata->hmirror = enable;
+	return tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
+			ddata->vmirror);
+}
+
+static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
+
+	return ddata->hmirror;
+}
+
+static ssize_t tpo_td043_vmirror_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ddata->vmirror);
+}
+
+static ssize_t tpo_td043_vmirror_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	int val;
+	int ret;
+
+	ret = kstrtoint(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	val = !!val;
+
+	ret = tpo_td043_write_mirror(ddata->spi, ddata->hmirror, val);
+	if (ret < 0)
+		return ret;
+
+	ddata->vmirror = val;
+
+	return count;
+}
+
+static ssize_t tpo_td043_mode_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ddata->mode);
+}
+
+static ssize_t tpo_td043_mode_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	long val;
+	int ret;
+
+	ret = kstrtol(buf, 0, &val);
+	if (ret != 0 || val & ~7)
+		return -EINVAL;
+
+	ddata->mode = val;
+
+	val |= TPO_R02_NCLK_RISING;
+	tpo_td043_write(ddata->spi, 2, val);
+
+	return count;
+}
+
+static ssize_t tpo_td043_gamma_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	ssize_t len = 0;
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ddata->gamma); i++) {
+		ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
+				ddata->gamma[i]);
+		if (ret < 0)
+			return ret;
+		len += ret;
+	}
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static ssize_t tpo_td043_gamma_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	unsigned int g[12];
+	int ret;
+	int i;
+
+	ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
+			&g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
+			&g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
+
+	if (ret != 12)
+		return -EINVAL;
+
+	for (i = 0; i < 12; i++)
+		ddata->gamma[i] = g[i];
+
+	tpo_td043_write_gamma(ddata->spi, ddata->gamma);
+
+	return count;
+}
+
+static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
+		tpo_td043_vmirror_show, tpo_td043_vmirror_store);
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
+		tpo_td043_mode_show, tpo_td043_mode_store);
+static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
+		tpo_td043_gamma_show, tpo_td043_gamma_store);
+
+static struct attribute *tpo_td043_attrs[] = {
+	&dev_attr_vmirror.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_gamma.attr,
+	NULL,
+};
+
+static struct attribute_group tpo_td043_attr_group = {
+	.attrs = tpo_td043_attrs,
+};
+
+static int tpo_td043_power_on(struct panel_drv_data *ddata)
+{
+	int r;
+
+	if (ddata->powered_on)
+		return 0;
+
+	r = regulator_enable(ddata->vcc_reg);
+	if (r != 0)
+		return r;
+
+	/* wait for panel to stabilize */
+	msleep(160);
+
+	if (gpio_is_valid(ddata->nreset_gpio))
+		gpio_set_value(ddata->nreset_gpio, 1);
+
+	tpo_td043_write(ddata->spi, 2,
+			TPO_R02_MODE(ddata->mode) | TPO_R02_NCLK_RISING);
+	tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_NORMAL);
+	tpo_td043_write(ddata->spi, 0x20, 0xf0);
+	tpo_td043_write(ddata->spi, 0x21, 0xf0);
+	tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
+			ddata->vmirror);
+	tpo_td043_write_gamma(ddata->spi, ddata->gamma);
+
+	ddata->powered_on = 1;
+	return 0;
+}
+
+static void tpo_td043_power_off(struct panel_drv_data *ddata)
+{
+	if (!ddata->powered_on)
+		return;
+
+	tpo_td043_write(ddata->spi, 3,
+			TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
+
+	if (gpio_is_valid(ddata->nreset_gpio))
+		gpio_set_value(ddata->nreset_gpio, 0);
+
+	/* wait for at least 2 vsyncs before cutting off power */
+	msleep(50);
+
+	tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_STANDBY);
+
+	regulator_disable(ddata->vcc_reg);
+
+	ddata->powered_on = 0;
+}
+
+static int tpo_td043_connect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return 0;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void tpo_td043_disconnect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	in->ops.dpi->disconnect(in, dssdev);
+}
+
+static int tpo_td043_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_data_lines(in, ddata->data_lines);
+	in->ops.dpi->set_timings(in, &ddata->videomode);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	/*
+	 * If we are resuming from system suspend, SPI clocks might not be
+	 * enabled yet, so we'll program the LCD from SPI PM resume callback.
+	 */
+	if (!ddata->spi_suspended) {
+		r = tpo_td043_power_on(ddata);
+		if (r) {
+			in->ops.dpi->disable(in);
+			return r;
+		}
+	}
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void tpo_td043_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	in->ops.dpi->disable(in);
+
+	if (!ddata->spi_suspended)
+		tpo_td043_power_off(ddata);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	ddata->videomode = *timings;
+	dssdev->panel.timings = *timings;
+
+	in->ops.dpi->set_timings(in, timings);
+}
+
+static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	*timings = ddata->videomode;
+}
+
+static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static struct omap_dss_driver tpo_td043_ops = {
+	.connect	= tpo_td043_connect,
+	.disconnect	= tpo_td043_disconnect,
+
+	.enable		= tpo_td043_enable,
+	.disable	= tpo_td043_disable,
+
+	.set_timings	= tpo_td043_set_timings,
+	.get_timings	= tpo_td043_get_timings,
+	.check_timings	= tpo_td043_check_timings,
+
+	.set_mirror	= tpo_td043_set_hmirror,
+	.get_mirror	= tpo_td043_get_hmirror,
+
+	.get_resolution	= omapdss_default_get_resolution,
+};
+
+
+static int tpo_td043_probe_pdata(struct spi_device *spi)
+{
+	const struct panel_tpo_td043mtea1_platform_data *pdata;
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev, *in;
+
+	pdata = dev_get_platdata(&spi->dev);
+
+	ddata->nreset_gpio = pdata->nreset_gpio;
+
+	in = omap_dss_find_output(pdata->source);
+	if (in == NULL) {
+		dev_err(&spi->dev, "failed to find video source '%s'\n",
+				pdata->source);
+		return -EPROBE_DEFER;
+	}
+	ddata->in = in;
+
+	ddata->data_lines = pdata->data_lines;
+
+	dssdev = &ddata->dssdev;
+	dssdev->name = pdata->name;
+
+	return 0;
+}
+
+static int tpo_td043_probe(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	int r;
+
+	dev_dbg(&spi->dev, "%s\n", __func__);
+
+	spi->bits_per_word = 16;
+	spi->mode = SPI_MODE_0;
+
+	r = spi_setup(spi);
+	if (r < 0) {
+		dev_err(&spi->dev, "spi_setup failed: %d\n", r);
+		return r;
+	}
+
+	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&spi->dev, ddata);
+
+	ddata->spi = spi;
+
+	if (dev_get_platdata(&spi->dev)) {
+		r = tpo_td043_probe_pdata(spi);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	ddata->mode = TPO_R02_MODE_800x480;
+	memcpy(ddata->gamma, tpo_td043_def_gamma, sizeof(ddata->gamma));
+
+	ddata->vcc_reg = devm_regulator_get(&spi->dev, "vcc");
+	if (IS_ERR(ddata->vcc_reg)) {
+		dev_err(&spi->dev, "failed to get LCD VCC regulator\n");
+		r = PTR_ERR(ddata->vcc_reg);
+		goto err_regulator;
+	}
+
+	if (gpio_is_valid(ddata->nreset_gpio)) {
+		r = devm_gpio_request_one(&spi->dev,
+				ddata->nreset_gpio, GPIOF_OUT_INIT_LOW,
+				"lcd reset");
+		if (r < 0) {
+			dev_err(&spi->dev, "couldn't request reset GPIO\n");
+			goto err_gpio_req;
+		}
+	}
+
+	r = sysfs_create_group(&spi->dev.kobj, &tpo_td043_attr_group);
+	if (r) {
+		dev_err(&spi->dev, "failed to create sysfs files\n");
+		goto err_sysfs;
+	}
+
+	ddata->videomode = tpo_td043_timings;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &spi->dev;
+	dssdev->driver = &tpo_td043_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->owner = THIS_MODULE;
+	dssdev->panel.timings = ddata->videomode;
+
+	r = omapdss_register_display(dssdev);
+	if (r) {
+		dev_err(&spi->dev, "Failed to register panel\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+	sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
+err_sysfs:
+err_gpio_req:
+err_regulator:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int tpo_td043_remove(struct spi_device *spi)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+	struct omap_dss_device *in = ddata->in;
+
+	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
+
+	omapdss_unregister_display(dssdev);
+
+	tpo_td043_disable(dssdev);
+	tpo_td043_disconnect(dssdev);
+
+	omap_dss_put_device(in);
+
+	sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tpo_td043_spi_suspend(struct device *dev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", ddata);
+
+	ddata->power_on_resume = ddata->powered_on;
+	tpo_td043_power_off(ddata);
+	ddata->spi_suspended = 1;
+
+	return 0;
+}
+
+static int tpo_td043_spi_resume(struct device *dev)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(dev);
+	int ret;
+
+	dev_dbg(dev, "tpo_td043_spi_resume\n");
+
+	if (ddata->power_on_resume) {
+		ret = tpo_td043_power_on(ddata);
+		if (ret)
+			return ret;
+	}
+	ddata->spi_suspended = 0;
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
+	tpo_td043_spi_suspend, tpo_td043_spi_resume);
+
+static struct spi_driver tpo_td043_spi_driver = {
+	.driver = {
+		.name	= "panel-tpo-td043mtea1",
+		.owner	= THIS_MODULE,
+		.pm	= &tpo_td043_spi_pm,
+	},
+	.probe	= tpo_td043_probe,
+	.remove	= tpo_td043_remove,
+};
+
+module_spi_driver(tpo_td043_spi_driver);
+
+MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
+MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/dss/Kconfig b/drivers/video/fbdev/omap2/dss/Kconfig
new file mode 100644
index 000000000000..dde4281663b1
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/Kconfig
@@ -0,0 +1,121 @@
+menuconfig OMAP2_DSS
+        tristate "OMAP2+ Display Subsystem support"
+	select VIDEOMODE_HELPERS
+        help
+	  OMAP2+ Display Subsystem support.
+
+if OMAP2_DSS
+
+config OMAP2_DSS_DEBUG
+	bool "Debug support"
+	default n
+	help
+	  This enables printing of debug messages. Alternatively, debug messages
+	  can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
+	  appropriate flags in <debugfs>/dynamic_debug/control.
+
+config OMAP2_DSS_DEBUGFS
+	bool "Debugfs filesystem support"
+	depends on DEBUG_FS
+	default n
+	help
+	  This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
+	  querying about clock configuration and register configuration of dss,
+	  dispc, dsi, hdmi and rfbi.
+
+config OMAP2_DSS_COLLECT_IRQ_STATS
+	bool "Collect DSS IRQ statistics"
+	depends on OMAP2_DSS_DEBUGFS
+	default n
+	help
+	  Collect DSS IRQ statistics, printable via debugfs.
+
+	  The statistics can be found from
+	  <debugfs>/omapdss/dispc_irq for DISPC interrupts, and
+	  <debugfs>/omapdss/dsi_irq for DSI interrupts.
+
+config OMAP2_DSS_DPI
+	bool "DPI support"
+	default y
+	help
+	  DPI Interface. This is the Parallel Display Interface.
+
+config OMAP2_DSS_RFBI
+	bool "RFBI support"
+	depends on BROKEN
+        default n
+	help
+	  MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
+	  Instrument's terminology).
+
+	  DBI is a bus between the host processor and a peripheral,
+	  such as a display or a framebuffer chip.
+
+	  See http://www.mipi.org/ for DBI specifications.
+
+config OMAP2_DSS_VENC
+	bool "VENC support"
+        default y
+	help
+	  OMAP Video Encoder support for S-Video and composite TV-out.
+
+config OMAP4_DSS_HDMI
+	bool "HDMI support"
+        default y
+	help
+	  HDMI Interface. This adds the High Definition Multimedia Interface.
+	  See http://www.hdmi.org/ for HDMI specification.
+
+config OMAP4_DSS_HDMI_AUDIO
+	bool
+
+config OMAP2_DSS_SDI
+	bool "SDI support"
+        default n
+	help
+	  SDI (Serial Display Interface) support.
+
+	  SDI is a high speed one-way display serial bus between the host
+	  processor and a display.
+
+config OMAP2_DSS_DSI
+	bool "DSI support"
+        default n
+	help
+	  MIPI DSI (Display Serial Interface) support.
+
+	  DSI is a high speed half-duplex serial interface between the host
+	  processor and a peripheral, such as a display or a framebuffer chip.
+
+	  See http://www.mipi.org/ for DSI specifications.
+
+config OMAP2_DSS_MIN_FCK_PER_PCK
+	int "Minimum FCK/PCK ratio (for scaling)"
+	range 0 32
+	default 0
+	help
+	  This can be used to adjust the minimum FCK/PCK ratio.
+
+	  With this you can make sure that DISPC FCK is at least
+	  n x PCK. Video plane scaling requires higher FCK than
+	  normally.
+
+	  If this is set to 0, there's no extra constraint on the
+	  DISPC FCK. However, the FCK will at minimum be
+	  2xPCK (if active matrix) or 3xPCK (if passive matrix).
+
+	  Max FCK is 173MHz, so this doesn't work if your PCK
+	  is very high.
+
+config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
+	bool "Sleep 20ms after VENC reset"
+	default y
+	help
+	  There is a 20ms sleep after VENC reset which seemed to fix the
+	  reset. The reason for the bug is unclear, and it's also unclear
+	  on what platforms this happens.
+
+	  This option enables the sleep, and is enabled by default. You can
+	  disable the sleep if it doesn't cause problems on your platform.
+
+endif
diff --git a/drivers/video/fbdev/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile
new file mode 100644
index 000000000000..8aec8bda27cc
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/Makefile
@@ -0,0 +1,15 @@
+obj-$(CONFIG_OMAP2_DSS) += omapdss.o
+# Core DSS files
+omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
+	output.o dss-of.o
+# DSS compat layer files
+omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
+	dispc-compat.o display-sysfs.o
+omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
+omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
+omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
+omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
+omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
+omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_common.o hdmi_wp.o hdmi_pll.o \
+	hdmi_phy.o hdmi4_core.o
+ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/fbdev/omap2/dss/apply.c b/drivers/video/fbdev/omap2/dss/apply.c
new file mode 100644
index 000000000000..0a0b084ce65d
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/apply.c
@@ -0,0 +1,1700 @@
+/*
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "APPLY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "dispc-compat.h"
+
+/*
+ * We have 4 levels of cache for the dispc settings. First two are in SW and
+ * the latter two in HW.
+ *
+ *       set_info()
+ *          v
+ * +--------------------+
+ * |     user_info      |
+ * +--------------------+
+ *          v
+ *        apply()
+ *          v
+ * +--------------------+
+ * |       info         |
+ * +--------------------+
+ *          v
+ *      write_regs()
+ *          v
+ * +--------------------+
+ * |  shadow registers  |
+ * +--------------------+
+ *          v
+ * VFP or lcd/digit_enable
+ *          v
+ * +--------------------+
+ * |      registers     |
+ * +--------------------+
+ */
+
+struct ovl_priv_data {
+
+	bool user_info_dirty;
+	struct omap_overlay_info user_info;
+
+	bool info_dirty;
+	struct omap_overlay_info info;
+
+	bool shadow_info_dirty;
+
+	bool extra_info_dirty;
+	bool shadow_extra_info_dirty;
+
+	bool enabled;
+	u32 fifo_low, fifo_high;
+
+	/*
+	 * True if overlay is to be enabled. Used to check and calculate configs
+	 * for the overlay before it is enabled in the HW.
+	 */
+	bool enabling;
+};
+
+struct mgr_priv_data {
+
+	bool user_info_dirty;
+	struct omap_overlay_manager_info user_info;
+
+	bool info_dirty;
+	struct omap_overlay_manager_info info;
+
+	bool shadow_info_dirty;
+
+	/* If true, GO bit is up and shadow registers cannot be written.
+	 * Never true for manual update displays */
+	bool busy;
+
+	/* If true, dispc output is enabled */
+	bool updating;
+
+	/* If true, a display is enabled using this manager */
+	bool enabled;
+
+	bool extra_info_dirty;
+	bool shadow_extra_info_dirty;
+
+	struct omap_video_timings timings;
+	struct dss_lcd_mgr_config lcd_config;
+
+	void (*framedone_handler)(void *);
+	void *framedone_handler_data;
+};
+
+static struct {
+	struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
+	struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
+
+	bool irq_enabled;
+} dss_data;
+
+/* protects dss_data */
+static spinlock_t data_lock;
+/* lock for blocking functions */
+static DEFINE_MUTEX(apply_lock);
+static DECLARE_COMPLETION(extra_updated_completion);
+
+static void dss_register_vsync_isr(void);
+
+static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
+{
+	return &dss_data.ovl_priv_data_array[ovl->id];
+}
+
+static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
+{
+	return &dss_data.mgr_priv_data_array[mgr->id];
+}
+
+static void apply_init_priv(void)
+{
+	const int num_ovls = dss_feat_get_num_ovls();
+	struct mgr_priv_data *mp;
+	int i;
+
+	spin_lock_init(&data_lock);
+
+	for (i = 0; i < num_ovls; ++i) {
+		struct ovl_priv_data *op;
+
+		op = &dss_data.ovl_priv_data_array[i];
+
+		op->info.color_mode = OMAP_DSS_COLOR_RGB16;
+		op->info.rotation_type = OMAP_DSS_ROT_DMA;
+
+		op->info.global_alpha = 255;
+
+		switch (i) {
+		case 0:
+			op->info.zorder = 0;
+			break;
+		case 1:
+			op->info.zorder =
+				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
+			break;
+		case 2:
+			op->info.zorder =
+				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
+			break;
+		case 3:
+			op->info.zorder =
+				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
+			break;
+		}
+
+		op->user_info = op->info;
+	}
+
+	/*
+	 * Initialize some of the lcd_config fields for TV manager, this lets
+	 * us prevent checking if the manager is LCD or TV at some places
+	 */
+	mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
+
+	mp->lcd_config.video_port_width = 24;
+	mp->lcd_config.clock_info.lck_div = 1;
+	mp->lcd_config.clock_info.pck_div = 1;
+}
+
+/*
+ * A LCD manager's stallmode decides whether it is in manual or auto update. TV
+ * manager is always auto update, stallmode field for TV manager is false by
+ * default
+ */
+static bool ovl_manual_update(struct omap_overlay *ovl)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
+
+	return mp->lcd_config.stallmode;
+}
+
+static bool mgr_manual_update(struct omap_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	return mp->lcd_config.stallmode;
+}
+
+static int dss_check_settings_low(struct omap_overlay_manager *mgr,
+		bool applying)
+{
+	struct omap_overlay_info *oi;
+	struct omap_overlay_manager_info *mi;
+	struct omap_overlay *ovl;
+	struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
+	struct ovl_priv_data *op;
+	struct mgr_priv_data *mp;
+
+	mp = get_mgr_priv(mgr);
+
+	if (!mp->enabled)
+		return 0;
+
+	if (applying && mp->user_info_dirty)
+		mi = &mp->user_info;
+	else
+		mi = &mp->info;
+
+	/* collect the infos to be tested into the array */
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
+
+		if (!op->enabled && !op->enabling)
+			oi = NULL;
+		else if (applying && op->user_info_dirty)
+			oi = &op->user_info;
+		else
+			oi = &op->info;
+
+		ois[ovl->id] = oi;
+	}
+
+	return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
+}
+
+/*
+ * check manager and overlay settings using overlay_info from data->info
+ */
+static int dss_check_settings(struct omap_overlay_manager *mgr)
+{
+	return dss_check_settings_low(mgr, false);
+}
+
+/*
+ * check manager and overlay settings using overlay_info from ovl->info if
+ * dirty and from data->info otherwise
+ */
+static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
+{
+	return dss_check_settings_low(mgr, true);
+}
+
+static bool need_isr(void)
+{
+	const int num_mgrs = dss_feat_get_num_mgrs();
+	int i;
+
+	for (i = 0; i < num_mgrs; ++i) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+		struct omap_overlay *ovl;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mp->enabled)
+			continue;
+
+		if (mgr_manual_update(mgr)) {
+			/* to catch FRAMEDONE */
+			if (mp->updating)
+				return true;
+		} else {
+			/* to catch GO bit going down */
+			if (mp->busy)
+				return true;
+
+			/* to write new values to registers */
+			if (mp->info_dirty)
+				return true;
+
+			/* to set GO bit */
+			if (mp->shadow_info_dirty)
+				return true;
+
+			/*
+			 * NOTE: we don't check extra_info flags for disabled
+			 * managers, once the manager is enabled, the extra_info
+			 * related manager changes will be taken in by HW.
+			 */
+
+			/* to write new values to registers */
+			if (mp->extra_info_dirty)
+				return true;
+
+			/* to set GO bit */
+			if (mp->shadow_extra_info_dirty)
+				return true;
+
+			list_for_each_entry(ovl, &mgr->overlays, list) {
+				struct ovl_priv_data *op;
+
+				op = get_ovl_priv(ovl);
+
+				/*
+				 * NOTE: we check extra_info flags even for
+				 * disabled overlays, as extra_infos need to be
+				 * always written.
+				 */
+
+				/* to write new values to registers */
+				if (op->extra_info_dirty)
+					return true;
+
+				/* to set GO bit */
+				if (op->shadow_extra_info_dirty)
+					return true;
+
+				if (!op->enabled)
+					continue;
+
+				/* to write new values to registers */
+				if (op->info_dirty)
+					return true;
+
+				/* to set GO bit */
+				if (op->shadow_info_dirty)
+					return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+static bool need_go(struct omap_overlay_manager *mgr)
+{
+	struct omap_overlay *ovl;
+	struct mgr_priv_data *mp;
+	struct ovl_priv_data *op;
+
+	mp = get_mgr_priv(mgr);
+
+	if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
+		return true;
+
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
+		if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
+			return true;
+	}
+
+	return false;
+}
+
+/* returns true if an extra_info field is currently being updated */
+static bool extra_info_update_ongoing(void)
+{
+	const int num_mgrs = dss_feat_get_num_mgrs();
+	int i;
+
+	for (i = 0; i < num_mgrs; ++i) {
+		struct omap_overlay_manager *mgr;
+		struct omap_overlay *ovl;
+		struct mgr_priv_data *mp;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mp->enabled)
+			continue;
+
+		if (!mp->updating)
+			continue;
+
+		if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
+			return true;
+
+		list_for_each_entry(ovl, &mgr->overlays, list) {
+			struct ovl_priv_data *op = get_ovl_priv(ovl);
+
+			if (op->extra_info_dirty || op->shadow_extra_info_dirty)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+/* wait until no extra_info updates are pending */
+static void wait_pending_extra_info_updates(void)
+{
+	bool updating;
+	unsigned long flags;
+	unsigned long t;
+	int r;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	updating = extra_info_update_ongoing();
+
+	if (!updating) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		return;
+	}
+
+	init_completion(&extra_updated_completion);
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	t = msecs_to_jiffies(500);
+	r = wait_for_completion_timeout(&extra_updated_completion, t);
+	if (r == 0)
+		DSSWARN("timeout in wait_pending_extra_info_updates\n");
+}
+
+static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
+{
+	struct omap_dss_device *dssdev;
+
+	dssdev = mgr->output;
+	if (dssdev == NULL)
+		return NULL;
+
+	while (dssdev->dst)
+		dssdev = dssdev->dst;
+
+	if (dssdev->driver)
+		return dssdev;
+	else
+		return NULL;
+}
+
+static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
+{
+	return ovl->manager ? dss_mgr_get_device(ovl->manager) : NULL;
+}
+
+static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
+{
+	unsigned long timeout = msecs_to_jiffies(500);
+	u32 irq;
+	int r;
+
+	if (mgr->output == NULL)
+		return -ENODEV;
+
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
+	switch (mgr->output->id) {
+	case OMAP_DSS_OUTPUT_VENC:
+		irq = DISPC_IRQ_EVSYNC_ODD;
+		break;
+	case OMAP_DSS_OUTPUT_HDMI:
+		irq = DISPC_IRQ_EVSYNC_EVEN;
+		break;
+	default:
+		irq = dispc_mgr_get_vsync_irq(mgr->id);
+		break;
+	}
+
+	r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+
+	dispc_runtime_put();
+
+	return r;
+}
+
+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
+{
+	unsigned long timeout = msecs_to_jiffies(500);
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	u32 irq;
+	unsigned long flags;
+	int r;
+	int i;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (mgr_manual_update(mgr)) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		return 0;
+	}
+
+	if (!mp->enabled) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		return 0;
+	}
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
+	irq = dispc_mgr_get_vsync_irq(mgr->id);
+
+	i = 0;
+	while (1) {
+		bool shadow_dirty, dirty;
+
+		spin_lock_irqsave(&data_lock, flags);
+		dirty = mp->info_dirty;
+		shadow_dirty = mp->shadow_info_dirty;
+		spin_unlock_irqrestore(&data_lock, flags);
+
+		if (!dirty && !shadow_dirty) {
+			r = 0;
+			break;
+		}
+
+		/* 4 iterations is the worst case:
+		 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
+		 * 2 - first VSYNC, dirty = true
+		 * 3 - dirty = false, shadow_dirty = true
+		 * 4 - shadow_dirty = false */
+		if (i++ == 3) {
+			DSSERR("mgr(%d)->wait_for_go() not finishing\n",
+					mgr->id);
+			r = 0;
+			break;
+		}
+
+		r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+		if (r == -ERESTARTSYS)
+			break;
+
+		if (r) {
+			DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
+			break;
+		}
+	}
+
+	dispc_runtime_put();
+
+	return r;
+}
+
+static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+{
+	unsigned long timeout = msecs_to_jiffies(500);
+	struct ovl_priv_data *op;
+	struct mgr_priv_data *mp;
+	u32 irq;
+	unsigned long flags;
+	int r;
+	int i;
+
+	if (!ovl->manager)
+		return 0;
+
+	mp = get_mgr_priv(ovl->manager);
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (ovl_manual_update(ovl)) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		return 0;
+	}
+
+	if (!mp->enabled) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		return 0;
+	}
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
+	irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
+
+	op = get_ovl_priv(ovl);
+	i = 0;
+	while (1) {
+		bool shadow_dirty, dirty;
+
+		spin_lock_irqsave(&data_lock, flags);
+		dirty = op->info_dirty;
+		shadow_dirty = op->shadow_info_dirty;
+		spin_unlock_irqrestore(&data_lock, flags);
+
+		if (!dirty && !shadow_dirty) {
+			r = 0;
+			break;
+		}
+
+		/* 4 iterations is the worst case:
+		 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
+		 * 2 - first VSYNC, dirty = true
+		 * 3 - dirty = false, shadow_dirty = true
+		 * 4 - shadow_dirty = false */
+		if (i++ == 3) {
+			DSSERR("ovl(%d)->wait_for_go() not finishing\n",
+					ovl->id);
+			r = 0;
+			break;
+		}
+
+		r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+		if (r == -ERESTARTSYS)
+			break;
+
+		if (r) {
+			DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
+			break;
+		}
+	}
+
+	dispc_runtime_put();
+
+	return r;
+}
+
+static void dss_ovl_write_regs(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	struct omap_overlay_info *oi;
+	bool replication;
+	struct mgr_priv_data *mp;
+	int r;
+
+	DSSDBG("writing ovl %d regs\n", ovl->id);
+
+	if (!op->enabled || !op->info_dirty)
+		return;
+
+	oi = &op->info;
+
+	mp = get_mgr_priv(ovl->manager);
+
+	replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
+
+	r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
+	if (r) {
+		/*
+		 * We can't do much here, as this function can be called from
+		 * vsync interrupt.
+		 */
+		DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
+
+		/* This will leave fifo configurations in a nonoptimal state */
+		op->enabled = false;
+		dispc_ovl_enable(ovl->id, false);
+		return;
+	}
+
+	op->info_dirty = false;
+	if (mp->updating)
+		op->shadow_info_dirty = true;
+}
+
+static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	struct mgr_priv_data *mp;
+
+	DSSDBG("writing ovl %d regs extra\n", ovl->id);
+
+	if (!op->extra_info_dirty)
+		return;
+
+	/* note: write also when op->enabled == false, so that the ovl gets
+	 * disabled */
+
+	dispc_ovl_enable(ovl->id, op->enabled);
+	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
+
+	mp = get_mgr_priv(ovl->manager);
+
+	op->extra_info_dirty = false;
+	if (mp->updating)
+		op->shadow_extra_info_dirty = true;
+}
+
+static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	struct omap_overlay *ovl;
+
+	DSSDBG("writing mgr %d regs\n", mgr->id);
+
+	if (!mp->enabled)
+		return;
+
+	WARN_ON(mp->busy);
+
+	/* Commit overlay settings */
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		dss_ovl_write_regs(ovl);
+		dss_ovl_write_regs_extra(ovl);
+	}
+
+	if (mp->info_dirty) {
+		dispc_mgr_setup(mgr->id, &mp->info);
+
+		mp->info_dirty = false;
+		if (mp->updating)
+			mp->shadow_info_dirty = true;
+	}
+}
+
+static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	DSSDBG("writing mgr %d regs extra\n", mgr->id);
+
+	if (!mp->extra_info_dirty)
+		return;
+
+	dispc_mgr_set_timings(mgr->id, &mp->timings);
+
+	/* lcd_config parameters */
+	if (dss_mgr_is_lcd(mgr->id))
+		dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
+
+	mp->extra_info_dirty = false;
+	if (mp->updating)
+		mp->shadow_extra_info_dirty = true;
+}
+
+static void dss_write_regs(void)
+{
+	const int num_mgrs = omap_dss_get_num_overlay_managers();
+	int i;
+
+	for (i = 0; i < num_mgrs; ++i) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+		int r;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
+			continue;
+
+		r = dss_check_settings(mgr);
+		if (r) {
+			DSSERR("cannot write registers for manager %s: "
+					"illegal configuration\n", mgr->name);
+			continue;
+		}
+
+		dss_mgr_write_regs(mgr);
+		dss_mgr_write_regs_extra(mgr);
+	}
+}
+
+static void dss_set_go_bits(void)
+{
+	const int num_mgrs = omap_dss_get_num_overlay_managers();
+	int i;
+
+	for (i = 0; i < num_mgrs; ++i) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
+			continue;
+
+		if (!need_go(mgr))
+			continue;
+
+		mp->busy = true;
+
+		if (!dss_data.irq_enabled && need_isr())
+			dss_register_vsync_isr();
+
+		dispc_mgr_go(mgr->id);
+	}
+
+}
+
+static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
+{
+	struct omap_overlay *ovl;
+	struct mgr_priv_data *mp;
+	struct ovl_priv_data *op;
+
+	mp = get_mgr_priv(mgr);
+	mp->shadow_info_dirty = false;
+	mp->shadow_extra_info_dirty = false;
+
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
+		op->shadow_info_dirty = false;
+		op->shadow_extra_info_dirty = false;
+	}
+}
+
+static int dss_mgr_connect_compat(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dst)
+{
+	return mgr->set_output(mgr, dst);
+}
+
+static void dss_mgr_disconnect_compat(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dst)
+{
+	mgr->unset_output(mgr);
+}
+
+static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	WARN_ON(mp->updating);
+
+	r = dss_check_settings(mgr);
+	if (r) {
+		DSSERR("cannot start manual update: illegal configuration\n");
+		spin_unlock_irqrestore(&data_lock, flags);
+		return;
+	}
+
+	dss_mgr_write_regs(mgr);
+	dss_mgr_write_regs_extra(mgr);
+
+	mp->updating = true;
+
+	if (!dss_data.irq_enabled && need_isr())
+		dss_register_vsync_isr();
+
+	dispc_mgr_enable_sync(mgr->id);
+
+	spin_unlock_irqrestore(&data_lock, flags);
+}
+
+static void dss_apply_irq_handler(void *data, u32 mask);
+
+static void dss_register_vsync_isr(void)
+{
+	const int num_mgrs = dss_feat_get_num_mgrs();
+	u32 mask;
+	int r, i;
+
+	mask = 0;
+	for (i = 0; i < num_mgrs; ++i)
+		mask |= dispc_mgr_get_vsync_irq(i);
+
+	for (i = 0; i < num_mgrs; ++i)
+		mask |= dispc_mgr_get_framedone_irq(i);
+
+	r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
+	WARN_ON(r);
+
+	dss_data.irq_enabled = true;
+}
+
+static void dss_unregister_vsync_isr(void)
+{
+	const int num_mgrs = dss_feat_get_num_mgrs();
+	u32 mask;
+	int r, i;
+
+	mask = 0;
+	for (i = 0; i < num_mgrs; ++i)
+		mask |= dispc_mgr_get_vsync_irq(i);
+
+	for (i = 0; i < num_mgrs; ++i)
+		mask |= dispc_mgr_get_framedone_irq(i);
+
+	r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
+	WARN_ON(r);
+
+	dss_data.irq_enabled = false;
+}
+
+static void dss_apply_irq_handler(void *data, u32 mask)
+{
+	const int num_mgrs = dss_feat_get_num_mgrs();
+	int i;
+	bool extra_updating;
+
+	spin_lock(&data_lock);
+
+	/* clear busy, updating flags, shadow_dirty flags */
+	for (i = 0; i < num_mgrs; i++) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mp->enabled)
+			continue;
+
+		mp->updating = dispc_mgr_is_enabled(i);
+
+		if (!mgr_manual_update(mgr)) {
+			bool was_busy = mp->busy;
+			mp->busy = dispc_mgr_go_busy(i);
+
+			if (was_busy && !mp->busy)
+				mgr_clear_shadow_dirty(mgr);
+		}
+	}
+
+	dss_write_regs();
+	dss_set_go_bits();
+
+	extra_updating = extra_info_update_ongoing();
+	if (!extra_updating)
+		complete_all(&extra_updated_completion);
+
+	/* call framedone handlers for manual update displays */
+	for (i = 0; i < num_mgrs; i++) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mgr_manual_update(mgr) || !mp->framedone_handler)
+			continue;
+
+		if (mask & dispc_mgr_get_framedone_irq(i))
+			mp->framedone_handler(mp->framedone_handler_data);
+	}
+
+	if (!need_isr())
+		dss_unregister_vsync_isr();
+
+	spin_unlock(&data_lock);
+}
+
+static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op;
+
+	op = get_ovl_priv(ovl);
+
+	if (!op->user_info_dirty)
+		return;
+
+	op->user_info_dirty = false;
+	op->info_dirty = true;
+	op->info = op->user_info;
+}
+
+static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp;
+
+	mp = get_mgr_priv(mgr);
+
+	if (!mp->user_info_dirty)
+		return;
+
+	mp->user_info_dirty = false;
+	mp->info_dirty = true;
+	mp->info = mp->user_info;
+}
+
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+{
+	unsigned long flags;
+	struct omap_overlay *ovl;
+	int r;
+
+	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	r = dss_check_settings_apply(mgr);
+	if (r) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("failed to apply settings: illegal configuration.\n");
+		return r;
+	}
+
+	/* Configure overlays */
+	list_for_each_entry(ovl, &mgr->overlays, list)
+		omap_dss_mgr_apply_ovl(ovl);
+
+	/* Configure manager */
+	omap_dss_mgr_apply_mgr(mgr);
+
+	dss_write_regs();
+	dss_set_go_bits();
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	return 0;
+}
+
+static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
+{
+	struct ovl_priv_data *op;
+
+	op = get_ovl_priv(ovl);
+
+	if (op->enabled == enable)
+		return;
+
+	op->enabled = enable;
+	op->extra_info_dirty = true;
+}
+
+static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
+		u32 fifo_low, u32 fifo_high)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+
+	if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
+		return;
+
+	op->fifo_low = fifo_low;
+	op->fifo_high = fifo_high;
+	op->extra_info_dirty = true;
+}
+
+static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	u32 fifo_low, fifo_high;
+	bool use_fifo_merge = false;
+
+	if (!op->enabled && !op->enabling)
+		return;
+
+	dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
+			use_fifo_merge, ovl_manual_update(ovl));
+
+	dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
+}
+
+static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
+{
+	struct omap_overlay *ovl;
+	struct mgr_priv_data *mp;
+
+	mp = get_mgr_priv(mgr);
+
+	if (!mp->enabled)
+		return;
+
+	list_for_each_entry(ovl, &mgr->overlays, list)
+		dss_ovl_setup_fifo(ovl);
+}
+
+static void dss_setup_fifos(void)
+{
+	const int num_mgrs = omap_dss_get_num_overlay_managers();
+	struct omap_overlay_manager *mgr;
+	int i;
+
+	for (i = 0; i < num_mgrs; ++i) {
+		mgr = omap_dss_get_overlay_manager(i);
+		dss_mgr_setup_fifos(mgr);
+	}
+}
+
+static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	unsigned long flags;
+	int r;
+
+	mutex_lock(&apply_lock);
+
+	if (mp->enabled)
+		goto out;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	mp->enabled = true;
+
+	r = dss_check_settings(mgr);
+	if (r) {
+		DSSERR("failed to enable manager %d: check_settings failed\n",
+				mgr->id);
+		goto err;
+	}
+
+	dss_setup_fifos();
+
+	dss_write_regs();
+	dss_set_go_bits();
+
+	if (!mgr_manual_update(mgr))
+		mp->updating = true;
+
+	if (!dss_data.irq_enabled && need_isr())
+		dss_register_vsync_isr();
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	if (!mgr_manual_update(mgr))
+		dispc_mgr_enable_sync(mgr->id);
+
+out:
+	mutex_unlock(&apply_lock);
+
+	return 0;
+
+err:
+	mp->enabled = false;
+	spin_unlock_irqrestore(&data_lock, flags);
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	unsigned long flags;
+
+	mutex_lock(&apply_lock);
+
+	if (!mp->enabled)
+		goto out;
+
+	if (!mgr_manual_update(mgr))
+		dispc_mgr_disable_sync(mgr->id);
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	mp->updating = false;
+	mp->enabled = false;
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+out:
+	mutex_unlock(&apply_lock);
+}
+
+static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
+		struct omap_overlay_manager_info *info)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	unsigned long flags;
+	int r;
+
+	r = dss_mgr_simple_check(mgr, info);
+	if (r)
+		return r;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	mp->user_info = *info;
+	mp->user_info_dirty = true;
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	return 0;
+}
+
+static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
+		struct omap_overlay_manager_info *info)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	*info = mp->user_info;
+
+	spin_unlock_irqrestore(&data_lock, flags);
+}
+
+static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *output)
+{
+	int r;
+
+	mutex_lock(&apply_lock);
+
+	if (mgr->output) {
+		DSSERR("manager %s is already connected to an output\n",
+			mgr->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	if ((mgr->supported_outputs & output->id) == 0) {
+		DSSERR("output does not support manager %s\n",
+			mgr->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	output->manager = mgr;
+	mgr->output = output;
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+err:
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
+{
+	int r;
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	unsigned long flags;
+
+	mutex_lock(&apply_lock);
+
+	if (!mgr->output) {
+		DSSERR("failed to unset output, output not set\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (mp->enabled) {
+		DSSERR("output can't be unset when manager is enabled\n");
+		r = -EINVAL;
+		goto err1;
+	}
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	mgr->output->manager = NULL;
+	mgr->output = NULL;
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+err1:
+	spin_unlock_irqrestore(&data_lock, flags);
+err:
+	mutex_unlock(&apply_lock);
+
+	return r;
+}
+
+static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	mp->timings = *timings;
+	mp->extra_info_dirty = true;
+}
+
+static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings)
+{
+	unsigned long flags;
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (mp->updating) {
+		DSSERR("cannot set timings for %s: manager needs to be disabled\n",
+			mgr->name);
+		goto out;
+	}
+
+	dss_apply_mgr_timings(mgr, timings);
+out:
+	spin_unlock_irqrestore(&data_lock, flags);
+}
+
+static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
+		const struct dss_lcd_mgr_config *config)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	mp->lcd_config = *config;
+	mp->extra_info_dirty = true;
+}
+
+static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
+		const struct dss_lcd_mgr_config *config)
+{
+	unsigned long flags;
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (mp->enabled) {
+		DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
+			mgr->name);
+		goto out;
+	}
+
+	dss_apply_mgr_lcd_config(mgr, config);
+out:
+	spin_unlock_irqrestore(&data_lock, flags);
+}
+
+static int dss_ovl_set_info(struct omap_overlay *ovl,
+		struct omap_overlay_info *info)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	unsigned long flags;
+	int r;
+
+	r = dss_ovl_simple_check(ovl, info);
+	if (r)
+		return r;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	op->user_info = *info;
+	op->user_info_dirty = true;
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	return 0;
+}
+
+static void dss_ovl_get_info(struct omap_overlay *ovl,
+		struct omap_overlay_info *info)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	*info = op->user_info;
+
+	spin_unlock_irqrestore(&data_lock, flags);
+}
+
+static int dss_ovl_set_manager(struct omap_overlay *ovl,
+		struct omap_overlay_manager *mgr)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	unsigned long flags;
+	int r;
+
+	if (!mgr)
+		return -EINVAL;
+
+	mutex_lock(&apply_lock);
+
+	if (ovl->manager) {
+		DSSERR("overlay '%s' already has a manager '%s'\n",
+				ovl->name, ovl->manager->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (op->enabled) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("overlay has to be disabled to change the manager\n");
+		r = -EINVAL;
+		goto err1;
+	}
+
+	dispc_ovl_set_channel_out(ovl->id, mgr->id);
+
+	ovl->manager = mgr;
+	list_add_tail(&ovl->list, &mgr->overlays);
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	dispc_runtime_put();
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+
+err1:
+	dispc_runtime_put();
+err:
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+static int dss_ovl_unset_manager(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	unsigned long flags;
+	int r;
+
+	mutex_lock(&apply_lock);
+
+	if (!ovl->manager) {
+		DSSERR("failed to detach overlay: manager not set\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (op->enabled) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("overlay has to be disabled to unset the manager\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	/* wait for pending extra_info updates to ensure the ovl is disabled */
+	wait_pending_extra_info_updates();
+
+	/*
+	 * For a manual update display, there is no guarantee that the overlay
+	 * is really disabled in HW, we may need an extra update from this
+	 * manager before the configurations can go in. Return an error if the
+	 * overlay needed an update from the manager.
+	 *
+	 * TODO: Instead of returning an error, try to do a dummy manager update
+	 * here to disable the overlay in hardware. Use the *GATED fields in
+	 * the DISPC_CONFIG registers to do a dummy update.
+	 */
+	spin_lock_irqsave(&data_lock, flags);
+
+	if (ovl_manual_update(ovl) && op->extra_info_dirty) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("need an update to change the manager\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	ovl->manager = NULL;
+	list_del(&ovl->list);
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+err:
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	unsigned long flags;
+	bool e;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	e = op->enabled;
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	return e;
+}
+
+static int dss_ovl_enable(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	unsigned long flags;
+	int r;
+
+	mutex_lock(&apply_lock);
+
+	if (op->enabled) {
+		r = 0;
+		goto err1;
+	}
+
+	if (ovl->manager == NULL || ovl->manager->output == NULL) {
+		r = -EINVAL;
+		goto err1;
+	}
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	op->enabling = true;
+
+	r = dss_check_settings(ovl->manager);
+	if (r) {
+		DSSERR("failed to enable overlay %d: check_settings failed\n",
+				ovl->id);
+		goto err2;
+	}
+
+	dss_setup_fifos();
+
+	op->enabling = false;
+	dss_apply_ovl_enable(ovl, true);
+
+	dss_write_regs();
+	dss_set_go_bits();
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+err2:
+	op->enabling = false;
+	spin_unlock_irqrestore(&data_lock, flags);
+err1:
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+static int dss_ovl_disable(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	unsigned long flags;
+	int r;
+
+	mutex_lock(&apply_lock);
+
+	if (!op->enabled) {
+		r = 0;
+		goto err;
+	}
+
+	if (ovl->manager == NULL || ovl->manager->output == NULL) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	dss_apply_ovl_enable(ovl, false);
+	dss_write_regs();
+	dss_set_go_bits();
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+
+err:
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	if (mp->framedone_handler)
+		return -EBUSY;
+
+	mp->framedone_handler = handler;
+	mp->framedone_handler_data = data;
+
+	return 0;
+}
+
+static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	WARN_ON(mp->framedone_handler != handler ||
+			mp->framedone_handler_data != data);
+
+	mp->framedone_handler = NULL;
+	mp->framedone_handler_data = NULL;
+}
+
+static const struct dss_mgr_ops apply_mgr_ops = {
+	.connect = dss_mgr_connect_compat,
+	.disconnect = dss_mgr_disconnect_compat,
+	.start_update = dss_mgr_start_update_compat,
+	.enable = dss_mgr_enable_compat,
+	.disable = dss_mgr_disable_compat,
+	.set_timings = dss_mgr_set_timings_compat,
+	.set_lcd_config = dss_mgr_set_lcd_config_compat,
+	.register_framedone_handler = dss_mgr_register_framedone_handler_compat,
+	.unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
+};
+
+static int compat_refcnt;
+static DEFINE_MUTEX(compat_init_lock);
+
+int omapdss_compat_init(void)
+{
+	struct platform_device *pdev = dss_get_core_pdev();
+	int i, r;
+
+	mutex_lock(&compat_init_lock);
+
+	if (compat_refcnt++ > 0)
+		goto out;
+
+	apply_init_priv();
+
+	dss_init_overlay_managers_sysfs(pdev);
+	dss_init_overlays(pdev);
+
+	for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+		struct omap_overlay_manager *mgr;
+
+		mgr = omap_dss_get_overlay_manager(i);
+
+		mgr->set_output = &dss_mgr_set_output;
+		mgr->unset_output = &dss_mgr_unset_output;
+		mgr->apply = &omap_dss_mgr_apply;
+		mgr->set_manager_info = &dss_mgr_set_info;
+		mgr->get_manager_info = &dss_mgr_get_info;
+		mgr->wait_for_go = &dss_mgr_wait_for_go;
+		mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
+		mgr->get_device = &dss_mgr_get_device;
+	}
+
+	for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+		struct omap_overlay *ovl = omap_dss_get_overlay(i);
+
+		ovl->is_enabled = &dss_ovl_is_enabled;
+		ovl->enable = &dss_ovl_enable;
+		ovl->disable = &dss_ovl_disable;
+		ovl->set_manager = &dss_ovl_set_manager;
+		ovl->unset_manager = &dss_ovl_unset_manager;
+		ovl->set_overlay_info = &dss_ovl_set_info;
+		ovl->get_overlay_info = &dss_ovl_get_info;
+		ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
+		ovl->get_device = &dss_ovl_get_device;
+	}
+
+	r = dss_install_mgr_ops(&apply_mgr_ops);
+	if (r)
+		goto err_mgr_ops;
+
+	r = display_init_sysfs(pdev);
+	if (r)
+		goto err_disp_sysfs;
+
+	dispc_runtime_get();
+
+	r = dss_dispc_initialize_irq();
+	if (r)
+		goto err_init_irq;
+
+	dispc_runtime_put();
+
+out:
+	mutex_unlock(&compat_init_lock);
+
+	return 0;
+
+err_init_irq:
+	dispc_runtime_put();
+	display_uninit_sysfs(pdev);
+
+err_disp_sysfs:
+	dss_uninstall_mgr_ops();
+
+err_mgr_ops:
+	dss_uninit_overlay_managers_sysfs(pdev);
+	dss_uninit_overlays(pdev);
+
+	compat_refcnt--;
+
+	mutex_unlock(&compat_init_lock);
+
+	return r;
+}
+EXPORT_SYMBOL(omapdss_compat_init);
+
+void omapdss_compat_uninit(void)
+{
+	struct platform_device *pdev = dss_get_core_pdev();
+
+	mutex_lock(&compat_init_lock);
+
+	if (--compat_refcnt > 0)
+		goto out;
+
+	dss_dispc_uninitialize_irq();
+
+	display_uninit_sysfs(pdev);
+
+	dss_uninstall_mgr_ops();
+
+	dss_uninit_overlay_managers_sysfs(pdev);
+	dss_uninit_overlays(pdev);
+out:
+	mutex_unlock(&compat_init_lock);
+}
+EXPORT_SYMBOL(omapdss_compat_uninit);
diff --git a/drivers/video/fbdev/omap2/dss/core.c b/drivers/video/fbdev/omap2/dss/core.c
new file mode 100644
index 000000000000..ffa45c894cd4
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/core.c
@@ -0,0 +1,360 @@
+/*
+ * linux/drivers/video/omap2/dss/core.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "CORE"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static struct {
+	struct platform_device *pdev;
+
+	const char *default_display_name;
+} core;
+
+static char *def_disp_name;
+module_param_named(def_disp, def_disp_name, charp, 0);
+MODULE_PARM_DESC(def_disp, "default display name");
+
+static bool dss_initialized;
+
+const char *omapdss_get_default_display_name(void)
+{
+	return core.default_display_name;
+}
+EXPORT_SYMBOL(omapdss_get_default_display_name);
+
+enum omapdss_version omapdss_get_version(void)
+{
+	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+	return pdata->version;
+}
+EXPORT_SYMBOL(omapdss_get_version);
+
+bool omapdss_is_initialized(void)
+{
+	return dss_initialized;
+}
+EXPORT_SYMBOL(omapdss_is_initialized);
+
+struct platform_device *dss_get_core_pdev(void)
+{
+	return core.pdev;
+}
+
+int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+{
+	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
+
+	if (!board_data->dsi_enable_pads)
+		return -ENOENT;
+
+	return board_data->dsi_enable_pads(dsi_id, lane_mask);
+}
+
+void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+{
+	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
+
+	if (!board_data->dsi_disable_pads)
+		return;
+
+	return board_data->dsi_disable_pads(dsi_id, lane_mask);
+}
+
+int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
+{
+	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+
+	if (pdata->set_min_bus_tput)
+		return pdata->set_min_bus_tput(dev, tput);
+	else
+		return 0;
+}
+
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
+static int dss_debug_show(struct seq_file *s, void *unused)
+{
+	void (*func)(struct seq_file *) = s->private;
+	func(s);
+	return 0;
+}
+
+static int dss_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dss_debug_show, inode->i_private);
+}
+
+static const struct file_operations dss_debug_fops = {
+	.open           = dss_debug_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
+static struct dentry *dss_debugfs_dir;
+
+static int dss_initialize_debugfs(void)
+{
+	dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
+	if (IS_ERR(dss_debugfs_dir)) {
+		int err = PTR_ERR(dss_debugfs_dir);
+		dss_debugfs_dir = NULL;
+		return err;
+	}
+
+	debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
+			&dss_debug_dump_clocks, &dss_debug_fops);
+
+	return 0;
+}
+
+static void dss_uninitialize_debugfs(void)
+{
+	if (dss_debugfs_dir)
+		debugfs_remove_recursive(dss_debugfs_dir);
+}
+
+int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
+{
+	struct dentry *d;
+
+	d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
+			write, &dss_debug_fops);
+
+	return PTR_ERR_OR_ZERO(d);
+}
+#else /* CONFIG_OMAP2_DSS_DEBUGFS */
+static inline int dss_initialize_debugfs(void)
+{
+	return 0;
+}
+static inline void dss_uninitialize_debugfs(void)
+{
+}
+int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
+{
+	return 0;
+}
+#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
+
+/* PLATFORM DEVICE */
+static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
+{
+	DSSDBG("pm notif %lu\n", v);
+
+	switch (v) {
+	case PM_SUSPEND_PREPARE:
+		DSSDBG("suspending displays\n");
+		return dss_suspend_all_devices();
+
+	case PM_POST_SUSPEND:
+		DSSDBG("resuming displays\n");
+		return dss_resume_all_devices();
+
+	default:
+		return 0;
+	}
+}
+
+static struct notifier_block omap_dss_pm_notif_block = {
+	.notifier_call = omap_dss_pm_notif,
+};
+
+static int __init omap_dss_probe(struct platform_device *pdev)
+{
+	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+	int r;
+
+	core.pdev = pdev;
+
+	dss_features_init(omapdss_get_version());
+
+	r = dss_initialize_debugfs();
+	if (r)
+		goto err_debugfs;
+
+	if (def_disp_name)
+		core.default_display_name = def_disp_name;
+	else if (pdata->default_display_name)
+		core.default_display_name = pdata->default_display_name;
+	else if (pdata->default_device)
+		core.default_display_name = pdata->default_device->name;
+
+	register_pm_notifier(&omap_dss_pm_notif_block);
+
+	return 0;
+
+err_debugfs:
+
+	return r;
+}
+
+static int omap_dss_remove(struct platform_device *pdev)
+{
+	unregister_pm_notifier(&omap_dss_pm_notif_block);
+
+	dss_uninitialize_debugfs();
+
+	return 0;
+}
+
+static void omap_dss_shutdown(struct platform_device *pdev)
+{
+	DSSDBG("shutdown\n");
+	dss_disable_all_devices();
+}
+
+static struct platform_driver omap_dss_driver = {
+	.remove         = omap_dss_remove,
+	.shutdown	= omap_dss_shutdown,
+	.driver         = {
+		.name   = "omapdss",
+		.owner  = THIS_MODULE,
+	},
+};
+
+/* INIT */
+static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_init_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_DPI
+	dpi_init_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_SDI
+	sdi_init_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_RFBI
+	rfbi_init_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_VENC
+	venc_init_platform_driver,
+#endif
+#ifdef CONFIG_OMAP4_DSS_HDMI
+	hdmi4_init_platform_driver,
+#endif
+};
+
+static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_uninit_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_DPI
+	dpi_uninit_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_SDI
+	sdi_uninit_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_RFBI
+	rfbi_uninit_platform_driver,
+#endif
+#ifdef CONFIG_OMAP2_DSS_VENC
+	venc_uninit_platform_driver,
+#endif
+#ifdef CONFIG_OMAP4_DSS_HDMI
+	hdmi4_uninit_platform_driver,
+#endif
+};
+
+static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
+
+static int __init omap_dss_init(void)
+{
+	int r;
+	int i;
+
+	r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
+	if (r)
+		return r;
+
+	r = dss_init_platform_driver();
+	if (r) {
+		DSSERR("Failed to initialize DSS platform driver\n");
+		goto err_dss;
+	}
+
+	r = dispc_init_platform_driver();
+	if (r) {
+		DSSERR("Failed to initialize dispc platform driver\n");
+		goto err_dispc;
+	}
+
+	/*
+	 * It's ok if the output-driver register fails. It happens, for example,
+	 * when there is no output-device (e.g. SDI for OMAP4).
+	 */
+	for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
+		r = dss_output_drv_reg_funcs[i]();
+		if (r == 0)
+			dss_output_drv_loaded[i] = true;
+	}
+
+	dss_initialized = true;
+
+	return 0;
+
+err_dispc:
+	dss_uninit_platform_driver();
+err_dss:
+	platform_driver_unregister(&omap_dss_driver);
+
+	return r;
+}
+
+static void __exit omap_dss_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) {
+		if (dss_output_drv_loaded[i])
+			dss_output_drv_unreg_funcs[i]();
+	}
+
+	dispc_uninit_platform_driver();
+	dss_uninit_platform_driver();
+
+	platform_driver_unregister(&omap_dss_driver);
+}
+
+module_init(omap_dss_init);
+module_exit(omap_dss_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/video/fbdev/omap2/dss/dispc-compat.c b/drivers/video/fbdev/omap2/dss/dispc-compat.c
new file mode 100644
index 000000000000..83779c2b292a
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dispc-compat.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "APPLY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "dispc-compat.h"
+
+#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_OCP_ERR | \
+					 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_SYNC_LOST | \
+					 DISPC_IRQ_SYNC_LOST_DIGIT)
+
+#define DISPC_MAX_NR_ISRS		8
+
+struct omap_dispc_isr_data {
+	omap_dispc_isr_t	isr;
+	void			*arg;
+	u32			mask;
+};
+
+struct dispc_irq_stats {
+	unsigned long last_reset;
+	unsigned irq_count;
+	unsigned irqs[32];
+};
+
+static struct {
+	spinlock_t irq_lock;
+	u32 irq_error_mask;
+	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+	u32 error_irqs;
+	struct work_struct error_work;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spinlock_t irq_stats_lock;
+	struct dispc_irq_stats irq_stats;
+#endif
+} dispc_compat;
+
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dispc_dump_irqs(struct seq_file *s)
+{
+	unsigned long flags;
+	struct dispc_irq_stats stats;
+
+	spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
+
+	stats = dispc_compat.irq_stats;
+	memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
+	dispc_compat.irq_stats.last_reset = jiffies;
+
+	spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
+
+	seq_printf(s, "period %u ms\n",
+			jiffies_to_msecs(jiffies - stats.last_reset));
+
+	seq_printf(s, "irqs %d\n", stats.irq_count);
+#define PIS(x) \
+	seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
+
+	PIS(FRAMEDONE);
+	PIS(VSYNC);
+	PIS(EVSYNC_EVEN);
+	PIS(EVSYNC_ODD);
+	PIS(ACBIAS_COUNT_STAT);
+	PIS(PROG_LINE_NUM);
+	PIS(GFX_FIFO_UNDERFLOW);
+	PIS(GFX_END_WIN);
+	PIS(PAL_GAMMA_MASK);
+	PIS(OCP_ERR);
+	PIS(VID1_FIFO_UNDERFLOW);
+	PIS(VID1_END_WIN);
+	PIS(VID2_FIFO_UNDERFLOW);
+	PIS(VID2_END_WIN);
+	if (dss_feat_get_num_ovls() > 3) {
+		PIS(VID3_FIFO_UNDERFLOW);
+		PIS(VID3_END_WIN);
+	}
+	PIS(SYNC_LOST);
+	PIS(SYNC_LOST_DIGIT);
+	PIS(WAKEUP);
+	if (dss_has_feature(FEAT_MGR_LCD2)) {
+		PIS(FRAMEDONE2);
+		PIS(VSYNC2);
+		PIS(ACBIAS_COUNT_STAT2);
+		PIS(SYNC_LOST2);
+	}
+	if (dss_has_feature(FEAT_MGR_LCD3)) {
+		PIS(FRAMEDONE3);
+		PIS(VSYNC3);
+		PIS(ACBIAS_COUNT_STAT3);
+		PIS(SYNC_LOST3);
+	}
+#undef PIS
+}
+#endif
+
+/* dispc.irq_lock has to be locked by the caller */
+static void _omap_dispc_set_irqs(void)
+{
+	u32 mask;
+	int i;
+	struct omap_dispc_isr_data *isr_data;
+
+	mask = dispc_compat.irq_error_mask;
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+
+		if (isr_data->isr == NULL)
+			continue;
+
+		mask |= isr_data->mask;
+	}
+
+	dispc_write_irqenable(mask);
+}
+
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+	int i;
+	int ret;
+	unsigned long flags;
+	struct omap_dispc_isr_data *isr_data;
+
+	if (isr == NULL)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+	/* check for duplicate entry */
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+		if (isr_data->isr == isr && isr_data->arg == arg &&
+				isr_data->mask == mask) {
+			ret = -EINVAL;
+			goto err;
+		}
+	}
+
+	isr_data = NULL;
+	ret = -EBUSY;
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+
+		if (isr_data->isr != NULL)
+			continue;
+
+		isr_data->isr = isr;
+		isr_data->arg = arg;
+		isr_data->mask = mask;
+		ret = 0;
+
+		break;
+	}
+
+	if (ret)
+		goto err;
+
+	_omap_dispc_set_irqs();
+
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	return 0;
+err:
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(omap_dispc_register_isr);
+
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+	int i;
+	unsigned long flags;
+	int ret = -EINVAL;
+	struct omap_dispc_isr_data *isr_data;
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+		if (isr_data->isr != isr || isr_data->arg != arg ||
+				isr_data->mask != mask)
+			continue;
+
+		/* found the correct isr */
+
+		isr_data->isr = NULL;
+		isr_data->arg = NULL;
+		isr_data->mask = 0;
+
+		ret = 0;
+		break;
+	}
+
+	if (ret == 0)
+		_omap_dispc_set_irqs();
+
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(omap_dispc_unregister_isr);
+
+static void print_irq_status(u32 status)
+{
+	if ((status & dispc_compat.irq_error_mask) == 0)
+		return;
+
+#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
+		status,
+		PIS(OCP_ERR),
+		PIS(GFX_FIFO_UNDERFLOW),
+		PIS(VID1_FIFO_UNDERFLOW),
+		PIS(VID2_FIFO_UNDERFLOW),
+		dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
+		PIS(SYNC_LOST),
+		PIS(SYNC_LOST_DIGIT),
+		dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
+		dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
+#undef PIS
+}
+
+/* Called from dss.c. Note that we don't touch clocks here,
+ * but we presume they are on because we got an IRQ. However,
+ * an irq handler may turn the clocks off, so we may not have
+ * clock later in the function. */
+static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
+{
+	int i;
+	u32 irqstatus, irqenable;
+	u32 handledirqs = 0;
+	u32 unhandled_errors;
+	struct omap_dispc_isr_data *isr_data;
+	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+
+	spin_lock(&dispc_compat.irq_lock);
+
+	irqstatus = dispc_read_irqstatus();
+	irqenable = dispc_read_irqenable();
+
+	/* IRQ is not for us */
+	if (!(irqstatus & irqenable)) {
+		spin_unlock(&dispc_compat.irq_lock);
+		return IRQ_NONE;
+	}
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spin_lock(&dispc_compat.irq_stats_lock);
+	dispc_compat.irq_stats.irq_count++;
+	dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
+	spin_unlock(&dispc_compat.irq_stats_lock);
+#endif
+
+	print_irq_status(irqstatus);
+
+	/* Ack the interrupt. Do it here before clocks are possibly turned
+	 * off */
+	dispc_clear_irqstatus(irqstatus);
+	/* flush posted write */
+	dispc_read_irqstatus();
+
+	/* make a copy and unlock, so that isrs can unregister
+	 * themselves */
+	memcpy(registered_isr, dispc_compat.registered_isr,
+			sizeof(registered_isr));
+
+	spin_unlock(&dispc_compat.irq_lock);
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &registered_isr[i];
+
+		if (!isr_data->isr)
+			continue;
+
+		if (isr_data->mask & irqstatus) {
+			isr_data->isr(isr_data->arg, irqstatus);
+			handledirqs |= isr_data->mask;
+		}
+	}
+
+	spin_lock(&dispc_compat.irq_lock);
+
+	unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
+
+	if (unhandled_errors) {
+		dispc_compat.error_irqs |= unhandled_errors;
+
+		dispc_compat.irq_error_mask &= ~unhandled_errors;
+		_omap_dispc_set_irqs();
+
+		schedule_work(&dispc_compat.error_work);
+	}
+
+	spin_unlock(&dispc_compat.irq_lock);
+
+	return IRQ_HANDLED;
+}
+
+static void dispc_error_worker(struct work_struct *work)
+{
+	int i;
+	u32 errors;
+	unsigned long flags;
+	static const unsigned fifo_underflow_bits[] = {
+		DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+		DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+		DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+		DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+	};
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+	errors = dispc_compat.error_irqs;
+	dispc_compat.error_irqs = 0;
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	dispc_runtime_get();
+
+	for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+		struct omap_overlay *ovl;
+		unsigned bit;
+
+		ovl = omap_dss_get_overlay(i);
+		bit = fifo_underflow_bits[i];
+
+		if (bit & errors) {
+			DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
+					ovl->name);
+			ovl->disable(ovl);
+			msleep(50);
+		}
+	}
+
+	for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+		struct omap_overlay_manager *mgr;
+		unsigned bit;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		bit = dispc_mgr_get_sync_lost_irq(i);
+
+		if (bit & errors) {
+			int j;
+
+			DSSERR("SYNC_LOST on channel %s, restarting the output "
+					"with video overlays disabled\n",
+					mgr->name);
+
+			dss_mgr_disable(mgr);
+
+			for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
+				struct omap_overlay *ovl;
+				ovl = omap_dss_get_overlay(j);
+
+				if (ovl->id != OMAP_DSS_GFX &&
+						ovl->manager == mgr)
+					ovl->disable(ovl);
+			}
+
+			dss_mgr_enable(mgr);
+		}
+	}
+
+	if (errors & DISPC_IRQ_OCP_ERR) {
+		DSSERR("OCP_ERR\n");
+		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+			struct omap_overlay_manager *mgr;
+
+			mgr = omap_dss_get_overlay_manager(i);
+			dss_mgr_disable(mgr);
+		}
+	}
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+	dispc_compat.irq_error_mask |= errors;
+	_omap_dispc_set_irqs();
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	dispc_runtime_put();
+}
+
+int dss_dispc_initialize_irq(void)
+{
+	int r;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spin_lock_init(&dispc_compat.irq_stats_lock);
+	dispc_compat.irq_stats.last_reset = jiffies;
+	dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
+#endif
+
+	spin_lock_init(&dispc_compat.irq_lock);
+
+	memset(dispc_compat.registered_isr, 0,
+			sizeof(dispc_compat.registered_isr));
+
+	dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+	if (dss_has_feature(FEAT_MGR_LCD2))
+		dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+	if (dss_has_feature(FEAT_MGR_LCD3))
+		dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
+	if (dss_feat_get_num_ovls() > 3)
+		dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
+
+	/*
+	 * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
+	 * so clear it
+	 */
+	dispc_clear_irqstatus(dispc_read_irqstatus());
+
+	INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
+
+	_omap_dispc_set_irqs();
+
+	r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
+	if (r) {
+		DSSERR("dispc_request_irq failed\n");
+		return r;
+	}
+
+	return 0;
+}
+
+void dss_dispc_uninitialize_irq(void)
+{
+	dispc_free_irq(&dispc_compat);
+}
+
+static void dispc_mgr_disable_isr(void *data, u32 mask)
+{
+	struct completion *compl = data;
+	complete(compl);
+}
+
+static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
+{
+	dispc_mgr_enable(channel, true);
+}
+
+static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
+{
+	DECLARE_COMPLETION_ONSTACK(framedone_compl);
+	int r;
+	u32 irq;
+
+	if (dispc_mgr_is_enabled(channel) == false)
+		return;
+
+	/*
+	 * When we disable LCD output, we need to wait for FRAMEDONE to know
+	 * that DISPC has finished with the LCD output.
+	 */
+
+	irq = dispc_mgr_get_framedone_irq(channel);
+
+	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq);
+	if (r)
+		DSSERR("failed to register FRAMEDONE isr\n");
+
+	dispc_mgr_enable(channel, false);
+
+	/* if we couldn't register for framedone, just sleep and exit */
+	if (r) {
+		msleep(100);
+		return;
+	}
+
+	if (!wait_for_completion_timeout(&framedone_compl,
+				msecs_to_jiffies(100)))
+		DSSERR("timeout waiting for FRAME DONE\n");
+
+	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq);
+	if (r)
+		DSSERR("failed to unregister FRAMEDONE isr\n");
+}
+
+static void dispc_digit_out_enable_isr(void *data, u32 mask)
+{
+	struct completion *compl = data;
+
+	/* ignore any sync lost interrupts */
+	if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
+		complete(compl);
+}
+
+static void dispc_mgr_enable_digit_out(void)
+{
+	DECLARE_COMPLETION_ONSTACK(vsync_compl);
+	int r;
+	u32 irq_mask;
+
+	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
+		return;
+
+	/*
+	 * Digit output produces some sync lost interrupts during the first
+	 * frame when enabling. Those need to be ignored, so we register for the
+	 * sync lost irq to prevent the error handler from triggering.
+	 */
+
+	irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
+		dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
+
+	r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
+			irq_mask);
+	if (r) {
+		DSSERR("failed to register %x isr\n", irq_mask);
+		return;
+	}
+
+	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
+
+	/* wait for the first evsync */
+	if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
+		DSSERR("timeout waiting for digit out to start\n");
+
+	r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
+			irq_mask);
+	if (r)
+		DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+static void dispc_mgr_disable_digit_out(void)
+{
+	DECLARE_COMPLETION_ONSTACK(framedone_compl);
+	int r, i;
+	u32 irq_mask;
+	int num_irqs;
+
+	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
+		return;
+
+	/*
+	 * When we disable the digit output, we need to wait for FRAMEDONE to
+	 * know that DISPC has finished with the output.
+	 */
+
+	irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
+	num_irqs = 1;
+
+	if (!irq_mask) {
+		/*
+		 * omap 2/3 don't have framedone irq for TV, so we need to use
+		 * vsyncs for this.
+		 */
+
+		irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
+		/*
+		 * We need to wait for both even and odd vsyncs. Note that this
+		 * is not totally reliable, as we could get a vsync interrupt
+		 * before we disable the output, which leads to timeout in the
+		 * wait_for_completion.
+		 */
+		num_irqs = 2;
+	}
+
+	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq_mask);
+	if (r)
+		DSSERR("failed to register %x isr\n", irq_mask);
+
+	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
+
+	/* if we couldn't register the irq, just sleep and exit */
+	if (r) {
+		msleep(100);
+		return;
+	}
+
+	for (i = 0; i < num_irqs; ++i) {
+		if (!wait_for_completion_timeout(&framedone_compl,
+					msecs_to_jiffies(100)))
+			DSSERR("timeout waiting for digit out to stop\n");
+	}
+
+	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq_mask);
+	if (r)
+		DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+void dispc_mgr_enable_sync(enum omap_channel channel)
+{
+	if (dss_mgr_is_lcd(channel))
+		dispc_mgr_enable_lcd_out(channel);
+	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+		dispc_mgr_enable_digit_out();
+	else
+		WARN_ON(1);
+}
+
+void dispc_mgr_disable_sync(enum omap_channel channel)
+{
+	if (dss_mgr_is_lcd(channel))
+		dispc_mgr_disable_lcd_out(channel);
+	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+		dispc_mgr_disable_digit_out();
+	else
+		WARN_ON(1);
+}
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+		unsigned long timeout)
+{
+	void dispc_irq_wait_handler(void *data, u32 mask)
+	{
+		complete((struct completion *)data);
+	}
+
+	int r;
+	DECLARE_COMPLETION_ONSTACK(completion);
+
+	r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
+			irqmask);
+
+	if (r)
+		return r;
+
+	timeout = wait_for_completion_interruptible_timeout(&completion,
+			timeout);
+
+	omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
+
+	if (timeout == 0)
+		return -ETIMEDOUT;
+
+	if (timeout == -ERESTARTSYS)
+		return -ERESTARTSYS;
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/omap2/dss/dispc-compat.h b/drivers/video/fbdev/omap2/dss/dispc-compat.h
new file mode 100644
index 000000000000..14a69b3d4fb0
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dispc-compat.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_DISPC_COMPAT_H
+#define __OMAP2_DSS_DISPC_COMPAT_H
+
+void dispc_mgr_enable_sync(enum omap_channel channel);
+void dispc_mgr_disable_sync(enum omap_channel channel);
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+		unsigned long timeout);
+
+int dss_dispc_initialize_irq(void);
+void dss_dispc_uninitialize_irq(void);
+
+#endif
diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c
new file mode 100644
index 000000000000..f18397c33e8f
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dispc.c
@@ -0,0 +1,3853 @@
+/*
+ * linux/drivers/video/omap2/dss/dispc.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPC"
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/export.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/hardirq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/sizes.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "dispc.h"
+
+/* DISPC */
+#define DISPC_SZ_REGS			SZ_4K
+
+enum omap_burst_size {
+	BURST_SIZE_X2 = 0,
+	BURST_SIZE_X4 = 1,
+	BURST_SIZE_X8 = 2,
+};
+
+#define REG_GET(idx, start, end) \
+	FLD_GET(dispc_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end)				\
+	dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
+
+struct dispc_features {
+	u8 sw_start;
+	u8 fp_start;
+	u8 bp_start;
+	u16 sw_max;
+	u16 vp_max;
+	u16 hp_max;
+	u8 mgr_width_start;
+	u8 mgr_height_start;
+	u16 mgr_width_max;
+	u16 mgr_height_max;
+	unsigned long max_lcd_pclk;
+	unsigned long max_tv_pclk;
+	int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
+		const struct omap_video_timings *mgr_timings,
+		u16 width, u16 height, u16 out_width, u16 out_height,
+		enum omap_color_mode color_mode, bool *five_taps,
+		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+		u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
+	unsigned long (*calc_core_clk) (unsigned long pclk,
+		u16 width, u16 height, u16 out_width, u16 out_height,
+		bool mem_to_mem);
+	u8 num_fifos;
+
+	/* swap GFX & WB fifos */
+	bool gfx_fifo_workaround:1;
+
+	/* no DISPC_IRQ_FRAMEDONETV on this SoC */
+	bool no_framedone_tv:1;
+
+	/* revert to the OMAP4 mechanism of DISPC Smart Standby operation */
+	bool mstandby_workaround:1;
+
+	bool set_max_preload:1;
+};
+
+#define DISPC_MAX_NR_FIFOS 5
+
+static struct {
+	struct platform_device *pdev;
+	void __iomem    *base;
+
+	int irq;
+	irq_handler_t user_handler;
+	void *user_data;
+
+	unsigned long core_clk_rate;
+	unsigned long tv_pclk_rate;
+
+	u32 fifo_size[DISPC_MAX_NR_FIFOS];
+	/* maps which plane is using a fifo. fifo-id -> plane-id */
+	int fifo_assignment[DISPC_MAX_NR_FIFOS];
+
+	bool		ctx_valid;
+	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
+
+	const struct dispc_features *feat;
+
+	bool is_enabled;
+} dispc;
+
+enum omap_color_component {
+	/* used for all color formats for OMAP3 and earlier
+	 * and for RGB and Y color component on OMAP4
+	 */
+	DISPC_COLOR_COMPONENT_RGB_Y		= 1 << 0,
+	/* used for UV component for
+	 * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12
+	 * color formats on OMAP4
+	 */
+	DISPC_COLOR_COMPONENT_UV		= 1 << 1,
+};
+
+enum mgr_reg_fields {
+	DISPC_MGR_FLD_ENABLE,
+	DISPC_MGR_FLD_STNTFT,
+	DISPC_MGR_FLD_GO,
+	DISPC_MGR_FLD_TFTDATALINES,
+	DISPC_MGR_FLD_STALLMODE,
+	DISPC_MGR_FLD_TCKENABLE,
+	DISPC_MGR_FLD_TCKSELECTION,
+	DISPC_MGR_FLD_CPR,
+	DISPC_MGR_FLD_FIFOHANDCHECK,
+	/* used to maintain a count of the above fields */
+	DISPC_MGR_FLD_NUM,
+};
+
+struct dispc_reg_field {
+	u16 reg;
+	u8 high;
+	u8 low;
+};
+
+static const struct {
+	const char *name;
+	u32 vsync_irq;
+	u32 framedone_irq;
+	u32 sync_lost_irq;
+	struct dispc_reg_field reg_desc[DISPC_MGR_FLD_NUM];
+} mgr_desc[] = {
+	[OMAP_DSS_CHANNEL_LCD] = {
+		.name		= "LCD",
+		.vsync_irq	= DISPC_IRQ_VSYNC,
+		.framedone_irq	= DISPC_IRQ_FRAMEDONE,
+		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST,
+		.reg_desc	= {
+			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL,  0,  0 },
+			[DISPC_MGR_FLD_STNTFT]		= { DISPC_CONTROL,  3,  3 },
+			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL,  5,  5 },
+			[DISPC_MGR_FLD_TFTDATALINES]	= { DISPC_CONTROL,  9,  8 },
+			[DISPC_MGR_FLD_STALLMODE]	= { DISPC_CONTROL, 11, 11 },
+			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG,  10, 10 },
+			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG,  11, 11 },
+			[DISPC_MGR_FLD_CPR]		= { DISPC_CONFIG,  15, 15 },
+			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG,  16, 16 },
+		},
+	},
+	[OMAP_DSS_CHANNEL_DIGIT] = {
+		.name		= "DIGIT",
+		.vsync_irq	= DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
+		.framedone_irq	= DISPC_IRQ_FRAMEDONETV,
+		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST_DIGIT,
+		.reg_desc	= {
+			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL,  1,  1 },
+			[DISPC_MGR_FLD_STNTFT]		= { },
+			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL,  6,  6 },
+			[DISPC_MGR_FLD_TFTDATALINES]	= { },
+			[DISPC_MGR_FLD_STALLMODE]	= { },
+			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG,  12, 12 },
+			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG,  13, 13 },
+			[DISPC_MGR_FLD_CPR]		= { },
+			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG,  16, 16 },
+		},
+	},
+	[OMAP_DSS_CHANNEL_LCD2] = {
+		.name		= "LCD2",
+		.vsync_irq	= DISPC_IRQ_VSYNC2,
+		.framedone_irq	= DISPC_IRQ_FRAMEDONE2,
+		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST2,
+		.reg_desc	= {
+			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL2,  0,  0 },
+			[DISPC_MGR_FLD_STNTFT]		= { DISPC_CONTROL2,  3,  3 },
+			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL2,  5,  5 },
+			[DISPC_MGR_FLD_TFTDATALINES]	= { DISPC_CONTROL2,  9,  8 },
+			[DISPC_MGR_FLD_STALLMODE]	= { DISPC_CONTROL2, 11, 11 },
+			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG2,  10, 10 },
+			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG2,  11, 11 },
+			[DISPC_MGR_FLD_CPR]		= { DISPC_CONFIG2,  15, 15 },
+			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG2,  16, 16 },
+		},
+	},
+	[OMAP_DSS_CHANNEL_LCD3] = {
+		.name		= "LCD3",
+		.vsync_irq	= DISPC_IRQ_VSYNC3,
+		.framedone_irq	= DISPC_IRQ_FRAMEDONE3,
+		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST3,
+		.reg_desc	= {
+			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL3,  0,  0 },
+			[DISPC_MGR_FLD_STNTFT]		= { DISPC_CONTROL3,  3,  3 },
+			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL3,  5,  5 },
+			[DISPC_MGR_FLD_TFTDATALINES]	= { DISPC_CONTROL3,  9,  8 },
+			[DISPC_MGR_FLD_STALLMODE]	= { DISPC_CONTROL3, 11, 11 },
+			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG3,  10, 10 },
+			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG3,  11, 11 },
+			[DISPC_MGR_FLD_CPR]		= { DISPC_CONFIG3,  15, 15 },
+			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG3,  16, 16 },
+		},
+	},
+};
+
+struct color_conv_coef {
+	int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
+	int full_range;
+};
+
+static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
+static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
+
+static inline void dispc_write_reg(const u16 idx, u32 val)
+{
+	__raw_writel(val, dispc.base + idx);
+}
+
+static inline u32 dispc_read_reg(const u16 idx)
+{
+	return __raw_readl(dispc.base + idx);
+}
+
+static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
+{
+	const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
+	return REG_GET(rfld.reg, rfld.high, rfld.low);
+}
+
+static void mgr_fld_write(enum omap_channel channel,
+					enum mgr_reg_fields regfld, int val) {
+	const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
+	REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
+}
+
+#define SR(reg) \
+	dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
+#define RR(reg) \
+	dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
+
+static void dispc_save_context(void)
+{
+	int i, j;
+
+	DSSDBG("dispc_save_context\n");
+
+	SR(IRQENABLE);
+	SR(CONTROL);
+	SR(CONFIG);
+	SR(LINE_NUMBER);
+	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
+		SR(GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_MGR_LCD2)) {
+		SR(CONTROL2);
+		SR(CONFIG2);
+	}
+	if (dss_has_feature(FEAT_MGR_LCD3)) {
+		SR(CONTROL3);
+		SR(CONFIG3);
+	}
+
+	for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+		SR(DEFAULT_COLOR(i));
+		SR(TRANS_COLOR(i));
+		SR(SIZE_MGR(i));
+		if (i == OMAP_DSS_CHANNEL_DIGIT)
+			continue;
+		SR(TIMING_H(i));
+		SR(TIMING_V(i));
+		SR(POL_FREQ(i));
+		SR(DIVISORo(i));
+
+		SR(DATA_CYCLE1(i));
+		SR(DATA_CYCLE2(i));
+		SR(DATA_CYCLE3(i));
+
+		if (dss_has_feature(FEAT_CPR)) {
+			SR(CPR_COEF_R(i));
+			SR(CPR_COEF_G(i));
+			SR(CPR_COEF_B(i));
+		}
+	}
+
+	for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+		SR(OVL_BA0(i));
+		SR(OVL_BA1(i));
+		SR(OVL_POSITION(i));
+		SR(OVL_SIZE(i));
+		SR(OVL_ATTRIBUTES(i));
+		SR(OVL_FIFO_THRESHOLD(i));
+		SR(OVL_ROW_INC(i));
+		SR(OVL_PIXEL_INC(i));
+		if (dss_has_feature(FEAT_PRELOAD))
+			SR(OVL_PRELOAD(i));
+		if (i == OMAP_DSS_GFX) {
+			SR(OVL_WINDOW_SKIP(i));
+			SR(OVL_TABLE_BA(i));
+			continue;
+		}
+		SR(OVL_FIR(i));
+		SR(OVL_PICTURE_SIZE(i));
+		SR(OVL_ACCU0(i));
+		SR(OVL_ACCU1(i));
+
+		for (j = 0; j < 8; j++)
+			SR(OVL_FIR_COEF_H(i, j));
+
+		for (j = 0; j < 8; j++)
+			SR(OVL_FIR_COEF_HV(i, j));
+
+		for (j = 0; j < 5; j++)
+			SR(OVL_CONV_COEF(i, j));
+
+		if (dss_has_feature(FEAT_FIR_COEF_V)) {
+			for (j = 0; j < 8; j++)
+				SR(OVL_FIR_COEF_V(i, j));
+		}
+
+		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+			SR(OVL_BA0_UV(i));
+			SR(OVL_BA1_UV(i));
+			SR(OVL_FIR2(i));
+			SR(OVL_ACCU2_0(i));
+			SR(OVL_ACCU2_1(i));
+
+			for (j = 0; j < 8; j++)
+				SR(OVL_FIR_COEF_H2(i, j));
+
+			for (j = 0; j < 8; j++)
+				SR(OVL_FIR_COEF_HV2(i, j));
+
+			for (j = 0; j < 8; j++)
+				SR(OVL_FIR_COEF_V2(i, j));
+		}
+		if (dss_has_feature(FEAT_ATTR2))
+			SR(OVL_ATTRIBUTES2(i));
+	}
+
+	if (dss_has_feature(FEAT_CORE_CLK_DIV))
+		SR(DIVISOR);
+
+	dispc.ctx_valid = true;
+
+	DSSDBG("context saved\n");
+}
+
+static void dispc_restore_context(void)
+{
+	int i, j;
+
+	DSSDBG("dispc_restore_context\n");
+
+	if (!dispc.ctx_valid)
+		return;
+
+	/*RR(IRQENABLE);*/
+	/*RR(CONTROL);*/
+	RR(CONFIG);
+	RR(LINE_NUMBER);
+	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
+		RR(GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_MGR_LCD2))
+		RR(CONFIG2);
+	if (dss_has_feature(FEAT_MGR_LCD3))
+		RR(CONFIG3);
+
+	for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+		RR(DEFAULT_COLOR(i));
+		RR(TRANS_COLOR(i));
+		RR(SIZE_MGR(i));
+		if (i == OMAP_DSS_CHANNEL_DIGIT)
+			continue;
+		RR(TIMING_H(i));
+		RR(TIMING_V(i));
+		RR(POL_FREQ(i));
+		RR(DIVISORo(i));
+
+		RR(DATA_CYCLE1(i));
+		RR(DATA_CYCLE2(i));
+		RR(DATA_CYCLE3(i));
+
+		if (dss_has_feature(FEAT_CPR)) {
+			RR(CPR_COEF_R(i));
+			RR(CPR_COEF_G(i));
+			RR(CPR_COEF_B(i));
+		}
+	}
+
+	for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+		RR(OVL_BA0(i));
+		RR(OVL_BA1(i));
+		RR(OVL_POSITION(i));
+		RR(OVL_SIZE(i));
+		RR(OVL_ATTRIBUTES(i));
+		RR(OVL_FIFO_THRESHOLD(i));
+		RR(OVL_ROW_INC(i));
+		RR(OVL_PIXEL_INC(i));
+		if (dss_has_feature(FEAT_PRELOAD))
+			RR(OVL_PRELOAD(i));
+		if (i == OMAP_DSS_GFX) {
+			RR(OVL_WINDOW_SKIP(i));
+			RR(OVL_TABLE_BA(i));
+			continue;
+		}
+		RR(OVL_FIR(i));
+		RR(OVL_PICTURE_SIZE(i));
+		RR(OVL_ACCU0(i));
+		RR(OVL_ACCU1(i));
+
+		for (j = 0; j < 8; j++)
+			RR(OVL_FIR_COEF_H(i, j));
+
+		for (j = 0; j < 8; j++)
+			RR(OVL_FIR_COEF_HV(i, j));
+
+		for (j = 0; j < 5; j++)
+			RR(OVL_CONV_COEF(i, j));
+
+		if (dss_has_feature(FEAT_FIR_COEF_V)) {
+			for (j = 0; j < 8; j++)
+				RR(OVL_FIR_COEF_V(i, j));
+		}
+
+		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+			RR(OVL_BA0_UV(i));
+			RR(OVL_BA1_UV(i));
+			RR(OVL_FIR2(i));
+			RR(OVL_ACCU2_0(i));
+			RR(OVL_ACCU2_1(i));
+
+			for (j = 0; j < 8; j++)
+				RR(OVL_FIR_COEF_H2(i, j));
+
+			for (j = 0; j < 8; j++)
+				RR(OVL_FIR_COEF_HV2(i, j));
+
+			for (j = 0; j < 8; j++)
+				RR(OVL_FIR_COEF_V2(i, j));
+		}
+		if (dss_has_feature(FEAT_ATTR2))
+			RR(OVL_ATTRIBUTES2(i));
+	}
+
+	if (dss_has_feature(FEAT_CORE_CLK_DIV))
+		RR(DIVISOR);
+
+	/* enable last, because LCD & DIGIT enable are here */
+	RR(CONTROL);
+	if (dss_has_feature(FEAT_MGR_LCD2))
+		RR(CONTROL2);
+	if (dss_has_feature(FEAT_MGR_LCD3))
+		RR(CONTROL3);
+	/* clear spurious SYNC_LOST_DIGIT interrupts */
+	dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
+
+	/*
+	 * enable last so IRQs won't trigger before
+	 * the context is fully restored
+	 */
+	RR(IRQENABLE);
+
+	DSSDBG("context restored\n");
+}
+
+#undef SR
+#undef RR
+
+int dispc_runtime_get(void)
+{
+	int r;
+
+	DSSDBG("dispc_runtime_get\n");
+
+	r = pm_runtime_get_sync(&dispc.pdev->dev);
+	WARN_ON(r < 0);
+	return r < 0 ? r : 0;
+}
+EXPORT_SYMBOL(dispc_runtime_get);
+
+void dispc_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("dispc_runtime_put\n");
+
+	r = pm_runtime_put_sync(&dispc.pdev->dev);
+	WARN_ON(r < 0 && r != -ENOSYS);
+}
+EXPORT_SYMBOL(dispc_runtime_put);
+
+u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
+{
+	return mgr_desc[channel].vsync_irq;
+}
+EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
+
+u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
+{
+	if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
+		return 0;
+
+	return mgr_desc[channel].framedone_irq;
+}
+EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
+
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
+{
+	return mgr_desc[channel].sync_lost_irq;
+}
+EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
+
+u32 dispc_wb_get_framedone_irq(void)
+{
+	return DISPC_IRQ_FRAMEDONEWB;
+}
+
+bool dispc_mgr_go_busy(enum omap_channel channel)
+{
+	return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
+}
+EXPORT_SYMBOL(dispc_mgr_go_busy);
+
+void dispc_mgr_go(enum omap_channel channel)
+{
+	WARN_ON(dispc_mgr_is_enabled(channel) == false);
+	WARN_ON(dispc_mgr_go_busy(channel));
+
+	DSSDBG("GO %s\n", mgr_desc[channel].name);
+
+	mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
+}
+EXPORT_SYMBOL(dispc_mgr_go);
+
+bool dispc_wb_go_busy(void)
+{
+	return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
+}
+
+void dispc_wb_go(void)
+{
+	enum omap_plane plane = OMAP_DSS_WB;
+	bool enable, go;
+
+	enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
+
+	if (!enable)
+		return;
+
+	go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
+	if (go) {
+		DSSERR("GO bit not down for WB\n");
+		return;
+	}
+
+	REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
+}
+
+static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
+{
+	dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
+}
+
+static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
+{
+	dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
+}
+
+static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value)
+{
+	dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
+}
+
+static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
+{
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
+}
+
+static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg,
+		u32 value)
+{
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
+}
+
+static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
+{
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
+}
+
+static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
+				int fir_vinc, int five_taps,
+				enum omap_color_component color_comp)
+{
+	const struct dispc_coef *h_coef, *v_coef;
+	int i;
+
+	h_coef = dispc_ovl_get_scale_coef(fir_hinc, true);
+	v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps);
+
+	for (i = 0; i < 8; i++) {
+		u32 h, hv;
+
+		h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0)
+			| FLD_VAL(h_coef[i].hc1_vc0, 15, 8)
+			| FLD_VAL(h_coef[i].hc2_vc1, 23, 16)
+			| FLD_VAL(h_coef[i].hc3_vc2, 31, 24);
+		hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0)
+			| FLD_VAL(v_coef[i].hc1_vc0, 15, 8)
+			| FLD_VAL(v_coef[i].hc2_vc1, 23, 16)
+			| FLD_VAL(v_coef[i].hc3_vc2, 31, 24);
+
+		if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
+			dispc_ovl_write_firh_reg(plane, i, h);
+			dispc_ovl_write_firhv_reg(plane, i, hv);
+		} else {
+			dispc_ovl_write_firh2_reg(plane, i, h);
+			dispc_ovl_write_firhv2_reg(plane, i, hv);
+		}
+
+	}
+
+	if (five_taps) {
+		for (i = 0; i < 8; i++) {
+			u32 v;
+			v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0)
+				| FLD_VAL(v_coef[i].hc4_vc22, 15, 8);
+			if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
+				dispc_ovl_write_firv_reg(plane, i, v);
+			else
+				dispc_ovl_write_firv2_reg(plane, i, v);
+		}
+	}
+}
+
+
+static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
+		const struct color_conv_coef *ct)
+{
+#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
+
+	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
+	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy,  ct->rcb));
+	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
+	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
+	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
+
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
+
+#undef CVAL
+}
+
+static void dispc_setup_color_conv_coef(void)
+{
+	int i;
+	int num_ovl = dss_feat_get_num_ovls();
+	int num_wb = dss_feat_get_num_wbs();
+	const struct color_conv_coef ctbl_bt601_5_ovl = {
+		298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
+	};
+	const struct color_conv_coef ctbl_bt601_5_wb = {
+		66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
+	};
+
+	for (i = 1; i < num_ovl; i++)
+		dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
+
+	for (; i < num_wb; i++)
+		dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
+}
+
+static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
+{
+	dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
+}
+
+static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr)
+{
+	dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
+}
+
+static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr)
+{
+	dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
+}
+
+static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
+{
+	dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
+}
+
+static void dispc_ovl_set_pos(enum omap_plane plane,
+		enum omap_overlay_caps caps, int x, int y)
+{
+	u32 val;
+
+	if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
+		return;
+
+	val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
+
+	dispc_write_reg(DISPC_OVL_POSITION(plane), val);
+}
+
+static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
+		int height)
+{
+	u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+
+	if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
+		dispc_write_reg(DISPC_OVL_SIZE(plane), val);
+	else
+		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
+}
+
+static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
+		int height)
+{
+	u32 val;
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+
+	if (plane == OMAP_DSS_WB)
+		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
+	else
+		dispc_write_reg(DISPC_OVL_SIZE(plane), val);
+}
+
+static void dispc_ovl_set_zorder(enum omap_plane plane,
+		enum omap_overlay_caps caps, u8 zorder)
+{
+	if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+		return;
+
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
+}
+
+static void dispc_ovl_enable_zorder_planes(void)
+{
+	int i;
+
+	if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
+		return;
+
+	for (i = 0; i < dss_feat_get_num_ovls(); i++)
+		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
+}
+
+static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
+		enum omap_overlay_caps caps, bool enable)
+{
+	if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+		return;
+
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
+}
+
+static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
+		enum omap_overlay_caps caps, u8 global_alpha)
+{
+	static const unsigned shifts[] = { 0, 8, 16, 24, };
+	int shift;
+
+	if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
+		return;
+
+	shift = shifts[plane];
+	REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
+}
+
+static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc)
+{
+	dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
+}
+
+static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc)
+{
+	dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
+}
+
+static void dispc_ovl_set_color_mode(enum omap_plane plane,
+		enum omap_color_mode color_mode)
+{
+	u32 m = 0;
+	if (plane != OMAP_DSS_GFX) {
+		switch (color_mode) {
+		case OMAP_DSS_COLOR_NV12:
+			m = 0x0; break;
+		case OMAP_DSS_COLOR_RGBX16:
+			m = 0x1; break;
+		case OMAP_DSS_COLOR_RGBA16:
+			m = 0x2; break;
+		case OMAP_DSS_COLOR_RGB12U:
+			m = 0x4; break;
+		case OMAP_DSS_COLOR_ARGB16:
+			m = 0x5; break;
+		case OMAP_DSS_COLOR_RGB16:
+			m = 0x6; break;
+		case OMAP_DSS_COLOR_ARGB16_1555:
+			m = 0x7; break;
+		case OMAP_DSS_COLOR_RGB24U:
+			m = 0x8; break;
+		case OMAP_DSS_COLOR_RGB24P:
+			m = 0x9; break;
+		case OMAP_DSS_COLOR_YUV2:
+			m = 0xa; break;
+		case OMAP_DSS_COLOR_UYVY:
+			m = 0xb; break;
+		case OMAP_DSS_COLOR_ARGB32:
+			m = 0xc; break;
+		case OMAP_DSS_COLOR_RGBA32:
+			m = 0xd; break;
+		case OMAP_DSS_COLOR_RGBX32:
+			m = 0xe; break;
+		case OMAP_DSS_COLOR_XRGB16_1555:
+			m = 0xf; break;
+		default:
+			BUG(); return;
+		}
+	} else {
+		switch (color_mode) {
+		case OMAP_DSS_COLOR_CLUT1:
+			m = 0x0; break;
+		case OMAP_DSS_COLOR_CLUT2:
+			m = 0x1; break;
+		case OMAP_DSS_COLOR_CLUT4:
+			m = 0x2; break;
+		case OMAP_DSS_COLOR_CLUT8:
+			m = 0x3; break;
+		case OMAP_DSS_COLOR_RGB12U:
+			m = 0x4; break;
+		case OMAP_DSS_COLOR_ARGB16:
+			m = 0x5; break;
+		case OMAP_DSS_COLOR_RGB16:
+			m = 0x6; break;
+		case OMAP_DSS_COLOR_ARGB16_1555:
+			m = 0x7; break;
+		case OMAP_DSS_COLOR_RGB24U:
+			m = 0x8; break;
+		case OMAP_DSS_COLOR_RGB24P:
+			m = 0x9; break;
+		case OMAP_DSS_COLOR_RGBX16:
+			m = 0xa; break;
+		case OMAP_DSS_COLOR_RGBA16:
+			m = 0xb; break;
+		case OMAP_DSS_COLOR_ARGB32:
+			m = 0xc; break;
+		case OMAP_DSS_COLOR_RGBA32:
+			m = 0xd; break;
+		case OMAP_DSS_COLOR_RGBX32:
+			m = 0xe; break;
+		case OMAP_DSS_COLOR_XRGB16_1555:
+			m = 0xf; break;
+		default:
+			BUG(); return;
+		}
+	}
+
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
+}
+
+static void dispc_ovl_configure_burst_type(enum omap_plane plane,
+		enum omap_dss_rotation_type rotation_type)
+{
+	if (dss_has_feature(FEAT_BURST_2D) == 0)
+		return;
+
+	if (rotation_type == OMAP_DSS_ROT_TILER)
+		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
+	else
+		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
+}
+
+void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
+{
+	int shift;
+	u32 val;
+	int chan = 0, chan2 = 0;
+
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		shift = 8;
+		break;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+	case OMAP_DSS_VIDEO3:
+		shift = 16;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+	if (dss_has_feature(FEAT_MGR_LCD2)) {
+		switch (channel) {
+		case OMAP_DSS_CHANNEL_LCD:
+			chan = 0;
+			chan2 = 0;
+			break;
+		case OMAP_DSS_CHANNEL_DIGIT:
+			chan = 1;
+			chan2 = 0;
+			break;
+		case OMAP_DSS_CHANNEL_LCD2:
+			chan = 0;
+			chan2 = 1;
+			break;
+		case OMAP_DSS_CHANNEL_LCD3:
+			if (dss_has_feature(FEAT_MGR_LCD3)) {
+				chan = 0;
+				chan2 = 2;
+			} else {
+				BUG();
+				return;
+			}
+			break;
+		default:
+			BUG();
+			return;
+		}
+
+		val = FLD_MOD(val, chan, shift, shift);
+		val = FLD_MOD(val, chan2, 31, 30);
+	} else {
+		val = FLD_MOD(val, channel, shift, shift);
+	}
+	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
+}
+EXPORT_SYMBOL(dispc_ovl_set_channel_out);
+
+static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
+{
+	int shift;
+	u32 val;
+	enum omap_channel channel;
+
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		shift = 8;
+		break;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+	case OMAP_DSS_VIDEO3:
+		shift = 16;
+		break;
+	default:
+		BUG();
+		return 0;
+	}
+
+	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+
+	if (dss_has_feature(FEAT_MGR_LCD3)) {
+		if (FLD_GET(val, 31, 30) == 0)
+			channel = FLD_GET(val, shift, shift);
+		else if (FLD_GET(val, 31, 30) == 1)
+			channel = OMAP_DSS_CHANNEL_LCD2;
+		else
+			channel = OMAP_DSS_CHANNEL_LCD3;
+	} else if (dss_has_feature(FEAT_MGR_LCD2)) {
+		if (FLD_GET(val, 31, 30) == 0)
+			channel = FLD_GET(val, shift, shift);
+		else
+			channel = OMAP_DSS_CHANNEL_LCD2;
+	} else {
+		channel = FLD_GET(val, shift, shift);
+	}
+
+	return channel;
+}
+
+void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
+{
+	enum omap_plane plane = OMAP_DSS_WB;
+
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
+}
+
+static void dispc_ovl_set_burst_size(enum omap_plane plane,
+		enum omap_burst_size burst_size)
+{
+	static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
+	int shift;
+
+	shift = shifts[plane];
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
+}
+
+static void dispc_configure_burst_sizes(void)
+{
+	int i;
+	const int burst_size = BURST_SIZE_X8;
+
+	/* Configure burst size always to maximum size */
+	for (i = 0; i < dss_feat_get_num_ovls(); ++i)
+		dispc_ovl_set_burst_size(i, burst_size);
+}
+
+static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
+{
+	unsigned unit = dss_feat_get_burst_size_unit();
+	/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
+	return unit * 8;
+}
+
+void dispc_enable_gamma_table(bool enable)
+{
+	/*
+	 * This is partially implemented to support only disabling of
+	 * the gamma table.
+	 */
+	if (enable) {
+		DSSWARN("Gamma table enabling for TV not yet supported");
+		return;
+	}
+
+	REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
+}
+
+static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
+{
+	if (channel == OMAP_DSS_CHANNEL_DIGIT)
+		return;
+
+	mgr_fld_write(channel, DISPC_MGR_FLD_CPR, enable);
+}
+
+static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
+		const struct omap_dss_cpr_coefs *coefs)
+{
+	u32 coef_r, coef_g, coef_b;
+
+	if (!dss_mgr_is_lcd(channel))
+		return;
+
+	coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
+		FLD_VAL(coefs->rb, 9, 0);
+	coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) |
+		FLD_VAL(coefs->gb, 9, 0);
+	coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) |
+		FLD_VAL(coefs->bb, 9, 0);
+
+	dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r);
+	dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g);
+	dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
+}
+
+static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
+{
+	u32 val;
+
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+	val = FLD_MOD(val, enable, 9, 9);
+	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
+}
+
+static void dispc_ovl_enable_replication(enum omap_plane plane,
+		enum omap_overlay_caps caps, bool enable)
+{
+	static const unsigned shifts[] = { 5, 10, 10, 10 };
+	int shift;
+
+	if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
+		return;
+
+	shift = shifts[plane];
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
+}
+
+static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
+		u16 height)
+{
+	u32 val;
+
+	val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
+		FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
+
+	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
+}
+
+static void dispc_init_fifos(void)
+{
+	u32 size;
+	int fifo;
+	u8 start, end;
+	u32 unit;
+
+	unit = dss_feat_get_buffer_size_unit();
+
+	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
+
+	for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
+		size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
+		size *= unit;
+		dispc.fifo_size[fifo] = size;
+
+		/*
+		 * By default fifos are mapped directly to overlays, fifo 0 to
+		 * ovl 0, fifo 1 to ovl 1, etc.
+		 */
+		dispc.fifo_assignment[fifo] = fifo;
+	}
+
+	/*
+	 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
+	 * causes problems with certain use cases, like using the tiler in 2D
+	 * mode. The below hack swaps the fifos of GFX and WB planes, thus
+	 * giving GFX plane a larger fifo. WB but should work fine with a
+	 * smaller fifo.
+	 */
+	if (dispc.feat->gfx_fifo_workaround) {
+		u32 v;
+
+		v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
+
+		v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
+		v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
+		v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
+		v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
+
+		dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
+
+		dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
+		dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
+	}
+}
+
+static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
+{
+	int fifo;
+	u32 size = 0;
+
+	for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
+		if (dispc.fifo_assignment[fifo] == plane)
+			size += dispc.fifo_size[fifo];
+	}
+
+	return size;
+}
+
+void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
+{
+	u8 hi_start, hi_end, lo_start, lo_end;
+	u32 unit;
+
+	unit = dss_feat_get_buffer_size_unit();
+
+	WARN_ON(low % unit != 0);
+	WARN_ON(high % unit != 0);
+
+	low /= unit;
+	high /= unit;
+
+	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
+	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
+
+	DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n",
+			plane,
+			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
+				lo_start, lo_end) * unit,
+			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
+				hi_start, hi_end) * unit,
+			low * unit, high * unit);
+
+	dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
+			FLD_VAL(high, hi_start, hi_end) |
+			FLD_VAL(low, lo_start, lo_end));
+
+	/*
+	 * configure the preload to the pipeline's high threhold, if HT it's too
+	 * large for the preload field, set the threshold to the maximum value
+	 * that can be held by the preload register
+	 */
+	if (dss_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload &&
+			plane != OMAP_DSS_WB)
+		dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu));
+}
+EXPORT_SYMBOL(dispc_ovl_set_fifo_threshold);
+
+void dispc_enable_fifomerge(bool enable)
+{
+	if (!dss_has_feature(FEAT_FIFO_MERGE)) {
+		WARN_ON(enable);
+		return;
+	}
+
+	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
+	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
+}
+
+void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
+		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
+		bool manual_update)
+{
+	/*
+	 * All sizes are in bytes. Both the buffer and burst are made of
+	 * buffer_units, and the fifo thresholds must be buffer_unit aligned.
+	 */
+
+	unsigned buf_unit = dss_feat_get_buffer_size_unit();
+	unsigned ovl_fifo_size, total_fifo_size, burst_size;
+	int i;
+
+	burst_size = dispc_ovl_get_burst_size(plane);
+	ovl_fifo_size = dispc_ovl_get_fifo_size(plane);
+
+	if (use_fifomerge) {
+		total_fifo_size = 0;
+		for (i = 0; i < dss_feat_get_num_ovls(); ++i)
+			total_fifo_size += dispc_ovl_get_fifo_size(i);
+	} else {
+		total_fifo_size = ovl_fifo_size;
+	}
+
+	/*
+	 * We use the same low threshold for both fifomerge and non-fifomerge
+	 * cases, but for fifomerge we calculate the high threshold using the
+	 * combined fifo size
+	 */
+
+	if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
+		*fifo_low = ovl_fifo_size - burst_size * 2;
+		*fifo_high = total_fifo_size - burst_size;
+	} else if (plane == OMAP_DSS_WB) {
+		/*
+		 * Most optimal configuration for writeback is to push out data
+		 * to the interconnect the moment writeback pushes enough pixels
+		 * in the FIFO to form a burst
+		 */
+		*fifo_low = 0;
+		*fifo_high = burst_size;
+	} else {
+		*fifo_low = ovl_fifo_size - burst_size;
+		*fifo_high = total_fifo_size - buf_unit;
+	}
+}
+EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds);
+
+static void dispc_ovl_set_fir(enum omap_plane plane,
+				int hinc, int vinc,
+				enum omap_color_component color_comp)
+{
+	u32 val;
+
+	if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
+		u8 hinc_start, hinc_end, vinc_start, vinc_end;
+
+		dss_feat_get_reg_field(FEAT_REG_FIRHINC,
+					&hinc_start, &hinc_end);
+		dss_feat_get_reg_field(FEAT_REG_FIRVINC,
+					&vinc_start, &vinc_end);
+		val = FLD_VAL(vinc, vinc_start, vinc_end) |
+				FLD_VAL(hinc, hinc_start, hinc_end);
+
+		dispc_write_reg(DISPC_OVL_FIR(plane), val);
+	} else {
+		val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
+		dispc_write_reg(DISPC_OVL_FIR2(plane), val);
+	}
+}
+
+static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
+{
+	u32 val;
+	u8 hor_start, hor_end, vert_start, vert_end;
+
+	dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
+	dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
+
+	val = FLD_VAL(vaccu, vert_start, vert_end) |
+			FLD_VAL(haccu, hor_start, hor_end);
+
+	dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
+}
+
+static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+{
+	u32 val;
+	u8 hor_start, hor_end, vert_start, vert_end;
+
+	dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
+	dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
+
+	val = FLD_VAL(vaccu, vert_start, vert_end) |
+			FLD_VAL(haccu, hor_start, hor_end);
+
+	dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
+}
+
+static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu,
+		int vaccu)
+{
+	u32 val;
+
+	val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
+	dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
+}
+
+static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu,
+		int vaccu)
+{
+	u32 val;
+
+	val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
+	dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
+}
+
+static void dispc_ovl_set_scale_param(enum omap_plane plane,
+		u16 orig_width, u16 orig_height,
+		u16 out_width, u16 out_height,
+		bool five_taps, u8 rotation,
+		enum omap_color_component color_comp)
+{
+	int fir_hinc, fir_vinc;
+
+	fir_hinc = 1024 * orig_width / out_width;
+	fir_vinc = 1024 * orig_height / out_height;
+
+	dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps,
+				color_comp);
+	dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
+}
+
+static void dispc_ovl_set_accu_uv(enum omap_plane plane,
+		u16 orig_width,	u16 orig_height, u16 out_width, u16 out_height,
+		bool ilace, enum omap_color_mode color_mode, u8 rotation)
+{
+	int h_accu2_0, h_accu2_1;
+	int v_accu2_0, v_accu2_1;
+	int chroma_hinc, chroma_vinc;
+	int idx;
+
+	struct accu {
+		s8 h0_m, h0_n;
+		s8 h1_m, h1_n;
+		s8 v0_m, v0_n;
+		s8 v1_m, v1_n;
+	};
+
+	const struct accu *accu_table;
+	const struct accu *accu_val;
+
+	static const struct accu accu_nv12[4] = {
+		{  0, 1,  0, 1 , -1, 2, 0, 1 },
+		{  1, 2, -3, 4 ,  0, 1, 0, 1 },
+		{ -1, 1,  0, 1 , -1, 2, 0, 1 },
+		{ -1, 2, -1, 2 , -1, 1, 0, 1 },
+	};
+
+	static const struct accu accu_nv12_ilace[4] = {
+		{  0, 1,  0, 1 , -3, 4, -1, 4 },
+		{ -1, 4, -3, 4 ,  0, 1,  0, 1 },
+		{ -1, 1,  0, 1 , -1, 4, -3, 4 },
+		{ -3, 4, -3, 4 , -1, 1,  0, 1 },
+	};
+
+	static const struct accu accu_yuv[4] = {
+		{  0, 1, 0, 1,  0, 1, 0, 1 },
+		{  0, 1, 0, 1,  0, 1, 0, 1 },
+		{ -1, 1, 0, 1,  0, 1, 0, 1 },
+		{  0, 1, 0, 1, -1, 1, 0, 1 },
+	};
+
+	switch (rotation) {
+	case OMAP_DSS_ROT_0:
+		idx = 0;
+		break;
+	case OMAP_DSS_ROT_90:
+		idx = 1;
+		break;
+	case OMAP_DSS_ROT_180:
+		idx = 2;
+		break;
+	case OMAP_DSS_ROT_270:
+		idx = 3;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_NV12:
+		if (ilace)
+			accu_table = accu_nv12_ilace;
+		else
+			accu_table = accu_nv12;
+		break;
+	case OMAP_DSS_COLOR_YUV2:
+	case OMAP_DSS_COLOR_UYVY:
+		accu_table = accu_yuv;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	accu_val = &accu_table[idx];
+
+	chroma_hinc = 1024 * orig_width / out_width;
+	chroma_vinc = 1024 * orig_height / out_height;
+
+	h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024;
+	h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024;
+	v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024;
+	v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024;
+
+	dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0);
+	dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1);
+}
+
+static void dispc_ovl_set_scaling_common(enum omap_plane plane,
+		u16 orig_width, u16 orig_height,
+		u16 out_width, u16 out_height,
+		bool ilace, bool five_taps,
+		bool fieldmode, enum omap_color_mode color_mode,
+		u8 rotation)
+{
+	int accu0 = 0;
+	int accu1 = 0;
+	u32 l;
+
+	dispc_ovl_set_scale_param(plane, orig_width, orig_height,
+				out_width, out_height, five_taps,
+				rotation, DISPC_COLOR_COMPONENT_RGB_Y);
+	l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+
+	/* RESIZEENABLE and VERTICALTAPS */
+	l &= ~((0x3 << 5) | (0x1 << 21));
+	l |= (orig_width != out_width) ? (1 << 5) : 0;
+	l |= (orig_height != out_height) ? (1 << 6) : 0;
+	l |= five_taps ? (1 << 21) : 0;
+
+	/* VRESIZECONF and HRESIZECONF */
+	if (dss_has_feature(FEAT_RESIZECONF)) {
+		l &= ~(0x3 << 7);
+		l |= (orig_width <= out_width) ? 0 : (1 << 7);
+		l |= (orig_height <= out_height) ? 0 : (1 << 8);
+	}
+
+	/* LINEBUFFERSPLIT */
+	if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
+		l &= ~(0x1 << 22);
+		l |= five_taps ? (1 << 22) : 0;
+	}
+
+	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
+
+	/*
+	 * field 0 = even field = bottom field
+	 * field 1 = odd field = top field
+	 */
+	if (ilace && !fieldmode) {
+		accu1 = 0;
+		accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff;
+		if (accu0 >= 1024/2) {
+			accu1 = 1024/2;
+			accu0 -= accu1;
+		}
+	}
+
+	dispc_ovl_set_vid_accu0(plane, 0, accu0);
+	dispc_ovl_set_vid_accu1(plane, 0, accu1);
+}
+
+static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
+		u16 orig_width, u16 orig_height,
+		u16 out_width, u16 out_height,
+		bool ilace, bool five_taps,
+		bool fieldmode, enum omap_color_mode color_mode,
+		u8 rotation)
+{
+	int scale_x = out_width != orig_width;
+	int scale_y = out_height != orig_height;
+	bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
+
+	if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
+		return;
+	if ((color_mode != OMAP_DSS_COLOR_YUV2 &&
+			color_mode != OMAP_DSS_COLOR_UYVY &&
+			color_mode != OMAP_DSS_COLOR_NV12)) {
+		/* reset chroma resampling for RGB formats  */
+		if (plane != OMAP_DSS_WB)
+			REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
+		return;
+	}
+
+	dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width,
+			out_height, ilace, color_mode, rotation);
+
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_NV12:
+		if (chroma_upscale) {
+			/* UV is subsampled by 2 horizontally and vertically */
+			orig_height >>= 1;
+			orig_width >>= 1;
+		} else {
+			/* UV is downsampled by 2 horizontally and vertically */
+			orig_height <<= 1;
+			orig_width <<= 1;
+		}
+
+		break;
+	case OMAP_DSS_COLOR_YUV2:
+	case OMAP_DSS_COLOR_UYVY:
+		/* For YUV422 with 90/270 rotation, we don't upsample chroma */
+		if (rotation == OMAP_DSS_ROT_0 ||
+				rotation == OMAP_DSS_ROT_180) {
+			if (chroma_upscale)
+				/* UV is subsampled by 2 horizontally */
+				orig_width >>= 1;
+			else
+				/* UV is downsampled by 2 horizontally */
+				orig_width <<= 1;
+		}
+
+		/* must use FIR for YUV422 if rotated */
+		if (rotation != OMAP_DSS_ROT_0)
+			scale_x = scale_y = true;
+
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	if (out_width != orig_width)
+		scale_x = true;
+	if (out_height != orig_height)
+		scale_y = true;
+
+	dispc_ovl_set_scale_param(plane, orig_width, orig_height,
+			out_width, out_height, five_taps,
+				rotation, DISPC_COLOR_COMPONENT_UV);
+
+	if (plane != OMAP_DSS_WB)
+		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
+			(scale_x || scale_y) ? 1 : 0, 8, 8);
+
+	/* set H scaling */
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
+	/* set V scaling */
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
+}
+
+static void dispc_ovl_set_scaling(enum omap_plane plane,
+		u16 orig_width, u16 orig_height,
+		u16 out_width, u16 out_height,
+		bool ilace, bool five_taps,
+		bool fieldmode, enum omap_color_mode color_mode,
+		u8 rotation)
+{
+	BUG_ON(plane == OMAP_DSS_GFX);
+
+	dispc_ovl_set_scaling_common(plane,
+			orig_width, orig_height,
+			out_width, out_height,
+			ilace, five_taps,
+			fieldmode, color_mode,
+			rotation);
+
+	dispc_ovl_set_scaling_uv(plane,
+		orig_width, orig_height,
+		out_width, out_height,
+		ilace, five_taps,
+		fieldmode, color_mode,
+		rotation);
+}
+
+static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+		enum omap_dss_rotation_type rotation_type,
+		bool mirroring, enum omap_color_mode color_mode)
+{
+	bool row_repeat = false;
+	int vidrot = 0;
+
+	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY) {
+
+		if (mirroring) {
+			switch (rotation) {
+			case OMAP_DSS_ROT_0:
+				vidrot = 2;
+				break;
+			case OMAP_DSS_ROT_90:
+				vidrot = 1;
+				break;
+			case OMAP_DSS_ROT_180:
+				vidrot = 0;
+				break;
+			case OMAP_DSS_ROT_270:
+				vidrot = 3;
+				break;
+			}
+		} else {
+			switch (rotation) {
+			case OMAP_DSS_ROT_0:
+				vidrot = 0;
+				break;
+			case OMAP_DSS_ROT_90:
+				vidrot = 1;
+				break;
+			case OMAP_DSS_ROT_180:
+				vidrot = 2;
+				break;
+			case OMAP_DSS_ROT_270:
+				vidrot = 3;
+				break;
+			}
+		}
+
+		if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
+			row_repeat = true;
+		else
+			row_repeat = false;
+	}
+
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
+	if (dss_has_feature(FEAT_ROWREPEATENABLE))
+		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
+			row_repeat ? 1 : 0, 18, 18);
+
+	if (color_mode == OMAP_DSS_COLOR_NV12) {
+		bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) &&
+					(rotation == OMAP_DSS_ROT_0 ||
+					rotation == OMAP_DSS_ROT_180);
+		/* DOUBLESTRIDE */
+		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22);
+	}
+
+}
+
+static int color_mode_to_bpp(enum omap_color_mode color_mode)
+{
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_CLUT1:
+		return 1;
+	case OMAP_DSS_COLOR_CLUT2:
+		return 2;
+	case OMAP_DSS_COLOR_CLUT4:
+		return 4;
+	case OMAP_DSS_COLOR_CLUT8:
+	case OMAP_DSS_COLOR_NV12:
+		return 8;
+	case OMAP_DSS_COLOR_RGB12U:
+	case OMAP_DSS_COLOR_RGB16:
+	case OMAP_DSS_COLOR_ARGB16:
+	case OMAP_DSS_COLOR_YUV2:
+	case OMAP_DSS_COLOR_UYVY:
+	case OMAP_DSS_COLOR_RGBA16:
+	case OMAP_DSS_COLOR_RGBX16:
+	case OMAP_DSS_COLOR_ARGB16_1555:
+	case OMAP_DSS_COLOR_XRGB16_1555:
+		return 16;
+	case OMAP_DSS_COLOR_RGB24P:
+		return 24;
+	case OMAP_DSS_COLOR_RGB24U:
+	case OMAP_DSS_COLOR_ARGB32:
+	case OMAP_DSS_COLOR_RGBA32:
+	case OMAP_DSS_COLOR_RGBX32:
+		return 32;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static s32 pixinc(int pixels, u8 ps)
+{
+	if (pixels == 1)
+		return 1;
+	else if (pixels > 1)
+		return 1 + (pixels - 1) * ps;
+	else if (pixels < 0)
+		return 1 - (-pixels + 1) * ps;
+	else
+		BUG();
+		return 0;
+}
+
+static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+		u16 screen_width,
+		u16 width, u16 height,
+		enum omap_color_mode color_mode, bool fieldmode,
+		unsigned int field_offset,
+		unsigned *offset0, unsigned *offset1,
+		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
+{
+	u8 ps;
+
+	/* FIXME CLUT formats */
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_CLUT1:
+	case OMAP_DSS_COLOR_CLUT2:
+	case OMAP_DSS_COLOR_CLUT4:
+	case OMAP_DSS_COLOR_CLUT8:
+		BUG();
+		return;
+	case OMAP_DSS_COLOR_YUV2:
+	case OMAP_DSS_COLOR_UYVY:
+		ps = 4;
+		break;
+	default:
+		ps = color_mode_to_bpp(color_mode) / 8;
+		break;
+	}
+
+	DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
+			width, height);
+
+	/*
+	 * field 0 = even field = bottom field
+	 * field 1 = odd field = top field
+	 */
+	switch (rotation + mirror * 4) {
+	case OMAP_DSS_ROT_0:
+	case OMAP_DSS_ROT_180:
+		/*
+		 * If the pixel format is YUV or UYVY divide the width
+		 * of the image by 2 for 0 and 180 degree rotation.
+		 */
+		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY)
+			width = width >> 1;
+	case OMAP_DSS_ROT_90:
+	case OMAP_DSS_ROT_270:
+		*offset1 = 0;
+		if (field_offset)
+			*offset0 = field_offset * screen_width * ps;
+		else
+			*offset0 = 0;
+
+		*row_inc = pixinc(1 +
+			(y_predecim * screen_width - x_predecim * width) +
+			(fieldmode ? screen_width : 0), ps);
+		*pix_inc = pixinc(x_predecim, ps);
+		break;
+
+	case OMAP_DSS_ROT_0 + 4:
+	case OMAP_DSS_ROT_180 + 4:
+		/* If the pixel format is YUV or UYVY divide the width
+		 * of the image by 2  for 0 degree and 180 degree
+		 */
+		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY)
+			width = width >> 1;
+	case OMAP_DSS_ROT_90 + 4:
+	case OMAP_DSS_ROT_270 + 4:
+		*offset1 = 0;
+		if (field_offset)
+			*offset0 = field_offset * screen_width * ps;
+		else
+			*offset0 = 0;
+		*row_inc = pixinc(1 -
+			(y_predecim * screen_width + x_predecim * width) -
+			(fieldmode ? screen_width : 0), ps);
+		*pix_inc = pixinc(x_predecim, ps);
+		break;
+
+	default:
+		BUG();
+		return;
+	}
+}
+
+static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+		u16 screen_width,
+		u16 width, u16 height,
+		enum omap_color_mode color_mode, bool fieldmode,
+		unsigned int field_offset,
+		unsigned *offset0, unsigned *offset1,
+		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
+{
+	u8 ps;
+	u16 fbw, fbh;
+
+	/* FIXME CLUT formats */
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_CLUT1:
+	case OMAP_DSS_COLOR_CLUT2:
+	case OMAP_DSS_COLOR_CLUT4:
+	case OMAP_DSS_COLOR_CLUT8:
+		BUG();
+		return;
+	default:
+		ps = color_mode_to_bpp(color_mode) / 8;
+		break;
+	}
+
+	DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
+			width, height);
+
+	/* width & height are overlay sizes, convert to fb sizes */
+
+	if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) {
+		fbw = width;
+		fbh = height;
+	} else {
+		fbw = height;
+		fbh = width;
+	}
+
+	/*
+	 * field 0 = even field = bottom field
+	 * field 1 = odd field = top field
+	 */
+	switch (rotation + mirror * 4) {
+	case OMAP_DSS_ROT_0:
+		*offset1 = 0;
+		if (field_offset)
+			*offset0 = *offset1 + field_offset * screen_width * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(1 +
+			(y_predecim * screen_width - fbw * x_predecim) +
+			(fieldmode ? screen_width : 0),	ps);
+		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(x_predecim, ps);
+		break;
+	case OMAP_DSS_ROT_90:
+		*offset1 = screen_width * (fbh - 1) * ps;
+		if (field_offset)
+			*offset0 = *offset1 + field_offset * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(screen_width * (fbh * x_predecim - 1) +
+				y_predecim + (fieldmode ? 1 : 0), ps);
+		*pix_inc = pixinc(-x_predecim * screen_width, ps);
+		break;
+	case OMAP_DSS_ROT_180:
+		*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+		if (field_offset)
+			*offset0 = *offset1 - field_offset * screen_width * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(-1 -
+			(y_predecim * screen_width - fbw * x_predecim) -
+			(fieldmode ? screen_width : 0),	ps);
+		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(-x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(-x_predecim, ps);
+		break;
+	case OMAP_DSS_ROT_270:
+		*offset1 = (fbw - 1) * ps;
+		if (field_offset)
+			*offset0 = *offset1 - field_offset * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) -
+				y_predecim - (fieldmode ? 1 : 0), ps);
+		*pix_inc = pixinc(x_predecim * screen_width, ps);
+		break;
+
+	/* mirroring */
+	case OMAP_DSS_ROT_0 + 4:
+		*offset1 = (fbw - 1) * ps;
+		if (field_offset)
+			*offset0 = *offset1 + field_offset * screen_width * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(y_predecim * screen_width * 2 - 1 +
+				(fieldmode ? screen_width : 0),
+				ps);
+		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(-x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(-x_predecim, ps);
+		break;
+
+	case OMAP_DSS_ROT_90 + 4:
+		*offset1 = 0;
+		if (field_offset)
+			*offset0 = *offset1 + field_offset * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) +
+				y_predecim + (fieldmode ? 1 : 0),
+				ps);
+		*pix_inc = pixinc(x_predecim * screen_width, ps);
+		break;
+
+	case OMAP_DSS_ROT_180 + 4:
+		*offset1 = screen_width * (fbh - 1) * ps;
+		if (field_offset)
+			*offset0 = *offset1 - field_offset * screen_width * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(1 - y_predecim * screen_width * 2 -
+				(fieldmode ? screen_width : 0),
+				ps);
+		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(x_predecim, ps);
+		break;
+
+	case OMAP_DSS_ROT_270 + 4:
+		*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+		if (field_offset)
+			*offset0 = *offset1 - field_offset * ps;
+		else
+			*offset0 = *offset1;
+		*row_inc = pixinc(screen_width * (fbh * x_predecim - 1) -
+				y_predecim - (fieldmode ? 1 : 0),
+				ps);
+		*pix_inc = pixinc(-x_predecim * screen_width, ps);
+		break;
+
+	default:
+		BUG();
+		return;
+	}
+}
+
+static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
+		enum omap_color_mode color_mode, bool fieldmode,
+		unsigned int field_offset, unsigned *offset0, unsigned *offset1,
+		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
+{
+	u8 ps;
+
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_CLUT1:
+	case OMAP_DSS_COLOR_CLUT2:
+	case OMAP_DSS_COLOR_CLUT4:
+	case OMAP_DSS_COLOR_CLUT8:
+		BUG();
+		return;
+	default:
+		ps = color_mode_to_bpp(color_mode) / 8;
+		break;
+	}
+
+	DSSDBG("scrw %d, width %d\n", screen_width, width);
+
+	/*
+	 * field 0 = even field = bottom field
+	 * field 1 = odd field = top field
+	 */
+	*offset1 = 0;
+	if (field_offset)
+		*offset0 = *offset1 + field_offset * screen_width * ps;
+	else
+		*offset0 = *offset1;
+	*row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) +
+			(fieldmode ? screen_width : 0), ps);
+	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+		color_mode == OMAP_DSS_COLOR_UYVY)
+		*pix_inc = pixinc(x_predecim, 2 * ps);
+	else
+		*pix_inc = pixinc(x_predecim, ps);
+}
+
+/*
+ * This function is used to avoid synclosts in OMAP3, because of some
+ * undocumented horizontal position and timing related limitations.
+ */
+static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
+		const struct omap_video_timings *t, u16 pos_x,
+		u16 width, u16 height, u16 out_width, u16 out_height,
+		bool five_taps)
+{
+	const int ds = DIV_ROUND_UP(height, out_height);
+	unsigned long nonactive;
+	static const u8 limits[3] = { 8, 10, 20 };
+	u64 val, blank;
+	int i;
+
+	nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
+
+	i = 0;
+	if (out_height < height)
+		i++;
+	if (out_width < width)
+		i++;
+	blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
+	DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
+	if (blank <= limits[i])
+		return -EINVAL;
+
+	/* FIXME add checks for 3-tap filter once the limitations are known */
+	if (!five_taps)
+		return 0;
+
+	/*
+	 * Pixel data should be prepared before visible display point starts.
+	 * So, atleast DS-2 lines must have already been fetched by DISPC
+	 * during nonactive - pos_x period.
+	 */
+	val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
+	DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
+		val, max(0, ds - 2) * width);
+	if (val < max(0, ds - 2) * width)
+		return -EINVAL;
+
+	/*
+	 * All lines need to be refilled during the nonactive period of which
+	 * only one line can be loaded during the active period. So, atleast
+	 * DS - 1 lines should be loaded during nonactive period.
+	 */
+	val =  div_u64((u64)nonactive * lclk, pclk);
+	DSSDBG("nonactive * pcd  = %llu, max(0, DS - 1) * width = %d\n",
+		val, max(0, ds - 1) * width);
+	if (val < max(0, ds - 1) * width)
+		return -EINVAL;
+
+	return 0;
+}
+
+static unsigned long calc_core_clk_five_taps(unsigned long pclk,
+		const struct omap_video_timings *mgr_timings, u16 width,
+		u16 height, u16 out_width, u16 out_height,
+		enum omap_color_mode color_mode)
+{
+	u32 core_clk = 0;
+	u64 tmp;
+
+	if (height <= out_height && width <= out_width)
+		return (unsigned long) pclk;
+
+	if (height > out_height) {
+		unsigned int ppl = mgr_timings->x_res;
+
+		tmp = pclk * height * out_width;
+		do_div(tmp, 2 * out_height * ppl);
+		core_clk = tmp;
+
+		if (height > 2 * out_height) {
+			if (ppl == out_width)
+				return 0;
+
+			tmp = pclk * (height - 2 * out_height) * out_width;
+			do_div(tmp, 2 * out_height * (ppl - out_width));
+			core_clk = max_t(u32, core_clk, tmp);
+		}
+	}
+
+	if (width > out_width) {
+		tmp = pclk * width;
+		do_div(tmp, out_width);
+		core_clk = max_t(u32, core_clk, tmp);
+
+		if (color_mode == OMAP_DSS_COLOR_RGB24U)
+			core_clk <<= 1;
+	}
+
+	return core_clk;
+}
+
+static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width,
+		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
+{
+	if (height > out_height && width > out_width)
+		return pclk * 4;
+	else
+		return pclk * 2;
+}
+
+static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
+		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
+{
+	unsigned int hf, vf;
+
+	/*
+	 * FIXME how to determine the 'A' factor
+	 * for the no downscaling case ?
+	 */
+
+	if (width > 3 * out_width)
+		hf = 4;
+	else if (width > 2 * out_width)
+		hf = 3;
+	else if (width > out_width)
+		hf = 2;
+	else
+		hf = 1;
+	if (height > out_height)
+		vf = 2;
+	else
+		vf = 1;
+
+	return pclk * vf * hf;
+}
+
+static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
+		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
+{
+	/*
+	 * If the overlay/writeback is in mem to mem mode, there are no
+	 * downscaling limitations with respect to pixel clock, return 1 as
+	 * required core clock to represent that we have sufficient enough
+	 * core clock to do maximum downscaling
+	 */
+	if (mem_to_mem)
+		return 1;
+
+	if (width > out_width)
+		return DIV_ROUND_UP(pclk, out_width) * width;
+	else
+		return pclk;
+}
+
+static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
+		const struct omap_video_timings *mgr_timings,
+		u16 width, u16 height, u16 out_width, u16 out_height,
+		enum omap_color_mode color_mode, bool *five_taps,
+		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+		u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
+{
+	int error;
+	u16 in_width, in_height;
+	int min_factor = min(*decim_x, *decim_y);
+	const int maxsinglelinewidth =
+			dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+	*five_taps = false;
+
+	do {
+		in_height = height / *decim_y;
+		in_width = width / *decim_x;
+		*core_clk = dispc.feat->calc_core_clk(pclk, in_width,
+				in_height, out_width, out_height, mem_to_mem);
+		error = (in_width > maxsinglelinewidth || !*core_clk ||
+			*core_clk > dispc_core_clk_rate());
+		if (error) {
+			if (*decim_x == *decim_y) {
+				*decim_x = min_factor;
+				++*decim_y;
+			} else {
+				swap(*decim_x, *decim_y);
+				if (*decim_x < *decim_y)
+					++*decim_x;
+			}
+		}
+	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+	if (in_width > maxsinglelinewidth) {
+		DSSERR("Cannot scale max input width exceeded");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
+		const struct omap_video_timings *mgr_timings,
+		u16 width, u16 height, u16 out_width, u16 out_height,
+		enum omap_color_mode color_mode, bool *five_taps,
+		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+		u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
+{
+	int error;
+	u16 in_width, in_height;
+	int min_factor = min(*decim_x, *decim_y);
+	const int maxsinglelinewidth =
+			dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+	do {
+		in_height = height / *decim_y;
+		in_width = width / *decim_x;
+		*five_taps = in_height > out_height;
+
+		if (in_width > maxsinglelinewidth)
+			if (in_height > out_height &&
+						in_height < out_height * 2)
+				*five_taps = false;
+again:
+		if (*five_taps)
+			*core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
+						in_width, in_height, out_width,
+						out_height, color_mode);
+		else
+			*core_clk = dispc.feat->calc_core_clk(pclk, in_width,
+					in_height, out_width, out_height,
+					mem_to_mem);
+
+		error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
+				pos_x, in_width, in_height, out_width,
+				out_height, *five_taps);
+		if (error && *five_taps) {
+			*five_taps = false;
+			goto again;
+		}
+
+		error = (error || in_width > maxsinglelinewidth * 2 ||
+			(in_width > maxsinglelinewidth && *five_taps) ||
+			!*core_clk || *core_clk > dispc_core_clk_rate());
+		if (error) {
+			if (*decim_x == *decim_y) {
+				*decim_x = min_factor;
+				++*decim_y;
+			} else {
+				swap(*decim_x, *decim_y);
+				if (*decim_x < *decim_y)
+					++*decim_x;
+			}
+		}
+	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+	if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
+				height, out_width, out_height, *five_taps)) {
+			DSSERR("horizontal timing too tight\n");
+			return -EINVAL;
+	}
+
+	if (in_width > (maxsinglelinewidth * 2)) {
+		DSSERR("Cannot setup scaling");
+		DSSERR("width exceeds maximum width possible");
+		return -EINVAL;
+	}
+
+	if (in_width > maxsinglelinewidth && *five_taps) {
+		DSSERR("cannot setup scaling with five taps");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
+		const struct omap_video_timings *mgr_timings,
+		u16 width, u16 height, u16 out_width, u16 out_height,
+		enum omap_color_mode color_mode, bool *five_taps,
+		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+		u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
+{
+	u16 in_width, in_width_max;
+	int decim_x_min = *decim_x;
+	u16 in_height = height / *decim_y;
+	const int maxsinglelinewidth =
+				dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
+
+	if (mem_to_mem) {
+		in_width_max = out_width * maxdownscale;
+	} else {
+		in_width_max = dispc_core_clk_rate() /
+					DIV_ROUND_UP(pclk, out_width);
+	}
+
+	*decim_x = DIV_ROUND_UP(width, in_width_max);
+
+	*decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
+	if (*decim_x > *x_predecim)
+		return -EINVAL;
+
+	do {
+		in_width = width / *decim_x;
+	} while (*decim_x <= *x_predecim &&
+			in_width > maxsinglelinewidth && ++*decim_x);
+
+	if (in_width > maxsinglelinewidth) {
+		DSSERR("Cannot scale width exceeds max line width");
+		return -EINVAL;
+	}
+
+	*core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
+				out_width, out_height, mem_to_mem);
+	return 0;
+}
+
+static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
+		enum omap_overlay_caps caps,
+		const struct omap_video_timings *mgr_timings,
+		u16 width, u16 height, u16 out_width, u16 out_height,
+		enum omap_color_mode color_mode, bool *five_taps,
+		int *x_predecim, int *y_predecim, u16 pos_x,
+		enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
+{
+	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
+	const int max_decim_limit = 16;
+	unsigned long core_clk = 0;
+	int decim_x, decim_y, ret;
+
+	if (width == out_width && height == out_height)
+		return 0;
+
+	if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
+		return -EINVAL;
+
+	if (mem_to_mem) {
+		*x_predecim = *y_predecim = 1;
+	} else {
+		*x_predecim = max_decim_limit;
+		*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
+				dss_has_feature(FEAT_BURST_2D)) ?
+				2 : max_decim_limit;
+	}
+
+	if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
+	    color_mode == OMAP_DSS_COLOR_CLUT2 ||
+	    color_mode == OMAP_DSS_COLOR_CLUT4 ||
+	    color_mode == OMAP_DSS_COLOR_CLUT8) {
+		*x_predecim = 1;
+		*y_predecim = 1;
+		*five_taps = false;
+		return 0;
+	}
+
+	decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
+	decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
+
+	if (decim_x > *x_predecim || out_width > width * 8)
+		return -EINVAL;
+
+	if (decim_y > *y_predecim || out_height > height * 8)
+		return -EINVAL;
+
+	ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
+		out_width, out_height, color_mode, five_taps,
+		x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
+		mem_to_mem);
+	if (ret)
+		return ret;
+
+	DSSDBG("required core clk rate = %lu Hz\n", core_clk);
+	DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
+
+	if (!core_clk || core_clk > dispc_core_clk_rate()) {
+		DSSERR("failed to set up scaling, "
+			"required core clk rate = %lu Hz, "
+			"current core clk rate = %lu Hz\n",
+			core_clk, dispc_core_clk_rate());
+		return -EINVAL;
+	}
+
+	*x_predecim = decim_x;
+	*y_predecim = decim_y;
+	return 0;
+}
+
+int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
+		const struct omap_overlay_info *oi,
+		const struct omap_video_timings *timings,
+		int *x_predecim, int *y_predecim)
+{
+	enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
+	bool five_taps = true;
+	bool fieldmode = false;
+	u16 in_height = oi->height;
+	u16 in_width = oi->width;
+	bool ilace = timings->interlace;
+	u16 out_width, out_height;
+	int pos_x = oi->pos_x;
+	unsigned long pclk = dispc_mgr_pclk_rate(channel);
+	unsigned long lclk = dispc_mgr_lclk_rate(channel);
+
+	out_width = oi->out_width == 0 ? oi->width : oi->out_width;
+	out_height = oi->out_height == 0 ? oi->height : oi->out_height;
+
+	if (ilace && oi->height == out_height)
+		fieldmode = true;
+
+	if (ilace) {
+		if (fieldmode)
+			in_height /= 2;
+		out_height /= 2;
+
+		DSSDBG("adjusting for ilace: height %d, out_height %d\n",
+				in_height, out_height);
+	}
+
+	if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+		return -EINVAL;
+
+	return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
+			in_height, out_width, out_height, oi->color_mode,
+			&five_taps, x_predecim, y_predecim, pos_x,
+			oi->rotation_type, false);
+}
+EXPORT_SYMBOL(dispc_ovl_check);
+
+static int dispc_ovl_setup_common(enum omap_plane plane,
+		enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
+		u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
+		u16 out_width, u16 out_height, enum omap_color_mode color_mode,
+		u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
+		u8 global_alpha, enum omap_dss_rotation_type rotation_type,
+		bool replication, const struct omap_video_timings *mgr_timings,
+		bool mem_to_mem)
+{
+	bool five_taps = true;
+	bool fieldmode = false;
+	int r, cconv = 0;
+	unsigned offset0, offset1;
+	s32 row_inc;
+	s32 pix_inc;
+	u16 frame_width, frame_height;
+	unsigned int field_offset = 0;
+	u16 in_height = height;
+	u16 in_width = width;
+	int x_predecim = 1, y_predecim = 1;
+	bool ilace = mgr_timings->interlace;
+	unsigned long pclk = dispc_plane_pclk_rate(plane);
+	unsigned long lclk = dispc_plane_lclk_rate(plane);
+
+	if (paddr == 0)
+		return -EINVAL;
+
+	out_width = out_width == 0 ? width : out_width;
+	out_height = out_height == 0 ? height : out_height;
+
+	if (ilace && height == out_height)
+		fieldmode = true;
+
+	if (ilace) {
+		if (fieldmode)
+			in_height /= 2;
+		pos_y /= 2;
+		out_height /= 2;
+
+		DSSDBG("adjusting for ilace: height %d, pos_y %d, "
+			"out_height %d\n", in_height, pos_y,
+			out_height);
+	}
+
+	if (!dss_feat_color_mode_supported(plane, color_mode))
+		return -EINVAL;
+
+	r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
+			in_height, out_width, out_height, color_mode,
+			&five_taps, &x_predecim, &y_predecim, pos_x,
+			rotation_type, mem_to_mem);
+	if (r)
+		return r;
+
+	in_width = in_width / x_predecim;
+	in_height = in_height / y_predecim;
+
+	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY ||
+			color_mode == OMAP_DSS_COLOR_NV12)
+		cconv = 1;
+
+	if (ilace && !fieldmode) {
+		/*
+		 * when downscaling the bottom field may have to start several
+		 * source lines below the top field. Unfortunately ACCUI
+		 * registers will only hold the fractional part of the offset
+		 * so the integer part must be added to the base address of the
+		 * bottom field.
+		 */
+		if (!in_height || in_height == out_height)
+			field_offset = 0;
+		else
+			field_offset = in_height / out_height / 2;
+	}
+
+	/* Fields are independent but interleaved in memory. */
+	if (fieldmode)
+		field_offset = 1;
+
+	offset0 = 0;
+	offset1 = 0;
+	row_inc = 0;
+	pix_inc = 0;
+
+	if (plane == OMAP_DSS_WB) {
+		frame_width = out_width;
+		frame_height = out_height;
+	} else {
+		frame_width = in_width;
+		frame_height = height;
+	}
+
+	if (rotation_type == OMAP_DSS_ROT_TILER)
+		calc_tiler_rotation_offset(screen_width, frame_width,
+				color_mode, fieldmode, field_offset,
+				&offset0, &offset1, &row_inc, &pix_inc,
+				x_predecim, y_predecim);
+	else if (rotation_type == OMAP_DSS_ROT_DMA)
+		calc_dma_rotation_offset(rotation, mirror, screen_width,
+				frame_width, frame_height,
+				color_mode, fieldmode, field_offset,
+				&offset0, &offset1, &row_inc, &pix_inc,
+				x_predecim, y_predecim);
+	else
+		calc_vrfb_rotation_offset(rotation, mirror,
+				screen_width, frame_width, frame_height,
+				color_mode, fieldmode, field_offset,
+				&offset0, &offset1, &row_inc, &pix_inc,
+				x_predecim, y_predecim);
+
+	DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
+			offset0, offset1, row_inc, pix_inc);
+
+	dispc_ovl_set_color_mode(plane, color_mode);
+
+	dispc_ovl_configure_burst_type(plane, rotation_type);
+
+	dispc_ovl_set_ba0(plane, paddr + offset0);
+	dispc_ovl_set_ba1(plane, paddr + offset1);
+
+	if (OMAP_DSS_COLOR_NV12 == color_mode) {
+		dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
+		dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
+	}
+
+	dispc_ovl_set_row_inc(plane, row_inc);
+	dispc_ovl_set_pix_inc(plane, pix_inc);
+
+	DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
+			in_height, out_width, out_height);
+
+	dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
+
+	dispc_ovl_set_input_size(plane, in_width, in_height);
+
+	if (caps & OMAP_DSS_OVL_CAP_SCALE) {
+		dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
+				   out_height, ilace, five_taps, fieldmode,
+				   color_mode, rotation);
+		dispc_ovl_set_output_size(plane, out_width, out_height);
+		dispc_ovl_set_vid_color_conv(plane, cconv);
+	}
+
+	dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror,
+			color_mode);
+
+	dispc_ovl_set_zorder(plane, caps, zorder);
+	dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
+	dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
+
+	dispc_ovl_enable_replication(plane, caps, replication);
+
+	return 0;
+}
+
+int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
+		bool replication, const struct omap_video_timings *mgr_timings,
+		bool mem_to_mem)
+{
+	int r;
+	enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
+	enum omap_channel channel;
+
+	channel = dispc_ovl_get_channel_out(plane);
+
+	DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
+		"%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
+		plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
+		oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
+		oi->color_mode, oi->rotation, oi->mirror, channel, replication);
+
+	r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
+		oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
+		oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
+		oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
+		oi->rotation_type, replication, mgr_timings, mem_to_mem);
+
+	return r;
+}
+EXPORT_SYMBOL(dispc_ovl_setup);
+
+int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
+		bool mem_to_mem, const struct omap_video_timings *mgr_timings)
+{
+	int r;
+	u32 l;
+	enum omap_plane plane = OMAP_DSS_WB;
+	const int pos_x = 0, pos_y = 0;
+	const u8 zorder = 0, global_alpha = 0;
+	const bool replication = false;
+	bool truncation;
+	int in_width = mgr_timings->x_res;
+	int in_height = mgr_timings->y_res;
+	enum omap_overlay_caps caps =
+		OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
+
+	DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
+		"rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
+		in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
+		wi->mirror);
+
+	r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
+		wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
+		wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
+		wi->pre_mult_alpha, global_alpha, wi->rotation_type,
+		replication, mgr_timings, mem_to_mem);
+
+	switch (wi->color_mode) {
+	case OMAP_DSS_COLOR_RGB16:
+	case OMAP_DSS_COLOR_RGB24P:
+	case OMAP_DSS_COLOR_ARGB16:
+	case OMAP_DSS_COLOR_RGBA16:
+	case OMAP_DSS_COLOR_RGB12U:
+	case OMAP_DSS_COLOR_ARGB16_1555:
+	case OMAP_DSS_COLOR_XRGB16_1555:
+	case OMAP_DSS_COLOR_RGBX16:
+		truncation = true;
+		break;
+	default:
+		truncation = false;
+		break;
+	}
+
+	/* setup extra DISPC_WB_ATTRIBUTES */
+	l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+	l = FLD_MOD(l, truncation, 10, 10);	/* TRUNCATIONENABLE */
+	l = FLD_MOD(l, mem_to_mem, 19, 19);	/* WRITEBACKMODE */
+	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
+
+	return r;
+}
+
+int dispc_ovl_enable(enum omap_plane plane, bool enable)
+{
+	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
+	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL(dispc_ovl_enable);
+
+bool dispc_ovl_enabled(enum omap_plane plane)
+{
+	return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+}
+EXPORT_SYMBOL(dispc_ovl_enabled);
+
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
+{
+	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
+	/* flush posted write */
+	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
+}
+EXPORT_SYMBOL(dispc_mgr_enable);
+
+bool dispc_mgr_is_enabled(enum omap_channel channel)
+{
+	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
+}
+EXPORT_SYMBOL(dispc_mgr_is_enabled);
+
+void dispc_wb_enable(bool enable)
+{
+	dispc_ovl_enable(OMAP_DSS_WB, enable);
+}
+
+bool dispc_wb_is_enabled(void)
+{
+	return dispc_ovl_enabled(OMAP_DSS_WB);
+}
+
+static void dispc_lcd_enable_signal_polarity(bool act_high)
+{
+	if (!dss_has_feature(FEAT_LCDENABLEPOL))
+		return;
+
+	REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
+}
+
+void dispc_lcd_enable_signal(bool enable)
+{
+	if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
+		return;
+
+	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
+}
+
+void dispc_pck_free_enable(bool enable)
+{
+	if (!dss_has_feature(FEAT_PCKFREEENABLE))
+		return;
+
+	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
+}
+
+static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
+{
+	mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
+}
+
+
+static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
+{
+	mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
+}
+
+void dispc_set_loadmode(enum omap_dss_load_mode mode)
+{
+	REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
+}
+
+
+static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
+{
+	dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
+}
+
+static void dispc_mgr_set_trans_key(enum omap_channel ch,
+		enum omap_dss_trans_key_type type,
+		u32 trans_key)
+{
+	mgr_fld_write(ch, DISPC_MGR_FLD_TCKSELECTION, type);
+
+	dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
+}
+
+static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
+{
+	mgr_fld_write(ch, DISPC_MGR_FLD_TCKENABLE, enable);
+}
+
+static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
+		bool enable)
+{
+	if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
+		return;
+
+	if (ch == OMAP_DSS_CHANNEL_LCD)
+		REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
+	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+		REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
+}
+
+void dispc_mgr_setup(enum omap_channel channel,
+		const struct omap_overlay_manager_info *info)
+{
+	dispc_mgr_set_default_color(channel, info->default_color);
+	dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
+	dispc_mgr_enable_trans_key(channel, info->trans_enabled);
+	dispc_mgr_enable_alpha_fixed_zorder(channel,
+			info->partial_alpha_enabled);
+	if (dss_has_feature(FEAT_CPR)) {
+		dispc_mgr_enable_cpr(channel, info->cpr_enable);
+		dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
+	}
+}
+EXPORT_SYMBOL(dispc_mgr_setup);
+
+static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+{
+	int code;
+
+	switch (data_lines) {
+	case 12:
+		code = 0;
+		break;
+	case 16:
+		code = 1;
+		break;
+	case 18:
+		code = 2;
+		break;
+	case 24:
+		code = 3;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
+}
+
+static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
+{
+	u32 l;
+	int gpout0, gpout1;
+
+	switch (mode) {
+	case DSS_IO_PAD_MODE_RESET:
+		gpout0 = 0;
+		gpout1 = 0;
+		break;
+	case DSS_IO_PAD_MODE_RFBI:
+		gpout0 = 1;
+		gpout1 = 0;
+		break;
+	case DSS_IO_PAD_MODE_BYPASS:
+		gpout0 = 1;
+		gpout1 = 1;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	l = dispc_read_reg(DISPC_CONTROL);
+	l = FLD_MOD(l, gpout0, 15, 15);
+	l = FLD_MOD(l, gpout1, 16, 16);
+	dispc_write_reg(DISPC_CONTROL, l);
+}
+
+static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
+{
+	mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
+}
+
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+		const struct dss_lcd_mgr_config *config)
+{
+	dispc_mgr_set_io_pad_mode(config->io_pad_mode);
+
+	dispc_mgr_enable_stallmode(channel, config->stallmode);
+	dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
+
+	dispc_mgr_set_clock_div(channel, &config->clock_info);
+
+	dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
+
+	dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
+
+	dispc_mgr_set_lcd_type_tft(channel);
+}
+EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
+
+static bool _dispc_mgr_size_ok(u16 width, u16 height)
+{
+	return width <= dispc.feat->mgr_width_max &&
+		height <= dispc.feat->mgr_height_max;
+}
+
+static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
+		int vsw, int vfp, int vbp)
+{
+	if (hsw < 1 || hsw > dispc.feat->sw_max ||
+			hfp < 1 || hfp > dispc.feat->hp_max ||
+			hbp < 1 || hbp > dispc.feat->hp_max ||
+			vsw < 1 || vsw > dispc.feat->sw_max ||
+			vfp < 0 || vfp > dispc.feat->vp_max ||
+			vbp < 0 || vbp > dispc.feat->vp_max)
+		return false;
+	return true;
+}
+
+static bool _dispc_mgr_pclk_ok(enum omap_channel channel,
+		unsigned long pclk)
+{
+	if (dss_mgr_is_lcd(channel))
+		return pclk <= dispc.feat->max_lcd_pclk ? true : false;
+	else
+		return pclk <= dispc.feat->max_tv_pclk ? true : false;
+}
+
+bool dispc_mgr_timings_ok(enum omap_channel channel,
+		const struct omap_video_timings *timings)
+{
+	bool timings_ok;
+
+	timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
+
+	timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixelclock);
+
+	if (dss_mgr_is_lcd(channel)) {
+		timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
+				timings->hbp, timings->vsw, timings->vfp,
+				timings->vbp);
+	}
+
+	return timings_ok;
+}
+
+static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
+		int hfp, int hbp, int vsw, int vfp, int vbp,
+		enum omap_dss_signal_level vsync_level,
+		enum omap_dss_signal_level hsync_level,
+		enum omap_dss_signal_edge data_pclk_edge,
+		enum omap_dss_signal_level de_level,
+		enum omap_dss_signal_edge sync_pclk_edge)
+
+{
+	u32 timing_h, timing_v, l;
+	bool onoff, rf, ipc;
+
+	timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
+			FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
+			FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
+	timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
+			FLD_VAL(vfp, dispc.feat->fp_start, 8) |
+			FLD_VAL(vbp, dispc.feat->bp_start, 20);
+
+	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
+	dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
+
+	switch (data_pclk_edge) {
+	case OMAPDSS_DRIVE_SIG_RISING_EDGE:
+		ipc = false;
+		break;
+	case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
+		ipc = true;
+		break;
+	case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
+	default:
+		BUG();
+	}
+
+	switch (sync_pclk_edge) {
+	case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
+		onoff = false;
+		rf = false;
+		break;
+	case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
+		onoff = true;
+		rf = false;
+		break;
+	case OMAPDSS_DRIVE_SIG_RISING_EDGE:
+		onoff = true;
+		rf = true;
+		break;
+	default:
+		BUG();
+	}
+
+	l = dispc_read_reg(DISPC_POL_FREQ(channel));
+	l |= FLD_VAL(onoff, 17, 17);
+	l |= FLD_VAL(rf, 16, 16);
+	l |= FLD_VAL(de_level, 15, 15);
+	l |= FLD_VAL(ipc, 14, 14);
+	l |= FLD_VAL(hsync_level, 13, 13);
+	l |= FLD_VAL(vsync_level, 12, 12);
+	dispc_write_reg(DISPC_POL_FREQ(channel), l);
+}
+
+/* change name to mode? */
+void dispc_mgr_set_timings(enum omap_channel channel,
+		const struct omap_video_timings *timings)
+{
+	unsigned xtot, ytot;
+	unsigned long ht, vt;
+	struct omap_video_timings t = *timings;
+
+	DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
+
+	if (!dispc_mgr_timings_ok(channel, &t)) {
+		BUG();
+		return;
+	}
+
+	if (dss_mgr_is_lcd(channel)) {
+		_dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
+				t.vfp, t.vbp, t.vsync_level, t.hsync_level,
+				t.data_pclk_edge, t.de_level, t.sync_pclk_edge);
+
+		xtot = t.x_res + t.hfp + t.hsw + t.hbp;
+		ytot = t.y_res + t.vfp + t.vsw + t.vbp;
+
+		ht = timings->pixelclock / xtot;
+		vt = timings->pixelclock / xtot / ytot;
+
+		DSSDBG("pck %u\n", timings->pixelclock);
+		DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
+			t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
+		DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n",
+			t.vsync_level, t.hsync_level, t.data_pclk_edge,
+			t.de_level, t.sync_pclk_edge);
+
+		DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
+	} else {
+		if (t.interlace == true)
+			t.y_res /= 2;
+	}
+
+	dispc_mgr_set_size(channel, t.x_res, t.y_res);
+}
+EXPORT_SYMBOL(dispc_mgr_set_timings);
+
+static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
+		u16 pck_div)
+{
+	BUG_ON(lck_div < 1);
+	BUG_ON(pck_div < 1);
+
+	dispc_write_reg(DISPC_DIVISORo(channel),
+			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+
+	if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
+			channel == OMAP_DSS_CHANNEL_LCD)
+		dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
+}
+
+static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
+		int *pck_div)
+{
+	u32 l;
+	l = dispc_read_reg(DISPC_DIVISORo(channel));
+	*lck_div = FLD_GET(l, 23, 16);
+	*pck_div = FLD_GET(l, 7, 0);
+}
+
+unsigned long dispc_fclk_rate(void)
+{
+	struct platform_device *dsidev;
+	unsigned long r = 0;
+
+	switch (dss_get_dispc_clk_source()) {
+	case OMAP_DSS_CLK_SRC_FCK:
+		r = dss_get_dispc_clk_rate();
+		break;
+	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+		dsidev = dsi_get_dsidev_from_id(0);
+		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+		break;
+	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+		dsidev = dsi_get_dsidev_from_id(1);
+		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+		break;
+	default:
+		BUG();
+		return 0;
+	}
+
+	return r;
+}
+
+unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
+{
+	struct platform_device *dsidev;
+	int lcd;
+	unsigned long r;
+	u32 l;
+
+	if (dss_mgr_is_lcd(channel)) {
+		l = dispc_read_reg(DISPC_DIVISORo(channel));
+
+		lcd = FLD_GET(l, 23, 16);
+
+		switch (dss_get_lcd_clk_source(channel)) {
+		case OMAP_DSS_CLK_SRC_FCK:
+			r = dss_get_dispc_clk_rate();
+			break;
+		case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+			dsidev = dsi_get_dsidev_from_id(0);
+			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+			break;
+		case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+			dsidev = dsi_get_dsidev_from_id(1);
+			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+			break;
+		default:
+			BUG();
+			return 0;
+		}
+
+		return r / lcd;
+	} else {
+		return dispc_fclk_rate();
+	}
+}
+
+unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
+{
+	unsigned long r;
+
+	if (dss_mgr_is_lcd(channel)) {
+		int pcd;
+		u32 l;
+
+		l = dispc_read_reg(DISPC_DIVISORo(channel));
+
+		pcd = FLD_GET(l, 7, 0);
+
+		r = dispc_mgr_lclk_rate(channel);
+
+		return r / pcd;
+	} else {
+		return dispc.tv_pclk_rate;
+	}
+}
+
+void dispc_set_tv_pclk(unsigned long pclk)
+{
+	dispc.tv_pclk_rate = pclk;
+}
+
+unsigned long dispc_core_clk_rate(void)
+{
+	return dispc.core_clk_rate;
+}
+
+static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
+{
+	enum omap_channel channel;
+
+	if (plane == OMAP_DSS_WB)
+		return 0;
+
+	channel = dispc_ovl_get_channel_out(plane);
+
+	return dispc_mgr_pclk_rate(channel);
+}
+
+static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
+{
+	enum omap_channel channel;
+
+	if (plane == OMAP_DSS_WB)
+		return 0;
+
+	channel	= dispc_ovl_get_channel_out(plane);
+
+	return dispc_mgr_lclk_rate(channel);
+}
+
+static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
+{
+	int lcd, pcd;
+	enum omap_dss_clk_source lcd_clk_src;
+
+	seq_printf(s, "- %s -\n", mgr_desc[channel].name);
+
+	lcd_clk_src = dss_get_lcd_clk_source(channel);
+
+	seq_printf(s, "%s clk source = %s (%s)\n", mgr_desc[channel].name,
+		dss_get_generic_clk_source_name(lcd_clk_src),
+		dss_feat_get_clk_source_name(lcd_clk_src));
+
+	dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd);
+
+	seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
+		dispc_mgr_lclk_rate(channel), lcd);
+	seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
+		dispc_mgr_pclk_rate(channel), pcd);
+}
+
+void dispc_dump_clocks(struct seq_file *s)
+{
+	int lcd;
+	u32 l;
+	enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
+
+	if (dispc_runtime_get())
+		return;
+
+	seq_printf(s, "- DISPC -\n");
+
+	seq_printf(s, "dispc fclk source = %s (%s)\n",
+			dss_get_generic_clk_source_name(dispc_clk_src),
+			dss_feat_get_clk_source_name(dispc_clk_src));
+
+	seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
+
+	if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
+		seq_printf(s, "- DISPC-CORE-CLK -\n");
+		l = dispc_read_reg(DISPC_DIVISOR);
+		lcd = FLD_GET(l, 23, 16);
+
+		seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
+				(dispc_fclk_rate()/lcd), lcd);
+	}
+
+	dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD);
+
+	if (dss_has_feature(FEAT_MGR_LCD2))
+		dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2);
+	if (dss_has_feature(FEAT_MGR_LCD3))
+		dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3);
+
+	dispc_runtime_put();
+}
+
+static void dispc_dump_regs(struct seq_file *s)
+{
+	int i, j;
+	const char *mgr_names[] = {
+		[OMAP_DSS_CHANNEL_LCD]		= "LCD",
+		[OMAP_DSS_CHANNEL_DIGIT]	= "TV",
+		[OMAP_DSS_CHANNEL_LCD2]		= "LCD2",
+		[OMAP_DSS_CHANNEL_LCD3]		= "LCD3",
+	};
+	const char *ovl_names[] = {
+		[OMAP_DSS_GFX]		= "GFX",
+		[OMAP_DSS_VIDEO1]	= "VID1",
+		[OMAP_DSS_VIDEO2]	= "VID2",
+		[OMAP_DSS_VIDEO3]	= "VID3",
+	};
+	const char **p_names;
+
+#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
+
+	if (dispc_runtime_get())
+		return;
+
+	/* DISPC common registers */
+	DUMPREG(DISPC_REVISION);
+	DUMPREG(DISPC_SYSCONFIG);
+	DUMPREG(DISPC_SYSSTATUS);
+	DUMPREG(DISPC_IRQSTATUS);
+	DUMPREG(DISPC_IRQENABLE);
+	DUMPREG(DISPC_CONTROL);
+	DUMPREG(DISPC_CONFIG);
+	DUMPREG(DISPC_CAPABLE);
+	DUMPREG(DISPC_LINE_STATUS);
+	DUMPREG(DISPC_LINE_NUMBER);
+	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
+		DUMPREG(DISPC_GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_MGR_LCD2)) {
+		DUMPREG(DISPC_CONTROL2);
+		DUMPREG(DISPC_CONFIG2);
+	}
+	if (dss_has_feature(FEAT_MGR_LCD3)) {
+		DUMPREG(DISPC_CONTROL3);
+		DUMPREG(DISPC_CONFIG3);
+	}
+	if (dss_has_feature(FEAT_MFLAG))
+		DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE);
+
+#undef DUMPREG
+
+#define DISPC_REG(i, name) name(i)
+#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
+	(int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
+	dispc_read_reg(DISPC_REG(i, r)))
+
+	p_names = mgr_names;
+
+	/* DISPC channel specific registers */
+	for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+		DUMPREG(i, DISPC_DEFAULT_COLOR);
+		DUMPREG(i, DISPC_TRANS_COLOR);
+		DUMPREG(i, DISPC_SIZE_MGR);
+
+		if (i == OMAP_DSS_CHANNEL_DIGIT)
+			continue;
+
+		DUMPREG(i, DISPC_DEFAULT_COLOR);
+		DUMPREG(i, DISPC_TRANS_COLOR);
+		DUMPREG(i, DISPC_TIMING_H);
+		DUMPREG(i, DISPC_TIMING_V);
+		DUMPREG(i, DISPC_POL_FREQ);
+		DUMPREG(i, DISPC_DIVISORo);
+		DUMPREG(i, DISPC_SIZE_MGR);
+
+		DUMPREG(i, DISPC_DATA_CYCLE1);
+		DUMPREG(i, DISPC_DATA_CYCLE2);
+		DUMPREG(i, DISPC_DATA_CYCLE3);
+
+		if (dss_has_feature(FEAT_CPR)) {
+			DUMPREG(i, DISPC_CPR_COEF_R);
+			DUMPREG(i, DISPC_CPR_COEF_G);
+			DUMPREG(i, DISPC_CPR_COEF_B);
+		}
+	}
+
+	p_names = ovl_names;
+
+	for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+		DUMPREG(i, DISPC_OVL_BA0);
+		DUMPREG(i, DISPC_OVL_BA1);
+		DUMPREG(i, DISPC_OVL_POSITION);
+		DUMPREG(i, DISPC_OVL_SIZE);
+		DUMPREG(i, DISPC_OVL_ATTRIBUTES);
+		DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD);
+		DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS);
+		DUMPREG(i, DISPC_OVL_ROW_INC);
+		DUMPREG(i, DISPC_OVL_PIXEL_INC);
+		if (dss_has_feature(FEAT_PRELOAD))
+			DUMPREG(i, DISPC_OVL_PRELOAD);
+
+		if (i == OMAP_DSS_GFX) {
+			DUMPREG(i, DISPC_OVL_WINDOW_SKIP);
+			DUMPREG(i, DISPC_OVL_TABLE_BA);
+			continue;
+		}
+
+		DUMPREG(i, DISPC_OVL_FIR);
+		DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
+		DUMPREG(i, DISPC_OVL_ACCU0);
+		DUMPREG(i, DISPC_OVL_ACCU1);
+		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+			DUMPREG(i, DISPC_OVL_BA0_UV);
+			DUMPREG(i, DISPC_OVL_BA1_UV);
+			DUMPREG(i, DISPC_OVL_FIR2);
+			DUMPREG(i, DISPC_OVL_ACCU2_0);
+			DUMPREG(i, DISPC_OVL_ACCU2_1);
+		}
+		if (dss_has_feature(FEAT_ATTR2))
+			DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
+		if (dss_has_feature(FEAT_PRELOAD))
+			DUMPREG(i, DISPC_OVL_PRELOAD);
+		if (dss_has_feature(FEAT_MFLAG))
+			DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
+	}
+
+#undef DISPC_REG
+#undef DUMPREG
+
+#define DISPC_REG(plane, name, i) name(plane, i)
+#define DUMPREG(plane, name, i) \
+	seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
+	(int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
+	dispc_read_reg(DISPC_REG(plane, name, i)))
+
+	/* Video pipeline coefficient registers */
+
+	/* start from OMAP_DSS_VIDEO1 */
+	for (i = 1; i < dss_feat_get_num_ovls(); i++) {
+		for (j = 0; j < 8; j++)
+			DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
+
+		for (j = 0; j < 8; j++)
+			DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j);
+
+		for (j = 0; j < 5; j++)
+			DUMPREG(i, DISPC_OVL_CONV_COEF, j);
+
+		if (dss_has_feature(FEAT_FIR_COEF_V)) {
+			for (j = 0; j < 8; j++)
+				DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
+		}
+
+		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+			for (j = 0; j < 8; j++)
+				DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
+
+			for (j = 0; j < 8; j++)
+				DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j);
+
+			for (j = 0; j < 8; j++)
+				DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j);
+		}
+	}
+
+	dispc_runtime_put();
+
+#undef DISPC_REG
+#undef DUMPREG
+}
+
+/* calculate clock rates using dividers in cinfo */
+int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
+		struct dispc_clock_info *cinfo)
+{
+	if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
+		return -EINVAL;
+	if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
+		return -EINVAL;
+
+	cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
+	cinfo->pck = cinfo->lck / cinfo->pck_div;
+
+	return 0;
+}
+
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data)
+{
+	int lckd, lckd_start, lckd_stop;
+	int pckd, pckd_start, pckd_stop;
+	unsigned long pck, lck;
+	unsigned long lck_max;
+	unsigned long pckd_hw_min, pckd_hw_max;
+	unsigned min_fck_per_pck;
+	unsigned long fck;
+
+#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
+	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+#else
+	min_fck_per_pck = 0;
+#endif
+
+	pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
+	pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
+
+	lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	pck_min = pck_min ? pck_min : 1;
+	pck_max = pck_max ? pck_max : ULONG_MAX;
+
+	lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
+	lckd_stop = min(dispc / pck_min, 255ul);
+
+	for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
+		lck = dispc / lckd;
+
+		pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
+		pckd_stop = min(lck / pck_min, pckd_hw_max);
+
+		for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
+			pck = lck / pckd;
+
+			/*
+			 * For OMAP2/3 the DISPC fclk is the same as LCD's logic
+			 * clock, which means we're configuring DISPC fclk here
+			 * also. Thus we need to use the calculated lck. For
+			 * OMAP4+ the DISPC fclk is a separate clock.
+			 */
+			if (dss_has_feature(FEAT_CORE_CLK_DIV))
+				fck = dispc_core_clk_rate();
+			else
+				fck = lck;
+
+			if (fck < pck * min_fck_per_pck)
+				continue;
+
+			if (func(lckd, pckd, lck, pck, data))
+				return true;
+		}
+	}
+
+	return false;
+}
+
+void dispc_mgr_set_clock_div(enum omap_channel channel,
+		const struct dispc_clock_info *cinfo)
+{
+	DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
+	DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
+
+	dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
+}
+
+int dispc_mgr_get_clock_div(enum omap_channel channel,
+		struct dispc_clock_info *cinfo)
+{
+	unsigned long fck;
+
+	fck = dispc_fclk_rate();
+
+	cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
+	cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
+
+	cinfo->lck = fck / cinfo->lck_div;
+	cinfo->pck = cinfo->lck / cinfo->pck_div;
+
+	return 0;
+}
+
+u32 dispc_read_irqstatus(void)
+{
+	return dispc_read_reg(DISPC_IRQSTATUS);
+}
+EXPORT_SYMBOL(dispc_read_irqstatus);
+
+void dispc_clear_irqstatus(u32 mask)
+{
+	dispc_write_reg(DISPC_IRQSTATUS, mask);
+}
+EXPORT_SYMBOL(dispc_clear_irqstatus);
+
+u32 dispc_read_irqenable(void)
+{
+	return dispc_read_reg(DISPC_IRQENABLE);
+}
+EXPORT_SYMBOL(dispc_read_irqenable);
+
+void dispc_write_irqenable(u32 mask)
+{
+	u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
+
+	/* clear the irqstatus for newly enabled irqs */
+	dispc_clear_irqstatus((mask ^ old_mask) & mask);
+
+	dispc_write_reg(DISPC_IRQENABLE, mask);
+}
+EXPORT_SYMBOL(dispc_write_irqenable);
+
+void dispc_enable_sidle(void)
+{
+	REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3);	/* SIDLEMODE: smart idle */
+}
+
+void dispc_disable_sidle(void)
+{
+	REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3);	/* SIDLEMODE: no idle */
+}
+
+static void _omap_dispc_initial_config(void)
+{
+	u32 l;
+
+	/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
+	if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
+		l = dispc_read_reg(DISPC_DIVISOR);
+		/* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
+		l = FLD_MOD(l, 1, 0, 0);
+		l = FLD_MOD(l, 1, 23, 16);
+		dispc_write_reg(DISPC_DIVISOR, l);
+
+		dispc.core_clk_rate = dispc_fclk_rate();
+	}
+
+	/* FUNCGATED */
+	if (dss_has_feature(FEAT_FUNCGATED))
+		REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
+
+	dispc_setup_color_conv_coef();
+
+	dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
+
+	dispc_init_fifos();
+
+	dispc_configure_burst_sizes();
+
+	dispc_ovl_enable_zorder_planes();
+
+	if (dispc.feat->mstandby_workaround)
+		REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);
+}
+
+static const struct dispc_features omap24xx_dispc_feats __initconst = {
+	.sw_start		=	5,
+	.fp_start		=	15,
+	.bp_start		=	27,
+	.sw_max			=	64,
+	.vp_max			=	255,
+	.hp_max			=	256,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
+	.max_lcd_pclk		=	66500000,
+	.calc_scaling		=	dispc_ovl_calc_scaling_24xx,
+	.calc_core_clk		=	calc_core_clk_24xx,
+	.num_fifos		=	3,
+	.no_framedone_tv	=	true,
+	.set_max_preload	=	false,
+};
+
+static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
+	.sw_start		=	5,
+	.fp_start		=	15,
+	.bp_start		=	27,
+	.sw_max			=	64,
+	.vp_max			=	255,
+	.hp_max			=	256,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
+	.max_lcd_pclk		=	173000000,
+	.max_tv_pclk		=	59000000,
+	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
+	.calc_core_clk		=	calc_core_clk_34xx,
+	.num_fifos		=	3,
+	.no_framedone_tv	=	true,
+	.set_max_preload	=	false,
+};
+
+static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
+	.sw_start		=	7,
+	.fp_start		=	19,
+	.bp_start		=	31,
+	.sw_max			=	256,
+	.vp_max			=	4095,
+	.hp_max			=	4096,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
+	.max_lcd_pclk		=	173000000,
+	.max_tv_pclk		=	59000000,
+	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
+	.calc_core_clk		=	calc_core_clk_34xx,
+	.num_fifos		=	3,
+	.no_framedone_tv	=	true,
+	.set_max_preload	=	false,
+};
+
+static const struct dispc_features omap44xx_dispc_feats __initconst = {
+	.sw_start		=	7,
+	.fp_start		=	19,
+	.bp_start		=	31,
+	.sw_max			=	256,
+	.vp_max			=	4095,
+	.hp_max			=	4096,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
+	.max_lcd_pclk		=	170000000,
+	.max_tv_pclk		=	185625000,
+	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
+	.calc_core_clk		=	calc_core_clk_44xx,
+	.num_fifos		=	5,
+	.gfx_fifo_workaround	=	true,
+	.set_max_preload	=	true,
+};
+
+static const struct dispc_features omap54xx_dispc_feats __initconst = {
+	.sw_start		=	7,
+	.fp_start		=	19,
+	.bp_start		=	31,
+	.sw_max			=	256,
+	.vp_max			=	4095,
+	.hp_max			=	4096,
+	.mgr_width_start	=	11,
+	.mgr_height_start	=	27,
+	.mgr_width_max		=	4096,
+	.mgr_height_max		=	4096,
+	.max_lcd_pclk		=	170000000,
+	.max_tv_pclk		=	186000000,
+	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
+	.calc_core_clk		=	calc_core_clk_44xx,
+	.num_fifos		=	5,
+	.gfx_fifo_workaround	=	true,
+	.mstandby_workaround	=	true,
+	.set_max_preload	=	true,
+};
+
+static int __init dispc_init_features(struct platform_device *pdev)
+{
+	const struct dispc_features *src;
+	struct dispc_features *dst;
+
+	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
+	if (!dst) {
+		dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
+		return -ENOMEM;
+	}
+
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+		src = &omap24xx_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+		src = &omap34xx_rev1_0_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		src = &omap34xx_rev3_0_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		src = &omap44xx_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP5:
+		src = &omap54xx_dispc_feats;
+		break;
+
+	default:
+		return -ENODEV;
+	}
+
+	memcpy(dst, src, sizeof(*dst));
+	dispc.feat = dst;
+
+	return 0;
+}
+
+static irqreturn_t dispc_irq_handler(int irq, void *arg)
+{
+	if (!dispc.is_enabled)
+		return IRQ_NONE;
+
+	return dispc.user_handler(irq, dispc.user_data);
+}
+
+int dispc_request_irq(irq_handler_t handler, void *dev_id)
+{
+	int r;
+
+	if (dispc.user_handler != NULL)
+		return -EBUSY;
+
+	dispc.user_handler = handler;
+	dispc.user_data = dev_id;
+
+	/* ensure the dispc_irq_handler sees the values above */
+	smp_wmb();
+
+	r = devm_request_irq(&dispc.pdev->dev, dispc.irq, dispc_irq_handler,
+			     IRQF_SHARED, "OMAP DISPC", &dispc);
+	if (r) {
+		dispc.user_handler = NULL;
+		dispc.user_data = NULL;
+	}
+
+	return r;
+}
+EXPORT_SYMBOL(dispc_request_irq);
+
+void dispc_free_irq(void *dev_id)
+{
+	devm_free_irq(&dispc.pdev->dev, dispc.irq, &dispc);
+
+	dispc.user_handler = NULL;
+	dispc.user_data = NULL;
+}
+EXPORT_SYMBOL(dispc_free_irq);
+
+/* DISPC HW IP initialisation */
+static int __init omap_dispchw_probe(struct platform_device *pdev)
+{
+	u32 rev;
+	int r = 0;
+	struct resource *dispc_mem;
+
+	dispc.pdev = pdev;
+
+	r = dispc_init_features(dispc.pdev);
+	if (r)
+		return r;
+
+	dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
+	if (!dispc_mem) {
+		DSSERR("can't get IORESOURCE_MEM DISPC\n");
+		return -EINVAL;
+	}
+
+	dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start,
+				  resource_size(dispc_mem));
+	if (!dispc.base) {
+		DSSERR("can't ioremap DISPC\n");
+		return -ENOMEM;
+	}
+
+	dispc.irq = platform_get_irq(dispc.pdev, 0);
+	if (dispc.irq < 0) {
+		DSSERR("platform_get_irq failed\n");
+		return -ENODEV;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_runtime_get;
+
+	_omap_dispc_initial_config();
+
+	rev = dispc_read_reg(DISPC_REVISION);
+	dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
+	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	dispc_runtime_put();
+
+	dss_init_overlay_managers();
+
+	dss_debugfs_create_file("dispc", dispc_dump_regs);
+
+	return 0;
+
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
+	return r;
+}
+
+static int __exit omap_dispchw_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	dss_uninit_overlay_managers();
+
+	return 0;
+}
+
+static int dispc_runtime_suspend(struct device *dev)
+{
+	dispc.is_enabled = false;
+	/* ensure the dispc_irq_handler sees the is_enabled value */
+	smp_wmb();
+	/* wait for current handler to finish before turning the DISPC off */
+	synchronize_irq(dispc.irq);
+
+	dispc_save_context();
+
+	return 0;
+}
+
+static int dispc_runtime_resume(struct device *dev)
+{
+	/*
+	 * The reset value for load mode is 0 (OMAP_DSS_LOAD_CLUT_AND_FRAME)
+	 * but we always initialize it to 2 (OMAP_DSS_LOAD_FRAME_ONLY) in
+	 * _omap_dispc_initial_config(). We can thus use it to detect if
+	 * we have lost register context.
+	 */
+	if (REG_GET(DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
+		_omap_dispc_initial_config();
+
+		dispc_restore_context();
+	}
+
+	dispc.is_enabled = true;
+	/* ensure the dispc_irq_handler sees the is_enabled value */
+	smp_wmb();
+
+	return 0;
+}
+
+static const struct dev_pm_ops dispc_pm_ops = {
+	.runtime_suspend = dispc_runtime_suspend,
+	.runtime_resume = dispc_runtime_resume,
+};
+
+static const struct of_device_id dispc_of_match[] = {
+	{ .compatible = "ti,omap2-dispc", },
+	{ .compatible = "ti,omap3-dispc", },
+	{ .compatible = "ti,omap4-dispc", },
+	{},
+};
+
+static struct platform_driver omap_dispchw_driver = {
+	.remove         = __exit_p(omap_dispchw_remove),
+	.driver         = {
+		.name   = "omapdss_dispc",
+		.owner  = THIS_MODULE,
+		.pm	= &dispc_pm_ops,
+		.of_match_table = dispc_of_match,
+	},
+};
+
+int __init dispc_init_platform_driver(void)
+{
+	return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe);
+}
+
+void __exit dispc_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omap_dispchw_driver);
+}
diff --git a/drivers/video/fbdev/omap2/dss/dispc.h b/drivers/video/fbdev/omap2/dss/dispc.h
new file mode 100644
index 000000000000..78edb449c763
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dispc.h
@@ -0,0 +1,917 @@
+/*
+ * linux/drivers/video/omap2/dss/dispc.h
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DISPC_REG_H
+#define __OMAP2_DISPC_REG_H
+
+/* DISPC common registers */
+#define DISPC_REVISION			0x0000
+#define DISPC_SYSCONFIG			0x0010
+#define DISPC_SYSSTATUS			0x0014
+#define DISPC_IRQSTATUS			0x0018
+#define DISPC_IRQENABLE			0x001C
+#define DISPC_CONTROL			0x0040
+#define DISPC_CONFIG			0x0044
+#define DISPC_CAPABLE			0x0048
+#define DISPC_LINE_STATUS		0x005C
+#define DISPC_LINE_NUMBER		0x0060
+#define DISPC_GLOBAL_ALPHA		0x0074
+#define DISPC_CONTROL2			0x0238
+#define DISPC_CONFIG2			0x0620
+#define DISPC_DIVISOR			0x0804
+#define DISPC_GLOBAL_BUFFER		0x0800
+#define DISPC_CONTROL3                  0x0848
+#define DISPC_CONFIG3                   0x084C
+#define DISPC_MSTANDBY_CTRL		0x0858
+#define DISPC_GLOBAL_MFLAG_ATTRIBUTE	0x085C
+
+/* DISPC overlay registers */
+#define DISPC_OVL_BA0(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_BA0_OFFSET(n))
+#define DISPC_OVL_BA1(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_BA1_OFFSET(n))
+#define DISPC_OVL_BA0_UV(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_BA0_UV_OFFSET(n))
+#define DISPC_OVL_BA1_UV(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_BA1_UV_OFFSET(n))
+#define DISPC_OVL_POSITION(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_POS_OFFSET(n))
+#define DISPC_OVL_SIZE(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_SIZE_OFFSET(n))
+#define DISPC_OVL_ATTRIBUTES(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_ATTR_OFFSET(n))
+#define DISPC_OVL_ATTRIBUTES2(n)	(DISPC_OVL_BASE(n) + \
+					DISPC_ATTR2_OFFSET(n))
+#define DISPC_OVL_FIFO_THRESHOLD(n)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIFO_THRESH_OFFSET(n))
+#define DISPC_OVL_FIFO_SIZE_STATUS(n)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIFO_SIZE_STATUS_OFFSET(n))
+#define DISPC_OVL_ROW_INC(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_ROW_INC_OFFSET(n))
+#define DISPC_OVL_PIXEL_INC(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_PIX_INC_OFFSET(n))
+#define DISPC_OVL_WINDOW_SKIP(n)	(DISPC_OVL_BASE(n) + \
+					DISPC_WINDOW_SKIP_OFFSET(n))
+#define DISPC_OVL_TABLE_BA(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_TABLE_BA_OFFSET(n))
+#define DISPC_OVL_FIR(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_FIR_OFFSET(n))
+#define DISPC_OVL_FIR2(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_FIR2_OFFSET(n))
+#define DISPC_OVL_PICTURE_SIZE(n)	(DISPC_OVL_BASE(n) + \
+					DISPC_PIC_SIZE_OFFSET(n))
+#define DISPC_OVL_ACCU0(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_ACCU0_OFFSET(n))
+#define DISPC_OVL_ACCU1(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_ACCU1_OFFSET(n))
+#define DISPC_OVL_ACCU2_0(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_ACCU2_0_OFFSET(n))
+#define DISPC_OVL_ACCU2_1(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_ACCU2_1_OFFSET(n))
+#define DISPC_OVL_FIR_COEF_H(n, i)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIR_COEF_H_OFFSET(n, i))
+#define DISPC_OVL_FIR_COEF_HV(n, i)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIR_COEF_HV_OFFSET(n, i))
+#define DISPC_OVL_FIR_COEF_H2(n, i)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIR_COEF_H2_OFFSET(n, i))
+#define DISPC_OVL_FIR_COEF_HV2(n, i)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIR_COEF_HV2_OFFSET(n, i))
+#define DISPC_OVL_CONV_COEF(n, i)	(DISPC_OVL_BASE(n) + \
+					DISPC_CONV_COEF_OFFSET(n, i))
+#define DISPC_OVL_FIR_COEF_V(n, i)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIR_COEF_V_OFFSET(n, i))
+#define DISPC_OVL_FIR_COEF_V2(n, i)	(DISPC_OVL_BASE(n) + \
+					DISPC_FIR_COEF_V2_OFFSET(n, i))
+#define DISPC_OVL_PRELOAD(n)		(DISPC_OVL_BASE(n) + \
+					DISPC_PRELOAD_OFFSET(n))
+#define DISPC_OVL_MFLAG_THRESHOLD(n)	(DISPC_OVL_BASE(n) + \
+					DISPC_MFLAG_THRESHOLD_OFFSET(n))
+
+/* DISPC up/downsampling FIR filter coefficient structure */
+struct dispc_coef {
+	s8 hc4_vc22;
+	s8 hc3_vc2;
+	u8 hc2_vc1;
+	s8 hc1_vc0;
+	s8 hc0_vc00;
+};
+
+const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps);
+
+/* DISPC manager/channel specific registers */
+static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x004C;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		return 0x0050;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03AC;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0814;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x0054;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		return 0x0058;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03B0;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0818;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_TIMING_H(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x0064;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x0400;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0840;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_TIMING_V(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x0068;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x0404;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0844;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x006C;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x0408;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x083C;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_DIVISORo(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x0070;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x040C;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0838;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* Named as DISPC_SIZE_LCD, DISPC_SIZE_DIGIT and DISPC_SIZE_LCD2 in TRM */
+static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x007C;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		return 0x0078;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03CC;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0834;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x01D4;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03C0;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0828;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x01D8;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03C4;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x082C;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x01DC;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03C8;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0830;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x0220;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03BC;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0824;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x0224;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03B8;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x0820;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return 0x0228;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		BUG();
+		return 0;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return 0x03B4;
+	case OMAP_DSS_CHANNEL_LCD3:
+		return 0x081C;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* DISPC overlay register base addresses */
+static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0080;
+	case OMAP_DSS_VIDEO1:
+		return 0x00BC;
+	case OMAP_DSS_VIDEO2:
+		return 0x014C;
+	case OMAP_DSS_VIDEO3:
+		return 0x0300;
+	case OMAP_DSS_WB:
+		return 0x0500;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* DISPC overlay register offsets */
+static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0000;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0008;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0004;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x000C;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0544;
+	case OMAP_DSS_VIDEO2:
+		return 0x04BC;
+	case OMAP_DSS_VIDEO3:
+		return 0x0310;
+	case OMAP_DSS_WB:
+		return 0x0118;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0548;
+	case OMAP_DSS_VIDEO2:
+		return 0x04C0;
+	case OMAP_DSS_VIDEO3:
+		return 0x0314;
+	case OMAP_DSS_WB:
+		return 0x011C;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0008;
+	case OMAP_DSS_VIDEO3:
+		return 0x009C;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x000C;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x00A8;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0020;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0010;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0070;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0568;
+	case OMAP_DSS_VIDEO2:
+		return 0x04DC;
+	case OMAP_DSS_VIDEO3:
+		return 0x032C;
+	case OMAP_DSS_WB:
+		return 0x0310;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0024;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0014;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x008C;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0028;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0018;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0088;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x002C;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x001C;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x00A4;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0030;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0020;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0098;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0034;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+	case OMAP_DSS_VIDEO3:
+		BUG();
+		return 0;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0038;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+	case OMAP_DSS_VIDEO3:
+		BUG();
+		return 0;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0024;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0090;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0580;
+	case OMAP_DSS_VIDEO2:
+		return 0x055C;
+	case OMAP_DSS_VIDEO3:
+		return 0x0424;
+	case OMAP_DSS_WB:
+		return 0x290;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0028;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0094;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+
+static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x002C;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0000;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0584;
+	case OMAP_DSS_VIDEO2:
+		return 0x0560;
+	case OMAP_DSS_VIDEO3:
+		return 0x0428;
+	case OMAP_DSS_WB:
+		return 0x0294;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0030;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0004;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0588;
+	case OMAP_DSS_VIDEO2:
+		return 0x0564;
+	case OMAP_DSS_VIDEO3:
+		return 0x042C;
+	case OMAP_DSS_WB:
+		return 0x0298;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0034 + i * 0x8;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0010 + i * 0x8;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x058C + i * 0x8;
+	case OMAP_DSS_VIDEO2:
+		return 0x0568 + i * 0x8;
+	case OMAP_DSS_VIDEO3:
+		return 0x0430 + i * 0x8;
+	case OMAP_DSS_WB:
+		return 0x02A0 + i * 0x8;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+		return 0x0038 + i * 0x8;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0014 + i * 0x8;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0590 + i * 8;
+	case OMAP_DSS_VIDEO2:
+		return 0x056C + i * 0x8;
+	case OMAP_DSS_VIDEO3:
+		return 0x0434 + i * 0x8;
+	case OMAP_DSS_WB:
+		return 0x02A4 + i * 0x8;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* coef index i = {0, 1, 2, 3, 4,} */
+static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+	case OMAP_DSS_VIDEO2:
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0074 + i * 0x4;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x0124 + i * 0x4;
+	case OMAP_DSS_VIDEO2:
+		return 0x00B4 + i * 0x4;
+	case OMAP_DSS_VIDEO3:
+	case OMAP_DSS_WB:
+		return 0x0050 + i * 0x4;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		BUG();
+		return 0;
+	case OMAP_DSS_VIDEO1:
+		return 0x05CC + i * 0x4;
+	case OMAP_DSS_VIDEO2:
+		return 0x05A8 + i * 0x4;
+	case OMAP_DSS_VIDEO3:
+		return 0x0470 + i * 0x4;
+	case OMAP_DSS_WB:
+		return 0x02E0 + i * 0x4;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x01AC;
+	case OMAP_DSS_VIDEO1:
+		return 0x0174;
+	case OMAP_DSS_VIDEO2:
+		return 0x00E8;
+	case OMAP_DSS_VIDEO3:
+		return 0x00A0;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane plane)
+{
+	switch (plane) {
+	case OMAP_DSS_GFX:
+		return 0x0860;
+	case OMAP_DSS_VIDEO1:
+		return 0x0864;
+	case OMAP_DSS_VIDEO2:
+		return 0x0868;
+	case OMAP_DSS_VIDEO3:
+		return 0x086c;
+	default:
+		BUG();
+		return 0;
+	}
+}
+#endif
diff --git a/drivers/video/fbdev/omap2/dss/dispc_coefs.c b/drivers/video/fbdev/omap2/dss/dispc_coefs.c
new file mode 100644
index 000000000000..038c15b04215
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dispc_coefs.c
@@ -0,0 +1,325 @@
+/*
+ * linux/drivers/video/omap2/dss/dispc_coefs.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Chandrabhanu Mahapatra <cmahapatra@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <video/omapdss.h>
+
+#include "dispc.h"
+
+static const struct dispc_coef coef3_M8[8] = {
+	{ 0,  0, 128,  0, 0 },
+	{ 0, -4, 123,  9, 0 },
+	{ 0, -4, 108, 24, 0 },
+	{ 0, -2,  87, 43, 0 },
+	{ 0, 64,  64,  0, 0 },
+	{ 0, 43,  87, -2, 0 },
+	{ 0, 24, 108, -4, 0 },
+	{ 0,  9, 123, -4, 0 },
+};
+
+static const struct dispc_coef coef3_M9[8] = {
+	{ 0,  6, 116,  6, 0 },
+	{ 0,  0, 112, 16, 0 },
+	{ 0, -2, 100, 30, 0 },
+	{ 0, -2,  83, 47, 0 },
+	{ 0, 64,  64,  0, 0 },
+	{ 0, 47,  83, -2, 0 },
+	{ 0, 30, 100, -2, 0 },
+	{ 0, 16, 112,  0, 0 },
+};
+
+static const struct dispc_coef coef3_M10[8] = {
+	{ 0, 10, 108, 10, 0 },
+	{ 0,  3, 104, 21, 0 },
+	{ 0,  0,  94, 34, 0 },
+	{ 0, -1,  80, 49, 0 },
+	{ 0, 64,  64,  0, 0 },
+	{ 0, 49,  80, -1, 0 },
+	{ 0, 34,  94,  0, 0 },
+	{ 0, 21, 104,  3, 0 },
+};
+
+static const struct dispc_coef coef3_M11[8] = {
+	{ 0, 14, 100, 14, 0 },
+	{ 0,  6,  98, 24, 0 },
+	{ 0,  2,  90, 36, 0 },
+	{ 0,  0,  78, 50, 0 },
+	{ 0, 64,  64,  0, 0 },
+	{ 0, 50,  78,  0, 0 },
+	{ 0, 36,  90,  2, 0 },
+	{ 0, 24,  98,  6, 0 },
+};
+
+static const struct dispc_coef coef3_M12[8] = {
+	{ 0, 16,  96, 16, 0 },
+	{ 0,  9,  93, 26, 0 },
+	{ 0,  4,  86, 38, 0 },
+	{ 0,  1,  76, 51, 0 },
+	{ 0, 64,  64,  0, 0 },
+	{ 0, 51,  76,  1, 0 },
+	{ 0, 38,  86,  4, 0 },
+	{ 0, 26,  93,  9, 0 },
+};
+
+static const struct dispc_coef coef3_M13[8] = {
+	{ 0, 18,  92, 18, 0 },
+	{ 0, 10,  90, 28, 0 },
+	{ 0,  5,  83, 40, 0 },
+	{ 0,  1,  75, 52, 0 },
+	{ 0, 64,  64,  0, 0 },
+	{ 0, 52,  75,  1, 0 },
+	{ 0, 40,  83,  5, 0 },
+	{ 0, 28,  90, 10, 0 },
+};
+
+static const struct dispc_coef coef3_M14[8] = {
+	{ 0, 20, 88, 20, 0 },
+	{ 0, 12, 86, 30, 0 },
+	{ 0,  6, 81, 41, 0 },
+	{ 0,  2, 74, 52, 0 },
+	{ 0, 64, 64,  0, 0 },
+	{ 0, 52, 74,  2, 0 },
+	{ 0, 41, 81,  6, 0 },
+	{ 0, 30, 86, 12, 0 },
+};
+
+static const struct dispc_coef coef3_M16[8] = {
+	{ 0, 22, 84, 22, 0 },
+	{ 0, 14, 82, 32, 0 },
+	{ 0,  8, 78, 42, 0 },
+	{ 0,  3, 72, 53, 0 },
+	{ 0, 64, 64,  0, 0 },
+	{ 0, 53, 72,  3, 0 },
+	{ 0, 42, 78,  8, 0 },
+	{ 0, 32, 82, 14, 0 },
+};
+
+static const struct dispc_coef coef3_M19[8] = {
+	{ 0, 24, 80, 24, 0 },
+	{ 0, 16, 79, 33, 0 },
+	{ 0,  9, 76, 43, 0 },
+	{ 0,  4, 70, 54, 0 },
+	{ 0, 64, 64,  0, 0 },
+	{ 0, 54, 70,  4, 0 },
+	{ 0, 43, 76,  9, 0 },
+	{ 0, 33, 79, 16, 0 },
+};
+
+static const struct dispc_coef coef3_M22[8] = {
+	{ 0, 25, 78, 25, 0 },
+	{ 0, 17, 77, 34, 0 },
+	{ 0, 10, 74, 44, 0 },
+	{ 0,  5, 69, 54, 0 },
+	{ 0, 64, 64,  0, 0 },
+	{ 0, 54, 69,  5, 0 },
+	{ 0, 44, 74, 10, 0 },
+	{ 0, 34, 77, 17, 0 },
+};
+
+static const struct dispc_coef coef3_M26[8] = {
+	{ 0, 26, 76, 26, 0 },
+	{ 0, 19, 74, 35, 0 },
+	{ 0, 11, 72, 45, 0 },
+	{ 0,  5, 69, 54, 0 },
+	{ 0, 64, 64,  0, 0 },
+	{ 0, 54, 69,  5, 0 },
+	{ 0, 45, 72, 11, 0 },
+	{ 0, 35, 74, 19, 0 },
+};
+
+static const struct dispc_coef coef3_M32[8] = {
+	{ 0, 27, 74, 27, 0 },
+	{ 0, 19, 73, 36, 0 },
+	{ 0, 12, 71, 45, 0 },
+	{ 0,  6, 68, 54, 0 },
+	{ 0, 64, 64,  0, 0 },
+	{ 0, 54, 68,  6, 0 },
+	{ 0, 45, 71, 12, 0 },
+	{ 0, 36, 73, 19, 0 },
+};
+
+static const struct dispc_coef coef5_M8[8] = {
+	{   0,   0, 128,   0,   0 },
+	{  -2,  14, 125, -10,   1 },
+	{  -6,  33, 114, -15,   2 },
+	{ -10,  55,  98, -16,   1 },
+	{   0, -14,  78,  78, -14 },
+	{   1, -16,  98,  55, -10 },
+	{   2, -15, 114,  33,  -6 },
+	{   1, -10, 125,  14,  -2 },
+};
+
+static const struct dispc_coef coef5_M9[8] = {
+	{  -3,  10, 114,  10,  -3 },
+	{  -6,  24, 111,   0,  -1 },
+	{  -8,  40, 103,  -7,   0 },
+	{ -11,  58,  91, -11,   1 },
+	{   0, -12,  76,  76, -12 },
+	{   1, -11,  91,  58, -11 },
+	{   0,  -7, 103,  40,  -8 },
+	{  -1,   0, 111,  24,  -6 },
+};
+
+static const struct dispc_coef coef5_M10[8] = {
+	{  -4,  18, 100,  18,  -4 },
+	{  -6,  30,  99,   8,  -3 },
+	{  -8,  44,  93,   0,  -1 },
+	{  -9,  58,  84,  -5,   0 },
+	{   0,  -8,  72,  72,  -8 },
+	{   0,  -5,  84,  58,  -9 },
+	{  -1,   0,  93,  44,  -8 },
+	{  -3,   8,  99,  30,  -6 },
+};
+
+static const struct dispc_coef coef5_M11[8] = {
+	{  -5,  23,  92,  23,  -5 },
+	{  -6,  34,  90,  13,  -3 },
+	{  -6,  45,  85,   6,  -2 },
+	{  -6,  57,  78,   0,  -1 },
+	{   0,  -4,  68,  68,  -4 },
+	{  -1,   0,  78,  57,  -6 },
+	{  -2,   6,  85,  45,  -6 },
+	{  -3,  13,  90,  34,  -6 },
+};
+
+static const struct dispc_coef coef5_M12[8] = {
+	{  -4,  26,  84,  26,  -4 },
+	{  -5,  36,  82,  18,  -3 },
+	{  -4,  46,  78,  10,  -2 },
+	{  -3,  55,  72,   5,  -1 },
+	{   0,   0,  64,  64,   0 },
+	{  -1,   5,  72,  55,  -3 },
+	{  -2,  10,  78,  46,  -4 },
+	{  -3,  18,  82,  36,  -5 },
+};
+
+static const struct dispc_coef coef5_M13[8] = {
+	{  -3,  28,  78,  28,  -3 },
+	{  -3,  37,  76,  21,  -3 },
+	{  -2,  45,  73,  14,  -2 },
+	{   0,  53,  68,   8,  -1 },
+	{   0,   3,  61,  61,   3 },
+	{  -1,   8,  68,  53,   0 },
+	{  -2,  14,  73,  45,  -2 },
+	{  -3,  21,  76,  37,  -3 },
+};
+
+static const struct dispc_coef coef5_M14[8] = {
+	{  -2,  30,  72,  30,  -2 },
+	{  -1,  37,  71,  23,  -2 },
+	{   0,  45,  69,  16,  -2 },
+	{   3,  52,  64,  10,  -1 },
+	{   0,   6,  58,  58,   6 },
+	{  -1,  10,  64,  52,   3 },
+	{  -2,  16,  69,  45,   0 },
+	{  -2,  23,  71,  37,  -1 },
+};
+
+static const struct dispc_coef coef5_M16[8] = {
+	{   0,  31,  66,  31,   0 },
+	{   1,  38,  65,  25,  -1 },
+	{   3,  44,  62,  20,  -1 },
+	{   6,  49,  59,  14,   0 },
+	{   0,  10,  54,  54,  10 },
+	{   0,  14,  59,  49,   6 },
+	{  -1,  20,  62,  44,   3 },
+	{  -1,  25,  65,  38,   1 },
+};
+
+static const struct dispc_coef coef5_M19[8] = {
+	{   3,  32,  58,  32,   3 },
+	{   4,  38,  58,  27,   1 },
+	{   7,  42,  55,  23,   1 },
+	{  10,  46,  54,  18,   0 },
+	{   0,  14,  50,  50,  14 },
+	{   0,  18,  54,  46,  10 },
+	{   1,  23,  55,  42,   7 },
+	{   1,  27,  58,  38,   4 },
+};
+
+static const struct dispc_coef coef5_M22[8] = {
+	{   4,  33,  54,  33,   4 },
+	{   6,  37,  54,  28,   3 },
+	{   9,  41,  53,  24,   1 },
+	{  12,  45,  51,  20,   0 },
+	{   0,  16,  48,  48,  16 },
+	{   0,  20,  51,  45,  12 },
+	{   1,  24,  53,  41,   9 },
+	{   3,  28,  54,  37,   6 },
+};
+
+static const struct dispc_coef coef5_M26[8] = {
+	{   6,  33,  50,  33,   6 },
+	{   8,  36,  51,  29,   4 },
+	{  11,  40,  50,  25,   2 },
+	{  14,  43,  48,  22,   1 },
+	{   0,  18,  46,  46,  18 },
+	{   1,  22,  48,  43,  14 },
+	{   2,  25,  50,  40,  11 },
+	{   4,  29,  51,  36,   8 },
+};
+
+static const struct dispc_coef coef5_M32[8] = {
+	{   7,  33,  48,  33,   7 },
+	{  10,  36,  48,  29,   5 },
+	{  13,  39,  47,  26,   3 },
+	{  16,  42,  46,  23,   1 },
+	{   0,  19,  45,  45,  19 },
+	{   1,  23,  46,  42,  16 },
+	{   3,  26,  47,  39,  13 },
+	{   5,  29,  48,  36,  10 },
+};
+
+const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
+{
+	int i;
+	static const struct {
+		int Mmin;
+		int Mmax;
+		const struct dispc_coef *coef_3;
+		const struct dispc_coef *coef_5;
+	} coefs[] = {
+		{ 27, 32, coef3_M32, coef5_M32 },
+		{ 23, 26, coef3_M26, coef5_M26 },
+		{ 20, 22, coef3_M22, coef5_M22 },
+		{ 17, 19, coef3_M19, coef5_M19 },
+		{ 15, 16, coef3_M16, coef5_M16 },
+		{ 14, 14, coef3_M14, coef5_M14 },
+		{ 13, 13, coef3_M13, coef5_M13 },
+		{ 12, 12, coef3_M12, coef5_M12 },
+		{ 11, 11, coef3_M11, coef5_M11 },
+		{ 10, 10, coef3_M10, coef5_M10 },
+		{  9,  9,  coef3_M9,  coef5_M9 },
+		{  4,  8,  coef3_M8,  coef5_M8 },
+		/*
+		 * When upscaling more than two times, blockiness and outlines
+		 * around the image are observed when M8 tables are used. M11,
+		 * M16 and M19 tables are used to prevent this.
+		 */
+		{  3,  3, coef3_M11, coef5_M11 },
+		{  2,  2, coef3_M16, coef5_M16 },
+		{  0,  1, coef3_M19, coef5_M19 },
+	};
+
+	inc /= 128;
+	for (i = 0; i < ARRAY_SIZE(coefs); ++i)
+		if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
+			return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
+	return NULL;
+}
diff --git a/drivers/video/fbdev/omap2/dss/display-sysfs.c b/drivers/video/fbdev/omap2/dss/display-sysfs.c
new file mode 100644
index 000000000000..5a2095a98ed8
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/display-sysfs.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+
+#include <video/omapdss.h>
+#include "dss.h"
+
+static struct omap_dss_device *to_dss_device_sysfs(struct device *dev)
+{
+	struct omap_dss_device *dssdev = NULL;
+
+	for_each_dss_dev(dssdev) {
+		if (dssdev->dev == dev) {
+			omap_dss_put_device(dssdev);
+			return dssdev;
+		}
+	}
+
+	return NULL;
+}
+
+static ssize_t display_name_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			dssdev->name ?
+			dssdev->name : "");
+}
+
+static ssize_t display_enabled_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			omapdss_device_is_enabled(dssdev));
+}
+
+static ssize_t display_enabled_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	int r;
+	bool enable;
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	if (enable == omapdss_device_is_enabled(dssdev))
+		return size;
+
+	if (omapdss_device_is_connected(dssdev) == false)
+		return -ENODEV;
+
+	if (enable) {
+		r = dssdev->driver->enable(dssdev);
+		if (r)
+			return r;
+	} else {
+		dssdev->driver->disable(dssdev);
+	}
+
+	return size;
+}
+
+static ssize_t display_tear_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			dssdev->driver->get_te ?
+			dssdev->driver->get_te(dssdev) : 0);
+}
+
+static ssize_t display_tear_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	int r;
+	bool te;
+
+	if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
+		return -ENOENT;
+
+	r = strtobool(buf, &te);
+	if (r)
+		return r;
+
+	r = dssdev->driver->enable_te(dssdev, te);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_timings_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	struct omap_video_timings t;
+
+	if (!dssdev->driver->get_timings)
+		return -ENOENT;
+
+	dssdev->driver->get_timings(dssdev, &t);
+
+	return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
+			t.pixelclock,
+			t.x_res, t.hfp, t.hbp, t.hsw,
+			t.y_res, t.vfp, t.vbp, t.vsw);
+}
+
+static ssize_t display_timings_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	struct omap_video_timings t = dssdev->panel.timings;
+	int r, found;
+
+	if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
+		return -ENOENT;
+
+	found = 0;
+#ifdef CONFIG_OMAP2_DSS_VENC
+	if (strncmp("pal", buf, 3) == 0) {
+		t = omap_dss_pal_timings;
+		found = 1;
+	} else if (strncmp("ntsc", buf, 4) == 0) {
+		t = omap_dss_ntsc_timings;
+		found = 1;
+	}
+#endif
+	if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
+				&t.pixelclock,
+				&t.x_res, &t.hfp, &t.hbp, &t.hsw,
+				&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+		return -EINVAL;
+
+	r = dssdev->driver->check_timings(dssdev, &t);
+	if (r)
+		return r;
+
+	dssdev->driver->disable(dssdev);
+	dssdev->driver->set_timings(dssdev, &t);
+	r = dssdev->driver->enable(dssdev);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_rotate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	int rotate;
+	if (!dssdev->driver->get_rotate)
+		return -ENOENT;
+	rotate = dssdev->driver->get_rotate(dssdev);
+	return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
+}
+
+static ssize_t display_rotate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	int rot, r;
+
+	if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+		return -ENOENT;
+
+	r = kstrtoint(buf, 0, &rot);
+	if (r)
+		return r;
+
+	r = dssdev->driver->set_rotate(dssdev, rot);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_mirror_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	int mirror;
+	if (!dssdev->driver->get_mirror)
+		return -ENOENT;
+	mirror = dssdev->driver->get_mirror(dssdev);
+	return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
+}
+
+static ssize_t display_mirror_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	int r;
+	bool mirror;
+
+	if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+		return -ENOENT;
+
+	r = strtobool(buf, &mirror);
+	if (r)
+		return r;
+
+	r = dssdev->driver->set_mirror(dssdev, mirror);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_wss_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	unsigned int wss;
+
+	if (!dssdev->driver->get_wss)
+		return -ENOENT;
+
+	wss = dssdev->driver->get_wss(dssdev);
+
+	return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
+}
+
+static ssize_t display_wss_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
+	u32 wss;
+	int r;
+
+	if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
+		return -ENOENT;
+
+	r = kstrtou32(buf, 0, &wss);
+	if (r)
+		return r;
+
+	if (wss > 0xfffff)
+		return -EINVAL;
+
+	r = dssdev->driver->set_wss(dssdev, wss);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static DEVICE_ATTR(display_name, S_IRUGO, display_name_show, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
+		display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
+		display_tear_show, display_tear_store);
+static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
+		display_timings_show, display_timings_store);
+static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
+		display_rotate_show, display_rotate_store);
+static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
+		display_mirror_show, display_mirror_store);
+static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
+		display_wss_show, display_wss_store);
+
+static const struct attribute *display_sysfs_attrs[] = {
+	&dev_attr_display_name.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_tear_elim.attr,
+	&dev_attr_timings.attr,
+	&dev_attr_rotate.attr,
+	&dev_attr_mirror.attr,
+	&dev_attr_wss.attr,
+	NULL
+};
+
+int display_init_sysfs(struct platform_device *pdev)
+{
+	struct omap_dss_device *dssdev = NULL;
+	int r;
+
+	for_each_dss_dev(dssdev) {
+		struct kobject *kobj = &dssdev->dev->kobj;
+
+		r = sysfs_create_files(kobj, display_sysfs_attrs);
+		if (r) {
+			DSSERR("failed to create sysfs files\n");
+			goto err;
+		}
+
+		r = sysfs_create_link(&pdev->dev.kobj, kobj, dssdev->alias);
+		if (r) {
+			sysfs_remove_files(kobj, display_sysfs_attrs);
+
+			DSSERR("failed to create sysfs display link\n");
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	display_uninit_sysfs(pdev);
+
+	return r;
+}
+
+void display_uninit_sysfs(struct platform_device *pdev)
+{
+	struct omap_dss_device *dssdev = NULL;
+
+	for_each_dss_dev(dssdev) {
+		sysfs_remove_link(&pdev->dev.kobj, dssdev->alias);
+		sysfs_remove_files(&dssdev->dev->kobj,
+				display_sysfs_attrs);
+	}
+}
diff --git a/drivers/video/fbdev/omap2/dss/display.c b/drivers/video/fbdev/omap2/dss/display.c
new file mode 100644
index 000000000000..2412a0dd0c13
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/display.c
@@ -0,0 +1,338 @@
+/*
+ * linux/drivers/video/omap2/dss/display.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <video/omapdss.h>
+#include "dss.h"
+#include "dss_features.h"
+
+void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
+			u16 *xres, u16 *yres)
+{
+	*xres = dssdev->panel.timings.x_res;
+	*yres = dssdev->panel.timings.y_res;
+}
+EXPORT_SYMBOL(omapdss_default_get_resolution);
+
+int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
+{
+	switch (dssdev->type) {
+	case OMAP_DISPLAY_TYPE_DPI:
+		if (dssdev->phy.dpi.data_lines == 24)
+			return 24;
+		else
+			return 16;
+
+	case OMAP_DISPLAY_TYPE_DBI:
+		if (dssdev->ctrl.pixel_size == 24)
+			return 24;
+		else
+			return 16;
+	case OMAP_DISPLAY_TYPE_DSI:
+		if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
+			return 24;
+		else
+			return 16;
+	case OMAP_DISPLAY_TYPE_VENC:
+	case OMAP_DISPLAY_TYPE_SDI:
+	case OMAP_DISPLAY_TYPE_HDMI:
+	case OMAP_DISPLAY_TYPE_DVI:
+		return 24;
+	default:
+		BUG();
+		return 0;
+	}
+}
+EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
+
+void omapdss_default_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	*timings = dssdev->panel.timings;
+}
+EXPORT_SYMBOL(omapdss_default_get_timings);
+
+int dss_suspend_all_devices(void)
+{
+	struct omap_dss_device *dssdev = NULL;
+
+	for_each_dss_dev(dssdev) {
+		if (!dssdev->driver)
+			continue;
+
+		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+			dssdev->driver->disable(dssdev);
+			dssdev->activate_after_resume = true;
+		} else {
+			dssdev->activate_after_resume = false;
+		}
+	}
+
+	return 0;
+}
+
+int dss_resume_all_devices(void)
+{
+	struct omap_dss_device *dssdev = NULL;
+
+	for_each_dss_dev(dssdev) {
+		if (!dssdev->driver)
+			continue;
+
+		if (dssdev->activate_after_resume) {
+			dssdev->driver->enable(dssdev);
+			dssdev->activate_after_resume = false;
+		}
+	}
+
+	return 0;
+}
+
+void dss_disable_all_devices(void)
+{
+	struct omap_dss_device *dssdev = NULL;
+
+	for_each_dss_dev(dssdev) {
+		if (!dssdev->driver)
+			continue;
+
+		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+			dssdev->driver->disable(dssdev);
+	}
+}
+
+static LIST_HEAD(panel_list);
+static DEFINE_MUTEX(panel_list_mutex);
+static int disp_num_counter;
+
+int omapdss_register_display(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_driver *drv = dssdev->driver;
+	int id;
+
+	/*
+	 * Note: this presumes all the displays are either using DT or non-DT,
+	 * which normally should be the case. This also presumes that all
+	 * displays either have an DT alias, or none has.
+	 */
+
+	if (dssdev->dev->of_node) {
+		id = of_alias_get_id(dssdev->dev->of_node, "display");
+
+		if (id < 0)
+			id = disp_num_counter++;
+	} else {
+		id = disp_num_counter++;
+	}
+
+	snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id);
+
+	/* Use 'label' property for name, if it exists */
+	if (dssdev->dev->of_node)
+		of_property_read_string(dssdev->dev->of_node, "label",
+			&dssdev->name);
+
+	if (dssdev->name == NULL)
+		dssdev->name = dssdev->alias;
+
+	if (drv && drv->get_resolution == NULL)
+		drv->get_resolution = omapdss_default_get_resolution;
+	if (drv && drv->get_recommended_bpp == NULL)
+		drv->get_recommended_bpp = omapdss_default_get_recommended_bpp;
+	if (drv && drv->get_timings == NULL)
+		drv->get_timings = omapdss_default_get_timings;
+
+	mutex_lock(&panel_list_mutex);
+	list_add_tail(&dssdev->panel_list, &panel_list);
+	mutex_unlock(&panel_list_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(omapdss_register_display);
+
+void omapdss_unregister_display(struct omap_dss_device *dssdev)
+{
+	mutex_lock(&panel_list_mutex);
+	list_del(&dssdev->panel_list);
+	mutex_unlock(&panel_list_mutex);
+}
+EXPORT_SYMBOL(omapdss_unregister_display);
+
+struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev)
+{
+	if (!try_module_get(dssdev->owner))
+		return NULL;
+
+	if (get_device(dssdev->dev) == NULL) {
+		module_put(dssdev->owner);
+		return NULL;
+	}
+
+	return dssdev;
+}
+EXPORT_SYMBOL(omap_dss_get_device);
+
+void omap_dss_put_device(struct omap_dss_device *dssdev)
+{
+	put_device(dssdev->dev);
+	module_put(dssdev->owner);
+}
+EXPORT_SYMBOL(omap_dss_put_device);
+
+/*
+ * ref count of the found device is incremented.
+ * ref count of from-device is decremented.
+ */
+struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
+{
+	struct list_head *l;
+	struct omap_dss_device *dssdev;
+
+	mutex_lock(&panel_list_mutex);
+
+	if (list_empty(&panel_list)) {
+		dssdev = NULL;
+		goto out;
+	}
+
+	if (from == NULL) {
+		dssdev = list_first_entry(&panel_list, struct omap_dss_device,
+				panel_list);
+		omap_dss_get_device(dssdev);
+		goto out;
+	}
+
+	omap_dss_put_device(from);
+
+	list_for_each(l, &panel_list) {
+		dssdev = list_entry(l, struct omap_dss_device, panel_list);
+		if (dssdev == from) {
+			if (list_is_last(l, &panel_list)) {
+				dssdev = NULL;
+				goto out;
+			}
+
+			dssdev = list_entry(l->next, struct omap_dss_device,
+					panel_list);
+			omap_dss_get_device(dssdev);
+			goto out;
+		}
+	}
+
+	WARN(1, "'from' dssdev not found\n");
+
+	dssdev = NULL;
+out:
+	mutex_unlock(&panel_list_mutex);
+	return dssdev;
+}
+EXPORT_SYMBOL(omap_dss_get_next_device);
+
+struct omap_dss_device *omap_dss_find_device(void *data,
+		int (*match)(struct omap_dss_device *dssdev, void *data))
+{
+	struct omap_dss_device *dssdev = NULL;
+
+	while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
+		if (match(dssdev, data))
+			return dssdev;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(omap_dss_find_device);
+
+void videomode_to_omap_video_timings(const struct videomode *vm,
+		struct omap_video_timings *ovt)
+{
+	memset(ovt, 0, sizeof(*ovt));
+
+	ovt->pixelclock = vm->pixelclock;
+	ovt->x_res = vm->hactive;
+	ovt->hbp = vm->hback_porch;
+	ovt->hfp = vm->hfront_porch;
+	ovt->hsw = vm->hsync_len;
+	ovt->y_res = vm->vactive;
+	ovt->vbp = vm->vback_porch;
+	ovt->vfp = vm->vfront_porch;
+	ovt->vsw = vm->vsync_len;
+
+	ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
+		OMAPDSS_SIG_ACTIVE_HIGH :
+		OMAPDSS_SIG_ACTIVE_LOW;
+	ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
+		OMAPDSS_SIG_ACTIVE_HIGH :
+		OMAPDSS_SIG_ACTIVE_LOW;
+	ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ?
+		OMAPDSS_SIG_ACTIVE_HIGH :
+		OMAPDSS_SIG_ACTIVE_LOW;
+	ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
+		OMAPDSS_DRIVE_SIG_RISING_EDGE :
+		OMAPDSS_DRIVE_SIG_FALLING_EDGE;
+
+	ovt->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+}
+EXPORT_SYMBOL(videomode_to_omap_video_timings);
+
+void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
+		struct videomode *vm)
+{
+	memset(vm, 0, sizeof(*vm));
+
+	vm->pixelclock = ovt->pixelclock;
+
+	vm->hactive = ovt->x_res;
+	vm->hback_porch = ovt->hbp;
+	vm->hfront_porch = ovt->hfp;
+	vm->hsync_len = ovt->hsw;
+	vm->vactive = ovt->y_res;
+	vm->vback_porch = ovt->vbp;
+	vm->vfront_porch = ovt->vfp;
+	vm->vsync_len = ovt->vsw;
+
+	if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
+		vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
+	else
+		vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
+
+	if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
+		vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+	else
+		vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
+
+	if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH)
+		vm->flags |= DISPLAY_FLAGS_DE_HIGH;
+	else
+		vm->flags |= DISPLAY_FLAGS_DE_LOW;
+
+	if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE)
+		vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+	else
+		vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+}
+EXPORT_SYMBOL(omap_video_timings_to_videomode);
diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
new file mode 100644
index 000000000000..157921db447a
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -0,0 +1,774 @@
+/*
+ * linux/drivers/video/omap2/dss/dpi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DPI"
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/string.h>
+#include <linux/of.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static struct {
+	struct platform_device *pdev;
+
+	struct regulator *vdds_dsi_reg;
+	struct platform_device *dsidev;
+
+	struct mutex lock;
+
+	struct omap_video_timings timings;
+	struct dss_lcd_mgr_config mgr_config;
+	int data_lines;
+
+	struct omap_dss_device output;
+
+	bool port_initialized;
+} dpi;
+
+static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
+{
+	/*
+	 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
+	 * would also be used for DISPC fclk. Meaning, when the DPI output is
+	 * disabled, DISPC clock will be disabled, and TV out will stop.
+	 */
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		return NULL;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		switch (channel) {
+		case OMAP_DSS_CHANNEL_LCD:
+			return dsi_get_dsidev_from_id(0);
+		case OMAP_DSS_CHANNEL_LCD2:
+			return dsi_get_dsidev_from_id(1);
+		default:
+			return NULL;
+		}
+
+	case OMAPDSS_VER_OMAP5:
+		switch (channel) {
+		case OMAP_DSS_CHANNEL_LCD:
+			return dsi_get_dsidev_from_id(0);
+		case OMAP_DSS_CHANNEL_LCD3:
+			return dsi_get_dsidev_from_id(1);
+		default:
+			return NULL;
+		}
+
+	default:
+		return NULL;
+	}
+}
+
+static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
+	default:
+		/* this shouldn't happen */
+		WARN_ON(1);
+		return OMAP_DSS_CLK_SRC_FCK;
+	}
+}
+
+struct dpi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	unsigned long pck_min, pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	unsigned long fck;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (ctx->pck_min >= 100000000) {
+		if (lckd > 1 && lckd % 2 != 0)
+			return false;
+
+		if (pckd > 1 && pckd % 2 != 0)
+			return false;
+	}
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+
+static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 100000000)
+		return false;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+
+static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
+			dpi_calc_hsdiv_cb, ctx);
+}
+
+static bool dpi_calc_dss_cb(unsigned long fck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->fck = fck;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	unsigned long clkin;
+	unsigned long pll_min, pll_max;
+
+	clkin = dsi_get_pll_clkin(dpi.dsidev);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dpi.dsidev;
+	ctx->pck_min = pck - 1000;
+	ctx->pck_max = pck + 1000;
+	ctx->dsi_cinfo.clkin = clkin;
+
+	pll_min = 0;
+	pll_max = 0;
+
+	return dsi_pll_calc(dpi.dsidev, clkin,
+			pll_min, pll_max,
+			dpi_calc_pll_cb, ctx);
+}
+
+static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	int i;
+
+	/*
+	 * DSS fck gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- ~15MHz.
+	 */
+
+	for (i = 0; i < 25; ++i) {
+		bool ok;
+
+		memset(ctx, 0, sizeof(*ctx));
+		if (pck > 1000 * i * i * i)
+			ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
+		else
+			ctx->pck_min = 0;
+		ctx->pck_max = pck + 1000 * i * i * i;
+
+		ok = dss_div_calc(pck, ctx->pck_min, dpi_calc_dss_cb, ctx);
+		if (ok)
+			return ok;
+	}
+
+	return false;
+}
+
+
+
+static int dpi_set_dsi_clk(enum omap_channel channel,
+		unsigned long pck_req, unsigned long *fck, int *lck_div,
+		int *pck_div)
+{
+	struct dpi_clk_calc_ctx ctx;
+	int r;
+	bool ok;
+
+	ok = dpi_dsi_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
+
+	r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
+	if (r)
+		return r;
+
+	dss_select_lcd_clk_source(channel,
+			dpi_get_alt_clk_src(channel));
+
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
+
+	*fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
+
+	return 0;
+}
+
+static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
+		int *lck_div, int *pck_div)
+{
+	struct dpi_clk_calc_ctx ctx;
+	int r;
+	bool ok;
+
+	ok = dpi_dss_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
+
+	r = dss_set_fck_rate(ctx.fck);
+	if (r)
+		return r;
+
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
+
+	*fck = ctx.fck;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
+
+	return 0;
+}
+
+static int dpi_set_mode(struct omap_overlay_manager *mgr)
+{
+	struct omap_video_timings *t = &dpi.timings;
+	int lck_div = 0, pck_div = 0;
+	unsigned long fck = 0;
+	unsigned long pck;
+	int r = 0;
+
+	if (dpi.dsidev)
+		r = dpi_set_dsi_clk(mgr->id, t->pixelclock, &fck,
+				&lck_div, &pck_div);
+	else
+		r = dpi_set_dispc_clk(t->pixelclock, &fck,
+				&lck_div, &pck_div);
+	if (r)
+		return r;
+
+	pck = fck / lck_div / pck_div;
+
+	if (pck != t->pixelclock) {
+		DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
+			t->pixelclock, pck);
+
+		t->pixelclock = pck;
+	}
+
+	dss_mgr_set_timings(mgr, t);
+
+	return 0;
+}
+
+static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
+{
+	dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
+
+	dpi.mgr_config.stallmode = false;
+	dpi.mgr_config.fifohandcheck = false;
+
+	dpi.mgr_config.video_port_width = dpi.data_lines;
+
+	dpi.mgr_config.lcden_sig_polarity = 0;
+
+	dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
+}
+
+static int dpi_display_enable(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_device *out = &dpi.output;
+	int r;
+
+	mutex_lock(&dpi.lock);
+
+	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
+		DSSERR("no VDSS_DSI regulator\n");
+		r = -ENODEV;
+		goto err_no_reg;
+	}
+
+	if (out == NULL || out->manager == NULL) {
+		DSSERR("failed to enable display: no output/manager\n");
+		r = -ENODEV;
+		goto err_no_out_mgr;
+	}
+
+	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
+		r = regulator_enable(dpi.vdds_dsi_reg);
+		if (r)
+			goto err_reg_enable;
+	}
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
+
+	r = dss_dpi_select_source(out->manager->id);
+	if (r)
+		goto err_src_sel;
+
+	if (dpi.dsidev) {
+		r = dsi_runtime_get(dpi.dsidev);
+		if (r)
+			goto err_get_dsi;
+
+		r = dsi_pll_init(dpi.dsidev, 0, 1);
+		if (r)
+			goto err_dsi_pll_init;
+	}
+
+	r = dpi_set_mode(out->manager);
+	if (r)
+		goto err_set_mode;
+
+	dpi_config_lcd_manager(out->manager);
+
+	mdelay(2);
+
+	r = dss_mgr_enable(out->manager);
+	if (r)
+		goto err_mgr_enable;
+
+	mutex_unlock(&dpi.lock);
+
+	return 0;
+
+err_mgr_enable:
+err_set_mode:
+	if (dpi.dsidev)
+		dsi_pll_uninit(dpi.dsidev, true);
+err_dsi_pll_init:
+	if (dpi.dsidev)
+		dsi_runtime_put(dpi.dsidev);
+err_get_dsi:
+err_src_sel:
+	dispc_runtime_put();
+err_get_dispc:
+	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
+		regulator_disable(dpi.vdds_dsi_reg);
+err_reg_enable:
+err_no_out_mgr:
+err_no_reg:
+	mutex_unlock(&dpi.lock);
+	return r;
+}
+
+static void dpi_display_disable(struct omap_dss_device *dssdev)
+{
+	struct omap_overlay_manager *mgr = dpi.output.manager;
+
+	mutex_lock(&dpi.lock);
+
+	dss_mgr_disable(mgr);
+
+	if (dpi.dsidev) {
+		dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
+		dsi_pll_uninit(dpi.dsidev, true);
+		dsi_runtime_put(dpi.dsidev);
+	}
+
+	dispc_runtime_put();
+
+	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
+		regulator_disable(dpi.vdds_dsi_reg);
+
+	mutex_unlock(&dpi.lock);
+}
+
+static void dpi_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	DSSDBG("dpi_set_timings\n");
+
+	mutex_lock(&dpi.lock);
+
+	dpi.timings = *timings;
+
+	mutex_unlock(&dpi.lock);
+}
+
+static void dpi_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	mutex_lock(&dpi.lock);
+
+	*timings = dpi.timings;
+
+	mutex_unlock(&dpi.lock);
+}
+
+static int dpi_check_timings(struct omap_dss_device *dssdev,
+			struct omap_video_timings *timings)
+{
+	struct omap_overlay_manager *mgr = dpi.output.manager;
+	int lck_div, pck_div;
+	unsigned long fck;
+	unsigned long pck;
+	struct dpi_clk_calc_ctx ctx;
+	bool ok;
+
+	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
+		return -EINVAL;
+
+	if (timings->pixelclock == 0)
+		return -EINVAL;
+
+	if (dpi.dsidev) {
+		ok = dpi_dsi_clk_calc(timings->pixelclock, &ctx);
+		if (!ok)
+			return -EINVAL;
+
+		fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+	} else {
+		ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
+		if (!ok)
+			return -EINVAL;
+
+		fck = ctx.fck;
+	}
+
+	lck_div = ctx.dispc_cinfo.lck_div;
+	pck_div = ctx.dispc_cinfo.pck_div;
+
+	pck = fck / lck_div / pck_div;
+
+	timings->pixelclock = pck;
+
+	return 0;
+}
+
+static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+{
+	mutex_lock(&dpi.lock);
+
+	dpi.data_lines = data_lines;
+
+	mutex_unlock(&dpi.lock);
+}
+
+static int dpi_verify_dsi_pll(struct platform_device *dsidev)
+{
+	int r;
+
+	/* do initial setup with the PLL to see if it is operational */
+
+	r = dsi_runtime_get(dsidev);
+	if (r)
+		return r;
+
+	r = dsi_pll_init(dsidev, 0, 1);
+	if (r) {
+		dsi_runtime_put(dsidev);
+		return r;
+	}
+
+	dsi_pll_uninit(dsidev, true);
+	dsi_runtime_put(dsidev);
+
+	return 0;
+}
+
+static int dpi_init_regulator(void)
+{
+	struct regulator *vdds_dsi;
+
+	if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
+		return 0;
+
+	if (dpi.vdds_dsi_reg)
+		return 0;
+
+	vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi");
+	if (IS_ERR(vdds_dsi)) {
+		if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
+			DSSERR("can't get VDDS_DSI regulator\n");
+		return PTR_ERR(vdds_dsi);
+	}
+
+	dpi.vdds_dsi_reg = vdds_dsi;
+
+	return 0;
+}
+
+static void dpi_init_pll(void)
+{
+	struct platform_device *dsidev;
+
+	if (dpi.dsidev)
+		return;
+
+	dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
+	if (!dsidev)
+		return;
+
+	if (dpi_verify_dsi_pll(dsidev)) {
+		DSSWARN("DSI PLL not operational\n");
+		return;
+	}
+
+	dpi.dsidev = dsidev;
+}
+
+/*
+ * Return a hardcoded channel for the DPI output. This should work for
+ * current use cases, but this can be later expanded to either resolve
+ * the channel in some more dynamic manner, or get the channel as a user
+ * parameter.
+ */
+static enum omap_channel dpi_get_channel(void)
+{
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		return OMAP_DSS_CHANNEL_LCD;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		return OMAP_DSS_CHANNEL_LCD2;
+
+	case OMAPDSS_VER_OMAP5:
+		return OMAP_DSS_CHANNEL_LCD3;
+
+	default:
+		DSSWARN("unsupported DSS version\n");
+		return OMAP_DSS_CHANNEL_LCD;
+	}
+}
+
+static int dpi_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct omap_overlay_manager *mgr;
+	int r;
+
+	r = dpi_init_regulator();
+	if (r)
+		return r;
+
+	dpi_init_pll();
+
+	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
+	if (!mgr)
+		return -ENODEV;
+
+	r = dss_mgr_connect(mgr, dssdev);
+	if (r)
+		return r;
+
+	r = omapdss_output_set_device(dssdev, dst);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dst->name);
+		dss_mgr_disconnect(mgr, dssdev);
+		return r;
+	}
+
+	return 0;
+}
+
+static void dpi_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	WARN_ON(dst != dssdev->dst);
+
+	if (dst != dssdev->dst)
+		return;
+
+	omapdss_output_unset_device(dssdev);
+
+	if (dssdev->manager)
+		dss_mgr_disconnect(dssdev->manager, dssdev);
+}
+
+static const struct omapdss_dpi_ops dpi_ops = {
+	.connect = dpi_connect,
+	.disconnect = dpi_disconnect,
+
+	.enable = dpi_display_enable,
+	.disable = dpi_display_disable,
+
+	.check_timings = dpi_check_timings,
+	.set_timings = dpi_set_timings,
+	.get_timings = dpi_get_timings,
+
+	.set_data_lines = dpi_set_data_lines,
+};
+
+static void dpi_init_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &dpi.output;
+
+	out->dev = &pdev->dev;
+	out->id = OMAP_DSS_OUTPUT_DPI;
+	out->output_type = OMAP_DISPLAY_TYPE_DPI;
+	out->name = "dpi.0";
+	out->dispc_channel = dpi_get_channel();
+	out->ops.dpi = &dpi_ops;
+	out->owner = THIS_MODULE;
+
+	omapdss_register_output(out);
+}
+
+static void __exit dpi_uninit_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &dpi.output;
+
+	omapdss_unregister_output(out);
+}
+
+static int omap_dpi_probe(struct platform_device *pdev)
+{
+	dpi.pdev = pdev;
+
+	mutex_init(&dpi.lock);
+
+	dpi_init_output(pdev);
+
+	return 0;
+}
+
+static int __exit omap_dpi_remove(struct platform_device *pdev)
+{
+	dpi_uninit_output(pdev);
+
+	return 0;
+}
+
+static struct platform_driver omap_dpi_driver = {
+	.probe		= omap_dpi_probe,
+	.remove         = __exit_p(omap_dpi_remove),
+	.driver         = {
+		.name   = "omapdss_dpi",
+		.owner  = THIS_MODULE,
+	},
+};
+
+int __init dpi_init_platform_driver(void)
+{
+	return platform_driver_register(&omap_dpi_driver);
+}
+
+void __exit dpi_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omap_dpi_driver);
+}
+
+int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
+{
+	struct device_node *ep;
+	u32 datalines;
+	int r;
+
+	ep = omapdss_of_get_next_endpoint(port, NULL);
+	if (!ep)
+		return 0;
+
+	r = of_property_read_u32(ep, "data-lines", &datalines);
+	if (r) {
+		DSSERR("failed to parse datalines\n");
+		goto err_datalines;
+	}
+
+	dpi.data_lines = datalines;
+
+	of_node_put(ep);
+
+	dpi.pdev = pdev;
+
+	mutex_init(&dpi.lock);
+
+	dpi_init_output(pdev);
+
+	dpi.port_initialized = true;
+
+	return 0;
+
+err_datalines:
+	of_node_put(ep);
+
+	return r;
+}
+
+void __exit dpi_uninit_port(void)
+{
+	if (!dpi.port_initialized)
+		return;
+
+	dpi_uninit_output(dpi.pdev);
+}
diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c
new file mode 100644
index 000000000000..8be9b04d8849
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dsi.c
@@ -0,0 +1,5751 @@
+/*
+ * linux/drivers/video/omap2/dss/dsi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DSI"
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/semaphore.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include <video/omapdss.h>
+#include <video/mipi_display.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+#define DSI_CATCH_MISSING_TE
+
+struct dsi_reg { u16 module; u16 idx; };
+
+#define DSI_REG(mod, idx)		((const struct dsi_reg) { mod, idx })
+
+/* DSI Protocol Engine */
+
+#define DSI_PROTO			0
+#define DSI_PROTO_SZ			0x200
+
+#define DSI_REVISION			DSI_REG(DSI_PROTO, 0x0000)
+#define DSI_SYSCONFIG			DSI_REG(DSI_PROTO, 0x0010)
+#define DSI_SYSSTATUS			DSI_REG(DSI_PROTO, 0x0014)
+#define DSI_IRQSTATUS			DSI_REG(DSI_PROTO, 0x0018)
+#define DSI_IRQENABLE			DSI_REG(DSI_PROTO, 0x001C)
+#define DSI_CTRL			DSI_REG(DSI_PROTO, 0x0040)
+#define DSI_GNQ				DSI_REG(DSI_PROTO, 0x0044)
+#define DSI_COMPLEXIO_CFG1		DSI_REG(DSI_PROTO, 0x0048)
+#define DSI_COMPLEXIO_IRQ_STATUS	DSI_REG(DSI_PROTO, 0x004C)
+#define DSI_COMPLEXIO_IRQ_ENABLE	DSI_REG(DSI_PROTO, 0x0050)
+#define DSI_CLK_CTRL			DSI_REG(DSI_PROTO, 0x0054)
+#define DSI_TIMING1			DSI_REG(DSI_PROTO, 0x0058)
+#define DSI_TIMING2			DSI_REG(DSI_PROTO, 0x005C)
+#define DSI_VM_TIMING1			DSI_REG(DSI_PROTO, 0x0060)
+#define DSI_VM_TIMING2			DSI_REG(DSI_PROTO, 0x0064)
+#define DSI_VM_TIMING3			DSI_REG(DSI_PROTO, 0x0068)
+#define DSI_CLK_TIMING			DSI_REG(DSI_PROTO, 0x006C)
+#define DSI_TX_FIFO_VC_SIZE		DSI_REG(DSI_PROTO, 0x0070)
+#define DSI_RX_FIFO_VC_SIZE		DSI_REG(DSI_PROTO, 0x0074)
+#define DSI_COMPLEXIO_CFG2		DSI_REG(DSI_PROTO, 0x0078)
+#define DSI_RX_FIFO_VC_FULLNESS		DSI_REG(DSI_PROTO, 0x007C)
+#define DSI_VM_TIMING4			DSI_REG(DSI_PROTO, 0x0080)
+#define DSI_TX_FIFO_VC_EMPTINESS	DSI_REG(DSI_PROTO, 0x0084)
+#define DSI_VM_TIMING5			DSI_REG(DSI_PROTO, 0x0088)
+#define DSI_VM_TIMING6			DSI_REG(DSI_PROTO, 0x008C)
+#define DSI_VM_TIMING7			DSI_REG(DSI_PROTO, 0x0090)
+#define DSI_STOPCLK_TIMING		DSI_REG(DSI_PROTO, 0x0094)
+#define DSI_VC_CTRL(n)			DSI_REG(DSI_PROTO, 0x0100 + (n * 0x20))
+#define DSI_VC_TE(n)			DSI_REG(DSI_PROTO, 0x0104 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_HEADER(n)	DSI_REG(DSI_PROTO, 0x0108 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_PAYLOAD(n)	DSI_REG(DSI_PROTO, 0x010C + (n * 0x20))
+#define DSI_VC_SHORT_PACKET_HEADER(n)	DSI_REG(DSI_PROTO, 0x0110 + (n * 0x20))
+#define DSI_VC_IRQSTATUS(n)		DSI_REG(DSI_PROTO, 0x0118 + (n * 0x20))
+#define DSI_VC_IRQENABLE(n)		DSI_REG(DSI_PROTO, 0x011C + (n * 0x20))
+
+/* DSIPHY_SCP */
+
+#define DSI_PHY				1
+#define DSI_PHY_OFFSET			0x200
+#define DSI_PHY_SZ			0x40
+
+#define DSI_DSIPHY_CFG0			DSI_REG(DSI_PHY, 0x0000)
+#define DSI_DSIPHY_CFG1			DSI_REG(DSI_PHY, 0x0004)
+#define DSI_DSIPHY_CFG2			DSI_REG(DSI_PHY, 0x0008)
+#define DSI_DSIPHY_CFG5			DSI_REG(DSI_PHY, 0x0014)
+#define DSI_DSIPHY_CFG10		DSI_REG(DSI_PHY, 0x0028)
+
+/* DSI_PLL_CTRL_SCP */
+
+#define DSI_PLL				2
+#define DSI_PLL_OFFSET			0x300
+#define DSI_PLL_SZ			0x20
+
+#define DSI_PLL_CONTROL			DSI_REG(DSI_PLL, 0x0000)
+#define DSI_PLL_STATUS			DSI_REG(DSI_PLL, 0x0004)
+#define DSI_PLL_GO			DSI_REG(DSI_PLL, 0x0008)
+#define DSI_PLL_CONFIGURATION1		DSI_REG(DSI_PLL, 0x000C)
+#define DSI_PLL_CONFIGURATION2		DSI_REG(DSI_PLL, 0x0010)
+
+#define REG_GET(dsidev, idx, start, end) \
+	FLD_GET(dsi_read_reg(dsidev, idx), start, end)
+
+#define REG_FLD_MOD(dsidev, idx, val, start, end) \
+	dsi_write_reg(dsidev, idx, FLD_MOD(dsi_read_reg(dsidev, idx), val, start, end))
+
+/* Global interrupts */
+#define DSI_IRQ_VC0		(1 << 0)
+#define DSI_IRQ_VC1		(1 << 1)
+#define DSI_IRQ_VC2		(1 << 2)
+#define DSI_IRQ_VC3		(1 << 3)
+#define DSI_IRQ_WAKEUP		(1 << 4)
+#define DSI_IRQ_RESYNC		(1 << 5)
+#define DSI_IRQ_PLL_LOCK	(1 << 7)
+#define DSI_IRQ_PLL_UNLOCK	(1 << 8)
+#define DSI_IRQ_PLL_RECALL	(1 << 9)
+#define DSI_IRQ_COMPLEXIO_ERR	(1 << 10)
+#define DSI_IRQ_HS_TX_TIMEOUT	(1 << 14)
+#define DSI_IRQ_LP_RX_TIMEOUT	(1 << 15)
+#define DSI_IRQ_TE_TRIGGER	(1 << 16)
+#define DSI_IRQ_ACK_TRIGGER	(1 << 17)
+#define DSI_IRQ_SYNC_LOST	(1 << 18)
+#define DSI_IRQ_LDO_POWER_GOOD	(1 << 19)
+#define DSI_IRQ_TA_TIMEOUT	(1 << 20)
+#define DSI_IRQ_ERROR_MASK \
+	(DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
+	DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST)
+#define DSI_IRQ_CHANNEL_MASK	0xf
+
+/* Virtual channel interrupts */
+#define DSI_VC_IRQ_CS		(1 << 0)
+#define DSI_VC_IRQ_ECC_CORR	(1 << 1)
+#define DSI_VC_IRQ_PACKET_SENT	(1 << 2)
+#define DSI_VC_IRQ_FIFO_TX_OVF	(1 << 3)
+#define DSI_VC_IRQ_FIFO_RX_OVF	(1 << 4)
+#define DSI_VC_IRQ_BTA		(1 << 5)
+#define DSI_VC_IRQ_ECC_NO_CORR	(1 << 6)
+#define DSI_VC_IRQ_FIFO_TX_UDF	(1 << 7)
+#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
+#define DSI_VC_IRQ_ERROR_MASK \
+	(DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
+	DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
+	DSI_VC_IRQ_FIFO_TX_UDF)
+
+/* ComplexIO interrupts */
+#define DSI_CIO_IRQ_ERRSYNCESC1		(1 << 0)
+#define DSI_CIO_IRQ_ERRSYNCESC2		(1 << 1)
+#define DSI_CIO_IRQ_ERRSYNCESC3		(1 << 2)
+#define DSI_CIO_IRQ_ERRSYNCESC4		(1 << 3)
+#define DSI_CIO_IRQ_ERRSYNCESC5		(1 << 4)
+#define DSI_CIO_IRQ_ERRESC1		(1 << 5)
+#define DSI_CIO_IRQ_ERRESC2		(1 << 6)
+#define DSI_CIO_IRQ_ERRESC3		(1 << 7)
+#define DSI_CIO_IRQ_ERRESC4		(1 << 8)
+#define DSI_CIO_IRQ_ERRESC5		(1 << 9)
+#define DSI_CIO_IRQ_ERRCONTROL1		(1 << 10)
+#define DSI_CIO_IRQ_ERRCONTROL2		(1 << 11)
+#define DSI_CIO_IRQ_ERRCONTROL3		(1 << 12)
+#define DSI_CIO_IRQ_ERRCONTROL4		(1 << 13)
+#define DSI_CIO_IRQ_ERRCONTROL5		(1 << 14)
+#define DSI_CIO_IRQ_STATEULPS1		(1 << 15)
+#define DSI_CIO_IRQ_STATEULPS2		(1 << 16)
+#define DSI_CIO_IRQ_STATEULPS3		(1 << 17)
+#define DSI_CIO_IRQ_STATEULPS4		(1 << 18)
+#define DSI_CIO_IRQ_STATEULPS5		(1 << 19)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1	(1 << 20)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1	(1 << 21)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2	(1 << 22)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2	(1 << 23)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3	(1 << 24)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3	(1 << 25)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_4	(1 << 26)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_4	(1 << 27)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_5	(1 << 28)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_5	(1 << 29)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0	(1 << 30)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1	(1 << 31)
+#define DSI_CIO_IRQ_ERROR_MASK \
+	(DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
+	 DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRSYNCESC4 | \
+	 DSI_CIO_IRQ_ERRSYNCESC5 | \
+	 DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
+	 DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRESC4 | \
+	 DSI_CIO_IRQ_ERRESC5 | \
+	 DSI_CIO_IRQ_ERRCONTROL1 | DSI_CIO_IRQ_ERRCONTROL2 | \
+	 DSI_CIO_IRQ_ERRCONTROL3 | DSI_CIO_IRQ_ERRCONTROL4 | \
+	 DSI_CIO_IRQ_ERRCONTROL5 | \
+	 DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
+	 DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
+	 DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3 | \
+	 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
+	 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
+
+typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
+
+static int dsi_display_init_dispc(struct platform_device *dsidev,
+	struct omap_overlay_manager *mgr);
+static void dsi_display_uninit_dispc(struct platform_device *dsidev,
+	struct omap_overlay_manager *mgr);
+
+static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
+
+#define DSI_MAX_NR_ISRS                2
+#define DSI_MAX_NR_LANES	5
+
+enum dsi_lane_function {
+	DSI_LANE_UNUSED	= 0,
+	DSI_LANE_CLK,
+	DSI_LANE_DATA1,
+	DSI_LANE_DATA2,
+	DSI_LANE_DATA3,
+	DSI_LANE_DATA4,
+};
+
+struct dsi_lane_config {
+	enum dsi_lane_function function;
+	u8 polarity;
+};
+
+struct dsi_isr_data {
+	omap_dsi_isr_t	isr;
+	void		*arg;
+	u32		mask;
+};
+
+enum fifo_size {
+	DSI_FIFO_SIZE_0		= 0,
+	DSI_FIFO_SIZE_32	= 1,
+	DSI_FIFO_SIZE_64	= 2,
+	DSI_FIFO_SIZE_96	= 3,
+	DSI_FIFO_SIZE_128	= 4,
+};
+
+enum dsi_vc_source {
+	DSI_VC_SOURCE_L4 = 0,
+	DSI_VC_SOURCE_VP,
+};
+
+struct dsi_irq_stats {
+	unsigned long last_reset;
+	unsigned irq_count;
+	unsigned dsi_irqs[32];
+	unsigned vc_irqs[4][32];
+	unsigned cio_irqs[32];
+};
+
+struct dsi_isr_tables {
+	struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
+	struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
+	struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
+};
+
+struct dsi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	const struct omap_dss_dsi_config *config;
+
+	unsigned long req_pck_min, req_pck_nom, req_pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+
+	struct omap_video_timings dispc_vm;
+	struct omap_dss_dsi_videomode_timings dsi_vm;
+};
+
+struct dsi_data {
+	struct platform_device *pdev;
+	void __iomem *proto_base;
+	void __iomem *phy_base;
+	void __iomem *pll_base;
+
+	int module_id;
+
+	int irq;
+
+	bool is_enabled;
+
+	struct clk *dss_clk;
+	struct clk *sys_clk;
+
+	struct dispc_clock_info user_dispc_cinfo;
+	struct dsi_clock_info user_dsi_cinfo;
+
+	struct dsi_clock_info current_cinfo;
+
+	bool vdds_dsi_enabled;
+	struct regulator *vdds_dsi_reg;
+
+	struct {
+		enum dsi_vc_source source;
+		struct omap_dss_device *dssdev;
+		enum fifo_size tx_fifo_size;
+		enum fifo_size rx_fifo_size;
+		int vc_id;
+	} vc[4];
+
+	struct mutex lock;
+	struct semaphore bus_lock;
+
+	unsigned pll_locked;
+
+	spinlock_t irq_lock;
+	struct dsi_isr_tables isr_tables;
+	/* space for a copy used by the interrupt handler */
+	struct dsi_isr_tables isr_tables_copy;
+
+	int update_channel;
+#ifdef DSI_PERF_MEASURE
+	unsigned update_bytes;
+#endif
+
+	bool te_enabled;
+	bool ulps_enabled;
+
+	void (*framedone_callback)(int, void *);
+	void *framedone_data;
+
+	struct delayed_work framedone_timeout_work;
+
+#ifdef DSI_CATCH_MISSING_TE
+	struct timer_list te_timer;
+#endif
+
+	unsigned long cache_req_pck;
+	unsigned long cache_clk_freq;
+	struct dsi_clock_info cache_cinfo;
+
+	u32		errors;
+	spinlock_t	errors_lock;
+#ifdef DSI_PERF_MEASURE
+	ktime_t perf_setup_time;
+	ktime_t perf_start_time;
+#endif
+	int debug_read;
+	int debug_write;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spinlock_t irq_stats_lock;
+	struct dsi_irq_stats irq_stats;
+#endif
+	/* DSI PLL Parameter Ranges */
+	unsigned long regm_max, regn_max;
+	unsigned long  regm_dispc_max, regm_dsi_max;
+	unsigned long  fint_min, fint_max;
+	unsigned long lpdiv_max;
+
+	unsigned num_lanes_supported;
+	unsigned line_buffer_size;
+
+	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
+	unsigned num_lanes_used;
+
+	unsigned scp_clk_refcount;
+
+	struct dss_lcd_mgr_config mgr_config;
+	struct omap_video_timings timings;
+	enum omap_dss_dsi_pixel_format pix_fmt;
+	enum omap_dss_dsi_mode mode;
+	struct omap_dss_dsi_videomode_timings vm_timings;
+
+	struct omap_dss_device output;
+};
+
+struct dsi_packet_sent_handler_data {
+	struct platform_device *dsidev;
+	struct completion *completion;
+};
+
+struct dsi_module_id_data {
+	u32 address;
+	int id;
+};
+
+static const struct of_device_id dsi_of_match[];
+
+#ifdef DSI_PERF_MEASURE
+static bool dsi_perf;
+module_param(dsi_perf, bool, 0644);
+#endif
+
+static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev)
+{
+	return dev_get_drvdata(&dsidev->dev);
+}
+
+static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
+{
+	return to_platform_device(dssdev->dev);
+}
+
+struct platform_device *dsi_get_dsidev_from_id(int module)
+{
+	struct omap_dss_device *out;
+	enum omap_dss_output_id	id;
+
+	switch (module) {
+	case 0:
+		id = OMAP_DSS_OUTPUT_DSI1;
+		break;
+	case 1:
+		id = OMAP_DSS_OUTPUT_DSI2;
+		break;
+	default:
+		return NULL;
+	}
+
+	out = omap_dss_get_output(id);
+
+	return out ? to_platform_device(out->dev) : NULL;
+}
+
+static inline void dsi_write_reg(struct platform_device *dsidev,
+		const struct dsi_reg idx, u32 val)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	void __iomem *base;
+
+	switch(idx.module) {
+		case DSI_PROTO: base = dsi->proto_base; break;
+		case DSI_PHY: base = dsi->phy_base; break;
+		case DSI_PLL: base = dsi->pll_base; break;
+		default: return;
+	}
+
+	__raw_writel(val, base + idx.idx);
+}
+
+static inline u32 dsi_read_reg(struct platform_device *dsidev,
+		const struct dsi_reg idx)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	void __iomem *base;
+
+	switch(idx.module) {
+		case DSI_PROTO: base = dsi->proto_base; break;
+		case DSI_PHY: base = dsi->phy_base; break;
+		case DSI_PLL: base = dsi->pll_base; break;
+		default: return 0;
+	}
+
+	return __raw_readl(base + idx.idx);
+}
+
+static void dsi_bus_lock(struct omap_dss_device *dssdev)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	down(&dsi->bus_lock);
+}
+
+static void dsi_bus_unlock(struct omap_dss_device *dssdev)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	up(&dsi->bus_lock);
+}
+
+static bool dsi_bus_is_locked(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	return dsi->bus_lock.count == 0;
+}
+
+static void dsi_completion_handler(void *data, u32 mask)
+{
+	complete((struct completion *)data);
+}
+
+static inline int wait_for_bit_change(struct platform_device *dsidev,
+		const struct dsi_reg idx, int bitnum, int value)
+{
+	unsigned long timeout;
+	ktime_t wait;
+	int t;
+
+	/* first busyloop to see if the bit changes right away */
+	t = 100;
+	while (t-- > 0) {
+		if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
+			return value;
+	}
+
+	/* then loop for 500ms, sleeping for 1ms in between */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (time_before(jiffies, timeout)) {
+		if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
+			return value;
+
+		wait = ns_to_ktime(1000 * 1000);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
+	}
+
+	return !value;
+}
+
+u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
+{
+	switch (fmt) {
+	case OMAP_DSS_DSI_FMT_RGB888:
+	case OMAP_DSS_DSI_FMT_RGB666:
+		return 24;
+	case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+		return 18;
+	case OMAP_DSS_DSI_FMT_RGB565:
+		return 16;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+#ifdef DSI_PERF_MEASURE
+static void dsi_perf_mark_setup(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	dsi->perf_setup_time = ktime_get();
+}
+
+static void dsi_perf_mark_start(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	dsi->perf_start_time = ktime_get();
+}
+
+static void dsi_perf_show(struct platform_device *dsidev, const char *name)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	ktime_t t, setup_time, trans_time;
+	u32 total_bytes;
+	u32 setup_us, trans_us, total_us;
+
+	if (!dsi_perf)
+		return;
+
+	t = ktime_get();
+
+	setup_time = ktime_sub(dsi->perf_start_time, dsi->perf_setup_time);
+	setup_us = (u32)ktime_to_us(setup_time);
+	if (setup_us == 0)
+		setup_us = 1;
+
+	trans_time = ktime_sub(t, dsi->perf_start_time);
+	trans_us = (u32)ktime_to_us(trans_time);
+	if (trans_us == 0)
+		trans_us = 1;
+
+	total_us = setup_us + trans_us;
+
+	total_bytes = dsi->update_bytes;
+
+	printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
+			"%u bytes, %u kbytes/sec\n",
+			name,
+			setup_us,
+			trans_us,
+			total_us,
+			1000*1000 / total_us,
+			total_bytes,
+			total_bytes * 1000 / total_us);
+}
+#else
+static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
+{
+}
+
+static inline void dsi_perf_mark_start(struct platform_device *dsidev)
+{
+}
+
+static inline void dsi_perf_show(struct platform_device *dsidev,
+		const char *name)
+{
+}
+#endif
+
+static int verbose_irq;
+
+static void print_irq_status(u32 status)
+{
+	if (status == 0)
+		return;
+
+	if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+		return;
+
+#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		status,
+		verbose_irq ? PIS(VC0) : "",
+		verbose_irq ? PIS(VC1) : "",
+		verbose_irq ? PIS(VC2) : "",
+		verbose_irq ? PIS(VC3) : "",
+		PIS(WAKEUP),
+		PIS(RESYNC),
+		PIS(PLL_LOCK),
+		PIS(PLL_UNLOCK),
+		PIS(PLL_RECALL),
+		PIS(COMPLEXIO_ERR),
+		PIS(HS_TX_TIMEOUT),
+		PIS(LP_RX_TIMEOUT),
+		PIS(TE_TRIGGER),
+		PIS(ACK_TRIGGER),
+		PIS(SYNC_LOST),
+		PIS(LDO_POWER_GOOD),
+		PIS(TA_TIMEOUT));
+#undef PIS
+}
+
+static void print_irq_status_vc(int channel, u32 status)
+{
+	if (status == 0)
+		return;
+
+	if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+		return;
+
+#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
+		channel,
+		status,
+		PIS(CS),
+		PIS(ECC_CORR),
+		PIS(ECC_NO_CORR),
+		verbose_irq ? PIS(PACKET_SENT) : "",
+		PIS(BTA),
+		PIS(FIFO_TX_OVF),
+		PIS(FIFO_RX_OVF),
+		PIS(FIFO_TX_UDF),
+		PIS(PP_BUSY_CHANGE));
+#undef PIS
+}
+
+static void print_irq_status_cio(u32 status)
+{
+	if (status == 0)
+		return;
+
+#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		status,
+		PIS(ERRSYNCESC1),
+		PIS(ERRSYNCESC2),
+		PIS(ERRSYNCESC3),
+		PIS(ERRESC1),
+		PIS(ERRESC2),
+		PIS(ERRESC3),
+		PIS(ERRCONTROL1),
+		PIS(ERRCONTROL2),
+		PIS(ERRCONTROL3),
+		PIS(STATEULPS1),
+		PIS(STATEULPS2),
+		PIS(STATEULPS3),
+		PIS(ERRCONTENTIONLP0_1),
+		PIS(ERRCONTENTIONLP1_1),
+		PIS(ERRCONTENTIONLP0_2),
+		PIS(ERRCONTENTIONLP1_2),
+		PIS(ERRCONTENTIONLP0_3),
+		PIS(ERRCONTENTIONLP1_3),
+		PIS(ULPSACTIVENOT_ALL0),
+		PIS(ULPSACTIVENOT_ALL1));
+#undef PIS
+}
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dsi_collect_irq_stats(struct platform_device *dsidev, u32 irqstatus,
+		u32 *vcstatus, u32 ciostatus)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int i;
+
+	spin_lock(&dsi->irq_stats_lock);
+
+	dsi->irq_stats.irq_count++;
+	dss_collect_irq_stats(irqstatus, dsi->irq_stats.dsi_irqs);
+
+	for (i = 0; i < 4; ++i)
+		dss_collect_irq_stats(vcstatus[i], dsi->irq_stats.vc_irqs[i]);
+
+	dss_collect_irq_stats(ciostatus, dsi->irq_stats.cio_irqs);
+
+	spin_unlock(&dsi->irq_stats_lock);
+}
+#else
+#define dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus)
+#endif
+
+static int debug_irq;
+
+static void dsi_handle_irq_errors(struct platform_device *dsidev, u32 irqstatus,
+		u32 *vcstatus, u32 ciostatus)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int i;
+
+	if (irqstatus & DSI_IRQ_ERROR_MASK) {
+		DSSERR("DSI error, irqstatus %x\n", irqstatus);
+		print_irq_status(irqstatus);
+		spin_lock(&dsi->errors_lock);
+		dsi->errors |= irqstatus & DSI_IRQ_ERROR_MASK;
+		spin_unlock(&dsi->errors_lock);
+	} else if (debug_irq) {
+		print_irq_status(irqstatus);
+	}
+
+	for (i = 0; i < 4; ++i) {
+		if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
+			DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
+				       i, vcstatus[i]);
+			print_irq_status_vc(i, vcstatus[i]);
+		} else if (debug_irq) {
+			print_irq_status_vc(i, vcstatus[i]);
+		}
+	}
+
+	if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
+		DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
+		print_irq_status_cio(ciostatus);
+	} else if (debug_irq) {
+		print_irq_status_cio(ciostatus);
+	}
+}
+
+static void dsi_call_isrs(struct dsi_isr_data *isr_array,
+		unsigned isr_array_size, u32 irqstatus)
+{
+	struct dsi_isr_data *isr_data;
+	int i;
+
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
+		if (isr_data->isr && isr_data->mask & irqstatus)
+			isr_data->isr(isr_data->arg, irqstatus);
+	}
+}
+
+static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
+		u32 irqstatus, u32 *vcstatus, u32 ciostatus)
+{
+	int i;
+
+	dsi_call_isrs(isr_tables->isr_table,
+			ARRAY_SIZE(isr_tables->isr_table),
+			irqstatus);
+
+	for (i = 0; i < 4; ++i) {
+		if (vcstatus[i] == 0)
+			continue;
+		dsi_call_isrs(isr_tables->isr_table_vc[i],
+				ARRAY_SIZE(isr_tables->isr_table_vc[i]),
+				vcstatus[i]);
+	}
+
+	if (ciostatus != 0)
+		dsi_call_isrs(isr_tables->isr_table_cio,
+				ARRAY_SIZE(isr_tables->isr_table_cio),
+				ciostatus);
+}
+
+static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
+{
+	struct platform_device *dsidev;
+	struct dsi_data *dsi;
+	u32 irqstatus, vcstatus[4], ciostatus;
+	int i;
+
+	dsidev = (struct platform_device *) arg;
+	dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (!dsi->is_enabled)
+		return IRQ_NONE;
+
+	spin_lock(&dsi->irq_lock);
+
+	irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS);
+
+	/* IRQ is not for us */
+	if (!irqstatus) {
+		spin_unlock(&dsi->irq_lock);
+		return IRQ_NONE;
+	}
+
+	dsi_write_reg(dsidev, DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
+	/* flush posted write */
+	dsi_read_reg(dsidev, DSI_IRQSTATUS);
+
+	for (i = 0; i < 4; ++i) {
+		if ((irqstatus & (1 << i)) == 0) {
+			vcstatus[i] = 0;
+			continue;
+		}
+
+		vcstatus[i] = dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
+
+		dsi_write_reg(dsidev, DSI_VC_IRQSTATUS(i), vcstatus[i]);
+		/* flush posted write */
+		dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
+	}
+
+	if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
+		ciostatus = dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
+
+		dsi_write_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
+		/* flush posted write */
+		dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
+	} else {
+		ciostatus = 0;
+	}
+
+#ifdef DSI_CATCH_MISSING_TE
+	if (irqstatus & DSI_IRQ_TE_TRIGGER)
+		del_timer(&dsi->te_timer);
+#endif
+
+	/* make a copy and unlock, so that isrs can unregister
+	 * themselves */
+	memcpy(&dsi->isr_tables_copy, &dsi->isr_tables,
+		sizeof(dsi->isr_tables));
+
+	spin_unlock(&dsi->irq_lock);
+
+	dsi_handle_isrs(&dsi->isr_tables_copy, irqstatus, vcstatus, ciostatus);
+
+	dsi_handle_irq_errors(dsidev, irqstatus, vcstatus, ciostatus);
+
+	dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus);
+
+	return IRQ_HANDLED;
+}
+
+/* dsi->irq_lock has to be locked by the caller */
+static void _omap_dsi_configure_irqs(struct platform_device *dsidev,
+		struct dsi_isr_data *isr_array,
+		unsigned isr_array_size, u32 default_mask,
+		const struct dsi_reg enable_reg,
+		const struct dsi_reg status_reg)
+{
+	struct dsi_isr_data *isr_data;
+	u32 mask;
+	u32 old_mask;
+	int i;
+
+	mask = default_mask;
+
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
+
+		if (isr_data->isr == NULL)
+			continue;
+
+		mask |= isr_data->mask;
+	}
+
+	old_mask = dsi_read_reg(dsidev, enable_reg);
+	/* clear the irqstatus for newly enabled irqs */
+	dsi_write_reg(dsidev, status_reg, (mask ^ old_mask) & mask);
+	dsi_write_reg(dsidev, enable_reg, mask);
+
+	/* flush posted writes */
+	dsi_read_reg(dsidev, enable_reg);
+	dsi_read_reg(dsidev, status_reg);
+}
+
+/* dsi->irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 mask = DSI_IRQ_ERROR_MASK;
+#ifdef DSI_CATCH_MISSING_TE
+	mask |= DSI_IRQ_TE_TRIGGER;
+#endif
+	_omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table,
+			ARRAY_SIZE(dsi->isr_tables.isr_table), mask,
+			DSI_IRQENABLE, DSI_IRQSTATUS);
+}
+
+/* dsi->irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs_vc(struct platform_device *dsidev, int vc)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	_omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_vc[vc],
+			ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]),
+			DSI_VC_IRQ_ERROR_MASK,
+			DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
+}
+
+/* dsi->irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs_cio(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	_omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_cio,
+			ARRAY_SIZE(dsi->isr_tables.isr_table_cio),
+			DSI_CIO_IRQ_ERROR_MASK,
+			DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
+}
+
+static void _dsi_initialize_irq(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	int vc;
+
+	spin_lock_irqsave(&dsi->irq_lock, flags);
+
+	memset(&dsi->isr_tables, 0, sizeof(dsi->isr_tables));
+
+	_omap_dsi_set_irqs(dsidev);
+	for (vc = 0; vc < 4; ++vc)
+		_omap_dsi_set_irqs_vc(dsidev, vc);
+	_omap_dsi_set_irqs_cio(dsidev);
+
+	spin_unlock_irqrestore(&dsi->irq_lock, flags);
+}
+
+static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
+		struct dsi_isr_data *isr_array, unsigned isr_array_size)
+{
+	struct dsi_isr_data *isr_data;
+	int free_idx;
+	int i;
+
+	BUG_ON(isr == NULL);
+
+	/* check for duplicate entry and find a free slot */
+	free_idx = -1;
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
+
+		if (isr_data->isr == isr && isr_data->arg == arg &&
+				isr_data->mask == mask) {
+			return -EINVAL;
+		}
+
+		if (isr_data->isr == NULL && free_idx == -1)
+			free_idx = i;
+	}
+
+	if (free_idx == -1)
+		return -EBUSY;
+
+	isr_data = &isr_array[free_idx];
+	isr_data->isr = isr;
+	isr_data->arg = arg;
+	isr_data->mask = mask;
+
+	return 0;
+}
+
+static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
+		struct dsi_isr_data *isr_array, unsigned isr_array_size)
+{
+	struct dsi_isr_data *isr_data;
+	int i;
+
+	for (i = 0; i < isr_array_size; i++) {
+		isr_data = &isr_array[i];
+		if (isr_data->isr != isr || isr_data->arg != arg ||
+				isr_data->mask != mask)
+			continue;
+
+		isr_data->isr = NULL;
+		isr_data->arg = NULL;
+		isr_data->mask = 0;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int dsi_register_isr(struct platform_device *dsidev, omap_dsi_isr_t isr,
+		void *arg, u32 mask)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi->irq_lock, flags);
+
+	r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table,
+			ARRAY_SIZE(dsi->isr_tables.isr_table));
+
+	if (r == 0)
+		_omap_dsi_set_irqs(dsidev);
+
+	spin_unlock_irqrestore(&dsi->irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_unregister_isr(struct platform_device *dsidev,
+		omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi->irq_lock, flags);
+
+	r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table,
+			ARRAY_SIZE(dsi->isr_tables.isr_table));
+
+	if (r == 0)
+		_omap_dsi_set_irqs(dsidev);
+
+	spin_unlock_irqrestore(&dsi->irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_register_isr_vc(struct platform_device *dsidev, int channel,
+		omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi->irq_lock, flags);
+
+	r = _dsi_register_isr(isr, arg, mask,
+			dsi->isr_tables.isr_table_vc[channel],
+			ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_vc(dsidev, channel);
+
+	spin_unlock_irqrestore(&dsi->irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_unregister_isr_vc(struct platform_device *dsidev, int channel,
+		omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi->irq_lock, flags);
+
+	r = _dsi_unregister_isr(isr, arg, mask,
+			dsi->isr_tables.isr_table_vc[channel],
+			ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_vc(dsidev, channel);
+
+	spin_unlock_irqrestore(&dsi->irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_register_isr_cio(struct platform_device *dsidev,
+		omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi->irq_lock, flags);
+
+	r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
+			ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_cio(dsidev);
+
+	spin_unlock_irqrestore(&dsi->irq_lock, flags);
+
+	return r;
+}
+
+static int dsi_unregister_isr_cio(struct platform_device *dsidev,
+		omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&dsi->irq_lock, flags);
+
+	r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
+			ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
+
+	if (r == 0)
+		_omap_dsi_set_irqs_cio(dsidev);
+
+	spin_unlock_irqrestore(&dsi->irq_lock, flags);
+
+	return r;
+}
+
+static u32 dsi_get_errors(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	u32 e;
+	spin_lock_irqsave(&dsi->errors_lock, flags);
+	e = dsi->errors;
+	dsi->errors = 0;
+	spin_unlock_irqrestore(&dsi->errors_lock, flags);
+	return e;
+}
+
+int dsi_runtime_get(struct platform_device *dsidev)
+{
+	int r;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	DSSDBG("dsi_runtime_get\n");
+
+	r = pm_runtime_get_sync(&dsi->pdev->dev);
+	WARN_ON(r < 0);
+	return r < 0 ? r : 0;
+}
+
+void dsi_runtime_put(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r;
+
+	DSSDBG("dsi_runtime_put\n");
+
+	r = pm_runtime_put_sync(&dsi->pdev->dev);
+	WARN_ON(r < 0 && r != -ENOSYS);
+}
+
+static int dsi_regulator_init(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct regulator *vdds_dsi;
+
+	if (dsi->vdds_dsi_reg != NULL)
+		return 0;
+
+	vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdd");
+
+	if (IS_ERR(vdds_dsi)) {
+		if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
+			DSSERR("can't get DSI VDD regulator\n");
+		return PTR_ERR(vdds_dsi);
+	}
+
+	dsi->vdds_dsi_reg = vdds_dsi;
+
+	return 0;
+}
+
+/* source clock for DSI PLL. this could also be PCLKFREE */
+static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
+		bool enable)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (enable)
+		clk_prepare_enable(dsi->sys_clk);
+	else
+		clk_disable_unprepare(dsi->sys_clk);
+
+	if (enable && dsi->pll_locked) {
+		if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
+			DSSERR("cannot lock PLL when enabling clocks\n");
+	}
+}
+
+static void _dsi_print_reset_status(struct platform_device *dsidev)
+{
+	u32 l;
+	int b0, b1, b2;
+
+	/* A dummy read using the SCP interface to any DSIPHY register is
+	 * required after DSIPHY reset to complete the reset of the DSI complex
+	 * I/O. */
+	l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
+
+	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
+		b0 = 28;
+		b1 = 27;
+		b2 = 26;
+	} else {
+		b0 = 24;
+		b1 = 25;
+		b2 = 26;
+	}
+
+#define DSI_FLD_GET(fld, start, end)\
+	FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
+
+	pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
+		DSI_FLD_GET(PLL_STATUS, 0, 0),
+		DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
+		DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
+		DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
+		DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
+		DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
+		DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
+		DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
+
+#undef DSI_FLD_GET
+}
+
+static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
+{
+	DSSDBG("dsi_if_enable(%d)\n", enable);
+
+	enable = enable ? 1 : 0;
+	REG_FLD_MOD(dsidev, DSI_CTRL, enable, 0, 0); /* IF_EN */
+
+	if (wait_for_bit_change(dsidev, DSI_CTRL, 0, enable) != enable) {
+			DSSERR("Failed to set dsi_if_enable to %d\n", enable);
+			return -EIO;
+	}
+
+	return 0;
+}
+
+unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk;
+}
+
+static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk;
+}
+
+static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	return dsi->current_cinfo.clkin4ddr / 16;
+}
+
+static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
+{
+	unsigned long r;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) {
+		/* DSI FCLK source is DSS_CLK_FCK */
+		r = clk_get_rate(dsi->dss_clk);
+	} else {
+		/* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
+		r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
+	}
+
+	return r;
+}
+
+static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
+		unsigned long lp_clk_min, unsigned long lp_clk_max)
+{
+	unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
+	unsigned lp_clk_div;
+	unsigned long lp_clk;
+
+	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
+	lp_clk = dsi_fclk / 2 / lp_clk_div;
+
+	if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
+		return -EINVAL;
+
+	cinfo->lp_clk_div = lp_clk_div;
+	cinfo->lp_clk = lp_clk;
+
+	return 0;
+}
+
+static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long dsi_fclk;
+	unsigned lp_clk_div;
+	unsigned long lp_clk;
+
+	lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div;
+
+	if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max)
+		return -EINVAL;
+
+	dsi_fclk = dsi_fclk_rate(dsidev);
+
+	lp_clk = dsi_fclk / 2 / lp_clk_div;
+
+	DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
+	dsi->current_cinfo.lp_clk = lp_clk;
+	dsi->current_cinfo.lp_clk_div = lp_clk_div;
+
+	/* LP_CLK_DIVISOR */
+	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0);
+
+	/* LP_RX_SYNCHRO_ENABLE */
+	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, 21, 21);
+
+	return 0;
+}
+
+static void dsi_enable_scp_clk(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (dsi->scp_clk_refcount++ == 0)
+		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */
+}
+
+static void dsi_disable_scp_clk(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	WARN_ON(dsi->scp_clk_refcount == 0);
+	if (--dsi->scp_clk_refcount == 0)
+		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */
+}
+
+enum dsi_pll_power_state {
+	DSI_PLL_POWER_OFF	= 0x0,
+	DSI_PLL_POWER_ON_HSCLK	= 0x1,
+	DSI_PLL_POWER_ON_ALL	= 0x2,
+	DSI_PLL_POWER_ON_DIV	= 0x3,
+};
+
+static int dsi_pll_power(struct platform_device *dsidev,
+		enum dsi_pll_power_state state)
+{
+	int t = 0;
+
+	/* DSI-PLL power command 0x3 is not working */
+	if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
+			state == DSI_PLL_POWER_ON_DIV)
+		state = DSI_PLL_POWER_ON_ALL;
+
+	/* PLL_PWR_CMD */
+	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, state, 31, 30);
+
+	/* PLL_PWR_STATUS */
+	while (FLD_GET(dsi_read_reg(dsidev, DSI_CLK_CTRL), 29, 28) != state) {
+		if (++t > 1000) {
+			DSSERR("Failed to set DSI PLL power mode to %d\n",
+					state);
+			return -ENODEV;
+		}
+		udelay(1);
+	}
+
+	return 0;
+}
+
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	return clk_get_rate(dsi->sys_clk);
+}
+
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regm, regm_start, regm_stop;
+	unsigned long out_max;
+	unsigned long out;
+
+	out_min = out_min ? out_min : 1;
+	out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
+	regm_stop = min(pll / out_min, dsi->regm_dispc_max);
+
+	for (regm = regm_start; regm <= regm_stop; ++regm) {
+		out = pll / regm;
+
+		if (func(regm, out, data))
+			return true;
+	}
+
+	return false;
+}
+
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regn, regn_start, regn_stop;
+	int regm, regm_start, regm_stop;
+	unsigned long fint, pll;
+	const unsigned long pll_hw_max = 1800000000;
+	unsigned long fint_hw_min, fint_hw_max;
+
+	fint_hw_min = dsi->fint_min;
+	fint_hw_max = dsi->fint_max;
+
+	regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
+	regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
+
+	pll_max = pll_max ? pll_max : ULONG_MAX;
+
+	for (regn = regn_start; regn <= regn_stop; ++regn) {
+		fint = clkin / regn;
+
+		regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
+				1ul);
+		regm_stop = min3(pll_max / fint / 2,
+				pll_hw_max / fint / 2,
+				dsi->regm_max);
+
+		for (regm = regm_start; regm <= regm_stop; ++regm) {
+			pll = 2 * regm * fint;
+
+			if (func(regn, regm, fint, pll, data))
+				return true;
+		}
+	}
+
+	return false;
+}
+
+/* calculate clock rates using dividers in cinfo */
+static int dsi_calc_clock_rates(struct platform_device *dsidev,
+		struct dsi_clock_info *cinfo)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
+		return -EINVAL;
+
+	if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max)
+		return -EINVAL;
+
+	if (cinfo->regm_dispc > dsi->regm_dispc_max)
+		return -EINVAL;
+
+	if (cinfo->regm_dsi > dsi->regm_dsi_max)
+		return -EINVAL;
+
+	cinfo->clkin = clk_get_rate(dsi->sys_clk);
+	cinfo->fint = cinfo->clkin / cinfo->regn;
+
+	if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
+		return -EINVAL;
+
+	cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
+
+	if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
+		return -EINVAL;
+
+	if (cinfo->regm_dispc > 0)
+		cinfo->dsi_pll_hsdiv_dispc_clk =
+			cinfo->clkin4ddr / cinfo->regm_dispc;
+	else
+		cinfo->dsi_pll_hsdiv_dispc_clk = 0;
+
+	if (cinfo->regm_dsi > 0)
+		cinfo->dsi_pll_hsdiv_dsi_clk =
+			cinfo->clkin4ddr / cinfo->regm_dsi;
+	else
+		cinfo->dsi_pll_hsdiv_dsi_clk = 0;
+
+	return 0;
+}
+
+static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
+{
+	unsigned long max_dsi_fck;
+
+	max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
+
+	cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
+	cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
+}
+
+int dsi_pll_set_clock_div(struct platform_device *dsidev,
+		struct dsi_clock_info *cinfo)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r = 0;
+	u32 l;
+	int f = 0;
+	u8 regn_start, regn_end, regm_start, regm_end;
+	u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
+
+	DSSDBG("DSI PLL clock config starts");
+
+	dsi->current_cinfo.clkin = cinfo->clkin;
+	dsi->current_cinfo.fint = cinfo->fint;
+	dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
+	dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
+			cinfo->dsi_pll_hsdiv_dispc_clk;
+	dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk =
+			cinfo->dsi_pll_hsdiv_dsi_clk;
+
+	dsi->current_cinfo.regn = cinfo->regn;
+	dsi->current_cinfo.regm = cinfo->regm;
+	dsi->current_cinfo.regm_dispc = cinfo->regm_dispc;
+	dsi->current_cinfo.regm_dsi = cinfo->regm_dsi;
+
+	DSSDBG("DSI Fint %ld\n", cinfo->fint);
+
+	DSSDBG("clkin rate %ld\n", cinfo->clkin);
+
+	/* DSIPHY == CLKIN4DDR */
+	DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",
+			cinfo->regm,
+			cinfo->regn,
+			cinfo->clkin,
+			cinfo->clkin4ddr);
+
+	DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
+			cinfo->clkin4ddr / 1000 / 1000 / 2);
+
+	DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
+
+	DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
+		dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+		dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+		cinfo->dsi_pll_hsdiv_dispc_clk);
+	DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
+		dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+		dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+		cinfo->dsi_pll_hsdiv_dsi_clk);
+
+	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
+	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
+	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
+			&regm_dispc_end);
+	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
+			&regm_dsi_end);
+
+	/* DSI_PLL_AUTOMODE = manual */
+	REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0);
+
+	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1);
+	l = FLD_MOD(l, 1, 0, 0);		/* DSI_PLL_STOPMODE */
+	/* DSI_PLL_REGN */
+	l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
+	/* DSI_PLL_REGM */
+	l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
+	/* DSI_CLOCK_DIV */
+	l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
+			regm_dispc_start, regm_dispc_end);
+	/* DSIPROTO_CLOCK_DIV */
+	l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
+			regm_dsi_start, regm_dsi_end);
+	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l);
+
+	BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
+
+	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
+
+	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
+		f = cinfo->fint < 1000000 ? 0x3 :
+			cinfo->fint < 1250000 ? 0x4 :
+			cinfo->fint < 1500000 ? 0x5 :
+			cinfo->fint < 1750000 ? 0x6 :
+			0x7;
+
+		l = FLD_MOD(l, f, 4, 1);	/* DSI_PLL_FREQSEL */
+	} else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
+		f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
+
+		l = FLD_MOD(l, f, 4, 1);	/* PLL_SELFREQDCO */
+	}
+
+	l = FLD_MOD(l, 1, 13, 13);		/* DSI_PLL_REFEN */
+	l = FLD_MOD(l, 0, 14, 14);		/* DSIPHY_CLKINEN */
+	l = FLD_MOD(l, 1, 20, 20);		/* DSI_HSDIVBYPASS */
+	if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
+		l = FLD_MOD(l, 3, 22, 21);	/* REF_SYSCLK = sysclk */
+	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
+
+	REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0);	/* DSI_PLL_GO */
+
+	if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) {
+		DSSERR("dsi pll go bit not going down.\n");
+		r = -EIO;
+		goto err;
+	}
+
+	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) {
+		DSSERR("cannot lock PLL\n");
+		r = -EIO;
+		goto err;
+	}
+
+	dsi->pll_locked = 1;
+
+	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
+	l = FLD_MOD(l, 0, 0, 0);	/* DSI_PLL_IDLE */
+	l = FLD_MOD(l, 0, 5, 5);	/* DSI_PLL_PLLLPMODE */
+	l = FLD_MOD(l, 0, 6, 6);	/* DSI_PLL_LOWCURRSTBY */
+	l = FLD_MOD(l, 0, 7, 7);	/* DSI_PLL_TIGHTPHASELOCK */
+	l = FLD_MOD(l, 0, 8, 8);	/* DSI_PLL_DRIFTGUARDEN */
+	l = FLD_MOD(l, 0, 10, 9);	/* DSI_PLL_LOCKSEL */
+	l = FLD_MOD(l, 1, 13, 13);	/* DSI_PLL_REFEN */
+	l = FLD_MOD(l, 1, 14, 14);	/* DSIPHY_CLKINEN */
+	l = FLD_MOD(l, 0, 15, 15);	/* DSI_BYPASSEN */
+	l = FLD_MOD(l, 1, 16, 16);	/* DSS_CLOCK_EN */
+	l = FLD_MOD(l, 0, 17, 17);	/* DSS_CLOCK_PWDN */
+	l = FLD_MOD(l, 1, 18, 18);	/* DSI_PROTO_CLOCK_EN */
+	l = FLD_MOD(l, 0, 19, 19);	/* DSI_PROTO_CLOCK_PWDN */
+	l = FLD_MOD(l, 0, 20, 20);	/* DSI_HSDIVBYPASS */
+	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
+
+	DSSDBG("PLL config done\n");
+err:
+	return r;
+}
+
+int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
+		bool enable_hsdiv)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r = 0;
+	enum dsi_pll_power_state pwstate;
+
+	DSSDBG("PLL init\n");
+
+	/*
+	 * It seems that on many OMAPs we need to enable both to have a
+	 * functional HSDivider.
+	 */
+	enable_hsclk = enable_hsdiv = true;
+
+	r = dsi_regulator_init(dsidev);
+	if (r)
+		return r;
+
+	dsi_enable_pll_clock(dsidev, 1);
+	/*
+	 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
+	 */
+	dsi_enable_scp_clk(dsidev);
+
+	if (!dsi->vdds_dsi_enabled) {
+		r = regulator_enable(dsi->vdds_dsi_reg);
+		if (r)
+			goto err0;
+		dsi->vdds_dsi_enabled = true;
+	}
+
+	/* XXX PLL does not come out of reset without this... */
+	dispc_pck_free_enable(1);
+
+	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 0, 1) != 1) {
+		DSSERR("PLL not coming out of reset.\n");
+		r = -ENODEV;
+		dispc_pck_free_enable(0);
+		goto err1;
+	}
+
+	/* XXX ... but if left on, we get problems when planes do not
+	 * fill the whole display. No idea about this */
+	dispc_pck_free_enable(0);
+
+	if (enable_hsclk && enable_hsdiv)
+		pwstate = DSI_PLL_POWER_ON_ALL;
+	else if (enable_hsclk)
+		pwstate = DSI_PLL_POWER_ON_HSCLK;
+	else if (enable_hsdiv)
+		pwstate = DSI_PLL_POWER_ON_DIV;
+	else
+		pwstate = DSI_PLL_POWER_OFF;
+
+	r = dsi_pll_power(dsidev, pwstate);
+
+	if (r)
+		goto err1;
+
+	DSSDBG("PLL init done\n");
+
+	return 0;
+err1:
+	if (dsi->vdds_dsi_enabled) {
+		regulator_disable(dsi->vdds_dsi_reg);
+		dsi->vdds_dsi_enabled = false;
+	}
+err0:
+	dsi_disable_scp_clk(dsidev);
+	dsi_enable_pll_clock(dsidev, 0);
+	return r;
+}
+
+void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	dsi->pll_locked = 0;
+	dsi_pll_power(dsidev, DSI_PLL_POWER_OFF);
+	if (disconnect_lanes) {
+		WARN_ON(!dsi->vdds_dsi_enabled);
+		regulator_disable(dsi->vdds_dsi_reg);
+		dsi->vdds_dsi_enabled = false;
+	}
+
+	dsi_disable_scp_clk(dsidev);
+	dsi_enable_pll_clock(dsidev, 0);
+
+	DSSDBG("PLL uninit done\n");
+}
+
+static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
+		struct seq_file *s)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clock_info *cinfo = &dsi->current_cinfo;
+	enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
+	int dsi_module = dsi->module_id;
+
+	dispc_clk_src = dss_get_dispc_clk_source();
+	dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
+
+	if (dsi_runtime_get(dsidev))
+		return;
+
+	seq_printf(s,	"- DSI%d PLL -\n", dsi_module + 1);
+
+	seq_printf(s,	"dsi pll clkin\t%lu\n", cinfo->clkin);
+
+	seq_printf(s,	"Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
+
+	seq_printf(s,	"CLKIN4DDR\t%-16luregm %u\n",
+			cinfo->clkin4ddr, cinfo->regm);
+
+	seq_printf(s,	"DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n",
+			dss_feat_get_clk_source_name(dsi_module == 0 ?
+				OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+				OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
+			cinfo->dsi_pll_hsdiv_dispc_clk,
+			cinfo->regm_dispc,
+			dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
+			"off" : "on");
+
+	seq_printf(s,	"DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n",
+			dss_feat_get_clk_source_name(dsi_module == 0 ?
+				OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+				OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
+			cinfo->dsi_pll_hsdiv_dsi_clk,
+			cinfo->regm_dsi,
+			dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
+			"off" : "on");
+
+	seq_printf(s,	"- DSI%d -\n", dsi_module + 1);
+
+	seq_printf(s,	"dsi fclk source = %s (%s)\n",
+			dss_get_generic_clk_source_name(dsi_clk_src),
+			dss_feat_get_clk_source_name(dsi_clk_src));
+
+	seq_printf(s,	"DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
+
+	seq_printf(s,	"DDR_CLK\t\t%lu\n",
+			cinfo->clkin4ddr / 4);
+
+	seq_printf(s,	"TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev));
+
+	seq_printf(s,	"LP_CLK\t\t%lu\n", cinfo->lp_clk);
+
+	dsi_runtime_put(dsidev);
+}
+
+void dsi_dump_clocks(struct seq_file *s)
+{
+	struct platform_device *dsidev;
+	int i;
+
+	for  (i = 0; i < MAX_NUM_DSI; i++) {
+		dsidev = dsi_get_dsidev_from_id(i);
+		if (dsidev)
+			dsi_dump_dsidev_clocks(dsidev, s);
+	}
+}
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
+		struct seq_file *s)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned long flags;
+	struct dsi_irq_stats stats;
+
+	spin_lock_irqsave(&dsi->irq_stats_lock, flags);
+
+	stats = dsi->irq_stats;
+	memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats));
+	dsi->irq_stats.last_reset = jiffies;
+
+	spin_unlock_irqrestore(&dsi->irq_stats_lock, flags);
+
+	seq_printf(s, "period %u ms\n",
+			jiffies_to_msecs(jiffies - stats.last_reset));
+
+	seq_printf(s, "irqs %d\n", stats.irq_count);
+#define PIS(x) \
+	seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
+
+	seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1);
+	PIS(VC0);
+	PIS(VC1);
+	PIS(VC2);
+	PIS(VC3);
+	PIS(WAKEUP);
+	PIS(RESYNC);
+	PIS(PLL_LOCK);
+	PIS(PLL_UNLOCK);
+	PIS(PLL_RECALL);
+	PIS(COMPLEXIO_ERR);
+	PIS(HS_TX_TIMEOUT);
+	PIS(LP_RX_TIMEOUT);
+	PIS(TE_TRIGGER);
+	PIS(ACK_TRIGGER);
+	PIS(SYNC_LOST);
+	PIS(LDO_POWER_GOOD);
+	PIS(TA_TIMEOUT);
+#undef PIS
+
+#define PIS(x) \
+	seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \
+			stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \
+			stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \
+			stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \
+			stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);
+
+	seq_printf(s, "-- VC interrupts --\n");
+	PIS(CS);
+	PIS(ECC_CORR);
+	PIS(PACKET_SENT);
+	PIS(FIFO_TX_OVF);
+	PIS(FIFO_RX_OVF);
+	PIS(BTA);
+	PIS(ECC_NO_CORR);
+	PIS(FIFO_TX_UDF);
+	PIS(PP_BUSY_CHANGE);
+#undef PIS
+
+#define PIS(x) \
+	seq_printf(s, "%-20s %10d\n", #x, \
+			stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);
+
+	seq_printf(s, "-- CIO interrupts --\n");
+	PIS(ERRSYNCESC1);
+	PIS(ERRSYNCESC2);
+	PIS(ERRSYNCESC3);
+	PIS(ERRESC1);
+	PIS(ERRESC2);
+	PIS(ERRESC3);
+	PIS(ERRCONTROL1);
+	PIS(ERRCONTROL2);
+	PIS(ERRCONTROL3);
+	PIS(STATEULPS1);
+	PIS(STATEULPS2);
+	PIS(STATEULPS3);
+	PIS(ERRCONTENTIONLP0_1);
+	PIS(ERRCONTENTIONLP1_1);
+	PIS(ERRCONTENTIONLP0_2);
+	PIS(ERRCONTENTIONLP1_2);
+	PIS(ERRCONTENTIONLP0_3);
+	PIS(ERRCONTENTIONLP1_3);
+	PIS(ULPSACTIVENOT_ALL0);
+	PIS(ULPSACTIVENOT_ALL1);
+#undef PIS
+}
+
+static void dsi1_dump_irqs(struct seq_file *s)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
+
+	dsi_dump_dsidev_irqs(dsidev, s);
+}
+
+static void dsi2_dump_irqs(struct seq_file *s)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
+
+	dsi_dump_dsidev_irqs(dsidev, s);
+}
+#endif
+
+static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
+		struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
+
+	if (dsi_runtime_get(dsidev))
+		return;
+	dsi_enable_scp_clk(dsidev);
+
+	DUMPREG(DSI_REVISION);
+	DUMPREG(DSI_SYSCONFIG);
+	DUMPREG(DSI_SYSSTATUS);
+	DUMPREG(DSI_IRQSTATUS);
+	DUMPREG(DSI_IRQENABLE);
+	DUMPREG(DSI_CTRL);
+	DUMPREG(DSI_COMPLEXIO_CFG1);
+	DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
+	DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
+	DUMPREG(DSI_CLK_CTRL);
+	DUMPREG(DSI_TIMING1);
+	DUMPREG(DSI_TIMING2);
+	DUMPREG(DSI_VM_TIMING1);
+	DUMPREG(DSI_VM_TIMING2);
+	DUMPREG(DSI_VM_TIMING3);
+	DUMPREG(DSI_CLK_TIMING);
+	DUMPREG(DSI_TX_FIFO_VC_SIZE);
+	DUMPREG(DSI_RX_FIFO_VC_SIZE);
+	DUMPREG(DSI_COMPLEXIO_CFG2);
+	DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
+	DUMPREG(DSI_VM_TIMING4);
+	DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
+	DUMPREG(DSI_VM_TIMING5);
+	DUMPREG(DSI_VM_TIMING6);
+	DUMPREG(DSI_VM_TIMING7);
+	DUMPREG(DSI_STOPCLK_TIMING);
+
+	DUMPREG(DSI_VC_CTRL(0));
+	DUMPREG(DSI_VC_TE(0));
+	DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
+	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
+	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
+	DUMPREG(DSI_VC_IRQSTATUS(0));
+	DUMPREG(DSI_VC_IRQENABLE(0));
+
+	DUMPREG(DSI_VC_CTRL(1));
+	DUMPREG(DSI_VC_TE(1));
+	DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
+	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
+	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
+	DUMPREG(DSI_VC_IRQSTATUS(1));
+	DUMPREG(DSI_VC_IRQENABLE(1));
+
+	DUMPREG(DSI_VC_CTRL(2));
+	DUMPREG(DSI_VC_TE(2));
+	DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
+	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
+	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
+	DUMPREG(DSI_VC_IRQSTATUS(2));
+	DUMPREG(DSI_VC_IRQENABLE(2));
+
+	DUMPREG(DSI_VC_CTRL(3));
+	DUMPREG(DSI_VC_TE(3));
+	DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
+	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
+	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
+	DUMPREG(DSI_VC_IRQSTATUS(3));
+	DUMPREG(DSI_VC_IRQENABLE(3));
+
+	DUMPREG(DSI_DSIPHY_CFG0);
+	DUMPREG(DSI_DSIPHY_CFG1);
+	DUMPREG(DSI_DSIPHY_CFG2);
+	DUMPREG(DSI_DSIPHY_CFG5);
+
+	DUMPREG(DSI_PLL_CONTROL);
+	DUMPREG(DSI_PLL_STATUS);
+	DUMPREG(DSI_PLL_GO);
+	DUMPREG(DSI_PLL_CONFIGURATION1);
+	DUMPREG(DSI_PLL_CONFIGURATION2);
+
+	dsi_disable_scp_clk(dsidev);
+	dsi_runtime_put(dsidev);
+#undef DUMPREG
+}
+
+static void dsi1_dump_regs(struct seq_file *s)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
+
+	dsi_dump_dsidev_regs(dsidev, s);
+}
+
+static void dsi2_dump_regs(struct seq_file *s)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
+
+	dsi_dump_dsidev_regs(dsidev, s);
+}
+
+enum dsi_cio_power_state {
+	DSI_COMPLEXIO_POWER_OFF		= 0x0,
+	DSI_COMPLEXIO_POWER_ON		= 0x1,
+	DSI_COMPLEXIO_POWER_ULPS	= 0x2,
+};
+
+static int dsi_cio_power(struct platform_device *dsidev,
+		enum dsi_cio_power_state state)
+{
+	int t = 0;
+
+	/* PWR_CMD */
+	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG1, state, 28, 27);
+
+	/* PWR_STATUS */
+	while (FLD_GET(dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1),
+			26, 25) != state) {
+		if (++t > 1000) {
+			DSSERR("failed to set complexio power state to "
+					"%d\n", state);
+			return -ENODEV;
+		}
+		udelay(1);
+	}
+
+	return 0;
+}
+
+static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
+{
+	int val;
+
+	/* line buffer on OMAP3 is 1024 x 24bits */
+	/* XXX: for some reason using full buffer size causes
+	 * considerable TX slowdown with update sizes that fill the
+	 * whole buffer */
+	if (!dss_has_feature(FEAT_DSI_GNQ))
+		return 1023 * 3;
+
+	val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */
+
+	switch (val) {
+	case 1:
+		return 512 * 3;		/* 512x24 bits */
+	case 2:
+		return 682 * 3;		/* 682x24 bits */
+	case 3:
+		return 853 * 3;		/* 853x24 bits */
+	case 4:
+		return 1024 * 3;	/* 1024x24 bits */
+	case 5:
+		return 1194 * 3;	/* 1194x24 bits */
+	case 6:
+		return 1365 * 3;	/* 1365x24 bits */
+	case 7:
+		return 1920 * 3;	/* 1920x24 bits */
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static int dsi_set_lane_config(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	static const u8 offsets[] = { 0, 4, 8, 12, 16 };
+	static const enum dsi_lane_function functions[] = {
+		DSI_LANE_CLK,
+		DSI_LANE_DATA1,
+		DSI_LANE_DATA2,
+		DSI_LANE_DATA3,
+		DSI_LANE_DATA4,
+	};
+	u32 r;
+	int i;
+
+	r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
+
+	for (i = 0; i < dsi->num_lanes_used; ++i) {
+		unsigned offset = offsets[i];
+		unsigned polarity, lane_number;
+		unsigned t;
+
+		for (t = 0; t < dsi->num_lanes_supported; ++t)
+			if (dsi->lanes[t].function == functions[i])
+				break;
+
+		if (t == dsi->num_lanes_supported)
+			return -EINVAL;
+
+		lane_number = t;
+		polarity = dsi->lanes[t].polarity;
+
+		r = FLD_MOD(r, lane_number + 1, offset + 2, offset);
+		r = FLD_MOD(r, polarity, offset + 3, offset + 3);
+	}
+
+	/* clear the unused lanes */
+	for (; i < dsi->num_lanes_supported; ++i) {
+		unsigned offset = offsets[i];
+
+		r = FLD_MOD(r, 0, offset + 2, offset);
+		r = FLD_MOD(r, 0, offset + 3, offset + 3);
+	}
+
+	dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
+
+	return 0;
+}
+
+static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	/* convert time in ns to ddr ticks, rounding up */
+	unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
+	return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
+}
+
+static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
+	return ddr * 1000 * 1000 / (ddr_clk / 1000);
+}
+
+static void dsi_cio_timings(struct platform_device *dsidev)
+{
+	u32 r;
+	u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
+	u32 tlpx_half, tclk_trail, tclk_zero;
+	u32 tclk_prepare;
+
+	/* calculate timings */
+
+	/* 1 * DDR_CLK = 2 * UI */
+
+	/* min 40ns + 4*UI	max 85ns + 6*UI */
+	ths_prepare = ns2ddr(dsidev, 70) + 2;
+
+	/* min 145ns + 10*UI */
+	ths_prepare_ths_zero = ns2ddr(dsidev, 175) + 2;
+
+	/* min max(8*UI, 60ns+4*UI) */
+	ths_trail = ns2ddr(dsidev, 60) + 5;
+
+	/* min 100ns */
+	ths_exit = ns2ddr(dsidev, 145);
+
+	/* tlpx min 50n */
+	tlpx_half = ns2ddr(dsidev, 25);
+
+	/* min 60ns */
+	tclk_trail = ns2ddr(dsidev, 60) + 2;
+
+	/* min 38ns, max 95ns */
+	tclk_prepare = ns2ddr(dsidev, 65);
+
+	/* min tclk-prepare + tclk-zero = 300ns */
+	tclk_zero = ns2ddr(dsidev, 260);
+
+	DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
+		ths_prepare, ddr2ns(dsidev, ths_prepare),
+		ths_prepare_ths_zero, ddr2ns(dsidev, ths_prepare_ths_zero));
+	DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
+			ths_trail, ddr2ns(dsidev, ths_trail),
+			ths_exit, ddr2ns(dsidev, ths_exit));
+
+	DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
+			"tclk_zero %u (%uns)\n",
+			tlpx_half, ddr2ns(dsidev, tlpx_half),
+			tclk_trail, ddr2ns(dsidev, tclk_trail),
+			tclk_zero, ddr2ns(dsidev, tclk_zero));
+	DSSDBG("tclk_prepare %u (%uns)\n",
+			tclk_prepare, ddr2ns(dsidev, tclk_prepare));
+
+	/* program timings */
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
+	r = FLD_MOD(r, ths_prepare, 31, 24);
+	r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
+	r = FLD_MOD(r, ths_trail, 15, 8);
+	r = FLD_MOD(r, ths_exit, 7, 0);
+	dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
+	r = FLD_MOD(r, tlpx_half, 20, 16);
+	r = FLD_MOD(r, tclk_trail, 15, 8);
+	r = FLD_MOD(r, tclk_zero, 7, 0);
+
+	if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
+		r = FLD_MOD(r, 0, 21, 21);	/* DCCEN = disable */
+		r = FLD_MOD(r, 1, 22, 22);	/* CLKINP_DIVBY2EN = enable */
+		r = FLD_MOD(r, 1, 23, 23);	/* CLKINP_SEL = enable */
+	}
+
+	dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
+	r = FLD_MOD(r, tclk_prepare, 7, 0);
+	dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
+}
+
+/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
+static void dsi_cio_enable_lane_override(struct platform_device *dsidev,
+		unsigned mask_p, unsigned mask_n)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int i;
+	u32 l;
+	u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26;
+
+	l = 0;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i) {
+		unsigned p = dsi->lanes[i].polarity;
+
+		if (mask_p & (1 << i))
+			l |= 1 << (i * 2 + (p ? 0 : 1));
+
+		if (mask_n & (1 << i))
+			l |= 1 << (i * 2 + (p ? 1 : 0));
+	}
+
+	/*
+	 * Bits in REGLPTXSCPDAT4TO0DXDY:
+	 * 17: DY0 18: DX0
+	 * 19: DY1 20: DX1
+	 * 21: DY2 22: DX2
+	 * 23: DY3 24: DX3
+	 * 25: DY4 26: DX4
+	 */
+
+	/* Set the lane override configuration */
+
+	/* REGLPTXSCPDAT4TO0DXDY */
+	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, lptxscp_start, 17);
+
+	/* Enable lane override */
+
+	/* ENLPTXSCPDAT */
+	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 1, 27, 27);
+}
+
+static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
+{
+	/* Disable lane override */
+	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
+	/* Reset the lane override configuration */
+	/* REGLPTXSCPDAT4TO0DXDY */
+	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
+}
+
+static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int t, i;
+	bool in_use[DSI_MAX_NR_LANES];
+	static const u8 offsets_old[] = { 28, 27, 26 };
+	static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
+	const u8 *offsets;
+
+	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
+		offsets = offsets_old;
+	else
+		offsets = offsets_new;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i)
+		in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED;
+
+	t = 100000;
+	while (true) {
+		u32 l;
+		int ok;
+
+		l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
+
+		ok = 0;
+		for (i = 0; i < dsi->num_lanes_supported; ++i) {
+			if (!in_use[i] || (l & (1 << offsets[i])))
+				ok++;
+		}
+
+		if (ok == dsi->num_lanes_supported)
+			break;
+
+		if (--t == 0) {
+			for (i = 0; i < dsi->num_lanes_supported; ++i) {
+				if (!in_use[i] || (l & (1 << offsets[i])))
+					continue;
+
+				DSSERR("CIO TXCLKESC%d domain not coming " \
+						"out of reset\n", i);
+			}
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+/* return bitmask of enabled lanes, lane0 being the lsb */
+static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned mask = 0;
+	int i;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i) {
+		if (dsi->lanes[i].function != DSI_LANE_UNUSED)
+			mask |= 1 << i;
+	}
+
+	return mask;
+}
+
+static int dsi_cio_init(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r;
+	u32 l;
+
+	DSSDBG("DSI CIO init starts");
+
+	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
+	if (r)
+		return r;
+
+	dsi_enable_scp_clk(dsidev);
+
+	/* A dummy read using the SCP interface to any DSIPHY register is
+	 * required after DSIPHY reset to complete the reset of the DSI complex
+	 * I/O. */
+	dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
+
+	if (wait_for_bit_change(dsidev, DSI_DSIPHY_CFG5, 30, 1) != 1) {
+		DSSERR("CIO SCP Clock domain not coming out of reset.\n");
+		r = -EIO;
+		goto err_scp_clk_dom;
+	}
+
+	r = dsi_set_lane_config(dsidev);
+	if (r)
+		goto err_scp_clk_dom;
+
+	/* set TX STOP MODE timer to maximum for this operation */
+	l = dsi_read_reg(dsidev, DSI_TIMING1);
+	l = FLD_MOD(l, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
+	l = FLD_MOD(l, 1, 14, 14);	/* STOP_STATE_X16_IO */
+	l = FLD_MOD(l, 1, 13, 13);	/* STOP_STATE_X4_IO */
+	l = FLD_MOD(l, 0x1fff, 12, 0);	/* STOP_STATE_COUNTER_IO */
+	dsi_write_reg(dsidev, DSI_TIMING1, l);
+
+	if (dsi->ulps_enabled) {
+		unsigned mask_p;
+		int i;
+
+		DSSDBG("manual ulps exit\n");
+
+		/* ULPS is exited by Mark-1 state for 1ms, followed by
+		 * stop state. DSS HW cannot do this via the normal
+		 * ULPS exit sequence, as after reset the DSS HW thinks
+		 * that we are not in ULPS mode, and refuses to send the
+		 * sequence. So we need to send the ULPS exit sequence
+		 * manually by setting positive lines high and negative lines
+		 * low for 1ms.
+		 */
+
+		mask_p = 0;
+
+		for (i = 0; i < dsi->num_lanes_supported; ++i) {
+			if (dsi->lanes[i].function == DSI_LANE_UNUSED)
+				continue;
+			mask_p |= 1 << i;
+		}
+
+		dsi_cio_enable_lane_override(dsidev, mask_p, 0);
+	}
+
+	r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
+	if (r)
+		goto err_cio_pwr;
+
+	if (wait_for_bit_change(dsidev, DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
+		DSSERR("CIO PWR clock domain not coming out of reset.\n");
+		r = -ENODEV;
+		goto err_cio_pwr_dom;
+	}
+
+	dsi_if_enable(dsidev, true);
+	dsi_if_enable(dsidev, false);
+	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
+
+	r = dsi_cio_wait_tx_clk_esc_reset(dsidev);
+	if (r)
+		goto err_tx_clk_esc_rst;
+
+	if (dsi->ulps_enabled) {
+		/* Keep Mark-1 state for 1ms (as per DSI spec) */
+		ktime_t wait = ns_to_ktime(1000 * 1000);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
+
+		/* Disable the override. The lanes should be set to Mark-11
+		 * state by the HW */
+		dsi_cio_disable_lane_override(dsidev);
+	}
+
+	/* FORCE_TX_STOP_MODE_IO */
+	REG_FLD_MOD(dsidev, DSI_TIMING1, 0, 15, 15);
+
+	dsi_cio_timings(dsidev);
+
+	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		/* DDR_CLK_ALWAYS_ON */
+		REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
+			dsi->vm_timings.ddr_clk_always_on, 13, 13);
+	}
+
+	dsi->ulps_enabled = false;
+
+	DSSDBG("CIO init done\n");
+
+	return 0;
+
+err_tx_clk_esc_rst:
+	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 20, 20); /* LP_CLK_ENABLE */
+err_cio_pwr_dom:
+	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
+err_cio_pwr:
+	if (dsi->ulps_enabled)
+		dsi_cio_disable_lane_override(dsidev);
+err_scp_clk_dom:
+	dsi_disable_scp_clk(dsidev);
+	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
+	return r;
+}
+
+static void dsi_cio_uninit(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	/* DDR_CLK_ALWAYS_ON */
+	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
+
+	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
+	dsi_disable_scp_clk(dsidev);
+	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
+}
+
+static void dsi_config_tx_fifo(struct platform_device *dsidev,
+		enum fifo_size size1, enum fifo_size size2,
+		enum fifo_size size3, enum fifo_size size4)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 r = 0;
+	int add = 0;
+	int i;
+
+	dsi->vc[0].tx_fifo_size = size1;
+	dsi->vc[1].tx_fifo_size = size2;
+	dsi->vc[2].tx_fifo_size = size3;
+	dsi->vc[3].tx_fifo_size = size4;
+
+	for (i = 0; i < 4; i++) {
+		u8 v;
+		int size = dsi->vc[i].tx_fifo_size;
+
+		if (add + size > 4) {
+			DSSERR("Illegal FIFO configuration\n");
+			BUG();
+			return;
+		}
+
+		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+		r |= v << (8 * i);
+		/*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
+		add += size;
+	}
+
+	dsi_write_reg(dsidev, DSI_TX_FIFO_VC_SIZE, r);
+}
+
+static void dsi_config_rx_fifo(struct platform_device *dsidev,
+		enum fifo_size size1, enum fifo_size size2,
+		enum fifo_size size3, enum fifo_size size4)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 r = 0;
+	int add = 0;
+	int i;
+
+	dsi->vc[0].rx_fifo_size = size1;
+	dsi->vc[1].rx_fifo_size = size2;
+	dsi->vc[2].rx_fifo_size = size3;
+	dsi->vc[3].rx_fifo_size = size4;
+
+	for (i = 0; i < 4; i++) {
+		u8 v;
+		int size = dsi->vc[i].rx_fifo_size;
+
+		if (add + size > 4) {
+			DSSERR("Illegal FIFO configuration\n");
+			BUG();
+			return;
+		}
+
+		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+		r |= v << (8 * i);
+		/*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
+		add += size;
+	}
+
+	dsi_write_reg(dsidev, DSI_RX_FIFO_VC_SIZE, r);
+}
+
+static int dsi_force_tx_stop_mode_io(struct platform_device *dsidev)
+{
+	u32 r;
+
+	r = dsi_read_reg(dsidev, DSI_TIMING1);
+	r = FLD_MOD(r, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
+	dsi_write_reg(dsidev, DSI_TIMING1, r);
+
+	if (wait_for_bit_change(dsidev, DSI_TIMING1, 15, 0) != 0) {
+		DSSERR("TX_STOP bit not going down\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static bool dsi_vc_is_enabled(struct platform_device *dsidev, int channel)
+{
+	return REG_GET(dsidev, DSI_VC_CTRL(channel), 0, 0);
+}
+
+static void dsi_packet_sent_handler_vp(void *data, u32 mask)
+{
+	struct dsi_packet_sent_handler_data *vp_data =
+		(struct dsi_packet_sent_handler_data *) data;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(vp_data->dsidev);
+	const int channel = dsi->update_channel;
+	u8 bit = dsi->te_enabled ? 30 : 31;
+
+	if (REG_GET(vp_data->dsidev, DSI_VC_TE(channel), bit, bit) == 0)
+		complete(vp_data->completion);
+}
+
+static int dsi_sync_vc_vp(struct platform_device *dsidev, int channel)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	DECLARE_COMPLETION_ONSTACK(completion);
+	struct dsi_packet_sent_handler_data vp_data = { dsidev, &completion };
+	int r = 0;
+	u8 bit;
+
+	bit = dsi->te_enabled ? 30 : 31;
+
+	r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
+		&vp_data, DSI_VC_IRQ_PACKET_SENT);
+	if (r)
+		goto err0;
+
+	/* Wait for completion only if TE_EN/TE_START is still set */
+	if (REG_GET(dsidev, DSI_VC_TE(channel), bit, bit)) {
+		if (wait_for_completion_timeout(&completion,
+				msecs_to_jiffies(10)) == 0) {
+			DSSERR("Failed to complete previous frame transfer\n");
+			r = -EIO;
+			goto err1;
+		}
+	}
+
+	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
+		&vp_data, DSI_VC_IRQ_PACKET_SENT);
+
+	return 0;
+err1:
+	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
+		&vp_data, DSI_VC_IRQ_PACKET_SENT);
+err0:
+	return r;
+}
+
+static void dsi_packet_sent_handler_l4(void *data, u32 mask)
+{
+	struct dsi_packet_sent_handler_data *l4_data =
+		(struct dsi_packet_sent_handler_data *) data;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(l4_data->dsidev);
+	const int channel = dsi->update_channel;
+
+	if (REG_GET(l4_data->dsidev, DSI_VC_CTRL(channel), 5, 5) == 0)
+		complete(l4_data->completion);
+}
+
+static int dsi_sync_vc_l4(struct platform_device *dsidev, int channel)
+{
+	DECLARE_COMPLETION_ONSTACK(completion);
+	struct dsi_packet_sent_handler_data l4_data = { dsidev, &completion };
+	int r = 0;
+
+	r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
+		&l4_data, DSI_VC_IRQ_PACKET_SENT);
+	if (r)
+		goto err0;
+
+	/* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */
+	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 5, 5)) {
+		if (wait_for_completion_timeout(&completion,
+				msecs_to_jiffies(10)) == 0) {
+			DSSERR("Failed to complete previous l4 transfer\n");
+			r = -EIO;
+			goto err1;
+		}
+	}
+
+	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
+		&l4_data, DSI_VC_IRQ_PACKET_SENT);
+
+	return 0;
+err1:
+	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
+		&l4_data, DSI_VC_IRQ_PACKET_SENT);
+err0:
+	return r;
+}
+
+static int dsi_sync_vc(struct platform_device *dsidev, int channel)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	WARN_ON(in_interrupt());
+
+	if (!dsi_vc_is_enabled(dsidev, channel))
+		return 0;
+
+	switch (dsi->vc[channel].source) {
+	case DSI_VC_SOURCE_VP:
+		return dsi_sync_vc_vp(dsidev, channel);
+	case DSI_VC_SOURCE_L4:
+		return dsi_sync_vc_l4(dsidev, channel);
+	default:
+		BUG();
+		return -EINVAL;
+	}
+}
+
+static int dsi_vc_enable(struct platform_device *dsidev, int channel,
+		bool enable)
+{
+	DSSDBG("dsi_vc_enable channel %d, enable %d\n",
+			channel, enable);
+
+	enable = enable ? 1 : 0;
+
+	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 0, 0);
+
+	if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel),
+		0, enable) != enable) {
+			DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
+			return -EIO;
+	}
+
+	return 0;
+}
+
+static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 r;
+
+	DSSDBG("Initial config of virtual channel %d", channel);
+
+	r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
+
+	if (FLD_GET(r, 15, 15)) /* VC_BUSY */
+		DSSERR("VC(%d) busy when trying to configure it!\n",
+				channel);
+
+	r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
+	r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN  */
+	r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+	r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
+	r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
+	r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
+	r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
+	if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
+		r = FLD_MOD(r, 3, 11, 10);	/* OCP_WIDTH = 32 bit */
+
+	r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
+	r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
+
+	dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
+
+	dsi->vc[channel].source = DSI_VC_SOURCE_L4;
+}
+
+static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
+		enum dsi_vc_source source)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (dsi->vc[channel].source == source)
+		return 0;
+
+	DSSDBG("Source config of virtual channel %d", channel);
+
+	dsi_sync_vc(dsidev, channel);
+
+	dsi_vc_enable(dsidev, channel, 0);
+
+	/* VC_BUSY */
+	if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
+		DSSERR("vc(%d) busy when trying to config for VP\n", channel);
+		return -EIO;
+	}
+
+	/* SOURCE, 0 = L4, 1 = video port */
+	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
+
+	/* DCS_CMD_ENABLE */
+	if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
+		bool enable = source == DSI_VC_SOURCE_VP;
+		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
+	}
+
+	dsi_vc_enable(dsidev, channel, 1);
+
+	dsi->vc[channel].source = source;
+
+	return 0;
+}
+
+static void dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
+		bool enable)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	dsi_vc_enable(dsidev, channel, 0);
+	dsi_if_enable(dsidev, 0);
+
+	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 9, 9);
+
+	dsi_vc_enable(dsidev, channel, 1);
+	dsi_if_enable(dsidev, 1);
+
+	dsi_force_tx_stop_mode_io(dsidev);
+
+	/* start the DDR clock by sending a NULL packet */
+	if (dsi->vm_timings.ddr_clk_always_on && enable)
+		dsi_vc_send_null(dssdev, channel);
+}
+
+static void dsi_vc_flush_long_data(struct platform_device *dsidev, int channel)
+{
+	while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
+		u32 val;
+		val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
+		DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
+				(val >> 0) & 0xff,
+				(val >> 8) & 0xff,
+				(val >> 16) & 0xff,
+				(val >> 24) & 0xff);
+	}
+}
+
+static void dsi_show_rx_ack_with_err(u16 err)
+{
+	DSSERR("\tACK with ERROR (%#x):\n", err);
+	if (err & (1 << 0))
+		DSSERR("\t\tSoT Error\n");
+	if (err & (1 << 1))
+		DSSERR("\t\tSoT Sync Error\n");
+	if (err & (1 << 2))
+		DSSERR("\t\tEoT Sync Error\n");
+	if (err & (1 << 3))
+		DSSERR("\t\tEscape Mode Entry Command Error\n");
+	if (err & (1 << 4))
+		DSSERR("\t\tLP Transmit Sync Error\n");
+	if (err & (1 << 5))
+		DSSERR("\t\tHS Receive Timeout Error\n");
+	if (err & (1 << 6))
+		DSSERR("\t\tFalse Control Error\n");
+	if (err & (1 << 7))
+		DSSERR("\t\t(reserved7)\n");
+	if (err & (1 << 8))
+		DSSERR("\t\tECC Error, single-bit (corrected)\n");
+	if (err & (1 << 9))
+		DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
+	if (err & (1 << 10))
+		DSSERR("\t\tChecksum Error\n");
+	if (err & (1 << 11))
+		DSSERR("\t\tData type not recognized\n");
+	if (err & (1 << 12))
+		DSSERR("\t\tInvalid VC ID\n");
+	if (err & (1 << 13))
+		DSSERR("\t\tInvalid Transmission Length\n");
+	if (err & (1 << 14))
+		DSSERR("\t\t(reserved14)\n");
+	if (err & (1 << 15))
+		DSSERR("\t\tDSI Protocol Violation\n");
+}
+
+static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
+		int channel)
+{
+	/* RX_FIFO_NOT_EMPTY */
+	while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
+		u32 val;
+		u8 dt;
+		val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
+		DSSERR("\trawval %#08x\n", val);
+		dt = FLD_GET(val, 5, 0);
+		if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
+			u16 err = FLD_GET(val, 23, 8);
+			dsi_show_rx_ack_with_err(err);
+		} else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {
+			DSSERR("\tDCS short response, 1 byte: %#x\n",
+					FLD_GET(val, 23, 8));
+		} else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
+			DSSERR("\tDCS short response, 2 byte: %#x\n",
+					FLD_GET(val, 23, 8));
+		} else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
+			DSSERR("\tDCS long response, len %d\n",
+					FLD_GET(val, 23, 8));
+			dsi_vc_flush_long_data(dsidev, channel);
+		} else {
+			DSSERR("\tunknown datatype 0x%02x\n", dt);
+		}
+	}
+	return 0;
+}
+
+static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (dsi->debug_write || dsi->debug_read)
+		DSSDBG("dsi_vc_send_bta %d\n", channel);
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	/* RX_FIFO_NOT_EMPTY */
+	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
+		DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
+		dsi_vc_flush_receive_data(dsidev, channel);
+	}
+
+	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
+
+	/* flush posted write */
+	dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
+
+	return 0;
+}
+
+static int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	DECLARE_COMPLETION_ONSTACK(completion);
+	int r = 0;
+	u32 err;
+
+	r = dsi_register_isr_vc(dsidev, channel, dsi_completion_handler,
+			&completion, DSI_VC_IRQ_BTA);
+	if (r)
+		goto err0;
+
+	r = dsi_register_isr(dsidev, dsi_completion_handler, &completion,
+			DSI_IRQ_ERROR_MASK);
+	if (r)
+		goto err1;
+
+	r = dsi_vc_send_bta(dsidev, channel);
+	if (r)
+		goto err2;
+
+	if (wait_for_completion_timeout(&completion,
+				msecs_to_jiffies(500)) == 0) {
+		DSSERR("Failed to receive BTA\n");
+		r = -EIO;
+		goto err2;
+	}
+
+	err = dsi_get_errors(dsidev);
+	if (err) {
+		DSSERR("Error while sending BTA: %x\n", err);
+		r = -EIO;
+		goto err2;
+	}
+err2:
+	dsi_unregister_isr(dsidev, dsi_completion_handler, &completion,
+			DSI_IRQ_ERROR_MASK);
+err1:
+	dsi_unregister_isr_vc(dsidev, channel, dsi_completion_handler,
+			&completion, DSI_VC_IRQ_BTA);
+err0:
+	return r;
+}
+
+static inline void dsi_vc_write_long_header(struct platform_device *dsidev,
+		int channel, u8 data_type, u16 len, u8 ecc)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 val;
+	u8 data_id;
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	data_id = data_type | dsi->vc[channel].vc_id << 6;
+
+	val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
+		FLD_VAL(ecc, 31, 24);
+
+	dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_HEADER(channel), val);
+}
+
+static inline void dsi_vc_write_long_payload(struct platform_device *dsidev,
+		int channel, u8 b1, u8 b2, u8 b3, u8 b4)
+{
+	u32 val;
+
+	val = b4 << 24 | b3 << 16 | b2 << 8  | b1 << 0;
+
+/*	DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
+			b1, b2, b3, b4, val); */
+
+	dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
+}
+
+static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
+		u8 data_type, u8 *data, u16 len, u8 ecc)
+{
+	/*u32 val; */
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int i;
+	u8 *p;
+	int r = 0;
+	u8 b1, b2, b3, b4;
+
+	if (dsi->debug_write)
+		DSSDBG("dsi_vc_send_long, %d bytes\n", len);
+
+	/* len + header */
+	if (dsi->vc[channel].tx_fifo_size * 32 * 4 < len + 4) {
+		DSSERR("unable to send long packet: packet too long.\n");
+		return -EINVAL;
+	}
+
+	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
+
+	dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
+
+	p = data;
+	for (i = 0; i < len >> 2; i++) {
+		if (dsi->debug_write)
+			DSSDBG("\tsending full packet %d\n", i);
+
+		b1 = *p++;
+		b2 = *p++;
+		b3 = *p++;
+		b4 = *p++;
+
+		dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, b4);
+	}
+
+	i = len % 4;
+	if (i) {
+		b1 = 0; b2 = 0; b3 = 0;
+
+		if (dsi->debug_write)
+			DSSDBG("\tsending remainder bytes %d\n", i);
+
+		switch (i) {
+		case 3:
+			b1 = *p++;
+			b2 = *p++;
+			b3 = *p++;
+			break;
+		case 2:
+			b1 = *p++;
+			b2 = *p++;
+			break;
+		case 1:
+			b1 = *p++;
+			break;
+		}
+
+		dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, 0);
+	}
+
+	return r;
+}
+
+static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
+		u8 data_type, u16 data, u8 ecc)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 r;
+	u8 data_id;
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	if (dsi->debug_write)
+		DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
+				channel,
+				data_type, data & 0xff, (data >> 8) & 0xff);
+
+	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
+
+	if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
+		DSSERR("ERROR FIFO FULL, aborting transfer\n");
+		return -EINVAL;
+	}
+
+	data_id = data_type | dsi->vc[channel].vc_id << 6;
+
+	r = (data_id << 0) | (data << 8) | (ecc << 24);
+
+	dsi_write_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel), r);
+
+	return 0;
+}
+
+static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+
+	return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL,
+		0, 0);
+}
+
+static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
+		int channel, u8 *data, int len, enum dss_dsi_content_type type)
+{
+	int r;
+
+	if (len == 0) {
+		BUG_ON(type == DSS_DSI_CONTENT_DCS);
+		r = dsi_vc_send_short(dsidev, channel,
+				MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0);
+	} else if (len == 1) {
+		r = dsi_vc_send_short(dsidev, channel,
+				type == DSS_DSI_CONTENT_GENERIC ?
+				MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
+				MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
+	} else if (len == 2) {
+		r = dsi_vc_send_short(dsidev, channel,
+				type == DSS_DSI_CONTENT_GENERIC ?
+				MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
+				MIPI_DSI_DCS_SHORT_WRITE_PARAM,
+				data[0] | (data[1] << 8), 0);
+	} else {
+		r = dsi_vc_send_long(dsidev, channel,
+				type == DSS_DSI_CONTENT_GENERIC ?
+				MIPI_DSI_GENERIC_LONG_WRITE :
+				MIPI_DSI_DCS_LONG_WRITE, data, len, 0);
+	}
+
+	return r;
+}
+
+static int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
+		u8 *data, int len)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+
+	return dsi_vc_write_nosync_common(dsidev, channel, data, len,
+			DSS_DSI_CONTENT_DCS);
+}
+
+static int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
+		u8 *data, int len)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+
+	return dsi_vc_write_nosync_common(dsidev, channel, data, len,
+			DSS_DSI_CONTENT_GENERIC);
+}
+
+static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
+		u8 *data, int len, enum dss_dsi_content_type type)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	int r;
+
+	r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);
+	if (r)
+		goto err;
+
+	r = dsi_vc_send_bta_sync(dssdev, channel);
+	if (r)
+		goto err;
+
+	/* RX_FIFO_NOT_EMPTY */
+	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
+		DSSERR("rx fifo not empty after write, dumping data:\n");
+		dsi_vc_flush_receive_data(dsidev, channel);
+		r = -EIO;
+		goto err;
+	}
+
+	return 0;
+err:
+	DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n",
+			channel, data[0], len);
+	return r;
+}
+
+static int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+		int len)
+{
+	return dsi_vc_write_common(dssdev, channel, data, len,
+			DSS_DSI_CONTENT_DCS);
+}
+
+static int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+		int len)
+{
+	return dsi_vc_write_common(dssdev, channel, data, len,
+			DSS_DSI_CONTENT_GENERIC);
+}
+
+static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
+		int channel, u8 dcs_cmd)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r;
+
+	if (dsi->debug_read)
+		DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n",
+			channel, dcs_cmd);
+
+	r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
+	if (r) {
+		DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)"
+			" failed\n", channel, dcs_cmd);
+		return r;
+	}
+
+	return 0;
+}
+
+static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,
+		int channel, u8 *reqdata, int reqlen)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u16 data;
+	u8 data_type;
+	int r;
+
+	if (dsi->debug_read)
+		DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n",
+			channel, reqlen);
+
+	if (reqlen == 0) {
+		data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
+		data = 0;
+	} else if (reqlen == 1) {
+		data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
+		data = reqdata[0];
+	} else if (reqlen == 2) {
+		data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
+		data = reqdata[0] | (reqdata[1] << 8);
+	} else {
+		BUG();
+		return -EINVAL;
+	}
+
+	r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
+	if (r) {
+		DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)"
+			" failed\n", channel, reqlen);
+		return r;
+	}
+
+	return 0;
+}
+
+static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
+		u8 *buf, int buflen, enum dss_dsi_content_type type)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 val;
+	u8 dt;
+	int r;
+
+	/* RX_FIFO_NOT_EMPTY */
+	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
+		DSSERR("RX fifo empty when trying to read.\n");
+		r = -EIO;
+		goto err;
+	}
+
+	val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
+	if (dsi->debug_read)
+		DSSDBG("\theader: %08x\n", val);
+	dt = FLD_GET(val, 5, 0);
+	if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
+		u16 err = FLD_GET(val, 23, 8);
+		dsi_show_rx_ack_with_err(err);
+		r = -EIO;
+		goto err;
+
+	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+			MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE :
+			MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {
+		u8 data = FLD_GET(val, 15, 8);
+		if (dsi->debug_read)
+			DSSDBG("\t%s short response, 1 byte: %02x\n",
+				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+				"DCS", data);
+
+		if (buflen < 1) {
+			r = -EIO;
+			goto err;
+		}
+
+		buf[0] = data;
+
+		return 1;
+	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+			MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE :
+			MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {
+		u16 data = FLD_GET(val, 23, 8);
+		if (dsi->debug_read)
+			DSSDBG("\t%s short response, 2 byte: %04x\n",
+				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+				"DCS", data);
+
+		if (buflen < 2) {
+			r = -EIO;
+			goto err;
+		}
+
+		buf[0] = data & 0xff;
+		buf[1] = (data >> 8) & 0xff;
+
+		return 2;
+	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+			MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE :
+			MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {
+		int w;
+		int len = FLD_GET(val, 23, 8);
+		if (dsi->debug_read)
+			DSSDBG("\t%s long response, len %d\n",
+				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+				"DCS", len);
+
+		if (len > buflen) {
+			r = -EIO;
+			goto err;
+		}
+
+		/* two byte checksum ends the packet, not included in len */
+		for (w = 0; w < len + 2;) {
+			int b;
+			val = dsi_read_reg(dsidev,
+				DSI_VC_SHORT_PACKET_HEADER(channel));
+			if (dsi->debug_read)
+				DSSDBG("\t\t%02x %02x %02x %02x\n",
+						(val >> 0) & 0xff,
+						(val >> 8) & 0xff,
+						(val >> 16) & 0xff,
+						(val >> 24) & 0xff);
+
+			for (b = 0; b < 4; ++b) {
+				if (w < len)
+					buf[w] = (val >> (b * 8)) & 0xff;
+				/* we discard the 2 byte checksum */
+				++w;
+			}
+		}
+
+		return len;
+	} else {
+		DSSERR("\tunknown datatype 0x%02x\n", dt);
+		r = -EIO;
+		goto err;
+	}
+
+err:
+	DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
+		type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
+
+	return r;
+}
+
+static int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
+		u8 *buf, int buflen)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	int r;
+
+	r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
+	if (r)
+		goto err;
+
+	r = dsi_vc_send_bta_sync(dssdev, channel);
+	if (r)
+		goto err;
+
+	r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
+		DSS_DSI_CONTENT_DCS);
+	if (r < 0)
+		goto err;
+
+	if (r != buflen) {
+		r = -EIO;
+		goto err;
+	}
+
+	return 0;
+err:
+	DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
+	return r;
+}
+
+static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
+		u8 *reqdata, int reqlen, u8 *buf, int buflen)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	int r;
+
+	r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);
+	if (r)
+		return r;
+
+	r = dsi_vc_send_bta_sync(dssdev, channel);
+	if (r)
+		return r;
+
+	r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
+		DSS_DSI_CONTENT_GENERIC);
+	if (r < 0)
+		return r;
+
+	if (r != buflen) {
+		r = -EIO;
+		return r;
+	}
+
+	return 0;
+}
+
+static int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
+		u16 len)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+
+	return dsi_vc_send_short(dsidev, channel,
+			MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
+}
+
+static int dsi_enter_ulps(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	DECLARE_COMPLETION_ONSTACK(completion);
+	int r, i;
+	unsigned mask;
+
+	DSSDBG("Entering ULPS");
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	WARN_ON(dsi->ulps_enabled);
+
+	if (dsi->ulps_enabled)
+		return 0;
+
+	/* DDR_CLK_ALWAYS_ON */
+	if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
+		dsi_if_enable(dsidev, 0);
+		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
+		dsi_if_enable(dsidev, 1);
+	}
+
+	dsi_sync_vc(dsidev, 0);
+	dsi_sync_vc(dsidev, 1);
+	dsi_sync_vc(dsidev, 2);
+	dsi_sync_vc(dsidev, 3);
+
+	dsi_force_tx_stop_mode_io(dsidev);
+
+	dsi_vc_enable(dsidev, 0, false);
+	dsi_vc_enable(dsidev, 1, false);
+	dsi_vc_enable(dsidev, 2, false);
+	dsi_vc_enable(dsidev, 3, false);
+
+	if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 16, 16)) {	/* HS_BUSY */
+		DSSERR("HS busy when enabling ULPS\n");
+		return -EIO;
+	}
+
+	if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 17, 17)) {	/* LP_BUSY */
+		DSSERR("LP busy when enabling ULPS\n");
+		return -EIO;
+	}
+
+	r = dsi_register_isr_cio(dsidev, dsi_completion_handler, &completion,
+			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
+	if (r)
+		return r;
+
+	mask = 0;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i) {
+		if (dsi->lanes[i].function == DSI_LANE_UNUSED)
+			continue;
+		mask |= 1 << i;
+	}
+	/* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
+	/* LANEx_ULPS_SIG2 */
+	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5);
+
+	/* flush posted write and wait for SCP interface to finish the write */
+	dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
+
+	if (wait_for_completion_timeout(&completion,
+				msecs_to_jiffies(1000)) == 0) {
+		DSSERR("ULPS enable timeout\n");
+		r = -EIO;
+		goto err;
+	}
+
+	dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
+			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
+
+	/* Reset LANEx_ULPS_SIG2 */
+	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5);
+
+	/* flush posted write and wait for SCP interface to finish the write */
+	dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
+
+	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
+
+	dsi_if_enable(dsidev, false);
+
+	dsi->ulps_enabled = true;
+
+	return 0;
+
+err:
+	dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
+			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
+	return r;
+}
+
+static void dsi_set_lp_rx_timeout(struct platform_device *dsidev,
+		unsigned ticks, bool x4, bool x16)
+{
+	unsigned long fck;
+	unsigned long total_ticks;
+	u32 r;
+
+	BUG_ON(ticks > 0x1fff);
+
+	/* ticks in DSI_FCK */
+	fck = dsi_fclk_rate(dsidev);
+
+	r = dsi_read_reg(dsidev, DSI_TIMING2);
+	r = FLD_MOD(r, 1, 15, 15);	/* LP_RX_TO */
+	r = FLD_MOD(r, x16 ? 1 : 0, 14, 14);	/* LP_RX_TO_X16 */
+	r = FLD_MOD(r, x4 ? 1 : 0, 13, 13);	/* LP_RX_TO_X4 */
+	r = FLD_MOD(r, ticks, 12, 0);	/* LP_RX_COUNTER */
+	dsi_write_reg(dsidev, DSI_TIMING2, r);
+
+	total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
+
+	DSSDBG("LP_RX_TO %lu ticks (%#x%s%s) = %lu ns\n",
+			total_ticks,
+			ticks, x4 ? " x4" : "", x16 ? " x16" : "",
+			(total_ticks * 1000) / (fck / 1000 / 1000));
+}
+
+static void dsi_set_ta_timeout(struct platform_device *dsidev, unsigned ticks,
+		bool x8, bool x16)
+{
+	unsigned long fck;
+	unsigned long total_ticks;
+	u32 r;
+
+	BUG_ON(ticks > 0x1fff);
+
+	/* ticks in DSI_FCK */
+	fck = dsi_fclk_rate(dsidev);
+
+	r = dsi_read_reg(dsidev, DSI_TIMING1);
+	r = FLD_MOD(r, 1, 31, 31);	/* TA_TO */
+	r = FLD_MOD(r, x16 ? 1 : 0, 30, 30);	/* TA_TO_X16 */
+	r = FLD_MOD(r, x8 ? 1 : 0, 29, 29);	/* TA_TO_X8 */
+	r = FLD_MOD(r, ticks, 28, 16);	/* TA_TO_COUNTER */
+	dsi_write_reg(dsidev, DSI_TIMING1, r);
+
+	total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1);
+
+	DSSDBG("TA_TO %lu ticks (%#x%s%s) = %lu ns\n",
+			total_ticks,
+			ticks, x8 ? " x8" : "", x16 ? " x16" : "",
+			(total_ticks * 1000) / (fck / 1000 / 1000));
+}
+
+static void dsi_set_stop_state_counter(struct platform_device *dsidev,
+		unsigned ticks, bool x4, bool x16)
+{
+	unsigned long fck;
+	unsigned long total_ticks;
+	u32 r;
+
+	BUG_ON(ticks > 0x1fff);
+
+	/* ticks in DSI_FCK */
+	fck = dsi_fclk_rate(dsidev);
+
+	r = dsi_read_reg(dsidev, DSI_TIMING1);
+	r = FLD_MOD(r, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
+	r = FLD_MOD(r, x16 ? 1 : 0, 14, 14);	/* STOP_STATE_X16_IO */
+	r = FLD_MOD(r, x4 ? 1 : 0, 13, 13);	/* STOP_STATE_X4_IO */
+	r = FLD_MOD(r, ticks, 12, 0);	/* STOP_STATE_COUNTER_IO */
+	dsi_write_reg(dsidev, DSI_TIMING1, r);
+
+	total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
+
+	DSSDBG("STOP_STATE_COUNTER %lu ticks (%#x%s%s) = %lu ns\n",
+			total_ticks,
+			ticks, x4 ? " x4" : "", x16 ? " x16" : "",
+			(total_ticks * 1000) / (fck / 1000 / 1000));
+}
+
+static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
+		unsigned ticks, bool x4, bool x16)
+{
+	unsigned long fck;
+	unsigned long total_ticks;
+	u32 r;
+
+	BUG_ON(ticks > 0x1fff);
+
+	/* ticks in TxByteClkHS */
+	fck = dsi_get_txbyteclkhs(dsidev);
+
+	r = dsi_read_reg(dsidev, DSI_TIMING2);
+	r = FLD_MOD(r, 1, 31, 31);	/* HS_TX_TO */
+	r = FLD_MOD(r, x16 ? 1 : 0, 30, 30);	/* HS_TX_TO_X16 */
+	r = FLD_MOD(r, x4 ? 1 : 0, 29, 29);	/* HS_TX_TO_X8 (4 really) */
+	r = FLD_MOD(r, ticks, 28, 16);	/* HS_TX_TO_COUNTER */
+	dsi_write_reg(dsidev, DSI_TIMING2, r);
+
+	total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
+
+	DSSDBG("HS_TX_TO %lu ticks (%#x%s%s) = %lu ns\n",
+			total_ticks,
+			ticks, x4 ? " x4" : "", x16 ? " x16" : "",
+			(total_ticks * 1000) / (fck / 1000 / 1000));
+}
+
+static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int num_line_buffers;
+
+	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
+		struct omap_video_timings *timings = &dsi->timings;
+		/*
+		 * Don't use line buffers if width is greater than the video
+		 * port's line buffer size
+		 */
+		if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
+			num_line_buffers = 0;
+		else
+			num_line_buffers = 2;
+	} else {
+		/* Use maximum number of line buffers in command mode */
+		num_line_buffers = 2;
+	}
+
+	/* LINE_BUFFER */
+	REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
+}
+
+static void dsi_config_vp_sync_events(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	bool sync_end;
+	u32 r;
+
+	if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE)
+		sync_end = true;
+	else
+		sync_end = false;
+
+	r = dsi_read_reg(dsidev, DSI_CTRL);
+	r = FLD_MOD(r, 1, 9, 9);		/* VP_DE_POL */
+	r = FLD_MOD(r, 1, 10, 10);		/* VP_HSYNC_POL */
+	r = FLD_MOD(r, 1, 11, 11);		/* VP_VSYNC_POL */
+	r = FLD_MOD(r, 1, 15, 15);		/* VP_VSYNC_START */
+	r = FLD_MOD(r, sync_end, 16, 16);	/* VP_VSYNC_END */
+	r = FLD_MOD(r, 1, 17, 17);		/* VP_HSYNC_START */
+	r = FLD_MOD(r, sync_end, 18, 18);	/* VP_HSYNC_END */
+	dsi_write_reg(dsidev, DSI_CTRL, r);
+}
+
+static void dsi_config_blanking_modes(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int blanking_mode = dsi->vm_timings.blanking_mode;
+	int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
+	int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
+	int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
+	u32 r;
+
+	/*
+	 * 0 = TX FIFO packets sent or LPS in corresponding blanking periods
+	 * 1 = Long blanking packets are sent in corresponding blanking periods
+	 */
+	r = dsi_read_reg(dsidev, DSI_CTRL);
+	r = FLD_MOD(r, blanking_mode, 20, 20);		/* BLANKING_MODE */
+	r = FLD_MOD(r, hfp_blanking_mode, 21, 21);	/* HFP_BLANKING */
+	r = FLD_MOD(r, hbp_blanking_mode, 22, 22);	/* HBP_BLANKING */
+	r = FLD_MOD(r, hsa_blanking_mode, 23, 23);	/* HSA_BLANKING */
+	dsi_write_reg(dsidev, DSI_CTRL, r);
+}
+
+/*
+ * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3
+ * results in maximum transition time for data and clock lanes to enter and
+ * exit HS mode. Hence, this is the scenario where the least amount of command
+ * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS
+ * clock cycles that can be used to interleave command mode data in HS so that
+ * all scenarios are satisfied.
+ */
+static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs,
+		int exit_hs, int exiths_clk, int ddr_pre, int ddr_post)
+{
+	int transition;
+
+	/*
+	 * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition
+	 * time of data lanes only, if it isn't set, we need to consider HS
+	 * transition time of both data and clock lanes. HS transition time
+	 * of Scenario 3 is considered.
+	 */
+	if (ddr_alwon) {
+		transition = enter_hs + exit_hs + max(enter_hs, 2) + 1;
+	} else {
+		int trans1, trans2;
+		trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1;
+		trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre +
+				enter_hs + 1;
+		transition = max(trans1, trans2);
+	}
+
+	return blank > transition ? blank - transition : 0;
+}
+
+/*
+ * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1
+ * results in maximum transition time for data lanes to enter and exit LP mode.
+ * Hence, this is the scenario where the least amount of command mode data can
+ * be interleaved. We program the minimum amount of bytes that can be
+ * interleaved in LP so that all scenarios are satisfied.
+ */
+static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
+		int lp_clk_div, int tdsi_fclk)
+{
+	int trans_lp;	/* time required for a LP transition, in TXBYTECLKHS */
+	int tlp_avail;	/* time left for interleaving commands, in CLKIN4DDR */
+	int ttxclkesc;	/* period of LP transmit escape clock, in CLKIN4DDR */
+	int thsbyte_clk = 16;	/* Period of TXBYTECLKHS clock, in CLKIN4DDR */
+	int lp_inter;	/* cmd mode data that can be interleaved, in bytes */
+
+	/* maximum LP transition time according to Scenario 1 */
+	trans_lp = exit_hs + max(enter_hs, 2) + 1;
+
+	/* CLKIN4DDR = 16 * TXBYTECLKHS */
+	tlp_avail = thsbyte_clk * (blank - trans_lp);
+
+	ttxclkesc = tdsi_fclk * lp_clk_div;
+
+	lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc -
+			26) / 16;
+
+	return max(lp_inter, 0);
+}
+
+static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int blanking_mode;
+	int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
+	int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div;
+	int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
+	int tclk_trail, ths_exit, exiths_clk;
+	bool ddr_alwon;
+	struct omap_video_timings *timings = &dsi->timings;
+	int bpp = dsi_get_pixel_size(dsi->pix_fmt);
+	int ndl = dsi->num_lanes_used - 1;
+	int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1;
+	int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
+	int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
+	int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
+	int bl_interleave_hs = 0, bl_interleave_lp = 0;
+	u32 r;
+
+	r = dsi_read_reg(dsidev, DSI_CTRL);
+	blanking_mode = FLD_GET(r, 20, 20);
+	hfp_blanking_mode = FLD_GET(r, 21, 21);
+	hbp_blanking_mode = FLD_GET(r, 22, 22);
+	hsa_blanking_mode = FLD_GET(r, 23, 23);
+
+	r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
+	hbp = FLD_GET(r, 11, 0);
+	hfp = FLD_GET(r, 23, 12);
+	hsa = FLD_GET(r, 31, 24);
+
+	r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
+	ddr_clk_post = FLD_GET(r, 7, 0);
+	ddr_clk_pre = FLD_GET(r, 15, 8);
+
+	r = dsi_read_reg(dsidev, DSI_VM_TIMING7);
+	exit_hs_mode_lat = FLD_GET(r, 15, 0);
+	enter_hs_mode_lat = FLD_GET(r, 31, 16);
+
+	r = dsi_read_reg(dsidev, DSI_CLK_CTRL);
+	lp_clk_div = FLD_GET(r, 12, 0);
+	ddr_alwon = FLD_GET(r, 13, 13);
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
+	ths_exit = FLD_GET(r, 7, 0);
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
+	tclk_trail = FLD_GET(r, 15, 8);
+
+	exiths_clk = ths_exit + tclk_trail;
+
+	width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+	bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
+
+	if (!hsa_blanking_mode) {
+		hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					exiths_clk, ddr_clk_pre, ddr_clk_post);
+		hsa_interleave_lp = dsi_compute_interleave_lp(hsa,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					lp_clk_div, dsi_fclk_hsdiv);
+	}
+
+	if (!hfp_blanking_mode) {
+		hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					exiths_clk, ddr_clk_pre, ddr_clk_post);
+		hfp_interleave_lp = dsi_compute_interleave_lp(hfp,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					lp_clk_div, dsi_fclk_hsdiv);
+	}
+
+	if (!hbp_blanking_mode) {
+		hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					exiths_clk, ddr_clk_pre, ddr_clk_post);
+
+		hbp_interleave_lp = dsi_compute_interleave_lp(hbp,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					lp_clk_div, dsi_fclk_hsdiv);
+	}
+
+	if (!blanking_mode) {
+		bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					exiths_clk, ddr_clk_pre, ddr_clk_post);
+
+		bl_interleave_lp = dsi_compute_interleave_lp(bllp,
+					enter_hs_mode_lat, exit_hs_mode_lat,
+					lp_clk_div, dsi_fclk_hsdiv);
+	}
+
+	DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n",
+		hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs,
+		bl_interleave_hs);
+
+	DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n",
+		hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp,
+		bl_interleave_lp);
+
+	r = dsi_read_reg(dsidev, DSI_VM_TIMING4);
+	r = FLD_MOD(r, hsa_interleave_hs, 23, 16);
+	r = FLD_MOD(r, hfp_interleave_hs, 15, 8);
+	r = FLD_MOD(r, hbp_interleave_hs, 7, 0);
+	dsi_write_reg(dsidev, DSI_VM_TIMING4, r);
+
+	r = dsi_read_reg(dsidev, DSI_VM_TIMING5);
+	r = FLD_MOD(r, hsa_interleave_lp, 23, 16);
+	r = FLD_MOD(r, hfp_interleave_lp, 15, 8);
+	r = FLD_MOD(r, hbp_interleave_lp, 7, 0);
+	dsi_write_reg(dsidev, DSI_VM_TIMING5, r);
+
+	r = dsi_read_reg(dsidev, DSI_VM_TIMING6);
+	r = FLD_MOD(r, bl_interleave_hs, 31, 15);
+	r = FLD_MOD(r, bl_interleave_lp, 16, 0);
+	dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
+}
+
+static int dsi_proto_config(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u32 r;
+	int buswidth = 0;
+
+	dsi_config_tx_fifo(dsidev, DSI_FIFO_SIZE_32,
+			DSI_FIFO_SIZE_32,
+			DSI_FIFO_SIZE_32,
+			DSI_FIFO_SIZE_32);
+
+	dsi_config_rx_fifo(dsidev, DSI_FIFO_SIZE_32,
+			DSI_FIFO_SIZE_32,
+			DSI_FIFO_SIZE_32,
+			DSI_FIFO_SIZE_32);
+
+	/* XXX what values for the timeouts? */
+	dsi_set_stop_state_counter(dsidev, 0x1000, false, false);
+	dsi_set_ta_timeout(dsidev, 0x1fff, true, true);
+	dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
+	dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
+
+	switch (dsi_get_pixel_size(dsi->pix_fmt)) {
+	case 16:
+		buswidth = 0;
+		break;
+	case 18:
+		buswidth = 1;
+		break;
+	case 24:
+		buswidth = 2;
+		break;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+
+	r = dsi_read_reg(dsidev, DSI_CTRL);
+	r = FLD_MOD(r, 1, 1, 1);	/* CS_RX_EN */
+	r = FLD_MOD(r, 1, 2, 2);	/* ECC_RX_EN */
+	r = FLD_MOD(r, 1, 3, 3);	/* TX_FIFO_ARBITRATION */
+	r = FLD_MOD(r, 1, 4, 4);	/* VP_CLK_RATIO, always 1, see errata*/
+	r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
+	r = FLD_MOD(r, 0, 8, 8);	/* VP_CLK_POL */
+	r = FLD_MOD(r, 1, 14, 14);	/* TRIGGER_RESET_MODE */
+	r = FLD_MOD(r, 1, 19, 19);	/* EOT_ENABLE */
+	if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
+		r = FLD_MOD(r, 1, 24, 24);	/* DCS_CMD_ENABLE */
+		/* DCS_CMD_CODE, 1=start, 0=continue */
+		r = FLD_MOD(r, 0, 25, 25);
+	}
+
+	dsi_write_reg(dsidev, DSI_CTRL, r);
+
+	dsi_config_vp_num_line_buffers(dsidev);
+
+	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		dsi_config_vp_sync_events(dsidev);
+		dsi_config_blanking_modes(dsidev);
+		dsi_config_cmd_mode_interleaving(dsidev);
+	}
+
+	dsi_vc_initial_config(dsidev, 0);
+	dsi_vc_initial_config(dsidev, 1);
+	dsi_vc_initial_config(dsidev, 2);
+	dsi_vc_initial_config(dsidev, 3);
+
+	return 0;
+}
+
+static void dsi_proto_timings(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
+	unsigned tclk_pre, tclk_post;
+	unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
+	unsigned ths_trail, ths_exit;
+	unsigned ddr_clk_pre, ddr_clk_post;
+	unsigned enter_hs_mode_lat, exit_hs_mode_lat;
+	unsigned ths_eot;
+	int ndl = dsi->num_lanes_used - 1;
+	u32 r;
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
+	ths_prepare = FLD_GET(r, 31, 24);
+	ths_prepare_ths_zero = FLD_GET(r, 23, 16);
+	ths_zero = ths_prepare_ths_zero - ths_prepare;
+	ths_trail = FLD_GET(r, 15, 8);
+	ths_exit = FLD_GET(r, 7, 0);
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
+	tlpx = FLD_GET(r, 20, 16) * 2;
+	tclk_trail = FLD_GET(r, 15, 8);
+	tclk_zero = FLD_GET(r, 7, 0);
+
+	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
+	tclk_prepare = FLD_GET(r, 7, 0);
+
+	/* min 8*UI */
+	tclk_pre = 20;
+	/* min 60ns + 52*UI */
+	tclk_post = ns2ddr(dsidev, 60) + 26;
+
+	ths_eot = DIV_ROUND_UP(4, ndl);
+
+	ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
+			4);
+	ddr_clk_post = DIV_ROUND_UP(tclk_post + ths_trail, 4) + ths_eot;
+
+	BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
+	BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
+
+	r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
+	r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+	r = FLD_MOD(r, ddr_clk_post, 7, 0);
+	dsi_write_reg(dsidev, DSI_CLK_TIMING, r);
+
+	DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
+			ddr_clk_pre,
+			ddr_clk_post);
+
+	enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
+		DIV_ROUND_UP(ths_prepare, 4) +
+		DIV_ROUND_UP(ths_zero + 3, 4);
+
+	exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
+
+	r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
+		FLD_VAL(exit_hs_mode_lat, 15, 0);
+	dsi_write_reg(dsidev, DSI_VM_TIMING7, r);
+
+	DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
+			enter_hs_mode_lat, exit_hs_mode_lat);
+
+	 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		/* TODO: Implement a video mode check_timings function */
+		int hsa = dsi->vm_timings.hsa;
+		int hfp = dsi->vm_timings.hfp;
+		int hbp = dsi->vm_timings.hbp;
+		int vsa = dsi->vm_timings.vsa;
+		int vfp = dsi->vm_timings.vfp;
+		int vbp = dsi->vm_timings.vbp;
+		int window_sync = dsi->vm_timings.window_sync;
+		bool hsync_end;
+		struct omap_video_timings *timings = &dsi->timings;
+		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
+		int tl, t_he, width_bytes;
+
+		hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE;
+		t_he = hsync_end ?
+			((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
+
+		width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+
+		/* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
+		tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
+			DIV_ROUND_UP(width_bytes + 6, ndl) + hbp;
+
+		DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
+			hfp, hsync_end ? hsa : 0, tl);
+		DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
+			vsa, timings->y_res);
+
+		r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
+		r = FLD_MOD(r, hbp, 11, 0);	/* HBP */
+		r = FLD_MOD(r, hfp, 23, 12);	/* HFP */
+		r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24);	/* HSA */
+		dsi_write_reg(dsidev, DSI_VM_TIMING1, r);
+
+		r = dsi_read_reg(dsidev, DSI_VM_TIMING2);
+		r = FLD_MOD(r, vbp, 7, 0);	/* VBP */
+		r = FLD_MOD(r, vfp, 15, 8);	/* VFP */
+		r = FLD_MOD(r, vsa, 23, 16);	/* VSA */
+		r = FLD_MOD(r, window_sync, 27, 24);	/* WINDOW_SYNC */
+		dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
+
+		r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
+		r = FLD_MOD(r, timings->y_res, 14, 0);	/* VACT */
+		r = FLD_MOD(r, tl, 31, 16);		/* TL */
+		dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
+	}
+}
+
+static int dsi_configure_pins(struct omap_dss_device *dssdev,
+		const struct omap_dsi_pin_config *pin_cfg)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int num_pins;
+	const int *pins;
+	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
+	int num_lanes;
+	int i;
+
+	static const enum dsi_lane_function functions[] = {
+		DSI_LANE_CLK,
+		DSI_LANE_DATA1,
+		DSI_LANE_DATA2,
+		DSI_LANE_DATA3,
+		DSI_LANE_DATA4,
+	};
+
+	num_pins = pin_cfg->num_pins;
+	pins = pin_cfg->pins;
+
+	if (num_pins < 4 || num_pins > dsi->num_lanes_supported * 2
+			|| num_pins % 2 != 0)
+		return -EINVAL;
+
+	for (i = 0; i < DSI_MAX_NR_LANES; ++i)
+		lanes[i].function = DSI_LANE_UNUSED;
+
+	num_lanes = 0;
+
+	for (i = 0; i < num_pins; i += 2) {
+		u8 lane, pol;
+		int dx, dy;
+
+		dx = pins[i];
+		dy = pins[i + 1];
+
+		if (dx < 0 || dx >= dsi->num_lanes_supported * 2)
+			return -EINVAL;
+
+		if (dy < 0 || dy >= dsi->num_lanes_supported * 2)
+			return -EINVAL;
+
+		if (dx & 1) {
+			if (dy != dx - 1)
+				return -EINVAL;
+			pol = 1;
+		} else {
+			if (dy != dx + 1)
+				return -EINVAL;
+			pol = 0;
+		}
+
+		lane = dx / 2;
+
+		lanes[lane].function = functions[i / 2];
+		lanes[lane].polarity = pol;
+		num_lanes++;
+	}
+
+	memcpy(dsi->lanes, lanes, sizeof(dsi->lanes));
+	dsi->num_lanes_used = num_lanes;
+
+	return 0;
+}
+
+static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct omap_overlay_manager *mgr = dsi->output.manager;
+	int bpp = dsi_get_pixel_size(dsi->pix_fmt);
+	struct omap_dss_device *out = &dsi->output;
+	u8 data_type;
+	u16 word_count;
+	int r;
+
+	if (out == NULL || out->manager == NULL) {
+		DSSERR("failed to enable display: no output/manager\n");
+		return -ENODEV;
+	}
+
+	r = dsi_display_init_dispc(dsidev, mgr);
+	if (r)
+		goto err_init_dispc;
+
+	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		switch (dsi->pix_fmt) {
+		case OMAP_DSS_DSI_FMT_RGB888:
+			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+			break;
+		case OMAP_DSS_DSI_FMT_RGB666:
+			data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+			break;
+		case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+			break;
+		case OMAP_DSS_DSI_FMT_RGB565:
+			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+			break;
+		default:
+			r = -EINVAL;
+			goto err_pix_fmt;
+		}
+
+		dsi_if_enable(dsidev, false);
+		dsi_vc_enable(dsidev, channel, false);
+
+		/* MODE, 1 = video mode */
+		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
+
+		word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
+
+		dsi_vc_write_long_header(dsidev, channel, data_type,
+				word_count, 0);
+
+		dsi_vc_enable(dsidev, channel, true);
+		dsi_if_enable(dsidev, true);
+	}
+
+	r = dss_mgr_enable(mgr);
+	if (r)
+		goto err_mgr_enable;
+
+	return 0;
+
+err_mgr_enable:
+	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		dsi_if_enable(dsidev, false);
+		dsi_vc_enable(dsidev, channel, false);
+	}
+err_pix_fmt:
+	dsi_display_uninit_dispc(dsidev, mgr);
+err_init_dispc:
+	return r;
+}
+
+static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct omap_overlay_manager *mgr = dsi->output.manager;
+
+	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+		dsi_if_enable(dsidev, false);
+		dsi_vc_enable(dsidev, channel, false);
+
+		/* MODE, 0 = command mode */
+		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
+
+		dsi_vc_enable(dsidev, channel, true);
+		dsi_if_enable(dsidev, true);
+	}
+
+	dss_mgr_disable(mgr);
+
+	dsi_display_uninit_dispc(dsidev, mgr);
+}
+
+static void dsi_update_screen_dispc(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct omap_overlay_manager *mgr = dsi->output.manager;
+	unsigned bytespp;
+	unsigned bytespl;
+	unsigned bytespf;
+	unsigned total_len;
+	unsigned packet_payload;
+	unsigned packet_len;
+	u32 l;
+	int r;
+	const unsigned channel = dsi->update_channel;
+	const unsigned line_buf_size = dsi->line_buffer_size;
+	u16 w = dsi->timings.x_res;
+	u16 h = dsi->timings.y_res;
+
+	DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
+
+	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
+
+	bytespp	= dsi_get_pixel_size(dsi->pix_fmt) / 8;
+	bytespl = w * bytespp;
+	bytespf = bytespl * h;
+
+	/* NOTE: packet_payload has to be equal to N * bytespl, where N is
+	 * number of lines in a packet.  See errata about VP_CLK_RATIO */
+
+	if (bytespf < line_buf_size)
+		packet_payload = bytespf;
+	else
+		packet_payload = (line_buf_size) / bytespl * bytespl;
+
+	packet_len = packet_payload + 1;	/* 1 byte for DCS cmd */
+	total_len = (bytespf / packet_payload) * packet_len;
+
+	if (bytespf % packet_payload)
+		total_len += (bytespf % packet_payload) + 1;
+
+	l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
+	dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
+
+	dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
+		packet_len, 0);
+
+	if (dsi->te_enabled)
+		l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
+	else
+		l = FLD_MOD(l, 1, 31, 31); /* TE_START */
+	dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
+
+	/* We put SIDLEMODE to no-idle for the duration of the transfer,
+	 * because DSS interrupts are not capable of waking up the CPU and the
+	 * framedone interrupt could be delayed for quite a long time. I think
+	 * the same goes for any DSS interrupts, but for some reason I have not
+	 * seen the problem anywhere else than here.
+	 */
+	dispc_disable_sidle();
+
+	dsi_perf_mark_start(dsidev);
+
+	r = schedule_delayed_work(&dsi->framedone_timeout_work,
+		msecs_to_jiffies(250));
+	BUG_ON(r == 0);
+
+	dss_mgr_set_timings(mgr, &dsi->timings);
+
+	dss_mgr_start_update(mgr);
+
+	if (dsi->te_enabled) {
+		/* disable LP_RX_TO, so that we can receive TE.  Time to wait
+		 * for TE is longer than the timer allows */
+		REG_FLD_MOD(dsidev, DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+
+		dsi_vc_send_bta(dsidev, channel);
+
+#ifdef DSI_CATCH_MISSING_TE
+		mod_timer(&dsi->te_timer, jiffies + msecs_to_jiffies(250));
+#endif
+	}
+}
+
+#ifdef DSI_CATCH_MISSING_TE
+static void dsi_te_timeout(unsigned long arg)
+{
+	DSSERR("TE not received for 250ms!\n");
+}
+#endif
+
+static void dsi_handle_framedone(struct platform_device *dsidev, int error)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	/* SIDLEMODE back to smart-idle */
+	dispc_enable_sidle();
+
+	if (dsi->te_enabled) {
+		/* enable LP_RX_TO again after the TE */
+		REG_FLD_MOD(dsidev, DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
+	}
+
+	dsi->framedone_callback(error, dsi->framedone_data);
+
+	if (!error)
+		dsi_perf_show(dsidev, "DISPC");
+}
+
+static void dsi_framedone_timeout_work_callback(struct work_struct *work)
+{
+	struct dsi_data *dsi = container_of(work, struct dsi_data,
+			framedone_timeout_work.work);
+	/* XXX While extremely unlikely, we could get FRAMEDONE interrupt after
+	 * 250ms which would conflict with this timeout work. What should be
+	 * done is first cancel the transfer on the HW, and then cancel the
+	 * possibly scheduled framedone work. However, cancelling the transfer
+	 * on the HW is buggy, and would probably require resetting the whole
+	 * DSI */
+
+	DSSERR("Framedone not received for 250ms!\n");
+
+	dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
+}
+
+static void dsi_framedone_irq_callback(void *data)
+{
+	struct platform_device *dsidev = (struct platform_device *) data;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	/* Note: We get FRAMEDONE when DISPC has finished sending pixels and
+	 * turns itself off. However, DSI still has the pixels in its buffers,
+	 * and is sending the data.
+	 */
+
+	cancel_delayed_work(&dsi->framedone_timeout_work);
+
+	dsi_handle_framedone(dsidev, 0);
+}
+
+static int dsi_update(struct omap_dss_device *dssdev, int channel,
+		void (*callback)(int, void *), void *data)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u16 dw, dh;
+
+	dsi_perf_mark_setup(dsidev);
+
+	dsi->update_channel = channel;
+
+	dsi->framedone_callback = callback;
+	dsi->framedone_data = data;
+
+	dw = dsi->timings.x_res;
+	dh = dsi->timings.y_res;
+
+#ifdef DSI_PERF_MEASURE
+	dsi->update_bytes = dw * dh *
+		dsi_get_pixel_size(dsi->pix_fmt) / 8;
+#endif
+	dsi_update_screen_dispc(dsidev);
+
+	return 0;
+}
+
+/* Display funcs */
+
+static int dsi_configure_dispc_clocks(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dispc_clock_info dispc_cinfo;
+	int r;
+	unsigned long fck;
+
+	fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+
+	dispc_cinfo.lck_div = dsi->user_dispc_cinfo.lck_div;
+	dispc_cinfo.pck_div = dsi->user_dispc_cinfo.pck_div;
+
+	r = dispc_calc_clock_rates(fck, &dispc_cinfo);
+	if (r) {
+		DSSERR("Failed to calc dispc clocks\n");
+		return r;
+	}
+
+	dsi->mgr_config.clock_info = dispc_cinfo;
+
+	return 0;
+}
+
+static int dsi_display_init_dispc(struct platform_device *dsidev,
+		struct omap_overlay_manager *mgr)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r;
+
+	dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
+
+	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
+		r = dss_mgr_register_framedone_handler(mgr,
+				dsi_framedone_irq_callback, dsidev);
+		if (r) {
+			DSSERR("can't register FRAMEDONE handler\n");
+			goto err;
+		}
+
+		dsi->mgr_config.stallmode = true;
+		dsi->mgr_config.fifohandcheck = true;
+	} else {
+		dsi->mgr_config.stallmode = false;
+		dsi->mgr_config.fifohandcheck = false;
+	}
+
+	/*
+	 * override interlace, logic level and edge related parameters in
+	 * omap_video_timings with default values
+	 */
+	dsi->timings.interlace = false;
+	dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+	dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+
+	dss_mgr_set_timings(mgr, &dsi->timings);
+
+	r = dsi_configure_dispc_clocks(dsidev);
+	if (r)
+		goto err1;
+
+	dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
+	dsi->mgr_config.video_port_width =
+			dsi_get_pixel_size(dsi->pix_fmt);
+	dsi->mgr_config.lcden_sig_polarity = 0;
+
+	dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);
+
+	return 0;
+err1:
+	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
+		dss_mgr_unregister_framedone_handler(mgr,
+				dsi_framedone_irq_callback, dsidev);
+err:
+	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
+	return r;
+}
+
+static void dsi_display_uninit_dispc(struct platform_device *dsidev,
+		struct omap_overlay_manager *mgr)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
+		dss_mgr_unregister_framedone_handler(mgr,
+				dsi_framedone_irq_callback, dsidev);
+
+	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
+}
+
+static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clock_info cinfo;
+	int r;
+
+	cinfo = dsi->user_dsi_cinfo;
+
+	r = dsi_calc_clock_rates(dsidev, &cinfo);
+	if (r) {
+		DSSERR("Failed to calc dsi clocks\n");
+		return r;
+	}
+
+	r = dsi_pll_set_clock_div(dsidev, &cinfo);
+	if (r) {
+		DSSERR("Failed to set dsi clocks\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static int dsi_display_init_dsi(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r;
+
+	r = dsi_pll_init(dsidev, true, true);
+	if (r)
+		goto err0;
+
+	r = dsi_configure_dsi_clocks(dsidev);
+	if (r)
+		goto err1;
+
+	dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
+
+	DSSDBG("PLL OK\n");
+
+	r = dsi_cio_init(dsidev);
+	if (r)
+		goto err2;
+
+	_dsi_print_reset_status(dsidev);
+
+	dsi_proto_timings(dsidev);
+	dsi_set_lp_clk_divisor(dsidev);
+
+	if (1)
+		_dsi_print_reset_status(dsidev);
+
+	r = dsi_proto_config(dsidev);
+	if (r)
+		goto err3;
+
+	/* enable interface */
+	dsi_vc_enable(dsidev, 0, 1);
+	dsi_vc_enable(dsidev, 1, 1);
+	dsi_vc_enable(dsidev, 2, 1);
+	dsi_vc_enable(dsidev, 3, 1);
+	dsi_if_enable(dsidev, 1);
+	dsi_force_tx_stop_mode_io(dsidev);
+
+	return 0;
+err3:
+	dsi_cio_uninit(dsidev);
+err2:
+	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
+err1:
+	dsi_pll_uninit(dsidev, true);
+err0:
+	return r;
+}
+
+static void dsi_display_uninit_dsi(struct platform_device *dsidev,
+		bool disconnect_lanes, bool enter_ulps)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (enter_ulps && !dsi->ulps_enabled)
+		dsi_enter_ulps(dsidev);
+
+	/* disable interface */
+	dsi_if_enable(dsidev, 0);
+	dsi_vc_enable(dsidev, 0, 0);
+	dsi_vc_enable(dsidev, 1, 0);
+	dsi_vc_enable(dsidev, 2, 0);
+	dsi_vc_enable(dsidev, 3, 0);
+
+	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
+	dsi_cio_uninit(dsidev);
+	dsi_pll_uninit(dsidev, disconnect_lanes);
+}
+
+static int dsi_display_enable(struct omap_dss_device *dssdev)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int r = 0;
+
+	DSSDBG("dsi_display_enable\n");
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	mutex_lock(&dsi->lock);
+
+	r = dsi_runtime_get(dsidev);
+	if (r)
+		goto err_get_dsi;
+
+	dsi_enable_pll_clock(dsidev, 1);
+
+	_dsi_initialize_irq(dsidev);
+
+	r = dsi_display_init_dsi(dsidev);
+	if (r)
+		goto err_init_dsi;
+
+	mutex_unlock(&dsi->lock);
+
+	return 0;
+
+err_init_dsi:
+	dsi_enable_pll_clock(dsidev, 0);
+	dsi_runtime_put(dsidev);
+err_get_dsi:
+	mutex_unlock(&dsi->lock);
+	DSSDBG("dsi_display_enable FAILED\n");
+	return r;
+}
+
+static void dsi_display_disable(struct omap_dss_device *dssdev,
+		bool disconnect_lanes, bool enter_ulps)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	DSSDBG("dsi_display_disable\n");
+
+	WARN_ON(!dsi_bus_is_locked(dsidev));
+
+	mutex_lock(&dsi->lock);
+
+	dsi_sync_vc(dsidev, 0);
+	dsi_sync_vc(dsidev, 1);
+	dsi_sync_vc(dsidev, 2);
+	dsi_sync_vc(dsidev, 3);
+
+	dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps);
+
+	dsi_runtime_put(dsidev);
+	dsi_enable_pll_clock(dsidev, 0);
+
+	mutex_unlock(&dsi->lock);
+}
+
+static int dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	dsi->te_enabled = enable;
+	return 0;
+}
+
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+static void print_dsi_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	unsigned long byteclk = t->hsclk / 4;
+	int bl, wc, pps, tot;
+
+	wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
+	pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
+	bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
+	tot = bl + pps;
+
+#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
+
+	pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			byteclk,
+			t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
+			bl, pps, tot,
+			TO_DSI_T(t->hss),
+			TO_DSI_T(t->hsa),
+			TO_DSI_T(t->hse),
+			TO_DSI_T(t->hbp),
+			TO_DSI_T(pps),
+			TO_DSI_T(t->hfp),
+
+			TO_DSI_T(bl),
+			TO_DSI_T(pps),
+
+			TO_DSI_T(tot));
+#undef TO_DSI_T
+}
+
+static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
+{
+	unsigned long pck = t->pixelclock;
+	int hact, bl, tot;
+
+	hact = t->x_res;
+	bl = t->hsw + t->hbp + t->hfp;
+	tot = hact + bl;
+
+#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
+
+	pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			pck,
+			t->hsw, t->hbp, hact, t->hfp,
+			bl, hact, tot,
+			TO_DISPC_T(t->hsw),
+			TO_DISPC_T(t->hbp),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(t->hfp),
+			TO_DISPC_T(bl),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(tot));
+#undef TO_DISPC_T
+}
+
+/* note: this is not quite accurate */
+static void print_dsi_dispc_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	struct omap_video_timings vm = { 0 };
+	unsigned long byteclk = t->hsclk / 4;
+	unsigned long pck;
+	u64 dsi_tput;
+	int dsi_hact, dsi_htot;
+
+	dsi_tput = (u64)byteclk * t->ndl * 8;
+	pck = (u32)div64_u64(dsi_tput, t->bitspp);
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
+	dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
+
+	vm.pixelclock = pck;
+	vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
+	vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
+	vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
+	vm.x_res = t->hact;
+
+	print_dispc_vm(str, &vm);
+}
+#endif /* PRINT_VERBOSE_VM_TIMINGS */
+
+static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+	struct omap_video_timings *t = &ctx->dispc_vm;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	*t = *ctx->config->timings;
+	t->pixelclock = pck;
+	t->x_res = ctx->config->timings->x_res;
+	t->y_res = ctx->config->timings->y_res;
+	t->hsw = t->hfp = t->hbp = t->vsw = 1;
+	t->vfp = t->vbp = 0;
+
+	return true;
+}
+
+static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
+			dsi_cm_calc_dispc_cb, ctx);
+}
+
+static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_cm_calc_hsdiv_cb, ctx);
+}
+
+static bool dsi_cm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
+{
+	unsigned long clkin;
+	int bitspp, ndl;
+	unsigned long pll_min, pll_max;
+	unsigned long pck, txbyteclk;
+
+	clkin = clk_get_rate(dsi->sys_clk);
+	bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	ndl = dsi->num_lanes_used - 1;
+
+	/*
+	 * Here we should calculate minimum txbyteclk to be able to send the
+	 * frame in time, and also to handle TE. That's not very simple, though,
+	 * especially as we go to LP between each pixel packet due to HW
+	 * "feature". So let's just estimate very roughly and multiply by 1.5.
+	 */
+	pck = cfg->timings->pixelclock;
+	pck = pck * 3 / 2;
+	txbyteclk = pck * bitspp / 8 / ndl;
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+	ctx->req_pck_min = pck;
+	ctx->req_pck_nom = pck;
+	ctx->req_pck_max = pck * 3 / 2;
+	ctx->dsi_cinfo.clkin = clkin;
+
+	pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
+	pll_max = cfg->hs_clk_max * 4;
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_cm_calc_pll_cb, ctx);
+}
+
+static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
+	const struct omap_dss_dsi_config *cfg = ctx->config;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	int ndl = dsi->num_lanes_used - 1;
+	unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
+	unsigned long byteclk = hsclk / 4;
+
+	unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
+	int xres;
+	int panel_htot, panel_hbl; /* pixels */
+	int dispc_htot, dispc_hbl; /* pixels */
+	int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
+	int hfp, hsa, hbp;
+	const struct omap_video_timings *req_vm;
+	struct omap_video_timings *dispc_vm;
+	struct omap_dss_dsi_videomode_timings *dsi_vm;
+	u64 dsi_tput, dispc_tput;
+
+	dsi_tput = (u64)byteclk * ndl * 8;
+
+	req_vm = cfg->timings;
+	req_pck_min = ctx->req_pck_min;
+	req_pck_max = ctx->req_pck_max;
+	req_pck_nom = ctx->req_pck_nom;
+
+	dispc_pck = ctx->dispc_cinfo.pck;
+	dispc_tput = (u64)dispc_pck * bitspp;
+
+	xres = req_vm->x_res;
+
+	panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
+	panel_htot = xres + panel_hbl;
+
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
+
+	/*
+	 * When there are no line buffers, DISPC and DSI must have the
+	 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
+	 */
+	if (dsi->line_buffer_size < xres * bitspp / 8) {
+		if (dispc_tput != dsi_tput)
+			return false;
+	} else {
+		if (dispc_tput < dsi_tput)
+			return false;
+	}
+
+	/* DSI tput must be over the min requirement */
+	if (dsi_tput < (u64)bitspp * req_pck_min)
+		return false;
+
+	/* When non-burst mode, DSI tput must be below max requirement. */
+	if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
+		if (dsi_tput > (u64)bitspp * req_pck_max)
+			return false;
+	}
+
+	hss = DIV_ROUND_UP(4, ndl);
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
+		if (ndl == 3 && req_vm->hsw == 0)
+			hse = 1;
+		else
+			hse = DIV_ROUND_UP(4, ndl);
+	} else {
+		hse = 0;
+	}
+
+	/* DSI htot to match the panel's nominal pck */
+	dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
+
+	/* fail if there would be no time for blanking */
+	if (dsi_htot < hss + hse + dsi_hact)
+		return false;
+
+	/* total DSI blanking needed to achieve panel's TL */
+	dsi_hbl = dsi_htot - dsi_hact;
+
+	/* DISPC htot to match the DSI TL */
+	dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
+
+	/* verify that the DSI and DISPC TLs are the same */
+	if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
+		return false;
+
+	dispc_hbl = dispc_htot - xres;
+
+	/* setup DSI videomode */
+
+	dsi_vm = &ctx->dsi_vm;
+	memset(dsi_vm, 0, sizeof(*dsi_vm));
+
+	dsi_vm->hsclk = hsclk;
+
+	dsi_vm->ndl = ndl;
+	dsi_vm->bitspp = bitspp;
+
+	if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
+		hsa = 0;
+	} else if (ndl == 3 && req_vm->hsw == 0) {
+		hsa = 0;
+	} else {
+		hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
+		hsa = max(hsa - hse, 1);
+	}
+
+	hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
+	hbp = max(hbp, 1);
+
+	hfp = dsi_hbl - (hss + hsa + hse + hbp);
+	if (hfp < 1) {
+		int t;
+		/* we need to take cycles from hbp */
+
+		t = 1 - hfp;
+		hbp = max(hbp - t, 1);
+		hfp = dsi_hbl - (hss + hsa + hse + hbp);
+
+		if (hfp < 1 && hsa > 0) {
+			/* we need to take cycles from hsa */
+			t = 1 - hfp;
+			hsa = max(hsa - t, 1);
+			hfp = dsi_hbl - (hss + hsa + hse + hbp);
+		}
+	}
+
+	if (hfp < 1)
+		return false;
+
+	dsi_vm->hss = hss;
+	dsi_vm->hsa = hsa;
+	dsi_vm->hse = hse;
+	dsi_vm->hbp = hbp;
+	dsi_vm->hact = xres;
+	dsi_vm->hfp = hfp;
+
+	dsi_vm->vsa = req_vm->vsw;
+	dsi_vm->vbp = req_vm->vbp;
+	dsi_vm->vact = req_vm->y_res;
+	dsi_vm->vfp = req_vm->vfp;
+
+	dsi_vm->trans_mode = cfg->trans_mode;
+
+	dsi_vm->blanking_mode = 0;
+	dsi_vm->hsa_blanking_mode = 1;
+	dsi_vm->hfp_blanking_mode = 1;
+	dsi_vm->hbp_blanking_mode = 1;
+
+	dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
+	dsi_vm->window_sync = 4;
+
+	/* setup DISPC videomode */
+
+	dispc_vm = &ctx->dispc_vm;
+	*dispc_vm = *req_vm;
+	dispc_vm->pixelclock = dispc_pck;
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
+		hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
+				req_pck_nom);
+		hsa = max(hsa, 1);
+	} else {
+		hsa = 1;
+	}
+
+	hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
+	hbp = max(hbp, 1);
+
+	hfp = dispc_hbl - hsa - hbp;
+	if (hfp < 1) {
+		int t;
+		/* we need to take cycles from hbp */
+
+		t = 1 - hfp;
+		hbp = max(hbp - t, 1);
+		hfp = dispc_hbl - hsa - hbp;
+
+		if (hfp < 1) {
+			/* we need to take cycles from hsa */
+			t = 1 - hfp;
+			hsa = max(hsa - t, 1);
+			hfp = dispc_hbl - hsa - hbp;
+		}
+	}
+
+	if (hfp < 1)
+		return false;
+
+	dispc_vm->hfp = hfp;
+	dispc_vm->hsw = hsa;
+	dispc_vm->hbp = hbp;
+
+	return true;
+}
+
+
+static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	if (dsi_vm_calc_blanking(ctx) == false)
+		return false;
+
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+	print_dispc_vm("dispc", &ctx->dispc_vm);
+	print_dsi_vm("dsi  ", &ctx->dsi_vm);
+	print_dispc_vm("req  ", ctx->config->timings);
+	print_dsi_dispc_vm("act  ", &ctx->dsi_vm);
+#endif
+
+	return true;
+}
+
+static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+	unsigned long pck_max;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	/*
+	 * In burst mode we can let the dispc pck be arbitrarily high, but it
+	 * limits our scaling abilities. So for now, don't aim too high.
+	 */
+
+	if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
+		pck_max = ctx->req_pck_max + 10000000;
+	else
+		pck_max = ctx->req_pck_max;
+
+	return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
+			dsi_vm_calc_dispc_cb, ctx);
+}
+
+static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_vm_calc_hsdiv_cb, ctx);
+}
+
+static bool dsi_vm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
+{
+	const struct omap_video_timings *t = cfg->timings;
+	unsigned long clkin;
+	unsigned long pll_min;
+	unsigned long pll_max;
+	int ndl = dsi->num_lanes_used - 1;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	unsigned long byteclk_min;
+
+	clkin = clk_get_rate(dsi->sys_clk);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+
+	ctx->dsi_cinfo.clkin = clkin;
+
+	/* these limits should come from the panel driver */
+	ctx->req_pck_min = t->pixelclock - 1000;
+	ctx->req_pck_nom = t->pixelclock;
+	ctx->req_pck_max = t->pixelclock + 1000;
+
+	byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
+	pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
+		pll_max = cfg->hs_clk_max * 4;
+	} else {
+		unsigned long byteclk_max;
+		byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
+				ndl * 8);
+
+		pll_max = byteclk_max * 4 * 4;
+	}
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_vm_calc_pll_cb, ctx);
+}
+
+static int dsi_set_config(struct omap_dss_device *dssdev,
+		const struct omap_dss_dsi_config *config)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clk_calc_ctx ctx;
+	bool ok;
+	int r;
+
+	mutex_lock(&dsi->lock);
+
+	dsi->pix_fmt = config->pixel_format;
+	dsi->mode = config->mode;
+
+	if (config->mode == OMAP_DSS_DSI_VIDEO_MODE)
+		ok = dsi_vm_calc(dsi, config, &ctx);
+	else
+		ok = dsi_cm_calc(dsi, config, &ctx);
+
+	if (!ok) {
+		DSSERR("failed to find suitable DSI clock settings\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
+
+	r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
+			config->lp_clk_max);
+	if (r) {
+		DSSERR("failed to find suitable DSI LP clock settings\n");
+		goto err;
+	}
+
+	dsi->user_dsi_cinfo = ctx.dsi_cinfo;
+	dsi->user_dispc_cinfo = ctx.dispc_cinfo;
+
+	dsi->timings = ctx.dispc_vm;
+	dsi->vm_timings = ctx.dsi_vm;
+
+	mutex_unlock(&dsi->lock);
+
+	return 0;
+err:
+	mutex_unlock(&dsi->lock);
+
+	return r;
+}
+
+/*
+ * Return a hardcoded channel for the DSI output. This should work for
+ * current use cases, but this can be later expanded to either resolve
+ * the channel in some more dynamic manner, or get the channel as a user
+ * parameter.
+ */
+static enum omap_channel dsi_get_channel(int module_id)
+{
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+		DSSWARN("DSI not supported\n");
+		return OMAP_DSS_CHANNEL_LCD;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		return OMAP_DSS_CHANNEL_LCD;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		switch (module_id) {
+		case 0:
+			return OMAP_DSS_CHANNEL_LCD;
+		case 1:
+			return OMAP_DSS_CHANNEL_LCD2;
+		default:
+			DSSWARN("unsupported module id\n");
+			return OMAP_DSS_CHANNEL_LCD;
+		}
+
+	case OMAPDSS_VER_OMAP5:
+		switch (module_id) {
+		case 0:
+			return OMAP_DSS_CHANNEL_LCD;
+		case 1:
+			return OMAP_DSS_CHANNEL_LCD3;
+		default:
+			DSSWARN("unsupported module id\n");
+			return OMAP_DSS_CHANNEL_LCD;
+		}
+
+	default:
+		DSSWARN("unsupported DSS version\n");
+		return OMAP_DSS_CHANNEL_LCD;
+	}
+}
+
+static int dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
+		if (!dsi->vc[i].dssdev) {
+			dsi->vc[i].dssdev = dssdev;
+			*channel = i;
+			return 0;
+		}
+	}
+
+	DSSERR("cannot get VC for display %s", dssdev->name);
+	return -ENOSPC;
+}
+
+static int dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (vc_id < 0 || vc_id > 3) {
+		DSSERR("VC ID out of range\n");
+		return -EINVAL;
+	}
+
+	if (channel < 0 || channel > 3) {
+		DSSERR("Virtual Channel out of range\n");
+		return -EINVAL;
+	}
+
+	if (dsi->vc[channel].dssdev != dssdev) {
+		DSSERR("Virtual Channel not allocated to display %s\n",
+			dssdev->name);
+		return -EINVAL;
+	}
+
+	dsi->vc[channel].vc_id = vc_id;
+
+	return 0;
+}
+
+static void dsi_release_vc(struct omap_dss_device *dssdev, int channel)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if ((channel >= 0 && channel <= 3) &&
+		dsi->vc[channel].dssdev == dssdev) {
+		dsi->vc[channel].dssdev = NULL;
+		dsi->vc[channel].vc_id = 0;
+	}
+}
+
+void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
+{
+	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1)
+		DSSERR("%s (%s) not active\n",
+			dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+			dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
+}
+
+void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
+{
+	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1)
+		DSSERR("%s (%s) not active\n",
+			dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+			dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
+}
+
+static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
+	dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
+	dsi->regm_dispc_max =
+		dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
+	dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
+	dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
+	dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
+	dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
+}
+
+static int dsi_get_clocks(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct clk *clk;
+
+	clk = devm_clk_get(&dsidev->dev, "fck");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get fck\n");
+		return PTR_ERR(clk);
+	}
+
+	dsi->dss_clk = clk;
+
+	clk = devm_clk_get(&dsidev->dev, "sys_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get sys_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	dsi->sys_clk = clk;
+
+	return 0;
+}
+
+static int dsi_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct omap_overlay_manager *mgr;
+	int r;
+
+	r = dsi_regulator_init(dsidev);
+	if (r)
+		return r;
+
+	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
+	if (!mgr)
+		return -ENODEV;
+
+	r = dss_mgr_connect(mgr, dssdev);
+	if (r)
+		return r;
+
+	r = omapdss_output_set_device(dssdev, dst);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dssdev->name);
+		dss_mgr_disconnect(mgr, dssdev);
+		return r;
+	}
+
+	return 0;
+}
+
+static void dsi_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	WARN_ON(dst != dssdev->dst);
+
+	if (dst != dssdev->dst)
+		return;
+
+	omapdss_output_unset_device(dssdev);
+
+	if (dssdev->manager)
+		dss_mgr_disconnect(dssdev->manager, dssdev);
+}
+
+static const struct omapdss_dsi_ops dsi_ops = {
+	.connect = dsi_connect,
+	.disconnect = dsi_disconnect,
+
+	.bus_lock = dsi_bus_lock,
+	.bus_unlock = dsi_bus_unlock,
+
+	.enable = dsi_display_enable,
+	.disable = dsi_display_disable,
+
+	.enable_hs = dsi_vc_enable_hs,
+
+	.configure_pins = dsi_configure_pins,
+	.set_config = dsi_set_config,
+
+	.enable_video_output = dsi_enable_video_output,
+	.disable_video_output = dsi_disable_video_output,
+
+	.update = dsi_update,
+
+	.enable_te = dsi_enable_te,
+
+	.request_vc = dsi_request_vc,
+	.set_vc_id = dsi_set_vc_id,
+	.release_vc = dsi_release_vc,
+
+	.dcs_write = dsi_vc_dcs_write,
+	.dcs_write_nosync = dsi_vc_dcs_write_nosync,
+	.dcs_read = dsi_vc_dcs_read,
+
+	.gen_write = dsi_vc_generic_write,
+	.gen_write_nosync = dsi_vc_generic_write_nosync,
+	.gen_read = dsi_vc_generic_read,
+
+	.bta_sync = dsi_vc_send_bta_sync,
+
+	.set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size,
+};
+
+static void dsi_init_output(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct omap_dss_device *out = &dsi->output;
+
+	out->dev = &dsidev->dev;
+	out->id = dsi->module_id == 0 ?
+			OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+
+	out->output_type = OMAP_DISPLAY_TYPE_DSI;
+	out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
+	out->dispc_channel = dsi_get_channel(dsi->module_id);
+	out->ops.dsi = &dsi_ops;
+	out->owner = THIS_MODULE;
+
+	omapdss_register_output(out);
+}
+
+static void dsi_uninit_output(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct omap_dss_device *out = &dsi->output;
+
+	omapdss_unregister_output(out);
+}
+
+static int dsi_probe_of(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
+	struct property *prop;
+	u32 lane_arr[10];
+	int len, num_pins;
+	int r, i;
+	struct device_node *ep;
+	struct omap_dsi_pin_config pin_cfg;
+
+	ep = omapdss_of_get_first_endpoint(node);
+	if (!ep)
+		return 0;
+
+	prop = of_find_property(ep, "lanes", &len);
+	if (prop == NULL) {
+		dev_err(&pdev->dev, "failed to find lane data\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	num_pins = len / sizeof(u32);
+
+	if (num_pins < 4 || num_pins % 2 != 0 ||
+		num_pins > dsi->num_lanes_supported * 2) {
+		dev_err(&pdev->dev, "bad number of lanes\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins);
+	if (r) {
+		dev_err(&pdev->dev, "failed to read lane data\n");
+		goto err;
+	}
+
+	pin_cfg.num_pins = num_pins;
+	for (i = 0; i < num_pins; ++i)
+		pin_cfg.pins[i] = (int)lane_arr[i];
+
+	r = dsi_configure_pins(&dsi->output, &pin_cfg);
+	if (r) {
+		dev_err(&pdev->dev, "failed to configure pins");
+		goto err;
+	}
+
+	of_node_put(ep);
+
+	return 0;
+
+err:
+	of_node_put(ep);
+	return r;
+}
+
+/* DSI1 HW IP initialisation */
+static int omap_dsihw_probe(struct platform_device *dsidev)
+{
+	u32 rev;
+	int r, i;
+	struct dsi_data *dsi;
+	struct resource *dsi_mem;
+	struct resource *res;
+	struct resource temp_res;
+
+	dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	dsi->pdev = dsidev;
+	dev_set_drvdata(&dsidev->dev, dsi);
+
+	spin_lock_init(&dsi->irq_lock);
+	spin_lock_init(&dsi->errors_lock);
+	dsi->errors = 0;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spin_lock_init(&dsi->irq_stats_lock);
+	dsi->irq_stats.last_reset = jiffies;
+#endif
+
+	mutex_init(&dsi->lock);
+	sema_init(&dsi->bus_lock, 1);
+
+	INIT_DEFERRABLE_WORK(&dsi->framedone_timeout_work,
+			     dsi_framedone_timeout_work_callback);
+
+#ifdef DSI_CATCH_MISSING_TE
+	init_timer(&dsi->te_timer);
+	dsi->te_timer.function = dsi_te_timeout;
+	dsi->te_timer.data = 0;
+#endif
+
+	res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "proto");
+	if (!res) {
+		res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DSSERR("can't get IORESOURCE_MEM DSI\n");
+			return -EINVAL;
+		}
+
+		temp_res.start = res->start;
+		temp_res.end = temp_res.start + DSI_PROTO_SZ - 1;
+		res = &temp_res;
+	}
+
+	dsi_mem = res;
+
+	dsi->proto_base = devm_ioremap(&dsidev->dev, res->start,
+		resource_size(res));
+	if (!dsi->proto_base) {
+		DSSERR("can't ioremap DSI protocol engine\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "phy");
+	if (!res) {
+		res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DSSERR("can't get IORESOURCE_MEM DSI\n");
+			return -EINVAL;
+		}
+
+		temp_res.start = res->start + DSI_PHY_OFFSET;
+		temp_res.end = temp_res.start + DSI_PHY_SZ - 1;
+		res = &temp_res;
+	}
+
+	dsi->phy_base = devm_ioremap(&dsidev->dev, res->start,
+		resource_size(res));
+	if (!dsi->proto_base) {
+		DSSERR("can't ioremap DSI PHY\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "pll");
+	if (!res) {
+		res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DSSERR("can't get IORESOURCE_MEM DSI\n");
+			return -EINVAL;
+		}
+
+		temp_res.start = res->start + DSI_PLL_OFFSET;
+		temp_res.end = temp_res.start + DSI_PLL_SZ - 1;
+		res = &temp_res;
+	}
+
+	dsi->pll_base = devm_ioremap(&dsidev->dev, res->start,
+		resource_size(res));
+	if (!dsi->proto_base) {
+		DSSERR("can't ioremap DSI PLL\n");
+		return -ENOMEM;
+	}
+
+	dsi->irq = platform_get_irq(dsi->pdev, 0);
+	if (dsi->irq < 0) {
+		DSSERR("platform_get_irq failed\n");
+		return -ENODEV;
+	}
+
+	r = devm_request_irq(&dsidev->dev, dsi->irq, omap_dsi_irq_handler,
+			     IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev);
+	if (r < 0) {
+		DSSERR("request_irq failed\n");
+		return r;
+	}
+
+	if (dsidev->dev.of_node) {
+		const struct of_device_id *match;
+		const struct dsi_module_id_data *d;
+
+		match = of_match_node(dsi_of_match, dsidev->dev.of_node);
+		if (!match) {
+			DSSERR("unsupported DSI module\n");
+			return -ENODEV;
+		}
+
+		d = match->data;
+
+		while (d->address != 0 && d->address != dsi_mem->start)
+			d++;
+
+		if (d->address == 0) {
+			DSSERR("unsupported DSI module\n");
+			return -ENODEV;
+		}
+
+		dsi->module_id = d->id;
+	} else {
+		dsi->module_id = dsidev->id;
+	}
+
+	/* DSI VCs initialization */
+	for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
+		dsi->vc[i].source = DSI_VC_SOURCE_L4;
+		dsi->vc[i].dssdev = NULL;
+		dsi->vc[i].vc_id = 0;
+	}
+
+	dsi_calc_clock_param_ranges(dsidev);
+
+	r = dsi_get_clocks(dsidev);
+	if (r)
+		return r;
+
+	pm_runtime_enable(&dsidev->dev);
+
+	r = dsi_runtime_get(dsidev);
+	if (r)
+		goto err_runtime_get;
+
+	rev = dsi_read_reg(dsidev, DSI_REVISION);
+	dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
+	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
+	 * of data to 3 by default */
+	if (dss_has_feature(FEAT_DSI_GNQ))
+		/* NB_DATA_LANES */
+		dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
+	else
+		dsi->num_lanes_supported = 3;
+
+	dsi->line_buffer_size = dsi_get_line_buf_size(dsidev);
+
+	dsi_init_output(dsidev);
+
+	if (dsidev->dev.of_node) {
+		r = dsi_probe_of(dsidev);
+		if (r) {
+			DSSERR("Invalid DSI DT data\n");
+			goto err_probe_of;
+		}
+
+		r = of_platform_populate(dsidev->dev.of_node, NULL, NULL,
+			&dsidev->dev);
+		if (r)
+			DSSERR("Failed to populate DSI child devices: %d\n", r);
+	}
+
+	dsi_runtime_put(dsidev);
+
+	if (dsi->module_id == 0)
+		dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs);
+	else if (dsi->module_id == 1)
+		dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs);
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	if (dsi->module_id == 0)
+		dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs);
+	else if (dsi->module_id == 1)
+		dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs);
+#endif
+
+	return 0;
+
+err_probe_of:
+	dsi_uninit_output(dsidev);
+	dsi_runtime_put(dsidev);
+
+err_runtime_get:
+	pm_runtime_disable(&dsidev->dev);
+	return r;
+}
+
+static int dsi_unregister_child(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	platform_device_unregister(pdev);
+	return 0;
+}
+
+static int __exit omap_dsihw_remove(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	device_for_each_child(&dsidev->dev, NULL, dsi_unregister_child);
+
+	WARN_ON(dsi->scp_clk_refcount > 0);
+
+	dsi_uninit_output(dsidev);
+
+	pm_runtime_disable(&dsidev->dev);
+
+	if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
+		regulator_disable(dsi->vdds_dsi_reg);
+		dsi->vdds_dsi_enabled = false;
+	}
+
+	return 0;
+}
+
+static int dsi_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
+
+	dsi->is_enabled = false;
+	/* ensure the irq handler sees the is_enabled value */
+	smp_wmb();
+	/* wait for current handler to finish before turning the DSI off */
+	synchronize_irq(dsi->irq);
+
+	dispc_runtime_put();
+
+	return 0;
+}
+
+static int dsi_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
+	int r;
+
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
+	dsi->is_enabled = true;
+	/* ensure the irq handler sees the is_enabled value */
+	smp_wmb();
+
+	return 0;
+}
+
+static const struct dev_pm_ops dsi_pm_ops = {
+	.runtime_suspend = dsi_runtime_suspend,
+	.runtime_resume = dsi_runtime_resume,
+};
+
+static const struct dsi_module_id_data dsi_of_data_omap3[] = {
+	{ .address = 0x4804fc00, .id = 0, },
+	{ },
+};
+
+static const struct dsi_module_id_data dsi_of_data_omap4[] = {
+	{ .address = 0x58004000, .id = 0, },
+	{ .address = 0x58005000, .id = 1, },
+	{ },
+};
+
+static const struct of_device_id dsi_of_match[] = {
+	{ .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, },
+	{ .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, },
+	{},
+};
+
+static struct platform_driver omap_dsihw_driver = {
+	.probe		= omap_dsihw_probe,
+	.remove         = __exit_p(omap_dsihw_remove),
+	.driver         = {
+		.name   = "omapdss_dsi",
+		.owner  = THIS_MODULE,
+		.pm	= &dsi_pm_ops,
+		.of_match_table = dsi_of_match,
+	},
+};
+
+int __init dsi_init_platform_driver(void)
+{
+	return platform_driver_register(&omap_dsihw_driver);
+}
+
+void __exit dsi_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omap_dsihw_driver);
+}
diff --git a/drivers/video/fbdev/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/dss/dss-of.c
new file mode 100644
index 000000000000..a4b20aaf6142
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dss-of.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2013 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/seq_file.h>
+
+#include <video/omapdss.h>
+
+struct device_node *
+omapdss_of_get_next_port(const struct device_node *parent,
+			 struct device_node *prev)
+{
+	struct device_node *port = NULL;
+
+	if (!parent)
+		return NULL;
+
+	if (!prev) {
+		struct device_node *ports;
+		/*
+		 * It's the first call, we have to find a port subnode
+		 * within this node or within an optional 'ports' node.
+		 */
+		ports = of_get_child_by_name(parent, "ports");
+		if (ports)
+			parent = ports;
+
+		port = of_get_child_by_name(parent, "port");
+
+		/* release the 'ports' node */
+		of_node_put(ports);
+	} else {
+		struct device_node *ports;
+
+		ports = of_get_parent(prev);
+		if (!ports)
+			return NULL;
+
+		do {
+			port = of_get_next_child(ports, prev);
+			if (!port) {
+				of_node_put(ports);
+				return NULL;
+			}
+			prev = port;
+		} while (of_node_cmp(port->name, "port") != 0);
+	}
+
+	return port;
+}
+EXPORT_SYMBOL_GPL(omapdss_of_get_next_port);
+
+struct device_node *
+omapdss_of_get_next_endpoint(const struct device_node *parent,
+			     struct device_node *prev)
+{
+	struct device_node *ep = NULL;
+
+	if (!parent)
+		return NULL;
+
+	do {
+		ep = of_get_next_child(parent, prev);
+		if (!ep)
+			return NULL;
+		prev = ep;
+	} while (of_node_cmp(ep->name, "endpoint") != 0);
+
+	return ep;
+}
+EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
+
+static struct device_node *
+omapdss_of_get_remote_device_node(const struct device_node *node)
+{
+	struct device_node *np;
+	int i;
+
+	np = of_parse_phandle(node, "remote-endpoint", 0);
+
+	if (!np)
+		return NULL;
+
+	np = of_get_next_parent(np);
+
+	for (i = 0; i < 3 && np; ++i) {
+		struct property *prop;
+
+		prop = of_find_property(np, "compatible", NULL);
+
+		if (prop)
+			return np;
+
+		np = of_get_next_parent(np);
+	}
+
+	return NULL;
+}
+
+struct device_node *
+omapdss_of_get_first_endpoint(const struct device_node *parent)
+{
+	struct device_node *port, *ep;
+
+	port = omapdss_of_get_next_port(parent, NULL);
+
+	if (!port)
+		return NULL;
+
+	ep = omapdss_of_get_next_endpoint(port, NULL);
+
+	of_node_put(port);
+
+	return ep;
+}
+EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint);
+
+struct omap_dss_device *
+omapdss_of_find_source_for_first_ep(struct device_node *node)
+{
+	struct device_node *ep;
+	struct device_node *src_node;
+	struct omap_dss_device *src;
+
+	ep = omapdss_of_get_first_endpoint(node);
+	if (!ep)
+		return ERR_PTR(-EINVAL);
+
+	src_node = omapdss_of_get_remote_device_node(ep);
+
+	of_node_put(ep);
+
+	if (!src_node)
+		return ERR_PTR(-EINVAL);
+
+	src = omap_dss_find_output_by_node(src_node);
+
+	of_node_put(src_node);
+
+	if (!src)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	return src;
+}
+EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep);
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
new file mode 100644
index 000000000000..d55266c0e029
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -0,0 +1,972 @@
+/*
+ * linux/drivers/video/omap2/dss/dss.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DSS"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/gfp.h>
+#include <linux/sizes.h>
+#include <linux/of.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+#define DSS_SZ_REGS			SZ_512
+
+struct dss_reg {
+	u16 idx;
+};
+
+#define DSS_REG(idx)			((const struct dss_reg) { idx })
+
+#define DSS_REVISION			DSS_REG(0x0000)
+#define DSS_SYSCONFIG			DSS_REG(0x0010)
+#define DSS_SYSSTATUS			DSS_REG(0x0014)
+#define DSS_CONTROL			DSS_REG(0x0040)
+#define DSS_SDI_CONTROL			DSS_REG(0x0044)
+#define DSS_PLL_CONTROL			DSS_REG(0x0048)
+#define DSS_SDI_STATUS			DSS_REG(0x005C)
+
+#define REG_GET(idx, start, end) \
+	FLD_GET(dss_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+	dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
+
+static int dss_runtime_get(void);
+static void dss_runtime_put(void);
+
+struct dss_features {
+	u8 fck_div_max;
+	u8 dss_fck_multiplier;
+	const char *parent_clk_name;
+	int (*dpi_select_source)(enum omap_channel channel);
+};
+
+static struct {
+	struct platform_device *pdev;
+	void __iomem    *base;
+
+	struct clk	*parent_clk;
+	struct clk	*dss_clk;
+	unsigned long	dss_clk_rate;
+
+	unsigned long	cache_req_pck;
+	unsigned long	cache_prate;
+	struct dispc_clock_info cache_dispc_cinfo;
+
+	enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
+	enum omap_dss_clk_source dispc_clk_source;
+	enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
+
+	bool		ctx_valid;
+	u32		ctx[DSS_SZ_REGS / sizeof(u32)];
+
+	const struct dss_features *feat;
+} dss;
+
+static const char * const dss_generic_clk_source_names[] = {
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC",
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI_PLL_HSDIV_DSI",
+	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DSI_PLL2_HSDIV_DISPC",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DSI_PLL2_HSDIV_DSI",
+};
+
+static inline void dss_write_reg(const struct dss_reg idx, u32 val)
+{
+	__raw_writel(val, dss.base + idx.idx);
+}
+
+static inline u32 dss_read_reg(const struct dss_reg idx)
+{
+	return __raw_readl(dss.base + idx.idx);
+}
+
+#define SR(reg) \
+	dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
+#define RR(reg) \
+	dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
+
+static void dss_save_context(void)
+{
+	DSSDBG("dss_save_context\n");
+
+	SR(CONTROL);
+
+	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+			OMAP_DISPLAY_TYPE_SDI) {
+		SR(SDI_CONTROL);
+		SR(PLL_CONTROL);
+	}
+
+	dss.ctx_valid = true;
+
+	DSSDBG("context saved\n");
+}
+
+static void dss_restore_context(void)
+{
+	DSSDBG("dss_restore_context\n");
+
+	if (!dss.ctx_valid)
+		return;
+
+	RR(CONTROL);
+
+	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+			OMAP_DISPLAY_TYPE_SDI) {
+		RR(SDI_CONTROL);
+		RR(PLL_CONTROL);
+	}
+
+	DSSDBG("context restored\n");
+}
+
+#undef SR
+#undef RR
+
+void dss_sdi_init(int datapairs)
+{
+	u32 l;
+
+	BUG_ON(datapairs > 3 || datapairs < 1);
+
+	l = dss_read_reg(DSS_SDI_CONTROL);
+	l = FLD_MOD(l, 0xf, 19, 15);		/* SDI_PDIV */
+	l = FLD_MOD(l, datapairs-1, 3, 2);	/* SDI_PRSEL */
+	l = FLD_MOD(l, 2, 1, 0);		/* SDI_BWSEL */
+	dss_write_reg(DSS_SDI_CONTROL, l);
+
+	l = dss_read_reg(DSS_PLL_CONTROL);
+	l = FLD_MOD(l, 0x7, 25, 22);	/* SDI_PLL_FREQSEL */
+	l = FLD_MOD(l, 0xb, 16, 11);	/* SDI_PLL_REGN */
+	l = FLD_MOD(l, 0xb4, 10, 1);	/* SDI_PLL_REGM */
+	dss_write_reg(DSS_PLL_CONTROL, l);
+}
+
+int dss_sdi_enable(void)
+{
+	unsigned long timeout;
+
+	dispc_pck_free_enable(1);
+
+	/* Reset SDI PLL */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
+	udelay(1);	/* wait 2x PCLK */
+
+	/* Lock SDI PLL */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
+
+	/* Waiting for PLL lock request to complete */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
+		if (time_after_eq(jiffies, timeout)) {
+			DSSERR("PLL lock request timed out\n");
+			goto err1;
+		}
+	}
+
+	/* Clearing PLL_GO bit */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
+
+	/* Waiting for PLL to lock */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
+		if (time_after_eq(jiffies, timeout)) {
+			DSSERR("PLL lock timed out\n");
+			goto err1;
+		}
+	}
+
+	dispc_lcd_enable_signal(1);
+
+	/* Waiting for SDI reset to complete */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
+		if (time_after_eq(jiffies, timeout)) {
+			DSSERR("SDI reset timed out\n");
+			goto err2;
+		}
+	}
+
+	return 0;
+
+ err2:
+	dispc_lcd_enable_signal(0);
+ err1:
+	/* Reset SDI PLL */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
+
+	dispc_pck_free_enable(0);
+
+	return -ETIMEDOUT;
+}
+
+void dss_sdi_disable(void)
+{
+	dispc_lcd_enable_signal(0);
+
+	dispc_pck_free_enable(0);
+
+	/* Reset SDI PLL */
+	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
+}
+
+const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
+{
+	return dss_generic_clk_source_names[clk_src];
+}
+
+void dss_dump_clocks(struct seq_file *s)
+{
+	const char *fclk_name, *fclk_real_name;
+	unsigned long fclk_rate;
+
+	if (dss_runtime_get())
+		return;
+
+	seq_printf(s, "- DSS -\n");
+
+	fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
+	fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
+	fclk_rate = clk_get_rate(dss.dss_clk);
+
+	seq_printf(s, "%s (%s) = %lu\n",
+			fclk_name, fclk_real_name,
+			fclk_rate);
+
+	dss_runtime_put();
+}
+
+static void dss_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
+
+	if (dss_runtime_get())
+		return;
+
+	DUMPREG(DSS_REVISION);
+	DUMPREG(DSS_SYSCONFIG);
+	DUMPREG(DSS_SYSSTATUS);
+	DUMPREG(DSS_CONTROL);
+
+	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+			OMAP_DISPLAY_TYPE_SDI) {
+		DUMPREG(DSS_SDI_CONTROL);
+		DUMPREG(DSS_PLL_CONTROL);
+		DUMPREG(DSS_SDI_STATUS);
+	}
+
+	dss_runtime_put();
+#undef DUMPREG
+}
+
+static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
+{
+	struct platform_device *dsidev;
+	int b;
+	u8 start, end;
+
+	switch (clk_src) {
+	case OMAP_DSS_CLK_SRC_FCK:
+		b = 0;
+		break;
+	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+		b = 1;
+		dsidev = dsi_get_dsidev_from_id(0);
+		dsi_wait_pll_hsdiv_dispc_active(dsidev);
+		break;
+	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+		b = 2;
+		dsidev = dsi_get_dsidev_from_id(1);
+		dsi_wait_pll_hsdiv_dispc_active(dsidev);
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
+
+	REG_FLD_MOD(DSS_CONTROL, b, start, end);	/* DISPC_CLK_SWITCH */
+
+	dss.dispc_clk_source = clk_src;
+}
+
+void dss_select_dsi_clk_source(int dsi_module,
+		enum omap_dss_clk_source clk_src)
+{
+	struct platform_device *dsidev;
+	int b, pos;
+
+	switch (clk_src) {
+	case OMAP_DSS_CLK_SRC_FCK:
+		b = 0;
+		break;
+	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
+		BUG_ON(dsi_module != 0);
+		b = 1;
+		dsidev = dsi_get_dsidev_from_id(0);
+		dsi_wait_pll_hsdiv_dsi_active(dsidev);
+		break;
+	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
+		BUG_ON(dsi_module != 1);
+		b = 1;
+		dsidev = dsi_get_dsidev_from_id(1);
+		dsi_wait_pll_hsdiv_dsi_active(dsidev);
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	pos = dsi_module == 0 ? 1 : 10;
+	REG_FLD_MOD(DSS_CONTROL, b, pos, pos);	/* DSIx_CLK_SWITCH */
+
+	dss.dsi_clk_source[dsi_module] = clk_src;
+}
+
+void dss_select_lcd_clk_source(enum omap_channel channel,
+		enum omap_dss_clk_source clk_src)
+{
+	struct platform_device *dsidev;
+	int b, ix, pos;
+
+	if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
+		dss_select_dispc_clk_source(clk_src);
+		return;
+	}
+
+	switch (clk_src) {
+	case OMAP_DSS_CLK_SRC_FCK:
+		b = 0;
+		break;
+	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+		BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
+		b = 1;
+		dsidev = dsi_get_dsidev_from_id(0);
+		dsi_wait_pll_hsdiv_dispc_active(dsidev);
+		break;
+	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+		BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
+		       channel != OMAP_DSS_CHANNEL_LCD3);
+		b = 1;
+		dsidev = dsi_get_dsidev_from_id(1);
+		dsi_wait_pll_hsdiv_dispc_active(dsidev);
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
+	     (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
+	REG_FLD_MOD(DSS_CONTROL, b, pos, pos);	/* LCDx_CLK_SWITCH */
+
+	ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
+	    (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
+	dss.lcd_clk_source[ix] = clk_src;
+}
+
+enum omap_dss_clk_source dss_get_dispc_clk_source(void)
+{
+	return dss.dispc_clk_source;
+}
+
+enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
+{
+	return dss.dsi_clk_source[dsi_module];
+}
+
+enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
+{
+	if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
+		int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
+			(channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
+		return dss.lcd_clk_source[ix];
+	} else {
+		/* LCD_CLK source is the same as DISPC_FCLK source for
+		 * OMAP2 and OMAP3 */
+		return dss.dispc_clk_source;
+	}
+}
+
+bool dss_div_calc(unsigned long pck, unsigned long fck_min,
+		dss_div_calc_func func, void *data)
+{
+	int fckd, fckd_start, fckd_stop;
+	unsigned long fck;
+	unsigned long fck_hw_max;
+	unsigned long fckd_hw_max;
+	unsigned long prate;
+	unsigned m;
+
+	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	if (dss.parent_clk == NULL) {
+		unsigned pckd;
+
+		pckd = fck_hw_max / pck;
+
+		fck = pck * pckd;
+
+		fck = clk_round_rate(dss.dss_clk, fck);
+
+		return func(fck, data);
+	}
+
+	fckd_hw_max = dss.feat->fck_div_max;
+
+	m = dss.feat->dss_fck_multiplier;
+	prate = clk_get_rate(dss.parent_clk);
+
+	fck_min = fck_min ? fck_min : 1;
+
+	fckd_start = min(prate * m / fck_min, fckd_hw_max);
+	fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
+
+	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
+		fck = DIV_ROUND_UP(prate, fckd) * m;
+
+		if (func(fck, data))
+			return true;
+	}
+
+	return false;
+}
+
+int dss_set_fck_rate(unsigned long rate)
+{
+	int r;
+
+	DSSDBG("set fck to %lu\n", rate);
+
+	r = clk_set_rate(dss.dss_clk, rate);
+	if (r)
+		return r;
+
+	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
+	WARN_ONCE(dss.dss_clk_rate != rate,
+			"clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
+			rate);
+
+	return 0;
+}
+
+unsigned long dss_get_dispc_clk_rate(void)
+{
+	return dss.dss_clk_rate;
+}
+
+static int dss_setup_default_clock(void)
+{
+	unsigned long max_dss_fck, prate;
+	unsigned long fck;
+	unsigned fck_div;
+	int r;
+
+	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	if (dss.parent_clk == NULL) {
+		fck = clk_round_rate(dss.dss_clk, max_dss_fck);
+	} else {
+		prate = clk_get_rate(dss.parent_clk);
+
+		fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
+				max_dss_fck);
+		fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
+	}
+
+	r = dss_set_fck_rate(fck);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+void dss_set_venc_output(enum omap_dss_venc_type type)
+{
+	int l = 0;
+
+	if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
+		l = 0;
+	else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
+		l = 1;
+	else
+		BUG();
+
+	/* venc out selection. 0 = comp, 1 = svideo */
+	REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
+}
+
+void dss_set_dac_pwrdn_bgz(bool enable)
+{
+	REG_FLD_MOD(DSS_CONTROL, enable, 5, 5);	/* DAC Power-Down Control */
+}
+
+void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
+{
+	enum omap_display_type dp;
+	dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
+
+	/* Complain about invalid selections */
+	WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
+	WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
+
+	/* Select only if we have options */
+	if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
+		REG_FLD_MOD(DSS_CONTROL, src, 15, 15);	/* VENC_HDMI_SWITCH */
+}
+
+enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
+{
+	enum omap_display_type displays;
+
+	displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
+	if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
+		return DSS_VENC_TV_CLK;
+
+	if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
+		return DSS_HDMI_M_PCLK;
+
+	return REG_GET(DSS_CONTROL, 15, 15);
+}
+
+static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
+{
+	if (channel != OMAP_DSS_CHANNEL_LCD)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int dss_dpi_select_source_omap4(enum omap_channel channel)
+{
+	int val;
+
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD2:
+		val = 0;
+		break;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		val = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
+
+	return 0;
+}
+
+static int dss_dpi_select_source_omap5(enum omap_channel channel)
+{
+	int val;
+
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		val = 1;
+		break;
+	case OMAP_DSS_CHANNEL_LCD2:
+		val = 2;
+		break;
+	case OMAP_DSS_CHANNEL_LCD3:
+		val = 3;
+		break;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		val = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
+
+	return 0;
+}
+
+int dss_dpi_select_source(enum omap_channel channel)
+{
+	return dss.feat->dpi_select_source(channel);
+}
+
+static int dss_get_clocks(void)
+{
+	struct clk *clk;
+
+	clk = devm_clk_get(&dss.pdev->dev, "fck");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get clock fck\n");
+		return PTR_ERR(clk);
+	}
+
+	dss.dss_clk = clk;
+
+	if (dss.feat->parent_clk_name) {
+		clk = clk_get(NULL, dss.feat->parent_clk_name);
+		if (IS_ERR(clk)) {
+			DSSERR("Failed to get %s\n", dss.feat->parent_clk_name);
+			return PTR_ERR(clk);
+		}
+	} else {
+		clk = NULL;
+	}
+
+	dss.parent_clk = clk;
+
+	return 0;
+}
+
+static void dss_put_clocks(void)
+{
+	if (dss.parent_clk)
+		clk_put(dss.parent_clk);
+}
+
+static int dss_runtime_get(void)
+{
+	int r;
+
+	DSSDBG("dss_runtime_get\n");
+
+	r = pm_runtime_get_sync(&dss.pdev->dev);
+	WARN_ON(r < 0);
+	return r < 0 ? r : 0;
+}
+
+static void dss_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("dss_runtime_put\n");
+
+	r = pm_runtime_put_sync(&dss.pdev->dev);
+	WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
+}
+
+/* DEBUGFS */
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
+void dss_debug_dump_clocks(struct seq_file *s)
+{
+	dss_dump_clocks(s);
+	dispc_dump_clocks(s);
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_dump_clocks(s);
+#endif
+}
+#endif
+
+static const struct dss_features omap24xx_dss_feats __initconst = {
+	/*
+	 * fck div max is really 16, but the divider range has gaps. The range
+	 * from 1 to 6 has no gaps, so let's use that as a max.
+	 */
+	.fck_div_max		=	6,
+	.dss_fck_multiplier	=	2,
+	.parent_clk_name	=	"core_ck",
+	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
+};
+
+static const struct dss_features omap34xx_dss_feats __initconst = {
+	.fck_div_max		=	16,
+	.dss_fck_multiplier	=	2,
+	.parent_clk_name	=	"dpll4_ck",
+	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
+};
+
+static const struct dss_features omap3630_dss_feats __initconst = {
+	.fck_div_max		=	32,
+	.dss_fck_multiplier	=	1,
+	.parent_clk_name	=	"dpll4_ck",
+	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
+};
+
+static const struct dss_features omap44xx_dss_feats __initconst = {
+	.fck_div_max		=	32,
+	.dss_fck_multiplier	=	1,
+	.parent_clk_name	=	"dpll_per_x2_ck",
+	.dpi_select_source	=	&dss_dpi_select_source_omap4,
+};
+
+static const struct dss_features omap54xx_dss_feats __initconst = {
+	.fck_div_max		=	64,
+	.dss_fck_multiplier	=	1,
+	.parent_clk_name	=	"dpll_per_x2_ck",
+	.dpi_select_source	=	&dss_dpi_select_source_omap5,
+};
+
+static int __init dss_init_features(struct platform_device *pdev)
+{
+	const struct dss_features *src;
+	struct dss_features *dst;
+
+	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
+	if (!dst) {
+		dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
+		return -ENOMEM;
+	}
+
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+		src = &omap24xx_dss_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_AM35xx:
+		src = &omap34xx_dss_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP3630:
+		src = &omap3630_dss_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
+		src = &omap44xx_dss_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP5:
+		src = &omap54xx_dss_feats;
+		break;
+
+	default:
+		return -ENODEV;
+	}
+
+	memcpy(dst, src, sizeof(*dst));
+	dss.feat = dst;
+
+	return 0;
+}
+
+static int __init dss_init_ports(struct platform_device *pdev)
+{
+	struct device_node *parent = pdev->dev.of_node;
+	struct device_node *port;
+	int r;
+
+	if (parent == NULL)
+		return 0;
+
+	port = omapdss_of_get_next_port(parent, NULL);
+	if (!port) {
+#ifdef CONFIG_OMAP2_DSS_DPI
+		dpi_init_port(pdev, parent);
+#endif
+		return 0;
+	}
+
+	do {
+		u32 reg;
+
+		r = of_property_read_u32(port, "reg", &reg);
+		if (r)
+			reg = 0;
+
+#ifdef CONFIG_OMAP2_DSS_DPI
+		if (reg == 0)
+			dpi_init_port(pdev, port);
+#endif
+
+#ifdef CONFIG_OMAP2_DSS_SDI
+		if (reg == 1)
+			sdi_init_port(pdev, port);
+#endif
+
+	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+
+	return 0;
+}
+
+static void dss_uninit_ports(void)
+{
+#ifdef CONFIG_OMAP2_DSS_DPI
+	dpi_uninit_port();
+#endif
+
+#ifdef CONFIG_OMAP2_DSS_SDI
+	sdi_uninit_port();
+#endif
+}
+
+/* DSS HW IP initialisation */
+static int __init omap_dsshw_probe(struct platform_device *pdev)
+{
+	struct resource *dss_mem;
+	u32 rev;
+	int r;
+
+	dss.pdev = pdev;
+
+	r = dss_init_features(dss.pdev);
+	if (r)
+		return r;
+
+	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+	if (!dss_mem) {
+		DSSERR("can't get IORESOURCE_MEM DSS\n");
+		return -EINVAL;
+	}
+
+	dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
+				resource_size(dss_mem));
+	if (!dss.base) {
+		DSSERR("can't ioremap DSS\n");
+		return -ENOMEM;
+	}
+
+	r = dss_get_clocks();
+	if (r)
+		return r;
+
+	r = dss_setup_default_clock();
+	if (r)
+		goto err_setup_clocks;
+
+	pm_runtime_enable(&pdev->dev);
+
+	r = dss_runtime_get();
+	if (r)
+		goto err_runtime_get;
+
+	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
+	/* Select DPLL */
+	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
+	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
+	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
+#endif
+	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
+	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+
+	dss_init_ports(pdev);
+
+	rev = dss_read_reg(DSS_REVISION);
+	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	dss_runtime_put();
+
+	dss_debugfs_create_file("dss", dss_dump_regs);
+
+	return 0;
+
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
+err_setup_clocks:
+	dss_put_clocks();
+	return r;
+}
+
+static int __exit omap_dsshw_remove(struct platform_device *pdev)
+{
+	dss_uninit_ports();
+
+	pm_runtime_disable(&pdev->dev);
+
+	dss_put_clocks();
+
+	return 0;
+}
+
+static int dss_runtime_suspend(struct device *dev)
+{
+	dss_save_context();
+	dss_set_min_bus_tput(dev, 0);
+	return 0;
+}
+
+static int dss_runtime_resume(struct device *dev)
+{
+	int r;
+	/*
+	 * Set an arbitrarily high tput request to ensure OPP100.
+	 * What we should really do is to make a request to stay in OPP100,
+	 * without any tput requirements, but that is not currently possible
+	 * via the PM layer.
+	 */
+
+	r = dss_set_min_bus_tput(dev, 1000000000);
+	if (r)
+		return r;
+
+	dss_restore_context();
+	return 0;
+}
+
+static const struct dev_pm_ops dss_pm_ops = {
+	.runtime_suspend = dss_runtime_suspend,
+	.runtime_resume = dss_runtime_resume,
+};
+
+static const struct of_device_id dss_of_match[] = {
+	{ .compatible = "ti,omap2-dss", },
+	{ .compatible = "ti,omap3-dss", },
+	{ .compatible = "ti,omap4-dss", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, dss_of_match);
+
+static struct platform_driver omap_dsshw_driver = {
+	.remove         = __exit_p(omap_dsshw_remove),
+	.driver         = {
+		.name   = "omapdss_dss",
+		.owner  = THIS_MODULE,
+		.pm	= &dss_pm_ops,
+		.of_match_table = dss_of_match,
+	},
+};
+
+int __init dss_init_platform_driver(void)
+{
+	return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe);
+}
+
+void dss_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omap_dsshw_driver);
+}
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h
new file mode 100644
index 000000000000..560078fcb198
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dss.h
@@ -0,0 +1,438 @@
+/*
+ * linux/drivers/video/omap2/dss/dss.h
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_H
+#define __OMAP2_DSS_H
+
+#include <linux/interrupt.h>
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
+#else
+#define pr_fmt(fmt) fmt
+#endif
+
+#define DSSDBG(format, ...) \
+	pr_debug(format, ## __VA_ARGS__)
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSERR(format, ...) \
+	printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
+	## __VA_ARGS__)
+#else
+#define DSSERR(format, ...) \
+	printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSINFO(format, ...) \
+	printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
+	## __VA_ARGS__)
+#else
+#define DSSINFO(format, ...) \
+	printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
+#endif
+
+#ifdef DSS_SUBSYS_NAME
+#define DSSWARN(format, ...) \
+	printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
+	## __VA_ARGS__)
+#else
+#define DSSWARN(format, ...) \
+	printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
+#endif
+
+/* OMAP TRM gives bitfields as start:end, where start is the higher bit
+   number. For example 7:0 */
+#define FLD_MASK(start, end)	(((1 << ((start) - (end) + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
+#define FLD_MOD(orig, val, start, end) \
+	(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+
+enum dss_io_pad_mode {
+	DSS_IO_PAD_MODE_RESET,
+	DSS_IO_PAD_MODE_RFBI,
+	DSS_IO_PAD_MODE_BYPASS,
+};
+
+enum dss_hdmi_venc_clk_source_select {
+	DSS_VENC_TV_CLK = 0,
+	DSS_HDMI_M_PCLK = 1,
+};
+
+enum dss_dsi_content_type {
+	DSS_DSI_CONTENT_DCS,
+	DSS_DSI_CONTENT_GENERIC,
+};
+
+enum dss_writeback_channel {
+	DSS_WB_LCD1_MGR =	0,
+	DSS_WB_LCD2_MGR =	1,
+	DSS_WB_TV_MGR =		2,
+	DSS_WB_OVL0 =		3,
+	DSS_WB_OVL1 =		4,
+	DSS_WB_OVL2 =		5,
+	DSS_WB_OVL3 =		6,
+	DSS_WB_LCD3_MGR =	7,
+};
+
+struct dispc_clock_info {
+	/* rates that we get with dividers below */
+	unsigned long lck;
+	unsigned long pck;
+
+	/* dividers */
+	u16 lck_div;
+	u16 pck_div;
+};
+
+struct dsi_clock_info {
+	/* rates that we get with dividers below */
+	unsigned long fint;
+	unsigned long clkin4ddr;
+	unsigned long clkin;
+	unsigned long dsi_pll_hsdiv_dispc_clk;	/* OMAP3: DSI1_PLL_CLK
+						 * OMAP4: PLLx_CLK1 */
+	unsigned long dsi_pll_hsdiv_dsi_clk;	/* OMAP3: DSI2_PLL_CLK
+						 * OMAP4: PLLx_CLK2 */
+	unsigned long lp_clk;
+
+	/* dividers */
+	u16 regn;
+	u16 regm;
+	u16 regm_dispc;	/* OMAP3: REGM3
+			 * OMAP4: REGM4 */
+	u16 regm_dsi;	/* OMAP3: REGM4
+			 * OMAP4: REGM5 */
+	u16 lp_clk_div;
+};
+
+struct dss_lcd_mgr_config {
+	enum dss_io_pad_mode io_pad_mode;
+
+	bool stallmode;
+	bool fifohandcheck;
+
+	struct dispc_clock_info clock_info;
+
+	int video_port_width;
+
+	int lcden_sig_polarity;
+};
+
+struct seq_file;
+struct platform_device;
+
+/* core */
+struct platform_device *dss_get_core_pdev(void);
+int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
+void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
+int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
+int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
+
+/* display */
+int dss_suspend_all_devices(void);
+int dss_resume_all_devices(void);
+void dss_disable_all_devices(void);
+
+int display_init_sysfs(struct platform_device *pdev);
+void display_uninit_sysfs(struct platform_device *pdev);
+
+/* manager */
+int dss_init_overlay_managers(void);
+void dss_uninit_overlay_managers(void);
+int dss_init_overlay_managers_sysfs(struct platform_device *pdev);
+void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev);
+int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
+		const struct omap_overlay_manager_info *info);
+int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings);
+int dss_mgr_check(struct omap_overlay_manager *mgr,
+		struct omap_overlay_manager_info *info,
+		const struct omap_video_timings *mgr_timings,
+		const struct dss_lcd_mgr_config *config,
+		struct omap_overlay_info **overlay_infos);
+
+static inline bool dss_mgr_is_lcd(enum omap_channel id)
+{
+	if (id == OMAP_DSS_CHANNEL_LCD || id == OMAP_DSS_CHANNEL_LCD2 ||
+			id == OMAP_DSS_CHANNEL_LCD3)
+		return true;
+	else
+		return false;
+}
+
+int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
+		struct platform_device *pdev);
+void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
+
+/* overlay */
+void dss_init_overlays(struct platform_device *pdev);
+void dss_uninit_overlays(struct platform_device *pdev);
+void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
+int dss_ovl_simple_check(struct omap_overlay *ovl,
+		const struct omap_overlay_info *info);
+int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
+		const struct omap_video_timings *mgr_timings);
+bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
+		enum omap_color_mode mode);
+int dss_overlay_kobj_init(struct omap_overlay *ovl,
+		struct platform_device *pdev);
+void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
+
+/* DSS */
+int dss_init_platform_driver(void) __init;
+void dss_uninit_platform_driver(void);
+
+unsigned long dss_get_dispc_clk_rate(void);
+int dss_dpi_select_source(enum omap_channel channel);
+void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
+enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
+const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
+void dss_dump_clocks(struct seq_file *s);
+
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
+void dss_debug_dump_clocks(struct seq_file *s);
+#endif
+
+void dss_sdi_init(int datapairs);
+int dss_sdi_enable(void);
+void dss_sdi_disable(void);
+
+void dss_select_dsi_clk_source(int dsi_module,
+		enum omap_dss_clk_source clk_src);
+void dss_select_lcd_clk_source(enum omap_channel channel,
+		enum omap_dss_clk_source clk_src);
+enum omap_dss_clk_source dss_get_dispc_clk_source(void);
+enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module);
+enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
+
+void dss_set_venc_output(enum omap_dss_venc_type type);
+void dss_set_dac_pwrdn_bgz(bool enable);
+
+int dss_set_fck_rate(unsigned long rate);
+
+typedef bool (*dss_div_calc_func)(unsigned long fck, void *data);
+bool dss_div_calc(unsigned long pck, unsigned long fck_min,
+		dss_div_calc_func func, void *data);
+
+/* SDI */
+int sdi_init_platform_driver(void) __init;
+void sdi_uninit_platform_driver(void) __exit;
+
+int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init;
+void sdi_uninit_port(void) __exit;
+
+/* DSI */
+
+typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data);
+typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
+		void *data);
+
+#ifdef CONFIG_OMAP2_DSS_DSI
+
+struct dentry;
+struct file_operations;
+
+int dsi_init_platform_driver(void) __init;
+void dsi_uninit_platform_driver(void) __exit;
+
+int dsi_runtime_get(struct platform_device *dsidev);
+void dsi_runtime_put(struct platform_device *dsidev);
+
+void dsi_dump_clocks(struct seq_file *s);
+
+void dsi_irq_handler(void);
+u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
+
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
+
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data);
+
+unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
+int dsi_pll_set_clock_div(struct platform_device *dsidev,
+		struct dsi_clock_info *cinfo);
+int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
+		bool enable_hsdiv);
+void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
+void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
+void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
+struct platform_device *dsi_get_dsidev_from_id(int module);
+#else
+static inline int dsi_runtime_get(struct platform_device *dsidev)
+{
+	return 0;
+}
+static inline void dsi_runtime_put(struct platform_device *dsidev)
+{
+}
+static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
+{
+	WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
+	return 0;
+}
+static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
+{
+	WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
+	return 0;
+}
+static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
+		struct dsi_clock_info *cinfo)
+{
+	WARN("%s: DSI not compiled in\n", __func__);
+	return -ENODEV;
+}
+static inline int dsi_pll_init(struct platform_device *dsidev,
+		bool enable_hsclk, bool enable_hsdiv)
+{
+	WARN("%s: DSI not compiled in\n", __func__);
+	return -ENODEV;
+}
+static inline void dsi_pll_uninit(struct platform_device *dsidev,
+		bool disconnect_lanes)
+{
+}
+static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
+{
+}
+static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
+{
+}
+static inline struct platform_device *dsi_get_dsidev_from_id(int module)
+{
+	return NULL;
+}
+
+static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
+{
+	return 0;
+}
+
+static inline bool dsi_hsdiv_calc(struct platform_device *dsidev,
+		unsigned long pll, unsigned long out_min,
+		dsi_hsdiv_calc_func func, void *data)
+{
+	return false;
+}
+
+static inline bool dsi_pll_calc(struct platform_device *dsidev,
+		unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data)
+{
+	return false;
+}
+
+#endif
+
+/* DPI */
+int dpi_init_platform_driver(void) __init;
+void dpi_uninit_platform_driver(void) __exit;
+
+int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init;
+void dpi_uninit_port(void) __exit;
+
+/* DISPC */
+int dispc_init_platform_driver(void) __init;
+void dispc_uninit_platform_driver(void) __exit;
+void dispc_dump_clocks(struct seq_file *s);
+
+void dispc_enable_sidle(void);
+void dispc_disable_sidle(void);
+
+void dispc_lcd_enable_signal(bool enable);
+void dispc_pck_free_enable(bool enable);
+void dispc_enable_fifomerge(bool enable);
+void dispc_enable_gamma_table(bool enable);
+void dispc_set_loadmode(enum omap_dss_load_mode mode);
+
+typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data);
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data);
+
+bool dispc_mgr_timings_ok(enum omap_channel channel,
+		const struct omap_video_timings *timings);
+unsigned long dispc_fclk_rate(void);
+int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
+		struct dispc_clock_info *cinfo);
+
+
+void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
+void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
+		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
+		bool manual_update);
+
+unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
+unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
+unsigned long dispc_core_clk_rate(void);
+void dispc_mgr_set_clock_div(enum omap_channel channel,
+		const struct dispc_clock_info *cinfo);
+int dispc_mgr_get_clock_div(enum omap_channel channel,
+		struct dispc_clock_info *cinfo);
+void dispc_set_tv_pclk(unsigned long pclk);
+
+u32 dispc_wb_get_framedone_irq(void);
+bool dispc_wb_go_busy(void);
+void dispc_wb_go(void);
+void dispc_wb_enable(bool enable);
+bool dispc_wb_is_enabled(void);
+void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
+int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
+		bool mem_to_mem, const struct omap_video_timings *timings);
+
+/* VENC */
+int venc_init_platform_driver(void) __init;
+void venc_uninit_platform_driver(void) __exit;
+
+/* HDMI */
+int hdmi4_init_platform_driver(void) __init;
+void hdmi4_uninit_platform_driver(void) __exit;
+
+/* RFBI */
+int rfbi_init_platform_driver(void) __init;
+void rfbi_uninit_platform_driver(void) __exit;
+
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
+{
+	int b;
+	for (b = 0; b < 32; ++b) {
+		if (irqstatus & (1 << b))
+			irq_arr[b]++;
+	}
+}
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/dss/dss_features.c
new file mode 100644
index 000000000000..7f8969191dc6
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dss_features.c
@@ -0,0 +1,935 @@
+/*
+ * linux/drivers/video/omap2/dss/dss_features.c
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+/* Defines a generic omap register field */
+struct dss_reg_field {
+	u8 start, end;
+};
+
+struct dss_param_range {
+	int min, max;
+};
+
+struct omap_dss_features {
+	const struct dss_reg_field *reg_fields;
+	const int num_reg_fields;
+
+	const enum dss_feat_id *features;
+	const int num_features;
+
+	const int num_mgrs;
+	const int num_ovls;
+	const int num_wbs;
+	const enum omap_display_type *supported_displays;
+	const enum omap_dss_output_id *supported_outputs;
+	const enum omap_color_mode *supported_color_modes;
+	const enum omap_overlay_caps *overlay_caps;
+	const char * const *clksrc_names;
+	const struct dss_param_range *dss_params;
+
+	const enum omap_dss_rotation_type supported_rotation_types;
+
+	const u32 buffer_size_unit;
+	const u32 burst_size_unit;
+};
+
+/* This struct is assigned to one of the below during initialization */
+static const struct omap_dss_features *omap_current_dss_features;
+
+static const struct dss_reg_field omap2_dss_reg_fields[] = {
+	[FEAT_REG_FIRHINC]			= { 11, 0 },
+	[FEAT_REG_FIRVINC]			= { 27, 16 },
+	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 8, 0 },
+	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 24, 16 },
+	[FEAT_REG_FIFOSIZE]			= { 8, 0 },
+	[FEAT_REG_HORIZONTALACCU]		= { 9, 0 },
+	[FEAT_REG_VERTICALACCU]			= { 25, 16 },
+	[FEAT_REG_DISPC_CLK_SWITCH]		= { 0, 0 },
+	[FEAT_REG_DSIPLL_REGN]			= { 0, 0 },
+	[FEAT_REG_DSIPLL_REGM]			= { 0, 0 },
+	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 0, 0 },
+	[FEAT_REG_DSIPLL_REGM_DSI]		= { 0, 0 },
+};
+
+static const struct dss_reg_field omap3_dss_reg_fields[] = {
+	[FEAT_REG_FIRHINC]			= { 12, 0 },
+	[FEAT_REG_FIRVINC]			= { 28, 16 },
+	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 11, 0 },
+	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 27, 16 },
+	[FEAT_REG_FIFOSIZE]			= { 10, 0 },
+	[FEAT_REG_HORIZONTALACCU]		= { 9, 0 },
+	[FEAT_REG_VERTICALACCU]			= { 25, 16 },
+	[FEAT_REG_DISPC_CLK_SWITCH]		= { 0, 0 },
+	[FEAT_REG_DSIPLL_REGN]			= { 7, 1 },
+	[FEAT_REG_DSIPLL_REGM]			= { 18, 8 },
+	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 22, 19 },
+	[FEAT_REG_DSIPLL_REGM_DSI]		= { 26, 23 },
+};
+
+static const struct dss_reg_field omap4_dss_reg_fields[] = {
+	[FEAT_REG_FIRHINC]			= { 12, 0 },
+	[FEAT_REG_FIRVINC]			= { 28, 16 },
+	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 15, 0 },
+	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 31, 16 },
+	[FEAT_REG_FIFOSIZE]			= { 15, 0 },
+	[FEAT_REG_HORIZONTALACCU]		= { 10, 0 },
+	[FEAT_REG_VERTICALACCU]			= { 26, 16 },
+	[FEAT_REG_DISPC_CLK_SWITCH]		= { 9, 8 },
+	[FEAT_REG_DSIPLL_REGN]			= { 8, 1 },
+	[FEAT_REG_DSIPLL_REGM]			= { 20, 9 },
+	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 25, 21 },
+	[FEAT_REG_DSIPLL_REGM_DSI]		= { 30, 26 },
+};
+
+static const struct dss_reg_field omap5_dss_reg_fields[] = {
+	[FEAT_REG_FIRHINC]			= { 12, 0 },
+	[FEAT_REG_FIRVINC]			= { 28, 16 },
+	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 15, 0 },
+	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 31, 16 },
+	[FEAT_REG_FIFOSIZE]			= { 15, 0 },
+	[FEAT_REG_HORIZONTALACCU]		= { 10, 0 },
+	[FEAT_REG_VERTICALACCU]			= { 26, 16 },
+	[FEAT_REG_DISPC_CLK_SWITCH]		= { 9, 7 },
+	[FEAT_REG_DSIPLL_REGN]			= { 8, 1 },
+	[FEAT_REG_DSIPLL_REGM]			= { 20, 9 },
+	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 25, 21 },
+	[FEAT_REG_DSIPLL_REGM_DSI]		= { 30, 26 },
+};
+
+static const enum omap_display_type omap2_dss_supported_displays[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_display_type omap3430_dss_supported_displays[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+	OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_display_type omap3630_dss_supported_displays[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+	OMAP_DISPLAY_TYPE_DSI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_display_type omap4_dss_supported_displays[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI,
+
+	/* OMAP_DSS_CHANNEL_LCD2 */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+	OMAP_DISPLAY_TYPE_DSI,
+};
+
+static const enum omap_display_type omap5_dss_supported_displays[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+	OMAP_DISPLAY_TYPE_DSI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
+
+	/* OMAP_DSS_CHANNEL_LCD2 */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+	OMAP_DISPLAY_TYPE_DSI,
+};
+
+static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DSS_OUTPUT_VENC,
+};
+
+static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+	OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DSS_OUTPUT_VENC,
+};
+
+static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+	OMAP_DSS_OUTPUT_DSI1,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DSS_OUTPUT_VENC,
+};
+
+static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
+
+	/* OMAP_DSS_CHANNEL_LCD2 */
+	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+	OMAP_DSS_OUTPUT_DSI2,
+};
+
+static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+	OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
+
+	/* OMAP_DSS_CHANNEL_LCD2 */
+	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+	OMAP_DSS_OUTPUT_DSI1,
+
+	/* OMAP_DSS_CHANNEL_LCD3 */
+	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
+	OMAP_DSS_OUTPUT_DSI2,
+};
+
+static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
+	OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+	OMAP_DSS_COLOR_UYVY,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+	OMAP_DSS_COLOR_UYVY,
+};
+
+static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
+	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+	OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+};
+
+static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
+	OMAP_DSS_COLOR_ARGB16_1555 | OMAP_DSS_COLOR_RGBX16 |
+	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_XRGB16_1555,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
+	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
+	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
+	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
+	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
+	OMAP_DSS_COLOR_RGBX32,
+
+       /* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
+	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
+	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
+	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
+	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
+	OMAP_DSS_COLOR_RGBX32,
+
+	/* OMAP_DSS_VIDEO3 */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
+	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
+	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
+	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
+	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
+	OMAP_DSS_COLOR_RGBX32,
+
+	/* OMAP_DSS_WB */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
+	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
+	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
+	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
+	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
+	OMAP_DSS_COLOR_RGBX32,
+};
+
+static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+		OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+		OMAP_DSS_OVL_CAP_REPLICATION,
+};
+
+static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
+		OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+		OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
+};
+
+static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
+		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
+		OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
+		OMAP_DSS_OVL_CAP_REPLICATION,
+};
+
+static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
+		OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
+		OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
+		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
+		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
+
+	/* OMAP_DSS_VIDEO3 */
+	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
+		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
+};
+
+static const char * const omap2_dss_clk_source_names[] = {
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "N/A",
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "N/A",
+	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCLK1",
+};
+
+static const char * const omap3_dss_clk_source_names[] = {
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI1_PLL_FCLK",
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI2_PLL_FCLK",
+	[OMAP_DSS_CLK_SRC_FCK]			= "DSS1_ALWON_FCLK",
+};
+
+static const char * const omap4_dss_clk_source_names[] = {
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "PLL1_CLK1",
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "PLL1_CLK2",
+	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCLK",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "PLL2_CLK1",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "PLL2_CLK2",
+};
+
+static const char * const omap5_dss_clk_source_names[] = {
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DPLL_DSI1_A_CLK1",
+	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DPLL_DSI1_A_CLK2",
+	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_CLK",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DPLL_DSI1_C_CLK1",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DPLL_DSI1_C_CLK2",
+};
+
+static const struct dss_param_range omap2_dss_param_range[] = {
+	[FEAT_PARAM_DSS_FCK]			= { 0, 133000000 },
+	[FEAT_PARAM_DSS_PCD]			= { 2, 255 },
+	[FEAT_PARAM_DSIPLL_REGN]		= { 0, 0 },
+	[FEAT_PARAM_DSIPLL_REGM]		= { 0, 0 },
+	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, 0 },
+	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, 0 },
+	[FEAT_PARAM_DSIPLL_FINT]		= { 0, 0 },
+	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, 0 },
+	[FEAT_PARAM_DOWNSCALE]			= { 1, 2 },
+	/*
+	 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
+	 * scaler cannot scale a image with width more than 768.
+	 */
+	[FEAT_PARAM_LINEWIDTH]			= { 1, 768 },
+};
+
+static const struct dss_param_range omap3_dss_param_range[] = {
+	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 },
+	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
+	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 7) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 11) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 4) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 4) - 1 },
+	[FEAT_PARAM_DSIPLL_FINT]		= { 750000, 2100000 },
+	[FEAT_PARAM_DSIPLL_LPDIV]		= { 1, (1 << 13) - 1},
+	[FEAT_PARAM_DSI_FCK]			= { 0, 173000000 },
+	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
+	[FEAT_PARAM_LINEWIDTH]			= { 1, 1024 },
+};
+
+static const struct dss_param_range omap4_dss_param_range[] = {
+	[FEAT_PARAM_DSS_FCK]			= { 0, 186000000 },
+	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
+	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 8) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 12) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 5) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 5) - 1 },
+	[FEAT_PARAM_DSIPLL_FINT]		= { 500000, 2500000 },
+	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, (1 << 13) - 1 },
+	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
+	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
+	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
+};
+
+static const struct dss_param_range omap5_dss_param_range[] = {
+	[FEAT_PARAM_DSS_FCK]			= { 0, 209250000 },
+	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
+	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 8) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 12) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 5) - 1 },
+	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 5) - 1 },
+	[FEAT_PARAM_DSIPLL_FINT]		= { 150000, 52000000 },
+	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, (1 << 13) - 1 },
+	[FEAT_PARAM_DSI_FCK]			= { 0, 209250000 },
+	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
+	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
+};
+
+static const enum dss_feat_id omap2_dss_feat_list[] = {
+	FEAT_LCDENABLEPOL,
+	FEAT_LCDENABLESIGNAL,
+	FEAT_PCKFREEENABLE,
+	FEAT_FUNCGATED,
+	FEAT_ROWREPEATENABLE,
+	FEAT_RESIZECONF,
+};
+
+static const enum dss_feat_id omap3430_dss_feat_list[] = {
+	FEAT_LCDENABLEPOL,
+	FEAT_LCDENABLESIGNAL,
+	FEAT_PCKFREEENABLE,
+	FEAT_FUNCGATED,
+	FEAT_LINEBUFFERSPLIT,
+	FEAT_ROWREPEATENABLE,
+	FEAT_RESIZECONF,
+	FEAT_DSI_PLL_FREQSEL,
+	FEAT_DSI_REVERSE_TXCLKESC,
+	FEAT_VENC_REQUIRES_TV_DAC_CLK,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FIXED_ZORDER,
+	FEAT_FIFO_MERGE,
+	FEAT_OMAP3_DSI_FIFO_BUG,
+	FEAT_DPI_USES_VDDS_DSI,
+};
+
+static const enum dss_feat_id am35xx_dss_feat_list[] = {
+	FEAT_LCDENABLEPOL,
+	FEAT_LCDENABLESIGNAL,
+	FEAT_PCKFREEENABLE,
+	FEAT_FUNCGATED,
+	FEAT_LINEBUFFERSPLIT,
+	FEAT_ROWREPEATENABLE,
+	FEAT_RESIZECONF,
+	FEAT_DSI_PLL_FREQSEL,
+	FEAT_DSI_REVERSE_TXCLKESC,
+	FEAT_VENC_REQUIRES_TV_DAC_CLK,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FIXED_ZORDER,
+	FEAT_FIFO_MERGE,
+	FEAT_OMAP3_DSI_FIFO_BUG,
+};
+
+static const enum dss_feat_id omap3630_dss_feat_list[] = {
+	FEAT_LCDENABLEPOL,
+	FEAT_LCDENABLESIGNAL,
+	FEAT_PCKFREEENABLE,
+	FEAT_FUNCGATED,
+	FEAT_LINEBUFFERSPLIT,
+	FEAT_ROWREPEATENABLE,
+	FEAT_RESIZECONF,
+	FEAT_DSI_PLL_PWR_BUG,
+	FEAT_DSI_PLL_FREQSEL,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FIXED_ZORDER,
+	FEAT_FIFO_MERGE,
+	FEAT_OMAP3_DSI_FIFO_BUG,
+	FEAT_DPI_USES_VDDS_DSI,
+};
+
+static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
+	FEAT_MGR_LCD2,
+	FEAT_CORE_CLK_DIV,
+	FEAT_LCD_CLK_SRC,
+	FEAT_DSI_DCS_CMD_CONFIG_VC,
+	FEAT_DSI_VC_OCP_WIDTH,
+	FEAT_DSI_GNQ,
+	FEAT_HANDLE_UV_SEPARATE,
+	FEAT_ATTR2,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FREE_ZORDER,
+	FEAT_FIFO_MERGE,
+	FEAT_BURST_2D,
+};
+
+static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
+	FEAT_MGR_LCD2,
+	FEAT_CORE_CLK_DIV,
+	FEAT_LCD_CLK_SRC,
+	FEAT_DSI_DCS_CMD_CONFIG_VC,
+	FEAT_DSI_VC_OCP_WIDTH,
+	FEAT_DSI_GNQ,
+	FEAT_HDMI_CTS_SWMODE,
+	FEAT_HANDLE_UV_SEPARATE,
+	FEAT_ATTR2,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FREE_ZORDER,
+	FEAT_FIFO_MERGE,
+	FEAT_BURST_2D,
+};
+
+static const enum dss_feat_id omap4_dss_feat_list[] = {
+	FEAT_MGR_LCD2,
+	FEAT_CORE_CLK_DIV,
+	FEAT_LCD_CLK_SRC,
+	FEAT_DSI_DCS_CMD_CONFIG_VC,
+	FEAT_DSI_VC_OCP_WIDTH,
+	FEAT_DSI_GNQ,
+	FEAT_HDMI_CTS_SWMODE,
+	FEAT_HDMI_AUDIO_USE_MCLK,
+	FEAT_HANDLE_UV_SEPARATE,
+	FEAT_ATTR2,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FREE_ZORDER,
+	FEAT_FIFO_MERGE,
+	FEAT_BURST_2D,
+};
+
+static const enum dss_feat_id omap5_dss_feat_list[] = {
+	FEAT_MGR_LCD2,
+	FEAT_CORE_CLK_DIV,
+	FEAT_LCD_CLK_SRC,
+	FEAT_DSI_DCS_CMD_CONFIG_VC,
+	FEAT_DSI_VC_OCP_WIDTH,
+	FEAT_DSI_GNQ,
+	FEAT_HDMI_CTS_SWMODE,
+	FEAT_HDMI_AUDIO_USE_MCLK,
+	FEAT_HANDLE_UV_SEPARATE,
+	FEAT_ATTR2,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FREE_ZORDER,
+	FEAT_FIFO_MERGE,
+	FEAT_BURST_2D,
+	FEAT_DSI_PLL_SELFREQDCO,
+	FEAT_DSI_PLL_REFSEL,
+	FEAT_DSI_PHY_DCC,
+	FEAT_MFLAG,
+};
+
+/* OMAP2 DSS Features */
+static const struct omap_dss_features omap2_dss_features = {
+	.reg_fields = omap2_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
+
+	.features = omap2_dss_feat_list,
+	.num_features = ARRAY_SIZE(omap2_dss_feat_list),
+
+	.num_mgrs = 2,
+	.num_ovls = 3,
+	.supported_displays = omap2_dss_supported_displays,
+	.supported_outputs = omap2_dss_supported_outputs,
+	.supported_color_modes = omap2_dss_supported_color_modes,
+	.overlay_caps = omap2_dss_overlay_caps,
+	.clksrc_names = omap2_dss_clk_source_names,
+	.dss_params = omap2_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
+	.buffer_size_unit = 1,
+	.burst_size_unit = 8,
+};
+
+/* OMAP3 DSS Features */
+static const struct omap_dss_features omap3430_dss_features = {
+	.reg_fields = omap3_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
+
+	.features = omap3430_dss_feat_list,
+	.num_features = ARRAY_SIZE(omap3430_dss_feat_list),
+
+	.num_mgrs = 2,
+	.num_ovls = 3,
+	.supported_displays = omap3430_dss_supported_displays,
+	.supported_outputs = omap3430_dss_supported_outputs,
+	.supported_color_modes = omap3_dss_supported_color_modes,
+	.overlay_caps = omap3430_dss_overlay_caps,
+	.clksrc_names = omap3_dss_clk_source_names,
+	.dss_params = omap3_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
+	.buffer_size_unit = 1,
+	.burst_size_unit = 8,
+};
+
+/*
+ * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
+ * vdds_dsi regulator.
+ */
+static const struct omap_dss_features am35xx_dss_features = {
+	.reg_fields = omap3_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
+
+	.features = am35xx_dss_feat_list,
+	.num_features = ARRAY_SIZE(am35xx_dss_feat_list),
+
+	.num_mgrs = 2,
+	.num_ovls = 3,
+	.supported_displays = omap3430_dss_supported_displays,
+	.supported_outputs = omap3430_dss_supported_outputs,
+	.supported_color_modes = omap3_dss_supported_color_modes,
+	.overlay_caps = omap3430_dss_overlay_caps,
+	.clksrc_names = omap3_dss_clk_source_names,
+	.dss_params = omap3_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
+	.buffer_size_unit = 1,
+	.burst_size_unit = 8,
+};
+
+static const struct omap_dss_features omap3630_dss_features = {
+	.reg_fields = omap3_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
+
+	.features = omap3630_dss_feat_list,
+	.num_features = ARRAY_SIZE(omap3630_dss_feat_list),
+
+	.num_mgrs = 2,
+	.num_ovls = 3,
+	.supported_displays = omap3630_dss_supported_displays,
+	.supported_outputs = omap3630_dss_supported_outputs,
+	.supported_color_modes = omap3_dss_supported_color_modes,
+	.overlay_caps = omap3630_dss_overlay_caps,
+	.clksrc_names = omap3_dss_clk_source_names,
+	.dss_params = omap3_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
+	.buffer_size_unit = 1,
+	.burst_size_unit = 8,
+};
+
+/* OMAP4 DSS Features */
+/* For OMAP4430 ES 1.0 revision */
+static const struct omap_dss_features omap4430_es1_0_dss_features  = {
+	.reg_fields = omap4_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
+
+	.features = omap4430_es1_0_dss_feat_list,
+	.num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list),
+
+	.num_mgrs = 3,
+	.num_ovls = 4,
+	.num_wbs = 1,
+	.supported_displays = omap4_dss_supported_displays,
+	.supported_outputs = omap4_dss_supported_outputs,
+	.supported_color_modes = omap4_dss_supported_color_modes,
+	.overlay_caps = omap4_dss_overlay_caps,
+	.clksrc_names = omap4_dss_clk_source_names,
+	.dss_params = omap4_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
+	.buffer_size_unit = 16,
+	.burst_size_unit = 16,
+};
+
+/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
+static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
+	.reg_fields = omap4_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
+
+	.features = omap4430_es2_0_1_2_dss_feat_list,
+	.num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list),
+
+	.num_mgrs = 3,
+	.num_ovls = 4,
+	.num_wbs = 1,
+	.supported_displays = omap4_dss_supported_displays,
+	.supported_outputs = omap4_dss_supported_outputs,
+	.supported_color_modes = omap4_dss_supported_color_modes,
+	.overlay_caps = omap4_dss_overlay_caps,
+	.clksrc_names = omap4_dss_clk_source_names,
+	.dss_params = omap4_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
+	.buffer_size_unit = 16,
+	.burst_size_unit = 16,
+};
+
+/* For all the other OMAP4 versions */
+static const struct omap_dss_features omap4_dss_features = {
+	.reg_fields = omap4_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
+
+	.features = omap4_dss_feat_list,
+	.num_features = ARRAY_SIZE(omap4_dss_feat_list),
+
+	.num_mgrs = 3,
+	.num_ovls = 4,
+	.num_wbs = 1,
+	.supported_displays = omap4_dss_supported_displays,
+	.supported_outputs = omap4_dss_supported_outputs,
+	.supported_color_modes = omap4_dss_supported_color_modes,
+	.overlay_caps = omap4_dss_overlay_caps,
+	.clksrc_names = omap4_dss_clk_source_names,
+	.dss_params = omap4_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
+	.buffer_size_unit = 16,
+	.burst_size_unit = 16,
+};
+
+/* OMAP5 DSS Features */
+static const struct omap_dss_features omap5_dss_features = {
+	.reg_fields = omap5_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
+
+	.features = omap5_dss_feat_list,
+	.num_features = ARRAY_SIZE(omap5_dss_feat_list),
+
+	.num_mgrs = 3,
+	.num_ovls = 4,
+	.supported_displays = omap5_dss_supported_displays,
+	.supported_outputs = omap5_dss_supported_outputs,
+	.supported_color_modes = omap4_dss_supported_color_modes,
+	.overlay_caps = omap4_dss_overlay_caps,
+	.clksrc_names = omap5_dss_clk_source_names,
+	.dss_params = omap5_dss_param_range,
+	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
+	.buffer_size_unit = 16,
+	.burst_size_unit = 16,
+};
+
+/* Functions returning values related to a DSS feature */
+int dss_feat_get_num_mgrs(void)
+{
+	return omap_current_dss_features->num_mgrs;
+}
+EXPORT_SYMBOL(dss_feat_get_num_mgrs);
+
+int dss_feat_get_num_ovls(void)
+{
+	return omap_current_dss_features->num_ovls;
+}
+EXPORT_SYMBOL(dss_feat_get_num_ovls);
+
+int dss_feat_get_num_wbs(void)
+{
+	return omap_current_dss_features->num_wbs;
+}
+
+unsigned long dss_feat_get_param_min(enum dss_range_param param)
+{
+	return omap_current_dss_features->dss_params[param].min;
+}
+
+unsigned long dss_feat_get_param_max(enum dss_range_param param)
+{
+	return omap_current_dss_features->dss_params[param].max;
+}
+
+enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
+{
+	return omap_current_dss_features->supported_displays[channel];
+}
+EXPORT_SYMBOL(dss_feat_get_supported_displays);
+
+enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
+{
+	return omap_current_dss_features->supported_outputs[channel];
+}
+EXPORT_SYMBOL(dss_feat_get_supported_outputs);
+
+enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
+{
+	return omap_current_dss_features->supported_color_modes[plane];
+}
+EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
+
+enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
+{
+	return omap_current_dss_features->overlay_caps[plane];
+}
+
+bool dss_feat_color_mode_supported(enum omap_plane plane,
+		enum omap_color_mode color_mode)
+{
+	return omap_current_dss_features->supported_color_modes[plane] &
+			color_mode;
+}
+
+const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
+{
+	return omap_current_dss_features->clksrc_names[id];
+}
+
+u32 dss_feat_get_buffer_size_unit(void)
+{
+	return omap_current_dss_features->buffer_size_unit;
+}
+
+u32 dss_feat_get_burst_size_unit(void)
+{
+	return omap_current_dss_features->burst_size_unit;
+}
+
+/* DSS has_feature check */
+bool dss_has_feature(enum dss_feat_id id)
+{
+	int i;
+	const enum dss_feat_id *features = omap_current_dss_features->features;
+	const int num_features = omap_current_dss_features->num_features;
+
+	for (i = 0; i < num_features; i++) {
+		if (features[i] == id)
+			return true;
+	}
+
+	return false;
+}
+
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
+{
+	if (id >= omap_current_dss_features->num_reg_fields)
+		BUG();
+
+	*start = omap_current_dss_features->reg_fields[id].start;
+	*end = omap_current_dss_features->reg_fields[id].end;
+}
+
+bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
+{
+	return omap_current_dss_features->supported_rotation_types & rot_type;
+}
+
+void dss_features_init(enum omapdss_version version)
+{
+	switch (version) {
+	case OMAPDSS_VER_OMAP24xx:
+		omap_current_dss_features = &omap2_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+		omap_current_dss_features = &omap3430_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP3630:
+		omap_current_dss_features = &omap3630_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+		omap_current_dss_features = &omap4430_es1_0_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES2:
+		omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP4:
+		omap_current_dss_features = &omap4_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP5:
+		omap_current_dss_features = &omap5_dss_features;
+		break;
+
+	case OMAPDSS_VER_AM35xx:
+		omap_current_dss_features = &am35xx_dss_features;
+		break;
+
+	default:
+		DSSWARN("Unsupported OMAP version");
+		break;
+	}
+}
diff --git a/drivers/video/fbdev/omap2/dss/dss_features.h b/drivers/video/fbdev/omap2/dss/dss_features.h
new file mode 100644
index 000000000000..e3ef3b714896
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/dss_features.h
@@ -0,0 +1,117 @@
+/*
+ * linux/drivers/video/omap2/dss/dss_features.h
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_FEATURES_H
+#define __OMAP2_DSS_FEATURES_H
+
+#define MAX_DSS_MANAGERS	4
+#define MAX_DSS_OVERLAYS	4
+#define MAX_DSS_LCD_MANAGERS	3
+#define MAX_NUM_DSI		2
+
+/* DSS has feature id */
+enum dss_feat_id {
+	FEAT_LCDENABLEPOL,
+	FEAT_LCDENABLESIGNAL,
+	FEAT_PCKFREEENABLE,
+	FEAT_FUNCGATED,
+	FEAT_MGR_LCD2,
+	FEAT_MGR_LCD3,
+	FEAT_LINEBUFFERSPLIT,
+	FEAT_ROWREPEATENABLE,
+	FEAT_RESIZECONF,
+	/* Independent core clk divider */
+	FEAT_CORE_CLK_DIV,
+	FEAT_LCD_CLK_SRC,
+	/* DSI-PLL power command 0x3 is not working */
+	FEAT_DSI_PLL_PWR_BUG,
+	FEAT_DSI_PLL_FREQSEL,
+	FEAT_DSI_DCS_CMD_CONFIG_VC,
+	FEAT_DSI_VC_OCP_WIDTH,
+	FEAT_DSI_REVERSE_TXCLKESC,
+	FEAT_DSI_GNQ,
+	FEAT_DPI_USES_VDDS_DSI,
+	FEAT_HDMI_CTS_SWMODE,
+	FEAT_HDMI_AUDIO_USE_MCLK,
+	FEAT_HANDLE_UV_SEPARATE,
+	FEAT_ATTR2,
+	FEAT_VENC_REQUIRES_TV_DAC_CLK,
+	FEAT_CPR,
+	FEAT_PRELOAD,
+	FEAT_FIR_COEF_V,
+	FEAT_ALPHA_FIXED_ZORDER,
+	FEAT_ALPHA_FREE_ZORDER,
+	FEAT_FIFO_MERGE,
+	/* An unknown HW bug causing the normal FIFO thresholds not to work */
+	FEAT_OMAP3_DSI_FIFO_BUG,
+	FEAT_BURST_2D,
+	FEAT_DSI_PLL_SELFREQDCO,
+	FEAT_DSI_PLL_REFSEL,
+	FEAT_DSI_PHY_DCC,
+	FEAT_MFLAG,
+};
+
+/* DSS register field id */
+enum dss_feat_reg_field {
+	FEAT_REG_FIRHINC,
+	FEAT_REG_FIRVINC,
+	FEAT_REG_FIFOHIGHTHRESHOLD,
+	FEAT_REG_FIFOLOWTHRESHOLD,
+	FEAT_REG_FIFOSIZE,
+	FEAT_REG_HORIZONTALACCU,
+	FEAT_REG_VERTICALACCU,
+	FEAT_REG_DISPC_CLK_SWITCH,
+	FEAT_REG_DSIPLL_REGN,
+	FEAT_REG_DSIPLL_REGM,
+	FEAT_REG_DSIPLL_REGM_DISPC,
+	FEAT_REG_DSIPLL_REGM_DSI,
+};
+
+enum dss_range_param {
+	FEAT_PARAM_DSS_FCK,
+	FEAT_PARAM_DSS_PCD,
+	FEAT_PARAM_DSIPLL_REGN,
+	FEAT_PARAM_DSIPLL_REGM,
+	FEAT_PARAM_DSIPLL_REGM_DISPC,
+	FEAT_PARAM_DSIPLL_REGM_DSI,
+	FEAT_PARAM_DSIPLL_FINT,
+	FEAT_PARAM_DSIPLL_LPDIV,
+	FEAT_PARAM_DSI_FCK,
+	FEAT_PARAM_DOWNSCALE,
+	FEAT_PARAM_LINEWIDTH,
+};
+
+/* DSS Feature Functions */
+int dss_feat_get_num_wbs(void);
+unsigned long dss_feat_get_param_min(enum dss_range_param param);
+unsigned long dss_feat_get_param_max(enum dss_range_param param);
+enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
+bool dss_feat_color_mode_supported(enum omap_plane plane,
+		enum omap_color_mode color_mode);
+const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
+
+u32 dss_feat_get_buffer_size_unit(void);	/* in bytes */
+u32 dss_feat_get_burst_size_unit(void);		/* in bytes */
+
+bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
+
+bool dss_has_feature(enum dss_feat_id id);
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
+void dss_features_init(enum omapdss_version version);
+#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h
new file mode 100644
index 000000000000..e25681ff5a70
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi.h
@@ -0,0 +1,444 @@
+/*
+ * HDMI driver definition for TI OMAP4 Processor.
+ *
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _HDMI_H
+#define _HDMI_H
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+/* HDMI Wrapper */
+
+#define HDMI_WP_REVISION			0x0
+#define HDMI_WP_SYSCONFIG			0x10
+#define HDMI_WP_IRQSTATUS_RAW			0x24
+#define HDMI_WP_IRQSTATUS			0x28
+#define HDMI_WP_IRQENABLE_SET			0x2C
+#define HDMI_WP_IRQENABLE_CLR			0x30
+#define HDMI_WP_IRQWAKEEN			0x34
+#define HDMI_WP_PWR_CTRL			0x40
+#define HDMI_WP_DEBOUNCE			0x44
+#define HDMI_WP_VIDEO_CFG			0x50
+#define HDMI_WP_VIDEO_SIZE			0x60
+#define HDMI_WP_VIDEO_TIMING_H			0x68
+#define HDMI_WP_VIDEO_TIMING_V			0x6C
+#define HDMI_WP_CLK				0x70
+#define HDMI_WP_AUDIO_CFG			0x80
+#define HDMI_WP_AUDIO_CFG2			0x84
+#define HDMI_WP_AUDIO_CTRL			0x88
+#define HDMI_WP_AUDIO_DATA			0x8C
+
+/* HDMI WP IRQ flags */
+#define HDMI_IRQ_CORE				(1 << 0)
+#define HDMI_IRQ_OCP_TIMEOUT			(1 << 4)
+#define HDMI_IRQ_AUDIO_FIFO_UNDERFLOW		(1 << 8)
+#define HDMI_IRQ_AUDIO_FIFO_OVERFLOW		(1 << 9)
+#define HDMI_IRQ_AUDIO_FIFO_SAMPLE_REQ		(1 << 10)
+#define HDMI_IRQ_VIDEO_VSYNC			(1 << 16)
+#define HDMI_IRQ_VIDEO_FRAME_DONE		(1 << 17)
+#define HDMI_IRQ_PHY_LINE5V_ASSERT		(1 << 24)
+#define HDMI_IRQ_LINK_CONNECT			(1 << 25)
+#define HDMI_IRQ_LINK_DISCONNECT		(1 << 26)
+#define HDMI_IRQ_PLL_LOCK			(1 << 29)
+#define HDMI_IRQ_PLL_UNLOCK			(1 << 30)
+#define HDMI_IRQ_PLL_RECAL			(1 << 31)
+
+/* HDMI PLL */
+
+#define PLLCTRL_PLL_CONTROL			0x0
+#define PLLCTRL_PLL_STATUS			0x4
+#define PLLCTRL_PLL_GO				0x8
+#define PLLCTRL_CFG1				0xC
+#define PLLCTRL_CFG2				0x10
+#define PLLCTRL_CFG3				0x14
+#define PLLCTRL_SSC_CFG1			0x18
+#define PLLCTRL_SSC_CFG2			0x1C
+#define PLLCTRL_CFG4				0x20
+
+/* HDMI PHY */
+
+#define HDMI_TXPHY_TX_CTRL			0x0
+#define HDMI_TXPHY_DIGITAL_CTRL			0x4
+#define HDMI_TXPHY_POWER_CTRL			0x8
+#define HDMI_TXPHY_PAD_CFG_CTRL			0xC
+
+enum hdmi_pll_pwr {
+	HDMI_PLLPWRCMD_ALLOFF = 0,
+	HDMI_PLLPWRCMD_PLLONLY = 1,
+	HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
+	HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
+};
+
+enum hdmi_phy_pwr {
+	HDMI_PHYPWRCMD_OFF = 0,
+	HDMI_PHYPWRCMD_LDOON = 1,
+	HDMI_PHYPWRCMD_TXON = 2
+};
+
+enum hdmi_core_hdmi_dvi {
+	HDMI_DVI = 0,
+	HDMI_HDMI = 1
+};
+
+enum hdmi_clk_refsel {
+	HDMI_REFSEL_PCLK = 0,
+	HDMI_REFSEL_REF1 = 1,
+	HDMI_REFSEL_REF2 = 2,
+	HDMI_REFSEL_SYSCLK = 3
+};
+
+enum hdmi_packing_mode {
+	HDMI_PACK_10b_RGB_YUV444 = 0,
+	HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
+	HDMI_PACK_20b_YUV422 = 2,
+	HDMI_PACK_ALREADYPACKED = 7
+};
+
+enum hdmi_stereo_channels {
+	HDMI_AUDIO_STEREO_NOCHANNELS = 0,
+	HDMI_AUDIO_STEREO_ONECHANNEL = 1,
+	HDMI_AUDIO_STEREO_TWOCHANNELS = 2,
+	HDMI_AUDIO_STEREO_THREECHANNELS = 3,
+	HDMI_AUDIO_STEREO_FOURCHANNELS = 4
+};
+
+enum hdmi_audio_type {
+	HDMI_AUDIO_TYPE_LPCM = 0,
+	HDMI_AUDIO_TYPE_IEC = 1
+};
+
+enum hdmi_audio_justify {
+	HDMI_AUDIO_JUSTIFY_LEFT = 0,
+	HDMI_AUDIO_JUSTIFY_RIGHT = 1
+};
+
+enum hdmi_audio_sample_order {
+	HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0,
+	HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1
+};
+
+enum hdmi_audio_samples_perword {
+	HDMI_AUDIO_ONEWORD_ONESAMPLE = 0,
+	HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
+};
+
+enum hdmi_audio_sample_size {
+	HDMI_AUDIO_SAMPLE_16BITS = 0,
+	HDMI_AUDIO_SAMPLE_24BITS = 1
+};
+
+enum hdmi_audio_transf_mode {
+	HDMI_AUDIO_TRANSF_DMA = 0,
+	HDMI_AUDIO_TRANSF_IRQ = 1
+};
+
+enum hdmi_audio_blk_strt_end_sig {
+	HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0,
+	HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1
+};
+
+enum hdmi_core_audio_layout {
+	HDMI_AUDIO_LAYOUT_2CH = 0,
+	HDMI_AUDIO_LAYOUT_8CH = 1
+};
+
+enum hdmi_core_cts_mode {
+	HDMI_AUDIO_CTS_MODE_HW = 0,
+	HDMI_AUDIO_CTS_MODE_SW = 1
+};
+
+enum hdmi_audio_mclk_mode {
+	HDMI_AUDIO_MCLK_128FS = 0,
+	HDMI_AUDIO_MCLK_256FS = 1,
+	HDMI_AUDIO_MCLK_384FS = 2,
+	HDMI_AUDIO_MCLK_512FS = 3,
+	HDMI_AUDIO_MCLK_768FS = 4,
+	HDMI_AUDIO_MCLK_1024FS = 5,
+	HDMI_AUDIO_MCLK_1152FS = 6,
+	HDMI_AUDIO_MCLK_192FS = 7
+};
+
+/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
+enum hdmi_core_infoframe {
+	HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
+	HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
+	HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2,
+	HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0,
+	HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON =  1,
+	HDMI_INFOFRAME_AVI_DB1B_NO = 0,
+	HDMI_INFOFRAME_AVI_DB1B_VERT = 1,
+	HDMI_INFOFRAME_AVI_DB1B_HORI = 2,
+	HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3,
+	HDMI_INFOFRAME_AVI_DB1S_0 = 0,
+	HDMI_INFOFRAME_AVI_DB1S_1 = 1,
+	HDMI_INFOFRAME_AVI_DB1S_2 = 2,
+	HDMI_INFOFRAME_AVI_DB2C_NO = 0,
+	HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1,
+	HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2,
+	HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3,
+	HDMI_INFOFRAME_AVI_DB2M_NO = 0,
+	HDMI_INFOFRAME_AVI_DB2M_43 = 1,
+	HDMI_INFOFRAME_AVI_DB2M_169 = 2,
+	HDMI_INFOFRAME_AVI_DB2R_SAME = 8,
+	HDMI_INFOFRAME_AVI_DB2R_43 = 9,
+	HDMI_INFOFRAME_AVI_DB2R_169 = 10,
+	HDMI_INFOFRAME_AVI_DB2R_149 = 11,
+	HDMI_INFOFRAME_AVI_DB3ITC_NO = 0,
+	HDMI_INFOFRAME_AVI_DB3ITC_YES = 1,
+	HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0,
+	HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1,
+	HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0,
+	HDMI_INFOFRAME_AVI_DB3Q_LR = 1,
+	HDMI_INFOFRAME_AVI_DB3Q_FR = 2,
+	HDMI_INFOFRAME_AVI_DB3SC_NO = 0,
+	HDMI_INFOFRAME_AVI_DB3SC_HORI = 1,
+	HDMI_INFOFRAME_AVI_DB3SC_VERT = 2,
+	HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3,
+	HDMI_INFOFRAME_AVI_DB5PR_NO = 0,
+	HDMI_INFOFRAME_AVI_DB5PR_2 = 1,
+	HDMI_INFOFRAME_AVI_DB5PR_3 = 2,
+	HDMI_INFOFRAME_AVI_DB5PR_4 = 3,
+	HDMI_INFOFRAME_AVI_DB5PR_5 = 4,
+	HDMI_INFOFRAME_AVI_DB5PR_6 = 5,
+	HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
+	HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
+	HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
+	HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
+};
+
+struct hdmi_cm {
+	int	code;
+	int	mode;
+};
+
+struct hdmi_video_format {
+	enum hdmi_packing_mode	packing_mode;
+	u32			y_res;	/* Line per panel */
+	u32			x_res;	/* pixel per line */
+};
+
+struct hdmi_config {
+	struct omap_video_timings timings;
+	struct hdmi_cm cm;
+};
+
+/* HDMI PLL structure */
+struct hdmi_pll_info {
+	u16 regn;
+	u16 regm;
+	u32 regmf;
+	u16 regm2;
+	u16 regsd;
+	u16 dcofreq;
+	enum hdmi_clk_refsel refsel;
+};
+
+struct hdmi_audio_format {
+	enum hdmi_stereo_channels		stereo_channels;
+	u8					active_chnnls_msk;
+	enum hdmi_audio_type			type;
+	enum hdmi_audio_justify			justification;
+	enum hdmi_audio_sample_order		sample_order;
+	enum hdmi_audio_samples_perword		samples_per_word;
+	enum hdmi_audio_sample_size		sample_size;
+	enum hdmi_audio_blk_strt_end_sig	en_sig_blk_strt_end;
+};
+
+struct hdmi_audio_dma {
+	u8				transfer_size;
+	u8				block_size;
+	enum hdmi_audio_transf_mode	mode;
+	u16				fifo_threshold;
+};
+
+struct hdmi_core_audio_i2s_config {
+	u8 in_length_bits;
+	u8 justification;
+	u8 sck_edge_mode;
+	u8 vbit;
+	u8 direction;
+	u8 shift;
+	u8 active_sds;
+};
+
+struct hdmi_core_audio_config {
+	struct hdmi_core_audio_i2s_config	i2s_cfg;
+	struct snd_aes_iec958			*iec60958_cfg;
+	bool					fs_override;
+	u32					n;
+	u32					cts;
+	u32					aud_par_busclk;
+	enum hdmi_core_audio_layout		layout;
+	enum hdmi_core_cts_mode			cts_mode;
+	bool					use_mclk;
+	enum hdmi_audio_mclk_mode		mclk_mode;
+	bool					en_acr_pkt;
+	bool					en_dsd_audio;
+	bool					en_parallel_aud_input;
+	bool					en_spdif;
+};
+
+/*
+ * Refer to section 8.2 in HDMI 1.3 specification for
+ * details about infoframe databytes
+ */
+struct hdmi_core_infoframe_avi {
+	/* Y0, Y1 rgb,yCbCr */
+	u8	db1_format;
+	/* A0  Active information Present */
+	u8	db1_active_info;
+	/* B0, B1 Bar info data valid */
+	u8	db1_bar_info_dv;
+	/* S0, S1 scan information */
+	u8	db1_scan_info;
+	/* C0, C1 colorimetry */
+	u8	db2_colorimetry;
+	/* M0, M1 Aspect ratio (4:3, 16:9) */
+	u8	db2_aspect_ratio;
+	/* R0...R3 Active format aspect ratio */
+	u8	db2_active_fmt_ar;
+	/* ITC IT content. */
+	u8	db3_itc;
+	/* EC0, EC1, EC2 Extended colorimetry */
+	u8	db3_ec;
+	/* Q1, Q0 Quantization range */
+	u8	db3_q_range;
+	/* SC1, SC0 Non-uniform picture scaling */
+	u8	db3_nup_scaling;
+	/* VIC0..6 Video format identification */
+	u8	db4_videocode;
+	/* PR0..PR3 Pixel repetition factor */
+	u8	db5_pixel_repeat;
+	/* Line number end of top bar */
+	u16	db6_7_line_eoftop;
+	/* Line number start of bottom bar */
+	u16	db8_9_line_sofbottom;
+	/* Pixel number end of left bar */
+	u16	db10_11_pixel_eofleft;
+	/* Pixel number start of right bar */
+	u16	db12_13_pixel_sofright;
+};
+
+struct hdmi_wp_data {
+	void __iomem *base;
+};
+
+struct hdmi_pll_data {
+	void __iomem *base;
+
+	struct hdmi_pll_info info;
+};
+
+struct hdmi_phy_data {
+	void __iomem *base;
+
+	int irq;
+};
+
+struct hdmi_core_data {
+	void __iomem *base;
+
+	struct hdmi_core_infoframe_avi avi_cfg;
+};
+
+static inline void hdmi_write_reg(void __iomem *base_addr, const u16 idx,
+		u32 val)
+{
+	__raw_writel(val, base_addr + idx);
+}
+
+static inline u32 hdmi_read_reg(void __iomem *base_addr, const u16 idx)
+{
+	return __raw_readl(base_addr + idx);
+}
+
+#define REG_FLD_MOD(base, idx, val, start, end) \
+	hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
+							val, start, end))
+#define REG_GET(base, idx, start, end) \
+	FLD_GET(hdmi_read_reg(base, idx), start, end)
+
+static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
+		const u32 idx, int b2, int b1, u32 val)
+{
+	u32 t = 0, v;
+	while (val != (v = REG_GET(base_addr, idx, b2, b1))) {
+		if (t++ > 10000)
+			return v;
+		udelay(1);
+	}
+	return v;
+}
+
+/* HDMI wrapper funcs */
+int hdmi_wp_video_start(struct hdmi_wp_data *wp);
+void hdmi_wp_video_stop(struct hdmi_wp_data *wp);
+void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s);
+u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp);
+void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus);
+void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask);
+void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask);
+int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val);
+int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val);
+void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
+		struct hdmi_video_format *video_fmt);
+void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
+		struct omap_video_timings *timings);
+void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
+		struct omap_video_timings *timings);
+void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
+		struct omap_video_timings *timings, struct hdmi_config *param);
+int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
+
+/* HDMI PLL funcs */
+int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
+void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
+void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
+void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy);
+int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll);
+
+/* HDMI PHY funcs */
+int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
+		struct hdmi_config *cfg);
+void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp);
+void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
+int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
+
+/* HDMI common funcs */
+const struct hdmi_config *hdmi_default_timing(void);
+const struct hdmi_config *hdmi_get_timings(int mode, int code);
+struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing);
+
+#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
+int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
+int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
+int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
+void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
+		struct hdmi_audio_format *aud_fmt);
+void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
+		struct hdmi_audio_dma *aud_dma);
+static inline bool hdmi_mode_has_audio(int mode)
+{
+	return mode == HDMI_HDMI ? true : false;
+}
+#endif
+#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c
new file mode 100644
index 000000000000..f5f7944a1fd1
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi4.c
@@ -0,0 +1,703 @@
+/*
+ * HDMI interface DSS driver for TI's OMAP4 family of SoCs.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Yong Zhi
+ *	Mythri pk <mythripk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "HDMI"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <video/omapdss.h>
+
+#include "hdmi4_core.h"
+#include "dss.h"
+#include "dss_features.h"
+
+static struct {
+	struct mutex lock;
+	struct platform_device *pdev;
+
+	struct hdmi_wp_data	wp;
+	struct hdmi_pll_data	pll;
+	struct hdmi_phy_data	phy;
+	struct hdmi_core_data	core;
+
+	struct hdmi_config cfg;
+
+	struct clk *sys_clk;
+	struct regulator *vdda_hdmi_dac_reg;
+
+	bool core_enabled;
+
+	struct omap_dss_device output;
+} hdmi;
+
+static int hdmi_runtime_get(void)
+{
+	int r;
+
+	DSSDBG("hdmi_runtime_get\n");
+
+	r = pm_runtime_get_sync(&hdmi.pdev->dev);
+	WARN_ON(r < 0);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+static void hdmi_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("hdmi_runtime_put\n");
+
+	r = pm_runtime_put_sync(&hdmi.pdev->dev);
+	WARN_ON(r < 0 && r != -ENOSYS);
+}
+
+static int hdmi_init_regulator(void)
+{
+	struct regulator *reg;
+
+	if (hdmi.vdda_hdmi_dac_reg != NULL)
+		return 0;
+
+	reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
+
+	if (IS_ERR(reg)) {
+		if (PTR_ERR(reg) != -EPROBE_DEFER)
+			DSSERR("can't get VDDA regulator\n");
+		return PTR_ERR(reg);
+	}
+
+	hdmi.vdda_hdmi_dac_reg = reg;
+
+	return 0;
+}
+
+static int hdmi_power_on_core(struct omap_dss_device *dssdev)
+{
+	int r;
+
+	r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
+	if (r)
+		return r;
+
+	r = hdmi_runtime_get();
+	if (r)
+		goto err_runtime_get;
+
+	/* Make selection of HDMI in DSS */
+	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
+
+	hdmi.core_enabled = true;
+
+	return 0;
+
+err_runtime_get:
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+
+	return r;
+}
+
+static void hdmi_power_off_core(struct omap_dss_device *dssdev)
+{
+	hdmi.core_enabled = false;
+
+	hdmi_runtime_put();
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+}
+
+static int hdmi_power_on_full(struct omap_dss_device *dssdev)
+{
+	int r;
+	struct omap_video_timings *p;
+	struct omap_overlay_manager *mgr = hdmi.output.manager;
+	unsigned long phy;
+
+	r = hdmi_power_on_core(dssdev);
+	if (r)
+		return r;
+
+	p = &hdmi.cfg.timings;
+
+	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
+
+	/* the functions below use kHz pixel clock. TODO: change to Hz */
+	phy = p->pixelclock / 1000;
+
+	hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
+
+	/* config the PLL and PHY hdmi_set_pll_pwrfirst */
+	r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
+	if (r) {
+		DSSDBG("Failed to lock PLL\n");
+		goto err_pll_enable;
+	}
+
+	r = hdmi_phy_enable(&hdmi.phy, &hdmi.wp, &hdmi.cfg);
+	if (r) {
+		DSSDBG("Failed to start PHY\n");
+		goto err_phy_enable;
+	}
+
+	hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
+
+	/* bypass TV gamma table */
+	dispc_enable_gamma_table(0);
+
+	/* tv size */
+	dss_mgr_set_timings(mgr, p);
+
+	r = hdmi_wp_video_start(&hdmi.wp);
+	if (r)
+		goto err_vid_enable;
+
+	r = dss_mgr_enable(mgr);
+	if (r)
+		goto err_mgr_enable;
+
+	return 0;
+
+err_mgr_enable:
+	hdmi_wp_video_stop(&hdmi.wp);
+err_vid_enable:
+	hdmi_phy_disable(&hdmi.phy, &hdmi.wp);
+err_phy_enable:
+	hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
+err_pll_enable:
+	hdmi_power_off_core(dssdev);
+	return -EIO;
+}
+
+static void hdmi_power_off_full(struct omap_dss_device *dssdev)
+{
+	struct omap_overlay_manager *mgr = hdmi.output.manager;
+
+	dss_mgr_disable(mgr);
+
+	hdmi_wp_video_stop(&hdmi.wp);
+	hdmi_phy_disable(&hdmi.phy, &hdmi.wp);
+	hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
+
+	hdmi_power_off_core(dssdev);
+}
+
+static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
+					struct omap_video_timings *timings)
+{
+	struct omap_dss_device *out = &hdmi.output;
+
+	if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct hdmi_cm cm;
+	const struct hdmi_config *t;
+
+	mutex_lock(&hdmi.lock);
+
+	cm = hdmi_get_code(timings);
+	hdmi.cfg.cm = cm;
+
+	t = hdmi_get_timings(cm.mode, cm.code);
+	if (t != NULL) {
+		hdmi.cfg = *t;
+
+		dispc_set_tv_pclk(t->timings.pixelclock);
+	} else {
+		hdmi.cfg.timings = *timings;
+		hdmi.cfg.cm.code = 0;
+		hdmi.cfg.cm.mode = HDMI_DVI;
+
+		dispc_set_tv_pclk(timings->pixelclock);
+	}
+
+	DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ?
+			"DVI" : "HDMI", hdmi.cfg.cm.code);
+
+	mutex_unlock(&hdmi.lock);
+}
+
+static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	const struct hdmi_config *cfg;
+	struct hdmi_cm cm = hdmi.cfg.cm;
+
+	cfg = hdmi_get_timings(cm.mode, cm.code);
+	if (cfg == NULL)
+		cfg = hdmi_default_timing();
+
+	memcpy(timings, &cfg->timings, sizeof(cfg->timings));
+}
+
+static void hdmi_dump_regs(struct seq_file *s)
+{
+	mutex_lock(&hdmi.lock);
+
+	if (hdmi_runtime_get()) {
+		mutex_unlock(&hdmi.lock);
+		return;
+	}
+
+	hdmi_wp_dump(&hdmi.wp, s);
+	hdmi_pll_dump(&hdmi.pll, s);
+	hdmi_phy_dump(&hdmi.phy, s);
+	hdmi4_core_dump(&hdmi.core, s);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+}
+
+static int read_edid(u8 *buf, int len)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_runtime_get();
+	BUG_ON(r);
+
+	r = hdmi4_read_edid(&hdmi.core,  buf, len);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+
+	return r;
+}
+
+static int hdmi_display_enable(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_device *out = &hdmi.output;
+	int r = 0;
+
+	DSSDBG("ENTER hdmi_display_enable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	if (out == NULL || out->manager == NULL) {
+		DSSERR("failed to enable display: no output/manager\n");
+		r = -ENODEV;
+		goto err0;
+	}
+
+	r = hdmi_power_on_full(dssdev);
+	if (r) {
+		DSSERR("failed to power on device\n");
+		goto err0;
+	}
+
+	mutex_unlock(&hdmi.lock);
+	return 0;
+
+err0:
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+static void hdmi_display_disable(struct omap_dss_device *dssdev)
+{
+	DSSDBG("Enter hdmi_display_disable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	hdmi_power_off_full(dssdev);
+
+	mutex_unlock(&hdmi.lock);
+}
+
+static int hdmi_core_enable(struct omap_dss_device *dssdev)
+{
+	int r = 0;
+
+	DSSDBG("ENTER omapdss_hdmi_core_enable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_power_on_core(dssdev);
+	if (r) {
+		DSSERR("failed to power on device\n");
+		goto err0;
+	}
+
+	mutex_unlock(&hdmi.lock);
+	return 0;
+
+err0:
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+static void hdmi_core_disable(struct omap_dss_device *dssdev)
+{
+	DSSDBG("Enter omapdss_hdmi_core_disable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	hdmi_power_off_core(dssdev);
+
+	mutex_unlock(&hdmi.lock);
+}
+
+static int hdmi_get_clocks(struct platform_device *pdev)
+{
+	struct clk *clk;
+
+	clk = devm_clk_get(&pdev->dev, "sys_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get sys_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	hdmi.sys_clk = clk;
+
+	return 0;
+}
+
+static int hdmi_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct omap_overlay_manager *mgr;
+	int r;
+
+	r = hdmi_init_regulator();
+	if (r)
+		return r;
+
+	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
+	if (!mgr)
+		return -ENODEV;
+
+	r = dss_mgr_connect(mgr, dssdev);
+	if (r)
+		return r;
+
+	r = omapdss_output_set_device(dssdev, dst);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dst->name);
+		dss_mgr_disconnect(mgr, dssdev);
+		return r;
+	}
+
+	return 0;
+}
+
+static void hdmi_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	WARN_ON(dst != dssdev->dst);
+
+	if (dst != dssdev->dst)
+		return;
+
+	omapdss_output_unset_device(dssdev);
+
+	if (dssdev->manager)
+		dss_mgr_disconnect(dssdev->manager, dssdev);
+}
+
+static int hdmi_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	bool need_enable;
+	int r;
+
+	need_enable = hdmi.core_enabled == false;
+
+	if (need_enable) {
+		r = hdmi_core_enable(dssdev);
+		if (r)
+			return r;
+	}
+
+	r = read_edid(edid, len);
+
+	if (need_enable)
+		hdmi_core_disable(dssdev);
+
+	return r;
+}
+
+#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
+static int hdmi_audio_enable(struct omap_dss_device *dssdev)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
+		r = -EPERM;
+		goto err;
+	}
+
+	r = hdmi_wp_audio_enable(&hdmi.wp, true);
+	if (r)
+		goto err;
+
+	mutex_unlock(&hdmi.lock);
+	return 0;
+
+err:
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+static void hdmi_audio_disable(struct omap_dss_device *dssdev)
+{
+	hdmi_wp_audio_enable(&hdmi.wp, false);
+}
+
+static int hdmi_audio_start(struct omap_dss_device *dssdev)
+{
+	return hdmi4_audio_start(&hdmi.core, &hdmi.wp);
+}
+
+static void hdmi_audio_stop(struct omap_dss_device *dssdev)
+{
+	hdmi4_audio_stop(&hdmi.core, &hdmi.wp);
+}
+
+static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
+{
+	bool r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
+
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+static int hdmi_audio_config(struct omap_dss_device *dssdev,
+		struct omap_dss_audio *audio)
+{
+	int r;
+	u32 pclk = hdmi.cfg.timings.pixelclock;
+
+	mutex_lock(&hdmi.lock);
+
+	if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
+		r = -EPERM;
+		goto err;
+	}
+
+	r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
+	if (r)
+		goto err;
+
+	mutex_unlock(&hdmi.lock);
+	return 0;
+
+err:
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+#else
+static int hdmi_audio_enable(struct omap_dss_device *dssdev)
+{
+	return -EPERM;
+}
+
+static void hdmi_audio_disable(struct omap_dss_device *dssdev)
+{
+}
+
+static int hdmi_audio_start(struct omap_dss_device *dssdev)
+{
+	return -EPERM;
+}
+
+static void hdmi_audio_stop(struct omap_dss_device *dssdev)
+{
+}
+
+static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
+{
+	return false;
+}
+
+static int hdmi_audio_config(struct omap_dss_device *dssdev,
+		struct omap_dss_audio *audio)
+{
+	return -EPERM;
+}
+#endif
+
+static const struct omapdss_hdmi_ops hdmi_ops = {
+	.connect		= hdmi_connect,
+	.disconnect		= hdmi_disconnect,
+
+	.enable			= hdmi_display_enable,
+	.disable		= hdmi_display_disable,
+
+	.check_timings		= hdmi_display_check_timing,
+	.set_timings		= hdmi_display_set_timing,
+	.get_timings		= hdmi_display_get_timings,
+
+	.read_edid		= hdmi_read_edid,
+
+	.audio_enable		= hdmi_audio_enable,
+	.audio_disable		= hdmi_audio_disable,
+	.audio_start		= hdmi_audio_start,
+	.audio_stop		= hdmi_audio_stop,
+	.audio_supported	= hdmi_audio_supported,
+	.audio_config		= hdmi_audio_config,
+};
+
+static void hdmi_init_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &hdmi.output;
+
+	out->dev = &pdev->dev;
+	out->id = OMAP_DSS_OUTPUT_HDMI;
+	out->output_type = OMAP_DISPLAY_TYPE_HDMI;
+	out->name = "hdmi.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
+	out->ops.hdmi = &hdmi_ops;
+	out->owner = THIS_MODULE;
+
+	omapdss_register_output(out);
+}
+
+static void __exit hdmi_uninit_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &hdmi.output;
+
+	omapdss_unregister_output(out);
+}
+
+/* HDMI HW IP initialisation */
+static int omapdss_hdmihw_probe(struct platform_device *pdev)
+{
+	int r;
+
+	hdmi.pdev = pdev;
+
+	mutex_init(&hdmi.lock);
+
+	r = hdmi_wp_init(pdev, &hdmi.wp);
+	if (r)
+		return r;
+
+	r = hdmi_pll_init(pdev, &hdmi.pll);
+	if (r)
+		return r;
+
+	r = hdmi_phy_init(pdev, &hdmi.phy);
+	if (r)
+		return r;
+
+	r = hdmi4_core_init(pdev, &hdmi.core);
+	if (r)
+		return r;
+
+	r = hdmi_get_clocks(pdev);
+	if (r) {
+		DSSERR("can't get clocks\n");
+		return r;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	hdmi_init_output(pdev);
+
+	dss_debugfs_create_file("hdmi", hdmi_dump_regs);
+
+	return 0;
+}
+
+static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
+{
+	hdmi_uninit_output(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static int hdmi_runtime_suspend(struct device *dev)
+{
+	clk_disable_unprepare(hdmi.sys_clk);
+
+	dispc_runtime_put();
+
+	return 0;
+}
+
+static int hdmi_runtime_resume(struct device *dev)
+{
+	int r;
+
+	r = dispc_runtime_get();
+	if (r < 0)
+		return r;
+
+	clk_prepare_enable(hdmi.sys_clk);
+
+	return 0;
+}
+
+static const struct dev_pm_ops hdmi_pm_ops = {
+	.runtime_suspend = hdmi_runtime_suspend,
+	.runtime_resume = hdmi_runtime_resume,
+};
+
+static const struct of_device_id hdmi_of_match[] = {
+	{ .compatible = "ti,omap4-hdmi", },
+	{},
+};
+
+static struct platform_driver omapdss_hdmihw_driver = {
+	.probe		= omapdss_hdmihw_probe,
+	.remove         = __exit_p(omapdss_hdmihw_remove),
+	.driver         = {
+		.name   = "omapdss_hdmi",
+		.owner  = THIS_MODULE,
+		.pm	= &hdmi_pm_ops,
+		.of_match_table = hdmi_of_match,
+	},
+};
+
+int __init hdmi4_init_platform_driver(void)
+{
+	return platform_driver_register(&omapdss_hdmihw_driver);
+}
+
+void __exit hdmi4_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omapdss_hdmihw_driver);
+}
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
new file mode 100644
index 000000000000..2eb04dcf807c
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
@@ -0,0 +1,1036 @@
+/*
+ * ti_hdmi_4xxx_ip.c
+ *
+ * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Yong Zhi
+ *	Mythri pk <mythripk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "HDMICORE"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
+#include <sound/asound.h>
+#include <sound/asoundef.h>
+#endif
+
+#include "hdmi4_core.h"
+#include "dss_features.h"
+
+#define HDMI_CORE_AV		0x500
+
+static inline void __iomem *hdmi_av_base(struct hdmi_core_data *core)
+{
+	return core->base + HDMI_CORE_AV;
+}
+
+static int hdmi_core_ddc_init(struct hdmi_core_data *core)
+{
+	void __iomem *base = core->base;
+
+	/* Turn on CLK for DDC */
+	REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0);
+
+	/* IN_PROG */
+	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
+		/* Abort transaction */
+		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0);
+		/* IN_PROG */
+		if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+					4, 4, 0) != 0) {
+			DSSERR("Timeout aborting DDC transaction\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	/* Clk SCL Devices */
+	REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+				4, 4, 0) != 0) {
+		DSSERR("Timeout starting SCL clock\n");
+		return -ETIMEDOUT;
+	}
+
+	/* Clear FIFO */
+	REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+				4, 4, 0) != 0) {
+		DSSERR("Timeout clearing DDC fifo\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
+		u8 *pedid, int ext)
+{
+	void __iomem *base = core->base;
+	u32 i;
+	char checksum;
+	u32 offset = 0;
+
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+				4, 4, 0) != 0) {
+		DSSERR("Timeout waiting DDC to be ready\n");
+		return -ETIMEDOUT;
+	}
+
+	if (ext % 2 != 0)
+		offset = 0x80;
+
+	/* Load Segment Address Register */
+	REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
+
+	/* Load Slave Address Register */
+	REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
+
+	/* Load Offset Address Register */
+	REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
+
+	/* Load Byte Count */
+	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
+
+	/* Set DDC_CMD */
+	if (ext)
+		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
+	else
+		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
+
+	/* HDMI_CORE_DDC_STATUS_BUS_LOW */
+	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
+		DSSERR("I2C Bus Low?\n");
+		return -EIO;
+	}
+	/* HDMI_CORE_DDC_STATUS_NO_ACK */
+	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
+		DSSERR("I2C No Ack\n");
+		return -EIO;
+	}
+
+	for (i = 0; i < 0x80; ++i) {
+		int t;
+
+		/* IN_PROG */
+		if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
+			DSSERR("operation stopped when reading edid\n");
+			return -EIO;
+		}
+
+		t = 0;
+		/* FIFO_EMPTY */
+		while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
+			if (t++ > 10000) {
+				DSSERR("timeout reading edid\n");
+				return -ETIMEDOUT;
+			}
+			udelay(1);
+		}
+
+		pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
+	}
+
+	checksum = 0;
+	for (i = 0; i < 0x80; ++i)
+		checksum += pedid[i];
+
+	if (checksum != 0) {
+		DSSERR("E-EDID checksum failed!!\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len)
+{
+	int r, l;
+
+	if (len < 128)
+		return -EINVAL;
+
+	r = hdmi_core_ddc_init(core);
+	if (r)
+		return r;
+
+	r = hdmi_core_ddc_edid(core, edid, 0);
+	if (r)
+		return r;
+
+	l = 128;
+
+	if (len >= 128 * 2 && edid[0x7e] > 0) {
+		r = hdmi_core_ddc_edid(core, edid + 0x80, 1);
+		if (r)
+			return r;
+		l += 128;
+	}
+
+	return l;
+}
+
+static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
+			struct hdmi_core_infoframe_avi *avi_cfg,
+			struct hdmi_core_packet_enable_repeat *repeat_cfg)
+{
+	DSSDBG("Enter hdmi_core_init\n");
+
+	/* video core */
+	video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
+	video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
+	video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
+	video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
+	video_cfg->hdmi_dvi = HDMI_DVI;
+	video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
+
+	/* info frame */
+	avi_cfg->db1_format = 0;
+	avi_cfg->db1_active_info = 0;
+	avi_cfg->db1_bar_info_dv = 0;
+	avi_cfg->db1_scan_info = 0;
+	avi_cfg->db2_colorimetry = 0;
+	avi_cfg->db2_aspect_ratio = 0;
+	avi_cfg->db2_active_fmt_ar = 0;
+	avi_cfg->db3_itc = 0;
+	avi_cfg->db3_ec = 0;
+	avi_cfg->db3_q_range = 0;
+	avi_cfg->db3_nup_scaling = 0;
+	avi_cfg->db4_videocode = 0;
+	avi_cfg->db5_pixel_repeat = 0;
+	avi_cfg->db6_7_line_eoftop = 0;
+	avi_cfg->db8_9_line_sofbottom = 0;
+	avi_cfg->db10_11_pixel_eofleft = 0;
+	avi_cfg->db12_13_pixel_sofright = 0;
+
+	/* packet enable and repeat */
+	repeat_cfg->audio_pkt = 0;
+	repeat_cfg->audio_pkt_repeat = 0;
+	repeat_cfg->avi_infoframe = 0;
+	repeat_cfg->avi_infoframe_repeat = 0;
+	repeat_cfg->gen_cntrl_pkt = 0;
+	repeat_cfg->gen_cntrl_pkt_repeat = 0;
+	repeat_cfg->generic_pkt = 0;
+	repeat_cfg->generic_pkt_repeat = 0;
+}
+
+static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
+{
+	DSSDBG("Enter hdmi_core_powerdown_disable\n");
+	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_release(struct hdmi_core_data *core)
+{
+	DSSDBG("Enter hdmi_core_swreset_release\n");
+	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_assert(struct hdmi_core_data *core)
+{
+	DSSDBG("Enter hdmi_core_swreset_assert\n");
+	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x1, 0, 0);
+}
+
+/* HDMI_CORE_VIDEO_CONFIG */
+static void hdmi_core_video_config(struct hdmi_core_data *core,
+				struct hdmi_core_video_config *cfg)
+{
+	u32 r = 0;
+	void __iomem *core_sys_base = core->base;
+	void __iomem *core_av_base = hdmi_av_base(core);
+
+	/* sys_ctrl1 default configuration not tunable */
+	r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1);
+	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
+	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
+	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS, 2, 2);
+	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE, 1, 1);
+	hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1, r);
+
+	REG_FLD_MOD(core_sys_base,
+			HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
+
+	/* Vid_Mode */
+	r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE);
+
+	/* dither truncation configuration */
+	if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
+		r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
+		r = FLD_MOD(r, 1, 5, 5);
+	} else {
+		r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
+		r = FLD_MOD(r, 0, 5, 5);
+	}
+	hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r);
+
+	/* HDMI_Ctrl */
+	r = hdmi_read_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL);
+	r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
+	r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
+	r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
+	hdmi_write_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL, r);
+
+	/* TMDS_CTRL */
+	REG_FLD_MOD(core_sys_base,
+			HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
+}
+
+static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core)
+{
+	u32 val;
+	char sum = 0, checksum = 0;
+	void __iomem *av_base = hdmi_av_base(core);
+	struct hdmi_core_infoframe_avi info_avi = core->avi_cfg;
+
+	sum += 0x82 + 0x002 + 0x00D;
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D);
+
+	val = (info_avi.db1_format << 5) |
+		(info_avi.db1_active_info << 4) |
+		(info_avi.db1_bar_info_dv << 2) |
+		(info_avi.db1_scan_info);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val);
+	sum += val;
+
+	val = (info_avi.db2_colorimetry << 6) |
+		(info_avi.db2_aspect_ratio << 4) |
+		(info_avi.db2_active_fmt_ar);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val);
+	sum += val;
+
+	val = (info_avi.db3_itc << 7) |
+		(info_avi.db3_ec << 4) |
+		(info_avi.db3_q_range << 2) |
+		(info_avi.db3_nup_scaling);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
+	sum += val;
+
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
+					info_avi.db4_videocode);
+	sum += info_avi.db4_videocode;
+
+	val = info_avi.db5_pixel_repeat;
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
+	sum += val;
+
+	val = info_avi.db6_7_line_eoftop & 0x00FF;
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
+	sum += val;
+
+	val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
+	sum += val;
+
+	val = info_avi.db8_9_line_sofbottom & 0x00FF;
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
+	sum += val;
+
+	val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
+	sum += val;
+
+	val = info_avi.db10_11_pixel_eofleft & 0x00FF;
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
+	sum += val;
+
+	val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
+	sum += val;
+
+	val = info_avi.db12_13_pixel_sofright & 0x00FF;
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
+	sum += val;
+
+	val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
+	sum += val;
+
+	checksum = 0x100 - sum;
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
+}
+
+static void hdmi_core_av_packet_config(struct hdmi_core_data *core,
+		struct hdmi_core_packet_enable_repeat repeat_cfg)
+{
+	/* enable/repeat the infoframe */
+	hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL1,
+		(repeat_cfg.audio_pkt << 5) |
+		(repeat_cfg.audio_pkt_repeat << 4) |
+		(repeat_cfg.avi_infoframe << 1) |
+		(repeat_cfg.avi_infoframe_repeat));
+
+	/* enable/repeat the packet */
+	hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL2,
+		(repeat_cfg.gen_cntrl_pkt << 3) |
+		(repeat_cfg.gen_cntrl_pkt_repeat << 2) |
+		(repeat_cfg.generic_pkt << 1) |
+		(repeat_cfg.generic_pkt_repeat));
+}
+
+void hdmi4_configure(struct hdmi_core_data *core,
+	struct hdmi_wp_data *wp, struct hdmi_config *cfg)
+{
+	/* HDMI */
+	struct omap_video_timings video_timing;
+	struct hdmi_video_format video_format;
+	/* HDMI core */
+	struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg;
+	struct hdmi_core_video_config v_core_cfg;
+	struct hdmi_core_packet_enable_repeat repeat_cfg;
+
+	hdmi_core_init(&v_core_cfg, avi_cfg, &repeat_cfg);
+
+	hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
+
+	hdmi_wp_video_config_timing(wp, &video_timing);
+
+	/* video config */
+	video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
+
+	hdmi_wp_video_config_format(wp, &video_format);
+
+	hdmi_wp_video_config_interface(wp, &video_timing);
+
+	/*
+	 * configure core video part
+	 * set software reset in the core
+	 */
+	hdmi_core_swreset_assert(core);
+
+	/* power down off */
+	hdmi_core_powerdown_disable(core);
+
+	v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
+	v_core_cfg.hdmi_dvi = cfg->cm.mode;
+
+	hdmi_core_video_config(core, &v_core_cfg);
+
+	/* release software reset in the core */
+	hdmi_core_swreset_release(core);
+
+	/*
+	 * configure packet
+	 * info frame video see doc CEA861-D page 65
+	 */
+	avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
+	avi_cfg->db1_active_info =
+			HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
+	avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
+	avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
+	avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
+	avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
+	avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
+	avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
+	avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
+	avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
+	avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
+	avi_cfg->db4_videocode = cfg->cm.code;
+	avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
+	avi_cfg->db6_7_line_eoftop = 0;
+	avi_cfg->db8_9_line_sofbottom = 0;
+	avi_cfg->db10_11_pixel_eofleft = 0;
+	avi_cfg->db12_13_pixel_sofright = 0;
+
+	hdmi_core_aux_infoframe_avi_config(core);
+
+	/* enable/repeat the infoframe */
+	repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
+	repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
+	/* wakeup */
+	repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
+	repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
+	hdmi_core_av_packet_config(core, repeat_cfg);
+}
+
+void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s)
+{
+	int i;
+
+#define CORE_REG(i, name) name(i)
+#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
+		hdmi_read_reg(core->base, r))
+#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
+		hdmi_read_reg(hdmi_av_base(core), r))
+#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
+		(i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
+		hdmi_read_reg(hdmi_av_base(core), CORE_REG(i, r)))
+
+	DUMPCORE(HDMI_CORE_SYS_VND_IDL);
+	DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
+	DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
+	DUMPCORE(HDMI_CORE_SYS_DEV_REV);
+	DUMPCORE(HDMI_CORE_SYS_SRST);
+	DUMPCORE(HDMI_CORE_SYS_SYS_CTRL1);
+	DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
+	DUMPCORE(HDMI_CORE_SYS_SYS_CTRL3);
+	DUMPCORE(HDMI_CORE_SYS_DE_DLY);
+	DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
+	DUMPCORE(HDMI_CORE_SYS_DE_TOP);
+	DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
+	DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
+	DUMPCORE(HDMI_CORE_SYS_DE_LINL);
+	DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
+	DUMPCORE(HDMI_CORE_SYS_HRES_L);
+	DUMPCORE(HDMI_CORE_SYS_HRES_H);
+	DUMPCORE(HDMI_CORE_SYS_VRES_L);
+	DUMPCORE(HDMI_CORE_SYS_VRES_H);
+	DUMPCORE(HDMI_CORE_SYS_IADJUST);
+	DUMPCORE(HDMI_CORE_SYS_POLDETECT);
+	DUMPCORE(HDMI_CORE_SYS_HWIDTH1);
+	DUMPCORE(HDMI_CORE_SYS_HWIDTH2);
+	DUMPCORE(HDMI_CORE_SYS_VWIDTH);
+	DUMPCORE(HDMI_CORE_SYS_VID_CTRL);
+	DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
+	DUMPCORE(HDMI_CORE_SYS_VID_MODE);
+	DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
+	DUMPCORE(HDMI_CORE_SYS_VID_BLANK3);
+	DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
+	DUMPCORE(HDMI_CORE_SYS_DC_HEADER);
+	DUMPCORE(HDMI_CORE_SYS_VID_DITHER);
+	DUMPCORE(HDMI_CORE_SYS_RGB2XVYCC_CT);
+	DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_LOW);
+	DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_UP);
+	DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_LOW);
+	DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_UP);
+	DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_LOW);
+	DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_UP);
+	DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_LOW);
+	DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_UP);
+	DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
+	DUMPCORE(HDMI_CORE_SYS_INTR1);
+	DUMPCORE(HDMI_CORE_SYS_INTR2);
+	DUMPCORE(HDMI_CORE_SYS_INTR3);
+	DUMPCORE(HDMI_CORE_SYS_INTR4);
+	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK1);
+	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK2);
+	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK3);
+	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK4);
+	DUMPCORE(HDMI_CORE_SYS_INTR_CTRL);
+	DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
+
+	DUMPCORE(HDMI_CORE_DDC_ADDR);
+	DUMPCORE(HDMI_CORE_DDC_SEGM);
+	DUMPCORE(HDMI_CORE_DDC_OFFSET);
+	DUMPCORE(HDMI_CORE_DDC_COUNT1);
+	DUMPCORE(HDMI_CORE_DDC_COUNT2);
+	DUMPCORE(HDMI_CORE_DDC_STATUS);
+	DUMPCORE(HDMI_CORE_DDC_CMD);
+	DUMPCORE(HDMI_CORE_DDC_DATA);
+
+	DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL);
+	DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL);
+	DUMPCOREAV(HDMI_CORE_AV_N_SVAL1);
+	DUMPCOREAV(HDMI_CORE_AV_N_SVAL2);
+	DUMPCOREAV(HDMI_CORE_AV_N_SVAL3);
+	DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1);
+	DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2);
+	DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3);
+	DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1);
+	DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2);
+	DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3);
+	DUMPCOREAV(HDMI_CORE_AV_AUD_MODE);
+	DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL);
+	DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS);
+	DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S);
+	DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5);
+	DUMPCOREAV(HDMI_CORE_AV_ASRC);
+	DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN);
+	DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL);
+	DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT);
+	DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
+	DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
+	DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
+	DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL);
+	DUMPCOREAV(HDMI_CORE_AV_DPD);
+	DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1);
+	DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2);
+	DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE);
+	DUMPCOREAV(HDMI_CORE_AV_AVI_VERS);
+	DUMPCOREAV(HDMI_CORE_AV_AVI_LEN);
+	DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM);
+
+	for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
+		DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE);
+
+	DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE);
+	DUMPCOREAV(HDMI_CORE_AV_SPD_VERS);
+	DUMPCOREAV(HDMI_CORE_AV_SPD_LEN);
+	DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM);
+
+	for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
+		DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE);
+
+	DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE);
+	DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS);
+	DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN);
+	DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM);
+
+	for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
+		DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE);
+
+	DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE);
+	DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS);
+	DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN);
+	DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM);
+
+	for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
+		DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE);
+
+	for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
+		DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE);
+
+	DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1);
+
+	for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
+		DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE);
+
+	DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
+}
+
+#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
+static void hdmi_core_audio_config(struct hdmi_core_data *core,
+					struct hdmi_core_audio_config *cfg)
+{
+	u32 r;
+	void __iomem *av_base = hdmi_av_base(core);
+
+	/*
+	 * Parameters for generation of Audio Clock Recovery packets
+	 */
+	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
+	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
+	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
+
+	if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
+		REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
+		REG_FLD_MOD(av_base,
+				HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
+		REG_FLD_MOD(av_base,
+				HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
+	} else {
+		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
+				cfg->aud_par_busclk, 7, 0);
+		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
+				(cfg->aud_par_busclk >> 8), 7, 0);
+		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
+				(cfg->aud_par_busclk >> 16), 7, 0);
+	}
+
+	/* Set ACR clock divisor */
+	REG_FLD_MOD(av_base,
+			HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
+
+	r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
+	/*
+	 * Use TMDS clock for ACR packets. For devices that use
+	 * the MCLK, this is the first part of the MCLK initialization.
+	 */
+	r = FLD_MOD(r, 0, 2, 2);
+
+	r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
+	r = FLD_MOD(r, cfg->cts_mode, 0, 0);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
+
+	/* For devices using MCLK, this completes its initialization. */
+	if (cfg->use_mclk)
+		REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2);
+
+	/* Override of SPDIF sample frequency with value in I2S_CHST4 */
+	REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
+						cfg->fs_override, 1, 1);
+
+	/*
+	 * Set IEC-60958-3 channel status word. It is passed to the IP
+	 * just as it is received. The user of the driver is responsible
+	 * for its contents.
+	 */
+	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0,
+		       cfg->iec60958_cfg->status[0]);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1,
+		       cfg->iec60958_cfg->status[1]);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2,
+		       cfg->iec60958_cfg->status[2]);
+	/* yes, this is correct: status[3] goes to CHST4 register */
+	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4,
+		       cfg->iec60958_cfg->status[3]);
+	/* yes, this is correct: status[4] goes to CHST5 register */
+	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5,
+		       cfg->iec60958_cfg->status[4]);
+
+	/* set I2S parameters */
+	r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
+	r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
+	r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
+	r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
+	r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
+	r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
+
+	REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
+			cfg->i2s_cfg.in_length_bits, 3, 0);
+
+	/* Audio channels and mode parameters */
+	REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
+	r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE);
+	r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
+	r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
+	r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
+	r = FLD_MOD(r, cfg->en_spdif, 1, 1);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
+
+	/* Audio channel mappings */
+	/* TODO: Make channel mapping dynamic. For now, map channels
+	 * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
+	 * HDMI speaker order is different. See CEA-861 Section 6.6.2.
+	 */
+	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78);
+	REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5);
+}
+
+static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core,
+		struct snd_cea_861_aud_if *info_aud)
+{
+	u8 sum = 0, checksum = 0;
+	void __iomem *av_base = hdmi_av_base(core);
+
+	/*
+	 * Set audio info frame type, version and length as
+	 * described in HDMI 1.4a Section 8.2.2 specification.
+	 * Checksum calculation is defined in Section 5.3.5.
+	 */
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
+	sum += 0x84 + 0x001 + 0x00a;
+
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0),
+		       info_aud->db1_ct_cc);
+	sum += info_aud->db1_ct_cc;
+
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1),
+		       info_aud->db2_sf_ss);
+	sum += info_aud->db2_sf_ss;
+
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
+	sum += info_aud->db3;
+
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
+	sum += info_aud->db4_ca;
+
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4),
+		       info_aud->db5_dminh_lsv);
+	sum += info_aud->db5_dminh_lsv;
+
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
+	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
+
+	checksum = 0x100 - sum;
+	hdmi_write_reg(av_base,
+					HDMI_CORE_AV_AUDIO_CHSUM, checksum);
+
+	/*
+	 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
+	 * is available.
+	 */
+}
+
+int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
+		struct omap_dss_audio *audio, u32 pclk)
+{
+	struct hdmi_audio_format audio_format;
+	struct hdmi_audio_dma audio_dma;
+	struct hdmi_core_audio_config acore;
+	int err, n, cts, channel_count;
+	unsigned int fs_nr;
+	bool word_length_16b = false;
+
+	if (!audio || !audio->iec || !audio->cea || !core)
+		return -EINVAL;
+
+	acore.iec60958_cfg = audio->iec;
+	/*
+	 * In the IEC-60958 status word, check if the audio sample word length
+	 * is 16-bit as several optimizations can be performed in such case.
+	 */
+	if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
+		if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
+			word_length_16b = true;
+
+	/* I2S configuration. See Phillips' specification */
+	if (word_length_16b)
+		acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
+	else
+		acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
+	/*
+	 * The I2S input word length is twice the lenght given in the IEC-60958
+	 * status word. If the word size is greater than
+	 * 20 bits, increment by one.
+	 */
+	acore.i2s_cfg.in_length_bits = audio->iec->status[4]
+		& IEC958_AES4_CON_WORDLEN;
+	if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
+		acore.i2s_cfg.in_length_bits++;
+	acore.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
+	acore.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
+	acore.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
+	acore.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
+
+	/* convert sample frequency to a number */
+	switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
+	case IEC958_AES3_CON_FS_32000:
+		fs_nr = 32000;
+		break;
+	case IEC958_AES3_CON_FS_44100:
+		fs_nr = 44100;
+		break;
+	case IEC958_AES3_CON_FS_48000:
+		fs_nr = 48000;
+		break;
+	case IEC958_AES3_CON_FS_88200:
+		fs_nr = 88200;
+		break;
+	case IEC958_AES3_CON_FS_96000:
+		fs_nr = 96000;
+		break;
+	case IEC958_AES3_CON_FS_176400:
+		fs_nr = 176400;
+		break;
+	case IEC958_AES3_CON_FS_192000:
+		fs_nr = 192000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = hdmi_compute_acr(pclk, fs_nr, &n, &cts);
+
+	/* Audio clock regeneration settings */
+	acore.n = n;
+	acore.cts = cts;
+	if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
+		acore.aud_par_busclk = 0;
+		acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
+		acore.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
+	} else {
+		acore.aud_par_busclk = (((128 * 31) - 1) << 8);
+		acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
+		acore.use_mclk = true;
+	}
+
+	if (acore.use_mclk)
+		acore.mclk_mode = HDMI_AUDIO_MCLK_128FS;
+
+	/* Audio channels settings */
+	channel_count = (audio->cea->db1_ct_cc &
+			 CEA861_AUDIO_INFOFRAME_DB1CC) + 1;
+
+	switch (channel_count) {
+	case 2:
+		audio_format.active_chnnls_msk = 0x03;
+		break;
+	case 3:
+		audio_format.active_chnnls_msk = 0x07;
+		break;
+	case 4:
+		audio_format.active_chnnls_msk = 0x0f;
+		break;
+	case 5:
+		audio_format.active_chnnls_msk = 0x1f;
+		break;
+	case 6:
+		audio_format.active_chnnls_msk = 0x3f;
+		break;
+	case 7:
+		audio_format.active_chnnls_msk = 0x7f;
+		break;
+	case 8:
+		audio_format.active_chnnls_msk = 0xff;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * the HDMI IP needs to enable four stereo channels when transmitting
+	 * more than 2 audio channels
+	 */
+	if (channel_count == 2) {
+		audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
+		acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
+		acore.layout = HDMI_AUDIO_LAYOUT_2CH;
+	} else {
+		audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
+		acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
+				HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
+				HDMI_AUDIO_I2S_SD3_EN;
+		acore.layout = HDMI_AUDIO_LAYOUT_8CH;
+	}
+
+	acore.en_spdif = false;
+	/* use sample frequency from channel status word */
+	acore.fs_override = true;
+	/* enable ACR packets */
+	acore.en_acr_pkt = true;
+	/* disable direct streaming digital audio */
+	acore.en_dsd_audio = false;
+	/* use parallel audio interface */
+	acore.en_parallel_aud_input = true;
+
+	/* DMA settings */
+	if (word_length_16b)
+		audio_dma.transfer_size = 0x10;
+	else
+		audio_dma.transfer_size = 0x20;
+	audio_dma.block_size = 0xC0;
+	audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
+	audio_dma.fifo_threshold = 0x20; /* in number of samples */
+
+	/* audio FIFO format settings */
+	if (word_length_16b) {
+		audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
+		audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
+		audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
+	} else {
+		audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
+		audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
+		audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
+	}
+	audio_format.type = HDMI_AUDIO_TYPE_LPCM;
+	audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
+	/* disable start/stop signals of IEC 60958 blocks */
+	audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
+
+	/* configure DMA and audio FIFO format*/
+	hdmi_wp_audio_config_dma(wp, &audio_dma);
+	hdmi_wp_audio_config_format(wp, &audio_format);
+
+	/* configure the core*/
+	hdmi_core_audio_config(core, &acore);
+
+	/* configure CEA 861 audio infoframe*/
+	hdmi_core_audio_infoframe_cfg(core, audio->cea);
+
+	return 0;
+}
+
+int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
+{
+	REG_FLD_MOD(hdmi_av_base(core),
+		    HDMI_CORE_AV_AUD_MODE, true, 0, 0);
+
+	hdmi_wp_audio_core_req_enable(wp, true);
+
+	return 0;
+}
+
+void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
+{
+	REG_FLD_MOD(hdmi_av_base(core),
+		    HDMI_CORE_AV_AUD_MODE, false, 0, 0);
+
+	hdmi_wp_audio_core_req_enable(wp, false);
+}
+
+int hdmi4_audio_get_dma_port(u32 *offset, u32 *size)
+{
+	if (!offset || !size)
+		return -EINVAL;
+	*offset = HDMI_WP_AUDIO_DATA;
+	*size = 4;
+	return 0;
+}
+
+#endif
+
+#define CORE_OFFSET		0x400
+#define CORE_SIZE		0xc00
+
+int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
+{
+	struct resource *res;
+	struct resource temp_res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
+	if (!res) {
+		DSSDBG("can't get CORE mem resource by name\n");
+		/*
+		 * if hwmod/DT doesn't have the memory resource information
+		 * split into HDMI sub blocks by name, we try again by getting
+		 * the platform's first resource. this code will be removed when
+		 * the driver can get the mem resources by name
+		 */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DSSERR("can't get CORE mem resource\n");
+			return -EINVAL;
+		}
+
+		temp_res.start = res->start + CORE_OFFSET;
+		temp_res.end = temp_res.start + CORE_SIZE - 1;
+		res = &temp_res;
+	}
+
+	core->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!core->base) {
+		DSSERR("can't ioremap CORE\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.h b/drivers/video/fbdev/omap2/dss/hdmi4_core.h
new file mode 100644
index 000000000000..bb646896fa82
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.h
@@ -0,0 +1,276 @@
+/*
+ * HDMI header definition for OMAP4 HDMI core IP
+ *
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _HDMI4_CORE_H_
+#define _HDMI4_CORE_H_
+
+#include "hdmi.h"
+
+/* OMAP4 HDMI IP Core System */
+
+#define HDMI_CORE_SYS_VND_IDL			0x0
+#define HDMI_CORE_SYS_DEV_IDL			0x8
+#define HDMI_CORE_SYS_DEV_IDH			0xC
+#define HDMI_CORE_SYS_DEV_REV			0x10
+#define HDMI_CORE_SYS_SRST			0x14
+#define HDMI_CORE_SYS_SYS_CTRL1			0x20
+#define HDMI_CORE_SYS_SYS_STAT			0x24
+#define HDMI_CORE_SYS_SYS_CTRL3			0x28
+#define HDMI_CORE_SYS_DCTL			0x34
+#define HDMI_CORE_SYS_DE_DLY			0xC8
+#define HDMI_CORE_SYS_DE_CTRL			0xCC
+#define HDMI_CORE_SYS_DE_TOP			0xD0
+#define HDMI_CORE_SYS_DE_CNTL			0xD8
+#define HDMI_CORE_SYS_DE_CNTH			0xDC
+#define HDMI_CORE_SYS_DE_LINL			0xE0
+#define HDMI_CORE_SYS_DE_LINH_1			0xE4
+#define HDMI_CORE_SYS_HRES_L			0xE8
+#define HDMI_CORE_SYS_HRES_H			0xEC
+#define HDMI_CORE_SYS_VRES_L			0xF0
+#define HDMI_CORE_SYS_VRES_H			0xF4
+#define HDMI_CORE_SYS_IADJUST			0xF8
+#define HDMI_CORE_SYS_POLDETECT			0xFC
+#define HDMI_CORE_SYS_HWIDTH1			0x110
+#define HDMI_CORE_SYS_HWIDTH2			0x114
+#define HDMI_CORE_SYS_VWIDTH			0x11C
+#define HDMI_CORE_SYS_VID_CTRL			0x120
+#define HDMI_CORE_SYS_VID_ACEN			0x124
+#define HDMI_CORE_SYS_VID_MODE			0x128
+#define HDMI_CORE_SYS_VID_BLANK1		0x12C
+#define HDMI_CORE_SYS_VID_BLANK2		0x130
+#define HDMI_CORE_SYS_VID_BLANK3		0x134
+#define HDMI_CORE_SYS_DC_HEADER			0x138
+#define HDMI_CORE_SYS_VID_DITHER		0x13C
+#define HDMI_CORE_SYS_RGB2XVYCC_CT		0x140
+#define HDMI_CORE_SYS_R2Y_COEFF_LOW		0x144
+#define HDMI_CORE_SYS_R2Y_COEFF_UP		0x148
+#define HDMI_CORE_SYS_G2Y_COEFF_LOW		0x14C
+#define HDMI_CORE_SYS_G2Y_COEFF_UP		0x150
+#define HDMI_CORE_SYS_B2Y_COEFF_LOW		0x154
+#define HDMI_CORE_SYS_B2Y_COEFF_UP		0x158
+#define HDMI_CORE_SYS_R2CB_COEFF_LOW		0x15C
+#define HDMI_CORE_SYS_R2CB_COEFF_UP		0x160
+#define HDMI_CORE_SYS_G2CB_COEFF_LOW		0x164
+#define HDMI_CORE_SYS_G2CB_COEFF_UP		0x168
+#define HDMI_CORE_SYS_B2CB_COEFF_LOW		0x16C
+#define HDMI_CORE_SYS_B2CB_COEFF_UP		0x170
+#define HDMI_CORE_SYS_R2CR_COEFF_LOW		0x174
+#define HDMI_CORE_SYS_R2CR_COEFF_UP		0x178
+#define HDMI_CORE_SYS_G2CR_COEFF_LOW		0x17C
+#define HDMI_CORE_SYS_G2CR_COEFF_UP		0x180
+#define HDMI_CORE_SYS_B2CR_COEFF_LOW		0x184
+#define HDMI_CORE_SYS_B2CR_COEFF_UP		0x188
+#define HDMI_CORE_SYS_RGB_OFFSET_LOW		0x18C
+#define HDMI_CORE_SYS_RGB_OFFSET_UP		0x190
+#define HDMI_CORE_SYS_Y_OFFSET_LOW		0x194
+#define HDMI_CORE_SYS_Y_OFFSET_UP		0x198
+#define HDMI_CORE_SYS_CBCR_OFFSET_LOW		0x19C
+#define HDMI_CORE_SYS_CBCR_OFFSET_UP		0x1A0
+#define HDMI_CORE_SYS_INTR_STATE		0x1C0
+#define HDMI_CORE_SYS_INTR1			0x1C4
+#define HDMI_CORE_SYS_INTR2			0x1C8
+#define HDMI_CORE_SYS_INTR3			0x1CC
+#define HDMI_CORE_SYS_INTR4			0x1D0
+#define HDMI_CORE_SYS_INTR_UNMASK1		0x1D4
+#define HDMI_CORE_SYS_INTR_UNMASK2		0x1D8
+#define HDMI_CORE_SYS_INTR_UNMASK3		0x1DC
+#define HDMI_CORE_SYS_INTR_UNMASK4		0x1E0
+#define HDMI_CORE_SYS_INTR_CTRL			0x1E4
+#define HDMI_CORE_SYS_TMDS_CTRL			0x208
+
+/* value definitions for HDMI_CORE_SYS_SYS_CTRL1 fields */
+#define HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC	0x1
+#define HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC	0x1
+#define HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS	0x1
+#define HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE	0x1
+
+/* HDMI DDC E-DID */
+#define HDMI_CORE_DDC_ADDR			0x3B4
+#define HDMI_CORE_DDC_SEGM			0x3B8
+#define HDMI_CORE_DDC_OFFSET			0x3BC
+#define HDMI_CORE_DDC_COUNT1			0x3C0
+#define HDMI_CORE_DDC_COUNT2			0x3C4
+#define HDMI_CORE_DDC_STATUS			0x3C8
+#define HDMI_CORE_DDC_CMD			0x3CC
+#define HDMI_CORE_DDC_DATA			0x3D0
+
+/* HDMI IP Core Audio Video */
+
+#define HDMI_CORE_AV_ACR_CTRL			0x4
+#define HDMI_CORE_AV_FREQ_SVAL			0x8
+#define HDMI_CORE_AV_N_SVAL1			0xC
+#define HDMI_CORE_AV_N_SVAL2			0x10
+#define HDMI_CORE_AV_N_SVAL3			0x14
+#define HDMI_CORE_AV_CTS_SVAL1			0x18
+#define HDMI_CORE_AV_CTS_SVAL2			0x1C
+#define HDMI_CORE_AV_CTS_SVAL3			0x20
+#define HDMI_CORE_AV_CTS_HVAL1			0x24
+#define HDMI_CORE_AV_CTS_HVAL2			0x28
+#define HDMI_CORE_AV_CTS_HVAL3			0x2C
+#define HDMI_CORE_AV_AUD_MODE			0x50
+#define HDMI_CORE_AV_SPDIF_CTRL			0x54
+#define HDMI_CORE_AV_HW_SPDIF_FS		0x60
+#define HDMI_CORE_AV_SWAP_I2S			0x64
+#define HDMI_CORE_AV_SPDIF_ERTH			0x6C
+#define HDMI_CORE_AV_I2S_IN_MAP			0x70
+#define HDMI_CORE_AV_I2S_IN_CTRL		0x74
+#define HDMI_CORE_AV_I2S_CHST0			0x78
+#define HDMI_CORE_AV_I2S_CHST1			0x7C
+#define HDMI_CORE_AV_I2S_CHST2			0x80
+#define HDMI_CORE_AV_I2S_CHST4			0x84
+#define HDMI_CORE_AV_I2S_CHST5			0x88
+#define HDMI_CORE_AV_ASRC			0x8C
+#define HDMI_CORE_AV_I2S_IN_LEN			0x90
+#define HDMI_CORE_AV_HDMI_CTRL			0xBC
+#define HDMI_CORE_AV_AUDO_TXSTAT		0xC0
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1		0xCC
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2		0xD0
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3		0xD4
+#define HDMI_CORE_AV_TEST_TXCTRL		0xF0
+#define HDMI_CORE_AV_DPD			0xF4
+#define HDMI_CORE_AV_PB_CTRL1			0xF8
+#define HDMI_CORE_AV_PB_CTRL2			0xFC
+#define HDMI_CORE_AV_AVI_TYPE			0x100
+#define HDMI_CORE_AV_AVI_VERS			0x104
+#define HDMI_CORE_AV_AVI_LEN			0x108
+#define HDMI_CORE_AV_AVI_CHSUM			0x10C
+#define HDMI_CORE_AV_AVI_DBYTE(n)		(n * 4 + 0x110)
+#define HDMI_CORE_AV_SPD_TYPE			0x180
+#define HDMI_CORE_AV_SPD_VERS			0x184
+#define HDMI_CORE_AV_SPD_LEN			0x188
+#define HDMI_CORE_AV_SPD_CHSUM			0x18C
+#define HDMI_CORE_AV_SPD_DBYTE(n)		(n * 4 + 0x190)
+#define HDMI_CORE_AV_AUDIO_TYPE			0x200
+#define HDMI_CORE_AV_AUDIO_VERS			0x204
+#define HDMI_CORE_AV_AUDIO_LEN			0x208
+#define HDMI_CORE_AV_AUDIO_CHSUM		0x20C
+#define HDMI_CORE_AV_AUD_DBYTE(n)		(n * 4 + 0x210)
+#define HDMI_CORE_AV_MPEG_TYPE			0x280
+#define HDMI_CORE_AV_MPEG_VERS			0x284
+#define HDMI_CORE_AV_MPEG_LEN			0x288
+#define HDMI_CORE_AV_MPEG_CHSUM			0x28C
+#define HDMI_CORE_AV_MPEG_DBYTE(n)		(n * 4 + 0x290)
+#define HDMI_CORE_AV_GEN_DBYTE(n)		(n * 4 + 0x300)
+#define HDMI_CORE_AV_CP_BYTE1			0x37C
+#define HDMI_CORE_AV_GEN2_DBYTE(n)		(n * 4 + 0x380)
+#define HDMI_CORE_AV_CEC_ADDR_ID		0x3FC
+
+#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE		0x4
+#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE		0x4
+#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE		0x4
+#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE		0x4
+
+#define HDMI_CORE_AV_AVI_DBYTE_NELEMS		15
+#define HDMI_CORE_AV_SPD_DBYTE_NELEMS		27
+#define HDMI_CORE_AV_AUD_DBYTE_NELEMS		10
+#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS		27
+#define HDMI_CORE_AV_GEN_DBYTE_NELEMS		31
+#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS		31
+
+enum hdmi_core_inputbus_width {
+	HDMI_INPUT_8BIT = 0,
+	HDMI_INPUT_10BIT = 1,
+	HDMI_INPUT_12BIT = 2
+};
+
+enum hdmi_core_dither_trunc {
+	HDMI_OUTPUTTRUNCATION_8BIT = 0,
+	HDMI_OUTPUTTRUNCATION_10BIT = 1,
+	HDMI_OUTPUTTRUNCATION_12BIT = 2,
+	HDMI_OUTPUTDITHER_8BIT = 3,
+	HDMI_OUTPUTDITHER_10BIT = 4,
+	HDMI_OUTPUTDITHER_12BIT = 5
+};
+
+enum hdmi_core_deepcolor_ed {
+	HDMI_DEEPCOLORPACKECTDISABLE = 0,
+	HDMI_DEEPCOLORPACKECTENABLE = 1
+};
+
+enum hdmi_core_packet_mode {
+	HDMI_PACKETMODERESERVEDVALUE = 0,
+	HDMI_PACKETMODE24BITPERPIXEL = 4,
+	HDMI_PACKETMODE30BITPERPIXEL = 5,
+	HDMI_PACKETMODE36BITPERPIXEL = 6,
+	HDMI_PACKETMODE48BITPERPIXEL = 7
+};
+
+enum hdmi_core_tclkselclkmult {
+	HDMI_FPLL05IDCK = 0,
+	HDMI_FPLL10IDCK = 1,
+	HDMI_FPLL20IDCK = 2,
+	HDMI_FPLL40IDCK = 3
+};
+
+enum hdmi_core_packet_ctrl {
+	HDMI_PACKETENABLE = 1,
+	HDMI_PACKETDISABLE = 0,
+	HDMI_PACKETREPEATON = 1,
+	HDMI_PACKETREPEATOFF = 0
+};
+
+enum hdmi_audio_i2s_config {
+	HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
+	HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
+	HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
+	HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
+	HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
+	HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
+	HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
+	HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
+	HDMI_AUDIO_I2S_SD0_EN = 1,
+	HDMI_AUDIO_I2S_SD1_EN = 1 << 1,
+	HDMI_AUDIO_I2S_SD2_EN = 1 << 2,
+	HDMI_AUDIO_I2S_SD3_EN = 1 << 3,
+};
+
+struct hdmi_core_video_config {
+	enum hdmi_core_inputbus_width	ip_bus_width;
+	enum hdmi_core_dither_trunc	op_dither_truc;
+	enum hdmi_core_deepcolor_ed	deep_color_pkt;
+	enum hdmi_core_packet_mode	pkt_mode;
+	enum hdmi_core_hdmi_dvi		hdmi_dvi;
+	enum hdmi_core_tclkselclkmult	tclk_sel_clkmult;
+};
+
+struct hdmi_core_packet_enable_repeat {
+	u32	audio_pkt;
+	u32	audio_pkt_repeat;
+	u32	avi_infoframe;
+	u32	avi_infoframe_repeat;
+	u32	gen_cntrl_pkt;
+	u32	gen_cntrl_pkt_repeat;
+	u32	generic_pkt;
+	u32	generic_pkt_repeat;
+};
+
+int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len);
+void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
+		struct hdmi_config *cfg);
+void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s);
+int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
+
+#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
+int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
+void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
+int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
+		struct omap_dss_audio *audio, u32 pclk);
+int hdmi4_audio_get_dma_port(u32 *offset, u32 *size);
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_common.c b/drivers/video/fbdev/omap2/dss/hdmi_common.c
new file mode 100644
index 000000000000..0b12a3f62fe1
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi_common.c
@@ -0,0 +1,425 @@
+
+/*
+ * Logic for the below structure :
+ * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
+ * There is a correspondence between CEA/VESA timing and code, please
+ * refer to section 6.3 in HDMI 1.3 specification for timing code.
+ *
+ * In the below structure, cea_vesa_timings corresponds to all OMAP4
+ * supported CEA and VESA timing values.code_cea corresponds to the CEA
+ * code, It is used to get the timing from cea_vesa_timing array.Similarly
+ * with code_vesa. Code_index is used for back mapping, that is once EDID
+ * is read from the TV, EDID is parsed to find the timing values and then
+ * map it to corresponding CEA or VESA index.
+ */
+
+#define DSS_SUBSYS_NAME "HDMI"
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <video/omapdss.h>
+
+#include "hdmi.h"
+
+static const struct hdmi_config cea_timings[] = {
+	{
+		{ 640, 480, 25200000, 96, 16, 48, 2, 10, 33,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 1, HDMI_HDMI },
+	},
+	{
+		{ 720, 480, 27027000, 62, 16, 60, 6, 9, 30,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 2, HDMI_HDMI },
+	},
+	{
+		{ 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 4, HDMI_HDMI },
+	},
+	{
+		{ 1920, 540, 74250000, 44, 88, 148, 5, 2, 15,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			true, },
+		{ 5, HDMI_HDMI },
+	},
+	{
+		{ 1440, 240, 27027000, 124, 38, 114, 3, 4, 15,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			true, },
+		{ 6, HDMI_HDMI },
+	},
+	{
+		{ 1920, 1080, 148500000, 44, 88, 148, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 16, HDMI_HDMI },
+	},
+	{
+		{ 720, 576, 27000000, 64, 12, 68, 5, 5, 39,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 17, HDMI_HDMI },
+	},
+	{
+		{ 1280, 720, 74250000, 40, 440, 220, 5, 5, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 19, HDMI_HDMI },
+	},
+	{
+		{ 1920, 540, 74250000, 44, 528, 148, 5, 2, 15,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			true, },
+		{ 20, HDMI_HDMI },
+	},
+	{
+		{ 1440, 288, 27000000, 126, 24, 138, 3, 2, 19,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			true, },
+		{ 21, HDMI_HDMI },
+	},
+	{
+		{ 1440, 576, 54000000, 128, 24, 136, 5, 5, 39,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 29, HDMI_HDMI },
+	},
+	{
+		{ 1920, 1080, 148500000, 44, 528, 148, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 31, HDMI_HDMI },
+	},
+	{
+		{ 1920, 1080, 74250000, 44, 638, 148, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 32, HDMI_HDMI },
+	},
+	{
+		{ 2880, 480, 108108000, 248, 64, 240, 6, 9, 30,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 35, HDMI_HDMI },
+	},
+	{
+		{ 2880, 576, 108000000, 256, 48, 272, 5, 5, 39,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 37, HDMI_HDMI },
+	},
+};
+
+static const struct hdmi_config vesa_timings[] = {
+/* VESA From Here */
+	{
+		{ 640, 480, 25175000, 96, 16, 48, 2, 11, 31,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 4, HDMI_DVI },
+	},
+	{
+		{ 800, 600, 40000000, 128, 40, 88, 4, 1, 23,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 9, HDMI_DVI },
+	},
+	{
+		{ 848, 480, 33750000, 112, 16, 112, 8, 6, 23,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0xE, HDMI_DVI },
+	},
+	{
+		{ 1280, 768, 79500000, 128, 64, 192, 7, 3, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x17, HDMI_DVI },
+	},
+	{
+		{ 1280, 800, 83500000, 128, 72, 200, 6, 3, 22,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x1C, HDMI_DVI },
+	},
+	{
+		{ 1360, 768, 85500000, 112, 64, 256, 6, 3, 18,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x27, HDMI_DVI },
+	},
+	{
+		{ 1280, 960, 108000000, 112, 96, 312, 3, 1, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x20, HDMI_DVI },
+	},
+	{
+		{ 1280, 1024, 108000000, 112, 48, 248, 3, 1, 38,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x23, HDMI_DVI },
+	},
+	{
+		{ 1024, 768, 65000000, 136, 24, 160, 6, 3, 29,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x10, HDMI_DVI },
+	},
+	{
+		{ 1400, 1050, 121750000, 144, 88, 232, 4, 3, 32,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x2A, HDMI_DVI },
+	},
+	{
+		{ 1440, 900, 106500000, 152, 80, 232, 6, 3, 25,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x2F, HDMI_DVI },
+	},
+	{
+		{ 1680, 1050, 146250000, 176 , 104, 280, 6, 3, 30,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
+			false, },
+		{ 0x3A, HDMI_DVI },
+	},
+	{
+		{ 1366, 768, 85500000, 143, 70, 213, 3, 3, 24,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x51, HDMI_DVI },
+	},
+	{
+		{ 1920, 1080, 148500000, 44, 148, 80, 5, 4, 36,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x52, HDMI_DVI },
+	},
+	{
+		{ 1280, 768, 68250000, 32, 48, 80, 7, 3, 12,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x16, HDMI_DVI },
+	},
+	{
+		{ 1400, 1050, 101000000, 32, 48, 80, 4, 3, 23,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x29, HDMI_DVI },
+	},
+	{
+		{ 1680, 1050, 119000000, 32, 48, 80, 6, 3, 21,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x39, HDMI_DVI },
+	},
+	{
+		{ 1280, 800, 79500000, 32, 48, 80, 6, 3, 14,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x1B, HDMI_DVI },
+	},
+	{
+		{ 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
+			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x55, HDMI_DVI },
+	},
+	{
+		{ 1920, 1200, 154000000, 32, 48, 80, 6, 3, 26,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x44, HDMI_DVI },
+	},
+};
+
+const struct hdmi_config *hdmi_default_timing(void)
+{
+	return &vesa_timings[0];
+}
+
+static const struct hdmi_config *hdmi_find_timing(int code,
+			const struct hdmi_config *timings_arr, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if (timings_arr[i].cm.code == code)
+			return &timings_arr[i];
+	}
+
+	return NULL;
+}
+
+const struct hdmi_config *hdmi_get_timings(int mode, int code)
+{
+	const struct hdmi_config *arr;
+	int len;
+
+	if (mode == HDMI_DVI) {
+		arr = vesa_timings;
+		len = ARRAY_SIZE(vesa_timings);
+	} else {
+		arr = cea_timings;
+		len = ARRAY_SIZE(cea_timings);
+	}
+
+	return hdmi_find_timing(code, arr, len);
+}
+
+static bool hdmi_timings_compare(struct omap_video_timings *timing1,
+			const struct omap_video_timings *timing2)
+{
+	int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
+
+	if ((DIV_ROUND_CLOSEST(timing2->pixelclock, 1000000) ==
+			DIV_ROUND_CLOSEST(timing1->pixelclock, 1000000)) &&
+		(timing2->x_res == timing1->x_res) &&
+		(timing2->y_res == timing1->y_res)) {
+
+		timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
+		timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
+		timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
+		timing1_vsync = timing1->vfp + timing1->vsw + timing1->vbp;
+
+		DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
+			"timing2_hsync = %d timing2_vsync = %d\n",
+			timing1_hsync, timing1_vsync,
+			timing2_hsync, timing2_vsync);
+
+		if ((timing1_hsync == timing2_hsync) &&
+			(timing1_vsync == timing2_vsync)) {
+			return true;
+		}
+	}
+	return false;
+}
+
+struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
+{
+	int i;
+	struct hdmi_cm cm = {-1};
+	DSSDBG("hdmi_get_code\n");
+
+	for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
+		if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
+			cm = cea_timings[i].cm;
+			goto end;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
+		if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
+			cm = vesa_timings[i].cm;
+			goto end;
+		}
+	}
+
+end:
+	return cm;
+}
+
+#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
+int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
+{
+	u32 deep_color;
+	bool deep_color_correct = false;
+
+	if (n == NULL || cts == NULL)
+		return -EINVAL;
+
+	/* TODO: When implemented, query deep color mode here. */
+	deep_color = 100;
+
+	/*
+	 * When using deep color, the default N value (as in the HDMI
+	 * specification) yields to an non-integer CTS. Hence, we
+	 * modify it while keeping the restrictions described in
+	 * section 7.2.1 of the HDMI 1.4a specification.
+	 */
+	switch (sample_freq) {
+	case 32000:
+	case 48000:
+	case 96000:
+	case 192000:
+		if (deep_color == 125)
+			if (pclk == 27027000 || pclk == 74250000)
+				deep_color_correct = true;
+		if (deep_color == 150)
+			if (pclk == 27027000)
+				deep_color_correct = true;
+		break;
+	case 44100:
+	case 88200:
+	case 176400:
+		if (deep_color == 125)
+			if (pclk == 27027000)
+				deep_color_correct = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (deep_color_correct) {
+		switch (sample_freq) {
+		case 32000:
+			*n = 8192;
+			break;
+		case 44100:
+			*n = 12544;
+			break;
+		case 48000:
+			*n = 8192;
+			break;
+		case 88200:
+			*n = 25088;
+			break;
+		case 96000:
+			*n = 16384;
+			break;
+		case 176400:
+			*n = 50176;
+			break;
+		case 192000:
+			*n = 32768;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		switch (sample_freq) {
+		case 32000:
+			*n = 4096;
+			break;
+		case 44100:
+			*n = 6272;
+			break;
+		case 48000:
+			*n = 6144;
+			break;
+		case 88200:
+			*n = 12544;
+			break;
+		case 96000:
+			*n = 12288;
+			break;
+		case 176400:
+			*n = 25088;
+			break;
+		case 192000:
+			*n = 24576;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
+	*cts = (pclk/1000) * (*n / 128) * deep_color / (sample_freq / 10);
+
+	return 0;
+}
+#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
new file mode 100644
index 000000000000..dd376ce8da01
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
@@ -0,0 +1,160 @@
+/*
+ * HDMI PHY
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "hdmi.h"
+
+void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
+{
+#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
+		hdmi_read_reg(phy->base, r))
+
+	DUMPPHY(HDMI_TXPHY_TX_CTRL);
+	DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
+	DUMPPHY(HDMI_TXPHY_POWER_CTRL);
+	DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
+}
+
+static irqreturn_t hdmi_irq_handler(int irq, void *data)
+{
+	struct hdmi_wp_data *wp = data;
+	u32 irqstatus;
+
+	irqstatus = hdmi_wp_get_irqstatus(wp);
+	hdmi_wp_set_irqstatus(wp, irqstatus);
+
+	if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
+			irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
+		/*
+		 * If we get both connect and disconnect interrupts at the same
+		 * time, turn off the PHY, clear interrupts, and restart, which
+		 * raises connect interrupt if a cable is connected, or nothing
+		 * if cable is not connected.
+		 */
+		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
+
+		hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
+				HDMI_IRQ_LINK_DISCONNECT);
+
+		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
+	} else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
+		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
+	} else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
+		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
+	}
+
+	return IRQ_HANDLED;
+}
+
+int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
+			struct hdmi_config *cfg)
+{
+	u16 r = 0;
+	u32 irqstatus;
+
+	hdmi_wp_clear_irqenable(wp, 0xffffffff);
+
+	irqstatus = hdmi_wp_get_irqstatus(wp);
+	hdmi_wp_set_irqstatus(wp, irqstatus);
+
+	r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
+	if (r)
+		return r;
+
+	/*
+	 * Read address 0 in order to get the SCP reset done completed
+	 * Dummy access performed to make sure reset is done
+	 */
+	hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL);
+
+	/*
+	 * Write to phy address 0 to configure the clock
+	 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
+	 */
+	REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
+
+	/* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
+	hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
+
+	/* Setup max LDO voltage */
+	REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
+
+	/* Write to phy address 3 to change the polarity control */
+	REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+
+	r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler,
+				IRQF_ONESHOT, "OMAP HDMI", wp);
+	if (r) {
+		DSSERR("HDMI IRQ request failed\n");
+		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
+		return r;
+	}
+
+	hdmi_wp_set_irqenable(wp,
+		HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
+
+	return 0;
+}
+
+void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp)
+{
+	free_irq(phy->irq, wp);
+
+	hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
+}
+
+#define PHY_OFFSET	0x300
+#define PHY_SIZE	0x100
+
+int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy)
+{
+	struct resource *res;
+	struct resource temp_res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
+	if (!res) {
+		DSSDBG("can't get PHY mem resource by name\n");
+		/*
+		 * if hwmod/DT doesn't have the memory resource information
+		 * split into HDMI sub blocks by name, we try again by getting
+		 * the platform's first resource. this code will be removed when
+		 * the driver can get the mem resources by name
+		 */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DSSERR("can't get PHY mem resource\n");
+			return -EINVAL;
+		}
+
+		temp_res.start = res->start + PHY_OFFSET;
+		temp_res.end = temp_res.start + PHY_SIZE - 1;
+		res = &temp_res;
+	}
+
+	phy->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!phy->base) {
+		DSSERR("can't ioremap TX PHY\n");
+		return -ENOMEM;
+	}
+
+	phy->irq = platform_get_irq(pdev, 0);
+	if (phy->irq < 0) {
+		DSSERR("platform_get_irq failed\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
new file mode 100644
index 000000000000..5fc71215c303
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
@@ -0,0 +1,232 @@
+/*
+ * HDMI PLL
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#define DSS_SUBSYS_NAME "HDMIPLL"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "hdmi.h"
+
+#define HDMI_DEFAULT_REGN 16
+#define HDMI_DEFAULT_REGM2 1
+
+void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
+{
+#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
+		hdmi_read_reg(pll->base, r))
+
+	DUMPPLL(PLLCTRL_PLL_CONTROL);
+	DUMPPLL(PLLCTRL_PLL_STATUS);
+	DUMPPLL(PLLCTRL_PLL_GO);
+	DUMPPLL(PLLCTRL_CFG1);
+	DUMPPLL(PLLCTRL_CFG2);
+	DUMPPLL(PLLCTRL_CFG3);
+	DUMPPLL(PLLCTRL_SSC_CFG1);
+	DUMPPLL(PLLCTRL_SSC_CFG2);
+	DUMPPLL(PLLCTRL_CFG4);
+}
+
+void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy)
+{
+	struct hdmi_pll_info *pi = &pll->info;
+	unsigned long refclk;
+	u32 mf;
+
+	/* use our funky units */
+	clkin /= 10000;
+
+	/*
+	 * Input clock is predivided by N + 1
+	 * out put of which is reference clk
+	 */
+
+	pi->regn = HDMI_DEFAULT_REGN;
+
+	refclk = clkin / pi->regn;
+
+	pi->regm2 = HDMI_DEFAULT_REGM2;
+
+	/*
+	 * multiplier is pixel_clk/ref_clk
+	 * Multiplying by 100 to avoid fractional part removal
+	 */
+	pi->regm = phy * pi->regm2 / refclk;
+
+	/*
+	 * fractional multiplier is remainder of the difference between
+	 * multiplier and actual phy(required pixel clock thus should be
+	 * multiplied by 2^18(262144) divided by the reference clock
+	 */
+	mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
+	pi->regmf = pi->regm2 * mf / refclk;
+
+	/*
+	 * Dcofreq should be set to 1 if required pixel clock
+	 * is greater than 1000MHz
+	 */
+	pi->dcofreq = phy > 1000 * 100;
+	pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
+
+	/* Set the reference clock to sysclk reference */
+	pi->refsel = HDMI_REFSEL_SYSCLK;
+
+	DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
+	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
+}
+
+
+static int hdmi_pll_config(struct hdmi_pll_data *pll)
+{
+	u32 r;
+	struct hdmi_pll_info *fmt = &pll->info;
+
+	/* PLL start always use manual mode */
+	REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
+
+	r = hdmi_read_reg(pll->base, PLLCTRL_CFG1);
+	r = FLD_MOD(r, fmt->regm, 20, 9);	/* CFG1_PLL_REGM */
+	r = FLD_MOD(r, fmt->regn - 1, 8, 1);	/* CFG1_PLL_REGN */
+	hdmi_write_reg(pll->base, PLLCTRL_CFG1, r);
+
+	r = hdmi_read_reg(pll->base, PLLCTRL_CFG2);
+
+	r = FLD_MOD(r, 0x0, 12, 12);	/* PLL_HIGHFREQ divide by 2 */
+	r = FLD_MOD(r, 0x1, 13, 13);	/* PLL_REFEN */
+	r = FLD_MOD(r, 0x0, 14, 14);	/* PHY_CLKINEN de-assert during locking */
+	r = FLD_MOD(r, fmt->refsel, 22, 21);	/* REFSEL */
+
+	if (fmt->dcofreq) {
+		/* divider programming for frequency beyond 1000Mhz */
+		REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
+		r = FLD_MOD(r, 0x4, 3, 1);	/* 1000MHz and 2000MHz */
+	} else {
+		r = FLD_MOD(r, 0x2, 3, 1);	/* 500MHz and 1000MHz */
+	}
+
+	hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
+
+	r = hdmi_read_reg(pll->base, PLLCTRL_CFG4);
+	r = FLD_MOD(r, fmt->regm2, 24, 18);
+	r = FLD_MOD(r, fmt->regmf, 17, 0);
+	hdmi_write_reg(pll->base, PLLCTRL_CFG4, r);
+
+	/* go now */
+	REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0);
+
+	/* wait for bit change */
+	if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
+			0, 0, 1) != 1) {
+		DSSERR("PLL GO bit not set\n");
+		return -ETIMEDOUT;
+	}
+
+	/* Wait till the lock bit is set in PLL status */
+	if (hdmi_wait_for_bit_change(pll->base,
+			PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
+		DSSERR("cannot lock PLL\n");
+		DSSERR("CFG1 0x%x\n",
+			hdmi_read_reg(pll->base, PLLCTRL_CFG1));
+		DSSERR("CFG2 0x%x\n",
+			hdmi_read_reg(pll->base, PLLCTRL_CFG2));
+		DSSERR("CFG4 0x%x\n",
+			hdmi_read_reg(pll->base, PLLCTRL_CFG4));
+		return -ETIMEDOUT;
+	}
+
+	DSSDBG("PLL locked!\n");
+
+	return 0;
+}
+
+static int hdmi_pll_reset(struct hdmi_pll_data *pll)
+{
+	/* SYSRESET  controlled by power FSM */
+	REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
+
+	/* READ 0x0 reset is in progress */
+	if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
+			!= 1) {
+		DSSERR("Failed to sysreset PLL\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
+{
+	u16 r = 0;
+
+	r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
+	if (r)
+		return r;
+
+	r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
+	if (r)
+		return r;
+
+	r = hdmi_pll_reset(pll);
+	if (r)
+		return r;
+
+	r = hdmi_pll_config(pll);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
+{
+	hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
+}
+
+#define PLL_OFFSET	0x200
+#define PLL_SIZE	0x100
+
+int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
+{
+	struct resource *res;
+	struct resource temp_res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
+	if (!res) {
+		DSSDBG("can't get PLL mem resource by name\n");
+		/*
+		 * if hwmod/DT doesn't have the memory resource information
+		 * split into HDMI sub blocks by name, we try again by getting
+		 * the platform's first resource. this code will be removed when
+		 * the driver can get the mem resources by name
+		 */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DSSERR("can't get PLL mem resource\n");
+			return -EINVAL;
+		}
+
+		temp_res.start = res->start + PLL_OFFSET;
+		temp_res.end = temp_res.start + PLL_SIZE - 1;
+		res = &temp_res;
+	}
+
+	pll->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!pll->base) {
+		DSSERR("can't ioremap PLLCTRL\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_wp.c b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
new file mode 100644
index 000000000000..f5f4ccf50d90
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
@@ -0,0 +1,275 @@
+/*
+ * HDMI wrapper
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#define DSS_SUBSYS_NAME "HDMIWP"
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "hdmi.h"
+
+void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r))
+
+	DUMPREG(HDMI_WP_REVISION);
+	DUMPREG(HDMI_WP_SYSCONFIG);
+	DUMPREG(HDMI_WP_IRQSTATUS_RAW);
+	DUMPREG(HDMI_WP_IRQSTATUS);
+	DUMPREG(HDMI_WP_IRQENABLE_SET);
+	DUMPREG(HDMI_WP_IRQENABLE_CLR);
+	DUMPREG(HDMI_WP_IRQWAKEEN);
+	DUMPREG(HDMI_WP_PWR_CTRL);
+	DUMPREG(HDMI_WP_DEBOUNCE);
+	DUMPREG(HDMI_WP_VIDEO_CFG);
+	DUMPREG(HDMI_WP_VIDEO_SIZE);
+	DUMPREG(HDMI_WP_VIDEO_TIMING_H);
+	DUMPREG(HDMI_WP_VIDEO_TIMING_V);
+	DUMPREG(HDMI_WP_CLK);
+	DUMPREG(HDMI_WP_AUDIO_CFG);
+	DUMPREG(HDMI_WP_AUDIO_CFG2);
+	DUMPREG(HDMI_WP_AUDIO_CTRL);
+	DUMPREG(HDMI_WP_AUDIO_DATA);
+}
+
+u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp)
+{
+	return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
+}
+
+void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus)
+{
+	hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus);
+	/* flush posted write */
+	hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
+}
+
+void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask)
+{
+	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask);
+}
+
+void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask)
+{
+	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask);
+}
+
+/* PHY_PWR_CMD */
+int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val)
+{
+	/* Return if already the state */
+	if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val)
+		return 0;
+
+	/* Command for power control of HDMI PHY */
+	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6);
+
+	/* Status of the power control of HDMI PHY */
+	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val)
+			!= val) {
+		DSSERR("Failed to set PHY power mode to %d\n", val);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+/* PLL_PWR_CMD */
+int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val)
+{
+	/* Command for power control of HDMI PLL */
+	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2);
+
+	/* wait till PHY_PWR_STATUS is set */
+	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val)
+			!= val) {
+		DSSERR("Failed to set PLL_PWR_STATUS\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+int hdmi_wp_video_start(struct hdmi_wp_data *wp)
+{
+	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31);
+
+	return 0;
+}
+
+void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
+{
+	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);
+}
+
+void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
+		struct hdmi_video_format *video_fmt)
+{
+	u32 l = 0;
+
+	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode,
+		10, 8);
+
+	l |= FLD_VAL(video_fmt->y_res, 31, 16);
+	l |= FLD_VAL(video_fmt->x_res, 15, 0);
+	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l);
+}
+
+void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
+		struct omap_video_timings *timings)
+{
+	u32 r;
+	bool vsync_pol, hsync_pol;
+	DSSDBG("Enter hdmi_wp_video_config_interface\n");
+
+	vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
+	hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
+
+	r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);
+	r = FLD_MOD(r, vsync_pol, 7, 7);
+	r = FLD_MOD(r, hsync_pol, 6, 6);
+	r = FLD_MOD(r, timings->interlace, 3, 3);
+	r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
+	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);
+}
+
+void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
+		struct omap_video_timings *timings)
+{
+	u32 timing_h = 0;
+	u32 timing_v = 0;
+
+	DSSDBG("Enter hdmi_wp_video_config_timing\n");
+
+	timing_h |= FLD_VAL(timings->hbp, 31, 20);
+	timing_h |= FLD_VAL(timings->hfp, 19, 8);
+	timing_h |= FLD_VAL(timings->hsw, 7, 0);
+	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);
+
+	timing_v |= FLD_VAL(timings->vbp, 31, 20);
+	timing_v |= FLD_VAL(timings->vfp, 19, 8);
+	timing_v |= FLD_VAL(timings->vsw, 7, 0);
+	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);
+}
+
+void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
+		struct omap_video_timings *timings, struct hdmi_config *param)
+{
+	DSSDBG("Enter hdmi_wp_video_init_format\n");
+
+	video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
+	video_fmt->y_res = param->timings.y_res;
+	video_fmt->x_res = param->timings.x_res;
+	if (param->timings.interlace)
+		video_fmt->y_res /= 2;
+
+	timings->hbp = param->timings.hbp;
+	timings->hfp = param->timings.hfp;
+	timings->hsw = param->timings.hsw;
+	timings->vbp = param->timings.vbp;
+	timings->vfp = param->timings.vfp;
+	timings->vsw = param->timings.vsw;
+	timings->vsync_level = param->timings.vsync_level;
+	timings->hsync_level = param->timings.hsync_level;
+	timings->interlace = param->timings.interlace;
+}
+
+#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
+void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
+		struct hdmi_audio_format *aud_fmt)
+{
+	u32 r;
+
+	DSSDBG("Enter hdmi_wp_audio_config_format\n");
+
+	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
+	r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
+	r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
+	r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
+	r = FLD_MOD(r, aud_fmt->type, 4, 4);
+	r = FLD_MOD(r, aud_fmt->justification, 3, 3);
+	r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
+	r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
+	r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
+	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r);
+}
+
+void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
+		struct hdmi_audio_dma *aud_dma)
+{
+	u32 r;
+
+	DSSDBG("Enter hdmi_wp_audio_config_dma\n");
+
+	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2);
+	r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
+	r = FLD_MOD(r, aud_dma->block_size, 7, 0);
+	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r);
+
+	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL);
+	r = FLD_MOD(r, aud_dma->mode, 9, 9);
+	r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
+	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r);
+}
+
+int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable)
+{
+	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31);
+
+	return 0;
+}
+
+int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
+{
+	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30);
+
+	return 0;
+}
+#endif
+
+#define WP_SIZE	0x200
+
+int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
+{
+	struct resource *res;
+	struct resource temp_res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp");
+	if (!res) {
+		DSSDBG("can't get WP mem resource by name\n");
+		/*
+		 * if hwmod/DT doesn't have the memory resource information
+		 * split into HDMI sub blocks by name, we try again by getting
+		 * the platform's first resource. this code will be removed when
+		 * the driver can get the mem resources by name
+		 */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DSSERR("can't get WP mem resource\n");
+			return -EINVAL;
+		}
+
+		temp_res.start = res->start;
+		temp_res.end = temp_res.start + WP_SIZE - 1;
+		res = &temp_res;
+	}
+
+	wp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!wp->base) {
+		DSSERR("can't ioremap HDMI WP\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/omap2/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/dss/manager-sysfs.c
new file mode 100644
index 000000000000..37b59fe28dc8
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/manager-sysfs.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "MANAGER"
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
+}
+
+static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
+{
+	struct omap_dss_device *dssdev = mgr->get_device(mgr);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
+			dssdev->name : "<none>");
+}
+
+static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
+		const char *buf, size_t size)
+{
+	int r = 0;
+	size_t len = size;
+	struct omap_dss_device *dssdev = NULL;
+	struct omap_dss_device *old_dssdev;
+
+	int match(struct omap_dss_device *dssdev, void *data)
+	{
+		const char *str = data;
+		return sysfs_streq(dssdev->name, str);
+	}
+
+	if (buf[size-1] == '\n')
+		--len;
+
+	if (len > 0)
+		dssdev = omap_dss_find_device((void *)buf, match);
+
+	if (len > 0 && dssdev == NULL)
+		return -EINVAL;
+
+	if (dssdev) {
+		DSSDBG("display %s found\n", dssdev->name);
+
+		if (omapdss_device_is_connected(dssdev)) {
+			DSSERR("new display is already connected\n");
+			r = -EINVAL;
+			goto put_device;
+		}
+
+		if (omapdss_device_is_enabled(dssdev)) {
+			DSSERR("new display is not disabled\n");
+			r = -EINVAL;
+			goto put_device;
+		}
+	}
+
+	old_dssdev = mgr->get_device(mgr);
+	if (old_dssdev) {
+		if (omapdss_device_is_enabled(old_dssdev)) {
+			DSSERR("old display is not disabled\n");
+			r = -EINVAL;
+			goto put_device;
+		}
+
+		old_dssdev->driver->disconnect(old_dssdev);
+	}
+
+	if (dssdev) {
+		r = dssdev->driver->connect(dssdev);
+		if (r) {
+			DSSERR("failed to connect new device\n");
+			goto put_device;
+		}
+
+		old_dssdev = mgr->get_device(mgr);
+		if (old_dssdev != dssdev) {
+			DSSERR("failed to connect device to this manager\n");
+			dssdev->driver->disconnect(dssdev);
+			goto put_device;
+		}
+
+		r = mgr->apply(mgr);
+		if (r) {
+			DSSERR("failed to apply dispc config\n");
+			goto put_device;
+		}
+	}
+
+put_device:
+	if (dssdev)
+		omap_dss_put_device(dssdev);
+
+	return r ? r : size;
+}
+
+static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
+					  char *buf)
+{
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
+}
+
+static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
+					   const char *buf, size_t size)
+{
+	struct omap_overlay_manager_info info;
+	u32 color;
+	int r;
+
+	r = kstrtouint(buf, 0, &color);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.default_color = color;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static const char *trans_key_type_str[] = {
+	"gfx-destination",
+	"video-source",
+};
+
+static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
+					   char *buf)
+{
+	enum omap_dss_trans_key_type key_type;
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	key_type = info.trans_key_type;
+	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
+}
+
+static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
+					    const char *buf, size_t size)
+{
+	enum omap_dss_trans_key_type key_type;
+	struct omap_overlay_manager_info info;
+	int r;
+
+	for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+			key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
+		if (sysfs_streq(buf, trans_key_type_str[key_type]))
+			break;
+	}
+
+	if (key_type == ARRAY_SIZE(trans_key_type_str))
+		return -EINVAL;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.trans_key_type = key_type;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
+					    char *buf)
+{
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
+}
+
+static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
+					     const char *buf, size_t size)
+{
+	struct omap_overlay_manager_info info;
+	u32 key_value;
+	int r;
+
+	r = kstrtouint(buf, 0, &key_value);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.trans_key = key_value;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
+					      char *buf)
+{
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
+}
+
+static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
+					       const char *buf, size_t size)
+{
+	struct omap_overlay_manager_info info;
+	bool enable;
+	int r;
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.trans_enabled = enable;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_alpha_blending_enabled_show(
+		struct omap_overlay_manager *mgr, char *buf)
+{
+	struct omap_overlay_manager_info info;
+
+	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
+		return -ENODEV;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+		info.partial_alpha_enabled);
+}
+
+static ssize_t manager_alpha_blending_enabled_store(
+		struct omap_overlay_manager *mgr,
+		const char *buf, size_t size)
+{
+	struct omap_overlay_manager_info info;
+	bool enable;
+	int r;
+
+	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
+		return -ENODEV;
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.partial_alpha_enabled = enable;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
+		char *buf)
+{
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
+}
+
+static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
+		const char *buf, size_t size)
+{
+	struct omap_overlay_manager_info info;
+	int r;
+	bool enable;
+
+	if (!dss_has_feature(FEAT_CPR))
+		return -ENODEV;
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	if (info.cpr_enable == enable)
+		return size;
+
+	info.cpr_enable = enable;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
+		char *buf)
+{
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE,
+			"%d %d %d %d %d %d %d %d %d\n",
+			info.cpr_coefs.rr,
+			info.cpr_coefs.rg,
+			info.cpr_coefs.rb,
+			info.cpr_coefs.gr,
+			info.cpr_coefs.gg,
+			info.cpr_coefs.gb,
+			info.cpr_coefs.br,
+			info.cpr_coefs.bg,
+			info.cpr_coefs.bb);
+}
+
+static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
+		const char *buf, size_t size)
+{
+	struct omap_overlay_manager_info info;
+	struct omap_dss_cpr_coefs coefs;
+	int r, i;
+	s16 *arr;
+
+	if (!dss_has_feature(FEAT_CPR))
+		return -ENODEV;
+
+	if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
+				&coefs.rr, &coefs.rg, &coefs.rb,
+				&coefs.gr, &coefs.gg, &coefs.gb,
+				&coefs.br, &coefs.bg, &coefs.bb) != 9)
+		return -EINVAL;
+
+	arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
+		coefs.gr, coefs.gg, coefs.gb,
+		coefs.br, coefs.bg, coefs.bb };
+
+	for (i = 0; i < 9; ++i) {
+		if (arr[i] < -512 || arr[i] > 511)
+			return -EINVAL;
+	}
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.cpr_coefs = coefs;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+struct manager_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct omap_overlay_manager *, char *);
+	ssize_t	(*store)(struct omap_overlay_manager *, const char *, size_t);
+};
+
+#define MANAGER_ATTR(_name, _mode, _show, _store) \
+	struct manager_attribute manager_attr_##_name = \
+	__ATTR(_name, _mode, _show, _store)
+
+static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
+static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
+		manager_display_show, manager_display_store);
+static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
+		manager_default_color_show, manager_default_color_store);
+static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
+		manager_trans_key_type_show, manager_trans_key_type_store);
+static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
+		manager_trans_key_value_show, manager_trans_key_value_store);
+static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
+		manager_trans_key_enabled_show,
+		manager_trans_key_enabled_store);
+static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
+		manager_alpha_blending_enabled_show,
+		manager_alpha_blending_enabled_store);
+static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
+		manager_cpr_enable_show,
+		manager_cpr_enable_store);
+static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
+		manager_cpr_coef_show,
+		manager_cpr_coef_store);
+
+
+static struct attribute *manager_sysfs_attrs[] = {
+	&manager_attr_name.attr,
+	&manager_attr_display.attr,
+	&manager_attr_default_color.attr,
+	&manager_attr_trans_key_type.attr,
+	&manager_attr_trans_key_value.attr,
+	&manager_attr_trans_key_enabled.attr,
+	&manager_attr_alpha_blending_enabled.attr,
+	&manager_attr_cpr_enable.attr,
+	&manager_attr_cpr_coef.attr,
+	NULL
+};
+
+static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
+		char *buf)
+{
+	struct omap_overlay_manager *manager;
+	struct manager_attribute *manager_attr;
+
+	manager = container_of(kobj, struct omap_overlay_manager, kobj);
+	manager_attr = container_of(attr, struct manager_attribute, attr);
+
+	if (!manager_attr->show)
+		return -ENOENT;
+
+	return manager_attr->show(manager, buf);
+}
+
+static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
+		const char *buf, size_t size)
+{
+	struct omap_overlay_manager *manager;
+	struct manager_attribute *manager_attr;
+
+	manager = container_of(kobj, struct omap_overlay_manager, kobj);
+	manager_attr = container_of(attr, struct manager_attribute, attr);
+
+	if (!manager_attr->store)
+		return -ENOENT;
+
+	return manager_attr->store(manager, buf, size);
+}
+
+static const struct sysfs_ops manager_sysfs_ops = {
+	.show = manager_attr_show,
+	.store = manager_attr_store,
+};
+
+static struct kobj_type manager_ktype = {
+	.sysfs_ops = &manager_sysfs_ops,
+	.default_attrs = manager_sysfs_attrs,
+};
+
+int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
+		struct platform_device *pdev)
+{
+	return kobject_init_and_add(&mgr->kobj, &manager_ktype,
+			&pdev->dev.kobj, "manager%d", mgr->id);
+}
+
+void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
+{
+	kobject_del(&mgr->kobj);
+	kobject_put(&mgr->kobj);
+
+	memset(&mgr->kobj, 0, sizeof(mgr->kobj));
+}
diff --git a/drivers/video/fbdev/omap2/dss/manager.c b/drivers/video/fbdev/omap2/dss/manager.c
new file mode 100644
index 000000000000..1aac9b4191a9
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/manager.c
@@ -0,0 +1,263 @@
+/*
+ * linux/drivers/video/omap2/dss/manager.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "MANAGER"
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static int num_managers;
+static struct omap_overlay_manager *managers;
+
+int dss_init_overlay_managers(void)
+{
+	int i;
+
+	num_managers = dss_feat_get_num_mgrs();
+
+	managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers,
+			GFP_KERNEL);
+
+	BUG_ON(managers == NULL);
+
+	for (i = 0; i < num_managers; ++i) {
+		struct omap_overlay_manager *mgr = &managers[i];
+
+		switch (i) {
+		case 0:
+			mgr->name = "lcd";
+			mgr->id = OMAP_DSS_CHANNEL_LCD;
+			break;
+		case 1:
+			mgr->name = "tv";
+			mgr->id = OMAP_DSS_CHANNEL_DIGIT;
+			break;
+		case 2:
+			mgr->name = "lcd2";
+			mgr->id = OMAP_DSS_CHANNEL_LCD2;
+			break;
+		case 3:
+			mgr->name = "lcd3";
+			mgr->id = OMAP_DSS_CHANNEL_LCD3;
+			break;
+		}
+
+		mgr->caps = 0;
+		mgr->supported_displays =
+			dss_feat_get_supported_displays(mgr->id);
+		mgr->supported_outputs =
+			dss_feat_get_supported_outputs(mgr->id);
+
+		INIT_LIST_HEAD(&mgr->overlays);
+	}
+
+	return 0;
+}
+
+int dss_init_overlay_managers_sysfs(struct platform_device *pdev)
+{
+	int i, r;
+
+	for (i = 0; i < num_managers; ++i) {
+		struct omap_overlay_manager *mgr = &managers[i];
+
+		r = dss_manager_kobj_init(mgr, pdev);
+		if (r)
+			DSSERR("failed to create sysfs file\n");
+	}
+
+	return 0;
+}
+
+void dss_uninit_overlay_managers(void)
+{
+	kfree(managers);
+	managers = NULL;
+	num_managers = 0;
+}
+
+void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < num_managers; ++i) {
+		struct omap_overlay_manager *mgr = &managers[i];
+
+		dss_manager_kobj_uninit(mgr);
+	}
+}
+
+int omap_dss_get_num_overlay_managers(void)
+{
+	return num_managers;
+}
+EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
+
+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
+{
+	if (num >= num_managers)
+		return NULL;
+
+	return &managers[num];
+}
+EXPORT_SYMBOL(omap_dss_get_overlay_manager);
+
+int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
+		const struct omap_overlay_manager_info *info)
+{
+	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
+		/*
+		 * OMAP3 supports only graphics source transparency color key
+		 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
+		 * Alpha Mode.
+		 */
+		if (info->partial_alpha_enabled && info->trans_enabled
+			&& info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) {
+			DSSERR("check_manager: illegal transparency key\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
+		struct omap_overlay_info **overlay_infos)
+{
+	struct omap_overlay *ovl1, *ovl2;
+	struct omap_overlay_info *info1, *info2;
+
+	list_for_each_entry(ovl1, &mgr->overlays, list) {
+		info1 = overlay_infos[ovl1->id];
+
+		if (info1 == NULL)
+			continue;
+
+		list_for_each_entry(ovl2, &mgr->overlays, list) {
+			if (ovl1 == ovl2)
+				continue;
+
+			info2 = overlay_infos[ovl2->id];
+
+			if (info2 == NULL)
+				continue;
+
+			if (info1->zorder == info2->zorder) {
+				DSSERR("overlays %d and %d have the same "
+						"zorder %d\n",
+					ovl1->id, ovl2->id, info1->zorder);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings)
+{
+	if (!dispc_mgr_timings_ok(mgr->id, timings)) {
+		DSSERR("check_manager: invalid timings\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr,
+		const struct dss_lcd_mgr_config *config)
+{
+	struct dispc_clock_info cinfo = config->clock_info;
+	int dl = config->video_port_width;
+	bool stallmode = config->stallmode;
+	bool fifohandcheck = config->fifohandcheck;
+
+	if (cinfo.lck_div < 1 || cinfo.lck_div > 255)
+		return -EINVAL;
+
+	if (cinfo.pck_div < 1 || cinfo.pck_div > 255)
+		return -EINVAL;
+
+	if (dl != 12 && dl != 16 && dl != 18 && dl != 24)
+		return -EINVAL;
+
+	/* fifohandcheck should be used only with stallmode */
+	if (stallmode == false && fifohandcheck == true)
+		return -EINVAL;
+
+	/*
+	 * io pad mode can be only checked by using dssdev connected to the
+	 * manager. Ignore checking these for now, add checks when manager
+	 * is capable of holding information related to the connected interface
+	 */
+
+	return 0;
+}
+
+int dss_mgr_check(struct omap_overlay_manager *mgr,
+		struct omap_overlay_manager_info *info,
+		const struct omap_video_timings *mgr_timings,
+		const struct dss_lcd_mgr_config *lcd_config,
+		struct omap_overlay_info **overlay_infos)
+{
+	struct omap_overlay *ovl;
+	int r;
+
+	if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
+		r = dss_mgr_check_zorder(mgr, overlay_infos);
+		if (r)
+			return r;
+	}
+
+	r = dss_mgr_check_timings(mgr, mgr_timings);
+	if (r)
+		return r;
+
+	r = dss_mgr_check_lcd_config(mgr, lcd_config);
+	if (r)
+		return r;
+
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		struct omap_overlay_info *oi;
+		int r;
+
+		oi = overlay_infos[ovl->id];
+
+		if (oi == NULL)
+			continue;
+
+		r = dss_ovl_check(ovl, oi, mgr_timings);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/omap2/dss/output.c b/drivers/video/fbdev/omap2/dss/output.c
new file mode 100644
index 000000000000..2ab3afa615e8
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/output.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Ltd
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+static LIST_HEAD(output_list);
+static DEFINE_MUTEX(output_lock);
+
+int omapdss_output_set_device(struct omap_dss_device *out,
+		struct omap_dss_device *dssdev)
+{
+	int r;
+
+	mutex_lock(&output_lock);
+
+	if (out->dst) {
+		DSSERR("output already has device %s connected to it\n",
+			out->dst->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	if (out->output_type != dssdev->type) {
+		DSSERR("output type and display type don't match\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	out->dst = dssdev;
+	dssdev->src = out;
+
+	mutex_unlock(&output_lock);
+
+	return 0;
+err:
+	mutex_unlock(&output_lock);
+
+	return r;
+}
+EXPORT_SYMBOL(omapdss_output_set_device);
+
+int omapdss_output_unset_device(struct omap_dss_device *out)
+{
+	int r;
+
+	mutex_lock(&output_lock);
+
+	if (!out->dst) {
+		DSSERR("output doesn't have a device connected to it\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
+		DSSERR("device %s is not disabled, cannot unset device\n",
+				out->dst->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	out->dst->src = NULL;
+	out->dst = NULL;
+
+	mutex_unlock(&output_lock);
+
+	return 0;
+err:
+	mutex_unlock(&output_lock);
+
+	return r;
+}
+EXPORT_SYMBOL(omapdss_output_unset_device);
+
+int omapdss_register_output(struct omap_dss_device *out)
+{
+	list_add_tail(&out->list, &output_list);
+	return 0;
+}
+EXPORT_SYMBOL(omapdss_register_output);
+
+void omapdss_unregister_output(struct omap_dss_device *out)
+{
+	list_del(&out->list);
+}
+EXPORT_SYMBOL(omapdss_unregister_output);
+
+struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
+{
+	struct omap_dss_device *out;
+
+	list_for_each_entry(out, &output_list, list) {
+		if (out->id == id)
+			return out;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(omap_dss_get_output);
+
+struct omap_dss_device *omap_dss_find_output(const char *name)
+{
+	struct omap_dss_device *out;
+
+	list_for_each_entry(out, &output_list, list) {
+		if (strcmp(out->name, name) == 0)
+			return omap_dss_get_device(out);
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(omap_dss_find_output);
+
+struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node)
+{
+	struct omap_dss_device *out;
+
+	list_for_each_entry(out, &output_list, list) {
+		if (out->dev->of_node == node)
+			return omap_dss_get_device(out);
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(omap_dss_find_output_by_node);
+
+struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
+{
+	while (dssdev->src)
+		dssdev = dssdev->src;
+
+	if (dssdev->id != 0)
+		return omap_dss_get_device(dssdev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(omapdss_find_output_from_display);
+
+struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_device *out;
+	struct omap_overlay_manager *mgr;
+
+	out = omapdss_find_output_from_display(dssdev);
+
+	if (out == NULL)
+		return NULL;
+
+	mgr = out->manager;
+
+	omap_dss_put_device(out);
+
+	return mgr;
+}
+EXPORT_SYMBOL(omapdss_find_mgr_from_display);
+
+static const struct dss_mgr_ops *dss_mgr_ops;
+
+int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
+{
+	if (dss_mgr_ops)
+		return -EBUSY;
+
+	dss_mgr_ops = mgr_ops;
+
+	return 0;
+}
+EXPORT_SYMBOL(dss_install_mgr_ops);
+
+void dss_uninstall_mgr_ops(void)
+{
+	dss_mgr_ops = NULL;
+}
+EXPORT_SYMBOL(dss_uninstall_mgr_ops);
+
+int dss_mgr_connect(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dst)
+{
+	return dss_mgr_ops->connect(mgr, dst);
+}
+EXPORT_SYMBOL(dss_mgr_connect);
+
+void dss_mgr_disconnect(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dst)
+{
+	dss_mgr_ops->disconnect(mgr, dst);
+}
+EXPORT_SYMBOL(dss_mgr_disconnect);
+
+void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings)
+{
+	dss_mgr_ops->set_timings(mgr, timings);
+}
+EXPORT_SYMBOL(dss_mgr_set_timings);
+
+void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+		const struct dss_lcd_mgr_config *config)
+{
+	dss_mgr_ops->set_lcd_config(mgr, config);
+}
+EXPORT_SYMBOL(dss_mgr_set_lcd_config);
+
+int dss_mgr_enable(struct omap_overlay_manager *mgr)
+{
+	return dss_mgr_ops->enable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_enable);
+
+void dss_mgr_disable(struct omap_overlay_manager *mgr)
+{
+	dss_mgr_ops->disable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_disable);
+
+void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+{
+	dss_mgr_ops->start_update(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_start_update);
+
+int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
+}
+EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
+
+void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
+}
+EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/video/fbdev/omap2/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/dss/overlay-sysfs.c
new file mode 100644
index 000000000000..4cc5ddebfb34
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/overlay-sysfs.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "OVERLAY"
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
+}
+
+static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			ovl->manager ? ovl->manager->name : "<none>");
+}
+
+static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
+		size_t size)
+{
+	int i, r;
+	struct omap_overlay_manager *mgr = NULL;
+	struct omap_overlay_manager *old_mgr;
+	int len = size;
+
+	if (buf[size-1] == '\n')
+		--len;
+
+	if (len > 0) {
+		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+			mgr = omap_dss_get_overlay_manager(i);
+
+			if (sysfs_streq(buf, mgr->name))
+				break;
+
+			mgr = NULL;
+		}
+	}
+
+	if (len > 0 && mgr == NULL)
+		return -EINVAL;
+
+	if (mgr)
+		DSSDBG("manager %s found\n", mgr->name);
+
+	if (mgr == ovl->manager)
+		return size;
+
+	old_mgr = ovl->manager;
+
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
+	/* detach old manager */
+	if (old_mgr) {
+		r = ovl->unset_manager(ovl);
+		if (r) {
+			DSSERR("detach failed\n");
+			goto err;
+		}
+
+		r = old_mgr->apply(old_mgr);
+		if (r)
+			goto err;
+	}
+
+	if (mgr) {
+		r = ovl->set_manager(ovl, mgr);
+		if (r) {
+			DSSERR("Failed to attach overlay\n");
+			goto err;
+		}
+
+		r = mgr->apply(mgr);
+		if (r)
+			goto err;
+	}
+
+	dispc_runtime_put();
+
+	return size;
+
+err:
+	dispc_runtime_put();
+	return r;
+}
+
+static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
+{
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+			info.width, info.height);
+}
+
+static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
+{
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
+}
+
+static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
+{
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+			info.pos_x, info.pos_y);
+}
+
+static ssize_t overlay_position_store(struct omap_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	char *last;
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.pos_x = simple_strtoul(buf, &last, 10);
+	++last;
+	if (last - buf >= size)
+		return -EINVAL;
+
+	info.pos_y = simple_strtoul(last, &last, 10);
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
+{
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+			info.out_width, info.out_height);
+}
+
+static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	char *last;
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.out_width = simple_strtoul(buf, &last, 10);
+	++last;
+	if (last - buf >= size)
+		return -EINVAL;
+
+	info.out_height = simple_strtoul(last, &last, 10);
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
+}
+
+static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
+		size_t size)
+{
+	int r;
+	bool enable;
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	if (enable)
+		r = ovl->enable(ovl);
+	else
+		r = ovl->disable(ovl);
+
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
+{
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			info.global_alpha);
+}
+
+static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	u8 alpha;
+	struct omap_overlay_info info;
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
+		return -ENODEV;
+
+	r = kstrtou8(buf, 0, &alpha);
+	if (r)
+		return r;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.global_alpha = alpha;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
+		char *buf)
+{
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			info.pre_mult_alpha);
+}
+
+static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	u8 alpha;
+	struct omap_overlay_info info;
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+		return -ENODEV;
+
+	r = kstrtou8(buf, 0, &alpha);
+	if (r)
+		return r;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.pre_mult_alpha = alpha;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
+{
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
+}
+
+static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	u8 zorder;
+	struct omap_overlay_info info;
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+		return -ENODEV;
+
+	r = kstrtou8(buf, 0, &zorder);
+	if (r)
+		return r;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.zorder = zorder;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+struct overlay_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct omap_overlay *, char *);
+	ssize_t	(*store)(struct omap_overlay *, const char *, size_t);
+};
+
+#define OVERLAY_ATTR(_name, _mode, _show, _store) \
+	struct overlay_attribute overlay_attr_##_name = \
+	__ATTR(_name, _mode, _show, _store)
+
+static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
+static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
+		overlay_manager_show, overlay_manager_store);
+static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
+static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
+static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
+		overlay_position_show, overlay_position_store);
+static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
+		overlay_output_size_show, overlay_output_size_store);
+static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
+		overlay_enabled_show, overlay_enabled_store);
+static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
+		overlay_global_alpha_show, overlay_global_alpha_store);
+static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
+		overlay_pre_mult_alpha_show,
+		overlay_pre_mult_alpha_store);
+static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
+		overlay_zorder_show, overlay_zorder_store);
+
+static struct attribute *overlay_sysfs_attrs[] = {
+	&overlay_attr_name.attr,
+	&overlay_attr_manager.attr,
+	&overlay_attr_input_size.attr,
+	&overlay_attr_screen_width.attr,
+	&overlay_attr_position.attr,
+	&overlay_attr_output_size.attr,
+	&overlay_attr_enabled.attr,
+	&overlay_attr_global_alpha.attr,
+	&overlay_attr_pre_mult_alpha.attr,
+	&overlay_attr_zorder.attr,
+	NULL
+};
+
+static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
+		char *buf)
+{
+	struct omap_overlay *overlay;
+	struct overlay_attribute *overlay_attr;
+
+	overlay = container_of(kobj, struct omap_overlay, kobj);
+	overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+	if (!overlay_attr->show)
+		return -ENOENT;
+
+	return overlay_attr->show(overlay, buf);
+}
+
+static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
+		const char *buf, size_t size)
+{
+	struct omap_overlay *overlay;
+	struct overlay_attribute *overlay_attr;
+
+	overlay = container_of(kobj, struct omap_overlay, kobj);
+	overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+	if (!overlay_attr->store)
+		return -ENOENT;
+
+	return overlay_attr->store(overlay, buf, size);
+}
+
+static const struct sysfs_ops overlay_sysfs_ops = {
+	.show = overlay_attr_show,
+	.store = overlay_attr_store,
+};
+
+static struct kobj_type overlay_ktype = {
+	.sysfs_ops = &overlay_sysfs_ops,
+	.default_attrs = overlay_sysfs_attrs,
+};
+
+int dss_overlay_kobj_init(struct omap_overlay *ovl,
+		struct platform_device *pdev)
+{
+	return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
+			&pdev->dev.kobj, "overlay%d", ovl->id);
+}
+
+void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
+{
+	kobject_del(&ovl->kobj);
+	kobject_put(&ovl->kobj);
+}
diff --git a/drivers/video/fbdev/omap2/dss/overlay.c b/drivers/video/fbdev/omap2/dss/overlay.c
new file mode 100644
index 000000000000..2f7cee985cdd
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/overlay.c
@@ -0,0 +1,202 @@
+/*
+ * linux/drivers/video/omap2/dss/overlay.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "OVERLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static int num_overlays;
+static struct omap_overlay *overlays;
+
+int omap_dss_get_num_overlays(void)
+{
+	return num_overlays;
+}
+EXPORT_SYMBOL(omap_dss_get_num_overlays);
+
+struct omap_overlay *omap_dss_get_overlay(int num)
+{
+	if (num >= num_overlays)
+		return NULL;
+
+	return &overlays[num];
+}
+EXPORT_SYMBOL(omap_dss_get_overlay);
+
+void dss_init_overlays(struct platform_device *pdev)
+{
+	int i, r;
+
+	num_overlays = dss_feat_get_num_ovls();
+
+	overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays,
+			GFP_KERNEL);
+
+	BUG_ON(overlays == NULL);
+
+	for (i = 0; i < num_overlays; ++i) {
+		struct omap_overlay *ovl = &overlays[i];
+
+		switch (i) {
+		case 0:
+			ovl->name = "gfx";
+			ovl->id = OMAP_DSS_GFX;
+			break;
+		case 1:
+			ovl->name = "vid1";
+			ovl->id = OMAP_DSS_VIDEO1;
+			break;
+		case 2:
+			ovl->name = "vid2";
+			ovl->id = OMAP_DSS_VIDEO2;
+			break;
+		case 3:
+			ovl->name = "vid3";
+			ovl->id = OMAP_DSS_VIDEO3;
+			break;
+		}
+
+		ovl->caps = dss_feat_get_overlay_caps(ovl->id);
+		ovl->supported_modes =
+			dss_feat_get_supported_color_modes(ovl->id);
+
+		r = dss_overlay_kobj_init(ovl, pdev);
+		if (r)
+			DSSERR("failed to create sysfs file\n");
+	}
+}
+
+void dss_uninit_overlays(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < num_overlays; ++i) {
+		struct omap_overlay *ovl = &overlays[i];
+		dss_overlay_kobj_uninit(ovl);
+	}
+
+	kfree(overlays);
+	overlays = NULL;
+	num_overlays = 0;
+}
+
+int dss_ovl_simple_check(struct omap_overlay *ovl,
+		const struct omap_overlay_info *info)
+{
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+		if (info->out_width != 0 && info->width != info->out_width) {
+			DSSERR("check_overlay: overlay %d doesn't support "
+					"scaling\n", ovl->id);
+			return -EINVAL;
+		}
+
+		if (info->out_height != 0 && info->height != info->out_height) {
+			DSSERR("check_overlay: overlay %d doesn't support "
+					"scaling\n", ovl->id);
+			return -EINVAL;
+		}
+	}
+
+	if ((ovl->supported_modes & info->color_mode) == 0) {
+		DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
+				ovl->id, info->color_mode);
+		return -EINVAL;
+	}
+
+	if (info->zorder >= omap_dss_get_num_overlays()) {
+		DSSERR("check_overlay: zorder %d too high\n", info->zorder);
+		return -EINVAL;
+	}
+
+	if (dss_feat_rotation_type_supported(info->rotation_type) == 0) {
+		DSSERR("check_overlay: rotation type %d not supported\n",
+				info->rotation_type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
+		const struct omap_video_timings *mgr_timings)
+{
+	u16 outw, outh;
+	u16 dw, dh;
+
+	dw = mgr_timings->x_res;
+	dh = mgr_timings->y_res;
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+		outw = info->width;
+		outh = info->height;
+	} else {
+		if (info->out_width == 0)
+			outw = info->width;
+		else
+			outw = info->out_width;
+
+		if (info->out_height == 0)
+			outh = info->height;
+		else
+			outh = info->out_height;
+	}
+
+	if (dw < info->pos_x + outw) {
+		DSSERR("overlay %d horizontally not inside the display area "
+				"(%d + %d >= %d)\n",
+				ovl->id, info->pos_x, outw, dw);
+		return -EINVAL;
+	}
+
+	if (dh < info->pos_y + outh) {
+		DSSERR("overlay %d vertically not inside the display area "
+				"(%d + %d >= %d)\n",
+				ovl->id, info->pos_y, outh, dh);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Checks if replication logic should be used. Only use when overlay is in
+ * RGB12U or RGB16 mode, and video port width interface is 18bpp or 24bpp
+ */
+bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
+		enum omap_color_mode mode)
+{
+	if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
+		return false;
+
+	return config.video_port_width > 16;
+}
diff --git a/drivers/video/fbdev/omap2/dss/rfbi.c b/drivers/video/fbdev/omap2/dss/rfbi.c
new file mode 100644
index 000000000000..c8a81a2b879c
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/rfbi.c
@@ -0,0 +1,1058 @@
+/*
+ * linux/drivers/video/omap2/dss/rfbi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "RFBI"
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/kfifo.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/seq_file.h>
+#include <linux/semaphore.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <video/omapdss.h>
+#include "dss.h"
+
+struct rfbi_reg { u16 idx; };
+
+#define RFBI_REG(idx)		((const struct rfbi_reg) { idx })
+
+#define RFBI_REVISION		RFBI_REG(0x0000)
+#define RFBI_SYSCONFIG		RFBI_REG(0x0010)
+#define RFBI_SYSSTATUS		RFBI_REG(0x0014)
+#define RFBI_CONTROL		RFBI_REG(0x0040)
+#define RFBI_PIXEL_CNT		RFBI_REG(0x0044)
+#define RFBI_LINE_NUMBER	RFBI_REG(0x0048)
+#define RFBI_CMD		RFBI_REG(0x004c)
+#define RFBI_PARAM		RFBI_REG(0x0050)
+#define RFBI_DATA		RFBI_REG(0x0054)
+#define RFBI_READ		RFBI_REG(0x0058)
+#define RFBI_STATUS		RFBI_REG(0x005c)
+
+#define RFBI_CONFIG(n)		RFBI_REG(0x0060 + (n)*0x18)
+#define RFBI_ONOFF_TIME(n)	RFBI_REG(0x0064 + (n)*0x18)
+#define RFBI_CYCLE_TIME(n)	RFBI_REG(0x0068 + (n)*0x18)
+#define RFBI_DATA_CYCLE1(n)	RFBI_REG(0x006c + (n)*0x18)
+#define RFBI_DATA_CYCLE2(n)	RFBI_REG(0x0070 + (n)*0x18)
+#define RFBI_DATA_CYCLE3(n)	RFBI_REG(0x0074 + (n)*0x18)
+
+#define RFBI_VSYNC_WIDTH	RFBI_REG(0x0090)
+#define RFBI_HSYNC_WIDTH	RFBI_REG(0x0094)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+	rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
+
+enum omap_rfbi_cycleformat {
+	OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
+	OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
+	OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
+	OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
+};
+
+enum omap_rfbi_datatype {
+	OMAP_DSS_RFBI_DATATYPE_12 = 0,
+	OMAP_DSS_RFBI_DATATYPE_16 = 1,
+	OMAP_DSS_RFBI_DATATYPE_18 = 2,
+	OMAP_DSS_RFBI_DATATYPE_24 = 3,
+};
+
+enum omap_rfbi_parallelmode {
+	OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
+	OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
+	OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
+	OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
+};
+
+static int rfbi_convert_timings(struct rfbi_timings *t);
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
+
+static struct {
+	struct platform_device *pdev;
+	void __iomem	*base;
+
+	unsigned long	l4_khz;
+
+	enum omap_rfbi_datatype datatype;
+	enum omap_rfbi_parallelmode parallelmode;
+
+	enum omap_rfbi_te_mode te_mode;
+	int te_enabled;
+
+	void (*framedone_callback)(void *data);
+	void *framedone_callback_data;
+
+	struct omap_dss_device *dssdev[2];
+
+	struct semaphore bus_lock;
+
+	struct omap_video_timings timings;
+	int pixel_size;
+	int data_lines;
+	struct rfbi_timings intf_timings;
+
+	struct omap_dss_device output;
+} rfbi;
+
+static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
+{
+	__raw_writel(val, rfbi.base + idx.idx);
+}
+
+static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
+{
+	return __raw_readl(rfbi.base + idx.idx);
+}
+
+static int rfbi_runtime_get(void)
+{
+	int r;
+
+	DSSDBG("rfbi_runtime_get\n");
+
+	r = pm_runtime_get_sync(&rfbi.pdev->dev);
+	WARN_ON(r < 0);
+	return r < 0 ? r : 0;
+}
+
+static void rfbi_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("rfbi_runtime_put\n");
+
+	r = pm_runtime_put_sync(&rfbi.pdev->dev);
+	WARN_ON(r < 0 && r != -ENOSYS);
+}
+
+static void rfbi_bus_lock(void)
+{
+	down(&rfbi.bus_lock);
+}
+
+static void rfbi_bus_unlock(void)
+{
+	up(&rfbi.bus_lock);
+}
+
+static void rfbi_write_command(const void *buf, u32 len)
+{
+	switch (rfbi.parallelmode) {
+	case OMAP_DSS_RFBI_PARALLELMODE_8:
+	{
+		const u8 *b = buf;
+		for (; len; len--)
+			rfbi_write_reg(RFBI_CMD, *b++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_16:
+	{
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_CMD, *w++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_9:
+	case OMAP_DSS_RFBI_PARALLELMODE_12:
+	default:
+		BUG();
+	}
+}
+
+static void rfbi_read_data(void *buf, u32 len)
+{
+	switch (rfbi.parallelmode) {
+	case OMAP_DSS_RFBI_PARALLELMODE_8:
+	{
+		u8 *b = buf;
+		for (; len; len--) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*b++ = rfbi_read_reg(RFBI_READ);
+		}
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_16:
+	{
+		u16 *w = buf;
+		BUG_ON(len & ~1);
+		for (; len; len -= 2) {
+			rfbi_write_reg(RFBI_READ, 0);
+			*w++ = rfbi_read_reg(RFBI_READ);
+		}
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_9:
+	case OMAP_DSS_RFBI_PARALLELMODE_12:
+	default:
+		BUG();
+	}
+}
+
+static void rfbi_write_data(const void *buf, u32 len)
+{
+	switch (rfbi.parallelmode) {
+	case OMAP_DSS_RFBI_PARALLELMODE_8:
+	{
+		const u8 *b = buf;
+		for (; len; len--)
+			rfbi_write_reg(RFBI_PARAM, *b++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_16:
+	{
+		const u16 *w = buf;
+		BUG_ON(len & 1);
+		for (; len; len -= 2)
+			rfbi_write_reg(RFBI_PARAM, *w++);
+		break;
+	}
+
+	case OMAP_DSS_RFBI_PARALLELMODE_9:
+	case OMAP_DSS_RFBI_PARALLELMODE_12:
+	default:
+		BUG();
+
+	}
+}
+
+static void rfbi_write_pixels(const void __iomem *buf, int scr_width,
+		u16 x, u16 y,
+		u16 w, u16 h)
+{
+	int start_offset = scr_width * y + x;
+	int horiz_offset = scr_width - w;
+	int i;
+
+	if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
+	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
+		const u16 __iomem *pd = buf;
+		pd += start_offset;
+
+		for (; h; --h) {
+			for (i = 0; i < w; ++i) {
+				const u8 __iomem *b = (const u8 __iomem *)pd;
+				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
+				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
+				++pd;
+			}
+			pd += horiz_offset;
+		}
+	} else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
+	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
+		const u32 __iomem *pd = buf;
+		pd += start_offset;
+
+		for (; h; --h) {
+			for (i = 0; i < w; ++i) {
+				const u8 __iomem *b = (const u8 __iomem *)pd;
+				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
+				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
+				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
+				++pd;
+			}
+			pd += horiz_offset;
+		}
+	} else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
+	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
+		const u16 __iomem *pd = buf;
+		pd += start_offset;
+
+		for (; h; --h) {
+			for (i = 0; i < w; ++i) {
+				rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
+				++pd;
+			}
+			pd += horiz_offset;
+		}
+	} else {
+		BUG();
+	}
+}
+
+static int rfbi_transfer_area(struct omap_dss_device *dssdev,
+		void (*callback)(void *data), void *data)
+{
+	u32 l;
+	int r;
+	struct omap_overlay_manager *mgr = rfbi.output.manager;
+	u16 width = rfbi.timings.x_res;
+	u16 height = rfbi.timings.y_res;
+
+	/*BUG_ON(callback == 0);*/
+	BUG_ON(rfbi.framedone_callback != NULL);
+
+	DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
+
+	dss_mgr_set_timings(mgr, &rfbi.timings);
+
+	r = dss_mgr_enable(mgr);
+	if (r)
+		return r;
+
+	rfbi.framedone_callback = callback;
+	rfbi.framedone_callback_data = data;
+
+	rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
+
+	l = rfbi_read_reg(RFBI_CONTROL);
+	l = FLD_MOD(l, 1, 0, 0); /* enable */
+	if (!rfbi.te_enabled)
+		l = FLD_MOD(l, 1, 4, 4); /* ITE */
+
+	rfbi_write_reg(RFBI_CONTROL, l);
+
+	return 0;
+}
+
+static void framedone_callback(void *data)
+{
+	void (*callback)(void *data);
+
+	DSSDBG("FRAMEDONE\n");
+
+	REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
+
+	callback = rfbi.framedone_callback;
+	rfbi.framedone_callback = NULL;
+
+	if (callback != NULL)
+		callback(rfbi.framedone_callback_data);
+}
+
+#if 1 /* VERBOSE */
+static void rfbi_print_timings(void)
+{
+	u32 l;
+	u32 time;
+
+	l = rfbi_read_reg(RFBI_CONFIG(0));
+	time = 1000000000 / rfbi.l4_khz;
+	if (l & (1 << 4))
+		time *= 2;
+
+	DSSDBG("Tick time %u ps\n", time);
+	l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
+	DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
+		"REONTIME %d, REOFFTIME %d\n",
+		l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
+		(l >> 20) & 0x0f, (l >> 24) & 0x3f);
+
+	l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
+	DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
+		"ACCESSTIME %d\n",
+		(l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
+		(l >> 22) & 0x3f);
+}
+#else
+static void rfbi_print_timings(void) {}
+#endif
+
+
+
+
+static u32 extif_clk_period;
+
+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+	int bus_tick = extif_clk_period * div;
+	return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(struct rfbi_timings *t, int div)
+{
+	t->clk_div = div;
+
+	t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
+
+	t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
+	t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
+	t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
+
+	t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
+	t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
+	t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
+
+	t->access_time = round_to_extif_ticks(t->access_time, div);
+	t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
+	t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
+
+	DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
+	       t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+	DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
+	       t->we_on_time, t->we_off_time, t->re_cycle_time,
+	       t->we_cycle_time);
+	DSSDBG("[reg]rdaccess %d cspulse %d\n",
+	       t->access_time, t->cs_pulse_width);
+
+	return rfbi_convert_timings(t);
+}
+
+static int calc_extif_timings(struct rfbi_timings *t)
+{
+	u32 max_clk_div;
+	int div;
+
+	rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
+	for (div = 1; div <= max_clk_div; div++) {
+		if (calc_reg_timing(t, div) == 0)
+			break;
+	}
+
+	if (div <= max_clk_div)
+		return 0;
+
+	DSSERR("can't setup timings\n");
+	return -1;
+}
+
+
+static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
+{
+	int r;
+
+	if (!t->converted) {
+		r = calc_extif_timings(t);
+		if (r < 0)
+			DSSERR("Failed to calc timings\n");
+	}
+
+	BUG_ON(!t->converted);
+
+	rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
+	rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
+
+	/* TIMEGRANULARITY */
+	REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
+		    (t->tim[2] ? 1 : 0), 4, 4);
+
+	rfbi_print_timings();
+}
+
+static int ps_to_rfbi_ticks(int time, int div)
+{
+	unsigned long tick_ps;
+	int ret;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = 1000000000 / (rfbi.l4_khz) * div;
+
+	ret = (time + tick_ps - 1) / tick_ps;
+
+	return ret;
+}
+
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+	*clk_period = 1000000000 / rfbi.l4_khz;
+	*max_clk_div = 2;
+}
+
+static int rfbi_convert_timings(struct rfbi_timings *t)
+{
+	u32 l;
+	int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
+	int actim, recyc, wecyc;
+	int div = t->clk_div;
+
+	if (div <= 0 || div > 2)
+		return -1;
+
+	/* Make sure that after conversion it still holds that:
+	 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
+	 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
+	 */
+	weon = ps_to_rfbi_ticks(t->we_on_time, div);
+	weoff = ps_to_rfbi_ticks(t->we_off_time, div);
+	if (weoff <= weon)
+		weoff = weon + 1;
+	if (weon > 0x0f)
+		return -1;
+	if (weoff > 0x3f)
+		return -1;
+
+	reon = ps_to_rfbi_ticks(t->re_on_time, div);
+	reoff = ps_to_rfbi_ticks(t->re_off_time, div);
+	if (reoff <= reon)
+		reoff = reon + 1;
+	if (reon > 0x0f)
+		return -1;
+	if (reoff > 0x3f)
+		return -1;
+
+	cson = ps_to_rfbi_ticks(t->cs_on_time, div);
+	csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
+	if (csoff <= cson)
+		csoff = cson + 1;
+	if (csoff < max(weoff, reoff))
+		csoff = max(weoff, reoff);
+	if (cson > 0x0f)
+		return -1;
+	if (csoff > 0x3f)
+		return -1;
+
+	l =  cson;
+	l |= csoff << 4;
+	l |= weon  << 10;
+	l |= weoff << 14;
+	l |= reon  << 20;
+	l |= reoff << 24;
+
+	t->tim[0] = l;
+
+	actim = ps_to_rfbi_ticks(t->access_time, div);
+	if (actim <= reon)
+		actim = reon + 1;
+	if (actim > 0x3f)
+		return -1;
+
+	wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
+	if (wecyc < weoff)
+		wecyc = weoff;
+	if (wecyc > 0x3f)
+		return -1;
+
+	recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
+	if (recyc < reoff)
+		recyc = reoff;
+	if (recyc > 0x3f)
+		return -1;
+
+	cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
+	if (cs_pulse > 0x3f)
+		return -1;
+
+	l =  wecyc;
+	l |= recyc    << 6;
+	l |= cs_pulse << 12;
+	l |= actim    << 22;
+
+	t->tim[1] = l;
+
+	t->tim[2] = div - 1;
+
+	t->converted = 1;
+
+	return 0;
+}
+
+/* xxx FIX module selection missing */
+static int rfbi_setup_te(enum omap_rfbi_te_mode mode,
+			     unsigned hs_pulse_time, unsigned vs_pulse_time,
+			     int hs_pol_inv, int vs_pol_inv, int extif_div)
+{
+	int hs, vs;
+	int min;
+	u32 l;
+
+	hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
+	vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
+	if (hs < 2)
+		return -EDOM;
+	if (mode == OMAP_DSS_RFBI_TE_MODE_2)
+		min = 2;
+	else /* OMAP_DSS_RFBI_TE_MODE_1 */
+		min = 4;
+	if (vs < min)
+		return -EDOM;
+	if (vs == hs)
+		return -EINVAL;
+	rfbi.te_mode = mode;
+	DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
+		mode, hs, vs, hs_pol_inv, vs_pol_inv);
+
+	rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
+	rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
+
+	l = rfbi_read_reg(RFBI_CONFIG(0));
+	if (hs_pol_inv)
+		l &= ~(1 << 21);
+	else
+		l |= 1 << 21;
+	if (vs_pol_inv)
+		l &= ~(1 << 20);
+	else
+		l |= 1 << 20;
+
+	return 0;
+}
+
+/* xxx FIX module selection missing */
+static int rfbi_enable_te(bool enable, unsigned line)
+{
+	u32 l;
+
+	DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
+	if (line > (1 << 11) - 1)
+		return -EINVAL;
+
+	l = rfbi_read_reg(RFBI_CONFIG(0));
+	l &= ~(0x3 << 2);
+	if (enable) {
+		rfbi.te_enabled = 1;
+		l |= rfbi.te_mode << 2;
+	} else
+		rfbi.te_enabled = 0;
+	rfbi_write_reg(RFBI_CONFIG(0), l);
+	rfbi_write_reg(RFBI_LINE_NUMBER, line);
+
+	return 0;
+}
+
+static int rfbi_configure_bus(int rfbi_module, int bpp, int lines)
+{
+	u32 l;
+	int cycle1 = 0, cycle2 = 0, cycle3 = 0;
+	enum omap_rfbi_cycleformat cycleformat;
+	enum omap_rfbi_datatype datatype;
+	enum omap_rfbi_parallelmode parallelmode;
+
+	switch (bpp) {
+	case 12:
+		datatype = OMAP_DSS_RFBI_DATATYPE_12;
+		break;
+	case 16:
+		datatype = OMAP_DSS_RFBI_DATATYPE_16;
+		break;
+	case 18:
+		datatype = OMAP_DSS_RFBI_DATATYPE_18;
+		break;
+	case 24:
+		datatype = OMAP_DSS_RFBI_DATATYPE_24;
+		break;
+	default:
+		BUG();
+		return 1;
+	}
+	rfbi.datatype = datatype;
+
+	switch (lines) {
+	case 8:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
+		break;
+	case 9:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
+		break;
+	case 12:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
+		break;
+	case 16:
+		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
+		break;
+	default:
+		BUG();
+		return 1;
+	}
+	rfbi.parallelmode = parallelmode;
+
+	if ((bpp % lines) == 0) {
+		switch (bpp / lines) {
+		case 1:
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
+			break;
+		case 2:
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
+			break;
+		case 3:
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
+			break;
+		default:
+			BUG();
+			return 1;
+		}
+	} else if ((2 * bpp % lines) == 0) {
+		if ((2 * bpp / lines) == 3)
+			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
+		else {
+			BUG();
+			return 1;
+		}
+	} else {
+		BUG();
+		return 1;
+	}
+
+	switch (cycleformat) {
+	case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
+		cycle1 = lines;
+		break;
+
+	case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
+		cycle1 = lines;
+		cycle2 = lines;
+		break;
+
+	case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
+		cycle1 = lines;
+		cycle2 = lines;
+		cycle3 = lines;
+		break;
+
+	case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
+		cycle1 = lines;
+		cycle2 = (lines / 2) | ((lines / 2) << 16);
+		cycle3 = (lines << 16);
+		break;
+	}
+
+	REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
+
+	l = 0;
+	l |= FLD_VAL(parallelmode, 1, 0);
+	l |= FLD_VAL(0, 3, 2);		/* TRIGGERMODE: ITE */
+	l |= FLD_VAL(0, 4, 4);		/* TIMEGRANULARITY */
+	l |= FLD_VAL(datatype, 6, 5);
+	/* l |= FLD_VAL(2, 8, 7); */	/* L4FORMAT, 2pix/L4 */
+	l |= FLD_VAL(0, 8, 7);	/* L4FORMAT, 1pix/L4 */
+	l |= FLD_VAL(cycleformat, 10, 9);
+	l |= FLD_VAL(0, 12, 11);	/* UNUSEDBITS */
+	l |= FLD_VAL(0, 16, 16);	/* A0POLARITY */
+	l |= FLD_VAL(0, 17, 17);	/* REPOLARITY */
+	l |= FLD_VAL(0, 18, 18);	/* WEPOLARITY */
+	l |= FLD_VAL(0, 19, 19);	/* CSPOLARITY */
+	l |= FLD_VAL(1, 20, 20);	/* TE_VSYNC_POLARITY */
+	l |= FLD_VAL(1, 21, 21);	/* HSYNCPOLARITY */
+	rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
+
+	rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
+	rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
+	rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
+
+
+	l = rfbi_read_reg(RFBI_CONTROL);
+	l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
+	l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
+	rfbi_write_reg(RFBI_CONTROL, l);
+
+
+	DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
+	       bpp, lines, cycle1, cycle2, cycle3);
+
+	return 0;
+}
+
+static int rfbi_configure(struct omap_dss_device *dssdev)
+{
+	return rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+			rfbi.data_lines);
+}
+
+static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
+		void *data)
+{
+	return rfbi_transfer_area(dssdev, callback, data);
+}
+
+static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+{
+	rfbi.timings.x_res = w;
+	rfbi.timings.y_res = h;
+}
+
+static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
+{
+	rfbi.pixel_size = pixel_size;
+}
+
+static void rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+{
+	rfbi.data_lines = data_lines;
+}
+
+static void rfbi_set_interface_timings(struct omap_dss_device *dssdev,
+		struct rfbi_timings *timings)
+{
+	rfbi.intf_timings = *timings;
+}
+
+static void rfbi_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
+
+	if (rfbi_runtime_get())
+		return;
+
+	DUMPREG(RFBI_REVISION);
+	DUMPREG(RFBI_SYSCONFIG);
+	DUMPREG(RFBI_SYSSTATUS);
+	DUMPREG(RFBI_CONTROL);
+	DUMPREG(RFBI_PIXEL_CNT);
+	DUMPREG(RFBI_LINE_NUMBER);
+	DUMPREG(RFBI_CMD);
+	DUMPREG(RFBI_PARAM);
+	DUMPREG(RFBI_DATA);
+	DUMPREG(RFBI_READ);
+	DUMPREG(RFBI_STATUS);
+
+	DUMPREG(RFBI_CONFIG(0));
+	DUMPREG(RFBI_ONOFF_TIME(0));
+	DUMPREG(RFBI_CYCLE_TIME(0));
+	DUMPREG(RFBI_DATA_CYCLE1(0));
+	DUMPREG(RFBI_DATA_CYCLE2(0));
+	DUMPREG(RFBI_DATA_CYCLE3(0));
+
+	DUMPREG(RFBI_CONFIG(1));
+	DUMPREG(RFBI_ONOFF_TIME(1));
+	DUMPREG(RFBI_CYCLE_TIME(1));
+	DUMPREG(RFBI_DATA_CYCLE1(1));
+	DUMPREG(RFBI_DATA_CYCLE2(1));
+	DUMPREG(RFBI_DATA_CYCLE3(1));
+
+	DUMPREG(RFBI_VSYNC_WIDTH);
+	DUMPREG(RFBI_HSYNC_WIDTH);
+
+	rfbi_runtime_put();
+#undef DUMPREG
+}
+
+static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
+{
+	struct omap_overlay_manager *mgr = rfbi.output.manager;
+	struct dss_lcd_mgr_config mgr_config;
+
+	mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
+
+	mgr_config.stallmode = true;
+	/* Do we need fifohandcheck for RFBI? */
+	mgr_config.fifohandcheck = false;
+
+	mgr_config.video_port_width = rfbi.pixel_size;
+	mgr_config.lcden_sig_polarity = 0;
+
+	dss_mgr_set_lcd_config(mgr, &mgr_config);
+
+	/*
+	 * Set rfbi.timings with default values, the x_res and y_res fields
+	 * are expected to be already configured by the panel driver via
+	 * omapdss_rfbi_set_size()
+	 */
+	rfbi.timings.hsw = 1;
+	rfbi.timings.hfp = 1;
+	rfbi.timings.hbp = 1;
+	rfbi.timings.vsw = 1;
+	rfbi.timings.vfp = 0;
+	rfbi.timings.vbp = 0;
+
+	rfbi.timings.interlace = false;
+	rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+	rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+
+	dss_mgr_set_timings(mgr, &rfbi.timings);
+}
+
+static int rfbi_display_enable(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_device *out = &rfbi.output;
+	int r;
+
+	if (out == NULL || out->manager == NULL) {
+		DSSERR("failed to enable display: no output/manager\n");
+		return -ENODEV;
+	}
+
+	r = rfbi_runtime_get();
+	if (r)
+		return r;
+
+	r = dss_mgr_register_framedone_handler(out->manager,
+			framedone_callback, NULL);
+	if (r) {
+		DSSERR("can't get FRAMEDONE irq\n");
+		goto err1;
+	}
+
+	rfbi_config_lcd_manager(dssdev);
+
+	rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+			rfbi.data_lines);
+
+	rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
+
+	return 0;
+err1:
+	rfbi_runtime_put();
+	return r;
+}
+
+static void rfbi_display_disable(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_device *out = &rfbi.output;
+
+	dss_mgr_unregister_framedone_handler(out->manager,
+			framedone_callback, NULL);
+
+	rfbi_runtime_put();
+}
+
+static int rfbi_init_display(struct omap_dss_device *dssdev)
+{
+	rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
+	return 0;
+}
+
+static void rfbi_init_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &rfbi.output;
+
+	out->dev = &pdev->dev;
+	out->id = OMAP_DSS_OUTPUT_DBI;
+	out->output_type = OMAP_DISPLAY_TYPE_DBI;
+	out->name = "rfbi.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
+	out->owner = THIS_MODULE;
+
+	omapdss_register_output(out);
+}
+
+static void __exit rfbi_uninit_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &rfbi.output;
+
+	omapdss_unregister_output(out);
+}
+
+/* RFBI HW IP initialisation */
+static int omap_rfbihw_probe(struct platform_device *pdev)
+{
+	u32 rev;
+	struct resource *rfbi_mem;
+	struct clk *clk;
+	int r;
+
+	rfbi.pdev = pdev;
+
+	sema_init(&rfbi.bus_lock, 1);
+
+	rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
+	if (!rfbi_mem) {
+		DSSERR("can't get IORESOURCE_MEM RFBI\n");
+		return -EINVAL;
+	}
+
+	rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start,
+				 resource_size(rfbi_mem));
+	if (!rfbi.base) {
+		DSSERR("can't ioremap RFBI\n");
+		return -ENOMEM;
+	}
+
+	clk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get ick\n");
+		return PTR_ERR(clk);
+	}
+
+	rfbi.l4_khz = clk_get_rate(clk) / 1000;
+
+	clk_put(clk);
+
+	pm_runtime_enable(&pdev->dev);
+
+	r = rfbi_runtime_get();
+	if (r)
+		goto err_runtime_get;
+
+	msleep(10);
+
+	rev = rfbi_read_reg(RFBI_REVISION);
+	dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
+	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+	rfbi_runtime_put();
+
+	dss_debugfs_create_file("rfbi", rfbi_dump_regs);
+
+	rfbi_init_output(pdev);
+
+	return 0;
+
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
+	return r;
+}
+
+static int __exit omap_rfbihw_remove(struct platform_device *pdev)
+{
+	rfbi_uninit_output(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static int rfbi_runtime_suspend(struct device *dev)
+{
+	dispc_runtime_put();
+
+	return 0;
+}
+
+static int rfbi_runtime_resume(struct device *dev)
+{
+	int r;
+
+	r = dispc_runtime_get();
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+static const struct dev_pm_ops rfbi_pm_ops = {
+	.runtime_suspend = rfbi_runtime_suspend,
+	.runtime_resume = rfbi_runtime_resume,
+};
+
+static struct platform_driver omap_rfbihw_driver = {
+	.probe		= omap_rfbihw_probe,
+	.remove         = __exit_p(omap_rfbihw_remove),
+	.driver         = {
+		.name   = "omapdss_rfbi",
+		.owner  = THIS_MODULE,
+		.pm	= &rfbi_pm_ops,
+	},
+};
+
+int __init rfbi_init_platform_driver(void)
+{
+	return platform_driver_register(&omap_rfbihw_driver);
+}
+
+void __exit rfbi_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omap_rfbihw_driver);
+}
diff --git a/drivers/video/fbdev/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c
new file mode 100644
index 000000000000..911dcc9173a6
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/sdi.c
@@ -0,0 +1,433 @@
+/*
+ * linux/drivers/video/omap2/dss/sdi.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "SDI"
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/of.h>
+
+#include <video/omapdss.h>
+#include "dss.h"
+
+static struct {
+	struct platform_device *pdev;
+
+	bool update_enabled;
+	struct regulator *vdds_sdi_reg;
+
+	struct dss_lcd_mgr_config mgr_config;
+	struct omap_video_timings timings;
+	int datapairs;
+
+	struct omap_dss_device output;
+
+	bool port_initialized;
+} sdi;
+
+struct sdi_clk_calc_ctx {
+	unsigned long pck_min, pck_max;
+
+	unsigned long fck;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+static bool dpi_calc_dss_cb(unsigned long fck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->fck = fck;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static int sdi_calc_clock_div(unsigned long pclk,
+		unsigned long *fck,
+		struct dispc_clock_info *dispc_cinfo)
+{
+	int i;
+	struct sdi_clk_calc_ctx ctx;
+
+	/*
+	 * DSS fclk gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- 1MHz.
+	 */
+
+	for (i = 0; i < 10; ++i) {
+		bool ok;
+
+		memset(&ctx, 0, sizeof(ctx));
+		if (pclk > 1000 * i * i * i)
+			ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
+		else
+			ctx.pck_min = 0;
+		ctx.pck_max = pclk + 1000 * i * i * i;
+
+		ok = dss_div_calc(pclk, ctx.pck_min, dpi_calc_dss_cb, &ctx);
+		if (ok) {
+			*fck = ctx.fck;
+			*dispc_cinfo = ctx.dispc_cinfo;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
+{
+	struct omap_overlay_manager *mgr = sdi.output.manager;
+
+	sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
+
+	sdi.mgr_config.stallmode = false;
+	sdi.mgr_config.fifohandcheck = false;
+
+	sdi.mgr_config.video_port_width = 24;
+	sdi.mgr_config.lcden_sig_polarity = 1;
+
+	dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
+}
+
+static int sdi_display_enable(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_device *out = &sdi.output;
+	struct omap_video_timings *t = &sdi.timings;
+	unsigned long fck;
+	struct dispc_clock_info dispc_cinfo;
+	unsigned long pck;
+	int r;
+
+	if (out == NULL || out->manager == NULL) {
+		DSSERR("failed to enable display: no output/manager\n");
+		return -ENODEV;
+	}
+
+	r = regulator_enable(sdi.vdds_sdi_reg);
+	if (r)
+		goto err_reg_enable;
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
+
+	/* 15.5.9.1.2 */
+	t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+	t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+
+	r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo);
+	if (r)
+		goto err_calc_clock_div;
+
+	sdi.mgr_config.clock_info = dispc_cinfo;
+
+	pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
+
+	if (pck != t->pixelclock) {
+		DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
+			t->pixelclock, pck);
+
+		t->pixelclock = pck;
+	}
+
+
+	dss_mgr_set_timings(out->manager, t);
+
+	r = dss_set_fck_rate(fck);
+	if (r)
+		goto err_set_dss_clock_div;
+
+	sdi_config_lcd_manager(dssdev);
+
+	/*
+	 * LCLK and PCLK divisors are located in shadow registers, and we
+	 * normally write them to DISPC registers when enabling the output.
+	 * However, SDI uses pck-free as source clock for its PLL, and pck-free
+	 * is affected by the divisors. And as we need the PLL before enabling
+	 * the output, we need to write the divisors early.
+	 *
+	 * It seems just writing to the DISPC register is enough, and we don't
+	 * need to care about the shadow register mechanism for pck-free. The
+	 * exact reason for this is unknown.
+	 */
+	dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
+
+	dss_sdi_init(sdi.datapairs);
+	r = dss_sdi_enable();
+	if (r)
+		goto err_sdi_enable;
+	mdelay(2);
+
+	r = dss_mgr_enable(out->manager);
+	if (r)
+		goto err_mgr_enable;
+
+	return 0;
+
+err_mgr_enable:
+	dss_sdi_disable();
+err_sdi_enable:
+err_set_dss_clock_div:
+err_calc_clock_div:
+	dispc_runtime_put();
+err_get_dispc:
+	regulator_disable(sdi.vdds_sdi_reg);
+err_reg_enable:
+	return r;
+}
+
+static void sdi_display_disable(struct omap_dss_device *dssdev)
+{
+	struct omap_overlay_manager *mgr = sdi.output.manager;
+
+	dss_mgr_disable(mgr);
+
+	dss_sdi_disable();
+
+	dispc_runtime_put();
+
+	regulator_disable(sdi.vdds_sdi_reg);
+}
+
+static void sdi_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	sdi.timings = *timings;
+}
+
+static void sdi_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	*timings = sdi.timings;
+}
+
+static int sdi_check_timings(struct omap_dss_device *dssdev,
+			struct omap_video_timings *timings)
+{
+	struct omap_overlay_manager *mgr = sdi.output.manager;
+
+	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
+		return -EINVAL;
+
+	if (timings->pixelclock == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
+{
+	sdi.datapairs = datapairs;
+}
+
+static int sdi_init_regulator(void)
+{
+	struct regulator *vdds_sdi;
+
+	if (sdi.vdds_sdi_reg)
+		return 0;
+
+	vdds_sdi = devm_regulator_get(&sdi.pdev->dev, "vdds_sdi");
+	if (IS_ERR(vdds_sdi)) {
+		if (PTR_ERR(vdds_sdi) != -EPROBE_DEFER)
+			DSSERR("can't get VDDS_SDI regulator\n");
+		return PTR_ERR(vdds_sdi);
+	}
+
+	sdi.vdds_sdi_reg = vdds_sdi;
+
+	return 0;
+}
+
+static int sdi_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct omap_overlay_manager *mgr;
+	int r;
+
+	r = sdi_init_regulator();
+	if (r)
+		return r;
+
+	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
+	if (!mgr)
+		return -ENODEV;
+
+	r = dss_mgr_connect(mgr, dssdev);
+	if (r)
+		return r;
+
+	r = omapdss_output_set_device(dssdev, dst);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dst->name);
+		dss_mgr_disconnect(mgr, dssdev);
+		return r;
+	}
+
+	return 0;
+}
+
+static void sdi_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	WARN_ON(dst != dssdev->dst);
+
+	if (dst != dssdev->dst)
+		return;
+
+	omapdss_output_unset_device(dssdev);
+
+	if (dssdev->manager)
+		dss_mgr_disconnect(dssdev->manager, dssdev);
+}
+
+static const struct omapdss_sdi_ops sdi_ops = {
+	.connect = sdi_connect,
+	.disconnect = sdi_disconnect,
+
+	.enable = sdi_display_enable,
+	.disable = sdi_display_disable,
+
+	.check_timings = sdi_check_timings,
+	.set_timings = sdi_set_timings,
+	.get_timings = sdi_get_timings,
+
+	.set_datapairs = sdi_set_datapairs,
+};
+
+static void sdi_init_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &sdi.output;
+
+	out->dev = &pdev->dev;
+	out->id = OMAP_DSS_OUTPUT_SDI;
+	out->output_type = OMAP_DISPLAY_TYPE_SDI;
+	out->name = "sdi.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
+	out->ops.sdi = &sdi_ops;
+	out->owner = THIS_MODULE;
+
+	omapdss_register_output(out);
+}
+
+static void __exit sdi_uninit_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &sdi.output;
+
+	omapdss_unregister_output(out);
+}
+
+static int omap_sdi_probe(struct platform_device *pdev)
+{
+	sdi.pdev = pdev;
+
+	sdi_init_output(pdev);
+
+	return 0;
+}
+
+static int __exit omap_sdi_remove(struct platform_device *pdev)
+{
+	sdi_uninit_output(pdev);
+
+	return 0;
+}
+
+static struct platform_driver omap_sdi_driver = {
+	.probe		= omap_sdi_probe,
+	.remove         = __exit_p(omap_sdi_remove),
+	.driver         = {
+		.name   = "omapdss_sdi",
+		.owner  = THIS_MODULE,
+	},
+};
+
+int __init sdi_init_platform_driver(void)
+{
+	return platform_driver_register(&omap_sdi_driver);
+}
+
+void __exit sdi_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omap_sdi_driver);
+}
+
+int __init sdi_init_port(struct platform_device *pdev, struct device_node *port)
+{
+	struct device_node *ep;
+	u32 datapairs;
+	int r;
+
+	ep = omapdss_of_get_next_endpoint(port, NULL);
+	if (!ep)
+		return 0;
+
+	r = of_property_read_u32(ep, "datapairs", &datapairs);
+	if (r) {
+		DSSERR("failed to parse datapairs\n");
+		goto err_datapairs;
+	}
+
+	sdi.datapairs = datapairs;
+
+	of_node_put(ep);
+
+	sdi.pdev = pdev;
+
+	sdi_init_output(pdev);
+
+	sdi.port_initialized = true;
+
+	return 0;
+
+err_datapairs:
+	of_node_put(ep);
+
+	return r;
+}
+
+void __exit sdi_uninit_port(void)
+{
+	if (!sdi.port_initialized)
+		return;
+
+	sdi_uninit_output(sdi.pdev);
+}
diff --git a/drivers/video/fbdev/omap2/dss/venc.c b/drivers/video/fbdev/omap2/dss/venc.c
new file mode 100644
index 000000000000..21d81113962b
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/venc.c
@@ -0,0 +1,980 @@
+/*
+ * linux/drivers/video/omap2/dss/venc.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * VENC settings from TI's DSS driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "VENC"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+/* Venc registers */
+#define VENC_REV_ID				0x00
+#define VENC_STATUS				0x04
+#define VENC_F_CONTROL				0x08
+#define VENC_VIDOUT_CTRL			0x10
+#define VENC_SYNC_CTRL				0x14
+#define VENC_LLEN				0x1C
+#define VENC_FLENS				0x20
+#define VENC_HFLTR_CTRL				0x24
+#define VENC_CC_CARR_WSS_CARR			0x28
+#define VENC_C_PHASE				0x2C
+#define VENC_GAIN_U				0x30
+#define VENC_GAIN_V				0x34
+#define VENC_GAIN_Y				0x38
+#define VENC_BLACK_LEVEL			0x3C
+#define VENC_BLANK_LEVEL			0x40
+#define VENC_X_COLOR				0x44
+#define VENC_M_CONTROL				0x48
+#define VENC_BSTAMP_WSS_DATA			0x4C
+#define VENC_S_CARR				0x50
+#define VENC_LINE21				0x54
+#define VENC_LN_SEL				0x58
+#define VENC_L21__WC_CTL			0x5C
+#define VENC_HTRIGGER_VTRIGGER			0x60
+#define VENC_SAVID__EAVID			0x64
+#define VENC_FLEN__FAL				0x68
+#define VENC_LAL__PHASE_RESET			0x6C
+#define VENC_HS_INT_START_STOP_X		0x70
+#define VENC_HS_EXT_START_STOP_X		0x74
+#define VENC_VS_INT_START_X			0x78
+#define VENC_VS_INT_STOP_X__VS_INT_START_Y	0x7C
+#define VENC_VS_INT_STOP_Y__VS_EXT_START_X	0x80
+#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y	0x84
+#define VENC_VS_EXT_STOP_Y			0x88
+#define VENC_AVID_START_STOP_X			0x90
+#define VENC_AVID_START_STOP_Y			0x94
+#define VENC_FID_INT_START_X__FID_INT_START_Y	0xA0
+#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X	0xA4
+#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y	0xA8
+#define VENC_TVDETGP_INT_START_STOP_X		0xB0
+#define VENC_TVDETGP_INT_START_STOP_Y		0xB4
+#define VENC_GEN_CTRL				0xB8
+#define VENC_OUTPUT_CONTROL			0xC4
+#define VENC_OUTPUT_TEST			0xC8
+#define VENC_DAC_B__DAC_C			0xC8
+
+struct venc_config {
+	u32 f_control;
+	u32 vidout_ctrl;
+	u32 sync_ctrl;
+	u32 llen;
+	u32 flens;
+	u32 hfltr_ctrl;
+	u32 cc_carr_wss_carr;
+	u32 c_phase;
+	u32 gain_u;
+	u32 gain_v;
+	u32 gain_y;
+	u32 black_level;
+	u32 blank_level;
+	u32 x_color;
+	u32 m_control;
+	u32 bstamp_wss_data;
+	u32 s_carr;
+	u32 line21;
+	u32 ln_sel;
+	u32 l21__wc_ctl;
+	u32 htrigger_vtrigger;
+	u32 savid__eavid;
+	u32 flen__fal;
+	u32 lal__phase_reset;
+	u32 hs_int_start_stop_x;
+	u32 hs_ext_start_stop_x;
+	u32 vs_int_start_x;
+	u32 vs_int_stop_x__vs_int_start_y;
+	u32 vs_int_stop_y__vs_ext_start_x;
+	u32 vs_ext_stop_x__vs_ext_start_y;
+	u32 vs_ext_stop_y;
+	u32 avid_start_stop_x;
+	u32 avid_start_stop_y;
+	u32 fid_int_start_x__fid_int_start_y;
+	u32 fid_int_offset_y__fid_ext_start_x;
+	u32 fid_ext_start_y__fid_ext_offset_y;
+	u32 tvdetgp_int_start_stop_x;
+	u32 tvdetgp_int_start_stop_y;
+	u32 gen_ctrl;
+};
+
+/* from TRM */
+static const struct venc_config venc_config_pal_trm = {
+	.f_control				= 0,
+	.vidout_ctrl				= 1,
+	.sync_ctrl				= 0x40,
+	.llen					= 0x35F, /* 863 */
+	.flens					= 0x270, /* 624 */
+	.hfltr_ctrl				= 0,
+	.cc_carr_wss_carr			= 0x2F7225ED,
+	.c_phase				= 0,
+	.gain_u					= 0x111,
+	.gain_v					= 0x181,
+	.gain_y					= 0x140,
+	.black_level				= 0x3B,
+	.blank_level				= 0x3B,
+	.x_color				= 0x7,
+	.m_control				= 0x2,
+	.bstamp_wss_data			= 0x3F,
+	.s_carr					= 0x2A098ACB,
+	.line21					= 0,
+	.ln_sel					= 0x01290015,
+	.l21__wc_ctl				= 0x0000F603,
+	.htrigger_vtrigger			= 0,
+
+	.savid__eavid				= 0x06A70108,
+	.flen__fal				= 0x00180270,
+	.lal__phase_reset			= 0x00040135,
+	.hs_int_start_stop_x			= 0x00880358,
+	.hs_ext_start_stop_x			= 0x000F035F,
+	.vs_int_start_x				= 0x01A70000,
+	.vs_int_stop_x__vs_int_start_y		= 0x000001A7,
+	.vs_int_stop_y__vs_ext_start_x		= 0x01AF0000,
+	.vs_ext_stop_x__vs_ext_start_y		= 0x000101AF,
+	.vs_ext_stop_y				= 0x00000025,
+	.avid_start_stop_x			= 0x03530083,
+	.avid_start_stop_y			= 0x026C002E,
+	.fid_int_start_x__fid_int_start_y	= 0x0001008A,
+	.fid_int_offset_y__fid_ext_start_x	= 0x002E0138,
+	.fid_ext_start_y__fid_ext_offset_y	= 0x01380001,
+
+	.tvdetgp_int_start_stop_x		= 0x00140001,
+	.tvdetgp_int_start_stop_y		= 0x00010001,
+	.gen_ctrl				= 0x00FF0000,
+};
+
+/* from TRM */
+static const struct venc_config venc_config_ntsc_trm = {
+	.f_control				= 0,
+	.vidout_ctrl				= 1,
+	.sync_ctrl				= 0x8040,
+	.llen					= 0x359,
+	.flens					= 0x20C,
+	.hfltr_ctrl				= 0,
+	.cc_carr_wss_carr			= 0x043F2631,
+	.c_phase				= 0,
+	.gain_u					= 0x102,
+	.gain_v					= 0x16C,
+	.gain_y					= 0x12F,
+	.black_level				= 0x43,
+	.blank_level				= 0x38,
+	.x_color				= 0x7,
+	.m_control				= 0x1,
+	.bstamp_wss_data			= 0x38,
+	.s_carr					= 0x21F07C1F,
+	.line21					= 0,
+	.ln_sel					= 0x01310011,
+	.l21__wc_ctl				= 0x0000F003,
+	.htrigger_vtrigger			= 0,
+
+	.savid__eavid				= 0x069300F4,
+	.flen__fal				= 0x0016020C,
+	.lal__phase_reset			= 0x00060107,
+	.hs_int_start_stop_x			= 0x008E0350,
+	.hs_ext_start_stop_x			= 0x000F0359,
+	.vs_int_start_x				= 0x01A00000,
+	.vs_int_stop_x__vs_int_start_y		= 0x020701A0,
+	.vs_int_stop_y__vs_ext_start_x		= 0x01AC0024,
+	.vs_ext_stop_x__vs_ext_start_y		= 0x020D01AC,
+	.vs_ext_stop_y				= 0x00000006,
+	.avid_start_stop_x			= 0x03480078,
+	.avid_start_stop_y			= 0x02060024,
+	.fid_int_start_x__fid_int_start_y	= 0x0001008A,
+	.fid_int_offset_y__fid_ext_start_x	= 0x01AC0106,
+	.fid_ext_start_y__fid_ext_offset_y	= 0x01060006,
+
+	.tvdetgp_int_start_stop_x		= 0x00140001,
+	.tvdetgp_int_start_stop_y		= 0x00010001,
+	.gen_ctrl				= 0x00F90000,
+};
+
+static const struct venc_config venc_config_pal_bdghi = {
+	.f_control				= 0,
+	.vidout_ctrl				= 0,
+	.sync_ctrl				= 0,
+	.hfltr_ctrl				= 0,
+	.x_color				= 0,
+	.line21					= 0,
+	.ln_sel					= 21,
+	.htrigger_vtrigger			= 0,
+	.tvdetgp_int_start_stop_x		= 0x00140001,
+	.tvdetgp_int_start_stop_y		= 0x00010001,
+	.gen_ctrl				= 0x00FB0000,
+
+	.llen					= 864-1,
+	.flens					= 625-1,
+	.cc_carr_wss_carr			= 0x2F7625ED,
+	.c_phase				= 0xDF,
+	.gain_u					= 0x111,
+	.gain_v					= 0x181,
+	.gain_y					= 0x140,
+	.black_level				= 0x3e,
+	.blank_level				= 0x3e,
+	.m_control				= 0<<2 | 1<<1,
+	.bstamp_wss_data			= 0x42,
+	.s_carr					= 0x2a098acb,
+	.l21__wc_ctl				= 0<<13 | 0x16<<8 | 0<<0,
+	.savid__eavid				= 0x06A70108,
+	.flen__fal				= 23<<16 | 624<<0,
+	.lal__phase_reset			= 2<<17 | 310<<0,
+	.hs_int_start_stop_x			= 0x00920358,
+	.hs_ext_start_stop_x			= 0x000F035F,
+	.vs_int_start_x				= 0x1a7<<16,
+	.vs_int_stop_x__vs_int_start_y		= 0x000601A7,
+	.vs_int_stop_y__vs_ext_start_x		= 0x01AF0036,
+	.vs_ext_stop_x__vs_ext_start_y		= 0x27101af,
+	.vs_ext_stop_y				= 0x05,
+	.avid_start_stop_x			= 0x03530082,
+	.avid_start_stop_y			= 0x0270002E,
+	.fid_int_start_x__fid_int_start_y	= 0x0005008A,
+	.fid_int_offset_y__fid_ext_start_x	= 0x002E0138,
+	.fid_ext_start_y__fid_ext_offset_y	= 0x01380005,
+};
+
+const struct omap_video_timings omap_dss_pal_timings = {
+	.x_res		= 720,
+	.y_res		= 574,
+	.pixelclock	= 13500000,
+	.hsw		= 64,
+	.hfp		= 12,
+	.hbp		= 68,
+	.vsw		= 5,
+	.vfp		= 5,
+	.vbp		= 41,
+
+	.interlace	= true,
+};
+EXPORT_SYMBOL(omap_dss_pal_timings);
+
+const struct omap_video_timings omap_dss_ntsc_timings = {
+	.x_res		= 720,
+	.y_res		= 482,
+	.pixelclock	= 13500000,
+	.hsw		= 64,
+	.hfp		= 16,
+	.hbp		= 58,
+	.vsw		= 6,
+	.vfp		= 6,
+	.vbp		= 31,
+
+	.interlace	= true,
+};
+EXPORT_SYMBOL(omap_dss_ntsc_timings);
+
+static struct {
+	struct platform_device *pdev;
+	void __iomem *base;
+	struct mutex venc_lock;
+	u32 wss_data;
+	struct regulator *vdda_dac_reg;
+
+	struct clk	*tv_dac_clk;
+
+	struct omap_video_timings timings;
+	enum omap_dss_venc_type type;
+	bool invert_polarity;
+
+	struct omap_dss_device output;
+} venc;
+
+static inline void venc_write_reg(int idx, u32 val)
+{
+	__raw_writel(val, venc.base + idx);
+}
+
+static inline u32 venc_read_reg(int idx)
+{
+	u32 l = __raw_readl(venc.base + idx);
+	return l;
+}
+
+static void venc_write_config(const struct venc_config *config)
+{
+	DSSDBG("write venc conf\n");
+
+	venc_write_reg(VENC_LLEN, config->llen);
+	venc_write_reg(VENC_FLENS, config->flens);
+	venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
+	venc_write_reg(VENC_C_PHASE, config->c_phase);
+	venc_write_reg(VENC_GAIN_U, config->gain_u);
+	venc_write_reg(VENC_GAIN_V, config->gain_v);
+	venc_write_reg(VENC_GAIN_Y, config->gain_y);
+	venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
+	venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
+	venc_write_reg(VENC_M_CONTROL, config->m_control);
+	venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
+			venc.wss_data);
+	venc_write_reg(VENC_S_CARR, config->s_carr);
+	venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
+	venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
+	venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
+	venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
+	venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
+	venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
+	venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
+	venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
+		       config->vs_int_stop_x__vs_int_start_y);
+	venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
+		       config->vs_int_stop_y__vs_ext_start_x);
+	venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
+		       config->vs_ext_stop_x__vs_ext_start_y);
+	venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
+	venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
+	venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
+	venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
+		       config->fid_int_start_x__fid_int_start_y);
+	venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
+		       config->fid_int_offset_y__fid_ext_start_x);
+	venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
+		       config->fid_ext_start_y__fid_ext_offset_y);
+
+	venc_write_reg(VENC_DAC_B__DAC_C,  venc_read_reg(VENC_DAC_B__DAC_C));
+	venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
+	venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
+	venc_write_reg(VENC_X_COLOR, config->x_color);
+	venc_write_reg(VENC_LINE21, config->line21);
+	venc_write_reg(VENC_LN_SEL, config->ln_sel);
+	venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
+	venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
+		       config->tvdetgp_int_start_stop_x);
+	venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
+		       config->tvdetgp_int_start_stop_y);
+	venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
+	venc_write_reg(VENC_F_CONTROL, config->f_control);
+	venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
+}
+
+static void venc_reset(void)
+{
+	int t = 1000;
+
+	venc_write_reg(VENC_F_CONTROL, 1<<8);
+	while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
+		if (--t == 0) {
+			DSSERR("Failed to reset venc\n");
+			return;
+		}
+	}
+
+#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
+	/* the magical sleep that makes things work */
+	/* XXX more info? What bug this circumvents? */
+	msleep(20);
+#endif
+}
+
+static int venc_runtime_get(void)
+{
+	int r;
+
+	DSSDBG("venc_runtime_get\n");
+
+	r = pm_runtime_get_sync(&venc.pdev->dev);
+	WARN_ON(r < 0);
+	return r < 0 ? r : 0;
+}
+
+static void venc_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("venc_runtime_put\n");
+
+	r = pm_runtime_put_sync(&venc.pdev->dev);
+	WARN_ON(r < 0 && r != -ENOSYS);
+}
+
+static const struct venc_config *venc_timings_to_config(
+		struct omap_video_timings *timings)
+{
+	if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+		return &venc_config_pal_trm;
+
+	if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+		return &venc_config_ntsc_trm;
+
+	BUG();
+	return NULL;
+}
+
+static int venc_power_on(struct omap_dss_device *dssdev)
+{
+	struct omap_overlay_manager *mgr = venc.output.manager;
+	u32 l;
+	int r;
+
+	r = venc_runtime_get();
+	if (r)
+		goto err0;
+
+	venc_reset();
+	venc_write_config(venc_timings_to_config(&venc.timings));
+
+	dss_set_venc_output(venc.type);
+	dss_set_dac_pwrdn_bgz(1);
+
+	l = 0;
+
+	if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
+		l |= 1 << 1;
+	else /* S-Video */
+		l |= (1 << 0) | (1 << 2);
+
+	if (venc.invert_polarity == false)
+		l |= 1 << 3;
+
+	venc_write_reg(VENC_OUTPUT_CONTROL, l);
+
+	dss_mgr_set_timings(mgr, &venc.timings);
+
+	r = regulator_enable(venc.vdda_dac_reg);
+	if (r)
+		goto err1;
+
+	r = dss_mgr_enable(mgr);
+	if (r)
+		goto err2;
+
+	return 0;
+
+err2:
+	regulator_disable(venc.vdda_dac_reg);
+err1:
+	venc_write_reg(VENC_OUTPUT_CONTROL, 0);
+	dss_set_dac_pwrdn_bgz(0);
+
+	venc_runtime_put();
+err0:
+	return r;
+}
+
+static void venc_power_off(struct omap_dss_device *dssdev)
+{
+	struct omap_overlay_manager *mgr = venc.output.manager;
+
+	venc_write_reg(VENC_OUTPUT_CONTROL, 0);
+	dss_set_dac_pwrdn_bgz(0);
+
+	dss_mgr_disable(mgr);
+
+	regulator_disable(venc.vdda_dac_reg);
+
+	venc_runtime_put();
+}
+
+static int venc_display_enable(struct omap_dss_device *dssdev)
+{
+	struct omap_dss_device *out = &venc.output;
+	int r;
+
+	DSSDBG("venc_display_enable\n");
+
+	mutex_lock(&venc.venc_lock);
+
+	if (out == NULL || out->manager == NULL) {
+		DSSERR("Failed to enable display: no output/manager\n");
+		r = -ENODEV;
+		goto err0;
+	}
+
+	r = venc_power_on(dssdev);
+	if (r)
+		goto err0;
+
+	venc.wss_data = 0;
+
+	mutex_unlock(&venc.venc_lock);
+
+	return 0;
+err0:
+	mutex_unlock(&venc.venc_lock);
+	return r;
+}
+
+static void venc_display_disable(struct omap_dss_device *dssdev)
+{
+	DSSDBG("venc_display_disable\n");
+
+	mutex_lock(&venc.venc_lock);
+
+	venc_power_off(dssdev);
+
+	mutex_unlock(&venc.venc_lock);
+}
+
+static void venc_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	DSSDBG("venc_set_timings\n");
+
+	mutex_lock(&venc.venc_lock);
+
+	/* Reset WSS data when the TV standard changes. */
+	if (memcmp(&venc.timings, timings, sizeof(*timings)))
+		venc.wss_data = 0;
+
+	venc.timings = *timings;
+
+	dispc_set_tv_pclk(13500000);
+
+	mutex_unlock(&venc.venc_lock);
+}
+
+static int venc_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	DSSDBG("venc_check_timings\n");
+
+	if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+		return 0;
+
+	if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+		return 0;
+
+	return -EINVAL;
+}
+
+static void venc_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	mutex_lock(&venc.venc_lock);
+
+	*timings = venc.timings;
+
+	mutex_unlock(&venc.venc_lock);
+}
+
+static u32 venc_get_wss(struct omap_dss_device *dssdev)
+{
+	/* Invert due to VENC_L21_WC_CTL:INV=1 */
+	return (venc.wss_data >> 8) ^ 0xfffff;
+}
+
+static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
+{
+	const struct venc_config *config;
+	int r;
+
+	DSSDBG("venc_set_wss\n");
+
+	mutex_lock(&venc.venc_lock);
+
+	config = venc_timings_to_config(&venc.timings);
+
+	/* Invert due to VENC_L21_WC_CTL:INV=1 */
+	venc.wss_data = (wss ^ 0xfffff) << 8;
+
+	r = venc_runtime_get();
+	if (r)
+		goto err;
+
+	venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
+			venc.wss_data);
+
+	venc_runtime_put();
+
+err:
+	mutex_unlock(&venc.venc_lock);
+
+	return r;
+}
+
+static void venc_set_type(struct omap_dss_device *dssdev,
+		enum omap_dss_venc_type type)
+{
+	mutex_lock(&venc.venc_lock);
+
+	venc.type = type;
+
+	mutex_unlock(&venc.venc_lock);
+}
+
+static void venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
+		bool invert_polarity)
+{
+	mutex_lock(&venc.venc_lock);
+
+	venc.invert_polarity = invert_polarity;
+
+	mutex_unlock(&venc.venc_lock);
+}
+
+static int venc_init_regulator(void)
+{
+	struct regulator *vdda_dac;
+
+	if (venc.vdda_dac_reg != NULL)
+		return 0;
+
+	if (venc.pdev->dev.of_node)
+		vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda");
+	else
+		vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac");
+
+	if (IS_ERR(vdda_dac)) {
+		if (PTR_ERR(vdda_dac) != -EPROBE_DEFER)
+			DSSERR("can't get VDDA_DAC regulator\n");
+		return PTR_ERR(vdda_dac);
+	}
+
+	venc.vdda_dac_reg = vdda_dac;
+
+	return 0;
+}
+
+static void venc_dump_regs(struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
+
+	if (venc_runtime_get())
+		return;
+
+	DUMPREG(VENC_F_CONTROL);
+	DUMPREG(VENC_VIDOUT_CTRL);
+	DUMPREG(VENC_SYNC_CTRL);
+	DUMPREG(VENC_LLEN);
+	DUMPREG(VENC_FLENS);
+	DUMPREG(VENC_HFLTR_CTRL);
+	DUMPREG(VENC_CC_CARR_WSS_CARR);
+	DUMPREG(VENC_C_PHASE);
+	DUMPREG(VENC_GAIN_U);
+	DUMPREG(VENC_GAIN_V);
+	DUMPREG(VENC_GAIN_Y);
+	DUMPREG(VENC_BLACK_LEVEL);
+	DUMPREG(VENC_BLANK_LEVEL);
+	DUMPREG(VENC_X_COLOR);
+	DUMPREG(VENC_M_CONTROL);
+	DUMPREG(VENC_BSTAMP_WSS_DATA);
+	DUMPREG(VENC_S_CARR);
+	DUMPREG(VENC_LINE21);
+	DUMPREG(VENC_LN_SEL);
+	DUMPREG(VENC_L21__WC_CTL);
+	DUMPREG(VENC_HTRIGGER_VTRIGGER);
+	DUMPREG(VENC_SAVID__EAVID);
+	DUMPREG(VENC_FLEN__FAL);
+	DUMPREG(VENC_LAL__PHASE_RESET);
+	DUMPREG(VENC_HS_INT_START_STOP_X);
+	DUMPREG(VENC_HS_EXT_START_STOP_X);
+	DUMPREG(VENC_VS_INT_START_X);
+	DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
+	DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
+	DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
+	DUMPREG(VENC_VS_EXT_STOP_Y);
+	DUMPREG(VENC_AVID_START_STOP_X);
+	DUMPREG(VENC_AVID_START_STOP_Y);
+	DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
+	DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
+	DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
+	DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
+	DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
+	DUMPREG(VENC_GEN_CTRL);
+	DUMPREG(VENC_OUTPUT_CONTROL);
+	DUMPREG(VENC_OUTPUT_TEST);
+
+	venc_runtime_put();
+
+#undef DUMPREG
+}
+
+static int venc_get_clocks(struct platform_device *pdev)
+{
+	struct clk *clk;
+
+	if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
+		clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
+		if (IS_ERR(clk)) {
+			DSSERR("can't get tv_dac_clk\n");
+			return PTR_ERR(clk);
+		}
+	} else {
+		clk = NULL;
+	}
+
+	venc.tv_dac_clk = clk;
+
+	return 0;
+}
+
+static int venc_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct omap_overlay_manager *mgr;
+	int r;
+
+	r = venc_init_regulator();
+	if (r)
+		return r;
+
+	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
+	if (!mgr)
+		return -ENODEV;
+
+	r = dss_mgr_connect(mgr, dssdev);
+	if (r)
+		return r;
+
+	r = omapdss_output_set_device(dssdev, dst);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dst->name);
+		dss_mgr_disconnect(mgr, dssdev);
+		return r;
+	}
+
+	return 0;
+}
+
+static void venc_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	WARN_ON(dst != dssdev->dst);
+
+	if (dst != dssdev->dst)
+		return;
+
+	omapdss_output_unset_device(dssdev);
+
+	if (dssdev->manager)
+		dss_mgr_disconnect(dssdev->manager, dssdev);
+}
+
+static const struct omapdss_atv_ops venc_ops = {
+	.connect = venc_connect,
+	.disconnect = venc_disconnect,
+
+	.enable = venc_display_enable,
+	.disable = venc_display_disable,
+
+	.check_timings = venc_check_timings,
+	.set_timings = venc_set_timings,
+	.get_timings = venc_get_timings,
+
+	.set_type = venc_set_type,
+	.invert_vid_out_polarity = venc_invert_vid_out_polarity,
+
+	.set_wss = venc_set_wss,
+	.get_wss = venc_get_wss,
+};
+
+static void venc_init_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &venc.output;
+
+	out->dev = &pdev->dev;
+	out->id = OMAP_DSS_OUTPUT_VENC;
+	out->output_type = OMAP_DISPLAY_TYPE_VENC;
+	out->name = "venc.0";
+	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
+	out->ops.atv = &venc_ops;
+	out->owner = THIS_MODULE;
+
+	omapdss_register_output(out);
+}
+
+static void __exit venc_uninit_output(struct platform_device *pdev)
+{
+	struct omap_dss_device *out = &venc.output;
+
+	omapdss_unregister_output(out);
+}
+
+static int venc_probe_of(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *ep;
+	u32 channels;
+	int r;
+
+	ep = omapdss_of_get_first_endpoint(node);
+	if (!ep)
+		return 0;
+
+	venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity");
+
+	r = of_property_read_u32(ep, "ti,channels", &channels);
+	if (r) {
+		dev_err(&pdev->dev,
+			"failed to read property 'ti,channels': %d\n", r);
+		goto err;
+	}
+
+	switch (channels) {
+	case 1:
+		venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
+		break;
+	case 2:
+		venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
+		break;
+	default:
+		dev_err(&pdev->dev, "bad channel propert '%d'\n", channels);
+		r = -EINVAL;
+		goto err;
+	}
+
+	of_node_put(ep);
+
+	return 0;
+err:
+	of_node_put(ep);
+
+	return 0;
+}
+
+/* VENC HW IP initialisation */
+static int omap_venchw_probe(struct platform_device *pdev)
+{
+	u8 rev_id;
+	struct resource *venc_mem;
+	int r;
+
+	venc.pdev = pdev;
+
+	mutex_init(&venc.venc_lock);
+
+	venc.wss_data = 0;
+
+	venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
+	if (!venc_mem) {
+		DSSERR("can't get IORESOURCE_MEM VENC\n");
+		return -EINVAL;
+	}
+
+	venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
+				 resource_size(venc_mem));
+	if (!venc.base) {
+		DSSERR("can't ioremap VENC\n");
+		return -ENOMEM;
+	}
+
+	r = venc_get_clocks(pdev);
+	if (r)
+		return r;
+
+	pm_runtime_enable(&pdev->dev);
+
+	r = venc_runtime_get();
+	if (r)
+		goto err_runtime_get;
+
+	rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
+	dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
+
+	venc_runtime_put();
+
+	if (pdev->dev.of_node) {
+		r = venc_probe_of(pdev);
+		if (r) {
+			DSSERR("Invalid DT data\n");
+			goto err_probe_of;
+		}
+	}
+
+	dss_debugfs_create_file("venc", venc_dump_regs);
+
+	venc_init_output(pdev);
+
+	return 0;
+
+err_probe_of:
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
+	return r;
+}
+
+static int __exit omap_venchw_remove(struct platform_device *pdev)
+{
+	venc_uninit_output(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static int venc_runtime_suspend(struct device *dev)
+{
+	if (venc.tv_dac_clk)
+		clk_disable_unprepare(venc.tv_dac_clk);
+
+	dispc_runtime_put();
+
+	return 0;
+}
+
+static int venc_runtime_resume(struct device *dev)
+{
+	int r;
+
+	r = dispc_runtime_get();
+	if (r < 0)
+		return r;
+
+	if (venc.tv_dac_clk)
+		clk_prepare_enable(venc.tv_dac_clk);
+
+	return 0;
+}
+
+static const struct dev_pm_ops venc_pm_ops = {
+	.runtime_suspend = venc_runtime_suspend,
+	.runtime_resume = venc_runtime_resume,
+};
+
+
+static const struct of_device_id venc_of_match[] = {
+	{ .compatible = "ti,omap2-venc", },
+	{ .compatible = "ti,omap3-venc", },
+	{ .compatible = "ti,omap4-venc", },
+	{},
+};
+
+static struct platform_driver omap_venchw_driver = {
+	.probe		= omap_venchw_probe,
+	.remove         = __exit_p(omap_venchw_remove),
+	.driver         = {
+		.name   = "omapdss_venc",
+		.owner  = THIS_MODULE,
+		.pm	= &venc_pm_ops,
+		.of_match_table = venc_of_match,
+	},
+};
+
+int __init venc_init_platform_driver(void)
+{
+	return platform_driver_register(&omap_venchw_driver);
+}
+
+void __exit venc_uninit_platform_driver(void)
+{
+	platform_driver_unregister(&omap_venchw_driver);
+}
diff --git a/drivers/video/fbdev/omap2/dss/venc_panel.c b/drivers/video/fbdev/omap2/dss/venc_panel.c
new file mode 100644
index 000000000000..af68cd444d7e
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/venc_panel.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * VENC panel driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+static struct {
+	struct mutex lock;
+} venc_panel;
+
+static ssize_t display_output_type_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	const char *ret;
+
+	switch (dssdev->phy.venc.type) {
+	case OMAP_DSS_VENC_TYPE_COMPOSITE:
+		ret = "composite";
+		break;
+	case OMAP_DSS_VENC_TYPE_SVIDEO:
+		ret = "svideo";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", ret);
+}
+
+static ssize_t display_output_type_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	enum omap_dss_venc_type new_type;
+
+	if (sysfs_streq("composite", buf))
+		new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
+	else if (sysfs_streq("svideo", buf))
+		new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
+	else
+		return -EINVAL;
+
+	mutex_lock(&venc_panel.lock);
+
+	if (dssdev->phy.venc.type != new_type) {
+		dssdev->phy.venc.type = new_type;
+		omapdss_venc_set_type(dssdev, new_type);
+		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+			omapdss_venc_display_disable(dssdev);
+			omapdss_venc_display_enable(dssdev);
+		}
+	}
+
+	mutex_unlock(&venc_panel.lock);
+
+	return size;
+}
+
+static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
+		display_output_type_show, display_output_type_store);
+
+static int venc_panel_probe(struct omap_dss_device *dssdev)
+{
+	/* set default timings to PAL */
+	const struct omap_video_timings default_timings = {
+		.x_res		= 720,
+		.y_res		= 574,
+		.pixelclock	= 13500000,
+		.hsw		= 64,
+		.hfp		= 12,
+		.hbp		= 68,
+		.vsw		= 5,
+		.vfp		= 5,
+		.vbp		= 41,
+
+		.vsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+		.hsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+
+		.interlace	= true,
+	};
+
+	mutex_init(&venc_panel.lock);
+
+	dssdev->panel.timings = default_timings;
+
+	return device_create_file(dssdev->dev, &dev_attr_output_type);
+}
+
+static void venc_panel_remove(struct omap_dss_device *dssdev)
+{
+	device_remove_file(dssdev->dev, &dev_attr_output_type);
+}
+
+static int venc_panel_enable(struct omap_dss_device *dssdev)
+{
+	int r;
+
+	dev_dbg(dssdev->dev, "venc_panel_enable\n");
+
+	mutex_lock(&venc_panel.lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
+	omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
+	omapdss_venc_invert_vid_out_polarity(dssdev,
+		dssdev->phy.venc.invert_polarity);
+
+	r = omapdss_venc_display_enable(dssdev);
+	if (r)
+		goto err;
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	mutex_unlock(&venc_panel.lock);
+
+	return 0;
+err:
+	mutex_unlock(&venc_panel.lock);
+
+	return r;
+}
+
+static void venc_panel_disable(struct omap_dss_device *dssdev)
+{
+	dev_dbg(dssdev->dev, "venc_panel_disable\n");
+
+	mutex_lock(&venc_panel.lock);
+
+	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+		goto end;
+
+	omapdss_venc_display_disable(dssdev);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+end:
+	mutex_unlock(&venc_panel.lock);
+}
+
+static void venc_panel_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	dev_dbg(dssdev->dev, "venc_panel_set_timings\n");
+
+	mutex_lock(&venc_panel.lock);
+
+	omapdss_venc_set_timings(dssdev, timings);
+	dssdev->panel.timings = *timings;
+
+	mutex_unlock(&venc_panel.lock);
+}
+
+static int venc_panel_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	dev_dbg(dssdev->dev, "venc_panel_check_timings\n");
+
+	return omapdss_venc_check_timings(dssdev, timings);
+}
+
+static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
+{
+	dev_dbg(dssdev->dev, "venc_panel_get_wss\n");
+
+	return omapdss_venc_get_wss(dssdev);
+}
+
+static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
+{
+	dev_dbg(dssdev->dev, "venc_panel_set_wss\n");
+
+	return omapdss_venc_set_wss(dssdev, wss);
+}
+
+static struct omap_dss_driver venc_driver = {
+	.probe		= venc_panel_probe,
+	.remove		= venc_panel_remove,
+
+	.enable		= venc_panel_enable,
+	.disable	= venc_panel_disable,
+
+	.get_resolution	= omapdss_default_get_resolution,
+	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
+	.set_timings	= venc_panel_set_timings,
+	.check_timings	= venc_panel_check_timings,
+
+	.get_wss	= venc_panel_get_wss,
+	.set_wss	= venc_panel_set_wss,
+
+	.driver         = {
+		.name   = "venc",
+		.owner  = THIS_MODULE,
+	},
+};
+
+int venc_panel_init(void)
+{
+	return omap_dss_register_driver(&venc_driver);
+}
+
+void venc_panel_exit(void)
+{
+	omap_dss_unregister_driver(&venc_driver);
+}
diff --git a/drivers/video/fbdev/omap2/omapfb/Kconfig b/drivers/video/fbdev/omap2/omapfb/Kconfig
new file mode 100644
index 000000000000..4cb12ce68855
--- /dev/null
+++ b/drivers/video/fbdev/omap2/omapfb/Kconfig
@@ -0,0 +1,27 @@
+menuconfig FB_OMAP2
+        tristate "OMAP2+ frame buffer support"
+        depends on FB && OMAP2_DSS && !DRM_OMAP
+
+	select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
+        select FB_CFB_FILLRECT
+        select FB_CFB_COPYAREA
+        select FB_CFB_IMAGEBLIT
+        help
+	  Frame buffer driver for OMAP2+ based boards.
+
+config FB_OMAP2_DEBUG_SUPPORT
+        bool "Debug support for OMAP2+ FB"
+	default y
+	depends on FB_OMAP2
+	help
+	  Support for debug output. You have to enable the actual printing
+	  with 'debug' module parameter.
+
+config FB_OMAP2_NUM_FBS
+	int "Number of framebuffers"
+	range 1 10
+	default 3
+	depends on FB_OMAP2
+	help
+	  Select the number of framebuffers created. OMAP2/3 has 3 overlays
+	  so normally this would be 3.
diff --git a/drivers/video/fbdev/omap2/omapfb/Makefile b/drivers/video/fbdev/omap2/omapfb/Makefile
new file mode 100644
index 000000000000..51c2e00d9bf8
--- /dev/null
+++ b/drivers/video/fbdev/omap2/omapfb/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FB_OMAP2) += omapfb.o
+omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
new file mode 100644
index 000000000000..146b6f5428db
--- /dev/null
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
@@ -0,0 +1,922 @@
+/*
+ * linux/drivers/video/omap2/omapfb-ioctl.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fb.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/omapfb.h>
+#include <linux/vmalloc.h>
+#include <linux/export.h>
+#include <linux/sizes.h>
+
+#include <video/omapdss.h>
+#include <video/omapvrfb.h>
+
+#include "omapfb.h"
+
+static u8 get_mem_idx(struct omapfb_info *ofbi)
+{
+	if (ofbi->id == ofbi->region->id)
+		return 0;
+
+	return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
+}
+
+static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
+						 u8 mem_idx)
+{
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+
+	if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
+		mem_idx &= OMAPFB_MEM_IDX_MASK;
+	else
+		mem_idx = ofbi->id;
+
+	if (mem_idx >= fbdev->num_fbs)
+		return NULL;
+
+	return &fbdev->regions[mem_idx];
+}
+
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_overlay *ovl;
+	struct omap_overlay_info old_info;
+	struct omapfb2_mem_region *old_rg, *new_rg;
+	int r = 0;
+
+	DBG("omapfb_setup_plane\n");
+
+	if (ofbi->num_overlays == 0) {
+		r = -EINVAL;
+		goto out;
+	}
+
+	/* XXX uses only the first overlay */
+	ovl = ofbi->overlays[0];
+
+	old_rg = ofbi->region;
+	new_rg = get_mem_region(ofbi, pi->mem_idx);
+	if (!new_rg) {
+		r = -EINVAL;
+		goto out;
+	}
+
+	/* Take the locks in a specific order to keep lockdep happy */
+	if (old_rg->id < new_rg->id) {
+		omapfb_get_mem_region(old_rg);
+		omapfb_get_mem_region(new_rg);
+	} else if (new_rg->id < old_rg->id) {
+		omapfb_get_mem_region(new_rg);
+		omapfb_get_mem_region(old_rg);
+	} else
+		omapfb_get_mem_region(old_rg);
+
+	if (pi->enabled && !new_rg->size) {
+		/*
+		 * This plane's memory was freed, can't enable it
+		 * until it's reallocated.
+		 */
+		r = -EINVAL;
+		goto put_mem;
+	}
+
+	ovl->get_overlay_info(ovl, &old_info);
+
+	if (old_rg != new_rg) {
+		ofbi->region = new_rg;
+		set_fb_fix(fbi);
+	}
+
+	if (!pi->enabled) {
+		r = ovl->disable(ovl);
+		if (r)
+			goto undo;
+	}
+
+	if (pi->enabled) {
+		r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
+			pi->out_width, pi->out_height);
+		if (r)
+			goto undo;
+	} else {
+		struct omap_overlay_info info;
+
+		ovl->get_overlay_info(ovl, &info);
+
+		info.pos_x = pi->pos_x;
+		info.pos_y = pi->pos_y;
+		info.out_width = pi->out_width;
+		info.out_height = pi->out_height;
+
+		r = ovl->set_overlay_info(ovl, &info);
+		if (r)
+			goto undo;
+	}
+
+	if (ovl->manager)
+		ovl->manager->apply(ovl->manager);
+
+	if (pi->enabled) {
+		r = ovl->enable(ovl);
+		if (r)
+			goto undo;
+	}
+
+	/* Release the locks in a specific order to keep lockdep happy */
+	if (old_rg->id > new_rg->id) {
+		omapfb_put_mem_region(old_rg);
+		omapfb_put_mem_region(new_rg);
+	} else if (new_rg->id > old_rg->id) {
+		omapfb_put_mem_region(new_rg);
+		omapfb_put_mem_region(old_rg);
+	} else
+		omapfb_put_mem_region(old_rg);
+
+	return 0;
+
+ undo:
+	if (old_rg != new_rg) {
+		ofbi->region = old_rg;
+		set_fb_fix(fbi);
+	}
+
+	ovl->set_overlay_info(ovl, &old_info);
+ put_mem:
+	/* Release the locks in a specific order to keep lockdep happy */
+	if (old_rg->id > new_rg->id) {
+		omapfb_put_mem_region(old_rg);
+		omapfb_put_mem_region(new_rg);
+	} else if (new_rg->id > old_rg->id) {
+		omapfb_put_mem_region(new_rg);
+		omapfb_put_mem_region(old_rg);
+	} else
+		omapfb_put_mem_region(old_rg);
+ out:
+	dev_err(fbdev->dev, "setup_plane failed\n");
+
+	return r;
+}
+
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+
+	if (ofbi->num_overlays == 0) {
+		memset(pi, 0, sizeof(*pi));
+	} else {
+		struct omap_overlay *ovl;
+		struct omap_overlay_info ovli;
+
+		ovl = ofbi->overlays[0];
+		ovl->get_overlay_info(ovl, &ovli);
+
+		pi->pos_x = ovli.pos_x;
+		pi->pos_y = ovli.pos_y;
+		pi->enabled = ovl->is_enabled(ovl);
+		pi->channel_out = 0; /* xxx */
+		pi->mirror = 0;
+		pi->mem_idx = get_mem_idx(ofbi);
+		pi->out_width = ovli.out_width;
+		pi->out_height = ovli.out_height;
+	}
+
+	return 0;
+}
+
+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_dss_device *display = fb2display(fbi);
+	struct omapfb2_mem_region *rg;
+	int r = 0, i;
+	size_t size;
+
+	if (mi->type != OMAPFB_MEMTYPE_SDRAM)
+		return -EINVAL;
+
+	size = PAGE_ALIGN(mi->size);
+
+	if (display && display->driver->sync)
+		display->driver->sync(display);
+
+	rg = ofbi->region;
+
+	down_write_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
+
+	if (rg->size == size && rg->type == mi->type)
+		goto out;
+
+	if (atomic_read(&rg->map_count)) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
+		int j;
+
+		if (ofbi2->region != rg)
+			continue;
+
+		for (j = 0; j < ofbi2->num_overlays; j++) {
+			struct omap_overlay *ovl;
+			ovl = ofbi2->overlays[j];
+			if (ovl->is_enabled(ovl)) {
+				r = -EBUSY;
+				goto out;
+			}
+		}
+	}
+
+	r = omapfb_realloc_fbmem(fbi, size, mi->type);
+	if (r) {
+		dev_err(fbdev->dev, "realloc fbmem failed\n");
+		goto out;
+	}
+
+ out:
+	atomic_dec(&rg->lock_count);
+	up_write(&rg->lock);
+
+	return r;
+}
+
+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_mem_region *rg;
+
+	rg = omapfb_get_mem_region(ofbi->region);
+	memset(mi, 0, sizeof(*mi));
+
+	mi->size = rg->size;
+	mi->type = rg->type;
+
+	omapfb_put_mem_region(rg);
+
+	return 0;
+}
+
+static int omapfb_update_window(struct fb_info *fbi,
+		u32 x, u32 y, u32 w, u32 h)
+{
+	struct omap_dss_device *display = fb2display(fbi);
+	u16 dw, dh;
+
+	if (!display)
+		return 0;
+
+	if (w == 0 || h == 0)
+		return 0;
+
+	display->driver->get_resolution(display, &dw, &dh);
+
+	if (x + w > dw || y + h > dh)
+		return -EINVAL;
+
+	return display->driver->update(display, x, y, w, h);
+}
+
+int omapfb_set_update_mode(struct fb_info *fbi,
+				   enum omapfb_update_mode mode)
+{
+	struct omap_dss_device *display = fb2display(fbi);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb_display_data *d;
+	int r;
+
+	if (!display)
+		return -EINVAL;
+
+	if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
+		return -EINVAL;
+
+	omapfb_lock(fbdev);
+
+	d = get_display_data(fbdev, display);
+
+	if (d->update_mode == mode) {
+		omapfb_unlock(fbdev);
+		return 0;
+	}
+
+	r = 0;
+
+	if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+		if (mode == OMAPFB_AUTO_UPDATE)
+			omapfb_start_auto_update(fbdev, display);
+		else /* MANUAL_UPDATE */
+			omapfb_stop_auto_update(fbdev, display);
+
+		d->update_mode = mode;
+	} else { /* AUTO_UPDATE */
+		if (mode == OMAPFB_MANUAL_UPDATE)
+			r = -EINVAL;
+	}
+
+	omapfb_unlock(fbdev);
+
+	return r;
+}
+
+int omapfb_get_update_mode(struct fb_info *fbi,
+		enum omapfb_update_mode *mode)
+{
+	struct omap_dss_device *display = fb2display(fbi);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb_display_data *d;
+
+	if (!display)
+		return -EINVAL;
+
+	omapfb_lock(fbdev);
+
+	d = get_display_data(fbdev, display);
+
+	*mode = d->update_mode;
+
+	omapfb_unlock(fbdev);
+
+	return 0;
+}
+
+/* XXX this color key handling is a hack... */
+static struct omapfb_color_key omapfb_color_keys[2];
+
+static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
+		struct omapfb_color_key *ck)
+{
+	struct omap_overlay_manager_info info;
+	enum omap_dss_trans_key_type kt;
+	int r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
+		info.trans_enabled = false;
+		omapfb_color_keys[mgr->id] = *ck;
+
+		r = mgr->set_manager_info(mgr, &info);
+		if (r)
+			return r;
+
+		r = mgr->apply(mgr);
+
+		return r;
+	}
+
+	switch (ck->key_type) {
+	case OMAPFB_COLOR_KEY_GFX_DST:
+		kt = OMAP_DSS_COLOR_KEY_GFX_DST;
+		break;
+	case OMAPFB_COLOR_KEY_VID_SRC:
+		kt = OMAP_DSS_COLOR_KEY_VID_SRC;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	info.default_color = ck->background;
+	info.trans_key = ck->trans_key;
+	info.trans_key_type = kt;
+	info.trans_enabled = true;
+
+	omapfb_color_keys[mgr->id] = *ck;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+
+	return r;
+}
+
+static int omapfb_set_color_key(struct fb_info *fbi,
+		struct omapfb_color_key *ck)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	int r;
+	int i;
+	struct omap_overlay_manager *mgr = NULL;
+
+	omapfb_lock(fbdev);
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ofbi->overlays[i]->manager) {
+			mgr = ofbi->overlays[i]->manager;
+			break;
+		}
+	}
+
+	if (!mgr) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	r = _omapfb_set_color_key(mgr, ck);
+err:
+	omapfb_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_get_color_key(struct fb_info *fbi,
+		struct omapfb_color_key *ck)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_overlay_manager *mgr = NULL;
+	int r = 0;
+	int i;
+
+	omapfb_lock(fbdev);
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ofbi->overlays[i]->manager) {
+			mgr = ofbi->overlays[i]->manager;
+			break;
+		}
+	}
+
+	if (!mgr) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	*ck = omapfb_color_keys[mgr->id];
+err:
+	omapfb_unlock(fbdev);
+
+	return r;
+}
+
+static int omapfb_memory_read(struct fb_info *fbi,
+		struct omapfb_memory_read *mr)
+{
+	struct omap_dss_device *display = fb2display(fbi);
+	void *buf;
+	int r;
+
+	if (!display || !display->driver->memory_read)
+		return -ENOENT;
+
+	if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
+		return -EFAULT;
+
+	if (mr->w * mr->h * 3 > mr->buffer_size)
+		return -EINVAL;
+
+	buf = vmalloc(mr->buffer_size);
+	if (!buf) {
+		DBG("vmalloc failed\n");
+		return -ENOMEM;
+	}
+
+	r = display->driver->memory_read(display, buf, mr->buffer_size,
+			mr->x, mr->y, mr->w, mr->h);
+
+	if (r > 0) {
+		if (copy_to_user(mr->buffer, buf, mr->buffer_size))
+			r = -EFAULT;
+	}
+
+	vfree(buf);
+
+	return r;
+}
+
+static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
+			     struct omapfb_ovl_colormode *mode)
+{
+	int ovl_idx = mode->overlay_idx;
+	int mode_idx = mode->mode_idx;
+	struct omap_overlay *ovl;
+	enum omap_color_mode supported_modes;
+	struct fb_var_screeninfo var;
+	int i;
+
+	if (ovl_idx >= fbdev->num_overlays)
+		return -ENODEV;
+	ovl = fbdev->overlays[ovl_idx];
+	supported_modes = ovl->supported_modes;
+
+	mode_idx = mode->mode_idx;
+
+	for (i = 0; i < sizeof(supported_modes) * 8; i++) {
+		if (!(supported_modes & (1 << i)))
+			continue;
+		/*
+		 * It's possible that the FB doesn't support a mode
+		 * that is supported by the overlay, so call the
+		 * following here.
+		 */
+		if (dss_mode_to_fb_mode(1 << i, &var) < 0)
+			continue;
+
+		mode_idx--;
+		if (mode_idx < 0)
+			break;
+	}
+
+	if (i == sizeof(supported_modes) * 8)
+		return -ENOENT;
+
+	mode->bits_per_pixel = var.bits_per_pixel;
+	mode->nonstd = var.nonstd;
+	mode->red = var.red;
+	mode->green = var.green;
+	mode->blue = var.blue;
+	mode->transp = var.transp;
+
+	return 0;
+}
+
+static int omapfb_wait_for_go(struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	int r = 0;
+	int i;
+
+	for (i = 0; i < ofbi->num_overlays; ++i) {
+		struct omap_overlay *ovl = ofbi->overlays[i];
+		r = ovl->wait_for_go(ovl);
+		if (r)
+			break;
+	}
+
+	return r;
+}
+
+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_dss_device *display = fb2display(fbi);
+	struct omap_overlay_manager *mgr;
+
+	union {
+		struct omapfb_update_window_old	uwnd_o;
+		struct omapfb_update_window	uwnd;
+		struct omapfb_plane_info	plane_info;
+		struct omapfb_caps		caps;
+		struct omapfb_mem_info          mem_info;
+		struct omapfb_color_key		color_key;
+		struct omapfb_ovl_colormode	ovl_colormode;
+		enum omapfb_update_mode		update_mode;
+		int test_num;
+		struct omapfb_memory_read	memory_read;
+		struct omapfb_vram_info		vram_info;
+		struct omapfb_tearsync_info	tearsync_info;
+		struct omapfb_display_info	display_info;
+		u32				crt;
+	} p;
+
+	int r = 0;
+
+	switch (cmd) {
+	case OMAPFB_SYNC_GFX:
+		DBG("ioctl SYNC_GFX\n");
+		if (!display || !display->driver->sync) {
+			/* DSS1 never returns an error here, so we neither */
+			/*r = -EINVAL;*/
+			break;
+		}
+
+		r = display->driver->sync(display);
+		break;
+
+	case OMAPFB_UPDATE_WINDOW_OLD:
+		DBG("ioctl UPDATE_WINDOW_OLD\n");
+		if (!display || !display->driver->update) {
+			r = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(&p.uwnd_o,
+					(void __user *)arg,
+					sizeof(p.uwnd_o))) {
+			r = -EFAULT;
+			break;
+		}
+
+		r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
+				p.uwnd_o.width, p.uwnd_o.height);
+		break;
+
+	case OMAPFB_UPDATE_WINDOW:
+		DBG("ioctl UPDATE_WINDOW\n");
+		if (!display || !display->driver->update) {
+			r = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(&p.uwnd, (void __user *)arg,
+					sizeof(p.uwnd))) {
+			r = -EFAULT;
+			break;
+		}
+
+		r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
+				p.uwnd.width, p.uwnd.height);
+		break;
+
+	case OMAPFB_SETUP_PLANE:
+		DBG("ioctl SETUP_PLANE\n");
+		if (copy_from_user(&p.plane_info, (void __user *)arg,
+					sizeof(p.plane_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_plane(fbi, &p.plane_info);
+		break;
+
+	case OMAPFB_QUERY_PLANE:
+		DBG("ioctl QUERY_PLANE\n");
+		r = omapfb_query_plane(fbi, &p.plane_info);
+		if (r < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.plane_info,
+					sizeof(p.plane_info)))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_SETUP_MEM:
+		DBG("ioctl SETUP_MEM\n");
+		if (copy_from_user(&p.mem_info, (void __user *)arg,
+					sizeof(p.mem_info)))
+			r = -EFAULT;
+		else
+			r = omapfb_setup_mem(fbi, &p.mem_info);
+		break;
+
+	case OMAPFB_QUERY_MEM:
+		DBG("ioctl QUERY_MEM\n");
+		r = omapfb_query_mem(fbi, &p.mem_info);
+		if (r < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.mem_info,
+					sizeof(p.mem_info)))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_GET_CAPS:
+		DBG("ioctl GET_CAPS\n");
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+
+		memset(&p.caps, 0, sizeof(p.caps));
+		if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+			p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE;
+		if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM)
+			p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC;
+
+		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_GET_OVERLAY_COLORMODE:
+		DBG("ioctl GET_OVERLAY_COLORMODE\n");
+		if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
+				   sizeof(p.ovl_colormode))) {
+			r = -EFAULT;
+			break;
+		}
+		r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
+		if (r < 0)
+			break;
+		if (copy_to_user((void __user *)arg, &p.ovl_colormode,
+				 sizeof(p.ovl_colormode)))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_SET_UPDATE_MODE:
+		DBG("ioctl SET_UPDATE_MODE\n");
+		if (get_user(p.update_mode, (int __user *)arg))
+			r = -EFAULT;
+		else
+			r = omapfb_set_update_mode(fbi, p.update_mode);
+		break;
+
+	case OMAPFB_GET_UPDATE_MODE:
+		DBG("ioctl GET_UPDATE_MODE\n");
+		r = omapfb_get_update_mode(fbi, &p.update_mode);
+		if (r)
+			break;
+		if (put_user(p.update_mode,
+					(enum omapfb_update_mode __user *)arg))
+			r = -EFAULT;
+		break;
+
+	case OMAPFB_SET_COLOR_KEY:
+		DBG("ioctl SET_COLOR_KEY\n");
+		if (copy_from_user(&p.color_key, (void __user *)arg,
+				   sizeof(p.color_key)))
+			r = -EFAULT;
+		else
+			r = omapfb_set_color_key(fbi, &p.color_key);
+		break;
+
+	case OMAPFB_GET_COLOR_KEY:
+		DBG("ioctl GET_COLOR_KEY\n");
+		r = omapfb_get_color_key(fbi, &p.color_key);
+		if (r)
+			break;
+		if (copy_to_user((void __user *)arg, &p.color_key,
+				 sizeof(p.color_key)))
+			r = -EFAULT;
+		break;
+
+	case FBIO_WAITFORVSYNC:
+		if (get_user(p.crt, (__u32 __user *)arg)) {
+			r = -EFAULT;
+			break;
+		}
+		if (p.crt != 0) {
+			r = -ENODEV;
+			break;
+		}
+		/* FALLTHROUGH */
+
+	case OMAPFB_WAITFORVSYNC:
+		DBG("ioctl WAITFORVSYNC\n");
+
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+
+		mgr = omapdss_find_mgr_from_display(display);
+		if (!mgr) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = mgr->wait_for_vsync(mgr);
+		break;
+
+	case OMAPFB_WAITFORGO:
+		DBG("ioctl WAITFORGO\n");
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = omapfb_wait_for_go(fbi);
+		break;
+
+	/* LCD and CTRL tests do the same thing for backward
+	 * compatibility */
+	case OMAPFB_LCD_TEST:
+		DBG("ioctl LCD_TEST\n");
+		if (get_user(p.test_num, (int __user *)arg)) {
+			r = -EFAULT;
+			break;
+		}
+		if (!display || !display->driver->run_test) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = display->driver->run_test(display, p.test_num);
+
+		break;
+
+	case OMAPFB_CTRL_TEST:
+		DBG("ioctl CTRL_TEST\n");
+		if (get_user(p.test_num, (int __user *)arg)) {
+			r = -EFAULT;
+			break;
+		}
+		if (!display || !display->driver->run_test) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = display->driver->run_test(display, p.test_num);
+
+		break;
+
+	case OMAPFB_MEMORY_READ:
+		DBG("ioctl MEMORY_READ\n");
+
+		if (copy_from_user(&p.memory_read, (void __user *)arg,
+					sizeof(p.memory_read))) {
+			r = -EFAULT;
+			break;
+		}
+
+		r = omapfb_memory_read(fbi, &p.memory_read);
+
+		break;
+
+	case OMAPFB_GET_VRAM_INFO: {
+		DBG("ioctl GET_VRAM_INFO\n");
+
+		/*
+		 * We don't have the ability to get this vram info anymore.
+		 * Fill in something that should keep the applications working.
+		 */
+		p.vram_info.total = SZ_1M * 64;
+		p.vram_info.free = SZ_1M * 64;
+		p.vram_info.largest_free_block = SZ_1M * 64;
+
+		if (copy_to_user((void __user *)arg, &p.vram_info,
+					sizeof(p.vram_info)))
+			r = -EFAULT;
+		break;
+	}
+
+	case OMAPFB_SET_TEARSYNC: {
+		DBG("ioctl SET_TEARSYNC\n");
+
+		if (copy_from_user(&p.tearsync_info, (void __user *)arg,
+					sizeof(p.tearsync_info))) {
+			r = -EFAULT;
+			break;
+		}
+
+		if (!display || !display->driver->enable_te) {
+			r = -ENODEV;
+			break;
+		}
+
+		r = display->driver->enable_te(display,
+				!!p.tearsync_info.enabled);
+
+		break;
+	}
+
+	case OMAPFB_GET_DISPLAY_INFO: {
+		u16 xres, yres;
+
+		DBG("ioctl GET_DISPLAY_INFO\n");
+
+		if (display == NULL) {
+			r = -ENODEV;
+			break;
+		}
+
+		display->driver->get_resolution(display, &xres, &yres);
+
+		p.display_info.xres = xres;
+		p.display_info.yres = yres;
+
+		if (display->driver->get_dimensions) {
+			u32 w, h;
+			display->driver->get_dimensions(display, &w, &h);
+			p.display_info.width = w;
+			p.display_info.height = h;
+		} else {
+			p.display_info.width = 0;
+			p.display_info.height = 0;
+		}
+
+		if (copy_to_user((void __user *)arg, &p.display_info,
+					sizeof(p.display_info)))
+			r = -EFAULT;
+		break;
+	}
+
+	default:
+		dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
+		r = -EINVAL;
+	}
+
+	if (r < 0)
+		DBG("ioctl failed: %d\n", r);
+
+	return r;
+}
+
+
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
new file mode 100644
index 000000000000..ec2d132c782d
--- /dev/null
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
@@ -0,0 +1,2656 @@
+/*
+ * linux/drivers/video/omap2/omapfb-main.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/omapfb.h>
+
+#include <video/omapdss.h>
+#include <video/omapvrfb.h>
+
+#include "omapfb.h"
+
+#define MODULE_NAME     "omapfb"
+
+#define OMAPFB_PLANE_XRES_MIN		8
+#define OMAPFB_PLANE_YRES_MIN		8
+
+static char *def_mode;
+static char *def_vram;
+static bool def_vrfb;
+static int def_rotate;
+static bool def_mirror;
+static bool auto_update;
+static unsigned int auto_update_freq;
+module_param(auto_update, bool, 0);
+module_param(auto_update_freq, uint, 0644);
+
+#ifdef DEBUG
+bool omapfb_debug;
+module_param_named(debug, omapfb_debug, bool, 0644);
+static bool omapfb_test_pattern;
+module_param_named(test, omapfb_test_pattern, bool, 0644);
+#endif
+
+static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
+static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
+		struct omap_dss_device *dssdev);
+
+#ifdef DEBUG
+static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	void __iomem *addr = fbi->screen_base;
+	const unsigned bytespp = var->bits_per_pixel >> 3;
+	const unsigned line_len = fix->line_length / bytespp;
+
+	int r = (color >> 16) & 0xff;
+	int g = (color >> 8) & 0xff;
+	int b = (color >> 0) & 0xff;
+
+	if (var->bits_per_pixel == 16) {
+		u16 __iomem *p = (u16 __iomem *)addr;
+		p += y * line_len + x;
+
+		r = r * 32 / 256;
+		g = g * 64 / 256;
+		b = b * 32 / 256;
+
+		__raw_writew((r << 11) | (g << 5) | (b << 0), p);
+	} else if (var->bits_per_pixel == 24) {
+		u8 __iomem *p = (u8 __iomem *)addr;
+		p += (y * line_len + x) * 3;
+
+		__raw_writeb(b, p + 0);
+		__raw_writeb(g, p + 1);
+		__raw_writeb(r, p + 2);
+	} else if (var->bits_per_pixel == 32) {
+		u32 __iomem *p = (u32 __iomem *)addr;
+		p += y * line_len + x;
+		__raw_writel(color, p);
+	}
+}
+
+static void fill_fb(struct fb_info *fbi)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+	const short w = var->xres_virtual;
+	const short h = var->yres_virtual;
+	void __iomem *addr = fbi->screen_base;
+	int y, x;
+
+	if (!addr)
+		return;
+
+	DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
+
+	for (y = 0; y < h; y++) {
+		for (x = 0; x < w; x++) {
+			if (x < 20 && y < 20)
+				draw_pixel(fbi, x, y, 0xffffff);
+			else if (x < 20 && (y > 20 && y < h - 20))
+				draw_pixel(fbi, x, y, 0xff);
+			else if (y < 20 && (x > 20 && x < w - 20))
+				draw_pixel(fbi, x, y, 0xff00);
+			else if (x > w - 20 && (y > 20 && y < h - 20))
+				draw_pixel(fbi, x, y, 0xff0000);
+			else if (y > h - 20 && (x > 20 && x < w - 20))
+				draw_pixel(fbi, x, y, 0xffff00);
+			else if (x == 20 || x == w - 20 ||
+					y == 20 || y == h - 20)
+				draw_pixel(fbi, x, y, 0xffffff);
+			else if (x == y || w - x == h - y)
+				draw_pixel(fbi, x, y, 0xff00ff);
+			else if (w - x == y || x == h - y)
+				draw_pixel(fbi, x, y, 0x00ffff);
+			else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
+				int t = x * 3 / w;
+				unsigned r = 0, g = 0, b = 0;
+				unsigned c;
+				if (var->bits_per_pixel == 16) {
+					if (t == 0)
+						b = (y % 32) * 256 / 32;
+					else if (t == 1)
+						g = (y % 64) * 256 / 64;
+					else if (t == 2)
+						r = (y % 32) * 256 / 32;
+				} else {
+					if (t == 0)
+						b = (y % 256);
+					else if (t == 1)
+						g = (y % 256);
+					else if (t == 2)
+						r = (y % 256);
+				}
+				c = (r << 16) | (g << 8) | (b << 0);
+				draw_pixel(fbi, x, y, c);
+			} else {
+				draw_pixel(fbi, x, y, 0);
+			}
+		}
+	}
+}
+#endif
+
+static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
+{
+	const struct vrfb *vrfb = &ofbi->region->vrfb;
+	unsigned offset;
+
+	switch (rot) {
+	case FB_ROTATE_UR:
+		offset = 0;
+		break;
+	case FB_ROTATE_CW:
+		offset = vrfb->yoffset;
+		break;
+	case FB_ROTATE_UD:
+		offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
+		break;
+	case FB_ROTATE_CCW:
+		offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
+		break;
+	default:
+		BUG();
+		return 0;
+	}
+
+	offset *= vrfb->bytespp;
+
+	return offset;
+}
+
+static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
+{
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		return ofbi->region->vrfb.paddr[rot]
+			+ omapfb_get_vrfb_offset(ofbi, rot);
+	} else {
+		return ofbi->region->paddr;
+	}
+}
+
+static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
+{
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		return ofbi->region->vrfb.paddr[0];
+	else
+		return ofbi->region->paddr;
+}
+
+static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
+{
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		return ofbi->region->vrfb.vaddr[0];
+	else
+		return ofbi->region->vaddr;
+}
+
+static struct omapfb_colormode omapfb_colormodes[] = {
+	{
+		.dssmode = OMAP_DSS_COLOR_UYVY,
+		.bits_per_pixel = 16,
+		.nonstd = OMAPFB_COLOR_YUV422,
+	}, {
+		.dssmode = OMAP_DSS_COLOR_YUV2,
+		.bits_per_pixel = 16,
+		.nonstd = OMAPFB_COLOR_YUY422,
+	}, {
+		.dssmode = OMAP_DSS_COLOR_ARGB16,
+		.bits_per_pixel = 16,
+		.red	= { .length = 4, .offset = 8, .msb_right = 0 },
+		.green	= { .length = 4, .offset = 4, .msb_right = 0 },
+		.blue	= { .length = 4, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 4, .offset = 12, .msb_right = 0 },
+	}, {
+		.dssmode = OMAP_DSS_COLOR_RGB16,
+		.bits_per_pixel = 16,
+		.red	= { .length = 5, .offset = 11, .msb_right = 0 },
+		.green	= { .length = 6, .offset = 5, .msb_right = 0 },
+		.blue	= { .length = 5, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OMAP_DSS_COLOR_RGB24P,
+		.bits_per_pixel = 24,
+		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OMAP_DSS_COLOR_RGB24U,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OMAP_DSS_COLOR_ARGB32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 8, .offset = 24, .msb_right = 0 },
+	}, {
+		.dssmode = OMAP_DSS_COLOR_RGBA32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.transp	= { .length = 8, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OMAP_DSS_COLOR_RGBX32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	},
+};
+
+static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
+		struct omapfb_colormode *color)
+{
+	bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
+	{
+		return f1->length == f2->length &&
+			f1->offset == f2->offset &&
+			f1->msb_right == f2->msb_right;
+	}
+
+	if (var->bits_per_pixel == 0 ||
+			var->red.length == 0 ||
+			var->blue.length == 0 ||
+			var->green.length == 0)
+		return 0;
+
+	return var->bits_per_pixel == color->bits_per_pixel &&
+		cmp_component(&var->red, &color->red) &&
+		cmp_component(&var->green, &color->green) &&
+		cmp_component(&var->blue, &color->blue) &&
+		cmp_component(&var->transp, &color->transp);
+}
+
+static void assign_colormode_to_var(struct fb_var_screeninfo *var,
+		struct omapfb_colormode *color)
+{
+	var->bits_per_pixel = color->bits_per_pixel;
+	var->nonstd = color->nonstd;
+	var->red = color->red;
+	var->green = color->green;
+	var->blue = color->blue;
+	var->transp = color->transp;
+}
+
+static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
+		enum omap_color_mode *mode)
+{
+	enum omap_color_mode dssmode;
+	int i;
+
+	/* first match with nonstd field */
+	if (var->nonstd) {
+		for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+			struct omapfb_colormode *m = &omapfb_colormodes[i];
+			if (var->nonstd == m->nonstd) {
+				assign_colormode_to_var(var, m);
+				*mode = m->dssmode;
+				return 0;
+			}
+		}
+
+		return -EINVAL;
+	}
+
+	/* then try exact match of bpp and colors */
+	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+		struct omapfb_colormode *m = &omapfb_colormodes[i];
+		if (cmp_var_to_colormode(var, m)) {
+			assign_colormode_to_var(var, m);
+			*mode = m->dssmode;
+			return 0;
+		}
+	}
+
+	/* match with bpp if user has not filled color fields
+	 * properly */
+	switch (var->bits_per_pixel) {
+	case 1:
+		dssmode = OMAP_DSS_COLOR_CLUT1;
+		break;
+	case 2:
+		dssmode = OMAP_DSS_COLOR_CLUT2;
+		break;
+	case 4:
+		dssmode = OMAP_DSS_COLOR_CLUT4;
+		break;
+	case 8:
+		dssmode = OMAP_DSS_COLOR_CLUT8;
+		break;
+	case 12:
+		dssmode = OMAP_DSS_COLOR_RGB12U;
+		break;
+	case 16:
+		dssmode = OMAP_DSS_COLOR_RGB16;
+		break;
+	case 24:
+		dssmode = OMAP_DSS_COLOR_RGB24P;
+		break;
+	case 32:
+		dssmode = OMAP_DSS_COLOR_RGB24U;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+		struct omapfb_colormode *m = &omapfb_colormodes[i];
+		if (dssmode == m->dssmode) {
+			assign_colormode_to_var(var, m);
+			*mode = m->dssmode;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int check_fb_res_bounds(struct fb_var_screeninfo *var)
+{
+	int xres_min = OMAPFB_PLANE_XRES_MIN;
+	int xres_max = 2048;
+	int yres_min = OMAPFB_PLANE_YRES_MIN;
+	int yres_max = 2048;
+
+	/* XXX: some applications seem to set virtual res to 0. */
+	if (var->xres_virtual == 0)
+		var->xres_virtual = var->xres;
+
+	if (var->yres_virtual == 0)
+		var->yres_virtual = var->yres;
+
+	if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
+		return -EINVAL;
+
+	if (var->xres < xres_min)
+		var->xres = xres_min;
+	if (var->yres < yres_min)
+		var->yres = yres_min;
+	if (var->xres > xres_max)
+		var->xres = xres_max;
+	if (var->yres > yres_max)
+		var->yres = yres_max;
+
+	if (var->xres > var->xres_virtual)
+		var->xres = var->xres_virtual;
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+
+	return 0;
+}
+
+static void shrink_height(unsigned long max_frame_size,
+		struct fb_var_screeninfo *var)
+{
+	DBG("can't fit FB into memory, reducing y\n");
+	var->yres_virtual = max_frame_size /
+		(var->xres_virtual * var->bits_per_pixel >> 3);
+
+	if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
+		var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
+
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+}
+
+static void shrink_width(unsigned long max_frame_size,
+		struct fb_var_screeninfo *var)
+{
+	DBG("can't fit FB into memory, reducing x\n");
+	var->xres_virtual = max_frame_size / var->yres_virtual /
+		(var->bits_per_pixel >> 3);
+
+	if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
+		var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
+
+	if (var->xres > var->xres_virtual)
+		var->xres = var->xres_virtual;
+}
+
+static int check_vrfb_fb_size(unsigned long region_size,
+		const struct fb_var_screeninfo *var)
+{
+	unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
+		var->yres_virtual, var->bits_per_pixel >> 3);
+
+	return min_phys_size > region_size ? -EINVAL : 0;
+}
+
+static int check_fb_size(const struct omapfb_info *ofbi,
+		struct fb_var_screeninfo *var)
+{
+	unsigned long max_frame_size = ofbi->region->size;
+	int bytespp = var->bits_per_pixel >> 3;
+	unsigned long line_size = var->xres_virtual * bytespp;
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		/* One needs to check for both VRFB and OMAPFB limitations. */
+		if (check_vrfb_fb_size(max_frame_size, var))
+			shrink_height(omap_vrfb_max_height(
+				max_frame_size, var->xres_virtual, bytespp) *
+				line_size, var);
+
+		if (check_vrfb_fb_size(max_frame_size, var)) {
+			DBG("cannot fit FB to memory\n");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
+
+	if (line_size * var->yres_virtual > max_frame_size)
+		shrink_height(max_frame_size, var);
+
+	if (line_size * var->yres_virtual > max_frame_size) {
+		shrink_width(max_frame_size, var);
+		line_size = var->xres_virtual * bytespp;
+	}
+
+	if (line_size * var->yres_virtual > max_frame_size) {
+		DBG("cannot fit FB to memory\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Consider if VRFB assisted rotation is in use and if the virtual space for
+ * the zero degree view needs to be mapped. The need for mapping also acts as
+ * the trigger for setting up the hardware on the context in question. This
+ * ensures that one does not attempt to access the virtual view before the
+ * hardware is serving the address translations.
+ */
+static int setup_vrfb_rotation(struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_mem_region *rg = ofbi->region;
+	struct vrfb *vrfb = &rg->vrfb;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	unsigned bytespp;
+	bool yuv_mode;
+	enum omap_color_mode mode;
+	int r;
+	bool reconf;
+
+	if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
+		return 0;
+
+	DBG("setup_vrfb_rotation\n");
+
+	r = fb_mode_to_dss_mode(var, &mode);
+	if (r)
+		return r;
+
+	bytespp = var->bits_per_pixel >> 3;
+
+	yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
+
+	/* We need to reconfigure VRFB if the resolution changes, if yuv mode
+	 * is enabled/disabled, or if bytes per pixel changes */
+
+	/* XXX we shouldn't allow this when framebuffer is mmapped */
+
+	reconf = false;
+
+	if (yuv_mode != vrfb->yuv_mode)
+		reconf = true;
+	else if (bytespp != vrfb->bytespp)
+		reconf = true;
+	else if (vrfb->xres != var->xres_virtual ||
+			vrfb->yres != var->yres_virtual)
+		reconf = true;
+
+	if (vrfb->vaddr[0] && reconf) {
+		fbi->screen_base = NULL;
+		fix->smem_start = 0;
+		fix->smem_len = 0;
+		iounmap(vrfb->vaddr[0]);
+		vrfb->vaddr[0] = NULL;
+		DBG("setup_vrfb_rotation: reset fb\n");
+	}
+
+	if (vrfb->vaddr[0])
+		return 0;
+
+	omap_vrfb_setup(&rg->vrfb, rg->paddr,
+			var->xres_virtual,
+			var->yres_virtual,
+			bytespp, yuv_mode);
+
+	/* Now one can ioremap the 0 angle view */
+	r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
+	if (r)
+		return r;
+
+	/* used by open/write in fbmem.c */
+	fbi->screen_base = ofbi->region->vrfb.vaddr[0];
+
+	fix->smem_start = ofbi->region->vrfb.paddr[0];
+
+	switch (var->nonstd) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUY422:
+		fix->line_length =
+			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
+		break;
+	default:
+		fix->line_length =
+			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
+		break;
+	}
+
+	fix->smem_len = var->yres_virtual * fix->line_length;
+
+	return 0;
+}
+
+int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
+			struct fb_var_screeninfo *var)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
+		struct omapfb_colormode *mode = &omapfb_colormodes[i];
+		if (dssmode == mode->dssmode) {
+			assign_colormode_to_var(var, mode);
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+void set_fb_fix(struct fb_info *fbi)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_mem_region *rg = ofbi->region;
+
+	DBG("set_fb_fix\n");
+
+	/* used by open/write in fbmem.c */
+	fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
+
+	/* used by mmap in fbmem.c */
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		switch (var->nonstd) {
+		case OMAPFB_COLOR_YUV422:
+		case OMAPFB_COLOR_YUY422:
+			fix->line_length =
+				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
+			break;
+		default:
+			fix->line_length =
+				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
+			break;
+		}
+
+		fix->smem_len = var->yres_virtual * fix->line_length;
+	} else {
+		fix->line_length =
+			(var->xres_virtual * var->bits_per_pixel) >> 3;
+		fix->smem_len = rg->size;
+	}
+
+	fix->smem_start = omapfb_get_region_paddr(ofbi);
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	if (var->nonstd)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else {
+		switch (var->bits_per_pixel) {
+		case 32:
+		case 24:
+		case 16:
+		case 12:
+			fix->visual = FB_VISUAL_TRUECOLOR;
+			/* 12bpp is stored in 16 bits */
+			break;
+		case 1:
+		case 2:
+		case 4:
+		case 8:
+			fix->visual = FB_VISUAL_PSEUDOCOLOR;
+			break;
+		}
+	}
+
+	fix->accel = FB_ACCEL_NONE;
+
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+}
+
+/* check new var and possibly modify it to be ok */
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omap_dss_device *display = fb2display(fbi);
+	enum omap_color_mode mode = 0;
+	int i;
+	int r;
+
+	DBG("check_fb_var %d\n", ofbi->id);
+
+	WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
+	r = fb_mode_to_dss_mode(var, &mode);
+	if (r) {
+		DBG("cannot convert var to omap dss mode\n");
+		return r;
+	}
+
+	for (i = 0; i < ofbi->num_overlays; ++i) {
+		if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
+			DBG("invalid mode\n");
+			return -EINVAL;
+		}
+	}
+
+	if (var->rotate > 3)
+		return -EINVAL;
+
+	if (check_fb_res_bounds(var))
+		return -EINVAL;
+
+	/* When no memory is allocated ignore the size check */
+	if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
+		return -EINVAL;
+
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
+			var->xres, var->yres,
+			var->xres_virtual, var->yres_virtual);
+
+	if (display && display->driver->get_dimensions) {
+		u32 w, h;
+		display->driver->get_dimensions(display, &w, &h);
+		var->width = DIV_ROUND_CLOSEST(w, 1000);
+		var->height = DIV_ROUND_CLOSEST(h, 1000);
+	} else {
+		var->height = -1;
+		var->width = -1;
+	}
+
+	var->grayscale          = 0;
+
+	if (display && display->driver->get_timings) {
+		struct omap_video_timings timings;
+		display->driver->get_timings(display, &timings);
+
+		/* pixclock in ps, the rest in pixclock */
+		var->pixclock = timings.pixelclock != 0 ?
+			KHZ2PICOS(timings.pixelclock / 1000) :
+			0;
+		var->left_margin = timings.hbp;
+		var->right_margin = timings.hfp;
+		var->upper_margin = timings.vbp;
+		var->lower_margin = timings.vfp;
+		var->hsync_len = timings.hsw;
+		var->vsync_len = timings.vsw;
+		var->sync |= timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
+				FB_SYNC_HOR_HIGH_ACT : 0;
+		var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
+				FB_SYNC_VERT_HIGH_ACT : 0;
+		var->vmode = timings.interlace ?
+				FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+	} else {
+		var->pixclock = 0;
+		var->left_margin = 0;
+		var->right_margin = 0;
+		var->upper_margin = 0;
+		var->lower_margin = 0;
+		var->hsync_len = 0;
+		var->vsync_len = 0;
+		var->sync = 0;
+		var->vmode = FB_VMODE_NONINTERLACED;
+	}
+
+	return 0;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks
+ * ---------------------------------------------------------------------------
+ */
+static int omapfb_open(struct fb_info *fbi, int user)
+{
+	return 0;
+}
+
+static int omapfb_release(struct fb_info *fbi, int user)
+{
+	return 0;
+}
+
+static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
+		const struct fb_fix_screeninfo *fix, int rotation)
+{
+	unsigned offset;
+
+	offset = var->yoffset * fix->line_length +
+		var->xoffset * (var->bits_per_pixel >> 3);
+
+	return offset;
+}
+
+static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
+		const struct fb_fix_screeninfo *fix, int rotation)
+{
+	unsigned offset;
+
+	if (rotation == FB_ROTATE_UD)
+		offset = (var->yres_virtual - var->yres) *
+			fix->line_length;
+	else if (rotation == FB_ROTATE_CW)
+		offset = (var->yres_virtual - var->yres) *
+			(var->bits_per_pixel >> 3);
+	else
+		offset = 0;
+
+	if (rotation == FB_ROTATE_UR)
+		offset += var->yoffset * fix->line_length +
+			var->xoffset * (var->bits_per_pixel >> 3);
+	else if (rotation == FB_ROTATE_UD)
+		offset -= var->yoffset * fix->line_length +
+			var->xoffset * (var->bits_per_pixel >> 3);
+	else if (rotation == FB_ROTATE_CW)
+		offset -= var->xoffset * fix->line_length +
+			var->yoffset * (var->bits_per_pixel >> 3);
+	else if (rotation == FB_ROTATE_CCW)
+		offset += var->xoffset * fix->line_length +
+			var->yoffset * (var->bits_per_pixel >> 3);
+
+	return offset;
+}
+
+static void omapfb_calc_addr(const struct omapfb_info *ofbi,
+			     const struct fb_var_screeninfo *var,
+			     const struct fb_fix_screeninfo *fix,
+			     int rotation, u32 *paddr)
+{
+	u32 data_start_p;
+	int offset;
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
+	else
+		data_start_p = omapfb_get_region_paddr(ofbi);
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		offset = calc_rotation_offset_vrfb(var, fix, rotation);
+	else
+		offset = calc_rotation_offset_dma(var, fix, rotation);
+
+	data_start_p += offset;
+
+	if (offset)
+		DBG("offset %d, %d = %d\n",
+		    var->xoffset, var->yoffset, offset);
+
+	DBG("paddr %x\n", data_start_p);
+
+	*paddr = data_start_p;
+}
+
+/* setup overlay according to the fb */
+int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+		u16 posx, u16 posy, u16 outw, u16 outh)
+{
+	int r = 0;
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	enum omap_color_mode mode = 0;
+	u32 data_start_p = 0;
+	struct omap_overlay_info info;
+	int xres, yres;
+	int screen_width;
+	int mirror;
+	int rotation = var->rotate;
+	int i;
+
+	WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ovl != ofbi->overlays[i])
+			continue;
+
+		rotation = (rotation + ofbi->rotation[i]) % 4;
+		break;
+	}
+
+	DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
+			posx, posy, outw, outh);
+
+	if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
+		xres = var->yres;
+		yres = var->xres;
+	} else {
+		xres = var->xres;
+		yres = var->yres;
+	}
+
+	if (ofbi->region->size)
+		omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
+
+	r = fb_mode_to_dss_mode(var, &mode);
+	if (r) {
+		DBG("fb_mode_to_dss_mode failed");
+		goto err;
+	}
+
+	switch (var->nonstd) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUY422:
+		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+			screen_width = fix->line_length
+				/ (var->bits_per_pixel >> 2);
+			break;
+		}
+	default:
+		screen_width = fix->line_length / (var->bits_per_pixel >> 3);
+		break;
+	}
+
+	ovl->get_overlay_info(ovl, &info);
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		mirror = 0;
+	else
+		mirror = ofbi->mirror;
+
+	info.paddr = data_start_p;
+	info.screen_width = screen_width;
+	info.width = xres;
+	info.height = yres;
+	info.color_mode = mode;
+	info.rotation_type = ofbi->rotation_type;
+	info.rotation = rotation;
+	info.mirror = mirror;
+
+	info.pos_x = posx;
+	info.pos_y = posy;
+	info.out_width = outw;
+	info.out_height = outh;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r) {
+		DBG("ovl->setup_overlay_info failed\n");
+		goto err;
+	}
+
+	return 0;
+
+err:
+	DBG("setup_overlay failed\n");
+	return r;
+}
+
+/* apply var to the overlay */
+int omapfb_apply_changes(struct fb_info *fbi, int init)
+{
+	int r = 0;
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omap_overlay *ovl;
+	u16 posx, posy;
+	u16 outw, outh;
+	int i;
+
+#ifdef DEBUG
+	if (omapfb_test_pattern)
+		fill_fb(fbi);
+#endif
+
+	WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		ovl = ofbi->overlays[i];
+
+		DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
+
+		if (ofbi->region->size == 0) {
+			/* the fb is not available. disable the overlay */
+			omapfb_overlay_enable(ovl, 0);
+			if (!init && ovl->manager)
+				ovl->manager->apply(ovl->manager);
+			continue;
+		}
+
+		if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+			int rotation = (var->rotate + ofbi->rotation[i]) % 4;
+			if (rotation == FB_ROTATE_CW ||
+					rotation == FB_ROTATE_CCW) {
+				outw = var->yres;
+				outh = var->xres;
+			} else {
+				outw = var->xres;
+				outh = var->yres;
+			}
+		} else {
+			struct omap_overlay_info info;
+			ovl->get_overlay_info(ovl, &info);
+			outw = info.out_width;
+			outh = info.out_height;
+		}
+
+		if (init) {
+			posx = 0;
+			posy = 0;
+		} else {
+			struct omap_overlay_info info;
+			ovl->get_overlay_info(ovl, &info);
+			posx = info.pos_x;
+			posy = info.pos_y;
+		}
+
+		r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
+		if (r)
+			goto err;
+
+		if (!init && ovl->manager)
+			ovl->manager->apply(ovl->manager);
+	}
+	return 0;
+err:
+	DBG("apply_changes failed\n");
+	return r;
+}
+
+/* checks var and eventually tweaks it to something supported,
+ * DO NOT MODIFY PAR */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	int r;
+
+	DBG("check_var(%d)\n", FB2OFB(fbi)->id);
+
+	omapfb_get_mem_region(ofbi->region);
+
+	r = check_fb_var(fbi, var);
+
+	omapfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+
+/* set the video mode according to info->var */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	int r;
+
+	DBG("set_par(%d)\n", FB2OFB(fbi)->id);
+
+	omapfb_get_mem_region(ofbi->region);
+
+	set_fb_fix(fbi);
+
+	r = setup_vrfb_rotation(fbi);
+	if (r)
+		goto out;
+
+	r = omapfb_apply_changes(fbi, 0);
+
+ out:
+	omapfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo new_var;
+	int r;
+
+	DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
+
+	if (var->xoffset == fbi->var.xoffset &&
+	    var->yoffset == fbi->var.yoffset)
+		return 0;
+
+	new_var = fbi->var;
+	new_var.xoffset = var->xoffset;
+	new_var.yoffset = var->yoffset;
+
+	fbi->var = new_var;
+
+	omapfb_get_mem_region(ofbi->region);
+
+	r = omapfb_apply_changes(fbi, 0);
+
+	omapfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+
+static void mmap_user_open(struct vm_area_struct *vma)
+{
+	struct omapfb2_mem_region *rg = vma->vm_private_data;
+
+	omapfb_get_mem_region(rg);
+	atomic_inc(&rg->map_count);
+	omapfb_put_mem_region(rg);
+}
+
+static void mmap_user_close(struct vm_area_struct *vma)
+{
+	struct omapfb2_mem_region *rg = vma->vm_private_data;
+
+	omapfb_get_mem_region(rg);
+	atomic_dec(&rg->map_count);
+	omapfb_put_mem_region(rg);
+}
+
+static struct vm_operations_struct mmap_user_ops = {
+	.open = mmap_user_open,
+	.close = mmap_user_close,
+};
+
+static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct omapfb2_mem_region *rg;
+	unsigned long start;
+	u32 len;
+	int r;
+
+	rg = omapfb_get_mem_region(ofbi->region);
+
+	start = omapfb_get_region_paddr(ofbi);
+	len = fix->smem_len;
+
+	DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
+			vma->vm_pgoff << PAGE_SHIFT);
+
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	vma->vm_ops = &mmap_user_ops;
+	vma->vm_private_data = rg;
+
+	r = vm_iomap_memory(vma, start, len);
+	if (r)
+		goto error;
+
+	/* vm_ops.open won't be called for mmap itself. */
+	atomic_inc(&rg->map_count);
+
+	omapfb_put_mem_region(rg);
+
+	return 0;
+
+error:
+	omapfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
+		u_int blue, u_int transp, int update_hw_pal)
+{
+	/*struct omapfb_info *ofbi = FB2OFB(fbi);*/
+	/*struct omapfb2_device *fbdev = ofbi->fbdev;*/
+	struct fb_var_screeninfo *var = &fbi->var;
+	int r = 0;
+
+	enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
+
+	/*switch (plane->color_mode) {*/
+	switch (mode) {
+	case OMAPFB_COLOR_YUV422:
+	case OMAPFB_COLOR_YUV420:
+	case OMAPFB_COLOR_YUY422:
+		r = -EINVAL;
+		break;
+	case OMAPFB_COLOR_CLUT_8BPP:
+	case OMAPFB_COLOR_CLUT_4BPP:
+	case OMAPFB_COLOR_CLUT_2BPP:
+	case OMAPFB_COLOR_CLUT_1BPP:
+		/*
+		   if (fbdev->ctrl->setcolreg)
+		   r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+		   transp, update_hw_pal);
+		   */
+		/* Fallthrough */
+		r = -EINVAL;
+		break;
+	case OMAPFB_COLOR_RGB565:
+	case OMAPFB_COLOR_RGB444:
+	case OMAPFB_COLOR_RGB24P:
+	case OMAPFB_COLOR_RGB24U:
+		if (r != 0)
+			break;
+
+		if (regno < 16) {
+			u32 pal;
+			pal = ((red >> (16 - var->red.length)) <<
+					var->red.offset) |
+				((green >> (16 - var->green.length)) <<
+				 var->green.offset) |
+				(blue >> (16 - var->blue.length));
+			((u32 *)(fbi->pseudo_palette))[regno] = pal;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		u_int transp, struct fb_info *info)
+{
+	DBG("setcolreg\n");
+
+	return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	int count, index, r;
+	u16 *red, *green, *blue, *transp;
+	u16 trans = 0xffff;
+
+	DBG("setcmap\n");
+
+	red     = cmap->red;
+	green   = cmap->green;
+	blue    = cmap->blue;
+	transp  = cmap->transp;
+	index   = cmap->start;
+
+	for (count = 0; count < cmap->len; count++) {
+		if (transp)
+			trans = *transp++;
+		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+				count == cmap->len - 1);
+		if (r != 0)
+			return r;
+	}
+
+	return 0;
+}
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_dss_device *display = fb2display(fbi);
+	struct omapfb_display_data *d;
+	int r = 0;
+
+	if (!display)
+		return -EINVAL;
+
+	omapfb_lock(fbdev);
+
+	d = get_display_data(fbdev, display);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
+			goto exit;
+
+		r = display->driver->enable(display);
+
+		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
+				d->update_mode == OMAPFB_AUTO_UPDATE &&
+				!d->auto_update_work_enabled)
+			omapfb_start_auto_update(fbdev, display);
+
+		break;
+
+	case FB_BLANK_NORMAL:
+		/* FB_BLANK_NORMAL could be implemented.
+		 * Needs DSS additions. */
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
+			goto exit;
+
+		if (d->auto_update_work_enabled)
+			omapfb_stop_auto_update(fbdev, display);
+
+		display->driver->disable(display);
+
+		break;
+
+	default:
+		r = -EINVAL;
+	}
+
+exit:
+	omapfb_unlock(fbdev);
+
+	return r;
+}
+
+#if 0
+/* XXX fb_read and fb_write are needed for VRFB */
+ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
+	/* XXX needed for VRFB */
+	return count;
+}
+#endif
+
+static struct fb_ops omapfb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_open        = omapfb_open,
+	.fb_release     = omapfb_release,
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_blank       = omapfb_blank,
+	.fb_ioctl       = omapfb_ioctl,
+	.fb_check_var   = omapfb_check_var,
+	.fb_set_par     = omapfb_set_par,
+	.fb_pan_display = omapfb_pan_display,
+	.fb_mmap	= omapfb_mmap,
+	.fb_setcolreg	= omapfb_setcolreg,
+	.fb_setcmap	= omapfb_setcmap,
+	/*.fb_write	= omapfb_write,*/
+};
+
+static void omapfb_free_fbmem(struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb2_mem_region *rg;
+
+	rg = ofbi->region;
+
+	if (rg->token == NULL)
+		return;
+
+	WARN_ON(atomic_read(&rg->map_count));
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		/* unmap the 0 angle rotation */
+		if (rg->vrfb.vaddr[0]) {
+			iounmap(rg->vrfb.vaddr[0]);
+			rg->vrfb.vaddr[0] = NULL;
+		}
+
+		omap_vrfb_release_ctx(&rg->vrfb);
+	}
+
+	dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
+			&rg->attrs);
+
+	rg->token = NULL;
+	rg->vaddr = NULL;
+	rg->paddr = 0;
+	rg->alloc = 0;
+	rg->size = 0;
+}
+
+static void clear_fb_info(struct fb_info *fbi)
+{
+	memset(&fbi->var, 0, sizeof(fbi->var));
+	memset(&fbi->fix, 0, sizeof(fbi->fix));
+	strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
+}
+
+static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
+{
+	int i;
+
+	DBG("free all fbmem\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		omapfb_free_fbmem(fbi);
+		clear_fb_info(fbi);
+	}
+
+	return 0;
+}
+
+static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
+		unsigned long paddr)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb2_mem_region *rg;
+	void *token;
+	DEFINE_DMA_ATTRS(attrs);
+	dma_addr_t dma_handle;
+	int r;
+
+	rg = ofbi->region;
+
+	rg->paddr = 0;
+	rg->vaddr = NULL;
+	memset(&rg->vrfb, 0, sizeof rg->vrfb);
+	rg->size = 0;
+	rg->type = 0;
+	rg->alloc = false;
+	rg->map = false;
+
+	size = PAGE_ALIGN(size);
+
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+
+	DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+
+	token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
+			GFP_KERNEL, &attrs);
+
+	if (token == NULL) {
+		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
+		return -ENOMEM;
+	}
+
+	DBG("allocated VRAM paddr %lx, vaddr %p\n",
+			(unsigned long)dma_handle, token);
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		r = omap_vrfb_request_ctx(&rg->vrfb);
+		if (r) {
+			dma_free_attrs(fbdev->dev, size, token, dma_handle,
+					&attrs);
+			dev_err(fbdev->dev, "vrfb create ctx failed\n");
+			return r;
+		}
+	}
+
+	rg->attrs = attrs;
+	rg->token = token;
+	rg->dma_handle = dma_handle;
+
+	rg->paddr = (unsigned long)dma_handle;
+	rg->vaddr = (void __iomem *)token;
+	rg->size = size;
+	rg->alloc = 1;
+
+	return 0;
+}
+
+/* allocate fbmem using display resolution as reference */
+static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
+		unsigned long paddr)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_dss_device *display;
+	int bytespp;
+
+	display =  fb2display(fbi);
+
+	if (!display)
+		return 0;
+
+	switch (omapfb_get_recommended_bpp(fbdev, display)) {
+	case 16:
+		bytespp = 2;
+		break;
+	case 24:
+		bytespp = 4;
+		break;
+	default:
+		bytespp = 4;
+		break;
+	}
+
+	if (!size) {
+		u16 w, h;
+
+		display->driver->get_resolution(display, &w, &h);
+
+		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+			size = max(omap_vrfb_min_phys_size(w, h, bytespp),
+					omap_vrfb_min_phys_size(h, w, bytespp));
+
+			DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
+					w * h * bytespp, size);
+		} else {
+			size = w * h * bytespp;
+		}
+	}
+
+	if (!size)
+		return 0;
+
+	return omapfb_alloc_fbmem(fbi, size, paddr);
+}
+
+static int omapfb_parse_vram_param(const char *param, int max_entries,
+		unsigned long *sizes, unsigned long *paddrs)
+{
+	int fbnum;
+	unsigned long size;
+	unsigned long paddr = 0;
+	char *p, *start;
+
+	start = (char *)param;
+
+	while (1) {
+		p = start;
+
+		fbnum = simple_strtoul(p, &p, 10);
+
+		if (p == start)
+			return -EINVAL;
+
+		if (*p != ':')
+			return -EINVAL;
+
+		if (fbnum >= max_entries)
+			return -EINVAL;
+
+		size = memparse(p + 1, &p);
+
+		if (!size)
+			return -EINVAL;
+
+		paddr = 0;
+
+		if (*p == '@') {
+			paddr = simple_strtoul(p + 1, &p, 16);
+
+			if (!paddr)
+				return -EINVAL;
+
+		}
+
+		WARN_ONCE(paddr,
+			"reserving memory at predefined address not supported\n");
+
+		paddrs[fbnum] = paddr;
+		sizes[fbnum] = size;
+
+		if (*p == 0)
+			break;
+
+		if (*p != ',')
+			return -EINVAL;
+
+		++p;
+
+		start = p;
+	}
+
+	return 0;
+}
+
+static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
+{
+	int i, r;
+	unsigned long vram_sizes[10];
+	unsigned long vram_paddrs[10];
+
+	memset(&vram_sizes, 0, sizeof(vram_sizes));
+	memset(&vram_paddrs, 0, sizeof(vram_paddrs));
+
+	if (def_vram &&	omapfb_parse_vram_param(def_vram, 10,
+				vram_sizes, vram_paddrs)) {
+		dev_err(fbdev->dev, "failed to parse vram parameter\n");
+
+		memset(&vram_sizes, 0, sizeof(vram_sizes));
+		memset(&vram_paddrs, 0, sizeof(vram_paddrs));
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		/* allocate memory automatically only for fb0, or if
+		 * excplicitly defined with vram or plat data option */
+		if (i == 0 || vram_sizes[i] != 0) {
+			r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
+					vram_sizes[i], vram_paddrs[i]);
+
+			if (r)
+				return r;
+		}
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		struct omapfb2_mem_region *rg;
+		rg = ofbi->region;
+
+		DBG("region%d phys %08x virt %p size=%lu\n",
+				i,
+				rg->paddr,
+				rg->vaddr,
+				rg->size);
+	}
+
+	return 0;
+}
+
+static void omapfb_clear_fb(struct fb_info *fbi)
+{
+	const struct fb_fillrect rect = {
+		.dx = 0,
+		.dy = 0,
+		.width = fbi->var.xres_virtual,
+		.height = fbi->var.yres_virtual,
+		.color = 0,
+		.rop = ROP_COPY,
+	};
+
+	cfb_fillrect(fbi, &rect);
+}
+
+int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb2_mem_region *rg = ofbi->region;
+	unsigned long old_size = rg->size;
+	unsigned long old_paddr = rg->paddr;
+	int old_type = rg->type;
+	int r;
+
+	if (type != OMAPFB_MEMTYPE_SDRAM)
+		return -EINVAL;
+
+	size = PAGE_ALIGN(size);
+
+	if (old_size == size && old_type == type)
+		return 0;
+
+	omapfb_free_fbmem(fbi);
+
+	if (size == 0) {
+		clear_fb_info(fbi);
+		return 0;
+	}
+
+	r = omapfb_alloc_fbmem(fbi, size, 0);
+
+	if (r) {
+		if (old_size)
+			omapfb_alloc_fbmem(fbi, old_size, old_paddr);
+
+		if (rg->size == 0)
+			clear_fb_info(fbi);
+
+		return r;
+	}
+
+	if (old_size == size)
+		return 0;
+
+	if (old_size == 0) {
+		DBG("initializing fb %d\n", ofbi->id);
+		r = omapfb_fb_init(fbdev, fbi);
+		if (r) {
+			DBG("omapfb_fb_init failed\n");
+			goto err;
+		}
+		r = omapfb_apply_changes(fbi, 1);
+		if (r) {
+			DBG("omapfb_apply_changes failed\n");
+			goto err;
+		}
+	} else {
+		struct fb_var_screeninfo new_var;
+		memcpy(&new_var, &fbi->var, sizeof(new_var));
+		r = check_fb_var(fbi, &new_var);
+		if (r)
+			goto err;
+		memcpy(&fbi->var, &new_var, sizeof(fbi->var));
+		set_fb_fix(fbi);
+		r = setup_vrfb_rotation(fbi);
+		if (r)
+			goto err;
+	}
+
+	omapfb_clear_fb(fbi);
+
+	return 0;
+err:
+	omapfb_free_fbmem(fbi);
+	clear_fb_info(fbi);
+	return r;
+}
+
+static void omapfb_auto_update_work(struct work_struct *work)
+{
+	struct omap_dss_device *dssdev;
+	struct omap_dss_driver *dssdrv;
+	struct omapfb_display_data *d;
+	u16 w, h;
+	unsigned int freq;
+	struct omapfb2_device *fbdev;
+
+	d = container_of(work, struct omapfb_display_data,
+			auto_update_work.work);
+
+	dssdev = d->dssdev;
+	dssdrv = dssdev->driver;
+	fbdev = d->fbdev;
+
+	if (!dssdrv || !dssdrv->update)
+		return;
+
+	if (dssdrv->sync)
+		dssdrv->sync(dssdev);
+
+	dssdrv->get_resolution(dssdev, &w, &h);
+	dssdrv->update(dssdev, 0, 0, w, h);
+
+	freq = auto_update_freq;
+	if (freq == 0)
+		freq = 20;
+	queue_delayed_work(fbdev->auto_update_wq,
+			&d->auto_update_work, HZ / freq);
+}
+
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+		struct omap_dss_device *display)
+{
+	struct omapfb_display_data *d;
+
+	if (fbdev->auto_update_wq == NULL) {
+		struct workqueue_struct *wq;
+
+		wq = create_singlethread_workqueue("omapfb_auto_update");
+
+		if (wq == NULL) {
+			dev_err(fbdev->dev, "Failed to create workqueue for "
+					"auto-update\n");
+			return;
+		}
+
+		fbdev->auto_update_wq = wq;
+	}
+
+	d = get_display_data(fbdev, display);
+
+	INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
+
+	d->auto_update_work_enabled = true;
+
+	omapfb_auto_update_work(&d->auto_update_work.work);
+}
+
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+		struct omap_dss_device *display)
+{
+	struct omapfb_display_data *d;
+
+	d = get_display_data(fbdev, display);
+
+	cancel_delayed_work_sync(&d->auto_update_work);
+
+	d->auto_update_work_enabled = false;
+}
+
+/* initialize fb_info, var, fix to something sane based on the display */
+static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct omap_dss_device *display = fb2display(fbi);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	int r = 0;
+
+	fbi->fbops = &omapfb_ops;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette = fbdev->pseudo_palette;
+
+	if (ofbi->region->size == 0) {
+		clear_fb_info(fbi);
+		return 0;
+	}
+
+	var->nonstd = 0;
+	var->bits_per_pixel = 0;
+
+	var->rotate = def_rotate;
+
+	if (display) {
+		u16 w, h;
+		int rotation = (var->rotate + ofbi->rotation[0]) % 4;
+
+		display->driver->get_resolution(display, &w, &h);
+
+		if (rotation == FB_ROTATE_CW ||
+				rotation == FB_ROTATE_CCW) {
+			var->xres = h;
+			var->yres = w;
+		} else {
+			var->xres = w;
+			var->yres = h;
+		}
+
+		var->xres_virtual = var->xres;
+		var->yres_virtual = var->yres;
+
+		if (!var->bits_per_pixel) {
+			switch (omapfb_get_recommended_bpp(fbdev, display)) {
+			case 16:
+				var->bits_per_pixel = 16;
+				break;
+			case 24:
+				var->bits_per_pixel = 32;
+				break;
+			default:
+				dev_err(fbdev->dev, "illegal display "
+						"bpp\n");
+				return -EINVAL;
+			}
+		}
+	} else {
+		/* if there's no display, let's just guess some basic values */
+		var->xres = 320;
+		var->yres = 240;
+		var->xres_virtual = var->xres;
+		var->yres_virtual = var->yres;
+		if (!var->bits_per_pixel)
+			var->bits_per_pixel = 16;
+	}
+
+	r = check_fb_var(fbi, var);
+	if (r)
+		goto err;
+
+	set_fb_fix(fbi);
+	r = setup_vrfb_rotation(fbi);
+	if (r)
+		goto err;
+
+	r = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (r)
+		dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
+err:
+	return r;
+}
+
+static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
+{
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+
+static void omapfb_free_resources(struct omapfb2_device *fbdev)
+{
+	int i;
+
+	DBG("free_resources\n");
+
+	if (fbdev == NULL)
+		return;
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		int j;
+
+		for (j = 0; j < ofbi->num_overlays; j++) {
+			struct omap_overlay *ovl = ofbi->overlays[j];
+			ovl->disable(ovl);
+		}
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++)
+		unregister_framebuffer(fbdev->fbs[i]);
+
+	/* free the reserved fbmem */
+	omapfb_free_all_fbmem(fbdev);
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		fbinfo_cleanup(fbdev, fbdev->fbs[i]);
+		framebuffer_release(fbdev->fbs[i]);
+	}
+
+	for (i = 0; i < fbdev->num_displays; i++) {
+		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+
+		if (fbdev->displays[i].auto_update_work_enabled)
+			omapfb_stop_auto_update(fbdev, dssdev);
+
+		if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
+			dssdev->driver->disable(dssdev);
+
+		dssdev->driver->disconnect(dssdev);
+
+		omap_dss_put_device(dssdev);
+	}
+
+	if (fbdev->auto_update_wq != NULL) {
+		flush_workqueue(fbdev->auto_update_wq);
+		destroy_workqueue(fbdev->auto_update_wq);
+		fbdev->auto_update_wq = NULL;
+	}
+
+	dev_set_drvdata(fbdev->dev, NULL);
+}
+
+static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
+{
+	int r, i;
+
+	fbdev->num_fbs = 0;
+
+	DBG("create %d framebuffers\n",	CONFIG_FB_OMAP2_NUM_FBS);
+
+	/* allocate fb_infos */
+	for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
+		struct fb_info *fbi;
+		struct omapfb_info *ofbi;
+
+		fbi = framebuffer_alloc(sizeof(struct omapfb_info),
+				fbdev->dev);
+
+		if (fbi == NULL) {
+			dev_err(fbdev->dev,
+				"unable to allocate memory for plane info\n");
+			return -ENOMEM;
+		}
+
+		clear_fb_info(fbi);
+
+		fbdev->fbs[i] = fbi;
+
+		ofbi = FB2OFB(fbi);
+		ofbi->fbdev = fbdev;
+		ofbi->id = i;
+
+		ofbi->region = &fbdev->regions[i];
+		ofbi->region->id = i;
+		init_rwsem(&ofbi->region->lock);
+
+		/* assign these early, so that fb alloc can use them */
+		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
+			OMAP_DSS_ROT_DMA;
+		ofbi->mirror = def_mirror;
+
+		fbdev->num_fbs++;
+	}
+
+	DBG("fb_infos allocated\n");
+
+	/* assign overlays for the fbs */
+	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+		ofbi->overlays[0] = fbdev->overlays[i];
+		ofbi->num_overlays = 1;
+	}
+
+	/* allocate fb memories */
+	r = omapfb_allocate_all_fbs(fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "failed to allocate fbmem\n");
+		return r;
+	}
+
+	DBG("fbmems allocated\n");
+
+	/* setup fb_infos */
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		struct omapfb_info *ofbi = FB2OFB(fbi);
+
+		omapfb_get_mem_region(ofbi->region);
+		r = omapfb_fb_init(fbdev, fbi);
+		omapfb_put_mem_region(ofbi->region);
+
+		if (r) {
+			dev_err(fbdev->dev, "failed to setup fb_info\n");
+			return r;
+		}
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		struct omapfb_info *ofbi = FB2OFB(fbi);
+
+		if (ofbi->region->size == 0)
+			continue;
+
+		omapfb_clear_fb(fbi);
+	}
+
+	DBG("fb_infos initialized\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		r = register_framebuffer(fbdev->fbs[i]);
+		if (r != 0) {
+			dev_err(fbdev->dev,
+				"registering framebuffer %d failed\n", i);
+			return r;
+		}
+	}
+
+	DBG("framebuffers registered\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		struct omapfb_info *ofbi = FB2OFB(fbi);
+
+		omapfb_get_mem_region(ofbi->region);
+		r = omapfb_apply_changes(fbi, 1);
+		omapfb_put_mem_region(ofbi->region);
+
+		if (r) {
+			dev_err(fbdev->dev, "failed to change mode\n");
+			return r;
+		}
+	}
+
+	/* Enable fb0 */
+	if (fbdev->num_fbs > 0) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
+
+		if (ofbi->num_overlays > 0) {
+			struct omap_overlay *ovl = ofbi->overlays[0];
+
+			ovl->manager->apply(ovl->manager);
+
+			r = omapfb_overlay_enable(ovl, 1);
+
+			if (r) {
+				dev_err(fbdev->dev,
+						"failed to enable overlay\n");
+				return r;
+			}
+		}
+	}
+
+	DBG("create_framebuffers done\n");
+
+	return 0;
+}
+
+static int omapfb_mode_to_timings(const char *mode_str,
+		struct omap_dss_device *display,
+		struct omap_video_timings *timings, u8 *bpp)
+{
+	struct fb_info *fbi;
+	struct fb_var_screeninfo *var;
+	struct fb_ops *fbops;
+	int r;
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+	if (strcmp(mode_str, "pal") == 0) {
+		*timings = omap_dss_pal_timings;
+		*bpp = 24;
+		return 0;
+	} else if (strcmp(mode_str, "ntsc") == 0) {
+		*timings = omap_dss_ntsc_timings;
+		*bpp = 24;
+		return 0;
+	}
+#endif
+
+	/* this is quite a hack, but I wanted to use the modedb and for
+	 * that we need fb_info and var, so we create dummy ones */
+
+	*bpp = 0;
+	fbi = NULL;
+	var = NULL;
+	fbops = NULL;
+
+	fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
+	if (fbi == NULL) {
+		r = -ENOMEM;
+		goto err;
+	}
+
+	var = kzalloc(sizeof(*var), GFP_KERNEL);
+	if (var == NULL) {
+		r = -ENOMEM;
+		goto err;
+	}
+
+	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
+	if (fbops == NULL) {
+		r = -ENOMEM;
+		goto err;
+	}
+
+	fbi->fbops = fbops;
+
+	r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
+	if (r == 0) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	if (display->driver->get_timings) {
+		display->driver->get_timings(display, timings);
+	} else {
+		timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+		timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+		timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+	}
+
+	timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000;
+	timings->hbp = var->left_margin;
+	timings->hfp = var->right_margin;
+	timings->vbp = var->upper_margin;
+	timings->vfp = var->lower_margin;
+	timings->hsw = var->hsync_len;
+	timings->vsw = var->vsync_len;
+	timings->x_res = var->xres;
+	timings->y_res = var->yres;
+	timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
+				OMAPDSS_SIG_ACTIVE_HIGH :
+				OMAPDSS_SIG_ACTIVE_LOW;
+	timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
+				OMAPDSS_SIG_ACTIVE_HIGH :
+				OMAPDSS_SIG_ACTIVE_LOW;
+	timings->interlace = var->vmode & FB_VMODE_INTERLACED;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		*bpp = 16;
+		break;
+	case 24:
+	case 32:
+	default:
+		*bpp = 24;
+		break;
+	}
+
+	r = 0;
+
+err:
+	kfree(fbi);
+	kfree(var);
+	kfree(fbops);
+
+	return r;
+}
+
+static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
+		struct omap_dss_device *display, char *mode_str)
+{
+	int r;
+	u8 bpp;
+	struct omap_video_timings timings, temp_timings;
+	struct omapfb_display_data *d;
+
+	r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
+	if (r)
+		return r;
+
+	d = get_display_data(fbdev, display);
+	d->bpp_override = bpp;
+
+	if (display->driver->check_timings) {
+		r = display->driver->check_timings(display, &timings);
+		if (r)
+			return r;
+	} else {
+		/* If check_timings is not present compare xres and yres */
+		if (display->driver->get_timings) {
+			display->driver->get_timings(display, &temp_timings);
+
+			if (temp_timings.x_res != timings.x_res ||
+				temp_timings.y_res != timings.y_res)
+				return -EINVAL;
+		}
+	}
+
+	if (display->driver->set_timings)
+			display->driver->set_timings(display, &timings);
+
+	return 0;
+}
+
+static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
+		struct omap_dss_device *dssdev)
+{
+	struct omapfb_display_data *d;
+
+	BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
+
+	d = get_display_data(fbdev, dssdev);
+
+	if (d->bpp_override != 0)
+		return d->bpp_override;
+
+	return dssdev->driver->get_recommended_bpp(dssdev);
+}
+
+static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
+{
+	char *str, *options, *this_opt;
+	int r = 0;
+
+	str = kstrdup(def_mode, GFP_KERNEL);
+	if (!str)
+		return -ENOMEM;
+	options = str;
+
+	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+		char *p, *display_str, *mode_str;
+		struct omap_dss_device *display;
+		int i;
+
+		p = strchr(this_opt, ':');
+		if (!p) {
+			r = -EINVAL;
+			break;
+		}
+
+		*p = 0;
+		display_str = this_opt;
+		mode_str = p + 1;
+
+		display = NULL;
+		for (i = 0; i < fbdev->num_displays; ++i) {
+			if (strcmp(fbdev->displays[i].dssdev->name,
+						display_str) == 0) {
+				display = fbdev->displays[i].dssdev;
+				break;
+			}
+		}
+
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = omapfb_set_def_mode(fbdev, display, mode_str);
+		if (r)
+			break;
+	}
+
+	kfree(str);
+
+	return r;
+}
+
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+		struct omap_dss_device *display,
+		struct omap_video_timings *t)
+{
+	if (display->driver->get_timings) {
+		display->driver->get_timings(display, t);
+	} else {
+		t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+		t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+		t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+	}
+
+	t->x_res = m->xres;
+	t->y_res = m->yres;
+	t->pixelclock = PICOS2KHZ(m->pixclock) * 1000;
+	t->hsw = m->hsync_len;
+	t->hfp = m->right_margin;
+	t->hbp = m->left_margin;
+	t->vsw = m->vsync_len;
+	t->vfp = m->lower_margin;
+	t->vbp = m->upper_margin;
+	t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
+				OMAPDSS_SIG_ACTIVE_HIGH :
+				OMAPDSS_SIG_ACTIVE_LOW;
+	t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
+				OMAPDSS_SIG_ACTIVE_HIGH :
+				OMAPDSS_SIG_ACTIVE_LOW;
+	t->interlace = m->vmode & FB_VMODE_INTERLACED;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+		struct omap_video_timings *timings)
+{
+	struct fb_monspecs *specs;
+	u8 *edid;
+	int r, i, best_idx, len;
+
+	if (!display->driver->read_edid)
+		return -ENODEV;
+
+	len = 0x80 * 2;
+	edid = kmalloc(len, GFP_KERNEL);
+	if (edid == NULL)
+		return -ENOMEM;
+
+	r = display->driver->read_edid(display, edid, len);
+	if (r < 0)
+		goto err1;
+
+	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+	if (specs == NULL) {
+		r = -ENOMEM;
+		goto err1;
+	}
+
+	fb_edid_to_monspecs(edid, specs);
+
+	best_idx = -1;
+
+	for (i = 0; i < specs->modedb_len; ++i) {
+		struct fb_videomode *m;
+		struct omap_video_timings t;
+
+		m = &specs->modedb[i];
+
+		if (m->pixclock == 0)
+			continue;
+
+		/* skip repeated pixel modes */
+		if (m->xres == 2880 || m->xres == 1440)
+			continue;
+
+		if (m->vmode & FB_VMODE_INTERLACED ||
+				m->vmode & FB_VMODE_DOUBLE)
+			continue;
+
+		fb_videomode_to_omap_timings(m, display, &t);
+
+		r = display->driver->check_timings(display, &t);
+		if (r == 0) {
+			best_idx = i;
+			break;
+		}
+	}
+
+	if (best_idx == -1) {
+		r = -ENOENT;
+		goto err2;
+	}
+
+	fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
+		timings);
+
+	r = 0;
+
+err2:
+	fb_destroy_modedb(specs->modedb);
+	kfree(specs);
+err1:
+	kfree(edid);
+
+	return r;
+}
+
+static int omapfb_init_display(struct omapfb2_device *fbdev,
+		struct omap_dss_device *dssdev)
+{
+	struct omap_dss_driver *dssdrv = dssdev->driver;
+	struct omapfb_display_data *d;
+	int r;
+
+	r = dssdrv->enable(dssdev);
+	if (r) {
+		dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
+				dssdev->name);
+		return r;
+	}
+
+	d = get_display_data(fbdev, dssdev);
+
+	d->fbdev = fbdev;
+
+	if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+		u16 w, h;
+
+		if (auto_update) {
+			omapfb_start_auto_update(fbdev, dssdev);
+			d->update_mode = OMAPFB_AUTO_UPDATE;
+		} else {
+			d->update_mode = OMAPFB_MANUAL_UPDATE;
+		}
+
+		if (dssdrv->enable_te) {
+			r = dssdrv->enable_te(dssdev, 1);
+			if (r) {
+				dev_err(fbdev->dev, "Failed to set TE\n");
+				return r;
+			}
+		}
+
+		dssdrv->get_resolution(dssdev, &w, &h);
+		r = dssdrv->update(dssdev, 0, 0, w, h);
+		if (r) {
+			dev_err(fbdev->dev,
+					"Failed to update display\n");
+			return r;
+		}
+	} else {
+		d->update_mode = OMAPFB_AUTO_UPDATE;
+	}
+
+	return 0;
+}
+
+static int omapfb_init_connections(struct omapfb2_device *fbdev,
+		struct omap_dss_device *def_dssdev)
+{
+	int i, r;
+	struct omap_overlay_manager *mgr;
+
+	r = def_dssdev->driver->connect(def_dssdev);
+	if (r) {
+		dev_err(fbdev->dev, "failed to connect default display\n");
+		return r;
+	}
+
+	for (i = 0; i < fbdev->num_displays; ++i) {
+		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+
+		if (dssdev == def_dssdev)
+			continue;
+
+		/*
+		 * We don't care if the connect succeeds or not. We just want to
+		 * connect as many displays as possible.
+		 */
+		dssdev->driver->connect(dssdev);
+	}
+
+	mgr = omapdss_find_mgr_from_display(def_dssdev);
+
+	if (!mgr) {
+		dev_err(fbdev->dev, "no ovl manager for the default display\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < fbdev->num_overlays; i++) {
+		struct omap_overlay *ovl = fbdev->overlays[i];
+
+		if (ovl->manager)
+			ovl->unset_manager(ovl);
+
+		r = ovl->set_manager(ovl, mgr);
+		if (r)
+			dev_warn(fbdev->dev,
+					"failed to connect overlay %s to manager %s\n",
+					ovl->name, mgr->name);
+	}
+
+	return 0;
+}
+
+static struct omap_dss_device *
+omapfb_find_default_display(struct omapfb2_device *fbdev)
+{
+	const char *def_name;
+	int i;
+
+	/*
+	 * Search with the display name from the user or the board file,
+	 * comparing to display names and aliases
+	 */
+
+	def_name = omapdss_get_default_display_name();
+
+	if (def_name) {
+		for (i = 0; i < fbdev->num_displays; ++i) {
+			struct omap_dss_device *dssdev;
+
+			dssdev = fbdev->displays[i].dssdev;
+
+			if (dssdev->name && strcmp(def_name, dssdev->name) == 0)
+				return dssdev;
+
+			if (strcmp(def_name, dssdev->alias) == 0)
+				return dssdev;
+		}
+
+		/* def_name given but not found */
+		return NULL;
+	}
+
+	/* then look for DT alias display0 */
+	for (i = 0; i < fbdev->num_displays; ++i) {
+		struct omap_dss_device *dssdev;
+		int id;
+
+		dssdev = fbdev->displays[i].dssdev;
+
+		if (dssdev->dev->of_node == NULL)
+			continue;
+
+		id = of_alias_get_id(dssdev->dev->of_node, "display");
+		if (id == 0)
+			return dssdev;
+	}
+
+	/* return the first display we have in the list */
+	return fbdev->displays[0].dssdev;
+}
+
+static int omapfb_probe(struct platform_device *pdev)
+{
+	struct omapfb2_device *fbdev = NULL;
+	int r = 0;
+	int i;
+	struct omap_dss_device *def_display;
+	struct omap_dss_device *dssdev;
+
+	DBG("omapfb_probe\n");
+
+	if (omapdss_is_initialized() == false)
+		return -EPROBE_DEFER;
+
+	if (pdev->num_resources != 0) {
+		dev_err(&pdev->dev, "probed for an unknown device\n");
+		r = -ENODEV;
+		goto err0;
+	}
+
+	fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
+			GFP_KERNEL);
+	if (fbdev == NULL) {
+		r = -ENOMEM;
+		goto err0;
+	}
+
+	if (def_vrfb && !omap_vrfb_supported()) {
+		def_vrfb = 0;
+		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
+				"ignoring the module parameter vrfb=y\n");
+	}
+
+	r = omapdss_compat_init();
+	if (r)
+		goto err0;
+
+	mutex_init(&fbdev->mtx);
+
+	fbdev->dev = &pdev->dev;
+	platform_set_drvdata(pdev, fbdev);
+
+	fbdev->num_displays = 0;
+	dssdev = NULL;
+	for_each_dss_dev(dssdev) {
+		struct omapfb_display_data *d;
+
+		omap_dss_get_device(dssdev);
+
+		if (!dssdev->driver) {
+			dev_warn(&pdev->dev, "no driver for display: %s\n",
+				dssdev->name);
+			omap_dss_put_device(dssdev);
+			continue;
+		}
+
+		d = &fbdev->displays[fbdev->num_displays++];
+		d->dssdev = dssdev;
+		if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+			d->update_mode = OMAPFB_MANUAL_UPDATE;
+		else
+			d->update_mode = OMAPFB_AUTO_UPDATE;
+	}
+
+	if (fbdev->num_displays == 0) {
+		dev_err(&pdev->dev, "no displays\n");
+		r = -EPROBE_DEFER;
+		goto cleanup;
+	}
+
+	fbdev->num_overlays = omap_dss_get_num_overlays();
+	for (i = 0; i < fbdev->num_overlays; i++)
+		fbdev->overlays[i] = omap_dss_get_overlay(i);
+
+	fbdev->num_managers = omap_dss_get_num_overlay_managers();
+	for (i = 0; i < fbdev->num_managers; i++)
+		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
+
+	def_display = omapfb_find_default_display(fbdev);
+	if (def_display == NULL) {
+		dev_err(fbdev->dev, "failed to find default display\n");
+		r = -EPROBE_DEFER;
+		goto cleanup;
+	}
+
+	r = omapfb_init_connections(fbdev, def_display);
+	if (r) {
+		dev_err(fbdev->dev, "failed to init overlay connections\n");
+		goto cleanup;
+	}
+
+	if (def_mode && strlen(def_mode) > 0) {
+		if (omapfb_parse_def_modes(fbdev))
+			dev_warn(&pdev->dev, "cannot parse default modes\n");
+	} else if (def_display && def_display->driver->set_timings &&
+			def_display->driver->check_timings) {
+		struct omap_video_timings t;
+
+		r = omapfb_find_best_mode(def_display, &t);
+
+		if (r == 0)
+			def_display->driver->set_timings(def_display, &t);
+	}
+
+	r = omapfb_create_framebuffers(fbdev);
+	if (r)
+		goto cleanup;
+
+	for (i = 0; i < fbdev->num_managers; i++) {
+		struct omap_overlay_manager *mgr;
+		mgr = fbdev->managers[i];
+		r = mgr->apply(mgr);
+		if (r)
+			dev_warn(fbdev->dev, "failed to apply dispc config\n");
+	}
+
+	DBG("mgr->apply'ed\n");
+
+	if (def_display) {
+		r = omapfb_init_display(fbdev, def_display);
+		if (r) {
+			dev_err(fbdev->dev,
+					"failed to initialize default "
+					"display\n");
+			goto cleanup;
+		}
+	}
+
+	DBG("create sysfs for fbs\n");
+	r = omapfb_create_sysfs(fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "failed to create sysfs entries\n");
+		goto cleanup;
+	}
+
+	if (def_display) {
+		u16 w, h;
+
+		def_display->driver->get_resolution(def_display, &w, &h);
+
+		dev_info(fbdev->dev, "using display '%s' mode %dx%d\n",
+			def_display->name, w, h);
+	}
+
+	return 0;
+
+cleanup:
+	omapfb_free_resources(fbdev);
+	omapdss_compat_uninit();
+err0:
+	dev_err(&pdev->dev, "failed to setup omapfb\n");
+	return r;
+}
+
+static int __exit omapfb_remove(struct platform_device *pdev)
+{
+	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
+
+	/* FIXME: wait till completion of pending events */
+
+	omapfb_remove_sysfs(fbdev);
+
+	omapfb_free_resources(fbdev);
+
+	omapdss_compat_uninit();
+
+	return 0;
+}
+
+static struct platform_driver omapfb_driver = {
+	.probe		= omapfb_probe,
+	.remove         = __exit_p(omapfb_remove),
+	.driver         = {
+		.name   = "omapfb",
+		.owner  = THIS_MODULE,
+	},
+};
+
+module_param_named(mode, def_mode, charp, 0);
+module_param_named(vram, def_vram, charp, 0);
+module_param_named(rotate, def_rotate, int, 0);
+module_param_named(vrfb, def_vrfb, bool, 0);
+module_param_named(mirror, def_mirror, bool, 0);
+
+module_platform_driver(omapfb_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c b/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
new file mode 100644
index 000000000000..18fa9e1d0033
--- /dev/null
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
@@ -0,0 +1,605 @@
+/*
+ * linux/drivers/video/omap2/omapfb-sysfs.c
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fb.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/omapfb.h>
+
+#include <video/omapdss.h>
+#include <video/omapvrfb.h>
+
+#include "omapfb.h"
+
+static ssize_t show_rotate_type(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
+}
+
+static ssize_t store_rotate_type(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_mem_region *rg;
+	int rot_type;
+	int r;
+
+	r = kstrtoint(buf, 0, &rot_type);
+	if (r)
+		return r;
+
+	if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
+		return -EINVAL;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+
+	r = 0;
+	if (rot_type == ofbi->rotation_type)
+		goto out;
+
+	rg = omapfb_get_mem_region(ofbi->region);
+
+	if (rg->size) {
+		r = -EBUSY;
+		goto put_region;
+	}
+
+	ofbi->rotation_type = rot_type;
+
+	/*
+	 * Since the VRAM for this FB is not allocated at the moment we don't
+	 * need to do any further parameter checking at this point.
+	 */
+put_region:
+	omapfb_put_mem_region(rg);
+out:
+	unlock_fb_info(fbi);
+
+	return r ? r : count;
+}
+
+
+static ssize_t show_mirror(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
+}
+
+static ssize_t store_mirror(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	bool mirror;
+	int r;
+	struct fb_var_screeninfo new_var;
+
+	r = strtobool(buf, &mirror);
+	if (r)
+		return r;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+
+	ofbi->mirror = mirror;
+
+	omapfb_get_mem_region(ofbi->region);
+
+	memcpy(&new_var, &fbi->var, sizeof(new_var));
+	r = check_fb_var(fbi, &new_var);
+	if (r)
+		goto out;
+	memcpy(&fbi->var, &new_var, sizeof(fbi->var));
+
+	set_fb_fix(fbi);
+
+	r = omapfb_apply_changes(fbi, 0);
+	if (r)
+		goto out;
+
+	r = count;
+out:
+	omapfb_put_mem_region(ofbi->region);
+
+	unlock_fb_info(fbi);
+
+	return r;
+}
+
+static ssize_t show_overlays(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	ssize_t l = 0;
+	int t;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+	omapfb_lock(fbdev);
+
+	for (t = 0; t < ofbi->num_overlays; t++) {
+		struct omap_overlay *ovl = ofbi->overlays[t];
+		int ovlnum;
+
+		for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
+			if (ovl == fbdev->overlays[ovlnum])
+				break;
+
+		l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
+				t == 0 ? "" : ",", ovlnum);
+	}
+
+	l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
+	omapfb_unlock(fbdev);
+	unlock_fb_info(fbi);
+
+	return l;
+}
+
+static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
+		struct omap_overlay *ovl)
+{
+	int i, t;
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+		for (t = 0; t < ofbi->num_overlays; t++) {
+			if (ofbi->overlays[t] == ovl)
+				return ofbi;
+		}
+	}
+
+	return NULL;
+}
+
+static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
+	struct omap_overlay *ovl;
+	int num_ovls, r, i;
+	int len;
+	bool added = false;
+
+	num_ovls = 0;
+
+	len = strlen(buf);
+	if (buf[len - 1] == '\n')
+		len = len - 1;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+	omapfb_lock(fbdev);
+
+	if (len > 0) {
+		char *p = (char *)buf;
+		int ovlnum;
+
+		while (p < buf + len) {
+			int found;
+			if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
+				r = -EINVAL;
+				goto out;
+			}
+
+			ovlnum = simple_strtoul(p, &p, 0);
+			if (ovlnum > fbdev->num_overlays) {
+				r = -EINVAL;
+				goto out;
+			}
+
+			found = 0;
+			for (i = 0; i < num_ovls; ++i) {
+				if (ovls[i] == fbdev->overlays[ovlnum]) {
+					found = 1;
+					break;
+				}
+			}
+
+			if (!found)
+				ovls[num_ovls++] = fbdev->overlays[ovlnum];
+
+			p++;
+		}
+	}
+
+	for (i = 0; i < num_ovls; ++i) {
+		struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
+		if (ofbi2 && ofbi2 != ofbi) {
+			dev_err(fbdev->dev, "overlay already in use\n");
+			r = -EINVAL;
+			goto out;
+		}
+	}
+
+	/* detach unused overlays */
+	for (i = 0; i < ofbi->num_overlays; ++i) {
+		int t, found;
+
+		ovl = ofbi->overlays[i];
+
+		found = 0;
+
+		for (t = 0; t < num_ovls; ++t) {
+			if (ovl == ovls[t]) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (found)
+			continue;
+
+		DBG("detaching %d\n", ofbi->overlays[i]->id);
+
+		omapfb_get_mem_region(ofbi->region);
+
+		omapfb_overlay_enable(ovl, 0);
+
+		if (ovl->manager)
+			ovl->manager->apply(ovl->manager);
+
+		omapfb_put_mem_region(ofbi->region);
+
+		for (t = i + 1; t < ofbi->num_overlays; t++) {
+			ofbi->rotation[t-1] = ofbi->rotation[t];
+			ofbi->overlays[t-1] = ofbi->overlays[t];
+		}
+
+		ofbi->num_overlays--;
+		i--;
+	}
+
+	for (i = 0; i < num_ovls; ++i) {
+		int t, found;
+
+		ovl = ovls[i];
+
+		found = 0;
+
+		for (t = 0; t < ofbi->num_overlays; ++t) {
+			if (ovl == ofbi->overlays[t]) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (found)
+			continue;
+		ofbi->rotation[ofbi->num_overlays] = 0;
+		ofbi->overlays[ofbi->num_overlays++] = ovl;
+
+		added = true;
+	}
+
+	if (added) {
+		omapfb_get_mem_region(ofbi->region);
+
+		r = omapfb_apply_changes(fbi, 0);
+
+		omapfb_put_mem_region(ofbi->region);
+
+		if (r)
+			goto out;
+	}
+
+	r = count;
+out:
+	omapfb_unlock(fbdev);
+	unlock_fb_info(fbi);
+
+	return r;
+}
+
+static ssize_t show_overlays_rotate(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	ssize_t l = 0;
+	int t;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+
+	for (t = 0; t < ofbi->num_overlays; t++) {
+		l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
+				t == 0 ? "" : ",", ofbi->rotation[t]);
+	}
+
+	l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
+	unlock_fb_info(fbi);
+
+	return l;
+}
+
+static ssize_t store_overlays_rotate(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	int num_ovls = 0, r, i;
+	int len;
+	bool changed = false;
+	u8 rotation[OMAPFB_MAX_OVL_PER_FB];
+
+	len = strlen(buf);
+	if (buf[len - 1] == '\n')
+		len = len - 1;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+
+	if (len > 0) {
+		char *p = (char *)buf;
+
+		while (p < buf + len) {
+			int rot;
+
+			if (num_ovls == ofbi->num_overlays) {
+				r = -EINVAL;
+				goto out;
+			}
+
+			rot = simple_strtoul(p, &p, 0);
+			if (rot < 0 || rot > 3) {
+				r = -EINVAL;
+				goto out;
+			}
+
+			if (ofbi->rotation[num_ovls] != rot)
+				changed = true;
+
+			rotation[num_ovls++] = rot;
+
+			p++;
+		}
+	}
+
+	if (num_ovls != ofbi->num_overlays) {
+		r = -EINVAL;
+		goto out;
+	}
+
+	if (changed) {
+		for (i = 0; i < num_ovls; ++i)
+			ofbi->rotation[i] = rotation[i];
+
+		omapfb_get_mem_region(ofbi->region);
+
+		r = omapfb_apply_changes(fbi, 0);
+
+		omapfb_put_mem_region(ofbi->region);
+
+		if (r)
+			goto out;
+
+		/* FIXME error handling? */
+	}
+
+	r = count;
+out:
+	unlock_fb_info(fbi);
+
+	return r;
+}
+
+static ssize_t show_size(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+
+	return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
+}
+
+static ssize_t store_size(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_dss_device *display = fb2display(fbi);
+	struct omapfb2_mem_region *rg;
+	unsigned long size;
+	int r;
+	int i;
+
+	r = kstrtoul(buf, 0, &size);
+	if (r)
+		return r;
+
+	size = PAGE_ALIGN(size);
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+
+	if (display && display->driver->sync)
+		display->driver->sync(display);
+
+	rg = ofbi->region;
+
+	down_write_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
+
+	if (atomic_read(&rg->map_count)) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
+		int j;
+
+		if (ofbi2->region != rg)
+			continue;
+
+		for (j = 0; j < ofbi2->num_overlays; j++) {
+			struct omap_overlay *ovl;
+			ovl = ofbi2->overlays[j];
+			if (ovl->is_enabled(ovl)) {
+				r = -EBUSY;
+				goto out;
+			}
+		}
+	}
+
+	if (size != ofbi->region->size) {
+		r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
+		if (r) {
+			dev_err(dev, "realloc fbmem failed\n");
+			goto out;
+		}
+	}
+
+	r = count;
+out:
+	atomic_dec(&rg->lock_count);
+	up_write(&rg->lock);
+
+	unlock_fb_info(fbi);
+
+	return r;
+}
+
+static ssize_t show_phys(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+
+	return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
+}
+
+static ssize_t show_virt(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+
+	return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
+}
+
+static ssize_t show_upd_mode(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	enum omapfb_update_mode mode;
+	int r;
+
+	r = omapfb_get_update_mode(fbi, &mode);
+
+	if (r)
+		return r;
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
+}
+
+static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	unsigned mode;
+	int r;
+
+	r = kstrtouint(buf, 0, &mode);
+	if (r)
+		return r;
+
+	r = omapfb_set_update_mode(fbi, mode);
+	if (r)
+		return r;
+
+	return count;
+}
+
+static struct device_attribute omapfb_attrs[] = {
+	__ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
+			store_rotate_type),
+	__ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+	__ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
+	__ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+	__ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
+			store_overlays_rotate),
+	__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+	__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+	__ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
+};
+
+int omapfb_create_sysfs(struct omapfb2_device *fbdev)
+{
+	int i;
+	int r;
+
+	DBG("create sysfs for fbs\n");
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		int t;
+		for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
+			r = device_create_file(fbdev->fbs[i]->dev,
+					&omapfb_attrs[t]);
+
+			if (r) {
+				dev_err(fbdev->dev, "failed to create sysfs "
+						"file\n");
+				return r;
+			}
+		}
+	}
+
+	return 0;
+}
+
+void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
+{
+	int i, t;
+
+	DBG("remove sysfs for fbs\n");
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
+			device_remove_file(fbdev->fbs[i]->dev,
+					&omapfb_attrs[t]);
+	}
+}
+
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb.h b/drivers/video/fbdev/omap2/omapfb/omapfb.h
new file mode 100644
index 000000000000..623cd872a367
--- /dev/null
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb.h
@@ -0,0 +1,208 @@
+/*
+ * linux/drivers/video/omap2/omapfb.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
+#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
+
+#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
+#define DEBUG
+#endif
+
+#include <linux/rwsem.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-mapping.h>
+
+#include <video/omapdss.h>
+
+#ifdef DEBUG
+extern bool omapfb_debug;
+#define DBG(format, ...) \
+	do { \
+		if (omapfb_debug) \
+			printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__); \
+	} while (0)
+#else
+#define DBG(format, ...)
+#endif
+
+#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
+
+/* max number of overlays to which a framebuffer data can be direct */
+#define OMAPFB_MAX_OVL_PER_FB 3
+
+struct omapfb2_mem_region {
+	int             id;
+	struct dma_attrs attrs;
+	void		*token;
+	dma_addr_t	dma_handle;
+	u32		paddr;
+	void __iomem	*vaddr;
+	struct vrfb	vrfb;
+	unsigned long	size;
+	u8		type;		/* OMAPFB_PLANE_MEM_* */
+	bool		alloc;		/* allocated by the driver */
+	bool		map;		/* kernel mapped by the driver */
+	atomic_t	map_count;
+	struct rw_semaphore lock;
+	atomic_t	lock_count;
+};
+
+/* appended to fb_info */
+struct omapfb_info {
+	int id;
+	struct omapfb2_mem_region *region;
+	int num_overlays;
+	struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
+	struct omapfb2_device *fbdev;
+	enum omap_dss_rotation_type rotation_type;
+	u8 rotation[OMAPFB_MAX_OVL_PER_FB];
+	bool mirror;
+};
+
+struct omapfb_display_data {
+	struct omapfb2_device *fbdev;
+	struct omap_dss_device *dssdev;
+	u8 bpp_override;
+	enum omapfb_update_mode update_mode;
+	bool auto_update_work_enabled;
+	struct delayed_work auto_update_work;
+};
+
+struct omapfb2_device {
+	struct device *dev;
+	struct mutex  mtx;
+
+	u32 pseudo_palette[17];
+
+	int state;
+
+	unsigned num_fbs;
+	struct fb_info *fbs[10];
+	struct omapfb2_mem_region regions[10];
+
+	unsigned num_displays;
+	struct omapfb_display_data displays[10];
+	unsigned num_overlays;
+	struct omap_overlay *overlays[10];
+	unsigned num_managers;
+	struct omap_overlay_manager *managers[10];
+
+	struct workqueue_struct *auto_update_wq;
+};
+
+struct omapfb_colormode {
+	enum omap_color_mode dssmode;
+	u32 bits_per_pixel;
+	u32 nonstd;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+};
+
+void set_fb_fix(struct fb_info *fbi);
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
+int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
+int omapfb_apply_changes(struct fb_info *fbi, int init);
+
+int omapfb_create_sysfs(struct omapfb2_device *fbdev);
+void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
+
+int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
+
+int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
+			struct fb_var_screeninfo *var);
+
+int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+		u16 posx, u16 posy, u16 outw, u16 outh);
+
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+		struct omap_dss_device *display);
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+		struct omap_dss_device *display);
+int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
+int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
+
+/* find the display connected to this fb, if any */
+static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omap_overlay *ovl;
+
+	/* XXX: returns the display connected to first attached overlay */
+
+	if (ofbi->num_overlays == 0)
+		return NULL;
+
+	ovl = ofbi->overlays[0];
+
+	return ovl->get_device(ovl);
+}
+
+static inline struct omapfb_display_data *get_display_data(
+		struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
+{
+	int i;
+
+	for (i = 0; i < fbdev->num_displays; ++i)
+		if (fbdev->displays[i].dssdev == dssdev)
+			return &fbdev->displays[i];
+
+	/* This should never happen */
+	BUG();
+	return NULL;
+}
+
+static inline void omapfb_lock(struct omapfb2_device *fbdev)
+{
+	mutex_lock(&fbdev->mtx);
+}
+
+static inline void omapfb_unlock(struct omapfb2_device *fbdev)
+{
+	mutex_unlock(&fbdev->mtx);
+}
+
+static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
+		int enable)
+{
+	if (enable)
+		return ovl->enable(ovl);
+	else
+		return ovl->disable(ovl);
+}
+
+static inline struct omapfb2_mem_region *
+omapfb_get_mem_region(struct omapfb2_mem_region *rg)
+{
+	down_read_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
+	return rg;
+}
+
+static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
+{
+	atomic_dec(&rg->lock_count);
+	up_read(&rg->lock);
+}
+
+#endif
diff --git a/drivers/video/fbdev/omap2/vrfb.c b/drivers/video/fbdev/omap2/vrfb.c
new file mode 100644
index 000000000000..f346b02eee1d
--- /dev/null
+++ b/drivers/video/fbdev/omap2/vrfb.c
@@ -0,0 +1,399 @@
+/*
+ * VRFB Rotation Engine
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*#define DEBUG*/
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <video/omapvrfb.h>
+
+#ifdef DEBUG
+#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define SMS_ROT_CONTROL(context)	(0x0 + 0x10 * context)
+#define SMS_ROT_SIZE(context)		(0x4 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context)	(0x8 + 0x10 * context)
+#define SMS_ROT_VIRT_BASE(rot)		(0x1000000 * (rot))
+
+#define OMAP_VRFB_SIZE			(2048 * 2048 * 4)
+
+#define VRFB_PAGE_WIDTH_EXP	5 /* Assuming SDRAM pagesize= 1024 */
+#define VRFB_PAGE_HEIGHT_EXP	5 /* 1024 = 2^5 * 2^5 */
+#define VRFB_PAGE_WIDTH		(1 << VRFB_PAGE_WIDTH_EXP)
+#define VRFB_PAGE_HEIGHT	(1 << VRFB_PAGE_HEIGHT_EXP)
+#define SMS_IMAGEHEIGHT_OFFSET	16
+#define SMS_IMAGEWIDTH_OFFSET	0
+#define SMS_PH_OFFSET		8
+#define SMS_PW_OFFSET		4
+#define SMS_PS_OFFSET		0
+
+/* bitmap of reserved contexts */
+static unsigned long ctx_map;
+
+struct vrfb_ctx {
+	u32 base;
+	u32 physical_ba;
+	u32 control;
+	u32 size;
+};
+
+static DEFINE_MUTEX(ctx_lock);
+
+/*
+ * Access to this happens from client drivers or the PM core after wake-up.
+ * For the first case we require locking at the driver level, for the second
+ * we don't need locking, since no drivers will run until after the wake-up
+ * has finished.
+ */
+
+static void __iomem *vrfb_base;
+
+static int num_ctxs;
+static struct vrfb_ctx *ctxs;
+
+static bool vrfb_loaded;
+
+static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
+}
+
+static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
+}
+
+static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
+}
+
+static inline void restore_hw_context(int ctx)
+{
+	omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
+	omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
+	omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
+}
+
+static u32 get_image_width_roundup(u16 width, u8 bytespp)
+{
+	unsigned long stride = width * bytespp;
+	unsigned long ceil_pages_per_stride = (stride / VRFB_PAGE_WIDTH) +
+		(stride % VRFB_PAGE_WIDTH != 0);
+
+	return ceil_pages_per_stride * VRFB_PAGE_WIDTH / bytespp;
+}
+
+/*
+ * This the extra space needed in the VRFB physical area for VRFB to safely wrap
+ * any memory accesses to the invisible part of the virtual view to the physical
+ * area.
+ */
+static inline u32 get_extra_physical_size(u16 image_width_roundup, u8 bytespp)
+{
+	return (OMAP_VRFB_LINE_LEN - image_width_roundup) * VRFB_PAGE_HEIGHT *
+		bytespp;
+}
+
+void omap_vrfb_restore_context(void)
+{
+	int i;
+	unsigned long map = ctx_map;
+
+	for (i = ffs(map); i; i = ffs(map)) {
+		/* i=1..32 */
+		i--;
+		map &= ~(1 << i);
+		restore_hw_context(i);
+	}
+}
+
+void omap_vrfb_adjust_size(u16 *width, u16 *height,
+		u8 bytespp)
+{
+	*width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
+	*height = ALIGN(*height, VRFB_PAGE_HEIGHT);
+}
+EXPORT_SYMBOL(omap_vrfb_adjust_size);
+
+u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
+{
+	unsigned long image_width_roundup = get_image_width_roundup(width,
+		bytespp);
+
+	if (image_width_roundup > OMAP_VRFB_LINE_LEN)
+		return 0;
+
+	return (width * height * bytespp) + get_extra_physical_size(
+		image_width_roundup, bytespp);
+}
+EXPORT_SYMBOL(omap_vrfb_min_phys_size);
+
+u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
+{
+	unsigned long image_width_roundup = get_image_width_roundup(width,
+		bytespp);
+	unsigned long height;
+	unsigned long extra;
+
+	if (image_width_roundup > OMAP_VRFB_LINE_LEN)
+		return 0;
+
+	extra = get_extra_physical_size(image_width_roundup, bytespp);
+
+	if (phys_size < extra)
+		return 0;
+
+	height = (phys_size - extra) / (width * bytespp);
+
+	/* Virtual views provided by VRFB are limited to 2048x2048. */
+	return min_t(unsigned long, height, 2048);
+}
+EXPORT_SYMBOL(omap_vrfb_max_height);
+
+void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+		u16 width, u16 height,
+		unsigned bytespp, bool yuv_mode)
+{
+	unsigned pixel_size_exp;
+	u16 vrfb_width;
+	u16 vrfb_height;
+	u8 ctx = vrfb->context;
+	u32 size;
+	u32 control;
+
+	DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d, %d)\n", ctx, paddr,
+			width, height, bytespp, yuv_mode);
+
+	/* For YUV2 and UYVY modes VRFB needs to handle pixels a bit
+	 * differently. See TRM. */
+	if (yuv_mode) {
+		bytespp *= 2;
+		width /= 2;
+	}
+
+	if (bytespp == 4)
+		pixel_size_exp = 2;
+	else if (bytespp == 2)
+		pixel_size_exp = 1;
+	else {
+		BUG();
+		return;
+	}
+
+	vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
+	vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
+
+	DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
+
+	size  = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
+	size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
+
+	control  = pixel_size_exp << SMS_PS_OFFSET;
+	control |= VRFB_PAGE_WIDTH_EXP  << SMS_PW_OFFSET;
+	control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
+
+	ctxs[ctx].physical_ba = paddr;
+	ctxs[ctx].size = size;
+	ctxs[ctx].control = control;
+
+	omap2_sms_write_rot_physical_ba(paddr, ctx);
+	omap2_sms_write_rot_size(size, ctx);
+	omap2_sms_write_rot_control(control, ctx);
+
+	DBG("vrfb offset pixels %d, %d\n",
+			vrfb_width - width, vrfb_height - height);
+
+	vrfb->xres = width;
+	vrfb->yres = height;
+	vrfb->xoffset = vrfb_width - width;
+	vrfb->yoffset = vrfb_height - height;
+	vrfb->bytespp = bytespp;
+	vrfb->yuv_mode = yuv_mode;
+}
+EXPORT_SYMBOL(omap_vrfb_setup);
+
+int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
+{
+	unsigned long size = height * OMAP_VRFB_LINE_LEN * vrfb->bytespp;
+
+	vrfb->vaddr[rot] = ioremap_wc(vrfb->paddr[rot], size);
+
+	if (!vrfb->vaddr[rot]) {
+		printk(KERN_ERR "vrfb: ioremap failed\n");
+		return -ENOMEM;
+	}
+
+	DBG("ioremapped vrfb area %d of size %lu into %p\n", rot, size,
+		vrfb->vaddr[rot]);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_vrfb_map_angle);
+
+void omap_vrfb_release_ctx(struct vrfb *vrfb)
+{
+	int rot;
+	int ctx = vrfb->context;
+
+	if (ctx == 0xff)
+		return;
+
+	DBG("release ctx %d\n", ctx);
+
+	mutex_lock(&ctx_lock);
+
+	BUG_ON(!(ctx_map & (1 << ctx)));
+
+	clear_bit(ctx, &ctx_map);
+
+	for (rot = 0; rot < 4; ++rot) {
+		if (vrfb->paddr[rot]) {
+			release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
+			vrfb->paddr[rot] = 0;
+		}
+	}
+
+	vrfb->context = 0xff;
+
+	mutex_unlock(&ctx_lock);
+}
+EXPORT_SYMBOL(omap_vrfb_release_ctx);
+
+int omap_vrfb_request_ctx(struct vrfb *vrfb)
+{
+	int rot;
+	u32 paddr;
+	u8 ctx;
+	int r;
+
+	DBG("request ctx\n");
+
+	mutex_lock(&ctx_lock);
+
+	for (ctx = 0; ctx < num_ctxs; ++ctx)
+		if ((ctx_map & (1 << ctx)) == 0)
+			break;
+
+	if (ctx == num_ctxs) {
+		pr_err("vrfb: no free contexts\n");
+		r = -EBUSY;
+		goto out;
+	}
+
+	DBG("found free ctx %d\n", ctx);
+
+	set_bit(ctx, &ctx_map);
+
+	memset(vrfb, 0, sizeof(*vrfb));
+
+	vrfb->context = ctx;
+
+	for (rot = 0; rot < 4; ++rot) {
+		paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
+		if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
+			pr_err("vrfb: failed to reserve VRFB "
+					"area for ctx %d, rotation %d\n",
+					ctx, rot * 90);
+			omap_vrfb_release_ctx(vrfb);
+			r = -ENOMEM;
+			goto out;
+		}
+
+		vrfb->paddr[rot] = paddr;
+
+		DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
+	}
+
+	r = 0;
+out:
+	mutex_unlock(&ctx_lock);
+	return r;
+}
+EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+bool omap_vrfb_supported(void)
+{
+	return vrfb_loaded;
+}
+EXPORT_SYMBOL(omap_vrfb_supported);
+
+static int __init vrfb_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int i;
+
+	/* first resource is the register res, the rest are vrfb contexts */
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	vrfb_base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(vrfb_base))
+		return PTR_ERR(vrfb_base);
+
+	num_ctxs = pdev->num_resources - 1;
+
+	ctxs = devm_kzalloc(&pdev->dev,
+			sizeof(struct vrfb_ctx) * num_ctxs,
+			GFP_KERNEL);
+
+	if (!ctxs)
+		return -ENOMEM;
+
+	for (i = 0; i < num_ctxs; ++i) {
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+		if (!mem) {
+			dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
+					i);
+			return -EINVAL;
+		}
+
+		ctxs[i].base = mem->start;
+	}
+
+	vrfb_loaded = true;
+
+	return 0;
+}
+
+static void __exit vrfb_remove(struct platform_device *pdev)
+{
+	vrfb_loaded = false;
+}
+
+static struct platform_driver vrfb_driver = {
+	.driver.name	= "omapvrfb",
+	.remove		= __exit_p(vrfb_remove),
+};
+
+module_platform_driver_probe(vrfb_driver, vrfb_probe);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("OMAP VRFB");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/p9100.c b/drivers/video/fbdev/p9100.c
new file mode 100644
index 000000000000..367cea8f43f3
--- /dev/null
+++ b/drivers/video/fbdev/p9100.c
@@ -0,0 +1,382 @@
+/* p9100.c: P9100 frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			   unsigned, struct fb_info *);
+static int p9100_blank(int, struct fb_info *);
+
+static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
+static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops p9100_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= p9100_setcolreg,
+	.fb_blank		= p9100_blank,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= p9100_mmap,
+	.fb_ioctl		= p9100_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+/* P9100 control registers */
+#define P9100_SYSCTL_OFF	0x0UL
+#define P9100_VIDEOCTL_OFF	0x100UL
+#define P9100_VRAMCTL_OFF 	0x180UL
+#define P9100_RAMDAC_OFF 	0x200UL
+#define P9100_VIDEOCOPROC_OFF 	0x400UL
+
+/* P9100 command registers */
+#define P9100_CMD_OFF 0x0UL
+
+/* P9100 framebuffer memory */
+#define P9100_FB_OFF 0x0UL
+
+/* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
+#define SYS_CONFIG_PIXELSIZE_SHIFT 26 
+
+#define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
+
+struct p9100_regs {
+	/* Registers for the system control */
+	u32 sys_base;
+	u32 sys_config;
+	u32 sys_intr;
+	u32 sys_int_ena;
+	u32 sys_alt_rd;
+	u32 sys_alt_wr;
+	u32 sys_xxx[58];
+
+	/* Registers for the video control */
+	u32 vid_base;
+	u32 vid_hcnt;
+	u32 vid_htotal;
+	u32 vid_hsync_rise;
+	u32 vid_hblank_rise;
+	u32 vid_hblank_fall;
+	u32 vid_hcnt_preload;
+	u32 vid_vcnt;
+	u32 vid_vlen;
+	u32 vid_vsync_rise;
+	u32 vid_vblank_rise;
+	u32 vid_vblank_fall;
+	u32 vid_vcnt_preload;
+	u32 vid_screenpaint_addr;
+	u32 vid_screenpaint_timectl1;
+	u32 vid_screenpaint_qsfcnt;
+	u32 vid_screenpaint_timectl2;
+	u32 vid_xxx[15];
+
+	/* Registers for the video control */
+	u32 vram_base;
+	u32 vram_memcfg;
+	u32 vram_refresh_pd;
+	u32 vram_refresh_cnt;
+	u32 vram_raslo_max;
+	u32 vram_raslo_cur;
+	u32 pwrup_cfg;
+	u32 vram_xxx[25];
+
+	/* Registers for IBM RGB528 Palette */
+	u32 ramdac_cmap_wridx; 
+	u32 ramdac_palette_data;
+	u32 ramdac_pixel_mask;
+	u32 ramdac_palette_rdaddr;
+	u32 ramdac_idx_lo;
+	u32 ramdac_idx_hi;
+	u32 ramdac_idx_data;
+	u32 ramdac_idx_ctl;
+	u32 ramdac_xxx[1784];
+};
+
+struct p9100_cmd_parameng {
+	u32 parameng_status;
+	u32 parameng_bltcmd;
+	u32 parameng_quadcmd;
+};
+
+struct p9100_par {
+	spinlock_t		lock;
+	struct p9100_regs	__iomem *regs;
+
+	u32			flags;
+#define P9100_FLAG_BLANKED	0x00000001
+
+	unsigned long		which_io;
+};
+
+/**
+ *      p9100_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int p9100_setcolreg(unsigned regno,
+			   unsigned red, unsigned green, unsigned blue,
+			   unsigned transp, struct fb_info *info)
+{
+	struct p9100_par *par = (struct p9100_par *) info->par;
+	struct p9100_regs __iomem *regs = par->regs;
+	unsigned long flags;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	sbus_writel((regno << 16), &regs->ramdac_cmap_wridx);
+	sbus_writel((red << 16), &regs->ramdac_palette_data);
+	sbus_writel((green << 16), &regs->ramdac_palette_data);
+	sbus_writel((blue << 16), &regs->ramdac_palette_data);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *      p9100_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+p9100_blank(int blank, struct fb_info *info)
+{
+	struct p9100_par *par = (struct p9100_par *) info->par;
+	struct p9100_regs __iomem *regs = par->regs;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		val = sbus_readl(&regs->vid_screenpaint_timectl1);
+		val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
+		sbus_writel(val, &regs->vid_screenpaint_timectl1);
+		par->flags &= ~P9100_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		val = sbus_readl(&regs->vid_screenpaint_timectl1);
+		val &= ~SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
+		sbus_writel(val, &regs->vid_screenpaint_timectl1);
+		par->flags |= P9100_FLAG_BLANKED;
+		break;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map p9100_mmap_map[] = {
+	{ CG3_MMAP_OFFSET,	0,		SBUS_MMAP_FBSIZE(1) },
+	{ 0,			0,		0		    }
+};
+
+static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct p9100_par *par = (struct p9100_par *)info->par;
+
+	return sbusfb_mmap_helper(p9100_mmap_map,
+				  info->fix.smem_start, info->fix.smem_len,
+				  par->which_io, vma);
+}
+
+static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	/* Make it look like a cg3. */
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN3COLOR, 8, info->fix.smem_len);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
+{
+	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = linebytes;
+
+	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
+}
+
+static int p9100_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct p9100_par *par;
+	int linebytes, err;
+
+	info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+
+	/* This is the framebuffer and the only resource apps can mmap.  */
+	info->fix.smem_start = op->resource[2].start;
+	par->which_io = op->resource[2].flags & IORESOURCE_BITS;
+
+	sbusfb_fill_var(&info->var, dp, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
+
+	linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
+	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
+
+	par->regs = of_ioremap(&op->resource[0], 0,
+			       sizeof(struct p9100_regs), "p9100 regs");
+	if (!par->regs)
+		goto out_release_fb;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &p9100_ops;
+	info->screen_base = of_ioremap(&op->resource[2], 0,
+				       info->fix.smem_len, "p9100 ram");
+	if (!info->screen_base)
+		goto out_unmap_regs;
+
+	p9100_blank(FB_BLANK_UNBLANK, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_screen;
+
+	p9100_init_fix(info, linebytes, dp);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	fb_set_cmap(&info->cmap, info);
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: p9100 at %lx:%lx\n",
+	       dp->full_name,
+	       par->which_io, info->fix.smem_start);
+
+	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_screen:
+	of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
+
+out_unmap_regs:
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
+
+out_release_fb:
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int p9100_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct p9100_par *par = info->par;
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
+	of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id p9100_match[] = {
+	{
+		.name = "p9100",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, p9100_match);
+
+static struct platform_driver p9100_driver = {
+	.driver = {
+		.name = "p9100",
+		.owner = THIS_MODULE,
+		.of_match_table = p9100_match,
+	},
+	.probe		= p9100_probe,
+	.remove		= p9100_remove,
+};
+
+static int __init p9100_init(void)
+{
+	if (fb_get_options("p9100fb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&p9100_driver);
+}
+
+static void __exit p9100_exit(void)
+{
+	platform_driver_unregister(&p9100_driver);
+}
+
+module_init(p9100_init);
+module_exit(p9100_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/platinumfb.c b/drivers/video/fbdev/platinumfb.c
new file mode 100644
index 000000000000..4c9299576827
--- /dev/null
+++ b/drivers/video/fbdev/platinumfb.c
@@ -0,0 +1,714 @@
+/*
+ *  platinumfb.c -- frame buffer device for the PowerMac 'platinum' display
+ *
+ *  Copyright (C) 1998 Franz Sirl
+ *
+ *  Frame buffer structure from:
+ *    drivers/video/controlfb.c -- frame buffer device for
+ *    Apple 'control' display chip.
+ *    Copyright (C) 1998 Dan Jacobowitz
+ *
+ *  Hardware information from:
+ *    platinum.c: Console support for PowerMac "platinum" display adaptor.
+ *    Copyright (C) 1996 Paul Mackerras and Mark Abene
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/nvram.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pgtable.h>
+
+#include "macmodes.h"
+#include "platinumfb.h"
+
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+
+struct fb_info_platinum {
+	struct fb_info			*info;
+
+	int				vmode, cmode;
+	int				xres, yres;
+	int				vxres, vyres;
+	int				xoffset, yoffset;
+
+	struct {
+		__u8 red, green, blue;
+	}				palette[256];
+	u32				pseudo_palette[16];
+	
+	volatile struct cmap_regs	__iomem *cmap_regs;
+	unsigned long			cmap_regs_phys;
+	
+	volatile struct platinum_regs	__iomem *platinum_regs;
+	unsigned long			platinum_regs_phys;
+	
+	__u8				__iomem *frame_buffer;
+	volatile __u8			__iomem *base_frame_buffer;
+	unsigned long			frame_buffer_phys;
+	
+	unsigned long			total_vram;
+	int				clktype;
+	int				dactype;
+
+	struct resource			rsrc_fb, rsrc_reg;
+};
+
+/*
+ * Frame buffer device API
+ */
+
+static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+	u_int transp, struct fb_info *info);
+static int platinumfb_blank(int blank_mode, struct fb_info *info);
+static int platinumfb_set_par (struct fb_info *info);
+static int platinumfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
+
+/*
+ * internal functions
+ */
+
+static inline int platinum_vram_reqd(int video_mode, int color_mode);
+static int read_platinum_sense(struct fb_info_platinum *pinfo);
+static void set_platinum_clock(struct fb_info_platinum *pinfo);
+static void platinum_set_hardware(struct fb_info_platinum *pinfo);
+static int platinum_var_to_par(struct fb_var_screeninfo *var,
+			       struct fb_info_platinum *pinfo,
+			       int check_only);
+
+/*
+ * Interface used by the world
+ */
+
+static struct fb_ops platinumfb_ops = {
+	.owner =	THIS_MODULE,
+	.fb_check_var	= platinumfb_check_var,
+	.fb_set_par	= platinumfb_set_par,
+	.fb_setcolreg	= platinumfb_setcolreg,
+	.fb_blank	= platinumfb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/*
+ * Checks a var structure
+ */
+static int platinumfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	return platinum_var_to_par(var, info->par, 1);
+}
+
+/*
+ * Applies current var to display
+ */
+static int platinumfb_set_par (struct fb_info *info)
+{
+	struct fb_info_platinum *pinfo = info->par;
+	struct platinum_regvals *init;
+	int err, offset = 0x20;
+
+	if((err = platinum_var_to_par(&info->var, pinfo, 0))) {
+		printk (KERN_ERR "platinumfb_set_par: error calling"
+				 " platinum_var_to_par: %d.\n", err);
+		return err;
+	}
+
+	platinum_set_hardware(pinfo);
+
+	init = platinum_reg_init[pinfo->vmode-1];
+	
+ 	if ((pinfo->vmode == VMODE_832_624_75) && (pinfo->cmode > CMODE_8))
+  		offset = 0x10;
+
+	info->screen_base = pinfo->frame_buffer + init->fb_offset + offset;
+	mutex_lock(&info->mm_lock);
+	info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
+	mutex_unlock(&info->mm_lock);
+	info->fix.visual = (pinfo->cmode == CMODE_8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+ 	info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode)
+		+ offset;
+	printk("line_length: %x\n", info->fix.line_length);
+	return 0;
+}
+
+static int platinumfb_blank(int blank,  struct fb_info *fb)
+{
+/*
+ *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+ *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+ *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+ *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+ *  and powerdown modes on hardware that supports disabling hsync/vsync:
+ *    blank_mode == 2: suspend vsync
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ */
+/* [danj] I think there's something fishy about those constants... */
+/*
+	struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
+	int	ctrl;
+
+	ctrl = ld_le32(&info->platinum_regs->ctrl.r) | 0x33;
+	if (blank)
+		--blank_mode;
+	if (blank & VESA_VSYNC_SUSPEND)
+		ctrl &= ~3;
+	if (blank & VESA_HSYNC_SUSPEND)
+		ctrl &= ~0x30;
+	out_le32(&info->platinum_regs->ctrl.r, ctrl);
+*/
+/* TODO: Figure out how the heck to powerdown this thing! */
+	return 0;
+}
+
+static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			      u_int transp, struct fb_info *info)
+{
+	struct fb_info_platinum *pinfo = info->par;
+	volatile struct cmap_regs __iomem *cmap_regs = pinfo->cmap_regs;
+
+	if (regno > 255)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	pinfo->palette[regno].red = red;
+	pinfo->palette[regno].green = green;
+	pinfo->palette[regno].blue = blue;
+
+	out_8(&cmap_regs->addr, regno);		/* tell clut what addr to fill	*/
+	out_8(&cmap_regs->lut, red);		/* send one color channel at	*/
+	out_8(&cmap_regs->lut, green);		/* a time...			*/
+	out_8(&cmap_regs->lut, blue);
+
+	if (regno < 16) {
+		int i;
+		u32 *pal = info->pseudo_palette;
+		switch (pinfo->cmode) {
+		case CMODE_16:
+			pal[regno] = (regno << 10) | (regno << 5) | regno;
+			break;
+		case CMODE_32:
+			i = (regno << 8) | regno;
+			pal[regno] = (i << 16) | i;
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+static inline int platinum_vram_reqd(int video_mode, int color_mode)
+{
+	int baseval = vmode_attrs[video_mode-1].hres * (1<<color_mode);
+
+	if ((video_mode == VMODE_832_624_75) && (color_mode > CMODE_8))
+		baseval += 0x10;
+	else
+		baseval += 0x20;
+
+	return vmode_attrs[video_mode-1].vres * baseval + 0x1000;
+}
+
+#define STORE_D2(a, d) { \
+	out_8(&cmap_regs->addr, (a+32)); \
+	out_8(&cmap_regs->d2, (d)); \
+}
+
+static void set_platinum_clock(struct fb_info_platinum *pinfo)
+{
+	volatile struct cmap_regs __iomem *cmap_regs = pinfo->cmap_regs;
+	struct platinum_regvals	*init;
+
+	init = platinum_reg_init[pinfo->vmode-1];
+
+	STORE_D2(6, 0xc6);
+	out_8(&cmap_regs->addr,3+32);
+
+	if (in_8(&cmap_regs->d2) == 2) {
+		STORE_D2(7, init->clock_params[pinfo->clktype][0]);
+		STORE_D2(8, init->clock_params[pinfo->clktype][1]);
+		STORE_D2(3, 3);
+	} else {
+		STORE_D2(4, init->clock_params[pinfo->clktype][0]);
+		STORE_D2(5, init->clock_params[pinfo->clktype][1]);
+		STORE_D2(3, 2);
+	}
+
+	__delay(5000);
+	STORE_D2(9, 0xa6);
+}
+
+
+/* Now how about actually saying, Make it so! */
+/* Some things in here probably don't need to be done each time. */
+static void platinum_set_hardware(struct fb_info_platinum *pinfo)
+{
+	volatile struct platinum_regs	__iomem *platinum_regs = pinfo->platinum_regs;
+	volatile struct cmap_regs	__iomem *cmap_regs = pinfo->cmap_regs;
+	struct platinum_regvals		*init;
+	int				i;
+	int				vmode, cmode;
+	
+	vmode = pinfo->vmode;
+	cmode = pinfo->cmode;
+
+	init = platinum_reg_init[vmode - 1];
+
+	/* Initialize display timing registers */
+	out_be32(&platinum_regs->reg[24].r, 7);	/* turn display off */
+
+	for (i = 0; i < 26; ++i)
+		out_be32(&platinum_regs->reg[i+32].r, init->regs[i]);
+
+	out_be32(&platinum_regs->reg[26+32].r, (pinfo->total_vram == 0x100000 ?
+						init->offset[cmode] + 4 - cmode :
+						init->offset[cmode]));
+	out_be32(&platinum_regs->reg[16].r, (unsigned) pinfo->frame_buffer_phys+init->fb_offset+0x10);
+	out_be32(&platinum_regs->reg[18].r, init->pitch[cmode]);
+	out_be32(&platinum_regs->reg[19].r, (pinfo->total_vram == 0x100000 ?
+					     init->mode[cmode+1] :
+					     init->mode[cmode]));
+	out_be32(&platinum_regs->reg[20].r, (pinfo->total_vram == 0x100000 ? 0x11 : 0x1011));
+	out_be32(&platinum_regs->reg[21].r, 0x100);
+	out_be32(&platinum_regs->reg[22].r, 1);
+	out_be32(&platinum_regs->reg[23].r, 1);
+	out_be32(&platinum_regs->reg[26].r, 0xc00);
+	out_be32(&platinum_regs->reg[27].r, 0x235);
+	/* out_be32(&platinum_regs->reg[27].r, 0x2aa); */
+
+	STORE_D2(0, (pinfo->total_vram == 0x100000 ?
+		     init->dacula_ctrl[cmode] & 0xf :
+		     init->dacula_ctrl[cmode]));
+	STORE_D2(1, 4);
+	STORE_D2(2, 0);
+
+	set_platinum_clock(pinfo);
+
+	out_be32(&platinum_regs->reg[24].r, 0);	/* turn display on */
+}
+
+/*
+ * Set misc info vars for this driver
+ */
+static void platinum_init_info(struct fb_info *info,
+			       struct fb_info_platinum *pinfo)
+{
+	/* Fill fb_info */
+	info->fbops = &platinumfb_ops;
+	info->pseudo_palette = pinfo->pseudo_palette;
+        info->flags = FBINFO_DEFAULT;
+	info->screen_base = pinfo->frame_buffer + 0x20;
+
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	/* Fill fix common fields */
+	strcpy(info->fix.id, "platinum");
+	info->fix.mmio_start = pinfo->platinum_regs_phys;
+	info->fix.mmio_len = 0x1000;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.smem_start = pinfo->frame_buffer_phys + 0x20; /* will be updated later */
+	info->fix.smem_len = pinfo->total_vram - 0x20;
+        info->fix.ywrapstep = 0;
+	info->fix.xpanstep = 0;
+	info->fix.ypanstep = 0;
+        info->fix.type_aux = 0;
+        info->fix.accel = FB_ACCEL_NONE;
+}
+
+
+static int platinum_init_fb(struct fb_info *info)
+{
+	struct fb_info_platinum *pinfo = info->par;
+	struct fb_var_screeninfo var;
+	int sense, rc;
+
+	sense = read_platinum_sense(pinfo);
+	printk(KERN_INFO "platinumfb: Monitor sense value = 0x%x, ", sense);
+	if (default_vmode == VMODE_NVRAM) {
+#ifdef CONFIG_NVRAM
+		default_vmode = nvram_read_byte(NV_VMODE);
+		if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
+		    !platinum_reg_init[default_vmode-1])
+#endif
+			default_vmode = VMODE_CHOOSE;
+	}
+	if (default_vmode == VMODE_CHOOSE) {
+		default_vmode = mac_map_monitor_sense(sense);
+	}
+	if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+		default_vmode = VMODE_640_480_60;
+#ifdef CONFIG_NVRAM
+	if (default_cmode == CMODE_NVRAM)
+		default_cmode = nvram_read_byte(NV_CMODE);
+#endif
+	if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+		default_cmode = CMODE_8;
+	/*
+	 * Reduce the pixel size if we don't have enough VRAM.
+	 */
+	while(default_cmode > CMODE_8 &&
+	      platinum_vram_reqd(default_vmode, default_cmode) > pinfo->total_vram)
+		default_cmode--;
+
+	printk("platinumfb:  Using video mode %d and color mode %d.\n", default_vmode, default_cmode);
+
+	/* Setup default var */
+	if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) {
+		/* This shouldn't happen! */
+		printk("mac_vmode_to_var(%d, %d,) failed\n", default_vmode, default_cmode);
+try_again:
+		default_vmode = VMODE_640_480_60;
+		default_cmode = CMODE_8;
+		if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) {
+			printk(KERN_ERR "platinumfb: mac_vmode_to_var() failed\n");
+			return -ENXIO;
+		}
+	}
+
+	/* Initialize info structure */
+	platinum_init_info(info, pinfo);
+
+	/* Apply default var */
+	info->var = var;
+	var.activate = FB_ACTIVATE_NOW;
+	rc = fb_set_var(info, &var);
+	if (rc && (default_vmode != VMODE_640_480_60 || default_cmode != CMODE_8))
+		goto try_again;
+
+	/* Register with fbdev layer */
+	rc = register_framebuffer(info);
+	if (rc < 0)
+		return rc;
+
+	fb_info(info, "Apple Platinum frame buffer device\n");
+
+	return 0;
+}
+
+/*
+ * Get the monitor sense value.
+ * Note that this can be called before calibrate_delay,
+ * so we can't use udelay.
+ */
+static int read_platinum_sense(struct fb_info_platinum *info)
+{
+	volatile struct platinum_regs __iomem *platinum_regs = info->platinum_regs;
+	int sense;
+
+	out_be32(&platinum_regs->reg[23].r, 7);	/* turn off drivers */
+	__delay(2000);
+	sense = (~in_be32(&platinum_regs->reg[23].r) & 7) << 8;
+
+	/* drive each sense line low in turn and collect the other 2 */
+	out_be32(&platinum_regs->reg[23].r, 3);	/* drive A low */
+	__delay(2000);
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 3) << 4;
+	out_be32(&platinum_regs->reg[23].r, 5);	/* drive B low */
+	__delay(2000);
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 4) << 1;
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 1) << 2;
+	out_be32(&platinum_regs->reg[23].r, 6);	/* drive C low */
+	__delay(2000);
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 6) >> 1;
+
+	out_be32(&platinum_regs->reg[23].r, 7);	/* turn off drivers */
+
+	return sense;
+}
+
+/*
+ * This routine takes a user-supplied var, and picks the best vmode/cmode from it.
+ * It also updates the var structure to the actual mode data obtained
+ */
+static int platinum_var_to_par(struct fb_var_screeninfo *var, 
+			       struct fb_info_platinum *pinfo,
+			       int check_only)
+{
+	int vmode, cmode;
+
+	if (mac_var_to_vmode(var, &vmode, &cmode) != 0) {
+		printk(KERN_ERR "platinum_var_to_par: mac_var_to_vmode unsuccessful.\n");
+		printk(KERN_ERR "platinum_var_to_par: var->xres = %d\n", var->xres);
+		printk(KERN_ERR "platinum_var_to_par: var->yres = %d\n", var->yres);
+		printk(KERN_ERR "platinum_var_to_par: var->xres_virtual = %d\n", var->xres_virtual);
+		printk(KERN_ERR "platinum_var_to_par: var->yres_virtual = %d\n", var->yres_virtual);
+		printk(KERN_ERR "platinum_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel);
+		printk(KERN_ERR "platinum_var_to_par: var->pixclock = %d\n", var->pixclock);
+		printk(KERN_ERR "platinum_var_to_par: var->vmode = %d\n", var->vmode);
+		return -EINVAL;
+	}
+
+	if (!platinum_reg_init[vmode-1]) {
+		printk(KERN_ERR "platinum_var_to_par, vmode %d not valid.\n", vmode);
+		return -EINVAL;
+	}
+
+	if (platinum_vram_reqd(vmode, cmode) > pinfo->total_vram) {
+		printk(KERN_ERR "platinum_var_to_par, not enough ram for vmode %d, cmode %d.\n", vmode, cmode);
+		return -EINVAL;
+	}
+
+	if (mac_vmode_to_var(vmode, cmode, var))
+		return -EINVAL;
+
+	if (check_only)
+		return 0;
+
+	pinfo->vmode = vmode;
+	pinfo->cmode = cmode;
+	pinfo->xres = vmode_attrs[vmode-1].hres;
+	pinfo->yres = vmode_attrs[vmode-1].vres;
+	pinfo->xoffset = 0;
+	pinfo->yoffset = 0;
+	pinfo->vxres = pinfo->xres;
+	pinfo->vyres = pinfo->yres;
+	
+	return 0;
+}
+
+
+/* 
+ * Parse user specified options (`video=platinumfb:')
+ */
+static int __init platinumfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "vmode:", 6)) {
+	    		int vmode = simple_strtoul(this_opt+6, NULL, 0);
+			if (vmode > 0 && vmode <= VMODE_MAX)
+				default_vmode = vmode;
+		} else if (!strncmp(this_opt, "cmode:", 6)) {
+			int depth = simple_strtoul(this_opt+6, NULL, 0);
+			switch (depth) {
+			 case 0:
+			 case 8:
+			    default_cmode = CMODE_8;
+			    break;
+			 case 15:
+			 case 16:
+			    default_cmode = CMODE_16;
+			    break;
+			 case 24:
+			 case 32:
+			    default_cmode = CMODE_32;
+			    break;
+			}
+		}
+	}
+	return 0;
+}
+
+#ifdef __powerpc__
+#define invalidate_cache(addr) \
+	asm volatile("eieio; dcbf 0,%1" \
+	: "=m" (*(addr)) : "r" (addr) : "memory");
+#else
+#define invalidate_cache(addr)
+#endif
+
+static int platinumfb_probe(struct platform_device* odev)
+{
+	struct device_node	*dp = odev->dev.of_node;
+	struct fb_info		*info;
+	struct fb_info_platinum	*pinfo;
+	volatile __u8		*fbuffer;
+	int			bank0, bank1, bank2, bank3, rc;
+
+	dev_info(&odev->dev, "Found Apple Platinum video hardware\n");
+
+	info = framebuffer_alloc(sizeof(*pinfo), &odev->dev);
+	if (info == NULL) {
+		dev_err(&odev->dev, "Failed to allocate fbdev !\n");
+		return -ENOMEM;
+	}
+	pinfo = info->par;
+
+	if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) ||
+	    of_address_to_resource(dp, 1, &pinfo->rsrc_fb)) {
+		dev_err(&odev->dev, "Can't get resources\n");
+		framebuffer_release(info);
+		return -ENXIO;
+	}
+	dev_dbg(&odev->dev, " registers  : 0x%llx...0x%llx\n",
+		(unsigned long long)pinfo->rsrc_reg.start,
+		(unsigned long long)pinfo->rsrc_reg.end);
+	dev_dbg(&odev->dev, " framebuffer: 0x%llx...0x%llx\n",
+		(unsigned long long)pinfo->rsrc_fb.start,
+		(unsigned long long)pinfo->rsrc_fb.end);
+
+	/* Do not try to request register space, they overlap with the
+	 * northbridge and that can fail. Only request framebuffer
+	 */
+	if (!request_mem_region(pinfo->rsrc_fb.start,
+				resource_size(&pinfo->rsrc_fb),
+				"platinumfb framebuffer")) {
+		printk(KERN_ERR "platinumfb: Can't request framebuffer !\n");
+		framebuffer_release(info);
+		return -ENXIO;
+	}
+
+	/* frame buffer - map only 4MB */
+	pinfo->frame_buffer_phys = pinfo->rsrc_fb.start;
+	pinfo->frame_buffer = __ioremap(pinfo->rsrc_fb.start, 0x400000,
+					_PAGE_WRITETHRU);
+	pinfo->base_frame_buffer = pinfo->frame_buffer;
+
+	/* registers */
+	pinfo->platinum_regs_phys = pinfo->rsrc_reg.start;
+	pinfo->platinum_regs = ioremap(pinfo->rsrc_reg.start, 0x1000);
+
+	pinfo->cmap_regs_phys = 0xf301b000;	/* XXX not in prom? */
+	request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap");
+	pinfo->cmap_regs = ioremap(pinfo->cmap_regs_phys, 0x1000);
+
+	/* Grok total video ram */
+	out_be32(&pinfo->platinum_regs->reg[16].r, (unsigned)pinfo->frame_buffer_phys);
+	out_be32(&pinfo->platinum_regs->reg[20].r, 0x1011);	/* select max vram */
+	out_be32(&pinfo->platinum_regs->reg[24].r, 0);	/* switch in vram */
+
+	fbuffer = pinfo->base_frame_buffer;
+	fbuffer[0x100000] = 0x34;
+	fbuffer[0x100008] = 0x0;
+	invalidate_cache(&fbuffer[0x100000]);
+	fbuffer[0x200000] = 0x56;
+	fbuffer[0x200008] = 0x0;
+	invalidate_cache(&fbuffer[0x200000]);
+	fbuffer[0x300000] = 0x78;
+	fbuffer[0x300008] = 0x0;
+	invalidate_cache(&fbuffer[0x300000]);
+	bank0 = 1; /* builtin 1MB vram, always there */
+	bank1 = fbuffer[0x100000] == 0x34;
+	bank2 = fbuffer[0x200000] == 0x56;
+	bank3 = fbuffer[0x300000] == 0x78;
+	pinfo->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
+	printk(KERN_INFO "platinumfb: Total VRAM = %dMB (%d%d%d%d)\n",
+	       (unsigned int) (pinfo->total_vram / 1024 / 1024),
+	       bank3, bank2, bank1, bank0);
+
+	/*
+	 * Try to determine whether we have an old or a new DACula.
+	 */
+	out_8(&pinfo->cmap_regs->addr, 0x40);
+	pinfo->dactype = in_8(&pinfo->cmap_regs->d2);
+	switch (pinfo->dactype) {
+	case 0x3c:
+		pinfo->clktype = 1;
+		printk(KERN_INFO "platinumfb: DACula type 0x3c\n");
+		break;
+	case 0x84:
+		pinfo->clktype = 0;
+		printk(KERN_INFO "platinumfb: DACula type 0x84\n");
+		break;
+	default:
+		pinfo->clktype = 0;
+		printk(KERN_INFO "platinumfb: Unknown DACula type: %x\n", pinfo->dactype);
+		break;
+	}
+	dev_set_drvdata(&odev->dev, info);
+	
+	rc = platinum_init_fb(info);
+	if (rc != 0) {
+		iounmap(pinfo->frame_buffer);
+		iounmap(pinfo->platinum_regs);
+		iounmap(pinfo->cmap_regs);
+		framebuffer_release(info);
+	}
+
+	return rc;
+}
+
+static int platinumfb_remove(struct platform_device* odev)
+{
+	struct fb_info		*info = dev_get_drvdata(&odev->dev);
+	struct fb_info_platinum	*pinfo = info->par;
+	
+        unregister_framebuffer (info);
+	
+	/* Unmap frame buffer and registers */
+	iounmap(pinfo->frame_buffer);
+	iounmap(pinfo->platinum_regs);
+	iounmap(pinfo->cmap_regs);
+
+	release_mem_region(pinfo->rsrc_fb.start,
+			   resource_size(&pinfo->rsrc_fb));
+
+	release_mem_region(pinfo->cmap_regs_phys, 0x1000);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct of_device_id platinumfb_match[] = 
+{
+	{
+	.name 		= "platinum",
+	},
+	{},
+};
+
+static struct platform_driver platinum_driver = 
+{
+	.driver = {
+		.name = "platinumfb",
+		.owner = THIS_MODULE,
+		.of_match_table = platinumfb_match,
+	},
+	.probe		= platinumfb_probe,
+	.remove		= platinumfb_remove,
+};
+
+static int __init platinumfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("platinumfb", &option))
+		return -ENODEV;
+	platinumfb_setup(option);
+#endif
+	platform_driver_register(&platinum_driver);
+
+	return 0;
+}
+
+static void __exit platinumfb_exit(void)
+{
+	platform_driver_unregister(&platinum_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("framebuffer driver for Apple Platinum video");
+module_init(platinumfb_init);
+
+#ifdef MODULE
+module_exit(platinumfb_exit);
+#endif
diff --git a/drivers/video/fbdev/platinumfb.h b/drivers/video/fbdev/platinumfb.h
new file mode 100644
index 000000000000..f6bd77cafd17
--- /dev/null
+++ b/drivers/video/fbdev/platinumfb.h
@@ -0,0 +1,368 @@
+/*
+ * linux/drivers/video/platinumfb-hw.c -- Frame buffer device for the
+ * Platinum on-board video in PowerMac 7200s (and some clones based
+ * on the same motherboard.)
+ *
+ *  Created 09 Feb 1998 by Jon Howell <jonh@cs.dartmouth.edu>
+ *
+ * Copyright (C) 1998 Jon Howell
+ *
+ *  based on drivers/macintosh/platinum.c: Console support
+ * 	for PowerMac "platinum" display adaptor.
+ *  Copyright (C) 1996 Paul Mackerras and Mark Abene.
+ *
+ *  based on skeletonfb.c:
+ *  Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Structure of the registers for the DACula colormap device.
+ */
+struct cmap_regs {
+	unsigned char addr;
+	char pad1[15];
+	unsigned char d1;
+	char pad2[15];
+	unsigned char d2;
+	char pad3[15];
+	unsigned char lut;
+	char pad4[15];
+};
+
+/*
+ * Structure of the registers for the "platinum" display adaptor".
+ */
+struct preg {			/* padded register */
+	unsigned r;			/* notice this is 32 bits. */
+	char pad[12];
+};
+
+struct platinum_regs {
+	struct preg reg[128];
+};
+
+/*
+ * Register initialization tables for the platinum display.
+ *
+ * It seems that there are two different types of platinum display
+ * out there.  Older ones use the values in clocksel[1], for which
+ * the formula for the clock frequency seems to be
+ *	F = 14.3MHz * c0 / (c1 & 0x1f) / (1 << (c1 >> 5))
+ * Newer ones use the values in clocksel[0], for which the formula
+ * seems to be
+ *	F = 15MHz * c0 / ((c1 & 0x1f) + 2) / (1 << (c1 >> 5))
+ */
+struct platinum_regvals {
+	int	fb_offset;
+	int	pitch[3];
+	unsigned regs[26];
+	unsigned char offset[3];
+	unsigned char mode[3];
+	unsigned char dacula_ctrl[3];
+	unsigned char clock_params[2][2];
+};
+
+#define DIV2	0x20
+#define DIV4	0x40
+#define DIV8	0x60
+#define DIV16	0x80
+
+/* 1280x1024, 75Hz (20) */
+static struct platinum_regvals platinum_reg_init_20 = {
+	0x5c00,
+	{ 1312, 2592, 2592 },
+	{ 0xffc, 4, 0, 0, 0, 0, 0x428, 0,
+	  0, 0xb3, 0xd3, 0x12, 0x1a5, 0x23, 0x28, 0x2d,
+	  0x5e, 0x19e, 0x1a4, 0x854, 0x852, 4, 9, 0x50,
+	  0x850, 0x851 }, { 0x58, 0x5d, 0x5d },
+	{ 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 },
+	{{ 45, 3 }, { 66, 7 }}
+};
+
+/* 1280x960, 75Hz (19) */
+static struct platinum_regvals platinum_reg_init_19 = {
+	0x5c00,
+	{ 1312, 2592, 2592 },
+	{ 0xffc, 4, 0, 0, 0, 0, 0x428, 0,
+	  0, 0xb2, 0xd2, 0x12, 0x1a3, 0x23, 0x28, 0x2d,
+	  0x5c, 0x19c, 0x1a2, 0x7d0, 0x7ce, 4, 9, 0x4c,
+	  0x7cc, 0x7cd }, { 0x56, 0x5b, 0x5b },
+	{ 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 },
+	{{ 42, 3 }, { 44, 5 }}
+};
+
+/* 1152x870, 75Hz (18) */
+static struct platinum_regvals platinum_reg_init_18 = {
+	0x11b0,
+	{ 1184, 2336, 4640 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x38f, 0,
+	  0, 0x294, 0x16c, 0x20, 0x2d7, 0x3f, 0x49, 0x53,
+	  0x82, 0x2c2, 0x2d6, 0x726, 0x724, 4, 9, 0x52,
+	  0x71e, 0x722 }, { 0x74, 0x7c, 0x81 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 26, 0 + DIV2 }, { 42, 6 }}
+};
+
+/* 1024x768, 75Hz (17) */
+static struct platinum_regvals platinum_reg_init_17 = {
+	0x10b0,
+	{ 1056, 2080, 4128 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x254, 0x14b, 0x18, 0x295, 0x2f, 0x32, 0x3b,
+	  0x80, 0x280, 0x296, 0x648, 0x646, 4, 9, 0x40,
+	  0x640, 0x644 }, { 0x72, 0x7a, 0x7f },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 54, 3 + DIV2 }, { 67, 12 }}
+};
+
+/* 1024x768, 75Hz (16) */
+static struct platinum_regvals platinum_reg_init_16 = {
+	0x10b0,
+	{ 1056, 2080, 4128 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x250, 0x147, 0x17, 0x28f, 0x2f, 0x35, 0x47,
+	  0x82, 0x282, 0x28e, 0x640, 0x63e, 4, 9, 0x3c,
+	  0x63c, 0x63d }, { 0x74, 0x7c, 0x81 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 20, 0 + DIV2 }, { 11, 2 }}
+};
+
+/* 1024x768, 70Hz (15) */
+static struct platinum_regvals platinum_reg_init_15 = {
+	0x10b0,
+	{ 1056, 2080, 4128 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x254, 0x14b, 0x22, 0x297, 0x43, 0x49, 0x5b,
+	  0x86, 0x286, 0x296, 0x64c, 0x64a, 0xa, 0xf, 0x44,
+	  0x644, 0x646 }, { 0x78, 0x80, 0x85 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 19, 0 + DIV2 }, { 110, 21 }}
+};
+
+/* 1024x768, 60Hz (14) */
+static struct platinum_regvals platinum_reg_init_14 = {
+	0x10b0,
+	{ 1056, 2080, 4128 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x25a, 0x14f, 0x22, 0x29f, 0x43, 0x49, 0x5b,
+	  0x8e, 0x28e, 0x29e, 0x64c, 0x64a, 0xa, 0xf, 0x44,
+	  0x644, 0x646 }, { 0x80, 0x88, 0x8d },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 71, 6 + DIV2 }, { 118, 13 + DIV2 }}
+};
+
+/* 832x624, 75Hz (13) */
+static struct platinum_regvals platinum_reg_init_13 = {
+	0x70,
+	{ 864, 1680, 3344 },	/* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB,
+				 * and we use 3344 instead of 3360 to fit in 2Mb
+				 */
+	{ 0xff0, 4, 0, 0, 0, 0, 0x299, 0,
+	  0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37,
+	  0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52,
+	  0x532, 0x533 }, { 0x7c, 0x84, 0x89 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }}
+};
+
+/* 800x600, 75Hz (12) */
+static struct platinum_regvals platinum_reg_init_12 = {
+	0x1010,
+	{ 832, 1632, 3232 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x1ce, 0x108, 0x14, 0x20f, 0x27, 0x30, 0x39,
+	  0x72, 0x202, 0x20e, 0x4e2, 0x4e0, 4, 9, 0x2e,
+	  0x4de, 0x4df }, { 0x64, 0x6c, 0x71 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 122, 7 + DIV4 }, { 62, 9 + DIV2 }}
+};
+
+/* 800x600, 72Hz (11) */
+static struct platinum_regvals platinum_reg_init_11 = {
+	0x1010,
+	{ 832, 1632, 3232 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x1ca, 0x104, 0x1e, 0x207, 0x3b, 0x44, 0x4d,
+	  0x56, 0x1e6, 0x206, 0x534, 0x532, 0xa, 0xe, 0x38,
+	  0x4e8, 0x4ec }, { 0x48, 0x50, 0x55 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 26, 0 + DIV4 }, { 42, 6 + DIV2 }}
+};
+
+/* 800x600, 60Hz (10) */
+static struct platinum_regvals platinum_reg_init_10 = {
+	0x1010,
+	{ 832, 1632, 3232 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d,
+	  0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34,
+	  0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 54, 3 + DIV4 }, { 95, 1 + DIV8 }}
+};
+
+/* 800x600, 56Hz (9) --unsupported? copy of mode 10 for now... */
+static struct platinum_regvals platinum_reg_init_9 = {
+	0x1010,
+	{ 832, 1632, 3232 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d,
+	  0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34,
+	  0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 54, 3 + DIV4 }, { 88, 1 + DIV8 }}
+};
+
+/* 768x576, 50Hz Interlaced-PAL (8) */
+static struct platinum_regvals platinum_reg_init_8 = {
+	0x1010,
+	{ 800, 1568, 3104 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36,
+	  0x47, 0x1c7, 0x1d6, 0x271, 0x270, 4, 9, 0x27,
+	  0x267, 0x26b }, { 0x39, 0x41, 0x46 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }}
+};
+
+/* 640x870, 75Hz Portrait (7) */
+static struct platinum_regvals platinum_reg_init_7 = {
+	0xb10,
+	{ 672, 1312, 2592 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x176, 0xd0, 0x14, 0x19f, 0x27, 0x2d, 0x3f,
+	  0x4a, 0x18a, 0x19e, 0x72c, 0x72a, 4, 9, 0x58,
+	  0x724, 0x72a }, { 0x3c, 0x44, 0x49 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }}
+};
+
+/* 640x480, 67Hz (6) */
+static struct platinum_regvals platinum_reg_init_6 = {
+	0x1010,
+	{ 672, 1312, 2592 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x209, 0,
+	  0, 0x18e, 0xd8, 0x10, 0x1af, 0x1f, 0x25, 0x37,
+	  0x4a, 0x18a, 0x1ae, 0x41a, 0x418, 4, 9, 0x52,
+	  0x412, 0x416 }, { 0x3c, 0x44, 0x49 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 99, 4 + DIV8 }, { 42, 5 + DIV4 }}
+};
+
+/* 640x480, 60Hz (5) */
+static struct platinum_regvals platinum_reg_init_5 = {
+	0x1010,
+	{ 672, 1312, 2592 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x15e, 0xc8, 0x18, 0x18f, 0x2f, 0x35, 0x3e,
+	  0x42, 0x182, 0x18e, 0x41a, 0x418, 2, 7, 0x44,
+	  0x404, 0x408 }, { 0x34, 0x3c, 0x41 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 26, 0 + DIV8 }, { 14, 2 + DIV4 }}
+};
+
+/* 640x480, 60Hz Interlaced-NTSC (4) */
+static struct platinum_regvals platinum_reg_init_4 = {
+	0x1010,
+	{ 672, 1312, 2592 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30,
+	  0x37, 0x177, 0x184, 0x20d, 0x20c, 5, 0xb, 0x23,
+	  0x203, 0x206 }, { 0x29, 0x31, 0x36 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }}
+};
+
+/* 640x480, 50Hz Interlaced-PAL (3) */
+static struct platinum_regvals platinum_reg_init_3 = {
+	0x1010,
+	{ 672, 1312, 2592 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36,
+	  0x67, 0x1a7, 0x1d6, 0x271, 0x270, 4, 9, 0x57,
+	  0x237, 0x26b }, { 0x59, 0x61, 0x66 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }}
+};
+
+/* 512x384, 60Hz (2) */
+static struct platinum_regvals platinum_reg_init_2 = {
+	0x1010,
+	{ 544, 1056, 2080 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0x25c, 0x140, 0x10, 0x27f, 0x1f, 0x2b, 0x4f,
+	  0x68, 0x268, 0x27e, 0x32e, 0x32c, 4, 9, 0x2a,
+	  0x32a, 0x32b }, { 0x5a, 0x62, 0x67 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 33, 2 + DIV8 }, { 79, 9 + DIV8 }}
+};
+
+/* 512x384, 60Hz Interlaced-NTSC (1) */
+static struct platinum_regvals platinum_reg_init_1 = {
+	0x1010,
+	{ 544, 1056, 2080 },
+	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
+	  0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30,
+	  0x57, 0x157, 0x184, 0x20d, 0x20c, 5, 0xb, 0x53,
+	  0x1d3, 0x206 }, { 0x49, 0x51, 0x56 },
+	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
+	{{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }}
+};
+
+static struct platinum_regvals *platinum_reg_init[VMODE_MAX] = {
+	&platinum_reg_init_1,
+	&platinum_reg_init_2,
+	&platinum_reg_init_3,
+	&platinum_reg_init_4,
+	&platinum_reg_init_5,
+	&platinum_reg_init_6,
+	&platinum_reg_init_7,
+	&platinum_reg_init_8,
+	&platinum_reg_init_9,
+	&platinum_reg_init_10,
+	&platinum_reg_init_11,
+	&platinum_reg_init_12,
+	&platinum_reg_init_13,
+	&platinum_reg_init_14,
+	&platinum_reg_init_15,
+	&platinum_reg_init_16,
+	&platinum_reg_init_17,
+	&platinum_reg_init_18,
+	&platinum_reg_init_19,
+	&platinum_reg_init_20
+};
+
+struct vmode_attr {
+	int hres;
+	int vres;
+	int vfreq;
+	int interlaced;
+};
+
+struct vmode_attr vmode_attrs[VMODE_MAX] = {
+	{512, 384, 60, 1},
+	{512, 384, 60},
+	{640, 480, 50, 1},
+	{640, 480, 60, 1},
+	{640, 480, 60},
+	{640, 480, 67},
+	{640, 870, 75},
+	{768, 576, 50, 1},
+	{800, 600, 56},
+	{800, 600, 60},
+	{800, 600, 72},
+	{800, 600, 75},
+	{832, 624, 75},
+	{1024, 768, 60},
+	{1024, 768, 72},
+	{1024, 768, 75},
+	{1024, 768, 75},
+	{1152, 870, 75},
+	{1280, 960, 75},
+	{1280, 1024, 75}
+};
+
diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c
new file mode 100644
index 000000000000..3b85b647bc10
--- /dev/null
+++ b/drivers/video/fbdev/pm2fb.c
@@ -0,0 +1,1858 @@
+/*
+ * Permedia2 framebuffer driver.
+ *
+ * 2.5/2.6 driver:
+ * Copyright (c) 2003 Jim Hague (jim.hague@acm.org)
+ *
+ * based on 2.4 driver:
+ * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * and additional input from James Simmon's port of Hannu Mallat's tdfx
+ * driver.
+ *
+ * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. I
+ * have no access to other pm2fb implementations. Sparc (and thus
+ * hopefully other big-endian) devices now work, thanks to a lot of
+ * testing work by Ron Murray. I have no access to CVision hardware,
+ * and therefore for now I am omitting the CVision code.
+ *
+ * Multiple boards support has been on the TODO list for ages.
+ * Don't expect this to change.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/permedia2.h>
+#include <video/cvisionppc.h>
+
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error	"The endianness of the target host has not been defined."
+#endif
+
+#if !defined(CONFIG_PCI)
+#error "Only generic PCI cards supported."
+#endif
+
+#undef PM2FB_MASTER_DEBUG
+#ifdef PM2FB_MASTER_DEBUG
+#define DPRINTK(a, b...)	\
+	printk(KERN_DEBUG "pm2fb: %s: " a, __func__ , ## b)
+#else
+#define DPRINTK(a, b...)
+#endif
+
+#define PM2_PIXMAP_SIZE	(1600 * 4)
+
+/*
+ * Driver data
+ */
+static int hwcursor = 1;
+static char *mode_option;
+
+/*
+ * The XFree GLINT driver will (I think to implement hardware cursor
+ * support on TVP4010 and similar where there is no RAMDAC - see
+ * comment in set_video) always request +ve sync regardless of what
+ * the mode requires. This screws me because I have a Sun
+ * fixed-frequency monitor which absolutely has to have -ve sync. So
+ * these flags allow the user to specify that requests for +ve sync
+ * should be silently turned in -ve sync.
+ */
+static bool lowhsync;
+static bool lowvsync;
+static bool noaccel;
+/* mtrr option */
+#ifdef CONFIG_MTRR
+static bool nomtrr;
+#endif
+
+/*
+ * The hardware state of the graphics card that isn't part of the
+ * screeninfo.
+ */
+struct pm2fb_par
+{
+	pm2type_t	type;		/* Board type */
+	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
+	u32		memclock;	/* memclock */
+	u32		video;		/* video flags before blanking */
+	u32		mem_config;	/* MemConfig reg at probe */
+	u32		mem_control;	/* MemControl reg at probe */
+	u32		boot_address;	/* BootAddress reg at probe */
+	u32		palette[16];
+	int		mtrr_handle;
+};
+
+/*
+ * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
+ * if we don't use modedb.
+ */
+static struct fb_fix_screeninfo pm2fb_fix = {
+	.id =		"",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.accel =	FB_ACCEL_3DLABS_PERMEDIA2,
+};
+
+/*
+ * Default video mode. In case the modedb doesn't work.
+ */
+static struct fb_var_screeninfo pm2fb_var = {
+	/* "640x480, 8 bpp @ 60 Hz */
+	.xres =			640,
+	.yres =			480,
+	.xres_virtual =		640,
+	.yres_virtual =		480,
+	.bits_per_pixel =	8,
+	.red =			{0, 8, 0},
+	.blue =			{0, 8, 0},
+	.green =		{0, 8, 0},
+	.activate =		FB_ACTIVATE_NOW,
+	.height =		-1,
+	.width =		-1,
+	.accel_flags =		0,
+	.pixclock =		39721,
+	.left_margin =		40,
+	.right_margin =		24,
+	.upper_margin =		32,
+	.lower_margin =		11,
+	.hsync_len =		96,
+	.vsync_len =		2,
+	.vmode =		FB_VMODE_NONINTERLACED
+};
+
+/*
+ * Utility functions
+ */
+
+static inline u32 pm2_RD(struct pm2fb_par *p, s32 off)
+{
+	return fb_readl(p->v_regs + off);
+}
+
+static inline void pm2_WR(struct pm2fb_par *p, s32 off, u32 v)
+{
+	fb_writel(v, p->v_regs + off);
+}
+
+static inline u32 pm2_RDAC_RD(struct pm2fb_par *p, s32 idx)
+{
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+	mb();
+	return pm2_RD(p, PM2R_RD_INDEXED_DATA);
+}
+
+static inline u32 pm2v_RDAC_RD(struct pm2fb_par *p, s32 idx)
+{
+	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
+	mb();
+	return pm2_RD(p,  PM2VR_RD_INDEXED_DATA);
+}
+
+static inline void pm2_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
+{
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+	wmb();
+	pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
+	wmb();
+}
+
+static inline void pm2v_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
+{
+	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
+	wmb();
+	pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
+	wmb();
+}
+
+#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
+#define WAIT_FIFO(p, a)
+#else
+static inline void WAIT_FIFO(struct pm2fb_par *p, u32 a)
+{
+	while (pm2_RD(p, PM2R_IN_FIFO_SPACE) < a)
+		cpu_relax();
+}
+#endif
+
+/*
+ * partial products for the supported horizontal resolutions.
+ */
+#define PACKPP(p0, p1, p2)	(((p2) << 6) | ((p1) << 3) | (p0))
+static const struct {
+	u16 width;
+	u16 pp;
+} pp_table[] = {
+	{ 32,	PACKPP(1, 0, 0) }, { 64,	PACKPP(1, 1, 0) },
+	{ 96,	PACKPP(1, 1, 1) }, { 128,	PACKPP(2, 1, 1) },
+	{ 160,	PACKPP(2, 2, 1) }, { 192,	PACKPP(2, 2, 2) },
+	{ 224,	PACKPP(3, 2, 1) }, { 256,	PACKPP(3, 2, 2) },
+	{ 288,	PACKPP(3, 3, 1) }, { 320,	PACKPP(3, 3, 2) },
+	{ 384,	PACKPP(3, 3, 3) }, { 416,	PACKPP(4, 3, 1) },
+	{ 448,	PACKPP(4, 3, 2) }, { 512,	PACKPP(4, 3, 3) },
+	{ 544,	PACKPP(4, 4, 1) }, { 576,	PACKPP(4, 4, 2) },
+	{ 640,	PACKPP(4, 4, 3) }, { 768,	PACKPP(4, 4, 4) },
+	{ 800,	PACKPP(5, 4, 1) }, { 832,	PACKPP(5, 4, 2) },
+	{ 896,	PACKPP(5, 4, 3) }, { 1024,	PACKPP(5, 4, 4) },
+	{ 1056,	PACKPP(5, 5, 1) }, { 1088,	PACKPP(5, 5, 2) },
+	{ 1152,	PACKPP(5, 5, 3) }, { 1280,	PACKPP(5, 5, 4) },
+	{ 1536,	PACKPP(5, 5, 5) }, { 1568,	PACKPP(6, 5, 1) },
+	{ 1600,	PACKPP(6, 5, 2) }, { 1664,	PACKPP(6, 5, 3) },
+	{ 1792,	PACKPP(6, 5, 4) }, { 2048,	PACKPP(6, 5, 5) },
+	{ 0,	0 } };
+
+static u32 partprod(u32 xres)
+{
+	int i;
+
+	for (i = 0; pp_table[i].width && pp_table[i].width != xres; i++)
+		;
+	if (pp_table[i].width == 0)
+		DPRINTK("invalid width %u\n", xres);
+	return pp_table[i].pp;
+}
+
+static u32 to3264(u32 timing, int bpp, int is64)
+{
+	switch (bpp) {
+	case 24:
+		timing *= 3;
+	case 8:
+		timing >>= 1;
+	case 16:
+		timing >>= 1;
+	case 32:
+		break;
+	}
+	if (is64)
+		timing >>= 1;
+	return timing;
+}
+
+static void pm2_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
+		    unsigned char *pp)
+{
+	unsigned char m;
+	unsigned char n;
+	unsigned char p;
+	u32 f;
+	s32 curr;
+	s32 delta = 100000;
+
+	*mm = *nn = *pp = 0;
+	for (n = 2; n < 15; n++) {
+		for (m = 2; m; m++) {
+			f = PM2_REFERENCE_CLOCK * m / n;
+			if (f >= 150000 && f <= 300000) {
+				for (p = 0; p < 5; p++, f >>= 1) {
+					curr = (clk > f) ? clk - f : f - clk;
+					if (curr < delta) {
+						delta = curr;
+						*mm = m;
+						*nn = n;
+						*pp = p;
+					}
+				}
+			}
+		}
+	}
+}
+
+static void pm2v_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
+		     unsigned char *pp)
+{
+	unsigned char m;
+	unsigned char n;
+	unsigned char p;
+	u32 f;
+	s32 delta = 1000;
+
+	*mm = *nn = *pp = 0;
+	for (m = 1; m < 128; m++) {
+		for (n = 2 * m + 1; n; n++) {
+			for (p = 0; p < 2; p++) {
+				f = (PM2_REFERENCE_CLOCK >> (p + 1)) * n / m;
+				if (clk > f - delta && clk < f + delta) {
+					delta = (clk > f) ? clk - f : f - clk;
+					*mm = m;
+					*nn = n;
+					*pp = p;
+				}
+			}
+		}
+	}
+}
+
+static void clear_palette(struct pm2fb_par *p)
+{
+	int i = 256;
+
+	WAIT_FIFO(p, 1);
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
+	wmb();
+	while (i--) {
+		WAIT_FIFO(p, 3);
+		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+	}
+}
+
+static void reset_card(struct pm2fb_par *p)
+{
+	if (p->type == PM2_TYPE_PERMEDIA2V)
+		pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
+	pm2_WR(p, PM2R_RESET_STATUS, 0);
+	mb();
+	while (pm2_RD(p, PM2R_RESET_STATUS) & PM2F_BEING_RESET)
+		cpu_relax();
+	mb();
+#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
+	DPRINTK("FIFO disconnect enabled\n");
+	pm2_WR(p, PM2R_FIFO_DISCON, 1);
+	mb();
+#endif
+
+	/* Restore stashed memory config information from probe */
+	WAIT_FIFO(p, 3);
+	pm2_WR(p, PM2R_MEM_CONTROL, p->mem_control);
+	pm2_WR(p, PM2R_BOOT_ADDRESS, p->boot_address);
+	wmb();
+	pm2_WR(p, PM2R_MEM_CONFIG, p->mem_config);
+}
+
+static void reset_config(struct pm2fb_par *p)
+{
+	WAIT_FIFO(p, 53);
+	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG) &
+			~(PM2F_VGA_ENABLE | PM2F_VGA_FIXED));
+	pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FIFO_CONTROL, 0);
+	pm2_WR(p, PM2R_APERTURE_ONE, 0);
+	pm2_WR(p, PM2R_APERTURE_TWO, 0);
+	pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
+	pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
+	pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
+	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
+	pm2_WR(p, PM2R_LB_READ_MODE, 0);
+	pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
+	pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
+	pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
+	pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
+	pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
+	pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FB_READ_PIXEL, 0);
+	pm2_WR(p, PM2R_DITHER_MODE, 0);
+	pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0);
+	pm2_WR(p, PM2R_DEPTH_MODE, 0);
+	pm2_WR(p, PM2R_STENCIL_MODE, 0);
+	pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0);
+	pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0);
+	pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0);
+	pm2_WR(p, PM2R_YUV_MODE, 0);
+	pm2_WR(p, PM2R_COLOR_DDA_MODE, 0);
+	pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0);
+	pm2_WR(p, PM2R_FOG_MODE, 0);
+	pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0);
+	pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
+	pm2_WR(p, PM2R_STATISTICS_MODE, 0);
+	pm2_WR(p, PM2R_SCISSOR_MODE, 0);
+	pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
+	pm2_WR(p, PM2R_RD_PIXEL_MASK, 0xff);
+	switch (p->type) {
+	case PM2_TYPE_PERMEDIA2:
+		pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
+		pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
+		pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
+		pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
+		pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
+		pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
+		pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
+		pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */
+		break;
+	}
+}
+
+static void set_aperture(struct pm2fb_par *p, u32 depth)
+{
+	/*
+	 * The hardware is little-endian. When used in big-endian
+	 * hosts, the on-chip aperture settings are used where
+	 * possible to translate from host to card byte order.
+	 */
+	WAIT_FIFO(p, 2);
+#ifdef __LITTLE_ENDIAN
+	pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
+#else
+	switch (depth) {
+	case 24:	/* RGB->BGR */
+		/*
+		 * We can't use the aperture to translate host to
+		 * card byte order here, so we switch to BGR mode
+		 * in pm2fb_set_par().
+		 */
+	case 8:		/* B->B */
+		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
+		break;
+	case 16:	/* HL->LH */
+		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_HALFWORDSWAP);
+		break;
+	case 32:	/* RGBA->ABGR */
+		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_BYTESWAP);
+		break;
+	}
+#endif
+
+	/* We don't use aperture two, so this may be superflous */
+	pm2_WR(p, PM2R_APERTURE_TWO, PM2F_APERTURE_STANDARD);
+}
+
+static void set_color(struct pm2fb_par *p, unsigned char regno,
+		      unsigned char r, unsigned char g, unsigned char b)
+{
+	WAIT_FIFO(p, 4);
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
+	wmb();
+	pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
+	wmb();
+	pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
+	wmb();
+	pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
+}
+
+static void set_memclock(struct pm2fb_par *par, u32 clk)
+{
+	int i;
+	unsigned char m, n, p;
+
+	switch (par->type) {
+	case PM2_TYPE_PERMEDIA2V:
+		pm2v_mnp(clk/2, &m, &n, &p);
+		WAIT_FIFO(par, 12);
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
+		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
+		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
+		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n);
+		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
+		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
+		rmb();
+		for (i = 256; i; i--)
+			if (pm2v_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2)
+				break;
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+		break;
+	case PM2_TYPE_PERMEDIA2:
+		pm2_mnp(clk, &m, &n, &p);
+		WAIT_FIFO(par, 10);
+		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
+		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
+		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
+		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
+		pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
+		rmb();
+		for (i = 256; i; i--)
+			if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
+				break;
+		break;
+	}
+}
+
+static void set_pixclock(struct pm2fb_par *par, u32 clk)
+{
+	int i;
+	unsigned char m, n, p;
+
+	switch (par->type) {
+	case PM2_TYPE_PERMEDIA2:
+		pm2_mnp(clk, &m, &n, &p);
+		WAIT_FIFO(par, 10);
+		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
+		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
+		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
+		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
+		pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
+		rmb();
+		for (i = 256; i; i--)
+			if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
+				break;
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		pm2v_mnp(clk/2, &m, &n, &p);
+		WAIT_FIFO(par, 8);
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8);
+		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_PRESCALE, m);
+		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_FEEDBACK, n);
+		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_POSTSCALE, p);
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+		break;
+	}
+}
+
+static void set_video(struct pm2fb_par *p, u32 video)
+{
+	u32 tmp;
+	u32 vsync = video;
+
+	DPRINTK("video = 0x%x\n", video);
+
+	/*
+	 * The hardware cursor needs +vsync to recognise vert retrace.
+	 * We may not be using the hardware cursor, but the X Glint
+	 * driver may well. So always set +hsync/+vsync and then set
+	 * the RAMDAC to invert the sync if necessary.
+	 */
+	vsync &= ~(PM2F_HSYNC_MASK | PM2F_VSYNC_MASK);
+	vsync |= PM2F_HSYNC_ACT_HIGH | PM2F_VSYNC_ACT_HIGH;
+
+	WAIT_FIFO(p, 3);
+	pm2_WR(p, PM2R_VIDEO_CONTROL, vsync);
+
+	switch (p->type) {
+	case PM2_TYPE_PERMEDIA2:
+		tmp = PM2F_RD_PALETTE_WIDTH_8;
+		if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
+			tmp |= 4; /* invert hsync */
+		if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
+			tmp |= 8; /* invert vsync */
+		pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, tmp);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		tmp = 0;
+		if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
+			tmp |= 1; /* invert hsync */
+		if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
+			tmp |= 4; /* invert vsync */
+		pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp);
+		break;
+	}
+}
+
+/*
+ *	pm2fb_check_var - Optional function. Validates a var passed in.
+ *	@var: frame buffer variable screen structure
+ *	@info: frame buffer structure that represents a single frame buffer
+ *
+ *	Checks to see if the hardware supports the state requested by
+ *	var passed in.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 lpitch;
+
+	if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
+	    var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
+		DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (var->xres != var->xres_virtual) {
+		DPRINTK("virtual x resolution != "
+			"physical x resolution not supported\n");
+		return -EINVAL;
+	}
+
+	if (var->yres > var->yres_virtual) {
+		DPRINTK("virtual y resolution < "
+			"physical y resolution not possible\n");
+		return -EINVAL;
+	}
+
+	/* permedia cannot blit over 2048 */
+	if (var->yres_virtual > 2047) {
+		var->yres_virtual = 2047;
+	}
+
+	if (var->xoffset) {
+		DPRINTK("xoffset not supported\n");
+		return -EINVAL;
+	}
+
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		DPRINTK("interlace not supported\n");
+		return -EINVAL;
+	}
+
+	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
+	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
+
+	if (var->xres < 320 || var->xres > 1600) {
+		DPRINTK("width not supported: %u\n", var->xres);
+		return -EINVAL;
+	}
+
+	if (var->yres < 200 || var->yres > 1200) {
+		DPRINTK("height not supported: %u\n", var->yres);
+		return -EINVAL;
+	}
+
+	if (lpitch * var->yres_virtual > info->fix.smem_len) {
+		DPRINTK("no memory for screen (%ux%ux%u)\n",
+			var->xres, var->yres_virtual, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
+		DPRINTK("pixclock too high (%ldKHz)\n",
+			PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case 16:
+		var->red.offset   = 11;
+		var->red.length   = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset  = 0;
+		var->blue.length  = 5;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset	  = 16;
+		var->green.offset = 8;
+		var->blue.offset  = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case 24:
+#ifdef __BIG_ENDIAN
+		var->red.offset   = 0;
+		var->blue.offset  = 16;
+#else
+		var->red.offset   = 16;
+		var->blue.offset  = 0;
+#endif
+		var->green.offset = 8;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	}
+	var->height = -1;
+	var->width = -1;
+
+	var->accel_flags = 0;	/* Can't mmap if this is on */
+
+	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
+		var->xres, var->yres, var->bits_per_pixel);
+	return 0;
+}
+
+/**
+ *	pm2fb_set_par - Alters the hardware state.
+ *	@info: frame buffer structure that represents a single frame buffer
+ *
+ *	Using the fb_var_screeninfo in fb_info we set the resolution of the
+ *	this particular framebuffer.
+ */
+static int pm2fb_set_par(struct fb_info *info)
+{
+	struct pm2fb_par *par = info->par;
+	u32 pixclock;
+	u32 width = (info->var.xres_virtual + 7) & ~7;
+	u32 height = info->var.yres_virtual;
+	u32 depth = (info->var.bits_per_pixel + 7) & ~7;
+	u32 hsstart, hsend, hbend, htotal;
+	u32 vsstart, vsend, vbend, vtotal;
+	u32 stride;
+	u32 base;
+	u32 video = 0;
+	u32 clrmode = PM2F_RD_COLOR_MODE_RGB | PM2F_RD_GUI_ACTIVE;
+	u32 txtmap = 0;
+	u32 pixsize = 0;
+	u32 clrformat = 0;
+	u32 misc = 1; /* 8-bit DAC */
+	u32 xres = (info->var.xres + 31) & ~31;
+	int data64;
+
+	reset_card(par);
+	reset_config(par);
+	clear_palette(par);
+	if (par->memclock)
+		set_memclock(par, par->memclock);
+
+	depth = (depth > 32) ? 32 : depth;
+	data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V;
+
+	pixclock = PICOS2KHZ(info->var.pixclock);
+	if (pixclock > PM2_MAX_PIXCLOCK) {
+		DPRINTK("pixclock too high (%uKHz)\n", pixclock);
+		return -EINVAL;
+	}
+
+	hsstart = to3264(info->var.right_margin, depth, data64);
+	hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
+	hbend = hsend + to3264(info->var.left_margin, depth, data64);
+	htotal = to3264(xres, depth, data64) + hbend - 1;
+	vsstart = (info->var.lower_margin)
+		? info->var.lower_margin - 1
+		: 0;	/* FIXME! */
+	vsend = info->var.lower_margin + info->var.vsync_len - 1;
+	vbend = info->var.lower_margin + info->var.vsync_len +
+		info->var.upper_margin;
+	vtotal = info->var.yres + vbend - 1;
+	stride = to3264(width, depth, 1);
+	base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
+	if (data64)
+		video |= PM2F_DATA_64_ENABLE;
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
+		if (lowhsync) {
+			DPRINTK("ignoring +hsync, using -hsync.\n");
+			video |= PM2F_HSYNC_ACT_LOW;
+		} else
+			video |= PM2F_HSYNC_ACT_HIGH;
+	} else
+		video |= PM2F_HSYNC_ACT_LOW;
+
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) {
+		if (lowvsync) {
+			DPRINTK("ignoring +vsync, using -vsync.\n");
+			video |= PM2F_VSYNC_ACT_LOW;
+		} else
+			video |= PM2F_VSYNC_ACT_HIGH;
+	} else
+		video |= PM2F_VSYNC_ACT_LOW;
+
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		DPRINTK("interlaced not supported\n");
+		return -EINVAL;
+	}
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+		video |= PM2F_LINE_DOUBLE;
+	if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+		video |= PM2F_VIDEO_ENABLE;
+	par->video = video;
+
+	info->fix.visual =
+		(depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = info->var.xres * depth / 8;
+	info->cmap.len = 256;
+
+	/*
+	 * Settings calculated. Now write them out.
+	 */
+	if (par->type == PM2_TYPE_PERMEDIA2V) {
+		WAIT_FIFO(par, 1);
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+	}
+
+	set_aperture(par, depth);
+
+	mb();
+	WAIT_FIFO(par, 19);
+	switch (depth) {
+	case 8:
+		pm2_WR(par, PM2R_FB_READ_PIXEL, 0);
+		clrformat = 0x2e;
+		break;
+	case 16:
+		pm2_WR(par, PM2R_FB_READ_PIXEL, 1);
+		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB565;
+		txtmap = PM2F_TEXTEL_SIZE_16;
+		pixsize = 1;
+		clrformat = 0x70;
+		misc |= 8;
+		break;
+	case 32:
+		pm2_WR(par, PM2R_FB_READ_PIXEL, 2);
+		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGBA8888;
+		txtmap = PM2F_TEXTEL_SIZE_32;
+		pixsize = 2;
+		clrformat = 0x20;
+		misc |= 8;
+		break;
+	case 24:
+		pm2_WR(par, PM2R_FB_READ_PIXEL, 4);
+		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB888;
+		txtmap = PM2F_TEXTEL_SIZE_24;
+		pixsize = 4;
+		clrformat = 0x20;
+		misc |= 8;
+		break;
+	}
+	pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
+	pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
+	pm2_WR(par, PM2R_LB_READ_MODE, partprod(xres));
+	pm2_WR(par, PM2R_TEXTURE_MAP_FORMAT, txtmap | partprod(xres));
+	pm2_WR(par, PM2R_H_TOTAL, htotal);
+	pm2_WR(par, PM2R_HS_START, hsstart);
+	pm2_WR(par, PM2R_HS_END, hsend);
+	pm2_WR(par, PM2R_HG_END, hbend);
+	pm2_WR(par, PM2R_HB_END, hbend);
+	pm2_WR(par, PM2R_V_TOTAL, vtotal);
+	pm2_WR(par, PM2R_VS_START, vsstart);
+	pm2_WR(par, PM2R_VS_END, vsend);
+	pm2_WR(par, PM2R_VB_END, vbend);
+	pm2_WR(par, PM2R_SCREEN_STRIDE, stride);
+	wmb();
+	pm2_WR(par, PM2R_WINDOW_ORIGIN, 0);
+	pm2_WR(par, PM2R_SCREEN_SIZE, (height << 16) | width);
+	pm2_WR(par, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
+	wmb();
+	pm2_WR(par, PM2R_SCREEN_BASE, base);
+	wmb();
+	set_video(par, video);
+	WAIT_FIFO(par, 10);
+	switch (par->type) {
+	case PM2_TYPE_PERMEDIA2:
+		pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE, clrmode);
+		pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
+				(depth == 8) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		pm2v_RDAC_WR(par, PM2VI_RD_DAC_CONTROL, 0);
+		pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize);
+		pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat);
+		pm2v_RDAC_WR(par, PM2VI_RD_MISC_CONTROL, misc);
+		pm2v_RDAC_WR(par, PM2VI_RD_OVERLAY_KEY, 0);
+		break;
+	}
+	set_pixclock(par, pixclock);
+	DPRINTK("Setting graphics mode at %dx%d depth %d\n",
+		info->var.xres, info->var.yres, info->var.bits_per_pixel);
+	return 0;
+}
+
+/**
+ *	pm2fb_setcolreg - Sets a color register.
+ *	@regno: boolean, 0 copy local, 1 get_user() function
+ *	@red: frame buffer colormap structure
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *	@info: frame buffer info structure
+ *
+ *	Set a single color register. The values supplied have a 16 bit
+ *	magnitude which needs to be scaled in this function for the hardware.
+ *	Pretty much a direct lift from tdfxfb.c.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct pm2fb_par *par = info->par;
+
+	if (regno >= info->cmap.len)  /* no. of hw registers */
+		return -EINVAL;
+	/*
+	 * Program hardware... do anything you want with transp
+	 */
+
+	/* grayscale works only partially under directcolor */
+	/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+	if (info->var.grayscale)
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of DAC
+	 *   cmap[X] is programmed to
+	 *   (X << red.offset) | (X << green.offset) | (X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 *
+	 * Pseudocolor:
+	 *    uses offset = 0 && length = DAC register width.
+	 *    var->{color}.offset is 0
+	 *    var->{color}.length contains width of DAC
+	 *    cmap is not used
+	 *    DAC[X] is programmed to (red, green, blue)
+	 * Truecolor:
+	 *    does not use RAMDAC (usually has 3 of them).
+	 *    var->{color}.offset contains start of bitfield
+	 *    var->{color}.length contains length of bitfield
+	 *    cmap is programmed to
+	 *    (red << red.offset) | (green << green.offset) |
+	 *    (blue << blue.offset) | (transp << transp.offset)
+	 *    RAMDAC does not exist
+	 */
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF -(val)) >> 16)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		/* example here assumes 8 bit DAC. Might be different
+		 * for your hardware */
+		red = CNVT_TOHW(red, 8);
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		v = (red << info->var.red.offset) |
+			(green << info->var.green.offset) |
+			(blue << info->var.blue.offset) |
+			(transp << info->var.transp.offset);
+
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+		case 24:
+		case 32:
+			par->palette[regno] = v;
+			break;
+		}
+		return 0;
+	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+		set_color(par, regno, red, green, blue);
+
+	return 0;
+}
+
+/**
+ *	pm2fb_pan_display - Pans the display.
+ *	@var: frame buffer variable screen structure
+ *	@info: frame buffer structure that represents a single frame buffer
+ *
+ *	Pan (or wrap, depending on the `vmode' field) the display using the
+ *	`xoffset' and `yoffset' fields of the `var' structure.
+ *	If the values don't fit, return -EINVAL.
+ *
+ *	Returns negative errno on error, or zero on success.
+ *
+ */
+static int pm2fb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct pm2fb_par *p = info->par;
+	u32 base;
+	u32 depth = (info->var.bits_per_pixel + 7) & ~7;
+	u32 xres = (info->var.xres + 31) & ~31;
+
+	depth = (depth > 32) ? 32 : depth;
+	base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
+	WAIT_FIFO(p, 1);
+	pm2_WR(p, PM2R_SCREEN_BASE, base);
+	return 0;
+}
+
+/**
+ *	pm2fb_blank - Blanks the display.
+ *	@blank_mode: the blank mode we want.
+ *	@info: frame buffer structure that represents a single frame buffer
+ *
+ *	Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *	blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *	video mode which doesn't support it. Implements VESA suspend
+ *	and powerdown modes on hardware that supports disabling hsync/vsync:
+ *	blank_mode == 2: suspend vsync
+ *	blank_mode == 3: suspend hsync
+ *	blank_mode == 4: powerdown
+ *
+ *	Returns negative errno on error, or zero on success.
+ *
+ */
+static int pm2fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct pm2fb_par *par = info->par;
+	u32 video = par->video;
+
+	DPRINTK("blank_mode %d\n", blank_mode);
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		/* Screen: On */
+		video |= PM2F_VIDEO_ENABLE;
+		break;
+	case FB_BLANK_NORMAL:
+		/* Screen: Off */
+		video &= ~PM2F_VIDEO_ENABLE;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		/* VSync: Off */
+		video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		/* HSync: Off */
+		video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
+		break;
+	case FB_BLANK_POWERDOWN:
+		/* HSync: Off, VSync: Off */
+		video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
+		break;
+	}
+	set_video(par, video);
+	return 0;
+}
+
+static int pm2fb_sync(struct fb_info *info)
+{
+	struct pm2fb_par *par = info->par;
+
+	WAIT_FIFO(par, 1);
+	pm2_WR(par, PM2R_SYNC, 0);
+	mb();
+	do {
+		while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0)
+			cpu_relax();
+	} while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
+
+	return 0;
+}
+
+static void pm2fb_fillrect(struct fb_info *info,
+				const struct fb_fillrect *region)
+{
+	struct pm2fb_par *par = info->par;
+	struct fb_fillrect modded;
+	int vxres, vyres;
+	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+		((u32 *)info->pseudo_palette)[region->color] : region->color;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
+		region->rop != ROP_COPY ) {
+		cfb_fillrect(info, region);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if (!modded.width || !modded.height ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.dx + modded.width  > vxres)
+		modded.width  = vxres - modded.dx;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	if (info->var.bits_per_pixel == 8)
+		color |= color << 8;
+	if (info->var.bits_per_pixel <= 16)
+		color |= color << 16;
+
+	WAIT_FIFO(par, 3);
+	pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE);
+	pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
+	pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
+	if (info->var.bits_per_pixel != 24) {
+		WAIT_FIFO(par, 2);
+		pm2_WR(par, PM2R_FB_BLOCK_COLOR, color);
+		wmb();
+		pm2_WR(par, PM2R_RENDER,
+				PM2F_RENDER_RECTANGLE | PM2F_RENDER_FASTFILL);
+	} else {
+		WAIT_FIFO(par, 4);
+		pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
+		pm2_WR(par, PM2R_CONSTANT_COLOR, color);
+		wmb();
+		pm2_WR(par, PM2R_RENDER,
+				PM2F_RENDER_RECTANGLE |
+				PM2F_INCREASE_X | PM2F_INCREASE_Y );
+		pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
+	}
+}
+
+static void pm2fb_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+	struct pm2fb_par *par = info->par;
+	struct fb_copyarea modded;
+	u32 vxres, vyres;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	memcpy(&modded, area, sizeof(struct fb_copyarea));
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!modded.width || !modded.height ||
+	    modded.sx >= vxres || modded.sy >= vyres ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.sx + modded.width > vxres)
+		modded.width = vxres - modded.sx;
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.sy + modded.height > vyres)
+		modded.height = vyres - modded.sy;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	WAIT_FIFO(par, 5);
+	pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
+		PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+	pm2_WR(par, PM2R_FB_SOURCE_DELTA,
+			((modded.sy - modded.dy) & 0xfff) << 16 |
+			((modded.sx - modded.dx) & 0xfff));
+	pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
+	pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
+	wmb();
+	pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
+				(modded.dx < modded.sx ? PM2F_INCREASE_X : 0) |
+				(modded.dy < modded.sy ? PM2F_INCREASE_Y : 0));
+}
+
+static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct pm2fb_par *par = info->par;
+	u32 height = image->height;
+	u32 fgx, bgx;
+	const u32 *src = (const u32 *)image->data;
+	u32 xres = (info->var.xres + 31) & ~31;
+	int raster_mode = 1; /* invert bits */
+
+#ifdef __LITTLE_ENDIAN
+	raster_mode |= 3 << 7; /* reverse byte order */
+#endif
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+	switch (info->fix.visual) {
+	case FB_VISUAL_PSEUDOCOLOR:
+		fgx = image->fg_color;
+		bgx = image->bg_color;
+		break;
+	case FB_VISUAL_TRUECOLOR:
+	default:
+		fgx = par->palette[image->fg_color];
+		bgx = par->palette[image->bg_color];
+		break;
+	}
+	if (info->var.bits_per_pixel == 8) {
+		fgx |= fgx << 8;
+		bgx |= bgx << 8;
+	}
+	if (info->var.bits_per_pixel <= 16) {
+		fgx |= fgx << 16;
+		bgx |= bgx << 16;
+	}
+
+	WAIT_FIFO(par, 13);
+	pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
+	pm2_WR(par, PM2R_SCISSOR_MIN_XY,
+			((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
+	pm2_WR(par, PM2R_SCISSOR_MAX_XY,
+			(((image->dy + image->height) & 0x0fff) << 16) |
+			((image->dx + image->width) & 0x0fff));
+	pm2_WR(par, PM2R_SCISSOR_MODE, 1);
+	/* GXcopy & UNIT_ENABLE */
+	pm2_WR(par, PM2R_LOGICAL_OP_MODE, (0x3 << 1) | 1);
+	pm2_WR(par, PM2R_RECTANGLE_ORIGIN,
+			((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
+	pm2_WR(par, PM2R_RECTANGLE_SIZE,
+			((image->height & 0x0fff) << 16) |
+			((image->width) & 0x0fff));
+	if (info->var.bits_per_pixel == 24) {
+		pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
+		/* clear area */
+		pm2_WR(par, PM2R_CONSTANT_COLOR, bgx);
+		pm2_WR(par, PM2R_RENDER,
+			PM2F_RENDER_RECTANGLE |
+			PM2F_INCREASE_X | PM2F_INCREASE_Y);
+		/* BitMapPackEachScanline */
+		pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9));
+		pm2_WR(par, PM2R_CONSTANT_COLOR, fgx);
+		pm2_WR(par, PM2R_RENDER,
+			PM2F_RENDER_RECTANGLE |
+			PM2F_INCREASE_X | PM2F_INCREASE_Y |
+			PM2F_RENDER_SYNC_ON_BIT_MASK);
+	} else {
+		pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
+		/* clear area */
+		pm2_WR(par, PM2R_FB_BLOCK_COLOR, bgx);
+		pm2_WR(par, PM2R_RENDER,
+			PM2F_RENDER_RECTANGLE |
+			PM2F_RENDER_FASTFILL |
+			PM2F_INCREASE_X | PM2F_INCREASE_Y);
+		pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode);
+		pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx);
+		pm2_WR(par, PM2R_RENDER,
+			PM2F_RENDER_RECTANGLE |
+			PM2F_INCREASE_X | PM2F_INCREASE_Y |
+			PM2F_RENDER_FASTFILL |
+			PM2F_RENDER_SYNC_ON_BIT_MASK);
+	}
+
+	while (height--) {
+		int width = ((image->width + 7) >> 3)
+				+ info->pixmap.scan_align - 1;
+		width >>= 2;
+		WAIT_FIFO(par, width);
+		while (width--) {
+			pm2_WR(par, PM2R_BIT_MASK_PATTERN, *src);
+			src++;
+		}
+	}
+	WAIT_FIFO(par, 3);
+	pm2_WR(par, PM2R_RASTERIZER_MODE, 0);
+	pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
+	pm2_WR(par, PM2R_SCISSOR_MODE, 0);
+}
+
+/*
+ *	Hardware cursor support.
+ */
+static const u8 cursor_bits_lookup[16] = {
+	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
+	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
+};
+
+static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct pm2fb_par *par = info->par;
+	u8 mode = PM2F_CURSORMODE_TYPE_X;
+	int x = cursor->image.dx - info->var.xoffset;
+	int y = cursor->image.dy - info->var.yoffset;
+
+	if (cursor->enable)
+		mode |= PM2F_CURSORMODE_CURSOR_ENABLE;
+
+	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_MODE, mode);
+
+	if (!cursor->enable)
+		x = 2047;	/* push it outside display */
+	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_LOW, x & 0xff);
+	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0xf);
+	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_LOW, y & 0xff);
+	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HIGH, (y >> 8) & 0xf);
+
+	/*
+	 * If the cursor is not be changed this means either we want the
+	 * current cursor state (if enable is set) or we want to query what
+	 * we can do with the cursor (if enable is not set)
+	 */
+	if (!cursor->set)
+		return 0;
+
+	if (cursor->set & FB_CUR_SETHOT) {
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HOT,
+			     cursor->hot.x & 0x3f);
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HOT,
+			     cursor->hot.y & 0x3f);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		u32 fg_idx = cursor->image.fg_color;
+		u32 bg_idx = cursor->image.bg_color;
+		struct fb_cmap cmap = info->cmap;
+
+		/* the X11 driver says one should use these color registers */
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8);
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 0,
+			     cmap.red[bg_idx] >> 8 );
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 1,
+			     cmap.green[bg_idx] >> 8 );
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 2,
+			     cmap.blue[bg_idx] >> 8 );
+
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 3,
+			     cmap.red[fg_idx] >> 8 );
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 4,
+			     cmap.green[fg_idx] >> 8 );
+		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 5,
+			     cmap.blue[fg_idx] >> 8 );
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+	}
+
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+		u8 *bitmap = (u8 *)cursor->image.data;
+		u8 *mask = (u8 *)cursor->mask;
+		int i;
+		int pos = PM2VI_RD_CURSOR_PATTERN;
+
+		for (i = 0; i < cursor->image.height; i++) {
+			int j = (cursor->image.width + 7) >> 3;
+			int k = 8 - j;
+
+			pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
+
+			for (; j > 0; j--) {
+				u8 data = *bitmap ^ *mask;
+
+				if (cursor->rop == ROP_COPY)
+					data = *mask & *bitmap;
+				/* Upper 4 bits of bitmap data */
+				pm2v_RDAC_WR(par, pos++,
+					cursor_bits_lookup[data >> 4] |
+					(cursor_bits_lookup[*mask >> 4] << 1));
+				/* Lower 4 bits of bitmap */
+				pm2v_RDAC_WR(par, pos++,
+					cursor_bits_lookup[data & 0xf] |
+					(cursor_bits_lookup[*mask & 0xf] << 1));
+				bitmap++;
+				mask++;
+			}
+			for (; k > 0; k--) {
+				pm2v_RDAC_WR(par, pos++, 0);
+				pm2v_RDAC_WR(par, pos++, 0);
+			}
+		}
+
+		while (pos < (1024 + PM2VI_RD_CURSOR_PATTERN)) {
+			pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
+			pm2v_RDAC_WR(par, pos++, 0);
+		}
+
+		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
+	}
+	return 0;
+}
+
+static int pm2fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct pm2fb_par *par = info->par;
+	u8 mode;
+
+	if (!hwcursor)
+		return -EINVAL;	/* just to force soft_cursor() call */
+
+	/* Too large of a cursor or wrong bpp :-( */
+	if (cursor->image.width > 64 ||
+	    cursor->image.height > 64 ||
+	    cursor->image.depth > 1)
+		return -EINVAL;
+
+	if (par->type == PM2_TYPE_PERMEDIA2V)
+		return pm2vfb_cursor(info, cursor);
+
+	mode = 0x40;
+	if (cursor->enable)
+		 mode = 0x43;
+
+	pm2_RDAC_WR(par, PM2I_RD_CURSOR_CONTROL, mode);
+
+	/*
+	 * If the cursor is not be changed this means either we want the
+	 * current cursor state (if enable is set) or we want to query what
+	 * we can do with the cursor (if enable is not set)
+	 */
+	if (!cursor->set)
+		return 0;
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		int x = cursor->image.dx - info->var.xoffset + 63;
+		int y = cursor->image.dy - info->var.yoffset + 63;
+
+		WAIT_FIFO(par, 4);
+		pm2_WR(par, PM2R_RD_CURSOR_X_LSB, x & 0xff);
+		pm2_WR(par, PM2R_RD_CURSOR_X_MSB, (x >> 8) & 0x7);
+		pm2_WR(par, PM2R_RD_CURSOR_Y_LSB, y & 0xff);
+		pm2_WR(par, PM2R_RD_CURSOR_Y_MSB, (y >> 8) & 0x7);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		u32 fg_idx = cursor->image.fg_color;
+		u32 bg_idx = cursor->image.bg_color;
+
+		WAIT_FIFO(par, 7);
+		pm2_WR(par, PM2R_RD_CURSOR_COLOR_ADDRESS, 1);
+		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+			info->cmap.red[bg_idx] >> 8);
+		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+			info->cmap.green[bg_idx] >> 8);
+		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+			info->cmap.blue[bg_idx] >> 8);
+
+		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+			info->cmap.red[fg_idx] >> 8);
+		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+			info->cmap.green[fg_idx] >> 8);
+		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
+			info->cmap.blue[fg_idx] >> 8);
+	}
+
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+		u8 *bitmap = (u8 *)cursor->image.data;
+		u8 *mask = (u8 *)cursor->mask;
+		int i;
+
+		WAIT_FIFO(par, 1);
+		pm2_WR(par, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
+
+		for (i = 0; i < cursor->image.height; i++) {
+			int j = (cursor->image.width + 7) >> 3;
+			int k = 8 - j;
+
+			WAIT_FIFO(par, 8);
+			for (; j > 0; j--) {
+				u8 data = *bitmap ^ *mask;
+
+				if (cursor->rop == ROP_COPY)
+					data = *mask & *bitmap;
+				/* bitmap data */
+				pm2_WR(par, PM2R_RD_CURSOR_DATA, data);
+				bitmap++;
+				mask++;
+			}
+			for (; k > 0; k--)
+				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+		}
+		for (; i < 64; i++) {
+			int j = 8;
+			WAIT_FIFO(par, 8);
+			while (j-- > 0)
+				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+		}
+
+		mask = (u8 *)cursor->mask;
+		for (i = 0; i < cursor->image.height; i++) {
+			int j = (cursor->image.width + 7) >> 3;
+			int k = 8 - j;
+
+			WAIT_FIFO(par, 8);
+			for (; j > 0; j--) {
+				/* mask */
+				pm2_WR(par, PM2R_RD_CURSOR_DATA, *mask);
+				mask++;
+			}
+			for (; k > 0; k--)
+				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+		}
+		for (; i < 64; i++) {
+			int j = 8;
+			WAIT_FIFO(par, 8);
+			while (j-- > 0)
+				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
+		}
+	}
+	return 0;
+}
+
+/* ------------ Hardware Independent Functions ------------ */
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops pm2fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= pm2fb_check_var,
+	.fb_set_par	= pm2fb_set_par,
+	.fb_setcolreg	= pm2fb_setcolreg,
+	.fb_blank	= pm2fb_blank,
+	.fb_pan_display	= pm2fb_pan_display,
+	.fb_fillrect	= pm2fb_fillrect,
+	.fb_copyarea	= pm2fb_copyarea,
+	.fb_imageblit	= pm2fb_imageblit,
+	.fb_sync	= pm2fb_sync,
+	.fb_cursor	= pm2fb_cursor,
+};
+
+/*
+ * PCI stuff
+ */
+
+
+/**
+ * Device initialisation
+ *
+ * Initialise and allocate resource for PCI device.
+ *
+ * @param	pdev	PCI device.
+ * @param	id	PCI device ID.
+ */
+static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct pm2fb_par *default_par;
+	struct fb_info *info;
+	int err;
+	int retval = -ENXIO;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
+		return err;
+	}
+
+	info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+	default_par = info->par;
+
+	switch (pdev->device) {
+	case  PCI_DEVICE_ID_TI_TVP4020:
+		strcpy(pm2fb_fix.id, "TVP4020");
+		default_par->type = PM2_TYPE_PERMEDIA2;
+		break;
+	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2:
+		strcpy(pm2fb_fix.id, "Permedia2");
+		default_par->type = PM2_TYPE_PERMEDIA2;
+		break;
+	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2V:
+		strcpy(pm2fb_fix.id, "Permedia2v");
+		default_par->type = PM2_TYPE_PERMEDIA2V;
+		break;
+	}
+
+	pm2fb_fix.mmio_start = pci_resource_start(pdev, 0);
+	pm2fb_fix.mmio_len = PM2_REGS_SIZE;
+
+#if defined(__BIG_ENDIAN)
+	/*
+	 * PM2 has a 64k register file, mapped twice in 128k. Lower
+	 * map is little-endian, upper map is big-endian.
+	 */
+	pm2fb_fix.mmio_start += PM2_REGS_SIZE;
+	DPRINTK("Adjusting register base for big-endian.\n");
+#endif
+	DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
+
+	/* Registers - request region and map it. */
+	if (!request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
+				"pm2fb regbase")) {
+		printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");
+		goto err_exit_neither;
+	}
+	default_par->v_regs =
+		ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
+	if (!default_par->v_regs) {
+		printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",
+		       pm2fb_fix.id);
+		release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
+		goto err_exit_neither;
+	}
+
+	/* Stash away memory register info for use when we reset the board */
+	default_par->mem_control = pm2_RD(default_par, PM2R_MEM_CONTROL);
+	default_par->boot_address = pm2_RD(default_par, PM2R_BOOT_ADDRESS);
+	default_par->mem_config = pm2_RD(default_par, PM2R_MEM_CONFIG);
+	DPRINTK("MemControl 0x%x BootAddress 0x%x MemConfig 0x%x\n",
+		default_par->mem_control, default_par->boot_address,
+		default_par->mem_config);
+
+	if (default_par->mem_control == 0 &&
+		default_par->boot_address == 0x31 &&
+		default_par->mem_config == 0x259fffff) {
+		default_par->memclock = CVPPC_MEMCLOCK;
+		default_par->mem_control = 0;
+		default_par->boot_address = 0x20;
+		default_par->mem_config = 0xe6002021;
+		if (pdev->subsystem_vendor == 0x1048 &&
+			pdev->subsystem_device == 0x0a31) {
+			DPRINTK("subsystem_vendor: %04x, "
+				"subsystem_device: %04x\n",
+				pdev->subsystem_vendor, pdev->subsystem_device);
+			DPRINTK("We have not been initialized by VGA BIOS and "
+				"are running on an Elsa Winner 2000 Office\n");
+			DPRINTK("Initializing card timings manually...\n");
+			default_par->memclock = 100000;
+		}
+		if (pdev->subsystem_vendor == 0x3d3d &&
+			pdev->subsystem_device == 0x0100) {
+			DPRINTK("subsystem_vendor: %04x, "
+				"subsystem_device: %04x\n",
+				pdev->subsystem_vendor, pdev->subsystem_device);
+			DPRINTK("We have not been initialized by VGA BIOS and "
+				"are running on an 3dlabs reference board\n");
+			DPRINTK("Initializing card timings manually...\n");
+			default_par->memclock = 74894;
+		}
+	}
+
+	/* Now work out how big lfb is going to be. */
+	switch (default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
+	case PM2F_MEM_BANKS_1:
+		pm2fb_fix.smem_len = 0x200000;
+		break;
+	case PM2F_MEM_BANKS_2:
+		pm2fb_fix.smem_len = 0x400000;
+		break;
+	case PM2F_MEM_BANKS_3:
+		pm2fb_fix.smem_len = 0x600000;
+		break;
+	case PM2F_MEM_BANKS_4:
+		pm2fb_fix.smem_len = 0x800000;
+		break;
+	}
+	pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
+
+	/* Linear frame buffer - request region and map it. */
+	if (!request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
+				"pm2fb smem")) {
+		printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
+		goto err_exit_mmio;
+	}
+	info->screen_base =
+		ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
+		release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
+		goto err_exit_mmio;
+	}
+
+#ifdef CONFIG_MTRR
+	default_par->mtrr_handle = -1;
+	if (!nomtrr)
+		default_par->mtrr_handle =
+			mtrr_add(pm2fb_fix.smem_start,
+				 pm2fb_fix.smem_len,
+				 MTRR_TYPE_WRCOMB, 1);
+#endif
+
+	info->fbops		= &pm2fb_ops;
+	info->fix		= pm2fb_fix;
+	info->pseudo_palette	= default_par->palette;
+	info->flags		= FBINFO_DEFAULT |
+				  FBINFO_HWACCEL_YPAN |
+				  FBINFO_HWACCEL_COPYAREA |
+				  FBINFO_HWACCEL_IMAGEBLIT |
+				  FBINFO_HWACCEL_FILLRECT;
+
+	info->pixmap.addr = kmalloc(PM2_PIXMAP_SIZE, GFP_KERNEL);
+	if (!info->pixmap.addr) {
+		retval = -ENOMEM;
+		goto err_exit_pixmap;
+	}
+	info->pixmap.size = PM2_PIXMAP_SIZE;
+	info->pixmap.buf_align = 4;
+	info->pixmap.scan_align = 4;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if (noaccel) {
+		printk(KERN_DEBUG "disabling acceleration\n");
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+		info->pixmap.scan_align = 1;
+	}
+
+	if (!mode_option)
+		mode_option = "640x480@60";
+
+	err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+	if (!err || err == 4)
+		info->var = pm2fb_var;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err_exit_both;
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_exit_all;
+
+	fb_info(info, "%s frame buffer device, memory = %dK\n",
+		info->fix.id, pm2fb_fix.smem_len / 1024);
+
+	/*
+	 * Our driver data
+	 */
+	pci_set_drvdata(pdev, info);
+
+	return 0;
+
+ err_exit_all:
+	fb_dealloc_cmap(&info->cmap);
+ err_exit_both:
+	kfree(info->pixmap.addr);
+ err_exit_pixmap:
+	iounmap(info->screen_base);
+	release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
+ err_exit_mmio:
+	iounmap(default_par->v_regs);
+	release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
+ err_exit_neither:
+	framebuffer_release(info);
+	return retval;
+}
+
+/**
+ * Device removal.
+ *
+ * Release all device resources.
+ *
+ * @param	pdev	PCI device to clean up.
+ */
+static void pm2fb_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct pm2fb_par *par = info->par;
+
+	unregister_framebuffer(info);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr_handle >= 0)
+		mtrr_del(par->mtrr_handle, info->fix.smem_start,
+			 info->fix.smem_len);
+#endif /* CONFIG_MTRR */
+	iounmap(info->screen_base);
+	release_mem_region(fix->smem_start, fix->smem_len);
+	iounmap(par->v_regs);
+	release_mem_region(fix->mmio_start, fix->mmio_len);
+
+	fb_dealloc_cmap(&info->cmap);
+	kfree(info->pixmap.addr);
+	framebuffer_release(info);
+}
+
+static struct pci_device_id pm2fb_id_table[] = {
+	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, }
+};
+
+static struct pci_driver pm2fb_driver = {
+	.name		= "pm2fb",
+	.id_table	= pm2fb_id_table,
+	.probe		= pm2fb_probe,
+	.remove		= pm2fb_remove,
+};
+
+MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
+
+
+#ifndef MODULE
+/**
+ * Parse user specified options.
+ *
+ * This is, comma-separated options following `video=pm2fb:'.
+ */
+static int __init pm2fb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strcmp(this_opt, "lowhsync"))
+			lowhsync = 1;
+		else if (!strcmp(this_opt, "lowvsync"))
+			lowvsync = 1;
+		else if (!strncmp(this_opt, "hwcursor=", 9))
+			hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
+#ifdef CONFIG_MTRR
+		else if (!strncmp(this_opt, "nomtrr", 6))
+			nomtrr = 1;
+#endif
+		else if (!strncmp(this_opt, "noaccel", 7))
+			noaccel = 1;
+		else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+#endif
+
+
+static int __init pm2fb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pm2fb", &option))
+		return -ENODEV;
+	pm2fb_setup(option);
+#endif
+
+	return pci_register_driver(&pm2fb_driver);
+}
+
+module_init(pm2fb_init);
+
+#ifdef MODULE
+/*
+ *  Cleanup
+ */
+
+static void __exit pm2fb_exit(void)
+{
+	pci_unregister_driver(&pm2fb_driver);
+}
+#endif
+
+#ifdef MODULE
+module_exit(pm2fb_exit);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+module_param_named(mode, mode_option, charp, 0);
+MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8@60' (deprecated)");
+module_param(lowhsync, bool, 0);
+MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");
+module_param(lowvsync, bool, 0);
+MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "Disable acceleration");
+module_param(hwcursor, int, 0644);
+MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
+			"(1=enable, 0=disable, default=1)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
+#endif
+
+MODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");
+MODULE_DESCRIPTION("Permedia2 framebuffer device driver");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/video/fbdev/pm3fb.c b/drivers/video/fbdev/pm3fb.c
new file mode 100644
index 000000000000..4bf3273d0433
--- /dev/null
+++ b/drivers/video/fbdev/pm3fb.c
@@ -0,0 +1,1586 @@
+/*
+ *  linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device
+ *
+ *  Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>.
+ *
+ *  Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl>
+ *	based on pm2fb.c
+ *
+ *  Based on code written by:
+ *	   Sven Luther, <luther@dpt-info.u-strasbg.fr>
+ *	   Alan Hourihane, <alanh@fairlite.demon.co.uk>
+ *	   Russell King, <rmk@arm.linux.org.uk>
+ *  Based on linux/drivers/video/skeletonfb.c:
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *  Based on linux/driver/video/pm2fb.c:
+ *	Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ *	Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/pm3fb.h>
+
+#if !defined(CONFIG_PCI)
+#error "Only generic PCI cards supported."
+#endif
+
+#undef PM3FB_MASTER_DEBUG
+#ifdef PM3FB_MASTER_DEBUG
+#define DPRINTK(a, b...)	\
+	printk(KERN_DEBUG "pm3fb: %s: " a, __func__ , ## b)
+#else
+#define DPRINTK(a, b...)
+#endif
+
+#define PM3_PIXMAP_SIZE	(2048 * 4)
+
+/*
+ * Driver data
+ */
+static int hwcursor = 1;
+static char *mode_option;
+static bool noaccel;
+
+/* mtrr option */
+#ifdef CONFIG_MTRR
+static bool nomtrr;
+#endif
+
+/*
+ * This structure defines the hardware state of the graphics card. Normally
+ * you place this in a header file in linux/include/video. This file usually
+ * also includes register information. That allows other driver subsystems
+ * and userland applications the ability to use the same header file to
+ * avoid duplicate work and easy porting of software.
+ */
+struct pm3_par {
+	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
+	u32		video;		/* video flags before blanking */
+	u32		base;		/* screen base in 128 bits unit */
+	u32		palette[16];
+	int		mtrr_handle;
+};
+
+/*
+ * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
+ * if we don't use modedb. If we do use modedb see pm3fb_init how to use it
+ * to get a fb_var_screeninfo. Otherwise define a default var as well.
+ */
+static struct fb_fix_screeninfo pm3fb_fix = {
+	.id =		"Permedia3",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.accel =	FB_ACCEL_3DLABS_PERMEDIA3,
+};
+
+/*
+ * Utility functions
+ */
+
+static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off)
+{
+	return fb_readl(par->v_regs + off);
+}
+
+static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
+{
+	fb_writel(v, par->v_regs + off);
+}
+
+static inline void PM3_WAIT(struct pm3_par *par, u32 n)
+{
+	while (PM3_READ_REG(par, PM3InFIFOSpace) < n)
+		cpu_relax();
+}
+
+static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
+{
+	PM3_WAIT(par, 3);
+	PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff);
+	PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_IndexedData, v);
+	wmb();
+}
+
+static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
+			unsigned char r, unsigned char g, unsigned char b)
+{
+	PM3_WAIT(par, 4);
+	PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_PaletteData, r);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_PaletteData, g);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_PaletteData, b);
+	wmb();
+}
+
+static void pm3fb_clear_colormap(struct pm3_par *par,
+			unsigned char r, unsigned char g, unsigned char b)
+{
+	int i;
+
+	for (i = 0; i < 256 ; i++)
+		pm3fb_set_color(par, i, r, g, b);
+
+}
+
+/* Calculating various clock parameters */
+static void pm3fb_calculate_clock(unsigned long reqclock,
+				unsigned char *prescale,
+				unsigned char *feedback,
+				unsigned char *postscale)
+{
+	int f, pre, post;
+	unsigned long freq;
+	long freqerr = 1000;
+	long currerr;
+
+	for (f = 1; f < 256; f++) {
+		for (pre = 1; pre < 256; pre++) {
+			for (post = 0; post < 5; post++) {
+				freq = ((2*PM3_REF_CLOCK * f) >> post) / pre;
+				currerr = (reqclock > freq)
+					? reqclock - freq
+					: freq - reqclock;
+				if (currerr < freqerr) {
+					freqerr = currerr;
+					*feedback = f;
+					*prescale = pre;
+					*postscale = post;
+				}
+			}
+		}
+	}
+}
+
+static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
+{
+	if (var->bits_per_pixel == 16)
+		return var->red.length + var->green.length
+			+ var->blue.length;
+
+	return var->bits_per_pixel;
+}
+
+static inline int pm3fb_shift_bpp(unsigned bpp, int v)
+{
+	switch (bpp) {
+	case 8:
+		return (v >> 4);
+	case 16:
+		return (v >> 3);
+	case 32:
+		return (v >> 2);
+	}
+	DPRINTK("Unsupported depth %u\n", bpp);
+	return 0;
+}
+
+/* acceleration */
+static int pm3fb_sync(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+
+	PM3_WAIT(par, 2);
+	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+	PM3_WRITE_REG(par, PM3Sync, 0);
+	mb();
+	do {
+		while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0)
+			cpu_relax();
+	} while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
+
+	return 0;
+}
+
+static void pm3fb_init_engine(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	const u32 width = (info->var.xres_virtual + 7) & ~7;
+
+	PM3_WAIT(par, 50);
+	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+	PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
+	PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
+	PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
+	PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
+	PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
+	PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
+	PM3_WRITE_REG(par, PM3GIDMode, 0x0);
+	PM3_WRITE_REG(par, PM3DepthMode, 0x0);
+	PM3_WRITE_REG(par, PM3StencilMode, 0x0);
+	PM3_WRITE_REG(par, PM3StencilData, 0x0);
+	PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
+	PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LUTMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
+	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
+	PM3_WRITE_REG(par, PM3FogMode, 0x0);
+	PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
+	PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
+	PM3_WRITE_REG(par, PM3YUVMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
+	PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
+	PM3_WRITE_REG(par, PM3DitherMode, 0x0);
+	PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
+	PM3_WRITE_REG(par, PM3RouterMode, 0x0);
+	PM3_WRITE_REG(par, PM3Window, 0x0);
+
+	PM3_WRITE_REG(par, PM3Config2D, 0x0);
+
+	PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);
+
+	PM3_WRITE_REG(par, PM3XBias, 0x0);
+	PM3_WRITE_REG(par, PM3YBias, 0x0);
+	PM3_WRITE_REG(par, PM3DeltaControl, 0x0);
+
+	PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);
+
+	PM3_WRITE_REG(par, PM3FBDestReadEnables,
+			   PM3FBDestReadEnables_E(0xff) |
+			   PM3FBDestReadEnables_R(0xff) |
+			   PM3FBDestReadEnables_ReferenceAlpha(0xff));
+	PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
+	PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
+	PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
+			   PM3FBDestReadBufferWidth_Width(width));
+
+	PM3_WRITE_REG(par, PM3FBDestReadMode,
+			   PM3FBDestReadMode_ReadEnable |
+			   PM3FBDestReadMode_Enable0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
+			   PM3FBSourceReadBufferWidth_Width(width));
+	PM3_WRITE_REG(par, PM3FBSourceReadMode,
+			   PM3FBSourceReadMode_Blocking |
+			   PM3FBSourceReadMode_ReadEnable);
+
+	PM3_WAIT(par, 2);
+	{
+		/* invert bits in bitmask */
+		unsigned long rm = 1 | (3 << 7);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_8BIT);
+#ifdef __BIG_ENDIAN
+			rm |= 3 << 15;
+#endif
+			break;
+		case 16:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_16BIT);
+#ifdef __BIG_ENDIAN
+			rm |= 2 << 15;
+#endif
+			break;
+		case 32:
+			PM3_WRITE_REG(par, PM3PixelSize,
+					   PM3PixelSize_GLOBAL_32BIT);
+			break;
+		default:
+			DPRINTK(1, "Unsupported depth %d\n",
+				info->var.bits_per_pixel);
+			break;
+		}
+		PM3_WRITE_REG(par, PM3RasterizerMode, rm);
+	}
+
+	PM3_WAIT(par, 20);
+	PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3FBWriteMode,
+			   PM3FBWriteMode_WriteEnable |
+			   PM3FBWriteMode_OpaqueSpan |
+			   PM3FBWriteMode_Enable0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
+	PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
+			   PM3FBWriteBufferWidth_Width(width));
+
+	PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
+	{
+		/* size in lines of FB */
+		unsigned long sofb = info->screen_size /
+			info->fix.line_length;
+		if (sofb > 4095)
+			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
+		else
+			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);
+
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (2 << 3));
+			break;
+		case 16:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (1 << 3));
+			break;
+		case 32:
+			PM3_WRITE_REG(par, PM3DitherMode,
+					   (1 << 10) | (0 << 3));
+			break;
+		default:
+			DPRINTK(1, "Unsupported depth %d\n",
+				info->current_par->depth);
+			break;
+		}
+	}
+
+	PM3_WRITE_REG(par, PM3dXDom, 0x0);
+	PM3_WRITE_REG(par, PM3dXSub, 0x0);
+	PM3_WRITE_REG(par, PM3dY, 1 << 16);
+	PM3_WRITE_REG(par, PM3StartXDom, 0x0);
+	PM3_WRITE_REG(par, PM3StartXSub, 0x0);
+	PM3_WRITE_REG(par, PM3StartY, 0x0);
+	PM3_WRITE_REG(par, PM3Count, 0x0);
+
+/* Disable LocalBuffer. better safe than sorry */
+	PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0);
+	PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0);
+	PM3_WRITE_REG(par, PM3LBWriteMode, 0x0);
+
+	pm3fb_sync(info);
+}
+
+static void pm3fb_fillrect(struct fb_info *info,
+				const struct fb_fillrect *region)
+{
+	struct pm3_par *par = info->par;
+	struct fb_fillrect modded;
+	int vxres, vyres;
+	int rop;
+	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+		((u32 *)info->pseudo_palette)[region->color] : region->color;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(info, region);
+		return;
+	}
+	if (region->rop == ROP_COPY )
+		rop = PM3Config2D_ForegroundROP(0x3); /* GXcopy */
+	else
+		rop = PM3Config2D_ForegroundROP(0x6) | /* GXxor */
+			PM3Config2D_FBDestReadEnable;
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if (!modded.width || !modded.height ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.dx + modded.width  > vxres)
+		modded.width  = vxres - modded.dx;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	if (info->var.bits_per_pixel == 8)
+		color |= color << 8;
+	if (info->var.bits_per_pixel <= 16)
+		color |= color << 16;
+
+	PM3_WAIT(par, 4);
+	/* ROP Ox3 is GXcopy */
+	PM3_WRITE_REG(par, PM3Config2D,
+			PM3Config2D_UseConstantSource |
+			PM3Config2D_ForegroundROPEnable |
+			rop |
+			PM3Config2D_FBWriteEnable);
+
+	PM3_WRITE_REG(par, PM3ForegroundColor, color);
+
+	PM3_WRITE_REG(par, PM3RectanglePosition,
+			PM3RectanglePosition_XOffset(modded.dx) |
+			PM3RectanglePosition_YOffset(modded.dy));
+
+	PM3_WRITE_REG(par, PM3Render2D,
+		      PM3Render2D_XPositive |
+		      PM3Render2D_YPositive |
+		      PM3Render2D_Operation_Normal |
+		      PM3Render2D_SpanOperation |
+		      PM3Render2D_Width(modded.width) |
+		      PM3Render2D_Height(modded.height));
+}
+
+static void pm3fb_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+	struct pm3_par *par = info->par;
+	struct fb_copyarea modded;
+	u32 vxres, vyres;
+	int x_align, o_x, o_y;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	memcpy(&modded, area, sizeof(struct fb_copyarea));
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!modded.width || !modded.height ||
+	    modded.sx >= vxres || modded.sy >= vyres ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.sx + modded.width > vxres)
+		modded.width = vxres - modded.sx;
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.sy + modded.height > vyres)
+		modded.height = vyres - modded.sy;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	o_x = modded.sx - modded.dx;	/*(sx > dx ) ? (sx - dx) : (dx - sx); */
+	o_y = modded.sy - modded.dy;	/*(sy > dy ) ? (sy - dy) : (dy - sy); */
+
+	x_align = (modded.sx & 0x1f);
+
+	PM3_WAIT(par, 6);
+
+	PM3_WRITE_REG(par, PM3Config2D,
+			PM3Config2D_UserScissorEnable |
+			PM3Config2D_ForegroundROPEnable |
+			PM3Config2D_Blocking |
+			PM3Config2D_ForegroundROP(0x3) | /* Ox3 is GXcopy */
+			PM3Config2D_FBWriteEnable);
+
+	PM3_WRITE_REG(par, PM3ScissorMinXY,
+			((modded.dy & 0x0fff) << 16) | (modded.dx & 0x0fff));
+	PM3_WRITE_REG(par, PM3ScissorMaxXY,
+			(((modded.dy + modded.height) & 0x0fff) << 16) |
+			((modded.dx + modded.width) & 0x0fff));
+
+	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset,
+			PM3FBSourceReadBufferOffset_XOffset(o_x) |
+			PM3FBSourceReadBufferOffset_YOffset(o_y));
+
+	PM3_WRITE_REG(par, PM3RectanglePosition,
+			PM3RectanglePosition_XOffset(modded.dx - x_align) |
+			PM3RectanglePosition_YOffset(modded.dy));
+
+	PM3_WRITE_REG(par, PM3Render2D,
+			((modded.sx > modded.dx) ? PM3Render2D_XPositive : 0) |
+			((modded.sy > modded.dy) ? PM3Render2D_YPositive : 0) |
+			PM3Render2D_Operation_Normal |
+			PM3Render2D_SpanOperation |
+			PM3Render2D_FBSourceReadEnable |
+			PM3Render2D_Width(modded.width + x_align) |
+			PM3Render2D_Height(modded.height));
+}
+
+static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct pm3_par *par = info->par;
+	u32 height = image->height;
+	u32 fgx, bgx;
+	const u32 *src = (const u32 *)image->data;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_imageblit(info, image);
+		return;
+	}
+	switch (info->fix.visual) {
+	case FB_VISUAL_PSEUDOCOLOR:
+		fgx = image->fg_color;
+		bgx = image->bg_color;
+		break;
+	case FB_VISUAL_TRUECOLOR:
+	default:
+		fgx = par->palette[image->fg_color];
+		bgx = par->palette[image->bg_color];
+		break;
+	}
+	if (image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	if (info->var.bits_per_pixel == 8) {
+		fgx |= fgx << 8;
+		bgx |= bgx << 8;
+	}
+	if (info->var.bits_per_pixel <= 16) {
+		fgx |= fgx << 16;
+		bgx |= bgx << 16;
+	}
+
+	PM3_WAIT(par, 7);
+
+	PM3_WRITE_REG(par, PM3ForegroundColor, fgx);
+	PM3_WRITE_REG(par, PM3BackgroundColor, bgx);
+
+	/* ROP Ox3 is GXcopy */
+	PM3_WRITE_REG(par, PM3Config2D,
+			PM3Config2D_UserScissorEnable |
+			PM3Config2D_UseConstantSource |
+			PM3Config2D_ForegroundROPEnable |
+			PM3Config2D_ForegroundROP(0x3) |
+			PM3Config2D_OpaqueSpan |
+			PM3Config2D_FBWriteEnable);
+	PM3_WRITE_REG(par, PM3ScissorMinXY,
+			((image->dy & 0x0fff) << 16) | (image->dx & 0x0fff));
+	PM3_WRITE_REG(par, PM3ScissorMaxXY,
+			(((image->dy + image->height) & 0x0fff) << 16) |
+			((image->dx + image->width) & 0x0fff));
+	PM3_WRITE_REG(par, PM3RectanglePosition,
+			PM3RectanglePosition_XOffset(image->dx) |
+			PM3RectanglePosition_YOffset(image->dy));
+	PM3_WRITE_REG(par, PM3Render2D,
+			PM3Render2D_XPositive |
+			PM3Render2D_YPositive |
+			PM3Render2D_Operation_SyncOnBitMask |
+			PM3Render2D_SpanOperation |
+			PM3Render2D_Width(image->width) |
+			PM3Render2D_Height(image->height));
+
+
+	while (height--) {
+		int width = ((image->width + 7) >> 3)
+				+ info->pixmap.scan_align - 1;
+		width >>= 2;
+
+		while (width >= PM3_FIFO_SIZE) {
+			int i = PM3_FIFO_SIZE - 1;
+
+			PM3_WAIT(par, PM3_FIFO_SIZE);
+			while (i--) {
+				PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
+				src++;
+			}
+			width -= PM3_FIFO_SIZE - 1;
+		}
+
+		PM3_WAIT(par, width + 1);
+		while (width--) {
+			PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
+			src++;
+		}
+	}
+}
+/* end of acceleration functions */
+
+/*
+ *	Hardware Cursor support.
+ */
+static const u8 cursor_bits_lookup[16] = {
+	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
+	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
+};
+
+static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct pm3_par *par = info->par;
+	u8 mode;
+
+	if (!hwcursor)
+		return -EINVAL;	/* just to force soft_cursor() call */
+
+	/* Too large of a cursor or wrong bpp :-( */
+	if (cursor->image.width > 64 ||
+	    cursor->image.height > 64 ||
+	    cursor->image.depth > 1)
+		return -EINVAL;
+
+	mode = PM3RD_CursorMode_TYPE_X;
+	if (cursor->enable)
+		 mode |= PM3RD_CursorMode_CURSOR_ENABLE;
+
+	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode);
+
+	/*
+	 * If the cursor is not be changed this means either we want the
+	 * current cursor state (if enable is set) or we want to query what
+	 * we can do with the cursor (if enable is not set)
+	 */
+	if (!cursor->set)
+		return 0;
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		int x = cursor->image.dx - info->var.xoffset;
+		int y = cursor->image.dy - info->var.yoffset;
+
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff);
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf);
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff);
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf);
+	}
+
+	if (cursor->set & FB_CUR_SETHOT) {
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX,
+				  cursor->hot.x & 0x3f);
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY,
+				  cursor->hot.y & 0x3f);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		u32 fg_idx = cursor->image.fg_color;
+		u32 bg_idx = cursor->image.bg_color;
+		struct fb_cmap cmap = info->cmap;
+
+		/* the X11 driver says one should use these color registers */
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39),
+				  cmap.red[fg_idx] >> 8 );
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40),
+				  cmap.green[fg_idx] >> 8 );
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41),
+				  cmap.blue[fg_idx] >> 8 );
+
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42),
+				  cmap.red[bg_idx] >> 8 );
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43),
+				  cmap.green[bg_idx] >> 8 );
+		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44),
+				  cmap.blue[bg_idx] >> 8 );
+	}
+
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+		u8 *bitmap = (u8 *)cursor->image.data;
+		u8 *mask = (u8 *)cursor->mask;
+		int i;
+		int pos = PM3RD_CursorPattern(0);
+
+		for (i = 0; i < cursor->image.height; i++) {
+			int j = (cursor->image.width + 7) >> 3;
+			int k = 8 - j;
+
+			for (; j > 0; j--) {
+				u8 data = *bitmap ^ *mask;
+
+				if (cursor->rop == ROP_COPY)
+					data = *mask & *bitmap;
+				/* Upper 4 bits of bitmap data */
+				PM3_WRITE_DAC_REG(par, pos++,
+					cursor_bits_lookup[data >> 4] |
+					(cursor_bits_lookup[*mask >> 4] << 1));
+				/* Lower 4 bits of bitmap */
+				PM3_WRITE_DAC_REG(par, pos++,
+					cursor_bits_lookup[data & 0xf] |
+					(cursor_bits_lookup[*mask & 0xf] << 1));
+				bitmap++;
+				mask++;
+			}
+			for (; k > 0; k--) {
+				PM3_WRITE_DAC_REG(par, pos++, 0);
+				PM3_WRITE_DAC_REG(par, pos++, 0);
+			}
+		}
+		while (pos < PM3RD_CursorPattern(1024))
+			PM3_WRITE_DAC_REG(par, pos++, 0);
+	}
+	return 0;
+}
+
+/* write the mode to registers */
+static void pm3fb_write_mode(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	char tempsync = 0x00;
+	char tempmisc = 0x00;
+	const u32 hsstart = info->var.right_margin;
+	const u32 hsend = hsstart + info->var.hsync_len;
+	const u32 hbend = hsend + info->var.left_margin;
+	const u32 xres = (info->var.xres + 31) & ~31;
+	const u32 htotal = xres + hbend;
+	const u32 vsstart = info->var.lower_margin;
+	const u32 vsend = vsstart + info->var.vsync_len;
+	const u32 vbend = vsend + info->var.upper_margin;
+	const u32 vtotal = info->var.yres + vbend;
+	const u32 width = (info->var.xres_virtual + 7) & ~7;
+	const unsigned bpp = info->var.bits_per_pixel;
+
+	PM3_WAIT(par, 20);
+	PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
+	PM3_WRITE_REG(par, PM3Aperture0, 0x00000000);
+	PM3_WRITE_REG(par, PM3Aperture1, 0x00000000);
+	PM3_WRITE_REG(par, PM3FIFODis, 0x00000007);
+
+	PM3_WRITE_REG(par, PM3HTotal,
+			   pm3fb_shift_bpp(bpp, htotal - 1));
+	PM3_WRITE_REG(par, PM3HsEnd,
+			   pm3fb_shift_bpp(bpp, hsend));
+	PM3_WRITE_REG(par, PM3HsStart,
+			   pm3fb_shift_bpp(bpp, hsstart));
+	PM3_WRITE_REG(par, PM3HbEnd,
+			   pm3fb_shift_bpp(bpp, hbend));
+	PM3_WRITE_REG(par, PM3HgEnd,
+			   pm3fb_shift_bpp(bpp, hbend));
+	PM3_WRITE_REG(par, PM3ScreenStride,
+			   pm3fb_shift_bpp(bpp, width));
+	PM3_WRITE_REG(par, PM3VTotal, vtotal - 1);
+	PM3_WRITE_REG(par, PM3VsEnd, vsend - 1);
+	PM3_WRITE_REG(par, PM3VsStart, vsstart - 1);
+	PM3_WRITE_REG(par, PM3VbEnd, vbend);
+
+	switch (bpp) {
+	case 8:
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
+				   PM3ByApertureMode_PIXELSIZE_8BIT);
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
+				   PM3ByApertureMode_PIXELSIZE_8BIT);
+		break;
+
+	case 16:
+#ifndef __BIG_ENDIAN
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
+				   PM3ByApertureMode_PIXELSIZE_16BIT);
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
+				   PM3ByApertureMode_PIXELSIZE_16BIT);
+#else
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
+				   PM3ByApertureMode_PIXELSIZE_16BIT |
+				   PM3ByApertureMode_BYTESWAP_BADC);
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
+				   PM3ByApertureMode_PIXELSIZE_16BIT |
+				   PM3ByApertureMode_BYTESWAP_BADC);
+#endif /* ! __BIG_ENDIAN */
+		break;
+
+	case 32:
+#ifndef __BIG_ENDIAN
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
+				   PM3ByApertureMode_PIXELSIZE_32BIT);
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
+				   PM3ByApertureMode_PIXELSIZE_32BIT);
+#else
+		PM3_WRITE_REG(par, PM3ByAperture1Mode,
+				   PM3ByApertureMode_PIXELSIZE_32BIT |
+				   PM3ByApertureMode_BYTESWAP_DCBA);
+		PM3_WRITE_REG(par, PM3ByAperture2Mode,
+				   PM3ByApertureMode_PIXELSIZE_32BIT |
+				   PM3ByApertureMode_BYTESWAP_DCBA);
+#endif /* ! __BIG_ENDIAN */
+		break;
+
+	default:
+		DPRINTK("Unsupported depth %d\n", bpp);
+		break;
+	}
+
+	/*
+	 * Oxygen VX1 - it appears that setting PM3VideoControl and
+	 * then PM3RD_SyncControl to the same SYNC settings undoes
+	 * any net change - they seem to xor together.  Only set the
+	 * sync options in PM3RD_SyncControl.  --rmk
+	 */
+	{
+		unsigned int video = par->video;
+
+		video &= ~(PM3VideoControl_HSYNC_MASK |
+			   PM3VideoControl_VSYNC_MASK);
+		video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
+			 PM3VideoControl_VSYNC_ACTIVE_HIGH;
+		PM3_WRITE_REG(par, PM3VideoControl, video);
+	}
+	PM3_WRITE_REG(par, PM3VClkCtl,
+			   (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
+	PM3_WRITE_REG(par, PM3ScreenBase, par->base);
+	PM3_WRITE_REG(par, PM3ChipConfig,
+			   (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
+
+	wmb();
+	{
+		unsigned char uninitialized_var(m);	/* ClkPreScale */
+		unsigned char uninitialized_var(n);	/* ClkFeedBackScale */
+		unsigned char uninitialized_var(p);	/* ClkPostScale */
+		unsigned long pixclock = PICOS2KHZ(info->var.pixclock);
+
+		(void)pm3fb_calculate_clock(pixclock, &m, &n, &p);
+
+		DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n",
+			pixclock, (int) m, (int) n, (int) p);
+
+		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m);
+		PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n);
+		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p);
+	}
+	/*
+	   PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00);
+	 */
+	/*
+	   PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00);
+	 */
+	if ((par->video & PM3VideoControl_HSYNC_MASK) ==
+	    PM3VideoControl_HSYNC_ACTIVE_HIGH)
+		tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
+	if ((par->video & PM3VideoControl_VSYNC_MASK) ==
+	    PM3VideoControl_VSYNC_ACTIVE_HIGH)
+		tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
+
+	PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync);
+	DPRINTK("PM3RD_SyncControl: %d\n", tempsync);
+
+	PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
+
+	switch (pm3fb_depth(&info->var)) {
+	case 8:
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
+				  PM3RD_PixelSize_8_BIT_PIXELS);
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
+				  PM3RD_ColorFormat_CI8_COLOR |
+				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
+		tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
+		break;
+	case 12:
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
+				  PM3RD_PixelSize_16_BIT_PIXELS);
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
+				  PM3RD_ColorFormat_4444_COLOR |
+				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
+				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
+		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
+			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
+		break;
+	case 15:
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
+				  PM3RD_PixelSize_16_BIT_PIXELS);
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
+				  PM3RD_ColorFormat_5551_FRONT_COLOR |
+				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
+				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
+		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
+			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
+		break;
+	case 16:
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
+				  PM3RD_PixelSize_16_BIT_PIXELS);
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
+				  PM3RD_ColorFormat_565_FRONT_COLOR |
+				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
+				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
+		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
+			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
+		break;
+	case 32:
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
+				  PM3RD_PixelSize_32_BIT_PIXELS);
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
+				  PM3RD_ColorFormat_8888_COLOR |
+				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
+		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
+			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
+		break;
+	}
+	PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc);
+}
+
+/*
+ * hardware independent functions
+ */
+static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 lpitch;
+	unsigned bpp = var->red.length + var->green.length
+			+ var->blue.length + var->transp.length;
+
+	if (bpp != var->bits_per_pixel) {
+		/* set predefined mode for bits_per_pixel settings */
+
+		switch (var->bits_per_pixel) {
+		case 8:
+			var->red.length = 8;
+			var->green.length = 8;
+			var->blue.length = 8;
+			var->red.offset = 0;
+			var->green.offset = 0;
+			var->blue.offset = 0;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+			break;
+		case 16:
+			var->red.length = 5;
+			var->blue.length = 5;
+			var->green.length = 6;
+			var->transp.length = 0;
+			break;
+		case 32:
+			var->red.length = 8;
+			var->green.length = 8;
+			var->blue.length = 8;
+			var->transp.length = 8;
+			break;
+		default:
+			DPRINTK("depth not supported: %u\n",
+				var->bits_per_pixel);
+			return -EINVAL;
+		}
+	}
+	/* it is assumed BGRA order */
+	if (var->bits_per_pixel > 8 ) {
+		var->blue.offset = 0;
+		var->green.offset = var->blue.length;
+		var->red.offset = var->green.offset + var->green.length;
+		var->transp.offset = var->red.offset + var->red.length;
+	}
+	var->height = -1;
+	var->width = -1;
+
+	if (var->xres != var->xres_virtual) {
+		DPRINTK("virtual x resolution != "
+			"physical x resolution not supported\n");
+		return -EINVAL;
+	}
+
+	if (var->yres > var->yres_virtual) {
+		DPRINTK("virtual y resolution < "
+			"physical y resolution not possible\n");
+		return -EINVAL;
+	}
+
+	if (var->xoffset) {
+		DPRINTK("xoffset not supported\n");
+		return -EINVAL;
+	}
+
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		DPRINTK("interlace not supported\n");
+		return -EINVAL;
+	}
+
+	var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */
+	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
+
+	if (var->xres < 200 || var->xres > 2048) {
+		DPRINTK("width not supported: %u\n", var->xres);
+		return -EINVAL;
+	}
+
+	if (var->yres < 200 || var->yres > 4095) {
+		DPRINTK("height not supported: %u\n", var->yres);
+		return -EINVAL;
+	}
+
+	if (lpitch * var->yres_virtual > info->fix.smem_len) {
+		DPRINTK("no memory for screen (%ux%ux%u)\n",
+			var->xres, var->yres_virtual, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) {
+		DPRINTK("pixclock too high (%ldKHz)\n",
+			PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+
+	var->accel_flags = 0;	/* Can't mmap if this is on */
+
+	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
+		var->xres, var->yres, var->bits_per_pixel);
+	return 0;
+}
+
+static int pm3fb_set_par(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	const u32 xres = (info->var.xres + 31) & ~31;
+	const unsigned bpp = info->var.bits_per_pixel;
+
+	par->base = pm3fb_shift_bpp(bpp, (info->var.yoffset * xres)
+					+ info->var.xoffset);
+	par->video = 0;
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;
+	else
+		par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW;
+
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;
+	else
+		par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW;
+
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+		par->video |= PM3VideoControl_LINE_DOUBLE_ON;
+
+	if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+		par->video |= PM3VideoControl_ENABLE;
+	else
+		DPRINTK("PM3Video disabled\n");
+
+	switch (bpp) {
+	case 8:
+		par->video |= PM3VideoControl_PIXELSIZE_8BIT;
+		break;
+	case 16:
+		par->video |= PM3VideoControl_PIXELSIZE_16BIT;
+		break;
+	case 32:
+		par->video |= PM3VideoControl_PIXELSIZE_32BIT;
+		break;
+	default:
+		DPRINTK("Unsupported depth\n");
+		break;
+	}
+
+	info->fix.visual =
+		(bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = ((info->var.xres_virtual + 7)  >> 3) * bpp;
+
+/*	pm3fb_clear_memory(info, 0);*/
+	pm3fb_clear_colormap(par, 0, 0, 0);
+	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, 0);
+	pm3fb_init_engine(info);
+	pm3fb_write_mode(info);
+	return 0;
+}
+
+static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+
+	if (regno >= 256)  /* no. of hw registers */
+	   return -EINVAL;
+
+	/* grayscale works only partially under directcolor */
+	/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+	if (info->var.grayscale)
+	   red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of DAC
+	 *   pseudo_palette[X] is programmed to (X << red.offset) |
+	 *					(X << green.offset) |
+	 *					(X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 *   color depth = SUM(var->{color}.length)
+	 *
+	 * Pseudocolor:
+	 *	var->{color}.offset is 0
+	 *	var->{color}.length contains width of DAC or the number
+	 *			of unique colors available (color depth)
+	 *	pseudo_palette is not used
+	 *	RAMDAC[X] is programmed to (red, green, blue)
+	 *	color depth = var->{color}.length
+	 */
+
+	/*
+	 * This is the point where the color is converted to something that
+	 * is acceptable by the hardware.
+	 */
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
+	red = CNVT_TOHW(red, info->var.red.length);
+	green = CNVT_TOHW(green, info->var.green.length);
+	blue = CNVT_TOHW(blue, info->var.blue.length);
+	transp = CNVT_TOHW(transp, info->var.transp.length);
+#undef CNVT_TOHW
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		v = (red << info->var.red.offset) |
+			(green << info->var.green.offset) |
+			(blue << info->var.blue.offset) |
+			(transp << info->var.transp.offset);
+
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+		case 32:
+			((u32 *)(info->pseudo_palette))[regno] = v;
+			break;
+		}
+		return 0;
+	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+		pm3fb_set_color(par, regno, red, green, blue);
+
+	return 0;
+}
+
+static int pm3fb_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	const u32 xres = (info->var.xres + 31) & ~31;
+
+	par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
+					(var->yoffset * xres)
+					+ var->xoffset);
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par, PM3ScreenBase, par->base);
+	return 0;
+}
+
+static int pm3fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	u32 video = par->video;
+
+	/*
+	 * Oxygen VX1 - it appears that setting PM3VideoControl and
+	 * then PM3RD_SyncControl to the same SYNC settings undoes
+	 * any net change - they seem to xor together.  Only set the
+	 * sync options in PM3RD_SyncControl.  --rmk
+	 */
+	video &= ~(PM3VideoControl_HSYNC_MASK |
+		   PM3VideoControl_VSYNC_MASK);
+	video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
+		 PM3VideoControl_VSYNC_ACTIVE_HIGH;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		video |= PM3VideoControl_ENABLE;
+		break;
+	case FB_BLANK_NORMAL:
+		video &= ~PM3VideoControl_ENABLE;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		video &= ~(PM3VideoControl_HSYNC_MASK |
+			  PM3VideoControl_BLANK_ACTIVE_LOW);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		video &= ~(PM3VideoControl_VSYNC_MASK |
+			  PM3VideoControl_BLANK_ACTIVE_LOW);
+		break;
+	case FB_BLANK_POWERDOWN:
+		video &= ~(PM3VideoControl_HSYNC_MASK |
+			  PM3VideoControl_VSYNC_MASK |
+			  PM3VideoControl_BLANK_ACTIVE_LOW);
+		break;
+	default:
+		DPRINTK("Unsupported blanking %d\n", blank_mode);
+		return 1;
+	}
+
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par, PM3VideoControl, video);
+	return 0;
+}
+
+	/*
+	 *  Frame buffer operations
+	 */
+
+static struct fb_ops pm3fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= pm3fb_check_var,
+	.fb_set_par	= pm3fb_set_par,
+	.fb_setcolreg	= pm3fb_setcolreg,
+	.fb_pan_display	= pm3fb_pan_display,
+	.fb_fillrect	= pm3fb_fillrect,
+	.fb_copyarea	= pm3fb_copyarea,
+	.fb_imageblit	= pm3fb_imageblit,
+	.fb_blank	= pm3fb_blank,
+	.fb_sync	= pm3fb_sync,
+	.fb_cursor	= pm3fb_cursor,
+};
+
+/* ------------------------------------------------------------------------- */
+
+	/*
+	 *  Initialization
+	 */
+
+/* mmio register are already mapped when this function is called */
+/* the pm3fb_fix.smem_start is also set */
+static unsigned long pm3fb_size_memory(struct pm3_par *par)
+{
+	unsigned long	memsize = 0;
+	unsigned long	tempBypass, i, temp1, temp2;
+	unsigned char	__iomem *screen_mem;
+
+	pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */
+	/* Linear frame buffer - request region and map it. */
+	if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
+				 "pm3fb smem")) {
+		printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
+		return 0;
+	}
+	screen_mem =
+		ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+	if (!screen_mem) {
+		printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
+		release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+		return 0;
+	}
+
+	/* TODO: card-specific stuff, *before* accessing *any* FB memory */
+	/* For Appian Jeronimo 2000 board second head */
+
+	tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask);
+
+	DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
+
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
+
+	/* pm3 split up memory, replicates, and do a lot of
+	 * nasty stuff IMHO ;-)
+	 */
+	for (i = 0; i < 32; i++) {
+		fb_writel(i * 0x00345678,
+			  (screen_mem + (i * 1048576)));
+		mb();
+		temp1 = fb_readl((screen_mem + (i * 1048576)));
+
+		/* Let's check for wrapover, write will fail at 16MB boundary */
+		if (temp1 == (i * 0x00345678))
+			memsize = i;
+		else
+			break;
+	}
+
+	DPRINTK("First detect pass already got %ld MB\n", memsize + 1);
+
+	if (memsize + 1 == i) {
+		for (i = 0; i < 32; i++) {
+			/* Clear first 32MB ; 0 is 0, no need to byteswap */
+			writel(0x0000000, (screen_mem + (i * 1048576)));
+		}
+		wmb();
+
+		for (i = 32; i < 64; i++) {
+			fb_writel(i * 0x00345678,
+				  (screen_mem + (i * 1048576)));
+			mb();
+			temp1 =
+			    fb_readl((screen_mem + (i * 1048576)));
+			temp2 =
+			    fb_readl((screen_mem + ((i - 32) * 1048576)));
+			/* different value, different RAM... */
+			if ((temp1 == (i * 0x00345678)) && (temp2 == 0))
+				memsize = i;
+			else
+				break;
+		}
+	}
+	DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
+
+	PM3_WAIT(par, 1);
+	PM3_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
+
+	iounmap(screen_mem);
+	release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+	memsize = 1048576 * (memsize + 1);
+
+	DPRINTK("Returning 0x%08lx bytes\n", memsize);
+
+	return memsize;
+}
+
+static int pm3fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct pm3_par *par;
+	struct device *device = &dev->dev; /* for pci drivers */
+	int err;
+	int retval = -ENXIO;
+
+	err = pci_enable_device(dev);
+	if (err) {
+		printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err);
+		return err;
+	}
+	/*
+	 * Dynamically allocate info and par
+	 */
+	info = framebuffer_alloc(sizeof(struct pm3_par), device);
+
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+
+	/*
+	 * Here we set the screen_base to the virtual memory address
+	 * for the framebuffer.
+	 */
+	pm3fb_fix.mmio_start = pci_resource_start(dev, 0);
+	pm3fb_fix.mmio_len = PM3_REGS_SIZE;
+#if defined(__BIG_ENDIAN)
+	pm3fb_fix.mmio_start += PM3_REGS_SIZE;
+	DPRINTK("Adjusting register base for big-endian.\n");
+#endif
+
+	/* Registers - request region and map it. */
+	if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len,
+				 "pm3fb regbase")) {
+		printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n");
+		goto err_exit_neither;
+	}
+	par->v_regs =
+		ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+	if (!par->v_regs) {
+		printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n",
+			pm3fb_fix.id);
+		release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+		goto err_exit_neither;
+	}
+
+	/* Linear frame buffer - request region and map it. */
+	pm3fb_fix.smem_start = pci_resource_start(dev, 1);
+	pm3fb_fix.smem_len = pm3fb_size_memory(par);
+	if (!pm3fb_fix.smem_len) {
+		printk(KERN_WARNING "pm3fb: Can't find memory on board.\n");
+		goto err_exit_mmio;
+	}
+	if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
+				 "pm3fb smem")) {
+		printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
+		goto err_exit_mmio;
+	}
+	info->screen_base =
+		ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
+		release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+		goto err_exit_mmio;
+	}
+	info->screen_size = pm3fb_fix.smem_len;
+
+#ifdef CONFIG_MTRR
+	if (!nomtrr)
+		par->mtrr_handle = mtrr_add(pm3fb_fix.smem_start,
+						pm3fb_fix.smem_len,
+						MTRR_TYPE_WRCOMB, 1);
+#endif
+	info->fbops = &pm3fb_ops;
+
+	par->video = PM3_READ_REG(par, PM3VideoControl);
+
+	info->fix = pm3fb_fix;
+	info->pseudo_palette = par->palette;
+	info->flags = FBINFO_DEFAULT |
+			FBINFO_HWACCEL_XPAN |
+			FBINFO_HWACCEL_YPAN |
+			FBINFO_HWACCEL_COPYAREA |
+			FBINFO_HWACCEL_IMAGEBLIT |
+			FBINFO_HWACCEL_FILLRECT;
+
+	if (noaccel) {
+		printk(KERN_DEBUG "disabling acceleration\n");
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+	info->pixmap.addr = kmalloc(PM3_PIXMAP_SIZE, GFP_KERNEL);
+	if (!info->pixmap.addr) {
+		retval = -ENOMEM;
+		goto err_exit_pixmap;
+	}
+	info->pixmap.size = PM3_PIXMAP_SIZE;
+	info->pixmap.buf_align = 4;
+	info->pixmap.scan_align = 4;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	/*
+	 * This should give a reasonable default video mode. The following is
+	 * done when we can set a video mode.
+	 */
+	if (!mode_option)
+		mode_option = "640x480@60";
+
+	retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+
+	if (!retval || retval == 4) {
+		retval = -EINVAL;
+		goto err_exit_both;
+	}
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		retval = -ENOMEM;
+		goto err_exit_both;
+	}
+
+	/*
+	 * For drivers that can...
+	 */
+	pm3fb_check_var(&info->var, info);
+
+	if (register_framebuffer(info) < 0) {
+		retval = -EINVAL;
+		goto err_exit_all;
+	}
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	pci_set_drvdata(dev, info);
+	return 0;
+
+ err_exit_all:
+	fb_dealloc_cmap(&info->cmap);
+ err_exit_both:
+	kfree(info->pixmap.addr);
+ err_exit_pixmap:
+	iounmap(info->screen_base);
+	release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ err_exit_mmio:
+	iounmap(par->v_regs);
+	release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+ err_exit_neither:
+	framebuffer_release(info);
+	return retval;
+}
+
+	/*
+	 *  Cleanup
+	 */
+static void pm3fb_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+
+	if (info) {
+		struct fb_fix_screeninfo *fix = &info->fix;
+		struct pm3_par *par = info->par;
+
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr_handle >= 0)
+		mtrr_del(par->mtrr_handle, info->fix.smem_start,
+			 info->fix.smem_len);
+#endif /* CONFIG_MTRR */
+		iounmap(info->screen_base);
+		release_mem_region(fix->smem_start, fix->smem_len);
+		iounmap(par->v_regs);
+		release_mem_region(fix->mmio_start, fix->mmio_len);
+
+		kfree(info->pixmap.addr);
+		framebuffer_release(info);
+	}
+}
+
+static struct pci_device_id pm3fb_id_table[] = {
+	{ PCI_VENDOR_ID_3DLABS, 0x0a,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, }
+};
+
+/* For PCI drivers */
+static struct pci_driver pm3fb_driver = {
+	.name =		"pm3fb",
+	.id_table =	pm3fb_id_table,
+	.probe =	pm3fb_probe,
+	.remove =	pm3fb_remove,
+};
+
+MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
+
+#ifndef MODULE
+	/*
+	 *  Setup
+	 */
+
+/*
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+static int __init pm3fb_setup(char *options)
+{
+	char *this_opt;
+
+	/* Parse user specified options (`video=pm3fb:') */
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		else if (!strncmp(this_opt, "noaccel", 7))
+			noaccel = 1;
+		else if (!strncmp(this_opt, "hwcursor=", 9))
+			hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
+#ifdef CONFIG_MTRR
+		else if (!strncmp(this_opt, "nomtrr", 6))
+			nomtrr = 1;
+#endif
+		else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+#endif /* MODULE */
+
+static int __init pm3fb_init(void)
+{
+	/*
+	 *  For kernel boot options (in 'video=pm3fb:<options>' format)
+	 */
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pm3fb", &option))
+		return -ENODEV;
+	pm3fb_setup(option);
+#endif
+
+	return pci_register_driver(&pm3fb_driver);
+}
+
+#ifdef MODULE
+static void __exit pm3fb_exit(void)
+{
+	pci_unregister_driver(&pm3fb_driver);
+}
+
+module_exit(pm3fb_exit);
+#endif
+module_init(pm3fb_init);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "Disable acceleration");
+module_param(hwcursor, int, 0644);
+MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
+			"(1=enable, 0=disable, default=1)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
+#endif
+
+MODULE_DESCRIPTION("Permedia3 framebuffer device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/pmag-aa-fb.c b/drivers/video/fbdev/pmag-aa-fb.c
new file mode 100644
index 000000000000..838424817de2
--- /dev/null
+++ b/drivers/video/fbdev/pmag-aa-fb.c
@@ -0,0 +1,510 @@
+/*
+ *	linux/drivers/video/pmag-aa-fb.c
+ *	Copyright 2002 Karsten Merker <merker@debian.org>
+ *
+ *	PMAG-AA TurboChannel framebuffer card support ... derived from
+ *	pmag-ba-fb.c, which is Copyright (C) 1999, 2000, 2001 by
+ *	Michael Engel <engel@unix-ag.org>, Karsten Merker <merker@debian.org>
+ *	and Harald Koerfgen <hkoerfg@web.de>, which itself is derived from
+ *	"HP300 Topcat framebuffer support (derived from macfb of all things)
+ *	Phil Blundell <philb@gnu.org> 1998"
+ *
+ *	This file is subject to the terms and conditions of the GNU General
+ *	Public License.  See the file COPYING in the main directory of this
+ *	archive for more details.
+ *
+ *	2002-09-28  Karsten Merker <merker@linuxtag.org>
+ *		Version 0.01: First try to get a PMAG-AA running.
+ *
+ *	2003-02-24  Thiemo Seufer  <seufer@csv.ica.uni-stuttgart.de>
+ *		Version 0.02: Major code cleanup.
+ *
+ *	2003-09-21  Thiemo Seufer  <seufer@csv.ica.uni-stuttgart.de>
+ *		Hardware cursor support.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+
+#include <asm/bootinfo.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/tc.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+
+#include "bt455.h"
+#include "bt431.h"
+
+/* Version information */
+#define DRIVER_VERSION "0.02"
+#define DRIVER_AUTHOR "Karsten Merker <merker@linuxtag.org>"
+#define DRIVER_DESCRIPTION "PMAG-AA Framebuffer Driver"
+
+/* Prototypes */
+static int aafb_set_var(struct fb_var_screeninfo *var, int con,
+			struct fb_info *info);
+
+/*
+ * Bt455 RAM DAC register base offset (rel. to TC slot base address).
+ */
+#define PMAG_AA_BT455_OFFSET		0x100000
+
+/*
+ * Bt431 cursor generator offset (rel. to TC slot base address).
+ */
+#define PMAG_AA_BT431_OFFSET		0x180000
+
+/*
+ * Begin of PMAG-AA framebuffer memory relative to TC slot address,
+ * resolution is 1280x1024x1 (8 bits deep, but only LSB is used).
+ */
+#define PMAG_AA_ONBOARD_FBMEM_OFFSET	0x200000
+
+struct aafb_cursor {
+	struct timer_list timer;
+	int enable;
+	int on;
+	int vbl_cnt;
+	int blink_rate;
+	u16 x, y, width, height;
+};
+
+#define CURSOR_TIMER_FREQ	(HZ / 50)
+#define CURSOR_BLINK_RATE	(20)
+#define CURSOR_DRAW_DELAY	(2)
+
+struct aafb_info {
+	struct fb_info info;
+	struct display disp;
+	struct aafb_cursor cursor;
+	struct bt455_regs *bt455;
+	struct bt431_regs *bt431;
+	unsigned long fb_start;
+	unsigned long fb_size;
+	unsigned long fb_line_length;
+};
+
+/*
+ * Max 3 TURBOchannel slots -> max 3 PMAG-AA.
+ */
+static struct aafb_info my_fb_info[3];
+
+static struct aafb_par {
+} current_par;
+
+static int currcon = -1;
+
+static void aafb_set_cursor(struct aafb_info *info, int on)
+{
+	struct aafb_cursor *c = &info->cursor;
+
+	if (on) {
+		bt431_position_cursor(info->bt431, c->x, c->y);
+		bt431_enable_cursor(info->bt431);
+	} else
+		bt431_erase_cursor(info->bt431);
+}
+
+static void aafbcon_cursor(struct display *disp, int mode, int x, int y)
+{
+	struct aafb_info *info = (struct aafb_info *)disp->fb_info;
+	struct aafb_cursor *c = &info->cursor;
+
+	x *= fontwidth(disp);
+	y *= fontheight(disp);
+
+	if (c->x == x && c->y == y && (mode == CM_ERASE) == !c->enable)
+		return;
+
+	c->enable = 0;
+	if (c->on)
+		aafb_set_cursor(info, 0);
+	c->x = x - disp->var.xoffset;
+	c->y = y - disp->var.yoffset;
+
+	switch (mode) {
+		case CM_ERASE:
+			c->on = 0;
+			break;
+		case CM_DRAW:
+		case CM_MOVE:
+			if (c->on)
+				aafb_set_cursor(info, c->on);
+			else
+				c->vbl_cnt = CURSOR_DRAW_DELAY;
+			c->enable = 1;
+			break;
+	}
+}
+
+static int aafbcon_set_font(struct display *disp, int width, int height)
+{
+	struct aafb_info *info = (struct aafb_info *)disp->fb_info;
+	struct aafb_cursor *c = &info->cursor;
+	u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info);
+
+	if (width > 64 || height > 64 || width < 0 || height < 0)
+		return -EINVAL;
+
+	c->height = height;
+	c->width = width;
+
+	bt431_set_font(info->bt431, fgc, width, height);
+
+	return 1;
+}
+
+static void aafb_cursor_timer_handler(unsigned long data)
+{
+	struct aafb_info *info = (struct aafb_info *)data;
+	struct aafb_cursor *c = &info->cursor;
+
+	if (!c->enable)
+		goto out;
+
+	if (c->vbl_cnt && --c->vbl_cnt == 0) {
+		c->on ^= 1;
+		aafb_set_cursor(info, c->on);
+		c->vbl_cnt = c->blink_rate;
+	}
+
+out:
+	c->timer.expires = jiffies + CURSOR_TIMER_FREQ;
+	add_timer(&c->timer);
+}
+
+static void __init aafb_cursor_init(struct aafb_info *info)
+{
+	struct aafb_cursor *c = &info->cursor;
+
+	c->enable = 1;
+	c->on = 1;
+	c->x = c->y = 0;
+	c->width = c->height = 0;
+	c->vbl_cnt = CURSOR_DRAW_DELAY;
+	c->blink_rate = CURSOR_BLINK_RATE;
+
+	init_timer(&c->timer);
+	c->timer.data = (unsigned long)info;
+	c->timer.function = aafb_cursor_timer_handler;
+	mod_timer(&c->timer, jiffies + CURSOR_TIMER_FREQ);
+}
+
+static void __exit aafb_cursor_exit(struct aafb_info *info)
+{
+	struct aafb_cursor *c = &info->cursor;
+
+	del_timer_sync(&c->timer);
+}
+
+static struct display_switch aafb_switch8 = {
+	.setup = fbcon_cfb8_setup,
+	.bmove = fbcon_cfb8_bmove,
+	.clear = fbcon_cfb8_clear,
+	.putc = fbcon_cfb8_putc,
+	.putcs = fbcon_cfb8_putcs,
+	.revc = fbcon_cfb8_revc,
+	.cursor = aafbcon_cursor,
+	.set_font = aafbcon_set_font,
+	.clear_margins = fbcon_cfb8_clear_margins,
+	.fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static void aafb_get_par(struct aafb_par *par)
+{
+	*par = current_par;
+}
+
+static int aafb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			struct fb_info *info)
+{
+	struct aafb_info *ip = (struct aafb_info *)info;
+
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strcpy(fix->id, "PMAG-AA");
+	fix->smem_start = ip->fb_start;
+	fix->smem_len = ip->fb_size;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 1;
+	fix->visual = FB_VISUAL_MONO10;
+	fix->line_length = 1280;
+	fix->accel = FB_ACCEL_NONE;
+
+	return 0;
+}
+
+static void aafb_set_disp(struct display *disp, int con,
+			  struct aafb_info *info)
+{
+	struct fb_fix_screeninfo fix;
+
+	disp->fb_info = &info->info;
+	aafb_set_var(&disp->var, con, &info->info);
+	if (disp->conp && disp->conp->vc_sw && disp->conp->vc_sw->con_cursor)
+		disp->conp->vc_sw->con_cursor(disp->conp, CM_ERASE);
+	disp->dispsw = &aafb_switch8;
+	disp->dispsw_data = 0;
+
+	aafb_get_fix(&fix, con, &info->info);
+	disp->screen_base = (u8 *) fix.smem_start;
+	disp->visual = fix.visual;
+	disp->type = fix.type;
+	disp->type_aux = fix.type_aux;
+	disp->ypanstep = fix.ypanstep;
+	disp->ywrapstep = fix.ywrapstep;
+	disp->line_length = fix.line_length;
+	disp->next_line = 2048;
+	disp->can_soft_blank = 1;
+	disp->inverse = 0;
+	disp->scrollmode = SCROLL_YREDRAW;
+
+	aafbcon_set_font(disp, fontwidth(disp), fontheight(disp));
+}
+
+static int aafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			 struct fb_info *info)
+{
+	static u16 color[2] = {0x0000, 0x000f};
+	static struct fb_cmap aafb_cmap = {0, 2, color, color, color, NULL};
+
+	fb_copy_cmap(&aafb_cmap, cmap, kspc ? 0 : 2);
+	return 0;
+}
+
+static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			 struct fb_info *info)
+{
+	u16 color[2] = {0x0000, 0x000f};
+
+	if (cmap->start == 0
+	    && cmap->len == 2
+	    && memcmp(cmap->red, color, sizeof(color)) == 0
+	    && memcmp(cmap->green, color, sizeof(color)) == 0
+	    && memcmp(cmap->blue, color, sizeof(color)) == 0
+	    && cmap->transp == NULL)
+		return 0;
+	else
+		return -EINVAL;
+}
+
+static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg)
+{
+	/* TODO: Not yet implemented */
+	return -ENOIOCTLCMD;
+}
+
+static int aafb_switch(int con, struct fb_info *info)
+{
+	struct aafb_info *ip = (struct aafb_info *)info;
+	struct display *old = (currcon < 0) ? &ip->disp : (fb_display + currcon);
+	struct display *new = (con < 0) ? &ip->disp : (fb_display + con);
+
+	if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor)
+		old->conp->vc_sw->con_cursor(old->conp, CM_ERASE);
+
+	/* Set the current console. */
+	currcon = con;
+	aafb_set_disp(new, con, ip);
+
+	return 0;
+}
+
+static void aafb_encode_var(struct fb_var_screeninfo *var,
+			    struct aafb_par *par)
+{
+	var->xres = 1280;
+	var->yres = 1024;
+	var->xres_virtual = 2048;
+	var->yres_virtual = 1024;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->bits_per_pixel = 8;
+	var->grayscale = 1;
+	var->red.offset = 0;
+	var->red.length = 0;
+	var->red.msb_right = 0;
+	var->green.offset = 0;
+	var->green.length = 1;
+	var->green.msb_right = 0;
+	var->blue.offset = 0;
+	var->blue.length = 0;
+	var->blue.msb_right = 0;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	var->nonstd = 0;
+	var->activate &= ~FB_ACTIVATE_MASK & FB_ACTIVATE_NOW;
+	var->accel_flags = 0;
+	var->sync = FB_SYNC_ON_GREEN;
+	var->vmode &= ~FB_VMODE_MASK & FB_VMODE_NONINTERLACED;
+}
+
+static int aafb_get_var(struct fb_var_screeninfo *var, int con,
+			struct fb_info *info)
+{
+	if (con < 0) {
+		struct aafb_par par;
+
+		memset(var, 0, sizeof(struct fb_var_screeninfo));
+		aafb_get_par(&par);
+		aafb_encode_var(var, &par);
+	} else
+		*var = info->var;
+
+	return 0;
+}
+
+static int aafb_set_var(struct fb_var_screeninfo *var, int con,
+			struct fb_info *info)
+{
+	struct aafb_par par;
+
+	aafb_get_par(&par);
+	aafb_encode_var(var, &par);
+	info->var = *var;
+
+	return 0;
+}
+
+static int aafb_update_var(int con, struct fb_info *info)
+{
+	struct aafb_info *ip = (struct aafb_info *)info;
+	struct display *disp = (con < 0) ? &ip->disp : (fb_display + con);
+
+	if (con == currcon)
+		aafbcon_cursor(disp, CM_ERASE, ip->cursor.x, ip->cursor.y);
+
+	return 0;
+}
+
+/* 0 unblanks, any other blanks. */
+
+static void aafb_blank(int blank, struct fb_info *info)
+{
+	struct aafb_info *ip = (struct aafb_info *)info;
+	u8 val = blank ? 0x00 : 0x0f;
+
+	bt455_write_cmap_entry(ip->bt455, 1, val, val, val);
+	aafbcon_cursor(&ip->disp, CM_ERASE, ip->cursor.x, ip->cursor.y);
+}
+
+static struct fb_ops aafb_ops = {
+	.owner = THIS_MODULE,
+	.fb_get_fix = aafb_get_fix,
+	.fb_get_var = aafb_get_var,
+	.fb_set_var = aafb_set_var,
+	.fb_get_cmap = aafb_get_cmap,
+	.fb_set_cmap = aafb_set_cmap,
+	.fb_ioctl = aafb_ioctl
+};
+
+static int __init init_one(int slot)
+{
+	unsigned long base_addr = CKSEG1ADDR(get_tc_base_addr(slot));
+	struct aafb_info *ip = &my_fb_info[slot];
+
+	memset(ip, 0, sizeof(struct aafb_info));
+
+	/*
+	 * Framebuffer display memory base address and friends.
+	 */
+	ip->bt455 = (struct bt455_regs *) (base_addr + PMAG_AA_BT455_OFFSET);
+	ip->bt431 = (struct bt431_regs *) (base_addr + PMAG_AA_BT431_OFFSET);
+	ip->fb_start = base_addr + PMAG_AA_ONBOARD_FBMEM_OFFSET;
+	ip->fb_size = 2048 * 1024; /* fb_fix_screeninfo.smem_length
+				      seems to be physical */
+	ip->fb_line_length = 2048;
+
+	/*
+	 * Let there be consoles..
+	 */
+	strcpy(ip->info.modename, "PMAG-AA");
+	ip->info.node = -1;
+	ip->info.flags = FBINFO_FLAG_DEFAULT;
+	ip->info.fbops = &aafb_ops;
+	ip->info.disp = &ip->disp;
+	ip->info.changevar = NULL;
+	ip->info.switch_con = &aafb_switch;
+	ip->info.updatevar = &aafb_update_var;
+	ip->info.blank = &aafb_blank;
+
+	aafb_set_disp(&ip->disp, currcon, ip);
+
+	/*
+	 * Configure the RAM DACs.
+	 */
+	bt455_erase_cursor(ip->bt455);
+
+	/* Init colormap. */
+	bt455_write_cmap_entry(ip->bt455, 0, 0x00, 0x00, 0x00);
+	bt455_write_cmap_entry(ip->bt455, 1, 0x0f, 0x0f, 0x0f);
+
+	/* Init hardware cursor. */
+	bt431_init_cursor(ip->bt431);
+	aafb_cursor_init(ip);
+
+	/* Clear the screen. */
+	memset ((void *)ip->fb_start, 0, ip->fb_size);
+
+	if (register_framebuffer(&ip->info) < 0)
+		return -EINVAL;
+
+	printk(KERN_INFO "fb%d: %s frame buffer in TC slot %d\n",
+	       GET_FB_IDX(ip->info.node), ip->info.modename, slot);
+
+	return 0;
+}
+
+static int __exit exit_one(int slot)
+{
+	struct aafb_info *ip = &my_fb_info[slot];
+
+	if (unregister_framebuffer(&ip->info) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Initialise the framebuffer.
+ */
+int __init pmagaafb_init(void)
+{
+	int sid;
+	int found = 0;
+
+	while ((sid = search_tc_card("PMAG-AA")) >= 0) {
+		found = 1;
+		claim_tc_card(sid);
+		init_one(sid);
+	}
+
+	return found ? 0 : -ENXIO;
+}
+
+static void __exit pmagaafb_exit(void)
+{
+	int sid;
+
+	while ((sid = search_tc_card("PMAG-AA")) >= 0) {
+		exit_one(sid);
+		release_tc_card(sid);
+	}
+}
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
+MODULE_LICENSE("GPL");
+#ifdef MODULE
+module_init(pmagaafb_init);
+module_exit(pmagaafb_exit);
+#endif
diff --git a/drivers/video/fbdev/pmag-ba-fb.c b/drivers/video/fbdev/pmag-ba-fb.c
new file mode 100644
index 000000000000..914a52ba8477
--- /dev/null
+++ b/drivers/video/fbdev/pmag-ba-fb.c
@@ -0,0 +1,295 @@
+/*
+ *	linux/drivers/video/pmag-ba-fb.c
+ *
+ *	PMAG-BA TURBOchannel Color Frame Buffer (CFB) card support,
+ *	derived from:
+ *	"HP300 Topcat framebuffer support (derived from macfb of all things)
+ *	Phil Blundell <philb@gnu.org> 1998", the original code can be
+ *	found in the file hpfb.c in the same directory.
+ *
+ *	Based on digital document:
+ * 	"PMAG-BA TURBOchannel Color Frame Buffer
+ *	 Functional Specification", Revision 1.2, August 27, 1990
+ *
+ *	DECstation related code Copyright (C) 1999, 2000, 2001 by
+ *	Michael Engel <engel@unix-ag.org>,
+ *	Karsten Merker <merker@linuxtag.org> and
+ *	Harald Koerfgen.
+ *	Copyright (c) 2005, 2006  Maciej W. Rozycki
+ *	Copyright (c) 2005  James Simmons
+ *
+ *	This file is subject to the terms and conditions of the GNU General
+ *	Public License.  See the file COPYING in the main directory of this
+ *	archive for more details.
+ */
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tc.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#include <video/pmag-ba-fb.h>
+
+
+struct pmagbafb_par {
+	volatile void __iomem *mmio;
+	volatile u32 __iomem *dac;
+};
+
+
+static struct fb_var_screeninfo pmagbafb_defined = {
+	.xres		= 1024,
+	.yres		= 864,
+	.xres_virtual	= 1024,
+	.yres_virtual	= 864,
+	.bits_per_pixel	= 8,
+	.red.length	= 8,
+	.green.length	= 8,
+	.blue.length	= 8,
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= FB_ACCEL_NONE,
+	.pixclock	= 14452,
+	.left_margin	= 116,
+	.right_margin	= 12,
+	.upper_margin	= 34,
+	.lower_margin	= 12,
+	.hsync_len	= 128,
+	.vsync_len	= 3,
+	.sync		= FB_SYNC_ON_GREEN,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo pmagbafb_fix = {
+	.id		= "PMAG-BA",
+	.smem_len	= (1024 * 1024),
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_PSEUDOCOLOR,
+	.line_length	= 1024,
+	.mmio_len	= PMAG_BA_SIZE - PMAG_BA_BT459,
+};
+
+
+static inline void dac_write(struct pmagbafb_par *par, unsigned int reg, u8 v)
+{
+	writeb(v, par->dac + reg / 4);
+}
+
+static inline u8 dac_read(struct pmagbafb_par *par, unsigned int reg)
+{
+	return readb(par->dac + reg / 4);
+}
+
+
+/*
+ * Set the palette.
+ */
+static int pmagbafb_setcolreg(unsigned int regno, unsigned int red,
+			      unsigned int green, unsigned int blue,
+			      unsigned int transp, struct fb_info *info)
+{
+	struct pmagbafb_par *par = info->par;
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	red   >>= 8;	/* The cmap fields are 16 bits    */
+	green >>= 8;	/* wide, but the hardware colormap */
+	blue  >>= 8;	/* registers are only 8 bits wide */
+
+	mb();
+	dac_write(par, BT459_ADDR_LO, regno);
+	dac_write(par, BT459_ADDR_HI, 0x00);
+	wmb();
+	dac_write(par, BT459_CMAP, red);
+	wmb();
+	dac_write(par, BT459_CMAP, green);
+	wmb();
+	dac_write(par, BT459_CMAP, blue);
+
+	return 0;
+}
+
+static struct fb_ops pmagbafb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= pmagbafb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+
+/*
+ * Turn the hardware cursor off.
+ */
+static void __init pmagbafb_erase_cursor(struct fb_info *info)
+{
+	struct pmagbafb_par *par = info->par;
+
+	mb();
+	dac_write(par, BT459_ADDR_LO, 0x00);
+	dac_write(par, BT459_ADDR_HI, 0x03);
+	wmb();
+	dac_write(par, BT459_DATA, 0x00);
+}
+
+
+static int pmagbafb_probe(struct device *dev)
+{
+	struct tc_dev *tdev = to_tc_dev(dev);
+	resource_size_t start, len;
+	struct fb_info *info;
+	struct pmagbafb_par *par;
+	int err;
+
+	info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev);
+	if (!info) {
+		printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev));
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	dev_set_drvdata(dev, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		printk(KERN_ERR "%s: Cannot allocate color map\n",
+		       dev_name(dev));
+		err = -ENOMEM;
+		goto err_alloc;
+	}
+
+	info->fbops = &pmagbafb_ops;
+	info->fix = pmagbafb_fix;
+	info->var = pmagbafb_defined;
+	info->flags = FBINFO_DEFAULT;
+
+	/* Request the I/O MEM resource.  */
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	if (!request_mem_region(start, len, dev_name(dev))) {
+		printk(KERN_ERR "%s: Cannot reserve FB region\n",
+		       dev_name(dev));
+		err = -EBUSY;
+		goto err_cmap;
+	}
+
+	/* MMIO mapping setup.  */
+	info->fix.mmio_start = start;
+	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+	if (!par->mmio) {
+		printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
+		err = -ENOMEM;
+		goto err_resource;
+	}
+	par->dac = par->mmio + PMAG_BA_BT459;
+
+	/* Frame buffer mapping setup.  */
+	info->fix.smem_start = start + PMAG_BA_FBMEM;
+	info->screen_base = ioremap_nocache(info->fix.smem_start,
+					    info->fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
+		err = -ENOMEM;
+		goto err_mmio_map;
+	}
+	info->screen_size = info->fix.smem_len;
+
+	pmagbafb_erase_cursor(info);
+
+	err = register_framebuffer(info);
+	if (err < 0) {
+		printk(KERN_ERR "%s: Cannot register framebuffer\n",
+		       dev_name(dev));
+		goto err_smem_map;
+	}
+
+	get_device(dev);
+
+	fb_info(info, "%s frame buffer device at %s\n",
+		info->fix.id, dev_name(dev));
+
+	return 0;
+
+
+err_smem_map:
+	iounmap(info->screen_base);
+
+err_mmio_map:
+	iounmap(par->mmio);
+
+err_resource:
+	release_mem_region(start, len);
+
+err_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+err_alloc:
+	framebuffer_release(info);
+	return err;
+}
+
+static int __exit pmagbafb_remove(struct device *dev)
+{
+	struct tc_dev *tdev = to_tc_dev(dev);
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct pmagbafb_par *par = info->par;
+	resource_size_t start, len;
+
+	put_device(dev);
+	unregister_framebuffer(info);
+	iounmap(info->screen_base);
+	iounmap(par->mmio);
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	release_mem_region(start, len);
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(info);
+	return 0;
+}
+
+
+/*
+ * Initialize the framebuffer.
+ */
+static const struct tc_device_id pmagbafb_tc_table[] = {
+	{ "DEC     ", "PMAG-BA " },
+	{ }
+};
+MODULE_DEVICE_TABLE(tc, pmagbafb_tc_table);
+
+static struct tc_driver pmagbafb_driver = {
+	.id_table	= pmagbafb_tc_table,
+	.driver		= {
+		.name	= "pmagbafb",
+		.bus	= &tc_bus_type,
+		.probe	= pmagbafb_probe,
+		.remove	= __exit_p(pmagbafb_remove),
+	},
+};
+
+static int __init pmagbafb_init(void)
+{
+#ifndef MODULE
+	if (fb_get_options("pmagbafb", NULL))
+		return -ENXIO;
+#endif
+	return tc_register_driver(&pmagbafb_driver);
+}
+
+static void __exit pmagbafb_exit(void)
+{
+	tc_unregister_driver(&pmagbafb_driver);
+}
+
+
+module_init(pmagbafb_init);
+module_exit(pmagbafb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/pmagb-b-fb.c b/drivers/video/fbdev/pmagb-b-fb.c
new file mode 100644
index 000000000000..0822b6f8dddc
--- /dev/null
+++ b/drivers/video/fbdev/pmagb-b-fb.c
@@ -0,0 +1,413 @@
+/*
+ *	linux/drivers/video/pmagb-b-fb.c
+ *
+ *	PMAGB-B TURBOchannel Smart Frame Buffer (SFB) card support,
+ *	derived from:
+ *	"HP300 Topcat framebuffer support (derived from macfb of all things)
+ *	Phil Blundell <philb@gnu.org> 1998", the original code can be
+ *	found in the file hpfb.c in the same directory.
+ *
+ *	DECstation related code Copyright (C) 1999, 2000, 2001 by
+ *	Michael Engel <engel@unix-ag.org>,
+ *	Karsten Merker <merker@linuxtag.org> and
+ *	Harald Koerfgen.
+ *	Copyright (c) 2005, 2006  Maciej W. Rozycki
+ *
+ *	This file is subject to the terms and conditions of the GNU General
+ *	Public License.  See the file COPYING in the main directory of this
+ *	archive for more details.
+ */
+
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tc.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#include <video/pmagb-b-fb.h>
+
+
+struct pmagbbfb_par {
+	volatile void __iomem *mmio;
+	volatile void __iomem *smem;
+	volatile u32 __iomem *sfb;
+	volatile u32 __iomem *dac;
+	unsigned int osc0;
+	unsigned int osc1;
+	int slot;
+};
+
+
+static struct fb_var_screeninfo pmagbbfb_defined = {
+	.bits_per_pixel	= 8,
+	.red.length	= 8,
+	.green.length	= 8,
+	.blue.length	= 8,
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= FB_ACCEL_NONE,
+	.sync		= FB_SYNC_ON_GREEN,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo pmagbbfb_fix = {
+	.id		= "PMAGB-BA",
+	.smem_len	= (2048 * 1024),
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_PSEUDOCOLOR,
+	.mmio_len	= PMAGB_B_FBMEM,
+};
+
+
+static inline void sfb_write(struct pmagbbfb_par *par, unsigned int reg, u32 v)
+{
+	writel(v, par->sfb + reg / 4);
+}
+
+static inline u32 sfb_read(struct pmagbbfb_par *par, unsigned int reg)
+{
+	return readl(par->sfb + reg / 4);
+}
+
+static inline void dac_write(struct pmagbbfb_par *par, unsigned int reg, u8 v)
+{
+	writeb(v, par->dac + reg / 4);
+}
+
+static inline u8 dac_read(struct pmagbbfb_par *par, unsigned int reg)
+{
+	return readb(par->dac + reg / 4);
+}
+
+static inline void gp0_write(struct pmagbbfb_par *par, u32 v)
+{
+	writel(v, par->mmio + PMAGB_B_GP0);
+}
+
+
+/*
+ * Set the palette.
+ */
+static int pmagbbfb_setcolreg(unsigned int regno, unsigned int red,
+			      unsigned int green, unsigned int blue,
+			      unsigned int transp, struct fb_info *info)
+{
+	struct pmagbbfb_par *par = info->par;
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	red   >>= 8;	/* The cmap fields are 16 bits    */
+	green >>= 8;	/* wide, but the hardware colormap */
+	blue  >>= 8;	/* registers are only 8 bits wide */
+
+	mb();
+	dac_write(par, BT459_ADDR_LO, regno);
+	dac_write(par, BT459_ADDR_HI, 0x00);
+	wmb();
+	dac_write(par, BT459_CMAP, red);
+	wmb();
+	dac_write(par, BT459_CMAP, green);
+	wmb();
+	dac_write(par, BT459_CMAP, blue);
+
+	return 0;
+}
+
+static struct fb_ops pmagbbfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= pmagbbfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+
+/*
+ * Turn the hardware cursor off.
+ */
+static void __init pmagbbfb_erase_cursor(struct fb_info *info)
+{
+	struct pmagbbfb_par *par = info->par;
+
+	mb();
+	dac_write(par, BT459_ADDR_LO, 0x00);
+	dac_write(par, BT459_ADDR_HI, 0x03);
+	wmb();
+	dac_write(par, BT459_DATA, 0x00);
+}
+
+/*
+ * Set up screen parameters.
+ */
+static void pmagbbfb_screen_setup(struct fb_info *info)
+{
+	struct pmagbbfb_par *par = info->par;
+
+	info->var.xres = ((sfb_read(par, SFB_REG_VID_HOR) >>
+			   SFB_VID_HOR_PIX_SHIFT) & SFB_VID_HOR_PIX_MASK) * 4;
+	info->var.xres_virtual = info->var.xres;
+	info->var.yres = (sfb_read(par, SFB_REG_VID_VER) >>
+			  SFB_VID_VER_SL_SHIFT) & SFB_VID_VER_SL_MASK;
+	info->var.yres_virtual = info->var.yres;
+	info->var.left_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
+				  SFB_VID_HOR_BP_SHIFT) &
+				 SFB_VID_HOR_BP_MASK) * 4;
+	info->var.right_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
+				   SFB_VID_HOR_FP_SHIFT) &
+				  SFB_VID_HOR_FP_MASK) * 4;
+	info->var.upper_margin = (sfb_read(par, SFB_REG_VID_VER) >>
+				  SFB_VID_VER_BP_SHIFT) & SFB_VID_VER_BP_MASK;
+	info->var.lower_margin = (sfb_read(par, SFB_REG_VID_VER) >>
+				  SFB_VID_VER_FP_SHIFT) & SFB_VID_VER_FP_MASK;
+	info->var.hsync_len = ((sfb_read(par, SFB_REG_VID_HOR) >>
+				SFB_VID_HOR_SYN_SHIFT) &
+			       SFB_VID_HOR_SYN_MASK) * 4;
+	info->var.vsync_len = (sfb_read(par, SFB_REG_VID_VER) >>
+			       SFB_VID_VER_SYN_SHIFT) & SFB_VID_VER_SYN_MASK;
+
+	info->fix.line_length = info->var.xres;
+};
+
+/*
+ * Determine oscillator configuration.
+ */
+static void pmagbbfb_osc_setup(struct fb_info *info)
+{
+	static unsigned int pmagbbfb_freqs[] = {
+		130808, 119843, 104000, 92980, 74370, 72800,
+		69197, 66000, 65000, 50350, 36000, 32000, 25175
+	};
+	struct pmagbbfb_par *par = info->par;
+	struct tc_bus *tbus = to_tc_dev(info->device)->bus;
+	u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8;
+	u32 freq0, freq1, freqtc = tc_get_speed(tbus) / 250;
+	int i, j;
+
+	gp0_write(par, 0);				/* select Osc0 */
+	for (j = 0; j < 16; j++) {
+		mb();
+		sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
+		mb();
+		for (i = 0; i < 100; i++) {	/* nominally max. 20.5us */
+			if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
+				break;
+			udelay(1);
+		}
+		count0 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
+	}
+
+	gp0_write(par, 1);				/* select Osc1 */
+	for (j = 0; j < 16; j++) {
+		mb();
+		sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
+
+		for (i = 0; i < 100; i++) {	/* nominally max. 20.5us */
+			if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
+				break;
+			udelay(1);
+		}
+		count1 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
+	}
+
+	freq0 = (freqtc * count0 + counttc / 2) / counttc;
+	par->osc0 = freq0;
+	if (freq0 >= pmagbbfb_freqs[0] - (pmagbbfb_freqs[0] + 32) / 64 &&
+	    freq0 <= pmagbbfb_freqs[0] + (pmagbbfb_freqs[0] + 32) / 64)
+		par->osc0 = pmagbbfb_freqs[0];
+
+	freq1 = (par->osc0 * count1 + count0 / 2) / count0;
+	par->osc1 = freq1;
+	for (i = 0; i < ARRAY_SIZE(pmagbbfb_freqs); i++)
+		if (freq1 >= pmagbbfb_freqs[i] -
+			     (pmagbbfb_freqs[i] + 128) / 256 &&
+		    freq1 <= pmagbbfb_freqs[i] +
+			     (pmagbbfb_freqs[i] + 128) / 256) {
+			par->osc1 = pmagbbfb_freqs[i];
+			break;
+		}
+
+	if (par->osc0 - par->osc1 <= (par->osc0 + par->osc1 + 256) / 512 ||
+	    par->osc1 - par->osc0 <= (par->osc0 + par->osc1 + 256) / 512)
+		par->osc1 = 0;
+
+	gp0_write(par, par->osc1 != 0);			/* reselect OscX */
+
+	info->var.pixclock = par->osc1 ?
+			     (1000000000 + par->osc1 / 2) / par->osc1 :
+			     (1000000000 + par->osc0 / 2) / par->osc0;
+};
+
+
+static int pmagbbfb_probe(struct device *dev)
+{
+	struct tc_dev *tdev = to_tc_dev(dev);
+	resource_size_t start, len;
+	struct fb_info *info;
+	struct pmagbbfb_par *par;
+	char freq0[12], freq1[12];
+	u32 vid_base;
+	int err;
+
+	info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev);
+	if (!info) {
+		printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev));
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	dev_set_drvdata(dev, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		printk(KERN_ERR "%s: Cannot allocate color map\n",
+		       dev_name(dev));
+		err = -ENOMEM;
+		goto err_alloc;
+	}
+
+	info->fbops = &pmagbbfb_ops;
+	info->fix = pmagbbfb_fix;
+	info->var = pmagbbfb_defined;
+	info->flags = FBINFO_DEFAULT;
+
+	/* Request the I/O MEM resource.  */
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	if (!request_mem_region(start, len, dev_name(dev))) {
+		printk(KERN_ERR "%s: Cannot reserve FB region\n",
+		       dev_name(dev));
+		err = -EBUSY;
+		goto err_cmap;
+	}
+
+	/* MMIO mapping setup.  */
+	info->fix.mmio_start = start;
+	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+	if (!par->mmio) {
+		printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
+		err = -ENOMEM;
+		goto err_resource;
+	}
+	par->sfb = par->mmio + PMAGB_B_SFB;
+	par->dac = par->mmio + PMAGB_B_BT459;
+
+	/* Frame buffer mapping setup.  */
+	info->fix.smem_start = start + PMAGB_B_FBMEM;
+	par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
+	if (!par->smem) {
+		printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
+		err = -ENOMEM;
+		goto err_mmio_map;
+	}
+	vid_base = sfb_read(par, SFB_REG_VID_BASE);
+	info->screen_base = (void __iomem *)par->smem + vid_base * 0x1000;
+	info->screen_size = info->fix.smem_len - 2 * vid_base * 0x1000;
+
+	pmagbbfb_erase_cursor(info);
+	pmagbbfb_screen_setup(info);
+	pmagbbfb_osc_setup(info);
+
+	err = register_framebuffer(info);
+	if (err < 0) {
+		printk(KERN_ERR "%s: Cannot register framebuffer\n",
+		       dev_name(dev));
+		goto err_smem_map;
+	}
+
+	get_device(dev);
+
+	snprintf(freq0, sizeof(freq0), "%u.%03uMHz",
+		 par->osc0 / 1000, par->osc0 % 1000);
+	snprintf(freq1, sizeof(freq1), "%u.%03uMHz",
+		 par->osc1 / 1000, par->osc1 % 1000);
+
+	fb_info(info, "%s frame buffer device at %s\n",
+		info->fix.id, dev_name(dev));
+	fb_info(info, "Osc0: %s, Osc1: %s, Osc%u selected\n",
+		freq0, par->osc1 ? freq1 : "disabled", par->osc1 != 0);
+
+	return 0;
+
+
+err_smem_map:
+	iounmap(par->smem);
+
+err_mmio_map:
+	iounmap(par->mmio);
+
+err_resource:
+	release_mem_region(start, len);
+
+err_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+err_alloc:
+	framebuffer_release(info);
+	return err;
+}
+
+static int __exit pmagbbfb_remove(struct device *dev)
+{
+	struct tc_dev *tdev = to_tc_dev(dev);
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct pmagbbfb_par *par = info->par;
+	resource_size_t start, len;
+
+	put_device(dev);
+	unregister_framebuffer(info);
+	iounmap(par->smem);
+	iounmap(par->mmio);
+	start = tdev->resource.start;
+	len = tdev->resource.end - start + 1;
+	release_mem_region(start, len);
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(info);
+	return 0;
+}
+
+
+/*
+ * Initialize the framebuffer.
+ */
+static const struct tc_device_id pmagbbfb_tc_table[] = {
+	{ "DEC     ", "PMAGB-BA" },
+	{ }
+};
+MODULE_DEVICE_TABLE(tc, pmagbbfb_tc_table);
+
+static struct tc_driver pmagbbfb_driver = {
+	.id_table	= pmagbbfb_tc_table,
+	.driver		= {
+		.name	= "pmagbbfb",
+		.bus	= &tc_bus_type,
+		.probe	= pmagbbfb_probe,
+		.remove	= __exit_p(pmagbbfb_remove),
+	},
+};
+
+static int __init pmagbbfb_init(void)
+{
+#ifndef MODULE
+	if (fb_get_options("pmagbbfb", NULL))
+		return -ENXIO;
+#endif
+	return tc_register_driver(&pmagbbfb_driver);
+}
+
+static void __exit pmagbbfb_exit(void)
+{
+	tc_unregister_driver(&pmagbbfb_driver);
+}
+
+
+module_init(pmagbbfb_init);
+module_exit(pmagbbfb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
new file mode 100644
index 000000000000..b269abd932aa
--- /dev/null
+++ b/drivers/video/fbdev/ps3fb.c
@@ -0,0 +1,1307 @@
+/*
+ *  linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
+ *
+ *	Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *	Copyright 2006, 2007 Sony Corporation
+ *
+ *  This file is based on :
+ *
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *	Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <linux/ioctl.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include <asm/cell-regs.h>
+#include <asm/lv1call.h>
+#include <asm/ps3av.h>
+#include <asm/ps3fb.h>
+#include <asm/ps3.h>
+#include <asm/ps3gpu.h>
+
+
+#define DEVICE_NAME		"ps3fb"
+
+#define GPU_CMD_BUF_SIZE			(2 * 1024 * 1024)
+#define GPU_FB_START				(64 * 1024)
+#define GPU_IOIF				(0x0d000000UL)
+#define GPU_ALIGN_UP(x)				_ALIGN_UP((x), 64)
+#define GPU_MAX_LINE_LENGTH			(65536 - 64)
+
+#define GPU_INTR_STATUS_VSYNC_0			0	/* vsync on head A */
+#define GPU_INTR_STATUS_VSYNC_1			1	/* vsync on head B */
+#define GPU_INTR_STATUS_FLIP_0			3	/* flip head A */
+#define GPU_INTR_STATUS_FLIP_1			4	/* flip head B */
+#define GPU_INTR_STATUS_QUEUE_0			5	/* queue head A */
+#define GPU_INTR_STATUS_QUEUE_1			6	/* queue head B */
+
+#define GPU_DRIVER_INFO_VERSION			0x211
+
+/* gpu internals */
+struct display_head {
+	u64 be_time_stamp;
+	u32 status;
+	u32 offset;
+	u32 res1;
+	u32 res2;
+	u32 field;
+	u32 reserved1;
+
+	u64 res3;
+	u32 raster;
+
+	u64 vblank_count;
+	u32 field_vsync;
+	u32 reserved2;
+};
+
+struct gpu_irq {
+	u32 irq_outlet;
+	u32 status;
+	u32 mask;
+	u32 video_cause;
+	u32 graph_cause;
+	u32 user_cause;
+
+	u32 res1;
+	u64 res2;
+
+	u32 reserved[4];
+};
+
+struct gpu_driver_info {
+	u32 version_driver;
+	u32 version_gpu;
+	u32 memory_size;
+	u32 hardware_channel;
+
+	u32 nvcore_frequency;
+	u32 memory_frequency;
+
+	u32 reserved[1063];
+	struct display_head display_head[8];
+	struct gpu_irq irq;
+};
+
+struct ps3fb_priv {
+	unsigned int irq_no;
+
+	u64 context_handle, memory_handle;
+	struct gpu_driver_info *dinfo;
+
+	u64 vblank_count;	/* frame count */
+	wait_queue_head_t wait_vsync;
+
+	atomic_t ext_flip;	/* on/off flip with vsync */
+	atomic_t f_count;	/* fb_open count */
+	int is_blanked;
+	int is_kicked;
+	struct task_struct *task;
+};
+static struct ps3fb_priv ps3fb;
+
+struct ps3fb_par {
+	u32 pseudo_palette[16];
+	int mode_id, new_mode_id;
+	unsigned int num_frames;	/* num of frame buffers */
+	unsigned int width;
+	unsigned int height;
+	unsigned int ddr_line_length;
+	unsigned int ddr_frame_size;
+	unsigned int xdr_frame_size;
+	unsigned int full_offset;	/* start of fullscreen DDR fb */
+	unsigned int fb_offset;		/* start of actual DDR fb */
+	unsigned int pan_offset;
+};
+
+
+#define FIRST_NATIVE_MODE_INDEX	10
+
+static const struct fb_videomode ps3fb_modedb[] = {
+    /* 60 Hz broadcast modes (modes "1" to "5") */
+    {
+        /* 480i */
+        "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 480p */
+        "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080i */
+        "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (modes "6" to "10") */
+    {
+        /* 576i */
+        "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 576p */
+        "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080i */
+        "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    [FIRST_NATIVE_MODE_INDEX] =
+    /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
+    {
+	/* 480if */
+	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 480pf */
+	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */
+    {
+	/* 576if */
+	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 576pf */
+	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* VESA modes (modes "11" to "13") */
+    {
+	/* WXGA */
+	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* SXGA */
+	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* WUXGA */
+	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
+	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }
+};
+
+
+#define HEAD_A
+#define HEAD_B
+
+#define BPP		4			/* number of bytes per pixel */
+
+
+static int ps3fb_mode;
+module_param(ps3fb_mode, int, 0);
+
+static char *mode_option;
+
+static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
+			  const struct fb_var_screeninfo *var)
+{
+	long xres, yres, left_margin, right_margin, upper_margin, lower_margin;
+	long dx, dy;
+
+	/* maximum values */
+	if (var->xres > vmode->xres || var->yres > vmode->yres ||
+	    var->pixclock > vmode->pixclock ||
+	    var->hsync_len > vmode->hsync_len ||
+	    var->vsync_len > vmode->vsync_len)
+		return -1;
+
+	/* progressive/interlaced must match */
+	if ((var->vmode & FB_VMODE_MASK) != vmode->vmode)
+		return -1;
+
+	/* minimum resolution */
+	xres = max(var->xres, 1U);
+	yres = max(var->yres, 1U);
+
+	/* minimum margins */
+	left_margin = max(var->left_margin, vmode->left_margin);
+	right_margin = max(var->right_margin, vmode->right_margin);
+	upper_margin = max(var->upper_margin, vmode->upper_margin);
+	lower_margin = max(var->lower_margin, vmode->lower_margin);
+
+	/* resolution + margins may not exceed native parameters */
+	dx = ((long)vmode->left_margin + (long)vmode->xres +
+	      (long)vmode->right_margin) -
+	     (left_margin + xres + right_margin);
+	if (dx < 0)
+		return -1;
+
+	dy = ((long)vmode->upper_margin + (long)vmode->yres +
+	      (long)vmode->lower_margin) -
+	     (upper_margin + yres + lower_margin);
+	if (dy < 0)
+		return -1;
+
+	/* exact match */
+	if (!dx && !dy)
+		return 0;
+
+	/* resolution difference */
+	return (vmode->xres - xres) * (vmode->yres - yres);
+}
+
+static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id)
+{
+	return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1];
+}
+
+static const struct fb_videomode *ps3fb_vmode(int id)
+{
+	u32 mode = id & PS3AV_MODE_MASK;
+
+	if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA)
+		return NULL;
+
+	if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) {
+		/* Non-fullscreen broadcast mode */
+		return &ps3fb_modedb[mode - 1];
+	}
+
+	return ps3fb_native_vmode(mode);
+}
+
+static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var,
+				    u32 *ddr_line_length, u32 *xdr_line_length)
+{
+	unsigned int id, best_id;
+	int diff, best_diff;
+	const struct fb_videomode *vmode;
+	long gap;
+
+	best_id = 0;
+	best_diff = INT_MAX;
+	pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__,
+		 var->left_margin, var->xres, var->right_margin,
+		 var->upper_margin, var->yres, var->lower_margin);
+	for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) {
+		vmode = ps3fb_native_vmode(id);
+		diff = ps3fb_cmp_mode(vmode, var);
+		pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n",
+			 __func__, id, vmode->left_margin, vmode->xres,
+			 vmode->right_margin, vmode->upper_margin,
+			 vmode->yres, vmode->lower_margin, diff);
+		if (diff < 0)
+			continue;
+		if (diff < best_diff) {
+			best_id = id;
+			if (!diff)
+				break;
+			best_diff = diff;
+		}
+	}
+
+	if (!best_id) {
+		pr_debug("%s: no suitable mode found\n", __func__);
+		return 0;
+	}
+
+	id = best_id;
+	vmode = ps3fb_native_vmode(id);
+
+	*ddr_line_length = vmode->xres * BPP;
+
+	/* minimum resolution */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+
+	/* minimum virtual resolution */
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	/* minimum margins */
+	if (var->left_margin < vmode->left_margin)
+		var->left_margin = vmode->left_margin;
+	if (var->right_margin < vmode->right_margin)
+		var->right_margin = vmode->right_margin;
+	if (var->upper_margin < vmode->upper_margin)
+		var->upper_margin = vmode->upper_margin;
+	if (var->lower_margin < vmode->lower_margin)
+		var->lower_margin = vmode->lower_margin;
+
+	/* extra margins */
+	gap = ((long)vmode->left_margin + (long)vmode->xres +
+	       (long)vmode->right_margin) -
+	      ((long)var->left_margin + (long)var->xres +
+	       (long)var->right_margin);
+	if (gap > 0) {
+		var->left_margin += gap/2;
+		var->right_margin += (gap+1)/2;
+		pr_debug("%s: rounded up H to %u [%u] %u\n", __func__,
+			 var->left_margin, var->xres, var->right_margin);
+	}
+
+	gap = ((long)vmode->upper_margin + (long)vmode->yres +
+	       (long)vmode->lower_margin) -
+	      ((long)var->upper_margin + (long)var->yres +
+	       (long)var->lower_margin);
+	if (gap > 0) {
+		var->upper_margin += gap/2;
+		var->lower_margin += (gap+1)/2;
+		pr_debug("%s: rounded up V to %u [%u] %u\n", __func__,
+			 var->upper_margin, var->yres, var->lower_margin);
+	}
+
+	/* fixed fields */
+	var->pixclock = vmode->pixclock;
+	var->hsync_len = vmode->hsync_len;
+	var->vsync_len = vmode->vsync_len;
+	var->sync = vmode->sync;
+
+	if (ps3_compare_firmware_version(1, 9, 0) >= 0) {
+		*xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP);
+		if (*xdr_line_length > GPU_MAX_LINE_LENGTH)
+			*xdr_line_length = GPU_MAX_LINE_LENGTH;
+	} else
+		*xdr_line_length = *ddr_line_length;
+
+	if (vmode->sync & FB_SYNC_BROADCAST) {
+		/* Full broadcast modes have the full mode bit set */
+		if (vmode->xres == var->xres && vmode->yres == var->yres)
+			id |= PS3AV_MODE_FULL;
+	}
+
+	pr_debug("%s: mode %u\n", __func__, id);
+	return id;
+}
+
+static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
+			     u64 dst_offset, u64 src_offset, u32 width,
+			     u32 height, u32 dst_line_length,
+			     u32 src_line_length)
+{
+	int status;
+	u64 line_length;
+
+	line_length = dst_line_length;
+	if (src_line_length != dst_line_length)
+		line_length |= (u64)src_line_length << 32;
+
+	src_offset += GPU_FB_START;
+
+	mutex_lock(&ps3_gpu_mutex);
+	status = lv1_gpu_fb_blit(ps3fb.context_handle, dst_offset,
+				 GPU_IOIF + src_offset,
+				 L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
+				 (width << 16) | height,
+				 line_length);
+	mutex_unlock(&ps3_gpu_mutex);
+
+	if (status)
+		dev_err(dev, "%s: lv1_gpu_fb_blit failed: %d\n", __func__,
+			status);
+#ifdef HEAD_A
+	status = lv1_gpu_display_flip(ps3fb.context_handle, 0, frame_offset);
+	if (status)
+		dev_err(dev, "%s: lv1_gpu_display_flip failed: %d\n", __func__,
+			status);
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_display_flip(ps3fb.context_handle, 1, frame_offset);
+	if (status)
+		dev_err(dev, "%s: lv1_gpu_display_flip failed: %d\n", __func__,
+			status);
+#endif
+}
+
+static int ps3fb_sync(struct fb_info *info, u32 frame)
+{
+	struct ps3fb_par *par = info->par;
+	int error = 0;
+	u64 ddr_base, xdr_base;
+
+	if (frame > par->num_frames - 1) {
+		dev_dbg(info->device, "%s: invalid frame number (%u)\n",
+			__func__, frame);
+		error = -EINVAL;
+		goto out;
+	}
+
+	xdr_base = frame * par->xdr_frame_size;
+	ddr_base = frame * par->ddr_frame_size;
+
+	ps3fb_sync_image(info->device, ddr_base + par->full_offset,
+			 ddr_base + par->fb_offset, xdr_base + par->pan_offset,
+			 par->width, par->height, par->ddr_line_length,
+			 info->fix.line_length);
+
+out:
+	return error;
+}
+
+static int ps3fb_open(struct fb_info *info, int user)
+{
+	atomic_inc(&ps3fb.f_count);
+	return 0;
+}
+
+static int ps3fb_release(struct fb_info *info, int user)
+{
+	if (atomic_dec_and_test(&ps3fb.f_count)) {
+		if (atomic_read(&ps3fb.ext_flip)) {
+			atomic_set(&ps3fb.ext_flip, 0);
+			if (console_trylock()) {
+				ps3fb_sync(info, 0);	/* single buffer */
+				console_unlock();
+			}
+		}
+	}
+	return 0;
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var.
+     */
+
+static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 xdr_line_length, ddr_line_length;
+	int mode;
+
+	mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length);
+	if (!mode)
+		return -EINVAL;
+
+	/* Virtual screen */
+	if (var->xres_virtual > xdr_line_length / BPP) {
+		dev_dbg(info->device,
+			"Horizontal virtual screen size too large\n");
+		return -EINVAL;
+	}
+
+	if (var->xoffset + var->xres > var->xres_virtual ||
+	    var->yoffset + var->yres > var->yres_virtual) {
+		dev_dbg(info->device, "panning out-of-range\n");
+		return -EINVAL;
+	}
+
+	/* We support ARGB8888 only */
+	if (var->bits_per_pixel > 32 || var->grayscale ||
+	    var->red.offset > 16 || var->green.offset > 8 ||
+	    var->blue.offset > 0 || var->transp.offset > 24 ||
+	    var->red.length > 8 || var->green.length > 8 ||
+	    var->blue.length > 8 || var->transp.length > 8 ||
+	    var->red.msb_right || var->green.msb_right ||
+	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
+		dev_dbg(info->device, "We support ARGB8888 only\n");
+		return -EINVAL;
+	}
+
+	var->bits_per_pixel = 32;
+	var->red.offset = 16;
+	var->green.offset = 8;
+	var->blue.offset = 0;
+	var->transp.offset = 24;
+	var->red.length = 8;
+	var->green.length = 8;
+	var->blue.length = 8;
+	var->transp.length = 8;
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	/* Rotation is not supported */
+	if (var->rotate) {
+		dev_dbg(info->device, "Rotation is not supported\n");
+		return -EINVAL;
+	}
+
+	/* Memory limit */
+	if (var->yres_virtual * xdr_line_length > info->fix.smem_len) {
+		dev_dbg(info->device, "Not enough memory\n");
+		return -ENOMEM;
+	}
+
+	var->height = -1;
+	var->width = -1;
+
+	return 0;
+}
+
+    /*
+     * This routine actually sets the video mode.
+     */
+
+static int ps3fb_set_par(struct fb_info *info)
+{
+	struct ps3fb_par *par = info->par;
+	unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines;
+	unsigned int ddr_xoff, ddr_yoff, offset;
+	const struct fb_videomode *vmode;
+	u64 dst;
+
+	mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length);
+	if (!mode)
+		return -EINVAL;
+
+	vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK);
+
+	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
+	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
+	info->fix.line_length = xdr_line_length;
+
+	par->ddr_line_length = ddr_line_length;
+	par->ddr_frame_size = vmode->yres * ddr_line_length;
+	par->xdr_frame_size = info->var.yres_virtual * xdr_line_length;
+
+	par->num_frames = info->fix.smem_len /
+			  max(par->ddr_frame_size, par->xdr_frame_size);
+
+	/* Keep the special bits we cannot set using fb_var_screeninfo */
+	par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
+
+	par->width = info->var.xres;
+	par->height = info->var.yres;
+
+	/* Start of the virtual frame buffer (relative to fullscreen) */
+	ddr_xoff = info->var.left_margin - vmode->left_margin;
+	ddr_yoff = info->var.upper_margin - vmode->upper_margin;
+	offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP;
+
+	par->fb_offset = GPU_ALIGN_UP(offset);
+	par->full_offset = par->fb_offset - offset;
+	par->pan_offset = info->var.yoffset * xdr_line_length +
+			  info->var.xoffset * BPP;
+
+	if (par->new_mode_id != par->mode_id) {
+		if (ps3av_set_video_mode(par->new_mode_id)) {
+			par->new_mode_id = par->mode_id;
+			return -EINVAL;
+		}
+		par->mode_id = par->new_mode_id;
+	}
+
+	/* Clear XDR frame buffer memory */
+	memset((void __force *)info->screen_base, 0, info->fix.smem_len);
+
+	/* Clear DDR frame buffer memory */
+	lines = vmode->yres * par->num_frames;
+	if (par->full_offset)
+		lines++;
+	maxlines = info->fix.smem_len / ddr_line_length;
+	for (dst = 0; lines; dst += maxlines * ddr_line_length) {
+		unsigned int l = min(lines, maxlines);
+		ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l,
+				 ddr_line_length, ddr_line_length);
+		lines -= l;
+	}
+
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp, struct fb_info *info)
+{
+	if (regno >= 16)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	transp >>= 8;
+
+	((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 |
+					       green << 8 | blue;
+	return 0;
+}
+
+static int ps3fb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct ps3fb_par *par = info->par;
+
+	par->pan_offset = var->yoffset * info->fix.line_length +
+			  var->xoffset * BPP;
+	return 0;
+}
+
+    /*
+     *  As we have a virtual frame buffer, we need our own mmap function
+     */
+
+static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	int r;
+
+	r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
+
+	dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
+		info->fix.smem_start + (vma->vm_pgoff << PAGE_SHIFT),
+		vma->vm_start);
+
+	return r;
+}
+
+    /*
+     * Blank the display
+     */
+
+static int ps3fb_blank(int blank, struct fb_info *info)
+{
+	int retval;
+
+	dev_dbg(info->device, "%s: blank:%d\n", __func__, blank);
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		retval = ps3av_video_mute(1);	/* mute on */
+		if (!retval)
+			ps3fb.is_blanked = 1;
+		break;
+
+	default:		/* unblank */
+		retval = ps3av_video_mute(0);	/* mute off */
+		if (!retval)
+			ps3fb.is_blanked = 0;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fb_get_vblank(struct fb_vblank *vblank)
+{
+	memset(vblank, 0, sizeof(*vblank));
+	vblank->flags = FB_VBLANK_HAVE_VSYNC;
+	return 0;
+}
+
+static int ps3fb_wait_for_vsync(u32 crtc)
+{
+	int ret;
+	u64 count;
+
+	count = ps3fb.vblank_count;
+	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
+					       count != ps3fb.vblank_count,
+					       HZ / 10);
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+
+    /*
+     * ioctl
+     */
+
+static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	u32 val;
+	int retval = -EFAULT;
+
+	switch (cmd) {
+	case FBIOGET_VBLANK:
+		{
+			struct fb_vblank vblank;
+			dev_dbg(info->device, "FBIOGET_VBLANK:\n");
+			retval = ps3fb_get_vblank(&vblank);
+			if (retval)
+				break;
+
+			if (copy_to_user(argp, &vblank, sizeof(vblank)))
+				retval = -EFAULT;
+			break;
+		}
+
+	case FBIO_WAITFORVSYNC:
+		{
+			u32 crt;
+			dev_dbg(info->device, "FBIO_WAITFORVSYNC:\n");
+			if (get_user(crt, (u32 __user *) arg))
+				break;
+
+			retval = ps3fb_wait_for_vsync(crt);
+			break;
+		}
+
+	case PS3FB_IOCTL_SETMODE:
+		{
+			struct ps3fb_par *par = info->par;
+			const struct fb_videomode *vmode;
+			struct fb_var_screeninfo var;
+
+			if (copy_from_user(&val, argp, sizeof(val)))
+				break;
+
+			if (!(val & PS3AV_MODE_MASK)) {
+				u32 id = ps3av_get_auto_mode();
+				if (id > 0)
+					val = (val & ~PS3AV_MODE_MASK) | id;
+			}
+			dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val);
+			retval = -EINVAL;
+			vmode = ps3fb_vmode(val);
+			if (vmode) {
+				var = info->var;
+				fb_videomode_to_var(&var, vmode);
+				console_lock();
+				info->flags |= FBINFO_MISC_USEREVENT;
+				/* Force, in case only special bits changed */
+				var.activate |= FB_ACTIVATE_FORCE;
+				par->new_mode_id = val;
+				retval = fb_set_var(info, &var);
+				info->flags &= ~FBINFO_MISC_USEREVENT;
+				console_unlock();
+			}
+			break;
+		}
+
+	case PS3FB_IOCTL_GETMODE:
+		val = ps3av_get_mode();
+		dev_dbg(info->device, "PS3FB_IOCTL_GETMODE:%x\n", val);
+		if (!copy_to_user(argp, &val, sizeof(val)))
+			retval = 0;
+		break;
+
+	case PS3FB_IOCTL_SCREENINFO:
+		{
+			struct ps3fb_par *par = info->par;
+			struct ps3fb_ioctl_res res;
+			dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n");
+			res.xres = info->fix.line_length / BPP;
+			res.yres = info->var.yres_virtual;
+			res.xoff = (res.xres - info->var.xres) / 2;
+			res.yoff = (res.yres - info->var.yres) / 2;
+			res.num_frames = par->num_frames;
+			if (!copy_to_user(argp, &res, sizeof(res)))
+				retval = 0;
+			break;
+		}
+
+	case PS3FB_IOCTL_ON:
+		dev_dbg(info->device, "PS3FB_IOCTL_ON:\n");
+		atomic_inc(&ps3fb.ext_flip);
+		retval = 0;
+		break;
+
+	case PS3FB_IOCTL_OFF:
+		dev_dbg(info->device, "PS3FB_IOCTL_OFF:\n");
+		atomic_dec_if_positive(&ps3fb.ext_flip);
+		retval = 0;
+		break;
+
+	case PS3FB_IOCTL_FSEL:
+		if (copy_from_user(&val, argp, sizeof(val)))
+			break;
+
+		dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val);
+		console_lock();
+		retval = ps3fb_sync(info, val);
+		console_unlock();
+		break;
+
+	default:
+		retval = -ENOIOCTLCMD;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fbd(void *arg)
+{
+	struct fb_info *info = arg;
+
+	set_freezable();
+	while (!kthread_should_stop()) {
+		try_to_freeze();
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (ps3fb.is_kicked) {
+			ps3fb.is_kicked = 0;
+			console_lock();
+			ps3fb_sync(info, 0);	/* single buffer */
+			console_unlock();
+		}
+		schedule();
+	}
+	return 0;
+}
+
+static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
+{
+	struct device *dev = ptr;
+	u64 v1;
+	int status;
+	struct display_head *head = &ps3fb.dinfo->display_head[1];
+
+	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
+	if (status) {
+		dev_err(dev, "%s: lv1_gpu_context_intr failed: %d\n", __func__,
+			status);
+		return IRQ_NONE;
+	}
+
+	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
+		/* VSYNC */
+		ps3fb.vblank_count = head->vblank_count;
+		if (ps3fb.task && !ps3fb.is_blanked &&
+		    !atomic_read(&ps3fb.ext_flip)) {
+			ps3fb.is_kicked = 1;
+			wake_up_process(ps3fb.task);
+		}
+		wake_up_interruptible(&ps3fb.wait_vsync);
+	}
+
+	return IRQ_HANDLED;
+}
+
+
+static struct fb_ops ps3fb_ops = {
+	.fb_open	= ps3fb_open,
+	.fb_release	= ps3fb_release,
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_check_var	= ps3fb_check_var,
+	.fb_set_par	= ps3fb_set_par,
+	.fb_setcolreg	= ps3fb_setcolreg,
+	.fb_pan_display	= ps3fb_pan_display,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_mmap	= ps3fb_mmap,
+	.fb_blank	= ps3fb_blank,
+	.fb_ioctl	= ps3fb_ioctl,
+	.fb_compat_ioctl = ps3fb_ioctl
+};
+
+static struct fb_fix_screeninfo ps3fb_fix = {
+	.id =		DEVICE_NAME,
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int ps3fb_probe(struct ps3_system_bus_device *dev)
+{
+	struct fb_info *info;
+	struct ps3fb_par *par;
+	int retval;
+	u64 ddr_lpar = 0;
+	u64 lpar_dma_control = 0;
+	u64 lpar_driver_info = 0;
+	u64 lpar_reports = 0;
+	u64 lpar_reports_size = 0;
+	u64 xdr_lpar;
+	struct gpu_driver_info *dinfo;
+	void *fb_start;
+	int status;
+	struct task_struct *task;
+	unsigned long max_ps3fb_size;
+
+	if (ps3fb_videomemory.size < GPU_CMD_BUF_SIZE) {
+		dev_err(&dev->core, "%s: Not enough video memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	retval = ps3_open_hv_device(dev);
+	if (retval) {
+		dev_err(&dev->core, "%s: ps3_open_hv_device failed\n",
+			__func__);
+		goto err;
+	}
+
+	if (!ps3fb_mode)
+		ps3fb_mode = ps3av_get_mode();
+	dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode);
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_waitqueue_head(&ps3fb.wait_vsync);
+
+#ifdef HEAD_A
+	status = lv1_gpu_display_sync(0x0, 0, L1GPU_DISPLAY_SYNC_VSYNC);
+	if (status) {
+		dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d\n",
+			__func__, status);
+		retval = -ENODEV;
+		goto err_close_device;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_display_sync(0x0, 1, L1GPU_DISPLAY_SYNC_VSYNC);
+	if (status) {
+		dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d\n",
+			__func__, status);
+		retval = -ENODEV;
+		goto err_close_device;
+	}
+#endif
+
+	max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF;
+	if (ps3fb_videomemory.size > max_ps3fb_size) {
+		dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n",
+			 max_ps3fb_size);
+		ps3fb_videomemory.size = max_ps3fb_size;
+	}
+
+	/* get gpu context handle */
+	status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0,
+					 &ps3fb.memory_handle, &ddr_lpar);
+	if (status) {
+		dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
+			__func__, status);
+		retval = -ENOMEM;
+		goto err_close_device;
+	}
+	dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
+
+	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
+					  &ps3fb.context_handle,
+					  &lpar_dma_control, &lpar_driver_info,
+					  &lpar_reports, &lpar_reports_size);
+	if (status) {
+		dev_err(&dev->core,
+			"%s: lv1_gpu_context_allocate failed: %d\n", __func__,
+			status);
+		retval = -ENOMEM;
+		goto err_gpu_memory_free;
+	}
+
+	/* vsync interrupt */
+	dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
+	if (!dinfo) {
+		dev_err(&dev->core, "%s: ioremap failed\n", __func__);
+		retval = -ENOMEM;
+		goto err_gpu_context_free;
+	}
+
+	ps3fb.dinfo = dinfo;
+	dev_dbg(&dev->core, "version_driver:%x\n", dinfo->version_driver);
+	dev_dbg(&dev->core, "irq outlet:%x\n", dinfo->irq.irq_outlet);
+	dev_dbg(&dev->core, "version_gpu: %x memory_size: %x ch: %x "
+		"core_freq: %d mem_freq:%d\n", dinfo->version_gpu,
+		dinfo->memory_size, dinfo->hardware_channel,
+		dinfo->nvcore_frequency/1000000,
+		dinfo->memory_frequency/1000000);
+
+	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
+		dev_err(&dev->core, "%s: version_driver err:%x\n", __func__,
+			dinfo->version_driver);
+		retval = -EINVAL;
+		goto err_iounmap_dinfo;
+	}
+
+	retval = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
+				    &ps3fb.irq_no);
+	if (retval) {
+		dev_err(&dev->core, "%s: ps3_alloc_irq failed %d\n", __func__,
+			retval);
+		goto err_iounmap_dinfo;
+	}
+
+	retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
+			     0, DEVICE_NAME, &dev->core);
+	if (retval) {
+		dev_err(&dev->core, "%s: request_irq failed %d\n", __func__,
+			retval);
+		goto err_destroy_plug;
+	}
+
+	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
+			  (1 << GPU_INTR_STATUS_FLIP_1);
+
+	/* Clear memory to prevent kernel info leakage into userspace */
+	memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size);
+
+	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
+
+	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
+				       xdr_lpar, ps3fb_videomemory.size,
+				       CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
+				       CBE_IOPTE_M);
+	if (status) {
+		dev_err(&dev->core, "%s: lv1_gpu_context_iomap failed: %d\n",
+			__func__, status);
+		retval =  -ENXIO;
+		goto err_free_irq;
+	}
+
+	dev_dbg(&dev->core, "video:%p ioif:%lx lpar:%llx size:%lx\n",
+		ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
+		ps3fb_videomemory.size);
+
+	status = lv1_gpu_fb_setup(ps3fb.context_handle, xdr_lpar,
+				  GPU_CMD_BUF_SIZE, GPU_IOIF);
+	if (status) {
+		dev_err(&dev->core, "%s: lv1_gpu_fb_setup failed: %d\n",
+			__func__, status);
+		retval = -ENXIO;
+		goto err_context_unmap;
+	}
+
+	info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
+	if (!info) {
+		retval = -ENOMEM;
+		goto err_context_fb_close;
+	}
+
+	par = info->par;
+	par->mode_id = ~ps3fb_mode;	/* != ps3fb_mode, to trigger change */
+	par->new_mode_id = ps3fb_mode;
+	par->num_frames = 1;
+
+	info->fbops = &ps3fb_ops;
+	info->fix = ps3fb_fix;
+
+	/*
+	 * The GPU command buffer is at the start of video memory
+	 * As we don't use the full command buffer, we can put the actual
+	 * frame buffer at offset GPU_FB_START and save some precious XDR
+	 * memory
+	 */
+	fb_start = ps3fb_videomemory.address + GPU_FB_START;
+	info->screen_base = (char __force __iomem *)fb_start;
+	info->fix.smem_start = __pa(fb_start);
+	info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START;
+
+	info->pseudo_palette = par->pseudo_palette;
+	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err_framebuffer_release;
+
+	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
+			  ARRAY_SIZE(ps3fb_modedb),
+			  ps3fb_vmode(par->new_mode_id), 32)) {
+		retval = -EINVAL;
+		goto err_fb_dealloc;
+	}
+
+	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),
+				 &info->modelist);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_fb_dealloc;
+
+	ps3_system_bus_set_drvdata(dev, info);
+
+	dev_info(info->device, "%s %s, using %u KiB of video memory\n",
+		 dev_driver_string(info->dev), dev_name(info->dev),
+		 info->fix.smem_len >> 10);
+
+	task = kthread_run(ps3fbd, info, DEVICE_NAME);
+	if (IS_ERR(task)) {
+		retval = PTR_ERR(task);
+		goto err_unregister_framebuffer;
+	}
+
+	ps3fb.task = task;
+
+	return 0;
+
+err_unregister_framebuffer:
+	unregister_framebuffer(info);
+err_fb_dealloc:
+	fb_dealloc_cmap(&info->cmap);
+err_framebuffer_release:
+	framebuffer_release(info);
+err_context_fb_close:
+	lv1_gpu_fb_close(ps3fb.context_handle);
+err_context_unmap:
+	lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
+			      ps3fb_videomemory.size, CBE_IOPTE_M);
+err_free_irq:
+	free_irq(ps3fb.irq_no, &dev->core);
+err_destroy_plug:
+	ps3_irq_plug_destroy(ps3fb.irq_no);
+err_iounmap_dinfo:
+	iounmap((u8 __force __iomem *)ps3fb.dinfo);
+err_gpu_context_free:
+	lv1_gpu_context_free(ps3fb.context_handle);
+err_gpu_memory_free:
+	lv1_gpu_memory_free(ps3fb.memory_handle);
+err_close_device:
+	ps3_close_hv_device(dev);
+err:
+	return retval;
+}
+
+static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
+{
+	struct fb_info *info = ps3_system_bus_get_drvdata(dev);
+	u64 xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
+
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+
+	atomic_inc(&ps3fb.ext_flip);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+
+	if (ps3fb.task) {
+		struct task_struct *task = ps3fb.task;
+		ps3fb.task = NULL;
+		kthread_stop(task);
+	}
+	if (ps3fb.irq_no) {
+		free_irq(ps3fb.irq_no, &dev->core);
+		ps3_irq_plug_destroy(ps3fb.irq_no);
+	}
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+		ps3_system_bus_set_drvdata(dev, NULL);
+	}
+	iounmap((u8 __force __iomem *)ps3fb.dinfo);
+	lv1_gpu_fb_close(ps3fb.context_handle);
+	lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
+			      ps3fb_videomemory.size, CBE_IOPTE_M);
+	lv1_gpu_context_free(ps3fb.context_handle);
+	lv1_gpu_memory_free(ps3fb.memory_handle);
+	ps3_close_hv_device(dev);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+
+	return 0;
+}
+
+static struct ps3_system_bus_driver ps3fb_driver = {
+	.match_id	= PS3_MATCH_ID_GPU,
+	.match_sub_id	= PS3_MATCH_SUB_ID_GPU_FB,
+	.core.name	= DEVICE_NAME,
+	.core.owner	= THIS_MODULE,
+	.probe		= ps3fb_probe,
+	.remove		= ps3fb_shutdown,
+	.shutdown	= ps3fb_shutdown,
+};
+
+static int __init ps3fb_setup(void)
+{
+	char *options;
+
+#ifdef MODULE
+	return 0;
+#endif
+
+	if (fb_get_options(DEVICE_NAME, &options))
+		return -ENXIO;
+
+	if (!options || !*options)
+		return 0;
+
+	while (1) {
+		char *this_opt = strsep(&options, ",");
+
+		if (!this_opt)
+			break;
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+
+static int __init ps3fb_init(void)
+{
+	if (!ps3fb_videomemory.address ||  ps3fb_setup())
+		return -ENXIO;
+
+	return ps3_system_bus_driver_register(&ps3fb_driver);
+}
+
+static void __exit ps3fb_exit(void)
+{
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+	ps3_system_bus_driver_unregister(&ps3fb_driver);
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+}
+
+module_init(ps3fb_init);
+module_exit(ps3fb_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_FB);
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
new file mode 100644
index 000000000000..167cffff3d4e
--- /dev/null
+++ b/drivers/video/fbdev/pvr2fb.c
@@ -0,0 +1,1142 @@
+/*
+ * drivers/video/pvr2fb.c
+ *
+ * Frame buffer and fbcon support for the NEC PowerVR2 found within the Sega
+ * Dreamcast.
+ *
+ * Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org>
+ * Copyright (c) 2001 - 2008  Paul Mundt <lethal@linux-sh.org>
+ *
+ * This driver is mostly based on the excellent amifb and vfb sources.  It uses
+ * an odd scheme for converting hardware values to/from framebuffer values,
+ * here are some hacked-up formulas:
+ *
+ *  The Dreamcast has screen offsets from each side of its four borders and
+ *  the start offsets of the display window.  I used these values to calculate
+ *  'pseudo' values (think of them as placeholders) for the fb video mode, so
+ *  that when it came time to convert these values back into their hardware
+ *  values, I could just add mode- specific offsets to get the correct mode
+ *  settings:
+ *
+ *      left_margin = diwstart_h - borderstart_h;
+ *      right_margin = borderstop_h - (diwstart_h + xres);
+ *      upper_margin = diwstart_v - borderstart_v;
+ *      lower_margin = borderstop_v - (diwstart_h + yres);
+ *
+ *      hsync_len = borderstart_h + (hsync_total - borderstop_h);
+ *      vsync_len = borderstart_v + (vsync_total - borderstop_v);
+ *
+ *  Then, when it's time to convert back to hardware settings, the only
+ *  constants are the borderstart_* offsets, all other values are derived from
+ *  the fb video mode:
+ *
+ *      // PAL
+ *      borderstart_h = 116;
+ *      borderstart_v = 44;
+ *      ...
+ *      borderstop_h = borderstart_h + hsync_total - hsync_len;
+ *      ...
+ *      diwstart_v = borderstart_v - upper_margin;
+ *
+ *  However, in the current implementation, the borderstart values haven't had
+ *  the benefit of being fully researched, so some modes may be broken.
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#ifdef CONFIG_SH_DREAMCAST
+#include <asm/machvec.h>
+#include <mach-dreamcast/mach/sysasic.h>
+#endif
+
+#ifdef CONFIG_PVR2_DMA
+#include <linux/pagemap.h>
+#include <mach/dma.h>
+#include <asm/dma.h>
+#endif
+
+#ifdef CONFIG_SH_STORE_QUEUES
+#include <linux/uaccess.h>
+#include <cpu/sq.h>
+#endif
+
+#ifndef PCI_DEVICE_ID_NEC_NEON250
+#  define PCI_DEVICE_ID_NEC_NEON250	0x0067
+#endif
+
+/* 2D video registers */
+#define DISP_BASE	par->mmio_base
+#define DISP_BRDRCOLR (DISP_BASE + 0x40)
+#define DISP_DIWMODE (DISP_BASE + 0x44)
+#define DISP_DIWADDRL (DISP_BASE + 0x50)
+#define DISP_DIWADDRS (DISP_BASE + 0x54)
+#define DISP_DIWSIZE (DISP_BASE + 0x5c)
+#define DISP_SYNCCONF (DISP_BASE + 0xd0)
+#define DISP_BRDRHORZ (DISP_BASE + 0xd4)
+#define DISP_SYNCSIZE (DISP_BASE + 0xd8)
+#define DISP_BRDRVERT (DISP_BASE + 0xdc)
+#define DISP_DIWCONF (DISP_BASE + 0xe8)
+#define DISP_DIWHSTRT (DISP_BASE + 0xec)
+#define DISP_DIWVSTRT (DISP_BASE + 0xf0)
+#define DISP_PIXDEPTH (DISP_BASE + 0x108)
+
+/* Pixel clocks, one for TV output, doubled for VGA output */
+#define TV_CLK 74239
+#define VGA_CLK 37119
+
+/* This is for 60Hz - the VTOTAL is doubled for interlaced modes */
+#define PAL_HTOTAL 863
+#define PAL_VTOTAL 312
+#define NTSC_HTOTAL 857
+#define NTSC_VTOTAL 262
+
+/* Supported cable types */
+enum { CT_VGA, CT_NONE, CT_RGB, CT_COMPOSITE };
+
+/* Supported video output types */
+enum { VO_PAL, VO_NTSC, VO_VGA };
+
+/* Supported palette types */
+enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 };
+
+struct pvr2_params { unsigned int val; char *name; };
+static struct pvr2_params cables[] = {
+	{ CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
+};
+
+static struct pvr2_params outputs[] = {
+	{ VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
+};
+
+/*
+ * This describes the current video mode
+ */
+
+static struct pvr2fb_par {
+	unsigned int hsync_total;	/* Clocks/line */
+	unsigned int vsync_total;	/* Lines/field */
+	unsigned int borderstart_h;
+	unsigned int borderstop_h;
+	unsigned int borderstart_v;
+	unsigned int borderstop_v;
+	unsigned int diwstart_h;	/* Horizontal offset of the display field */
+	unsigned int diwstart_v;	/* Vertical offset of the display field, for
+				   interlaced modes, this is the long field */
+	unsigned long disp_start;	/* Address of image within VRAM */
+	unsigned char is_interlaced;	/* Is the display interlaced? */
+	unsigned char is_doublescan;	/* Are scanlines output twice? (doublescan) */
+	unsigned char is_lowres;	/* Is horizontal pixel-doubling enabled? */
+
+	unsigned long mmio_base;	/* MMIO base */
+	u32 palette[16];
+} *currentpar;
+
+static struct fb_info *fb_info;
+
+static struct fb_fix_screeninfo pvr2_fix = {
+	.id =		"NEC PowerVR2",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo pvr2_var = {
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual = 480,
+	.bits_per_pixel	=16,
+	.red =		{ 11, 5, 0 },
+	.green =	{  5, 6, 0 },
+	.blue =		{  0, 5, 0 },
+	.activate =	FB_ACTIVATE_NOW,
+	.height =	-1,
+	.width =	-1,
+	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static int cable_type = CT_VGA;
+static int video_output = VO_VGA;
+
+static int nopan = 0;
+static int nowrap = 1;
+
+/*
+ * We do all updating, blanking, etc. during the vertical retrace period
+ */
+static unsigned int do_vmode_full = 0;	/* Change the video mode */
+static unsigned int do_vmode_pan = 0;	/* Update the video mode */
+static short do_blank = 0;		/* (Un)Blank the screen */
+
+static unsigned int is_blanked = 0;		/* Is the screen blanked? */
+
+#ifdef CONFIG_SH_STORE_QUEUES
+static unsigned long pvr2fb_map;
+#endif
+
+#ifdef CONFIG_PVR2_DMA
+static unsigned int shdma = PVR2_CASCADE_CHAN;
+static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
+#endif
+
+static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue,
+                            unsigned int transp, struct fb_info *info);
+static int pvr2fb_blank(int blank, struct fb_info *info);
+static unsigned long get_line_length(int xres_virtual, int bpp);
+static void set_color_bitfields(struct fb_var_screeninfo *var);
+static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+static int pvr2fb_set_par(struct fb_info *info);
+static void pvr2_update_display(struct fb_info *info);
+static void pvr2_init_display(struct fb_info *info);
+static void pvr2_do_blank(void);
+static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id);
+static int pvr2_init_cable(void);
+static int pvr2_get_param(const struct pvr2_params *p, const char *s,
+                            int val, int size);
+#ifdef CONFIG_PVR2_DMA
+static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
+			    size_t count, loff_t *ppos);
+#endif
+
+static struct fb_ops pvr2fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= pvr2fb_setcolreg,
+	.fb_blank	= pvr2fb_blank,
+	.fb_check_var	= pvr2fb_check_var,
+	.fb_set_par	= pvr2fb_set_par,
+#ifdef CONFIG_PVR2_DMA
+	.fb_write	= pvr2fb_write,
+#endif
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static struct fb_videomode pvr2_modedb[] = {
+    /*
+     * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with
+     * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
+     * NTSC, so it shouldn't be a problem (I hope).
+     */
+
+    {
+	/* 640x480 @ 60Hz interlaced (NTSC) */
+	"ntsc_640x480i", 60, 640, 480, TV_CLK, 38, 33, 0, 18, 146, 26,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+    }, {
+	/* 640x240 @ 60Hz (NTSC) */
+	/* XXX: Broken! Don't use... */
+	"ntsc_640x240", 60, 640, 240, TV_CLK, 38, 33, 0, 0, 146, 22,
+	FB_SYNC_BROADCAST, FB_VMODE_YWRAP
+    }, {
+	/* 640x480 @ 60hz (VGA) */
+	"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,
+	0, FB_VMODE_YWRAP
+    },
+};
+
+#define NUM_TOTAL_MODES  ARRAY_SIZE(pvr2_modedb)
+
+#define DEFMODE_NTSC	0
+#define DEFMODE_PAL	0
+#define DEFMODE_VGA	2
+
+static int defmode = DEFMODE_NTSC;
+static char *mode_option = NULL;
+
+static inline void pvr2fb_set_pal_type(unsigned int type)
+{
+	struct pvr2fb_par *par = (struct pvr2fb_par *)fb_info->par;
+
+	fb_writel(type, par->mmio_base + 0x108);
+}
+
+static inline void pvr2fb_set_pal_entry(struct pvr2fb_par *par,
+					unsigned int regno,
+					unsigned int val)
+{
+	fb_writel(val, par->mmio_base + 0x1000 + (4 * regno));
+}
+
+static int pvr2fb_blank(int blank, struct fb_info *info)
+{
+	do_blank = blank ? blank : -1;
+	return 0;
+}
+
+static inline unsigned long get_line_length(int xres_virtual, int bpp)
+{
+	return (unsigned long)((((xres_virtual*bpp)+31)&~31) >> 3);
+}
+
+static void set_color_bitfields(struct fb_var_screeninfo *var)
+{
+	switch (var->bits_per_pixel) {
+	    case 16:        /* RGB 565 */
+		pvr2fb_set_pal_type(PAL_RGB565);
+		var->red.offset = 11;    var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 6;
+		var->blue.offset = 0;    var->blue.length = 5;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	    case 24:        /* RGB 888 */
+		var->red.offset = 16;    var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	    case 32:        /* ARGB 8888 */
+		pvr2fb_set_pal_type(PAL_ARGB8888);
+		var->red.offset = 16;    var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 24; var->transp.length = 8;
+		break;
+	}
+}
+
+static int pvr2fb_setcolreg(unsigned int regno, unsigned int red,
+			    unsigned int green, unsigned int blue,
+                            unsigned int transp, struct fb_info *info)
+{
+	struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
+	unsigned int tmp;
+
+	if (regno > info->cmap.len)
+		return 1;
+
+	/*
+	 * We only support the hardware palette for 16 and 32bpp. It's also
+	 * expected that the palette format has been set by the time we get
+	 * here, so we don't waste time setting it again.
+	 */
+	switch (info->var.bits_per_pixel) {
+	    case 16: /* RGB 565 */
+		tmp =  (red   & 0xf800)       |
+		      ((green & 0xfc00) >> 5) |
+		      ((blue  & 0xf800) >> 11);
+
+		pvr2fb_set_pal_entry(par, regno, tmp);
+		break;
+	    case 24: /* RGB 888 */
+		red >>= 8; green >>= 8; blue >>= 8;
+		tmp = (red << 16) | (green << 8) | blue;
+		break;
+	    case 32: /* ARGB 8888 */
+		red >>= 8; green >>= 8; blue >>= 8;
+		tmp = (transp << 24) | (red << 16) | (green << 8) | blue;
+
+		pvr2fb_set_pal_entry(par, regno, tmp);
+		break;
+	    default:
+		pr_debug("Invalid bit depth %d?!?\n", info->var.bits_per_pixel);
+		return 1;
+	}
+
+	if (regno < 16)
+		((u32*)(info->pseudo_palette))[regno] = tmp;
+
+	return 0;
+}
+
+static int pvr2fb_set_par(struct fb_info *info)
+{
+	struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned long line_length;
+	unsigned int vtotal;
+
+	/*
+	 * XXX: It's possible that a user could use a VGA box, change the cable
+	 * type in hardware (i.e. switch from VGA<->composite), then change
+	 * modes (i.e. switching to another VT).  If that happens we should
+	 * automagically change the output format to cope, but currently I
+	 * don't have a VGA box to make sure this works properly.
+	 */
+	cable_type = pvr2_init_cable();
+	if (cable_type == CT_VGA && video_output != VO_VGA)
+		video_output = VO_VGA;
+
+	var->vmode &= FB_VMODE_MASK;
+	if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
+		par->is_interlaced = 1;
+	/*
+	 * XXX: Need to be more creative with this (i.e. allow doublecan for
+	 * PAL/NTSC output).
+	 */
+	if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA)
+		par->is_doublescan = 1;
+
+	par->hsync_total = var->left_margin + var->xres + var->right_margin +
+	                   var->hsync_len;
+	par->vsync_total = var->upper_margin + var->yres + var->lower_margin +
+	                   var->vsync_len;
+
+	if (var->sync & FB_SYNC_BROADCAST) {
+		vtotal = par->vsync_total;
+		if (par->is_interlaced)
+			vtotal /= 2;
+		if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) {
+			/* XXX: Check for start values here... */
+			/* XXX: Check hardware for PAL-compatibility */
+			par->borderstart_h = 116;
+			par->borderstart_v = 44;
+		} else {
+			/* NTSC video output */
+			par->borderstart_h = 126;
+			par->borderstart_v = 18;
+		}
+	} else {
+		/* VGA mode */
+		/* XXX: What else needs to be checked? */
+		/*
+		 * XXX: We have a little freedom in VGA modes, what ranges
+		 * should be here (i.e. hsync/vsync totals, etc.)?
+		 */
+		par->borderstart_h = 126;
+		par->borderstart_v = 40;
+	}
+
+	/* Calculate the remainding offsets */
+	par->diwstart_h = par->borderstart_h + var->left_margin;
+	par->diwstart_v = par->borderstart_v + var->upper_margin;
+	par->borderstop_h = par->diwstart_h + var->xres +
+			    var->right_margin;
+	par->borderstop_v = par->diwstart_v + var->yres +
+			    var->lower_margin;
+
+	if (!par->is_interlaced)
+		par->borderstop_v /= 2;
+	if (info->var.xres < 640)
+		par->is_lowres = 1;
+
+	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+	par->disp_start = info->fix.smem_start + (line_length * var->yoffset) * line_length;
+	info->fix.line_length = line_length;
+	return 0;
+}
+
+static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
+	unsigned int vtotal, hsync_total;
+	unsigned long line_length;
+
+	if (var->pixclock != TV_CLK && var->pixclock != VGA_CLK) {
+		pr_debug("Invalid pixclock value %d\n", var->pixclock);
+		return -EINVAL;
+	}
+
+	if (var->xres < 320)
+		var->xres = 320;
+	if (var->yres < 240)
+		var->yres = 240;
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+
+	set_color_bitfields(var);
+
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->xoffset || var->yoffset < 0 ||
+		    var->yoffset >= var->yres_virtual) {
+			var->xoffset = var->yoffset = 0;
+		} else {
+			if (var->xoffset > var->xres_virtual - var->xres ||
+			    var->yoffset > var->yres_virtual - var->yres ||
+			    var->xoffset < 0 || var->yoffset < 0)
+				var->xoffset = var->yoffset = 0;
+		}
+	} else {
+		var->xoffset = var->yoffset = 0;
+	}
+
+	/*
+	 * XXX: Need to be more creative with this (i.e. allow doublecan for
+	 * PAL/NTSC output).
+	 */
+	if (var->yres < 480 && video_output == VO_VGA)
+		var->vmode |= FB_VMODE_DOUBLE;
+
+	if (video_output != VO_VGA) {
+		var->sync |= FB_SYNC_BROADCAST;
+		var->vmode |= FB_VMODE_INTERLACED;
+	} else {
+		var->sync &= ~FB_SYNC_BROADCAST;
+		var->vmode &= ~FB_VMODE_INTERLACED;
+		var->vmode |= FB_VMODE_NONINTERLACED;
+	}
+
+	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_TEST) {
+		var->right_margin = par->borderstop_h -
+				   (par->diwstart_h + var->xres);
+		var->left_margin  = par->diwstart_h - par->borderstart_h;
+		var->hsync_len    = par->borderstart_h +
+		                   (par->hsync_total - par->borderstop_h);
+
+		var->upper_margin = par->diwstart_v - par->borderstart_v;
+		var->lower_margin = par->borderstop_v -
+				   (par->diwstart_v + var->yres);
+		var->vsync_len    = par->borderstop_v +
+				   (par->vsync_total - par->borderstop_v);
+	}
+
+	hsync_total = var->left_margin + var->xres + var->right_margin +
+		      var->hsync_len;
+	vtotal = var->upper_margin + var->yres + var->lower_margin +
+		 var->vsync_len;
+
+	if (var->sync & FB_SYNC_BROADCAST) {
+		if (var->vmode & FB_VMODE_INTERLACED)
+			vtotal /= 2;
+		if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) {
+			/* PAL video output */
+			/* XXX: Should be using a range here ... ? */
+			if (hsync_total != PAL_HTOTAL) {
+				pr_debug("invalid hsync total for PAL\n");
+				return -EINVAL;
+			}
+		} else {
+			/* NTSC video output */
+			if (hsync_total != NTSC_HTOTAL) {
+				pr_debug("invalid hsync total for NTSC\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* Check memory sizes */
+	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > info->fix.smem_len)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void pvr2_update_display(struct fb_info *info)
+{
+	struct pvr2fb_par *par = (struct pvr2fb_par *) info->par;
+	struct fb_var_screeninfo *var = &info->var;
+
+	/* Update the start address of the display image */
+	fb_writel(par->disp_start, DISP_DIWADDRL);
+	fb_writel(par->disp_start +
+		  get_line_length(var->xoffset+var->xres, var->bits_per_pixel),
+	          DISP_DIWADDRS);
+}
+
+/*
+ * Initialize the video mode.  Currently, the 16bpp and 24bpp modes aren't
+ * very stable.  It's probably due to the fact that a lot of the 2D video
+ * registers are still undocumented.
+ */
+
+static void pvr2_init_display(struct fb_info *info)
+{
+	struct pvr2fb_par *par = (struct pvr2fb_par *) info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned int diw_height, diw_width, diw_modulo = 1;
+	unsigned int bytesperpixel = var->bits_per_pixel >> 3;
+
+	/* hsync and vsync totals */
+	fb_writel((par->vsync_total << 16) | par->hsync_total, DISP_SYNCSIZE);
+
+	/* column height, modulo, row width */
+	/* since we're "panning" within vram, we need to offset things based
+	 * on the offset from the virtual x start to our real gfx. */
+	if (video_output != VO_VGA && par->is_interlaced)
+		diw_modulo += info->fix.line_length / 4;
+	diw_height = (par->is_interlaced ? var->yres / 2 : var->yres);
+	diw_width = get_line_length(var->xres, var->bits_per_pixel) / 4;
+	fb_writel((diw_modulo << 20) | (--diw_height << 10) | --diw_width,
+	          DISP_DIWSIZE);
+
+	/* display address, long and short fields */
+	fb_writel(par->disp_start, DISP_DIWADDRL);
+	fb_writel(par->disp_start +
+	          get_line_length(var->xoffset+var->xres, var->bits_per_pixel),
+	          DISP_DIWADDRS);
+
+	/* border horizontal, border vertical, border color */
+	fb_writel((par->borderstart_h << 16) | par->borderstop_h, DISP_BRDRHORZ);
+	fb_writel((par->borderstart_v << 16) | par->borderstop_v, DISP_BRDRVERT);
+	fb_writel(0, DISP_BRDRCOLR);
+
+	/* display window start position */
+	fb_writel(par->diwstart_h, DISP_DIWHSTRT);
+	fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT);
+
+	/* misc. settings */
+	fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF);
+
+	/* clock doubler (for VGA), scan doubler, display enable */
+	fb_writel(((video_output == VO_VGA) << 23) |
+	          (par->is_doublescan << 1) | 1, DISP_DIWMODE);
+
+	/* bits per pixel */
+	fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
+	fb_writel(bytesperpixel << 2, DISP_PIXDEPTH);
+
+	/* video enable, color sync, interlace,
+	 * hsync and vsync polarity (currently unused) */
+	fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
+}
+
+/* Simulate blanking by making the border cover the entire screen */
+
+#define BLANK_BIT (1<<3)
+
+static void pvr2_do_blank(void)
+{
+	struct pvr2fb_par *par = currentpar;
+	unsigned long diwconf;
+
+	diwconf = fb_readl(DISP_DIWCONF);
+	if (do_blank > 0)
+		fb_writel(diwconf | BLANK_BIT, DISP_DIWCONF);
+	else
+		fb_writel(diwconf & ~BLANK_BIT, DISP_DIWCONF);
+
+	is_blanked = do_blank > 0 ? do_blank : 0;
+}
+
+static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id)
+{
+	struct fb_info *info = dev_id;
+
+	if (do_vmode_pan || do_vmode_full)
+		pvr2_update_display(info);
+	if (do_vmode_full)
+		pvr2_init_display(info);
+	if (do_vmode_pan)
+		do_vmode_pan = 0;
+	if (do_vmode_full)
+		do_vmode_full = 0;
+	if (do_blank) {
+		pvr2_do_blank();
+		do_blank = 0;
+	}
+	return IRQ_HANDLED;
+}
+
+/*
+ * Determine the cable type and initialize the cable output format.  Don't do
+ * anything if the cable type has been overidden (via "cable:XX").
+ */
+
+#define PCTRA 0xff80002c
+#define PDTRA 0xff800030
+#define VOUTC 0xa0702c00
+
+static int pvr2_init_cable(void)
+{
+	if (cable_type < 0) {
+		fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
+	                  PCTRA);
+		cable_type = (fb_readw(PDTRA) >> 8) & 3;
+	}
+
+	/* Now select the output format (either composite or other) */
+	/* XXX: Save the previous val first, as this reg is also AICA
+	  related */
+	if (cable_type == CT_COMPOSITE)
+		fb_writel(3 << 8, VOUTC);
+	else if (cable_type == CT_RGB)
+		fb_writel(1 << 9, VOUTC);
+	else
+		fb_writel(0, VOUTC);
+
+	return cable_type;
+}
+
+#ifdef CONFIG_PVR2_DMA
+static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
+			    size_t count, loff_t *ppos)
+{
+	unsigned long dst, start, end, len;
+	unsigned int nr_pages;
+	struct page **pages;
+	int ret, i;
+
+	nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+	if (!pages)
+		return -ENOMEM;
+
+	down_read(&current->mm->mmap_sem);
+	ret = get_user_pages(current, current->mm, (unsigned long)buf,
+			     nr_pages, WRITE, 0, pages, NULL);
+	up_read(&current->mm->mmap_sem);
+
+	if (ret < nr_pages) {
+		nr_pages = ret;
+		ret = -EINVAL;
+		goto out_unmap;
+	}
+
+	dma_configure_channel(shdma, 0x12c1);
+
+	dst   = (unsigned long)fb_info->screen_base + *ppos;
+	start = (unsigned long)page_address(pages[0]);
+	end   = (unsigned long)page_address(pages[nr_pages]);
+	len   = nr_pages << PAGE_SHIFT;
+
+	/* Half-assed contig check */
+	if (start + len == end) {
+		/* As we do this in one shot, it's either all or nothing.. */
+		if ((*ppos + len) > fb_info->fix.smem_len) {
+			ret = -ENOSPC;
+			goto out_unmap;
+		}
+
+		dma_write(shdma, start, 0, len);
+		dma_write(pvr2dma, 0, dst, len);
+		dma_wait_for_completion(pvr2dma);
+
+		goto out;
+	}
+
+	/* Not contiguous, writeout per-page instead.. */
+	for (i = 0; i < nr_pages; i++, dst += PAGE_SIZE) {
+		if ((*ppos + (i << PAGE_SHIFT)) > fb_info->fix.smem_len) {
+			ret = -ENOSPC;
+			goto out_unmap;
+		}
+
+		dma_write_page(shdma, (unsigned long)page_address(pages[i]), 0);
+		dma_write_page(pvr2dma, 0, dst);
+		dma_wait_for_completion(pvr2dma);
+	}
+
+out:
+	*ppos += count;
+	ret = count;
+
+out_unmap:
+	for (i = 0; i < nr_pages; i++)
+		page_cache_release(pages[i]);
+
+	kfree(pages);
+
+	return ret;
+}
+#endif /* CONFIG_PVR2_DMA */
+
+/**
+ * pvr2fb_common_init
+ *
+ * Common init code for the PVR2 chips.
+ *
+ * This mostly takes care of the common aspects of the fb setup and
+ * registration. It's expected that the board-specific init code has
+ * already setup pvr2_fix with something meaningful at this point.
+ *
+ * Device info reporting is also done here, as well as picking a sane
+ * default from the modedb. For board-specific modelines, simply define
+ * a per-board modedb.
+ *
+ * Also worth noting is that the cable and video output types are likely
+ * always going to be VGA for the PCI-based PVR2 boards, but we leave this
+ * in for flexibility anyways. Who knows, maybe someone has tv-out on a
+ * PCI-based version of these things ;-)
+ */
+static int pvr2fb_common_init(void)
+{
+	struct pvr2fb_par *par = currentpar;
+	unsigned long modememused, rev;
+
+	fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start,
+					       pvr2_fix.smem_len);
+
+	if (!fb_info->screen_base) {
+		printk(KERN_ERR "pvr2fb: Failed to remap smem space\n");
+		goto out_err;
+	}
+
+	par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start,
+							pvr2_fix.mmio_len);
+	if (!par->mmio_base) {
+		printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n");
+		goto out_err;
+	}
+
+	fb_memset(fb_info->screen_base, 0, pvr2_fix.smem_len);
+
+	pvr2_fix.ypanstep	= nopan  ? 0 : 1;
+	pvr2_fix.ywrapstep	= nowrap ? 0 : 1;
+
+	fb_info->fbops		= &pvr2fb_ops;
+	fb_info->fix		= pvr2_fix;
+	fb_info->par		= currentpar;
+	fb_info->pseudo_palette	= currentpar->palette;
+	fb_info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	if (video_output == VO_VGA)
+		defmode = DEFMODE_VGA;
+
+	if (!mode_option)
+		mode_option = "640x480@60";
+
+	if (!fb_find_mode(&fb_info->var, fb_info, mode_option, pvr2_modedb,
+	                  NUM_TOTAL_MODES, &pvr2_modedb[defmode], 16))
+		fb_info->var = pvr2_var;
+
+	fb_alloc_cmap(&fb_info->cmap, 256, 0);
+
+	if (register_framebuffer(fb_info) < 0)
+		goto out_err;
+	/*Must write PIXDEPTH to register before anything is displayed - so force init */
+	pvr2_init_display(fb_info);
+
+	modememused = get_line_length(fb_info->var.xres_virtual,
+				      fb_info->var.bits_per_pixel);
+	modememused *= fb_info->var.yres_virtual;
+
+	rev = fb_readl(par->mmio_base + 0x04);
+
+	fb_info(fb_info, "%s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n",
+		fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f,
+		modememused >> 10,
+		(unsigned long)(fb_info->fix.smem_len >> 10));
+	fb_info(fb_info, "Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
+		fb_info->var.xres, fb_info->var.yres,
+		fb_info->var.bits_per_pixel,
+		get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
+		(char *)pvr2_get_param(cables, NULL, cable_type, 3),
+		(char *)pvr2_get_param(outputs, NULL, video_output, 3));
+
+#ifdef CONFIG_SH_STORE_QUEUES
+	fb_notice(fb_info, "registering with SQ API\n");
+
+	pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
+			      fb_info->fix.id, PAGE_SHARED);
+
+	fb_notice(fb_info, "Mapped video memory to SQ addr 0x%lx\n",
+		  pvr2fb_map);
+#endif
+
+	return 0;
+
+out_err:
+	if (fb_info->screen_base)
+		iounmap(fb_info->screen_base);
+	if (par->mmio_base)
+		iounmap((void *)par->mmio_base);
+
+	return -ENXIO;
+}
+
+#ifdef CONFIG_SH_DREAMCAST
+static int __init pvr2fb_dc_init(void)
+{
+	if (!mach_is_dreamcast())
+		return -ENXIO;
+
+	/* Make a guess at the monitor based on the attached cable */
+	if (pvr2_init_cable() == CT_VGA) {
+		fb_info->monspecs.hfmin = 30000;
+		fb_info->monspecs.hfmax = 70000;
+		fb_info->monspecs.vfmin = 60;
+		fb_info->monspecs.vfmax = 60;
+	} else {
+		/* Not VGA, using a TV (taken from acornfb) */
+		fb_info->monspecs.hfmin = 15469;
+		fb_info->monspecs.hfmax = 15781;
+		fb_info->monspecs.vfmin = 49;
+		fb_info->monspecs.vfmax = 51;
+	}
+
+	/*
+	 * XXX: This needs to pull default video output via BIOS or other means
+	 */
+	if (video_output < 0) {
+		if (cable_type == CT_VGA) {
+			video_output = VO_VGA;
+		} else {
+			video_output = VO_NTSC;
+		}
+	}
+
+	/*
+	 * Nothing exciting about the DC PVR2 .. only a measly 8MiB.
+	 */
+	pvr2_fix.smem_start	= 0xa5000000;	/* RAM starts here */
+	pvr2_fix.smem_len	= 8 << 20;
+
+	pvr2_fix.mmio_start	= 0xa05f8000;	/* registers start here */
+	pvr2_fix.mmio_len	= 0x2000;
+
+	if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, IRQF_SHARED,
+	                "pvr2 VBL handler", fb_info)) {
+		return -EBUSY;
+	}
+
+#ifdef CONFIG_PVR2_DMA
+	if (request_dma(pvr2dma, "pvr2") != 0) {
+		free_irq(HW_EVENT_VSYNC, fb_info);
+		return -EBUSY;
+	}
+#endif
+
+	return pvr2fb_common_init();
+}
+
+static void __exit pvr2fb_dc_exit(void)
+{
+	if (fb_info->screen_base) {
+		iounmap(fb_info->screen_base);
+		fb_info->screen_base = NULL;
+	}
+	if (currentpar->mmio_base) {
+		iounmap((void *)currentpar->mmio_base);
+		currentpar->mmio_base = 0;
+	}
+
+	free_irq(HW_EVENT_VSYNC, fb_info);
+#ifdef CONFIG_PVR2_DMA
+	free_dma(pvr2dma);
+#endif
+}
+#endif /* CONFIG_SH_DREAMCAST */
+
+#ifdef CONFIG_PCI
+static int pvr2fb_pci_probe(struct pci_dev *pdev,
+			    const struct pci_device_id *ent)
+{
+	int ret;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		printk(KERN_ERR "pvr2fb: PCI enable failed\n");
+		return ret;
+	}
+
+	ret = pci_request_regions(pdev, "pvr2fb");
+	if (ret) {
+		printk(KERN_ERR "pvr2fb: PCI request regions failed\n");
+		return ret;
+	}
+
+	/*
+	 * Slightly more exciting than the DC PVR2 .. 16MiB!
+	 */
+	pvr2_fix.smem_start	= pci_resource_start(pdev, 0);
+	pvr2_fix.smem_len	= pci_resource_len(pdev, 0);
+
+	pvr2_fix.mmio_start	= pci_resource_start(pdev, 1);
+	pvr2_fix.mmio_len	= pci_resource_len(pdev, 1);
+
+	fb_info->device		= &pdev->dev;
+
+	return pvr2fb_common_init();
+}
+
+static void pvr2fb_pci_remove(struct pci_dev *pdev)
+{
+	if (fb_info->screen_base) {
+		iounmap(fb_info->screen_base);
+		fb_info->screen_base = NULL;
+	}
+	if (currentpar->mmio_base) {
+		iounmap((void *)currentpar->mmio_base);
+		currentpar->mmio_base = 0;
+	}
+
+	pci_release_regions(pdev);
+}
+
+static struct pci_device_id pvr2fb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NEON250,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, pvr2fb_pci_tbl);
+
+static struct pci_driver pvr2fb_pci_driver = {
+	.name		= "pvr2fb",
+	.id_table	= pvr2fb_pci_tbl,
+	.probe		= pvr2fb_pci_probe,
+	.remove		= pvr2fb_pci_remove,
+};
+
+static int __init pvr2fb_pci_init(void)
+{
+	return pci_register_driver(&pvr2fb_pci_driver);
+}
+
+static void __exit pvr2fb_pci_exit(void)
+{
+	pci_unregister_driver(&pvr2fb_pci_driver);
+}
+#endif /* CONFIG_PCI */
+
+static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val,
+			  int size)
+{
+	int i;
+
+	for (i = 0 ; i < size ; i++ ) {
+		if (s != NULL) {
+			if (!strnicmp(p[i].name, s, strlen(s)))
+				return p[i].val;
+		} else {
+			if (p[i].val == val)
+				return (int)p[i].name;
+		}
+	}
+	return -1;
+}
+
+/*
+ * Parse command arguments.  Supported arguments are:
+ *    inverse                             Use inverse color maps
+ *    cable:composite|rgb|vga             Override the video cable type
+ *    output:NTSC|PAL|VGA                 Override the video output format
+ *
+ *    <xres>x<yres>[-<bpp>][@<refresh>]   or,
+ *    <name>[-<bpp>][@<refresh>]          Startup using this video mode
+ */
+
+#ifndef MODULE
+static int __init pvr2fb_setup(char *options)
+{
+	char *this_opt;
+	char cable_arg[80];
+	char output_arg[80];
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ","))) {
+		if (!*this_opt)
+			continue;
+		if (!strcmp(this_opt, "inverse")) {
+			fb_invert_cmaps();
+		} else if (!strncmp(this_opt, "cable:", 6)) {
+			strcpy(cable_arg, this_opt + 6);
+		} else if (!strncmp(this_opt, "output:", 7)) {
+			strcpy(output_arg, this_opt + 7);
+		} else if (!strncmp(this_opt, "nopan", 5)) {
+			nopan = 1;
+		} else if (!strncmp(this_opt, "nowrap", 6)) {
+			nowrap = 1;
+		} else {
+			mode_option = this_opt;
+		}
+	}
+
+	if (*cable_arg)
+		cable_type = pvr2_get_param(cables, cable_arg, 0, 3);
+	if (*output_arg)
+		video_output = pvr2_get_param(outputs, output_arg, 0, 3);
+
+	return 0;
+}
+#endif
+
+static struct pvr2_board {
+	int (*init)(void);
+	void (*exit)(void);
+	char name[16];
+} board_driver[] __refdata = {
+#ifdef CONFIG_SH_DREAMCAST
+	{ pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" },
+#endif
+#ifdef CONFIG_PCI
+	{ pvr2fb_pci_init, pvr2fb_pci_exit, "PCI PVR2" },
+#endif
+	{ 0, },
+};
+
+static int __init pvr2fb_init(void)
+{
+	int i, ret = -ENODEV;
+	int size;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pvr2fb", &option))
+		return -ENODEV;
+	pvr2fb_setup(option);
+#endif
+	size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
+
+	fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL);
+
+	if (!fb_info) {
+		printk(KERN_ERR "Failed to allocate memory for fb_info\n");
+		return -ENOMEM;
+	}
+
+
+	currentpar = fb_info->par;
+
+	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+		struct pvr2_board *pvr_board = board_driver + i;
+
+		if (!pvr_board->init)
+			continue;
+
+		ret = pvr_board->init();
+
+		if (ret != 0) {
+			printk(KERN_ERR "pvr2fb: Failed init of %s device\n",
+				pvr_board->name);
+			framebuffer_release(fb_info);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static void __exit pvr2fb_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+		struct pvr2_board *pvr_board = board_driver + i;
+
+		if (pvr_board->exit)
+			pvr_board->exit();
+	}
+
+#ifdef CONFIG_SH_STORE_QUEUES
+	sq_unmap(pvr2fb_map);
+#endif
+
+	unregister_framebuffer(fb_info);
+	framebuffer_release(fb_info);
+}
+
+module_init(pvr2fb_init);
+module_exit(pvr2fb_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
+MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c
new file mode 100644
index 000000000000..c95b9e46d48f
--- /dev/null
+++ b/drivers/video/fbdev/pxa168fb.c
@@ -0,0 +1,837 @@
+/*
+ * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller
+ *
+ *  Copyright (C) 2008 Marvell International Ltd.
+ *  All rights reserved.
+ *
+ *  2009-02-16  adapted from original version for PXA168/910
+ *              Jun Nie <njun@marvell.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <video/pxa168fb.h>
+
+#include "pxa168fb.h"
+
+#define DEFAULT_REFRESH		60	/* Hz */
+
+static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
+{
+	/*
+	 * Pseudocolor mode?
+	 */
+	if (var->bits_per_pixel == 8)
+		return PIX_FMT_PSEUDOCOLOR;
+
+	/*
+	 * Check for 565/1555.
+	 */
+	if (var->bits_per_pixel == 16 && var->red.length <= 5 &&
+	    var->green.length <= 6 && var->blue.length <= 5) {
+		if (var->transp.length == 0) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB565;
+			else
+				return PIX_FMT_BGR565;
+		}
+
+		if (var->transp.length == 1 && var->green.length <= 5) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB1555;
+			else
+				return PIX_FMT_BGR1555;
+		}
+
+		/* fall through */
+	}
+
+	/*
+	 * Check for 888/A888.
+	 */
+	if (var->bits_per_pixel <= 32 && var->red.length <= 8 &&
+	    var->green.length <= 8 && var->blue.length <= 8) {
+		if (var->bits_per_pixel == 24 && var->transp.length == 0) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB888PACK;
+			else
+				return PIX_FMT_BGR888PACK;
+		}
+
+		if (var->bits_per_pixel == 32 && var->transp.length == 8) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGBA888;
+			else
+				return PIX_FMT_BGRA888;
+		} else {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB888UNPACK;
+			else
+				return PIX_FMT_BGR888UNPACK;
+		}
+
+		/* fall through */
+	}
+
+	return -EINVAL;
+}
+
+static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt)
+{
+	switch (pix_fmt) {
+	case PIX_FMT_RGB565:
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;    var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 6;
+		var->blue.offset = 0;    var->blue.length = 5;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_BGR565:
+		var->bits_per_pixel = 16;
+		var->red.offset = 0;     var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 6;
+		var->blue.offset = 11;   var->blue.length = 5;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_RGB1555:
+		var->bits_per_pixel = 16;
+		var->red.offset = 10;    var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 5;
+		var->blue.offset = 0;    var->blue.length = 5;
+		var->transp.offset = 15; var->transp.length = 1;
+		break;
+	case PIX_FMT_BGR1555:
+		var->bits_per_pixel = 16;
+		var->red.offset = 0;     var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 5;
+		var->blue.offset = 10;   var->blue.length = 5;
+		var->transp.offset = 15; var->transp.length = 1;
+		break;
+	case PIX_FMT_RGB888PACK:
+		var->bits_per_pixel = 24;
+		var->red.offset = 16;    var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_BGR888PACK:
+		var->bits_per_pixel = 24;
+		var->red.offset = 0;     var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 16;   var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_RGBA888:
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;    var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 24; var->transp.length = 8;
+		break;
+	case PIX_FMT_BGRA888:
+		var->bits_per_pixel = 32;
+		var->red.offset = 0;     var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 16;   var->blue.length = 8;
+		var->transp.offset = 24; var->transp.length = 8;
+		break;
+	case PIX_FMT_PSEUDOCOLOR:
+		var->bits_per_pixel = 8;
+		var->red.offset = 0;     var->red.length = 8;
+		var->green.offset = 0;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	}
+}
+
+static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var,
+		     struct fb_videomode *mode, int pix_fmt, int ystretch)
+{
+	struct fb_info *info = fbi->info;
+
+	set_pix_fmt(var, pix_fmt);
+
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->xres_virtual = max(var->xres, var->xres_virtual);
+	if (ystretch)
+		var->yres_virtual = info->fix.smem_len /
+			(var->xres_virtual * (var->bits_per_pixel >> 3));
+	else
+		var->yres_virtual = max(var->yres, var->yres_virtual);
+	var->grayscale = 0;
+	var->accel_flags = FB_ACCEL_NONE;
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->sync = mode->sync;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	var->rotate = FB_ROTATE_UR;
+}
+
+static int pxa168fb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	int pix_fmt;
+
+	/*
+	 * Determine which pixel format we're going to use.
+	 */
+	pix_fmt = determine_best_pix_fmt(var);
+	if (pix_fmt < 0)
+		return pix_fmt;
+	set_pix_fmt(var, pix_fmt);
+	fbi->pix_fmt = pix_fmt;
+
+	/*
+	 * Basic geometry sanity checks.
+	 */
+	if (var->xoffset + var->xres > var->xres_virtual)
+		return -EINVAL;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		return -EINVAL;
+	if (var->xres + var->right_margin +
+	    var->hsync_len + var->left_margin > 2048)
+		return -EINVAL;
+	if (var->yres + var->lower_margin +
+	    var->vsync_len + var->upper_margin > 2048)
+		return -EINVAL;
+
+	/*
+	 * Check size of framebuffer.
+	 */
+	if (var->xres_virtual * var->yres_virtual *
+	    (var->bits_per_pixel >> 3) > info->fix.smem_len)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * The hardware clock divider has an integer and a fractional
+ * stage:
+ *
+ *	clk2 = clk_in / integer_divider
+ *	clk_out = clk2 * (1 - (fractional_divider >> 12))
+ *
+ * Calculate integer and fractional divider for given clk_in
+ * and clk_out.
+ */
+static void set_clock_divider(struct pxa168fb_info *fbi,
+			      const struct fb_videomode *m)
+{
+	int divider_int;
+	int needed_pixclk;
+	u64 div_result;
+	u32 x = 0;
+
+	/*
+	 * Notice: The field pixclock is used by linux fb
+	 * is in pixel second. E.g. struct fb_videomode &
+	 * struct fb_var_screeninfo
+	 */
+
+	/*
+	 * Check input values.
+	 */
+	if (!m || !m->pixclock || !m->refresh) {
+		dev_err(fbi->dev, "Input refresh or pixclock is wrong.\n");
+		return;
+	}
+
+	/*
+	 * Using PLL/AXI clock.
+	 */
+	x = 0x80000000;
+
+	/*
+	 * Calc divider according to refresh rate.
+	 */
+	div_result = 1000000000000ll;
+	do_div(div_result, m->pixclock);
+	needed_pixclk = (u32)div_result;
+
+	divider_int = clk_get_rate(fbi->clk) / needed_pixclk;
+
+	/* check whether divisor is too small. */
+	if (divider_int < 2) {
+		dev_warn(fbi->dev, "Warning: clock source is too slow."
+				"Try smaller resolution\n");
+		divider_int = 2;
+	}
+
+	/*
+	 * Set setting to reg.
+	 */
+	x |= divider_int;
+	writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV);
+}
+
+static void set_dma_control0(struct pxa168fb_info *fbi)
+{
+	u32 x;
+
+	/*
+	 * Set bit to enable graphics DMA.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
+	x &= ~CFG_GRA_ENA_MASK;
+	x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0);
+
+	/*
+	 * If we are in a pseudo-color mode, we need to enable
+	 * palette lookup.
+	 */
+	if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
+		x |= 0x10000000;
+
+	/*
+	 * Configure hardware pixel format.
+	 */
+	x &= ~(0xF << 16);
+	x |= (fbi->pix_fmt >> 1) << 16;
+
+	/*
+	 * Check red and blue pixel swap.
+	 * 1. source data swap
+	 * 2. panel output data swap
+	 */
+	x &= ~(1 << 12);
+	x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12;
+
+	writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0);
+}
+
+static void set_dma_control1(struct pxa168fb_info *fbi, int sync)
+{
+	u32 x;
+
+	/*
+	 * Configure default bits: vsync triggers DMA, gated clock
+	 * enable, power save enable, configure alpha registers to
+	 * display 100% graphics, and set pixel command.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1);
+	x |= 0x2032ff81;
+
+	/*
+	 * We trigger DMA on the falling edge of vsync if vsync is
+	 * active low, or on the rising edge if vsync is active high.
+	 */
+	if (!(sync & FB_SYNC_VERT_HIGH_ACT))
+		x |= 0x08000000;
+
+	writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1);
+}
+
+static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int pixel_offset;
+	unsigned long addr;
+
+	pixel_offset = (yoffset * var->xres_virtual) + xoffset;
+
+	addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3));
+	writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0);
+}
+
+static void set_dumb_panel_control(struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct pxa168fb_mach_info *mi = dev_get_platdata(fbi->dev);
+	u32 x;
+
+	/*
+	 * Preserve enable flag.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001;
+
+	x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28;
+	x |= mi->gpio_output_data << 20;
+	x |= mi->gpio_output_mask << 12;
+	x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0;
+	x |= mi->invert_composite_blank ? 0x00000040 : 0;
+	x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0;
+	x |= mi->invert_pix_val_ena ? 0x00000010 : 0;
+	x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008;
+	x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004;
+	x |= mi->invert_pixclock ? 0x00000002 : 0;
+
+	writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL);
+}
+
+static void set_dumb_screen_dimensions(struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *v = &info->var;
+	int x;
+	int y;
+
+	x = v->xres + v->right_margin + v->hsync_len + v->left_margin;
+	y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin;
+
+	writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL);
+}
+
+static int pxa168fb_set_par(struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_videomode mode;
+	u32 x;
+	struct pxa168fb_mach_info *mi;
+
+	mi = dev_get_platdata(fbi->dev);
+
+	/*
+	 * Set additional mode info.
+	 */
+	if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	info->fix.ypanstep = var->yres;
+
+	/*
+	 * Disable panel output while we setup the display.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
+	writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
+
+	/*
+	 * Configure global panel parameters.
+	 */
+	writel((var->yres << 16) | var->xres,
+		fbi->reg_base + LCD_SPU_V_H_ACTIVE);
+
+	/*
+	 * convet var to video mode
+	 */
+	fb_var_to_videomode(&mode, &info->var);
+
+	/* Calculate clock divisor. */
+	set_clock_divider(fbi, &mode);
+
+	/* Configure dma ctrl regs. */
+	set_dma_control0(fbi);
+	set_dma_control1(fbi, info->var.sync);
+
+	/*
+	 * Configure graphics DMA parameters.
+	 */
+	x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH);
+	x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3);
+	writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH);
+	writel((var->yres << 16) | var->xres,
+		fbi->reg_base + LCD_SPU_GRA_HPXL_VLN);
+	writel((var->yres << 16) | var->xres,
+		fbi->reg_base + LCD_SPU_GZM_HPXL_VLN);
+
+	/*
+	 * Configure dumb panel ctrl regs & timings.
+	 */
+	set_dumb_panel_control(info);
+	set_dumb_screen_dimensions(info);
+
+	writel((var->left_margin << 16) | var->right_margin,
+			fbi->reg_base + LCD_SPU_H_PORCH);
+	writel((var->upper_margin << 16) | var->lower_margin,
+			fbi->reg_base + LCD_SPU_V_PORCH);
+
+	/*
+	 * Re-enable panel output.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
+	writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
+
+	return 0;
+}
+
+static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
+}
+
+static u32 to_rgb(u16 red, u16 green, u16 blue)
+{
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	return (red << 16) | (green << 8) | blue;
+}
+
+static int
+pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+		 unsigned int blue, unsigned int trans, struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	u32 val;
+
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) {
+		val =  chan_to_field(red,   &info->var.red);
+		val |= chan_to_field(green, &info->var.green);
+		val |= chan_to_field(blue , &info->var.blue);
+		fbi->pseudo_palette[regno] = val;
+	}
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
+		val = to_rgb(red, green, blue);
+		writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT);
+		writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL);
+	}
+
+	return 0;
+}
+
+static int pxa168fb_blank(int blank, struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+
+	fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1;
+	set_dumb_panel_control(info);
+
+	return 0;
+}
+
+static int pxa168fb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	set_graphics_start(info, var->xoffset, var->yoffset);
+
+	return 0;
+}
+
+static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id)
+{
+	struct pxa168fb_info *fbi = dev_id;
+	u32 isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+
+	if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) {
+
+		writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK),
+			fbi->reg_base + SPU_IRQ_ISR);
+
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static struct fb_ops pxa168fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= pxa168fb_check_var,
+	.fb_set_par	= pxa168fb_set_par,
+	.fb_setcolreg	= pxa168fb_setcolreg,
+	.fb_blank	= pxa168fb_blank,
+	.fb_pan_display	= pxa168fb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int pxa168fb_init_mode(struct fb_info *info,
+			      struct pxa168fb_mach_info *mi)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int ret = 0;
+	u32 total_w, total_h, refresh;
+	u64 div_result;
+	const struct fb_videomode *m;
+
+	/*
+	 * Set default value
+	 */
+	refresh = DEFAULT_REFRESH;
+
+	/* try to find best video mode. */
+	m = fb_find_best_mode(&info->var, &info->modelist);
+	if (m)
+		fb_videomode_to_var(&info->var, m);
+
+	/* Init settings. */
+	var->xres_virtual = var->xres;
+	var->yres_virtual = info->fix.smem_len /
+		(var->xres_virtual * (var->bits_per_pixel >> 3));
+	dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n",
+				var->xres, var->yres);
+
+	/* correct pixclock. */
+	total_w = var->xres + var->left_margin + var->right_margin +
+		  var->hsync_len;
+	total_h = var->yres + var->upper_margin + var->lower_margin +
+		  var->vsync_len;
+
+	div_result = 1000000000000ll;
+	do_div(div_result, total_w * total_h * refresh);
+	var->pixclock = (u32)div_result;
+
+	return ret;
+}
+
+static int pxa168fb_probe(struct platform_device *pdev)
+{
+	struct pxa168fb_mach_info *mi;
+	struct fb_info *info = 0;
+	struct pxa168fb_info *fbi = 0;
+	struct resource *res;
+	struct clk *clk;
+	int irq, ret;
+
+	mi = dev_get_platdata(&pdev->dev);
+	if (mi == NULL) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
+
+	clk = clk_get(&pdev->dev, "LCDCLK");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "unable to get LCDCLK");
+		return PTR_ERR(clk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no IO memory defined\n");
+		ret = -ENOENT;
+		goto failed_put_clk;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		ret = -ENOENT;
+		goto failed_put_clk;
+	}
+
+	info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev);
+	if (info == NULL) {
+		ret = -ENOMEM;
+		goto failed_put_clk;
+	}
+
+	/* Initialize private data */
+	fbi = info->par;
+	fbi->info = info;
+	fbi->clk = clk;
+	fbi->dev = info->dev = &pdev->dev;
+	fbi->panel_rbswap = mi->panel_rbswap;
+	fbi->is_blanked = 0;
+	fbi->active = mi->active;
+
+	/*
+	 * Initialise static fb parameters.
+	 */
+	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
+		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+	info->node = -1;
+	strlcpy(info->fix.id, mi->id, 16);
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 0;
+	info->fix.ypanstep = 0;
+	info->fix.ywrapstep = 0;
+	info->fix.mmio_start = res->start;
+	info->fix.mmio_len = resource_size(res);
+	info->fix.accel = FB_ACCEL_NONE;
+	info->fbops = &pxa168fb_ops;
+	info->pseudo_palette = fbi->pseudo_palette;
+
+	/*
+	 * Map LCD controller registers.
+	 */
+	fbi->reg_base = devm_ioremap_nocache(&pdev->dev, res->start,
+					     resource_size(res));
+	if (fbi->reg_base == NULL) {
+		ret = -ENOMEM;
+		goto failed_free_info;
+	}
+
+	/*
+	 * Allocate framebuffer memory.
+	 */
+	info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE);
+
+	info->screen_base = dma_alloc_writecombine(fbi->dev, info->fix.smem_len,
+						&fbi->fb_start_dma, GFP_KERNEL);
+	if (info->screen_base == NULL) {
+		ret = -ENOMEM;
+		goto failed_free_info;
+	}
+
+	info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
+	set_graphics_start(info, 0, 0);
+
+	/*
+	 * Set video mode according to platform data.
+	 */
+	set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1);
+
+	fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist);
+
+	/*
+	 * init video mode data.
+	 */
+	pxa168fb_init_mode(info, mi);
+
+	/*
+	 * Fill in sane defaults.
+	 */
+	ret = pxa168fb_check_var(&info->var, info);
+	if (ret)
+		goto failed_free_fbmem;
+
+	/*
+	 * enable controller clock
+	 */
+	clk_enable(fbi->clk);
+
+	pxa168fb_set_par(info);
+
+	/*
+	 * Configure default register values.
+	 */
+	writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR);
+	writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL);
+	writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1);
+	writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN);
+	writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
+	writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
+		fbi->reg_base + LCD_SPU_SRAM_PARA1);
+
+	/*
+	 * Allocate color map.
+	 */
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		ret = -ENOMEM;
+		goto failed_free_clk;
+	}
+
+	/*
+	 * Register irq handler.
+	 */
+	ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
+			       IRQF_SHARED, info->fix.id, fbi);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to request IRQ\n");
+		ret = -ENXIO;
+		goto failed_free_cmap;
+	}
+
+	/*
+	 * Enable GFX interrupt
+	 */
+	writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA);
+
+	/*
+	 * Register framebuffer.
+	 */
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
+		ret = -ENXIO;
+		goto failed_free_cmap;
+	}
+
+	platform_set_drvdata(pdev, fbi);
+	return 0;
+
+failed_free_cmap:
+	fb_dealloc_cmap(&info->cmap);
+failed_free_clk:
+	clk_disable(fbi->clk);
+failed_free_fbmem:
+	dma_free_coherent(fbi->dev, info->fix.smem_len,
+			info->screen_base, fbi->fb_start_dma);
+failed_free_info:
+	kfree(info);
+failed_put_clk:
+	clk_put(clk);
+
+	dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret);
+	return ret;
+}
+
+static int pxa168fb_remove(struct platform_device *pdev)
+{
+	struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
+	struct fb_info *info;
+	int irq;
+	unsigned int data;
+
+	if (!fbi)
+		return 0;
+
+	/* disable DMA transfer */
+	data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
+	data &= ~CFG_GRA_ENA_MASK;
+	writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
+
+	info = fbi->info;
+
+	unregister_framebuffer(info);
+
+	writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
+
+	if (info->cmap.len)
+		fb_dealloc_cmap(&info->cmap);
+
+	irq = platform_get_irq(pdev, 0);
+
+	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+				info->screen_base, info->fix.smem_start);
+
+	clk_disable(fbi->clk);
+	clk_put(fbi->clk);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver pxa168fb_driver = {
+	.driver		= {
+		.name	= "pxa168-fb",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pxa168fb_probe,
+	.remove		= pxa168fb_remove,
+};
+
+module_platform_driver(pxa168fb_driver);
+
+MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
+	      "Green Wan <gwan@marvell.com>");
+MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/pxa168fb.h b/drivers/video/fbdev/pxa168fb.h
new file mode 100644
index 000000000000..eee09279c524
--- /dev/null
+++ b/drivers/video/fbdev/pxa168fb.h
@@ -0,0 +1,558 @@
+#ifndef __PXA168FB_H__
+#define __PXA168FB_H__
+
+/* ------------< LCD register >------------ */
+/* Video Frame 0&1 start address registers */
+#define	LCD_SPU_DMA_START_ADDR_Y0		0x00C0
+#define	LCD_SPU_DMA_START_ADDR_U0		0x00C4
+#define	LCD_SPU_DMA_START_ADDR_V0		0x00C8
+#define LCD_CFG_DMA_START_ADDR_0		0x00CC /* Cmd address */
+#define	LCD_SPU_DMA_START_ADDR_Y1		0x00D0
+#define	LCD_SPU_DMA_START_ADDR_U1		0x00D4
+#define	LCD_SPU_DMA_START_ADDR_V1		0x00D8
+#define LCD_CFG_DMA_START_ADDR_1		0x00DC /* Cmd address */
+
+/* YC & UV Pitch */
+#define LCD_SPU_DMA_PITCH_YC			0x00E0
+#define     SPU_DMA_PITCH_C(c)			((c) << 16)
+#define     SPU_DMA_PITCH_Y(y)			(y)
+#define LCD_SPU_DMA_PITCH_UV			0x00E4
+#define     SPU_DMA_PITCH_V(v)			((v) << 16)
+#define     SPU_DMA_PITCH_U(u)			(u)
+
+/* Video Starting Point on Screen Register */
+#define LCD_SPUT_DMA_OVSA_HPXL_VLN		0x00E8
+#define     CFG_DMA_OVSA_VLN(y)			((y) << 16) /* 0~0xfff */
+#define     CFG_DMA_OVSA_HPXL(x)		(x)     /* 0~0xfff */
+
+/* Video Size Register */
+#define LCD_SPU_DMA_HPXL_VLN			0x00EC
+#define     CFG_DMA_VLN(y)			((y) << 16)
+#define     CFG_DMA_HPXL(x)			(x)
+
+/* Video Size After zooming Register */
+#define LCD_SPU_DZM_HPXL_VLN			0x00F0
+#define     CFG_DZM_VLN(y)			((y) << 16)
+#define     CFG_DZM_HPXL(x)			(x)
+
+/* Graphic Frame 0&1 Starting Address Register */
+#define LCD_CFG_GRA_START_ADDR0			0x00F4
+#define LCD_CFG_GRA_START_ADDR1			0x00F8
+
+/* Graphic Frame Pitch */
+#define LCD_CFG_GRA_PITCH			0x00FC
+
+/* Graphic Starting Point on Screen Register */
+#define LCD_SPU_GRA_OVSA_HPXL_VLN		0x0100
+#define     CFG_GRA_OVSA_VLN(y)			((y) << 16)
+#define     CFG_GRA_OVSA_HPXL(x)		(x)
+
+/* Graphic Size Register */
+#define LCD_SPU_GRA_HPXL_VLN			0x0104
+#define     CFG_GRA_VLN(y)			((y) << 16)
+#define     CFG_GRA_HPXL(x)			(x)
+
+/* Graphic Size after Zooming Register */
+#define LCD_SPU_GZM_HPXL_VLN			0x0108
+#define     CFG_GZM_VLN(y)			((y) << 16)
+#define     CFG_GZM_HPXL(x)			(x)
+
+/* HW Cursor Starting Point on Screen Register */
+#define LCD_SPU_HWC_OVSA_HPXL_VLN		0x010C
+#define     CFG_HWC_OVSA_VLN(y)			((y) << 16)
+#define     CFG_HWC_OVSA_HPXL(x)		(x)
+
+/* HW Cursor Size */
+#define LCD_SPU_HWC_HPXL_VLN			0x0110
+#define     CFG_HWC_VLN(y)			((y) << 16)
+#define     CFG_HWC_HPXL(x)			(x)
+
+/* Total Screen Size Register */
+#define LCD_SPUT_V_H_TOTAL			0x0114
+#define     CFG_V_TOTAL(y)			((y) << 16)
+#define     CFG_H_TOTAL(x)			(x)
+
+/* Total Screen Active Size Register */
+#define LCD_SPU_V_H_ACTIVE			0x0118
+#define     CFG_V_ACTIVE(y)			((y) << 16)
+#define     CFG_H_ACTIVE(x)			(x)
+
+/* Screen H&V Porch Register */
+#define LCD_SPU_H_PORCH				0x011C
+#define     CFG_H_BACK_PORCH(b)			((b) << 16)
+#define     CFG_H_FRONT_PORCH(f)		(f)
+#define LCD_SPU_V_PORCH				0x0120
+#define     CFG_V_BACK_PORCH(b)			((b) << 16)
+#define     CFG_V_FRONT_PORCH(f)		(f)
+
+/* Screen Blank Color Register */
+#define LCD_SPU_BLANKCOLOR			0x0124
+#define     CFG_BLANKCOLOR_MASK			0x00FFFFFF
+#define     CFG_BLANKCOLOR_R_MASK		0x000000FF
+#define     CFG_BLANKCOLOR_G_MASK		0x0000FF00
+#define     CFG_BLANKCOLOR_B_MASK		0x00FF0000
+
+/* HW Cursor Color 1&2 Register */
+#define LCD_SPU_ALPHA_COLOR1			0x0128
+#define     CFG_HWC_COLOR1			0x00FFFFFF
+#define     CFG_HWC_COLOR1_R(red)		((red) << 16)
+#define     CFG_HWC_COLOR1_G(green)		((green) << 8)
+#define     CFG_HWC_COLOR1_B(blue)		(blue)
+#define     CFG_HWC_COLOR1_R_MASK		0x000000FF
+#define     CFG_HWC_COLOR1_G_MASK		0x0000FF00
+#define     CFG_HWC_COLOR1_B_MASK		0x00FF0000
+#define LCD_SPU_ALPHA_COLOR2			0x012C
+#define     CFG_HWC_COLOR2			0x00FFFFFF
+#define     CFG_HWC_COLOR2_R_MASK		0x000000FF
+#define     CFG_HWC_COLOR2_G_MASK		0x0000FF00
+#define     CFG_HWC_COLOR2_B_MASK		0x00FF0000
+
+/* Video YUV Color Key Control */
+#define LCD_SPU_COLORKEY_Y			0x0130
+#define     CFG_CKEY_Y2(y2)			((y2) << 24)
+#define     CFG_CKEY_Y2_MASK			0xFF000000
+#define     CFG_CKEY_Y1(y1)			((y1) << 16)
+#define     CFG_CKEY_Y1_MASK			0x00FF0000
+#define     CFG_CKEY_Y(y)			((y) << 8)
+#define     CFG_CKEY_Y_MASK			0x0000FF00
+#define     CFG_ALPHA_Y(y)			(y)
+#define     CFG_ALPHA_Y_MASK			0x000000FF
+#define LCD_SPU_COLORKEY_U			0x0134
+#define     CFG_CKEY_U2(u2)			((u2) << 24)
+#define     CFG_CKEY_U2_MASK			0xFF000000
+#define     CFG_CKEY_U1(u1)			((u1) << 16)
+#define     CFG_CKEY_U1_MASK			0x00FF0000
+#define     CFG_CKEY_U(u)			((u) << 8)
+#define     CFG_CKEY_U_MASK			0x0000FF00
+#define     CFG_ALPHA_U(u)			(u)
+#define     CFG_ALPHA_U_MASK			0x000000FF
+#define LCD_SPU_COLORKEY_V			0x0138
+#define     CFG_CKEY_V2(v2)			((v2) << 24)
+#define     CFG_CKEY_V2_MASK			0xFF000000
+#define     CFG_CKEY_V1(v1)			((v1) << 16)
+#define     CFG_CKEY_V1_MASK			0x00FF0000
+#define     CFG_CKEY_V(v)			((v) << 8)
+#define     CFG_CKEY_V_MASK			0x0000FF00
+#define     CFG_ALPHA_V(v)			(v)
+#define     CFG_ALPHA_V_MASK			0x000000FF
+
+/* SPI Read Data Register */
+#define LCD_SPU_SPI_RXDATA			0x0140
+
+/* Smart Panel Read Data Register */
+#define LCD_SPU_ISA_RSDATA			0x0144
+#define     ISA_RXDATA_16BIT_1_DATA_MASK	0x000000FF
+#define     ISA_RXDATA_16BIT_2_DATA_MASK	0x0000FF00
+#define     ISA_RXDATA_16BIT_3_DATA_MASK	0x00FF0000
+#define     ISA_RXDATA_16BIT_4_DATA_MASK	0xFF000000
+#define     ISA_RXDATA_32BIT_1_DATA_MASK	0x00FFFFFF
+
+/* HWC SRAM Read Data Register */
+#define LCD_SPU_HWC_RDDAT			0x0158
+
+/* Gamma Table SRAM Read Data Register */
+#define LCD_SPU_GAMMA_RDDAT			0x015c
+#define     CFG_GAMMA_RDDAT_MASK		0x000000FF
+
+/* Palette Table SRAM Read Data Register */
+#define LCD_SPU_PALETTE_RDDAT			0x0160
+#define     CFG_PALETTE_RDDAT_MASK		0x00FFFFFF
+
+/* I/O Pads Input Read Only Register */
+#define LCD_SPU_IOPAD_IN			0x0178
+#define     CFG_IOPAD_IN_MASK			0x0FFFFFFF
+
+/* Reserved Read Only Registers */
+#define LCD_CFG_RDREG5F				0x017C
+#define     IRE_FRAME_CNT_MASK			0x000000C0
+#define     IPE_FRAME_CNT_MASK			0x00000030
+#define     GRA_FRAME_CNT_MASK			0x0000000C  /* Graphic */
+#define     DMA_FRAME_CNT_MASK			0x00000003  /* Video */
+
+/* SPI Control Register. */
+#define LCD_SPU_SPI_CTRL			0x0180
+#define     CFG_SCLKCNT(div)			((div) << 24)  /* 0xFF~0x2 */
+#define     CFG_SCLKCNT_MASK			0xFF000000
+#define     CFG_RXBITS(rx)			((rx) << 16)   /* 0x1F~0x1 */
+#define     CFG_RXBITS_MASK			0x00FF0000
+#define     CFG_TXBITS(tx)			((tx) << 8)    /* 0x1F~0x1 */
+#define     CFG_TXBITS_MASK			0x0000FF00
+#define     CFG_CLKINV(clk)			((clk) << 7)
+#define     CFG_CLKINV_MASK			0x00000080
+#define     CFG_KEEPXFER(transfer)		((transfer) << 6)
+#define     CFG_KEEPXFER_MASK			0x00000040
+#define     CFG_RXBITSTO0(rx)			((rx) << 5)
+#define     CFG_RXBITSTO0_MASK			0x00000020
+#define     CFG_TXBITSTO0(tx)			((tx) << 4)
+#define     CFG_TXBITSTO0_MASK			0x00000010
+#define     CFG_SPI_ENA(spi)			((spi) << 3)
+#define     CFG_SPI_ENA_MASK			0x00000008
+#define     CFG_SPI_SEL(spi)			((spi) << 2)
+#define     CFG_SPI_SEL_MASK			0x00000004
+#define     CFG_SPI_3W4WB(wire)			((wire) << 1)
+#define     CFG_SPI_3W4WB_MASK			0x00000002
+#define     CFG_SPI_START(start)		(start)
+#define     CFG_SPI_START_MASK			0x00000001
+
+/* SPI Tx Data Register */
+#define LCD_SPU_SPI_TXDATA			0x0184
+
+/*
+   1. Smart Pannel 8-bit Bus Control Register.
+   2. AHB Slave Path Data Port Register
+*/
+#define LCD_SPU_SMPN_CTRL			0x0188
+
+/* DMA Control 0 Register */
+#define LCD_SPU_DMA_CTRL0			0x0190
+#define     CFG_NOBLENDING(nb)			((nb) << 31)
+#define     CFG_NOBLENDING_MASK			0x80000000
+#define     CFG_GAMMA_ENA(gn)			((gn) << 30)
+#define     CFG_GAMMA_ENA_MASK			0x40000000
+#define     CFG_CBSH_ENA(cn)			((cn) << 29)
+#define     CFG_CBSH_ENA_MASK			0x20000000
+#define     CFG_PALETTE_ENA(pn)			((pn) << 28)
+#define     CFG_PALETTE_ENA_MASK		0x10000000
+#define     CFG_ARBFAST_ENA(an)			((an) << 27)
+#define     CFG_ARBFAST_ENA_MASK		0x08000000
+#define     CFG_HWC_1BITMOD(mode)		((mode) << 26)
+#define     CFG_HWC_1BITMOD_MASK		0x04000000
+#define     CFG_HWC_1BITENA(mn)			((mn) << 25)
+#define     CFG_HWC_1BITENA_MASK		0x02000000
+#define     CFG_HWC_ENA(cn)		        ((cn) << 24)
+#define     CFG_HWC_ENA_MASK			0x01000000
+#define     CFG_DMAFORMAT(dmaformat)		((dmaformat) << 20)
+#define     CFG_DMAFORMAT_MASK			0x00F00000
+#define     CFG_GRAFORMAT(graformat)		((graformat) << 16)
+#define     CFG_GRAFORMAT_MASK			0x000F0000
+/* for graphic part */
+#define     CFG_GRA_FTOGGLE(toggle)		((toggle) << 15)
+#define     CFG_GRA_FTOGGLE_MASK		0x00008000
+#define     CFG_GRA_HSMOOTH(smooth)		((smooth) << 14)
+#define     CFG_GRA_HSMOOTH_MASK		0x00004000
+#define     CFG_GRA_TSTMODE(test)		((test) << 13)
+#define     CFG_GRA_TSTMODE_MASK		0x00002000
+#define     CFG_GRA_SWAPRB(swap)		((swap) << 12)
+#define     CFG_GRA_SWAPRB_MASK			0x00001000
+#define     CFG_GRA_SWAPUV(swap)		((swap) << 11)
+#define     CFG_GRA_SWAPUV_MASK			0x00000800
+#define     CFG_GRA_SWAPYU(swap)		((swap) << 10)
+#define     CFG_GRA_SWAPYU_MASK			0x00000400
+#define     CFG_YUV2RGB_GRA(cvrt)		((cvrt) << 9)
+#define     CFG_YUV2RGB_GRA_MASK		0x00000200
+#define     CFG_GRA_ENA(gra)			((gra) << 8)
+#define     CFG_GRA_ENA_MASK			0x00000100
+/* for video part */
+#define     CFG_DMA_FTOGGLE(toggle)		((toggle) << 7)
+#define     CFG_DMA_FTOGGLE_MASK		0x00000080
+#define     CFG_DMA_HSMOOTH(smooth)		((smooth) << 6)
+#define     CFG_DMA_HSMOOTH_MASK		0x00000040
+#define     CFG_DMA_TSTMODE(test)		((test) << 5)
+#define     CFG_DMA_TSTMODE_MASK		0x00000020
+#define     CFG_DMA_SWAPRB(swap)		((swap) << 4)
+#define     CFG_DMA_SWAPRB_MASK			0x00000010
+#define     CFG_DMA_SWAPUV(swap)		((swap) << 3)
+#define     CFG_DMA_SWAPUV_MASK			0x00000008
+#define     CFG_DMA_SWAPYU(swap)		((swap) << 2)
+#define     CFG_DMA_SWAPYU_MASK			0x00000004
+#define     CFG_DMA_SWAP_MASK			0x0000001C
+#define     CFG_YUV2RGB_DMA(cvrt)		((cvrt) << 1)
+#define     CFG_YUV2RGB_DMA_MASK		0x00000002
+#define     CFG_DMA_ENA(video)			(video)
+#define     CFG_DMA_ENA_MASK			0x00000001
+
+/* DMA Control 1 Register */
+#define LCD_SPU_DMA_CTRL1			0x0194
+#define     CFG_FRAME_TRIG(trig)		((trig) << 31)
+#define     CFG_FRAME_TRIG_MASK			0x80000000
+#define     CFG_VSYNC_TRIG(trig)		((trig) << 28)
+#define     CFG_VSYNC_TRIG_MASK			0x70000000
+#define     CFG_VSYNC_INV(inv)			((inv) << 27)
+#define     CFG_VSYNC_INV_MASK			0x08000000
+#define     CFG_COLOR_KEY_MODE(cmode)		((cmode) << 24)
+#define     CFG_COLOR_KEY_MASK			0x07000000
+#define     CFG_CARRY(carry)			((carry) << 23)
+#define     CFG_CARRY_MASK			0x00800000
+#define     CFG_LNBUF_ENA(lnbuf)		((lnbuf) << 22)
+#define     CFG_LNBUF_ENA_MASK			0x00400000
+#define     CFG_GATED_ENA(gated)		((gated) << 21)
+#define     CFG_GATED_ENA_MASK			0x00200000
+#define     CFG_PWRDN_ENA(power)		((power) << 20)
+#define     CFG_PWRDN_ENA_MASK			0x00100000
+#define     CFG_DSCALE(dscale)			((dscale) << 18)
+#define     CFG_DSCALE_MASK			0x000C0000
+#define     CFG_ALPHA_MODE(amode)		((amode) << 16)
+#define     CFG_ALPHA_MODE_MASK			0x00030000
+#define     CFG_ALPHA(alpha)			((alpha) << 8)
+#define     CFG_ALPHA_MASK			0x0000FF00
+#define     CFG_PXLCMD(pxlcmd)			(pxlcmd)
+#define     CFG_PXLCMD_MASK			0x000000FF
+
+/* SRAM Control Register */
+#define LCD_SPU_SRAM_CTRL			0x0198
+#define     CFG_SRAM_INIT_WR_RD(mode)		((mode) << 14)
+#define     CFG_SRAM_INIT_WR_RD_MASK		0x0000C000
+#define     CFG_SRAM_ADDR_LCDID(id)		((id) << 8)
+#define     CFG_SRAM_ADDR_LCDID_MASK		0x00000F00
+#define     CFG_SRAM_ADDR(addr)			(addr)
+#define     CFG_SRAM_ADDR_MASK			0x000000FF
+
+/* SRAM Write Data Register */
+#define LCD_SPU_SRAM_WRDAT			0x019C
+
+/* SRAM RTC/WTC Control Register */
+#define LCD_SPU_SRAM_PARA0			0x01A0
+
+/* SRAM Power Down Control Register */
+#define LCD_SPU_SRAM_PARA1			0x01A4
+#define     CFG_CSB_256x32(hwc)			((hwc) << 15)	/* HWC */
+#define     CFG_CSB_256x32_MASK			0x00008000
+#define     CFG_CSB_256x24(palette)		((palette) << 14)	/* Palette */
+#define     CFG_CSB_256x24_MASK			0x00004000
+#define     CFG_CSB_256x8(gamma)		((gamma) << 13)	/* Gamma */
+#define     CFG_CSB_256x8_MASK			0x00002000
+#define     CFG_PDWN256x32(pdwn)		((pdwn) << 7)	/* HWC */
+#define     CFG_PDWN256x32_MASK			0x00000080
+#define     CFG_PDWN256x24(pdwn)		((pdwn) << 6)	/* Palette */
+#define     CFG_PDWN256x24_MASK			0x00000040
+#define     CFG_PDWN256x8(pdwn)			((pdwn) << 5)	/* Gamma */
+#define     CFG_PDWN256x8_MASK			0x00000020
+#define     CFG_PDWN32x32(pdwn)			((pdwn) << 3)
+#define     CFG_PDWN32x32_MASK			0x00000008
+#define     CFG_PDWN16x66(pdwn)			((pdwn) << 2)
+#define     CFG_PDWN16x66_MASK			0x00000004
+#define     CFG_PDWN32x66(pdwn)			((pdwn) << 1)
+#define     CFG_PDWN32x66_MASK			0x00000002
+#define     CFG_PDWN64x66(pdwn)			(pdwn)
+#define     CFG_PDWN64x66_MASK			0x00000001
+
+/* Smart or Dumb Panel Clock Divider */
+#define LCD_CFG_SCLK_DIV			0x01A8
+#define     SCLK_SOURCE_SELECT(src)		((src) << 31)
+#define     SCLK_SOURCE_SELECT_MASK		0x80000000
+#define     CLK_FRACDIV(frac)			((frac) << 16)
+#define     CLK_FRACDIV_MASK			0x0FFF0000
+#define     CLK_INT_DIV(div)			(div)
+#define     CLK_INT_DIV_MASK			0x0000FFFF
+
+/* Video Contrast Register */
+#define LCD_SPU_CONTRAST			0x01AC
+#define     CFG_BRIGHTNESS(bright)		((bright) << 16)
+#define     CFG_BRIGHTNESS_MASK			0xFFFF0000
+#define     CFG_CONTRAST(contrast)		(contrast)
+#define     CFG_CONTRAST_MASK			0x0000FFFF
+
+/* Video Saturation Register */
+#define LCD_SPU_SATURATION			0x01B0
+#define     CFG_C_MULTS(mult)			((mult) << 16)
+#define     CFG_C_MULTS_MASK			0xFFFF0000
+#define     CFG_SATURATION(sat)			(sat)
+#define     CFG_SATURATION_MASK			0x0000FFFF
+
+/* Video Hue Adjust Register */
+#define LCD_SPU_CBSH_HUE			0x01B4
+#define     CFG_SIN0(sin0)			((sin0) << 16)
+#define     CFG_SIN0_MASK			0xFFFF0000
+#define     CFG_COS0(con0)			(con0)
+#define     CFG_COS0_MASK			0x0000FFFF
+
+/* Dump LCD Panel Control Register */
+#define LCD_SPU_DUMB_CTRL			0x01B8
+#define     CFG_DUMBMODE(mode)			((mode) << 28)
+#define     CFG_DUMBMODE_MASK			0xF0000000
+#define     CFG_LCDGPIO_O(data)			((data) << 20)
+#define     CFG_LCDGPIO_O_MASK			0x0FF00000
+#define     CFG_LCDGPIO_ENA(gpio)		((gpio) << 12)
+#define     CFG_LCDGPIO_ENA_MASK		0x000FF000
+#define     CFG_BIAS_OUT(bias)			((bias) << 8)
+#define     CFG_BIAS_OUT_MASK			0x00000100
+#define     CFG_REVERSE_RGB(rRGB)		((rRGB) << 7)
+#define     CFG_REVERSE_RGB_MASK		0x00000080
+#define     CFG_INV_COMPBLANK(blank)		((blank) << 6)
+#define     CFG_INV_COMPBLANK_MASK		0x00000040
+#define     CFG_INV_COMPSYNC(sync)		((sync) << 5)
+#define     CFG_INV_COMPSYNC_MASK		0x00000020
+#define     CFG_INV_HENA(hena)			((hena) << 4)
+#define     CFG_INV_HENA_MASK			0x00000010
+#define     CFG_INV_VSYNC(vsync)		((vsync) << 3)
+#define     CFG_INV_VSYNC_MASK			0x00000008
+#define     CFG_INV_HSYNC(hsync)		((hsync) << 2)
+#define     CFG_INV_HSYNC_MASK			0x00000004
+#define     CFG_INV_PCLK(pclk)			((pclk) << 1)
+#define     CFG_INV_PCLK_MASK			0x00000002
+#define     CFG_DUMB_ENA(dumb)			(dumb)
+#define     CFG_DUMB_ENA_MASK			0x00000001
+
+/* LCD I/O Pads Control Register */
+#define SPU_IOPAD_CONTROL			0x01BC
+#define     CFG_GRA_VM_ENA(vm)			((vm) << 15)        /* gfx */
+#define     CFG_GRA_VM_ENA_MASK			0x00008000
+#define     CFG_DMA_VM_ENA(vm)			((vm) << 13)	/* video */
+#define     CFG_DMA_VM_ENA_MASK			0x00002000
+#define     CFG_CMD_VM_ENA(vm)			((vm) << 13)
+#define     CFG_CMD_VM_ENA_MASK			0x00000800
+#define     CFG_CSC(csc)			((csc) << 8)	/* csc */
+#define     CFG_CSC_MASK			0x00000300
+#define     CFG_AXICTRL(axi)			((axi) << 4)
+#define     CFG_AXICTRL_MASK			0x000000F0
+#define     CFG_IOPADMODE(iopad)		(iopad)
+#define     CFG_IOPADMODE_MASK			0x0000000F
+
+/* LCD Interrupt Control Register */
+#define SPU_IRQ_ENA				0x01C0
+#define     DMA_FRAME_IRQ0_ENA(irq)		((irq) << 31)
+#define     DMA_FRAME_IRQ0_ENA_MASK		0x80000000
+#define     DMA_FRAME_IRQ1_ENA(irq)		((irq) << 30)
+#define     DMA_FRAME_IRQ1_ENA_MASK		0x40000000
+#define     DMA_FF_UNDERFLOW_ENA(ff)		((ff) << 29)
+#define     DMA_FF_UNDERFLOW_ENA_MASK		0x20000000
+#define     GRA_FRAME_IRQ0_ENA(irq)		((irq) << 27)
+#define     GRA_FRAME_IRQ0_ENA_MASK		0x08000000
+#define     GRA_FRAME_IRQ1_ENA(irq)		((irq) << 26)
+#define     GRA_FRAME_IRQ1_ENA_MASK		0x04000000
+#define     GRA_FF_UNDERFLOW_ENA(ff)		((ff) << 25)
+#define     GRA_FF_UNDERFLOW_ENA_MASK		0x02000000
+#define     VSYNC_IRQ_ENA(vsync_irq)		((vsync_irq) << 23)
+#define     VSYNC_IRQ_ENA_MASK			0x00800000
+#define     DUMB_FRAMEDONE_ENA(fdone)		((fdone) << 22)
+#define     DUMB_FRAMEDONE_ENA_MASK		0x00400000
+#define     TWC_FRAMEDONE_ENA(fdone)		((fdone) << 21)
+#define     TWC_FRAMEDONE_ENA_MASK		0x00200000
+#define     HWC_FRAMEDONE_ENA(fdone)		((fdone) << 20)
+#define     HWC_FRAMEDONE_ENA_MASK		0x00100000
+#define     SLV_IRQ_ENA(irq)			((irq) << 19)
+#define     SLV_IRQ_ENA_MASK			0x00080000
+#define     SPI_IRQ_ENA(irq)			((irq) << 18)
+#define     SPI_IRQ_ENA_MASK			0x00040000
+#define     PWRDN_IRQ_ENA(irq)			((irq) << 17)
+#define     PWRDN_IRQ_ENA_MASK			0x00020000
+#define     ERR_IRQ_ENA(irq)			((irq) << 16)
+#define     ERR_IRQ_ENA_MASK			0x00010000
+#define     CLEAN_SPU_IRQ_ISR(irq)		(irq)
+#define     CLEAN_SPU_IRQ_ISR_MASK		0x0000FFFF
+
+/* LCD Interrupt Status Register */
+#define SPU_IRQ_ISR				0x01C4
+#define     DMA_FRAME_IRQ0(irq)			((irq) << 31)
+#define     DMA_FRAME_IRQ0_MASK			0x80000000
+#define     DMA_FRAME_IRQ1(irq)			((irq) << 30)
+#define     DMA_FRAME_IRQ1_MASK			0x40000000
+#define     DMA_FF_UNDERFLOW(ff)		((ff) << 29)
+#define     DMA_FF_UNDERFLOW_MASK		0x20000000
+#define     GRA_FRAME_IRQ0(irq)			((irq) << 27)
+#define     GRA_FRAME_IRQ0_MASK			0x08000000
+#define     GRA_FRAME_IRQ1(irq)			((irq) << 26)
+#define     GRA_FRAME_IRQ1_MASK			0x04000000
+#define     GRA_FF_UNDERFLOW(ff)		((ff) << 25)
+#define     GRA_FF_UNDERFLOW_MASK		0x02000000
+#define     VSYNC_IRQ(vsync_irq)		((vsync_irq) << 23)
+#define     VSYNC_IRQ_MASK			0x00800000
+#define     DUMB_FRAMEDONE(fdone)		((fdone) << 22)
+#define     DUMB_FRAMEDONE_MASK			0x00400000
+#define     TWC_FRAMEDONE(fdone)		((fdone) << 21)
+#define     TWC_FRAMEDONE_MASK			0x00200000
+#define     HWC_FRAMEDONE(fdone)		((fdone) << 20)
+#define     HWC_FRAMEDONE_MASK			0x00100000
+#define     SLV_IRQ(irq)			((irq) << 19)
+#define     SLV_IRQ_MASK			0x00080000
+#define     SPI_IRQ(irq)			((irq) << 18)
+#define     SPI_IRQ_MASK			0x00040000
+#define     PWRDN_IRQ(irq)			((irq) << 17)
+#define     PWRDN_IRQ_MASK			0x00020000
+#define     ERR_IRQ(irq)			((irq) << 16)
+#define     ERR_IRQ_MASK			0x00010000
+/* read-only */
+#define     DMA_FRAME_IRQ0_LEVEL_MASK		0x00008000
+#define     DMA_FRAME_IRQ1_LEVEL_MASK		0x00004000
+#define     DMA_FRAME_CNT_ISR_MASK		0x00003000
+#define     GRA_FRAME_IRQ0_LEVEL_MASK		0x00000800
+#define     GRA_FRAME_IRQ1_LEVEL_MASK		0x00000400
+#define     GRA_FRAME_CNT_ISR_MASK		0x00000300
+#define     VSYNC_IRQ_LEVEL_MASK		0x00000080
+#define     DUMB_FRAMEDONE_LEVEL_MASK		0x00000040
+#define     TWC_FRAMEDONE_LEVEL_MASK		0x00000020
+#define     HWC_FRAMEDONE_LEVEL_MASK		0x00000010
+#define     SLV_FF_EMPTY_MASK			0x00000008
+#define     DMA_FF_ALLEMPTY_MASK		0x00000004
+#define     GRA_FF_ALLEMPTY_MASK		0x00000002
+#define     PWRDN_IRQ_LEVEL_MASK		0x00000001
+
+
+/*
+ * defined Video Memory Color format for DMA control 0 register
+ * DMA0 bit[23:20]
+ */
+#define VMODE_RGB565		0x0
+#define VMODE_RGB1555		0x1
+#define VMODE_RGB888PACKED	0x2
+#define VMODE_RGB888UNPACKED	0x3
+#define VMODE_RGBA888		0x4
+#define VMODE_YUV422PACKED	0x5
+#define VMODE_YUV422PLANAR	0x6
+#define VMODE_YUV420PLANAR	0x7
+#define VMODE_SMPNCMD		0x8
+#define VMODE_PALETTE4BIT	0x9
+#define VMODE_PALETTE8BIT	0xa
+#define VMODE_RESERVED		0xb
+
+/*
+ * defined Graphic Memory Color format for DMA control 0 register
+ * DMA0 bit[19:16]
+ */
+#define GMODE_RGB565		0x0
+#define GMODE_RGB1555		0x1
+#define GMODE_RGB888PACKED	0x2
+#define GMODE_RGB888UNPACKED	0x3
+#define GMODE_RGBA888		0x4
+#define GMODE_YUV422PACKED	0x5
+#define GMODE_YUV422PLANAR	0x6
+#define GMODE_YUV420PLANAR	0x7
+#define GMODE_SMPNCMD		0x8
+#define GMODE_PALETTE4BIT	0x9
+#define GMODE_PALETTE8BIT	0xa
+#define GMODE_RESERVED		0xb
+
+/*
+ * define for DMA control 1 register
+ */
+#define DMA1_FRAME_TRIG		31 /* bit location */
+#define DMA1_VSYNC_MODE		28
+#define DMA1_VSYNC_INV		27
+#define DMA1_CKEY		24
+#define DMA1_CARRY		23
+#define DMA1_LNBUF_ENA		22
+#define DMA1_GATED_ENA		21
+#define DMA1_PWRDN_ENA		20
+#define DMA1_DSCALE		18
+#define DMA1_ALPHA_MODE		16
+#define DMA1_ALPHA		08
+#define DMA1_PXLCMD		00
+
+/*
+ * defined for Configure Dumb Mode
+ * DUMB LCD Panel bit[31:28]
+ */
+#define DUMB16_RGB565_0		0x0
+#define DUMB16_RGB565_1		0x1
+#define DUMB18_RGB666_0		0x2
+#define DUMB18_RGB666_1		0x3
+#define DUMB12_RGB444_0		0x4
+#define DUMB12_RGB444_1		0x5
+#define DUMB24_RGB888_0		0x6
+#define DUMB_BLANK		0x7
+
+/*
+ * defined for Configure I/O Pin Allocation Mode
+ * LCD LCD I/O Pads control register bit[3:0]
+ */
+#define IOPAD_DUMB24		0x0
+#define IOPAD_DUMB18SPI		0x1
+#define IOPAD_DUMB18GPIO	0x2
+#define IOPAD_DUMB16SPI		0x3
+#define IOPAD_DUMB16GPIO	0x4
+#define IOPAD_DUMB12		0x5
+#define IOPAD_SMART18SPI	0x6
+#define IOPAD_SMART16SPI	0x7
+#define IOPAD_SMART8BOTH	0x8
+
+#endif /* __PXA168FB_H__ */
diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c
new file mode 100644
index 000000000000..417f9a27eb7d
--- /dev/null
+++ b/drivers/video/fbdev/pxa3xx-gcu.c
@@ -0,0 +1,724 @@
+/*
+ *  pxa3xx-gcu.c - Linux kernel module for PXA3xx graphics controllers
+ *
+ *  This driver needs a DirectFB counterpart in user space, communication
+ *  is handled via mmap()ed memory areas and an ioctl.
+ *
+ *  Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *  Copyright (c) 2009 Janine Kropp <nin@directfb.org>
+ *  Copyright (c) 2009 Denis Oliver Kropp <dok@directfb.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * WARNING: This controller is attached to System Bus 2 of the PXA which
+ * needs its arbiter to be enabled explicitly (CKENB & 1<<9).
+ * There is currently no way to do this from Linux, so you need to teach
+ * your bootloader for now.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+
+#include "pxa3xx-gcu.h"
+
+#define DRV_NAME	"pxa3xx-gcu"
+#define MISCDEV_MINOR	197
+
+#define REG_GCCR	0x00
+#define GCCR_SYNC_CLR	(1 << 9)
+#define GCCR_BP_RST	(1 << 8)
+#define GCCR_ABORT	(1 << 6)
+#define GCCR_STOP	(1 << 4)
+
+#define REG_GCISCR	0x04
+#define REG_GCIECR	0x08
+#define REG_GCRBBR	0x20
+#define REG_GCRBLR	0x24
+#define REG_GCRBHR	0x28
+#define REG_GCRBTR	0x2C
+#define REG_GCRBEXHR	0x30
+
+#define IE_EOB		(1 << 0)
+#define IE_EEOB		(1 << 5)
+#define IE_ALL		0xff
+
+#define SHARED_SIZE	PAGE_ALIGN(sizeof(struct pxa3xx_gcu_shared))
+
+/* #define PXA3XX_GCU_DEBUG */
+/* #define PXA3XX_GCU_DEBUG_TIMER */
+
+#ifdef PXA3XX_GCU_DEBUG
+#define QDUMP(msg)					\
+	do {						\
+		QPRINT(priv, KERN_DEBUG, msg);		\
+	} while (0)
+#else
+#define QDUMP(msg)	do {} while (0)
+#endif
+
+#define QERROR(msg)					\
+	do {						\
+		QPRINT(priv, KERN_ERR, msg);		\
+	} while (0)
+
+struct pxa3xx_gcu_batch {
+	struct pxa3xx_gcu_batch *next;
+	u32			*ptr;
+	dma_addr_t		 phys;
+	unsigned long		 length;
+};
+
+struct pxa3xx_gcu_priv {
+	void __iomem		 *mmio_base;
+	struct clk		 *clk;
+	struct pxa3xx_gcu_shared *shared;
+	dma_addr_t		  shared_phys;
+	struct resource		 *resource_mem;
+	struct miscdevice	  misc_dev;
+	wait_queue_head_t	  wait_idle;
+	wait_queue_head_t	  wait_free;
+	spinlock_t		  spinlock;
+	struct timeval 		  base_time;
+
+	struct pxa3xx_gcu_batch *free;
+	struct pxa3xx_gcu_batch *ready;
+	struct pxa3xx_gcu_batch *ready_last;
+	struct pxa3xx_gcu_batch *running;
+};
+
+static inline unsigned long
+gc_readl(struct pxa3xx_gcu_priv *priv, unsigned int off)
+{
+	return __raw_readl(priv->mmio_base + off);
+}
+
+static inline void
+gc_writel(struct pxa3xx_gcu_priv *priv, unsigned int off, unsigned long val)
+{
+	__raw_writel(val, priv->mmio_base + off);
+}
+
+#define QPRINT(priv, level, msg)					\
+	do {								\
+		struct timeval tv;					\
+		struct pxa3xx_gcu_shared *shared = priv->shared;	\
+		u32 base = gc_readl(priv, REG_GCRBBR);			\
+									\
+		do_gettimeofday(&tv);					\
+									\
+		printk(level "%ld.%03ld.%03ld - %-17s: %-21s (%s, "	\
+			"STATUS "					\
+			"0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, "	\
+			"T %5ld)\n",					\
+			tv.tv_sec - priv->base_time.tv_sec,		\
+			tv.tv_usec / 1000, tv.tv_usec % 1000,		\
+			__func__, msg,					\
+			shared->hw_running ? "running" : "   idle",	\
+			gc_readl(priv, REG_GCISCR),			\
+			gc_readl(priv, REG_GCRBBR),			\
+			gc_readl(priv, REG_GCRBLR),			\
+			(gc_readl(priv, REG_GCRBEXHR) - base) / 4,	\
+			(gc_readl(priv, REG_GCRBHR) - base) / 4,	\
+			(gc_readl(priv, REG_GCRBTR) - base) / 4);	\
+	} while (0)
+
+static void
+pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
+{
+	QDUMP("RESET");
+
+	/* disable interrupts */
+	gc_writel(priv, REG_GCIECR, 0);
+
+	/* reset hardware */
+	gc_writel(priv, REG_GCCR, GCCR_ABORT);
+	gc_writel(priv, REG_GCCR, 0);
+
+	memset(priv->shared, 0, SHARED_SIZE);
+	priv->shared->buffer_phys = priv->shared_phys;
+	priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
+
+	do_gettimeofday(&priv->base_time);
+
+	/* set up the ring buffer pointers */
+	gc_writel(priv, REG_GCRBLR, 0);
+	gc_writel(priv, REG_GCRBBR, priv->shared_phys);
+	gc_writel(priv, REG_GCRBTR, priv->shared_phys);
+
+	/* enable all IRQs except EOB */
+	gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
+}
+
+static void
+dump_whole_state(struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_shared *sh = priv->shared;
+	u32 base = gc_readl(priv, REG_GCRBBR);
+
+	QDUMP("DUMP");
+
+	printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
+		"%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
+		sh->hw_running ? "running" : "idle   ",
+		gc_readl(priv, REG_GCISCR),
+		gc_readl(priv, REG_GCRBBR),
+		gc_readl(priv, REG_GCRBLR),
+		(gc_readl(priv, REG_GCRBEXHR) - base) / 4,
+		(gc_readl(priv, REG_GCRBHR) - base) / 4,
+		(gc_readl(priv, REG_GCRBTR) - base) / 4);
+}
+
+static void
+flush_running(struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_batch *running = priv->running;
+	struct pxa3xx_gcu_batch *next;
+
+	while (running) {
+		next = running->next;
+		running->next = priv->free;
+		priv->free = running;
+		running = next;
+	}
+
+	priv->running = NULL;
+}
+
+static void
+run_ready(struct pxa3xx_gcu_priv *priv)
+{
+	unsigned int num = 0;
+	struct pxa3xx_gcu_shared *shared = priv->shared;
+	struct pxa3xx_gcu_batch	*ready = priv->ready;
+
+	QDUMP("Start");
+
+	BUG_ON(!ready);
+
+	shared->buffer[num++] = 0x05000000;
+
+	while (ready) {
+		shared->buffer[num++] = 0x00000001;
+		shared->buffer[num++] = ready->phys;
+		ready = ready->next;
+	}
+
+	shared->buffer[num++] = 0x05000000;
+	priv->running = priv->ready;
+	priv->ready = priv->ready_last = NULL;
+	gc_writel(priv, REG_GCRBLR, 0);
+	shared->hw_running = 1;
+
+	/* ring base address */
+	gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
+
+	/* ring tail address */
+	gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
+
+	/* ring length */
+	gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
+}
+
+static irqreturn_t
+pxa3xx_gcu_handle_irq(int irq, void *ctx)
+{
+	struct pxa3xx_gcu_priv *priv = ctx;
+	struct pxa3xx_gcu_shared *shared = priv->shared;
+	u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
+
+	QDUMP("-Interrupt");
+
+	if (!status)
+		return IRQ_NONE;
+
+	spin_lock(&priv->spinlock);
+	shared->num_interrupts++;
+
+	if (status & IE_EEOB) {
+		QDUMP(" [EEOB]");
+
+		flush_running(priv);
+		wake_up_all(&priv->wait_free);
+
+		if (priv->ready) {
+			run_ready(priv);
+		} else {
+			/* There is no more data prepared by the userspace.
+			 * Set hw_running = 0 and wait for the next userspace
+			 * kick-off */
+			shared->num_idle++;
+			shared->hw_running = 0;
+
+			QDUMP(" '-> Idle.");
+
+			/* set ring buffer length to zero */
+			gc_writel(priv, REG_GCRBLR, 0);
+
+			wake_up_all(&priv->wait_idle);
+		}
+
+		shared->num_done++;
+	} else {
+		QERROR(" [???]");
+		dump_whole_state(priv);
+	}
+
+	/* Clear the interrupt */
+	gc_writel(priv, REG_GCISCR, status);
+	spin_unlock(&priv->spinlock);
+
+	return IRQ_HANDLED;
+}
+
+static int
+pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
+{
+	int ret = 0;
+
+	QDUMP("Waiting for idle...");
+
+	/* Does not need to be atomic. There's a lock in user space,
+	 * but anyhow, this is just for statistics. */
+	priv->shared->num_wait_idle++;
+
+	while (priv->shared->hw_running) {
+		int num = priv->shared->num_interrupts;
+		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
+
+		ret = wait_event_interruptible_timeout(priv->wait_idle,
+					!priv->shared->hw_running, HZ*4);
+
+		if (ret != 0)
+			break;
+
+		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
+		    priv->shared->num_interrupts == num) {
+			QERROR("TIMEOUT");
+			ret = -ETIMEDOUT;
+			break;
+		}
+	}
+
+	QDUMP("done");
+
+	return ret;
+}
+
+static int
+pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
+{
+	int ret = 0;
+
+	QDUMP("Waiting for free...");
+
+	/* Does not need to be atomic. There's a lock in user space,
+	 * but anyhow, this is just for statistics. */
+	priv->shared->num_wait_free++;
+
+	while (!priv->free) {
+		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
+
+		ret = wait_event_interruptible_timeout(priv->wait_free,
+						       priv->free, HZ*4);
+
+		if (ret < 0)
+			break;
+
+		if (ret > 0)
+			continue;
+
+		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
+			QERROR("TIMEOUT");
+			ret = -ETIMEDOUT;
+			break;
+		}
+	}
+
+	QDUMP("done");
+
+	return ret;
+}
+
+/* Misc device layer */
+
+static inline struct pxa3xx_gcu_priv *to_pxa3xx_gcu_priv(struct file *file)
+{
+	struct miscdevice *dev = file->private_data;
+	return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
+}
+
+/*
+ * provide an empty .open callback, so the core sets file->private_data
+ * for us.
+ */
+static int pxa3xx_gcu_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t
+pxa3xx_gcu_write(struct file *file, const char *buff,
+		 size_t count, loff_t *offp)
+{
+	int ret;
+	unsigned long flags;
+	struct pxa3xx_gcu_batch	*buffer;
+	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
+
+	int words = count / 4;
+
+	/* Does not need to be atomic. There's a lock in user space,
+	 * but anyhow, this is just for statistics. */
+	priv->shared->num_writes++;
+	priv->shared->num_words += words;
+
+	/* Last word reserved for batch buffer end command */
+	if (words >= PXA3XX_GCU_BATCH_WORDS)
+		return -E2BIG;
+
+	/* Wait for a free buffer */
+	if (!priv->free) {
+		ret = pxa3xx_gcu_wait_free(priv);
+		if (ret < 0)
+			return ret;
+	}
+
+	/*
+	 * Get buffer from free list
+	 */
+	spin_lock_irqsave(&priv->spinlock, flags);
+	buffer = priv->free;
+	priv->free = buffer->next;
+	spin_unlock_irqrestore(&priv->spinlock, flags);
+
+
+	/* Copy data from user into buffer */
+	ret = copy_from_user(buffer->ptr, buff, words * 4);
+	if (ret) {
+		spin_lock_irqsave(&priv->spinlock, flags);
+		buffer->next = priv->free;
+		priv->free = buffer;
+		spin_unlock_irqrestore(&priv->spinlock, flags);
+		return -EFAULT;
+	}
+
+	buffer->length = words;
+
+	/* Append batch buffer end command */
+	buffer->ptr[words] = 0x01000000;
+
+	/*
+	 * Add buffer to ready list
+	 */
+	spin_lock_irqsave(&priv->spinlock, flags);
+
+	buffer->next = NULL;
+
+	if (priv->ready) {
+		BUG_ON(priv->ready_last == NULL);
+
+		priv->ready_last->next = buffer;
+	} else
+		priv->ready = buffer;
+
+	priv->ready_last = buffer;
+
+	if (!priv->shared->hw_running)
+		run_ready(priv);
+
+	spin_unlock_irqrestore(&priv->spinlock, flags);
+
+	return words * 4;
+}
+
+
+static long
+pxa3xx_gcu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	unsigned long flags;
+	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
+
+	switch (cmd) {
+	case PXA3XX_GCU_IOCTL_RESET:
+		spin_lock_irqsave(&priv->spinlock, flags);
+		pxa3xx_gcu_reset(priv);
+		spin_unlock_irqrestore(&priv->spinlock, flags);
+		return 0;
+
+	case PXA3XX_GCU_IOCTL_WAIT_IDLE:
+		return pxa3xx_gcu_wait_idle(priv);
+	}
+
+	return -ENOSYS;
+}
+
+static int
+pxa3xx_gcu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	unsigned int size = vma->vm_end - vma->vm_start;
+	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
+
+	switch (vma->vm_pgoff) {
+	case 0:
+		/* hand out the shared data area */
+		if (size != SHARED_SIZE)
+			return -EINVAL;
+
+		return dma_mmap_coherent(NULL, vma,
+			priv->shared, priv->shared_phys, size);
+
+	case SHARED_SIZE >> PAGE_SHIFT:
+		/* hand out the MMIO base for direct register access
+		 * from userspace */
+		if (size != resource_size(priv->resource_mem))
+			return -EINVAL;
+
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+		return io_remap_pfn_range(vma, vma->vm_start,
+				priv->resource_mem->start >> PAGE_SHIFT,
+				size, vma->vm_page_prot);
+	}
+
+	return -EINVAL;
+}
+
+
+#ifdef PXA3XX_GCU_DEBUG_TIMER
+static struct timer_list pxa3xx_gcu_debug_timer;
+
+static void pxa3xx_gcu_debug_timedout(unsigned long ptr)
+{
+	struct pxa3xx_gcu_priv *priv = (struct pxa3xx_gcu_priv *) ptr;
+
+	QERROR("Timer DUMP");
+
+	/* init the timer structure */
+	init_timer(&pxa3xx_gcu_debug_timer);
+	pxa3xx_gcu_debug_timer.function = pxa3xx_gcu_debug_timedout;
+	pxa3xx_gcu_debug_timer.data = ptr;
+	pxa3xx_gcu_debug_timer.expires = jiffies + 5*HZ; /* one second */
+
+	add_timer(&pxa3xx_gcu_debug_timer);
+}
+
+static void pxa3xx_gcu_init_debug_timer(void)
+{
+	pxa3xx_gcu_debug_timedout((unsigned long) &pxa3xx_gcu_debug_timer);
+}
+#else
+static inline void pxa3xx_gcu_init_debug_timer(void) {}
+#endif
+
+static int
+pxa3xx_gcu_add_buffer(struct device *dev,
+		      struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_batch *buffer;
+
+	buffer = kzalloc(sizeof(struct pxa3xx_gcu_batch), GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	buffer->ptr = dma_alloc_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
+					 &buffer->phys, GFP_KERNEL);
+	if (!buffer->ptr) {
+		kfree(buffer);
+		return -ENOMEM;
+	}
+
+	buffer->next = priv->free;
+	priv->free = buffer;
+
+	return 0;
+}
+
+static void
+pxa3xx_gcu_free_buffers(struct device *dev,
+			struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_batch *next, *buffer = priv->free;
+
+	while (buffer) {
+		next = buffer->next;
+
+		dma_free_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
+				  buffer->ptr, buffer->phys);
+
+		kfree(buffer);
+		buffer = next;
+	}
+
+	priv->free = NULL;
+}
+
+static const struct file_operations pxa3xx_gcu_miscdev_fops = {
+	.owner =		THIS_MODULE,
+	.open =			pxa3xx_gcu_open,
+	.write =		pxa3xx_gcu_write,
+	.unlocked_ioctl =	pxa3xx_gcu_ioctl,
+	.mmap =			pxa3xx_gcu_mmap,
+};
+
+static int pxa3xx_gcu_probe(struct platform_device *pdev)
+{
+	int i, ret, irq;
+	struct resource *r;
+	struct pxa3xx_gcu_priv *priv;
+	struct device *dev = &pdev->dev;
+
+	priv = devm_kzalloc(dev, sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	init_waitqueue_head(&priv->wait_idle);
+	init_waitqueue_head(&priv->wait_free);
+	spin_lock_init(&priv->spinlock);
+
+	/* we allocate the misc device structure as part of our own allocation,
+	 * so we can get a pointer to our priv structure later on with
+	 * container_of(). This isn't really necessary as we have a fixed minor
+	 * number anyway, but this is to avoid statics. */
+
+	priv->misc_dev.minor	= MISCDEV_MINOR,
+	priv->misc_dev.name	= DRV_NAME,
+	priv->misc_dev.fops	= &pxa3xx_gcu_miscdev_fops;
+
+	/* handle IO resources */
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->mmio_base = devm_request_and_ioremap(dev, r);
+	if (IS_ERR(priv->mmio_base)) {
+		dev_err(dev, "failed to map I/O memory\n");
+		return PTR_ERR(priv->mmio_base);
+	}
+
+	/* enable the clock */
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "failed to get clock\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	/* request the IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "no IRQ defined\n");
+		return -ENODEV;
+	}
+
+	ret = devm_request_irq(dev, irq, pxa3xx_gcu_handle_irq,
+			       0, DRV_NAME, priv);
+	if (ret < 0) {
+		dev_err(dev, "request_irq failed\n");
+		return ret;
+	}
+
+	/* allocate dma memory */
+	priv->shared = dma_alloc_coherent(dev, SHARED_SIZE,
+					  &priv->shared_phys, GFP_KERNEL);
+	if (!priv->shared) {
+		dev_err(dev, "failed to allocate DMA memory\n");
+		return -ENOMEM;
+	}
+
+	/* register misc device */
+	ret = misc_register(&priv->misc_dev);
+	if (ret < 0) {
+		dev_err(dev, "misc_register() for minor %d failed\n",
+			MISCDEV_MINOR);
+		goto err_free_dma;
+	}
+
+	ret = clk_enable(priv->clk);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable clock\n");
+		goto err_misc_deregister;
+	}
+
+	for (i = 0; i < 8; i++) {
+		ret = pxa3xx_gcu_add_buffer(dev, priv);
+		if (ret) {
+			dev_err(dev, "failed to allocate DMA memory\n");
+			goto err_disable_clk;
+		}
+	}
+
+	platform_set_drvdata(pdev, priv);
+	priv->resource_mem = r;
+	pxa3xx_gcu_reset(priv);
+	pxa3xx_gcu_init_debug_timer();
+
+	dev_info(dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
+			(void *) r->start, (void *) priv->shared_phys,
+			SHARED_SIZE, irq);
+	return 0;
+
+err_free_dma:
+	dma_free_coherent(dev, SHARED_SIZE,
+			priv->shared, priv->shared_phys);
+
+err_misc_deregister:
+	misc_deregister(&priv->misc_dev);
+
+err_disable_clk:
+	clk_disable(priv->clk);
+
+	return ret;
+}
+
+static int pxa3xx_gcu_remove(struct platform_device *pdev)
+{
+	struct pxa3xx_gcu_priv *priv = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+
+	pxa3xx_gcu_wait_idle(priv);
+	misc_deregister(&priv->misc_dev);
+	dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys);
+	pxa3xx_gcu_free_buffers(dev, priv);
+
+	return 0;
+}
+
+static struct platform_driver pxa3xx_gcu_driver = {
+	.probe	  = pxa3xx_gcu_probe,
+	.remove	 = pxa3xx_gcu_remove,
+	.driver	 = {
+		.owner  = THIS_MODULE,
+		.name   = DRV_NAME,
+	},
+};
+
+module_platform_driver(pxa3xx_gcu_driver);
+
+MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(MISCDEV_MINOR);
+MODULE_AUTHOR("Janine Kropp <nin@directfb.org>, "
+		"Denis Oliver Kropp <dok@directfb.org>, "
+		"Daniel Mack <daniel@caiaq.de>");
diff --git a/drivers/video/fbdev/pxa3xx-gcu.h b/drivers/video/fbdev/pxa3xx-gcu.h
new file mode 100644
index 000000000000..0428ed03dc49
--- /dev/null
+++ b/drivers/video/fbdev/pxa3xx-gcu.h
@@ -0,0 +1,38 @@
+#ifndef __PXA3XX_GCU_H__
+#define __PXA3XX_GCU_H__
+
+#include <linux/types.h>
+
+/* Number of 32bit words in display list (ring buffer). */
+#define PXA3XX_GCU_BUFFER_WORDS  ((256 * 1024 - 256) / 4)
+
+/* To be increased when breaking the ABI */
+#define PXA3XX_GCU_SHARED_MAGIC  0x30000001
+
+#define PXA3XX_GCU_BATCH_WORDS   8192
+
+struct pxa3xx_gcu_shared {
+	u32            buffer[PXA3XX_GCU_BUFFER_WORDS];
+
+	bool           hw_running;
+
+	unsigned long  buffer_phys;
+
+	unsigned int   num_words;
+	unsigned int   num_writes;
+	unsigned int   num_done;
+	unsigned int   num_interrupts;
+	unsigned int   num_wait_idle;
+	unsigned int   num_wait_free;
+	unsigned int   num_idle;
+
+	u32            magic;
+};
+
+/* Initialization and synchronization.
+ * Hardware is started upon write(). */
+#define PXA3XX_GCU_IOCTL_RESET		_IO('G', 0)
+#define PXA3XX_GCU_IOCTL_WAIT_IDLE	_IO('G', 2)
+
+#endif /* __PXA3XX_GCU_H__ */
+
diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
new file mode 100644
index 000000000000..1ecd9cec2921
--- /dev/null
+++ b/drivers/video/fbdev/pxafb.c
@@ -0,0 +1,2332 @@
+/*
+ *  linux/drivers/video/pxafb.c
+ *
+ *  Copyright (C) 1999 Eric A. Thomas.
+ *  Copyright (C) 2004 Jean-Frederic Clere.
+ *  Copyright (C) 2004 Ian Campbell.
+ *  Copyright (C) 2004 Jeff Lackey.
+ *   Based on sa1100fb.c Copyright (C) 1999 Eric A. Thomas
+ *  which in turn is
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *	        Intel PXA250/210 LCD Controller Frame Buffer Driver
+ *
+ * Please direct your questions and comments on this driver to the following
+ * email address:
+ *
+ *	linux-arm-kernel@lists.arm.linux.org.uk
+ *
+ * Add support for overlay1 and overlay2 based on pxafb_overlay.c:
+ *
+ *   Copyright (C) 2004, Intel Corporation
+ *
+ *     2003/08/27: <yu.tang@intel.com>
+ *     2004/03/10: <stanley.cai@intel.com>
+ *     2004/10/28: <yan.yin@intel.com>
+ *
+ *   Copyright (C) 2006-2008 Marvell International Ltd.
+ *   All Rights Reserved
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/cpufreq.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/console.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+#include <mach/bitfield.h>
+#include <linux/platform_data/video-pxafb.h>
+
+/*
+ * Complain if VAR is out of range.
+ */
+#define DEBUG_VAR 1
+
+#include "pxafb.h"
+
+/* Bits which should not be set in machine configuration structures */
+#define LCCR0_INVALID_CONFIG_MASK	(LCCR0_OUM | LCCR0_BM | LCCR0_QDM |\
+					 LCCR0_DIS | LCCR0_EFM | LCCR0_IUM |\
+					 LCCR0_SFM | LCCR0_LDM | LCCR0_ENB)
+
+#define LCCR3_INVALID_CONFIG_MASK	(LCCR3_HSP | LCCR3_VSP |\
+					 LCCR3_PCD | LCCR3_BPP(0xf))
+
+static int pxafb_activate_var(struct fb_var_screeninfo *var,
+				struct pxafb_info *);
+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
+static void setup_base_frame(struct pxafb_info *fbi,
+                             struct fb_var_screeninfo *var, int branch);
+static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
+			   unsigned long offset, size_t size);
+
+static unsigned long video_mem_size = 0;
+
+static inline unsigned long
+lcd_readl(struct pxafb_info *fbi, unsigned int off)
+{
+	return __raw_readl(fbi->mmio_base + off);
+}
+
+static inline void
+lcd_writel(struct pxafb_info *fbi, unsigned int off, unsigned long val)
+{
+	__raw_writel(val, fbi->mmio_base + off);
+}
+
+static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	/*
+	 * We need to handle two requests being made at the same time.
+	 * There are two important cases:
+	 *  1. When we are changing VT (C_REENABLE) while unblanking
+	 *     (C_ENABLE) We must perform the unblanking, which will
+	 *     do our REENABLE for us.
+	 *  2. When we are blanking, but immediately unblank before
+	 *     we have blanked.  We do the "REENABLE" thing here as
+	 *     well, just to be sure.
+	 */
+	if (fbi->task_state == C_ENABLE && state == C_REENABLE)
+		state = (u_int) -1;
+	if (fbi->task_state == C_DISABLE && state == C_ENABLE)
+		state = C_REENABLE;
+
+	if (state != (u_int)-1) {
+		fbi->task_state = state;
+		schedule_work(&fbi->task);
+	}
+	local_irq_restore(flags);
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int
+pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
+		       u_int trans, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	u_int val;
+
+	if (regno >= fbi->palette_size)
+		return 1;
+
+	if (fbi->fb.var.grayscale) {
+		fbi->palette_cpu[regno] = ((blue >> 8) & 0x00ff);
+		return 0;
+	}
+
+	switch (fbi->lccr4 & LCCR4_PAL_FOR_MASK) {
+	case LCCR4_PAL_FOR_0:
+		val  = ((red   >>  0) & 0xf800);
+		val |= ((green >>  5) & 0x07e0);
+		val |= ((blue  >> 11) & 0x001f);
+		fbi->palette_cpu[regno] = val;
+		break;
+	case LCCR4_PAL_FOR_1:
+		val  = ((red   << 8) & 0x00f80000);
+		val |= ((green >> 0) & 0x0000fc00);
+		val |= ((blue  >> 8) & 0x000000f8);
+		((u32 *)(fbi->palette_cpu))[regno] = val;
+		break;
+	case LCCR4_PAL_FOR_2:
+		val  = ((red   << 8) & 0x00fc0000);
+		val |= ((green >> 0) & 0x0000fc00);
+		val |= ((blue  >> 8) & 0x000000fc);
+		((u32 *)(fbi->palette_cpu))[regno] = val;
+		break;
+	case LCCR4_PAL_FOR_3:
+		val  = ((red   << 8) & 0x00ff0000);
+		val |= ((green >> 0) & 0x0000ff00);
+		val |= ((blue  >> 8) & 0x000000ff);
+		((u32 *)(fbi->palette_cpu))[regno] = val;
+		break;
+	}
+
+	return 0;
+}
+
+static int
+pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		   u_int trans, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	unsigned int val;
+	int ret = 1;
+
+	/*
+	 * If inverse mode was selected, invert all the colours
+	 * rather than the register number.  The register number
+	 * is what you poke into the framebuffer to produce the
+	 * colour you requested.
+	 */
+	if (fbi->cmap_inverse) {
+		red   = 0xffff - red;
+		green = 0xffff - green;
+		blue  = 0xffff - blue;
+	}
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (fbi->fb.var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = fbi->fb.pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);
+		break;
+	}
+
+	return ret;
+}
+
+/* calculate pixel depth, transparency bit included, >=16bpp formats _only_ */
+static inline int var_to_depth(struct fb_var_screeninfo *var)
+{
+	return var->red.length + var->green.length +
+		var->blue.length + var->transp.length;
+}
+
+/* calculate 4-bit BPP value for LCCR3 and OVLxC1 */
+static int pxafb_var_to_bpp(struct fb_var_screeninfo *var)
+{
+	int bpp = -EINVAL;
+
+	switch (var->bits_per_pixel) {
+	case 1:  bpp = 0; break;
+	case 2:  bpp = 1; break;
+	case 4:  bpp = 2; break;
+	case 8:  bpp = 3; break;
+	case 16: bpp = 4; break;
+	case 24:
+		switch (var_to_depth(var)) {
+		case 18: bpp = 6; break; /* 18-bits/pixel packed */
+		case 19: bpp = 8; break; /* 19-bits/pixel packed */
+		case 24: bpp = 9; break;
+		}
+		break;
+	case 32:
+		switch (var_to_depth(var)) {
+		case 18: bpp = 5; break; /* 18-bits/pixel unpacked */
+		case 19: bpp = 7; break; /* 19-bits/pixel unpacked */
+		case 25: bpp = 10; break;
+		}
+		break;
+	}
+	return bpp;
+}
+
+/*
+ *  pxafb_var_to_lccr3():
+ *    Convert a bits per pixel value to the correct bit pattern for LCCR3
+ *
+ *  NOTE: for PXA27x with overlays support, the LCCR3_PDFOR_x bits have an
+ *  implication of the acutal use of transparency bit,  which we handle it
+ *  here separatedly. See PXA27x Developer's Manual, Section <<7.4.6 Pixel
+ *  Formats>> for the valid combination of PDFOR, PAL_FOR for various BPP.
+ *
+ *  Transparency for palette pixel formats is not supported at the moment.
+ */
+static uint32_t pxafb_var_to_lccr3(struct fb_var_screeninfo *var)
+{
+	int bpp = pxafb_var_to_bpp(var);
+	uint32_t lccr3;
+
+	if (bpp < 0)
+		return 0;
+
+	lccr3 = LCCR3_BPP(bpp);
+
+	switch (var_to_depth(var)) {
+	case 16: lccr3 |= var->transp.length ? LCCR3_PDFOR_3 : 0; break;
+	case 18: lccr3 |= LCCR3_PDFOR_3; break;
+	case 24: lccr3 |= var->transp.length ? LCCR3_PDFOR_2 : LCCR3_PDFOR_3;
+		 break;
+	case 19:
+	case 25: lccr3 |= LCCR3_PDFOR_0; break;
+	}
+	return lccr3;
+}
+
+#define SET_PIXFMT(v, r, g, b, t)				\
+({								\
+	(v)->transp.offset = (t) ? (r) + (g) + (b) : 0;		\
+	(v)->transp.length = (t) ? (t) : 0;			\
+	(v)->blue.length   = (b); (v)->blue.offset = 0;		\
+	(v)->green.length  = (g); (v)->green.offset = (b);	\
+	(v)->red.length    = (r); (v)->red.offset = (b) + (g);	\
+})
+
+/* set the RGBT bitfields of fb_var_screeninf according to
+ * var->bits_per_pixel and given depth
+ */
+static void pxafb_set_pixfmt(struct fb_var_screeninfo *var, int depth)
+{
+	if (depth == 0)
+		depth = var->bits_per_pixel;
+
+	if (var->bits_per_pixel < 16) {
+		/* indexed pixel formats */
+		var->red.offset    = 0; var->red.length    = 8;
+		var->green.offset  = 0; var->green.length  = 8;
+		var->blue.offset   = 0; var->blue.length   = 8;
+		var->transp.offset = 0; var->transp.length = 8;
+	}
+
+	switch (depth) {
+	case 16: var->transp.length ?
+		 SET_PIXFMT(var, 5, 5, 5, 1) :		/* RGBT555 */
+		 SET_PIXFMT(var, 5, 6, 5, 0); break;	/* RGB565 */
+	case 18: SET_PIXFMT(var, 6, 6, 6, 0); break;	/* RGB666 */
+	case 19: SET_PIXFMT(var, 6, 6, 6, 1); break;	/* RGBT666 */
+	case 24: var->transp.length ?
+		 SET_PIXFMT(var, 8, 8, 7, 1) :		/* RGBT887 */
+		 SET_PIXFMT(var, 8, 8, 8, 0); break;	/* RGB888 */
+	case 25: SET_PIXFMT(var, 8, 8, 8, 1); break;	/* RGBT888 */
+	}
+}
+
+#ifdef CONFIG_CPU_FREQ
+/*
+ *  pxafb_display_dma_period()
+ *    Calculate the minimum period (in picoseconds) between two DMA
+ *    requests for the LCD controller.  If we hit this, it means we're
+ *    doing nothing but LCD DMA.
+ */
+static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
+{
+	/*
+	 * Period = pixclock * bits_per_byte * bytes_per_transfer
+	 *              / memory_bits_per_pixel;
+	 */
+	return var->pixclock * 8 * 16 / var->bits_per_pixel;
+}
+#endif
+
+/*
+ * Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired parameters can be rounded up.
+ */
+static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach,
+					     struct fb_var_screeninfo *var)
+{
+	struct pxafb_mode_info *mode = NULL;
+	struct pxafb_mode_info *modelist = mach->modes;
+	unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+	unsigned int i;
+
+	for (i = 0; i < mach->num_modes; i++) {
+		if (modelist[i].xres >= var->xres &&
+		    modelist[i].yres >= var->yres &&
+		    modelist[i].xres < best_x &&
+		    modelist[i].yres < best_y &&
+		    modelist[i].bpp >= var->bits_per_pixel) {
+			best_x = modelist[i].xres;
+			best_y = modelist[i].yres;
+			mode = &modelist[i];
+		}
+	}
+
+	return mode;
+}
+
+static void pxafb_setmode(struct fb_var_screeninfo *var,
+			  struct pxafb_mode_info *mode)
+{
+	var->xres		= mode->xres;
+	var->yres		= mode->yres;
+	var->bits_per_pixel	= mode->bpp;
+	var->pixclock		= mode->pixclock;
+	var->hsync_len		= mode->hsync_len;
+	var->left_margin	= mode->left_margin;
+	var->right_margin	= mode->right_margin;
+	var->vsync_len		= mode->vsync_len;
+	var->upper_margin	= mode->upper_margin;
+	var->lower_margin	= mode->lower_margin;
+	var->sync		= mode->sync;
+	var->grayscale		= mode->cmap_greyscale;
+	var->transp.length	= mode->transparency;
+
+	/* set the initial RGBA bitfields */
+	pxafb_set_pixfmt(var, mode->depth);
+}
+
+static int pxafb_adjust_timing(struct pxafb_info *fbi,
+			       struct fb_var_screeninfo *var)
+{
+	int line_length;
+
+	var->xres = max_t(int, var->xres, MIN_XRES);
+	var->yres = max_t(int, var->yres, MIN_YRES);
+
+	if (!(fbi->lccr0 & LCCR0_LCDT)) {
+		clamp_val(var->hsync_len, 1, 64);
+		clamp_val(var->vsync_len, 1, 64);
+		clamp_val(var->left_margin,  1, 255);
+		clamp_val(var->right_margin, 1, 255);
+		clamp_val(var->upper_margin, 1, 255);
+		clamp_val(var->lower_margin, 1, 255);
+	}
+
+	/* make sure each line is aligned on word boundary */
+	line_length = var->xres * var->bits_per_pixel / 8;
+	line_length = ALIGN(line_length, 4);
+	var->xres = line_length * 8 / var->bits_per_pixel;
+
+	/* we don't support xpan, force xres_virtual to be equal to xres */
+	var->xres_virtual = var->xres;
+
+	if (var->accel_flags & FB_ACCELF_TEXT)
+		var->yres_virtual = fbi->fb.fix.smem_len / line_length;
+	else
+		var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	/* check for limits */
+	if (var->xres > MAX_XRES || var->yres > MAX_YRES)
+		return -EINVAL;
+
+	if (var->yres > var->yres_virtual)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ *  pxafb_check_var():
+ *    Get the video params out of 'var'. If a value doesn't fit, round it up,
+ *    if it's too big, return -EINVAL.
+ *
+ *    Round up in the following order: bits_per_pixel, xres,
+ *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+ *    bitfields, horizontal timing, vertical timing.
+ */
+static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
+	int err;
+
+	if (inf->fixed_modes) {
+		struct pxafb_mode_info *mode;
+
+		mode = pxafb_getmode(inf, var);
+		if (!mode)
+			return -EINVAL;
+		pxafb_setmode(var, mode);
+	}
+
+	/* do a test conversion to BPP fields to check the color formats */
+	err = pxafb_var_to_bpp(var);
+	if (err < 0)
+		return err;
+
+	pxafb_set_pixfmt(var, var_to_depth(var));
+
+	err = pxafb_adjust_timing(fbi, var);
+	if (err)
+		return err;
+
+#ifdef CONFIG_CPU_FREQ
+	pr_debug("pxafb: dma period = %d ps\n",
+		 pxafb_display_dma_period(var));
+#endif
+
+	return 0;
+}
+
+/*
+ * pxafb_set_par():
+ *	Set the user defined part of the display for the specified console
+ */
+static int pxafb_set_par(struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	struct fb_var_screeninfo *var = &info->var;
+
+	if (var->bits_per_pixel >= 16)
+		fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+	else if (!fbi->cmap_static)
+		fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else {
+		/*
+		 * Some people have weird ideas about wanting static
+		 * pseudocolor maps.  I suspect their user space
+		 * applications are broken.
+		 */
+		fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+	}
+
+	fbi->fb.fix.line_length = var->xres_virtual *
+				  var->bits_per_pixel / 8;
+	if (var->bits_per_pixel >= 16)
+		fbi->palette_size = 0;
+	else
+		fbi->palette_size = var->bits_per_pixel == 1 ?
+					4 : 1 << var->bits_per_pixel;
+
+	fbi->palette_cpu = (u16 *)&fbi->dma_buff->palette[0];
+
+	if (fbi->fb.var.bits_per_pixel >= 16)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+	else
+		fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
+
+	pxafb_activate_var(var, fbi);
+
+	return 0;
+}
+
+static int pxafb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	struct fb_var_screeninfo newvar;
+	int dma = DMA_MAX + DMA_BASE;
+
+	if (fbi->state != C_ENABLE)
+		return 0;
+
+	/* Only take .xoffset, .yoffset and .vmode & FB_VMODE_YWRAP from what
+	 * was passed in and copy the rest from the old screeninfo.
+	 */
+	memcpy(&newvar, &fbi->fb.var, sizeof(newvar));
+	newvar.xoffset = var->xoffset;
+	newvar.yoffset = var->yoffset;
+	newvar.vmode &= ~FB_VMODE_YWRAP;
+	newvar.vmode |= var->vmode & FB_VMODE_YWRAP;
+
+	setup_base_frame(fbi, &newvar, 1);
+
+	if (fbi->lccr0 & LCCR0_SDS)
+		lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1);
+
+	lcd_writel(fbi, FBR0, fbi->fdadr[dma] | 0x1);
+	return 0;
+}
+
+/*
+ * pxafb_blank():
+ *	Blank the display by setting all palette values to zero.  Note, the
+ * 	16 bpp mode does not really use the palette, so this will not
+ *      blank the display in all modes.
+ */
+static int pxafb_blank(int blank, struct fb_info *info)
+{
+	struct pxafb_info *fbi = (struct pxafb_info *)info;
+	int i;
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			for (i = 0; i < fbi->palette_size; i++)
+				pxafb_setpalettereg(i, 0, 0, 0, 0, info);
+
+		pxafb_schedule_work(fbi, C_DISABLE);
+		/* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
+		break;
+
+	case FB_BLANK_UNBLANK:
+		/* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
+		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			fb_set_cmap(&fbi->fb.cmap, info);
+		pxafb_schedule_work(fbi, C_ENABLE);
+	}
+	return 0;
+}
+
+static struct fb_ops pxafb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= pxafb_check_var,
+	.fb_set_par	= pxafb_set_par,
+	.fb_pan_display	= pxafb_pan_display,
+	.fb_setcolreg	= pxafb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_blank	= pxafb_blank,
+};
+
+#ifdef CONFIG_FB_PXA_OVERLAY
+static void overlay1fb_setup(struct pxafb_layer *ofb)
+{
+	int size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
+	unsigned long start = ofb->video_mem_phys;
+	setup_frame_dma(ofb->fbi, DMA_OV1, PAL_NONE, start, size);
+}
+
+/* Depending on the enable status of overlay1/2, the DMA should be
+ * updated from FDADRx (when disabled) or FBRx (when enabled).
+ */
+static void overlay1fb_enable(struct pxafb_layer *ofb)
+{
+	int enabled = lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN;
+	uint32_t fdadr1 = ofb->fbi->fdadr[DMA_OV1] | (enabled ? 0x1 : 0);
+
+	lcd_writel(ofb->fbi, enabled ? FBR1 : FDADR1, fdadr1);
+	lcd_writel(ofb->fbi, OVL1C2, ofb->control[1]);
+	lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] | OVLxC1_OEN);
+}
+
+static void overlay1fb_disable(struct pxafb_layer *ofb)
+{
+	uint32_t lccr5;
+
+	if (!(lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN))
+		return;
+
+	lccr5 = lcd_readl(ofb->fbi, LCCR5);
+
+	lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
+
+	lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(1));
+	lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(1));
+	lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3);
+
+	if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
+		pr_warning("%s: timeout disabling overlay1\n", __func__);
+
+	lcd_writel(ofb->fbi, LCCR5, lccr5);
+}
+
+static void overlay2fb_setup(struct pxafb_layer *ofb)
+{
+	int size, div = 1, pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
+	unsigned long start[3] = { ofb->video_mem_phys, 0, 0 };
+
+	if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED) {
+		size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
+		setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size);
+	} else {
+		size = ofb->fb.var.xres_virtual * ofb->fb.var.yres_virtual;
+		switch (pfor) {
+		case OVERLAY_FORMAT_YUV444_PLANAR: div = 1; break;
+		case OVERLAY_FORMAT_YUV422_PLANAR: div = 2; break;
+		case OVERLAY_FORMAT_YUV420_PLANAR: div = 4; break;
+		}
+		start[1] = start[0] + size;
+		start[2] = start[1] + size / div;
+		setup_frame_dma(ofb->fbi, DMA_OV2_Y,  -1, start[0], size);
+		setup_frame_dma(ofb->fbi, DMA_OV2_Cb, -1, start[1], size / div);
+		setup_frame_dma(ofb->fbi, DMA_OV2_Cr, -1, start[2], size / div);
+	}
+}
+
+static void overlay2fb_enable(struct pxafb_layer *ofb)
+{
+	int pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
+	int enabled = lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN;
+	uint32_t fdadr2 = ofb->fbi->fdadr[DMA_OV2_Y]  | (enabled ? 0x1 : 0);
+	uint32_t fdadr3 = ofb->fbi->fdadr[DMA_OV2_Cb] | (enabled ? 0x1 : 0);
+	uint32_t fdadr4 = ofb->fbi->fdadr[DMA_OV2_Cr] | (enabled ? 0x1 : 0);
+
+	if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED)
+		lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
+	else {
+		lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
+		lcd_writel(ofb->fbi, enabled ? FBR3 : FDADR3, fdadr3);
+		lcd_writel(ofb->fbi, enabled ? FBR4 : FDADR4, fdadr4);
+	}
+	lcd_writel(ofb->fbi, OVL2C2, ofb->control[1]);
+	lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] | OVLxC1_OEN);
+}
+
+static void overlay2fb_disable(struct pxafb_layer *ofb)
+{
+	uint32_t lccr5;
+
+	if (!(lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN))
+		return;
+
+	lccr5 = lcd_readl(ofb->fbi, LCCR5);
+
+	lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);
+
+	lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(2));
+	lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(2));
+	lcd_writel(ofb->fbi, FBR2, ofb->fbi->fdadr[DMA_OV2_Y]  | 0x3);
+	lcd_writel(ofb->fbi, FBR3, ofb->fbi->fdadr[DMA_OV2_Cb] | 0x3);
+	lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3);
+
+	if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
+		pr_warning("%s: timeout disabling overlay2\n", __func__);
+}
+
+static struct pxafb_layer_ops ofb_ops[] = {
+	[0] = {
+		.enable		= overlay1fb_enable,
+		.disable	= overlay1fb_disable,
+		.setup		= overlay1fb_setup,
+	},
+	[1] = {
+		.enable		= overlay2fb_enable,
+		.disable	= overlay2fb_disable,
+		.setup		= overlay2fb_setup,
+	},
+};
+
+static int overlayfb_open(struct fb_info *info, int user)
+{
+	struct pxafb_layer *ofb = (struct pxafb_layer *)info;
+
+	/* no support for framebuffer console on overlay */
+	if (user == 0)
+		return -ENODEV;
+
+	if (ofb->usage++ == 0) {
+		/* unblank the base framebuffer */
+		console_lock();
+		fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
+		console_unlock();
+	}
+
+	return 0;
+}
+
+static int overlayfb_release(struct fb_info *info, int user)
+{
+	struct pxafb_layer *ofb = (struct pxafb_layer*) info;
+
+	if (ofb->usage == 1) {
+		ofb->ops->disable(ofb);
+		ofb->fb.var.height	= -1;
+		ofb->fb.var.width	= -1;
+		ofb->fb.var.xres = ofb->fb.var.xres_virtual = 0;
+		ofb->fb.var.yres = ofb->fb.var.yres_virtual = 0;
+
+		ofb->usage--;
+	}
+	return 0;
+}
+
+static int overlayfb_check_var(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	struct pxafb_layer *ofb = (struct pxafb_layer *)info;
+	struct fb_var_screeninfo *base_var = &ofb->fbi->fb.var;
+	int xpos, ypos, pfor, bpp;
+
+	xpos = NONSTD_TO_XPOS(var->nonstd);
+	ypos = NONSTD_TO_YPOS(var->nonstd);
+	pfor = NONSTD_TO_PFOR(var->nonstd);
+
+	bpp = pxafb_var_to_bpp(var);
+	if (bpp < 0)
+		return -EINVAL;
+
+	/* no support for YUV format on overlay1 */
+	if (ofb->id == OVERLAY1 && pfor != 0)
+		return -EINVAL;
+
+	/* for YUV packed formats, bpp = 'minimum bpp of YUV components' */
+	switch (pfor) {
+	case OVERLAY_FORMAT_RGB:
+		bpp = pxafb_var_to_bpp(var);
+		if (bpp < 0)
+			return -EINVAL;
+
+		pxafb_set_pixfmt(var, var_to_depth(var));
+		break;
+	case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
+	case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 8; break;
+	case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 4; break;
+	case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 2; break;
+	default:
+		return -EINVAL;
+	}
+
+	/* each line must start at a 32-bit word boundary */
+	if ((xpos * bpp) % 32)
+		return -EINVAL;
+
+	/* xres must align on 32-bit word boundary */
+	var->xres = roundup(var->xres * bpp, 32) / bpp;
+
+	if ((xpos + var->xres > base_var->xres) ||
+	    (ypos + var->yres > base_var->yres))
+		return -EINVAL;
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = max(var->yres, var->yres_virtual);
+	return 0;
+}
+
+static int overlayfb_check_video_memory(struct pxafb_layer *ofb)
+{
+	struct fb_var_screeninfo *var = &ofb->fb.var;
+	int pfor = NONSTD_TO_PFOR(var->nonstd);
+	int size, bpp = 0;
+
+	switch (pfor) {
+	case OVERLAY_FORMAT_RGB: bpp = var->bits_per_pixel; break;
+	case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
+	case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 24; break;
+	case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 16; break;
+	case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 12; break;
+	}
+
+	ofb->fb.fix.line_length = var->xres_virtual * bpp / 8;
+
+	size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual);
+
+	if (ofb->video_mem) {
+		if (ofb->video_mem_size >= size)
+			return 0;
+	}
+	return -EINVAL;
+}
+
+static int overlayfb_set_par(struct fb_info *info)
+{
+	struct pxafb_layer *ofb = (struct pxafb_layer *)info;
+	struct fb_var_screeninfo *var = &info->var;
+	int xpos, ypos, pfor, bpp, ret;
+
+	ret = overlayfb_check_video_memory(ofb);
+	if (ret)
+		return ret;
+
+	bpp  = pxafb_var_to_bpp(var);
+	xpos = NONSTD_TO_XPOS(var->nonstd);
+	ypos = NONSTD_TO_YPOS(var->nonstd);
+	pfor = NONSTD_TO_PFOR(var->nonstd);
+
+	ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) |
+			  OVLxC1_BPP(bpp);
+	ofb->control[1] = OVLxC2_XPOS(xpos) | OVLxC2_YPOS(ypos);
+
+	if (ofb->id == OVERLAY2)
+		ofb->control[1] |= OVL2C2_PFOR(pfor);
+
+	ofb->ops->setup(ofb);
+	ofb->ops->enable(ofb);
+	return 0;
+}
+
+static struct fb_ops overlay_fb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_open		= overlayfb_open,
+	.fb_release		= overlayfb_release,
+	.fb_check_var 		= overlayfb_check_var,
+	.fb_set_par		= overlayfb_set_par,
+};
+
+static void init_pxafb_overlay(struct pxafb_info *fbi, struct pxafb_layer *ofb,
+			       int id)
+{
+	sprintf(ofb->fb.fix.id, "overlay%d", id + 1);
+
+	ofb->fb.fix.type		= FB_TYPE_PACKED_PIXELS;
+	ofb->fb.fix.xpanstep		= 0;
+	ofb->fb.fix.ypanstep		= 1;
+
+	ofb->fb.var.activate		= FB_ACTIVATE_NOW;
+	ofb->fb.var.height		= -1;
+	ofb->fb.var.width		= -1;
+	ofb->fb.var.vmode		= FB_VMODE_NONINTERLACED;
+
+	ofb->fb.fbops			= &overlay_fb_ops;
+	ofb->fb.flags			= FBINFO_FLAG_DEFAULT;
+	ofb->fb.node			= -1;
+	ofb->fb.pseudo_palette		= NULL;
+
+	ofb->id = id;
+	ofb->ops = &ofb_ops[id];
+	ofb->usage = 0;
+	ofb->fbi = fbi;
+	init_completion(&ofb->branch_done);
+}
+
+static inline int pxafb_overlay_supported(void)
+{
+	if (cpu_is_pxa27x() || cpu_is_pxa3xx())
+		return 1;
+
+	return 0;
+}
+
+static int pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
+					  struct pxafb_layer *ofb)
+{
+	/* We assume that user will use at most video_mem_size for overlay fb,
+	 * anyway, it's useless to use 16bpp main plane and 24bpp overlay
+	 */
+	ofb->video_mem = alloc_pages_exact(PAGE_ALIGN(pxafb->video_mem_size),
+		GFP_KERNEL | __GFP_ZERO);
+	if (ofb->video_mem == NULL)
+		return -ENOMEM;
+
+	ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
+	ofb->video_mem_size = PAGE_ALIGN(pxafb->video_mem_size);
+
+	mutex_lock(&ofb->fb.mm_lock);
+	ofb->fb.fix.smem_start	= ofb->video_mem_phys;
+	ofb->fb.fix.smem_len	= pxafb->video_mem_size;
+	mutex_unlock(&ofb->fb.mm_lock);
+
+	ofb->fb.screen_base	= ofb->video_mem;
+
+	return 0;
+}
+
+static void pxafb_overlay_init(struct pxafb_info *fbi)
+{
+	int i, ret;
+
+	if (!pxafb_overlay_supported())
+		return;
+
+	for (i = 0; i < 2; i++) {
+		struct pxafb_layer *ofb = &fbi->overlay[i];
+		init_pxafb_overlay(fbi, ofb, i);
+		ret = register_framebuffer(&ofb->fb);
+		if (ret) {
+			dev_err(fbi->dev, "failed to register overlay %d\n", i);
+			continue;
+		}
+		ret = pxafb_overlay_map_video_memory(fbi, ofb);
+		if (ret) {
+			dev_err(fbi->dev,
+				"failed to map video memory for overlay %d\n",
+				i);
+			unregister_framebuffer(&ofb->fb);
+			continue;
+		}
+		ofb->registered = 1;
+	}
+
+	/* mask all IU/BS/EOF/SOF interrupts */
+	lcd_writel(fbi, LCCR5, ~0);
+
+	pr_info("PXA Overlay driver loaded successfully!\n");
+}
+
+static void pxafb_overlay_exit(struct pxafb_info *fbi)
+{
+	int i;
+
+	if (!pxafb_overlay_supported())
+		return;
+
+	for (i = 0; i < 2; i++) {
+		struct pxafb_layer *ofb = &fbi->overlay[i];
+		if (ofb->registered) {
+			if (ofb->video_mem)
+				free_pages_exact(ofb->video_mem,
+					ofb->video_mem_size);
+			unregister_framebuffer(&ofb->fb);
+		}
+	}
+}
+#else
+static inline void pxafb_overlay_init(struct pxafb_info *fbi) {}
+static inline void pxafb_overlay_exit(struct pxafb_info *fbi) {}
+#endif /* CONFIG_FB_PXA_OVERLAY */
+
+/*
+ * Calculate the PCD value from the clock rate (in picoseconds).
+ * We take account of the PPCR clock setting.
+ * From PXA Developer's Manual:
+ *
+ *   PixelClock =      LCLK
+ *                -------------
+ *                2 ( PCD + 1 )
+ *
+ *   PCD =      LCLK
+ *         ------------- - 1
+ *         2(PixelClock)
+ *
+ * Where:
+ *   LCLK = LCD/Memory Clock
+ *   PCD = LCCR3[7:0]
+ *
+ * PixelClock here is in Hz while the pixclock argument given is the
+ * period in picoseconds. Hence PixelClock = 1 / ( pixclock * 10^-12 )
+ *
+ * The function get_lclk_frequency_10khz returns LCLK in units of
+ * 10khz. Calling the result of this function lclk gives us the
+ * following
+ *
+ *    PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 )
+ *          -------------------------------------- - 1
+ *                          2
+ *
+ * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
+ */
+static inline unsigned int get_pcd(struct pxafb_info *fbi,
+				   unsigned int pixclock)
+{
+	unsigned long long pcd;
+
+	/* FIXME: Need to take into account Double Pixel Clock mode
+	 * (DPC) bit? or perhaps set it based on the various clock
+	 * speeds */
+	pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000);
+	pcd *= pixclock;
+	do_div(pcd, 100000000 * 2);
+	/* no need for this, since we should subtract 1 anyway. they cancel */
+	/* pcd += 1; */ /* make up for integer math truncations */
+	return (unsigned int)pcd;
+}
+
+/*
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.  Note that 'hsync_time' and
+ * the value returned from pxafb_get_hsync_time() is the *reciprocal*
+ * of the hsync period in seconds.
+ */
+static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
+{
+	unsigned long htime;
+
+	if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
+		fbi->hsync_time = 0;
+		return;
+	}
+
+	htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len);
+
+	fbi->hsync_time = htime;
+}
+
+unsigned long pxafb_get_hsync_time(struct device *dev)
+{
+	struct pxafb_info *fbi = dev_get_drvdata(dev);
+
+	/* If display is blanked/suspended, hsync isn't active */
+	if (!fbi || (fbi->state != C_ENABLE))
+		return 0;
+
+	return fbi->hsync_time;
+}
+EXPORT_SYMBOL(pxafb_get_hsync_time);
+
+static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
+			   unsigned long start, size_t size)
+{
+	struct pxafb_dma_descriptor *dma_desc, *pal_desc;
+	unsigned int dma_desc_off, pal_desc_off;
+
+	if (dma < 0 || dma >= DMA_MAX * 2)
+		return -EINVAL;
+
+	dma_desc = &fbi->dma_buff->dma_desc[dma];
+	dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]);
+
+	dma_desc->fsadr = start;
+	dma_desc->fidr  = 0;
+	dma_desc->ldcmd = size;
+
+	if (pal < 0 || pal >= PAL_MAX * 2) {
+		dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
+		fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
+	} else {
+		pal_desc = &fbi->dma_buff->pal_desc[pal];
+		pal_desc_off = offsetof(struct pxafb_dma_buff, pal_desc[pal]);
+
+		pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE;
+		pal_desc->fidr  = 0;
+
+		if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+			pal_desc->ldcmd = fbi->palette_size * sizeof(u16);
+		else
+			pal_desc->ldcmd = fbi->palette_size * sizeof(u32);
+
+		pal_desc->ldcmd |= LDCMD_PAL;
+
+		/* flip back and forth between palette and frame buffer */
+		pal_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
+		dma_desc->fdadr = fbi->dma_buff_phys + pal_desc_off;
+		fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
+	}
+
+	return 0;
+}
+
+static void setup_base_frame(struct pxafb_info *fbi,
+                             struct fb_var_screeninfo *var,
+                             int branch)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fb.fix;
+	int nbytes, dma, pal, bpp = var->bits_per_pixel;
+	unsigned long offset;
+
+	dma = DMA_BASE + (branch ? DMA_MAX : 0);
+	pal = (bpp >= 16) ? PAL_NONE : PAL_BASE + (branch ? PAL_MAX : 0);
+
+	nbytes = fix->line_length * var->yres;
+	offset = fix->line_length * var->yoffset + fbi->video_mem_phys;
+
+	if (fbi->lccr0 & LCCR0_SDS) {
+		nbytes = nbytes / 2;
+		setup_frame_dma(fbi, dma + 1, PAL_NONE, offset + nbytes, nbytes);
+	}
+
+	setup_frame_dma(fbi, dma, pal, offset, nbytes);
+}
+
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+static int setup_smart_dma(struct pxafb_info *fbi)
+{
+	struct pxafb_dma_descriptor *dma_desc;
+	unsigned long dma_desc_off, cmd_buff_off;
+
+	dma_desc = &fbi->dma_buff->dma_desc[DMA_CMD];
+	dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[DMA_CMD]);
+	cmd_buff_off = offsetof(struct pxafb_dma_buff, cmd_buff);
+
+	dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
+	dma_desc->fsadr = fbi->dma_buff_phys + cmd_buff_off;
+	dma_desc->fidr  = 0;
+	dma_desc->ldcmd = fbi->n_smart_cmds * sizeof(uint16_t);
+
+	fbi->fdadr[DMA_CMD] = dma_desc->fdadr;
+	return 0;
+}
+
+int pxafb_smart_flush(struct fb_info *info)
+{
+	struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
+	uint32_t prsr;
+	int ret = 0;
+
+	/* disable controller until all registers are set up */
+	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
+
+	/* 1. make it an even number of commands to align on 32-bit boundary
+	 * 2. add the interrupt command to the end of the chain so we can
+	 *    keep track of the end of the transfer
+	 */
+
+	while (fbi->n_smart_cmds & 1)
+		fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_NOOP;
+
+	fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_INTERRUPT;
+	fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_WAIT_FOR_VSYNC;
+	setup_smart_dma(fbi);
+
+	/* continue to execute next command */
+	prsr = lcd_readl(fbi, PRSR) | PRSR_ST_OK | PRSR_CON_NT;
+	lcd_writel(fbi, PRSR, prsr);
+
+	/* stop the processor in case it executed "wait for sync" cmd */
+	lcd_writel(fbi, CMDCR, 0x0001);
+
+	/* don't send interrupts for fifo underruns on channel 6 */
+	lcd_writel(fbi, LCCR5, LCCR5_IUM(6));
+
+	lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
+	lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
+	lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
+	lcd_writel(fbi, LCCR4, fbi->reg_lccr4);
+	lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
+	lcd_writel(fbi, FDADR6, fbi->fdadr[6]);
+
+	/* begin sending */
+	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
+
+	if (wait_for_completion_timeout(&fbi->command_done, HZ/2) == 0) {
+		pr_warning("%s: timeout waiting for command done\n",
+				__func__);
+		ret = -ETIMEDOUT;
+	}
+
+	/* quick disable */
+	prsr = lcd_readl(fbi, PRSR) & ~(PRSR_ST_OK | PRSR_CON_NT);
+	lcd_writel(fbi, PRSR, prsr);
+	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
+	lcd_writel(fbi, FDADR6, 0);
+	fbi->n_smart_cmds = 0;
+	return ret;
+}
+
+int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
+{
+	int i;
+	struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
+
+	for (i = 0; i < n_cmds; i++, cmds++) {
+		/* if it is a software delay, flush and delay */
+		if ((*cmds & 0xff00) == SMART_CMD_DELAY) {
+			pxafb_smart_flush(info);
+			mdelay(*cmds & 0xff);
+			continue;
+		}
+
+		/* leave 2 commands for INTERRUPT and WAIT_FOR_SYNC */
+		if (fbi->n_smart_cmds == CMD_BUFF_SIZE - 8)
+			pxafb_smart_flush(info);
+
+		fbi->smart_cmds[fbi->n_smart_cmds++] = *cmds;
+	}
+
+	return 0;
+}
+
+static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk)
+{
+	unsigned int t = (time_ns * (lcd_clk / 1000000) / 1000);
+	return (t == 0) ? 1 : t;
+}
+
+static void setup_smart_timing(struct pxafb_info *fbi,
+				struct fb_var_screeninfo *var)
+{
+	struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
+	struct pxafb_mode_info *mode = &inf->modes[0];
+	unsigned long lclk = clk_get_rate(fbi->clk);
+	unsigned t1, t2, t3, t4;
+
+	t1 = max(mode->a0csrd_set_hld, mode->a0cswr_set_hld);
+	t2 = max(mode->rd_pulse_width, mode->wr_pulse_width);
+	t3 = mode->op_hold_time;
+	t4 = mode->cmd_inh_time;
+
+	fbi->reg_lccr1 =
+		LCCR1_DisWdth(var->xres) |
+		LCCR1_BegLnDel(__smart_timing(t1, lclk)) |
+		LCCR1_EndLnDel(__smart_timing(t2, lclk)) |
+		LCCR1_HorSnchWdth(__smart_timing(t3, lclk));
+
+	fbi->reg_lccr2 = LCCR2_DisHght(var->yres);
+	fbi->reg_lccr3 = fbi->lccr3 | LCCR3_PixClkDiv(__smart_timing(t4, lclk));
+	fbi->reg_lccr3 |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HSP : 0;
+	fbi->reg_lccr3 |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VSP : 0;
+
+	/* FIXME: make this configurable */
+	fbi->reg_cmdcr = 1;
+}
+
+static int pxafb_smart_thread(void *arg)
+{
+	struct pxafb_info *fbi = arg;
+	struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
+
+	if (!inf->smart_update) {
+		pr_err("%s: not properly initialized, thread terminated\n",
+				__func__);
+		return -EINVAL;
+	}
+	inf = dev_get_platdata(fbi->dev);
+
+	pr_debug("%s(): task starting\n", __func__);
+
+	set_freezable();
+	while (!kthread_should_stop()) {
+
+		if (try_to_freeze())
+			continue;
+
+		mutex_lock(&fbi->ctrlr_lock);
+
+		if (fbi->state == C_ENABLE) {
+			inf->smart_update(&fbi->fb);
+			complete(&fbi->refresh_done);
+		}
+
+		mutex_unlock(&fbi->ctrlr_lock);
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(30 * HZ / 1000);
+	}
+
+	pr_debug("%s(): task ending\n", __func__);
+	return 0;
+}
+
+static int pxafb_smart_init(struct pxafb_info *fbi)
+{
+	if (!(fbi->lccr0 & LCCR0_LCDT))
+		return 0;
+
+	fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
+	fbi->n_smart_cmds = 0;
+
+	init_completion(&fbi->command_done);
+	init_completion(&fbi->refresh_done);
+
+	fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
+					"lcd_refresh");
+	if (IS_ERR(fbi->smart_thread)) {
+		pr_err("%s: unable to create kernel thread\n", __func__);
+		return PTR_ERR(fbi->smart_thread);
+	}
+
+	return 0;
+}
+#else
+static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; }
+#endif /* CONFIG_FB_PXA_SMARTPANEL */
+
+static void setup_parallel_timing(struct pxafb_info *fbi,
+				  struct fb_var_screeninfo *var)
+{
+	unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+
+	fbi->reg_lccr1 =
+		LCCR1_DisWdth(var->xres) +
+		LCCR1_HorSnchWdth(var->hsync_len) +
+		LCCR1_BegLnDel(var->left_margin) +
+		LCCR1_EndLnDel(var->right_margin);
+
+	/*
+	 * If we have a dual scan LCD, we need to halve
+	 * the YRES parameter.
+	 */
+	lines_per_panel = var->yres;
+	if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual)
+		lines_per_panel /= 2;
+
+	fbi->reg_lccr2 =
+		LCCR2_DisHght(lines_per_panel) +
+		LCCR2_VrtSnchWdth(var->vsync_len) +
+		LCCR2_BegFrmDel(var->upper_margin) +
+		LCCR2_EndFrmDel(var->lower_margin);
+
+	fbi->reg_lccr3 = fbi->lccr3 |
+		(var->sync & FB_SYNC_HOR_HIGH_ACT ?
+		 LCCR3_HorSnchH : LCCR3_HorSnchL) |
+		(var->sync & FB_SYNC_VERT_HIGH_ACT ?
+		 LCCR3_VrtSnchH : LCCR3_VrtSnchL);
+
+	if (pcd) {
+		fbi->reg_lccr3 |= LCCR3_PixClkDiv(pcd);
+		set_hsync_time(fbi, pcd);
+	}
+}
+
+/*
+ * pxafb_activate_var():
+ *	Configures LCD Controller based on entries in var parameter.
+ *	Settings are only written to the controller if changes were made.
+ */
+static int pxafb_activate_var(struct fb_var_screeninfo *var,
+			      struct pxafb_info *fbi)
+{
+	u_long flags;
+
+	/* Update shadow copy atomically */
+	local_irq_save(flags);
+
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+	if (fbi->lccr0 & LCCR0_LCDT)
+		setup_smart_timing(fbi, var);
+	else
+#endif
+		setup_parallel_timing(fbi, var);
+
+	setup_base_frame(fbi, var, 0);
+
+	fbi->reg_lccr0 = fbi->lccr0 |
+		(LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
+		 LCCR0_QDM | LCCR0_BM  | LCCR0_OUM);
+
+	fbi->reg_lccr3 |= pxafb_var_to_lccr3(var);
+
+	fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK;
+	fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
+	local_irq_restore(flags);
+
+	/*
+	 * Only update the registers if the controller is enabled
+	 * and something has changed.
+	 */
+	if ((lcd_readl(fbi, LCCR0) != fbi->reg_lccr0) ||
+	    (lcd_readl(fbi, LCCR1) != fbi->reg_lccr1) ||
+	    (lcd_readl(fbi, LCCR2) != fbi->reg_lccr2) ||
+	    (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
+	    (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) ||
+	    (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
+	    ((fbi->lccr0 & LCCR0_SDS) &&
+	    (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])))
+		pxafb_schedule_work(fbi, C_REENABLE);
+
+	return 0;
+}
+
+/*
+ * NOTE!  The following functions are purely helpers for set_ctrlr_state.
+ * Do not call them directly; set_ctrlr_state does the correct serialisation
+ * to ensure that things happen in the right way 100% of time time.
+ *	-- rmk
+ */
+static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
+{
+	pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
+
+	if (fbi->backlight_power)
+		fbi->backlight_power(on);
+}
+
+static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
+{
+	pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
+
+	if (fbi->lcd_power)
+		fbi->lcd_power(on, &fbi->fb.var);
+}
+
+static void pxafb_enable_controller(struct pxafb_info *fbi)
+{
+	pr_debug("pxafb: Enabling LCD controller\n");
+	pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr[0]);
+	pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr[1]);
+	pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
+	pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
+	pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
+	pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
+
+	/* enable LCD controller clock */
+	clk_prepare_enable(fbi->clk);
+
+	if (fbi->lccr0 & LCCR0_LCDT)
+		return;
+
+	/* Sequence from 11.7.10 */
+	lcd_writel(fbi, LCCR4, fbi->reg_lccr4);
+	lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
+	lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
+	lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
+	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
+
+	lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
+	if (fbi->lccr0 & LCCR0_SDS)
+		lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
+	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
+}
+
+static void pxafb_disable_controller(struct pxafb_info *fbi)
+{
+	uint32_t lccr0;
+
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+	if (fbi->lccr0 & LCCR0_LCDT) {
+		wait_for_completion_timeout(&fbi->refresh_done,
+				200 * HZ / 1000);
+		return;
+	}
+#endif
+
+	/* Clear LCD Status Register */
+	lcd_writel(fbi, LCSR, 0xffffffff);
+
+	lccr0 = lcd_readl(fbi, LCCR0) & ~LCCR0_LDM;
+	lcd_writel(fbi, LCCR0, lccr0);
+	lcd_writel(fbi, LCCR0, lccr0 | LCCR0_DIS);
+
+	wait_for_completion_timeout(&fbi->disable_done, 200 * HZ / 1000);
+
+	/* disable LCD controller clock */
+	clk_disable_unprepare(fbi->clk);
+}
+
+/*
+ *  pxafb_handle_irq: Handle 'LCD DONE' interrupts.
+ */
+static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
+{
+	struct pxafb_info *fbi = dev_id;
+	unsigned int lccr0, lcsr;
+
+	lcsr = lcd_readl(fbi, LCSR);
+	if (lcsr & LCSR_LDD) {
+		lccr0 = lcd_readl(fbi, LCCR0);
+		lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM);
+		complete(&fbi->disable_done);
+	}
+
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+	if (lcsr & LCSR_CMD_INT)
+		complete(&fbi->command_done);
+#endif
+	lcd_writel(fbi, LCSR, lcsr);
+
+#ifdef CONFIG_FB_PXA_OVERLAY
+	{
+		unsigned int lcsr1 = lcd_readl(fbi, LCSR1);
+		if (lcsr1 & LCSR1_BS(1))
+			complete(&fbi->overlay[0].branch_done);
+
+		if (lcsr1 & LCSR1_BS(2))
+			complete(&fbi->overlay[1].branch_done);
+
+		lcd_writel(fbi, LCSR1, lcsr1);
+	}
+#endif
+	return IRQ_HANDLED;
+}
+
+/*
+ * This function must be called from task context only, since it will
+ * sleep when disabling the LCD controller, or if we get two contending
+ * processes trying to alter state.
+ */
+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
+{
+	u_int old_state;
+
+	mutex_lock(&fbi->ctrlr_lock);
+
+	old_state = fbi->state;
+
+	/*
+	 * Hack around fbcon initialisation.
+	 */
+	if (old_state == C_STARTUP && state == C_REENABLE)
+		state = C_ENABLE;
+
+	switch (state) {
+	case C_DISABLE_CLKCHANGE:
+		/*
+		 * Disable controller for clock change.  If the
+		 * controller is already disabled, then do nothing.
+		 */
+		if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
+			fbi->state = state;
+			/* TODO __pxafb_lcd_power(fbi, 0); */
+			pxafb_disable_controller(fbi);
+		}
+		break;
+
+	case C_DISABLE_PM:
+	case C_DISABLE:
+		/*
+		 * Disable controller
+		 */
+		if (old_state != C_DISABLE) {
+			fbi->state = state;
+			__pxafb_backlight_power(fbi, 0);
+			__pxafb_lcd_power(fbi, 0);
+			if (old_state != C_DISABLE_CLKCHANGE)
+				pxafb_disable_controller(fbi);
+		}
+		break;
+
+	case C_ENABLE_CLKCHANGE:
+		/*
+		 * Enable the controller after clock change.  Only
+		 * do this if we were disabled for the clock change.
+		 */
+		if (old_state == C_DISABLE_CLKCHANGE) {
+			fbi->state = C_ENABLE;
+			pxafb_enable_controller(fbi);
+			/* TODO __pxafb_lcd_power(fbi, 1); */
+		}
+		break;
+
+	case C_REENABLE:
+		/*
+		 * Re-enable the controller only if it was already
+		 * enabled.  This is so we reprogram the control
+		 * registers.
+		 */
+		if (old_state == C_ENABLE) {
+			__pxafb_lcd_power(fbi, 0);
+			pxafb_disable_controller(fbi);
+			pxafb_enable_controller(fbi);
+			__pxafb_lcd_power(fbi, 1);
+		}
+		break;
+
+	case C_ENABLE_PM:
+		/*
+		 * Re-enable the controller after PM.  This is not
+		 * perfect - think about the case where we were doing
+		 * a clock change, and we suspended half-way through.
+		 */
+		if (old_state != C_DISABLE_PM)
+			break;
+		/* fall through */
+
+	case C_ENABLE:
+		/*
+		 * Power up the LCD screen, enable controller, and
+		 * turn on the backlight.
+		 */
+		if (old_state != C_ENABLE) {
+			fbi->state = C_ENABLE;
+			pxafb_enable_controller(fbi);
+			__pxafb_lcd_power(fbi, 1);
+			__pxafb_backlight_power(fbi, 1);
+		}
+		break;
+	}
+	mutex_unlock(&fbi->ctrlr_lock);
+}
+
+/*
+ * Our LCD controller task (which is called when we blank or unblank)
+ * via keventd.
+ */
+static void pxafb_task(struct work_struct *work)
+{
+	struct pxafb_info *fbi =
+		container_of(work, struct pxafb_info, task);
+	u_int state = xchg(&fbi->task_state, -1);
+
+	set_ctrlr_state(fbi, state);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/*
+ * CPU clock speed change handler.  We need to adjust the LCD timing
+ * parameters when the CPU clock is adjusted by the power management
+ * subsystem.
+ *
+ * TODO: Determine why f->new != 10*get_lclk_frequency_10khz()
+ */
+static int
+pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct pxafb_info *fbi = TO_INF(nb, freq_transition);
+	/* TODO struct cpufreq_freqs *f = data; */
+	u_int pcd;
+
+	switch (val) {
+	case CPUFREQ_PRECHANGE:
+#ifdef CONFIG_FB_PXA_OVERLAY
+		if (!(fbi->overlay[0].usage || fbi->overlay[1].usage))
+#endif
+			set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
+		break;
+
+	case CPUFREQ_POSTCHANGE:
+		pcd = get_pcd(fbi, fbi->fb.var.pixclock);
+		set_hsync_time(fbi, pcd);
+		fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) |
+				  LCCR3_PixClkDiv(pcd);
+		set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
+		break;
+	}
+	return 0;
+}
+
+static int
+pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct pxafb_info *fbi = TO_INF(nb, freq_policy);
+	struct fb_var_screeninfo *var = &fbi->fb.var;
+	struct cpufreq_policy *policy = data;
+
+	switch (val) {
+	case CPUFREQ_ADJUST:
+	case CPUFREQ_INCOMPATIBLE:
+		pr_debug("min dma period: %d ps, "
+			"new clock %d kHz\n", pxafb_display_dma_period(var),
+			policy->max);
+		/* TODO: fill in min/max values */
+		break;
+	}
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks.  Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int pxafb_suspend(struct device *dev)
+{
+	struct pxafb_info *fbi = dev_get_drvdata(dev);
+
+	set_ctrlr_state(fbi, C_DISABLE_PM);
+	return 0;
+}
+
+static int pxafb_resume(struct device *dev)
+{
+	struct pxafb_info *fbi = dev_get_drvdata(dev);
+
+	set_ctrlr_state(fbi, C_ENABLE_PM);
+	return 0;
+}
+
+static const struct dev_pm_ops pxafb_pm_ops = {
+	.suspend	= pxafb_suspend,
+	.resume		= pxafb_resume,
+};
+#endif
+
+static int pxafb_init_video_memory(struct pxafb_info *fbi)
+{
+	int size = PAGE_ALIGN(fbi->video_mem_size);
+
+	fbi->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
+	if (fbi->video_mem == NULL)
+		return -ENOMEM;
+
+	fbi->video_mem_phys = virt_to_phys(fbi->video_mem);
+	fbi->video_mem_size = size;
+
+	fbi->fb.fix.smem_start	= fbi->video_mem_phys;
+	fbi->fb.fix.smem_len	= fbi->video_mem_size;
+	fbi->fb.screen_base	= fbi->video_mem;
+
+	return fbi->video_mem ? 0 : -ENOMEM;
+}
+
+static void pxafb_decode_mach_info(struct pxafb_info *fbi,
+				   struct pxafb_mach_info *inf)
+{
+	unsigned int lcd_conn = inf->lcd_conn;
+	struct pxafb_mode_info *m;
+	int i;
+
+	fbi->cmap_inverse	= inf->cmap_inverse;
+	fbi->cmap_static	= inf->cmap_static;
+	fbi->lccr4 		= inf->lccr4;
+
+	switch (lcd_conn & LCD_TYPE_MASK) {
+	case LCD_TYPE_MONO_STN:
+		fbi->lccr0 = LCCR0_CMS;
+		break;
+	case LCD_TYPE_MONO_DSTN:
+		fbi->lccr0 = LCCR0_CMS | LCCR0_SDS;
+		break;
+	case LCD_TYPE_COLOR_STN:
+		fbi->lccr0 = 0;
+		break;
+	case LCD_TYPE_COLOR_DSTN:
+		fbi->lccr0 = LCCR0_SDS;
+		break;
+	case LCD_TYPE_COLOR_TFT:
+		fbi->lccr0 = LCCR0_PAS;
+		break;
+	case LCD_TYPE_SMART_PANEL:
+		fbi->lccr0 = LCCR0_LCDT | LCCR0_PAS;
+		break;
+	default:
+		/* fall back to backward compatibility way */
+		fbi->lccr0 = inf->lccr0;
+		fbi->lccr3 = inf->lccr3;
+		goto decode_mode;
+	}
+
+	if (lcd_conn == LCD_MONO_STN_8BPP)
+		fbi->lccr0 |= LCCR0_DPD;
+
+	fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;
+
+	fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
+	fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
+	fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL)  ? LCCR3_PCP : 0;
+
+decode_mode:
+	pxafb_setmode(&fbi->fb.var, &inf->modes[0]);
+
+	/* decide video memory size as follows:
+	 * 1. default to mode of maximum resolution
+	 * 2. allow platform to override
+	 * 3. allow module parameter to override
+	 */
+	for (i = 0, m = &inf->modes[0]; i < inf->num_modes; i++, m++)
+		fbi->video_mem_size = max_t(size_t, fbi->video_mem_size,
+				m->xres * m->yres * m->bpp / 8);
+
+	if (inf->video_mem_size > fbi->video_mem_size)
+		fbi->video_mem_size = inf->video_mem_size;
+
+	if (video_mem_size > fbi->video_mem_size)
+		fbi->video_mem_size = video_mem_size;
+}
+
+static struct pxafb_info *pxafb_init_fbinfo(struct device *dev)
+{
+	struct pxafb_info *fbi;
+	void *addr;
+	struct pxafb_mach_info *inf = dev_get_platdata(dev);
+
+	/* Alloc the pxafb_info and pseudo_palette in one step */
+	fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
+	if (!fbi)
+		return NULL;
+
+	memset(fbi, 0, sizeof(struct pxafb_info));
+	fbi->dev = dev;
+
+	fbi->clk = clk_get(dev, NULL);
+	if (IS_ERR(fbi->clk)) {
+		kfree(fbi);
+		return NULL;
+	}
+
+	strcpy(fbi->fb.fix.id, PXA_NAME);
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.type_aux	= 0;
+	fbi->fb.fix.xpanstep	= 0;
+	fbi->fb.fix.ypanstep	= 1;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.var.nonstd	= 0;
+	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
+	fbi->fb.var.height	= -1;
+	fbi->fb.var.width	= -1;
+	fbi->fb.var.accel_flags	= FB_ACCELF_TEXT;
+	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
+
+	fbi->fb.fbops		= &pxafb_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT;
+	fbi->fb.node		= -1;
+
+	addr = fbi;
+	addr = addr + sizeof(struct pxafb_info);
+	fbi->fb.pseudo_palette	= addr;
+
+	fbi->state		= C_STARTUP;
+	fbi->task_state		= (u_char)-1;
+
+	pxafb_decode_mach_info(fbi, inf);
+
+#ifdef CONFIG_FB_PXA_OVERLAY
+	/* place overlay(s) on top of base */
+	if (pxafb_overlay_supported())
+		fbi->lccr0 |= LCCR0_OUC;
+#endif
+
+	init_waitqueue_head(&fbi->ctrlr_wait);
+	INIT_WORK(&fbi->task, pxafb_task);
+	mutex_init(&fbi->ctrlr_lock);
+	init_completion(&fbi->disable_done);
+
+	return fbi;
+}
+
+#ifdef CONFIG_FB_PXA_PARAMETERS
+static int parse_opt_mode(struct device *dev, const char *this_opt)
+{
+	struct pxafb_mach_info *inf = dev_get_platdata(dev);
+
+	const char *name = this_opt+5;
+	unsigned int namelen = strlen(name);
+	int res_specified = 0, bpp_specified = 0;
+	unsigned int xres = 0, yres = 0, bpp = 0;
+	int yres_specified = 0;
+	int i;
+	for (i = namelen-1; i >= 0; i--) {
+		switch (name[i]) {
+		case '-':
+			namelen = i;
+			if (!bpp_specified && !yres_specified) {
+				bpp = simple_strtoul(&name[i+1], NULL, 0);
+				bpp_specified = 1;
+			} else
+				goto done;
+			break;
+		case 'x':
+			if (!yres_specified) {
+				yres = simple_strtoul(&name[i+1], NULL, 0);
+				yres_specified = 1;
+			} else
+				goto done;
+			break;
+		case '0' ... '9':
+			break;
+		default:
+			goto done;
+		}
+	}
+	if (i < 0 && yres_specified) {
+		xres = simple_strtoul(name, NULL, 0);
+		res_specified = 1;
+	}
+done:
+	if (res_specified) {
+		dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
+		inf->modes[0].xres = xres; inf->modes[0].yres = yres;
+	}
+	if (bpp_specified)
+		switch (bpp) {
+		case 1:
+		case 2:
+		case 4:
+		case 8:
+		case 16:
+			inf->modes[0].bpp = bpp;
+			dev_info(dev, "overriding bit depth: %d\n", bpp);
+			break;
+		default:
+			dev_err(dev, "Depth %d is not valid\n", bpp);
+			return -EINVAL;
+		}
+	return 0;
+}
+
+static int parse_opt(struct device *dev, char *this_opt)
+{
+	struct pxafb_mach_info *inf = dev_get_platdata(dev);
+	struct pxafb_mode_info *mode = &inf->modes[0];
+	char s[64];
+
+	s[0] = '\0';
+
+	if (!strncmp(this_opt, "vmem:", 5)) {
+		video_mem_size = memparse(this_opt + 5, NULL);
+	} else if (!strncmp(this_opt, "mode:", 5)) {
+		return parse_opt_mode(dev, this_opt);
+	} else if (!strncmp(this_opt, "pixclock:", 9)) {
+		mode->pixclock = simple_strtoul(this_opt+9, NULL, 0);
+		sprintf(s, "pixclock: %ld\n", mode->pixclock);
+	} else if (!strncmp(this_opt, "left:", 5)) {
+		mode->left_margin = simple_strtoul(this_opt+5, NULL, 0);
+		sprintf(s, "left: %u\n", mode->left_margin);
+	} else if (!strncmp(this_opt, "right:", 6)) {
+		mode->right_margin = simple_strtoul(this_opt+6, NULL, 0);
+		sprintf(s, "right: %u\n", mode->right_margin);
+	} else if (!strncmp(this_opt, "upper:", 6)) {
+		mode->upper_margin = simple_strtoul(this_opt+6, NULL, 0);
+		sprintf(s, "upper: %u\n", mode->upper_margin);
+	} else if (!strncmp(this_opt, "lower:", 6)) {
+		mode->lower_margin = simple_strtoul(this_opt+6, NULL, 0);
+		sprintf(s, "lower: %u\n", mode->lower_margin);
+	} else if (!strncmp(this_opt, "hsynclen:", 9)) {
+		mode->hsync_len = simple_strtoul(this_opt+9, NULL, 0);
+		sprintf(s, "hsynclen: %u\n", mode->hsync_len);
+	} else if (!strncmp(this_opt, "vsynclen:", 9)) {
+		mode->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
+		sprintf(s, "vsynclen: %u\n", mode->vsync_len);
+	} else if (!strncmp(this_opt, "hsync:", 6)) {
+		if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+			sprintf(s, "hsync: Active Low\n");
+			mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+		} else {
+			sprintf(s, "hsync: Active High\n");
+			mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+		}
+	} else if (!strncmp(this_opt, "vsync:", 6)) {
+		if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+			sprintf(s, "vsync: Active Low\n");
+			mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+		} else {
+			sprintf(s, "vsync: Active High\n");
+			mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+		}
+	} else if (!strncmp(this_opt, "dpc:", 4)) {
+		if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
+			sprintf(s, "double pixel clock: false\n");
+			inf->lccr3 &= ~LCCR3_DPC;
+		} else {
+			sprintf(s, "double pixel clock: true\n");
+			inf->lccr3 |= LCCR3_DPC;
+		}
+	} else if (!strncmp(this_opt, "outputen:", 9)) {
+		if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
+			sprintf(s, "output enable: active low\n");
+			inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
+		} else {
+			sprintf(s, "output enable: active high\n");
+			inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
+		}
+	} else if (!strncmp(this_opt, "pixclockpol:", 12)) {
+		if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
+			sprintf(s, "pixel clock polarity: falling edge\n");
+			inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
+		} else {
+			sprintf(s, "pixel clock polarity: rising edge\n");
+			inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
+		}
+	} else if (!strncmp(this_opt, "color", 5)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
+	} else if (!strncmp(this_opt, "mono", 4)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
+	} else if (!strncmp(this_opt, "active", 6)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
+	} else if (!strncmp(this_opt, "passive", 7)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
+	} else if (!strncmp(this_opt, "single", 6)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
+	} else if (!strncmp(this_opt, "dual", 4)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
+	} else if (!strncmp(this_opt, "4pix", 4)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
+	} else if (!strncmp(this_opt, "8pix", 4)) {
+		inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
+	} else {
+		dev_err(dev, "unknown option: %s\n", this_opt);
+		return -EINVAL;
+	}
+
+	if (s[0] != '\0')
+		dev_info(dev, "override %s", s);
+
+	return 0;
+}
+
+static int pxafb_parse_options(struct device *dev, char *options)
+{
+	char *this_opt;
+	int ret;
+
+	if (!options || !*options)
+		return 0;
+
+	dev_dbg(dev, "options are \"%s\"\n", options ? options : "null");
+
+	/* could be made table driven or similar?... */
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		ret = parse_opt(dev, this_opt);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static char g_options[256] = "";
+
+#ifndef MODULE
+static int __init pxafb_setup_options(void)
+{
+	char *options = NULL;
+
+	if (fb_get_options("pxafb", &options))
+		return -ENODEV;
+
+	if (options)
+		strlcpy(g_options, options, sizeof(g_options));
+
+	return 0;
+}
+#else
+#define pxafb_setup_options()		(0)
+
+module_param_string(options, g_options, sizeof(g_options), 0);
+MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
+#endif
+
+#else
+#define pxafb_parse_options(...)	(0)
+#define pxafb_setup_options()		(0)
+#endif
+
+#ifdef DEBUG_VAR
+/* Check for various illegal bit-combinations. Currently only
+ * a warning is given. */
+static void pxafb_check_options(struct device *dev, struct pxafb_mach_info *inf)
+{
+	if (inf->lcd_conn)
+		return;
+
+	if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
+		dev_warn(dev, "machine LCCR0 setting contains "
+				"illegal bits: %08x\n",
+			inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
+	if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
+		dev_warn(dev, "machine LCCR3 setting contains "
+				"illegal bits: %08x\n",
+			inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
+	if (inf->lccr0 & LCCR0_DPD &&
+	    ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
+	     (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
+	     (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
+		dev_warn(dev, "Double Pixel Data (DPD) mode is "
+				"only valid in passive mono"
+				" single panel mode\n");
+	if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
+	    (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
+		dev_warn(dev, "Dual panel only valid in passive mode\n");
+	if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
+	     (inf->modes->upper_margin || inf->modes->lower_margin))
+		dev_warn(dev, "Upper and lower margins must be 0 in "
+				"passive mode\n");
+}
+#else
+#define pxafb_check_options(...)	do {} while (0)
+#endif
+
+static int pxafb_probe(struct platform_device *dev)
+{
+	struct pxafb_info *fbi;
+	struct pxafb_mach_info *inf;
+	struct resource *r;
+	int irq, ret;
+
+	dev_dbg(&dev->dev, "pxafb_probe\n");
+
+	inf = dev_get_platdata(&dev->dev);
+	ret = -ENOMEM;
+	fbi = NULL;
+	if (!inf)
+		goto failed;
+
+	ret = pxafb_parse_options(&dev->dev, g_options);
+	if (ret < 0)
+		goto failed;
+
+	pxafb_check_options(&dev->dev, inf);
+
+	dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
+			inf->modes->xres,
+			inf->modes->yres,
+			inf->modes->bpp);
+	if (inf->modes->xres == 0 ||
+	    inf->modes->yres == 0 ||
+	    inf->modes->bpp == 0) {
+		dev_err(&dev->dev, "Invalid resolution or bit depth\n");
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	fbi = pxafb_init_fbinfo(&dev->dev);
+	if (!fbi) {
+		/* only reason for pxafb_init_fbinfo to fail is kmalloc */
+		dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	if (cpu_is_pxa3xx() && inf->acceleration_enabled)
+		fbi->fb.fix.accel = FB_ACCEL_PXA3XX;
+
+	fbi->backlight_power = inf->pxafb_backlight_power;
+	fbi->lcd_power = inf->pxafb_lcd_power;
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&dev->dev, "no I/O memory resource defined\n");
+		ret = -ENODEV;
+		goto failed_fbi;
+	}
+
+	r = request_mem_region(r->start, resource_size(r), dev->name);
+	if (r == NULL) {
+		dev_err(&dev->dev, "failed to request I/O memory\n");
+		ret = -EBUSY;
+		goto failed_fbi;
+	}
+
+	fbi->mmio_base = ioremap(r->start, resource_size(r));
+	if (fbi->mmio_base == NULL) {
+		dev_err(&dev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto failed_free_res;
+	}
+
+	fbi->dma_buff_size = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
+	fbi->dma_buff = dma_alloc_coherent(fbi->dev, fbi->dma_buff_size,
+				&fbi->dma_buff_phys, GFP_KERNEL);
+	if (fbi->dma_buff == NULL) {
+		dev_err(&dev->dev, "failed to allocate memory for DMA\n");
+		ret = -ENOMEM;
+		goto failed_free_io;
+	}
+
+	ret = pxafb_init_video_memory(fbi);
+	if (ret) {
+		dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
+		ret = -ENOMEM;
+		goto failed_free_dma;
+	}
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "no IRQ defined\n");
+		ret = -ENODEV;
+		goto failed_free_mem;
+	}
+
+	ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi);
+	if (ret) {
+		dev_err(&dev->dev, "request_irq failed: %d\n", ret);
+		ret = -EBUSY;
+		goto failed_free_mem;
+	}
+
+	ret = pxafb_smart_init(fbi);
+	if (ret) {
+		dev_err(&dev->dev, "failed to initialize smartpanel\n");
+		goto failed_free_irq;
+	}
+
+	/*
+	 * This makes sure that our colour bitfield
+	 * descriptors are correctly initialised.
+	 */
+	ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);
+	if (ret) {
+		dev_err(&dev->dev, "failed to get suitable mode\n");
+		goto failed_free_irq;
+	}
+
+	ret = pxafb_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&dev->dev, "Failed to set parameters\n");
+		goto failed_free_irq;
+	}
+
+	platform_set_drvdata(dev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0) {
+		dev_err(&dev->dev,
+			"Failed to register framebuffer device: %d\n", ret);
+		goto failed_free_cmap;
+	}
+
+	pxafb_overlay_init(fbi);
+
+#ifdef CONFIG_CPU_FREQ
+	fbi->freq_transition.notifier_call = pxafb_freq_transition;
+	fbi->freq_policy.notifier_call = pxafb_freq_policy;
+	cpufreq_register_notifier(&fbi->freq_transition,
+				CPUFREQ_TRANSITION_NOTIFIER);
+	cpufreq_register_notifier(&fbi->freq_policy,
+				CPUFREQ_POLICY_NOTIFIER);
+#endif
+
+	/*
+	 * Ok, now enable the LCD controller
+	 */
+	set_ctrlr_state(fbi, C_ENABLE);
+
+	return 0;
+
+failed_free_cmap:
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_irq:
+	free_irq(irq, fbi);
+failed_free_mem:
+	free_pages_exact(fbi->video_mem, fbi->video_mem_size);
+failed_free_dma:
+	dma_free_coherent(&dev->dev, fbi->dma_buff_size,
+			fbi->dma_buff, fbi->dma_buff_phys);
+failed_free_io:
+	iounmap(fbi->mmio_base);
+failed_free_res:
+	release_mem_region(r->start, resource_size(r));
+failed_fbi:
+	clk_put(fbi->clk);
+	kfree(fbi);
+failed:
+	return ret;
+}
+
+static int pxafb_remove(struct platform_device *dev)
+{
+	struct pxafb_info *fbi = platform_get_drvdata(dev);
+	struct resource *r;
+	int irq;
+	struct fb_info *info;
+
+	if (!fbi)
+		return 0;
+
+	info = &fbi->fb;
+
+	pxafb_overlay_exit(fbi);
+	unregister_framebuffer(info);
+
+	pxafb_disable_controller(fbi);
+
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+
+	irq = platform_get_irq(dev, 0);
+	free_irq(irq, fbi);
+
+	free_pages_exact(fbi->video_mem, fbi->video_mem_size);
+
+	dma_free_writecombine(&dev->dev, fbi->dma_buff_size,
+			fbi->dma_buff, fbi->dma_buff_phys);
+
+	iounmap(fbi->mmio_base);
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	clk_put(fbi->clk);
+	kfree(fbi);
+
+	return 0;
+}
+
+static struct platform_driver pxafb_driver = {
+	.probe		= pxafb_probe,
+	.remove 	= pxafb_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "pxa2xx-fb",
+#ifdef CONFIG_PM
+		.pm	= &pxafb_pm_ops,
+#endif
+	},
+};
+
+static int __init pxafb_init(void)
+{
+	if (pxafb_setup_options())
+		return -EINVAL;
+
+	return platform_driver_register(&pxafb_driver);
+}
+
+static void __exit pxafb_exit(void)
+{
+	platform_driver_unregister(&pxafb_driver);
+}
+
+module_init(pxafb_init);
+module_exit(pxafb_exit);
+
+MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/pxafb.h b/drivers/video/fbdev/pxafb.h
new file mode 100644
index 000000000000..26ba9fa3f737
--- /dev/null
+++ b/drivers/video/fbdev/pxafb.h
@@ -0,0 +1,200 @@
+#ifndef __PXAFB_H__
+#define __PXAFB_H__
+
+/*
+ * linux/drivers/video/pxafb.h
+ *    -- Intel PXA250/210 LCD Controller Frame Buffer Device
+ *
+ *  Copyright (C) 1999 Eric A. Thomas.
+ *  Copyright (C) 2004 Jean-Frederic Clere.
+ *  Copyright (C) 2004 Ian Campbell.
+ *  Copyright (C) 2004 Jeff Lackey.
+ *   Based on sa1100fb.c Copyright (C) 1999 Eric A. Thomas
+ *  which in turn is
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ *  2001-08-03: Cliff Brake <cbrake@acclent.com>
+ *	 - ported SA1100 code to PXA
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/* PXA LCD DMA descriptor */
+struct pxafb_dma_descriptor {
+	unsigned int fdadr;
+	unsigned int fsadr;
+	unsigned int fidr;
+	unsigned int ldcmd;
+};
+
+enum {
+	PAL_NONE	= -1,
+	PAL_BASE	= 0,
+	PAL_OV1		= 1,
+	PAL_OV2		= 2,
+	PAL_MAX,
+};
+
+enum {
+	DMA_BASE	= 0,
+	DMA_UPPER	= 0,
+	DMA_LOWER	= 1,
+	DMA_OV1		= 1,
+	DMA_OV2_Y	= 2,
+	DMA_OV2_Cb	= 3,
+	DMA_OV2_Cr	= 4,
+	DMA_CURSOR	= 5,
+	DMA_CMD		= 6,
+	DMA_MAX,
+};
+
+/* maximum palette size - 256 entries, each 4 bytes long */
+#define PALETTE_SIZE	(256 * 4)
+#define CMD_BUFF_SIZE	(1024 * 50)
+
+/* NOTE: the palette and frame dma descriptors are doubled to allow
+ * the 2nd set for branch settings (FBRx)
+ */
+struct pxafb_dma_buff {
+	unsigned char palette[PAL_MAX * PALETTE_SIZE];
+	uint16_t cmd_buff[CMD_BUFF_SIZE];
+	struct pxafb_dma_descriptor pal_desc[PAL_MAX * 2];
+	struct pxafb_dma_descriptor dma_desc[DMA_MAX * 2];
+};
+
+enum {
+	OVERLAY1,
+	OVERLAY2,
+};
+
+enum {
+	OVERLAY_FORMAT_RGB = 0,
+	OVERLAY_FORMAT_YUV444_PACKED,
+	OVERLAY_FORMAT_YUV444_PLANAR,
+	OVERLAY_FORMAT_YUV422_PLANAR,
+	OVERLAY_FORMAT_YUV420_PLANAR,
+};
+
+#define NONSTD_TO_XPOS(x)	(((x) >> 0)  & 0x3ff)
+#define NONSTD_TO_YPOS(x)	(((x) >> 10) & 0x3ff)
+#define NONSTD_TO_PFOR(x)	(((x) >> 20) & 0x7)
+
+struct pxafb_layer;
+
+struct pxafb_layer_ops {
+	void (*enable)(struct pxafb_layer *);
+	void (*disable)(struct pxafb_layer *);
+	void (*setup)(struct pxafb_layer *);
+};
+
+struct pxafb_layer {
+	struct fb_info		fb;
+	int			id;
+	int			registered;
+	uint32_t		usage;
+	uint32_t		control[2];
+
+	struct pxafb_layer_ops	*ops;
+
+	void __iomem		*video_mem;
+	unsigned long		video_mem_phys;
+	size_t			video_mem_size;
+	struct completion	branch_done;
+
+	struct pxafb_info	*fbi;
+};
+
+struct pxafb_info {
+	struct fb_info		fb;
+	struct device		*dev;
+	struct clk		*clk;
+
+	void __iomem		*mmio_base;
+
+	struct pxafb_dma_buff	*dma_buff;
+	size_t			dma_buff_size;
+	dma_addr_t		dma_buff_phys;
+	dma_addr_t		fdadr[DMA_MAX * 2];
+
+	void __iomem		*video_mem;	/* virtual address of frame buffer */
+	unsigned long		video_mem_phys;	/* physical address of frame buffer */
+	size_t			video_mem_size;	/* size of the frame buffer */
+	u16 *			palette_cpu;	/* virtual address of palette memory */
+	u_int			palette_size;
+
+	u_int			lccr0;
+	u_int			lccr3;
+	u_int			lccr4;
+	u_int			cmap_inverse:1,
+				cmap_static:1,
+				unused:30;
+
+	u_int			reg_lccr0;
+	u_int			reg_lccr1;
+	u_int			reg_lccr2;
+	u_int			reg_lccr3;
+	u_int			reg_lccr4;
+	u_int			reg_cmdcr;
+
+	unsigned long	hsync_time;
+
+	volatile u_char		state;
+	volatile u_char		task_state;
+	struct mutex		ctrlr_lock;
+	wait_queue_head_t	ctrlr_wait;
+	struct work_struct	task;
+
+	struct completion	disable_done;
+
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+	uint16_t		*smart_cmds;
+	size_t			n_smart_cmds;
+	struct completion	command_done;
+	struct completion	refresh_done;
+	struct task_struct	*smart_thread;
+#endif
+
+#ifdef CONFIG_FB_PXA_OVERLAY
+	struct pxafb_layer	overlay[2];
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+	struct notifier_block	freq_policy;
+#endif
+
+	void (*lcd_power)(int, struct fb_var_screeninfo *);
+	void (*backlight_power)(int);
+};
+
+#define TO_INF(ptr,member) container_of(ptr,struct pxafb_info,member)
+
+/*
+ * These are the actions for set_ctrlr_state
+ */
+#define C_DISABLE		(0)
+#define C_ENABLE		(1)
+#define C_DISABLE_CLKCHANGE	(2)
+#define C_ENABLE_CLKCHANGE	(3)
+#define C_REENABLE		(4)
+#define C_DISABLE_PM		(5)
+#define C_ENABLE_PM		(6)
+#define C_STARTUP		(7)
+
+#define PXA_NAME	"PXA"
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES	64
+#define MIN_YRES	64
+
+/* maximum X and Y resolutions - note these are limits from the register
+ * bits length instead of the real ones
+ */
+#define MAX_XRES	1024
+#define MAX_YRES	1024
+
+#endif /* __PXAFB_H__ */
diff --git a/drivers/video/fbdev/q40fb.c b/drivers/video/fbdev/q40fb.c
new file mode 100644
index 000000000000..7487f76f6275
--- /dev/null
+++ b/drivers/video/fbdev/q40fb.c
@@ -0,0 +1,155 @@
+/*
+ * linux/drivers/video/q40fb.c -- Q40 frame buffer device
+ *
+ * Copyright (C) 2001
+ *
+ *      Richard Zidlicky <rz@linux-m68k.org>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/uaccess.h>
+#include <asm/setup.h>
+#include <asm/q40_master.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#define Q40_PHYS_SCREEN_ADDR 0xFE800000
+
+static struct fb_fix_screeninfo q40fb_fix = {
+	.id		= "Q40",
+	.smem_len	= 1024*1024,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.line_length	= 1024*2,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo q40fb_var = {
+	.xres		= 1024,
+	.yres		= 512,
+	.xres_virtual	= 1024,
+	.yres_virtual	= 512,
+	.bits_per_pixel	= 16,
+    	.red		= {6, 5, 0},
+	.green		= {11, 5, 0},
+	.blue		= {0, 6, 0},
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= 230,
+	.width		= 300,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+    /*
+     *  Set a single color register. The values supplied have a 16 bit
+     *  magnitude.
+     *  Return != 0 for invalid regno.
+     */
+
+    if (regno > 255)
+	    return 1;
+    red>>=11;
+    green>>=11;
+    blue>>=10;
+
+    if (regno < 16) {
+	((u32 *)info->pseudo_palette)[regno] = ((red & 31) <<6) |
+					       ((green & 31) << 11) |
+					       (blue & 63);
+    }
+    return 0;
+}
+
+static struct fb_ops q40fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= q40fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int q40fb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+
+	if (!MACH_IS_Q40)
+		return -ENXIO;
+
+	/* mapped in q40/config.c */
+	q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR;
+
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	info->var = q40fb_var;
+	info->fix = q40fb_fix;
+	info->fbops = &q40fb_ops;
+	info->flags = FBINFO_DEFAULT;  /* not as module for now */
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->screen_base = (char *) q40fb_fix.smem_start;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		framebuffer_release(info);
+		return -ENOMEM;
+	}
+
+	master_outb(3, DISPLAY_CONTROL_REG);
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "Unable to register Q40 frame buffer\n");
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+		return -EINVAL;
+	}
+
+	fb_info(info, "Q40 frame buffer alive and kicking !\n");
+	return 0;
+}
+
+static struct platform_driver q40fb_driver = {
+	.probe	= q40fb_probe,
+	.driver	= {
+		.name	= "q40fb",
+	},
+};
+
+static struct platform_device q40fb_device = {
+	.name	= "q40fb",
+};
+
+int __init q40fb_init(void)
+{
+	int ret = 0;
+
+	if (fb_get_options("q40fb", NULL))
+		return -ENODEV;
+
+	ret = platform_driver_register(&q40fb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&q40fb_device);
+		if (ret)
+			platform_driver_unregister(&q40fb_driver);
+	}
+	return ret;
+}
+
+module_init(q40fb_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/riva/Makefile b/drivers/video/fbdev/riva/Makefile
new file mode 100644
index 000000000000..8898c9915b02
--- /dev/null
+++ b/drivers/video/fbdev/riva/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Riva framebuffer driver
+#
+
+obj-$(CONFIG_FB_RIVA)     += rivafb.o
+
+rivafb-objs               := fbdev.o riva_hw.o nv_driver.o
+
+ifdef CONFIG_FB_RIVA_I2C
+	rivafb-objs       += rivafb-i2c.o
+endif
diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c
new file mode 100644
index 000000000000..8a8d7f060784
--- /dev/null
+++ b/drivers/video/fbdev/riva/fbdev.c
@@ -0,0 +1,2230 @@
+/*
+ * linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
+ *
+ * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
+ *
+ * Copyright 1999-2000 Jeff Garzik
+ *
+ * Contributors:
+ *
+ *	Ani Joshi:  Lots of debugging and cleanup work, really helped
+ *	get the driver going
+ *
+ *	Ferenc Bakonyi:  Bug fixes, cleanup, modularization
+ *
+ *	Jindrich Makovicka:  Accel code help, hw cursor, mtrr
+ *
+ *	Paul Richards:  Bug fixes, updates
+ *
+ * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
+ * Includes riva_hw.c from nVidia, see copyright below.
+ * KGI code provided the basis for state storage, init, and mode switching.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * Known bugs and issues:
+ *	restoring text mode fails
+ *	doublescan modes are broken
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/backlight.h>
+#include <linux/bitrev.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/machdep.h>
+#include <asm/backlight.h>
+#endif
+
+#include "rivafb.h"
+#include "nvreg.h"
+
+/* version number of this driver */
+#define RIVAFB_VERSION "0.9.5b"
+
+/* ------------------------------------------------------------------------- *
+ *
+ * various helpful macros and constants
+ *
+ * ------------------------------------------------------------------------- */
+#ifdef CONFIG_FB_RIVA_DEBUG
+#define NVTRACE          printk
+#else
+#define NVTRACE          if(0) printk
+#endif
+
+#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __func__)
+#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __func__)
+
+#ifdef CONFIG_FB_RIVA_DEBUG
+#define assert(expr) \
+	if(!(expr)) { \
+	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+	#expr,__FILE__,__func__,__LINE__); \
+	BUG(); \
+	}
+#else
+#define assert(expr)
+#endif
+
+#define PFX "rivafb: "
+
+/* macro that allows you to set overflow bits */
+#define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
+#define SetBit(n)		(1<<(n))
+#define Set8Bits(value)		((value)&0xff)
+
+/* HW cursor parameters */
+#define MAX_CURS		32
+
+/* ------------------------------------------------------------------------- *
+ *
+ * prototypes
+ *
+ * ------------------------------------------------------------------------- */
+
+static int rivafb_blank(int blank, struct fb_info *info);
+
+/* ------------------------------------------------------------------------- *
+ *
+ * card identification
+ *
+ * ------------------------------------------------------------------------- */
+
+static struct pci_device_id rivafb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	// NF2/IGP version, GeForce 4 MX, NV18
+	{ PCI_VENDOR_ID_NVIDIA, 0x01f0,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
+
+/* ------------------------------------------------------------------------- *
+ *
+ * global variables
+ *
+ * ------------------------------------------------------------------------- */
+
+/* command line data, set in rivafb_setup() */
+static int flatpanel = -1; /* Autodetect later */
+static int forceCRTC = -1;
+static bool noaccel  = 0;
+#ifdef CONFIG_MTRR
+static bool nomtrr = 0;
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight = 1;
+#else
+static int backlight = 0;
+#endif
+
+static char *mode_option = NULL;
+static bool strictmode       = 0;
+
+static struct fb_fix_screeninfo rivafb_fix = {
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.xpanstep	= 1,
+	.ypanstep	= 1,
+};
+
+static struct fb_var_screeninfo rivafb_default_var = {
+	.xres		= 640,
+	.yres		= 480,
+	.xres_virtual	= 640,
+	.yres_virtual	= 480,
+	.bits_per_pixel	= 8,
+	.red		= {0, 8, 0},
+	.green		= {0, 8, 0},
+	.blue		= {0, 8, 0},
+	.transp		= {0, 0, 0},
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.pixclock	= 39721,
+	.left_margin	= 40,
+	.right_margin	= 24,
+	.upper_margin	= 32,
+	.lower_margin	= 11,
+	.hsync_len	= 96,
+	.vsync_len	= 2,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
+/* from GGI */
+static const struct riva_regs reg_template = {
+	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* ATTR */
+	 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	 0x41, 0x01, 0x0F, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* CRT  */
+	 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3,	/* 0x10 */
+	 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x20 */
+	 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x30 */
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00,							/* 0x40 */
+	 },
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,	/* GRA  */
+	 0xFF},
+	{0x03, 0x01, 0x0F, 0x00, 0x0E},				/* SEQ  */
+	0xEB							/* MISC */
+};
+
+/*
+ * Backlight control
+ */
+#ifdef CONFIG_FB_RIVA_BACKLIGHT
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
+#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
+
+static int riva_bl_get_level_brightness(struct riva_par *par,
+		int level)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	int nlevel;
+
+	/* Get and convert the value */
+	/* No locking on bl_curve since accessing a single value */
+	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
+
+	if (nlevel < 0)
+		nlevel = 0;
+	else if (nlevel < MIN_LEVEL)
+		nlevel = MIN_LEVEL;
+	else if (nlevel > MAX_LEVEL)
+		nlevel = MAX_LEVEL;
+
+	return nlevel;
+}
+
+static int riva_bl_update_status(struct backlight_device *bd)
+{
+	struct riva_par *par = bl_get_data(bd);
+	U032 tmp_pcrt, tmp_pmc;
+	int level;
+
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props.brightness;
+
+	tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF;
+	tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC;
+	if(level > 0) {
+		tmp_pcrt |= 0x1;
+		tmp_pmc |= (1 << 31); /* backlight bit */
+		tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
+	}
+	NV_WR32(par->riva.PCRTC0, 0x081C, tmp_pcrt);
+	NV_WR32(par->riva.PMC, 0x10F0, tmp_pmc);
+
+	return 0;
+}
+
+static int riva_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops riva_bl_ops = {
+	.get_brightness = riva_bl_get_brightness,
+	.update_status	= riva_bl_update_status,
+};
+
+static void riva_bl_init(struct riva_par *par)
+{
+	struct backlight_properties props;
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd;
+	char name[12];
+
+	if (!par->FlatPanel)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!machine_is(powermac) ||
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	snprintf(name, sizeof(name), "rivabl%d", info->node);
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
+				       &props);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk(KERN_WARNING "riva: Backlight registration failed\n");
+		goto error;
+	}
+
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+		MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,
+		FB_BACKLIGHT_MAX);
+
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	printk("riva: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+static void riva_bl_exit(struct fb_info *info)
+{
+	struct backlight_device *bd = info->bl_dev;
+
+	backlight_device_unregister(bd);
+	printk("riva: Backlight unloaded\n");
+}
+#else
+static inline void riva_bl_init(struct riva_par *par) {}
+static inline void riva_bl_exit(struct fb_info *info) {}
+#endif /* CONFIG_FB_RIVA_BACKLIGHT */
+
+/* ------------------------------------------------------------------------- *
+ *
+ * MMIO access macros
+ *
+ * ------------------------------------------------------------------------- */
+
+static inline void CRTCout(struct riva_par *par, unsigned char index,
+			   unsigned char val)
+{
+	VGA_WR08(par->riva.PCIO, 0x3d4, index);
+	VGA_WR08(par->riva.PCIO, 0x3d5, val);
+}
+
+static inline unsigned char CRTCin(struct riva_par *par,
+				   unsigned char index)
+{
+	VGA_WR08(par->riva.PCIO, 0x3d4, index);
+	return (VGA_RD08(par->riva.PCIO, 0x3d5));
+}
+
+static inline void GRAout(struct riva_par *par, unsigned char index,
+			  unsigned char val)
+{
+	VGA_WR08(par->riva.PVIO, 0x3ce, index);
+	VGA_WR08(par->riva.PVIO, 0x3cf, val);
+}
+
+static inline unsigned char GRAin(struct riva_par *par,
+				  unsigned char index)
+{
+	VGA_WR08(par->riva.PVIO, 0x3ce, index);
+	return (VGA_RD08(par->riva.PVIO, 0x3cf));
+}
+
+static inline void SEQout(struct riva_par *par, unsigned char index,
+			  unsigned char val)
+{
+	VGA_WR08(par->riva.PVIO, 0x3c4, index);
+	VGA_WR08(par->riva.PVIO, 0x3c5, val);
+}
+
+static inline unsigned char SEQin(struct riva_par *par,
+				  unsigned char index)
+{
+	VGA_WR08(par->riva.PVIO, 0x3c4, index);
+	return (VGA_RD08(par->riva.PVIO, 0x3c5));
+}
+
+static inline void ATTRout(struct riva_par *par, unsigned char index,
+			   unsigned char val)
+{
+	VGA_WR08(par->riva.PCIO, 0x3c0, index);
+	VGA_WR08(par->riva.PCIO, 0x3c0, val);
+}
+
+static inline unsigned char ATTRin(struct riva_par *par,
+				   unsigned char index)
+{
+	VGA_WR08(par->riva.PCIO, 0x3c0, index);
+	return (VGA_RD08(par->riva.PCIO, 0x3c1));
+}
+
+static inline void MISCout(struct riva_par *par, unsigned char val)
+{
+	VGA_WR08(par->riva.PVIO, 0x3c2, val);
+}
+
+static inline unsigned char MISCin(struct riva_par *par)
+{
+	return (VGA_RD08(par->riva.PVIO, 0x3cc));
+}
+
+static inline void reverse_order(u32 *l)
+{
+	u8 *a = (u8 *)l;
+	a[0] = bitrev8(a[0]);
+	a[1] = bitrev8(a[1]);
+	a[2] = bitrev8(a[2]);
+	a[3] = bitrev8(a[3]);
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * cursor stuff
+ *
+ * ------------------------------------------------------------------------- */
+
+/**
+ * rivafb_load_cursor_image - load cursor image to hardware
+ * @data: address to monochrome bitmap (1 = foreground color, 0 = background)
+ * @par:  pointer to private data
+ * @w:    width of cursor image in pixels
+ * @h:    height of cursor image in scanlines
+ * @bg:   background color (ARGB1555) - alpha bit determines opacity
+ * @fg:   foreground color (ARGB1555)
+ *
+ * DESCRIPTiON:
+ * Loads cursor image based on a monochrome source and mask bitmap.  The
+ * image bits determines the color of the pixel, 0 for background, 1 for
+ * foreground.  Only the affected region (as determined by @w and @h 
+ * parameters) will be updated.
+ *
+ * CALLED FROM:
+ * rivafb_cursor()
+ */
+static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
+				     u16 bg, u16 fg, u32 w, u32 h)
+{
+	int i, j, k = 0;
+	u32 b, tmp;
+	u32 *data = (u32 *)data8;
+	bg = le16_to_cpu(bg);
+	fg = le16_to_cpu(fg);
+
+	w = (w + 1) & ~1;
+
+	for (i = 0; i < h; i++) {
+		b = *data++;
+		reverse_order(&b);
+		
+		for (j = 0; j < w/2; j++) {
+			tmp = 0;
+#if defined (__BIG_ENDIAN)
+			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
+			b <<= 1;
+			tmp |= (b & (1 << 31)) ? fg : bg;
+			b <<= 1;
+#else
+			tmp = (b & 1) ? fg : bg;
+			b >>= 1;
+			tmp |= (b & 1) ? fg << 16 : bg << 16;
+			b >>= 1;
+#endif
+			writel(tmp, &par->riva.CURSOR[k++]);
+		}
+		k += (MAX_CURS - w)/2;
+	}
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * general utility functions
+ *
+ * ------------------------------------------------------------------------- */
+
+/**
+ * riva_wclut - set CLUT entry
+ * @chip: pointer to RIVA_HW_INST object
+ * @regnum: register number
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ *
+ * DESCRIPTION:
+ * Sets color register @regnum.
+ *
+ * CALLED FROM:
+ * rivafb_setcolreg()
+ */
+static void riva_wclut(RIVA_HW_INST *chip,
+		       unsigned char regnum, unsigned char red,
+		       unsigned char green, unsigned char blue)
+{
+	VGA_WR08(chip->PDIO, 0x3c8, regnum);
+	VGA_WR08(chip->PDIO, 0x3c9, red);
+	VGA_WR08(chip->PDIO, 0x3c9, green);
+	VGA_WR08(chip->PDIO, 0x3c9, blue);
+}
+
+/**
+ * riva_rclut - read fromCLUT register
+ * @chip: pointer to RIVA_HW_INST object
+ * @regnum: register number
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ *
+ * DESCRIPTION:
+ * Reads red, green, and blue from color register @regnum.
+ *
+ * CALLED FROM:
+ * rivafb_setcolreg()
+ */
+static void riva_rclut(RIVA_HW_INST *chip,
+		       unsigned char regnum, unsigned char *red,
+		       unsigned char *green, unsigned char *blue)
+{
+	
+	VGA_WR08(chip->PDIO, 0x3c7, regnum);
+	*red = VGA_RD08(chip->PDIO, 0x3c9);
+	*green = VGA_RD08(chip->PDIO, 0x3c9);
+	*blue = VGA_RD08(chip->PDIO, 0x3c9);
+}
+
+/**
+ * riva_save_state - saves current chip state
+ * @par: pointer to riva_par object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Saves current chip state to @regs.
+ *
+ * CALLED FROM:
+ * rivafb_probe()
+ */
+/* from GGI */
+static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
+{
+	int i;
+
+	NVTRACE_ENTER();
+	par->riva.LockUnlock(&par->riva, 0);
+
+	par->riva.UnloadStateExt(&par->riva, &regs->ext);
+
+	regs->misc_output = MISCin(par);
+
+	for (i = 0; i < NUM_CRT_REGS; i++)
+		regs->crtc[i] = CRTCin(par, i);
+
+	for (i = 0; i < NUM_ATC_REGS; i++)
+		regs->attr[i] = ATTRin(par, i);
+
+	for (i = 0; i < NUM_GRC_REGS; i++)
+		regs->gra[i] = GRAin(par, i);
+
+	for (i = 0; i < NUM_SEQ_REGS; i++)
+		regs->seq[i] = SEQin(par, i);
+	NVTRACE_LEAVE();
+}
+
+/**
+ * riva_load_state - loads current chip state
+ * @par: pointer to riva_par object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Loads chip state from @regs.
+ *
+ * CALLED FROM:
+ * riva_load_video_mode()
+ * rivafb_probe()
+ * rivafb_remove()
+ */
+/* from GGI */
+static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
+{
+	RIVA_HW_STATE *state = &regs->ext;
+	int i;
+
+	NVTRACE_ENTER();
+	CRTCout(par, 0x11, 0x00);
+
+	par->riva.LockUnlock(&par->riva, 0);
+
+	par->riva.LoadStateExt(&par->riva, state);
+
+	MISCout(par, regs->misc_output);
+
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		switch (i) {
+		case 0x19:
+		case 0x20 ... 0x40:
+			break;
+		default:
+			CRTCout(par, i, regs->crtc[i]);
+		}
+	}
+
+	for (i = 0; i < NUM_ATC_REGS; i++)
+		ATTRout(par, i, regs->attr[i]);
+
+	for (i = 0; i < NUM_GRC_REGS; i++)
+		GRAout(par, i, regs->gra[i]);
+
+	for (i = 0; i < NUM_SEQ_REGS; i++)
+		SEQout(par, i, regs->seq[i]);
+	NVTRACE_LEAVE();
+}
+
+/**
+ * riva_load_video_mode - calculate timings
+ * @info: pointer to fb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Calculate some timings and then send em off to riva_load_state().
+ *
+ * CALLED FROM:
+ * rivafb_set_par()
+ */
+static int riva_load_video_mode(struct fb_info *info)
+{
+	int bpp, width, hDisplaySize, hDisplay, hStart,
+	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
+	int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
+	int rc;
+	struct riva_par *par = info->par;
+	struct riva_regs newmode;
+	
+	NVTRACE_ENTER();
+	/* time to calculate */
+	rivafb_blank(FB_BLANK_NORMAL, info);
+
+	bpp = info->var.bits_per_pixel;
+	if (bpp == 16 && info->var.green.length == 5)
+		bpp = 15;
+	width = info->var.xres_virtual;
+	hDisplaySize = info->var.xres;
+	hDisplay = (hDisplaySize / 8) - 1;
+	hStart = (hDisplaySize + info->var.right_margin) / 8 - 1;
+	hEnd = (hDisplaySize + info->var.right_margin +
+		info->var.hsync_len) / 8 - 1;
+	hTotal = (hDisplaySize + info->var.right_margin +
+		  info->var.hsync_len + info->var.left_margin) / 8 - 5;
+	hBlankStart = hDisplay;
+	hBlankEnd = hTotal + 4;
+
+	height = info->var.yres_virtual;
+	vDisplay = info->var.yres - 1;
+	vStart = info->var.yres + info->var.lower_margin - 1;
+	vEnd = info->var.yres + info->var.lower_margin +
+	       info->var.vsync_len - 1;
+	vTotal = info->var.yres + info->var.lower_margin +
+		 info->var.vsync_len + info->var.upper_margin + 2;
+	vBlankStart = vDisplay;
+	vBlankEnd = vTotal + 1;
+	dotClock = 1000000000 / info->var.pixclock;
+
+	memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
+
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+		vTotal |= 1;
+
+	if (par->FlatPanel) {
+		vStart = vTotal - 3;
+		vEnd = vTotal - 2;
+		vBlankStart = vStart;
+		hStart = hTotal - 3;
+		hEnd = hTotal - 2;
+		hBlankEnd = hTotal + 4;
+	}
+
+	newmode.crtc[0x0] = Set8Bits (hTotal); 
+	newmode.crtc[0x1] = Set8Bits (hDisplay);
+	newmode.crtc[0x2] = Set8Bits (hBlankStart);
+	newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7);
+	newmode.crtc[0x4] = Set8Bits (hStart);
+	newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7)
+		| SetBitField (hEnd, 4: 0, 4:0);
+	newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
+	newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
+		| SetBitField (vDisplay, 8: 8, 1:1)
+		| SetBitField (vStart, 8: 8, 2:2)
+		| SetBitField (vBlankStart, 8: 8, 3:3)
+		| SetBit (4)
+		| SetBitField (vTotal, 9: 9, 5:5)
+		| SetBitField (vDisplay, 9: 9, 6:6)
+		| SetBitField (vStart, 9: 9, 7:7);
+	newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5)
+		| SetBit (6);
+	newmode.crtc[0x10] = Set8Bits (vStart);
+	newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
+		| SetBit (5);
+	newmode.crtc[0x12] = Set8Bits (vDisplay);
+	newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8);
+	newmode.crtc[0x15] = Set8Bits (vBlankStart);
+	newmode.crtc[0x16] = Set8Bits (vBlankEnd);
+
+	newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4)
+		| SetBitField(vBlankStart,10:10,3:3)
+		| SetBitField(vStart,10:10,2:2)
+		| SetBitField(vDisplay,10:10,1:1)
+		| SetBitField(vTotal,10:10,0:0);
+	newmode.ext.horiz  = SetBitField(hTotal,8:8,0:0) 
+		| SetBitField(hDisplay,8:8,1:1)
+		| SetBitField(hBlankStart,8:8,2:2)
+		| SetBitField(hStart,8:8,3:3);
+	newmode.ext.extra  = SetBitField(vTotal,11:11,0:0)
+		| SetBitField(vDisplay,11:11,2:2)
+		| SetBitField(vStart,11:11,4:4)
+		| SetBitField(vBlankStart,11:11,6:6); 
+
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		int tmp = (hTotal >> 1) & ~1;
+		newmode.ext.interlace = Set8Bits(tmp);
+		newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4);
+	} else 
+		newmode.ext.interlace = 0xff; /* interlace off */
+
+	if (par->riva.Architecture >= NV_ARCH_10)
+		par->riva.CURSOR = (U032 __iomem *)(info->screen_base + par->riva.CursorStart);
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		newmode.misc_output &= ~0x40;
+	else
+		newmode.misc_output |= 0x40;
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		newmode.misc_output &= ~0x80;
+	else
+		newmode.misc_output |= 0x80;	
+
+	rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width,
+			  hDisplaySize, height, dotClock);
+	if (rc)
+		goto out;
+
+	newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) &
+		0xfff000ff;
+	if (par->FlatPanel == 1) {
+		newmode.ext.pixel |= (1 << 7);
+		newmode.ext.scale |= (1 << 8);
+	}
+	if (par->SecondCRTC) {
+		newmode.ext.head  = NV_RD32(par->riva.PCRTC0, 0x00000860) &
+			~0x00001000;
+		newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) |
+			0x00001000;
+		newmode.ext.crtcOwner = 3;
+		newmode.ext.pllsel |= 0x20000800;
+		newmode.ext.vpll2 = newmode.ext.vpll;
+	} else if (par->riva.twoHeads) {
+		newmode.ext.head  =  NV_RD32(par->riva.PCRTC0, 0x00000860) |
+			0x00001000;
+		newmode.ext.head2 =  NV_RD32(par->riva.PCRTC0, 0x00002860) &
+			~0x00001000;
+		newmode.ext.crtcOwner = 0;
+		newmode.ext.vpll2 = NV_RD32(par->riva.PRAMDAC0, 0x00000520);
+	}
+	if (par->FlatPanel == 1) {
+		newmode.ext.pixel |= (1 << 7);
+		newmode.ext.scale |= (1 << 8);
+	}
+	newmode.ext.cursorConfig = 0x02000100;
+	par->current_state = newmode;
+	riva_load_state(par, &par->current_state);
+	par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
+
+out:
+	rivafb_blank(FB_BLANK_UNBLANK, info);
+	NVTRACE_LEAVE();
+
+	return rc;
+}
+
+static void riva_update_var(struct fb_var_screeninfo *var,
+			    const struct fb_videomode *modedb)
+{
+	NVTRACE_ENTER();
+	var->xres = var->xres_virtual = modedb->xres;
+	var->yres = modedb->yres;
+        if (var->yres_virtual < var->yres)
+	    var->yres_virtual = var->yres;
+        var->xoffset = var->yoffset = 0;
+        var->pixclock = modedb->pixclock;
+        var->left_margin = modedb->left_margin;
+        var->right_margin = modedb->right_margin;
+        var->upper_margin = modedb->upper_margin;
+        var->lower_margin = modedb->lower_margin;
+        var->hsync_len = modedb->hsync_len;
+        var->vsync_len = modedb->vsync_len;
+        var->sync = modedb->sync;
+        var->vmode = modedb->vmode;
+	NVTRACE_LEAVE();
+}
+
+/**
+ * rivafb_do_maximize - 
+ * @info: pointer to fb_info object containing info for current riva board
+ * @var:
+ * @nom:
+ * @den:
+ *
+ * DESCRIPTION:
+ * .
+ *
+ * RETURNS:
+ * -EINVAL on failure, 0 on success
+ * 
+ *
+ * CALLED FROM:
+ * rivafb_check_var()
+ */
+static int rivafb_do_maximize(struct fb_info *info,
+			      struct fb_var_screeninfo *var,
+			      int nom, int den)
+{
+	static struct {
+		int xres, yres;
+	} modes[] = {
+		{1600, 1280},
+		{1280, 1024},
+		{1024, 768},
+		{800, 600},
+		{640, 480},
+		{-1, -1}
+	};
+	int i;
+
+	NVTRACE_ENTER();
+	/* use highest possible virtual resolution */
+	if (var->xres_virtual == -1 && var->yres_virtual == -1) {
+		printk(KERN_WARNING PFX
+		       "using maximum available virtual resolution\n");
+		for (i = 0; modes[i].xres != -1; i++) {
+			if (modes[i].xres * nom / den * modes[i].yres <
+			    info->fix.smem_len)
+				break;
+		}
+		if (modes[i].xres == -1) {
+			printk(KERN_ERR PFX
+			       "could not find a virtual resolution that fits into video memory!!\n");
+			NVTRACE("EXIT - EINVAL error\n");
+			return -EINVAL;
+		}
+		var->xres_virtual = modes[i].xres;
+		var->yres_virtual = modes[i].yres;
+
+		printk(KERN_INFO PFX
+		       "virtual resolution set to maximum of %dx%d\n",
+		       var->xres_virtual, var->yres_virtual);
+	} else if (var->xres_virtual == -1) {
+		var->xres_virtual = (info->fix.smem_len * den /
+			(nom * var->yres_virtual)) & ~15;
+		printk(KERN_WARNING PFX
+		       "setting virtual X resolution to %d\n", var->xres_virtual);
+	} else if (var->yres_virtual == -1) {
+		var->xres_virtual = (var->xres_virtual + 15) & ~15;
+		var->yres_virtual = info->fix.smem_len * den /
+			(nom * var->xres_virtual);
+		printk(KERN_WARNING PFX
+		       "setting virtual Y resolution to %d\n", var->yres_virtual);
+	} else {
+		var->xres_virtual = (var->xres_virtual + 15) & ~15;
+		if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) {
+			printk(KERN_ERR PFX
+			       "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
+			       var->xres, var->yres, var->bits_per_pixel);
+			NVTRACE("EXIT - EINVAL error\n");
+			return -EINVAL;
+		}
+	}
+	
+	if (var->xres_virtual * nom / den >= 8192) {
+		printk(KERN_WARNING PFX
+		       "virtual X resolution (%d) is too high, lowering to %d\n",
+		       var->xres_virtual, 8192 * den / nom - 16);
+		var->xres_virtual = 8192 * den / nom - 16;
+	}
+	
+	if (var->xres_virtual < var->xres) {
+		printk(KERN_ERR PFX
+		       "virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
+		return -EINVAL;
+	}
+
+	if (var->yres_virtual < var->yres) {
+		printk(KERN_ERR PFX
+		       "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
+		return -EINVAL;
+	}
+	if (var->yres_virtual > 0x7fff/nom)
+		var->yres_virtual = 0x7fff/nom;
+	if (var->xres_virtual > 0x7fff/nom)
+		var->xres_virtual = 0x7fff/nom;
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static void
+riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1)
+{
+	RIVA_FIFO_FREE(par->riva, Patt, 4);
+	NV_WR32(&par->riva.Patt->Color0, 0, clr0);
+	NV_WR32(&par->riva.Patt->Color1, 0, clr1);
+	NV_WR32(par->riva.Patt->Monochrome, 0, pat0);
+	NV_WR32(par->riva.Patt->Monochrome, 4, pat1);
+}
+
+/* acceleration routines */
+static inline void wait_for_idle(struct riva_par *par)
+{
+	while (par->riva.Busy(&par->riva));
+}
+
+/*
+ * Set ROP.  Translate X rop into ROP3.  Internal routine.
+ */
+static void
+riva_set_rop_solid(struct riva_par *par, int rop)
+{
+	riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+        RIVA_FIFO_FREE(par->riva, Rop, 1);
+        NV_WR32(&par->riva.Rop->Rop3, 0, rop);
+
+}
+
+static void riva_setup_accel(struct fb_info *info)
+{
+	struct riva_par *par = info->par;
+
+	RIVA_FIFO_FREE(par->riva, Clip, 2);
+	NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0);
+	NV_WR32(&par->riva.Clip->WidthHeight, 0,
+		(info->var.xres_virtual & 0xffff) |
+		(info->var.yres_virtual << 16));
+	riva_set_rop_solid(par, 0xcc);
+	wait_for_idle(par);
+}
+
+/**
+ * riva_get_cmap_len - query current color map length
+ * @var: standard kernel fb changeable data
+ *
+ * DESCRIPTION:
+ * Get current color map length.
+ *
+ * RETURNS:
+ * Length of color map
+ *
+ * CALLED FROM:
+ * rivafb_setcolreg()
+ */
+static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
+{
+	int rc = 256;		/* reasonable default */
+
+	switch (var->green.length) {
+	case 8:
+		rc = 256;	/* 256 entries (2^8), 8 bpp and RGB8888 */
+		break;
+	case 5:
+		rc = 32;	/* 32 entries (2^5), 16 bpp, RGB555 */
+		break;
+	case 6:
+		rc = 64;	/* 64 entries (2^6), 16 bpp, RGB565 */
+		break;		
+	default:
+		/* should not occur */
+		break;
+	}
+	return rc;
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * framebuffer operations
+ *
+ * ------------------------------------------------------------------------- */
+
+static int rivafb_open(struct fb_info *info, int user)
+{
+	struct riva_par *par = info->par;
+
+	NVTRACE_ENTER();
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+#ifdef CONFIG_X86
+		memset(&par->state, 0, sizeof(struct vgastate));
+		par->state.flags = VGA_SAVE_MODE  | VGA_SAVE_FONTS;
+		/* save the DAC for Riva128 */
+		if (par->riva.Architecture == NV_ARCH_03)
+			par->state.flags |= VGA_SAVE_CMAP;
+		save_vga(&par->state);
+#endif
+		/* vgaHWunlock() + riva unlock (0x7F) */
+		CRTCout(par, 0x11, 0xFF);
+		par->riva.LockUnlock(&par->riva, 0);
+	
+		riva_save_state(par, &par->initial_state);
+	}
+	par->ref_count++;
+	mutex_unlock(&par->open_lock);
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int rivafb_release(struct fb_info *info, int user)
+{
+	struct riva_par *par = info->par;
+
+	NVTRACE_ENTER();
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+		mutex_unlock(&par->open_lock);
+		return -EINVAL;
+	}
+	if (par->ref_count == 1) {
+		par->riva.LockUnlock(&par->riva, 0);
+		par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
+		riva_load_state(par, &par->initial_state);
+#ifdef CONFIG_X86
+		restore_vga(&par->state);
+#endif
+		par->riva.LockUnlock(&par->riva, 1);
+	}
+	par->ref_count--;
+	mutex_unlock(&par->open_lock);
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	const struct fb_videomode *mode;
+	struct riva_par *par = info->par;
+	int nom, den;		/* translating from pixels->bytes */
+	int mode_valid = 0;
+	
+	NVTRACE_ENTER();
+	switch (var->bits_per_pixel) {
+	case 1 ... 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		var->bits_per_pixel = 8;
+		nom = den = 1;
+		break;
+	case 9 ... 15:
+		var->green.length = 5;
+		/* fall through */
+	case 16:
+		var->bits_per_pixel = 16;
+		/* The Riva128 supports RGB555 only */
+		if (par->riva.Architecture == NV_ARCH_03)
+			var->green.length = 5;
+		if (var->green.length == 5) {
+			/* 0rrrrrgg gggbbbbb */
+			var->red.offset = 10;
+			var->green.offset = 5;
+			var->blue.offset = 0;
+			var->red.length = 5;
+			var->green.length = 5;
+			var->blue.length = 5;
+		} else {
+			/* rrrrrggg gggbbbbb */
+			var->red.offset = 11;
+			var->green.offset = 5;
+			var->blue.offset = 0;
+			var->red.length = 5;
+			var->green.length = 6;
+			var->blue.length = 5;
+		}
+		nom = 2;
+		den = 1;
+		break;
+	case 17 ... 32:
+		var->red.length = var->green.length = var->blue.length = 8;
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		nom = 4;
+		den = 1;
+		break;
+	default:
+		printk(KERN_ERR PFX
+		       "mode %dx%dx%d rejected...color depth not supported.\n",
+		       var->xres, var->yres, var->bits_per_pixel);
+		NVTRACE("EXIT, returning -EINVAL\n");
+		return -EINVAL;
+	}
+
+	if (!strictmode) {
+		if (!info->monspecs.vfmax || !info->monspecs.hfmax ||
+		    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
+			mode_valid = 1;
+	}
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+
+	if (!mode_valid) {
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			riva_update_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual <= var->yres)
+		var->yres_virtual = -1;
+	if (rivafb_do_maximize(info, var, nom, den) < 0)
+		return -EINVAL;
+
+	/* truncate xoffset and yoffset to maximum if too high */
+	if (var->xoffset > var->xres_virtual - var->xres)
+		var->xoffset = var->xres_virtual - var->xres - 1;
+
+	if (var->yoffset > var->yres_virtual - var->yres)
+		var->yoffset = var->yres_virtual - var->yres - 1;
+
+	var->red.msb_right = 
+	    var->green.msb_right =
+	    var->blue.msb_right =
+	    var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int rivafb_set_par(struct fb_info *info)
+{
+	struct riva_par *par = info->par;
+	int rc = 0;
+
+	NVTRACE_ENTER();
+	/* vgaHWunlock() + riva unlock (0x7F) */
+	CRTCout(par, 0x11, 0xFF);
+	par->riva.LockUnlock(&par->riva, 0);
+	rc = riva_load_video_mode(info);
+	if (rc)
+		goto out;
+	if(!(info->flags & FBINFO_HWACCEL_DISABLED))
+		riva_setup_accel(info);
+	
+	par->cursor_reset = 1;
+	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED)
+		info->pixmap.scan_align = 1;
+	else
+		info->pixmap.scan_align = 4;
+
+out:
+	NVTRACE_LEAVE();
+	return rc;
+}
+
+/**
+ * rivafb_pan_display
+ * @var: standard kernel fb changeable data
+ * @con: TODO
+ * @info: pointer to fb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * `xoffset' and `yoffset' fields of the `var' structure.
+ * If the values don't fit, return -EINVAL.
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int rivafb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct riva_par *par = info->par;
+	unsigned int base;
+
+	NVTRACE_ENTER();
+	base = var->yoffset * info->fix.line_length + var->xoffset;
+	par->riva.SetStartAddress(&par->riva, base);
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int rivafb_blank(int blank, struct fb_info *info)
+{
+	struct riva_par *par= info->par;
+	unsigned char tmp, vesa;
+
+	tmp = SEQin(par, 0x01) & ~0x20;	/* screen on/off */
+	vesa = CRTCin(par, 0x1a) & ~0xc0;	/* sync on/off */
+
+	NVTRACE_ENTER();
+
+	if (blank)
+		tmp |= 0x20;
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		vesa |= 0x80;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		vesa |= 0x40;
+		break;
+	case FB_BLANK_POWERDOWN:
+		vesa |= 0xc0;
+		break;
+	}
+
+	SEQout(par, 0x01, tmp);
+	CRTCout(par, 0x1a, vesa);
+
+	NVTRACE_LEAVE();
+
+	return 0;
+}
+
+/**
+ * rivafb_setcolreg
+ * @regno: register index
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ * @transp: transparency
+ * @info: pointer to fb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude.
+ *
+ * RETURNS:
+ * Return != 0 for invalid regno.
+ *
+ * CALLED FROM:
+ * fbcmap.c:fb_set_cmap()
+ */
+static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp,
+			  struct fb_info *info)
+{
+	struct riva_par *par = info->par;
+	RIVA_HW_INST *chip = &par->riva;
+	int i;
+
+	if (regno >= riva_get_cmap_len(&info->var))
+			return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		((u32 *) info->pseudo_palette)[regno] =
+			(regno << info->var.red.offset) |
+			(regno << info->var.green.offset) |
+			(regno << info->var.blue.offset);
+		/*
+		 * The Riva128 2D engine requires color information in
+		 * TrueColor format even if framebuffer is in DirectColor
+		 */
+		if (par->riva.Architecture == NV_ARCH_03) {
+			switch (info->var.bits_per_pixel) {
+			case 16:
+				par->palette[regno] = ((red & 0xf800) >> 1) |
+					((green & 0xf800) >> 6) |
+					((blue & 0xf800) >> 11);
+				break;
+			case 32:
+				par->palette[regno] = ((red & 0xff00) << 8) |
+					((green & 0xff00)) |
+					((blue & 0xff00) >> 8);
+				break;
+			}
+		}
+	}
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	case 16:
+		if (info->var.green.length == 5) {
+			for (i = 0; i < 8; i++) {
+				riva_wclut(chip, regno*8+i, red >> 8,
+					   green >> 8, blue >> 8);
+			}
+		} else {
+			u8 r, g, b;
+
+			if (regno < 32) {
+				for (i = 0; i < 8; i++) {
+					riva_wclut(chip, regno*8+i,
+						   red >> 8, green >> 8,
+						   blue >> 8);
+				}
+			}
+			riva_rclut(chip, regno*4, &r, &g, &b);
+			for (i = 0; i < 4; i++)
+				riva_wclut(chip, regno*4+i, r,
+					   green >> 8, b);
+		}
+		break;
+	case 32:
+		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+	return 0;
+}
+
+/**
+ * rivafb_fillrect - hardware accelerated color fill function
+ * @info: pointer to fb_info structure
+ * @rect: pointer to fb_fillrect structure
+ *
+ * DESCRIPTION:
+ * This function fills up a region of framebuffer memory with a solid
+ * color with a choice of two different ROP's, copy or invert.
+ *
+ * CALLED FROM:
+ * framebuffer hook
+ */
+static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct riva_par *par = info->par;
+	u_int color, rop = 0;
+
+	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if (info->var.bits_per_pixel == 8)
+		color = rect->color;
+	else {
+		if (par->riva.Architecture != NV_ARCH_03)
+			color = ((u32 *)info->pseudo_palette)[rect->color];
+		else
+			color = par->palette[rect->color];
+	}
+
+	switch (rect->rop) {
+	case ROP_XOR:
+		rop = 0x66;
+		break;
+	case ROP_COPY:
+	default:
+		rop = 0xCC;
+		break;
+	}
+
+	riva_set_rop_solid(par, rop);
+
+	RIVA_FIFO_FREE(par->riva, Bitmap, 1);
+	NV_WR32(&par->riva.Bitmap->Color1A, 0, color);
+
+	RIVA_FIFO_FREE(par->riva, Bitmap, 2);
+	NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].TopLeft, 0,
+		(rect->dx << 16) | rect->dy);
+	mb();
+	NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].WidthHeight, 0,
+		(rect->width << 16) | rect->height);
+	mb();
+	riva_set_rop_solid(par, 0xcc);
+
+}
+
+/**
+ * rivafb_copyarea - hardware accelerated blit function
+ * @info: pointer to fb_info structure
+ * @region: pointer to fb_copyarea structure
+ *
+ * DESCRIPTION:
+ * This copies an area of pixels from one location to another
+ *
+ * CALLED FROM:
+ * framebuffer hook
+ */
+static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct riva_par *par = info->par;
+
+	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
+	RIVA_FIFO_FREE(par->riva, Blt, 3);
+	NV_WR32(&par->riva.Blt->TopLeftSrc, 0,
+		(region->sy << 16) | region->sx);
+	NV_WR32(&par->riva.Blt->TopLeftDst, 0,
+		(region->dy << 16) | region->dx);
+	mb();
+	NV_WR32(&par->riva.Blt->WidthHeight, 0,
+		(region->height << 16) | region->width);
+	mb();
+}
+
+static inline void convert_bgcolor_16(u32 *col)
+{
+	*col = ((*col & 0x0000F800) << 8)
+		| ((*col & 0x00007E0) << 5)
+		| ((*col & 0x0000001F) << 3)
+		|	   0xFF000000;
+	mb();
+}
+
+/**
+ * rivafb_imageblit: hardware accelerated color expand function
+ * @info: pointer to fb_info structure
+ * @image: pointer to fb_image structure
+ *
+ * DESCRIPTION:
+ * If the source is a monochrome bitmap, the function fills up a a region
+ * of framebuffer memory with pixels whose color is determined by the bit
+ * setting of the bitmap, 1 - foreground, 0 - background.
+ *
+ * If the source is not a monochrome bitmap, color expansion is not done.
+ * In this case, it is channeled to a software function.
+ *
+ * CALLED FROM:
+ * framebuffer hook
+ */
+static void rivafb_imageblit(struct fb_info *info, 
+			     const struct fb_image *image)
+{
+	struct riva_par *par = info->par;
+	u32 fgx = 0, bgx = 0, width, tmp;
+	u8 *cdat = (u8 *) image->data;
+	volatile u32 __iomem *d;
+	int i, size;
+
+	if ((info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		fgx = image->fg_color;
+		bgx = image->bg_color;
+		break;
+	case 16:
+	case 32:
+		if (par->riva.Architecture != NV_ARCH_03) {
+			fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
+			bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
+		} else {
+			fgx = par->palette[image->fg_color];
+			bgx = par->palette[image->bg_color];
+		}
+		if (info->var.green.length == 6)
+			convert_bgcolor_16(&bgx);	
+		break;
+	}
+
+	RIVA_FIFO_FREE(par->riva, Bitmap, 7);
+	NV_WR32(&par->riva.Bitmap->ClipE.TopLeft, 0,
+		(image->dy << 16) | (image->dx & 0xFFFF));
+	NV_WR32(&par->riva.Bitmap->ClipE.BottomRight, 0,
+		(((image->dy + image->height) << 16) |
+		 ((image->dx + image->width) & 0xffff)));
+	NV_WR32(&par->riva.Bitmap->Color0E, 0, bgx);
+	NV_WR32(&par->riva.Bitmap->Color1E, 0, fgx);
+	NV_WR32(&par->riva.Bitmap->WidthHeightInE, 0,
+		(image->height << 16) | ((image->width + 31) & ~31));
+	NV_WR32(&par->riva.Bitmap->WidthHeightOutE, 0,
+		(image->height << 16) | ((image->width + 31) & ~31));
+	NV_WR32(&par->riva.Bitmap->PointE, 0,
+		(image->dy << 16) | (image->dx & 0xFFFF));
+
+	d = &par->riva.Bitmap->MonochromeData01E;
+
+	width = (image->width + 31)/32;
+	size = width * image->height;
+	while (size >= 16) {
+		RIVA_FIFO_FREE(par->riva, Bitmap, 16);
+		for (i = 0; i < 16; i++) {
+			tmp = *((u32 *)cdat);
+			cdat = (u8 *)((u32 *)cdat + 1);
+			reverse_order(&tmp);
+			NV_WR32(d, i*4, tmp);
+		}
+		size -= 16;
+	}
+	if (size) {
+		RIVA_FIFO_FREE(par->riva, Bitmap, size);
+		for (i = 0; i < size; i++) {
+			tmp = *((u32 *) cdat);
+			cdat = (u8 *)((u32 *)cdat + 1);
+			reverse_order(&tmp);
+			NV_WR32(d, i*4, tmp);
+		}
+	}
+}
+
+/**
+ * rivafb_cursor - hardware cursor function
+ * @info: pointer to info structure
+ * @cursor: pointer to fbcursor structure
+ *
+ * DESCRIPTION:
+ * A cursor function that supports displaying a cursor image via hardware.
+ * Within the kernel, copy and invert rops are supported.  If exported
+ * to user space, only the copy rop will be supported.
+ *
+ * CALLED FROM
+ * framebuffer hook
+ */
+static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct riva_par *par = info->par;
+	u8 data[MAX_CURS * MAX_CURS/8];
+	int i, set = cursor->set;
+	u16 fg, bg;
+
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return -ENXIO;
+
+	par->riva.ShowHideCursor(&par->riva, 0);
+
+	if (par->cursor_reset) {
+		set = FB_CUR_SETALL;
+		par->cursor_reset = 0;
+	}
+
+	if (set & FB_CUR_SETSIZE)
+		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+
+	if (set & FB_CUR_SETPOS) {
+		u32 xx, yy, temp;
+
+		yy = cursor->image.dy - info->var.yoffset;
+		xx = cursor->image.dx - info->var.xoffset;
+		temp = xx & 0xFFFF;
+		temp |= yy << 16;
+
+		NV_WR32(par->riva.PRAMDAC, 0x0000300, temp);
+	}
+
+
+	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		u32 bg_idx = cursor->image.bg_color;
+		u32 fg_idx = cursor->image.fg_color;
+		u32 s_pitch = (cursor->image.width+7) >> 3;
+		u32 d_pitch = MAX_CURS/8;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) cursor->mask;
+		u8 *src;
+		
+		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+
+		if (src) {
+			switch (cursor->rop) {
+			case ROP_XOR:
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
+					src[i] = dat[i] ^ msk[i];
+				break;
+			case ROP_COPY:
+			default:
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
+					src[i] = dat[i] & msk[i];
+				break;
+			}
+
+			fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+						cursor->image.height);
+
+			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+				((info->cmap.green[bg_idx] & 0xf8) << 2) |
+				((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
+				1 << 15;
+
+			fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+				((info->cmap.green[fg_idx] & 0xf8) << 2) |
+				((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
+				1 << 15;
+
+			par->riva.LockUnlock(&par->riva, 0);
+
+			rivafb_load_cursor_image(par, data, bg, fg,
+						 cursor->image.width,
+						 cursor->image.height);
+			kfree(src);
+		}
+	}
+
+	if (cursor->enable)
+		par->riva.ShowHideCursor(&par->riva, 1);
+
+	return 0;
+}
+
+static int rivafb_sync(struct fb_info *info)
+{
+	struct riva_par *par = info->par;
+
+	wait_for_idle(par);
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization helper functions
+ *
+ * ------------------------------------------------------------------------- */
+
+/* kernel interface */
+static struct fb_ops riva_fb_ops = {
+	.owner 		= THIS_MODULE,
+	.fb_open	= rivafb_open,
+	.fb_release	= rivafb_release,
+	.fb_check_var 	= rivafb_check_var,
+	.fb_set_par 	= rivafb_set_par,
+	.fb_setcolreg 	= rivafb_setcolreg,
+	.fb_pan_display	= rivafb_pan_display,
+	.fb_blank 	= rivafb_blank,
+	.fb_fillrect 	= rivafb_fillrect,
+	.fb_copyarea 	= rivafb_copyarea,
+	.fb_imageblit 	= rivafb_imageblit,
+	.fb_cursor	= rivafb_cursor,	
+	.fb_sync 	= rivafb_sync,
+};
+
+static int riva_set_fbinfo(struct fb_info *info)
+{
+	unsigned int cmap_len;
+	struct riva_par *par = info->par;
+
+	NVTRACE_ENTER();
+	info->flags = FBINFO_DEFAULT
+		    | FBINFO_HWACCEL_XPAN
+		    | FBINFO_HWACCEL_YPAN
+		    | FBINFO_HWACCEL_COPYAREA
+		    | FBINFO_HWACCEL_FILLRECT
+	            | FBINFO_HWACCEL_IMAGEBLIT;
+
+	/* Accel seems to not work properly on NV30 yet...*/
+	if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
+	    	printk(KERN_DEBUG PFX "disabling acceleration\n");
+  		info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+
+	info->var = rivafb_default_var;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+	info->pseudo_palette = par->pseudo_palette;
+
+	cmap_len = riva_get_cmap_len(&info->var);
+	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
+
+	info->pixmap.size = 8 * 1024;
+	info->pixmap.buf_align = 4;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->var.yres_virtual = -1;
+	NVTRACE_LEAVE();
+	return (rivafb_check_var(&info->var, info));
+}
+
+#ifdef CONFIG_PPC_OF
+static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
+{
+	struct riva_par *par = info->par;
+	struct device_node *dp;
+	const unsigned char *pedid = NULL;
+	const unsigned char *disptype = NULL;
+	static char *propnames[] = {
+		"DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
+	int i;
+
+	NVTRACE_ENTER();
+	dp = pci_device_to_OF_node(pd);
+	for (; dp != NULL; dp = dp->child) {
+		disptype = of_get_property(dp, "display-type", NULL);
+		if (disptype == NULL)
+			continue;
+		if (strncmp(disptype, "LCD", 3) != 0)
+			continue;
+		for (i = 0; propnames[i] != NULL; ++i) {
+			pedid = of_get_property(dp, propnames[i], NULL);
+			if (pedid != NULL) {
+				par->EDID = (unsigned char *)pedid;
+				NVTRACE("LCD found.\n");
+				return 1;
+			}
+		}
+	}
+	NVTRACE_LEAVE();
+	return 0;
+}
+#endif /* CONFIG_PPC_OF */
+
+#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
+static int riva_get_EDID_i2c(struct fb_info *info)
+{
+	struct riva_par *par = info->par;
+	struct fb_var_screeninfo var;
+	int i;
+
+	NVTRACE_ENTER();
+	riva_create_i2c_busses(par);
+	for (i = 0; i < 3; i++) {
+		if (!par->chan[i].par)
+			continue;
+		riva_probe_i2c_connector(par, i, &par->EDID);
+		if (par->EDID && !fb_parse_edid(par->EDID, &var)) {
+			printk(PFX "Found EDID Block from BUS %i\n", i);
+			break;
+		}
+	}
+
+	NVTRACE_LEAVE();
+	return (par->EDID) ? 1 : 0;
+}
+#endif /* CONFIG_FB_RIVA_I2C */
+
+static void riva_update_default_var(struct fb_var_screeninfo *var,
+				    struct fb_info *info)
+{
+	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode modedb;
+
+	NVTRACE_ENTER();
+	/* respect mode options */
+	if (mode_option) {
+		fb_find_mode(var, info, mode_option,
+			     specs->modedb, specs->modedb_len,
+			     NULL, 8);
+	} else if (specs->modedb != NULL) {
+		/* get first mode in database as fallback */
+		modedb = specs->modedb[0];
+		/* get preferred timing */
+		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
+			int i;
+
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = specs->modedb[i];
+					break;
+				}
+			}
+		}
+		var->bits_per_pixel = 8;
+		riva_update_var(var, &modedb);
+	}
+	NVTRACE_LEAVE();
+}
+
+
+static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
+{
+	NVTRACE_ENTER();
+#ifdef CONFIG_PPC_OF
+	if (!riva_get_EDID_OF(info, pdev))
+		printk(PFX "could not retrieve EDID from OF\n");
+#elif defined(CONFIG_FB_RIVA_I2C)
+	if (!riva_get_EDID_i2c(info))
+		printk(PFX "could not retrieve EDID from DDC/I2C\n");
+#endif
+	NVTRACE_LEAVE();
+}
+
+
+static void riva_get_edidinfo(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &rivafb_default_var;
+	struct riva_par *par = info->par;
+
+	fb_edid_to_monspecs(par->EDID, &info->monspecs);
+	fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
+				 &info->modelist);
+	riva_update_default_var(var, info);
+
+	/* if user specified flatpanel, we respect that */
+	if (info->monspecs.input & FB_DISP_DDI)
+		par->FlatPanel = 1;
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * PCI bus
+ *
+ * ------------------------------------------------------------------------- */
+
+static u32 riva_get_arch(struct pci_dev *pd)
+{
+    	u32 arch = 0;
+
+	switch (pd->device & 0x0ff0) {
+		case 0x0100:   /* GeForce 256 */
+		case 0x0110:   /* GeForce2 MX */
+		case 0x0150:   /* GeForce2 */
+		case 0x0170:   /* GeForce4 MX */
+		case 0x0180:   /* GeForce4 MX (8x AGP) */
+		case 0x01A0:   /* nForce */
+		case 0x01F0:   /* nForce2 */
+		     arch =  NV_ARCH_10;
+		     break;
+		case 0x0200:   /* GeForce3 */
+		case 0x0250:   /* GeForce4 Ti */
+		case 0x0280:   /* GeForce4 Ti (8x AGP) */
+		     arch =  NV_ARCH_20;
+		     break;
+		case 0x0300:   /* GeForceFX 5800 */
+		case 0x0310:   /* GeForceFX 5600 */
+		case 0x0320:   /* GeForceFX 5200 */
+		case 0x0330:   /* GeForceFX 5900 */
+		case 0x0340:   /* GeForceFX 5700 */
+		     arch =  NV_ARCH_30;
+		     break;
+		case 0x0020:   /* TNT, TNT2 */
+		     arch =  NV_ARCH_04;
+		     break;
+		case 0x0010:   /* Riva128 */
+		     arch =  NV_ARCH_03;
+		     break;
+		default:   /* unknown architecture */
+		     break;
+	}
+	return arch;
+}
+
+static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
+{
+	struct riva_par *default_par;
+	struct fb_info *info;
+	int ret;
+
+	NVTRACE_ENTER();
+	assert(pd != NULL);
+
+	info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev);
+	if (!info) {
+		printk (KERN_ERR PFX "could not allocate memory\n");
+		ret = -ENOMEM;
+		goto err_ret;
+	}
+	default_par = info->par;
+	default_par->pdev = pd;
+
+	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
+	if (info->pixmap.addr == NULL) {
+	    	ret = -ENOMEM;
+		goto err_framebuffer_release;
+	}
+
+	ret = pci_enable_device(pd);
+	if (ret < 0) {
+		printk(KERN_ERR PFX "cannot enable PCI device\n");
+		goto err_free_pixmap;
+	}
+
+	ret = pci_request_regions(pd, "rivafb");
+	if (ret < 0) {
+		printk(KERN_ERR PFX "cannot request PCI regions\n");
+		goto err_disable_device;
+	}
+
+	mutex_init(&default_par->open_lock);
+	default_par->riva.Architecture = riva_get_arch(pd);
+
+	default_par->Chipset = (pd->vendor << 16) | pd->device;
+	printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
+	
+	if(default_par->riva.Architecture == 0) {
+		printk(KERN_ERR PFX "unknown NV_ARCH\n");
+		ret=-ENODEV;
+		goto err_release_region;
+	}
+	if(default_par->riva.Architecture == NV_ARCH_10 ||
+	   default_par->riva.Architecture == NV_ARCH_20 ||
+	   default_par->riva.Architecture == NV_ARCH_30) {
+		sprintf(rivafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+	} else {
+		sprintf(rivafb_fix.id, "NV%x", default_par->riva.Architecture);
+	}
+
+	default_par->FlatPanel = flatpanel;
+	if (flatpanel == 1)
+		printk(KERN_INFO PFX "flatpanel support enabled\n");
+	default_par->forceCRTC = forceCRTC;
+	
+	rivafb_fix.mmio_len = pci_resource_len(pd, 0);
+	rivafb_fix.smem_len = pci_resource_len(pd, 1);
+
+	{
+		/* enable IO and mem if not already done */
+		unsigned short cmd;
+
+		pci_read_config_word(pd, PCI_COMMAND, &cmd);
+		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+		pci_write_config_word(pd, PCI_COMMAND, cmd);
+	}
+	
+	rivafb_fix.mmio_start = pci_resource_start(pd, 0);
+	rivafb_fix.smem_start = pci_resource_start(pd, 1);
+
+	default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
+					 rivafb_fix.mmio_len);
+	if (!default_par->ctrl_base) {
+		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+		ret = -EIO;
+		goto err_release_region;
+	}
+
+	switch (default_par->riva.Architecture) {
+	case NV_ARCH_03:
+		/* Riva128's PRAMIN is in the "framebuffer" space
+		 * Since these cards were never made with more than 8 megabytes
+		 * we can safely allocate this separately.
+		 */
+		default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
+		if (!default_par->riva.PRAMIN) {
+			printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
+			ret = -EIO;
+			goto err_iounmap_ctrl_base;
+		}
+		break;
+	case NV_ARCH_04:
+	case NV_ARCH_10:
+	case NV_ARCH_20:
+	case NV_ARCH_30:
+		default_par->riva.PCRTC0 =
+			(u32 __iomem *)(default_par->ctrl_base + 0x00600000);
+		default_par->riva.PRAMIN =
+			(u32 __iomem *)(default_par->ctrl_base + 0x00710000);
+		break;
+	}
+	riva_common_setup(default_par);
+
+	if (default_par->riva.Architecture == NV_ARCH_03) {
+		default_par->riva.PCRTC = default_par->riva.PCRTC0
+		                        = default_par->riva.PGRAPH;
+	}
+
+	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
+	default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
+	info->screen_base = ioremap(rivafb_fix.smem_start,
+				    rivafb_fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_ERR PFX "cannot ioremap FB base\n");
+		ret = -EIO;
+		goto err_iounmap_pramin;
+	}
+
+#ifdef CONFIG_MTRR
+	if (!nomtrr) {
+		default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
+					   	  rivafb_fix.smem_len,
+					    	  MTRR_TYPE_WRCOMB, 1);
+		if (default_par->mtrr.vram < 0) {
+			printk(KERN_ERR PFX "unable to setup MTRR\n");
+		} else {
+			default_par->mtrr.vram_valid = 1;
+			/* let there be speed */
+			printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
+		}
+	}
+#endif /* CONFIG_MTRR */
+
+	info->fbops = &riva_fb_ops;
+	info->fix = rivafb_fix;
+	riva_get_EDID(info, pd);
+	riva_get_edidinfo(info);
+
+	ret=riva_set_fbinfo(info);
+	if (ret < 0) {
+		printk(KERN_ERR PFX "error setting initial video mode\n");
+		goto err_iounmap_screen_base;
+	}
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	pci_set_drvdata(pd, info);
+
+	if (backlight)
+		riva_bl_init(info->par);
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		printk(KERN_ERR PFX
+			"error registering riva framebuffer\n");
+		goto err_iounmap_screen_base;
+	}
+
+	printk(KERN_INFO PFX
+		"PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
+		info->fix.id,
+		RIVAFB_VERSION,
+		info->fix.smem_len / (1024 * 1024),
+		info->fix.smem_start);
+
+	NVTRACE_LEAVE();
+	return 0;
+
+err_iounmap_screen_base:
+#ifdef CONFIG_FB_RIVA_I2C
+	riva_delete_i2c_busses(info->par);
+#endif
+	iounmap(info->screen_base);
+err_iounmap_pramin:
+	if (default_par->riva.Architecture == NV_ARCH_03) 
+		iounmap(default_par->riva.PRAMIN);
+err_iounmap_ctrl_base:
+	iounmap(default_par->ctrl_base);
+err_release_region:
+	pci_release_regions(pd);
+err_disable_device:
+err_free_pixmap:
+	kfree(info->pixmap.addr);
+err_framebuffer_release:
+	framebuffer_release(info);
+err_ret:
+	return ret;
+}
+
+static void rivafb_remove(struct pci_dev *pd)
+{
+	struct fb_info *info = pci_get_drvdata(pd);
+	struct riva_par *par = info->par;
+	
+	NVTRACE_ENTER();
+
+#ifdef CONFIG_FB_RIVA_I2C
+	riva_delete_i2c_busses(par);
+	kfree(par->EDID);
+#endif
+
+	unregister_framebuffer(info);
+
+	riva_bl_exit(info);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr.vram_valid)
+		mtrr_del(par->mtrr.vram, info->fix.smem_start,
+			 info->fix.smem_len);
+#endif /* CONFIG_MTRR */
+
+	iounmap(par->ctrl_base);
+	iounmap(info->screen_base);
+	if (par->riva.Architecture == NV_ARCH_03)
+		iounmap(par->riva.PRAMIN);
+	pci_release_regions(pd);
+	kfree(info->pixmap.addr);
+	framebuffer_release(info);
+	NVTRACE_LEAVE();
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+static int rivafb_setup(char *options)
+{
+	char *this_opt;
+
+	NVTRACE_ENTER();
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "forceCRTC", 9)) {
+			char *p;
+			
+			p = this_opt + 9;
+			if (!*p || !*(++p)) continue; 
+			forceCRTC = *p - '0';
+			if (forceCRTC < 0 || forceCRTC > 1) 
+				forceCRTC = -1;
+		} else if (!strncmp(this_opt, "flatpanel", 9)) {
+			flatpanel = 1;
+		} else if (!strncmp(this_opt, "backlight:", 10)) {
+			backlight = simple_strtoul(this_opt+10, NULL, 0);
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else if (!strncmp(this_opt, "strictmode", 10)) {
+			strictmode = 1;
+		} else if (!strncmp(this_opt, "noaccel", 7)) {
+			noaccel = 1;
+		} else
+			mode_option = this_opt;
+	}
+	NVTRACE_LEAVE();
+	return 0;
+}
+#endif /* !MODULE */
+
+static struct pci_driver rivafb_driver = {
+	.name		= "rivafb",
+	.id_table	= rivafb_pci_tbl,
+	.probe		= rivafb_probe,
+	.remove		= rivafb_remove,
+};
+
+
+
+/* ------------------------------------------------------------------------- *
+ *
+ * modularization
+ *
+ * ------------------------------------------------------------------------- */
+
+static int rivafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("rivafb", &option))
+		return -ENODEV;
+	rivafb_setup(option);
+#endif
+	return pci_register_driver(&rivafb_driver);
+}
+
+
+module_init(rivafb_init);
+
+static void __exit rivafb_exit(void)
+{
+	pci_unregister_driver(&rivafb_driver);
+}
+
+module_exit(rivafb_exit);
+
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+module_param(flatpanel, int, 0);
+MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");
+module_param(forceCRTC, int, 0);
+MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
+#endif
+module_param(strictmode, bool, 0);
+MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
+
+MODULE_AUTHOR("Ani Joshi, maintainer");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/riva/nv_driver.c b/drivers/video/fbdev/riva/nv_driver.c
new file mode 100644
index 000000000000..f3694cf17e58
--- /dev/null
+++ b/drivers/video/fbdev/riva/nv_driver.c
@@ -0,0 +1,422 @@
+/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */
+/*
+ * Copyright 1996-1997  David J. McKay
+ *
+ * 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,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * DAVID J. MCKAY 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.
+ */
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
+ */
+
+/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
+   <jpaana@s2.org> */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.18 2002/08/0
+5 20:47:06 mvojkovi Exp $ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include "nv_type.h"
+#include "rivafb.h"
+#include "nvreg.h"
+
+#define PFX "rivafb: "
+
+static inline unsigned char MISCin(struct riva_par *par)
+{
+	return (VGA_RD08(par->riva.PVIO, 0x3cc));
+}
+
+static Bool 
+riva_is_connected(struct riva_par *par, Bool second)
+{
+	volatile U032 __iomem *PRAMDAC = par->riva.PRAMDAC0;
+	U032 reg52C, reg608;
+	Bool present;
+
+	if(second) PRAMDAC += 0x800;
+
+	reg52C = NV_RD32(PRAMDAC, 0x052C);
+	reg608 = NV_RD32(PRAMDAC, 0x0608);
+
+	NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
+	mdelay(1); 
+	NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
+
+	NV_WR32(par->riva.PRAMDAC0, 0x0610, 0x94050140);
+	NV_WR32(par->riva.PRAMDAC0, 0x0608, 0x00001000);
+
+	mdelay(1);
+
+	present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? TRUE : FALSE;
+
+	NV_WR32(par->riva.PRAMDAC0, 0x0608,
+		NV_RD32(par->riva.PRAMDAC0, 0x0608) & 0x0000EFFF);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C);
+	NV_WR32(PRAMDAC, 0x0608, reg608);
+
+	return present;
+}
+
+static void
+riva_override_CRTC(struct riva_par *par)
+{
+	printk(KERN_INFO PFX
+		"Detected CRTC controller %i being used\n",
+		par->SecondCRTC ? 1 : 0);
+
+	if(par->forceCRTC != -1) {
+		printk(KERN_INFO PFX
+			"Forcing usage of CRTC %i\n", par->forceCRTC);
+		par->SecondCRTC = par->forceCRTC;
+	}
+}
+
+static void
+riva_is_second(struct riva_par *par)
+{
+	if (par->FlatPanel == 1) {
+		switch(par->Chipset & 0xffff) {
+		case 0x0174:
+		case 0x0175:
+		case 0x0176:
+		case 0x0177:
+		case 0x0179:
+		case 0x017C:
+		case 0x017D:
+		case 0x0186:
+		case 0x0187:
+		/* this might not be a good default for the chips below */
+		case 0x0286:
+		case 0x028C:
+		case 0x0316:
+		case 0x0317:
+		case 0x031A:
+		case 0x031B:
+		case 0x031C:
+		case 0x031D:
+		case 0x031E:
+		case 0x031F:
+		case 0x0324:
+		case 0x0325:
+		case 0x0328:
+		case 0x0329:
+		case 0x032C:
+		case 0x032D:
+			par->SecondCRTC = TRUE;
+			break;
+		default:
+			par->SecondCRTC = FALSE;
+			break;
+		}
+	} else {
+		if(riva_is_connected(par, 0)) {
+
+			if (NV_RD32(par->riva.PRAMDAC0, 0x0000052C) & 0x100)
+				par->SecondCRTC = TRUE;
+			else
+				par->SecondCRTC = FALSE;
+		} else 
+		if (riva_is_connected(par, 1)) {
+			if(NV_RD32(par->riva.PRAMDAC0, 0x0000252C) & 0x100)
+				par->SecondCRTC = TRUE;
+			else
+				par->SecondCRTC = FALSE;
+		} else /* default */
+			par->SecondCRTC = FALSE;
+	}
+	riva_override_CRTC(par);
+}
+
+unsigned long riva_get_memlen(struct riva_par *par)
+{
+	RIVA_HW_INST *chip = &par->riva;
+	unsigned long memlen = 0;
+	unsigned int chipset = par->Chipset;
+	struct pci_dev* dev;
+	u32 amt;
+
+	switch (chip->Architecture) {
+	case NV_ARCH_03:
+		if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) {
+			if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
+			    && ((NV_RD32(chip->PMC, 0x00000000)&0x0F)>=0x02)) {
+				/*
+				 * SDRAM 128 ZX.
+				 */
+				switch (NV_RD32(chip->PFB,0x00000000) & 0x03) {
+				case 2:
+					memlen = 1024 * 4;
+					break;
+				case 1:
+					memlen = 1024 * 2;
+					break;
+				default:
+					memlen = 1024 * 8;
+					break;
+				}
+			} else {
+				memlen = 1024 * 8;
+			}            
+		} else 	{
+			/*
+			 * SGRAM 128.
+			 */
+			switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) {
+			case 0:
+				memlen = 1024 * 8;
+				break;
+			case 2:
+				memlen = 1024 * 4;
+				break;
+			default:
+				memlen = 1024 * 2;
+				break;
+			}
+		}        
+		break;
+	case NV_ARCH_04:
+		if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100) {
+			memlen = ((NV_RD32(chip->PFB, 0x00000000)>>12)&0x0F) *
+				1024 * 2 + 1024 * 2;
+		} else {
+			switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) {
+			case 0:
+				memlen = 1024 * 32;
+				break;
+			case 1:
+				memlen = 1024 * 4;
+				break;
+			case 2:
+				memlen = 1024 * 8;
+				break;
+			case 3:
+			default:
+				memlen = 1024 * 16;
+				break;
+			}
+		}
+		break;
+	case NV_ARCH_10:
+	case NV_ARCH_20:
+	case NV_ARCH_30:
+		if(chipset == NV_CHIP_IGEFORCE2) {
+
+			dev = pci_get_bus_and_slot(0, 1);
+			pci_read_config_dword(dev, 0x7C, &amt);
+			pci_dev_put(dev);
+			memlen = (((amt >> 6) & 31) + 1) * 1024;
+		} else if (chipset == NV_CHIP_0x01F0) {
+			dev = pci_get_bus_and_slot(0, 1);
+			pci_read_config_dword(dev, 0x84, &amt);
+			pci_dev_put(dev);
+			memlen = (((amt >> 4) & 127) + 1) * 1024;
+		} else {
+			switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) &
+				0x000000FF){
+			case 0x02:
+				memlen = 1024 * 2;
+				break;
+			case 0x04:
+				memlen = 1024 * 4;
+				break;
+			case 0x08:
+				memlen = 1024 * 8;
+				break;
+			case 0x10:
+				memlen = 1024 * 16;
+				break;
+			case 0x20:
+				memlen = 1024 * 32;
+				break;
+			case 0x40:
+				memlen = 1024 * 64;
+				break;
+			case 0x80:
+				memlen = 1024 * 128;
+				break;
+			default:
+				memlen = 1024 * 16;
+				break;
+			}
+		}
+		break;
+	}
+	return memlen;
+}
+
+unsigned long riva_get_maxdclk(struct riva_par *par)
+{
+	RIVA_HW_INST *chip = &par->riva;
+	unsigned long dclk = 0;
+
+	switch (chip->Architecture) {
+	case NV_ARCH_03:
+		if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) {
+			if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
+			    && ((NV_RD32(chip->PMC,0x00000000)&0x0F) >= 0x02)) {
+				/*
+				 * SDRAM 128 ZX.
+				 */
+				dclk = 800000;
+			} else {
+				dclk = 1000000;
+			}            
+		} else {
+			/*
+			 * SGRAM 128.
+			 */
+			dclk = 1000000;
+		} 
+		break;
+	case NV_ARCH_04:
+	case NV_ARCH_10:
+	case NV_ARCH_20:
+	case NV_ARCH_30:
+		switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003) {
+		case 3:
+			dclk = 800000;
+			break;
+		default:
+			dclk = 1000000;
+			break;
+		}
+		break;
+	}
+	return dclk;
+}
+
+void
+riva_common_setup(struct riva_par *par)
+{
+	par->riva.EnableIRQ = 0;
+	par->riva.PRAMDAC0 =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00680000);
+	par->riva.PFB =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00100000);
+	par->riva.PFIFO =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00002000);
+	par->riva.PGRAPH =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00400000);
+	par->riva.PEXTDEV =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00101000);
+	par->riva.PTIMER =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00009000);
+	par->riva.PMC =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00000000);
+	par->riva.FIFO =
+		(volatile U032 __iomem *)(par->ctrl_base + 0x00800000);
+	par->riva.PCIO0 = par->ctrl_base + 0x00601000;
+	par->riva.PDIO0 = par->ctrl_base + 0x00681000;
+	par->riva.PVIO = par->ctrl_base + 0x000C0000;
+
+	par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0;
+	
+	if (par->FlatPanel == -1) {
+		switch (par->Chipset & 0xffff) {
+		case 0x0112:   /* known laptop chips */
+		case 0x0174:
+		case 0x0175:
+		case 0x0176:
+		case 0x0177:
+		case 0x0179:
+		case 0x017C:
+		case 0x017D:
+		case 0x0186:
+		case 0x0187:
+		case 0x0286:
+		case 0x028C:
+		case 0x0316:
+		case 0x0317:
+		case 0x031A:
+		case 0x031B:
+		case 0x031C:
+		case 0x031D:
+		case 0x031E:
+		case 0x031F:
+		case 0x0324:
+		case 0x0325:
+		case 0x0328:
+		case 0x0329:
+		case 0x032C:
+		case 0x032D:
+			printk(KERN_INFO PFX 
+				"On a laptop.  Assuming Digital Flat Panel\n");
+			par->FlatPanel = 1;
+			break;
+		default:
+			break;
+		}
+	}
+	
+	switch (par->Chipset & 0x0ff0) {
+	case 0x0110:
+		if (par->Chipset == NV_CHIP_GEFORCE2_GO)
+			par->SecondCRTC = TRUE; 
+#if defined(__powerpc__)
+		if (par->FlatPanel == 1)
+			par->SecondCRTC = TRUE;
+#endif
+		riva_override_CRTC(par);
+		break;
+	case 0x0170:
+	case 0x0180:
+	case 0x01F0:
+	case 0x0250:
+	case 0x0280:
+	case 0x0300:
+	case 0x0310:
+	case 0x0320:
+	case 0x0330:
+	case 0x0340:
+		riva_is_second(par);
+		break;
+	default:
+		break;
+	}
+
+	if (par->SecondCRTC) {
+		par->riva.PCIO = par->riva.PCIO0 + 0x2000;
+		par->riva.PCRTC = par->riva.PCRTC0 + 0x800;
+		par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800;
+		par->riva.PDIO = par->riva.PDIO0 + 0x2000;
+	} else {
+		par->riva.PCIO = par->riva.PCIO0;
+		par->riva.PCRTC = par->riva.PCRTC0;
+		par->riva.PRAMDAC = par->riva.PRAMDAC0;
+		par->riva.PDIO = par->riva.PDIO0;
+	}
+
+	if (par->FlatPanel == -1) {
+		/* Fix me, need x86 DDC code */
+		par->FlatPanel = 0;
+	}
+	par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE;
+
+	RivaGetConfig(&par->riva, par->Chipset);
+}
+
diff --git a/drivers/video/fbdev/riva/nv_type.h b/drivers/video/fbdev/riva/nv_type.h
new file mode 100644
index 000000000000..a69480c9a67c
--- /dev/null
+++ b/drivers/video/fbdev/riva/nv_type.h
@@ -0,0 +1,58 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_type.h,v 1.35 2002/08/05 20:47:06 mvojkovi Exp $ */
+
+#ifndef __NV_STRUCT_H__
+#define __NV_STRUCT_H__
+
+#define NV_CHIP_RIVA_128            ((PCI_VENDOR_ID_NVIDIA_SGS << 16)| PCI_DEVICE_ID_NVIDIA_RIVA128)
+#define NV_CHIP_TNT                 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT)
+#define NV_CHIP_TNT2                ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT2)
+#define NV_CHIP_UTNT2               ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UTNT2)
+#define NV_CHIP_VTNT2               ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_VTNT2)
+#define NV_CHIP_UVTNT2              ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UVTNT2)
+#define NV_CHIP_ITNT2               ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_ITNT2)
+#define NV_CHIP_GEFORCE_256         ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_256)
+#define NV_CHIP_GEFORCE_DDR         ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR)
+#define NV_CHIP_QUADRO              ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_QUADRO)
+#define NV_CHIP_GEFORCE2_MX         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX)
+#define NV_CHIP_GEFORCE2_MX_100     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX_100)
+#define NV_CHIP_QUADRO2_MXR         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR)
+#define NV_CHIP_GEFORCE2_GO         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO)
+#define NV_CHIP_GEFORCE2_GTS        ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS)
+#define NV_CHIP_GEFORCE2_TI         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_TI)
+#define NV_CHIP_GEFORCE2_ULTRA      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA)
+#define NV_CHIP_QUADRO2_PRO         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO)
+#define NV_CHIP_GEFORCE4_MX_460     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460)
+#define NV_CHIP_GEFORCE4_MX_440     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440)
+#define NV_CHIP_GEFORCE4_MX_420     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420)
+#define NV_CHIP_GEFORCE4_440_GO     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO)
+#define NV_CHIP_GEFORCE4_420_GO     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO)
+#define NV_CHIP_GEFORCE4_420_GO_M32 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32)
+#define NV_CHIP_QUADRO4_500XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL)
+#define NV_CHIP_GEFORCE4_440_GO_M64 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64)
+#define NV_CHIP_QUADRO4_200         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_200)
+#define NV_CHIP_QUADRO4_550XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL)
+#define NV_CHIP_QUADRO4_500_GOGL    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL)
+#define NV_CHIP_0x0180              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0180)
+#define NV_CHIP_0x0181              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0181)
+#define NV_CHIP_0x0182              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0182)
+#define NV_CHIP_0x0188              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0188)
+#define NV_CHIP_0x018A              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018A)
+#define NV_CHIP_0x018B              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018B)
+#define NV_CHIP_IGEFORCE2           ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_IGEFORCE2)
+#define NV_CHIP_0x01F0              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x01F0)
+#define NV_CHIP_GEFORCE3            ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3)
+#define NV_CHIP_GEFORCE3_TI_200     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_200)
+#define NV_CHIP_GEFORCE3_TI_500     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_500)
+#define NV_CHIP_QUADRO_DCC          ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO_DCC)
+#define NV_CHIP_GEFORCE4_TI_4600    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600)
+#define NV_CHIP_GEFORCE4_TI_4400    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400)
+#define NV_CHIP_GEFORCE4_TI_4200    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200)
+#define NV_CHIP_QUADRO4_900XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL)
+#define NV_CHIP_QUADRO4_750XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL)
+#define NV_CHIP_QUADRO4_700XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL)
+#define NV_CHIP_0x0280              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0280)
+#define NV_CHIP_0x0281              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0281)
+#define NV_CHIP_0x0288              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0288)
+#define NV_CHIP_0x0289              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0289)
+
+#endif /* __NV_STRUCT_H__ */
diff --git a/drivers/video/fbdev/riva/nvreg.h b/drivers/video/fbdev/riva/nvreg.h
new file mode 100644
index 000000000000..abfc167ae8d8
--- /dev/null
+++ b/drivers/video/fbdev/riva/nvreg.h
@@ -0,0 +1,188 @@
+/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */
+/*
+ * Copyright 1996-1997  David J. McKay
+ *
+ * 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,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * DAVID J. MCKAY 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.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/nvreg.h,v 3.2.2.1 1998/01/18 10:35:36 hohndel Exp $ */
+
+#ifndef __NVREG_H_
+#define __NVREG_H_
+
+/* Little macro to construct bitmask for contiguous ranges of bits */
+#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1)  << (b))
+#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
+
+/* Macro to set specific bitfields (mask has to be a macro x:y) ! */
+#define SetBF(mask,value) ((value) << (0?mask))
+#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
+
+#define MaskAndSetBF(var,mask,value) (var)=(((var)&(~MASKEXPAND(mask)) \
+                                             | SetBF(mask,value)))
+
+#define DEVICE_BASE(device) (0?NV##_##device)
+#define DEVICE_SIZE(device) ((1?NV##_##device) - DEVICE_BASE(device)+1)
+
+/* This is where we will have to have conditional compilation */
+#define DEVICE_ACCESS(device,reg) \
+  nvCONTROL[(NV_##device##_##reg)/4]
+
+#define DEVICE_WRITE(device,reg,value) DEVICE_ACCESS(device,reg)=(value)
+#define DEVICE_READ(device,reg)        DEVICE_ACCESS(device,reg)
+#define DEVICE_PRINT(device,reg) \
+  ErrorF("NV_"#device"_"#reg"=#%08lx\n",DEVICE_ACCESS(device,reg))
+#define DEVICE_DEF(device,mask,value) \
+  SetBF(NV_##device##_##mask,NV_##device##_##mask##_##value)
+#define DEVICE_VALUE(device,mask,value) SetBF(NV_##device##_##mask,value)
+#define DEVICE_MASK(device,mask) MASKEXPAND(NV_##device##_##mask)
+
+#define PDAC_Write(reg,value)           DEVICE_WRITE(PDAC,reg,value)
+#define PDAC_Read(reg)                  DEVICE_READ(PDAC,reg)
+#define PDAC_Print(reg)                 DEVICE_PRINT(PDAC,reg)
+#define PDAC_Def(mask,value)            DEVICE_DEF(PDAC,mask,value)
+#define PDAC_Val(mask,value)            DEVICE_VALUE(PDAC,mask,value)
+#define PDAC_Mask(mask)                 DEVICE_MASK(PDAC,mask)
+
+#define PFB_Write(reg,value)            DEVICE_WRITE(PFB,reg,value)
+#define PFB_Read(reg)                   DEVICE_READ(PFB,reg)
+#define PFB_Print(reg)                  DEVICE_PRINT(PFB,reg)
+#define PFB_Def(mask,value)             DEVICE_DEF(PFB,mask,value)
+#define PFB_Val(mask,value)             DEVICE_VALUE(PFB,mask,value)
+#define PFB_Mask(mask)                  DEVICE_MASK(PFB,mask)
+
+#define PRM_Write(reg,value)            DEVICE_WRITE(PRM,reg,value)
+#define PRM_Read(reg)                   DEVICE_READ(PRM,reg)
+#define PRM_Print(reg)                  DEVICE_PRINT(PRM,reg)
+#define PRM_Def(mask,value)             DEVICE_DEF(PRM,mask,value)
+#define PRM_Val(mask,value)             DEVICE_VALUE(PRM,mask,value)
+#define PRM_Mask(mask)                  DEVICE_MASK(PRM,mask)
+
+#define PGRAPH_Write(reg,value)         DEVICE_WRITE(PGRAPH,reg,value)
+#define PGRAPH_Read(reg)                DEVICE_READ(PGRAPH,reg)
+#define PGRAPH_Print(reg)               DEVICE_PRINT(PGRAPH,reg)
+#define PGRAPH_Def(mask,value)          DEVICE_DEF(PGRAPH,mask,value)
+#define PGRAPH_Val(mask,value)          DEVICE_VALUE(PGRAPH,mask,value)
+#define PGRAPH_Mask(mask)               DEVICE_MASK(PGRAPH,mask)
+
+#define PDMA_Write(reg,value)           DEVICE_WRITE(PDMA,reg,value)
+#define PDMA_Read(reg)                  DEVICE_READ(PDMA,reg)
+#define PDMA_Print(reg)                 DEVICE_PRINT(PDMA,reg)
+#define PDMA_Def(mask,value)            DEVICE_DEF(PDMA,mask,value)
+#define PDMA_Val(mask,value)            DEVICE_VALUE(PDMA,mask,value)
+#define PDMA_Mask(mask)                 DEVICE_MASK(PDMA,mask)
+
+#define PTIMER_Write(reg,value)         DEVICE_WRITE(PTIMER,reg,value)
+#define PTIMER_Read(reg)                DEVICE_READ(PTIMER,reg)
+#define PTIMER_Print(reg)               DEVICE_PRINT(PTIMER,reg)
+#define PTIMER_Def(mask,value)          DEVICE_DEF(PTIMER,mask,value)
+#define PTIMER_Val(mask,value)          DEVICE_VALUE(PTIEMR,mask,value)
+#define PTIMER_Mask(mask)               DEVICE_MASK(PTIMER,mask)
+
+#define PEXTDEV_Write(reg,value)         DEVICE_WRITE(PEXTDEV,reg,value)
+#define PEXTDEV_Read(reg)                DEVICE_READ(PEXTDEV,reg)
+#define PEXTDEV_Print(reg)               DEVICE_PRINT(PEXTDEV,reg)
+#define PEXTDEV_Def(mask,value)          DEVICE_DEF(PEXTDEV,mask,value)
+#define PEXTDEV_Val(mask,value)          DEVICE_VALUE(PEXTDEV,mask,value)
+#define PEXTDEV_Mask(mask)               DEVICE_MASK(PEXTDEV,mask)
+
+#define PFIFO_Write(reg,value)          DEVICE_WRITE(PFIFO,reg,value)
+#define PFIFO_Read(reg)                 DEVICE_READ(PFIFO,reg)
+#define PFIFO_Print(reg)                DEVICE_PRINT(PFIFO,reg)
+#define PFIFO_Def(mask,value)           DEVICE_DEF(PFIFO,mask,value)
+#define PFIFO_Val(mask,value)           DEVICE_VALUE(PFIFO,mask,value)
+#define PFIFO_Mask(mask)                DEVICE_MASK(PFIFO,mask)
+
+#define PRAM_Write(reg,value)           DEVICE_WRITE(PRAM,reg,value)
+#define PRAM_Read(reg)                  DEVICE_READ(PRAM,reg)
+#define PRAM_Print(reg)                 DEVICE_PRINT(PRAM,reg)
+#define PRAM_Def(mask,value)            DEVICE_DEF(PRAM,mask,value)
+#define PRAM_Val(mask,value)            DEVICE_VALUE(PRAM,mask,value)
+#define PRAM_Mask(mask)                 DEVICE_MASK(PRAM,mask)
+
+#define PRAMFC_Write(reg,value)         DEVICE_WRITE(PRAMFC,reg,value)
+#define PRAMFC_Read(reg)                DEVICE_READ(PRAMFC,reg)
+#define PRAMFC_Print(reg)               DEVICE_PRINT(PRAMFC,reg)
+#define PRAMFC_Def(mask,value)          DEVICE_DEF(PRAMFC,mask,value)
+#define PRAMFC_Val(mask,value)          DEVICE_VALUE(PRAMFC,mask,value)
+#define PRAMFC_Mask(mask)               DEVICE_MASK(PRAMFC,mask)
+
+#define PMC_Write(reg,value)            DEVICE_WRITE(PMC,reg,value)
+#define PMC_Read(reg)                   DEVICE_READ(PMC,reg)
+#define PMC_Print(reg)                  DEVICE_PRINT(PMC,reg)
+#define PMC_Def(mask,value)             DEVICE_DEF(PMC,mask,value)
+#define PMC_Val(mask,value)             DEVICE_VALUE(PMC,mask,value)
+#define PMC_Mask(mask)                  DEVICE_MASK(PMC,mask)
+
+#define PMC_Write(reg,value)            DEVICE_WRITE(PMC,reg,value)
+#define PMC_Read(reg)                   DEVICE_READ(PMC,reg)
+#define PMC_Print(reg)                  DEVICE_PRINT(PMC,reg)
+#define PMC_Def(mask,value)             DEVICE_DEF(PMC,mask,value)
+#define PMC_Val(mask,value)             DEVICE_VALUE(PMC,mask,value)
+#define PMC_Mask(mask)                  DEVICE_MASK(PMC,mask)
+
+
+#define PBUS_Write(reg,value)         DEVICE_WRITE(PBUS,reg,value)
+#define PBUS_Read(reg)                DEVICE_READ(PBUS,reg)
+#define PBUS_Print(reg)               DEVICE_PRINT(PBUS,reg)
+#define PBUS_Def(mask,value)          DEVICE_DEF(PBUS,mask,value)
+#define PBUS_Val(mask,value)          DEVICE_VALUE(PBUS,mask,value)
+#define PBUS_Mask(mask)               DEVICE_MASK(PBUS,mask)
+
+
+#define PRAMDAC_Write(reg,value)         DEVICE_WRITE(PRAMDAC,reg,value)
+#define PRAMDAC_Read(reg)                DEVICE_READ(PRAMDAC,reg)
+#define PRAMDAC_Print(reg)               DEVICE_PRINT(PRAMDAC,reg)
+#define PRAMDAC_Def(mask,value)          DEVICE_DEF(PRAMDAC,mask,value)
+#define PRAMDAC_Val(mask,value)          DEVICE_VALUE(PRAMDAC,mask,value)
+#define PRAMDAC_Mask(mask)               DEVICE_MASK(PRAMDAC,mask)
+
+
+#define PDAC_ReadExt(reg) \
+  ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\
+  (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\
+  (PDAC_Read(INDEX_DATA)))
+
+#define PDAC_WriteExt(reg,value)\
+  ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\
+  (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\
+  (PDAC_Write(INDEX_DATA,(value))))
+
+#define CRTC_Write(index,value) outb((index), 0x3d4); outb(value, 0x3d5)
+#define CRTC_Read(index) (outb(index, 0x3d4),inb(0x3d5))
+
+#define PCRTC_Write(index,value) CRTC_Write(NV_PCRTC_##index,value)
+#define PCRTC_Read(index) CRTC_Read(NV_PCRTC_##index)
+
+#define PCRTC_Def(mask,value)          DEVICE_DEF(PCRTC,mask,value)
+#define PCRTC_Val(mask,value)          DEVICE_VALUE(PCRTC,mask,value)
+#define PCRTC_Mask(mask)               DEVICE_MASK(PCRTC,mask)
+
+#define SR_Write(index,value) outb(0x3c4,(index));outb(0x3c5,value)
+#define SR_Read(index) (outb(0x3c4,index),inb(0x3c5))
+
+extern volatile unsigned  *nvCONTROL;
+
+typedef enum {NV1,NV3,NV4,NumNVChips} NVChipType;
+
+NVChipType GetChipType(void);
+
+#endif
+
+
diff --git a/drivers/video/fbdev/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c
new file mode 100644
index 000000000000..78fdbf5178d7
--- /dev/null
+++ b/drivers/video/fbdev/riva/riva_hw.c
@@ -0,0 +1,2268 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.33 2002/08/05 20:47:06 mvojkovi Exp $ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include "riva_hw.h"
+#include "riva_tbl.h"
+#include "nv_type.h"
+
+/*
+ * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
+ * operate identically (except TNT has more memory and better 3D quality.
+ */
+static int nv3Busy
+(
+    RIVA_HW_INST *chip
+)
+{
+    return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
+	    NV_RD32(&chip->PGRAPH[0x000006B0/4], 0) & 0x01);
+}
+static int nv4Busy
+(
+    RIVA_HW_INST *chip
+)
+{
+    return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
+	    NV_RD32(&chip->PGRAPH[0x00000700/4], 0) & 0x01);
+}
+static int nv10Busy
+(
+    RIVA_HW_INST *chip
+)
+{
+    return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
+	    NV_RD32(&chip->PGRAPH[0x00000700/4], 0) & 0x01);
+}
+
+static void vgaLockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           Lock
+)
+{
+    U008 cr11;
+    VGA_WR08(chip->PCIO, 0x3D4, 0x11);
+    cr11 = VGA_RD08(chip->PCIO, 0x3D5);
+    if(Lock) cr11 |= 0x80;
+    else cr11 &= ~0x80;
+    VGA_WR08(chip->PCIO, 0x3D5, cr11);
+}
+static void nv3LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           Lock
+)
+{
+    VGA_WR08(chip->PVIO, 0x3C4, 0x06);
+    VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57);
+    vgaLockUnlock(chip, Lock);
+}
+static void nv4LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           Lock
+)
+{
+    VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
+    VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
+    vgaLockUnlock(chip, Lock);
+}
+
+static int ShowHideCursor
+(
+    RIVA_HW_INST *chip,
+    int           ShowHide
+)
+{
+    int cursor;
+    cursor                      =  chip->CurrentState->cursor1;
+    chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
+                                  (ShowHide & 0x01);
+    VGA_WR08(chip->PCIO, 0x3D4, 0x31);
+    VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
+    return (cursor & 0x01);
+}
+
+/****************************************************************************\
+*                                                                            *
+* The video arbitration routines calculate some "magic" numbers.  Fixes      *
+* the snow seen when accessing the framebuffer without it.                   *
+* It just works (I hope).                                                    *
+*                                                                            *
+\****************************************************************************/
+
+#define DEFAULT_GR_LWM 100
+#define DEFAULT_VID_LWM 100
+#define DEFAULT_GR_BURST_SIZE 256
+#define DEFAULT_VID_BURST_SIZE 128
+#define VIDEO		0
+#define GRAPHICS	1
+#define MPORT		2
+#define ENGINE		3
+#define GFIFO_SIZE	320
+#define GFIFO_SIZE_128	256
+#define MFIFO_SIZE	120
+#define VFIFO_SIZE	256
+
+typedef struct {
+  int gdrain_rate;
+  int vdrain_rate;
+  int mdrain_rate;
+  int gburst_size;
+  int vburst_size;
+  char vid_en;
+  char gr_en;
+  int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm;
+  int by_gfacc;
+  char vid_only_once;
+  char gr_only_once;
+  char first_vacc;
+  char first_gacc;
+  char first_macc;
+  int vocc;
+  int gocc;
+  int mocc;
+  char cur;
+  char engine_en;
+  char converged;
+  int priority;
+} nv3_arb_info;
+typedef struct {
+  int graphics_lwm;
+  int video_lwm;
+  int graphics_burst_size;
+  int video_burst_size;
+  int graphics_hi_priority;
+  int media_hi_priority;
+  int rtl_values;
+  int valid;
+} nv3_fifo_info;
+typedef struct {
+  char pix_bpp;
+  char enable_video;
+  char gr_during_vid;
+  char enable_mp;
+  int memory_width;
+  int video_scale;
+  int pclk_khz;
+  int mclk_khz;
+  int mem_page_miss;
+  int mem_latency;
+  char mem_aligned;
+} nv3_sim_state;
+typedef struct {
+  int graphics_lwm;
+  int video_lwm;
+  int graphics_burst_size;
+  int video_burst_size;
+  int valid;
+} nv4_fifo_info;
+typedef struct {
+  int pclk_khz;
+  int mclk_khz;
+  int nvclk_khz;
+  char mem_page_miss;
+  char mem_latency;
+  int memory_width;
+  char enable_video;
+  char gr_during_vid;
+  char pix_bpp;
+  char mem_aligned;
+  char enable_mp;
+} nv4_sim_state;
+typedef struct {
+  int graphics_lwm;
+  int video_lwm;
+  int graphics_burst_size;
+  int video_burst_size;
+  int valid;
+} nv10_fifo_info;
+typedef struct {
+  int pclk_khz;
+  int mclk_khz;
+  int nvclk_khz;
+  char mem_page_miss;
+  char mem_latency;
+  u32 memory_type;
+  int memory_width;
+  char enable_video;
+  char gr_during_vid;
+  char pix_bpp;
+  char mem_aligned;
+  char enable_mp;
+} nv10_sim_state;
+static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
+{
+    int iter = 0;
+    int tmp;
+    int vfsize, mfsize, gfsize;
+    int mburst_size = 32;
+    int mmisses, gmisses, vmisses;
+    int misses;
+    int vlwm, glwm, mlwm;
+    int last, next, cur;
+    int max_gfsize ;
+    long ns;
+
+    vlwm = 0;
+    glwm = 0;
+    mlwm = 0;
+    vfsize = 0;
+    gfsize = 0;
+    cur = ainfo->cur;
+    mmisses = 2;
+    gmisses = 2;
+    vmisses = 2;
+    if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128;
+    else  max_gfsize = GFIFO_SIZE;
+    max_gfsize = GFIFO_SIZE;
+    while (1)
+    {
+        if (ainfo->vid_en)
+        {
+            if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc;
+            if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ;
+            ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
+            vfsize = ns * ainfo->vdrain_rate / 1000000;
+            vfsize =  ainfo->wcvlwm - ainfo->vburst_size + vfsize;
+        }
+        if (state->enable_mp)
+        {
+            if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc;
+        }
+        if (ainfo->gr_en)
+        {
+            if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
+            if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
+            ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
+            gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
+            gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
+        }
+        mfsize = 0;
+        if (!state->gr_during_vid && ainfo->vid_en)
+            if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once)
+                next = VIDEO;
+            else if (ainfo->mocc < 0)
+                next = MPORT;
+            else if (ainfo->gocc< ainfo->by_gfacc)
+                next = GRAPHICS;
+            else return (0);
+        else switch (ainfo->priority)
+            {
+                case VIDEO:
+                    if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
+                        next = VIDEO;
+                    else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
+                        next = GRAPHICS;
+                    else if (ainfo->mocc<0)
+                        next = MPORT;
+                    else    return (0);
+                    break;
+                case GRAPHICS:
+                    if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
+                        next = GRAPHICS;
+                    else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
+                        next = VIDEO;
+                    else if (ainfo->mocc<0)
+                        next = MPORT;
+                    else    return (0);
+                    break;
+                default:
+                    if (ainfo->mocc<0)
+                        next = MPORT;
+                    else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
+                        next = GRAPHICS;
+                    else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
+                        next = VIDEO;
+                    else    return (0);
+                    break;
+            }
+        last = cur;
+        cur = next;
+        iter++;
+        switch (cur)
+        {
+            case VIDEO:
+                if (last==cur)    misses = 0;
+                else if (ainfo->first_vacc)   misses = vmisses;
+                else    misses = 1;
+                ainfo->first_vacc = 0;
+                if (last!=cur)
+                {
+                    ns =  1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; 
+                    vlwm = ns * ainfo->vdrain_rate/ 1000000;
+                    vlwm = ainfo->vocc - vlwm;
+                }
+                ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz;
+                ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000;
+                ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000;
+                ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000;
+                break;
+            case GRAPHICS:
+                if (last==cur)    misses = 0;
+                else if (ainfo->first_gacc)   misses = gmisses;
+                else    misses = 1;
+                ainfo->first_gacc = 0;
+                if (last!=cur)
+                {
+                    ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ;
+                    glwm = ns * ainfo->gdrain_rate/1000000;
+                    glwm = ainfo->gocc - glwm;
+                }
+                ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
+                ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
+                ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000;
+                ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000;
+                break;
+            default:
+                if (last==cur)    misses = 0;
+                else if (ainfo->first_macc)   misses = mmisses;
+                else    misses = 1;
+                ainfo->first_macc = 0;
+                ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz;
+                ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
+                ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000;
+                ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000;
+                break;
+        }
+        if (iter>100)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
+        tmp = ns * ainfo->gdrain_rate/1000000;
+        if (abs(ainfo->gburst_size) + ((abs(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
+        tmp = ns * ainfo->vdrain_rate/1000000;
+        if (abs(ainfo->vburst_size) + (abs(ainfo->wcvlwm + 32) & ~0xf)  - tmp> VFIFO_SIZE)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        if (abs(ainfo->gocc) > max_gfsize)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        if (abs(ainfo->vocc) > VFIFO_SIZE)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        if (abs(ainfo->mocc) > MFIFO_SIZE)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        if (abs(vfsize) > VFIFO_SIZE)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        if (abs(gfsize) > max_gfsize)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+        if (abs(mfsize) > MFIFO_SIZE)
+        {
+            ainfo->converged = 0;
+            return (1);
+        }
+    }
+}
+static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state,  nv3_arb_info *ainfo) 
+{
+    long ens, vns, mns, gns;
+    int mmisses, gmisses, vmisses, eburst_size, mburst_size;
+    int refresh_cycle;
+
+    refresh_cycle = 0;
+    refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5;
+    mmisses = 2;
+    if (state->mem_aligned) gmisses = 2;
+    else    gmisses = 3;
+    vmisses = 2;
+    eburst_size = state->memory_width * 1;
+    mburst_size = 32;
+    gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
+    ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
+    ainfo->wcmocc = 0;
+    ainfo->wcgocc = 0;
+    ainfo->wcvocc = 0;
+    ainfo->wcvlwm = 0;
+    ainfo->wcglwm = 0;
+    ainfo->engine_en = 1;
+    ainfo->converged = 1;
+    if (ainfo->engine_en)
+    {
+        ens =  1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz;
+        ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0;
+        ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0;
+        ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0;
+        ainfo->cur = ENGINE;
+        ainfo->first_vacc = 1;
+        ainfo->first_gacc = 1;
+        ainfo->first_macc = 1;
+        nv3_iterate(res_info, state,ainfo);
+    }
+    if (state->enable_mp)
+    {
+        mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
+        ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000;
+        ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000;
+        ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000;
+        ainfo->cur = MPORT;
+        ainfo->first_vacc = 1;
+        ainfo->first_gacc = 1;
+        ainfo->first_macc = 0;
+        nv3_iterate(res_info, state,ainfo);
+    }
+    if (ainfo->gr_en)
+    {
+        ainfo->first_vacc = 1;
+        ainfo->first_gacc = 0;
+        ainfo->first_macc = 1;
+        gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
+        ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000;
+        ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0;
+        ainfo->mocc = state->enable_mp ?  0-gns*ainfo->mdrain_rate/1000000: 0;
+        ainfo->cur = GRAPHICS;
+        nv3_iterate(res_info, state,ainfo);
+    }
+    if (ainfo->vid_en)
+    {
+        ainfo->first_vacc = 0;
+        ainfo->first_gacc = 1;
+        ainfo->first_macc = 1;
+        vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
+        ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000;
+        ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0;
+        ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ;
+        ainfo->cur = VIDEO;
+        nv3_iterate(res_info, state, ainfo);
+    }
+    if (ainfo->converged)
+    {
+        res_info->graphics_lwm = (int)abs(ainfo->wcglwm) + 16;
+        res_info->video_lwm = (int)abs(ainfo->wcvlwm) + 32;
+        res_info->graphics_burst_size = ainfo->gburst_size;
+        res_info->video_burst_size = ainfo->vburst_size;
+        res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS);
+        res_info->media_hi_priority = (ainfo->priority == MPORT);
+        if (res_info->video_lwm > 160)
+        {
+            res_info->graphics_lwm = 256;
+            res_info->video_lwm = 128;
+            res_info->graphics_burst_size = 64;
+            res_info->video_burst_size = 64;
+            res_info->graphics_hi_priority = 0;
+            res_info->media_hi_priority = 0;
+            ainfo->converged = 0;
+            return (0);
+        }
+        if (res_info->video_lwm > 128)
+        {
+            res_info->video_lwm = 128;
+        }
+        return (1);
+    }
+    else
+    {
+        res_info->graphics_lwm = 256;
+        res_info->video_lwm = 128;
+        res_info->graphics_burst_size = 64;
+        res_info->video_burst_size = 64;
+        res_info->graphics_hi_priority = 0;
+        res_info->media_hi_priority = 0;
+        return (0);
+    }
+}
+static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
+{
+    int done, g,v, p;
+    
+    done = 0;
+    for (p=0; p < 2; p++)
+    {
+        for (g=128 ; g > 32; g= g>> 1)
+        {
+            for (v=128; v >=32; v = v>> 1)
+            {
+                ainfo->priority = p;
+                ainfo->gburst_size = g;     
+                ainfo->vburst_size = v;
+                done = nv3_arb(res_info, state,ainfo);
+                if (done && (g==128))
+                    if ((res_info->graphics_lwm + g) > 256)
+                        done = 0;
+                if (done)
+                    goto Done;
+            }
+        }
+    }
+
+ Done:
+    return done;
+}
+static void nv3CalcArbitration 
+(
+    nv3_fifo_info * res_info,
+    nv3_sim_state * state
+)
+{
+    nv3_fifo_info save_info;
+    nv3_arb_info ainfo;
+    char   res_gr, res_vid;
+
+    ainfo.gr_en = 1;
+    ainfo.vid_en = state->enable_video;
+    ainfo.vid_only_once = 0;
+    ainfo.gr_only_once = 0;
+    ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
+    ainfo.vdrain_rate = (int) state->pclk_khz * 2;
+    if (state->video_scale != 0)
+        ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
+    ainfo.mdrain_rate = 33000;
+    res_info->rtl_values = 0;
+    if (!state->gr_during_vid && state->enable_video)
+    {
+        ainfo.gr_only_once = 1;
+        ainfo.gr_en = 1;
+        ainfo.gdrain_rate = 0;
+        res_vid = nv3_get_param(res_info, state,  &ainfo);
+        res_vid = ainfo.converged;
+        save_info.video_lwm = res_info->video_lwm;
+        save_info.video_burst_size = res_info->video_burst_size;
+        ainfo.vid_en = 1;
+        ainfo.vid_only_once = 1;
+        ainfo.gr_en = 1;
+        ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
+        ainfo.vdrain_rate = 0;
+        res_gr = nv3_get_param(res_info, state,  &ainfo);
+        res_gr = ainfo.converged;
+        res_info->video_lwm = save_info.video_lwm;
+        res_info->video_burst_size = save_info.video_burst_size;
+        res_info->valid = res_gr & res_vid;
+    }
+    else
+    {
+        if (!ainfo.gr_en) ainfo.gdrain_rate = 0;
+        if (!ainfo.vid_en) ainfo.vdrain_rate = 0;
+        res_gr = nv3_get_param(res_info, state,  &ainfo);
+        res_info->valid = ainfo.converged;
+    }
+}
+static void nv3UpdateArbitrationSettings
+(
+    unsigned      VClk, 
+    unsigned      pixelDepth, 
+    unsigned     *burst,
+    unsigned     *lwm,
+    RIVA_HW_INST *chip
+)
+{
+    nv3_fifo_info fifo_data;
+    nv3_sim_state sim_data;
+    unsigned int M, N, P, pll, MClk;
+    
+    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
+    M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
+    MClk = (N * chip->CrystalFreqKHz / M) >> P;
+    sim_data.pix_bpp        = (char)pixelDepth;
+    sim_data.enable_video   = 0;
+    sim_data.enable_mp      = 0;
+    sim_data.video_scale    = 1;
+    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
+	128 : 64;
+    sim_data.memory_width   = 128;
+
+    sim_data.mem_latency    = 9;
+    sim_data.mem_aligned    = 1;
+    sim_data.mem_page_miss  = 11;
+    sim_data.gr_during_vid  = 0;
+    sim_data.pclk_khz       = VClk;
+    sim_data.mclk_khz       = MClk;
+    nv3CalcArbitration(&fifo_data, &sim_data);
+    if (fifo_data.valid)
+    {
+        int  b = fifo_data.graphics_burst_size >> 4;
+        *burst = 0;
+        while (b >>= 1)
+	    (*burst)++;
+        *lwm   = fifo_data.graphics_lwm >> 3;
+    }
+    else
+    {
+        *lwm   = 0x24;
+        *burst = 0x2;
+    }
+}
+static void nv4CalcArbitration 
+(
+    nv4_fifo_info *fifo,
+    nv4_sim_state *arb
+)
+{
+    int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
+    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+    int found, mclk_extra, mclk_loop, cbs, m1, p1;
+    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+    int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
+    int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
+    int craw, vraw;
+
+    fifo->valid = 1;
+    pclk_freq = arb->pclk_khz;
+    mclk_freq = arb->mclk_khz;
+    nvclk_freq = arb->nvclk_khz;
+    pagemiss = arb->mem_page_miss;
+    cas = arb->mem_latency;
+    width = arb->memory_width >> 6;
+    video_enable = arb->enable_video;
+    color_key_enable = arb->gr_during_vid;
+    bpp = arb->pix_bpp;
+    align = arb->mem_aligned;
+    mp_enable = arb->enable_mp;
+    clwm = 0;
+    vlwm = 0;
+    cbs = 128;
+    pclks = 2;
+    nvclks = 2;
+    nvclks += 2;
+    nvclks += 1;
+    mclks = 5;
+    mclks += 3;
+    mclks += 1;
+    mclks += cas;
+    mclks += 1;
+    mclks += 1;
+    mclks += 1;
+    mclks += 1;
+    mclk_extra = 3;
+    nvclks += 2;
+    nvclks += 1;
+    nvclks += 1;
+    nvclks += 1;
+    if (mp_enable)
+        mclks+=4;
+    nvclks += 0;
+    pclks += 0;
+    found = 0;
+    vbs = 0;
+    while (found != 1)
+    {
+        fifo->valid = 1;
+        found = 1;
+        mclk_loop = mclks+mclk_extra;
+        us_m = mclk_loop *1000*1000 / mclk_freq;
+        us_n = nvclks*1000*1000 / nvclk_freq;
+        us_p = nvclks*1000*1000 / pclk_freq;
+        if (video_enable)
+        {
+            video_drain_rate = pclk_freq * 2;
+            crtc_drain_rate = pclk_freq * bpp/8;
+            vpagemiss = 2;
+            vpagemiss += 1;
+            crtpagemiss = 2;
+            vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
+            if (nvclk_freq * 2 > mclk_freq * width)
+                video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
+            else
+                video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
+            us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
+            vlwm = us_video * video_drain_rate/(1000*1000);
+            vlwm++;
+            vbs = 128;
+            if (vlwm > 128) vbs = 64;
+            if (vlwm > (256-64)) vbs = 32;
+            if (nvclk_freq * 2 > mclk_freq * width)
+                video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
+            else
+                video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
+            cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+            us_crt =
+            us_video
+            +video_fill_us
+            +cpm_us
+            +us_m + us_n +us_p
+            ;
+            clwm = us_crt * crtc_drain_rate/(1000*1000);
+            clwm++;
+        }
+        else
+        {
+            crtc_drain_rate = pclk_freq * bpp/8;
+            crtpagemiss = 2;
+            crtpagemiss += 1;
+            cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+            us_crt =  cpm_us + us_m + us_n + us_p ;
+            clwm = us_crt * crtc_drain_rate/(1000*1000);
+            clwm++;
+        }
+        m1 = clwm + cbs - 512;
+        p1 = m1 * pclk_freq / mclk_freq;
+        p1 = p1 * bpp / 8;
+        if ((p1 < m1) && (m1 > 0))
+        {
+            fifo->valid = 0;
+            found = 0;
+            if (mclk_extra ==0)   found = 1;
+            mclk_extra--;
+        }
+        else if (video_enable)
+        {
+            if ((clwm > 511) || (vlwm > 255))
+            {
+                fifo->valid = 0;
+                found = 0;
+                if (mclk_extra ==0)   found = 1;
+                mclk_extra--;
+            }
+        }
+        else
+        {
+            if (clwm > 519)
+            {
+                fifo->valid = 0;
+                found = 0;
+                if (mclk_extra ==0)   found = 1;
+                mclk_extra--;
+            }
+        }
+        craw = clwm;
+        vraw = vlwm;
+        if (clwm < 384) clwm = 384;
+        if (vlwm < 128) vlwm = 128;
+        data = (int)(clwm);
+        fifo->graphics_lwm = data;
+        fifo->graphics_burst_size = 128;
+        data = (int)((vlwm+15));
+        fifo->video_lwm = data;
+        fifo->video_burst_size = vbs;
+    }
+}
+static void nv4UpdateArbitrationSettings
+(
+    unsigned      VClk, 
+    unsigned      pixelDepth, 
+    unsigned     *burst,
+    unsigned     *lwm,
+    RIVA_HW_INST *chip
+)
+{
+    nv4_fifo_info fifo_data;
+    nv4_sim_state sim_data;
+    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
+
+    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
+    sim_data.pix_bpp        = (char)pixelDepth;
+    sim_data.enable_video   = 0;
+    sim_data.enable_mp      = 0;
+    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
+	128 : 64;
+    sim_data.mem_latency    = (char)cfg1 & 0x0F;
+    sim_data.mem_aligned    = 1;
+    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
+    sim_data.gr_during_vid  = 0;
+    sim_data.pclk_khz       = VClk;
+    sim_data.mclk_khz       = MClk;
+    sim_data.nvclk_khz      = NVClk;
+    nv4CalcArbitration(&fifo_data, &sim_data);
+    if (fifo_data.valid)
+    {
+        int  b = fifo_data.graphics_burst_size >> 4;
+        *burst = 0;
+        while (b >>= 1)
+	    (*burst)++;
+        *lwm   = fifo_data.graphics_lwm >> 3;
+    }
+}
+static void nv10CalcArbitration 
+(
+    nv10_fifo_info *fifo,
+    nv10_sim_state *arb
+)
+{
+    int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
+    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+    int nvclk_fill, us_extra;
+    int found, mclk_extra, mclk_loop, cbs, m1;
+    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+    int us_m, us_m_min, us_n, us_p, video_drain_rate, crtc_drain_rate;
+    int vus_m, vus_n, vus_p;
+    int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm;
+    int clwm_rnd_down;
+    int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2;
+    int pclks_2_top_fifo, min_mclk_extra;
+    int us_min_mclk_extra;
+
+    fifo->valid = 1;
+    pclk_freq = arb->pclk_khz; /* freq in KHz */
+    mclk_freq = arb->mclk_khz;
+    nvclk_freq = arb->nvclk_khz;
+    pagemiss = arb->mem_page_miss;
+    cas = arb->mem_latency;
+    width = arb->memory_width/64;
+    video_enable = arb->enable_video;
+    color_key_enable = arb->gr_during_vid;
+    bpp = arb->pix_bpp;
+    align = arb->mem_aligned;
+    mp_enable = arb->enable_mp;
+    clwm = 0;
+    vlwm = 1024;
+
+    cbs = 512;
+    vbs = 512;
+
+    pclks = 4; /* lwm detect. */
+
+    nvclks = 3; /* lwm -> sync. */
+    nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
+
+    mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
+
+    mclks += 1;   /* arb_hp_req */
+    mclks += 5;   /* ap_hp_req   tiling pipeline */
+
+    mclks += 2;    /* tc_req     latency fifo */
+    mclks += 2;    /* fb_cas_n_  memory request to fbio block */
+    mclks += 7;    /* sm_d_rdv   data returned from fbio block */
+
+    /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
+    if (arb->memory_type == 0)
+      if (arb->memory_width == 64) /* 64 bit bus */
+        mclks += 4;
+      else
+        mclks += 2;
+    else
+      if (arb->memory_width == 64) /* 64 bit bus */
+        mclks += 2;
+      else
+        mclks += 1;
+
+    if ((!video_enable) && (arb->memory_width == 128))
+    {  
+      mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
+      min_mclk_extra = 17;
+    }
+    else
+    {
+      mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
+      /* mclk_extra = 4; */ /* Margin of error */
+      min_mclk_extra = 18;
+    }
+
+    nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
+    nvclks += 1; /* fbi_d_rdv_n */
+    nvclks += 1; /* Fbi_d_rdata */
+    nvclks += 1; /* crtfifo load */
+
+    if(mp_enable)
+      mclks+=4; /* Mp can get in with a burst of 8. */
+    /* Extra clocks determined by heuristics */
+
+    nvclks += 0;
+    pclks += 0;
+    found = 0;
+    while(found != 1) {
+      fifo->valid = 1;
+      found = 1;
+      mclk_loop = mclks+mclk_extra;
+      us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+      us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
+      us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
+      us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
+      us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
+      us_pipe = us_m + us_n + us_p;
+      us_pipe_min = us_m_min + us_n + us_p;
+      us_extra = 0;
+
+      vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+      vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */
+      vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */
+      vus_pipe = vus_m + vus_n + vus_p;
+
+      if(video_enable) {
+        video_drain_rate = pclk_freq * 4; /* MB/s */
+        crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
+
+        vpagemiss = 1; /* self generating page miss */
+        vpagemiss += 1; /* One higher priority before */
+
+        crtpagemiss = 2; /* self generating page miss */
+        if(mp_enable)
+            crtpagemiss += 1; /* if MA0 conflict */
+
+        vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
+
+        us_video = vpm_us + vus_m; /* Video has separate read return path */
+
+        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+        us_crt =
+          us_video  /* Wait for video */
+          +cpm_us /* CRT Page miss */
+          +us_m + us_n +us_p /* other latency */
+          ;
+
+        clwm = us_crt * crtc_drain_rate/(1000*1000);
+        clwm++; /* fixed point <= float_point - 1.  Fixes that */
+      } else {
+        crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
+
+        crtpagemiss = 1; /* self generating page miss */
+        crtpagemiss += 1; /* MA0 page miss */
+        if(mp_enable)
+            crtpagemiss += 1; /* if MA0 conflict */
+        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+        us_crt =  cpm_us + us_m + us_n + us_p ;
+        clwm = us_crt * crtc_drain_rate/(1000*1000);
+        clwm++; /* fixed point <= float_point - 1.  Fixes that */
+
+  /*
+          //
+          // Another concern, only for high pclks so don't do this
+          // with video:
+          // What happens if the latency to fetch the cbs is so large that
+          // fifo empties.  In that case we need to have an alternate clwm value
+          // based off the total burst fetch
+          //
+          us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+          us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq;
+          clwm_mt = us_crt * crtc_drain_rate/(1000*1000);
+          clwm_mt ++;
+          if(clwm_mt > clwm)
+              clwm = clwm_mt;
+  */
+          /* Finally, a heuristic check when width == 64 bits */
+          if(width == 1){
+              nvclk_fill = nvclk_freq * 8;
+              if(crtc_drain_rate * 100 >= nvclk_fill * 102)
+                      clwm = 0xfff; /*Large number to fail */
+
+              else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
+                  clwm = 1024;
+                  cbs = 512;
+                  us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+              }
+          }
+      }
+
+
+      /*
+        Overfill check:
+
+        */
+
+      clwm_rnd_down = ((int)clwm/8)*8;
+      if (clwm_rnd_down < clwm)
+          clwm += 8;
+
+      m1 = clwm + cbs -  1024; /* Amount of overfill */
+      m2us = us_pipe_min + us_min_mclk_extra;
+      pclks_2_top_fifo = (1024-clwm)/(8*width);
+
+      /* pclk cycles to drain */
+      p1clk = m2us * pclk_freq/(1000*1000); 
+      p2 = p1clk * bpp / 8; /* bytes drained. */
+
+      if((p2 < m1) && (m1 > 0)) {
+          fifo->valid = 0;
+          found = 0;
+          if(min_mclk_extra == 0)   {
+            if(cbs <= 32) {
+              found = 1; /* Can't adjust anymore! */
+            } else {
+              cbs = cbs/2;  /* reduce the burst size */
+            }
+          } else {
+            min_mclk_extra--;
+          }
+      } else {
+        if (clwm > 1023){ /* Have some margin */
+          fifo->valid = 0;
+          found = 0;
+          if(min_mclk_extra == 0)   
+              found = 1; /* Can't adjust anymore! */
+          else 
+              min_mclk_extra--;
+        }
+      }
+      craw = clwm;
+
+      if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
+      data = (int)(clwm);
+      /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
+      fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
+
+      /*  printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */
+      fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
+    }
+}
+static void nv10UpdateArbitrationSettings
+(
+    unsigned      VClk, 
+    unsigned      pixelDepth, 
+    unsigned     *burst,
+    unsigned     *lwm,
+    RIVA_HW_INST *chip
+)
+{
+    nv10_fifo_info fifo_data;
+    nv10_sim_state sim_data;
+    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
+
+    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
+    sim_data.pix_bpp        = (char)pixelDepth;
+    sim_data.enable_video   = 0;
+    sim_data.enable_mp      = 0;
+    sim_data.memory_type    = (NV_RD32(&chip->PFB[0x00000200/4], 0) & 0x01) ?
+	1 : 0;
+    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
+	128 : 64;
+    sim_data.mem_latency    = (char)cfg1 & 0x0F;
+    sim_data.mem_aligned    = 1;
+    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
+    sim_data.gr_during_vid  = 0;
+    sim_data.pclk_khz       = VClk;
+    sim_data.mclk_khz       = MClk;
+    sim_data.nvclk_khz      = NVClk;
+    nv10CalcArbitration(&fifo_data, &sim_data);
+    if (fifo_data.valid)
+    {
+        int  b = fifo_data.graphics_burst_size >> 4;
+        *burst = 0;
+        while (b >>= 1)
+	    (*burst)++;
+        *lwm   = fifo_data.graphics_lwm >> 3;
+    }
+}
+
+static void nForceUpdateArbitrationSettings
+(
+    unsigned      VClk,
+    unsigned      pixelDepth,
+    unsigned     *burst,
+    unsigned     *lwm,
+    RIVA_HW_INST *chip
+)
+{
+    nv10_fifo_info fifo_data;
+    nv10_sim_state sim_data;
+    unsigned int M, N, P, pll, MClk, NVClk;
+    unsigned int uMClkPostDiv;
+    struct pci_dev *dev;
+
+    dev = pci_get_bus_and_slot(0, 3);
+    pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
+    pci_dev_put(dev);
+    uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
+
+    if(!uMClkPostDiv) uMClkPostDiv = 4;
+    MClk = 400000 / uMClkPostDiv;
+
+    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    sim_data.pix_bpp        = (char)pixelDepth;
+    sim_data.enable_video   = 0;
+    sim_data.enable_mp      = 0;
+
+    dev = pci_get_bus_and_slot(0, 1);
+    pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+    pci_dev_put(dev);
+    sim_data.memory_type    = (sim_data.memory_type >> 12) & 1;
+
+    sim_data.memory_width   = 64;
+    sim_data.mem_latency    = 3;
+    sim_data.mem_aligned    = 1;
+    sim_data.mem_page_miss  = 10;
+    sim_data.gr_during_vid  = 0;
+    sim_data.pclk_khz       = VClk;
+    sim_data.mclk_khz       = MClk;
+    sim_data.nvclk_khz      = NVClk;
+    nv10CalcArbitration(&fifo_data, &sim_data);
+    if (fifo_data.valid)
+    {
+        int  b = fifo_data.graphics_burst_size >> 4;
+        *burst = 0;
+        while (b >>= 1)
+	    (*burst)++;
+        *lwm   = fifo_data.graphics_lwm >> 3;
+    }
+}
+
+/****************************************************************************\
+*                                                                            *
+*                          RIVA Mode State Routines                          *
+*                                                                            *
+\****************************************************************************/
+
+/*
+ * Calculate the Video Clock parameters for the PLL.
+ */
+static int CalcVClock
+(
+    int           clockIn,
+    int          *clockOut,
+    int          *mOut,
+    int          *nOut,
+    int          *pOut,
+    RIVA_HW_INST *chip
+)
+{
+    unsigned lowM, highM, highP;
+    unsigned DeltaNew, DeltaOld;
+    unsigned VClk, Freq;
+    unsigned M, N, P;
+    
+    DeltaOld = 0xFFFFFFFF;
+
+    VClk     = (unsigned)clockIn;
+    
+    if (chip->CrystalFreqKHz == 13500)
+    {
+        lowM  = 7;
+        highM = 13 - (chip->Architecture == NV_ARCH_03);
+    }
+    else
+    {
+        lowM  = 8;
+        highM = 14 - (chip->Architecture == NV_ARCH_03);
+    }                      
+
+    highP = 4 - (chip->Architecture == NV_ARCH_03);
+    for (P = 0; P <= highP; P ++)
+    {
+        Freq = VClk << P;
+        if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz))
+        {
+            for (M = lowM; M <= highM; M++)
+            {
+                N    = (VClk << P) * M / chip->CrystalFreqKHz;
+                if(N <= 255) {
+                Freq = (chip->CrystalFreqKHz * N / M) >> P;
+                if (Freq > VClk)
+                    DeltaNew = Freq - VClk;
+                else
+                    DeltaNew = VClk - Freq;
+                if (DeltaNew < DeltaOld)
+                {
+                    *mOut     = M;
+                    *nOut     = N;
+                    *pOut     = P;
+                    *clockOut = Freq;
+                    DeltaOld  = DeltaNew;
+                }
+            }
+        }
+    }
+    }
+
+    /* non-zero: M/N/P/clock values assigned.  zero: error (not set) */
+    return (DeltaOld != 0xFFFFFFFF);
+}
+/*
+ * Calculate extended mode parameters (SVGA) and save in a 
+ * mode state structure.
+ */
+int CalcStateExt
+(
+    RIVA_HW_INST  *chip,
+    RIVA_HW_STATE *state,
+    int            bpp,
+    int            width,
+    int            hDisplaySize,
+    int            height,
+    int            dotClock
+)
+{
+    int pixelDepth;
+    int uninitialized_var(VClk),uninitialized_var(m),
+        uninitialized_var(n),	uninitialized_var(p);
+
+    /*
+     * Save mode parameters.
+     */
+    state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
+    state->width  = width;
+    state->height = height;
+    /*
+     * Extended RIVA registers.
+     */
+    pixelDepth = (bpp + 1)/8;
+    if (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip))
+    	return -EINVAL;
+
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_03:
+            nv3UpdateArbitrationSettings(VClk, 
+                                         pixelDepth * 8, 
+                                        &(state->arbitration0),
+                                        &(state->arbitration1),
+                                         chip);
+            state->cursor0  = 0x00;
+            state->cursor1  = 0x78;
+            state->cursor2  = 0x00000000;
+            state->pllsel   = 0x10010100;
+            state->config   = ((width + 31)/32)
+                            | (((pixelDepth > 2) ? 3 : pixelDepth) << 8)
+                            | 0x1000;
+            state->general  = 0x00100100;
+            state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02;
+            break;
+        case NV_ARCH_04:
+            nv4UpdateArbitrationSettings(VClk, 
+                                         pixelDepth * 8, 
+                                        &(state->arbitration0),
+                                        &(state->arbitration1),
+                                         chip);
+            state->cursor0  = 0x00;
+            state->cursor1  = 0xFC;
+            state->cursor2  = 0x00000000;
+            state->pllsel   = 0x10000700;
+            state->config   = 0x00001114;
+            state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
+            state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+            break;
+        case NV_ARCH_10:
+        case NV_ARCH_20:
+        case NV_ARCH_30:
+            if((chip->Chipset == NV_CHIP_IGEFORCE2) ||
+               (chip->Chipset == NV_CHIP_0x01F0))
+            {
+                nForceUpdateArbitrationSettings(VClk,
+                                          pixelDepth * 8,
+                                         &(state->arbitration0),
+                                         &(state->arbitration1),
+                                          chip);
+            } else {
+                nv10UpdateArbitrationSettings(VClk, 
+                                          pixelDepth * 8, 
+                                         &(state->arbitration0),
+                                         &(state->arbitration1),
+                                          chip);
+            }
+            state->cursor0  = 0x80 | (chip->CursorStart >> 17);
+            state->cursor1  = (chip->CursorStart >> 11) << 2;
+            state->cursor2  = chip->CursorStart >> 24;
+            state->pllsel   = 0x10000700;
+            state->config   = NV_RD32(&chip->PFB[0x00000200/4], 0);
+            state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
+            state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+            break;
+    }
+
+     /* Paul Richards: below if block borks things in kernel for some reason */
+     /* Tony: Below is needed to set hardware in DirectColor */
+    if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
+	    state->general |= 0x00000030;
+
+    state->vpll     = (p << 16) | (n << 8) | m;
+    state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
+    state->pixel    = pixelDepth > 2   ? 3    : pixelDepth;
+    state->offset0  =
+    state->offset1  =
+    state->offset2  =
+    state->offset3  = 0;
+    state->pitch0   =
+    state->pitch1   =
+    state->pitch2   =
+    state->pitch3   = pixelDepth * width;
+
+    return 0;
+}
+/*
+ * Load fixed function state and pre-calculated/stored state.
+ */
+#if 0
+#define LOAD_FIXED_STATE(tbl,dev)                                       \
+    for (i = 0; i < sizeof(tbl##Table##dev)/8; i++)                 \
+        chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1]
+#define LOAD_FIXED_STATE_8BPP(tbl,dev)                                  \
+    for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++)            \
+        chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1]
+#define LOAD_FIXED_STATE_15BPP(tbl,dev)                                 \
+    for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++)           \
+        chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1]
+#define LOAD_FIXED_STATE_16BPP(tbl,dev)                                 \
+    for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++)           \
+        chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1]
+#define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
+    for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
+        chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
+#endif
+
+#define LOAD_FIXED_STATE(tbl,dev)                                       \
+    for (i = 0; i < sizeof(tbl##Table##dev)/8; i++)                 \
+        NV_WR32(&chip->dev[tbl##Table##dev[i][0]], 0, tbl##Table##dev[i][1])
+#define LOAD_FIXED_STATE_8BPP(tbl,dev)                                  \
+    for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++)            \
+        NV_WR32(&chip->dev[tbl##Table##dev##_8BPP[i][0]], 0, tbl##Table##dev##_8BPP[i][1])
+#define LOAD_FIXED_STATE_15BPP(tbl,dev)                                 \
+    for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++)           \
+        NV_WR32(&chip->dev[tbl##Table##dev##_15BPP[i][0]], 0, tbl##Table##dev##_15BPP[i][1])
+#define LOAD_FIXED_STATE_16BPP(tbl,dev)                                 \
+    for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++)           \
+        NV_WR32(&chip->dev[tbl##Table##dev##_16BPP[i][0]], 0, tbl##Table##dev##_16BPP[i][1])
+#define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
+    for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
+        NV_WR32(&chip->dev[tbl##Table##dev##_32BPP[i][0]], 0, tbl##Table##dev##_32BPP[i][1])
+
+static void UpdateFifoState
+(
+    RIVA_HW_INST  *chip
+)
+{
+    int i;
+
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_04:
+            LOAD_FIXED_STATE(nv4,FIFO);
+            chip->Tri03 = NULL;
+            chip->Tri05 = (RivaTexturedTriangle05 __iomem *)&(chip->FIFO[0x0000E000/4]);
+            break;
+        case NV_ARCH_10:
+        case NV_ARCH_20:
+        case NV_ARCH_30:
+            /*
+             * Initialize state for the RivaTriangle3D05 routines.
+             */
+            LOAD_FIXED_STATE(nv10tri05,PGRAPH);
+            LOAD_FIXED_STATE(nv10,FIFO);
+            chip->Tri03 = NULL;
+            chip->Tri05 = (RivaTexturedTriangle05 __iomem *)&(chip->FIFO[0x0000E000/4]);
+            break;
+    }
+}
+static void LoadStateExt
+(
+    RIVA_HW_INST  *chip,
+    RIVA_HW_STATE *state
+)
+{
+    int i;
+
+    /*
+     * Load HW fixed function state.
+     */
+    LOAD_FIXED_STATE(Riva,PMC);
+    LOAD_FIXED_STATE(Riva,PTIMER);
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_03:
+            /*
+             * Make sure frame buffer config gets set before loading PRAMIN.
+             */
+            NV_WR32(chip->PFB, 0x00000200, state->config);
+            LOAD_FIXED_STATE(nv3,PFIFO);
+            LOAD_FIXED_STATE(nv3,PRAMIN);
+            LOAD_FIXED_STATE(nv3,PGRAPH);
+            switch (state->bpp)
+            {
+                case 15:
+                case 16:
+                    LOAD_FIXED_STATE_15BPP(nv3,PRAMIN);
+                    LOAD_FIXED_STATE_15BPP(nv3,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 24:
+                case 32:
+                    LOAD_FIXED_STATE_32BPP(nv3,PRAMIN);
+                    LOAD_FIXED_STATE_32BPP(nv3,PGRAPH);
+                    chip->Tri03 = NULL;
+                    break;
+                case 8:
+                default:
+                    LOAD_FIXED_STATE_8BPP(nv3,PRAMIN);
+                    LOAD_FIXED_STATE_8BPP(nv3,PGRAPH);
+                    chip->Tri03 = NULL;
+                    break;
+            }
+            for (i = 0x00000; i < 0x00800; i++)
+                NV_WR32(&chip->PRAMIN[0x00000502 + i], 0, (i << 12) | 0x03);
+            NV_WR32(chip->PGRAPH, 0x00000630, state->offset0);
+            NV_WR32(chip->PGRAPH, 0x00000634, state->offset1);
+            NV_WR32(chip->PGRAPH, 0x00000638, state->offset2);
+            NV_WR32(chip->PGRAPH, 0x0000063C, state->offset3);
+            NV_WR32(chip->PGRAPH, 0x00000650, state->pitch0);
+            NV_WR32(chip->PGRAPH, 0x00000654, state->pitch1);
+            NV_WR32(chip->PGRAPH, 0x00000658, state->pitch2);
+            NV_WR32(chip->PGRAPH, 0x0000065C, state->pitch3);
+            break;
+        case NV_ARCH_04:
+            /*
+             * Make sure frame buffer config gets set before loading PRAMIN.
+             */
+            NV_WR32(chip->PFB, 0x00000200, state->config);
+            LOAD_FIXED_STATE(nv4,PFIFO);
+            LOAD_FIXED_STATE(nv4,PRAMIN);
+            LOAD_FIXED_STATE(nv4,PGRAPH);
+            switch (state->bpp)
+            {
+                case 15:
+                    LOAD_FIXED_STATE_15BPP(nv4,PRAMIN);
+                    LOAD_FIXED_STATE_15BPP(nv4,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 16:
+                    LOAD_FIXED_STATE_16BPP(nv4,PRAMIN);
+                    LOAD_FIXED_STATE_16BPP(nv4,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 24:
+                case 32:
+                    LOAD_FIXED_STATE_32BPP(nv4,PRAMIN);
+                    LOAD_FIXED_STATE_32BPP(nv4,PGRAPH);
+                    chip->Tri03 = NULL;
+                    break;
+                case 8:
+                default:
+                    LOAD_FIXED_STATE_8BPP(nv4,PRAMIN);
+                    LOAD_FIXED_STATE_8BPP(nv4,PGRAPH);
+                    chip->Tri03 = NULL;
+                    break;
+            }
+            NV_WR32(chip->PGRAPH, 0x00000640, state->offset0);
+            NV_WR32(chip->PGRAPH, 0x00000644, state->offset1);
+            NV_WR32(chip->PGRAPH, 0x00000648, state->offset2);
+            NV_WR32(chip->PGRAPH, 0x0000064C, state->offset3);
+            NV_WR32(chip->PGRAPH, 0x00000670, state->pitch0);
+            NV_WR32(chip->PGRAPH, 0x00000674, state->pitch1);
+            NV_WR32(chip->PGRAPH, 0x00000678, state->pitch2);
+            NV_WR32(chip->PGRAPH, 0x0000067C, state->pitch3);
+            break;
+        case NV_ARCH_10:
+        case NV_ARCH_20:
+        case NV_ARCH_30:
+            if(chip->twoHeads) {
+               VGA_WR08(chip->PCIO, 0x03D4, 0x44);
+               VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner);
+               chip->LockUnlock(chip, 0);
+            }
+
+            LOAD_FIXED_STATE(nv10,PFIFO);
+            LOAD_FIXED_STATE(nv10,PRAMIN);
+            LOAD_FIXED_STATE(nv10,PGRAPH);
+            switch (state->bpp)
+            {
+                case 15:
+                    LOAD_FIXED_STATE_15BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_15BPP(nv10,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 16:
+                    LOAD_FIXED_STATE_16BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_16BPP(nv10,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 24:
+                case 32:
+                    LOAD_FIXED_STATE_32BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_32BPP(nv10,PGRAPH);
+                    chip->Tri03 = NULL;
+                    break;
+                case 8:
+                default:
+                    LOAD_FIXED_STATE_8BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_8BPP(nv10,PGRAPH);
+                    chip->Tri03 = NULL;
+                    break;
+            }
+
+            if(chip->Architecture == NV_ARCH_10) {
+                NV_WR32(chip->PGRAPH, 0x00000640, state->offset0);
+                NV_WR32(chip->PGRAPH, 0x00000644, state->offset1);
+                NV_WR32(chip->PGRAPH, 0x00000648, state->offset2);
+                NV_WR32(chip->PGRAPH, 0x0000064C, state->offset3);
+                NV_WR32(chip->PGRAPH, 0x00000670, state->pitch0);
+                NV_WR32(chip->PGRAPH, 0x00000674, state->pitch1);
+                NV_WR32(chip->PGRAPH, 0x00000678, state->pitch2);
+                NV_WR32(chip->PGRAPH, 0x0000067C, state->pitch3);
+                NV_WR32(chip->PGRAPH, 0x00000680, state->pitch3);
+        } else {
+        NV_WR32(chip->PGRAPH, 0x00000820, state->offset0);
+        NV_WR32(chip->PGRAPH, 0x00000824, state->offset1);
+        NV_WR32(chip->PGRAPH, 0x00000828, state->offset2);
+        NV_WR32(chip->PGRAPH, 0x0000082C, state->offset3);
+        NV_WR32(chip->PGRAPH, 0x00000850, state->pitch0);
+        NV_WR32(chip->PGRAPH, 0x00000854, state->pitch1);
+        NV_WR32(chip->PGRAPH, 0x00000858, state->pitch2);
+        NV_WR32(chip->PGRAPH, 0x0000085C, state->pitch3);
+        NV_WR32(chip->PGRAPH, 0x00000860, state->pitch3);
+        NV_WR32(chip->PGRAPH, 0x00000864, state->pitch3);
+        NV_WR32(chip->PGRAPH, 0x000009A4, NV_RD32(chip->PFB, 0x00000200));
+        NV_WR32(chip->PGRAPH, 0x000009A8, NV_RD32(chip->PFB, 0x00000204));
+        }
+            if(chip->twoHeads) {
+               NV_WR32(chip->PCRTC0, 0x00000860, state->head);
+               NV_WR32(chip->PCRTC0, 0x00002860, state->head2);
+            }
+            NV_WR32(chip->PRAMDAC, 0x00000404, NV_RD32(chip->PRAMDAC, 0x00000404) | (1 << 25));
+
+            NV_WR32(chip->PMC, 0x00008704, 1);
+            NV_WR32(chip->PMC, 0x00008140, 0);
+            NV_WR32(chip->PMC, 0x00008920, 0);
+            NV_WR32(chip->PMC, 0x00008924, 0);
+            NV_WR32(chip->PMC, 0x00008908, 0x01ffffff);
+            NV_WR32(chip->PMC, 0x0000890C, 0x01ffffff);
+            NV_WR32(chip->PMC, 0x00001588, 0);
+
+            NV_WR32(chip->PFB, 0x00000240, 0);
+            NV_WR32(chip->PFB, 0x00000250, 0);
+            NV_WR32(chip->PFB, 0x00000260, 0);
+            NV_WR32(chip->PFB, 0x00000270, 0);
+            NV_WR32(chip->PFB, 0x00000280, 0);
+            NV_WR32(chip->PFB, 0x00000290, 0);
+            NV_WR32(chip->PFB, 0x000002A0, 0);
+            NV_WR32(chip->PFB, 0x000002B0, 0);
+
+            NV_WR32(chip->PGRAPH, 0x00000B00, NV_RD32(chip->PFB, 0x00000240));
+            NV_WR32(chip->PGRAPH, 0x00000B04, NV_RD32(chip->PFB, 0x00000244));
+            NV_WR32(chip->PGRAPH, 0x00000B08, NV_RD32(chip->PFB, 0x00000248));
+            NV_WR32(chip->PGRAPH, 0x00000B0C, NV_RD32(chip->PFB, 0x0000024C));
+            NV_WR32(chip->PGRAPH, 0x00000B10, NV_RD32(chip->PFB, 0x00000250));
+            NV_WR32(chip->PGRAPH, 0x00000B14, NV_RD32(chip->PFB, 0x00000254));
+            NV_WR32(chip->PGRAPH, 0x00000B18, NV_RD32(chip->PFB, 0x00000258));
+            NV_WR32(chip->PGRAPH, 0x00000B1C, NV_RD32(chip->PFB, 0x0000025C));
+            NV_WR32(chip->PGRAPH, 0x00000B20, NV_RD32(chip->PFB, 0x00000260));
+            NV_WR32(chip->PGRAPH, 0x00000B24, NV_RD32(chip->PFB, 0x00000264));
+            NV_WR32(chip->PGRAPH, 0x00000B28, NV_RD32(chip->PFB, 0x00000268));
+            NV_WR32(chip->PGRAPH, 0x00000B2C, NV_RD32(chip->PFB, 0x0000026C));
+            NV_WR32(chip->PGRAPH, 0x00000B30, NV_RD32(chip->PFB, 0x00000270));
+            NV_WR32(chip->PGRAPH, 0x00000B34, NV_RD32(chip->PFB, 0x00000274));
+            NV_WR32(chip->PGRAPH, 0x00000B38, NV_RD32(chip->PFB, 0x00000278));
+            NV_WR32(chip->PGRAPH, 0x00000B3C, NV_RD32(chip->PFB, 0x0000027C));
+            NV_WR32(chip->PGRAPH, 0x00000B40, NV_RD32(chip->PFB, 0x00000280));
+            NV_WR32(chip->PGRAPH, 0x00000B44, NV_RD32(chip->PFB, 0x00000284));
+            NV_WR32(chip->PGRAPH, 0x00000B48, NV_RD32(chip->PFB, 0x00000288));
+            NV_WR32(chip->PGRAPH, 0x00000B4C, NV_RD32(chip->PFB, 0x0000028C));
+            NV_WR32(chip->PGRAPH, 0x00000B50, NV_RD32(chip->PFB, 0x00000290));
+            NV_WR32(chip->PGRAPH, 0x00000B54, NV_RD32(chip->PFB, 0x00000294));
+            NV_WR32(chip->PGRAPH, 0x00000B58, NV_RD32(chip->PFB, 0x00000298));
+            NV_WR32(chip->PGRAPH, 0x00000B5C, NV_RD32(chip->PFB, 0x0000029C));
+            NV_WR32(chip->PGRAPH, 0x00000B60, NV_RD32(chip->PFB, 0x000002A0));
+            NV_WR32(chip->PGRAPH, 0x00000B64, NV_RD32(chip->PFB, 0x000002A4));
+            NV_WR32(chip->PGRAPH, 0x00000B68, NV_RD32(chip->PFB, 0x000002A8));
+            NV_WR32(chip->PGRAPH, 0x00000B6C, NV_RD32(chip->PFB, 0x000002AC));
+            NV_WR32(chip->PGRAPH, 0x00000B70, NV_RD32(chip->PFB, 0x000002B0));
+            NV_WR32(chip->PGRAPH, 0x00000B74, NV_RD32(chip->PFB, 0x000002B4));
+            NV_WR32(chip->PGRAPH, 0x00000B78, NV_RD32(chip->PFB, 0x000002B8));
+            NV_WR32(chip->PGRAPH, 0x00000B7C, NV_RD32(chip->PFB, 0x000002BC));
+            NV_WR32(chip->PGRAPH, 0x00000F40, 0x10000000);
+            NV_WR32(chip->PGRAPH, 0x00000F44, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
+            NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000008);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000200);
+            for (i = 0; i < (3*16); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
+            NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000800);
+            for (i = 0; i < (16*16); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F40, 0x30000000);
+            NV_WR32(chip->PGRAPH, 0x00000F44, 0x00000004);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006400);
+            for (i = 0; i < (59*4); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006800);
+            for (i = 0; i < (47*4); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006C00);
+            for (i = 0; i < (3*4); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007000);
+            for (i = 0; i < (19*4); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007400);
+            for (i = 0; i < (12*4); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007800);
+            for (i = 0; i < (12*4); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00004400);
+            for (i = 0; i < (8*4); i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000000);
+            for (i = 0; i < 16; i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
+            for (i = 0; i < 4; i++)
+                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+
+            NV_WR32(chip->PCRTC, 0x00000810, state->cursorConfig);
+
+            if(chip->flatPanel) {
+               if((chip->Chipset & 0x0ff0) == 0x0110) {
+                   NV_WR32(chip->PRAMDAC, 0x0528, state->dither);
+               } else 
+               if((chip->Chipset & 0x0ff0) >= 0x0170) {
+                   NV_WR32(chip->PRAMDAC, 0x083C, state->dither);
+               }
+            
+               VGA_WR08(chip->PCIO, 0x03D4, 0x53);
+               VGA_WR08(chip->PCIO, 0x03D5, 0);
+               VGA_WR08(chip->PCIO, 0x03D4, 0x54);
+               VGA_WR08(chip->PCIO, 0x03D5, 0);
+               VGA_WR08(chip->PCIO, 0x03D4, 0x21);
+               VGA_WR08(chip->PCIO, 0x03D5, 0xfa);
+            }
+
+            VGA_WR08(chip->PCIO, 0x03D4, 0x41);
+            VGA_WR08(chip->PCIO, 0x03D5, state->extra);
+    }
+    LOAD_FIXED_STATE(Riva,FIFO);
+    UpdateFifoState(chip);
+    /*
+     * Load HW mode state.
+     */
+    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+    VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+    VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+    VGA_WR08(chip->PCIO, 0x03D5, state->screen);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+    VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+    VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+    VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+    VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
+    VGA_WR08(chip->PCIO, 0x03D5, state->cursor2);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x39);
+    VGA_WR08(chip->PCIO, 0x03D5, state->interlace);
+
+    if(!chip->flatPanel) {
+       NV_WR32(chip->PRAMDAC0, 0x00000508, state->vpll);
+       NV_WR32(chip->PRAMDAC0, 0x0000050C, state->pllsel);
+       if(chip->twoHeads)
+          NV_WR32(chip->PRAMDAC0, 0x00000520, state->vpll2);
+    }  else {
+       NV_WR32(chip->PRAMDAC, 0x00000848 , state->scale);
+    }  
+    NV_WR32(chip->PRAMDAC, 0x00000600 , state->general);
+
+    /*
+     * Turn off VBlank enable and reset.
+     */
+    NV_WR32(chip->PCRTC, 0x00000140, 0);
+    NV_WR32(chip->PCRTC, 0x00000100, chip->VBlankBit);
+    /*
+     * Set interrupt enable.
+     */    
+    NV_WR32(chip->PMC, 0x00000140, chip->EnableIRQ & 0x01);
+    /*
+     * Set current state pointer.
+     */
+    chip->CurrentState = state;
+    /*
+     * Reset FIFO free and empty counts.
+     */
+    chip->FifoFreeCount  = 0;
+    /* Free count from first subchannel */
+    chip->FifoEmptyCount = NV_RD32(&chip->Rop->FifoFree, 0);
+}
+static void UnloadStateExt
+(
+    RIVA_HW_INST  *chip,
+    RIVA_HW_STATE *state
+)
+{
+    /*
+     * Save current HW state.
+     */
+    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+    state->repaint0     = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+    state->repaint1     = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+    state->screen       = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+    state->pixel        = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+    state->horiz        = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+    state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+    state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+    state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+    state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
+    state->cursor2      = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x39);
+    state->interlace    = VGA_RD08(chip->PCIO, 0x03D5);
+    state->vpll         = NV_RD32(chip->PRAMDAC0, 0x00000508);
+    state->vpll2        = NV_RD32(chip->PRAMDAC0, 0x00000520);
+    state->pllsel       = NV_RD32(chip->PRAMDAC0, 0x0000050C);
+    state->general      = NV_RD32(chip->PRAMDAC, 0x00000600);
+    state->scale        = NV_RD32(chip->PRAMDAC, 0x00000848);
+    state->config       = NV_RD32(chip->PFB, 0x00000200);
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_03:
+            state->offset0  = NV_RD32(chip->PGRAPH, 0x00000630);
+            state->offset1  = NV_RD32(chip->PGRAPH, 0x00000634);
+            state->offset2  = NV_RD32(chip->PGRAPH, 0x00000638);
+            state->offset3  = NV_RD32(chip->PGRAPH, 0x0000063C);
+            state->pitch0   = NV_RD32(chip->PGRAPH, 0x00000650);
+            state->pitch1   = NV_RD32(chip->PGRAPH, 0x00000654);
+            state->pitch2   = NV_RD32(chip->PGRAPH, 0x00000658);
+            state->pitch3   = NV_RD32(chip->PGRAPH, 0x0000065C);
+            break;
+        case NV_ARCH_04:
+            state->offset0  = NV_RD32(chip->PGRAPH, 0x00000640);
+            state->offset1  = NV_RD32(chip->PGRAPH, 0x00000644);
+            state->offset2  = NV_RD32(chip->PGRAPH, 0x00000648);
+            state->offset3  = NV_RD32(chip->PGRAPH, 0x0000064C);
+            state->pitch0   = NV_RD32(chip->PGRAPH, 0x00000670);
+            state->pitch1   = NV_RD32(chip->PGRAPH, 0x00000674);
+            state->pitch2   = NV_RD32(chip->PGRAPH, 0x00000678);
+            state->pitch3   = NV_RD32(chip->PGRAPH, 0x0000067C);
+            break;
+        case NV_ARCH_10:
+        case NV_ARCH_20:
+        case NV_ARCH_30:
+            state->offset0  = NV_RD32(chip->PGRAPH, 0x00000640);
+            state->offset1  = NV_RD32(chip->PGRAPH, 0x00000644);
+            state->offset2  = NV_RD32(chip->PGRAPH, 0x00000648);
+            state->offset3  = NV_RD32(chip->PGRAPH, 0x0000064C);
+            state->pitch0   = NV_RD32(chip->PGRAPH, 0x00000670);
+            state->pitch1   = NV_RD32(chip->PGRAPH, 0x00000674);
+            state->pitch2   = NV_RD32(chip->PGRAPH, 0x00000678);
+            state->pitch3   = NV_RD32(chip->PGRAPH, 0x0000067C);
+            if(chip->twoHeads) {
+               state->head     = NV_RD32(chip->PCRTC0, 0x00000860);
+               state->head2    = NV_RD32(chip->PCRTC0, 0x00002860);
+               VGA_WR08(chip->PCIO, 0x03D4, 0x44);
+               state->crtcOwner = VGA_RD08(chip->PCIO, 0x03D5);
+            }
+            VGA_WR08(chip->PCIO, 0x03D4, 0x41);
+            state->extra = VGA_RD08(chip->PCIO, 0x03D5);
+            state->cursorConfig = NV_RD32(chip->PCRTC, 0x00000810);
+
+            if((chip->Chipset & 0x0ff0) == 0x0110) {
+                state->dither = NV_RD32(chip->PRAMDAC, 0x0528);
+            } else 
+            if((chip->Chipset & 0x0ff0) >= 0x0170) {
+                state->dither = NV_RD32(chip->PRAMDAC, 0x083C);
+            }
+            break;
+    }
+}
+static void SetStartAddress
+(
+    RIVA_HW_INST *chip,
+    unsigned      start
+)
+{
+    NV_WR32(chip->PCRTC, 0x800, start);
+}
+
+static void SetStartAddress3
+(
+    RIVA_HW_INST *chip,
+    unsigned      start
+)
+{
+    int offset = start >> 2;
+    int pan    = (start & 3) << 1;
+    unsigned char tmp;
+
+    /*
+     * Unlock extended registers.
+     */
+    chip->LockUnlock(chip, 0);
+    /*
+     * Set start address.
+     */
+    VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
+    offset >>= 8;
+    VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
+    offset >>= 8;
+    VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
+    VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
+    /*
+     * 4 pixel pan register.
+     */
+    offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
+    VGA_WR08(chip->PCIO, 0x3C0, 0x13);
+    VGA_WR08(chip->PCIO, 0x3C0, pan);
+}
+static void nv3SetSurfaces2D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface __iomem *Surface =
+	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,5);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
+    NV_WR32(&Surface->Offset, 0, surf0);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
+    NV_WR32(&Surface->Offset, 0, surf1);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000013);
+}
+static void nv4SetSurfaces2D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface __iomem *Surface =
+	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
+    NV_WR32(&Surface->Offset, 0, surf0);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
+    NV_WR32(&Surface->Offset, 0, surf1);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+static void nv10SetSurfaces2D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface __iomem *Surface =
+	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
+    NV_WR32(&Surface->Offset, 0, surf0);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
+    NV_WR32(&Surface->Offset, 0, surf1);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+static void nv3SetSurfaces3D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface __iomem *Surface =
+	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,5);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000005);
+    NV_WR32(&Surface->Offset, 0, surf0);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000006);
+    NV_WR32(&Surface->Offset, 0, surf1);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000013);
+}
+static void nv4SetSurfaces3D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface __iomem *Surface =
+	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000005);
+    NV_WR32(&Surface->Offset, 0, surf0);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000006);
+    NV_WR32(&Surface->Offset, 0, surf1);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+static void nv10SetSurfaces3D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface3D __iomem *Surfaces3D =
+	(RivaSurface3D __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,4);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000007);
+    NV_WR32(&Surfaces3D->RenderBufferOffset, 0, surf0);
+    NV_WR32(&Surfaces3D->ZBufferOffset, 0, surf1);
+    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+
+/****************************************************************************\
+*                                                                            *
+*                      Probe RIVA Chip Configuration                         *
+*                                                                            *
+\****************************************************************************/
+
+static void nv3GetConfig
+(
+    RIVA_HW_INST *chip
+)
+{
+    /*
+     * Fill in chip configuration.
+     */
+    if (NV_RD32(&chip->PFB[0x00000000/4], 0) & 0x00000020)
+    {
+        if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
+         && ((NV_RD32(chip->PMC, 0x00000000) & 0x0F) >= 0x02))
+        {        
+            /*
+             * SDRAM 128 ZX.
+             */
+            chip->RamBandwidthKBytesPerSec = 800000;
+            switch (NV_RD32(chip->PFB, 0x00000000) & 0x03)
+            {
+                case 2:
+                    chip->RamAmountKBytes = 1024 * 4;
+                    break;
+                case 1:
+                    chip->RamAmountKBytes = 1024 * 2;
+                    break;
+                default:
+                    chip->RamAmountKBytes = 1024 * 8;
+                    break;
+            }
+        }            
+        else            
+        {
+            chip->RamBandwidthKBytesPerSec = 1000000;
+            chip->RamAmountKBytes          = 1024 * 8;
+        }            
+    }
+    else
+    {
+        /*
+         * SGRAM 128.
+         */
+        chip->RamBandwidthKBytesPerSec = 1000000;
+        switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003)
+        {
+            case 0:
+                chip->RamAmountKBytes = 1024 * 8;
+                break;
+            case 2:
+                chip->RamAmountKBytes = 1024 * 4;
+                break;
+            default:
+                chip->RamAmountKBytes = 1024 * 2;
+                break;
+        }
+    }        
+    chip->CrystalFreqKHz   = (NV_RD32(chip->PEXTDEV, 0x00000000) & 0x00000040) ? 14318 : 13500;
+    chip->CURSOR           = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
+    chip->VBlankBit        = 0x00000100;
+    chip->MaxVClockFreqKHz = 256000;
+    /*
+     * Set chip functions.
+     */
+    chip->Busy            = nv3Busy;
+    chip->ShowHideCursor  = ShowHideCursor;
+    chip->LoadStateExt    = LoadStateExt;
+    chip->UnloadStateExt  = UnloadStateExt;
+    chip->SetStartAddress = SetStartAddress3;
+    chip->SetSurfaces2D   = nv3SetSurfaces2D;
+    chip->SetSurfaces3D   = nv3SetSurfaces3D;
+    chip->LockUnlock      = nv3LockUnlock;
+}
+static void nv4GetConfig
+(
+    RIVA_HW_INST *chip
+)
+{
+    /*
+     * Fill in chip configuration.
+     */
+    if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100)
+    {
+        chip->RamAmountKBytes = ((NV_RD32(chip->PFB, 0x00000000) >> 12) & 0x0F) * 1024 * 2
+                              + 1024 * 2;
+    }
+    else
+    {
+        switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003)
+        {
+            case 0:
+                chip->RamAmountKBytes = 1024 * 32;
+                break;
+            case 1:
+                chip->RamAmountKBytes = 1024 * 4;
+                break;
+            case 2:
+                chip->RamAmountKBytes = 1024 * 8;
+                break;
+            case 3:
+            default:
+                chip->RamAmountKBytes = 1024 * 16;
+                break;
+        }
+    }
+    switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003)
+    {
+        case 3:
+            chip->RamBandwidthKBytesPerSec = 800000;
+            break;
+        default:
+            chip->RamBandwidthKBytesPerSec = 1000000;
+            break;
+    }
+    chip->CrystalFreqKHz   = (NV_RD32(chip->PEXTDEV, 0x00000000) & 0x00000040) ? 14318 : 13500;
+    chip->CURSOR           = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
+    chip->VBlankBit        = 0x00000001;
+    chip->MaxVClockFreqKHz = 350000;
+    /*
+     * Set chip functions.
+     */
+    chip->Busy            = nv4Busy;
+    chip->ShowHideCursor  = ShowHideCursor;
+    chip->LoadStateExt    = LoadStateExt;
+    chip->UnloadStateExt  = UnloadStateExt;
+    chip->SetStartAddress = SetStartAddress;
+    chip->SetSurfaces2D   = nv4SetSurfaces2D;
+    chip->SetSurfaces3D   = nv4SetSurfaces3D;
+    chip->LockUnlock      = nv4LockUnlock;
+}
+static void nv10GetConfig
+(
+    RIVA_HW_INST *chip,
+    unsigned int chipset
+)
+{
+    struct pci_dev* dev;
+    u32 amt;
+
+#ifdef __BIG_ENDIAN
+    /* turn on big endian register access */
+    if(!(NV_RD32(chip->PMC, 0x00000004) & 0x01000001))
+    	NV_WR32(chip->PMC, 0x00000004, 0x01000001);
+#endif
+
+    /*
+     * Fill in chip configuration.
+     */
+    if(chipset == NV_CHIP_IGEFORCE2) {
+        dev = pci_get_bus_and_slot(0, 1);
+        pci_read_config_dword(dev, 0x7C, &amt);
+        pci_dev_put(dev);
+        chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+    } else if(chipset == NV_CHIP_0x01F0) {
+        dev = pci_get_bus_and_slot(0, 1);
+        pci_read_config_dword(dev, 0x84, &amt);
+        pci_dev_put(dev);
+        chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+    } else {
+        switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & 0x000000FF)
+        {
+            case 0x02:
+                chip->RamAmountKBytes = 1024 * 2;
+                break;
+            case 0x04:
+                chip->RamAmountKBytes = 1024 * 4;
+                break;
+            case 0x08:
+                chip->RamAmountKBytes = 1024 * 8;
+                break;
+            case 0x10:
+                chip->RamAmountKBytes = 1024 * 16;
+                break;
+            case 0x20:
+                chip->RamAmountKBytes = 1024 * 32;
+                break;
+            case 0x40:
+                chip->RamAmountKBytes = 1024 * 64;
+                break;
+            case 0x80:
+                chip->RamAmountKBytes = 1024 * 128;
+                break;
+            default:
+                chip->RamAmountKBytes = 1024 * 16;
+                break;
+        }
+    }
+    switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003)
+    {
+        case 3:
+            chip->RamBandwidthKBytesPerSec = 800000;
+            break;
+        default:
+            chip->RamBandwidthKBytesPerSec = 1000000;
+            break;
+    }
+    chip->CrystalFreqKHz = (NV_RD32(chip->PEXTDEV, 0x0000) & (1 << 6)) ?
+	14318 : 13500;
+
+    switch (chipset & 0x0ff0) {
+    case 0x0170:
+    case 0x0180:
+    case 0x01F0:
+    case 0x0250:
+    case 0x0280:
+    case 0x0300:
+    case 0x0310:
+    case 0x0320:
+    case 0x0330:
+    case 0x0340:
+       if(NV_RD32(chip->PEXTDEV, 0x0000) & (1 << 22))
+           chip->CrystalFreqKHz = 27000;
+       break;
+    default:
+       break;
+    }
+
+    chip->CursorStart      = (chip->RamAmountKBytes - 128) * 1024;
+    chip->CURSOR           = NULL;  /* can't set this here */
+    chip->VBlankBit        = 0x00000001;
+    chip->MaxVClockFreqKHz = 350000;
+    /*
+     * Set chip functions.
+     */
+    chip->Busy            = nv10Busy;
+    chip->ShowHideCursor  = ShowHideCursor;
+    chip->LoadStateExt    = LoadStateExt;
+    chip->UnloadStateExt  = UnloadStateExt;
+    chip->SetStartAddress = SetStartAddress;
+    chip->SetSurfaces2D   = nv10SetSurfaces2D;
+    chip->SetSurfaces3D   = nv10SetSurfaces3D;
+    chip->LockUnlock      = nv4LockUnlock;
+
+    switch(chipset & 0x0ff0) {
+    case 0x0110:
+    case 0x0170:
+    case 0x0180:
+    case 0x01F0:
+    case 0x0250:
+    case 0x0280:
+    case 0x0300:
+    case 0x0310:
+    case 0x0320:
+    case 0x0330:
+    case 0x0340:
+        chip->twoHeads = TRUE;
+        break;
+    default:
+        chip->twoHeads = FALSE;
+        break;
+    }
+}
+int RivaGetConfig
+(
+    RIVA_HW_INST *chip,
+    unsigned int chipset
+)
+{
+    /*
+     * Save this so future SW know whats it's dealing with.
+     */
+    chip->Version = RIVA_SW_VERSION;
+    /*
+     * Chip specific configuration.
+     */
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_03:
+            nv3GetConfig(chip);
+            break;
+        case NV_ARCH_04:
+            nv4GetConfig(chip);
+            break;
+        case NV_ARCH_10:
+        case NV_ARCH_20:
+        case NV_ARCH_30:
+            nv10GetConfig(chip, chipset);
+            break;
+        default:
+            return (-1);
+    }
+    chip->Chipset = chipset;
+    /*
+     * Fill in FIFO pointers.
+     */
+    chip->Rop    = (RivaRop __iomem         *)&(chip->FIFO[0x00000000/4]);
+    chip->Clip   = (RivaClip __iomem        *)&(chip->FIFO[0x00002000/4]);
+    chip->Patt   = (RivaPattern __iomem     *)&(chip->FIFO[0x00004000/4]);
+    chip->Pixmap = (RivaPixmap __iomem      *)&(chip->FIFO[0x00006000/4]);
+    chip->Blt    = (RivaScreenBlt __iomem   *)&(chip->FIFO[0x00008000/4]);
+    chip->Bitmap = (RivaBitmap __iomem      *)&(chip->FIFO[0x0000A000/4]);
+    chip->Line   = (RivaLine __iomem        *)&(chip->FIFO[0x0000C000/4]);
+    chip->Tri03  = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
+    return (0);
+}
+
diff --git a/drivers/video/fbdev/riva/riva_hw.h b/drivers/video/fbdev/riva/riva_hw.h
new file mode 100644
index 000000000000..c2769f73e0b2
--- /dev/null
+++ b/drivers/video/fbdev/riva/riva_hw.h
@@ -0,0 +1,563 @@
+/***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+\***************************************************************************/
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.21 2002/10/14 18:22:46 mvojkovi Exp $ */
+#ifndef __RIVA_HW_H__
+#define __RIVA_HW_H__
+#define RIVA_SW_VERSION 0x00010003
+
+#ifndef Bool
+typedef int Bool;
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * Typedefs to force certain sized values.
+ */
+typedef unsigned char  U008;
+typedef unsigned short U016;
+typedef unsigned int   U032;
+
+/*
+ * HW access macros.
+ */
+#include <asm/io.h>
+
+#define NV_WR08(p,i,d)  (__raw_writeb((d), (void __iomem *)(p) + (i)))
+#define NV_RD08(p,i)    (__raw_readb((void __iomem *)(p) + (i)))
+#define NV_WR16(p,i,d)  (__raw_writew((d), (void __iomem *)(p) + (i)))
+#define NV_RD16(p,i)    (__raw_readw((void __iomem *)(p) + (i)))
+#define NV_WR32(p,i,d)  (__raw_writel((d), (void __iomem *)(p) + (i)))
+#define NV_RD32(p,i)    (__raw_readl((void __iomem *)(p) + (i)))
+
+#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
+#define VGA_RD08(p,i)   (readb((void __iomem *)(p) + (i)))
+
+/*
+ * Define different architectures.
+ */
+#define NV_ARCH_03  0x03
+#define NV_ARCH_04  0x04
+#define NV_ARCH_10  0x10
+#define NV_ARCH_20  0x20
+#define NV_ARCH_30  0x30
+#define NV_ARCH_40  0x40
+
+/***************************************************************************\
+*                                                                           *
+*                             FIFO registers.                               *
+*                                                                           *
+\***************************************************************************/
+
+/*
+ * Raster OPeration. Windows style ROP3.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BB];
+    U032 Rop3;
+} RivaRop;
+/*
+ * 8X8 Monochrome pattern.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BD];
+    U032 Shape;
+    U032 reserved03[0x001];
+    U032 Color0;
+    U032 Color1;
+    U032 Monochrome[2];
+} RivaPattern;
+/*
+ * Scissor clip rectangle.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BB];
+    U032 TopLeft;
+    U032 WidthHeight;
+} RivaClip;
+/*
+ * 2D filled rectangle.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop[1];
+#endif
+    U032 reserved01[0x0BC];
+    U032 Color;
+    U032 reserved03[0x03E];
+    U032 TopLeft;
+    U032 WidthHeight;
+} RivaRectangle;
+/*
+ * 2D screen-screen BLT.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BB];
+    U032 TopLeftSrc;
+    U032 TopLeftDst;
+    U032 WidthHeight;
+} RivaScreenBlt;
+/*
+ * 2D pixel BLT.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop[1];
+#endif
+    U032 reserved01[0x0BC];
+    U032 TopLeft;
+    U032 WidthHeight;
+    U032 WidthHeightIn;
+    U032 reserved02[0x03C];
+    U032 Pixels;
+} RivaPixmap;
+/*
+ * Filled rectangle combined with monochrome expand.  Useful for glyphs.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BB];
+    U032 reserved03[(0x040)-1];
+    U032 Color1A;
+    struct
+    {
+        U032 TopLeft;
+        U032 WidthHeight;
+    } UnclippedRectangle[64];
+    U032 reserved04[(0x080)-3];
+    struct
+    {
+        U032 TopLeft;
+        U032 BottomRight;
+    } ClipB;
+    U032 Color1B;
+    struct
+    {
+        U032 TopLeft;
+        U032 BottomRight;
+    } ClippedRectangle[64];
+    U032 reserved05[(0x080)-5];
+    struct
+    {
+        U032 TopLeft;
+        U032 BottomRight;
+    } ClipC;
+    U032 Color1C;
+    U032 WidthHeightC;
+    U032 PointC;
+    U032 MonochromeData1C;
+    U032 reserved06[(0x080)+121];
+    struct
+    {
+        U032 TopLeft;
+        U032 BottomRight;
+    } ClipD;
+    U032 Color1D;
+    U032 WidthHeightInD;
+    U032 WidthHeightOutD;
+    U032 PointD;
+    U032 MonochromeData1D;
+    U032 reserved07[(0x080)+120];
+    struct
+    {
+        U032 TopLeft;
+        U032 BottomRight;
+    } ClipE;
+    U032 Color0E;
+    U032 Color1E;
+    U032 WidthHeightInE;
+    U032 WidthHeightOutE;
+    U032 PointE;
+    U032 MonochromeData01E;
+} RivaBitmap;
+/*
+ * 3D textured, Z buffered triangle.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BC];
+    U032 TextureOffset;
+    U032 TextureFormat;
+    U032 TextureFilter;
+    U032 FogColor;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+    U032 Control;
+    U032 AlphaTest;
+    U032 reserved02[0x339];
+    U032 FogAndIndex;
+    U032 Color;
+    float ScreenX;
+    float ScreenY;
+    float ScreenZ;
+    float EyeM;
+    float TextureS;
+    float TextureT;
+} RivaTexturedTriangle03;
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BB];
+    U032 ColorKey;
+    U032 TextureOffset;
+    U032 TextureFormat;
+    U032 TextureFilter;
+    U032 Blend;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+    U032 Control;
+    U032 FogColor;
+    U032 reserved02[0x39];
+    struct
+    {
+        float ScreenX;
+        float ScreenY;
+        float ScreenZ;
+        float EyeM;
+        U032 Color;
+        U032 Specular;
+        float TextureS;
+        float TextureT;
+    } Vertex[16];
+    U032 DrawTriangle3D;
+} RivaTexturedTriangle05;
+/*
+ * 2D line.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop[1];
+#endif
+    U032 reserved01[0x0BC];
+    U032 Color;             /* source color               0304-0307*/
+    U032 Reserved02[0x03e];
+    struct {                /* start aliased methods in array   0400-    */
+        U032 point0;        /* y_x S16_S16 in pixels            0-   3*/
+        U032 point1;        /* y_x S16_S16 in pixels            4-   7*/
+    } Lin[16];              /* end of aliased methods in array      -047f*/
+    struct {                /* start aliased methods in array   0480-    */
+        U032 point0X;       /* in pixels, 0 at left                0-   3*/
+        U032 point0Y;       /* in pixels, 0 at top                 4-   7*/
+        U032 point1X;       /* in pixels, 0 at left                8-   b*/
+        U032 point1Y;       /* in pixels, 0 at top                 c-   f*/
+    } Lin32[8];             /* end of aliased methods in array      -04ff*/
+    U032 PolyLin[32];       /* y_x S16_S16 in pixels         0500-057f*/
+    struct {                /* start aliased methods in array   0580-    */
+        U032 x;             /* in pixels, 0 at left                0-   3*/
+        U032 y;             /* in pixels, 0 at top                 4-   7*/
+    } PolyLin32[16];        /* end of aliased methods in array      -05ff*/
+    struct {                /* start aliased methods in array   0600-    */
+        U032 color;         /* source color                     0-   3*/
+        U032 point;         /* y_x S16_S16 in pixels            4-   7*/
+    } ColorPolyLin[16];     /* end of aliased methods in array      -067f*/
+} RivaLine;
+/*
+ * 2D/3D surfaces
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BE];
+    U032 Offset;
+} RivaSurface;
+typedef volatile struct
+{
+    U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
+    U016 FifoFree;
+    U016 Nop;
+#endif
+    U032 reserved01[0x0BD];
+    U032 Pitch;
+    U032 RenderBufferOffset;
+    U032 ZBufferOffset;
+} RivaSurface3D;
+    
+/***************************************************************************\
+*                                                                           *
+*                        Virtualized RIVA H/W interface.                    *
+*                                                                           *
+\***************************************************************************/
+
+#define FP_ENABLE  1
+#define FP_DITHER  2
+
+struct _riva_hw_inst;
+struct _riva_hw_state;
+/*
+ * Virtialized chip interface. Makes RIVA 128 and TNT look alike.
+ */
+typedef struct _riva_hw_inst
+{
+    /*
+     * Chip specific settings.
+     */
+    U032 Architecture;
+    U032 Version;
+    U032 Chipset;
+    U032 CrystalFreqKHz;
+    U032 RamAmountKBytes;
+    U032 MaxVClockFreqKHz;
+    U032 RamBandwidthKBytesPerSec;
+    U032 EnableIRQ;
+    U032 IO;
+    U032 VBlankBit;
+    U032 FifoFreeCount;
+    U032 FifoEmptyCount;
+    U032 CursorStart;
+    U032 flatPanel;
+    Bool twoHeads;
+    /*
+     * Non-FIFO registers.
+     */
+    volatile U032 __iomem *PCRTC0;
+    volatile U032 __iomem *PCRTC;
+    volatile U032 __iomem *PRAMDAC0;
+    volatile U032 __iomem *PFB;
+    volatile U032 __iomem *PFIFO;
+    volatile U032 __iomem *PGRAPH;
+    volatile U032 __iomem *PEXTDEV;
+    volatile U032 __iomem *PTIMER;
+    volatile U032 __iomem *PMC;
+    volatile U032 __iomem *PRAMIN;
+    volatile U032 __iomem *FIFO;
+    volatile U032 __iomem *CURSOR;
+    volatile U008 __iomem *PCIO0;
+    volatile U008 __iomem *PCIO;
+    volatile U008 __iomem *PVIO;
+    volatile U008 __iomem *PDIO0;
+    volatile U008 __iomem *PDIO;
+    volatile U032 __iomem *PRAMDAC;
+    /*
+     * Common chip functions.
+     */
+    int  (*Busy)(struct _riva_hw_inst *);
+    void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
+    void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
+    void (*SetStartAddress)(struct _riva_hw_inst *,U032);
+    void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032);
+    void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032);
+    int  (*ShowHideCursor)(struct _riva_hw_inst *,int);
+    void (*LockUnlock)(struct _riva_hw_inst *, int);
+    /*
+     * Current extended mode settings.
+     */
+    struct _riva_hw_state *CurrentState;
+    /*
+     * FIFO registers.
+     */
+    RivaRop                 __iomem *Rop;
+    RivaPattern             __iomem *Patt;
+    RivaClip                __iomem *Clip;
+    RivaPixmap              __iomem *Pixmap;
+    RivaScreenBlt           __iomem *Blt;
+    RivaBitmap              __iomem *Bitmap;
+    RivaLine                __iomem *Line;
+    RivaTexturedTriangle03  __iomem *Tri03;
+    RivaTexturedTriangle05  __iomem *Tri05;
+} RIVA_HW_INST;
+/*
+ * Extended mode state information.
+ */
+typedef struct _riva_hw_state
+{
+    U032 bpp;
+    U032 width;
+    U032 height;
+    U032 interlace;
+    U032 repaint0;
+    U032 repaint1;
+    U032 screen;
+    U032 scale;
+    U032 dither;
+    U032 extra;
+    U032 pixel;
+    U032 horiz;
+    U032 arbitration0;
+    U032 arbitration1;
+    U032 vpll;
+    U032 vpll2;
+    U032 pllsel;
+    U032 general;
+    U032 crtcOwner;
+    U032 head; 
+    U032 head2; 
+    U032 config;
+    U032 cursorConfig;	
+    U032 cursor0;
+    U032 cursor1;
+    U032 cursor2;
+    U032 offset0;
+    U032 offset1;
+    U032 offset2;
+    U032 offset3;
+    U032 pitch0;
+    U032 pitch1;
+    U032 pitch2;
+    U032 pitch3;
+} RIVA_HW_STATE;
+
+/*
+ * function prototypes
+ */
+
+extern int CalcStateExt
+(
+    RIVA_HW_INST  *chip,
+    RIVA_HW_STATE *state,
+    int            bpp,
+    int            width,
+    int            hDisplaySize,
+    int            height,
+    int            dotClock
+);
+
+/*
+ * External routines.
+ */
+int RivaGetConfig(RIVA_HW_INST *, unsigned int);
+/*
+ * FIFO Free Count. Should attempt to yield processor if RIVA is busy.
+ */
+
+#define RIVA_FIFO_FREE(hwinst,hwptr,cnt)                            \
+{                                                                   \
+    while ((hwinst).FifoFreeCount < (cnt)) {                        \
+	mb();mb();						    \
+        (hwinst).FifoFreeCount = NV_RD32(&(hwinst).hwptr->FifoFree, 0) >> 2;     \
+    }								    \
+    (hwinst).FifoFreeCount -= (cnt);                                \
+}
+#endif /* __RIVA_HW_H__ */
+
diff --git a/drivers/video/fbdev/riva/riva_tbl.h b/drivers/video/fbdev/riva/riva_tbl.h
new file mode 100644
index 000000000000..7ee7d72932d4
--- /dev/null
+++ b/drivers/video/fbdev/riva/riva_tbl.h
@@ -0,0 +1,1008 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.9 2002/01/30 01:35:03 mvojkovi Exp $ */
+
+
+/*
+ * RIVA Fixed Functionality Init Tables.
+ */
+static unsigned RivaTablePMC[][2] =
+{
+    {0x00000050, 0x00000000},
+    {0x00000080, 0xFFFF00FF},
+    {0x00000080, 0xFFFFFFFF}
+};
+static unsigned RivaTablePTIMER[][2] =
+{
+    {0x00000080, 0x00000008},
+    {0x00000084, 0x00000003},
+    {0x00000050, 0x00000000},
+    {0x00000040, 0xFFFFFFFF}
+};
+static unsigned RivaTableFIFO[][2] =
+{
+    {0x00000000, 0x80000000},
+    {0x00000800, 0x80000001},
+    {0x00001000, 0x80000002},
+    {0x00001800, 0x80000010},
+    {0x00002000, 0x80000011},
+    {0x00002800, 0x80000012},
+    {0x00003000, 0x80000016},
+    {0x00003800, 0x80000013}
+};
+static unsigned nv3TablePFIFO[][2] =
+{
+    {0x00000140, 0x00000000},
+    {0x00000480, 0x00000000},
+    {0x00000490, 0x00000000},
+    {0x00000494, 0x00000000},
+    {0x00000481, 0x00000000},
+    {0x00000084, 0x00000000},
+    {0x00000086, 0x00002000},
+    {0x00000085, 0x00002200},
+    {0x00000484, 0x00000000},
+    {0x0000049C, 0x00000000},
+    {0x00000104, 0x00000000},
+    {0x00000108, 0x00000000},
+    {0x00000100, 0x00000000},
+    {0x000004A0, 0x00000000},
+    {0x000004A4, 0x00000000},
+    {0x000004A8, 0x00000000},
+    {0x000004AC, 0x00000000},
+    {0x000004B0, 0x00000000},
+    {0x000004B4, 0x00000000},
+    {0x000004B8, 0x00000000},
+    {0x000004BC, 0x00000000},
+    {0x00000050, 0x00000000},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000480, 0x00000001},
+    {0x00000490, 0x00000001},
+    {0x00000140, 0x00000001}
+};
+static unsigned nv3TablePGRAPH[][2] =
+{
+    {0x00000020, 0x1230001F},
+    {0x00000021, 0x10113000},
+    {0x00000022, 0x1131F101},
+    {0x00000023, 0x0100F531},
+    {0x00000060, 0x00000000},
+    {0x00000065, 0x00000000},
+    {0x00000068, 0x00000000},
+    {0x00000069, 0x00000000},
+    {0x0000006A, 0x00000000},
+    {0x0000006B, 0x00000000},
+    {0x0000006C, 0x00000000},
+    {0x0000006D, 0x00000000},
+    {0x0000006E, 0x00000000},
+    {0x0000006F, 0x00000000},
+    {0x000001A8, 0x00000000},
+    {0x00000440, 0xFFFFFFFF},
+    {0x00000480, 0x00000001},
+    {0x000001A0, 0x00000000},
+    {0x000001A2, 0x00000000},
+    {0x0000018A, 0xFFFFFFFF},
+    {0x00000190, 0x00000000},
+    {0x00000142, 0x00000000},
+    {0x00000154, 0x00000000},
+    {0x00000155, 0xFFFFFFFF},
+    {0x00000156, 0x00000000},
+    {0x00000157, 0xFFFFFFFF},
+    {0x00000064, 0x10010002},
+    {0x00000050, 0x00000000},
+    {0x00000051, 0x00000000},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000041, 0xFFFFFFFF},
+    {0x00000440, 0xFFFFFFFF},
+    {0x000001A9, 0x00000001}
+};
+static unsigned nv3TablePGRAPH_8BPP[][2] =
+{
+    {0x000001AA, 0x00001111}
+};
+static unsigned nv3TablePGRAPH_15BPP[][2] =
+{
+    {0x000001AA, 0x00002222}
+};
+static unsigned nv3TablePGRAPH_32BPP[][2] =
+{
+    {0x000001AA, 0x00003333}
+};
+static unsigned nv3TablePRAMIN[][2] =
+{
+    {0x00000500, 0x00010000},
+    {0x00000501, 0x007FFFFF},
+    {0x00000200, 0x80000000},
+    {0x00000201, 0x00C20341},
+    {0x00000204, 0x80000001},
+    {0x00000205, 0x00C50342},
+    {0x00000208, 0x80000002},
+    {0x00000209, 0x00C60343},
+    {0x0000020C, 0x80000003},
+    {0x0000020D, 0x00DC0348},
+    {0x00000210, 0x80000004},
+    {0x00000211, 0x00DC0349},
+    {0x00000214, 0x80000005},
+    {0x00000215, 0x00DC034A},
+    {0x00000218, 0x80000006},
+    {0x00000219, 0x00DC034B},
+    {0x00000240, 0x80000010},
+    {0x00000241, 0x00D10344},
+    {0x00000244, 0x80000011},
+    {0x00000245, 0x00D00345},
+    {0x00000248, 0x80000012},
+    {0x00000249, 0x00CC0346},
+    {0x0000024C, 0x80000013},
+    {0x0000024D, 0x00D70347},
+    {0x00000258, 0x80000016},
+    {0x00000259, 0x00CA034C},
+    {0x00000D05, 0x00000000},
+    {0x00000D06, 0x00000000},
+    {0x00000D07, 0x00000000},
+    {0x00000D09, 0x00000000},
+    {0x00000D0A, 0x00000000},
+    {0x00000D0B, 0x00000000},
+    {0x00000D0D, 0x00000000},
+    {0x00000D0E, 0x00000000},
+    {0x00000D0F, 0x00000000},
+    {0x00000D11, 0x00000000},
+    {0x00000D12, 0x00000000},
+    {0x00000D13, 0x00000000},
+    {0x00000D15, 0x00000000},
+    {0x00000D16, 0x00000000},
+    {0x00000D17, 0x00000000},
+    {0x00000D19, 0x00000000},
+    {0x00000D1A, 0x00000000},
+    {0x00000D1B, 0x00000000},
+    {0x00000D1D, 0x00000140},
+    {0x00000D1E, 0x00000000},
+    {0x00000D1F, 0x00000000},
+    {0x00000D20, 0x10100200},
+    {0x00000D21, 0x00000000},
+    {0x00000D22, 0x00000000},
+    {0x00000D23, 0x00000000},
+    {0x00000D24, 0x10210200},
+    {0x00000D25, 0x00000000},
+    {0x00000D26, 0x00000000},
+    {0x00000D27, 0x00000000},
+    {0x00000D28, 0x10420200},
+    {0x00000D29, 0x00000000},
+    {0x00000D2A, 0x00000000},
+    {0x00000D2B, 0x00000000},
+    {0x00000D2C, 0x10830200},
+    {0x00000D2D, 0x00000000},
+    {0x00000D2E, 0x00000000},
+    {0x00000D2F, 0x00000000},
+    {0x00000D31, 0x00000000},
+    {0x00000D32, 0x00000000},
+    {0x00000D33, 0x00000000}
+};
+static unsigned nv3TablePRAMIN_8BPP[][2] =
+{
+    /*           0xXXXXX3XX For  MSB mono format */
+    /*           0xXXXXX2XX For  LSB mono format */
+    {0x00000D04, 0x10110203},
+    {0x00000D08, 0x10110203},
+    {0x00000D0C, 0x1011020B},
+    {0x00000D10, 0x10118203},
+    {0x00000D14, 0x10110203},
+    {0x00000D18, 0x10110203},
+    {0x00000D1C, 0x10419208},
+    {0x00000D30, 0x10118203}
+};
+static unsigned nv3TablePRAMIN_15BPP[][2] =
+{
+    /*           0xXXXXX2XX For  MSB mono format */
+    /*           0xXXXXX3XX For  LSB mono format */
+    {0x00000D04, 0x10110200},
+    {0x00000D08, 0x10110200},
+    {0x00000D0C, 0x10110208},
+    {0x00000D10, 0x10118200},
+    {0x00000D14, 0x10110200},
+    {0x00000D18, 0x10110200},
+    {0x00000D1C, 0x10419208},
+    {0x00000D30, 0x10118200}
+};
+static unsigned nv3TablePRAMIN_32BPP[][2] =
+{
+    /*           0xXXXXX3XX For  MSB mono format */
+    /*           0xXXXXX2XX For  LSB mono format */
+    {0x00000D04, 0x10110201},
+    {0x00000D08, 0x10110201},
+    {0x00000D0C, 0x10110209},
+    {0x00000D10, 0x10118201},
+    {0x00000D14, 0x10110201},
+    {0x00000D18, 0x10110201},
+    {0x00000D1C, 0x10419208},
+    {0x00000D30, 0x10118201}
+};
+static unsigned nv4TableFIFO[][2] =
+{
+    {0x00003800, 0x80000014}
+};
+static unsigned nv4TablePFIFO[][2] =
+{
+    {0x00000140, 0x00000000},
+    {0x00000480, 0x00000000},
+    {0x00000494, 0x00000000},
+    {0x00000481, 0x00000000},
+    {0x0000048B, 0x00000000},
+    {0x00000400, 0x00000000},
+    {0x00000414, 0x00000000},
+    {0x00000084, 0x03000100},  
+    {0x00000085, 0x00000110},
+    {0x00000086, 0x00000112},  
+    {0x00000143, 0x0000FFFF},
+    {0x00000496, 0x0000FFFF},
+    {0x00000050, 0x00000000},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000415, 0x00000001},
+    {0x00000480, 0x00000001},
+    {0x00000494, 0x00000001},
+    {0x00000495, 0x00000001},
+    {0x00000140, 0x00000001}
+};
+static unsigned nv4TablePGRAPH[][2] =
+{
+    {0x00000020, 0x1231C001},
+    {0x00000021, 0x72111101},
+    {0x00000022, 0x11D5F071},
+    {0x00000023, 0x10D4FF31},
+    {0x00000060, 0x00000000},
+    {0x00000068, 0x00000000},
+    {0x00000070, 0x00000000},
+    {0x00000078, 0x00000000},
+    {0x00000061, 0x00000000},
+    {0x00000069, 0x00000000},
+    {0x00000071, 0x00000000},
+    {0x00000079, 0x00000000},
+    {0x00000062, 0x00000000},
+    {0x0000006A, 0x00000000},
+    {0x00000072, 0x00000000},
+    {0x0000007A, 0x00000000},
+    {0x00000063, 0x00000000},
+    {0x0000006B, 0x00000000},
+    {0x00000073, 0x00000000},
+    {0x0000007B, 0x00000000},
+    {0x00000064, 0x00000000},
+    {0x0000006C, 0x00000000},
+    {0x00000074, 0x00000000},
+    {0x0000007C, 0x00000000},
+    {0x00000065, 0x00000000},
+    {0x0000006D, 0x00000000},
+    {0x00000075, 0x00000000},
+    {0x0000007D, 0x00000000},
+    {0x00000066, 0x00000000},
+    {0x0000006E, 0x00000000},
+    {0x00000076, 0x00000000},
+    {0x0000007E, 0x00000000},
+    {0x00000067, 0x00000000},
+    {0x0000006F, 0x00000000},
+    {0x00000077, 0x00000000},
+    {0x0000007F, 0x00000000},
+    {0x00000058, 0x00000000},
+    {0x00000059, 0x00000000},
+    {0x0000005A, 0x00000000},
+    {0x0000005B, 0x00000000},
+    {0x00000196, 0x00000000},
+    {0x000001A1, 0x01FFFFFF},
+    {0x00000197, 0x00000000},
+    {0x000001A2, 0x01FFFFFF},
+    {0x00000198, 0x00000000},
+    {0x000001A3, 0x01FFFFFF},
+    {0x00000199, 0x00000000},
+    {0x000001A4, 0x01FFFFFF},
+    {0x00000050, 0x00000000},
+    {0x00000040, 0xFFFFFFFF},
+    {0x0000005C, 0x10010100},
+    {0x000001C4, 0xFFFFFFFF},
+    {0x000001C8, 0x00000001},
+    {0x00000204, 0x00000000},
+    {0x000001C3, 0x00000001}
+};
+static unsigned nv4TablePGRAPH_8BPP[][2] =
+{
+    {0x000001C9, 0x00111111},
+    {0x00000186, 0x00001010},
+    {0x0000020C, 0x03020202}
+};
+static unsigned nv4TablePGRAPH_15BPP[][2] =
+{
+    {0x000001C9, 0x00226222},
+    {0x00000186, 0x00002071},
+    {0x0000020C, 0x09080808}
+};
+static unsigned nv4TablePGRAPH_16BPP[][2] =
+{
+    {0x000001C9, 0x00556555},
+    {0x00000186, 0x000050C2},
+    {0x0000020C, 0x0C0B0B0B}
+};
+static unsigned nv4TablePGRAPH_32BPP[][2] =
+{
+    {0x000001C9, 0x0077D777},
+    {0x00000186, 0x000070E5},
+    {0x0000020C, 0x0E0D0D0D}
+};
+static unsigned nv4TablePRAMIN[][2] =
+{
+    {0x00000000, 0x80000010},
+    {0x00000001, 0x80011145},
+    {0x00000002, 0x80000011},
+    {0x00000003, 0x80011146},
+    {0x00000004, 0x80000012},
+    {0x00000005, 0x80011147},
+    {0x00000006, 0x80000013},
+    {0x00000007, 0x80011148},
+    {0x00000008, 0x80000014},
+    {0x00000009, 0x80011149},
+    {0x0000000A, 0x80000015},
+    {0x0000000B, 0x8001114A},
+    {0x0000000C, 0x80000016},
+    {0x0000000D, 0x8001114F},
+    {0x00000020, 0x80000000},
+    {0x00000021, 0x80011142},
+    {0x00000022, 0x80000001},
+    {0x00000023, 0x80011143},
+    {0x00000024, 0x80000002},
+    {0x00000025, 0x80011144}, 
+    {0x00000026, 0x80000003},
+    {0x00000027, 0x8001114B},
+    {0x00000028, 0x80000004},
+    {0x00000029, 0x8001114C},
+    {0x0000002A, 0x80000005},
+    {0x0000002B, 0x8001114D},
+    {0x0000002C, 0x80000006},
+    {0x0000002D, 0x8001114E},
+    {0x00000500, 0x00003000},
+    {0x00000501, 0x01FFFFFF},
+    {0x00000502, 0x00000002},
+    {0x00000503, 0x00000002},
+    {0x00000508, 0x01008043},
+    {0x0000050A, 0x00000000},
+    {0x0000050B, 0x00000000},
+    {0x0000050C, 0x01008019},
+    {0x0000050E, 0x00000000},
+    {0x0000050F, 0x00000000},
+#if 1
+    {0x00000510, 0x01008018},
+#else
+    {0x00000510, 0x01008044},
+#endif
+    {0x00000512, 0x00000000},
+    {0x00000513, 0x00000000},
+    {0x00000514, 0x01008021},
+    {0x00000516, 0x00000000},
+    {0x00000517, 0x00000000},
+    {0x00000518, 0x0100805F},
+    {0x0000051A, 0x00000000},
+    {0x0000051B, 0x00000000},
+#if 1
+    {0x0000051C, 0x0100804B},
+#else
+    {0x0000051C, 0x0100804A},
+#endif
+    {0x0000051E, 0x00000000},
+    {0x0000051F, 0x00000000},
+    {0x00000520, 0x0100A048},
+    {0x00000521, 0x00000D01},
+    {0x00000522, 0x11401140},
+    {0x00000523, 0x00000000},
+    {0x00000524, 0x0300A054},
+    {0x00000525, 0x00000D01},
+    {0x00000526, 0x11401140},
+    {0x00000527, 0x00000000},
+    {0x00000528, 0x0300A055},
+    {0x00000529, 0x00000D01},
+    {0x0000052A, 0x11401140},
+    {0x0000052B, 0x00000000},
+    {0x0000052C, 0x00000058},
+    {0x0000052E, 0x11401140},
+    {0x0000052F, 0x00000000},
+    {0x00000530, 0x00000059},
+    {0x00000532, 0x11401140},
+    {0x00000533, 0x00000000},
+    {0x00000534, 0x0000005A},
+    {0x00000536, 0x11401140},
+    {0x00000537, 0x00000000},
+    {0x00000538, 0x0000005B},
+    {0x0000053A, 0x11401140},
+    {0x0000053B, 0x00000000},
+    {0x0000053C, 0x0300A01C},
+    {0x0000053E, 0x11401140},
+    {0x0000053F, 0x00000000}
+};
+static unsigned nv4TablePRAMIN_8BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000302},
+    {0x0000050D, 0x00000302},
+    {0x00000511, 0x00000202},
+    {0x00000515, 0x00000302},
+    {0x00000519, 0x00000302},
+    {0x0000051D, 0x00000302},
+    {0x0000052D, 0x00000302},
+    {0x0000052E, 0x00000302},
+    {0x00000535, 0x00000000},
+    {0x00000539, 0x00000000},
+    {0x0000053D, 0x00000302}
+};
+static unsigned nv4TablePRAMIN_15BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000902},
+    {0x0000050D, 0x00000902},
+    {0x00000511, 0x00000802},
+    {0x00000515, 0x00000902},
+    {0x00000519, 0x00000902},
+    {0x0000051D, 0x00000902},
+    {0x0000052D, 0x00000902},
+    {0x0000052E, 0x00000902},
+    {0x00000535, 0x00000702},
+    {0x00000539, 0x00000702},
+    {0x0000053D, 0x00000902}
+};
+static unsigned nv4TablePRAMIN_16BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000C02},
+    {0x0000050D, 0x00000C02},
+    {0x00000511, 0x00000B02},
+    {0x00000515, 0x00000C02},
+    {0x00000519, 0x00000C02},
+    {0x0000051D, 0x00000C02},
+    {0x0000052D, 0x00000C02},
+    {0x0000052E, 0x00000C02},
+    {0x00000535, 0x00000702},
+    {0x00000539, 0x00000702},
+    {0x0000053D, 0x00000C02}
+};
+static unsigned nv4TablePRAMIN_32BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000E02},
+    {0x0000050D, 0x00000E02},
+    {0x00000511, 0x00000D02},
+    {0x00000515, 0x00000E02},
+    {0x00000519, 0x00000E02},
+    {0x0000051D, 0x00000E02},
+    {0x0000052D, 0x00000E02},
+    {0x0000052E, 0x00000E02},
+    {0x00000535, 0x00000E02},
+    {0x00000539, 0x00000E02},
+    {0x0000053D, 0x00000E02}
+};
+static unsigned nv10TableFIFO[][2] =
+{
+    {0x00003800, 0x80000014}
+};
+static unsigned nv10TablePFIFO[][2] =
+{
+    {0x00000140, 0x00000000},
+    {0x00000480, 0x00000000},
+    {0x00000494, 0x00000000},
+    {0x00000481, 0x00000000},
+    {0x0000048B, 0x00000000},
+    {0x00000400, 0x00000000},
+    {0x00000414, 0x00000000},
+    {0x00000084, 0x03000100},
+    {0x00000085, 0x00000110},
+    {0x00000086, 0x00000112},
+    {0x00000143, 0x0000FFFF},
+    {0x00000496, 0x0000FFFF},
+    {0x00000050, 0x00000000},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000415, 0x00000001},
+    {0x00000480, 0x00000001},
+    {0x00000494, 0x00000001},
+    {0x00000495, 0x00000001},
+    {0x00000140, 0x00000001}
+};
+static unsigned nv10TablePGRAPH[][2] =
+{
+    {0x00000020, 0x0003FFFF},
+    {0x00000021, 0x00118701},
+    {0x00000022, 0x24F82AD9},
+    {0x00000023, 0x55DE0030},
+    {0x00000020, 0x00000000},
+    {0x00000024, 0x00000000},
+    {0x00000058, 0x00000000},
+    {0x00000060, 0x00000000},
+    {0x00000068, 0x00000000},
+    {0x00000070, 0x00000000},
+    {0x00000078, 0x00000000},
+    {0x00000059, 0x00000000},
+    {0x00000061, 0x00000000},
+    {0x00000069, 0x00000000},
+    {0x00000071, 0x00000000},
+    {0x00000079, 0x00000000},
+    {0x0000005A, 0x00000000},
+    {0x00000062, 0x00000000},
+    {0x0000006A, 0x00000000},
+    {0x00000072, 0x00000000},
+    {0x0000007A, 0x00000000},
+    {0x0000005B, 0x00000000},
+    {0x00000063, 0x00000000},
+    {0x0000006B, 0x00000000},
+    {0x00000073, 0x00000000},
+    {0x0000007B, 0x00000000},
+    {0x0000005C, 0x00000000},
+    {0x00000064, 0x00000000},
+    {0x0000006C, 0x00000000},
+    {0x00000074, 0x00000000},
+    {0x0000007C, 0x00000000},
+    {0x0000005D, 0x00000000},
+    {0x00000065, 0x00000000},
+    {0x0000006D, 0x00000000},
+    {0x00000075, 0x00000000},
+    {0x0000007D, 0x00000000},
+    {0x0000005E, 0x00000000},
+    {0x00000066, 0x00000000},
+    {0x0000006E, 0x00000000},
+    {0x00000076, 0x00000000},
+    {0x0000007E, 0x00000000},
+    {0x0000005F, 0x00000000},
+    {0x00000067, 0x00000000},
+    {0x0000006F, 0x00000000},
+    {0x00000077, 0x00000000},
+    {0x0000007F, 0x00000000},
+    {0x00000053, 0x00000000},
+    {0x00000054, 0x00000000},
+    {0x00000055, 0x00000000},
+    {0x00000056, 0x00000000},
+    {0x00000057, 0x00000000},
+    {0x00000196, 0x00000000},
+    {0x000001A1, 0x01FFFFFF},
+    {0x00000197, 0x00000000},
+    {0x000001A2, 0x01FFFFFF},
+    {0x00000198, 0x00000000},
+    {0x000001A3, 0x01FFFFFF},
+    {0x00000199, 0x00000000},
+    {0x000001A4, 0x01FFFFFF},
+    {0x0000019A, 0x00000000},
+    {0x000001A5, 0x01FFFFFF},
+    {0x0000019B, 0x00000000},
+    {0x000001A6, 0x01FFFFFF},
+    {0x00000050, 0x01111111},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000051, 0x10010100},
+    {0x000001C5, 0xFFFFFFFF},
+    {0x000001C8, 0x00000001},
+    {0x00000204, 0x00000000},
+    {0x000001C4, 0x00000001}
+};
+static unsigned nv10TablePGRAPH_8BPP[][2] =
+{
+    {0x000001C9, 0x00111111},
+    {0x00000186, 0x00001010},
+    {0x0000020C, 0x03020202}
+};
+static unsigned nv10TablePGRAPH_15BPP[][2] =
+{
+    {0x000001C9, 0x00226222},
+    {0x00000186, 0x00002071},
+    {0x0000020C, 0x09080808}
+};
+static unsigned nv10TablePGRAPH_16BPP[][2] =
+{
+    {0x000001C9, 0x00556555},
+    {0x00000186, 0x000050C2},
+    {0x0000020C, 0x000B0B0C}
+};
+static unsigned nv10TablePGRAPH_32BPP[][2] =
+{
+    {0x000001C9, 0x0077D777},
+    {0x00000186, 0x000070E5},
+    {0x0000020C, 0x0E0D0D0D}
+};
+static unsigned nv10tri05TablePGRAPH[][2] =
+{
+    {(0x00000E00/4), 0x00000000},
+    {(0x00000E04/4), 0x00000000},
+    {(0x00000E08/4), 0x00000000},
+    {(0x00000E0C/4), 0x00000000},
+    {(0x00000E10/4), 0x00001000},
+    {(0x00000E14/4), 0x00001000},
+    {(0x00000E18/4), 0x4003ff80},
+    {(0x00000E1C/4), 0x00000000},
+    {(0x00000E20/4), 0x00000000},
+    {(0x00000E24/4), 0x00000000},
+    {(0x00000E28/4), 0x00000000},
+    {(0x00000E2C/4), 0x00000000},
+    {(0x00000E30/4), 0x00080008},
+    {(0x00000E34/4), 0x00080008},
+    {(0x00000E38/4), 0x00000000},
+    {(0x00000E3C/4), 0x00000000},
+    {(0x00000E40/4), 0x00000000},
+    {(0x00000E44/4), 0x00000000},
+    {(0x00000E48/4), 0x00000000},
+    {(0x00000E4C/4), 0x00000000},
+    {(0x00000E50/4), 0x00000000},
+    {(0x00000E54/4), 0x00000000},
+    {(0x00000E58/4), 0x00000000},
+    {(0x00000E5C/4), 0x00000000},
+    {(0x00000E60/4), 0x00000000},
+    {(0x00000E64/4), 0x10000000},
+    {(0x00000E68/4), 0x00000000},
+    {(0x00000E6C/4), 0x00000000},
+    {(0x00000E70/4), 0x00000000},
+    {(0x00000E74/4), 0x00000000},
+    {(0x00000E78/4), 0x00000000},
+    {(0x00000E7C/4), 0x00000000},
+    {(0x00000E80/4), 0x00000000},
+    {(0x00000E84/4), 0x00000000},
+    {(0x00000E88/4), 0x08000000},
+    {(0x00000E8C/4), 0x00000000},
+    {(0x00000E90/4), 0x00000000},
+    {(0x00000E94/4), 0x00000000},
+    {(0x00000E98/4), 0x00000000},
+    {(0x00000E9C/4), 0x4B7FFFFF},
+    {(0x00000EA0/4), 0x00000000},
+    {(0x00000EA4/4), 0x00000000},
+    {(0x00000EA8/4), 0x00000000},
+    {(0x00000F00/4), 0x07FF0800},
+    {(0x00000F04/4), 0x07FF0800},
+    {(0x00000F08/4), 0x07FF0800},
+    {(0x00000F0C/4), 0x07FF0800},
+    {(0x00000F10/4), 0x07FF0800},
+    {(0x00000F14/4), 0x07FF0800},
+    {(0x00000F18/4), 0x07FF0800},
+    {(0x00000F1C/4), 0x07FF0800},
+    {(0x00000F20/4), 0x07FF0800},
+    {(0x00000F24/4), 0x07FF0800},
+    {(0x00000F28/4), 0x07FF0800},
+    {(0x00000F2C/4), 0x07FF0800},
+    {(0x00000F30/4), 0x07FF0800},
+    {(0x00000F34/4), 0x07FF0800},
+    {(0x00000F38/4), 0x07FF0800},
+    {(0x00000F3C/4), 0x07FF0800},
+    {(0x00000F40/4), 0x10000000},
+    {(0x00000F44/4), 0x00000000},
+    {(0x00000F50/4), 0x00006740},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006750},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F50/4), 0x00006760},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006770},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006780},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000067A0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AB0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AC0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006C10},
+    {(0x00000F54/4), 0xBF800000},
+    {(0x00000F50/4), 0x00007030},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007040},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007050},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007060},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007070},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007080},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007090},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x000070A0},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00006A80},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AA0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00000040},
+    {(0x00000F54/4), 0x00000005},
+    {(0x00000F50/4), 0x00006400},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x4B7FFFFF},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006410},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006420},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006430},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064C0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x477FFFFF},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x000064D0},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064E0},
+    {(0x00000F54/4), 0xC4FFF000},
+    {(0x00000F54/4), 0xC4FFF000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064F0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F40/4), 0x30000000},
+    {(0x00000F44/4), 0x00000004},
+    {(0x00000F48/4), 0x10000000},
+    {(0x00000F4C/4), 0x00000000}
+};
+static unsigned nv10TablePRAMIN[][2] =
+{
+    {0x00000000, 0x80000010},
+    {0x00000001, 0x80011145},
+    {0x00000002, 0x80000011},
+    {0x00000003, 0x80011146},
+    {0x00000004, 0x80000012},
+    {0x00000005, 0x80011147},
+    {0x00000006, 0x80000013},
+    {0x00000007, 0x80011148},
+    {0x00000008, 0x80000014},
+    {0x00000009, 0x80011149},
+    {0x0000000A, 0x80000015},
+    {0x0000000B, 0x8001114A},
+    {0x0000000C, 0x80000016},
+    {0x0000000D, 0x80011150},
+    {0x00000020, 0x80000000},
+    {0x00000021, 0x80011142},
+    {0x00000022, 0x80000001},
+    {0x00000023, 0x80011143},
+    {0x00000024, 0x80000002},
+    {0x00000025, 0x80011144},
+    {0x00000026, 0x80000003},
+    {0x00000027, 0x8001114B},
+    {0x00000028, 0x80000004},
+    {0x00000029, 0x8001114C},
+    {0x0000002A, 0x80000005},
+    {0x0000002B, 0x8001114D},
+    {0x0000002C, 0x80000006},
+    {0x0000002D, 0x8001114E},
+    {0x0000002E, 0x80000007},
+    {0x0000002F, 0x8001114F},
+    {0x00000500, 0x00003000},
+    {0x00000501, 0x01FFFFFF},
+    {0x00000502, 0x00000002},
+    {0x00000503, 0x00000002},
+#ifdef __BIG_ENDIAN
+    {0x00000508, 0x01088043}, 
+#else
+    {0x00000508, 0x01008043},
+#endif
+    {0x0000050A, 0x00000000},
+    {0x0000050B, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x0000050C, 0x01088019},
+#else
+    {0x0000050C, 0x01008019},
+#endif
+    {0x0000050E, 0x00000000},
+    {0x0000050F, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000510, 0x01088018},
+#else
+    {0x00000510, 0x01008018},
+#endif
+    {0x00000512, 0x00000000},
+    {0x00000513, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000514, 0x01088021},
+#else
+    {0x00000514, 0x01008021},
+#endif
+    {0x00000516, 0x00000000},
+    {0x00000517, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000518, 0x0108805F},
+#else
+    {0x00000518, 0x0100805F},
+#endif
+    {0x0000051A, 0x00000000},
+    {0x0000051B, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x0000051C, 0x0108804B},
+#else
+    {0x0000051C, 0x0100804B},
+#endif
+    {0x0000051E, 0x00000000},
+    {0x0000051F, 0x00000000},
+    {0x00000520, 0x0100A048},
+    {0x00000521, 0x00000D01},
+    {0x00000522, 0x11401140},
+    {0x00000523, 0x00000000},
+    {0x00000524, 0x0300A094},
+    {0x00000525, 0x00000D01},
+    {0x00000526, 0x11401140},
+    {0x00000527, 0x00000000},
+    {0x00000528, 0x0300A095},
+    {0x00000529, 0x00000D01},
+    {0x0000052A, 0x11401140},
+    {0x0000052B, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x0000052C, 0x00080058},
+#else
+    {0x0000052C, 0x00000058},
+#endif
+    {0x0000052E, 0x11401140},
+    {0x0000052F, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000530, 0x00080059},
+#else
+    {0x00000530, 0x00000059},
+#endif
+    {0x00000532, 0x11401140},
+    {0x00000533, 0x00000000},
+    {0x00000534, 0x0000005A},
+    {0x00000536, 0x11401140},
+    {0x00000537, 0x00000000},
+    {0x00000538, 0x0000005B},
+    {0x0000053A, 0x11401140},
+    {0x0000053B, 0x00000000},
+    {0x0000053C, 0x00000093},
+    {0x0000053E, 0x11401140},
+    {0x0000053F, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000540, 0x0308A01C},
+#else
+    {0x00000540, 0x0300A01C},
+#endif
+    {0x00000542, 0x11401140},
+    {0x00000543, 0x00000000}
+};
+static unsigned nv10TablePRAMIN_8BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000302},
+    {0x0000050D, 0x00000302},
+    {0x00000511, 0x00000202},
+    {0x00000515, 0x00000302},
+    {0x00000519, 0x00000302},
+    {0x0000051D, 0x00000302},
+    {0x0000052D, 0x00000302},
+    {0x0000052E, 0x00000302},
+    {0x00000535, 0x00000000},
+    {0x00000539, 0x00000000},
+    {0x0000053D, 0x00000000},
+    {0x00000541, 0x00000302}
+};
+static unsigned nv10TablePRAMIN_15BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000902},
+    {0x0000050D, 0x00000902},
+    {0x00000511, 0x00000802},
+    {0x00000515, 0x00000902},
+    {0x00000519, 0x00000902},
+    {0x0000051D, 0x00000902},
+    {0x0000052D, 0x00000902},
+    {0x0000052E, 0x00000902},
+    {0x00000535, 0x00000902},
+    {0x00000539, 0x00000902}, 
+    {0x0000053D, 0x00000902},
+    {0x00000541, 0x00000902}
+};
+static unsigned nv10TablePRAMIN_16BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000C02},
+    {0x0000050D, 0x00000C02},
+    {0x00000511, 0x00000B02},
+    {0x00000515, 0x00000C02},
+    {0x00000519, 0x00000C02},
+    {0x0000051D, 0x00000C02},
+    {0x0000052D, 0x00000C02},
+    {0x0000052E, 0x00000C02},
+    {0x00000535, 0x00000C02},
+    {0x00000539, 0x00000C02},
+    {0x0000053D, 0x00000C02},
+    {0x00000541, 0x00000C02}
+};
+static unsigned nv10TablePRAMIN_32BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000E02},
+    {0x0000050D, 0x00000E02},
+    {0x00000511, 0x00000D02},
+    {0x00000515, 0x00000E02},
+    {0x00000519, 0x00000E02},
+    {0x0000051D, 0x00000E02},
+    {0x0000052D, 0x00000E02},
+    {0x0000052E, 0x00000E02},
+    {0x00000535, 0x00000E02},
+    {0x00000539, 0x00000E02},
+    {0x0000053D, 0x00000E02},
+    {0x00000541, 0x00000E02}
+};
+
diff --git a/drivers/video/fbdev/riva/rivafb-i2c.c b/drivers/video/fbdev/riva/rivafb-i2c.c
new file mode 100644
index 000000000000..6a183375ced1
--- /dev/null
+++ b/drivers/video/fbdev/riva/rivafb-i2c.c
@@ -0,0 +1,166 @@
+/*
+ * linux/drivers/video/riva/fbdev-i2c.c - nVidia i2c
+ *
+ * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on radeonfb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+#include <linux/jiffies.h>
+
+#include <asm/io.h>
+
+#include "rivafb.h"
+#include "../edid.h"
+
+static void riva_gpio_setscl(void* data, int state)
+{
+	struct riva_i2c_chan 	*chan = data;
+	struct riva_par 	*par = chan->par;
+	u32			val;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x20;
+	else
+		val &= ~0x20;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
+}
+
+static void riva_gpio_setsda(void* data, int state)
+{
+	struct riva_i2c_chan 	*chan = data;
+	struct riva_par 	*par = chan->par;
+	u32			val;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x10;
+	else
+		val &= ~0x10;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
+}
+
+static int riva_gpio_getscl(void* data)
+{
+	struct riva_i2c_chan 	*chan = data;
+	struct riva_par 	*par = chan->par;
+	u32			val = 0;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04)
+		val = 1;
+
+	return val;
+}
+
+static int riva_gpio_getsda(void* data)
+{
+	struct riva_i2c_chan 	*chan = data;
+	struct riva_par 	*par = chan->par;
+	u32			val = 0;
+
+	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x08)
+		val = 1;
+
+	return val;
+}
+
+static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name,
+			      unsigned int i2c_class)
+{
+	int rc;
+
+	strcpy(chan->adapter.name, name);
+	chan->adapter.owner		= THIS_MODULE;
+	chan->adapter.class		= i2c_class;
+	chan->adapter.algo_data		= &chan->algo;
+	chan->adapter.dev.parent	= &chan->par->pdev->dev;
+	chan->algo.setsda		= riva_gpio_setsda;
+	chan->algo.setscl		= riva_gpio_setscl;
+	chan->algo.getsda		= riva_gpio_getsda;
+	chan->algo.getscl		= riva_gpio_getscl;
+	chan->algo.udelay		= 40;
+	chan->algo.timeout		= msecs_to_jiffies(2);
+	chan->algo.data 		= chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	/* Raise SCL and SDA */
+	riva_gpio_setsda(chan, 1);
+	riva_gpio_setscl(chan, 1);
+	udelay(20);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		dev_dbg(&chan->par->pdev->dev, "I2C bus %s registered.\n", name);
+	else {
+		dev_warn(&chan->par->pdev->dev,
+			 "Failed to register I2C bus %s.\n", name);
+		chan->par = NULL;
+	}
+
+	return rc;
+}
+
+void riva_create_i2c_busses(struct riva_par *par)
+{
+	par->chan[0].par	= par;
+	par->chan[1].par	= par;
+	par->chan[2].par        = par;
+
+	par->chan[0].ddc_base = 0x36;
+	par->chan[1].ddc_base = 0x3e;
+	par->chan[2].ddc_base = 0x50;
+	riva_setup_i2c_bus(&par->chan[0], "BUS1", I2C_CLASS_HWMON);
+	riva_setup_i2c_bus(&par->chan[1], "BUS2", 0);
+	riva_setup_i2c_bus(&par->chan[2], "BUS3", 0);
+}
+
+void riva_delete_i2c_busses(struct riva_par *par)
+{
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		if (!par->chan[i].par)
+			continue;
+		i2c_del_adapter(&par->chan[i].adapter);
+		par->chan[i].par = NULL;
+	}
+}
+
+int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
+{
+	u8 *edid = NULL;
+
+	if (par->chan[conn].par)
+		edid = fb_ddc_read(&par->chan[conn].adapter);
+
+	if (out_edid)
+		*out_edid = edid;
+	if (!edid)
+		return 1;
+
+	return 0;
+}
+
diff --git a/drivers/video/fbdev/riva/rivafb.h b/drivers/video/fbdev/riva/rivafb.h
new file mode 100644
index 000000000000..d9f107b704c6
--- /dev/null
+++ b/drivers/video/fbdev/riva/rivafb.h
@@ -0,0 +1,77 @@
+#ifndef __RIVAFB_H
+#define __RIVAFB_H
+
+#include <linux/fb.h>
+#include <video/vga.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "riva_hw.h"
+
+/* GGI compatibility macros */
+#define NUM_SEQ_REGS		0x05
+#define NUM_CRT_REGS		0x41
+#define NUM_GRC_REGS		0x09
+#define NUM_ATC_REGS		0x15
+
+/* I2C */
+#define DDC_SCL_READ_MASK       (1 << 2)
+#define DDC_SCL_WRITE_MASK      (1 << 5)
+#define DDC_SDA_READ_MASK       (1 << 3)
+#define DDC_SDA_WRITE_MASK      (1 << 4)
+
+/* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
+ * From KGI originally. */
+struct riva_regs {
+	u8 attr[NUM_ATC_REGS];
+	u8 crtc[NUM_CRT_REGS];
+	u8 gra[NUM_GRC_REGS];
+	u8 seq[NUM_SEQ_REGS];
+	u8 misc_output;
+	RIVA_HW_STATE ext;
+};
+
+struct riva_par;
+
+struct riva_i2c_chan {
+	struct riva_par *par;
+	unsigned long   ddc_base;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+};
+
+struct riva_par {
+	RIVA_HW_INST riva;	/* interface to riva_hw.c */
+	u32 pseudo_palette[16]; /* default palette */
+	u32 palette[16];        /* for Riva128 */
+	u8 __iomem *ctrl_base;	/* virtual control register base addr */
+	unsigned dclk_max;	/* max DCLK */
+
+	struct riva_regs initial_state;	/* initial startup video mode */
+	struct riva_regs current_state;
+#ifdef CONFIG_X86
+	struct vgastate state;
+#endif
+	struct mutex open_lock;
+	unsigned int ref_count;
+	unsigned char *EDID;
+	unsigned int Chipset;
+	int forceCRTC;
+	Bool SecondCRTC;
+	int FlatPanel;
+	struct pci_dev *pdev;
+	int cursor_reset;
+#ifdef CONFIG_MTRR
+	struct { int vram; int vram_valid; } mtrr;
+#endif
+	struct riva_i2c_chan chan[3];
+};
+
+void riva_common_setup(struct riva_par *);
+unsigned long riva_get_memlen(struct riva_par *);
+unsigned long riva_get_maxdclk(struct riva_par *);
+void riva_delete_i2c_busses(struct riva_par *par);
+void riva_create_i2c_busses(struct riva_par *par);
+int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid);
+
+#endif /* __RIVAFB_H */
diff --git a/drivers/video/fbdev/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c
new file mode 100644
index 000000000000..83433cb0dfba
--- /dev/null
+++ b/drivers/video/fbdev/s1d13xxxfb.c
@@ -0,0 +1,1040 @@
+/* drivers/video/s1d13xxxfb.c
+ *
+ * (c) 2004 Simtec Electronics
+ * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ * (c) 2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
+ *
+ * Driver for Epson S1D13xxx series framebuffer chips
+ *
+ * Adapted from
+ *  linux/drivers/video/skeletonfb.c
+ *  linux/drivers/video/epson1355fb.c
+ *  linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson)
+ *
+ * TODO: - handle dual screen display (CRT and LCD at the same time).
+ *	 - check_var(), mode change, etc.
+ *	 - probably not SMP safe :)
+ *       - support all bitblt operations on all cards
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/fb.h>
+#include <linux/spinlock_types.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+
+#include <video/s1d13xxxfb.h>
+
+#define PFX	"s1d13xxxfb: "
+#define BLIT	"s1d13xxxfb_bitblt: "
+
+/*
+ * set this to enable debugging on general functions
+ */
+#if 0
+#define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)
+#else
+#define dbg(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * set this to enable debugging on 2D acceleration
+ */
+#if 0
+#define dbg_blit(fmt, args...) do { printk(KERN_INFO BLIT fmt, ## args); } while (0)
+#else
+#define dbg_blit(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * we make sure only one bitblt operation is running
+ */
+static DEFINE_SPINLOCK(s1d13xxxfb_bitblt_lock);
+
+/*
+ * list of card production ids
+ */
+static const int s1d13xxxfb_prod_ids[] = {
+	S1D13505_PROD_ID,
+	S1D13506_PROD_ID,
+	S1D13806_PROD_ID,
+};
+
+/*
+ * List of card strings
+ */
+static const char *s1d13xxxfb_prod_names[] = {
+	"S1D13505",
+	"S1D13506",
+	"S1D13806",
+};
+
+/*
+ * here we define the default struct fb_fix_screeninfo
+ */
+static struct fb_fix_screeninfo s1d13xxxfb_fix = {
+	.id		= S1D_FBID,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 1,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static inline u8
+s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
+{
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
+	regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
+#endif
+	return readb(par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
+{
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
+	regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
+#endif
+	writeb(value, par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_runinit(struct s1d13xxxfb_par *par,
+			const struct s1d13xxxfb_regval *initregs,
+			const unsigned int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+        	if ((initregs[i].addr == S1DREG_DELAYOFF) ||
+				(initregs[i].addr == S1DREG_DELAYON))
+			mdelay((int)initregs[i].value);
+        	else {
+			s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);
+		}
+        }
+
+	/* make sure the hardware can cope with us */
+	mdelay(1);
+}
+
+static inline void
+lcd_enable(struct s1d13xxxfb_par *par, int enable)
+{
+	u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+	if (enable)
+		mode |= 0x01;
+	else
+		mode &= ~0x01;
+
+	s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+static inline void
+crt_enable(struct s1d13xxxfb_par *par, int enable)
+{
+	u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+	if (enable)
+		mode |= 0x02;
+	else
+		mode &= ~0x02;
+
+	s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+
+/*************************************************************
+ framebuffer control functions
+ *************************************************************/
+static inline void
+s1d13xxxfb_setup_pseudocolour(struct fb_info *info)
+{
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->var.red.length = 4;
+	info->var.green.length = 4;
+	info->var.blue.length = 4;
+}
+
+static inline void
+s1d13xxxfb_setup_truecolour(struct fb_info *info)
+{
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->var.bits_per_pixel = 16;
+
+	info->var.red.length = 5;
+	info->var.red.offset = 11;
+
+	info->var.green.length = 6;
+	info->var.green.offset = 5;
+
+	info->var.blue.length = 5;
+	info->var.blue.offset = 0;
+}
+
+/**
+ *      s1d13xxxfb_set_par - Alters the hardware state.
+ *      @info: frame buffer structure
+ *
+ *	Using the fb_var_screeninfo in fb_info we set the depth of the
+ *	framebuffer. This function alters the par AND the
+ *	fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
+ *	fb_info since we are using that data. This means we depend on the
+ *	data in var inside fb_info to be supported by the hardware.
+ *	xxxfb_check_var is always called before xxxfb_set_par to ensure this.
+ *
+ *	XXX TODO: write proper s1d13xxxfb_check_var(), without which that
+ *	function is quite useless.
+ */
+static int
+s1d13xxxfb_set_par(struct fb_info *info)
+{
+	struct s1d13xxxfb_par *s1dfb = info->par;
+	unsigned int val;
+
+	dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);
+
+	if ((s1dfb->display & 0x01))	/* LCD */
+		val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE);   /* read colour control */
+	else	/* CRT */
+		val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE);   /* read colour control */
+
+	val &= ~0x07;
+
+	switch (info->var.bits_per_pixel) {
+		case 4:
+			dbg("pseudo colour 4\n");
+			s1d13xxxfb_setup_pseudocolour(info);
+			val |= 2;
+			break;
+		case 8:
+			dbg("pseudo colour 8\n");
+			s1d13xxxfb_setup_pseudocolour(info);
+			val |= 3;
+			break;
+		case 16:
+			dbg("true colour\n");
+			s1d13xxxfb_setup_truecolour(info);
+			val |= 5;
+			break;
+
+		default:
+			dbg("bpp not supported!\n");
+			return -EINVAL;
+	}
+
+	dbg("writing %02x to display mode register\n", val);
+
+	if ((s1dfb->display & 0x01))	/* LCD */
+		s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);
+	else	/* CRT */
+		s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);
+
+	info->fix.line_length  = info->var.xres * info->var.bits_per_pixel;
+	info->fix.line_length /= 8;
+
+	dbg("setting line_length to %d\n", info->fix.line_length);
+
+	dbg("done setup\n");
+
+	return 0;
+}
+
+/**
+ *	s1d13xxxfb_setcolreg - sets a color register.
+ *	@regno: Which register in the CLUT we are programming
+ *	@red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *	@info: frame buffer info structure
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			u_int transp, struct fb_info *info)
+{
+	struct s1d13xxxfb_par *s1dfb = info->par;
+	unsigned int pseudo_val;
+
+	if (regno >= S1D_PALETTE_SIZE)
+		return -EINVAL;
+
+	dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",
+		    regno, red, green, blue, transp);
+
+	if (info->var.grayscale)
+		red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;
+
+	switch (info->fix.visual) {
+		case FB_VISUAL_TRUECOLOR:
+			if (regno >= 16)
+				return -EINVAL;
+
+			/* deal with creating pseudo-palette entries */
+
+			pseudo_val  = (red   >> 11) << info->var.red.offset;
+			pseudo_val |= (green >> 10) << info->var.green.offset;
+			pseudo_val |= (blue  >> 11) << info->var.blue.offset;
+
+			dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
+				    regno, pseudo_val);
+
+#if defined(CONFIG_PLAT_MAPPI)
+			((u32 *)info->pseudo_palette)[regno] = cpu_to_le16(pseudo_val);
+#else
+			((u32 *)info->pseudo_palette)[regno] = pseudo_val;
+#endif
+
+			break;
+		case FB_VISUAL_PSEUDOCOLOR:
+			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);
+			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);
+			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);
+			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);
+
+			break;
+		default:
+			return -ENOSYS;
+	}
+
+	dbg("s1d13xxxfb_setcolreg: done\n");
+
+	return 0;
+}
+
+/**
+ *      s1d13xxxfb_blank - blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *      video mode which doesn't support it. Implements VESA suspend
+ *      and powerdown modes on hardware that supports disabling hsync/vsync:
+ *      blank_mode == 2: suspend vsync
+ *      blank_mode == 3: suspend hsync
+ *      blank_mode == 4: powerdown
+ *
+ *      Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct s1d13xxxfb_par *par = info->par;
+
+	dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);
+
+	switch (blank_mode) {
+		case FB_BLANK_UNBLANK:
+		case FB_BLANK_NORMAL:
+			if ((par->display & 0x01) != 0)
+				lcd_enable(par, 1);
+			if ((par->display & 0x02) != 0)
+				crt_enable(par, 1);
+			break;
+		case FB_BLANK_VSYNC_SUSPEND:
+		case FB_BLANK_HSYNC_SUSPEND:
+			break;
+		case FB_BLANK_POWERDOWN:
+			lcd_enable(par, 0);
+			crt_enable(par, 0);
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	/* let fbcon do a soft blank for us */
+	return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
+}
+
+/**
+ *	s1d13xxxfb_pan_display - Pans the display.
+ *	@var: frame buffer variable screen structure
+ *	@info: frame buffer structure that represents a single frame buffer
+ *
+ *	Pan (or wrap, depending on the `vmode' field) the display using the
+ *	`yoffset' field of the `var' structure (`xoffset'  not yet supported).
+ *	If the values don't fit, return -EINVAL.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct s1d13xxxfb_par *par = info->par;
+	u32 start;
+
+	if (var->xoffset != 0)	/* not yet ... */
+		return -EINVAL;
+
+	if (var->yoffset + info->var.yres > info->var.yres_virtual)
+		return -EINVAL;
+
+	start = (info->fix.line_length >> 1) * var->yoffset;
+
+	if ((par->display & 0x01)) {
+		/* LCD */
+		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));
+		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));
+		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));
+	} else {
+		/* CRT */
+		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));
+		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));
+		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));
+	}
+
+	return 0;
+}
+
+/************************************************************
+ functions to handle bitblt acceleration
+ ************************************************************/
+
+/**
+ *	bltbit_wait_bitclear - waits for change in register value
+ *	@info : frambuffer structure
+ *	@bit  : value currently in register
+ *	@timeout : ...
+ *
+ *	waits until value changes FROM bit
+ *
+ */
+static u8
+bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout)
+{
+	while (s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit) {
+		udelay(10);
+		if (!--timeout) {
+			dbg_blit("wait_bitclear timeout\n");
+			break;
+		}
+	}
+
+	return timeout;
+}
+
+/*
+ *	s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
+ *	@info : framebuffer structure
+ *	@area : fb_copyarea structure
+ *
+ *	supports (atleast) S1D13506
+ *
+ */
+static void
+s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	u32 dst, src;
+	u32 stride;
+	u16 reverse = 0;
+	u16 sx = area->sx, sy = area->sy;
+	u16 dx = area->dx, dy = area->dy;
+	u16 width = area->width, height = area->height;
+	u16 bpp;
+
+	spin_lock(&s1d13xxxfb_bitblt_lock);
+
+	/* bytes per xres line */
+	bpp = (info->var.bits_per_pixel >> 3);
+	stride = bpp * info->var.xres;
+
+	/* reverse, calculate the last pixel in rectangle */
+	if ((dy > sy) || ((dy == sy) && (dx >= sx))) {
+		dst = (((dy + height - 1) * stride) + (bpp * (dx + width - 1)));
+		src = (((sy + height - 1) * stride) + (bpp * (sx + width - 1)));
+		reverse = 1;
+	/* not reverse, calculate the first pixel in rectangle */
+	} else { /* (y * xres) + (bpp * x) */
+		dst = (dy * stride) + (bpp * dx);
+		src = (sy * stride) + (bpp * sx);
+	}
+
+	/* set source address */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff));
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff);
+
+	/* set destination address */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff));
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff);
+
+	/* program height and width */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, (width & 0xff) - 1);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (width >> 8));
+
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, (height & 0xff) - 1);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (height >> 8));
+
+	/* negative direction ROP */
+	if (reverse == 1) {
+		dbg_blit("(copyarea) negative rop\n");
+		s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x03);
+	} else /* positive direction ROP */ {
+		s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x02);
+		dbg_blit("(copyarea) positive rop\n");
+	}
+
+	/* set for rectangel mode and not linear */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
+
+	/* setup the bpp 1 = 16bpp, 0 = 8bpp*/
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (bpp >> 1));
+
+	/* set words per xres */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (stride >> 1) & 0xff);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (stride >> 9));
+
+	dbg_blit("(copyarea) dx=%d, dy=%d\n", dx, dy);
+	dbg_blit("(copyarea) sx=%d, sy=%d\n", sx, sy);
+	dbg_blit("(copyarea) width=%d, height=%d\n", width - 1, height - 1);
+	dbg_blit("(copyarea) stride=%d\n", stride);
+	dbg_blit("(copyarea) bpp=%d=0x0%d, mem_offset1=%d, mem_offset2=%d\n", bpp, (bpp >> 1),
+		(stride >> 1) & 0xff, stride >> 9);
+
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CC_EXP, 0x0c);
+
+	/* initialize the engine */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
+
+	/* wait to complete */
+	bltbit_wait_bitclear(info, 0x80, 8000);
+
+	spin_unlock(&s1d13xxxfb_bitblt_lock);
+}
+
+/**
+ *
+ *	s1d13xxxfb_bitblt_solidfill - accelerated solidfill function
+ *	@info : framebuffer structure
+ *	@rect : fb_fillrect structure
+ *
+ *	supports (atleast 13506)
+ *
+ **/
+static void
+s1d13xxxfb_bitblt_solidfill(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u32 screen_stride, dest;
+	u32 fg;
+	u16 bpp = (info->var.bits_per_pixel >> 3);
+
+	/* grab spinlock */
+	spin_lock(&s1d13xxxfb_bitblt_lock);
+
+	/* bytes per x width */
+	screen_stride = (bpp * info->var.xres);
+
+	/* bytes to starting point */
+	dest = ((rect->dy * screen_stride) + (bpp * rect->dx));
+
+	dbg_blit("(solidfill) dx=%d, dy=%d, stride=%d, dest=%d\n"
+		 "(solidfill) : rect_width=%d, rect_height=%d\n",
+				rect->dx, rect->dy, screen_stride, dest,
+				rect->width - 1, rect->height - 1);
+
+	dbg_blit("(solidfill) : xres=%d, yres=%d, bpp=%d\n",
+				info->var.xres, info->var.yres,
+				info->var.bits_per_pixel);
+	dbg_blit("(solidfill) : rop=%d\n", rect->rop);
+
+	/* We split the destination into the three registers */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dest & 0x00ff));
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, ((dest >> 8) & 0x00ff));
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, ((dest >> 16) & 0x00ff));
+
+	/* give information regarding rectangel width */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, ((rect->width) & 0x00ff) - 1);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (rect->width >> 8));
+
+	/* give information regarding rectangel height */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, ((rect->height) & 0x00ff) - 1);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (rect->height >> 8));
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+		info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		fg = ((u32 *)info->pseudo_palette)[rect->color];
+		dbg_blit("(solidfill) truecolor/directcolor\n");
+		dbg_blit("(solidfill) pseudo_palette[%d] = %d\n", rect->color, fg);
+	} else {
+		fg = rect->color;
+		dbg_blit("(solidfill) color = %d\n", rect->color);
+	}
+
+	/* set foreground color */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC0, (fg & 0xff));
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC1, (fg >> 8) & 0xff);
+
+	/* set rectangual region of memory (rectangle and not linear) */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
+
+	/* set operation mode SOLID_FILL */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, BBLT_SOLID_FILL);
+
+	/* set bits per pixel (1 = 16bpp, 0 = 8bpp) */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (info->var.bits_per_pixel >> 4));
+
+	/* set the memory offset for the bblt in word sizes */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (screen_stride >> 1) & 0x00ff);
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (screen_stride >> 9));
+
+	/* and away we go.... */
+	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
+
+	/* wait until its done */
+	bltbit_wait_bitclear(info, 0x80, 8000);
+
+	/* let others play */
+	spin_unlock(&s1d13xxxfb_bitblt_lock);
+}
+
+/* framebuffer information structures */
+static struct fb_ops s1d13xxxfb_fbops = {
+	.owner		= THIS_MODULE,
+	.fb_set_par	= s1d13xxxfb_set_par,
+	.fb_setcolreg	= s1d13xxxfb_setcolreg,
+	.fb_blank	= s1d13xxxfb_blank,
+
+	.fb_pan_display	= s1d13xxxfb_pan_display,
+
+	/* gets replaced at chip detection time */
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int s1d13xxxfb_width_tab[2][4] = {
+	{4, 8, 16, -1},
+	{9, 12, 18, -1},
+};
+
+/**
+ *	s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to
+ *	hardware setup.
+ *	@info: frame buffer structure
+ *
+ *	We setup the framebuffer structures according to the current
+ *	hardware setup. On some machines, the BIOS will have filled
+ *	the chip registers with such info, on others, these values will
+ *	have been written in some init procedure. In any case, the
+ *	software values needs to match the hardware ones. This is what
+ *	this function ensures.
+ *
+ *	Note: some of the hardcoded values here might need some love to
+ *	work on various chips, and might need to no longer be hardcoded.
+ */
+static void s1d13xxxfb_fetch_hw_state(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct s1d13xxxfb_par *par = info->par;
+	u8 panel, display;
+	u16 offset;
+	u32 xres, yres;
+	u32 xres_virtual, yres_virtual;
+	int bpp, lcd_bpp;
+	int is_color, is_dual, is_tft;
+	int lcd_enabled, crt_enabled;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	/* general info */
+	par->display = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+	crt_enabled = (par->display & 0x02) != 0;
+	lcd_enabled = (par->display & 0x01) != 0;
+
+	if (lcd_enabled && crt_enabled)
+		printk(KERN_WARNING PFX "Warning: LCD and CRT detected, using LCD\n");
+
+	if (lcd_enabled)
+		display = s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_MODE);
+	else	/* CRT */
+		display = s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_MODE);
+
+	bpp = display & 0x07;
+
+	switch (bpp) {
+		case 2:	/* 4 bpp */
+		case 3:	/* 8 bpp */
+			var->bits_per_pixel = 8;
+			var->red.offset = var->green.offset = var->blue.offset = 0;
+			var->red.length = var->green.length = var->blue.length = 8;
+			break;
+		case 5:	/* 16 bpp */
+			s1d13xxxfb_setup_truecolour(info);
+			break;
+		default:
+			dbg("bpp: %i\n", bpp);
+	}
+	fb_alloc_cmap(&info->cmap, 256, 0);
+
+	/* LCD info */
+	panel = s1d13xxxfb_readreg(par, S1DREG_PANEL_TYPE);
+	is_color = (panel & 0x04) != 0;
+	is_dual = (panel & 0x02) != 0;
+	is_tft = (panel & 0x01) != 0;
+	lcd_bpp = s1d13xxxfb_width_tab[is_tft][(panel >> 4) & 3];
+
+	if (lcd_enabled) {
+		xres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_HWIDTH) + 1) * 8;
+		yres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT0) +
+			((s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+		offset = (s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF0) +
+			((s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF1) & 0x7) << 8));
+	} else { /* crt */
+		xres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_HWIDTH) + 1) * 8;
+		yres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT0) +
+			((s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+		offset = (s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF0) +
+			((s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF1) & 0x7) << 8));
+	}
+	xres_virtual = offset * 16 / var->bits_per_pixel;
+	yres_virtual = fix->smem_len / (offset * 2);
+
+	var->xres		= xres;
+	var->yres		= yres;
+	var->xres_virtual	= xres_virtual;
+	var->yres_virtual	= yres_virtual;
+	var->xoffset		= var->yoffset = 0;
+
+	fix->line_length	= offset * 2;
+
+	var->grayscale		= !is_color;
+
+	var->activate		= FB_ACTIVATE_NOW;
+
+	dbg(PFX "bpp=%d, lcd_bpp=%d, "
+		"crt_enabled=%d, lcd_enabled=%d\n",
+		var->bits_per_pixel, lcd_bpp, crt_enabled, lcd_enabled);
+	dbg(PFX "xres=%d, yres=%d, vxres=%d, vyres=%d "
+		"is_color=%d, is_dual=%d, is_tft=%d\n",
+		xres, yres, xres_virtual, yres_virtual, is_color, is_dual, is_tft);
+}
+
+
+static int
+s1d13xxxfb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct s1d13xxxfb_par *par = NULL;
+
+	if (info) {
+		par = info->par;
+		if (par && par->regs) {
+			/* disable output & enable powersave */
+			s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, 0x00);
+			s1d13xxxfb_writereg(par, S1DREG_PS_CNF, 0x11);
+			iounmap(par->regs);
+		}
+
+		fb_dealloc_cmap(&info->cmap);
+
+		if (info->screen_base)
+			iounmap(info->screen_base);
+
+		framebuffer_release(info);
+	}
+
+	release_mem_region(pdev->resource[0].start,
+			pdev->resource[0].end - pdev->resource[0].start +1);
+	release_mem_region(pdev->resource[1].start,
+			pdev->resource[1].end - pdev->resource[1].start +1);
+	return 0;
+}
+
+static int s1d13xxxfb_probe(struct platform_device *pdev)
+{
+	struct s1d13xxxfb_par *default_par;
+	struct fb_info *info;
+	struct s1d13xxxfb_pdata *pdata = NULL;
+	int ret = 0;
+	int i;
+	u8 revision, prod_id;
+
+	dbg("probe called: device is %p\n", pdev);
+
+	printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
+
+	/* enable platform-dependent hardware glue, if any */
+	if (dev_get_platdata(&pdev->dev))
+		pdata = dev_get_platdata(&pdev->dev);
+
+	if (pdata && pdata->platform_init_video)
+		pdata->platform_init_video();
+
+	if (pdev->num_resources != 2) {
+		dev_err(&pdev->dev, "invalid num_resources: %i\n",
+		       pdev->num_resources);
+		ret = -ENODEV;
+		goto bail;
+	}
+
+	/* resource[0] is VRAM, resource[1] is registers */
+	if (pdev->resource[0].flags != IORESOURCE_MEM
+			|| pdev->resource[1].flags != IORESOURCE_MEM) {
+		dev_err(&pdev->dev, "invalid resource type\n");
+		ret = -ENODEV;
+		goto bail;
+	}
+
+	if (!request_mem_region(pdev->resource[0].start,
+		pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		ret = -EBUSY;
+		goto bail;
+	}
+
+	if (!request_mem_region(pdev->resource[1].start,
+		pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		ret = -EBUSY;
+		goto bail;
+	}
+
+	info = framebuffer_alloc(sizeof(struct s1d13xxxfb_par) + sizeof(u32) * 256, &pdev->dev);
+	if (!info) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	platform_set_drvdata(pdev, info);
+	default_par = info->par;
+	default_par->regs = ioremap_nocache(pdev->resource[1].start,
+			pdev->resource[1].end - pdev->resource[1].start +1);
+	if (!default_par->regs) {
+		printk(KERN_ERR PFX "unable to map registers\n");
+		ret = -ENOMEM;
+		goto bail;
+	}
+	info->pseudo_palette = default_par->pseudo_palette;
+
+	info->screen_base = ioremap_nocache(pdev->resource[0].start,
+			pdev->resource[0].end - pdev->resource[0].start +1);
+
+	if (!info->screen_base) {
+		printk(KERN_ERR PFX "unable to map framebuffer\n");
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	/* production id is top 6 bits */
+	prod_id = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
+	/* revision id is lower 2 bits */
+	revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) & 0x3;
+	ret = -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_prod_ids); i++) {
+		if (prod_id == s1d13xxxfb_prod_ids[i]) {
+			/* looks like we got it in our list */
+			default_par->prod_id = prod_id;
+			default_par->revision = revision;
+			ret = 0;
+			break;
+		}
+	}
+
+	if (!ret) {
+		printk(KERN_INFO PFX "chip production id %i = %s\n",
+			prod_id, s1d13xxxfb_prod_names[i]);
+		printk(KERN_INFO PFX "chip revision %i\n", revision);
+	} else {
+		printk(KERN_INFO PFX
+			"unknown chip production id %i, revision %i\n",
+			prod_id, revision);
+		printk(KERN_INFO PFX "please contact maintainer\n");
+		goto bail;
+	}
+
+	info->fix = s1d13xxxfb_fix;
+	info->fix.mmio_start = pdev->resource[1].start;
+	info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start + 1;
+	info->fix.smem_start = pdev->resource[0].start;
+	info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+
+	printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n",
+	       default_par->regs, info->fix.smem_len / 1024, info->screen_base);
+
+	info->par = default_par;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	info->fbops = &s1d13xxxfb_fbops;
+
+	switch(prod_id) {
+	case S1D13506_PROD_ID:	/* activate acceleration */
+		s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill;
+		s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+			FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
+		break;
+	default:
+		break;
+	}
+
+	/* perform "manual" chip initialization, if needed */
+	if (pdata && pdata->initregs)
+		s1d13xxxfb_runinit(info->par, pdata->initregs, pdata->initregssize);
+
+	s1d13xxxfb_fetch_hw_state(info);
+
+	if (register_framebuffer(info) < 0) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	return 0;
+
+bail:
+	s1d13xxxfb_remove(pdev);
+	return ret;
+
+}
+
+#ifdef CONFIG_PM
+static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct s1d13xxxfb_par *s1dfb = info->par;
+	struct s1d13xxxfb_pdata *pdata = NULL;
+
+	/* disable display */
+	lcd_enable(s1dfb, 0);
+	crt_enable(s1dfb, 0);
+
+	if (dev_get_platdata(&dev->dev))
+		pdata = dev_get_platdata(&dev->dev);
+
+#if 0
+	if (!s1dfb->disp_save)
+		s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
+
+	if (!s1dfb->disp_save) {
+		printk(KERN_ERR PFX "no memory to save screen");
+		return -ENOMEM;
+	}
+
+	memcpy_fromio(s1dfb->disp_save, info->screen_base, info->fix.smem_len);
+#else
+	s1dfb->disp_save = NULL;
+#endif
+
+	if (!s1dfb->regs_save)
+		s1dfb->regs_save = kmalloc(info->fix.mmio_len, GFP_KERNEL);
+
+	if (!s1dfb->regs_save) {
+		printk(KERN_ERR PFX "no memory to save registers");
+		return -ENOMEM;
+	}
+
+	/* backup all registers */
+	memcpy_fromio(s1dfb->regs_save, s1dfb->regs, info->fix.mmio_len);
+
+	/* now activate power save mode */
+	s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x11);
+
+	if (pdata && pdata->platform_suspend_video)
+		return pdata->platform_suspend_video();
+	else
+		return 0;
+}
+
+static int s1d13xxxfb_resume(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct s1d13xxxfb_par *s1dfb = info->par;
+	struct s1d13xxxfb_pdata *pdata = NULL;
+
+	/* awaken the chip */
+	s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
+
+	/* do not let go until SDRAM "wakes up" */
+	while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
+		udelay(10);
+
+	if (dev_get_platdata(&dev->dev))
+		pdata = dev_get_platdata(&dev->dev);
+
+	if (s1dfb->regs_save) {
+		/* will write RO regs, *should* get away with it :) */
+		memcpy_toio(s1dfb->regs, s1dfb->regs_save, info->fix.mmio_len);
+		kfree(s1dfb->regs_save);
+	}
+
+	if (s1dfb->disp_save) {
+		memcpy_toio(info->screen_base, s1dfb->disp_save,
+				info->fix.smem_len);
+		kfree(s1dfb->disp_save);	/* XXX kmalloc()'d when? */
+	}
+
+	if ((s1dfb->display & 0x01) != 0)
+		lcd_enable(s1dfb, 1);
+	if ((s1dfb->display & 0x02) != 0)
+		crt_enable(s1dfb, 1);
+
+	if (pdata && pdata->platform_resume_video)
+		return pdata->platform_resume_video();
+	else
+		return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct platform_driver s1d13xxxfb_driver = {
+	.probe		= s1d13xxxfb_probe,
+	.remove		= s1d13xxxfb_remove,
+#ifdef CONFIG_PM
+	.suspend	= s1d13xxxfb_suspend,
+	.resume		= s1d13xxxfb_resume,
+#endif
+	.driver		= {
+		.name	= S1D_DEVICENAME,
+	},
+};
+
+
+static int __init
+s1d13xxxfb_init(void)
+{
+
+#ifndef MODULE
+	if (fb_get_options("s1d13xxxfb", NULL))
+		return -ENODEV;
+#endif
+
+	return platform_driver_register(&s1d13xxxfb_driver);
+}
+
+
+static void __exit
+s1d13xxxfb_exit(void)
+{
+	platform_driver_unregister(&s1d13xxxfb_driver);
+}
+
+module_init(s1d13xxxfb_init);
+module_exit(s1d13xxxfb_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Framebuffer driver for S1D13xxx devices");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Thibaut VARENE <varenet@parisc-linux.org>");
diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c
new file mode 100644
index 000000000000..62acae2694a9
--- /dev/null
+++ b/drivers/video/fbdev/s3c-fb.c
@@ -0,0 +1,2049 @@
+/* linux/drivers/video/s3c-fb.c
+ *
+ * Copyright 2008 Openmoko Inc.
+ * Copyright 2008-2010 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Samsung SoC Framebuffer driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software FoundatIon.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_data/video_s3c.h>
+
+#include <video/samsung_fimd.h>
+
+/* This driver will export a number of framebuffer interfaces depending
+ * on the configuration passed in via the platform data. Each fb instance
+ * maps to a hardware window. Currently there is no support for runtime
+ * setting of the alpha-blending functions that each window has, so only
+ * window 0 is actually useful.
+ *
+ * Window 0 is treated specially, it is used for the basis of the LCD
+ * output timings and as the control for the output power-down state.
+*/
+
+/* note, the previous use of <mach/regs-fb.h> to get platform specific data
+ * has been replaced by using the platform device name to pick the correct
+ * configuration data for the system.
+*/
+
+#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
+#undef writel
+#define writel(v, r) do { \
+	pr_debug("%s: %08x => %p\n", __func__, (unsigned int)v, r); \
+	__raw_writel(v, r); \
+} while (0)
+#endif /* FB_S3C_DEBUG_REGWRITE */
+
+/* irq_flags bits */
+#define S3C_FB_VSYNC_IRQ_EN	0
+
+#define VSYNC_TIMEOUT_MSEC 50
+
+struct s3c_fb;
+
+#define VALID_BPP(x) (1 << ((x) - 1))
+
+#define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride))
+#define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00)
+#define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04)
+#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
+#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
+
+/**
+ * struct s3c_fb_variant - fb variant information
+ * @is_2443: Set if S3C2443/S3C2416 style hardware.
+ * @nr_windows: The number of windows.
+ * @vidtcon: The base for the VIDTCONx registers
+ * @wincon: The base for the WINxCON registers.
+ * @winmap: The base for the WINxMAP registers.
+ * @keycon: The abse for the WxKEYCON registers.
+ * @buf_start: Offset of buffer start registers.
+ * @buf_size: Offset of buffer size registers.
+ * @buf_end: Offset of buffer end registers.
+ * @osd: The base for the OSD registers.
+ * @palette: Address of palette memory, or 0 if none.
+ * @has_prtcon: Set if has PRTCON register.
+ * @has_shadowcon: Set if has SHADOWCON register.
+ * @has_blendcon: Set if has BLENDCON register.
+ * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
+ * @has_fixvclk: Set if VIDCON1 register has FIXVCLK bits.
+ */
+struct s3c_fb_variant {
+	unsigned int	is_2443:1;
+	unsigned short	nr_windows;
+	unsigned int	vidtcon;
+	unsigned short	wincon;
+	unsigned short	winmap;
+	unsigned short	keycon;
+	unsigned short	buf_start;
+	unsigned short	buf_end;
+	unsigned short	buf_size;
+	unsigned short	osd;
+	unsigned short	osd_stride;
+	unsigned short	palette[S3C_FB_MAX_WIN];
+
+	unsigned int	has_prtcon:1;
+	unsigned int	has_shadowcon:1;
+	unsigned int	has_blendcon:1;
+	unsigned int	has_clksel:1;
+	unsigned int	has_fixvclk:1;
+};
+
+/**
+ * struct s3c_fb_win_variant
+ * @has_osd_c: Set if has OSD C register.
+ * @has_osd_d: Set if has OSD D register.
+ * @has_osd_alpha: Set if can change alpha transparency for a window.
+ * @palette_sz: Size of palette in entries.
+ * @palette_16bpp: Set if palette is 16bits wide.
+ * @osd_size_off: If != 0, supports setting up OSD for a window; the appropriate
+ *                register is located at the given offset from OSD_BASE.
+ * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel.
+ *
+ * valid_bpp bit x is set if (x+1)BPP is supported.
+ */
+struct s3c_fb_win_variant {
+	unsigned int	has_osd_c:1;
+	unsigned int	has_osd_d:1;
+	unsigned int	has_osd_alpha:1;
+	unsigned int	palette_16bpp:1;
+	unsigned short	osd_size_off;
+	unsigned short	palette_sz;
+	u32		valid_bpp;
+};
+
+/**
+ * struct s3c_fb_driverdata - per-device type driver data for init time.
+ * @variant: The variant information for this driver.
+ * @win: The window information for each window.
+ */
+struct s3c_fb_driverdata {
+	struct s3c_fb_variant	variant;
+	struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN];
+};
+
+/**
+ * struct s3c_fb_palette - palette information
+ * @r: Red bitfield.
+ * @g: Green bitfield.
+ * @b: Blue bitfield.
+ * @a: Alpha bitfield.
+ */
+struct s3c_fb_palette {
+	struct fb_bitfield	r;
+	struct fb_bitfield	g;
+	struct fb_bitfield	b;
+	struct fb_bitfield	a;
+};
+
+/**
+ * struct s3c_fb_win - per window private data for each framebuffer.
+ * @windata: The platform data supplied for the window configuration.
+ * @parent: The hardware that this window is part of.
+ * @fbinfo: Pointer pack to the framebuffer info for this window.
+ * @varint: The variant information for this window.
+ * @palette_buffer: Buffer/cache to hold palette entries.
+ * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
+ * @index: The window number of this window.
+ * @palette: The bitfields for changing r/g/b into a hardware palette entry.
+ */
+struct s3c_fb_win {
+	struct s3c_fb_pd_win	*windata;
+	struct s3c_fb		*parent;
+	struct fb_info		*fbinfo;
+	struct s3c_fb_palette	 palette;
+	struct s3c_fb_win_variant variant;
+
+	u32			*palette_buffer;
+	u32			 pseudo_palette[16];
+	unsigned int		 index;
+};
+
+/**
+ * struct s3c_fb_vsync - vsync information
+ * @wait:	a queue for processes waiting for vsync
+ * @count:	vsync interrupt count
+ */
+struct s3c_fb_vsync {
+	wait_queue_head_t	wait;
+	unsigned int		count;
+};
+
+/**
+ * struct s3c_fb - overall hardware state of the hardware
+ * @slock: The spinlock protection for this data structure.
+ * @dev: The device that we bound to, for printing, etc.
+ * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
+ * @lcd_clk: The clk (sclk) feeding pixclk.
+ * @regs: The mapped hardware registers.
+ * @variant: Variant information for this hardware.
+ * @enabled: A bitmask of enabled hardware windows.
+ * @output_on: Flag if the physical output is enabled.
+ * @pdata: The platform configuration data passed with the device.
+ * @windows: The hardware windows that have been claimed.
+ * @irq_no: IRQ line number
+ * @irq_flags: irq flags
+ * @vsync_info: VSYNC-related information (count, queues...)
+ */
+struct s3c_fb {
+	spinlock_t		slock;
+	struct device		*dev;
+	struct clk		*bus_clk;
+	struct clk		*lcd_clk;
+	void __iomem		*regs;
+	struct s3c_fb_variant	 variant;
+
+	unsigned char		 enabled;
+	bool			 output_on;
+
+	struct s3c_fb_platdata	*pdata;
+	struct s3c_fb_win	*windows[S3C_FB_MAX_WIN];
+
+	int			 irq_no;
+	unsigned long		 irq_flags;
+	struct s3c_fb_vsync	 vsync_info;
+};
+
+/**
+ * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
+ * @win: The device window.
+ * @bpp: The bit depth.
+ */
+static bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp)
+{
+	return win->variant.valid_bpp & VALID_BPP(bpp);
+}
+
+/**
+ * s3c_fb_check_var() - framebuffer layer request to verify a given mode.
+ * @var: The screen information to verify.
+ * @info: The framebuffer device.
+ *
+ * Framebuffer layer call to verify the given information and allow us to
+ * update various information depending on the hardware capabilities.
+ */
+static int s3c_fb_check_var(struct fb_var_screeninfo *var,
+			    struct fb_info *info)
+{
+	struct s3c_fb_win *win = info->par;
+	struct s3c_fb *sfb = win->parent;
+
+	dev_dbg(sfb->dev, "checking parameters\n");
+
+	var->xres_virtual = max(var->xres_virtual, var->xres);
+	var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
+		dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
+			win->index, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* always ensure these are zero, for drop through cases below */
+	var->transp.offset = 0;
+	var->transp.length = 0;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		if (sfb->variant.palette[win->index] != 0) {
+			/* non palletised, A:1,R:2,G:3,B:2 mode */
+			var->red.offset		= 5;
+			var->green.offset	= 2;
+			var->blue.offset	= 0;
+			var->red.length		= 2;
+			var->green.length	= 3;
+			var->blue.length	= 2;
+			var->transp.offset	= 7;
+			var->transp.length	= 1;
+		} else {
+			var->red.offset	= 0;
+			var->red.length	= var->bits_per_pixel;
+			var->green	= var->red;
+			var->blue	= var->red;
+		}
+		break;
+
+	case 19:
+		/* 666 with one bit alpha/transparency */
+		var->transp.offset	= 18;
+		var->transp.length	= 1;
+		/* drop through */
+	case 18:
+		var->bits_per_pixel	= 32;
+
+		/* 666 format */
+		var->red.offset		= 12;
+		var->green.offset	= 6;
+		var->blue.offset	= 0;
+		var->red.length		= 6;
+		var->green.length	= 6;
+		var->blue.length	= 6;
+		break;
+
+	case 16:
+		/* 16 bpp, 565 format */
+		var->red.offset		= 11;
+		var->green.offset	= 5;
+		var->blue.offset	= 0;
+		var->red.length		= 5;
+		var->green.length	= 6;
+		var->blue.length	= 5;
+		break;
+
+	case 32:
+	case 28:
+	case 25:
+		var->transp.length	= var->bits_per_pixel - 24;
+		var->transp.offset	= 24;
+		/* drop through */
+	case 24:
+		/* our 24bpp is unpacked, so 32bpp */
+		var->bits_per_pixel	= 32;
+		var->red.offset		= 16;
+		var->red.length		= 8;
+		var->green.offset	= 8;
+		var->green.length	= 8;
+		var->blue.offset	= 0;
+		var->blue.length	= 8;
+		break;
+
+	default:
+		dev_err(sfb->dev, "invalid bpp\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
+	return 0;
+}
+
+/**
+ * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
+ * @sfb: The hardware state.
+ * @pixclock: The pixel clock wanted, in picoseconds.
+ *
+ * Given the specified pixel clock, work out the necessary divider to get
+ * close to the output frequency.
+ */
+static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
+{
+	unsigned long clk;
+	unsigned long long tmp;
+	unsigned int result;
+
+	if (sfb->variant.has_clksel)
+		clk = clk_get_rate(sfb->bus_clk);
+	else
+		clk = clk_get_rate(sfb->lcd_clk);
+
+	tmp = (unsigned long long)clk;
+	tmp *= pixclk;
+
+	do_div(tmp, 1000000000UL);
+	result = (unsigned int)tmp / 1000;
+
+	dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
+		pixclk, clk, result, result ? clk / result : clk);
+
+	return result;
+}
+
+/**
+ * s3c_fb_align_word() - align pixel count to word boundary
+ * @bpp: The number of bits per pixel
+ * @pix: The value to be aligned.
+ *
+ * Align the given pixel count so that it will start on an 32bit word
+ * boundary.
+ */
+static int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
+{
+	int pix_per_word;
+
+	if (bpp > 16)
+		return pix;
+
+	pix_per_word = (8 * 32) / bpp;
+	return ALIGN(pix, pix_per_word);
+}
+
+/**
+ * vidosd_set_size() - set OSD size for a window
+ *
+ * @win: the window to set OSD size for
+ * @size: OSD size register value
+ */
+static void vidosd_set_size(struct s3c_fb_win *win, u32 size)
+{
+	struct s3c_fb *sfb = win->parent;
+
+	/* OSD can be set up if osd_size_off != 0 for this window */
+	if (win->variant.osd_size_off)
+		writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant)
+				+ win->variant.osd_size_off);
+}
+
+/**
+ * vidosd_set_alpha() - set alpha transparency for a window
+ *
+ * @win: the window to set OSD size for
+ * @alpha: alpha register value
+ */
+static void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha)
+{
+	struct s3c_fb *sfb = win->parent;
+
+	if (win->variant.has_osd_alpha)
+		writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant));
+}
+
+/**
+ * shadow_protect_win() - disable updating values from shadow registers at vsync
+ *
+ * @win: window to protect registers for
+ * @protect: 1 to protect (disable updates)
+ */
+static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
+{
+	struct s3c_fb *sfb = win->parent;
+	u32 reg;
+
+	if (protect) {
+		if (sfb->variant.has_prtcon) {
+			writel(PRTCON_PROTECT, sfb->regs + PRTCON);
+		} else if (sfb->variant.has_shadowcon) {
+			reg = readl(sfb->regs + SHADOWCON);
+			writel(reg | SHADOWCON_WINx_PROTECT(win->index),
+				sfb->regs + SHADOWCON);
+		}
+	} else {
+		if (sfb->variant.has_prtcon) {
+			writel(0, sfb->regs + PRTCON);
+		} else if (sfb->variant.has_shadowcon) {
+			reg = readl(sfb->regs + SHADOWCON);
+			writel(reg & ~SHADOWCON_WINx_PROTECT(win->index),
+				sfb->regs + SHADOWCON);
+		}
+	}
+}
+
+/**
+ * s3c_fb_enable() - Set the state of the main LCD output
+ * @sfb: The main framebuffer state.
+ * @enable: The state to set.
+ */
+static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
+{
+	u32 vidcon0 = readl(sfb->regs + VIDCON0);
+
+	if (enable && !sfb->output_on)
+		pm_runtime_get_sync(sfb->dev);
+
+	if (enable) {
+		vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+	} else {
+		/* see the note in the framebuffer datasheet about
+		 * why you cannot take both of these bits down at the
+		 * same time. */
+
+		if (vidcon0 & VIDCON0_ENVID) {
+			vidcon0 |= VIDCON0_ENVID;
+			vidcon0 &= ~VIDCON0_ENVID_F;
+		}
+	}
+
+	writel(vidcon0, sfb->regs + VIDCON0);
+
+	if (!enable && sfb->output_on)
+		pm_runtime_put_sync(sfb->dev);
+
+	sfb->output_on = enable;
+}
+
+/**
+ * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
+ * @info: The framebuffer to change.
+ *
+ * Framebuffer layer request to set a new mode for the specified framebuffer
+ */
+static int s3c_fb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct s3c_fb_win *win = info->par;
+	struct s3c_fb *sfb = win->parent;
+	void __iomem *regs = sfb->regs;
+	void __iomem *buf = regs;
+	int win_no = win->index;
+	u32 alpha = 0;
+	u32 data;
+	u32 pagewidth;
+
+	dev_dbg(sfb->dev, "setting framebuffer parameters\n");
+
+	pm_runtime_get_sync(sfb->dev);
+
+	shadow_protect_win(win, 1);
+
+	switch (var->bits_per_pixel) {
+	case 32:
+	case 24:
+	case 16:
+	case 12:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 8:
+		if (win->variant.palette_sz >= 256)
+			info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		else
+			info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 1:
+		info->fix.visual = FB_VISUAL_MONO01;
+		break;
+	default:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
+
+	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
+	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
+
+	/* disable the window whilst we update it */
+	writel(0, regs + WINCON(win_no));
+
+	if (!sfb->output_on)
+		s3c_fb_enable(sfb, 1);
+
+	/* write the buffer address */
+
+	/* start and end registers stride is 8 */
+	buf = regs + win_no * 8;
+
+	writel(info->fix.smem_start, buf + sfb->variant.buf_start);
+
+	data = info->fix.smem_start + info->fix.line_length * var->yres;
+	writel(data, buf + sfb->variant.buf_end);
+
+	pagewidth = (var->xres * var->bits_per_pixel) >> 3;
+	data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
+	       VIDW_BUF_SIZE_PAGEWIDTH(pagewidth) |
+	       VIDW_BUF_SIZE_OFFSET_E(info->fix.line_length - pagewidth) |
+	       VIDW_BUF_SIZE_PAGEWIDTH_E(pagewidth);
+	writel(data, regs + sfb->variant.buf_size + (win_no * 4));
+
+	/* write 'OSD' registers to control position of framebuffer */
+
+	data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0) |
+	       VIDOSDxA_TOPLEFT_X_E(0) | VIDOSDxA_TOPLEFT_Y_E(0);
+	writel(data, regs + VIDOSD_A(win_no, sfb->variant));
+
+	data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
+						     var->xres - 1)) |
+	       VIDOSDxB_BOTRIGHT_Y(var->yres - 1) |
+	       VIDOSDxB_BOTRIGHT_X_E(s3c_fb_align_word(var->bits_per_pixel,
+						     var->xres - 1)) |
+	       VIDOSDxB_BOTRIGHT_Y_E(var->yres - 1);
+
+	writel(data, regs + VIDOSD_B(win_no, sfb->variant));
+
+	data = var->xres * var->yres;
+
+	alpha = VIDISD14C_ALPHA1_R(0xf) |
+		VIDISD14C_ALPHA1_G(0xf) |
+		VIDISD14C_ALPHA1_B(0xf);
+
+	vidosd_set_alpha(win, alpha);
+	vidosd_set_size(win, data);
+
+	/* Enable DMA channel for this window */
+	if (sfb->variant.has_shadowcon) {
+		data = readl(sfb->regs + SHADOWCON);
+		data |= SHADOWCON_CHx_ENABLE(win_no);
+		writel(data, sfb->regs + SHADOWCON);
+	}
+
+	data = WINCONx_ENWIN;
+	sfb->enabled |= (1 << win->index);
+
+	/* note, since we have to round up the bits-per-pixel, we end up
+	 * relying on the bitfield information for r/g/b/a to work out
+	 * exactly which mode of operation is intended. */
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		data |= WINCON0_BPPMODE_1BPP;
+		data |= WINCONx_BITSWP;
+		data |= WINCONx_BURSTLEN_4WORD;
+		break;
+	case 2:
+		data |= WINCON0_BPPMODE_2BPP;
+		data |= WINCONx_BITSWP;
+		data |= WINCONx_BURSTLEN_8WORD;
+		break;
+	case 4:
+		data |= WINCON0_BPPMODE_4BPP;
+		data |= WINCONx_BITSWP;
+		data |= WINCONx_BURSTLEN_8WORD;
+		break;
+	case 8:
+		if (var->transp.length != 0)
+			data |= WINCON1_BPPMODE_8BPP_1232;
+		else
+			data |= WINCON0_BPPMODE_8BPP_PALETTE;
+		data |= WINCONx_BURSTLEN_8WORD;
+		data |= WINCONx_BYTSWP;
+		break;
+	case 16:
+		if (var->transp.length != 0)
+			data |= WINCON1_BPPMODE_16BPP_A1555;
+		else
+			data |= WINCON0_BPPMODE_16BPP_565;
+		data |= WINCONx_HAWSWP;
+		data |= WINCONx_BURSTLEN_16WORD;
+		break;
+	case 24:
+	case 32:
+		if (var->red.length == 6) {
+			if (var->transp.length != 0)
+				data |= WINCON1_BPPMODE_19BPP_A1666;
+			else
+				data |= WINCON1_BPPMODE_18BPP_666;
+		} else if (var->transp.length == 1)
+			data |= WINCON1_BPPMODE_25BPP_A1888
+				| WINCON1_BLD_PIX;
+		else if ((var->transp.length == 4) ||
+			(var->transp.length == 8))
+			data |= WINCON1_BPPMODE_28BPP_A4888
+				| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
+		else
+			data |= WINCON0_BPPMODE_24BPP_888;
+
+		data |= WINCONx_WSWP;
+		data |= WINCONx_BURSTLEN_16WORD;
+		break;
+	}
+
+	/* Enable the colour keying for the window below this one */
+	if (win_no > 0) {
+		u32 keycon0_data = 0, keycon1_data = 0;
+		void __iomem *keycon = regs + sfb->variant.keycon;
+
+		keycon0_data = ~(WxKEYCON0_KEYBL_EN |
+				WxKEYCON0_KEYEN_F |
+				WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
+
+		keycon1_data = WxKEYCON1_COLVAL(0xffffff);
+
+		keycon += (win_no - 1) * 8;
+
+		writel(keycon0_data, keycon + WKEYCON0);
+		writel(keycon1_data, keycon + WKEYCON1);
+	}
+
+	writel(data, regs + sfb->variant.wincon + (win_no * 4));
+	writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
+
+	/* Set alpha value width */
+	if (sfb->variant.has_blendcon) {
+		data = readl(sfb->regs + BLENDCON);
+		data &= ~BLENDCON_NEW_MASK;
+		if (var->transp.length > 4)
+			data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
+		else
+			data |= BLENDCON_NEW_4BIT_ALPHA_VALUE;
+		writel(data, sfb->regs + BLENDCON);
+	}
+
+	shadow_protect_win(win, 0);
+
+	pm_runtime_put_sync(sfb->dev);
+
+	return 0;
+}
+
+/**
+ * s3c_fb_update_palette() - set or schedule a palette update.
+ * @sfb: The hardware information.
+ * @win: The window being updated.
+ * @reg: The palette index being changed.
+ * @value: The computed palette value.
+ *
+ * Change the value of a palette register, either by directly writing to
+ * the palette (this requires the palette RAM to be disconnected from the
+ * hardware whilst this is in progress) or schedule the update for later.
+ *
+ * At the moment, since we have no VSYNC interrupt support, we simply set
+ * the palette entry directly.
+ */
+static void s3c_fb_update_palette(struct s3c_fb *sfb,
+				  struct s3c_fb_win *win,
+				  unsigned int reg,
+				  u32 value)
+{
+	void __iomem *palreg;
+	u32 palcon;
+
+	palreg = sfb->regs + sfb->variant.palette[win->index];
+
+	dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
+		__func__, win->index, reg, palreg, value);
+
+	win->palette_buffer[reg] = value;
+
+	palcon = readl(sfb->regs + WPALCON);
+	writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
+
+	if (win->variant.palette_16bpp)
+		writew(value, palreg + (reg * 2));
+	else
+		writel(value, palreg + (reg * 4));
+
+	writel(palcon, sfb->regs + WPALCON);
+}
+
+static inline unsigned int chan_to_field(unsigned int chan,
+					 struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/**
+ * s3c_fb_setcolreg() - framebuffer layer request to change palette.
+ * @regno: The palette index to change.
+ * @red: The red field for the palette data.
+ * @green: The green field for the palette data.
+ * @blue: The blue field for the palette data.
+ * @trans: The transparency (alpha) field for the palette data.
+ * @info: The framebuffer being changed.
+ */
+static int s3c_fb_setcolreg(unsigned regno,
+			    unsigned red, unsigned green, unsigned blue,
+			    unsigned transp, struct fb_info *info)
+{
+	struct s3c_fb_win *win = info->par;
+	struct s3c_fb *sfb = win->parent;
+	unsigned int val;
+
+	dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
+		__func__, win->index, regno, red, green, blue);
+
+	pm_runtime_get_sync(sfb->dev);
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/* true-colour, use pseudo-palette */
+
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red,   &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue,  &info->var.blue);
+
+			pal[regno] = val;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < win->variant.palette_sz) {
+			val  = chan_to_field(red, &win->palette.r);
+			val |= chan_to_field(green, &win->palette.g);
+			val |= chan_to_field(blue, &win->palette.b);
+
+			s3c_fb_update_palette(sfb, win, regno, val);
+		}
+
+		break;
+
+	default:
+		pm_runtime_put_sync(sfb->dev);
+		return 1;	/* unknown type */
+	}
+
+	pm_runtime_put_sync(sfb->dev);
+	return 0;
+}
+
+/**
+ * s3c_fb_blank() - blank or unblank the given window
+ * @blank_mode: The blank state from FB_BLANK_*
+ * @info: The framebuffer to blank.
+ *
+ * Framebuffer layer request to change the power state.
+ */
+static int s3c_fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct s3c_fb_win *win = info->par;
+	struct s3c_fb *sfb = win->parent;
+	unsigned int index = win->index;
+	u32 wincon;
+	u32 output_on = sfb->output_on;
+
+	dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
+
+	pm_runtime_get_sync(sfb->dev);
+
+	wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
+
+	switch (blank_mode) {
+	case FB_BLANK_POWERDOWN:
+		wincon &= ~WINCONx_ENWIN;
+		sfb->enabled &= ~(1 << index);
+		/* fall through to FB_BLANK_NORMAL */
+
+	case FB_BLANK_NORMAL:
+		/* disable the DMA and display 0x0 (black) */
+		shadow_protect_win(win, 1);
+		writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
+		       sfb->regs + sfb->variant.winmap + (index * 4));
+		shadow_protect_win(win, 0);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		shadow_protect_win(win, 1);
+		writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
+		shadow_protect_win(win, 0);
+		wincon |= WINCONx_ENWIN;
+		sfb->enabled |= (1 << index);
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	default:
+		pm_runtime_put_sync(sfb->dev);
+		return 1;
+	}
+
+	shadow_protect_win(win, 1);
+	writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
+
+	/* Check the enabled state to see if we need to be running the
+	 * main LCD interface, as if there are no active windows then
+	 * it is highly likely that we also do not need to output
+	 * anything.
+	 */
+	s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
+	shadow_protect_win(win, 0);
+
+	pm_runtime_put_sync(sfb->dev);
+
+	return output_on == sfb->output_on;
+}
+
+/**
+ * s3c_fb_pan_display() - Pan the display.
+ *
+ * Note that the offsets can be written to the device at any time, as their
+ * values are latched at each vsync automatically. This also means that only
+ * the last call to this function will have any effect on next vsync, but
+ * there is no need to sleep waiting for it to prevent tearing.
+ *
+ * @var: The screen information to verify.
+ * @info: The framebuffer device.
+ */
+static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct s3c_fb_win *win	= info->par;
+	struct s3c_fb *sfb	= win->parent;
+	void __iomem *buf	= sfb->regs + win->index * 8;
+	unsigned int start_boff, end_boff;
+
+	pm_runtime_get_sync(sfb->dev);
+
+	/* Offset in bytes to the start of the displayed area */
+	start_boff = var->yoffset * info->fix.line_length;
+	/* X offset depends on the current bpp */
+	if (info->var.bits_per_pixel >= 8) {
+		start_boff += var->xoffset * (info->var.bits_per_pixel >> 3);
+	} else {
+		switch (info->var.bits_per_pixel) {
+		case 4:
+			start_boff += var->xoffset >> 1;
+			break;
+		case 2:
+			start_boff += var->xoffset >> 2;
+			break;
+		case 1:
+			start_boff += var->xoffset >> 3;
+			break;
+		default:
+			dev_err(sfb->dev, "invalid bpp\n");
+			pm_runtime_put_sync(sfb->dev);
+			return -EINVAL;
+		}
+	}
+	/* Offset in bytes to the end of the displayed area */
+	end_boff = start_boff + info->var.yres * info->fix.line_length;
+
+	/* Temporarily turn off per-vsync update from shadow registers until
+	 * both start and end addresses are updated to prevent corruption */
+	shadow_protect_win(win, 1);
+
+	writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start);
+	writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end);
+
+	shadow_protect_win(win, 0);
+
+	pm_runtime_put_sync(sfb->dev);
+	return 0;
+}
+
+/**
+ * s3c_fb_enable_irq() - enable framebuffer interrupts
+ * @sfb: main hardware state
+ */
+static void s3c_fb_enable_irq(struct s3c_fb *sfb)
+{
+	void __iomem *regs = sfb->regs;
+	u32 irq_ctrl_reg;
+
+	if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
+		/* IRQ disabled, enable it */
+		irq_ctrl_reg = readl(regs + VIDINTCON0);
+
+		irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
+		irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
+
+		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
+		irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
+		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
+		irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
+
+		writel(irq_ctrl_reg, regs + VIDINTCON0);
+	}
+}
+
+/**
+ * s3c_fb_disable_irq() - disable framebuffer interrupts
+ * @sfb: main hardware state
+ */
+static void s3c_fb_disable_irq(struct s3c_fb *sfb)
+{
+	void __iomem *regs = sfb->regs;
+	u32 irq_ctrl_reg;
+
+	if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
+		/* IRQ enabled, disable it */
+		irq_ctrl_reg = readl(regs + VIDINTCON0);
+
+		irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
+		irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
+
+		writel(irq_ctrl_reg, regs + VIDINTCON0);
+	}
+}
+
+static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
+{
+	struct s3c_fb *sfb = dev_id;
+	void __iomem  *regs = sfb->regs;
+	u32 irq_sts_reg;
+
+	spin_lock(&sfb->slock);
+
+	irq_sts_reg = readl(regs + VIDINTCON1);
+
+	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
+
+		/* VSYNC interrupt, accept it */
+		writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
+
+		sfb->vsync_info.count++;
+		wake_up_interruptible(&sfb->vsync_info.wait);
+	}
+
+	/* We only support waiting for VSYNC for now, so it's safe
+	 * to always disable irqs here.
+	 */
+	s3c_fb_disable_irq(sfb);
+
+	spin_unlock(&sfb->slock);
+	return IRQ_HANDLED;
+}
+
+/**
+ * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
+ * @sfb: main hardware state
+ * @crtc: head index.
+ */
+static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
+{
+	unsigned long count;
+	int ret;
+
+	if (crtc != 0)
+		return -ENODEV;
+
+	pm_runtime_get_sync(sfb->dev);
+
+	count = sfb->vsync_info.count;
+	s3c_fb_enable_irq(sfb);
+	ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
+				       count != sfb->vsync_info.count,
+				       msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
+
+	pm_runtime_put_sync(sfb->dev);
+
+	if (ret == 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			unsigned long arg)
+{
+	struct s3c_fb_win *win = info->par;
+	struct s3c_fb *sfb = win->parent;
+	int ret;
+	u32 crtc;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		if (get_user(crtc, (u32 __user *)arg)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		ret = s3c_fb_wait_for_vsync(sfb, crtc);
+		break;
+	default:
+		ret = -ENOTTY;
+	}
+
+	return ret;
+}
+
+static struct fb_ops s3c_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= s3c_fb_check_var,
+	.fb_set_par	= s3c_fb_set_par,
+	.fb_blank	= s3c_fb_blank,
+	.fb_setcolreg	= s3c_fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_pan_display	= s3c_fb_pan_display,
+	.fb_ioctl	= s3c_fb_ioctl,
+};
+
+/**
+ * s3c_fb_missing_pixclock() - calculates pixel clock
+ * @mode: The video mode to change.
+ *
+ * Calculate the pixel clock when none has been given through platform data.
+ */
+static void s3c_fb_missing_pixclock(struct fb_videomode *mode)
+{
+	u64 pixclk = 1000000000000ULL;
+	u32 div;
+
+	div  = mode->left_margin + mode->hsync_len + mode->right_margin +
+	       mode->xres;
+	div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
+	       mode->yres;
+	div *= mode->refresh ? : 60;
+
+	do_div(pixclk, div);
+
+	mode->pixclock = pixclk;
+}
+
+/**
+ * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
+ * @sfb: The base resources for the hardware.
+ * @win: The window to initialise memory for.
+ *
+ * Allocate memory for the given framebuffer.
+ */
+static int s3c_fb_alloc_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
+{
+	struct s3c_fb_pd_win *windata = win->windata;
+	unsigned int real_size, virt_size, size;
+	struct fb_info *fbi = win->fbinfo;
+	dma_addr_t map_dma;
+
+	dev_dbg(sfb->dev, "allocating memory for display\n");
+
+	real_size = windata->xres * windata->yres;
+	virt_size = windata->virtual_x * windata->virtual_y;
+
+	dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
+		real_size, windata->xres, windata->yres,
+		virt_size, windata->virtual_x, windata->virtual_y);
+
+	size = (real_size > virt_size) ? real_size : virt_size;
+	size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
+	size /= 8;
+
+	fbi->fix.smem_len = size;
+	size = PAGE_ALIGN(size);
+
+	dev_dbg(sfb->dev, "want %u bytes for window\n", size);
+
+	fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,
+						  &map_dma, GFP_KERNEL);
+	if (!fbi->screen_base)
+		return -ENOMEM;
+
+	dev_dbg(sfb->dev, "mapped %x to %p\n",
+		(unsigned int)map_dma, fbi->screen_base);
+
+	memset(fbi->screen_base, 0x0, size);
+	fbi->fix.smem_start = map_dma;
+
+	return 0;
+}
+
+/**
+ * s3c_fb_free_memory() - free the display memory for the given window
+ * @sfb: The base resources for the hardware.
+ * @win: The window to free the display memory for.
+ *
+ * Free the display memory allocated by s3c_fb_alloc_memory().
+ */
+static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
+{
+	struct fb_info *fbi = win->fbinfo;
+
+	if (fbi->screen_base)
+		dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
+			      fbi->screen_base, fbi->fix.smem_start);
+}
+
+/**
+ * s3c_fb_release_win() - release resources for a framebuffer window.
+ * @win: The window to cleanup the resources for.
+ *
+ * Release the resources that where claimed for the hardware window,
+ * such as the framebuffer instance and any memory claimed for it.
+ */
+static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
+{
+	u32 data;
+
+	if (win->fbinfo) {
+		if (sfb->variant.has_shadowcon) {
+			data = readl(sfb->regs + SHADOWCON);
+			data &= ~SHADOWCON_CHx_ENABLE(win->index);
+			data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
+			writel(data, sfb->regs + SHADOWCON);
+		}
+		unregister_framebuffer(win->fbinfo);
+		if (win->fbinfo->cmap.len)
+			fb_dealloc_cmap(&win->fbinfo->cmap);
+		s3c_fb_free_memory(sfb, win);
+		framebuffer_release(win->fbinfo);
+	}
+}
+
+/**
+ * s3c_fb_probe_win() - register an hardware window
+ * @sfb: The base resources for the hardware
+ * @variant: The variant information for this window.
+ * @res: Pointer to where to place the resultant window.
+ *
+ * Allocate and do the basic initialisation for one of the hardware's graphics
+ * windows.
+ */
+static int s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
+			    struct s3c_fb_win_variant *variant,
+			    struct s3c_fb_win **res)
+{
+	struct fb_var_screeninfo *var;
+	struct fb_videomode initmode;
+	struct s3c_fb_pd_win *windata;
+	struct s3c_fb_win *win;
+	struct fb_info *fbinfo;
+	int palette_size;
+	int ret;
+
+	dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
+
+	init_waitqueue_head(&sfb->vsync_info.wait);
+
+	palette_size = variant->palette_sz * 4;
+
+	fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
+				   palette_size * sizeof(u32), sfb->dev);
+	if (!fbinfo) {
+		dev_err(sfb->dev, "failed to allocate framebuffer\n");
+		return -ENOENT;
+	}
+
+	windata = sfb->pdata->win[win_no];
+	initmode = *sfb->pdata->vtiming;
+
+	WARN_ON(windata->max_bpp == 0);
+	WARN_ON(windata->xres == 0);
+	WARN_ON(windata->yres == 0);
+
+	win = fbinfo->par;
+	*res = win;
+	var = &fbinfo->var;
+	win->variant = *variant;
+	win->fbinfo = fbinfo;
+	win->parent = sfb;
+	win->windata = windata;
+	win->index = win_no;
+	win->palette_buffer = (u32 *)(win + 1);
+
+	ret = s3c_fb_alloc_memory(sfb, win);
+	if (ret) {
+		dev_err(sfb->dev, "failed to allocate display memory\n");
+		return ret;
+	}
+
+	/* setup the r/b/g positions for the window's palette */
+	if (win->variant.palette_16bpp) {
+		/* Set RGB 5:6:5 as default */
+		win->palette.r.offset = 11;
+		win->palette.r.length = 5;
+		win->palette.g.offset = 5;
+		win->palette.g.length = 6;
+		win->palette.b.offset = 0;
+		win->palette.b.length = 5;
+
+	} else {
+		/* Set 8bpp or 8bpp and 1bit alpha */
+		win->palette.r.offset = 16;
+		win->palette.r.length = 8;
+		win->palette.g.offset = 8;
+		win->palette.g.length = 8;
+		win->palette.b.offset = 0;
+		win->palette.b.length = 8;
+	}
+
+	/* setup the initial video mode from the window */
+	initmode.xres = windata->xres;
+	initmode.yres = windata->yres;
+	fb_videomode_to_var(&fbinfo->var, &initmode);
+
+	fbinfo->fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.accel	= FB_ACCEL_NONE;
+	fbinfo->var.activate	= FB_ACTIVATE_NOW;
+	fbinfo->var.vmode	= FB_VMODE_NONINTERLACED;
+	fbinfo->var.bits_per_pixel = windata->default_bpp;
+	fbinfo->fbops		= &s3c_fb_ops;
+	fbinfo->flags		= FBINFO_FLAG_DEFAULT;
+	fbinfo->pseudo_palette  = &win->pseudo_palette;
+
+	/* prepare to actually start the framebuffer */
+
+	ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
+	if (ret < 0) {
+		dev_err(sfb->dev, "check_var failed on initial video params\n");
+		return ret;
+	}
+
+	/* create initial colour map */
+
+	ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
+	if (ret == 0)
+		fb_set_cmap(&fbinfo->cmap, fbinfo);
+	else
+		dev_err(sfb->dev, "failed to allocate fb cmap\n");
+
+	s3c_fb_set_par(fbinfo);
+
+	dev_dbg(sfb->dev, "about to register framebuffer\n");
+
+	/* run the check_var and set_par on our configuration. */
+
+	ret = register_framebuffer(fbinfo);
+	if (ret < 0) {
+		dev_err(sfb->dev, "failed to register framebuffer\n");
+		return ret;
+	}
+
+	dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
+
+	return 0;
+}
+
+/**
+ * s3c_fb_set_rgb_timing() - set video timing for rgb interface.
+ * @sfb: The base resources for the hardware.
+ *
+ * Set horizontal and vertical lcd rgb interface timing.
+ */
+static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb)
+{
+	struct fb_videomode *vmode = sfb->pdata->vtiming;
+	void __iomem *regs = sfb->regs;
+	int clkdiv;
+	u32 data;
+
+	if (!vmode->pixclock)
+		s3c_fb_missing_pixclock(vmode);
+
+	clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock);
+
+	data = sfb->pdata->vidcon0;
+	data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
+
+	if (clkdiv > 1)
+		data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
+	else
+		data &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
+
+	if (sfb->variant.is_2443)
+		data |= (1 << 5);
+	writel(data, regs + VIDCON0);
+
+	data = VIDTCON0_VBPD(vmode->upper_margin - 1) |
+	       VIDTCON0_VFPD(vmode->lower_margin - 1) |
+	       VIDTCON0_VSPW(vmode->vsync_len - 1);
+	writel(data, regs + sfb->variant.vidtcon);
+
+	data = VIDTCON1_HBPD(vmode->left_margin - 1) |
+	       VIDTCON1_HFPD(vmode->right_margin - 1) |
+	       VIDTCON1_HSPW(vmode->hsync_len - 1);
+	writel(data, regs + sfb->variant.vidtcon + 4);
+
+	data = VIDTCON2_LINEVAL(vmode->yres - 1) |
+	       VIDTCON2_HOZVAL(vmode->xres - 1) |
+	       VIDTCON2_LINEVAL_E(vmode->yres - 1) |
+	       VIDTCON2_HOZVAL_E(vmode->xres - 1);
+	writel(data, regs + sfb->variant.vidtcon + 8);
+}
+
+/**
+ * s3c_fb_clear_win() - clear hardware window registers.
+ * @sfb: The base resources for the hardware.
+ * @win: The window to process.
+ *
+ * Reset the specific window registers to a known state.
+ */
+static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
+{
+	void __iomem *regs = sfb->regs;
+	u32 reg;
+
+	writel(0, regs + sfb->variant.wincon + (win * 4));
+	writel(0, regs + VIDOSD_A(win, sfb->variant));
+	writel(0, regs + VIDOSD_B(win, sfb->variant));
+	writel(0, regs + VIDOSD_C(win, sfb->variant));
+
+	if (sfb->variant.has_shadowcon) {
+		reg = readl(sfb->regs + SHADOWCON);
+		reg &= ~(SHADOWCON_WINx_PROTECT(win) |
+			SHADOWCON_CHx_ENABLE(win) |
+			SHADOWCON_CHx_LOCAL_ENABLE(win));
+		writel(reg, sfb->regs + SHADOWCON);
+	}
+}
+
+static int s3c_fb_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *platid;
+	struct s3c_fb_driverdata *fbdrv;
+	struct device *dev = &pdev->dev;
+	struct s3c_fb_platdata *pd;
+	struct s3c_fb *sfb;
+	struct resource *res;
+	int win;
+	int ret = 0;
+	u32 reg;
+
+	platid = platform_get_device_id(pdev);
+	fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
+
+	if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
+		dev_err(dev, "too many windows, cannot attach\n");
+		return -EINVAL;
+	}
+
+	pd = dev_get_platdata(&pdev->dev);
+	if (!pd) {
+		dev_err(dev, "no platform data specified\n");
+		return -EINVAL;
+	}
+
+	sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
+	if (!sfb) {
+		dev_err(dev, "no memory for framebuffers\n");
+		return -ENOMEM;
+	}
+
+	dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
+
+	sfb->dev = dev;
+	sfb->pdata = pd;
+	sfb->variant = fbdrv->variant;
+
+	spin_lock_init(&sfb->slock);
+
+	sfb->bus_clk = devm_clk_get(dev, "lcd");
+	if (IS_ERR(sfb->bus_clk)) {
+		dev_err(dev, "failed to get bus clock\n");
+		return PTR_ERR(sfb->bus_clk);
+	}
+
+	clk_prepare_enable(sfb->bus_clk);
+
+	if (!sfb->variant.has_clksel) {
+		sfb->lcd_clk = devm_clk_get(dev, "sclk_fimd");
+		if (IS_ERR(sfb->lcd_clk)) {
+			dev_err(dev, "failed to get lcd clock\n");
+			ret = PTR_ERR(sfb->lcd_clk);
+			goto err_bus_clk;
+		}
+
+		clk_prepare_enable(sfb->lcd_clk);
+	}
+
+	pm_runtime_enable(sfb->dev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sfb->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(sfb->regs)) {
+		ret = PTR_ERR(sfb->regs);
+		goto err_lcd_clk;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "failed to acquire irq resource\n");
+		ret = -ENOENT;
+		goto err_lcd_clk;
+	}
+	sfb->irq_no = res->start;
+	ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,
+			  0, "s3c_fb", sfb);
+	if (ret) {
+		dev_err(dev, "irq request failed\n");
+		goto err_lcd_clk;
+	}
+
+	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
+
+	platform_set_drvdata(pdev, sfb);
+	pm_runtime_get_sync(sfb->dev);
+
+	/* setup gpio and output polarity controls */
+
+	pd->setup_gpio();
+
+	writel(pd->vidcon1, sfb->regs + VIDCON1);
+
+	/* set video clock running at under-run */
+	if (sfb->variant.has_fixvclk) {
+		reg = readl(sfb->regs + VIDCON1);
+		reg &= ~VIDCON1_VCLK_MASK;
+		reg |= VIDCON1_VCLK_RUN;
+		writel(reg, sfb->regs + VIDCON1);
+	}
+
+	/* zero all windows before we do anything */
+
+	for (win = 0; win < fbdrv->variant.nr_windows; win++)
+		s3c_fb_clear_win(sfb, win);
+
+	/* initialise colour key controls */
+	for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) {
+		void __iomem *regs = sfb->regs + sfb->variant.keycon;
+
+		regs += (win * 8);
+		writel(0xffffff, regs + WKEYCON0);
+		writel(0xffffff, regs + WKEYCON1);
+	}
+
+	s3c_fb_set_rgb_timing(sfb);
+
+	/* we have the register setup, start allocating framebuffers */
+
+	for (win = 0; win < fbdrv->variant.nr_windows; win++) {
+		if (!pd->win[win])
+			continue;
+
+		ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
+				       &sfb->windows[win]);
+		if (ret < 0) {
+			dev_err(dev, "failed to create window %d\n", win);
+			for (; win >= 0; win--)
+				s3c_fb_release_win(sfb, sfb->windows[win]);
+			goto err_pm_runtime;
+		}
+	}
+
+	platform_set_drvdata(pdev, sfb);
+	pm_runtime_put_sync(sfb->dev);
+
+	return 0;
+
+err_pm_runtime:
+	pm_runtime_put_sync(sfb->dev);
+
+err_lcd_clk:
+	pm_runtime_disable(sfb->dev);
+
+	if (!sfb->variant.has_clksel)
+		clk_disable_unprepare(sfb->lcd_clk);
+
+err_bus_clk:
+	clk_disable_unprepare(sfb->bus_clk);
+
+	return ret;
+}
+
+/**
+ * s3c_fb_remove() - Cleanup on module finalisation
+ * @pdev: The platform device we are bound to.
+ *
+ * Shutdown and then release all the resources that the driver allocated
+ * on initialisation.
+ */
+static int s3c_fb_remove(struct platform_device *pdev)
+{
+	struct s3c_fb *sfb = platform_get_drvdata(pdev);
+	int win;
+
+	pm_runtime_get_sync(sfb->dev);
+
+	for (win = 0; win < S3C_FB_MAX_WIN; win++)
+		if (sfb->windows[win])
+			s3c_fb_release_win(sfb, sfb->windows[win]);
+
+	if (!sfb->variant.has_clksel)
+		clk_disable_unprepare(sfb->lcd_clk);
+
+	clk_disable_unprepare(sfb->bus_clk);
+
+	pm_runtime_put_sync(sfb->dev);
+	pm_runtime_disable(sfb->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int s3c_fb_suspend(struct device *dev)
+{
+	struct s3c_fb *sfb = dev_get_drvdata(dev);
+	struct s3c_fb_win *win;
+	int win_no;
+
+	pm_runtime_get_sync(sfb->dev);
+
+	for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
+		win = sfb->windows[win_no];
+		if (!win)
+			continue;
+
+		/* use the blank function to push into power-down */
+		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
+	}
+
+	if (!sfb->variant.has_clksel)
+		clk_disable_unprepare(sfb->lcd_clk);
+
+	clk_disable_unprepare(sfb->bus_clk);
+
+	pm_runtime_put_sync(sfb->dev);
+
+	return 0;
+}
+
+static int s3c_fb_resume(struct device *dev)
+{
+	struct s3c_fb *sfb = dev_get_drvdata(dev);
+	struct s3c_fb_platdata *pd = sfb->pdata;
+	struct s3c_fb_win *win;
+	int win_no;
+	u32 reg;
+
+	pm_runtime_get_sync(sfb->dev);
+
+	clk_prepare_enable(sfb->bus_clk);
+
+	if (!sfb->variant.has_clksel)
+		clk_prepare_enable(sfb->lcd_clk);
+
+	/* setup gpio and output polarity controls */
+	pd->setup_gpio();
+	writel(pd->vidcon1, sfb->regs + VIDCON1);
+
+	/* set video clock running at under-run */
+	if (sfb->variant.has_fixvclk) {
+		reg = readl(sfb->regs + VIDCON1);
+		reg &= ~VIDCON1_VCLK_MASK;
+		reg |= VIDCON1_VCLK_RUN;
+		writel(reg, sfb->regs + VIDCON1);
+	}
+
+	/* zero all windows before we do anything */
+	for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
+		s3c_fb_clear_win(sfb, win_no);
+
+	for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
+		void __iomem *regs = sfb->regs + sfb->variant.keycon;
+		win = sfb->windows[win_no];
+		if (!win)
+			continue;
+
+		shadow_protect_win(win, 1);
+		regs += (win_no * 8);
+		writel(0xffffff, regs + WKEYCON0);
+		writel(0xffffff, regs + WKEYCON1);
+		shadow_protect_win(win, 0);
+	}
+
+	s3c_fb_set_rgb_timing(sfb);
+
+	/* restore framebuffers */
+	for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
+		win = sfb->windows[win_no];
+		if (!win)
+			continue;
+
+		dev_dbg(dev, "resuming window %d\n", win_no);
+		s3c_fb_set_par(win->fbinfo);
+	}
+
+	pm_runtime_put_sync(sfb->dev);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int s3c_fb_runtime_suspend(struct device *dev)
+{
+	struct s3c_fb *sfb = dev_get_drvdata(dev);
+
+	if (!sfb->variant.has_clksel)
+		clk_disable_unprepare(sfb->lcd_clk);
+
+	clk_disable_unprepare(sfb->bus_clk);
+
+	return 0;
+}
+
+static int s3c_fb_runtime_resume(struct device *dev)
+{
+	struct s3c_fb *sfb = dev_get_drvdata(dev);
+	struct s3c_fb_platdata *pd = sfb->pdata;
+
+	clk_prepare_enable(sfb->bus_clk);
+
+	if (!sfb->variant.has_clksel)
+		clk_prepare_enable(sfb->lcd_clk);
+
+	/* setup gpio and output polarity controls */
+	pd->setup_gpio();
+	writel(pd->vidcon1, sfb->regs + VIDCON1);
+
+	return 0;
+}
+#endif
+
+#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
+#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
+
+static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
+	[0] = {
+		.has_osd_c	= 1,
+		.osd_size_off	= 0x8,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(24)),
+	},
+	[1] = {
+		.has_osd_c	= 1,
+		.has_osd_d	= 1,
+		.osd_size_off	= 0xc,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(28)),
+	},
+	[2] = {
+		.has_osd_c	= 1,
+		.has_osd_d	= 1,
+		.osd_size_off	= 0xc,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 16,
+		.palette_16bpp	= 1,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(28)),
+	},
+	[3] = {
+		.has_osd_c	= 1,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 16,
+		.palette_16bpp	= 1,
+		.valid_bpp	= (VALID_BPP124  | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(28)),
+	},
+	[4] = {
+		.has_osd_c	= 1,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 4,
+		.palette_16bpp	= 1,
+		.valid_bpp	= (VALID_BPP(1) | VALID_BPP(2) |
+				   VALID_BPP(16) | VALID_BPP(18) |
+				   VALID_BPP(19) | VALID_BPP(24) |
+				   VALID_BPP(25) | VALID_BPP(28)),
+	},
+};
+
+static struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {
+	[0] = {
+		.has_osd_c	= 1,
+		.osd_size_off	= 0x8,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
+				   VALID_BPP(15) | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(32)),
+	},
+	[1] = {
+		.has_osd_c	= 1,
+		.has_osd_d	= 1,
+		.osd_size_off	= 0xc,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
+				   VALID_BPP(15) | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(32)),
+	},
+	[2] = {
+		.has_osd_c	= 1,
+		.has_osd_d	= 1,
+		.osd_size_off	= 0xc,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
+				   VALID_BPP(15) | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(32)),
+	},
+	[3] = {
+		.has_osd_c	= 1,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
+				   VALID_BPP(15) | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(32)),
+	},
+	[4] = {
+		.has_osd_c	= 1,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
+				   VALID_BPP(15) | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(32)),
+	},
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_64xx = {
+	.variant = {
+		.nr_windows	= 5,
+		.vidtcon	= VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x400,
+			[1] = 0x800,
+			[2] = 0x300,
+			[3] = 0x320,
+			[4] = 0x340,
+		},
+
+		.has_prtcon	= 1,
+		.has_clksel	= 1,
+	},
+	.win[0]	= &s3c_fb_data_64xx_wins[0],
+	.win[1]	= &s3c_fb_data_64xx_wins[1],
+	.win[2]	= &s3c_fb_data_64xx_wins[2],
+	.win[3]	= &s3c_fb_data_64xx_wins[3],
+	.win[4]	= &s3c_fb_data_64xx_wins[4],
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
+	.variant = {
+		.nr_windows	= 5,
+		.vidtcon	= VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x2400,
+			[1] = 0x2800,
+			[2] = 0x2c00,
+			[3] = 0x3000,
+			[4] = 0x3400,
+		},
+
+		.has_prtcon	= 1,
+		.has_blendcon	= 1,
+		.has_clksel	= 1,
+	},
+	.win[0]	= &s3c_fb_data_s5p_wins[0],
+	.win[1]	= &s3c_fb_data_s5p_wins[1],
+	.win[2]	= &s3c_fb_data_s5p_wins[2],
+	.win[3]	= &s3c_fb_data_s5p_wins[3],
+	.win[4]	= &s3c_fb_data_s5p_wins[4],
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
+	.variant = {
+		.nr_windows	= 5,
+		.vidtcon	= VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x2400,
+			[1] = 0x2800,
+			[2] = 0x2c00,
+			[3] = 0x3000,
+			[4] = 0x3400,
+		},
+
+		.has_shadowcon	= 1,
+		.has_blendcon	= 1,
+		.has_clksel	= 1,
+		.has_fixvclk	= 1,
+	},
+	.win[0]	= &s3c_fb_data_s5p_wins[0],
+	.win[1]	= &s3c_fb_data_s5p_wins[1],
+	.win[2]	= &s3c_fb_data_s5p_wins[2],
+	.win[3]	= &s3c_fb_data_s5p_wins[3],
+	.win[4]	= &s3c_fb_data_s5p_wins[4],
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
+	.variant = {
+		.nr_windows	= 5,
+		.vidtcon	= VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x2400,
+			[1] = 0x2800,
+			[2] = 0x2c00,
+			[3] = 0x3000,
+			[4] = 0x3400,
+		},
+
+		.has_shadowcon	= 1,
+		.has_blendcon	= 1,
+		.has_fixvclk	= 1,
+	},
+	.win[0]	= &s3c_fb_data_s5p_wins[0],
+	.win[1]	= &s3c_fb_data_s5p_wins[1],
+	.win[2]	= &s3c_fb_data_s5p_wins[2],
+	.win[3]	= &s3c_fb_data_s5p_wins[3],
+	.win[4]	= &s3c_fb_data_s5p_wins[4],
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
+	.variant = {
+		.nr_windows	= 5,
+		.vidtcon	= FIMD_V8_VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x2400,
+			[1] = 0x2800,
+			[2] = 0x2c00,
+			[3] = 0x3000,
+			[4] = 0x3400,
+		},
+		.has_shadowcon	= 1,
+		.has_blendcon	= 1,
+		.has_fixvclk	= 1,
+	},
+	.win[0]	= &s3c_fb_data_s5p_wins[0],
+	.win[1]	= &s3c_fb_data_s5p_wins[1],
+	.win[2]	= &s3c_fb_data_s5p_wins[2],
+	.win[3]	= &s3c_fb_data_s5p_wins[3],
+	.win[4]	= &s3c_fb_data_s5p_wins[4],
+};
+
+/* S3C2443/S3C2416 style hardware */
+static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
+	.variant = {
+		.nr_windows	= 2,
+		.is_2443	= 1,
+
+		.vidtcon	= 0x08,
+		.wincon		= 0x14,
+		.winmap		= 0xd0,
+		.keycon		= 0xb0,
+		.osd		= 0x28,
+		.osd_stride	= 12,
+		.buf_start	= 0x64,
+		.buf_size	= 0x94,
+		.buf_end	= 0x7c,
+
+		.palette = {
+			[0] = 0x400,
+			[1] = 0x800,
+		},
+		.has_clksel	= 1,
+	},
+	.win[0] = &(struct s3c_fb_win_variant) {
+		.palette_sz	= 256,
+		.valid_bpp	= VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
+	},
+	.win[1] = &(struct s3c_fb_win_variant) {
+		.has_osd_c	= 1,
+		.has_osd_alpha	= 1,
+		.palette_sz	= 256,
+		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
+				   VALID_BPP(18) | VALID_BPP(19) |
+				   VALID_BPP(24) | VALID_BPP(25) |
+				   VALID_BPP(28)),
+	},
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
+	.variant = {
+		.nr_windows	= 3,
+		.vidtcon	= VIDTCON0,
+		.wincon		= WINCON(0),
+		.winmap		= WINxMAP(0),
+		.keycon		= WKEYCON,
+		.osd		= VIDOSD_BASE,
+		.osd_stride	= 16,
+		.buf_start	= VIDW_BUF_START(0),
+		.buf_size	= VIDW_BUF_SIZE(0),
+		.buf_end	= VIDW_BUF_END(0),
+
+		.palette = {
+			[0] = 0x2400,
+			[1] = 0x2800,
+			[2] = 0x2c00,
+		},
+
+		.has_blendcon	= 1,
+		.has_fixvclk	= 1,
+	},
+	.win[0] = &s3c_fb_data_s5p_wins[0],
+	.win[1] = &s3c_fb_data_s5p_wins[1],
+	.win[2] = &s3c_fb_data_s5p_wins[2],
+};
+
+static struct platform_device_id s3c_fb_driver_ids[] = {
+	{
+		.name		= "s3c-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_64xx,
+	}, {
+		.name		= "s5pc100-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_s5pc100,
+	}, {
+		.name		= "s5pv210-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_s5pv210,
+	}, {
+		.name		= "exynos4-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_exynos4,
+	}, {
+		.name		= "exynos5-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_exynos5,
+	}, {
+		.name		= "s3c2443-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_s3c2443,
+	}, {
+		.name		= "s5p64x0-fb",
+		.driver_data	= (unsigned long)&s3c_fb_data_s5p64x0,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
+
+static const struct dev_pm_ops s3cfb_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
+	SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
+			   NULL)
+};
+
+static struct platform_driver s3c_fb_driver = {
+	.probe		= s3c_fb_probe,
+	.remove		= s3c_fb_remove,
+	.id_table	= s3c_fb_driver_ids,
+	.driver		= {
+		.name	= "s3c-fb",
+		.owner	= THIS_MODULE,
+		.pm	= &s3cfb_pm_ops,
+	},
+};
+
+module_platform_driver(s3c_fb_driver);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c-fb");
diff --git a/drivers/video/fbdev/s3c2410fb.c b/drivers/video/fbdev/s3c2410fb.c
new file mode 100644
index 000000000000..81af5a63e9e1
--- /dev/null
+++ b/drivers/video/fbdev/s3c2410fb.c
@@ -0,0 +1,1146 @@
+/* linux/drivers/video/s3c2410fb.c
+ *	Copyright (c) 2004,2005 Arnaud Patard
+ *	Copyright (c) 2004-2008 Ben Dooks
+ *
+ * S3C2410 LCD Framebuffer Driver
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Driver based on skeletonfb.c, sa1100fb.c and others.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/io.h>
+
+#include <asm/div64.h>
+
+#include <asm/mach/map.h>
+#include <mach/regs-lcd.h>
+#include <mach/regs-gpio.h>
+#include <mach/fb.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include "s3c2410fb.h"
+
+/* Debugging stuff */
+#ifdef CONFIG_FB_S3C2410_DEBUG
+static int debug	= 1;
+#else
+static int debug;
+#endif
+
+#define dprintk(msg...) \
+do { \
+	if (debug) \
+		pr_debug(msg); \
+} while (0)
+
+/* useful functions */
+
+static int is_s3c2412(struct s3c2410fb_info *fbi)
+{
+	return (fbi->drv_type == DRV_S3C2412);
+}
+
+/* s3c2410fb_set_lcdaddr
+ *
+ * initialise lcd controller address pointers
+ */
+static void s3c2410fb_set_lcdaddr(struct fb_info *info)
+{
+	unsigned long saddr1, saddr2, saddr3;
+	struct s3c2410fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+
+	saddr1  = info->fix.smem_start >> 1;
+	saddr2  = info->fix.smem_start;
+	saddr2 += info->fix.line_length * info->var.yres;
+	saddr2 >>= 1;
+
+	saddr3 = S3C2410_OFFSIZE(0) |
+		 S3C2410_PAGEWIDTH((info->fix.line_length / 2) & 0x3ff);
+
+	dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
+	dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
+	dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
+
+	writel(saddr1, regs + S3C2410_LCDSADDR1);
+	writel(saddr2, regs + S3C2410_LCDSADDR2);
+	writel(saddr3, regs + S3C2410_LCDSADDR3);
+}
+
+/* s3c2410fb_calc_pixclk()
+ *
+ * calculate divisor for clk->pixclk
+ */
+static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
+					  unsigned long pixclk)
+{
+	unsigned long clk = fbi->clk_rate;
+	unsigned long long div;
+
+	/* pixclk is in picoseconds, our clock is in Hz
+	 *
+	 * Hz -> picoseconds is / 10^-12
+	 */
+
+	div = (unsigned long long)clk * pixclk;
+	div >>= 12;			/* div / 2^12 */
+	do_div(div, 625 * 625UL * 625); /* div / 5^12 */
+
+	dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);
+	return div;
+}
+
+/*
+ *	s3c2410fb_check_var():
+ *	Get the video params out of 'var'. If a value doesn't fit, round it up,
+ *	if it's too big, return -EINVAL.
+ *
+ */
+static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	struct s3c2410fb_info *fbi = info->par;
+	struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
+	struct s3c2410fb_display *display = NULL;
+	struct s3c2410fb_display *default_display = mach_info->displays +
+						    mach_info->default_display;
+	int type = default_display->type;
+	unsigned i;
+
+	dprintk("check_var(var=%p, info=%p)\n", var, info);
+
+	/* validate x/y resolution */
+	/* choose default mode if possible */
+	if (var->yres == default_display->yres &&
+	    var->xres == default_display->xres &&
+	    var->bits_per_pixel == default_display->bpp)
+		display = default_display;
+	else
+		for (i = 0; i < mach_info->num_displays; i++)
+			if (type == mach_info->displays[i].type &&
+			    var->yres == mach_info->displays[i].yres &&
+			    var->xres == mach_info->displays[i].xres &&
+			    var->bits_per_pixel == mach_info->displays[i].bpp) {
+				display = mach_info->displays + i;
+				break;
+			}
+
+	if (!display) {
+		dprintk("wrong resolution or depth %dx%d at %d bpp\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* it is always the size as the display */
+	var->xres_virtual = display->xres;
+	var->yres_virtual = display->yres;
+	var->height = display->height;
+	var->width = display->width;
+
+	/* copy lcd settings */
+	var->pixclock = display->pixclock;
+	var->left_margin = display->left_margin;
+	var->right_margin = display->right_margin;
+	var->upper_margin = display->upper_margin;
+	var->lower_margin = display->lower_margin;
+	var->vsync_len = display->vsync_len;
+	var->hsync_len = display->hsync_len;
+
+	fbi->regs.lcdcon5 = display->lcdcon5;
+	/* set display type */
+	fbi->regs.lcdcon1 = display->type;
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	/* set r/g/b positions */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 2:
+	case 4:
+		var->red.offset	= 0;
+		var->red.length	= var->bits_per_pixel;
+		var->green	= var->red;
+		var->blue	= var->red;
+		break;
+	case 8:
+		if (display->type != S3C2410_LCDCON1_TFT) {
+			/* 8 bpp 332 */
+			var->red.length		= 3;
+			var->red.offset		= 5;
+			var->green.length	= 3;
+			var->green.offset	= 2;
+			var->blue.length	= 2;
+			var->blue.offset	= 0;
+		} else {
+			var->red.offset		= 0;
+			var->red.length		= 8;
+			var->green		= var->red;
+			var->blue		= var->red;
+		}
+		break;
+	case 12:
+		/* 12 bpp 444 */
+		var->red.length		= 4;
+		var->red.offset		= 8;
+		var->green.length	= 4;
+		var->green.offset	= 4;
+		var->blue.length	= 4;
+		var->blue.offset	= 0;
+		break;
+
+	default:
+	case 16:
+		if (display->lcdcon5 & S3C2410_LCDCON5_FRM565) {
+			/* 16 bpp, 565 format */
+			var->red.offset		= 11;
+			var->green.offset	= 5;
+			var->blue.offset	= 0;
+			var->red.length		= 5;
+			var->green.length	= 6;
+			var->blue.length	= 5;
+		} else {
+			/* 16 bpp, 5551 format */
+			var->red.offset		= 11;
+			var->green.offset	= 6;
+			var->blue.offset	= 1;
+			var->red.length		= 5;
+			var->green.length	= 5;
+			var->blue.length	= 5;
+		}
+		break;
+	case 32:
+		/* 24 bpp 888 and 8 dummy */
+		var->red.length		= 8;
+		var->red.offset		= 16;
+		var->green.length	= 8;
+		var->green.offset	= 8;
+		var->blue.length	= 8;
+		var->blue.offset	= 0;
+		break;
+	}
+	return 0;
+}
+
+/* s3c2410fb_calculate_stn_lcd_regs
+ *
+ * calculate register values from var settings
+ */
+static void s3c2410fb_calculate_stn_lcd_regs(const struct fb_info *info,
+					     struct s3c2410fb_hw *regs)
+{
+	const struct s3c2410fb_info *fbi = info->par;
+	const struct fb_var_screeninfo *var = &info->var;
+	int type = regs->lcdcon1 & ~S3C2410_LCDCON1_TFT;
+	int hs = var->xres >> 2;
+	unsigned wdly = (var->left_margin >> 4) - 1;
+	unsigned wlh = (var->hsync_len >> 4) - 1;
+
+	if (type != S3C2410_LCDCON1_STN4)
+		hs >>= 1;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		regs->lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
+		break;
+	case 2:
+		regs->lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
+		break;
+	case 4:
+		regs->lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
+		break;
+	case 8:
+		regs->lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
+		hs *= 3;
+		break;
+	case 12:
+		regs->lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
+		hs *= 3;
+		break;
+
+	default:
+		/* invalid pixel depth */
+		dev_err(fbi->dev, "invalid bpp %d\n",
+			var->bits_per_pixel);
+	}
+	/* update X/Y info */
+	dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+		var->left_margin, var->right_margin, var->hsync_len);
+
+	regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+
+	if (wdly > 3)
+		wdly = 3;
+
+	if (wlh > 3)
+		wlh = 3;
+
+	regs->lcdcon3 =	S3C2410_LCDCON3_WDLY(wdly) |
+			S3C2410_LCDCON3_LINEBLANK(var->right_margin / 8) |
+			S3C2410_LCDCON3_HOZVAL(hs - 1);
+
+	regs->lcdcon4 = S3C2410_LCDCON4_WLH(wlh);
+}
+
+/* s3c2410fb_calculate_tft_lcd_regs
+ *
+ * calculate register values from var settings
+ */
+static void s3c2410fb_calculate_tft_lcd_regs(const struct fb_info *info,
+					     struct s3c2410fb_hw *regs)
+{
+	const struct s3c2410fb_info *fbi = info->par;
+	const struct fb_var_screeninfo *var = &info->var;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		regs->lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+		break;
+	case 2:
+		regs->lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+		break;
+	case 4:
+		regs->lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+		break;
+	case 8:
+		regs->lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+		regs->lcdcon5 |= S3C2410_LCDCON5_BSWP |
+				 S3C2410_LCDCON5_FRM565;
+		regs->lcdcon5 &= ~S3C2410_LCDCON5_HWSWP;
+		break;
+	case 16:
+		regs->lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+		regs->lcdcon5 &= ~S3C2410_LCDCON5_BSWP;
+		regs->lcdcon5 |= S3C2410_LCDCON5_HWSWP;
+		break;
+	case 32:
+		regs->lcdcon1 |= S3C2410_LCDCON1_TFT24BPP;
+		regs->lcdcon5 &= ~(S3C2410_LCDCON5_BSWP |
+				   S3C2410_LCDCON5_HWSWP |
+				   S3C2410_LCDCON5_BPP24BL);
+		break;
+	default:
+		/* invalid pixel depth */
+		dev_err(fbi->dev, "invalid bpp %d\n",
+			var->bits_per_pixel);
+	}
+	/* update X/Y info */
+	dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+		var->upper_margin, var->lower_margin, var->vsync_len);
+
+	dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+		var->left_margin, var->right_margin, var->hsync_len);
+
+	regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1) |
+			S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
+			S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
+			S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+
+	regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
+			S3C2410_LCDCON3_HFPD(var->left_margin - 1) |
+			S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+
+	regs->lcdcon4 = S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
+}
+
+/* s3c2410fb_activate_var
+ *
+ * activate (set) the controller from the given framebuffer
+ * information
+ */
+static void s3c2410fb_activate_var(struct fb_info *info)
+{
+	struct s3c2410fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+	int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT;
+	struct fb_var_screeninfo *var = &info->var;
+	int clkdiv;
+
+	clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2);
+
+	dprintk("%s: var->xres  = %d\n", __func__, var->xres);
+	dprintk("%s: var->yres  = %d\n", __func__, var->yres);
+	dprintk("%s: var->bpp   = %d\n", __func__, var->bits_per_pixel);
+
+	if (type == S3C2410_LCDCON1_TFT) {
+		s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);
+		--clkdiv;
+		if (clkdiv < 0)
+			clkdiv = 0;
+	} else {
+		s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);
+		if (clkdiv < 2)
+			clkdiv = 2;
+	}
+
+	fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);
+
+	/* write new registers */
+
+	dprintk("new register set:\n");
+	dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);
+	dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);
+	dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);
+	dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
+	dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
+
+	writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,
+		regs + S3C2410_LCDCON1);
+	writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);
+	writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);
+	writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);
+	writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);
+
+	/* set lcd address pointers */
+	s3c2410fb_set_lcdaddr(info);
+
+	fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,
+	writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);
+}
+
+/*
+ *      s3c2410fb_set_par - Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ */
+static int s3c2410fb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+	case 16:
+	case 12:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 1:
+		info->fix.visual = FB_VISUAL_MONO01;
+		break;
+	default:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
+
+	/* activate this new configuration */
+
+	s3c2410fb_activate_var(info);
+	return 0;
+}
+
+static void schedule_palette_update(struct s3c2410fb_info *fbi,
+				    unsigned int regno, unsigned int val)
+{
+	unsigned long flags;
+	unsigned long irqen;
+	void __iomem *irq_base = fbi->irq_base;
+
+	local_irq_save(flags);
+
+	fbi->palette_buffer[regno] = val;
+
+	if (!fbi->palette_ready) {
+		fbi->palette_ready = 1;
+
+		/* enable IRQ */
+		irqen = readl(irq_base + S3C24XX_LCDINTMSK);
+		irqen &= ~S3C2410_LCDINT_FRSYNC;
+		writel(irqen, irq_base + S3C24XX_LCDINTMSK);
+	}
+
+	local_irq_restore(flags);
+}
+
+/* from pxafb.c */
+static inline unsigned int chan_to_field(unsigned int chan,
+					 struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int s3c2410fb_setcolreg(unsigned regno,
+			       unsigned red, unsigned green, unsigned blue,
+			       unsigned transp, struct fb_info *info)
+{
+	struct s3c2410fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+	unsigned int val;
+
+	/* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n",
+		   regno, red, green, blue); */
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/* true-colour, use pseudo-palette */
+
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red,   &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue,  &info->var.blue);
+
+			pal[regno] = val;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			/* currently assume RGB 5-6-5 mode */
+
+			val  = (red   >>  0) & 0xf800;
+			val |= (green >>  5) & 0x07e0;
+			val |= (blue  >> 11) & 0x001f;
+
+			writel(val, regs + S3C2410_TFTPAL(regno));
+			schedule_palette_update(fbi, regno, val);
+		}
+
+		break;
+
+	default:
+		return 1;	/* unknown type */
+	}
+
+	return 0;
+}
+
+/* s3c2410fb_lcd_enable
+ *
+ * shutdown the lcd controller
+ */
+static void s3c2410fb_lcd_enable(struct s3c2410fb_info *fbi, int enable)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	if (enable)
+		fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
+	else
+		fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
+
+	writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1);
+
+	local_irq_restore(flags);
+}
+
+
+/*
+ *      s3c2410fb_blank
+ *	@blank_mode: the blank mode we want.
+ *	@info: frame buffer structure that represents a single frame buffer
+ *
+ *	Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *	blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *	video mode which doesn't support it. Implements VESA suspend
+ *	and powerdown modes on hardware that supports disabling hsync/vsync:
+ *
+ *	Returns negative errno on error, or zero on success.
+ *
+ */
+static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct s3c2410fb_info *fbi = info->par;
+	void __iomem *tpal_reg = fbi->io;
+
+	dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
+
+	tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
+
+	if (blank_mode == FB_BLANK_POWERDOWN)
+		s3c2410fb_lcd_enable(fbi, 0);
+	else
+		s3c2410fb_lcd_enable(fbi, 1);
+
+	if (blank_mode == FB_BLANK_UNBLANK)
+		writel(0x0, tpal_reg);
+	else {
+		dprintk("setting TPAL to output 0x000000\n");
+		writel(S3C2410_TPAL_EN, tpal_reg);
+	}
+
+	return 0;
+}
+
+static int s3c2410fb_debug_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");
+}
+
+static int s3c2410fb_debug_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t len)
+{
+	if (len < 1)
+		return -EINVAL;
+
+	if (strnicmp(buf, "on", 2) == 0 ||
+	    strnicmp(buf, "1", 1) == 0) {
+		debug = 1;
+		dev_dbg(dev, "s3c2410fb: Debug On");
+	} else if (strnicmp(buf, "off", 3) == 0 ||
+		   strnicmp(buf, "0", 1) == 0) {
+		debug = 0;
+		dev_dbg(dev, "s3c2410fb: Debug Off");
+	} else {
+		return -EINVAL;
+	}
+
+	return len;
+}
+
+static DEVICE_ATTR(debug, 0666, s3c2410fb_debug_show, s3c2410fb_debug_store);
+
+static struct fb_ops s3c2410fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= s3c2410fb_check_var,
+	.fb_set_par	= s3c2410fb_set_par,
+	.fb_blank	= s3c2410fb_blank,
+	.fb_setcolreg	= s3c2410fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/*
+ * s3c2410fb_map_video_memory():
+ *	Allocates the DRAM memory for the frame buffer.  This buffer is
+ *	remapped into a non-cached, non-buffered, memory region to
+ *	allow palette and pixel writes to occur without flushing the
+ *	cache.  Once this area is remapped, all virtual memory
+ *	access to the video memory should occur at the new region.
+ */
+static int s3c2410fb_map_video_memory(struct fb_info *info)
+{
+	struct s3c2410fb_info *fbi = info->par;
+	dma_addr_t map_dma;
+	unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
+
+	dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
+
+	info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
+						   &map_dma, GFP_KERNEL);
+
+	if (info->screen_base) {
+		/* prevent initial garbage on screen */
+		dprintk("map_video_memory: clear %p:%08x\n",
+			info->screen_base, map_size);
+		memset(info->screen_base, 0x00, map_size);
+
+		info->fix.smem_start = map_dma;
+
+		dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\n",
+			info->fix.smem_start, info->screen_base, map_size);
+	}
+
+	return info->screen_base ? 0 : -ENOMEM;
+}
+
+static inline void s3c2410fb_unmap_video_memory(struct fb_info *info)
+{
+	struct s3c2410fb_info *fbi = info->par;
+
+	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+			      info->screen_base, info->fix.smem_start);
+}
+
+static inline void modify_gpio(void __iomem *reg,
+			       unsigned long set, unsigned long mask)
+{
+	unsigned long tmp;
+
+	tmp = readl(reg) & ~mask;
+	writel(tmp | set, reg);
+}
+
+/*
+ * s3c2410fb_init_registers - Initialise all LCD-related registers
+ */
+static int s3c2410fb_init_registers(struct fb_info *info)
+{
+	struct s3c2410fb_info *fbi = info->par;
+	struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
+	unsigned long flags;
+	void __iomem *regs = fbi->io;
+	void __iomem *tpal;
+	void __iomem *lpcsel;
+
+	if (is_s3c2412(fbi)) {
+		tpal = regs + S3C2412_TPAL;
+		lpcsel = regs + S3C2412_TCONSEL;
+	} else {
+		tpal = regs + S3C2410_TPAL;
+		lpcsel = regs + S3C2410_LPCSEL;
+	}
+
+	/* Initialise LCD with values from haret */
+
+	local_irq_save(flags);
+
+	/* modify the gpio(s) with interrupts set (bjd) */
+
+	modify_gpio(S3C2410_GPCUP,  mach_info->gpcup,  mach_info->gpcup_mask);
+	modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
+	modify_gpio(S3C2410_GPDUP,  mach_info->gpdup,  mach_info->gpdup_mask);
+	modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
+
+	local_irq_restore(flags);
+
+	dprintk("LPCSEL    = 0x%08lx\n", mach_info->lpcsel);
+	writel(mach_info->lpcsel, lpcsel);
+
+	dprintk("replacing TPAL %08x\n", readl(tpal));
+
+	/* ensure temporary palette disabled */
+	writel(0x00, tpal);
+
+	return 0;
+}
+
+static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
+{
+	unsigned int i;
+	void __iomem *regs = fbi->io;
+
+	fbi->palette_ready = 0;
+
+	for (i = 0; i < 256; i++) {
+		unsigned long ent = fbi->palette_buffer[i];
+		if (ent == PALETTE_BUFF_CLEAR)
+			continue;
+
+		writel(ent, regs + S3C2410_TFTPAL(i));
+
+		/* it seems the only way to know exactly
+		 * if the palette wrote ok, is to check
+		 * to see if the value verifies ok
+		 */
+
+		if (readw(regs + S3C2410_TFTPAL(i)) == ent)
+			fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+		else
+			fbi->palette_ready = 1;   /* retry */
+	}
+}
+
+static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
+{
+	struct s3c2410fb_info *fbi = dev_id;
+	void __iomem *irq_base = fbi->irq_base;
+	unsigned long lcdirq = readl(irq_base + S3C24XX_LCDINTPND);
+
+	if (lcdirq & S3C2410_LCDINT_FRSYNC) {
+		if (fbi->palette_ready)
+			s3c2410fb_write_palette(fbi);
+
+		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND);
+		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
+					unsigned long val, void *data)
+{
+	struct s3c2410fb_info *info;
+	struct fb_info *fbinfo;
+	long delta_f;
+
+	info = container_of(nb, struct s3c2410fb_info, freq_transition);
+	fbinfo = platform_get_drvdata(to_platform_device(info->dev));
+
+	/* work out change, <0 for speed-up */
+	delta_f = info->clk_rate - clk_get_rate(info->clk);
+
+	if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
+	    (val == CPUFREQ_PRECHANGE && delta_f < 0)) {
+		info->clk_rate = clk_get_rate(info->clk);
+		s3c2410fb_activate_var(fbinfo);
+	}
+
+	return 0;
+}
+
+static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info)
+{
+	info->freq_transition.notifier_call = s3c2410fb_cpufreq_transition;
+
+	return cpufreq_register_notifier(&info->freq_transition,
+					 CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
+{
+	cpufreq_unregister_notifier(&info->freq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info)
+{
+	return 0;
+}
+
+static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
+{
+}
+#endif
+
+
+static const char driver_name[] = "s3c2410fb";
+
+static int s3c24xxfb_probe(struct platform_device *pdev,
+			   enum s3c_drv_type drv_type)
+{
+	struct s3c2410fb_info *info;
+	struct s3c2410fb_display *display;
+	struct fb_info *fbinfo;
+	struct s3c2410fb_mach_info *mach_info;
+	struct resource *res;
+	int ret;
+	int irq;
+	int i;
+	int size;
+	u32 lcdcon1;
+
+	mach_info = dev_get_platdata(&pdev->dev);
+	if (mach_info == NULL) {
+		dev_err(&pdev->dev,
+			"no platform data for lcd, cannot attach\n");
+		return -EINVAL;
+	}
+
+	if (mach_info->default_display >= mach_info->num_displays) {
+		dev_err(&pdev->dev, "default is %d but only %d displays\n",
+			mach_info->default_display, mach_info->num_displays);
+		return -EINVAL;
+	}
+
+	display = mach_info->displays + mach_info->default_display;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq for device\n");
+		return -ENOENT;
+	}
+
+	fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);
+	if (!fbinfo)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	info = fbinfo->par;
+	info->dev = &pdev->dev;
+	info->drv_type = drv_type;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get memory registers\n");
+		ret = -ENXIO;
+		goto dealloc_fb;
+	}
+
+	size = resource_size(res);
+	info->mem = request_mem_region(res->start, size, pdev->name);
+	if (info->mem == NULL) {
+		dev_err(&pdev->dev, "failed to get memory region\n");
+		ret = -ENOENT;
+		goto dealloc_fb;
+	}
+
+	info->io = ioremap(res->start, size);
+	if (info->io == NULL) {
+		dev_err(&pdev->dev, "ioremap() of registers failed\n");
+		ret = -ENXIO;
+		goto release_mem;
+	}
+
+	if (drv_type == DRV_S3C2412)
+		info->irq_base = info->io + S3C2412_LCDINTBASE;
+	else
+		info->irq_base = info->io + S3C2410_LCDINTBASE;
+
+	dprintk("devinit\n");
+
+	strcpy(fbinfo->fix.id, driver_name);
+
+	/* Stop the video */
+	lcdcon1 = readl(info->io + S3C2410_LCDCON1);
+	writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
+
+	fbinfo->fix.type	    = FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux	    = 0;
+	fbinfo->fix.xpanstep	    = 0;
+	fbinfo->fix.ypanstep	    = 0;
+	fbinfo->fix.ywrapstep	    = 0;
+	fbinfo->fix.accel	    = FB_ACCEL_NONE;
+
+	fbinfo->var.nonstd	    = 0;
+	fbinfo->var.activate	    = FB_ACTIVATE_NOW;
+	fbinfo->var.accel_flags     = 0;
+	fbinfo->var.vmode	    = FB_VMODE_NONINTERLACED;
+
+	fbinfo->fbops		    = &s3c2410fb_ops;
+	fbinfo->flags		    = FBINFO_FLAG_DEFAULT;
+	fbinfo->pseudo_palette      = &info->pseudo_pal;
+
+	for (i = 0; i < 256; i++)
+		info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+
+	ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
+		ret = -EBUSY;
+		goto release_regs;
+	}
+
+	info->clk = clk_get(NULL, "lcd");
+	if (IS_ERR(info->clk)) {
+		dev_err(&pdev->dev, "failed to get lcd clock source\n");
+		ret = PTR_ERR(info->clk);
+		goto release_irq;
+	}
+
+	clk_enable(info->clk);
+	dprintk("got and enabled clock\n");
+
+	usleep_range(1000, 1100);
+
+	info->clk_rate = clk_get_rate(info->clk);
+
+	/* find maximum required memory size for display */
+	for (i = 0; i < mach_info->num_displays; i++) {
+		unsigned long smem_len = mach_info->displays[i].xres;
+
+		smem_len *= mach_info->displays[i].yres;
+		smem_len *= mach_info->displays[i].bpp;
+		smem_len >>= 3;
+		if (fbinfo->fix.smem_len < smem_len)
+			fbinfo->fix.smem_len = smem_len;
+	}
+
+	/* Initialize video memory */
+	ret = s3c2410fb_map_video_memory(fbinfo);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
+		ret = -ENOMEM;
+		goto release_clock;
+	}
+
+	dprintk("got video memory\n");
+
+	fbinfo->var.xres = display->xres;
+	fbinfo->var.yres = display->yres;
+	fbinfo->var.bits_per_pixel = display->bpp;
+
+	s3c2410fb_init_registers(fbinfo);
+
+	s3c2410fb_check_var(&fbinfo->var, fbinfo);
+
+	ret = s3c2410fb_cpufreq_register(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register cpufreq\n");
+		goto free_video_memory;
+	}
+
+	ret = register_framebuffer(fbinfo);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n",
+			ret);
+		goto free_cpufreq;
+	}
+
+	/* create device files */
+	ret = device_create_file(&pdev->dev, &dev_attr_debug);
+	if (ret)
+		dev_err(&pdev->dev, "failed to add debug attribute\n");
+
+	dev_info(&pdev->dev, "fb%d: %s frame buffer device\n",
+		fbinfo->node, fbinfo->fix.id);
+
+	return 0;
+
+ free_cpufreq:
+	s3c2410fb_cpufreq_deregister(info);
+free_video_memory:
+	s3c2410fb_unmap_video_memory(fbinfo);
+release_clock:
+	clk_disable(info->clk);
+	clk_put(info->clk);
+release_irq:
+	free_irq(irq, info);
+release_regs:
+	iounmap(info->io);
+release_mem:
+	release_mem_region(res->start, size);
+dealloc_fb:
+	framebuffer_release(fbinfo);
+	return ret;
+}
+
+static int s3c2410fb_probe(struct platform_device *pdev)
+{
+	return s3c24xxfb_probe(pdev, DRV_S3C2410);
+}
+
+static int s3c2412fb_probe(struct platform_device *pdev)
+{
+	return s3c24xxfb_probe(pdev, DRV_S3C2412);
+}
+
+
+/*
+ *  Cleanup
+ */
+static int s3c2410fb_remove(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct s3c2410fb_info *info = fbinfo->par;
+	int irq;
+
+	unregister_framebuffer(fbinfo);
+	s3c2410fb_cpufreq_deregister(info);
+
+	s3c2410fb_lcd_enable(info, 0);
+	usleep_range(1000, 1100);
+
+	s3c2410fb_unmap_video_memory(fbinfo);
+
+	if (info->clk) {
+		clk_disable(info->clk);
+		clk_put(info->clk);
+		info->clk = NULL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, info);
+
+	iounmap(info->io);
+
+	release_mem_region(info->mem->start, resource_size(info->mem));
+
+	framebuffer_release(fbinfo);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* suspend and resume support for the lcd controller */
+static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
+	struct s3c2410fb_info *info = fbinfo->par;
+
+	s3c2410fb_lcd_enable(info, 0);
+
+	/* sleep before disabling the clock, we need to ensure
+	 * the LCD DMA engine is not going to get back on the bus
+	 * before the clock goes off again (bjd) */
+
+	usleep_range(1000, 1100);
+	clk_disable(info->clk);
+
+	return 0;
+}
+
+static int s3c2410fb_resume(struct platform_device *dev)
+{
+	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
+	struct s3c2410fb_info *info = fbinfo->par;
+
+	clk_enable(info->clk);
+	usleep_range(1000, 1100);
+
+	s3c2410fb_init_registers(fbinfo);
+
+	/* re-activate our display after resume */
+	s3c2410fb_activate_var(fbinfo);
+	s3c2410fb_blank(FB_BLANK_UNBLANK, fbinfo);
+
+	return 0;
+}
+
+#else
+#define s3c2410fb_suspend NULL
+#define s3c2410fb_resume  NULL
+#endif
+
+static struct platform_driver s3c2410fb_driver = {
+	.probe		= s3c2410fb_probe,
+	.remove		= s3c2410fb_remove,
+	.suspend	= s3c2410fb_suspend,
+	.resume		= s3c2410fb_resume,
+	.driver		= {
+		.name	= "s3c2410-lcd",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static struct platform_driver s3c2412fb_driver = {
+	.probe		= s3c2412fb_probe,
+	.remove		= s3c2410fb_remove,
+	.suspend	= s3c2410fb_suspend,
+	.resume		= s3c2410fb_resume,
+	.driver		= {
+		.name	= "s3c2412-lcd",
+		.owner	= THIS_MODULE,
+	},
+};
+
+int __init s3c2410fb_init(void)
+{
+	int ret = platform_driver_register(&s3c2410fb_driver);
+
+	if (ret == 0)
+		ret = platform_driver_register(&s3c2412fb_driver);
+
+	return ret;
+}
+
+static void __exit s3c2410fb_cleanup(void)
+{
+	platform_driver_unregister(&s3c2410fb_driver);
+	platform_driver_unregister(&s3c2412fb_driver);
+}
+
+module_init(s3c2410fb_init);
+module_exit(s3c2410fb_cleanup);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c2410-lcd");
+MODULE_ALIAS("platform:s3c2412-lcd");
diff --git a/drivers/video/fbdev/s3c2410fb.h b/drivers/video/fbdev/s3c2410fb.h
new file mode 100644
index 000000000000..47a17bd23011
--- /dev/null
+++ b/drivers/video/fbdev/s3c2410fb.h
@@ -0,0 +1,48 @@
+/*
+ * linux/drivers/video/s3c2410fb.h
+ *	Copyright (c) 2004 Arnaud Patard
+ *
+ *  S3C2410 LCD Framebuffer Driver
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+*/
+
+#ifndef __S3C2410FB_H
+#define __S3C2410FB_H
+
+enum s3c_drv_type {
+	DRV_S3C2410,
+	DRV_S3C2412,
+};
+
+struct s3c2410fb_info {
+	struct device		*dev;
+	struct clk		*clk;
+
+	struct resource		*mem;
+	void __iomem		*io;
+	void __iomem		*irq_base;
+
+	enum s3c_drv_type	drv_type;
+	struct s3c2410fb_hw	regs;
+
+	unsigned long		clk_rate;
+	unsigned int		palette_ready;
+
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+#endif
+
+	/* keep these registers in case we need to re-write palette */
+	u32			palette_buffer[256];
+	u32			pseudo_pal[16];
+};
+
+#define PALETTE_BUFF_CLEAR (0x80000000)	/* entry is clear/invalid */
+
+int s3c2410fb_init(void);
+
+#endif
diff --git a/drivers/video/fbdev/s3fb.c b/drivers/video/fbdev/s3fb.c
new file mode 100644
index 000000000000..9a3f8f1c6aab
--- /dev/null
+++ b/drivers/video/fbdev/s3fb.c
@@ -0,0 +1,1597 @@
+/*
+ * linux/drivers/video/s3fb.c -- Frame buffer device driver for S3 Trio/Virge
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Code is based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ * which is based on the code of neofb.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
+#include <video/vga.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+struct s3fb_info {
+	int chip, rev, mclk_freq;
+	int mtrr_reg;
+	struct vgastate state;
+	struct mutex open_lock;
+	unsigned int ref_count;
+	u32 pseudo_palette[16];
+#ifdef CONFIG_FB_S3_DDC
+	u8 __iomem *mmio;
+	bool ddc_registered;
+	struct i2c_adapter ddc_adapter;
+	struct i2c_algo_bit_data ddc_algo;
+#endif
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+static const struct svga_fb_format s3fb_formats[] = {
+	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 4,  {0, 4, 0},  {0, 4, 0},  {0, 4, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 4,  {0, 4, 0},  {0, 4, 0},  {0, 4, 0}, {0, 0, 0}, 1,
+		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 8,  {0, 8, 0},  {0, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 4, 8},
+	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
+	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
+	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
+	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
+	SVGA_FORMAT_END
+};
+
+
+static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
+	35000, 240000, 14318};
+static const struct svga_pll s3_trio3d_pll = {3, 129, 3, 31, 0, 4,
+	230000, 460000, 14318};
+
+static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
+
+static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
+			"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
+			"S3 Plato/PX", "S3 Aurora64V+", "S3 Virge",
+			"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
+			"S3 Virge/GX2", "S3 Virge/GX2+", "",
+			"S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X",
+			"S3 Trio3D", "S3 Virge/MX"};
+
+#define CHIP_UNKNOWN		0x00
+#define CHIP_732_TRIO32		0x01
+#define CHIP_764_TRIO64		0x02
+#define CHIP_765_TRIO64VP	0x03
+#define CHIP_767_TRIO64UVP	0x04
+#define CHIP_775_TRIO64V2_DX	0x05
+#define CHIP_785_TRIO64V2_GX	0x06
+#define CHIP_551_PLATO_PX	0x07
+#define CHIP_M65_AURORA64VP	0x08
+#define CHIP_325_VIRGE		0x09
+#define CHIP_988_VIRGE_VX	0x0A
+#define CHIP_375_VIRGE_DX	0x0B
+#define CHIP_385_VIRGE_GX	0x0C
+#define CHIP_357_VIRGE_GX2	0x0D
+#define CHIP_359_VIRGE_GX2P	0x0E
+#define CHIP_360_TRIO3D_1X	0x10
+#define CHIP_362_TRIO3D_2X	0x11
+#define CHIP_368_TRIO3D_2X	0x12
+#define CHIP_365_TRIO3D		0x13
+#define CHIP_260_VIRGE_MX	0x14
+
+#define CHIP_XXX_TRIO		0x80
+#define CHIP_XXX_TRIO64V2_DXGX	0x81
+#define CHIP_XXX_VIRGE_DXGX	0x82
+#define CHIP_36X_TRIO3D_1X_2X	0x83
+
+#define CHIP_UNDECIDED_FLAG	0x80
+#define CHIP_MASK		0xFF
+
+#define MMIO_OFFSET		0x1000000
+#define MMIO_SIZE		0x10000
+
+/* CRT timing register sets */
+
+static const struct vga_regset s3_h_total_regs[]        = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END};
+static const struct vga_regset s3_h_display_regs[]      = {{0x01, 0, 7}, {0x5D, 1, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x5D, 2, 2}, VGA_REGSET_END};
+static const struct vga_regset s3_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7}, VGA_REGSET_END};
+static const struct vga_regset s3_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x5D, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset s3_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
+
+static const struct vga_regset s3_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x5E, 0, 0}, VGA_REGSET_END};
+static const struct vga_regset s3_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x5E, 1, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x5E, 2, 2}, VGA_REGSET_END};
+static const struct vga_regset s3_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
+static const struct vga_regset s3_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x5E, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset s3_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
+
+static const struct vga_regset s3_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset s3_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x69, 0, 4}, VGA_REGSET_END};
+static const struct vga_regset s3_offset_regs[]         = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */
+
+static const struct vga_regset s3_dtpc_regs[]		= {{0x3B, 0, 7}, {0x5D, 6, 6}, VGA_REGSET_END};
+
+static const struct svga_timing_regs s3_timing_regs     = {
+	s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs,
+	s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs,
+	s3_v_total_regs, s3_v_display_regs, s3_v_blank_start_regs,
+	s3_v_blank_end_regs, s3_v_sync_start_regs, s3_v_sync_end_regs,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Module parameters */
+
+
+static char *mode_option;
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+static int fasttext = 1;
+
+
+MODULE_AUTHOR("(c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for S3 Trio/Virge");
+
+module_param(mode_option, charp, 0444);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+module_param_named(mode, mode_option, charp, 0444);
+MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
+
+module_param(fasttext, int, 0644);
+MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, default=1)");
+
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_FB_S3_DDC
+
+#define DDC_REG		0xaa		/* Trio 3D/1X/2X */
+#define DDC_MMIO_REG	0xff20		/* all other chips */
+#define DDC_SCL_OUT	(1 << 0)
+#define DDC_SDA_OUT	(1 << 1)
+#define DDC_SCL_IN	(1 << 2)
+#define DDC_SDA_IN	(1 << 3)
+#define DDC_DRIVE_EN	(1 << 4)
+
+static bool s3fb_ddc_needs_mmio(int chip)
+{
+	return !(chip == CHIP_360_TRIO3D_1X  ||
+		 chip == CHIP_362_TRIO3D_2X  ||
+		 chip == CHIP_368_TRIO3D_2X);
+}
+
+static u8 s3fb_ddc_read(struct s3fb_info *par)
+{
+	if (s3fb_ddc_needs_mmio(par->chip))
+		return readb(par->mmio + DDC_MMIO_REG);
+	else
+		return vga_rcrt(par->state.vgabase, DDC_REG);
+}
+
+static void s3fb_ddc_write(struct s3fb_info *par, u8 val)
+{
+	if (s3fb_ddc_needs_mmio(par->chip))
+		writeb(val, par->mmio + DDC_MMIO_REG);
+	else
+		vga_wcrt(par->state.vgabase, DDC_REG, val);
+}
+
+static void s3fb_ddc_setscl(void *data, int val)
+{
+	struct s3fb_info *par = data;
+	unsigned char reg;
+
+	reg = s3fb_ddc_read(par) | DDC_DRIVE_EN;
+	if (val)
+		reg |= DDC_SCL_OUT;
+	else
+		reg &= ~DDC_SCL_OUT;
+	s3fb_ddc_write(par, reg);
+}
+
+static void s3fb_ddc_setsda(void *data, int val)
+{
+	struct s3fb_info *par = data;
+	unsigned char reg;
+
+	reg = s3fb_ddc_read(par) | DDC_DRIVE_EN;
+	if (val)
+		reg |= DDC_SDA_OUT;
+	else
+		reg &= ~DDC_SDA_OUT;
+	s3fb_ddc_write(par, reg);
+}
+
+static int s3fb_ddc_getscl(void *data)
+{
+	struct s3fb_info *par = data;
+
+	return !!(s3fb_ddc_read(par) & DDC_SCL_IN);
+}
+
+static int s3fb_ddc_getsda(void *data)
+{
+	struct s3fb_info *par = data;
+
+	return !!(s3fb_ddc_read(par) & DDC_SDA_IN);
+}
+
+static int s3fb_setup_ddc_bus(struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+
+	strlcpy(par->ddc_adapter.name, info->fix.id,
+		sizeof(par->ddc_adapter.name));
+	par->ddc_adapter.owner		= THIS_MODULE;
+	par->ddc_adapter.class		= I2C_CLASS_DDC;
+	par->ddc_adapter.algo_data	= &par->ddc_algo;
+	par->ddc_adapter.dev.parent	= info->device;
+	par->ddc_algo.setsda		= s3fb_ddc_setsda;
+	par->ddc_algo.setscl		= s3fb_ddc_setscl;
+	par->ddc_algo.getsda		= s3fb_ddc_getsda;
+	par->ddc_algo.getscl		= s3fb_ddc_getscl;
+	par->ddc_algo.udelay		= 10;
+	par->ddc_algo.timeout		= 20;
+	par->ddc_algo.data		= par;
+
+	i2c_set_adapdata(&par->ddc_adapter, par);
+
+	/*
+	 * some Virge cards have external MUX to switch chip I2C bus between
+	 * DDC and extension pins - switch it do DDC
+	 */
+/*	vga_wseq(par->state.vgabase, 0x08, 0x06); - not needed, already unlocked */
+	if (par->chip == CHIP_357_VIRGE_GX2 ||
+	    par->chip == CHIP_359_VIRGE_GX2P ||
+	    par->chip == CHIP_260_VIRGE_MX)
+		svga_wseq_mask(par->state.vgabase, 0x0d, 0x01, 0x03);
+	else
+		svga_wseq_mask(par->state.vgabase, 0x0d, 0x00, 0x03);
+	/* some Virge need this or the DDC is ignored */
+	svga_wcrt_mask(par->state.vgabase, 0x5c, 0x03, 0x03);
+
+	return i2c_bit_add_bus(&par->ddc_adapter);
+}
+#endif /* CONFIG_FB_S3_DDC */
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Set font in S3 fast text mode */
+
+static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8 __iomem *fb = (u8 __iomem *) info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+		       map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (i = 0; i < map->height; i++) {
+		for (c = 0; c < map->length; c++) {
+			fb_writeb(font[c * map->height + i], fb + c * 4);
+		}
+		fb += 1024;
+	}
+}
+
+static void s3fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
+{
+	struct s3fb_info *par = info->par;
+
+	svga_tilecursor(par->state.vgabase, info, cursor);
+}
+
+static struct fb_tile_ops s3fb_tile_ops = {
+	.fb_settile	= svga_settile,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = s3fb_tilecursor,
+	.fb_get_tilemax = svga_get_tilemax,
+};
+
+static struct fb_tile_ops s3fb_fast_tile_ops = {
+	.fb_settile	= s3fb_settile_fast,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = s3fb_tilecursor,
+	.fb_get_tilemax = svga_get_tilemax,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/* image data is MSB-first, fb structure is MSB-first too */
+static inline u32 expand_color(u32 c)
+{
+	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
+}
+
+/* s3fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = expand_color(image->fg_color);
+	u32 bg = expand_color(image->bg_color);
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = *(src++) * 0x01010101;
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+
+}
+
+/* s3fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u32 fg = expand_color(rect->color);
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	int x, y;
+
+	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
+		 + ((rect->dx / 8) * 4);
+
+	for (y = 0; y < rect->height; y++) {
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < rect->width; x += 8) {
+			fb_writel(fg, dst++);
+		}
+		dst1 += info->fix.line_length;
+	}
+}
+
+
+/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
+static inline u32 expand_pixel(u32 c)
+{
+	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
+		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
+}
+
+/* s3fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = image->fg_color * 0x11111111;
+	u32 bg = image->bg_color * 0x11111111;
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = expand_pixel(*(src++));
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+}
+
+static void s3fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
+	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
+		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
+			s3fb_iplan_imageblit(info, image);
+		else
+			s3fb_cfb4_imageblit(info, image);
+	} else
+		cfb_imageblit(info, image);
+}
+
+static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	if ((info->var.bits_per_pixel == 4)
+	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
+	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
+		s3fb_iplan_fillrect(info, rect);
+	 else
+		cfb_fillrect(info, rect);
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
+{
+	struct s3fb_info *par = info->par;
+	u16 m, n, r;
+	u8 regval;
+	int rv;
+
+	rv = svga_compute_pll((par->chip == CHIP_365_TRIO3D) ? &s3_trio3d_pll : &s3_pll,
+			      1000000000 / pixclock, &m, &n, &r, info->node);
+	if (rv < 0) {
+		fb_err(info, "cannot set requested pixclock, keeping old value\n");
+		return;
+	}
+
+	/* Set VGA misc register  */
+	regval = vga_r(par->state.vgabase, VGA_MIS_R);
+	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
+
+	/* Set S3 clock registers */
+	if (par->chip == CHIP_357_VIRGE_GX2 ||
+	    par->chip == CHIP_359_VIRGE_GX2P ||
+	    par->chip == CHIP_360_TRIO3D_1X ||
+	    par->chip == CHIP_362_TRIO3D_2X ||
+	    par->chip == CHIP_368_TRIO3D_2X ||
+	    par->chip == CHIP_260_VIRGE_MX) {
+		vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6));	/* n and two bits of r */
+		vga_wseq(par->state.vgabase, 0x29, r >> 2); /* remaining highest bit of r */
+	} else
+		vga_wseq(par->state.vgabase, 0x12, (n - 2) | (r << 5));
+	vga_wseq(par->state.vgabase, 0x13, m - 2);
+
+	udelay(1000);
+
+	/* Activate clock - write 0, 1, 0 to seq/15 bit 5 */
+	regval = vga_rseq (par->state.vgabase, 0x15); /* | 0x80; */
+	vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5));
+	vga_wseq(par->state.vgabase, 0x15, regval |  (1<<5));
+	vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5));
+}
+
+
+/* Open framebuffer */
+
+static int s3fb_open(struct fb_info *info, int user)
+{
+	struct s3fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		void __iomem *vgabase = par->state.vgabase;
+
+		memset(&(par->state), 0, sizeof(struct vgastate));
+		par->state.vgabase = vgabase;
+		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
+		par->state.num_crtc = 0x70;
+		par->state.num_seq = 0x20;
+		save_vga(&(par->state));
+	}
+
+	par->ref_count++;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Close framebuffer */
+
+static int s3fb_release(struct fb_info *info, int user)
+{
+	struct s3fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		return -EINVAL;
+	}
+
+	if (par->ref_count == 1)
+		restore_vga(&(par->state));
+
+	par->ref_count--;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Validate passed in var */
+
+static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+	int rv, mem, step;
+	u16 m, n, r;
+
+	/* Find appropriate format */
+	rv = svga_match_format (s3fb_formats, var, NULL);
+
+	/* 32bpp mode is not supported on VIRGE VX,
+	   24bpp is not supported on others */
+	if ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6))
+		rv = -EINVAL;
+
+	if (rv < 0) {
+		fb_err(info, "unsupported mode requested\n");
+		return rv;
+	}
+
+	/* Do not allow to have real resoulution larger than virtual */
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	/* Round up xres_virtual to have proper alignment of lines */
+	step = s3fb_formats[rv].xresstep - 1;
+	var->xres_virtual = (var->xres_virtual+step) & ~step;
+
+	/* Check whether have enough memory */
+	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
+	if (mem > info->screen_size) {
+		fb_err(info, "not enough framebuffer memory (%d kB requested , %u kB available)\n",
+		       mem >> 10, (unsigned int) (info->screen_size >> 10));
+		return -EINVAL;
+	}
+
+	rv = svga_check_timings (&s3_timing_regs, var, info->node);
+	if (rv < 0) {
+		fb_err(info, "invalid timings requested\n");
+		return rv;
+	}
+
+	rv = svga_compute_pll(&s3_pll, PICOS2KHZ(var->pixclock), &m, &n, &r,
+				info->node);
+	if (rv < 0) {
+		fb_err(info, "invalid pixclock value requested\n");
+		return rv;
+	}
+
+	return 0;
+}
+
+/* Set video mode from par */
+
+static int s3fb_set_par(struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+	u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes;
+	u32 bpp = info->var.bits_per_pixel;
+	u32 htotal, hsstart;
+
+	if (bpp != 0) {
+		info->fix.ypanstep = 1;
+		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
+
+		info->flags &= ~FBINFO_MISC_TILEBLITTING;
+		info->tileops = NULL;
+
+		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
+		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
+		info->pixmap.blit_y = ~(u32)0;
+
+		offset_value = (info->var.xres_virtual * bpp) / 64;
+		screen_size = info->var.yres_virtual * info->fix.line_length;
+	} else {
+		info->fix.ypanstep = 16;
+		info->fix.line_length = 0;
+
+		info->flags |= FBINFO_MISC_TILEBLITTING;
+		info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
+
+		/* supports 8x16 tiles only */
+		info->pixmap.blit_x = 1 << (8 - 1);
+		info->pixmap.blit_y = 1 << (16 - 1);
+
+		offset_value = info->var.xres_virtual / 16;
+		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
+	}
+
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	/* Unlock registers */
+	vga_wcrt(par->state.vgabase, 0x38, 0x48);
+	vga_wcrt(par->state.vgabase, 0x39, 0xA5);
+	vga_wseq(par->state.vgabase, 0x08, 0x06);
+	svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
+
+	/* Blank screen and turn off sync */
+	svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+	svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
+
+	/* Set default values */
+	svga_set_default_gfx_regs(par->state.vgabase);
+	svga_set_default_atc_regs(par->state.vgabase);
+	svga_set_default_seq_regs(par->state.vgabase);
+	svga_set_default_crt_regs(par->state.vgabase);
+	svga_wcrt_multi(par->state.vgabase, s3_line_compare_regs, 0xFFFFFFFF);
+	svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, 0);
+
+	/* S3 specific initialization */
+	svga_wcrt_mask(par->state.vgabase, 0x58, 0x10, 0x10); /* enable linear framebuffer */
+	svga_wcrt_mask(par->state.vgabase, 0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */
+
+/*	svga_wcrt_mask(par->state.vgabase, 0x33, 0x08, 0x08); */ /* DDR ?	*/
+/*	svga_wcrt_mask(par->state.vgabase, 0x43, 0x01, 0x01); */ /* DDR ?	*/
+	svga_wcrt_mask(par->state.vgabase, 0x33, 0x00, 0x08); /* no DDR ?	*/
+	svga_wcrt_mask(par->state.vgabase, 0x43, 0x00, 0x01); /* no DDR ?	*/
+
+	svga_wcrt_mask(par->state.vgabase, 0x5D, 0x00, 0x28); /* Clear strange HSlen bits */
+
+/*	svga_wcrt_mask(par->state.vgabase, 0x58, 0x03, 0x03); */
+
+/*	svga_wcrt_mask(par->state.vgabase, 0x53, 0x12, 0x13); */ /* enable MMIO */
+/*	svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08); */ /* enable write buffer */
+
+
+	/* Set the offset register */
+	fb_dbg(info, "offset register       : %d\n", offset_value);
+	svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value);
+
+	if (par->chip != CHIP_357_VIRGE_GX2 &&
+	    par->chip != CHIP_359_VIRGE_GX2P &&
+	    par->chip != CHIP_360_TRIO3D_1X &&
+	    par->chip != CHIP_362_TRIO3D_2X &&
+	    par->chip != CHIP_368_TRIO3D_2X &&
+	    par->chip != CHIP_260_VIRGE_MX) {
+		vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */
+		vga_wcrt(par->state.vgabase, 0x60, 0xff); /* N parameter */
+		vga_wcrt(par->state.vgabase, 0x61, 0xff); /* L parameter */
+		vga_wcrt(par->state.vgabase, 0x62, 0xff); /* L parameter */
+	}
+
+	vga_wcrt(par->state.vgabase, 0x3A, 0x35);
+	svga_wattr(par->state.vgabase, 0x33, 0x00);
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
+	else
+		svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		svga_wcrt_mask(par->state.vgabase, 0x42, 0x20, 0x20);
+	else
+		svga_wcrt_mask(par->state.vgabase, 0x42, 0x00, 0x20);
+
+	/* Disable hardware graphics cursor */
+	svga_wcrt_mask(par->state.vgabase, 0x45, 0x00, 0x01);
+	/* Disable Streams engine */
+	svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0x0C);
+
+	mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));
+
+	/* S3 virge DX hack */
+	if (par->chip == CHIP_375_VIRGE_DX) {
+		vga_wcrt(par->state.vgabase, 0x86, 0x80);
+		vga_wcrt(par->state.vgabase, 0x90, 0x00);
+	}
+
+	/* S3 virge VX hack */
+	if (par->chip == CHIP_988_VIRGE_VX) {
+		vga_wcrt(par->state.vgabase, 0x50, 0x00);
+		vga_wcrt(par->state.vgabase, 0x67, 0x50);
+		msleep(10); /* screen remains blank sometimes without this */
+		vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
+		vga_wcrt(par->state.vgabase, 0x66, 0x90);
+	}
+
+	if (par->chip == CHIP_357_VIRGE_GX2 ||
+	    par->chip == CHIP_359_VIRGE_GX2P ||
+	    par->chip == CHIP_360_TRIO3D_1X ||
+	    par->chip == CHIP_362_TRIO3D_2X ||
+	    par->chip == CHIP_368_TRIO3D_2X ||
+	    par->chip == CHIP_365_TRIO3D    ||
+	    par->chip == CHIP_375_VIRGE_DX  ||
+	    par->chip == CHIP_385_VIRGE_GX  ||
+	    par->chip == CHIP_260_VIRGE_MX) {
+		dbytes = info->var.xres * ((bpp+7)/8);
+		vga_wcrt(par->state.vgabase, 0x91, (dbytes + 7) / 8);
+		vga_wcrt(par->state.vgabase, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80);
+
+		vga_wcrt(par->state.vgabase, 0x66, 0x81);
+	}
+
+	if (par->chip == CHIP_357_VIRGE_GX2  ||
+	    par->chip == CHIP_359_VIRGE_GX2P ||
+	    par->chip == CHIP_360_TRIO3D_1X ||
+	    par->chip == CHIP_362_TRIO3D_2X ||
+	    par->chip == CHIP_368_TRIO3D_2X ||
+	    par->chip == CHIP_260_VIRGE_MX)
+		vga_wcrt(par->state.vgabase, 0x34, 0x00);
+	else	/* enable Data Transfer Position Control (DTPC) */
+		vga_wcrt(par->state.vgabase, 0x34, 0x10);
+
+	svga_wcrt_mask(par->state.vgabase, 0x31, 0x00, 0x40);
+	multiplex = 0;
+	hmul = 1;
+
+	/* Set mode-specific register values */
+	switch (mode) {
+	case 0:
+		fb_dbg(info, "text mode\n");
+		svga_set_textmode_vga_regs(par->state.vgabase);
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
+		svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
+
+		/* Disable enhanced mode */
+		svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
+
+		if (fasttext) {
+			fb_dbg(info, "high speed text mode set\n");
+			svga_wcrt_mask(par->state.vgabase, 0x31, 0x40, 0x40);
+		}
+		break;
+	case 1:
+		fb_dbg(info, "4 bit pseudocolor\n");
+		vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
+		svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
+
+		/* disable enhanced mode */
+		svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
+		break;
+	case 2:
+		fb_dbg(info, "4 bit pseudocolor, planar\n");
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
+		svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
+
+		/* disable enhanced mode */
+		svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
+		break;
+	case 3:
+		fb_dbg(info, "8 bit pseudocolor\n");
+		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
+		if (info->var.pixclock > 20000 ||
+		    par->chip == CHIP_357_VIRGE_GX2 ||
+		    par->chip == CHIP_359_VIRGE_GX2P ||
+		    par->chip == CHIP_360_TRIO3D_1X ||
+		    par->chip == CHIP_362_TRIO3D_2X ||
+		    par->chip == CHIP_368_TRIO3D_2X ||
+		    par->chip == CHIP_260_VIRGE_MX)
+			svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
+		else {
+			svga_wcrt_mask(par->state.vgabase, 0x67, 0x10, 0xF0);
+			multiplex = 1;
+		}
+		break;
+	case 4:
+		fb_dbg(info, "5/5/5 truecolor\n");
+		if (par->chip == CHIP_988_VIRGE_VX) {
+			if (info->var.pixclock > 20000)
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0);
+			else
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
+		} else if (par->chip == CHIP_365_TRIO3D) {
+			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
+			if (info->var.pixclock > 8695) {
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
+				hmul = 2;
+			} else {
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0);
+				multiplex = 1;
+			}
+		} else {
+			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
+			svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
+			if (par->chip != CHIP_357_VIRGE_GX2 &&
+			    par->chip != CHIP_359_VIRGE_GX2P &&
+			    par->chip != CHIP_360_TRIO3D_1X &&
+			    par->chip != CHIP_362_TRIO3D_2X &&
+			    par->chip != CHIP_368_TRIO3D_2X &&
+			    par->chip != CHIP_260_VIRGE_MX)
+				hmul = 2;
+		}
+		break;
+	case 5:
+		fb_dbg(info, "5/6/5 truecolor\n");
+		if (par->chip == CHIP_988_VIRGE_VX) {
+			if (info->var.pixclock > 20000)
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0);
+			else
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
+		} else if (par->chip == CHIP_365_TRIO3D) {
+			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
+			if (info->var.pixclock > 8695) {
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
+				hmul = 2;
+			} else {
+				svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0);
+				multiplex = 1;
+			}
+		} else {
+			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
+			svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
+			if (par->chip != CHIP_357_VIRGE_GX2 &&
+			    par->chip != CHIP_359_VIRGE_GX2P &&
+			    par->chip != CHIP_360_TRIO3D_1X &&
+			    par->chip != CHIP_362_TRIO3D_2X &&
+			    par->chip != CHIP_368_TRIO3D_2X &&
+			    par->chip != CHIP_260_VIRGE_MX)
+				hmul = 2;
+		}
+		break;
+	case 6:
+		/* VIRGE VX case */
+		fb_dbg(info, "8/8/8 truecolor\n");
+		svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
+		break;
+	case 7:
+		fb_dbg(info, "8/8/8/8 truecolor\n");
+		svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30);
+		svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
+		break;
+	default:
+		fb_err(info, "unsupported mode - bug\n");
+		return -EINVAL;
+	}
+
+	if (par->chip != CHIP_988_VIRGE_VX) {
+		svga_wseq_mask(par->state.vgabase, 0x15, multiplex ? 0x10 : 0x00, 0x10);
+		svga_wseq_mask(par->state.vgabase, 0x18, multiplex ? 0x80 : 0x00, 0x80);
+	}
+
+	s3_set_pixclock(info, info->var.pixclock);
+	svga_set_timings(par->state.vgabase, &s3_timing_regs, &(info->var), hmul, 1,
+			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
+			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
+			 hmul, info->node);
+
+	/* Set interlaced mode start/end register */
+	htotal = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
+	htotal = ((htotal * hmul) / 8) - 5;
+	vga_wcrt(par->state.vgabase, 0x3C, (htotal + 1) / 2);
+
+	/* Set Data Transfer Position */
+	hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8;
+	/* + 2 is needed for Virge/VX, does no harm on other cards */
+	value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1);
+	svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value);
+
+	memset_io(info->screen_base, 0x00, screen_size);
+	/* Device and screen back on */
+	svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
+	svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
+
+	return 0;
+}
+
+/* Set a colour register */
+
+static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+				u_int transp, struct fb_info *fb)
+{
+	switch (fb->var.bits_per_pixel) {
+	case 0:
+	case 4:
+		if (regno >= 16)
+			return -EINVAL;
+
+		if ((fb->var.bits_per_pixel == 4) &&
+		    (fb->var.nonstd == 0)) {
+			outb(0xF0, VGA_PEL_MSK);
+			outb(regno*16, VGA_PEL_IW);
+		} else {
+			outb(0x0F, VGA_PEL_MSK);
+			outb(regno, VGA_PEL_IW);
+		}
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 8:
+		if (regno >= 256)
+			return -EINVAL;
+
+		outb(0xFF, VGA_PEL_MSK);
+		outb(regno, VGA_PEL_IW);
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 16:
+		if (regno >= 16)
+			return 0;
+
+		if (fb->var.green.length == 5)
+			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
+				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+		else if (fb->var.green.length == 6)
+			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
+				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+		else return -EINVAL;
+		break;
+	case 24:
+	case 32:
+		if (regno >= 16)
+			return 0;
+
+		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
+			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/* Set the display blanking state */
+
+static int s3fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		fb_dbg(info, "unblank\n");
+		svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
+		break;
+	case FB_BLANK_NORMAL:
+		fb_dbg(info, "blank\n");
+		svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		fb_dbg(info, "hsync\n");
+		svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		fb_dbg(info, "vsync\n");
+		svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_POWERDOWN:
+		fb_dbg(info, "sync down\n");
+		svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	}
+
+	return 0;
+}
+
+
+/* Pan the display */
+
+static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+	unsigned int offset;
+
+	/* Calculate the offset */
+	if (info->var.bits_per_pixel == 0) {
+		offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
+		       + (var->xoffset / 2);
+		offset = offset >> 2;
+	} else {
+		offset = (var->yoffset * info->fix.line_length) +
+			 (var->xoffset * info->var.bits_per_pixel / 8);
+		offset = offset >> 2;
+	}
+
+	/* Set the offset */
+	svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, offset);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Frame buffer operations */
+
+static struct fb_ops s3fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= s3fb_open,
+	.fb_release	= s3fb_release,
+	.fb_check_var	= s3fb_check_var,
+	.fb_set_par	= s3fb_set_par,
+	.fb_setcolreg	= s3fb_setcolreg,
+	.fb_blank	= s3fb_blank,
+	.fb_pan_display	= s3fb_pan_display,
+	.fb_fillrect	= s3fb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= s3fb_imageblit,
+	.fb_get_caps    = svga_get_caps,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int s3_identification(struct s3fb_info *par)
+{
+	int chip = par->chip;
+
+	if (chip == CHIP_XXX_TRIO) {
+		u8 cr30 = vga_rcrt(par->state.vgabase, 0x30);
+		u8 cr2e = vga_rcrt(par->state.vgabase, 0x2e);
+		u8 cr2f = vga_rcrt(par->state.vgabase, 0x2f);
+
+		if ((cr30 == 0xE0) || (cr30 == 0xE1)) {
+			if (cr2e == 0x10)
+				return CHIP_732_TRIO32;
+			if (cr2e == 0x11) {
+				if (! (cr2f & 0x40))
+					return CHIP_764_TRIO64;
+				else
+					return CHIP_765_TRIO64VP;
+			}
+		}
+	}
+
+	if (chip == CHIP_XXX_TRIO64V2_DXGX) {
+		u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f);
+
+		if (! (cr6f & 0x01))
+			return CHIP_775_TRIO64V2_DX;
+		else
+			return CHIP_785_TRIO64V2_GX;
+	}
+
+	if (chip == CHIP_XXX_VIRGE_DXGX) {
+		u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f);
+
+		if (! (cr6f & 0x01))
+			return CHIP_375_VIRGE_DX;
+		else
+			return CHIP_385_VIRGE_GX;
+	}
+
+	if (chip == CHIP_36X_TRIO3D_1X_2X) {
+		switch (vga_rcrt(par->state.vgabase, 0x2f)) {
+		case 0x00:
+			return CHIP_360_TRIO3D_1X;
+		case 0x01:
+			return CHIP_362_TRIO3D_2X;
+		case 0x02:
+			return CHIP_368_TRIO3D_2X;
+		}
+	}
+
+	return CHIP_UNKNOWN;
+}
+
+
+/* PCI probe */
+
+static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct pci_bus_region bus_reg;
+	struct resource vga_res;
+	struct fb_info *info;
+	struct s3fb_info *par;
+	int rc;
+	u8 regval, cr38, cr39;
+	bool found = false;
+
+	/* Ignore secondary VGA device because there is no VGA arbitration */
+	if (! svga_primary_device(dev)) {
+		dev_info(&(dev->dev), "ignoring secondary device\n");
+		return -ENODEV;
+	}
+
+	/* Allocate and fill driver data structure */
+	info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev));
+	if (!info) {
+		dev_err(&(dev->dev), "cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	mutex_init(&par->open_lock);
+
+	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+	info->fbops = &s3fb_ops;
+
+	/* Prepare PCI device */
+	rc = pci_enable_device(dev);
+	if (rc < 0) {
+		dev_err(info->device, "cannot enable PCI device\n");
+		goto err_enable_device;
+	}
+
+	rc = pci_request_regions(dev, "s3fb");
+	if (rc < 0) {
+		dev_err(info->device, "cannot reserve framebuffer region\n");
+		goto err_request_regions;
+	}
+
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = pci_resource_len(dev, 0);
+
+	/* Map physical IO memory address into kernel space */
+	info->screen_base = pci_iomap(dev, 0, 0);
+	if (! info->screen_base) {
+		rc = -ENOMEM;
+		dev_err(info->device, "iomap for framebuffer failed\n");
+		goto err_iomap;
+	}
+
+	bus_reg.start = 0;
+	bus_reg.end = 64 * 1024;
+
+	vga_res.flags = IORESOURCE_IO;
+
+	pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
+
+	par->state.vgabase = (void __iomem *) vga_res.start;
+
+	/* Unlock regs */
+	cr38 = vga_rcrt(par->state.vgabase, 0x38);
+	cr39 = vga_rcrt(par->state.vgabase, 0x39);
+	vga_wseq(par->state.vgabase, 0x08, 0x06);
+	vga_wcrt(par->state.vgabase, 0x38, 0x48);
+	vga_wcrt(par->state.vgabase, 0x39, 0xA5);
+
+	/* Identify chip type */
+	par->chip = id->driver_data & CHIP_MASK;
+	par->rev = vga_rcrt(par->state.vgabase, 0x2f);
+	if (par->chip & CHIP_UNDECIDED_FLAG)
+		par->chip = s3_identification(par);
+
+	/* Find how many physical memory there is on card */
+	/* 0x36 register is accessible even if other registers are locked */
+	regval = vga_rcrt(par->state.vgabase, 0x36);
+	if (par->chip == CHIP_360_TRIO3D_1X ||
+	    par->chip == CHIP_362_TRIO3D_2X ||
+	    par->chip == CHIP_368_TRIO3D_2X ||
+	    par->chip == CHIP_365_TRIO3D) {
+		switch ((regval & 0xE0) >> 5) {
+		case 0: /* 8MB -- only 4MB usable for display */
+		case 1: /* 4MB with 32-bit bus */
+		case 2:	/* 4MB */
+			info->screen_size = 4 << 20;
+			break;
+		case 4: /* 2MB on 365 Trio3D */
+		case 6: /* 2MB */
+			info->screen_size = 2 << 20;
+			break;
+		}
+	} else if (par->chip == CHIP_357_VIRGE_GX2 ||
+		   par->chip == CHIP_359_VIRGE_GX2P ||
+		   par->chip == CHIP_260_VIRGE_MX) {
+		switch ((regval & 0xC0) >> 6) {
+		case 1: /* 4MB */
+			info->screen_size = 4 << 20;
+			break;
+		case 3: /* 2MB */
+			info->screen_size = 2 << 20;
+			break;
+		}
+	} else if (par->chip == CHIP_988_VIRGE_VX) {
+		switch ((regval & 0x60) >> 5) {
+		case 0: /* 2MB */
+			info->screen_size = 2 << 20;
+			break;
+		case 1: /* 4MB */
+			info->screen_size = 4 << 20;
+			break;
+		case 2: /* 6MB */
+			info->screen_size = 6 << 20;
+			break;
+		case 3: /* 8MB */
+			info->screen_size = 8 << 20;
+			break;
+		}
+		/* off-screen memory */
+		regval = vga_rcrt(par->state.vgabase, 0x37);
+		switch ((regval & 0x60) >> 5) {
+		case 1: /* 4MB */
+			info->screen_size -= 4 << 20;
+			break;
+		case 2: /* 2MB */
+			info->screen_size -= 2 << 20;
+			break;
+		}
+	} else
+		info->screen_size = s3_memsizes[regval >> 5] << 10;
+	info->fix.smem_len = info->screen_size;
+
+	/* Find MCLK frequency */
+	regval = vga_rseq(par->state.vgabase, 0x10);
+	par->mclk_freq = ((vga_rseq(par->state.vgabase, 0x11) + 2) * 14318) / ((regval & 0x1F)  + 2);
+	par->mclk_freq = par->mclk_freq >> (regval >> 5);
+
+	/* Restore locks */
+	vga_wcrt(par->state.vgabase, 0x38, cr38);
+	vga_wcrt(par->state.vgabase, 0x39, cr39);
+
+	strcpy(info->fix.id, s3_names [par->chip]);
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	info->fix.ypanstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->pseudo_palette = (void*) (par->pseudo_palette);
+	info->var.bits_per_pixel = 8;
+
+#ifdef CONFIG_FB_S3_DDC
+	/* Enable MMIO if needed */
+	if (s3fb_ddc_needs_mmio(par->chip)) {
+		par->mmio = ioremap(info->fix.smem_start + MMIO_OFFSET, MMIO_SIZE);
+		if (par->mmio)
+			svga_wcrt_mask(par->state.vgabase, 0x53, 0x08, 0x08);	/* enable MMIO */
+		else
+			dev_err(info->device, "unable to map MMIO at 0x%lx, disabling DDC",
+				info->fix.smem_start + MMIO_OFFSET);
+	}
+	if (!s3fb_ddc_needs_mmio(par->chip) || par->mmio)
+		if (s3fb_setup_ddc_bus(info) == 0) {
+			u8 *edid = fb_ddc_read(&par->ddc_adapter);
+			par->ddc_registered = true;
+			if (edid) {
+				fb_edid_to_monspecs(edid, &info->monspecs);
+				kfree(edid);
+				if (!info->monspecs.modedb)
+					dev_err(info->device, "error getting mode database\n");
+				else {
+					const struct fb_videomode *m;
+
+					fb_videomode_to_modelist(info->monspecs.modedb,
+								 info->monspecs.modedb_len,
+								 &info->modelist);
+					m = fb_find_best_display(&info->monspecs, &info->modelist);
+					if (m) {
+						fb_videomode_to_var(&info->var, m);
+						/* fill all other info->var's fields */
+						if (s3fb_check_var(&info->var, info) == 0)
+							found = true;
+					}
+				}
+			}
+		}
+#endif
+	if (!mode_option && !found)
+		mode_option = "640x480-8@60";
+
+	/* Prepare startup mode */
+	if (mode_option) {
+		rc = fb_find_mode(&info->var, info, mode_option,
+				   info->monspecs.modedb, info->monspecs.modedb_len,
+				   NULL, info->var.bits_per_pixel);
+		if (!rc || rc == 4) {
+			rc = -EINVAL;
+			dev_err(info->device, "mode %s not found\n", mode_option);
+			fb_destroy_modedb(info->monspecs.modedb);
+			info->monspecs.modedb = NULL;
+			goto err_find_mode;
+		}
+	}
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	/* maximize virtual vertical size for fast scrolling */
+	info->var.yres_virtual = info->fix.smem_len * 8 /
+			(info->var.bits_per_pixel * info->var.xres_virtual);
+	if (info->var.yres_virtual < info->var.yres) {
+		dev_err(info->device, "virtual vertical size smaller than real\n");
+		rc = -EINVAL;
+		goto err_find_mode;
+	}
+
+	rc = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (rc < 0) {
+		dev_err(info->device, "cannot allocate colormap\n");
+		goto err_alloc_cmap;
+	}
+
+	rc = register_framebuffer(info);
+	if (rc < 0) {
+		dev_err(info->device, "cannot register framebuffer\n");
+		goto err_reg_fb;
+	}
+
+	fb_info(info, "%s on %s, %d MB RAM, %d MHz MCLK\n",
+		info->fix.id, pci_name(dev),
+		info->fix.smem_len >> 20, (par->mclk_freq + 500) / 1000);
+
+	if (par->chip == CHIP_UNKNOWN)
+		fb_info(info, "unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n",
+			vga_rcrt(par->state.vgabase, 0x2d),
+			vga_rcrt(par->state.vgabase, 0x2e),
+			vga_rcrt(par->state.vgabase, 0x2f),
+			vga_rcrt(par->state.vgabase, 0x30));
+
+	/* Record a reference to the driver data */
+	pci_set_drvdata(dev, info);
+
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		par->mtrr_reg = -1;
+		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+	}
+#endif
+
+	return 0;
+
+	/* Error handling */
+err_reg_fb:
+	fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+#ifdef CONFIG_FB_S3_DDC
+	if (par->ddc_registered)
+		i2c_del_adapter(&par->ddc_adapter);
+	if (par->mmio)
+		iounmap(par->mmio);
+#endif
+	pci_iounmap(dev, info->screen_base);
+err_iomap:
+	pci_release_regions(dev);
+err_request_regions:
+/*	pci_disable_device(dev); */
+err_enable_device:
+	framebuffer_release(info);
+	return rc;
+}
+
+
+/* PCI remove */
+
+static void s3_pci_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info __maybe_unused *par = info->par;
+
+	if (info) {
+
+#ifdef CONFIG_MTRR
+		if (par->mtrr_reg >= 0) {
+			mtrr_del(par->mtrr_reg, 0, 0);
+			par->mtrr_reg = -1;
+		}
+#endif
+
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+#ifdef CONFIG_FB_S3_DDC
+		if (par->ddc_registered)
+			i2c_del_adapter(&par->ddc_adapter);
+		if (par->mmio)
+			iounmap(par->mmio);
+#endif
+
+		pci_iounmap(dev, info->screen_base);
+		pci_release_regions(dev);
+/*		pci_disable_device(dev); */
+
+		framebuffer_release(info);
+	}
+}
+
+/* PCI suspend */
+
+static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+
+	dev_info(info->device, "suspend\n");
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
+		mutex_unlock(&(par->open_lock));
+		console_unlock();
+		return 0;
+	}
+
+	fb_set_suspend(info, 1);
+
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
+
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+
+	return 0;
+}
+
+
+/* PCI resume */
+
+static int s3_pci_resume(struct pci_dev* dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+	int err;
+
+	dev_info(info->device, "resume\n");
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		console_unlock();
+		return 0;
+	}
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+	err = pci_enable_device(dev);
+	if (err) {
+		mutex_unlock(&(par->open_lock));
+		console_unlock();
+		dev_err(info->device, "error %d enabling device for resume\n", err);
+		return err;
+	}
+	pci_set_master(dev);
+
+	s3fb_set_par(info);
+	fb_set_suspend(info, 0);
+
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+
+	return 0;
+}
+
+
+/* List of boards that we are trying to support */
+
+static struct pci_device_id s3_devices[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8810), .driver_data = CHIP_XXX_TRIO},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8811), .driver_data = CHIP_XXX_TRIO},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8812), .driver_data = CHIP_M65_AURORA64VP},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8814), .driver_data = CHIP_767_TRIO64UVP},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8901), .driver_data = CHIP_XXX_TRIO64V2_DXGX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8902), .driver_data = CHIP_551_PLATO_PX},
+
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8C01), .driver_data = CHIP_260_VIRGE_MX},
+
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+
+MODULE_DEVICE_TABLE(pci, s3_devices);
+
+static struct pci_driver s3fb_pci_driver = {
+	.name		= "s3fb",
+	.id_table	= s3_devices,
+	.probe		= s3_pci_probe,
+	.remove		= s3_pci_remove,
+	.suspend	= s3_pci_suspend,
+	.resume		= s3_pci_resume,
+};
+
+/* Parse user specified options */
+
+#ifndef MODULE
+static int  __init s3fb_setup(char *options)
+{
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+
+		if (!*opt)
+			continue;
+#ifdef CONFIG_MTRR
+		else if (!strncmp(opt, "mtrr:", 5))
+			mtrr = simple_strtoul(opt + 5, NULL, 0);
+#endif
+		else if (!strncmp(opt, "fasttext:", 9))
+			fasttext = simple_strtoul(opt + 9, NULL, 0);
+		else
+			mode_option = opt;
+	}
+
+	return 0;
+}
+#endif
+
+/* Cleanup */
+
+static void __exit s3fb_cleanup(void)
+{
+	pr_debug("s3fb: cleaning up\n");
+	pci_unregister_driver(&s3fb_pci_driver);
+}
+
+/* Driver Initialisation */
+
+static int __init s3fb_init(void)
+{
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("s3fb", &option))
+		return -ENODEV;
+	s3fb_setup(option);
+#endif
+
+	pr_debug("s3fb: initializing\n");
+	return pci_register_driver(&s3fb_pci_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Modularization */
+
+module_init(s3fb_init);
+module_exit(s3fb_cleanup);
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
new file mode 100644
index 000000000000..580c444ec301
--- /dev/null
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -0,0 +1,1340 @@
+/*
+ *  linux/drivers/video/sa1100fb.c
+ *
+ *  Copyright (C) 1999 Eric A. Thomas
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *	        StrongARM 1100 LCD Controller Frame Buffer Driver
+ *
+ * Please direct your questions and comments on this driver to the following
+ * email address:
+ *
+ *	linux-arm-kernel@lists.arm.linux.org.uk
+ *
+ * Clean patches should be sent to the ARM Linux Patch System.  Please see the
+ * following web page for more information:
+ *
+ *	http://www.arm.linux.org.uk/developer/patches/info.shtml
+ *
+ * Thank you.
+ *
+ * Known problems:
+ *	- With the Neponset plugged into an Assabet, LCD powerdown
+ *	  doesn't work (LCD stays powered up).  Therefore we shouldn't
+ *	  blank the screen.
+ *	- We don't limit the CPU clock rate nor the mode selection
+ *	  according to the available SDRAM bandwidth.
+ *
+ * Other notes:
+ *	- Linear grayscale palettes and the kernel.
+ *	  Such code does not belong in the kernel.  The kernel frame buffer
+ *	  drivers do not expect a linear colourmap, but a colourmap based on
+ *	  the VT100 standard mapping.
+ *
+ *	  If your _userspace_ requires a linear colourmap, then the setup of
+ *	  such a colourmap belongs _in userspace_, not in the kernel.  Code
+ *	  to set the colourmap correctly from user space has been sent to
+ *	  David Neuer.  It's around 8 lines of C code, plus another 4 to
+ *	  detect if we are using grayscale.
+ *
+ *	- The following must never be specified in a panel definition:
+ *	     LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
+ *
+ *	- The following should be specified:
+ *	     either LCCR0_Color or LCCR0_Mono
+ *	     either LCCR0_Sngl or LCCR0_Dual
+ *	     either LCCR0_Act or LCCR0_Pas
+ *	     either LCCR3_OutEnH or LCCD3_OutEnL
+ *	     either LCCR3_PixRsEdg or LCCR3_PixFlEdg
+ *	     either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
+ *
+ * Code Status:
+ * 1999/04/01:
+ *	- Driver appears to be working for Brutus 320x200x8bpp mode.  Other
+ *	  resolutions are working, but only the 8bpp mode is supported.
+ *	  Changes need to be made to the palette encode and decode routines
+ *	  to support 4 and 16 bpp modes.  
+ *	  Driver is not designed to be a module.  The FrameBuffer is statically
+ *	  allocated since dynamic allocation of a 300k buffer cannot be 
+ *	  guaranteed. 
+ *
+ * 1999/06/17:
+ *	- FrameBuffer memory is now allocated at run-time when the
+ *	  driver is initialized.    
+ *
+ * 2000/04/10: Nicolas Pitre <nico@fluxnic.net>
+ *	- Big cleanup for dynamic selection of machine type at run time.
+ *
+ * 2000/07/19: Jamey Hicks <jamey@crl.dec.com>
+ *	- Support for Bitsy aka Compaq iPAQ H3600 added.
+ *
+ * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com>
+ *	       Jeff Sutherland <jsutherland@accelent.com>
+ *	- Resolved an issue caused by a change made to the Assabet's PLD 
+ *	  earlier this year which broke the framebuffer driver for newer 
+ *	  Phase 4 Assabets.  Some other parameters were changed to optimize
+ *	  for the Sharp display.
+ *
+ * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp>
+ *	- XP860 support added
+ *
+ * 2000/08/19: Mark Huang <mhuang@livetoy.com>
+ *	- Allows standard options to be passed on the kernel command line
+ *	  for most common passive displays.
+ *
+ * 2000/08/29:
+ *	- s/save_flags_cli/local_irq_save/
+ *	- remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller
+ *
+ * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
+ *	- Updated LART stuff. Fixed some minor bugs.
+ *
+ * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw>
+ *	- Pangolin support added
+ *
+ * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de>
+ *	- Huw Webpanel support added
+ *
+ * 2000/11/23: Eric Peng <ericpeng@coventive.com>
+ *	- Freebird add
+ *
+ * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> 
+ *	       Cliff Brake <cbrake@accelent.com>
+ *	- Added PM callback
+ *
+ * 2001/05/26: <rmk@arm.linux.org.uk>
+ *	- Fix 16bpp so that (a) we use the right colours rather than some
+ *	  totally random colour depending on what was in page 0, and (b)
+ *	  we don't de-reference a NULL pointer.
+ *	- remove duplicated implementation of consistent_alloc()
+ *	- convert dma address types to dma_addr_t
+ *	- remove unused 'montype' stuff
+ *	- remove redundant zero inits of init_var after the initial
+ *	  memset.
+ *	- remove allow_modeset (acornfb idea does not belong here)
+ *
+ * 2001/05/28: <rmk@arm.linux.org.uk>
+ *	- massive cleanup - move machine dependent data into structures
+ *	- I've left various #warnings in - if you see one, and know
+ *	  the hardware concerned, please get in contact with me.
+ *
+ * 2001/05/31: <rmk@arm.linux.org.uk>
+ *	- Fix LCCR1 HSW value, fix all machine type specifications to
+ *	  keep values in line.  (Please check your machine type specs)
+ *
+ * 2001/06/10: <rmk@arm.linux.org.uk>
+ *	- Fiddle with the LCD controller from task context only; mainly
+ *	  so that we can run with interrupts on, and sleep.
+ *	- Convert #warnings into #errors.  No pain, no gain. ;)
+ *
+ * 2001/06/14: <rmk@arm.linux.org.uk>
+ *	- Make the palette BPS value for 12bpp come out correctly.
+ *	- Take notice of "greyscale" on any colour depth.
+ *	- Make truecolor visuals use the RGB channel encoding information.
+ *
+ * 2001/07/02: <rmk@arm.linux.org.uk>
+ *	- Fix colourmap problems.
+ *
+ * 2001/07/13: <abraham@2d3d.co.za>
+ *	- Added support for the ICP LCD-Kit01 on LART. This LCD is
+ *	  manufactured by Prime View, model no V16C6448AB
+ *
+ * 2001/07/23: <rmk@arm.linux.org.uk>
+ *	- Hand merge version from handhelds.org CVS tree.  See patch
+ *	  notes for 595/1 for more information.
+ *	- Drop 12bpp (it's 16bpp with different colour register mappings).
+ *	- This hardware can not do direct colour.  Therefore we don't
+ *	  support it.
+ *
+ * 2001/07/27: <rmk@arm.linux.org.uk>
+ *	- Halve YRES on dual scan LCDs.
+ *
+ * 2001/08/22: <rmk@arm.linux.org.uk>
+ *	- Add b/w iPAQ pixclock value.
+ *
+ * 2001/10/12: <rmk@arm.linux.org.uk>
+ *	- Add patch 681/1 and clean up stork definitions.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/cpufreq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+
+#include <video/sa1100fb.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <mach/shannon.h>
+
+/*
+ * Complain if VAR is out of range.
+ */
+#define DEBUG_VAR 1
+
+#include "sa1100fb.h"
+
+static const struct sa1100fb_rgb rgb_4 = {
+	.red	= { .offset = 0,  .length = 4, },
+	.green	= { .offset = 0,  .length = 4, },
+	.blue	= { .offset = 0,  .length = 4, },
+	.transp	= { .offset = 0,  .length = 0, },
+};
+
+static const struct sa1100fb_rgb rgb_8 = {
+	.red	= { .offset = 0,  .length = 8, },
+	.green	= { .offset = 0,  .length = 8, },
+	.blue	= { .offset = 0,  .length = 8, },
+	.transp	= { .offset = 0,  .length = 0, },
+};
+
+static const struct sa1100fb_rgb def_rgb_16 = {
+	.red	= { .offset = 11, .length = 5, },
+	.green	= { .offset = 5,  .length = 6, },
+	.blue	= { .offset = 0,  .length = 5, },
+	.transp	= { .offset = 0,  .length = 0, },
+};
+
+
+
+static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
+static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
+
+static inline void sa1100fb_schedule_work(struct sa1100fb_info *fbi, u_int state)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	/*
+	 * We need to handle two requests being made at the same time.
+	 * There are two important cases:
+	 *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
+	 *     We must perform the unblanking, which will do our REENABLE for us.
+	 *  2. When we are blanking, but immediately unblank before we have
+	 *     blanked.  We do the "REENABLE" thing here as well, just to be sure.
+	 */
+	if (fbi->task_state == C_ENABLE && state == C_REENABLE)
+		state = (u_int) -1;
+	if (fbi->task_state == C_DISABLE && state == C_ENABLE)
+		state = C_REENABLE;
+
+	if (state != (u_int)-1) {
+		fbi->task_state = state;
+		schedule_work(&fbi->task);
+	}
+	local_irq_restore(flags);
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/*
+ * Convert bits-per-pixel to a hardware palette PBS value.
+ */
+static inline u_int palette_pbs(struct fb_var_screeninfo *var)
+{
+	int ret = 0;
+	switch (var->bits_per_pixel) {
+	case 4:  ret = 0 << 12;	break;
+	case 8:  ret = 1 << 12; break;
+	case 16: ret = 2 << 12; break;
+	}
+	return ret;
+}
+
+static int
+sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
+		       u_int trans, struct fb_info *info)
+{
+	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+	u_int val, ret = 1;
+
+	if (regno < fbi->palette_size) {
+		val = ((red >> 4) & 0xf00);
+		val |= ((green >> 8) & 0x0f0);
+		val |= ((blue >> 12) & 0x00f);
+
+		if (regno == 0)
+			val |= palette_pbs(&fbi->fb.var);
+
+		fbi->palette_cpu[regno] = val;
+		ret = 0;
+	}
+	return ret;
+}
+
+static int
+sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		   u_int trans, struct fb_info *info)
+{
+	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+	unsigned int val;
+	int ret = 1;
+
+	/*
+	 * If inverse mode was selected, invert all the colours
+	 * rather than the register number.  The register number
+	 * is what you poke into the framebuffer to produce the
+	 * colour you requested.
+	 */
+	if (fbi->inf->cmap_inverse) {
+		red   = 0xffff - red;
+		green = 0xffff - green;
+		blue  = 0xffff - blue;
+	}
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no mater what visual we are using.
+	 */
+	if (fbi->fb.var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 12 or 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = fbi->fb.pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		ret = sa1100fb_setpalettereg(regno, red, green, blue, trans, info);
+		break;
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_CPU_FREQ
+/*
+ *  sa1100fb_display_dma_period()
+ *    Calculate the minimum period (in picoseconds) between two DMA
+ *    requests for the LCD controller.  If we hit this, it means we're
+ *    doing nothing but LCD DMA.
+ */
+static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
+{
+	/*
+	 * Period = pixclock * bits_per_byte * bytes_per_transfer
+	 *		/ memory_bits_per_pixel;
+	 */
+	return var->pixclock * 8 * 16 / var->bits_per_pixel;
+}
+#endif
+
+/*
+ *  sa1100fb_check_var():
+ *    Round up in the following order: bits_per_pixel, xres,
+ *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+ *    bitfields, horizontal timing, vertical timing.
+ */
+static int
+sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+	int rgbidx;
+
+	if (var->xres < MIN_XRES)
+		var->xres = MIN_XRES;
+	if (var->yres < MIN_YRES)
+		var->yres = MIN_YRES;
+	if (var->xres > fbi->inf->xres)
+		var->xres = fbi->inf->xres;
+	if (var->yres > fbi->inf->yres)
+		var->yres = fbi->inf->yres;
+	var->xres_virtual = max(var->xres_virtual, var->xres);
+	var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	dev_dbg(fbi->dev, "var->bits_per_pixel=%d\n", var->bits_per_pixel);
+	switch (var->bits_per_pixel) {
+	case 4:
+		rgbidx = RGB_4;
+		break;
+	case 8:
+		rgbidx = RGB_8;
+		break;
+	case 16:
+		rgbidx = RGB_16;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Copy the RGB parameters for this display
+	 * from the machine specific parameters.
+	 */
+	var->red    = fbi->rgb[rgbidx]->red;
+	var->green  = fbi->rgb[rgbidx]->green;
+	var->blue   = fbi->rgb[rgbidx]->blue;
+	var->transp = fbi->rgb[rgbidx]->transp;
+
+	dev_dbg(fbi->dev, "RGBT length = %d:%d:%d:%d\n",
+		var->red.length, var->green.length, var->blue.length,
+		var->transp.length);
+
+	dev_dbg(fbi->dev, "RGBT offset = %d:%d:%d:%d\n",
+		var->red.offset, var->green.offset, var->blue.offset,
+		var->transp.offset);
+
+#ifdef CONFIG_CPU_FREQ
+	dev_dbg(fbi->dev, "dma period = %d ps, clock = %d kHz\n",
+		sa1100fb_display_dma_period(var),
+		cpufreq_get(smp_processor_id()));
+#endif
+
+	return 0;
+}
+
+static void sa1100fb_set_visual(struct sa1100fb_info *fbi, u32 visual)
+{
+	if (fbi->inf->set_visual)
+		fbi->inf->set_visual(visual);
+}
+
+/*
+ * sa1100fb_set_par():
+ *	Set the user defined part of the display for the specified console
+ */
+static int sa1100fb_set_par(struct fb_info *info)
+{
+	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned long palette_mem_size;
+
+	dev_dbg(fbi->dev, "set_par\n");
+
+	if (var->bits_per_pixel == 16)
+		fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+	else if (!fbi->inf->cmap_static)
+		fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else {
+		/*
+		 * Some people have weird ideas about wanting static
+		 * pseudocolor maps.  I suspect their user space
+		 * applications are broken.
+		 */
+		fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+	}
+
+	fbi->fb.fix.line_length = var->xres_virtual *
+				  var->bits_per_pixel / 8;
+	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
+
+	palette_mem_size = fbi->palette_size * sizeof(u16);
+
+	dev_dbg(fbi->dev, "palette_mem_size = 0x%08lx\n", palette_mem_size);
+
+	fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
+	fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
+
+	/*
+	 * Set (any) board control register to handle new color depth
+	 */
+	sa1100fb_set_visual(fbi, fbi->fb.fix.visual);
+	sa1100fb_activate_var(var, fbi);
+
+	return 0;
+}
+
+#if 0
+static int
+sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+		  struct fb_info *info)
+{
+	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+
+	/*
+	 * Make sure the user isn't doing something stupid.
+	 */
+	if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->inf->cmap_static))
+		return -EINVAL;
+
+	return gen_set_cmap(cmap, kspc, con, info);
+}
+#endif
+
+/*
+ * Formal definition of the VESA spec:
+ *  On
+ *  	This refers to the state of the display when it is in full operation
+ *  Stand-By
+ *  	This defines an optional operating state of minimal power reduction with
+ *  	the shortest recovery time
+ *  Suspend
+ *  	This refers to a level of power management in which substantial power
+ *  	reduction is achieved by the display.  The display can have a longer 
+ *  	recovery time from this state than from the Stand-by state
+ *  Off
+ *  	This indicates that the display is consuming the lowest level of power
+ *  	and is non-operational. Recovery from this state may optionally require
+ *  	the user to manually power on the monitor
+ *
+ *  Now, the fbdev driver adds an additional state, (blank), where they
+ *  turn off the video (maybe by colormap tricks), but don't mess with the
+ *  video itself: think of it semantically between on and Stand-By.
+ *
+ *  So here's what we should do in our fbdev blank routine:
+ *
+ *  	VESA_NO_BLANKING (mode 0)	Video on,  front/back light on
+ *  	VESA_VSYNC_SUSPEND (mode 1)  	Video on,  front/back light off
+ *  	VESA_HSYNC_SUSPEND (mode 2)  	Video on,  front/back light off
+ *  	VESA_POWERDOWN (mode 3)		Video off, front/back light off
+ *
+ *  This will match the matrox implementation.
+ */
+/*
+ * sa1100fb_blank():
+ *	Blank the display by setting all palette values to zero.  Note, the 
+ * 	12 and 16 bpp modes don't really use the palette, so this will not
+ *      blank the display in all modes.  
+ */
+static int sa1100fb_blank(int blank, struct fb_info *info)
+{
+	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+	int i;
+
+	dev_dbg(fbi->dev, "sa1100fb_blank: blank=%d\n", blank);
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			for (i = 0; i < fbi->palette_size; i++)
+				sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
+		sa1100fb_schedule_work(fbi, C_DISABLE);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			fb_set_cmap(&fbi->fb.cmap, info);
+		sa1100fb_schedule_work(fbi, C_ENABLE);
+	}
+	return 0;
+}
+
+static int sa1100fb_mmap(struct fb_info *info,
+			 struct vm_area_struct *vma)
+{
+	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+
+	if (off < info->fix.smem_len) {
+		vma->vm_pgoff += 1; /* skip over the palette */
+		return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu,
+					     fbi->map_dma, fbi->map_size);
+	}
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	return vm_iomap_memory(vma, info->fix.mmio_start, info->fix.mmio_len);
+}
+
+static struct fb_ops sa1100fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= sa1100fb_check_var,
+	.fb_set_par	= sa1100fb_set_par,
+//	.fb_set_cmap	= sa1100fb_set_cmap,
+	.fb_setcolreg	= sa1100fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_blank	= sa1100fb_blank,
+	.fb_mmap	= sa1100fb_mmap,
+};
+
+/*
+ * Calculate the PCD value from the clock rate (in picoseconds).
+ * We take account of the PPCR clock setting.
+ */
+static inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock)
+{
+	unsigned int pcd = cpuclock / 100;
+
+	pcd *= pixclock;
+	pcd /= 10000000;
+
+	return pcd + 1;	/* make up for integer math truncations */
+}
+
+/*
+ * sa1100fb_activate_var():
+ *	Configures LCD Controller based on entries in var parameter.  Settings are      
+ *	only written to the controller if changes were made.  
+ */
+static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
+{
+	struct sa1100fb_lcd_reg new_regs;
+	u_int half_screen_size, yres, pcd;
+	u_long flags;
+
+	dev_dbg(fbi->dev, "Configuring SA1100 LCD\n");
+
+	dev_dbg(fbi->dev, "var: xres=%d hslen=%d lm=%d rm=%d\n",
+		var->xres, var->hsync_len,
+		var->left_margin, var->right_margin);
+	dev_dbg(fbi->dev, "var: yres=%d vslen=%d um=%d bm=%d\n",
+		var->yres, var->vsync_len,
+		var->upper_margin, var->lower_margin);
+
+#if DEBUG_VAR
+	if (var->xres < 16        || var->xres > 1024)
+		dev_err(fbi->dev, "%s: invalid xres %d\n",
+			fbi->fb.fix.id, var->xres);
+	if (var->hsync_len < 1    || var->hsync_len > 64)
+		dev_err(fbi->dev, "%s: invalid hsync_len %d\n",
+			fbi->fb.fix.id, var->hsync_len);
+	if (var->left_margin < 1  || var->left_margin > 255)
+		dev_err(fbi->dev, "%s: invalid left_margin %d\n",
+			fbi->fb.fix.id, var->left_margin);
+	if (var->right_margin < 1 || var->right_margin > 255)
+		dev_err(fbi->dev, "%s: invalid right_margin %d\n",
+			fbi->fb.fix.id, var->right_margin);
+	if (var->yres < 1         || var->yres > 1024)
+		dev_err(fbi->dev, "%s: invalid yres %d\n",
+			fbi->fb.fix.id, var->yres);
+	if (var->vsync_len < 1    || var->vsync_len > 64)
+		dev_err(fbi->dev, "%s: invalid vsync_len %d\n",
+			fbi->fb.fix.id, var->vsync_len);
+	if (var->upper_margin < 0 || var->upper_margin > 255)
+		dev_err(fbi->dev, "%s: invalid upper_margin %d\n",
+			fbi->fb.fix.id, var->upper_margin);
+	if (var->lower_margin < 0 || var->lower_margin > 255)
+		dev_err(fbi->dev, "%s: invalid lower_margin %d\n",
+			fbi->fb.fix.id, var->lower_margin);
+#endif
+
+	new_regs.lccr0 = fbi->inf->lccr0 |
+		LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
+		LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
+
+	new_regs.lccr1 =
+		LCCR1_DisWdth(var->xres) +
+		LCCR1_HorSnchWdth(var->hsync_len) +
+		LCCR1_BegLnDel(var->left_margin) +
+		LCCR1_EndLnDel(var->right_margin);
+
+	/*
+	 * If we have a dual scan LCD, then we need to halve
+	 * the YRES parameter.
+	 */
+	yres = var->yres;
+	if (fbi->inf->lccr0 & LCCR0_Dual)
+		yres /= 2;
+
+	new_regs.lccr2 =
+		LCCR2_DisHght(yres) +
+		LCCR2_VrtSnchWdth(var->vsync_len) +
+		LCCR2_BegFrmDel(var->upper_margin) +
+		LCCR2_EndFrmDel(var->lower_margin);
+
+	pcd = get_pcd(var->pixclock, cpufreq_get(0));
+	new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->inf->lccr3 |
+		(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
+		(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
+
+	dev_dbg(fbi->dev, "nlccr0 = 0x%08lx\n", new_regs.lccr0);
+	dev_dbg(fbi->dev, "nlccr1 = 0x%08lx\n", new_regs.lccr1);
+	dev_dbg(fbi->dev, "nlccr2 = 0x%08lx\n", new_regs.lccr2);
+	dev_dbg(fbi->dev, "nlccr3 = 0x%08lx\n", new_regs.lccr3);
+
+	half_screen_size = var->bits_per_pixel;
+	half_screen_size = half_screen_size * var->xres * var->yres / 16;
+
+	/* Update shadow copy atomically */
+	local_irq_save(flags);
+	fbi->dbar1 = fbi->palette_dma;
+	fbi->dbar2 = fbi->screen_dma + half_screen_size;
+
+	fbi->reg_lccr0 = new_regs.lccr0;
+	fbi->reg_lccr1 = new_regs.lccr1;
+	fbi->reg_lccr2 = new_regs.lccr2;
+	fbi->reg_lccr3 = new_regs.lccr3;
+	local_irq_restore(flags);
+
+	/*
+	 * Only update the registers if the controller is enabled
+	 * and something has changed.
+	 */
+	if (readl_relaxed(fbi->base + LCCR0) != fbi->reg_lccr0 ||
+	    readl_relaxed(fbi->base + LCCR1) != fbi->reg_lccr1 ||
+	    readl_relaxed(fbi->base + LCCR2) != fbi->reg_lccr2 ||
+	    readl_relaxed(fbi->base + LCCR3) != fbi->reg_lccr3 ||
+	    readl_relaxed(fbi->base + DBAR1) != fbi->dbar1 ||
+	    readl_relaxed(fbi->base + DBAR2) != fbi->dbar2)
+		sa1100fb_schedule_work(fbi, C_REENABLE);
+
+	return 0;
+}
+
+/*
+ * NOTE!  The following functions are purely helpers for set_ctrlr_state.
+ * Do not call them directly; set_ctrlr_state does the correct serialisation
+ * to ensure that things happen in the right way 100% of time time.
+ *	-- rmk
+ */
+static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on)
+{
+	dev_dbg(fbi->dev, "backlight o%s\n", on ? "n" : "ff");
+
+	if (fbi->inf->backlight_power)
+		fbi->inf->backlight_power(on);
+}
+
+static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on)
+{
+	dev_dbg(fbi->dev, "LCD power o%s\n", on ? "n" : "ff");
+
+	if (fbi->inf->lcd_power)
+		fbi->inf->lcd_power(on);
+}
+
+static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
+{
+	u_int mask = 0;
+
+	/*
+	 * Enable GPIO<9:2> for LCD use if:
+	 *  1. Active display, or
+	 *  2. Color Dual Passive display
+	 *
+	 * see table 11.8 on page 11-27 in the SA1100 manual
+	 *   -- Erik.
+	 *
+	 * SA1110 spec update nr. 25 says we can and should
+	 * clear LDD15 to 12 for 4 or 8bpp modes with active
+	 * panels.  
+	 */
+	if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
+	    (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
+		mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
+
+		if (fbi->fb.var.bits_per_pixel > 8 ||
+		    (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual)
+			mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12;
+
+	}
+
+	if (mask) {
+		unsigned long flags;
+
+		/*
+		 * SA-1100 requires the GPIO direction register set
+		 * appropriately for the alternate function.  Hence
+		 * we set it here via bitmask rather than excessive
+		 * fiddling via the GPIO subsystem - and even then
+		 * we'll still have to deal with GAFR.
+		 */
+		local_irq_save(flags);
+		GPDR |= mask;
+		GAFR |= mask;
+		local_irq_restore(flags);
+	}
+}
+
+static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
+{
+	dev_dbg(fbi->dev, "Enabling LCD controller\n");
+
+	/*
+	 * Make sure the mode bits are present in the first palette entry
+	 */
+	fbi->palette_cpu[0] &= 0xcfff;
+	fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
+
+	/* Sequence from 11.7.10 */
+	writel_relaxed(fbi->reg_lccr3, fbi->base + LCCR3);
+	writel_relaxed(fbi->reg_lccr2, fbi->base + LCCR2);
+	writel_relaxed(fbi->reg_lccr1, fbi->base + LCCR1);
+	writel_relaxed(fbi->reg_lccr0 & ~LCCR0_LEN, fbi->base + LCCR0);
+	writel_relaxed(fbi->dbar1, fbi->base + DBAR1);
+	writel_relaxed(fbi->dbar2, fbi->base + DBAR2);
+	writel_relaxed(fbi->reg_lccr0 | LCCR0_LEN, fbi->base + LCCR0);
+
+	if (machine_is_shannon())
+		gpio_set_value(SHANNON_GPIO_DISP_EN, 1);
+
+	dev_dbg(fbi->dev, "DBAR1: 0x%08x\n", readl_relaxed(fbi->base + DBAR1));
+	dev_dbg(fbi->dev, "DBAR2: 0x%08x\n", readl_relaxed(fbi->base + DBAR2));
+	dev_dbg(fbi->dev, "LCCR0: 0x%08x\n", readl_relaxed(fbi->base + LCCR0));
+	dev_dbg(fbi->dev, "LCCR1: 0x%08x\n", readl_relaxed(fbi->base + LCCR1));
+	dev_dbg(fbi->dev, "LCCR2: 0x%08x\n", readl_relaxed(fbi->base + LCCR2));
+	dev_dbg(fbi->dev, "LCCR3: 0x%08x\n", readl_relaxed(fbi->base + LCCR3));
+}
+
+static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	u32 lccr0;
+
+	dev_dbg(fbi->dev, "Disabling LCD controller\n");
+
+	if (machine_is_shannon())
+		gpio_set_value(SHANNON_GPIO_DISP_EN, 0);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	add_wait_queue(&fbi->ctrlr_wait, &wait);
+
+	/* Clear LCD Status Register */
+	writel_relaxed(~0, fbi->base + LCSR);
+
+	lccr0 = readl_relaxed(fbi->base + LCCR0);
+	lccr0 &= ~LCCR0_LDM;	/* Enable LCD Disable Done Interrupt */
+	writel_relaxed(lccr0, fbi->base + LCCR0);
+	lccr0 &= ~LCCR0_LEN;	/* Disable LCD Controller */
+	writel_relaxed(lccr0, fbi->base + LCCR0);
+
+	schedule_timeout(20 * HZ / 1000);
+	remove_wait_queue(&fbi->ctrlr_wait, &wait);
+}
+
+/*
+ *  sa1100fb_handle_irq: Handle 'LCD DONE' interrupts.
+ */
+static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
+{
+	struct sa1100fb_info *fbi = dev_id;
+	unsigned int lcsr = readl_relaxed(fbi->base + LCSR);
+
+	if (lcsr & LCSR_LDD) {
+		u32 lccr0 = readl_relaxed(fbi->base + LCCR0) | LCCR0_LDM;
+		writel_relaxed(lccr0, fbi->base + LCCR0);
+		wake_up(&fbi->ctrlr_wait);
+	}
+
+	writel_relaxed(lcsr, fbi->base + LCSR);
+	return IRQ_HANDLED;
+}
+
+/*
+ * This function must be called from task context only, since it will
+ * sleep when disabling the LCD controller, or if we get two contending
+ * processes trying to alter state.
+ */
+static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
+{
+	u_int old_state;
+
+	mutex_lock(&fbi->ctrlr_lock);
+
+	old_state = fbi->state;
+
+	/*
+	 * Hack around fbcon initialisation.
+	 */
+	if (old_state == C_STARTUP && state == C_REENABLE)
+		state = C_ENABLE;
+
+	switch (state) {
+	case C_DISABLE_CLKCHANGE:
+		/*
+		 * Disable controller for clock change.  If the
+		 * controller is already disabled, then do nothing.
+		 */
+		if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
+			fbi->state = state;
+			sa1100fb_disable_controller(fbi);
+		}
+		break;
+
+	case C_DISABLE_PM:
+	case C_DISABLE:
+		/*
+		 * Disable controller
+		 */
+		if (old_state != C_DISABLE) {
+			fbi->state = state;
+
+			__sa1100fb_backlight_power(fbi, 0);
+			if (old_state != C_DISABLE_CLKCHANGE)
+				sa1100fb_disable_controller(fbi);
+			__sa1100fb_lcd_power(fbi, 0);
+		}
+		break;
+
+	case C_ENABLE_CLKCHANGE:
+		/*
+		 * Enable the controller after clock change.  Only
+		 * do this if we were disabled for the clock change.
+		 */
+		if (old_state == C_DISABLE_CLKCHANGE) {
+			fbi->state = C_ENABLE;
+			sa1100fb_enable_controller(fbi);
+		}
+		break;
+
+	case C_REENABLE:
+		/*
+		 * Re-enable the controller only if it was already
+		 * enabled.  This is so we reprogram the control
+		 * registers.
+		 */
+		if (old_state == C_ENABLE) {
+			sa1100fb_disable_controller(fbi);
+			sa1100fb_setup_gpio(fbi);
+			sa1100fb_enable_controller(fbi);
+		}
+		break;
+
+	case C_ENABLE_PM:
+		/*
+		 * Re-enable the controller after PM.  This is not
+		 * perfect - think about the case where we were doing
+		 * a clock change, and we suspended half-way through.
+		 */
+		if (old_state != C_DISABLE_PM)
+			break;
+		/* fall through */
+
+	case C_ENABLE:
+		/*
+		 * Power up the LCD screen, enable controller, and
+		 * turn on the backlight.
+		 */
+		if (old_state != C_ENABLE) {
+			fbi->state = C_ENABLE;
+			sa1100fb_setup_gpio(fbi);
+			__sa1100fb_lcd_power(fbi, 1);
+			sa1100fb_enable_controller(fbi);
+			__sa1100fb_backlight_power(fbi, 1);
+		}
+		break;
+	}
+	mutex_unlock(&fbi->ctrlr_lock);
+}
+
+/*
+ * Our LCD controller task (which is called when we blank or unblank)
+ * via keventd.
+ */
+static void sa1100fb_task(struct work_struct *w)
+{
+	struct sa1100fb_info *fbi = container_of(w, struct sa1100fb_info, task);
+	u_int state = xchg(&fbi->task_state, -1);
+
+	set_ctrlr_state(fbi, state);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/*
+ * Calculate the minimum DMA period over all displays that we own.
+ * This, together with the SDRAM bandwidth defines the slowest CPU
+ * frequency that can be selected.
+ */
+static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
+{
+#if 0
+	unsigned int min_period = (unsigned int)-1;
+	int i;
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+		struct display *disp = &fb_display[i];
+		unsigned int period;
+
+		/*
+		 * Do we own this display?
+		 */
+		if (disp->fb_info != &fbi->fb)
+			continue;
+
+		/*
+		 * Ok, calculate its DMA period
+		 */
+		period = sa1100fb_display_dma_period(&disp->var);
+		if (period < min_period)
+			min_period = period;
+	}
+
+	return min_period;
+#else
+	/*
+	 * FIXME: we need to verify _all_ consoles.
+	 */
+	return sa1100fb_display_dma_period(&fbi->fb.var);
+#endif
+}
+
+/*
+ * CPU clock speed change handler.  We need to adjust the LCD timing
+ * parameters when the CPU clock is adjusted by the power management
+ * subsystem.
+ */
+static int
+sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val,
+			 void *data)
+{
+	struct sa1100fb_info *fbi = TO_INF(nb, freq_transition);
+	struct cpufreq_freqs *f = data;
+	u_int pcd;
+
+	switch (val) {
+	case CPUFREQ_PRECHANGE:
+		set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
+		break;
+
+	case CPUFREQ_POSTCHANGE:
+		pcd = get_pcd(fbi->fb.var.pixclock, f->new);
+		fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
+		set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
+		break;
+	}
+	return 0;
+}
+
+static int
+sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
+		     void *data)
+{
+	struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
+	struct cpufreq_policy *policy = data;
+
+	switch (val) {
+	case CPUFREQ_ADJUST:
+	case CPUFREQ_INCOMPATIBLE:
+		dev_dbg(fbi->dev, "min dma period: %d ps, "
+			"new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
+			policy->max);
+		/* todo: fill in min/max values */
+		break;
+	case CPUFREQ_NOTIFY:
+		do {} while(0);
+		/* todo: panic if min/max values aren't fulfilled 
+		 * [can't really happen unless there's a bug in the
+		 * CPU policy verififcation process *
+		 */
+		break;
+	}
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks.  Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int sa1100fb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct sa1100fb_info *fbi = platform_get_drvdata(dev);
+
+	set_ctrlr_state(fbi, C_DISABLE_PM);
+	return 0;
+}
+
+static int sa1100fb_resume(struct platform_device *dev)
+{
+	struct sa1100fb_info *fbi = platform_get_drvdata(dev);
+
+	set_ctrlr_state(fbi, C_ENABLE_PM);
+	return 0;
+}
+#else
+#define sa1100fb_suspend	NULL
+#define sa1100fb_resume		NULL
+#endif
+
+/*
+ * sa1100fb_map_video_memory():
+ *      Allocates the DRAM memory for the frame buffer.  This buffer is  
+ *	remapped into a non-cached, non-buffered, memory region to  
+ *      allow palette and pixel writes to occur without flushing the 
+ *      cache.  Once this area is remapped, all virtual memory
+ *      access to the video memory should occur at the new region.
+ */
+static int sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
+{
+	/*
+	 * We reserve one page for the palette, plus the size
+	 * of the framebuffer.
+	 */
+	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
+	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+					      &fbi->map_dma, GFP_KERNEL);
+
+	if (fbi->map_cpu) {
+		fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
+		fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
+		/*
+		 * FIXME: this is actually the wrong thing to place in
+		 * smem_start.  But fbdev suffers from the problem that
+		 * it needs an API which doesn't exist (in this case,
+		 * dma_writecombine_mmap)
+		 */
+		fbi->fb.fix.smem_start = fbi->screen_dma;
+	}
+
+	return fbi->map_cpu ? 0 : -ENOMEM;
+}
+
+/* Fake monspecs to fill in fbinfo structure */
+static struct fb_monspecs monspecs = {
+	.hfmin	= 30000,
+	.hfmax	= 70000,
+	.vfmin	= 50,
+	.vfmax	= 65,
+};
+
+
+static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev)
+{
+	struct sa1100fb_mach_info *inf = dev_get_platdata(dev);
+	struct sa1100fb_info *fbi;
+	unsigned i;
+
+	fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
+		      GFP_KERNEL);
+	if (!fbi)
+		return NULL;
+
+	memset(fbi, 0, sizeof(struct sa1100fb_info));
+	fbi->dev = dev;
+
+	strcpy(fbi->fb.fix.id, SA1100_NAME);
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.type_aux	= 0;
+	fbi->fb.fix.xpanstep	= 0;
+	fbi->fb.fix.ypanstep	= 0;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.var.nonstd	= 0;
+	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
+	fbi->fb.var.height	= -1;
+	fbi->fb.var.width	= -1;
+	fbi->fb.var.accel_flags	= 0;
+	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
+
+	fbi->fb.fbops		= &sa1100fb_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT;
+	fbi->fb.monspecs	= monspecs;
+	fbi->fb.pseudo_palette	= (fbi + 1);
+
+	fbi->rgb[RGB_4]		= &rgb_4;
+	fbi->rgb[RGB_8]		= &rgb_8;
+	fbi->rgb[RGB_16]	= &def_rgb_16;
+
+	/*
+	 * People just don't seem to get this.  We don't support
+	 * anything but correct entries now, so panic if someone
+	 * does something stupid.
+	 */
+	if (inf->lccr3 & (LCCR3_VrtSnchL|LCCR3_HorSnchL|0xff) ||
+	    inf->pixclock == 0)
+		panic("sa1100fb error: invalid LCCR3 fields set or zero "
+			"pixclock.");
+
+	fbi->fb.var.xres		= inf->xres;
+	fbi->fb.var.xres_virtual	= inf->xres;
+	fbi->fb.var.yres		= inf->yres;
+	fbi->fb.var.yres_virtual	= inf->yres;
+	fbi->fb.var.bits_per_pixel	= inf->bpp;
+	fbi->fb.var.pixclock		= inf->pixclock;
+	fbi->fb.var.hsync_len		= inf->hsync_len;
+	fbi->fb.var.left_margin		= inf->left_margin;
+	fbi->fb.var.right_margin	= inf->right_margin;
+	fbi->fb.var.vsync_len		= inf->vsync_len;
+	fbi->fb.var.upper_margin	= inf->upper_margin;
+	fbi->fb.var.lower_margin	= inf->lower_margin;
+	fbi->fb.var.sync		= inf->sync;
+	fbi->fb.var.grayscale		= inf->cmap_greyscale;
+	fbi->state			= C_STARTUP;
+	fbi->task_state			= (u_char)-1;
+	fbi->fb.fix.smem_len		= inf->xres * inf->yres *
+					  inf->bpp / 8;
+	fbi->inf			= inf;
+
+	/* Copy the RGB bitfield overrides */
+	for (i = 0; i < NR_RGB; i++)
+		if (inf->rgb[i])
+			fbi->rgb[i] = inf->rgb[i];
+
+	init_waitqueue_head(&fbi->ctrlr_wait);
+	INIT_WORK(&fbi->task, sa1100fb_task);
+	mutex_init(&fbi->ctrlr_lock);
+
+	return fbi;
+}
+
+static int sa1100fb_probe(struct platform_device *pdev)
+{
+	struct sa1100fb_info *fbi;
+	struct resource *res;
+	int ret, irq;
+
+	if (!dev_get_platdata(&pdev->dev)) {
+		dev_err(&pdev->dev, "no platform LCD data\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0 || !res)
+		return -EINVAL;
+
+	if (!request_mem_region(res->start, resource_size(res), "LCD"))
+		return -EBUSY;
+
+	fbi = sa1100fb_init_fbinfo(&pdev->dev);
+	ret = -ENOMEM;
+	if (!fbi)
+		goto failed;
+
+	fbi->base = ioremap(res->start, resource_size(res));
+	if (!fbi->base)
+		goto failed;
+
+	/* Initialize video memory */
+	ret = sa1100fb_map_video_memory(fbi);
+	if (ret)
+		goto failed;
+
+	ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
+	if (ret) {
+		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
+		goto failed;
+	}
+
+	if (machine_is_shannon()) {
+		ret = gpio_request_one(SHANNON_GPIO_DISP_EN,
+			GPIOF_OUT_INIT_LOW, "display enable");
+		if (ret)
+			goto err_free_irq;
+	}
+
+	/*
+	 * This makes sure that our colour bitfield
+	 * descriptors are correctly initialised.
+	 */
+	sa1100fb_check_var(&fbi->fb.var, &fbi->fb);
+
+	platform_set_drvdata(pdev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0)
+		goto err_reg_fb;
+
+#ifdef CONFIG_CPU_FREQ
+	fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
+	fbi->freq_policy.notifier_call = sa1100fb_freq_policy;
+	cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
+	cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
+#endif
+
+	/* This driver cannot be unloaded at the moment */
+	return 0;
+
+ err_reg_fb:
+	if (machine_is_shannon())
+		gpio_free(SHANNON_GPIO_DISP_EN);
+ err_free_irq:
+	free_irq(irq, fbi);
+ failed:
+	if (fbi)
+		iounmap(fbi->base);
+	kfree(fbi);
+	release_mem_region(res->start, resource_size(res));
+	return ret;
+}
+
+static struct platform_driver sa1100fb_driver = {
+	.probe		= sa1100fb_probe,
+	.suspend	= sa1100fb_suspend,
+	.resume		= sa1100fb_resume,
+	.driver		= {
+		.name	= "sa11x0-fb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+int __init sa1100fb_init(void)
+{
+	if (fb_get_options("sa1100fb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&sa1100fb_driver);
+}
+
+int __init sa1100fb_setup(char *options)
+{
+#if 0
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+
+		if (!strncmp(this_opt, "bpp:", 4))
+			current_par.max_bpp =
+			    simple_strtoul(this_opt + 4, NULL, 0);
+
+		if (!strncmp(this_opt, "lccr0:", 6))
+			lcd_shadow.lccr0 =
+			    simple_strtoul(this_opt + 6, NULL, 0);
+		if (!strncmp(this_opt, "lccr1:", 6)) {
+			lcd_shadow.lccr1 =
+			    simple_strtoul(this_opt + 6, NULL, 0);
+			current_par.max_xres =
+			    (lcd_shadow.lccr1 & 0x3ff) + 16;
+		}
+		if (!strncmp(this_opt, "lccr2:", 6)) {
+			lcd_shadow.lccr2 =
+			    simple_strtoul(this_opt + 6, NULL, 0);
+			current_par.max_yres =
+			    (lcd_shadow.
+			     lccr0 & LCCR0_SDS) ? ((lcd_shadow.
+						    lccr2 & 0x3ff) +
+						   1) *
+			    2 : ((lcd_shadow.lccr2 & 0x3ff) + 1);
+		}
+		if (!strncmp(this_opt, "lccr3:", 6))
+			lcd_shadow.lccr3 =
+			    simple_strtoul(this_opt + 6, NULL, 0);
+	}
+#endif
+	return 0;
+}
+
+module_init(sa1100fb_init);
+MODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/sa1100fb.h b/drivers/video/fbdev/sa1100fb.h
new file mode 100644
index 000000000000..fc5d4292fad6
--- /dev/null
+++ b/drivers/video/fbdev/sa1100fb.h
@@ -0,0 +1,96 @@
+/*
+ * linux/drivers/video/sa1100fb.h
+ *    -- StrongARM 1100 LCD Controller Frame Buffer Device
+ *
+ *  Copyright (C) 1999 Eric A. Thomas
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *  
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#define LCCR0           0x0000          /* LCD Control Reg. 0 */
+#define LCSR            0x0004          /* LCD Status Reg. */
+#define DBAR1           0x0010          /* LCD DMA Base Address Reg. channel 1 */
+#define DCAR1           0x0014          /* LCD DMA Current Address Reg. channel 1 */
+#define DBAR2           0x0018          /* LCD DMA Base Address Reg.  channel 2 */
+#define DCAR2           0x001C          /* LCD DMA Current Address Reg. channel 2 */
+#define LCCR1           0x0020          /* LCD Control Reg. 1 */
+#define LCCR2           0x0024          /* LCD Control Reg. 2 */
+#define LCCR3           0x0028          /* LCD Control Reg. 3 */
+
+/* Shadows for LCD controller registers */
+struct sa1100fb_lcd_reg {
+	unsigned long lccr0;
+	unsigned long lccr1;
+	unsigned long lccr2;
+	unsigned long lccr3;
+};
+
+struct sa1100fb_info {
+	struct fb_info		fb;
+	struct device		*dev;
+	const struct sa1100fb_rgb *rgb[NR_RGB];
+	void __iomem		*base;
+
+	/*
+	 * These are the addresses we mapped
+	 * the framebuffer memory region to.
+	 */
+	dma_addr_t		map_dma;
+	u_char *		map_cpu;
+	u_int			map_size;
+
+	u_char *		screen_cpu;
+	dma_addr_t		screen_dma;
+	u16 *			palette_cpu;
+	dma_addr_t		palette_dma;
+	u_int			palette_size;
+
+	dma_addr_t		dbar1;
+	dma_addr_t		dbar2;
+
+	u_int			reg_lccr0;
+	u_int			reg_lccr1;
+	u_int			reg_lccr2;
+	u_int			reg_lccr3;
+
+	volatile u_char		state;
+	volatile u_char		task_state;
+	struct mutex		ctrlr_lock;
+	wait_queue_head_t	ctrlr_wait;
+	struct work_struct	task;
+
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+	struct notifier_block	freq_policy;
+#endif
+
+	const struct sa1100fb_mach_info *inf;
+};
+
+#define TO_INF(ptr,member)	container_of(ptr,struct sa1100fb_info,member)
+
+#define SA1100_PALETTE_MODE_VAL(bpp)    (((bpp) & 0x018) << 9)
+
+/*
+ * These are the actions for set_ctrlr_state
+ */
+#define C_DISABLE		(0)
+#define C_ENABLE		(1)
+#define C_DISABLE_CLKCHANGE	(2)
+#define C_ENABLE_CLKCHANGE	(3)
+#define C_REENABLE		(4)
+#define C_DISABLE_PM		(5)
+#define C_ENABLE_PM		(6)
+#define C_STARTUP		(7)
+
+#define SA1100_NAME	"SA1100"
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES	64
+#define MIN_YRES	64
+
diff --git a/drivers/video/fbdev/savage/Makefile b/drivers/video/fbdev/savage/Makefile
new file mode 100644
index 000000000000..e09770fff8ea
--- /dev/null
+++ b/drivers/video/fbdev/savage/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the S3 Savage framebuffer driver
+#
+
+obj-$(CONFIG_FB_SAVAGE)			+= savagefb.o
+
+savagefb-y				+= savagefb_driver.o
+savagefb-$(CONFIG_FB_SAVAGE_I2C)	+= savagefb-i2c.o
+savagefb-$(CONFIG_FB_SAVAGE_ACCEL)	+= savagefb_accel.o
diff --git a/drivers/video/fbdev/savage/savagefb-i2c.c b/drivers/video/fbdev/savage/savagefb-i2c.c
new file mode 100644
index 000000000000..80fa87e2ae2f
--- /dev/null
+++ b/drivers/video/fbdev/savage/savagefb-i2c.c
@@ -0,0 +1,241 @@
+/*
+ * linux/drivers/video/savage/savagefb-i2c.c - S3 Savage DDC2
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based partly on rivafb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+#include "savagefb.h"
+
+#define SAVAGE_DDC 	0x50
+
+#define VGA_CR_IX	0x3d4
+#define VGA_CR_DATA	0x3d5
+
+#define CR_SERIAL1	0xa0	/* I2C serial communications interface */
+#define MM_SERIAL1	0xff20
+#define CR_SERIAL2	0xb1	/* DDC2 monitor communications interface */
+
+/* based on vt8365 documentation */
+#define PROSAVAGE_I2C_ENAB	0x10
+#define PROSAVAGE_I2C_SCL_OUT	0x01
+#define PROSAVAGE_I2C_SDA_OUT	0x02
+#define PROSAVAGE_I2C_SCL_IN	0x04
+#define PROSAVAGE_I2C_SDA_IN	0x08
+
+#define SAVAGE4_I2C_ENAB	0x00000020
+#define SAVAGE4_I2C_SCL_OUT	0x00000001
+#define SAVAGE4_I2C_SDA_OUT	0x00000002
+#define SAVAGE4_I2C_SCL_IN	0x00000008
+#define SAVAGE4_I2C_SDA_IN	0x00000010
+
+static void savage4_gpio_setscl(void *data, int val)
+{
+	struct savagefb_i2c_chan *chan = data;
+	unsigned int r;
+
+	r = readl(chan->ioaddr + chan->reg);
+	if(val)
+		r |= SAVAGE4_I2C_SCL_OUT;
+	else
+		r &= ~SAVAGE4_I2C_SCL_OUT;
+	writel(r, chan->ioaddr + chan->reg);
+	readl(chan->ioaddr + chan->reg);	/* flush posted write */
+}
+
+static void savage4_gpio_setsda(void *data, int val)
+{
+	struct savagefb_i2c_chan *chan = data;
+
+	unsigned int r;
+	r = readl(chan->ioaddr + chan->reg);
+	if(val)
+		r |= SAVAGE4_I2C_SDA_OUT;
+	else
+		r &= ~SAVAGE4_I2C_SDA_OUT;
+	writel(r, chan->ioaddr + chan->reg);
+	readl(chan->ioaddr + chan->reg);	/* flush posted write */
+}
+
+static int savage4_gpio_getscl(void *data)
+{
+	struct savagefb_i2c_chan *chan = data;
+
+	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));
+}
+
+static int savage4_gpio_getsda(void *data)
+{
+	struct savagefb_i2c_chan *chan = data;
+
+	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));
+}
+
+static void prosavage_gpio_setscl(void* data, int val)
+{
+	struct savagefb_i2c_chan *chan = data;
+	u32			  r;
+
+	r = VGArCR(chan->reg, chan->par);
+	r |= PROSAVAGE_I2C_ENAB;
+	if (val) {
+		r |= PROSAVAGE_I2C_SCL_OUT;
+	} else {
+		r &= ~PROSAVAGE_I2C_SCL_OUT;
+	}
+
+	VGAwCR(chan->reg, r, chan->par);
+}
+
+static void prosavage_gpio_setsda(void* data, int val)
+{
+	struct savagefb_i2c_chan *chan = data;
+	unsigned int r;
+
+	r = VGArCR(chan->reg, chan->par);
+	r |= PROSAVAGE_I2C_ENAB;
+	if (val) {
+		r |= PROSAVAGE_I2C_SDA_OUT;
+	} else {
+		r &= ~PROSAVAGE_I2C_SDA_OUT;
+	}
+
+	VGAwCR(chan->reg, r, chan->par);
+}
+
+static int prosavage_gpio_getscl(void* data)
+{
+	struct savagefb_i2c_chan *chan = data;
+
+	return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SCL_IN) ? 1 : 0;
+}
+
+static int prosavage_gpio_getsda(void* data)
+{
+	struct savagefb_i2c_chan *chan = data;
+
+	return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SDA_IN) ? 1 : 0;
+}
+
+static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
+				const char *name)
+{
+	int rc = 0;
+
+	if (chan->par) {
+		strcpy(chan->adapter.name, name);
+		chan->adapter.owner		= THIS_MODULE;
+		chan->adapter.algo_data		= &chan->algo;
+		chan->adapter.dev.parent	= &chan->par->pcidev->dev;
+		chan->algo.udelay		= 10;
+		chan->algo.timeout		= 20;
+		chan->algo.data 		= chan;
+
+		i2c_set_adapdata(&chan->adapter, chan);
+
+		/* Raise SCL and SDA */
+		chan->algo.setsda(chan, 1);
+		chan->algo.setscl(chan, 1);
+		udelay(20);
+
+		rc = i2c_bit_add_bus(&chan->adapter);
+
+		if (rc == 0)
+			dev_dbg(&chan->par->pcidev->dev,
+				"I2C bus %s registered.\n", name);
+		else
+			dev_warn(&chan->par->pcidev->dev,
+				 "Failed to register I2C bus %s.\n", name);
+	}
+
+	return rc;
+}
+
+void savagefb_create_i2c_busses(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	par->chan.par	= par;
+
+	switch (par->chip) {
+	case S3_PROSAVAGE:
+	case S3_PROSAVAGEDDR:
+	case S3_TWISTER:
+		par->chan.reg         = CR_SERIAL2;
+		par->chan.ioaddr      = par->mmio.vbase;
+		par->chan.algo.setsda = prosavage_gpio_setsda;
+		par->chan.algo.setscl = prosavage_gpio_setscl;
+		par->chan.algo.getsda = prosavage_gpio_getsda;
+		par->chan.algo.getscl = prosavage_gpio_getscl;
+		break;
+	case S3_SAVAGE4:
+		par->chan.reg = CR_SERIAL1;
+		if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))
+			par->chan.reg = CR_SERIAL2;
+		par->chan.ioaddr      = par->mmio.vbase;
+		par->chan.algo.setsda = prosavage_gpio_setsda;
+		par->chan.algo.setscl = prosavage_gpio_setscl;
+		par->chan.algo.getsda = prosavage_gpio_getsda;
+		par->chan.algo.getscl = prosavage_gpio_getscl;
+		break;
+	case S3_SAVAGE2000:
+		par->chan.reg         = MM_SERIAL1;
+		par->chan.ioaddr      = par->mmio.vbase;
+		par->chan.algo.setsda = savage4_gpio_setsda;
+		par->chan.algo.setscl = savage4_gpio_setscl;
+		par->chan.algo.getsda = savage4_gpio_getsda;
+		par->chan.algo.getscl = savage4_gpio_getscl;
+		break;
+	default:
+		par->chan.par = NULL;
+	}
+
+	savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");
+}
+
+void savagefb_delete_i2c_busses(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+
+	if (par->chan.par)
+		i2c_del_adapter(&par->chan.adapter);
+
+	par->chan.par = NULL;
+}
+
+int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
+{
+	struct savagefb_par *par = info->par;
+	u8 *edid;
+
+	if (par->chan.par)
+		edid = fb_ddc_read(&par->chan.adapter);
+	else
+		edid = NULL;
+
+	if (!edid) {
+		/* try to get from firmware */
+		const u8 *e = fb_firmware_edid(info->device);
+
+		if (e)
+			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
+	}
+
+	*out_edid = edid;
+
+	return (edid) ? 0 : 1;
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/savage/savagefb.h b/drivers/video/fbdev/savage/savagefb.h
new file mode 100644
index 000000000000..dcaab9012ca2
--- /dev/null
+++ b/drivers/video/fbdev/savage/savagefb.h
@@ -0,0 +1,415 @@
+/*
+ * linux/drivers/video/savagefb.h -- S3 Savage Framebuffer Driver
+ *
+ * Copyright (c) 2001  Denis Oliver Kropp <dok@convergence.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+
+#ifndef __SAVAGEFB_H__
+#define __SAVAGEFB_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/mutex.h>
+#include <video/vga.h>
+#include "../edid.h"
+
+#ifdef SAVAGEFB_DEBUG
+# define DBG(x)		printk (KERN_DEBUG "savagefb: %s\n", (x));
+#else
+# define DBG(x)
+# define SavagePrintRegs(...)
+#endif
+
+
+#define PCI_CHIP_SAVAGE4      0x8a22
+#define PCI_CHIP_SAVAGE3D     0x8a20
+#define PCI_CHIP_SAVAGE3D_MV  0x8a21
+#define PCI_CHIP_SAVAGE2000   0x9102
+#define PCI_CHIP_SAVAGE_MX_MV 0x8c10
+#define PCI_CHIP_SAVAGE_MX    0x8c11
+#define PCI_CHIP_SAVAGE_IX_MV 0x8c12
+#define PCI_CHIP_SAVAGE_IX    0x8c13
+#define PCI_CHIP_PROSAVAGE_PM 0x8a25
+#define PCI_CHIP_PROSAVAGE_KM 0x8a26
+#define PCI_CHIP_S3TWISTER_P  0x8d01
+#define PCI_CHIP_S3TWISTER_K  0x8d02
+#define PCI_CHIP_PROSAVAGE_DDR          0x8d03
+#define PCI_CHIP_PROSAVAGE_DDRK         0x8d04
+#define PCI_CHIP_SUPSAV_MX128		0x8c22
+#define PCI_CHIP_SUPSAV_MX64		0x8c24
+#define PCI_CHIP_SUPSAV_MX64C		0x8c26
+#define PCI_CHIP_SUPSAV_IX128SDR	0x8c2a
+#define PCI_CHIP_SUPSAV_IX128DDR	0x8c2b
+#define PCI_CHIP_SUPSAV_IX64SDR		0x8c2c
+#define PCI_CHIP_SUPSAV_IX64DDR		0x8c2d
+#define PCI_CHIP_SUPSAV_IXCSDR		0x8c2e
+#define PCI_CHIP_SUPSAV_IXCDDR		0x8c2f
+
+
+#define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+
+#define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+#define S3_SAVAGE4_SERIES(chip)   ((chip>=S3_SAVAGE4) && (chip<=S3_PROSAVAGEDDR))
+
+#define S3_SAVAGE_MOBILE_SERIES(chip)  ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
+
+#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip==S3_PROSAVAGEDDR))
+
+/* Chip tags.  These are used to group the adapters into
+ * related families.
+ */
+
+typedef enum {
+  S3_UNKNOWN = 0,
+  S3_SAVAGE3D,
+  S3_SAVAGE_MX,
+  S3_SAVAGE4,
+  S3_PROSAVAGE,
+  S3_TWISTER,
+  S3_PROSAVAGEDDR,
+  S3_SUPERSAVAGE,
+  S3_SAVAGE2000,
+  S3_LAST
+} savage_chipset;
+
+#define BIOS_BSIZE		     1024
+#define BIOS_BASE		     0xc0000
+
+#define SAVAGE_NEWMMIO_REGBASE_S3    0x1000000  /* 16MB */
+#define SAVAGE_NEWMMIO_REGBASE_S4    0x0000000
+#define SAVAGE_NEWMMIO_REGSIZE	     0x0080000  /* 512kb */
+#define SAVAGE_NEWMMIO_VGABASE	     0x8000
+
+#define BASE_FREQ		     14318
+#define HALF_BASE_FREQ               7159
+
+#define FIFO_CONTROL_REG	     0x8200
+#define MIU_CONTROL_REG		     0x8204
+#define STREAMS_TIMEOUT_REG	     0x8208
+#define MISC_TIMEOUT_REG	     0x820c
+
+#define MONO_PAT_0                   0xa4e8
+#define MONO_PAT_1                   0xa4ec
+
+#define MAXFIFO                      0x7f00
+
+#define BCI_CMD_NOP                  0x40000000
+#define BCI_CMD_SETREG               0x96000000
+#define BCI_CMD_RECT                 0x48000000
+#define BCI_CMD_RECT_XP              0x01000000
+#define BCI_CMD_RECT_YP              0x02000000
+#define BCI_CMD_SEND_COLOR           0x00008000
+#define BCI_CMD_DEST_GBD             0x00000000
+#define BCI_CMD_SRC_GBD              0x00000020
+#define BCI_CMD_SRC_SOLID            0x00000000
+#define BCI_CMD_SRC_MONO             0x00000060
+#define BCI_CMD_CLIP_NEW             0x00006000
+#define BCI_CMD_CLIP_LR              0x00004000
+
+#define BCI_CLIP_LR(l, r)            ((((r) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_TL(t, l)            ((((t) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_BR(b, r)            ((((b) << 16) | (r)) & 0x0FFF0FFF)
+#define BCI_W_H(w, h)                (((h) << 16) | ((w) & 0xFFF))
+#define BCI_X_Y(x, y)                (((y) << 16) | ((x) & 0xFFF))
+
+#define BCI_GBD1                     0xE0
+#define BCI_GBD2                     0xE1
+
+#define BCI_BUFFER_OFFSET            0x10000
+#define BCI_SIZE                     0x4000
+
+#define BCI_SEND(dw)                 writel(dw, par->bci_base + par->bci_ptr++)
+
+#define BCI_CMD_GET_ROP(cmd)         (((cmd) >> 16) & 0xFF)
+#define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
+#define BCI_CMD_SEND_COLOR           0x00008000
+
+#define DISP_CRT     1
+#define DISP_LCD     2
+#define DISP_DFP     3
+
+struct xtimings {
+	unsigned int Clock;
+	unsigned int HDisplay;
+	unsigned int HSyncStart;
+	unsigned int HSyncEnd;
+	unsigned int HTotal;
+	unsigned int HAdjusted;
+	unsigned int VDisplay;
+	unsigned int VSyncStart;
+	unsigned int VSyncEnd;
+	unsigned int VTotal;
+	unsigned int sync;
+	int	       dblscan;
+	int	       interlaced;
+};
+
+struct savage_reg {
+	unsigned char MiscOutReg;     /* Misc */
+	unsigned char CRTC[25];       /* Crtc Controller */
+	unsigned char Sequencer[5];   /* Video Sequencer */
+	unsigned char Graphics[9];    /* Video Graphics */
+	unsigned char Attribute[21];  /* Video Attribute */
+
+	unsigned int mode, refresh;
+	unsigned char SR08, SR0E, SR0F;
+	unsigned char SR10, SR11, SR12, SR13, SR15, SR18, SR29, SR30;
+	unsigned char SR54[8];
+	unsigned char Clock;
+	unsigned char CR31, CR32, CR33, CR34, CR36, CR3A, CR3B, CR3C;
+	unsigned char CR40, CR41, CR42, CR43, CR45;
+	unsigned char CR50, CR51, CR53, CR55, CR58, CR5B, CR5D, CR5E;
+	unsigned char CR60, CR63, CR65, CR66, CR67, CR68, CR69, CR6D, CR6F;
+	unsigned char CR86, CR88;
+	unsigned char CR90, CR91, CRB0;
+	unsigned int  STREAMS[22];	/* yuck, streams regs */
+	unsigned int  MMPR0, MMPR1, MMPR2, MMPR3;
+};
+/* --------------------------------------------------------------------- */
+
+#define NR_PALETTE	256
+
+
+struct savagefb_par;
+
+struct savagefb_i2c_chan {
+	struct savagefb_par *par;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+	volatile u8 __iomem *ioaddr;
+	u32   reg;
+};
+
+struct savagefb_par {
+	struct pci_dev *pcidev;
+	savage_chipset  chip;
+	struct savagefb_i2c_chan chan;
+	struct savage_reg state;
+	struct savage_reg save;
+	struct savage_reg initial;
+	struct vgastate vgastate;
+	struct mutex open_lock;
+	unsigned char   *edid;
+	u32 pseudo_palette[16];
+	u32 open_count;
+	int paletteEnabled;
+	int pm_state;
+	int display_type;
+	int dvi;
+	int crtonly;
+	int dacSpeedBpp;
+	int maxClock;
+	int minClock;
+	int numClocks;
+	int clock[4];
+	int MCLK, REFCLK, LCDclk;
+	struct {
+		void   __iomem *vbase;
+		u32    pbase;
+		u32    len;
+#ifdef CONFIG_MTRR
+		int    mtrr;
+#endif
+	} video;
+
+	struct {
+		void  __iomem *vbase;
+		u32           pbase;
+		u32           len;
+	} mmio;
+
+	volatile u32  __iomem *bci_base;
+	unsigned int  bci_ptr;
+	u32           cob_offset;
+	u32           cob_size;
+	int           cob_index;
+
+	void (*SavageWaitIdle) (struct savagefb_par *par);
+	void (*SavageWaitFifo) (struct savagefb_par *par, int space);
+
+	int HorizScaleFactor;
+
+	/* Panels size */
+	int SavagePanelWidth;
+	int SavagePanelHeight;
+
+	struct {
+		u16 red, green, blue, transp;
+	} palette[NR_PALETTE];
+
+	int depth;
+	int vwidth;
+};
+
+#define BCI_BD_BW_DISABLE            0x10000000
+#define BCI_BD_SET_BPP(bd, bpp)      ((bd) |= (((bpp) & 0xFF) << 16))
+#define BCI_BD_SET_STRIDE(bd, st)    ((bd) |= ((st) & 0xFFFF))
+
+
+/* IO functions */
+static inline u8 savage_in8(u32 addr, struct savagefb_par *par)
+{
+	return readb(par->mmio.vbase + addr);
+}
+
+static inline u16 savage_in16(u32 addr, struct savagefb_par *par)
+{
+	return readw(par->mmio.vbase + addr);
+}
+
+static inline u32 savage_in32(u32 addr, struct savagefb_par *par)
+{
+	return readl(par->mmio.vbase + addr);
+}
+
+static inline void savage_out8(u32 addr, u8 val, struct savagefb_par *par)
+{
+	writeb(val, par->mmio.vbase + addr);
+}
+
+static inline void savage_out16(u32 addr, u16 val, struct savagefb_par *par)
+{
+	writew(val, par->mmio.vbase + addr);
+}
+
+static inline void savage_out32(u32 addr, u32 val, struct savagefb_par *par)
+{
+	writel(val, par->mmio.vbase + addr);
+}
+
+static inline u8 vga_in8(int addr, struct savagefb_par *par)
+{
+	return savage_in8(0x8000 + addr, par);
+}
+
+static inline u16 vga_in16(int addr, struct savagefb_par *par)
+{
+	return savage_in16(0x8000 + addr, par);
+}
+
+static inline u8 vga_in32(int addr, struct savagefb_par *par)
+{
+	return savage_in32(0x8000 + addr, par);
+}
+
+static inline void vga_out8(int addr, u8 val, struct savagefb_par *par)
+{
+	savage_out8(0x8000 + addr, val, par);
+}
+
+static inline void vga_out16(int addr, u16 val, struct savagefb_par *par)
+{
+	savage_out16(0x8000 + addr, val, par);
+}
+
+static inline void vga_out32(int addr, u32 val, struct savagefb_par *par)
+{
+	savage_out32(0x8000 + addr, val, par);
+}
+
+static inline u8 VGArCR (u8 index, struct savagefb_par *par)
+{
+	vga_out8(0x3d4, index,  par);
+	return vga_in8(0x3d5, par);
+}
+
+static inline u8 VGArGR (u8 index, struct savagefb_par *par)
+{
+	vga_out8(0x3ce, index, par);
+	return vga_in8(0x3cf, par);
+}
+
+static inline u8 VGArSEQ (u8 index, struct savagefb_par *par)
+{
+	vga_out8(0x3c4, index, par);
+	return vga_in8(0x3c5, par);
+}
+
+static inline void VGAwCR(u8 index, u8 val, struct savagefb_par *par)
+{
+	vga_out8(0x3d4, index, par);
+	vga_out8(0x3d5, val, par);
+}
+
+static inline void VGAwGR(u8 index, u8 val, struct savagefb_par *par)
+{
+	vga_out8(0x3ce, index, par);
+	vga_out8(0x3cf, val, par);
+}
+
+static inline void VGAwSEQ(u8 index, u8 val, struct savagefb_par *par)
+{
+	vga_out8(0x3c4, index, par);
+	vga_out8 (0x3c5, val, par);
+}
+
+static inline void VGAenablePalette(struct savagefb_par *par)
+{
+	u8 tmp;
+
+	tmp = vga_in8(0x3da, par);
+	vga_out8(0x3c0, 0x00, par);
+	par->paletteEnabled = 1;
+}
+
+static inline void VGAdisablePalette(struct savagefb_par *par)
+{
+	u8 tmp;
+
+	tmp = vga_in8(0x3da, par);
+	vga_out8(0x3c0, 0x20, par);
+	par->paletteEnabled = 0;
+}
+
+static inline void VGAwATTR(u8 index, u8 value, struct savagefb_par *par)
+{
+	u8 tmp;
+
+	if (par->paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+
+	tmp = vga_in8(0x3da, par);
+	vga_out8(0x3c0, index, par);
+	vga_out8 (0x3c0, value, par);
+}
+
+static inline void VGAwMISC(u8 value, struct savagefb_par *par)
+{
+	vga_out8(0x3c2, value, par);
+}
+
+#ifndef CONFIG_FB_SAVAGE_ACCEL
+#define savagefb_set_clip(x)
+#endif
+
+static inline void VerticalRetraceWait(struct savagefb_par *par)
+{
+	vga_out8(0x3d4, 0x17, par);
+	if (vga_in8(0x3d5, par) & 0x80) {
+		while ((vga_in8(0x3da, par) & 0x08) == 0x08);
+		while ((vga_in8(0x3da, par) & 0x08) == 0x00);
+	}
+}
+
+extern int savagefb_probe_i2c_connector(struct fb_info *info,
+					u8 **out_edid);
+extern void savagefb_create_i2c_busses(struct fb_info *info);
+extern void savagefb_delete_i2c_busses(struct fb_info *info);
+extern int  savagefb_sync(struct fb_info *info);
+extern void savagefb_copyarea(struct fb_info *info,
+			      const struct fb_copyarea *region);
+extern void savagefb_fillrect(struct fb_info *info,
+			      const struct fb_fillrect *rect);
+extern void savagefb_imageblit(struct fb_info *info,
+			       const struct fb_image *image);
+
+
+#endif /* __SAVAGEFB_H__ */
diff --git a/drivers/video/fbdev/savage/savagefb_accel.c b/drivers/video/fbdev/savage/savagefb_accel.c
new file mode 100644
index 000000000000..bfefa6234cf0
--- /dev/null
+++ b/drivers/video/fbdev/savage/savagefb_accel.c
@@ -0,0 +1,137 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/savage/savage_accel.c -- Hardware Acceleration
+ *
+ *      Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+
+#include "savagefb.h"
+
+static u32 savagefb_rop[] = {
+	0xCC, /* ROP_COPY */
+	0x5A  /* ROP_XOR  */
+};
+
+int savagefb_sync(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+
+	par->SavageWaitIdle(par);
+	return 0;
+}
+
+void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct savagefb_par *par = info->par;
+	int sx = region->sx, dx = region->dx;
+	int sy = region->sy, dy = region->dy;
+	int cmd;
+
+	if (!region->width || !region->height)
+		return;
+	par->bci_ptr = 0;
+	cmd = BCI_CMD_RECT | BCI_CMD_DEST_GBD | BCI_CMD_SRC_GBD;
+	BCI_CMD_SET_ROP(cmd, savagefb_rop[0]);
+
+	if (dx <= sx) {
+		cmd |= BCI_CMD_RECT_XP;
+	} else {
+		sx += region->width - 1;
+		dx += region->width - 1;
+	}
+
+	if (dy <= sy) {
+		cmd |= BCI_CMD_RECT_YP;
+	} else {
+		sy += region->height - 1;
+		dy += region->height - 1;
+	}
+
+	par->SavageWaitFifo(par,4);
+	BCI_SEND(cmd);
+	BCI_SEND(BCI_X_Y(sx, sy));
+	BCI_SEND(BCI_X_Y(dx, dy));
+	BCI_SEND(BCI_W_H(region->width, region->height));
+}
+
+void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct savagefb_par *par = info->par;
+	int cmd, color;
+
+	if (!rect->width || !rect->height)
+		return;
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+		color = rect->color;
+	else
+		color = ((u32 *)info->pseudo_palette)[rect->color];
+
+	cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+	      BCI_CMD_DEST_GBD | BCI_CMD_SRC_SOLID |
+	      BCI_CMD_SEND_COLOR;
+
+	par->bci_ptr = 0;
+	BCI_CMD_SET_ROP(cmd, savagefb_rop[rect->rop]);
+
+	par->SavageWaitFifo(par,4);
+	BCI_SEND(cmd);
+	BCI_SEND(color);
+	BCI_SEND( BCI_X_Y(rect->dx, rect->dy) );
+	BCI_SEND( BCI_W_H(rect->width, rect->height) );
+}
+
+void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct savagefb_par *par = info->par;
+	int fg, bg, size, i, width;
+	int cmd;
+	u32 *src = (u32 *) image->data;
+
+	if (!image->width || !image->height)
+		return;
+
+	if (image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		fg = image->fg_color;
+		bg = image->bg_color;
+	} else {
+		fg = ((u32 *)info->pseudo_palette)[image->fg_color];
+		bg = ((u32 *)info->pseudo_palette)[image->bg_color];
+	}
+
+	cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+	      BCI_CMD_CLIP_LR | BCI_CMD_DEST_GBD | BCI_CMD_SRC_MONO |
+	      BCI_CMD_SEND_COLOR;
+
+	par->bci_ptr = 0;
+	BCI_CMD_SET_ROP(cmd, savagefb_rop[0]);
+
+	width = (image->width + 31) & ~31;
+	size = (width * image->height)/8;
+	size >>= 2;
+
+	par->SavageWaitFifo(par, size + 5);
+	BCI_SEND(cmd);
+	BCI_SEND(BCI_CLIP_LR(image->dx, image->dx + image->width - 1));
+	BCI_SEND(fg);
+	BCI_SEND(bg);
+	BCI_SEND(BCI_X_Y(image->dx, image->dy));
+	BCI_SEND(BCI_W_H(width, image->height));
+	for (i = 0; i < size; i++)
+		BCI_SEND(src[i]);
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c
new file mode 100644
index 000000000000..4dbf45f3b21a
--- /dev/null
+++ b/drivers/video/fbdev/savage/savagefb_driver.c
@@ -0,0 +1,2571 @@
+/*
+ * linux/drivers/video/savagefb.c -- S3 Savage Framebuffer Driver
+ *
+ * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
+ *                          Sven Neumann <neo@directfb.org>
+ *
+ *
+ * Card specific code is based on XFree86's savage driver.
+ * Framebuffer framework code is based on code of cyber2000fb and tdfxfb.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * 0.4.0 (neo)
+ *  - hardware accelerated clear and move
+ *
+ * 0.3.2 (dok)
+ *  - wait for vertical retrace before writing to cr67
+ *    at the beginning of savagefb_set_par
+ *  - use synchronization registers cr23 and cr26
+ *
+ * 0.3.1 (dok)
+ *  - reset 3D engine
+ *  - don't return alpha bits for 32bit format
+ *
+ * 0.3.0 (dok)
+ *  - added WaitIdle functions for all Savage types
+ *  - do WaitIdle before mode switching
+ *  - code cleanup
+ *
+ * 0.2.0 (dok)
+ *  - first working version
+ *
+ *
+ * TODO
+ * - clock validations in decode_var
+ *
+ * BUGS
+ * - white margin on bootup
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "savagefb.h"
+
+
+#define SAVAGEFB_VERSION "0.4.0_2.6"
+
+/* --------------------------------------------------------------------- */
+
+
+static char *mode_option = NULL;
+
+#ifdef MODULE
+
+MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");
+
+#endif
+
+
+/* --------------------------------------------------------------------- */
+
+static void vgaHWSeqReset(struct savagefb_par *par, int start)
+{
+	if (start)
+		VGAwSEQ(0x00, 0x01, par);	/* Synchronous Reset */
+	else
+		VGAwSEQ(0x00, 0x03, par);	/* End Reset */
+}
+
+static void vgaHWProtect(struct savagefb_par *par, int on)
+{
+	unsigned char tmp;
+
+	if (on) {
+		/*
+		 * Turn off screen and disable sequencer.
+		 */
+		tmp = VGArSEQ(0x01, par);
+
+		vgaHWSeqReset(par, 1);	        /* start synchronous reset */
+		VGAwSEQ(0x01, tmp | 0x20, par);/* disable the display */
+
+		VGAenablePalette(par);
+	} else {
+		/*
+		 * Reenable sequencer, then turn on screen.
+		 */
+
+		tmp = VGArSEQ(0x01, par);
+
+		VGAwSEQ(0x01, tmp & ~0x20, par);/* reenable display */
+		vgaHWSeqReset(par, 0);	        /* clear synchronous reset */
+
+		VGAdisablePalette(par);
+	}
+}
+
+static void vgaHWRestore(struct savagefb_par  *par, struct savage_reg *reg)
+{
+	int i;
+
+	VGAwMISC(reg->MiscOutReg, par);
+
+	for (i = 1; i < 5; i++)
+		VGAwSEQ(i, reg->Sequencer[i], par);
+
+	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
+	   CRTC[17] */
+	VGAwCR(17, reg->CRTC[17] & ~0x80, par);
+
+	for (i = 0; i < 25; i++)
+		VGAwCR(i, reg->CRTC[i], par);
+
+	for (i = 0; i < 9; i++)
+		VGAwGR(i, reg->Graphics[i], par);
+
+	VGAenablePalette(par);
+
+	for (i = 0; i < 21; i++)
+		VGAwATTR(i, reg->Attribute[i], par);
+
+	VGAdisablePalette(par);
+}
+
+static void vgaHWInit(struct fb_var_screeninfo *var,
+		      struct savagefb_par            *par,
+		      struct xtimings                *timings,
+		      struct savage_reg              *reg)
+{
+	reg->MiscOutReg = 0x23;
+
+	if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
+		reg->MiscOutReg |= 0x40;
+
+	if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
+		reg->MiscOutReg |= 0x80;
+
+	/*
+	 * Time Sequencer
+	 */
+	reg->Sequencer[0x00] = 0x00;
+	reg->Sequencer[0x01] = 0x01;
+	reg->Sequencer[0x02] = 0x0F;
+	reg->Sequencer[0x03] = 0x00;          /* Font select */
+	reg->Sequencer[0x04] = 0x0E;          /* Misc */
+
+	/*
+	 * CRTC Controller
+	 */
+	reg->CRTC[0x00] = (timings->HTotal >> 3) - 5;
+	reg->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
+	reg->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
+	reg->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
+	reg->CRTC[0x04] = (timings->HSyncStart >> 3);
+	reg->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
+		(((timings->HSyncEnd >> 3)) & 0x1f);
+	reg->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
+	reg->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
+		(((timings->VDisplay - 1) & 0x100) >> 7) |
+		((timings->VSyncStart & 0x100) >> 6) |
+		(((timings->VSyncStart - 1) & 0x100) >> 5) |
+		0x10 |
+		(((timings->VTotal - 2) & 0x200) >> 4) |
+		(((timings->VDisplay - 1) & 0x200) >> 3) |
+		((timings->VSyncStart & 0x200) >> 2);
+	reg->CRTC[0x08] = 0x00;
+	reg->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
+
+	if (timings->dblscan)
+		reg->CRTC[0x09] |= 0x80;
+
+	reg->CRTC[0x0a] = 0x00;
+	reg->CRTC[0x0b] = 0x00;
+	reg->CRTC[0x0c] = 0x00;
+	reg->CRTC[0x0d] = 0x00;
+	reg->CRTC[0x0e] = 0x00;
+	reg->CRTC[0x0f] = 0x00;
+	reg->CRTC[0x10] = timings->VSyncStart & 0xff;
+	reg->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
+	reg->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
+	reg->CRTC[0x13] = var->xres_virtual >> 4;
+	reg->CRTC[0x14] = 0x00;
+	reg->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
+	reg->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
+	reg->CRTC[0x17] = 0xc3;
+	reg->CRTC[0x18] = 0xff;
+
+	/*
+	 * are these unnecessary?
+	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
+	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
+	 */
+
+	/*
+	 * Graphics Display Controller
+	 */
+	reg->Graphics[0x00] = 0x00;
+	reg->Graphics[0x01] = 0x00;
+	reg->Graphics[0x02] = 0x00;
+	reg->Graphics[0x03] = 0x00;
+	reg->Graphics[0x04] = 0x00;
+	reg->Graphics[0x05] = 0x40;
+	reg->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
+	reg->Graphics[0x07] = 0x0F;
+	reg->Graphics[0x08] = 0xFF;
+
+
+	reg->Attribute[0x00]  = 0x00; /* standard colormap translation */
+	reg->Attribute[0x01]  = 0x01;
+	reg->Attribute[0x02]  = 0x02;
+	reg->Attribute[0x03]  = 0x03;
+	reg->Attribute[0x04]  = 0x04;
+	reg->Attribute[0x05]  = 0x05;
+	reg->Attribute[0x06]  = 0x06;
+	reg->Attribute[0x07]  = 0x07;
+	reg->Attribute[0x08]  = 0x08;
+	reg->Attribute[0x09]  = 0x09;
+	reg->Attribute[0x0a] = 0x0A;
+	reg->Attribute[0x0b] = 0x0B;
+	reg->Attribute[0x0c] = 0x0C;
+	reg->Attribute[0x0d] = 0x0D;
+	reg->Attribute[0x0e] = 0x0E;
+	reg->Attribute[0x0f] = 0x0F;
+	reg->Attribute[0x10] = 0x41;
+	reg->Attribute[0x11] = 0xFF;
+	reg->Attribute[0x12] = 0x0F;
+	reg->Attribute[0x13] = 0x00;
+	reg->Attribute[0x14] = 0x00;
+}
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Acceleration for SavageFB
+ */
+
+/* Wait for fifo space */
+static void
+savage3D_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C00, par) & 0x0000ffff) > slots);
+}
+
+static void
+savage4_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C60, par) & 0x001fffff) > slots);
+}
+
+static void
+savage2000_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C60, par) & 0x0000ffff) > slots);
+}
+
+/* Wait for idle accelerator */
+static void
+savage3D_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C00, par) & 0x0008ffff) != 0x80000);
+}
+
+static void
+savage4_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C60, par) & 0x00a00000) != 0x00a00000);
+}
+
+static void
+savage2000_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C60, par) & 0x009fffff));
+}
+
+#ifdef CONFIG_FB_SAVAGE_ACCEL
+static void
+SavageSetup2DEngine(struct savagefb_par  *par)
+{
+	unsigned long GlobalBitmapDescriptor;
+
+	GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;
+	BCI_BD_SET_BPP(GlobalBitmapDescriptor, par->depth);
+	BCI_BD_SET_STRIDE(GlobalBitmapDescriptor, par->vwidth);
+
+	switch(par->chip) {
+	case S3_SAVAGE3D:
+	case S3_SAVAGE_MX:
+		/* Disable BCI */
+		savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
+		/* Setup BCI command overflow buffer */
+		savage_out32(0x48C14,
+			     (par->cob_offset >> 11) | (par->cob_index << 29),
+			     par);
+		/* Program shadow status update. */
+		savage_out32(0x48C10, 0x78207220, par);
+		savage_out32(0x48C0C, 0, par);
+		/* Enable BCI and command overflow buffer */
+		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par);
+		break;
+	case S3_SAVAGE4:
+	case S3_TWISTER:
+	case S3_PROSAVAGE:
+	case S3_PROSAVAGEDDR:
+	case S3_SUPERSAVAGE:
+		/* Disable BCI */
+		savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
+		/* Program shadow status update */
+		savage_out32(0x48C10, 0x00700040, par);
+		savage_out32(0x48C0C, 0, par);
+		/* Enable BCI without the COB */
+		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x08, par);
+		break;
+	case S3_SAVAGE2000:
+		/* Disable BCI */
+		savage_out32(0x48C18, 0, par);
+		/* Setup BCI command overflow buffer */
+		savage_out32(0x48C18,
+			     (par->cob_offset >> 7) | (par->cob_index),
+			     par);
+		/* Disable shadow status update */
+		savage_out32(0x48A30, 0, par);
+		/* Enable BCI and command overflow buffer */
+		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x00280000,
+			     par);
+		break;
+	    default:
+		break;
+	}
+	/* Turn on 16-bit register access. */
+	vga_out8(0x3d4, 0x31, par);
+	vga_out8(0x3d5, 0x0c, par);
+
+	/* Set stride to use GBD. */
+	vga_out8(0x3d4, 0x50, par);
+	vga_out8(0x3d5, vga_in8(0x3d5, par) | 0xC1, par);
+
+	/* Enable 2D engine. */
+	vga_out8(0x3d4, 0x40, par);
+	vga_out8(0x3d5, 0x01, par);
+
+	savage_out32(MONO_PAT_0, ~0, par);
+	savage_out32(MONO_PAT_1, ~0, par);
+
+	/* Setup plane masks */
+	savage_out32(0x8128, ~0, par); /* enable all write planes */
+	savage_out32(0x812C, ~0, par); /* enable all read planes */
+	savage_out16(0x8134, 0x27, par);
+	savage_out16(0x8136, 0x07, par);
+
+	/* Now set the GBD */
+	par->bci_ptr = 0;
+	par->SavageWaitFifo(par, 4);
+
+	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD1);
+	BCI_SEND(0);
+	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2);
+	BCI_SEND(GlobalBitmapDescriptor);
+
+	/*
+	 * I don't know why, sending this twice fixes the initial black screen,
+	 * prevents X from crashing at least in Toshiba laptops with SavageIX.
+	 * --Tony
+	 */
+	par->bci_ptr = 0;
+	par->SavageWaitFifo(par, 4);
+
+	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD1);
+	BCI_SEND(0);
+	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2);
+	BCI_SEND(GlobalBitmapDescriptor);
+}
+
+static void savagefb_set_clip(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	int cmd;
+
+	cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
+	par->bci_ptr = 0;
+	par->SavageWaitFifo(par,3);
+	BCI_SEND(cmd);
+	BCI_SEND(BCI_CLIP_TL(0, 0));
+	BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
+}
+#else
+static void SavageSetup2DEngine(struct savagefb_par  *par) {}
+
+#endif
+
+static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
+			    int min_n2, int max_n2, long freq_min,
+			    long freq_max, unsigned int *mdiv,
+			    unsigned int *ndiv, unsigned int *r)
+{
+	long diff, best_diff;
+	unsigned int m;
+	unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
+
+	if (freq < freq_min / (1 << max_n2)) {
+		printk(KERN_ERR "invalid frequency %ld Khz\n", freq);
+		freq = freq_min / (1 << max_n2);
+	}
+	if (freq > freq_max / (1 << min_n2)) {
+		printk(KERN_ERR "invalid frequency %ld Khz\n", freq);
+		freq = freq_max / (1 << min_n2);
+	}
+
+	/* work out suitable timings */
+	best_diff = freq;
+
+	for (n2=min_n2; n2<=max_n2; n2++) {
+		for (n1=min_n1+2; n1<=max_n1+2; n1++) {
+			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
+				BASE_FREQ;
+			if (m < min_m+2 || m > 127+2)
+				continue;
+			if ((m * BASE_FREQ >= freq_min * n1) &&
+			    (m * BASE_FREQ <= freq_max * n1)) {
+				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
+				if (diff < 0)
+					diff = -diff;
+				if (diff < best_diff) {
+					best_diff = diff;
+					best_m = m;
+					best_n1 = n1;
+					best_n2 = n2;
+				}
+			}
+		}
+	}
+
+	*ndiv = best_n1 - 2;
+	*r = best_n2;
+	*mdiv = best_m - 2;
+}
+
+static int common_calc_clock(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)
+{
+	long diff, best_diff;
+	unsigned int m;
+	unsigned char n1, n2;
+	unsigned char best_n1 = 16+2, best_n2 = 2, best_m = 125+2;
+
+	best_diff = freq;
+
+	for (n2 = min_n2; n2 <= max_n2; n2++) {
+		for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {
+			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
+				BASE_FREQ;
+			if (m < min_m + 2 || m > 127+2)
+				continue;
+			if ((m * BASE_FREQ >= freq_min * n1) &&
+			    (m * BASE_FREQ <= freq_max * n1)) {
+				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
+				if (diff < 0)
+					diff = -diff;
+				if (diff < best_diff) {
+					best_diff = diff;
+					best_m = m;
+					best_n1 = n1;
+					best_n2 = n2;
+				}
+			}
+		}
+	}
+
+	if (max_n1 == 63)
+		*ndiv = (best_n1 - 2) | (best_n2 << 6);
+	else
+		*ndiv = (best_n1 - 2) | (best_n2 << 5);
+
+	*mdiv = best_m - 2;
+
+	return 0;
+}
+
+#ifdef SAVAGEFB_DEBUG
+/* This function is used to debug, it prints out the contents of s3 regs */
+
+static void SavagePrintRegs(struct savagefb_par *par)
+{
+	unsigned char i;
+	int vgaCRIndex = 0x3d4;
+	int vgaCRReg = 0x3d5;
+
+	printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "
+	       "xF");
+
+	for (i = 0; i < 0x70; i++) {
+		if (!(i % 16))
+			printk(KERN_DEBUG "\nSR%xx ", i >> 4);
+		vga_out8(0x3c4, i, par);
+		printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par));
+	}
+
+	printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
+	       "xD xE xF");
+
+	for (i = 0; i < 0xB7; i++) {
+		if (!(i % 16))
+			printk(KERN_DEBUG "\nCR%xx ", i >> 4);
+		vga_out8(vgaCRIndex, i, par);
+		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par));
+	}
+
+	printk(KERN_DEBUG "\n\n");
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static void savage_get_default_par(struct savagefb_par *par, struct savage_reg *reg)
+{
+	unsigned char cr3a, cr53, cr66;
+
+	vga_out16(0x3d4, 0x4838, par);
+	vga_out16(0x3d4, 0xa039, par);
+	vga_out16(0x3c4, 0x0608, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+	vga_out8(0x3d4, 0x53, par);
+	cr53 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr53 & 0x7f, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+
+	/* unlock extended seq regs */
+	vga_out8(0x3c4, 0x08, par);
+	reg->SR08 = vga_in8(0x3c5, par);
+	vga_out8(0x3c5, 0x06, par);
+
+	/* now save all the extended regs we need */
+	vga_out8(0x3d4, 0x31, par);
+	reg->CR31 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x32, par);
+	reg->CR32 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x34, par);
+	reg->CR34 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x36, par);
+	reg->CR36 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x3a, par);
+	reg->CR3A = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x40, par);
+	reg->CR40 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x42, par);
+	reg->CR42 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x45, par);
+	reg->CR45 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x50, par);
+	reg->CR50 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x51, par);
+	reg->CR51 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x53, par);
+	reg->CR53 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x58, par);
+	reg->CR58 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x60, par);
+	reg->CR60 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x66, par);
+	reg->CR66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x67, par);
+	reg->CR67 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x68, par);
+	reg->CR68 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x69, par);
+	reg->CR69 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x6f, par);
+	reg->CR6F = vga_in8(0x3d5, par);
+
+	vga_out8(0x3d4, 0x33, par);
+	reg->CR33 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x86, par);
+	reg->CR86 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x88, par);
+	reg->CR88 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x90, par);
+	reg->CR90 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x91, par);
+	reg->CR91 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0xb0, par);
+	reg->CRB0 = vga_in8(0x3d5, par) | 0x80;
+
+	/* extended mode timing regs */
+	vga_out8(0x3d4, 0x3b, par);
+	reg->CR3B = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x3c, par);
+	reg->CR3C = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x43, par);
+	reg->CR43 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x5d, par);
+	reg->CR5D = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x5e, par);
+	reg->CR5E = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x65, par);
+	reg->CR65 = vga_in8(0x3d5, par);
+
+	/* save seq extended regs for DCLK PLL programming */
+	vga_out8(0x3c4, 0x0e, par);
+	reg->SR0E = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x0f, par);
+	reg->SR0F = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x10, par);
+	reg->SR10 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x11, par);
+	reg->SR11 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x12, par);
+	reg->SR12 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x13, par);
+	reg->SR13 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x29, par);
+	reg->SR29 = vga_in8(0x3c5, par);
+
+	vga_out8(0x3c4, 0x15, par);
+	reg->SR15 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x30, par);
+	reg->SR30 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x18, par);
+	reg->SR18 = vga_in8(0x3c5, par);
+
+	/* Save flat panel expansion registers. */
+	if (par->chip == S3_SAVAGE_MX) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			vga_out8(0x3c4, 0x54+i, par);
+			reg->SR54[i] = vga_in8(0x3c5, par);
+		}
+	}
+
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+
+	/* now save MIU regs */
+	if (par->chip != S3_SAVAGE_MX) {
+		reg->MMPR0 = savage_in32(FIFO_CONTROL_REG, par);
+		reg->MMPR1 = savage_in32(MIU_CONTROL_REG, par);
+		reg->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par);
+		reg->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par);
+	}
+
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+}
+
+static void savage_set_default_par(struct savagefb_par *par,
+				struct savage_reg *reg)
+{
+	unsigned char cr3a, cr53, cr66;
+
+	vga_out16(0x3d4, 0x4838, par);
+	vga_out16(0x3d4, 0xa039, par);
+	vga_out16(0x3c4, 0x0608, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+	vga_out8(0x3d4, 0x53, par);
+	cr53 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr53 & 0x7f, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+
+	/* unlock extended seq regs */
+	vga_out8(0x3c4, 0x08, par);
+	vga_out8(0x3c5, reg->SR08, par);
+	vga_out8(0x3c5, 0x06, par);
+
+	/* now restore all the extended regs we need */
+	vga_out8(0x3d4, 0x31, par);
+	vga_out8(0x3d5, reg->CR31, par);
+	vga_out8(0x3d4, 0x32, par);
+	vga_out8(0x3d5, reg->CR32, par);
+	vga_out8(0x3d4, 0x34, par);
+	vga_out8(0x3d5, reg->CR34, par);
+	vga_out8(0x3d4, 0x36, par);
+	vga_out8(0x3d5,reg->CR36, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, reg->CR3A, par);
+	vga_out8(0x3d4, 0x40, par);
+	vga_out8(0x3d5, reg->CR40, par);
+	vga_out8(0x3d4, 0x42, par);
+	vga_out8(0x3d5, reg->CR42, par);
+	vga_out8(0x3d4, 0x45, par);
+	vga_out8(0x3d5, reg->CR45, par);
+	vga_out8(0x3d4, 0x50, par);
+	vga_out8(0x3d5, reg->CR50, par);
+	vga_out8(0x3d4, 0x51, par);
+	vga_out8(0x3d5, reg->CR51, par);
+	vga_out8(0x3d4, 0x53, par);
+	vga_out8(0x3d5, reg->CR53, par);
+	vga_out8(0x3d4, 0x58, par);
+	vga_out8(0x3d5, reg->CR58, par);
+	vga_out8(0x3d4, 0x60, par);
+	vga_out8(0x3d5, reg->CR60, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, reg->CR66, par);
+	vga_out8(0x3d4, 0x67, par);
+	vga_out8(0x3d5, reg->CR67, par);
+	vga_out8(0x3d4, 0x68, par);
+	vga_out8(0x3d5, reg->CR68, par);
+	vga_out8(0x3d4, 0x69, par);
+	vga_out8(0x3d5, reg->CR69, par);
+	vga_out8(0x3d4, 0x6f, par);
+	vga_out8(0x3d5, reg->CR6F, par);
+
+	vga_out8(0x3d4, 0x33, par);
+	vga_out8(0x3d5, reg->CR33, par);
+	vga_out8(0x3d4, 0x86, par);
+	vga_out8(0x3d5, reg->CR86, par);
+	vga_out8(0x3d4, 0x88, par);
+	vga_out8(0x3d5, reg->CR88, par);
+	vga_out8(0x3d4, 0x90, par);
+	vga_out8(0x3d5, reg->CR90, par);
+	vga_out8(0x3d4, 0x91, par);
+	vga_out8(0x3d5, reg->CR91, par);
+	vga_out8(0x3d4, 0xb0, par);
+	vga_out8(0x3d5, reg->CRB0, par);
+
+	/* extended mode timing regs */
+	vga_out8(0x3d4, 0x3b, par);
+	vga_out8(0x3d5, reg->CR3B, par);
+	vga_out8(0x3d4, 0x3c, par);
+	vga_out8(0x3d5, reg->CR3C, par);
+	vga_out8(0x3d4, 0x43, par);
+	vga_out8(0x3d5, reg->CR43, par);
+	vga_out8(0x3d4, 0x5d, par);
+	vga_out8(0x3d5, reg->CR5D, par);
+	vga_out8(0x3d4, 0x5e, par);
+	vga_out8(0x3d5, reg->CR5E, par);
+	vga_out8(0x3d4, 0x65, par);
+	vga_out8(0x3d5, reg->CR65, par);
+
+	/* save seq extended regs for DCLK PLL programming */
+	vga_out8(0x3c4, 0x0e, par);
+	vga_out8(0x3c5, reg->SR0E, par);
+	vga_out8(0x3c4, 0x0f, par);
+	vga_out8(0x3c5, reg->SR0F, par);
+	vga_out8(0x3c4, 0x10, par);
+	vga_out8(0x3c5, reg->SR10, par);
+	vga_out8(0x3c4, 0x11, par);
+	vga_out8(0x3c5, reg->SR11, par);
+	vga_out8(0x3c4, 0x12, par);
+	vga_out8(0x3c5, reg->SR12, par);
+	vga_out8(0x3c4, 0x13, par);
+	vga_out8(0x3c5, reg->SR13, par);
+	vga_out8(0x3c4, 0x29, par);
+	vga_out8(0x3c5, reg->SR29, par);
+
+	vga_out8(0x3c4, 0x15, par);
+	vga_out8(0x3c5, reg->SR15, par);
+	vga_out8(0x3c4, 0x30, par);
+	vga_out8(0x3c5, reg->SR30, par);
+	vga_out8(0x3c4, 0x18, par);
+	vga_out8(0x3c5, reg->SR18, par);
+
+	/* Save flat panel expansion registers. */
+	if (par->chip == S3_SAVAGE_MX) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			vga_out8(0x3c4, 0x54+i, par);
+			vga_out8(0x3c5, reg->SR54[i], par);
+		}
+	}
+
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+
+	/* now save MIU regs */
+	if (par->chip != S3_SAVAGE_MX) {
+		savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par);
+		savage_out32(MIU_CONTROL_REG, reg->MMPR1, par);
+		savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par);
+		savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par);
+	}
+
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+}
+
+static void savage_update_var(struct fb_var_screeninfo *var,
+			      const struct fb_videomode *modedb)
+{
+	var->xres = var->xres_virtual = modedb->xres;
+	var->yres = modedb->yres;
+        if (var->yres_virtual < var->yres)
+	    var->yres_virtual = var->yres;
+        var->xoffset = var->yoffset = 0;
+        var->pixclock = modedb->pixclock;
+        var->left_margin = modedb->left_margin;
+        var->right_margin = modedb->right_margin;
+        var->upper_margin = modedb->upper_margin;
+        var->lower_margin = modedb->lower_margin;
+        var->hsync_len = modedb->hsync_len;
+        var->vsync_len = modedb->vsync_len;
+        var->sync = modedb->sync;
+        var->vmode = modedb->vmode;
+}
+
+static int savagefb_check_var(struct fb_var_screeninfo   *var,
+			      struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	int memlen, vramlen, mode_valid = 0;
+
+	DBG("savagefb_check_var");
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = var->green.offset =
+			var->blue.offset = 0;
+		var->red.length = var->green.length =
+			var->blue.length = var->bits_per_pixel;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
+		mode_valid = 1;
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+
+	if (!mode_valid) {
+		const struct fb_videomode *mode;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			savage_update_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	/* Is the mode larger than the LCD panel? */
+	if (par->SavagePanelWidth &&
+	    (var->xres > par->SavagePanelWidth ||
+	     var->yres > par->SavagePanelHeight)) {
+		printk(KERN_INFO "Mode (%dx%d) larger than the LCD panel "
+		       "(%dx%d)\n", var->xres,  var->yres,
+		       par->SavagePanelWidth,
+		       par->SavagePanelHeight);
+		return -1;
+	}
+
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	vramlen = info->fix.smem_len;
+
+	memlen = var->xres_virtual * var->bits_per_pixel *
+		var->yres_virtual / 8;
+	if (memlen > vramlen) {
+		var->yres_virtual = vramlen * 8 /
+			(var->xres_virtual * var->bits_per_pixel);
+		memlen = var->xres_virtual * var->bits_per_pixel *
+			var->yres_virtual / 8;
+	}
+
+	/* we must round yres/xres down, we already rounded y/xres_virtual up
+	   if it was possible. We should return -EINVAL, but I disagree */
+	if (var->yres_virtual < var->yres)
+		var->yres = var->yres_virtual;
+	if (var->xres_virtual < var->xres)
+		var->xres = var->xres_virtual;
+	if (var->xoffset + var->xres > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	return 0;
+}
+
+
+static int savagefb_decode_var(struct fb_var_screeninfo   *var,
+			       struct savagefb_par        *par,
+			       struct savage_reg          *reg)
+{
+	struct xtimings timings;
+	int width, dclk, i, j; /*, refresh; */
+	unsigned int m, n, r;
+	unsigned char tmp = 0;
+	unsigned int pixclock = var->pixclock;
+
+	DBG("savagefb_decode_var");
+
+	memset(&timings, 0, sizeof(timings));
+
+	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
+	timings.Clock = 1000000000 / pixclock;
+	if (timings.Clock < 1) timings.Clock = 1;
+	timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
+	timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
+	timings.HDisplay = var->xres;
+	timings.HSyncStart = timings.HDisplay + var->right_margin;
+	timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
+	timings.HTotal = timings.HSyncEnd + var->left_margin;
+	timings.VDisplay = var->yres;
+	timings.VSyncStart = timings.VDisplay + var->lower_margin;
+	timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
+	timings.VTotal = timings.VSyncEnd + var->upper_margin;
+	timings.sync = var->sync;
+
+
+	par->depth  = var->bits_per_pixel;
+	par->vwidth = var->xres_virtual;
+
+	if (var->bits_per_pixel == 16  &&  par->chip == S3_SAVAGE3D) {
+		timings.HDisplay *= 2;
+		timings.HSyncStart *= 2;
+		timings.HSyncEnd *= 2;
+		timings.HTotal *= 2;
+	}
+
+	/*
+	 * This will allocate the datastructure and initialize all of the
+	 * generic VGA registers.
+	 */
+	vgaHWInit(var, par, &timings, reg);
+
+	/* We need to set CR67 whether or not we use the BIOS. */
+
+	dclk = timings.Clock;
+	reg->CR67 = 0x00;
+
+	switch(var->bits_per_pixel) {
+	case 8:
+		if ((par->chip == S3_SAVAGE2000) && (dclk >= 230000))
+			reg->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
+		else
+			reg->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
+		break;
+	case 15:
+		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))
+			reg->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
+		else
+			reg->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
+		break;
+	case 16:
+		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		   ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))
+			reg->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
+		else
+			reg->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
+		break;
+	case 24:
+		reg->CR67 = 0x70;
+		break;
+	case 32:
+		reg->CR67 = 0xd0;
+		break;
+	}
+
+	/*
+	 * Either BIOS use is disabled, or we failed to find a suitable
+	 * match.  Fall back to traditional register-crunching.
+	 */
+
+	vga_out8(0x3d4, 0x3a, par);
+	tmp = vga_in8(0x3d5, par);
+	if (1 /*FIXME:psav->pci_burst*/)
+		reg->CR3A = (tmp & 0x7f) | 0x15;
+	else
+		reg->CR3A = tmp | 0x95;
+
+	reg->CR53 = 0x00;
+	reg->CR31 = 0x8c;
+	reg->CR66 = 0x89;
+
+	vga_out8(0x3d4, 0x58, par);
+	reg->CR58 = vga_in8(0x3d5, par) & 0x80;
+	reg->CR58 |= 0x13;
+
+	reg->SR15 = 0x03 | 0x80;
+	reg->SR18 = 0x00;
+	reg->CR43 = reg->CR45 = reg->CR65 = 0x00;
+
+	vga_out8(0x3d4, 0x40, par);
+	reg->CR40 = vga_in8(0x3d5, par) & ~0x01;
+
+	reg->MMPR0 = 0x010400;
+	reg->MMPR1 = 0x00;
+	reg->MMPR2 = 0x0808;
+	reg->MMPR3 = 0x08080810;
+
+	SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
+	/* m = 107; n = 4; r = 2; */
+
+	if (par->MCLK <= 0) {
+		reg->SR10 = 255;
+		reg->SR11 = 255;
+	} else {
+		common_calc_clock(par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
+				   &reg->SR11, &reg->SR10);
+		/*      reg->SR10 = 80; // MCLK == 286000 */
+		/*      reg->SR11 = 125; */
+	}
+
+	reg->SR12 = (r << 6) | (n & 0x3f);
+	reg->SR13 = m & 0xff;
+	reg->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
+
+	if (var->bits_per_pixel < 24)
+		reg->MMPR0 -= 0x8000;
+	else
+		reg->MMPR0 -= 0x4000;
+
+	if (timings.interlaced)
+		reg->CR42 = 0x20;
+	else
+		reg->CR42 = 0x00;
+
+	reg->CR34 = 0x10; /* display fifo */
+
+	i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |
+		((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |
+		((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) |
+		((timings.HSyncStart & 0x800) >> 7);
+
+	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64)
+		i |= 0x08;
+	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)
+		i |= 0x20;
+
+	j = (reg->CRTC[0] + ((i & 0x01) << 8) +
+	     reg->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
+
+	if (j - (reg->CRTC[4] + ((i & 0x10) << 4)) < 4) {
+		if (reg->CRTC[4] + ((i & 0x10) << 4) + 4 <=
+		    reg->CRTC[0] + ((i & 0x01) << 8))
+			j = reg->CRTC[4] + ((i & 0x10) << 4) + 4;
+		else
+			j = reg->CRTC[0] + ((i & 0x01) << 8) + 1;
+	}
+
+	reg->CR3B = j & 0xff;
+	i |= (j & 0x100) >> 2;
+	reg->CR3C = (reg->CRTC[0] + ((i & 0x01) << 8)) / 2;
+	reg->CR5D = i;
+	reg->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
+		(((timings.VDisplay - 1) & 0x400) >> 9) |
+		(((timings.VSyncStart) & 0x400) >> 8) |
+		(((timings.VSyncStart) & 0x400) >> 6) | 0x40;
+	width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;
+	reg->CR91 = reg->CRTC[19] = 0xff & width;
+	reg->CR51 = (0x300 & width) >> 4;
+	reg->CR90 = 0x80 | (width >> 8);
+	reg->MiscOutReg |= 0x0c;
+
+	/* Set frame buffer description. */
+
+	if (var->bits_per_pixel <= 8)
+		reg->CR50 = 0;
+	else if (var->bits_per_pixel <= 16)
+		reg->CR50 = 0x10;
+	else
+		reg->CR50 = 0x30;
+
+	if (var->xres_virtual <= 640)
+		reg->CR50 |= 0x40;
+	else if (var->xres_virtual == 800)
+		reg->CR50 |= 0x80;
+	else if (var->xres_virtual == 1024)
+		reg->CR50 |= 0x00;
+	else if (var->xres_virtual == 1152)
+		reg->CR50 |= 0x01;
+	else if (var->xres_virtual == 1280)
+		reg->CR50 |= 0xc0;
+	else if (var->xres_virtual == 1600)
+		reg->CR50 |= 0x81;
+	else
+		reg->CR50 |= 0xc1;	/* Use GBD */
+
+	if (par->chip == S3_SAVAGE2000)
+		reg->CR33 = 0x08;
+	else
+		reg->CR33 = 0x20;
+
+	reg->CRTC[0x17] = 0xeb;
+
+	reg->CR67 |= 1;
+
+	vga_out8(0x3d4, 0x36, par);
+	reg->CR36 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x68, par);
+	reg->CR68 = vga_in8(0x3d5, par);
+	reg->CR69 = 0;
+	vga_out8(0x3d4, 0x6f, par);
+	reg->CR6F = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x86, par);
+	reg->CR86 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x88, par);
+	reg->CR88 = vga_in8(0x3d5, par) | 0x08;
+	vga_out8(0x3d4, 0xb0, par);
+	reg->CRB0 = vga_in8(0x3d5, par) | 0x80;
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
+static int savagefb_setcolreg(unsigned        regno,
+			      unsigned        red,
+			      unsigned        green,
+			      unsigned        blue,
+			      unsigned        transp,
+			      struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+
+	if (regno >= NR_PALETTE)
+		return -EINVAL;
+
+	par->palette[regno].red    = red;
+	par->palette[regno].green  = green;
+	par->palette[regno].blue   = blue;
+	par->palette[regno].transp = transp;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		vga_out8(0x3c8, regno, par);
+
+		vga_out8(0x3c9, red   >> 10, par);
+		vga_out8(0x3c9, green >> 10, par);
+		vga_out8(0x3c9, blue  >> 10, par);
+		break;
+
+	case 16:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((red   & 0xf800)      ) |
+				((green & 0xfc00) >>  5) |
+				((blue  & 0xf800) >> 11);
+		break;
+
+	case 24:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((red    & 0xff00) <<  8) |
+				((green  & 0xff00)      ) |
+				((blue   & 0xff00) >>  8);
+		break;
+	case 32:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((transp & 0xff00) << 16) |
+				((red    & 0xff00) <<  8) |
+				((green  & 0xff00)      ) |
+				((blue   & 0xff00) >>  8);
+		break;
+
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+static void savagefb_set_par_int(struct savagefb_par  *par, struct savage_reg *reg)
+{
+	unsigned char tmp, cr3a, cr66, cr67;
+
+	DBG("savagefb_set_par_int");
+
+	par->SavageWaitIdle(par);
+
+	vga_out8(0x3c2, 0x23, par);
+
+	vga_out16(0x3d4, 0x4838, par);
+	vga_out16(0x3d4, 0xa539, par);
+	vga_out16(0x3c4, 0x0608, par);
+
+	vgaHWProtect(par, 1);
+
+	/*
+	 * Some Savage/MX and /IX systems go nuts when trying to exit the
+	 * server after WindowMaker has displayed a gradient background.  I
+	 * haven't been able to find what causes it, but a non-destructive
+	 * switch to mode 3 here seems to eliminate the issue.
+	 */
+
+	VerticalRetraceWait(par);
+	vga_out8(0x3d4, 0x67, par);
+	cr67 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */
+
+	vga_out8(0x3d4, 0x23, par);
+	vga_out8(0x3d5, 0x00, par);
+	vga_out8(0x3d4, 0x26, par);
+	vga_out8(0x3d5, 0x00, par);
+
+	/* restore extended regs */
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, reg->CR66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, reg->CR3A, par);
+	vga_out8(0x3d4, 0x31, par);
+	vga_out8(0x3d5, reg->CR31, par);
+	vga_out8(0x3d4, 0x32, par);
+	vga_out8(0x3d5, reg->CR32, par);
+	vga_out8(0x3d4, 0x58, par);
+	vga_out8(0x3d5, reg->CR58, par);
+	vga_out8(0x3d4, 0x53, par);
+	vga_out8(0x3d5, reg->CR53 & 0x7f, par);
+
+	vga_out16(0x3c4, 0x0608, par);
+
+	/* Restore DCLK registers. */
+
+	vga_out8(0x3c4, 0x0e, par);
+	vga_out8(0x3c5, reg->SR0E, par);
+	vga_out8(0x3c4, 0x0f, par);
+	vga_out8(0x3c5, reg->SR0F, par);
+	vga_out8(0x3c4, 0x29, par);
+	vga_out8(0x3c5, reg->SR29, par);
+	vga_out8(0x3c4, 0x15, par);
+	vga_out8(0x3c5, reg->SR15, par);
+
+	/* Restore flat panel expansion registers. */
+	if (par->chip == S3_SAVAGE_MX) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			vga_out8(0x3c4, 0x54+i, par);
+			vga_out8(0x3c5, reg->SR54[i], par);
+		}
+	}
+
+	vgaHWRestore (par, reg);
+
+	/* extended mode timing registers */
+	vga_out8(0x3d4, 0x53, par);
+	vga_out8(0x3d5, reg->CR53, par);
+	vga_out8(0x3d4, 0x5d, par);
+	vga_out8(0x3d5, reg->CR5D, par);
+	vga_out8(0x3d4, 0x5e, par);
+	vga_out8(0x3d5, reg->CR5E, par);
+	vga_out8(0x3d4, 0x3b, par);
+	vga_out8(0x3d5, reg->CR3B, par);
+	vga_out8(0x3d4, 0x3c, par);
+	vga_out8(0x3d5, reg->CR3C, par);
+	vga_out8(0x3d4, 0x43, par);
+	vga_out8(0x3d5, reg->CR43, par);
+	vga_out8(0x3d4, 0x65, par);
+	vga_out8(0x3d5, reg->CR65, par);
+
+	/* restore the desired video mode with cr67 */
+	vga_out8(0x3d4, 0x67, par);
+	/* following part not present in X11 driver */
+	cr67 = vga_in8(0x3d5, par) & 0xf;
+	vga_out8(0x3d5, 0x50 | cr67, par);
+	mdelay(10);
+	vga_out8(0x3d4, 0x67, par);
+	/* end of part */
+	vga_out8(0x3d5, reg->CR67 & ~0x0c, par);
+
+	/* other mode timing and extended regs */
+	vga_out8(0x3d4, 0x34, par);
+	vga_out8(0x3d5, reg->CR34, par);
+	vga_out8(0x3d4, 0x40, par);
+	vga_out8(0x3d5, reg->CR40, par);
+	vga_out8(0x3d4, 0x42, par);
+	vga_out8(0x3d5, reg->CR42, par);
+	vga_out8(0x3d4, 0x45, par);
+	vga_out8(0x3d5, reg->CR45, par);
+	vga_out8(0x3d4, 0x50, par);
+	vga_out8(0x3d5, reg->CR50, par);
+	vga_out8(0x3d4, 0x51, par);
+	vga_out8(0x3d5, reg->CR51, par);
+
+	/* memory timings */
+	vga_out8(0x3d4, 0x36, par);
+	vga_out8(0x3d5, reg->CR36, par);
+	vga_out8(0x3d4, 0x60, par);
+	vga_out8(0x3d5, reg->CR60, par);
+	vga_out8(0x3d4, 0x68, par);
+	vga_out8(0x3d5, reg->CR68, par);
+	vga_out8(0x3d4, 0x69, par);
+	vga_out8(0x3d5, reg->CR69, par);
+	vga_out8(0x3d4, 0x6f, par);
+	vga_out8(0x3d5, reg->CR6F, par);
+
+	vga_out8(0x3d4, 0x33, par);
+	vga_out8(0x3d5, reg->CR33, par);
+	vga_out8(0x3d4, 0x86, par);
+	vga_out8(0x3d5, reg->CR86, par);
+	vga_out8(0x3d4, 0x88, par);
+	vga_out8(0x3d5, reg->CR88, par);
+	vga_out8(0x3d4, 0x90, par);
+	vga_out8(0x3d5, reg->CR90, par);
+	vga_out8(0x3d4, 0x91, par);
+	vga_out8(0x3d5, reg->CR91, par);
+
+	if (par->chip == S3_SAVAGE4) {
+		vga_out8(0x3d4, 0xb0, par);
+		vga_out8(0x3d5, reg->CRB0, par);
+	}
+
+	vga_out8(0x3d4, 0x32, par);
+	vga_out8(0x3d5, reg->CR32, par);
+
+	/* unlock extended seq regs */
+	vga_out8(0x3c4, 0x08, par);
+	vga_out8(0x3c5, 0x06, par);
+
+	/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
+	 * that we should leave the default SR10 and SR11 values there.
+	 */
+	if (reg->SR10 != 255) {
+		vga_out8(0x3c4, 0x10, par);
+		vga_out8(0x3c5, reg->SR10, par);
+		vga_out8(0x3c4, 0x11, par);
+		vga_out8(0x3c5, reg->SR11, par);
+	}
+
+	/* restore extended seq regs for dclk */
+	vga_out8(0x3c4, 0x0e, par);
+	vga_out8(0x3c5, reg->SR0E, par);
+	vga_out8(0x3c4, 0x0f, par);
+	vga_out8(0x3c5, reg->SR0F, par);
+	vga_out8(0x3c4, 0x12, par);
+	vga_out8(0x3c5, reg->SR12, par);
+	vga_out8(0x3c4, 0x13, par);
+	vga_out8(0x3c5, reg->SR13, par);
+	vga_out8(0x3c4, 0x29, par);
+	vga_out8(0x3c5, reg->SR29, par);
+	vga_out8(0x3c4, 0x18, par);
+	vga_out8(0x3c5, reg->SR18, par);
+
+	/* load new m, n pll values for dclk & mclk */
+	vga_out8(0x3c4, 0x15, par);
+	tmp = vga_in8(0x3c5, par) & ~0x21;
+
+	vga_out8(0x3c5, tmp | 0x03, par);
+	vga_out8(0x3c5, tmp | 0x23, par);
+	vga_out8(0x3c5, tmp | 0x03, par);
+	vga_out8(0x3c5, reg->SR15, par);
+	udelay(100);
+
+	vga_out8(0x3c4, 0x30, par);
+	vga_out8(0x3c5, reg->SR30, par);
+	vga_out8(0x3c4, 0x08, par);
+	vga_out8(0x3c5, reg->SR08, par);
+
+	/* now write out cr67 in full, possibly starting STREAMS */
+	VerticalRetraceWait(par);
+	vga_out8(0x3d4, 0x67, par);
+	vga_out8(0x3d5, reg->CR67, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+
+	if (par->chip != S3_SAVAGE_MX) {
+		VerticalRetraceWait(par);
+		savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par);
+		par->SavageWaitIdle(par);
+		savage_out32(MIU_CONTROL_REG, reg->MMPR1, par);
+		par->SavageWaitIdle(par);
+		savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par);
+		par->SavageWaitIdle(par);
+		savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par);
+	}
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+
+	SavageSetup2DEngine(par);
+	vgaHWProtect(par, 0);
+}
+
+static void savagefb_update_start(struct savagefb_par *par, int base)
+{
+	/* program the start address registers */
+	vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
+	vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
+	vga_out8(0x3d4, 0x69, par);
+	vga_out8(0x3d5, (base & 0x7f0000) >> 16, par);
+}
+
+
+static void savagefb_set_fix(struct fb_info *info)
+{
+	info->fix.line_length = info->var.xres_virtual *
+		info->var.bits_per_pixel / 8;
+
+	if (info->var.bits_per_pixel == 8) {
+		info->fix.visual      = FB_VISUAL_PSEUDOCOLOR;
+		info->fix.xpanstep    = 4;
+	} else {
+		info->fix.visual      = FB_VISUAL_TRUECOLOR;
+		info->fix.xpanstep    = 2;
+	}
+
+}
+
+static int savagefb_set_par(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int err;
+
+	DBG("savagefb_set_par");
+	err = savagefb_decode_var(var, par, &par->state);
+	if (err)
+		return err;
+
+	if (par->dacSpeedBpp <= 0) {
+		if (var->bits_per_pixel > 24)
+			par->dacSpeedBpp = par->clock[3];
+		else if (var->bits_per_pixel >= 24)
+			par->dacSpeedBpp = par->clock[2];
+		else if ((var->bits_per_pixel > 8) && (var->bits_per_pixel < 24))
+			par->dacSpeedBpp = par->clock[1];
+		else if (var->bits_per_pixel <= 8)
+			par->dacSpeedBpp = par->clock[0];
+	}
+
+	/* Set ramdac limits */
+	par->maxClock = par->dacSpeedBpp;
+	par->minClock = 10000;
+
+	savagefb_set_par_int(par, &par->state);
+	fb_set_cmap(&info->cmap, info);
+	savagefb_set_fix(info);
+	savagefb_set_clip(info);
+
+	SavagePrintRegs(par);
+	return 0;
+}
+
+/*
+ *    Pan or Wrap the Display
+ */
+static int savagefb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info           *info)
+{
+	struct savagefb_par *par = info->par;
+	int base;
+
+	base = (var->yoffset * info->fix.line_length
+	     + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2;
+
+	savagefb_update_start(par, base);
+	return 0;
+}
+
+static int savagefb_blank(int blank, struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	u8 sr8 = 0, srd = 0;
+
+	if (par->display_type == DISP_CRT) {
+		vga_out8(0x3c4, 0x08, par);
+		sr8 = vga_in8(0x3c5, par);
+		sr8 |= 0x06;
+		vga_out8(0x3c5, sr8, par);
+		vga_out8(0x3c4, 0x0d, par);
+		srd = vga_in8(0x3c5, par);
+		srd &= 0x50;
+
+		switch (blank) {
+		case FB_BLANK_UNBLANK:
+		case FB_BLANK_NORMAL:
+			break;
+		case FB_BLANK_VSYNC_SUSPEND:
+			srd |= 0x10;
+			break;
+		case FB_BLANK_HSYNC_SUSPEND:
+			srd |= 0x40;
+			break;
+		case FB_BLANK_POWERDOWN:
+			srd |= 0x50;
+			break;
+		}
+
+		vga_out8(0x3c4, 0x0d, par);
+		vga_out8(0x3c5, srd, par);
+	}
+
+	if (par->display_type == DISP_LCD ||
+	    par->display_type == DISP_DFP) {
+		switch(blank) {
+		case FB_BLANK_UNBLANK:
+		case FB_BLANK_NORMAL:
+			vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
+			vga_out8(0x3c5, vga_in8(0x3c5, par) | 0x10, par);
+			break;
+		case FB_BLANK_VSYNC_SUSPEND:
+		case FB_BLANK_HSYNC_SUSPEND:
+		case FB_BLANK_POWERDOWN:
+			vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
+			vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x10, par);
+			break;
+		}
+	}
+
+	return (blank == FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static int savagefb_open(struct fb_info *info, int user)
+{
+	struct savagefb_par *par = info->par;
+
+	mutex_lock(&par->open_lock);
+
+	if (!par->open_count) {
+		memset(&par->vgastate, 0, sizeof(par->vgastate));
+		par->vgastate.flags = VGA_SAVE_CMAP | VGA_SAVE_FONTS |
+			VGA_SAVE_MODE;
+		par->vgastate.vgabase = par->mmio.vbase + 0x8000;
+		save_vga(&par->vgastate);
+		savage_get_default_par(par, &par->initial);
+	}
+
+	par->open_count++;
+	mutex_unlock(&par->open_lock);
+	return 0;
+}
+
+static int savagefb_release(struct fb_info *info, int user)
+{
+	struct savagefb_par *par = info->par;
+
+	mutex_lock(&par->open_lock);
+
+	if (par->open_count == 1) {
+		savage_set_default_par(par, &par->initial);
+		restore_vga(&par->vgastate);
+	}
+
+	par->open_count--;
+	mutex_unlock(&par->open_lock);
+	return 0;
+}
+
+static struct fb_ops savagefb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_open        = savagefb_open,
+	.fb_release     = savagefb_release,
+	.fb_check_var   = savagefb_check_var,
+	.fb_set_par     = savagefb_set_par,
+	.fb_setcolreg   = savagefb_setcolreg,
+	.fb_pan_display = savagefb_pan_display,
+	.fb_blank       = savagefb_blank,
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	.fb_fillrect    = savagefb_fillrect,
+	.fb_copyarea    = savagefb_copyarea,
+	.fb_imageblit   = savagefb_imageblit,
+	.fb_sync        = savagefb_sync,
+#else
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+#endif
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo savagefb_var800x600x8 = {
+	.accel_flags =	FB_ACCELF_TEXT,
+	.xres =		800,
+	.yres =		600,
+	.xres_virtual =  800,
+	.yres_virtual =  600,
+	.bits_per_pixel = 8,
+	.pixclock =	25000,
+	.left_margin =	88,
+	.right_margin =	40,
+	.upper_margin =	23,
+	.lower_margin =	1,
+	.hsync_len =	128,
+	.vsync_len =	4,
+	.sync =		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode =	FB_VMODE_NONINTERLACED
+};
+
+static void savage_enable_mmio(struct savagefb_par *par)
+{
+	unsigned char val;
+
+	DBG("savage_enable_mmio\n");
+
+	val = vga_in8(0x3c3, par);
+	vga_out8(0x3c3, val | 0x01, par);
+	val = vga_in8(0x3cc, par);
+	vga_out8(0x3c2, val | 0x01, par);
+
+	if (par->chip >= S3_SAVAGE4) {
+		vga_out8(0x3d4, 0x40, par);
+		val = vga_in8(0x3d5, par);
+		vga_out8(0x3d5, val | 1, par);
+	}
+}
+
+
+static void savage_disable_mmio(struct savagefb_par *par)
+{
+	unsigned char val;
+
+	DBG("savage_disable_mmio\n");
+
+	if (par->chip >= S3_SAVAGE4) {
+		vga_out8(0x3d4, 0x40, par);
+		val = vga_in8(0x3d5, par);
+		vga_out8(0x3d5, val | 1, par);
+	}
+}
+
+
+static int savage_map_mmio(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	DBG("savage_map_mmio");
+
+	if (S3_SAVAGE3D_SERIES(par->chip))
+		par->mmio.pbase = pci_resource_start(par->pcidev, 0) +
+			SAVAGE_NEWMMIO_REGBASE_S3;
+	else
+		par->mmio.pbase = pci_resource_start(par->pcidev, 0) +
+			SAVAGE_NEWMMIO_REGBASE_S4;
+
+	par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
+
+	par->mmio.vbase = ioremap(par->mmio.pbase, par->mmio.len);
+	if (!par->mmio.vbase) {
+		printk("savagefb: unable to map memory mapped IO\n");
+		return -ENOMEM;
+	} else
+		printk(KERN_INFO "savagefb: mapped io at %p\n",
+			par->mmio.vbase);
+
+	info->fix.mmio_start = par->mmio.pbase;
+	info->fix.mmio_len   = par->mmio.len;
+
+	par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
+	par->bci_ptr  = 0;
+
+	savage_enable_mmio(par);
+
+	return 0;
+}
+
+static void savage_unmap_mmio(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	DBG("savage_unmap_mmio");
+
+	savage_disable_mmio(par);
+
+	if (par->mmio.vbase) {
+		iounmap(par->mmio.vbase);
+		par->mmio.vbase = NULL;
+	}
+}
+
+static int savage_map_video(struct fb_info *info, int video_len)
+{
+	struct savagefb_par *par = info->par;
+	int resource;
+
+	DBG("savage_map_video");
+
+	if (S3_SAVAGE3D_SERIES(par->chip))
+		resource = 0;
+	else
+		resource = 1;
+
+	par->video.pbase = pci_resource_start(par->pcidev, resource);
+	par->video.len   = video_len;
+	par->video.vbase = ioremap(par->video.pbase, par->video.len);
+
+	if (!par->video.vbase) {
+		printk("savagefb: unable to map screen memory\n");
+		return -ENOMEM;
+	} else
+		printk(KERN_INFO "savagefb: mapped framebuffer at %p, "
+		       "pbase == %x\n", par->video.vbase, par->video.pbase);
+
+	info->fix.smem_start = par->video.pbase;
+	info->fix.smem_len   = par->video.len - par->cob_size;
+	info->screen_base    = par->video.vbase;
+
+#ifdef CONFIG_MTRR
+	par->video.mtrr = mtrr_add(par->video.pbase, video_len,
+				   MTRR_TYPE_WRCOMB, 1);
+#endif
+
+	/* Clear framebuffer, it's all white in memory after boot */
+	memset_io(par->video.vbase, 0, par->video.len);
+
+	return 0;
+}
+
+static void savage_unmap_video(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+
+	DBG("savage_unmap_video");
+
+	if (par->video.vbase) {
+#ifdef CONFIG_MTRR
+		mtrr_del(par->video.mtrr, par->video.pbase, par->video.len);
+#endif
+
+		iounmap(par->video.vbase);
+		par->video.vbase = NULL;
+		info->screen_base = NULL;
+	}
+}
+
+static int savage_init_hw(struct savagefb_par *par)
+{
+	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
+
+	static unsigned char RamSavage3D[] = { 8, 4, 4, 2 };
+	static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
+	static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
+	static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
+	int videoRam, videoRambytes, dvi;
+
+	DBG("savage_init_hw");
+
+	/* unprotect CRTC[0-7] */
+	vga_out8(0x3d4, 0x11, par);
+	tmp = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, tmp & 0x7f, par);
+
+	/* unlock extended regs */
+	vga_out16(0x3d4, 0x4838, par);
+	vga_out16(0x3d4, 0xa039, par);
+	vga_out16(0x3c4, 0x0608, par);
+
+	vga_out8(0x3d4, 0x40, par);
+	tmp = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, tmp & ~0x01, par);
+
+	/* unlock sys regs */
+	vga_out8(0x3d4, 0x38, par);
+	vga_out8(0x3d5, 0x48, par);
+
+	/* Unlock system registers. */
+	vga_out16(0x3d4, 0x4838, par);
+
+	/* Next go on to detect amount of installed ram */
+
+	vga_out8(0x3d4, 0x36, par);            /* for register CR36 (CONFG_REG1), */
+	config1 = vga_in8(0x3d5, par);    /* get amount of vram installed */
+
+	/* Compute the amount of video memory and offscreen memory. */
+
+	switch  (par->chip) {
+	case S3_SAVAGE3D:
+		videoRam = RamSavage3D[(config1 & 0xC0) >> 6 ] * 1024;
+		break;
+
+	case S3_SAVAGE4:
+		/*
+		 * The Savage4 has one ugly special case to consider.  On
+		 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
+		 * when it really means 8MB.  Why do it the same when you
+		 * can do it different...
+		 */
+		vga_out8(0x3d4, 0x68, par);	/* memory control 1 */
+		if ((vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6))
+			RamSavage4[1] = 8;
+
+		/*FALLTHROUGH*/
+
+	case S3_SAVAGE2000:
+		videoRam = RamSavage4[(config1 & 0xE0) >> 5] * 1024;
+		break;
+
+	case S3_SAVAGE_MX:
+	case S3_SUPERSAVAGE:
+		videoRam = RamSavageMX[(config1 & 0x0E) >> 1] * 1024;
+		break;
+
+	case S3_PROSAVAGE:
+	case S3_PROSAVAGEDDR:
+	case S3_TWISTER:
+		videoRam = RamSavageNB[(config1 & 0xE0) >> 5] * 1024;
+		break;
+
+	default:
+		/* How did we get here? */
+		videoRam = 0;
+		break;
+	}
+
+	videoRambytes = videoRam * 1024;
+
+	printk(KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
+
+	/* reset graphics engine to avoid memory corruption */
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x02, par);
+	mdelay(10);
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66 & ~0x02, par);	/* clear reset flag */
+	mdelay(10);
+
+
+	/*
+	 * reset memory interface, 3D engine, AGP master, PCI master,
+	 * master engine unit, motion compensation/LPB
+	 */
+	vga_out8(0x3d4, 0x3f, par);
+	cr3f = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3f | 0x08, par);
+	mdelay(10);
+
+	vga_out8(0x3d4, 0x3f, par);
+	vga_out8(0x3d5, cr3f & ~0x08, par);	/* clear reset flags */
+	mdelay(10);
+
+	/* Savage ramdac speeds */
+	par->numClocks = 4;
+	par->clock[0] = 250000;
+	par->clock[1] = 250000;
+	par->clock[2] = 220000;
+	par->clock[3] = 220000;
+
+	/* detect current mclk */
+	vga_out8(0x3c4, 0x08, par);
+	sr8 = vga_in8(0x3c5, par);
+	vga_out8(0x3c5, 0x06, par);
+	vga_out8(0x3c4, 0x10, par);
+	n = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x11, par);
+	m = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x08, par);
+	vga_out8(0x3c5, sr8, par);
+	m &= 0x7f;
+	n1 = n & 0x1f;
+	n2 = (n >> 5) & 0x03;
+	par->MCLK = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
+	printk(KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
+		par->MCLK);
+
+	/* check for DVI/flat panel */
+	dvi = 0;
+
+	if (par->chip == S3_SAVAGE4) {
+		unsigned char sr30 = 0x00;
+
+		vga_out8(0x3c4, 0x30, par);
+		/* clear bit 1 */
+		vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x02, par);
+		sr30 = vga_in8(0x3c5, par);
+		if (sr30 & 0x02 /*0x04 */) {
+			dvi = 1;
+			printk("savagefb: Digital Flat Panel Detected\n");
+		}
+	}
+
+	if ((S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+	     S3_MOBILE_TWISTER_SERIES(par->chip)) && !par->crtonly)
+		par->display_type = DISP_LCD;
+	else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
+		par->display_type = DISP_DFP;
+	else
+		par->display_type = DISP_CRT;
+
+	/* Check LCD panel parrmation */
+
+	if (par->display_type == DISP_LCD) {
+		unsigned char cr6b = VGArCR(0x6b, par);
+
+		int panelX = (VGArSEQ(0x61, par) +
+			      ((VGArSEQ(0x66, par) & 0x02) << 7) + 1) * 8;
+		int panelY = (VGArSEQ(0x69, par) +
+			      ((VGArSEQ(0x6e, par) & 0x70) << 4) + 1);
+
+		char * sTechnology = "Unknown";
+
+		/* OK, I admit it.  I don't know how to limit the max dot clock
+		 * for LCD panels of various sizes.  I thought I copied the
+		 * formula from the BIOS, but many users have parrmed me of
+		 * my folly.
+		 *
+		 * Instead, I'll abandon any attempt to automatically limit the
+		 * clock, and add an LCDClock option to XF86Config.  Some day,
+		 * I should come back to this.
+		 */
+
+		enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */
+			ActiveCRT = 0x01,
+			ActiveLCD = 0x02,
+			ActiveTV = 0x04,
+			ActiveCRT2 = 0x20,
+			ActiveDUO = 0x80
+		};
+
+		if ((VGArSEQ(0x39, par) & 0x03) == 0) {
+			sTechnology = "TFT";
+		} else if ((VGArSEQ(0x30, par) & 0x01) == 0) {
+			sTechnology = "DSTN";
+		} else 	{
+			sTechnology = "STN";
+		}
+
+		printk(KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
+		       panelX, panelY, sTechnology,
+		       cr6b & ActiveLCD ? "and active" : "but not active");
+
+		if (cr6b & ActiveLCD) 	{
+			/*
+			 * If the LCD is active and panel expansion is enabled,
+			 * we probably want to kill the HW cursor.
+			 */
+
+			printk(KERN_INFO "savagefb: Limiting video mode to "
+				"%dx%d\n", panelX, panelY);
+
+			par->SavagePanelWidth = panelX;
+			par->SavagePanelHeight = panelY;
+
+		} else
+			par->display_type = DISP_CRT;
+	}
+
+	savage_get_default_par(par, &par->state);
+	par->save = par->state;
+
+	if (S3_SAVAGE4_SERIES(par->chip)) {
+		/*
+		 * The Savage4 and ProSavage have COB coherency bugs which
+		 * render the buffer useless.  We disable it.
+		 */
+		par->cob_index = 2;
+		par->cob_size = 0x8000 << par->cob_index;
+		par->cob_offset = videoRambytes;
+	} else {
+		/* We use 128kB for the COB on all chips. */
+
+		par->cob_index  = 7;
+		par->cob_size   = 0x400 << par->cob_index;
+		par->cob_offset = videoRambytes - par->cob_size;
+	}
+
+	return videoRambytes;
+}
+
+static int savage_init_fb_info(struct fb_info *info, struct pci_dev *dev,
+			       const struct pci_device_id *id)
+{
+	struct savagefb_par *par = info->par;
+	int err = 0;
+
+	par->pcidev  = dev;
+
+	info->fix.type	   = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux	   = 0;
+	info->fix.ypanstep	   = 1;
+	info->fix.ywrapstep   = 0;
+	info->fix.accel       = id->driver_data;
+
+	switch (info->fix.accel) {
+	case FB_ACCEL_SUPERSAVAGE:
+		par->chip = S3_SUPERSAVAGE;
+		snprintf(info->fix.id, 16, "SuperSavage");
+		break;
+	case FB_ACCEL_SAVAGE4:
+		par->chip = S3_SAVAGE4;
+		snprintf(info->fix.id, 16, "Savage4");
+		break;
+	case FB_ACCEL_SAVAGE3D:
+		par->chip = S3_SAVAGE3D;
+		snprintf(info->fix.id, 16, "Savage3D");
+		break;
+	case FB_ACCEL_SAVAGE3D_MV:
+		par->chip = S3_SAVAGE3D;
+		snprintf(info->fix.id, 16, "Savage3D-MV");
+		break;
+	case FB_ACCEL_SAVAGE2000:
+		par->chip = S3_SAVAGE2000;
+		snprintf(info->fix.id, 16, "Savage2000");
+		break;
+	case FB_ACCEL_SAVAGE_MX_MV:
+		par->chip = S3_SAVAGE_MX;
+		snprintf(info->fix.id, 16, "Savage/MX-MV");
+		break;
+	case FB_ACCEL_SAVAGE_MX:
+		par->chip = S3_SAVAGE_MX;
+		snprintf(info->fix.id, 16, "Savage/MX");
+		break;
+	case FB_ACCEL_SAVAGE_IX_MV:
+		par->chip = S3_SAVAGE_MX;
+		snprintf(info->fix.id, 16, "Savage/IX-MV");
+		break;
+	case FB_ACCEL_SAVAGE_IX:
+		par->chip = S3_SAVAGE_MX;
+		snprintf(info->fix.id, 16, "Savage/IX");
+		break;
+	case FB_ACCEL_PROSAVAGE_PM:
+		par->chip = S3_PROSAVAGE;
+		snprintf(info->fix.id, 16, "ProSavagePM");
+		break;
+	case FB_ACCEL_PROSAVAGE_KM:
+		par->chip = S3_PROSAVAGE;
+		snprintf(info->fix.id, 16, "ProSavageKM");
+		break;
+	case FB_ACCEL_S3TWISTER_P:
+		par->chip = S3_TWISTER;
+		snprintf(info->fix.id, 16, "TwisterP");
+		break;
+	case FB_ACCEL_S3TWISTER_K:
+		par->chip = S3_TWISTER;
+		snprintf(info->fix.id, 16, "TwisterK");
+		break;
+	case FB_ACCEL_PROSAVAGE_DDR:
+		par->chip = S3_PROSAVAGEDDR;
+		snprintf(info->fix.id, 16, "ProSavageDDR");
+		break;
+	case FB_ACCEL_PROSAVAGE_DDRK:
+		par->chip = S3_PROSAVAGEDDR;
+		snprintf(info->fix.id, 16, "ProSavage8");
+		break;
+	}
+
+	if (S3_SAVAGE3D_SERIES(par->chip)) {
+		par->SavageWaitIdle = savage3D_waitidle;
+		par->SavageWaitFifo = savage3D_waitfifo;
+	} else if (S3_SAVAGE4_SERIES(par->chip) ||
+		   S3_SUPERSAVAGE == par->chip) {
+		par->SavageWaitIdle = savage4_waitidle;
+		par->SavageWaitFifo = savage4_waitfifo;
+	} else {
+		par->SavageWaitIdle = savage2000_waitidle;
+		par->SavageWaitFifo = savage2000_waitfifo;
+	}
+
+	info->var.nonstd      = 0;
+	info->var.activate    = FB_ACTIVATE_NOW;
+	info->var.width       = -1;
+	info->var.height      = -1;
+	info->var.accel_flags = 0;
+
+	info->fbops          = &savagefb_ops;
+	info->flags          = FBINFO_DEFAULT |
+		               FBINFO_HWACCEL_YPAN |
+		               FBINFO_HWACCEL_XPAN;
+
+	info->pseudo_palette = par->pseudo_palette;
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	/* FIFO size + padding for commands */
+	info->pixmap.addr = kcalloc(8, 1024, GFP_KERNEL);
+
+	err = -ENOMEM;
+	if (info->pixmap.addr) {
+		info->pixmap.size = 8*1024;
+		info->pixmap.scan_align = 4;
+		info->pixmap.buf_align = 4;
+		info->pixmap.access_align = 32;
+
+		err = fb_alloc_cmap(&info->cmap, NR_PALETTE, 0);
+		if (!err)
+		info->flags |= FBINFO_HWACCEL_COPYAREA |
+	                       FBINFO_HWACCEL_FILLRECT |
+		               FBINFO_HWACCEL_IMAGEBLIT;
+	}
+#endif
+	return err;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct fb_info *info;
+	struct savagefb_par *par;
+	u_int h_sync, v_sync;
+	int err, lpitch;
+	int video_len;
+
+	DBG("savagefb_probe");
+
+	info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+	mutex_init(&par->open_lock);
+	err = pci_enable_device(dev);
+	if (err)
+		goto failed_enable;
+
+	if ((err = pci_request_regions(dev, "savagefb"))) {
+		printk(KERN_ERR "cannot request PCI regions\n");
+		goto failed_enable;
+	}
+
+	err = -ENOMEM;
+
+	if ((err = savage_init_fb_info(info, dev, id)))
+		goto failed_init;
+
+	err = savage_map_mmio(info);
+	if (err)
+		goto failed_mmio;
+
+	video_len = savage_init_hw(par);
+	/* FIXME: can't be negative */
+	if (video_len < 0) {
+		err = video_len;
+		goto failed_mmio;
+	}
+
+	err = savage_map_video(info, video_len);
+	if (err)
+		goto failed_video;
+
+	INIT_LIST_HEAD(&info->modelist);
+#if defined(CONFIG_FB_SAVAGE_I2C)
+	savagefb_create_i2c_busses(info);
+	savagefb_probe_i2c_connector(info, &par->edid);
+	fb_edid_to_monspecs(par->edid, &info->monspecs);
+	kfree(par->edid);
+	fb_videomode_to_modelist(info->monspecs.modedb,
+				 info->monspecs.modedb_len,
+				 &info->modelist);
+#endif
+	info->var = savagefb_var800x600x8;
+	/* if a panel was detected, default to a CVT mode instead */
+	if (par->SavagePanelWidth) {
+		struct fb_videomode cvt_mode;
+
+		memset(&cvt_mode, 0, sizeof(cvt_mode));
+		cvt_mode.xres = par->SavagePanelWidth;
+		cvt_mode.yres = par->SavagePanelHeight;
+		cvt_mode.refresh = 60;
+		/* FIXME: if we know there is only the panel
+		 * we can enable reduced blanking as well */
+		if (fb_find_mode_cvt(&cvt_mode, 0, 0))
+			printk(KERN_WARNING "No CVT mode found for panel\n");
+		else if (fb_find_mode(&info->var, info, NULL, NULL, 0,
+				      &cvt_mode, 0) != 3)
+			info->var = savagefb_var800x600x8;
+	}
+
+	if (mode_option) {
+		fb_find_mode(&info->var, info, mode_option,
+			     info->monspecs.modedb, info->monspecs.modedb_len,
+			     NULL, 8);
+	} else if (info->monspecs.modedb != NULL) {
+		const struct fb_videomode *mode;
+
+		mode = fb_find_best_display(&info->monspecs, &info->modelist);
+		savage_update_var(&info->var, mode);
+	}
+
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len/lpitch;
+
+	if (info->var.yres_virtual < info->var.yres) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	/*
+	 * The clipping coordinates are masked with 0xFFF, so limit our
+	 * virtual resolutions to these sizes.
+	 */
+	if (info->var.yres_virtual > 0x1000)
+		info->var.yres_virtual = 0x1000;
+
+	if (info->var.xres_virtual > 0x1000)
+		info->var.xres_virtual = 0x1000;
+#endif
+	savagefb_check_var(&info->var, info);
+	savagefb_set_fix(info);
+
+	/*
+	 * Calculate the hsync and vsync frequencies.  Note that
+	 * we split the 1e12 constant up so that we can preserve
+	 * the precision and fit the results into 32-bit registers.
+	 *  (1953125000 * 512 = 1e12)
+	 */
+	h_sync = 1953125000 / info->var.pixclock;
+	h_sync = h_sync * 512 / (info->var.xres + info->var.left_margin +
+				 info->var.right_margin +
+				 info->var.hsync_len);
+	v_sync = h_sync / (info->var.yres + info->var.upper_margin +
+			   info->var.lower_margin + info->var.vsync_len);
+
+	printk(KERN_INFO "savagefb v" SAVAGEFB_VERSION ": "
+	       "%dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+	       info->fix.smem_len >> 10,
+	       info->var.xres, info->var.yres,
+	       h_sync / 1000, h_sync % 1000, v_sync);
+
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto failed;
+
+	printk(KERN_INFO "fb: S3 %s frame buffer device\n",
+	       info->fix.id);
+
+	/*
+	 * Our driver data
+	 */
+	pci_set_drvdata(dev, info);
+
+	return 0;
+
+ failed:
+#ifdef CONFIG_FB_SAVAGE_I2C
+	savagefb_delete_i2c_busses(info);
+#endif
+	fb_alloc_cmap(&info->cmap, 0, 0);
+	savage_unmap_video(info);
+ failed_video:
+	savage_unmap_mmio(info);
+ failed_mmio:
+	kfree(info->pixmap.addr);
+ failed_init:
+	pci_release_regions(dev);
+ failed_enable:
+	framebuffer_release(info);
+
+	return err;
+}
+
+static void savagefb_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+
+	DBG("savagefb_remove");
+
+	if (info) {
+		/*
+		 * If unregister_framebuffer fails, then
+		 * we will be leaving hooks that could cause
+		 * oopsen laying around.
+		 */
+		if (unregister_framebuffer(info))
+			printk(KERN_WARNING "savagefb: danger danger! "
+			       "Oopsen imminent!\n");
+
+#ifdef CONFIG_FB_SAVAGE_I2C
+		savagefb_delete_i2c_busses(info);
+#endif
+		fb_alloc_cmap(&info->cmap, 0, 0);
+		savage_unmap_video(info);
+		savage_unmap_mmio(info);
+		kfree(info->pixmap.addr);
+		pci_release_regions(dev);
+		framebuffer_release(info);
+	}
+}
+
+static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct savagefb_par *par = info->par;
+
+	DBG("savagefb_suspend");
+
+	if (mesg.event == PM_EVENT_PRETHAW)
+		mesg.event = PM_EVENT_FREEZE;
+	par->pm_state = mesg.event;
+	dev->dev.power.power_state = mesg;
+
+	/*
+	 * For PM_EVENT_FREEZE, do not power down so the console
+	 * can remain active.
+	 */
+	if (mesg.event == PM_EVENT_FREEZE)
+		return 0;
+
+	console_lock();
+	fb_set_suspend(info, 1);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	savagefb_blank(FB_BLANK_POWERDOWN, info);
+	savage_set_default_par(par, &par->save);
+	savage_disable_mmio(par);
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, mesg));
+	console_unlock();
+
+	return 0;
+}
+
+static int savagefb_resume(struct pci_dev* dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct savagefb_par *par = info->par;
+	int cur_state = par->pm_state;
+
+	DBG("savage_resume");
+
+	par->pm_state = PM_EVENT_ON;
+
+	/*
+	 * The adapter was not powered down coming back from a
+	 * PM_EVENT_FREEZE.
+	 */
+	if (cur_state == PM_EVENT_FREEZE) {
+		pci_set_power_state(dev, PCI_D0);
+		return 0;
+	}
+
+	console_lock();
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+
+	if (pci_enable_device(dev))
+		DBG("err");
+
+	pci_set_master(dev);
+	savage_enable_mmio(par);
+	savage_init_hw(par);
+	savagefb_set_par(info);
+	fb_set_suspend(info, 0);
+	savagefb_blank(FB_BLANK_UNBLANK, info);
+	console_unlock();
+
+	return 0;
+}
+
+
+static struct pci_device_id savagefb_devices[] = {
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64C,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCSDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCDDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE4},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE2000},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_PM,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_PM},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_KM,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_KM},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_P,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_P},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_K,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_K},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDR},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDRK,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDRK},
+
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, savagefb_devices);
+
+static struct pci_driver savagefb_driver = {
+	.name =     "savagefb",
+	.id_table = savagefb_devices,
+	.probe =    savagefb_probe,
+	.suspend =  savagefb_suspend,
+	.resume =   savagefb_resume,
+	.remove =   savagefb_remove,
+};
+
+/* **************************** exit-time only **************************** */
+
+static void __exit savage_done(void)
+{
+	DBG("savage_done");
+	pci_unregister_driver(&savagefb_driver);
+}
+
+
+/* ************************* init in-kernel code ************************** */
+
+static int __init savagefb_setup(char *options)
+{
+#ifndef MODULE
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		mode_option = this_opt;
+	}
+#endif /* !MODULE */
+	return 0;
+}
+
+static int __init savagefb_init(void)
+{
+	char *option;
+
+	DBG("savagefb_init");
+
+	if (fb_get_options("savagefb", &option))
+		return -ENODEV;
+
+	savagefb_setup(option);
+	return pci_register_driver(&savagefb_driver);
+
+}
+
+module_init(savagefb_init);
+module_exit(savage_done);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
diff --git a/drivers/video/fbdev/sbuslib.c b/drivers/video/fbdev/sbuslib.c
new file mode 100644
index 000000000000..a350209ffbd3
--- /dev/null
+++ b/drivers/video/fbdev/sbuslib.c
@@ -0,0 +1,267 @@
+/* sbuslib.c: Helper library for SBUS framebuffer drivers.
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/of_device.h>
+
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp,
+		     int bpp)
+{
+	memset(var, 0, sizeof(*var));
+
+	var->xres = of_getintprop_default(dp, "width", 1152);
+	var->yres = of_getintprop_default(dp, "height", 900);
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+	var->bits_per_pixel = bpp;
+}
+
+EXPORT_SYMBOL(sbusfb_fill_var);
+
+static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize)
+{
+	if (size == SBUS_MMAP_EMPTY) return 0;
+	if (size >= 0) return size;
+	return fbsize * (-size);
+}
+
+int sbusfb_mmap_helper(struct sbus_mmap_map *map,
+		       unsigned long physbase,
+		       unsigned long fbsize,
+		       unsigned long iospace,
+		       struct vm_area_struct *vma)
+{
+	unsigned int size, page, r, map_size;
+	unsigned long map_offset = 0;
+	unsigned long off;
+	int i;
+                                        
+	if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE)))
+		return -EINVAL;
+
+	size = vma->vm_end - vma->vm_start;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+
+	off = vma->vm_pgoff << PAGE_SHIFT;
+
+	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	/* Each page, see which map applies */
+	for (page = 0; page < size; ){
+		map_size = 0;
+		for (i = 0; map[i].size; i++)
+			if (map[i].voff == off+page) {
+				map_size = sbusfb_mmapsize(map[i].size, fbsize);
+#ifdef __sparc_v9__
+#define POFF_MASK	(PAGE_MASK|0x1UL)
+#else
+#define POFF_MASK	(PAGE_MASK)
+#endif				
+				map_offset = (physbase + map[i].poff) & POFF_MASK;
+				break;
+			}
+		if (!map_size) {
+			page += PAGE_SIZE;
+			continue;
+		}
+		if (page + map_size > size)
+			map_size = size - page;
+		r = io_remap_pfn_range(vma,
+					vma->vm_start + page,
+					MK_IOSPACE_PFN(iospace,
+						map_offset >> PAGE_SHIFT),
+					map_size,
+					vma->vm_page_prot);
+		if (r)
+			return -EAGAIN;
+		page += map_size;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sbusfb_mmap_helper);
+
+int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
+			struct fb_info *info,
+			int type, int fb_depth, unsigned long fb_size)
+{
+	switch(cmd) {
+	case FBIOGTYPE: {
+		struct fbtype __user *f = (struct fbtype __user *) arg;
+
+		if (put_user(type, &f->fb_type) ||
+		    __put_user(info->var.yres, &f->fb_height) ||
+		    __put_user(info->var.xres, &f->fb_width) ||
+		    __put_user(fb_depth, &f->fb_depth) ||
+		    __put_user(0, &f->fb_cmsize) ||
+		    __put_user(fb_size, &f->fb_cmsize))
+			return -EFAULT;
+		return 0;
+	}
+	case FBIOPUTCMAP_SPARC: {
+		struct fbcmap __user *c = (struct fbcmap __user *) arg;
+		struct fb_cmap cmap;
+		u16 red, green, blue;
+		u8 red8, green8, blue8;
+		unsigned char __user *ured;
+		unsigned char __user *ugreen;
+		unsigned char __user *ublue;
+		int index, count, i;
+
+		if (get_user(index, &c->index) ||
+		    __get_user(count, &c->count) ||
+		    __get_user(ured, &c->red) ||
+		    __get_user(ugreen, &c->green) ||
+		    __get_user(ublue, &c->blue))
+			return -EFAULT;
+
+		cmap.len = 1;
+		cmap.red = &red;
+		cmap.green = &green;
+		cmap.blue = &blue;
+		cmap.transp = NULL;
+		for (i = 0; i < count; i++) {
+			int err;
+
+			if (get_user(red8, &ured[i]) ||
+			    get_user(green8, &ugreen[i]) ||
+			    get_user(blue8, &ublue[i]))
+				return -EFAULT;
+
+			red = red8 << 8;
+			green = green8 << 8;
+			blue = blue8 << 8;
+
+			cmap.start = index + i;
+			err = fb_set_cmap(&cmap, info);
+			if (err)
+				return err;
+		}
+		return 0;
+	}
+	case FBIOGETCMAP_SPARC: {
+		struct fbcmap __user *c = (struct fbcmap __user *) arg;
+		unsigned char __user *ured;
+		unsigned char __user *ugreen;
+		unsigned char __user *ublue;
+		struct fb_cmap *cmap = &info->cmap;
+		int index, count, i;
+		u8 red, green, blue;
+
+		if (get_user(index, &c->index) ||
+		    __get_user(count, &c->count) ||
+		    __get_user(ured, &c->red) ||
+		    __get_user(ugreen, &c->green) ||
+		    __get_user(ublue, &c->blue))
+			return -EFAULT;
+
+		if (index + count > cmap->len)
+			return -EINVAL;
+
+		for (i = 0; i < count; i++) {
+			red = cmap->red[index + i] >> 8;
+			green = cmap->green[index + i] >> 8;
+			blue = cmap->blue[index + i] >> 8;
+			if (put_user(red, &ured[i]) ||
+			    put_user(green, &ugreen[i]) ||
+			    put_user(blue, &ublue[i]))
+				return -EFAULT;
+		}
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	}
+}
+EXPORT_SYMBOL(sbusfb_ioctl_helper);
+
+#ifdef CONFIG_COMPAT
+static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	struct fbcmap32 __user *argp = (void __user *)arg;
+	struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p));
+	u32 addr;
+	int ret;
+
+	ret = copy_in_user(p, argp, 2 * sizeof(int));
+	ret |= get_user(addr, &argp->red);
+	ret |= put_user(compat_ptr(addr), &p->red);
+	ret |= get_user(addr, &argp->green);
+	ret |= put_user(compat_ptr(addr), &p->green);
+	ret |= get_user(addr, &argp->blue);
+	ret |= put_user(compat_ptr(addr), &p->blue);
+	if (ret)
+		return -EFAULT;
+	return info->fbops->fb_ioctl(info,
+			(cmd == FBIOPUTCMAP32) ?
+			FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC,
+			(unsigned long)p);
+}
+
+static int fbiogscursor(struct fb_info *info, unsigned long arg)
+{
+	struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
+	struct fbcursor32 __user *argp =  (void __user *)arg;
+	compat_uptr_t addr;
+	int ret;
+
+	ret = copy_in_user(p, argp,
+			      2 * sizeof (short) + 2 * sizeof(struct fbcurpos));
+	ret |= copy_in_user(&p->size, &argp->size, sizeof(struct fbcurpos));
+	ret |= copy_in_user(&p->cmap, &argp->cmap, 2 * sizeof(int));
+	ret |= get_user(addr, &argp->cmap.red);
+	ret |= put_user(compat_ptr(addr), &p->cmap.red);
+	ret |= get_user(addr, &argp->cmap.green);
+	ret |= put_user(compat_ptr(addr), &p->cmap.green);
+	ret |= get_user(addr, &argp->cmap.blue);
+	ret |= put_user(compat_ptr(addr), &p->cmap.blue);
+	ret |= get_user(addr, &argp->mask);
+	ret |= put_user(compat_ptr(addr), &p->mask);
+	ret |= get_user(addr, &argp->image);
+	ret |= put_user(compat_ptr(addr), &p->image);
+	if (ret)
+		return -EFAULT;
+	return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p);
+}
+
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case FBIOGTYPE:
+	case FBIOSATTR:
+	case FBIOGATTR:
+	case FBIOSVIDEO:
+	case FBIOGVIDEO:
+	case FBIOGCURSOR32:	/* This is not implemented yet.
+				   Later it should be converted... */
+	case FBIOSCURPOS:
+	case FBIOGCURPOS:
+	case FBIOGCURMAX:
+		return info->fbops->fb_ioctl(info, cmd, arg);
+	case FBIOPUTCMAP32:
+		return fbiogetputcmap(info, cmd, arg);
+	case FBIOGETCMAP32:
+		return fbiogetputcmap(info, cmd, arg);
+	case FBIOSCURSOR32:
+		return fbiogscursor(info, arg);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+EXPORT_SYMBOL(sbusfb_compat_ioctl);
+#endif
diff --git a/drivers/video/fbdev/sbuslib.h b/drivers/video/fbdev/sbuslib.h
new file mode 100644
index 000000000000..7ba3250236bd
--- /dev/null
+++ b/drivers/video/fbdev/sbuslib.h
@@ -0,0 +1,27 @@
+/* sbuslib.h: SBUS fb helper library interfaces */
+#ifndef _SBUSLIB_H
+#define _SBUSLIB_H
+
+struct sbus_mmap_map {
+	unsigned long voff;
+	unsigned long poff;
+	unsigned long size;
+};
+
+#define SBUS_MMAP_FBSIZE(n) (-n)
+#define SBUS_MMAP_EMPTY	0x80000000
+
+extern void sbusfb_fill_var(struct fb_var_screeninfo *var,
+			    struct device_node *dp, int bpp);
+struct vm_area_struct;
+extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
+			      unsigned long physbase, unsigned long fbsize,
+			      unsigned long iospace,
+			      struct vm_area_struct *vma);
+int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
+			struct fb_info *info,
+			int type, int fb_depth, unsigned long fb_size);
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd,
+			unsigned long arg);
+
+#endif /* _SBUSLIB_H */
diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c
new file mode 100644
index 000000000000..1265b25f9f99
--- /dev/null
+++ b/drivers/video/fbdev/sh7760fb.c
@@ -0,0 +1,591 @@
+/*
+ * SH7760/SH7763 LCDC Framebuffer driver.
+ *
+ * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
+ *             Manuel Lauss <mano@roarinelk.homelinux.net>
+ * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General
+ *  Public License.  See the file COPYING in the main directory of this
+ *  archive for more details.
+ *
+ * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt!
+ *
+ * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de>
+ *     for his original source and testing!
+ *
+ * sh7760_setcolreg get from drivers/video/sh_mobile_lcdcfb.c
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <asm/sh7760fb.h>
+
+struct sh7760fb_par {
+	void __iomem *base;
+	int irq;
+
+	struct sh7760fb_platdata *pd;	/* display information */
+
+	dma_addr_t fbdma;	/* physical address */
+
+	int rot;		/* rotation enabled? */
+
+	u32 pseudo_palette[16];
+
+	struct platform_device *dev;
+	struct resource *ioarea;
+	struct completion vsync;	/* vsync irq event */
+};
+
+static irqreturn_t sh7760fb_irq(int irq, void *data)
+{
+	struct completion *c = data;
+
+	complete(c);
+
+	return IRQ_HANDLED;
+}
+
+/* wait_for_lps - wait until power supply has reached a certain state. */
+static int wait_for_lps(struct sh7760fb_par *par, int val)
+{
+	int i = 100;
+	while (--i && ((ioread16(par->base + LDPMMR) & 3) != val))
+		msleep(1);
+
+	if (i <= 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/* en/disable the LCDC */
+static int sh7760fb_blank(int blank, struct fb_info *info)
+{
+	struct sh7760fb_par *par = info->par;
+	struct sh7760fb_platdata *pd = par->pd;
+	unsigned short cntr = ioread16(par->base + LDCNTR);
+	unsigned short intr = ioread16(par->base + LDINTR);
+	int lps;
+
+	if (blank == FB_BLANK_UNBLANK) {
+		intr |= VINT_START;
+		cntr = LDCNTR_DON2 | LDCNTR_DON;
+		lps = 3;
+	} else {
+		intr &= ~VINT_START;
+		cntr = LDCNTR_DON2;
+		lps = 0;
+	}
+
+	if (pd->blank)
+		pd->blank(blank);
+
+	iowrite16(intr, par->base + LDINTR);
+	iowrite16(cntr, par->base + LDCNTR);
+
+	return wait_for_lps(par, lps);
+}
+
+static int sh7760_setcolreg (u_int regno,
+	u_int red, u_int green, u_int blue,
+	u_int transp, struct fb_info *info)
+{
+	u32 *palette = info->pseudo_palette;
+
+	if (regno >= 16)
+		return -EINVAL;
+
+	/* only FB_VISUAL_TRUECOLOR supported */
+
+	red >>= 16 - info->var.red.length;
+	green >>= 16 - info->var.green.length;
+	blue >>= 16 - info->var.blue.length;
+	transp >>= 16 - info->var.transp.length;
+
+	palette[regno] = (red << info->var.red.offset) |
+		(green << info->var.green.offset) |
+		(blue << info->var.blue.offset) |
+		(transp << info->var.transp.offset);
+
+	return 0;
+}
+
+static int sh7760fb_get_color_info(struct device *dev,
+				   u16 lddfr, int *bpp, int *gray)
+{
+	int lbpp, lgray;
+
+	lgray = lbpp = 0;
+
+	switch (lddfr & LDDFR_COLOR_MASK) {
+	case LDDFR_1BPP_MONO:
+		lgray = 1;
+		lbpp = 1;
+		break;
+	case LDDFR_2BPP_MONO:
+		lgray = 1;
+		lbpp = 2;
+		break;
+	case LDDFR_4BPP_MONO:
+		lgray = 1;
+	case LDDFR_4BPP:
+		lbpp = 4;
+		break;
+	case LDDFR_6BPP_MONO:
+		lgray = 1;
+	case LDDFR_8BPP:
+		lbpp = 8;
+		break;
+	case LDDFR_16BPP_RGB555:
+	case LDDFR_16BPP_RGB565:
+		lbpp = 16;
+		lgray = 0;
+		break;
+	default:
+		dev_dbg(dev, "unsupported LDDFR bit depth.\n");
+		return -EINVAL;
+	}
+
+	if (bpp)
+		*bpp = lbpp;
+	if (gray)
+		*gray = lgray;
+
+	return 0;
+}
+
+static int sh7760fb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct fb_fix_screeninfo *fix = &info->fix;
+	struct sh7760fb_par *par = info->par;
+	int ret, bpp;
+
+	/* get color info from register value */
+	ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+	if (ret)
+		return ret;
+
+	var->bits_per_pixel = bpp;
+
+	if ((var->grayscale) && (var->bits_per_pixel == 1))
+		fix->visual = FB_VISUAL_MONO10;
+	else if (var->bits_per_pixel >= 15)
+		fix->visual = FB_VISUAL_TRUECOLOR;
+	else
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+
+	/* TODO: add some more validation here */
+	return 0;
+}
+
+/*
+ * sh7760fb_set_par - set videomode.
+ *
+ * NOTE: The rotation, grayscale and DSTN codepaths are
+ *     totally untested!
+ */
+static int sh7760fb_set_par(struct fb_info *info)
+{
+	struct sh7760fb_par *par = info->par;
+	struct fb_videomode *vm = par->pd->def_mode;
+	unsigned long sbase, dstn_off, ldsarl, stride;
+	unsigned short hsynp, hsynw, htcn, hdcn;
+	unsigned short vsynp, vsynw, vtln, vdln;
+	unsigned short lddfr, ldmtr;
+	int ret, bpp, gray;
+
+	par->rot = par->pd->rotate;
+
+	/* rotate only works with xres <= 320 */
+	if (par->rot && (vm->xres > 320)) {
+		dev_dbg(info->dev, "rotation disabled due to display size\n");
+		par->rot = 0;
+	}
+
+	/* calculate LCDC reg vals from display parameters */
+	hsynp = vm->right_margin + vm->xres;
+	hsynw = vm->hsync_len;
+	htcn = vm->left_margin + hsynp + hsynw;
+	hdcn = vm->xres;
+	vsynp = vm->lower_margin + vm->yres;
+	vsynw = vm->vsync_len;
+	vtln = vm->upper_margin + vsynp + vsynw;
+	vdln = vm->yres;
+
+	/* get color info from register value */
+	ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, &gray);
+	if (ret)
+		return ret;
+
+	dev_dbg(info->dev, "%dx%d %dbpp %s (orientation %s)\n", hdcn,
+		vdln, bpp, gray ? "grayscale" : "color",
+		par->rot ? "rotated" : "normal");
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	lddfr = par->pd->lddfr | (1 << 8);
+#else
+	lddfr = par->pd->lddfr & ~(1 << 8);
+#endif
+
+	ldmtr = par->pd->ldmtr;
+
+	if (!(vm->sync & FB_SYNC_HOR_HIGH_ACT))
+		ldmtr |= LDMTR_CL1POL;
+	if (!(vm->sync & FB_SYNC_VERT_HIGH_ACT))
+		ldmtr |= LDMTR_FLMPOL;
+
+	/* shut down LCDC before changing display parameters */
+	sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+
+	iowrite16(par->pd->ldickr, par->base + LDICKR);	/* pixclock */
+	iowrite16(ldmtr, par->base + LDMTR);	/* polarities */
+	iowrite16(lddfr, par->base + LDDFR);	/* color/depth */
+	iowrite16((par->rot ? 1 << 13 : 0), par->base + LDSMR);	/* rotate */
+	iowrite16(par->pd->ldpmmr, par->base + LDPMMR);	/* Power Management */
+	iowrite16(par->pd->ldpspr, par->base + LDPSPR);	/* Power Supply Ctrl */
+
+	/* display resolution */
+	iowrite16(((htcn >> 3) - 1) | (((hdcn >> 3) - 1) << 8),
+		  par->base + LDHCNR);
+	iowrite16(vdln - 1, par->base + LDVDLNR);
+	iowrite16(vtln - 1, par->base + LDVTLNR);
+	/* h/v sync signals */
+	iowrite16((vsynp - 1) | ((vsynw - 1) << 12), par->base + LDVSYNR);
+	iowrite16(((hsynp >> 3) - 1) | (((hsynw >> 3) - 1) << 12),
+		  par->base + LDHSYNR);
+	/* AC modulation sig */
+	iowrite16(par->pd->ldaclnr, par->base + LDACLNR);
+
+	stride = (par->rot) ? vtln : hdcn;
+	if (!gray)
+		stride *= (bpp + 7) >> 3;
+	else {
+		if (bpp == 1)
+			stride >>= 3;
+		else if (bpp == 2)
+			stride >>= 2;
+		else if (bpp == 4)
+			stride >>= 1;
+		/* 6 bpp == 8 bpp */
+	}
+
+	/* if rotated, stride must be power of 2 */
+	if (par->rot) {
+		unsigned long bit = 1 << 31;
+		while (bit) {
+			if (stride & bit)
+				break;
+			bit >>= 1;
+		}
+		if (stride & ~bit)
+			stride = bit << 1;	/* not P-o-2, round up */
+	}
+	iowrite16(stride, par->base + LDLAOR);
+
+	/* set display mem start address */
+	sbase = (unsigned long)par->fbdma;
+	if (par->rot)
+		sbase += (hdcn - 1) * stride;
+
+	iowrite32(sbase, par->base + LDSARU);
+
+	/*
+	 * for DSTN need to set address for lower half.
+	 * I (mlau) don't know which address to set it to,
+	 * so I guessed at (stride * yres/2).
+	 */
+	if (((ldmtr & 0x003f) >= LDMTR_DSTN_MONO_8) &&
+	    ((ldmtr & 0x003f) <= LDMTR_DSTN_COLOR_16)) {
+
+		dev_dbg(info->dev, " ***** DSTN untested! *****\n");
+
+		dstn_off = stride;
+		if (par->rot)
+			dstn_off *= hdcn >> 1;
+		else
+			dstn_off *= vdln >> 1;
+
+		ldsarl = sbase + dstn_off;
+	} else
+		ldsarl = 0;
+
+	iowrite32(ldsarl, par->base + LDSARL);	/* mem for lower half of DSTN */
+
+	info->fix.line_length = stride;
+
+	sh7760fb_check_var(&info->var, info);
+
+	sh7760fb_blank(FB_BLANK_UNBLANK, info);	/* panel on! */
+
+	dev_dbg(info->dev, "hdcn  : %6d htcn  : %6d\n", hdcn, htcn);
+	dev_dbg(info->dev, "hsynw : %6d hsynp : %6d\n", hsynw, hsynp);
+	dev_dbg(info->dev, "vdln  : %6d vtln  : %6d\n", vdln, vtln);
+	dev_dbg(info->dev, "vsynw : %6d vsynp : %6d\n", vsynw, vsynp);
+	dev_dbg(info->dev, "clksrc: %6d clkdiv: %6d\n",
+		(par->pd->ldickr >> 12) & 3, par->pd->ldickr & 0x1f);
+	dev_dbg(info->dev, "ldpmmr: 0x%04x ldpspr: 0x%04x\n", par->pd->ldpmmr,
+		par->pd->ldpspr);
+	dev_dbg(info->dev, "ldmtr : 0x%04x lddfr : 0x%04x\n", ldmtr, lddfr);
+	dev_dbg(info->dev, "ldlaor: %ld\n", stride);
+	dev_dbg(info->dev, "ldsaru: 0x%08lx ldsarl: 0x%08lx\n", sbase, ldsarl);
+
+	return 0;
+}
+
+static struct fb_ops sh7760fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_blank = sh7760fb_blank,
+	.fb_check_var = sh7760fb_check_var,
+	.fb_setcolreg = sh7760_setcolreg,
+	.fb_set_par = sh7760fb_set_par,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+};
+
+static void sh7760fb_free_mem(struct fb_info *info)
+{
+	struct sh7760fb_par *par = info->par;
+
+	if (!info->screen_base)
+		return;
+
+	dma_free_coherent(info->dev, info->screen_size,
+			  info->screen_base, par->fbdma);
+
+	par->fbdma = 0;
+	info->screen_base = NULL;
+	info->screen_size = 0;
+}
+
+/* allocate the framebuffer memory. This memory must be in Area3,
+ * (dictated by the DMA engine) and contiguous, at a 512 byte boundary.
+ */
+static int sh7760fb_alloc_mem(struct fb_info *info)
+{
+	struct sh7760fb_par *par = info->par;
+	void *fbmem;
+	unsigned long vram;
+	int ret, bpp;
+
+	if (info->screen_base)
+		return 0;
+
+	/* get color info from register value */
+	ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+	if (ret) {
+		printk(KERN_ERR "colinfo\n");
+		return ret;
+	}
+
+	/* min VRAM: xres_min = 16, yres_min = 1, bpp = 1: 2byte -> 1 page
+	   max VRAM: xres_max = 1024, yres_max = 1024, bpp = 16: 2MB */
+
+	vram = info->var.xres * info->var.yres;
+	if (info->var.grayscale) {
+		if (bpp == 1)
+			vram >>= 3;
+		else if (bpp == 2)
+			vram >>= 2;
+		else if (bpp == 4)
+			vram >>= 1;
+	} else if (bpp > 8)
+		vram *= 2;
+	if ((vram < 1) || (vram > 1024 * 2048)) {
+		dev_dbg(info->dev, "too much VRAM required. Check settings\n");
+		return -ENODEV;
+	}
+
+	if (vram < PAGE_SIZE)
+		vram = PAGE_SIZE;
+
+	fbmem = dma_alloc_coherent(info->dev, vram, &par->fbdma, GFP_KERNEL);
+
+	if (!fbmem)
+		return -ENOMEM;
+
+	if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) {
+		sh7760fb_free_mem(info);
+		dev_err(info->dev, "kernel gave me memory at 0x%08lx, which is"
+			"unusable for the LCDC\n", (unsigned long)par->fbdma);
+		return -ENOMEM;
+	}
+
+	info->screen_base = fbmem;
+	info->screen_size = vram;
+	info->fix.smem_start = (unsigned long)info->screen_base;
+	info->fix.smem_len = info->screen_size;
+
+	return 0;
+}
+
+static int sh7760fb_probe(struct platform_device *pdev)
+{
+	struct fb_info *info;
+	struct resource *res;
+	struct sh7760fb_par *par;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(res == NULL)) {
+		dev_err(&pdev->dev, "invalid resource\n");
+		return -EINVAL;
+	}
+
+	info = framebuffer_alloc(sizeof(struct sh7760fb_par), &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	par = info->par;
+	par->dev = pdev;
+
+	par->pd = pdev->dev.platform_data;
+	if (!par->pd) {
+		dev_dbg(info->dev, "no display setup data!\n");
+		ret = -ENODEV;
+		goto out_fb;
+	}
+
+	par->ioarea = request_mem_region(res->start,
+					 resource_size(res), pdev->name);
+	if (!par->ioarea) {
+		dev_err(&pdev->dev, "mmio area busy\n");
+		ret = -EBUSY;
+		goto out_fb;
+	}
+
+	par->base = ioremap_nocache(res->start, resource_size(res));
+	if (!par->base) {
+		dev_err(&pdev->dev, "cannot remap\n");
+		ret = -ENODEV;
+		goto out_res;
+	}
+
+	iowrite16(0, par->base + LDINTR);	/* disable vsync irq */
+	par->irq = platform_get_irq(pdev, 0);
+	if (par->irq >= 0) {
+		ret = request_irq(par->irq, sh7760fb_irq, 0,
+				  "sh7760-lcdc", &par->vsync);
+		if (ret) {
+			dev_err(&pdev->dev, "cannot grab IRQ\n");
+			par->irq = -ENXIO;
+		} else
+			disable_irq_nosync(par->irq);
+	}
+
+	fb_videomode_to_var(&info->var, par->pd->def_mode);
+
+	ret = sh7760fb_alloc_mem(info);
+	if (ret) {
+		dev_dbg(info->dev, "framebuffer memory allocation failed!\n");
+		goto out_unmap;
+	}
+
+	info->pseudo_palette = par->pseudo_palette;
+
+	/* fixup color register bitpositions. These are fixed by hardware */
+	info->var.red.offset = 11;
+	info->var.red.length = 5;
+	info->var.red.msb_right = 0;
+
+	info->var.green.offset = 5;
+	info->var.green.length = 6;
+	info->var.green.msb_right = 0;
+
+	info->var.blue.offset = 0;
+	info->var.blue.length = 5;
+	info->var.blue.msb_right = 0;
+
+	info->var.transp.offset = 0;
+	info->var.transp.length = 0;
+	info->var.transp.msb_right = 0;
+
+	strcpy(info->fix.id, "sh7760-lcdc");
+
+	/* set the DON2 bit now, before cmap allocation, as it will randomize
+	 * palette memory.
+	 */
+	iowrite16(LDCNTR_DON2, par->base + LDCNTR);
+	info->fbops = &sh7760fb_ops;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		dev_dbg(info->dev, "Unable to allocate cmap memory\n");
+		goto out_mem;
+	}
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_dbg(info->dev, "cannot register fb!\n");
+		goto out_cmap;
+	}
+	platform_set_drvdata(pdev, info);
+
+	printk(KERN_INFO "%s: memory at phys 0x%08lx-0x%08lx, size %ld KiB\n",
+	       pdev->name,
+	       (unsigned long)par->fbdma,
+	       (unsigned long)(par->fbdma + info->screen_size - 1),
+	       info->screen_size >> 10);
+
+	return 0;
+
+out_cmap:
+	sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+	fb_dealloc_cmap(&info->cmap);
+out_mem:
+	sh7760fb_free_mem(info);
+out_unmap:
+	if (par->irq >= 0)
+		free_irq(par->irq, &par->vsync);
+	iounmap(par->base);
+out_res:
+	release_mem_region(res->start, resource_size(res));
+out_fb:
+	framebuffer_release(info);
+	return ret;
+}
+
+static int sh7760fb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct sh7760fb_par *par = info->par;
+
+	sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+	sh7760fb_free_mem(info);
+	if (par->irq >= 0)
+		free_irq(par->irq, &par->vsync);
+	iounmap(par->base);
+	release_mem_region(par->ioarea->start, resource_size(par->ioarea));
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver sh7760_lcdc_driver = {
+	.driver = {
+		   .name = "sh7760-lcdc",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = sh7760fb_probe,
+	.remove = sh7760fb_remove,
+};
+
+module_platform_driver(sh7760_lcdc_driver);
+
+MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
+MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/sh_mipi_dsi.c b/drivers/video/fbdev/sh_mipi_dsi.c
new file mode 100644
index 000000000000..8f6e8ff620d4
--- /dev/null
+++ b/drivers/video/fbdev/sh_mipi_dsi.c
@@ -0,0 +1,587 @@
+/*
+ * Renesas SH-mobile MIPI DSI support
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/module.h>
+
+#include <video/mipi_display.h>
+#include <video/sh_mipi_dsi.h>
+#include <video/sh_mobile_lcdc.h>
+
+#include "sh_mobile_lcdcfb.h"
+
+#define SYSCTRL		0x0000
+#define SYSCONF		0x0004
+#define TIMSET		0x0008
+#define RESREQSET0	0x0018
+#define RESREQSET1	0x001c
+#define HSTTOVSET	0x0020
+#define LPRTOVSET	0x0024
+#define TATOVSET	0x0028
+#define PRTOVSET	0x002c
+#define DSICTRL		0x0030
+#define DSIINTE		0x0060
+#define PHYCTRL		0x0070
+
+/* relative to linkbase */
+#define DTCTR		0x0000
+#define VMCTR1		0x0020
+#define VMCTR2		0x0024
+#define VMLEN1		0x0028
+#define VMLEN2		0x002c
+#define CMTSRTREQ	0x0070
+#define CMTSRTCTR	0x00d0
+
+/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
+#define MAX_SH_MIPI_DSI 2
+
+struct sh_mipi {
+	struct sh_mobile_lcdc_entity entity;
+
+	void __iomem	*base;
+	void __iomem	*linkbase;
+	struct clk	*dsit_clk;
+	struct platform_device *pdev;
+};
+
+#define to_sh_mipi(e)	container_of(e, struct sh_mipi, entity)
+
+static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
+
+/* Protect the above array */
+static DEFINE_MUTEX(array_lock);
+
+static struct sh_mipi *sh_mipi_by_handle(int handle)
+{
+	if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0)
+		return NULL;
+
+	return mipi_dsi[handle];
+}
+
+static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
+			      u8 cmd, u8 param)
+{
+	u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8);
+	int cnt = 100;
+
+	/* transmit a short packet to LCD panel */
+	iowrite32(1 | data, mipi->linkbase + CMTSRTCTR);
+	iowrite32(1, mipi->linkbase + CMTSRTREQ);
+
+	while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt)
+		udelay(1);
+
+	return cnt ? 0 : -ETIMEDOUT;
+}
+
+#define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
+				-EINVAL : (c) - 1)
+
+static int sh_mipi_dcs(int handle, u8 cmd)
+{
+	struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
+	if (!mipi)
+		return -ENODEV;
+	return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
+}
+
+static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
+{
+	struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
+	if (!mipi)
+		return -ENODEV;
+	return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd,
+				  param);
+}
+
+static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
+{
+	/*
+	 * enable LCDC data tx, transition to LPS after completion of each HS
+	 * packet
+	 */
+	iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR);
+}
+
+static void sh_mipi_shutdown(struct platform_device *pdev)
+{
+	struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
+
+	sh_mipi_dsi_enable(mipi, false);
+}
+
+static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode)
+{
+	void __iomem *base = mipi->base;
+	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
+	u32 pctype, datatype, pixfmt, linelength, vmctr2;
+	u32 tmp, top, bottom, delay, div;
+	int bpp;
+
+	/*
+	 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
+	 * the default videomode. If this ever becomes a problem, We'll have to
+	 * move this to mipi_display_on() above and use info->var.xres
+	 */
+	switch (pdata->data_format) {
+	case MIPI_RGB888:
+		pctype = 0;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
+		linelength = mode->xres * 3;
+		break;
+	case MIPI_RGB565:
+		pctype = 1;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
+		linelength = mode->xres * 2;
+		break;
+	case MIPI_RGB666_LP:
+		pctype = 2;
+		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
+		linelength = mode->xres * 3;
+		break;
+	case MIPI_RGB666:
+		pctype = 3;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
+		linelength = (mode->xres * 18 + 7) / 8;
+		break;
+	case MIPI_BGR888:
+		pctype = 8;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
+		linelength = mode->xres * 3;
+		break;
+	case MIPI_BGR565:
+		pctype = 9;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
+		linelength = mode->xres * 2;
+		break;
+	case MIPI_BGR666_LP:
+		pctype = 0xa;
+		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
+		linelength = mode->xres * 3;
+		break;
+	case MIPI_BGR666:
+		pctype = 0xb;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
+		linelength = (mode->xres * 18 + 7) / 8;
+		break;
+	case MIPI_YUYV:
+		pctype = 4;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
+		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
+		linelength = mode->xres * 2;
+		break;
+	case MIPI_UYVY:
+		pctype = 5;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
+		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
+		linelength = mode->xres * 2;
+		break;
+	case MIPI_YUV420_L:
+		pctype = 6;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
+		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
+		linelength = (mode->xres * 12 + 7) / 8;
+		break;
+	case MIPI_YUV420:
+		pctype = 7;
+		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
+		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
+		/* Length of U/V line */
+		linelength = (mode->xres + 1) / 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (!pdata->lane)
+		return -EINVAL;
+
+	/* reset DSI link */
+	iowrite32(0x00000001, base + SYSCTRL);
+	/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
+	udelay(50);
+	iowrite32(0x00000000, base + SYSCTRL);
+
+	/* setup DSI link */
+
+	/*
+	 * T_wakeup = 0x7000
+	 * T_hs-trail = 3
+	 * T_hs-prepare = 3
+	 * T_clk-trail = 3
+	 * T_clk-prepare = 2
+	 */
+	iowrite32(0x70003332, base + TIMSET);
+	/* no responses requested */
+	iowrite32(0x00000000, base + RESREQSET0);
+	/* request response to packets of type 0x28 */
+	iowrite32(0x00000100, base + RESREQSET1);
+	/* High-speed transmission timeout, default 0xffffffff */
+	iowrite32(0x0fffffff, base + HSTTOVSET);
+	/* LP reception timeout, default 0xffffffff */
+	iowrite32(0x0fffffff, base + LPRTOVSET);
+	/* Turn-around timeout, default 0xffffffff */
+	iowrite32(0x0fffffff, base + TATOVSET);
+	/* Peripheral reset timeout, default 0xffffffff */
+	iowrite32(0x0fffffff, base + PRTOVSET);
+	/* Interrupts not used, disable all */
+	iowrite32(0, base + DSIINTE);
+	/* DSI-Tx bias on */
+	iowrite32(0x00000001, base + PHYCTRL);
+	udelay(200);
+	/* Deassert resets, power on */
+	iowrite32(0x03070001 | pdata->phyctrl, base + PHYCTRL);
+
+	/*
+	 * Default = ULPS enable |
+	 *	Contention detection enabled |
+	 *	EoT packet transmission enable |
+	 *	CRC check enable |
+	 *	ECC check enable
+	 */
+	bitmap_fill((unsigned long *)&tmp, pdata->lane);
+	tmp |= 0x00003700;
+	iowrite32(tmp, base + SYSCONF);
+
+	/* setup l-bridge */
+
+	/*
+	 * Enable transmission of all packets,
+	 * transmit LPS after each HS packet completion
+	 */
+	iowrite32(0x00000006, mipi->linkbase + DTCTR);
+	/* VSYNC width = 2 (<< 17) */
+	iowrite32((mode->vsync_len << pdata->vsynw_offset) |
+		  (pdata->clksrc << 16) | (pctype << 12) | datatype,
+		  mipi->linkbase + VMCTR1);
+
+	/*
+	 * Non-burst mode with sync pulses: VSE and HSE are output,
+	 * HSA period allowed, no commands in LP
+	 */
+	vmctr2 = 0;
+	if (pdata->flags & SH_MIPI_DSI_VSEE)
+		vmctr2 |= 1 << 23;
+	if (pdata->flags & SH_MIPI_DSI_HSEE)
+		vmctr2 |= 1 << 22;
+	if (pdata->flags & SH_MIPI_DSI_HSAE)
+		vmctr2 |= 1 << 21;
+	if (pdata->flags & SH_MIPI_DSI_BL2E)
+		vmctr2 |= 1 << 17;
+	if (pdata->flags & SH_MIPI_DSI_HSABM)
+		vmctr2 |= 1 << 5;
+	if (pdata->flags & SH_MIPI_DSI_HBPBM)
+		vmctr2 |= 1 << 4;
+	if (pdata->flags & SH_MIPI_DSI_HFPBM)
+		vmctr2 |= 1 << 3;
+	iowrite32(vmctr2, mipi->linkbase + VMCTR2);
+
+	/*
+	 * VMLEN1 = RGBLEN | HSALEN
+	 *
+	 * see
+	 *  Video mode - Blanking Packet setting
+	 */
+	top = linelength << 16; /* RGBLEN */
+	bottom = 0x00000001;
+	if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
+		bottom = (pdata->lane * mode->hsync_len) - 10;
+	iowrite32(top | bottom , mipi->linkbase + VMLEN1);
+
+	/*
+	 * VMLEN2 = HBPLEN | HFPLEN
+	 *
+	 * see
+	 *  Video mode - Blanking Packet setting
+	 */
+	top	= 0x00010000;
+	bottom	= 0x00000001;
+	delay	= 0;
+
+	div = 1;	/* HSbyteCLK is calculation base
+			 * HS4divCLK = HSbyteCLK/2
+			 * HS6divCLK is not supported for now */
+	if (pdata->flags & SH_MIPI_DSI_HS4divCLK)
+		div = 2;
+
+	if (pdata->flags & SH_MIPI_DSI_HFPBM) {	/* HBPLEN */
+		top = mode->hsync_len + mode->left_margin;
+		top = ((pdata->lane * top / div) - 10) << 16;
+	}
+	if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
+		bottom = mode->right_margin;
+		bottom = (pdata->lane * bottom / div) - 12;
+	}
+
+	bpp = linelength / mode->xres; /* byte / pixel */
+	if ((pdata->lane / div) > bpp) {
+		tmp = mode->xres / bpp; /* output cycle */
+		tmp = mode->xres - tmp; /* (input - output) cycle */
+		delay = (pdata->lane * tmp);
+	}
+
+	iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2);
+
+	msleep(5);
+
+	/* setup LCD panel */
+
+	/* cf. drivers/video/omap/lcd_mipid.c */
+	sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE);
+	msleep(120);
+	/*
+	 * [7] - Page Address Mode
+	 * [6] - Column Address Mode
+	 * [5] - Page / Column Address Mode
+	 * [4] - Display Device Line Refresh Order
+	 * [3] - RGB/BGR Order
+	 * [2] - Display Data Latch Data Order
+	 * [1] - Flip Horizontal
+	 * [0] - Flip Vertical
+	 */
+	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+	/* cf. set_data_lines() */
+	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT,
+			  pixfmt << 4);
+	sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON);
+
+	/* Enable timeout counters */
+	iowrite32(0x00000f00, base + DSICTRL);
+
+	return 0;
+}
+
+static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
+{
+	struct sh_mipi *mipi = to_sh_mipi(entity);
+	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
+	int ret;
+
+	pm_runtime_get_sync(&mipi->pdev->dev);
+
+	ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1);
+	if (ret < 0)
+		goto mipi_display_on_fail1;
+
+	ret = sh_mipi_setup(mipi, &entity->def_mode);
+	if (ret < 0)
+		goto mipi_display_on_fail2;
+
+	sh_mipi_dsi_enable(mipi, true);
+
+	return SH_MOBILE_LCDC_DISPLAY_CONNECTED;
+
+mipi_display_on_fail1:
+	pm_runtime_put_sync(&mipi->pdev->dev);
+mipi_display_on_fail2:
+	pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
+
+	return ret;
+}
+
+static void mipi_display_off(struct sh_mobile_lcdc_entity *entity)
+{
+	struct sh_mipi *mipi = to_sh_mipi(entity);
+	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
+
+	sh_mipi_dsi_enable(mipi, false);
+
+	pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
+
+	pm_runtime_put_sync(&mipi->pdev->dev);
+}
+
+static const struct sh_mobile_lcdc_entity_ops mipi_ops = {
+	.display_on = mipi_display_on,
+	.display_off = mipi_display_off,
+};
+
+static int __init sh_mipi_probe(struct platform_device *pdev)
+{
+	struct sh_mipi *mipi;
+	struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	unsigned long rate, f_current;
+	int idx = pdev->id, ret;
+
+	if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
+		return -ENODEV;
+
+	if (!pdata->set_dot_clock)
+		return -EINVAL;
+
+	mutex_lock(&array_lock);
+	if (idx < 0)
+		for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
+			;
+
+	if (idx == ARRAY_SIZE(mipi_dsi)) {
+		ret = -EBUSY;
+		goto efindslot;
+	}
+
+	mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
+	if (!mipi) {
+		ret = -ENOMEM;
+		goto ealloc;
+	}
+
+	mipi->entity.owner = THIS_MODULE;
+	mipi->entity.ops = &mipi_ops;
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "MIPI register region already claimed\n");
+		ret = -EBUSY;
+		goto ereqreg;
+	}
+
+	mipi->base = ioremap(res->start, resource_size(res));
+	if (!mipi->base) {
+		ret = -ENOMEM;
+		goto emap;
+	}
+
+	if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) {
+		dev_err(&pdev->dev, "MIPI register region 2 already claimed\n");
+		ret = -EBUSY;
+		goto ereqreg2;
+	}
+
+	mipi->linkbase = ioremap(res2->start, resource_size(res2));
+	if (!mipi->linkbase) {
+		ret = -ENOMEM;
+		goto emap2;
+	}
+
+	mipi->pdev = pdev;
+
+	mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
+	if (IS_ERR(mipi->dsit_clk)) {
+		ret = PTR_ERR(mipi->dsit_clk);
+		goto eclktget;
+	}
+
+	f_current = clk_get_rate(mipi->dsit_clk);
+	/* 80MHz required by the datasheet */
+	rate = clk_round_rate(mipi->dsit_clk, 80000000);
+	if (rate > 0 && rate != f_current)
+		ret = clk_set_rate(mipi->dsit_clk, rate);
+	else
+		ret = rate;
+	if (ret < 0)
+		goto esettrate;
+
+	dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
+
+	ret = clk_enable(mipi->dsit_clk);
+	if (ret < 0)
+		goto eclkton;
+
+	mipi_dsi[idx] = mipi;
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_resume(&pdev->dev);
+
+	mutex_unlock(&array_lock);
+	platform_set_drvdata(pdev, &mipi->entity);
+
+	return 0;
+
+eclkton:
+esettrate:
+	clk_put(mipi->dsit_clk);
+eclktget:
+	iounmap(mipi->linkbase);
+emap2:
+	release_mem_region(res2->start, resource_size(res2));
+ereqreg2:
+	iounmap(mipi->base);
+emap:
+	release_mem_region(res->start, resource_size(res));
+ereqreg:
+	kfree(mipi);
+ealloc:
+efindslot:
+	mutex_unlock(&array_lock);
+
+	return ret;
+}
+
+static int sh_mipi_remove(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
+	int i, ret;
+
+	mutex_lock(&array_lock);
+
+	for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++)
+		;
+
+	if (i == ARRAY_SIZE(mipi_dsi)) {
+		ret = -EINVAL;
+	} else {
+		ret = 0;
+		mipi_dsi[i] = NULL;
+	}
+
+	mutex_unlock(&array_lock);
+
+	if (ret < 0)
+		return ret;
+
+	pm_runtime_disable(&pdev->dev);
+	clk_disable(mipi->dsit_clk);
+	clk_put(mipi->dsit_clk);
+
+	iounmap(mipi->linkbase);
+	if (res2)
+		release_mem_region(res2->start, resource_size(res2));
+	iounmap(mipi->base);
+	if (res)
+		release_mem_region(res->start, resource_size(res));
+	kfree(mipi);
+
+	return 0;
+}
+
+static struct platform_driver sh_mipi_driver = {
+	.remove		= sh_mipi_remove,
+	.shutdown	= sh_mipi_shutdown,
+	.driver = {
+		.name	= "sh-mipi-dsi",
+	},
+};
+
+module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/sh_mobile_hdmi.c b/drivers/video/fbdev/sh_mobile_hdmi.c
new file mode 100644
index 000000000000..9a33ee0413fb
--- /dev/null
+++ b/drivers/video/fbdev/sh_mobile_hdmi.c
@@ -0,0 +1,1449 @@
+/*
+ * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
+ * for SLISHDMI13T and SLIPHDMIT IP cores
+ *
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include <video/sh_mobile_hdmi.h>
+#include <video/sh_mobile_lcdc.h>
+
+#include "sh_mobile_lcdcfb.h"
+
+/* HDMI Core Control Register (HTOP0) */
+#define HDMI_SYSTEM_CTRL			0x00 /* System control */
+#define HDMI_L_R_DATA_SWAP_CTRL_RPKT		0x01 /* L/R data swap control,
+							bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
+#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8	0x02 /* bits 15..8 of 20-bit N for Audio Clock Regeneration packet */
+#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0	0x03 /* bits 7..0 of 20-bit N for Audio Clock Regeneration packet */
+#define HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS		0x04 /* SPDIF audio sampling frequency,
+							bits 19..16 of Internal CTS */
+#define HDMI_INTERNAL_CTS_15_8			0x05 /* bits 15..8 of Internal CTS */
+#define HDMI_INTERNAL_CTS_7_0			0x06 /* bits 7..0 of Internal CTS */
+#define HDMI_EXTERNAL_CTS_19_16			0x07 /* External CTS */
+#define HDMI_EXTERNAL_CTS_15_8			0x08 /* External CTS */
+#define HDMI_EXTERNAL_CTS_7_0			0x09 /* External CTS */
+#define HDMI_AUDIO_SETTING_1			0x0A /* Audio setting.1 */
+#define HDMI_AUDIO_SETTING_2			0x0B /* Audio setting.2 */
+#define HDMI_I2S_AUDIO_SET			0x0C /* I2S audio setting */
+#define HDMI_DSD_AUDIO_SET			0x0D /* DSD audio setting */
+#define HDMI_DEBUG_MONITOR_1			0x0E /* Debug monitor.1 */
+#define HDMI_DEBUG_MONITOR_2			0x0F /* Debug monitor.2 */
+#define HDMI_I2S_INPUT_PIN_SWAP			0x10 /* I2S input pin swap */
+#define HDMI_AUDIO_STATUS_BITS_SETTING_1	0x11 /* Audio status bits setting.1 */
+#define HDMI_AUDIO_STATUS_BITS_SETTING_2	0x12 /* Audio status bits setting.2 */
+#define HDMI_CATEGORY_CODE			0x13 /* Category code */
+#define HDMI_SOURCE_NUM_AUDIO_WORD_LEN		0x14 /* Source number/Audio word length */
+#define HDMI_AUDIO_VIDEO_SETTING_1		0x15 /* Audio/Video setting.1 */
+#define HDMI_VIDEO_SETTING_1			0x16 /* Video setting.1 */
+#define HDMI_DEEP_COLOR_MODES			0x17 /* Deep Color Modes */
+
+/* 12 16- and 10-bit Color space conversion parameters: 0x18..0x2f */
+#define HDMI_COLOR_SPACE_CONVERSION_PARAMETERS	0x18
+
+#define HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS	0x30 /* External video parameter settings */
+#define HDMI_EXTERNAL_H_TOTAL_7_0		0x31 /* External horizontal total (LSB) */
+#define HDMI_EXTERNAL_H_TOTAL_11_8		0x32 /* External horizontal total (MSB) */
+#define HDMI_EXTERNAL_H_BLANK_7_0		0x33 /* External horizontal blank (LSB) */
+#define HDMI_EXTERNAL_H_BLANK_9_8		0x34 /* External horizontal blank (MSB) */
+#define HDMI_EXTERNAL_H_DELAY_7_0		0x35 /* External horizontal delay (LSB) */
+#define HDMI_EXTERNAL_H_DELAY_9_8		0x36 /* External horizontal delay (MSB) */
+#define HDMI_EXTERNAL_H_DURATION_7_0		0x37 /* External horizontal duration (LSB) */
+#define HDMI_EXTERNAL_H_DURATION_9_8		0x38 /* External horizontal duration (MSB) */
+#define HDMI_EXTERNAL_V_TOTAL_7_0		0x39 /* External vertical total (LSB) */
+#define HDMI_EXTERNAL_V_TOTAL_9_8		0x3A /* External vertical total (MSB) */
+#define HDMI_AUDIO_VIDEO_SETTING_2		0x3B /* Audio/Video setting.2 */
+#define HDMI_EXTERNAL_V_BLANK			0x3D /* External vertical blank */
+#define HDMI_EXTERNAL_V_DELAY			0x3E /* External vertical delay */
+#define HDMI_EXTERNAL_V_DURATION		0x3F /* External vertical duration */
+#define HDMI_CTRL_PKT_MANUAL_SEND_CONTROL	0x40 /* Control packet manual send control */
+#define HDMI_CTRL_PKT_AUTO_SEND			0x41 /* Control packet auto send with VSYNC control */
+#define HDMI_AUTO_CHECKSUM_OPTION		0x42 /* Auto checksum option */
+#define HDMI_VIDEO_SETTING_2			0x45 /* Video setting.2 */
+#define HDMI_OUTPUT_OPTION			0x46 /* Output option */
+#define HDMI_SLIPHDMIT_PARAM_OPTION		0x51 /* SLIPHDMIT parameter option */
+#define HDMI_HSYNC_PMENT_AT_EMB_7_0		0x52 /* HSYNC placement at embedded sync (LSB) */
+#define HDMI_HSYNC_PMENT_AT_EMB_15_8		0x53 /* HSYNC placement at embedded sync (MSB) */
+#define HDMI_VSYNC_PMENT_AT_EMB_7_0		0x54 /* VSYNC placement at embedded sync (LSB) */
+#define HDMI_VSYNC_PMENT_AT_EMB_14_8		0x55 /* VSYNC placement at embedded sync (MSB) */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_1		0x56 /* SLIPHDMIT parameter settings.1 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_2		0x57 /* SLIPHDMIT parameter settings.2 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_3		0x58 /* SLIPHDMIT parameter settings.3 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_5		0x59 /* SLIPHDMIT parameter settings.5 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_6		0x5A /* SLIPHDMIT parameter settings.6 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_7		0x5B /* SLIPHDMIT parameter settings.7 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_8		0x5C /* SLIPHDMIT parameter settings.8 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_9		0x5D /* SLIPHDMIT parameter settings.9 */
+#define HDMI_SLIPHDMIT_PARAM_SETTINGS_10	0x5E /* SLIPHDMIT parameter settings.10 */
+#define HDMI_CTRL_PKT_BUF_INDEX			0x5F /* Control packet buffer index */
+#define HDMI_CTRL_PKT_BUF_ACCESS_HB0		0x60 /* Control packet data buffer access window - HB0 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_HB1		0x61 /* Control packet data buffer access window - HB1 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_HB2		0x62 /* Control packet data buffer access window - HB2 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB0		0x63 /* Control packet data buffer access window - PB0 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB1		0x64 /* Control packet data buffer access window - PB1 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB2		0x65 /* Control packet data buffer access window - PB2 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB3		0x66 /* Control packet data buffer access window - PB3 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB4		0x67 /* Control packet data buffer access window - PB4 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB5		0x68 /* Control packet data buffer access window - PB5 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB6		0x69 /* Control packet data buffer access window - PB6 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB7		0x6A /* Control packet data buffer access window - PB7 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB8		0x6B /* Control packet data buffer access window - PB8 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB9		0x6C /* Control packet data buffer access window - PB9 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB10		0x6D /* Control packet data buffer access window - PB10 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB11		0x6E /* Control packet data buffer access window - PB11 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB12		0x6F /* Control packet data buffer access window - PB12 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB13		0x70 /* Control packet data buffer access window - PB13 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB14		0x71 /* Control packet data buffer access window - PB14 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB15		0x72 /* Control packet data buffer access window - PB15 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB16		0x73 /* Control packet data buffer access window - PB16 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB17		0x74 /* Control packet data buffer access window - PB17 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB18		0x75 /* Control packet data buffer access window - PB18 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB19		0x76 /* Control packet data buffer access window - PB19 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB20		0x77 /* Control packet data buffer access window - PB20 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB21		0x78 /* Control packet data buffer access window - PB21 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB22		0x79 /* Control packet data buffer access window - PB22 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB23		0x7A /* Control packet data buffer access window - PB23 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB24		0x7B /* Control packet data buffer access window - PB24 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB25		0x7C /* Control packet data buffer access window - PB25 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB26		0x7D /* Control packet data buffer access window - PB26 */
+#define HDMI_CTRL_PKT_BUF_ACCESS_PB27		0x7E /* Control packet data buffer access window - PB27 */
+#define HDMI_EDID_KSV_FIFO_ACCESS_WINDOW	0x80 /* EDID/KSV FIFO access window */
+#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_7_0	0x81 /* DDC bus access frequency control (LSB) */
+#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_15_8	0x82 /* DDC bus access frequency control (MSB) */
+#define HDMI_INTERRUPT_MASK_1			0x92 /* Interrupt mask.1 */
+#define HDMI_INTERRUPT_MASK_2			0x93 /* Interrupt mask.2 */
+#define HDMI_INTERRUPT_STATUS_1			0x94 /* Interrupt status.1 */
+#define HDMI_INTERRUPT_STATUS_2			0x95 /* Interrupt status.2 */
+#define HDMI_INTERRUPT_MASK_3			0x96 /* Interrupt mask.3 */
+#define HDMI_INTERRUPT_MASK_4			0x97 /* Interrupt mask.4 */
+#define HDMI_INTERRUPT_STATUS_3			0x98 /* Interrupt status.3 */
+#define HDMI_INTERRUPT_STATUS_4			0x99 /* Interrupt status.4 */
+#define HDMI_SOFTWARE_HDCP_CONTROL_1		0x9A /* Software HDCP control.1 */
+#define HDMI_FRAME_COUNTER			0x9C /* Frame counter */
+#define HDMI_FRAME_COUNTER_FOR_RI_CHECK		0x9D /* Frame counter for Ri check */
+#define HDMI_HDCP_CONTROL			0xAF /* HDCP control */
+#define HDMI_RI_FRAME_COUNT_REGISTER		0xB2 /* Ri frame count register */
+#define HDMI_DDC_BUS_CONTROL			0xB7 /* DDC bus control */
+#define HDMI_HDCP_STATUS			0xB8 /* HDCP status */
+#define HDMI_SHA0				0xB9 /* sha0 */
+#define HDMI_SHA1				0xBA /* sha1 */
+#define HDMI_SHA2				0xBB /* sha2 */
+#define HDMI_SHA3				0xBC /* sha3 */
+#define HDMI_SHA4				0xBD /* sha4 */
+#define HDMI_BCAPS_READ				0xBE /* BCAPS read / debug */
+#define HDMI_AKSV_BKSV_7_0_MONITOR		0xBF /* AKSV/BKSV[7:0] monitor */
+#define HDMI_AKSV_BKSV_15_8_MONITOR		0xC0 /* AKSV/BKSV[15:8] monitor */
+#define HDMI_AKSV_BKSV_23_16_MONITOR		0xC1 /* AKSV/BKSV[23:16] monitor */
+#define HDMI_AKSV_BKSV_31_24_MONITOR		0xC2 /* AKSV/BKSV[31:24] monitor */
+#define HDMI_AKSV_BKSV_39_32_MONITOR		0xC3 /* AKSV/BKSV[39:32] monitor */
+#define HDMI_EDID_SEGMENT_POINTER		0xC4 /* EDID segment pointer */
+#define HDMI_EDID_WORD_ADDRESS			0xC5 /* EDID word address */
+#define HDMI_EDID_DATA_FIFO_ADDRESS		0xC6 /* EDID data FIFO address */
+#define HDMI_NUM_OF_HDMI_DEVICES		0xC7 /* Number of HDMI devices */
+#define HDMI_HDCP_ERROR_CODE			0xC8 /* HDCP error code */
+#define HDMI_100MS_TIMER_SET			0xC9 /* 100ms timer setting */
+#define HDMI_5SEC_TIMER_SET			0xCA /* 5sec timer setting */
+#define HDMI_RI_READ_COUNT			0xCB /* Ri read count */
+#define HDMI_AN_SEED				0xCC /* An seed */
+#define HDMI_MAX_NUM_OF_RCIVRS_ALLOWED		0xCD /* Maximum number of receivers allowed */
+#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_1	0xCE /* HDCP memory access control.1 */
+#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_2	0xCF /* HDCP memory access control.2 */
+#define HDMI_HDCP_CONTROL_2			0xD0 /* HDCP Control 2 */
+#define HDMI_HDCP_KEY_MEMORY_CONTROL		0xD2 /* HDCP Key Memory Control */
+#define HDMI_COLOR_SPACE_CONV_CONFIG_1		0xD3 /* Color space conversion configuration.1 */
+#define HDMI_VIDEO_SETTING_3			0xD4 /* Video setting.3 */
+#define HDMI_RI_7_0				0xD5 /* Ri[7:0] */
+#define HDMI_RI_15_8				0xD6 /* Ri[15:8] */
+#define HDMI_PJ					0xD7 /* Pj */
+#define HDMI_SHA_RD				0xD8 /* sha_rd */
+#define HDMI_RI_7_0_SAVED			0xD9 /* Ri[7:0] saved */
+#define HDMI_RI_15_8_SAVED			0xDA /* Ri[15:8] saved */
+#define HDMI_PJ_SAVED				0xDB /* Pj saved */
+#define HDMI_NUM_OF_DEVICES			0xDC /* Number of devices */
+#define HDMI_HOT_PLUG_MSENS_STATUS		0xDF /* Hot plug/MSENS status */
+#define HDMI_BCAPS_WRITE			0xE0 /* bcaps */
+#define HDMI_BSTAT_7_0				0xE1 /* bstat[7:0] */
+#define HDMI_BSTAT_15_8				0xE2 /* bstat[15:8] */
+#define HDMI_BKSV_7_0				0xE3 /* bksv[7:0] */
+#define HDMI_BKSV_15_8				0xE4 /* bksv[15:8] */
+#define HDMI_BKSV_23_16				0xE5 /* bksv[23:16] */
+#define HDMI_BKSV_31_24				0xE6 /* bksv[31:24] */
+#define HDMI_BKSV_39_32				0xE7 /* bksv[39:32] */
+#define HDMI_AN_7_0				0xE8 /* An[7:0] */
+#define HDMI_AN_15_8				0xE9 /* An [15:8] */
+#define HDMI_AN_23_16				0xEA /* An [23:16] */
+#define HDMI_AN_31_24				0xEB /* An [31:24] */
+#define HDMI_AN_39_32				0xEC /* An [39:32] */
+#define HDMI_AN_47_40				0xED /* An [47:40] */
+#define HDMI_AN_55_48				0xEE /* An [55:48] */
+#define HDMI_AN_63_56				0xEF /* An [63:56] */
+#define HDMI_PRODUCT_ID				0xF0 /* Product ID */
+#define HDMI_REVISION_ID			0xF1 /* Revision ID */
+#define HDMI_TEST_MODE				0xFE /* Test mode */
+
+/* HDMI Control Register (HTOP1) */
+#define HDMI_HTOP1_TEST_MODE			0x0000 /* Test mode */
+#define HDMI_HTOP1_VIDEO_INPUT			0x0008 /* VideoInput */
+#define HDMI_HTOP1_CORE_RSTN			0x000C /* CoreResetn */
+#define HDMI_HTOP1_PLLBW			0x0018 /* PLLBW */
+#define HDMI_HTOP1_CLK_TO_PHY			0x001C /* Clk to Phy */
+#define HDMI_HTOP1_VIDEO_INPUT2			0x0020 /* VideoInput2 */
+#define HDMI_HTOP1_TISEMP0_1			0x0024 /* tisemp0-1 */
+#define HDMI_HTOP1_TISEMP2_C			0x0028 /* tisemp2-c */
+#define HDMI_HTOP1_TISIDRV			0x002C /* tisidrv */
+#define HDMI_HTOP1_TISEN			0x0034 /* tisen */
+#define HDMI_HTOP1_TISDREN			0x0038 /* tisdren  */
+#define HDMI_HTOP1_CISRANGE			0x003C /* cisrange  */
+#define HDMI_HTOP1_ENABLE_SELECTOR		0x0040 /* Enable Selector */
+#define HDMI_HTOP1_MACRO_RESET			0x0044 /* Macro reset */
+#define HDMI_HTOP1_PLL_CALIBRATION		0x0048 /* PLL calibration */
+#define HDMI_HTOP1_RE_CALIBRATION		0x004C /* Re-calibration */
+#define HDMI_HTOP1_CURRENT			0x0050 /* Current */
+#define HDMI_HTOP1_PLL_LOCK_DETECT		0x0054 /* PLL lock detect */
+#define HDMI_HTOP1_PHY_TEST_MODE		0x0058 /* PHY Test Mode */
+#define HDMI_HTOP1_CLK_SET			0x0080 /* Clock Set */
+#define HDMI_HTOP1_DDC_FAIL_SAFE		0x0084 /* DDC fail safe */
+#define HDMI_HTOP1_PRBS				0x0088 /* PRBS */
+#define HDMI_HTOP1_EDID_AINC_CONTROL		0x008C /* EDID ainc Control */
+#define HDMI_HTOP1_HTOP_DCL_MODE		0x00FC /* Deep Coloer Mode */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0		0x0100 /* Deep Color:FRC COEF0 */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1		0x0104 /* Deep Color:FRC COEF1 */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2		0x0108 /* Deep Color:FRC COEF2 */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3		0x010C /* Deep Color:FRC COEF3 */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C		0x0110 /* Deep Color:FRC COEF0C */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C		0x0114 /* Deep Color:FRC COEF1C */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C		0x0118 /* Deep Color:FRC COEF2C */
+#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C		0x011C /* Deep Color:FRC COEF3C */
+#define HDMI_HTOP1_HTOP_DCL_FRC_MODE		0x0120 /* Deep Color:FRC Mode */
+#define HDMI_HTOP1_HTOP_DCL_RECT_START1		0x0124 /* Deep Color:Rect Start1 */
+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1		0x0128 /* Deep Color:Rect Size1 */
+#define HDMI_HTOP1_HTOP_DCL_RECT_START2		0x012C /* Deep Color:Rect Start2 */
+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2		0x0130 /* Deep Color:Rect Size2 */
+#define HDMI_HTOP1_HTOP_DCL_RECT_START3		0x0134 /* Deep Color:Rect Start3 */
+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3		0x0138 /* Deep Color:Rect Size3 */
+#define HDMI_HTOP1_HTOP_DCL_RECT_START4		0x013C /* Deep Color:Rect Start4 */
+#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4		0x0140 /* Deep Color:Rect Size4 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1	0x0144 /* Deep Color:Fil Para Y1_1 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2	0x0148 /* Deep Color:Fil Para Y1_2 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1	0x014C /* Deep Color:Fil Para CB1_1 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2	0x0150 /* Deep Color:Fil Para CB1_2 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1	0x0154 /* Deep Color:Fil Para CR1_1 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2	0x0158 /* Deep Color:Fil Para CR1_2 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1	0x015C /* Deep Color:Fil Para Y2_1 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2	0x0160 /* Deep Color:Fil Para Y2_2 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1	0x0164 /* Deep Color:Fil Para CB2_1 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2	0x0168 /* Deep Color:Fil Para CB2_2 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1	0x016C /* Deep Color:Fil Para CR2_1 */
+#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2	0x0170 /* Deep Color:Fil Para CR2_2 */
+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1		0x0174 /* Deep Color:Cor Para Y1 */
+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1	0x0178 /* Deep Color:Cor Para CB1 */
+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1	0x017C /* Deep Color:Cor Para CR1 */
+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2		0x0180 /* Deep Color:Cor Para Y2 */
+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2	0x0184 /* Deep Color:Cor Para CB2 */
+#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2	0x0188 /* Deep Color:Cor Para CR2 */
+#define HDMI_HTOP1_EDID_DATA_READ		0x0200 /* EDID Data Read 128Byte:0x03FC */
+
+enum hotplug_state {
+	HDMI_HOTPLUG_DISCONNECTED,
+	HDMI_HOTPLUG_CONNECTED,
+	HDMI_HOTPLUG_EDID_DONE,
+};
+
+struct sh_hdmi {
+	struct sh_mobile_lcdc_entity entity;
+
+	void __iomem *base;
+	void __iomem *htop1;
+	enum hotplug_state hp_state;	/* hot-plug status */
+	u8 preprogrammed_vic;		/* use a pre-programmed VIC or
+					   the external mode */
+	u8 edid_block_addr;
+	u8 edid_segment_nr;
+	u8 edid_blocks;
+	struct clk *hdmi_clk;
+	struct device *dev;
+	struct delayed_work edid_work;
+	struct fb_videomode mode;
+	struct fb_monspecs monspec;
+
+	/* register access functions */
+	void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg);
+	u8 (*read)(struct sh_hdmi *hdmi, u8 reg);
+};
+
+#define entity_to_sh_hdmi(e)	container_of(e, struct sh_hdmi, entity)
+
+static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg)
+{
+	iowrite8(data, hdmi->base + reg);
+}
+
+static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg)
+{
+	return ioread8(hdmi->base + reg);
+}
+
+static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg)
+{
+	iowrite32((u32)data, hdmi->base + (reg * 4));
+	udelay(100);
+}
+
+static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg)
+{
+	return (u8)ioread32(hdmi->base + (reg * 4));
+}
+
+static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
+{
+	hdmi->write(hdmi, data, reg);
+}
+
+static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
+{
+	return hdmi->read(hdmi, reg);
+}
+
+static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
+{
+	u8 val = hdmi_read(hdmi, reg);
+
+	val &= ~mask;
+	val |= (data & mask);
+
+	hdmi_write(hdmi, val, reg);
+}
+
+static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg)
+{
+	iowrite32(data, hdmi->htop1 + reg);
+	udelay(100);
+}
+
+static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg)
+{
+	return ioread32(hdmi->htop1 + reg);
+}
+
+/*
+ *	HDMI sound
+ */
+static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec,
+				     unsigned int reg)
+{
+	struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
+
+	return hdmi_read(hdmi, reg);
+}
+
+static int sh_hdmi_snd_write(struct snd_soc_codec *codec,
+			     unsigned int reg,
+			     unsigned int value)
+{
+	struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
+
+	hdmi_write(hdmi, value, reg);
+	return 0;
+}
+
+static struct snd_soc_dai_driver sh_hdmi_dai = {
+	.name = "sh_mobile_hdmi-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100  |
+			 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200  |
+			 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+			 SNDRV_PCM_RATE_192000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+	},
+};
+
+static int sh_hdmi_snd_probe(struct snd_soc_codec *codec)
+{
+	dev_info(codec->dev, "SH Mobile HDMI Audio Codec");
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
+	.probe		= sh_hdmi_snd_probe,
+	.read		= sh_hdmi_snd_read,
+	.write		= sh_hdmi_snd_write,
+};
+
+/*
+ *	HDMI video
+ */
+
+/* External video parameter settings */
+static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
+{
+	struct fb_videomode *mode = &hdmi->mode;
+	u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
+	u8 sync = 0;
+
+	htotal = mode->xres + mode->right_margin + mode->left_margin
+	       + mode->hsync_len;
+	hdelay = mode->hsync_len + mode->left_margin;
+	hblank = mode->right_margin + hdelay;
+
+	/*
+	 * Vertical timing looks a bit different in Figure 18,
+	 * but let's try the same first by setting offset = 0
+	 */
+	vtotal = mode->yres + mode->upper_margin + mode->lower_margin
+	       + mode->vsync_len;
+	vdelay = mode->vsync_len + mode->upper_margin;
+	vblank = mode->lower_margin + vdelay;
+	voffset = min(mode->upper_margin / 2, 6U);
+
+	/*
+	 * [3]: VSYNC polarity: Positive
+	 * [2]: HSYNC polarity: Positive
+	 * [1]: Interlace/Progressive: Progressive
+	 * [0]: External video settings enable: used.
+	 */
+	if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+		sync |= 4;
+	if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+		sync |= 8;
+
+	dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
+		htotal, hblank, hdelay, mode->hsync_len,
+		vtotal, vblank, vdelay, mode->vsync_len, sync);
+
+	hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
+
+	hdmi_write(hdmi, htotal, HDMI_EXTERNAL_H_TOTAL_7_0);
+	hdmi_write(hdmi, htotal >> 8, HDMI_EXTERNAL_H_TOTAL_11_8);
+
+	hdmi_write(hdmi, hblank, HDMI_EXTERNAL_H_BLANK_7_0);
+	hdmi_write(hdmi, hblank >> 8, HDMI_EXTERNAL_H_BLANK_9_8);
+
+	hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0);
+	hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8);
+
+	hdmi_write(hdmi, mode->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0);
+	hdmi_write(hdmi, mode->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8);
+
+	hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0);
+	hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8);
+
+	hdmi_write(hdmi, vblank, HDMI_EXTERNAL_V_BLANK);
+
+	hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY);
+
+	hdmi_write(hdmi, mode->vsync_len, HDMI_EXTERNAL_V_DURATION);
+
+	/* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
+	if (!hdmi->preprogrammed_vic)
+		hdmi_write(hdmi, sync | 1 | (voffset << 4),
+			   HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
+}
+
+/**
+ * sh_hdmi_video_config()
+ */
+static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
+{
+	/*
+	 * [7:4]: Audio sampling frequency: 48kHz
+	 * [3:1]: Input video format: RGB and YCbCr 4:4:4 (Y on Green)
+	 * [0]: Internal/External DE select: internal
+	 */
+	hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
+
+	/*
+	 * [7:6]: Video output format: RGB 4:4:4
+	 * [5:4]: Input video data width: 8 bit
+	 * [3:1]: EAV/SAV location: channel 1
+	 * [0]: Video input color space: RGB
+	 */
+	hdmi_write(hdmi, 0x34, HDMI_VIDEO_SETTING_1);
+
+	/*
+	 * [7:6]: Together with bit [6] of HDMI_AUDIO_VIDEO_SETTING_2, which is
+	 * left at 0 by default, this configures 24bpp and sets the Color Depth
+	 * (CD) field in the General Control Packet
+	 */
+	hdmi_write(hdmi, 0x20, HDMI_DEEP_COLOR_MODES);
+}
+
+/**
+ * sh_hdmi_audio_config()
+ */
+static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
+{
+	u8 data;
+	struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev);
+
+	/*
+	 * [7:4] L/R data swap control
+	 * [3:0] appropriate N[19:16]
+	 */
+	hdmi_write(hdmi, 0x00, HDMI_L_R_DATA_SWAP_CTRL_RPKT);
+	/* appropriate N[15:8] */
+	hdmi_write(hdmi, 0x18, HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8);
+	/* appropriate N[7:0] */
+	hdmi_write(hdmi, 0x00, HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0);
+
+	/* [7:4] 48 kHz	SPDIF not used */
+	hdmi_write(hdmi, 0x20, HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS);
+
+	/*
+	 * [6:5] set required down sampling rate if required
+	 * [4:3] set required audio source
+	 */
+	switch (pdata->flags & HDMI_SND_SRC_MASK) {
+	default:
+		/* fall through */
+	case HDMI_SND_SRC_I2S:
+		data = 0x0 << 3;
+		break;
+	case HDMI_SND_SRC_SPDIF:
+		data = 0x1 << 3;
+		break;
+	case HDMI_SND_SRC_DSD:
+		data = 0x2 << 3;
+		break;
+	case HDMI_SND_SRC_HBR:
+		data = 0x3 << 3;
+		break;
+	}
+	hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1);
+
+	/* [3:0] set sending channel number for channel status */
+	hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
+
+	/*
+	 * [5:2] set valid I2S source input pin
+	 * [1:0] set input I2S source mode
+	 */
+	hdmi_write(hdmi, 0x04, HDMI_I2S_AUDIO_SET);
+
+	/* [7:4] set valid DSD source input pin */
+	hdmi_write(hdmi, 0x00, HDMI_DSD_AUDIO_SET);
+
+	/* [7:0] set appropriate I2S input pin swap settings if required */
+	hdmi_write(hdmi, 0x00, HDMI_I2S_INPUT_PIN_SWAP);
+
+	/*
+	 * [7] set validity bit for channel status
+	 * [3:0] set original sample frequency for channel status
+	 */
+	hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_1);
+
+	/*
+	 * [7] set value for channel status
+	 * [6] set value for channel status
+	 * [5] set copyright bit for channel status
+	 * [4:2] set additional information for channel status
+	 * [1:0] set clock accuracy for channel status
+	 */
+	hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_2);
+
+	/* [7:0] set category code for channel status */
+	hdmi_write(hdmi, 0x00, HDMI_CATEGORY_CODE);
+
+	/*
+	 * [7:4] set source number for channel status
+	 * [3:0] set word length for channel status
+	 */
+	hdmi_write(hdmi, 0x00, HDMI_SOURCE_NUM_AUDIO_WORD_LEN);
+
+	/* [7:4] set sample frequency for channel status */
+	hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
+}
+
+/**
+ * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode
+ */
+static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
+{
+	if (hdmi->mode.pixclock < 10000) {
+		/* for 1080p8bit 148MHz */
+		hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
+		hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
+		hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
+		hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
+		hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
+		hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
+		hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
+	} else if (hdmi->mode.pixclock < 30000) {
+		/* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
+		/*
+		 * [1:0]	Speed_A
+		 * [3:2]	Speed_B
+		 * [4]		PLLA_Bypass
+		 * [6]		DRV_TEST_EN
+		 * [7]		DRV_TEST_IN
+		 */
+		hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
+		/* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
+		/*
+		 * [2:0]	BGR_I_OFFSET
+		 * [6:4]	BGR_V_OFFSET
+		 */
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
+		/* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
+		hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
+		/*
+		 * PLLA_CONFIG[15:8]: regulator voltage[0], CP current,
+		 * LPF capacitance, LPF resistance[1]
+		 */
+		hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
+		/* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */
+		hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
+		/*
+		 * PLLB_CONFIG[15:8]: regulator voltage[0], CP current,
+		 * LPF capacitance, LPF resistance[1]
+		 */
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
+		/* DRV_CONFIG, PE_CONFIG */
+		hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
+		/*
+		 * [2:0]	AMON_SEL (4 == LPF voltage)
+		 * [4]		PLLA_CONFIG[16]
+		 * [5]		PLLB_CONFIG[16]
+		 */
+		hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
+	} else {
+		/* for 480p8bit 27MHz */
+		hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
+		hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
+		hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
+		hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
+		hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
+		hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
+		hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
+	}
+}
+
+/**
+ * sh_hdmi_avi_infoframe_setup() - Auxiliary Video Information InfoFrame CONTROL PACKET
+ */
+static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
+{
+	u8 vic;
+
+	/* AVI InfoFrame */
+	hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
+
+	/* Packet Type = 0x82 */
+	hdmi_write(hdmi, 0x82, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
+
+	/* Version = 0x02 */
+	hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
+
+	/* Length = 13 (0x0D) */
+	hdmi_write(hdmi, 0x0D, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
+
+	/* N. A. Checksum */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
+
+	/*
+	 * Y = RGB
+	 * A0 = No Data
+	 * B = Bar Data not valid
+	 * S = No Data
+	 */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
+
+	/*
+	 * [7:6] C = Colorimetry: no data
+	 * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio
+	 * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio
+	 */
+	hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
+
+	/*
+	 * ITC = No Data
+	 * EC = xvYCC601
+	 * Q = Default (depends on video format)
+	 * SC = No Known non_uniform Scaling
+	 */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
+
+	/*
+	 * VIC should be ignored if external config is used, so, we could just use 0,
+	 * but play safe and use a valid value in any case just in case
+	 */
+	if (hdmi->preprogrammed_vic)
+		vic = hdmi->preprogrammed_vic;
+	else
+		vic = 4;
+	hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
+
+	/* PR = No Repetition */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
+
+	/* Line Number of End of Top Bar (lower 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
+
+	/* Line Number of End of Top Bar (upper 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
+
+	/* Line Number of Start of Bottom Bar (lower 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
+
+	/* Line Number of Start of Bottom Bar (upper 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
+
+	/* Pixel Number of End of Left Bar (lower 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
+
+	/* Pixel Number of End of Left Bar (upper 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB11);
+
+	/* Pixel Number of Start of Right Bar (lower 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB12);
+
+	/* Pixel Number of Start of Right Bar (upper 8 bits) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB13);
+}
+
+/**
+ * sh_hdmi_audio_infoframe_setup() - Audio InfoFrame of CONTROL PACKET
+ */
+static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
+{
+	/* Audio InfoFrame */
+	hdmi_write(hdmi, 0x08, HDMI_CTRL_PKT_BUF_INDEX);
+
+	/* Packet Type = 0x84 */
+	hdmi_write(hdmi, 0x84, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
+
+	/* Version Number = 0x01 */
+	hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
+
+	/* 0 Length = 10 (0x0A) */
+	hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
+
+	/* n. a. Checksum */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
+
+	/* Audio Channel Count = Refer to Stream Header */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
+
+	/* Refer to Stream Header */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
+
+	/* Format depends on coding type (i.e. CT0...CT3) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
+
+	/* Speaker Channel Allocation = Front Right + Front Left */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
+
+	/* Level Shift Value = 0 dB, Down - mix is permitted or no information */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
+
+	/* Reserved (0) */
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
+	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
+}
+
+/**
+ * sh_hdmi_configure() - Initialise HDMI for output
+ */
+static void sh_hdmi_configure(struct sh_hdmi *hdmi)
+{
+	/* Configure video format */
+	sh_hdmi_video_config(hdmi);
+
+	/* Configure audio format */
+	sh_hdmi_audio_config(hdmi);
+
+	/* Configure PHY */
+	sh_hdmi_phy_config(hdmi);
+
+	/* Auxiliary Video Information (AVI) InfoFrame */
+	sh_hdmi_avi_infoframe_setup(hdmi);
+
+	/* Audio InfoFrame */
+	sh_hdmi_audio_infoframe_setup(hdmi);
+
+	/*
+	 * Control packet auto send with VSYNC control: auto send
+	 * General control, Gamut metadata, ISRC, and ACP packets
+	 */
+	hdmi_write(hdmi, 0x8E, HDMI_CTRL_PKT_AUTO_SEND);
+
+	/* FIXME */
+	msleep(10);
+
+	/* PS mode b->d, reset PLLA and PLLB */
+	hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL);
+
+	udelay(10);
+
+	hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL);
+}
+
+static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
+		const struct fb_videomode *mode,
+		unsigned long *hdmi_rate, unsigned long *parent_rate)
+{
+	unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
+	struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev);
+
+	*hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
+	if ((long)*hdmi_rate < 0)
+		*hdmi_rate = clk_get_rate(hdmi->hdmi_clk);
+
+	rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX;
+	if (rate_error && pdata->clk_optimize_parent)
+		rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate);
+	else if (clk_get_parent(hdmi->hdmi_clk))
+		*parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk));
+
+	dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
+		mode->left_margin, mode->xres,
+		mode->right_margin, mode->hsync_len,
+		mode->upper_margin, mode->yres,
+		mode->lower_margin, mode->vsync_len);
+
+	dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target,
+		rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
+		mode->refresh, *parent_rate);
+
+	return rate_error;
+}
+
+static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
+			     unsigned long *parent_rate)
+{
+	struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
+	const struct fb_videomode *mode, *found = NULL;
+	unsigned int f_width = 0, f_height = 0, f_refresh = 0;
+	unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
+	bool scanning = false, preferred_bad = false;
+	bool use_edid_mode = false;
+	u8 edid[128];
+	char *forced;
+	int i;
+
+	/* Read EDID */
+	dev_dbg(hdmi->dev, "Read back EDID code:");
+	for (i = 0; i < 128; i++) {
+		edid[i] = (hdmi->htop1) ?
+			(u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) :
+			hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
+#ifdef DEBUG
+		if ((i % 16) == 0) {
+			printk(KERN_CONT "\n");
+			printk(KERN_DEBUG "%02X | %02X", i, edid[i]);
+		} else {
+			printk(KERN_CONT " %02X", edid[i]);
+		}
+#endif
+	}
+#ifdef DEBUG
+	printk(KERN_CONT "\n");
+#endif
+
+	if (!hdmi->edid_blocks) {
+		fb_edid_to_monspecs(edid, &hdmi->monspec);
+		hdmi->edid_blocks = edid[126] + 1;
+
+		dev_dbg(hdmi->dev, "%d main modes, %d extension blocks\n",
+			hdmi->monspec.modedb_len, hdmi->edid_blocks - 1);
+	} else {
+		dev_dbg(hdmi->dev, "Extension %u detected, DTD start %u\n",
+			edid[0], edid[2]);
+		fb_edid_add_monspecs(edid, &hdmi->monspec);
+	}
+
+	if (hdmi->edid_blocks > hdmi->edid_segment_nr * 2 +
+	    (hdmi->edid_block_addr >> 7) + 1) {
+		/* More blocks to read */
+		if (hdmi->edid_block_addr) {
+			hdmi->edid_block_addr = 0;
+			hdmi->edid_segment_nr++;
+		} else {
+			hdmi->edid_block_addr = 0x80;
+		}
+		/* Set EDID word address  */
+		hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
+		/* Enable EDID interrupt */
+		hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
+		/* Set EDID segment pointer - starts reading EDID */
+		hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
+		return -EAGAIN;
+	}
+
+	/* All E-EDID blocks ready */
+	dev_dbg(hdmi->dev, "%d main and extended modes\n", hdmi->monspec.modedb_len);
+
+	fb_get_options("sh_mobile_lcdc", &forced);
+	if (forced && *forced) {
+		/* Only primitive parsing so far */
+		i = sscanf(forced, "%ux%u@%u",
+			   &f_width, &f_height, &f_refresh);
+		if (i < 2) {
+			f_width = 0;
+			f_height = 0;
+		} else {
+			/* The user wants us to use the EDID data */
+			scanning = true;
+		}
+		dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
+			f_width, f_height, f_refresh);
+	}
+
+	/* Walk monitor modes to find the best or the exact match */
+	for (i = 0, mode = hdmi->monspec.modedb;
+	     i < hdmi->monspec.modedb_len && scanning;
+	     i++, mode++) {
+		unsigned long rate_error;
+
+		if (!f_width && !f_height) {
+			/*
+			 * A parameter string "video=sh_mobile_lcdc:0x0" means
+			 * use the preferred EDID mode. If it is rejected by
+			 * .fb_check_var(), keep looking, until an acceptable
+			 * one is found.
+			 */
+			if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad)
+				scanning = false;
+			else
+				continue;
+		} else if (f_width != mode->xres || f_height != mode->yres) {
+			/* No interest in unmatching modes */
+			continue;
+		}
+
+		rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
+
+		if (scanning) {
+			if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
+				/*
+				 * Exact match if either the refresh rate
+				 * matches or it hasn't been specified and we've
+				 * found a mode, for which we can configure the
+				 * clock precisely
+				 */
+				scanning = false;
+			else if (found && found_rate_error <= rate_error)
+				/*
+				 * We otherwise search for the closest matching
+				 * clock rate - either if no refresh rate has
+				 * been specified or we cannot find an exactly
+				 * matching one
+				 */
+				continue;
+		}
+
+		/* Check if supported: sufficient fb memory, supported clock-rate */
+		if (ch && ch->notify &&
+		    ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_MODE, mode,
+			       NULL)) {
+			scanning = true;
+			preferred_bad = true;
+			continue;
+		}
+
+		found = mode;
+		found_rate_error = rate_error;
+		use_edid_mode = true;
+	}
+
+	/*
+	 * TODO 1: if no default mode is present, postpone running the config
+	 * until after the LCDC channel is initialized.
+	 * TODO 2: consider registering the HDMI platform device from the LCDC
+	 * driver.
+	 */
+	if (!found && hdmi->entity.def_mode.xres != 0) {
+		found = &hdmi->entity.def_mode;
+		found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate,
+						      parent_rate);
+	}
+
+	/* No cookie today */
+	if (!found)
+		return -ENXIO;
+
+	if (found->xres == 640 && found->yres == 480 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 1;
+	else if (found->xres == 720 && found->yres == 480 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 2;
+	else if (found->xres == 720 && found->yres == 576 && found->refresh == 50)
+		hdmi->preprogrammed_vic = 17;
+	else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 4;
+	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24)
+		hdmi->preprogrammed_vic = 32;
+	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50)
+		hdmi->preprogrammed_vic = 31;
+	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 16;
+	else
+		hdmi->preprogrammed_vic = 0;
+
+	dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), "
+		"clock error %luHz\n", use_edid_mode ? "EDID" : "default",
+		hdmi->preprogrammed_vic ? "VIC" : "external", found->xres,
+		found->yres, found->refresh, PICOS2KHZ(found->pixclock) * 1000,
+		found_rate_error);
+
+	hdmi->mode = *found;
+	sh_hdmi_external_video_param(hdmi);
+
+	return 0;
+}
+
+static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
+{
+	struct sh_hdmi *hdmi = dev_id;
+	u8 status1, status2, mask1, mask2;
+
+	/* mode_b and PLLA and PLLB reset */
+	hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL);
+
+	/* How long shall reset be held? */
+	udelay(10);
+
+	/* mode_b and PLLA and PLLB reset release */
+	hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL);
+
+	status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
+	status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
+
+	mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1);
+	mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2);
+
+	/* Correct would be to ack only set bits, but the datasheet requires 0xff */
+	hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1);
+	hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
+
+	if (printk_ratelimit())
+		dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
+			irq, status1, mask1, status2, mask2);
+
+	if (!((status1 & mask1) | (status2 & mask2))) {
+		return IRQ_NONE;
+	} else if (status1 & 0xc0) {
+		u8 msens;
+
+		/* Datasheet specifies 10ms... */
+		udelay(500);
+
+		msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
+		dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens);
+		/* Check, if hot plug & MSENS pin status are both high */
+		if ((msens & 0xC0) == 0xC0) {
+			/* Display plug in */
+			hdmi->edid_segment_nr = 0;
+			hdmi->edid_block_addr = 0;
+			hdmi->edid_blocks = 0;
+			hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
+
+			/* Set EDID word address  */
+			hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
+			/* Enable EDID interrupt */
+			hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
+			/* Set EDID segment pointer - starts reading EDID */
+			hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
+		} else if (!(status1 & 0x80)) {
+			/* Display unplug, beware multiple interrupts */
+			if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) {
+				hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
+				schedule_delayed_work(&hdmi->edid_work, 0);
+			}
+			/* display_off will switch back to mode_a */
+		}
+	} else if (status1 & 2) {
+		/* EDID error interrupt: retry */
+		/* Set EDID word address  */
+		hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
+		/* Set EDID segment pointer */
+		hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
+	} else if (status1 & 4) {
+		/* Disable EDID interrupt */
+		hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
+		schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity)
+{
+	struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
+
+	dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, hdmi,
+		hdmi->hp_state);
+
+	/*
+	 * hp_state can be set to
+	 * HDMI_HOTPLUG_DISCONNECTED:	on monitor unplug
+	 * HDMI_HOTPLUG_CONNECTED:	on monitor plug-in
+	 * HDMI_HOTPLUG_EDID_DONE:	on EDID read completion
+	 */
+	if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
+		/* PS mode d->e. All functions are active */
+		hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL);
+		dev_dbg(hdmi->dev, "HDMI running\n");
+	}
+
+	return hdmi->hp_state == HDMI_HOTPLUG_DISCONNECTED
+		? SH_MOBILE_LCDC_DISPLAY_DISCONNECTED
+		: SH_MOBILE_LCDC_DISPLAY_CONNECTED;
+}
+
+static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
+{
+	struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
+
+	dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi);
+	/* PS mode e->a */
+	hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL);
+}
+
+static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
+	.display_on = sh_hdmi_display_on,
+	.display_off = sh_hdmi_display_off,
+};
+
+/**
+ * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
+ * @hdmi:		driver context
+ * @hdmi_rate:		HDMI clock frequency in Hz
+ * @parent_rate:	if != 0 - set parent clock rate for optimal precision
+ * return:		configured positive rate if successful
+ *			0 if couldn't set the rate, but managed to enable the
+ *			clock, negative error, if couldn't enable the clock
+ */
+static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
+				  unsigned long parent_rate)
+{
+	int ret;
+
+	if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) {
+		ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate);
+		if (ret < 0) {
+			dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret);
+			hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate);
+		} else {
+			dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate);
+		}
+	}
+
+	ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate);
+	if (ret < 0) {
+		dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret);
+		hdmi_rate = 0;
+	} else {
+		dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate);
+	}
+
+	return hdmi_rate;
+}
+
+/* Hotplug interrupt occurred, read EDID */
+static void sh_hdmi_edid_work_fn(struct work_struct *work)
+{
+	struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
+	struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
+	int ret;
+
+	dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi,
+		hdmi->hp_state);
+
+	if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
+		unsigned long parent_rate = 0, hdmi_rate;
+
+		ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
+		if (ret < 0)
+			goto out;
+
+		hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
+
+		/* Reconfigure the clock */
+		ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
+		if (ret < 0)
+			goto out;
+
+		msleep(10);
+		sh_hdmi_configure(hdmi);
+		/* Switched to another (d) power-save mode */
+		msleep(10);
+
+		if (ch && ch->notify)
+			ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
+				   &hdmi->mode, &hdmi->monspec);
+	} else {
+		hdmi->monspec.modedb_len = 0;
+		fb_destroy_modedb(hdmi->monspec.modedb);
+		hdmi->monspec.modedb = NULL;
+
+		if (ch && ch->notify)
+			ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
+				   NULL, NULL);
+
+		ret = 0;
+	}
+
+out:
+	if (ret < 0 && ret != -EAGAIN)
+		hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
+
+	dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
+}
+
+static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi)
+{
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE);
+	hdmi_htop1_write(hdmi, 0x0000000b, 0x0010);
+	hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE);
+	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1);
+	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2);
+	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1);
+	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2);
+	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1);
+	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2);
+	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1);
+	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2);
+	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1);
+	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2);
+	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1);
+	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2);
+	hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE);
+	hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW);
+	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
+	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
+	hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
+	hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
+	hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE);
+	msleep(100);
+	hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR);
+	msleep(100);
+	hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
+	hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
+	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
+	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY);
+	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2);
+	hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET);
+}
+
+static int __init sh_hdmi_probe(struct platform_device *pdev)
+{
+	struct sh_mobile_hdmi_info *pdata = dev_get_platdata(&pdev->dev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *htop1_res;
+	int irq = platform_get_irq(pdev, 0), ret;
+	struct sh_hdmi *hdmi;
+	long rate;
+
+	if (!res || !pdata || irq < 0)
+		return -ENODEV;
+
+	htop1_res = NULL;
+	if (pdata->flags & HDMI_HAS_HTOP1) {
+		htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (!htop1_res) {
+			dev_err(&pdev->dev, "htop1 needs register base\n");
+			return -EINVAL;
+		}
+	}
+
+	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+	if (!hdmi) {
+		dev_err(&pdev->dev, "Cannot allocate device data\n");
+		return -ENOMEM;
+	}
+
+	hdmi->dev = &pdev->dev;
+	hdmi->entity.owner = THIS_MODULE;
+	hdmi->entity.ops = &sh_hdmi_ops;
+
+	hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(hdmi->hdmi_clk)) {
+		ret = PTR_ERR(hdmi->hdmi_clk);
+		dev_err(&pdev->dev, "Unable to get clock: %d\n", ret);
+		return ret;
+	}
+
+	/* select register access functions */
+	if (pdata->flags & HDMI_32BIT_REG) {
+		hdmi->write	= __hdmi_write32;
+		hdmi->read	= __hdmi_read32;
+	} else {
+		hdmi->write	= __hdmi_write8;
+		hdmi->read	= __hdmi_read8;
+	}
+
+	/* An arbitrary relaxed pixclock just to get things started: from standard 480p */
+	rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
+	if (rate > 0)
+		rate = sh_hdmi_clk_configure(hdmi, rate, 0);
+
+	if (rate < 0) {
+		ret = rate;
+		goto erate;
+	}
+
+	ret = clk_prepare_enable(hdmi->hdmi_clk);
+	if (ret < 0) {
+		dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
+		goto erate;
+	}
+
+	dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
+
+	if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "HDMI register region already claimed\n");
+		ret = -EBUSY;
+		goto ereqreg;
+	}
+
+	hdmi->base = ioremap(res->start, resource_size(res));
+	if (!hdmi->base) {
+		dev_err(&pdev->dev, "HDMI register region already claimed\n");
+		ret = -ENOMEM;
+		goto emap;
+	}
+
+	platform_set_drvdata(pdev, &hdmi->entity);
+
+	INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
+	/* init interrupt polarity */
+	if (pdata->flags & HDMI_OUTPUT_PUSH_PULL)
+		hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL);
+
+	if (pdata->flags & HDMI_OUTPUT_POLARITY_HI)
+		hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL);
+
+	/* enable htop1 register if needed */
+	if (htop1_res) {
+		hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res));
+		if (!hdmi->htop1) {
+			dev_err(&pdev->dev, "control register region already claimed\n");
+			ret = -ENOMEM;
+			goto emap_htop1;
+		}
+		sh_hdmi_htop1_init(hdmi);
+	}
+
+	/* Product and revision IDs are 0 in sh-mobile version */
+	dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
+		 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
+
+	ret = request_irq(irq, sh_hdmi_hotplug, 0,
+			  dev_name(&pdev->dev), hdmi);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to request irq: %d\n", ret);
+		goto ereqirq;
+	}
+
+	ret = snd_soc_register_codec(&pdev->dev,
+			&soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "codec registration failed\n");
+		goto ecodec;
+	}
+
+	return 0;
+
+ecodec:
+	free_irq(irq, hdmi);
+ereqirq:
+	if (hdmi->htop1)
+		iounmap(hdmi->htop1);
+emap_htop1:
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	iounmap(hdmi->base);
+emap:
+	release_mem_region(res->start, resource_size(res));
+ereqreg:
+	clk_disable_unprepare(hdmi->hdmi_clk);
+erate:
+	clk_put(hdmi->hdmi_clk);
+
+	return ret;
+}
+
+static int __exit sh_hdmi_remove(struct platform_device *pdev)
+{
+	struct sh_hdmi *hdmi = entity_to_sh_hdmi(platform_get_drvdata(pdev));
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	int irq = platform_get_irq(pdev, 0);
+
+	snd_soc_unregister_codec(&pdev->dev);
+
+	/* No new work will be scheduled, wait for running ISR */
+	free_irq(irq, hdmi);
+	/* Wait for already scheduled work */
+	cancel_delayed_work_sync(&hdmi->edid_work);
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	clk_disable_unprepare(hdmi->hdmi_clk);
+	clk_put(hdmi->hdmi_clk);
+	if (hdmi->htop1)
+		iounmap(hdmi->htop1);
+	iounmap(hdmi->base);
+	release_mem_region(res->start, resource_size(res));
+
+	return 0;
+}
+
+static struct platform_driver sh_hdmi_driver = {
+	.remove		= __exit_p(sh_hdmi_remove),
+	.driver = {
+		.name	= "sh-mobile-hdmi",
+	},
+};
+
+module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
new file mode 100644
index 000000000000..2bcc84ac18c7
--- /dev/null
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -0,0 +1,2863 @@
+/*
+ * SuperH Mobile LCDC Framebuffer
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/atomic.h>
+#include <linux/backlight.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+
+#include <video/sh_mobile_lcdc.h>
+#include <video/sh_mobile_meram.h>
+
+#include "sh_mobile_lcdcfb.h"
+
+/* ----------------------------------------------------------------------------
+ * Overlay register definitions
+ */
+
+#define LDBCR			0xb00
+#define LDBCR_UPC(n)		(1 << ((n) + 16))
+#define LDBCR_UPF(n)		(1 << ((n) + 8))
+#define LDBCR_UPD(n)		(1 << ((n) + 0))
+#define LDBnBSIFR(n)		(0xb20 + (n) * 0x20 + 0x00)
+#define LDBBSIFR_EN		(1 << 31)
+#define LDBBSIFR_VS		(1 << 29)
+#define LDBBSIFR_BRSEL		(1 << 28)
+#define LDBBSIFR_MX		(1 << 27)
+#define LDBBSIFR_MY		(1 << 26)
+#define LDBBSIFR_CV3		(3 << 24)
+#define LDBBSIFR_CV2		(2 << 24)
+#define LDBBSIFR_CV1		(1 << 24)
+#define LDBBSIFR_CV0		(0 << 24)
+#define LDBBSIFR_CV_MASK	(3 << 24)
+#define LDBBSIFR_LAY_MASK	(0xff << 16)
+#define LDBBSIFR_LAY_SHIFT	16
+#define LDBBSIFR_ROP3_MASK	(0xff << 16)
+#define LDBBSIFR_ROP3_SHIFT	16
+#define LDBBSIFR_AL_PL8		(3 << 14)
+#define LDBBSIFR_AL_PL1		(2 << 14)
+#define LDBBSIFR_AL_PK		(1 << 14)
+#define LDBBSIFR_AL_1		(0 << 14)
+#define LDBBSIFR_AL_MASK	(3 << 14)
+#define LDBBSIFR_SWPL		(1 << 10)
+#define LDBBSIFR_SWPW		(1 << 9)
+#define LDBBSIFR_SWPB		(1 << 8)
+#define LDBBSIFR_RY		(1 << 7)
+#define LDBBSIFR_CHRR_420	(2 << 0)
+#define LDBBSIFR_CHRR_422	(1 << 0)
+#define LDBBSIFR_CHRR_444	(0 << 0)
+#define LDBBSIFR_RPKF_ARGB32	(0x00 << 0)
+#define LDBBSIFR_RPKF_RGB16	(0x03 << 0)
+#define LDBBSIFR_RPKF_RGB24	(0x0b << 0)
+#define LDBBSIFR_RPKF_MASK	(0x1f << 0)
+#define LDBnBSSZR(n)		(0xb20 + (n) * 0x20 + 0x04)
+#define LDBBSSZR_BVSS_MASK	(0xfff << 16)
+#define LDBBSSZR_BVSS_SHIFT	16
+#define LDBBSSZR_BHSS_MASK	(0xfff << 0)
+#define LDBBSSZR_BHSS_SHIFT	0
+#define LDBnBLOCR(n)		(0xb20 + (n) * 0x20 + 0x08)
+#define LDBBLOCR_CVLC_MASK	(0xfff << 16)
+#define LDBBLOCR_CVLC_SHIFT	16
+#define LDBBLOCR_CHLC_MASK	(0xfff << 0)
+#define LDBBLOCR_CHLC_SHIFT	0
+#define LDBnBSMWR(n)		(0xb20 + (n) * 0x20 + 0x0c)
+#define LDBBSMWR_BSMWA_MASK	(0xffff << 16)
+#define LDBBSMWR_BSMWA_SHIFT	16
+#define LDBBSMWR_BSMW_MASK	(0xffff << 0)
+#define LDBBSMWR_BSMW_SHIFT	0
+#define LDBnBSAYR(n)		(0xb20 + (n) * 0x20 + 0x10)
+#define LDBBSAYR_FG1A_MASK	(0xff << 24)
+#define LDBBSAYR_FG1A_SHIFT	24
+#define LDBBSAYR_FG1R_MASK	(0xff << 16)
+#define LDBBSAYR_FG1R_SHIFT	16
+#define LDBBSAYR_FG1G_MASK	(0xff << 8)
+#define LDBBSAYR_FG1G_SHIFT	8
+#define LDBBSAYR_FG1B_MASK	(0xff << 0)
+#define LDBBSAYR_FG1B_SHIFT	0
+#define LDBnBSACR(n)		(0xb20 + (n) * 0x20 + 0x14)
+#define LDBBSACR_FG2A_MASK	(0xff << 24)
+#define LDBBSACR_FG2A_SHIFT	24
+#define LDBBSACR_FG2R_MASK	(0xff << 16)
+#define LDBBSACR_FG2R_SHIFT	16
+#define LDBBSACR_FG2G_MASK	(0xff << 8)
+#define LDBBSACR_FG2G_SHIFT	8
+#define LDBBSACR_FG2B_MASK	(0xff << 0)
+#define LDBBSACR_FG2B_SHIFT	0
+#define LDBnBSAAR(n)		(0xb20 + (n) * 0x20 + 0x18)
+#define LDBBSAAR_AP_MASK	(0xff << 24)
+#define LDBBSAAR_AP_SHIFT	24
+#define LDBBSAAR_R_MASK		(0xff << 16)
+#define LDBBSAAR_R_SHIFT	16
+#define LDBBSAAR_GY_MASK	(0xff << 8)
+#define LDBBSAAR_GY_SHIFT	8
+#define LDBBSAAR_B_MASK		(0xff << 0)
+#define LDBBSAAR_B_SHIFT	0
+#define LDBnBPPCR(n)		(0xb20 + (n) * 0x20 + 0x1c)
+#define LDBBPPCR_AP_MASK	(0xff << 24)
+#define LDBBPPCR_AP_SHIFT	24
+#define LDBBPPCR_R_MASK		(0xff << 16)
+#define LDBBPPCR_R_SHIFT	16
+#define LDBBPPCR_GY_MASK	(0xff << 8)
+#define LDBBPPCR_GY_SHIFT	8
+#define LDBBPPCR_B_MASK		(0xff << 0)
+#define LDBBPPCR_B_SHIFT	0
+#define LDBnBBGCL(n)		(0xb10 + (n) * 0x04)
+#define LDBBBGCL_BGA_MASK	(0xff << 24)
+#define LDBBBGCL_BGA_SHIFT	24
+#define LDBBBGCL_BGR_MASK	(0xff << 16)
+#define LDBBBGCL_BGR_SHIFT	16
+#define LDBBBGCL_BGG_MASK	(0xff << 8)
+#define LDBBBGCL_BGG_SHIFT	8
+#define LDBBBGCL_BGB_MASK	(0xff << 0)
+#define LDBBBGCL_BGB_SHIFT	0
+
+#define SIDE_B_OFFSET 0x1000
+#define MIRROR_OFFSET 0x2000
+
+#define MAX_XRES 1920
+#define MAX_YRES 1080
+
+enum sh_mobile_lcdc_overlay_mode {
+	LCDC_OVERLAY_BLEND,
+	LCDC_OVERLAY_ROP3,
+};
+
+/*
+ * struct sh_mobile_lcdc_overlay - LCDC display overlay
+ *
+ * @channel: LCDC channel this overlay belongs to
+ * @cfg: Overlay configuration
+ * @info: Frame buffer device
+ * @index: Overlay index (0-3)
+ * @base: Overlay registers base address
+ * @enabled: True if the overlay is enabled
+ * @mode: Overlay blending mode (alpha blend or ROP3)
+ * @alpha: Global alpha blending value (0-255, for alpha blending mode)
+ * @rop3: Raster operation (for ROP3 mode)
+ * @fb_mem: Frame buffer virtual memory address
+ * @fb_size: Frame buffer size in bytes
+ * @dma_handle: Frame buffer DMA address
+ * @base_addr_y: Overlay base address (RGB or luma component)
+ * @base_addr_c: Overlay base address (chroma component)
+ * @pan_y_offset: Panning linear offset in bytes (luma component)
+ * @format: Current pixelf format
+ * @xres: Horizontal visible resolution
+ * @xres_virtual: Horizontal total resolution
+ * @yres: Vertical visible resolution
+ * @yres_virtual: Vertical total resolution
+ * @pitch: Overlay line pitch
+ * @pos_x: Horizontal overlay position
+ * @pos_y: Vertical overlay position
+ */
+struct sh_mobile_lcdc_overlay {
+	struct sh_mobile_lcdc_chan *channel;
+
+	const struct sh_mobile_lcdc_overlay_cfg *cfg;
+	struct fb_info *info;
+
+	unsigned int index;
+	unsigned long base;
+
+	bool enabled;
+	enum sh_mobile_lcdc_overlay_mode mode;
+	unsigned int alpha;
+	unsigned int rop3;
+
+	void *fb_mem;
+	unsigned long fb_size;
+
+	dma_addr_t dma_handle;
+	unsigned long base_addr_y;
+	unsigned long base_addr_c;
+	unsigned long pan_y_offset;
+
+	const struct sh_mobile_lcdc_format_info *format;
+	unsigned int xres;
+	unsigned int xres_virtual;
+	unsigned int yres;
+	unsigned int yres_virtual;
+	unsigned int pitch;
+	int pos_x;
+	int pos_y;
+};
+
+struct sh_mobile_lcdc_priv {
+	void __iomem *base;
+	int irq;
+	atomic_t hw_usecnt;
+	struct device *dev;
+	struct clk *dot_clk;
+	unsigned long lddckr;
+
+	struct sh_mobile_lcdc_chan ch[2];
+	struct sh_mobile_lcdc_overlay overlays[4];
+
+	struct notifier_block notifier;
+	int started;
+	int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
+	struct sh_mobile_meram_info *meram_dev;
+};
+
+/* -----------------------------------------------------------------------------
+ * Registers access
+ */
+
+static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
+	[LDDCKPAT1R] = 0x400,
+	[LDDCKPAT2R] = 0x404,
+	[LDMT1R] = 0x418,
+	[LDMT2R] = 0x41c,
+	[LDMT3R] = 0x420,
+	[LDDFR] = 0x424,
+	[LDSM1R] = 0x428,
+	[LDSM2R] = 0x42c,
+	[LDSA1R] = 0x430,
+	[LDSA2R] = 0x434,
+	[LDMLSR] = 0x438,
+	[LDHCNR] = 0x448,
+	[LDHSYNR] = 0x44c,
+	[LDVLNR] = 0x450,
+	[LDVSYNR] = 0x454,
+	[LDPMR] = 0x460,
+	[LDHAJR] = 0x4a0,
+};
+
+static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
+	[LDDCKPAT1R] = 0x408,
+	[LDDCKPAT2R] = 0x40c,
+	[LDMT1R] = 0x600,
+	[LDMT2R] = 0x604,
+	[LDMT3R] = 0x608,
+	[LDDFR] = 0x60c,
+	[LDSM1R] = 0x610,
+	[LDSM2R] = 0x614,
+	[LDSA1R] = 0x618,
+	[LDMLSR] = 0x620,
+	[LDHCNR] = 0x624,
+	[LDHSYNR] = 0x628,
+	[LDVLNR] = 0x62c,
+	[LDVSYNR] = 0x630,
+	[LDPMR] = 0x63c,
+};
+
+static bool banked(int reg_nr)
+{
+	switch (reg_nr) {
+	case LDMT1R:
+	case LDMT2R:
+	case LDMT3R:
+	case LDDFR:
+	case LDSM1R:
+	case LDSA1R:
+	case LDSA2R:
+	case LDMLSR:
+	case LDHCNR:
+	case LDHSYNR:
+	case LDVLNR:
+	case LDVSYNR:
+		return true;
+	}
+	return false;
+}
+
+static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
+{
+	return chan->cfg->chan == LCDC_CHAN_SUBLCD;
+}
+
+static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
+			    int reg_nr, unsigned long data)
+{
+	iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
+	if (banked(reg_nr))
+		iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
+			  SIDE_B_OFFSET);
+}
+
+static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan,
+			    int reg_nr, unsigned long data)
+{
+	iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
+		  MIRROR_OFFSET);
+}
+
+static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
+				    int reg_nr)
+{
+	return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
+}
+
+static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl,
+			       int reg, unsigned long data)
+{
+	iowrite32(data, ovl->channel->lcdc->base + reg);
+	iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET);
+}
+
+static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
+		       unsigned long reg_offs, unsigned long data)
+{
+	iowrite32(data, priv->base + reg_offs);
+}
+
+static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
+			       unsigned long reg_offs)
+{
+	return ioread32(priv->base + reg_offs);
+}
+
+static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
+			  unsigned long reg_offs,
+			  unsigned long mask, unsigned long until)
+{
+	while ((lcdc_read(priv, reg_offs) & mask) != until)
+		cpu_relax();
+}
+
+/* -----------------------------------------------------------------------------
+ * Clock management
+ */
+
+static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
+{
+	if (atomic_inc_and_test(&priv->hw_usecnt)) {
+		if (priv->dot_clk)
+			clk_prepare_enable(priv->dot_clk);
+		pm_runtime_get_sync(priv->dev);
+		if (priv->meram_dev && priv->meram_dev->pdev)
+			pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
+	}
+}
+
+static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
+{
+	if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
+		if (priv->meram_dev && priv->meram_dev->pdev)
+			pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
+		pm_runtime_put(priv->dev);
+		if (priv->dot_clk)
+			clk_disable_unprepare(priv->dot_clk);
+	}
+}
+
+static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
+				       int clock_source)
+{
+	struct clk *clk;
+	char *str;
+
+	switch (clock_source) {
+	case LCDC_CLK_BUS:
+		str = "bus_clk";
+		priv->lddckr = LDDCKR_ICKSEL_BUS;
+		break;
+	case LCDC_CLK_PERIPHERAL:
+		str = "peripheral_clk";
+		priv->lddckr = LDDCKR_ICKSEL_MIPI;
+		break;
+	case LCDC_CLK_EXTERNAL:
+		str = NULL;
+		priv->lddckr = LDDCKR_ICKSEL_HDMI;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (str == NULL)
+		return 0;
+
+	clk = clk_get(priv->dev, str);
+	if (IS_ERR(clk)) {
+		dev_err(priv->dev, "cannot get dot clock %s\n", str);
+		return PTR_ERR(clk);
+	}
+
+	priv->dot_clk = clk;
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Display, panel and deferred I/O
+ */
+
+static void lcdc_sys_write_index(void *handle, unsigned long data)
+{
+	struct sh_mobile_lcdc_chan *ch = handle;
+
+	lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+	lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
+		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+}
+
+static void lcdc_sys_write_data(void *handle, unsigned long data)
+{
+	struct sh_mobile_lcdc_chan *ch = handle;
+
+	lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+	lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
+		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+}
+
+static unsigned long lcdc_sys_read_data(void *handle)
+{
+	struct sh_mobile_lcdc_chan *ch = handle;
+
+	lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+	lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
+		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	udelay(1);
+	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+
+	return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
+}
+
+static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+	lcdc_sys_write_index,
+	lcdc_sys_write_data,
+	lcdc_sys_read_data,
+};
+
+static int sh_mobile_lcdc_sginit(struct fb_info *info,
+				  struct list_head *pagelist)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
+	struct page *page;
+	int nr_pages = 0;
+
+	sg_init_table(ch->sglist, nr_pages_max);
+
+	list_for_each_entry(page, pagelist, lru)
+		sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
+
+	return nr_pages;
+}
+
+static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
+				       struct list_head *pagelist)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
+
+	/* enable clocks before accessing hardware */
+	sh_mobile_lcdc_clk_on(ch->lcdc);
+
+	/*
+	 * It's possible to get here without anything on the pagelist via
+	 * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
+	 * invocation. In the former case, the acceleration routines are
+	 * stepped in to when using the framebuffer console causing the
+	 * workqueue to be scheduled without any dirty pages on the list.
+	 *
+	 * Despite this, a panel update is still needed given that the
+	 * acceleration routines have their own methods for writing in
+	 * that still need to be updated.
+	 *
+	 * The fsync() and empty pagelist case could be optimized for,
+	 * but we don't bother, as any application exhibiting such
+	 * behaviour is fundamentally broken anyways.
+	 */
+	if (!list_empty(pagelist)) {
+		unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
+
+		/* trigger panel update */
+		dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
+		if (panel->start_transfer)
+			panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
+		lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
+		dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages,
+			     DMA_TO_DEVICE);
+	} else {
+		if (panel->start_transfer)
+			panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
+		lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
+	}
+}
+
+static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
+{
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+
+	if (fbdefio)
+		schedule_delayed_work(&info->deferred_work, fbdefio->delay);
+}
+
+static void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch)
+{
+	const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
+
+	if (ch->tx_dev) {
+		int ret;
+
+		ret = ch->tx_dev->ops->display_on(ch->tx_dev);
+		if (ret < 0)
+			return;
+
+		if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED)
+			ch->info->state = FBINFO_STATE_SUSPENDED;
+	}
+
+	/* HDMI must be enabled before LCDC configuration */
+	if (panel->display_on)
+		panel->display_on();
+}
+
+static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
+{
+	const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
+
+	if (panel->display_off)
+		panel->display_off();
+
+	if (ch->tx_dev)
+		ch->tx_dev->ops->display_off(ch->tx_dev);
+}
+
+static bool
+sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
+				const struct fb_videomode *new_mode)
+{
+	dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
+		ch->display.mode.xres, ch->display.mode.yres,
+		new_mode->xres, new_mode->yres);
+
+	/* It can be a different monitor with an equal video-mode */
+	if (fb_mode_is_equal(&ch->display.mode, new_mode))
+		return false;
+
+	dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
+		ch->display.mode.yres, new_mode->yres);
+	ch->display.mode = *new_mode;
+
+	return true;
+}
+
+static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
+				    struct fb_info *info);
+
+static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
+					 enum sh_mobile_lcdc_entity_event event,
+					 const struct fb_videomode *mode,
+					 const struct fb_monspecs *monspec)
+{
+	struct fb_info *info = ch->info;
+	struct fb_var_screeninfo var;
+	int ret = 0;
+
+	switch (event) {
+	case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
+		/* HDMI plug in */
+		console_lock();
+		if (lock_fb_info(info)) {
+
+
+			ch->display.width = monspec->max_x * 10;
+			ch->display.height = monspec->max_y * 10;
+
+			if (!sh_mobile_lcdc_must_reconfigure(ch, mode) &&
+			    info->state == FBINFO_STATE_RUNNING) {
+				/* First activation with the default monitor.
+				 * Just turn on, if we run a resume here, the
+				 * logo disappears.
+				 */
+				info->var.width = ch->display.width;
+				info->var.height = ch->display.height;
+				sh_mobile_lcdc_display_on(ch);
+			} else {
+				/* New monitor or have to wake up */
+				fb_set_suspend(info, 0);
+			}
+
+
+			unlock_fb_info(info);
+		}
+		console_unlock();
+		break;
+
+	case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
+		/* HDMI disconnect */
+		console_lock();
+		if (lock_fb_info(info)) {
+			fb_set_suspend(info, 1);
+			unlock_fb_info(info);
+		}
+		console_unlock();
+		break;
+
+	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
+		/* Validate a proposed new mode */
+		fb_videomode_to_var(&var, mode);
+		var.bits_per_pixel = info->var.bits_per_pixel;
+		var.grayscale = info->var.grayscale;
+		ret = sh_mobile_lcdc_check_var(&var, info);
+		break;
+	}
+
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+struct sh_mobile_lcdc_format_info {
+	u32 fourcc;
+	unsigned int bpp;
+	bool yuv;
+	u32 lddfr;
+};
+
+static const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_RGB565,
+		.bpp = 16,
+		.yuv = false,
+		.lddfr = LDDFR_PKF_RGB16,
+	}, {
+		.fourcc = V4L2_PIX_FMT_BGR24,
+		.bpp = 24,
+		.yuv = false,
+		.lddfr = LDDFR_PKF_RGB24,
+	}, {
+		.fourcc = V4L2_PIX_FMT_BGR32,
+		.bpp = 32,
+		.yuv = false,
+		.lddfr = LDDFR_PKF_ARGB32,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.bpp = 12,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_420,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.bpp = 12,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_420,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV16,
+		.bpp = 16,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV61,
+		.bpp = 16,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_422,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV24,
+		.bpp = 24,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_444,
+	}, {
+		.fourcc = V4L2_PIX_FMT_NV42,
+		.bpp = 24,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_444,
+	},
+};
+
+static const struct sh_mobile_lcdc_format_info *
+sh_mobile_format_info(u32 fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) {
+		if (sh_mobile_format_infos[i].fourcc == fourcc)
+			return &sh_mobile_format_infos[i];
+	}
+
+	return NULL;
+}
+
+static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
+{
+	if (var->grayscale > 1)
+		return var->grayscale;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		return V4L2_PIX_FMT_RGB565;
+	case 24:
+		return V4L2_PIX_FMT_BGR24;
+	case 32:
+		return V4L2_PIX_FMT_BGR32;
+	default:
+		return 0;
+	}
+}
+
+static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
+{
+	return var->grayscale > 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Start, stop and IRQ
+ */
+
+static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
+{
+	struct sh_mobile_lcdc_priv *priv = data;
+	struct sh_mobile_lcdc_chan *ch;
+	unsigned long ldintr;
+	int is_sub;
+	int k;
+
+	/* Acknowledge interrupts and disable further VSYNC End IRQs. */
+	ldintr = lcdc_read(priv, _LDINTR);
+	lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
+
+	/* figure out if this interrupt is for main or sub lcd */
+	is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
+
+	/* wake up channel and disable clocks */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		ch = &priv->ch[k];
+
+		if (!ch->enabled)
+			continue;
+
+		/* Frame End */
+		if (ldintr & LDINTR_FS) {
+			if (is_sub == lcdc_chan_is_sublcd(ch)) {
+				ch->frame_end = 1;
+				wake_up(&ch->frame_end_wait);
+
+				sh_mobile_lcdc_clk_off(priv);
+			}
+		}
+
+		/* VSYNC End */
+		if (ldintr & LDINTR_VES)
+			complete(&ch->vsync_completion);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
+{
+	unsigned long ldintr;
+	int ret;
+
+	/* Enable VSync End interrupt and be careful not to acknowledge any
+	 * pending interrupt.
+	 */
+	ldintr = lcdc_read(ch->lcdc, _LDINTR);
+	ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
+	lcdc_write(ch->lcdc, _LDINTR, ldintr);
+
+	ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
+							msecs_to_jiffies(100));
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
+				      int start)
+{
+	unsigned long tmp = lcdc_read(priv, _LDCNT2R);
+	int k;
+
+	/* start or stop the lcdc */
+	if (start)
+		lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
+	else
+		lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
+
+	/* wait until power is applied/stopped on all channels */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
+		if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
+			while (1) {
+				tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
+				    & LDPMR_LPS;
+				if (start && tmp == LDPMR_LPS)
+					break;
+				if (!start && tmp == 0)
+					break;
+				cpu_relax();
+			}
+
+	if (!start)
+		lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
+}
+
+static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
+{
+	const struct fb_var_screeninfo *var = &ch->info->var;
+	const struct fb_videomode *mode = &ch->display.mode;
+	unsigned long h_total, hsync_pos, display_h_total;
+	u32 tmp;
+
+	tmp = ch->ldmt1r_value;
+	tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
+	tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
+	tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
+	tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
+	tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
+	tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
+	tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
+	lcdc_write_chan(ch, LDMT1R, tmp);
+
+	/* setup SYS bus */
+	lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r);
+	lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r);
+
+	/* horizontal configuration */
+	h_total = mode->xres + mode->hsync_len + mode->left_margin
+		+ mode->right_margin;
+	tmp = h_total / 8; /* HTCN */
+	tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
+	lcdc_write_chan(ch, LDHCNR, tmp);
+
+	hsync_pos = mode->xres + mode->right_margin;
+	tmp = hsync_pos / 8; /* HSYNP */
+	tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */
+	lcdc_write_chan(ch, LDHSYNR, tmp);
+
+	/* vertical configuration */
+	tmp = mode->yres + mode->vsync_len + mode->upper_margin
+	    + mode->lower_margin; /* VTLN */
+	tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
+	lcdc_write_chan(ch, LDVLNR, tmp);
+
+	tmp = mode->yres + mode->lower_margin; /* VSYNP */
+	tmp |= mode->vsync_len << 16; /* VSYNW */
+	lcdc_write_chan(ch, LDVSYNR, tmp);
+
+	/* Adjust horizontal synchronisation for HDMI */
+	display_h_total = mode->xres + mode->hsync_len + mode->left_margin
+			+ mode->right_margin;
+	tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
+	    | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
+	lcdc_write_chan(ch, LDHAJR, tmp);
+	lcdc_write_chan_mirror(ch, LDHAJR, tmp);
+}
+
+static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
+{
+	u32 format = 0;
+
+	if (!ovl->enabled) {
+		lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
+		lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0);
+		lcdc_write(ovl->channel->lcdc, LDBCR,
+			   LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
+		return;
+	}
+
+	ovl->base_addr_y = ovl->dma_handle;
+	ovl->base_addr_c = ovl->dma_handle
+			 + ovl->xres_virtual * ovl->yres_virtual;
+
+	switch (ovl->mode) {
+	case LCDC_OVERLAY_BLEND:
+		format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT);
+		break;
+
+	case LCDC_OVERLAY_ROP3:
+		format = LDBBSIFR_EN | LDBBSIFR_BRSEL
+		       | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT);
+		break;
+	}
+
+	switch (ovl->format->fourcc) {
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_NV21:
+	case V4L2_PIX_FMT_NV61:
+	case V4L2_PIX_FMT_NV42:
+		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
+		break;
+	case V4L2_PIX_FMT_BGR24:
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV24:
+		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
+		break;
+	case V4L2_PIX_FMT_BGR32:
+	default:
+		format |= LDBBSIFR_SWPL;
+		break;
+	}
+
+	switch (ovl->format->fourcc) {
+	case V4L2_PIX_FMT_RGB565:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
+		break;
+	case V4L2_PIX_FMT_BGR24:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
+		break;
+	case V4L2_PIX_FMT_BGR32:
+		format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
+		break;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
+		break;
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV61:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
+		break;
+	case V4L2_PIX_FMT_NV24:
+	case V4L2_PIX_FMT_NV42:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
+		break;
+	}
+
+	lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
+
+	lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format);
+
+	lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index),
+		(ovl->yres << LDBBSSZR_BVSS_SHIFT) |
+		(ovl->xres << LDBBSSZR_BHSS_SHIFT));
+	lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index),
+		(ovl->pos_y << LDBBLOCR_CVLC_SHIFT) |
+		(ovl->pos_x << LDBBLOCR_CHLC_SHIFT));
+	lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index),
+		ovl->pitch << LDBBSMWR_BSMW_SHIFT);
+
+	lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
+	lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
+
+	lcdc_write(ovl->channel->lcdc, LDBCR,
+		   LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
+}
+
+/*
+ * __sh_mobile_lcdc_start - Configure and start the LCDC
+ * @priv: LCDC device
+ *
+ * Configure all enabled channels and start the LCDC device. All external
+ * devices (clocks, MERAM, panels, ...) are not touched by this function.
+ */
+static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+{
+	struct sh_mobile_lcdc_chan *ch;
+	unsigned long tmp;
+	int k, m;
+
+	/* Enable LCDC channels. Read data from external memory, avoid using the
+	 * BEU for now.
+	 */
+	lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
+
+	/* Stop the LCDC first and disable all interrupts. */
+	sh_mobile_lcdc_start_stop(priv, 0);
+	lcdc_write(priv, _LDINTR, 0);
+
+	/* Configure power supply, dot clocks and start them. */
+	tmp = priv->lddckr;
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		ch = &priv->ch[k];
+		if (!ch->enabled)
+			continue;
+
+		/* Power supply */
+		lcdc_write_chan(ch, LDPMR, 0);
+
+		m = ch->cfg->clock_divider;
+		if (!m)
+			continue;
+
+		/* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
+		 * denominator.
+		 */
+		lcdc_write_chan(ch, LDDCKPAT1R, 0);
+		lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
+
+		if (m == 1)
+			m = LDDCKR_MOSEL;
+		tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
+	}
+
+	lcdc_write(priv, _LDDCKR, tmp);
+	lcdc_write(priv, _LDDCKSTPR, 0);
+	lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
+
+	/* Setup geometry, format, frame buffer memory and operation mode. */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		ch = &priv->ch[k];
+		if (!ch->enabled)
+			continue;
+
+		sh_mobile_lcdc_geometry(ch);
+
+		tmp = ch->format->lddfr;
+
+		if (ch->format->yuv) {
+			switch (ch->colorspace) {
+			case V4L2_COLORSPACE_REC709:
+				tmp |= LDDFR_CF1;
+				break;
+			case V4L2_COLORSPACE_JPEG:
+				tmp |= LDDFR_CF0;
+				break;
+			}
+		}
+
+		lcdc_write_chan(ch, LDDFR, tmp);
+		lcdc_write_chan(ch, LDMLSR, ch->line_size);
+		lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
+		if (ch->format->yuv)
+			lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
+
+		/* When using deferred I/O mode, configure the LCDC for one-shot
+		 * operation and enable the frame end interrupt. Otherwise use
+		 * continuous read mode.
+		 */
+		if (ch->ldmt1r_value & LDMT1R_IFM &&
+		    ch->cfg->sys_bus_cfg.deferred_io_msec) {
+			lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
+			lcdc_write(priv, _LDINTR, LDINTR_FE);
+		} else {
+			lcdc_write_chan(ch, LDSM1R, 0);
+		}
+	}
+
+	/* Word and long word swap. */
+	switch (priv->ch[0].format->fourcc) {
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_NV21:
+	case V4L2_PIX_FMT_NV61:
+	case V4L2_PIX_FMT_NV42:
+		tmp = LDDDSR_LS | LDDDSR_WS;
+		break;
+	case V4L2_PIX_FMT_BGR24:
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV24:
+		tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
+		break;
+	case V4L2_PIX_FMT_BGR32:
+	default:
+		tmp = LDDDSR_LS;
+		break;
+	}
+	lcdc_write(priv, _LDDDSR, tmp);
+
+	/* Enable the display output. */
+	lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
+	sh_mobile_lcdc_start_stop(priv, 1);
+	priv->started = 1;
+}
+
+static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+{
+	struct sh_mobile_meram_info *mdev = priv->meram_dev;
+	struct sh_mobile_lcdc_chan *ch;
+	unsigned long tmp;
+	int ret;
+	int k;
+
+	/* enable clocks before accessing the hardware */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		if (priv->ch[k].enabled)
+			sh_mobile_lcdc_clk_on(priv);
+	}
+
+	/* reset */
+	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
+	lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
+
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		const struct sh_mobile_lcdc_panel_cfg *panel;
+
+		ch = &priv->ch[k];
+		if (!ch->enabled)
+			continue;
+
+		panel = &ch->cfg->panel_cfg;
+		if (panel->setup_sys) {
+			ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* Compute frame buffer base address and pitch for each channel. */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		int pixelformat;
+		void *cache;
+
+		ch = &priv->ch[k];
+		if (!ch->enabled)
+			continue;
+
+		ch->base_addr_y = ch->dma_handle;
+		ch->base_addr_c = ch->dma_handle
+				+ ch->xres_virtual * ch->yres_virtual;
+		ch->line_size = ch->pitch;
+
+		/* Enable MERAM if possible. */
+		if (mdev == NULL || ch->cfg->meram_cfg == NULL)
+			continue;
+
+		/* Free the allocated MERAM cache. */
+		if (ch->cache) {
+			sh_mobile_meram_cache_free(mdev, ch->cache);
+			ch->cache = NULL;
+		}
+
+		switch (ch->format->fourcc) {
+		case V4L2_PIX_FMT_NV12:
+		case V4L2_PIX_FMT_NV21:
+		case V4L2_PIX_FMT_NV16:
+		case V4L2_PIX_FMT_NV61:
+			pixelformat = SH_MOBILE_MERAM_PF_NV;
+			break;
+		case V4L2_PIX_FMT_NV24:
+		case V4L2_PIX_FMT_NV42:
+			pixelformat = SH_MOBILE_MERAM_PF_NV24;
+			break;
+		case V4L2_PIX_FMT_RGB565:
+		case V4L2_PIX_FMT_BGR24:
+		case V4L2_PIX_FMT_BGR32:
+		default:
+			pixelformat = SH_MOBILE_MERAM_PF_RGB;
+			break;
+		}
+
+		cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
+					ch->pitch, ch->yres, pixelformat,
+					&ch->line_size);
+		if (!IS_ERR(cache)) {
+			sh_mobile_meram_cache_update(mdev, cache,
+					ch->base_addr_y, ch->base_addr_c,
+					&ch->base_addr_y, &ch->base_addr_c);
+			ch->cache = cache;
+		}
+	}
+
+	for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) {
+		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k];
+		sh_mobile_lcdc_overlay_setup(ovl);
+	}
+
+	/* Start the LCDC. */
+	__sh_mobile_lcdc_start(priv);
+
+	/* Setup deferred I/O, tell the board code to enable the panels, and
+	 * turn backlight on.
+	 */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		ch = &priv->ch[k];
+		if (!ch->enabled)
+			continue;
+
+		tmp = ch->cfg->sys_bus_cfg.deferred_io_msec;
+		if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
+			ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
+			ch->defio.delay = msecs_to_jiffies(tmp);
+			ch->info->fbdefio = &ch->defio;
+			fb_deferred_io_init(ch->info);
+		}
+
+		sh_mobile_lcdc_display_on(ch);
+
+		if (ch->bl) {
+			ch->bl->props.power = FB_BLANK_UNBLANK;
+			backlight_update_status(ch->bl);
+		}
+	}
+
+	return 0;
+}
+
+static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
+{
+	struct sh_mobile_lcdc_chan *ch;
+	int k;
+
+	/* clean up deferred io and ask board code to disable panel */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		ch = &priv->ch[k];
+		if (!ch->enabled)
+			continue;
+
+		/* deferred io mode:
+		 * flush frame, and wait for frame end interrupt
+		 * clean up deferred io and enable clock
+		 */
+		if (ch->info && ch->info->fbdefio) {
+			ch->frame_end = 0;
+			schedule_delayed_work(&ch->info->deferred_work, 0);
+			wait_event(ch->frame_end_wait, ch->frame_end);
+			fb_deferred_io_cleanup(ch->info);
+			ch->info->fbdefio = NULL;
+			sh_mobile_lcdc_clk_on(priv);
+		}
+
+		if (ch->bl) {
+			ch->bl->props.power = FB_BLANK_POWERDOWN;
+			backlight_update_status(ch->bl);
+		}
+
+		sh_mobile_lcdc_display_off(ch);
+
+		/* Free the MERAM cache. */
+		if (ch->cache) {
+			sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
+			ch->cache = NULL;
+		}
+
+	}
+
+	/* stop the lcdc */
+	if (priv->started) {
+		sh_mobile_lcdc_start_stop(priv, 0);
+		priv->started = 0;
+	}
+
+	/* stop clocks */
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
+		if (priv->ch[k].enabled)
+			sh_mobile_lcdc_clk_off(priv);
+}
+
+static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
+				      struct fb_info *info)
+{
+	if (var->xres > MAX_XRES || var->yres > MAX_YRES)
+		return -EINVAL;
+
+	/* Make sure the virtual resolution is at least as big as the visible
+	 * resolution.
+	 */
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (sh_mobile_format_is_fourcc(var)) {
+		const struct sh_mobile_lcdc_format_info *format;
+
+		format = sh_mobile_format_info(var->grayscale);
+		if (format == NULL)
+			return -EINVAL;
+		var->bits_per_pixel = format->bpp;
+
+		/* Default to RGB and JPEG color-spaces for RGB and YUV formats
+		 * respectively.
+		 */
+		if (!format->yuv)
+			var->colorspace = V4L2_COLORSPACE_SRGB;
+		else if (var->colorspace != V4L2_COLORSPACE_REC709)
+			var->colorspace = V4L2_COLORSPACE_JPEG;
+	} else {
+		if (var->bits_per_pixel <= 16) {		/* RGB 565 */
+			var->bits_per_pixel = 16;
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		} else if (var->bits_per_pixel <= 24) {		/* RGB 888 */
+			var->bits_per_pixel = 24;
+			var->red.offset = 16;
+			var->red.length = 8;
+			var->green.offset = 8;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		} else if (var->bits_per_pixel <= 32) {		/* RGBA 888 */
+			var->bits_per_pixel = 32;
+			var->red.offset = 16;
+			var->red.length = 8;
+			var->green.offset = 8;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 24;
+			var->transp.length = 8;
+		} else
+			return -EINVAL;
+
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		var->transp.msb_right = 0;
+	}
+
+	/* Make sure we don't exceed our allocated memory. */
+	if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
+	    info->fix.smem_len)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Frame buffer operations - Overlays
+ */
+
+static ssize_t
+overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha);
+}
+
+static ssize_t
+overlay_alpha_store(struct device *dev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+	unsigned int alpha;
+	char *endp;
+
+	alpha = simple_strtoul(buf, &endp, 10);
+	if (isspace(*endp))
+		endp++;
+
+	if (endp - buf != count)
+		return -EINVAL;
+
+	if (alpha > 255)
+		return -EINVAL;
+
+	if (ovl->alpha != alpha) {
+		ovl->alpha = alpha;
+
+		if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled)
+			sh_mobile_lcdc_overlay_setup(ovl);
+	}
+
+	return count;
+}
+
+static ssize_t
+overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode);
+}
+
+static ssize_t
+overlay_mode_store(struct device *dev, struct device_attribute *attr,
+		   const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+	unsigned int mode;
+	char *endp;
+
+	mode = simple_strtoul(buf, &endp, 10);
+	if (isspace(*endp))
+		endp++;
+
+	if (endp - buf != count)
+		return -EINVAL;
+
+	if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3)
+		return -EINVAL;
+
+	if (ovl->mode != mode) {
+		ovl->mode = mode;
+
+		if (ovl->enabled)
+			sh_mobile_lcdc_overlay_setup(ovl);
+	}
+
+	return count;
+}
+
+static ssize_t
+overlay_position_show(struct device *dev, struct device_attribute *attr,
+		      char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y);
+}
+
+static ssize_t
+overlay_position_store(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+	char *endp;
+	int pos_x;
+	int pos_y;
+
+	pos_x = simple_strtol(buf, &endp, 10);
+	if (*endp != ',')
+		return -EINVAL;
+
+	pos_y = simple_strtol(endp + 1, &endp, 10);
+	if (isspace(*endp))
+		endp++;
+
+	if (endp - buf != count)
+		return -EINVAL;
+
+	if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) {
+		ovl->pos_x = pos_x;
+		ovl->pos_y = pos_y;
+
+		if (ovl->enabled)
+			sh_mobile_lcdc_overlay_setup(ovl);
+	}
+
+	return count;
+}
+
+static ssize_t
+overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3);
+}
+
+static ssize_t
+overlay_rop3_store(struct device *dev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+	unsigned int rop3;
+	char *endp;
+
+	rop3 = !!simple_strtoul(buf, &endp, 10);
+	if (isspace(*endp))
+		endp++;
+
+	if (endp - buf != count)
+		return -EINVAL;
+
+	if (rop3 > 255)
+		return -EINVAL;
+
+	if (ovl->rop3 != rop3) {
+		ovl->rop3 = rop3;
+
+		if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled)
+			sh_mobile_lcdc_overlay_setup(ovl);
+	}
+
+	return count;
+}
+
+static const struct device_attribute overlay_sysfs_attrs[] = {
+	__ATTR(ovl_alpha, S_IRUGO|S_IWUSR,
+	       overlay_alpha_show, overlay_alpha_store),
+	__ATTR(ovl_mode, S_IRUGO|S_IWUSR,
+	       overlay_mode_show, overlay_mode_store),
+	__ATTR(ovl_position, S_IRUGO|S_IWUSR,
+	       overlay_position_show, overlay_position_store),
+	__ATTR(ovl_rop3, S_IRUGO|S_IWUSR,
+	       overlay_rop3_show, overlay_rop3_store),
+};
+
+static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix  = {
+	.id =		"SH Mobile LCDC",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.capabilities =	FB_CAP_FOURCC,
+};
+
+static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
+				    struct fb_info *info)
+{
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+	unsigned long base_addr_y;
+	unsigned long base_addr_c;
+	unsigned long y_offset;
+	unsigned long c_offset;
+
+	if (!ovl->format->yuv) {
+		y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset)
+			 * ovl->format->bpp / 8;
+		c_offset = 0;
+	} else {
+		unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1;
+		unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1;
+
+		y_offset = var->yoffset * ovl->xres_virtual + var->xoffset;
+		c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub
+			 + var->xoffset * 2 / xsub;
+	}
+
+	/* If the Y offset hasn't changed, the C offset hasn't either. There's
+	 * nothing to do in that case.
+	 */
+	if (y_offset == ovl->pan_y_offset)
+		return 0;
+
+	/* Set the source address for the next refresh */
+	base_addr_y = ovl->dma_handle + y_offset;
+	base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual
+		    + c_offset;
+
+	ovl->base_addr_y = base_addr_y;
+	ovl->base_addr_c = base_addr_c;
+	ovl->pan_y_offset = y_offset;
+
+	lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
+
+	lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
+	lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
+
+	lcdc_write(ovl->channel->lcdc, LDBCR,
+		   LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
+
+	return 0;
+}
+
+static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd,
+				      unsigned long arg)
+{
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		return sh_mobile_lcdc_wait_for_vsync(ovl->channel);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var,
+					  struct fb_info *info)
+{
+	return __sh_mobile_lcdc_check_var(var, info);
+}
+
+static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
+{
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	ovl->format =
+		sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
+
+	ovl->xres = info->var.xres;
+	ovl->xres_virtual = info->var.xres_virtual;
+	ovl->yres = info->var.yres;
+	ovl->yres_virtual = info->var.yres_virtual;
+
+	if (ovl->format->yuv)
+		ovl->pitch = info->var.xres_virtual;
+	else
+		ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8;
+
+	sh_mobile_lcdc_overlay_setup(ovl);
+
+	info->fix.line_length = ovl->pitch;
+
+	if (sh_mobile_format_is_fourcc(&info->var)) {
+		info->fix.type = FB_TYPE_FOURCC;
+		info->fix.visual = FB_VISUAL_FOURCC;
+	} else {
+		info->fix.type = FB_TYPE_PACKED_PIXELS;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	}
+
+	return 0;
+}
+
+/* Overlay blanking. Disable the overlay when blanked. */
+static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
+{
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	ovl->enabled = !blank;
+	sh_mobile_lcdc_overlay_setup(ovl);
+
+	/* Prevent the backlight from receiving a blanking event by returning
+	 * a non-zero value.
+	 */
+	return 1;
+}
+
+static int
+sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
+				 ovl->dma_handle, ovl->fb_size);
+}
+
+static struct fb_ops sh_mobile_lcdc_overlay_ops = {
+	.owner          = THIS_MODULE,
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_blank	= sh_mobile_lcdc_overlay_blank,
+	.fb_pan_display = sh_mobile_lcdc_overlay_pan,
+	.fb_ioctl       = sh_mobile_lcdc_overlay_ioctl,
+	.fb_check_var	= sh_mobile_lcdc_overlay_check_var,
+	.fb_set_par	= sh_mobile_lcdc_overlay_set_par,
+	.fb_mmap	= sh_mobile_lcdc_overlay_mmap,
+};
+
+static void
+sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl)
+{
+	struct fb_info *info = ovl->info;
+
+	if (info == NULL || info->dev == NULL)
+		return;
+
+	unregister_framebuffer(ovl->info);
+}
+
+static int
+sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl)
+{
+	struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc;
+	struct fb_info *info = ovl->info;
+	unsigned int i;
+	int ret;
+
+	if (info == NULL)
+		return 0;
+
+	ret = register_framebuffer(info);
+	if (ret < 0)
+		return ret;
+
+	dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n",
+		 dev_name(lcdc->dev), ovl->index, info->var.xres,
+		 info->var.yres, info->var.bits_per_pixel);
+
+	for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) {
+		ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void
+sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl)
+{
+	struct fb_info *info = ovl->info;
+
+	if (info == NULL || info->device == NULL)
+		return;
+
+	framebuffer_release(info);
+}
+
+static int
+sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
+{
+	struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc;
+	struct fb_var_screeninfo *var;
+	struct fb_info *info;
+
+	/* Allocate and initialize the frame buffer device. */
+	info = framebuffer_alloc(0, priv->dev);
+	if (info == NULL) {
+		dev_err(priv->dev, "unable to allocate fb_info\n");
+		return -ENOMEM;
+	}
+
+	ovl->info = info;
+
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &sh_mobile_lcdc_overlay_ops;
+	info->device = priv->dev;
+	info->screen_base = ovl->fb_mem;
+	info->par = ovl;
+
+	/* Initialize fixed screen information. Restrict pan to 2 lines steps
+	 * for NV12 and NV21.
+	 */
+	info->fix = sh_mobile_lcdc_overlay_fix;
+	snprintf(info->fix.id, sizeof(info->fix.id),
+		 "SH Mobile LCDC Overlay %u", ovl->index);
+	info->fix.smem_start = ovl->dma_handle;
+	info->fix.smem_len = ovl->fb_size;
+	info->fix.line_length = ovl->pitch;
+
+	if (ovl->format->yuv)
+		info->fix.visual = FB_VISUAL_FOURCC;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	switch (ovl->format->fourcc) {
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		info->fix.ypanstep = 2;
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV61:
+		info->fix.xpanstep = 2;
+	}
+
+	/* Initialize variable screen information. */
+	var = &info->var;
+	memset(var, 0, sizeof(*var));
+	var->xres = ovl->xres;
+	var->yres = ovl->yres;
+	var->xres_virtual = ovl->xres_virtual;
+	var->yres_virtual = ovl->yres_virtual;
+	var->activate = FB_ACTIVATE_NOW;
+
+	/* Use the legacy API by default for RGB formats, and the FOURCC API
+	 * for YUV formats.
+	 */
+	if (!ovl->format->yuv)
+		var->bits_per_pixel = ovl->format->bpp;
+	else
+		var->grayscale = ovl->format->fourcc;
+
+	return sh_mobile_lcdc_overlay_check_var(var, info);
+}
+
+/* -----------------------------------------------------------------------------
+ * Frame buffer operations - main frame buffer
+ */
+
+static int sh_mobile_lcdc_setcolreg(u_int regno,
+				    u_int red, u_int green, u_int blue,
+				    u_int transp, struct fb_info *info)
+{
+	u32 *palette = info->pseudo_palette;
+
+	if (regno >= PALETTE_NR)
+		return -EINVAL;
+
+	/* only FB_VISUAL_TRUECOLOR supported */
+
+	red >>= 16 - info->var.red.length;
+	green >>= 16 - info->var.green.length;
+	blue >>= 16 - info->var.blue.length;
+	transp >>= 16 - info->var.transp.length;
+
+	palette[regno] = (red << info->var.red.offset) |
+	  (green << info->var.green.offset) |
+	  (blue << info->var.blue.offset) |
+	  (transp << info->var.transp.offset);
+
+	return 0;
+}
+
+static const struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
+	.id =		"SH Mobile LCDC",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.capabilities =	FB_CAP_FOURCC,
+};
+
+static void sh_mobile_lcdc_fillrect(struct fb_info *info,
+				    const struct fb_fillrect *rect)
+{
+	sys_fillrect(info, rect);
+	sh_mobile_lcdc_deferred_io_touch(info);
+}
+
+static void sh_mobile_lcdc_copyarea(struct fb_info *info,
+				    const struct fb_copyarea *area)
+{
+	sys_copyarea(info, area);
+	sh_mobile_lcdc_deferred_io_touch(info);
+}
+
+static void sh_mobile_lcdc_imageblit(struct fb_info *info,
+				     const struct fb_image *image)
+{
+	sys_imageblit(info, image);
+	sh_mobile_lcdc_deferred_io_touch(info);
+}
+
+static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
+	unsigned long ldrcntr;
+	unsigned long base_addr_y, base_addr_c;
+	unsigned long y_offset;
+	unsigned long c_offset;
+
+	if (!ch->format->yuv) {
+		y_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
+			 * ch->format->bpp / 8;
+		c_offset = 0;
+	} else {
+		unsigned int xsub = ch->format->bpp < 24 ? 2 : 1;
+		unsigned int ysub = ch->format->bpp < 16 ? 2 : 1;
+
+		y_offset = var->yoffset * ch->xres_virtual + var->xoffset;
+		c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub
+			 + var->xoffset * 2 / xsub;
+	}
+
+	/* If the Y offset hasn't changed, the C offset hasn't either. There's
+	 * nothing to do in that case.
+	 */
+	if (y_offset == ch->pan_y_offset)
+		return 0;
+
+	/* Set the source address for the next refresh */
+	base_addr_y = ch->dma_handle + y_offset;
+	base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
+		    + c_offset;
+
+	if (ch->cache)
+		sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
+					     base_addr_y, base_addr_c,
+					     &base_addr_y, &base_addr_c);
+
+	ch->base_addr_y = base_addr_y;
+	ch->base_addr_c = base_addr_c;
+	ch->pan_y_offset = y_offset;
+
+	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
+	if (ch->format->yuv)
+		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
+
+	ldrcntr = lcdc_read(priv, _LDRCNTR);
+	if (lcdc_chan_is_sublcd(ch))
+		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
+	else
+		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
+
+
+	sh_mobile_lcdc_deferred_io_touch(info);
+
+	return 0;
+}
+
+static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd,
+				unsigned long arg)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	int retval;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		retval = sh_mobile_lcdc_wait_for_vsync(ch);
+		break;
+
+	default:
+		retval = -ENOIOCTLCMD;
+		break;
+	}
+	return retval;
+}
+
+static void sh_mobile_fb_reconfig(struct fb_info *info)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	struct fb_var_screeninfo var;
+	struct fb_videomode mode;
+	struct fb_event event;
+	int evnt = FB_EVENT_MODE_CHANGE_ALL;
+
+	if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
+		/* More framebuffer users are active */
+		return;
+
+	fb_var_to_videomode(&mode, &info->var);
+
+	if (fb_mode_is_equal(&ch->display.mode, &mode))
+		return;
+
+	/* Display has been re-plugged, framebuffer is free now, reconfigure */
+	var = info->var;
+	fb_videomode_to_var(&var, &ch->display.mode);
+	var.width = ch->display.width;
+	var.height = ch->display.height;
+	var.activate = FB_ACTIVATE_NOW;
+
+	if (fb_set_var(info, &var) < 0)
+		/* Couldn't reconfigure, hopefully, can continue as before */
+		return;
+
+	/*
+	 * fb_set_var() calls the notifier change internally, only if
+	 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
+	 * user event, we have to call the chain ourselves.
+	 */
+	event.info = info;
+	event.data = &ch->display.mode;
+	fb_notifier_call_chain(evnt, &event);
+}
+
+/*
+ * Locking: both .fb_release() and .fb_open() are called with info->lock held if
+ * user == 1, or with console sem held, if user == 0.
+ */
+static int sh_mobile_lcdc_release(struct fb_info *info, int user)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+
+	mutex_lock(&ch->open_lock);
+	dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
+
+	ch->use_count--;
+
+	/* Nothing to reconfigure, when called from fbcon */
+	if (user) {
+		console_lock();
+		sh_mobile_fb_reconfig(info);
+		console_unlock();
+	}
+
+	mutex_unlock(&ch->open_lock);
+
+	return 0;
+}
+
+static int sh_mobile_lcdc_open(struct fb_info *info, int user)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+
+	mutex_lock(&ch->open_lock);
+	ch->use_count++;
+
+	dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
+	mutex_unlock(&ch->open_lock);
+
+	return 0;
+}
+
+static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
+				    struct fb_info *info)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	struct sh_mobile_lcdc_priv *p = ch->lcdc;
+	unsigned int best_dist = (unsigned int)-1;
+	unsigned int best_xres = 0;
+	unsigned int best_yres = 0;
+	unsigned int i;
+	int ret;
+
+	/* If board code provides us with a list of available modes, make sure
+	 * we use one of them. Find the mode closest to the requested one. The
+	 * distance between two modes is defined as the size of the
+	 * non-overlapping parts of the two rectangles.
+	 */
+	for (i = 0; i < ch->cfg->num_modes; ++i) {
+		const struct fb_videomode *mode = &ch->cfg->lcd_modes[i];
+		unsigned int dist;
+
+		/* We can only round up. */
+		if (var->xres > mode->xres || var->yres > mode->yres)
+			continue;
+
+		dist = var->xres * var->yres + mode->xres * mode->yres
+		     - 2 * min(var->xres, mode->xres)
+			 * min(var->yres, mode->yres);
+
+		if (dist < best_dist) {
+			best_xres = mode->xres;
+			best_yres = mode->yres;
+			best_dist = dist;
+		}
+	}
+
+	/* If no available mode can be used, return an error. */
+	if (ch->cfg->num_modes != 0) {
+		if (best_dist == (unsigned int)-1)
+			return -EINVAL;
+
+		var->xres = best_xres;
+		var->yres = best_yres;
+	}
+
+	ret = __sh_mobile_lcdc_check_var(var, info);
+	if (ret < 0)
+		return ret;
+
+	/* only accept the forced_fourcc for dual channel configurations */
+	if (p->forced_fourcc &&
+	    p->forced_fourcc != sh_mobile_format_fourcc(var))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sh_mobile_lcdc_set_par(struct fb_info *info)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	int ret;
+
+	sh_mobile_lcdc_stop(ch->lcdc);
+
+	ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
+	ch->colorspace = info->var.colorspace;
+
+	ch->xres = info->var.xres;
+	ch->xres_virtual = info->var.xres_virtual;
+	ch->yres = info->var.yres;
+	ch->yres_virtual = info->var.yres_virtual;
+
+	if (ch->format->yuv)
+		ch->pitch = info->var.xres_virtual;
+	else
+		ch->pitch = info->var.xres_virtual * ch->format->bpp / 8;
+
+	ret = sh_mobile_lcdc_start(ch->lcdc);
+	if (ret < 0)
+		dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
+
+	info->fix.line_length = ch->pitch;
+
+	if (sh_mobile_format_is_fourcc(&info->var)) {
+		info->fix.type = FB_TYPE_FOURCC;
+		info->fix.visual = FB_VISUAL_FOURCC;
+	} else {
+		info->fix.type = FB_TYPE_PACKED_PIXELS;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	}
+
+	return ret;
+}
+
+/*
+ * Screen blanking. Behavior is as follows:
+ * FB_BLANK_UNBLANK: screen unblanked, clocks enabled
+ * FB_BLANK_NORMAL: screen blanked, clocks enabled
+ * FB_BLANK_VSYNC,
+ * FB_BLANK_HSYNC,
+ * FB_BLANK_POWEROFF: screen blanked, clocks disabled
+ */
+static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	struct sh_mobile_lcdc_priv *p = ch->lcdc;
+
+	/* blank the screen? */
+	if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
+		struct fb_fillrect rect = {
+			.width = ch->xres,
+			.height = ch->yres,
+		};
+		sh_mobile_lcdc_fillrect(info, &rect);
+	}
+	/* turn clocks on? */
+	if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) {
+		sh_mobile_lcdc_clk_on(p);
+	}
+	/* turn clocks off? */
+	if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) {
+		/* make sure the screen is updated with the black fill before
+		 * switching the clocks off. one vsync is not enough since
+		 * blanking may occur in the middle of a refresh. deferred io
+		 * mode will reenable the clocks and update the screen in time,
+		 * so it does not need this. */
+		if (!info->fbdefio) {
+			sh_mobile_lcdc_wait_for_vsync(ch);
+			sh_mobile_lcdc_wait_for_vsync(ch);
+		}
+		sh_mobile_lcdc_clk_off(p);
+	}
+
+	ch->blank_status = blank;
+	return 0;
+}
+
+static int
+sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+
+	return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
+				 ch->dma_handle, ch->fb_size);
+}
+
+static struct fb_ops sh_mobile_lcdc_ops = {
+	.owner          = THIS_MODULE,
+	.fb_setcolreg	= sh_mobile_lcdc_setcolreg,
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_fillrect	= sh_mobile_lcdc_fillrect,
+	.fb_copyarea	= sh_mobile_lcdc_copyarea,
+	.fb_imageblit	= sh_mobile_lcdc_imageblit,
+	.fb_blank	= sh_mobile_lcdc_blank,
+	.fb_pan_display = sh_mobile_lcdc_pan,
+	.fb_ioctl       = sh_mobile_lcdc_ioctl,
+	.fb_open	= sh_mobile_lcdc_open,
+	.fb_release	= sh_mobile_lcdc_release,
+	.fb_check_var	= sh_mobile_lcdc_check_var,
+	.fb_set_par	= sh_mobile_lcdc_set_par,
+	.fb_mmap	= sh_mobile_lcdc_mmap,
+};
+
+static void
+sh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch)
+{
+	if (ch->info && ch->info->dev)
+		unregister_framebuffer(ch->info);
+}
+
+static int
+sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
+{
+	struct fb_info *info = ch->info;
+	int ret;
+
+	if (info->fbdefio) {
+		ch->sglist = vmalloc(sizeof(struct scatterlist) *
+				     ch->fb_size >> PAGE_SHIFT);
+		if (!ch->sglist) {
+			dev_err(ch->lcdc->dev, "cannot allocate sglist\n");
+			return -ENOMEM;
+		}
+	}
+
+	info->bl_dev = ch->bl;
+
+	ret = register_framebuffer(info);
+	if (ret < 0)
+		return ret;
+
+	dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n",
+		 dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ?
+		 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
+		 info->var.bits_per_pixel);
+
+	/* deferred io mode: disable clock to save power */
+	if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
+		sh_mobile_lcdc_clk_off(ch->lcdc);
+
+	return ret;
+}
+
+static void
+sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
+{
+	struct fb_info *info = ch->info;
+
+	if (!info || !info->device)
+		return;
+
+	if (ch->sglist)
+		vfree(ch->sglist);
+
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(info);
+}
+
+static int
+sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
+			       const struct fb_videomode *modes,
+			       unsigned int num_modes)
+{
+	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
+	struct fb_var_screeninfo *var;
+	struct fb_info *info;
+	int ret;
+
+	/* Allocate and initialize the frame buffer device. Create the modes
+	 * list and allocate the color map.
+	 */
+	info = framebuffer_alloc(0, priv->dev);
+	if (info == NULL) {
+		dev_err(priv->dev, "unable to allocate fb_info\n");
+		return -ENOMEM;
+	}
+
+	ch->info = info;
+
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &sh_mobile_lcdc_ops;
+	info->device = priv->dev;
+	info->screen_base = ch->fb_mem;
+	info->pseudo_palette = &ch->pseudo_palette;
+	info->par = ch;
+
+	fb_videomode_to_modelist(modes, num_modes, &info->modelist);
+
+	ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
+	if (ret < 0) {
+		dev_err(priv->dev, "unable to allocate cmap\n");
+		return ret;
+	}
+
+	/* Initialize fixed screen information. Restrict pan to 2 lines steps
+	 * for NV12 and NV21.
+	 */
+	info->fix = sh_mobile_lcdc_fix;
+	info->fix.smem_start = ch->dma_handle;
+	info->fix.smem_len = ch->fb_size;
+	info->fix.line_length = ch->pitch;
+
+	if (ch->format->yuv)
+		info->fix.visual = FB_VISUAL_FOURCC;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	switch (ch->format->fourcc) {
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		info->fix.ypanstep = 2;
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV61:
+		info->fix.xpanstep = 2;
+	}
+
+	/* Initialize variable screen information using the first mode as
+	 * default.
+	 */
+	var = &info->var;
+	fb_videomode_to_var(var, modes);
+	var->width = ch->display.width;
+	var->height = ch->display.height;
+	var->xres_virtual = ch->xres_virtual;
+	var->yres_virtual = ch->yres_virtual;
+	var->activate = FB_ACTIVATE_NOW;
+
+	/* Use the legacy API by default for RGB formats, and the FOURCC API
+	 * for YUV formats.
+	 */
+	if (!ch->format->yuv)
+		var->bits_per_pixel = ch->format->bpp;
+	else
+		var->grayscale = ch->format->fourcc;
+
+	ret = sh_mobile_lcdc_check_var(var, info);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Backlight
+ */
+
+static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
+{
+	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
+	int brightness = bdev->props.brightness;
+
+	if (bdev->props.power != FB_BLANK_UNBLANK ||
+	    bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+		brightness = 0;
+
+	ch->bl_brightness = brightness;
+	return ch->cfg->bl_info.set_brightness(brightness);
+}
+
+static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
+{
+	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
+
+	return ch->bl_brightness;
+}
+
+static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
+				   struct fb_info *info)
+{
+	return (info->bl_dev == bdev);
+}
+
+static struct backlight_ops sh_mobile_lcdc_bl_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= sh_mobile_lcdc_update_bl,
+	.get_brightness	= sh_mobile_lcdc_get_brightness,
+	.check_fb	= sh_mobile_lcdc_check_fb,
+};
+
+static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
+					       struct sh_mobile_lcdc_chan *ch)
+{
+	struct backlight_device *bl;
+
+	bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch,
+				       &sh_mobile_lcdc_bl_ops, NULL);
+	if (IS_ERR(bl)) {
+		dev_err(parent, "unable to register backlight device: %ld\n",
+			PTR_ERR(bl));
+		return NULL;
+	}
+
+	bl->props.max_brightness = ch->cfg->bl_info.max_brightness;
+	bl->props.brightness = bl->props.max_brightness;
+	backlight_update_status(bl);
+
+	return bl;
+}
+
+static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
+{
+	backlight_device_unregister(bdev);
+}
+
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
+static int sh_mobile_lcdc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static int sh_mobile_lcdc_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
+}
+
+static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+
+	/* turn off LCDC hardware */
+	lcdc_write(priv, _LDCNT1R, 0);
+
+	return 0;
+}
+
+static int sh_mobile_lcdc_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+
+	__sh_mobile_lcdc_start(priv);
+
+	return 0;
+}
+
+static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
+	.suspend = sh_mobile_lcdc_suspend,
+	.resume = sh_mobile_lcdc_resume,
+	.runtime_suspend = sh_mobile_lcdc_runtime_suspend,
+	.runtime_resume = sh_mobile_lcdc_runtime_resume,
+};
+
+/* -----------------------------------------------------------------------------
+ * Framebuffer notifier
+ */
+
+/* locking: called with info->lock held */
+static int sh_mobile_lcdc_notify(struct notifier_block *nb,
+				 unsigned long action, void *data)
+{
+	struct fb_event *event = data;
+	struct fb_info *info = event->info;
+	struct sh_mobile_lcdc_chan *ch = info->par;
+
+	if (&ch->lcdc->notifier != nb)
+		return NOTIFY_DONE;
+
+	dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
+		__func__, action, event->data);
+
+	switch(action) {
+	case FB_EVENT_SUSPEND:
+		sh_mobile_lcdc_display_off(ch);
+		sh_mobile_lcdc_stop(ch->lcdc);
+		break;
+	case FB_EVENT_RESUME:
+		mutex_lock(&ch->open_lock);
+		sh_mobile_fb_reconfig(info);
+		mutex_unlock(&ch->open_lock);
+
+		sh_mobile_lcdc_display_on(ch);
+		sh_mobile_lcdc_start(ch->lcdc);
+	}
+
+	return NOTIFY_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Probe/remove and driver init/exit
+ */
+
+static const struct fb_videomode default_720p = {
+	.name = "HDMI 720p",
+	.xres = 1280,
+	.yres = 720,
+
+	.left_margin = 220,
+	.right_margin = 110,
+	.hsync_len = 40,
+
+	.upper_margin = 20,
+	.lower_margin = 5,
+	.vsync_len = 5,
+
+	.pixclock = 13468,
+	.refresh = 60,
+	.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+};
+
+static int sh_mobile_lcdc_remove(struct platform_device *pdev)
+{
+	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+	unsigned int i;
+
+	fb_unregister_client(&priv->notifier);
+
+	for (i = 0; i < ARRAY_SIZE(priv->overlays); i++)
+		sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]);
+	for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
+		sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
+
+	sh_mobile_lcdc_stop(priv);
+
+	for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) {
+		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
+
+		sh_mobile_lcdc_overlay_fb_cleanup(ovl);
+
+		if (ovl->fb_mem)
+			dma_free_coherent(&pdev->dev, ovl->fb_size,
+					  ovl->fb_mem, ovl->dma_handle);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
+
+		if (ch->tx_dev) {
+			ch->tx_dev->lcdc = NULL;
+			module_put(ch->cfg->tx_dev->dev.driver->owner);
+		}
+
+		sh_mobile_lcdc_channel_fb_cleanup(ch);
+
+		if (ch->fb_mem)
+			dma_free_coherent(&pdev->dev, ch->fb_size,
+					  ch->fb_mem, ch->dma_handle);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
+
+		if (ch->bl)
+			sh_mobile_lcdc_bl_remove(ch->bl);
+		mutex_destroy(&ch->open_lock);
+	}
+
+	if (priv->dot_clk) {
+		pm_runtime_disable(&pdev->dev);
+		clk_put(priv->dot_clk);
+	}
+
+	if (priv->base)
+		iounmap(priv->base);
+
+	if (priv->irq)
+		free_irq(priv->irq, priv);
+	kfree(priv);
+	return 0;
+}
+
+static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
+{
+	int interface_type = ch->cfg->interface_type;
+
+	switch (interface_type) {
+	case RGB8:
+	case RGB9:
+	case RGB12A:
+	case RGB12B:
+	case RGB16:
+	case RGB18:
+	case RGB24:
+	case SYS8A:
+	case SYS8B:
+	case SYS8C:
+	case SYS8D:
+	case SYS9:
+	case SYS12:
+	case SYS16A:
+	case SYS16B:
+	case SYS16C:
+	case SYS18:
+	case SYS24:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* SUBLCD only supports SYS interface */
+	if (lcdc_chan_is_sublcd(ch)) {
+		if (!(interface_type & LDMT1R_IFM))
+			return -EINVAL;
+
+		interface_type &= ~LDMT1R_IFM;
+	}
+
+	ch->ldmt1r_value = interface_type;
+	return 0;
+}
+
+static int
+sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
+{
+	const struct sh_mobile_lcdc_format_info *format;
+	struct device *dev = ovl->channel->lcdc->dev;
+	int ret;
+
+	if (ovl->cfg->fourcc == 0)
+		return 0;
+
+	/* Validate the format. */
+	format = sh_mobile_format_info(ovl->cfg->fourcc);
+	if (format == NULL) {
+		dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
+		return -EINVAL;
+	}
+
+	ovl->enabled = false;
+	ovl->mode = LCDC_OVERLAY_BLEND;
+	ovl->alpha = 255;
+	ovl->rop3 = 0;
+	ovl->pos_x = 0;
+	ovl->pos_y = 0;
+
+	/* The default Y virtual resolution is twice the panel size to allow for
+	 * double-buffering.
+	 */
+	ovl->format = format;
+	ovl->xres = ovl->cfg->max_xres;
+	ovl->xres_virtual = ovl->xres;
+	ovl->yres = ovl->cfg->max_yres;
+	ovl->yres_virtual = ovl->yres * 2;
+
+	if (!format->yuv)
+		ovl->pitch = ovl->xres_virtual * format->bpp / 8;
+	else
+		ovl->pitch = ovl->xres_virtual;
+
+	/* Allocate frame buffer memory. */
+	ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
+		       * format->bpp / 8 * 2;
+	ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
+					 GFP_KERNEL);
+	if (!ovl->fb_mem) {
+		dev_err(dev, "unable to allocate buffer\n");
+		return -ENOMEM;
+	}
+
+	ret = sh_mobile_lcdc_overlay_fb_init(ovl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int
+sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
+{
+	const struct sh_mobile_lcdc_format_info *format;
+	const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
+	struct device *dev = ch->lcdc->dev;
+	const struct fb_videomode *max_mode;
+	const struct fb_videomode *mode;
+	unsigned int num_modes;
+	unsigned int max_size;
+	unsigned int i;
+
+	mutex_init(&ch->open_lock);
+	ch->notify = sh_mobile_lcdc_display_notify;
+
+	/* Validate the format. */
+	format = sh_mobile_format_info(cfg->fourcc);
+	if (format == NULL) {
+		dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
+		return -EINVAL;
+	}
+
+	/* Iterate through the modes to validate them and find the highest
+	 * resolution.
+	 */
+	max_mode = NULL;
+	max_size = 0;
+
+	for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) {
+		unsigned int size = mode->yres * mode->xres;
+
+		/* NV12/NV21 buffers must have even number of lines */
+		if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
+		     cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
+			dev_err(dev, "yres must be multiple of 2 for "
+				"YCbCr420 mode.\n");
+			return -EINVAL;
+		}
+
+		if (size > max_size) {
+			max_mode = mode;
+			max_size = size;
+		}
+	}
+
+	if (!max_size)
+		max_size = MAX_XRES * MAX_YRES;
+	else
+		dev_dbg(dev, "Found largest videomode %ux%u\n",
+			max_mode->xres, max_mode->yres);
+
+	if (cfg->lcd_modes == NULL) {
+		mode = &default_720p;
+		num_modes = 1;
+	} else {
+		mode = cfg->lcd_modes;
+		num_modes = cfg->num_modes;
+	}
+
+	/* Use the first mode as default. The default Y virtual resolution is
+	 * twice the panel size to allow for double-buffering.
+	 */
+	ch->format = format;
+	ch->xres = mode->xres;
+	ch->xres_virtual = mode->xres;
+	ch->yres = mode->yres;
+	ch->yres_virtual = mode->yres * 2;
+
+	if (!format->yuv) {
+		ch->colorspace = V4L2_COLORSPACE_SRGB;
+		ch->pitch = ch->xres_virtual * format->bpp / 8;
+	} else {
+		ch->colorspace = V4L2_COLORSPACE_REC709;
+		ch->pitch = ch->xres_virtual;
+	}
+
+	ch->display.width = cfg->panel_cfg.width;
+	ch->display.height = cfg->panel_cfg.height;
+	ch->display.mode = *mode;
+
+	/* Allocate frame buffer memory. */
+	ch->fb_size = max_size * format->bpp / 8 * 2;
+	ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
+					GFP_KERNEL);
+	if (ch->fb_mem == NULL) {
+		dev_err(dev, "unable to allocate buffer\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize the transmitter device if present. */
+	if (cfg->tx_dev) {
+		if (!cfg->tx_dev->dev.driver ||
+		    !try_module_get(cfg->tx_dev->dev.driver->owner)) {
+			dev_warn(dev, "unable to get transmitter device\n");
+			return -EINVAL;
+		}
+		ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
+		ch->tx_dev->lcdc = ch;
+		ch->tx_dev->def_mode = *mode;
+	}
+
+	return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes);
+}
+
+static int sh_mobile_lcdc_probe(struct platform_device *pdev)
+{
+	struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
+	struct sh_mobile_lcdc_priv *priv;
+	struct resource *res;
+	int num_channels;
+	int error;
+	int i;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i = platform_get_irq(pdev, 0);
+	if (!res || i < 0) {
+		dev_err(&pdev->dev, "cannot get platform resources\n");
+		return -ENOENT;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "cannot allocate device data\n");
+		return -ENOMEM;
+	}
+
+	priv->dev = &pdev->dev;
+	priv->meram_dev = pdata->meram_dev;
+	platform_set_drvdata(pdev, priv);
+
+	error = request_irq(i, sh_mobile_lcdc_irq, 0,
+			    dev_name(&pdev->dev), priv);
+	if (error) {
+		dev_err(&pdev->dev, "unable to request irq\n");
+		goto err1;
+	}
+
+	priv->irq = i;
+	atomic_set(&priv->hw_usecnt, -1);
+
+	for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) {
+		struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
+
+		ch->lcdc = priv;
+		ch->cfg = &pdata->ch[i];
+
+		error = sh_mobile_lcdc_check_interface(ch);
+		if (error) {
+			dev_err(&pdev->dev, "unsupported interface type\n");
+			goto err1;
+		}
+		init_waitqueue_head(&ch->frame_end_wait);
+		init_completion(&ch->vsync_completion);
+
+		/* probe the backlight is there is one defined */
+		if (ch->cfg->bl_info.max_brightness)
+			ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
+
+		switch (pdata->ch[i].chan) {
+		case LCDC_CHAN_MAINLCD:
+			ch->enabled = LDCNT2R_ME;
+			ch->reg_offs = lcdc_offs_mainlcd;
+			num_channels++;
+			break;
+		case LCDC_CHAN_SUBLCD:
+			ch->enabled = LDCNT2R_SE;
+			ch->reg_offs = lcdc_offs_sublcd;
+			num_channels++;
+			break;
+		}
+	}
+
+	if (!num_channels) {
+		dev_err(&pdev->dev, "no channels defined\n");
+		error = -EINVAL;
+		goto err1;
+	}
+
+	/* for dual channel LCDC (MAIN + SUB) force shared format setting */
+	if (num_channels == 2)
+		priv->forced_fourcc = pdata->ch[0].fourcc;
+
+	priv->base = ioremap_nocache(res->start, resource_size(res));
+	if (!priv->base)
+		goto err1;
+
+	error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source);
+	if (error) {
+		dev_err(&pdev->dev, "unable to setup clocks\n");
+		goto err1;
+	}
+
+	/* Enable runtime PM. */
+	pm_runtime_enable(&pdev->dev);
+
+	for (i = 0; i < num_channels; i++) {
+		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
+
+		error = sh_mobile_lcdc_channel_init(ch);
+		if (error)
+			goto err1;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
+		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
+
+		ovl->cfg = &pdata->overlays[i];
+		ovl->channel = &priv->ch[0];
+
+		error = sh_mobile_lcdc_overlay_init(ovl);
+		if (error)
+			goto err1;
+	}
+
+	error = sh_mobile_lcdc_start(priv);
+	if (error) {
+		dev_err(&pdev->dev, "unable to start hardware\n");
+		goto err1;
+	}
+
+	for (i = 0; i < num_channels; i++) {
+		struct sh_mobile_lcdc_chan *ch = priv->ch + i;
+
+		error = sh_mobile_lcdc_channel_fb_register(ch);
+		if (error)
+			goto err1;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
+		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
+
+		error = sh_mobile_lcdc_overlay_fb_register(ovl);
+		if (error)
+			goto err1;
+	}
+
+	/* Failure ignored */
+	priv->notifier.notifier_call = sh_mobile_lcdc_notify;
+	fb_register_client(&priv->notifier);
+
+	return 0;
+err1:
+	sh_mobile_lcdc_remove(pdev);
+
+	return error;
+}
+
+static struct platform_driver sh_mobile_lcdc_driver = {
+	.driver		= {
+		.name		= "sh_mobile_lcdc_fb",
+		.owner		= THIS_MODULE,
+		.pm		= &sh_mobile_lcdc_dev_pm_ops,
+	},
+	.probe		= sh_mobile_lcdc_probe,
+	.remove		= sh_mobile_lcdc_remove,
+};
+
+module_platform_driver(sh_mobile_lcdc_driver);
+
+MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.h b/drivers/video/fbdev/sh_mobile_lcdcfb.h
new file mode 100644
index 000000000000..f839adef1d90
--- /dev/null
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.h
@@ -0,0 +1,112 @@
+#ifndef SH_MOBILE_LCDCFB_H
+#define SH_MOBILE_LCDCFB_H
+
+#include <linux/completion.h>
+#include <linux/fb.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+
+/* per-channel registers */
+enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
+       LDSM2R, LDSA1R, LDSA2R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
+       LDHAJR,
+       NR_CH_REGS };
+
+#define PALETTE_NR 16
+
+struct backlight_device;
+struct fb_info;
+struct module;
+struct sh_mobile_lcdc_chan;
+struct sh_mobile_lcdc_entity;
+struct sh_mobile_lcdc_format_info;
+struct sh_mobile_lcdc_priv;
+
+#define SH_MOBILE_LCDC_DISPLAY_DISCONNECTED	0
+#define SH_MOBILE_LCDC_DISPLAY_CONNECTED	1
+
+struct sh_mobile_lcdc_entity_ops {
+	/* Display */
+	int (*display_on)(struct sh_mobile_lcdc_entity *entity);
+	void (*display_off)(struct sh_mobile_lcdc_entity *entity);
+};
+
+enum sh_mobile_lcdc_entity_event {
+	SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
+	SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
+	SH_MOBILE_LCDC_EVENT_DISPLAY_MODE,
+};
+
+struct sh_mobile_lcdc_entity {
+	struct module *owner;
+	const struct sh_mobile_lcdc_entity_ops *ops;
+	struct sh_mobile_lcdc_chan *lcdc;
+	struct fb_videomode def_mode;
+};
+
+/*
+ * struct sh_mobile_lcdc_chan - LCDC display channel
+ *
+ * @pan_y_offset: Panning linear offset in bytes (luma component)
+ * @base_addr_y: Frame buffer viewport base address (luma component)
+ * @base_addr_c: Frame buffer viewport base address (chroma component)
+ * @pitch: Frame buffer line pitch
+ */
+struct sh_mobile_lcdc_chan {
+	struct sh_mobile_lcdc_priv *lcdc;
+	struct sh_mobile_lcdc_entity *tx_dev;
+	const struct sh_mobile_lcdc_chan_cfg *cfg;
+
+	unsigned long *reg_offs;
+	unsigned long ldmt1r_value;
+	unsigned long enabled; /* ME and SE in LDCNT2R */
+	void *cache;
+
+	struct mutex open_lock;		/* protects the use counter */
+	int use_count;
+
+	void *fb_mem;
+	unsigned long fb_size;
+
+	dma_addr_t dma_handle;
+	unsigned long pan_y_offset;
+
+	unsigned long frame_end;
+	wait_queue_head_t frame_end_wait;
+	struct completion vsync_completion;
+
+	const struct sh_mobile_lcdc_format_info *format;
+	u32 colorspace;
+	unsigned int xres;
+	unsigned int xres_virtual;
+	unsigned int yres;
+	unsigned int yres_virtual;
+	unsigned int pitch;
+
+	unsigned long base_addr_y;
+	unsigned long base_addr_c;
+	unsigned int line_size;
+
+	int (*notify)(struct sh_mobile_lcdc_chan *ch,
+		      enum sh_mobile_lcdc_entity_event event,
+		      const struct fb_videomode *mode,
+		      const struct fb_monspecs *monspec);
+
+	/* Backlight */
+	struct backlight_device *bl;
+	unsigned int bl_brightness;
+
+	/* FB */
+	struct fb_info *info;
+	u32 pseudo_palette[PALETTE_NR];
+	struct {
+		unsigned int width;
+		unsigned int height;
+		struct fb_videomode mode;
+	} display;
+	struct fb_deferred_io defio;
+	struct scatterlist *sglist;
+	int blank_status;
+};
+
+#endif
diff --git a/drivers/video/fbdev/sh_mobile_meram.c b/drivers/video/fbdev/sh_mobile_meram.c
new file mode 100644
index 000000000000..a297de5cc859
--- /dev/null
+++ b/drivers/video/fbdev/sh_mobile_meram.c
@@ -0,0 +1,759 @@
+/*
+ * SuperH Mobile MERAM Driver for SuperH Mobile LCDC Driver
+ *
+ * Copyright (c) 2011	Damian Hobson-Garcia <dhobsong@igel.co.jp>
+ *                      Takanari Hayama <taki@igel.co.jp>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include <video/sh_mobile_meram.h>
+
+/* -----------------------------------------------------------------------------
+ * MERAM registers
+ */
+
+#define MEVCR1			0x4
+#define MEVCR1_RST		(1 << 31)
+#define MEVCR1_WD		(1 << 30)
+#define MEVCR1_AMD1		(1 << 29)
+#define MEVCR1_AMD0		(1 << 28)
+#define MEQSEL1			0x40
+#define MEQSEL2			0x44
+
+#define MExxCTL			0x400
+#define MExxCTL_BV		(1 << 31)
+#define MExxCTL_BSZ_SHIFT	28
+#define MExxCTL_MSAR_MASK	(0x7ff << MExxCTL_MSAR_SHIFT)
+#define MExxCTL_MSAR_SHIFT	16
+#define MExxCTL_NXT_MASK	(0x1f << MExxCTL_NXT_SHIFT)
+#define MExxCTL_NXT_SHIFT	11
+#define MExxCTL_WD1		(1 << 10)
+#define MExxCTL_WD0		(1 << 9)
+#define MExxCTL_WS		(1 << 8)
+#define MExxCTL_CB		(1 << 7)
+#define MExxCTL_WBF		(1 << 6)
+#define MExxCTL_WF		(1 << 5)
+#define MExxCTL_RF		(1 << 4)
+#define MExxCTL_CM		(1 << 3)
+#define MExxCTL_MD_READ		(1 << 0)
+#define MExxCTL_MD_WRITE	(2 << 0)
+#define MExxCTL_MD_ICB_WB	(3 << 0)
+#define MExxCTL_MD_ICB		(4 << 0)
+#define MExxCTL_MD_FB		(7 << 0)
+#define MExxCTL_MD_MASK		(7 << 0)
+#define MExxBSIZE		0x404
+#define MExxBSIZE_RCNT_SHIFT	28
+#define MExxBSIZE_YSZM1_SHIFT	16
+#define MExxBSIZE_XSZM1_SHIFT	0
+#define MExxMNCF		0x408
+#define MExxMNCF_KWBNM_SHIFT	28
+#define MExxMNCF_KRBNM_SHIFT	24
+#define MExxMNCF_BNM_SHIFT	16
+#define MExxMNCF_XBV		(1 << 15)
+#define MExxMNCF_CPL_YCBCR444	(1 << 12)
+#define MExxMNCF_CPL_YCBCR420	(2 << 12)
+#define MExxMNCF_CPL_YCBCR422	(3 << 12)
+#define MExxMNCF_CPL_MSK	(3 << 12)
+#define MExxMNCF_BL		(1 << 2)
+#define MExxMNCF_LNM_SHIFT	0
+#define MExxSARA		0x410
+#define MExxSARB		0x414
+#define MExxSBSIZE		0x418
+#define MExxSBSIZE_HDV		(1 << 31)
+#define MExxSBSIZE_HSZ16	(0 << 28)
+#define MExxSBSIZE_HSZ32	(1 << 28)
+#define MExxSBSIZE_HSZ64	(2 << 28)
+#define MExxSBSIZE_HSZ128	(3 << 28)
+#define MExxSBSIZE_SBSIZZ_SHIFT	0
+
+#define MERAM_MExxCTL_VAL(next, addr)	\
+	((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
+	 (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
+#define	MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
+	(((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
+	 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
+	 ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
+
+static const unsigned long common_regs[] = {
+	MEVCR1,
+	MEQSEL1,
+	MEQSEL2,
+};
+#define MERAM_REGS_SIZE ARRAY_SIZE(common_regs)
+
+static const unsigned long icb_regs[] = {
+	MExxCTL,
+	MExxBSIZE,
+	MExxMNCF,
+	MExxSARA,
+	MExxSARB,
+	MExxSBSIZE,
+};
+#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
+
+/*
+ * sh_mobile_meram_icb - MERAM ICB information
+ * @regs: Registers cache
+ * @index: ICB index
+ * @offset: MERAM block offset
+ * @size: MERAM block size in KiB
+ * @cache_unit: Bytes to cache per ICB
+ * @pixelformat: Video pixel format of the data stored in the ICB
+ * @current_reg: Which of Start Address Register A (0) or B (1) is in use
+ */
+struct sh_mobile_meram_icb {
+	unsigned long regs[ICB_REGS_SIZE];
+	unsigned int index;
+	unsigned long offset;
+	unsigned int size;
+
+	unsigned int cache_unit;
+	unsigned int pixelformat;
+	unsigned int current_reg;
+};
+
+#define MERAM_ICB_NUM			32
+
+struct sh_mobile_meram_fb_plane {
+	struct sh_mobile_meram_icb *marker;
+	struct sh_mobile_meram_icb *cache;
+};
+
+struct sh_mobile_meram_fb_cache {
+	unsigned int nplanes;
+	struct sh_mobile_meram_fb_plane planes[2];
+};
+
+/*
+ * sh_mobile_meram_priv - MERAM device
+ * @base: Registers base address
+ * @meram: MERAM physical address
+ * @regs: Registers cache
+ * @lock: Protects used_icb and icbs
+ * @used_icb: Bitmask of used ICBs
+ * @icbs: ICBs
+ * @pool: Allocation pool to manage the MERAM
+ */
+struct sh_mobile_meram_priv {
+	void __iomem *base;
+	unsigned long meram;
+	unsigned long regs[MERAM_REGS_SIZE];
+
+	struct mutex lock;
+	unsigned long used_icb;
+	struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM];
+
+	struct gen_pool *pool;
+};
+
+/* settings */
+#define MERAM_GRANULARITY		1024
+#define MERAM_SEC_LINE			15
+#define MERAM_LINE_WIDTH		2048
+
+/* -----------------------------------------------------------------------------
+ * Registers access
+ */
+
+#define MERAM_ICB_OFFSET(base, idx, off)	((base) + (off) + (idx) * 0x20)
+
+static inline void meram_write_icb(void __iomem *base, unsigned int idx,
+				   unsigned int off, unsigned long val)
+{
+	iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
+}
+
+static inline unsigned long meram_read_icb(void __iomem *base, unsigned int idx,
+					   unsigned int off)
+{
+	return ioread32(MERAM_ICB_OFFSET(base, idx, off));
+}
+
+static inline void meram_write_reg(void __iomem *base, unsigned int off,
+				   unsigned long val)
+{
+	iowrite32(val, base + off);
+}
+
+static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
+{
+	return ioread32(base + off);
+}
+
+/* -----------------------------------------------------------------------------
+ * MERAM allocation and free
+ */
+
+static unsigned long meram_alloc(struct sh_mobile_meram_priv *priv, size_t size)
+{
+	return gen_pool_alloc(priv->pool, size);
+}
+
+static void meram_free(struct sh_mobile_meram_priv *priv, unsigned long mem,
+		       size_t size)
+{
+	gen_pool_free(priv->pool, mem, size);
+}
+
+/* -----------------------------------------------------------------------------
+ * LCDC cache planes allocation, init, cleanup and free
+ */
+
+/* Allocate ICBs and MERAM for a plane. */
+static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
+			     struct sh_mobile_meram_fb_plane *plane,
+			     size_t size)
+{
+	unsigned long mem;
+	unsigned long idx;
+
+	idx = find_first_zero_bit(&priv->used_icb, 28);
+	if (idx == 28)
+		return -ENOMEM;
+	plane->cache = &priv->icbs[idx];
+
+	idx = find_next_zero_bit(&priv->used_icb, 32, 28);
+	if (idx == 32)
+		return -ENOMEM;
+	plane->marker = &priv->icbs[idx];
+
+	mem = meram_alloc(priv, size * 1024);
+	if (mem == 0)
+		return -ENOMEM;
+
+	__set_bit(plane->marker->index, &priv->used_icb);
+	__set_bit(plane->cache->index, &priv->used_icb);
+
+	plane->marker->offset = mem - priv->meram;
+	plane->marker->size = size;
+
+	return 0;
+}
+
+/* Free ICBs and MERAM for a plane. */
+static void meram_plane_free(struct sh_mobile_meram_priv *priv,
+			     struct sh_mobile_meram_fb_plane *plane)
+{
+	meram_free(priv, priv->meram + plane->marker->offset,
+		   plane->marker->size * 1024);
+
+	__clear_bit(plane->marker->index, &priv->used_icb);
+	__clear_bit(plane->cache->index, &priv->used_icb);
+}
+
+/* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */
+static int is_nvcolor(int cspace)
+{
+	if (cspace == SH_MOBILE_MERAM_PF_NV ||
+	    cspace == SH_MOBILE_MERAM_PF_NV24)
+		return 1;
+	return 0;
+}
+
+/* Set the next address to fetch. */
+static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
+				struct sh_mobile_meram_fb_cache *cache,
+				unsigned long base_addr_y,
+				unsigned long base_addr_c)
+{
+	struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
+	unsigned long target;
+
+	icb->current_reg ^= 1;
+	target = icb->current_reg ? MExxSARB : MExxSARA;
+
+	/* set the next address to fetch */
+	meram_write_icb(priv->base, cache->planes[0].cache->index, target,
+			base_addr_y);
+	meram_write_icb(priv->base, cache->planes[0].marker->index, target,
+			base_addr_y + cache->planes[0].marker->cache_unit);
+
+	if (cache->nplanes == 2) {
+		meram_write_icb(priv->base, cache->planes[1].cache->index,
+				target, base_addr_c);
+		meram_write_icb(priv->base, cache->planes[1].marker->index,
+				target, base_addr_c +
+				cache->planes[1].marker->cache_unit);
+	}
+}
+
+/* Get the next ICB address. */
+static void
+meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
+			struct sh_mobile_meram_fb_cache *cache,
+			unsigned long *icb_addr_y, unsigned long *icb_addr_c)
+{
+	struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
+	unsigned long icb_offset;
+
+	if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
+		icb_offset = 0x80000000 | (icb->current_reg << 29);
+	else
+		icb_offset = 0xc0000000 | (icb->current_reg << 23);
+
+	*icb_addr_y = icb_offset | (cache->planes[0].marker->index << 24);
+	if (cache->nplanes == 2)
+		*icb_addr_c = icb_offset
+			    | (cache->planes[1].marker->index << 24);
+}
+
+#define MERAM_CALC_BYTECOUNT(x, y) \
+	(((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
+
+/* Initialize MERAM. */
+static int meram_plane_init(struct sh_mobile_meram_priv *priv,
+			    struct sh_mobile_meram_fb_plane *plane,
+			    unsigned int xres, unsigned int yres,
+			    unsigned int *out_pitch)
+{
+	struct sh_mobile_meram_icb *marker = plane->marker;
+	unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
+	unsigned long bnm;
+	unsigned int lcdc_pitch;
+	unsigned int xpitch;
+	unsigned int line_cnt;
+	unsigned int save_lines;
+
+	/* adjust pitch to 1024, 2048, 4096 or 8192 */
+	lcdc_pitch = (xres - 1) | 1023;
+	lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1);
+	lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2);
+	lcdc_pitch += 1;
+
+	/* derive settings */
+	if (lcdc_pitch == 8192 && yres >= 1024) {
+		lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
+		line_cnt = total_byte_count >> 11;
+		*out_pitch = xres;
+		save_lines = plane->marker->size / 16 / MERAM_SEC_LINE;
+		save_lines *= MERAM_SEC_LINE;
+	} else {
+		xpitch = xres;
+		line_cnt = yres;
+		*out_pitch = lcdc_pitch;
+		save_lines = plane->marker->size / (lcdc_pitch >> 10) / 2;
+		save_lines &= 0xff;
+	}
+	bnm = (save_lines - 1) << 16;
+
+	/* TODO: we better to check if we have enough MERAM buffer size */
+
+	/* set up ICB */
+	meram_write_icb(priv->base, plane->cache->index,  MExxBSIZE,
+			MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
+	meram_write_icb(priv->base, plane->marker->index, MExxBSIZE,
+			MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
+
+	meram_write_icb(priv->base, plane->cache->index,  MExxMNCF, bnm);
+	meram_write_icb(priv->base, plane->marker->index, MExxMNCF, bnm);
+
+	meram_write_icb(priv->base, plane->cache->index,  MExxSBSIZE, xpitch);
+	meram_write_icb(priv->base, plane->marker->index, MExxSBSIZE, xpitch);
+
+	/* save a cache unit size */
+	plane->cache->cache_unit = xres * save_lines;
+	plane->marker->cache_unit = xres * save_lines;
+
+	/*
+	 * Set MERAM for framebuffer
+	 *
+	 * we also chain the cache_icb and the marker_icb.
+	 * we also split the allocated MERAM buffer between two ICBs.
+	 */
+	meram_write_icb(priv->base, plane->cache->index, MExxCTL,
+			MERAM_MExxCTL_VAL(plane->marker->index, marker->offset)
+			| MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
+			MExxCTL_MD_FB);
+	meram_write_icb(priv->base, plane->marker->index, MExxCTL,
+			MERAM_MExxCTL_VAL(plane->cache->index, marker->offset +
+					  plane->marker->size / 2) |
+			MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
+			MExxCTL_MD_FB);
+
+	return 0;
+}
+
+static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
+				struct sh_mobile_meram_fb_plane *plane)
+{
+	/* disable ICB */
+	meram_write_icb(priv->base, plane->cache->index,  MExxCTL,
+			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
+	meram_write_icb(priv->base, plane->marker->index, MExxCTL,
+			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
+
+	plane->cache->cache_unit = 0;
+	plane->marker->cache_unit = 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * MERAM operations
+ */
+
+unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *pdata,
+				    size_t size)
+{
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+
+	return meram_alloc(priv, size);
+}
+EXPORT_SYMBOL_GPL(sh_mobile_meram_alloc);
+
+void sh_mobile_meram_free(struct sh_mobile_meram_info *pdata, unsigned long mem,
+			  size_t size)
+{
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+
+	meram_free(priv, mem, size);
+}
+EXPORT_SYMBOL_GPL(sh_mobile_meram_free);
+
+/* Allocate memory for the ICBs and mark them as used. */
+static struct sh_mobile_meram_fb_cache *
+meram_cache_alloc(struct sh_mobile_meram_priv *priv,
+		  const struct sh_mobile_meram_cfg *cfg,
+		  int pixelformat)
+{
+	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
+	struct sh_mobile_meram_fb_cache *cache;
+	int ret;
+
+	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
+	if (cache == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	cache->nplanes = nplanes;
+
+	ret = meram_plane_alloc(priv, &cache->planes[0],
+				cfg->icb[0].meram_size);
+	if (ret < 0)
+		goto error;
+
+	cache->planes[0].marker->current_reg = 1;
+	cache->planes[0].marker->pixelformat = pixelformat;
+
+	if (cache->nplanes == 1)
+		return cache;
+
+	ret = meram_plane_alloc(priv, &cache->planes[1],
+				cfg->icb[1].meram_size);
+	if (ret < 0) {
+		meram_plane_free(priv, &cache->planes[0]);
+		goto error;
+	}
+
+	return cache;
+
+error:
+	kfree(cache);
+	return ERR_PTR(-ENOMEM);
+}
+
+void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *pdata,
+				  const struct sh_mobile_meram_cfg *cfg,
+				  unsigned int xres, unsigned int yres,
+				  unsigned int pixelformat, unsigned int *pitch)
+{
+	struct sh_mobile_meram_fb_cache *cache;
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+	struct platform_device *pdev = pdata->pdev;
+	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
+	unsigned int out_pitch;
+
+	if (priv == NULL)
+		return ERR_PTR(-ENODEV);
+
+	if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+	    pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
+	    pixelformat != SH_MOBILE_MERAM_PF_RGB)
+		return ERR_PTR(-EINVAL);
+
+	dev_dbg(&pdev->dev, "registering %dx%d (%s)", xres, yres,
+		!pixelformat ? "yuv" : "rgb");
+
+	/* we can't handle wider than 8192px */
+	if (xres > 8192) {
+		dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (cfg->icb[0].meram_size == 0)
+		return ERR_PTR(-EINVAL);
+
+	if (nplanes == 2 && cfg->icb[1].meram_size == 0)
+		return ERR_PTR(-EINVAL);
+
+	mutex_lock(&priv->lock);
+
+	/* We now register the ICBs and allocate the MERAM regions. */
+	cache = meram_cache_alloc(priv, cfg, pixelformat);
+	if (IS_ERR(cache)) {
+		dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
+			PTR_ERR(cache));
+		goto err;
+	}
+
+	/* initialize MERAM */
+	meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
+	*pitch = out_pitch;
+	if (pixelformat == SH_MOBILE_MERAM_PF_NV)
+		meram_plane_init(priv, &cache->planes[1],
+				 xres, (yres + 1) / 2, &out_pitch);
+	else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
+		meram_plane_init(priv, &cache->planes[1],
+				 2 * xres, (yres + 1) / 2, &out_pitch);
+
+err:
+	mutex_unlock(&priv->lock);
+	return cache;
+}
+EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_alloc);
+
+void
+sh_mobile_meram_cache_free(struct sh_mobile_meram_info *pdata, void *data)
+{
+	struct sh_mobile_meram_fb_cache *cache = data;
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+
+	mutex_lock(&priv->lock);
+
+	/* Cleanup and free. */
+	meram_plane_cleanup(priv, &cache->planes[0]);
+	meram_plane_free(priv, &cache->planes[0]);
+
+	if (cache->nplanes == 2) {
+		meram_plane_cleanup(priv, &cache->planes[1]);
+		meram_plane_free(priv, &cache->planes[1]);
+	}
+
+	kfree(cache);
+
+	mutex_unlock(&priv->lock);
+}
+EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_free);
+
+void
+sh_mobile_meram_cache_update(struct sh_mobile_meram_info *pdata, void *data,
+			     unsigned long base_addr_y,
+			     unsigned long base_addr_c,
+			     unsigned long *icb_addr_y,
+			     unsigned long *icb_addr_c)
+{
+	struct sh_mobile_meram_fb_cache *cache = data;
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+
+	mutex_lock(&priv->lock);
+
+	meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
+	meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
+
+	mutex_unlock(&priv->lock);
+}
+EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
+
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
+static int sh_mobile_meram_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+	unsigned int i, j;
+
+	for (i = 0; i < MERAM_REGS_SIZE; i++)
+		priv->regs[i] = meram_read_reg(priv->base, common_regs[i]);
+
+	for (i = 0; i < 32; i++) {
+		if (!test_bit(i, &priv->used_icb))
+			continue;
+		for (j = 0; j < ICB_REGS_SIZE; j++) {
+			priv->icbs[i].regs[j] =
+				meram_read_icb(priv->base, i, icb_regs[j]);
+			/* Reset ICB on resume */
+			if (icb_regs[j] == MExxCTL)
+				priv->icbs[i].regs[j] |=
+					MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
+		}
+	}
+	return 0;
+}
+
+static int sh_mobile_meram_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+	unsigned int i, j;
+
+	for (i = 0; i < 32; i++) {
+		if (!test_bit(i, &priv->used_icb))
+			continue;
+		for (j = 0; j < ICB_REGS_SIZE; j++)
+			meram_write_icb(priv->base, i, icb_regs[j],
+					priv->icbs[i].regs[j]);
+	}
+
+	for (i = 0; i < MERAM_REGS_SIZE; i++)
+		meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME */
+
+static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
+			    sh_mobile_meram_suspend,
+			    sh_mobile_meram_resume, NULL);
+
+/* -----------------------------------------------------------------------------
+ * Probe/remove and driver init/exit
+ */
+
+static int sh_mobile_meram_probe(struct platform_device *pdev)
+{
+	struct sh_mobile_meram_priv *priv;
+	struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
+	struct resource *regs;
+	struct resource *meram;
+	unsigned int i;
+	int error;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (regs == NULL || meram == NULL) {
+		dev_err(&pdev->dev, "cannot get platform resources\n");
+		return -ENOENT;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "cannot allocate device data\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize private data. */
+	mutex_init(&priv->lock);
+	priv->used_icb = pdata->reserved_icbs;
+
+	for (i = 0; i < MERAM_ICB_NUM; ++i)
+		priv->icbs[i].index = i;
+
+	pdata->priv = priv;
+	pdata->pdev = pdev;
+
+	/* Request memory regions and remap the registers. */
+	if (!request_mem_region(regs->start, resource_size(regs), pdev->name)) {
+		dev_err(&pdev->dev, "MERAM registers region already claimed\n");
+		error = -EBUSY;
+		goto err_req_regs;
+	}
+
+	if (!request_mem_region(meram->start, resource_size(meram),
+				pdev->name)) {
+		dev_err(&pdev->dev, "MERAM memory region already claimed\n");
+		error = -EBUSY;
+		goto err_req_meram;
+	}
+
+	priv->base = ioremap_nocache(regs->start, resource_size(regs));
+	if (!priv->base) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		error = -EFAULT;
+		goto err_ioremap;
+	}
+
+	priv->meram = meram->start;
+
+	/* Create and initialize the MERAM memory pool. */
+	priv->pool = gen_pool_create(ilog2(MERAM_GRANULARITY), -1);
+	if (priv->pool == NULL) {
+		error = -ENOMEM;
+		goto err_genpool;
+	}
+
+	error = gen_pool_add(priv->pool, meram->start, resource_size(meram),
+			     -1);
+	if (error < 0)
+		goto err_genpool;
+
+	/* initialize ICB addressing mode */
+	if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
+		meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
+
+	platform_set_drvdata(pdev, priv);
+	pm_runtime_enable(&pdev->dev);
+
+	dev_info(&pdev->dev, "sh_mobile_meram initialized.");
+
+	return 0;
+
+err_genpool:
+	if (priv->pool)
+		gen_pool_destroy(priv->pool);
+	iounmap(priv->base);
+err_ioremap:
+	release_mem_region(meram->start, resource_size(meram));
+err_req_meram:
+	release_mem_region(regs->start, resource_size(regs));
+err_req_regs:
+	mutex_destroy(&priv->lock);
+	kfree(priv);
+
+	return error;
+}
+
+
+static int sh_mobile_meram_remove(struct platform_device *pdev)
+{
+	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+	pm_runtime_disable(&pdev->dev);
+
+	gen_pool_destroy(priv->pool);
+
+	iounmap(priv->base);
+	release_mem_region(meram->start, resource_size(meram));
+	release_mem_region(regs->start, resource_size(regs));
+
+	mutex_destroy(&priv->lock);
+
+	kfree(priv);
+
+	return 0;
+}
+
+static struct platform_driver sh_mobile_meram_driver = {
+	.driver	= {
+		.name		= "sh_mobile_meram",
+		.owner		= THIS_MODULE,
+		.pm		= &sh_mobile_meram_dev_pm_ops,
+	},
+	.probe		= sh_mobile_meram_probe,
+	.remove		= sh_mobile_meram_remove,
+};
+
+module_platform_driver(sh_mobile_meram_driver);
+
+MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
+MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
new file mode 100644
index 000000000000..210f3a02121a
--- /dev/null
+++ b/drivers/video/fbdev/simplefb.c
@@ -0,0 +1,280 @@
+/*
+ * Simplest possible simple frame-buffer driver, as a platform device
+ *
+ * Copyright (c) 2013, Stephen Warren
+ *
+ * Based on q40fb.c, which was:
+ * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org>
+ *
+ * Also based on offb.c, which was:
+ * Copyright (C) 1997 Geert Uytterhoeven
+ * Copyright (C) 1996 Paul Mackerras
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_data/simplefb.h>
+#include <linux/platform_device.h>
+
+static struct fb_fix_screeninfo simplefb_fix = {
+	.id		= "simple",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo simplefb_var = {
+	.height		= -1,
+	.width		= -1,
+	.activate	= FB_ACTIVATE_NOW,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			      u_int transp, struct fb_info *info)
+{
+	u32 *pal = info->pseudo_palette;
+	u32 cr = red >> (16 - info->var.red.length);
+	u32 cg = green >> (16 - info->var.green.length);
+	u32 cb = blue >> (16 - info->var.blue.length);
+	u32 value;
+
+	if (regno >= 16)
+		return -EINVAL;
+
+	value = (cr << info->var.red.offset) |
+		(cg << info->var.green.offset) |
+		(cb << info->var.blue.offset);
+	if (info->var.transp.length > 0) {
+		u32 mask = (1 << info->var.transp.length) - 1;
+		mask <<= info->var.transp.offset;
+		value |= mask;
+	}
+	pal[regno] = value;
+
+	return 0;
+}
+
+static void simplefb_destroy(struct fb_info *info)
+{
+	if (info->screen_base)
+		iounmap(info->screen_base);
+}
+
+static struct fb_ops simplefb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_destroy	= simplefb_destroy,
+	.fb_setcolreg	= simplefb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static struct simplefb_format simplefb_formats[] = SIMPLEFB_FORMATS;
+
+struct simplefb_params {
+	u32 width;
+	u32 height;
+	u32 stride;
+	struct simplefb_format *format;
+};
+
+static int simplefb_parse_dt(struct platform_device *pdev,
+			   struct simplefb_params *params)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+	const char *format;
+	int i;
+
+	ret = of_property_read_u32(np, "width", &params->width);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse width property\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(np, "height", &params->height);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse height property\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(np, "stride", &params->stride);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse stride property\n");
+		return ret;
+	}
+
+	ret = of_property_read_string(np, "format", &format);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't parse format property\n");
+		return ret;
+	}
+	params->format = NULL;
+	for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
+		if (strcmp(format, simplefb_formats[i].name))
+			continue;
+		params->format = &simplefb_formats[i];
+		break;
+	}
+	if (!params->format) {
+		dev_err(&pdev->dev, "Invalid format value\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int simplefb_parse_pd(struct platform_device *pdev,
+			     struct simplefb_params *params)
+{
+	struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
+	int i;
+
+	params->width = pd->width;
+	params->height = pd->height;
+	params->stride = pd->stride;
+
+	params->format = NULL;
+	for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
+		if (strcmp(pd->format, simplefb_formats[i].name))
+			continue;
+
+		params->format = &simplefb_formats[i];
+		break;
+	}
+
+	if (!params->format) {
+		dev_err(&pdev->dev, "Invalid format value\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int simplefb_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct simplefb_params params;
+	struct fb_info *info;
+	struct resource *mem;
+
+	if (fb_get_options("simplefb", NULL))
+		return -ENODEV;
+
+	ret = -ENODEV;
+	if (dev_get_platdata(&pdev->dev))
+		ret = simplefb_parse_pd(pdev, &params);
+	else if (pdev->dev.of_node)
+		ret = simplefb_parse_dt(pdev, &params);
+
+	if (ret)
+		return ret;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "No memory resource\n");
+		return -EINVAL;
+	}
+
+	info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, info);
+
+	info->fix = simplefb_fix;
+	info->fix.smem_start = mem->start;
+	info->fix.smem_len = resource_size(mem);
+	info->fix.line_length = params.stride;
+
+	info->var = simplefb_var;
+	info->var.xres = params.width;
+	info->var.yres = params.height;
+	info->var.xres_virtual = params.width;
+	info->var.yres_virtual = params.height;
+	info->var.bits_per_pixel = params.format->bits_per_pixel;
+	info->var.red = params.format->red;
+	info->var.green = params.format->green;
+	info->var.blue = params.format->blue;
+	info->var.transp = params.format->transp;
+
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures) {
+		framebuffer_release(info);
+		return -ENOMEM;
+	}
+	info->apertures->ranges[0].base = info->fix.smem_start;
+	info->apertures->ranges[0].size = info->fix.smem_len;
+
+	info->fbops = &simplefb_ops;
+	info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE;
+	info->screen_base = ioremap_wc(info->fix.smem_start,
+				       info->fix.smem_len);
+	if (!info->screen_base) {
+		framebuffer_release(info);
+		return -ENODEV;
+	}
+	info->pseudo_palette = (void *)(info + 1);
+
+	dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n",
+			     info->fix.smem_start, info->fix.smem_len,
+			     info->screen_base);
+	dev_info(&pdev->dev, "format=%s, mode=%dx%dx%d, linelength=%d\n",
+			     params.format->name,
+			     info->var.xres, info->var.yres,
+			     info->var.bits_per_pixel, info->fix.line_length);
+
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
+		iounmap(info->screen_base);
+		framebuffer_release(info);
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
+
+	return 0;
+}
+
+static int simplefb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+
+	unregister_framebuffer(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id simplefb_of_match[] = {
+	{ .compatible = "simple-framebuffer", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, simplefb_of_match);
+
+static struct platform_driver simplefb_driver = {
+	.driver = {
+		.name = "simple-framebuffer",
+		.owner = THIS_MODULE,
+		.of_match_table = simplefb_of_match,
+	},
+	.probe = simplefb_probe,
+	.remove = simplefb_remove,
+};
+module_platform_driver(simplefb_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
+MODULE_DESCRIPTION("Simple framebuffer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/sis/300vtbl.h b/drivers/video/fbdev/sis/300vtbl.h
new file mode 100644
index 000000000000..e4b4a2626da4
--- /dev/null
+++ b/drivers/video/fbdev/sis/300vtbl.h
@@ -0,0 +1,1072 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Register settings for SiS 300 series
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+static const struct SiS_Ext SiS300_EModeIDTable[] =
+{
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},
+	{0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x8 */
+	{0x32,0x6a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x8 */
+	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x16 */
+	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x16 */
+	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x32 */
+	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},  /* 1280x1024x8 */
+	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x15 */
+	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x15 */
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x8  */
+	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x8  */
+	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x8  */
+	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x16 */
+	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x16 */
+	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x16 */
+	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x8  */
+	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x32 */
+	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x16 */
+	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x8 */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x16 */
+	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x8 */
+	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x8 */
+	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x16 */
+	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x16 */
+	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x32 */
+	{0x77,0x4a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x32 */
+	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x32 */
+	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x8 */
+	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x16 */
+	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x8 */
+	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x16 */
+	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x32 */
+	{0x20,0x4a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},  /* 1024x600 */
+	{0x21,0x4a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x22,0x4a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x23,0x4a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},  /* 1152x768 */
+	{0x24,0x4a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x25,0x4a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},  /* 1152x864 */
+	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x39,-1},  /* 848x480 */
+	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x39,-1},
+	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x39,-1},
+	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3b,-1},  /* 856x480 */
+	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3b,-1},
+	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3b,-1},
+	{0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1},  /* 1360x768 */
+	{0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x32 */
+	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x32 */
+	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x32 */
+	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1},  /* 1280x768   */
+	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1},
+	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1},
+	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3f,-1},  /* 768x576x8 */
+	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3f,-1},  /* 768x576x16 */
+	{0x61,0x6a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3f,-1},  /* 768x576x32 */
+	{0x67,0x6e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1},  /* 1360x1024x8 (BARCO) */
+	{0x6f,0x6e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1},  /* 1360x1024x16 (BARCO) */
+	{0x72,0x6eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1},  /* 1360x1024x32 (BARCO) */
+	{0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_Ext2 SiS300_RefIndex[] =
+{
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 00 */
+	{0x0467,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 01 */
+	{0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 02 - CRT1CRTC was 0x4f */
+	{0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 03 */
+	{0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 04 */
+	{0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 05 */
+	{0x0047,0x11,0x0e,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 06 - CRT1CRTC was 0x51 */
+	{0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 07 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 08 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 09 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0a */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0b */
+	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0c */
+	{0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0d */
+	{0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0e */
+	{0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0f */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0, 0x4a, 0x49}, /* 10 */
+	{0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0, 0x00, 0x00}, /* 11 */
+	{0x006f,0x32,0x4a,0x06,0x14,0x32, 720, 576, 0, 0x00, 0x00}, /* 12 */ /* 4a was 03 */
+	{0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 13 */
+	{0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 14 */
+	{0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 15 - CRT1CRTC was 0x97 */
+	{0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 16 */
+	{0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 17 - CRT1CRTC was 0x59 */
+	{0x0047,0x1a,0x12,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 18 */
+	{0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 19 - CRT1CRTC was 0x5b */
+	{0x0387,0x1c,0x0d,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1a - CRT1CRTC was 0x5c */
+	{0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1b */
+	{0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1c */
+	{0x0007,0x1f,0x18,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1d */
+	{0x0007,0x20,0x19,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1e - CRT1CRTC was 0x60 */
+	{0x0007,0x21,0x1a,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1f */
+	{0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 20 */
+	{0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 21 - CRT1CRTC was 0x63 */
+	{0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 22 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0, 0x4b, 0x4b}, /* 23 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0, 0x00, 0x00}, /* 24 */
+	{0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0, 0x00, 0x00}, /* 25 */
+	{0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0, 0x00, 0x00}, /* 26 */  /* was c077 */
+	{0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0, 0x00, 0x00}, /* 27 */
+	{0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0, 0x00, 0x00}, /* 28 */
+	{0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 29 - 1280x960-60 */
+	{0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 2a - 1280x960-85 */
+	{0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0, 0x00, 0x00}, /* 2b */
+	{0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0, 0x00, 0x00}, /* 2c */	/* VCLK 0x09 */
+	{0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2d */
+	{0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2e */
+	{0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2f */
+	{0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 30 */
+	{0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 31 */
+	{0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 32 */
+	{0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 33 */
+	{0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 34 */
+	{0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 35 */
+	{0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 36 1152x864-60Hz  */
+	{0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 37 1152x864-75Hz */
+	{0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 38 1152x864-85Hz */
+	{0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 39 848x480-38Hzi */
+	{0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 3a 848x480-60Hz  */
+	{0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3b 856x480-38Hzi */
+	{0xc067,0x42,0x28,0x0c,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3c 856x480-60Hz  */
+	{0x0067,0x43,0x3e,0x0d,0x1b,0x48,1360, 768, 0, 0x00, 0x00}, /* 3d 1360x768-60Hz */
+	{0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0, 0x00, 0x00}, /* 3e 1280x768-60Hz */
+	{0x006f,0x47,0x4c,0x06,0x15,0x5f, 768, 576, 0, 0x00, 0x00}, /* 3f 768x576 */
+	{0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0, 0x00, 0x00}, /* 40 1360x1024-59Hz (BARCO1366 only) */
+	{0xffff,   0,   0,   0,   0,   0,   0,   0, 0, 0x00, 0x00}
+};
+
+static const struct SiS_VBMode SiS300_VBModeIDTable[] =
+{
+	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
+	{0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x02},
+	{0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x00},
+	{0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x01},
+	{0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x02},
+	{0x05,0x00,0x00,0x01,0x04,0x00,0x00,0x00},
+	{0x06,0x00,0x00,0x01,0x05,0x00,0x02,0x00},
+	{0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x01},
+	{0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x02},
+	{0x0d,0x00,0x00,0x01,0x04,0x00,0x00,0x00},
+	{0x0e,0x00,0x00,0x01,0x05,0x00,0x02,0x00},
+	{0x0f,0x00,0x00,0x01,0x05,0x00,0x02,0x01},
+	{0x10,0x00,0x00,0x01,0x05,0x00,0x02,0x01},
+	{0x11,0x00,0x00,0x01,0x05,0x00,0x02,0x03},
+	{0x12,0x00,0x00,0x01,0x05,0x00,0x02,0x03},
+	{0x13,0x00,0x00,0x01,0x04,0x00,0x04,0x00},
+	{0x6a,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
+	{0x2e,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
+	{0x2f,0x00,0x00,0x01,0x05,0x00,0x06,0x06},
+	{0x30,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
+	{0x31,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x32,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x33,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x34,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x35,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x36,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x37,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
+	{0x38,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
+	{0x3a,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+	{0x40,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
+	{0x41,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
+	{0x43,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
+	{0x44,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
+	{0x46,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
+	{0x47,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
+	{0x49,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
+	{0x4a,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
+	{0x4c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+	{0x4d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+	{0x4f,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
+	{0x50,0x00,0x00,0x01,0x04,0x00,0x05,0x07},
+	{0x51,0x00,0x00,0x01,0x07,0x00,0x07,0x09},
+	{0x52,0x00,0x00,0x01,0x00,0x00,0x09,0x0b},
+	{0x53,0x00,0x00,0x01,0x04,0x00,0x05,0x07},
+	{0x54,0x00,0x00,0x01,0x07,0x00,0x07,0x09},
+	{0x56,0x00,0x00,0x01,0x04,0x00,0x05,0x07},
+	{0x57,0x00,0x00,0x01,0x07,0x00,0x07,0x09},
+	{0x58,0x00,0x00,0x01,0x00,0x00,0x09,0x0b},
+	{0x59,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
+	{0x5c,0x00,0x00,0x01,0x00,0x00,0x09,0x0b},
+	{0x5d,0x00,0x00,0x01,0x05,0x00,0x06,0x06},
+	{0x5e,0x00,0x00,0x01,0x05,0x00,0x06,0x06},
+	{0x5f,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x60,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x61,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
+	{0x62,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
+	{0x63,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
+	{0x64,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
+	{0x65,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+	{0x6c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+	{0x6d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+	{0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_CRT1Table SiS300_CRT1Table[] =
+{
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,    /* 0x00 - 320x200 */
+  0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,     /* HRE [4],[15] is invalid - but correcting it does not work */
+  0x00}},
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,    /* 0x01 */
+  0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,     /* HRE [4],[15] is invalid - but correcting it does not work */
+  0x00}},
+ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,    /* 0x02 */
+  0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
+  0x01}},
+ {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
+  0x01}},
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+  0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
+  0x00}},
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* 0x05 - corrected 640x480-60 */
+  0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+  0x00}},
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,    /* 0x06 - corrected 640x480-72 */
+  0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
+  0x00}},
+ {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
+  0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
+  0x00}},
+ {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
+  0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+  0x00}},
+ {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e,    /* 0x09 - corrected 640x480-100 */
+  0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
+  0x00}},
+ {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e,    /* 0x0a - corrected 640x480-120 */
+  0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
+  0x00}},
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9d,0xfb,0x1f,
+  0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x01,
+  0x00}},
+ {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
+  0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,    /* Corrected VDE, VBE */
+  0x00}},
+ {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
+  0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
+  0x01}},
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+  0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
+  0x01}},
+ {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
+  0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
+  0x01}},
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
+  0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
+  0x01}},
+ {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
+  0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
+  0x01}},
+ {{0x8c,0x63,0x63,0x87,0x72,0x16,0x7e,0xf0,
+  0x59,0x8d,0x57,0x57,0x7f,0x00,0x00,0x06,
+  0x01}},
+ {{0x7e,0x63,0x63,0x82,0x6c,0x14,0x75,0xe0,
+  0x58,0x0b,0x57,0x57,0x76,0x20,0x00,0x06,
+  0x01}},
+ {{0x7e,0x63,0x63,0x82,0x6c,0x14,0x75,0xe0,   /* 0x14 */
+  0x58,0x0b,0x57,0x57,0x76,0x20,0x00,0x06,
+  0x01}},
+ {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
+  0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
+  0x00}},
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+  0x01}},
+ {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
+  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+  0x01}},
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
+  0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
+  0x01}},
+ {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
+  0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
+  0x01}},
+ {{0x9f,0x7f,0x7f,0x83,0x83,0x93,0x1e,0xf5,  /* 0x1a */
+  0x00,0x84,0xff,0xff,0x1f,0x10,0x00,0x02,
+  0x01}},
+ {{0xa2,0x7f,0x7f,0x86,0x84,0x94,0x37,0xf5,
+  0x0b,0x82,0xff,0xff,0x38,0x10,0x00,0x02,
+  0x01}},
+ {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
+  0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
+  0x00}},
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
+  0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+  0x01}},
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,  /* 0x1e */
+  0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+  0x01}},
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
+  0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
+  0x01}},
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+  0x00}},
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+  0x00}},
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+  0x00}},
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+  0x00}},
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,  /* 36: 1600x1200x85Hz */
+  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+  0x00}},
+ {{0x3f,0xef,0xef,0x83,0xfd,0x1a,0xda,0x1f,  /* 37: 1920x1440x60Hz */
+  0xa0,0x84,0x9f,0x9f,0xdb,0x1f,0x01,0x01,
+  0x00}},
+ {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
+  0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
+  0x00}},
+ {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,  /* 0x27: 1280x960-60 - correct */
+  0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
+  0x01}},
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,  /* 0x28 */
+  0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+  0x01}},
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+  0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
+  0x01}},
+ {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
+  0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
+  0x01}},
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
+  0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
+  0x01}},
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+  0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+  0x01}},
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x15,0x26,0xf1,
+  0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+  0x01}},
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+  0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+  0x01}},
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
+  0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+  0x01}},
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+  0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+  0x01}},
+ {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
+  0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
+  0x00}},
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,  /* 0x32: 720x576, corrected to 60Hz */
+  0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+  0x41}},
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,  /* 0x33 - 1024x600 */
+  0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
+  0x01}},
+ {{0xa3,0x8f,0x8f,0x97,0x96,0x97,0x24,0xf5,  /* 0x34 - 1152x768 - corrected */
+  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+  0x01}},
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,  /* 0x35 */
+   0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+   0x01}}, /* 0x35 */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+   0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
+   0x01}}, /* 0x36 */
+ {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
+   0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
+   0x01}}, /* 0x37 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
+   0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
+   0x01}}, /* 0x38 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+   0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+   0x01}}, /* 0x39 */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,  /* 95 was 15 - illegal HBE! */
+   0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+   0x01}}, /* 0x3a */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}}, /* 0x3b */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}}, /* 0x3c */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+   0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+   0x01}}, /* 0x3d */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,  /* 1152x864-75 */
+   0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
+   0x01}},  /* 0x3e */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,  /* 848x480-38i */
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}}, /* 0x3f */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,  /* 848x480-60  */
+   0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
+   0x00}}, /* 0x40 */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,  /* 856x480-38i */
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}}, /* 0x41 */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,  /* 856x480-60  */
+   0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+   0x00}}, /* 0x42 */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,  /* 1360x768-60 */
+   0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
+   0x01}}, /* 0x43 */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,  /* 1152x864-84 */
+   0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
+   0x01}}, /* 0x44 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,  /* 1280x960-85 */
+   0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+   0x01}}, /* 0x45 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,  /* 1280x768-60 */
+   0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
+   0x01}}, /* 0x46 */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,  /* 768x576, corrected to 60Hz */
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}}, /* 0x47 */
+ {{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52,  /* 1360x1024 (Barco iQ Pro R300) */
+   0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03,
+   0x00}}, /* 0x48 */
+ {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,  /* 1152x864-60 */
+   0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
+   0x41}}, /* 0x49 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+   0x40}}, /* 0x4a */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+   0x00}}  /* 0x4b */
+};
+
+static const struct SiS_MCLKData SiS300_MCLKData_630[] =
+{
+	{ 0x5a,0x64,0x80, 66},
+	{ 0xb3,0x45,0x80, 83},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x22,0x80,133},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x61,0x80,100}
+};
+
+static const struct SiS_MCLKData SiS300_MCLKData_300[] =
+{
+	{ 0x68,0x43,0x80,125},
+	{ 0x68,0x43,0x80,125},
+	{ 0x68,0x43,0x80,125},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x61,0x80,100},
+	{ 0x37,0x61,0x80,100}
+};
+
+static struct SiS_VCLKData SiS300_VCLKData[] =
+{
+	{ 0x1b,0xe1, 25}, /* 0x00 */
+	{ 0x4e,0xe4, 28}, /* 0x01 */
+	{ 0x57,0xe4, 32}, /* 0x02 */
+	{ 0xc3,0xc8, 36}, /* 0x03 */
+	{ 0x42,0xc3, 40}, /* 0x04 */
+	{ 0x5d,0xc4, 45}, /* 0x05 */
+	{ 0x52,0x65, 50}, /* 0x06 */
+	{ 0x53,0x65, 50}, /* 0x07 */
+	{ 0x6d,0x66, 56}, /* 0x08 */
+	{ 0x5a,0x64, 65}, /* 0x09 */
+	{ 0x46,0x44, 68}, /* 0x0a */
+	{ 0x3e,0x43, 75}, /* 0x0b */
+	{ 0x6d,0x46, 76}, /* 0x0c */  /* 800x600 | LVDS_2(CH), MITAC(CH);  - 730, A901(301B): 0xb1,0x46, 76 */
+	{ 0x41,0x43, 79}, /* 0x0d */
+	{ 0x31,0x42, 79}, /* 0x0e */
+	{ 0x46,0x25, 85}, /* 0x0f */
+	{ 0x78,0x29, 87}, /* 0x10 */
+	{ 0x62,0x44, 95}, /* 0x11 */
+	{ 0x2b,0x22,105}, /* 0x12 */
+	{ 0x49,0x24,106}, /* 0x13 */
+	{ 0xc3,0x28,108}, /* 0x14 */
+	{ 0x3c,0x23,109}, /* 0x15 */
+	{ 0xf7,0x2c,132}, /* 0x16 */
+	{ 0xd4,0x28,136}, /* 0x17 */
+	{ 0x41,0x05,158}, /* 0x18 */
+	{ 0x43,0x05,162}, /* 0x19 */
+	{ 0xe1,0x0f,175}, /* 0x1a */
+	{ 0xfc,0x12,189}, /* 0x1b */
+	{ 0xde,0x26,194}, /* 0x1c */
+	{ 0x54,0x05,203}, /* 0x1d */
+	{ 0x3f,0x03,230}, /* 0x1e */
+	{ 0x30,0x02,234}, /* 0x1f */
+	{ 0x24,0x01,266}, /* 0x20 */
+	{ 0x52,0x2a, 54}, /* 0x21 */  /* 301 TV */
+	{ 0x52,0x6a, 27}, /* 0x22 */  /* 301 TV */
+	{ 0x62,0x24, 70}, /* 0x23 */  /* 301 TV */
+	{ 0x62,0x64, 70}, /* 0x24 */  /* 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x25 */  /* 301 TV */
+	{ 0x20,0x26, 33}, /* 0x26 */  /* 301 TV */
+	{ 0x31,0xc2, 39}, /* 0x27 */
+	{ 0xbf,0xc8, 35}, /* 0x28 */  /* 856x480 */
+	{ 0x60,0x36, 30}, /* 0x29 */  /* CH/UNTSC TEXT | LVDS_2(CH) - 730, A901(301B), Mitac(CH): 0xe0, 0xb6, 30 */
+	{ 0x40,0x4a, 28}, /* 0x2a */  /* CH-TV */
+	{ 0x9f,0x46, 44}, /* 0x2b */  /* CH-TV */
+	{ 0x97,0x2c, 26}, /* 0x2c */  /* CH-TV */
+	{ 0x44,0xe4, 25}, /* 0x2d */  /* CH-TV */
+	{ 0x7e,0x32, 47}, /* 0x2e */  /* CH-TV */
+	{ 0x8a,0x24, 31}, /* 0x2f */  /* CH/PAL TEXT | LVDS_2(CH), Mitac(CH) -  730, A901(301B): 0x57, 0xe4, 31 */
+	{ 0x97,0x2c, 26}, /* 0x30 */  /* CH-TV */
+	{ 0xce,0x3c, 39}, /* 0x31 */  /* CH-TV */
+	{ 0x52,0x4a, 36}, /* 0x32 */  /* CH/PAL 800x600 5/6 */
+	{ 0x34,0x61, 95}, /* 0x33 */
+	{ 0x78,0x27,108}, /* 0x34 */  /* Replacement for index 0x14 for 630 (?) */
+	{ 0x70,0x28, 90}, /* 0x35 */  /* 1152x864@60 */
+	{ 0x45,0x6b, 21}, /* 0x36 */  /* Chrontel SuperOverscan */
+	{ 0x52,0xe2, 49}, /* 0x37 */  /* 16:9 modes  */
+	{ 0x2b,0x61, 78}, /* 0x38 */  /* 16:9 modes  */
+	{ 0x70,0x44,108}, /* 0x39 */  /* 16:9 modes  */
+	{ 0x54,0x42,135}, /* 0x3a */  /* 16:9 modes  */
+	{ 0x41,0x22,157}, /* 0x3b */  /* 16:9 modes  */
+	{ 0x52,0x07,149}, /* 0x3c */  /* 1280x960-85 */
+	{ 0x62,0xc6, 34}, /* 0x3d */  /* 848x480-60  */
+	{ 0x30,0x23, 88}, /* 0x3e */  /* 1360x768-60 */
+        { 0x70,0x29, 81}, /* 0x3f */  /* 1280x768-60 */
+	{ 0x72,0x2a, 76}, /* 0x40 */  /* test for SiS730 --- LIMIT for table (&0x3f) */
+	{ 0x15,0x21, 79}, /* 0x41 */  /* test for SiS730 */
+	{ 0xa1,0x42,108}, /* 0x42 */  /* 1280x960 LCD */
+	{ 0x37,0x61,100}, /* 0x43 */  /* 1280x960 LCD */
+	{ 0xe3,0x9a,106}, /* 0x44 */  /* 1360x1024 - special for Barco iQ R300 */
+	{ 0xe2,0x46,135}, /* 0x45 */  /* 1280x1024-75, better clock for VGA2 */
+	{ 0x70,0x29, 81}, /* 0x46 */  /* unused */
+	{    0,   0,  0}, /* 0x47 custom (will be filled out) */
+	{ 0xce,0x25,189}, /* 0x48 */  /* Replacement for index 0x1b for 730 (and 540?) */
+	{ 0x15,0xe1, 20}, /* 0x49 */  /* 640x400@60 (fake, not actually used) */
+	{ 0x5f,0xc6, 33}, /* 0x4a */  /* 720x576@60 */
+	{ 0x37,0x5a, 10}, /* 0x4b */  /* 320x200@60 (fake, not actually used) */
+	{ 0x2b,0xc2, 35}  /* 0x4c */  /* 768@576@60 */
+};
+
+static const unsigned char SiS300_SR15[4 * 8] =
+{
+	0x01,0x09,0xa3,0x00,
+	0x43,0x43,0x43,0x00,
+	0x1e,0x1e,0x1e,0x00,
+	0x2a,0x2a,0x2a,0x00,
+	0x06,0x06,0x06,0x00,
+	0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00
+};
+
+static const struct SiS_PanelDelayTbl SiS300_PanelDelayTbl[] =
+{
+	{{0x05,0xaa}},
+	{{0x05,0x14}},
+	{{0x05,0x36}},
+	{{0x05,0x14}},
+	{{0x05,0x14}},
+	{{0x05,0x14}},
+	{{0x05,0x90}},
+	{{0x05,0x90}},
+	{{0x05,0x14}},
+	{{0x05,0x14}},
+	{{0x05,0x14}},
+	{{0x05,0x14}},
+	{{0x20,0x80}},
+	{{0x05,0x14}},
+	{{0x05,0x40}},
+	{{0x05,0x60}}
+};
+
+/**************************************************************/
+/* SIS VIDEO BRIDGE ----------------------------------------- */
+/**************************************************************/
+
+static const struct SiS_LCDData SiS300_St2LCD1024x768Data[] =
+{
+	{   62,  25, 800, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{  104,  45, 945, 496,1344, 806},
+	{   62,  25, 800, 546,1344, 806},
+	{   31,  18,1008, 624,1344, 806},
+	{    1,   1,1344, 806,1344, 806}
+};
+
+static const struct SiS_LCDData SiS300_ExtLCD1024x768Data[] =
+{
+	{   12,   5, 896, 512,1344, 806},
+	{   12,   5, 896, 510,1344, 806},
+	{   32,  15,1008, 505,1344, 806},
+	{   32,  15,1008, 514,1344, 806},
+	{   12,   5, 896, 500,1344, 806},
+	{   42,  25,1024, 625,1344, 806},
+	{    1,   1,1344, 806,1344, 806},
+	{   12,   5, 896, 500,1344, 806},
+	{   42,  25,1024, 625,1344, 806},
+	{    1,   1,1344, 806,1344, 806},
+	{   12,   5, 896, 500,1344, 806},
+	{   42,  25,1024, 625,1344, 806},
+	{    1,   1,1344, 806,1344, 806}
+};
+
+static const struct SiS_LCDData SiS300_St2LCD1280x1024Data[] =
+{
+	{   22,   5, 800, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
+	{  176,  45, 900, 510,1650,1088},
+	{  176,  45, 900, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
+	{   13,   5,1024, 675,1560,1152},
+	{   16,   9,1266, 804,1688,1072},
+	{    1,   1,1688,1066,1688,1066}
+};
+
+static const struct SiS_LCDData SiS300_ExtLCD1280x1024Data[] =
+{
+	{  211,  60,1024, 501,1688,1066},
+	{  211,  60,1024, 508,1688,1066},
+	{  211,  60,1024, 501,1688,1066},
+	{  211,  60,1024, 508,1688,1066},
+	{  211,  60,1024, 500,1688,1066},
+	{  211,  75,1024, 625,1688,1066},
+	{  211, 120,1280, 798,1688,1066},
+	{    1,   1,1688,1066,1688,1066}
+};
+
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_1[] =
+{ /* VESA Timing */
+	{{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+	{{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+	{{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+	{{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+	{{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+	{{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
+};
+
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_2[] =
+{  /* Non-VESA */
+	{{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
+};
+
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_3[] =
+{
+	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+};
+
+/**************************************************************/
+/* LVDS/Chrontel -------------------------------------------- */
+/**************************************************************/
+
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_1[]=
+{
+	{ 832, 438,1331, 806},
+	{ 832, 388,1331, 806},
+	{ 832, 438,1331, 806},
+	{ 832, 388,1331, 806},
+	{ 832, 518,1331, 806},
+	{1050, 638,1344, 806},
+	{1344, 806,1344, 806},
+	{1688,1066,1688,1066},
+	{1688,1066,1688,1066}   /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_2[]=
+{
+	{1344, 806,1344, 806},
+	{1344, 806,1344, 806},
+	{1344, 806,1344, 806},
+	{1344, 806,1344, 806},
+	{1344, 806,1344, 806},
+	{1344, 806,1344, 806},
+	{1344, 806,1344, 806},
+	{1688,1066,1688,1066},
+	{1688,1066,1688,1066}   /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ G series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1024Data_1[]=
+{
+	{ 832, 438,1331, 806},
+	{ 832, 409,1331, 806},
+	{ 832, 438,1331, 806},
+	{ 832, 409,1331, 806},
+	{ 832, 518,1331, 806},   /* 640x480 */
+	{1050, 638,1344, 806},   /* 800x600 */
+	{1344, 806,1344, 806},   /* 1024x768 */
+};
+
+/* Custom data for 848x480 and 856x480 parallel LVDS panels */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_1[]=
+{
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{1088, 525,1088, 525},  /* 640x480 TODO */
+	{1088, 525,1088, 525},  /* 800x600 TODO */
+	{1088, 525,1088, 525},  /* 1024x768 TODO */
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{1088, 525,1088, 525},  /* 848x480 */
+	{1088, 525,1088, 525},  /* 856x480 */
+	{1088, 525,1088, 525}   /* 1360x768 TODO */
+};
+
+/* Custom data for 848x480 parallel panel */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_2[]=
+{
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{1088, 525,1088, 525},  /*  640x480 */
+	{1088, 525,1088, 525},  /*  800x600 */
+	{1088, 525,1088, 525},  /* 1024x768 */
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{   0,   0,   0,   0},
+	{1088, 525,1088, 525},  /* 848x480 */
+	{1088, 525,1088, 525},  /* 856x480 */
+	{1088, 525,1088, 525}	/* 1360x768 TODO */
+};
+
+static const struct SiS_LVDSData SiS300_CHTVUPALData[] =
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 750, 840, 750},
+	{ 936, 836, 936, 836}
+};
+
+static const struct SiS_LVDSData SiS300_CHTVOPALData[] =
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 625, 840, 625},
+	{ 960, 750, 960, 750}
+};
+
+static const struct SiS_LVDSData SiS300_CHTVSOPALData[] =
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 500, 840, 500},
+	{ 944, 625, 944, 625}
+};
+
+/* Custom des data for Barco iQ R200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
+{
+	{1330, 798},  /* 320x200 */
+	{1330, 794},
+	{1330, 798},
+	{1330, 794},
+	{1330,   0},  /* 640x480 / 320x240  */
+	{1343,   0},  /* 800x600 / 400x300  */
+	{   0, 805},  /* 1024x768 / 512x384 */
+	{1688,1066},  /* 1280x1024          */
+	{   0,   0}   /* 1360x1024          */
+};
+
+static const struct SiS_LVDSDes SiS300_PanelType04_2a[] =
+{
+	{1152, 622},
+	{1152, 597},
+	{1152, 622},
+	{1152, 597},
+	{1152, 662},
+	{1232, 722},
+	{   0, 805},
+	{1688,1066},
+	{   0,   0}
+};
+
+/* Custom des data for Barco iQ G200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1b[] =	/* 1024x768 */
+{
+	{1330, 798},  /* 320x200 */
+	{1330, 794},
+	{1330, 798},
+	{1330, 794},
+	{1330,   0},  /* 640x480 / 320x240  */
+	{1343,   0},  /* 800x600 / 400x300  */
+	{   0, 805}   /* 1024x768 / 512x384 */
+};
+
+static const struct SiS_LVDSDes SiS300_PanelType04_2b[] =
+{
+	{1152, 622},
+	{1152, 597},
+	{1152, 622},
+	{1152, 597},
+	{1152, 662},
+	{1232, 722},
+	{   0, 805}
+};
+
+/* CRT1 CRTC for slave modes */
+
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UNTSC[] =
+{
+	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+	  0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+	  0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+	  0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+	  0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
+	  0x00 }},
+	{{0x5d,0x4f,0x81,0x53,0x9c,0x56,0xba,
+	  0x18,0x84,0xdf,0x57,0x00,0x00,0x01,
+	  0x00 }},
+	{{0x80,0x63,0x84,0x6c,0x17,0xec,0xf0,
+	  0x90,0x8c,0x57,0xed,0x20,0x00,0x06,
+	  0x01 }}
+};
+
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1ONTSC[] =
+{
+	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+	  0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+	  0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+	  0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+	  0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
+	  0x00 }},
+	{{0x5d,0x4f,0x81,0x56,0x9c,0x0b,0x3e,
+	  0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,
+	  0x00 }},
+	{{0x7d,0x63,0x81,0x6a,0x16,0xba,0xf0,
+	  0x7f,0x86,0x57,0xbb,0x00,0x00,0x06,
+	  0x01 }}
+};
+
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UPAL[] =
+{
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x55,0x80,0xec,0xba,
+	  0x50,0x84,0xdf,0xed,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x70,0x63,0x94,0x68,0x8d,0x42,0xf1,
+	  0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05,
+	  0x01 }}
+};
+
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1OPAL[] =
+{
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba,
+	  0x20,0x83,0xdf,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0,
+	  0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
+	  0x01 }}
+};
+
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1SOPAL[] =
+{
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
+	  0x00 }},
+	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba,  /* TODO */
+	  0x20,0x83,0xdf,0x70,0x00,0x00,0x05,
+	  0x00 }},
+	{{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0,  /* TODO */
+	  0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
+	  0x01 }}
+};
+
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UNTSC[] =
+{
+	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x6a,0x6a,0x00,0x2d,0xfa,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 17: 640x480 NTSC 7/8  */
+	{{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 24: 800x600 NTSC 7/10 */
+};
+
+static const struct SiS_CHTVRegData SiS300_CHTVReg_ONTSC[] =
+{
+	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x69,0x6a,0x00,0x1e,0xfd,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 16: 640x480 NTSC 1/1 */
+	{{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 23: 800x600 NTSC 3/4 */
+};
+
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UPAL[] =
+{
+	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x63,0x94,0x01,0x50,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 15: 640x480 PAL 5/6 */
+	{{0x84,0x64,0x01,0x4e,0x2f,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 21: 800x600 PAL 3/4 */
+
+};
+
+static const struct SiS_CHTVRegData SiS300_CHTVReg_OPAL[] =
+{
+	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
+	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x61,0x94,0x01,0x36,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 14: 640x480 PAL 1/1 */
+	{{0x83,0x76,0x01,0x40,0x31,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 20: 800x600 PAL 5/6 */
+
+};
+
+static const struct SiS_CHTVRegData SiS300_CHTVReg_SOPAL[] =
+{
+	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
+	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
+	{{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 13: 640x480 PAL 5/4 */
+	{{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 19: 800x600 PAL 1/1 */
+};
+
+static const unsigned char SiS300_CHTVVCLKUNTSC[]  = { 0x29,0x29,0x29,0x29,0x2a,0x2e };
+
+static const unsigned char SiS300_CHTVVCLKONTSC[]  = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
+
+static const unsigned char SiS300_CHTVVCLKSONTSC[] = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
+
+static const unsigned char SiS300_CHTVVCLKUPAL[]   = { 0x2f,0x2f,0x2f,0x2f,0x2f,0x31 };
+
+static const unsigned char SiS300_CHTVVCLKOPAL[]   = { 0x2f,0x2f,0x2f,0x2f,0x30,0x32 };
+
+static const unsigned char SiS300_CHTVVCLKSOPAL[]  = { 0x2f,0x2f,0x2f,0x2f,0x36,0x29 };
+
+
diff --git a/drivers/video/fbdev/sis/310vtbl.h b/drivers/video/fbdev/sis/310vtbl.h
new file mode 100644
index 000000000000..54fcbbf4ef63
--- /dev/null
+++ b/drivers/video/fbdev/sis/310vtbl.h
@@ -0,0 +1,1339 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Register settings for SiS 315/330/340 series
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+static const struct SiS_Ext SiS310_EModeIDTable[] =
+{
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+	{0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+	{0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+	{0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x8 */
+	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x8 */
+	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x16 */
+	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x15 */
+	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3},
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13, 4},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
+	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8  */
+	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8  */
+	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8  */
+	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
+	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
+	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
+	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8  */
+	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8  fstn */
+	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
+	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x32 */
+	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0},
+	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x32 */
+	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x32 */
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x8 */
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x16 */
+	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x32 */
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x8 */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x16 */
+	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x32 */
+	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x8 */
+	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x8 */
+	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x16 */
+	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x16 */
+	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x32 */
+	{0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x32 */
+	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x32 */
+	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x8 */
+	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x16 */
+	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x8 */
+	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x16 */
+	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x32 */
+	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
+	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
+	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
+	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x8 */
+	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x16 */
+	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x32*/
+	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1}, /* 1152x864 */
+	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1}, /* 848x480 */
+	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1},
+	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1},
+	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1}, /* 856x480 */
+	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1},
+	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1},
+	{0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1}, /* 1360x768 */
+	{0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
+	{0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
+	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
+	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
+	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
+	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1}, /* 768x576 */
+	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1},
+	{0x61,0x6a3f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1},
+	{0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7}, /* 1280x800 */
+	{0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+	{0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+	{0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9}, /* 1680x1050 */
+	{0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+	{0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+	{0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1}, /* 1920x1080(i) */
+	{0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+	{0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+	{0x1d,0x6a1b,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1}, /* 960x540 */
+	{0x1e,0x6a3d,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1},
+	{0x1f,0x6a7f,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1},
+	{0x20,0x6a1b,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1}, /* 960x600 */
+	{0x21,0x6a3d,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1},
+	{0x22,0x6a7f,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1},
+	{0x1a,0x0e3b,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8}, /* 1280x854 */
+	{0x1b,0x0e7d,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
+	{0x1c,0x0eff,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
+	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
+};
+
+static const struct SiS_Ext2 SiS310_RefIndex[] =
+{
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x0 */
+	{0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1 */
+	{0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2 */
+	{0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3 */
+	{0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4 */
+	{0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x5 */
+	{0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x6 */
+	{0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x7 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x8 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x9 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xa */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xb */
+	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xc */
+	{0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xd */
+	{0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xe */
+	{0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xf */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e, 0x00, 0x00, 0x00, 0x00}, /* 0x10 */
+	{0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x11 */
+	{0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x12 (6f was 03) */
+	{0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x13 */
+	{0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x14 */
+	{0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x15 */
+	{0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x16 */
+	{0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x17 */
+	{0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x18 */
+	{0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x19 */
+	{0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1a */
+	{0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1b */
+	{0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1c */
+	{0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1d */
+	{0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1e */
+	{0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1f */
+	{0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x20 */
+	{0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x21 */
+	{0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x22 */
+	{0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x23 */
+	{0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x24 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30, 0x56, 0x4e, 0x00, 0x00, 0x00, 0x00}, /* 0x25 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x26 */
+	{0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x27 */
+	{0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x28 */
+	{0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x29 */
+	{0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2a */
+	{0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2b */
+	{0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2c */
+	{0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2d */
+	{0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2e */
+	{0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2f */
+	{0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x30 */
+	{0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x31 */
+	{0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x32 */
+	{0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x33 */
+	{0x2077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x32, 0x40, 0x5e, 0x73}, /* 0x34 */
+	{0x2047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x33, 0x07, 0xff, 0xff}, /* 0x35 */
+	{0x2047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x34, 0x0a, 0xff, 0xff}, /* 0x36 */
+	{0x2077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x35, 0x0b, 0x5f, 0x74}, /* 0x37 */
+	{0x2047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x36, 0x11, 0xff, 0xff}, /* 0x38 */
+	{0x2047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x37, 0x16, 0xff, 0xff}, /* 0x39 */
+	{0x3137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x38, 0x19, 0x60, 0x75}, /* 0x3a */
+	{0x3107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x39, 0x1e, 0xff, 0xff}, /* 0x3b */
+	{0x3307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x3a, 0x20, 0xff, 0xff}, /* 0x3c */
+	{0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3d */
+	{0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3e */
+	{0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3f */    /* FSTN 320x240 */
+	{0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x58, 0x19, 0x42, 0x5b}, /* 0x40 */    /* 0x5b was 0x12 */
+	{0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x59, 0x1e, 0xff, 0xff}, /* 0x41 */
+	{0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x5a, 0x20, 0xff, 0xff}, /* 0x42 */
+	{0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x43 */
+	{0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x44 1400x1050-75Hz */
+	{0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x45 1152x864-60Hz  */
+	{0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x46 1152x864-75Hz  */
+	{0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x47 1152x864-85Hz  */
+	{0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x48 848x480-38Hzi  */
+	{0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x49 848x480-60Hz   */
+	{0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4a 856x480-38Hzi  */
+	{0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4b 856x480-60Hz   */
+	{0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4c 1360x768-60Hz  */
+	{0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4d 768x576-56Hz   */
+	{0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5b, 0x19, 0x4f, 0x5c}, /* 0x4e 1280x800-60Hz  */
+	{0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5c, 0x1e, 0xff, 0xff}, /* 0x4f 1280x800-75Hz  */
+	{0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5d, 0x20, 0xff, 0xff}, /* 0x50 1280x800-85Hz  */
+	{0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x51 1680x1050-60Hz */
+	{0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x52 1920x1080 60Hzi */
+	{0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x53 960x540 60Hz */
+	{0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x54 960x600 60Hz */
+	{0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x62, 0x19, 0x61, 0x76}, /* 0x55 1280x854-60Hz  */
+	{0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x63, 0x1e, 0xff, 0xff}, /* 0x56 1280x854-75Hz  */
+	{0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x64, 0x20, 0xff, 0xff}, /* 0x57 1280x854-85Hz  */
+	{0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiS310_CRT1Table[] =
+{
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},  /* 0x0 */
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},  /* 0x1 */
+ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
+   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
+   0x01}},  /* 0x2 */
+ {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
+   0x01}},  /* 0x3 */
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},  /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* corrected 640x480-60 */
+   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+   0x00}},  /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,    /* corrected 640x480-72 */
+   0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
+   0x00}},  /* 0x6 */
+ {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
+   0x00}},  /* 0x7 */
+ {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+   0x00}},  /* 0x8 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* Corrected VBE */
+   0x61}},  /* 0x9 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
+   0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
+   0x61}},  /* 0xa */
+ {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
+   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* Corrected VBE */
+   0x61}},  /* 0xb */
+ {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
+   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* Corrected VDE, VBE */
+   0x00}},  /* 0xc */
+ {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
+   0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
+   0x01}},  /* 0xd */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
+   0x01}},  /* 0xe */
+ {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
+   0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
+   0x01}},  /* 0xf */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
+   0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
+   0x01}},  /* 0x10 */
+ {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
+   0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
+   0x01}},  /* 0x11 */
+ {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
+   0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
+   0x61}},  /* 0x12 */
+ {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
+   0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
+   0x61}},  /* 0x13 */
+ {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
+   0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
+   0x61}},  /* 0x14 */
+ {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
+   0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
+   0x00}},  /* 0x15 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}},  /* 0x16 */
+ {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}},  /* 0x17 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
+   0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
+   0x01}},  /* 0x18 */
+ {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
+   0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
+   0x01}},  /* 0x19 */
+ {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
+   0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
+   0x62}},  /* 0x1a */
+ {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
+   0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
+   0x62}},  /* 0x1b */
+ {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
+   0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
+   0x00}},  /* 0x1c */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
+   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+   0x01}},  /* 0x1d */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
+   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+   0x01}},  /* 0x1e */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
+   0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
+   0x01}},  /* 0x1f */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}},  /* 0x20 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}},  /* 0x21 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}},  /* 0x22 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}},  /* 0x23 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}},  /* 0x24 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}},  /* 0x25 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}},  /* 0x26 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}},  /* 0x27 */
+ {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
+   0x63}},  /* 0x28 */
+ {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
+   0x63}},  /* 0x29 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}},  /* 0x2a */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}},  /* 0x2b */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}},  /* 0x2c */
+ {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
+   0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
+   0x44}},  /* 0x2d */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
+   0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
+   0x44}},  /* 0x2e */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
+   0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
+   0x44}},  /* 0x2f */
+ {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
+   0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
+   0x44}},  /* 0x30 */
+ {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
+   0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
+   0x00}},  /* 0x31 */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
+   0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+   0x01}},  /* 0x32 */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+   0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
+   0x01}},  /* 0x33 */
+ {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
+   0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
+   0x01}},  /* 0x34 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
+   0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
+   0x01}},  /* 0x35 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+   0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+   0x01}},  /* 0x36 */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* 95 was 15 - illegal HBE! */
+   0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+   0x01}},  /* 0x37 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}},  /* 0x38 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}},  /* 0x39 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+   0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+   0x01}},  /* 0x3a */
+ {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,	/* 1280x960-60 - corrected */
+   0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
+   0x01}},  /* 0x3b */
+ {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
+   0x00}},  /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,	/* 720x576, corrected to 60Hz */
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}},  /* 0x3d */
+ {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
+   0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
+   0x00}},  /* 0x3e */
+ {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
+   0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
+   0x00}},  /* 0x3f */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
+   0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
+   0x01}},  /* 0x40 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}},  /* 0x41 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
+   0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
+   0x01}},  /* 0x42 */
+ {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
+   0x00}},  /* 0x43 */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */
+   0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
+   0x01}},  /* 0x44 */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}},  /* 0x45 */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */
+   0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
+   0x00}},  /* 0x46 */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}},  /* 0x47 */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */
+   0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+   0x00}},  /* 0x48 */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */
+   0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
+   0x01}},  /* 0x49 */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84  */
+   0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
+   0x01}},  /* 0x4a */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* 1400x1050-75  */
+   0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
+   0x00}},  /* 0x4b */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
+   0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+   0x01}},  /* 0x4c */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, /* 768x576, corrected to 60Hz */
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}},  /* 0x4d */
+ {{0x5f,0x27,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* FSTN 320x240 (working) */
+   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+   0x00}},  /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
+   0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+   0x21}},  /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, /* 1680x1050-60 */
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+   0x20}},  /* 0x50 */
+ {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0, /* 1920x1080-60i */
+   0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
+   0x61}},  /* 0x51 */
+ {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0, /* 960x540-60 */
+   0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
+   0x41}},  /* 0x52 */
+ {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0, /* 960x600-60 */
+   0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
+   0x01}},  /* 0x53 */
+ {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */
+   0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
+   0x41}},  /* 0x54 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+   0x40}},  /* 0x55 */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+   0x00}},  /* 0x56 */
+ {{0xd7,0xc7,0xc7,0x9b,0xd1,0x15,0xd1,0x10, /* 1600x1200 for LCDA */
+   0xb2,0x86,0xaf,0xb0,0xd2,0x2f,0x00,0x03,
+   0x00}},  /* 0x57 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 60 Hz */
+   0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+   0x01}},  /* 0x58 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 75 Hz */
+   0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+   0x01}},  /* 0x59 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xdc, /* 1280x768 (1280x1024) 85 Hz */
+   0x95,0x89,0xff,0x94,0x2f,0x21,0x00,0x07,
+   0x01}},  /* 0x5a */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x800 (1280x1024) 60 Hz */
+   0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+   0x01}},  /* 0x5b */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x800 (1280x1024) 75 Hz */
+   0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+   0x01}},  /* 0x5c */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x800 (1280x1024) 85 Hz */
+   0xa5,0x89,0x1f,0xa4,0x2f,0x01,0x00,0x07,
+   0x01}},  /* 0x5d */
+ {{0x7f,0x63,0x63,0x83,0x6d,0x1d,0x0b,0x3e, /* 800x480 (wide) 60 Hz */
+   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x06,
+   0x00}},  /* 0x5e */
+ {{0xa0,0x7f,0x7f,0x84,0x85,0x97,0x52,0xf0, /* 1024x576 (wide) 60 Hz */
+   0x41,0x85,0x3f,0x40,0x53,0x00,0x00,0x02,
+   0x01}},  /* 0x5f */
+ {{0xc9,0x9f,0x9f,0x8d,0xb0,0x15,0xec,0xf0, /* 1280x720 (wide) 60 Hz */
+   0xd4,0x89,0xcf,0xd3,0xed,0x20,0x00,0x07,
+   0x01}},  /* 0x60 */
+ {{0xcb,0x9f,0x9f,0x8f,0xa5,0x13,0x5b,0xff, /* 1280x854-60 wide */
+   0x56,0x89,0x55,0x55,0x5c,0x30,0x00,0x07,
+   0x01}},  /* 0x61 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x854 (1280x1024) 60 Hz */
+   0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+   0x41}},  /* 0x62 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x854 (1280x1024) 75 Hz */
+   0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+   0x41}},  /* 0x63 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x854 (1280x1024) 85 Hz */
+   0xc0,0x84,0x55,0xbf,0x2f,0x01,0x00,0x07,
+   0x41}}   /* 0x64 */
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_315[] =
+{
+	{ 0x3b,0x22,0x01,143},
+	{ 0x5c,0x23,0x01,166},
+	{ 0x5c,0x23,0x01,166},
+	{ 0x5c,0x23,0x01,166},
+	{ 0x5c,0x23,0x01,166},
+	{ 0x5c,0x23,0x01,166},
+	{ 0x5c,0x23,0x01,166},
+	{ 0x5c,0x23,0x01,166}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_650[] =
+{
+	{ 0x5a,0x64,0x82, 66},
+	{ 0xb3,0x45,0x82, 83},
+	{ 0x37,0x61,0x82,100},
+	{ 0x37,0x22,0x82,133},
+	{ 0x37,0x61,0x82,100},
+	{ 0x37,0x22,0x82,133},
+	{ 0x37,0x22,0x82,133},
+	{ 0x37,0x22,0x82,133}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_330[] =
+{
+	{ 0x5c,0x23,0x01,166},
+	{ 0x5c,0x23,0x01,166},
+	{ 0x7c,0x08,0x01,200},
+	{ 0x79,0x06,0x01,250},
+	{ 0x7c,0x08,0x01,200},
+	{ 0x7c,0x08,0x01,200},
+	{ 0x7c,0x08,0x01,200},
+	{ 0x79,0x06,0x01,250}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_660[] =
+{
+	{ 0x5c,0x23,0x82,166},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x37,0x21,0x82,200},
+	{ 0x37,0x22,0x82,133},
+	{ 0x29,0x21,0x82,150},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x37,0x21,0x82,200}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_760[] =
+{
+	{ 0x37,0x22,0x82,133},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x7c,0x08,0x82,200},
+	{ 0x29,0x21,0x82,150},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x37,0x21,0x82,200}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_761[] =
+{
+	{ 0x37,0x22,0x82,133},  /* Preliminary */
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x7c,0x08,0x82,200},
+	{ 0x29,0x21,0x82,150},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x37,0x21,0x82,200}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_340[] =
+{
+	{ 0x79,0x06,0x01,250},
+	{ 0x7c,0x08,0x01,200},
+	{ 0x7c,0x08,0x80,200},
+	{ 0x79,0x06,0x80,250},
+	{ 0x29,0x01,0x81,300},
+	{ 0x29,0x01,0x81,300},
+	{ 0x29,0x01,0x81,300},
+	{ 0x29,0x01,0x81,300}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_1[] = /* ECLK */
+{
+	{ 0x29,0x21,0x82,150},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x37,0x21,0x82,200},
+	{ 0x37,0x22,0x82,133},
+	{ 0x37,0x22,0x82,133},
+	{ 0x37,0x22,0x82,133},
+	{ 0x37,0x22,0x82,133}
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_1_340[] =
+{
+	{ 0x7c,0x08,0x01,200},
+	{ 0x7c,0x08,0x01,200},
+	{ 0x7c,0x08,0x80,200},
+	{ 0x79,0x06,0x80,250},
+	{ 0x29,0x01,0x81,300},
+	{ 0x29,0x01,0x81,300},
+	{ 0x29,0x01,0x81,300},
+	{ 0x29,0x01,0x81,300}
+};
+
+static struct SiS_VCLKData SiS310_VCLKData[] =
+{
+	{ 0x1b,0xe1, 25}, /* 0x00 */
+	{ 0x4e,0xe4, 28}, /* 0x01 */
+	{ 0x57,0xe4, 31}, /* 0x02 */
+	{ 0xc3,0xc8, 36}, /* 0x03 */
+	{ 0x42,0xe2, 40}, /* 0x04 */
+	{ 0xfe,0xcd, 43}, /* 0x05 */
+	{ 0x5d,0xc4, 44}, /* 0x06 */
+	{ 0x52,0xe2, 49}, /* 0x07 */
+	{ 0x53,0xe2, 50}, /* 0x08 */
+	{ 0x74,0x67, 52}, /* 0x09 */
+	{ 0x6d,0x66, 56}, /* 0x0a */
+	{ 0x5a,0x64, 65}, /* 0x0b */  /* was 6c c3 - WRONG */
+	{ 0x46,0x44, 67}, /* 0x0c */
+	{ 0xb1,0x46, 68}, /* 0x0d */
+	{ 0xd3,0x4a, 72}, /* 0x0e */
+	{ 0x29,0x61, 75}, /* 0x0f */
+	{ 0x6e,0x46, 76}, /* 0x10 */
+	{ 0x2b,0x61, 78}, /* 0x11 */
+	{ 0x31,0x42, 79}, /* 0x12 */
+	{ 0xab,0x44, 83}, /* 0x13 */
+	{ 0x46,0x25, 84}, /* 0x14 */
+	{ 0x78,0x29, 86}, /* 0x15 */
+	{ 0x62,0x44, 94}, /* 0x16 */
+	{ 0x2b,0x41,104}, /* 0x17 */
+	{ 0x3a,0x23,105}, /* 0x18 */
+	{ 0x70,0x44,108}, /* 0x19 */
+	{ 0x3c,0x23,109}, /* 0x1a */
+	{ 0x5e,0x43,113}, /* 0x1b */
+	{ 0xbc,0x44,116}, /* 0x1c */
+	{ 0xe0,0x46,132}, /* 0x1d */
+	{ 0x54,0x42,135}, /* 0x1e */
+	{ 0xea,0x2a,139}, /* 0x1f */
+	{ 0x41,0x22,157}, /* 0x20 */
+	{ 0x70,0x24,162}, /* 0x21 */
+	{ 0x30,0x21,175}, /* 0x22 */
+	{ 0x4e,0x22,189}, /* 0x23 */
+	{ 0xde,0x26,194}, /* 0x24 */
+	{ 0x62,0x06,202}, /* 0x25 */
+	{ 0x3f,0x03,229}, /* 0x26 */
+	{ 0xb8,0x06,234}, /* 0x27 */
+	{ 0x34,0x02,253}, /* 0x28 */
+	{ 0x58,0x04,255}, /* 0x29 */
+	{ 0x24,0x01,265}, /* 0x2a */
+	{ 0x9b,0x02,267}, /* 0x2b */
+	{ 0x70,0x05,270}, /* 0x2c */
+	{ 0x25,0x01,272}, /* 0x2d */
+	{ 0x9c,0x02,277}, /* 0x2e */
+	{ 0x27,0x01,286}, /* 0x2f */
+	{ 0x3c,0x02,291}, /* 0x30 */
+	{ 0xef,0x0a,292}, /* 0x31 */
+	{ 0xf6,0x0a,310}, /* 0x32 */
+	{ 0x95,0x01,315}, /* 0x33 */
+	{ 0xf0,0x09,324}, /* 0x34 */
+	{ 0xfe,0x0a,331}, /* 0x35 */
+	{ 0xf3,0x09,332}, /* 0x36 */
+	{ 0xea,0x08,340}, /* 0x37 */
+	{ 0xe8,0x07,376}, /* 0x38 */
+	{ 0xde,0x06,389}, /* 0x39 */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
+	{ 0x31,0xc2, 39}, /* 0x40 */
+	{ 0x60,0x36, 30}, /* 0x41 Chrontel */
+	{ 0x40,0x4a, 28}, /* 0x42 Chrontel */
+	{ 0x9f,0x46, 44}, /* 0x43 Chrontel */
+	{ 0x97,0x2c, 26}, /* 0x44 */
+	{ 0x44,0xe4, 25}, /* 0x45 Chrontel */
+	{ 0x7e,0x32, 47}, /* 0x46 Chrontel */
+	{ 0x8a,0x24, 31}, /* 0x47 Chrontel */
+	{ 0x97,0x2c, 26}, /* 0x48 Chrontel */
+	{ 0xce,0x3c, 39}, /* 0x49 */
+	{ 0x52,0x4a, 36}, /* 0x4a Chrontel */
+	{ 0x34,0x61, 95}, /* 0x4b */
+	{ 0x78,0x27,108}, /* 0x4c - was 102 */
+	{ 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
+	{ 0x41,0x4e, 21}, /* 0x4e */
+	{ 0xa1,0x4a, 29}, /* 0x4f Chrontel */
+	{ 0x19,0x42, 42}, /* 0x50 */
+	{ 0x54,0x46, 58}, /* 0x51 Chrontel */
+	{ 0x25,0x42, 61}, /* 0x52 */
+	{ 0x44,0x44, 66}, /* 0x53 Chrontel */
+	{ 0x3a,0x62, 70}, /* 0x54 Chrontel */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800  */
+	{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
+	{ 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+	{ 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
+	{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
+	{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
+	{ 0x45,0x25, 83}, /* 0x6c 1280x800 */
+	{ 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+	{ 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+	{ 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+	{ 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+	{ 0x2b,0xc2, 35}, /* 0x71 768x576@60 */
+	{ 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+	{ 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+	{ 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+	{ 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+	{ 0x75,0x13, 84}  /* 0x76 1280x854 60Hz (wide) */
+};
+
+static struct SiS_VBVCLKData SiS310_VBVCLKData[] =
+{
+	{ 0x1b,0xe1, 25}, /* 0x00 */
+	{ 0x4e,0xe4, 28}, /* 0x01 */
+	{ 0x57,0xe4, 31}, /* 0x02 */
+	{ 0xc3,0xc8, 36}, /* 0x03 */
+	{ 0x42,0x47, 40}, /* 0x04 */
+	{ 0xfe,0xcd, 43}, /* 0x05 */
+	{ 0x5d,0xc4, 44}, /* 0x06 */
+	{ 0x52,0x47, 49}, /* 0x07 */
+	{ 0x53,0x47, 50}, /* 0x08 */
+	{ 0x74,0x67, 52}, /* 0x09 */
+	{ 0x6d,0x66, 56}, /* 0x0a */
+	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301: 35,62  */
+	{ 0x46,0x44, 67}, /* 0x0c */
+	{ 0xb1,0x46, 68}, /* 0x0d */
+	{ 0xd3,0x4a, 72}, /* 0x0e */
+	{ 0x29,0x61, 75}, /* 0x0f */
+	{ 0x6d,0x46, 75}, /* 0x10 */
+	{ 0x41,0x43, 78}, /* 0x11 */
+	{ 0x31,0x42, 79}, /* 0x12 */
+	{ 0xab,0x44, 83}, /* 0x13 */
+	{ 0x46,0x25, 84}, /* 0x14 */
+	{ 0x78,0x29, 86}, /* 0x15 */
+	{ 0x62,0x44, 94}, /* 0x16 */
+	{ 0x2b,0x22,104}, /* 0x17 */
+	{ 0x49,0x24,105}, /* 0x18 */
+	{ 0xf8,0x2f,108}, /* 0x19 */  /* 1400x1050 LCD */
+	{ 0x3c,0x23,109}, /* 0x1a */
+	{ 0x5e,0x43,113}, /* 0x1b */
+	{ 0xbc,0x44,116}, /* 0x1c */
+	{ 0xe0,0x46,132}, /* 0x1d */
+	{ 0xe2,0x46,135}, /* 0x1e */  /* 1280x1024-75, better clock for VGA2 */
+	{ 0xe5,0x46,139}, /* 0x1f */  /* 1024x768-120, better clock for VGA2 */
+	{ 0x15,0x01,157}, /* 0x20 */  /* 1280x1024-85, better clock for VGA2 */
+	{ 0x70,0x09,162}, /* 0x21 */  /* 1600x1200-60, better clock for VGA2 */
+	{ 0x30,0x21,175}, /* 0x22 */
+	{ 0x4e,0x22,189}, /* 0x23 */
+	{ 0xde,0x26,194}, /* 0x24 */
+	{ 0x70,0x07,202}, /* 0x25 */
+	{ 0x3f,0x03,229}, /* 0x26 */
+	{ 0xb8,0x06,234}, /* 0x27 */
+	{ 0x34,0x02,253}, /* 0x28 */
+	{ 0x58,0x04,255}, /* 0x29 */
+	{ 0x24,0x01,265}, /* 0x2a */
+	{ 0x9b,0x02,267}, /* 0x2b */
+	{ 0x70,0x05,270}, /* 0x2c */
+	{ 0x25,0x01,272}, /* 0x2d */
+	{ 0x9c,0x02,277}, /* 0x2e */
+	{ 0x27,0x01,286}, /* 0x2f */
+	{ 0x3c,0x02,291}, /* 0x30 */
+	{ 0xef,0x0a,292}, /* 0x31 */
+	{ 0xf6,0x0a,310}, /* 0x32 */
+	{ 0x95,0x01,315}, /* 0x33 */
+	{ 0xf0,0x09,324}, /* 0x34 */
+	{ 0xfe,0x0a,331}, /* 0x35 */
+	{ 0xf3,0x09,332}, /* 0x36 */
+	{ 0xea,0x08,340}, /* 0x37 */
+	{ 0xe8,0x07,376}, /* 0x38 */
+	{ 0xde,0x06,389}, /* 0x39 */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV - start */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
+	{ 0x31,0xc2, 39}, /* 0x40 */
+	{ 0x2e,0x48, 25}, /* 0x41 Replacement for LCD on 315 for index 0 */
+	{ 0x24,0x46, 25}, /* 0x42 Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
+	{ 0x26,0x64, 28}, /* 0x43 Replacement for LCD on 315 for index 1 */
+	{ 0x37,0x64, 40}, /* 0x44 Replacement for LCD on 315 for index 4 */
+	{ 0xa1,0x42,108}, /* 0x45 1280x960 LCD */
+	{ 0x37,0x61,100}, /* 0x46 1280x960 LCD */
+	{ 0x78,0x27,108}, /* 0x47 */
+	{ 0x97,0x2c, 26}, /* 0x48 UNUSED */
+	{ 0xce,0x3c, 39}, /* 0x49 UNUSED */
+	{ 0x52,0x4a, 36}, /* 0x4a UNUSED */
+	{ 0x34,0x61, 95}, /* 0x4b UNUSED */
+	{ 0x78,0x27,108}, /* 0x4c UNUSED */
+	{ 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
+	{ 0x41,0x4e, 21}, /* 0x4e */
+	{ 0xa1,0x4a, 29}, /* 0x4f UNUSED */
+	{ 0x19,0x42, 42}, /* 0x50 UNUSED */
+	{ 0x54,0x46, 58}, /* 0x51 UNUSED */
+	{ 0x25,0x42, 61}, /* 0x52 UNUSED */
+	{ 0x44,0x44, 66}, /* 0x53 UNUSED */
+	{ 0x3a,0x62, 70}, /* 0x54 UNUSED */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP, UNUSED */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60  */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85  */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
+	{ 0xce,0x1e, 73}, /* 0x5c 1280x800_2 LCD (SiS LVDS) - (CRT1: 45 25 83) */
+	{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
+	{ 0x52,0x27, 75}, /* 0x5f 1280x720 (TMDS + HDTV) (correct) */
+	{ 0xc8,0x48, 77}, /* 0x60 1280x768_2 (SiS LVDS) */
+	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 (SiS LVDS) - temp */
+	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+	{ 0x9c,0x62, 69}, /* 0x63 1280x720 (SiS LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+	{ 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced (UNUSED) */
+	{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
+	{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
+	{ 0x9c,0x62, 69}, /* 0x6c 1280x800 (SiS TMDS) (special) */
+	{ 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+	{ 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+	{ 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+	{ 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+	{ 0x2b,0xc2, 35}, /* 0x71 768@576@60 */
+	{ 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+	{ 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+	{ 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+	{ 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+	{ 0x75,0x13, 84}  /* 0x76 1280x854 60Hz (SiS LVDS) LCD */
+};
+
+static const unsigned char SiS310_SR15[4 * 8] =
+{
+	0x00,0x04,0x60,0x60,
+	0x0f,0x0f,0x0f,0x0f,
+	0xba,0xba,0xba,0xba,
+	0xa9,0xa9,0xac,0xac,
+	0xa0,0xa0,0xa0,0xa8,
+	0x00,0x00,0x02,0x02,
+	0x30,0x30,0x40,0x40,
+	0x00,0xa5,0xfb,0xf6
+};
+
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTbl[] =
+{
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}},
+	{{0x10,0x40}}
+};
+
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTblLVDS[] =
+{
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}},
+	{{0x28,0xc8}}
+};
+
+/**************************************************************/
+/* SIS VIDEO BRIDGE ----------------------------------------- */
+/**************************************************************/
+
+static const struct SiS_LCDData SiS310_St2LCD1024x768Data[] =
+{
+	{   62,  25, 800, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{   62,  25, 800, 546,1344, 806},
+	{  104,  45, 945, 496,1344, 806},
+	{   62,  25, 800, 546,1344, 806},
+	{   31,  18,1008, 624,1344, 806},
+	{    1,   1,1344, 806,1344, 806}
+};
+
+static const struct SiS_LCDData SiS310_ExtLCD1024x768Data[] =
+{
+	{   42,  25,1536, 419,1344, 806},
+	{   48,  25,1536, 369,1344, 806},
+	{   42,  25,1536, 419,1344, 806},
+	{   48,  25,1536, 369,1344, 806},
+	{   12,   5, 896, 500,1344, 806},
+	{   42,  25,1024, 625,1344, 806},
+	{    1,   1,1344, 806,1344, 806}
+};
+
+static const struct SiS_LCDData SiS310_St2LCD1280x1024Data[] =
+{
+	{   22,   5, 800, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
+	{  176,  45, 900, 510,1650,1088},
+	{  176,  45, 900, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
+	{   13,   5,1024, 675,1560,1152},
+	{   16,   9,1266, 804,1688,1072},
+	{    1,   1,1688,1066,1688,1066}
+};
+
+static const struct SiS_LCDData SiS310_ExtLCD1280x1024Data[] =
+{
+	{  211,  60,1024, 501,1688,1066},
+	{  211,  60,1024, 508,1688,1066},
+	{  211,  60,1024, 501,1688,1066},
+	{  211,  60,1024, 508,1688,1066},
+	{  211,  60,1024, 500,1688,1066},
+	{  211,  75,1024, 625,1688,1066},
+	{  211, 120,1280, 798,1688,1066},
+	{    1,   1,1688,1066,1688,1066}
+};
+
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_1024x768_1[] =
+{
+	{{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+	{{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+};
+
+/**************************************************************/
+/* LVDS, CHRONTEL ------------------------------------------- */
+/**************************************************************/
+
+static const struct SiS_LVDSData SiS310_CHTVUPALData[] =
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 625, 840, 625},
+	{ 960, 750, 960, 750},
+	{1400,1000,1400,1000}
+};
+
+static const struct SiS_LVDSData SiS310_CHTVOPALData[] =
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 625, 840, 625},
+	{ 944, 625, 944, 625},
+	{1400, 875,1400, 875}
+};
+
+static const struct SiS_LVDSData SiS310_CHTVUPALMData[] =
+{
+	{ 840, 600, 840, 600},
+	{ 840, 600, 840, 600},
+	{ 840, 600, 840, 600},
+	{ 840, 600, 840, 600},
+	{ 784, 600, 784, 600},
+	{1064, 750,1064, 750},
+	{1160, 945,1160, 945}
+};
+
+static const struct SiS_LVDSData SiS310_CHTVOPALMData[] =
+{
+	{ 840, 525, 840, 525},
+	{ 840, 525, 840, 525},
+	{ 840, 525, 840, 525},
+	{ 840, 525, 840, 525},
+	{ 784, 525, 784, 525},
+	{1040, 700,1040, 700},
+	{1160, 840,1160, 840}
+};
+
+static const struct SiS_LVDSData SiS310_CHTVUPALNData[] =
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 625, 840, 625},
+	{ 960, 750, 960, 750},
+	{1400,1000,1400,1000}
+};
+
+static const struct SiS_LVDSData SiS310_CHTVOPALNData[] =
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 625, 840, 625},
+	{ 944, 625, 944, 625},
+	{1400, 875,1400, 875}
+};
+
+static const struct SiS_LVDSData SiS310_CHTVSOPALData[] =   /* (super overscan - no effect on 7019) */
+{
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{1008, 625,1008, 625},
+	{ 840, 625, 840, 625},
+	{ 944, 625, 944, 625},
+        {1400, 875,1400, 875}
+};
+
+/* CRT1 CRTC for Chrontel TV slave modes */
+
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UNTSC[] =
+{
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+   0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
+   0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+   0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
+   0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+   0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
+   0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+   0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
+   0x00 }},
+ {{0x5d,0x4f,0x81,0x56,0x99,0x56,0xba,
+   0x0a,0x84,0xdf,0x57,0x00,0x00,0x01,
+   0x00 }},
+ {{0x80,0x63,0x84,0x6d,0x0f,0xec,0xf0,
+   0x7a,0x8f,0x57,0xed,0x20,0x00,0x06,
+   0x01 }},
+ {{0x8c,0x7f,0x90,0x86,0x09,0xaf,0xf5,
+   0x36,0x88,0xff,0xb0,0x10,0x00,0x02,
+   0x01}}
+};
+
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1ONTSC[] =
+{
+ {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
+   0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
+   0x00 }},
+ {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
+   0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
+   0x00 }},
+ {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
+   0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
+   0x00 }},
+ {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
+   0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
+   0x00 }},
+ {{0x5d,0x4f,0x81,0x58,0x9d,0x0b,0x3e,
+   0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,
+   0x00 }},
+ {{0x7d,0x63,0x81,0x68,0x0e,0xba,0xf0,
+   0x78,0x8a,0x57,0xbb,0x20,0x00,0x06,
+   0x01 }},
+ {{0x8c,0x7f,0x90,0x82,0x06,0x46,0xf5,
+   0x15,0x88,0xff,0x47,0x70,0x00,0x02,
+   0x01 }}
+};
+
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UPAL[] =
+{
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
+   0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+   0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
+   0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+   0x00 }},
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x6f,0xba,
+   0x15,0x83,0xdf,0x70,0x00,0x00,0x01,
+   0x00 }},
+ {{0x73,0x63,0x97,0x69,0x8b,0xec,0xf0,
+   0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
+   0x01 }},
+ {{0xaa,0x7f,0x8e,0x8e,0x96,0xe6,0xf5,
+   0x50,0x88,0xff,0xe7,0x10,0x00,0x02,
+   0x01}}
+};
+
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1OPAL[] =
+{
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
+   0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+   0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
+   0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
+   0x00 }},
+ {{0x64,0x4f,0x88,0x58,0x9d,0x6f,0xba,
+   0x15,0x83,0xdf,0x70,0x00,0x00,0x01,
+   0x00 }},
+ {{0x71,0x63,0x95,0x69,0x8c,0x6f,0xf0,
+   0x5a,0x8b,0x57,0x70,0x20,0x00,0x05,
+   0x01 }},
+ {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5,
+   0x28,0x88,0xff,0x6a,0x10,0x00,0x02,
+   0x01 }}
+};
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UNTSC[] =
+{
+ {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x6a,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x7e,0x80,0x98,0x00}},
+ {{0xcf,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x88,0x30,0x7f,0x00}},
+ {{0xee,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xd3,0xf2,0x36,0x00}}
+}; /* WRONG: 0x02: should be 0xfx, because if CIVEnable is clear, this should be set;
+             0x07: Blacklevel: NTSC/PAL-M: Should be 131 (0x83), and not 0x50/0x5a
+	                       PAL/PAL-N:  110 (0x6e)
+			       NTSC-J:     102 (0x66)
+	     0x0c-0x0f: CIV is not default as in datasheet
+      MISSING: 0x21: Should set D1 to ZERO (for NTSC, PAL-M) or ONE (PAL, NTSC-J)
+      Most of this is wrong in all NTSC and PAL register arrays. But I won't correct
+      it as long as it works. For NTSC-J, the blacklevel is corrected in init301.c;
+      for PAL-M and PAL-N all above is corrected.
+    */
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_ONTSC[] =
+{
+ {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x69,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x43,0x04,0x00}},
+ {{0xce,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1c,0x00,0x82,0x97,0x00}},
+ {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
+};
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPAL[] =
+{
+ {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}},
+ {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x1f,0x84,0x3d,0x28,0x00}},
+ {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
+};
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPAL[] =
+{
+ {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}},
+ {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00}},
+ {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
+};
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALM[] =
+{
+ {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x72,0x77,0xfb,0x6e,0x84,0x2e,0x02,0x83,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}},
+ {{0xd7,0x77,0xf7,0xc8,0x84,0x3b,0x02,0x83,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}},
+ {{0xf6,0x77,0xfb,0x66,0x87,0x32,0x01,0x83,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}}
+#if 0 /* Correct blacklevel and CFRB */
+ {{0x72,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}},
+ {{0xd7,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}},
+ {{0xf6,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}}
+#endif
+};
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALM[] =
+{
+ {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
+ {{0x71,0x77,0xfb,0x6e,0x84,0x1e,0x00,0x83,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}},
+ {{0xd6,0x77,0xf7,0xb6,0x83,0x2c,0x02,0x83,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}},
+ {{0xf5,0x77,0xfb,0x66,0x8c,0x21,0x02,0x83,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}}
+#if 0 /* Correct blacklevel and CFRB */
+ {{0x71,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}},
+ {{0xd6,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}},
+ {{0xf5,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}}
+#endif
+};
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALN[] =
+{
+ {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}
+#if 0 /* Correct blacklevel, CIV and CFRB */
+ {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}},
+ {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x19,0x78,0xef,0x35,0x00}},
+ {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x1a,0x33,0x3f,0x2f,0x00}}
+#endif
+};
+
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALN[] =
+{
+ {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
+ {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}
+#if 0 /* Correct blacklevel, CIV and CFRB */
+ {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}},
+ {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x1f,0x15,0xc0,0x1e,0x00}},
+ {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x1d,0xf1,0x6c,0xcb,0x00}}
+#endif
+};
+
+static const unsigned char SiS310_CHTVVCLKUNTSC[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKONTSC[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
+
+static const unsigned char SiS310_CHTVVCLKUPAL[]  = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPAL[]  = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
+
+static const unsigned char SiS310_CHTVVCLKUPALM[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKOPALM[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
+
+static const unsigned char SiS310_CHTVVCLKUPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
+
+
diff --git a/drivers/video/fbdev/sis/Makefile b/drivers/video/fbdev/sis/Makefile
new file mode 100644
index 000000000000..f7c0046e5b1d
--- /dev/null
+++ b/drivers/video/fbdev/sis/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the SiS framebuffer device driver
+#
+
+obj-$(CONFIG_FB_SIS) += sisfb.o
+
+sisfb-objs := sis_main.o sis_accel.o init.o init301.o initextlfb.o
diff --git a/drivers/video/fbdev/sis/init.c b/drivers/video/fbdev/sis/init.c
new file mode 100644
index 000000000000..bd40f5ecd901
--- /dev/null
+++ b/drivers/video/fbdev/sis/init.c
@@ -0,0 +1,3655 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Mode initializing code (CRT1 section) for
+ * for SiS 300/305/540/630/730,
+ *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ *     XGI Volari V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
+ * Used by permission.
+ */
+
+#include "init.h"
+
+#ifdef CONFIG_FB_SIS_300
+#include "300vtbl.h"
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+#include "310vtbl.h"
+#endif
+
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(PAGE,SiSSetMode)
+#endif
+
+/*********************************************/
+/*         POINTER INITIALIZATION            */
+/*********************************************/
+
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+static void
+InitCommonPointer(struct SiS_Private *SiS_Pr)
+{
+   SiS_Pr->SiS_SModeIDTable  = SiS_SModeIDTable;
+   SiS_Pr->SiS_StResInfo     = SiS_StResInfo;
+   SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;
+   SiS_Pr->SiS_StandTable    = SiS_StandTable;
+
+   SiS_Pr->SiS_NTSCTiming     = SiS_NTSCTiming;
+   SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
+   SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
+   SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;
+
+   SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
+   SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
+   SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
+#if 0
+   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
+   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
+#endif
+
+   SiS_Pr->SiS_StPALData   = SiS_StPALData;
+   SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;
+   SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;
+   SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
+   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData;
+   SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
+   SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
+   SiS_Pr->SiS_St525iData  = SiS_StNTSCData;
+   SiS_Pr->SiS_St525pData  = SiS_St525pData;
+   SiS_Pr->SiS_St750pData  = SiS_St750pData;
+   SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData;
+   SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData;
+   SiS_Pr->SiS_Ext750pData = SiS_Ext750pData;
+
+   SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
+   SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
+
+   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
+   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
+   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
+   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
+   SiS_Pr->SiS_LCD1280x800_2Data    = SiS_LCD1280x800_2Data;
+   SiS_Pr->SiS_LCD1280x854Data      = SiS_LCD1280x854Data;
+   SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
+   SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
+   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
+   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
+   SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
+   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
+   SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
+
+   SiS_Pr->SiS_LVDS320x240Data_1   = SiS_LVDS320x240Data_1;
+   SiS_Pr->SiS_LVDS320x240Data_2   = SiS_LVDS320x240Data_2;
+   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
+   SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;
+   SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;
+   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;
+
+   SiS_Pr->SiS_LVDSCRT1320x240_1     = SiS_LVDSCRT1320x240_1;
+   SiS_Pr->SiS_LVDSCRT1320x240_2     = SiS_LVDSCRT1320x240_2;
+   SiS_Pr->SiS_LVDSCRT1320x240_2_H   = SiS_LVDSCRT1320x240_2_H;
+   SiS_Pr->SiS_LVDSCRT1320x240_3     = SiS_LVDSCRT1320x240_3;
+   SiS_Pr->SiS_LVDSCRT1320x240_3_H   = SiS_LVDSCRT1320x240_3_H;
+   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
+   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
+#if 0
+   SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
+   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;
+   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
+#endif
+
+   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
+   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
+
+   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
+   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_300
+static void
+InitTo300Pointer(struct SiS_Private *SiS_Pr)
+{
+   InitCommonPointer(SiS_Pr);
+
+   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
+   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
+   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
+   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
+   if(SiS_Pr->ChipType == SIS_300) {
+      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
+   } else {
+      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
+   }
+   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
+   SiS_Pr->SiS_VBVCLKData    = (struct SiS_VBVCLKData *)SiS300_VCLKData;
+
+   SiS_Pr->SiS_SR15  = SiS300_SR15;
+
+   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
+
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
+   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
+   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
+
+   SiS_Pr->SiS_LVDS848x480Data_1   = SiS300_LVDS848x480Data_1;
+   SiS_Pr->SiS_LVDS848x480Data_2   = SiS300_LVDS848x480Data_2;
+   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
+
+   SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
+   SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
+   SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
+   SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
+
+   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
+   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
+   SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
+   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
+   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS300_CHTVVCLKOPAL;
+   SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static void
+InitTo310Pointer(struct SiS_Private *SiS_Pr)
+{
+   InitCommonPointer(SiS_Pr);
+
+   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
+   SiS_Pr->SiS_RefIndex      = SiS310_RefIndex;
+   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
+   if(SiS_Pr->ChipType >= SIS_340) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 + XGI */
+   } else if(SiS_Pr->ChipType >= SIS_761) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761;  /* 761 - preliminary */
+   } else if(SiS_Pr->ChipType >= SIS_760) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
+   } else if(SiS_Pr->ChipType >= SIS_661) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
+   } else if(SiS_Pr->ChipType == SIS_330) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
+   } else if(SiS_Pr->ChipType > SIS_315PRO) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
+   } else {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
+   }
+   if(SiS_Pr->ChipType >= SIS_340) {
+      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
+   } else {
+      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
+   }
+   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
+   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
+
+   SiS_Pr->SiS_SR15  = SiS310_SR15;
+
+   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
+
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
+   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
+   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
+   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
+   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
+
+   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS310_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS310_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
+
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
+
+   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
+   SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
+   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS310_CHTVVCLKUPAL;
+   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS310_CHTVVCLKOPAL;
+   SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
+   SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
+   SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
+   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
+   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
+}
+#endif
+
+bool
+SiSInitPtr(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+      InitTo300Pointer(SiS_Pr);
+#else
+      return false;
+#endif
+   } else {
+#ifdef CONFIG_FB_SIS_315
+      InitTo310Pointer(SiS_Pr);
+#else
+      return false;
+#endif
+   }
+   return true;
+}
+
+/*********************************************/
+/*            HELPER: Get ModeID             */
+/*********************************************/
+
+static
+unsigned short
+SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+		int Depth, bool FSTN, int LCDwidth, int LCDheight)
+{
+   unsigned short ModeIndex = 0;
+
+   switch(HDisplay)
+   {
+	case 320:
+		if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+		else if(VDisplay == 240) {
+			if((VBFlags & CRT2_LCD) && (FSTN))
+				ModeIndex = ModeIndex_320x240_FSTN[Depth];
+			else
+				ModeIndex = ModeIndex_320x240[Depth];
+		}
+		break;
+	case 400:
+		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
+			if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+		}
+		break;
+	case 512:
+		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
+			if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+		}
+		break;
+	case 640:
+		if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
+		else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
+		break;
+	case 720:
+		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+		break;
+	case 768:
+		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+		break;
+	case 800:
+		if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
+		else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+		break;
+	case 848:
+		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+		break;
+	case 856:
+		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+		break;
+	case 960:
+		if(VGAEngine == SIS_315_VGA) {
+			if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
+			else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
+		}
+		break;
+	case 1024:
+		if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];
+		else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+		else if(VGAEngine == SIS_300_VGA) {
+			if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
+		}
+		break;
+	case 1152:
+		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+		if(VGAEngine == SIS_300_VGA) {
+			if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
+		}
+		break;
+	case 1280:
+		switch(VDisplay) {
+			case 720:
+				ModeIndex = ModeIndex_1280x720[Depth];
+				break;
+			case 768:
+				if(VGAEngine == SIS_300_VGA) {
+					ModeIndex = ModeIndex_300_1280x768[Depth];
+				} else {
+					ModeIndex = ModeIndex_310_1280x768[Depth];
+				}
+				break;
+			case 800:
+				if(VGAEngine == SIS_315_VGA) {
+					ModeIndex = ModeIndex_1280x800[Depth];
+				}
+				break;
+			case 854:
+				if(VGAEngine == SIS_315_VGA) {
+					ModeIndex = ModeIndex_1280x854[Depth];
+				}
+				break;
+			case 960:
+				ModeIndex = ModeIndex_1280x960[Depth];
+				break;
+			case 1024:
+				ModeIndex = ModeIndex_1280x1024[Depth];
+				break;
+		}
+		break;
+	case 1360:
+		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+		if(VGAEngine == SIS_300_VGA) {
+			if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
+		}
+		break;
+	case 1400:
+		if(VGAEngine == SIS_315_VGA) {
+			if(VDisplay == 1050) {
+				ModeIndex = ModeIndex_1400x1050[Depth];
+			}
+		}
+		break;
+	case 1600:
+		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+		break;
+	case 1680:
+		if(VGAEngine == SIS_315_VGA) {
+			if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		}
+		break;
+	case 1920:
+		if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+		else if(VGAEngine == SIS_315_VGA) {
+			if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
+		}
+		break;
+	case 2048:
+		if(VDisplay == 1536) {
+			if(VGAEngine == SIS_300_VGA) {
+				ModeIndex = ModeIndex_300_2048x1536[Depth];
+			} else {
+				ModeIndex = ModeIndex_310_2048x1536[Depth];
+			}
+		}
+		break;
+   }
+
+   return ModeIndex;
+}
+
+unsigned short
+SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+		int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
+		unsigned int VBFlags2)
+{
+   unsigned short ModeIndex = 0;
+
+   if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
+
+      switch(HDisplay)
+      {
+	case 320:
+	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+		if(VDisplay == 200) {
+		   if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
+		} else if(VDisplay == 240) {
+		   if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
+		   else if(VGAEngine == SIS_315_VGA) {
+		      ModeIndex = ModeIndex_320x240_FSTN[Depth];
+		   }
+		}
+	     }
+	     break;
+	case 400:
+	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
+		   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+		}
+	     }
+	     break;
+	case 512:
+	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
+		   if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
+		      if(VDisplay == 384) {
+		         ModeIndex = ModeIndex_512x384[Depth];
+		      }
+		   }
+		}
+	     }
+	     break;
+	case 640:
+	     if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
+	     else if(VDisplay == 400) {
+		if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
+		   ModeIndex = ModeIndex_640x400[Depth];
+	     }
+	     break;
+	case 800:
+	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+	     break;
+	case 848:
+	     if(CustomT == CUT_PANEL848) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+	     }
+	     break;
+	case 856:
+	     if(CustomT == CUT_PANEL856) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+	     }
+	     break;
+	case 1024:
+	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+	     else if(VGAEngine == SIS_300_VGA) {
+		if((VDisplay == 600) && (LCDheight == 600)) {
+		   ModeIndex = ModeIndex_1024x600[Depth];
+		}
+	     }
+	     break;
+	case 1152:
+	     if(VGAEngine == SIS_300_VGA) {
+		if((VDisplay == 768) && (LCDheight == 768)) {
+		   ModeIndex = ModeIndex_1152x768[Depth];
+		}
+	     }
+	     break;
+        case 1280:
+	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
+	     else if(VGAEngine == SIS_315_VGA) {
+		if((VDisplay == 768) && (LCDheight == 768)) {
+		   ModeIndex = ModeIndex_310_1280x768[Depth];
+		}
+	     }
+	     break;
+	case 1360:
+	     if(VGAEngine == SIS_300_VGA) {
+		if(CustomT == CUT_BARCO1366) {
+		   if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
+		}
+	     }
+	     if(CustomT == CUT_PANEL848) {
+		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+	     }
+	     break;
+	case 1400:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+	     }
+	     break;
+	case 1600:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+	     }
+	     break;
+      }
+
+   } else if(VBFlags2 & VB2_SISBRIDGE) {
+
+      switch(HDisplay)
+      {
+	case 320:
+	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
+	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
+	     break;
+	case 400:
+	     if(LCDwidth >= 800 && LCDheight >= 600) {
+		if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+	     }
+	     break;
+	case 512:
+	     if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
+		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+	     }
+	     break;
+	case 640:
+	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
+	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
+	     break;
+	case 720:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+	     }
+	     break;
+	case 768:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+	     }
+	     break;
+	case 800:
+	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+	     }
+	     break;
+	case 848:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+	     }
+	     break;
+	case 856:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+	     }
+	     break;
+	case 960:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
+		else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
+	     }
+	     break;
+	case 1024:
+	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+	     }
+	     break;
+	case 1152:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+	     }
+	     break;
+	case 1280:
+	     switch(VDisplay) {
+	     case 720:
+		ModeIndex = ModeIndex_1280x720[Depth];
+		break;
+	     case 768:
+		if(VGAEngine == SIS_300_VGA) {
+		   ModeIndex = ModeIndex_300_1280x768[Depth];
+		} else {
+		   ModeIndex = ModeIndex_310_1280x768[Depth];
+		}
+		break;
+	     case 800:
+		if(VGAEngine == SIS_315_VGA) {
+		   ModeIndex = ModeIndex_1280x800[Depth];
+		}
+		break;
+	     case 854:
+		if(VGAEngine == SIS_315_VGA) {
+		   ModeIndex = ModeIndex_1280x854[Depth];
+		}
+		break;
+	     case 960:
+		ModeIndex = ModeIndex_1280x960[Depth];
+		break;
+	     case 1024:
+		ModeIndex = ModeIndex_1280x1024[Depth];
+		break;
+	     }
+	     break;
+	case 1360:
+	     if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */
+		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+	     }
+	     break;
+	case 1400:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+		   if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+		}
+	     }
+	     break;
+	case 1600:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+		   if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+		}
+	     }
+	     break;
+#ifndef VB_FORBID_CRT2LCD_OVER_1600
+	case 1680:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+		   if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		}
+	     }
+	     break;
+	case 1920:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+		   if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+		}
+	     }
+	     break;
+	case 2048:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+		   if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
+		}
+	     }
+	     break;
+#endif
+      }
+   }
+
+   return ModeIndex;
+}
+
+unsigned short
+SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+			unsigned int VBFlags2)
+{
+   unsigned short ModeIndex = 0;
+
+   if(VBFlags2 & VB2_CHRONTEL) {
+
+      switch(HDisplay)
+      {
+	case 512:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+	     }
+	     break;
+	case 640:
+	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
+	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
+	     break;
+	case 800:
+	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+	     break;
+	case 1024:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+	     }
+	     break;
+      }
+
+   } else if(VBFlags2 & VB2_SISTVBRIDGE) {
+
+      switch(HDisplay)
+      {
+	case 320:
+	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
+	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
+	     break;
+	case 400:
+	     if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+	     break;
+	case 512:
+	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
+		 (VBFlags & TV_HIVISION) 					      ||
+		 ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
+		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+	     }
+	     break;
+	case 640:
+	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
+	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
+	     break;
+	case 720:
+	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
+		if(VDisplay == 480) {
+		   ModeIndex = ModeIndex_720x480[Depth];
+		} else if(VDisplay == 576) {
+		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
+		      ModeIndex = ModeIndex_720x576[Depth];
+		}
+	     }
+             break;
+	case 768:
+	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
+		if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
+		   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+		}
+             }
+	     break;
+	case 800:
+	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+	     else if(VDisplay == 480) {
+		if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
+		   ModeIndex = ModeIndex_800x480[Depth];
+		}
+	     }
+	     break;
+	case 960:
+	     if(VGAEngine == SIS_315_VGA) {
+		if(VDisplay == 600) {
+		   if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+		      ModeIndex = ModeIndex_960x600[Depth];
+		   }
+		}
+	     }
+	     break;
+	case 1024:
+	     if(VDisplay == 768) {
+		if(VBFlags2 & VB2_30xBLV) {
+		   ModeIndex = ModeIndex_1024x768[Depth];
+		}
+	     } else if(VDisplay == 576) {
+		if( (VBFlags & TV_HIVISION) ||
+		    ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
+		    ((VBFlags2 & VB2_30xBLV) &&
+		     ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
+		   ModeIndex = ModeIndex_1024x576[Depth];
+		}
+	     }
+	     break;
+	case 1280:
+	     if(VDisplay == 720) {
+		if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
+		   ModeIndex = ModeIndex_1280x720[Depth];
+		}
+	     } else if(VDisplay == 1024) {
+		if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+		   ModeIndex = ModeIndex_1280x1024[Depth];
+		}
+	     }
+	     break;
+      }
+   }
+   return ModeIndex;
+}
+
+unsigned short
+SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+			unsigned int VBFlags2)
+{
+   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
+
+   if(HDisplay >= 1920) return 0;
+
+   switch(HDisplay)
+   {
+	case 1600:
+		if(VDisplay == 1200) {
+			if(VGAEngine != SIS_315_VGA) return 0;
+			if(!(VBFlags2 & VB2_30xB)) return 0;
+		}
+		break;
+	case 1680:
+		if(VDisplay == 1050) {
+			if(VGAEngine != SIS_315_VGA) return 0;
+			if(!(VBFlags2 & VB2_30xB)) return 0;
+		}
+		break;
+   }
+
+   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
+}
+
+
+/*********************************************/
+/*          HELPER: SetReg, GetReg           */
+/*********************************************/
+
+void
+SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
+{
+	outb(index, port);
+	outb(data, port + 1);
+}
+
+void
+SiS_SetRegByte(SISIOADDRESS port, u8 data)
+{
+	outb(data, port);
+}
+
+void
+SiS_SetRegShort(SISIOADDRESS port, u16 data)
+{
+	outw(data, port);
+}
+
+void
+SiS_SetRegLong(SISIOADDRESS port, u32 data)
+{
+	outl(data, port);
+}
+
+u8
+SiS_GetReg(SISIOADDRESS port, u8 index)
+{
+	outb(index, port);
+	return inb(port + 1);
+}
+
+u8
+SiS_GetRegByte(SISIOADDRESS port)
+{
+	return inb(port);
+}
+
+u16
+SiS_GetRegShort(SISIOADDRESS port)
+{
+	return inw(port);
+}
+
+u32
+SiS_GetRegLong(SISIOADDRESS port)
+{
+	return inl(port);
+}
+
+void
+SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
+{
+   u8 temp;
+
+   temp = SiS_GetReg(Port, Index);
+   temp = (temp & (DataAND)) | DataOR;
+   SiS_SetReg(Port, Index, temp);
+}
+
+void
+SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
+{
+   u8 temp;
+
+   temp = SiS_GetReg(Port, Index);
+   temp &= DataAND;
+   SiS_SetReg(Port, Index, temp);
+}
+
+void
+SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
+{
+   u8 temp;
+
+   temp = SiS_GetReg(Port, Index);
+   temp |= DataOR;
+   SiS_SetReg(Port, Index, temp);
+}
+
+/*********************************************/
+/*      HELPER: DisplayOn, DisplayOff        */
+/*********************************************/
+
+void
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
+{
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
+}
+
+void
+SiS_DisplayOff(struct SiS_Private *SiS_Pr)
+{
+   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
+}
+
+
+/*********************************************/
+/*        HELPER: Init Port Addresses        */
+/*********************************************/
+
+void
+SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
+{
+   SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
+   SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
+   SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
+   SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
+   SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
+   SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
+   SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
+   SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
+   SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
+   SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
+   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
+   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
+   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
+   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
+   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
+   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
+   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;
+   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;
+   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;
+}
+
+/*********************************************/
+/*             HELPER: GetSysFlags           */
+/*********************************************/
+
+static void
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
+{
+   unsigned char cr5f, temp1, temp2;
+
+   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
+   /* (SR11 is used for DDC and in enable/disablebridge) */
+   SiS_Pr->SiS_SensibleSR11 = false;
+   SiS_Pr->SiS_MyCR63 = 0x63;
+   if(SiS_Pr->ChipType >= SIS_330) {
+      SiS_Pr->SiS_MyCR63 = 0x53;
+      if(SiS_Pr->ChipType >= SIS_661) {
+         SiS_Pr->SiS_SensibleSR11 = true;
+      }
+   }
+
+   /* You should use the macros, not these flags directly */
+
+   SiS_Pr->SiS_SysFlags = 0;
+   if(SiS_Pr->ChipType == SIS_650) {
+      cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
+      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
+      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
+      temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
+      if((!temp1) || (temp2)) {
+	 switch(cr5f) {
+	    case 0x80:
+	    case 0x90:
+	    case 0xc0:
+	       SiS_Pr->SiS_SysFlags |= SF_IsM650;
+	       break;
+	    case 0xa0:
+	    case 0xb0:
+	    case 0xe0:
+	       SiS_Pr->SiS_SysFlags |= SF_Is651;
+	       break;
+	 }
+      } else {
+	 switch(cr5f) {
+	    case 0x90:
+	       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
+	       switch(temp1) {
+		  case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
+		  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
+		  default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
+	       }
+	       break;
+	    case 0xb0:
+	       SiS_Pr->SiS_SysFlags |= SF_Is652;
+	       break;
+	    default:
+	       SiS_Pr->SiS_SysFlags |= SF_IsM650;
+	       break;
+	 }
+      }
+   }
+
+   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
+         SiS_Pr->SiS_SysFlags |= SF_760LFB;
+      }
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
+         SiS_Pr->SiS_SysFlags |= SF_760UMA;
+      }
+   }
+}
+
+/*********************************************/
+/*         HELPER: Init PCI & Engines        */
+/*********************************************/
+
+static void
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
+{
+   switch(SiS_Pr->ChipType) {
+#ifdef CONFIG_FB_SIS_300
+   case SIS_300:
+   case SIS_540:
+   case SIS_630:
+   case SIS_730:
+      /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
+       *     - RELOCATED VGA IO ENABLED (0x20)
+       *     - MMIO ENABLED (0x01)
+       * Leave other bits untouched.
+       */
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
+      /*  - Enable 2D (0x40)
+       *  - Enable 3D (0x02)
+       *  - Enable 3D Vertex command fetch (0x10) ?
+       *  - Enable 3D command parser (0x08) ?
+       */
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
+      break;
+#endif
+#ifdef CONFIG_FB_SIS_315
+   case SIS_315H:
+   case SIS_315:
+   case SIS_315PRO:
+   case SIS_650:
+   case SIS_740:
+   case SIS_330:
+   case SIS_661:
+   case SIS_741:
+   case SIS_660:
+   case SIS_760:
+   case SIS_761:
+   case SIS_340:
+   case XGI_40:
+      /* See above */
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
+      /*  - Enable 3D G/L transformation engine (0x80)
+       *  - Enable 2D (0x40)
+       *  - Enable 3D vertex command fetch (0x10)
+       *  - Enable 3D command parser (0x08)
+       *  - Enable 3D (0x02)
+       */
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
+      break;
+   case XGI_20:
+   case SIS_550:
+      /* See above */
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
+      /* No 3D engine ! */
+      /*  - Enable 2D (0x40)
+       *  - disable 3D
+       */
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
+      break;
+#endif
+   default:
+      break;
+   }
+}
+
+/*********************************************/
+/*             HELPER: SetLVDSetc            */
+/*********************************************/
+
+static
+void
+SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
+{
+   unsigned short temp;
+
+   SiS_Pr->SiS_IF_DEF_LVDS = 0;
+   SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
+   SiS_Pr->SiS_IF_DEF_CH70xx = 0;
+   SiS_Pr->SiS_IF_DEF_CONEX = 0;
+
+   SiS_Pr->SiS_ChrontelInit = 0;
+
+   if(SiS_Pr->ChipType == XGI_20) return;
+
+   /* Check for SiS30x first */
+   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+   if((temp == 1) || (temp == 2)) return;
+
+   switch(SiS_Pr->ChipType) {
+#ifdef CONFIG_FB_SIS_300
+   case SIS_540:
+   case SIS_630:
+   case SIS_730:
+	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+	if((temp >= 2) && (temp <= 5))	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+	if(temp == 3)			SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
+	if((temp == 4) || (temp == 5)) {
+		/* Save power status (and error check) - UNUSED */
+		SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
+		SiS_Pr->SiS_IF_DEF_CH70xx = 1;
+	}
+	break;
+#endif
+#ifdef CONFIG_FB_SIS_315
+   case SIS_550:
+   case SIS_650:
+   case SIS_740:
+   case SIS_330:
+	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+	if((temp >= 2) && (temp <= 3))	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+	break;
+   case SIS_661:
+   case SIS_741:
+   case SIS_660:
+   case SIS_760:
+   case SIS_761:
+   case SIS_340:
+   case XGI_20:
+   case XGI_40:
+	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
+	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+	if(temp == 4)			SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
+	break;
+#endif
+   default:
+	break;
+   }
+}
+
+/*********************************************/
+/*          HELPER: Enable DSTN/FSTN         */
+/*********************************************/
+
+void
+SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
+{
+   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
+}
+
+void
+SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
+{
+   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
+}
+
+/*********************************************/
+/*            HELPER: Get modeflag           */
+/*********************************************/
+
+unsigned short
+SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex)
+{
+   if(SiS_Pr->UseCustomMode) {
+      return SiS_Pr->CModeFlag;
+   } else if(ModeNo <= 0x13) {
+      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else {
+      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+}
+
+/*********************************************/
+/*        HELPER: Determine ROM usage        */
+/*********************************************/
+
+bool
+SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+   unsigned short romversoffs, romvmaj = 1, romvmin = 0;
+
+   if(SiS_Pr->ChipType >= XGI_20) {
+      /* XGI ROMs don't qualify */
+      return false;
+   } else if(SiS_Pr->ChipType >= SIS_761) {
+      /* I very much assume 761, 340 and newer will use new layout */
+      return true;
+   } else if(SiS_Pr->ChipType >= SIS_661) {
+      if((ROMAddr[0x1a] == 'N') &&
+	 (ROMAddr[0x1b] == 'e') &&
+	 (ROMAddr[0x1c] == 'w') &&
+	 (ROMAddr[0x1d] == 'V')) {
+	 return true;
+      }
+      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
+      if(romversoffs) {
+	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
+	    romvmaj = ROMAddr[romversoffs] - '0';
+	    romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
+	 }
+      }
+      if((romvmaj != 0) || (romvmin >= 92)) {
+	 return true;
+      }
+   } else if(IS_SIS650740) {
+      if((ROMAddr[0x1a] == 'N') &&
+	 (ROMAddr[0x1b] == 'e') &&
+	 (ROMAddr[0x1c] == 'w') &&
+	 (ROMAddr[0x1d] == 'V')) {
+	 return true;
+      }
+   }
+   return false;
+}
+
+static void
+SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+   unsigned short romptr = 0;
+
+   SiS_Pr->SiS_UseROM = false;
+   SiS_Pr->SiS_ROMNew = false;
+   SiS_Pr->SiS_PWDOffset = 0;
+
+   if(SiS_Pr->ChipType >= XGI_20) return;
+
+   if((ROMAddr) && (SiS_Pr->UseROM)) {
+      if(SiS_Pr->ChipType == SIS_300) {
+	 /* 300: We check if the code starts below 0x220 by
+	  * checking the jmp instruction at the beginning
+	  * of the BIOS image.
+	  */
+	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
+	    SiS_Pr->SiS_UseROM = true;
+      } else if(SiS_Pr->ChipType < SIS_315H) {
+	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
+	  * the others do as well
+	  */
+	 SiS_Pr->SiS_UseROM = true;
+      } else {
+	 /* 315/330 series stick to the standard(s) */
+	 SiS_Pr->SiS_UseROM = true;
+	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
+	    SiS_Pr->SiS_EMIOffset = 14;
+	    SiS_Pr->SiS_PWDOffset = 17;
+	    SiS_Pr->SiS661LCD2TableSize = 36;
+	    /* Find out about LCD data table entry size */
+	    if((romptr = SISGETROMW(0x0102))) {
+	       if(ROMAddr[romptr + (32 * 16)] == 0xff)
+		  SiS_Pr->SiS661LCD2TableSize = 32;
+	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
+		  SiS_Pr->SiS661LCD2TableSize = 34;
+	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)	   /* 0.94, 2.05.00+ */
+		  SiS_Pr->SiS661LCD2TableSize = 36;
+	       else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */
+		 	(ROMAddr[0x6F] & 0x01) ) {		   /* 2.03.00 - <2.05.00 */
+		  SiS_Pr->SiS661LCD2TableSize = 38;		   /* UMC data layout abandoned at 2.05.00 */
+		  SiS_Pr->SiS_EMIOffset = 16;
+		  SiS_Pr->SiS_PWDOffset = 19;
+	       }
+	    }
+	 }
+      }
+   }
+}
+
+/*********************************************/
+/*        HELPER: SET SEGMENT REGISTERS      */
+/*********************************************/
+
+static void
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+   unsigned short temp;
+
+   value &= 0x00ff;
+   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
+   temp |= (value >> 4);
+   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
+   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;
+   temp |= (value & 0x0f);
+   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+   unsigned short temp;
+
+   value &= 0x00ff;
+   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
+   temp |= (value & 0xf0);
+   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
+   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;
+   temp |= (value << 4);
+   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+   SiS_SetSegRegLower(SiS_Pr, value);
+   SiS_SetSegRegUpper(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
+{
+   SiS_SetSegmentReg(SiS_Pr, 0);
+}
+
+static void
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+   unsigned short temp = value >> 8;
+
+   temp &= 0x07;
+   temp |= (temp << 4);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);
+   SiS_SetSegmentReg(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
+{
+   SiS_SetSegmentRegOver(SiS_Pr, 0);
+}
+
+static void
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
+{
+   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
+      SiS_ResetSegmentReg(SiS_Pr);
+      SiS_ResetSegmentRegOver(SiS_Pr);
+   }
+}
+
+/*********************************************/
+/*             HELPER: GetVBType             */
+/*********************************************/
+
+static
+void
+SiS_GetVBType(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag = 0, rev = 0, nolcd = 0;
+   unsigned short p4_0f, p4_25, p4_27;
+
+   SiS_Pr->SiS_VBType = 0;
+
+   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
+      return;
+
+   if(SiS_Pr->ChipType == XGI_20)
+      return;
+
+   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+
+   if(flag > 3)
+      return;
+
+   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
+
+   if(flag >= 2) {
+      SiS_Pr->SiS_VBType = VB_SIS302B;
+   } else if(flag == 1) {
+      if(rev >= 0xC0) {
+	 SiS_Pr->SiS_VBType = VB_SIS301C;
+      } else if(rev >= 0xB0) {
+	 SiS_Pr->SiS_VBType = VB_SIS301B;
+	 /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
+	 nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
+	 if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
+      } else {
+	 SiS_Pr->SiS_VBType = VB_SIS301;
+      }
+   }
+   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
+      if(rev >= 0xE0) {
+	 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
+	 if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
+	 else 	 	  SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
+      } else if(rev >= 0xD0) {
+	 SiS_Pr->SiS_VBType = VB_SIS301LV;
+      }
+   }
+   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
+      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
+      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
+      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
+      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
+         SiS_Pr->SiS_VBType |= VB_UMC;
+      }
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
+   }
+}
+
+/*********************************************/
+/*           HELPER: Check RAM size          */
+/*********************************************/
+
+static bool
+SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex)
+{
+   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
+   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
+
+   if(!AdapterMemSize) return true;
+
+   if(AdapterMemSize < memorysize) return false;
+   return true;
+}
+
+/*********************************************/
+/*           HELPER: Get DRAM type           */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_315
+static unsigned char
+SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
+{
+   unsigned char data;
+
+   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
+      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
+   } else {
+      if(SiS_Pr->ChipType >= XGI_20) {
+         /* Do I need this? SR17 seems to be zero anyway... */
+	 data = 0;
+      } else if(SiS_Pr->ChipType >= SIS_340) {
+	 /* TODO */
+	 data = 0;
+      } if(SiS_Pr->ChipType >= SIS_661) {
+	 if(SiS_Pr->SiS_ROMNew) {
+	    data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+	 } else {
+	    data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
+	 }
+      } else if(IS_SIS550650740) {
+	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
+      } else {	/* 315, 330 */
+	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
+	 if(SiS_Pr->ChipType == SIS_330) {
+	    if(data > 1) {
+	       switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
+	       case 0x00: data = 1; break;
+	       case 0x10: data = 3; break;
+	       case 0x20: data = 3; break;
+	       case 0x30: data = 2; break;
+	       }
+	    } else {
+	       data = 0;
+	    }
+	 }
+      }
+   }
+
+   return data;
+}
+
+static unsigned short
+SiS_GetMCLK(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short index;
+
+   index = SiS_Get310DRAMType(SiS_Pr);
+   if(SiS_Pr->ChipType >= SIS_661) {
+      if(SiS_Pr->SiS_ROMNew) {
+	 return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
+      }
+      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+   } else if(index >= 4) {
+      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
+   } else {
+      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+   }
+}
+#endif
+
+/*********************************************/
+/*           HELPER: ClearBuffer             */
+/*********************************************/
+
+static void
+SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
+   unsigned int   memsize = SiS_Pr->VideoMemorySize;
+   unsigned short SISIOMEMTYPE *pBuffer;
+   int i;
+
+   if(!memaddr || !memsize) return;
+
+   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
+      if(ModeNo > 0x13) {
+	 memset_io(memaddr, 0, memsize);
+      } else {
+	 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+	 for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
+      }
+   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
+      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
+   } else {
+      memset_io(memaddr, 0, 0x8000);
+   }
+}
+
+/*********************************************/
+/*           HELPER: SearchModeID            */
+/*********************************************/
+
+bool
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+		unsigned short *ModeIdIndex)
+{
+   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
+
+   if((*ModeNo) <= 0x13) {
+
+      if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
+
+      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
+	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
+      }
+
+      if((*ModeNo) == 0x07) {
+	  if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
+	  /* else 350 lines */
+      }
+      if((*ModeNo) <= 0x03) {
+	 if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
+	 if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
+	 /* else 350 lines  */
+      }
+      /* else 200 lines  */
+
+   } else {
+
+      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
+	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
+      }
+
+   }
+   return true;
+}
+
+/*********************************************/
+/*            HELPER: GetModePtr             */
+/*********************************************/
+
+unsigned short
+SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short index;
+
+   if(ModeNo <= 0x13) {
+      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
+   } else {
+      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
+      else index = 0x0F;
+   }
+   return index;
+}
+
+/*********************************************/
+/*         HELPERS: Get some indices         */
+/*********************************************/
+
+unsigned short
+SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+      if(UseWide == 1) {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
+      } else {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
+      }
+   } else {
+      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
+   }
+}
+
+unsigned short
+SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+      if(UseWide == 1) {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
+      } else {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
+      }
+   } else {
+      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
+   }
+}
+
+/*********************************************/
+/*           HELPER: LowModeTests            */
+/*********************************************/
+
+static bool
+SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+   unsigned short temp, temp1, temp2;
+
+   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
+      return true;
+   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
+   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
+   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
+   if((SiS_Pr->ChipType >= SIS_315H) ||
+      (SiS_Pr->ChipType == SIS_300)) {
+      if(temp2 == 0x55) return false;
+      else return true;
+   } else {
+      if(temp2 != 0x55) return true;
+      else {
+	 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
+	 return false;
+      }
+   }
+}
+
+static void
+SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
+      SiS_Pr->SiS_SetFlag |= LowModeTests;
+   }
+}
+
+/*********************************************/
+/*        HELPER: OPEN/CLOSE CRT1 CRTC       */
+/*********************************************/
+
+static void
+SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
+{
+   if(IS_SIS650) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+   } else if(IS_SIS661741660760) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+      if(!SiS_Pr->SiS_ROMNew) {
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
+      }
+   }
+}
+
+static void
+SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
+{
+#if 0 /* This locks some CRTC registers. We don't want that. */
+   unsigned short temp1 = 0, temp2 = 0;
+
+   if(IS_SIS661741660760) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+         temp1 = 0xa0; temp2 = 0x08;
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
+   }
+#endif
+}
+
+static void
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
+{
+   /* Enable CRT1 gating */
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
+#if 0
+   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
+      }
+   }
+#endif
+}
+
+/*********************************************/
+/*           HELPER: GetColorDepth           */
+/*********************************************/
+
+unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex)
+{
+   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
+   unsigned short modeflag;
+   short index;
+
+   /* Do NOT check UseCustomMode, will skrew up FIFO */
+   if(ModeNo == 0xfe) {
+      modeflag = SiS_Pr->CModeFlag;
+   } else if(ModeNo <= 0x13) {
+      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else {
+      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+
+   index = (modeflag & ModeTypeMask) - ModeEGA;
+   if(index < 0) index = 0;
+   return ColorDepth[index];
+}
+
+/*********************************************/
+/*             HELPER: GetOffset             */
+/*********************************************/
+
+unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   unsigned short xres, temp, colordepth, infoflag;
+
+   if(SiS_Pr->UseCustomMode) {
+      infoflag = SiS_Pr->CInfoFlag;
+      xres = SiS_Pr->CHDisplay;
+   } else {
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
+   }
+
+   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+   temp = xres / 16;
+   if(infoflag & InterlaceMode) temp <<= 1;
+   temp *= colordepth;
+   if(xres % 16) temp += (colordepth >> 1);
+
+   return temp;
+}
+
+/*********************************************/
+/*                   SEQ                     */
+/*********************************************/
+
+static void
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+   unsigned char SRdata;
+   int i;
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
+
+   /* or "display off"  */
+   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
+
+   /* determine whether to force x8 dotclock */
+   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
+
+      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
+
+   }
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
+
+   for(i = 2; i <= 4; i++) {
+      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
+      SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
+   }
+}
+
+/*********************************************/
+/*                  MISC                     */
+/*********************************************/
+
+static void
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+   unsigned char Miscdata;
+
+   Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
+
+   if(SiS_Pr->ChipType < SIS_661) {
+      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	   Miscdata |= 0x0C;
+	 }
+      }
+   }
+
+   SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);
+}
+
+/*********************************************/
+/*                  CRTC                     */
+/*********************************************/
+
+static void
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+   unsigned char  CRTCdata;
+   unsigned short i;
+
+   /* Unlock CRTC */
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i = 0; i <= 0x18; i++) {
+      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+   }
+
+   if(SiS_Pr->ChipType >= SIS_661) {
+      SiS_OpenCRTC(SiS_Pr);
+      for(i = 0x13; i <= 0x14; i++) {
+	 CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+	 SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+      }
+   } else if( ( (SiS_Pr->ChipType == SIS_630) ||
+	        (SiS_Pr->ChipType == SIS_730) )  &&
+	      (SiS_Pr->ChipRevision >= 0x30) ) {
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
+	 }
+      }
+   }
+}
+
+/*********************************************/
+/*                   ATT                     */
+/*********************************************/
+
+static void
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+   unsigned char  ARdata;
+   unsigned short i;
+
+   for(i = 0; i <= 0x13; i++) {
+      ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
+
+      if(i == 0x13) {
+	 /* Pixel shift. If screen on LCD or TV is shifted left or right,
+	  * this might be the cause.
+	  */
+	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
+	 }
+	 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	    if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+		  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+	       }
+	    }
+	 }
+	 if(SiS_Pr->ChipType >= SIS_661) {
+	    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
+	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+	    }
+	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	    if(SiS_Pr->ChipType >= SIS_315H) {
+	       if(IS_SIS550650740660) {
+		  /* 315, 330 don't do this */
+		  if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
+		     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+		  } else {
+		     ARdata = 0;
+		  }
+	       }
+	    } else {
+	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+	    }
+	 }
+      }
+      SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */
+      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);	/* set index  */
+      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata);	/* set data   */
+   }
+
+   SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */
+   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);	/* set index  */
+   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);	/* set data   */
+
+   SiS_GetRegByte(SiS_Pr->SiS_P3da);
+   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);	/* Enable Attribute  */
+   SiS_GetRegByte(SiS_Pr->SiS_P3da);
+}
+
+/*********************************************/
+/*                   GRC                     */
+/*********************************************/
+
+static void
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+   unsigned char  GRdata;
+   unsigned short i;
+
+   for(i = 0; i <= 0x08; i++) {
+      GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
+      SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);
+   }
+
+   if(SiS_Pr->SiS_ModeType > ModeVGA) {
+      /* 256 color disable */
+      SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);
+   }
+}
+
+/*********************************************/
+/*          CLEAR EXTENDED REGISTERS         */
+/*********************************************/
+
+static void
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+   unsigned short i;
+
+   for(i = 0x0A; i <= 0x0E; i++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
+   }
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
+      if(ModeNo <= 0x13) {
+	 if(ModeNo == 0x06 || ModeNo >= 0x0e) {
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
+	 }
+      }
+   }
+}
+
+/*********************************************/
+/*                 RESET VCLK                */
+/*********************************************/
+
+static void
+SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(SiS_Pr->ChipType < SIS_661) {
+	 if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
+      }
+   } else {
+      if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
+	 (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
+	 return;
+      }
+   }
+
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
+}
+
+/*********************************************/
+/*                  SYNC                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
+{
+   unsigned short sync;
+
+   if(SiS_Pr->UseCustomMode) {
+      sync = SiS_Pr->CInfoFlag >> 8;
+   } else {
+      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
+   }
+
+   sync &= 0xC0;
+   sync |= 0x2f;
+   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
+}
+
+/*********************************************/
+/*                  CRTC/2                   */
+/*********************************************/
+
+static void
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   unsigned short temp, i, j, modeflag;
+   unsigned char  *crt1data = NULL;
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->UseCustomMode) {
+
+      crt1data = &SiS_Pr->CCRT1CRTC[0];
+
+   } else {
+
+      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
+
+      /* Alternate for 1600x1200 LCDA */
+      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
+
+      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
+
+   }
+
+   /* unlock cr0-7 */
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i = 0, j = 0; i <= 7; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+   }
+   for(j = 0x10; i <= 10; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+   }
+   for(j = 0x15; i <= 12; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+   }
+   for(j = 0x0A; i <= 15; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
+   }
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
+
+   temp = (crt1data[16] & 0x01) << 5;
+   if(modeflag & DoubleScanMode) temp |= 0x80;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
+
+   if(SiS_Pr->SiS_ModeType > ModeVGA) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
+   }
+
+#ifdef CONFIG_FB_SIS_315
+   if(SiS_Pr->ChipType == XGI_20) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
+      if(!(temp = crt1data[5] & 0x1f)) {
+         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
+      temp = (crt1data[16] >> 5) + 3;
+      if(temp > 7) temp -= 7;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
+   }
+#endif
+}
+
+/*********************************************/
+/*               OFFSET & PITCH              */
+/*********************************************/
+/*  (partly overruled by SetPitch() in XF86) */
+/*********************************************/
+
+static void
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   unsigned short temp, DisplayUnit, infoflag;
+
+   if(SiS_Pr->UseCustomMode) {
+      infoflag = SiS_Pr->CInfoFlag;
+   } else {
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+   }
+
+   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+
+   temp = (DisplayUnit >> 8) & 0x0f;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
+
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
+
+   if(infoflag & InterlaceMode) DisplayUnit >>= 1;
+
+   DisplayUnit <<= 5;
+   temp = (DisplayUnit >> 8) + 1;
+   if(DisplayUnit & 0xff) temp++;
+   if(SiS_Pr->ChipType == XGI_20) {
+      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
+   }
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
+}
+
+/*********************************************/
+/*                  VCLK                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   unsigned short index = 0, clka, clkb;
+
+   if(SiS_Pr->UseCustomMode) {
+      clka = SiS_Pr->CSR2B;
+      clkb = SiS_Pr->CSR2C;
+   } else {
+      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+	 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	 /* Alternate for 1600x1200 LCDA */
+	 if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
+	 clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
+	 clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
+      } else {
+	 clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+	 clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+      }
+   }
+
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef CONFIG_FB_SIS_315
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
+      if(SiS_Pr->ChipType == XGI_20) {
+         unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+	 if(mf & HalfDCLK) {
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
+	    clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
+	    clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+	 }
+      }
+#endif
+   } else {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
+   }
+}
+
+/*********************************************/
+/*                  FIFO                     */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_300
+void
+SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+		unsigned short *idx2)
+{
+   unsigned short temp1, temp2;
+   static const unsigned char ThTiming[8] = {
+		1, 2, 2, 3, 0, 1, 1, 2
+   };
+
+   temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
+   (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
+   (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
+   (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
+   (*idx1) <<= 1;
+}
+
+static unsigned short
+SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
+{
+   static const unsigned char ThLowA[8 * 3] = {
+		61, 3,52, 5,68, 7,100,11,
+		43, 3,42, 5,54, 7, 78,11,
+		34, 3,37, 5,47, 7, 67,11
+   };
+
+   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
+}
+
+unsigned short
+SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
+{
+   static const unsigned char ThLowB[8 * 3] = {
+		81, 4,72, 6,88, 8,120,12,
+		55, 4,54, 6,66, 8, 90,12,
+		42, 4,45, 6,55, 8, 75,12
+   };
+
+   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
+}
+
+static unsigned short
+SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
+		unsigned short colordepth, unsigned short key)
+{
+   unsigned short idx1, idx2;
+   unsigned int   longtemp = VCLK * colordepth;
+
+   SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
+
+   if(key == 0) {
+      longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
+   } else {
+      longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
+   }
+   idx1 = longtemp % (MCLK * 16);
+   longtemp /= (MCLK * 16);
+   if(idx1) longtemp++;
+   return (unsigned short)longtemp;
+}
+
+static unsigned short
+SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
+		unsigned short colordepth, unsigned short MCLK)
+{
+   unsigned short temp1, temp2;
+
+   temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
+   temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
+   if(temp1 < 4) temp1 = 4;
+   temp1 -= 4;
+   if(temp2 < temp1) temp2 = temp1;
+   return temp2;
+}
+
+static void
+SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short RefreshRateTableIndex)
+{
+   unsigned short ThresholdLow = 0;
+   unsigned short temp, index, VCLK, MCLK, colorth;
+   static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
+
+   if(ModeNo > 0x13) {
+
+      /* Get VCLK  */
+      if(SiS_Pr->UseCustomMode) {
+	 VCLK = SiS_Pr->CSRClock;
+      } else {
+	 index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+	 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+      }
+
+      /* Get half colordepth */
+      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
+
+      /* Get MCLK  */
+      index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
+      MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
+
+      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
+
+      do {
+	 ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
+	 if(ThresholdLow < 0x13) break;
+	 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
+	 ThresholdLow = 0x13;
+	 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
+	 if(!temp) break;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
+      } while(0);
+
+   } else ThresholdLow = 2;
+
+   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+   temp = (ThresholdLow << 4) | 0x0f;
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
+
+   temp = (ThresholdLow & 0x10) << 1;
+   if(ModeNo > 0x13) temp |= 0x40;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
+
+   /* What is this? */
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+
+   /* Write CRT/CPU threshold high */
+   temp = ThresholdLow + 3;
+   if(temp > 0x0f) temp = 0x0f;
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
+}
+
+unsigned short
+SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
+{
+   static const unsigned char LatencyFactor[] = {
+		97, 88, 86, 79, 77,  0,       /* 64  bit    BQ=2   */
+		 0, 87, 85, 78, 76, 54,       /* 64  bit    BQ=1   */
+		97, 88, 86, 79, 77,  0,       /* 128 bit    BQ=2   */
+		 0, 79, 77, 70, 68, 48,       /* 128 bit    BQ=1   */
+		80, 72, 69, 63, 61,  0,       /* 64  bit    BQ=2   */
+		 0, 70, 68, 61, 59, 37,       /* 64  bit    BQ=1   */
+		86, 77, 75, 68, 66,  0,       /* 128 bit    BQ=2   */
+		 0, 68, 66, 59, 57, 37        /* 128 bit    BQ=1   */
+   };
+   static const unsigned char LatencyFactor730[] = {
+		 69, 63, 61,
+		 86, 79, 77,
+		103, 96, 94,
+		120,113,111,
+		137,130,128
+   };
+
+   if(SiS_Pr->ChipType == SIS_730) {
+      return (unsigned short)LatencyFactor730[index];
+   } else {
+      return (unsigned short)LatencyFactor[index];
+   }
+}
+
+static unsigned short
+SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
+{
+   unsigned short index;
+
+   if(SiS_Pr->ChipType == SIS_730) {
+      index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
+   } else {
+      index = (key & 0xe0) >> 5;
+      if(key & 0x10)    index +=  6;
+      if(!(key & 0x01)) index += 24;
+      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
+   }
+   return SiS_GetLatencyFactor630(SiS_Pr, index);
+}
+
+static void
+SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                    unsigned short RefreshRateTableIndex)
+{
+   unsigned short  ThresholdLow = 0;
+   unsigned short  i, data, VCLK, MCLK16, colorth = 0;
+   unsigned int    templ, datal;
+   const unsigned char *queuedata = NULL;
+   static const unsigned char FQBQData[21] = {
+		0x01,0x21,0x41,0x61,0x81,
+		0x31,0x51,0x71,0x91,0xb1,
+		0x00,0x20,0x40,0x60,0x80,
+		0x30,0x50,0x70,0x90,0xb0,
+		0xff
+   };
+   static const unsigned char FQBQData730[16] = {
+		0x34,0x74,0xb4,
+		0x23,0x63,0xa3,
+		0x12,0x52,0x92,
+		0x01,0x41,0x81,
+		0x00,0x40,0x80,
+		0xff
+   };
+   static const unsigned short colortharray[6] = {
+		1, 1, 2, 2, 3, 4
+   };
+
+   i = 0;
+
+   if(ModeNo > 0x13) {
+
+      /* Get VCLK  */
+      if(SiS_Pr->UseCustomMode) {
+	 VCLK = SiS_Pr->CSRClock;
+      } else {
+	 data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+	 VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
+      }
+
+      /* Get MCLK * 16 */
+      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
+      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
+
+      /* Get half colordepth */
+      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
+
+      if(SiS_Pr->ChipType == SIS_730) {
+	 queuedata = &FQBQData730[0];
+      } else {
+	 queuedata = &FQBQData[0];
+      }
+
+      do {
+	 templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
+
+	 datal = templ % MCLK16;
+	 templ = (templ / MCLK16) + 1;
+	 if(datal) templ++;
+
+	 if(templ > 0x13) {
+	    if(queuedata[i + 1] == 0xFF) {
+	       ThresholdLow = 0x13;
+	       break;
+	    }
+	    i++;
+	 } else {
+	    ThresholdLow = templ;
+	    break;
+	 }
+      } while(queuedata[i] != 0xFF);
+
+   } else {
+
+      if(SiS_Pr->ChipType != SIS_730) i = 9;
+      ThresholdLow = 0x02;
+
+   }
+
+   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
+
+   data = (ThresholdLow & 0x10) << 1;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
+
+   /* What is this? */
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+
+   /* Write CRT/CPU threshold high (gap = 3) */
+   data = ThresholdLow + 3;
+   if(data > 0x0f) data = 0x0f;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
+
+  /* Write foreground and background queue */
+   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
+
+   if(SiS_Pr->ChipType == SIS_730) {
+
+      templ &= 0xfffff9ff;
+      templ |= ((queuedata[i] & 0xc0) << 3);
+
+   } else {
+
+      templ &= 0xf0ffffff;
+      if( (ModeNo <= 0x13) &&
+          (SiS_Pr->ChipType == SIS_630) &&
+	  (SiS_Pr->ChipRevision >= 0x30) ) {
+	 templ |= 0x0b000000;
+      } else {
+         templ |= ((queuedata[i] & 0xf0) << 20);
+      }
+
+   }
+
+   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
+   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
+
+   /* GUI grant timer (PCI config 0xA3) */
+   if(SiS_Pr->ChipType == SIS_730) {
+
+      templ &= 0x00ffffff;
+      datal = queuedata[i] << 8;
+      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
+
+   } else {
+
+      templ &= 0xf0ffffff;
+      templ |= ((queuedata[i] & 0x0f) << 24);
+
+   }
+
+   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
+}
+#endif /* CONFIG_FB_SIS_300 */
+
+#ifdef CONFIG_FB_SIS_315
+static void
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short modeflag;
+
+   /* disable auto-threshold */
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+   if(ModeNo > 0x13) {
+      if(SiS_Pr->ChipType >= XGI_20) {
+	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+      } else if(SiS_Pr->ChipType >= SIS_661) {
+	 if(!(modeflag & HalfDCLK)) {
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+	 }
+      } else {
+	 if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+	 }
+      }
+   }
+}
+#endif
+
+/*********************************************/
+/*              MODE REGISTERS               */
+/*********************************************/
+
+static void
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
+{
+   unsigned short data = 0, VCLK = 0, index = 0;
+
+   if(ModeNo > 0x13) {
+      if(SiS_Pr->UseCustomMode) {
+         VCLK = SiS_Pr->CSRClock;
+      } else {
+         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+      }
+   }
+
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+      if(VCLK > 150) data |= 0x80;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
+
+      data = 0x00;
+      if(VCLK >= 150) data |= 0x08;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
+#endif
+   } else if(SiS_Pr->ChipType < XGI_20) {
+#ifdef CONFIG_FB_SIS_315
+      if(VCLK >= 166) data |= 0x0c;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+
+      if(VCLK >= 166) {
+         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
+      }
+#endif
+   } else {
+#ifdef CONFIG_FB_SIS_315
+      if(VCLK >= 200) data |= 0x0c;
+      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+      if(SiS_Pr->ChipType != XGI_20) {
+         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
+	 if(VCLK < 200) data |= 0x10;
+	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
+      }
+#endif
+   }
+
+   /* DAC speed */
+   if(SiS_Pr->ChipType >= SIS_661) {
+
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
+
+   } else {
+
+      data = 0x03;
+      if(VCLK >= 260)      data = 0x00;
+      else if(VCLK >= 160) data = 0x01;
+      else if(VCLK >= 135) data = 0x02;
+
+      if(SiS_Pr->ChipType == SIS_540) {
+         /* Was == 203 or < 234 which made no sense */
+         if (VCLK < 234) data = 0x02;
+      }
+
+      if(SiS_Pr->ChipType < SIS_315H) {
+         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
+      } else {
+         if(SiS_Pr->ChipType > SIS_315PRO) {
+            if(ModeNo > 0x13) data &= 0xfc;
+         }
+         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
+      }
+
+   }
+}
+
+static void
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   unsigned short data, infoflag = 0, modeflag, resindex;
+#ifdef CONFIG_FB_SIS_315
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+   unsigned short data2, data3;
+#endif
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->UseCustomMode) {
+      infoflag = SiS_Pr->CInfoFlag;
+   } else {
+      resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+      if(ModeNo > 0x13) {
+	 infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+      }
+   }
+
+   /* Disable DPMS */
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
+
+   data = 0;
+   if(ModeNo > 0x13) {
+      if(SiS_Pr->SiS_ModeType > ModeEGA) {
+         data |= 0x02;
+         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+      }
+      if(infoflag & InterlaceMode) data |= 0x20;
+   }
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
+
+   if(SiS_Pr->ChipType != SIS_300) {
+      data = 0;
+      if(infoflag & InterlaceMode) {
+	 /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+	 int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
+		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
+	 int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
+		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
+	 data = hrs - (hto >> 1) + 3;
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
+   }
+
+   if(modeflag & HalfDCLK) {
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
+   }
+
+   data = 0;
+   if(modeflag & LineCompareOff) data = 0x08;
+   if(SiS_Pr->ChipType == SIS_300) {
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
+   } else {
+      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
+      if(SiS_Pr->SiS_ModeType == ModeEGA) {
+	 if(ModeNo > 0x13) {
+	    data |= 0x40;
+	 }
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
+   }
+
+#ifdef CONFIG_FB_SIS_315
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
+   }
+
+   if(SiS_Pr->ChipType == SIS_315PRO) {
+
+      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
+      if(SiS_Pr->SiS_ModeType == ModeText) {
+	 data &= 0xc7;
+      } else {
+	 data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
+	 if(infoflag & InterlaceMode) data2 >>= 1;
+	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+	 if(data3) data2 /= data3;
+	 if(data2 >= 0x50) {
+	    data &= 0x0f;
+	    data |= 0x50;
+	 }
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
+
+      data = SiS_Get310DRAMType(SiS_Pr);
+      if(SiS_Pr->ChipType == SIS_330) {
+	 data = SiS_Pr->SiS_SR15[(2 * 4) + data];
+      } else {
+	 if(SiS_Pr->SiS_ROMNew)	     data = ROMAddr[0xf6];
+	 else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
+	 else			     data = 0xba;
+      }
+      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
+	 data &= 0xc7;
+      } else {
+	 if(SiS_Pr->UseCustomMode) {
+	    data2 = SiS_Pr->CSRClock;
+	 } else {
+	    data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+	    data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
+	 }
+
+	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+	 if(data3) data2 *= data3;
+
+	 data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
+
+	 if(SiS_Pr->ChipType == SIS_330) {
+	    if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+	       if     (data2 >= 0x19c) data = 0xba;
+	       else if(data2 >= 0x140) data = 0x7a;
+	       else if(data2 >= 0x101) data = 0x3a;
+	       else if(data2 >= 0xf5)  data = 0x32;
+	       else if(data2 >= 0xe2)  data = 0x2a;
+	       else if(data2 >= 0xc4)  data = 0x22;
+	       else if(data2 >= 0xac)  data = 0x1a;
+	       else if(data2 >= 0x9e)  data = 0x12;
+	       else if(data2 >= 0x8e)  data = 0x0a;
+	       else                    data = 0x02;
+	    } else {
+	       if(data2 >= 0x127)      data = 0xba;
+	       else                    data = 0x7a;
+	    }
+	 } else {  /* 76x+LFB */
+	    if     (data2 >= 0x190) data = 0xba;
+	    else if(data2 >= 0xff)  data = 0x7a;
+	    else if(data2 >= 0xd3)  data = 0x3a;
+	    else if(data2 >= 0xa9)  data = 0x1a;
+	    else if(data2 >= 0x93)  data = 0x0a;
+	    else                    data = 0x02;
+	 }
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+   }
+      /* XGI: Nothing. */
+      /* TODO: Check SiS340 */
+#endif
+
+   data = 0x60;
+   if(SiS_Pr->SiS_ModeType != ModeText) {
+      data ^= 0x60;
+      if(SiS_Pr->SiS_ModeType != ModeEGA) {
+         data ^= 0xA0;
+      }
+   }
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
+
+   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
+
+#ifdef CONFIG_FB_SIS_315
+   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
+       (SiS_Pr->ChipType == XGI_40)) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
+      } else {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
+      }
+   } else if(SiS_Pr->ChipType == XGI_20) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
+      } else {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
+   }
+#endif
+}
+
+#ifdef CONFIG_FB_SIS_315
+static void
+SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
+{
+#if 0
+   /* TODO: Find out about IOAddress2 */
+   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
+   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
+   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
+   int i;
+
+   if((SiS_Pr->ChipRevision != 0) ||
+      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
+      return;
+
+   for(i = 0; i <= 4; i++) {					/* SR00 - SR04 */
+      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
+   }
+   for(i = 0; i <= 8; i++) {					/* GR00 - GR08 */
+      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
+   }
+   SiS_SetReg(P2_3c4,0x05,0x86);
+   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));	/* SR06 */
+   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));	/* SR21 */
+   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));	/* MISC */
+   SiS_SetReg(P2_3c4,0x05,0x00);
+#endif
+}
+#endif
+
+/*********************************************/
+/*                 LOAD DAC                  */
+/*********************************************/
+
+static void
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
+             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
+{
+   unsigned short d1, d2, d3;
+
+   switch(dl) {
+   case  0: d1 = dh; d2 = ah; d3 = al; break;
+   case  1: d1 = ah; d2 = al; d3 = dh; break;
+   default: d1 = al; d2 = dh; d3 = ah;
+   }
+   SiS_SetRegByte(DACData, (d1 << shiftflag));
+   SiS_SetRegByte(DACData, (d2 << shiftflag));
+   SiS_SetRegByte(DACData, (d3 << shiftflag));
+}
+
+void
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short data, data2, time, i, j, k, m, n, o;
+   unsigned short si, di, bx, sf;
+   SISIOADDRESS DACAddr, DACData;
+   const unsigned char *table = NULL;
+
+   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
+
+   j = time = 64;
+   if(data == 0x00)      table = SiS_MDA_DAC;
+   else if(data == 0x08) table = SiS_CGA_DAC;
+   else if(data == 0x10) table = SiS_EGA_DAC;
+   else if(data == 0x18) {
+      j = 16;
+      time = 256;
+      table = SiS_VGA_DAC;
+   }
+
+   if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */
+         (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||
+       (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */
+       (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */
+      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
+      DACAddr = SiS_Pr->SiS_P3c8;
+      DACData = SiS_Pr->SiS_P3c9;
+      sf = 0;
+   } else {
+      DACAddr = SiS_Pr->SiS_Part5Port;
+      DACData = SiS_Pr->SiS_Part5Port + 1;
+      sf = 2;
+   }
+
+   SiS_SetRegByte(DACAddr,0x00);
+
+   for(i = 0; i < j; i++) {
+      data = table[i];
+      for(k = 0; k < 3; k++) {
+	data2 = 0;
+	if(data & 0x01) data2 += 0x2A;
+	if(data & 0x02) data2 += 0x15;
+	SiS_SetRegByte(DACData, (data2 << sf));
+	data >>= 2;
+      }
+   }
+
+   if(time == 256) {
+      for(i = 16; i < 32; i++) {
+	 data = table[i] << sf;
+	 for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
+      }
+      si = 32;
+      for(m = 0; m < 9; m++) {
+	 di = si;
+	 bx = si + 4;
+	 for(n = 0; n < 3; n++) {
+	    for(o = 0; o < 5; o++) {
+	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
+	       si++;
+	    }
+	    si -= 2;
+	    for(o = 0; o < 3; o++) {
+	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
+	       si--;
+	    }
+	 }            /* for n < 3 */
+	 si += 5;
+      }               /* for m < 9 */
+   }
+}
+
+/*********************************************/
+/*         SET CRT1 REGISTER GROUP           */
+/*********************************************/
+
+static void
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short StandTableIndex, RefreshRateTableIndex;
+
+   SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
+         SiS_DisableBridge(SiS_Pr);
+      }
+   }
+
+   SiS_ResetSegmentRegisters(SiS_Pr);
+
+   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+   SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+   SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+   SiS_ResetCRT1VCLK(SiS_Pr);
+
+   SiS_Pr->SiS_SelectCRT2Rate = 0;
+   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+
+   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+      }
+   }
+
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+   }
+
+   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
+   }
+
+   if(RefreshRateTableIndex != 0xFFFF) {
+      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
+      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+   }
+
+   switch(SiS_Pr->ChipType) {
+#ifdef CONFIG_FB_SIS_300
+   case SIS_300:
+      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
+      break;
+   case SIS_540:
+   case SIS_630:
+   case SIS_730:
+      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
+      break;
+#endif
+   default:
+#ifdef CONFIG_FB_SIS_315
+      if(SiS_Pr->ChipType == XGI_20) {
+         unsigned char sr2b = 0, sr2c = 0;
+         switch(ModeNo) {
+	 case 0x00:
+	 case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
+	 case 0x04:
+	 case 0x05:
+	 case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
+	 }
+	 if(sr2b) {
+            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
+	 }
+      }
+      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
+#endif
+      break;
+   }
+
+   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+
+#ifdef CONFIG_FB_SIS_315
+   if(SiS_Pr->ChipType == XGI_40) {
+      SiS_SetupDualChip(SiS_Pr);
+   }
+#endif
+
+   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->SiS_flag_clearbuffer) {
+      SiS_ClearBuffer(SiS_Pr, ModeNo);
+   }
+
+   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
+      SiS_WaitRetrace1(SiS_Pr);
+      SiS_DisplayOn(SiS_Pr);
+   }
+}
+
+/*********************************************/
+/*       HELPER: VIDEO BRIDGE PROG CLK       */
+/*********************************************/
+
+static void
+SiS_InitVB(struct SiS_Private *SiS_Pr)
+{
+   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+
+   SiS_Pr->Init_P4_0E = 0;
+   if(SiS_Pr->SiS_ROMNew) {
+      SiS_Pr->Init_P4_0E = ROMAddr[0x82];
+   } else if(SiS_Pr->ChipType >= XGI_40) {
+      if(SiS_Pr->SiS_XGIROM) {
+         SiS_Pr->Init_P4_0E = ROMAddr[0x80];
+      }
+   }
+}
+
+static void
+SiS_ResetVB(struct SiS_Private *SiS_Pr)
+{
+#ifdef CONFIG_FB_SIS_315
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp;
+
+   /* VB programming clock */
+   if(SiS_Pr->SiS_UseROM) {
+      if(SiS_Pr->ChipType < SIS_330) {
+	 temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
+	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
+	 temp = ROMAddr[0x7e] | 0x40;
+	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      }
+   } else if(SiS_Pr->ChipType >= XGI_40) {
+      temp = 0x40;
+      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
+      /* Can we do this on any chipset? */
+      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+   }
+#endif
+}
+
+/*********************************************/
+/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */
+/*********************************************/
+
+static void
+SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
+{
+   /* SiS65x and XGI set up some sort of "lock mode" for text
+    * which locks CRT2 in some way to CRT1 timing. Disable
+    * this here.
+    */
+#ifdef CONFIG_FB_SIS_315
+   if((IS_SIS651) || (IS_SISM650) ||
+      SiS_Pr->ChipType == SIS_340 ||
+      SiS_Pr->ChipType == XGI_40) {
+      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
+      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
+      SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
+      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
+      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
+   }
+   /* !!! This does not support modes < 0x13 !!! */
+#endif
+}
+
+/*********************************************/
+/*     HELPER: SET AGP TIMING FOR SiS760     */
+/*********************************************/
+
+static void
+SiS_Handle760(struct SiS_Private *SiS_Pr)
+{
+#ifdef CONFIG_FB_SIS_315
+   unsigned int somebase;
+   unsigned char temp1, temp2, temp3;
+
+   if( (SiS_Pr->ChipType != SIS_760)                         ||
+       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
+       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||
+       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
+      return;
+
+   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
+   somebase &= 0xffff;
+
+   if(somebase == 0) return;
+
+   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
+
+   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+      temp1 = 0x21;
+      temp2 = 0x03;
+      temp3 |= 0x08;
+   } else {
+      temp1 = 0x25;
+      temp2 = 0x0b;
+   }
+
+   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
+   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
+
+   SiS_SetRegByte((somebase + 0x85), temp3);
+#endif
+}
+
+/*********************************************/
+/*                 SiSSetMode()              */
+/*********************************************/
+
+bool
+SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
+   unsigned short RealModeNo, ModeIdIndex;
+   unsigned char  backupreg = 0;
+   unsigned short KeepLockReg;
+
+   SiS_Pr->UseCustomMode = false;
+   SiS_Pr->CRT1UsesCustomMode = false;
+
+   SiS_Pr->SiS_flag_clearbuffer = 0;
+
+   if(SiS_Pr->UseCustomMode) {
+      ModeNo = 0xfe;
+   } else {
+      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
+      ModeNo &= 0x7f;
+   }
+
+   /* Don't use FSTN mode for CRT1 */
+   RealModeNo = ModeNo;
+   if(ModeNo == 0x5b) ModeNo = 0x56;
+
+   SiSInitPtr(SiS_Pr);
+   SiSRegInit(SiS_Pr, BaseAddr);
+   SiS_GetSysFlags(SiS_Pr);
+
+   SiS_Pr->SiS_VGAINFO = 0x11;
+
+   KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
+
+   SiSInitPCIetc(SiS_Pr);
+   SiSSetLVDSetc(SiS_Pr);
+   SiSDetermineROMUsage(SiS_Pr);
+
+   SiS_UnLockCRT2(SiS_Pr);
+
+   if(!SiS_Pr->UseCustomMode) {
+      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
+   } else {
+      ModeIdIndex = 0;
+   }
+
+   SiS_GetVBType(SiS_Pr);
+
+   /* Init/restore some VB registers */
+   SiS_InitVB(SiS_Pr);
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
+         SiS_ResetVB(SiS_Pr);
+	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
+	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
+         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+      } else {
+         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+      }
+   }
+
+   /* Get VB information (connectors, connected devices) */
+   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
+   SiS_SetYPbPr(SiS_Pr);
+   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_SetLowModeTest(SiS_Pr, ModeNo);
+
+   /* Check memory size (kernel framebuffer driver only) */
+   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
+      return false;
+   }
+
+   SiS_OpenCRTC(SiS_Pr);
+
+   if(SiS_Pr->UseCustomMode) {
+      SiS_Pr->CRT1UsesCustomMode = true;
+      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
+      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
+   } else {
+      SiS_Pr->CRT1UsesCustomMode = false;
+   }
+
+   /* Set mode on CRT1 */
+   if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
+       (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
+      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
+   }
+
+   /* Set mode on CRT2 */
+   if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
+      if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
+	  (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
+	  (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
+	  (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
+	 SiS_SetCRT2Group(SiS_Pr, RealModeNo);
+      }
+   }
+
+   SiS_HandleCRT1(SiS_Pr);
+
+   SiS_StrangeStuff(SiS_Pr);
+
+   SiS_DisplayOn(SiS_Pr);
+   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
+
+#ifdef CONFIG_FB_SIS_315
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	 if(!(SiS_IsDualEdge(SiS_Pr))) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
+	 }
+      }
+   }
+#endif
+
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef CONFIG_FB_SIS_315
+	 if(!SiS_Pr->SiS_ROMNew) {
+	    if(SiS_IsVAMode(SiS_Pr)) {
+	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
+	    } else {
+	       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
+	    }
+	 }
+
+	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
+
+	 if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
+	    if((ModeNo == 0x03) || (ModeNo == 0x10)) {
+	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
+	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
+	    }
+	 }
+
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
+	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
+	 }
+#endif
+      } else if((SiS_Pr->ChipType == SIS_630) ||
+	        (SiS_Pr->ChipType == SIS_730)) {
+	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
+      }
+   }
+
+   SiS_CloseCRTC(SiS_Pr);
+
+   SiS_Handle760(SiS_Pr);
+
+   /* We never lock registers in XF86 */
+   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
+
+   return true;
+}
+
+#ifndef GETBITSTR
+#define GENBITSMASK(mask)   	GENMASK(1?mask,0?mask)
+#define GETBITS(var,mask)   	(((var) & GENBITSMASK(mask)) >> (0?mask))
+#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
+#endif
+
+void
+SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
+{
+   int x = 1; /* Fix sync */
+
+   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;		/* CR0 */
+   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;			/* CR1 */
+   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;			/* CR2 */
+   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;	/* CR3 */
+   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;			/* CR4 */
+   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |	/* CR5 */
+			    (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+
+   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal       - 2) & 0xFF;			/* CR6 */
+   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal     - 2) & 0x100) >> 8)		/* CR7 */
+			  | (((SiS_Pr->CVDisplay   - 1) & 0x100) >> 7)
+			  | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
+			  | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
+			  | 0x10
+			  | (((SiS_Pr->CVTotal     - 2) & 0x200) >> 4)
+			  | (((SiS_Pr->CVDisplay   - 1) & 0x200) >> 3)
+			  | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
+
+   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* CR9 */
+
+   if(depth != 8) {
+      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;		/* SRE */
+      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
+   }
+
+   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart  - x) & 0xFF;			/* CR10 */
+   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd   - x) & 0x0F) | 0x80;		/* CR11 */
+   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;			/* CR12 */
+   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;			/* CR15 */
+   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;			/* CR16 */
+
+   SiS_Pr->CCRT1CRTC[13] =							/* SRA */
+			GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
+			GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
+			GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+			GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
+			GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
+			GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
+
+   SiS_Pr->CCRT1CRTC[14] =							/* SRB */
+			GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
+			GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
+			GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+			GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
+
+
+   SiS_Pr->CCRT1CRTC[15] =							/* SRC */
+			GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+			GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+}
+
+void
+SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex)
+{
+   unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
+   unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
+   int i, j;
+
+   /* 1:1 data: use data set by setcrt1crtc() */
+   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(modeflag & HalfDCLK) VGAHDE >>= 1;
+
+   SiS_Pr->CHDisplay = VGAHDE;
+   SiS_Pr->CHBlankStart = VGAHDE;
+
+   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
+   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
+
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+      tempbx = SiS_Pr->SiS_VGAHT;
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+         tempbx = SiS_Pr->PanelHT;
+      }
+      if(modeflag & HalfDCLK) tempbx >>= 1;
+      remaining = tempbx % 8;
+#endif
+   } else {
+#ifdef CONFIG_FB_SIS_315
+      /* OK for LCDA, LVDS */
+      tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
+      tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+         tempax = SiS_Pr->PanelXRes;
+      }
+      tempbx += tempax;
+      if(modeflag & HalfDCLK) tempbx -= VGAHDE;
+#endif
+   }
+   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
+
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+      if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
+	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
+	 SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
+	 if(modeflag & HalfDCLK) {
+	    SiS_Pr->CHSyncStart >>= 1;
+	    SiS_Pr->CHSyncEnd >>= 1;
+	 }
+      } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	 tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
+	 tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
+	 if(modeflag & HalfDCLK) {
+	    tempax >>= 1;
+	    tempbx >>= 1;
+	 }
+	 SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
+	 tempax = SiS_Pr->PanelHRE + 7;
+	 if(modeflag & HalfDCLK) tempax >>= 1;
+	 SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
+      } else {
+	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
+	 if(modeflag & HalfDCLK) {
+	    SiS_Pr->CHSyncStart >>= 1;
+	    tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
+	    SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
+	 } else {
+	    SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
+	    SiS_Pr->CHSyncStart += 8;
+	 }
+      }
+#endif
+   } else {
+#ifdef CONFIG_FB_SIS_315
+      tempax = VGAHDE;
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	 tempbx = SiS_Pr->PanelXRes;
+	 if(modeflag & HalfDCLK) tempbx >>= 1;
+	 tempax += ((tempbx - tempax) >> 1);
+      }
+      tempax += SiS_Pr->PanelHRS;
+      SiS_Pr->CHSyncStart = tempax;
+      tempax += SiS_Pr->PanelHRE;
+      SiS_Pr->CHSyncEnd = tempax;
+#endif
+   }
+
+   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax = SiS_Pr->PanelYRes;
+   } else if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+      /* Stupid hack for 640x400/320x200 */
+      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	 if((tempax + tempbx) == 438) tempbx += 16;
+      } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
+		(SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
+	 tempax = 0;
+	 tempbx = SiS_Pr->SiS_VGAVT;
+      }
+#endif
+   }
+   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
+
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
+   }
+   tempax += SiS_Pr->PanelVRS;
+   SiS_Pr->CVSyncStart = tempax;
+   tempax += SiS_Pr->PanelVRE;
+   SiS_Pr->CVSyncEnd = tempax;
+   if(SiS_Pr->ChipType < SIS_315H) {
+      SiS_Pr->CVSyncStart--;
+      SiS_Pr->CVSyncEnd--;
+   }
+
+   SiS_CalcCRRegisters(SiS_Pr, 8);
+   SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
+   SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
+   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
+
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i = 0, j = 0; i <= 7; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j = 0x10; i <= 10; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j = 0x15; i <= 12; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j = 0x0A; i <= 15; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+
+   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
+
+   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+   if(modeflag & DoubleScanMode) tempax |= 0x80;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
+
+}
+
+void
+SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+			int xres, int yres,
+			struct fb_var_screeninfo *var, bool writeres
+)
+{
+   unsigned short HRE, HBE, HRS, HBS, HDE, HT;
+   unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+   unsigned char  sr_data, cr_data, cr_data2;
+   int            A, B, C, D, E, F, temp;
+
+   sr_data = crdata[14];
+
+   /* Horizontal total */
+   HT =  crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
+   A = HT + 5;
+
+   /* Horizontal display enable end */
+   HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
+   E = HDE + 1;
+
+   /* Horizontal retrace (=sync) start */
+   HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
+   F = HRS - E - 3;
+
+   /* Horizontal blank start */
+   HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
+
+   sr_data = crdata[15];
+   cr_data = crdata[5];
+
+   /* Horizontal blank end */
+   HBE = (crdata[3] & 0x1f) |
+         ((unsigned short)(cr_data & 0x80) >> 2) |
+         ((unsigned short)(sr_data & 0x03) << 6);
+
+   /* Horizontal retrace (=sync) end */
+   HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
+
+   temp = HBE - ((E - 1) & 255);
+   B = (temp > 0) ? temp : (temp + 256);
+
+   temp = HRE - ((E + F + 3) & 63);
+   C = (temp > 0) ? temp : (temp + 64);
+
+   D = B - F - C;
+
+   if(writeres) var->xres = xres = E * 8;
+   var->left_margin = D * 8;
+   var->right_margin = F * 8;
+   var->hsync_len = C * 8;
+
+   /* Vertical */
+   sr_data = crdata[13];
+   cr_data = crdata[7];
+
+   /* Vertical total */
+   VT  = crdata[6] |
+	 ((unsigned short)(cr_data & 0x01) << 8) |
+	 ((unsigned short)(cr_data & 0x20) << 4) |
+	 ((unsigned short)(sr_data & 0x01) << 10);
+   A = VT + 2;
+
+   /* Vertical display enable end */
+   VDE = crdata[10] |
+	 ((unsigned short)(cr_data & 0x02) << 7) |
+	 ((unsigned short)(cr_data & 0x40) << 3) |
+	 ((unsigned short)(sr_data & 0x02) << 9);
+   E = VDE + 1;
+
+   /* Vertical retrace (=sync) start */
+   VRS = crdata[8] |
+	 ((unsigned short)(cr_data & 0x04) << 6) |
+	 ((unsigned short)(cr_data & 0x80) << 2) |
+	 ((unsigned short)(sr_data & 0x08) << 7);
+   F = VRS + 1 - E;
+
+   cr_data2 = (crdata[16] & 0x01) << 5;
+
+   /* Vertical blank start */
+   VBS = crdata[11] |
+	 ((unsigned short)(cr_data  & 0x08) << 5) |
+	 ((unsigned short)(cr_data2 & 0x20) << 4) |
+	 ((unsigned short)(sr_data  & 0x04) << 8);
+
+   /* Vertical blank end */
+   VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
+   temp = VBE - ((E - 1) & 511);
+   B = (temp > 0) ? temp : (temp + 512);
+
+   /* Vertical retrace (=sync) end */
+   VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
+   temp = VRE - ((E + F - 1) & 31);
+   C = (temp > 0) ? temp : (temp + 32);
+
+   D = B - F - C;
+
+   if(writeres) var->yres = yres = E;
+   var->upper_margin = D;
+   var->lower_margin = F;
+   var->vsync_len = C;
+
+   if((xres == 320) && ((yres == 200) || (yres == 240))) {
+	/* Terrible hack, but correct CRTC data for
+	 * these modes only produces a black screen...
+	 * (HRE is 0, leading into a too large C and
+	 * a negative D. The CRT controller does not
+	 * seem to like correcting HRE to 50)
+	 */
+      var->left_margin = (400 - 376);
+      var->right_margin = (328 - 320);
+      var->hsync_len = (376 - 328);
+
+   }
+
+}
+
+
+
+
diff --git a/drivers/video/fbdev/sis/init.h b/drivers/video/fbdev/sis/init.h
new file mode 100644
index 000000000000..85d6738b6c64
--- /dev/null
+++ b/drivers/video/fbdev/sis/init.h
@@ -0,0 +1,1541 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Data and prototypes for init.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _INIT_H_
+#define _INIT_H_
+
+#include "initdef.h"
+
+#include "vgatypes.h"
+#include "vstruct.h"
+#ifdef SIS_CP
+#undef SIS_CP
+#endif
+#include <linux/types.h>
+#include <asm/io.h>
+#include <linux/fb.h>
+#include "sis.h"
+#include <video/sisfb.h>
+
+/* Mode numbers */
+static const unsigned short ModeIndex_320x200[]      = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[]      = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00};  /* FSTN */
+static const unsigned short ModeIndex_400x300[]      = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[]      = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[]      = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[]      = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[]      = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[]      = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[]      = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[]      = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[]      = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[]      = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[]      = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[]      = {0x1d, 0x1e, 0x00, 0x1f};  /* 315 series only */
+static const unsigned short ModeIndex_960x600[]      = {0x20, 0x21, 0x00, 0x22};  /* 315 series only */
+static const unsigned short ModeIndex_1024x768[]     = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[]     = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1024x600[]     = {0x20, 0x21, 0x00, 0x22};  /* 300 series only */
+static const unsigned short ModeIndex_1280x1024[]    = {0x3a, 0x4d, 0x00, 0x65};
+static const unsigned short ModeIndex_1280x960[]     = {0x7c, 0x7d, 0x00, 0x7e};
+static const unsigned short ModeIndex_1152x768[]     = {0x23, 0x24, 0x00, 0x25};  /* 300 series only */
+static const unsigned short ModeIndex_1152x864[]     = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
+static const unsigned short ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x720[]     = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x800[]     = {0x14, 0x15, 0x00, 0x16};
+static const unsigned short ModeIndex_1280x854[]     = {0x1a, 0x1b, 0x00, 0x1c};
+static const unsigned short ModeIndex_1360x768[]     = {0x48, 0x4b, 0x00, 0x4e};
+static const unsigned short ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72};  /* 300 series, BARCO only */
+static const unsigned short ModeIndex_1400x1050[]    = {0x26, 0x27, 0x00, 0x28};  /* 315 series only */
+static const unsigned short ModeIndex_1680x1050[]    = {0x17, 0x18, 0x00, 0x19};  /* 315 series only */
+static const unsigned short ModeIndex_1600x1200[]    = {0x3c, 0x3d, 0x00, 0x66};
+static const unsigned short ModeIndex_1920x1080[]    = {0x2c, 0x2d, 0x00, 0x73};  /* 315 series only */
+static const unsigned short ModeIndex_1920x1440[]    = {0x68, 0x69, 0x00, 0x6b};
+static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
+static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
+
+static const unsigned char SiS_MDA_DAC[] =
+{
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
+};
+
+static const unsigned char SiS_CGA_DAC[] =
+{
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_EGA_DAC[] =
+{
+        0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+        0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+        0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+        0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+        0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+        0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+        0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_VGA_DAC[] =
+{
+	0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+	0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+	0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+	0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+	0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+	0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+	0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+	0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+	0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+	0x0B,0x0C,0x0D,0x0F,0x10
+};
+
+static const struct SiS_St SiS_SModeIDTable[] =
+{
+	{0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00,0x40},
+	{0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00,0x40},
+	{0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01,0x40},
+	{0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02,0x40},
+	{0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02,0x40},
+	{0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+	{0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04,0x40},
+	{0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05,0x40},
+	{0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03,0x40},
+	{0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03,0x40},
+	{0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04,0x40},
+	{0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05,0x40},
+	{0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05,0x40},
+	{0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05,0x40},
+	{0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05,0x40},
+	{0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05,0x40},
+	{0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04,0x40},
+	{0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05,0x40},
+	{0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05,0x40},
+	{0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiS_StResInfo[]=
+{
+	{ 640,400},
+	{ 640,350},
+	{ 720,400},
+	{ 720,350},
+	{ 640,480}
+};
+
+static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
+{
+	{  320, 200, 8, 8},   /* 0x00 */
+	{  320, 240, 8, 8},   /* 0x01 */
+	{  320, 400, 8, 8},   /* 0x02 */
+	{  400, 300, 8, 8},   /* 0x03 */
+	{  512, 384, 8, 8},   /* 0x04 */
+	{  640, 400, 8,16},   /* 0x05 */
+	{  640, 480, 8,16},   /* 0x06 */
+	{  800, 600, 8,16},   /* 0x07 */
+	{ 1024, 768, 8,16},   /* 0x08 */
+	{ 1280,1024, 8,16},   /* 0x09 */
+	{ 1600,1200, 8,16},   /* 0x0a */
+	{ 1920,1440, 8,16},   /* 0x0b */
+	{ 2048,1536, 8,16},   /* 0x0c */
+	{  720, 480, 8,16},   /* 0x0d */
+	{  720, 576, 8,16},   /* 0x0e */
+	{ 1280, 960, 8,16},   /* 0x0f */
+	{  800, 480, 8,16},   /* 0x10 */
+	{ 1024, 576, 8,16},   /* 0x11 */
+	{ 1280, 720, 8,16},   /* 0x12 */
+	{  856, 480, 8,16},   /* 0x13 */
+	{ 1280, 768, 8,16},   /* 0x14 */
+	{ 1400,1050, 8,16},   /* 0x15 */
+	{ 1152, 864, 8,16},   /* 0x16 */
+	{  848, 480, 8,16},   /* 0x17 */
+	{ 1360, 768, 8,16},   /* 0x18 */
+	{ 1024, 600, 8,16},   /* 0x19 */
+	{ 1152, 768, 8,16},   /* 0x1a */
+	{  768, 576, 8,16},   /* 0x1b */
+	{ 1360,1024, 8,16},   /* 0x1c */
+	{ 1680,1050, 8,16},   /* 0x1d */
+	{ 1280, 800, 8,16},   /* 0x1e */
+	{ 1920,1080, 8,16},   /* 0x1f */
+	{  960, 540, 8,16},   /* 0x20 */
+	{  960, 600, 8,16},   /* 0x21 */
+	{ 1280, 854, 8,16}    /* 0x22 */
+};
+
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+static const struct SiS_StandTable_S SiS_StandTable[]=
+{
+/* 0x00: MD_0_200 */
+ {
+  0x28,0x18,0x08,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x01: MD_1_200 */
+ {
+  0x28,0x18,0x08,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x02: MD_2_200 */
+ {
+  0x50,0x18,0x08,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x03: MD_3_200 - mode 0x03 - 0 */
+ {
+  0x50,0x18,0x08,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x04: MD_4 */
+ {
+  0x28,0x18,0x08,0x4000,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,   /* 0x2c is 2b for 300 */
+   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+   0xff},
+  {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x03,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+   0xff}
+ },
+/* 0x05: MD_5 */
+ {
+  0x28,0x18,0x08,0x4000,
+  {0x09,0x03,0x00,0x02},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,   /* 0x2c is 2b for 300 */
+   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+   0xff},
+  {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x03,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+   0xff}
+ },
+/* 0x06: MD_6 */
+ {
+  0x50,0x18,0x08,0x4000,
+  {0x01,0x01,0x00,0x06},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,   /* 55,81 is 54,80 for 300 */
+   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
+   0xff},
+  {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+   0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+   0x01,0x00,0x01,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
+   0xff}
+ },
+/* 0x07: MD_7 */
+ {
+  0x50,0x18,0x0e,0x1000,
+  {0x00,0x03,0x00,0x03},
+  0xa6,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+   0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+   0x0e,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+   0xff}
+ },
+/* 0x08: MDA_DAC */
+ {
+  0x00,0x00,0x00,0x0000,
+  {0x00,0x00,0x00,0x15},
+  0x15,
+  {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+   0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
+   0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
+   0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
+   0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+   0x15,0x15,0x15,0x15},
+  {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+   0x3f}
+ },
+/* 0x09: CGA_DAC */
+ {
+  0x00,0x10,0x04,0x0114,
+  {0x11,0x09,0x15,0x00},
+  0x10,
+  {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
+   0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
+   0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
+   0x04},
+  {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
+   0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
+   0x3e,0x2b,0x3b,0x2f},
+  {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+   0x3f}
+ },
+/* 0x0a: EGA_DAC */
+ {
+  0x00,0x10,0x04,0x0114,
+  {0x11,0x05,0x15,0x20},
+  0x30,
+  {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
+   0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
+   0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
+   0x06},
+  {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
+   0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
+   0x1e,0x0b,0x1b,0x0f},
+  {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+   0x3f}
+ },
+/* 0x0b: VGA_DAC */
+ {
+  0x00,0x10,0x04,0x0114,
+  {0x11,0x09,0x15,0x2a},
+  0x3a,
+  {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
+   0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
+   0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
+   0x1f},
+  {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
+   0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
+   0x1c,0x0e,0x11,0x15},
+  {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
+   0x04}
+ },
+/* 0x0c */
+ {
+  0x08,0x0c,0x10,0x0a08,
+  {0x0c,0x0e,0x10,0x0b},
+  0x0c,
+  {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
+   0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
+   0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
+   0x06},
+  {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
+   0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
+   0x00,0x00,0x00,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00}
+ },
+/* 0x0d: MD_D */
+ {
+  0x28,0x18,0x08,0x2000,
+  {0x09,0x0f,0x00,0x06},
+  0x63,
+  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,     /* 2c is 2b for 300 */
+   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* 0x0e: MD_E */
+ {
+  0x50,0x18,0x08,0x4000,
+  {0x01,0x0f,0x00,0x06},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,     /* 55,81 is 54,80 for 300 */
+   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* 0x0f: ExtVGATable - modes > 0x13 */
+ {
+  0x00,0x00,0x00,0x0000,
+  {0x01,0x0f,0x00,0x0e},
+  0x23,
+  {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+   0x01,0x00,0x00,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+   0xff}
+ },
+/* 0x10: ROM_SAVEPTR - totally different for 300 */
+ {
+  0x9f,0x3b,0x00,0x00c0,
+  {0x00,0x00,0x00,0x00},
+  0x00,
+  {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f,
+   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0,
+   0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00,0x00,0x00,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x00}
+ },
+/* 0x11: MD_F */
+ {
+  0x50,0x18,0x0e,0x8000,
+  {0x01,0x0f,0x00,0x06},
+  0xa2,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,    /* 55,81 is 54,80 on 300 */
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,    /* 82,84 is 83,85 on 300 */
+   0xff},
+  {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+   0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+   0x0b,0x00,0x05,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
+   0xff}
+ },
+/* 0x12: MD_10 */
+ {
+  0x50,0x18,0x0e,0x8000,
+  {0x01,0x0f,0x00,0x06},
+  0xa3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,    /* 55,81 is 54,80 on 300 */
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,    /* 82,84 is 83,85 on 300 */
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* 0x13: MD_0_350 */
+ {
+  0x28,0x18,0x0e,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0xa3,
+  {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,    /* b1 is a0 on 300 */
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x14: MD_1_350 */
+ {
+  0x28,0x18,0x0e,0x0800,
+  {0x09,0x03,0x00,0x02},
+  0xa3,
+  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x15: MD_2_350 */
+ {
+  0x50,0x18,0x0e,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0xa3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x16: MD_3_350 - mode 0x03 - 1 */
+ {
+  0x50,0x18,0x0e,0x1000,
+  {0x01,0x03,0x00,0x02},
+  0xa3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+   0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x08,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x17: MD_0_1_400 */
+ {
+  0x28,0x18,0x10,0x0800,
+  {0x08,0x03,0x00,0x02},
+  0x67,
+  {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,    /* b1 is a0 on 300 */
+   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x0c,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x18: MD_2_3_400 - mode 0x03 - 2 */
+ {
+  0x50,0x18,0x10,0x1000,
+  {0x00,0x03,0x00,0x02},
+  0x67,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x0c,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+   0xff}
+ },
+/* 0x19: MD_7_400 */
+ {
+  0x50,0x18,0x10,0x1000,
+  {0x00,0x03,0x00,0x02},
+  0x66,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+   0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+   0x0e,0x00,0x0f,0x08},
+  {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+   0xff}
+ },
+/* 0x1a: MD_11 */
+ {
+  0x50,0x1d,0x10,0xa000,
+  {0x01,0x0f,0x00,0x06},
+  0xe3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,    /* 55,81 is 54,80 on 300 */
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3,    /* e9,8b is ea,8c on 300 */
+   0xff},
+  {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+   0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
+   0xff}
+ },
+/* 0x1b: ExtEGATable - Modes <= 0x02 */
+ {
+  0x50,0x1d,0x10,0xa000,
+  {0x01,0x0f,0x00,0x06},
+  0xe3,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,    /* 55,81 is 54,80 on 300 */
+   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+   0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,    /* e9,8b is ea,8c on 300 */
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+   0x01,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+   0xff}
+ },
+/* 0x1c: MD_13 */
+ {
+  0x28,0x18,0x08,0x2000,
+  {0x01,0x0f,0x00,0x0e},
+  0x63,
+  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,    /* 55,81 is 54,80 on 300 */
+   0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
+   0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
+   0xff},
+  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+   0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+   0x41,0x00,0x0f,0x00},
+  {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+   0xff}
+ }
+};
+#endif
+
+/**************************************************************/
+/* SIS VIDEO BRIDGE ----------------------------------------- */
+/**************************************************************/
+
+static const unsigned char SiS_SoftSetting  = 0x30;   /* RAM setting */
+
+static const unsigned char SiS_OutputSelect = 0x40;
+
+static const unsigned char SiS_NTSCTiming[] = {
+	0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+	0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+	0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+	0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
+	0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
+	0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
+	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
+	0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
+};
+
+static const unsigned char SiS_PALTiming[] = {
+	0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
+	0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
+	0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
+	0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17,
+	0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02,
+	0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
+	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
+	0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
+};
+
+static const unsigned char SiS_HiTVExtTiming[] = {
+	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+	0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
+	0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
+	0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
+	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
+	0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
+};
+
+static const unsigned char SiS_HiTVSt1Timing[] = {
+	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+	0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
+	0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10,
+	0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40,
+	0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86,
+	0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
+};
+
+static const unsigned char SiS_HiTVSt2Timing[] = {
+	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+	0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
+	0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
+	0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
+	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
+	0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
+};
+
+#if 0
+static const unsigned char SiS_HiTVTextTiming[] = {
+	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+	0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
+	0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
+	0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40,
+        0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96,
+	0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00
+};
+#endif
+
+static const unsigned char SiS_HiTVGroup3Data[] = {
+	0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
+	0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
+	0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+	0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
+	0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+	0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9,
+	0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75,
+	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+};
+
+static const unsigned char SiS_HiTVGroup3Simu[] = {
+	0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
+	0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
+	0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+	0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
+	0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+	0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4,
+	0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
+	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+};
+
+#if 0
+static const unsigned char SiS_HiTVGroup3Text[] = {
+	0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
+	0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
+	0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+	0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
+	0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+	0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca,
+	0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
+	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+};
+#endif
+
+static const struct SiS_TVData SiS_StPALData[] =
+{
+ {    1,   1, 864, 525,1270, 400, 100, 0, 760,    0,0xf4,0xff,0x1c,0x22},
+ {    1,   1, 864, 525,1270, 350, 100, 0, 760,    0,0xf4,0xff,0x1c,0x22},
+ {    1,   1, 864, 525,1270, 400,   0, 0, 720,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 864, 525,1270, 350,   0, 0, 720,    0,0xf4,0x0b,0x1c,0x0a},
+ {    1,   1, 864, 525,1270, 480,  50, 0, 760,    0,0xf4,0xff,0x1c,0x22},
+ {    1,   1, 864, 525,1270, 600,  50, 0,   0,0x300,0xf4,0xff,0x1c,0x22}
+};
+
+static const struct SiS_TVData SiS_ExtPALData[] =
+{
+ {   27,  10, 848, 448,1270, 530,  50, 0,  50,    0,0xf4,0xff,0x1c,0x22},  /* 640x400, 320x200 */
+ {  108,  35, 848, 398,1270, 530,  50, 0,  50,    0,0xf4,0xff,0x1c,0x22},
+ {   12,   5, 954, 448,1270, 530,  50, 0,  50,    0,0xf1,0x04,0x1f,0x18},
+ {    9,   4, 960, 463,1644, 438,  50, 0,  50,    0,0xf4,0x0b,0x1c,0x0a},
+ {    9,   4, 848, 528,1270, 530,   0, 0,  50,    0,0xf5,0xfb,0x1b,0x2a},  /* 640x480, 320x240 */
+ {   36,  25,1060, 648,1270, 530, 438, 0, 438,    0,0xeb,0x05,0x25,0x16},  /* 800x600, 400x300 */
+ {    3,   2,1080, 619,1270, 540, 438, 0, 438,    0,0xf3,0x00,0x1d,0x20},  /* 720x576 */
+ {    1,   1,1170, 821,1270, 520, 686, 0, 686,    0,0xF3,0x00,0x1D,0x20},  /* 1024x768 */
+ {    1,   1,1170, 821,1270, 520, 686, 0, 686,    0,0xF3,0x00,0x1D,0x20},  /* 1024x768 (for NTSC equ) */
+ {    9,   4, 848, 528,1270, 530,   0, 0,  50,    0,0xf5,0xfb,0x1b,0x2a}   /* 720x480 */
+};
+
+static const struct SiS_TVData SiS_StNTSCData[] =
+{
+ {    1,   1, 858, 525,1270, 400,  50, 0, 760,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 858, 525,1270, 350,  50, 0, 640,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 858, 525,1270, 400,   0, 0, 720,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 858, 525,1270, 350,   0, 0, 720,    0,0xf4,0x0b,0x1c,0x0a},
+ {    1,   1, 858, 525,1270, 480,   0, 0, 760,    0,0xf1,0x04,0x1f,0x18}
+};
+
+static const struct SiS_TVData SiS_ExtNTSCData[] =
+{
+ {  143,  65, 858, 443,1270, 440, 171, 0, 171,    0,0xf1,0x04,0x1f,0x18},    /* 640x400, 320x200 */
+ {   88,  35, 858, 393,1270, 440, 171, 0, 171,    0,0xf1,0x04,0x1f,0x18},
+ {  143,  70, 924, 443,1270, 440,  92, 0,  92,    0,0xf1,0x04,0x1f,0x18},
+ {  143,  70, 924, 393,1270, 440,  92, 0,  92,    0,0xf4,0x0b,0x1c,0x0a},
+ {  143,  76, 836, 523,1270, 440, 224, 0,   0,    0,0xf1,0x05,0x1f,0x16},    /* 640x480, 320x240 */
+ {  143, 120,1056, 643,1270, 440,   0, 1,   0,    0,0xf4,0x10,0x1c,0x00},    /* 800x600, 400x300  */
+ {  143,  76, 836, 523,1270, 440,   0, 1,   0,    0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
+ {    1,   1,1100, 811,1412, 440,   0, 1,   0,    0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
+#if 0  /* flimmert und ist unten abgeschnitten (NTSCHT, NTSC clock) */
+ {   65,  64,1056, 791,1270, 480, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0
+ {    1,   1,1100, 811,1412, 440,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0
+ {    1,   1,1120, 821,1516, 420,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0
+ {    1,   1, 938, 821,1516, 420,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0 /* zoom hin, unten abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ {    1,   1,1072, 791,1270, 480, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 1 /* zu weit links (squeezed) (NTSC2HT, NTSC1024 clock) */
+ {    1,   1,1100, 846,1270, 440, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0 /* zu weit links, rechts abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ {    1,   1,1100, 846,1412, 440, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+};
+
+static const struct SiS_TVData SiS_StHiTVData[] =  /* Slave + TVSimu */
+{
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x150, 1, 0, 0, 0, 0, 0, 0}
+};
+
+static const struct SiS_TVData SiS_St2HiTVData[] = /* Slave */
+{
+ {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc, 	  0, 0, 0, 0, 0, 0, 0, 0},
+ {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    5,   2, 0x348,0x233,0x670,0x3c0,0x08d, 1, 0, 0, 0, 0, 0, 0},
+ {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x17c, 1, 0, 0, 0, 0, 0, 0}
+};
+
+static const struct SiS_TVData SiS_ExtHiTVData[] =
+{ /* all ok */
+ {    6,   1, 0x348,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    6,   1, 0x348,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    5,   1, 0x348,0x233,0x670,0x3c0,0x166, 1, 0, 0, 0, 0, 0, 0},  /* 640x480   */
+ {   16,   5, 0x41a,0x2ab,0x670,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0},  /* 800x600   */
+ {   25,  12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 1024x768  */
+ {    5,   4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0},  /* 1280x1024 */
+ {    4,   1, 0x41a,0x233,0x60c,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0},  /* 800x480   */
+ {    5,   2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 1024x576  */
+ {    8,   5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0},  /* 1280x720  */
+ {    8,   3, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 960x600  */
+};
+
+static const struct SiS_TVData SiS_St525pData[] =
+{
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x1e0,    0, 0, 0x2f8, 0, 0, 0, 0, 0}
+};
+
+static const struct SiS_TVData SiS_St750pData[] =
+{
+ {    1,   1, 0x672,0x2ee,0x500,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x190,    0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x15e,    0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x1e0,    0, 0, 0x2f8, 0, 0, 0, 0, 0}
+};
+
+static const struct SiS_TVData SiS_Ext750pData[] =
+{ /* all ok */
+ {    3,  1,  935, 470, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},  /* 320x200/640x400 */
+ {   24,  7,  935, 420, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
+ {    3,  1,  935, 470, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
+ {   24,  7,  935, 420, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
+ {    2,  1, 1100, 590, 1130, 640,  50, 0, 0, 0, 0, 0, 0, 0},  /* 640x480 */
+ {    3,  2, 1210, 690, 1130, 660,  50, 0, 0, 0, 0, 0, 0, 0},  /* 800x600 OK */
+ {    2,  1, 1100, 562, 1130, 640,   0, 1, 0, 0, 0, 0, 0, 0},  /* 720x480 OK */
+ {    1,  1, 1375, 878, 1130, 640, 638, 0, 0, 0, 0, 0, 0, 0},  /* 1024x768 OK */
+ {    5,  3, 1100, 675, 1130, 640,   0, 1, 0, 0, 0, 0, 0, 0},  /* 720/768x576 OK */
+ {   25, 24, 1496, 755, 1120, 680,  50, 0, 0, 0, 0, 0, 0, 0}   /* 1280x720 OK */
+};
+
+static const struct SiS_LCDData SiS_LCD1280x720Data[] =  /* 2.03.00 */
+{
+	{  44,   15,  864,  430, 1408,  806 }, /* 640x400 */
+	{ 128,   35,  792,  385, 1408,  806 },
+	{  44,   15,  864,  430, 1408,  806 },
+	{ 128,   35,  792,  385, 1408,  806 },
+	{  22,    9,  864,  516, 1408,  806 }, /* 640x480 */
+	{   8,    5, 1056,  655, 1408,  806 }, /* 800x600 */
+	{   0,    0,    0,    0,    0,    0 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 }, /* 1280x1024 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }  /* 1280x720 */
+};
+
+/* About 1280x768: For TMDS, Panel_1280x768 will only be set if
+ * the panel is a Fujitsu 7911 (VL-17WDX8) (with clock 81, 1688x802)
+ * Other TMDS panels of this resolution will be treated as custom.
+ * For LVDS, we know another type (_2).
+ * (Note: 1280x768_3 is now special for SiS301/NetVista
+ */
+
+static const struct SiS_LCDData SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
+{
+	{  64,   21,  858,  434, 1408,  806 }, /* 640x400 */
+	{  32,    9,  858,  372, 1408,  806 },
+	{  64,   21,  858,  434, 1408,  806 },
+	{  32,    9,  858,  372, 1408,  806 },
+	{ 143,   68, 1024,  527, 1408,  806 }, /* 640x480 */
+	{  64,   51, 1364,  663, 1408,  806 }, /* 800x600 */
+	{  88,   81, 1296,  806, 1408,  806 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }, /* 1280x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{  16,   15, 1600,  750, 1600,  806 }  /* 1280x720 - from Ext */
+};
+
+static const struct SiS_LCDData SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
+{
+	{  16,    5,  960,  410, 1600,  806 }, /* 640x400 */
+	{  64,   21, 1152,  364, 1600,  806 },
+	{  16,    5,  960,  410, 1600,  806 },
+	{  64,   21, 1152,  364, 1600,  806 },
+	{  32,   13, 1040,  493, 1600,  806 }, /* 640x480 */
+	{  16,    9, 1152,  618, 1600,  806 }, /* 800x600 */
+	{  25,   21, 1344,  796, 1600,  806 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1600,  806, 1600,  806 }, /* 1280x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{  16,   15, 1600,  750, 1600,  806 }  /* 1280x720 */
+};
+
+#if 0  /* Not used; _3 now reserved for NetVista (SiS301) */
+static const struct SiS_LCDData SiS_LCD1280x768_3Data[] =
+{
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  32,   15, 1056,  513, 1408,  806 }, /* ,664 */	/* 640x480 */
+	{ 176,  125, 1280,  640, 1408,  806 }, /* ,768 */	/* 800x600 */
+	{  64,   61, 1342,  806, 1408,  806 },			/* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 },			/* 1280x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{  16,   15, 1600,  750, 1600,  806 }  /* 1280x720  from above */
+};
+#endif
+
+static const struct SiS_LCDData SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
+{
+	{ 128,   51, 1122,  412, 1408,  816 },  /* 640x400 */
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{ 128,   51, 1122,  412, 1408,  816 },
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{   8,    3,  880,  491, 1408,  816 },  /* 640x480 */
+	{  11,    6, 1024,  612, 1408,  816 },  /* 800x600 */
+	{  22,   21, 1400,  784, 1408,  816 },  /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },  /* 1280x1024 */
+	{   1,    1, 1408,  816, 1408,  816 },  /* 1280x800 */
+	{   0,    0,    0,    0,    0,    0 },  /* 1280x768 (patch index) */
+	{   0,    0,    0,    0,    0,    0 }   /* 1280x720 */
+};
+
+static const struct SiS_LCDData SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
+{
+	{  97,   42, 1344,  409, 1552,  812 }, /* 640x400 */
+	{  97,   35, 1280,  358, 1552,  812 },
+	{  97,   42, 1344,  409, 1552,  812 },
+	{  97,   35, 1280,  358, 1552,  812 },
+	{  97,   39, 1040,  488, 1552,  812 }, /* 640x480 */
+	{ 194,  105, 1120,  608, 1552,  812 }, /* 800x600 */
+	{  97,   84, 1400,  780, 1552,  812 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 }, /* 1280x1024 */
+	{   1,    1, 1552,  812, 1552,  812 }, /* 1280x800 */
+	{  97,   96, 1600,  780, 1552,  812 }, /* 1280x768 - patch index */
+	{  97,   90, 1600,  730, 1552,  812 }  /* 1280x720 */
+};
+
+#if 0
+static const struct SiS_LCDData SiS_LCD1280x800_3Data[] = /* 2.02.05a (LVDS); m250 */
+{
+	{ 128,   51, 1122,  412, 1408,  816 }, /* 640x400 */
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{ 128,   51, 1122,  412, 1408,  816 },
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{   8,    3,  880,  491, 1408,  816 }, /* 640x480 */
+	{  11,    6, 1024,  612, 1408,  816 }, /* 800x600 */
+	{  22,   21, 1400,  784, 1408,  816 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 }, /* 1280x1024 */
+	{   1,    1, 1408,  816, 1408,  816 }, /* 1280x800 */
+	{   0,    0,    0,    0,    0,    0 }, /* 1280x768 - patch index */
+	{   0,    0,    0,    0,    0,    0 }  /* 1280x720 */
+};
+#endif
+
+static const struct SiS_LCDData SiS_LCD1280x854Data[] = /* 2.21.00CS (LVDS) */
+{
+	{  56,   15,  936,  410, 1664,  861 },  /* 640x400 */
+	{  64,   25, 1586,  355, 1664,  861 },
+	{  56,   15,  936,  410, 1664,  861 },
+	{  64,   25, 1586,  355, 1664,  861 },
+	{  91,   45, 1464,  485, 1664,  861 },  /* 640x480 */
+	{ 182,   75,  976,  605, 1664,  861 },  /* 800x600 */
+	{  91,   66, 1342,  774, 1664,  861 },  /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },  /* 1280x1024 */
+	{  26,   25, 1708,  807, 1664,  861 },  /* 1280x800 */
+	{  13,   12, 1708,  774, 1664,  861 },  /* 1280x768 - patch index */
+	{  52,   45, 1708,  725, 1664,  861 },  /* 1280x720 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1664,  861, 1664,  861 }   /* 1280x854 */
+};
+
+static const struct SiS_LCDData SiS_LCD1280x960Data[] =
+{
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{   30,  11, 1056,  625, 1800, 1000 },
+	{    5,   3, 1350,  800, 1800, 1000 },
+	{    1,   1, 1576, 1050, 1576, 1050 },
+	{    1,   1, 1800, 1000, 1800, 1000 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 }
+};
+
+static const struct SiS_LCDData SiS_StLCD1400x1050Data[] =
+{
+	{ 211,  100, 2100,  408, 1688, 1066 },
+	{ 211,   64, 1536,  358, 1688, 1066 },
+	{ 211,  100, 2100,  408, 1688, 1066 },
+	{ 211,   64, 1536,  358, 1688, 1066 },
+	{ 211,   48,  840,  488, 1688, 1066 },
+	{ 211,   72, 1008,  609, 1688, 1066 },
+	{ 211,  128, 1400,  776, 1688, 1066 },
+	{ 211,  205, 1680, 1041, 1688, 1066 },
+	{   1,    1, 1688, 1066, 1688, 1066 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 }
+};
+
+static const struct SiS_LCDData SiS_ExtLCD1400x1050Data[] =
+{
+/*	{ 211,   60, 1260,  410, 1688, 1066 },    640x400 (6330) */
+	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 (6325) WORKS */
+	{ 211,   64, 1536,  358, 1688, 1066 },
+	{ 211,  100, 2100,  408, 1688, 1066 },
+	{ 211,   64, 1536,  358, 1688, 1066 },
+/*	{ 211,   80, 1400,  490, 1688, 1066 },    640x480 (6330) */
+	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 (6325) WORKS */
+/*	{ 211,  117, 1638,  613, 1688, 1066 },    800x600 (6330) */
+	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 (6325) WORKS */
+	{ 211,  128, 1400,  776, 1688, 1066 }, /* 1024x768 */
+	{ 211,  205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
+	{   1,    1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
+	{   0,    0,    0,    0,    0,    0 }, /* kludge */
+	{ 211,  120, 1400,  730, 1688, 1066 }, /* 1280x720 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 }
+};
+
+static const struct SiS_LCDData SiS_LCD1680x1050Data[] =
+{
+	{  95,   24, 1260,  410, 1900, 1066 }, /*  0 640x400 */
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   24, 1260,  410, 1900, 1066 },
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   32, 1400,  490, 1900, 1066 }, /*  4 640x480 */
+	{  95,   42, 1470,  610, 1900, 1066 }, /*  5 800x600 */
+	{  95,   64, 1750,  784, 1900, 1066 }, /*  6 1024x768 */
+	{  95,   94, 1900, 1055, 1900, 1066 }, /*  7 1280x1024 */
+	{  41,   31, 1900,  806, 1900, 1066 }, /*  8 1280x768 */
+	{  95,   69, 1800,  817, 1900, 1066 }, /*  9 1280x800 patch index */
+	{  13,    9, 1900,  739, 1900, 1066 }, /* 10 1280x720 */
+	{  95,   94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch index */
+	{   1,    1, 1900, 1066, 1900, 1066 }, /* 12 1680x1050 */
+	{   0,    0,    0,    0,    0,    0 }
+};
+
+static const struct SiS_LCDData SiS_StLCD1600x1200Data[] =
+{
+	{27,  4, 800, 500, 2160, 1250 },
+	{27,  4, 800, 500, 2160, 1250 },
+	{ 6,  1, 900, 500, 2160, 1250 },
+	{ 6,  1, 900, 500, 2160, 1250 },
+	{27,  1, 800, 500, 2160, 1250 },
+	{ 4,  1,1080, 625, 2160, 1250 },
+	{ 5,  2,1350, 800, 2160, 1250 },
+	{135,88,1600,1100, 2160, 1250 },
+	{72, 49,1680,1092, 2160, 1250 },
+	{ 1,  1,2160,1250, 2160, 1250 },
+	{ 0,  0,   0,   0,    0,    0 },
+	{ 0,  0,   0,   0,    0,    0 },
+	{ 0,  0,   0,   0,    0,    0 },
+	{ 0,  0,   0,   0,    0,    0 }
+};
+
+static const struct SiS_LCDData SiS_ExtLCD1600x1200Data[] =
+{
+	{72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) WORKS */
+/*	{27, 4, 800, 500, 2160, 1250 },    640x400 (6235) */
+	{27, 4, 800, 500, 2160, 1250 },
+	{ 6, 1, 900, 500, 2160, 1250 },
+	{ 6, 1, 900, 500, 2160, 1250 },
+	{45, 8, 960, 505, 2160, 1250 }, /* 640x480 (6330) WORKS */
+/*	{27, 1, 800, 500, 2160, 1250 },    640x480 (6325) */
+	{ 4, 1,1080, 625, 2160, 1250 },
+	{ 5, 2,1350, 800, 2160, 1250 },
+	{27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
+	{72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
+	{ 1, 1,2160,1250, 2160, 1250 },
+	{ 0, 0,   0,   0,    0,    0 },
+	{ 0, 0,   0,   0,    0,    0 },
+	{ 0, 0,   0,   0,    0,    0 },
+	{ 0, 0,   0,   0,    0,    0 }
+};
+
+static const struct SiS_LCDData SiS_NoScaleData[] =
+{
+	{ 1, 1, 800, 449, 800, 449 },  /* 0x00: 320x200, 640x400 */
+	{ 1, 1, 800, 449, 800, 449 },
+	{ 1, 1, 900, 449, 900, 449 },
+	{ 1, 1, 900, 449, 900, 449 },
+	{ 1, 1, 800, 525, 800, 525 },  /* 0x04: 320x240, 640x480  */
+	{ 1, 1,1056, 628,1056, 628 },  /* 0x05: 400x300, 800x600  */
+	{ 1, 1,1344, 806,1344, 806 },  /* 0x06: 512x384, 1024x768 */
+	{ 1, 1,1688,1066,1688,1066 },  /* 0x07: 1280x1024 */
+        { 1, 1,1688, 802,1688, 802 },  /* 0x08: 1280x768: Fujitsu, TMDS only */
+        { 1, 1,2160,1250,2160,1250 },  /* 0x09: 1600x1200 */
+	{ 1, 1,1800,1000,1800,1000 },  /* 0x0a: 1280x960  */
+	{ 1, 1,1688,1066,1688,1066 },  /* 0x0b: 1400x1050 */
+	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS, projector)  */
+	{ 1, 1,1552, 812,1552, 812 },  /* 0x0d: 1280x800_2 (LVDS) (was: 1408,816/ 1656,841) */
+	{ 1, 1,1900,1066,1900,1066 },  /* 0x0e: 1680x1050 (LVDS) */
+	{ 1, 1,1660, 806,1660, 806 },  /* 0x0f: 1280x768_2 (LVDS) */
+	{ 1, 1,1664, 798,1664, 798 },  /* 0x10: 1280x768_3 (NetVista SiS 301) - TODO */
+	{ 1, 1,1688, 802,1688, 802 },  /* 0x11: 1280x768   (TMDS Fujitsu) */
+	{ 1, 1,1408, 806,1408, 806 },  /* 0x12: 1280x720 (LVDS) */
+	{ 1, 1, 896, 497, 896, 497 },  /* 0x13: 720x480 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x14: 720x576 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x15: 768x576 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x16: 848x480 */
+	{ 1, 1,1064, 497,1064, 497 },  /* 0x17: 856x480 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x18: 800x480 */
+	{ 1, 1,1328, 739,1328, 739 },  /* 0x19: 1024x576 */
+	{ 1, 1,1680, 892,1680, 892 },  /* 0x1a: 1152x864 */
+	{ 1, 1,1808, 808,1808, 808 },  /* 0x1b: 1360x768 */
+	{ 1, 1,1104, 563,1104, 563 },  /* 0x1c: 960x540 */
+	{ 1, 1,1120, 618,1120, 618 },  /* 0x1d: 960x600 */
+	{ 1, 1,1408, 816,1408, 816 },  /* 0x1f: 1280x800 (TMDS special) */
+	{ 1, 1,1760,1235,1760,1235 },  /* 0x20: 1600x1200 for LCDA */
+	{ 1, 1,2048,1320,2048,1320 },  /* 0x21: 1600x1200 for non-SiS LVDS */
+	{ 1, 1,1664, 861,1664, 861 }   /* 0x22: 1280x854 */
+};
+
+/**************************************************************/
+/* LVDS ----------------------------------------------------- */
+/**************************************************************/
+
+/* FSTN/DSTN 320x240, 2 variants */
+static const struct SiS_LVDSData SiS_LVDS320x240Data_1[]=
+{
+	{ 848, 433, 400, 525},
+	{ 848, 389, 400, 525},
+	{ 848, 433, 400, 525},
+	{ 848, 389, 400, 525},
+	{ 848, 518, 400, 525},
+	{1056, 628, 400, 525},
+	{ 400, 525, 400, 525}  /* xSTN */
+};
+
+static const struct SiS_LVDSData SiS_LVDS320x240Data_2[]=
+{
+	{ 800, 445, 800, 525},
+	{ 800, 395, 800, 525},
+	{ 800, 445, 800, 525},
+	{ 800, 395, 800, 525},
+	{ 800, 525, 800, 525},
+	{1056, 628,1056, 628},
+	{ 480, 525, 480, 525} /* xSTN */
+};
+
+static const struct SiS_LVDSData SiS_LVDS640x480Data_1[]=
+{
+	{ 800, 445, 800, 525},   /* 800, 449, 800, 449 */
+	{ 800, 395, 800, 525},
+	{ 800, 445, 800, 525},
+	{ 800, 395, 800, 525},
+	{ 800, 525, 800, 525}
+};
+
+static const struct SiS_LVDSData SiS_LVDS800x600Data_1[]=
+{
+	{ 848, 433,1060, 629},
+	{ 848, 389,1060, 629},
+	{ 848, 433,1060, 629},
+	{ 848, 389,1060, 629},
+	{ 848, 518,1060, 629},
+	{1056, 628,1056, 628}
+};
+
+static const struct SiS_LVDSData SiS_LVDS1024x600Data_1[] =
+{
+	{ 840, 604,1344, 800},
+	{ 840, 560,1344, 800},
+	{ 840, 604,1344, 800},
+	{ 840, 560,1344, 800},
+	{ 840, 689,1344, 800},
+	{1050, 800,1344, 800},
+	{1344, 800,1344, 800}
+};
+
+static const struct SiS_LVDSData SiS_LVDS1024x768Data_1[]=
+{
+	{ 840, 438,1344, 806},
+	{ 840, 409,1344, 806},
+	{ 840, 438,1344, 806},
+	{ 840, 409,1344, 806},
+	{ 840, 518,1344, 806},   /* 640x480 */
+	{1050, 638,1344, 806},   /* 800x600 */
+	{1344, 806,1344, 806},   /* 1024x768 */
+};
+
+static const struct SiS_LVDSData SiS_CHTVUNTSCData[]=
+{
+	{ 840, 600, 840, 600},
+	{ 840, 600, 840, 600},
+	{ 840, 600, 840, 600},
+	{ 840, 600, 840, 600},
+	{ 784, 600, 784, 600},
+	{1064, 750,1064, 750},
+        {1160, 945,1160, 945}
+};
+
+static const struct SiS_LVDSData SiS_CHTVONTSCData[]=
+{
+	{ 840, 525, 840, 525},
+	{ 840, 525, 840, 525},
+	{ 840, 525, 840, 525},
+	{ 840, 525, 840, 525},
+	{ 784, 525, 784, 525},
+	{1040, 700,1040, 700},
+        {1160, 840,1160, 840}
+};
+
+/* CRT1 CRTC data for slave modes */
+
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_1[] =
+{
+ {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
+   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
+   0x00 }},
+ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+   0x00 }},
+ {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
+   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+   0x00 }},
+ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+   0x00 }},
+ {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
+   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
+   0x00 }},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01 }},
+ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00 }}
+};
+
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+#if 0
+ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}
+#endif
+ {{0x5f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe8,0x0c,0x00,0x00,0x05,
+   0x00}},
+};
+
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2_H[] =
+{
+ {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
+   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
+   0x00}},
+ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+   0x00}},
+ {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
+   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+   0x00}},
+ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+   0x00}},
+ {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
+   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}
+};
+
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}
+};
+
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3_H[] =
+{
+ {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
+   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
+   0x00}},
+ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+   0x00}},
+ {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
+   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+   0x00}},
+ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+   0x00}},
+ {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
+   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}
+};
+
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}}
+};
+
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
+{
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
+   0x00}},
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
+   0x00}},
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
+   0x00}},
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
+   0x00}},
+ {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}
+};
+
+bool		SiSInitPtr(struct SiS_Private *SiS_Pr);
+unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+				int VDisplay, int Depth, bool FSTN,
+				unsigned short CustomT, int LCDwith, int LCDheight,
+				unsigned int VBFlags2);
+unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+				int VDisplay, int Depth, unsigned int VBFlags2);
+unsigned short	SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+				int VDisplay, int Depth, unsigned int VBFlags2);
+
+void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+void		SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+void		SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+
+bool		SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+				unsigned short *ModeIdIndex);
+unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+unsigned short  SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short  SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short	SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+unsigned short	SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
+				unsigned short ModeIdIndex, unsigned short RRTI);
+#ifdef CONFIG_FB_SIS_300
+void		SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+				unsigned short *idx2);
+unsigned short	SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
+unsigned short	SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
+#endif
+void		SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+void		SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+void		SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+void		SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+				int yres, struct fb_var_screeninfo *var, bool writeres);
+
+/* From init301.c: */
+extern void		SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex, int chkcrt2mode);
+extern void		SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+extern void		SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+extern void		SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+extern void		SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+extern void		SiS_DisableBridge(struct SiS_Private *);
+extern bool		SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
+extern unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+extern void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+extern unsigned short	SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+extern unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+extern unsigned short	SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex, unsigned short RRTI);
+extern bool		SiS_IsVAMode(struct SiS_Private *);
+extern bool		SiS_IsDualEdge(struct SiS_Private *);
+
+#ifdef CONFIG_FB_SIS_300
+extern unsigned int	sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern void		sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
+				unsigned int val);
+#endif
+#ifdef CONFIG_FB_SIS_315
+extern void		sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
+				unsigned char val);
+extern unsigned int	sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
+
+#endif
+
diff --git a/drivers/video/fbdev/sis/init301.c b/drivers/video/fbdev/sis/init301.c
new file mode 100644
index 000000000000..a89e3cafd5ad
--- /dev/null
+++ b/drivers/video/fbdev/sis/init301.c
@@ -0,0 +1,11071 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Mode initializing code (CRT2 section)
+ * for SiS 300/305/540/630/730,
+ *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ *     XGI V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
+ * Used by permission.
+ *
+ */
+
+#if 1
+#define SET_EMI		/* 302LV/ELV: Set EMI values */
+#endif
+
+#if 1
+#define SET_PWD		/* 301/302LV: Set PWD */
+#endif
+
+#define COMPAL_HACK	/* Needed for Compal 1400x1050 (EMI) */
+#define COMPAQ_HACK	/* Needed for Inventec/Compaq 1280x1024 (EMI) */
+#define ASUS_HACK	/* Needed for Asus A2H 1024x768 (EMI) */
+
+#include "init301.h"
+
+#ifdef CONFIG_FB_SIS_300
+#include "oem300.h"
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+#include "oem310.h"
+#endif
+
+#define SiS_I2CDELAY      1000
+#define SiS_I2CDELAYSHORT  150
+
+static unsigned short	SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
+static void		SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+
+/*********************************************/
+/*         HELPER: Lock/Unlock CRT2          */
+/*********************************************/
+
+void
+SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType == XGI_20)
+      return;
+   else if(SiS_Pr->ChipType >= SIS_315H)
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+   else
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
+}
+
+static
+void
+SiS_LockCRT2(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType == XGI_20)
+      return;
+   else if(SiS_Pr->ChipType >= SIS_315H)
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
+   else
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
+}
+
+/*********************************************/
+/*            HELPER: Write SR11             */
+/*********************************************/
+
+static void
+SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
+{
+   if(SiS_Pr->ChipType >= SIS_661) {
+      DataAND &= 0x0f;
+      DataOR  &= 0x0f;
+   }
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
+}
+
+/*********************************************/
+/*    HELPER: Get Pointer to LCD structure   */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_315
+static unsigned char *
+GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned char  *myptr = NULL;
+   unsigned short romindex = 0, reg = 0, idx = 0;
+
+   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    * Exception: If the BIOS has better knowledge (such as in case
+    * of machines with a 301C and a panel that does not support DDC)
+    * use the BIOS data as well.
+    */
+
+   if((SiS_Pr->SiS_ROMNew) &&
+      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
+
+      if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
+      else                           reg = 0x7d;
+
+      idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
+
+      if(idx < (8*26)) {
+         myptr = (unsigned char *)&SiS_LCDStruct661[idx];
+      }
+      romindex = SISGETROMW(0x100);
+      if(romindex) {
+         romindex += idx;
+         myptr = &ROMAddr[romindex];
+      }
+   }
+   return myptr;
+}
+
+static unsigned short
+GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short romptr = 0;
+
+   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    * Exception: If the BIOS has better knowledge (such as in case
+    * of machines with a 301C and a panel that does not support DDC)
+    * use the BIOS data as well.
+    */
+
+   if((SiS_Pr->SiS_ROMNew) &&
+      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
+      romptr = SISGETROMW(0x102);
+      romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
+   }
+
+   return romptr;
+}
+#endif
+
+/*********************************************/
+/*           Adjust Rate for CRT2            */
+/*********************************************/
+
+static bool
+SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RRTI, unsigned short *i)
+{
+   unsigned short checkmask=0, modeid, infoflag;
+
+   modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
+
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+
+	 checkmask |= SupportRAMDAC2;
+	 if(SiS_Pr->ChipType >= SIS_315H) {
+	    checkmask |= SupportRAMDAC2_135;
+	    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	       checkmask |= SupportRAMDAC2_162;
+	       if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
+		  checkmask |= SupportRAMDAC2_202;
+	       }
+	    }
+	 }
+
+      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+
+	 checkmask |= SupportLCD;
+	 if(SiS_Pr->ChipType >= SIS_315H) {
+	    if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	       if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	          if(modeid == 0x2e) checkmask |= Support64048060Hz;
+	       }
+	    }
+	 }
+
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+
+	 checkmask |= SupportHiVision;
+
+      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
+
+	 checkmask |= SupportTV;
+	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	    checkmask |= SupportTV1024;
+	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	          checkmask |= SupportYPbPr750p;
+	       }
+	    }
+	 }
+
+      }
+
+   } else {	/* LVDS */
+
+      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	    checkmask |= SupportCHTV;
+	 }
+      }
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	 checkmask |= SupportLCD;
+      }
+
+   }
+
+   /* Look backwards in table for matching CRT2 mode */
+   for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+      if(infoflag & checkmask) return true;
+      if((*i) == 0) break;
+   }
+
+   /* Look through the whole mode-section of the table from the beginning
+    * for a matching CRT2 mode if no mode was found yet.
+    */
+   for((*i) = 0; ; (*i)++) {
+      if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+      if(infoflag & checkmask) return true;
+   }
+   return false;
+}
+
+/*********************************************/
+/*              Get rate index               */
+/*********************************************/
+
+unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short RRTI,i,backup_i;
+   unsigned short modeflag,index,temp,backupindex;
+   static const unsigned short LCDRefreshIndex[] = {
+		0x00, 0x00, 0x01, 0x01,
+		0x01, 0x01, 0x01, 0x01,
+		0x01, 0x01, 0x01, 0x01,
+		0x01, 0x01, 0x01, 0x01,
+		0x00, 0x00, 0x00, 0x00
+   };
+
+   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
+   if(ModeNo == 0xfe) return 0;
+
+   if(ModeNo <= 0x13) {
+      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else {
+      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+
+   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	 if(modeflag & HalfDCLK) return 0;
+      }
+   }
+
+   if(ModeNo < 0x14) return 0xFFFF;
+
+   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
+   backupindex = index;
+
+   if(index > 0) index--;
+
+   if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	    if(SiS_Pr->SiS_VBType & VB_NoLCD)		 index = 0;
+	    else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
+	 }
+	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+	    if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
+	       temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
+	       if(index > temp) index = temp;
+	    }
+	 }
+      } else {
+	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
+	 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
+	 }
+      }
+   }
+
+   RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+   ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
+	 if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
+	     (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
+	    if(backupindex <= 1) RRTI++;
+	 }
+      }
+   }
+
+   i = 0;
+   do {
+      if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
+      temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
+      temp &= ModeTypeMask;
+      if(temp < SiS_Pr->SiS_ModeType) break;
+      i++;
+      index--;
+   } while(index != 0xFFFF);
+
+   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	 temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
+	 if(temp & InterlaceMode) i++;
+      }
+   }
+
+   i--;
+
+   if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
+      backup_i = i;
+      if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
+	 i = backup_i;
+      }
+   }
+
+   return (RRTI + i);
+}
+
+/*********************************************/
+/*            STORE CRT2 INFO in CR34        */
+/*********************************************/
+
+static void
+SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+   unsigned short temp1, temp2;
+
+   /* Store CRT1 ModeNo in CR34 */
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
+   temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
+   temp2 = ~(SetInSlaveMode >> 8);
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
+}
+
+/*********************************************/
+/*    HELPER: GET SOME DATA FROM BIOS ROM    */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_300
+static bool
+SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp,temp1;
+
+   if(SiS_Pr->SiS_UseROM) {
+      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+	 temp1 = SISGETROMW(0x23b);
+	 if(temp1 & temp) return true;
+      }
+   }
+   return false;
+}
+
+static bool
+SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp,temp1;
+
+   if(SiS_Pr->SiS_UseROM) {
+      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+	 temp1 = SISGETROMW(0x23d);
+	 if(temp1 & temp) return true;
+      }
+   }
+   return false;
+}
+#endif
+
+/*********************************************/
+/*          HELPER: DELAY FUNCTIONS          */
+/*********************************************/
+
+void
+SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
+{
+   while (delaytime-- > 0)
+      SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
+}
+
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+static void
+SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
+{
+   SiS_DDC2Delay(SiS_Pr, delay * 36);
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static void
+SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
+{
+   while(delay--) {
+      SiS_GenericDelay(SiS_Pr, 6623);
+   }
+}
+#endif
+
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+static void
+SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
+{
+   while(delay--) {
+      SiS_GenericDelay(SiS_Pr, 66);
+   }
+}
+#endif
+
+static void
+SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
+{
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short PanelID, DelayIndex, Delay=0;
+#endif
+
+   if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300
+
+      PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	 if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
+	 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
+      }
+      DelayIndex = PanelID >> 4;
+      if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
+	 Delay = 3;
+      } else {
+	 if(DelayTime >= 2) DelayTime -= 2;
+	 if(!(DelayTime & 0x01)) {
+	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+	 } else {
+	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+	 }
+	 if(SiS_Pr->SiS_UseROM) {
+	    if(ROMAddr[0x220] & 0x40) {
+	       if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
+	       else 	    	       Delay = (unsigned short)ROMAddr[0x226];
+	    }
+	 }
+      }
+      SiS_ShortDelay(SiS_Pr, Delay);
+
+#endif  /* CONFIG_FB_SIS_300 */
+
+   } else {
+
+#ifdef CONFIG_FB_SIS_315
+
+      if((SiS_Pr->ChipType >= SIS_661)    ||
+	 (SiS_Pr->ChipType <= SIS_315PRO) ||
+	 (SiS_Pr->ChipType == SIS_330)    ||
+	 (SiS_Pr->SiS_ROMNew)) {
+
+	 if(!(DelayTime & 0x01)) {
+	    SiS_DDC2Delay(SiS_Pr, 0x1000);
+	 } else {
+	    SiS_DDC2Delay(SiS_Pr, 0x4000);
+	 }
+
+      } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
+	 (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {			/* 315 series, LVDS; Special */
+
+	 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+	    PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+	    if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
+	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
+	    }
+	    if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+	       DelayIndex = PanelID & 0x0f;
+	    } else {
+	       DelayIndex = PanelID >> 4;
+	    }
+	    if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
+	       Delay = 3;
+	    } else {
+	       if(DelayTime >= 2) DelayTime -= 2;
+	       if(!(DelayTime & 0x01)) {
+		  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
+		} else {
+		  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
+	       }
+	       if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+		  if(ROMAddr[0x13c] & 0x40) {
+		     if(!(DelayTime & 0x01)) {
+			Delay = (unsigned short)ROMAddr[0x17e];
+		     } else {
+			Delay = (unsigned short)ROMAddr[0x17f];
+		     }
+		  }
+	       }
+	    }
+	    SiS_ShortDelay(SiS_Pr, Delay);
+	 }
+
+      } else if(SiS_Pr->SiS_VBType & VB_SISVB) {			/* 315 series, all bridges */
+
+	 DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
+	 if(!(DelayTime & 0x01)) {
+	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+	 } else {
+	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+	 }
+	 Delay <<= 8;
+	 SiS_DDC2Delay(SiS_Pr, Delay);
+
+      }
+
+#endif /* CONFIG_FB_SIS_315 */
+
+   }
+}
+
+#ifdef CONFIG_FB_SIS_315
+static void
+SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
+{
+   int i;
+   for(i = 0; i < DelayLoop; i++) {
+      SiS_PanelDelay(SiS_Pr, DelayTime);
+   }
+}
+#endif
+
+/*********************************************/
+/*    HELPER: WAIT-FOR-RETRACE FUNCTIONS     */
+/*********************************************/
+
+void
+SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
+{
+   unsigned short watchdog;
+
+   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
+   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
+
+   watchdog = 65535;
+   while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
+   watchdog = 65535;
+   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
+}
+
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+static void
+SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
+{
+   unsigned short watchdog;
+
+   watchdog = 65535;
+   while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
+   watchdog = 65535;
+   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
+}
+#endif
+
+static void
+SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
+      }
+      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
+	 SiS_WaitRetrace1(SiS_Pr);
+      } else {
+	 SiS_WaitRetrace2(SiS_Pr, 0x25);
+      }
+#endif
+   } else {
+#ifdef CONFIG_FB_SIS_315
+      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
+	 SiS_WaitRetrace1(SiS_Pr);
+      } else {
+	 SiS_WaitRetrace2(SiS_Pr, 0x30);
+      }
+#endif
+   }
+}
+
+static void
+SiS_VBWait(struct SiS_Private *SiS_Pr)
+{
+   unsigned short tempal,temp,i,j;
+
+   temp = 0;
+   for(i = 0; i < 3; i++) {
+     for(j = 0; j < 100; j++) {
+        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
+        if(temp & 0x01) {
+	   if((tempal & 0x08))  continue;
+	   else break;
+        } else {
+	   if(!(tempal & 0x08)) continue;
+	   else break;
+        }
+     }
+     temp ^= 0x01;
+   }
+}
+
+static void
+SiS_VBLongWait(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+      SiS_VBWait(SiS_Pr);
+   } else {
+      SiS_WaitRetrace1(SiS_Pr);
+   }
+}
+
+/*********************************************/
+/*               HELPER: MISC                */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_300
+static bool
+SiS_Is301B(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
+   return false;
+}
+#endif
+
+static bool
+SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType == SIS_730) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
+   }
+   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
+   return false;
+}
+
+bool
+SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
+{
+#ifdef CONFIG_FB_SIS_315
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
+      }
+   }
+#endif
+   return false;
+}
+
+bool
+SiS_IsVAMode(struct SiS_Private *SiS_Pr)
+{
+#ifdef CONFIG_FB_SIS_315
+   unsigned short flag;
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
+   }
+#endif
+   return false;
+}
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_IsVAMode(SiS_Pr))  return true;
+   if(SiS_CRT2IsLCD(SiS_Pr)) return true;
+   return false;
+}
+#endif
+
+static bool
+SiS_IsDualLink(struct SiS_Private *SiS_Pr)
+{
+#ifdef CONFIG_FB_SIS_315
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if((SiS_CRT2IsLCD(SiS_Pr)) ||
+         (SiS_IsVAMode(SiS_Pr))) {
+	 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
+      }
+   }
+#endif
+   return false;
+}
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_TVEnabled(struct SiS_Private *SiS_Pr)
+{
+   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
+   if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
+   }
+   return false;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
+   return false;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
+{
+   if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
+   }
+   return false;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag;
+
+   if(SiS_Pr->ChipType == SIS_650) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
+      /* Check for revision != A0 only */
+      if((flag == 0xe0) || (flag == 0xc0) ||
+         (flag == 0xb0) || (flag == 0x90)) return false;
+   } else if(SiS_Pr->ChipType >= SIS_661) return false;
+   return true;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      /* YPrPb = 0x08 */
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
+   }
+   return false;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_IsChScart(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      /* Scart = 0x04 */
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
+   }
+   return false;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag;
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToTV)        return true;
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+      if(flag & EnableCHYPbPr)      return true;  /* = YPrPb = 0x08 */
+      if(flag & EnableCHScart)      return true;  /* = Scart = 0x04 - TW */
+   } else {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToTV)        return true;
+   }
+   return false;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static bool
+SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag;
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToLCD) return true;
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+      if(flag & SetToLCDA)    return true;
+   } else {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToLCD) return true;
+   }
+   return false;
+}
+#endif
+
+static bool
+SiS_HaveBridge(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag;
+
+   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+      return true;
+   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+      if((flag == 1) || (flag == 2)) return true;
+   }
+   return false;
+}
+
+static bool
+SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag;
+
+   if(SiS_HaveBridge(SiS_Pr)) {
+      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+      if(SiS_Pr->ChipType < SIS_315H) {
+	flag &= 0xa0;
+	if((flag == 0x80) || (flag == 0x20)) return true;
+      } else {
+	flag &= 0x50;
+	if((flag == 0x40) || (flag == 0x10)) return true;
+      }
+   }
+   return false;
+}
+
+static bool
+SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag1;
+
+   flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
+   if(flag1 & (SetInSlaveMode >> 8)) return true;
+   return false;
+}
+
+/*********************************************/
+/*       GET VIDEO BRIDGE CONFIG INFO        */
+/*********************************************/
+
+/* Setup general purpose IO for Chrontel communication */
+#ifdef CONFIG_FB_SIS_300
+void
+SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
+{
+   unsigned int   acpibase;
+   unsigned short temp;
+
+   if(!(SiS_Pr->SiS_ChSW)) return;
+
+   acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
+   acpibase &= 0xFFFF;
+   if(!acpibase) return;
+   temp = SiS_GetRegShort((acpibase + 0x3c));	/* ACPI register 0x3c: GP Event 1 I/O mode select */
+   temp &= 0xFEFF;
+   SiS_SetRegShort((acpibase + 0x3c), temp);
+   temp = SiS_GetRegShort((acpibase + 0x3c));
+   temp = SiS_GetRegShort((acpibase + 0x3a));	/* ACPI register 0x3a: GP Pin Level (low/high) */
+   temp &= 0xFEFF;
+   if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
+   SiS_SetRegShort((acpibase + 0x3a), temp);
+   temp = SiS_GetRegShort((acpibase + 0x3a));
+}
+#endif
+
+void
+SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, int checkcrt2mode)
+{
+   unsigned short tempax, tempbx, temp;
+   unsigned short modeflag, resinfo = 0;
+
+   SiS_Pr->SiS_SetFlag = 0;
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
+
+   if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
+
+   tempbx = 0;
+
+   if(SiS_HaveBridge(SiS_Pr)) {
+
+	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+	tempbx |= temp;
+	tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
+	tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
+	tempbx |= tempax;
+
+#ifdef CONFIG_FB_SIS_315
+	if(SiS_Pr->ChipType >= SIS_315H) {
+	   if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
+	      if(ModeNo == 0x03) {
+		 /* Mode 0x03 is never in driver mode */
+		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
+	      }
+	      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
+		 /* Reset LCDA setting if not driver mode */
+		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
+	      }
+	      if(IS_SIS650) {
+		 if(SiS_Pr->SiS_UseLCDA) {
+		    if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
+		       if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
+			  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
+		       }
+		    }
+		 }
+	      }
+	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	      if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
+		 tempbx |= SetCRT2ToLCDA;
+	      }
+	   }
+
+	   if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
+	      tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
+	      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
+		 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+		 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+		 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+		    tempbx |= SetCRT2ToYPbPr525750;
+		 }
+	      }
+	   }
+
+	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	      if(temp & SetToLCDA) {
+		 tempbx |= SetCRT2ToLCDA;
+	      }
+	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+		 if(temp & EnableCHYPbPr) {
+		    tempbx |= SetCRT2ToCHYPbPr;
+		 }
+	      }
+	   }
+	}
+
+#endif  /* CONFIG_FB_SIS_315 */
+
+        if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
+	   tempbx &= ~(SetCRT2ToRAMDAC);
+	}
+
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   temp = SetCRT2ToSVIDEO   |
+		  SetCRT2ToAVIDEO   |
+		  SetCRT2ToSCART    |
+		  SetCRT2ToLCDA     |
+		  SetCRT2ToLCD      |
+		  SetCRT2ToRAMDAC   |
+		  SetCRT2ToHiVision |
+		  SetCRT2ToYPbPr525750;
+	} else {
+	   if(SiS_Pr->ChipType >= SIS_315H) {
+	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+		 temp = SetCRT2ToAVIDEO |
+		        SetCRT2ToSVIDEO |
+		        SetCRT2ToSCART  |
+		        SetCRT2ToLCDA   |
+		        SetCRT2ToLCD    |
+		        SetCRT2ToCHYPbPr;
+	      } else {
+		 temp = SetCRT2ToLCDA   |
+		        SetCRT2ToLCD;
+	      }
+	   } else {
+	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+		 temp = SetCRT2ToTV | SetCRT2ToLCD;
+	      } else {
+		 temp = SetCRT2ToLCD;
+	      }
+	   }
+	}
+
+	if(!(tempbx & temp)) {
+	   tempax = DisableCRT2Display;
+	   tempbx = 0;
+	}
+
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+	   unsigned short clearmask = ( DriverMode |
+				DisableCRT2Display |
+				LoadDACFlag 	   |
+				SetNotSimuMode 	   |
+				SetInSlaveMode 	   |
+				SetPALTV 	   |
+				SwitchCRT2	   |
+				SetSimuScanMode );
+
+	   if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
+	   if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
+	   if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
+	   if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
+	   if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
+	   if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
+
+	} else {
+
+	   if(SiS_Pr->ChipType >= SIS_315H) {
+	      if(tempbx & SetCRT2ToLCDA) {
+		 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
+	      }
+	   }
+	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	      if(tempbx & SetCRT2ToTV) {
+		 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
+	      }
+	   }
+	   if(tempbx & SetCRT2ToLCD) {
+	      tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
+	   }
+	   if(SiS_Pr->ChipType >= SIS_315H) {
+	      if(tempbx & SetCRT2ToLCDA) {
+	         tempbx |= SetCRT2ToLCD;
+	      }
+	   }
+
+	}
+
+	if(tempax & DisableCRT2Display) {
+	   if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
+	      tempbx = SetSimuScanMode | DisableCRT2Display;
+	   }
+	}
+
+	if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
+
+	/* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+	       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
+	      modeflag &= (~CRT2Mode);
+	   }
+	}
+
+	if(!(tempbx & SetSimuScanMode)) {
+	   if(tempbx & SwitchCRT2) {
+	      if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+		 if(resinfo != SIS_RI_1600x1200) {
+		    tempbx |= SetSimuScanMode;
+		 }
+              }
+	   } else {
+	      if(SiS_BridgeIsEnabled(SiS_Pr)) {
+		 if(!(tempbx & DriverMode)) {
+		    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+		       tempbx |= SetSimuScanMode;
+		    }
+		 }
+	      }
+	   }
+	}
+
+	if(!(tempbx & DisableCRT2Display)) {
+	   if(tempbx & DriverMode) {
+	      if(tempbx & SetSimuScanMode) {
+		 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+		    if(resinfo != SIS_RI_1600x1200) {
+		       tempbx |= SetInSlaveMode;
+		    }
+		 }
+	      }
+	   } else {
+	      tempbx |= SetInSlaveMode;
+	   }
+	}
+
+   }
+
+   SiS_Pr->SiS_VBInfo = tempbx;
+
+#ifdef CONFIG_FB_SIS_300
+   if(SiS_Pr->ChipType == SIS_630) {
+      SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
+   }
+#endif
+
+#if 0
+   printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
+      SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
+#endif
+}
+
+/*********************************************/
+/*           DETERMINE YPbPr MODE            */
+/*********************************************/
+
+void
+SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
+{
+
+   unsigned char temp;
+
+   /* Note: This variable is only used on 30xLV systems.
+    * CR38 has a different meaning on LVDS/CH7019 systems.
+    * On 661 and later, these bits moved to CR35.
+    *
+    * On 301, 301B, only HiVision 1080i is supported.
+    * On 30xLV, 301C, only YPbPr 1080i is supported.
+    */
+
+   SiS_Pr->SiS_YPbPr = 0;
+   if(SiS_Pr->ChipType >= SIS_661) return;
+
+   if(SiS_Pr->SiS_VBType) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	 SiS_Pr->SiS_YPbPr = YPbPrHiVision;
+      }
+   }
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+	 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	 if(temp & 0x08) {
+	    switch((temp >> 4)) {
+	    case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
+	    case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
+	    case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
+	    case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
+	    }
+	 }
+      }
+   }
+
+}
+
+/*********************************************/
+/*           DETERMINE TVMode flag           */
+/*********************************************/
+
+void
+SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp, temp1, resinfo = 0, romindex = 0;
+   unsigned char  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
+
+   SiS_Pr->SiS_TVMode = 0;
+
+   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
+   if(SiS_Pr->UseCustomMode) return;
+
+   if(ModeNo > 0x13) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
+
+   if(SiS_Pr->ChipType < SIS_661) {
+
+      if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
+
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	 temp = 0;
+	 if((SiS_Pr->ChipType == SIS_630) ||
+	    (SiS_Pr->ChipType == SIS_730)) {
+	    temp = 0x35;
+	    romindex = 0xfe;
+	 } else if(SiS_Pr->ChipType >= SIS_315H) {
+	    temp = 0x38;
+	    if(SiS_Pr->ChipType < XGI_20) {
+	       romindex = 0xf3;
+	       if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
+	    }
+	 }
+	 if(temp) {
+	    if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
+	       OutputSelect = ROMAddr[romindex];
+	       if(!(OutputSelect & EnablePALMN)) {
+		  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
+	       }
+	    }
+	    temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
+	    if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	       if(temp1 & EnablePALM) {		/* 0x40 */
+		  SiS_Pr->SiS_TVMode |= TVSetPALM;
+		  SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+	       } else if(temp1 & EnablePALN) {	/* 0x80 */
+		  SiS_Pr->SiS_TVMode |= TVSetPALN;
+	       }
+	    } else {
+	       if(temp1 & EnableNTSCJ) {	/* 0x40 */
+		  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+	       }
+	    }
+	 }
+	 /* Translate HiVision/YPbPr to our new flags */
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	    if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+	    else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+	    else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
+	    else				        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+	    if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
+	       SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
+	       SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
+	    } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+	       SiS_Pr->SiS_TVMode |= TVSetPAL;
+	    }
+	 }
+      } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	 if(SiS_Pr->SiS_CHOverScan) {
+	    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+	       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+	       if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
+		  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+	       }
+	    } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
+	       if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
+		  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+	       }
+	    }
+	    if(SiS_Pr->SiS_CHSOverScan) {
+	       SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+	    }
+	 }
+	 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	    if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	       if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
+	       else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
+	    } else {
+	       if(temp & EnableNTSCJ) {
+		  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+	       }
+	    }
+	 }
+      }
+
+   } else {  /* 661 and later */
+
+      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+      if(temp1 & 0x01) {
+	 SiS_Pr->SiS_TVMode |= TVSetPAL;
+	 if(temp1 & 0x08) {
+	    SiS_Pr->SiS_TVMode |= TVSetPALN;
+	 } else if(temp1 & 0x04) {
+	    if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	       SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+	    }
+	    SiS_Pr->SiS_TVMode |= TVSetPALM;
+	 }
+      } else {
+	 if(temp1 & 0x02) {
+	    SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+	 }
+      }
+      if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	 if(SiS_Pr->SiS_CHOverScan) {
+	    if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
+	       SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+	    }
+	 }
+      }
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	    temp1 &= 0xe0;
+	    if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+	    else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+	    else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	    SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
+	 }
+	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
+	    if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
+	       SiS_Pr->SiS_TVMode |= TVAspect169;
+	    } else {
+	       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
+	       if(temp1 & 0x02) {
+		  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
+		     SiS_Pr->SiS_TVMode |= TVAspect169;
+		  } else {
+		     SiS_Pr->SiS_TVMode |= TVAspect43LB;
+		  }
+	       } else {
+		  SiS_Pr->SiS_TVMode |= TVAspect43;
+	       }
+	    }
+	 }
+      }
+   }
+
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
+
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	 SiS_Pr->SiS_TVMode |= TVSetPAL;
+	 SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
+	    SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
+	 }
+      }
+
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+	    SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+	 }
+      }
+
+      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+	 if(resinfo == SIS_RI_1024x768) {
+	    if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+	       SiS_Pr->SiS_TVMode |= TVSet525p1024;
+	    } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
+	       SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
+	    }
+	 }
+      }
+
+      SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
+	 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+	 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+      } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+	 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+      } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
+	 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+	    SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+	 }
+      }
+
+   }
+
+   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
+}
+
+/*********************************************/
+/*               GET LCD INFO                */
+/*********************************************/
+
+static unsigned short
+SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
+{
+   unsigned short temp = SiS_Pr->SiS_LCDResInfo;
+   /* Translate my LCDResInfo to BIOS value */
+   switch(temp) {
+   case Panel_1280x768_2: temp = Panel_1280x768;    break;
+   case Panel_1280x800_2: temp = Panel_1280x800;    break;
+   case Panel_1280x854:   temp = Panel661_1280x854; break;
+   }
+   return temp;
+}
+
+static void
+SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
+{
+#ifdef CONFIG_FB_SIS_315
+   unsigned char  *ROMAddr;
+   unsigned short temp;
+
+   if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
+      if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
+	 SiS_Pr->SiS_NeedRomModeData = true;
+	 SiS_Pr->PanelHT  = temp;
+      }
+      if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
+	 SiS_Pr->SiS_NeedRomModeData = true;
+	 SiS_Pr->PanelVT  = temp;
+      }
+      SiS_Pr->PanelHRS = SISGETROMW(10);
+      SiS_Pr->PanelHRE = SISGETROMW(12);
+      SiS_Pr->PanelVRS = SISGETROMW(14);
+      SiS_Pr->PanelVRE = SISGETROMW(16);
+      SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+
+   }
+#endif
+}
+
+static void
+SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
+			const unsigned char *nonscalingmodes)
+{
+   int i = 0;
+   while(nonscalingmodes[i] != 0xff) {
+      if(nonscalingmodes[i++] == resinfo) {
+	 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
+	    (SiS_Pr->UsePanelScaler == -1)) {
+	    SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	 }
+	 break;
+      }
+   }
+}
+
+void
+SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
+  bool panelcanscale = false;
+#ifdef CONFIG_FB_SIS_300
+  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+  static const unsigned char SiS300SeriesLCDRes[] =
+          { 0,  1,  2,  3,  7,  4,  5,  8,
+	    0,  0, 10,  0,  0,  0,  0, 15 };
+#endif
+#ifdef CONFIG_FB_SIS_315
+  unsigned char   *myptr = NULL;
+#endif
+
+  SiS_Pr->SiS_LCDResInfo  = 0;
+  SiS_Pr->SiS_LCDTypeInfo = 0;
+  SiS_Pr->SiS_LCDInfo     = 0;
+  SiS_Pr->PanelHRS        = 999; /* HSync start */
+  SiS_Pr->PanelHRE        = 999; /* HSync end */
+  SiS_Pr->PanelVRS        = 999; /* VSync start */
+  SiS_Pr->PanelVRE        = 999; /* VSync end */
+  SiS_Pr->SiS_NeedRomModeData = false;
+
+  /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
+  SiS_Pr->Alternate1600x1200 = false;
+
+  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
+
+  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+  if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
+     modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
+  }
+
+  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+
+  /* For broken BIOSes: Assume 1024x768 */
+  if(temp == 0) temp = 0x02;
+
+  if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+     SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
+  } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
+     SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
+  } else {
+     SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
+  }
+  temp &= 0x0f;
+#ifdef CONFIG_FB_SIS_300
+  if(SiS_Pr->ChipType < SIS_315H) {
+     /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
+     if(SiS_Pr->SiS_VBType & VB_SIS301) {
+        if(temp < 0x0f) temp &= 0x07;
+     }
+     /* Translate 300 series LCDRes to 315 series for unified usage */
+     temp = SiS300SeriesLCDRes[temp];
+  }
+#endif
+
+  /* Translate to our internal types */
+#ifdef CONFIG_FB_SIS_315
+  if(SiS_Pr->ChipType == SIS_550) {
+     if     (temp == Panel310_1152x768)  temp = Panel_320x240_2; /* Verified working */
+     else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
+     else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
+  } else if(SiS_Pr->ChipType >= SIS_661) {
+     if(temp == Panel661_1280x854)       temp = Panel_1280x854;
+  }
+#endif
+
+  if(SiS_Pr->SiS_VBType & VB_SISLVDS) {		/* SiS LVDS */
+     if(temp == Panel310_1280x768) {
+        temp = Panel_1280x768_2;
+     }
+     if(SiS_Pr->SiS_ROMNew) {
+	if(temp == Panel661_1280x800) {
+	   temp = Panel_1280x800_2;
+	}
+     }
+  }
+
+  SiS_Pr->SiS_LCDResInfo = temp;
+
+#ifdef CONFIG_FB_SIS_300
+  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+     if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+	SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
+     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
+	SiS_Pr->SiS_LCDResInfo = Panel_848x480;
+     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+	SiS_Pr->SiS_LCDResInfo = Panel_856x480;
+     }
+  }
+#endif
+
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+  }
+
+  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+  SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
+  /* Need temp below! */
+
+  /* These must/can't scale no matter what */
+  switch(SiS_Pr->SiS_LCDResInfo) {
+  case Panel_320x240_1:
+  case Panel_320x240_2:
+  case Panel_320x240_3:
+  case Panel_1280x960:
+      SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+      break;
+  case Panel_640x480:
+      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+  }
+
+  panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
+
+  if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+
+  /* Dual link, Pass 1:1 BIOS default, etc. */
+#ifdef CONFIG_FB_SIS_315
+  if(SiS_Pr->ChipType >= SIS_661) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+     }
+     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+	if(SiS_Pr->SiS_ROMNew) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	} else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
+	   if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
+     }
+  } else if(SiS_Pr->ChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+     }
+     if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
+	SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
+	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+	if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
+	if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
+     } else if(!(SiS_Pr->SiS_ROMNew)) {
+	if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+	   if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+	   if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+	}
+     }
+  }
+#endif
+
+  /* Pass 1:1 */
+  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
+     /* Always center screen on LVDS (if scaling is disabled) */
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	/* Always center screen on SiS LVDS (if scaling is disabled) */
+	SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     } else {
+	/* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
+	if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
+	if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     }
+  }
+
+  SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+  SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+
+  switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_320x240_1:
+     case Panel_320x240_2:
+     case Panel_320x240_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+			    SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+						      SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
+     			    SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
+			    SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK40;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK40;
+			    break;
+     case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
+			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+			    break;
+     case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(SiS_Pr->ChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+						      SiS_Pr->PanelVRE  =    5;
+			    }
+			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
+			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(SiS_Pr->ChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+						      SiS_Pr->PanelVRE  =    5;
+			    }
+			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+			    break;
+     case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
+			    break;
+     case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
+			    SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
+			    SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
+			    SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
+			    /* Data above for TMDS (projector); get from BIOS for LVDS */
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+			    if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+			       SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
+			       SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
+			       SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
+			    } else {
+			       SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
+			       SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
+			       SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			       SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
+			       SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
+			    }
+			    break;
+     case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+			    SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
+			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
+			    SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
+			    SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
+			    SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
+			    SiS_Pr->PanelHRS   =  48; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1280x854:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  854;
+			    SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  861;
+			    SiS_Pr->PanelHRS   =  16; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS   =   1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
+			    SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
+			    if(resinfo == SIS_RI_1280x1024) {
+			       SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
+			       SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
+			    }
+			    break;
+     case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
+			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
+			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
+			    SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
+			    SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
+			    if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
+			       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+				  SiS_Pr->PanelHT  = 1760; SiS_Pr->PanelVT  = 1235;
+				  SiS_Pr->PanelHRS =   48; SiS_Pr->PanelHRE =   32;
+				  SiS_Pr->PanelVRS =    2; SiS_Pr->PanelVRE =    4;
+				  SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
+				  SiS_Pr->Alternate1600x1200 = true;
+			       }
+			    } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
+			       SiS_Pr->PanelHT  = 2048; SiS_Pr->PanelVT  = 1320;
+			       SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
+			       SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
+			    }
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
+			    SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr);
+			    break;
+     case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
+			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    break;
+     case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
+			    SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
+			    break;
+     case Panel_856x480:    SiS_Pr->PanelXRes =  856; SiS_Pr->PanelYRes =  480;
+			    SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
+			    break;
+     case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
+			    SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
+			    SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
+			    SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
+			    if(SiS_Pr->CP_PreferredIndex != -1) {
+			       SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
+			       SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
+			       SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
+			       SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
+			       if(SiS_Pr->CP_PrefClock) {
+				  int idx;
+				  SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
+				  SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
+				  if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
+				  else				   idx = VCLK_CUSTOM_315;
+				  SiS_Pr->SiS_VCLKData[idx].CLOCK =
+				     SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
+				  SiS_Pr->SiS_VCLKData[idx].SR2B =
+				     SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
+				  SiS_Pr->SiS_VCLKData[idx].SR2C =
+				     SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
+			       }
+			    }
+			    break;
+     default:		    SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    break;
+  }
+
+  /* Special cases */
+  if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
+      (SiS_Pr->SiS_IF_DEF_DSTN)              ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
+     SiS_Pr->PanelHRS = 999;
+     SiS_Pr->PanelHRE = 999;
+  }
+
+  if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
+     SiS_Pr->PanelVRS = 999;
+     SiS_Pr->PanelVRE = 999;
+  }
+
+  /* DontExpand overrule */
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+
+     if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
+	/* No scaling for this mode on any panel (LCD=CRT2)*/
+	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+     }
+
+     switch(SiS_Pr->SiS_LCDResInfo) {
+
+     case Panel_Custom:
+     case Panel_1152x864:
+     case Panel_1280x768:	/* TMDS only */
+	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	break;
+
+     case Panel_800x600: {
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	break;
+     }
+     case Panel_1024x768: {
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	break;
+     }
+     case Panel_1280x720: {
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	if(SiS_Pr->PanelHT == 1650) {
+	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	}
+	break;
+     }
+     case Panel_1280x768_2: {  /* LVDS only */
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   SIS_RI_1152x768,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	switch(resinfo) {
+	case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
+				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+			       }
+			       break;
+	}
+	break;
+     }
+     case Panel_1280x800: {  	/* SiS TMDS special (Averatec 6200 series) */
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	break;
+     }
+     case Panel_1280x800_2:  { 	/* SiS LVDS */
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   SIS_RI_1152x768,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	switch(resinfo) {
+	case SIS_RI_1280x720:
+	case SIS_RI_1280x768:  if(SiS_Pr->UsePanelScaler == -1) {
+				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+			       }
+			       break;
+	}
+	break;
+     }
+     case Panel_1280x854: {  	/* SiS LVDS */
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   SIS_RI_1152x768,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	switch(resinfo) {
+	case SIS_RI_1280x720:
+	case SIS_RI_1280x768:
+	case SIS_RI_1280x800:  if(SiS_Pr->UsePanelScaler == -1) {
+				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+			       }
+			       break;
+	}
+	break;
+     }
+     case Panel_1280x960: {
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
+	   SIS_RI_1280x854,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	break;
+     }
+     case Panel_1280x1024: {
+	static const unsigned char nonscalingmodes[] = {
+	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	   SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
+	   SIS_RI_1280x854,SIS_RI_1280x960,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	break;
+     }
+     case Panel_1400x1050: {
+	static const unsigned char nonscalingmodes[] = {
+	     SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	     SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	     SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
+	     SIS_RI_1280x960,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	switch(resinfo) {
+	case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
+				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+			       }
+			       break;
+	case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+			       break;
+	}
+	break;
+     }
+     case Panel_1600x1200: {
+	static const unsigned char nonscalingmodes[] = {
+	     SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	     SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	     SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
+	     SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	break;
+     }
+     case Panel_1680x1050: {
+	static const unsigned char nonscalingmodes[] = {
+	     SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+	     SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+	     SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
+	     SIS_RI_1360x1024,0xff
+	};
+	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+	break;
+     }
+     }
+  }
+
+#ifdef CONFIG_FB_SIS_300
+  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+     if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+	SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
+     }
+  }
+
+  if(SiS_Pr->ChipType < SIS_315H) {
+     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	if(SiS_Pr->SiS_UseROM) {
+	   if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+	      if(!(ROMAddr[0x235] & 0x02)) {
+		 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+	      }
+	   }
+	}
+     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
+	   SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+	}
+     }
+  }
+#endif
+
+  /* Special cases */
+
+  if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+  }
+
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+  }
+
+  switch(SiS_Pr->SiS_LCDResInfo) {
+  case Panel_640x480:
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+     break;
+  case Panel_1280x800:
+     /* Don't pass 1:1 by default (TMDS special) */
+     if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     break;
+  case Panel_1280x960:
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     break;
+  case Panel_Custom:
+     if((!SiS_Pr->CP_PrefClock) ||
+        (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
+        SiS_Pr->SiS_LCDInfo |= LCDPass11;
+     }
+     break;
+  }
+
+  if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+  }
+
+  /* (In)validate LCDPass11 flag */
+  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+  }
+
+  /* LVDS DDA */
+  if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
+
+     if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
+	if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+	   if(ModeNo == 0x12) {
+	      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+		 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	      }
+	   } else if(ModeNo > 0x13) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+		 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+		    if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+		       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+		    }
+		 }
+	      }
+	   }
+	}
+     }
+
+     if(modeflag & HalfDCLK) {
+	if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(ModeNo > 0x13) {
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	      if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	   } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
+	      if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	   }
+	}
+     }
+
+  }
+
+  /* VESA timing */
+  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+     if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
+	SiS_Pr->SiS_SetFlag |= LCDVESATiming;
+     }
+  } else {
+     SiS_Pr->SiS_SetFlag |= LCDVESATiming;
+  }
+
+#if 0
+  printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
+	SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
+#endif
+}
+
+/*********************************************/
+/*                 GET VCLK                  */
+/*********************************************/
+
+unsigned short
+SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex)
+{
+  unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
+  unsigned short modeflag, resinfo, tempbx;
+  const unsigned char *CHTVVCLKPtr = NULL;
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+     CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
+     VCLKIndexGENCRT = VCLKIndexGEN;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+     VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
+		(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
+  }
+
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
+
+     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+
+	CRT2Index >>= 6;
+	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      	/*  LCD */
+
+	   if(SiS_Pr->ChipType < SIS_315H) {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
+	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+		 VCLKIndex = VCLKIndexGEN;
+	      }
+	   } else {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
+	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+		 switch(resinfo) {
+		 /* Correct those whose IndexGEN doesn't match VBVCLK array */
+		 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
+		 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
+		 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
+		 case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
+		 case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
+		 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
+		 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
+		 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
+		 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
+		 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
+		 default:              VCLKIndex = VCLKIndexGEN;
+		 }
+
+		 if(ModeNo <= 0x13) {
+		    if(SiS_Pr->ChipType <= SIS_315PRO) {
+		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
+		    } else {
+		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
+		    }
+		 }
+		 if(SiS_Pr->ChipType <= SIS_315PRO) {
+		    if(VCLKIndex == 0) VCLKIndex = 0x41;
+		    if(VCLKIndex == 1) VCLKIndex = 0x43;
+		    if(VCLKIndex == 4) VCLKIndex = 0x44;
+		 }
+	      }
+	   }
+
+	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 	/*  TV */
+
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	      if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) 	   VCLKIndex = HiTVVCLKDIV2;
+	      else                                  	   VCLKIndex = HiTVVCLK;
+	      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     VCLKIndex = HiTVSimuVCLK;
+	   } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  VCLKIndex = YPbPr750pVCLK;
+	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)    VCLKIndex = TVVCLKDIV2;
+	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)      VCLKIndex = TVVCLKDIV2;
+	   else						   VCLKIndex = TVVCLK;
+
+	   if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
+	   else				   VCLKIndex += TVCLKBASE_315;
+
+	} else {							/* VGA2 */
+
+	   VCLKIndex = VCLKIndexGENCRT;
+	   if(SiS_Pr->ChipType < SIS_315H) {
+	      if(ModeNo > 0x13) {
+		 if( (SiS_Pr->ChipType == SIS_630) &&
+		     (SiS_Pr->ChipRevision >= 0x30)) {
+		    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
+		 }
+		 /* Better VGA2 clock for 1280x1024@75 */
+		 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
+	      }
+	   }
+	}
+
+     } else {   /* If not programming CRT2 */
+
+	VCLKIndex = VCLKIndexGENCRT;
+	if(SiS_Pr->ChipType < SIS_315H) {
+	   if(ModeNo > 0x13) {
+	      if( (SiS_Pr->ChipType != SIS_630) &&
+		  (SiS_Pr->ChipType != SIS_300) ) {
+		 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
+	      }
+	   }
+	}
+     }
+
+  } else {       /*   LVDS  */
+
+     VCLKIndex = CRT2Index;
+
+     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+
+	if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
+
+	   VCLKIndex &= 0x1f;
+	   tempbx = 0;
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	      tempbx += 2;
+	      if(SiS_Pr->SiS_ModeType > ModeVGA) {
+		 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
+	      }
+	      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+		 tempbx = 4;
+		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+		 tempbx = 6;
+		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	      }
+	   }
+	   switch(tempbx) {
+	     case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
+	     case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
+	     case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
+	     case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
+	     case  4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM;  break;
+	     case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
+	     case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
+	     case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
+	     case  8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL;  break;
+	     default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
+	   }
+	   VCLKIndex = CHTVVCLKPtr[VCLKIndex];
+
+	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+	   if(SiS_Pr->ChipType < SIS_315H) {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
+	   } else {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
+	   }
+
+#ifdef CONFIG_FB_SIS_300
+	   /* Special Timing: Barco iQ Pro R series */
+	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
+
+	   /* Special Timing: 848x480 and 856x480 parallel lvds panels */
+	   if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+	      if(SiS_Pr->ChipType < SIS_315H) {
+		 VCLKIndex = VCLK34_300;
+		 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
+	      } else {
+		 VCLKIndex = VCLK34_315;
+		 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
+	      }
+	   }
+#endif
+
+	} else {
+
+	   VCLKIndex = VCLKIndexGENCRT;
+	   if(SiS_Pr->ChipType < SIS_315H) {
+	      if(ModeNo > 0x13) {
+		 if( (SiS_Pr->ChipType == SIS_630) &&
+		     (SiS_Pr->ChipRevision >= 0x30) ) {
+		    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
+		 }
+	      }
+	   }
+	}
+
+     } else {  /* if not programming CRT2 */
+
+	VCLKIndex = VCLKIndexGENCRT;
+	if(SiS_Pr->ChipType < SIS_315H) {
+	   if(ModeNo > 0x13) {
+	      if( (SiS_Pr->ChipType != SIS_630) &&
+		  (SiS_Pr->ChipType != SIS_300) ) {
+		 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
+	      }
+#if 0
+	      if(SiS_Pr->ChipType == SIS_730) {
+		 if(VCLKIndex == 0x0b) VCLKIndex = 0x40;   /* 1024x768-70 */
+		 if(VCLKIndex == 0x0d) VCLKIndex = 0x41;   /* 1024x768-75 */
+	      }
+#endif
+	   }
+        }
+
+     }
+
+  }
+
+  return VCLKIndex;
+}
+
+/*********************************************/
+/*        SET CRT2 MODE TYPE REGISTERS       */
+/*********************************************/
+
+static void
+SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned short i, j, modeflag, tempah=0;
+  short tempcl;
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+  unsigned short tempbl;
+#endif
+#ifdef CONFIG_FB_SIS_315
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short tempah2, tempbl2;
+#endif
+
+  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
+
+  } else {
+
+     for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
+     if(SiS_Pr->ChipType >= SIS_315H) {
+        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
+     }
+
+     tempcl = SiS_Pr->SiS_ModeType;
+
+     if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300    /* ---- 300 series ---- */
+
+	/* For 301BDH: (with LCD via LVDS) */
+	if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	   tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
+	   tempbl &= 0xef;
+	   tempbl |= 0x02;
+	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	      tempbl |= 0x10;
+	      tempbl &= 0xfd;
+	   }
+	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
+	}
+
+	if(ModeNo > 0x13) {
+	   tempcl -= ModeVGA;
+	   if(tempcl >= 0) {
+	      tempah = ((0x10 >> tempcl) | 0x80);
+	   }
+	} else tempah = 0x80;
+
+	if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
+
+#endif  /* CONFIG_FB_SIS_300 */
+
+     } else {
+
+#ifdef CONFIG_FB_SIS_315    /* ------- 315/330 series ------ */
+
+	if(ModeNo > 0x13) {
+	   tempcl -= ModeVGA;
+	   if(tempcl >= 0) {
+	      tempah = (0x08 >> tempcl);
+	      if (tempah == 0) tempah = 1;
+	      tempah |= 0x40;
+	   }
+	} else tempah = 0x40;
+
+	if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
+
+#endif  /* CONFIG_FB_SIS_315 */
+
+     }
+
+     if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
+
+     if(SiS_Pr->ChipType < SIS_315H) {
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
+     } else {
+#ifdef CONFIG_FB_SIS_315
+	if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+	} else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   if(IS_SIS740) {
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
+	   } else {
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+	   }
+	}
+#endif
+     }
+
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+	tempah = 0x01;
+	if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+	   tempah |= 0x02;
+	}
+	if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	   tempah ^= 0x05;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+	      tempah ^= 0x01;
+	   }
+	}
+
+	if(SiS_Pr->ChipType < SIS_315H) {
+
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
+
+	   tempah = (tempah << 5) & 0xFF;
+	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
+	   tempah = (tempah >> 5) & 0xFF;
+
+	} else {
+
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0x08;
+	   else if(!(SiS_IsDualEdge(SiS_Pr)))           tempah |= 0x08;
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
+	   tempah &= ~0x08;
+
+	}
+
+	if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+	   tempah |= 0x10;
+	}
+
+	tempah |= 0x80;
+	if(SiS_Pr->SiS_VBType & VB_SIS301) {
+	   if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
+	}
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	   if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
+	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+		 tempah |= 0x20;
+	      }
+	   }
+	}
+
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
+
+	tempah = 0x80;
+	if(SiS_Pr->SiS_VBType & VB_SIS301) {
+	   if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
+	}
+
+	if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	   if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
+	      tempah |= 0x40;
+	   }
+	}
+
+	SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
+
+     } else {  /* LVDS */
+
+	if(SiS_Pr->ChipType >= SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_315
+	   /* LVDS can only be slave in 8bpp modes */
+	   tempah = 0x80;
+	   if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
+	      if(SiS_Pr->SiS_VBInfo & DriverMode) {
+	         tempah |= 0x02;
+	      }
+	   }
+
+	   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  tempah |= 0x02;
+
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)        tempah ^= 0x01;
+
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
+
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
+#endif
+
+	} else {
+
+#ifdef CONFIG_FB_SIS_300
+	   tempah = 0;
+	   if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
+	      tempah |= 0x02;
+	   }
+	   tempah <<= 5;
+
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
+
+	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
+#endif
+
+	}
+
+     }
+
+  }  /* LCDA */
+
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+     if(SiS_Pr->ChipType >= SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_315
+	/* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
+
+	/* The following is nearly unpreditable and varies from machine
+	 * to machine. Especially the 301DH seems to be a real trouble
+	 * maker. Some BIOSes simply set the registers (like in the
+	 * NoLCD-if-statements here), some set them according to the
+	 * LCDA stuff. It is very likely that some machines are not
+	 * treated correctly in the following, very case-orientated
+	 * code. What do I do then...?
+	 */
+
+	/* 740 variants match for 30xB, 301B-DH, 30xLV */
+
+	if(!(IS_SIS740)) {
+	   tempah = 0x04;						   /* For all bridges */
+	   tempbl = 0xfb;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	      tempah = 0x00;
+	      if(SiS_IsDualEdge(SiS_Pr)) {
+	         tempbl = 0xff;
+	      }
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
+	}
+
+	/* The following two are responsible for eventually wrong colors
+	 * in TV output. The DH (VB_NoLCD) conditions are unknown; the
+	 * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
+	 * in a 650 box (Jake). What is the criteria?
+	 * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
+	 * treatment like the 651+301B-DH(b0) case. Seems more to be the
+	 * chipset than the bridge revision.
+	 */
+
+	if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+	   tempah = 0x30;
+	   tempbl = 0xc0;
+	   if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+	      ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
+	      tempah = 0x00;
+	      tempbl = 0x00;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
+	} else if(SiS_Pr->SiS_VBType & VB_SIS301) {
+	   /* Fixes "TV-blue-bug" on 315+301 */
+	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);	/* For 301   */
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
+	} else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);	/* For 30xLV */
+	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
+	} else if(SiS_Pr->SiS_VBType & VB_NoLCD) {		/* For 301B-DH */
+	   tempah = 0x30; tempah2 = 0xc0;
+	   tempbl = 0xcf; tempbl2 = 0x3f;
+	   if(SiS_Pr->SiS_TVBlue == 0) {
+	         tempah = tempah2 = 0x00;
+	   } else if(SiS_Pr->SiS_TVBlue == -1) {
+	      /* Set on 651/M650, clear on 315/650 */
+	      if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
+	         tempah = tempah2 = 0x00;
+	      }
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
+	} else {
+	   tempah = 0x30; tempah2 = 0xc0;		       /* For 30xB, 301C */
+	   tempbl = 0xcf; tempbl2 = 0x3f;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	      tempah = tempah2 = 0x00;
+	      if(SiS_IsDualEdge(SiS_Pr)) {
+		 tempbl = tempbl2 = 0xff;
+	      }
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
+	}
+
+	if(IS_SIS740) {
+	   tempah = 0x80;
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
+	} else {
+	   tempah = 0x00;
+	   tempbl = 0x7f;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	      tempbl = 0xff;
+	      if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
+	}
+
+#endif /* CONFIG_FB_SIS_315 */
+
+     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+
+#ifdef CONFIG_FB_SIS_300
+	SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
+
+	if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+	   ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+	    (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
+	} else {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
+	}
+#endif
+
+     }
+
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
+	if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
+        }
+     }
+
+  } else {  /* LVDS */
+
+#ifdef CONFIG_FB_SIS_315
+     if(SiS_Pr->ChipType >= SIS_315H) {
+
+	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+
+	   tempah = 0x04;
+	   tempbl = 0xfb;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	      tempah = 0x00;
+	      if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
+
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
+	   }
+
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
+
+	} else if(SiS_Pr->ChipType == SIS_550) {
+
+	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
+
+	}
+
+     }
+#endif
+
+  }
+
+}
+
+/*********************************************/
+/*            GET RESOLUTION DATA            */
+/*********************************************/
+
+unsigned short
+SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   if(ModeNo <= 0x13)
+      return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
+   else
+      return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
+}
+
+static void
+SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short xres, yres, modeflag=0, resindex;
+
+   if(SiS_Pr->UseCustomMode) {
+      xres = SiS_Pr->CHDisplay;
+      if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
+      SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+      /* DoubleScanMode-check done in CheckCalcCustomMode()! */
+      SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
+      return;
+   }
+
+   resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
+
+   if(ModeNo <= 0x13) {
+      xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
+      yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
+   } else {
+      xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+      yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
+      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+
+   if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
+
+      if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
+	 if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+	    if(yres == 350) yres = 400;
+	 }
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
+	    if(ModeNo == 0x12) yres = 400;
+	 }
+      }
+
+      if(modeflag & HalfDCLK)       xres <<= 1;
+      if(modeflag & DoubleScanMode) yres <<= 1;
+
+   }
+
+   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	 switch(SiS_Pr->SiS_LCDResInfo) {
+	   case Panel_1024x768:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+		 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+		    if(yres == 350) yres = 357;
+		    if(yres == 400) yres = 420;
+		    if(yres == 480) yres = 525;
+		 }
+	      }
+	      break;
+	   case Panel_1280x1024:
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+		 /* BIOS bug - does this regardless of scaling */
+		 if(yres == 400) yres = 405;
+	      }
+	      if(yres == 350) yres = 360;
+	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+		 if(yres == 360) yres = 375;
+	      }
+	      break;
+	   case Panel_1600x1200:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+		 if(yres == 1024) yres = 1056;
+	      }
+	      break;
+	 }
+      }
+
+   } else {
+
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
+	    if(xres == 720) xres = 640;
+	 }
+      } else if(xres == 720) xres = 640;
+
+      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+	 yres = 400;
+	 if(SiS_Pr->ChipType >= SIS_315H) {
+	    if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+	 } else {
+	    if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+	 }
+	 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
+      }
+
+   }
+   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
+}
+
+/*********************************************/
+/*           GET CRT2 TIMING DATA            */
+/*********************************************/
+
+static void
+SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+	       unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
+	       unsigned short *ResIndex)
+{
+  unsigned short tempbx=0, tempal=0, resinfo=0;
+
+  if(ModeNo <= 0x13) {
+     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else {
+     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+  }
+
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
+
+	tempbx = SiS_Pr->SiS_LCDResInfo;
+	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
+
+	/* patch index */
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
+	   if     (resinfo == SIS_RI_1280x800)  tempal =  9;
+	   else if(resinfo == SIS_RI_1400x1050) tempal = 11;
+	} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
+		  (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
+		  (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
+	   if     (resinfo == SIS_RI_1280x768)  tempal =  9;
+	}
+
+	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	   /* Pass 1:1 only (center-screen handled outside) */
+	   /* This is never called for the panel's native resolution */
+	   /* since Pass1:1 will not be set in this case */
+	   tempbx = 100;
+	   if(ModeNo >= 0x13) {
+	      tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+	   }
+	}
+
+#ifdef CONFIG_FB_SIS_315
+	if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+		 tempbx = 200;
+		 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+	      }
+	   }
+	}
+#endif
+
+     } else {						  	/* TV */
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	   /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
+	   tempbx = 2;
+	   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	      tempbx = 13;
+	      if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
+	   }
+	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	   if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)	tempbx = 7;
+	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)	tempbx = 6;
+	   else						tempbx = 5;
+	   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)	tempbx += 5;
+	} else {
+	   if(SiS_Pr->SiS_TVMode & TVSetPAL)		tempbx = 3;
+	   else						tempbx = 4;
+	   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)	tempbx += 5;
+	}
+
+     }
+
+     tempal &= 0x3F;
+
+     if(ModeNo > 0x13) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
+	   switch(resinfo) {
+	   case SIS_RI_720x480:
+	      tempal = 6;
+	      if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN))	tempal = 9;
+	      break;
+	   case SIS_RI_720x576:
+	   case SIS_RI_768x576:
+	   case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
+	      tempal = 6;
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+		 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)	tempal = 8;
+	      }
+	      break;
+	   case SIS_RI_800x480:
+	      tempal = 4;
+	      break;
+	   case SIS_RI_512x384:
+	   case SIS_RI_1024x768:
+	      tempal = 7;
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+		 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)	tempal = 8;
+	      }
+	      break;
+	   case SIS_RI_1280x720:
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+		 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)	tempal = 9;
+	      }
+	      break;
+	   }
+	}
+     }
+
+     *CRT2Index = tempbx;
+     *ResIndex = tempal;
+
+  } else {   /* LVDS, 301B-DH (if running on LCD) */
+
+     tempbx = 0;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+	tempbx = 90;
+	if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	   tempbx = 92;
+	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
+	   }
+	   if(SiS_Pr->SiS_TVMode & TVSetPALM)      tempbx = 94;
+	   else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
+	}
+	if(tempbx != 99) {
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
+	}
+
+     } else {
+
+	switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_640x480:   tempbx = 12; break;
+	case Panel_320x240_1: tempbx = 10; break;
+	case Panel_320x240_2:
+	case Panel_320x240_3: tempbx = 14; break;
+	case Panel_800x600:   tempbx = 16; break;
+	case Panel_1024x600:  tempbx = 18; break;
+	case Panel_1152x768:
+	case Panel_1024x768:  tempbx = 20; break;
+	case Panel_1280x768:  tempbx = 22; break;
+	case Panel_1280x1024: tempbx = 24; break;
+	case Panel_1400x1050: tempbx = 26; break;
+	case Panel_1600x1200: tempbx = 28; break;
+#ifdef CONFIG_FB_SIS_300
+	case Panel_Barco1366: tempbx = 80; break;
+#endif
+	}
+
+	switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_320x240_1:
+	case Panel_320x240_2:
+	case Panel_320x240_3:
+	case Panel_640x480:
+	   break;
+	default:
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
+	}
+
+	if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
+
+#ifdef CONFIG_FB_SIS_300
+	if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+	   tempbx = 82;
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
+	} else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+	   tempbx = 84;
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
+	}
+#endif
+
+     }
+
+     (*CRT2Index) = tempbx;
+     (*ResIndex) = tempal & 0x1F;
+  }
+}
+
+static void
+SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex)
+{
+  unsigned short tempax=0, tempbx=0, index, dotclock;
+  unsigned short temp1=0, modeflag=0, tempcx=0;
+
+  SiS_Pr->SiS_RVBHCMAX  = 1;
+  SiS_Pr->SiS_RVBHCFACT = 1;
+
+  if(ModeNo <= 0x13) {
+
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
+
+     tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
+     tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
+     temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
+
+     dotclock = (modeflag & Charx8Dot) ? 8 : 9;
+
+  } else {
+
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
+
+     tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
+     tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
+     tempax &= 0x03FF;
+     tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
+     tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
+     tempcx &= 0x0100;
+     tempcx <<= 2;
+     tempbx |= tempcx;
+     temp1  = SiS_Pr->SiS_CRT1Table[index].CR[7];
+
+     dotclock = 8;
+
+  }
+
+  if(temp1 & 0x01) tempbx |= 0x0100;
+  if(temp1 & 0x20) tempbx |= 0x0200;
+
+  tempax += 5;
+  tempax *= dotclock;
+  if(modeflag & HalfDCLK) tempax <<= 1;
+
+  tempbx++;
+
+  SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+  SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
+}
+
+static void
+SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
+{
+   unsigned short ResIndex;
+
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+	 if(SiS_Pr->UseCustomMode) {
+	    ResIndex = SiS_Pr->CHTotal;
+	    if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
+	    SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
+	    SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+	 } else {
+	    if(ModeNo < 0x13) {
+	       ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+	    } else {
+	       ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+	    }
+	    if(ResIndex == 0x09) {
+	       if(SiS_Pr->Alternate1600x1200)        ResIndex = 0x20; /* 1600x1200 LCDA */
+	       else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
+	    }
+	    SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
+	    SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
+	    SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
+	    SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
+	 }
+      } else {
+	 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+	 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+      }
+   } else {
+      /* This handles custom modes and custom panels */
+      SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+      SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+      SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
+      SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
+      SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
+      SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
+   }
+}
+
+static void
+SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                    unsigned short RefreshRateTableIndex)
+{
+   unsigned short CRT2Index, ResIndex, backup;
+   const struct SiS_LVDSData *LVDSData = NULL;
+
+   SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+      SiS_Pr->SiS_RVBHCMAX  = 1;
+      SiS_Pr->SiS_RVBHCFACT = 1;
+      SiS_Pr->SiS_NewFlickerMode = 0;
+      SiS_Pr->SiS_RVBHRS = 50;
+      SiS_Pr->SiS_RY1COE = 0;
+      SiS_Pr->SiS_RY2COE = 0;
+      SiS_Pr->SiS_RY3COE = 0;
+      SiS_Pr->SiS_RY4COE = 0;
+      SiS_Pr->SiS_RVBHRS2 = 0;
+   }
+
+   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+
+#ifdef CONFIG_FB_SIS_315
+      SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
+#endif
+
+   } else {
+
+      /* 301BDH needs LVDS Data */
+      backup = SiS_Pr->SiS_IF_DEF_LVDS;
+      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+	 SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      }
+
+      SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
+                     		            &CRT2Index, &ResIndex);
+
+      SiS_Pr->SiS_IF_DEF_LVDS = backup;
+
+      switch(CRT2Index) {
+	 case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1;    break;
+	 case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2;    break;
+	 case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
+	 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
+	 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
+	 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+#ifdef CONFIG_FB_SIS_300
+	 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
+	 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
+	 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
+	 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
+	 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
+#endif
+	 case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
+	 case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
+	 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
+	 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
+	 case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
+	 case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
+	 case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
+	 case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
+	 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;
+      }
+
+      if(LVDSData) {
+	 SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
+	 SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
+	 SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
+	 SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
+      } else {
+	 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      }
+
+      if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
+	  (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
+	  (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
+	 if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
+	     (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
+	    SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+            SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+#ifdef CONFIG_FB_SIS_300
+	    if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+	       if(ResIndex < 0x08) {
+		  SiS_Pr->SiS_HDE = 1280;
+		  SiS_Pr->SiS_VDE = 1024;
+	       }
+	    }
+#endif
+         }
+      }
+   }
+}
+
+static void
+SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex)
+{
+  unsigned char  *ROMAddr = NULL;
+  unsigned short tempax, tempbx, modeflag, romptr=0;
+  unsigned short resinfo, CRT2Index, ResIndex;
+  const struct SiS_LCDData *LCDPtr = NULL;
+  const struct SiS_TVData  *TVPtr  = NULL;
+#ifdef CONFIG_FB_SIS_315
+  short resinfo661;
+#endif
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef CONFIG_FB_SIS_315
+     resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
+	 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
+	 (resinfo661 >= 0)                     &&
+	 (SiS_Pr->SiS_NeedRomModeData) ) {
+	if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
+	   if((romptr = (SISGETROMW(21)))) {
+	      romptr += (resinfo661 * 10);
+	      ROMAddr = SiS_Pr->VirtualRomBase;
+	   }
+	}
+     }
+#endif
+  }
+
+  SiS_Pr->SiS_NewFlickerMode = 0;
+  SiS_Pr->SiS_RVBHRS = 50;
+  SiS_Pr->SiS_RY1COE = 0;
+  SiS_Pr->SiS_RY2COE = 0;
+  SiS_Pr->SiS_RY3COE = 0;
+  SiS_Pr->SiS_RY4COE = 0;
+  SiS_Pr->SiS_RVBHRS2 = 0;
+
+  SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+
+     if(SiS_Pr->UseCustomMode) {
+
+	SiS_Pr->SiS_RVBHCMAX  = 1;
+	SiS_Pr->SiS_RVBHCFACT = 1;
+	SiS_Pr->SiS_HDE       = SiS_Pr->SiS_VGAHDE;
+	SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
+
+	tempax = SiS_Pr->CHTotal;
+	if(modeflag & HalfDCLK) tempax <<= 1;
+	SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+	SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+
+     } else {
+
+	SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+
+     }
+
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+     SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+		    &CRT2Index,&ResIndex);
+
+     switch(CRT2Index) {
+	case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
+	case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
+	case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
+	case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
+	case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
+	case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
+	case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
+	case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
+	case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
+	case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
+	case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
+	case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
+	case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
+	default: TVPtr = SiS_Pr->SiS_StPALData;     break;
+     }
+
+     SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
+     SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
+     SiS_Pr->SiS_VGAHT     = (TVPtr+ResIndex)->VGAHT;
+     SiS_Pr->SiS_VGAVT     = (TVPtr+ResIndex)->VGAVT;
+     SiS_Pr->SiS_HDE       = (TVPtr+ResIndex)->TVHDE;
+     SiS_Pr->SiS_VDE       = (TVPtr+ResIndex)->TVVDE;
+     SiS_Pr->SiS_RVBHRS2   = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
+     if(modeflag & HalfDCLK) {
+	SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+	if(SiS_Pr->SiS_RVBHRS2) {
+	   SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+	   tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
+	   if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
+	   else                                   SiS_Pr->SiS_RVBHRS2 += tempax;
+	}
+     } else {
+	SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
+     }
+     SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+
+	if((resinfo == SIS_RI_960x600)   ||
+	   (resinfo == SIS_RI_1024x768)  ||
+	   (resinfo == SIS_RI_1280x1024) ||
+	   (resinfo == SIS_RI_1280x720)) {
+	   SiS_Pr->SiS_NewFlickerMode = 0x40;
+	}
+
+	if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+
+	SiS_Pr->SiS_HT = ExtHiTVHT;
+	SiS_Pr->SiS_VT = ExtHiTVVT;
+	if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+	      SiS_Pr->SiS_HT = StHiTVHT;
+	      SiS_Pr->SiS_VT = StHiTVVT;
+	   }
+	}
+
+     } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+
+	if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	   SiS_Pr->SiS_HT = 1650;
+	   SiS_Pr->SiS_VT = 750;
+	} else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+	   SiS_Pr->SiS_HT = NTSCHT;
+	   if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
+	   SiS_Pr->SiS_VT = NTSCVT;
+	} else {
+	   SiS_Pr->SiS_HT = NTSCHT;
+	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
+	   SiS_Pr->SiS_VT = NTSCVT;
+	}
+
+     } else {
+
+	SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
+	SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
+	SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
+	SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
+
+	if(modeflag & HalfDCLK) {
+	   SiS_Pr->SiS_RY1COE = 0x00;
+	   SiS_Pr->SiS_RY2COE = 0xf4;
+	   SiS_Pr->SiS_RY3COE = 0x10;
+	   SiS_Pr->SiS_RY4COE = 0x38;
+	}
+
+	if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+	   SiS_Pr->SiS_HT = NTSCHT;
+	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
+	   SiS_Pr->SiS_VT = NTSCVT;
+	} else {
+	   SiS_Pr->SiS_HT = PALHT;
+	   SiS_Pr->SiS_VT = PALVT;
+	}
+
+     }
+
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+     SiS_Pr->SiS_RVBHCMAX  = 1;
+     SiS_Pr->SiS_RVBHCFACT = 1;
+
+     if(SiS_Pr->UseCustomMode) {
+
+	SiS_Pr->SiS_HDE   = SiS_Pr->SiS_VGAHDE;
+	SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
+
+	tempax = SiS_Pr->CHTotal;
+	if(modeflag & HalfDCLK) tempax <<= 1;
+	SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+	SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+
+     } else {
+
+	bool gotit = false;
+
+	if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+
+	   SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
+	   SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
+	   SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
+	   SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
+	   gotit = true;
+
+	} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
+
+#ifdef CONFIG_FB_SIS_315
+	   SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
+	   SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
+	   SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
+	   SiS_Pr->SiS_VGAVT     = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
+	   SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
+	   SiS_Pr->SiS_VT        = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
+	   SiS_Pr->SiS_RVBHRS2   = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
+	   if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
+	      SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+	      tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
+	      if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
+	      else                         SiS_Pr->SiS_RVBHRS2 += tempax;
+	   }
+	   if(SiS_Pr->SiS_VGAHT) gotit = true;
+	   else {
+	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+	      SiS_Pr->SiS_RVBHCMAX  = 1;
+	      SiS_Pr->SiS_RVBHCFACT = 1;
+	      SiS_Pr->SiS_VGAHT   = SiS_Pr->PanelHT;
+	      SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
+	      SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
+	      SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
+	      SiS_Pr->SiS_RVBHRS2 = 0;
+	      gotit = true;
+	   }
+#endif
+
+	}
+
+	if(!gotit) {
+
+	   SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+			  &CRT2Index,&ResIndex);
+
+	   switch(CRT2Index) {
+	      case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+	      case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
+	      case Panel_1280x720      :
+	      case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
+	      case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
+	      case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
+	      case Panel_1280x800      :
+	      case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
+	      case Panel_1280x800_2    :
+	      case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data;    break;
+	      case Panel_1280x854      :
+	      case Panel_1280x854  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data;      break;
+	      case Panel_1280x960      :
+	      case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
+	      case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
+	      case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+	      case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
+	      case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
+	      case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
+	      case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
+	      case Panel_1680x1050     :
+	      case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
+	      case 100		       : LCDPtr = SiS_Pr->SiS_NoScaleData;	    break;
+#ifdef CONFIG_FB_SIS_315
+	      case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
+	      case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+#endif
+	      default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+	   }
+
+	   SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
+	   SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+	   SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
+	   SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
+	   SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
+	   SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+
+        }
+
+	tempax = SiS_Pr->PanelXRes;
+	tempbx = SiS_Pr->PanelYRes;
+
+	switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_1024x768:
+	   if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+	      if(SiS_Pr->ChipType < SIS_315H) {
+		 if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+		 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+	      }
+	   } else {
+	      if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
+	      else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
+	      else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
+	      else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
+	      else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+	      else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+	   }
+	   break;
+	case Panel_1280x960:
+	   if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
+	   else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
+	   else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
+	   break;
+	case Panel_1280x1024:
+	   if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+	   else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+	   else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+	   break;
+	case Panel_1600x1200:
+	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+	      if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
+	      else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
+	   }
+	   break;
+	}
+
+	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	   tempax = SiS_Pr->SiS_VGAHDE;
+	   tempbx = SiS_Pr->SiS_VGAVDE;
+	}
+
+	SiS_Pr->SiS_HDE = tempax;
+	SiS_Pr->SiS_VDE = tempbx;
+     }
+  }
+}
+
+static void
+SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                unsigned short RefreshRateTableIndex)
+{
+
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+         SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      } else {
+	 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+	    /* Need LVDS Data for LCD on 301B-DH */
+	    SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	 } else {
+	    SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	 }
+      }
+
+   } else {
+
+      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+
+   }
+}
+
+/*********************************************/
+/*         GET LVDS DES (SKEW) DATA          */
+/*********************************************/
+
+static const struct SiS_LVDSDes *
+SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
+{
+   const struct SiS_LVDSDes *PanelDesPtr = NULL;
+
+#ifdef CONFIG_FB_SIS_300
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+      if(SiS_Pr->ChipType < SIS_315H) {
+	 if(SiS_Pr->SiS_LCDTypeInfo == 4) {
+	    if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+	       PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
+	       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+		  PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
+	       }
+            } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+	       PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
+	       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+		  PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
+	       }
+	    }
+	 }
+      }
+   }
+#endif
+   return PanelDesPtr;
+}
+
+static void
+SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                   unsigned short RefreshRateTableIndex)
+{
+  unsigned short modeflag, ResIndex;
+  const struct SiS_LVDSDes *PanelDesPtr = NULL;
+
+  SiS_Pr->SiS_LCDHDES = 0;
+  SiS_Pr->SiS_LCDVDES = 0;
+
+  /* Some special cases */
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+     /* Trumpion */
+     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	   if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	}
+	return;
+     }
+
+     /* 640x480 on LVDS */
+     if(SiS_Pr->ChipType < SIS_315H) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
+	   SiS_Pr->SiS_LCDHDES = 8;
+	   if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+	   else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+	   else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+	   return;
+	}
+     }
+
+  } /* LCD */
+
+  if( (SiS_Pr->UseCustomMode) 		         ||
+      (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL856)      ||
+      (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
+     return;
+  }
+
+  if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  else               ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+
+#ifdef CONFIG_FB_SIS_315
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	/* non-pass 1:1 only, see above */
+	if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+	   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+	}
+	if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+	}
+     }
+     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+	switch(SiS_Pr->SiS_CustomT) {
+	case CUT_UNIWILL1024:
+	case CUT_UNIWILL10242:
+	case CUT_CLEVO1400:
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	   break;
+	}
+	switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_1280x1024:
+	   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	   break;
+	case Panel_1280x800:	/* Verified for Averatec 6240 */
+	case Panel_1280x800_2:	/* Verified for Asus A4L */
+	case Panel_1280x854:    /* Not verified yet FIXME */
+	   SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   break;
+	}
+     }
+#endif
+
+  } else {
+
+     if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+	if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+	   if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
+	}
+
+     } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
+
+	SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+	SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+
+     } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+
+	if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+	   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+	}
+	if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+	} else {
+	   if(SiS_Pr->ChipType < SIS_315H) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   } else {
+	      switch(SiS_Pr->SiS_LCDResInfo) {
+	      case Panel_800x600:
+	      case Panel_1024x768:
+	      case Panel_1280x1024:
+		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+		 break;
+	      case Panel_1400x1050:
+		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+		 break;
+	      }
+	   }
+	}
+
+     } else {
+
+        if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+	   switch(SiS_Pr->SiS_LCDResInfo) {
+	   case Panel_800x600:
+	      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	      } else {
+		 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
+		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+		 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
+		 else                          SiS_Pr->SiS_LCDVDES -= 4;
+	      }
+	      break;
+	   case Panel_1024x768:
+	      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	      } else {
+		 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+		 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
+		 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
+	      }
+	      break;
+	   case Panel_1024x600:
+	   default:
+	      if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
+		  (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
+		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	      } else {
+		 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+	      }
+	      break;
+	   }
+
+	   switch(SiS_Pr->SiS_LCDTypeInfo) {
+	   case 1:
+	      SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
+	      break;
+	   case 3: /* 640x480 only? */
+	      SiS_Pr->SiS_LCDHDES = 8;
+	      if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+	      else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+	      else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+	      break;
+	   }
+#endif
+        } else {
+#ifdef CONFIG_FB_SIS_315
+	   switch(SiS_Pr->SiS_LCDResInfo) {
+	   case Panel_1024x768:
+	   case Panel_1280x1024:
+	      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+	         SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	      }
+	      break;
+	   case Panel_320x240_1:
+	   case Panel_320x240_2:
+	   case Panel_320x240_3:
+	      SiS_Pr->SiS_LCDVDES = 524;
+	      break;
+	   }
+#endif
+	}
+     }
+
+     if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+	if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	   if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
+	} else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+	   if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+	      if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
+	         if(SiS_Pr->ChipType < SIS_315H) {
+	            if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
+	         } else {
+#ifdef CONFIG_FB_SIS_315
+		    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
+		    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
+		    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
+		    if(!(modeflag & HalfDCLK)) {
+		       SiS_Pr->SiS_LCDHDES = 320;
+		       if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
+		       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
+        	    }
+#endif
+		 }
+	      }
+	   }
+	}
+     }
+  }
+}
+
+/*********************************************/
+/*           DISABLE VIDEO BRIDGE            */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_315
+static int
+SiS_HandlePWD(struct SiS_Private *SiS_Pr)
+{
+   int ret = 0;
+#ifdef SET_PWD
+   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
+   unsigned char  drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
+   unsigned short temp;
+
+   if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
+       (romptr)				&&
+       (SiS_Pr->SiS_PWDOffset) ) {
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
+      temp = 0x00;
+      if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
+         temp = 0x80;
+	 ret = 1;
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
+   }
+#endif
+   return ret;
+}
+#endif
+
+/* NEVER use any variables (VBInfo), this will be called
+ * from outside the context of modeswitch!
+ * MUST call getVBType before calling this
+ */
+void
+SiS_DisableBridge(struct SiS_Private *SiS_Pr)
+{
+#ifdef CONFIG_FB_SIS_315
+  unsigned short tempah, pushax=0, modenum;
+#endif
+  unsigned short temp=0;
+
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {		/* ===== For 30xB/C/LV ===== */
+
+	if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300	   /* 300 series */
+
+	   if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+		 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+	      }
+	      SiS_PanelDelay(SiS_Pr, 3);
+	   }
+	   if(SiS_Is301B(SiS_Pr)) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
+	      SiS_ShortDelay(SiS_Pr,1);
+	   }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
+	   SiS_DisplayOff(SiS_Pr);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	   SiS_UnLockCRT2(SiS_Pr);
+	   if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
+	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
+	   }
+	   if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+	       (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+	      SiS_PanelDelay(SiS_Pr, 2);
+	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
+	      }
+	   }
+
+#endif  /* CONFIG_FB_SIS_300 */
+
+        } else {
+
+#ifdef CONFIG_FB_SIS_315	   /* 315 series */
+
+	   int didpwd = 0;
+	   bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+	                  (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
+
+	   modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
+
+	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+
+#ifdef SET_EMI
+	      if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+		 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+		 }
+	      }
+#endif
+
+	      didpwd = SiS_HandlePWD(SiS_Pr);
+
+	      if( (modenum <= 0x13)           ||
+		  (SiS_IsVAMode(SiS_Pr))      ||
+		  (!(SiS_IsDualEdge(SiS_Pr))) ) {
+		 if(!didpwd) {
+		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
+		    if(custom1) SiS_PanelDelay(SiS_Pr, 3);
+		 } else {
+		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
+		 }
+	      }
+
+	      if(!custom1) {
+		 SiS_DDC2Delay(SiS_Pr,0xff00);
+		 SiS_DDC2Delay(SiS_Pr,0xe000);
+		 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+		 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+		 if(IS_SIS740) {
+		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
+		 }
+	         SiS_PanelDelay(SiS_Pr, 3);
+	      }
+
+	   }
+
+	   if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+	      /* if(SiS_Pr->ChipType < SIS_340) {*/
+		 tempah = 0xef;
+		 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
+		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	      /*}*/
+	   }
+
+	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
+	   }
+
+	   tempah = 0x3f;
+	   if(SiS_IsDualEdge(SiS_Pr)) {
+	      tempah = 0x7f;
+	      if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
+	   }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+
+	   if((SiS_IsVAMode(SiS_Pr)) ||
+	      ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
+
+	      SiS_DisplayOff(SiS_Pr);
+	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+		 SiS_PanelDelay(SiS_Pr, 2);
+	      }
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
+
+	   }
+
+	   if((!(SiS_IsVAMode(SiS_Pr))) ||
+	      ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
+
+	      if(!(SiS_IsDualEdge(SiS_Pr))) {
+		 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
+		 SiS_DisplayOff(SiS_Pr);
+	      }
+	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+
+	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+		 SiS_PanelDelay(SiS_Pr, 2);
+	      }
+
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
+
+	   }
+
+	   if(SiS_IsNotM650orLater(SiS_Pr)) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	   }
+
+	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+
+	      if( (!(SiS_IsVAMode(SiS_Pr)))  &&
+		  (!(SiS_CRT2IsLCD(SiS_Pr))) &&
+		  (!(SiS_IsDualEdge(SiS_Pr))) ) {
+
+		 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
+		 if(!didpwd) {
+		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+		 }
+		 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
+	      }
+
+	      if(!custom1) {
+		 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+		 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+		    if(SiS_IsVAorLCD(SiS_Pr)) {
+		       SiS_PanelDelayLoop(SiS_Pr, 3, 20);
+		    }
+		 }
+	      }
+
+	   }
+
+#endif /* CONFIG_FB_SIS_315 */
+
+	}
+
+     } else {     /* ============ For 301 ================ */
+
+        if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef CONFIG_FB_SIS_300
+	   if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+	      SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+	      SiS_PanelDelay(SiS_Pr, 3);
+	   }
+#endif
+	}
+
+	SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
+	SiS_DisplayOff(SiS_Pr);
+
+	if(SiS_Pr->ChipType >= SIS_315H) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+	}
+
+	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
+
+	if(SiS_Pr->ChipType >= SIS_315H) {
+	    temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
+	} else {
+#ifdef CONFIG_FB_SIS_300
+	    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
+	    if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+		(!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+		SiS_PanelDelay(SiS_Pr, 2);
+		SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
+	    }
+#endif
+	}
+
+      }
+
+  } else {     /* ============ For LVDS =============*/
+
+    if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300	/* 300 series */
+
+	if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+	   SiS_SetCH700x(SiS_Pr,0x0E,0x09);
+	}
+
+	if(SiS_Pr->ChipType == SIS_730) {
+	   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
+	      SiS_WaitVBRetrace(SiS_Pr);
+	   }
+	   if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+	      SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+	      SiS_PanelDelay(SiS_Pr, 3);
+	   }
+	} else {
+	   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
+	      if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+		 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+		    SiS_WaitVBRetrace(SiS_Pr);
+		    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
+		       SiS_DisplayOff(SiS_Pr);
+		    }
+		    SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+		    SiS_PanelDelay(SiS_Pr, 3);
+		 }
+	      }
+	   }
+	}
+
+	SiS_DisplayOff(SiS_Pr);
+
+	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+
+	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	SiS_UnLockCRT2(SiS_Pr);
+	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
+	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
+
+	if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+	    (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+	   SiS_PanelDelay(SiS_Pr, 2);
+	   SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
+	}
+
+#endif  /* CONFIG_FB_SIS_300 */
+
+    } else {
+
+#ifdef CONFIG_FB_SIS_315	/* 315 series */
+
+	if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+	   /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
+	   /* } */
+	}
+
+	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+
+	   if(SiS_Pr->ChipType == SIS_740) {
+	      temp = SiS_GetCH701x(SiS_Pr,0x61);
+	      if(temp < 1) {
+		 SiS_SetCH701x(SiS_Pr,0x76,0xac);
+		 SiS_SetCH701x(SiS_Pr,0x66,0x00);
+	      }
+
+	      if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+		  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+		 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
+	      }
+	   }
+
+	   if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+	       (SiS_IsVAMode(SiS_Pr)) ) {
+	      SiS_Chrontel701xBLOff(SiS_Pr);
+	      SiS_Chrontel701xOff(SiS_Pr);
+	   }
+
+	   if(SiS_Pr->ChipType != SIS_740) {
+	      if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+		  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+		 SiS_SetCH701x(SiS_Pr,0x49,0x01);
+	      }
+	   }
+
+	}
+
+	if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+	   SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+	   SiS_PanelDelay(SiS_Pr, 3);
+	}
+
+	if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
+	    (!(SiS_IsDualEdge(SiS_Pr))) ||
+	    (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
+	   SiS_DisplayOff(SiS_Pr);
+	}
+
+	if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
+	    (!(SiS_IsDualEdge(SiS_Pr))) ||
+	    (!(SiS_IsVAMode(SiS_Pr))) ) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+	}
+
+	if(SiS_Pr->ChipType == SIS_740) {
+	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	}
+
+	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+
+	if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
+	    (!(SiS_IsDualEdge(SiS_Pr))) ||
+	    (!(SiS_IsVAMode(SiS_Pr))) ) {
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	}
+
+	if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+	   if(SiS_CRT2IsLCD(SiS_Pr)) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
+	      if(SiS_Pr->ChipType == SIS_550) {
+		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
+		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
+	      }
+	   }
+	} else {
+	   if(SiS_Pr->ChipType == SIS_740) {
+	      if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
+	      }
+	   } else if(SiS_IsVAMode(SiS_Pr)) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
+	   }
+	}
+
+	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	   if(SiS_IsDualEdge(SiS_Pr)) {
+	      /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
+	   } else {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
+	   }
+	}
+
+	SiS_UnLockCRT2(SiS_Pr);
+
+	if(SiS_Pr->ChipType == SIS_550) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
+	} else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
+		   (!(SiS_IsDualEdge(SiS_Pr))) ||
+		   (!(SiS_IsVAMode(SiS_Pr))) ) {
+	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
+	}
+
+        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+	   if(SiS_CRT2IsLCD(SiS_Pr)) {
+	      if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+		 SiS_PanelDelay(SiS_Pr, 2);
+		 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
+	      }
+	   }
+        }
+
+#endif  /* CONFIG_FB_SIS_315 */
+
+    }  /* 315 series */
+
+  }  /* LVDS */
+
+}
+
+/*********************************************/
+/*            ENABLE VIDEO BRIDGE            */
+/*********************************************/
+
+/* NEVER use any variables (VBInfo), this will be called
+ * from outside the context of a mode switch!
+ * MUST call getVBType before calling this
+ */
+static
+void
+SiS_EnableBridge(struct SiS_Private *SiS_Pr)
+{
+  unsigned short temp=0, tempah;
+#ifdef CONFIG_FB_SIS_315
+  unsigned short temp1, pushax=0;
+  bool delaylong = false;
+#endif
+
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {		/* ====== For 301B et al  ====== */
+
+      if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300     /* 300 series */
+
+	 if(SiS_CRT2IsLCD(SiS_Pr)) {
+	    if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	       SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+	    }
+	    if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
+	       if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+		  SiS_PanelDelay(SiS_Pr, 0);
+	       }
+	    }
+	 }
+
+	 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+	    (SiS_CRT2IsLCD(SiS_Pr))) {
+
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   		/* Enable CRT2 */
+	    SiS_DisplayOn(SiS_Pr);
+	    SiS_UnLockCRT2(SiS_Pr);
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+	    } else {
+	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+	    }
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+		  if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+		     SiS_PanelDelay(SiS_Pr, 1);
+		  }
+		  SiS_WaitVBRetrace(SiS_Pr);
+		  SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+	       }
+	    }
+
+	 } else {
+
+	    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+	       tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+	       if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+	    }
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
+	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
+	    SiS_DisplayOn(SiS_Pr);
+	    if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	       if(SiS_CRT2IsLCD(SiS_Pr)) {
+		  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+		     if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+		        SiS_PanelDelay(SiS_Pr, 1);
+		     }
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+		  }
+	       }
+	    }
+
+	 }
+
+
+#endif /* CONFIG_FB_SIS_300 */
+
+      } else {
+
+#ifdef CONFIG_FB_SIS_315    /* 315 series */
+
+#ifdef SET_EMI
+	 unsigned char   r30=0, r31=0, r32=0, r33=0, cr36=0;
+	 int didpwd = 0;
+	 /* unsigned short  emidelay=0; */
+#endif
+
+	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
+#ifdef SET_EMI
+	    if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+	    }
+#endif
+	 }
+
+	 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+	    /*if(SiS_Pr->ChipType < SIS_340) { */
+	       tempah = 0x10;
+	       if(SiS_LCDAEnabled(SiS_Pr)) {
+		  if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
+		  else			    tempah = 0x08;
+	       }
+	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	    /*}*/
+	 }
+
+	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+	    SiS_DisplayOff(SiS_Pr);
+	    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+	    if(IS_SIS740) {
+	       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
+	    }
+
+	    didpwd = SiS_HandlePWD(SiS_Pr);
+
+	    if(SiS_IsVAorLCD(SiS_Pr)) {
+	       if(!didpwd) {
+		  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+		     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+		     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+		     if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+		        SiS_GenericDelay(SiS_Pr, 17664);
+		     }
+		  }
+	       } else {
+		  SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+		  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+		     SiS_GenericDelay(SiS_Pr, 17664);
+		  }
+	       }
+	    }
+
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
+	       SiS_PanelDelayLoop(SiS_Pr, 3, 10);
+	       delaylong = true;
+	    }
+
+	 }
+
+	 if(!(SiS_IsVAMode(SiS_Pr))) {
+
+	    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+	       tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+	       if(!(tempah & SetCRT2ToRAMDAC)) {
+		  if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
+	       }
+	    }
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
+
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+
+	    if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	       SiS_PanelDelay(SiS_Pr, 2);
+	    }
+
+	 } else {
+
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+
+	 }
+
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+	 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+
+	 if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
+	    if( (SiS_LCDAEnabled(SiS_Pr)) ||
+	        (SiS_CRT2IsLCD(SiS_Pr)) ) {
+	       /* Enable "LVDS PLL power on" (even on 301C) */
+	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
+	       /* Enable "LVDS Driver Power on" (even on 301C) */
+	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
+	    }
+	 }
+
+	 tempah = 0xc0;
+	 if(SiS_IsDualEdge(SiS_Pr)) {
+	    tempah = 0x80;
+	    if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
+	 }
+	 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+
+	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+
+	    SiS_PanelDelay(SiS_Pr, 2);
+
+	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+
+	    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+#ifdef SET_EMI
+	       if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+		  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+		  SiS_GenericDelay(SiS_Pr, 2048);
+	       }
+#endif
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
+
+	       if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+#ifdef SET_EMI
+		  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+
+		  if(SiS_Pr->SiS_ROMNew) {
+		     unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+		     unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
+		     if(romptr) {
+			SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
+			SiS_Pr->EMI_30 = 0;
+			SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
+			SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
+			SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
+			if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
+			/* emidelay = SISGETROMW((romptr + 0x22)); */
+			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
+		     }
+		  }
+
+		  /*                                              (P4_30|0x40)  */
+		  /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
+		  /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
+		  /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
+		  /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
+		  /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
+		  /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
+
+		  if(SiS_Pr->HaveEMI) {
+		     r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
+		     r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
+		  } else {
+		     r30 = 0;
+		  }
+
+		  /* EMI_30 is read at driver start; however, the BIOS sets this
+		   * (if it is used) only if the LCD is in use. In case we caught
+		   * the machine while on TV output, this bit is not set and we
+		   * don't know if it should be set - hence our detection is wrong.
+		   * Work-around this here:
+		   */
+
+		  if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
+		     switch((cr36 & 0x0f)) {
+		     case 2:
+			r30 |= 0x40;
+			if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x33;
+			   if((cr36 & 0xf0) == 0x30) {
+			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;
+			   }
+			}
+			break;
+		     case 3:  /* 1280x1024 */
+			if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
+			   if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+			      r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
+			   }
+			}
+			break;
+		     case 9:  /* 1400x1050 */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
+			   if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
+			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
+			   }
+			}
+			break;
+		     case 11: /* 1600x1200 - unknown */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
+			}
+		     }
+                  }
+
+		  /* BIOS values don't work so well sometimes */
+		  if(!SiS_Pr->OverruleEMI) {
+#ifdef COMPAL_HACK
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
+			if((cr36 & 0x0f) == 0x09) {
+			   r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
+			}
+ 		     }
+#endif
+#ifdef COMPAQ_HACK
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+			if((cr36 & 0x0f) == 0x03) {
+			   r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
+			}
+		     }
+#endif
+#ifdef ASUS_HACK
+		     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+			if((cr36 & 0x0f) == 0x02) {
+			   /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
+			   /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
+			   /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
+			   /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
+			}
+		     }
+#endif
+		  }
+
+		  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
+		     SiS_GenericDelay(SiS_Pr, 2048);
+		  }
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
+#endif	/* SET_EMI */
+
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+
+#ifdef SET_EMI
+		  if( (SiS_LCDAEnabled(SiS_Pr)) ||
+		      (SiS_CRT2IsLCD(SiS_Pr)) ) {
+		     if(r30 & 0x40) {
+			/*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
+			SiS_PanelDelayLoop(SiS_Pr, 3, 5);
+			if(delaylong) {
+			   SiS_PanelDelayLoop(SiS_Pr, 3, 5);
+			   delaylong = false;
+			}
+			SiS_WaitVBRetrace(SiS_Pr);
+			SiS_WaitVBRetrace(SiS_Pr);
+			if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+			   SiS_GenericDelay(SiS_Pr, 1280);
+			}
+			SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
+			/*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
+		     }
+		  }
+#endif
+	       }
+	    }
+
+	    if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+	       if(SiS_IsVAorLCD(SiS_Pr)) {
+		  SiS_PanelDelayLoop(SiS_Pr, 3, 10);
+		  if(delaylong) {
+		     SiS_PanelDelayLoop(SiS_Pr, 3, 10);
+		  }
+		  SiS_WaitVBRetrace(SiS_Pr);
+		  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+		     SiS_GenericDelay(SiS_Pr, 2048);
+		     SiS_WaitVBRetrace(SiS_Pr);
+		  }
+		  if(!didpwd) {
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+		  } else {
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
+		  }
+	       }
+	    }
+
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+	    SiS_DisplayOn(SiS_Pr);
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
+
+	 }
+
+	 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+	 }
+
+#endif /* CONFIG_FB_SIS_315 */
+
+      }
+
+    } else {	/* ============  For 301 ================ */
+
+       if(SiS_Pr->ChipType < SIS_315H) {
+	  if(SiS_CRT2IsLCD(SiS_Pr)) {
+	     SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+	     SiS_PanelDelay(SiS_Pr, 0);
+	  }
+       }
+
+       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
+	  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+	  if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+       }
+       SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                  /* enable CRT2 */
+
+       if(SiS_Pr->ChipType >= SIS_315H) {
+	  temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
+	  if(!(temp & 0x80)) {
+	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
+	  }
+       }
+
+       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);     /* enable VB processor */
+
+       SiS_VBLongWait(SiS_Pr);
+       SiS_DisplayOn(SiS_Pr);
+       if(SiS_Pr->ChipType >= SIS_315H) {
+	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+       }
+       SiS_VBLongWait(SiS_Pr);
+
+       if(SiS_Pr->ChipType < SIS_315H) {
+	  if(SiS_CRT2IsLCD(SiS_Pr)) {
+	     SiS_PanelDelay(SiS_Pr, 1);
+	     SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+	  }
+       }
+
+    }
+
+  } else {   /* =================== For LVDS ================== */
+
+    if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300    /* 300 series */
+
+       if(SiS_CRT2IsLCD(SiS_Pr)) {
+	  if(SiS_Pr->ChipType == SIS_730) {
+	     SiS_PanelDelay(SiS_Pr, 1);
+	     SiS_PanelDelay(SiS_Pr, 1);
+	     SiS_PanelDelay(SiS_Pr, 1);
+	  }
+	  SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+	  if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+	     SiS_PanelDelay(SiS_Pr, 0);
+	  }
+       }
+
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+       SiS_DisplayOn(SiS_Pr);
+       SiS_UnLockCRT2(SiS_Pr);
+       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
+	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+       } else {
+	  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+       }
+
+       if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+	  if(!(SiS_CRT2IsLCD(SiS_Pr))) {
+	     SiS_WaitVBRetrace(SiS_Pr);
+	     SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
+	  }
+       }
+
+       if(SiS_CRT2IsLCD(SiS_Pr)) {
+	  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+	     if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+		if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+		   SiS_PanelDelay(SiS_Pr, 1);
+		   SiS_PanelDelay(SiS_Pr, 1);
+		}
+		SiS_WaitVBRetrace(SiS_Pr);
+		SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+	     }
+	  }
+       }
+
+#endif  /* CONFIG_FB_SIS_300 */
+
+    } else {
+
+#ifdef CONFIG_FB_SIS_315    /* 315 series */
+
+       if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+	  /*if(SiS_Pr->ChipType < SIS_340) {*/  /* XGI needs this */
+	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
+	  /*}*/
+       }
+
+       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+	  if(SiS_CRT2IsLCD(SiS_Pr)) {
+	     SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+	     SiS_PanelDelay(SiS_Pr, 0);
+	  }
+       }
+
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+       SiS_UnLockCRT2(SiS_Pr);
+
+       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
+
+       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	  temp = SiS_GetCH701x(SiS_Pr,0x66);
+	  temp &= 0x20;
+	  SiS_Chrontel701xBLOff(SiS_Pr);
+       }
+
+       if(SiS_Pr->ChipType != SIS_550) {
+	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+       }
+
+       if(SiS_Pr->ChipType == SIS_740) {
+	  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	     if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+		SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+	     }
+	  }
+       }
+
+       temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
+       if(!(temp1 & 0x80)) {
+	  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+       }
+
+       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	  if(temp) {
+	     SiS_Chrontel701xBLOn(SiS_Pr);
+	  }
+       }
+
+       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+	  if(SiS_CRT2IsLCD(SiS_Pr)) {
+	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+	     if(SiS_Pr->ChipType == SIS_550) {
+		SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
+		SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
+	     }
+	  }
+       } else if(SiS_IsVAMode(SiS_Pr)) {
+	  if(SiS_Pr->ChipType != SIS_740) {
+	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+	  }
+       }
+
+       if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+       }
+
+       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	  if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
+	     SiS_Chrontel701xOn(SiS_Pr);
+	  }
+	  if( (SiS_IsVAMode(SiS_Pr)) ||
+	      (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+	     SiS_ChrontelDoSomething1(SiS_Pr);
+	  }
+       }
+
+       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+	  if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+	     if( (SiS_IsVAMode(SiS_Pr)) ||
+		 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+		SiS_Chrontel701xBLOn(SiS_Pr);
+		SiS_ChrontelInitTVVSync(SiS_Pr);
+	     }
+	  }
+       } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+	  if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+	     if(SiS_CRT2IsLCD(SiS_Pr)) {
+		SiS_PanelDelay(SiS_Pr, 1);
+		SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+	     }
+	  }
+       }
+
+#endif  /* CONFIG_FB_SIS_315 */
+
+    } /* 310 series */
+
+  }  /* LVDS */
+
+}
+
+/*********************************************/
+/*         SET PART 1 REGISTER GROUP         */
+/*********************************************/
+
+/* Set CRT2 OFFSET / PITCH */
+static void
+SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RRTI)
+{
+   unsigned short offset;
+   unsigned char  temp;
+
+   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
+
+   offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
+
+   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
+   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
+
+   temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
+   if(offset & 0x07) temp++;
+   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
+}
+
+/* Set CRT2 sync and PanelLink mode */
+static void
+SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
+{
+   unsigned short tempah=0, tempbl, infoflag;
+
+   tempbl = 0xC0;
+
+   if(SiS_Pr->UseCustomMode) {
+      infoflag = SiS_Pr->CInfoFlag;
+   } else {
+      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+   }
+
+   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* LVDS */
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	 tempah = 0;
+      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
+	 tempah = SiS_Pr->SiS_LCDInfo;
+      } else tempah = infoflag >> 8;
+      tempah &= 0xC0;
+      tempah |= 0x20;
+      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+	    (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+	    tempah |= 0xf0;
+	 }
+	 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+	     (SiS_Pr->SiS_IF_DEF_DSTN) ||
+	     (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
+	     (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+	     (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
+	    tempah |= 0x30;
+	 }
+	 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+	     (SiS_Pr->SiS_IF_DEF_DSTN) ) {
+	    tempah &= ~0xc0;
+	 }
+      }
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	 if(SiS_Pr->ChipType >= SIS_315H) {
+	    tempah >>= 3;
+	    tempah &= 0x18;
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
+	    /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
+	 } else {
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
+	 }
+      } else {
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+      }
+
+   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+      if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300  /* ---- 300 series --- */
+
+	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {			/* 630 - 301B(-DH) */
+
+	    tempah = infoflag >> 8;
+	    tempbl = 0;
+	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	       if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+		  tempah = SiS_Pr->SiS_LCDInfo;
+		  tempbl = (tempah >> 6) & 0x03;
+	       }
+	    }
+	    tempah &= 0xC0;
+	    tempah |= 0x20;
+	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+	    tempah |= 0xc0;
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	    if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+	       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	    }
+
+	 } else {							/* 630 - 301 */
+
+	    tempah = ((infoflag >> 8) & 0xc0) | 0x20;
+	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+
+	 }
+
+#endif /* CONFIG_FB_SIS_300 */
+
+      } else {
+
+#ifdef CONFIG_FB_SIS_315  /* ------- 315 series ------ */
+
+	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {	  		/* 315 - LVDS */
+
+	    tempbl = 0;
+	    if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+	       tempah = infoflag >> 8;
+	       if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+		 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
+	       }
+	    } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
+		      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
+	       tempah = infoflag >> 8;
+	       tempbl = 0x03;
+	    } else {
+	       tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+	       tempbl = (tempah >> 6) & 0x03;
+	       tempbl |= 0x08;
+	       if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
+	    }
+	    tempah &= 0xC0;
+	    tempah |= 0x20;
+	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+		  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	       }
+	    }
+
+	 } else {							/* 315 - TMDS */
+
+	    tempah = tempbl = infoflag >> 8;
+	    if(!SiS_Pr->UseCustomMode) {
+	       tempbl = 0;
+	       if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+		  if(ModeNo <= 0x13) {
+		     tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+		  }
+	       }
+	       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+		  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+		    if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+		       tempah = SiS_Pr->SiS_LCDInfo;
+		       tempbl = (tempah >> 6) & 0x03;
+		    }
+		  }
+	       }
+	    }
+	    tempah &= 0xC0;
+	    tempah |= 0x20;
+	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+	    if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	       /* Imitate BIOS bug */
+	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
+	    }
+	    if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	       tempah >>= 3;
+	       tempah &= 0x18;
+	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
+	    } else {
+	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	       if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+		  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+		     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+		  }
+	       }
+	    }
+
+         }
+#endif  /* CONFIG_FB_SIS_315 */
+      }
+   }
+}
+
+/* Set CRT2 FIFO on 300/540/630/730 */
+#ifdef CONFIG_FB_SIS_300
+static void
+SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
+{
+  unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+  unsigned short temp, index, modeidindex, refreshratetableindex;
+  unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
+  unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
+  unsigned int   data, pci50, pciA0;
+  static const unsigned char colortharray[] = {
+  	1, 1, 2, 2, 3, 4
+  };
+
+  SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
+
+  if(!SiS_Pr->CRT1UsesCustomMode) {
+
+     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
+     SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
+     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+     SiS_Pr->SiS_SelectCRT2Rate = 0;
+     refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
+
+     if(CRT1ModeNo >= 0x13) {
+        /* Get VCLK */
+	index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
+	VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+
+	/* Get colordepth */
+	colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
+	if(!colorth) colorth++;
+     }
+
+  } else {
+
+     CRT1ModeNo = 0xfe;
+
+     /* Get VCLK */
+     VCLK = SiS_Pr->CSRClock_CRT1;
+
+     /* Get color depth */
+     colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
+
+  }
+
+  if(CRT1ModeNo >= 0x13) {
+     /* Get MCLK */
+     if(SiS_Pr->ChipType == SIS_300) {
+        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
+     } else {
+        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
+     }
+     index &= 0x07;
+     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
+
+     temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
+     if(!temp) temp++;
+     temp <<= 2;
+
+     data2 = temp - ((colorth * VCLK) / MCLK);
+
+     temp = (28 * 16) % data2;
+     data2 = (28 * 16) / data2;
+     if(temp) data2++;
+
+     if(SiS_Pr->ChipType == SIS_300) {
+
+	SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
+	data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
+
+     } else {
+
+	pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
+	pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
+
+        if(SiS_Pr->ChipType == SIS_730) {
+
+	   index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
+	   index += (unsigned short)(((pci50 >> 9)) & 0x03);
+
+	   /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
+	   index = 0;  /* -- do it like the BIOS anyway... */
+
+	} else {
+
+	   pci50 >>= 24;
+	   pciA0 >>= 24;
+
+	   index = (pci50 >> 1) & 0x07;
+
+	   if(pci50 & 0x01)    index += 6;
+	   if(!(pciA0 & 0x01)) index += 24;
+
+	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
+
+	}
+
+	data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
+	if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
+
+     }
+
+     data += data2;						/* CRT1 Request Period */
+
+     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+
+     if(!SiS_Pr->UseCustomMode) {
+
+	CRT2ModeNo = ModeNo;
+	SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
+
+	refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
+
+	/* Get VCLK  */
+	index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
+	VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+
+	if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x01) {
+		 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
+	      }
+           }
+        }
+
+     } else {
+
+	/* Get VCLK */
+	CRT2ModeNo = 0xfe;
+	VCLK = SiS_Pr->CSRClock;
+
+     }
+
+     /* Get colordepth */
+     colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
+     if(!colorth) colorth++;
+
+     data = data * VCLK * colorth;
+     temp = data % (MCLK << 4);
+     data = data / (MCLK << 4);
+     if(temp) data++;
+
+     if(data < 6) data = 6;
+     else if(data > 0x14) data = 0x14;
+
+     if(SiS_Pr->ChipType == SIS_300) {
+        temp = 0x16;
+	if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
+	   temp = 0x13;
+     } else {
+        temp = 0x16;
+	if(( (SiS_Pr->ChipType == SIS_630) ||
+	     (SiS_Pr->ChipType == SIS_730) )  &&
+	   (SiS_Pr->ChipRevision >= 0x30))
+	   temp = 0x1b;
+     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
+
+     if((SiS_Pr->ChipType == SIS_630) &&
+	(SiS_Pr->ChipRevision >= 0x30)) {
+	if(data > 0x13) data = 0x13;
+     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
+
+  } else {  /* If mode <= 0x13, we just restore everything */
+
+     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+
+  }
+}
+#endif
+
+/* Set CRT2 FIFO on 315/330 series */
+#ifdef CONFIG_FB_SIS_315
+static void
+SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
+{
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
+  if( (SiS_Pr->ChipType == SIS_760)      &&
+      (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
+      (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
+      (SiS_Pr->SiS_VGAHDE >= 1280)	  &&
+      (SiS_Pr->SiS_VGAVDE >= 1024) ) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
+  } else {
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
+  }
+
+}
+#endif
+
+static unsigned short
+SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
+{
+  unsigned int tempax,tempbx;
+
+  tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
+  tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
+  tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
+  return (unsigned short)tempax;
+}
+
+/* Set Part 1 / SiS bridge slave mode */
+static void
+SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+                  unsigned short RefreshRateTableIndex)
+{
+  unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
+  static const unsigned short CRTranslation[] = {
+       /* CR0   CR1   CR2   CR3   CR4   CR5   CR6   CR7   */
+	  0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+       /* CR8   CR9   SR0A  SR0B  SR0C  SR0D  SR0E  CR0F  */
+	  0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
+       /* CR10  CR11  CR12  CR13  CR14  CR15  CR16  CR17  */
+	  0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
+  };
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     xres = SiS_Pr->CHDisplay;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
+  }
+
+  /* The following is only done if bridge is in slave mode: */
+
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(xres >= 1600) {  /* BIOS: == 1600 */
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
+     }
+  }
+
+  SiS_Pr->CHTotal = 8224;  /* Max HT, 0x2020, results in 0x3ff in registers */
+
+  SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
+  if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
+
+  SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+     SiS_Pr->CHBlankStart += 16;
+  }
+
+  SiS_Pr->CHBlankEnd = 32;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
+  }
+
+  temp = SiS_Pr->SiS_VGAHT - 96;
+  if(!(modeflag & HalfDCLK)) temp -= 32;
+  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
+     temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
+     temp -= 3;
+     temp <<= 3;
+  } else {
+     if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
+  }
+  SiS_Pr->CHSyncStart = temp;
+
+  SiS_Pr->CHSyncEnd = 0xffe8; 	/* results in 0x2000 in registers */
+
+  SiS_Pr->CVTotal = 2049;  	/* Max VT, 0x0801, results in 0x7ff in registers */
+
+  VGAVDE = SiS_Pr->SiS_VGAVDE;
+  if     (VGAVDE ==  357) VGAVDE =  350;
+  else if(VGAVDE ==  360) VGAVDE =  350;
+  else if(VGAVDE ==  375) VGAVDE =  350;
+  else if(VGAVDE ==  405) VGAVDE =  400;
+  else if(VGAVDE ==  420) VGAVDE =  400;
+  else if(VGAVDE ==  525) VGAVDE =  480;
+  else if(VGAVDE == 1056) VGAVDE = 1024;
+  SiS_Pr->CVDisplay = VGAVDE;
+
+  SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
+
+  SiS_Pr->CVBlankEnd = 1;
+  if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
+
+  temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
+  SiS_Pr->CVSyncStart = VGAVDE + temp;
+
+  temp >>= 3;
+  SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
+
+  SiS_CalcCRRegisters(SiS_Pr, 0);
+  SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
+
+  for(i = 0; i <= 7; i++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
+  }
+  for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
+  }
+  for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
+  }
+  for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
+  }
+
+  temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
+
+  temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+  if(modeflag & DoubleScanMode) temp |= 0x80;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
+
+  temp = 0;
+  temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
+  if(modeflag & HalfDCLK) temp |= 0x08;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);              	/* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
+
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);              	/* CR14: (text mode: underline location) */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);              	/* CR17: n/a */
+
+  temp = 0;
+  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+     temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                	/* SR0E, dither[7] */
+
+  temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);			/* ? */
+}
+
+/* Setup panel link
+ * This is used for LVDS, LCDA and Chrontel TV output
+ * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
+ */
+static void
+SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex)
+{
+  unsigned short modeflag, resinfo = 0;
+  unsigned short push2, tempax, tempbx, tempcx, temp;
+  unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
+  bool islvds = false, issis  = false, chkdclkfirst = false;
+#ifdef CONFIG_FB_SIS_300
+  unsigned short crt2crtc = 0;
+#endif
+#ifdef CONFIG_FB_SIS_315
+  unsigned short pushcx;
+#endif
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+#ifdef CONFIG_FB_SIS_300
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+#endif
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef CONFIG_FB_SIS_300
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+#endif
+  }
+
+  /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
+  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
+     islvds = true;
+  }
+
+  /* is really sis if sis bridge, but not 301B-DH */
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+     issis = true;
+  }
+
+  if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
+     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+        chkdclkfirst = true;
+     }
+  }
+
+#ifdef CONFIG_FB_SIS_315
+  if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+     if(IS_SIS330) {
+        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+     } else if(IS_SIS740) {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+        }
+     } else {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
+	   if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
+	      if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
+	         (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+	         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
+	      }
+	   }
+        }
+     }
+  }
+#endif
+
+  /* Horizontal */
+
+  tempax = SiS_Pr->SiS_LCDHDES;
+  if(islvds) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+	if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
+	   if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
+	      (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+	      tempax -= 8;
+	   }
+	}
+     }
+  }
+
+  temp = (tempax & 0x0007);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);			/* BPLHDESKEW[2:0]   */
+  temp = (tempax >> 3) & 0x00FF;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);			/* BPLHDESKEW[10:3]  */
+
+  tempbx = SiS_Pr->SiS_HDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        tempbx = SiS_Pr->PanelXRes;
+     }
+     if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
+        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
+        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
+        tempbx >>= 1;
+     }
+  }
+
+  tempax += tempbx;
+  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
+
+  temp = tempax;
+  if(temp & 0x07) temp += 8;
+  temp >>= 3;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);			/* BPLHDEE  */
+
+  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
+     }
+  }
+
+  tempcx += tempax;
+  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
+
+  temp = (tempcx >> 3) & 0x00FF;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	   switch(ModeNo) {
+	   case 0x04:
+	   case 0x05:
+	   case 0x0d: temp = 0x56; break;
+	   case 0x10: temp = 0x60; break;
+	   case 0x13: temp = 0x5f; break;
+	   case 0x40:
+	   case 0x41:
+	   case 0x4f:
+	   case 0x43:
+	   case 0x44:
+	   case 0x62:
+	   case 0x56:
+	   case 0x53:
+	   case 0x5d:
+	   case 0x5e: temp = 0x54; break;
+	   }
+	}
+     }
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);			/* BPLHRS */
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     temp += 2;
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	temp += 8;
+	if(SiS_Pr->PanelHRE != 999) {
+	   temp = tempcx + SiS_Pr->PanelHRE;
+	   if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
+	   temp >>= 3;
+	}
+     }
+  } else {
+     temp += 10;
+  }
+
+  temp &= 0x1F;
+  temp |= ((tempcx & 0x07) << 5);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);			/* BPLHRE */
+
+  /* Vertical */
+
+  tempax = SiS_Pr->SiS_VGAVDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	tempax = SiS_Pr->PanelYRes;
+     }
+  }
+
+  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
+  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
+
+  push2 = tempbx;
+
+  tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
+  if(SiS_Pr->ChipType < SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+	if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
+	}
+     }
+  }
+  if(islvds) tempcx >>= 1;
+  else       tempcx >>= 2;
+
+  if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+      (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) 		    &&
+      (SiS_Pr->PanelVRS != 999) ) {
+     tempcx = SiS_Pr->PanelVRS;
+     tempbx += tempcx;
+     if(issis) tempbx++;
+  } else {
+     tempbx += tempcx;
+     if(SiS_Pr->ChipType < SIS_315H) tempbx++;
+     else if(issis)                   tempbx++;
+  }
+
+  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
+
+  temp = tempbx & 0x00FF;
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	if(ModeNo == 0x10) temp = 0xa9;
+     }
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);			/* BPLVRS */
+
+  tempcx >>= 3;
+  tempcx++;
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
+     }
+  }
+
+  tempcx += tempbx;
+  temp = tempcx & 0x000F;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);	/* BPLVRE  */
+
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
+     if(SiS_Pr->SiS_HDE != 640) {
+        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
+     }
+  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
+  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
+  tempbx = 0x87;
+  if((SiS_Pr->ChipType >= SIS_315H) ||
+     (SiS_Pr->ChipRevision >= 0x30)) {
+     tempbx = 0x07;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
+     }
+     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
+     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
+	} else {
+	   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
+	}
+     }
+  }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
+
+  tempbx = push2;						/* BPLVDEE */
+
+  tempcx = SiS_Pr->SiS_LCDVDES;					/* BPLVDES */
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:
+	tempbx = SiS_Pr->SiS_VGAVDE - 1;
+	tempcx = SiS_Pr->SiS_VGAVDE;
+	break;
+     case Panel_800x600:
+	if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+	   if(resinfo == SIS_RI_800x600) tempcx++;
+	}
+	break;
+     case Panel_1024x600:
+	if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+	   if(resinfo == SIS_RI_1024x600) tempcx++;
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	      if(resinfo == SIS_RI_800x600) tempcx++;
+	   }
+	}
+	break;
+     case Panel_1024x768:
+	if(SiS_Pr->ChipType < SIS_315H) {
+	   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+	      if(resinfo == SIS_RI_1024x768) tempcx++;
+	   }
+	}
+	break;
+     }
+  }
+
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp |= ((tempcx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
+
+  /* Vertical scaling */
+
+  if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300      /* 300 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 6;
+     temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
+     tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
+     if(temp) tempeax++;
+
+     if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
+
+     temp = (unsigned short)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      	/* BPLVCFACT */
+     tempvcfact = temp;
+#endif /* CONFIG_FB_SIS_300 */
+
+  } else {
+
+#ifdef CONFIG_FB_SIS_315  /* 315 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 18;
+     tempebx = SiS_Pr->SiS_VDE;
+     temp = (tempeax % tempebx);
+     tempeax = tempeax / tempebx;
+     if(temp) tempeax++;
+     tempvcfact = tempeax;
+
+     temp = (unsigned short)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
+     temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
+     temp = (unsigned short)((tempeax & 0x00030000) >> 16);
+     if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
+
+     if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
+        temp = (unsigned short)(tempeax & 0x00FF);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
+        temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
+        temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
+        temp = 0;
+        if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
+     }
+#endif
+
+  }
+
+  /* Horizontal scaling */
+
+  tempeax = SiS_Pr->SiS_VGAHDE;		/* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
+  if(chkdclkfirst) {
+     if(modeflag & HalfDCLK) tempeax >>= 1;
+  }
+  tempebx = tempeax << 16;
+  if(SiS_Pr->SiS_HDE == tempeax) {
+     tempecx = 0xFFFF;
+  } else {
+     tempecx = tempebx / SiS_Pr->SiS_HDE;
+     if(SiS_Pr->ChipType >= SIS_315H) {
+        if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
+     }
+  }
+
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     tempeax = (tempebx / tempecx) - 1;
+  } else {
+     tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
+  }
+  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
+  temp = (unsigned short)(tempecx & 0x00FF);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
+
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
+     tempbx = (unsigned short)(tempeax & 0xFFFF);
+  } else {
+     tempeax = SiS_Pr->SiS_VGAVDE << 6;
+     tempbx = tempvcfact & 0x3f;
+     if(tempbx == 0) tempbx = 64;
+     tempeax /= tempbx;
+     tempbx = (unsigned short)(tempeax & 0xFFFF);
+  }
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
+  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
+     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
+     else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
+  }
+
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp = temp | ((tempecx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
+
+  tempecx >>= 16;						/* BPLHCFACT  */
+  if(!chkdclkfirst) {
+     if(modeflag & HalfDCLK) tempecx >>= 1;
+  }
+  temp = (unsigned short)((tempecx & 0xFF00) >> 8);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
+  temp = (unsigned short)(tempecx & 0x00FF);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
+
+#ifdef CONFIG_FB_SIS_315
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
+           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+	}
+     } else {
+        if(islvds) {
+           if(SiS_Pr->ChipType == SIS_740) {
+              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
+           } else {
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
+           }
+        }
+     }
+  }
+#endif
+
+#ifdef CONFIG_FB_SIS_300
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+     unsigned char *trumpdata;
+     int   i, j = crt2crtc;
+     unsigned char TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
+     unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
+     unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+
+     if(SiS_Pr->SiS_UseROM) {
+	trumpdata = &ROMAddr[0x8001 + (j * 80)];
+     } else {
+	if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
+	trumpdata = &SiS300_TrumpionData[j][0];
+     }
+
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
+     for(i=0; i<5; i++) {
+	SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
+     }
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	if(ModeNo == 0x13) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
+	   }
+	} else if(ModeNo == 0x10) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
+	   }
+	}
+     }
+     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
+  }
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
+     tempax = SiS_Pr->SiS_HDE;					/* Blps = lcdhdee(lcdhdes+HDE) + 64 */
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+     tempax += 64;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
+     temp = (tempax >> 8) << 3;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
+     tempax += 32;						/* Blpe = lBlps+32 */
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);		/* Bflml = 0 */
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
+
+     tempax = SiS_Pr->SiS_VDE;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+     tempax >>= 1;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
+     temp = (tempax >> 8) << 3;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
+
+     tempeax = SiS_Pr->SiS_HDE;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
+     tempeax <<= 2;			 			/* BDxFIFOSTOP = (HDE*4)/128 */
+     temp = tempeax & 0x7f;
+     tempeax >>= 7;
+     if(temp) tempeax++;
+     temp = tempeax & 0x3f;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);		/* BDxWadrst0 */
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
+
+     tempax = SiS_Pr->SiS_HDE;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+     tempax >>= 4;						/* BDxWadroff = HDE*4/8/8 */
+     pushcx = tempax;
+     temp = tempax & 0x00FF;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
+     temp = ((tempax & 0xFF00) >> 8) << 3;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
+
+     tempax = SiS_Pr->SiS_VDE;				 	/* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+     tempeax = tempax * pushcx;
+     temp = tempeax & 0xFF;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
+     temp = (tempeax & 0xFF00) >> 8;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
+     temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
+     temp = ((tempeax & 0x01000000) >> 24) << 7;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
+
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
+
+     if(SiS_Pr->SiS_IF_DEF_FSTN) {
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
+     }
+  }
+#endif  /* CONFIG_FB_SIS_315 */
+}
+
+/* Set Part 1 */
+static void
+SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex)
+{
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+  unsigned char   *ROMAddr = SiS_Pr->VirtualRomBase;
+#endif
+  unsigned short  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
+  unsigned short  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
+#ifdef CONFIG_FB_SIS_315
+  unsigned short  tempbl=0;
+#endif
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+     return;
+  }
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+  } else {
+     CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+  }
+
+  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+
+  if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
+         (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
+         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
+
+     if(SiS_Pr->ChipType < SIS_315H ) {
+#ifdef CONFIG_FB_SIS_300
+	SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
+#endif
+     } else {
+#ifdef CONFIG_FB_SIS_315
+	SiS_SetCRT2FIFO_310(SiS_Pr);
+#endif
+     }
+
+     /* 1. Horizontal setup */
+
+     if(SiS_Pr->ChipType < SIS_315H ) {
+
+#ifdef CONFIG_FB_SIS_300   /* ------------- 300 series --------------*/
+
+	temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   		  /* BTVGA2HT 0x08,0x09 */
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
+
+	temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
+
+	temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
+
+	pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
+	tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+	tempbx = pushbx + tempcx;
+	tempcx <<= 1;
+	tempcx += tempbx;
+
+	bridgeadd = 12;
+
+#endif /* CONFIG_FB_SIS_300 */
+
+     } else {
+
+#ifdef CONFIG_FB_SIS_315  /* ------------------- 315/330 series --------------- */
+
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HT 0x08,0x09 */
+	if(modeflag & HalfDCLK) {
+	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	      tempcx >>= 1;
+	   } else {
+	      tempax = SiS_Pr->SiS_VGAHDE >> 1;
+	      tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
+	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	         tempcx = SiS_Pr->SiS_HT - tempax;
+	      }
+	   }
+	}
+	tempcx--;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
+	temp = (tempcx >> 4) & 0xF0;
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
+
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HDEE 0x0A,0x0C */
+	tempbx = SiS_Pr->SiS_VGAHDE;
+	tempcx -= tempbx;
+	tempcx >>= 2;
+	if(modeflag & HalfDCLK) {
+	   tempbx >>= 1;
+	   tempcx >>= 1;
+	}
+	tempbx += 16;
+
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
+
+	pushbx = tempbx;
+	tempcx >>= 1;
+	tempbx += tempcx;
+	tempcx += tempbx;
+
+	bridgeadd = 16;
+
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   if(SiS_Pr->ChipType >= SIS_661) {
+	      if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+		 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+		 if(resinfo == SIS_RI_1280x1024) {
+		    tempcx = (tempcx & 0xff00) | 0x30;
+		 } else if(resinfo == SIS_RI_1600x1200) {
+		    tempcx = (tempcx & 0xff00) | 0xff;
+		 }
+	      }
+	   }
+        }
+
+#endif  /* CONFIG_FB_SIS_315 */
+
+     }  /* 315/330 series */
+
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+	if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CHSyncStart + bridgeadd;
+	   tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+	}
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	   unsigned char cr4, cr14, cr5, cr15;
+	   if(SiS_Pr->UseCustomMode) {
+	      cr4  = SiS_Pr->CCRT1CRTC[4];
+	      cr14 = SiS_Pr->CCRT1CRTC[14];
+	      cr5  = SiS_Pr->CCRT1CRTC[5];
+	      cr15 = SiS_Pr->CCRT1CRTC[15];
+	   } else {
+	      cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
+	      cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+	      cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
+	      cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
+	   }
+	   tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		    /* (VGAHRS-3)*8 */
+	   tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
+	   tempcx &= 0x00FF;
+	   tempcx |= (tempbx & 0xFF00);
+	   tempbx += bridgeadd;
+	   tempcx += bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+	}
+
+	if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
+	   tempbx = 1040;
+	   tempcx = 1044;   /* HWCursor bug! */
+	}
+
+     }
+
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);            	  /* CRT2 Horizontal Retrace Start */
+
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
+
+     temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);		  /* Overflow */
+
+     /* 2. Vertical setup */
+
+     tempcx = SiS_Pr->SiS_VGAVT - 1;
+     temp = tempcx & 0x00FF;
+
+     if(SiS_Pr->ChipType < SIS_661) {
+        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	   if(SiS_Pr->ChipType < SIS_315H) {
+	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
+	            temp--;
+	         }
+	      }
+	   } else {
+	      temp--;
+	   }
+	} else if(SiS_Pr->ChipType >= SIS_315H) {
+	   temp--;
+	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
+
+     tempbx = SiS_Pr->SiS_VGAVDE - 1;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
+
+     temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
+
+     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+	tempbx++;
+	tempax = tempbx;
+	tempcx++;
+	tempcx -= tempax;
+	tempcx >>= 2;
+	tempbx += tempcx;
+	if(tempcx < 4) tempcx = 4;
+	tempcx >>= 2;
+	tempcx += tempbx;
+	tempcx++;
+     } else {
+	tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
+	tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
+     }
+
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CVSyncStart;
+	   tempcx = SiS_Pr->CVSyncEnd;
+	}
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	   unsigned char cr8, cr7, cr13;
+	   if(SiS_Pr->UseCustomMode) {
+	      cr8    = SiS_Pr->CCRT1CRTC[8];
+	      cr7    = SiS_Pr->CCRT1CRTC[7];
+	      cr13   = SiS_Pr->CCRT1CRTC[13];
+	      tempcx = SiS_Pr->CCRT1CRTC[9];
+	   } else {
+	      cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
+	      cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+	      cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+	      tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
+	   }
+	   tempbx = cr8;
+	   if(cr7  & 0x04) tempbx |= 0x0100;
+	   if(cr7  & 0x80) tempbx |= 0x0200;
+	   if(cr13 & 0x08) tempbx |= 0x0400;
+	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
+
+     temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
+
+     /* 3. Panel delay compensation */
+
+     if(SiS_Pr->ChipType < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300  /* ---------- 300 series -------------- */
+
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   temp = 0x20;
+	   if(SiS_Pr->ChipType == SIS_300) {
+	      temp = 0x10;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_VBType & VB_SIS301) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 	    temp = 0x08;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	    temp = 0x2c;
+	      else 					    temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+		 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
+		    temp = ROMAddr[0x221];
+		 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
+		    temp = ROMAddr[0x222];
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
+		    temp = ROMAddr[0x223];
+		 else
+		    temp = ROMAddr[0x224];
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC;
+	   }
+
+	} else {
+	   temp = 0x20;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
+	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+	         temp = ROMAddr[0x220];
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
+	   }
+	}
+
+	temp &= 0x3c;
+
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+
+#endif  /* CONFIG_FB_SIS_300 */
+
+     } else {
+
+#ifdef CONFIG_FB_SIS_315   /* --------------- 315/330 series ---------------*/
+
+	if(SiS_Pr->ChipType < SIS_661) {
+
+	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+
+	      if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
+	      else 		              temp = 0x00;
+
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
+	      tempbl = 0xF0;
+	      if(SiS_Pr->ChipType == SIS_650) {
+		 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+		    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
+		 }
+	      }
+
+	      if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
+		 temp = 0x08;
+		 tempbl = 0;
+		 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+		    if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
+		 }
+	      }
+
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);	    /* Panel Link Delay Compensation */
+	   }
+
+	} /* < 661 */
+
+	tempax = 0;
+	if(modeflag & DoubleScanMode) tempax |= 0x80;
+	if(modeflag & HalfDCLK)       tempax |= 0x40;
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
+
+#endif  /* CONFIG_FB_SIS_315 */
+
+     }
+
+  }  /* Slavemode */
+
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+	/* For 301BDH with LCD, we set up the Panel Link */
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+     } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+     }
+  } else {
+     if(SiS_Pr->ChipType < SIS_315H) {
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+     } else {
+	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	   if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
+	   }
+	} else {
+	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
+	}
+     }
+  }
+}
+
+/*********************************************/
+/*         SET PART 2 REGISTER GROUP         */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_315
+static unsigned char *
+SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
+{
+   const unsigned char *tableptr = NULL;
+   unsigned short      a, b, p = 0;
+
+   a = SiS_Pr->SiS_VGAHDE;
+   b = SiS_Pr->SiS_HDE;
+   if(tabletype) {
+      a = SiS_Pr->SiS_VGAVDE;
+      b = SiS_Pr->SiS_VDE;
+   }
+
+   if(a < b) {
+      tableptr = SiS_Part2CLVX_1;
+   } else if(a == b) {
+      tableptr = SiS_Part2CLVX_2;
+   } else {
+      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	 tableptr = SiS_Part2CLVX_4;
+      } else {
+	 tableptr = SiS_Part2CLVX_3;
+      }
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	tableptr = SiS_Part2CLVX_3;
+	 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) 	tableptr = SiS_Part2CLVX_3;
+	 else 				         	tableptr = SiS_Part2CLVX_5;
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	 tableptr = SiS_Part2CLVX_6;
+      }
+      do {
+	 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
+	 p += 0x42;
+      } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
+      if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
+   }
+   p += 2;
+   return ((unsigned char *)&tableptr[p]);
+}
+
+static void
+SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+	      	    unsigned short RefreshRateTableIndex)
+{
+   unsigned char *tableptr;
+   unsigned char temp;
+   int i, j;
+
+   if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
+
+   tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
+   for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
+   }
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+      tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
+      for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
+         SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
+      }
+   }
+   temp = 0x10;
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
+}
+
+static bool
+SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
+		    unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
+		    unsigned short *ResIndex)
+{
+
+  if(SiS_Pr->ChipType < SIS_315H) return false;
+
+  if(ModeNo <= 0x13)
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  else
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+  (*ResIndex) &= 0x3f;
+  (*CRT2Index) = 0;
+
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+        (*CRT2Index) = 200;
+     }
+  }
+
+  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
+     }
+  }
+  return (((*CRT2Index) != 0));
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_300
+static void
+SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
+{
+   unsigned short tempcx;
+   static const unsigned char atable[] = {
+       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
+       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
+   };
+
+   if(!SiS_Pr->UseCustomMode) {
+      if( ( ( (SiS_Pr->ChipType == SIS_630) ||
+	      (SiS_Pr->ChipType == SIS_730) ) &&
+	    (SiS_Pr->ChipRevision > 2) )  &&
+	  (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
+	  (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
+	  (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+	 if(ModeNo == 0x13) {
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+	 } else if((crt2crtc & 0x3F) == 4) {
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+	 }
+      }
+
+      if(SiS_Pr->ChipType < SIS_315H) {
+	 if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+	    crt2crtc &= 0x1f;
+	    tempcx = 0;
+	    if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+		  tempcx += 7;
+	       }
+	    }
+	    tempcx += crt2crtc;
+	    if(crt2crtc >= 4) {
+	       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
+	    }
+
+	    if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+		  if(crt2crtc == 4) {
+		     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
+		  }
+	       }
+	    }
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
+	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
+	 }
+      }
+   }
+}
+
+/* For ECS A907. Highly preliminary. */
+static void
+SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
+		    unsigned short ModeNo)
+{
+  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
+  unsigned short crt2crtc, resindex;
+  int i, j;
+
+  if(SiS_Pr->ChipType != SIS_300) return;
+  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
+  if(SiS_Pr->UseCustomMode) return;
+
+  if(ModeNo <= 0x13) {
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else {
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+  }
+
+  resindex = crt2crtc & 0x3F;
+  if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
+  else                                    CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
+
+  /* The BIOS code (1.16.51,56) is obviously a fragment! */
+  if(ModeNo > 0x13) {
+     CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
+     resindex = 4;
+  }
+
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
+  for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+  }
+  for(j = 0x1c; j <= 0x1d; i++, j++ ) {
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+  }
+  for(j = 0x1f; j <= 0x21; i++, j++ ) {
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
+}
+#endif
+
+static void
+SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
+  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
+
+  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+     if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+        const unsigned char specialtv[] = {
+		0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
+		0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
+		0x58,0xe4,0x73,0xda,0x13
+	};
+	int i, j;
+	for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
+	if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
+	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
+	   } else {
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
+	   }
+	}
+     }
+  } else {
+     if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
+        (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
+     } else {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
+     }
+  }
+}
+
+static void
+SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+  unsigned short temp;
+
+  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+     if(SiS_Pr->SiS_VGAVDE == 525) {
+	temp = 0xc3;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
+     } else if(SiS_Pr->SiS_VGAVDE == 420) {
+	temp = 0x4d;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+     }
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
+	if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
+	   /* Not always for LV, see SetGrp2 */
+	}
+	temp = 1;
+	if(ModeNo <= 0x13) temp = 3;
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
+     }
+#if 0
+     /* 651+301C, for 1280x768 - do I really need that? */
+     if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
+        if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+	   if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
+	      ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
+	      SiS_SetReg(SiS_Part2Port,0x01,0x2b);
+	      SiS_SetReg(SiS_Part2Port,0x02,0x13);
+	      SiS_SetReg(SiS_Part2Port,0x04,0xe5);
+	      SiS_SetReg(SiS_Part2Port,0x05,0x08);
+	      SiS_SetReg(SiS_Part2Port,0x06,0xe2);
+	      SiS_SetReg(SiS_Part2Port,0x1c,0x21);
+	      SiS_SetReg(SiS_Part2Port,0x1d,0x45);
+	      SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x20,0x00);
+	      SiS_SetReg(SiS_Part2Port,0x21,0xa9);
+	      SiS_SetReg(SiS_Part2Port,0x23,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x25,0x04);
+	   }
+	}
+     }
+#endif
+  }
+}
+
+static void
+SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex)
+{
+  unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
+  unsigned short push2, modeflag, crt2crtc, bridgeoffset;
+  unsigned int   longtemp, PhaseIndex;
+  bool           newtvphase;
+  const unsigned char *TimingPoint;
+#ifdef CONFIG_FB_SIS_315
+  unsigned short resindex, CRT2Index;
+  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
+#endif
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     crt2crtc = 0;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+  }
+
+  temp = 0;
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
+
+  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) 	      temp |= 0x10;
+
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
+
+  PhaseIndex  = 0x01; /* SiS_PALPhase */
+  TimingPoint = SiS_Pr->SiS_PALTiming;
+
+  newtvphase = false;
+  if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+      ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+	(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+     newtvphase = true;
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+
+     TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
+     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+        TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
+        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+	   TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
+        }
+     }
+
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+
+     i = 0;
+     if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      i = 2;
+     else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
+
+     TimingPoint = &SiS_YPbPrTable[i][0];
+
+     PhaseIndex = 0x00; /* SiS_NTSCPhase */
+
+  } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+
+     if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
+
+  } else {
+
+     TimingPoint = SiS_Pr->SiS_NTSCTiming;
+     PhaseIndex  = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00;	/* SiS_PALPhase : SiS_NTSCPhase */
+     if(newtvphase) PhaseIndex += 8;					/* SiS_PALPhase2 : SiS_NTSCPhase2 */
+
+  }
+
+  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
+     PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03;	/* SiS_PALMPhase : SiS_PALNPhase */
+     if(newtvphase) PhaseIndex += 8;					/* SiS_PALMPhase2 : SiS_PALNPhase2 */
+  }
+
+  if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+     if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+        PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
+     } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
+        PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
+     } else {
+        PhaseIndex = 0x10; /* SiS_SpecialPhase */
+     }
+  }
+
+  for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
+  }
+
+  for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
+  }
+  for(i = 0x39; i <= 0x45; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+     if(SiS_Pr->SiS_ModeType != ModeText) {
+        SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
+     }
+  }
+
+  SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
+
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)	tempax = 950;
+  else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  tempax = 680;
+  else if(SiS_Pr->SiS_TVMode & TVSetPAL)	tempax = 520;
+  else						tempax = 440; /* NTSC, YPbPr 525 */
+
+  if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
+      ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
+        ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
+
+     tempax -= SiS_Pr->SiS_VDE;
+     tempax >>= 1;
+     if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
+        tempax >>= 1;
+     }
+     tempax &= 0x00ff;
+
+     temp = tempax + (unsigned short)TimingPoint[0];
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
+
+     temp = tempax + (unsigned short)TimingPoint[1];
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
+
+     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
+        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
+        } else {
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
+        }
+     }
+
+  }
+
+  tempcx = SiS_Pr->SiS_HT;
+  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
+  tempcx--;
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
+
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
+  tempcx += 7;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
+
+  tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
+  tempbx += tempcx;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
+
+  tempbx += 8;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     tempbx -= 4;
+     tempcx = tempbx;
+  }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
+
+  j += 2;
+  tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
+
+  tempcx += 8;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
+
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
+  j += 2;
+  tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
+
+  tempcx -= 11;
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+     tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
+
+  tempbx = SiS_Pr->SiS_VDE;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
+  } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+             (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
+     tempbx >>= 1;
+     if(SiS_Pr->ChipType >= SIS_315H) {
+        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+	   if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
+	} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	   if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	      if(crt2crtc == 4) tempbx++;
+	   }
+	}
+     }
+     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	   if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
+	}
+	if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+	   if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
+        }
+     }
+  }
+  tempbx -= 2;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
+
+  temp = (tempcx >> 8) & 0x0F;
+  temp |= ((tempbx >> 2) & 0xC0);
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
+     temp |= 0x10;
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
+
+  if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
+  }
+
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+     tempbx = SiS_Pr->SiS_VDE;
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
+        tempbx >>= 1;
+     }
+     tempbx -= 3;
+     temp = ((tempbx >> 3) & 0x60) | 0x18;
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
+
+     if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
+     }
+  }
+
+  tempbx = 0;
+  if(!(modeflag & HalfDCLK)) {
+     if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
+        tempax = 0;
+        tempbx |= 0x20;
+     }
+  }
+
+  tempch = tempcl = 0x01;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+     if(SiS_Pr->SiS_VGAHDE >= 960) {
+        if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
+	   tempcl = 0x20;
+	   if(SiS_Pr->SiS_VGAHDE >= 1280) {
+              tempch = 20;
+              tempbx &= ~0x20;
+           } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
+              tempch = 25;
+           } else {
+	      tempch = 25; /* OK */
+	   }
+        }
+     }
+  }
+
+  if(!(tempbx & 0x20)) {
+     if(modeflag & HalfDCLK) tempcl <<= 1;
+     longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
+     tempax = longtemp / SiS_Pr->SiS_HDE;
+     if(longtemp % SiS_Pr->SiS_HDE) tempax++;
+     tempbx |= ((tempax >> 8) & 0x1F);
+     tempcx = tempax >> 13;
+  }
+
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
+
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+
+     tempcx &= 0x07;
+     if(tempbx & 0x20) tempcx = 0;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
+
+     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+        tempbx = 0x0382;
+        tempcx = 0x007e;
+     } else {
+        tempbx = 0x0369;
+        tempcx = 0x0061;
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
+     temp = (tempcx & 0x0300) >> 6;
+     temp |= ((tempbx >> 8) & 0x03);
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+        temp |= 0x10;
+	if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)      temp |= 0x20;
+	else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
+
+     temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
+
+     SiS_SetTVSpecial(SiS_Pr, ModeNo);
+
+     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
+        temp = 0;
+        if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
+     }
+
+  }
+
+  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+     if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
+        temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
+     }
+     SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
+     }
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
+
+  /* From here: Part2 LCD setup */
+
+  tempbx = SiS_Pr->SiS_HDE;
+  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
+  tempbx--;			         	/* RHACTE = HDE - 1 */
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
+
+  temp = 0x01;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+     if(SiS_Pr->SiS_ModeType == ModeEGA) {
+        if(SiS_Pr->SiS_VGAHDE >= 1024) {
+           temp = 0x02;
+           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+              temp = 0x01;
+	   }
+        }
+     }
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
+
+  tempbx = SiS_Pr->SiS_VDE - 1;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
+
+  tempcx = SiS_Pr->SiS_VT - 1;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
+  temp = (tempcx >> 3) & 0xE0;
+  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+     /* Enable dithering; only do this for 32bpp mode */
+     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
+        temp |= 0x10;
+     }
+  }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
+
+  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
+  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
+
+  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
+  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
+
+#ifdef CONFIG_FB_SIS_315
+  if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
+                          			&CRT2Index, &resindex)) {
+      switch(CRT2Index) {
+        case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
+	default:
+        case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
+      }
+
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
+      for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+      }
+      for(j = 0x1c; j <= 0x1d; i++, j++ ) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+      }
+      for(j = 0x1f; j <= 0x21; i++, j++ ) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+      }
+      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
+
+      SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
+
+  } else {
+#endif
+
+    /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
+    /*             Clevo dual-link 1024x768 */
+    /* 		   Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
+    /*		   Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
+
+    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
+          tempbx = SiS_Pr->SiS_VDE - 1;
+          tempcx = SiS_Pr->SiS_VT - 1;
+       } else {
+          tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+	  tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+       }
+    } else {
+       tempbx = SiS_Pr->PanelYRes;
+       tempcx = SiS_Pr->SiS_VT;
+       tempax = 1;
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          tempax = SiS_Pr->PanelYRes;
+	  /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
+          if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
+             tempax = tempcx = 0;
+          } else {
+             tempax -= SiS_Pr->SiS_VDE;
+          }
+          tempax >>= 1;
+       }
+       tempcx -= tempax; /* lcdvdes */
+       tempbx -= tempax; /* lcdvdee */
+    }
+
+    /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);	/* lcdvdes  */
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);	/* lcdvdee  */
+
+    temp = (tempbx >> 5) & 0x38;
+    temp |= ((tempcx >> 8) & 0x07);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
+
+    tempax = SiS_Pr->SiS_VDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       tempax = SiS_Pr->PanelYRes;
+    }
+    tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+	  tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
+       }
+    }
+
+    tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
+    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
+             tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
+	     if(tempax % 4) { tempax >>= 2; tempax++; }
+	     else           { tempax >>= 2;           }
+             tempbx -= (tempax - 1);
+	  } else {
+	     tempbx -= 10;
+	     if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
+	  }
+       }
+    }
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+       tempbx++;
+       if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
+          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+	     tempbx = 770;
+	     tempcx = 3;
+	  }
+       }
+    }
+
+    /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
+
+    if(SiS_Pr->UseCustomMode) {
+       tempbx = SiS_Pr->CVSyncStart;
+    }
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);	    /* lcdvrs */
+
+    temp = (tempbx >> 4) & 0xF0;
+    tempbx += (tempcx + 1);
+    temp |= (tempbx & 0x0F);
+
+    if(SiS_Pr->UseCustomMode) {
+       temp &= 0xf0;
+       temp |= (SiS_Pr->CVSyncEnd & 0x0f);
+    }
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
+
+#ifdef CONFIG_FB_SIS_300
+    SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
+#endif
+
+    bridgeoffset = 7;
+    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)	bridgeoffset += 2;
+    if(SiS_Pr->SiS_VBType & VB_SIS30xCLV)	bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
+    if(SiS_IsDualLink(SiS_Pr))			bridgeoffset++;
+    else if(SiS_Pr->SiS_VBType & VB_SIS302LV)	bridgeoffset++;    /* OK for Asus A4L 1280x800 */
+    /* Higher bridgeoffset shifts to the LEFT */
+
+    temp = 0;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+	  temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+	  if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
+       }
+    }
+    temp += bridgeoffset;
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	     /* lcdhdes */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
+
+    tempcx = SiS_Pr->SiS_HT;
+    tempax = tempbx = SiS_Pr->SiS_HDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+          tempax = SiS_Pr->PanelXRes;
+          tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+       }
+    }
+    if(SiS_IsDualLink(SiS_Pr)) {
+       tempcx >>= 1;
+       tempbx >>= 1;
+       tempax >>= 1;
+    }
+
+    tempbx += bridgeoffset;
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);	    /* lcdhdee */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
+
+    tempcx = (tempcx - tempax) >> 2;
+
+    tempbx += tempcx;
+    push2 = tempbx;
+
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+             if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
+	  }
+       }
+    }
+
+    if(SiS_Pr->UseCustomMode) {
+       tempbx = SiS_Pr->CHSyncStart;
+       if(modeflag & HalfDCLK) tempbx <<= 1;
+       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
+       tempbx += bridgeoffset;
+    }
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);	    /* lcdhrs */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
+
+    tempbx = push2;
+
+    tempcx <<= 1;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
+    }
+    tempbx += tempcx;
+
+    if(SiS_Pr->UseCustomMode) {
+       tempbx = SiS_Pr->CHSyncEnd;
+       if(modeflag & HalfDCLK) tempbx <<= 1;
+       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
+       tempbx += bridgeoffset;
+    }
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);	    /* lcdhre */
+
+    SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
+
+#ifdef CONFIG_FB_SIS_300
+    SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
+#endif
+#ifdef CONFIG_FB_SIS_315
+  } /* CRT2-LCD from table */
+#endif
+}
+
+/*********************************************/
+/*         SET PART 3 REGISTER GROUP         */
+/*********************************************/
+
+static void
+SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned short i;
+  const unsigned char *tempdi;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
+
+#ifndef SIS_CP
+  SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
+#else
+  SIS_CP_INIT301_CP
+#endif
+
+  if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
+     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
+  } else {
+     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
+     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
+  }
+
+  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
+     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
+     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
+  }
+
+  tempdi = NULL;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     tempdi = SiS_Pr->SiS_HiTVGroup3Data;
+     if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+        tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
+     }
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+     if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
+        tempdi = SiS_HiTVGroup3_1;
+        if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
+     }
+  }
+  if(tempdi) {
+     for(i=0; i<=0x3E; i++) {
+        SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
+     }
+     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
+	if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+	   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
+	}
+     }
+  }
+
+#ifdef SIS_CP
+  SIS_CP_INIT301_CP2
+#endif
+}
+
+/*********************************************/
+/*         SET PART 4 REGISTER GROUP         */
+/*********************************************/
+
+#ifdef CONFIG_FB_SIS_315
+#if 0
+static void
+SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
+{
+   unsigned short temp, temp1, temp2;
+
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
+   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
+   temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
+   temp = (unsigned short)((int)(temp) + shift);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
+   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
+}
+#endif
+
+static void
+SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short temp, temp1, resinfo = 0;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+
+   if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
+   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
+
+   if(SiS_Pr->ChipType >= XGI_20) return;
+
+   if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
+      if(!(ROMAddr[0x61] & 0x04)) return;
+   }
+
+   if(ModeNo > 0x13) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
+
+   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
+   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
+   if(!(temp & 0x01)) {
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
+      if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
+         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
+      }
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
+      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
+      else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
+      else					   temp = 0x0402;
+      if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+         temp1 = 0;
+	 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
+	 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+	 if(ModeNo > 0x13) {
+            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
+         }
+      } else {
+         temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
+	 if(temp1 == 0x01) temp |= 0x01;
+	 if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+	 if(ModeNo > 0x13) {
+            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
+         }
+      }
+
+#if 0
+      if(SiS_Pr->ChipType >= SIS_661) { 		/* ? */
+         if(SiS_Pr->SiS_TVMode & TVAspect43) {
+            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	       if(resinfo == SIS_RI_1024x768) {
+	          SiS_ShiftXPos(SiS_Pr, 97);
+	       } else {
+	          SiS_ShiftXPos(SiS_Pr, 111);
+	       }
+	    } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+	       SiS_ShiftXPos(SiS_Pr, 136);
+	    }
+         }
+      }
+#endif
+
+   }
+
+}
+#endif
+
+static void
+SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                 unsigned short RefreshRateTableIndex)
+{
+  unsigned short vclkindex, temp, reg1, reg2;
+
+  if(SiS_Pr->UseCustomMode) {
+     reg1 = SiS_Pr->CSR2B;
+     reg2 = SiS_Pr->CSR2C;
+  } else {
+     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+     reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
+     reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
+  }
+
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+     if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
+ 	SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
+	SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
+     } else {
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
+     }
+  } else {
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
+  temp = 0x08;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
+  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
+}
+
+static void
+SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
+{
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+	if((SiS_CRT2IsLCD(SiS_Pr)) ||
+	   (SiS_IsVAMode(SiS_Pr))) {
+	   if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
+	      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
+	   } else {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
+	   }
+	}
+     }
+  }
+  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
+     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+  }
+}
+
+static void
+SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex)
+{
+  unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
+  unsigned int   tempebx, tempeax, templong;
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+  }
+
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
+	}
+     }
+  }
+
+  if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
+     }
+  }
+
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	SiS_SetDualLinkEtc(SiS_Pr);
+	return;
+     }
+  }
+
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
+
+  tempbx = SiS_Pr->SiS_RVBHCMAX;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
+
+  temp = (tempbx >> 1) & 0x80;
+
+  tempcx = SiS_Pr->SiS_VGAHT - 1;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
+
+  temp |= ((tempcx >> 5) & 0x78);
+
+  tempcx = SiS_Pr->SiS_VGAVT - 1;
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
+
+  temp |= ((tempcx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
+
+  tempbx = SiS_Pr->SiS_VGAHDE;
+  if(modeflag & HalfDCLK)    tempbx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     temp = 0;
+     if(tempbx > 800)        temp = 0x60;
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     temp = 0;
+     if(tempbx > 1024)       temp = 0xC0;
+     else if(tempbx >= 960)  temp = 0xA0;
+  } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+     temp = 0;
+     if(tempbx >= 1280)      temp = 0x40;
+     else if(tempbx >= 1024) temp = 0x20;
+  } else {
+     temp = 0x80;
+     if(tempbx >= 1024)      temp = 0xA0;
+  }
+
+  temp |= SiS_Pr->Init_P4_0E;
+
+  if(SiS_Pr->SiS_VBType & VB_SIS301) {
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+        temp &= 0xf0;
+        temp |= 0x0A;
+     }
+  }
+
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
+
+  tempeax = SiS_Pr->SiS_VGAVDE;
+  tempebx = SiS_Pr->SiS_VDE;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     if(!(temp & 0xE0)) tempebx >>=1;
+  }
+
+  tempcx = SiS_Pr->SiS_RVBHRS;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
+  tempcx >>= 8;
+  tempcx |= 0x40;
+
+  if(tempeax <= tempebx) {
+     tempcx ^= 0x40;
+  } else {
+     tempeax -= tempebx;
+  }
+
+  tempeax *= (256 * 1024);
+  templong = tempeax % tempebx;
+  tempeax /= tempebx;
+  if(templong) tempeax++;
+
+  temp = (unsigned short)(tempeax & 0x000000FF);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
+  temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
+  temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
+  temp |= (tempcx & 0x4F);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
+
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
+
+     /* Calc Linebuffer max address and set/clear decimode */
+     tempbx = 0;
+     if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
+     tempax = SiS_Pr->SiS_VGAHDE;
+     if(modeflag & HalfDCLK)    tempax >>= 1;
+     if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
+     if(tempax > 800) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	   tempax -= 800;
+	} else {
+	   tempbx = 0x08;
+	   if(tempax == 960)	   tempax *= 25; /* Correct */
+           else if(tempax == 1024) tempax *= 25;
+           else			   tempax *= 20;
+	   temp = tempax % 32;
+	   tempax /= 32;
+	   if(temp) tempax++;
+	   tempax++;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	      if(resinfo == SIS_RI_1024x768 ||
+	         resinfo == SIS_RI_1024x576 ||
+		 resinfo == SIS_RI_1280x1024 ||
+		 resinfo == SIS_RI_1280x720) {
+	         /* Otherwise white line or garbage at right edge */
+	         tempax = (tempax & 0xff00) | 0x20;
+	      }
+	   }
+	}
+     }
+     tempax--;
+     temp = ((tempax >> 4) & 0x30) | tempbx;
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
+
+     temp = 0x0036; tempbx = 0xD0;
+     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+	temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
+     }
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+        if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
+	   temp |= 0x01;
+	   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+	      if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
+  	         temp &= ~0x01;
+	      }
+	   }
+	}
+     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
+
+     tempbx = SiS_Pr->SiS_HT >> 1;
+     if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
+     tempbx -= 2;
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
+     temp = (tempbx >> 5) & 0x38;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
+
+     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
+	   /* LCD-too-dark-error-source, see FinalizeLCD() */
+	}
+     }
+
+     SiS_SetDualLinkEtc(SiS_Pr);
+
+  }  /* 301B */
+
+  SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+}
+
+/*********************************************/
+/*         SET PART 5 REGISTER GROUP         */
+/*********************************************/
+
+static void
+SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
+
+  if(SiS_Pr->SiS_ModeType == ModeVGA) {
+     if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+        SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
+     }
+  }
+}
+
+/*********************************************/
+/*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
+/*********************************************/
+
+static bool
+SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		   unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
+		   unsigned short *DisplayType)
+ {
+  unsigned short modeflag = 0;
+  bool checkhd = true;
+
+  /* Pass 1:1 not supported here */
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+  }
+
+  (*ResIndex) &= 0x3F;
+
+  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+     (*DisplayType) = 80;
+     if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+      	(*DisplayType) = 82;
+	if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	   if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
+	}
+     }
+     if((*DisplayType) != 84) {
+        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+     }
+
+  } else {
+
+     (*DisplayType = 0);
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_320x240_1: (*DisplayType) = 50;
+			   checkhd = false;
+			   break;
+     case Panel_320x240_2: (*DisplayType) = 14;
+			   break;
+     case Panel_320x240_3: (*DisplayType) = 18;
+			   break;
+     case Panel_640x480:   (*DisplayType) = 10;
+			   break;
+     case Panel_1024x600:  (*DisplayType) = 26;
+			   break;
+     default: return true;
+     }
+
+     if(checkhd) {
+        if(modeflag & HalfDCLK) (*DisplayType)++;
+     }
+
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
+     }
+
+  }
+
+  return true;
+}
+
+static void
+SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                unsigned short RefreshRateTableIndex)
+{
+  unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
+  const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
+  static const unsigned short CRIdx[] = {
+	0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
+	0x07, 0x10, 0x11, 0x15, 0x16
+  };
+
+  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+     (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+     (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
+     (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
+     return;
+
+  if(SiS_Pr->SiS_IF_DEF_LVDS) {
+     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+     }
+  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+  } else return;
+
+  if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+  if(SiS_Pr->ChipType < SIS_315H) {
+     if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
+  }
+
+  if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
+                          &ResIndex, &DisplayType))) {
+     return;
+  }
+
+  switch(DisplayType) {
+    case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1;           break; /* xSTN */
+    case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2;           break; /* xSTN */
+    case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H;         break; /* xSTN */
+    case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3;           break; /* xSTN */
+    case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H;         break; /* xSTN */
+    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
+    case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
+#if 0 /* Works better with calculated numbers */
+    case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
+    case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
+    case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
+    case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
+#endif
+    case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
+    case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
+    case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
+    case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
+    case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
+  }
+
+  if(LVDSCRT1Ptr) {
+
+     SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+     for(i = 0; i <= 10; i++) {
+        tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
+        SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
+     }
+
+     for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
+        tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+        SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
+     }
+
+     tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
+
+     if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+     tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
+     if(modeflag & DoubleScanMode) tempah |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+
+  } else {
+
+     SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
+
+  }
+}
+
+/*********************************************/
+/*              SET CRT2 ECLK                */
+/*********************************************/
+
+static void
+SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+           unsigned short RefreshRateTableIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short clkbase, vclkindex = 0;
+  unsigned char  sr2b, sr2c;
+
+  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
+	RefreshRateTableIndex--;
+     }
+     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+                                    RefreshRateTableIndex);
+     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+  } else {
+     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+                                    RefreshRateTableIndex);
+  }
+
+  sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
+  sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
+
+  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+     if(SiS_Pr->SiS_UseROM) {
+	if(ROMAddr[0x220] & 0x01) {
+	   sr2b = ROMAddr[0x227];
+	   sr2c = ROMAddr[0x228];
+	}
+     }
+  }
+
+  clkbase = 0x02B;
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+	clkbase += 3;
+     }
+  }
+
+  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
+  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
+}
+
+/*********************************************/
+/*           SET UP CHRONTEL CHIPS           */
+/*********************************************/
+
+static void
+SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
+{
+   unsigned short TVType, resindex;
+   const struct SiS_CHTVRegData *CHTVRegData = NULL;
+
+   if(ModeNo <= 0x13)
+      resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+   else
+      resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+   resindex &= 0x3F;
+
+   TVType = 0;
+   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+      TVType += 2;
+      if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	 if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
+      }
+      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	 TVType = 4;
+	 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+	 TVType = 6;
+	 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+      }
+   }
+
+   switch(TVType) {
+      case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
+      case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
+      case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
+      case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+      case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
+      case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
+      case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
+      case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
+      case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
+      default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+   }
+
+
+   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+
+#ifdef CONFIG_FB_SIS_300
+
+      /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
+
+      /* We don't support modes >800x600 */
+      if (resindex > 5) return;
+
+      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	 SiS_SetCH700x(SiS_Pr,0x04,0x43);  /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
+	 SiS_SetCH700x(SiS_Pr,0x09,0x69);  /* Black level for PAL (105)*/
+      } else {
+	 SiS_SetCH700x(SiS_Pr,0x04,0x03);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
+	 SiS_SetCH700x(SiS_Pr,0x09,0x71);   /* Black level for NTSC (113)*/
+      }
+
+      SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]);	/* Mode register */
+      SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]);	/* Start active video register */
+      SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]);	/* Position overflow register */
+      SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]);	/* Horiz Position register */
+      SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]);	/* Vertical Position register */
+
+      /* Set minimum flicker filter for Luma channel (SR1-0=00),
+                minimum text enhancement (S3-2=10),
+   	        maximum flicker filter for Chroma channel (S5-4=10)
+	        =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
+       */
+      SiS_SetCH700x(SiS_Pr,0x01,0x28);
+
+      /* Set video bandwidth
+            High bandwidth Luma composite video filter(S0=1)
+            low bandwidth Luma S-video filter (S2-1=00)
+	    disable peak filter in S-video channel (S3=0)
+	    high bandwidth Chroma Filter (S5-4=11)
+	    =00110001=0x31
+      */
+      SiS_SetCH700x(SiS_Pr,0x03,0xb1);       /* old: 3103 */
+
+      /* Register 0x3D does not exist in non-macrovision register map
+            (Maybe this is a macrovision register?)
+       */
+#ifndef SIS_CP
+      SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
+#endif
+
+      /* Register 0x10 only contains 1 writable bit (S0) for sensing,
+             all other bits a read-only. Macrovision?
+       */
+      SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
+
+      /* Register 0x11 only contains 3 writable bits (S0-S2) for
+             contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
+       */
+      SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
+
+      /* Clear DSEN
+       */
+      SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
+
+      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {		/* ---- NTSC ---- */
+         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
+            if(resindex == 0x04) {   			/* 640x480 overscan: Mode 16 */
+      	       SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);	/* ACIV on, no need to set FSCI */
+            } else if(resindex == 0x05) {    		/* 800x600 overscan: Mode 23 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);	/* 0x18-0x1f: FSCI 469,762,048 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF);	/* Loop filter on for mode 23 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);	/* ACIV off, need to set FSCI */
+            }
+         } else {
+            if(resindex == 0x04) {     			/* ----- 640x480 underscan; Mode 17 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+            } else if(resindex == 0x05) {   		/* ----- 800x600 underscan: Mode 24 */
+#if 0
+               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);	/* (FSCI was 0x1f1c71c7 - this is for mode 22) */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0);	/* FSCI for mode 24 is 428,554,851 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0);       /* 198b3a63 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off for mode 24 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);	* ACIV off, need to set FSCI */
+#endif         /* All alternatives wrong (datasheet wrong?), don't use FSCI */
+	       SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	 /* loop filter off */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+            }
+         }
+      } else {						/* ---- PAL ---- */
+         /* We don't play around with FSCI in PAL mode */
+         if(resindex == 0x04) {
+            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
+            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);	/* ACIV on */
+         } else {
+            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
+            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);	/* ACIV on */
+         }
+      }
+
+#endif  /* 300 */
+
+   } else {
+
+      /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
+
+#ifdef CONFIG_FB_SIS_315
+
+      unsigned short temp;
+
+      /* We don't support modes >1024x768 */
+      if (resindex > 6) return;
+
+      temp = CHTVRegData[resindex].Reg[0];
+      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
+      SiS_SetCH701x(SiS_Pr,0x00,temp);
+
+      SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
+      SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
+      SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
+      SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
+      SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
+      SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
+
+      temp = CHTVRegData[resindex].Reg[7];
+      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
+      SiS_SetCH701x(SiS_Pr,0x07,temp);
+
+      SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
+      SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
+      SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
+      SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
+      SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
+      SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
+      SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
+      SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
+
+      temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
+      /* D1 should be set for PAL, PAL-N and NTSC-J,
+         but I won't do that for PAL unless somebody
+	 tells me to do so. Since the BIOS uses
+	 non-default CIV values and blacklevels,
+	 this might be compensated anyway.
+       */
+      if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
+      SiS_SetCH701x(SiS_Pr,0x21,temp);
+
+#endif	/* 315 */
+
+   }
+
+#ifdef SIS_CP
+   SIS_CP_INIT301_CP3
+#endif
+
+}
+
+#ifdef CONFIG_FB_SIS_315  /* ----------- 315 series only ---------- */
+
+void
+SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
+{
+   unsigned short temp;
+
+   /* Enable Chrontel 7019 LCD panel backlight */
+   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+      if(SiS_Pr->ChipType == SIS_740) {
+	 SiS_SetCH701x(SiS_Pr,0x66,0x65);
+      } else {
+	 temp = SiS_GetCH701x(SiS_Pr,0x66);
+	 temp |= 0x20;
+	 SiS_SetCH701x(SiS_Pr,0x66,temp);
+      }
+   }
+}
+
+void
+SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
+{
+   unsigned short temp;
+
+   /* Disable Chrontel 7019 LCD panel backlight */
+   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+      temp = SiS_GetCH701x(SiS_Pr,0x66);
+      temp &= 0xDF;
+      SiS_SetCH701x(SiS_Pr,0x66,temp);
+   }
+}
+
+static void
+SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
+{
+  static const unsigned char regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
+  static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
+  static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
+  static const unsigned char asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+  static const unsigned char asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+  static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+  static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+  const unsigned char *tableptr = NULL;
+  int i;
+
+  /* Set up Power up/down timing */
+
+  if(SiS_Pr->ChipType == SIS_740) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
+	else    			          tableptr = table1024_740;
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
+	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
+        else					  tableptr = table1400_740;
+     } else return;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	tableptr = table1024_650;
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
+	tableptr = table1400_650;
+     } else return;
+  }
+
+  for(i=0; i<5; i++) {
+     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
+  }
+}
+
+static void
+SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
+{
+  const unsigned char *tableptr = NULL;
+  unsigned short tempbh;
+  int i;
+  static const unsigned char regtable[] = {
+		0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
+		0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
+  };
+  static const unsigned char table1024_740[] = {
+		0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+		0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
+  };
+  static const unsigned char table1280_740[] = {
+		0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+		0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+  };
+  static const unsigned char table1400_740[] = {
+		0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+		0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+  };
+  static const unsigned char table1600_740[] = {
+		0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+		0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
+  };
+  static const unsigned char table1024_650[] = {
+		0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+		0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
+  };
+  static const unsigned char table1280_650[] = {
+		0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+		0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
+  };
+  static const unsigned char table1400_650[] = {
+		0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
+		0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
+  };
+  static const unsigned char table1600_650[] = {
+		0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+		0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
+  };
+
+  if(SiS_Pr->ChipType == SIS_740) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
+     else return;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
+     else return;
+  }
+
+  tempbh = SiS_GetCH701x(SiS_Pr,0x74);
+  if((tempbh == 0xf6) || (tempbh == 0xc7)) {
+     tempbh = SiS_GetCH701x(SiS_Pr,0x73);
+     if(tempbh == 0xc8) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
+     } else if(tempbh == 0xdb) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
+     } else if(tempbh == 0xde) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
+     }
+  }
+
+  if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
+  else     			  tempbh = 0x0c;
+
+  for(i = 0; i < tempbh; i++) {
+     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
+  }
+  SiS_ChrontelPowerSequencing(SiS_Pr);
+  tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
+  tempbh |= 0xc0;
+  SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
+
+  if(SiS_Pr->ChipType == SIS_740) {
+     tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
+     tempbh &= 0xfb;
+     SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
+     tempbh = SiS_GetCH701x(SiS_Pr,0x64);
+     tempbh |= 0x40;
+     SiS_SetCH701x(SiS_Pr,0x64,tempbh);
+     tempbh = SiS_GetCH701x(SiS_Pr,0x03);
+     tempbh &= 0x3f;
+     SiS_SetCH701x(SiS_Pr,0x03,tempbh);
+  }
+}
+
+static void
+SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
+{
+  unsigned char temp, temp1;
+
+  temp1 = SiS_GetCH701x(SiS_Pr,0x49);
+  SiS_SetCH701x(SiS_Pr,0x49,0x3e);
+  temp = SiS_GetCH701x(SiS_Pr,0x47);
+  temp &= 0x7f;	/* Use external VSYNC */
+  SiS_SetCH701x(SiS_Pr,0x47,temp);
+  SiS_LongDelay(SiS_Pr, 3);
+  temp = SiS_GetCH701x(SiS_Pr,0x47);
+  temp |= 0x80;	/* Use internal VSYNC */
+  SiS_SetCH701x(SiS_Pr,0x47,temp);
+  SiS_SetCH701x(SiS_Pr,0x49,temp1);
+}
+
+static void
+SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
+{
+  unsigned short temp;
+
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+     if(SiS_Pr->ChipType == SIS_740) {
+        temp = SiS_GetCH701x(SiS_Pr,0x1c);
+        temp |= 0x04;	/* Invert XCLK phase */
+        SiS_SetCH701x(SiS_Pr,0x1c,temp);
+     }
+     if(SiS_IsYPbPr(SiS_Pr)) {
+        temp = SiS_GetCH701x(SiS_Pr,0x01);
+	temp &= 0x3f;
+	temp |= 0x80;	/* Enable YPrPb (HDTV) */
+	SiS_SetCH701x(SiS_Pr,0x01,temp);
+     }
+     if(SiS_IsChScart(SiS_Pr)) {
+        temp = SiS_GetCH701x(SiS_Pr,0x01);
+	temp &= 0x3f;
+	temp |= 0xc0;	/* Enable SCART + CVBS */
+	SiS_SetCH701x(SiS_Pr,0x01,temp);
+     }
+     if(SiS_Pr->ChipType == SIS_740) {
+        SiS_ChrontelResetVSync(SiS_Pr);
+        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
+     } else {
+        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
+        temp = SiS_GetCH701x(SiS_Pr,0x49);
+        if(SiS_IsYPbPr(SiS_Pr)) {
+           temp = SiS_GetCH701x(SiS_Pr,0x73);
+	   temp |= 0x60;
+	   SiS_SetCH701x(SiS_Pr,0x73,temp);
+        }
+        temp = SiS_GetCH701x(SiS_Pr,0x47);
+        temp &= 0x7f;
+        SiS_SetCH701x(SiS_Pr,0x47,temp);
+        SiS_LongDelay(SiS_Pr, 2);
+        temp = SiS_GetCH701x(SiS_Pr,0x47);
+        temp |= 0x80;
+        SiS_SetCH701x(SiS_Pr,0x47,temp);
+     }
+  }
+}
+
+static void
+SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
+{
+  unsigned short temp;
+
+  /* Complete power down of LVDS */
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+     if(SiS_Pr->ChipType == SIS_740) {
+        SiS_LongDelay(SiS_Pr, 1);
+	SiS_GenericDelay(SiS_Pr, 5887);
+	SiS_SetCH701x(SiS_Pr,0x76,0xac);
+	SiS_SetCH701x(SiS_Pr,0x66,0x00);
+     } else {
+        SiS_LongDelay(SiS_Pr, 2);
+	temp = SiS_GetCH701x(SiS_Pr,0x76);
+	temp &= 0xfc;
+	SiS_SetCH701x(SiS_Pr,0x76,temp);
+	SiS_SetCH701x(SiS_Pr,0x66,0x00);
+     }
+  }
+}
+
+static void
+SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
+{
+     unsigned short temp;
+
+     if(SiS_Pr->ChipType == SIS_740) {
+
+        temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
+        temp &= 0x01;
+        if(!temp) {
+
+           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
+	      temp = SiS_GetCH701x(SiS_Pr,0x49);
+	      SiS_SetCH701x(SiS_Pr,0x49,0x3e);
+	   }
+
+	   /* Reset Chrontel 7019 datapath */
+           SiS_SetCH701x(SiS_Pr,0x48,0x10);
+           SiS_LongDelay(SiS_Pr, 1);
+           SiS_SetCH701x(SiS_Pr,0x48,0x18);
+
+	   if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
+	      SiS_ChrontelResetVSync(SiS_Pr);
+	      SiS_SetCH701x(SiS_Pr,0x49,temp);
+	   }
+
+        } else {
+
+	   /* Clear/set/clear GPIO */
+           temp = SiS_GetCH701x(SiS_Pr,0x5c);
+	   temp &= 0xef;
+	   SiS_SetCH701x(SiS_Pr,0x5c,temp);
+	   temp = SiS_GetCH701x(SiS_Pr,0x5c);
+	   temp |= 0x10;
+	   SiS_SetCH701x(SiS_Pr,0x5c,temp);
+	   temp = SiS_GetCH701x(SiS_Pr,0x5c);
+	   temp &= 0xef;
+	   SiS_SetCH701x(SiS_Pr,0x5c,temp);
+	   temp = SiS_GetCH701x(SiS_Pr,0x61);
+	   if(!temp) {
+	      SiS_SetCH701xForLCD(SiS_Pr);
+	   }
+        }
+
+     } else { /* 650 */
+        /* Reset Chrontel 7019 datapath */
+        SiS_SetCH701x(SiS_Pr,0x48,0x10);
+        SiS_LongDelay(SiS_Pr, 1);
+        SiS_SetCH701x(SiS_Pr,0x48,0x18);
+     }
+}
+
+static void
+SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
+{
+     unsigned short temp;
+
+     if(SiS_Pr->ChipType == SIS_740) {
+
+        if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
+           SiS_ChrontelResetVSync(SiS_Pr);
+        }
+
+     } else {
+
+        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* Power up LVDS block */
+        temp = SiS_GetCH701x(SiS_Pr,0x49);
+        temp &= 1;
+        if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
+	   temp = SiS_GetCH701x(SiS_Pr,0x47);
+	   temp &= 0x70;
+	   SiS_SetCH701x(SiS_Pr,0x47,temp);  /* enable VSYNC */
+	   SiS_LongDelay(SiS_Pr, 3);
+	   temp = SiS_GetCH701x(SiS_Pr,0x47);
+	   temp |= 0x80;
+	   SiS_SetCH701x(SiS_Pr,0x47,temp);  /* disable VSYNC */
+        }
+
+     }
+}
+
+static void
+SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+     unsigned short temp,temp1;
+
+     if(SiS_Pr->ChipType == SIS_740) {
+
+        temp = SiS_GetCH701x(SiS_Pr,0x61);
+        if(temp < 1) {
+           temp++;
+	   SiS_SetCH701x(SiS_Pr,0x61,temp);
+        }
+        SiS_SetCH701x(SiS_Pr,0x66,0x45);  /* Panel power on */
+        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on */
+        SiS_LongDelay(SiS_Pr, 1);
+        SiS_GenericDelay(SiS_Pr, 5887);
+
+     } else {  /* 650 */
+
+        temp1 = 0;
+        temp = SiS_GetCH701x(SiS_Pr,0x61);
+        if(temp < 2) {
+           temp++;
+	   SiS_SetCH701x(SiS_Pr,0x61,temp);
+	   temp1 = 1;
+        }
+        SiS_SetCH701x(SiS_Pr,0x76,0xac);
+        temp = SiS_GetCH701x(SiS_Pr,0x66);
+        temp |= 0x5f;
+        SiS_SetCH701x(SiS_Pr,0x66,temp);
+        if(ModeNo > 0x13) {
+           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
+	      SiS_GenericDelay(SiS_Pr, 1023);
+	   } else {
+	      SiS_GenericDelay(SiS_Pr, 767);
+	   }
+        } else {
+           if(!temp1)
+	      SiS_GenericDelay(SiS_Pr, 767);
+        }
+        temp = SiS_GetCH701x(SiS_Pr,0x76);
+        temp |= 0x03;
+        SiS_SetCH701x(SiS_Pr,0x76,temp);
+        temp = SiS_GetCH701x(SiS_Pr,0x66);
+        temp &= 0x7f;
+        SiS_SetCH701x(SiS_Pr,0x66,temp);
+        SiS_LongDelay(SiS_Pr, 1);
+
+     }
+}
+
+static void
+SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
+{
+     unsigned short temp;
+
+     SiS_LongDelay(SiS_Pr, 1);
+
+     do {
+       temp = SiS_GetCH701x(SiS_Pr,0x66);
+       temp &= 0x04;  /* PLL stable? -> bail out */
+       if(temp == 0x04) break;
+
+       if(SiS_Pr->ChipType == SIS_740) {
+          /* Power down LVDS output, PLL normal operation */
+          SiS_SetCH701x(SiS_Pr,0x76,0xac);
+       }
+
+       SiS_SetCH701xForLCD(SiS_Pr);
+
+       temp = SiS_GetCH701x(SiS_Pr,0x76);
+       temp &= 0xfb;  /* Reset PLL */
+       SiS_SetCH701x(SiS_Pr,0x76,temp);
+       SiS_LongDelay(SiS_Pr, 2);
+       temp = SiS_GetCH701x(SiS_Pr,0x76);
+       temp |= 0x04;  /* PLL normal operation */
+       SiS_SetCH701x(SiS_Pr,0x76,temp);
+       if(SiS_Pr->ChipType == SIS_740) {
+          SiS_SetCH701x(SiS_Pr,0x78,0xe0);	/* PLL loop filter */
+       } else {
+          SiS_SetCH701x(SiS_Pr,0x78,0x60);
+       }
+       SiS_LongDelay(SiS_Pr, 2);
+    } while(0);
+
+    SiS_SetCH701x(SiS_Pr,0x77,0x00);  /* MV? */
+}
+
+static void
+SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
+{
+     unsigned short temp;
+
+     temp = SiS_GetCH701x(SiS_Pr,0x03);
+     temp |= 0x80;	/* Set datapath 1 to TV   */
+     temp &= 0xbf;	/* Set datapath 2 to LVDS */
+     SiS_SetCH701x(SiS_Pr,0x03,temp);
+
+     if(SiS_Pr->ChipType == SIS_740) {
+
+        temp = SiS_GetCH701x(SiS_Pr,0x1c);
+        temp &= 0xfb;	/* Normal XCLK phase */
+        SiS_SetCH701x(SiS_Pr,0x1c,temp);
+
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
+
+        temp = SiS_GetCH701x(SiS_Pr,0x64);
+        temp |= 0x40;	/* ? Bit not defined */
+        SiS_SetCH701x(SiS_Pr,0x64,temp);
+
+        temp = SiS_GetCH701x(SiS_Pr,0x03);
+        temp &= 0x3f;	/* D1 input to both LVDS and TV */
+        SiS_SetCH701x(SiS_Pr,0x03,temp);
+
+	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
+	   SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
+	   SiS_LongDelay(SiS_Pr, 1);
+	   SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
+	   SiS_ChrontelResetDB(SiS_Pr);
+	   SiS_ChrontelDoSomething2(SiS_Pr);
+	   SiS_ChrontelDoSomething3(SiS_Pr, 0);
+	} else {
+           temp = SiS_GetCH701x(SiS_Pr,0x66);
+           if(temp != 0x45) {
+              SiS_ChrontelResetDB(SiS_Pr);
+              SiS_ChrontelDoSomething2(SiS_Pr);
+              SiS_ChrontelDoSomething3(SiS_Pr, 0);
+           }
+	}
+
+     } else { /* 650 */
+
+        SiS_ChrontelResetDB(SiS_Pr);
+        SiS_ChrontelDoSomething2(SiS_Pr);
+        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
+        SiS_ChrontelDoSomething3(SiS_Pr,temp);
+        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on, LVDS normal operation */
+
+     }
+
+}
+#endif  /* 315 series  */
+
+/*********************************************/
+/*      MAIN: SET CRT2 REGISTER GROUP        */
+/*********************************************/
+
+bool
+SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+#ifdef CONFIG_FB_SIS_300
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+#endif
+   unsigned short ModeIdIndex, RefreshRateTableIndex;
+
+   SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+
+   if(!SiS_Pr->UseCustomMode) {
+      SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
+   } else {
+      ModeIdIndex = 0;
+   }
+
+   /* Used for shifting CR33 */
+   SiS_Pr->SiS_SelectCRT2Rate = 4;
+
+   SiS_UnLockCRT2(SiS_Pr);
+
+   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+   SiS_SaveCRT2Info(SiS_Pr,ModeNo);
+
+   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+      SiS_DisableBridge(SiS_Pr);
+      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
+         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
+      }
+      SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
+   }
+
+   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+      SiS_LockCRT2(SiS_Pr);
+      SiS_DisplayOn(SiS_Pr);
+      return true;
+   }
+
+   SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+
+   /* Set up Panel Link for LVDS and LCDA */
+   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
+   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
+       ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
+      SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+   }
+
+   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+      SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+   }
+
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+
+	 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+#ifdef CONFIG_FB_SIS_315
+	 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+#endif
+	 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
+	 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+#ifdef CONFIG_FB_SIS_315
+	 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
+#endif
+	 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
+
+	 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
+
+	 /* For 301BDH (Panel link initialization): */
+	 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+
+	    if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
+	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+		  SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	       }
+            }
+	    SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	 }
+      }
+
+   } else {
+
+      SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
+
+      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
+
+      SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
+
+      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+	 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+	       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+#ifdef CONFIG_FB_SIS_315
+		  SiS_SetCH701xForLCD(SiS_Pr);
+#endif
+	       }
+	    }
+	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	       SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
+	    }
+	 }
+      }
+
+   }
+
+#ifdef CONFIG_FB_SIS_300
+   if(SiS_Pr->ChipType < SIS_315H) {
+      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+	 if(SiS_Pr->SiS_UseOEM) {
+	    if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
+	       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+		  SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	       }
+	    } else {
+	       SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	    }
+	 }
+	 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	    if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+	       (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+	       SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
+	    }
+	    SiS_DisplayOn(SiS_Pr);
+         }
+      }
+   }
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+	 if(SiS_Pr->ChipType < SIS_661) {
+	    SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
+	    SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	 } else {
+	    SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+	 }
+	 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
+      }
+   }
+#endif
+
+   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+      SiS_EnableBridge(SiS_Pr);
+   }
+
+   SiS_DisplayOn(SiS_Pr);
+
+   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+	 /* Disable LCD panel when using TV */
+	 SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
+      } else {
+	 /* Disable TV when using LCD */
+	 SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
+      }
+   }
+
+   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+      SiS_LockCRT2(SiS_Pr);
+   }
+
+   return true;
+}
+
+
+/*********************************************/
+/*     ENABLE/DISABLE LCD BACKLIGHT (SIS)    */
+/*********************************************/
+
+void
+SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
+{
+  /* Switch on LCD backlight on SiS30xLV */
+  SiS_DDC2Delay(SiS_Pr,0xff00);
+  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+     SiS_WaitVBRetrace(SiS_Pr);
+  }
+  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
+     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+  }
+}
+
+void
+SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
+{
+  /* Switch off LCD backlight on SiS30xLV */
+  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+  SiS_DDC2Delay(SiS_Pr,0xff00);
+}
+
+/*********************************************/
+/*          DDC RELATED FUNCTIONS            */
+/*********************************************/
+
+static void
+SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
+{
+  SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
+  SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
+  if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
+     SiS_Pr->SiS_DDC_NData &= 0x0f;
+     SiS_Pr->SiS_DDC_NClk  &= 0x0f;
+  }
+}
+
+#ifdef CONFIG_FB_SIS_300
+static unsigned char *
+SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
+{
+  int i, j, num;
+  unsigned short tempah,temp;
+  unsigned char *mydataptr;
+
+  for(i=0; i<20; i++) {				/* Do 20 attempts to write */
+     mydataptr = dataptr;
+     num = *mydataptr++;
+     if(!num) return mydataptr;
+     if(i) {
+        SiS_SetStop(SiS_Pr);
+	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;		/* Set start condition */
+     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write DAB (S0=0=write) */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     tempah = *mydataptr++;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write register number */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     for(j=0; j<num; j++) {
+        tempah = *mydataptr++;
+        temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
+	if(temp) break;
+     }
+     if(temp) continue;
+     if(SiS_SetStop(SiS_Pr)) continue;
+     return mydataptr;
+  }
+  return NULL;
+}
+
+static bool
+SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;			/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;			/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+
+  SiS_SetSwitchDDC2(SiS_Pr);
+
+  while(*dataptr) {
+     dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
+     if(!dataptr) return false;
+  }
+  return true;
+}
+#endif
+
+/* The Chrontel 700x is connected to the 630/730 via
+ * the 630/730's DDC/I2C port.
+ *
+ * On 630(S)T chipset, the index changed from 0x11 to
+ * 0x0a, possibly for working around the DDC problems
+ */
+
+static bool
+SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
+{
+  unsigned short temp, i;
+
+  for(i=0; i<20; i++) {				/* Do 20 attempts to write */
+     if(i) {
+	SiS_SetStop(SiS_Pr);
+	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;					/* Set start condition */
+     temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr);	/* Write DAB (S0=0=write) */
+     if(temp) continue;							/*    (ERROR: no ack) */
+     temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor));			/* Write RAB (700x: set bit 7, see datasheet) */
+     if(temp) continue;							/*    (ERROR: no ack) */
+     temp = SiS_WriteDDC2Data(SiS_Pr, val);				/* Write data */
+     if(temp) continue;							/*    (ERROR: no ack) */
+     if(SiS_SetStop(SiS_Pr)) continue;					/* Set stop condition */
+     SiS_Pr->SiS_ChrontelInit = 1;
+     return true;
+  }
+  return false;
+}
+
+/* Write to Chrontel 700x */
+void
+SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;  		/* DAB (Device Address Byte) */
+
+  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
+  if(!(SiS_Pr->SiS_ChrontelInit)) {
+     SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
+     SiS_Pr->SiS_DDC_Data  = 0x02;		/* Bitmask in IndexReg for Data */
+     SiS_Pr->SiS_DDC_Clk   = 0x01;		/* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
+  }
+
+  if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
+      (!(SiS_Pr->SiS_ChrontelInit)) ) {
+     SiS_Pr->SiS_DDC_Index = 0x0a;
+     SiS_Pr->SiS_DDC_Data  = 0x80;
+     SiS_Pr->SiS_DDC_Clk   = 0x40;
+     SiS_SetupDDCN(SiS_Pr);
+
+     SiS_SetChReg(SiS_Pr, reg, val, 0x80);
+  }
+}
+
+/* Write to Chrontel 701x */
+/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
+void
+SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
+{
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x08;			/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x04;			/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB (Device Address Byte) */
+  SiS_SetChReg(SiS_Pr, reg, val, 0);
+}
+
+static
+void
+SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
+{
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     SiS_SetCH700x(SiS_Pr, reg, val);
+  else
+     SiS_SetCH701x(SiS_Pr, reg, val);
+}
+
+static unsigned short
+SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
+{
+  unsigned short tempah, temp, i;
+
+  for(i=0; i<20; i++) {				/* Do 20 attempts to read */
+     if(i) {
+	SiS_SetStop(SiS_Pr);
+	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;					/* Set start condition */
+     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr);	/* Write DAB (S0=0=write) */
+     if(temp) continue;							/*        (ERROR: no ack) */
+     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor);	/* Write RAB (700x: | 0x80) */
+     if(temp) continue;							/*        (ERROR: no ack) */
+     if (SiS_SetStart(SiS_Pr)) continue;				/* Re-start */
+     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
+     if(temp) continue;							/*        (ERROR: no ack) */
+     tempah = SiS_ReadDDC2Data(SiS_Pr);					/* Read byte */
+     if(SiS_SetStop(SiS_Pr)) continue;					/* Stop condition */
+     SiS_Pr->SiS_ChrontelInit = 1;
+     return tempah;
+  }
+  return 0xFFFF;
+}
+
+/* Read from Chrontel 700x */
+/* Parameter is [Register no (S7-S0)] */
+unsigned short
+SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
+{
+  unsigned short result;
+
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
+
+  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
+  if(!(SiS_Pr->SiS_ChrontelInit)) {
+     SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
+     SiS_Pr->SiS_DDC_Data  = 0x02;		/* Bitmask in IndexReg for Data */
+     SiS_Pr->SiS_DDC_Clk   = 0x01;		/* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
+  }
+
+  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
+
+  if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
+      (!SiS_Pr->SiS_ChrontelInit) ) {
+
+     SiS_Pr->SiS_DDC_Index = 0x0a;
+     SiS_Pr->SiS_DDC_Data  = 0x80;
+     SiS_Pr->SiS_DDC_Clk   = 0x40;
+     SiS_SetupDDCN(SiS_Pr);
+
+     result = SiS_GetChReg(SiS_Pr,0x80);
+  }
+  return result;
+}
+
+/* Read from Chrontel 701x */
+/* Parameter is [Register no (S7-S0)] */
+unsigned short
+SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
+{
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x08;			/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x04;			/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
+
+  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
+
+  return SiS_GetChReg(SiS_Pr,0);
+}
+
+/* Read from Chrontel 70xx */
+/* Parameter is [Register no (S7-S0)] */
+static
+unsigned short
+SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
+{
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     return SiS_GetCH700x(SiS_Pr, tempbx);
+  else
+     return SiS_GetCH701x(SiS_Pr, tempbx);
+}
+
+void
+SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+		unsigned char myor, unsigned short myand)
+{
+  unsigned short tempbl;
+
+  tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
+  SiS_SetCH70xx(SiS_Pr, reg, tempbl);
+}
+
+/* Our own DDC functions */
+static
+unsigned short
+SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+                unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
+		unsigned int VBFlags2)
+{
+     unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
+     unsigned char flag, cr32;
+     unsigned short        temp = 0, myadaptnum = adaptnum;
+
+     if(adaptnum != 0) {
+	if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
+	if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
+     }
+
+     /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
+
+     SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
+
+     SiS_Pr->SiS_DDC_SecAddr = 0;
+     SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
+     SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
+     SiS_Pr->SiS_DDC_Index = 0x11;
+     flag = 0xff;
+
+     cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
+
+#if 0
+     if(VBFlags2 & VB2_SISBRIDGE) {
+	if(myadaptnum == 0) {
+	   if(!(cr32 & 0x20)) {
+	      myadaptnum = 2;
+	      if(!(cr32 & 0x10)) {
+	         myadaptnum = 1;
+		 if(!(cr32 & 0x08)) {
+		    myadaptnum = 0;
+		 }
+	      }
+	   }
+        }
+     }
+#endif
+
+     if(VGAEngine == SIS_300_VGA) {		/* 300 series */
+
+        if(myadaptnum != 0) {
+	   flag = 0;
+	   if(VBFlags2 & VB2_SISBRIDGE) {
+	      SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
+              SiS_Pr->SiS_DDC_Index = 0x0f;
+	   }
+        }
+
+	if(!(VBFlags2 & VB2_301)) {
+	   if((cr32 & 0x80) && (checkcr32)) {
+              if(myadaptnum >= 1) {
+	         if(!(cr32 & 0x08)) {
+		     myadaptnum = 1;
+		     if(!(cr32 & 0x10)) return 0xFFFF;
+                 }
+	      }
+	   }
+	}
+
+	temp = 4 - (myadaptnum * 2);
+	if(flag) temp = 0;
+
+     } else {						/* 315/330 series */
+
+	/* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
+
+	if(VBFlags2 & VB2_SISBRIDGE) {
+	   if(myadaptnum == 2) {
+	      myadaptnum = 1;
+	   }
+	}
+
+        if(myadaptnum == 1) {
+	   flag = 0;
+	   if(VBFlags2 & VB2_SISBRIDGE) {
+	      SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
+              SiS_Pr->SiS_DDC_Index = 0x0f;
+	   }
+        }
+
+        if((cr32 & 0x80) && (checkcr32)) {
+           if(myadaptnum >= 1) {
+	      if(!(cr32 & 0x08)) {
+	         myadaptnum = 1;
+		 if(!(cr32 & 0x10)) return 0xFFFF;
+	      }
+	   }
+        }
+
+        temp = myadaptnum;
+        if(myadaptnum == 1) {
+           temp = 0;
+	   if(VBFlags2 & VB2_LVDS) flag = 0xff;
+        }
+
+	if(flag) temp = 0;
+    }
+
+    SiS_Pr->SiS_DDC_Data = 0x02 << temp;
+    SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
+
+    SiS_SetupDDCN(SiS_Pr);
+
+    return 0;
+}
+
+static unsigned short
+SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
+   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
+      return 0xFFFF;
+   }
+   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
+      return 0xFFFF;
+   }
+   return 0;
+}
+
+static unsigned short
+SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
+   if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
+      return 0xFFFF;
+   }
+   return 0;
+}
+
+static unsigned short
+SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
+{
+   if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
+   if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
+   return 0;
+}
+
+static void
+SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
+{
+   SiS_SetSCLKLow(SiS_Pr);
+   if(yesno) {
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		      SiS_Pr->SiS_DDC_Index,
+		      SiS_Pr->SiS_DDC_NData,
+		      SiS_Pr->SiS_DDC_Data);
+   } else {
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		      SiS_Pr->SiS_DDC_Index,
+		      SiS_Pr->SiS_DDC_NData,
+		      0);
+   }
+   SiS_SetSCLKHigh(SiS_Pr);
+}
+
+static unsigned short
+SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
+{
+    unsigned char mask, value;
+    unsigned short  temp, ret=0;
+    bool failed = false;
+
+    SiS_SetSwitchDDC2(SiS_Pr);
+    if(SiS_PrepareDDC(SiS_Pr)) {
+         SiS_SetStop(SiS_Pr);
+         return 0xFFFF;
+    }
+    mask = 0xf0;
+    value = 0x20;
+    if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
+       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
+       SiS_SendACK(SiS_Pr, 0);
+       if(temp == 0) {
+           mask = 0xff;
+	   value = 0xff;
+       } else {
+           failed = true;
+	   ret = 0xFFFF;
+       }
+    }
+    if(!failed) {
+       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
+       SiS_SendACK(SiS_Pr, 1);
+       temp &= mask;
+       if(temp == value) ret = 0;
+       else {
+          ret = 0xFFFF;
+          if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
+             if(temp == 0x30) ret = 0;
+          }
+       }
+    }
+    SiS_SetStop(SiS_Pr);
+    return ret;
+}
+
+static
+unsigned short
+SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
+{
+   unsigned short flag;
+
+   flag = 0x180;
+   SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
+   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
+   SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
+   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
+   SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
+   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
+   if(!(flag & 0x1a)) flag = 0;
+   return flag;
+}
+
+static
+unsigned short
+SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
+{
+   unsigned short flag, length, i;
+   unsigned char chksum,gotcha;
+
+   if(DDCdatatype > 4) return 0xFFFF;
+
+   flag = 0;
+   SiS_SetSwitchDDC2(SiS_Pr);
+   if(!(SiS_PrepareDDC(SiS_Pr))) {
+      length = 127;
+      if(DDCdatatype != 1) length = 255;
+      chksum = 0;
+      gotcha = 0;
+      for(i=0; i<length; i++) {
+	 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
+	 chksum += buffer[i];
+	 gotcha |= buffer[i];
+	 SiS_SendACK(SiS_Pr, 0);
+      }
+      buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
+      chksum += buffer[i];
+      SiS_SendACK(SiS_Pr, 1);
+      if(gotcha) flag = (unsigned short)chksum;
+      else flag = 0xFFFF;
+   } else {
+      flag = 0xFFFF;
+   }
+   SiS_SetStop(SiS_Pr);
+   return flag;
+}
+
+/* Our private DDC functions
+
+   It complies somewhat with the corresponding VESA function
+   in arguments and return values.
+
+   Since this is probably called before the mode is changed,
+   we use our pre-detected pSiS-values instead of SiS_Pr as
+   regards chipset and video bridge type.
+
+   Arguments:
+       adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
+                 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
+		 LCDA is CRT1, but DDC is read from CRT2 port.
+       DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
+       buffer: ptr to 256 data bytes which will be filled with read data.
+
+   Returns 0xFFFF if error, otherwise
+       if DDCdatatype > 0:  Returns 0 if reading OK (included a correct checksum)
+       if DDCdatatype = 0:  Returns supported DDC modes
+
+ */
+unsigned short
+SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+              unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+	      unsigned int VBFlags2)
+{
+   unsigned char  sr1f, cr17=1;
+   unsigned short result;
+
+   if(adaptnum > 2)
+      return 0xFFFF;
+
+   if(DDCdatatype > 4)
+      return 0xFFFF;
+
+   if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
+      return 0xFFFF;
+
+   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
+      return 0xFFFF;
+
+   sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
+   if(VGAEngine == SIS_300_VGA) {
+      cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
+      if(!cr17) {
+         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
+         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
+         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
+      }
+   }
+   if((sr1f) || (!cr17)) {
+      SiS_WaitRetrace1(SiS_Pr);
+      SiS_WaitRetrace1(SiS_Pr);
+      SiS_WaitRetrace1(SiS_Pr);
+      SiS_WaitRetrace1(SiS_Pr);
+   }
+
+   if(DDCdatatype == 0) {
+      result = SiS_ProbeDDC(SiS_Pr);
+   } else {
+      result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
+      if((!result) && (DDCdatatype == 1)) {
+         if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
+	    (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
+	    (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
+	    (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
+	    (buffer[0x12] == 1)) {
+	    if(!SiS_Pr->DDCPortMixup) {
+	       if(adaptnum == 1) {
+	          if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
+	       } else {
+	          if(buffer[0x14] & 0x80)    result = 0xFFFE;
+	       }
+	    }
+	 }
+      }
+   }
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
+   if(VGAEngine == SIS_300_VGA) {
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
+   }
+   return result;
+}
+
+/* Generic I2C functions for Chrontel & DDC --------- */
+
+static void
+SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
+{
+  SiS_SetSCLKHigh(SiS_Pr);
+  SiS_WaitRetrace1(SiS_Pr);
+
+  SiS_SetSCLKLow(SiS_Pr);
+  SiS_WaitRetrace1(SiS_Pr);
+}
+
+unsigned short
+SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
+{
+   SiS_WaitRetrace1(SiS_Pr);
+   return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
+}
+
+/* Set I2C start condition */
+/* This is done by a SD high-to-low transition while SC is high */
+static unsigned short
+SiS_SetStart(struct SiS_Private *SiS_Pr)
+{
+  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			/* (SC->low)  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		  SiS_Pr->SiS_DDC_Index,
+		  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);        		/* SD->high */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* SC->high */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		  SiS_Pr->SiS_DDC_Index,
+		  SiS_Pr->SiS_DDC_NData,
+		  0x00);					/* SD->low = start condition */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* (SC->low) */
+  return 0;
+}
+
+/* Set I2C stop condition */
+/* This is done by a SD low-to-high transition while SC is high */
+static unsigned short
+SiS_SetStop(struct SiS_Private *SiS_Pr)
+{
+  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			/* (SC->low) */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		  SiS_Pr->SiS_DDC_Index,
+		  SiS_Pr->SiS_DDC_NData,
+		  0x00);					/* SD->low   */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* SC->high  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		  SiS_Pr->SiS_DDC_Index,
+		  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);			/* SD->high = stop condition */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* (SC->high) */
+  return 0;
+}
+
+/* Write 8 bits of data */
+static unsigned short
+SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
+{
+  unsigned short i,flag,temp;
+
+  flag = 0x80;
+  for(i = 0; i < 8; i++) {
+    SiS_SetSCLKLow(SiS_Pr);					/* SC->low */
+    if(tempax & flag) {
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		      SiS_Pr->SiS_DDC_Index,
+		      SiS_Pr->SiS_DDC_NData,
+		      SiS_Pr->SiS_DDC_Data);			/* Write bit (1) to SD */
+    } else {
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		      SiS_Pr->SiS_DDC_Index,
+		      SiS_Pr->SiS_DDC_NData,
+		      0x00);					/* Write bit (0) to SD */
+    }
+    SiS_SetSCLKHigh(SiS_Pr);					/* SC->high */
+    flag >>= 1;
+  }
+  temp = SiS_CheckACK(SiS_Pr);					/* Check acknowledge */
+  return temp;
+}
+
+static unsigned short
+SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
+{
+  unsigned short i, temp, getdata;
+
+  getdata = 0;
+  for(i = 0; i < 8; i++) {
+    getdata <<= 1;
+    SiS_SetSCLKLow(SiS_Pr);
+    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		    SiS_Pr->SiS_DDC_Index,
+		    SiS_Pr->SiS_DDC_NData,
+		    SiS_Pr->SiS_DDC_Data);
+    SiS_SetSCLKHigh(SiS_Pr);
+    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
+    if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
+  }
+  return getdata;
+}
+
+static unsigned short
+SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
+{
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		  SiS_Pr->SiS_DDC_Index,
+		  SiS_Pr->SiS_DDC_NClk,
+		  0x00);					/* SetSCLKLow()  */
+  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+  return 0;
+}
+
+static unsigned short
+SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
+{
+  unsigned short temp, watchdog=1000;
+
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		  SiS_Pr->SiS_DDC_Index,
+		  SiS_Pr->SiS_DDC_NClk,
+		  SiS_Pr->SiS_DDC_Clk);  			/* SetSCLKHigh()  */
+  do {
+    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
+  } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
+  if (!watchdog) {
+  	return 0xFFFF;
+  }
+  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+  return 0;
+}
+
+/* Check I2C acknowledge */
+/* Returns 0 if ack ok, non-0 if ack not ok */
+static unsigned short
+SiS_CheckACK(struct SiS_Private *SiS_Pr)
+{
+  unsigned short tempah;
+
+  SiS_SetSCLKLow(SiS_Pr);				           /* (SC->low) */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+		  SiS_Pr->SiS_DDC_Index,
+		  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);			   /* (SD->high) */
+  SiS_SetSCLKHigh(SiS_Pr);				           /* SC->high = clock impulse for ack */
+  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
+  SiS_SetSCLKLow(SiS_Pr);				           /* SC->low = end of clock impulse */
+  if(tempah & SiS_Pr->SiS_DDC_Data) return 1;			   /* Ack OK if bit = 0 */
+  return 0;
+}
+
+/* End of I2C functions ----------------------- */
+
+
+/* =============== SiS 315/330 O.E.M. ================= */
+
+#ifdef CONFIG_FB_SIS_315
+
+static unsigned short
+GetRAMDACromptr(struct SiS_Private *SiS_Pr)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short romptr;
+
+  if(SiS_Pr->ChipType < SIS_330) {
+     romptr = SISGETROMW(0x128);
+     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
+        romptr = SISGETROMW(0x12a);
+  } else {
+     romptr = SISGETROMW(0x1a8);
+     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
+        romptr = SISGETROMW(0x1aa);
+  }
+  return romptr;
+}
+
+static unsigned short
+GetLCDromptr(struct SiS_Private *SiS_Pr)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short romptr;
+
+  if(SiS_Pr->ChipType < SIS_330) {
+     romptr = SISGETROMW(0x120);
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
+        romptr = SISGETROMW(0x122);
+  } else {
+     romptr = SISGETROMW(0x1a0);
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
+        romptr = SISGETROMW(0x1a2);
+  }
+  return romptr;
+}
+
+static unsigned short
+GetTVromptr(struct SiS_Private *SiS_Pr)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short romptr;
+
+  if(SiS_Pr->ChipType < SIS_330) {
+     romptr = SISGETROMW(0x114);
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
+        romptr = SISGETROMW(0x11a);
+  } else {
+     romptr = SISGETROMW(0x194);
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
+        romptr = SISGETROMW(0x19a);
+  }
+  return romptr;
+}
+
+static unsigned short
+GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
+{
+  unsigned short index;
+
+  if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+     if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+        if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
+	   index >>= 4;
+	   index *= 3;
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
+           else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
+           return index;
+	}
+     }
+  }
+
+  index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
+  if(SiS_Pr->SiS_VBType & VB_SIS301C) {  /* 1.15.20 and later (not VB specific) */
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
+  }
+  index--;
+  index *= 3;
+  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
+  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
+  return index;
+}
+
+static unsigned short
+GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
+{
+  unsigned short index;
+
+  index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
+  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
+  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
+  return index;
+}
+
+static unsigned short
+GetTVPtrIndex(struct SiS_Private *SiS_Pr)
+{
+  unsigned short index;
+
+  index = 0;
+  if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
+
+  index <<= 1;
+
+  if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
+     (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
+     index++;
+  }
+
+  return index;
+}
+
+static unsigned int
+GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
+{
+   unsigned short index = 0, temp = 0;
+
+   if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
+   if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
+   if(SiS_Pr->SiS_TVMode & TVSetPALN)  index = 3;
+   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
+   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+      index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetPALM)  index++;
+      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
+   }
+
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+         (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
+	 index += addme;
+	 temp++;
+      }
+      temp += 0x0100;
+   }
+   return (unsigned int)(index | (temp << 16));
+}
+
+static unsigned int
+GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
+{
+   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
+}
+
+#if 0
+static unsigned int
+GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
+{
+   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
+}
+#endif
+
+static int
+GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
+{
+   int index = 0;
+
+   if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
+   if(SiS_Pr->SiS_ROMNew) {
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
+   } else {
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
+   }
+
+   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
+
+   return index;
+}
+
+static void
+SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short delay=0,index,myindex,temp,romptr=0;
+  bool dochiptest = true;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
+  } else {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
+  }
+
+  /* Find delay (from ROM, internal tables, PCI subsystem) */
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {			/* ------------ VGA */
+
+     if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+        romptr = GetRAMDACromptr(SiS_Pr);
+     }
+     if(romptr) delay = ROMAddr[romptr];
+     else {
+        delay = 0x04;
+        if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
+	   if(IS_SIS650) {
+	      delay = 0x0a;
+	   } else if(IS_SIS740) {
+	      delay = 0x00;
+	   } else if(SiS_Pr->ChipType < SIS_330) {
+	      delay = 0x0c;
+	   } else {
+	      delay = 0x0c;
+	   }
+	} else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+           delay = 0x00;
+	}
+     }
+
+  } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ----------	LCD/LCDA */
+
+     bool gotitfrompci = false;
+
+     /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	if(SiS_Pr->PDC != -1) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
+	   return;
+	}
+     } else {
+	if(SiS_Pr->PDCA != -1) {
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
+	   return;
+	}
+     }
+
+     /* Custom Panel? */
+
+     if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	   delay = 0x00;
+	   if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
+	      delay = 0x20;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
+	} else {
+	   delay = 0x0c;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      delay = 0x03;
+	      if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
+	         delay = 0x00;
+	      }
+	   } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = 0x03;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
+	}
+        return;
+     }
+
+     /* This is a piece of typical SiS crap: They code the OEM LCD
+      * delay into the code, at no defined place in the BIOS.
+      * We now have to start doing a PCI subsystem check here.
+      */
+
+     switch(SiS_Pr->SiS_CustomT) {
+     case CUT_COMPAQ1280:
+     case CUT_COMPAQ12802:
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	   gotitfrompci = true;
+	   dochiptest = false;
+	   delay = 0x03;
+	}
+	break;
+     case CUT_CLEVO1400:
+     case CUT_CLEVO14002:
+	gotitfrompci = true;
+	dochiptest = false;
+	delay = 0x02;
+	break;
+     case CUT_CLEVO1024:
+     case CUT_CLEVO10242:
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	   gotitfrompci = true;
+	   dochiptest = false;
+	   delay = 0x33;
+	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
+	   delay &= 0x0f;
+	}
+	break;
+     }
+
+     /* Could we find it through the PCI ID? If no, use ROM or table */
+
+     if(!gotitfrompci) {
+
+        index = GetLCDPtrIndexBIOS(SiS_Pr);
+        myindex = GetLCDPtrIndex(SiS_Pr);
+
+        if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+
+           if(SiS_IsNotM650orLater(SiS_Pr)) {
+
+              if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+	         /* Always use the second pointer on 650; some BIOSes */
+                 /* still carry old 301 data at the first location    */
+	         /* romptr = SISGETROMW(0x120);                       */
+	         /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
+	         romptr = SISGETROMW(0x122);
+	         if(!romptr) return;
+	         delay = ROMAddr[(romptr + index)];
+	      } else {
+                 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
+	      }
+
+          } else {
+
+             delay = SiS310_LCDDelayCompensation_651301LV[myindex];
+	     if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
+	        delay = SiS310_LCDDelayCompensation_651302LV[myindex];
+
+          }
+
+        } else if(SiS_Pr->SiS_UseROM 			      &&
+		  (!(SiS_Pr->SiS_ROMNew))		      &&
+	          (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)  &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)  &&
+		  ((romptr = GetLCDromptr(SiS_Pr)))) {
+
+	   /* Data for 1280x1024 wrong in 301B BIOS */
+	   /* Data for 1600x1200 wrong in 301C BIOS */
+	   delay = ROMAddr[(romptr + index)];
+
+        } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+
+	   if(IS_SIS740) delay = 0x03;
+	   else          delay = 0x00;
+
+	} else {
+
+           delay = SiS310_LCDDelayCompensation_301[myindex];
+	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+	      if(IS_SIS740) delay = 0x01;
+	      else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
+	      else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
+	   } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      if(IS_SIS740) delay = 0x01;  /* ? */
+	      else          delay = 0x03;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
+	   } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
+	   }
+
+        }
+
+     }  /* got it from PCI */
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
+	dochiptest = false;
+     }
+
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {			/* ------------ TV */
+
+     index = GetTVPtrIndex(SiS_Pr);
+
+     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+
+        if(SiS_IsNotM650orLater(SiS_Pr)) {
+
+           if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+	      /* Always use the second pointer on 650; some BIOSes */
+              /* still carry old 301 data at the first location    */
+              /* romptr = SISGETROMW(0x114);			   */
+	      /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
+	      romptr = SISGETROMW(0x11a);
+	      if(!romptr) return;
+	      delay = ROMAddr[romptr + index];
+
+	   } else {
+
+	      delay = SiS310_TVDelayCompensation_301B[index];
+
+	   }
+
+        } else {
+
+           switch(SiS_Pr->SiS_CustomT) {
+	   case CUT_COMPAQ1280:
+	   case CUT_COMPAQ12802:
+	   case CUT_CLEVO1400:
+	   case CUT_CLEVO14002:
+	      delay = 0x02;
+	      dochiptest = false;
+	      break;
+	   case CUT_CLEVO1024:
+	   case CUT_CLEVO10242:
+	      delay = 0x03;
+	      dochiptest = false;
+   	      break;
+	   default:
+              delay = SiS310_TVDelayCompensation_651301LV[index];
+	      if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
+	         delay = SiS310_TVDelayCompensation_651302LV[index];
+	      }
+	   }
+        }
+
+     } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+
+        romptr = GetTVromptr(SiS_Pr);
+	if(!romptr) return;
+	delay = ROMAddr[romptr + index];
+
+     } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+
+        delay = SiS310_TVDelayCompensation_LVDS[index];
+
+     } else {
+
+	delay = SiS310_TVDelayCompensation_301[index];
+        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+	   if(IS_SIS740) {
+	      delay = SiS310_TVDelayCompensation_740301B[index];
+	      /* LV: use 301 data? BIOS bug? */
+	   } else {
+              delay = SiS310_TVDelayCompensation_301B[index];
+	      if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
+	   }
+	}
+
+     }
+
+     if(SiS_LCDAEnabled(SiS_Pr)) {
+	delay &= 0x0f;
+	dochiptest = false;
+     }
+
+  } else return;
+
+  /* Write delay */
+
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
+
+        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
+        if(temp == 8) {		/* 1400x1050 BIOS (COMPAL) */
+	   delay &= 0x0f;
+	   delay |= 0xb0;
+        } else if(temp == 6) {
+           delay &= 0x0f;
+	   delay |= 0xc0;
+        } else if(temp > 7) {	/* 1280x1024 BIOS (which one?) */
+	   delay = 0x35;
+        }
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
+
+     } else {
+
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
+
+     }
+
+  } else {  /* LVDS */
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
+     } else {
+        if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
+           delay <<= 4;
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
+        } else {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
+        }
+     }
+
+  }
+
+}
+
+static void
+SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,temp1,romptr=0;
+
+  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
+
+  if(ModeNo<=0x13)
+     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
+  else
+     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
+
+  temp = GetTVPtrIndex(SiS_Pr);
+  temp >>= 1;  	  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
+  temp1 = temp;
+
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
+     if(SiS_Pr->ChipType >= SIS_661) {
+        temp1 = GetOEMTVPtr661(SiS_Pr);
+        temp1 >>= 1;
+        romptr = SISGETROMW(0x260);
+        if(SiS_Pr->ChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x360);
+	}
+     } else if(SiS_Pr->ChipType >= SIS_330) {
+        romptr = SISGETROMW(0x192);
+     } else {
+        romptr = SISGETROMW(0x112);
+     }
+  }
+
+  if(romptr) {
+     temp1 <<= 1;
+     temp = ROMAddr[romptr + temp1 + index];
+  } else {
+     temp = SiS310_TVAntiFlick1[temp][index];
+  }
+  temp <<= 4;
+
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp);  /* index 0A D[6:4] */
+}
+
+static void
+SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,temp1,romptr=0;
+
+  temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; 	/* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
+
+  if(ModeNo <= 0x13)
+     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
+  else
+     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
+
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
+     if(SiS_Pr->ChipType >= SIS_661) {
+        romptr = SISGETROMW(0x26c);
+        if(SiS_Pr->ChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x36c);
+	}
+	temp1 = GetOEMTVPtr661(SiS_Pr);
+        temp1 >>= 1;
+     } else if(SiS_Pr->ChipType >= SIS_330) {
+        romptr = SISGETROMW(0x1a4);
+     } else {
+        romptr = SISGETROMW(0x124);
+     }
+  }
+
+  if(romptr) {
+     temp1 <<= 1;
+     temp = ROMAddr[romptr + temp1 + index];
+  } else {
+     temp = SiS310_TVEdge1[temp][index];
+  }
+  temp <<= 5;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp);  /* index 0A D[7:5] */
+}
+
+static void
+SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
+{
+  unsigned short index, temp, i, j;
+
+  if(ModeNo <= 0x13) {
+     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
+  } else {
+     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
+  }
+
+  temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
+
+  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)	     temp = 1;  /* NTSC-J uses PAL */
+  else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
+  else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
+
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+     for(i=0x35, j=0; i<=0x38; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
+     }
+     for(i=0x48; i<=0x4A; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
+     }
+  } else {
+     for(i=0x35, j=0; i<=0x38; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
+     }
+  }
+}
+
+static void
+SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,i,j,resinfo,romptr=0;
+  unsigned int  lindex;
+
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
+
+  /* NTSC-J data not in BIOS, and already set in SetGroup2 */
+  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
+
+  if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
+     lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
+     lindex <<= 2;
+     for(j=0, i=0x31; i<=0x34; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
+     }
+     return;
+  }
+
+  /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
+  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
+
+  if(ModeNo<=0x13) {
+     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else {
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+  }
+
+  temp = GetTVPtrIndex(SiS_Pr);
+  /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
+   * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
+   */
+  if(SiS_Pr->SiS_UseROM) {
+     romptr = SISGETROMW(0x116);
+     if(SiS_Pr->ChipType >= SIS_330) {
+        romptr = SISGETROMW(0x196);
+     }
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+        romptr = SISGETROMW(0x11c);
+	if(SiS_Pr->ChipType >= SIS_330) {
+	   romptr = SISGETROMW(0x19c);
+	}
+	if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
+	   romptr = SISGETROMW(0x116);
+	   if(SiS_Pr->ChipType >= SIS_330) {
+              romptr = SISGETROMW(0x196);
+           }
+	}
+     }
+  }
+  if(romptr) {
+     romptr += (temp << 2);
+     for(j=0, i=0x31; i<=0x34; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
+     }
+  } else {
+     index = temp % 2;
+     temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
+     for(j=0, i=0x31; i<=0x34; i++, j++) {
+        if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
+        else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
+        else
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
+     }
+  }
+
+  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
+     if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
+        if((resinfo == SIS_RI_640x480) ||
+	   (resinfo == SIS_RI_800x600)) {
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
+	} else if(resinfo == SIS_RI_1024x768) {
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
+	}
+     }
+  }
+}
+
+static void
+SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                unsigned short ModeIdIndex, unsigned short RTI)
+{
+   unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+
+   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
+      return;
+
+   /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
+   /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
+
+   if(SiS_Pr->SiS_ROMNew) {
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) 			||
+         ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+	  (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+         index = 25;
+         if(SiS_Pr->UseCustomMode) {
+	    index = SiS_Pr->CSRClock;
+         } else if(ModeNo > 0x13) {
+            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
+            index = SiS_Pr->SiS_VCLKData[index].CLOCK;
+         }
+	 if(index < 25) index = 25;
+         index = ((index / 25) - 1) << 1;
+         if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
+	    index++;
+	 }
+	 romptr = SISGETROMW(0x104);
+         delay = ROMAddr[romptr + index];
+         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
+         } else {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+         }
+         return;
+      }
+   }
+
+   /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
+
+   if(SiS_Pr->UseCustomMode) delay = 0x04;
+   else if(ModeNo <= 0x13)   delay = 0x04;
+   else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
+   delay |= (delay << 8);
+
+   if(SiS_Pr->ChipType >= XGI_20) {
+
+      delay = 0x0606;
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+	 delay = 0x0404;
+         if(SiS_Pr->SiS_XGIROM) {
+	     index = GetTVPtrIndex(SiS_Pr);
+	     if((romptr = SISGETROMW(0x35e))) {
+	        delay = (ROMAddr[romptr + index] & 0x0f) << 1;
+		delay |= (delay << 8);
+	     }
+	 }
+
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	    if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
+	       delay -= 0x0404;
+	    }
+	 }
+      }
+
+   } else if(SiS_Pr->ChipType >= SIS_340) {
+
+      delay = 0x0606;
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+         delay = 0x0404;
+      }
+      /* TODO (eventually) */
+
+   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+      /* 3. TV */
+
+      index = GetOEMTVPtr661(SiS_Pr);
+      if(SiS_Pr->SiS_ROMNew) {
+         romptr = SISGETROMW(0x106);
+	 if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
+         delay = ROMAddr[romptr + index];
+      } else {
+         delay = 0x04;
+	 if(index > 3) delay = 0;
+      }
+
+   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+
+      /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
+
+      if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
+          ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
+
+	 lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
+
+	 /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
+	 delay = ROMAddr[romptr + lcdpdcindex + 1];	/* LCD  */
+	 delay |= (ROMAddr[romptr + lcdpdcindex] << 8);	/* LCDA */
+
+      } else {
+
+         /* TMDS: Set our own, since BIOS has no idea */
+	 /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
+         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	    switch(SiS_Pr->SiS_LCDResInfo) {
+	    case Panel_1024x768:  delay = 0x0008; break;
+	    case Panel_1280x720:  delay = 0x0004; break;
+	    case Panel_1280x768:
+	    case Panel_1280x768_2:delay = 0x0004; break;
+	    case Panel_1280x800:
+	    case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
+	    case Panel_1280x854:  delay = 0x0004; break; /* FIXME */
+	    case Panel_1280x1024: delay = 0x1e04; break;
+	    case Panel_1400x1050: delay = 0x0004; break;
+	    case Panel_1600x1200: delay = 0x0400; break;
+	    case Panel_1680x1050: delay = 0x0e04; break;
+	    default:
+               if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
+	          delay = 0x0008;
+	       } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
+	          delay = 0x1e04;
+               } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
+	          delay = 0x0004;
+	       } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
+	          delay = 0x0400;
+               } else
+	          delay = 0x0e04;
+	       break;
+	    }
+         }
+
+	 /* Override by detected or user-set values */
+	 /* (but only if, for some reason, we can't read value from BIOS) */
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
+            delay = SiS_Pr->PDC & 0x1f;
+         }
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
+            delay = (SiS_Pr->PDCA & 0x1f) << 8;
+         }
+
+      }
+
+   }
+
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+      delay >>= 8;
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+   } else {
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
+   }
+}
+
+static void
+SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
+{
+   unsigned short infoflag;
+   unsigned char  temp;
+
+   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+
+      if(ModeNo <= 0x13) {
+         infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
+      } else if(SiS_Pr->UseCustomMode) {
+         infoflag = SiS_Pr->CInfoFlag;
+      } else {
+         infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
+      }
+
+      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+         infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
+      }
+
+      infoflag &= 0xc0;
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+         temp = (infoflag >> 6) | 0x0c;
+         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+	    temp ^= 0x04;
+	    if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
+	 }
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
+      } else {
+         temp = 0x30;
+         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
+         temp |= infoflag;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
+         temp = 0;
+         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+	    if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
+	 }
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
+      }
+
+   }
+}
+
+static void
+SetPanelParms661(struct SiS_Private *SiS_Pr)
+{
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short romptr, temp1, temp2;
+
+   if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
+   }
+
+   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+      if(SiS_Pr->LVDSHL != -1) {
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
+      }
+   }
+
+   if(SiS_Pr->SiS_ROMNew) {
+
+      if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
+         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+            temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
+	    temp2 = 0xfc;
+	    if(SiS_Pr->LVDSHL != -1) {
+	      temp1 &= 0xfc;
+	      temp2 = 0xf3;
+	    }
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
+         }
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+            temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
+	 }
+      }
+
+   }
+}
+
+static void
+SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+         SetPanelParms661(SiS_Pr);
+      }
+   } else {
+      SetDelayComp(SiS_Pr,ModeNo);
+   }
+
+   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+      SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
+      SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
+      SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
+      if(SiS_Pr->SiS_VBType & VB_SIS301) {
+         SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
+      }
+   }
+}
+
+static void
+SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+			unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+
+      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+         SetPanelParms661(SiS_Pr);
+      }
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+         SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
+         SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
+         SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
+         if(SiS_Pr->SiS_VBType & VB_SIS301) {
+            SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
+         }
+      }
+   }
+}
+
+/* FinalizeLCD
+ * This finalizes some CRT2 registers for the very panel used.
+ * If we have a backup if these registers, we use it; otherwise
+ * we set the register according to most BIOSes. However, this
+ * function looks quite different in every BIOS, so you better
+ * pray that we have a backup...
+ */
+static void
+SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
+  unsigned short resinfo,modeflag;
+
+  if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
+  if(SiS_Pr->SiS_ROMNew) return;
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(SiS_Pr->LVDSHL != -1) {
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
+     }
+  }
+
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
+  if(SiS_Pr->UseCustomMode) return;
+
+  switch(SiS_Pr->SiS_CustomT) {
+  case CUT_COMPAQ1280:
+  case CUT_COMPAQ12802:
+  case CUT_CLEVO1400:
+  case CUT_CLEVO14002:
+     return;
+  }
+
+  if(ModeNo <= 0x13) {
+     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+     modeflag =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else {
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     modeflag =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+  }
+
+  if(IS_SIS650) {
+     if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
+        if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
+	} else {
+           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
+	}
+     }
+  }
+
+  if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        /* Maybe all panels? */
+        if(SiS_Pr->LVDSHL == -1) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
+	}
+	return;
+     }
+  }
+
+  if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	   if(SiS_Pr->LVDSHL == -1) {
+	      /* Maybe all panels? */
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
+	      if(tempch == 3) {
+	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
+	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
+	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
+	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
+	      }
+	   }
+	   return;
+	}
+     }
+  }
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
+	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+	}
+     } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+        if(SiS_Pr->LVDSHL == -1) {
+           /* Maybe ACER only? */
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
+	}
+     }
+     tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
+	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	   if(tempch == 0x03) {
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
+	   }
+	   if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
+	   } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {	/* 1.10.8w */
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
+	      if(ModeNo <= 0x13) {
+	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
+		 if((resinfo == 0) || (resinfo == 2)) return;
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
+		 if((resinfo == 1) || (resinfo == 3)) return;
+	      }
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
+	      if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
+	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);  /* 1.10.7u */
+#if 0
+	         tempbx = 806;  /* 0x326 */			 /* other older BIOSes */
+		 tempbx--;
+		 temp = tempbx & 0xff;
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
+		 temp = (tempbx >> 8) & 0x03;
+		 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
+#endif
+	      }
+	   } else if(ModeNo <= 0x13) {
+	      if(ModeNo <= 1) {
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
+	      }
+	      if(!(modeflag & HalfDCLK)) {
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
+		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
+		 if(ModeNo == 0x12) {
+		    switch(tempch) {
+		       case 0:
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
+			  break;
+		       case 2:
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
+			  break;
+		       case 3:
+			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
+			  break;
+		    }
+		 }
+	      }
+	   }
+	}
+     } else {
+        tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
+	tempcl &= 0x0f;
+	tempbh &= 0x70;
+	tempbh >>= 4;
+	tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
+	tempbx = (tempbh << 8) | tempbl;
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	   if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
+	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+	      	 tempbx = 770;
+	      } else {
+	         if(tempbx > 770) tempbx = 770;
+		 if(SiS_Pr->SiS_VGAVDE < 600) {
+		    tempax = 768 - SiS_Pr->SiS_VGAVDE;
+		    tempax >>= 4;  				 /* 1.10.7w; 1.10.6s: 3;  */
+		    if(SiS_Pr->SiS_VGAVDE <= 480)  tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
+		    tempbx -= tempax;
+		 }
+	      }
+	   } else return;
+	}
+	temp = tempbx & 0xff;
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
+	temp = ((tempbx & 0xff00) >> 4) | tempcl;
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
+     }
+  }
+}
+
+#endif
+
+/*  =================  SiS 300 O.E.M. ================== */
+
+#ifdef CONFIG_FB_SIS_300
+
+static void
+SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+		unsigned short RefTabIndex)
+{
+  unsigned short crt2crtc=0, modeflag, myindex=0;
+  unsigned char  temp;
+  int i;
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
+  }
+
+  crt2crtc &= 0x3f;
+
+  if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
+  }
+
+  if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+     if(modeflag & HalfDCLK) myindex = 1;
+
+     if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+        for(i=0; i<7; i++) {
+           if(barco_p1[myindex][crt2crtc][i][0]) {
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
+	                      barco_p1[myindex][crt2crtc][i][0],
+	   	   	      barco_p1[myindex][crt2crtc][i][2],
+			      barco_p1[myindex][crt2crtc][i][1]);
+	   }
+        }
+     }
+     temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+     if(temp & 0x80) {
+        temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
+        temp++;
+        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
+     }
+  }
+}
+
+static unsigned short
+GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short tempbx=0,romptr=0;
+  static const unsigned char customtable300[] = {
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+  };
+  static const unsigned char customtable630[] = {
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+  };
+
+  if(SiS_Pr->ChipType == SIS_300) {
+
+    tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
+    if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
+    tempbx -= 2;
+    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
+    }
+    if(SiS_Pr->SiS_UseROM) {
+       if(ROMAddr[0x235] & 0x80) {
+          tempbx = SiS_Pr->SiS_LCDTypeInfo;
+          if(Flag) {
+	     romptr = SISGETROMW(0x255);
+	     if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	     else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
+             if(tempbx == 0xFF) return 0xFFFF;
+          }
+	  tempbx <<= 1;
+	  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+       }
+    }
+
+  } else {
+
+    if(Flag) {
+       if(SiS_Pr->SiS_UseROM) {
+          romptr = SISGETROMW(0x255);
+	  if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	  else 	     tempbx = 0xff;
+       } else {
+          tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
+       }
+       if(tempbx == 0xFF) return 0xFFFF;
+       tempbx <<= 2;
+       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
+       return tempbx;
+    }
+    tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
+    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
+    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
+
+  }
+
+  return tempbx;
+}
+
+static void
+SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,romptr=0;
+
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
+
+  if(SiS_Pr->SiS_UseROM) {
+     if(!(ROMAddr[0x237] & 0x01)) return;
+     if(!(ROMAddr[0x237] & 0x02)) return;
+     romptr = SISGETROMW(0x24b);
+  }
+
+  /* The Panel Compensation Delay should be set according to tables
+   * here. Unfortunately, various BIOS versions don't care about
+   * a uniform way using eg. ROM byte 0x220, but use different
+   * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
+   * Thus we don't set this if the user selected a custom pdc or if
+   * we otherwise detected a valid pdc.
+   */
+  if(SiS_Pr->PDC != -1) return;
+
+  temp = GetOEMLCDPtr(SiS_Pr, 0);
+
+  if(SiS_Pr->UseCustomMode)
+     index = 0;
+  else
+     index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
+
+  if(SiS_Pr->ChipType != SIS_300) {
+     if(romptr) {
+	romptr += (temp * 2);
+	romptr = SISGETROMW(romptr);
+	romptr += index;
+	temp = ROMAddr[romptr];
+     } else {
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+    	   temp = SiS300_OEMLCDDelay2[temp][index];
+	} else {
+           temp = SiS300_OEMLCDDelay3[temp][index];
+        }
+     }
+  } else {
+     if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
+	if(romptr) {
+	   romptr += (temp * 2);
+	   romptr = SISGETROMW(romptr);
+	   romptr += index;
+	   temp = ROMAddr[romptr];
+	} else {
+	   temp = SiS300_OEMLCDDelay5[temp][index];
+	}
+     } else {
+        if(SiS_Pr->SiS_UseROM) {
+	   romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
+	   if(romptr) {
+	      romptr += (temp * 2);
+	      romptr = SISGETROMW(romptr);
+	      romptr += index;
+	      temp = ROMAddr[romptr];
+	   } else {
+	      temp = SiS300_OEMLCDDelay4[temp][index];
+	   }
+	} else {
+	   temp = SiS300_OEMLCDDelay4[temp][index];
+	}
+     }
+  }
+  temp &= 0x3c;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
+}
+
+static void
+SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+#if 0  /* Unfinished; Data table missing */
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp;
+
+  if((SiS_Pr->SiS_UseROM) {
+     if(!(ROMAddr[0x237] & 0x01)) return;
+     if(!(ROMAddr[0x237] & 0x04)) return;
+     /* No rom pointer in BIOS header! */
+  }
+
+  temp = GetOEMLCDPtr(SiS_Pr, 1);
+  if(temp == 0xFFFF) return;
+
+  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
+  for(i=0x14, j=0; i<=0x17; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
+  }
+  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
+
+  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
+  SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
+  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
+  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
+  for(i=0x1b, j=3; i<=0x1d; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
+  }
+#endif
+}
+
+static unsigned short
+GetOEMTVPtr(struct SiS_Private *SiS_Pr)
+{
+  unsigned short index;
+
+  index = 0;
+  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)  index += 2;
+     else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
+     else if(SiS_Pr->SiS_TVMode & TVSetPAL)   index += 1;
+  } else {
+     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
+     if(SiS_Pr->SiS_TVMode & TVSetPAL)        index += 1;
+  }
+  return index;
+}
+
+static void
+SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,romptr=0;
+
+  if(SiS_Pr->SiS_UseROM) {
+     if(!(ROMAddr[0x238] & 0x01)) return;
+     if(!(ROMAddr[0x238] & 0x02)) return;
+     romptr = SISGETROMW(0x241);
+  }
+
+  temp = GetOEMTVPtr(SiS_Pr);
+
+  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
+
+  if(romptr) {
+     romptr += (temp * 2);
+     romptr = SISGETROMW(romptr);
+     romptr += index;
+     temp = ROMAddr[romptr];
+  } else {
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        temp = SiS300_OEMTVDelay301[temp][index];
+     } else {
+        temp = SiS300_OEMTVDelayLVDS[temp][index];
+     }
+  }
+  temp &= 0x3c;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
+}
+
+static void
+SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,romptr=0;
+
+  if(SiS_Pr->SiS_UseROM) {
+     if(!(ROMAddr[0x238] & 0x01)) return;
+     if(!(ROMAddr[0x238] & 0x04)) return;
+     romptr = SISGETROMW(0x243);
+  }
+
+  temp = GetOEMTVPtr(SiS_Pr);
+
+  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
+
+  if(romptr) {
+     romptr += (temp * 2);
+     romptr = SISGETROMW(romptr);
+     romptr += index;
+     temp = ROMAddr[romptr];
+  } else {
+     temp = SiS300_OEMTVFlicker[temp][index];
+  }
+  temp &= 0x70;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
+}
+
+static void
+SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,i,j,temp,romptr=0;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
+
+  if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
+
+  if(SiS_Pr->SiS_UseROM) {
+     if(!(ROMAddr[0x238] & 0x01)) return;
+     if(!(ROMAddr[0x238] & 0x08)) return;
+     romptr = SISGETROMW(0x245);
+  }
+
+  temp = GetOEMTVPtr(SiS_Pr);
+
+  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
+
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+     for(i=0x31, j=0; i<=0x34; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
+     }
+  } else {
+     if(romptr) {
+        romptr += (temp * 2);
+	romptr = SISGETROMW(romptr);
+	romptr += (index * 4);
+        for(i=0x31, j=0; i<=0x34; i++, j++) {
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
+	}
+     } else {
+        for(i=0x31, j=0; i<=0x34; i++, j++) {
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
+	}
+     }
+  }
+}
+
+static void
+SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,i,j,romptr=0;
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
+
+  if(SiS_Pr->SiS_UseROM) {
+     if(!(ROMAddr[0x238] & 0x01)) return;
+     if(!(ROMAddr[0x238] & 0x10)) return;
+     romptr = SISGETROMW(0x247);
+  }
+
+  temp = GetOEMTVPtr(SiS_Pr);
+
+  if(SiS_Pr->SiS_TVMode & TVSetPALM)      temp = 8;
+  else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
+  /* NTSCJ uses NTSC filters */
+
+  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
+
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      for(i=0x35, j=0; i<=0x38; i++, j++) {
+       	SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
+      }
+      for(i=0x48; i<=0x4A; i++, j++) {
+     	SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
+      }
+  } else {
+      if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
+         romptr += (temp * 2);
+	 romptr = SISGETROMW(romptr);
+	 romptr += (index * 4);
+	 for(i=0x35, j=0; i<=0x38; i++, j++) {
+       	    SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
+         }
+      } else {
+         for(i=0x35, j=0; i<=0x38; i++, j++) {
+       	    SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
+         }
+      }
+  }
+}
+
+static unsigned short
+SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
+{
+   unsigned short ModeIdIndex;
+   unsigned char  VGAINFO = SiS_Pr->SiS_VGAINFO;
+
+   if(*ModeNo <= 5) *ModeNo |= 1;
+
+   for(ModeIdIndex=0; ; ModeIdIndex++) {
+      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
+      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)    return 0;
+   }
+
+   if(*ModeNo != 0x07) {
+      if(*ModeNo > 0x03) return ModeIdIndex;
+      if(VGAINFO & 0x80) return ModeIdIndex;
+      ModeIdIndex++;
+   }
+
+   if(VGAINFO & 0x10) ModeIdIndex++;   /* 400 lines */
+	                               /* else 350 lines */
+   return ModeIdIndex;
+}
+
+static void
+SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+		  unsigned short RefTableIndex)
+{
+  unsigned short OEMModeIdIndex = 0;
+
+  if(!SiS_Pr->UseCustomMode) {
+     OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
+     if(!(OEMModeIdIndex)) return;
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
+     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+        SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
+     }
+  }
+  if(SiS_Pr->UseCustomMode) return;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+     SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
+    	SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
+       	SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
+     }
+  }
+}
+#endif
+
diff --git a/drivers/video/fbdev/sis/init301.h b/drivers/video/fbdev/sis/init301.h
new file mode 100644
index 000000000000..2112d6d7feda
--- /dev/null
+++ b/drivers/video/fbdev/sis/init301.h
@@ -0,0 +1,456 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Data and prototypes for init301.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef  _INIT301_H_
+#define  _INIT301_H_
+
+#include "initdef.h"
+
+#include "vgatypes.h"
+#include "vstruct.h"
+#ifdef SIS_CP
+#undef SIS_CP
+#endif
+#include <linux/types.h>
+#include <asm/io.h>
+#include <linux/fb.h>
+#include "sis.h"
+#include <video/sisfb.h>
+
+static const unsigned char SiS_YPbPrTable[3][64] = {
+  {
+    0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+    0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+    0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
+    0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
+    0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
+    0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
+  },
+  {
+    0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+    0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
+    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
+    0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
+    0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
+    0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
+  },
+  {
+#if 0 /* OK, but sticks to left edge */
+    0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
+    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+    0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
+    0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+    0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
+    0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
+#endif
+#if 1 /* Perfect */
+    0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
+    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+    0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
+    0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+    0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
+    0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
+#endif
+  }
+};
+
+static const unsigned char SiS_TVPhase[] =
+{
+	0x21,0xED,0xBA,0x08,	/* 0x00 SiS_NTSCPhase */
+	0x2A,0x05,0xE3,0x00,	/* 0x01 SiS_PALPhase */
+	0x21,0xE4,0x2E,0x9B,	/* 0x02 SiS_PALMPhase */
+	0x21,0xF4,0x3E,0xBA,	/* 0x03 SiS_PALNPhase */
+	0x1E,0x8B,0xA2,0xA7,
+	0x1E,0x83,0x0A,0xE0,	/* 0x05 SiS_SpecialPhaseM */
+	0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x21,0xF0,0x7B,0xD6,	/* 0x08 SiS_NTSCPhase2 */
+	0x2A,0x09,0x86,0xE9,	/* 0x09 SiS_PALPhase2 */
+	0x21,0xE6,0xEF,0xA4,	/* 0x0a SiS_PALMPhase2 */
+	0x21,0xF6,0x94,0x46,	/* 0x0b SiS_PALNPhase2 */
+	0x1E,0x8B,0xA2,0xA7,
+	0x1E,0x83,0x0A,0xE0,	/* 0x0d SiS_SpecialPhaseM */
+	0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,
+	0x1e,0x8c,0x5c,0x7a,	/* 0x10 SiS_SpecialPhase */
+	0x25,0xd4,0xfd,0x5e	/* 0x11 SiS_SpecialPhaseJ */
+};
+
+static const unsigned char SiS_HiTVGroup3_1[] = {
+    0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
+    0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
+    0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
+    0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10,
+    0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80,
+    0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0,
+    0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e,
+    0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
+};
+
+static const unsigned char SiS_HiTVGroup3_2[] = {
+    0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
+    0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
+    0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
+    0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10,
+    0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80,
+    0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94,
+    0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64,
+    0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
+};
+
+/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
+
+static const unsigned char SiS_Part2CLVX_1[] = {
+    0x00,0x00,
+    0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
+    0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
+    0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
+    0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
+};
+
+static const unsigned char SiS_Part2CLVX_2[] = {
+    0x00,0x00,
+    0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
+    0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
+    0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
+    0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
+};
+
+static const unsigned char SiS_Part2CLVX_3[] = {  /* NTSC, 525i, 525p */
+    0xE0,0x01,
+    0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
+    0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
+    0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E,
+    0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00,0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02,
+    0x58,0x02,
+    0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D,0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E,
+    0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F,0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F,
+    0x00,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01,0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03,
+    0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04,0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06,
+    0x00,0x03,
+    0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00,0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01,
+    0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02,0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03,
+    0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05,0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06,
+    0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07,0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08,
+    0xFF,0xFF
+};
+
+static const unsigned char SiS_Part2CLVX_4[] = {   /* PAL */
+    0x58,0x02,
+    0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
+    0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
+    0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
+    0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
+    0x00,0x03,
+    0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E,0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F,
+    0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00,0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01,
+    0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02,0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04,
+    0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05,0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07,
+    0x40,0x02,
+    0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
+    0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
+    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
+    0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
+    0xFF,0xFF
+};
+
+static const unsigned char SiS_Part2CLVX_5[] = {   /* 750p */
+    0x00,0x03,
+    0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
+    0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
+    0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
+    0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
+    0xFF,0xFF
+};
+
+static const unsigned char SiS_Part2CLVX_6[] = {   /* 1080i */
+    0x00,0x04,
+    0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
+    0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
+    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
+    0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
+    0xFF,0xFF,
+};
+
+#ifdef CONFIG_FB_SIS_315
+/* 661 et al LCD data structure (2.03.00) */
+static const unsigned char SiS_LCDStruct661[] = {
+    /* 1024x768 */
+/*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
+    0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
+    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
+    /*  | vss     |    vse  |clck|  clock  |CRT2DataP|CRT2DataP|idx     */
+    /*					      VESA    non-VESA  noscale */
+    /* 1280x1024 */
+    0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
+    /* 1400x1050 */
+    0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
+    /* 1600x1200 */
+    0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
+    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0A,
+    /* 1280x768 (_2) */
+    0x0A,0xE0,0x00,0x05,0x00,0x03,0x7C,0x06,0x26,0x03,0x30,0x00,0x70,
+    0x00,0x03,0x00,0x06,0x00,0x4D,0xC8,0x48,0x00,0x00,0x00,0x00,0x06,
+    /* 1280x720 */
+    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x20,
+    0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
+    /* 1280x800 (_2) */
+    0x0C,0xE0,0x00,0x05,0x20,0x03,0x10,0x06,0x2C,0x03,0x30,0x00,0x70,
+    0x00,0x04,0x00,0x03,0x00,0x49,0xCE,0x1E,0x00,0x00,0x00,0x00,0x09,
+    /* 1680x1050 */
+    0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
+    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
+    /* 1280x800_3 */
+    0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
+    0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
+    /* 800x600 */
+    0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
+    0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
+    /* 1280x854 */
+    0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
+    0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
+};
+#endif
+
+#ifdef CONFIG_FB_SIS_300
+static unsigned char SiS300_TrumpionData[14][80] = {
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
+    0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
+    0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
+    0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  /* variant 2 */
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
+};
+#endif
+
+void		SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+void		SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
+unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+bool		SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
+bool		SiS_IsVAMode(struct SiS_Private *SiS_Pr);
+void		SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+			unsigned short ModeIdIndex, int checkcrt2mode);
+void		SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+void    	SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+			unsigned short ModeIdIndex);
+void		SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex);
+unsigned short	SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+			unsigned short RefreshRateTableIndex);
+unsigned short	SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
+void		SiS_DisableBridge(struct SiS_Private *SiS_Pr);
+bool		SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+void		SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+void		SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
+
+void		SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+void		SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short	SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+void		SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+			unsigned char orval,unsigned short andval);
+#ifdef CONFIG_FB_SIS_315
+static void	SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
+static void	SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
+static void	SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
+static void	SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
+void		SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+void		SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
+#endif /* 315 */
+
+#ifdef CONFIG_FB_SIS_300
+static  bool	SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
+void		SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
+#endif
+
+void		SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+unsigned short	SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+unsigned short	SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+			unsigned short adaptnum, unsigned short DDCdatatype,
+			unsigned char *buffer, unsigned int VBFlags2);
+
+static unsigned short	SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+				int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+				bool checkcr32, unsigned int VBFlags2);
+static unsigned short	SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+				unsigned char *buffer);
+static void		SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_SetStart(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_SetStop(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
+static unsigned short	SiS_CheckACK(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
+static unsigned short	SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
+static void		SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
+static unsigned short	SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
+
+#ifdef CONFIG_FB_SIS_300
+static void		SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
+				unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
+static void		SetOEMLCDData2(struct SiS_Private *SiS_Pr,
+				unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
+#endif
+#ifdef CONFIG_FB_SIS_315
+static void		SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
+				unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void		SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
+				unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void		SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
+#endif
+
+extern void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+extern void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+extern bool		SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
+extern unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+extern unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short	SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short	SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+				unsigned short RefreshRateTableIndex);
+extern void		SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+extern void		SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+				unsigned short ModeIdIndex);
+extern void		SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+extern unsigned short	SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+extern unsigned short	SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+#ifdef CONFIG_FB_SIS_300
+extern void		SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
+				unsigned short *tempcl);
+extern unsigned short	SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
+extern unsigned short	SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
+extern unsigned int	sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern unsigned int	sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/sis/initdef.h b/drivers/video/fbdev/sis/initdef.h
new file mode 100644
index 000000000000..264b55a5947b
--- /dev/null
+++ b/drivers/video/fbdev/sis/initdef.h
@@ -0,0 +1,708 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Global definitions for init.c and init301.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _INITDEF_
+#define _INITDEF_
+
+#define IS_SIS330		(SiS_Pr->ChipType == SIS_330)
+#define IS_SIS550		(SiS_Pr->ChipType == SIS_550)
+#define IS_SIS650		(SiS_Pr->ChipType == SIS_650)  /* All versions, incl 651, M65x */
+#define IS_SIS740		(SiS_Pr->ChipType == SIS_740)
+#define IS_SIS651	        (SiS_Pr->SiS_SysFlags & (SF_Is651 | SF_Is652))
+#define IS_SISM650	        (SiS_Pr->SiS_SysFlags & (SF_IsM650 | SF_IsM652 | SF_IsM653))
+#define IS_SIS65x               (IS_SIS651 || IS_SISM650)       /* Only special versions of 65x */
+#define IS_SIS661		(SiS_Pr->ChipType == SIS_661)
+#define IS_SIS741		(SiS_Pr->ChipType == SIS_741)
+#define IS_SIS660		(SiS_Pr->ChipType == SIS_660)
+#define IS_SIS760		(SiS_Pr->ChipType == SIS_760)
+#define IS_SIS761		(SiS_Pr->ChipType == SIS_761)
+#define IS_SIS661741660760	(IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760 || IS_SIS761)
+#define IS_SIS650740            ((SiS_Pr->ChipType >= SIS_650) && (SiS_Pr->ChipType < SIS_330))
+#define IS_SIS550650740         (IS_SIS550 || IS_SIS650740)
+#define IS_SIS650740660         (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
+#define IS_SIS550650740660      (IS_SIS550 || IS_SIS650740660)
+
+#define SISGETROMW(x)		(ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
+
+/* SiS_VBType */
+#define VB_SIS301		0x0001
+#define VB_SIS301B		0x0002
+#define VB_SIS302B		0x0004
+#define VB_SIS301LV		0x0008
+#define VB_SIS302LV		0x0010
+#define VB_SIS302ELV		0x0020
+#define VB_SIS301C		0x0040
+#define VB_SIS307T		0x0080
+#define VB_SIS307LV		0x0100
+#define VB_UMC			0x4000
+#define VB_NoLCD        	0x8000
+#define VB_SIS30xB		(VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SIS30xC		(VB_SIS301C | VB_SIS307T)
+#define VB_SISTMDS		(VB_SIS301 | VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SISLVDS		(VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SIS30xBLV		(VB_SIS30xB | VB_SISLVDS)
+#define VB_SIS30xCLV		(VB_SIS30xC | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISVB		(VB_SIS301 | VB_SIS30xBLV)
+#define VB_SISLCDA		(VB_SIS302B | VB_SIS301C  | VB_SIS307T  | VB_SISLVDS)
+#define VB_SISTMDSLCDA		(VB_SIS301C | VB_SIS307T)
+#define VB_SISPART4SCALER	(VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISHIVISION		(VB_SIS301 | VB_SIS301B | VB_SIS302B)
+#define VB_SISYPBPR		(VB_SIS301C | VB_SIS307T  | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISTAP4SCALER	(VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPART4OVERFLOW	(VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPWD		(VB_SIS301C | VB_SIS307T | VB_SISLVDS)
+#define VB_SISEMI		(VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPOWER		(VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISDUALLINK		(VB_SIS302LV | VB_SIS302ELV | VB_SIS307T | VB_SIS307LV)
+#define VB_SISVGA2		VB_SISTMDS
+#define VB_SISRAMDAC202		(VB_SIS301C | VB_SIS307T)
+
+/* VBInfo */
+#define SetSimuScanMode         0x0001   /* CR 30 */
+#define SwitchCRT2              0x0002
+#define SetCRT2ToAVIDEO         0x0004
+#define SetCRT2ToSVIDEO         0x0008
+#define SetCRT2ToSCART          0x0010
+#define SetCRT2ToLCD            0x0020
+#define SetCRT2ToRAMDAC         0x0040
+#define SetCRT2ToHiVision       0x0080   		/* for SiS bridge */
+#define SetCRT2ToCHYPbPr       	SetCRT2ToHiVision	/* for Chrontel   */
+#define SetNTSCTV               0x0000   /* CR 31 */
+#define SetPALTV                0x0100   		/* Deprecated here, now in TVMode */
+#define SetInSlaveMode          0x0200
+#define SetNotSimuMode          0x0400
+#define SetNotSimuTVMode        SetNotSimuMode
+#define SetDispDevSwitch        0x0800
+#define SetCRT2ToYPbPr525750    0x0800
+#define LoadDACFlag             0x1000
+#define DisableCRT2Display      0x2000
+#define DriverMode              0x4000
+#define HotKeySwitch            0x8000
+#define SetCRT2ToLCDA           0x8000
+
+/* v-- Needs change in sis_vga.c if changed (GPIO) --v */
+#define SetCRT2ToTV             (SetCRT2ToYPbPr525750|SetCRT2ToHiVision|SetCRT2ToSCART|SetCRT2ToSVIDEO|SetCRT2ToAVIDEO)
+#define SetCRT2ToTVNoYPbPrHiVision (SetCRT2ToSCART | SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)
+#define SetCRT2ToTVNoHiVision  	(SetCRT2ToYPbPr525750 | SetCRT2ToSCART | SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)
+
+/* SiS_ModeType */
+#define ModeText                0x00
+#define ModeCGA                 0x01
+#define ModeEGA                 0x02
+#define ModeVGA                 0x03
+#define Mode15Bpp               0x04
+#define Mode16Bpp               0x05
+#define Mode24Bpp               0x06
+#define Mode32Bpp               0x07
+
+#define ModeTypeMask            0x07
+#define IsTextMode              0x07
+
+#define DACInfoFlag             0x0018
+#define MemoryInfoFlag          0x01E0
+#define MemorySizeShift         5
+
+/* modeflag */
+#define Charx8Dot               0x0200
+#define LineCompareOff          0x0400
+#define CRT2Mode                0x0800
+#define HalfDCLK                0x1000
+#define NoSupportSimuTV         0x2000
+#define NoSupportLCDScale	0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
+#define DoubleScanMode          0x8000
+
+/* Infoflag */
+#define SupportTV               0x0008
+#define SupportTV1024           0x0800
+#define SupportCHTV 		0x0800
+#define Support64048060Hz       0x0800  /* Special for 640x480 LCD */
+#define SupportHiVision         0x0010
+#define SupportYPbPr750p        0x1000
+#define SupportLCD              0x0020
+#define SupportRAMDAC2          0x0040	/* All           (<= 100Mhz) */
+#define SupportRAMDAC2_135      0x0100  /* All except DH (<= 135Mhz) */
+#define SupportRAMDAC2_162      0x0200  /* B, C          (<= 162Mhz) */
+#define SupportRAMDAC2_202      0x0400  /* C             (<= 202Mhz) */
+#define InterlaceMode           0x0080
+#define SyncPP                  0x0000
+#define HaveWideTiming		0x2000	/* Have specific wide- and non-wide timing */
+#define SyncPN                  0x4000
+#define SyncNP                  0x8000
+#define SyncNN                  0xc000
+
+/* SetFlag */
+#define ProgrammingCRT2         0x0001
+#define LowModeTests		0x0002
+/* #define TVSimuMode           0x0002 - deprecated */
+/* #define RPLLDIV2XO           0x0004 - deprecated */
+#define LCDVESATiming           0x0008
+#define EnableLVDSDDA           0x0010
+#define SetDispDevSwitchFlag    0x0020
+#define CheckWinDos             0x0040
+#define SetDOSMode              0x0080
+
+/* TVMode flag */
+#define TVSetPAL		0x0001
+#define TVSetNTSCJ		0x0002
+#define TVSetPALM		0x0004
+#define TVSetPALN		0x0008
+#define TVSetCHOverScan		0x0010
+#define TVSetYPbPr525i		0x0020 /* new 0x10 */
+#define TVSetYPbPr525p		0x0040 /* new 0x20 */
+#define TVSetYPbPr750p		0x0080 /* new 0x40 */
+#define TVSetHiVision		0x0100 /* new 0x80; = 1080i, software-wise identical */
+#define TVSetTVSimuMode		0x0200 /* new 0x200, prev. 0x800 */
+#define TVRPLLDIV2XO		0x0400 /* prev 0x1000 */
+#define TVSetNTSC1024		0x0800 /* new 0x100, prev. 0x2000 */
+#define TVSet525p1024		0x1000 /* TW */
+#define TVAspect43		0x2000
+#define TVAspect169		0x4000
+#define TVAspect43LB		0x8000
+
+/* YPbPr flag (>=315, <661; converted to TVMode) */
+#define YPbPr525p               0x0001
+#define YPbPr750p               0x0002
+#define YPbPr525i               0x0004
+#define YPbPrHiVision           0x0008
+#define YPbPrModeMask           (YPbPr750p | YPbPr525p | YPbPr525i | YPbPrHiVision)
+
+/* SysFlags (to identify special versions) */
+#define SF_Is651                0x0001
+#define SF_IsM650               0x0002
+#define SF_Is652		0x0004
+#define SF_IsM652		0x0008
+#define SF_IsM653		0x0010
+#define SF_IsM661		0x0020
+#define SF_IsM741		0x0040
+#define SF_IsM760		0x0080
+#define SF_760UMA		0x4000  /* 76x: We have UMA */
+#define SF_760LFB		0x8000  /* 76x: We have LFB */
+
+/* CR32 (Newer 630, and 315 series)
+
+   [0]   VB connected with CVBS
+   [1]   VB connected with SVHS
+   [2]   VB connected with SCART
+   [3]   VB connected with LCD
+   [4]   VB connected with CRT2 (secondary VGA)
+   [5]   CRT1 monitor is connected
+   [6]   VB connected with Hi-Vision TV
+   [7]   <= 330: VB connected with DVI combo connector
+         >= 661: VB connected to YPbPr
+*/
+
+/* CR35 (300 series only) */
+#define TVOverScan              0x10
+#define TVOverScanShift         4
+
+/* CR35 (661 series only)
+   [0]    1 = PAL, 0 = NTSC
+   [1]    1 = NTSC-J (if D0 = 0)
+   [2]    1 = PALM (if D0 = 1)
+   [3]    1 = PALN (if D0 = 1)
+   [4]    1 = Overscan (Chrontel only)
+   [7:5]  (only if D2 in CR38 is set)
+	  000  525i
+	  001  525p
+	  010  750p
+	  011  1080i (or HiVision on 301, 301B)
+*/
+
+/* CR37
+   [0]   Set 24/18 bit (0/1) RGB to LVDS/TMDS transmitter (set by BIOS)
+   [3:1] External chip
+         300 series:
+	    001   SiS301 (never seen)
+	    010   LVDS
+	    011   LVDS + Tumpion Zurac
+	    100   LVDS + Chrontel 7005
+	    110   Chrontel 7005
+	  315/330 series
+	    001   SiS30x (never seen)
+	    010   LVDS
+	    011   LVDS + Chrontel 7019
+	  660 series [2:1] only:
+	     reserved (chip type now in CR38)
+	  All other combinations reserved
+   [3]    661 only: Pass 1:1 data
+   [4]    LVDS: 0: Panel Link expands / 1: Panel Link does not expand
+          30x:  0: Bridge scales      / 1: Bridge does not scale = Panel scales (if possible)
+   [5]    LCD polarity select
+          0: VESA DMT Standard
+	  1: EDID 2.x defined
+   [6]    LCD horizontal polarity select
+          0: High active
+	  1: Low active
+   [7]    LCD vertical polarity select
+          0: High active
+	  1: Low active
+*/
+
+/* CR37: LCDInfo */
+#define LCDRGB18Bit           0x0001
+#define LCDNonExpanding       0x0010
+#define LCDSync               0x0020
+#define LCDPass11             0x0100   /* 0: center screen, 1: Pass 1:1 data */
+#define LCDDualLink	      0x0200
+
+#define DontExpandLCD	      LCDNonExpanding
+#define LCDNonExpandingShift       4
+#define DontExpandLCDShift    LCDNonExpandingShift
+#define LCDSyncBit            0x00e0
+#define LCDSyncShift               6
+
+/* CR38 (315 series) */
+#define EnableDualEdge 		0x01
+#define SetToLCDA		0x02   /* LCD channel A (301C/302B/30x(E)LV and 650+LVDS only) */
+#define EnableCHScart           0x04   /* Scart on Ch7019 (unofficial definition - TW) */
+#define EnableCHYPbPr           0x08   /* YPbPr on Ch7019 (480i HDTV); only on 650/Ch7019 systems */
+#define EnableSiSYPbPr          0x08   /* Enable YPbPr mode (30xLV/301C only) */
+#define EnableYPbPr525i         0x00   /* Enable 525i YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr525p         0x10   /* Enable 525p YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr750p         0x20   /* Enable 750p YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr1080i        0x30   /* Enable 1080i YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnablePALM              0x40   /* 1 = Set PALM */
+#define EnablePALN              0x80   /* 1 = Set PALN */
+#define EnableNTSCJ             EnablePALM  /* Not BIOS */
+
+/* CR38 (661 and later)
+  D[7:5]  000 No VB
+          001 301 series VB
+	  010 LVDS
+	  011 Chrontel 7019
+	  100 Conexant
+  D2      Enable YPbPr output (see CR35)
+  D[1:0]  LCDA (like before)
+*/
+
+#define EnablePALMN             0x40   /* Romflag: 1 = Allow PALM/PALN */
+
+/* CR39 (650 only) */
+#define LCDPass1_1		0x01   /* 0: center screen, 1: pass 1:1 data output  */
+#define Enable302LV_DualLink    0x04   /* 302LV only; enable dual link */
+
+/* CR39 (661 and later)
+   D[7]   LVDS (SiS or third party)
+   D[1:0] YPbPr Aspect Ratio
+          00 4:3 letterbox
+	  01 4:3
+	  10 16:9
+	  11 4:3
+*/
+
+/* CR3B (651+301C)
+   D[1:0] YPbPr Aspect Ratio
+          ?
+*/
+
+/* CR79 (315/330 series only; not 661 and later)
+   [3-0] Notify driver
+         0001 Mode Switch event (set by BIOS)
+	 0010 Epansion On/Off event
+	 0011 TV UnderScan/OverScan event
+	 0100 Set Brightness event
+	 0101 Set Contrast event
+	 0110 Set Mute event
+	 0111 Set Volume Up/Down event
+   [4]   Enable Backlight Control by BIOS/driver
+         (set by driver; set means that the BIOS should
+	 not touch the backlight registers because eg.
+	 the driver already switched off the backlight)
+   [5]   PAL/NTSC (set by BIOS)
+   [6]   Expansion On/Off (set by BIOS; copied to CR32[4])
+   [7]   TV UnderScan/OverScan (set by BIOS)
+*/
+
+/* CR7C - 661 and later
+   [7]   DualEdge enabled (or: to be enabled)
+   [6]   CRT2 = TV/LCD/VGA enabled (or: to be enabled)
+   [5]   Init done (set at end of SiS_Init)
+   {4]   LVDS LCD capabilities
+   [3]   LVDS LCD capabilities
+   [2]   LVDS LCD capabilities (PWD)
+   [1]   LVDS LCD capabilities (PWD)
+   [0]   LVDS=1, TMDS=0 (SiS or third party)
+*/
+
+/* CR7E - 661 and later
+   VBType:
+   [7] LVDS (third party)
+   [3] 301C
+   [2] 302LV
+   [1] 301LV
+   [0] 301B
+*/
+
+/* LCDResInfo */
+#define Panel300_800x600        0x01	/* CR36 */
+#define Panel300_1024x768       0x02
+#define Panel300_1280x1024      0x03
+#define Panel300_1280x960       0x04
+#define Panel300_640x480        0x05
+#define Panel300_1024x600       0x06
+#define Panel300_1152x768       0x07
+#define Panel300_1280x768       0x0a
+#define Panel300_Custom		0x0f
+#define Panel300_Barco1366      0x10
+
+#define Panel310_800x600        0x01
+#define Panel310_1024x768       0x02
+#define Panel310_1280x1024      0x03
+#define Panel310_640x480        0x04
+#define Panel310_1024x600       0x05
+#define Panel310_1152x864       0x06
+#define Panel310_1280x960       0x07
+#define Panel310_1152x768       0x08	/* LVDS only */
+#define Panel310_1400x1050      0x09
+#define Panel310_1280x768       0x0a
+#define Panel310_1600x1200      0x0b
+#define Panel310_320x240_2      0x0c    /* xSTN */
+#define Panel310_320x240_3      0x0d    /* xSTN */
+#define Panel310_320x240_1      0x0e    /* xSTN - This is fake, can be any */
+#define Panel310_Custom		0x0f
+
+#define Panel661_800x600        0x01
+#define Panel661_1024x768       0x02
+#define Panel661_1280x1024      0x03
+#define Panel661_640x480        0x04
+#define Panel661_1024x600       0x05
+#define Panel661_1152x864       0x06
+#define Panel661_1280x960       0x07
+#define Panel661_1280x854       0x08
+#define Panel661_1400x1050      0x09
+#define Panel661_1280x768       0x0a
+#define Panel661_1600x1200      0x0b
+#define Panel661_1280x800       0x0c
+#define Panel661_1680x1050      0x0d
+#define Panel661_1280x720       0x0e
+#define Panel661_Custom		0x0f
+
+#define Panel_800x600           0x01	/* Unified values */
+#define Panel_1024x768          0x02    /* MUST match BIOS values from 0-e */
+#define Panel_1280x1024         0x03
+#define Panel_640x480           0x04
+#define Panel_1024x600          0x05
+#define Panel_1152x864          0x06
+#define Panel_1280x960          0x07
+#define Panel_1152x768          0x08	/* LVDS only */
+#define Panel_1400x1050         0x09
+#define Panel_1280x768          0x0a    /* 30xB/C and LVDS only (BIOS: all) */
+#define Panel_1600x1200         0x0b
+#define Panel_1280x800		0x0c    /* 661etc (TMDS) */
+#define Panel_1680x1050         0x0d    /* 661etc  */
+#define Panel_1280x720		0x0e    /* 661etc  */
+#define Panel_Custom		0x0f	/* MUST BE 0x0f (for DVI DDC detection) */
+#define Panel_320x240_1         0x10    /* SiS 550 xSTN */
+#define Panel_Barco1366         0x11
+#define Panel_848x480		0x12
+#define Panel_320x240_2		0x13    /* SiS 550 xSTN */
+#define Panel_320x240_3		0x14    /* SiS 550 xSTN */
+#define Panel_1280x768_2        0x15	/* 30xLV */
+#define Panel_1280x768_3        0x16    /* (unused) */
+#define Panel_1280x800_2	0x17    /* 30xLV */
+#define Panel_856x480		0x18
+#define Panel_1280x854		0x19	/* 661etc */
+
+/* Index in ModeResInfo table */
+#define SIS_RI_320x200    0
+#define SIS_RI_320x240    1
+#define SIS_RI_320x400    2
+#define SIS_RI_400x300    3
+#define SIS_RI_512x384    4
+#define SIS_RI_640x400    5
+#define SIS_RI_640x480    6
+#define SIS_RI_800x600    7
+#define SIS_RI_1024x768   8
+#define SIS_RI_1280x1024  9
+#define SIS_RI_1600x1200 10
+#define SIS_RI_1920x1440 11
+#define SIS_RI_2048x1536 12
+#define SIS_RI_720x480   13
+#define SIS_RI_720x576   14
+#define SIS_RI_1280x960  15
+#define SIS_RI_800x480   16
+#define SIS_RI_1024x576  17
+#define SIS_RI_1280x720  18
+#define SIS_RI_856x480   19
+#define SIS_RI_1280x768  20
+#define SIS_RI_1400x1050 21
+#define SIS_RI_1152x864  22  /* Up to here SiS conforming */
+#define SIS_RI_848x480   23
+#define SIS_RI_1360x768  24
+#define SIS_RI_1024x600  25
+#define SIS_RI_1152x768  26
+#define SIS_RI_768x576   27
+#define SIS_RI_1360x1024 28
+#define SIS_RI_1680x1050 29
+#define SIS_RI_1280x800  30
+#define SIS_RI_1920x1080 31
+#define SIS_RI_960x540   32
+#define SIS_RI_960x600   33
+#define SIS_RI_1280x854  34
+
+/* CR5F */
+#define IsM650                  0x80
+
+/* Timing data */
+#define NTSCHT                  1716
+#define NTSC2HT                 1920
+#define NTSCVT                  525
+#define PALHT                   1728
+#define PALVT                   625
+#define StHiTVHT                892
+#define StHiTVVT                1126
+#define StHiTextTVHT            1000
+#define StHiTextTVVT            1126
+#define ExtHiTVHT               2100
+#define ExtHiTVVT               1125
+
+/* Indices in (VB)VCLKData tables */
+
+#define VCLK28                  0x00   /* Index in VCLKData table (300 and 315) */
+#define VCLK40                  0x04   /* Index in VCLKData table (300 and 315) */
+#define VCLK65_300              0x09   /* Index in VCLKData table (300) */
+#define VCLK108_2_300           0x14   /* Index in VCLKData table (300) */
+#define VCLK81_300		0x3f   /* Index in VCLKData table (300) */
+#define VCLK108_3_300           0x42   /* Index in VCLKData table (300) */
+#define VCLK100_300             0x43   /* Index in VCLKData table (300) */
+#define VCLK34_300              0x3d   /* Index in VCLKData table (300) */
+#define VCLK_CUSTOM_300		0x47
+
+#define VCLK65_315              0x0b   /* Indices in (VB)VCLKData table (315) */
+#define VCLK108_2_315           0x19
+#define VCLK81_315		0x5b
+#define VCLK162_315             0x5e
+#define VCLK108_3_315           0x45
+#define VCLK100_315             0x46
+#define VCLK34_315              0x55
+#define VCLK68_315		0x0d
+#define VCLK_1280x800_315_2	0x5c
+#define VCLK121_315		0x5d
+#define VCLK130_315		0x72
+#define VCLK_1280x720		0x5f
+#define VCLK_1280x768_2		0x60
+#define VCLK_1280x768_3		0x61   /* (unused?) */
+#define VCLK_CUSTOM_315		0x62
+#define VCLK_1280x720_2		0x63
+#define VCLK_720x480		0x67
+#define VCLK_720x576		0x68
+#define VCLK_768x576		0x68
+#define VCLK_848x480		0x65
+#define VCLK_856x480		0x66
+#define VCLK_800x480		0x65
+#define VCLK_1024x576		0x51
+#define VCLK_1152x864		0x64
+#define VCLK_1360x768		0x58
+#define VCLK_1280x800_315	0x6c
+#define VCLK_1280x854		0x76
+
+#define TVCLKBASE_300		0x21   /* Indices on TV clocks in VCLKData table (300) */
+#define TVCLKBASE_315	        0x3a   /* Indices on TV clocks in (VB)VCLKData table (315) */
+#define TVVCLKDIV2              0x00   /* Index relative to TVCLKBASE */
+#define TVVCLK                  0x01   /* Index relative to TVCLKBASE */
+#define HiTVVCLKDIV2            0x02   /* Index relative to TVCLKBASE */
+#define HiTVVCLK                0x03   /* Index relative to TVCLKBASE */
+#define HiTVSimuVCLK            0x04   /* Index relative to TVCLKBASE */
+#define HiTVTextVCLK            0x05   /* Index relative to TVCLKBASE */
+#define YPbPr750pVCLK		0x25   /* Index relative to TVCLKBASE; was 0x0f NOT relative */
+
+/* ------------------------------ */
+
+#define SetSCARTOutput          0x01
+
+#define HotPlugFunction         0x08
+
+#define StStructSize            0x06
+
+#define SIS_VIDEO_CAPTURE       0x00 - 0x30
+#define SIS_VIDEO_PLAYBACK      0x02 - 0x30
+#define SIS_CRT2_PORT_04        0x04 - 0x30
+#define SIS_CRT2_PORT_10        0x10 - 0x30
+#define SIS_CRT2_PORT_12        0x12 - 0x30
+#define SIS_CRT2_PORT_14        0x14 - 0x30
+
+#define ADR_CRT2PtrData         0x20E
+#define offset_Zurac            0x210   /* TW: Trumpion Zurac data pointer */
+#define ADR_LVDSDesPtrData      0x212
+#define ADR_LVDSCRT1DataPtr     0x214
+#define ADR_CHTVVCLKPtr         0x216
+#define ADR_CHTVRegDataPtr      0x218
+
+#define LCDDataLen              8
+#define HiTVDataLen             12
+#define TVDataLen               16
+
+#define LVDSDataLen             6
+#define LVDSDesDataLen          3
+#define ActiveNonExpanding      0x40
+#define ActiveNonExpandingShift 6
+#define ActivePAL               0x20
+#define ActivePALShift          5
+#define ModeSwitchStatus        0x0F
+#define SoftTVType              0x40
+#define SoftSettingAddr         0x52
+#define ModeSettingAddr         0x53
+
+#define _PanelType00             0x00
+#define _PanelType01             0x08
+#define _PanelType02             0x10
+#define _PanelType03             0x18
+#define _PanelType04             0x20
+#define _PanelType05             0x28
+#define _PanelType06             0x30
+#define _PanelType07             0x38
+#define _PanelType08             0x40
+#define _PanelType09             0x48
+#define _PanelType0A             0x50
+#define _PanelType0B             0x58
+#define _PanelType0C             0x60
+#define _PanelType0D             0x68
+#define _PanelType0E             0x70
+#define _PanelType0F             0x78
+
+#define PRIMARY_VGA       	0     /* 1: SiS is primary vga 0:SiS is secondary vga */
+
+#define BIOSIDCodeAddr          0x235  /* Offsets to ptrs in BIOS image */
+#define OEMUtilIDCodeAddr       0x237
+#define VBModeIDTableAddr       0x239
+#define OEMTVPtrAddr            0x241
+#define PhaseTableAddr          0x243
+#define NTSCFilterTableAddr     0x245
+#define PALFilterTableAddr      0x247
+#define OEMLCDPtr_1Addr         0x249
+#define OEMLCDPtr_2Addr         0x24B
+#define LCDHPosTable_1Addr      0x24D
+#define LCDHPosTable_2Addr      0x24F
+#define LCDVPosTable_1Addr      0x251
+#define LCDVPosTable_2Addr      0x253
+#define OEMLCDPIDTableAddr      0x255
+
+#define VBModeStructSize        5
+#define PhaseTableSize          4
+#define FilterTableSize         4
+#define LCDHPosTableSize        7
+#define LCDVPosTableSize        5
+#define OEMLVDSPIDTableSize     4
+#define LVDSHPosTableSize       4
+#define LVDSVPosTableSize       6
+
+#define VB_ModeID               0
+#define VB_TVTableIndex         1
+#define VB_LCDTableIndex        2
+#define VB_LCDHIndex            3
+#define VB_LCDVIndex            4
+
+#define OEMLCDEnable            0x0001
+#define OEMLCDDelayEnable       0x0002
+#define OEMLCDPOSEnable         0x0004
+#define OEMTVEnable             0x0100
+#define OEMTVDelayEnable        0x0200
+#define OEMTVFlickerEnable      0x0400
+#define OEMTVPhaseEnable        0x0800
+#define OEMTVFilterEnable       0x1000
+
+#define OEMLCDPanelIDSupport    0x0080
+
+/*
+  =============================================================
+   		  for 315 series (old data layout)
+  =============================================================
+*/
+#define SoftDRAMType        0x80
+#define SoftSetting_OFFSET  0x52
+#define SR07_OFFSET  0x7C
+#define SR15_OFFSET  0x7D
+#define SR16_OFFSET  0x81
+#define SR17_OFFSET  0x85
+#define SR19_OFFSET  0x8D
+#define SR1F_OFFSET  0x99
+#define SR21_OFFSET  0x9A
+#define SR22_OFFSET  0x9B
+#define SR23_OFFSET  0x9C
+#define SR24_OFFSET  0x9D
+#define SR25_OFFSET  0x9E
+#define SR31_OFFSET  0x9F
+#define SR32_OFFSET  0xA0
+#define SR33_OFFSET  0xA1
+
+#define CR40_OFFSET  0xA2
+#define SR25_1_OFFSET  0xF6
+#define CR49_OFFSET  0xF7
+
+#define VB310Data_1_2_Offset  0xB6
+#define VB310Data_4_D_Offset  0xB7
+#define VB310Data_4_E_Offset  0xB8
+#define VB310Data_4_10_Offset 0xBB
+
+#define RGBSenseDataOffset    0xBD
+#define YCSenseDataOffset     0xBF
+#define VideoSenseDataOffset  0xC1
+#define OutputSelectOffset    0xF3
+
+#define ECLK_MCLK_DISTANCE  0x14
+#define VBIOSTablePointerStart    0x100
+#define StandTablePtrOffset       VBIOSTablePointerStart+0x02
+#define EModeIDTablePtrOffset     VBIOSTablePointerStart+0x04
+#define CRT1TablePtrOffset        VBIOSTablePointerStart+0x06
+#define ScreenOffsetPtrOffset     VBIOSTablePointerStart+0x08
+#define VCLKDataPtrOffset         VBIOSTablePointerStart+0x0A
+#define MCLKDataPtrOffset         VBIOSTablePointerStart+0x0E
+#define CRT2PtrDataPtrOffset      VBIOSTablePointerStart+0x10
+#define TVAntiFlickPtrOffset      VBIOSTablePointerStart+0x12
+#define TVDelayPtr1Offset         VBIOSTablePointerStart+0x14
+#define TVPhaseIncrPtr1Offset     VBIOSTablePointerStart+0x16
+#define TVYFilterPtr1Offset       VBIOSTablePointerStart+0x18
+#define LCDDelayPtr1Offset        VBIOSTablePointerStart+0x20
+#define TVEdgePtr1Offset          VBIOSTablePointerStart+0x24
+#define CRT2Delay1Offset          VBIOSTablePointerStart+0x28
+
+#endif
diff --git a/drivers/video/fbdev/sis/initextlfb.c b/drivers/video/fbdev/sis/initextlfb.c
new file mode 100644
index 000000000000..3ab18f5a3759
--- /dev/null
+++ b/drivers/video/fbdev/sis/initextlfb.c
@@ -0,0 +1,231 @@
+/*
+ * SiS 300/540/630[S]/730[S]
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX]
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
+ *
+ * Linux kernel specific extensions to init.c/init301.c
+ *
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Author:	Thomas Winischhofer <thomas@winischhofer.net>
+ */
+
+#include "initdef.h"
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#include <linux/types.h>
+#include <linux/fb.h>
+
+int		sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+			unsigned char modeno, unsigned char rateindex);
+int		sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+			unsigned char rateindex, struct fb_var_screeninfo *var);
+bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+			int *htotal, int *vtotal, unsigned char rateindex);
+
+extern bool	SiSInitPtr(struct SiS_Private *SiS_Pr);
+extern bool	SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+			unsigned short *ModeIdIndex);
+extern void	SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+			int xres, int yres, struct fb_var_screeninfo *var, bool writeres);
+
+int
+sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
+			unsigned char rateindex)
+{
+    unsigned short ModeNo = modeno;
+    unsigned short ModeIdIndex = 0, ClockIndex = 0;
+    unsigned short RRTI = 0;
+    int Clock;
+
+    if(!SiSInitPtr(SiS_Pr)) return 65000;
+
+    if(rateindex > 0) rateindex--;
+
+#ifdef CONFIG_FB_SIS_315
+    switch(ModeNo) {
+    case 0x5a: ModeNo = 0x50; break;
+    case 0x5b: ModeNo = 0x56;
+    }
+#endif
+
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {
+       printk(KERN_ERR "Could not find mode %x\n", ModeNo);
+       return 65000;
+    }
+
+    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+       if(SiS_Pr->SiS_UseWide == 1) {
+	  /* Wide screen: Ignore rateindex */
+	  ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_WIDE;
+       } else {
+	  RRTI += rateindex;
+	  ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_NORM;
+       }
+    } else {
+       RRTI += rateindex;
+       ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK;
+    }
+
+    Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
+
+    return Clock;
+}
+
+int
+sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+			unsigned char rateindex, struct fb_var_screeninfo *var)
+{
+    unsigned short ModeNo = modeno;
+    unsigned short ModeIdIndex = 0, index = 0, RRTI = 0;
+    int            j;
+
+    if(!SiSInitPtr(SiS_Pr)) return 0;
+
+    if(rateindex > 0) rateindex--;
+
+#ifdef CONFIG_FB_SIS_315
+    switch(ModeNo) {
+       case 0x5a: ModeNo = 0x50; break;
+       case 0x5b: ModeNo = 0x56;
+    }
+#endif
+
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
+
+    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+       if(SiS_Pr->SiS_UseWide == 1) {
+	  /* Wide screen: Ignore rateindex */
+	  index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+       } else {
+	  RRTI += rateindex;
+	  index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+       }
+    } else {
+       RRTI += rateindex;
+       index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+    }
+
+    SiS_Generic_ConvertCRData(SiS_Pr,
+			(unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
+			SiS_Pr->SiS_RefIndex[RRTI].XRes,
+			SiS_Pr->SiS_RefIndex[RRTI].YRes,
+			var, false);
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
+       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+    else
+       var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x4000)
+       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+    else
+       var->sync |= FB_SYNC_HOR_HIGH_ACT;
+
+    var->vmode = FB_VMODE_NONINTERLACED;
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x0080)
+       var->vmode = FB_VMODE_INTERLACED;
+    else {
+       j = 0;
+       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
+	  if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
+	                  SiS_Pr->SiS_RefIndex[RRTI].ModeID) {
+	      if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
+	      	  var->vmode = FB_VMODE_DOUBLE;
+	      }
+	      break;
+	  }
+	  j++;
+       }
+    }
+
+    if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+#if 0  /* Do this? */
+       var->upper_margin <<= 1;
+       var->lower_margin <<= 1;
+       var->vsync_len <<= 1;
+#endif
+    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+       var->upper_margin >>= 1;
+       var->lower_margin >>= 1;
+       var->vsync_len >>= 1;
+    }
+
+    return 1;
+}
+
+bool
+sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
+			int *vtotal, unsigned char rateindex)
+{
+    unsigned short ModeNo = modeno;
+    unsigned short ModeIdIndex = 0, CRT1Index = 0;
+    unsigned short RRTI = 0;
+    unsigned char  sr_data, cr_data, cr_data2;
+
+    if(!SiSInitPtr(SiS_Pr)) return false;
+
+    if(rateindex > 0) rateindex--;
+
+#ifdef CONFIG_FB_SIS_315
+    switch(ModeNo) {
+       case 0x5a: ModeNo = 0x50; break;
+       case 0x5b: ModeNo = 0x56;
+    }
+#endif
+
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
+
+    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+       if(SiS_Pr->SiS_UseWide == 1) {
+	  /* Wide screen: Ignore rateindex */
+	  CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+       } else {
+	  RRTI += rateindex;
+	  CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+       }
+    } else {
+       RRTI += rateindex;
+       CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+    }
+
+    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
+    *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
+
+    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
+    cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+    *vtotal = ((cr_data & 0xFF) |
+	       ((unsigned short)(cr_data2 & 0x01) <<  8) |
+	       ((unsigned short)(cr_data2 & 0x20) <<  4) |
+	       ((unsigned short)(sr_data  & 0x01) << 10)) + 2;
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
+       *vtotal *= 2;
+
+    return true;
+}
+
+
+
diff --git a/drivers/video/fbdev/sis/oem300.h b/drivers/video/fbdev/sis/oem300.h
new file mode 100644
index 000000000000..b73f26840143
--- /dev/null
+++ b/drivers/video/fbdev/sis/oem300.h
@@ -0,0 +1,840 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * OEM Data for 300 series
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+static const unsigned char SiS300_OEMTVDelay301[8][4] =
+{
+	{0x08,0x08,0x08,0x08},
+	{0x08,0x08,0x08,0x08},
+	{0x08,0x08,0x08,0x08},
+	{0x2c,0x2c,0x2c,0x2c},
+	{0x08,0x08,0x08,0x08},
+	{0x08,0x08,0x08,0x08},
+	{0x08,0x08,0x08,0x08},
+	{0x20,0x20,0x20,0x20}
+};
+
+static const unsigned char SiS300_OEMTVDelayLVDS[8][4] =
+{
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20}
+};
+
+static const unsigned char SiS300_OEMTVFlicker[8][4] =
+{
+	{0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00}
+};
+
+static const unsigned char SiS300_OEMLCDDelay2[64][4] =		 /* for 301/301b/302b/301LV/302LV */
+{
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20}
+};
+
+static const unsigned char SiS300_OEMLCDDelay4[12][4] =
+{
+	{0x2c,0x2c,0x2c,0x2c},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x2c,0x2c,0x2c,0x2c},
+	{0x2c,0x2c,0x2c,0x2c},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x24,0x24,0x24,0x24},
+	{0x24,0x24,0x24,0x24},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x24,0x24,0x24,0x24}
+};
+
+static const unsigned char SiS300_OEMLCDDelay5[32][4] =
+{
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+};
+
+static const unsigned char SiS300_OEMLCDDelay3[64][4] =		/* For LVDS */
+{
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20},
+	{0x20,0x20,0x20,0x20}
+};
+
+static const unsigned char SiS300_Phase1[8][5][4] =
+{
+    {
+	{0x21,0xed,0x00,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08}
+    },
+    {
+        {0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+        {0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+        {0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+        {0x21,0xed,0x00,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08}
+    },
+    {
+        {0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+        {0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+        {0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    }
+};
+
+static const unsigned char SiS300_Phase2[8][5][4] =
+{
+    {
+	{0x21,0xed,0x00,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08}
+    },
+    {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+	{0x21,0xed,0x00,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08},
+	{0x21,0xed,0x8a,0x08}
+    },
+    {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    },
+    {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+    }
+};
+
+static const unsigned char SiS300_Filter1[10][16][4] =
+{
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x10,0x18},
+	{0xf7,0x06,0x19,0x14},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x15,0x25,0xf6},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x10,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xfc,0xfb,0x14,0x2a},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x10,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xfc,0xfb,0x14,0x2a},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x10,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xfc,0xfb,0x14,0x2a},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x10,0x18},
+	{0xf7,0x06,0x19,0x14},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x15,0x25,0xf6},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x10,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xfc,0xfb,0x14,0x2a},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x10,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xfc,0xfb,0x14,0x2a},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x10,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xfc,0xfb,0x14,0x2a},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf1,0xf7,0x1f,0x32}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x10,0x18},
+	{0xf7,0x06,0x19,0x14},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x15,0x25,0xf6},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18}
+    },
+    {
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x10,0x18},
+	{0xf7,0x06,0x19,0x14},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x15,0x25,0xf6},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18}
+    },
+};
+
+static const unsigned char SiS300_Filter2[10][9][7] =
+{
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    },
+    {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+    }
+};
+
+/* Custom data for Barco iQ Pro R300 */
+static const unsigned char barco_p1[2][9][7][3] =
+{
+  {
+     {
+	{ 0x16, 0xcf, 0x00 },
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x19, 0x00 }
+     },
+     {
+	{ 0x16, 0xcf, 0x00 },
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x1e, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x16, 0x00 }
+     },
+     {
+	{ 0x16, 0xcf, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x19, 0x00 },
+	{    0,    0,    0 }
+     },
+     {
+	{    0,    0,    0 }
+     },
+     {
+	{ 0x16, 0xcf, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x1e, 0x00 },
+	{    0,    0,    0 }
+     },
+     {
+	{ 0x16, 0xd1, 0x00 },
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x11, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x26, 0x00 }
+     },
+     {
+	{ 0x16, 0xd1, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x30, 0x00 },
+	{    0,    0,    0 }
+     },
+     {
+	{ 0x16, 0x00, 0x00 },
+	{ 0x17, 0xa0, 0x00 },
+	{ 0x1a, 0xa0, 0x00 },
+	{ 0x1b, 0x2a, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{    0,    0,    0 }
+     },
+     {
+	{ 0x16, 0x00, 0x00 },
+	{ 0x17, 0xaa, 0x00 },
+	{ 0x1a, 0xa0, 0x00 },
+	{ 0x1b, 0x2a, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{    0,    0,    0 }
+     }
+  },
+  {
+     {
+	{ 0x16, 0xcf, 0x00 },
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x19, 0x00 }
+     },
+     {
+	{    0,    0,    0 }
+     },
+     {
+	{ 0x16, 0xcf, 0x00 },
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x19, 0x00 },
+     },
+     {
+	{    0,    0,    0 }
+     },
+     {
+	{ 0x16, 0xcf, 0x00 },
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe7, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x1e, 0x00 }
+     },
+     {
+	{ 0x16, 0xd1, 0x00 },
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe6, 0x00 },
+	{ 0x1b, 0x11, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x26, 0x00 }
+     },
+     {
+	{ 0x18, 0x00, 0x00 },
+	{ 0x1a, 0xe0, 0x00 },
+	{ 0x1b, 0x26, 0x00 },
+	{ 0x1c, 0xff, 0x00 },
+	{ 0x1d, 0x1c, 0x00 },
+	{ 0x1e, 0x30, 0x00 },
+	{    0,    0,    0 }
+     },
+     {
+	{    0,    0,    0 }
+     },
+     {
+	{    0,    0,    0 }
+     }
+  }
+};
+
+
+
+
+
+
diff --git a/drivers/video/fbdev/sis/oem310.h b/drivers/video/fbdev/sis/oem310.h
new file mode 100644
index 000000000000..8fce56e4482c
--- /dev/null
+++ b/drivers/video/fbdev/sis/oem310.h
@@ -0,0 +1,430 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * OEM Data for 315/330/340 series
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+static const unsigned char SiS310_LCDDelayCompensation_301[] =	    		/* 301 */
+{
+	0x00,0x00,0x00,    /*   800x600 */
+	0x0b,0x0b,0x0b,    /*  1024x768 */
+	0x08,0x08,0x08,    /* 1280x1024 */
+	0x00,0x00,0x00,    /*   640x480 (unknown) */
+	0x00,0x00,0x00,    /*  1024x600 (unknown) */
+	0x00,0x00,0x00,    /*  1152x864 (unknown) */
+	0x08,0x08,0x08,    /*  1280x960 (guessed) */
+	0x00,0x00,0x00,    /*  1152x768 (unknown) */
+	0x08,0x08,0x08,    /* 1400x1050 */
+	0x08,0x08,0x08,    /*  1280x768  (guessed) */
+	0x00,0x00,0x00,    /* 1600x1200 */
+	0x00,0x00,0x00,    /*   320x480 (unknown) */
+	0x00,0x00,0x00,
+	0x00,0x00,0x00,
+	0x00,0x00,0x00
+};
+
+/* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */
+static const unsigned char SiS310_LCDDelayCompensation_650301LV[] =	   	/* 650 + 30xLV */
+{
+	0x01,0x01,0x01,    /*   800x600 */
+	0x01,0x01,0x01,    /*  1024x768 */
+	0x01,0x01,0x01,    /* 1280x1024 */
+	0x01,0x01,0x01,    /*   640x480 (unknown) */
+	0x01,0x01,0x01,    /*  1024x600 (unknown) */
+	0x01,0x01,0x01,    /*  1152x864 (unknown) */
+	0x01,0x01,0x01,    /*  1280x960 (guessed) */
+	0x01,0x01,0x01,    /*  1152x768 (unknown) */
+	0x01,0x01,0x01,    /* 1400x1050 */
+	0x01,0x01,0x01,    /*  1280x768  (guessed) */
+	0x01,0x01,0x01,    /* 1600x1200 */
+	0x02,0x02,0x02,
+	0x02,0x02,0x02,
+	0x02,0x02,0x02,
+	0x02,0x02,0x02
+};
+
+static const unsigned char SiS310_LCDDelayCompensation_651301LV[] =	  	/* M650/651 301LV */
+{
+	0x33,0x33,0x33,    /*   800x600 (guessed) - new: PanelType, not PanelRes ! */
+	0x33,0x33,0x33,    /*  1024x768 */
+	0x33,0x33,0x33,    /* 1280x1024 */
+	0x33,0x33,0x33,    /*   640x480 (unknown) */
+	0x33,0x33,0x33,    /*  1024x600 (unknown) */
+	0x33,0x33,0x33,    /*  1152x864 (unknown) */
+	0x33,0x33,0x33,    /*  1280x960 (guessed) */
+	0x33,0x33,0x33,    /*  1152x768 (unknown) */
+	0x33,0x33,0x33,    /* 1400x1050 */
+	0x33,0x33,0x33,    /*  1280x768  (guessed) */
+	0x33,0x33,0x33,    /* 1600x1200 */
+	0x33,0x33,0x33,
+	0x33,0x33,0x33,
+	0x33,0x33,0x33,
+	0x33,0x33,0x33
+};
+
+static const unsigned char SiS310_LCDDelayCompensation_651302LV[] =	   	/* M650/651 302LV */
+{
+	0x33,0x33,0x33,    /*   800x600 (guessed) */
+	0x33,0x33,0x33,    /*  1024x768 */
+	0x33,0x33,0x33,    /* 1280x1024 */
+	0x33,0x33,0x33,    /*   640x480 (unknown) */
+	0x33,0x33,0x33,    /*  1024x600 (unknown) */
+	0x33,0x33,0x33,    /*  1152x864 (unknown) */
+	0x33,0x33,0x33,    /*  1280x960 (guessed) */
+	0x33,0x33,0x33,    /*  1152x768 (unknown) */
+	0x33,0x33,0x33,    /* 1400x1050 */
+	0x33,0x33,0x33,    /*  1280x768  (guessed) */
+	0x33,0x33,0x33,    /* 1600x1200 */
+	0x33,0x33,0x33,
+	0x33,0x33,0x33,
+	0x33,0x33,0x33,
+	0x33,0x33,0x33
+};
+
+static const unsigned char SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB */
+{
+	0x01,0x01,0x01,    /*   800x600 */
+	0x0C,0x0C,0x0C,    /*  1024x768 */
+	0x0C,0x0C,0x0C,    /* 1280x1024 */
+	0x08,0x08,0x08,    /*   640x480 */
+	0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+	0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+	0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+	0x02,0x02,0x02,
+	0x02,0x02,0x02,
+	0x02,0x02,0x02,
+	0x02,0x02,0x02
+};
+
+static const unsigned char SiS310_LCDDelayCompensation_3xx301LV[] =	   	/* 315+30xLV */
+{
+	0x01,0x01,0x01,    /*   800x600 */
+	0x04,0x04,0x04,    /*  1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
+	0x0C,0x0C,0x0C,    /* 1280x1024 */
+	0x08,0x08,0x08,    /*   640x480 */
+	0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+	0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+	0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+	0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+	0x02,0x02,0x02,
+	0x02,0x02,0x02,
+	0x02,0x02,0x02,
+	0x02,0x02,0x02
+};
+
+static const unsigned char SiS310_TVDelayCompensation_301[] = 		/* 301 */
+{
+	0x02,0x02,    /* NTSC Enhanced, Standard */
+	0x02,0x02,    /* PAL */
+	0x08,0x0b     /* HiVision */
+};
+
+static const unsigned char SiS310_TVDelayCompensation_301B[] =		/* 30xB, 30xLV */
+{
+	0x03,0x03,
+	0x03,0x03,
+	0x03,0x03
+};
+
+static const unsigned char SiS310_TVDelayCompensation_740301B[] =	/* 740 + 30xB (30xLV?) */
+{
+	0x05,0x05,
+	0x05,0x05,
+	0x05,0x05
+};
+
+static const unsigned char SiS310_TVDelayCompensation_651301LV[] =	/* M650, 651, 301LV */
+{
+	0x33,0x33,
+	0x33,0x33,
+	0x33,0x33
+};
+
+static const unsigned char SiS310_TVDelayCompensation_651302LV[] =	/* M650, 651, 302LV */
+{
+	0x33,0x33,
+	0x33,0x33,
+	0x33,0x33
+};
+
+static const unsigned char SiS_TVDelay661_301[] =			/* 661, 301 */
+{
+	0x44,0x44,
+	0x44,0x44,
+	0x00,0x00,
+	0x44,0x44,
+	0x44,0x44,
+	0x44,0x44
+};
+
+static const unsigned char SiS_TVDelay661_301B[] =			/* 661, 301B et al */
+{
+	0x44,0x44,
+	0x44,0x44,
+	0x00,0x00,
+	0x44,0x44,
+	0x44,0x44,
+	0x44,0x44
+};
+
+static const unsigned char SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
+{
+	0x0a,0x0a,
+	0x0a,0x0a,
+	0x0a,0x0a
+};
+
+static const unsigned char SiS310_TVAntiFlick1[6][2] =
+{
+	{0x4,0x0},
+	{0x4,0x8},
+	{0x0,0x0},
+	{0x0,0x0},
+	{0x0,0x0},
+	{0x0,0x0}
+};
+
+static const unsigned char SiS310_TVEdge1[6][2] =
+{
+	{0x0,0x4},
+	{0x0,0x4},
+	{0x0,0x0},
+	{0x0,0x0},
+	{0x0,0x0},
+	{0x0,0x0}
+};
+
+static const unsigned char SiS310_TVYFilter1[5][8][4] =
+{
+   {
+	{0x00,0xf4,0x10,0x38},	/* NTSC */
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xf1,0x04,0x1f,0x18},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xee,0x0c,0x22,0x08},
+	{0xeb,0x15,0x25,0xf6}
+   },
+   {
+	{0x00,0xf4,0x10,0x38},	/* PAL */
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0x00,0xf4,0x10,0x38},
+	{0xf1,0xf7,0x1f,0x32},
+	{0xf3,0x00,0x1d,0x20},
+	{0xfc,0xfb,0x14,0x2a}
+   },
+   {
+	{0x00,0x00,0x00,0x00},	/* HiVision */
+	{0x00,0xf4,0x10,0x38},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xf7,0x06,0x19,0x14},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xee,0x0c,0x22,0x08}
+   },
+   {
+	{0x00,0xf4,0x10,0x38},	/* PAL-M */
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x10,0x18},
+	{0xf7,0x06,0x19,0x14},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x15,0x25,0xf6}
+   },
+   {
+	{0x00,0xf4,0x10,0x38},	/* PAL-N */
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x10,0x18},
+	{0xf7,0x06,0x19,0x14},
+	{0x00,0xf4,0x10,0x38},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x04,0x25,0x18},
+	{0xeb,0x15,0x25,0xf6}
+   }
+};
+
+static const unsigned char SiS310_TVYFilter2[5][9][7] =
+{
+   {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},	/* NTSC */
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+   },
+   {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* PAL */
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+   },
+   {
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},	/* HiVision */
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
+	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}
+   },
+   {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, 	/* PAL-M */
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+   },
+   {
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},	/* PAL-N */
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
+	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
+	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
+	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
+   }
+};
+
+static const unsigned char SiS310_TVPhaseIncr1[3][2][4] =
+{
+   {
+	{0x21,0xed,0xba,0x08},
+	{0x21,0xed,0xba,0x08}
+   },
+   {
+	{0x2a,0x05,0xe3,0x00},
+	{0x2a,0x05,0xe3,0x00}
+   },
+   {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+   }
+};
+
+static const unsigned char SiS310_TVPhaseIncr2[3][2][4] =
+{
+   {
+	{0x21,0xf0,0x7b,0xd6},
+	{0x21,0xf0,0x7b,0xd6}
+   },
+   {
+	{0x2a,0x0a,0x41,0xe9},
+	{0x2a,0x0a,0x41,0xe9}
+   },
+   {
+	{0x2a,0x05,0xd3,0x00},
+	{0x2a,0x05,0xd3,0x00}
+   }
+};
+
+/**************************************************************/
+/* CUSTOM TIMING DATA --------------------------------------- */
+/**************************************************************/
+
+/* Inventec / Compaq Presario 3045US, 3017 */
+
+static const struct SiS_LCDData SiS310_ExtCompaq1280x1024Data[] =
+{
+	{  211,  60,1024, 501,1688,1066},
+	{  211,  60,1024, 508,1688,1066},
+	{  211,  60,1024, 501,1688,1066},
+	{  211,  60,1024, 508,1688,1066},
+	{   32,  15,1696, 501,1696,1066},
+	{  212,  75,1024, 621,1696,1066},
+	{    4,   3,1696, 810,1696,1066},
+	{    1,   1,1696,1066,1696,1066}
+};
+
+/* Asus A2xxxH _2 */
+
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_Asus1024x768_3[] =
+{
+	{{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+	{{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+	{{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+	{{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+};
+
+
+
+
diff --git a/drivers/video/fbdev/sis/sis.h b/drivers/video/fbdev/sis/sis.h
new file mode 100644
index 000000000000..1987f1b7212f
--- /dev/null
+++ b/drivers/video/fbdev/sis/sis.h
@@ -0,0 +1,586 @@
+/*
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]661[F|M]X/740/[M]741[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
+ *
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef _SIS_H_
+#define _SIS_H_
+
+#include <video/sisfb.h>
+
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#define VER_MAJOR		1
+#define VER_MINOR		8
+#define VER_LEVEL		9
+
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_COMPAT
+#define SIS_NEW_CONFIG_COMPAT
+#endif	/* CONFIG_COMPAT */
+
+#undef SISFBDEBUG
+
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+#define TWDEBUG(x) printk(KERN_INFO x "\n");
+#else
+#define DPRINTK(fmt, args...)
+#define TWDEBUG(x)
+#endif
+
+#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
+
+/* To be included in pci_ids.h */
+#ifndef PCI_DEVICE_ID_SI_650_VGA
+#define PCI_DEVICE_ID_SI_650_VGA	0x6325
+#endif
+#ifndef PCI_DEVICE_ID_SI_650
+#define PCI_DEVICE_ID_SI_650		0x0650
+#endif
+#ifndef PCI_DEVICE_ID_SI_651
+#define PCI_DEVICE_ID_SI_651		0x0651
+#endif
+#ifndef PCI_DEVICE_ID_SI_740
+#define PCI_DEVICE_ID_SI_740		0x0740
+#endif
+#ifndef PCI_DEVICE_ID_SI_330
+#define PCI_DEVICE_ID_SI_330		0x0330
+#endif
+#ifndef PCI_DEVICE_ID_SI_660_VGA
+#define PCI_DEVICE_ID_SI_660_VGA	0x6330
+#endif
+#ifndef PCI_DEVICE_ID_SI_661
+#define PCI_DEVICE_ID_SI_661		0x0661
+#endif
+#ifndef PCI_DEVICE_ID_SI_741
+#define PCI_DEVICE_ID_SI_741		0x0741
+#endif
+#ifndef PCI_DEVICE_ID_SI_660
+#define PCI_DEVICE_ID_SI_660		0x0660
+#endif
+#ifndef PCI_DEVICE_ID_SI_760
+#define PCI_DEVICE_ID_SI_760		0x0760
+#endif
+#ifndef PCI_DEVICE_ID_SI_761
+#define PCI_DEVICE_ID_SI_761		0x0761
+#endif
+
+#ifndef PCI_VENDOR_ID_XGI
+#define PCI_VENDOR_ID_XGI		0x18ca
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_20
+#define PCI_DEVICE_ID_XGI_20		0x0020
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_40
+#define PCI_DEVICE_ID_XGI_40		0x0040
+#endif
+
+/* To be included in fb.h */
+#ifndef FB_ACCEL_SIS_GLAMOUR_2
+#define FB_ACCEL_SIS_GLAMOUR_2	40	/* SiS 315, 65x, 740, 661, 741  */
+#endif
+#ifndef FB_ACCEL_SIS_XABRE
+#define FB_ACCEL_SIS_XABRE	41	/* SiS 330 ("Xabre"), 76x 	*/
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_V
+#define FB_ACCEL_XGI_VOLARI_V	47	/* XGI Volari Vx (V3XT, V5, V8)	*/
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_Z
+#define FB_ACCEL_XGI_VOLARI_Z	48	/* XGI Volari Z7		*/
+#endif
+
+/* ivideo->caps */
+#define HW_CURSOR_CAP		0x80
+#define TURBO_QUEUE_CAP		0x40
+#define AGP_CMD_QUEUE_CAP	0x20
+#define VM_CMD_QUEUE_CAP	0x10
+#define MMIO_CMD_QUEUE_CAP	0x08
+
+/* For 300 series */
+#define TURBO_QUEUE_AREA_SIZE	(512 * 1024)	/* 512K */
+#define HW_CURSOR_AREA_SIZE_300	4096		/* 4K */
+
+/* For 315/Xabre series */
+#define COMMAND_QUEUE_AREA_SIZE	(512 * 1024)	/* 512K */
+#define COMMAND_QUEUE_AREA_SIZE_Z7 (128 * 1024)	/* 128k for XGI Z7 */
+#define HW_CURSOR_AREA_SIZE_315	16384		/* 16K */
+#define COMMAND_QUEUE_THRESHOLD	0x1F
+
+#define SIS_OH_ALLOC_SIZE	4000
+#define SENTINEL		0x7fffffff
+
+#define SEQ_ADR			0x14
+#define SEQ_DATA		0x15
+#define DAC_ADR			0x18
+#define DAC_DATA		0x19
+#define CRTC_ADR		0x24
+#define CRTC_DATA		0x25
+#define DAC2_ADR		(0x16-0x30)
+#define DAC2_DATA		(0x17-0x30)
+#define VB_PART1_ADR		(0x04-0x30)
+#define VB_PART1_DATA		(0x05-0x30)
+#define VB_PART2_ADR		(0x10-0x30)
+#define VB_PART2_DATA		(0x11-0x30)
+#define VB_PART3_ADR		(0x12-0x30)
+#define VB_PART3_DATA		(0x13-0x30)
+#define VB_PART4_ADR		(0x14-0x30)
+#define VB_PART4_DATA		(0x15-0x30)
+
+#define SISSR			ivideo->SiS_Pr.SiS_P3c4
+#define SISCR			ivideo->SiS_Pr.SiS_P3d4
+#define SISDACA			ivideo->SiS_Pr.SiS_P3c8
+#define SISDACD			ivideo->SiS_Pr.SiS_P3c9
+#define SISPART1		ivideo->SiS_Pr.SiS_Part1Port
+#define SISPART2		ivideo->SiS_Pr.SiS_Part2Port
+#define SISPART3		ivideo->SiS_Pr.SiS_Part3Port
+#define SISPART4		ivideo->SiS_Pr.SiS_Part4Port
+#define SISPART5		ivideo->SiS_Pr.SiS_Part5Port
+#define SISDAC2A		SISPART5
+#define SISDAC2D		(SISPART5 + 1)
+#define SISMISCR		(ivideo->SiS_Pr.RelIO + 0x1c)
+#define SISMISCW		ivideo->SiS_Pr.SiS_P3c2
+#define SISINPSTAT		(ivideo->SiS_Pr.RelIO + 0x2a)
+#define SISPEL			ivideo->SiS_Pr.SiS_P3c6
+#define SISVGAENABLE		(ivideo->SiS_Pr.RelIO + 0x13)
+#define SISVID			(ivideo->SiS_Pr.RelIO + 0x02 - 0x30)
+#define SISCAP			(ivideo->SiS_Pr.RelIO + 0x00 - 0x30)
+
+#define IND_SIS_PASSWORD		0x05  /* SRs */
+#define IND_SIS_COLOR_MODE		0x06
+#define IND_SIS_RAMDAC_CONTROL		0x07
+#define IND_SIS_DRAM_SIZE		0x14
+#define IND_SIS_MODULE_ENABLE		0x1E
+#define IND_SIS_PCI_ADDRESS_SET		0x20
+#define IND_SIS_TURBOQUEUE_ADR		0x26
+#define IND_SIS_TURBOQUEUE_SET		0x27
+#define IND_SIS_POWER_ON_TRAP		0x38
+#define IND_SIS_POWER_ON_TRAP2		0x39
+#define IND_SIS_CMDQUEUE_SET		0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD	0x27
+
+#define IND_SIS_AGP_IO_PAD	0x48
+
+#define SIS_CRT2_WENABLE_300	0x24  /* Part1 */
+#define SIS_CRT2_WENABLE_315	0x2F
+
+#define SIS_PASSWORD		0x86  /* SR05 */
+
+#define SIS_INTERLACED_MODE	0x20  /* SR06 */
+#define SIS_8BPP_COLOR_MODE	0x0
+#define SIS_15BPP_COLOR_MODE	0x1
+#define SIS_16BPP_COLOR_MODE	0x2
+#define SIS_32BPP_COLOR_MODE	0x4
+
+#define SIS_ENABLE_2D		0x40  /* SR1E */
+
+#define SIS_MEM_MAP_IO_ENABLE	0x01  /* SR20 */
+#define SIS_PCI_ADDR_ENABLE	0x80
+
+#define SIS_AGP_CMDQUEUE_ENABLE		0x80  /* 315/330/340 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE	0x40
+#define SIS_MMIO_CMD_ENABLE		0x20
+#define SIS_CMD_QUEUE_SIZE_512k		0x00
+#define SIS_CMD_QUEUE_SIZE_1M		0x04
+#define SIS_CMD_QUEUE_SIZE_2M		0x08
+#define SIS_CMD_QUEUE_SIZE_4M		0x0C
+#define SIS_CMD_QUEUE_RESET		0x01
+#define SIS_CMD_AUTO_CORR		0x02
+
+#define SIS_CMD_QUEUE_SIZE_Z7_64k	0x00 /* XGI Z7 */
+#define SIS_CMD_QUEUE_SIZE_Z7_128k	0x04
+
+#define SIS_SIMULTANEOUS_VIEW_ENABLE	0x01  /* CR30 */
+#define SIS_MODE_SELECT_CRT2		0x02
+#define SIS_VB_OUTPUT_COMPOSITE		0x04
+#define SIS_VB_OUTPUT_SVIDEO		0x08
+#define SIS_VB_OUTPUT_SCART		0x10
+#define SIS_VB_OUTPUT_LCD		0x20
+#define SIS_VB_OUTPUT_CRT2		0x40
+#define SIS_VB_OUTPUT_HIVISION		0x80
+
+#define SIS_VB_OUTPUT_DISABLE	0x20  /* CR31 */
+#define SIS_DRIVER_MODE		0x40
+
+#define SIS_VB_COMPOSITE	0x01  /* CR32 */
+#define SIS_VB_SVIDEO		0x02
+#define SIS_VB_SCART		0x04
+#define SIS_VB_LCD		0x08
+#define SIS_VB_CRT2		0x10
+#define SIS_CRT1		0x20
+#define SIS_VB_HIVISION		0x40
+#define SIS_VB_YPBPR		0x80
+#define SIS_VB_TV		(SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
+				SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
+
+#define SIS_EXTERNAL_CHIP_MASK			0x0E  /* CR37 (< SiS 660) */
+#define SIS_EXTERNAL_CHIP_SIS301		0x01  /* in CR37 << 1 ! */
+#define SIS_EXTERNAL_CHIP_LVDS			0x02
+#define SIS_EXTERNAL_CHIP_TRUMPION		0x03
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL		0x04
+#define SIS_EXTERNAL_CHIP_CHRONTEL		0x05
+#define SIS310_EXTERNAL_CHIP_LVDS		0x02
+#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL	0x03
+
+#define SIS_AGP_2X		0x20  /* CR48 */
+
+/* vbflags, private entries (others in sisfb.h) */
+#define VB_CONEXANT		0x00000800	/* 661 series only */
+#define VB_TRUMPION		VB_CONEXANT	/* 300 series only */
+#define VB_302ELV		0x00004000
+#define VB_301			0x00100000	/* Video bridge type */
+#define VB_301B			0x00200000
+#define VB_302B			0x00400000
+#define VB_30xBDH		0x00800000	/* 30xB DH version (w/o LCD support) */
+#define VB_LVDS			0x01000000
+#define VB_CHRONTEL		0x02000000
+#define VB_301LV		0x04000000
+#define VB_302LV		0x08000000
+#define VB_301C			0x10000000
+
+#define VB_SISBRIDGE		(VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
+#define VB_VIDEOBRIDGE		(VB_SISBRIDGE | VB_LVDS | VB_CHRONTEL | VB_CONEXANT)
+
+/* vbflags2 (static stuff only!) */
+#define VB2_SISUMC		0x00000001
+#define VB2_301			0x00000002	/* Video bridge type */
+#define VB2_301B		0x00000004
+#define VB2_301C		0x00000008
+#define VB2_307T		0x00000010
+#define VB2_302B		0x00000800
+#define VB2_301LV		0x00001000
+#define VB2_302LV		0x00002000
+#define VB2_302ELV		0x00004000
+#define VB2_307LV		0x00008000
+#define VB2_30xBDH		0x08000000      /* 30xB DH version (w/o LCD support) */
+#define VB2_CONEXANT		0x10000000
+#define VB2_TRUMPION		0x20000000
+#define VB2_LVDS		0x40000000
+#define VB2_CHRONTEL		0x80000000
+
+#define VB2_SISLVDSBRIDGE	(VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_SISTMDSBRIDGE	(VB2_301   | VB2_301B  | VB2_301C   | VB2_302B | VB2_307T)
+#define VB2_SISBRIDGE		(VB2_SISLVDSBRIDGE | VB2_SISTMDSBRIDGE)
+
+#define VB2_SISTMDSLCDABRIDGE	(VB2_301C | VB2_307T)
+#define VB2_SISLCDABRIDGE	(VB2_SISTMDSLCDABRIDGE | VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+
+#define VB2_SISHIVISIONBRIDGE	(VB2_301  | VB2_301B | VB2_302B)
+#define VB2_SISYPBPRBRIDGE	(VB2_301C | VB2_307T | VB2_SISLVDSBRIDGE)
+#define VB2_SISYPBPRARBRIDGE	(VB2_301C | VB2_307T | VB2_307LV)
+#define VB2_SISTAP4SCALER	(VB2_301C | VB2_307T | VB2_302ELV | VB2_307LV)
+#define VB2_SISTVBRIDGE		(VB2_SISHIVISIONBRIDGE | VB2_SISYPBPRBRIDGE)
+
+#define VB2_SISVGA2BRIDGE	(VB2_301 | VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+
+#define VB2_VIDEOBRIDGE		(VB2_SISBRIDGE | VB2_LVDS | VB2_CHRONTEL | VB2_CONEXANT)
+
+#define VB2_30xB		(VB2_301B  | VB2_301C   | VB2_302B  | VB2_307T)
+#define VB2_30xBLV		(VB2_30xB  | VB2_SISLVDSBRIDGE)
+#define VB2_30xC		(VB2_301C  | VB2_307T)
+#define VB2_30xCLV		(VB2_301C  | VB2_307T   | VB2_302ELV| VB2_307LV)
+#define VB2_SISEMIBRIDGE	(VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCD162MHZBRIDGE	(VB2_301C  | VB2_307T)
+#define VB2_LCDOVER1280BRIDGE	(VB2_301C  | VB2_307T   | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCDOVER1600BRIDGE	(VB2_307T  | VB2_307LV)
+#define VB2_RAMDAC202MHZBRIDGE	(VB2_301C  | VB2_307T)
+
+/* I/O port access functions */
+
+void SiS_SetReg(SISIOADDRESS, u8, u8);
+void SiS_SetRegByte(SISIOADDRESS, u8);
+void SiS_SetRegShort(SISIOADDRESS, u16);
+void SiS_SetRegLong(SISIOADDRESS, u32);
+void SiS_SetRegANDOR(SISIOADDRESS, u8, u8, u8);
+void SiS_SetRegAND(SISIOADDRESS, u8, u8);
+void SiS_SetRegOR(SISIOADDRESS, u8, u8);
+u8 SiS_GetReg(SISIOADDRESS, u8);
+u8 SiS_GetRegByte(SISIOADDRESS);
+u16 SiS_GetRegShort(SISIOADDRESS);
+u32 SiS_GetRegLong(SISIOADDRESS);
+
+/* MMIO access macros */
+#define MMIO_IN8(base, offset)  readb((base+offset))
+#define MMIO_IN16(base, offset) readw((base+offset))
+#define MMIO_IN32(base, offset) readl((base+offset))
+
+#define MMIO_OUT8(base, offset, val)  writeb(((u8)(val)), (base+offset))
+#define MMIO_OUT16(base, offset, val) writew(((u16)(val)), (base+offset))
+#define MMIO_OUT32(base, offset, val) writel(((u32)(val)), (base+offset))
+
+/* Queue control MMIO registers */
+#define Q_BASE_ADDR		0x85C0  /* Base address of software queue */
+#define Q_WRITE_PTR		0x85C4  /* Current write pointer */
+#define Q_READ_PTR		0x85C8  /* Current read pointer */
+#define Q_STATUS		0x85CC  /* queue status */
+
+#define MMIO_QUEUE_PHYBASE      Q_BASE_ADDR
+#define MMIO_QUEUE_WRITEPORT    Q_WRITE_PTR
+#define MMIO_QUEUE_READPORT     Q_READ_PTR
+
+#ifndef FB_BLANK_UNBLANK
+#define FB_BLANK_UNBLANK	0
+#endif
+#ifndef FB_BLANK_NORMAL
+#define FB_BLANK_NORMAL		1
+#endif
+#ifndef FB_BLANK_VSYNC_SUSPEND
+#define FB_BLANK_VSYNC_SUSPEND	2
+#endif
+#ifndef FB_BLANK_HSYNC_SUSPEND
+#define FB_BLANK_HSYNC_SUSPEND	3
+#endif
+#ifndef FB_BLANK_POWERDOWN
+#define FB_BLANK_POWERDOWN	4
+#endif
+
+enum _SIS_LCD_TYPE {
+    LCD_INVALID = 0,
+    LCD_800x600,
+    LCD_1024x768,
+    LCD_1280x1024,
+    LCD_1280x960,
+    LCD_640x480,
+    LCD_1600x1200,
+    LCD_1920x1440,
+    LCD_2048x1536,
+    LCD_320x240,	/* FSTN */
+    LCD_1400x1050,
+    LCD_1152x864,
+    LCD_1152x768,
+    LCD_1280x768,
+    LCD_1024x600,
+    LCD_320x240_2,	/* DSTN */
+    LCD_320x240_3,	/* DSTN */
+    LCD_848x480,
+    LCD_1280x800,
+    LCD_1680x1050,
+    LCD_1280x720,
+    LCD_1280x854,
+    LCD_CUSTOM,
+    LCD_UNKNOWN
+};
+
+enum _SIS_CMDTYPE {
+    MMIO_CMD = 0,
+    AGP_CMD_QUEUE,
+    VM_CMD_QUEUE,
+};
+
+struct SIS_OH {
+	struct SIS_OH *poh_next;
+	struct SIS_OH *poh_prev;
+	u32            offset;
+	u32            size;
+};
+
+struct SIS_OHALLOC {
+	struct SIS_OHALLOC *poha_next;
+	struct SIS_OH aoh[1];
+};
+
+struct SIS_HEAP {
+	struct SIS_OH	oh_free;
+	struct SIS_OH	oh_used;
+	struct SIS_OH	*poh_freelist;
+	struct SIS_OHALLOC *poha_chain;
+	u32		max_freesize;
+	struct sis_video_info *vinfo;
+};
+
+/* Our "par" */
+struct sis_video_info {
+	int		cardnumber;
+	struct fb_info  *memyselfandi;
+
+	struct SiS_Private SiS_Pr;
+
+	struct sisfb_info sisfbinfo;	/* For ioctl SISFB_GET_INFO */
+
+	struct fb_var_screeninfo default_var;
+
+	struct fb_fix_screeninfo sisfb_fix;
+	u32		pseudo_palette[16];
+
+	struct sisfb_monitor {
+		u16 hmin;
+		u16 hmax;
+		u16 vmin;
+		u16 vmax;
+		u32 dclockmax;
+		u8  feature;
+		bool datavalid;
+	}		sisfb_thismonitor;
+
+	unsigned short	chip_id;	/* PCI ID of chip */
+	unsigned short	chip_vendor;	/* PCI ID of vendor */
+	char		myid[40];
+
+	struct pci_dev  *nbridge;
+	struct pci_dev  *lpcdev;
+
+	int		mni;	/* Mode number index */
+
+	unsigned long	video_size;
+	unsigned long	video_base;
+	unsigned long	mmio_size;
+	unsigned long	mmio_base;
+	unsigned long	vga_base;
+
+	unsigned long	video_offset;
+
+	unsigned long	UMAsize, LFBsize;
+
+	void __iomem	*video_vbase;
+	void __iomem	*mmio_vbase;
+
+	unsigned char	*bios_abase;
+
+	int		mtrr;
+
+	u32		sisfb_mem;
+
+	u32		sisfb_parm_mem;
+	int		sisfb_accel;
+	int		sisfb_ypan;
+	int		sisfb_max;
+	int		sisfb_userom;
+	int		sisfb_useoem;
+	int		sisfb_mode_idx;
+	int		sisfb_parm_rate;
+	int		sisfb_crt1off;
+	int		sisfb_forcecrt1;
+	int		sisfb_crt2type;
+	int		sisfb_crt2flags;
+	int		sisfb_dstn;
+	int		sisfb_fstn;
+	int		sisfb_tvplug;
+	int		sisfb_tvstd;
+	int		sisfb_nocrt2rate;
+
+	u32		heapstart;		/* offset  */
+	void __iomem	*sisfb_heap_start;	/* address */
+	void __iomem	*sisfb_heap_end;	/* address */
+	u32		sisfb_heap_size;
+	int		havenoheap;
+
+	struct SIS_HEAP	sisfb_heap;		/* This card's vram heap */
+
+	int		video_bpp;
+	int		video_cmap_len;
+	int		video_width;
+	int		video_height;
+	unsigned int	refresh_rate;
+
+	unsigned int	chip;
+	unsigned int	chip_real_id;
+	u8		revision_id;
+	int		sisvga_enabled;		/* PCI device was enabled */
+
+	int		video_linelength;	/* real pitch */
+	int		scrnpitchCRT1;		/* pitch regarding interlace */
+
+	u16		DstColor;		/* For 2d acceleration */
+	u32		SiS310_AccelDepth;
+	u32		CommandReg;
+	int		cmdqueuelength;		/* Current (for accel) */
+	u32		cmdQueueSize;		/* Total size in KB */
+
+	spinlock_t	lockaccel;		/* Do not use outside of kernel! */
+
+	unsigned int	pcibus;
+	unsigned int	pcislot;
+	unsigned int	pcifunc;
+
+	int		accel;
+	int		engineok;
+
+	u16		subsysvendor;
+	u16		subsysdevice;
+
+	u32		vbflags;		/* Replacing deprecated stuff from above */
+	u32		currentvbflags;
+	u32		vbflags2;
+
+	int		lcdxres, lcdyres;
+	int		lcddefmodeidx, tvdefmodeidx, defmodeidx;
+	u32		CRT2LCDType;		/* defined in "SIS_LCD_TYPE" */
+	u32		curFSTN, curDSTN;
+
+	int		current_bpp;
+	int		current_width;
+	int		current_height;
+	int		current_htotal;
+	int		current_vtotal;
+	int		current_linelength;
+	__u32		current_pixclock;
+	int		current_refresh_rate;
+
+	unsigned int	current_base;
+
+	u8		mode_no;
+	u8		rate_idx;
+	int		modechanged;
+	unsigned char	modeprechange;
+
+	u8		sisfb_lastrates[128];
+
+	int		newrom;
+	int		haveXGIROM;
+	int		registered;
+	int		warncount;
+
+	int		sisvga_engine;
+	int		hwcursor_size;
+	int		CRT2_write_enable;
+	u8		caps;
+
+	u8		detectedpdc;
+	u8		detectedpdca;
+	u8		detectedlcda;
+
+	void __iomem	*hwcursor_vbase;
+
+	int		chronteltype;
+	int		tvxpos, tvypos;
+	u8		p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
+	int		tvx, tvy;
+
+	u8		sisfblocked;
+
+	struct sisfb_info sisfb_infoblock;
+
+	struct sisfb_cmd sisfb_command;
+
+	u32		sisfb_id;
+
+	u8		sisfb_can_post;
+	u8		sisfb_card_posted;
+	u8		sisfb_was_boot_device;
+
+	struct sis_video_info *next;
+};
+
+#endif
diff --git a/drivers/video/fbdev/sis/sis_accel.c b/drivers/video/fbdev/sis/sis_accel.c
new file mode 100644
index 000000000000..ceb434c95c0d
--- /dev/null
+++ b/drivers/video/fbdev/sis/sis_accel.c
@@ -0,0 +1,423 @@
+/*
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
+ *
+ * 2D acceleration part
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Based on the XFree86/X.org driver which is
+ *     Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *			(see http://www.winischhofer.net/
+ *			for more information and updates)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "sis.h"
+#include "sis_accel.h"
+
+static const u8 sisALUConv[] =
+{
+    0x00,       /* dest = 0;            0,      GXclear,        0 */
+    0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
+    0x44,       /* dest = src & ~dest;  SDna,   GXandReverse,   0x2 */
+    0xCC,       /* dest = src;          S,      GXcopy,         0x3 */
+    0x22,       /* dest &= ~src;        DSna,   GXandInverted,  0x4 */
+    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
+    0x66,       /* dest = ^src;         DSx,    GXxor,          0x6 */
+    0xEE,       /* dest |= src;         DSo,    GXor,           0x7 */
+    0x11,       /* dest = ~src & ~dest; DSon,   GXnor,          0x8 */
+    0x99,       /* dest ^= ~src ;       DSxn,   GXequiv,        0x9 */
+    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
+    0xDD,       /* dest = src|~dest ;   SDno,   GXorReverse,    0xB */
+    0x33,       /* dest = ~src;         Sn,     GXcopyInverted, 0xC */
+    0xBB,       /* dest |= ~src;        DSno,   GXorInverted,   0xD */
+    0x77,       /* dest = ~src|~dest;   DSan,   GXnand,         0xE */
+    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
+};
+/* same ROP but with Pattern as Source */
+static const u8 sisPatALUConv[] =
+{
+    0x00,       /* dest = 0;            0,      GXclear,        0 */
+    0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
+    0x50,       /* dest = src & ~dest;  PDna,   GXandReverse,   0x2 */
+    0xF0,       /* dest = src;          P,      GXcopy,         0x3 */
+    0x0A,       /* dest &= ~src;        DPna,   GXandInverted,  0x4 */
+    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
+    0x5A,       /* dest = ^src;         DPx,    GXxor,          0x6 */
+    0xFA,       /* dest |= src;         DPo,    GXor,           0x7 */
+    0x05,       /* dest = ~src & ~dest; DPon,   GXnor,          0x8 */
+    0xA5,       /* dest ^= ~src ;       DPxn,   GXequiv,        0x9 */
+    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
+    0xF5,       /* dest = src|~dest ;   PDno,   GXorReverse,    0xB */
+    0x0F,       /* dest = ~src;         Pn,     GXcopyInverted, 0xC */
+    0xAF,       /* dest |= ~src;        DPno,   GXorInverted,   0xD */
+    0x5F,       /* dest = ~src|~dest;   DPan,   GXnand,         0xE */
+    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
+};
+
+static const int myrops[] = {
+   	3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
+};
+
+/* 300 series ----------------------------------------------------- */
+#ifdef CONFIG_FB_SIS_300
+static void
+SiS300Sync(struct sis_video_info *ivideo)
+{
+	SiS300Idle
+}
+
+static void
+SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir,
+                                 int rop, int trans_color)
+{
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
+	SiS300SetupSRCPitch(ivideo->video_linelength)
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
+
+	if(trans_color != -1) {
+		SiS300SetupROP(0x0A)
+		SiS300SetupSRCTrans(trans_color)
+		SiS300SetupCMDFlag(TRANSPARENT_BITBLT)
+	} else {
+	        SiS300SetupROP(sisALUConv[rop])
+	}
+	if(xdir > 0) {
+		SiS300SetupCMDFlag(X_INC)
+	}
+	if(ydir > 0) {
+		SiS300SetupCMDFlag(Y_INC)
+	}
+}
+
+static void
+SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x,
+				   int src_y, int dst_x, int dst_y, int width, int height)
+{
+	u32 srcbase = 0, dstbase = 0;
+
+	if(src_y >= 2048) {
+		srcbase = ivideo->video_linelength * src_y;
+		src_y = 0;
+	}
+	if(dst_y >= 2048) {
+		dstbase = ivideo->video_linelength * dst_y;
+		dst_y = 0;
+	}
+
+	SiS300SetupSRCBase(srcbase);
+	SiS300SetupDSTBase(dstbase);
+
+	if(!(ivideo->CommandReg & X_INC))  {
+		src_x += width-1;
+		dst_x += width-1;
+	}
+	if(!(ivideo->CommandReg & Y_INC))  {
+		src_y += height-1;
+		dst_y += height-1;
+	}
+	SiS300SetupRect(width, height)
+	SiS300SetupSRCXY(src_x, src_y)
+	SiS300SetupDSTXY(dst_x, dst_y)
+	SiS300DoCMD
+}
+
+static void
+SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
+{
+	SiS300SetupPATFG(color)
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
+	SiS300SetupROP(sisPatALUConv[rop])
+	SiS300SetupCMDFlag(PATFG)
+}
+
+static void
+SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
+{
+	u32 dstbase = 0;
+
+	if(y >= 2048) {
+		dstbase = ivideo->video_linelength * y;
+		y = 0;
+	}
+	SiS300SetupDSTBase(dstbase)
+	SiS300SetupDSTXY(x,y)
+	SiS300SetupRect(w,h)
+	SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT)
+	SiS300DoCMD
+}
+#endif
+
+/* 315/330/340 series ---------------------------------------------- */
+
+#ifdef CONFIG_FB_SIS_315
+static void
+SiS310Sync(struct sis_video_info *ivideo)
+{
+	SiS310Idle
+}
+
+static void
+SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color)
+{
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
+	SiS310SetupSRCPitch(ivideo->video_linelength)
+	SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
+	if(trans_color != -1) {
+		SiS310SetupROP(0x0A)
+		SiS310SetupSRCTrans(trans_color)
+		SiS310SetupCMDFlag(TRANSPARENT_BITBLT)
+	} else {
+	        SiS310SetupROP(sisALUConv[rop])
+		/* Set command - not needed, both 0 */
+		/* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
+	}
+	SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
+	/* The chip is smart enough to know the direction */
+}
+
+static void
+SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y,
+			 int dst_x, int dst_y, int width, int height)
+{
+	u32 srcbase = 0, dstbase = 0;
+	int mymin = min(src_y, dst_y);
+	int mymax = max(src_y, dst_y);
+
+	/* Although the chip knows the direction to use
+	 * if the source and destination areas overlap,
+	 * that logic fails if we fiddle with the bitmap
+	 * addresses. Therefore, we check if the source
+	 * and destination blitting areas overlap and
+	 * adapt the bitmap addresses synchronously
+	 * if the coordinates exceed the valid range.
+	 * The the areas do not overlap, we do our
+	 * normal check.
+	 */
+	if((mymax - mymin) < height) {
+		if((src_y >= 2048) || (dst_y >= 2048)) {
+			srcbase = ivideo->video_linelength * mymin;
+			dstbase = ivideo->video_linelength * mymin;
+			src_y -= mymin;
+			dst_y -= mymin;
+		}
+	} else {
+		if(src_y >= 2048) {
+			srcbase = ivideo->video_linelength * src_y;
+			src_y = 0;
+		}
+		if(dst_y >= 2048) {
+			dstbase = ivideo->video_linelength * dst_y;
+			dst_y = 0;
+		}
+	}
+
+	srcbase += ivideo->video_offset;
+	dstbase += ivideo->video_offset;
+
+	SiS310SetupSRCBase(srcbase);
+	SiS310SetupDSTBase(dstbase);
+	SiS310SetupRect(width, height)
+	SiS310SetupSRCXY(src_x, src_y)
+	SiS310SetupDSTXY(dst_x, dst_y)
+	SiS310DoCMD
+}
+
+static void
+SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
+{
+	SiS310SetupPATFG(color)
+	SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
+	SiS310SetupROP(sisPatALUConv[rop])
+	SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
+}
+
+static void
+SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
+{
+	u32 dstbase = 0;
+
+	if(y >= 2048) {
+		dstbase = ivideo->video_linelength * y;
+		y = 0;
+	}
+	dstbase += ivideo->video_offset;
+	SiS310SetupDSTBase(dstbase)
+	SiS310SetupDSTXY(x,y)
+	SiS310SetupRect(w,h)
+	SiS310SetupCMDFlag(BITBLT)
+	SiS310DoCMD
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+/* The exported routines */
+
+int sisfb_initaccel(struct sis_video_info *ivideo)
+{
+#ifdef SISFB_USE_SPINLOCKS
+	spin_lock_init(&ivideo->lockaccel);
+#endif
+	return 0;
+}
+
+void sisfb_syncaccel(struct sis_video_info *ivideo)
+{
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+		SiS300Sync(ivideo);
+#endif
+	} else {
+#ifdef CONFIG_FB_SIS_315
+		SiS310Sync(ivideo);
+#endif
+	}
+}
+
+int fbcon_sis_sync(struct fb_info *info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	CRITFLAGS
+
+	if((!ivideo->accel) || (!ivideo->engineok))
+		return 0;
+
+	CRITBEGIN
+	sisfb_syncaccel(ivideo);
+	CRITEND
+
+	return 0;
+}
+
+void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	u32 col = 0;
+	u32 vxres = info->var.xres_virtual;
+	u32 vyres = info->var.yres_virtual;
+	int width, height;
+	CRITFLAGS
+
+	if(info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if((!ivideo->accel) || (!ivideo->engineok)) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres)
+		return;
+
+	/* Clipping */
+	width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+	height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+
+	switch(info->var.bits_per_pixel) {
+	case 8:  col = rect->color;
+		 break;
+	case 16:
+	case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
+		 break;
+	}
+
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+		CRITBEGIN
+		SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+		SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+		CRITEND
+#endif
+	} else {
+#ifdef CONFIG_FB_SIS_315
+		CRITBEGIN
+		SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+		SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+		CRITEND
+#endif
+	}
+
+	sisfb_syncaccel(ivideo);
+}
+
+void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	u32 vxres = info->var.xres_virtual;
+	u32 vyres = info->var.yres_virtual;
+	int width = area->width;
+	int height = area->height;
+	CRITFLAGS
+
+	if(info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if((!ivideo->accel) || (!ivideo->engineok)) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	if(!width || !height ||
+	   area->sx >= vxres || area->sy >= vyres ||
+	   area->dx >= vxres || area->dy >= vyres)
+		return;
+
+	/* Clipping */
+	if((area->sx + width) > vxres) width = vxres - area->sx;
+	if((area->dx + width) > vxres) width = vxres - area->dx;
+	if((area->sy + height) > vyres) height = vyres - area->sy;
+	if((area->dy + height) > vyres) height = vyres - area->dy;
+
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+		int xdir, ydir;
+
+		if(area->sx < area->dx) xdir = 0;
+		else                    xdir = 1;
+		if(area->sy < area->dy) ydir = 0;
+		else                    ydir = 1;
+
+		CRITBEGIN
+		SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+		SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+					area->dx, area->dy, width, height);
+		CRITEND
+#endif
+	} else {
+#ifdef CONFIG_FB_SIS_315
+		CRITBEGIN
+		SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+		SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+					area->dx, area->dy, width, height);
+		CRITEND
+#endif
+	}
+
+	sisfb_syncaccel(ivideo);
+}
diff --git a/drivers/video/fbdev/sis/sis_accel.h b/drivers/video/fbdev/sis/sis_accel.h
new file mode 100644
index 000000000000..30e03cdf6b85
--- /dev/null
+++ b/drivers/video/fbdev/sis/sis_accel.h
@@ -0,0 +1,400 @@
+/*
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
+ *
+ * 2D acceleration part
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Based on the X driver's sis300_accel.h which is
+ *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * and sis310_accel.h which is
+ *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ *
+ * Author:   Thomas Winischhofer <thomas@winischhofer.net>:
+ *			(see http://www.winischhofer.net/
+ *			for more information and updates)
+ */
+
+#ifndef _SISFB_ACCEL_H
+#define _SISFB_ACCEL_H
+
+/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */
+#undef SISFB_USE_SPINLOCKS
+
+#ifdef SISFB_USE_SPINLOCKS
+#include <linux/spinlock.h>
+#define CRITBEGIN  spin_lock_irqsave(&ivideo->lockaccel, critflags);
+#define CRITEND	   spin_unlock_irqrestore(&ivideo->lockaccel, critflags);
+#define CRITFLAGS  unsigned long critflags;
+#else
+#define CRITBEGIN
+#define CRITEND
+#define CRITFLAGS
+#endif
+
+/* Definitions for the SIS engine communication. */
+
+#define PATREGSIZE      384  /* Pattern register size. 384 bytes @ 0x8300 */
+#define BR(x)   (0x8200 | (x) << 2)
+#define PBR(x)  (0x8300 | (x) << 2)
+
+/* SiS300 engine commands */
+#define BITBLT                  0x00000000  /* Blit */
+#define COLOREXP                0x00000001  /* Color expand */
+#define ENCOLOREXP              0x00000002  /* Enhanced color expand */
+#define MULTIPLE_SCANLINE       0x00000003  /* ? */
+#define LINE                    0x00000004  /* Draw line */
+#define TRAPAZOID_FILL          0x00000005  /* Fill trapezoid */
+#define TRANSPARENT_BITBLT      0x00000006  /* Transparent Blit */
+
+/* Additional engine commands for 315 */
+#define ALPHA_BLEND		0x00000007  /* Alpha blend ? */
+#define A3D_FUNCTION		0x00000008  /* 3D command ? */
+#define	CLEAR_Z_BUFFER		0x00000009  /* ? */
+#define GRADIENT_FILL		0x0000000A  /* Gradient fill */
+
+/* source select */
+#define SRCVIDEO                0x00000000  /* source is video RAM */
+#define SRCSYSTEM               0x00000010  /* source is system memory */
+#define SRCCPUBLITBUF           SRCSYSTEM   /* source is CPU-driven BitBuffer (for color expand) */
+#define SRCAGP                  0x00000020  /* source is AGP memory (?) */
+
+/* Pattern flags */
+#define PATFG                   0x00000000  /* foreground color */
+#define PATPATREG               0x00000040  /* pattern in pattern buffer (0x8300) */
+#define PATMONO                 0x00000080  /* mono pattern */
+
+/* blitting direction (300 series only) */
+#define X_INC                   0x00010000
+#define X_DEC                   0x00000000
+#define Y_INC                   0x00020000
+#define Y_DEC                   0x00000000
+
+/* Clipping flags */
+#define NOCLIP                  0x00000000
+#define NOMERGECLIP             0x04000000
+#define CLIPENABLE              0x00040000
+#define CLIPWITHOUTMERGE        0x04040000
+
+/* Transparency */
+#define OPAQUE                  0x00000000
+#define TRANSPARENT             0x00100000
+
+/* ? */
+#define DSTAGP                  0x02000000
+#define DSTVIDEO                0x02000000
+
+/* Subfunctions for Color/Enhanced Color Expansion (315 only) */
+#define COLOR_TO_MONO		0x00100000
+#define AA_TEXT			0x00200000
+
+/* Some general registers for 315 series */
+#define SRC_ADDR		0x8200
+#define SRC_PITCH		0x8204
+#define AGP_BASE		0x8206 /* color-depth dependent value */
+#define SRC_Y			0x8208
+#define SRC_X			0x820A
+#define DST_Y			0x820C
+#define DST_X			0x820E
+#define DST_ADDR		0x8210
+#define DST_PITCH		0x8214
+#define DST_HEIGHT		0x8216
+#define RECT_WIDTH		0x8218
+#define RECT_HEIGHT		0x821A
+#define PAT_FGCOLOR		0x821C
+#define PAT_BGCOLOR		0x8220
+#define SRC_FGCOLOR		0x8224
+#define SRC_BGCOLOR		0x8228
+#define MONO_MASK		0x822C
+#define LEFT_CLIP		0x8234
+#define TOP_CLIP		0x8236
+#define RIGHT_CLIP		0x8238
+#define BOTTOM_CLIP		0x823A
+#define COMMAND_READY		0x823C
+#define FIRE_TRIGGER      	0x8240
+
+#define PATTERN_REG		0x8300  /* 384 bytes pattern buffer */
+
+/* Transparent bitblit registers */
+#define TRANS_DST_KEY_HIGH	PAT_FGCOLOR
+#define TRANS_DST_KEY_LOW	PAT_BGCOLOR
+#define TRANS_SRC_KEY_HIGH	SRC_FGCOLOR
+#define TRANS_SRC_KEY_LOW	SRC_BGCOLOR
+
+/* Store queue length in par */
+#define CmdQueLen ivideo->cmdqueuelength
+
+/* ------------- SiS 300 series -------------- */
+
+/* BR(16) (0x8240):
+
+   bit 31 2D engine: 1 is idle,
+   bit 30 3D engine: 1 is idle,
+   bit 29 Command queue: 1 is empty
+   bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
+   bits 15:0:  Current command queue length
+
+*/
+
+#define SiS300Idle \
+  { \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \
+  }
+/* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
+
+#define SiS300SetupSRCBase(base) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\
+	CmdQueLen--;
+
+#define SiS300SetupSRCPitch(pitch) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\
+	CmdQueLen--;
+
+#define SiS300SetupSRCXY(x,y) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\
+	CmdQueLen--;
+
+#define SiS300SetupDSTBase(base) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\
+	CmdQueLen--;
+
+#define SiS300SetupDSTXY(x,y) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\
+	CmdQueLen--;
+
+#define SiS300SetupDSTRect(x,y) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\
+	CmdQueLen--;
+
+#define SiS300SetupDSTColorDepth(bpp) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\
+	CmdQueLen--;
+
+#define SiS300SetupRect(w,h) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\
+	CmdQueLen--;
+
+#define SiS300SetupPATFG(color) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\
+	CmdQueLen--;
+
+#define SiS300SetupPATBG(color) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\
+	CmdQueLen--;
+
+#define SiS300SetupSRCFG(color) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\
+	CmdQueLen--;
+
+#define SiS300SetupSRCBG(color) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\
+	CmdQueLen--;
+
+/* 0x8224 src colorkey high */
+/* 0x8228 src colorkey low */
+/* 0x821c dest colorkey high */
+/* 0x8220 dest colorkey low */
+#define SiS300SetupSRCTrans(color) \
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\
+	CmdQueLen -= 2;
+
+#define SiS300SetupDSTTrans(color) \
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \
+	CmdQueLen -= 2;
+
+#define SiS300SetupMONOPAT(p0,p1) \
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\
+	CmdQueLen -= 2;
+
+#define SiS300SetupClipLT(left,top) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
+
+#define SiS300SetupClipRB(right,bottom) \
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
+
+/* General */
+#define SiS300SetupROP(rop) \
+	ivideo->CommandReg = (rop) << 8;
+
+#define SiS300SetupCMDFlag(flags) \
+	ivideo->CommandReg |= (flags);
+
+#define SiS300DoCMD \
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\
+	CmdQueLen -= 2;
+
+/* -------------- SiS 315/330 series --------------- */
+
+/* Q_STATUS:
+   bit 31 = 1: All engines idle and all queues empty
+   bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty
+   bit 29 = 1: 2D engine is idle
+   bit 28 = 1: 3D engine is idle
+   bit 27 = 1: HW command queue empty
+   bit 26 = 1: 2D queue empty
+   bit 25 = 1: 3D queue empty
+   bit 24 = 1: SW command queue empty
+   bits 23:16: 2D counter 3
+   bits 15:8:  2D counter 2
+   bits 7:0:   2D counter 1
+*/
+
+#define SiS310Idle \
+  { \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	CmdQueLen = 0; \
+  }
+
+#define SiS310SetupSRCBase(base) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\
+	CmdQueLen--;
+
+#define SiS310SetupSRCPitch(pitch) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\
+	CmdQueLen--;
+
+#define SiS310SetupSRCXY(x,y) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
+
+#define SiS310SetupDSTBase(base) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\
+	CmdQueLen--;
+
+#define SiS310SetupDSTXY(x,y) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
+
+#define SiS310SetupDSTRect(x,y) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
+	CmdQueLen--;
+
+#define SiS310SetupDSTColorDepth(bpp) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\
+	CmdQueLen--;
+
+#define SiS310SetupRect(w,h) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
+	CmdQueLen--;
+
+#define SiS310SetupPATFG(color) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\
+	CmdQueLen--;
+
+#define SiS310SetupPATBG(color) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\
+	CmdQueLen--;
+
+#define SiS310SetupSRCFG(color) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\
+	CmdQueLen--;
+
+#define SiS310SetupSRCBG(color) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\
+	CmdQueLen--;
+
+#define SiS310SetupSRCTrans(color) \
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\
+	CmdQueLen -= 2;
+
+#define SiS310SetupDSTTrans(color) \
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \
+	CmdQueLen -= 2;
+
+#define SiS310SetupMONOPAT(p0,p1) \
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\
+	CmdQueLen -= 2;
+
+#define SiS310SetupClipLT(left,top) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
+
+#define SiS310SetupClipRB(right,bottom) \
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
+
+#define SiS310SetupROP(rop) \
+	ivideo->CommandReg = (rop) << 8;
+
+#define SiS310SetupCMDFlag(flags) \
+	ivideo->CommandReg |= (flags);
+
+#define SiS310DoCMD \
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \
+	CmdQueLen -= 2;
+
+int  sisfb_initaccel(struct sis_video_info *ivideo);
+void sisfb_syncaccel(struct sis_video_info *ivideo);
+
+int  fbcon_sis_sync(struct fb_info *info);
+void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+
+#endif
diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c
new file mode 100644
index 000000000000..22ad028bf123
--- /dev/null
+++ b/drivers/video/fbdev/sis/sis_main.c
@@ -0,0 +1,6844 @@
+/*
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
+ *
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Author:	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Author of (practically wiped) code base:
+ *		SiS (www.sis.com)
+ *		Copyright (C) 1999 Silicon Integrated Systems, Inc.
+ *
+ * See http://www.winischhofer.net/ for more information and updates
+ *
+ * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
+ * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/screen_info.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <asm/io.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "sis.h"
+#include "sis_main.h"
+
+#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
+#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
+#warning sisfb will not work!
+#endif
+
+static void sisfb_handle_command(struct sis_video_info *ivideo,
+				 struct sisfb_cmd *sisfb_command);
+
+/* ------------------ Internal helper routines ----------------- */
+
+static void __init
+sisfb_setdefaultparms(void)
+{
+	sisfb_off		= 0;
+	sisfb_parm_mem		= 0;
+	sisfb_accel		= -1;
+	sisfb_ypan		= -1;
+	sisfb_max		= -1;
+	sisfb_userom		= -1;
+	sisfb_useoem		= -1;
+	sisfb_mode_idx		= -1;
+	sisfb_parm_rate		= -1;
+	sisfb_crt1off		= 0;
+	sisfb_forcecrt1		= -1;
+	sisfb_crt2type		= -1;
+	sisfb_crt2flags		= 0;
+	sisfb_pdc		= 0xff;
+	sisfb_pdca		= 0xff;
+	sisfb_scalelcd		= -1;
+	sisfb_specialtiming 	= CUT_NONE;
+	sisfb_lvdshl		= -1;
+	sisfb_dstn		= 0;
+	sisfb_fstn		= 0;
+	sisfb_tvplug		= -1;
+	sisfb_tvstd		= -1;
+	sisfb_tvxposoffset	= 0;
+	sisfb_tvyposoffset	= 0;
+	sisfb_nocrt2rate	= 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+	sisfb_resetcard		= 0;
+	sisfb_videoram		= 0;
+#endif
+}
+
+/* ------------- Parameter parsing -------------- */
+
+static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
+{
+	int i = 0, j = 0;
+
+	/* We don't know the hardware specs yet and there is no ivideo */
+
+	if(vesamode == 0) {
+		if(!quiet)
+			printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
+
+		sisfb_mode_idx = DEFAULT_MODE;
+
+		return;
+	}
+
+	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
+
+	while(sisbios_mode[i++].mode_no[0] != 0) {
+		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
+		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
+			if(sisfb_fstn) {
+				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
+				   sisbios_mode[i-1].mode_no[1] == 0x53)
+					continue;
+			} else {
+				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+				   sisbios_mode[i-1].mode_no[1] == 0x5b)
+					continue;
+			}
+			sisfb_mode_idx = i - 1;
+			j = 1;
+			break;
+		}
+	}
+	if((!j) && !quiet)
+		printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
+}
+
+static void sisfb_search_mode(char *name, bool quiet)
+{
+	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
+	int i = 0;
+	char strbuf[16], strbuf1[20];
+	char *nameptr = name;
+
+	/* We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) {
+		if(!quiet)
+			printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
+
+		sisfb_mode_idx = DEFAULT_MODE;
+		return;
+	}
+
+	if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+		if(!quiet)
+			printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+
+		sisfb_mode_idx = DEFAULT_MODE;
+		return;
+	}
+
+	if(strlen(name) <= 19) {
+		strcpy(strbuf1, name);
+		for(i = 0; i < strlen(strbuf1); i++) {
+			if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
+		}
+
+		/* This does some fuzzy mode naming detection */
+		if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
+			if((rate <= 32) || (depth > 32)) {
+				j = rate; rate = depth; depth = j;
+			}
+			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+			nameptr = strbuf;
+			sisfb_parm_rate = rate;
+		} else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
+			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+			nameptr = strbuf;
+		} else {
+			xres = 0;
+			if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
+				sprintf(strbuf, "%ux%ux8", xres, yres);
+				nameptr = strbuf;
+			} else {
+				sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
+				return;
+			}
+		}
+	}
+
+	i = 0; j = 0;
+	while(sisbios_mode[i].mode_no[0] != 0) {
+		if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
+			if(sisfb_fstn) {
+				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
+				   sisbios_mode[i-1].mode_no[1] == 0x53)
+					continue;
+			} else {
+				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+				   sisbios_mode[i-1].mode_no[1] == 0x5b)
+					continue;
+			}
+			sisfb_mode_idx = i - 1;
+			j = 1;
+			break;
+		}
+	}
+
+	if((!j) && !quiet)
+		printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
+}
+
+#ifndef MODULE
+static void sisfb_get_vga_mode_from_kernel(void)
+{
+#ifdef CONFIG_X86
+	char mymode[32];
+	int  mydepth = screen_info.lfb_depth;
+
+	if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
+
+	if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
+	    (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
+	    (mydepth >= 8) && (mydepth <= 32) ) {
+
+		if(mydepth == 24) mydepth = 32;
+
+		sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
+					screen_info.lfb_height,
+					mydepth);
+
+		printk(KERN_DEBUG
+			"sisfb: Using vga mode %s pre-set by kernel as default\n",
+			mymode);
+
+		sisfb_search_mode(mymode, true);
+	}
+#endif
+	return;
+}
+#endif
+
+static void __init
+sisfb_search_crt2type(const char *name)
+{
+	int i = 0;
+
+	/* We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	while(sis_crt2type[i].type_no != -1) {
+		if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+			sisfb_crt2type = sis_crt2type[i].type_no;
+			sisfb_tvplug = sis_crt2type[i].tvplug_no;
+			sisfb_crt2flags = sis_crt2type[i].flags;
+			break;
+		}
+		i++;
+	}
+
+	sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
+	sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
+
+	if(sisfb_crt2type < 0)
+		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
+}
+
+static void __init
+sisfb_search_tvstd(const char *name)
+{
+	int i = 0;
+
+	/* We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL)
+		return;
+
+	while(sis_tvtype[i].type_no != -1) {
+		if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+			sisfb_tvstd = sis_tvtype[i].type_no;
+			break;
+		}
+		i++;
+	}
+}
+
+static void __init
+sisfb_search_specialtiming(const char *name)
+{
+	int i = 0;
+	bool found = false;
+
+	/* We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL)
+		return;
+
+	if(!strnicmp(name, "none", 4)) {
+		sisfb_specialtiming = CUT_FORCENONE;
+		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
+	} else {
+		while(mycustomttable[i].chipID != 0) {
+			if(!strnicmp(name,mycustomttable[i].optionName,
+			   strlen(mycustomttable[i].optionName))) {
+				sisfb_specialtiming = mycustomttable[i].SpecialID;
+				found = true;
+				printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+					mycustomttable[i].vendorName,
+					mycustomttable[i].cardName,
+					mycustomttable[i].optionName);
+				break;
+			}
+			i++;
+		}
+		if(!found) {
+			printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
+			printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
+			i = 0;
+			while(mycustomttable[i].chipID != 0) {
+				printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
+					mycustomttable[i].optionName,
+					mycustomttable[i].vendorName,
+					mycustomttable[i].cardName);
+				i++;
+			}
+		}
+	}
+}
+
+/* ----------- Various detection routines ----------- */
+
+static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
+{
+	unsigned char *biosver = NULL;
+	unsigned char *biosdate = NULL;
+	bool footprint;
+	u32 chksum = 0;
+	int i, j;
+
+	if(ivideo->SiS_Pr.UseROM) {
+		biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
+		biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
+		for(i = 0; i < 32768; i++)
+			chksum += ivideo->SiS_Pr.VirtualRomBase[i];
+	}
+
+	i = 0;
+	do {
+		if( (mycustomttable[i].chipID == ivideo->chip)			&&
+		    ((!strlen(mycustomttable[i].biosversion)) ||
+		     (ivideo->SiS_Pr.UseROM &&
+		      (!strncmp(mycustomttable[i].biosversion, biosver,
+				strlen(mycustomttable[i].biosversion)))))	&&
+		    ((!strlen(mycustomttable[i].biosdate)) ||
+		     (ivideo->SiS_Pr.UseROM &&
+		      (!strncmp(mycustomttable[i].biosdate, biosdate,
+				strlen(mycustomttable[i].biosdate)))))		&&
+		    ((!mycustomttable[i].bioschksum) ||
+		     (ivideo->SiS_Pr.UseROM &&
+		      (mycustomttable[i].bioschksum == chksum)))		&&
+		    (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
+		    (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
+			footprint = true;
+			for(j = 0; j < 5; j++) {
+				if(mycustomttable[i].biosFootprintAddr[j]) {
+					if(ivideo->SiS_Pr.UseROM) {
+						if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
+							mycustomttable[i].biosFootprintData[j]) {
+							footprint = false;
+						}
+					} else
+						footprint = false;
+				}
+			}
+			if(footprint) {
+				ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+				printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
+					mycustomttable[i].vendorName,
+				mycustomttable[i].cardName);
+				printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
+					mycustomttable[i].optionName);
+				break;
+			}
+		}
+		i++;
+	} while(mycustomttable[i].chipID);
+}
+
+static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
+{
+	int i, j, xres, yres, refresh, index;
+	u32 emodes;
+
+	if(buffer[0] != 0x00 || buffer[1] != 0xff ||
+	   buffer[2] != 0xff || buffer[3] != 0xff ||
+	   buffer[4] != 0xff || buffer[5] != 0xff ||
+	   buffer[6] != 0xff || buffer[7] != 0x00) {
+		printk(KERN_DEBUG "sisfb: Bad EDID header\n");
+		return false;
+	}
+
+	if(buffer[0x12] != 0x01) {
+		printk(KERN_INFO "sisfb: EDID version %d not supported\n",
+			buffer[0x12]);
+		return false;
+	}
+
+	monitor->feature = buffer[0x18];
+
+	if(!(buffer[0x14] & 0x80)) {
+		if(!(buffer[0x14] & 0x08)) {
+			printk(KERN_INFO
+				"sisfb: WARNING: Monitor does not support separate syncs\n");
+		}
+	}
+
+	if(buffer[0x13] >= 0x01) {
+	   /* EDID V1 rev 1 and 2: Search for monitor descriptor
+	    * to extract ranges
+	    */
+	    j = 0x36;
+	    for(i=0; i<4; i++) {
+	       if(buffer[j]     == 0x00 && buffer[j + 1] == 0x00 &&
+		  buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
+		  buffer[j + 4] == 0x00) {
+		  monitor->hmin = buffer[j + 7];
+		  monitor->hmax = buffer[j + 8];
+		  monitor->vmin = buffer[j + 5];
+		  monitor->vmax = buffer[j + 6];
+		  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
+		  monitor->datavalid = true;
+		  break;
+	       }
+	       j += 18;
+	    }
+	}
+
+	if(!monitor->datavalid) {
+	   /* Otherwise: Get a range from the list of supported
+	    * Estabished Timings. This is not entirely accurate,
+	    * because fixed frequency monitors are not supported
+	    * that way.
+	    */
+	   monitor->hmin = 65535; monitor->hmax = 0;
+	   monitor->vmin = 65535; monitor->vmax = 0;
+	   monitor->dclockmax = 0;
+	   emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
+	   for(i = 0; i < 13; i++) {
+	      if(emodes & sisfb_ddcsmodes[i].mask) {
+		 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
+		 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
+		 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
+		 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
+		 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
+	      }
+	   }
+	   index = 0x26;
+	   for(i = 0; i < 8; i++) {
+	      xres = (buffer[index] + 31) * 8;
+	      switch(buffer[index + 1] & 0xc0) {
+		 case 0xc0: yres = (xres * 9) / 16; break;
+		 case 0x80: yres = (xres * 4) /  5; break;
+		 case 0x40: yres = (xres * 3) /  4; break;
+		 default:   yres = xres;	    break;
+	      }
+	      refresh = (buffer[index + 1] & 0x3f) + 60;
+	      if((xres >= 640) && (yres >= 480)) {
+		 for(j = 0; j < 8; j++) {
+		    if((xres == sisfb_ddcfmodes[j].x) &&
+		       (yres == sisfb_ddcfmodes[j].y) &&
+		       (refresh == sisfb_ddcfmodes[j].v)) {
+		      if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
+		      if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
+		      if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
+		      if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
+		      if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
+		    }
+		 }
+	      }
+	      index += 2;
+	   }
+	   if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
+	      monitor->datavalid = true;
+	   }
+	}
+
+	return monitor->datavalid;
+}
+
+static void sisfb_handle_ddc(struct sis_video_info *ivideo,
+			     struct sisfb_monitor *monitor, int crtno)
+{
+	unsigned short temp, i, realcrtno = crtno;
+	unsigned char  buffer[256];
+
+	monitor->datavalid = false;
+
+	if(crtno) {
+	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
+	   else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
+	   else return;
+	}
+
+	if((ivideo->sisfb_crt1off) && (!crtno))
+		return;
+
+	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+				realcrtno, 0, &buffer[0], ivideo->vbflags2);
+	if((!temp) || (temp == 0xffff)) {
+	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
+	   return;
+	} else {
+	   printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
+	   printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
+		crtno + 1,
+		(temp & 0x1a) ? "" : "[none of the supported]",
+		(temp & 0x02) ? "2 " : "",
+		(temp & 0x08) ? "D&P" : "",
+		(temp & 0x10) ? "FPDI-2" : "");
+	   if(temp & 0x02) {
+	      i = 3;  /* Number of retrys */
+	      do {
+		 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+				     realcrtno, 1, &buffer[0], ivideo->vbflags2);
+	      } while((temp) && i--);
+	      if(!temp) {
+		 if(sisfb_interpret_edid(monitor, &buffer[0])) {
+		    printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
+			monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
+			monitor->dclockmax / 1000);
+		 } else {
+		    printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
+		 }
+	      } else {
+		 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
+	      }
+	   } else {
+	      printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
+	   }
+	}
+}
+
+/* -------------- Mode validation --------------- */
+
+static bool
+sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
+		int mode_idx, int rate_idx, int rate)
+{
+	int htotal, vtotal;
+	unsigned int dclock, hsync;
+
+	if(!monitor->datavalid)
+		return true;
+
+	if(mode_idx < 0)
+		return false;
+
+	/* Skip for 320x200, 320x240, 640x400 */
+	switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
+	case 0x59:
+	case 0x41:
+	case 0x4f:
+	case 0x50:
+	case 0x56:
+	case 0x53:
+	case 0x2f:
+	case 0x5d:
+	case 0x5e:
+		return true;
+#ifdef CONFIG_FB_SIS_315
+	case 0x5a:
+	case 0x5b:
+		if(ivideo->sisvga_engine == SIS_315_VGA) return true;
+#endif
+	}
+
+	if(rate < (monitor->vmin - 1))
+		return false;
+	if(rate > (monitor->vmax + 1))
+		return false;
+
+	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
+				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
+				  &htotal, &vtotal, rate_idx)) {
+		dclock = (htotal * vtotal * rate) / 1000;
+		if(dclock > (monitor->dclockmax + 1000))
+			return false;
+		hsync = dclock / htotal;
+		if(hsync < (monitor->hmin - 1))
+			return false;
+		if(hsync > (monitor->hmax + 1))
+			return false;
+        } else {
+		return false;
+	}
+	return true;
+}
+
+static int
+sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
+{
+	u16 xres=0, yres, myres;
+
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		if(!(sisbios_mode[myindex].chipset & MD_SIS300))
+			return -1 ;
+	}
+#endif
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+		if(!(sisbios_mode[myindex].chipset & MD_SIS315))
+			return -1;
+	}
+#endif
+
+	myres = sisbios_mode[myindex].yres;
+
+	switch(vbflags & VB_DISPTYPE_DISP2) {
+
+	case CRT2_LCD:
+		xres = ivideo->lcdxres; yres = ivideo->lcdyres;
+
+		if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
+		   (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
+			if(sisbios_mode[myindex].xres > xres)
+				return -1;
+			if(myres > yres)
+				return -1;
+		}
+
+		if(ivideo->sisfb_fstn) {
+			if(sisbios_mode[myindex].xres == 320) {
+				if(myres == 240) {
+					switch(sisbios_mode[myindex].mode_no[1]) {
+						case 0x50: myindex = MODE_FSTN_8;  break;
+						case 0x56: myindex = MODE_FSTN_16; break;
+						case 0x53: return -1;
+					}
+				}
+			}
+		}
+
+		if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+			 	sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
+			 	ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
+			return -1;
+		}
+		break;
+
+	case CRT2_TV:
+		if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+			return -1;
+		}
+		break;
+
+	case CRT2_VGA:
+		if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+			return -1;
+		}
+		break;
+	}
+
+	return myindex;
+}
+
+static u8
+sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
+{
+	int i = 0;
+	u16 xres = sisbios_mode[mode_idx].xres;
+	u16 yres = sisbios_mode[mode_idx].yres;
+
+	ivideo->rate_idx = 0;
+	while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
+		if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
+			if(sisfb_vrate[i].refresh == rate) {
+				ivideo->rate_idx = sisfb_vrate[i].idx;
+				break;
+			} else if(sisfb_vrate[i].refresh > rate) {
+				if((sisfb_vrate[i].refresh - rate) <= 3) {
+					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
+						rate, sisfb_vrate[i].refresh);
+					ivideo->rate_idx = sisfb_vrate[i].idx;
+					ivideo->refresh_rate = sisfb_vrate[i].refresh;
+				} else if((sisfb_vrate[i].idx != 1) &&
+						((rate - sisfb_vrate[i-1].refresh) <= 2)) {
+					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
+						rate, sisfb_vrate[i-1].refresh);
+					ivideo->rate_idx = sisfb_vrate[i-1].idx;
+					ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
+				}
+				break;
+			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
+				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
+						rate, sisfb_vrate[i].refresh);
+				ivideo->rate_idx = sisfb_vrate[i].idx;
+				break;
+			}
+		}
+		i++;
+	}
+	if(ivideo->rate_idx > 0) {
+		return ivideo->rate_idx;
+	} else {
+		printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
+				rate, xres, yres);
+		return 0;
+	}
+}
+
+static bool
+sisfb_bridgeisslave(struct sis_video_info *ivideo)
+{
+	unsigned char P1_00;
+
+	if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
+		return false;
+
+	P1_00 = SiS_GetReg(SISPART1, 0x00);
+	if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+	    ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static bool
+sisfballowretracecrt1(struct sis_video_info *ivideo)
+{
+	u8 temp;
+
+	temp = SiS_GetReg(SISCR, 0x17);
+	if(!(temp & 0x80))
+		return false;
+
+	temp = SiS_GetReg(SISSR, 0x1f);
+	if(temp & 0xc0)
+		return false;
+
+	return true;
+}
+
+static bool
+sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
+{
+	if(!sisfballowretracecrt1(ivideo))
+		return false;
+
+	if (SiS_GetRegByte(SISINPSTAT) & 0x08)
+		return true;
+	else
+		return false;
+}
+
+static void
+sisfbwaitretracecrt1(struct sis_video_info *ivideo)
+{
+	int watchdog;
+
+	if(!sisfballowretracecrt1(ivideo))
+		return;
+
+	watchdog = 65536;
+	while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
+	watchdog = 65536;
+	while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
+}
+
+static bool
+sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
+{
+	unsigned char temp, reg;
+
+	switch(ivideo->sisvga_engine) {
+	case SIS_300_VGA: reg = 0x25; break;
+	case SIS_315_VGA: reg = 0x30; break;
+	default:	  return false;
+	}
+
+	temp = SiS_GetReg(SISPART1, reg);
+	if(temp & 0x02)
+		return true;
+	else
+		return false;
+}
+
+static bool
+sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
+{
+	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+		if(!sisfb_bridgeisslave(ivideo)) {
+			return sisfbcheckvretracecrt2(ivideo);
+		}
+	}
+	return sisfbcheckvretracecrt1(ivideo);
+}
+
+static u32
+sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
+{
+	u8 idx, reg1, reg2, reg3, reg4;
+	u32 ret = 0;
+
+	(*vcount) = (*hcount) = 0;
+
+	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
+
+		ret |= (FB_VBLANK_HAVE_VSYNC  |
+			FB_VBLANK_HAVE_HBLANK |
+			FB_VBLANK_HAVE_VBLANK |
+			FB_VBLANK_HAVE_VCOUNT |
+			FB_VBLANK_HAVE_HCOUNT);
+		switch(ivideo->sisvga_engine) {
+			case SIS_300_VGA: idx = 0x25; break;
+			default:
+			case SIS_315_VGA: idx = 0x30; break;
+		}
+		reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
+		reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
+		reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
+		reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
+		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+		if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
+		if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
+		(*vcount) = reg3 | ((reg4 & 0x70) << 4);
+		(*hcount) = reg2 | ((reg4 & 0x0f) << 8);
+
+	} else if(sisfballowretracecrt1(ivideo)) {
+
+		ret |= (FB_VBLANK_HAVE_VSYNC  |
+			FB_VBLANK_HAVE_VBLANK |
+			FB_VBLANK_HAVE_VCOUNT |
+			FB_VBLANK_HAVE_HCOUNT);
+		reg1 = SiS_GetRegByte(SISINPSTAT);
+		if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
+		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+		reg1 = SiS_GetReg(SISCR, 0x20);
+		reg1 = SiS_GetReg(SISCR, 0x1b);
+		reg2 = SiS_GetReg(SISCR, 0x1c);
+		reg3 = SiS_GetReg(SISCR, 0x1d);
+		(*vcount) = reg2 | ((reg3 & 0x07) << 8);
+		(*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
+	}
+
+	return ret;
+}
+
+static int
+sisfb_myblank(struct sis_video_info *ivideo, int blank)
+{
+	u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
+	bool backlight = true;
+
+	switch(blank) {
+		case FB_BLANK_UNBLANK:	/* on */
+			sr01  = 0x00;
+			sr11  = 0x00;
+			sr1f  = 0x00;
+			cr63  = 0x00;
+			p2_0  = 0x20;
+			p1_13 = 0x00;
+			backlight = true;
+			break;
+		case FB_BLANK_NORMAL:	/* blank */
+			sr01  = 0x20;
+			sr11  = 0x00;
+			sr1f  = 0x00;
+			cr63  = 0x00;
+			p2_0  = 0x20;
+			p1_13 = 0x00;
+			backlight = true;
+			break;
+		case FB_BLANK_VSYNC_SUSPEND:	/* no vsync */
+			sr01  = 0x20;
+			sr11  = 0x08;
+			sr1f  = 0x80;
+			cr63  = 0x40;
+			p2_0  = 0x40;
+			p1_13 = 0x80;
+			backlight = false;
+			break;
+		case FB_BLANK_HSYNC_SUSPEND:	/* no hsync */
+			sr01  = 0x20;
+			sr11  = 0x08;
+			sr1f  = 0x40;
+			cr63  = 0x40;
+			p2_0  = 0x80;
+			p1_13 = 0x40;
+			backlight = false;
+			break;
+		case FB_BLANK_POWERDOWN:	/* off */
+			sr01  = 0x20;
+			sr11  = 0x08;
+			sr1f  = 0xc0;
+			cr63  = 0x40;
+			p2_0  = 0xc0;
+			p1_13 = 0xc0;
+			backlight = false;
+			break;
+		default:
+			return 1;
+	}
+
+	if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
+
+		if( (!ivideo->sisfb_thismonitor.datavalid) ||
+		    ((ivideo->sisfb_thismonitor.datavalid) &&
+		     (ivideo->sisfb_thismonitor.feature & 0xe0))) {
+
+			if(ivideo->sisvga_engine == SIS_315_VGA) {
+				SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+			}
+
+			if(!(sisfb_bridgeisslave(ivideo))) {
+				SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
+				SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
+			}
+		}
+
+	}
+
+	if(ivideo->currentvbflags & CRT2_LCD) {
+
+		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+			if(backlight) {
+				SiS_SiS30xBLOn(&ivideo->SiS_Pr);
+			} else {
+				SiS_SiS30xBLOff(&ivideo->SiS_Pr);
+			}
+		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
+#ifdef CONFIG_FB_SIS_315
+			if(ivideo->vbflags2 & VB2_CHRONTEL) {
+				if(backlight) {
+					SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
+				} else {
+					SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
+				}
+			}
+#endif
+		}
+
+		if(((ivideo->sisvga_engine == SIS_300_VGA) &&
+		    (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
+		   ((ivideo->sisvga_engine == SIS_315_VGA) &&
+		    ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
+			SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
+		}
+
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+			if((ivideo->vbflags2 & VB2_30xB) &&
+			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
+				SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
+			}
+		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
+			if((ivideo->vbflags2 & VB2_30xB) &&
+			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
+				SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
+			}
+		}
+
+	} else if(ivideo->currentvbflags & CRT2_VGA) {
+
+		if(ivideo->vbflags2 & VB2_30xB) {
+			SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
+		}
+
+	}
+
+	return 0;
+}
+
+/* ------------- Callbacks from init.c/init301.c  -------------- */
+
+#ifdef CONFIG_FB_SIS_300
+unsigned int
+sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+   u32 val = 0;
+
+   pci_read_config_dword(ivideo->nbridge, reg, &val);
+   return (unsigned int)val;
+}
+
+void
+sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+   pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
+}
+
+unsigned int
+sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+   u32 val = 0;
+
+   if(!ivideo->lpcdev) return 0;
+
+   pci_read_config_dword(ivideo->lpcdev, reg, &val);
+   return (unsigned int)val;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+void
+sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+   pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
+}
+
+unsigned int
+sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+   u16 val = 0;
+
+   if(!ivideo->lpcdev) return 0;
+
+   pci_read_config_word(ivideo->lpcdev, reg, &val);
+   return (unsigned int)val;
+}
+#endif
+
+/* ----------- FBDev related routines for all series ----------- */
+
+static int
+sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
+{
+	return (var->bits_per_pixel == 8) ? 256 : 16;
+}
+
+static void
+sisfb_set_vparms(struct sis_video_info *ivideo)
+{
+	switch(ivideo->video_bpp) {
+	case 8:
+		ivideo->DstColor = 0x0000;
+		ivideo->SiS310_AccelDepth = 0x00000000;
+		ivideo->video_cmap_len = 256;
+		break;
+	case 16:
+		ivideo->DstColor = 0x8000;
+		ivideo->SiS310_AccelDepth = 0x00010000;
+		ivideo->video_cmap_len = 16;
+		break;
+	case 32:
+		ivideo->DstColor = 0xC000;
+		ivideo->SiS310_AccelDepth = 0x00020000;
+		ivideo->video_cmap_len = 16;
+		break;
+	default:
+		ivideo->video_cmap_len = 16;
+		printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
+		ivideo->accel = 0;
+	}
+}
+
+static int
+sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
+
+	if(maxyres > 32767) maxyres = 32767;
+
+	return maxyres;
+}
+
+static void
+sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
+	ivideo->scrnpitchCRT1 = ivideo->video_linelength;
+	if(!(ivideo->currentvbflags & CRT1_LCDA)) {
+		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+			ivideo->scrnpitchCRT1 <<= 1;
+		}
+	}
+}
+
+static void
+sisfb_set_pitch(struct sis_video_info *ivideo)
+{
+	bool isslavemode = false;
+	unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
+	unsigned short HDisplay2 = ivideo->video_linelength >> 3;
+
+	if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
+
+	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
+	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
+		SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
+		SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
+	}
+
+	/* We must not set the pitch for CRT2 if bridge is in slave mode */
+	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
+		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
+		SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
+		SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
+	}
+}
+
+static void
+sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	ivideo->video_cmap_len = sisfb_get_cmap_len(var);
+
+	switch(var->bits_per_pixel) {
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+}
+
+static int
+sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
+{
+	unsigned short modeno = ivideo->mode_no;
+
+	/* >=2.6.12's fbcon clears the screen anyway */
+	modeno |= 0x80;
+
+	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+	sisfb_pre_setmode(ivideo);
+
+	if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
+		printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
+		return -EINVAL;
+	}
+
+	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+	sisfb_post_setmode(ivideo);
+
+	return 0;
+}
+
+
+static int
+sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	unsigned int htotal = 0, vtotal = 0;
+	unsigned int drate = 0, hrate = 0;
+	int found_mode = 0, ret;
+	int old_mode;
+	u32 pixclock;
+
+	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
+
+	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
+
+	pixclock = var->pixclock;
+
+	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+		vtotal += var->yres;
+		vtotal <<= 1;
+	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		vtotal += var->yres;
+		vtotal <<= 2;
+	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		vtotal += var->yres;
+		vtotal <<= 1;
+	} else 	vtotal += var->yres;
+
+	if(!(htotal) || !(vtotal)) {
+		DPRINTK("sisfb: Invalid 'var' information\n");
+		return -EINVAL;
+	}
+
+	if(pixclock && htotal && vtotal) {
+		drate = 1000000000 / pixclock;
+		hrate = (drate * 1000) / htotal;
+		ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+	} else {
+		ivideo->refresh_rate = 60;
+	}
+
+	old_mode = ivideo->sisfb_mode_idx;
+	ivideo->sisfb_mode_idx = 0;
+
+	while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
+	       (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
+		if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
+			ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
+			found_mode = 1;
+			break;
+		}
+		ivideo->sisfb_mode_idx++;
+	}
+
+	if(found_mode) {
+		ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
+				ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+	} else {
+		ivideo->sisfb_mode_idx = -1;
+	}
+
+       	if(ivideo->sisfb_mode_idx < 0) {
+		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
+		       var->yres, var->bits_per_pixel);
+		ivideo->sisfb_mode_idx = old_mode;
+		return -EINVAL;
+	}
+
+	ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
+
+	if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
+		ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
+		ivideo->refresh_rate = 60;
+	}
+
+	if(isactive) {
+		/* If acceleration to be used? Need to know
+		 * before pre/post_set_mode()
+		 */
+		ivideo->accel = 0;
+#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
+#ifdef STUPID_ACCELF_TEXT_SHIT
+		if(var->accel_flags & FB_ACCELF_TEXT) {
+			info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		} else {
+			info->flags |= FBINFO_HWACCEL_DISABLED;
+		}
+#endif
+		if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
+#else
+		if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
+#endif
+
+		if((ret = sisfb_set_mode(ivideo, 1))) {
+			return ret;
+		}
+
+		ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+
+		sisfb_calc_pitch(ivideo, var);
+		sisfb_set_pitch(ivideo);
+
+		sisfb_set_vparms(ivideo);
+
+		ivideo->current_width = ivideo->video_width;
+		ivideo->current_height = ivideo->video_height;
+		ivideo->current_bpp = ivideo->video_bpp;
+		ivideo->current_htotal = htotal;
+		ivideo->current_vtotal = vtotal;
+		ivideo->current_linelength = ivideo->video_linelength;
+		ivideo->current_pixclock = var->pixclock;
+		ivideo->current_refresh_rate = ivideo->refresh_rate;
+		ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
+	}
+
+	return 0;
+}
+
+static void
+sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
+{
+	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+	SiS_SetReg(SISCR, 0x0D, base & 0xFF);
+	SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
+	SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+		SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
+	}
+}
+
+static void
+sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
+{
+	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
+		SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
+		SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
+		SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
+			SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
+		}
+	}
+}
+
+static int
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
+	      struct fb_var_screeninfo *var)
+{
+	ivideo->current_base = var->yoffset * info->var.xres_virtual
+			     + var->xoffset;
+
+	/* calculate base bpp dep. */
+	switch (info->var.bits_per_pixel) {
+	case 32:
+		break;
+	case 16:
+		ivideo->current_base >>= 1;
+		break;
+	case 8:
+	default:
+		ivideo->current_base >>= 2;
+		break;
+	}
+
+	ivideo->current_base += (ivideo->video_offset >> 2);
+
+	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
+
+	return 0;
+}
+
+static int
+sisfb_open(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+static int
+sisfb_release(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+static int
+sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+		unsigned transp, struct fb_info *info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+	if(regno >= sisfb_get_cmap_len(&info->var))
+		return 1;
+
+	switch(info->var.bits_per_pixel) {
+	case 8:
+		SiS_SetRegByte(SISDACA, regno);
+		SiS_SetRegByte(SISDACD, (red >> 10));
+		SiS_SetRegByte(SISDACD, (green >> 10));
+		SiS_SetRegByte(SISDACD, (blue >> 10));
+		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+			SiS_SetRegByte(SISDAC2A, regno);
+			SiS_SetRegByte(SISDAC2D, (red >> 8));
+			SiS_SetRegByte(SISDAC2D, (green >> 8));
+			SiS_SetRegByte(SISDAC2D, (blue >> 8));
+		}
+		break;
+	case 16:
+		if (regno >= 16)
+			break;
+
+		((u32 *)(info->pseudo_palette))[regno] =
+				(red & 0xf800)          |
+				((green & 0xfc00) >> 5) |
+				((blue & 0xf800) >> 11);
+		break;
+	case 32:
+		if (regno >= 16)
+			break;
+
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+		((u32 *)(info->pseudo_palette))[regno] =
+				(red << 16) | (green << 8) | (blue);
+		break;
+	}
+	return 0;
+}
+
+static int
+sisfb_set_par(struct fb_info *info)
+{
+	int err;
+
+	if((err = sisfb_do_set_var(&info->var, 1, info)))
+		return err;
+
+	sisfb_get_fix(&info->fix, -1, info);
+
+	return 0;
+}
+
+static int
+sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
+	unsigned int drate = 0, hrate = 0, maxyres;
+	int found_mode = 0;
+	int refresh_rate, search_idx, tidx;
+	bool recalc_clock = false;
+	u32 pixclock;
+
+	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
+
+	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
+
+	pixclock = var->pixclock;
+
+	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+		vtotal += var->yres;
+		vtotal <<= 1;
+	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		vtotal += var->yres;
+		vtotal <<= 2;
+	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		vtotal += var->yres;
+		vtotal <<= 1;
+	} else
+		vtotal += var->yres;
+
+	if(!(htotal) || !(vtotal)) {
+		SISFAIL("sisfb: no valid timing data");
+	}
+
+	search_idx = 0;
+	while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
+	       (sisbios_mode[search_idx].xres <= var->xres) ) {
+		if( (sisbios_mode[search_idx].xres == var->xres) &&
+		    (sisbios_mode[search_idx].yres == var->yres) &&
+		    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
+			if((tidx = sisfb_validate_mode(ivideo, search_idx,
+						ivideo->currentvbflags)) > 0) {
+				found_mode = 1;
+				search_idx = tidx;
+				break;
+			}
+		}
+		search_idx++;
+	}
+
+	if(!found_mode) {
+		search_idx = 0;
+		while(sisbios_mode[search_idx].mode_no[0] != 0) {
+		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
+		       (var->yres <= sisbios_mode[search_idx].yres) &&
+		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
+			if((tidx = sisfb_validate_mode(ivideo,search_idx,
+						ivideo->currentvbflags)) > 0) {
+				found_mode = 1;
+				search_idx = tidx;
+				break;
+			}
+		   }
+		   search_idx++;
+		}
+		if(found_mode) {
+			printk(KERN_DEBUG
+				"sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
+				var->xres, var->yres, var->bits_per_pixel,
+				sisbios_mode[search_idx].xres,
+				sisbios_mode[search_idx].yres,
+				var->bits_per_pixel);
+			var->xres = sisbios_mode[search_idx].xres;
+			var->yres = sisbios_mode[search_idx].yres;
+		} else {
+			printk(KERN_ERR
+				"sisfb: Failed to find supported mode near %dx%dx%d\n",
+				var->xres, var->yres, var->bits_per_pixel);
+			return -EINVAL;
+		}
+	}
+
+	if( ((ivideo->vbflags2 & VB2_LVDS) ||
+	     ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
+	    (var->bits_per_pixel == 8) ) {
+		/* Slave modes on LVDS and 301B-DH */
+		refresh_rate = 60;
+		recalc_clock = true;
+	} else if( (ivideo->current_htotal == htotal) &&
+		   (ivideo->current_vtotal == vtotal) &&
+		   (ivideo->current_pixclock == pixclock) ) {
+		/* x=x & y=y & c=c -> assume depth change */
+		drate = 1000000000 / pixclock;
+		hrate = (drate * 1000) / htotal;
+		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+	} else if( ( (ivideo->current_htotal != htotal) ||
+		     (ivideo->current_vtotal != vtotal) ) &&
+		   (ivideo->current_pixclock == var->pixclock) ) {
+		/* x!=x | y!=y & c=c -> invalid pixclock */
+		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
+			refresh_rate =
+				ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
+		} else if(ivideo->sisfb_parm_rate != -1) {
+			/* Sic, sisfb_parm_rate - want to know originally desired rate here */
+			refresh_rate = ivideo->sisfb_parm_rate;
+		} else {
+			refresh_rate = 60;
+		}
+		recalc_clock = true;
+	} else if((pixclock) && (htotal) && (vtotal)) {
+		drate = 1000000000 / pixclock;
+		hrate = (drate * 1000) / htotal;
+		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+	} else if(ivideo->current_refresh_rate) {
+		refresh_rate = ivideo->current_refresh_rate;
+		recalc_clock = true;
+	} else {
+		refresh_rate = 60;
+		recalc_clock = true;
+	}
+
+	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
+
+	/* Eventually recalculate timing and clock */
+	if(recalc_clock) {
+		if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
+		var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
+						sisbios_mode[search_idx].mode_no[ivideo->mni],
+						myrateindex));
+		sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
+					sisbios_mode[search_idx].mode_no[ivideo->mni],
+					myrateindex, var);
+		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+			var->pixclock <<= 1;
+		}
+	}
+
+	if(ivideo->sisfb_thismonitor.datavalid) {
+		if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
+				myrateindex, refresh_rate)) {
+			printk(KERN_INFO
+				"sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+		}
+	}
+
+	/* Adapt RGB settings */
+	sisfb_bpp_to_var(ivideo, var);
+
+	/* Sanity check for offsets */
+	if(var->xoffset < 0) var->xoffset = 0;
+	if(var->yoffset < 0) var->yoffset = 0;
+
+	if(var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if(ivideo->sisfb_ypan) {
+		maxyres = sisfb_calc_maxyres(ivideo, var);
+		if(ivideo->sisfb_max) {
+			var->yres_virtual = maxyres;
+		} else {
+			if(var->yres_virtual > maxyres) {
+				var->yres_virtual = maxyres;
+			}
+		}
+		if(var->yres_virtual <= var->yres) {
+			var->yres_virtual = var->yres;
+		}
+	} else {
+		if(var->yres != var->yres_virtual) {
+			var->yres_virtual = var->yres;
+		}
+		var->xoffset = 0;
+		var->yoffset = 0;
+	}
+
+	/* Truncate offsets to maximum if too high */
+	if(var->xoffset > var->xres_virtual - var->xres) {
+		var->xoffset = var->xres_virtual - var->xres - 1;
+	}
+
+	if(var->yoffset > var->yres_virtual - var->yres) {
+		var->yoffset = var->yres_virtual - var->yres - 1;
+	}
+
+	/* Set everything else to 0 */
+	var->red.msb_right =
+		var->green.msb_right =
+		var->blue.msb_right =
+		var->transp.offset =
+		var->transp.length =
+		var->transp.msb_right = 0;
+
+	return 0;
+}
+
+static int
+sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	int err;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		return -EINVAL;
+
+	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+	    var->yoffset + info->var.yres > info->var.yres_virtual)
+		return -EINVAL;
+
+	err = sisfb_pan_var(ivideo, info, var);
+	if (err < 0)
+		return err;
+
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+
+	return 0;
+}
+
+static int
+sisfb_blank(int blank, struct fb_info *info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+	return sisfb_myblank(ivideo, blank);
+}
+
+/* ----------- FBDev related routines for all series ---------- */
+
+static int	sisfb_ioctl(struct fb_info *info, unsigned int cmd,
+			    unsigned long arg)
+{
+	struct sis_video_info	*ivideo = (struct sis_video_info *)info->par;
+	struct sis_memreq	sismemreq;
+	struct fb_vblank	sisvbblank;
+	u32			gpu32 = 0;
+#ifndef __user
+#define __user
+#endif
+	u32 __user 		*argp = (u32 __user *)arg;
+
+	switch(cmd) {
+	   case FBIO_ALLOC:
+		if(!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+
+		if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
+			return -EFAULT;
+
+		sis_malloc(&sismemreq);
+
+		if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
+			sis_free((u32)sismemreq.offset);
+			return -EFAULT;
+		}
+		break;
+
+	   case FBIO_FREE:
+		if(!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+
+		if(get_user(gpu32, argp))
+			return -EFAULT;
+
+		sis_free(gpu32);
+		break;
+
+	   case FBIOGET_VBLANK:
+
+		memset(&sisvbblank, 0, sizeof(struct fb_vblank));
+
+		sisvbblank.count = 0;
+		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
+
+		if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
+			return -EFAULT;
+
+		break;
+
+	   case SISFB_GET_INFO_SIZE:
+		return put_user(sizeof(struct sisfb_info), argp);
+
+	   case SISFB_GET_INFO_OLD:
+		if(ivideo->warncount++ < 10)
+			printk(KERN_INFO
+				"sisfb: Deprecated ioctl call received - update your application!\n");
+	   case SISFB_GET_INFO:  /* For communication with X driver */
+		ivideo->sisfb_infoblock.sisfb_id         = SISFB_ID;
+		ivideo->sisfb_infoblock.sisfb_version    = VER_MAJOR;
+		ivideo->sisfb_infoblock.sisfb_revision   = VER_MINOR;
+		ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
+		ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
+		ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
+		ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
+		ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
+		if(ivideo->modechanged) {
+			ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
+		} else {
+			ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
+		}
+		ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
+		ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
+		ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
+		ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
+		ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
+		ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
+		ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
+		ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
+		ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
+		ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
+		ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
+		ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
+		ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
+		ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
+		ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
+		ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
+		ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
+		ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
+		ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
+		ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
+		ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
+		ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
+		ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
+		ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
+		ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
+		ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
+		ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
+		ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
+
+		if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
+						sizeof(ivideo->sisfb_infoblock)))
+			return -EFAULT;
+
+	        break;
+
+	   case SISFB_GET_VBRSTATUS_OLD:
+		if(ivideo->warncount++ < 10)
+			printk(KERN_INFO
+				"sisfb: Deprecated ioctl call received - update your application!\n");
+	   case SISFB_GET_VBRSTATUS:
+		if(sisfb_CheckVBRetrace(ivideo))
+			return put_user((u32)1, argp);
+		else
+			return put_user((u32)0, argp);
+
+	   case SISFB_GET_AUTOMAXIMIZE_OLD:
+		if(ivideo->warncount++ < 10)
+			printk(KERN_INFO
+				"sisfb: Deprecated ioctl call received - update your application!\n");
+	   case SISFB_GET_AUTOMAXIMIZE:
+		if(ivideo->sisfb_max)
+			return put_user((u32)1, argp);
+		else
+			return put_user((u32)0, argp);
+
+	   case SISFB_SET_AUTOMAXIMIZE_OLD:
+		if(ivideo->warncount++ < 10)
+			printk(KERN_INFO
+				"sisfb: Deprecated ioctl call received - update your application!\n");
+	   case SISFB_SET_AUTOMAXIMIZE:
+		if(get_user(gpu32, argp))
+			return -EFAULT;
+
+		ivideo->sisfb_max = (gpu32) ? 1 : 0;
+		break;
+
+	   case SISFB_SET_TVPOSOFFSET:
+		if(get_user(gpu32, argp))
+			return -EFAULT;
+
+		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
+		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
+		break;
+
+	   case SISFB_GET_TVPOSOFFSET:
+		return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
+							argp);
+
+	   case SISFB_COMMAND:
+		if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
+							sizeof(struct sisfb_cmd)))
+			return -EFAULT;
+
+		sisfb_handle_command(ivideo, &ivideo->sisfb_command);
+
+		if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
+							sizeof(struct sisfb_cmd)))
+			return -EFAULT;
+
+		break;
+
+	   case SISFB_SET_LOCK:
+		if(get_user(gpu32, argp))
+			return -EFAULT;
+
+		ivideo->sisfblocked = (gpu32) ? 1 : 0;
+		break;
+
+	   default:
+#ifdef SIS_NEW_CONFIG_COMPAT
+		return -ENOIOCTLCMD;
+#else
+		return -EINVAL;
+#endif
+	}
+	return 0;
+}
+
+static int
+sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+	strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
+
+	mutex_lock(&info->mm_lock);
+	fix->smem_start  = ivideo->video_base + ivideo->video_offset;
+	fix->smem_len    = ivideo->sisfb_mem;
+	mutex_unlock(&info->mm_lock);
+	fix->type        = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux    = 0;
+	fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	fix->xpanstep    = 1;
+	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;
+	fix->ywrapstep   = 0;
+	fix->line_length = ivideo->video_linelength;
+	fix->mmio_start  = ivideo->mmio_base;
+	fix->mmio_len    = ivideo->mmio_size;
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		fix->accel = FB_ACCEL_SIS_GLAMOUR;
+	} else if((ivideo->chip == SIS_330) ||
+		  (ivideo->chip == SIS_760) ||
+		  (ivideo->chip == SIS_761)) {
+		fix->accel = FB_ACCEL_SIS_XABRE;
+	} else if(ivideo->chip == XGI_20) {
+		fix->accel = FB_ACCEL_XGI_VOLARI_Z;
+	} else if(ivideo->chip >= XGI_40) {
+		fix->accel = FB_ACCEL_XGI_VOLARI_V;
+	} else {
+		fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
+	}
+
+	return 0;
+}
+
+/* ----------------  fb_ops structures ----------------- */
+
+static struct fb_ops sisfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= sisfb_open,
+	.fb_release	= sisfb_release,
+	.fb_check_var	= sisfb_check_var,
+	.fb_set_par	= sisfb_set_par,
+	.fb_setcolreg	= sisfb_setcolreg,
+	.fb_pan_display	= sisfb_pan_display,
+	.fb_blank	= sisfb_blank,
+	.fb_fillrect	= fbcon_sis_fillrect,
+	.fb_copyarea	= fbcon_sis_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_sync	= fbcon_sis_sync,
+#ifdef SIS_NEW_CONFIG_COMPAT
+	.fb_compat_ioctl= sisfb_ioctl,
+#endif
+	.fb_ioctl	= sisfb_ioctl
+};
+
+/* ---------------- Chip generation dependent routines ---------------- */
+
+static struct pci_dev *sisfb_get_northbridge(int basechipid)
+{
+	struct pci_dev *pdev = NULL;
+	int nbridgenum, nbridgeidx, i;
+	static const unsigned short nbridgeids[] = {
+		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */
+		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */
+		PCI_DEVICE_ID_SI_730,
+		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
+		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
+		PCI_DEVICE_ID_SI_651,
+		PCI_DEVICE_ID_SI_740,
+		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760/761 VGA */
+		PCI_DEVICE_ID_SI_741,
+		PCI_DEVICE_ID_SI_660,
+		PCI_DEVICE_ID_SI_760,
+		PCI_DEVICE_ID_SI_761
+	};
+
+	switch(basechipid) {
+#ifdef CONFIG_FB_SIS_300
+	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;
+	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;
+#endif
+#ifdef CONFIG_FB_SIS_315
+	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
+	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;
+	case SIS_660:	nbridgeidx = 7; nbridgenum = 5; break;
+#endif
+	default:	return NULL;
+	}
+	for(i = 0; i < nbridgenum; i++) {
+		if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
+				nbridgeids[nbridgeidx+i], NULL)))
+			break;
+	}
+	return pdev;
+}
+
+static int sisfb_get_dram_size(struct sis_video_info *ivideo)
+{
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+	u8 reg;
+#endif
+
+	ivideo->video_size = 0;
+	ivideo->UMAsize = ivideo->LFBsize = 0;
+
+	switch(ivideo->chip) {
+#ifdef CONFIG_FB_SIS_300
+	case SIS_300:
+		reg = SiS_GetReg(SISSR, 0x14);
+		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
+		break;
+	case SIS_540:
+	case SIS_630:
+	case SIS_730:
+		if(!ivideo->nbridge)
+			return -1;
+		pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
+		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
+		break;
+#endif
+#ifdef CONFIG_FB_SIS_315
+	case SIS_315H:
+	case SIS_315PRO:
+	case SIS_315:
+		reg = SiS_GetReg(SISSR, 0x14);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		switch((reg >> 2) & 0x03) {
+		case 0x01:
+		case 0x03:
+			ivideo->video_size <<= 1;
+			break;
+		case 0x02:
+			ivideo->video_size += (ivideo->video_size/2);
+		}
+		break;
+	case SIS_330:
+		reg = SiS_GetReg(SISSR, 0x14);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		if(reg & 0x0c) ivideo->video_size <<= 1;
+		break;
+	case SIS_550:
+	case SIS_650:
+	case SIS_740:
+		reg = SiS_GetReg(SISSR, 0x14);
+		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
+		break;
+	case SIS_661:
+	case SIS_741:
+		reg = SiS_GetReg(SISCR, 0x79);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		break;
+	case SIS_660:
+	case SIS_760:
+	case SIS_761:
+		reg = SiS_GetReg(SISCR, 0x79);
+		reg = (reg & 0xf0) >> 4;
+		if(reg)	{
+			ivideo->video_size = (1 << reg) << 20;
+			ivideo->UMAsize = ivideo->video_size;
+		}
+		reg = SiS_GetReg(SISCR, 0x78);
+		reg &= 0x30;
+		if(reg) {
+			if(reg == 0x10) {
+				ivideo->LFBsize = (32 << 20);
+			} else {
+				ivideo->LFBsize = (64 << 20);
+			}
+			ivideo->video_size += ivideo->LFBsize;
+		}
+		break;
+	case SIS_340:
+	case XGI_20:
+	case XGI_40:
+		reg = SiS_GetReg(SISSR, 0x14);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		if(ivideo->chip != XGI_20) {
+			reg = (reg & 0x0c) >> 2;
+			if(ivideo->revision_id == 2) {
+				if(reg & 0x01) reg = 0x02;
+				else	       reg = 0x00;
+			}
+			if(reg == 0x02)		ivideo->video_size <<= 1;
+			else if(reg == 0x03)	ivideo->video_size <<= 2;
+		}
+		break;
+#endif
+	default:
+		return -1;
+	}
+	return 0;
+}
+
+/* -------------- video bridge device detection --------------- */
+
+static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
+{
+	u8 cr32, temp;
+
+	/* No CRT2 on XGI Z7 */
+	if(ivideo->chip == XGI_20) {
+		ivideo->sisfb_crt1off = 0;
+		return;
+	}
+
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		temp = SiS_GetReg(SISSR, 0x17);
+		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
+			/* PAL/NTSC is stored on SR16 on such machines */
+			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
+				temp = SiS_GetReg(SISSR, 0x16);
+				if(temp & 0x20)
+					ivideo->vbflags |= TV_PAL;
+				else
+					ivideo->vbflags |= TV_NTSC;
+			}
+		}
+	}
+#endif
+
+	cr32 = SiS_GetReg(SISCR, 0x32);
+
+	if(cr32 & SIS_CRT1) {
+		ivideo->sisfb_crt1off = 0;
+	} else {
+		ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
+	}
+
+	ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
+
+	if(cr32 & SIS_VB_TV)   ivideo->vbflags |= CRT2_TV;
+	if(cr32 & SIS_VB_LCD)  ivideo->vbflags |= CRT2_LCD;
+	if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
+
+	/* Check given parms for hardware compatibility.
+	 * (Cannot do this in the search_xx routines since we don't
+	 * know what hardware we are running on then)
+	 */
+
+	if(ivideo->chip != SIS_550) {
+	   ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
+	}
+
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
+	       (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
+	      if(ivideo->sisfb_tvplug & TV_YPBPR) {
+		 ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: YPbPr not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
+	       (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
+	      if(ivideo->sisfb_tvplug & TV_HIVISION) {
+		 ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: HiVision not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvstd != -1) {
+	   if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
+	       (!((ivideo->sisvga_engine == SIS_315_VGA) &&
+			(ivideo->vbflags2 & VB2_CHRONTEL))) ) {
+	      if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
+		 ivideo->sisfb_tvstd = -1;
+		 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
+	      }
+	   }
+	}
+
+	/* Detect/set TV plug & type */
+	if(ivideo->sisfb_tvplug != -1) {
+		ivideo->vbflags |= ivideo->sisfb_tvplug;
+	} else {
+		if(cr32 & SIS_VB_YPBPR)     	 ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
+		else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
+		else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
+		else {
+			if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
+			if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
+		}
+	}
+
+	if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
+	    if(ivideo->sisfb_tvstd != -1) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
+	       ivideo->vbflags |= ivideo->sisfb_tvstd;
+	    }
+	    if(ivideo->vbflags & TV_SCART) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
+	       ivideo->vbflags |= TV_PAL;
+	    }
+	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+			temp = SiS_GetReg(SISSR, 0x38);
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
+		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
+			temp = SiS_GetReg(SISSR, 0x38);
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
+		} else {
+			temp = SiS_GetReg(SISCR, 0x79);
+			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
+		}
+	    }
+	}
+
+	/* Copy forceCRT1 option to CRT1off if option is given */
+	if(ivideo->sisfb_forcecrt1 != -1) {
+	   ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
+	}
+}
+
+/* ------------------ Sensing routines ------------------ */
+
+static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
+{
+    unsigned short old;
+    int count = 48;
+
+    old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
+    do {
+	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
+    } while(count--);
+    return (count != -1);
+}
+
+static void sisfb_sense_crt1(struct sis_video_info *ivideo)
+{
+    bool mustwait = false;
+    u8  sr1F, cr17;
+#ifdef CONFIG_FB_SIS_315
+    u8  cr63=0;
+#endif
+    u16 temp = 0xffff;
+    int i;
+
+    sr1F = SiS_GetReg(SISSR, 0x1F);
+    SiS_SetRegOR(SISSR, 0x1F, 0x04);
+    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
+    if(sr1F & 0xc0) mustwait = true;
+
+#ifdef CONFIG_FB_SIS_315
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
+       cr63 &= 0x40;
+       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
+    }
+#endif
+
+    cr17 = SiS_GetReg(SISCR, 0x17);
+    cr17 &= 0x80;
+    if(!cr17) {
+       SiS_SetRegOR(SISCR, 0x17, 0x80);
+       mustwait = true;
+       SiS_SetReg(SISSR, 0x00, 0x01);
+       SiS_SetReg(SISSR, 0x00, 0x03);
+    }
+
+    if(mustwait) {
+       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
+    }
+
+#ifdef CONFIG_FB_SIS_315
+    if(ivideo->chip >= SIS_330) {
+       SiS_SetRegAND(SISCR, 0x32, ~0x20);
+       if(ivideo->chip >= SIS_340) {
+	   SiS_SetReg(SISCR, 0x57, 0x4a);
+       } else {
+	   SiS_SetReg(SISCR, 0x57, 0x5f);
+       }
+	SiS_SetRegOR(SISCR, 0x53, 0x02);
+	while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
+	while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
+	if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
+	SiS_SetRegAND(SISCR, 0x53, 0xfd);
+	SiS_SetRegAND(SISCR, 0x57, 0x00);
+    }
+#endif
+
+    if(temp == 0xffff) {
+       i = 3;
+       do {
+	  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+		ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
+       } while(((temp == 0) || (temp == 0xffff)) && i--);
+
+       if((temp == 0) || (temp == 0xffff)) {
+          if(sisfb_test_DDC1(ivideo)) temp = 1;
+       }
+    }
+
+    if((temp) && (temp != 0xffff)) {
+       SiS_SetRegOR(SISCR, 0x32, 0x20);
+    }
+
+#ifdef CONFIG_FB_SIS_315
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+	SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
+    }
+#endif
+
+    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
+
+    SiS_SetReg(SISSR, 0x1F, sr1F);
+}
+
+/* Determine and detect attached devices on SiS30x */
+static void SiS_SenseLCD(struct sis_video_info *ivideo)
+{
+	unsigned char buffer[256];
+	unsigned short temp, realcrtno, i;
+	u8 reg, cr37 = 0, paneltype = 0;
+	u16 xres, yres;
+
+	ivideo->SiS_Pr.PanelSelfDetected = false;
+
+	/* LCD detection only for TMDS bridges */
+	if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
+		return;
+	if(ivideo->vbflags2 & VB2_30xBDH)
+		return;
+
+	/* If LCD already set up by BIOS, skip it */
+	reg = SiS_GetReg(SISCR, 0x32);
+	if(reg & 0x08)
+		return;
+
+	realcrtno = 1;
+	if(ivideo->SiS_Pr.DDCPortMixup)
+		realcrtno = 0;
+
+	/* Check DDC capabilities */
+	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+				realcrtno, 0, &buffer[0], ivideo->vbflags2);
+
+	if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
+		return;
+
+	/* Read DDC data */
+	i = 3;  /* Number of retrys */
+	do {
+		temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+				ivideo->sisvga_engine, realcrtno, 1,
+				&buffer[0], ivideo->vbflags2);
+	} while((temp) && i--);
+
+	if(temp)
+		return;
+
+	/* No digital device */
+	if(!(buffer[0x14] & 0x80))
+		return;
+
+	/* First detailed timing preferred timing? */
+	if(!(buffer[0x18] & 0x02))
+		return;
+
+	xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
+	yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
+
+	switch(xres) {
+		case 1024:
+			if(yres == 768)
+				paneltype = 0x02;
+			break;
+		case 1280:
+			if(yres == 1024)
+				paneltype = 0x03;
+			break;
+		case 1600:
+			if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
+				paneltype = 0x0b;
+			break;
+	}
+
+	if(!paneltype)
+		return;
+
+	if(buffer[0x23])
+		cr37 |= 0x10;
+
+	if((buffer[0x47] & 0x18) == 0x18)
+		cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
+	else
+		cr37 |= 0xc0;
+
+	SiS_SetReg(SISCR, 0x36, paneltype);
+	cr37 &= 0xf1;
+	SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
+	SiS_SetRegOR(SISCR, 0x32, 0x08);
+
+	ivideo->SiS_Pr.PanelSelfDetected = true;
+}
+
+static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
+{
+    int temp, mytest, result, i, j;
+
+    for(j = 0; j < 10; j++) {
+       result = 0;
+       for(i = 0; i < 3; i++) {
+          mytest = test;
+	   SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
+          temp = (type >> 8) | (mytest & 0x00ff);
+	  SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
+          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
+          mytest >>= 8;
+          mytest &= 0x7f;
+	   temp = SiS_GetReg(SISPART4, 0x03);
+          temp ^= 0x0e;
+          temp &= mytest;
+          if(temp == mytest) result++;
+#if 1
+	  SiS_SetReg(SISPART4, 0x11, 0x00);
+	  SiS_SetRegAND(SISPART4, 0x10, 0xe0);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
+#endif
+       }
+       if((result == 0) || (result >= 2)) break;
+    }
+    return result;
+}
+
+static void SiS_Sense30x(struct sis_video_info *ivideo)
+{
+    u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
+    u16 svhs=0, svhs_c=0;
+    u16 cvbs=0, cvbs_c=0;
+    u16 vga2=0, vga2_c=0;
+    int myflag, result;
+    char stdstr[] = "sisfb: Detected";
+    char tvstr[]  = "TV connected to";
+
+    if(ivideo->vbflags2 & VB2_301) {
+       svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
+       myflag = SiS_GetReg(SISPART4, 0x01);
+       if(myflag & 0x04) {
+	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
+       }
+    } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
+       svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
+    } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
+       svhs = 0x0200; cvbs = 0x0100;
+    } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
+       svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
+    } else
+       return;
+
+    vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
+    if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
+       svhs_c = 0x0408; cvbs_c = 0x0808;
+    }
+
+    biosflag = 2;
+    if(ivideo->haveXGIROM) {
+       biosflag = ivideo->bios_abase[0x58] & 0x03;
+    } else if(ivideo->newrom) {
+       if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
+    } else if(ivideo->sisvga_engine == SIS_300_VGA) {
+       if(ivideo->bios_abase) {
+          biosflag = ivideo->bios_abase[0xfe] & 0x03;
+       }
+    }
+
+    if(ivideo->chip == SIS_300) {
+       myflag = SiS_GetReg(SISSR, 0x3b);
+       if(!(myflag & 0x01)) vga2 = vga2_c = 0;
+    }
+
+    if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
+       vga2 = vga2_c = 0;
+    }
+
+    backupSR_1e = SiS_GetReg(SISSR, 0x1e);
+    SiS_SetRegOR(SISSR, 0x1e, 0x20);
+
+    backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
+    if(ivideo->vbflags2 & VB2_30xC) {
+	SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
+    } else {
+       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
+    }
+    SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
+
+    backupP2_00 = SiS_GetReg(SISPART2, 0x00);
+    SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
+
+    backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
+    if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
+	SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
+    }
+
+    if(!(ivideo->vbflags2 & VB2_30xCLV)) {
+       SISDoSense(ivideo, 0, 0);
+    }
+
+    SiS_SetRegAND(SISCR, 0x32, ~0x14);
+
+    if(vga2_c || vga2) {
+       if(SISDoSense(ivideo, vga2, vga2_c)) {
+          if(biosflag & 0x01) {
+	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
+	     SiS_SetRegOR(SISCR, 0x32, 0x04);
+	  } else {
+	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
+	     SiS_SetRegOR(SISCR, 0x32, 0x10);
+	  }
+       }
+    }
+
+    SiS_SetRegAND(SISCR, 0x32, 0x3f);
+
+    if(ivideo->vbflags2 & VB2_30xCLV) {
+       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
+    }
+
+    if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
+       SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
+       if((result = SISDoSense(ivideo, svhs, 0x0604))) {
+          if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
+	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
+	     SiS_SetRegOR(SISCR, 0x32, 0x80);
+	  }
+       }
+       SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
+    }
+
+    SiS_SetRegAND(SISCR, 0x32, ~0x03);
+
+    if(!(ivideo->vbflags & TV_YPBPR)) {
+       if((result = SISDoSense(ivideo, svhs, svhs_c))) {
+          printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
+	   SiS_SetRegOR(SISCR, 0x32, 0x02);
+       }
+       if((biosflag & 0x02) || (!result)) {
+          if(SISDoSense(ivideo, cvbs, cvbs_c)) {
+	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
+	     SiS_SetRegOR(SISCR, 0x32, 0x01);
+          }
+       }
+    }
+
+    SISDoSense(ivideo, 0, 0);
+
+    SiS_SetReg(SISPART2, 0x00, backupP2_00);
+    SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
+    SiS_SetReg(SISSR, 0x1e, backupSR_1e);
+
+    if(ivideo->vbflags2 & VB2_30xCLV) {
+	biosflag = SiS_GetReg(SISPART2, 0x00);
+       if(biosflag & 0x20) {
+          for(myflag = 2; myflag > 0; myflag--) {
+	     biosflag ^= 0x20;
+	     SiS_SetReg(SISPART2, 0x00, biosflag);
+	  }
+       }
+    }
+
+    SiS_SetReg(SISPART2, 0x00, backupP2_00);
+}
+
+/* Determine and detect attached TV's on Chrontel */
+static void SiS_SenseCh(struct sis_video_info *ivideo)
+{
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+    u8 temp1, temp2;
+    char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
+#endif
+#ifdef CONFIG_FB_SIS_300
+    unsigned char test[3];
+    int i;
+#endif
+
+    if(ivideo->chip < SIS_315H) {
+
+#ifdef CONFIG_FB_SIS_300
+       ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
+       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
+       /* See Chrontel TB31 for explanation */
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
+       if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
+	  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
+       }
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
+       if(temp2 != temp1) temp1 = temp2;
+
+       if((temp1 >= 0x22) && (temp1 <= 0x50)) {
+	   /* Read power status */
+	   temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
+	   if((temp1 & 0x03) != 0x03) {
+		/* Power all outputs */
+		SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
+		SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
+	   }
+	   /* Sense connected TV devices */
+	   for(i = 0; i < 3; i++) {
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
+	       if(!(temp1 & 0x08))       test[i] = 0x02;
+	       else if(!(temp1 & 0x02))  test[i] = 0x01;
+	       else                      test[i] = 0;
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	   }
+
+	   if(test[0] == test[1])      temp1 = test[0];
+	   else if(test[0] == test[2]) temp1 = test[0];
+	   else if(test[1] == test[2]) temp1 = test[1];
+	   else {
+		printk(KERN_INFO
+			"sisfb: TV detection unreliable - test results varied\n");
+		temp1 = test[2];
+	   }
+	   if(temp1 == 0x02) {
+		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
+		ivideo->vbflags |= TV_SVIDEO;
+		SiS_SetRegOR(SISCR, 0x32, 0x02);
+		SiS_SetRegAND(SISCR, 0x32, ~0x05);
+	   } else if (temp1 == 0x01) {
+		printk(KERN_INFO "%s CVBS output\n", stdstr);
+		ivideo->vbflags |= TV_AVIDEO;
+		SiS_SetRegOR(SISCR, 0x32, 0x01);
+		SiS_SetRegAND(SISCR, 0x32, ~0x06);
+	   } else {
+		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
+		SiS_SetRegAND(SISCR, 0x32, ~0x07);
+	   }
+       } else if(temp1 == 0) {
+	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
+	  SiS_SetRegAND(SISCR, 0x32, ~0x07);
+       }
+       /* Set general purpose IO for Chrontel communication */
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
+#endif
+
+    } else {
+
+#ifdef CONFIG_FB_SIS_315
+	ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
+	temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
+	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
+	temp2 |= 0x01;
+	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 ^= 0x01;
+	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
+	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
+	temp1 = 0;
+	if(temp2 & 0x02) temp1 |= 0x01;
+	if(temp2 & 0x10) temp1 |= 0x01;
+	if(temp2 & 0x04) temp1 |= 0x02;
+	if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
+	switch(temp1) {
+	case 0x01:
+	     printk(KERN_INFO "%s CVBS output\n", stdstr);
+	     ivideo->vbflags |= TV_AVIDEO;
+	     SiS_SetRegOR(SISCR, 0x32, 0x01);
+	     SiS_SetRegAND(SISCR, 0x32, ~0x06);
+	     break;
+	case 0x02:
+	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
+	     ivideo->vbflags |= TV_SVIDEO;
+	     SiS_SetRegOR(SISCR, 0x32, 0x02);
+	     SiS_SetRegAND(SISCR, 0x32, ~0x05);
+	     break;
+	case 0x04:
+	     printk(KERN_INFO "%s SCART output\n", stdstr);
+	     SiS_SetRegOR(SISCR, 0x32, 0x04);
+	     SiS_SetRegAND(SISCR, 0x32, ~0x03);
+	     break;
+	default:
+	     SiS_SetRegAND(SISCR, 0x32, ~0x07);
+	}
+#endif
+    }
+}
+
+static void sisfb_get_VB_type(struct sis_video_info *ivideo)
+{
+	char stdstr[]    = "sisfb: Detected";
+	char bridgestr[] = "video bridge";
+	u8 vb_chipid;
+	u8 reg;
+
+	/* No CRT2 on XGI Z7 */
+	if(ivideo->chip == XGI_20)
+		return;
+
+	vb_chipid = SiS_GetReg(SISPART4, 0x00);
+	switch(vb_chipid) {
+	case 0x01:
+		reg = SiS_GetReg(SISPART4, 0x01);
+		if(reg < 0xb0) {
+			ivideo->vbflags |= VB_301;	/* Deprecated */
+			ivideo->vbflags2 |= VB2_301;
+			printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
+		} else if(reg < 0xc0) {
+			ivideo->vbflags |= VB_301B;	/* Deprecated */
+			ivideo->vbflags2 |= VB2_301B;
+			reg = SiS_GetReg(SISPART4, 0x23);
+			if(!(reg & 0x02)) {
+			   ivideo->vbflags |= VB_30xBDH;	/* Deprecated */
+			   ivideo->vbflags2 |= VB2_30xBDH;
+			   printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
+			} else {
+			   printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
+			}
+		} else if(reg < 0xd0) {
+			ivideo->vbflags |= VB_301C;	/* Deprecated */
+			ivideo->vbflags2 |= VB2_301C;
+			printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
+		} else if(reg < 0xe0) {
+			ivideo->vbflags |= VB_301LV;	/* Deprecated */
+			ivideo->vbflags2 |= VB2_301LV;
+			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
+		} else if(reg <= 0xe1) {
+			reg = SiS_GetReg(SISPART4, 0x39);
+			if(reg == 0xff) {
+			   ivideo->vbflags |= VB_302LV;	/* Deprecated */
+			   ivideo->vbflags2 |= VB2_302LV;
+			   printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
+			} else {
+			   ivideo->vbflags |= VB_301C;	/* Deprecated */
+			   ivideo->vbflags2 |= VB2_301C;
+			   printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
+#if 0
+			   ivideo->vbflags |= VB_302ELV;	/* Deprecated */
+			   ivideo->vbflags2 |= VB2_302ELV;
+			   printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+#endif
+			}
+		}
+		break;
+	case 0x02:
+		ivideo->vbflags |= VB_302B;	/* Deprecated */
+		ivideo->vbflags2 |= VB2_302B;
+		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
+		break;
+	}
+
+	if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
+		reg = SiS_GetReg(SISCR, 0x37);
+		reg &= SIS_EXTERNAL_CHIP_MASK;
+		reg >>= 1;
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+			switch(reg) {
+			   case SIS_EXTERNAL_CHIP_LVDS:
+				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
+				ivideo->vbflags2 |= VB2_LVDS;
+				break;
+			   case SIS_EXTERNAL_CHIP_TRUMPION:
+				ivideo->vbflags |= (VB_LVDS | VB_TRUMPION);	/* Deprecated */
+				ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
+				break;
+			   case SIS_EXTERNAL_CHIP_CHRONTEL:
+				ivideo->vbflags |= VB_CHRONTEL;	/* Deprecated */
+				ivideo->vbflags2 |= VB2_CHRONTEL;
+				break;
+			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
+				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+				break;
+			}
+			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
+#endif
+		} else if(ivideo->chip < SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+			switch (reg) {
+			   case SIS310_EXTERNAL_CHIP_LVDS:
+				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
+				ivideo->vbflags2 |= VB2_LVDS;
+				break;
+			   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
+				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+				break;
+			}
+			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+		} else if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+			reg = SiS_GetReg(SISCR, 0x38);
+			reg >>= 5;
+			switch(reg) {
+			   case 0x02:
+				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
+				ivideo->vbflags2 |= VB2_LVDS;
+				break;
+			   case 0x03:
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
+				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+				break;
+			   case 0x04:
+				ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);	/* Deprecated */
+				ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
+				break;
+			}
+			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+		}
+		if(ivideo->vbflags2 & VB2_LVDS) {
+		   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
+		}
+		if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
+		   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
+		}
+		if(ivideo->vbflags2 & VB2_CHRONTEL) {
+		   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
+		}
+		if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
+		   printk(KERN_INFO "%s Conexant external device\n", stdstr);
+		}
+	}
+
+	if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+		SiS_SenseLCD(ivideo);
+		SiS_Sense30x(ivideo);
+	} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+		SiS_SenseCh(ivideo);
+	}
+}
+
+/* ---------- Engine initialization routines ------------ */
+
+static void
+sisfb_engine_init(struct sis_video_info *ivideo)
+{
+
+	/* Initialize command queue (we use MMIO only) */
+
+	/* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
+
+	ivideo->caps &= ~(TURBO_QUEUE_CAP    |
+			  MMIO_CMD_QUEUE_CAP |
+			  VM_CMD_QUEUE_CAP   |
+			  AGP_CMD_QUEUE_CAP);
+
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		u32 tqueue_pos;
+		u8 tq_state;
+
+		tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
+
+		tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
+		tq_state |= 0xf0;
+		tq_state &= 0xfc;
+		tq_state |= (u8)(tqueue_pos >> 8);
+		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+
+		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+
+		ivideo->caps |= TURBO_QUEUE_CAP;
+	}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+		u32 tempq = 0, templ;
+		u8  temp;
+
+		if(ivideo->chip == XGI_20) {
+			switch(ivideo->cmdQueueSize) {
+			case (64 * 1024):
+				temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
+				break;
+			case (128 * 1024):
+			default:
+				temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
+			}
+		} else {
+			switch(ivideo->cmdQueueSize) {
+			case (4 * 1024 * 1024):
+				temp = SIS_CMD_QUEUE_SIZE_4M;
+				break;
+			case (2 * 1024 * 1024):
+				temp = SIS_CMD_QUEUE_SIZE_2M;
+				break;
+			case (1 * 1024 * 1024):
+				temp = SIS_CMD_QUEUE_SIZE_1M;
+				break;
+			default:
+			case (512 * 1024):
+				temp = SIS_CMD_QUEUE_SIZE_512k;
+			}
+		}
+
+		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+		if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
+			/* Must disable dual pipe on XGI_40. Can't do
+			 * this in MMIO mode, because it requires
+			 * setting/clearing a bit in the MMIO fire trigger
+			 * register.
+			 */
+			if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
+
+				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
+
+				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
+
+				tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
+				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
+
+				tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+				MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
+
+				writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
+				writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
+				writel(0x168F0000, ivideo->video_vbase + tempq + 8);
+				writel(0x168F0000, ivideo->video_vbase + tempq + 12);
+
+				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
+
+				sisfb_syncaccel(ivideo);
+
+				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+			}
+		}
+
+		tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
+		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+
+		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+
+		tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
+
+		ivideo->caps |= MMIO_CMD_QUEUE_CAP;
+	}
+#endif
+
+	ivideo->engineok = 1;
+}
+
+static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
+{
+	u8 reg;
+	int i;
+
+	reg = SiS_GetReg(SISCR, 0x36);
+	reg &= 0x0f;
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		ivideo->CRT2LCDType = sis300paneltype[reg];
+	} else if(ivideo->chip >= SIS_661) {
+		ivideo->CRT2LCDType = sis661paneltype[reg];
+	} else {
+		ivideo->CRT2LCDType = sis310paneltype[reg];
+		if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
+			if((ivideo->CRT2LCDType != LCD_320x240_2) &&
+			   (ivideo->CRT2LCDType != LCD_320x240_3)) {
+				ivideo->CRT2LCDType = LCD_320x240;
+			}
+		}
+	}
+
+	if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
+		/* For broken BIOSes: Assume 1024x768, RGB18 */
+		ivideo->CRT2LCDType = LCD_1024x768;
+		SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
+		SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
+		printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
+	}
+
+	for(i = 0; i < SIS_LCD_NUMBER; i++) {
+		if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
+			ivideo->lcdxres = sis_lcd_data[i].xres;
+			ivideo->lcdyres = sis_lcd_data[i].yres;
+			ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
+			break;
+		}
+	}
+
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
+		ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
+		ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
+	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
+		ivideo->lcdxres =  848; ivideo->lcdyres =  480;
+		ivideo->lcddefmodeidx = DEFAULT_MODE_848;
+	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
+		ivideo->lcdxres =  856; ivideo->lcdyres =  480;
+		ivideo->lcddefmodeidx = DEFAULT_MODE_856;
+	}
+#endif
+
+	printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
+			ivideo->lcdxres, ivideo->lcdyres);
+}
+
+static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
+{
+#ifdef CONFIG_FB_SIS_300
+	/* Save the current PanelDelayCompensation if the LCD is currently used */
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
+			int tmp;
+			tmp = SiS_GetReg(SISCR, 0x30);
+			if(tmp & 0x20) {
+				/* Currently on LCD? If yes, read current pdc */
+				ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
+				ivideo->detectedpdc &= 0x3c;
+				if(ivideo->SiS_Pr.PDC == -1) {
+					/* Let option override detection */
+					ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+				}
+				printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
+					ivideo->detectedpdc);
+			}
+			if((ivideo->SiS_Pr.PDC != -1) &&
+			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
+					ivideo->SiS_Pr.PDC);
+			}
+		}
+	}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+
+		/* Try to find about LCDA */
+		if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
+			int tmp;
+			tmp = SiS_GetReg(SISPART1, 0x13);
+			if(tmp & 0x04) {
+				ivideo->SiS_Pr.SiS_UseLCDA = true;
+				ivideo->detectedlcda = 0x03;
+			}
+		}
+
+		/* Save PDC */
+		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+			int tmp;
+			tmp = SiS_GetReg(SISCR, 0x30);
+			if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+				/* Currently on LCD? If yes, read current pdc */
+				u8 pdc;
+				pdc = SiS_GetReg(SISPART1, 0x2D);
+				ivideo->detectedpdc  = (pdc & 0x0f) << 1;
+				ivideo->detectedpdca = (pdc & 0xf0) >> 3;
+				pdc = SiS_GetReg(SISPART1, 0x35);
+				ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
+				pdc = SiS_GetReg(SISPART1, 0x20);
+				ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
+				if(ivideo->newrom) {
+					/* New ROM invalidates other PDC resp. */
+					if(ivideo->detectedlcda != 0xff) {
+						ivideo->detectedpdc = 0xff;
+					} else {
+						ivideo->detectedpdca = 0xff;
+					}
+				}
+				if(ivideo->SiS_Pr.PDC == -1) {
+					if(ivideo->detectedpdc != 0xff) {
+						ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+					}
+				}
+				if(ivideo->SiS_Pr.PDCA == -1) {
+					if(ivideo->detectedpdca != 0xff) {
+						ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
+					}
+				}
+				if(ivideo->detectedpdc != 0xff) {
+					printk(KERN_INFO
+						"sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
+						ivideo->detectedpdc);
+				}
+				if(ivideo->detectedpdca != 0xff) {
+					printk(KERN_INFO
+						"sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
+						ivideo->detectedpdca);
+				}
+			}
+
+			/* Save EMI */
+			if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
+				ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
+				ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
+				ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
+				ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
+				ivideo->SiS_Pr.HaveEMI = true;
+				if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+					ivideo->SiS_Pr.HaveEMILCD = true;
+				}
+			}
+		}
+
+		/* Let user override detected PDCs (all bridges) */
+		if(ivideo->vbflags2 & VB2_30xBLV) {
+			if((ivideo->SiS_Pr.PDC != -1) &&
+			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
+					ivideo->SiS_Pr.PDC);
+			}
+			if((ivideo->SiS_Pr.PDCA != -1) &&
+			   (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
+				printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
+				 ivideo->SiS_Pr.PDCA);
+			}
+		}
+
+	}
+#endif
+}
+
+/* -------------------- Memory manager routines ---------------------- */
+
+static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
+{
+	u32 ret = ivideo->sisfb_parm_mem * 1024;
+	u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+	u32 def;
+
+	/* Calculate heap start = end of memory for console
+	 *
+	 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
+	 * C = console, D = heap, H = HWCursor, Q = cmd-queue
+	 *
+	 * On 76x in UMA+LFB mode, the layout is as follows:
+	 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
+	 * where the heap is the entire UMA area, eventually
+	 * into the LFB area if the given mem parameter is
+	 * higher than the size of the UMA memory.
+	 *
+	 * Basically given by "mem" parameter
+	 *
+	 * maximum = videosize - cmd_queue - hwcursor
+	 *           (results in a heap of size 0)
+	 * default = SiS 300: depends on videosize
+	 *           SiS 315/330/340/XGI: 32k below max
+	 */
+
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		if(ivideo->video_size > 0x1000000) {
+			def = 0xc00000;
+		} else if(ivideo->video_size > 0x800000) {
+			def = 0x800000;
+		} else {
+			def = 0x400000;
+		}
+	} else if(ivideo->UMAsize && ivideo->LFBsize) {
+		ret = def = 0;
+	} else {
+		def = maxoffs - 0x8000;
+	}
+
+	/* Use default for secondary card for now (FIXME) */
+	if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
+		ret = def;
+
+	return ret;
+}
+
+static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
+{
+	u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+	u32 ret = 0;
+
+	if(ivideo->UMAsize && ivideo->LFBsize) {
+		if( (!ivideo->sisfb_parm_mem)			||
+		    ((ivideo->sisfb_parm_mem * 1024) > max)	||
+		    ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
+			ret = ivideo->UMAsize;
+			max -= ivideo->UMAsize;
+		} else {
+			ret = max - (ivideo->sisfb_parm_mem * 1024);
+			max = ivideo->sisfb_parm_mem * 1024;
+		}
+		ivideo->video_offset = ret;
+		ivideo->sisfb_mem = max;
+	} else {
+		ret = max - ivideo->heapstart;
+		ivideo->sisfb_mem = ivideo->heapstart;
+	}
+
+	return ret;
+}
+
+static int sisfb_heap_init(struct sis_video_info *ivideo)
+{
+	struct SIS_OH *poh;
+
+	ivideo->video_offset = 0;
+	if(ivideo->sisfb_parm_mem) {
+		if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
+		    (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
+			ivideo->sisfb_parm_mem = 0;
+		}
+	}
+
+	ivideo->heapstart = sisfb_getheapstart(ivideo);
+	ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
+
+	ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
+	ivideo->sisfb_heap_end   = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
+
+	printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
+		(int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
+
+	ivideo->sisfb_heap.vinfo = ivideo;
+
+	ivideo->sisfb_heap.poha_chain = NULL;
+	ivideo->sisfb_heap.poh_freelist = NULL;
+
+	poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
+	if(poh == NULL)
+		return 1;
+
+	poh->poh_next = &ivideo->sisfb_heap.oh_free;
+	poh->poh_prev = &ivideo->sisfb_heap.oh_free;
+	poh->size = ivideo->sisfb_heap_size;
+	poh->offset = ivideo->heapstart;
+
+	ivideo->sisfb_heap.oh_free.poh_next = poh;
+	ivideo->sisfb_heap.oh_free.poh_prev = poh;
+	ivideo->sisfb_heap.oh_free.size = 0;
+	ivideo->sisfb_heap.max_freesize = poh->size;
+
+	ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
+	ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
+	ivideo->sisfb_heap.oh_used.size = SENTINEL;
+
+	if(ivideo->cardnumber == 0) {
+		/* For the first card, make this heap the "global" one
+		 * for old DRM (which could handle only one card)
+		 */
+		sisfb_heap = &ivideo->sisfb_heap;
+	}
+
+	return 0;
+}
+
+static struct SIS_OH *
+sisfb_poh_new_node(struct SIS_HEAP *memheap)
+{
+	struct SIS_OHALLOC	*poha;
+	struct SIS_OH		*poh;
+	unsigned long		cOhs;
+	int			i;
+
+	if(memheap->poh_freelist == NULL) {
+		poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
+		if(!poha)
+			return NULL;
+
+		poha->poha_next = memheap->poha_chain;
+		memheap->poha_chain = poha;
+
+		cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
+
+		poh = &poha->aoh[0];
+		for(i = cOhs - 1; i != 0; i--) {
+			poh->poh_next = poh + 1;
+			poh = poh + 1;
+		}
+
+		poh->poh_next = NULL;
+		memheap->poh_freelist = &poha->aoh[0];
+	}
+
+	poh = memheap->poh_freelist;
+	memheap->poh_freelist = poh->poh_next;
+
+	return poh;
+}
+
+static struct SIS_OH *
+sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
+{
+	struct SIS_OH	*pohThis;
+	struct SIS_OH	*pohRoot;
+	int		bAllocated = 0;
+
+	if(size > memheap->max_freesize) {
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
+			(unsigned int) size / 1024);
+		return NULL;
+	}
+
+	pohThis = memheap->oh_free.poh_next;
+
+	while(pohThis != &memheap->oh_free) {
+		if(size <= pohThis->size) {
+			bAllocated = 1;
+			break;
+		}
+		pohThis = pohThis->poh_next;
+	}
+
+	if(!bAllocated) {
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
+			(unsigned int) size / 1024);
+		return NULL;
+	}
+
+	if(size == pohThis->size) {
+		pohRoot = pohThis;
+		sisfb_delete_node(pohThis);
+	} else {
+		pohRoot = sisfb_poh_new_node(memheap);
+		if(pohRoot == NULL)
+			return NULL;
+
+		pohRoot->offset = pohThis->offset;
+		pohRoot->size = size;
+
+		pohThis->offset += size;
+		pohThis->size -= size;
+	}
+
+	memheap->max_freesize -= size;
+
+	pohThis = &memheap->oh_used;
+	sisfb_insert_node(pohThis, pohRoot);
+
+	return pohRoot;
+}
+
+static void
+sisfb_delete_node(struct SIS_OH *poh)
+{
+	poh->poh_prev->poh_next = poh->poh_next;
+	poh->poh_next->poh_prev = poh->poh_prev;
+}
+
+static void
+sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
+{
+	struct SIS_OH *pohTemp = pohList->poh_next;
+
+	pohList->poh_next = poh;
+	pohTemp->poh_prev = poh;
+
+	poh->poh_prev = pohList;
+	poh->poh_next = pohTemp;
+}
+
+static struct SIS_OH *
+sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
+{
+	struct SIS_OH *pohThis;
+	struct SIS_OH *poh_freed;
+	struct SIS_OH *poh_prev;
+	struct SIS_OH *poh_next;
+	u32    ulUpper;
+	u32    ulLower;
+	int    foundNode = 0;
+
+	poh_freed = memheap->oh_used.poh_next;
+
+	while(poh_freed != &memheap->oh_used) {
+		if(poh_freed->offset == base) {
+			foundNode = 1;
+			break;
+		}
+
+		poh_freed = poh_freed->poh_next;
+	}
+
+	if(!foundNode)
+		return NULL;
+
+	memheap->max_freesize += poh_freed->size;
+
+	poh_prev = poh_next = NULL;
+	ulUpper = poh_freed->offset + poh_freed->size;
+	ulLower = poh_freed->offset;
+
+	pohThis = memheap->oh_free.poh_next;
+
+	while(pohThis != &memheap->oh_free) {
+		if(pohThis->offset == ulUpper) {
+			poh_next = pohThis;
+		} else if((pohThis->offset + pohThis->size) == ulLower) {
+			poh_prev = pohThis;
+		}
+		pohThis = pohThis->poh_next;
+	}
+
+	sisfb_delete_node(poh_freed);
+
+	if(poh_prev && poh_next) {
+		poh_prev->size += (poh_freed->size + poh_next->size);
+		sisfb_delete_node(poh_next);
+		sisfb_free_node(memheap, poh_freed);
+		sisfb_free_node(memheap, poh_next);
+		return poh_prev;
+	}
+
+	if(poh_prev) {
+		poh_prev->size += poh_freed->size;
+		sisfb_free_node(memheap, poh_freed);
+		return poh_prev;
+	}
+
+	if(poh_next) {
+		poh_next->size += poh_freed->size;
+		poh_next->offset = poh_freed->offset;
+		sisfb_free_node(memheap, poh_freed);
+		return poh_next;
+	}
+
+	sisfb_insert_node(&memheap->oh_free, poh_freed);
+
+	return poh_freed;
+}
+
+static void
+sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
+{
+	if(poh == NULL)
+		return;
+
+	poh->poh_next = memheap->poh_freelist;
+	memheap->poh_freelist = poh;
+}
+
+static void
+sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
+{
+	struct SIS_OH *poh = NULL;
+
+	if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
+		poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
+
+	if(poh == NULL) {
+		req->offset = req->size = 0;
+		DPRINTK("sisfb: Video RAM allocation failed\n");
+	} else {
+		req->offset = poh->offset;
+		req->size = poh->size;
+		DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
+			(poh->offset + ivideo->video_vbase));
+	}
+}
+
+void
+sis_malloc(struct sis_memreq *req)
+{
+	struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+	if(&ivideo->sisfb_heap == sisfb_heap)
+		sis_int_malloc(ivideo, req);
+	else
+		req->offset = req->size = 0;
+}
+
+void
+sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+	sis_int_malloc(ivideo, req);
+}
+
+/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+
+static void
+sis_int_free(struct sis_video_info *ivideo, u32 base)
+{
+	struct SIS_OH *poh;
+
+	if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
+		return;
+
+	poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
+
+	if(poh == NULL) {
+		DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
+			(unsigned int) base);
+	}
+}
+
+void
+sis_free(u32 base)
+{
+	struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+	sis_int_free(ivideo, base);
+}
+
+void
+sis_free_new(struct pci_dev *pdev, u32 base)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+	sis_int_free(ivideo, base);
+}
+
+/* --------------------- SetMode routines ------------------------- */
+
+static void
+sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
+{
+	u8 cr30, cr31;
+
+	/* Check if MMIO and engines are enabled,
+	 * and sync in case they are. Can't use
+	 * ivideo->accel here, as this might have
+	 * been changed before this is called.
+	 */
+	cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
+	cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
+	/* MMIO and 2D/3D engine enabled? */
+	if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
+#ifdef CONFIG_FB_SIS_300
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+			/* Don't care about TurboQueue. It's
+			 * enough to know that the engines
+			 * are enabled
+			 */
+			sisfb_syncaccel(ivideo);
+		}
+#endif
+#ifdef CONFIG_FB_SIS_315
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
+			/* Check that any queue mode is
+			 * enabled, and that the queue
+			 * is not in the state of "reset"
+			 */
+			cr30 = SiS_GetReg(SISSR, 0x26);
+			if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
+				sisfb_syncaccel(ivideo);
+			}
+		}
+#endif
+	}
+}
+
+static void
+sisfb_pre_setmode(struct sis_video_info *ivideo)
+{
+	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
+	int tvregnum = 0;
+
+	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
+
+	SiS_SetReg(SISSR, 0x05, 0x86);
+
+	cr31 = SiS_GetReg(SISCR, 0x31);
+	cr31 &= ~0x60;
+	cr31 |= 0x04;
+
+	cr33 = ivideo->rate_idx & 0x0F;
+
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if(ivideo->chip >= SIS_661) {
+	      cr38 = SiS_GetReg(SISCR, 0x38);
+	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   } else {
+	      tvregnum = 0x38;
+	      cr38 = SiS_GetReg(SISCR, tvregnum);
+	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   }
+	}
+#endif
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   tvregnum = 0x35;
+	   cr38 = SiS_GetReg(SISCR, tvregnum);
+	}
+#endif
+
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
+	ivideo->curFSTN = ivideo->curDSTN = 0;
+
+	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+
+	   case CRT2_TV:
+	      cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
+	      if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
+#ifdef CONFIG_FB_SIS_315
+		 if(ivideo->chip >= SIS_661) {
+		    cr38 |= 0x04;
+		    if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
+		    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
+		    cr35 &= ~0x01;
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+		 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+		    cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    cr38 |= 0x08;
+		    if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
+		    cr31 &= ~0x01;
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+		 }
+#endif
+	      } else if((ivideo->vbflags & TV_HIVISION) &&
+				(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
+		 if(ivideo->chip >= SIS_661) {
+		    cr38 |= 0x04;
+		    cr35 |= 0x60;
+		 } else {
+		    cr30 |= 0x80;
+		 }
+		 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
+		 cr31 |= 0x01;
+		 cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_HIVISION;
+	      } else if(ivideo->vbflags & TV_SCART) {
+		 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		 cr31 |= 0x01;
+		 cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_SCART;
+	      } else {
+		 if(ivideo->vbflags & TV_SVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_SVIDEO;
+		 }
+		 if(ivideo->vbflags & TV_AVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_AVIDEO;
+		 }
+	      }
+	      cr31 |= SIS_DRIVER_MODE;
+
+	      if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
+		 if(ivideo->vbflags & TV_PAL) {
+		    cr31 |= 0x01; cr35 |= 0x01;
+		    ivideo->currentvbflags |= TV_PAL;
+		    if(ivideo->vbflags & TV_PALM) {
+		       cr38 |= 0x40; cr35 |= 0x04;
+		       ivideo->currentvbflags |= TV_PALM;
+		    } else if(ivideo->vbflags & TV_PALN) {
+		       cr38 |= 0x80; cr35 |= 0x08;
+		       ivideo->currentvbflags |= TV_PALN;
+		    }
+		 } else {
+		    cr31 &= ~0x01; cr35 &= ~0x01;
+		    ivideo->currentvbflags |= TV_NTSC;
+		    if(ivideo->vbflags & TV_NTSCJ) {
+		       cr38 |= 0x40; cr35 |= 0x02;
+		       ivideo->currentvbflags |= TV_NTSCJ;
+		    }
+		 }
+	      }
+	      break;
+
+	   case CRT2_LCD:
+	      cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
+	      SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
+	      ivideo->curFSTN = ivideo->sisfb_fstn;
+	      ivideo->curDSTN = ivideo->sisfb_dstn;
+	      break;
+
+	   case CRT2_VGA:
+	      cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      if(ivideo->sisfb_nocrt2rate) {
+		 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
+	      } else {
+		 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
+	      }
+	      break;
+
+	   default:	/* disable CRT2 */
+	      cr30 = 0x00;
+	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
+	}
+
+	SiS_SetReg(SISCR, 0x30, cr30);
+	SiS_SetReg(SISCR, 0x33, cr33);
+
+	if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
+	   SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
+	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
+	   SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
+#endif
+	} else if(ivideo->chip != SIS_300) {
+	   SiS_SetReg(SISCR, tvregnum, cr38);
+	}
+	SiS_SetReg(SISCR, 0x31, cr31);
+
+	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
+
+	sisfb_check_engine_and_sync(ivideo);
+}
+
+/* Fix SR11 for 661 and later */
+#ifdef CONFIG_FB_SIS_315
+static void
+sisfb_fixup_SR11(struct sis_video_info *ivideo)
+{
+	u8  tmpreg;
+
+	if(ivideo->chip >= SIS_661) {
+		tmpreg = SiS_GetReg(SISSR, 0x11);
+		if(tmpreg & 0x20) {
+			tmpreg = SiS_GetReg(SISSR, 0x3e);
+			tmpreg = (tmpreg + 1) & 0xff;
+			SiS_SetReg(SISSR, 0x3e, tmpreg);
+			tmpreg = SiS_GetReg(SISSR, 0x11);
+		}
+		if(tmpreg & 0xf0) {
+			SiS_SetRegAND(SISSR, 0x11, 0x0f);
+		}
+	}
+}
+#endif
+
+static void
+sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
+{
+	if(val > 32) val = 32;
+	if(val < -32) val = -32;
+	ivideo->tvxpos = val;
+
+	if(ivideo->sisfblocked) return;
+	if(!ivideo->modechanged) return;
+
+	if(ivideo->currentvbflags & CRT2_TV) {
+
+		if(ivideo->vbflags2 & VB2_CHRONTEL) {
+
+			int x = ivideo->tvx;
+
+			switch(ivideo->chronteltype) {
+			case 1:
+				x += val;
+				if(x < 0) x = 0;
+				SiS_SetReg(SISSR, 0x05, 0x86);
+				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
+				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
+				break;
+			case 2:
+				/* Not supported by hardware */
+				break;
+			}
+
+		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+			u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
+			unsigned short temp;
+
+			p2_1f = ivideo->p2_1f;
+			p2_20 = ivideo->p2_20;
+			p2_2b = ivideo->p2_2b;
+			p2_42 = ivideo->p2_42;
+			p2_43 = ivideo->p2_43;
+
+			temp = p2_1f | ((p2_20 & 0xf0) << 4);
+			temp += (val * 2);
+			p2_1f = temp & 0xff;
+			p2_20 = (temp & 0xf00) >> 4;
+			p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
+			temp = p2_43 | ((p2_42 & 0xf0) << 4);
+			temp += (val * 2);
+			p2_43 = temp & 0xff;
+			p2_42 = (temp & 0xf00) >> 4;
+			SiS_SetReg(SISPART2, 0x1f, p2_1f);
+			SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
+			SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
+			SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
+			SiS_SetReg(SISPART2, 0x43, p2_43);
+		}
+	}
+}
+
+static void
+sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
+{
+	if(val > 32) val = 32;
+	if(val < -32) val = -32;
+	ivideo->tvypos = val;
+
+	if(ivideo->sisfblocked) return;
+	if(!ivideo->modechanged) return;
+
+	if(ivideo->currentvbflags & CRT2_TV) {
+
+		if(ivideo->vbflags2 & VB2_CHRONTEL) {
+
+			int y = ivideo->tvy;
+
+			switch(ivideo->chronteltype) {
+			case 1:
+				y -= val;
+				if(y < 0) y = 0;
+				SiS_SetReg(SISSR, 0x05, 0x86);
+				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
+				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
+				break;
+			case 2:
+				/* Not supported by hardware */
+				break;
+			}
+
+		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+			char p2_01, p2_02;
+			val /= 2;
+			p2_01 = ivideo->p2_01;
+			p2_02 = ivideo->p2_02;
+
+			p2_01 += val;
+			p2_02 += val;
+			if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
+				while((p2_01 <= 0) || (p2_02 <= 0)) {
+					p2_01 += 2;
+					p2_02 += 2;
+				}
+			}
+			SiS_SetReg(SISPART2, 0x01, p2_01);
+			SiS_SetReg(SISPART2, 0x02, p2_02);
+		}
+	}
+}
+
+static void
+sisfb_post_setmode(struct sis_video_info *ivideo)
+{
+	bool crt1isoff = false;
+	bool doit = true;
+#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
+	u8 reg;
+#endif
+#ifdef CONFIG_FB_SIS_315
+	u8 reg1;
+#endif
+
+	SiS_SetReg(SISSR, 0x05, 0x86);
+
+#ifdef CONFIG_FB_SIS_315
+	sisfb_fixup_SR11(ivideo);
+#endif
+
+	/* Now we actually HAVE changed the display mode */
+	ivideo->modechanged = 1;
+
+	/* We can't switch off CRT1 if bridge is in slave mode */
+	if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
+		if(sisfb_bridgeisslave(ivideo)) doit = false;
+	} else
+		ivideo->sisfb_crt1off = 0;
+
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		if((ivideo->sisfb_crt1off) && (doit)) {
+			crt1isoff = true;
+			reg = 0x00;
+		} else {
+			crt1isoff = false;
+			reg = 0x80;
+		}
+		SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
+	}
+#endif
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+		if((ivideo->sisfb_crt1off) && (doit)) {
+			crt1isoff = true;
+			reg  = 0x40;
+			reg1 = 0xc0;
+		} else {
+			crt1isoff = false;
+			reg  = 0x00;
+			reg1 = 0x00;
+		}
+		SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
+		SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
+	}
+#endif
+
+	if(crt1isoff) {
+		ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
+		ivideo->currentvbflags |= VB_SINGLE_MODE;
+	} else {
+		ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
+		if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
+			ivideo->currentvbflags |= VB_MIRROR_MODE;
+		} else {
+			ivideo->currentvbflags |= VB_SINGLE_MODE;
+		}
+	}
+
+	SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+
+	if(ivideo->currentvbflags & CRT2_TV) {
+		if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+			ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
+			ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
+			ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
+			ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
+			ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
+			ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
+			ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
+		} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+			if(ivideo->chronteltype == 1) {
+				ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
+				ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
+				ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
+				ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
+			}
+		}
+	}
+
+	if(ivideo->tvxpos) {
+		sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
+	}
+	if(ivideo->tvypos) {
+		sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
+	}
+
+	/* Eventually sync engines */
+	sisfb_check_engine_and_sync(ivideo);
+
+	/* (Re-)Initialize chip engines */
+	if(ivideo->accel) {
+		sisfb_engine_init(ivideo);
+	} else {
+		ivideo->engineok = 0;
+	}
+}
+
+static int
+sisfb_reset_mode(struct sis_video_info *ivideo)
+{
+	if(sisfb_set_mode(ivideo, 0))
+		return 1;
+
+	sisfb_set_pitch(ivideo);
+	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
+
+	return 0;
+}
+
+static void
+sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
+{
+	int mycrt1off;
+
+	switch(sisfb_command->sisfb_cmd) {
+	case SISFB_CMD_GETVBFLAGS:
+		if(!ivideo->modechanged) {
+			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+		} else {
+			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+			sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
+			sisfb_command->sisfb_result[2] = ivideo->vbflags2;
+		}
+		break;
+	case SISFB_CMD_SWITCHCRT1:
+		/* arg[0]: 0 = off, 1 = on, 99 = query */
+		if(!ivideo->modechanged) {
+			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+		} else if(sisfb_command->sisfb_arg[0] == 99) {
+			/* Query */
+			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
+			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+		} else if(ivideo->sisfblocked) {
+			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
+		} else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
+					(sisfb_command->sisfb_arg[0] == 0)) {
+			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
+		} else {
+			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+			mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
+			if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
+			    ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
+				ivideo->sisfb_crt1off = mycrt1off;
+				if(sisfb_reset_mode(ivideo)) {
+					sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
+				}
+			}
+			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
+		}
+		break;
+	/* more to come */
+	default:
+		sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
+		printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
+			sisfb_command->sisfb_cmd);
+	}
+}
+
+#ifndef MODULE
+static int __init sisfb_setup(char *options)
+{
+	char *this_opt;
+
+	sisfb_setdefaultparms();
+
+	if(!options || !(*options))
+		return 0;
+
+	while((this_opt = strsep(&options, ",")) != NULL) {
+
+		if(!(*this_opt)) continue;
+
+		if(!strnicmp(this_opt, "off", 3)) {
+			sisfb_off = 1;
+		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
+			/* Need to check crt2 type first for fstn/dstn */
+			sisfb_search_crt2type(this_opt + 14);
+		} else if(!strnicmp(this_opt, "tvmode:",7)) {
+			sisfb_search_tvstd(this_opt + 7);
+		} else if(!strnicmp(this_opt, "tvstandard:",11)) {
+			sisfb_search_tvstd(this_opt + 11);
+		} else if(!strnicmp(this_opt, "mode:", 5)) {
+			sisfb_search_mode(this_opt + 5, false);
+		} else if(!strnicmp(this_opt, "vesa:", 5)) {
+			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
+		} else if(!strnicmp(this_opt, "rate:", 5)) {
+			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
+		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
+			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
+		} else if(!strnicmp(this_opt, "mem:",4)) {
+			sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
+		} else if(!strnicmp(this_opt, "pdc:", 4)) {
+			sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
+		} else if(!strnicmp(this_opt, "pdc1:", 5)) {
+			sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
+		} else if(!strnicmp(this_opt, "noaccel", 7)) {
+			sisfb_accel = 0;
+		} else if(!strnicmp(this_opt, "accel", 5)) {
+			sisfb_accel = -1;
+		} else if(!strnicmp(this_opt, "noypan", 6)) {
+			sisfb_ypan = 0;
+		} else if(!strnicmp(this_opt, "ypan", 4)) {
+			sisfb_ypan = -1;
+		} else if(!strnicmp(this_opt, "nomax", 5)) {
+			sisfb_max = 0;
+		} else if(!strnicmp(this_opt, "max", 3)) {
+			sisfb_max = -1;
+		} else if(!strnicmp(this_opt, "userom:", 7)) {
+			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
+		} else if(!strnicmp(this_opt, "useoem:", 7)) {
+			sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
+		} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
+			sisfb_nocrt2rate = 1;
+		} else if(!strnicmp(this_opt, "scalelcd:", 9)) {
+			unsigned long temp = 2;
+			temp = simple_strtoul(this_opt + 9, NULL, 0);
+			if((temp == 0) || (temp == 1)) {
+			   sisfb_scalelcd = temp ^ 1;
+			}
+		} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
+			int temp = 0;
+			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+			if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvxposoffset = temp;
+			}
+		} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
+			int temp = 0;
+			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+			if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvyposoffset = temp;
+			}
+		} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
+			sisfb_search_specialtiming(this_opt + 14);
+		} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
+			int temp = 4;
+			temp = simple_strtoul(this_opt + 7, NULL, 0);
+			if((temp >= 0) && (temp <= 3)) {
+			   sisfb_lvdshl = temp;
+			}
+		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
+			sisfb_search_mode(this_opt, true);
+#if !defined(__i386__) && !defined(__x86_64__)
+		} else if(!strnicmp(this_opt, "resetcard", 9)) {
+			sisfb_resetcard = 1;
+	        } else if(!strnicmp(this_opt, "videoram:", 9)) {
+			sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
+#endif
+		} else {
+			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
+		}
+
+	}
+
+	return 0;
+}
+#endif
+
+static int sisfb_check_rom(void __iomem *rom_base,
+			   struct sis_video_info *ivideo)
+{
+	void __iomem *rom;
+	int romptr;
+
+	if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
+		return 0;
+
+	romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	if(romptr > (0x10000 - 8))
+		return 0;
+
+	rom = rom_base + romptr;
+
+	if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
+	   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
+		return 0;
+
+	if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
+		return 0;
+
+	if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
+		return 0;
+
+	return 1;
+}
+
+static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	void __iomem *rom_base;
+	unsigned char *myrombase = NULL;
+	size_t romsize;
+
+	/* First, try the official pci ROM functions (except
+	 * on integrated chipsets which have no ROM).
+	 */
+
+	if(!ivideo->nbridge) {
+
+		if((rom_base = pci_map_rom(pdev, &romsize))) {
+
+			if(sisfb_check_rom(rom_base, ivideo)) {
+
+				if((myrombase = vmalloc(65536))) {
+					memcpy_fromio(myrombase, rom_base,
+							(romsize > 65536) ? 65536 : romsize);
+				}
+			}
+			pci_unmap_rom(pdev, rom_base);
+		}
+	}
+
+	if(myrombase) return myrombase;
+
+	/* Otherwise do it the conventional way. */
+
+#if defined(__i386__) || defined(__x86_64__)
+	{
+		u32 temp;
+
+		for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+
+			rom_base = ioremap(temp, 65536);
+			if (!rom_base)
+				continue;
+
+			if (!sisfb_check_rom(rom_base, ivideo)) {
+				iounmap(rom_base);
+				continue;
+			}
+
+			if ((myrombase = vmalloc(65536)))
+				memcpy_fromio(myrombase, rom_base, 65536);
+
+			iounmap(rom_base);
+			break;
+
+		}
+
+	}
+#endif
+
+	return myrombase;
+}
+
+static void sisfb_post_map_vram(struct sis_video_info *ivideo,
+				unsigned int *mapsize, unsigned int min)
+{
+	if (*mapsize < (min << 20))
+		return;
+
+	ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
+
+	if(!ivideo->video_vbase) {
+		printk(KERN_ERR
+			"sisfb: Unable to map maximum video RAM for size detection\n");
+		(*mapsize) >>= 1;
+		while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
+			(*mapsize) >>= 1;
+			if((*mapsize) < (min << 20))
+				break;
+		}
+		if(ivideo->video_vbase) {
+			printk(KERN_ERR
+				"sisfb: Video RAM size detection limited to %dMB\n",
+				(int)((*mapsize) >> 20));
+		}
+	}
+}
+
+#ifdef CONFIG_FB_SIS_300
+static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
+{
+	void __iomem *FBAddress = ivideo->video_vbase;
+	unsigned short temp;
+	unsigned char reg;
+	int i, j;
+
+	SiS_SetRegAND(SISSR, 0x15, 0xFB);
+	SiS_SetRegOR(SISSR, 0x15, 0x04);
+	SiS_SetReg(SISSR, 0x13, 0x00);
+	SiS_SetReg(SISSR, 0x14, 0xBF);
+
+	for(i = 0; i < 2; i++) {
+		temp = 0x1234;
+		for(j = 0; j < 4; j++) {
+			writew(temp, FBAddress);
+			if(readw(FBAddress) == temp)
+				break;
+			SiS_SetRegOR(SISSR, 0x3c, 0x01);
+			reg = SiS_GetReg(SISSR, 0x05);
+			reg = SiS_GetReg(SISSR, 0x05);
+			SiS_SetRegAND(SISSR, 0x3c, 0xfe);
+			reg = SiS_GetReg(SISSR, 0x05);
+			reg = SiS_GetReg(SISSR, 0x05);
+			temp++;
+		}
+	}
+
+	writel(0x01234567L, FBAddress);
+	writel(0x456789ABL, (FBAddress + 4));
+	writel(0x89ABCDEFL, (FBAddress + 8));
+	writel(0xCDEF0123L, (FBAddress + 12));
+
+	reg = SiS_GetReg(SISSR, 0x3b);
+	if(reg & 0x01) {
+		if(readl((FBAddress + 12)) == 0xCDEF0123L)
+			return 4;	/* Channel A 128bit */
+	}
+
+	if(readl((FBAddress + 4)) == 0x456789ABL)
+		return 2;		/* Channel B 64bit */
+
+	return 1;			/* 32bit */
+}
+
+static const unsigned short SiS_DRAMType[17][5] = {
+	{0x0C,0x0A,0x02,0x40,0x39},
+	{0x0D,0x0A,0x01,0x40,0x48},
+	{0x0C,0x09,0x02,0x20,0x35},
+	{0x0D,0x09,0x01,0x20,0x44},
+	{0x0C,0x08,0x02,0x10,0x31},
+	{0x0D,0x08,0x01,0x10,0x40},
+	{0x0C,0x0A,0x01,0x20,0x34},
+	{0x0C,0x09,0x01,0x08,0x32},
+	{0x0B,0x08,0x02,0x08,0x21},
+	{0x0C,0x08,0x01,0x08,0x30},
+	{0x0A,0x08,0x02,0x04,0x11},
+	{0x0B,0x0A,0x01,0x10,0x28},
+	{0x09,0x08,0x02,0x02,0x01},
+	{0x0B,0x09,0x01,0x08,0x24},
+	{0x0B,0x08,0x01,0x04,0x20},
+	{0x0A,0x08,0x01,0x02,0x10},
+	{0x09,0x08,0x01,0x01,0x00}
+};
+
+static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
+				 int buswidth, int PseudoRankCapacity,
+				 int PseudoAdrPinCount, unsigned int mapsize)
+{
+	void __iomem *FBAddr = ivideo->video_vbase;
+	unsigned short sr14;
+	unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
+	unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
+
+	 for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
+
+		RankCapacity = buswidth * SiS_DRAMType[k][3];
+
+		if(RankCapacity != PseudoRankCapacity)
+			continue;
+
+		if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
+			continue;
+
+		BankNumHigh = RankCapacity * 16 * iteration - 1;
+		if(iteration == 3) {             /* Rank No */
+			BankNumMid  = RankCapacity * 16 - 1;
+		} else {
+			BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
+		}
+
+		PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
+		PhysicalAdrHigh = BankNumHigh;
+		PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
+		PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
+
+		SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
+		SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
+		sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
+		if(buswidth == 4)      sr14 |= 0x80;
+		else if(buswidth == 2) sr14 |= 0x40;
+		SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
+		SiS_SetReg(SISSR, 0x14, sr14);
+
+		BankNumHigh <<= 16;
+		BankNumMid <<= 16;
+
+		if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
+		   (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
+		   (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
+		   (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
+			continue;
+
+		/* Write data */
+		writew(((unsigned short)PhysicalAdrHigh),
+				(FBAddr + BankNumHigh + PhysicalAdrHigh));
+		writew(((unsigned short)BankNumMid),
+				(FBAddr + BankNumMid  + PhysicalAdrHigh));
+		writew(((unsigned short)PhysicalAdrHalfPage),
+				(FBAddr + BankNumHigh + PhysicalAdrHalfPage));
+		writew(((unsigned short)PhysicalAdrOtherPage),
+				(FBAddr + BankNumHigh + PhysicalAdrOtherPage));
+
+		/* Read data */
+		if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
+{
+	struct	sis_video_info *ivideo = pci_get_drvdata(pdev);
+	int	i, j, buswidth;
+	int	PseudoRankCapacity, PseudoAdrPinCount;
+
+	buswidth = sisfb_post_300_buswidth(ivideo);
+
+	for(i = 6; i >= 0; i--) {
+		PseudoRankCapacity = 1 << i;
+		for(j = 4; j >= 1; j--) {
+			PseudoAdrPinCount = 15 - j;
+			if((PseudoRankCapacity * j) <= 64) {
+				if(sisfb_post_300_rwtest(ivideo,
+						j,
+						buswidth,
+						PseudoRankCapacity,
+						PseudoAdrPinCount,
+						mapsize))
+					return;
+			}
+		}
+	}
+}
+
+static void sisfb_post_sis300(struct pci_dev *pdev)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
+	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
+	u16 index, rindex, memtype = 0;
+	unsigned int mapsize;
+
+	if(!ivideo->SiS_Pr.UseROM)
+		bios = NULL;
+
+	SiS_SetReg(SISSR, 0x05, 0x86);
+
+	if(bios) {
+		if(bios[0x52] & 0x80) {
+			memtype = bios[0x52];
+		} else {
+			memtype = SiS_GetReg(SISSR, 0x3a);
+		}
+		memtype &= 0x07;
+	}
+
+	v3 = 0x80; v6 = 0x80;
+	if(ivideo->revision_id <= 0x13) {
+		v1 = 0x44; v2 = 0x42;
+		v4 = 0x44; v5 = 0x42;
+	} else {
+		v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
+		v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
+		if(bios) {
+			index = memtype * 5;
+			rindex = index + 0x54;
+			v1 = bios[rindex++];
+			v2 = bios[rindex++];
+			v3 = bios[rindex++];
+			rindex = index + 0x7c;
+			v4 = bios[rindex++];
+			v5 = bios[rindex++];
+			v6 = bios[rindex++];
+		}
+	}
+	SiS_SetReg(SISSR, 0x28, v1);
+	SiS_SetReg(SISSR, 0x29, v2);
+	SiS_SetReg(SISSR, 0x2a, v3);
+	SiS_SetReg(SISSR, 0x2e, v4);
+	SiS_SetReg(SISSR, 0x2f, v5);
+	SiS_SetReg(SISSR, 0x30, v6);
+
+	v1 = 0x10;
+	if(bios)
+		v1 = bios[0xa4];
+	SiS_SetReg(SISSR, 0x07, v1);       /* DAC speed */
+
+	SiS_SetReg(SISSR, 0x11, 0x0f);     /* DDC, power save */
+
+	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
+	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
+	if(bios) {
+		memtype += 0xa5;
+		v1 = bios[memtype];
+		v2 = bios[memtype + 8];
+		v3 = bios[memtype + 16];
+		v4 = bios[memtype + 24];
+		v5 = bios[memtype + 32];
+		v6 = bios[memtype + 40];
+		v7 = bios[memtype + 48];
+		v8 = bios[memtype + 56];
+	}
+	if(ivideo->revision_id >= 0x80)
+		v3 &= 0xfd;
+	SiS_SetReg(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+	SiS_SetReg(SISSR, 0x16, v2);
+	SiS_SetReg(SISSR, 0x17, v3);
+	SiS_SetReg(SISSR, 0x18, v4);
+	SiS_SetReg(SISSR, 0x19, v5);
+	SiS_SetReg(SISSR, 0x1a, v6);
+	SiS_SetReg(SISSR, 0x1b, v7);
+	SiS_SetReg(SISSR, 0x1c, v8);	   /* ---- */
+	SiS_SetRegAND(SISSR, 0x15, 0xfb);
+	SiS_SetRegOR(SISSR, 0x15, 0x04);
+	if(bios) {
+		if(bios[0x53] & 0x02) {
+			SiS_SetRegOR(SISSR, 0x19, 0x20);
+		}
+	}
+	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
+	if(ivideo->revision_id >= 0x80)
+		v1 |= 0x01;
+	SiS_SetReg(SISSR, 0x1f, v1);
+	SiS_SetReg(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
+	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
+	if(bios) {
+		v1 = bios[0xe8];
+		v2 = bios[0xe9];
+		v3 = bios[0xea];
+	}
+	SiS_SetReg(SISSR, 0x23, v1);
+	SiS_SetReg(SISSR, 0x24, v2);
+	SiS_SetReg(SISSR, 0x25, v3);
+	SiS_SetReg(SISSR, 0x21, 0x84);
+	SiS_SetReg(SISSR, 0x22, 0x00);
+	SiS_SetReg(SISCR, 0x37, 0x00);
+	SiS_SetRegOR(SISPART1, 0x24, 0x01);   /* unlock crt2 */
+	SiS_SetReg(SISPART1, 0x00, 0x00);
+	v1 = 0x40; v2 = 0x11;
+	if(bios) {
+		v1 = bios[0xec];
+		v2 = bios[0xeb];
+	}
+	SiS_SetReg(SISPART1, 0x02, v1);
+
+	if(ivideo->revision_id >= 0x80)
+		v2 &= ~0x01;
+
+	reg = SiS_GetReg(SISPART4, 0x00);
+	if((reg == 1) || (reg == 2)) {
+		SiS_SetReg(SISCR, 0x37, 0x02);
+		SiS_SetReg(SISPART2, 0x00, 0x1c);
+		v4 = 0x00; v5 = 0x00; v6 = 0x10;
+		if(ivideo->SiS_Pr.UseROM) {
+			v4 = bios[0xf5];
+			v5 = bios[0xf6];
+			v6 = bios[0xf7];
+		}
+		SiS_SetReg(SISPART4, 0x0d, v4);
+		SiS_SetReg(SISPART4, 0x0e, v5);
+		SiS_SetReg(SISPART4, 0x10, v6);
+		SiS_SetReg(SISPART4, 0x0f, 0x3f);
+		reg = SiS_GetReg(SISPART4, 0x01);
+		if(reg >= 0xb0) {
+			reg = SiS_GetReg(SISPART4, 0x23);
+			reg &= 0x20;
+			reg <<= 1;
+			SiS_SetReg(SISPART4, 0x23, reg);
+		}
+	} else {
+		v2 &= ~0x10;
+	}
+	SiS_SetReg(SISSR, 0x32, v2);
+
+	SiS_SetRegAND(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
+
+	reg = SiS_GetReg(SISSR, 0x16);
+	reg &= 0xc3;
+	SiS_SetReg(SISCR, 0x35, reg);
+	SiS_SetReg(SISCR, 0x83, 0x00);
+#if !defined(__i386__) && !defined(__x86_64__)
+	if(sisfb_videoram) {
+		SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
+		reg = ((sisfb_videoram >> 10) - 1) | 0x40;
+		SiS_SetReg(SISSR, 0x14, reg);
+	} else {
+#endif
+		/* Need to map max FB size for finding out about RAM size */
+		mapsize = ivideo->video_size;
+		sisfb_post_map_vram(ivideo, &mapsize, 4);
+
+		if(ivideo->video_vbase) {
+			sisfb_post_300_ramsize(pdev, mapsize);
+			iounmap(ivideo->video_vbase);
+		} else {
+			printk(KERN_DEBUG
+				"sisfb: Failed to map memory for size detection, assuming 8MB\n");
+			SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
+			SiS_SetReg(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
+		}
+#if !defined(__i386__) && !defined(__x86_64__)
+	}
+#endif
+	if(bios) {
+		v1 = bios[0xe6];
+		v2 = bios[0xe7];
+	} else {
+		reg = SiS_GetReg(SISSR, 0x3a);
+		if((reg & 0x30) == 0x30) {
+			v1 = 0x04; /* PCI */
+			v2 = 0x92;
+		} else {
+			v1 = 0x14; /* AGP */
+			v2 = 0xb2;
+		}
+	}
+	SiS_SetReg(SISSR, 0x21, v1);
+	SiS_SetReg(SISSR, 0x22, v2);
+
+	/* Sense CRT1 */
+	sisfb_sense_crt1(ivideo);
+
+	/* Set default mode, don't clear screen */
+	ivideo->SiS_Pr.SiS_UseOEM = false;
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
+	ivideo->curFSTN = ivideo->curDSTN = 0;
+	ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+	SiS_SetReg(SISSR, 0x05, 0x86);
+
+	/* Display off */
+	SiS_SetRegOR(SISSR, 0x01, 0x20);
+
+	/* Save mode number in CR34 */
+	SiS_SetReg(SISCR, 0x34, 0x2e);
+
+	/* Let everyone know what the current mode is */
+	ivideo->modeprechange = 0x2e;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+#if 0
+static void sisfb_post_sis315330(struct pci_dev *pdev)
+{
+	/* TODO */
+}
+#endif
+
+static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
+{
+	return ivideo->chip_real_id == XGI_21;
+}
+
+static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
+{
+	unsigned int i;
+	u8 reg;
+
+	for(i = 0; i <= (delay * 10 * 36); i++) {
+		reg = SiS_GetReg(SISSR, 0x05);
+		reg++;
+	}
+}
+
+static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
+				  struct pci_dev *mypdev,
+				  unsigned short pcivendor)
+{
+	struct pci_dev *pdev = NULL;
+	unsigned short temp;
+	int ret = 0;
+
+	while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
+		temp = pdev->vendor;
+		if(temp == pcivendor) {
+			ret = 1;
+			pci_dev_put(pdev);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
+				 unsigned int enda, unsigned int mapsize)
+{
+	unsigned int pos;
+	int i;
+
+	writel(0, ivideo->video_vbase);
+
+	for(i = starta; i <= enda; i++) {
+		pos = 1 << i;
+		if(pos < mapsize)
+			writel(pos, ivideo->video_vbase + pos);
+	}
+
+	sisfb_post_xgi_delay(ivideo, 150);
+
+	if(readl(ivideo->video_vbase) != 0)
+		return 0;
+
+	for(i = starta; i <= enda; i++) {
+		pos = 1 << i;
+		if(pos < mapsize) {
+			if(readl(ivideo->video_vbase + pos) != pos)
+				return 0;
+		} else
+			return 0;
+	}
+
+	return 1;
+}
+
+static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
+{
+	unsigned int buswidth, ranksize, channelab, mapsize;
+	int i, j, k, l, status;
+	u8 reg, sr14;
+	static const u8 dramsr13[12 * 5] = {
+		0x02, 0x0e, 0x0b, 0x80, 0x5d,
+		0x02, 0x0e, 0x0a, 0x40, 0x59,
+		0x02, 0x0d, 0x0b, 0x40, 0x4d,
+		0x02, 0x0e, 0x09, 0x20, 0x55,
+		0x02, 0x0d, 0x0a, 0x20, 0x49,
+		0x02, 0x0c, 0x0b, 0x20, 0x3d,
+		0x02, 0x0e, 0x08, 0x10, 0x51,
+		0x02, 0x0d, 0x09, 0x10, 0x45,
+		0x02, 0x0c, 0x0a, 0x10, 0x39,
+		0x02, 0x0d, 0x08, 0x08, 0x41,
+		0x02, 0x0c, 0x09, 0x08, 0x35,
+		0x02, 0x0c, 0x08, 0x04, 0x31
+	};
+	static const u8 dramsr13_4[4 * 5] = {
+		0x02, 0x0d, 0x09, 0x40, 0x45,
+		0x02, 0x0c, 0x09, 0x20, 0x35,
+		0x02, 0x0c, 0x08, 0x10, 0x31,
+		0x02, 0x0b, 0x08, 0x08, 0x21
+	};
+
+	/* Enable linear mode, disable 0xa0000 address decoding */
+	/* We disable a0000 address decoding, because
+	 * - if running on x86, if the card is disabled, it means
+	 *   that another card is in the system. We don't want
+	 *   to interphere with that primary card's textmode.
+	 * - if running on non-x86, there usually is no VGA window
+	 *   at a0000.
+	 */
+	SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
+
+	/* Need to map max FB size for finding out about RAM size */
+	mapsize = ivideo->video_size;
+	sisfb_post_map_vram(ivideo, &mapsize, 32);
+
+	if(!ivideo->video_vbase) {
+		printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
+		SiS_SetReg(SISSR, 0x13, 0x35);
+		SiS_SetReg(SISSR, 0x14, 0x41);
+		/* TODO */
+		return -ENOMEM;
+	}
+
+	/* Non-interleaving */
+	SiS_SetReg(SISSR, 0x15, 0x00);
+	/* No tiling */
+	SiS_SetReg(SISSR, 0x1c, 0x00);
+
+	if(ivideo->chip == XGI_20) {
+
+		channelab = 1;
+		reg = SiS_GetReg(SISCR, 0x97);
+		if(!(reg & 0x01)) {	/* Single 32/16 */
+			buswidth = 32;
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x52);
+			sisfb_post_xgi_delay(ivideo, 1);
+			sr14 = 0x02;
+			if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+				goto bail_out;
+
+			SiS_SetReg(SISSR, 0x13, 0x31);
+			SiS_SetReg(SISSR, 0x14, 0x42);
+			sisfb_post_xgi_delay(ivideo, 1);
+			if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
+				goto bail_out;
+
+			buswidth = 16;
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x41);
+			sisfb_post_xgi_delay(ivideo, 1);
+			sr14 = 0x01;
+			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+				goto bail_out;
+			else
+				SiS_SetReg(SISSR, 0x13, 0x31);
+		} else {		/* Dual 16/8 */
+			buswidth = 16;
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x41);
+			sisfb_post_xgi_delay(ivideo, 1);
+			sr14 = 0x01;
+			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+				goto bail_out;
+
+			SiS_SetReg(SISSR, 0x13, 0x31);
+			SiS_SetReg(SISSR, 0x14, 0x31);
+			sisfb_post_xgi_delay(ivideo, 1);
+			if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
+				goto bail_out;
+
+			buswidth = 8;
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x30);
+			sisfb_post_xgi_delay(ivideo, 1);
+			sr14 = 0x00;
+			if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
+				goto bail_out;
+			else
+				SiS_SetReg(SISSR, 0x13, 0x31);
+		}
+
+	} else {	/* XGI_40 */
+
+		reg = SiS_GetReg(SISCR, 0x97);
+		if(!(reg & 0x10)) {
+			reg = SiS_GetReg(SISSR, 0x39);
+			reg >>= 1;
+		}
+
+		if(reg & 0x01) {	/* DDRII */
+			buswidth = 32;
+			if(ivideo->revision_id == 2) {
+				channelab = 2;
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x44);
+				sr14 = 0x04;
+				sisfb_post_xgi_delay(ivideo, 1);
+				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+					goto bail_out;
+
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x34);
+				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+					goto bail_out;
+
+				channelab = 1;
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x40);
+				sr14 = 0x00;
+				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+					goto bail_out;
+
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x30);
+			} else {
+				channelab = 3;
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x4c);
+				sr14 = 0x0c;
+				sisfb_post_xgi_delay(ivideo, 1);
+				if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
+					goto bail_out;
+
+				channelab = 2;
+				SiS_SetReg(SISSR, 0x14, 0x48);
+				sisfb_post_xgi_delay(ivideo, 1);
+				sr14 = 0x08;
+				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+					goto bail_out;
+
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x3c);
+				sr14 = 0x0c;
+
+				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
+					channelab = 3;
+				} else {
+					channelab = 2;
+					SiS_SetReg(SISSR, 0x14, 0x38);
+					sr14 = 0x08;
+				}
+			}
+			sisfb_post_xgi_delay(ivideo, 1);
+
+		} else {	/* DDR */
+
+			buswidth = 64;
+			if(ivideo->revision_id == 2) {
+				channelab = 1;
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x52);
+				sisfb_post_xgi_delay(ivideo, 1);
+				sr14 = 0x02;
+				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+					goto bail_out;
+
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x42);
+			} else {
+				channelab = 2;
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x5a);
+				sisfb_post_xgi_delay(ivideo, 1);
+				sr14 = 0x0a;
+				if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
+					goto bail_out;
+
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x4a);
+			}
+			sisfb_post_xgi_delay(ivideo, 1);
+
+		}
+	}
+
+bail_out:
+	SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
+	sisfb_post_xgi_delay(ivideo, 1);
+
+	j = (ivideo->chip == XGI_20) ? 5 : 9;
+	k = (ivideo->chip == XGI_20) ? 12 : 4;
+	status = -EIO;
+
+	for(i = 0; i < k; i++) {
+
+		reg = (ivideo->chip == XGI_20) ?
+				dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
+		SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
+		sisfb_post_xgi_delay(ivideo, 50);
+
+		ranksize = (ivideo->chip == XGI_20) ?
+				dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
+
+		reg = SiS_GetReg(SISSR, 0x13);
+		if(reg & 0x80) ranksize <<= 1;
+
+		if(ivideo->chip == XGI_20) {
+			if(buswidth == 16)      ranksize <<= 1;
+			else if(buswidth == 32) ranksize <<= 2;
+		} else {
+			if(buswidth == 64)      ranksize <<= 1;
+		}
+
+		reg = 0;
+		l = channelab;
+		if(l == 3) l = 4;
+		if((ranksize * l) <= 256) {
+			while((ranksize >>= 1)) reg += 0x10;
+		}
+
+		if(!reg) continue;
+
+		SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
+		sisfb_post_xgi_delay(ivideo, 1);
+
+		if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
+			status = 0;
+			break;
+		}
+	}
+
+	iounmap(ivideo->video_vbase);
+
+	return status;
+}
+
+static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
+{
+	u8 v1, v2, v3;
+	int index;
+	static const u8 cs90[8 * 3] = {
+		0x16, 0x01, 0x01,
+		0x3e, 0x03, 0x01,
+		0x7c, 0x08, 0x01,
+		0x79, 0x06, 0x01,
+		0x29, 0x01, 0x81,
+		0x5c, 0x23, 0x01,
+		0x5c, 0x23, 0x01,
+		0x5c, 0x23, 0x01
+	};
+	static const u8 csb8[8 * 3] = {
+		0x5c, 0x23, 0x01,
+		0x29, 0x01, 0x01,
+		0x7c, 0x08, 0x01,
+		0x79, 0x06, 0x01,
+		0x29, 0x01, 0x81,
+		0x5c, 0x23, 0x01,
+		0x5c, 0x23, 0x01,
+		0x5c, 0x23, 0x01
+	};
+
+	regb = 0;  /* ! */
+
+	index = regb * 3;
+	v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
+	if(ivideo->haveXGIROM) {
+		v1 = ivideo->bios_abase[0x90 + index];
+		v2 = ivideo->bios_abase[0x90 + index + 1];
+		v3 = ivideo->bios_abase[0x90 + index + 2];
+	}
+	SiS_SetReg(SISSR, 0x28, v1);
+	SiS_SetReg(SISSR, 0x29, v2);
+	SiS_SetReg(SISSR, 0x2a, v3);
+	sisfb_post_xgi_delay(ivideo, 0x43);
+	sisfb_post_xgi_delay(ivideo, 0x43);
+	sisfb_post_xgi_delay(ivideo, 0x43);
+	index = regb * 3;
+	v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
+	if(ivideo->haveXGIROM) {
+		v1 = ivideo->bios_abase[0xb8 + index];
+		v2 = ivideo->bios_abase[0xb8 + index + 1];
+		v3 = ivideo->bios_abase[0xb8 + index + 2];
+	}
+	SiS_SetReg(SISSR, 0x2e, v1);
+	SiS_SetReg(SISSR, 0x2f, v2);
+	SiS_SetReg(SISSR, 0x30, v3);
+	sisfb_post_xgi_delay(ivideo, 0x43);
+	sisfb_post_xgi_delay(ivideo, 0x43);
+	sisfb_post_xgi_delay(ivideo, 0x43);
+}
+
+static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
+					    u8 regb)
+{
+	unsigned char *bios = ivideo->bios_abase;
+	u8 v1;
+
+	SiS_SetReg(SISSR, 0x28, 0x64);
+	SiS_SetReg(SISSR, 0x29, 0x63);
+	sisfb_post_xgi_delay(ivideo, 15);
+	SiS_SetReg(SISSR, 0x18, 0x00);
+	SiS_SetReg(SISSR, 0x19, 0x20);
+	SiS_SetReg(SISSR, 0x16, 0x00);
+	SiS_SetReg(SISSR, 0x16, 0x80);
+	SiS_SetReg(SISSR, 0x18, 0xc5);
+	SiS_SetReg(SISSR, 0x19, 0x23);
+	SiS_SetReg(SISSR, 0x16, 0x00);
+	SiS_SetReg(SISSR, 0x16, 0x80);
+	sisfb_post_xgi_delay(ivideo, 1);
+	SiS_SetReg(SISCR, 0x97, 0x11);
+	sisfb_post_xgi_setclocks(ivideo, regb);
+	sisfb_post_xgi_delay(ivideo, 0x46);
+	SiS_SetReg(SISSR, 0x18, 0xc5);
+	SiS_SetReg(SISSR, 0x19, 0x23);
+	SiS_SetReg(SISSR, 0x16, 0x00);
+	SiS_SetReg(SISSR, 0x16, 0x80);
+	sisfb_post_xgi_delay(ivideo, 1);
+	SiS_SetReg(SISSR, 0x1b, 0x04);
+	sisfb_post_xgi_delay(ivideo, 1);
+	SiS_SetReg(SISSR, 0x1b, 0x00);
+	sisfb_post_xgi_delay(ivideo, 1);
+	v1 = 0x31;
+	if (ivideo->haveXGIROM) {
+		v1 = bios[0xf0];
+	}
+	SiS_SetReg(SISSR, 0x18, v1);
+	SiS_SetReg(SISSR, 0x19, 0x06);
+	SiS_SetReg(SISSR, 0x16, 0x04);
+	SiS_SetReg(SISSR, 0x16, 0x84);
+	sisfb_post_xgi_delay(ivideo, 1);
+}
+
+static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
+{
+	sisfb_post_xgi_setclocks(ivideo, 1);
+
+	SiS_SetReg(SISCR, 0x97, 0x11);
+	sisfb_post_xgi_delay(ivideo, 0x46);
+
+	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS2 */
+	SiS_SetReg(SISSR, 0x19, 0x80);
+	SiS_SetReg(SISSR, 0x16, 0x05);
+	SiS_SetReg(SISSR, 0x16, 0x85);
+
+	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS3 */
+	SiS_SetReg(SISSR, 0x19, 0xc0);
+	SiS_SetReg(SISSR, 0x16, 0x05);
+	SiS_SetReg(SISSR, 0x16, 0x85);
+
+	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS1 */
+	SiS_SetReg(SISSR, 0x19, 0x40);
+	SiS_SetReg(SISSR, 0x16, 0x05);
+	SiS_SetReg(SISSR, 0x16, 0x85);
+
+	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
+	SiS_SetReg(SISSR, 0x19, 0x02);
+	SiS_SetReg(SISSR, 0x16, 0x05);
+	SiS_SetReg(SISSR, 0x16, 0x85);
+	sisfb_post_xgi_delay(ivideo, 1);
+
+	SiS_SetReg(SISSR, 0x1b, 0x04);
+	sisfb_post_xgi_delay(ivideo, 1);
+
+	SiS_SetReg(SISSR, 0x1b, 0x00);
+	sisfb_post_xgi_delay(ivideo, 1);
+
+	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
+	SiS_SetReg(SISSR, 0x19, 0x00);
+	SiS_SetReg(SISSR, 0x16, 0x05);
+	SiS_SetReg(SISSR, 0x16, 0x85);
+	sisfb_post_xgi_delay(ivideo, 1);
+}
+
+static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
+{
+	unsigned char *bios = ivideo->bios_abase;
+	static const u8 cs158[8] = {
+		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs160[8] = {
+		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs168[8] = {
+		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	u8 reg;
+	u8 v1;
+	u8 v2;
+	u8 v3;
+
+	SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
+	SiS_SetReg(SISCR, 0x82, 0x77);
+	SiS_SetReg(SISCR, 0x86, 0x00);
+	reg = SiS_GetReg(SISCR, 0x86);
+	SiS_SetReg(SISCR, 0x86, 0x88);
+	reg = SiS_GetReg(SISCR, 0x86);
+	v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
+	if (ivideo->haveXGIROM) {
+		v1 = bios[regb + 0x168];
+		v2 = bios[regb + 0x160];
+		v3 = bios[regb + 0x158];
+	}
+	SiS_SetReg(SISCR, 0x86, v1);
+	SiS_SetReg(SISCR, 0x82, 0x77);
+	SiS_SetReg(SISCR, 0x85, 0x00);
+	reg = SiS_GetReg(SISCR, 0x85);
+	SiS_SetReg(SISCR, 0x85, 0x88);
+	reg = SiS_GetReg(SISCR, 0x85);
+	SiS_SetReg(SISCR, 0x85, v2);
+	SiS_SetReg(SISCR, 0x82, v3);
+	SiS_SetReg(SISCR, 0x98, 0x01);
+	SiS_SetReg(SISCR, 0x9a, 0x02);
+	if (sisfb_xgi_is21(ivideo))
+		sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
+	else
+		sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
+}
+
+static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
+{
+	unsigned char *bios = ivideo->bios_abase;
+	u8 ramtype;
+	u8 reg;
+	u8 v1;
+
+	ramtype = 0x00; v1 = 0x10;
+	if (ivideo->haveXGIROM) {
+		ramtype = bios[0x62];
+		v1 = bios[0x1d2];
+	}
+	if (!(ramtype & 0x80)) {
+		if (sisfb_xgi_is21(ivideo)) {
+			SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
+			SiS_SetRegOR(SISCR, 0x4a, 0x80);  /* GPIOH EN */
+			reg = SiS_GetReg(SISCR, 0x48);
+			SiS_SetRegOR(SISCR, 0xb4, 0x02);
+			ramtype = reg & 0x01;		  /* GPIOH */
+		} else if (ivideo->chip == XGI_20) {
+			SiS_SetReg(SISCR, 0x97, v1);
+			reg = SiS_GetReg(SISCR, 0x97);
+			if (reg & 0x10) {
+				ramtype = (reg & 0x01) << 1;
+			}
+		} else {
+			reg = SiS_GetReg(SISSR, 0x39);
+			ramtype = reg & 0x02;
+			if (!(ramtype)) {
+				reg = SiS_GetReg(SISSR, 0x3a);
+				ramtype = (reg >> 1) & 0x01;
+			}
+		}
+	}
+	ramtype &= 0x07;
+
+	return ramtype;
+}
+
+static int sisfb_post_xgi(struct pci_dev *pdev)
+{
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	unsigned char *bios = ivideo->bios_abase;
+	struct pci_dev *mypdev = NULL;
+	const u8 *ptr, *ptr2;
+	u8 v1, v2, v3, v4, v5, reg, ramtype;
+	u32 rega, regb, regd;
+	int i, j, k, index;
+	static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
+	static const u8 cs76[2] = { 0xa3, 0xfb };
+	static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
+	static const u8 cs158[8] = {
+		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs160[8] = {
+		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs168[8] = {
+		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs128[3 * 8] = {
+		0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs148[2 * 8] = {
+		0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs31a[8 * 4] = {
+		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs33a[8 * 4] = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs45a[8 * 2] = {
+		0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs170[7 * 8] = {
+		0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs1a8[3 * 8] = {
+		0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	static const u8 cs100[2 * 8] = {
+		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+
+	/* VGA enable */
+	reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
+	SiS_SetRegByte(SISVGAENABLE, reg);
+
+	/* Misc */
+	reg = SiS_GetRegByte(SISMISCR) | 0x01;
+	SiS_SetRegByte(SISMISCW, reg);
+
+	/* Unlock SR */
+	SiS_SetReg(SISSR, 0x05, 0x86);
+	reg = SiS_GetReg(SISSR, 0x05);
+	if(reg != 0xa1)
+		return 0;
+
+	/* Clear some regs */
+	for(i = 0; i < 0x22; i++) {
+		if(0x06 + i == 0x20) continue;
+		SiS_SetReg(SISSR, 0x06 + i, 0x00);
+	}
+	for(i = 0; i < 0x0b; i++) {
+		SiS_SetReg(SISSR, 0x31 + i, 0x00);
+	}
+	for(i = 0; i < 0x10; i++) {
+		SiS_SetReg(SISCR, 0x30 + i, 0x00);
+	}
+
+	ptr = cs78;
+	if(ivideo->haveXGIROM) {
+		ptr = (const u8 *)&bios[0x78];
+	}
+	for(i = 0; i < 3; i++) {
+		SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
+	}
+
+	ptr = cs76;
+	if(ivideo->haveXGIROM) {
+		ptr = (const u8 *)&bios[0x76];
+	}
+	for(i = 0; i < 2; i++) {
+		SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
+	}
+
+	v1 = 0x18; v2 = 0x00;
+	if(ivideo->haveXGIROM) {
+		v1 = bios[0x74];
+		v2 = bios[0x75];
+	}
+	SiS_SetReg(SISSR, 0x07, v1);
+	SiS_SetReg(SISSR, 0x11, 0x0f);
+	SiS_SetReg(SISSR, 0x1f, v2);
+	/* PCI linear mode, RelIO enabled, A0000 decoding disabled */
+	SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
+	SiS_SetReg(SISSR, 0x27, 0x74);
+
+	ptr = cs7b;
+	if(ivideo->haveXGIROM) {
+		ptr = (const u8 *)&bios[0x7b];
+	}
+	for(i = 0; i < 3; i++) {
+		SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
+	}
+
+	if(ivideo->chip == XGI_40) {
+		if(ivideo->revision_id == 2) {
+			SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
+		}
+		SiS_SetReg(SISCR, 0x7d, 0xfe);
+		SiS_SetReg(SISCR, 0x7e, 0x0f);
+	}
+	if(ivideo->revision_id == 0) {	/* 40 *and* 20? */
+		SiS_SetRegAND(SISCR, 0x58, 0xd7);
+		reg = SiS_GetReg(SISCR, 0xcb);
+		if(reg & 0x20) {
+			SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
+		}
+	}
+
+	reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
+	SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
+
+	if(ivideo->chip == XGI_20) {
+		SiS_SetReg(SISSR, 0x36, 0x70);
+	} else {
+		SiS_SetReg(SISVID, 0x00, 0x86);
+		SiS_SetReg(SISVID, 0x32, 0x00);
+		SiS_SetReg(SISVID, 0x30, 0x00);
+		SiS_SetReg(SISVID, 0x32, 0x01);
+		SiS_SetReg(SISVID, 0x30, 0x00);
+		SiS_SetRegAND(SISVID, 0x2f, 0xdf);
+		SiS_SetRegAND(SISCAP, 0x00, 0x3f);
+
+		SiS_SetReg(SISPART1, 0x2f, 0x01);
+		SiS_SetReg(SISPART1, 0x00, 0x00);
+		SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
+		SiS_SetReg(SISPART1, 0x2e, 0x08);
+		SiS_SetRegAND(SISPART1, 0x35, 0x7f);
+		SiS_SetRegAND(SISPART1, 0x50, 0xfe);
+
+		reg = SiS_GetReg(SISPART4, 0x00);
+		if(reg == 1 || reg == 2) {
+			SiS_SetReg(SISPART2, 0x00, 0x1c);
+			SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
+			SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
+			SiS_SetReg(SISPART4, 0x10, bios[0x81]);
+			SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
+
+			reg = SiS_GetReg(SISPART4, 0x01);
+			if((reg & 0xf0) >= 0xb0) {
+				reg = SiS_GetReg(SISPART4, 0x23);
+				if(reg & 0x20) reg |= 0x40;
+				SiS_SetReg(SISPART4, 0x23, reg);
+				reg = (reg & 0x20) ? 0x02 : 0x00;
+				SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
+			}
+		}
+
+		v1 = bios[0x77];
+
+		reg = SiS_GetReg(SISSR, 0x3b);
+		if(reg & 0x02) {
+			reg = SiS_GetReg(SISSR, 0x3a);
+			v2 = (reg & 0x30) >> 3;
+			if(!(v2 & 0x04)) v2 ^= 0x02;
+			reg = SiS_GetReg(SISSR, 0x39);
+			if(reg & 0x80) v2 |= 0x80;
+			v2 |= 0x01;
+
+			if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
+				pci_dev_put(mypdev);
+				if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
+					v2 &= 0xf9;
+				v2 |= 0x08;
+				v1 &= 0xfe;
+			} else {
+				mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
+				if(!mypdev)
+					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
+				if(!mypdev)
+					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
+				if(mypdev) {
+					pci_read_config_dword(mypdev, 0x94, &regd);
+					regd &= 0xfffffeff;
+					pci_write_config_dword(mypdev, 0x94, regd);
+					v1 &= 0xfe;
+					pci_dev_put(mypdev);
+				} else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
+					v1 &= 0xfe;
+				} else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
+					  sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
+					  sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
+					  sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
+					if((v2 & 0x06) == 4)
+						v2 ^= 0x06;
+					v2 |= 0x08;
+				}
+			}
+			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
+		}
+		SiS_SetReg(SISSR, 0x22, v1);
+
+		if(ivideo->revision_id == 2) {
+			v1 = SiS_GetReg(SISSR, 0x3b);
+			v2 = SiS_GetReg(SISSR, 0x3a);
+			regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
+			if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
+				SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
+
+			if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
+				/* TODO: set CR5f &0xf1 | 0x01 for version 6570
+				 * of nforce 2 ROM
+				 */
+				if(0)
+					SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
+				pci_dev_put(mypdev);
+			}
+		}
+
+		v1 = 0x30;
+		reg = SiS_GetReg(SISSR, 0x3b);
+		v2 = SiS_GetReg(SISCR, 0x5f);
+		if((!(reg & 0x02)) && (v2 & 0x0e))
+			v1 |= 0x08;
+		SiS_SetReg(SISSR, 0x27, v1);
+
+		if(bios[0x64] & 0x01) {
+			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
+		}
+
+		v1 = bios[0x4f7];
+		pci_read_config_dword(pdev, 0x50, &regd);
+		regd = (regd >> 20) & 0x0f;
+		if(regd == 1) {
+			v1 &= 0xfc;
+			SiS_SetRegOR(SISCR, 0x5f, 0x08);
+		}
+		SiS_SetReg(SISCR, 0x48, v1);
+
+		SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
+		SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
+		SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
+		SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
+		SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
+		SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
+		SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
+		SiS_SetReg(SISCR, 0x74, 0xd0);
+		SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
+		SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
+		SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
+		v1 = bios[0x501];
+		if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
+			v1 = 0xf0;
+			pci_dev_put(mypdev);
+		}
+		SiS_SetReg(SISCR, 0x77, v1);
+	}
+
+	/* RAM type:
+	 *
+	 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
+	 *
+	 * The code seems to written so that regb should equal ramtype,
+	 * however, so far it has been hardcoded to 0. Enable other values only
+	 * on XGI Z9, as it passes the POST, and add a warning for others.
+	 */
+	ramtype = sisfb_post_xgi_ramtype(ivideo);
+	if (!sisfb_xgi_is21(ivideo) && ramtype) {
+		dev_warn(&pdev->dev,
+			 "RAM type something else than expected: %d\n",
+			 ramtype);
+		regb = 0;
+	} else {
+		regb = ramtype;
+	}
+
+	v1 = 0xff;
+	if(ivideo->haveXGIROM) {
+		v1 = bios[0x140 + regb];
+	}
+	SiS_SetReg(SISCR, 0x6d, v1);
+
+	ptr = cs128;
+	if(ivideo->haveXGIROM) {
+		ptr = (const u8 *)&bios[0x128];
+	}
+	for(i = 0, j = 0; i < 3; i++, j += 8) {
+		SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
+	}
+
+	ptr  = cs31a;
+	ptr2 = cs33a;
+	if(ivideo->haveXGIROM) {
+		index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
+		ptr  = (const u8 *)&bios[index];
+		ptr2 = (const u8 *)&bios[index + 0x20];
+	}
+	for(i = 0; i < 2; i++) {
+		if(i == 0) {
+			regd = le32_to_cpu(((u32 *)ptr)[regb]);
+			rega = 0x6b;
+		} else {
+			regd = le32_to_cpu(((u32 *)ptr2)[regb]);
+			rega = 0x6e;
+		}
+		reg = 0x00;
+		for(j = 0; j < 16; j++) {
+			reg &= 0xf3;
+			if(regd & 0x01) reg |= 0x04;
+			if(regd & 0x02) reg |= 0x08;
+			regd >>= 2;
+			SiS_SetReg(SISCR, rega, reg);
+			reg = SiS_GetReg(SISCR, rega);
+			reg = SiS_GetReg(SISCR, rega);
+			reg += 0x10;
+		}
+	}
+
+	SiS_SetRegAND(SISCR, 0x6e, 0xfc);
+
+	ptr  = NULL;
+	if(ivideo->haveXGIROM) {
+		index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
+		ptr  = (const u8 *)&bios[index];
+	}
+	for(i = 0; i < 4; i++) {
+		SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
+		reg = 0x00;
+		for(j = 0; j < 2; j++) {
+			regd = 0;
+			if(ptr) {
+				regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
+				ptr += 4;
+			}
+			/* reg = 0x00; */
+			for(k = 0; k < 16; k++) {
+				reg &= 0xfc;
+				if(regd & 0x01) reg |= 0x01;
+				if(regd & 0x02) reg |= 0x02;
+				regd >>= 2;
+				SiS_SetReg(SISCR, 0x6f, reg);
+				reg = SiS_GetReg(SISCR, 0x6f);
+				reg = SiS_GetReg(SISCR, 0x6f);
+				reg += 0x08;
+			}
+		}
+	}
+
+	ptr  = cs148;
+	if(ivideo->haveXGIROM) {
+		ptr  = (const u8 *)&bios[0x148];
+	}
+	for(i = 0, j = 0; i < 2; i++, j += 8) {
+		SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
+	}
+
+	SiS_SetRegAND(SISCR, 0x89, 0x8f);
+
+	ptr  = cs45a;
+	if(ivideo->haveXGIROM) {
+		index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
+		ptr  = (const u8 *)&bios[index];
+	}
+	regd = le16_to_cpu(((const u16 *)ptr)[regb]);
+	reg = 0x80;
+	for(i = 0; i < 5; i++) {
+		reg &= 0xfc;
+		if(regd & 0x01) reg |= 0x01;
+		if(regd & 0x02) reg |= 0x02;
+		regd >>= 2;
+		SiS_SetReg(SISCR, 0x89, reg);
+		reg = SiS_GetReg(SISCR, 0x89);
+		reg = SiS_GetReg(SISCR, 0x89);
+		reg += 0x10;
+	}
+
+	v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
+	if(ivideo->haveXGIROM) {
+		v1 = bios[0x118 + regb];
+		v2 = bios[0xf8 + regb];
+		v3 = bios[0x120 + regb];
+		v4 = bios[0x1ca];
+	}
+	SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
+	SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
+	SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
+	SiS_SetReg(SISCR, 0x41, v2);
+
+	ptr  = cs170;
+	if(ivideo->haveXGIROM) {
+		ptr  = (const u8 *)&bios[0x170];
+	}
+	for(i = 0, j = 0; i < 7; i++, j += 8) {
+		SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
+	}
+
+	SiS_SetReg(SISCR, 0x59, v3);
+
+	ptr  = cs1a8;
+	if(ivideo->haveXGIROM) {
+		ptr  = (const u8 *)&bios[0x1a8];
+	}
+	for(i = 0, j = 0; i < 3; i++, j += 8) {
+		SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
+	}
+
+	ptr  = cs100;
+	if(ivideo->haveXGIROM) {
+		ptr  = (const u8 *)&bios[0x100];
+	}
+	for(i = 0, j = 0; i < 2; i++, j += 8) {
+		SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
+	}
+
+	SiS_SetReg(SISCR, 0xcf, v4);
+
+	SiS_SetReg(SISCR, 0x83, 0x09);
+	SiS_SetReg(SISCR, 0x87, 0x00);
+
+	if(ivideo->chip == XGI_40) {
+		if( (ivideo->revision_id == 1) ||
+		    (ivideo->revision_id == 2) ) {
+			SiS_SetReg(SISCR, 0x8c, 0x87);
+		}
+	}
+
+	if (regb == 1)
+		SiS_SetReg(SISSR, 0x17, 0x80);		/* DDR2 */
+	else
+		SiS_SetReg(SISSR, 0x17, 0x00);		/* DDR1 */
+	SiS_SetReg(SISSR, 0x1a, 0x87);
+
+	if(ivideo->chip == XGI_20) {
+		SiS_SetReg(SISSR, 0x15, 0x00);
+		SiS_SetReg(SISSR, 0x1c, 0x00);
+	}
+
+	switch(ramtype) {
+	case 0:
+		sisfb_post_xgi_setclocks(ivideo, regb);
+		if((ivideo->chip == XGI_20) ||
+		   (ivideo->revision_id == 1)   ||
+		   (ivideo->revision_id == 2)) {
+			v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
+			if(ivideo->haveXGIROM) {
+				v1 = bios[regb + 0x158];
+				v2 = bios[regb + 0x160];
+				v3 = bios[regb + 0x168];
+			}
+			SiS_SetReg(SISCR, 0x82, v1);
+			SiS_SetReg(SISCR, 0x85, v2);
+			SiS_SetReg(SISCR, 0x86, v3);
+		} else {
+			SiS_SetReg(SISCR, 0x82, 0x88);
+			SiS_SetReg(SISCR, 0x86, 0x00);
+			reg = SiS_GetReg(SISCR, 0x86);
+			SiS_SetReg(SISCR, 0x86, 0x88);
+			reg = SiS_GetReg(SISCR, 0x86);
+			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
+			SiS_SetReg(SISCR, 0x82, 0x77);
+			SiS_SetReg(SISCR, 0x85, 0x00);
+			reg = SiS_GetReg(SISCR, 0x85);
+			SiS_SetReg(SISCR, 0x85, 0x88);
+			reg = SiS_GetReg(SISCR, 0x85);
+			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
+			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
+		}
+		if(ivideo->chip == XGI_40) {
+			SiS_SetReg(SISCR, 0x97, 0x00);
+		}
+		SiS_SetReg(SISCR, 0x98, 0x01);
+		SiS_SetReg(SISCR, 0x9a, 0x02);
+
+		SiS_SetReg(SISSR, 0x18, 0x01);
+		if((ivideo->chip == XGI_20) ||
+		   (ivideo->revision_id == 2)) {
+			SiS_SetReg(SISSR, 0x19, 0x40);
+		} else {
+			SiS_SetReg(SISSR, 0x19, 0x20);
+		}
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
+		if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
+			sisfb_post_xgi_delay(ivideo, 0x43);
+			sisfb_post_xgi_delay(ivideo, 0x43);
+			sisfb_post_xgi_delay(ivideo, 0x43);
+			SiS_SetReg(SISSR, 0x18, 0x00);
+			if((ivideo->chip == XGI_20) ||
+			   (ivideo->revision_id == 2)) {
+				SiS_SetReg(SISSR, 0x19, 0x40);
+			} else {
+				SiS_SetReg(SISSR, 0x19, 0x20);
+			}
+		} else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
+			/* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
+		}
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
+		sisfb_post_xgi_delay(ivideo, 4);
+		v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
+		if(ivideo->haveXGIROM) {
+			v1 = bios[0xf0];
+			index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
+			v2 = bios[index];
+			v3 = bios[index + 1];
+			v4 = bios[index + 2];
+			v5 = bios[index + 3];
+		}
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
+		SiS_SetReg(SISSR, 0x16, v2);
+		SiS_SetReg(SISSR, 0x16, v3);
+		sisfb_post_xgi_delay(ivideo, 0x43);
+		SiS_SetReg(SISSR, 0x1b, 0x03);
+		sisfb_post_xgi_delay(ivideo, 0x22);
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, 0x00);
+		SiS_SetReg(SISSR, 0x16, v4);
+		SiS_SetReg(SISSR, 0x16, v5);
+		SiS_SetReg(SISSR, 0x1b, 0x00);
+		break;
+	case 1:
+		sisfb_post_xgi_ddr2(ivideo, regb);
+		break;
+	default:
+		sisfb_post_xgi_setclocks(ivideo, regb);
+		if((ivideo->chip == XGI_40) &&
+		   ((ivideo->revision_id == 1) ||
+		    (ivideo->revision_id == 2))) {
+			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
+			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
+			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
+		} else {
+			SiS_SetReg(SISCR, 0x82, 0x88);
+			SiS_SetReg(SISCR, 0x86, 0x00);
+			reg = SiS_GetReg(SISCR, 0x86);
+			SiS_SetReg(SISCR, 0x86, 0x88);
+			SiS_SetReg(SISCR, 0x82, 0x77);
+			SiS_SetReg(SISCR, 0x85, 0x00);
+			reg = SiS_GetReg(SISCR, 0x85);
+			SiS_SetReg(SISCR, 0x85, 0x88);
+			reg = SiS_GetReg(SISCR, 0x85);
+			v1 = cs160[regb]; v2 = cs158[regb];
+			if(ivideo->haveXGIROM) {
+				v1 = bios[regb + 0x160];
+				v2 = bios[regb + 0x158];
+			}
+			SiS_SetReg(SISCR, 0x85, v1);
+			SiS_SetReg(SISCR, 0x82, v2);
+		}
+		if(ivideo->chip == XGI_40) {
+			SiS_SetReg(SISCR, 0x97, 0x11);
+		}
+		if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
+			SiS_SetReg(SISCR, 0x98, 0x01);
+		} else {
+			SiS_SetReg(SISCR, 0x98, 0x03);
+		}
+		SiS_SetReg(SISCR, 0x9a, 0x02);
+
+		if(ivideo->chip == XGI_40) {
+			SiS_SetReg(SISSR, 0x18, 0x01);
+		} else {
+			SiS_SetReg(SISSR, 0x18, 0x00);
+		}
+		SiS_SetReg(SISSR, 0x19, 0x40);
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
+		if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
+			sisfb_post_xgi_delay(ivideo, 0x43);
+			sisfb_post_xgi_delay(ivideo, 0x43);
+			sisfb_post_xgi_delay(ivideo, 0x43);
+			SiS_SetReg(SISSR, 0x18, 0x00);
+			SiS_SetReg(SISSR, 0x19, 0x40);
+			SiS_SetReg(SISSR, 0x16, 0x00);
+			SiS_SetReg(SISSR, 0x16, 0x80);
+		}
+		sisfb_post_xgi_delay(ivideo, 4);
+		v1 = 0x31;
+		if(ivideo->haveXGIROM) {
+			v1 = bios[0xf0];
+		}
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, 0x01);
+		if(ivideo->chip == XGI_40) {
+			SiS_SetReg(SISSR, 0x16, bios[0x53e]);
+			SiS_SetReg(SISSR, 0x16, bios[0x53f]);
+		} else {
+			SiS_SetReg(SISSR, 0x16, 0x05);
+			SiS_SetReg(SISSR, 0x16, 0x85);
+		}
+		sisfb_post_xgi_delay(ivideo, 0x43);
+		if(ivideo->chip == XGI_40) {
+			SiS_SetReg(SISSR, 0x1b, 0x01);
+		} else {
+			SiS_SetReg(SISSR, 0x1b, 0x03);
+		}
+		sisfb_post_xgi_delay(ivideo, 0x22);
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, 0x00);
+		if(ivideo->chip == XGI_40) {
+			SiS_SetReg(SISSR, 0x16, bios[0x540]);
+			SiS_SetReg(SISSR, 0x16, bios[0x541]);
+		} else {
+			SiS_SetReg(SISSR, 0x16, 0x05);
+			SiS_SetReg(SISSR, 0x16, 0x85);
+		}
+		SiS_SetReg(SISSR, 0x1b, 0x00);
+	}
+
+	regb = 0;	/* ! */
+	v1 = 0x03;
+	if(ivideo->haveXGIROM) {
+		v1 = bios[0x110 + regb];
+	}
+	SiS_SetReg(SISSR, 0x1b, v1);
+
+	/* RAM size */
+	v1 = 0x00; v2 = 0x00;
+	if(ivideo->haveXGIROM) {
+		v1 = bios[0x62];
+		v2 = bios[0x63];
+	}
+	regb = 0;	/* ! */
+	regd = 1 << regb;
+	if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
+
+		SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
+		SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
+
+	} else {
+		int err;
+
+		/* Set default mode, don't clear screen */
+		ivideo->SiS_Pr.SiS_UseOEM = false;
+		SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+		SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
+		ivideo->curFSTN = ivideo->curDSTN = 0;
+		ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+		SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+		SiS_SetReg(SISSR, 0x05, 0x86);
+
+		/* Disable read-cache */
+		SiS_SetRegAND(SISSR, 0x21, 0xdf);
+		err = sisfb_post_xgi_ramsize(ivideo);
+		/* Enable read-cache */
+		SiS_SetRegOR(SISSR, 0x21, 0x20);
+
+		if (err) {
+			dev_err(&pdev->dev,
+				"%s: RAM size detection failed: %d\n",
+				__func__, err);
+			return 0;
+		}
+	}
+
+#if 0
+	printk(KERN_DEBUG "-----------------\n");
+	for(i = 0; i < 0xff; i++) {
+		reg = SiS_GetReg(SISCR, i);
+		printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
+	}
+	for(i = 0; i < 0x40; i++) {
+		reg = SiS_GetReg(SISSR, i);
+		printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
+	}
+	printk(KERN_DEBUG "-----------------\n");
+#endif
+
+	/* Sense CRT1 */
+	if(ivideo->chip == XGI_20) {
+		SiS_SetRegOR(SISCR, 0x32, 0x20);
+	} else {
+		reg = SiS_GetReg(SISPART4, 0x00);
+		if((reg == 1) || (reg == 2)) {
+			sisfb_sense_crt1(ivideo);
+		} else {
+			SiS_SetRegOR(SISCR, 0x32, 0x20);
+		}
+	}
+
+	/* Set default mode, don't clear screen */
+	ivideo->SiS_Pr.SiS_UseOEM = false;
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
+	ivideo->curFSTN = ivideo->curDSTN = 0;
+	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+	SiS_SetReg(SISSR, 0x05, 0x86);
+
+	/* Display off */
+	SiS_SetRegOR(SISSR, 0x01, 0x20);
+
+	/* Save mode number in CR34 */
+	SiS_SetReg(SISCR, 0x34, 0x2e);
+
+	/* Let everyone know what the current mode is */
+	ivideo->modeprechange = 0x2e;
+
+	if(ivideo->chip == XGI_40) {
+		reg = SiS_GetReg(SISCR, 0xca);
+		v1 = SiS_GetReg(SISCR, 0xcc);
+		if((reg & 0x10) && (!(v1 & 0x04))) {
+			printk(KERN_ERR
+				"sisfb: Please connect power to the card.\n");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+#endif
+
+static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct sisfb_chip_info	*chipinfo = &sisfb_chip_info[ent->driver_data];
+	struct sis_video_info	*ivideo = NULL;
+	struct fb_info		*sis_fb_info = NULL;
+	u16 reg16;
+	u8  reg;
+	int i, ret;
+
+	if(sisfb_off)
+		return -ENXIO;
+
+	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
+	if(!sis_fb_info)
+		return -ENOMEM;
+
+	ivideo = (struct sis_video_info *)sis_fb_info->par;
+	ivideo->memyselfandi = sis_fb_info;
+
+	ivideo->sisfb_id = SISFB_ID;
+
+	if(card_list == NULL) {
+		ivideo->cardnumber = 0;
+	} else {
+		struct sis_video_info *countvideo = card_list;
+		ivideo->cardnumber = 1;
+		while((countvideo = countvideo->next) != NULL)
+			ivideo->cardnumber++;
+	}
+
+	strncpy(ivideo->myid, chipinfo->chip_name, 30);
+
+	ivideo->warncount = 0;
+	ivideo->chip_id = pdev->device;
+	ivideo->chip_vendor = pdev->vendor;
+	ivideo->revision_id = pdev->revision;
+	ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
+	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
+	ivideo->sisvga_enabled = reg16 & 0x01;
+	ivideo->pcibus = pdev->bus->number;
+	ivideo->pcislot = PCI_SLOT(pdev->devfn);
+	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
+	ivideo->subsysvendor = pdev->subsystem_vendor;
+	ivideo->subsysdevice = pdev->subsystem_device;
+
+#ifndef MODULE
+	if(sisfb_mode_idx == -1) {
+		sisfb_get_vga_mode_from_kernel();
+	}
+#endif
+
+	ivideo->chip = chipinfo->chip;
+	ivideo->chip_real_id = chipinfo->chip;
+	ivideo->sisvga_engine = chipinfo->vgaengine;
+	ivideo->hwcursor_size = chipinfo->hwcursor_size;
+	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
+	ivideo->mni = chipinfo->mni;
+
+	ivideo->detectedpdc  = 0xff;
+	ivideo->detectedpdca = 0xff;
+	ivideo->detectedlcda = 0xff;
+
+	ivideo->sisfb_thismonitor.datavalid = false;
+
+	ivideo->current_base = 0;
+
+	ivideo->engineok = 0;
+
+	ivideo->sisfb_was_boot_device = 0;
+
+	if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
+		if(ivideo->sisvga_enabled)
+			ivideo->sisfb_was_boot_device = 1;
+		else {
+			printk(KERN_DEBUG "sisfb: PCI device is disabled, "
+				"but marked as boot video device ???\n");
+			printk(KERN_DEBUG "sisfb: I will not accept this "
+				"as the primary VGA device\n");
+		}
+	}
+
+	ivideo->sisfb_parm_mem = sisfb_parm_mem;
+	ivideo->sisfb_accel = sisfb_accel;
+	ivideo->sisfb_ypan = sisfb_ypan;
+	ivideo->sisfb_max = sisfb_max;
+	ivideo->sisfb_userom = sisfb_userom;
+	ivideo->sisfb_useoem = sisfb_useoem;
+	ivideo->sisfb_mode_idx = sisfb_mode_idx;
+	ivideo->sisfb_parm_rate = sisfb_parm_rate;
+	ivideo->sisfb_crt1off = sisfb_crt1off;
+	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
+	ivideo->sisfb_crt2type = sisfb_crt2type;
+	ivideo->sisfb_crt2flags = sisfb_crt2flags;
+	/* pdc(a), scalelcd, special timing, lvdshl handled below */
+	ivideo->sisfb_dstn = sisfb_dstn;
+	ivideo->sisfb_fstn = sisfb_fstn;
+	ivideo->sisfb_tvplug = sisfb_tvplug;
+	ivideo->sisfb_tvstd = sisfb_tvstd;
+	ivideo->tvxpos = sisfb_tvxposoffset;
+	ivideo->tvypos = sisfb_tvyposoffset;
+	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
+	ivideo->refresh_rate = 0;
+	if(ivideo->sisfb_parm_rate != -1) {
+		ivideo->refresh_rate = ivideo->sisfb_parm_rate;
+	}
+
+	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
+	ivideo->SiS_Pr.CenterScreen = -1;
+	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
+	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
+
+	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
+	ivideo->SiS_Pr.SiS_CHOverScan = -1;
+	ivideo->SiS_Pr.SiS_ChSW = false;
+	ivideo->SiS_Pr.SiS_UseLCDA = false;
+	ivideo->SiS_Pr.HaveEMI = false;
+	ivideo->SiS_Pr.HaveEMILCD = false;
+	ivideo->SiS_Pr.OverruleEMI = false;
+	ivideo->SiS_Pr.SiS_SensibleSR11 = false;
+	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
+	ivideo->SiS_Pr.PDC  = -1;
+	ivideo->SiS_Pr.PDCA = -1;
+	ivideo->SiS_Pr.DDCPortMixup = false;
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->chip >= SIS_330) {
+		ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
+		if(ivideo->chip >= SIS_661) {
+			ivideo->SiS_Pr.SiS_SensibleSR11 = true;
+		}
+	}
+#endif
+
+	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
+
+	pci_set_drvdata(pdev, ivideo);
+
+	/* Patch special cases */
+	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
+		switch(ivideo->nbridge->device) {
+#ifdef CONFIG_FB_SIS_300
+		case PCI_DEVICE_ID_SI_730:
+			ivideo->chip = SIS_730;
+			strcpy(ivideo->myid, "SiS 730");
+			break;
+#endif
+#ifdef CONFIG_FB_SIS_315
+		case PCI_DEVICE_ID_SI_651:
+			/* ivideo->chip is ok */
+			strcpy(ivideo->myid, "SiS 651");
+			break;
+		case PCI_DEVICE_ID_SI_740:
+			ivideo->chip = SIS_740;
+			strcpy(ivideo->myid, "SiS 740");
+			break;
+		case PCI_DEVICE_ID_SI_661:
+			ivideo->chip = SIS_661;
+			strcpy(ivideo->myid, "SiS 661");
+			break;
+		case PCI_DEVICE_ID_SI_741:
+			ivideo->chip = SIS_741;
+			strcpy(ivideo->myid, "SiS 741");
+			break;
+		case PCI_DEVICE_ID_SI_760:
+			ivideo->chip = SIS_760;
+			strcpy(ivideo->myid, "SiS 760");
+			break;
+		case PCI_DEVICE_ID_SI_761:
+			ivideo->chip = SIS_761;
+			strcpy(ivideo->myid, "SiS 761");
+			break;
+#endif
+		default:
+			break;
+		}
+	}
+
+	ivideo->SiS_Pr.ChipType = ivideo->chip;
+
+	ivideo->SiS_Pr.ivideo = (void *)ivideo;
+
+#ifdef CONFIG_FB_SIS_315
+	if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
+	   (ivideo->SiS_Pr.ChipType == SIS_315)) {
+		ivideo->SiS_Pr.ChipType = SIS_315H;
+	}
+#endif
+
+	if(!ivideo->sisvga_enabled) {
+		if(pci_enable_device(pdev)) {
+			if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
+			framebuffer_release(sis_fb_info);
+			return -EIO;
+		}
+	}
+
+	ivideo->video_base = pci_resource_start(pdev, 0);
+	ivideo->video_size = pci_resource_len(pdev, 0);
+	ivideo->mmio_base  = pci_resource_start(pdev, 1);
+	ivideo->mmio_size  = pci_resource_len(pdev, 1);
+	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
+	ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
+
+	SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
+
+#ifdef CONFIG_FB_SIS_300
+	/* Find PCI systems for Chrontel/GPIO communication setup */
+	if(ivideo->chip == SIS_630) {
+		i = 0;
+        	do {
+			if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
+			   mychswtable[i].subsysCard   == ivideo->subsysdevice) {
+				ivideo->SiS_Pr.SiS_ChSW = true;
+				printk(KERN_DEBUG "sisfb: Identified [%s %s] "
+					"requiring Chrontel/GPIO setup\n",
+					mychswtable[i].vendorName,
+					mychswtable[i].cardName);
+				ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
+				break;
+			}
+			i++;
+		} while(mychswtable[i].subsysVendor != 0);
+	}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+	if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
+		ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
+	}
+#endif
+
+	SiS_SetReg(SISSR, 0x05, 0x86);
+
+	if( (!ivideo->sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+			      || (sisfb_resetcard)
+#endif
+						   ) {
+		for(i = 0x30; i <= 0x3f; i++) {
+			SiS_SetReg(SISCR, i, 0x00);
+		}
+	}
+
+	/* Find out about current video mode */
+	ivideo->modeprechange = 0x03;
+	reg = SiS_GetReg(SISCR, 0x34);
+	if(reg & 0x7f) {
+		ivideo->modeprechange = reg & 0x7f;
+	} else if(ivideo->sisvga_enabled) {
+#if defined(__i386__) || defined(__x86_64__)
+		unsigned char __iomem *tt = ioremap(0x400, 0x100);
+		if(tt) {
+			ivideo->modeprechange = readb(tt + 0x49);
+			iounmap(tt);
+		}
+#endif
+	}
+
+	/* Search and copy ROM image */
+	ivideo->bios_abase = NULL;
+	ivideo->SiS_Pr.VirtualRomBase = NULL;
+	ivideo->SiS_Pr.UseROM = false;
+	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
+	if(ivideo->sisfb_userom) {
+		ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
+		ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
+		ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
+		printk(KERN_INFO "sisfb: Video ROM %sfound\n",
+			ivideo->SiS_Pr.UseROM ? "" : "not ");
+		if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
+		   ivideo->SiS_Pr.UseROM = false;
+		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
+		   if( (ivideo->revision_id == 2) &&
+		       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
+			ivideo->SiS_Pr.DDCPortMixup = true;
+		   }
+		}
+	} else {
+		printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
+	}
+
+	/* Find systems for special custom timing */
+	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
+		sisfb_detect_custom_timing(ivideo);
+	}
+
+#ifdef CONFIG_FB_SIS_315
+	if (ivideo->chip == XGI_20) {
+		/* Check if our Z7 chip is actually Z9 */
+		SiS_SetRegOR(SISCR, 0x4a, 0x40);	/* GPIOG EN */
+		reg = SiS_GetReg(SISCR, 0x48);
+		if (reg & 0x02) {			/* GPIOG */
+			ivideo->chip_real_id = XGI_21;
+			dev_info(&pdev->dev, "Z9 detected\n");
+		}
+	}
+#endif
+
+	/* POST card in case this has not been done by the BIOS */
+	if( (!ivideo->sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+			     || (sisfb_resetcard)
+#endif
+						 ) {
+#ifdef CONFIG_FB_SIS_300
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+			if(ivideo->chip == SIS_300) {
+				sisfb_post_sis300(pdev);
+				ivideo->sisfb_can_post = 1;
+			}
+		}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
+			int result = 1;
+		/*	if((ivideo->chip == SIS_315H)   ||
+			   (ivideo->chip == SIS_315)    ||
+			   (ivideo->chip == SIS_315PRO) ||
+			   (ivideo->chip == SIS_330)) {
+				sisfb_post_sis315330(pdev);
+			} else */ if(ivideo->chip == XGI_20) {
+				result = sisfb_post_xgi(pdev);
+				ivideo->sisfb_can_post = 1;
+			} else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
+				result = sisfb_post_xgi(pdev);
+				ivideo->sisfb_can_post = 1;
+			} else {
+				printk(KERN_INFO "sisfb: Card is not "
+					"POSTed and sisfb can't do this either.\n");
+			}
+			if(!result) {
+				printk(KERN_ERR "sisfb: Failed to POST card\n");
+				ret = -ENODEV;
+				goto error_3;
+			}
+		}
+#endif
+	}
+
+	ivideo->sisfb_card_posted = 1;
+
+	/* Find out about RAM size */
+	if(sisfb_get_dram_size(ivideo)) {
+		printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
+		ret = -ENODEV;
+		goto error_3;
+	}
+
+
+	/* Enable PCI addressing and MMIO */
+	if((ivideo->sisfb_mode_idx < 0) ||
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
+		/* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
+		SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
+		/* Enable 2D accelerator engine */
+		SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
+	}
+
+	if(sisfb_pdc != 0xff) {
+		if(ivideo->sisvga_engine == SIS_300_VGA)
+			sisfb_pdc &= 0x3c;
+		else
+			sisfb_pdc &= 0x1f;
+		ivideo->SiS_Pr.PDC = sisfb_pdc;
+	}
+#ifdef CONFIG_FB_SIS_315
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+		if(sisfb_pdca != 0xff)
+			ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
+	}
+#endif
+
+	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
+		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
+				(int)(ivideo->video_size >> 20));
+		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
+		ret = -ENODEV;
+		goto error_3;
+	}
+
+	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
+		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
+		ret = -ENODEV;
+		goto error_2;
+	}
+
+	ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
+	ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
+	if(!ivideo->video_vbase) {
+		printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
+		ret = -ENODEV;
+		goto error_1;
+	}
+
+	ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
+	if(!ivideo->mmio_vbase) {
+		printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
+		ret = -ENODEV;
+error_0:	iounmap(ivideo->video_vbase);
+error_1:	release_mem_region(ivideo->video_base, ivideo->video_size);
+error_2:	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+error_3:	vfree(ivideo->bios_abase);
+		if(ivideo->lpcdev)
+			pci_dev_put(ivideo->lpcdev);
+		if(ivideo->nbridge)
+			pci_dev_put(ivideo->nbridge);
+		if(!ivideo->sisvga_enabled)
+			pci_disable_device(pdev);
+		framebuffer_release(sis_fb_info);
+		return ret;
+	}
+
+	printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
+		ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
+
+	if(ivideo->video_offset) {
+		printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
+			ivideo->video_offset / 1024);
+	}
+
+	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
+		ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+
+
+	/* Determine the size of the command queue */
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+		ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
+	} else {
+		if(ivideo->chip == XGI_20) {
+			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
+		} else {
+			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
+		}
+	}
+
+	/* Engines are no longer initialized here; this is
+	 * now done after the first mode-switch (if the
+	 * submitted var has its acceleration flags set).
+	 */
+
+	/* Calculate the base of the (unused) hw cursor */
+	ivideo->hwcursor_vbase = ivideo->video_vbase
+				 + ivideo->video_size
+				 - ivideo->cmdQueueSize
+				 - ivideo->hwcursor_size;
+	ivideo->caps |= HW_CURSOR_CAP;
+
+	/* Initialize offscreen memory manager */
+	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
+		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
+	}
+
+	/* Used for clearing the screen only, therefore respect our mem limit */
+	ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
+	ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
+
+	ivideo->mtrr = -1;
+
+	ivideo->vbflags = 0;
+	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
+	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
+	ivideo->defmodeidx    = DEFAULT_MODE;
+
+	ivideo->newrom = 0;
+	if(ivideo->chip < XGI_20) {
+		if(ivideo->bios_abase) {
+			ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
+		}
+	}
+
+	if((ivideo->sisfb_mode_idx < 0) ||
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
+
+		sisfb_sense_crt1(ivideo);
+
+		sisfb_get_VB_type(ivideo);
+
+		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
+			sisfb_detect_VB_connect(ivideo);
+		}
+
+		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
+
+		/* Decide on which CRT2 device to use */
+		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
+			if(ivideo->sisfb_crt2type != -1) {
+				if((ivideo->sisfb_crt2type == CRT2_LCD) &&
+				   (ivideo->vbflags & CRT2_LCD)) {
+					ivideo->currentvbflags |= CRT2_LCD;
+				} else if(ivideo->sisfb_crt2type != CRT2_LCD) {
+					ivideo->currentvbflags |= ivideo->sisfb_crt2type;
+				}
+			} else {
+				/* Chrontel 700x TV detection often unreliable, therefore
+				 * use a different default order on such machines
+				 */
+				if((ivideo->sisvga_engine == SIS_300_VGA) &&
+				   (ivideo->vbflags2 & VB2_CHRONTEL)) {
+					if(ivideo->vbflags & CRT2_LCD)
+						ivideo->currentvbflags |= CRT2_LCD;
+					else if(ivideo->vbflags & CRT2_TV)
+						ivideo->currentvbflags |= CRT2_TV;
+					else if(ivideo->vbflags & CRT2_VGA)
+						ivideo->currentvbflags |= CRT2_VGA;
+				} else {
+					if(ivideo->vbflags & CRT2_TV)
+						ivideo->currentvbflags |= CRT2_TV;
+					else if(ivideo->vbflags & CRT2_LCD)
+						ivideo->currentvbflags |= CRT2_LCD;
+					else if(ivideo->vbflags & CRT2_VGA)
+						ivideo->currentvbflags |= CRT2_VGA;
+				}
+			}
+		}
+
+		if(ivideo->vbflags & CRT2_LCD) {
+			sisfb_detect_lcd_type(ivideo);
+		}
+
+		sisfb_save_pdc_emi(ivideo);
+
+		if(!ivideo->sisfb_crt1off) {
+			sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
+		} else {
+			if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
+			   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
+				sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
+			}
+		}
+
+		if(ivideo->sisfb_mode_idx >= 0) {
+			int bu = ivideo->sisfb_mode_idx;
+			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
+					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+			if(bu != ivideo->sisfb_mode_idx) {
+				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
+					sisbios_mode[bu].xres,
+					sisbios_mode[bu].yres,
+					sisbios_mode[bu].bpp);
+			}
+		}
+
+		if(ivideo->sisfb_mode_idx < 0) {
+			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+			   case CRT2_LCD:
+				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
+				break;
+			   case CRT2_TV:
+				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
+				break;
+			   default:
+				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
+				break;
+			}
+		}
+
+		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
+
+		if(ivideo->refresh_rate != 0) {
+			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
+						ivideo->sisfb_mode_idx);
+		}
+
+		if(ivideo->rate_idx == 0) {
+			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
+			ivideo->refresh_rate = 60;
+		}
+
+		if(ivideo->sisfb_thismonitor.datavalid) {
+			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
+						ivideo->sisfb_mode_idx,
+						ivideo->rate_idx,
+						ivideo->refresh_rate)) {
+				printk(KERN_INFO "sisfb: WARNING: Refresh rate "
+							"exceeds monitor specs!\n");
+			}
+		}
+
+		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+
+		sisfb_set_vparms(ivideo);
+
+		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
+			ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+			ivideo->refresh_rate);
+
+		/* Set up the default var according to chosen default display mode */
+		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
+		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
+		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
+
+		sisfb_bpp_to_var(ivideo, &ivideo->default_var);
+
+		ivideo->default_var.pixclock = (u32) (1000000000 /
+			sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
+
+		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
+						ivideo->rate_idx, &ivideo->default_var)) {
+			if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+				ivideo->default_var.pixclock <<= 1;
+			}
+		}
+
+		if(ivideo->sisfb_ypan) {
+			/* Maximize regardless of sisfb_max at startup */
+			ivideo->default_var.yres_virtual =
+				sisfb_calc_maxyres(ivideo, &ivideo->default_var);
+			if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
+				ivideo->default_var.yres_virtual = ivideo->default_var.yres;
+			}
+		}
+
+		sisfb_calc_pitch(ivideo, &ivideo->default_var);
+
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+			ivideo->accel = -1;
+#ifdef STUPID_ACCELF_TEXT_SHIT
+			ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+#endif
+		}
+		sisfb_initaccel(ivideo);
+
+#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
+		sis_fb_info->flags = FBINFO_DEFAULT 		|
+				     FBINFO_HWACCEL_YPAN 	|
+				     FBINFO_HWACCEL_XPAN 	|
+				     FBINFO_HWACCEL_COPYAREA 	|
+				     FBINFO_HWACCEL_FILLRECT 	|
+				     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
+#else
+		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
+#endif
+		sis_fb_info->var = ivideo->default_var;
+		sis_fb_info->fix = ivideo->sisfb_fix;
+		sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
+		sis_fb_info->fbops = &sisfb_ops;
+		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
+
+		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
+
+		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
+
+#ifdef CONFIG_MTRR
+		ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
+					MTRR_TYPE_WRCOMB, 1);
+		if(ivideo->mtrr < 0) {
+			printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
+		}
+#endif
+
+		if(register_framebuffer(sis_fb_info) < 0) {
+			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
+			ret = -EINVAL;
+			iounmap(ivideo->mmio_vbase);
+			goto error_0;
+		}
+
+		ivideo->registered = 1;
+
+		/* Enlist us */
+		ivideo->next = card_list;
+		card_list = ivideo;
+
+		printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
+			ivideo->sisfb_accel ? "enabled" : "disabled",
+			ivideo->sisfb_ypan  ?
+				(ivideo->sisfb_max ? "enabled (auto-max)" :
+						"enabled (no auto-max)") :
+									"disabled");
+
+
+		fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
+			ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+
+		printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
+
+	}	/* if mode = "none" */
+
+	return 0;
+}
+
+/*****************************************************/
+/*                PCI DEVICE HANDLING                */
+/*****************************************************/
+
+static void sisfb_remove(struct pci_dev *pdev)
+{
+	struct sis_video_info	*ivideo = pci_get_drvdata(pdev);
+	struct fb_info		*sis_fb_info = ivideo->memyselfandi;
+	int			registered = ivideo->registered;
+	int			modechanged = ivideo->modechanged;
+
+	/* Unmap */
+	iounmap(ivideo->mmio_vbase);
+	iounmap(ivideo->video_vbase);
+
+	/* Release mem regions */
+	release_mem_region(ivideo->video_base, ivideo->video_size);
+	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+
+	vfree(ivideo->bios_abase);
+
+	if(ivideo->lpcdev)
+		pci_dev_put(ivideo->lpcdev);
+
+	if(ivideo->nbridge)
+		pci_dev_put(ivideo->nbridge);
+
+#ifdef CONFIG_MTRR
+	/* Release MTRR region */
+	if(ivideo->mtrr >= 0)
+		mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
+#endif
+
+	/* If device was disabled when starting, disable
+	 * it when quitting.
+	 */
+	if(!ivideo->sisvga_enabled)
+		pci_disable_device(pdev);
+
+	/* Unregister the framebuffer */
+	if(ivideo->registered) {
+		unregister_framebuffer(sis_fb_info);
+		framebuffer_release(sis_fb_info);
+	}
+
+	/* OK, our ivideo is gone for good from here. */
+
+	/* TODO: Restore the initial mode
+	 * This sounds easy but is as good as impossible
+	 * on many machines with SiS chip and video bridge
+	 * since text modes are always set up differently
+	 * from machine to machine. Depends on the type
+	 * of integration between chipset and bridge.
+	 */
+	if(registered && modechanged)
+		printk(KERN_INFO
+			"sisfb: Restoring of text mode not supported yet\n");
+};
+
+static struct pci_driver sisfb_driver = {
+	.name		= "sisfb",
+	.id_table 	= sisfb_pci_table,
+	.probe		= sisfb_probe,
+	.remove 	= sisfb_remove,
+};
+
+static int __init sisfb_init(void)
+{
+#ifndef MODULE
+	char *options = NULL;
+
+	if(fb_get_options("sisfb", &options))
+		return -ENODEV;
+
+	sisfb_setup(options);
+#endif
+	return pci_register_driver(&sisfb_driver);
+}
+
+#ifndef MODULE
+module_init(sisfb_init);
+#endif
+
+/*****************************************************/
+/*                      MODULE                       */
+/*****************************************************/
+
+#ifdef MODULE
+
+static char		*mode = NULL;
+static int		vesa = -1;
+static unsigned int	rate = 0;
+static unsigned int	crt1off = 1;
+static unsigned int	mem = 0;
+static char		*forcecrt2type = NULL;
+static int		forcecrt1 = -1;
+static int		pdc = -1;
+static int		pdc1 = -1;
+static int		noaccel = -1;
+static int		noypan  = -1;
+static int		nomax = -1;
+static int		userom = -1;
+static int		useoem = -1;
+static char		*tvstandard = NULL;
+static int		nocrt2rate = 0;
+static int		scalelcd = -1;
+static char		*specialtiming = NULL;
+static int		lvdshl = -1;
+static int		tvxposoffset = 0, tvyposoffset = 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int		resetcard = 0;
+static int		videoram = 0;
+#endif
+
+static int __init sisfb_init_module(void)
+{
+	sisfb_setdefaultparms();
+
+	if(rate)
+		sisfb_parm_rate = rate;
+
+	if((scalelcd == 0) || (scalelcd == 1))
+		sisfb_scalelcd = scalelcd ^ 1;
+
+	/* Need to check crt2 type first for fstn/dstn */
+
+	if(forcecrt2type)
+		sisfb_search_crt2type(forcecrt2type);
+
+	if(tvstandard)
+		sisfb_search_tvstd(tvstandard);
+
+	if(mode)
+		sisfb_search_mode(mode, false);
+	else if(vesa != -1)
+		sisfb_search_vesamode(vesa, false);
+
+	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
+
+	sisfb_forcecrt1 = forcecrt1;
+	if(forcecrt1 == 1)
+		sisfb_crt1off = 0;
+	else if(forcecrt1 == 0)
+		sisfb_crt1off = 1;
+
+	if(noaccel == 1)
+		sisfb_accel = 0;
+	else if(noaccel == 0)
+		sisfb_accel = 1;
+
+	if(noypan == 1)
+		sisfb_ypan = 0;
+	else if(noypan == 0)
+		sisfb_ypan = 1;
+
+	if(nomax == 1)
+		sisfb_max = 0;
+	else if(nomax == 0)
+		sisfb_max = 1;
+
+	if(mem)
+		sisfb_parm_mem = mem;
+
+	if(userom != -1)
+		sisfb_userom = userom;
+
+	if(useoem != -1)
+		sisfb_useoem = useoem;
+
+        if(pdc != -1)
+		sisfb_pdc  = (pdc  & 0x7f);
+
+	if(pdc1 != -1)
+		sisfb_pdca = (pdc1 & 0x1f);
+
+	sisfb_nocrt2rate = nocrt2rate;
+
+	if(specialtiming)
+		sisfb_search_specialtiming(specialtiming);
+
+	if((lvdshl >= 0) && (lvdshl <= 3))
+		sisfb_lvdshl = lvdshl;
+
+	sisfb_tvxposoffset = tvxposoffset;
+	sisfb_tvyposoffset = tvyposoffset;
+
+#if !defined(__i386__) && !defined(__x86_64__)
+	sisfb_resetcard = (resetcard) ? 1 : 0;
+	if(videoram)
+		sisfb_videoram = videoram;
+#endif
+
+	return sisfb_init();
+}
+
+static void __exit sisfb_remove_module(void)
+{
+	pci_unregister_driver(&sisfb_driver);
+	printk(KERN_DEBUG "sisfb: Module unloaded\n");
+}
+
+module_init(sisfb_init_module);
+module_exit(sisfb_remove_module);
+
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
+
+module_param(mem, int, 0);
+module_param(noaccel, int, 0);
+module_param(noypan, int, 0);
+module_param(nomax, int, 0);
+module_param(userom, int, 0);
+module_param(useoem, int, 0);
+module_param(mode, charp, 0);
+module_param(vesa, int, 0);
+module_param(rate, int, 0);
+module_param(forcecrt1, int, 0);
+module_param(forcecrt2type, charp, 0);
+module_param(scalelcd, int, 0);
+module_param(pdc, int, 0);
+module_param(pdc1, int, 0);
+module_param(specialtiming, charp, 0);
+module_param(lvdshl, int, 0);
+module_param(tvstandard, charp, 0);
+module_param(tvxposoffset, int, 0);
+module_param(tvyposoffset, int, 0);
+module_param(nocrt2rate, int, 0);
+#if !defined(__i386__) && !defined(__x86_64__)
+module_param(resetcard, int, 0);
+module_param(videoram, int, 0);
+#endif
+
+MODULE_PARM_DESC(mem,
+	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+	  "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
+	  "The value is to be specified without 'KB'.\n");
+
+MODULE_PARM_DESC(noaccel,
+	"\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+	  "(default: 0)\n");
+
+MODULE_PARM_DESC(noypan,
+	"\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+	  "will be performed by redrawing the screen. (default: 0)\n");
+
+MODULE_PARM_DESC(nomax,
+	"\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
+	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
+	  "enable the user to positively specify a virtual Y size of the screen using\n"
+	  "fbset. (default: 0)\n");
+
+MODULE_PARM_DESC(mode,
+	"\nSelects the desired default display mode in the format XxYxDepth,\n"
+	 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
+
+MODULE_PARM_DESC(vesa,
+	"\nSelects the desired default display mode by VESA defined mode number, eg.\n"
+	 "0x117 (default: 0x0103)\n");
+
+MODULE_PARM_DESC(rate,
+	"\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
+	  "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
+	  "will be ignored (default: 60)\n");
+
+MODULE_PARM_DESC(forcecrt1,
+	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
+	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
+	  "0=CRT1 OFF) (default: [autodetected])\n");
+
+MODULE_PARM_DESC(forcecrt2type,
+	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
+	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
+	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
+	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
+	  "be used instead of TV to override the TV detection. Furthermore, on systems\n"
+	  "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
+	  "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
+	  "depends on the very hardware in use. (default: [autodetected])\n");
+
+MODULE_PARM_DESC(scalelcd,
+	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
+	  "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
+	  "show black bars around the image, TMDS panels will probably do the scaling\n"
+	  "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
+
+MODULE_PARM_DESC(pdc,
+	"\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
+	  "should detect this correctly in most cases; however, sometimes this is not\n"
+	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
+	  "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
+	  "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
+	  "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
+
+#ifdef CONFIG_FB_SIS_315
+MODULE_PARM_DESC(pdc1,
+	"\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
+	  "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
+	  "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
+	  "implemented yet.\n");
+#endif
+
+MODULE_PARM_DESC(specialtiming,
+	"\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(lvdshl,
+	"\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(tvstandard,
+	"\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
+	  "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
+
+MODULE_PARM_DESC(tvxposoffset,
+	"\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");
+
+MODULE_PARM_DESC(tvyposoffset,
+	"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");
+
+MODULE_PARM_DESC(nocrt2rate,
+	"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
+	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
+
+#if !defined(__i386__) && !defined(__x86_64__)
+#ifdef CONFIG_FB_SIS_300
+MODULE_PARM_DESC(resetcard,
+	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
+	  "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
+	  "currently). Default: 0\n");
+
+MODULE_PARM_DESC(videoram,
+	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
+	  "some non-x86 architectures where the memory auto detection fails. Only\n"
+	  "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
+#endif
+#endif
+
+#endif 	   /*  /MODULE  */
+
+/* _GPL only for new symbols. */
+EXPORT_SYMBOL(sis_malloc);
+EXPORT_SYMBOL(sis_free);
+EXPORT_SYMBOL_GPL(sis_malloc_new);
+EXPORT_SYMBOL_GPL(sis_free_new);
+
+
+
diff --git a/drivers/video/fbdev/sis/sis_main.h b/drivers/video/fbdev/sis/sis_main.h
new file mode 100644
index 000000000000..32e23c209430
--- /dev/null
+++ b/drivers/video/fbdev/sis/sis_main.h
@@ -0,0 +1,781 @@
+/*
+ * SiS 300/305/540/630(S)/730(S),
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
+ *
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef _SISFB_MAIN
+#define _SISFB_MAIN
+
+#include "vstruct.h"
+#include "sis.h"
+
+/* Fbcon stuff */
+static struct fb_var_screeninfo my_default_var = {
+	.xres            = 0,
+	.yres            = 0,
+	.xres_virtual    = 0,
+	.yres_virtual    = 0,
+	.xoffset         = 0,
+	.yoffset         = 0,
+	.bits_per_pixel  = 0,
+	.grayscale       = 0,
+	.red             = {0, 8, 0},
+	.green           = {0, 8, 0},
+	.blue            = {0, 8, 0},
+	.transp          = {0, 0, 0},
+	.nonstd          = 0,
+	.activate        = FB_ACTIVATE_NOW,
+	.height          = -1,
+	.width           = -1,
+	.accel_flags     = 0,
+	.pixclock        = 0,
+	.left_margin     = 0,
+	.right_margin    = 0,
+	.upper_margin    = 0,
+	.lower_margin    = 0,
+	.hsync_len       = 0,
+	.vsync_len       = 0,
+	.sync            = 0,
+	.vmode           = FB_VMODE_NONINTERLACED,
+};
+
+#define MODE_INDEX_NONE           0  /* index for mode=none */
+
+/* Boot-time parameters */
+static int sisfb_off = 0;
+static int sisfb_parm_mem = 0;
+static int sisfb_accel = -1;
+static int sisfb_ypan = -1;
+static int sisfb_max = -1;
+static int sisfb_userom = 1;
+static int sisfb_useoem = -1;
+static int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
+static int sisfb_parm_rate = -1;
+static int sisfb_crt1off = 0;
+static int sisfb_forcecrt1 = -1;
+static int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
+static int sisfb_crt2flags = 0;
+static int sisfb_pdc = 0xff;
+static int sisfb_pdca = 0xff;
+static int sisfb_scalelcd = -1;
+static int sisfb_specialtiming = CUT_NONE;
+static int sisfb_lvdshl = -1;
+static int sisfb_dstn = 0;
+static int sisfb_fstn = 0;
+static int sisfb_tvplug = -1;		/* Tv plug type (for overriding autodetection) */
+static int sisfb_tvstd  = -1;
+static int sisfb_tvxposoffset = 0;
+static int sisfb_tvyposoffset = 0;
+static int sisfb_nocrt2rate = 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int sisfb_resetcard = 0;
+static int sisfb_videoram = 0;
+#endif
+
+/* List of supported chips */
+static struct sisfb_chip_info {
+	int		chip;
+	int		vgaengine;
+	int		mni;
+	int		hwcursor_size;
+	int		CRT2_write_enable;
+	const char	*chip_name;
+} sisfb_chip_info[] = {
+	{ SIS_300,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
+	{ SIS_540,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
+	{ SIS_630,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
+	{ SIS_315H,   SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
+	{ SIS_315,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
+	{ SIS_315PRO, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
+	{ SIS_550,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
+	{ SIS_650,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
+	{ SIS_330,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
+	{ SIS_660,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
+	{ XGI_20,     SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI Z7" },
+	{ XGI_40,     SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI V3XT/V5/V8" },
+};
+
+static struct pci_device_id sisfb_pci_table[] = {
+#ifdef CONFIG_FB_SIS_300
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+#endif
+#ifdef CONFIG_FB_SIS_315
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+	{ PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_20,     PCI_ANY_ID, PCI_ANY_ID, 0, 0,10},
+	{ PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_40,     PCI_ANY_ID, PCI_ANY_ID, 0, 0,11},
+#endif
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
+
+static struct sis_video_info *card_list = NULL;
+
+/* The memory heap is now handled card-wise, by using
+   sis_malloc_new/sis_free_new. However, the DRM does
+   not do this yet. Until it does, we keep a "global"
+   heap which is actually the first card's one.
+ */
+static struct SIS_HEAP	*sisfb_heap;
+
+#define MD_SIS300 1
+#define MD_SIS315 2
+
+/* Mode table */
+static const struct _sisbios_mode {
+	char name[15];
+	u8  mode_no[2];
+	u16 vesa_mode_no_1;  /* "SiS defined" VESA mode number */
+	u16 vesa_mode_no_2;  /* Real VESA mode numbers */
+	u16 xres;
+	u16 yres;
+	u16 bpp;
+	u16 rate_idx;
+	u16 cols;
+	u16 rows;
+	u8  chipset;
+} sisbios_mode[] = {
+/*0*/	{"none",         {0xff,0xff}, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_SIS300|MD_SIS315},
+	{"320x200x8",    {0x59,0x59}, 0x0138, 0x0000,  320,  200,  8, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x16",   {0x41,0x41}, 0x010e, 0x0000,  320,  200, 16, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x24",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},  /* That's for people who mix up color- and fb depth */
+	{"320x200x32",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x240x8",    {0x50,0x50}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x16",   {0x56,0x56}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x24",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x32",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+#define MODE_FSTN_8	9
+#define MODE_FSTN_16	10
+	{"320x240x8",    {0x5a,0x5a}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15,           MD_SIS315},  /* FSTN */
+/*10*/	{"320x240x16",   {0x5b,0x5b}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15,           MD_SIS315},  /* FSTN */
+	{"400x300x8",    {0x51,0x51}, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x16",   {0x57,0x57}, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x24",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x32",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"512x384x8",    {0x52,0x52}, 0x0000, 0x0000,  512,  384,  8, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x16",   {0x58,0x58}, 0x0000, 0x0000,  512,  384, 16, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x24",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x32",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"640x400x8",    {0x2f,0x2f}, 0x0000, 0x0000,  640,  400,  8, 1,  80, 25, MD_SIS300|MD_SIS315},
+/*20*/	{"640x400x16",   {0x5d,0x5d}, 0x0000, 0x0000,  640,  400, 16, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x24",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x32",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x480x8",    {0x2e,0x2e}, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x16",   {0x44,0x44}, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x24",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x32",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"720x480x8",    {0x31,0x31}, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x16",   {0x33,0x33}, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x24",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+/*30*/	{"720x480x32",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x576x8",    {0x32,0x32}, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x16",   {0x34,0x34}, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x24",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x32",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"768x576x8",    {0x5f,0x5f}, 0x0000, 0x0000,  768,  576,  8, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x16",   {0x60,0x60}, 0x0000, 0x0000,  768,  576, 16, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x24",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x32",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"800x480x8",    {0x70,0x70}, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_SIS300|MD_SIS315},
+/*40*/	{"800x480x16",   {0x7a,0x7a}, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x24",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x32",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE		43 /* index for 800x600x8 */
+#define DEFAULT_LCDMODE		43 /* index for 800x600x8 */
+#define DEFAULT_TVMODE		43 /* index for 800x600x8 */
+	{"800x600x8",    {0x30,0x30}, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x16",   {0x47,0x47}, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x24",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x32",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"848x480x8",    {0x39,0x39}, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_848	48
+	{"848x480x16",   {0x3b,0x3b}, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"848x480x24",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+/*50*/	{"848x480x32",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"856x480x8",    {0x3f,0x3f}, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_856	52
+	{"856x480x16",   {0x42,0x42}, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x24",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x32",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"960x540x8",    {0x1d,0x1d}, 0x0000, 0x0000,  960,  540,  8, 1, 120, 33,           MD_SIS315},
+	{"960x540x16",   {0x1e,0x1e}, 0x0000, 0x0000,  960,  540, 16, 1, 120, 33,           MD_SIS315},
+	{"960x540x24",   {0x1f,0x1f}, 0x0000, 0x0000,  960,  540, 32, 1, 120, 33,           MD_SIS315},
+	{"960x540x32",   {0x1f,0x1f}, 0x0000, 0x0000,  960,  540, 32, 1, 120, 33,           MD_SIS315},
+	{"960x600x8",    {0x20,0x20}, 0x0000, 0x0000,  960,  600,  8, 1, 120, 37,           MD_SIS315},
+/*60*/	{"960x600x16",   {0x21,0x21}, 0x0000, 0x0000,  960,  600, 16, 1, 120, 37,           MD_SIS315},
+	{"960x600x24",   {0x22,0x22}, 0x0000, 0x0000,  960,  600, 32, 1, 120, 37,           MD_SIS315},
+	{"960x600x32",   {0x22,0x22}, 0x0000, 0x0000,  960,  600, 32, 1, 120, 37,           MD_SIS315},
+	{"1024x576x8",   {0x71,0x71}, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x16",  {0x74,0x74}, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x24",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x32",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x600x8",   {0x20,0x20}, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_SIS300          },
+	{"1024x600x16",  {0x21,0x21}, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_SIS300          },
+	{"1024x600x24",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+/*70*/	{"1024x600x32",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+	{"1024x768x8",   {0x38,0x38}, 0x0105, 0x0105, 1024,  768,  8, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x16",  {0x4a,0x4a}, 0x0117, 0x0117, 1024,  768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x24",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x32",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1152x768x8",   {0x23,0x23}, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_SIS300          },
+	{"1152x768x16",  {0x24,0x24}, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_SIS300          },
+	{"1152x768x24",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+	{"1152x768x32",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+	{"1152x864x8",   {0x29,0x29}, 0x0000, 0x0000, 1152,  864,  8, 1, 144, 54, MD_SIS300|MD_SIS315},
+/*80*/	{"1152x864x16",  {0x2a,0x2a}, 0x0000, 0x0000, 1152,  864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x24",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x32",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1280x720x8",   {0x79,0x79}, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x16",  {0x75,0x75}, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x24",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x32",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x768x8",   {0x55,0x23}, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x16",  {0x5a,0x24}, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x24",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+/*90*/	{"1280x768x32",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x800x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
+	{"1280x800x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
+	{"1280x800x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x800x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x854x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  854,  8, 1, 160, 53,           MD_SIS315},
+	{"1280x854x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  854, 16, 1, 160, 53,           MD_SIS315},
+	{"1280x854x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  854, 32, 1, 160, 53,           MD_SIS315},
+	{"1280x854x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  854, 32, 1, 160, 53,           MD_SIS315},
+	{"1280x960x8",   {0x7c,0x7c}, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
+/*100*/	{"1280x960x16",  {0x7d,0x7d}, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x24",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x32",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x1024x8",  {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1360x768x8",   {0x48,0x48}, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x16",  {0x4b,0x4b}, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x24",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+/*110*/	{"1360x768x32",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x1024x8",  {0x67,0x67}, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
+#define DEFAULT_MODE_1360	112
+	{"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1400x1050x8",  {0x26,0x26}, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+	{"1600x1200x8",  {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
+/*120*/	{"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1680x1050x8",  {0x17,0x17}, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1920x1080x8",  {0x2c,0x2c}, 0x0000, 0x0000, 1920, 1080,  8, 1, 240, 67,           MD_SIS315},
+	{"1920x1080x16", {0x2d,0x2d}, 0x0000, 0x0000, 1920, 1080, 16, 1, 240, 67,           MD_SIS315},
+	{"1920x1080x24", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
+/*130*/	{"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
+	{"1920x1440x8",  {0x68,0x68}, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"2048x1536x8",  {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x32", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+	{"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
+};
+
+#define SIS_LCD_NUMBER 18
+static struct _sis_lcd_data {
+	u32 lcdtype;
+	u16 xres;
+	u16 yres;
+	u8  default_mode_idx;
+} sis_lcd_data[] = {
+	{ LCD_640x480,    640,  480,  23 },
+	{ LCD_800x600,    800,  600,  43 },
+	{ LCD_1024x600,  1024,  600,  67 },
+	{ LCD_1024x768,  1024,  768,  71 },
+	{ LCD_1152x768,  1152,  768,  75 },
+	{ LCD_1152x864,  1152,  864,  79 },
+	{ LCD_1280x720,  1280,  720,  83 },
+	{ LCD_1280x768,  1280,  768,  87 },
+	{ LCD_1280x800,  1280,  800,  91 },
+	{ LCD_1280x854,  1280,  854,  95 },
+	{ LCD_1280x960,  1280,  960,  99 },
+	{ LCD_1280x1024, 1280, 1024, 103 },
+	{ LCD_1400x1050, 1400, 1050, 115 },
+	{ LCD_1680x1050, 1680, 1050, 123 },
+	{ LCD_1600x1200, 1600, 1200, 119 },
+	{ LCD_320x240_2,  320,  240,   9 },
+	{ LCD_320x240_3,  320,  240,   9 },
+	{ LCD_320x240,    320,  240,   9 },
+};
+
+/* CR36 evaluation */
+static unsigned short sis300paneltype[] = {
+	LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+	LCD_1280x960,  LCD_640x480,   LCD_1024x600,  LCD_1152x768,
+	LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
+	LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN
+};
+
+static unsigned short sis310paneltype[] = {
+	LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+	LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
+	LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
+	LCD_320x240_2, LCD_320x240_3, LCD_UNKNOWN,   LCD_UNKNOWN
+};
+
+static unsigned short sis661paneltype[] = {
+	LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+	LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
+	LCD_1280x854,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
+	LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_UNKNOWN
+};
+
+#define FL_550_DSTN 0x01
+#define FL_550_FSTN 0x02
+#define FL_300      0x04
+#define FL_315      0x08
+
+static struct _sis_crt2type {
+	char name[32];
+	u32 type_no;
+	u32 tvplug_no;
+	u16 flags;
+} sis_crt2type[] __initdata = {
+	{"NONE", 	     0, 	-1,                     FL_300|FL_315},
+	{"LCD",  	     CRT2_LCD, 	-1,                     FL_300|FL_315},
+	{"TV",   	     CRT2_TV, 	-1,                     FL_300|FL_315},
+	{"VGA",  	     CRT2_VGA, 	-1,                     FL_300|FL_315},
+	{"SVIDEO", 	     CRT2_TV, 	TV_SVIDEO,              FL_300|FL_315},
+	{"COMPOSITE", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"CVBS", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"SVIDEO+COMPOSITE", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"COMPOSITE+SVIDEO", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SVIDEO+CVBS",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"CVBS+SVIDEO",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SCART", 	     CRT2_TV, 	TV_SCART,               FL_300|FL_315},
+	{"HIVISION",	     CRT2_TV,   TV_HIVISION,            FL_315},
+	{"YPBPR480I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525I,  FL_315},
+	{"YPBPR480P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525P,  FL_315},
+	{"YPBPR720P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR750P,  FL_315},
+	{"YPBPR1080I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR1080I, FL_315},
+	{"DSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_DSTN},
+	{"FSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_FSTN},
+	{"\0",  	     -1, 	-1,                     0}
+};
+
+/* TV standard */
+static struct _sis_tvtype {
+	char name[6];
+	u32 type_no;
+} sis_tvtype[] __initdata = {
+	{"PAL",  	TV_PAL},
+	{"NTSC", 	TV_NTSC},
+	{"PALM",  	TV_PAL|TV_PALM},
+	{"PALN",  	TV_PAL|TV_PALN},
+	{"NTSCJ",  	TV_NTSC|TV_NTSCJ},
+	{"\0",   	-1}
+};
+
+static const struct _sis_vrate {
+	u16 idx;
+	u16 xres;
+	u16 yres;
+	u16 refresh;
+	bool SiS730valid32bpp;
+} sisfb_vrate[] = {
+	{1,  320,  200,  70,  true},
+	{1,  320,  240,  60,  true},
+	{1,  400,  300,  60,  true},
+	{1,  512,  384,  60,  true},
+	{1,  640,  400,  72,  true},
+	{1,  640,  480,  60,  true}, {2,  640,  480,  72,  true}, {3,  640,  480,  75,  true},
+	{4,  640,  480,  85,  true}, {5,  640,  480, 100,  true}, {6,  640,  480, 120,  true},
+	{7,  640,  480, 160,  true}, {8,  640,  480, 200,  true},
+	{1,  720,  480,  60,  true},
+	{1,  720,  576,  58,  true},
+	{1,  768,  576,  58,  true},
+	{1,  800,  480,  60,  true}, {2,  800,  480,  75,  true}, {3,  800,  480,  85,  true},
+	{1,  800,  600,  56,  true}, {2,  800,  600,  60,  true}, {3,  800,  600,  72,  true},
+	{4,  800,  600,  75,  true}, {5,  800,  600,  85,  true}, {6,  800,  600, 105,  true},
+	{7,  800,  600, 120,  true}, {8,  800,  600, 160,  true},
+	{1,  848,  480,  39,  true}, {2,  848,  480,  60,  true},
+	{1,  856,  480,  39,  true}, {2,  856,  480,  60,  true},
+	{1,  960,  540,  60,  true},
+	{1,  960,  600,  60,  true},
+	{1, 1024,  576,  60,  true}, {2, 1024,  576,  75,  true}, {3, 1024,  576,  85,  true},
+	{1, 1024,  600,  60,  true},
+	{1, 1024,  768,  43,  true}, {2, 1024,  768,  60,  true}, {3, 1024,  768,  70, false},
+	{4, 1024,  768,  75, false}, {5, 1024,  768,  85,  true}, {6, 1024,  768, 100,  true},
+	{7, 1024,  768, 120,  true},
+	{1, 1152,  768,  60,  true},
+	{1, 1152,  864,  60,  true}, {2, 1152,  864,  75,  true}, {3, 1152,  864,  84,  true},
+	{1, 1280,  720,  60,  true}, {2, 1280,  720,  75,  true}, {3, 1280,  720,  85,  true},
+	{1, 1280,  768,  60,  true},
+	{1, 1280,  800,  60,  true},
+	{1, 1280,  854,  60,  true},
+	{1, 1280,  960,  60,  true}, {2, 1280,  960,  85,  true},
+	{1, 1280, 1024,  43,  true}, {2, 1280, 1024,  60,  true}, {3, 1280, 1024,  75,  true},
+	{4, 1280, 1024,  85,  true},
+	{1, 1360,  768,  60,  true},
+	{1, 1360, 1024,  59,  true},
+	{1, 1400, 1050,  60,  true}, {2, 1400, 1050,  75,  true},
+	{1, 1600, 1200,  60,  true}, {2, 1600, 1200,  65,  true}, {3, 1600, 1200,  70,  true},
+	{4, 1600, 1200,  75,  true}, {5, 1600, 1200,  85,  true}, {6, 1600, 1200, 100,  true},
+	{7, 1600, 1200, 120,  true},
+	{1, 1680, 1050,  60,  true},
+	{1, 1920, 1080,  30,  true},
+	{1, 1920, 1440,  60,  true}, {2, 1920, 1440,  65,  true}, {3, 1920, 1440,  70,  true},
+	{4, 1920, 1440,  75,  true}, {5, 1920, 1440,  85,  true}, {6, 1920, 1440, 100,  true},
+	{1, 2048, 1536,  60,  true}, {2, 2048, 1536,  65,  true}, {3, 2048, 1536,  70,  true},
+	{4, 2048, 1536,  75,  true}, {5, 2048, 1536,  85,  true},
+	{0,    0,    0,   0, false}
+};
+
+static struct _sisfbddcsmodes {
+	u32 mask;
+	u16 h;
+	u16 v;
+	u32 d;
+} sisfb_ddcsmodes[] = {
+	{ 0x10000, 67, 75, 108000},
+	{ 0x08000, 48, 72,  50000},
+	{ 0x04000, 46, 75,  49500},
+	{ 0x01000, 35, 43,  44900},
+	{ 0x00800, 48, 60,  65000},
+	{ 0x00400, 56, 70,  75000},
+	{ 0x00200, 60, 75,  78800},
+	{ 0x00100, 80, 75, 135000},
+	{ 0x00020, 31, 60,  25200},
+	{ 0x00008, 38, 72,  31500},
+	{ 0x00004, 37, 75,  31500},
+	{ 0x00002, 35, 56,  36000},
+	{ 0x00001, 38, 60,  40000}
+};
+
+static struct _sisfbddcfmodes {
+	u16 x;
+	u16 y;
+	u16 v;
+	u16 h;
+	u32 d;
+} sisfb_ddcfmodes[] = {
+	{ 1280, 1024, 85, 92, 157500},
+	{ 1600, 1200, 60, 75, 162000},
+	{ 1600, 1200, 65, 82, 175500},
+	{ 1600, 1200, 70, 88, 189000},
+	{ 1600, 1200, 75, 94, 202500},
+	{ 1600, 1200, 85, 107,229500},
+	{ 1920, 1440, 60, 90, 234000},
+	{ 1920, 1440, 75, 113,297000}
+};
+
+#ifdef CONFIG_FB_SIS_300
+static struct _chswtable {
+	u16  subsysVendor;
+	u16  subsysCard;
+	char *vendorName;
+	char *cardName;
+} mychswtable[] = {
+	{ 0x1631, 0x1002, "Mitachi", "0x1002" },
+	{ 0x1071, 0x7521, "Mitac"  , "7521P"  },
+	{ 0,      0,      ""       , ""       }
+};
+#endif
+
+static struct _customttable {
+	u16   chipID;
+	char  *biosversion;
+	char  *biosdate;
+	u32   bioschksum;
+	u16   biosFootprintAddr[5];
+	u8    biosFootprintData[5];
+	u16   pcisubsysvendor;
+	u16   pcisubsyscard;
+	char  *vendorName;
+	char  *cardName;
+	u32   SpecialID;
+	char  *optionName;
+} mycustomttable[] = {
+	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
+	  0x3240A8,
+	  { 0x220, 0x227, 0x228, 0x229, 0x0ee },
+	  {  0x01,  0xe3,  0x9a,  0x6a,  0xef },
+	  0x1039, 0x6300,
+	  "Barco", "iQ R200L/300/400", CUT_BARCO1366, "BARCO_1366"
+	},
+	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
+	  0x323FBD,
+	  { 0x220, 0x227, 0x228, 0x229, 0x0ee },
+	  {  0x00,  0x5a,  0x64,  0x41,  0xef },
+	  0x1039, 0x6300,
+	  "Barco", "iQ G200L/300/400/500", CUT_BARCO1024, "BARCO_1024"
+	},
+	{ SIS_650, "", "",
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x0e11, 0x083c,
+	  "Inventec (Compaq)", "3017cl/3045US", CUT_COMPAQ12802, "COMPAQ_1280"
+	},
+	{ SIS_650, "", "",
+	  0,
+	  { 0x00c, 0, 0, 0, 0 },
+	  { 'e'  , 0, 0, 0, 0 },
+	  0x1558, 0x0287,
+	  "Clevo", "L285/L287 (Version 1)", CUT_CLEVO1024, "CLEVO_L28X_1"
+	},
+	{ SIS_650, "", "",
+	  0,
+	  { 0x00c, 0, 0, 0, 0 },
+	  { 'y'  , 0, 0, 0, 0 },
+	  0x1558, 0x0287,
+	  "Clevo", "L285/L287 (Version 2)", CUT_CLEVO10242, "CLEVO_L28X_2"
+	},
+	{ SIS_650, "", "",
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1558, 0x0400,  /* possibly 401 and 402 as well; not panelsize specific (?) */
+	  "Clevo", "D400S/D410S/D400H/D410H", CUT_CLEVO1400, "CLEVO_D4X0"
+	},
+	{ SIS_650, "", "",
+	  0,	/* Shift LCD in LCD-via-CRT1 mode */
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1558, 0x2263,
+	  "Clevo", "D22ES/D27ES", CUT_UNIWILL1024, "CLEVO_D2X0ES"
+	},
+	{ SIS_650, "", "",
+	  0,	/* Shift LCD in LCD-via-CRT1 mode */
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1734, 0x101f,
+	  "Uniwill", "N243S9", CUT_UNIWILL1024, "UNIWILL_N243S9"
+	},
+	{ SIS_650, "", "",
+	  0,	/* Shift LCD in LCD-via-CRT1 mode */
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1584, 0x5103,
+	  "Uniwill", "N35BS1", CUT_UNIWILL10242, "UNIWILL_N35BS1"
+	},
+	{ SIS_650, "1.09.2c", "",  /* Other versions, too? */
+	  0,	/* Shift LCD in LCD-via-CRT1 mode */
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1019, 0x0f05,
+	  "ECS", "A928", CUT_UNIWILL1024, "ECS_A928"
+	},
+	{ SIS_740, "1.11.27a", "",
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1043, 0x1612,
+	  "Asus", "L3000D/L3500D", CUT_ASUSL3000D, "ASUS_L3X00"
+	},
+	{ SIS_650, "1.10.9k", "",
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1025, 0x0028,
+	  "Acer", "Aspire 1700", CUT_ACER1280, "ACER_ASPIRE1700"
+	},
+	{ SIS_650, "1.10.7w", "",
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x14c0, 0x0012,
+	  "Compal", "??? (V1)", CUT_COMPAL1400_1, "COMPAL_1400_1"
+	},
+	{ SIS_650, "1.10.7x", "",
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x14c0, 0x0012,
+	  "Compal", "??? (V2)", CUT_COMPAL1400_2, "COMPAL_1400_2"
+	},
+	{ SIS_650, "1.10.8o", "",
+	  0,	/* For EMI (unknown) */
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1043, 0x1612,
+	  "Asus", "A2H (V1)", CUT_ASUSA2H_1, "ASUS_A2H_1"
+	},
+	{ SIS_650, "1.10.8q", "",
+	  0,	/* For EMI */
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0x1043, 0x1612,
+	  "Asus", "A2H (V2)", CUT_ASUSA2H_2, "ASUS_A2H_2"
+	},
+	{ 4321, "", "",			/* never autodetected */
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0, 0,
+	  "Generic", "LVDS/Parallel 848x480", CUT_PANEL848, "PANEL848x480"
+	},
+	{ 4322, "", "",			/* never autodetected */
+	  0,
+	  { 0, 0, 0, 0, 0 },
+	  { 0, 0, 0, 0, 0 },
+	  0, 0,
+	  "Generic", "LVDS/Parallel 856x480", CUT_PANEL856, "PANEL856x480"
+	},
+	{ 0, "", "",
+	  0,
+	  { 0, 0, 0, 0 },
+	  { 0, 0, 0, 0 },
+	  0, 0,
+	  "", "", CUT_NONE, ""
+	}
+};
+
+/* ---------------------- Prototypes ------------------------- */
+
+/* Interface used by the world */
+#ifndef MODULE
+static int sisfb_setup(char *options);
+#endif
+
+/* Interface to the low level console driver */
+static int sisfb_init(void);
+
+/* fbdev routines */
+static int	sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+				struct fb_info *info);
+
+static int	sisfb_ioctl(struct fb_info *info, unsigned int cmd,
+			    unsigned long arg);
+static int	sisfb_set_par(struct fb_info *info);
+static int	sisfb_blank(int blank,
+				struct fb_info *info);
+extern void	fbcon_sis_fillrect(struct fb_info *info,
+				const struct fb_fillrect *rect);
+extern void	fbcon_sis_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area);
+extern int	fbcon_sis_sync(struct fb_info *info);
+
+/* Internal 2D accelerator functions */
+extern int	sisfb_initaccel(struct sis_video_info *ivideo);
+extern void	sisfb_syncaccel(struct sis_video_info *ivideo);
+
+/* Internal general routines */
+static void	sisfb_search_mode(char *name, bool quiet);
+static int	sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8	sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
+				int index);
+static int	sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+				unsigned blue, unsigned transp,
+				struct fb_info *fb_info);
+static int	sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+				struct fb_info *info);
+static void	sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void	sisfb_post_setmode(struct sis_video_info *ivideo);
+static bool	sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static bool	sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static bool	sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static bool	sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void	sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void	sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void	sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void	sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+#ifdef CONFIG_FB_SIS_300
+unsigned int	sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+void		sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val);
+unsigned int	sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+#endif
+#ifdef CONFIG_FB_SIS_315
+void		sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val);
+unsigned int	sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
+
+/* SiS-specific exported functions */
+void			sis_malloc(struct sis_memreq *req);
+void			sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
+void			sis_free(u32 base);
+void			sis_free_new(struct pci_dev *pdev, u32 base);
+
+/* Internal heap routines */
+static int		sisfb_heap_init(struct sis_video_info *ivideo);
+static struct SIS_OH *	sisfb_poh_new_node(struct SIS_HEAP *memheap);
+static struct SIS_OH *	sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
+static void		sisfb_delete_node(struct SIS_OH *poh);
+static void		sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
+static struct SIS_OH *	sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
+static void		sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
+
+/* Routines from init.c/init301.c */
+extern unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+				int VDisplay, int Depth, bool FSTN, unsigned short CustomT,
+				int LCDwith, int LCDheight, unsigned int VBFlags2);
+extern unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+				int VDisplay, int Depth, unsigned int VBFlags2);
+extern unsigned short	SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+				int VDisplay, int Depth, unsigned int VBFlags2);
+extern void		SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+extern bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern void		SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+extern void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+
+extern bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+
+extern bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+				int *htotal, int *vtotal, unsigned char rateindex);
+extern int		sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+				unsigned char modeno, unsigned char rateindex);
+extern int		sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+				unsigned char rateindex, struct fb_var_screeninfo *var);
+
+/* Chrontel TV, DDC and DPMS functions */
+extern unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void		SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern unsigned short	SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void		SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern void		SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+				unsigned char myor, unsigned char myand);
+extern void		SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+extern void		SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
+extern unsigned short	SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+				unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+				unsigned int VBFlags2);
+extern unsigned short	SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+#ifdef CONFIG_FB_SIS_315
+extern void		SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+extern void		SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
+#endif
+extern void		SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+extern void		SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
+#endif
+
+
diff --git a/drivers/video/fbdev/sis/vgatypes.h b/drivers/video/fbdev/sis/vgatypes.h
new file mode 100644
index 000000000000..e3f9976cfef0
--- /dev/null
+++ b/drivers/video/fbdev/sis/vgatypes.h
@@ -0,0 +1,97 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * General type definitions for universal mode switching modules
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _VGATYPES_H_
+#define _VGATYPES_H_
+
+#define SISIOMEMTYPE
+
+typedef unsigned long SISIOADDRESS;
+#include <linux/types.h>  /* Need __iomem */
+#undef SISIOMEMTYPE
+#define SISIOMEMTYPE __iomem
+
+typedef enum _SIS_CHIP_TYPE {
+    SIS_VGALegacy = 0,
+    SIS_530,
+    SIS_OLD,
+    SIS_300,
+    SIS_630,
+    SIS_730,
+    SIS_540,
+    SIS_315H,   /* SiS 310 */
+    SIS_315,
+    SIS_315PRO, /* SiS 325 */
+    SIS_550,
+    SIS_650,
+    SIS_740,
+    SIS_330,
+    SIS_661,
+    SIS_741,
+    SIS_670,
+    SIS_660 = 35,
+    SIS_760,
+    SIS_761,
+    SIS_762,
+    SIS_770,
+    SIS_340 = 55,
+    SIS_341,
+    SIS_342,
+    XGI_20  = 75,
+    XGI_21,
+    XGI_40,
+    MAX_SIS_CHIP
+} SIS_CHIP_TYPE;
+
+
+#endif
+
diff --git a/drivers/video/fbdev/sis/vstruct.h b/drivers/video/fbdev/sis/vstruct.h
new file mode 100644
index 000000000000..ea94d214dcff
--- /dev/null
+++ b/drivers/video/fbdev/sis/vstruct.h
@@ -0,0 +1,551 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * General structure definitions for universal mode switching modules
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * This program is free software; you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation; either version 2 of the named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _VSTRUCT_H_
+#define _VSTRUCT_H_
+
+struct SiS_PanelDelayTbl {
+ 	unsigned char timer[2];
+};
+
+struct SiS_LCDData {
+	unsigned short RVBHCMAX;
+	unsigned short RVBHCFACT;
+	unsigned short VGAHT;
+	unsigned short VGAVT;
+	unsigned short LCDHT;
+	unsigned short LCDVT;
+};
+
+struct SiS_TVData {
+	unsigned short RVBHCMAX;
+	unsigned short RVBHCFACT;
+	unsigned short VGAHT;
+	unsigned short VGAVT;
+	unsigned short TVHDE;
+	unsigned short TVVDE;
+	unsigned short RVBHRS;
+	unsigned char  FlickerMode;
+	unsigned short HALFRVBHRS;
+	unsigned short RVBHRS2;
+	unsigned char  RY1COE;
+	unsigned char  RY2COE;
+	unsigned char  RY3COE;
+	unsigned char  RY4COE;
+};
+
+struct SiS_LVDSData {
+	unsigned short VGAHT;
+	unsigned short VGAVT;
+	unsigned short LCDHT;
+	unsigned short LCDVT;
+};
+
+struct SiS_LVDSDes {
+	unsigned short LCDHDES;
+	unsigned short LCDVDES;
+};
+
+struct SiS_LVDSCRT1Data {
+	unsigned char  CR[15];
+};
+
+struct SiS_CHTVRegData {
+	unsigned char  Reg[16];
+};
+
+struct SiS_St {
+	unsigned char  St_ModeID;
+	unsigned short St_ModeFlag;
+	unsigned char  St_StTableIndex;
+	unsigned char  St_CRT2CRTC;
+	unsigned char  St_ResInfo;
+	unsigned char  VB_StTVFlickerIndex;
+	unsigned char  VB_StTVEdgeIndex;
+	unsigned char  VB_StTVYFilterIndex;
+	unsigned char  St_PDC;
+};
+
+struct SiS_VBMode {
+	unsigned char  ModeID;
+	unsigned char  VB_TVDelayIndex;
+	unsigned char  VB_TVFlickerIndex;
+	unsigned char  VB_TVPhaseIndex;
+	unsigned char  VB_TVYFilterIndex;
+	unsigned char  VB_LCDDelayIndex;
+	unsigned char  _VB_LCDHIndex;
+	unsigned char  _VB_LCDVIndex;
+};
+
+struct SiS_StandTable_S {
+	unsigned char  CRT_COLS;
+	unsigned char  ROWS;
+	unsigned char  CHAR_HEIGHT;
+	unsigned short CRT_LEN;
+	unsigned char  SR[4];
+	unsigned char  MISC;
+	unsigned char  CRTC[0x19];
+	unsigned char  ATTR[0x14];
+	unsigned char  GRC[9];
+};
+
+struct SiS_Ext {
+	unsigned char  Ext_ModeID;
+	unsigned short Ext_ModeFlag;
+	unsigned short Ext_VESAID;
+	unsigned char  Ext_RESINFO;
+	unsigned char  VB_ExtTVFlickerIndex;
+	unsigned char  VB_ExtTVEdgeIndex;
+	unsigned char  VB_ExtTVYFilterIndex;
+	unsigned char  VB_ExtTVYFilterIndexROM661;
+	unsigned char  REFindex;
+	char           ROMMODEIDX661;
+};
+
+struct SiS_Ext2 {
+	unsigned short Ext_InfoFlag;
+	unsigned char  Ext_CRT1CRTC;
+	unsigned char  Ext_CRTVCLK;
+	unsigned char  Ext_CRT2CRTC;
+	unsigned char  Ext_CRT2CRTC_NS;
+	unsigned char  ModeID;
+	unsigned short XRes;
+	unsigned short YRes;
+	unsigned char  Ext_PDC;
+	unsigned char  Ext_FakeCRT2CRTC;
+	unsigned char  Ext_FakeCRT2Clk;
+	unsigned char  Ext_CRT1CRTC_NORM;
+	unsigned char  Ext_CRTVCLK_NORM;
+	unsigned char  Ext_CRT1CRTC_WIDE;
+	unsigned char  Ext_CRTVCLK_WIDE;
+};
+
+struct SiS_Part2PortTbl {
+ 	unsigned char  CR[12];
+};
+
+struct SiS_CRT1Table {
+	unsigned char  CR[17];
+};
+
+struct SiS_MCLKData {
+	unsigned char  SR28,SR29,SR2A;
+	unsigned short CLOCK;
+};
+
+struct SiS_VCLKData {
+	unsigned char  SR2B,SR2C;
+	unsigned short CLOCK;
+};
+
+struct SiS_VBVCLKData {
+	unsigned char  Part4_A,Part4_B;
+	unsigned short CLOCK;
+};
+
+struct SiS_StResInfo_S {
+	unsigned short HTotal;
+	unsigned short VTotal;
+};
+
+struct SiS_ModeResInfo_S {
+	unsigned short HTotal;
+	unsigned short VTotal;
+	unsigned char  XChar;
+	unsigned char  YChar;
+};
+
+/* Defines for SiS_CustomT */
+/* Never change these for sisfb compatibility */
+#define CUT_NONE		 0
+#define CUT_FORCENONE		 1
+#define CUT_BARCO1366		 2
+#define CUT_BARCO1024		 3
+#define CUT_COMPAQ1280		 4
+#define CUT_COMPAQ12802		 5
+#define CUT_PANEL848		 6
+#define CUT_CLEVO1024		 7
+#define CUT_CLEVO10242		 8
+#define CUT_CLEVO1400		 9
+#define CUT_CLEVO14002		10
+#define CUT_UNIWILL1024		11
+#define CUT_ASUSL3000D		12
+#define CUT_UNIWILL10242	13
+#define CUT_ACER1280		14
+#define CUT_COMPAL1400_1	15
+#define CUT_COMPAL1400_2	16
+#define CUT_ASUSA2H_1		17
+#define CUT_ASUSA2H_2		18
+#define CUT_UNKNOWNLCD		19
+#define CUT_AOP8060		20
+#define CUT_PANEL856		21
+
+struct SiS_Private
+{
+	unsigned char			ChipType;
+	unsigned char			ChipRevision;
+	void				*ivideo;
+	unsigned char 			*VirtualRomBase;
+	bool				UseROM;
+	unsigned char SISIOMEMTYPE	*VideoMemoryAddress;
+	unsigned int			VideoMemorySize;
+	SISIOADDRESS			IOAddress;
+	SISIOADDRESS			IOAddress2;  /* For dual chip XGI volari */
+
+	SISIOADDRESS			RelIO;
+	SISIOADDRESS			SiS_P3c4;
+	SISIOADDRESS			SiS_P3d4;
+	SISIOADDRESS			SiS_P3c0;
+	SISIOADDRESS			SiS_P3ce;
+	SISIOADDRESS			SiS_P3c2;
+	SISIOADDRESS			SiS_P3ca;
+	SISIOADDRESS			SiS_P3c6;
+	SISIOADDRESS			SiS_P3c7;
+	SISIOADDRESS			SiS_P3c8;
+	SISIOADDRESS			SiS_P3c9;
+	SISIOADDRESS			SiS_P3cb;
+	SISIOADDRESS			SiS_P3cc;
+	SISIOADDRESS			SiS_P3cd;
+	SISIOADDRESS			SiS_P3da;
+	SISIOADDRESS			SiS_Part1Port;
+	SISIOADDRESS			SiS_Part2Port;
+	SISIOADDRESS			SiS_Part3Port;
+	SISIOADDRESS			SiS_Part4Port;
+	SISIOADDRESS			SiS_Part5Port;
+	SISIOADDRESS			SiS_VidCapt;
+	SISIOADDRESS			SiS_VidPlay;
+	unsigned short			SiS_IF_DEF_LVDS;
+	unsigned short			SiS_IF_DEF_CH70xx;
+	unsigned short			SiS_IF_DEF_CONEX;
+	unsigned short			SiS_IF_DEF_TRUMPION;
+	unsigned short			SiS_IF_DEF_DSTN;
+	unsigned short			SiS_IF_DEF_FSTN;
+	unsigned short			SiS_SysFlags;
+	unsigned char			SiS_VGAINFO;
+	bool				SiS_UseROM;
+	bool				SiS_ROMNew;
+	bool				SiS_XGIROM;
+	bool				SiS_NeedRomModeData;
+	bool				PanelSelfDetected;
+	bool				DDCPortMixup;
+	int				SiS_CHOverScan;
+	bool				SiS_CHSOverScan;
+	bool				SiS_ChSW;
+	bool				SiS_UseLCDA;
+	int				SiS_UseOEM;
+	unsigned int			SiS_CustomT;
+	int				SiS_UseWide, SiS_UseWideCRT2;
+	int				SiS_TVBlue;
+	unsigned short			SiS_Backup70xx;
+	bool				HaveEMI;
+	bool				HaveEMILCD;
+	bool				OverruleEMI;
+	unsigned char			EMI_30,EMI_31,EMI_32,EMI_33;
+	unsigned short			SiS_EMIOffset;
+	unsigned short			SiS_PWDOffset;
+	short				PDC, PDCA;
+	unsigned char			SiS_MyCR63;
+	unsigned short			SiS_CRT1Mode;
+	unsigned short			SiS_flag_clearbuffer;
+	int				SiS_RAMType;
+	unsigned char			SiS_ChannelAB;
+	unsigned char			SiS_DataBusWidth;
+	unsigned short			SiS_ModeType;
+	unsigned short			SiS_VBInfo;
+	unsigned short			SiS_TVMode;
+	unsigned short			SiS_LCDResInfo;
+	unsigned short			SiS_LCDTypeInfo;
+	unsigned short			SiS_LCDInfo;
+	unsigned short			SiS_LCDInfo661;
+	unsigned short			SiS_VBType;
+	unsigned short			SiS_VBExtInfo;
+	unsigned short			SiS_YPbPr;
+	unsigned short			SiS_SelectCRT2Rate;
+	unsigned short			SiS_SetFlag;
+	unsigned short			SiS_RVBHCFACT;
+	unsigned short			SiS_RVBHCMAX;
+	unsigned short			SiS_RVBHRS;
+	unsigned short			SiS_RVBHRS2;
+	unsigned short			SiS_VGAVT;
+	unsigned short			SiS_VGAHT;
+	unsigned short			SiS_VT;
+	unsigned short			SiS_HT;
+	unsigned short			SiS_VGAVDE;
+	unsigned short			SiS_VGAHDE;
+	unsigned short			SiS_VDE;
+	unsigned short			SiS_HDE;
+	unsigned short			SiS_NewFlickerMode;
+	unsigned short			SiS_RY1COE;
+	unsigned short			SiS_RY2COE;
+	unsigned short			SiS_RY3COE;
+	unsigned short			SiS_RY4COE;
+	unsigned short			SiS_LCDHDES;
+	unsigned short			SiS_LCDVDES;
+	SISIOADDRESS			SiS_DDC_Port;
+	unsigned short			SiS_DDC_Index;
+	unsigned short			SiS_DDC_Data;
+	unsigned short			SiS_DDC_NData;
+	unsigned short			SiS_DDC_Clk;
+	unsigned short			SiS_DDC_NClk;
+	unsigned short			SiS_DDC_DeviceAddr;
+	unsigned short			SiS_DDC_ReadAddr;
+	unsigned short			SiS_DDC_SecAddr;
+	unsigned short			SiS_ChrontelInit;
+	bool				SiS_SensibleSR11;
+	unsigned short			SiS661LCD2TableSize;
+
+	unsigned short			SiS_PanelMinLVDS;
+	unsigned short			SiS_PanelMin301;
+
+	const struct SiS_St		*SiS_SModeIDTable;
+	const struct SiS_StandTable_S	*SiS_StandTable;
+	const struct SiS_Ext		*SiS_EModeIDTable;
+	const struct SiS_Ext2		*SiS_RefIndex;
+	const struct SiS_VBMode		*SiS_VBModeIDTable;
+	const struct SiS_CRT1Table	*SiS_CRT1Table;
+	const struct SiS_MCLKData	*SiS_MCLKData_0;
+	const struct SiS_MCLKData	*SiS_MCLKData_1;
+	struct SiS_VCLKData		*SiS_VCLKData;
+	struct SiS_VBVCLKData		*SiS_VBVCLKData;
+	const struct SiS_StResInfo_S	*SiS_StResInfo;
+	const struct SiS_ModeResInfo_S	*SiS_ModeResInfo;
+
+	const unsigned char		*pSiS_OutputSelect;
+	const unsigned char		*pSiS_SoftSetting;
+
+	const unsigned char		*SiS_SR15;
+
+	const struct SiS_PanelDelayTbl	*SiS_PanelDelayTbl;
+	const struct SiS_PanelDelayTbl	*SiS_PanelDelayTblLVDS;
+
+	/* SiS bridge */
+
+	const struct SiS_LCDData	*SiS_ExtLCD1024x768Data;
+	const struct SiS_LCDData	*SiS_St2LCD1024x768Data;
+	const struct SiS_LCDData	*SiS_LCD1280x720Data;
+	const struct SiS_LCDData	*SiS_StLCD1280x768_2Data;
+	const struct SiS_LCDData	*SiS_ExtLCD1280x768_2Data;
+	const struct SiS_LCDData	*SiS_LCD1280x800Data;
+	const struct SiS_LCDData	*SiS_LCD1280x800_2Data;
+	const struct SiS_LCDData	*SiS_LCD1280x854Data;
+	const struct SiS_LCDData	*SiS_LCD1280x960Data;
+	const struct SiS_LCDData	*SiS_ExtLCD1280x1024Data;
+	const struct SiS_LCDData	*SiS_St2LCD1280x1024Data;
+	const struct SiS_LCDData	*SiS_StLCD1400x1050Data;
+	const struct SiS_LCDData	*SiS_ExtLCD1400x1050Data;
+	const struct SiS_LCDData	*SiS_StLCD1600x1200Data;
+	const struct SiS_LCDData	*SiS_ExtLCD1600x1200Data;
+	const struct SiS_LCDData	*SiS_LCD1680x1050Data;
+	const struct SiS_LCDData	*SiS_NoScaleData;
+	const struct SiS_TVData		*SiS_StPALData;
+	const struct SiS_TVData		*SiS_ExtPALData;
+	const struct SiS_TVData		*SiS_StNTSCData;
+	const struct SiS_TVData		*SiS_ExtNTSCData;
+	const struct SiS_TVData		*SiS_St1HiTVData;
+	const struct SiS_TVData		*SiS_St2HiTVData;
+	const struct SiS_TVData		*SiS_ExtHiTVData;
+	const struct SiS_TVData		*SiS_St525iData;
+	const struct SiS_TVData		*SiS_St525pData;
+	const struct SiS_TVData		*SiS_St750pData;
+	const struct SiS_TVData		*SiS_Ext525iData;
+	const struct SiS_TVData		*SiS_Ext525pData;
+	const struct SiS_TVData		*SiS_Ext750pData;
+	const unsigned char		*SiS_NTSCTiming;
+	const unsigned char		*SiS_PALTiming;
+	const unsigned char		*SiS_HiTVExtTiming;
+	const unsigned char		*SiS_HiTVSt1Timing;
+	const unsigned char		*SiS_HiTVSt2Timing;
+	const unsigned char		*SiS_HiTVGroup3Data;
+	const unsigned char		*SiS_HiTVGroup3Simu;
+#if 0
+	const unsigned char		*SiS_HiTVTextTiming;
+	const unsigned char		*SiS_HiTVGroup3Text;
+#endif
+
+	const struct SiS_Part2PortTbl	*SiS_CRT2Part2_1024x768_1;
+	const struct SiS_Part2PortTbl	*SiS_CRT2Part2_1024x768_2;
+	const struct SiS_Part2PortTbl	*SiS_CRT2Part2_1024x768_3;
+
+	/* LVDS, Chrontel */
+
+	const struct SiS_LVDSData	*SiS_LVDS320x240Data_1;
+	const struct SiS_LVDSData	*SiS_LVDS320x240Data_2;
+	const struct SiS_LVDSData	*SiS_LVDS640x480Data_1;
+	const struct SiS_LVDSData	*SiS_LVDS800x600Data_1;
+	const struct SiS_LVDSData	*SiS_LVDS1024x600Data_1;
+	const struct SiS_LVDSData	*SiS_LVDS1024x768Data_1;
+	const struct SiS_LVDSData	*SiS_LVDSBARCO1366Data_1;
+	const struct SiS_LVDSData	*SiS_LVDSBARCO1366Data_2;
+	const struct SiS_LVDSData	*SiS_LVDSBARCO1024Data_1;
+	const struct SiS_LVDSData	*SiS_LVDS848x480Data_1;
+	const struct SiS_LVDSData	*SiS_LVDS848x480Data_2;
+	const struct SiS_LVDSData	*SiS_CHTVUNTSCData;
+	const struct SiS_LVDSData	*SiS_CHTVONTSCData;
+	const struct SiS_LVDSData	*SiS_CHTVUPALData;
+	const struct SiS_LVDSData	*SiS_CHTVOPALData;
+	const struct SiS_LVDSData	*SiS_CHTVUPALMData;
+	const struct SiS_LVDSData	*SiS_CHTVOPALMData;
+	const struct SiS_LVDSData	*SiS_CHTVUPALNData;
+	const struct SiS_LVDSData	*SiS_CHTVOPALNData;
+	const struct SiS_LVDSData	*SiS_CHTVSOPALData;
+
+	const struct SiS_LVDSDes	*SiS_PanelType04_1a;
+	const struct SiS_LVDSDes	*SiS_PanelType04_2a;
+	const struct SiS_LVDSDes	*SiS_PanelType04_1b;
+	const struct SiS_LVDSDes	*SiS_PanelType04_2b;
+
+	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_1;
+	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_2;
+	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_2_H;
+	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_3;
+	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_3_H;
+	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1640x480_1;
+	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1640x480_1_H;
+	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1UNTSC;
+	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1ONTSC;
+	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1UPAL;
+	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1OPAL;
+	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1SOPAL;
+
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_UNTSC;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_ONTSC;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_UPAL;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_OPAL;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_UPALM;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_OPALM;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_UPALN;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_OPALN;
+	const struct SiS_CHTVRegData	*SiS_CHTVReg_SOPAL;
+
+	const unsigned char		*SiS_CHTVVCLKUNTSC;
+	const unsigned char		*SiS_CHTVVCLKONTSC;
+	const unsigned char		*SiS_CHTVVCLKUPAL;
+	const unsigned char		*SiS_CHTVVCLKOPAL;
+	const unsigned char		*SiS_CHTVVCLKUPALM;
+	const unsigned char		*SiS_CHTVVCLKOPALM;
+	const unsigned char		*SiS_CHTVVCLKUPALN;
+	const unsigned char		*SiS_CHTVVCLKOPALN;
+	const unsigned char		*SiS_CHTVVCLKSOPAL;
+
+	unsigned short			PanelXRes, PanelHT;
+	unsigned short			PanelYRes, PanelVT;
+	unsigned short			PanelHRS,  PanelHRE;
+	unsigned short			PanelVRS,  PanelVRE;
+	unsigned short			PanelVCLKIdx300;
+	unsigned short			PanelVCLKIdx315;
+	bool				Alternate1600x1200;
+
+	bool				UseCustomMode;
+	bool				CRT1UsesCustomMode;
+	unsigned short			CHDisplay;
+	unsigned short			CHSyncStart;
+	unsigned short			CHSyncEnd;
+	unsigned short			CHTotal;
+	unsigned short			CHBlankStart;
+	unsigned short			CHBlankEnd;
+	unsigned short			CVDisplay;
+	unsigned short			CVSyncStart;
+	unsigned short			CVSyncEnd;
+	unsigned short			CVTotal;
+	unsigned short			CVBlankStart;
+	unsigned short			CVBlankEnd;
+	unsigned int			CDClock;
+	unsigned int			CFlags;
+	unsigned char			CCRT1CRTC[17];
+	unsigned char			CSR2B;
+	unsigned char			CSR2C;
+	unsigned short			CSRClock;
+	unsigned short			CSRClock_CRT1;
+	unsigned short			CModeFlag;
+	unsigned short			CModeFlag_CRT1;
+	unsigned short			CInfoFlag;
+
+	int				LVDSHL;
+
+	bool				Backup;
+	unsigned char			Backup_Mode;
+	unsigned char			Backup_14;
+	unsigned char			Backup_15;
+	unsigned char			Backup_16;
+	unsigned char			Backup_17;
+	unsigned char			Backup_18;
+	unsigned char			Backup_19;
+	unsigned char			Backup_1a;
+	unsigned char			Backup_1b;
+	unsigned char			Backup_1c;
+	unsigned char			Backup_1d;
+
+	unsigned char			Init_P4_0E;
+
+	int				UsePanelScaler;
+	int				CenterScreen;
+
+	unsigned short			CP_Vendor, CP_Product;
+	bool				CP_HaveCustomData;
+	int				CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
+	int				CP_MaxX, CP_MaxY, CP_MaxClock;
+	unsigned char			CP_PrefSR2B, CP_PrefSR2C;
+	unsigned short			CP_PrefClock;
+	bool				CP_Supports64048075;
+	int				CP_HDisplay[7], CP_VDisplay[7];	/* For Custom LCD panel dimensions */
+	int				CP_HTotal[7], CP_VTotal[7];
+	int				CP_HSyncStart[7], CP_VSyncStart[7];
+	int				CP_HSyncEnd[7], CP_VSyncEnd[7];
+	int				CP_HBlankStart[7], CP_VBlankStart[7];
+	int				CP_HBlankEnd[7], CP_VBlankEnd[7];
+	int				CP_Clock[7];
+	bool				CP_DataValid[7];
+	bool				CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
+};
+
+#endif
+
diff --git a/drivers/video/fbdev/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c
new file mode 100644
index 000000000000..fefde7c6add7
--- /dev/null
+++ b/drivers/video/fbdev/skeletonfb.c
@@ -0,0 +1,1037 @@
+/*
+ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
+ *
+ *  Modified to new api Jan 2001 by James Simmons (jsimmons@transvirtual.com)
+ *
+ *  Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ *
+ *  I have started rewriting this driver as a example of the upcoming new API
+ *  The primary goal is to remove the console code from fbdev and place it
+ *  into fbcon.c. This reduces the code and makes writing a new fbdev driver
+ *  easy since the author doesn't need to worry about console internals. It
+ *  also allows the ability to run fbdev without a console/tty system on top 
+ *  of it. 
+ *
+ *  First the roles of struct fb_info and struct display have changed. Struct
+ *  display will go away. The way the new framebuffer console code will
+ *  work is that it will act to translate data about the tty/console in 
+ *  struct vc_data to data in a device independent way in struct fb_info. Then
+ *  various functions in struct fb_ops will be called to store the device 
+ *  dependent state in the par field in struct fb_info and to change the 
+ *  hardware to that state. This allows a very clean separation of the fbdev
+ *  layer from the console layer. It also allows one to use fbdev on its own
+ *  which is a bounus for embedded devices. The reason this approach works is  
+ *  for each framebuffer device when used as a tty/console device is allocated
+ *  a set of virtual terminals to it. Only one virtual terminal can be active 
+ *  per framebuffer device. We already have all the data we need in struct 
+ *  vc_data so why store a bunch of colormaps and other fbdev specific data
+ *  per virtual terminal. 
+ *
+ *  As you can see doing this makes the con parameter pretty much useless
+ *  for struct fb_ops functions, as it should be. Also having struct  
+ *  fb_var_screeninfo and other data in fb_info pretty much eliminates the 
+ *  need for get_fix and get_var. Once all drivers use the fix, var, and cmap
+ *  fbcon can be written around these fields. This will also eliminate the
+ *  need to regenerate struct fb_var_screeninfo, struct fb_fix_screeninfo
+ *  struct fb_cmap every time get_var, get_fix, get_cmap functions are called
+ *  as many drivers do now. 
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+    /*
+     *  This is just simple sample code.
+     *
+     *  No warranty that it actually compiles.
+     *  Even less warranty that it actually works :-)
+     */
+
+/*
+ * Driver data
+ */
+static char *mode_option;
+
+/*
+ *  If your driver supports multiple boards, you should make the  
+ *  below data types arrays, or allocate them dynamically (using kmalloc()). 
+ */ 
+
+/* 
+ * This structure defines the hardware state of the graphics card. Normally
+ * you place this in a header file in linux/include/video. This file usually
+ * also includes register information. That allows other driver subsystems
+ * and userland applications the ability to use the same header file to 
+ * avoid duplicate work and easy porting of software. 
+ */
+struct xxx_par;
+
+/*
+ * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
+ * if we don't use modedb. If we do use modedb see xxxfb_init how to use it
+ * to get a fb_var_screeninfo. Otherwise define a default var as well. 
+ */
+static struct fb_fix_screeninfo xxxfb_fix = {
+	.id =		"FB's name", 
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	1, 
+	.accel =	FB_ACCEL_NONE,
+};
+
+    /*
+     * 	Modern graphical hardware not only supports pipelines but some 
+     *  also support multiple monitors where each display can have its  
+     *  its own unique data. In this case each display could be  
+     *  represented by a separate framebuffer device thus a separate 
+     *  struct fb_info. Now the struct xxx_par represents the graphics
+     *  hardware state thus only one exist per card. In this case the 
+     *  struct xxx_par for each graphics card would be shared between 
+     *  every struct fb_info that represents a framebuffer on that card. 
+     *  This allows when one display changes it video resolution (info->var) 
+     *  the other displays know instantly. Each display can always be
+     *  aware of the entire hardware state that affects it because they share
+     *  the same xxx_par struct. The other side of the coin is multiple
+     *  graphics cards that pass data around until it is finally displayed
+     *  on one monitor. Such examples are the voodoo 1 cards and high end
+     *  NUMA graphics servers. For this case we have a bunch of pars, each
+     *  one that represents a graphics state, that belong to one struct 
+     *  fb_info. Their you would want to have *par point to a array of device
+     *  states and have each struct fb_ops function deal with all those 
+     *  states. I hope this covers every possible hardware design. If not
+     *  feel free to send your ideas at jsimmons@users.sf.net 
+     */
+
+    /*
+     *  If your driver supports multiple boards or it supports multiple 
+     *  framebuffers, you should make these arrays, or allocate them 
+     *  dynamically using framebuffer_alloc() and free them with
+     *  framebuffer_release().
+     */ 
+static struct fb_info info;
+
+    /* 
+     * Each one represents the state of the hardware. Most hardware have
+     * just one hardware state. These here represent the default state(s). 
+     */
+static struct xxx_par __initdata current_par;
+
+int xxxfb_init(void);
+
+/**
+ *	xxxfb_open - Optional function. Called when the framebuffer is
+ *		     first accessed.
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@user: tell us if the userland (value=1) or the console is accessing
+ *	       the framebuffer. 
+ *
+ *	This function is the first function called in the framebuffer api.
+ *	Usually you don't need to provide this function. The case where it 
+ *	is used is to change from a text mode hardware state to a graphics
+ * 	mode state. 
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int xxxfb_open(struct fb_info *info, int user)
+{
+    return 0;
+}
+
+/**
+ *	xxxfb_release - Optional function. Called when the framebuffer 
+ *			device is closed. 
+ *	@info: frame buffer structure that represents a single frame buffer
+ *	@user: tell us if the userland (value=1) or the console is accessing
+ *	       the framebuffer. 
+ *	
+ *	Thus function is called when we close /dev/fb or the framebuffer 
+ *	console system is released. Usually you don't need this function.
+ *	The case where it is usually used is to go from a graphics state
+ *	to a text mode state.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int xxxfb_release(struct fb_info *info, int user)
+{
+    return 0;
+}
+
+/**
+ *      xxxfb_check_var - Optional function. Validates a var passed in. 
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer 
+ *
+ *	Checks to see if the hardware supports the state requested by
+ *	var passed in. This function does not alter the hardware state!!! 
+ *	This means the data stored in struct fb_info and struct xxx_par do 
+ *      not change. This includes the var inside of struct fb_info. 
+ *	Do NOT change these. This function can be called on its own if we
+ *	intent to only test a mode and not actually set it. The stuff in 
+ *	modedb.c is a example of this. If the var passed in is slightly 
+ *	off by what the hardware can support then we alter the var PASSED in
+ *	to what we can do.
+ *
+ *      For values that are off, this function must round them _up_ to the
+ *      next value that is supported by the hardware.  If the value is
+ *      greater than the highest value supported by the hardware, then this
+ *      function must return -EINVAL.
+ *
+ *      Exception to the above rule:  Some drivers have a fixed mode, ie,
+ *      the hardware is already set at boot up, and cannot be changed.  In
+ *      this case, it is more acceptable that this function just return
+ *      a copy of the currently working var (info->var). Better is to not
+ *      implement this function, as the upper layer will do the copying
+ *      of the current var for you.
+ *
+ *      Note:  This is the only function where the contents of var can be
+ *      freely adjusted after the driver has been registered. If you find
+ *      that you have code outside of this function that alters the content
+ *      of var, then you are doing something wrong.  Note also that the
+ *      contents of info->var must be left untouched at all times after
+ *      driver registration.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+    /* ... */
+    return 0;	   	
+}
+
+/**
+ *      xxxfb_set_par - Optional function. Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Using the fb_var_screeninfo in fb_info we set the resolution of the
+ *	this particular framebuffer. This function alters the par AND the
+ *	fb_fix_screeninfo stored in fb_info. It doesn't not alter var in 
+ *	fb_info since we are using that data. This means we depend on the
+ *	data in var inside fb_info to be supported by the hardware. 
+ *
+ *      This function is also used to recover/restore the hardware to a
+ *      known working state.
+ *
+ *	xxxfb_check_var is always called before xxxfb_set_par to ensure that
+ *      the contents of var is always valid.
+ *
+ *	Again if you can't change the resolution you don't need this function.
+ *
+ *      However, even if your hardware does not support mode changing,
+ *      a set_par might be needed to at least initialize the hardware to
+ *      a known working state, especially if it came back from another
+ *      process that also modifies the same hardware, such as X.
+ *
+ *      If this is the case, a combination such as the following should work:
+ *
+ *      static int xxxfb_check_var(struct fb_var_screeninfo *var,
+ *                                struct fb_info *info)
+ *      {
+ *              *var = info->var;
+ *              return 0;
+ *      }
+ *
+ *      static int xxxfb_set_par(struct fb_info *info)
+ *      {
+ *              init your hardware here
+ *      }
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int xxxfb_set_par(struct fb_info *info)
+{
+    struct xxx_par *par = info->par;
+    /* ... */
+    return 0;	
+}
+
+/**
+ *  	xxxfb_setcolreg - Optional function. Sets a color register.
+ *      @regno: Which register in the CLUT we are programming 
+ *      @red: The red value which can be up to 16 bits wide 
+ *	@green: The green value which can be up to 16 bits wide 
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported, the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ * 
+ *  	Set a single color register. The values supplied have a 16 bit
+ *  	magnitude which needs to be scaled in this function for the hardware. 
+ *	Things to take into consideration are how many color registers, if
+ *	any, are supported with the current color visual. With truecolor mode
+ *	no color palettes are supported. Here a pseudo palette is created
+ *	which we store the value in pseudo_palette in struct fb_info. For
+ *	pseudocolor mode we have a limited color palette. To deal with this
+ *	we can program what color is displayed for a particular pixel value.
+ *	DirectColor is similar in that we can program each color field. If
+ *	we have a static colormap we don't need to implement this function. 
+ * 
+ *	Returns negative errno on error, or zero on success.
+ */
+static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+    if (regno >= 256)  /* no. of hw registers */
+       return -EINVAL;
+    /*
+     * Program hardware... do anything you want with transp
+     */
+
+    /* grayscale works only partially under directcolor */
+    if (info->var.grayscale) {
+       /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+       red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+    }
+
+    /* Directcolor:
+     *   var->{color}.offset contains start of bitfield
+     *   var->{color}.length contains length of bitfield
+     *   {hardwarespecific} contains width of DAC
+     *   pseudo_palette[X] is programmed to (X << red.offset) |
+     *                                      (X << green.offset) |
+     *                                      (X << blue.offset)
+     *   RAMDAC[X] is programmed to (red, green, blue)
+     *   color depth = SUM(var->{color}.length)
+     *
+     * Pseudocolor:
+     *    var->{color}.offset is 0 unless the palette index takes less than
+     *                        bits_per_pixel bits and is stored in the upper
+     *                        bits of the pixel value
+     *    var->{color}.length is set so that 1 << length is the number of
+     *                        available palette entries
+     *    pseudo_palette is not used
+     *    RAMDAC[X] is programmed to (red, green, blue)
+     *    color depth = var->{color}.length
+     *
+     * Static pseudocolor:
+     *    same as Pseudocolor, but the RAMDAC is not programmed (read-only)
+     *
+     * Mono01/Mono10:
+     *    Has only 2 values, black on white or white on black (fg on bg),
+     *    var->{color}.offset is 0
+     *    white = (1 << var->{color}.length) - 1, black = 0
+     *    pseudo_palette is not used
+     *    RAMDAC does not exist
+     *    color depth is always 2
+     *
+     * Truecolor:
+     *    does not use RAMDAC (usually has 3 of them).
+     *    var->{color}.offset contains start of bitfield
+     *    var->{color}.length contains length of bitfield
+     *    pseudo_palette is programmed to (red << red.offset) |
+     *                                    (green << green.offset) |
+     *                                    (blue << blue.offset) |
+     *                                    (transp << transp.offset)
+     *    RAMDAC does not exist
+     *    color depth = SUM(var->{color}.length})
+     *
+     *  The color depth is used by fbcon for choosing the logo and also
+     *  for color palette transformation if color depth < 4
+     *
+     *  As can be seen from the above, the field bits_per_pixel is _NOT_
+     *  a criteria for describing the color visual.
+     *
+     *  A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor,
+     *  and higher than that, true/directcolor.  This is incorrect, one needs
+     *  to look at the fix->visual.
+     *
+     *  Another common mistake is using bits_per_pixel to calculate the color
+     *  depth.  The bits_per_pixel field does not directly translate to color
+     *  depth. You have to compute for the color depth (using the color
+     *  bitfields) and fix->visual as seen above.
+     */
+
+    /*
+     * This is the point where the color is converted to something that
+     * is acceptable by the hardware.
+     */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+    red = CNVT_TOHW(red, info->var.red.length);
+    green = CNVT_TOHW(green, info->var.green.length);
+    blue = CNVT_TOHW(blue, info->var.blue.length);
+    transp = CNVT_TOHW(transp, info->var.transp.length);
+#undef CNVT_TOHW
+    /*
+     * This is the point where the function feeds the color to the hardware
+     * palette after converting the colors to something acceptable by
+     * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and
+     * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette.
+     * If you have code that writes to the hardware CLUT, and it's not
+     * any of the above visuals, then you are doing something wrong.
+     */
+    if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
+	info->fix.visual == FB_VISUAL_TRUECOLOR)
+	    write_{red|green|blue|transp}_to_clut();
+
+    /* This is the point were you need to fill up the contents of
+     * info->pseudo_palette. This structure is used _only_ by fbcon, thus
+     * it only contains 16 entries to match the number of colors supported
+     * by the console. The pseudo_palette is used only if the visual is
+     * in directcolor or truecolor mode.  With other visuals, the
+     * pseudo_palette is not used. (This might change in the future.)
+     *
+     * The contents of the pseudo_palette is in raw pixel format.  Ie, each
+     * entry can be written directly to the framebuffer without any conversion.
+     * The pseudo_palette is (void *).  However, if using the generic
+     * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette
+     * must be casted to (u32 *) _regardless_ of the bits per pixel. If the
+     * driver is using its own drawing functions, then it can use whatever
+     * size it wants.
+     */
+    if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+	    u32 v;
+
+	    if (regno >= 16)
+		    return -EINVAL;
+
+	    v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+
+	    ((u32*)(info->pseudo_palette))[regno] = v;
+    }
+
+    /* ... */
+    return 0;
+}
+
+/**
+ *      xxxfb_pan_display - NOT a required function. Pans the display.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Pan (or wrap, depending on the `vmode' field) the display using the
+ *  	`xoffset' and `yoffset' fields of the `var' structure.
+ *  	If the values don't fit, return -EINVAL.
+ *
+ *      Returns negative errno on error, or zero on success.
+ */
+static int xxxfb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+    /*
+     * If your hardware does not support panning, _do_ _not_ implement this
+     * function. Creating a dummy function will just confuse user apps.
+     */
+
+    /*
+     * Note that even if this function is fully functional, a setting of
+     * 0 in both xpanstep and ypanstep means that this function will never
+     * get called.
+     */
+
+    /* ... */
+    return 0;
+}
+
+/**
+ *      xxxfb_blank - NOT a required function. Blanks the display.
+ *      @blank_mode: the blank mode we want. 
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
+ *      Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
+ *      e.g. a video mode which doesn't support it.
+ *
+ *      Implements VESA suspend and powerdown modes on hardware that supports
+ *      disabling hsync/vsync:
+ *
+ *      FB_BLANK_NORMAL = display is blanked, syncs are on.
+ *      FB_BLANK_HSYNC_SUSPEND = hsync off
+ *      FB_BLANK_VSYNC_SUSPEND = vsync off
+ *      FB_BLANK_POWERDOWN =  hsync and vsync off
+ *
+ *      If implementing this function, at least support FB_BLANK_UNBLANK.
+ *      Return !0 for any modes that are unimplemented.
+ *
+ */
+static int xxxfb_blank(int blank_mode, struct fb_info *info)
+{
+    /* ... */
+    return 0;
+}
+
+/* ------------ Accelerated Functions --------------------- */
+
+/*
+ * We provide our own functions if we have hardware acceleration
+ * or non packed pixel format layouts. If we have no hardware 
+ * acceleration, we can use a generic unaccelerated function. If using
+ * a pack pixel format just use the functions in cfb_*.c. Each file 
+ * has one of the three different accel functions we support.
+ */
+
+/**
+ *      xxxfb_fillrect - REQUIRED function. Can use generic routines if 
+ *		 	 non acclerated hardware and packed pixel based.
+ *			 Draws a rectangle on the screen.		
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *	@region: The structure representing the rectangular region we 
+ *		 wish to draw to.
+ *
+ *	This drawing operation places/removes a retangle on the screen 
+ *	depending on the rastering operation with the value of color which
+ *	is in the current color depth format.
+ */
+void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
+{
+/*	Meaning of struct fb_fillrect
+ *
+ *	@dx: The x and y corrdinates of the upper left hand corner of the 
+ *	@dy: area we want to draw to. 
+ *	@width: How wide the rectangle is we want to draw.
+ *	@height: How tall the rectangle is we want to draw.
+ *	@color:	The color to fill in the rectangle with. 
+ *	@rop: The raster operation. We can draw the rectangle with a COPY
+ *	      of XOR which provides erasing effect. 
+ */
+}
+
+/**
+ *      xxxfb_copyarea - REQUIRED function. Can use generic routines if
+ *                       non acclerated hardware and packed pixel based.
+ *                       Copies one area of the screen to another area.
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @area: Structure providing the data to copy the framebuffer contents
+ *	       from one region to another.
+ *
+ *      This drawing operation copies a rectangular area from one area of the
+ *	screen to another area.
+ */
+void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) 
+{
+/*
+ *      @dx: The x and y coordinates of the upper left hand corner of the
+ *	@dy: destination area on the screen.
+ *      @width: How wide the rectangle is we want to copy.
+ *      @height: How tall the rectangle is we want to copy.
+ *      @sx: The x and y coordinates of the upper left hand corner of the
+ *      @sy: source area on the screen.
+ */
+}
+
+
+/**
+ *      xxxfb_imageblit - REQUIRED function. Can use generic routines if
+ *                        non acclerated hardware and packed pixel based.
+ *                        Copies a image from system memory to the screen. 
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *	@image:	structure defining the image.
+ *
+ *      This drawing operation draws a image on the screen. It can be a 
+ *	mono image (needed for font handling) or a color image (needed for
+ *	tux). 
+ */
+void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) 
+{
+/*
+ *      @dx: The x and y coordinates of the upper left hand corner of the
+ *	@dy: destination area to place the image on the screen.
+ *      @width: How wide the image is we want to copy.
+ *      @height: How tall the image is we want to copy.
+ *      @fg_color: For mono bitmap images this is color data for     
+ *      @bg_color: the foreground and background of the image to
+ *		   write directly to the frmaebuffer.
+ *	@depth:	How many bits represent a single pixel for this image.
+ *	@data: The actual data used to construct the image on the display.
+ *	@cmap: The colormap used for color images.   
+ */
+
+/*
+ * The generic function, cfb_imageblit, expects that the bitmap scanlines are
+ * padded to the next byte.  Most hardware accelerators may require padding to
+ * the next u16 or the next u32.  If that is the case, the driver can specify
+ * this by setting info->pixmap.scan_align = 2 or 4.  See a more
+ * comprehensive description of the pixmap below.
+ */
+}
+
+/**
+ *	xxxfb_cursor - 	OPTIONAL. If your hardware lacks support
+ *			for a cursor, leave this field NULL.
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *	@cursor: structure defining the cursor to draw.
+ *
+ *      This operation is used to set or alter the properities of the
+ *	cursor.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+/*
+ *      @set: 	Which fields we are altering in struct fb_cursor 
+ *	@enable: Disable or enable the cursor 
+ *      @rop: 	The bit operation we want to do. 
+ *      @mask:  This is the cursor mask bitmap. 
+ *      @dest:  A image of the area we are going to display the cursor.
+ *		Used internally by the driver.	 
+ *      @hot:	The hot spot. 
+ *	@image:	The actual data for the cursor image.
+ *
+ *      NOTES ON FLAGS (cursor->set):
+ *
+ *      FB_CUR_SETIMAGE - the cursor image has changed (cursor->image.data)
+ *      FB_CUR_SETPOS   - the cursor position has changed (cursor->image.dx|dy)
+ *      FB_CUR_SETHOT   - the cursor hot spot has changed (cursor->hot.dx|dy)
+ *      FB_CUR_SETCMAP  - the cursor colors has changed (cursor->fg_color|bg_color)
+ *      FB_CUR_SETSHAPE - the cursor bitmask has changed (cursor->mask)
+ *      FB_CUR_SETSIZE  - the cursor size has changed (cursor->width|height)
+ *      FB_CUR_SETALL   - everything has changed
+ *
+ *      NOTES ON ROPs (cursor->rop, Raster Operation)
+ *
+ *      ROP_XOR         - cursor->image.data XOR cursor->mask
+ *      ROP_COPY        - curosr->image.data AND cursor->mask
+ *
+ *      OTHER NOTES:
+ *
+ *      - fbcon only supports a 2-color cursor (cursor->image.depth = 1)
+ *      - The fb_cursor structure, @cursor, _will_ always contain valid
+ *        fields, whether any particular bitfields in cursor->set is set
+ *        or not.
+ */
+}
+
+/**
+ *	xxxfb_rotate -  NOT a required function. If your hardware
+ *			supports rotation the whole screen then 
+ *			you would provide a hook for this. 
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *	@angle: The angle we rotate the screen.   
+ *
+ *      This operation is used to set or alter the properities of the
+ *	cursor.
+ */
+void xxxfb_rotate(struct fb_info *info, int angle)
+{
+/* Will be deprecated */
+}
+
+/**
+ *	xxxfb_sync - NOT a required function. Normally the accel engine 
+ *		     for a graphics card take a specific amount of time.
+ *		     Often we have to wait for the accelerator to finish
+ *		     its operation before we can write to the framebuffer
+ *		     so we can have consistent display output. 
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      If the driver has implemented its own hardware-based drawing function,
+ *      implementing this function is highly recommended.
+ */
+int xxxfb_sync(struct fb_info *info)
+{
+	return 0;
+}
+
+    /*
+     *  Frame buffer operations
+     */
+
+static struct fb_ops xxxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= xxxfb_open,
+	.fb_read	= xxxfb_read,
+	.fb_write	= xxxfb_write,
+	.fb_release	= xxxfb_release,
+	.fb_check_var	= xxxfb_check_var,
+	.fb_set_par	= xxxfb_set_par,
+	.fb_setcolreg	= xxxfb_setcolreg,
+	.fb_blank	= xxxfb_blank,
+	.fb_pan_display	= xxxfb_pan_display,
+	.fb_fillrect	= xxxfb_fillrect, 	/* Needed !!! */
+	.fb_copyarea	= xxxfb_copyarea,	/* Needed !!! */
+	.fb_imageblit	= xxxfb_imageblit,	/* Needed !!! */
+	.fb_cursor	= xxxfb_cursor,		/* Optional !!! */
+	.fb_rotate	= xxxfb_rotate,
+	.fb_sync	= xxxfb_sync,
+	.fb_ioctl	= xxxfb_ioctl,
+	.fb_mmap	= xxxfb_mmap,
+};
+
+/* ------------------------------------------------------------------------- */
+
+    /*
+     *  Initialization
+     */
+
+/* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
+static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+    struct fb_info *info;
+    struct xxx_par *par;
+    struct device *device = &dev->dev; /* or &pdev->dev */
+    int cmap_len, retval;	
+   
+    /*
+     * Dynamically allocate info and par
+     */
+    info = framebuffer_alloc(sizeof(struct xxx_par), device);
+
+    if (!info) {
+	    /* goto error path */
+    }
+
+    par = info->par;
+
+    /* 
+     * Here we set the screen_base to the virtual memory address
+     * for the framebuffer. Usually we obtain the resource address
+     * from the bus layer and then translate it to virtual memory
+     * space via ioremap. Consult ioport.h. 
+     */
+    info->screen_base = framebuffer_virtual_memory;
+    info->fbops = &xxxfb_ops;
+    info->fix = xxxfb_fix;
+    info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
+					    * 16-member array
+					    */
+    /*
+     * Set up flags to indicate what sort of acceleration your
+     * driver can provide (pan/wrap/copyarea/etc.) and whether it
+     * is a module -- see FBINFO_* in include/linux/fb.h
+     *
+     * If your hardware can support any of the hardware accelerated functions
+     * fbcon performance will improve if info->flags is set properly.
+     *
+     * FBINFO_HWACCEL_COPYAREA - hardware moves
+     * FBINFO_HWACCEL_FILLRECT - hardware fills
+     * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion
+     * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis
+     * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis
+     * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled
+     * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion
+     * FBINFO_MISC_TILEBLITTING - hardware can do tile blits
+     *
+     * NOTE: These are for fbcon use only.
+     */
+    info->flags = FBINFO_DEFAULT;
+
+/********************* This stage is optional ******************************/
+     /*
+     * The struct pixmap is a scratch pad for the drawing functions. This
+     * is where the monochrome bitmap is constructed by the higher layers
+     * and then passed to the accelerator.  For drivers that uses
+     * cfb_imageblit, you can skip this part.  For those that have a more
+     * rigorous requirement, this stage is needed
+     */
+
+    /* PIXMAP_SIZE should be small enough to optimize drawing, but not
+     * large enough that memory is wasted.  A safe size is
+     * (max_xres * max_font_height/8). max_xres is driver dependent,
+     * max_font_height is 32.
+     */
+    info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL);
+    if (!info->pixmap.addr) {
+	    /* goto error */
+    }
+
+    info->pixmap.size = PIXMAP_SIZE;
+
+    /*
+     * FB_PIXMAP_SYSTEM - memory is in system ram
+     * FB_PIXMAP_IO     - memory is iomapped
+     * FB_PIXMAP_SYNC   - if set, will call fb_sync() per access to pixmap,
+     *                    usually if FB_PIXMAP_IO is set.
+     *
+     * Currently, FB_PIXMAP_IO is unimplemented.
+     */
+    info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+    /*
+     * scan_align is the number of padding for each scanline.  It is in bytes.
+     * Thus for accelerators that need padding to the next u32, put 4 here.
+     */
+    info->pixmap.scan_align = 4;
+
+    /*
+     * buf_align is the amount to be padded for the buffer. For example,
+     * the i810fb needs a scan_align of 2 but expects it to be fed with
+     * dwords, so a buf_align = 4 is required.
+     */
+    info->pixmap.buf_align = 4;
+
+    /* access_align is how many bits can be accessed from the framebuffer
+     * ie. some epson cards allow 16-bit access only.  Most drivers will
+     * be safe with u32 here.
+     *
+     * NOTE: This field is currently unused.
+     */
+    info->pixmap.access_align = 32;
+/***************************** End optional stage ***************************/
+
+    /*
+     * This should give a reasonable default video mode. The following is
+     * done when we can set a video mode. 
+     */
+    if (!mode_option)
+	mode_option = "640x480@60";	 	
+
+    retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+  
+    if (!retval || retval == 4)
+	return -EINVAL;			
+
+    /* This has to be done! */
+    if (fb_alloc_cmap(&info->cmap, cmap_len, 0))
+	return -ENOMEM;
+	
+    /* 
+     * The following is done in the case of having hardware with a static 
+     * mode. If we are setting the mode ourselves we don't call this. 
+     */	
+    info->var = xxxfb_var;
+
+    /*
+     * For drivers that can...
+     */
+    xxxfb_check_var(&info->var, info);
+
+    /*
+     * Does a call to fb_set_par() before register_framebuffer needed?  This
+     * will depend on you and the hardware.  If you are sure that your driver
+     * is the only device in the system, a call to fb_set_par() is safe.
+     *
+     * Hardware in x86 systems has a VGA core.  Calling set_par() at this
+     * point will corrupt the VGA console, so it might be safer to skip a
+     * call to set_par here and just allow fbcon to do it for you.
+     */
+    /* xxxfb_set_par(info); */
+
+    if (register_framebuffer(info) < 0) {
+	fb_dealloc_cmap(&info->cmap);
+	return -EINVAL;
+    }
+    fb_info(info, "%s frame buffer device\n", info->fix.id);
+    pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */
+    return 0;
+}
+
+    /*
+     *  Cleanup
+     */
+/* static void xxxfb_remove(struct platform_device *pdev) */
+static void xxxfb_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	/* or platform_get_drvdata(pdev); */
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		/* ... */
+		framebuffer_release(info);
+	}
+}
+
+#ifdef CONFIG_PCI
+#ifdef CONFIG_PM
+/**
+ *	xxxfb_suspend - Optional but recommended function. Suspend the device.
+ *	@dev: PCI device
+ *	@msg: the suspend event code.
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct xxxfb_par *par = info->par;
+
+	/* suspend here */
+	return 0;
+}
+
+/**
+ *	xxxfb_resume - Optional but recommended function. Resume the device.
+ *	@dev: PCI device
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_resume(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct xxxfb_par *par = info->par;
+
+	/* resume here */
+	return 0;
+}
+#else
+#define xxxfb_suspend NULL
+#define xxxfb_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id xxxfb_id_table[] = {
+	{ PCI_VENDOR_ID_XXX, PCI_DEVICE_ID_XXX,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  PCI_CLASS_MASK, 0 },
+	{ 0, }
+};
+
+/* For PCI drivers */
+static struct pci_driver xxxfb_driver = {
+	.name =		"xxxfb",
+	.id_table =	xxxfb_id_table,
+	.probe =	xxxfb_probe,
+	.remove =	xxxfb_remove,
+	.suspend =      xxxfb_suspend, /* optional but recommended */
+	.resume =       xxxfb_resume,  /* optional but recommended */
+};
+
+MODULE_DEVICE_TABLE(pci, xxxfb_id_table);
+
+int __init xxxfb_init(void)
+{
+	/*
+	 *  For kernel boot options (in 'video=xxxfb:<options>' format)
+	 */
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("xxxfb", &option))
+		return -ENODEV;
+	xxxfb_setup(option);
+#endif
+
+	return pci_register_driver(&xxxfb_driver);
+}
+
+static void __exit xxxfb_exit(void)
+{
+	pci_unregister_driver(&xxxfb_driver);
+}
+#else /* non PCI, platform drivers */
+#include <linux/platform_device.h>
+/* for platform devices */
+
+#ifdef CONFIG_PM
+/**
+ *	xxxfb_suspend - Optional but recommended function. Suspend the device.
+ *	@dev: platform device
+ *	@msg: the suspend event code.
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct xxxfb_par *par = info->par;
+
+	/* suspend here */
+	return 0;
+}
+
+/**
+ *	xxxfb_resume - Optional but recommended function. Resume the device.
+ *	@dev: platform device
+ *
+ *      See Documentation/power/devices.txt for more information
+ */
+static int xxxfb_resume(struct platform_dev *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct xxxfb_par *par = info->par;
+
+	/* resume here */
+	return 0;
+}
+#else
+#define xxxfb_suspend NULL
+#define xxxfb_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_device_driver xxxfb_driver = {
+	.probe = xxxfb_probe,
+	.remove = xxxfb_remove,
+	.suspend = xxxfb_suspend, /* optional but recommended */
+	.resume = xxxfb_resume,   /* optional but recommended */
+	.driver = {
+		.name = "xxxfb",
+	},
+};
+
+static struct platform_device *xxxfb_device;
+
+#ifndef MODULE
+    /*
+     *  Setup
+     */
+
+/*
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+int __init xxxfb_setup(char *options)
+{
+    /* Parse user specified options (`video=xxxfb:') */
+}
+#endif /* MODULE */
+
+static int __init xxxfb_init(void)
+{
+	int ret;
+	/*
+	 *  For kernel boot options (in 'video=xxxfb:<options>' format)
+	 */
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("xxxfb", &option))
+		return -ENODEV;
+	xxxfb_setup(option);
+#endif
+	ret = platform_driver_register(&xxxfb_driver);
+
+	if (!ret) {
+		xxxfb_device = platform_device_register_simple("xxxfb", 0,
+								NULL, 0);
+
+		if (IS_ERR(xxxfb_device)) {
+			platform_driver_unregister(&xxxfb_driver);
+			ret = PTR_ERR(xxxfb_device);
+		}
+	}
+
+	return ret;
+}
+
+static void __exit xxxfb_exit(void)
+{
+	platform_device_unregister(xxxfb_device);
+	platform_driver_unregister(&xxxfb_driver);
+}
+#endif /* CONFIG_PCI */
+
+/* ------------------------------------------------------------------------- */
+
+
+    /*
+     *  Modularization
+     */
+
+module_init(xxxfb_init);
+module_exit(xxxfb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c
new file mode 100644
index 000000000000..1501979099dc
--- /dev/null
+++ b/drivers/video/fbdev/sm501fb.c
@@ -0,0 +1,2240 @@
+/* linux/drivers/video/sm501fb.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Vincent Sanders <vince@simtec.co.uk>
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Framebuffer driver for the Silicon Motion SM501
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
+#include "edid.h"
+
+static char *fb_mode = "640x480-16@60";
+static unsigned long default_bpp = 16;
+
+static struct fb_videomode sm501_default_mode = {
+	.refresh	= 60,
+	.xres		= 640,
+	.yres		= 480,
+	.pixclock	= 20833,
+	.left_margin	= 142,
+	.right_margin	= 13,
+	.upper_margin	= 21,
+	.lower_margin	= 1,
+	.hsync_len	= 69,
+	.vsync_len	= 3,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
+#define NR_PALETTE	256
+
+enum sm501_controller {
+	HEAD_CRT	= 0,
+	HEAD_PANEL	= 1,
+};
+
+/* SM501 memory address.
+ *
+ * This structure is used to track memory usage within the SM501 framebuffer
+ * allocation. The sm_addr field is stored as an offset as it is often used
+ * against both the physical and mapped addresses.
+ */
+struct sm501_mem {
+	unsigned long	 size;
+	unsigned long	 sm_addr;	/* offset from base of sm501 fb. */
+	void __iomem	*k_addr;
+};
+
+/* private data that is shared between all frambuffers* */
+struct sm501fb_info {
+	struct device		*dev;
+	struct fb_info		*fb[2];		/* fb info for both heads */
+	struct resource		*fbmem_res;	/* framebuffer resource */
+	struct resource		*regs_res;	/* registers resource */
+	struct resource		*regs2d_res;	/* 2d registers resource */
+	struct sm501_platdata_fb *pdata;	/* our platform data */
+
+	unsigned long		 pm_crt_ctrl;	/* pm: crt ctrl save */
+
+	int			 irq;
+	int			 swap_endian;	/* set to swap rgb=>bgr */
+	void __iomem		*regs;		/* remapped registers */
+	void __iomem		*regs2d;	/* 2d remapped registers */
+	void __iomem		*fbmem;		/* remapped framebuffer */
+	size_t			 fbmem_len;	/* length of remapped region */
+	u8 *edid_data;
+};
+
+/* per-framebuffer private data */
+struct sm501fb_par {
+	u32			 pseudo_palette[16];
+
+	enum sm501_controller	 head;
+	struct sm501_mem	 cursor;
+	struct sm501_mem	 screen;
+	struct fb_ops		 ops;
+
+	void			*store_fb;
+	void			*store_cursor;
+	void __iomem		*cursor_regs;
+	struct sm501fb_info	*info;
+};
+
+/* Helper functions */
+
+static inline int h_total(struct fb_var_screeninfo *var)
+{
+	return var->xres + var->left_margin +
+		var->right_margin + var->hsync_len;
+}
+
+static inline int v_total(struct fb_var_screeninfo *var)
+{
+	return var->yres + var->upper_margin +
+		var->lower_margin + var->vsync_len;
+}
+
+/* sm501fb_sync_regs()
+ *
+ * This call is mainly for PCI bus systems where we need to
+ * ensure that any writes to the bus are completed before the
+ * next phase, or after completing a function.
+*/
+
+static inline void sm501fb_sync_regs(struct sm501fb_info *info)
+{
+	smc501_readl(info->regs);
+}
+
+/* sm501_alloc_mem
+ *
+ * This is an attempt to lay out memory for the two framebuffers and
+ * everything else
+ *
+ * |fbmem_res->start					       fbmem_res->end|
+ * |									     |
+ * |fb[0].fix.smem_start    |	      |fb[1].fix.smem_start    |     2K	     |
+ * |-> fb[0].fix.smem_len <-| spare   |-> fb[1].fix.smem_len <-|-> cursors <-|
+ *
+ * The "spare" space is for the 2d engine data
+ * the fixed is space for the cursors (2x1Kbyte)
+ *
+ * we need to allocate memory for the 2D acceleration engine
+ * command list and the data for the engine to deal with.
+ *
+ * - all allocations must be 128bit aligned
+ * - cursors are 64x64x2 bits (1Kbyte)
+ *
+ */
+
+#define SM501_MEMF_CURSOR		(1)
+#define SM501_MEMF_PANEL		(2)
+#define SM501_MEMF_CRT			(4)
+#define SM501_MEMF_ACCEL		(8)
+
+static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
+			   unsigned int why, size_t size, u32 smem_len)
+{
+	struct sm501fb_par *par;
+	struct fb_info *fbi;
+	unsigned int ptr;
+	unsigned int end;
+
+	switch (why) {
+	case SM501_MEMF_CURSOR:
+		ptr = inf->fbmem_len - size;
+		inf->fbmem_len = ptr;	/* adjust available memory. */
+		break;
+
+	case SM501_MEMF_PANEL:
+		if (size > inf->fbmem_len)
+			return -ENOMEM;
+
+		ptr = inf->fbmem_len - size;
+		fbi = inf->fb[HEAD_CRT];
+
+		/* round down, some programs such as directfb do not draw
+		 * 0,0 correctly unless the start is aligned to a page start.
+		 */
+
+		if (ptr > 0)
+			ptr &= ~(PAGE_SIZE - 1);
+
+		if (fbi && ptr < smem_len)
+			return -ENOMEM;
+
+		break;
+
+	case SM501_MEMF_CRT:
+		ptr = 0;
+
+		/* check to see if we have panel memory allocated
+		 * which would put an limit on available memory. */
+
+		fbi = inf->fb[HEAD_PANEL];
+		if (fbi) {
+			par = fbi->par;
+			end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len;
+		} else
+			end = inf->fbmem_len;
+
+		if ((ptr + size) > end)
+			return -ENOMEM;
+
+		break;
+
+	case SM501_MEMF_ACCEL:
+		fbi = inf->fb[HEAD_CRT];
+		ptr = fbi ? smem_len : 0;
+
+		fbi = inf->fb[HEAD_PANEL];
+		if (fbi) {
+			par = fbi->par;
+			end = par->screen.sm_addr;
+		} else
+			end = inf->fbmem_len;
+
+		if ((ptr + size) > end)
+			return -ENOMEM;
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	mem->size    = size;
+	mem->sm_addr = ptr;
+	mem->k_addr  = inf->fbmem + ptr;
+
+	dev_dbg(inf->dev, "%s: result %08lx, %p - %u, %zd\n",
+		__func__, mem->sm_addr, mem->k_addr, why, size);
+
+	return 0;
+}
+
+/* sm501fb_ps_to_hz
+ *
+ * Converts a period in picoseconds to Hz.
+ *
+ * Note, we try to keep this in Hz to minimise rounding with
+ * the limited PLL settings on the SM501.
+*/
+
+static unsigned long sm501fb_ps_to_hz(unsigned long psvalue)
+{
+	unsigned long long numerator=1000000000000ULL;
+
+	/* 10^12 / picosecond period gives frequency in Hz */
+	do_div(numerator, psvalue);
+	return (unsigned long)numerator;
+}
+
+/* sm501fb_hz_to_ps is identical to the opposite transform */
+
+#define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x)
+
+/* sm501fb_setup_gamma
+ *
+ * Programs a linear 1.0 gamma ramp in case the gamma
+ * correction is enabled without programming anything else.
+*/
+
+static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
+				unsigned long palette)
+{
+	unsigned long value = 0;
+	int offset;
+
+	/* set gamma values */
+	for (offset = 0; offset < 256 * 4; offset += 4) {
+		smc501_writel(value, fbi->regs + palette + offset);
+		value += 0x010101; 	/* Advance RGB by 1,1,1.*/
+	}
+}
+
+/* sm501fb_check_var
+ *
+ * check common variables for both panel and crt
+*/
+
+static int sm501fb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *sm  = par->info;
+	unsigned long tmp;
+
+	/* check we can fit these values into the registers */
+
+	if (var->hsync_len > 255 || var->vsync_len > 63)
+		return -EINVAL;
+
+	/* hdisplay end and hsync start */
+	if ((var->xres + var->right_margin) > 4096)
+		return -EINVAL;
+
+	/* vdisplay end and vsync start */
+	if ((var->yres + var->lower_margin) > 2048)
+		return -EINVAL;
+
+	/* hard limits of device */
+
+	if (h_total(var) > 4096 || v_total(var) > 2048)
+		return -EINVAL;
+
+	/* check our line length is going to be 128 bit aligned */
+
+	tmp = (var->xres * var->bits_per_pixel) / 8;
+	if ((tmp & 15) != 0)
+		return -EINVAL;
+
+	/* check the virtual size */
+
+	if (var->xres_virtual > 4096 || var->yres_virtual > 2048)
+		return -EINVAL;
+
+	/* can cope with 8,16 or 32bpp */
+
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel == 24)
+		var->bits_per_pixel = 32;
+
+	/* set r/g/b positions and validate bpp */
+	switch(var->bits_per_pixel) {
+	case 8:
+		var->red.length		= var->bits_per_pixel;
+		var->red.offset		= 0;
+		var->green.length	= var->bits_per_pixel;
+		var->green.offset	= 0;
+		var->blue.length	= var->bits_per_pixel;
+		var->blue.offset	= 0;
+		var->transp.length	= 0;
+		var->transp.offset	= 0;
+
+		break;
+
+	case 16:
+		if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
+			var->blue.offset	= 11;
+			var->green.offset	= 5;
+			var->red.offset		= 0;
+		} else {
+			var->red.offset		= 11;
+			var->green.offset	= 5;
+			var->blue.offset	= 0;
+		}
+		var->transp.offset	= 0;
+
+		var->red.length		= 5;
+		var->green.length	= 6;
+		var->blue.length	= 5;
+		var->transp.length	= 0;
+		break;
+
+	case 32:
+		if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
+			var->transp.offset	= 0;
+			var->red.offset		= 8;
+			var->green.offset	= 16;
+			var->blue.offset	= 24;
+		} else {
+			var->transp.offset	= 24;
+			var->red.offset		= 16;
+			var->green.offset	= 8;
+			var->blue.offset	= 0;
+		}
+
+		var->red.length		= 8;
+		var->green.length	= 8;
+		var->blue.length	= 8;
+		var->transp.length	= 0;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * sm501fb_check_var_crt():
+ *
+ * check the parameters for the CRT head, and either bring them
+ * back into range, or return -EINVAL.
+*/
+
+static int sm501fb_check_var_crt(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	return sm501fb_check_var(var, info);
+}
+
+/* sm501fb_check_var_pnl():
+ *
+ * check the parameters for the CRT head, and either bring them
+ * back into range, or return -EINVAL.
+*/
+
+static int sm501fb_check_var_pnl(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	return sm501fb_check_var(var, info);
+}
+
+/* sm501fb_set_par_common
+ *
+ * set common registers for framebuffers
+*/
+
+static int sm501fb_set_par_common(struct fb_info *info,
+				  struct fb_var_screeninfo *var)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned long pixclock;      /* pixelclock in Hz */
+	unsigned long sm501pixclock; /* pixelclock the 501 can achieve in Hz */
+	unsigned int mem_type;
+	unsigned int clock_type;
+	unsigned int head_addr;
+	unsigned int smem_len;
+
+	dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n",
+		__func__, var->xres, var->yres, var->bits_per_pixel,
+		var->xres_virtual, var->yres_virtual);
+
+	switch (par->head) {
+	case HEAD_CRT:
+		mem_type = SM501_MEMF_CRT;
+		clock_type = SM501_CLOCK_V2XCLK;
+		head_addr = SM501_DC_CRT_FB_ADDR;
+		break;
+
+	case HEAD_PANEL:
+		mem_type = SM501_MEMF_PANEL;
+		clock_type = SM501_CLOCK_P2XCLK;
+		head_addr = SM501_DC_PANEL_FB_ADDR;
+		break;
+
+	default:
+		mem_type = 0;		/* stop compiler warnings */
+		head_addr = 0;
+		clock_type = 0;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+
+	case 16:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+
+	case 32:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	}
+
+	/* allocate fb memory within 501 */
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8;
+	smem_len = info->fix.line_length * var->yres_virtual;
+
+	dev_dbg(fbi->dev, "%s: line length = %u\n", __func__,
+		info->fix.line_length);
+
+	if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) {
+		dev_err(fbi->dev, "no memory available\n");
+		return -ENOMEM;
+	}
+
+	mutex_lock(&info->mm_lock);
+	info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr;
+	info->fix.smem_len   = smem_len;
+	mutex_unlock(&info->mm_lock);
+
+	info->screen_base = fbi->fbmem + par->screen.sm_addr;
+	info->screen_size = info->fix.smem_len;
+
+	/* set start of framebuffer to the screen */
+
+	smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP,
+			fbi->regs + head_addr);
+
+	/* program CRT clock  */
+
+	pixclock = sm501fb_ps_to_hz(var->pixclock);
+
+	sm501pixclock = sm501_set_clock(fbi->dev->parent, clock_type,
+					pixclock);
+
+	/* update fb layer with actual clock used */
+	var->pixclock = sm501fb_hz_to_ps(sm501pixclock);
+
+	dev_dbg(fbi->dev, "%s: pixclock(ps) = %u, pixclock(Hz)  = %lu, "
+	       "sm501pixclock = %lu,  error = %ld%%\n",
+	       __func__, var->pixclock, pixclock, sm501pixclock,
+	       ((pixclock - sm501pixclock)*100)/pixclock);
+
+	return 0;
+}
+
+/* sm501fb_set_par_geometry
+ *
+ * set the geometry registers for specified framebuffer.
+*/
+
+static void sm501fb_set_par_geometry(struct fb_info *info,
+				     struct fb_var_screeninfo *var)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	void __iomem *base = fbi->regs;
+	unsigned long reg;
+
+	if (par->head == HEAD_CRT)
+		base += SM501_DC_CRT_H_TOT;
+	else
+		base += SM501_DC_PANEL_H_TOT;
+
+	/* set framebuffer width and display width */
+
+	reg = info->fix.line_length;
+	reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
+
+	smc501_writel(reg, fbi->regs + (par->head == HEAD_CRT ?
+		    SM501_DC_CRT_FB_OFFSET :  SM501_DC_PANEL_FB_OFFSET));
+
+	/* program horizontal total */
+
+	reg  = (h_total(var) - 1) << 16;
+	reg |= (var->xres - 1);
+
+	smc501_writel(reg, base + SM501_OFF_DC_H_TOT);
+
+	/* program horizontal sync */
+
+	reg  = var->hsync_len << 16;
+	reg |= var->xres + var->right_margin - 1;
+
+	smc501_writel(reg, base + SM501_OFF_DC_H_SYNC);
+
+	/* program vertical total */
+
+	reg  = (v_total(var) - 1) << 16;
+	reg |= (var->yres - 1);
+
+	smc501_writel(reg, base + SM501_OFF_DC_V_TOT);
+
+	/* program vertical sync */
+	reg  = var->vsync_len << 16;
+	reg |= var->yres + var->lower_margin - 1;
+
+	smc501_writel(reg, base + SM501_OFF_DC_V_SYNC);
+}
+
+/* sm501fb_pan_crt
+ *
+ * pan the CRT display output within an virtual framebuffer
+*/
+
+static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned int bytes_pixel = info->var.bits_per_pixel / 8;
+	unsigned long reg;
+	unsigned long xoffs;
+
+	xoffs = var->xoffset * bytes_pixel;
+
+	reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+	reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
+	reg |= ((xoffs & 15) / bytes_pixel) << 4;
+	smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
+
+	reg = (par->screen.sm_addr + xoffs +
+	       var->yoffset * info->fix.line_length);
+	smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
+
+	sm501fb_sync_regs(fbi);
+	return 0;
+}
+
+/* sm501fb_pan_pnl
+ *
+ * pan the panel display output within an virtual framebuffer
+*/
+
+static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned long reg;
+
+	reg = var->xoffset | (info->var.xres_virtual << 16);
+	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
+
+	reg = var->yoffset | (info->var.yres_virtual << 16);
+	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
+
+	sm501fb_sync_regs(fbi);
+	return 0;
+}
+
+/* sm501fb_set_par_crt
+ *
+ * Set the CRT video mode from the fb_info structure
+*/
+
+static int sm501fb_set_par_crt(struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned long control;       /* control register */
+	int ret;
+
+	/* activate new configuration */
+
+	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
+
+	/* enable CRT DAC - note 0 is on!*/
+	sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
+
+	control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+	control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
+		    SM501_DC_CRT_CONTROL_GAMMA |
+		    SM501_DC_CRT_CONTROL_BLANK |
+		    SM501_DC_CRT_CONTROL_SEL |
+		    SM501_DC_CRT_CONTROL_CP |
+		    SM501_DC_CRT_CONTROL_TVP);
+
+	/* set the sync polarities before we check data source  */
+
+	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
+		control |= SM501_DC_CRT_CONTROL_HSP;
+
+	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
+		control |= SM501_DC_CRT_CONTROL_VSP;
+
+	if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
+		/* the head is displaying panel data... */
+
+		sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0,
+				info->fix.smem_len);
+		goto out_update;
+	}
+
+	ret = sm501fb_set_par_common(info, var);
+	if (ret) {
+		dev_err(fbi->dev, "failed to set common parameters\n");
+		return ret;
+	}
+
+	sm501fb_pan_crt(var, info);
+	sm501fb_set_par_geometry(info, var);
+
+	control |= SM501_FIFO_3;	/* fill if >3 free slots */
+
+	switch(var->bits_per_pixel) {
+	case 8:
+		control |= SM501_DC_CRT_CONTROL_8BPP;
+		break;
+
+	case 16:
+		control |= SM501_DC_CRT_CONTROL_16BPP;
+		sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE);
+		break;
+
+	case 32:
+		control |= SM501_DC_CRT_CONTROL_32BPP;
+		sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE);
+		break;
+
+	default:
+		BUG();
+	}
+
+	control |= SM501_DC_CRT_CONTROL_SEL;	/* CRT displays CRT data */
+	control |= SM501_DC_CRT_CONTROL_TE;	/* enable CRT timing */
+	control |= SM501_DC_CRT_CONTROL_ENABLE;	/* enable CRT plane */
+
+ out_update:
+	dev_dbg(fbi->dev, "new control is %08lx\n", control);
+
+	smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
+	sm501fb_sync_regs(fbi);
+
+	return 0;
+}
+
+static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
+{
+	unsigned long control;
+	void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
+	struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
+
+	control = smc501_readl(ctrl_reg);
+
+	if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
+		/* enable panel power */
+
+		control |= SM501_DC_PANEL_CONTROL_VDD;	/* FPVDDEN */
+		smc501_writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control |= SM501_DC_PANEL_CONTROL_DATA;	/* DATA */
+		smc501_writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		/* VBIASEN */
+
+		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+			else
+				control |= SM501_DC_PANEL_CONTROL_BIAS;
+
+			smc501_writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
+
+		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+			else
+				control |= SM501_DC_PANEL_CONTROL_FPEN;
+
+			smc501_writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
+	} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
+		/* disable panel power */
+		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+				control |= SM501_DC_PANEL_CONTROL_FPEN;
+			else
+				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+
+			smc501_writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
+
+		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+				control |= SM501_DC_PANEL_CONTROL_BIAS;
+			else
+				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+
+			smc501_writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
+
+		control &= ~SM501_DC_PANEL_CONTROL_DATA;
+		smc501_writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+
+		control &= ~SM501_DC_PANEL_CONTROL_VDD;
+		smc501_writel(control, ctrl_reg);
+		sm501fb_sync_regs(fbi);
+		mdelay(10);
+	}
+
+	sm501fb_sync_regs(fbi);
+}
+
+/* sm501fb_set_par_pnl
+ *
+ * Set the panel video mode from the fb_info structure
+*/
+
+static int sm501fb_set_par_pnl(struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	struct fb_var_screeninfo *var = &info->var;
+	unsigned long control;
+	unsigned long reg;
+	int ret;
+
+	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
+
+	/* activate this new configuration */
+
+	ret = sm501fb_set_par_common(info, var);
+	if (ret)
+		return ret;
+
+	sm501fb_pan_pnl(var, info);
+	sm501fb_set_par_geometry(info, var);
+
+	/* update control register */
+
+	control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL);
+	control &= (SM501_DC_PANEL_CONTROL_GAMMA |
+		    SM501_DC_PANEL_CONTROL_VDD  |
+		    SM501_DC_PANEL_CONTROL_DATA |
+		    SM501_DC_PANEL_CONTROL_BIAS |
+		    SM501_DC_PANEL_CONTROL_FPEN |
+		    SM501_DC_PANEL_CONTROL_CP |
+		    SM501_DC_PANEL_CONTROL_CK |
+		    SM501_DC_PANEL_CONTROL_HP |
+		    SM501_DC_PANEL_CONTROL_VP |
+		    SM501_DC_PANEL_CONTROL_HPD |
+		    SM501_DC_PANEL_CONTROL_VPD);
+
+	control |= SM501_FIFO_3;	/* fill if >3 free slots */
+
+	switch(var->bits_per_pixel) {
+	case 8:
+		control |= SM501_DC_PANEL_CONTROL_8BPP;
+		break;
+
+	case 16:
+		control |= SM501_DC_PANEL_CONTROL_16BPP;
+		sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE);
+		break;
+
+	case 32:
+		control |= SM501_DC_PANEL_CONTROL_32BPP;
+		sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE);
+		break;
+
+	default:
+		BUG();
+	}
+
+	smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
+
+	/* panel plane top left and bottom right location */
+
+	smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
+
+	reg  = var->xres - 1;
+	reg |= (var->yres - 1) << 16;
+
+	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
+
+	/* program panel control register */
+
+	control |= SM501_DC_PANEL_CONTROL_TE;	/* enable PANEL timing */
+	control |= SM501_DC_PANEL_CONTROL_EN;	/* enable PANEL gfx plane */
+
+	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
+		control |= SM501_DC_PANEL_CONTROL_HSP;
+
+	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
+		control |= SM501_DC_PANEL_CONTROL_VSP;
+
+	smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
+	sm501fb_sync_regs(fbi);
+
+	/* ensure the panel interface is not tristated at this point */
+
+	sm501_modify_reg(fbi->dev->parent, SM501_SYSTEM_CONTROL,
+			 0, SM501_SYSCTRL_PANEL_TRISTATE);
+
+	/* power the panel up */
+	sm501fb_panel_power(fbi, 1);
+	return 0;
+}
+
+
+/* chan_to_field
+ *
+ * convert a colour value into a field position
+ *
+ * from pxafb.c
+*/
+
+static inline unsigned int chan_to_field(unsigned int chan,
+					 struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/* sm501fb_setcolreg
+ *
+ * set the colour mapping for modes that support palettised data
+*/
+
+static int sm501fb_setcolreg(unsigned regno,
+			     unsigned red, unsigned green, unsigned blue,
+			     unsigned transp, struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	void __iomem *base = fbi->regs;
+	unsigned int val;
+
+	if (par->head == HEAD_CRT)
+		base += SM501_DC_CRT_PALETTE;
+	else
+		base += SM501_DC_PANEL_PALETTE;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/* true-colour, use pseuo-palette */
+
+		if (regno < 16) {
+			u32 *pal = par->pseudo_palette;
+
+			val  = chan_to_field(red,   &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue,  &info->var.blue);
+
+			pal[regno] = val;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			val = (red >> 8) << 16;
+			val |= (green >> 8) << 8;
+			val |= blue >> 8;
+
+			smc501_writel(val, base + (regno * 4));
+		}
+
+		break;
+
+	default:
+		return 1;   /* unknown type */
+	}
+
+	return 0;
+}
+
+/* sm501fb_blank_pnl
+ *
+ * Blank or un-blank the panel interface
+*/
+
+static int sm501fb_blank_pnl(int blank_mode, struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+
+	dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
+
+	switch (blank_mode) {
+	case FB_BLANK_POWERDOWN:
+		sm501fb_panel_power(fbi, 0);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		sm501fb_panel_power(fbi, 1);
+		break;
+
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/* sm501fb_blank_crt
+ *
+ * Blank or un-blank the crt interface
+*/
+
+static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	unsigned long ctrl;
+
+	dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
+
+	ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
+
+	switch (blank_mode) {
+	case FB_BLANK_POWERDOWN:
+		ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
+		sm501_misc_control(fbi->dev->parent, SM501_MISC_DAC_POWER, 0);
+
+	case FB_BLANK_NORMAL:
+		ctrl |= SM501_DC_CRT_CONTROL_BLANK;
+		break;
+
+	case FB_BLANK_UNBLANK:
+		ctrl &= ~SM501_DC_CRT_CONTROL_BLANK;
+		ctrl |=  SM501_DC_CRT_CONTROL_ENABLE;
+		sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	default:
+		return 1;
+
+	}
+
+	smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
+	sm501fb_sync_regs(fbi);
+
+	return 0;
+}
+
+/* sm501fb_cursor
+ *
+ * set or change the hardware cursor parameters
+*/
+
+static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	void __iomem *base = fbi->regs;
+	unsigned long hwc_addr;
+	unsigned long fg, bg;
+
+	dev_dbg(fbi->dev, "%s(%p,%p)\n", __func__, info, cursor);
+
+	if (par->head == HEAD_CRT)
+		base += SM501_DC_CRT_HWC_BASE;
+	else
+		base += SM501_DC_PANEL_HWC_BASE;
+
+	/* check not being asked to exceed capabilities */
+
+	if (cursor->image.width > 64)
+		return -EINVAL;
+
+	if (cursor->image.height > 64)
+		return -EINVAL;
+
+	if (cursor->image.depth > 1)
+		return -EINVAL;
+
+	hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR);
+
+	if (cursor->enable)
+		smc501_writel(hwc_addr | SM501_HWC_EN,
+				base + SM501_OFF_HWC_ADDR);
+	else
+		smc501_writel(hwc_addr & ~SM501_HWC_EN,
+				base + SM501_OFF_HWC_ADDR);
+
+	/* set data */
+	if (cursor->set & FB_CUR_SETPOS) {
+		unsigned int x = cursor->image.dx;
+		unsigned int y = cursor->image.dy;
+
+		if (x >= 2048 || y >= 2048 )
+			return -EINVAL;
+
+		dev_dbg(fbi->dev, "set position %d,%d\n", x, y);
+
+		//y += cursor->image.height;
+
+		smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		unsigned int bg_col = cursor->image.bg_color;
+		unsigned int fg_col = cursor->image.fg_color;
+
+		dev_dbg(fbi->dev, "%s: update cmap (%08x,%08x)\n",
+			__func__, bg_col, fg_col);
+
+		bg = ((info->cmap.red[bg_col] & 0xF8) << 8) |
+			((info->cmap.green[bg_col] & 0xFC) << 3) |
+			((info->cmap.blue[bg_col] & 0xF8) >> 3);
+
+		fg = ((info->cmap.red[fg_col] & 0xF8) << 8) |
+			((info->cmap.green[fg_col] & 0xFC) << 3) |
+			((info->cmap.blue[fg_col] & 0xF8) >> 3);
+
+		dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
+
+		smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
+		smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3);
+	}
+
+	if (cursor->set & FB_CUR_SETSIZE ||
+	    cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
+		/* SM501 cursor is a two bpp 64x64 bitmap this routine
+		 * clears it to transparent then combines the cursor
+		 * shape plane with the colour plane to set the
+		 * cursor */
+		int x, y;
+		const unsigned char *pcol = cursor->image.data;
+		const unsigned char *pmsk = cursor->mask;
+		void __iomem   *dst = par->cursor.k_addr;
+		unsigned char  dcol = 0;
+		unsigned char  dmsk = 0;
+		unsigned int   op;
+
+		dev_dbg(fbi->dev, "%s: setting shape (%d,%d)\n",
+			__func__, cursor->image.width, cursor->image.height);
+
+		for (op = 0; op < (64*64*2)/8; op+=4)
+			smc501_writel(0x0, dst + op);
+
+		for (y = 0; y < cursor->image.height; y++) {
+			for (x = 0; x < cursor->image.width; x++) {
+				if ((x % 8) == 0) {
+					dcol = *pcol++;
+					dmsk = *pmsk++;
+				} else {
+					dcol >>= 1;
+					dmsk >>= 1;
+				}
+
+				if (dmsk & 1) {
+					op = (dcol & 1) ? 1 : 3;
+					op <<= ((x % 4) * 2);
+
+					op |= readb(dst + (x / 4));
+					writeb(op, dst + (x / 4));
+				}
+			}
+			dst += (64*2)/8;
+		}
+	}
+
+	sm501fb_sync_regs(fbi);	/* ensure cursor data flushed */
+	return 0;
+}
+
+/* sm501fb_crtsrc_show
+ *
+ * device attribute code to show where the crt output is sourced from
+*/
+
+static ssize_t sm501fb_crtsrc_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	unsigned long ctrl;
+
+	ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
+	ctrl &= SM501_DC_CRT_CONTROL_SEL;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
+}
+
+/* sm501fb_crtsrc_show
+ *
+ * device attribute code to set where the crt output is sourced from
+*/
+
+static ssize_t sm501fb_crtsrc_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t len)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	enum sm501_controller head;
+	unsigned long ctrl;
+
+	if (len < 1)
+		return -EINVAL;
+
+	if (strnicmp(buf, "crt", 3) == 0)
+		head = HEAD_CRT;
+	else if (strnicmp(buf, "panel", 5) == 0)
+		head = HEAD_PANEL;
+	else
+		return -EINVAL;
+
+	dev_info(dev, "setting crt source to head %d\n", head);
+
+	ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
+
+	if (head == HEAD_CRT) {
+		ctrl |= SM501_DC_CRT_CONTROL_SEL;
+		ctrl |= SM501_DC_CRT_CONTROL_ENABLE;
+		ctrl |= SM501_DC_CRT_CONTROL_TE;
+	} else {
+		ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
+		ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
+		ctrl &= ~SM501_DC_CRT_CONTROL_TE;
+	}
+
+	smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+	sm501fb_sync_regs(info);
+
+	return len;
+}
+
+/* Prepare the device_attr for registration with sysfs later */
+static DEVICE_ATTR(crt_src, 0666, sm501fb_crtsrc_show, sm501fb_crtsrc_store);
+
+/* sm501fb_show_regs
+ *
+ * show the primary sm501 registers
+*/
+static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
+			     unsigned int start, unsigned int len)
+{
+	void __iomem *mem = info->regs;
+	char *buf = ptr;
+	unsigned int reg;
+
+	for (reg = start; reg < (len + start); reg += 4)
+		ptr += sprintf(ptr, "%08x = %08x\n", reg,
+				smc501_readl(mem + reg));
+
+	return ptr - buf;
+}
+
+/* sm501fb_debug_show_crt
+ *
+ * show the crt control and cursor registers
+*/
+
+static ssize_t sm501fb_debug_show_crt(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	char *ptr = buf;
+
+	ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_CONTROL, 0x40);
+	ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_HWC_BASE, 0x10);
+
+	return ptr - buf;
+}
+
+static DEVICE_ATTR(fbregs_crt, 0444, sm501fb_debug_show_crt, NULL);
+
+/* sm501fb_debug_show_pnl
+ *
+ * show the panel control and cursor registers
+*/
+
+static ssize_t sm501fb_debug_show_pnl(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct sm501fb_info *info = dev_get_drvdata(dev);
+	char *ptr = buf;
+
+	ptr += sm501fb_show_regs(info, ptr, 0x0, 0x40);
+	ptr += sm501fb_show_regs(info, ptr, SM501_DC_PANEL_HWC_BASE, 0x10);
+
+	return ptr - buf;
+}
+
+static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL);
+
+/* acceleration operations */
+static int sm501fb_sync(struct fb_info *info)
+{
+	int count = 1000000;
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+
+	/* wait for the 2d engine to be ready */
+	while ((count > 0) &&
+	       (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) &
+		SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
+		count--;
+
+	if (count <= 0) {
+		dev_err(info->dev, "Timeout waiting for 2d engine sync\n");
+		return 1;
+	}
+	return 0;
+}
+
+static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	int width = area->width;
+	int height = area->height;
+	int sx = area->sx;
+	int sy = area->sy;
+	int dx = area->dx;
+	int dy = area->dy;
+	unsigned long rtl = 0;
+
+	/* source clip */
+	if ((sx >= info->var.xres_virtual) ||
+	    (sy >= info->var.yres_virtual))
+		/* source Area not within virtual screen, skipping */
+		return;
+	if ((sx + width) >= info->var.xres_virtual)
+		width = info->var.xres_virtual - sx - 1;
+	if ((sy + height) >= info->var.yres_virtual)
+		height = info->var.yres_virtual - sy - 1;
+
+	/* dest clip */
+	if ((dx >= info->var.xres_virtual) ||
+	    (dy >= info->var.yres_virtual))
+		/* Destination Area not within virtual screen, skipping */
+		return;
+	if ((dx + width) >= info->var.xres_virtual)
+		width = info->var.xres_virtual - dx - 1;
+	if ((dy + height) >= info->var.yres_virtual)
+		height = info->var.yres_virtual - dy - 1;
+
+	if ((sx < dx) || (sy < dy)) {
+		rtl = 1 << 27;
+		sx += width - 1;
+		dx += width - 1;
+		sy += height - 1;
+		dy += height - 1;
+	}
+
+	if (sm501fb_sync(info))
+		return;
+
+	/* set the base addresses */
+	smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+	smc501_writel(par->screen.sm_addr,
+			fbi->regs2d + SM501_2D_DESTINATION_BASE);
+
+	/* set the window width */
+	smc501_writel((info->var.xres << 16) | info->var.xres,
+	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
+
+	/* set window stride */
+	smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+	       fbi->regs2d + SM501_2D_PITCH);
+
+	/* set data format */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 16:
+		smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 32:
+		smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	}
+
+	/* 2d compare mask */
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+
+	/* 2d mask */
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+
+	/* source and destination x y */
+	smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
+	smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
+
+	/* w/h */
+	smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+
+	/* do area move */
+	smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
+}
+
+static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	int width = rect->width, height = rect->height;
+
+	if ((rect->dx >= info->var.xres_virtual) ||
+	    (rect->dy >= info->var.yres_virtual))
+		/* Rectangle not within virtual screen, skipping */
+		return;
+	if ((rect->dx + width) >= info->var.xres_virtual)
+		width = info->var.xres_virtual - rect->dx - 1;
+	if ((rect->dy + height) >= info->var.yres_virtual)
+		height = info->var.yres_virtual - rect->dy - 1;
+
+	if (sm501fb_sync(info))
+		return;
+
+	/* set the base addresses */
+	smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+	smc501_writel(par->screen.sm_addr,
+			fbi->regs2d + SM501_2D_DESTINATION_BASE);
+
+	/* set the window width */
+	smc501_writel((info->var.xres << 16) | info->var.xres,
+	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
+
+	/* set window stride */
+	smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+	       fbi->regs2d + SM501_2D_PITCH);
+
+	/* set data format */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 16:
+		smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 32:
+		smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	}
+
+	/* 2d compare mask */
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+
+	/* 2d mask */
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+
+	/* colour */
+	smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
+
+	/* x y */
+	smc501_writel((rect->dx << 16) | rect->dy,
+			fbi->regs2d + SM501_2D_DESTINATION);
+
+	/* w/h */
+	smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+
+	/* do rectangle fill */
+	smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
+}
+
+
+static struct fb_ops sm501fb_ops_crt = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= sm501fb_check_var_crt,
+	.fb_set_par	= sm501fb_set_par_crt,
+	.fb_blank	= sm501fb_blank_crt,
+	.fb_setcolreg	= sm501fb_setcolreg,
+	.fb_pan_display	= sm501fb_pan_crt,
+	.fb_cursor	= sm501fb_cursor,
+	.fb_fillrect	= sm501fb_fillrect,
+	.fb_copyarea	= sm501fb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_sync	= sm501fb_sync,
+};
+
+static struct fb_ops sm501fb_ops_pnl = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= sm501fb_check_var_pnl,
+	.fb_set_par	= sm501fb_set_par_pnl,
+	.fb_pan_display	= sm501fb_pan_pnl,
+	.fb_blank	= sm501fb_blank_pnl,
+	.fb_setcolreg	= sm501fb_setcolreg,
+	.fb_cursor	= sm501fb_cursor,
+	.fb_fillrect	= sm501fb_fillrect,
+	.fb_copyarea	= sm501fb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_sync	= sm501fb_sync,
+};
+
+/* sm501_init_cursor
+ *
+ * initialise hw cursor parameters
+*/
+
+static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
+{
+	struct sm501fb_par *par;
+	struct sm501fb_info *info;
+	int ret;
+
+	if (fbi == NULL)
+		return 0;
+
+	par = fbi->par;
+	info = par->info;
+
+	par->cursor_regs = info->regs + reg_base;
+
+	ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024,
+			      fbi->fix.smem_len);
+	if (ret < 0)
+		return ret;
+
+	/* initialise the colour registers */
+
+	smc501_writel(par->cursor.sm_addr,
+			par->cursor_regs + SM501_OFF_HWC_ADDR);
+
+	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
+	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
+	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
+	sm501fb_sync_regs(info);
+
+	return 0;
+}
+
+/* sm501fb_info_start
+ *
+ * fills the par structure claiming resources and remapping etc.
+*/
+
+static int sm501fb_start(struct sm501fb_info *info,
+			 struct platform_device *pdev)
+{
+	struct resource	*res;
+	struct device *dev = &pdev->dev;
+	int k;
+	int ret;
+
+	info->irq = ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
+		/* we currently do not use the IRQ */
+		dev_warn(dev, "no irq for device\n");
+	}
+
+	/* allocate, reserve and remap resources for display
+	 * controller registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "no resource definition for registers\n");
+		ret = -ENOENT;
+		goto err_release;
+	}
+
+	info->regs_res = request_mem_region(res->start,
+					    resource_size(res),
+					    pdev->name);
+
+	if (info->regs_res == NULL) {
+		dev_err(dev, "cannot claim registers\n");
+		ret = -ENXIO;
+		goto err_release;
+	}
+
+	info->regs = ioremap(res->start, resource_size(res));
+	if (info->regs == NULL) {
+		dev_err(dev, "cannot remap registers\n");
+		ret = -ENXIO;
+		goto err_regs_res;
+	}
+
+	/* allocate, reserve and remap resources for 2d
+	 * controller registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res == NULL) {
+		dev_err(dev, "no resource definition for 2d registers\n");
+		ret = -ENOENT;
+		goto err_regs_map;
+	}
+
+	info->regs2d_res = request_mem_region(res->start,
+					      resource_size(res),
+					      pdev->name);
+
+	if (info->regs2d_res == NULL) {
+		dev_err(dev, "cannot claim registers\n");
+		ret = -ENXIO;
+		goto err_regs_map;
+	}
+
+	info->regs2d = ioremap(res->start, resource_size(res));
+	if (info->regs2d == NULL) {
+		dev_err(dev, "cannot remap registers\n");
+		ret = -ENXIO;
+		goto err_regs2d_res;
+	}
+
+	/* allocate, reserve resources for framebuffer */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (res == NULL) {
+		dev_err(dev, "no memory resource defined\n");
+		ret = -ENXIO;
+		goto err_regs2d_map;
+	}
+
+	info->fbmem_res = request_mem_region(res->start,
+					     resource_size(res),
+					     pdev->name);
+	if (info->fbmem_res == NULL) {
+		dev_err(dev, "cannot claim framebuffer\n");
+		ret = -ENXIO;
+		goto err_regs2d_map;
+	}
+
+	info->fbmem = ioremap(res->start, resource_size(res));
+	if (info->fbmem == NULL) {
+		dev_err(dev, "cannot remap framebuffer\n");
+		goto err_mem_res;
+	}
+
+	info->fbmem_len = resource_size(res);
+
+	/* clear framebuffer memory - avoids garbage data on unused fb */
+	memset(info->fbmem, 0, info->fbmem_len);
+
+	/* clear palette ram - undefined at power on */
+	for (k = 0; k < (256 * 3); k++)
+		smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
+
+	/* enable display controller */
+	sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
+
+	/* enable 2d controller */
+	sm501_unit_power(dev->parent, SM501_GATE_2D_ENGINE, 1);
+
+	/* setup cursors */
+	sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR);
+	sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR);
+
+	return 0; /* everything is setup */
+
+ err_mem_res:
+	release_mem_region(info->fbmem_res->start,
+			   resource_size(info->fbmem_res));
+
+ err_regs2d_map:
+	iounmap(info->regs2d);
+
+ err_regs2d_res:
+	release_mem_region(info->regs2d_res->start,
+			   resource_size(info->regs2d_res));
+
+ err_regs_map:
+	iounmap(info->regs);
+
+ err_regs_res:
+	release_mem_region(info->regs_res->start,
+			   resource_size(info->regs_res));
+
+ err_release:
+	return ret;
+}
+
+static void sm501fb_stop(struct sm501fb_info *info)
+{
+	/* disable display controller */
+	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
+
+	iounmap(info->fbmem);
+	release_mem_region(info->fbmem_res->start,
+			   resource_size(info->fbmem_res));
+
+	iounmap(info->regs2d);
+	release_mem_region(info->regs2d_res->start,
+			   resource_size(info->regs2d_res));
+
+	iounmap(info->regs);
+	release_mem_region(info->regs_res->start,
+			   resource_size(info->regs_res));
+}
+
+static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head,
+			   const char *fbname)
+{
+	struct sm501_platdata_fbsub *pd;
+	struct sm501fb_par *par = fb->par;
+	struct sm501fb_info *info = par->info;
+	unsigned long ctrl;
+	unsigned int enable;
+	int ret;
+
+	switch (head) {
+	case HEAD_CRT:
+		pd = info->pdata->fb_crt;
+		ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
+		enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
+
+		/* ensure we set the correct source register */
+		if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
+			ctrl |= SM501_DC_CRT_CONTROL_SEL;
+			smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+		}
+
+		break;
+
+	case HEAD_PANEL:
+		pd = info->pdata->fb_pnl;
+		ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL);
+		enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
+		break;
+
+	default:
+		pd = NULL;		/* stop compiler warnings */
+		ctrl = 0;
+		enable = 0;
+		BUG();
+	}
+
+	dev_info(info->dev, "fb %s %sabled at start\n",
+		 fbname, enable ? "en" : "dis");
+
+	/* check to see if our routing allows this */
+
+	if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) {
+		ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
+		smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+		enable = 0;
+	}
+
+	strlcpy(fb->fix.id, fbname, sizeof(fb->fix.id));
+
+	memcpy(&par->ops,
+	       (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
+	       sizeof(struct fb_ops));
+
+	/* update ops dependent on what we've been passed */
+
+	if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0)
+		par->ops.fb_cursor = NULL;
+
+	fb->fbops = &par->ops;
+	fb->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+
+#if defined(CONFIG_OF)
+#ifdef __BIG_ENDIAN
+	if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#else
+	if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#endif
+#endif
+	/* fixed data */
+
+	fb->fix.type		= FB_TYPE_PACKED_PIXELS;
+	fb->fix.type_aux	= 0;
+	fb->fix.xpanstep	= 1;
+	fb->fix.ypanstep	= 1;
+	fb->fix.ywrapstep	= 0;
+	fb->fix.accel		= FB_ACCEL_NONE;
+
+	/* screenmode */
+
+	fb->var.nonstd		= 0;
+	fb->var.activate	= FB_ACTIVATE_NOW;
+	fb->var.accel_flags	= 0;
+	fb->var.vmode		= FB_VMODE_NONINTERLACED;
+	fb->var.bits_per_pixel  = 16;
+
+	if (info->edid_data) {
+			/* Now build modedb from EDID */
+			fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
+			fb_videomode_to_modelist(fb->monspecs.modedb,
+						 fb->monspecs.modedb_len,
+						 &fb->modelist);
+	}
+
+	if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
+		/* TODO read the mode from the current display */
+	} else {
+		if (pd->def_mode) {
+			dev_info(info->dev, "using supplied mode\n");
+			fb_videomode_to_var(&fb->var, pd->def_mode);
+
+			fb->var.bits_per_pixel = pd->def_bpp ? pd->def_bpp : 8;
+			fb->var.xres_virtual = fb->var.xres;
+			fb->var.yres_virtual = fb->var.yres;
+		} else {
+			if (info->edid_data) {
+				ret = fb_find_mode(&fb->var, fb, fb_mode,
+					fb->monspecs.modedb,
+					fb->monspecs.modedb_len,
+					&sm501_default_mode, default_bpp);
+				/* edid_data is no longer needed, free it */
+				kfree(info->edid_data);
+			} else {
+				ret = fb_find_mode(&fb->var, fb,
+					   NULL, NULL, 0, NULL, 8);
+			}
+
+			switch (ret) {
+			case 1:
+				dev_info(info->dev, "using mode specified in "
+						"@mode\n");
+				break;
+			case 2:
+				dev_info(info->dev, "using mode specified in "
+					"@mode with ignored refresh rate\n");
+				break;
+			case 3:
+				dev_info(info->dev, "using mode default "
+					"mode\n");
+				break;
+			case 4:
+				dev_info(info->dev, "using mode from list\n");
+				break;
+			default:
+				dev_info(info->dev, "ret = %d\n", ret);
+				dev_info(info->dev, "failed to find mode\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* initialise and set the palette */
+	if (fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0)) {
+		dev_err(info->dev, "failed to allocate cmap memory\n");
+		return -ENOMEM;
+	}
+	fb_set_cmap(&fb->cmap, fb);
+
+	ret = (fb->fbops->fb_check_var)(&fb->var, fb);
+	if (ret)
+		dev_err(info->dev, "check_var() failed on initial setup?\n");
+
+	return 0;
+}
+
+/* default platform data if none is supplied (ie, PCI device) */
+
+static struct sm501_platdata_fbsub sm501fb_pdata_crt = {
+	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
+			   SM501FB_FLAG_USE_HWCURSOR |
+			   SM501FB_FLAG_USE_HWACCEL |
+			   SM501FB_FLAG_DISABLE_AT_EXIT),
+
+};
+
+static struct sm501_platdata_fbsub sm501fb_pdata_pnl = {
+	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
+			   SM501FB_FLAG_USE_HWCURSOR |
+			   SM501FB_FLAG_USE_HWACCEL |
+			   SM501FB_FLAG_DISABLE_AT_EXIT),
+};
+
+static struct sm501_platdata_fb sm501fb_def_pdata = {
+	.fb_route		= SM501_FB_OWN,
+	.fb_crt			= &sm501fb_pdata_crt,
+	.fb_pnl			= &sm501fb_pdata_pnl,
+};
+
+static char driver_name_crt[] = "sm501fb-crt";
+static char driver_name_pnl[] = "sm501fb-panel";
+
+static int sm501fb_probe_one(struct sm501fb_info *info,
+			     enum sm501_controller head)
+{
+	unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
+	struct sm501_platdata_fbsub *pd;
+	struct sm501fb_par *par;
+	struct fb_info *fbi;
+
+	pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
+
+	/* Do not initialise if we've not been given any platform data */
+	if (pd == NULL) {
+		dev_info(info->dev, "no data for fb %s (disabled)\n", name);
+		return 0;
+	}
+
+	fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
+	if (fbi == NULL) {
+		dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
+		return -ENOMEM;
+	}
+
+	par = fbi->par;
+	par->info = info;
+	par->head = head;
+	fbi->pseudo_palette = &par->pseudo_palette;
+
+	info->fb[head] = fbi;
+
+	return 0;
+}
+
+/* Free up anything allocated by sm501fb_init_fb */
+
+static void sm501_free_init_fb(struct sm501fb_info *info,
+				enum sm501_controller head)
+{
+	struct fb_info *fbi = info->fb[head];
+
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+static int sm501fb_start_one(struct sm501fb_info *info,
+			     enum sm501_controller head, const char *drvname)
+{
+	struct fb_info *fbi = info->fb[head];
+	int ret;
+
+	if (!fbi)
+		return 0;
+
+	mutex_init(&info->fb[head]->mm_lock);
+
+	ret = sm501fb_init_fb(info->fb[head], head, drvname);
+	if (ret) {
+		dev_err(info->dev, "cannot initialise fb %s\n", drvname);
+		return ret;
+	}
+
+	ret = register_framebuffer(info->fb[head]);
+	if (ret) {
+		dev_err(info->dev, "failed to register fb %s\n", drvname);
+		sm501_free_init_fb(info, head);
+		return ret;
+	}
+
+	dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
+
+	return 0;
+}
+
+static int sm501fb_probe(struct platform_device *pdev)
+{
+	struct sm501fb_info *info;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	/* allocate our framebuffers */
+
+	info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+	if (!info) {
+		dev_err(dev, "failed to allocate state\n");
+		return -ENOMEM;
+	}
+
+	info->dev = dev = &pdev->dev;
+	platform_set_drvdata(pdev, info);
+
+	if (dev->parent->platform_data) {
+		struct sm501_platdata *pd = dev->parent->platform_data;
+		info->pdata = pd->fb;
+	}
+
+	if (info->pdata == NULL) {
+		int found = 0;
+#if defined(CONFIG_OF)
+		struct device_node *np = pdev->dev.parent->of_node;
+		const u8 *prop;
+		const char *cp;
+		int len;
+
+		info->pdata = &sm501fb_def_pdata;
+		if (np) {
+			/* Get EDID */
+			cp = of_get_property(np, "mode", &len);
+			if (cp)
+				strcpy(fb_mode, cp);
+			prop = of_get_property(np, "edid", &len);
+			if (prop && len == EDID_LENGTH) {
+				info->edid_data = kmemdup(prop, EDID_LENGTH,
+							  GFP_KERNEL);
+				if (info->edid_data)
+					found = 1;
+			}
+		}
+#endif
+		if (!found) {
+			dev_info(dev, "using default configuration data\n");
+			info->pdata = &sm501fb_def_pdata;
+		}
+	}
+
+	/* probe for the presence of each panel */
+
+	ret = sm501fb_probe_one(info, HEAD_CRT);
+	if (ret < 0) {
+		dev_err(dev, "failed to probe CRT\n");
+		goto err_alloc;
+	}
+
+	ret = sm501fb_probe_one(info, HEAD_PANEL);
+	if (ret < 0) {
+		dev_err(dev, "failed to probe PANEL\n");
+		goto err_probed_crt;
+	}
+
+	if (info->fb[HEAD_PANEL] == NULL &&
+	    info->fb[HEAD_CRT] == NULL) {
+		dev_err(dev, "no framebuffers found\n");
+		goto err_alloc;
+	}
+
+	/* get the resources for both of the framebuffers */
+
+	ret = sm501fb_start(info, pdev);
+	if (ret) {
+		dev_err(dev, "cannot initialise SM501\n");
+		goto err_probed_panel;
+	}
+
+	ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
+	if (ret) {
+		dev_err(dev, "failed to start CRT\n");
+		goto err_started;
+	}
+
+	ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
+	if (ret) {
+		dev_err(dev, "failed to start Panel\n");
+		goto err_started_crt;
+	}
+
+	/* create device files */
+
+	ret = device_create_file(dev, &dev_attr_crt_src);
+	if (ret)
+		goto err_started_panel;
+
+	ret = device_create_file(dev, &dev_attr_fbregs_pnl);
+	if (ret)
+		goto err_attached_crtsrc_file;
+
+	ret = device_create_file(dev, &dev_attr_fbregs_crt);
+	if (ret)
+		goto err_attached_pnlregs_file;
+
+	/* we registered, return ok */
+	return 0;
+
+err_attached_pnlregs_file:
+	device_remove_file(dev, &dev_attr_fbregs_pnl);
+
+err_attached_crtsrc_file:
+	device_remove_file(dev, &dev_attr_crt_src);
+
+err_started_panel:
+	unregister_framebuffer(info->fb[HEAD_PANEL]);
+	sm501_free_init_fb(info, HEAD_PANEL);
+
+err_started_crt:
+	unregister_framebuffer(info->fb[HEAD_CRT]);
+	sm501_free_init_fb(info, HEAD_CRT);
+
+err_started:
+	sm501fb_stop(info);
+
+err_probed_panel:
+	framebuffer_release(info->fb[HEAD_PANEL]);
+
+err_probed_crt:
+	framebuffer_release(info->fb[HEAD_CRT]);
+
+err_alloc:
+	kfree(info);
+
+	return ret;
+}
+
+
+/*
+ *  Cleanup
+ */
+static int sm501fb_remove(struct platform_device *pdev)
+{
+	struct sm501fb_info *info = platform_get_drvdata(pdev);
+	struct fb_info	   *fbinfo_crt = info->fb[0];
+	struct fb_info	   *fbinfo_pnl = info->fb[1];
+
+	device_remove_file(&pdev->dev, &dev_attr_fbregs_crt);
+	device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
+	device_remove_file(&pdev->dev, &dev_attr_crt_src);
+
+	sm501_free_init_fb(info, HEAD_CRT);
+	sm501_free_init_fb(info, HEAD_PANEL);
+
+	unregister_framebuffer(fbinfo_crt);
+	unregister_framebuffer(fbinfo_pnl);
+
+	sm501fb_stop(info);
+	kfree(info);
+
+	framebuffer_release(fbinfo_pnl);
+	framebuffer_release(fbinfo_crt);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int sm501fb_suspend_fb(struct sm501fb_info *info,
+			      enum sm501_controller head)
+{
+	struct fb_info *fbi = info->fb[head];
+	struct sm501fb_par *par = fbi->par;
+
+	if (par->screen.size == 0)
+		return 0;
+
+	/* blank the relevant interface to ensure unit power minimised */
+	(par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
+
+	/* tell console/fb driver we are suspending */
+
+	console_lock();
+	fb_set_suspend(fbi, 1);
+	console_unlock();
+
+	/* backup copies in case chip is powered down over suspend */
+
+	par->store_fb = vmalloc(par->screen.size);
+	if (par->store_fb == NULL) {
+		dev_err(info->dev, "no memory to store screen\n");
+		return -ENOMEM;
+	}
+
+	par->store_cursor = vmalloc(par->cursor.size);
+	if (par->store_cursor == NULL) {
+		dev_err(info->dev, "no memory to store cursor\n");
+		goto err_nocursor;
+	}
+
+	dev_dbg(info->dev, "suspending screen to %p\n", par->store_fb);
+	dev_dbg(info->dev, "suspending cursor to %p\n", par->store_cursor);
+
+	memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size);
+	memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size);
+
+	return 0;
+
+ err_nocursor:
+	vfree(par->store_fb);
+	par->store_fb = NULL;
+
+	return -ENOMEM;
+}
+
+static void sm501fb_resume_fb(struct sm501fb_info *info,
+			      enum sm501_controller head)
+{
+	struct fb_info *fbi = info->fb[head];
+	struct sm501fb_par *par = fbi->par;
+
+	if (par->screen.size == 0)
+		return;
+
+	/* re-activate the configuration */
+
+	(par->ops.fb_set_par)(fbi);
+
+	/* restore the data */
+
+	dev_dbg(info->dev, "restoring screen from %p\n", par->store_fb);
+	dev_dbg(info->dev, "restoring cursor from %p\n", par->store_cursor);
+
+	if (par->store_fb)
+		memcpy_toio(par->screen.k_addr, par->store_fb,
+			    par->screen.size);
+
+	if (par->store_cursor)
+		memcpy_toio(par->cursor.k_addr, par->store_cursor,
+			    par->cursor.size);
+
+	console_lock();
+	fb_set_suspend(fbi, 0);
+	console_unlock();
+
+	vfree(par->store_fb);
+	vfree(par->store_cursor);
+}
+
+
+/* suspend and resume support */
+
+static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct sm501fb_info *info = platform_get_drvdata(pdev);
+
+	/* store crt control to resume with */
+	info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
+
+	sm501fb_suspend_fb(info, HEAD_CRT);
+	sm501fb_suspend_fb(info, HEAD_PANEL);
+
+	/* turn off the clocks, in case the device is not powered down */
+	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
+
+	return 0;
+}
+
+#define SM501_CRT_CTRL_SAVE (SM501_DC_CRT_CONTROL_TVP |        \
+			     SM501_DC_CRT_CONTROL_SEL)
+
+
+static int sm501fb_resume(struct platform_device *pdev)
+{
+	struct sm501fb_info *info = platform_get_drvdata(pdev);
+	unsigned long crt_ctrl;
+
+	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1);
+
+	/* restore the items we want to be saved for crt control */
+
+	crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
+	crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
+	crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
+	smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
+
+	sm501fb_resume_fb(info, HEAD_CRT);
+	sm501fb_resume_fb(info, HEAD_PANEL);
+
+	return 0;
+}
+
+#else
+#define sm501fb_suspend NULL
+#define sm501fb_resume  NULL
+#endif
+
+static struct platform_driver sm501fb_driver = {
+	.probe		= sm501fb_probe,
+	.remove		= sm501fb_remove,
+	.suspend	= sm501fb_suspend,
+	.resume		= sm501fb_resume,
+	.driver		= {
+		.name	= "sm501-fb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(sm501fb_driver);
+
+module_param_named(mode, fb_mode, charp, 0);
+MODULE_PARM_DESC(mode,
+	"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+module_param_named(bpp, default_bpp, ulong, 0);
+MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
+MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
+MODULE_DESCRIPTION("SM501 Framebuffer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
new file mode 100644
index 000000000000..d513ed6a49f2
--- /dev/null
+++ b/drivers/video/fbdev/smscufx.c
@@ -0,0 +1,1980 @@
+/*
+ * smscufx.c -- Framebuffer driver for SMSC UFX USB controller
+ *
+ * Copyright (C) 2011 Steve Glendinning <steve.glendinning@shawell.net>
+ * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
+ * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
+ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Based on udlfb, with work from Florian Echtler, Henrik Bjerregaard Pedersen,
+ * and others.
+ *
+ * Works well with Bernie Thompson's X DAMAGE patch to xf86-video-fbdev
+ * available from http://git.plugable.com
+ *
+ * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
+ * usb-skeleton by GregKH.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "edid.h"
+
+#define check_warn(status, fmt, args...) \
+	({ if (status < 0) pr_warn(fmt, ##args); })
+
+#define check_warn_return(status, fmt, args...) \
+	({ if (status < 0) { pr_warn(fmt, ##args); return status; } })
+
+#define check_warn_goto_error(status, fmt, args...) \
+	({ if (status < 0) { pr_warn(fmt, ##args); goto error; } })
+
+#define all_bits_set(x, bits) (((x) & (bits)) == (bits))
+
+#define USB_VENDOR_REQUEST_WRITE_REGISTER	0xA0
+#define USB_VENDOR_REQUEST_READ_REGISTER	0xA1
+
+/*
+ * TODO: Propose standard fb.h ioctl for reporting damage,
+ * using _IOWR() and one of the existing area structs from fb.h
+ * Consider these ioctls deprecated, but they're still used by the
+ * DisplayLink X server as yet - need both to be modified in tandem
+ * when new ioctl(s) are ready.
+ */
+#define UFX_IOCTL_RETURN_EDID	(0xAD)
+#define UFX_IOCTL_REPORT_DAMAGE	(0xAA)
+
+/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
+#define BULK_SIZE		(512)
+#define MAX_TRANSFER		(PAGE_SIZE*16 - BULK_SIZE)
+#define WRITES_IN_FLIGHT	(4)
+
+#define GET_URB_TIMEOUT		(HZ)
+#define FREE_URB_TIMEOUT	(HZ*2)
+
+#define BPP			2
+
+#define UFX_DEFIO_WRITE_DELAY	5 /* fb_deferred_io.delay in jiffies */
+#define UFX_DEFIO_WRITE_DISABLE	(HZ*60) /* "disable" with long delay */
+
+struct dloarea {
+	int x, y;
+	int w, h;
+};
+
+struct urb_node {
+	struct list_head entry;
+	struct ufx_data *dev;
+	struct delayed_work release_urb_work;
+	struct urb *urb;
+};
+
+struct urb_list {
+	struct list_head list;
+	spinlock_t lock;
+	struct semaphore limit_sem;
+	int available;
+	int count;
+	size_t size;
+};
+
+struct ufx_data {
+	struct usb_device *udev;
+	struct device *gdev; /* &udev->dev */
+	struct fb_info *info;
+	struct urb_list urbs;
+	struct kref kref;
+	int fb_count;
+	bool virtualized; /* true when physical usb device not present */
+	struct delayed_work free_framebuffer_work;
+	atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
+	atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
+	u8 *edid; /* null until we read edid from hw or get from sysfs */
+	size_t edid_size;
+	u32 pseudo_palette[256];
+};
+
+static struct fb_fix_screeninfo ufx_fix = {
+	.id =           "smscufx",
+	.type =         FB_TYPE_PACKED_PIXELS,
+	.visual =       FB_VISUAL_TRUECOLOR,
+	.xpanstep =     0,
+	.ypanstep =     0,
+	.ywrapstep =    0,
+	.accel =        FB_ACCEL_NONE,
+};
+
+static const u32 smscufx_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+	FBINFO_VIRTFB |	FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
+	FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
+
+static struct usb_device_id id_table[] = {
+	{USB_DEVICE(0x0424, 0x9d00),},
+	{USB_DEVICE(0x0424, 0x9d01),},
+	{},
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* module options */
+static bool console;   /* Optionally allow fbcon to consume first framebuffer */
+static bool fb_defio = true;  /* Optionally enable fb_defio mmap support */
+
+/* ufx keeps a list of urbs for efficient bulk transfers */
+static void ufx_urb_completion(struct urb *urb);
+static struct urb *ufx_get_urb(struct ufx_data *dev);
+static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len);
+static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size);
+static void ufx_free_urb_list(struct ufx_data *dev);
+
+/* reads a control register */
+static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data)
+{
+	u32 *buf = kmalloc(4, GFP_KERNEL);
+	int ret;
+
+	BUG_ON(!dev);
+
+	if (!buf)
+		return -ENOMEM;
+
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+		USB_VENDOR_REQUEST_READ_REGISTER,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+
+	le32_to_cpus(buf);
+	*data = *buf;
+	kfree(buf);
+
+	if (unlikely(ret < 0))
+		pr_warn("Failed to read register index 0x%08x\n", index);
+
+	return ret;
+}
+
+/* writes a control register */
+static int ufx_reg_write(struct ufx_data *dev, u32 index, u32 data)
+{
+	u32 *buf = kmalloc(4, GFP_KERNEL);
+	int ret;
+
+	BUG_ON(!dev);
+
+	if (!buf)
+		return -ENOMEM;
+
+	*buf = data;
+	cpu_to_le32s(buf);
+
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+		USB_VENDOR_REQUEST_WRITE_REGISTER,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+
+	kfree(buf);
+
+	if (unlikely(ret < 0))
+		pr_warn("Failed to write register index 0x%08x with value "
+			"0x%08x\n", index, data);
+
+	return ret;
+}
+
+static int ufx_reg_clear_and_set_bits(struct ufx_data *dev, u32 index,
+	u32 bits_to_clear, u32 bits_to_set)
+{
+	u32 data;
+	int status = ufx_reg_read(dev, index, &data);
+	check_warn_return(status, "ufx_reg_clear_and_set_bits error reading "
+		"0x%x", index);
+
+	data &= (~bits_to_clear);
+	data |= bits_to_set;
+
+	status = ufx_reg_write(dev, index, data);
+	check_warn_return(status, "ufx_reg_clear_and_set_bits error writing "
+		"0x%x", index);
+
+	return 0;
+}
+
+static int ufx_reg_set_bits(struct ufx_data *dev, u32 index, u32 bits)
+{
+	return ufx_reg_clear_and_set_bits(dev, index, 0, bits);
+}
+
+static int ufx_reg_clear_bits(struct ufx_data *dev, u32 index, u32 bits)
+{
+	return ufx_reg_clear_and_set_bits(dev, index, bits, 0);
+}
+
+static int ufx_lite_reset(struct ufx_data *dev)
+{
+	int status;
+	u32 value;
+
+	status = ufx_reg_write(dev, 0x3008, 0x00000001);
+	check_warn_return(status, "ufx_lite_reset error writing 0x3008");
+
+	status = ufx_reg_read(dev, 0x3008, &value);
+	check_warn_return(status, "ufx_lite_reset error reading 0x3008");
+
+	return (value == 0) ? 0 : -EIO;
+}
+
+/* If display is unblanked, then blank it */
+static int ufx_blank(struct ufx_data *dev, bool wait)
+{
+	u32 dc_ctrl, dc_sts;
+	int i;
+
+	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+	check_warn_return(status, "ufx_blank error reading 0x2004");
+
+	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+	check_warn_return(status, "ufx_blank error reading 0x2000");
+
+	/* return success if display is already blanked */
+	if ((dc_sts & 0x00000100) || (dc_ctrl & 0x00000100))
+		return 0;
+
+	/* request the DC to blank the display */
+	dc_ctrl |= 0x00000100;
+	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+	check_warn_return(status, "ufx_blank error writing 0x2000");
+
+	/* return success immediately if we don't have to wait */
+	if (!wait)
+		return 0;
+
+	for (i = 0; i < 250; i++) {
+		status = ufx_reg_read(dev, 0x2004, &dc_sts);
+		check_warn_return(status, "ufx_blank error reading 0x2004");
+
+		if (dc_sts & 0x00000100)
+			return 0;
+	}
+
+	/* timed out waiting for display to blank */
+	return -EIO;
+}
+
+/* If display is blanked, then unblank it */
+static int ufx_unblank(struct ufx_data *dev, bool wait)
+{
+	u32 dc_ctrl, dc_sts;
+	int i;
+
+	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+	check_warn_return(status, "ufx_unblank error reading 0x2004");
+
+	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+	check_warn_return(status, "ufx_unblank error reading 0x2000");
+
+	/* return success if display is already unblanked */
+	if (((dc_sts & 0x00000100) == 0) || ((dc_ctrl & 0x00000100) == 0))
+		return 0;
+
+	/* request the DC to unblank the display */
+	dc_ctrl &= ~0x00000100;
+	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+	check_warn_return(status, "ufx_unblank error writing 0x2000");
+
+	/* return success immediately if we don't have to wait */
+	if (!wait)
+		return 0;
+
+	for (i = 0; i < 250; i++) {
+		status = ufx_reg_read(dev, 0x2004, &dc_sts);
+		check_warn_return(status, "ufx_unblank error reading 0x2004");
+
+		if ((dc_sts & 0x00000100) == 0)
+			return 0;
+	}
+
+	/* timed out waiting for display to unblank */
+	return -EIO;
+}
+
+/* If display is enabled, then disable it */
+static int ufx_disable(struct ufx_data *dev, bool wait)
+{
+	u32 dc_ctrl, dc_sts;
+	int i;
+
+	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+	check_warn_return(status, "ufx_disable error reading 0x2004");
+
+	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+	check_warn_return(status, "ufx_disable error reading 0x2000");
+
+	/* return success if display is already disabled */
+	if (((dc_sts & 0x00000001) == 0) || ((dc_ctrl & 0x00000001) == 0))
+		return 0;
+
+	/* request the DC to disable the display */
+	dc_ctrl &= ~(0x00000001);
+	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+	check_warn_return(status, "ufx_disable error writing 0x2000");
+
+	/* return success immediately if we don't have to wait */
+	if (!wait)
+		return 0;
+
+	for (i = 0; i < 250; i++) {
+		status = ufx_reg_read(dev, 0x2004, &dc_sts);
+		check_warn_return(status, "ufx_disable error reading 0x2004");
+
+		if ((dc_sts & 0x00000001) == 0)
+			return 0;
+	}
+
+	/* timed out waiting for display to disable */
+	return -EIO;
+}
+
+/* If display is disabled, then enable it */
+static int ufx_enable(struct ufx_data *dev, bool wait)
+{
+	u32 dc_ctrl, dc_sts;
+	int i;
+
+	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+	check_warn_return(status, "ufx_enable error reading 0x2004");
+
+	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+	check_warn_return(status, "ufx_enable error reading 0x2000");
+
+	/* return success if display is already enabled */
+	if ((dc_sts & 0x00000001) || (dc_ctrl & 0x00000001))
+		return 0;
+
+	/* request the DC to enable the display */
+	dc_ctrl |= 0x00000001;
+	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+	check_warn_return(status, "ufx_enable error writing 0x2000");
+
+	/* return success immediately if we don't have to wait */
+	if (!wait)
+		return 0;
+
+	for (i = 0; i < 250; i++) {
+		status = ufx_reg_read(dev, 0x2004, &dc_sts);
+		check_warn_return(status, "ufx_enable error reading 0x2004");
+
+		if (dc_sts & 0x00000001)
+			return 0;
+	}
+
+	/* timed out waiting for display to enable */
+	return -EIO;
+}
+
+static int ufx_config_sys_clk(struct ufx_data *dev)
+{
+	int status = ufx_reg_write(dev, 0x700C, 0x8000000F);
+	check_warn_return(status, "error writing 0x700C");
+
+	status = ufx_reg_write(dev, 0x7014, 0x0010024F);
+	check_warn_return(status, "error writing 0x7014");
+
+	status = ufx_reg_write(dev, 0x7010, 0x00000000);
+	check_warn_return(status, "error writing 0x7010");
+
+	status = ufx_reg_clear_bits(dev, 0x700C, 0x0000000A);
+	check_warn_return(status, "error clearing PLL1 bypass in 0x700C");
+	msleep(1);
+
+	status = ufx_reg_clear_bits(dev, 0x700C, 0x80000000);
+	check_warn_return(status, "error clearing output gate in 0x700C");
+
+	return 0;
+}
+
+static int ufx_config_ddr2(struct ufx_data *dev)
+{
+	int status, i = 0;
+	u32 tmp;
+
+	status = ufx_reg_write(dev, 0x0004, 0x001F0F77);
+	check_warn_return(status, "error writing 0x0004");
+
+	status = ufx_reg_write(dev, 0x0008, 0xFFF00000);
+	check_warn_return(status, "error writing 0x0008");
+
+	status = ufx_reg_write(dev, 0x000C, 0x0FFF2222);
+	check_warn_return(status, "error writing 0x000C");
+
+	status = ufx_reg_write(dev, 0x0010, 0x00030814);
+	check_warn_return(status, "error writing 0x0010");
+
+	status = ufx_reg_write(dev, 0x0014, 0x00500019);
+	check_warn_return(status, "error writing 0x0014");
+
+	status = ufx_reg_write(dev, 0x0018, 0x020D0F15);
+	check_warn_return(status, "error writing 0x0018");
+
+	status = ufx_reg_write(dev, 0x001C, 0x02532305);
+	check_warn_return(status, "error writing 0x001C");
+
+	status = ufx_reg_write(dev, 0x0020, 0x0B030905);
+	check_warn_return(status, "error writing 0x0020");
+
+	status = ufx_reg_write(dev, 0x0024, 0x00000827);
+	check_warn_return(status, "error writing 0x0024");
+
+	status = ufx_reg_write(dev, 0x0028, 0x00000000);
+	check_warn_return(status, "error writing 0x0028");
+
+	status = ufx_reg_write(dev, 0x002C, 0x00000042);
+	check_warn_return(status, "error writing 0x002C");
+
+	status = ufx_reg_write(dev, 0x0030, 0x09520000);
+	check_warn_return(status, "error writing 0x0030");
+
+	status = ufx_reg_write(dev, 0x0034, 0x02223314);
+	check_warn_return(status, "error writing 0x0034");
+
+	status = ufx_reg_write(dev, 0x0038, 0x00430043);
+	check_warn_return(status, "error writing 0x0038");
+
+	status = ufx_reg_write(dev, 0x003C, 0xF00F000F);
+	check_warn_return(status, "error writing 0x003C");
+
+	status = ufx_reg_write(dev, 0x0040, 0xF380F00F);
+	check_warn_return(status, "error writing 0x0040");
+
+	status = ufx_reg_write(dev, 0x0044, 0xF00F0496);
+	check_warn_return(status, "error writing 0x0044");
+
+	status = ufx_reg_write(dev, 0x0048, 0x03080406);
+	check_warn_return(status, "error writing 0x0048");
+
+	status = ufx_reg_write(dev, 0x004C, 0x00001000);
+	check_warn_return(status, "error writing 0x004C");
+
+	status = ufx_reg_write(dev, 0x005C, 0x00000007);
+	check_warn_return(status, "error writing 0x005C");
+
+	status = ufx_reg_write(dev, 0x0100, 0x54F00012);
+	check_warn_return(status, "error writing 0x0100");
+
+	status = ufx_reg_write(dev, 0x0104, 0x00004012);
+	check_warn_return(status, "error writing 0x0104");
+
+	status = ufx_reg_write(dev, 0x0118, 0x40404040);
+	check_warn_return(status, "error writing 0x0118");
+
+	status = ufx_reg_write(dev, 0x0000, 0x00000001);
+	check_warn_return(status, "error writing 0x0000");
+
+	while (i++ < 500) {
+		status = ufx_reg_read(dev, 0x0000, &tmp);
+		check_warn_return(status, "error reading 0x0000");
+
+		if (all_bits_set(tmp, 0xC0000000))
+			return 0;
+	}
+
+	pr_err("DDR2 initialisation timed out, reg 0x0000=0x%08x", tmp);
+	return -ETIMEDOUT;
+}
+
+struct pll_values {
+	u32 div_r0;
+	u32 div_f0;
+	u32 div_q0;
+	u32 range0;
+	u32 div_r1;
+	u32 div_f1;
+	u32 div_q1;
+	u32 range1;
+};
+
+static u32 ufx_calc_range(u32 ref_freq)
+{
+	if (ref_freq >= 88000000)
+		return 7;
+
+	if (ref_freq >= 54000000)
+		return 6;
+
+	if (ref_freq >= 34000000)
+		return 5;
+
+	if (ref_freq >= 21000000)
+		return 4;
+
+	if (ref_freq >= 13000000)
+		return 3;
+
+	if (ref_freq >= 8000000)
+		return 2;
+
+	return 1;
+}
+
+/* calculates PLL divider settings for a desired target frequency */
+static void ufx_calc_pll_values(const u32 clk_pixel_pll, struct pll_values *asic_pll)
+{
+	const u32 ref_clk = 25000000;
+	u32 div_r0, div_f0, div_q0, div_r1, div_f1, div_q1;
+	u32 min_error = clk_pixel_pll;
+
+	for (div_r0 = 1; div_r0 <= 32; div_r0++) {
+		u32 ref_freq0 = ref_clk / div_r0;
+		if (ref_freq0 < 5000000)
+			break;
+
+		if (ref_freq0 > 200000000)
+			continue;
+
+		for (div_f0 = 1; div_f0 <= 256; div_f0++) {
+			u32 vco_freq0 = ref_freq0 * div_f0;
+
+			if (vco_freq0 < 350000000)
+				continue;
+
+			if (vco_freq0 > 700000000)
+				break;
+
+			for (div_q0 = 0; div_q0 < 7; div_q0++) {
+				u32 pllout_freq0 = vco_freq0 / (1 << div_q0);
+
+				if (pllout_freq0 < 5000000)
+					break;
+
+				if (pllout_freq0 > 200000000)
+					continue;
+
+				for (div_r1 = 1; div_r1 <= 32; div_r1++) {
+					u32 ref_freq1 = pllout_freq0 / div_r1;
+
+					if (ref_freq1 < 5000000)
+						break;
+
+					for (div_f1 = 1; div_f1 <= 256; div_f1++) {
+						u32 vco_freq1 = ref_freq1 * div_f1;
+
+						if (vco_freq1 < 350000000)
+							continue;
+
+						if (vco_freq1 > 700000000)
+							break;
+
+						for (div_q1 = 0; div_q1 < 7; div_q1++) {
+							u32 pllout_freq1 = vco_freq1 / (1 << div_q1);
+							int error = abs(pllout_freq1 - clk_pixel_pll);
+
+							if (pllout_freq1 < 5000000)
+								break;
+
+							if (pllout_freq1 > 700000000)
+								continue;
+
+							if (error < min_error) {
+								min_error = error;
+
+								/* final returned value is equal to calculated value - 1
+								 * because a value of 0 = divide by 1 */
+								asic_pll->div_r0 = div_r0 - 1;
+								asic_pll->div_f0 = div_f0 - 1;
+								asic_pll->div_q0 = div_q0;
+								asic_pll->div_r1 = div_r1 - 1;
+								asic_pll->div_f1 = div_f1 - 1;
+								asic_pll->div_q1 = div_q1;
+
+								asic_pll->range0 = ufx_calc_range(ref_freq0);
+								asic_pll->range1 = ufx_calc_range(ref_freq1);
+
+								if (min_error == 0)
+									return;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+/* sets analog bit PLL configuration values */
+static int ufx_config_pix_clk(struct ufx_data *dev, u32 pixclock)
+{
+	struct pll_values asic_pll = {0};
+	u32 value, clk_pixel, clk_pixel_pll;
+	int status;
+
+	/* convert pixclock (in ps) to frequency (in Hz) */
+	clk_pixel = PICOS2KHZ(pixclock) * 1000;
+	pr_debug("pixclock %d ps = clk_pixel %d Hz", pixclock, clk_pixel);
+
+	/* clk_pixel = 1/2 clk_pixel_pll */
+	clk_pixel_pll = clk_pixel * 2;
+
+	ufx_calc_pll_values(clk_pixel_pll, &asic_pll);
+
+	/* Keep BYPASS and RESET signals asserted until configured */
+	status = ufx_reg_write(dev, 0x7000, 0x8000000F);
+	check_warn_return(status, "error writing 0x7000");
+
+	value = (asic_pll.div_f1 | (asic_pll.div_r1 << 8) |
+		(asic_pll.div_q1 << 16) | (asic_pll.range1 << 20));
+	status = ufx_reg_write(dev, 0x7008, value);
+	check_warn_return(status, "error writing 0x7008");
+
+	value = (asic_pll.div_f0 | (asic_pll.div_r0 << 8) |
+		(asic_pll.div_q0 << 16) | (asic_pll.range0 << 20));
+	status = ufx_reg_write(dev, 0x7004, value);
+	check_warn_return(status, "error writing 0x7004");
+
+	status = ufx_reg_clear_bits(dev, 0x7000, 0x00000005);
+	check_warn_return(status,
+		"error clearing PLL0 bypass bits in 0x7000");
+	msleep(1);
+
+	status = ufx_reg_clear_bits(dev, 0x7000, 0x0000000A);
+	check_warn_return(status,
+		"error clearing PLL1 bypass bits in 0x7000");
+	msleep(1);
+
+	status = ufx_reg_clear_bits(dev, 0x7000, 0x80000000);
+	check_warn_return(status, "error clearing gate bits in 0x7000");
+
+	return 0;
+}
+
+static int ufx_set_vid_mode(struct ufx_data *dev, struct fb_var_screeninfo *var)
+{
+	u32 temp;
+	u16 h_total, h_active, h_blank_start, h_blank_end, h_sync_start, h_sync_end;
+	u16 v_total, v_active, v_blank_start, v_blank_end, v_sync_start, v_sync_end;
+
+	int status = ufx_reg_write(dev, 0x8028, 0);
+	check_warn_return(status, "ufx_set_vid_mode error disabling RGB pad");
+
+	status = ufx_reg_write(dev, 0x8024, 0);
+	check_warn_return(status, "ufx_set_vid_mode error disabling VDAC");
+
+	/* shut everything down before changing timing */
+	status = ufx_blank(dev, true);
+	check_warn_return(status, "ufx_set_vid_mode error blanking display");
+
+	status = ufx_disable(dev, true);
+	check_warn_return(status, "ufx_set_vid_mode error disabling display");
+
+	status = ufx_config_pix_clk(dev, var->pixclock);
+	check_warn_return(status, "ufx_set_vid_mode error configuring pixclock");
+
+	status = ufx_reg_write(dev, 0x2000, 0x00000104);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2000");
+
+	/* set horizontal timings */
+	h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+	h_active = var->xres;
+	h_blank_start = var->xres + var->right_margin;
+	h_blank_end = var->xres + var->right_margin + var->hsync_len;
+	h_sync_start = var->xres + var->right_margin;
+	h_sync_end = var->xres + var->right_margin + var->hsync_len;
+
+	temp = ((h_total - 1) << 16) | (h_active - 1);
+	status = ufx_reg_write(dev, 0x2008, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2008");
+
+	temp = ((h_blank_start - 1) << 16) | (h_blank_end - 1);
+	status = ufx_reg_write(dev, 0x200C, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x200C");
+
+	temp = ((h_sync_start - 1) << 16) | (h_sync_end - 1);
+	status = ufx_reg_write(dev, 0x2010, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2010");
+
+	/* set vertical timings */
+	v_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
+	v_active = var->yres;
+	v_blank_start = var->yres + var->lower_margin;
+	v_blank_end = var->yres + var->lower_margin + var->vsync_len;
+	v_sync_start = var->yres + var->lower_margin;
+	v_sync_end = var->yres + var->lower_margin + var->vsync_len;
+
+	temp = ((v_total - 1) << 16) | (v_active - 1);
+	status = ufx_reg_write(dev, 0x2014, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2014");
+
+	temp = ((v_blank_start - 1) << 16) | (v_blank_end - 1);
+	status = ufx_reg_write(dev, 0x2018, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2018");
+
+	temp = ((v_sync_start - 1) << 16) | (v_sync_end - 1);
+	status = ufx_reg_write(dev, 0x201C, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x201C");
+
+	status = ufx_reg_write(dev, 0x2020, 0x00000000);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2020");
+
+	status = ufx_reg_write(dev, 0x2024, 0x00000000);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2024");
+
+	/* Set the frame length register (#pix * 2 bytes/pixel) */
+	temp = var->xres * var->yres * 2;
+	temp = (temp + 7) & (~0x7);
+	status = ufx_reg_write(dev, 0x2028, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2028");
+
+	/* enable desired output interface & disable others */
+	status = ufx_reg_write(dev, 0x2040, 0);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
+
+	status = ufx_reg_write(dev, 0x2044, 0);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2044");
+
+	status = ufx_reg_write(dev, 0x2048, 0);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2048");
+
+	/* set the sync polarities & enable bit */
+	temp = 0x00000001;
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		temp |= 0x00000010;
+
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		temp |= 0x00000008;
+
+	status = ufx_reg_write(dev, 0x2040, temp);
+	check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
+
+	/* start everything back up */
+	status = ufx_enable(dev, true);
+	check_warn_return(status, "ufx_set_vid_mode error enabling display");
+
+	/* Unblank the display */
+	status = ufx_unblank(dev, true);
+	check_warn_return(status, "ufx_set_vid_mode error unblanking display");
+
+	/* enable RGB pad */
+	status = ufx_reg_write(dev, 0x8028, 0x00000003);
+	check_warn_return(status, "ufx_set_vid_mode error enabling RGB pad");
+
+	/* enable VDAC */
+	status = ufx_reg_write(dev, 0x8024, 0x00000007);
+	check_warn_return(status, "ufx_set_vid_mode error enabling VDAC");
+
+	return 0;
+}
+
+static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long page, pos;
+
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	if (size > info->fix.smem_len)
+		return -EINVAL;
+	if (offset > info->fix.smem_len - size)
+		return -EINVAL;
+
+	pos = (unsigned long)info->fix.smem_start + offset;
+
+	pr_debug("mmap() framebuffer addr:%lu size:%lu\n",
+		  pos, size);
+
+	while (size > 0) {
+		page = vmalloc_to_pfn((void *)pos);
+		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	return 0;
+}
+
+static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y,
+	int width, int height)
+{
+	size_t packed_line_len = ALIGN((width * 2), 4);
+	size_t packed_rect_len = packed_line_len * height;
+	int line;
+
+	BUG_ON(!dev);
+	BUG_ON(!dev->info);
+
+	/* command word */
+	*((u32 *)&cmd[0]) = cpu_to_le32(0x01);
+
+	/* length word */
+	*((u32 *)&cmd[2]) = cpu_to_le32(packed_rect_len + 16);
+
+	cmd[4] = cpu_to_le16(x);
+	cmd[5] = cpu_to_le16(y);
+	cmd[6] = cpu_to_le16(width);
+	cmd[7] = cpu_to_le16(height);
+
+	/* frame base address */
+	*((u32 *)&cmd[8]) = cpu_to_le32(0);
+
+	/* color mode and horizontal resolution */
+	cmd[10] = cpu_to_le16(0x4000 | dev->info->var.xres);
+
+	/* vertical resolution */
+	cmd[11] = cpu_to_le16(dev->info->var.yres);
+
+	/* packed data */
+	for (line = 0; line < height; line++) {
+		const int line_offset = dev->info->fix.line_length * (y + line);
+		const int byte_offset = line_offset + (x * BPP);
+		memcpy(&cmd[(24 + (packed_line_len * line)) / 2],
+			(char *)dev->info->fix.smem_start + byte_offset, width * BPP);
+	}
+}
+
+static int ufx_handle_damage(struct ufx_data *dev, int x, int y,
+	int width, int height)
+{
+	size_t packed_line_len = ALIGN((width * 2), 4);
+	int len, status, urb_lines, start_line = 0;
+
+	if ((width <= 0) || (height <= 0) ||
+	    (x + width > dev->info->var.xres) ||
+	    (y + height > dev->info->var.yres))
+		return -EINVAL;
+
+	if (!atomic_read(&dev->usb_active))
+		return 0;
+
+	while (start_line < height) {
+		struct urb *urb = ufx_get_urb(dev);
+		if (!urb) {
+			pr_warn("ufx_handle_damage unable to get urb");
+			return 0;
+		}
+
+		/* assume we have enough space to transfer at least one line */
+		BUG_ON(urb->transfer_buffer_length < (24 + (width * 2)));
+
+		/* calculate the maximum number of lines we could fit in */
+		urb_lines = (urb->transfer_buffer_length - 24) / packed_line_len;
+
+		/* but we might not need this many */
+		urb_lines = min(urb_lines, (height - start_line));
+
+		memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
+
+		ufx_raw_rect(dev, urb->transfer_buffer, x, (y + start_line), width, urb_lines);
+		len = 24 + (packed_line_len * urb_lines);
+
+		status = ufx_submit_urb(dev, urb, len);
+		check_warn_return(status, "Error submitting URB");
+
+		start_line += urb_lines;
+	}
+
+	return 0;
+}
+
+/* Path triggered by usermode clients who write to filesystem
+ * e.g. cat filename > /dev/fb1
+ * Not used by X Windows or text-mode console. But useful for testing.
+ * Slow because of extra copy and we must assume all pixels dirty. */
+static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf,
+			  size_t count, loff_t *ppos)
+{
+	ssize_t result;
+	struct ufx_data *dev = info->par;
+	u32 offset = (u32) *ppos;
+
+	result = fb_sys_write(info, buf, count, ppos);
+
+	if (result > 0) {
+		int start = max((int)(offset / info->fix.line_length), 0);
+		int lines = min((u32)((result / info->fix.line_length) + 1),
+				(u32)info->var.yres);
+
+		ufx_handle_damage(dev, 0, start, info->var.xres, lines);
+	}
+
+	return result;
+}
+
+static void ufx_ops_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+
+	struct ufx_data *dev = info->par;
+
+	sys_copyarea(info, area);
+
+	ufx_handle_damage(dev, area->dx, area->dy,
+			area->width, area->height);
+}
+
+static void ufx_ops_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	struct ufx_data *dev = info->par;
+
+	sys_imageblit(info, image);
+
+	ufx_handle_damage(dev, image->dx, image->dy,
+			image->width, image->height);
+}
+
+static void ufx_ops_fillrect(struct fb_info *info,
+			  const struct fb_fillrect *rect)
+{
+	struct ufx_data *dev = info->par;
+
+	sys_fillrect(info, rect);
+
+	ufx_handle_damage(dev, rect->dx, rect->dy, rect->width,
+			      rect->height);
+}
+
+/* NOTE: fb_defio.c is holding info->fbdefio.mutex
+ *   Touching ANY framebuffer memory that triggers a page fault
+ *   in fb_defio will cause a deadlock, when it also tries to
+ *   grab the same mutex. */
+static void ufx_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	struct page *cur;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct ufx_data *dev = info->par;
+
+	if (!fb_defio)
+		return;
+
+	if (!atomic_read(&dev->usb_active))
+		return;
+
+	/* walk the written page list and render each to device */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+		/* create a rectangle of full screen width that encloses the
+		 * entire dirty framebuffer page */
+		const int x = 0;
+		const int width = dev->info->var.xres;
+		const int y = (cur->index << PAGE_SHIFT) / (width * 2);
+		int height = (PAGE_SIZE / (width * 2)) + 1;
+		height = min(height, (int)(dev->info->var.yres - y));
+
+		BUG_ON(y >= dev->info->var.yres);
+		BUG_ON((y + height) > dev->info->var.yres);
+
+		ufx_handle_damage(dev, x, y, width, height);
+	}
+}
+
+static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg)
+{
+	struct ufx_data *dev = info->par;
+	struct dloarea *area = NULL;
+
+	if (!atomic_read(&dev->usb_active))
+		return 0;
+
+	/* TODO: Update X server to get this from sysfs instead */
+	if (cmd == UFX_IOCTL_RETURN_EDID) {
+		u8 __user *edid = (u8 __user *)arg;
+		if (copy_to_user(edid, dev->edid, dev->edid_size))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+	if (cmd == UFX_IOCTL_REPORT_DAMAGE) {
+		/* If we have a damage-aware client, turn fb_defio "off"
+		 * To avoid perf imact of unnecessary page fault handling.
+		 * Done by resetting the delay for this fb_info to a very
+		 * long period. Pages will become writable and stay that way.
+		 * Reset to normal value when all clients have closed this fb.
+		 */
+		if (info->fbdefio)
+			info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE;
+
+		area = (struct dloarea *)arg;
+
+		if (area->x < 0)
+			area->x = 0;
+
+		if (area->x > info->var.xres)
+			area->x = info->var.xres;
+
+		if (area->y < 0)
+			area->y = 0;
+
+		if (area->y > info->var.yres)
+			area->y = info->var.yres;
+
+		ufx_handle_damage(dev, area->x, area->y, area->w, area->h);
+	}
+
+	return 0;
+}
+
+/* taken from vesafb */
+static int
+ufx_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
+	       unsigned blue, unsigned transp, struct fb_info *info)
+{
+	int err = 0;
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	if (regno < 16) {
+		if (info->var.red.offset == 10) {
+			/* 1:5:5:5 */
+			((u32 *) (info->pseudo_palette))[regno] =
+			    ((red & 0xf800) >> 1) |
+			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
+		} else {
+			/* 0:5:6:5 */
+			((u32 *) (info->pseudo_palette))[regno] =
+			    ((red & 0xf800)) |
+			    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+		}
+	}
+
+	return err;
+}
+
+/* It's common for several clients to have framebuffer open simultaneously.
+ * e.g. both fbcon and X. Makes things interesting.
+ * Assumes caller is holding info->lock (for open and release at least) */
+static int ufx_ops_open(struct fb_info *info, int user)
+{
+	struct ufx_data *dev = info->par;
+
+	/* fbcon aggressively connects to first framebuffer it finds,
+	 * preventing other clients (X) from working properly. Usually
+	 * not what the user wants. Fail by default with option to enable. */
+	if (user == 0 && !console)
+		return -EBUSY;
+
+	/* If the USB device is gone, we don't accept new opens */
+	if (dev->virtualized)
+		return -ENODEV;
+
+	dev->fb_count++;
+
+	kref_get(&dev->kref);
+
+	if (fb_defio && (info->fbdefio == NULL)) {
+		/* enable defio at last moment if not disabled by client */
+
+		struct fb_deferred_io *fbdefio;
+
+		fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
+
+		if (fbdefio) {
+			fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
+			fbdefio->deferred_io = ufx_dpy_deferred_io;
+		}
+
+		info->fbdefio = fbdefio;
+		fb_deferred_io_init(info);
+	}
+
+	pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d",
+		info->node, user, info, dev->fb_count);
+
+	return 0;
+}
+
+/*
+ * Called when all client interfaces to start transactions have been disabled,
+ * and all references to our device instance (ufx_data) are released.
+ * Every transaction must have a reference, so we know are fully spun down
+ */
+static void ufx_free(struct kref *kref)
+{
+	struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
+
+	/* this function will wait for all in-flight urbs to complete */
+	if (dev->urbs.count > 0)
+		ufx_free_urb_list(dev);
+
+	pr_debug("freeing ufx_data %p", dev);
+
+	kfree(dev);
+}
+
+static void ufx_release_urb_work(struct work_struct *work)
+{
+	struct urb_node *unode = container_of(work, struct urb_node,
+					      release_urb_work.work);
+
+	up(&unode->dev->urbs.limit_sem);
+}
+
+static void ufx_free_framebuffer_work(struct work_struct *work)
+{
+	struct ufx_data *dev = container_of(work, struct ufx_data,
+					    free_framebuffer_work.work);
+	struct fb_info *info = dev->info;
+	int node = info->node;
+
+	unregister_framebuffer(info);
+
+	if (info->cmap.len != 0)
+		fb_dealloc_cmap(&info->cmap);
+	if (info->monspecs.modedb)
+		fb_destroy_modedb(info->monspecs.modedb);
+	if (info->screen_base)
+		vfree(info->screen_base);
+
+	fb_destroy_modelist(&info->modelist);
+
+	dev->info = NULL;
+
+	/* Assume info structure is freed after this point */
+	framebuffer_release(info);
+
+	pr_debug("fb_info for /dev/fb%d has been freed", node);
+
+	/* ref taken in probe() as part of registering framebfufer */
+	kref_put(&dev->kref, ufx_free);
+}
+
+/*
+ * Assumes caller is holding info->lock mutex (for open and release at least)
+ */
+static int ufx_ops_release(struct fb_info *info, int user)
+{
+	struct ufx_data *dev = info->par;
+
+	dev->fb_count--;
+
+	/* We can't free fb_info here - fbmem will touch it when we return */
+	if (dev->virtualized && (dev->fb_count == 0))
+		schedule_delayed_work(&dev->free_framebuffer_work, HZ);
+
+	if ((dev->fb_count == 0) && (info->fbdefio)) {
+		fb_deferred_io_cleanup(info);
+		kfree(info->fbdefio);
+		info->fbdefio = NULL;
+		info->fbops->fb_mmap = ufx_ops_mmap;
+	}
+
+	pr_debug("released /dev/fb%d user=%d count=%d",
+		  info->node, user, dev->fb_count);
+
+	kref_put(&dev->kref, ufx_free);
+
+	return 0;
+}
+
+/* Check whether a video mode is supported by the chip
+ * We start from monitor's modes, so don't need to filter that here */
+static int ufx_is_valid_mode(struct fb_videomode *mode,
+		struct fb_info *info)
+{
+	if ((mode->xres * mode->yres) > (2048 * 1152)) {
+		pr_debug("%dx%d too many pixels",
+		       mode->xres, mode->yres);
+		return 0;
+	}
+
+	if (mode->pixclock < 5000) {
+		pr_debug("%dx%d %dps pixel clock too fast",
+		       mode->xres, mode->yres, mode->pixclock);
+		return 0;
+	}
+
+	pr_debug("%dx%d (pixclk %dps %dMHz) valid mode", mode->xres, mode->yres,
+		mode->pixclock, (1000000 / mode->pixclock));
+	return 1;
+}
+
+static void ufx_var_color_format(struct fb_var_screeninfo *var)
+{
+	const struct fb_bitfield red = { 11, 5, 0 };
+	const struct fb_bitfield green = { 5, 6, 0 };
+	const struct fb_bitfield blue = { 0, 5, 0 };
+
+	var->bits_per_pixel = 16;
+	var->red = red;
+	var->green = green;
+	var->blue = blue;
+}
+
+static int ufx_ops_check_var(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct fb_videomode mode;
+
+	/* TODO: support dynamically changing framebuffer size */
+	if ((var->xres * var->yres * 2) > info->fix.smem_len)
+		return -EINVAL;
+
+	/* set device-specific elements of var unrelated to mode */
+	ufx_var_color_format(var);
+
+	fb_var_to_videomode(&mode, var);
+
+	if (!ufx_is_valid_mode(&mode, info))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ufx_ops_set_par(struct fb_info *info)
+{
+	struct ufx_data *dev = info->par;
+	int result;
+	u16 *pix_framebuffer;
+	int i;
+
+	pr_debug("set_par mode %dx%d", info->var.xres, info->var.yres);
+	result = ufx_set_vid_mode(dev, &info->var);
+
+	if ((result == 0) && (dev->fb_count == 0)) {
+		/* paint greenscreen */
+		pix_framebuffer = (u16 *) info->screen_base;
+		for (i = 0; i < info->fix.smem_len / 2; i++)
+			pix_framebuffer[i] = 0x37e6;
+
+		ufx_handle_damage(dev, 0, 0, info->var.xres, info->var.yres);
+	}
+
+	/* re-enable defio if previously disabled by damage tracking */
+	if (info->fbdefio)
+		info->fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
+
+	return result;
+}
+
+/* In order to come back from full DPMS off, we need to set the mode again */
+static int ufx_ops_blank(int blank_mode, struct fb_info *info)
+{
+	struct ufx_data *dev = info->par;
+	ufx_set_vid_mode(dev, &info->var);
+	return 0;
+}
+
+static struct fb_ops ufx_ops = {
+	.owner = THIS_MODULE,
+	.fb_read = fb_sys_read,
+	.fb_write = ufx_ops_write,
+	.fb_setcolreg = ufx_ops_setcolreg,
+	.fb_fillrect = ufx_ops_fillrect,
+	.fb_copyarea = ufx_ops_copyarea,
+	.fb_imageblit = ufx_ops_imageblit,
+	.fb_mmap = ufx_ops_mmap,
+	.fb_ioctl = ufx_ops_ioctl,
+	.fb_open = ufx_ops_open,
+	.fb_release = ufx_ops_release,
+	.fb_blank = ufx_ops_blank,
+	.fb_check_var = ufx_ops_check_var,
+	.fb_set_par = ufx_ops_set_par,
+};
+
+/* Assumes &info->lock held by caller
+ * Assumes no active clients have framebuffer open */
+static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
+{
+	int retval = -ENOMEM;
+	int old_len = info->fix.smem_len;
+	int new_len;
+	unsigned char *old_fb = info->screen_base;
+	unsigned char *new_fb;
+
+	pr_debug("Reallocating framebuffer. Addresses will change!");
+
+	new_len = info->fix.line_length * info->var.yres;
+
+	if (PAGE_ALIGN(new_len) > old_len) {
+		/*
+		 * Alloc system memory for virtual framebuffer
+		 */
+		new_fb = vmalloc(new_len);
+		if (!new_fb) {
+			pr_err("Virtual framebuffer alloc failed");
+			goto error;
+		}
+
+		if (info->screen_base) {
+			memcpy(new_fb, old_fb, old_len);
+			vfree(info->screen_base);
+		}
+
+		info->screen_base = new_fb;
+		info->fix.smem_len = PAGE_ALIGN(new_len);
+		info->fix.smem_start = (unsigned long) new_fb;
+		info->flags = smscufx_info_flags;
+	}
+
+	retval = 0;
+
+error:
+	return retval;
+}
+
+/* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master,
+ * restart enabled, but no start byte, enable controller */
+static int ufx_i2c_init(struct ufx_data *dev)
+{
+	u32 tmp;
+
+	/* disable the controller before it can be reprogrammed */
+	int status = ufx_reg_write(dev, 0x106C, 0x00);
+	check_warn_return(status, "failed to disable I2C");
+
+	/* Setup the clock count registers
+	 * (12+1) = 13 clks @ 2.5 MHz = 5.2 uS */
+	status = ufx_reg_write(dev, 0x1018, 12);
+	check_warn_return(status, "error writing 0x1018");
+
+	/* (6+8) = 14 clks @ 2.5 MHz = 5.6 uS */
+	status = ufx_reg_write(dev, 0x1014, 6);
+	check_warn_return(status, "error writing 0x1014");
+
+	status = ufx_reg_read(dev, 0x1000, &tmp);
+	check_warn_return(status, "error reading 0x1000");
+
+	/* set speed to std mode */
+	tmp &= ~(0x06);
+	tmp |= 0x02;
+
+	/* 7-bit (not 10-bit) addressing */
+	tmp &= ~(0x10);
+
+	/* enable restart conditions and master mode */
+	tmp |= 0x21;
+
+	status = ufx_reg_write(dev, 0x1000, tmp);
+	check_warn_return(status, "error writing 0x1000");
+
+	/* Set normal tx using target address 0 */
+	status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0xC00, 0x000);
+	check_warn_return(status, "error setting TX mode bits in 0x1004");
+
+	/* Enable the controller */
+	status = ufx_reg_write(dev, 0x106C, 0x01);
+	check_warn_return(status, "failed to enable I2C");
+
+	return 0;
+}
+
+/* sets the I2C port mux and target address */
+static int ufx_i2c_configure(struct ufx_data *dev)
+{
+	int status = ufx_reg_write(dev, 0x106C, 0x00);
+	check_warn_return(status, "failed to disable I2C");
+
+	status = ufx_reg_write(dev, 0x3010, 0x00000000);
+	check_warn_return(status, "failed to write 0x3010");
+
+	/* A0h is std for any EDID, right shifted by one */
+	status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0x3FF,	(0xA0 >> 1));
+	check_warn_return(status, "failed to set TAR bits in 0x1004");
+
+	status = ufx_reg_write(dev, 0x106C, 0x01);
+	check_warn_return(status, "failed to enable I2C");
+
+	return 0;
+}
+
+/* wait for BUSY to clear, with a timeout of 50ms with 10ms sleeps. if no
+ * monitor is connected, there is no error except for timeout */
+static int ufx_i2c_wait_busy(struct ufx_data *dev)
+{
+	u32 tmp;
+	int i, status;
+
+	for (i = 0; i < 15; i++) {
+		status = ufx_reg_read(dev, 0x1100, &tmp);
+		check_warn_return(status, "0x1100 read failed");
+
+		/* if BUSY is clear, check for error */
+		if ((tmp & 0x80000000) == 0) {
+			if (tmp & 0x20000000) {
+				pr_warn("I2C read failed, 0x1100=0x%08x", tmp);
+				return -EIO;
+			}
+
+			return 0;
+		}
+
+		/* perform the first 10 retries without delay */
+		if (i >= 10)
+			msleep(10);
+	}
+
+	pr_warn("I2C access timed out, resetting I2C hardware");
+	status =  ufx_reg_write(dev, 0x1100, 0x40000000);
+	check_warn_return(status, "0x1100 write failed");
+
+	return -ETIMEDOUT;
+}
+
+/* reads a 128-byte EDID block from the currently selected port and TAR */
+static int ufx_read_edid(struct ufx_data *dev, u8 *edid, int edid_len)
+{
+	int i, j, status;
+	u32 *edid_u32 = (u32 *)edid;
+
+	BUG_ON(edid_len != EDID_LENGTH);
+
+	status = ufx_i2c_configure(dev);
+	if (status < 0) {
+		pr_err("ufx_i2c_configure failed");
+		return status;
+	}
+
+	memset(edid, 0xff, EDID_LENGTH);
+
+	/* Read the 128-byte EDID as 2 bursts of 64 bytes */
+	for (i = 0; i < 2; i++) {
+		u32 temp = 0x28070000 | (63 << 20) | (((u32)(i * 64)) << 8);
+		status = ufx_reg_write(dev, 0x1100, temp);
+		check_warn_return(status, "Failed to write 0x1100");
+
+		temp |= 0x80000000;
+		status = ufx_reg_write(dev, 0x1100, temp);
+		check_warn_return(status, "Failed to write 0x1100");
+
+		status = ufx_i2c_wait_busy(dev);
+		check_warn_return(status, "Timeout waiting for I2C BUSY to clear");
+
+		for (j = 0; j < 16; j++) {
+			u32 data_reg_addr = 0x1110 + (j * 4);
+			status = ufx_reg_read(dev, data_reg_addr, edid_u32++);
+			check_warn_return(status, "Error reading i2c data");
+		}
+	}
+
+	/* all FF's in the first 16 bytes indicates nothing is connected */
+	for (i = 0; i < 16; i++) {
+		if (edid[i] != 0xFF) {
+			pr_debug("edid data read successfully");
+			return EDID_LENGTH;
+		}
+	}
+
+	pr_warn("edid data contains all 0xff");
+	return -ETIMEDOUT;
+}
+
+/* 1) use sw default
+ * 2) Parse into various fb_info structs
+ * 3) Allocate virtual framebuffer memory to back highest res mode
+ *
+ * Parses EDID into three places used by various parts of fbdev:
+ * fb_var_screeninfo contains the timing of the monitor's preferred mode
+ * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
+ * fb_info.modelist is a linked list of all monitor & VESA modes which work
+ *
+ * If EDID is not readable/valid, then modelist is all VESA modes,
+ * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
+ * Returns 0 if successful */
+static int ufx_setup_modes(struct ufx_data *dev, struct fb_info *info,
+	char *default_edid, size_t default_edid_size)
+{
+	const struct fb_videomode *default_vmode = NULL;
+	u8 *edid;
+	int i, result = 0, tries = 3;
+
+	if (info->dev) /* only use mutex if info has been registered */
+		mutex_lock(&info->lock);
+
+	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!edid) {
+		result = -ENOMEM;
+		goto error;
+	}
+
+	fb_destroy_modelist(&info->modelist);
+	memset(&info->monspecs, 0, sizeof(info->monspecs));
+
+	/* Try to (re)read EDID from hardware first
+	 * EDID data may return, but not parse as valid
+	 * Try again a few times, in case of e.g. analog cable noise */
+	while (tries--) {
+		i = ufx_read_edid(dev, edid, EDID_LENGTH);
+
+		if (i >= EDID_LENGTH)
+			fb_edid_to_monspecs(edid, &info->monspecs);
+
+		if (info->monspecs.modedb_len > 0) {
+			dev->edid = edid;
+			dev->edid_size = i;
+			break;
+		}
+	}
+
+	/* If that fails, use a previously returned EDID if available */
+	if (info->monspecs.modedb_len == 0) {
+		pr_err("Unable to get valid EDID from device/display\n");
+
+		if (dev->edid) {
+			fb_edid_to_monspecs(dev->edid, &info->monspecs);
+			if (info->monspecs.modedb_len > 0)
+				pr_err("Using previously queried EDID\n");
+		}
+	}
+
+	/* If that fails, use the default EDID we were handed */
+	if (info->monspecs.modedb_len == 0) {
+		if (default_edid_size >= EDID_LENGTH) {
+			fb_edid_to_monspecs(default_edid, &info->monspecs);
+			if (info->monspecs.modedb_len > 0) {
+				memcpy(edid, default_edid, default_edid_size);
+				dev->edid = edid;
+				dev->edid_size = default_edid_size;
+				pr_err("Using default/backup EDID\n");
+			}
+		}
+	}
+
+	/* If we've got modes, let's pick a best default mode */
+	if (info->monspecs.modedb_len > 0) {
+
+		for (i = 0; i < info->monspecs.modedb_len; i++) {
+			if (ufx_is_valid_mode(&info->monspecs.modedb[i], info))
+				fb_add_videomode(&info->monspecs.modedb[i],
+					&info->modelist);
+			else /* if we've removed top/best mode */
+				info->monspecs.misc &= ~FB_MISC_1ST_DETAIL;
+		}
+
+		default_vmode = fb_find_best_display(&info->monspecs,
+						     &info->modelist);
+	}
+
+	/* If everything else has failed, fall back to safe default mode */
+	if (default_vmode == NULL) {
+
+		struct fb_videomode fb_vmode = {0};
+
+		/* Add the standard VESA modes to our modelist
+		 * Since we don't have EDID, there may be modes that
+		 * overspec monitor and/or are incorrect aspect ratio, etc.
+		 * But at least the user has a chance to choose
+		 */
+		for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+			if (ufx_is_valid_mode((struct fb_videomode *)
+						&vesa_modes[i], info))
+				fb_add_videomode(&vesa_modes[i],
+						 &info->modelist);
+		}
+
+		/* default to resolution safe for projectors
+		 * (since they are most common case without EDID)
+		 */
+		fb_vmode.xres = 800;
+		fb_vmode.yres = 600;
+		fb_vmode.refresh = 60;
+		default_vmode = fb_find_nearest_mode(&fb_vmode,
+						     &info->modelist);
+	}
+
+	/* If we have good mode and no active clients */
+	if ((default_vmode != NULL) && (dev->fb_count == 0)) {
+
+		fb_videomode_to_var(&info->var, default_vmode);
+		ufx_var_color_format(&info->var);
+
+		/* with mode size info, we can now alloc our framebuffer */
+		memcpy(&info->fix, &ufx_fix, sizeof(ufx_fix));
+		info->fix.line_length = info->var.xres *
+			(info->var.bits_per_pixel / 8);
+
+		result = ufx_realloc_framebuffer(dev, info);
+
+	} else
+		result = -EINVAL;
+
+error:
+	if (edid && (dev->edid != edid))
+		kfree(edid);
+
+	if (info->dev)
+		mutex_unlock(&info->lock);
+
+	return result;
+}
+
+static int ufx_usb_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
+{
+	struct usb_device *usbdev;
+	struct ufx_data *dev;
+	struct fb_info *info = NULL;
+	int retval = -ENOMEM;
+	u32 id_rev, fpga_rev;
+
+	/* usb initialization */
+	usbdev = interface_to_usbdev(interface);
+	BUG_ON(!usbdev);
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n");
+		goto error;
+	}
+
+	/* we need to wait for both usb and fbdev to spin down on disconnect */
+	kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
+	kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
+
+	dev->udev = usbdev;
+	dev->gdev = &usbdev->dev; /* our generic struct device * */
+	usb_set_intfdata(interface, dev);
+
+	dev_dbg(dev->gdev, "%s %s - serial #%s\n",
+		usbdev->manufacturer, usbdev->product, usbdev->serial);
+	dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n",
+		usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
+		usbdev->descriptor.bcdDevice, dev);
+	dev_dbg(dev->gdev, "console enable=%d\n", console);
+	dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio);
+
+	if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+		retval = -ENOMEM;
+		dev_err(dev->gdev, "ufx_alloc_urb_list failed\n");
+		goto error;
+	}
+
+	/* We don't register a new USB class. Our client interface is fbdev */
+
+	/* allocates framebuffer driver structure, not framebuffer memory */
+	info = framebuffer_alloc(0, &usbdev->dev);
+	if (!info) {
+		retval = -ENOMEM;
+		dev_err(dev->gdev, "framebuffer_alloc failed\n");
+		goto error;
+	}
+
+	dev->info = info;
+	info->par = dev;
+	info->pseudo_palette = dev->pseudo_palette;
+	info->fbops = &ufx_ops;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0) {
+		dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval);
+		goto error;
+	}
+
+	INIT_DELAYED_WORK(&dev->free_framebuffer_work,
+			  ufx_free_framebuffer_work);
+
+	INIT_LIST_HEAD(&info->modelist);
+
+	retval = ufx_reg_read(dev, 0x3000, &id_rev);
+	check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
+	dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev);
+
+	retval = ufx_reg_read(dev, 0x3004, &fpga_rev);
+	check_warn_goto_error(retval, "error %d reading 0x3004 register from device", retval);
+	dev_dbg(dev->gdev, "FPGA_REV register value 0x%08x", fpga_rev);
+
+	dev_dbg(dev->gdev, "resetting device");
+	retval = ufx_lite_reset(dev);
+	check_warn_goto_error(retval, "error %d resetting device", retval);
+
+	dev_dbg(dev->gdev, "configuring system clock");
+	retval = ufx_config_sys_clk(dev);
+	check_warn_goto_error(retval, "error %d configuring system clock", retval);
+
+	dev_dbg(dev->gdev, "configuring DDR2 controller");
+	retval = ufx_config_ddr2(dev);
+	check_warn_goto_error(retval, "error %d initialising DDR2 controller", retval);
+
+	dev_dbg(dev->gdev, "configuring I2C controller");
+	retval = ufx_i2c_init(dev);
+	check_warn_goto_error(retval, "error %d initialising I2C controller", retval);
+
+	dev_dbg(dev->gdev, "selecting display mode");
+	retval = ufx_setup_modes(dev, info, NULL, 0);
+	check_warn_goto_error(retval, "unable to find common mode for display and adapter");
+
+	retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001);
+	check_warn_goto_error(retval, "error %d enabling graphics engine", retval);
+
+	/* ready to begin using device */
+	atomic_set(&dev->usb_active, 1);
+
+	dev_dbg(dev->gdev, "checking var");
+	retval = ufx_ops_check_var(&info->var, info);
+	check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval);
+
+	dev_dbg(dev->gdev, "setting par");
+	retval = ufx_ops_set_par(info);
+	check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval);
+
+	dev_dbg(dev->gdev, "registering framebuffer");
+	retval = register_framebuffer(info);
+	check_warn_goto_error(retval, "error %d register_framebuffer", retval);
+
+	dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution."
+		" Using %dK framebuffer memory\n", info->node,
+		info->var.xres, info->var.yres, info->fix.smem_len >> 10);
+
+	return 0;
+
+error:
+	if (dev) {
+		if (info) {
+			if (info->cmap.len != 0)
+				fb_dealloc_cmap(&info->cmap);
+			if (info->monspecs.modedb)
+				fb_destroy_modedb(info->monspecs.modedb);
+			if (info->screen_base)
+				vfree(info->screen_base);
+
+			fb_destroy_modelist(&info->modelist);
+
+			framebuffer_release(info);
+		}
+
+		kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
+		kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
+
+		/* dev has been deallocated. Do not dereference */
+	}
+
+	return retval;
+}
+
+static void ufx_usb_disconnect(struct usb_interface *interface)
+{
+	struct ufx_data *dev;
+	struct fb_info *info;
+
+	dev = usb_get_intfdata(interface);
+	info = dev->info;
+
+	pr_debug("USB disconnect starting\n");
+
+	/* we virtualize until all fb clients release. Then we free */
+	dev->virtualized = true;
+
+	/* When non-active we'll update virtual framebuffer, but no new urbs */
+	atomic_set(&dev->usb_active, 0);
+
+	usb_set_intfdata(interface, NULL);
+
+	/* if clients still have us open, will be freed on last close */
+	if (dev->fb_count == 0)
+		schedule_delayed_work(&dev->free_framebuffer_work, 0);
+
+	/* release reference taken by kref_init in probe() */
+	kref_put(&dev->kref, ufx_free);
+
+	/* consider ufx_data freed */
+}
+
+static struct usb_driver ufx_driver = {
+	.name = "smscufx",
+	.probe = ufx_usb_probe,
+	.disconnect = ufx_usb_disconnect,
+	.id_table = id_table,
+};
+
+module_usb_driver(ufx_driver);
+
+static void ufx_urb_completion(struct urb *urb)
+{
+	struct urb_node *unode = urb->context;
+	struct ufx_data *dev = unode->dev;
+	unsigned long flags;
+
+	/* sync/async unlink faults aren't errors */
+	if (urb->status) {
+		if (!(urb->status == -ENOENT ||
+		    urb->status == -ECONNRESET ||
+		    urb->status == -ESHUTDOWN)) {
+			pr_err("%s - nonzero write bulk status received: %d\n",
+				__func__, urb->status);
+			atomic_set(&dev->lost_pixels, 1);
+		}
+	}
+
+	urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
+
+	spin_lock_irqsave(&dev->urbs.lock, flags);
+	list_add_tail(&unode->entry, &dev->urbs.list);
+	dev->urbs.available++;
+	spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+	/* When using fb_defio, we deadlock if up() is called
+	 * while another is waiting. So queue to another process */
+	if (fb_defio)
+		schedule_delayed_work(&unode->release_urb_work, 0);
+	else
+		up(&dev->urbs.limit_sem);
+}
+
+static void ufx_free_urb_list(struct ufx_data *dev)
+{
+	int count = dev->urbs.count;
+	struct list_head *node;
+	struct urb_node *unode;
+	struct urb *urb;
+	int ret;
+	unsigned long flags;
+
+	pr_debug("Waiting for completes and freeing all render urbs\n");
+
+	/* keep waiting and freeing, until we've got 'em all */
+	while (count--) {
+		/* Getting interrupted means a leak, but ok at shutdown*/
+		ret = down_interruptible(&dev->urbs.limit_sem);
+		if (ret)
+			break;
+
+		spin_lock_irqsave(&dev->urbs.lock, flags);
+
+		node = dev->urbs.list.next; /* have reserved one with sem */
+		list_del_init(node);
+
+		spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+		unode = list_entry(node, struct urb_node, entry);
+		urb = unode->urb;
+
+		/* Free each separately allocated piece */
+		usb_free_coherent(urb->dev, dev->urbs.size,
+				  urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+		kfree(node);
+	}
+}
+
+static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size)
+{
+	int i = 0;
+	struct urb *urb;
+	struct urb_node *unode;
+	char *buf;
+
+	spin_lock_init(&dev->urbs.lock);
+
+	dev->urbs.size = size;
+	INIT_LIST_HEAD(&dev->urbs.list);
+
+	while (i < count) {
+		unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
+		if (!unode)
+			break;
+		unode->dev = dev;
+
+		INIT_DELAYED_WORK(&unode->release_urb_work,
+			  ufx_release_urb_work);
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			kfree(unode);
+			break;
+		}
+		unode->urb = urb;
+
+		buf = usb_alloc_coherent(dev->udev, size, GFP_KERNEL,
+					 &urb->transfer_dma);
+		if (!buf) {
+			kfree(unode);
+			usb_free_urb(urb);
+			break;
+		}
+
+		/* urb->transfer_buffer_length set to actual before submit */
+		usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
+			buf, size, ufx_urb_completion, unode);
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		list_add_tail(&unode->entry, &dev->urbs.list);
+
+		i++;
+	}
+
+	sema_init(&dev->urbs.limit_sem, i);
+	dev->urbs.count = i;
+	dev->urbs.available = i;
+
+	pr_debug("allocated %d %d byte urbs\n", i, (int) size);
+
+	return i;
+}
+
+static struct urb *ufx_get_urb(struct ufx_data *dev)
+{
+	int ret = 0;
+	struct list_head *entry;
+	struct urb_node *unode;
+	struct urb *urb = NULL;
+	unsigned long flags;
+
+	/* Wait for an in-flight buffer to complete and get re-queued */
+	ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
+	if (ret) {
+		atomic_set(&dev->lost_pixels, 1);
+		pr_warn("wait for urb interrupted: %x available: %d\n",
+		       ret, dev->urbs.available);
+		goto error;
+	}
+
+	spin_lock_irqsave(&dev->urbs.lock, flags);
+
+	BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
+	entry = dev->urbs.list.next;
+	list_del_init(entry);
+	dev->urbs.available--;
+
+	spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+	unode = list_entry(entry, struct urb_node, entry);
+	urb = unode->urb;
+
+error:
+	return urb;
+}
+
+static int ufx_submit_urb(struct ufx_data *dev, struct urb *urb, size_t len)
+{
+	int ret;
+
+	BUG_ON(len > dev->urbs.size);
+
+	urb->transfer_buffer_length = len; /* set to actual payload len */
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret) {
+		ufx_urb_completion(urb); /* because no one else will */
+		atomic_set(&dev->lost_pixels, 1);
+		pr_err("usb_submit_urb error %x\n", ret);
+	}
+	return ret;
+}
+
+module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(console, "Allow fbcon to be used on this display");
+
+module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support");
+
+MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>");
+MODULE_DESCRIPTION("SMSC UFX kernel framebuffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
new file mode 100644
index 000000000000..f4daa59f0a80
--- /dev/null
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -0,0 +1,581 @@
+/*
+ * Driver for the Solomon SSD1307 OLED controller
+ *
+ * Copyright 2012 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+
+#define SSD1307FB_DATA			0x40
+#define SSD1307FB_COMMAND		0x80
+
+#define SSD1307FB_SET_ADDRESS_MODE	0x20
+#define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL	(0x00)
+#define SSD1307FB_SET_ADDRESS_MODE_VERTICAL	(0x01)
+#define SSD1307FB_SET_ADDRESS_MODE_PAGE		(0x02)
+#define SSD1307FB_SET_COL_RANGE		0x21
+#define SSD1307FB_SET_PAGE_RANGE	0x22
+#define SSD1307FB_CONTRAST		0x81
+#define	SSD1307FB_CHARGE_PUMP		0x8d
+#define SSD1307FB_SEG_REMAP_ON		0xa1
+#define SSD1307FB_DISPLAY_OFF		0xae
+#define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
+#define SSD1307FB_DISPLAY_ON		0xaf
+#define SSD1307FB_START_PAGE_ADDRESS	0xb0
+#define SSD1307FB_SET_DISPLAY_OFFSET	0xd3
+#define	SSD1307FB_SET_CLOCK_FREQ	0xd5
+#define	SSD1307FB_SET_PRECHARGE_PERIOD	0xd9
+#define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
+#define	SSD1307FB_SET_VCOMH		0xdb
+
+struct ssd1307fb_par;
+
+struct ssd1307fb_ops {
+	int (*init)(struct ssd1307fb_par *);
+	int (*remove)(struct ssd1307fb_par *);
+};
+
+struct ssd1307fb_par {
+	struct i2c_client *client;
+	u32 height;
+	struct fb_info *info;
+	struct ssd1307fb_ops *ops;
+	u32 page_offset;
+	struct pwm_device *pwm;
+	u32 pwm_period;
+	int reset;
+	u32 width;
+};
+
+struct ssd1307fb_array {
+	u8	type;
+	u8	data[0];
+};
+
+static struct fb_fix_screeninfo ssd1307fb_fix = {
+	.id		= "Solomon SSD1307",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_MONO10,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo ssd1307fb_var = {
+	.bits_per_pixel	= 1,
+};
+
+static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
+{
+	struct ssd1307fb_array *array;
+
+	array = kzalloc(sizeof(struct ssd1307fb_array) + len, GFP_KERNEL);
+	if (!array)
+		return NULL;
+
+	array->type = type;
+
+	return array;
+}
+
+static int ssd1307fb_write_array(struct i2c_client *client,
+				 struct ssd1307fb_array *array, u32 len)
+{
+	int ret;
+
+	len += sizeof(struct ssd1307fb_array);
+
+	ret = i2c_master_send(client, (u8 *)array, len);
+	if (ret != len) {
+		dev_err(&client->dev, "Couldn't send I2C command.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
+{
+	struct ssd1307fb_array *array;
+	int ret;
+
+	array = ssd1307fb_alloc_array(1, SSD1307FB_COMMAND);
+	if (!array)
+		return -ENOMEM;
+
+	array->data[0] = cmd;
+
+	ret = ssd1307fb_write_array(client, array, 1);
+	kfree(array);
+
+	return ret;
+}
+
+static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
+{
+	struct ssd1307fb_array *array;
+	int ret;
+
+	array = ssd1307fb_alloc_array(1, SSD1307FB_DATA);
+	if (!array)
+		return -ENOMEM;
+
+	array->data[0] = data;
+
+	ret = ssd1307fb_write_array(client, array, 1);
+	kfree(array);
+
+	return ret;
+}
+
+static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+{
+	struct ssd1307fb_array *array;
+	u8 *vmem = par->info->screen_base;
+	int i, j, k;
+
+	array = ssd1307fb_alloc_array(par->width * par->height / 8,
+				      SSD1307FB_DATA);
+	if (!array)
+		return;
+
+	/*
+	 * The screen is divided in pages, each having a height of 8
+	 * pixels, and the width of the screen. When sending a byte of
+	 * data to the controller, it gives the 8 bits for the current
+	 * column. I.e, the first byte are the 8 bits of the first
+	 * column, then the 8 bits for the second column, etc.
+	 *
+	 *
+	 * Representation of the screen, assuming it is 5 bits
+	 * wide. Each letter-number combination is a bit that controls
+	 * one pixel.
+	 *
+	 * A0 A1 A2 A3 A4
+	 * B0 B1 B2 B3 B4
+	 * C0 C1 C2 C3 C4
+	 * D0 D1 D2 D3 D4
+	 * E0 E1 E2 E3 E4
+	 * F0 F1 F2 F3 F4
+	 * G0 G1 G2 G3 G4
+	 * H0 H1 H2 H3 H4
+	 *
+	 * If you want to update this screen, you need to send 5 bytes:
+	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
+	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
+	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
+	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
+	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
+	 */
+
+	for (i = 0; i < (par->height / 8); i++) {
+		for (j = 0; j < par->width; j++) {
+			u32 array_idx = i * par->width + j;
+			array->data[array_idx] = 0;
+			for (k = 0; k < 8; k++) {
+				u32 page_length = par->width * i;
+				u32 index = page_length + (par->width * k + j) / 8;
+				u8 byte = *(vmem + index);
+				u8 bit = byte & (1 << (j % 8));
+				bit = bit >> (j % 8);
+				array->data[array_idx] |= bit << k;
+			}
+		}
+	}
+
+	ssd1307fb_write_array(par->client, array, par->width * par->height / 8);
+	kfree(array);
+}
+
+
+static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct ssd1307fb_par *par = info->par;
+	unsigned long total_size;
+	unsigned long p = *ppos;
+	u8 __iomem *dst;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EINVAL;
+
+	if (count + p > total_size)
+		count = total_size - p;
+
+	if (!count)
+		return -EINVAL;
+
+	dst = (void __force *) (info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		return -EFAULT;
+
+	ssd1307fb_update_display(par);
+
+	*ppos += count;
+
+	return count;
+}
+
+static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_fillrect(info, rect);
+	ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_copyarea(info, area);
+	ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_imageblit(info, image);
+	ssd1307fb_update_display(par);
+}
+
+static struct fb_ops ssd1307fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read	= fb_sys_read,
+	.fb_write	= ssd1307fb_write,
+	.fb_fillrect	= ssd1307fb_fillrect,
+	.fb_copyarea	= ssd1307fb_copyarea,
+	.fb_imageblit	= ssd1307fb_imageblit,
+};
+
+static void ssd1307fb_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	ssd1307fb_update_display(info->par);
+}
+
+static struct fb_deferred_io ssd1307fb_defio = {
+	.delay		= HZ,
+	.deferred_io	= ssd1307fb_deferred_io,
+};
+
+static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
+{
+	int ret;
+
+	par->pwm = pwm_get(&par->client->dev, NULL);
+	if (IS_ERR(par->pwm)) {
+		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+		return PTR_ERR(par->pwm);
+	}
+
+	par->pwm_period = pwm_get_period(par->pwm);
+	/* Enable the PWM */
+	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+	pwm_enable(par->pwm);
+
+	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
+		par->pwm->pwm, par->pwm_period);
+
+	/* Map column 127 of the OLED to segment 0 */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the display */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
+{
+	pwm_disable(par->pwm);
+	pwm_put(par->pwm);
+	return 0;
+}
+
+static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
+	.init	= ssd1307fb_ssd1307_init,
+	.remove	= ssd1307fb_ssd1307_remove,
+};
+
+static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
+{
+	int ret;
+
+	/* Set initial contrast */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x7f);
+	if (ret < 0)
+		return ret;
+
+	/* Set COM direction */
+	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	if (ret < 0)
+		return ret;
+
+	/* Set segment re-map */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (ret < 0)
+		return ret;
+
+	/* Set multiplex ratio value */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* set display offset value */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET);
+	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	if (ret < 0)
+		return ret;
+
+	/* Set clock frequency */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0xf0);
+	if (ret < 0)
+		return ret;
+
+	/* Set precharge period in number of ticks from the internal clock */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
+	if (ret < 0)
+		return ret;
+
+	/* Set COM pins configuration */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
+	if (ret < 0)
+		return ret;
+
+	/* Set VCOMH */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x49);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the DC-DC Charge Pump */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x14);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to horizontal addressing mode */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
+	ret = ret & ssd1307fb_write_cmd(par->client,
+					SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
+	ret = ret & ssd1307fb_write_cmd(par->client,
+					par->page_offset + (par->height / 8) - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the display */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
+	.init	= ssd1307fb_ssd1306_init,
+};
+
+static const struct of_device_id ssd1307fb_of_match[] = {
+	{
+		.compatible = "solomon,ssd1306fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1306_ops,
+	},
+	{
+		.compatible = "solomon,ssd1307fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1307_ops,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
+
+static int ssd1307fb_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct fb_info *info;
+	struct device_node *node = client->dev.of_node;
+	u32 vmem_size;
+	struct ssd1307fb_par *par;
+	u8 *vmem;
+	int ret;
+
+	if (!node) {
+		dev_err(&client->dev, "No device tree data found!\n");
+		return -EINVAL;
+	}
+
+	info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
+	if (!info) {
+		dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	par->info = info;
+	par->client = client;
+
+	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
+							   &client->dev)->data;
+
+	par->reset = of_get_named_gpio(client->dev.of_node,
+					 "reset-gpios", 0);
+	if (!gpio_is_valid(par->reset)) {
+		ret = -EINVAL;
+		goto fb_alloc_error;
+	}
+
+	if (of_property_read_u32(node, "solomon,width", &par->width))
+		par->width = 96;
+
+	if (of_property_read_u32(node, "solomon,height", &par->height))
+		par->width = 16;
+
+	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
+		par->page_offset = 1;
+
+	vmem_size = par->width * par->height / 8;
+
+	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	if (!vmem) {
+		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	info->fbops = &ssd1307fb_ops;
+	info->fix = ssd1307fb_fix;
+	info->fix.line_length = par->width / 8;
+	info->fbdefio = &ssd1307fb_defio;
+
+	info->var = ssd1307fb_var;
+	info->var.xres = par->width;
+	info->var.xres_virtual = par->width;
+	info->var.yres = par->height;
+	info->var.yres_virtual = par->height;
+
+	info->var.red.length = 1;
+	info->var.red.offset = 0;
+	info->var.green.length = 1;
+	info->var.green.offset = 0;
+	info->var.blue.length = 1;
+	info->var.blue.offset = 0;
+
+	info->screen_base = (u8 __force __iomem *)vmem;
+	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_len = vmem_size;
+
+	fb_deferred_io_init(info);
+
+	ret = devm_gpio_request_one(&client->dev, par->reset,
+				    GPIOF_OUT_INIT_HIGH,
+				    "oled-reset");
+	if (ret) {
+		dev_err(&client->dev,
+			"failed to request gpio %d: %d\n",
+			par->reset, ret);
+		goto reset_oled_error;
+	}
+
+	i2c_set_clientdata(client, info);
+
+	/* Reset the screen */
+	gpio_set_value(par->reset, 0);
+	udelay(4);
+	gpio_set_value(par->reset, 1);
+	udelay(4);
+
+	if (par->ops->init) {
+		ret = par->ops->init(par);
+		if (ret)
+			goto reset_oled_error;
+	}
+
+	ret = register_framebuffer(info);
+	if (ret) {
+		dev_err(&client->dev, "Couldn't register the framebuffer\n");
+		goto panel_init_error;
+	}
+
+	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
+
+	return 0;
+
+panel_init_error:
+	if (par->ops->remove)
+		par->ops->remove(par);
+reset_oled_error:
+	fb_deferred_io_cleanup(info);
+fb_alloc_error:
+	framebuffer_release(info);
+	return ret;
+}
+
+static int ssd1307fb_remove(struct i2c_client *client)
+{
+	struct fb_info *info = i2c_get_clientdata(client);
+	struct ssd1307fb_par *par = info->par;
+
+	unregister_framebuffer(info);
+	if (par->ops->remove)
+		par->ops->remove(par);
+	fb_deferred_io_cleanup(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1306fb", 0 },
+	{ "ssd1307fb", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
+
+static struct i2c_driver ssd1307fb_driver = {
+	.probe = ssd1307fb_probe,
+	.remove = ssd1307fb_remove,
+	.id_table = ssd1307fb_i2c_id,
+	.driver = {
+		.name = "ssd1307fb",
+		.of_match_table = ssd1307fb_of_match,
+		.owner = THIS_MODULE,
+	},
+};
+
+module_i2c_driver(ssd1307fb_driver);
+
+MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controller");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c
new file mode 100644
index 000000000000..f0cb279ef333
--- /dev/null
+++ b/drivers/video/fbdev/sstfb.c
@@ -0,0 +1,1532 @@
+/*
+ * linux/drivers/video/sstfb.c -- voodoo graphics frame buffer
+ *
+ *     Copyright (c) 2000-2002 Ghozlane Toumi <gtoumi@laposte.net>
+ *
+ *     Created 15 Jan 2000 by Ghozlane Toumi
+ *
+ * Contributions (and many thanks) :
+ *
+ * 03/2001 James Simmons   <jsimmons@infradead.org>
+ * 04/2001 Paul Mundt      <lethal@chaoticdreams.org>
+ * 05/2001 Urs Ganse       <ursg@uni.de>
+ *	(initial work on voodoo2 port, interlace)
+ * 09/2002 Helge Deller    <deller@gmx.de>
+ *	(enable driver on big-endian machines (hppa), ioctl fixes)
+ * 12/2002 Helge Deller    <deller@gmx.de>
+ *	(port driver to new frambuffer infrastructure)
+ * 01/2003 Helge Deller    <deller@gmx.de>
+ *	(initial work on fb hardware acceleration for voodoo2)
+ * 08/2006 Alan Cox 	   <alan@redhat.com>
+ *	Remove never finished and bogus 24/32bit support
+ *	Clean up macro abuse
+ *	Minor tidying for format.
+ * 12/2006 Helge Deller    <deller@gmx.de>
+ *	add /sys/class/graphics/fbX/vgapass sysfs-interface
+ *	add module option "mode_option" to set initial screen mode
+ *	use fbdev default videomode database
+ *	remove debug functions from ioctl
+ */
+
+/*
+ * The voodoo1 has the following memory mapped address space:
+ * 0x000000 - 0x3fffff : registers              (4MB)
+ * 0x400000 - 0x7fffff : linear frame buffer    (4MB)
+ * 0x800000 - 0xffffff : texture memory         (8MB)
+ */
+
+/*
+ * misc notes, TODOs, toASKs, and deep thoughts
+
+-TODO: at one time or another test that the mode is acceptable by the monitor
+-ASK: Can I choose different ordering for the color bitfields (rgba argb ...)
+      which one should i use ? is there any preferred one ? It seems ARGB is
+      the one ...
+-TODO: in  set_var check the validity of timings (hsync vsync)...
+-TODO: check and recheck the use of sst_wait_idle : we don't flush the fifo via
+       a nop command. so it's ok as long as the commands we pass don't go
+       through the fifo. warning: issuing a nop command seems to need pci_fifo
+-FIXME: in case of failure in the init sequence, be sure we return to a safe
+        state.
+- FIXME: Use accelerator for 2D scroll
+-FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)
+ */
+
+/*
+ * debug info
+ * SST_DEBUG : enable debugging
+ * SST_DEBUG_REG : debug registers
+ *   0 :  no debug
+ *   1 : dac calls, [un]set_bits, FbiInit
+ *   2 : insane debug level (log every register read/write)
+ * SST_DEBUG_FUNC : functions
+ *   0 : no debug
+ *   1 : function call / debug ioctl
+ *   2 : variables
+ *   3 : flood . you don't want to do that. trust me.
+ * SST_DEBUG_VAR : debug display/var structs
+ *   0 : no debug
+ *   1 : dumps display, fb_var
+ *
+ * sstfb specific ioctls:
+ *   		toggle vga (0x46db) : toggle vga_pass_through
+ */
+
+#undef SST_DEBUG
+
+
+/*
+ * Includes
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <video/sstfb.h>
+
+
+/* initialized by setup */
+
+static bool vgapass;		/* enable VGA passthrough cable */
+static int mem;			/* mem size in MB, 0 = autodetect */
+static bool clipping = 1;	/* use clipping (slower, safer) */
+static int gfxclk;		/* force FBI freq in Mhz . Dangerous */
+static bool slowpci;		/* slow PCI settings */
+
+/*
+  Possible default video modes: 800x600@60, 640x480@75, 1024x768@76, 640x480@60
+*/
+#define DEFAULT_VIDEO_MODE "640x480@60"
+
+static char *mode_option = DEFAULT_VIDEO_MODE;
+
+enum {
+	ID_VOODOO1 = 0,
+	ID_VOODOO2 = 1,
+};
+
+#define IS_VOODOO2(par) ((par)->type == ID_VOODOO2)
+
+static struct sst_spec voodoo_spec[] = {
+ { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
+ { .name = "Voodoo2",	      .default_gfx_clock = 75000, .max_gfxclk = 85 },
+};
+
+
+/*
+ * debug functions
+ */
+
+#if (SST_DEBUG_REG > 0)
+static void sst_dbg_print_read_reg(u32 reg, u32 val) {
+	const char *regname;
+	switch (reg) {
+	case FBIINIT0:	regname = "FbiInit0"; break;
+	case FBIINIT1:	regname = "FbiInit1"; break;
+	case FBIINIT2:	regname = "FbiInit2"; break;
+	case FBIINIT3:	regname = "FbiInit3"; break;
+	case FBIINIT4:	regname = "FbiInit4"; break;
+	case FBIINIT5:	regname = "FbiInit5"; break;
+	case FBIINIT6:	regname = "FbiInit6"; break;
+	default:	regname = NULL;       break;
+	}
+	if (regname == NULL)
+		r_ddprintk("sst_read(%#x): %#x\n", reg, val);
+	else
+		r_dprintk(" sst_read(%s): %#x\n", regname, val);
+}
+
+static void sst_dbg_print_write_reg(u32 reg, u32 val) {
+	const char *regname;
+	switch (reg) {
+	case FBIINIT0:	regname = "FbiInit0"; break;
+	case FBIINIT1:	regname = "FbiInit1"; break;
+	case FBIINIT2:	regname = "FbiInit2"; break;
+	case FBIINIT3:	regname = "FbiInit3"; break;
+	case FBIINIT4:	regname = "FbiInit4"; break;
+	case FBIINIT5:	regname = "FbiInit5"; break;
+	case FBIINIT6:	regname = "FbiInit6"; break;
+	default:	regname = NULL;       break;
+	}
+	if (regname == NULL)
+		r_ddprintk("sst_write(%#x, %#x)\n", reg, val);
+	else
+		r_dprintk(" sst_write(%s, %#x)\n", regname, val);
+}
+#else /*  (SST_DEBUG_REG > 0) */
+#  define sst_dbg_print_read_reg(reg, val)	do {} while(0)
+#  define sst_dbg_print_write_reg(reg, val)	do {} while(0)
+#endif /*  (SST_DEBUG_REG > 0) */
+
+/*
+ * hardware access functions
+ */
+
+/* register access */
+#define sst_read(reg)		__sst_read(par->mmio_vbase, reg)
+#define sst_write(reg,val)	__sst_write(par->mmio_vbase, reg, val)
+#define sst_set_bits(reg,val)	__sst_set_bits(par->mmio_vbase, reg, val)
+#define sst_unset_bits(reg,val)	__sst_unset_bits(par->mmio_vbase, reg, val)
+#define sst_dac_read(reg)	__sst_dac_read(par->mmio_vbase, reg)
+#define sst_dac_write(reg,val)	__sst_dac_write(par->mmio_vbase, reg, val)
+#define dac_i_read(reg)		__dac_i_read(par->mmio_vbase, reg)
+#define dac_i_write(reg,val)	__dac_i_write(par->mmio_vbase, reg, val)
+
+static inline u32 __sst_read(u8 __iomem *vbase, u32 reg)
+{
+	u32 ret = readl(vbase + reg);
+	sst_dbg_print_read_reg(reg, ret);
+	return ret;
+}
+
+static inline void __sst_write(u8 __iomem *vbase, u32 reg, u32 val)
+{
+	sst_dbg_print_write_reg(reg, val);
+	writel(val, vbase + reg);
+}
+
+static inline void __sst_set_bits(u8 __iomem *vbase, u32 reg, u32 val)
+{
+	r_dprintk("sst_set_bits(%#x, %#x)\n", reg, val);
+	__sst_write(vbase, reg, __sst_read(vbase, reg) | val);
+}
+
+static inline void __sst_unset_bits(u8 __iomem *vbase, u32 reg, u32 val)
+{
+	r_dprintk("sst_unset_bits(%#x, %#x)\n", reg, val);
+	__sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);
+}
+
+/*
+ * wait for the fbi chip. ASK: what happens if the fbi is stuck ?
+ *
+ * the FBI is supposed to be ready if we receive 5 time
+ * in a row a "idle" answer to our requests
+ */
+
+#define sst_wait_idle() __sst_wait_idle(par->mmio_vbase)
+
+static int __sst_wait_idle(u8 __iomem *vbase)
+{
+	int count = 0;
+
+	/* if (doFBINOP) __sst_write(vbase, NOPCMD, 0); */
+
+	while(1) {
+		if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
+			f_dddprintk("status: busy\n");
+/* FIXME basically, this is a busy wait. maybe not that good. oh well;
+ * this is a small loop after all.
+ * Or maybe we should use mdelay() or udelay() here instead ? */
+			count = 0;
+		} else {
+			count++;
+			f_dddprintk("status: idle(%d)\n", count);
+		}
+		if (count >= 5) return 1;
+/* XXX  do something to avoid hanging the machine if the voodoo is out */
+	}
+}
+
+
+/* dac access */
+/* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */
+static u8 __sst_dac_read(u8 __iomem *vbase, u8 reg)
+{
+	u8 ret;
+
+	reg &= 0x07;
+	__sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
+	__sst_wait_idle(vbase);
+	/* udelay(10); */
+	ret = __sst_read(vbase, DAC_READ) & 0xff;
+	r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
+
+	return ret;
+}
+
+static void __sst_dac_write(u8 __iomem *vbase, u8 reg, u8 val)
+{
+	r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);
+	reg &= 0x07;
+	__sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);
+	__sst_wait_idle(vbase);
+}
+
+/* indexed access to ti/att dacs */
+static u32 __dac_i_read(u8 __iomem *vbase, u8 reg)
+{
+	u32 ret;
+
+	__sst_dac_write(vbase, DACREG_ADDR_I, reg);
+	ret = __sst_dac_read(vbase, DACREG_DATA_I);
+	r_dprintk("sst_dac_read_i(%#x): %#x\n", reg, ret);
+	return ret;
+}
+static void __dac_i_write(u8 __iomem *vbase, u8 reg,u8 val)
+{
+	r_dprintk("sst_dac_write_i(%#x, %#x)\n", reg, val);
+	__sst_dac_write(vbase, DACREG_ADDR_I, reg);
+	__sst_dac_write(vbase, DACREG_DATA_I, val);
+}
+
+/* compute the m,n,p  , returns the real freq
+ * (ics datasheet :  N <-> N1 , P <-> N2)
+ *
+ * Fout= Fref * (M+2)/( 2^P * (N+2))
+ *  we try to get close to the asked freq
+ *  with P as high, and M as low as possible
+ * range:
+ * ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63
+ * ics    : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31
+ * we'll use the lowest limitation, should be precise enouth
+ */
+static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
+{
+	int m, m2, n, p, best_err, fout;
+	int best_n = -1;
+	int best_m = -1;
+
+	best_err = freq;
+	p = 3;
+	/* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
+	while (((1 << p) * freq > VCO_MAX) && (p >= 0))
+		p--;
+	if (p == -1)
+		return -EINVAL;
+	for (n = 1; n < 32; n++) {
+		/* calc 2 * m so we can round it later*/
+		m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
+
+		m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
+		if (m >= 128)
+			break;
+		fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
+		if ((abs(fout - freq) < best_err) && (m > 0)) {
+			best_n = n;
+			best_m = m;
+			best_err = abs(fout - freq);
+			/* we get the lowest m , allowing 0.5% error in freq*/
+			if (200*best_err < freq) break;
+		}
+	}
+	if (best_n == -1)  /* unlikely, but who knows ? */
+		return -EINVAL;
+	t->p = p;
+	t->n = best_n;
+	t->m = best_m;
+	*freq_out = (DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
+	f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
+		  t->m, t->n, t->p, *freq_out);
+	return 0;
+}
+
+/*
+ * clear lfb screen
+ */
+static void sstfb_clear_screen(struct fb_info *info)
+{
+	/* clear screen */
+	fb_memset(info->screen_base, 0, info->fix.smem_len);
+}
+
+
+/**
+ *      sstfb_check_var - Optional function.  Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Limit to the abilities of a single chip as SLI is not supported
+ *	by this driver.
+ */
+
+static int sstfb_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	struct sstfb_par *par = info->par;
+	int hSyncOff   = var->xres + var->right_margin + var->left_margin;
+	int vSyncOff   = var->yres + var->lower_margin + var->upper_margin;
+	int vBackPorch = var->left_margin, yDim = var->yres;
+	int vSyncOn    = var->vsync_len;
+	int tiles_in_X, real_length;
+	unsigned int freq;
+
+	if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) {
+		printk(KERN_ERR "sstfb: Pixclock at %ld KHZ out of range\n",
+				PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+	var->pixclock = KHZ2PICOS(freq);
+	
+	if (var->vmode & FB_VMODE_INTERLACED)
+		vBackPorch += (vBackPorch % 2);
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		vBackPorch <<= 1;
+		yDim <<=1;
+		vSyncOn <<=1;
+		vSyncOff <<=1;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 0 ... 16 :
+		var->bits_per_pixel = 16;
+		break;
+	default :
+		printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+	
+	/* validity tests */
+	if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1  ||
+	    hSyncOff <= 1  || var->left_margin <= 2  || vSyncOn <= 0 ||
+	    vSyncOff <= 0 || vBackPorch <= 0) {
+		return -EINVAL;
+	}
+
+	if (IS_VOODOO2(par)) {
+		/* Voodoo 2 limits */
+		tiles_in_X = (var->xres + 63 ) / 64 * 2;		
+
+		if (var->xres  > POW2(11) || yDim >= POW2(11)) {
+			printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
+			         var->xres, var->yres);
+			return -EINVAL;
+		}
+
+		if (var->hsync_len > POW2(9) || hSyncOff > POW2(11) ||
+		    var->left_margin - 2 >= POW2(9) || vSyncOn >= POW2(13) ||
+		    vSyncOff >= POW2(13) || vBackPorch >= POW2(9) ||
+		    tiles_in_X >= POW2(6) || tiles_in_X <= 0) {
+			printk(KERN_ERR "sstfb: Unsupported timings\n");
+			return -EINVAL;
+		}
+	} else {
+		/* Voodoo limits */
+		tiles_in_X = (var->xres + 63 ) / 64;
+
+		if (var->vmode) {
+			printk(KERN_ERR "sstfb: Interlace/doublescan not supported %#x\n",
+				var->vmode);
+			return -EINVAL;
+		}
+		if (var->xres > POW2(10) || var->yres >= POW2(10)) {
+			printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
+			         var->xres, var->yres);
+			return -EINVAL;
+		}
+		if (var->hsync_len > POW2(8) || hSyncOff - 1 > POW2(10) ||
+		    var->left_margin - 2 >= POW2(8) || vSyncOn >= POW2(12) ||
+		    vSyncOff >= POW2(12) || vBackPorch >= POW2(8) ||
+		    tiles_in_X >= POW2(4) || tiles_in_X <= 0) {
+			printk(KERN_ERR "sstfb: Unsupported timings\n");
+			return -EINVAL;
+		}
+	}
+
+	/* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem */
+	/* FIXME: i don't like this... looks wrong */
+	real_length = tiles_in_X  * (IS_VOODOO2(par) ? 32 : 64 )
+	              * ((var->bits_per_pixel == 16) ? 2 : 4);
+
+	if (real_length * yDim > info->fix.smem_len) {
+		printk(KERN_ERR "sstfb: Not enough video memory\n");
+		return -ENOMEM;
+	}
+
+	var->sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
+	var->vmode &= (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->height  = -1;
+	var->width   = -1;
+
+	/*
+	 * correct the color bit fields
+	 */
+	/* var->{red|green|blue}.msb_right = 0; */
+
+	switch (var->bits_per_pixel) {
+	case 16:	/* RGB 565  LfbMode 0 */
+		var->red.length    = 5;
+		var->green.length  = 6;
+		var->blue.length   = 5;
+		var->transp.length = 0;
+
+		var->red.offset    = 11;
+		var->green.offset  = 5;
+		var->blue.offset   = 0;
+		var->transp.offset = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ *      sstfb_set_par - Optional function.  Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int sstfb_set_par(struct fb_info *info)
+{
+	struct sstfb_par *par = info->par;
+	u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
+	struct pci_dev *sst_dev = par->dev;
+	unsigned int freq;
+	int ntiles;
+
+	par->hSyncOff	= info->var.xres + info->var.right_margin + info->var.left_margin;
+
+	par->yDim 	= info->var.yres;
+	par->vSyncOn 	= info->var.vsync_len;
+	par->vSyncOff	= info->var.yres + info->var.lower_margin + info->var.upper_margin;
+	par->vBackPorch = info->var.upper_margin;
+
+	/* We need par->pll */
+	sst_calc_pll(PICOS2KHZ(info->var.pixclock), &freq, &par->pll);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		par->vBackPorch += (par->vBackPorch % 2);
+	if (info->var.vmode & FB_VMODE_DOUBLE) {
+		par->vBackPorch <<= 1;
+		par->yDim <<=1;
+		par->vSyncOn <<=1;
+		par->vSyncOff <<=1;
+	}
+
+	if (IS_VOODOO2(par)) {
+		/* voodoo2 has 32 pixel wide tiles , BUT strange things
+		   happen with odd number of tiles */
+		par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2;
+	} else {
+		/* voodoo1 has 64 pixels wide tiles. */
+		par->tiles_in_X = (info->var.xres + 63 ) / 64;
+	}
+
+	f_ddprintk("hsync_len hSyncOff vsync_len vSyncOff\n");
+	f_ddprintk("%-7d %-8d %-7d %-8d\n",
+	           info->var.hsync_len, par->hSyncOff,
+	           par->vSyncOn, par->vSyncOff);
+	f_ddprintk("left_margin upper_margin xres yres Freq\n");
+	f_ddprintk("%-10d %-10d %-4d %-4d %-8ld\n",
+	           info->var.left_margin, info->var.upper_margin,
+	           info->var.xres, info->var.yres, PICOS2KHZ(info->var.pixclock));
+
+	sst_write(NOPCMD, 0);
+	sst_wait_idle();
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
+	sst_set_bits(FBIINIT1, VIDEO_RESET);
+	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
+	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
+	sst_wait_idle();
+
+	/*sst_unset_bits (FBIINIT0, FBI_RESET); / reenable FBI ? */
+
+	sst_write(BACKPORCH, par->vBackPorch << 16 | (info->var.left_margin - 2));
+	sst_write(VIDEODIMENSIONS, par->yDim << 16 | (info->var.xres - 1));
+	sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1));
+	sst_write(VSYNC,       par->vSyncOff << 16 | par->vSyncOn);
+
+	fbiinit2 = sst_read(FBIINIT2);
+	fbiinit3 = sst_read(FBIINIT3);
+
+	/* everything is reset. we enable fbiinit2/3 remap : dac access ok */
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+	                       PCI_EN_INIT_WR | PCI_REMAP_DAC );
+
+	par->dac_sw.set_vidmod(info, info->var.bits_per_pixel);
+
+	/* set video clock */
+	par->dac_sw.set_pll(info, &par->pll, VID_CLOCK);
+
+	/* disable fbiinit2/3 remap */
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+	                       PCI_EN_INIT_WR);
+
+	/* restore fbiinit2/3 */
+	sst_write(FBIINIT2,fbiinit2);
+	sst_write(FBIINIT3,fbiinit3);
+
+	fbiinit1 = (sst_read(FBIINIT1) & VIDEO_MASK)
+	            | EN_DATA_OE
+	            | EN_BLANK_OE
+	            | EN_HVSYNC_OE
+	            | EN_DCLK_OE
+		 /* | (15 << TILES_IN_X_SHIFT) */
+	            | SEL_INPUT_VCLK_2X
+		 /* | (2 << VCLK_2X_SEL_DEL_SHIFT)
+	            | (2 << VCLK_DEL_SHIFT) */;
+/* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28)
+ in (near) future set them accordingly to revision + resolution (cf glide)
+ first understand what it stands for :)
+ FIXME: there are some artefacts... check for the vclk_in_delay
+ lets try with 6ns delay in both vclk_out & in...
+ doh... they're still there :\
+*/
+
+	ntiles = par->tiles_in_X;
+	if (IS_VOODOO2(par)) {
+		fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
+		            | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT;
+/* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
+   and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just
+   write our value. BTW due to the dac unable to read odd number of tiles, this
+   field is always null ... */
+		fbiinit6 = (ntiles & 0x1) << TILES_IN_X_LSB_SHIFT;
+	}
+	else
+		fbiinit1 |= ntiles << TILES_IN_X_SHIFT;
+
+	switch (info->var.bits_per_pixel) {
+	case 16:
+		fbiinit1 |=  SEL_SOURCE_VCLK_2X_SEL;
+		break;
+	default:
+		return -EINVAL;
+	}
+	sst_write(FBIINIT1, fbiinit1);
+	if (IS_VOODOO2(par)) {
+		sst_write(FBIINIT6, fbiinit6);
+		fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
+		if (info->var.vmode & FB_VMODE_INTERLACED)
+			fbiinit5 |= INTERLACE;
+		if (info->var.vmode & FB_VMODE_DOUBLE)
+			fbiinit5 |= VDOUBLESCAN;
+		if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+			fbiinit5 |= HSYNC_HIGH;
+		if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+			fbiinit5 |= VSYNC_HIGH;
+		sst_write(FBIINIT5, fbiinit5);
+	}
+	sst_wait_idle();
+	sst_unset_bits(FBIINIT1, VIDEO_RESET);
+	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
+	sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);
+	/* disables fbiinit writes */
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
+
+	/* set lfbmode : set mode + front buffer for reads/writes
+	   + disable pipeline */
+	switch (info->var.bits_per_pixel) {
+	case 16:
+		lfbmode = LFB_565;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+#if defined(__BIG_ENDIAN)
+	/* Enable byte-swizzle functionality in hardware.
+	 * With this enabled, all our read- and write-accesses to
+	 * the voodoo framebuffer can be done in native format, and
+	 * the hardware will automatically convert it to little-endian.
+	 * - tested on HP-PARISC, Helge Deller <deller@gmx.de> */
+	lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
+		     LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
+#endif
+	
+	if (clipping) {
+		sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
+	/*
+	 * Set "clipping" dimensions. If clipping is disabled and
+	 * writes to offscreen areas of the framebuffer are performed,
+	 * the "behaviour is undefined" (_very_ undefined) - Urs
+	 */
+	/* btw, it requires enabling pixel pipeline in LFBMODE .
+	   off screen read/writes will just wrap and read/print pixels
+	   on screen. Ugly but not that dangerous */
+		f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
+		            info->var.xres - 1, par->yDim - 1);
+
+		sst_write(CLIP_LEFT_RIGHT, info->var.xres);
+		sst_write(CLIP_LOWY_HIGHY, par->yDim);
+		sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
+	} else {
+		/* no clipping : direct access, no pipeline */
+		sst_write(LFBMODE, lfbmode);
+	}
+	return 0;
+}
+
+/**
+ *      sstfb_setcolreg - Optional function. Sets a color register.
+ *      @regno: hardware colormap register
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                           u_int transp, struct fb_info *info)
+{
+	struct sstfb_par *par = info->par;
+	u32 col;
+
+	f_dddprintk("sstfb_setcolreg\n");
+	f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
+	            regno, red, green, blue, transp);
+	if (regno > 15)
+		return 0;
+
+	red    >>= (16 - info->var.red.length);
+	green  >>= (16 - info->var.green.length);
+	blue   >>= (16 - info->var.blue.length);
+	transp >>= (16 - info->var.transp.length);
+	col = (red << info->var.red.offset)
+	    | (green << info->var.green.offset)
+	    | (blue  << info->var.blue.offset)
+	    | (transp << info->var.transp.offset);
+	
+	par->palette[regno] = col;
+
+	return 0;
+}
+
+static void sstfb_setvgapass( struct fb_info *info, int enable )
+{
+	struct sstfb_par *par = info->par;
+	struct pci_dev *sst_dev = par->dev;
+	u32 fbiinit0, tmp;
+
+	enable = enable ? 1:0;
+	if (par->vgapass == enable)
+		return;
+	par->vgapass = enable;
+
+	pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+			       tmp | PCI_EN_INIT_WR );
+	fbiinit0 = sst_read (FBIINIT0);
+	if (par->vgapass) {
+		sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);
+		fb_info(info, "Enabling VGA pass-through\n");
+	} else {
+		sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);
+		fb_info(info, "Disabling VGA pass-through\n");
+	}
+	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
+}
+
+static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	char ** last = NULL;
+	int val;
+
+	val = simple_strtoul(buf, last, 0);
+	sstfb_setvgapass(info, val);
+
+	return count;
+}
+
+static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,
+			char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct sstfb_par *par = info->par;
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->vgapass);
+}
+
+static struct device_attribute device_attrs[] = {
+	__ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)
+	};
+
+static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,
+			unsigned long arg)
+{
+	struct sstfb_par *par;
+	u32 val;
+
+	switch (cmd) {
+	/* set/get VGA pass_through mode */
+	case SSTFB_SET_VGAPASS:
+		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+			return -EFAULT;
+		sstfb_setvgapass(info, val);
+		return 0;
+	case SSTFB_GET_VGAPASS:
+		par = info->par;
+		val = par->vgapass;
+		if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+			return -EFAULT;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+
+/*
+ * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) - Voodoo2 only
+ */
+#if 0
+static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct sstfb_par *par = info->par;
+	u32 stride = info->fix.line_length;
+   
+	if (!IS_VOODOO2(par))
+		return;
+
+	sst_write(BLTSRCBASEADDR, 0);
+	sst_write(BLTDSTBASEADDR, 0);
+	sst_write(BLTROP, BLTROP_COPY);
+	sst_write(BLTXYSTRIDES, stride | (stride << 16));
+	sst_write(BLTSRCXY, area->sx | (area->sy << 16));
+	sst_write(BLTDSTXY, area->dx | (area->dy << 16));
+	sst_write(BLTSIZE, area->width | (area->height << 16));
+	sst_write(BLTCOMMAND, BLT_SCR2SCR_BITBLT | LAUNCH_BITBLT |
+		(BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) );
+	sst_wait_idle();
+}
+#endif
+
+
+/*
+ * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
+ */
+#if 0
+static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
+{
+	struct sstfb_par *par = info->par;
+	u32 stride = info->fix.line_length;
+
+	if (!IS_VOODOO2(par))
+		return;
+   	
+	sst_write(BLTCLIPX, info->var.xres);
+	sst_write(BLTCLIPY, info->var.yres);
+	
+	sst_write(BLTDSTBASEADDR, 0);
+	sst_write(BLTCOLOR, rect->color);
+	sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);
+	sst_write(BLTXYSTRIDES, stride | (stride << 16));
+	sst_write(BLTDSTXY, rect->dx | (rect->dy << 16));
+	sst_write(BLTSIZE, rect->width | (rect->height << 16));
+	sst_write(BLTCOMMAND, BLT_RECFILL_BITBLT | LAUNCH_BITBLT
+		 | (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );
+	sst_wait_idle();
+}
+#endif
+
+
+
+/* 
+ * get lfb size 
+ */
+static int sst_get_memsize(struct fb_info *info, __u32 *memsize)
+{
+	u8 __iomem *fbbase_virt = info->screen_base;
+
+	/* force memsize */
+	if (mem >= 1  && mem <= 4) {
+		*memsize = (mem * 0x100000);
+		printk(KERN_INFO "supplied memsize: %#x\n", *memsize);
+		return 1;
+	}
+
+	writel(0xdeadbeef, fbbase_virt);
+	writel(0xdeadbeef, fbbase_virt+0x100000);
+	writel(0xdeadbeef, fbbase_virt+0x200000);
+	f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
+	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),
+	           readl(fbbase_virt + 0x200000));
+
+	writel(0xabcdef01, fbbase_virt);
+
+	f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
+	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),
+	           readl(fbbase_virt + 0x200000));
+
+	/* checks for 4mb lfb, then 2, then defaults to 1 */
+	if (readl(fbbase_virt + 0x200000) == 0xdeadbeef)
+		*memsize = 0x400000;
+	else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef)
+		*memsize = 0x200000;
+	else
+		*memsize = 0x100000;
+	f_ddprintk("detected memsize: %dMB\n", *memsize >> 20);
+	return 1;
+}
+
+
+/* 
+ * DAC detection routines 
+ */
+
+/* fbi should be idle, and fifo emty and mem disabled */
+/* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */
+
+static int sst_detect_att(struct fb_info *info)
+{
+	struct sstfb_par *par = info->par;
+	int i, mir, dir;
+
+	for (i = 0; i < 3; i++) {
+		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
+		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
+		sst_dac_read(DACREG_RMR);
+		sst_dac_read(DACREG_RMR);
+		sst_dac_read(DACREG_RMR);
+		/* the fifth time,  CR0 is read */
+		sst_dac_read(DACREG_RMR);
+		/* the 6th, manufacturer id register */
+		mir = sst_dac_read(DACREG_RMR);
+		/*the 7th, device ID register */
+		dir = sst_dac_read(DACREG_RMR);
+		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
+		if (mir == DACREG_MIR_ATT && dir == DACREG_DIR_ATT) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int sst_detect_ti(struct fb_info *info)
+{
+	struct sstfb_par *par = info->par;
+	int i, mir, dir;
+
+	for (i = 0; i<3; i++) {
+		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
+		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
+		sst_dac_read(DACREG_RMR);
+		sst_dac_read(DACREG_RMR);
+		sst_dac_read(DACREG_RMR);
+		/* the fifth time,  CR0 is read */
+		sst_dac_read(DACREG_RMR);
+		/* the 6th, manufacturer id register */
+		mir = sst_dac_read(DACREG_RMR);
+		/*the 7th, device ID register */
+		dir = sst_dac_read(DACREG_RMR);
+		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
+		if ((mir == DACREG_MIR_TI ) && (dir == DACREG_DIR_TI)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * try to detect ICS5342  ramdac
+ * we get the 1st byte (M value) of preset f1,f7 and fB
+ * why those 3 ? mmmh... for now, i'll do it the glide way...
+ * and ask questions later. anyway, it seems that all the freq registers are
+ * really at their default state (cf specs) so i ask again, why those 3 regs ?
+ * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for
+ * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be
+ * touched...
+ * is it really safe ? how can i reset this ramdac ? geee...
+ */
+static int sst_detect_ics(struct fb_info *info)
+{
+	struct sstfb_par *par = info->par;
+	int m_clk0_1, m_clk0_7, m_clk1_b;
+	int n_clk0_1, n_clk0_7, n_clk1_b;
+	int i;
+
+	for (i = 0; i<5; i++ ) {
+		sst_dac_write(DACREG_ICS_PLLRMA, 0x1);	/* f1 */
+		m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
+		n_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
+		sst_dac_write(DACREG_ICS_PLLRMA, 0x7);	/* f7 */
+		m_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
+		n_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
+		sst_dac_write(DACREG_ICS_PLLRMA, 0xb);	/* fB */
+		m_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
+		n_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
+		f_ddprintk("m_clk0_1: %#x, m_clk0_7: %#x, m_clk1_b: %#x\n",
+			m_clk0_1, m_clk0_7, m_clk1_b);
+		f_ddprintk("n_clk0_1: %#x, n_clk0_7: %#x, n_clk1_b: %#x\n",
+			n_clk0_1, n_clk0_7, n_clk1_b);
+		if ((   m_clk0_1 == DACREG_ICS_PLL_CLK0_1_INI)
+		    && (m_clk0_7 == DACREG_ICS_PLL_CLK0_7_INI)
+		    && (m_clk1_b == DACREG_ICS_PLL_CLK1_B_INI)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * gfx, video, pci fifo should be reset, dram refresh disabled
+ * see detect_dac
+ */
+
+static int sst_set_pll_att_ti(struct fb_info *info, 
+		const struct pll_timing *t, const int clock)
+{
+	struct sstfb_par *par = info->par;
+	u8 cr0, cc;
+
+	/* enable indexed mode */
+	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
+	sst_dac_read(DACREG_RMR);	/* 1 time:  RMR */
+	sst_dac_read(DACREG_RMR);	/* 2 RMR */
+	sst_dac_read(DACREG_RMR);	/* 3 //  */
+	sst_dac_read(DACREG_RMR);	/* 4 //  */
+	cr0 = sst_dac_read(DACREG_RMR);	/* 5 CR0 */
+
+	sst_dac_write(DACREG_WMA, 0);
+	sst_dac_read(DACREG_RMR);
+	sst_dac_read(DACREG_RMR);
+	sst_dac_read(DACREG_RMR);
+	sst_dac_read(DACREG_RMR);
+	sst_dac_write(DACREG_RMR, (cr0 & 0xf0)
+	              | DACREG_CR0_EN_INDEXED
+	              | DACREG_CR0_8BIT
+	              | DACREG_CR0_PWDOWN );
+	/* so, now we are in indexed mode . dunno if its common, but
+	   i find this way of doing things a little bit weird :p */
+
+	udelay(300);
+	cc = dac_i_read(DACREG_CC_I);
+	switch (clock) {
+	case VID_CLOCK:
+		dac_i_write(DACREG_AC0_I, t->m);
+		dac_i_write(DACREG_AC1_I, t->p << 6 | t->n);
+		dac_i_write(DACREG_CC_I,
+		            (cc & 0x0f) | DACREG_CC_CLKA | DACREG_CC_CLKA_C);
+		break;
+	case GFX_CLOCK:
+		dac_i_write(DACREG_BD0_I, t->m);
+		dac_i_write(DACREG_BD1_I, t->p << 6 | t->n);
+		dac_i_write(DACREG_CC_I,
+		            (cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D);
+		break;
+	default:
+		dprintk("%s: wrong clock code '%d'\n",
+		        __func__, clock);
+		return 0;
+		}
+	udelay(300);
+
+	/* power up the dac & return to "normal" non-indexed mode */
+	dac_i_write(DACREG_CR0_I,
+	            cr0 & ~DACREG_CR0_PWDOWN & ~DACREG_CR0_EN_INDEXED);
+	return 1;
+}
+
+static int sst_set_pll_ics(struct fb_info *info,
+		const struct pll_timing *t, const int clock)
+{
+	struct sstfb_par *par = info->par;
+	u8 pll_ctrl;
+
+	sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
+	pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);
+	switch(clock) {
+	case VID_CLOCK:
+		sst_dac_write(DACREG_ICS_PLLWMA, 0x0);	/* CLK0, f0 */
+		sst_dac_write(DACREG_ICS_PLLDATA, t->m);
+		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
+		/* selects freq f0 for clock 0 */
+		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
+		sst_dac_write(DACREG_ICS_PLLDATA,
+		              (pll_ctrl & 0xd8)
+		              | DACREG_ICS_CLK0
+		              | DACREG_ICS_CLK0_0);
+		break;
+	case GFX_CLOCK :
+		sst_dac_write(DACREG_ICS_PLLWMA, 0xa);	/* CLK1, fA */
+		sst_dac_write(DACREG_ICS_PLLDATA, t->m);
+		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
+		/* selects freq fA for clock 1 */
+		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
+		sst_dac_write(DACREG_ICS_PLLDATA,
+		              (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);
+		break;
+	default:
+		dprintk("%s: wrong clock code '%d'\n",
+		        __func__, clock);
+		return 0;
+		}
+	udelay(300);
+	return 1;
+}
+
+static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
+{
+	struct sstfb_par *par = info->par;
+	u8 cr0;
+
+	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
+	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
+	sst_dac_read(DACREG_RMR);
+	sst_dac_read(DACREG_RMR);
+	sst_dac_read(DACREG_RMR);
+	/* the fifth time,  CR0 is read */
+	cr0 = sst_dac_read(DACREG_RMR);
+
+	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
+	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
+	sst_dac_read(DACREG_RMR);
+	sst_dac_read(DACREG_RMR);
+	sst_dac_read(DACREG_RMR);
+	/* cr0 */
+	switch(bpp) {
+	case 16:
+		sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);
+		break;
+	default:
+		dprintk("%s: bad depth '%u'\n", __func__, bpp);
+		break;
+	}
+}
+
+static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
+{
+	struct sstfb_par *par = info->par;
+
+	switch(bpp) {
+	case 16:
+		sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
+		break;
+	default:
+		dprintk("%s: bad depth '%u'\n", __func__, bpp);
+		break;
+	}
+}
+
+/*
+ * detect dac type
+ * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
+ * dram refresh disabled, FbiInit remaped.
+ * TODO: mmh.. maybe i should put the "prerequisite" in the func ...
+ */
+
+
+static struct dac_switch dacs[] = {
+	{	.name		= "TI TVP3409",
+		.detect		= sst_detect_ti,
+		.set_pll	= sst_set_pll_att_ti,
+		.set_vidmod	= sst_set_vidmod_att_ti },
+
+	{	.name		= "AT&T ATT20C409",
+		.detect		= sst_detect_att,
+		.set_pll	= sst_set_pll_att_ti,
+		.set_vidmod	= sst_set_vidmod_att_ti },
+	{	.name		= "ICS ICS5342",
+		.detect		= sst_detect_ics,
+		.set_pll	= sst_set_pll_ics,
+		.set_vidmod	= sst_set_vidmod_ics },
+};
+
+static int sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < ARRAY_SIZE(dacs); i++) {
+		ret = dacs[i].detect(info);
+		if (ret)
+			break;
+	}
+	if (!ret)
+		return 0;
+	f_dprintk("%s found %s\n", __func__, dacs[i].name);
+	par->dac_sw = dacs[i];
+	return 1;
+}
+
+/*
+ * Internal Routines
+ */
+static int sst_init(struct fb_info *info, struct sstfb_par *par)
+{
+	u32 fbiinit0, fbiinit1, fbiinit4;
+	struct pci_dev *dev = par->dev;
+	struct pll_timing gfx_timings;
+	struct sst_spec *spec;
+	int Fout;
+	int gfx_clock;
+
+	spec = &voodoo_spec[par->type];
+	f_ddprintk(" fbiinit0   fbiinit1   fbiinit2   fbiinit3   fbiinit4  "
+	           " fbiinit6\n");
+	f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n",
+	            sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),
+	            sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));
+	/* disable video clock */
+	pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0);
+
+	/* enable writing to init registers, disable pci fifo */
+	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
+	/* reset video */
+	sst_set_bits(FBIINIT1, VIDEO_RESET);
+	sst_wait_idle();
+	/* reset gfx + pci fifo */
+	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
+	sst_wait_idle();
+
+	/* unreset fifo */
+	/*sst_unset_bits(FBIINIT0, FIFO_RESET);
+	sst_wait_idle();*/
+	/* unreset FBI */
+	/*sst_unset_bits(FBIINIT0, FBI_RESET);
+	sst_wait_idle();*/
+
+	/* disable dram refresh */
+	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
+	sst_wait_idle();
+	/* remap fbinit2/3 to dac */
+	pci_write_config_dword(dev, PCI_INIT_ENABLE,
+				PCI_EN_INIT_WR | PCI_REMAP_DAC );
+	/* detect dac type */
+	if (!sst_detect_dactype(info, par)) {
+		printk(KERN_ERR "sstfb: unknown dac type.\n");
+		//FIXME watch it: we are not in a safe state, bad bad bad.
+		return 0;
+	}
+
+	/* set graphic clock */
+	gfx_clock = spec->default_gfx_clock;
+	if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
+		printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);
+		 gfx_clock = gfxclk *1000;
+	} else if (gfxclk) {
+		printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);
+	}
+
+	sst_calc_pll(gfx_clock, &Fout, &gfx_timings);
+	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
+
+	/* disable fbiinit remap */
+	pci_write_config_dword(dev, PCI_INIT_ENABLE,
+	                       PCI_EN_INIT_WR| PCI_EN_FIFO_WR );
+	/* defaults init registers */
+	/* FbiInit0: unreset gfx, unreset fifo */
+	fbiinit0 = FBIINIT0_DEFAULT;
+	fbiinit1 = FBIINIT1_DEFAULT;
+	fbiinit4 = FBIINIT4_DEFAULT;
+	par->vgapass = vgapass;
+	if (par->vgapass)
+		fbiinit0 &= ~DIS_VGA_PASSTHROUGH;
+	else
+		fbiinit0 |= DIS_VGA_PASSTHROUGH;
+	if (slowpci) {
+		fbiinit1 |= SLOW_PCI_WRITES;
+		fbiinit4 |= SLOW_PCI_READS;
+	} else {
+		fbiinit1 &= ~SLOW_PCI_WRITES;
+		fbiinit4 &= ~SLOW_PCI_READS;
+	}
+	sst_write(FBIINIT0, fbiinit0);
+	sst_wait_idle();
+	sst_write(FBIINIT1, fbiinit1);
+	sst_wait_idle();
+	sst_write(FBIINIT2, FBIINIT2_DEFAULT);
+	sst_wait_idle();
+	sst_write(FBIINIT3, FBIINIT3_DEFAULT);
+	sst_wait_idle();
+	sst_write(FBIINIT4, fbiinit4);
+	sst_wait_idle();
+	if (IS_VOODOO2(par)) {
+		sst_write(FBIINIT6, FBIINIT6_DEFAULT);
+		sst_wait_idle();
+	}
+
+	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
+	pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);
+	return 1;
+}
+
+static void sst_shutdown(struct fb_info *info)
+{
+	struct sstfb_par *par = info->par;
+	struct pci_dev *dev = par->dev;
+	struct pll_timing gfx_timings;
+	int Fout;
+
+	/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */
+	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
+	sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);
+	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
+	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
+	sst_wait_idle();
+	pci_write_config_dword(dev, PCI_INIT_ENABLE,
+	                       PCI_EN_INIT_WR | PCI_REMAP_DAC);
+	/* set 20Mhz gfx clock */
+	sst_calc_pll(20000, &Fout, &gfx_timings);
+	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
+	/* TODO maybe shutdown the dac, vrefresh and so on... */
+	pci_write_config_dword(dev, PCI_INIT_ENABLE,
+	                       PCI_EN_INIT_WR);
+	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);
+	pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
+	/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct
+	 * from start ? */
+	pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);
+
+}
+
+/*
+ * Interface to the world
+ */
+static int sstfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt) continue;
+
+		f_ddprintk("option %s\n", this_opt);
+
+		if (!strcmp(this_opt, "vganopass"))
+			vgapass = 0;
+		else if (!strcmp(this_opt, "vgapass"))
+			vgapass = 1;
+		else if (!strcmp(this_opt, "clipping"))
+		        clipping = 1;
+		else if (!strcmp(this_opt, "noclipping"))
+		        clipping = 0;
+		else if (!strcmp(this_opt, "fastpci"))
+		        slowpci = 0;
+		else if (!strcmp(this_opt, "slowpci"))
+		        slowpci = 1;
+		else if (!strncmp(this_opt, "mem:",4))
+			mem = simple_strtoul (this_opt+4, NULL, 0);
+		else if (!strncmp(this_opt, "gfxclk:",7))
+			gfxclk = simple_strtoul (this_opt+7, NULL, 0);
+		else
+			mode_option = this_opt;
+	}
+	return 0;
+}
+
+
+static struct fb_ops sstfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= sstfb_check_var,
+	.fb_set_par	= sstfb_set_par,
+	.fb_setcolreg	= sstfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect, /* sstfb_fillrect */
+	.fb_copyarea	= cfb_copyarea, /* sstfb_copyarea */
+	.fb_imageblit	= cfb_imageblit,
+	.fb_ioctl	= sstfb_ioctl,
+};
+
+static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct fb_info *info;
+	struct fb_fix_screeninfo *fix;
+	struct sstfb_par *par;
+	struct sst_spec *spec;
+	int err;
+
+	/* Enable device in PCI config. */
+	if ((err=pci_enable_device(pdev))) {
+		printk(KERN_ERR "cannot enable device\n");
+		return err;
+	}
+
+	/* Allocate the fb and par structures.  */
+	info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	pci_set_drvdata(pdev, info);
+	
+	par  = info->par;
+	fix  = &info->fix;
+	
+	par->type = id->driver_data;
+	spec = &voodoo_spec[par->type];
+	f_ddprintk("found device : %s\n", spec->name);
+
+	par->dev = pdev;
+	par->revision = pdev->revision;
+
+	fix->mmio_start = pci_resource_start(pdev,0);
+	fix->mmio_len	= 0x400000;
+	fix->smem_start = fix->mmio_start + 0x400000;
+
+	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) {
+		printk(KERN_ERR "sstfb: cannot reserve mmio memory\n");
+		goto fail_mmio_mem;
+	}
+
+	if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {
+		printk(KERN_ERR "sstfb: cannot reserve fb memory\n");
+		goto fail_fb_mem;
+	}
+
+	par->mmio_vbase = ioremap_nocache(fix->mmio_start,
+					fix->mmio_len);
+	if (!par->mmio_vbase) {
+		printk(KERN_ERR "sstfb: cannot remap register area %#lx\n",
+		        fix->mmio_start);
+		goto fail_mmio_remap;
+	}
+	info->screen_base = ioremap_nocache(fix->smem_start, 0x400000);
+	if (!info->screen_base) {
+		printk(KERN_ERR "sstfb: cannot remap framebuffer %#lx\n",
+		        fix->smem_start);
+		goto fail_fb_remap;
+	}
+
+	if (!sst_init(info, par)) {
+		printk(KERN_ERR "sstfb: Init failed\n");
+		goto fail;
+	}
+	sst_get_memsize(info, &fix->smem_len);
+	strlcpy(fix->id, spec->name, sizeof(fix->id));
+
+	printk(KERN_INFO "%s (revision %d) with %s dac\n",
+		fix->id, par->revision, par->dac_sw.name);
+	printk(KERN_INFO "framebuffer at %#lx, mapped to 0x%p, size %dMB\n",
+	        fix->smem_start, info->screen_base,
+	        fix->smem_len >> 20);
+
+	f_ddprintk("regbase_virt: %#lx\n", par->mmio_vbase);
+	f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
+	f_ddprintk("fbbase_virt: %p\n", info->screen_base);
+
+	info->flags	= FBINFO_DEFAULT;
+	info->fbops	= &sstfb_ops;
+	info->pseudo_palette = par->palette;
+
+	fix->type	= FB_TYPE_PACKED_PIXELS;
+	fix->visual	= FB_VISUAL_TRUECOLOR;
+	fix->accel	= FB_ACCEL_NONE;  /* FIXME */
+	/*
+	 * According to the specs, the linelength must be of 1024 *pixels*
+	 * and the 24bpp mode is in fact a 32 bpp mode (and both are in
+	 * fact dithered to 16bit).
+	 */
+	fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
+	
+	fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
+
+	if (sstfb_check_var(&info->var, info)) {
+		printk(KERN_ERR "sstfb: invalid video mode.\n");
+		goto fail;
+	}
+
+	if (sstfb_set_par(info)) {
+		printk(KERN_ERR "sstfb: can't set default video mode.\n");
+		goto fail;
+	}
+	
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+		printk(KERN_ERR "sstfb: can't alloc cmap memory.\n");
+		goto fail;
+	}
+
+	/* register fb */
+	info->device = &pdev->dev;
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "sstfb: can't register framebuffer.\n");
+		goto fail_register;
+	}
+
+	sstfb_clear_screen(info);
+
+	if (device_create_file(info->dev, &device_attrs[0]))
+		printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");
+
+
+	fb_info(info, "%s frame buffer device at 0x%p\n",
+		fix->id, info->screen_base);
+
+	return 0;
+
+fail_register:
+	fb_dealloc_cmap(&info->cmap);
+fail:
+	iounmap(info->screen_base);
+fail_fb_remap:
+	iounmap(par->mmio_vbase);
+fail_mmio_remap:
+	release_mem_region(fix->smem_start, 0x400000);
+fail_fb_mem:
+	release_mem_region(fix->mmio_start, info->fix.mmio_len);
+fail_mmio_mem:
+	framebuffer_release(info);
+	return -ENXIO; 	/* no voodoo detected */
+}
+
+static void sstfb_remove(struct pci_dev *pdev)
+{
+	struct sstfb_par *par;
+	struct fb_info *info;
+
+	info = pci_get_drvdata(pdev);
+	par = info->par;
+	
+	device_remove_file(info->dev, &device_attrs[0]);
+	sst_shutdown(info);
+	iounmap(info->screen_base);
+	iounmap(par->mmio_vbase);
+	release_mem_region(info->fix.smem_start, 0x400000);
+	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+	fb_dealloc_cmap(&info->cmap);
+	unregister_framebuffer(info);
+	framebuffer_release(info);
+}
+
+
+static const struct pci_device_id sstfb_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),
+		.driver_data = ID_VOODOO1, },
+	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),
+		.driver_data = ID_VOODOO2, },
+	{ 0 },
+};
+
+static struct pci_driver sstfb_driver = {
+	.name		= "sstfb",
+	.id_table	= sstfb_id_tbl,
+	.probe		= sstfb_probe,
+	.remove		= sstfb_remove,
+};
+
+
+static int sstfb_init(void)
+{
+	char *option = NULL;
+
+	if (fb_get_options("sstfb", &option))
+		return -ENODEV;
+	sstfb_setup(option);
+
+	return pci_register_driver(&sstfb_driver);
+}
+
+static void sstfb_exit(void)
+{
+	pci_unregister_driver(&sstfb_driver);
+}
+
+
+module_init(sstfb_init);
+module_exit(sstfb_exit);
+
+MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
+MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
+MODULE_LICENSE("GPL");
+
+module_param(mem, int, 0);
+MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");
+module_param(vgapass, bool, 0);
+MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");
+module_param(clipping, bool, 0);
+MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");
+module_param(gfxclk, int, 0);
+MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
+module_param(slowpci, bool, 0);
+MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");
+
diff --git a/drivers/video/fbdev/sticore.h b/drivers/video/fbdev/sticore.h
new file mode 100644
index 000000000000..af1619536ac8
--- /dev/null
+++ b/drivers/video/fbdev/sticore.h
@@ -0,0 +1,401 @@
+#ifndef STICORE_H
+#define STICORE_H
+
+/* generic STI structures & functions */
+
+#if 0
+#define DPRINTK(x)	printk x
+#else
+#define DPRINTK(x) 
+#endif
+
+#define MAX_STI_ROMS 4		/* max no. of ROMs which this driver handles */
+
+#define STI_REGION_MAX 8	/* hardcoded STI constants */
+#define STI_DEV_NAME_LENGTH 32
+#define STI_MONITOR_MAX 256
+
+#define STI_FONT_HPROMAN8 1
+#define STI_FONT_KANA8 2
+
+#define ALT_CODE_TYPE_UNKNOWN 0x00	/* alt code type values */
+#define ALT_CODE_TYPE_PA_RISC_64 0x01
+
+/* The latency of the STI functions cannot really be reduced by setting
+ * this to 0;  STI doesn't seem to be designed to allow calling a different
+ * function (or the same function with different arguments) after a
+ * function exited with 1 as return value.
+ *
+ * As all of the functions below could be called from interrupt context,
+ * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
+ * block.  Really bad latency there.
+ *
+ * Probably the best solution to all this is have the generic code manage
+ * the screen buffer and a kernel thread to call STI occasionally.
+ * 
+ * Luckily, the frame buffer guys have the same problem so we can just wait
+ * for them to fix it and steal their solution.   prumpf
+ */
+ 
+#include <asm/io.h>
+
+#define STI_WAIT 1
+
+#define STI_PTR(p)	( virt_to_phys(p) )
+#define PTR_STI(p)	( phys_to_virt((unsigned long)p) )
+
+#define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x)
+#define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y)
+
+/* sti_font_xy() use the native font ROM ! */
+#define sti_font_x(sti) (PTR_STI(sti->font)->width)
+#define sti_font_y(sti) (PTR_STI(sti->font)->height)
+
+#ifdef CONFIG_64BIT
+#define STI_LOWMEM	(GFP_KERNEL | GFP_DMA)
+#else
+#define STI_LOWMEM	(GFP_KERNEL)
+#endif
+
+
+/* STI function configuration structs */
+
+typedef union region {
+	struct { 
+		u32 offset	: 14;	/* offset in 4kbyte page */
+		u32 sys_only	: 1;	/* don't map to user space */
+		u32 cache	: 1;	/* map to data cache */
+		u32 btlb	: 1;	/* map to block tlb */
+		u32 last	: 1;	/* last region in list */
+		u32 length	: 14;	/* length in 4kbyte page */
+	} region_desc;
+
+	u32 region;			/* complete region value */
+} region_t;
+
+#define REGION_OFFSET_TO_PHYS( rt, hpa ) \
+	(((rt).region_desc.offset << 12) + (hpa))
+
+struct sti_glob_cfg_ext {
+	 u8 curr_mon;			/* current monitor configured */
+	 u8 friendly_boot;		/* in friendly boot mode */
+	s16 power;			/* power calculation (in Watts) */
+	s32 freq_ref;			/* frequency reference */
+	u32 sti_mem_addr;		/* pointer to global sti memory (size=sti_mem_request) */
+	u32 future_ptr; 		/* pointer to future data */
+};
+
+struct sti_glob_cfg {
+	s32 text_planes;		/* number of planes used for text */
+	s16 onscreen_x;			/* screen width in pixels */
+	s16 onscreen_y;			/* screen height in pixels */
+	s16 offscreen_x;		/* offset width in pixels */
+	s16 offscreen_y;		/* offset height in pixels */
+	s16 total_x;			/* frame buffer width in pixels */
+	s16 total_y;			/* frame buffer height in pixels */
+	u32 region_ptrs[STI_REGION_MAX]; /* region pointers */
+	s32 reent_lvl;			/* storage for reentry level value */
+	u32 save_addr;			/* where to save or restore reentrant state */
+	u32 ext_ptr;			/* pointer to extended glob_cfg data structure */
+};
+
+
+/* STI init function structs */
+
+struct sti_init_flags {
+	u32 wait : 1;		/* should routine idle wait or not */
+	u32 reset : 1;		/* hard reset the device? */
+	u32 text : 1;		/* turn on text display planes? */
+	u32 nontext : 1;	/* turn on non-text display planes? */
+	u32 clear : 1;		/* clear text display planes? */
+	u32 cmap_blk : 1;	/* non-text planes cmap black? */
+	u32 enable_be_timer : 1; /* enable bus error timer */
+	u32 enable_be_int : 1;	/* enable bus error timer interrupt */
+	u32 no_chg_tx : 1;	/* don't change text settings */
+	u32 no_chg_ntx : 1;	/* don't change non-text settings */
+	u32 no_chg_bet : 1;	/* don't change berr timer settings */
+	u32 no_chg_bei : 1;	/* don't change berr int settings */
+	u32 init_cmap_tx : 1;	/* initialize cmap for text planes */
+	u32 cmt_chg : 1;	/* change current monitor type */
+	u32 retain_ie : 1;	/* don't allow reset to clear int enables */
+	u32 caller_bootrom : 1;	/* set only by bootrom for each call */
+	u32 caller_kernel : 1;	/* set only by kernel for each call */
+	u32 caller_other : 1;	/* set only by non-[BR/K] caller */
+	u32 pad	: 14;		/* pad to word boundary */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+struct sti_init_inptr_ext {
+	u8  config_mon_type;	/* configure to monitor type */
+	u8  pad[1];		/* pad to word boundary */
+	u16 inflight_data;	/* inflight data possible on PCI */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+struct sti_init_inptr {
+	s32 text_planes;	/* number of planes to use for text */
+	u32 ext_ptr;		/* pointer to extended init_graph inptr data structure*/
+};
+
+
+struct sti_init_outptr {
+	s32 errno;		/* error number on failure */
+	s32 text_planes;	/* number of planes used for text */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+
+
+/* STI configuration function structs */
+
+struct sti_conf_flags {
+	u32 wait : 1;		/* should routine idle wait or not */
+	u32 pad : 31;		/* pad to word boundary */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+struct sti_conf_inptr {
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+struct sti_conf_outptr_ext {
+	u32 crt_config[3];	/* hardware specific X11/OGL information */	
+	u32 crt_hdw[3];
+	u32 future_ptr;
+};
+
+struct sti_conf_outptr {
+	s32 errno;		/* error number on failure */
+	s16 onscreen_x;		/* screen width in pixels */
+	s16 onscreen_y;		/* screen height in pixels */
+	s16 offscreen_x;	/* offscreen width in pixels */
+	s16 offscreen_y;	/* offscreen height in pixels */
+	s16 total_x;		/* frame buffer width in pixels */
+	s16 total_y;		/* frame buffer height in pixels */
+	s32 bits_per_pixel;	/* bits/pixel device has configured */
+	s32 bits_used;		/* bits which can be accessed */
+	s32 planes;		/* number of fb planes in system */
+	 u8 dev_name[STI_DEV_NAME_LENGTH]; /* null terminated product name */
+	u32 attributes;		/* flags denoting attributes */
+	u32 ext_ptr;		/* pointer to future data */
+};
+
+struct sti_rom {
+	 u8 type[4];
+	 u8 res004;
+	 u8 num_mons;
+	 u8 revno[2];
+	u32 graphics_id[2];
+
+	u32 font_start;
+	u32 statesize;
+	u32 last_addr;
+	u32 region_list;
+
+	u16 reentsize;
+	u16 maxtime;
+	u32 mon_tbl_addr;
+	u32 user_data_addr;
+	u32 sti_mem_req;
+
+	u32 user_data_size;
+	u16 power;
+	 u8 bus_support;
+	 u8 ext_bus_support;
+	 u8 alt_code_type;
+	 u8 ext_dd_struct[3];
+	u32 cfb_addr;
+
+	u32 init_graph;
+	u32 state_mgmt;
+	u32 font_unpmv;
+	u32 block_move;
+	u32 self_test;
+	u32 excep_hdlr;
+	u32 inq_conf;
+	u32 set_cm_entry;
+	u32 dma_ctrl;
+	 u8 res040[7 * 4];
+	
+	u32 init_graph_addr;
+	u32 state_mgmt_addr;
+	u32 font_unp_addr;
+	u32 block_move_addr;
+	u32 self_test_addr;
+	u32 excep_hdlr_addr;
+	u32 inq_conf_addr;
+	u32 set_cm_entry_addr;
+	u32 image_unpack_addr;
+	u32 pa_risx_addrs[7];
+};
+
+struct sti_rom_font {
+	u16 first_char;
+	u16 last_char;
+	 u8 width;
+	 u8 height;
+	 u8 font_type;		/* language type */
+	 u8 bytes_per_char;
+	u32 next_font;
+	 u8 underline_height;
+	 u8 underline_pos;
+	 u8 res008[2];
+};
+
+/* sticore internal font handling */
+
+struct sti_cooked_font {
+        struct sti_rom_font *raw;
+	struct sti_cooked_font *next_font;
+};
+
+struct sti_cooked_rom {
+        struct sti_rom *raw;
+	struct sti_cooked_font *font_start;
+};
+
+/* STI font printing function structs */
+
+struct sti_font_inptr {
+	u32 font_start_addr;	/* address of font start */
+	s16 index;		/* index into font table of character */
+	u8 fg_color;		/* foreground color of character */
+	u8 bg_color;		/* background color of character */
+	s16 dest_x;		/* X location of character upper left */
+	s16 dest_y;		/* Y location of character upper left */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+struct sti_font_flags {
+	u32 wait : 1;		/* should routine idle wait or not */
+	u32 non_text : 1;	/* font unpack/move in non_text planes =1, text =0 */
+	u32 pad : 30;		/* pad to word boundary */
+	u32 future_ptr; 	/* pointer to future data */
+};
+	
+struct sti_font_outptr {
+	s32 errno;		/* error number on failure */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+/* STI blockmove structs */
+
+struct sti_blkmv_flags {
+	u32 wait : 1;		/* should routine idle wait or not */
+	u32 color : 1;		/* change color during move? */
+	u32 clear : 1;		/* clear during move? */
+	u32 non_text : 1;	/* block move in non_text planes =1, text =0 */
+	u32 pad : 28;		/* pad to word boundary */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+struct sti_blkmv_inptr {
+	u8 fg_color;		/* foreground color after move */
+	u8 bg_color;		/* background color after move */
+	s16 src_x;		/* source upper left pixel x location */
+	s16 src_y;		/* source upper left pixel y location */
+	s16 dest_x;		/* dest upper left pixel x location */
+	s16 dest_y;		/* dest upper left pixel y location */
+	s16 width;		/* block width in pixels */
+	s16 height;		/* block height in pixels */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+struct sti_blkmv_outptr {
+	s32 errno;		/* error number on failure */
+	u32 future_ptr; 	/* pointer to future data */
+};
+
+
+/* sti_all_data is an internal struct which needs to be allocated in
+ * low memory (< 4GB) if STI is used with 32bit STI on a 64bit kernel */
+
+struct sti_all_data {
+	struct sti_glob_cfg glob_cfg;
+	struct sti_glob_cfg_ext glob_cfg_ext;
+
+	struct sti_conf_inptr		inq_inptr;
+	struct sti_conf_outptr		inq_outptr; /* configuration */
+	struct sti_conf_outptr_ext	inq_outptr_ext;
+
+	struct sti_init_inptr_ext	init_inptr_ext;
+	struct sti_init_inptr		init_inptr;
+	struct sti_init_outptr		init_outptr;
+
+	struct sti_blkmv_inptr		blkmv_inptr;
+	struct sti_blkmv_outptr		blkmv_outptr;
+
+	struct sti_font_inptr		font_inptr;
+	struct sti_font_outptr		font_outptr;
+
+	/* leave as last entries */
+	unsigned long save_addr[1024 / sizeof(unsigned long)];
+	   /* min 256 bytes which is STI default, max sti->sti_mem_request */
+	unsigned long sti_mem_addr[256 / sizeof(unsigned long)];
+	/* do not add something below here ! */
+};
+
+/* internal generic STI struct */
+
+struct sti_struct {
+	spinlock_t lock;
+		
+	/* the following fields needs to be filled in by the word/byte routines */
+	int font_width;	
+	int font_height;
+	/* char **mon_strings; */
+	int sti_mem_request;
+	u32 graphics_id[2];
+
+	struct sti_cooked_rom *rom;
+
+	unsigned long font_unpmv;
+	unsigned long block_move;
+	unsigned long init_graph;
+	unsigned long inq_conf;
+
+	/* all following fields are initialized by the generic routines */
+	int text_planes;
+	region_t regions[STI_REGION_MAX];
+	unsigned long regions_phys[STI_REGION_MAX];
+
+	struct sti_glob_cfg *glob_cfg;	/* points into sti_all_data */
+
+	struct sti_cooked_font *font;	/* ptr to selected font (cooked) */
+
+	struct pci_dev *pd;
+
+	/* PCI data structures (pg. 17ff from sti.pdf) */
+	u8 rm_entry[16]; /* pci region mapper array == pci config space offset */
+
+	/* pointer to the fb_info where this STI device is used */
+	struct fb_info *info;
+
+	/* pointer to all internal data */
+	struct sti_all_data *sti_data;
+};
+
+
+/* sticore interface functions */
+
+struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
+
+
+/* sticore main function to call STI firmware */
+
+int sti_call(const struct sti_struct *sti, unsigned long func,
+		const void *flags, void *inptr, void *outptr,
+		struct sti_glob_cfg *glob_cfg);
+
+
+/* functions to call the STI ROM directly */
+
+void sti_putc(struct sti_struct *sti, int c, int y, int x);
+void sti_set(struct sti_struct *sti, int src_y, int src_x,
+	     int height, int width, u8 color);
+void sti_clear(struct sti_struct *sti, int src_y, int src_x,
+	       int height, int width, int c);
+void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
+	       int dst_y, int dst_x, int height, int width);
+
+#endif	/* STICORE_H */
diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c
new file mode 100644
index 000000000000..cfe8a2f905c5
--- /dev/null
+++ b/drivers/video/fbdev/stifb.c
@@ -0,0 +1,1417 @@
+/*
+ * linux/drivers/video/stifb.c - 
+ * Low level Frame buffer driver for HP workstations with 
+ * STI (standard text interface) video firmware.
+ *
+ * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>
+ * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+ * 
+ * Based on:
+ * - linux/drivers/video/artistfb.c -- Artist frame buffer driver
+ *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *   - based on skeletonfb, which was
+ *	Created 28 Dec 1997 by Geert Uytterhoeven
+ * - HP Xhp cfb-based X11 window driver for XFree86
+ *	(c)Copyright 1992 Hewlett-Packard Co.
+ *
+ * 
+ *  The following graphics display devices (NGLE family) are supported by this driver:
+ *
+ *  HPA4070A	known as "HCRX", a 1280x1024 color device with 8 planes
+ *  HPA4071A	known as "HCRX24", a 1280x1024 color device with 24 planes,
+ *		optionally available with a hardware accelerator as HPA4071A_Z
+ *  HPA1659A	known as "CRX", a 1280x1024 color device with 8 planes
+ *  HPA1439A	known as "CRX24", a 1280x1024 color device with 24 planes,
+ *		optionally available with a hardware accelerator.
+ *  HPA1924A	known as "GRX", a 1280x1024 grayscale device with 8 planes
+ *  HPA2269A	known as "Dual CRX", a 1280x1024 color device with 8 planes,
+ *		implements support for two displays on a single graphics card.
+ *  HP710C	internal graphics support optionally available on the HP9000s710 SPU,
+ *		supports 1280x1024 color displays with 8 planes.
+ *  HP710G	same as HP710C, 1280x1024 grayscale only
+ *  HP710L	same as HP710C, 1024x768 color only
+ *  HP712	internal graphics support on HP9000s712 SPU, supports 640x480, 
+ *		1024x768 or 1280x1024 color displays on 8 planes (Artist)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/* TODO:
+ *	- 1bpp mode is completely untested
+ *	- add support for h/w acceleration
+ *	- add hardware cursor
+ *	- automatically disable double buffering (e.g. on RDI precisionbook laptop)
+ */
+
+
+/* on supported graphic devices you may:
+ * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or
+ * #undef  FALLBACK_TO_1BPP to reject support for unsupported cards */
+#undef FALLBACK_TO_1BPP
+
+#undef DEBUG_STIFB_REGS		/* debug sti register accesses */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/grfioctl.h>	/* for HP-UX compatibility */
+#include <asm/uaccess.h>
+
+#include "sticore.h"
+
+/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
+#define REGION_BASE(fb_info, index) \
+	F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
+
+#define NGLEDEVDEPROM_CRT_REGION 1
+
+#define NR_PALETTE 256
+
+typedef struct {
+	__s32	video_config_reg;
+	__s32	misc_video_start;
+	__s32	horiz_timing_fmt;
+	__s32	serr_timing_fmt;
+	__s32	vert_timing_fmt;
+	__s32	horiz_state;
+	__s32	vert_state;
+	__s32	vtg_state_elements;
+	__s32	pipeline_delay;
+	__s32	misc_video_end;
+} video_setup_t;
+
+typedef struct {                  
+	__s16	sizeof_ngle_data;
+	__s16	x_size_visible;	    /* visible screen dim in pixels  */
+	__s16	y_size_visible;
+	__s16	pad2[15];
+	__s16	cursor_pipeline_delay;
+	__s16	video_interleaves;
+	__s32	pad3[11];
+} ngle_rom_t;
+
+struct stifb_info {
+	struct fb_info info;
+	unsigned int id;
+	ngle_rom_t ngle_rom;
+	struct sti_struct *sti;
+	int deviceSpecificConfig;
+	u32 pseudo_palette[16];
+};
+
+static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
+
+/* ------------------- chipset specific functions -------------------------- */
+
+/* offsets to graphic-chip internal registers */
+
+#define REG_1		0x000118
+#define REG_2		0x000480
+#define REG_3		0x0004a0
+#define REG_4		0x000600
+#define REG_6		0x000800
+#define REG_8		0x000820
+#define REG_9		0x000a04
+#define REG_10		0x018000
+#define REG_11		0x018004
+#define REG_12		0x01800c
+#define REG_13		0x018018
+#define REG_14  	0x01801c
+#define REG_15		0x200000
+#define REG_15b0	0x200000
+#define REG_16b1	0x200005
+#define REG_16b3	0x200007
+#define REG_21		0x200218
+#define REG_22		0x0005a0
+#define REG_23		0x0005c0
+#define REG_26		0x200118
+#define REG_27		0x200308
+#define REG_32		0x21003c
+#define REG_33		0x210040
+#define REG_34		0x200008
+#define REG_35		0x018010
+#define REG_38		0x210020
+#define REG_39		0x210120
+#define REG_40		0x210130
+#define REG_42		0x210028
+#define REG_43		0x21002c
+#define REG_44		0x210030
+#define REG_45		0x210034
+
+#define READ_BYTE(fb,reg)		gsc_readb((fb)->info.fix.mmio_start + (reg))
+#define READ_WORD(fb,reg)		gsc_readl((fb)->info.fix.mmio_start + (reg))
+
+
+#ifndef DEBUG_STIFB_REGS
+# define  DEBUG_OFF()
+# define  DEBUG_ON()
+# define WRITE_BYTE(value,fb,reg)	gsc_writeb((value),(fb)->info.fix.mmio_start + (reg))
+# define WRITE_WORD(value,fb,reg)	gsc_writel((value),(fb)->info.fix.mmio_start + (reg))
+#else
+  static int debug_on = 1;
+# define  DEBUG_OFF() debug_on=0
+# define  DEBUG_ON()  debug_on=1
+# define WRITE_BYTE(value,fb,reg)	do { if (debug_on) \
+						printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \
+							__func__, reg, value, READ_BYTE(fb,reg)); 		  \
+					gsc_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
+# define WRITE_WORD(value,fb,reg)	do { if (debug_on) \
+						printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \
+							__func__, reg, value, READ_WORD(fb,reg)); 		  \
+					gsc_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
+#endif /* DEBUG_STIFB_REGS */
+
+
+#define ENABLE	1	/* for enabling/disabling screen */	
+#define DISABLE 0
+
+#define NGLE_LOCK(fb_info)	do { } while (0) 
+#define NGLE_UNLOCK(fb_info)	do { } while (0)
+
+static void
+SETUP_HW(struct stifb_info *fb)
+{
+	char stat;
+
+	do {
+		stat = READ_BYTE(fb, REG_15b0);
+		if (!stat)
+	    		stat = READ_BYTE(fb, REG_15b0);
+	} while (stat);
+}
+
+
+static void
+SETUP_FB(struct stifb_info *fb)
+{	
+	unsigned int reg10_value = 0;
+	
+	SETUP_HW(fb);
+	switch (fb->id)
+	{
+		case CRT_ID_VISUALIZE_EG:
+		case S9000_ID_ARTIST:
+		case S9000_ID_A1659A:
+			reg10_value = 0x13601000;
+			break;
+		case S9000_ID_A1439A:
+			if (fb->info.var.bits_per_pixel == 32)						
+				reg10_value = 0xBBA0A000;
+			else 
+				reg10_value = 0x13601000;
+			break;
+		case S9000_ID_HCRX:
+			if (fb->info.var.bits_per_pixel == 32)
+				reg10_value = 0xBBA0A000;
+			else					
+				reg10_value = 0x13602000;
+			break;
+		case S9000_ID_TIMBER:
+		case CRX24_OVERLAY_PLANES:
+			reg10_value = 0x13602000;
+			break;
+	}
+	if (reg10_value)
+		WRITE_WORD(reg10_value, fb, REG_10);
+	WRITE_WORD(0x83000300, fb, REG_14);
+	SETUP_HW(fb);
+	WRITE_BYTE(1, fb, REG_16b1);
+}
+
+static void
+START_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
+{
+	SETUP_HW(fb);
+	WRITE_WORD(0xBBE0F000, fb, REG_10);
+	WRITE_WORD(0x03000300, fb, REG_14);
+	WRITE_WORD(~0, fb, REG_13);
+}
+
+static void
+WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color) 
+{
+	SETUP_HW(fb);
+	WRITE_WORD(((0x100+index)<<2), fb, REG_3);
+	WRITE_WORD(color, fb, REG_4);
+}
+
+static void
+FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb) 
+{		
+	WRITE_WORD(0x400, fb, REG_2);
+	if (fb->info.var.bits_per_pixel == 32) {
+		WRITE_WORD(0x83000100, fb, REG_1);
+	} else {
+		if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG)
+			WRITE_WORD(0x80000100, fb, REG_26);
+		else							
+			WRITE_WORD(0x80000100, fb, REG_1);
+	}
+	SETUP_FB(fb);
+}
+
+static void
+SETUP_RAMDAC(struct stifb_info *fb) 
+{
+	SETUP_HW(fb);
+	WRITE_WORD(0x04000000, fb, 0x1020);
+	WRITE_WORD(0xff000000, fb, 0x1028);
+}
+
+static void 
+CRX24_SETUP_RAMDAC(struct stifb_info *fb) 
+{
+	SETUP_HW(fb);
+	WRITE_WORD(0x04000000, fb, 0x1000);
+	WRITE_WORD(0x02000000, fb, 0x1004);
+	WRITE_WORD(0xff000000, fb, 0x1008);
+	WRITE_WORD(0x05000000, fb, 0x1000);
+	WRITE_WORD(0x02000000, fb, 0x1004);
+	WRITE_WORD(0x03000000, fb, 0x1008);
+}
+
+#if 0
+static void 
+HCRX_SETUP_RAMDAC(struct stifb_info *fb)
+{
+	WRITE_WORD(0xffffffff, fb, REG_32);
+}
+#endif
+
+static void 
+CRX24_SET_OVLY_MASK(struct stifb_info *fb)
+{
+	SETUP_HW(fb);
+	WRITE_WORD(0x13a02000, fb, REG_11);
+	WRITE_WORD(0x03000300, fb, REG_14);
+	WRITE_WORD(0x000017f0, fb, REG_3);
+	WRITE_WORD(0xffffffff, fb, REG_13);
+	WRITE_WORD(0xffffffff, fb, REG_22);
+	WRITE_WORD(0x00000000, fb, REG_23);
+}
+
+static void
+ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
+{
+	unsigned int value = enable ? 0x43000000 : 0x03000000;
+        SETUP_HW(fb);
+        WRITE_WORD(0x06000000,	fb, 0x1030);
+        WRITE_WORD(value, 	fb, 0x1038);
+}
+
+static void 
+CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
+{
+	unsigned int value = enable ? 0x10000000 : 0x30000000;
+	SETUP_HW(fb);
+	WRITE_WORD(0x01000000,	fb, 0x1000);
+	WRITE_WORD(0x02000000,	fb, 0x1004);
+	WRITE_WORD(value,	fb, 0x1008);
+}
+
+static void
+ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) 
+{
+	u32 DregsMiscVideo = REG_21;
+	u32 DregsMiscCtl = REG_27;
+	
+	SETUP_HW(fb);
+	if (enable) {
+	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo);
+	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   | 0x00800000, fb, DregsMiscCtl);
+	} else {
+	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) & ~0x0A000000, fb, DregsMiscVideo);
+	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   & ~0x00800000, fb, DregsMiscCtl);
+	}
+}
+
+#define GET_ROMTABLE_INDEX(fb) \
+	(READ_BYTE(fb, REG_16b3) - 1)
+
+#define HYPER_CONFIG_PLANES_24 0x00000100
+	
+#define IS_24_DEVICE(fb) \
+	(fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24)
+
+#define IS_888_DEVICE(fb) \
+	(!(IS_24_DEVICE(fb)))
+
+#define GET_FIFO_SLOTS(fb, cnt, numslots)	\
+{	while (cnt < numslots) 			\
+		cnt = READ_WORD(fb, REG_34);	\
+	cnt -= numslots;			\
+}
+
+#define	    IndexedDcd	0	/* Pixel data is indexed (pseudo) color */
+#define	    Otc04	2	/* Pixels in each longword transfer (4) */
+#define	    Otc32	5	/* Pixels in each longword transfer (32) */
+#define	    Ots08	3	/* Each pixel is size (8)d transfer (1) */
+#define	    OtsIndirect	6	/* Each bit goes through FG/BG color(8) */
+#define	    AddrLong	5	/* FB address is Long aligned (pixel) */
+#define	    BINovly	0x2	/* 8 bit overlay */
+#define	    BINapp0I	0x0	/* Application Buffer 0, Indexed */
+#define	    BINapp1I	0x1	/* Application Buffer 1, Indexed */
+#define	    BINapp0F8	0xa	/* Application Buffer 0, Fractional 8-8-8 */
+#define	    BINattr	0xd	/* Attribute Bitmap */
+#define	    RopSrc 	0x3
+#define	    BitmapExtent08  3	/* Each write hits ( 8) bits in depth */
+#define	    BitmapExtent32  5	/* Each write hits (32) bits in depth */
+#define	    DataDynamic	    0	/* Data register reloaded by direct access */
+#define	    MaskDynamic	    1	/* Mask register reloaded by direct access */
+#define	    MaskOtc	    0	/* Mask contains Object Count valid bits */
+
+#define MaskAddrOffset(offset) (offset)
+#define StaticReg(en) (en)
+#define BGx(en) (en)
+#define FGx(en) (en)
+
+#define BAJustPoint(offset) (offset)
+#define BAIndexBase(base) (base)
+#define BA(F,C,S,A,J,B,I) \
+	(((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))
+
+#define IBOvals(R,M,X,S,D,L,B,F) \
+	(((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))
+
+#define NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, val) \
+	WRITE_WORD(val, fb, REG_14)
+
+#define NGLE_QUICK_SET_DST_BM_ACCESS(fb, val) \
+	WRITE_WORD(val, fb, REG_11)
+
+#define NGLE_QUICK_SET_CTL_PLN_REG(fb, val) \
+	WRITE_WORD(val, fb, REG_12)
+
+#define NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, plnmsk32) \
+	WRITE_WORD(plnmsk32, fb, REG_13)
+
+#define NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, fg32) \
+	WRITE_WORD(fg32, fb, REG_35)
+
+#define NGLE_SET_TRANSFERDATA(fb, val) \
+	WRITE_WORD(val, fb, REG_8)
+
+#define NGLE_SET_DSTXY(fb, val) \
+	WRITE_WORD(val, fb, REG_6)
+
+#define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) (		\
+	(u32) (fbaddrbase) +					\
+	    (	(unsigned int)  ( (y) << 13      ) |		\
+		(unsigned int)  ( (x) << 2       )	)	\
+	)
+
+#define NGLE_BINC_SET_DSTADDR(fb, addr) \
+	WRITE_WORD(addr, fb, REG_3)
+
+#define NGLE_BINC_SET_SRCADDR(fb, addr) \
+	WRITE_WORD(addr, fb, REG_2)
+
+#define NGLE_BINC_SET_DSTMASK(fb, mask) \
+	WRITE_WORD(mask, fb, REG_22)
+
+#define NGLE_BINC_WRITE32(fb, data32) \
+	WRITE_WORD(data32, fb, REG_23)
+
+#define START_COLORMAPLOAD(fb, cmapBltCtlData32) \
+	WRITE_WORD((cmapBltCtlData32), fb, REG_38)
+
+#define SET_LENXY_START_RECFILL(fb, lenxy) \
+	WRITE_WORD(lenxy, fb, REG_9)
+
+static void
+HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
+{
+	u32 DregsHypMiscVideo = REG_33;
+	unsigned int value;
+	SETUP_HW(fb);
+	value = READ_WORD(fb, DregsHypMiscVideo);
+	if (enable)
+		value |= 0x0A000000;
+	else
+		value &= ~0x0A000000;
+	WRITE_WORD(value, fb, DregsHypMiscVideo);
+}
+
+
+/* BufferNumbers used by SETUP_ATTR_ACCESS() */
+#define BUFF0_CMAP0	0x00001e02
+#define BUFF1_CMAP0	0x02001e02
+#define BUFF1_CMAP3	0x0c001e02
+#define ARTIST_CMAP0	0x00000102
+#define HYPER_CMAP8	0x00000100
+#define HYPER_CMAP24	0x00000800
+
+static void
+SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber)
+{
+	SETUP_HW(fb);
+	WRITE_WORD(0x2EA0D000, fb, REG_11);
+	WRITE_WORD(0x23000302, fb, REG_14);
+	WRITE_WORD(BufferNumber, fb, REG_12);
+	WRITE_WORD(0xffffffff, fb, REG_8);
+}
+
+static void
+SET_ATTR_SIZE(struct stifb_info *fb, int width, int height) 
+{
+	/* REG_6 seems to have special values when run on a 
+	   RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or
+	   INTERNAL_EG_X1024).  The values are:
+		0x2f0: internal (LCD) & external display enabled
+		0x2a0: external display only
+		0x000: zero on standard artist graphic cards
+	*/ 
+	WRITE_WORD(0x00000000, fb, REG_6);
+	WRITE_WORD((width<<16) | height, fb, REG_9);
+	WRITE_WORD(0x05000000, fb, REG_6);
+	WRITE_WORD(0x00040001, fb, REG_9);
+}
+
+static void
+FINISH_ATTR_ACCESS(struct stifb_info *fb) 
+{
+	SETUP_HW(fb);
+	WRITE_WORD(0x00000000, fb, REG_12);
+}
+
+static void
+elkSetupPlanes(struct stifb_info *fb)
+{
+	SETUP_RAMDAC(fb);
+	SETUP_FB(fb);
+}
+
+static void 
+ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)
+{
+	SETUP_ATTR_ACCESS(fb, BufferNumber);
+	SET_ATTR_SIZE(fb, fb->info.var.xres, fb->info.var.yres);
+	FINISH_ATTR_ACCESS(fb);
+	SETUP_FB(fb);
+}
+
+
+static void
+rattlerSetupPlanes(struct stifb_info *fb)
+{
+	int saved_id, y;
+
+ 	/* Write RAMDAC pixel read mask register so all overlay
+	 * planes are display-enabled.  (CRX24 uses Bt462 pixel
+	 * read mask register for overlay planes, not image planes).
+	 */
+	CRX24_SETUP_RAMDAC(fb);
+    
+	/* change fb->id temporarily to fool SETUP_FB() */
+	saved_id = fb->id;
+	fb->id = CRX24_OVERLAY_PLANES;
+	SETUP_FB(fb);
+	fb->id = saved_id;
+
+	for (y = 0; y < fb->info.var.yres; ++y)
+		memset(fb->info.screen_base + y * fb->info.fix.line_length,
+			0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8);
+
+	CRX24_SET_OVLY_MASK(fb);
+	SETUP_FB(fb);
+}
+
+
+#define HYPER_CMAP_TYPE				0
+#define NGLE_CMAP_INDEXED0_TYPE			0
+#define NGLE_CMAP_OVERLAY_TYPE			3
+
+/* typedef of LUT (Colormap) BLT Control Register */
+typedef union	/* Note assumption that fields are packed left-to-right */
+{	u32 all;
+	struct
+	{
+		unsigned enable              :  1;
+		unsigned waitBlank           :  1;
+		unsigned reserved1           :  4;
+		unsigned lutOffset           : 10;   /* Within destination LUT */
+		unsigned lutType             :  2;   /* Cursor, image, overlay */
+		unsigned reserved2           :  4;
+		unsigned length              : 10;
+	} fields;
+} NgleLutBltCtl;
+
+
+#if 0
+static NgleLutBltCtl
+setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
+{
+	NgleLutBltCtl lutBltCtl;
+
+	/* set enable, zero reserved fields */
+	lutBltCtl.all           = 0x80000000;
+	lutBltCtl.fields.length = length;
+
+	switch (fb->id) 
+	{
+	case S9000_ID_A1439A:		/* CRX24 */
+		if (fb->var.bits_per_pixel == 8) {
+			lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE;
+			lutBltCtl.fields.lutOffset = 0;
+		} else {
+			lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
+			lutBltCtl.fields.lutOffset = 0 * 256;
+		}
+		break;
+		
+	case S9000_ID_ARTIST:
+		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
+		lutBltCtl.fields.lutOffset = 0 * 256;
+		break;
+		
+	default:
+		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
+		lutBltCtl.fields.lutOffset = 0;
+		break;
+	}
+
+	/* Offset points to start of LUT.  Adjust for within LUT */
+	lutBltCtl.fields.lutOffset += offsetWithinLut;
+
+	return lutBltCtl;
+}
+#endif
+
+static NgleLutBltCtl
+setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length) 
+{
+	NgleLutBltCtl lutBltCtl;
+
+	/* set enable, zero reserved fields */
+	lutBltCtl.all = 0x80000000;
+
+	lutBltCtl.fields.length = length;
+	lutBltCtl.fields.lutType = HYPER_CMAP_TYPE;
+
+	/* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */
+	if (fb->info.var.bits_per_pixel == 8)
+		lutBltCtl.fields.lutOffset = 2 * 256;
+	else
+		lutBltCtl.fields.lutOffset = 0 * 256;
+
+	/* Offset points to start of LUT.  Adjust for within LUT */
+	lutBltCtl.fields.lutOffset += offsetWithinLut;
+
+	return lutBltCtl;
+}
+
+
+static void hyperUndoITE(struct stifb_info *fb)
+{
+	int nFreeFifoSlots = 0;
+	u32 fbAddr;
+
+	NGLE_LOCK(fb);
+
+	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
+	WRITE_WORD(0xffffffff, fb, REG_32);
+
+	/* Write overlay transparency mask so only entry 255 is transparent */
+
+	/* Hardware setup for full-depth write to "magic" location */
+	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
+	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
+		BA(IndexedDcd, Otc04, Ots08, AddrLong,
+		BAJustPoint(0), BINovly, BAIndexBase(0)));
+	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
+		IBOvals(RopSrc, MaskAddrOffset(0),
+		BitmapExtent08, StaticReg(0),
+		DataDynamic, MaskOtc, BGx(0), FGx(0)));
+
+	/* Now prepare to write to the "magic" location */
+	fbAddr = NGLE_LONG_FB_ADDRESS(0, 1532, 0);
+	NGLE_BINC_SET_DSTADDR(fb, fbAddr);
+	NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffff);
+	NGLE_BINC_SET_DSTMASK(fb, 0xffffffff);
+
+	/* Finally, write a zero to clear the mask */
+	NGLE_BINC_WRITE32(fb, 0);
+
+	NGLE_UNLOCK(fb);
+}
+
+static void 
+ngleDepth8_ClearImagePlanes(struct stifb_info *fb)
+{
+	/* FIXME! */
+}
+
+static void 
+ngleDepth24_ClearImagePlanes(struct stifb_info *fb)
+{
+	/* FIXME! */
+}
+
+static void
+ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg)
+{
+	int nFreeFifoSlots = 0;
+	u32 packed_dst;
+	u32 packed_len;
+
+	NGLE_LOCK(fb);
+
+	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4);
+	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
+				     BA(IndexedDcd, Otc32, OtsIndirect,
+					AddrLong, BAJustPoint(0),
+					BINattr, BAIndexBase(0)));
+	NGLE_QUICK_SET_CTL_PLN_REG(fb, ctlPlaneReg);
+	NGLE_SET_TRANSFERDATA(fb, 0xffffffff);
+
+	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
+				       IBOvals(RopSrc, MaskAddrOffset(0),
+					       BitmapExtent08, StaticReg(1),
+					       DataDynamic, MaskOtc,
+					       BGx(0), FGx(0)));
+	packed_dst = 0;
+	packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
+	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
+	NGLE_SET_DSTXY(fb, packed_dst);
+	SET_LENXY_START_RECFILL(fb, packed_len);
+
+	/*
+	 * In order to work around an ELK hardware problem (Buffy doesn't
+	 * always flush it's buffers when writing to the attribute
+	 * planes), at least 4 pixels must be written to the attribute
+	 * planes starting at (X == 1280) and (Y != to the last Y written
+	 * by BIF):
+	 */
+
+	if (fb->id == S9000_ID_A1659A) {   /* ELK_DEVICE_ID */
+		/* It's safe to use scanline zero: */
+		packed_dst = (1280 << 16);
+		GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
+		NGLE_SET_DSTXY(fb, packed_dst);
+		packed_len = (4 << 16) | 1;
+		SET_LENXY_START_RECFILL(fb, packed_len);
+	}   /* ELK Hardware Kludge */
+
+	/**** Finally, set the Control Plane Register back to zero: ****/
+	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
+	NGLE_QUICK_SET_CTL_PLN_REG(fb, 0);
+	
+	NGLE_UNLOCK(fb);
+}
+    
+static void
+ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data)
+{
+	int nFreeFifoSlots = 0;
+	u32 packed_dst;
+	u32 packed_len;
+    
+	NGLE_LOCK(fb);
+
+	/* Hardware setup */
+	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8);
+	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
+				     BA(IndexedDcd, Otc04, Ots08, AddrLong,
+					BAJustPoint(0), BINovly, BAIndexBase(0)));
+
+        NGLE_SET_TRANSFERDATA(fb, 0xffffffff);  /* Write foreground color */
+
+        NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data);
+        NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask);
+    
+        packed_dst = 0;
+        packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
+        NGLE_SET_DSTXY(fb, packed_dst);
+    
+        /* Write zeroes to overlay planes */		       
+	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
+				       IBOvals(RopSrc, MaskAddrOffset(0),
+					       BitmapExtent08, StaticReg(0),
+					       DataDynamic, MaskOtc, BGx(0), FGx(0)));
+		       
+        SET_LENXY_START_RECFILL(fb, packed_len);
+
+	NGLE_UNLOCK(fb);
+}
+
+static void 
+hyperResetPlanes(struct stifb_info *fb, int enable)
+{
+	unsigned int controlPlaneReg;
+
+	NGLE_LOCK(fb);
+
+	if (IS_24_DEVICE(fb))
+		if (fb->info.var.bits_per_pixel == 32)
+			controlPlaneReg = 0x04000F00;
+		else
+			controlPlaneReg = 0x00000F00;   /* 0x00000800 should be enough, but lets clear all 4 bits */
+	else
+		controlPlaneReg = 0x00000F00; /* 0x00000100 should be enough, but lets clear all 4 bits */
+
+	switch (enable) {
+	case ENABLE:
+		/* clear screen */
+		if (IS_24_DEVICE(fb))
+			ngleDepth24_ClearImagePlanes(fb);
+		else
+			ngleDepth8_ClearImagePlanes(fb);
+
+		/* Paint attribute planes for default case.
+		 * On Hyperdrive, this means all windows using overlay cmap 0. */
+		ngleResetAttrPlanes(fb, controlPlaneReg);
+
+		/* clear overlay planes */
+	        ngleClearOverlayPlanes(fb, 0xff, 255);
+
+		/**************************************************
+		 ** Also need to counteract ITE settings 
+		 **************************************************/
+		hyperUndoITE(fb);
+		break;
+
+	case DISABLE:
+		/* clear screen */
+		if (IS_24_DEVICE(fb))
+			ngleDepth24_ClearImagePlanes(fb);
+		else
+			ngleDepth8_ClearImagePlanes(fb);
+		ngleResetAttrPlanes(fb, controlPlaneReg);
+		ngleClearOverlayPlanes(fb, 0xff, 0);
+		break;
+
+	case -1:	/* RESET */
+		hyperUndoITE(fb);
+		ngleResetAttrPlanes(fb, controlPlaneReg);
+		break;
+    	}
+	
+	NGLE_UNLOCK(fb);
+}
+
+/* Return pointer to in-memory structure holding ELK device-dependent ROM values. */
+
+static void 
+ngleGetDeviceRomData(struct stifb_info *fb)
+{
+#if 0
+XXX: FIXME: !!!
+	int	*pBytePerLongDevDepData;/* data byte == LSB */
+	int 	*pRomTable;
+	NgleDevRomData	*pPackedDevRomData;
+	int	sizePackedDevRomData = sizeof(*pPackedDevRomData);
+	char	*pCard8;
+	int	i;
+	char	*mapOrigin = NULL;
+    
+	int romTableIdx;
+
+	pPackedDevRomData = fb->ngle_rom;
+
+	SETUP_HW(fb);
+	if (fb->id == S9000_ID_ARTIST) {
+		pPackedDevRomData->cursor_pipeline_delay = 4;
+		pPackedDevRomData->video_interleaves     = 4;
+	} else {
+		/* Get pointer to unpacked byte/long data in ROM */
+		pBytePerLongDevDepData = fb->sti->regions[NGLEDEVDEPROM_CRT_REGION];
+
+		/* Tomcat supports several resolutions: 1280x1024, 1024x768, 640x480 */
+		if (fb->id == S9000_ID_TOMCAT)
+	{
+	    /*  jump to the correct ROM table  */
+	    GET_ROMTABLE_INDEX(romTableIdx);
+	    while  (romTableIdx > 0)
+	    {
+		pCard8 = (Card8 *) pPackedDevRomData;
+		pRomTable = pBytePerLongDevDepData;
+		/* Pack every fourth byte from ROM into structure */
+		for (i = 0; i < sizePackedDevRomData; i++)
+		{
+		    *pCard8++ = (Card8) (*pRomTable++);
+		}
+
+		pBytePerLongDevDepData = (Card32 *)
+			((Card8 *) pBytePerLongDevDepData +
+			       pPackedDevRomData->sizeof_ngle_data);
+
+		romTableIdx--;
+	    }
+	}
+
+	pCard8 = (Card8 *) pPackedDevRomData;
+
+	/* Pack every fourth byte from ROM into structure */
+	for (i = 0; i < sizePackedDevRomData; i++)
+	{
+	    *pCard8++ = (Card8) (*pBytePerLongDevDepData++);
+	}
+    }
+
+    SETUP_FB(fb);
+#endif
+}
+
+
+#define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES	4
+#define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE	8
+#define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE		10
+#define HYPERBOWL_MODE2_8_24					15
+
+/* HCRX specific boot-time initialization */
+static void __init
+SETUP_HCRX(struct stifb_info *fb)
+{
+	int	hyperbowl;
+        int	nFreeFifoSlots = 0;
+
+	if (fb->id != S9000_ID_HCRX)
+		return;
+
+	/* Initialize Hyperbowl registers */
+	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
+	
+	if (IS_24_DEVICE(fb)) {
+		hyperbowl = (fb->info.var.bits_per_pixel == 32) ?
+			HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE :
+			HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE;
+
+		/* First write to Hyperbowl must happen twice (bug) */
+		WRITE_WORD(hyperbowl, fb, REG_40);
+		WRITE_WORD(hyperbowl, fb, REG_40);
+		
+		WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39);
+		
+		WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */
+		WRITE_WORD(0x404c4048, fb, REG_43);
+		WRITE_WORD(0x034c0348, fb, REG_44);
+		WRITE_WORD(0x444c4448, fb, REG_45);
+	} else {
+		hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES;
+
+		/* First write to Hyperbowl must happen twice (bug) */
+		WRITE_WORD(hyperbowl, fb, REG_40);
+		WRITE_WORD(hyperbowl, fb, REG_40);
+
+		WRITE_WORD(0x00000000, fb, REG_42);
+		WRITE_WORD(0x00000000, fb, REG_43);
+		WRITE_WORD(0x00000000, fb, REG_44);
+		WRITE_WORD(0x444c4048, fb, REG_45);
+	}
+}
+
+
+/* ------------------- driver specific functions --------------------------- */
+
+static int
+stifb_setcolreg(u_int regno, u_int red, u_int green,
+	      u_int blue, u_int transp, struct fb_info *info)
+{
+	struct stifb_info *fb = (struct stifb_info *) info;
+	u32 color;
+
+	if (regno >= NR_PALETTE)
+		return 1;
+
+	red   >>= 8;
+	green >>= 8;
+	blue  >>= 8;
+
+	DEBUG_OFF();
+
+	START_IMAGE_COLORMAP_ACCESS(fb);
+
+	if (unlikely(fb->info.var.grayscale)) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		color = ((red * 77) +
+			 (green * 151) +
+			 (blue * 28)) >> 8;
+	} else {
+		color = ((red << 16) |
+			 (green << 8) |
+			 (blue));
+	}
+
+	if (fb->info.fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		struct fb_var_screeninfo *var = &fb->info.var;
+		if (regno < 16)
+			((u32 *)fb->info.pseudo_palette)[regno] =
+				regno << var->red.offset |
+				regno << var->green.offset |
+				regno << var->blue.offset;
+	}
+
+	WRITE_IMAGE_COLOR(fb, regno, color);
+
+	if (fb->id == S9000_ID_HCRX) {
+		NgleLutBltCtl lutBltCtl;
+
+		lutBltCtl = setHyperLutBltCtl(fb,
+				0,	/* Offset w/i LUT */
+				256);	/* Load entire LUT */
+		NGLE_BINC_SET_SRCADDR(fb,
+				NGLE_LONG_FB_ADDRESS(0, 0x100, 0)); 
+				/* 0x100 is same as used in WRITE_IMAGE_COLOR() */
+		START_COLORMAPLOAD(fb, lutBltCtl.all);
+		SETUP_FB(fb);
+	} else {
+		/* cleanup colormap hardware */
+		FINISH_IMAGE_COLORMAP_ACCESS(fb);
+	}
+
+	DEBUG_ON();
+
+	return 0;
+}
+
+static int
+stifb_blank(int blank_mode, struct fb_info *info)
+{
+	struct stifb_info *fb = (struct stifb_info *) info;
+	int enable = (blank_mode == 0) ? ENABLE : DISABLE;
+
+	switch (fb->id) {
+	case S9000_ID_A1439A:
+		CRX24_ENABLE_DISABLE_DISPLAY(fb, enable);
+		break;
+	case CRT_ID_VISUALIZE_EG:
+	case S9000_ID_ARTIST:
+		ARTIST_ENABLE_DISABLE_DISPLAY(fb, enable);
+		break;
+	case S9000_ID_HCRX:
+		HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);
+		break;
+	case S9000_ID_A1659A:	/* fall through */
+	case S9000_ID_TIMBER:
+	case CRX24_OVERLAY_PLANES:
+	default:
+		ENABLE_DISABLE_DISPLAY(fb, enable);
+		break;
+	}
+	
+	SETUP_FB(fb);
+	return 0;
+}
+
+static void __init
+stifb_init_display(struct stifb_info *fb)
+{
+	int id = fb->id;
+
+	SETUP_FB(fb);
+
+	/* HCRX specific initialization */
+	SETUP_HCRX(fb);
+	
+	/*
+	if (id == S9000_ID_HCRX)
+		hyperInitSprite(fb);
+	else
+		ngleInitSprite(fb);
+	*/
+	
+	/* Initialize the image planes. */ 
+        switch (id) {
+	 case S9000_ID_HCRX:
+	    hyperResetPlanes(fb, ENABLE);
+	    break;
+	 case S9000_ID_A1439A:
+	    rattlerSetupPlanes(fb);
+	    break;
+	 case S9000_ID_A1659A:
+	 case S9000_ID_ARTIST:
+	 case CRT_ID_VISUALIZE_EG:
+	    elkSetupPlanes(fb);
+	    break;
+	}
+
+	/* Clear attribute planes on non HCRX devices. */
+        switch (id) {
+	 case S9000_ID_A1659A:
+	 case S9000_ID_A1439A:
+	    if (fb->info.var.bits_per_pixel == 32)
+		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
+	    else {
+		ngleSetupAttrPlanes(fb, BUFF1_CMAP0);
+	    }
+	    if (id == S9000_ID_A1439A)
+		ngleClearOverlayPlanes(fb, 0xff, 0);
+	    break;
+	 case S9000_ID_ARTIST:
+	 case CRT_ID_VISUALIZE_EG:
+	    if (fb->info.var.bits_per_pixel == 32)
+		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
+	    else {
+		ngleSetupAttrPlanes(fb, ARTIST_CMAP0);
+	    }
+	    break;
+	}
+	stifb_blank(0, (struct fb_info *)fb);	/* 0=enable screen */
+
+	SETUP_FB(fb);
+}
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+static struct fb_ops stifb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= stifb_setcolreg,
+	.fb_blank	= stifb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+
+/*
+ *  Initialization
+ */
+
+static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
+{
+	struct fb_fix_screeninfo *fix;
+	struct fb_var_screeninfo *var;
+	struct stifb_info *fb;
+	struct fb_info *info;
+	unsigned long sti_rom_address;
+	char *dev_name;
+	int bpp, xres, yres;
+
+	fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
+	if (!fb) {
+		printk(KERN_ERR "stifb: Could not allocate stifb structure\n");
+		return -ENODEV;
+	}
+	
+	info = &fb->info;
+
+	/* set struct to a known state */
+	fix = &info->fix;
+	var = &info->var;
+
+	fb->sti = sti;
+	dev_name = sti->sti_data->inq_outptr.dev_name;
+	/* store upper 32bits of the graphics id */
+	fb->id = fb->sti->graphics_id[0];
+
+	/* only supported cards are allowed */
+	switch (fb->id) {
+	case CRT_ID_VISUALIZE_EG:
+		/* Visualize cards can run either in "double buffer" or
+ 		  "standard" mode. Depending on the mode, the card reports
+		  a different device name, e.g. "INTERNAL_EG_DX1024" in double
+		  buffer mode and "INTERNAL_EG_X1024" in standard mode.
+		  Since this driver only supports standard mode, we check
+		  if the device name contains the string "DX" and tell the
+		  user how to reconfigure the card. */
+		if (strstr(dev_name, "DX")) {
+		   printk(KERN_WARNING
+"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"
+"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",
+			dev_name);
+		   goto out_err0;
+		}
+		/* fall though */
+	case S9000_ID_ARTIST:
+	case S9000_ID_HCRX:
+	case S9000_ID_TIMBER:
+	case S9000_ID_A1659A:
+	case S9000_ID_A1439A:
+		break;
+	default:
+		printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",
+			dev_name, fb->id);
+		goto out_err0;
+	}
+	
+	/* default to 8 bpp on most graphic chips */
+	bpp = 8;
+	xres = sti_onscreen_x(fb->sti);
+	yres = sti_onscreen_y(fb->sti);
+
+	ngleGetDeviceRomData(fb);
+
+	/* get (virtual) io region base addr */
+	fix->mmio_start = REGION_BASE(fb,2);
+	fix->mmio_len   = 0x400000;
+
+       	/* Reject any device not in the NGLE family */
+	switch (fb->id) {
+	case S9000_ID_A1659A:	/* CRX/A1659A */
+		break;
+	case S9000_ID_ELM:	/* GRX, grayscale but else same as A1659A */
+		var->grayscale = 1;
+		fb->id = S9000_ID_A1659A;
+		break;
+	case S9000_ID_TIMBER:	/* HP9000/710 Any (may be a grayscale device) */
+		if (strstr(dev_name, "GRAYSCALE") || 
+		    strstr(dev_name, "Grayscale") ||
+		    strstr(dev_name, "grayscale"))
+			var->grayscale = 1;
+		break;
+	case S9000_ID_TOMCAT:	/* Dual CRX, behaves else like a CRX */
+		/* FIXME: TomCat supports two heads:
+		 * fb.iobase = REGION_BASE(fb_info,3);
+		 * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx);
+		 * for now we only support the left one ! */
+		xres = fb->ngle_rom.x_size_visible;
+		yres = fb->ngle_rom.y_size_visible;
+		fb->id = S9000_ID_A1659A;
+		break;
+	case S9000_ID_A1439A:	/* CRX24/A1439A */
+		bpp = 32;
+		break;
+	case S9000_ID_HCRX:	/* Hyperdrive/HCRX */
+		memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
+		if ((fb->sti->regions_phys[0] & 0xfc000000) ==
+		    (fb->sti->regions_phys[2] & 0xfc000000))
+			sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
+		else
+			sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
+
+		fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
+		if (IS_24_DEVICE(fb)) {
+			if (bpp_pref == 8 || bpp_pref == 32)
+				bpp = bpp_pref;
+			else
+				bpp = 32;
+		} else
+			bpp = 8;
+		READ_WORD(fb, REG_15);
+		SETUP_HW(fb);
+		break;
+	case CRT_ID_VISUALIZE_EG:
+	case S9000_ID_ARTIST:	/* Artist */
+		break;
+	default: 
+#ifdef FALLBACK_TO_1BPP
+	       	printk(KERN_WARNING 
+			"stifb: Unsupported graphics card (id=0x%08x) "
+				"- now trying 1bpp mode instead\n",
+			fb->id);
+		bpp = 1;	/* default to 1 bpp */
+		break;
+#else
+	       	printk(KERN_WARNING 
+			"stifb: Unsupported graphics card (id=0x%08x) "
+				"- skipping.\n",
+			fb->id);
+		goto out_err0;
+#endif
+	}
+
+
+	/* get framebuffer physical and virtual base addr & len (64bit ready) */
+	fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]);
+	fix->smem_len = fb->sti->regions[1].region_desc.length * 4096;
+
+	fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;
+	if (!fix->line_length)
+		fix->line_length = 2048; /* default */
+	
+	/* limit fbsize to max visible screen size */
+	if (fix->smem_len > yres*fix->line_length)
+		fix->smem_len = yres*fix->line_length;
+	
+	fix->accel = FB_ACCEL_NONE;
+
+	switch (bpp) {
+	    case 1:
+		fix->type = FB_TYPE_PLANES;	/* well, sort of */
+		fix->visual = FB_VISUAL_MONO10;
+		var->red.length = var->green.length = var->blue.length = 1;
+		break;
+	    case 8:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	    case 32:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->visual = FB_VISUAL_DIRECTCOLOR;
+		var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
+		var->blue.offset = 0;
+		var->green.offset = 8;
+		var->red.offset = 16;
+		var->transp.offset = 24;
+		break;
+	    default:
+		break;
+	}
+	
+	var->xres = var->xres_virtual = xres;
+	var->yres = var->yres_virtual = yres;
+	var->bits_per_pixel = bpp;
+
+	strcpy(fix->id, "stifb");
+	info->fbops = &stifb_ops;
+	info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len);
+	info->screen_size = fix->smem_len;
+	info->flags = FBINFO_DEFAULT;
+	info->pseudo_palette = &fb->pseudo_palette;
+
+	/* This has to be done !!! */
+	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0))
+		goto out_err1;
+	stifb_init_display(fb);
+
+	if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
+		printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",
+				fix->smem_start, fix->smem_start+fix->smem_len);
+		goto out_err2;
+	}
+		
+	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) {
+		printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n",
+				fix->mmio_start, fix->mmio_start+fix->mmio_len);
+		goto out_err3;
+	}
+
+	if (register_framebuffer(&fb->info) < 0)
+		goto out_err4;
+
+	sti->info = info; /* save for unregister_framebuffer() */
+
+	fb_info(&fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",
+		fix->id,
+		var->xres, 
+		var->yres,
+		var->bits_per_pixel,
+		dev_name,
+		fb->id, 
+		fix->mmio_start);
+
+	return 0;
+
+
+out_err4:
+	release_mem_region(fix->mmio_start, fix->mmio_len);
+out_err3:
+	release_mem_region(fix->smem_start, fix->smem_len);
+out_err2:
+	fb_dealloc_cmap(&info->cmap);
+out_err1:
+	iounmap(info->screen_base);
+out_err0:
+	kfree(fb);
+	return -ENXIO;
+}
+
+static int stifb_disabled __initdata;
+
+int __init
+stifb_setup(char *options);
+
+static int __init stifb_init(void)
+{
+	struct sti_struct *sti;
+	struct sti_struct *def_sti;
+	int i;
+	
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("stifb", &option))
+		return -ENODEV;
+	stifb_setup(option);
+#endif
+	if (stifb_disabled) {
+		printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
+		return -ENXIO;
+	}
+	
+	def_sti = sti_get_rom(0);
+	if (def_sti) {
+		for (i = 1; i <= MAX_STI_ROMS; i++) {
+			sti = sti_get_rom(i);
+			if (!sti)
+				break;
+			if (sti == def_sti) {
+				stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
+				break;
+			}
+		}
+	}
+
+	for (i = 1; i <= MAX_STI_ROMS; i++) {
+		sti = sti_get_rom(i);
+		if (!sti)
+			break;
+		if (sti == def_sti)
+			continue;
+		stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
+	}
+	return 0;
+}
+
+/*
+ *  Cleanup
+ */
+
+static void __exit
+stifb_cleanup(void)
+{
+	struct sti_struct *sti;
+	int i;
+	
+	for (i = 1; i <= MAX_STI_ROMS; i++) {
+		sti = sti_get_rom(i);
+		if (!sti)
+			break;
+		if (sti->info) {
+			struct fb_info *info = sti->info;
+			unregister_framebuffer(sti->info);
+			release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+		        release_mem_region(info->fix.smem_start, info->fix.smem_len);
+				if (info->screen_base)
+					iounmap(info->screen_base);
+		        fb_dealloc_cmap(&info->cmap);
+		        framebuffer_release(info);
+		}
+		sti->info = NULL;
+	}
+}
+
+int __init
+stifb_setup(char *options)
+{
+	int i;
+	
+	if (!options || !*options)
+		return 1;
+	
+	if (strncmp(options, "off", 3) == 0) {
+		stifb_disabled = 1;
+		options += 3;
+	}
+
+	if (strncmp(options, "bpp", 3) == 0) {
+		options += 3;
+		for (i = 0; i < MAX_STI_ROMS; i++) {
+			if (*options++ != ':')
+				break;
+			stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);
+		}
+	}
+	return 1;
+}
+
+__setup("stifb=", stifb_setup);
+
+module_init(stifb_init);
+module_exit(stifb_cleanup);
+
+MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/sunxvr1000.c b/drivers/video/fbdev/sunxvr1000.c
new file mode 100644
index 000000000000..58241b47a96d
--- /dev/null
+++ b/drivers/video/fbdev/sunxvr1000.c
@@ -0,0 +1,229 @@
+/* sunxvr1000.c: Sun XVR-1000 driver for sparc64 systems
+ *
+ * Copyright (C) 2010 David S. Miller (davem@davemloft.net)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/of_device.h>
+
+struct gfb_info {
+	struct fb_info		*info;
+
+	char __iomem		*fb_base;
+	unsigned long		fb_base_phys;
+
+	struct device_node	*of_node;
+
+	unsigned int		width;
+	unsigned int		height;
+	unsigned int		depth;
+	unsigned int		fb_size;
+
+	u32			pseudo_palette[16];
+};
+
+static int gfb_get_props(struct gfb_info *gp)
+{
+	gp->width = of_getintprop_default(gp->of_node, "width", 0);
+	gp->height = of_getintprop_default(gp->of_node, "height", 0);
+	gp->depth = of_getintprop_default(gp->of_node, "depth", 32);
+
+	if (!gp->width || !gp->height) {
+		printk(KERN_ERR "gfb: Critical properties missing for %s\n",
+		       gp->of_node->full_name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int gfb_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	u32 value;
+
+	if (regno < 16) {
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+
+		value = (blue << 16) | (green << 8) | red;
+		((u32 *)info->pseudo_palette)[regno] = value;
+	}
+
+	return 0;
+}
+
+static struct fb_ops gfb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= gfb_setcolreg,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+};
+
+static int gfb_set_fbinfo(struct gfb_info *gp)
+{
+	struct fb_info *info = gp->info;
+	struct fb_var_screeninfo *var = &info->var;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &gfb_ops;
+	info->screen_base = gp->fb_base;
+	info->screen_size = gp->fb_size;
+
+	info->pseudo_palette = gp->pseudo_palette;
+
+	/* Fill fix common fields */
+	strlcpy(info->fix.id, "gfb", sizeof(info->fix.id));
+        info->fix.smem_start = gp->fb_base_phys;
+        info->fix.smem_len = gp->fb_size;
+        info->fix.type = FB_TYPE_PACKED_PIXELS;
+	if (gp->depth == 32 || gp->depth == 24)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	var->xres = gp->width;
+	var->yres = gp->height;
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+	var->bits_per_pixel = gp->depth;
+
+	var->red.offset = 0;
+	var->red.length = 8;
+	var->green.offset = 8;
+	var->green.length = 8;
+	var->blue.offset = 16;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+		printk(KERN_ERR "gfb: Cannot allocate color map.\n");
+		return -ENOMEM;
+	}
+
+        return 0;
+}
+
+static int gfb_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct gfb_info *gp;
+	int err;
+
+	info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev);
+	if (!info) {
+		printk(KERN_ERR "gfb: Cannot allocate fb_info\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	gp = info->par;
+	gp->info = info;
+	gp->of_node = dp;
+
+	gp->fb_base_phys = op->resource[6].start;
+
+	err = gfb_get_props(gp);
+	if (err)
+		goto err_release_fb;
+
+	/* Framebuffer length is the same regardless of resolution. */
+	info->fix.line_length = 16384;
+	gp->fb_size = info->fix.line_length * gp->height;
+
+	gp->fb_base = of_ioremap(&op->resource[6], 0,
+				 gp->fb_size, "gfb fb");
+	if (!gp->fb_base) {
+		err = -ENOMEM;
+		goto err_release_fb;
+	}
+
+	err = gfb_set_fbinfo(gp);
+	if (err)
+		goto err_unmap_fb;
+
+	printk("gfb: Found device at %s\n", dp->full_name);
+
+	err = register_framebuffer(info);
+	if (err < 0) {
+		printk(KERN_ERR "gfb: Could not register framebuffer %s\n",
+		       dp->full_name);
+		goto err_unmap_fb;
+	}
+
+	dev_set_drvdata(&op->dev, info);
+
+	return 0;
+
+err_unmap_fb:
+	of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size);
+
+err_release_fb:
+        framebuffer_release(info);
+
+err_out:
+	return err;
+}
+
+static int gfb_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct gfb_info *gp = info->par;
+
+	unregister_framebuffer(info);
+
+	iounmap(gp->fb_base);
+
+	of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size);
+
+        framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id gfb_match[] = {
+	{
+		.name = "SUNW,gfb",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ffb_match);
+
+static struct platform_driver gfb_driver = {
+	.probe		= gfb_probe,
+	.remove		= gfb_remove,
+	.driver = {
+		.name		= "gfb",
+		.owner		= THIS_MODULE,
+		.of_match_table	= gfb_match,
+	},
+};
+
+static int __init gfb_init(void)
+{
+	if (fb_get_options("gfb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&gfb_driver);
+}
+
+static void __exit gfb_exit(void)
+{
+	platform_driver_unregister(&gfb_driver);
+}
+
+module_init(gfb_init);
+module_exit(gfb_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for Sun XVR-1000 graphics");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/sunxvr2500.c b/drivers/video/fbdev/sunxvr2500.c
new file mode 100644
index 000000000000..843b6bab0483
--- /dev/null
+++ b/drivers/video/fbdev/sunxvr2500.c
@@ -0,0 +1,276 @@
+/* s3d.c: Sun 3DLABS XVR-2500 et al. driver for sparc64 systems
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+
+struct s3d_info {
+	struct fb_info		*info;
+	struct pci_dev		*pdev;
+
+	char __iomem		*fb_base;
+	unsigned long		fb_base_phys;
+
+	struct device_node	*of_node;
+
+	unsigned int		width;
+	unsigned int		height;
+	unsigned int		depth;
+	unsigned int		fb_size;
+
+	u32			pseudo_palette[16];
+};
+
+static int s3d_get_props(struct s3d_info *sp)
+{
+	sp->width = of_getintprop_default(sp->of_node, "width", 0);
+	sp->height = of_getintprop_default(sp->of_node, "height", 0);
+	sp->depth = of_getintprop_default(sp->of_node, "depth", 8);
+
+	if (!sp->width || !sp->height) {
+		printk(KERN_ERR "s3d: Critical properties missing for %s\n",
+		       pci_name(sp->pdev));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int s3d_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	u32 value;
+
+	if (regno < 16) {
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+
+		value = (blue << 24) | (green << 16) | (red << 8);
+		((u32 *)info->pseudo_palette)[regno] = value;
+	}
+
+	return 0;
+}
+
+static struct fb_ops s3d_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= s3d_setcolreg,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+};
+
+static int s3d_set_fbinfo(struct s3d_info *sp)
+{
+	struct fb_info *info = sp->info;
+	struct fb_var_screeninfo *var = &info->var;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &s3d_ops;
+	info->screen_base = sp->fb_base;
+	info->screen_size = sp->fb_size;
+
+	info->pseudo_palette = sp->pseudo_palette;
+
+	/* Fill fix common fields */
+	strlcpy(info->fix.id, "s3d", sizeof(info->fix.id));
+        info->fix.smem_start = sp->fb_base_phys;
+        info->fix.smem_len = sp->fb_size;
+        info->fix.type = FB_TYPE_PACKED_PIXELS;
+	if (sp->depth == 32 || sp->depth == 24)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	var->xres = sp->width;
+	var->yres = sp->height;
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+	var->bits_per_pixel = sp->depth;
+
+	var->red.offset = 8;
+	var->red.length = 8;
+	var->green.offset = 16;
+	var->green.length = 8;
+	var->blue.offset = 24;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+		printk(KERN_ERR "s3d: Cannot allocate color map.\n");
+		return -ENOMEM;
+	}
+
+        return 0;
+}
+
+static int s3d_pci_register(struct pci_dev *pdev,
+			    const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct s3d_info *sp;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err < 0) {
+		printk(KERN_ERR "s3d: Cannot enable PCI device %s\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+
+	info = framebuffer_alloc(sizeof(struct s3d_info), &pdev->dev);
+	if (!info) {
+		printk(KERN_ERR "s3d: Cannot allocate fb_info\n");
+		err = -ENOMEM;
+		goto err_disable;
+	}
+
+	sp = info->par;
+	sp->info = info;
+	sp->pdev = pdev;
+	sp->of_node = pci_device_to_OF_node(pdev);
+	if (!sp->of_node) {
+		printk(KERN_ERR "s3d: Cannot find OF node of %s\n",
+		       pci_name(pdev));
+		err = -ENODEV;
+		goto err_release_fb;
+	}
+
+	sp->fb_base_phys = pci_resource_start (pdev, 1);
+
+	err = pci_request_region(pdev, 1, "s3d framebuffer");
+	if (err < 0) {
+		printk("s3d: Cannot request region 1 for %s\n",
+		       pci_name(pdev));
+		goto err_release_fb;
+	}
+
+	err = s3d_get_props(sp);
+	if (err)
+		goto err_release_pci;
+
+	/* XXX 'linebytes' is often wrong, it is equal to the width
+	 * XXX with depth of 32 on my XVR-2500 which is clearly not
+	 * XXX right.  So we don't try to use it.
+	 */
+	switch (sp->depth) {
+	case 8:
+		info->fix.line_length = sp->width;
+		break;
+	case 16:
+		info->fix.line_length = sp->width * 2;
+		break;
+	case 24:
+		info->fix.line_length = sp->width * 3;
+		break;
+	case 32:
+		info->fix.line_length = sp->width * 4;
+		break;
+	}
+	sp->fb_size = info->fix.line_length * sp->height;
+
+	sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size);
+	if (!sp->fb_base) {
+		err = -ENOMEM;
+		goto err_release_pci;
+	}
+
+	err = s3d_set_fbinfo(sp);
+	if (err)
+		goto err_unmap_fb;
+
+	pci_set_drvdata(pdev, info);
+
+	printk("s3d: Found device at %s\n", pci_name(pdev));
+
+	err = register_framebuffer(info);
+	if (err < 0) {
+		printk(KERN_ERR "s3d: Could not register framebuffer %s\n",
+		       pci_name(pdev));
+		goto err_unmap_fb;
+	}
+
+	return 0;
+
+err_unmap_fb:
+	iounmap(sp->fb_base);
+
+err_release_pci:
+	pci_release_region(pdev, 1);
+
+err_release_fb:
+        framebuffer_release(info);
+
+err_disable:
+	pci_disable_device(pdev);
+
+err_out:
+	return err;
+}
+
+static void s3d_pci_unregister(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct s3d_info *sp = info->par;
+
+	unregister_framebuffer(info);
+
+	iounmap(sp->fb_base);
+
+	pci_release_region(pdev, 1);
+
+        framebuffer_release(info);
+
+	pci_disable_device(pdev);
+}
+
+static struct pci_device_id s3d_pci_table[] = {
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002c),	},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002d),	},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002e),	},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002f),	},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0030),	},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0031),	},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0032),	},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0033),	},
+	{ 0, }
+};
+
+static struct pci_driver s3d_driver = {
+	.name		= "s3d",
+	.id_table	= s3d_pci_table,
+	.probe		= s3d_pci_register,
+	.remove		= s3d_pci_unregister,
+};
+
+static int __init s3d_init(void)
+{
+	if (fb_get_options("s3d", NULL))
+		return -ENODEV;
+
+	return pci_register_driver(&s3d_driver);
+}
+
+static void __exit s3d_exit(void)
+{
+	pci_unregister_driver(&s3d_driver);
+}
+
+module_init(s3d_init);
+module_exit(s3d_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for Sun XVR-2500 graphics");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/sunxvr500.c b/drivers/video/fbdev/sunxvr500.c
new file mode 100644
index 000000000000..387350d004df
--- /dev/null
+++ b/drivers/video/fbdev/sunxvr500.c
@@ -0,0 +1,462 @@
+/* sunxvr500.c: Sun 3DLABS XVR-500 Expert3D driver for sparc64 systems
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+
+/* XXX This device has a 'dev-comm' property which apparently is
+ * XXX a pointer into the openfirmware's address space which is
+ * XXX a shared area the kernel driver can use to keep OBP
+ * XXX informed about the current resolution setting.  The idea
+ * XXX is that the kernel can change resolutions, and as long
+ * XXX as the values in the 'dev-comm' area are accurate then
+ * XXX OBP can still render text properly to the console.
+ * XXX
+ * XXX I'm still working out the layout of this and whether there
+ * XXX are any signatures we need to look for etc.
+ */
+struct e3d_info {
+	struct fb_info		*info;
+	struct pci_dev		*pdev;
+
+	spinlock_t		lock;
+
+	char __iomem		*fb_base;
+	unsigned long		fb_base_phys;
+
+	unsigned long		fb8_buf_diff;
+	unsigned long		regs_base_phys;
+
+	void __iomem		*ramdac;
+
+	struct device_node	*of_node;
+
+	unsigned int		width;
+	unsigned int		height;
+	unsigned int		depth;
+	unsigned int		fb_size;
+
+	u32			fb_base_reg;
+	u32			fb8_0_off;
+	u32			fb8_1_off;
+
+	u32			pseudo_palette[16];
+};
+
+static int e3d_get_props(struct e3d_info *ep)
+{
+	ep->width = of_getintprop_default(ep->of_node, "width", 0);
+	ep->height = of_getintprop_default(ep->of_node, "height", 0);
+	ep->depth = of_getintprop_default(ep->of_node, "depth", 8);
+
+	if (!ep->width || !ep->height) {
+		printk(KERN_ERR "e3d: Critical properties missing for %s\n",
+		       pci_name(ep->pdev));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* My XVR-500 comes up, at 1280x768 and a FB base register value of
+ * 0x04000000, the following video layout register values:
+ *
+ * RAMDAC_VID_WH	0x03ff04ff
+ * RAMDAC_VID_CFG	0x1a0b0088
+ * RAMDAC_VID_32FB_0	0x04000000
+ * RAMDAC_VID_32FB_1	0x04800000
+ * RAMDAC_VID_8FB_0	0x05000000
+ * RAMDAC_VID_8FB_1	0x05200000
+ * RAMDAC_VID_XXXFB	0x05400000
+ * RAMDAC_VID_YYYFB	0x05c00000
+ * RAMDAC_VID_ZZZFB	0x05e00000
+ */
+/* Video layout registers */
+#define RAMDAC_VID_WH		0x00000070UL /* (height-1)<<16 | (width-1) */
+#define RAMDAC_VID_CFG		0x00000074UL /* 0x1a000088|(linesz_log2<<16) */
+#define RAMDAC_VID_32FB_0	0x00000078UL /* PCI base 32bpp FB buffer 0 */
+#define RAMDAC_VID_32FB_1	0x0000007cUL /* PCI base 32bpp FB buffer 1 */
+#define RAMDAC_VID_8FB_0	0x00000080UL /* PCI base 8bpp FB buffer 0 */
+#define RAMDAC_VID_8FB_1	0x00000084UL /* PCI base 8bpp FB buffer 1 */
+#define RAMDAC_VID_XXXFB	0x00000088UL /* PCI base of XXX FB */
+#define RAMDAC_VID_YYYFB	0x0000008cUL /* PCI base of YYY FB */
+#define RAMDAC_VID_ZZZFB	0x00000090UL /* PCI base of ZZZ FB */
+
+/* CLUT registers */
+#define RAMDAC_INDEX		0x000000bcUL
+#define RAMDAC_DATA		0x000000c0UL
+
+static void e3d_clut_write(struct e3d_info *ep, int index, u32 val)
+{
+	void __iomem *ramdac = ep->ramdac;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+
+	writel(index, ramdac + RAMDAC_INDEX);
+	writel(val, ramdac + RAMDAC_DATA);
+
+	spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static int e3d_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct e3d_info *ep = info->par;
+	u32 red_8, green_8, blue_8;
+	u32 red_10, green_10, blue_10;
+	u32 value;
+
+	if (regno >= 256)
+		return 1;
+
+	red_8 = red >> 8;
+	green_8 = green >> 8;
+	blue_8 = blue >> 8;
+
+	value = (blue_8 << 24) | (green_8 << 16) | (red_8 << 8);
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16)
+		((u32 *)info->pseudo_palette)[regno] = value;
+
+
+	red_10 = red >> 6;
+	green_10 = green >> 6;
+	blue_10 = blue >> 6;
+
+	value = (blue_10 << 20) | (green_10 << 10) | (red_10 << 0);
+	e3d_clut_write(ep, regno, value);
+
+	return 0;
+}
+
+/* XXX This is a bit of a hack.  I can't figure out exactly how the
+ * XXX two 8bpp areas of the framebuffer work.  I imagine there is
+ * XXX a WID attribute somewhere else in the framebuffer which tells
+ * XXX the ramdac which of the two 8bpp framebuffer regions to take
+ * XXX the pixel from.  So, for now, render into both regions to make
+ * XXX sure the pixel shows up.
+ */
+static void e3d_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct e3d_info *ep = info->par;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	cfb_imageblit(info, image);
+	info->screen_base += ep->fb8_buf_diff;
+	cfb_imageblit(info, image);
+	info->screen_base -= ep->fb8_buf_diff;
+	spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static void e3d_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct e3d_info *ep = info->par;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	cfb_fillrect(info, rect);
+	info->screen_base += ep->fb8_buf_diff;
+	cfb_fillrect(info, rect);
+	info->screen_base -= ep->fb8_buf_diff;
+	spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static void e3d_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct e3d_info *ep = info->par;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	cfb_copyarea(info, area);
+	info->screen_base += ep->fb8_buf_diff;
+	cfb_copyarea(info, area);
+	info->screen_base -= ep->fb8_buf_diff;
+	spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+static struct fb_ops e3d_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= e3d_setcolreg,
+	.fb_fillrect		= e3d_fillrect,
+	.fb_copyarea		= e3d_copyarea,
+	.fb_imageblit		= e3d_imageblit,
+};
+
+static int e3d_set_fbinfo(struct e3d_info *ep)
+{
+	struct fb_info *info = ep->info;
+	struct fb_var_screeninfo *var = &info->var;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &e3d_ops;
+	info->screen_base = ep->fb_base;
+	info->screen_size = ep->fb_size;
+
+	info->pseudo_palette = ep->pseudo_palette;
+
+	/* Fill fix common fields */
+	strlcpy(info->fix.id, "e3d", sizeof(info->fix.id));
+        info->fix.smem_start = ep->fb_base_phys;
+        info->fix.smem_len = ep->fb_size;
+        info->fix.type = FB_TYPE_PACKED_PIXELS;
+	if (ep->depth == 32 || ep->depth == 24)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	var->xres = ep->width;
+	var->yres = ep->height;
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+	var->bits_per_pixel = ep->depth;
+
+	var->red.offset = 8;
+	var->red.length = 8;
+	var->green.offset = 16;
+	var->green.length = 8;
+	var->blue.offset = 24;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+		printk(KERN_ERR "e3d: Cannot allocate color map.\n");
+		return -ENOMEM;
+	}
+
+        return 0;
+}
+
+static int e3d_pci_register(struct pci_dev *pdev,
+			    const struct pci_device_id *ent)
+{
+	struct device_node *of_node;
+	const char *device_type;
+	struct fb_info *info;
+	struct e3d_info *ep;
+	unsigned int line_length;
+	int err;
+
+	of_node = pci_device_to_OF_node(pdev);
+	if (!of_node) {
+		printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
+		       pci_name(pdev));
+		return -ENODEV;
+	}
+
+	device_type = of_get_property(of_node, "device_type", NULL);
+	if (!device_type) {
+		printk(KERN_INFO "e3d: Ignoring secondary output device "
+		       "at %s\n", pci_name(pdev));
+		return -ENODEV;
+	}
+
+	err = pci_enable_device(pdev);
+	if (err < 0) {
+		printk(KERN_ERR "e3d: Cannot enable PCI device %s\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+
+	info = framebuffer_alloc(sizeof(struct e3d_info), &pdev->dev);
+	if (!info) {
+		printk(KERN_ERR "e3d: Cannot allocate fb_info\n");
+		err = -ENOMEM;
+		goto err_disable;
+	}
+
+	ep = info->par;
+	ep->info = info;
+	ep->pdev = pdev;
+	spin_lock_init(&ep->lock);
+	ep->of_node = of_node;
+
+	/* Read the PCI base register of the frame buffer, which we
+	 * need in order to interpret the RAMDAC_VID_*FB* values in
+	 * the ramdac correctly.
+	 */
+	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
+			      &ep->fb_base_reg);
+	ep->fb_base_reg &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	ep->regs_base_phys = pci_resource_start (pdev, 1);
+	err = pci_request_region(pdev, 1, "e3d regs");
+	if (err < 0) {
+		printk("e3d: Cannot request region 1 for %s\n",
+		       pci_name(pdev));
+		goto err_release_fb;
+	}
+	ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000);
+	if (!ep->ramdac) {
+		err = -ENOMEM;
+		goto err_release_pci1;
+	}
+
+	ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);
+	ep->fb8_0_off -= ep->fb_base_reg;
+
+	ep->fb8_1_off = readl(ep->ramdac + RAMDAC_VID_8FB_1);
+	ep->fb8_1_off -= ep->fb_base_reg;
+
+	ep->fb8_buf_diff = ep->fb8_1_off - ep->fb8_0_off;
+
+	ep->fb_base_phys = pci_resource_start (pdev, 0);
+	ep->fb_base_phys += ep->fb8_0_off;
+
+	err = pci_request_region(pdev, 0, "e3d framebuffer");
+	if (err < 0) {
+		printk("e3d: Cannot request region 0 for %s\n",
+		       pci_name(pdev));
+		goto err_unmap_ramdac;
+	}
+
+	err = e3d_get_props(ep);
+	if (err)
+		goto err_release_pci0;
+
+	line_length = (readl(ep->ramdac + RAMDAC_VID_CFG) >> 16) & 0xff;
+	line_length = 1 << line_length;
+
+	switch (ep->depth) {
+	case 8:
+		info->fix.line_length = line_length;
+		break;
+	case 16:
+		info->fix.line_length = line_length * 2;
+		break;
+	case 24:
+		info->fix.line_length = line_length * 3;
+		break;
+	case 32:
+		info->fix.line_length = line_length * 4;
+		break;
+	}
+	ep->fb_size = info->fix.line_length * ep->height;
+
+	ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size);
+	if (!ep->fb_base) {
+		err = -ENOMEM;
+		goto err_release_pci0;
+	}
+
+	err = e3d_set_fbinfo(ep);
+	if (err)
+		goto err_unmap_fb;
+
+	pci_set_drvdata(pdev, info);
+
+	printk("e3d: Found device at %s\n", pci_name(pdev));
+
+	err = register_framebuffer(info);
+	if (err < 0) {
+		printk(KERN_ERR "e3d: Could not register framebuffer %s\n",
+		       pci_name(pdev));
+		goto err_free_cmap;
+	}
+
+	return 0;
+
+err_free_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+err_unmap_fb:
+	iounmap(ep->fb_base);
+
+err_release_pci0:
+	pci_release_region(pdev, 0);
+
+err_unmap_ramdac:
+	iounmap(ep->ramdac);
+
+err_release_pci1:
+	pci_release_region(pdev, 1);
+
+err_release_fb:
+        framebuffer_release(info);
+
+err_disable:
+	pci_disable_device(pdev);
+
+err_out:
+	return err;
+}
+
+static void e3d_pci_unregister(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct e3d_info *ep = info->par;
+
+	unregister_framebuffer(info);
+
+	iounmap(ep->ramdac);
+	iounmap(ep->fb_base);
+
+	pci_release_region(pdev, 0);
+	pci_release_region(pdev, 1);
+
+	fb_dealloc_cmap(&info->cmap);
+        framebuffer_release(info);
+
+	pci_disable_device(pdev);
+}
+
+static struct pci_device_id e3d_pci_table[] = {
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a0),	},
+	{	PCI_DEVICE(0x1091, 0x7a0),			},
+	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a2),	},
+	{	.vendor = PCI_VENDOR_ID_3DLABS,
+		.device = PCI_ANY_ID,
+		.subvendor = PCI_VENDOR_ID_3DLABS,
+		.subdevice = 0x0108,
+	},
+	{	.vendor = PCI_VENDOR_ID_3DLABS,
+		.device = PCI_ANY_ID,
+		.subvendor = PCI_VENDOR_ID_3DLABS,
+		.subdevice = 0x0140,
+	},
+	{	.vendor = PCI_VENDOR_ID_3DLABS,
+		.device = PCI_ANY_ID,
+		.subvendor = PCI_VENDOR_ID_3DLABS,
+		.subdevice = 0x1024,
+	},
+	{ 0, }
+};
+
+static struct pci_driver e3d_driver = {
+	.name		= "e3d",
+	.id_table	= e3d_pci_table,
+	.probe		= e3d_pci_register,
+	.remove		= e3d_pci_unregister,
+};
+
+static int __init e3d_init(void)
+{
+	if (fb_get_options("e3d", NULL))
+		return -ENODEV;
+
+	return pci_register_driver(&e3d_driver);
+}
+
+static void __exit e3d_exit(void)
+{
+	pci_unregister_driver(&e3d_driver);
+}
+
+module_init(e3d_init);
+module_exit(e3d_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for Sun XVR-500 graphics");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c
new file mode 100644
index 000000000000..7fb2d696fac7
--- /dev/null
+++ b/drivers/video/fbdev/tcx.c
@@ -0,0 +1,541 @@
+/* tcx.c: TCX frame buffer driver
+ *
+ * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int tcx_blank(int, struct fb_info *);
+
+static int tcx_mmap(struct fb_info *, struct vm_area_struct *);
+static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long);
+static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops tcx_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= tcx_setcolreg,
+	.fb_blank		= tcx_blank,
+	.fb_pan_display		= tcx_pan_display,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= tcx_mmap,
+	.fb_ioctl		= tcx_ioctl,
+#ifdef CONFIG_COMPAT
+	.fb_compat_ioctl	= sbusfb_compat_ioctl,
+#endif
+};
+
+/* THC definitions */
+#define TCX_THC_MISC_REV_SHIFT       16
+#define TCX_THC_MISC_REV_MASK        15
+#define TCX_THC_MISC_VSYNC_DIS       (1 << 25)
+#define TCX_THC_MISC_HSYNC_DIS       (1 << 24)
+#define TCX_THC_MISC_RESET           (1 << 12)
+#define TCX_THC_MISC_VIDEO           (1 << 10)
+#define TCX_THC_MISC_SYNC            (1 << 9)
+#define TCX_THC_MISC_VSYNC           (1 << 8)
+#define TCX_THC_MISC_SYNC_ENAB       (1 << 7)
+#define TCX_THC_MISC_CURS_RES        (1 << 6)
+#define TCX_THC_MISC_INT_ENAB        (1 << 5)
+#define TCX_THC_MISC_INT             (1 << 4)
+#define TCX_THC_MISC_INIT            0x9f
+#define TCX_THC_REV_REV_SHIFT        20
+#define TCX_THC_REV_REV_MASK         15
+#define TCX_THC_REV_MINREV_SHIFT     28
+#define TCX_THC_REV_MINREV_MASK      15
+
+/* The contents are unknown */
+struct tcx_tec {
+	u32 tec_matrix;
+	u32 tec_clip;
+	u32 tec_vdc;
+};
+
+struct tcx_thc {
+	u32 thc_rev;
+	u32 thc_pad0[511];
+	u32 thc_hs;		/* hsync timing */
+	u32 thc_hsdvs;
+	u32 thc_hd;
+	u32 thc_vs;		/* vsync timing */
+	u32 thc_vd;
+	u32 thc_refresh;
+	u32 thc_misc;
+	u32 thc_pad1[56];
+	u32 thc_cursxy;	/* cursor x,y position (16 bits each) */
+	u32 thc_cursmask[32];	/* cursor mask bits */
+	u32 thc_cursbits[32];	/* what to show where mask enabled */
+};
+
+struct bt_regs {
+	u32 addr;
+	u32 color_map;
+	u32 control;
+	u32 cursor;
+};
+
+#define TCX_MMAP_ENTRIES 14
+
+struct tcx_par {
+	spinlock_t		lock;
+	struct bt_regs		__iomem *bt;
+	struct tcx_thc		__iomem *thc;
+	struct tcx_tec		__iomem *tec;
+	u32			__iomem *cplane;
+
+	u32			flags;
+#define TCX_FLAG_BLANKED	0x00000001
+
+	unsigned long		which_io;
+
+	struct sbus_mmap_map	mmap_map[TCX_MMAP_ENTRIES];
+	int			lowdepth;
+};
+
+/* Reset control plane so that WID is 8-bit plane. */
+static void __tcx_set_control_plane(struct fb_info *info)
+{
+	struct tcx_par *par = info->par;
+	u32 __iomem *p, *pend;
+
+	if (par->lowdepth)
+		return;
+
+	p = par->cplane;
+	if (p == NULL)
+		return;
+	for (pend = p + info->fix.smem_len; p < pend; p++) {
+		u32 tmp = sbus_readl(p);
+
+		tmp &= 0xffffff;
+		sbus_writel(tmp, p);
+	}
+}
+
+static void tcx_reset(struct fb_info *info)
+{
+	struct tcx_par *par = (struct tcx_par *) info->par;
+	unsigned long flags;
+
+	spin_lock_irqsave(&par->lock, flags);
+	__tcx_set_control_plane(info);
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static int tcx_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	tcx_reset(info);
+	return 0;
+}
+
+/**
+ *      tcx_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int tcx_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct tcx_par *par = (struct tcx_par *) info->par;
+	struct bt_regs __iomem *bt = par->bt;
+	unsigned long flags;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	sbus_writel(regno << 24, &bt->addr);
+	sbus_writel(red << 24, &bt->color_map);
+	sbus_writel(green << 24, &bt->color_map);
+	sbus_writel(blue << 24, &bt->color_map);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *      tcx_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tcx_blank(int blank, struct fb_info *info)
+{
+	struct tcx_par *par = (struct tcx_par *) info->par;
+	struct tcx_thc __iomem *thc = par->thc;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	val = sbus_readl(&thc->thc_misc);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		val &= ~(TCX_THC_MISC_VSYNC_DIS |
+			 TCX_THC_MISC_HSYNC_DIS);
+		val |= TCX_THC_MISC_VIDEO;
+		par->flags &= ~TCX_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+		val &= ~TCX_THC_MISC_VIDEO;
+		par->flags |= TCX_FLAG_BLANKED;
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+		val |= TCX_THC_MISC_VSYNC_DIS;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+		val |= TCX_THC_MISC_HSYNC_DIS;
+		break;
+
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		break;
+	}
+
+	sbus_writel(val, &thc->thc_misc);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = {
+	{
+		.voff	= TCX_RAM8BIT,
+		.size	= SBUS_MMAP_FBSIZE(1)
+	},
+	{
+		.voff	= TCX_RAM24BIT,
+		.size	= SBUS_MMAP_FBSIZE(4)
+	},
+	{
+		.voff	= TCX_UNK3,
+		.size	= SBUS_MMAP_FBSIZE(8)
+	},
+	{
+		.voff	= TCX_UNK4,
+		.size	= SBUS_MMAP_FBSIZE(8)
+	},
+	{
+		.voff	= TCX_CONTROLPLANE,
+		.size	= SBUS_MMAP_FBSIZE(4)
+	},
+	{
+		.voff	= TCX_UNK6,
+		.size	= SBUS_MMAP_FBSIZE(8)
+	},
+	{
+		.voff	= TCX_UNK7,
+		.size	= SBUS_MMAP_FBSIZE(8)
+	},
+	{
+		.voff	= TCX_TEC,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= TCX_BTREGS,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= TCX_THC,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= TCX_DHC,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= TCX_ALT,
+		.size	= PAGE_SIZE
+	},
+	{
+		.voff	= TCX_UNK2,
+		.size	= 0x20000
+	},
+	{ .size = 0 }
+};
+
+static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct tcx_par *par = (struct tcx_par *)info->par;
+
+	return sbusfb_mmap_helper(par->mmap_map,
+				  info->fix.smem_start, info->fix.smem_len,
+				  par->which_io, vma);
+}
+
+static int tcx_ioctl(struct fb_info *info, unsigned int cmd,
+		     unsigned long arg)
+{
+	struct tcx_par *par = (struct tcx_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_TCXCOLOR,
+				   (par->lowdepth ? 8 : 24),
+				   info->fix.smem_len);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+tcx_init_fix(struct fb_info *info, int linebytes)
+{
+	struct tcx_par *par = (struct tcx_par *)info->par;
+	const char *tcx_name;
+
+	if (par->lowdepth)
+		tcx_name = "TCX8";
+	else
+		tcx_name = "TCX24";
+
+	strlcpy(info->fix.id, tcx_name, sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+	info->fix.line_length = linebytes;
+
+	info->fix.accel = FB_ACCEL_SUN_TCX;
+}
+
+static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
+			   struct tcx_par *par)
+{
+	if (par->tec)
+		of_iounmap(&op->resource[7],
+			   par->tec, sizeof(struct tcx_tec));
+	if (par->thc)
+		of_iounmap(&op->resource[9],
+			   par->thc, sizeof(struct tcx_thc));
+	if (par->bt)
+		of_iounmap(&op->resource[8],
+			   par->bt, sizeof(struct bt_regs));
+	if (par->cplane)
+		of_iounmap(&op->resource[4],
+			   par->cplane, info->fix.smem_len * sizeof(u32));
+	if (info->screen_base)
+		of_iounmap(&op->resource[0],
+			   info->screen_base, info->fix.smem_len);
+}
+
+static int tcx_probe(struct platform_device *op)
+{
+	struct device_node *dp = op->dev.of_node;
+	struct fb_info *info;
+	struct tcx_par *par;
+	int linebytes, i, err;
+
+	info = framebuffer_alloc(sizeof(struct tcx_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+
+	par->lowdepth =
+		(of_find_property(dp, "tcx-8-bit", NULL) != NULL);
+
+	sbusfb_fill_var(&info->var, dp, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
+
+	linebytes = of_getintprop_default(dp, "linebytes",
+					  info->var.xres);
+	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
+
+	par->tec = of_ioremap(&op->resource[7], 0,
+				  sizeof(struct tcx_tec), "tcx tec");
+	par->thc = of_ioremap(&op->resource[9], 0,
+				  sizeof(struct tcx_thc), "tcx thc");
+	par->bt = of_ioremap(&op->resource[8], 0,
+				 sizeof(struct bt_regs), "tcx dac");
+	info->screen_base = of_ioremap(&op->resource[0], 0,
+					   info->fix.smem_len, "tcx ram");
+	if (!par->tec || !par->thc ||
+	    !par->bt || !info->screen_base)
+		goto out_unmap_regs;
+
+	memcpy(&par->mmap_map, &__tcx_mmap_map, sizeof(par->mmap_map));
+	if (!par->lowdepth) {
+		par->cplane = of_ioremap(&op->resource[4], 0,
+					     info->fix.smem_len * sizeof(u32),
+					     "tcx cplane");
+		if (!par->cplane)
+			goto out_unmap_regs;
+	} else {
+		par->mmap_map[1].size = SBUS_MMAP_EMPTY;
+		par->mmap_map[4].size = SBUS_MMAP_EMPTY;
+		par->mmap_map[5].size = SBUS_MMAP_EMPTY;
+		par->mmap_map[6].size = SBUS_MMAP_EMPTY;
+	}
+
+	info->fix.smem_start = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+	for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
+		int j;
+
+		switch (i) {
+		case 10:
+			j = 12;
+			break;
+
+		case 11: case 12:
+			j = i - 1;
+			break;
+
+		default:
+			j = i;
+			break;
+		}
+		par->mmap_map[i].poff = op->resource[j].start;
+	}
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &tcx_ops;
+
+	/* Initialize brooktree DAC. */
+	sbus_writel(0x04 << 24, &par->bt->addr);         /* color planes */
+	sbus_writel(0xff << 24, &par->bt->control);
+	sbus_writel(0x05 << 24, &par->bt->addr);
+	sbus_writel(0x00 << 24, &par->bt->control);
+	sbus_writel(0x06 << 24, &par->bt->addr);         /* overlay plane */
+	sbus_writel(0x73 << 24, &par->bt->control);
+	sbus_writel(0x07 << 24, &par->bt->addr);
+	sbus_writel(0x00 << 24, &par->bt->control);
+
+	tcx_reset(info);
+
+	tcx_blank(FB_BLANK_UNBLANK, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
+
+	fb_set_cmap(&info->cmap, info);
+	tcx_init_fix(info, linebytes);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
+
+	printk(KERN_INFO "%s: TCX at %lx:%lx, %s\n",
+	       dp->full_name,
+	       par->which_io,
+	       info->fix.smem_start,
+	       par->lowdepth ? "8-bit only" : "24-bit depth");
+
+	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	tcx_unmap_regs(op, info, par);
+	framebuffer_release(info);
+
+out_err:
+	return err;
+}
+
+static int tcx_remove(struct platform_device *op)
+{
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct tcx_par *par = info->par;
+
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+
+	tcx_unmap_regs(op, info, par);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct of_device_id tcx_match[] = {
+	{
+		.name = "SUNW,tcx",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, tcx_match);
+
+static struct platform_driver tcx_driver = {
+	.driver = {
+		.name = "tcx",
+		.owner = THIS_MODULE,
+		.of_match_table = tcx_match,
+	},
+	.probe		= tcx_probe,
+	.remove		= tcx_remove,
+};
+
+static int __init tcx_init(void)
+{
+	if (fb_get_options("tcxfb", NULL))
+		return -ENODEV;
+
+	return platform_driver_register(&tcx_driver);
+}
+
+static void __exit tcx_exit(void)
+{
+	platform_driver_unregister(&tcx_driver);
+}
+
+module_init(tcx_init);
+module_exit(tcx_exit);
+
+MODULE_DESCRIPTION("framebuffer driver for TCX chipsets");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c
new file mode 100644
index 000000000000..f761fe375f5b
--- /dev/null
+++ b/drivers/video/fbdev/tdfxfb.c
@@ -0,0 +1,1686 @@
+/*
+ *
+ * tdfxfb.c
+ *
+ * Author: Hannu Mallat <hmallat@cc.hut.fi>
+ *
+ * Copyright © 1999 Hannu Mallat
+ * All rights reserved
+ *
+ * Created      : Thu Sep 23 18:17:43 1999, hmallat
+ * Last modified: Tue Nov  2 21:19:47 1999, hmallat
+ *
+ * I2C part copied from the i2c-voodoo3.c driver by:
+ * Frodo Looijaard <frodol@dds.nl>,
+ * Philip Edelbrock <phil@netroedge.com>,
+ * Ralph Metzler <rjkm@thp.uni-koeln.de>, and
+ * Mark D. Studebaker <mdsxyz123@yahoo.com>
+ *
+ * Lots of the information here comes from the Daryll Strauss' Banshee
+ * patches to the XF86 server, and the rest comes from the 3dfx
+ * Banshee specification. I'm very much indebted to Daryll for his
+ * work on the X server.
+ *
+ * Voodoo3 support was contributed Harold Oga. Lots of additions
+ * (proper acceleration, 24 bpp, hardware cursor) and bug fixes by Attila
+ * Kesmarki. Thanks guys!
+ *
+ * Voodoo1 and Voodoo2 support aren't relevant to this driver as they
+ * behave very differently from the Voodoo3/4/5. For anyone wanting to
+ * use frame buffer on the Voodoo1/2, see the sstfb driver (which is
+ * located at http://www.sourceforge.net/projects/sstfb).
+ *
+ * While I _am_ grateful to 3Dfx for releasing the specs for Banshee,
+ * I do wish the next version is a bit more complete. Without the XF86
+ * patches I couldn't have gotten even this far... for instance, the
+ * extensions to the VGA register set go completely unmentioned in the
+ * spec! Also, lots of references are made to the 'SST core', but no
+ * spec is publicly available, AFAIK.
+ *
+ * The structure of this driver comes pretty much from the Permedia
+ * driver by Ilario Nardinocchi, which in turn is based on skeletonfb.
+ *
+ * TODO:
+ * - multihead support (basically need to support an array of fb_infos)
+ * - support other architectures (PPC, Alpha); does the fact that the VGA
+ *   core can be accessed only thru I/O (not memory mapped) complicate
+ *   things?
+ *
+ * Version history:
+ *
+ * 0.1.4 (released 2002-05-28)	ported over to new fbdev api by James Simmons
+ *
+ * 0.1.3 (released 1999-11-02)	added Attila's panning support, code
+ *				reorg, hwcursor address page size alignment
+ *				(for mmapping both frame buffer and regs),
+ *				and my changes to get rid of hardcoded
+ *				VGA i/o register locations (uses PCI
+ *				configuration info now)
+ * 0.1.2 (released 1999-10-19)	added Attila Kesmarki's bug fixes and
+ *				improvements
+ * 0.1.1 (released 1999-10-07)	added Voodoo3 support by Harold Oga.
+ * 0.1.0 (released 1999-10-06)	initial version
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include <video/tdfx.h>
+
+#define DPRINTK(a, b...) pr_debug("fb: %s: " a, __func__ , ## b)
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#else
+/* duplicate asm/mtrr.h defines to work on archs without mtrr */
+#define MTRR_TYPE_WRCOMB     1
+
+static inline int mtrr_add(unsigned long base, unsigned long size,
+				unsigned int type, char increment)
+{
+    return -ENODEV;
+}
+static inline int mtrr_del(int reg, unsigned long base,
+				unsigned long size)
+{
+    return -ENODEV;
+}
+#endif
+
+#define BANSHEE_MAX_PIXCLOCK 270000
+#define VOODOO3_MAX_PIXCLOCK 300000
+#define VOODOO5_MAX_PIXCLOCK 350000
+
+static struct fb_fix_screeninfo tdfx_fix = {
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_3DFX_BANSHEE
+};
+
+static struct fb_var_screeninfo tdfx_var = {
+	/* "640x480, 8 bpp @ 60 Hz */
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual =	1024,
+	.bits_per_pixel = 8,
+	.red =		{0, 8, 0},
+	.blue =		{0, 8, 0},
+	.green =	{0, 8, 0},
+	.activate =	FB_ACTIVATE_NOW,
+	.height =	-1,
+	.width =	-1,
+	.accel_flags =	FB_ACCELF_TEXT,
+	.pixclock =	39722,
+	.left_margin =	40,
+	.right_margin =	24,
+	.upper_margin =	32,
+	.lower_margin =	11,
+	.hsync_len =	96,
+	.vsync_len =	2,
+	.vmode =	FB_VMODE_NONINTERLACED
+};
+
+/*
+ * PCI driver prototypes
+ */
+static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+static void tdfxfb_remove(struct pci_dev *pdev);
+
+static struct pci_device_id tdfxfb_id_table[] = {
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ 0, }
+};
+
+static struct pci_driver tdfxfb_driver = {
+	.name		= "tdfxfb",
+	.id_table	= tdfxfb_id_table,
+	.probe		= tdfxfb_probe,
+	.remove		= tdfxfb_remove,
+};
+
+MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
+
+/*
+ * Driver data
+ */
+static int nopan;
+static int nowrap = 1;      /* not implemented (yet) */
+static int hwcursor = 1;
+static char *mode_option;
+/* mtrr option */
+static bool nomtrr;
+
+/* -------------------------------------------------------------------------
+ *			Hardware-specific funcions
+ * ------------------------------------------------------------------------- */
+
+static inline u8 vga_inb(struct tdfx_par *par, u32 reg)
+{
+	return inb(par->iobase + reg - 0x300);
+}
+
+static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val)
+{
+	outb(val, par->iobase + reg - 0x300);
+}
+
+static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val)
+{
+	vga_outb(par, GRA_I, idx);
+	wmb();
+	vga_outb(par, GRA_D, val);
+	wmb();
+}
+
+static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val)
+{
+	vga_outb(par, SEQ_I, idx);
+	wmb();
+	vga_outb(par, SEQ_D, val);
+	wmb();
+}
+
+static inline u8 seq_inb(struct tdfx_par *par, u32 idx)
+{
+	vga_outb(par, SEQ_I, idx);
+	mb();
+	return vga_inb(par, SEQ_D);
+}
+
+static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val)
+{
+	vga_outb(par, CRT_I, idx);
+	wmb();
+	vga_outb(par, CRT_D, val);
+	wmb();
+}
+
+static inline u8 crt_inb(struct tdfx_par *par, u32 idx)
+{
+	vga_outb(par, CRT_I, idx);
+	mb();
+	return vga_inb(par, CRT_D);
+}
+
+static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val)
+{
+	unsigned char tmp;
+
+	tmp = vga_inb(par, IS1_R);
+	vga_outb(par, ATT_IW, idx);
+	vga_outb(par, ATT_IW, val);
+}
+
+static inline void vga_disable_video(struct tdfx_par *par)
+{
+	unsigned char s;
+
+	s = seq_inb(par, 0x01) | 0x20;
+	seq_outb(par, 0x00, 0x01);
+	seq_outb(par, 0x01, s);
+	seq_outb(par, 0x00, 0x03);
+}
+
+static inline void vga_enable_video(struct tdfx_par *par)
+{
+	unsigned char s;
+
+	s = seq_inb(par, 0x01) & 0xdf;
+	seq_outb(par, 0x00, 0x01);
+	seq_outb(par, 0x01, s);
+	seq_outb(par, 0x00, 0x03);
+}
+
+static inline void vga_enable_palette(struct tdfx_par *par)
+{
+	vga_inb(par, IS1_R);
+	mb();
+	vga_outb(par, ATT_IW, 0x20);
+}
+
+static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg)
+{
+	return readl(par->regbase_virt + reg);
+}
+
+static inline void tdfx_outl(struct tdfx_par *par, unsigned int reg, u32 val)
+{
+	writel(val, par->regbase_virt + reg);
+}
+
+static inline void banshee_make_room(struct tdfx_par *par, int size)
+{
+	/* Note: The Voodoo3's onboard FIFO has 32 slots. This loop
+	 * won't quit if you ask for more. */
+	while ((tdfx_inl(par, STATUS) & 0x1f) < size - 1)
+		cpu_relax();
+}
+
+static int banshee_wait_idle(struct fb_info *info)
+{
+	struct tdfx_par *par = info->par;
+	int i = 0;
+
+	banshee_make_room(par, 1);
+	tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP);
+
+	do {
+		if ((tdfx_inl(par, STATUS) & STATUS_BUSY) == 0)
+			i++;
+	} while (i < 3);
+
+	return 0;
+}
+
+/*
+ * Set the color of a palette entry in 8bpp mode
+ */
+static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c)
+{
+	banshee_make_room(par, 2);
+	tdfx_outl(par, DACADDR, regno);
+	/* read after write makes it working */
+	tdfx_inl(par, DACADDR);
+	tdfx_outl(par, DACDATA, c);
+}
+
+static u32 do_calc_pll(int freq, int *freq_out)
+{
+	int m, n, k, best_m, best_n, best_k, best_error;
+	int fref = 14318;
+
+	best_error = freq;
+	best_n = best_m = best_k = 0;
+
+	for (k = 3; k >= 0; k--) {
+		for (m = 63; m >= 0; m--) {
+			/*
+			 * Estimate value of n that produces target frequency
+			 * with current m and k
+			 */
+			int n_estimated = ((freq * (m + 2) << k) / fref) - 2;
+
+			/* Search neighborhood of estimated n */
+			for (n = max(0, n_estimated);
+				n <= min(255, n_estimated + 1);
+				n++) {
+				/*
+				 * Calculate PLL freqency with current m, k and
+				 * estimated n
+				 */
+				int f = (fref * (n + 2) / (m + 2)) >> k;
+				int error = abs(f - freq);
+
+				/*
+				 * If this is the closest we've come to the
+				 * target frequency then remember n, m and k
+				 */
+				if (error < best_error) {
+					best_error = error;
+					best_n = n;
+					best_m = m;
+					best_k = k;
+				}
+			}
+		}
+	}
+
+	n = best_n;
+	m = best_m;
+	k = best_k;
+	*freq_out = (fref * (n + 2) / (m + 2)) >> k;
+
+	return (n << 8) | (m << 2) | k;
+}
+
+static void do_write_regs(struct fb_info *info, struct banshee_reg *reg)
+{
+	struct tdfx_par *par = info->par;
+	int i;
+
+	banshee_wait_idle(info);
+
+	tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01);
+
+	crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */
+
+	banshee_make_room(par, 3);
+	tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF);
+	tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001);
+#if 0
+	tdfx_outl(par, PLLCTRL1, reg->mempll);
+	tdfx_outl(par, PLLCTRL2, reg->gfxpll);
+#endif
+	tdfx_outl(par, PLLCTRL0, reg->vidpll);
+
+	vga_outb(par, MISC_W, reg->misc[0x00] | 0x01);
+
+	for (i = 0; i < 5; i++)
+		seq_outb(par, i, reg->seq[i]);
+
+	for (i = 0; i < 25; i++)
+		crt_outb(par, i, reg->crt[i]);
+
+	for (i = 0; i < 9; i++)
+		gra_outb(par, i, reg->gra[i]);
+
+	for (i = 0; i < 21; i++)
+		att_outb(par, i, reg->att[i]);
+
+	crt_outb(par, 0x1a, reg->ext[0]);
+	crt_outb(par, 0x1b, reg->ext[1]);
+
+	vga_enable_palette(par);
+	vga_enable_video(par);
+
+	banshee_make_room(par, 9);
+	tdfx_outl(par, VGAINIT0, reg->vgainit0);
+	tdfx_outl(par, DACMODE, reg->dacmode);
+	tdfx_outl(par, VIDDESKSTRIDE, reg->stride);
+	tdfx_outl(par, HWCURPATADDR, reg->curspataddr);
+
+	tdfx_outl(par, VIDSCREENSIZE, reg->screensize);
+	tdfx_outl(par, VIDDESKSTART, reg->startaddr);
+	tdfx_outl(par, VIDPROCCFG, reg->vidcfg);
+	tdfx_outl(par, VGAINIT1, reg->vgainit1);
+	tdfx_outl(par, MISCINIT0, reg->miscinit0);
+
+	banshee_make_room(par, 8);
+	tdfx_outl(par, SRCBASE, reg->startaddr);
+	tdfx_outl(par, DSTBASE, reg->startaddr);
+	tdfx_outl(par, COMMANDEXTRA_2D, 0);
+	tdfx_outl(par, CLIP0MIN, 0);
+	tdfx_outl(par, CLIP0MAX, 0x0fff0fff);
+	tdfx_outl(par, CLIP1MIN, 0);
+	tdfx_outl(par, CLIP1MAX, 0x0fff0fff);
+	tdfx_outl(par, SRCXY, 0);
+
+	banshee_wait_idle(info);
+}
+
+static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
+{
+	u32 draminit0 = tdfx_inl(par, DRAMINIT0);
+	u32 draminit1 = tdfx_inl(par, DRAMINIT1);
+	u32 miscinit1;
+	int num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4;
+	int chip_size; /* in MB */
+	int has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM;
+
+	if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
+		/* Banshee/Voodoo3 */
+		chip_size = 2;
+		if (has_sgram && !(draminit0 & DRAMINIT0_SGRAM_TYPE))
+			chip_size = 1;
+	} else {
+		/* Voodoo4/5 */
+		has_sgram = 0;
+		chip_size = draminit0 & DRAMINIT0_SGRAM_TYPE_MASK;
+		chip_size = 1 << (chip_size >> DRAMINIT0_SGRAM_TYPE_SHIFT);
+	}
+
+	/* disable block writes for SDRAM */
+	miscinit1 = tdfx_inl(par, MISCINIT1);
+	miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS;
+	miscinit1 |= MISCINIT1_CLUT_INV;
+
+	banshee_make_room(par, 1);
+	tdfx_outl(par, MISCINIT1, miscinit1);
+	return num_chips * chip_size * 1024l * 1024;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct tdfx_par *par = info->par;
+	u32 lpitch;
+
+	if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
+	    var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
+		DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (var->xres != var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	if (var->xoffset) {
+		DPRINTK("xoffset not supported\n");
+		return -EINVAL;
+	}
+	var->yoffset = 0;
+
+	/*
+	 * Banshee doesn't support interlace, but Voodoo4/5 and probably
+	 * Voodoo3 do.
+	 * no direct information about device id now?
+	 *  use max_pixclock for this...
+	 */
+	if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) &&
+	    (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
+		DPRINTK("interlace not supported\n");
+		return -EINVAL;
+	}
+
+	if (info->monspecs.hfmax && info->monspecs.vfmax &&
+	    info->monspecs.dclkmax && fb_validate_mode(var, info) < 0) {
+		DPRINTK("mode outside monitor's specs\n");
+		return -EINVAL;
+	}
+
+	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
+	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
+
+	if (var->xres < 320 || var->xres > 2048) {
+		DPRINTK("width not supported: %u\n", var->xres);
+		return -EINVAL;
+	}
+
+	if (var->yres < 200 || var->yres > 2048) {
+		DPRINTK("height not supported: %u\n", var->yres);
+		return -EINVAL;
+	}
+
+	if (lpitch * var->yres_virtual > info->fix.smem_len) {
+		var->yres_virtual = info->fix.smem_len / lpitch;
+		if (var->yres_virtual < var->yres) {
+			DPRINTK("no memory for screen (%ux%ux%u)\n",
+				var->xres, var->yres_virtual,
+				var->bits_per_pixel);
+			return -EINVAL;
+		}
+	}
+
+	if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
+		DPRINTK("pixclock too high (%ldKHz)\n",
+			PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.length = 8;
+		var->red.offset = 0;
+		var->green = var->red;
+		var->blue = var->red;
+		break;
+	case 16:
+		var->red.offset   = 11;
+		var->red.length   = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset  = 0;
+		var->blue.length  = 5;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+	case 24:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	}
+	var->width = -1;
+	var->height = -1;
+
+	var->accel_flags = FB_ACCELF_TEXT;
+
+	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
+		var->xres, var->yres, var->bits_per_pixel);
+	return 0;
+}
+
+static int tdfxfb_set_par(struct fb_info *info)
+{
+	struct tdfx_par *par = info->par;
+	u32 hdispend = info->var.xres;
+	u32 hsyncsta = hdispend + info->var.right_margin;
+	u32 hsyncend = hsyncsta + info->var.hsync_len;
+	u32 htotal   = hsyncend + info->var.left_margin;
+	u32 hd, hs, he, ht, hbs, hbe;
+	u32 vd, vs, ve, vt, vbs, vbe;
+	struct banshee_reg reg;
+	int fout, freq;
+	u32 wd;
+	u32 cpp = (info->var.bits_per_pixel + 7) >> 3;
+
+	memset(&reg, 0, sizeof(reg));
+
+	reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE |
+		     VIDCFG_CURS_X11 |
+		     ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) |
+		     (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);
+
+	/* PLL settings */
+	freq = PICOS2KHZ(info->var.pixclock);
+
+	reg.vidcfg &= ~VIDCFG_2X;
+
+	if (freq > par->max_pixclock / 2) {
+		freq = freq > par->max_pixclock ? par->max_pixclock : freq;
+		reg.dacmode |= DACMODE_2X;
+		reg.vidcfg  |= VIDCFG_2X;
+		hdispend >>= 1;
+		hsyncsta >>= 1;
+		hsyncend >>= 1;
+		htotal   >>= 1;
+	}
+
+	wd = (hdispend >> 3) - 1;
+	hd  = wd;
+	hs  = (hsyncsta >> 3) - 1;
+	he  = (hsyncend >> 3) - 1;
+	ht  = (htotal >> 3) - 1;
+	hbs = hd;
+	hbe = ht;
+
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		vd = (info->var.yres << 1) - 1;
+		vs  = vd + (info->var.lower_margin << 1);
+		ve  = vs + (info->var.vsync_len << 1);
+		vt = ve + (info->var.upper_margin << 1) - 1;
+		reg.screensize = info->var.xres | (info->var.yres << 13);
+		reg.vidcfg |= VIDCFG_HALF_MODE;
+		reg.crt[0x09] = 0x80;
+	} else {
+		vd = info->var.yres - 1;
+		vs  = vd + info->var.lower_margin;
+		ve  = vs + info->var.vsync_len;
+		vt = ve + info->var.upper_margin - 1;
+		reg.screensize = info->var.xres | (info->var.yres << 12);
+		reg.vidcfg &= ~VIDCFG_HALF_MODE;
+	}
+	vbs = vd;
+	vbe = vt;
+
+	/* this is all pretty standard VGA register stuffing */
+	reg.misc[0x00] = 0x0f |
+			(info->var.xres < 400 ? 0xa0 :
+			 info->var.xres < 480 ? 0x60 :
+			 info->var.xres < 768 ? 0xe0 : 0x20);
+
+	reg.gra[0x05] = 0x40;
+	reg.gra[0x06] = 0x05;
+	reg.gra[0x07] = 0x0f;
+	reg.gra[0x08] = 0xff;
+
+	reg.att[0x00] = 0x00;
+	reg.att[0x01] = 0x01;
+	reg.att[0x02] = 0x02;
+	reg.att[0x03] = 0x03;
+	reg.att[0x04] = 0x04;
+	reg.att[0x05] = 0x05;
+	reg.att[0x06] = 0x06;
+	reg.att[0x07] = 0x07;
+	reg.att[0x08] = 0x08;
+	reg.att[0x09] = 0x09;
+	reg.att[0x0a] = 0x0a;
+	reg.att[0x0b] = 0x0b;
+	reg.att[0x0c] = 0x0c;
+	reg.att[0x0d] = 0x0d;
+	reg.att[0x0e] = 0x0e;
+	reg.att[0x0f] = 0x0f;
+	reg.att[0x10] = 0x41;
+	reg.att[0x12] = 0x0f;
+
+	reg.seq[0x00] = 0x03;
+	reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */
+	reg.seq[0x02] = 0x0f;
+	reg.seq[0x03] = 0x00;
+	reg.seq[0x04] = 0x0e;
+
+	reg.crt[0x00] = ht - 4;
+	reg.crt[0x01] = hd;
+	reg.crt[0x02] = hbs;
+	reg.crt[0x03] = 0x80 | (hbe & 0x1f);
+	reg.crt[0x04] = hs;
+	reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
+	reg.crt[0x06] = vt;
+	reg.crt[0x07] = ((vs & 0x200) >> 2) |
+			((vd & 0x200) >> 3) |
+			((vt & 0x200) >> 4) | 0x10 |
+			((vbs & 0x100) >> 5) |
+			((vs & 0x100) >> 6) |
+			((vd & 0x100) >> 7) |
+			((vt & 0x100) >> 8);
+	reg.crt[0x09] |= 0x40 | ((vbs & 0x200) >> 4);
+	reg.crt[0x10] = vs;
+	reg.crt[0x11] = (ve & 0x0f) | 0x20;
+	reg.crt[0x12] = vd;
+	reg.crt[0x13] = wd;
+	reg.crt[0x15] = vbs;
+	reg.crt[0x16] = vbe + 1;
+	reg.crt[0x17] = 0xc3;
+	reg.crt[0x18] = 0xff;
+
+	/* Banshee's nonvga stuff */
+	reg.ext[0x00] = (((ht & 0x100) >> 8) |
+			((hd & 0x100) >> 6) |
+			((hbs & 0x100) >> 4) |
+			((hbe & 0x40) >> 1) |
+			((hs & 0x100) >> 2) |
+			((he & 0x20) << 2));
+	reg.ext[0x01] = (((vt & 0x400) >> 10) |
+			((vd & 0x400) >> 8) |
+			((vbs & 0x400) >> 6) |
+			((vbe & 0x400) >> 4));
+
+	reg.vgainit0 =	VGAINIT0_8BIT_DAC     |
+			VGAINIT0_EXT_ENABLE   |
+			VGAINIT0_WAKEUP_3C3   |
+			VGAINIT0_ALT_READBACK |
+			VGAINIT0_EXTSHIFTOUT;
+	reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff;
+
+	if (hwcursor)
+		reg.curspataddr = info->fix.smem_len;
+
+	reg.cursloc   = 0;
+
+	reg.cursc0    = 0;
+	reg.cursc1    = 0xffffff;
+
+	reg.stride    = info->var.xres * cpp;
+	reg.startaddr = info->var.yoffset * reg.stride
+			+ info->var.xoffset * cpp;
+
+	reg.vidpll = do_calc_pll(freq, &fout);
+#if 0
+	reg.mempll = do_calc_pll(..., &fout);
+	reg.gfxpll = do_calc_pll(..., &fout);
+#endif
+
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+		reg.vidcfg |= VIDCFG_INTERLACE;
+	reg.miscinit0 = tdfx_inl(par, MISCINIT0);
+
+#if defined(__BIG_ENDIAN)
+	switch (info->var.bits_per_pixel) {
+	case 8:
+	case 24:
+		reg.miscinit0 &= ~(1 << 30);
+		reg.miscinit0 &= ~(1 << 31);
+		break;
+	case 16:
+		reg.miscinit0 |= (1 << 30);
+		reg.miscinit0 |= (1 << 31);
+		break;
+	case 32:
+		reg.miscinit0 |= (1 << 30);
+		reg.miscinit0 &= ~(1 << 31);
+		break;
+	}
+#endif
+	do_write_regs(info, &reg);
+
+	/* Now change fb_fix_screeninfo according to changes in par */
+	info->fix.line_length = reg.stride;
+	info->fix.visual = (info->var.bits_per_pixel == 8)
+				? FB_VISUAL_PSEUDOCOLOR
+				: FB_VISUAL_TRUECOLOR;
+	DPRINTK("Graphics mode is now set at %dx%d depth %d\n",
+		info->var.xres, info->var.yres, info->var.bits_per_pixel);
+	return 0;
+}
+
+/* A handy macro shamelessly pinched from matroxfb */
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
+
+static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp,
+			    struct fb_info *info)
+{
+	struct tdfx_par *par = info->par;
+	u32 rgbcol;
+
+	if (regno >= info->cmap.len || regno > 255)
+		return 1;
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		blue = (red * 77 + green * 151 + blue * 28) >> 8;
+		green = blue;
+		red = blue;
+	}
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_PSEUDOCOLOR:
+		rgbcol = (((u32)red   & 0xff00) << 8) |
+			 (((u32)green & 0xff00) << 0) |
+			 (((u32)blue  & 0xff00) >> 8);
+		do_setpalentry(par, regno, rgbcol);
+		break;
+	/* Truecolor has no hardware color palettes. */
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			rgbcol = (CNVT_TOHW(red, info->var.red.length) <<
+				  info->var.red.offset) |
+				(CNVT_TOHW(green, info->var.green.length) <<
+				 info->var.green.offset) |
+				(CNVT_TOHW(blue, info->var.blue.length) <<
+				 info->var.blue.offset) |
+				(CNVT_TOHW(transp, info->var.transp.length) <<
+				 info->var.transp.offset);
+			par->palette[regno] = rgbcol;
+		}
+
+		break;
+	default:
+		DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
+		break;
+	}
+
+	return 0;
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+static int tdfxfb_blank(int blank, struct fb_info *info)
+{
+	struct tdfx_par *par = info->par;
+	int vgablank = 1;
+	u32 dacmode = tdfx_inl(par, DACMODE);
+
+	dacmode &= ~(BIT(1) | BIT(3));
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */
+		vgablank = 0;
+		break;
+	case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */
+		break;
+	case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */
+		dacmode |= BIT(3);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */
+		dacmode |= BIT(1);
+		break;
+	case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */
+		dacmode |= BIT(1) | BIT(3);
+		break;
+	}
+
+	banshee_make_room(par, 1);
+	tdfx_outl(par, DACMODE, dacmode);
+	if (vgablank)
+		vga_disable_video(par);
+	else
+		vga_enable_video(par);
+	return 0;
+}
+
+/*
+ * Set the starting position of the visible screen to var->yoffset
+ */
+static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct tdfx_par *par = info->par;
+	u32 addr = var->yoffset * info->fix.line_length;
+
+	if (nopan || var->xoffset)
+		return -EINVAL;
+
+	banshee_make_room(par, 1);
+	tdfx_outl(par, VIDDESKSTART, addr);
+
+	return 0;
+}
+
+#ifdef CONFIG_FB_3DFX_ACCEL
+/*
+ * FillRect 2D command (solidfill or invert (via ROP_XOR))
+ */
+static void tdfxfb_fillrect(struct fb_info *info,
+			    const struct fb_fillrect *rect)
+{
+	struct tdfx_par *par = info->par;
+	u32 bpp = info->var.bits_per_pixel;
+	u32 stride = info->fix.line_length;
+	u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
+	int tdfx_rop;
+	u32 dx = rect->dx;
+	u32 dy = rect->dy;
+	u32 dstbase = 0;
+
+	if (rect->rop == ROP_COPY)
+		tdfx_rop = TDFX_ROP_COPY;
+	else
+		tdfx_rop = TDFX_ROP_XOR;
+
+	/* assume always rect->height < 4096 */
+	if (dy + rect->height > 4095) {
+		dstbase = stride * dy;
+		dy = 0;
+	}
+	/* assume always rect->width < 4096 */
+	if (dx + rect->width > 4095) {
+		dstbase += dx * bpp >> 3;
+		dx = 0;
+	}
+	banshee_make_room(par, 6);
+	tdfx_outl(par, DSTFORMAT, fmt);
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		tdfx_outl(par, COLORFORE, rect->color);
+	} else { /* FB_VISUAL_TRUECOLOR */
+		tdfx_outl(par, COLORFORE, par->palette[rect->color]);
+	}
+	tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
+	tdfx_outl(par, DSTBASE, dstbase);
+	tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
+	tdfx_outl(par, LAUNCH_2D, dx | (dy << 16));
+}
+
+/*
+ * Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
+ */
+static void tdfxfb_copyarea(struct fb_info *info,
+			    const struct fb_copyarea *area)
+{
+	struct tdfx_par *par = info->par;
+	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
+	u32 bpp = info->var.bits_per_pixel;
+	u32 stride = info->fix.line_length;
+	u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
+	u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
+	u32 dstbase = 0;
+	u32 srcbase = 0;
+
+	/* assume always area->height < 4096 */
+	if (sy + area->height > 4095) {
+		srcbase = stride * sy;
+		sy = 0;
+	}
+	/* assume always area->width < 4096 */
+	if (sx + area->width > 4095) {
+		srcbase += sx * bpp >> 3;
+		sx = 0;
+	}
+	/* assume always area->height < 4096 */
+	if (dy + area->height > 4095) {
+		dstbase = stride * dy;
+		dy = 0;
+	}
+	/* assume always area->width < 4096 */
+	if (dx + area->width > 4095) {
+		dstbase += dx * bpp >> 3;
+		dx = 0;
+	}
+
+	if (area->sx <= area->dx) {
+		/* -X */
+		blitcmd |= BIT(14);
+		sx += area->width - 1;
+		dx += area->width - 1;
+	}
+	if (area->sy <= area->dy) {
+		/* -Y */
+		blitcmd |= BIT(15);
+		sy += area->height - 1;
+		dy += area->height - 1;
+	}
+
+	banshee_make_room(par, 8);
+
+	tdfx_outl(par, SRCFORMAT, fmt);
+	tdfx_outl(par, DSTFORMAT, fmt);
+	tdfx_outl(par, COMMAND_2D, blitcmd);
+	tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
+	tdfx_outl(par, DSTXY, dx | (dy << 16));
+	tdfx_outl(par, SRCBASE, srcbase);
+	tdfx_outl(par, DSTBASE, dstbase);
+	tdfx_outl(par, LAUNCH_2D, sx | (sy << 16));
+}
+
+static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct tdfx_par *par = info->par;
+	int size = image->height * ((image->width * image->depth + 7) >> 3);
+	int fifo_free;
+	int i, stride = info->fix.line_length;
+	u32 bpp = info->var.bits_per_pixel;
+	u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
+	u8 *chardata = (u8 *) image->data;
+	u32 srcfmt;
+	u32 dx = image->dx;
+	u32 dy = image->dy;
+	u32 dstbase = 0;
+
+	if (image->depth != 1) {
+#ifdef BROKEN_CODE
+		banshee_make_room(par, 6 + ((size + 3) >> 2));
+		srcfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13) |
+			0x400000;
+#else
+		cfb_imageblit(info, image);
+#endif
+		return;
+	}
+	banshee_make_room(par, 9);
+	switch (info->fix.visual) {
+	case FB_VISUAL_PSEUDOCOLOR:
+		tdfx_outl(par, COLORFORE, image->fg_color);
+		tdfx_outl(par, COLORBACK, image->bg_color);
+		break;
+	case FB_VISUAL_TRUECOLOR:
+	default:
+		tdfx_outl(par, COLORFORE,
+			  par->palette[image->fg_color]);
+		tdfx_outl(par, COLORBACK,
+			  par->palette[image->bg_color]);
+	}
+#ifdef __BIG_ENDIAN
+	srcfmt = 0x400000 | BIT(20);
+#else
+	srcfmt = 0x400000;
+#endif
+	/* assume always image->height < 4096 */
+	if (dy + image->height > 4095) {
+		dstbase = stride * dy;
+		dy = 0;
+	}
+	/* assume always image->width < 4096 */
+	if (dx + image->width > 4095) {
+		dstbase += dx * bpp >> 3;
+		dx = 0;
+	}
+
+	tdfx_outl(par, DSTBASE, dstbase);
+	tdfx_outl(par, SRCXY, 0);
+	tdfx_outl(par, DSTXY, dx | (dy << 16));
+	tdfx_outl(par, COMMAND_2D,
+		  COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
+	tdfx_outl(par, SRCFORMAT, srcfmt);
+	tdfx_outl(par, DSTFORMAT, dstfmt);
+	tdfx_outl(par, DSTSIZE, image->width | (image->height << 16));
+
+	/* A count of how many free FIFO entries we've requested.
+	 * When this goes negative, we need to request more. */
+	fifo_free = 0;
+
+	/* Send four bytes at a time of data */
+	for (i = (size >> 2); i > 0; i--) {
+		if (--fifo_free < 0) {
+			fifo_free = 31;
+			banshee_make_room(par, fifo_free);
+		}
+		tdfx_outl(par, LAUNCH_2D, *(u32 *)chardata);
+		chardata += 4;
+	}
+
+	/* Send the leftovers now */
+	banshee_make_room(par, 3);
+	switch (size % 4) {
+	case 0:
+		break;
+	case 1:
+		tdfx_outl(par, LAUNCH_2D, *chardata);
+		break;
+	case 2:
+		tdfx_outl(par, LAUNCH_2D, *(u16 *)chardata);
+		break;
+	case 3:
+		tdfx_outl(par, LAUNCH_2D,
+			*(u16 *)chardata | (chardata[3] << 24));
+		break;
+	}
+}
+#endif /* CONFIG_FB_3DFX_ACCEL */
+
+static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct tdfx_par *par = info->par;
+	u32 vidcfg;
+
+	if (!hwcursor)
+		return -EINVAL;	/* just to force soft_cursor() call */
+
+	/* Too large of a cursor or wrong bpp :-( */
+	if (cursor->image.width > 64 ||
+	    cursor->image.height > 64 ||
+	    cursor->image.depth > 1)
+		return -EINVAL;
+
+	vidcfg = tdfx_inl(par, VIDPROCCFG);
+	if (cursor->enable)
+		tdfx_outl(par, VIDPROCCFG, vidcfg | VIDCFG_HWCURSOR_ENABLE);
+	else
+		tdfx_outl(par, VIDPROCCFG, vidcfg & ~VIDCFG_HWCURSOR_ENABLE);
+
+	/*
+	 * If the cursor is not be changed this means either we want the
+	 * current cursor state (if enable is set) or we want to query what
+	 * we can do with the cursor (if enable is not set)
+	 */
+	if (!cursor->set)
+		return 0;
+
+	/* fix cursor color - XFree86 forgets to restore it properly */
+	if (cursor->set & FB_CUR_SETCMAP) {
+		struct fb_cmap cmap = info->cmap;
+		u32 bg_idx = cursor->image.bg_color;
+		u32 fg_idx = cursor->image.fg_color;
+		unsigned long bg_color, fg_color;
+
+		fg_color = (((u32)cmap.red[fg_idx]   & 0xff00) << 8) |
+			   (((u32)cmap.green[fg_idx] & 0xff00) << 0) |
+			   (((u32)cmap.blue[fg_idx]  & 0xff00) >> 8);
+		bg_color = (((u32)cmap.red[bg_idx]   & 0xff00) << 8) |
+			   (((u32)cmap.green[bg_idx] & 0xff00) << 0) |
+			   (((u32)cmap.blue[bg_idx]  & 0xff00) >> 8);
+		banshee_make_room(par, 2);
+		tdfx_outl(par, HWCURC0, bg_color);
+		tdfx_outl(par, HWCURC1, fg_color);
+	}
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		int x = cursor->image.dx;
+		int y = cursor->image.dy - info->var.yoffset;
+
+		x += 63;
+		y += 63;
+		banshee_make_room(par, 1);
+		tdfx_outl(par, HWCURLOC, (y << 16) + x);
+	}
+	if (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
+		/*
+		 * Voodoo 3 and above cards use 2 monochrome cursor patterns.
+		 *    The reason is so the card can fetch 8 words at a time
+		 * and are stored on chip for use for the next 8 scanlines.
+		 * This reduces the number of times for access to draw the
+		 * cursor for each screen refresh.
+		 *    Each pattern is a bitmap of 64 bit wide and 64 bit high
+		 * (total of 8192 bits or 1024 bytes). The two patterns are
+		 * stored in such a way that pattern 0 always resides in the
+		 * lower half (least significant 64 bits) of a 128 bit word
+		 * and pattern 1 the upper half. If you examine the data of
+		 * the cursor image the graphics card uses then from the
+		 * beginning you see line one of pattern 0, line one of
+		 * pattern 1, line two of pattern 0, line two of pattern 1,
+		 * etc etc. The linear stride for the cursor is always 16 bytes
+		 * (128 bits) which is the maximum cursor width times two for
+		 * the two monochrome patterns.
+		 */
+		u8 __iomem *cursorbase = info->screen_base + info->fix.smem_len;
+		u8 *bitmap = (u8 *)cursor->image.data;
+		u8 *mask = (u8 *)cursor->mask;
+		int i;
+
+		fb_memset(cursorbase, 0, 1024);
+
+		for (i = 0; i < cursor->image.height; i++) {
+			int h = 0;
+			int j = (cursor->image.width + 7) >> 3;
+
+			for (; j > 0; j--) {
+				u8 data = *mask ^ *bitmap;
+				if (cursor->rop == ROP_COPY)
+					data = *mask & *bitmap;
+				/* Pattern 0. Copy the cursor mask to it */
+				fb_writeb(*mask, cursorbase + h);
+				mask++;
+				/* Pattern 1. Copy the cursor bitmap to it */
+				fb_writeb(data, cursorbase + h + 8);
+				bitmap++;
+				h++;
+			}
+			cursorbase += 16;
+		}
+	}
+	return 0;
+}
+
+static struct fb_ops tdfxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= tdfxfb_check_var,
+	.fb_set_par	= tdfxfb_set_par,
+	.fb_setcolreg	= tdfxfb_setcolreg,
+	.fb_blank	= tdfxfb_blank,
+	.fb_pan_display	= tdfxfb_pan_display,
+	.fb_sync	= banshee_wait_idle,
+	.fb_cursor	= tdfxfb_cursor,
+#ifdef CONFIG_FB_3DFX_ACCEL
+	.fb_fillrect	= tdfxfb_fillrect,
+	.fb_copyarea	= tdfxfb_copyarea,
+	.fb_imageblit	= tdfxfb_imageblit,
+#else
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+#endif
+};
+
+#ifdef CONFIG_FB_3DFX_I2C
+/* The voo GPIO registers don't have individual masks for each bit
+   so we always have to read before writing. */
+
+static void tdfxfb_i2c_setscl(void *data, int val)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+	unsigned int r;
+
+	r = tdfx_inl(par, VIDSERPARPORT);
+	if (val)
+		r |= I2C_SCL_OUT;
+	else
+		r &= ~I2C_SCL_OUT;
+	tdfx_outl(par, VIDSERPARPORT, r);
+	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
+}
+
+static void tdfxfb_i2c_setsda(void *data, int val)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+	unsigned int r;
+
+	r = tdfx_inl(par, VIDSERPARPORT);
+	if (val)
+		r |= I2C_SDA_OUT;
+	else
+		r &= ~I2C_SDA_OUT;
+	tdfx_outl(par, VIDSERPARPORT, r);
+	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
+}
+
+/* The GPIO pins are open drain, so the pins always remain outputs.
+   We rely on the i2c-algo-bit routines to set the pins high before
+   reading the input from other chips. */
+
+static int tdfxfb_i2c_getscl(void *data)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+
+	return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SCL_IN));
+}
+
+static int tdfxfb_i2c_getsda(void *data)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+
+	return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SDA_IN));
+}
+
+static void tdfxfb_ddc_setscl(void *data, int val)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+	unsigned int r;
+
+	r = tdfx_inl(par, VIDSERPARPORT);
+	if (val)
+		r |= DDC_SCL_OUT;
+	else
+		r &= ~DDC_SCL_OUT;
+	tdfx_outl(par, VIDSERPARPORT, r);
+	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
+}
+
+static void tdfxfb_ddc_setsda(void *data, int val)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+	unsigned int r;
+
+	r = tdfx_inl(par, VIDSERPARPORT);
+	if (val)
+		r |= DDC_SDA_OUT;
+	else
+		r &= ~DDC_SDA_OUT;
+	tdfx_outl(par, VIDSERPARPORT, r);
+	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
+}
+
+static int tdfxfb_ddc_getscl(void *data)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+
+	return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SCL_IN));
+}
+
+static int tdfxfb_ddc_getsda(void *data)
+{
+	struct tdfxfb_i2c_chan 	*chan = data;
+	struct tdfx_par 	*par = chan->par;
+
+	return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SDA_IN));
+}
+
+static int tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan, const char *name,
+				struct device *dev)
+{
+	int rc;
+
+	strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+	chan->adapter.owner		= THIS_MODULE;
+	chan->adapter.class		= I2C_CLASS_DDC;
+	chan->adapter.algo_data		= &chan->algo;
+	chan->adapter.dev.parent	= dev;
+	chan->algo.setsda		= tdfxfb_ddc_setsda;
+	chan->algo.setscl		= tdfxfb_ddc_setscl;
+	chan->algo.getsda		= tdfxfb_ddc_getsda;
+	chan->algo.getscl		= tdfxfb_ddc_getscl;
+	chan->algo.udelay		= 10;
+	chan->algo.timeout		= msecs_to_jiffies(500);
+	chan->algo.data 		= chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		DPRINTK("I2C bus %s registered.\n", name);
+	else
+		chan->par = NULL;
+
+	return rc;
+}
+
+static int tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan, const char *name,
+				struct device *dev)
+{
+	int rc;
+
+	strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+	chan->adapter.owner		= THIS_MODULE;
+	chan->adapter.algo_data		= &chan->algo;
+	chan->adapter.dev.parent	= dev;
+	chan->algo.setsda		= tdfxfb_i2c_setsda;
+	chan->algo.setscl		= tdfxfb_i2c_setscl;
+	chan->algo.getsda		= tdfxfb_i2c_getsda;
+	chan->algo.getscl		= tdfxfb_i2c_getscl;
+	chan->algo.udelay		= 10;
+	chan->algo.timeout		= msecs_to_jiffies(500);
+	chan->algo.data 		= chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		DPRINTK("I2C bus %s registered.\n", name);
+	else
+		chan->par = NULL;
+
+	return rc;
+}
+
+static void tdfxfb_create_i2c_busses(struct fb_info *info)
+{
+	struct tdfx_par *par = info->par;
+
+	tdfx_outl(par, VIDINFORMAT, 0x8160);
+	tdfx_outl(par, VIDSERPARPORT, 0xcffc0020);
+
+	par->chan[0].par = par;
+	par->chan[1].par = par;
+
+	tdfxfb_setup_ddc_bus(&par->chan[0], "Voodoo3-DDC", info->dev);
+	tdfxfb_setup_i2c_bus(&par->chan[1], "Voodoo3-I2C", info->dev);
+}
+
+static void tdfxfb_delete_i2c_busses(struct tdfx_par *par)
+{
+	if (par->chan[0].par)
+		i2c_del_adapter(&par->chan[0].adapter);
+	par->chan[0].par = NULL;
+
+	if (par->chan[1].par)
+		i2c_del_adapter(&par->chan[1].adapter);
+	par->chan[1].par = NULL;
+}
+
+static int tdfxfb_probe_i2c_connector(struct tdfx_par *par,
+				      struct fb_monspecs *specs)
+{
+	u8 *edid = NULL;
+
+	DPRINTK("Probe DDC Bus\n");
+	if (par->chan[0].par)
+		edid = fb_ddc_read(&par->chan[0].adapter);
+
+	if (edid) {
+		fb_edid_to_monspecs(edid, specs);
+		kfree(edid);
+		return 0;
+	}
+	return 1;
+}
+#endif /* CONFIG_FB_3DFX_I2C */
+
+/**
+ *      tdfxfb_probe - Device Initializiation
+ *
+ *      @pdev:  PCI Device to initialize
+ *      @id:    PCI Device ID
+ *
+ *      Initializes and allocates resources for PCI device @pdev.
+ *
+ */
+static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct tdfx_par *default_par;
+	struct fb_info *info;
+	int err, lpitch;
+	struct fb_monspecs *specs;
+	bool found;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err);
+		return err;
+	}
+
+	info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev);
+
+	if (!info)
+		return -ENOMEM;
+
+	default_par = info->par;
+	info->fix = tdfx_fix;
+
+	/* Configure the default fb_fix_screeninfo first */
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_3DFX_BANSHEE:
+		strcpy(info->fix.id, "3Dfx Banshee");
+		default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
+		break;
+	case PCI_DEVICE_ID_3DFX_VOODOO3:
+		strcpy(info->fix.id, "3Dfx Voodoo3");
+		default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
+		break;
+	case PCI_DEVICE_ID_3DFX_VOODOO5:
+		strcpy(info->fix.id, "3Dfx Voodoo5");
+		default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
+		break;
+	}
+
+	info->fix.mmio_start = pci_resource_start(pdev, 0);
+	info->fix.mmio_len = pci_resource_len(pdev, 0);
+	if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len,
+				"tdfx regbase")) {
+		printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
+		goto out_err;
+	}
+
+	default_par->regbase_virt =
+		ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+	if (!default_par->regbase_virt) {
+		printk(KERN_ERR "fb: Can't remap %s register area.\n",
+				info->fix.id);
+		goto out_err_regbase;
+	}
+
+	info->fix.smem_start = pci_resource_start(pdev, 1);
+	info->fix.smem_len = do_lfb_size(default_par, pdev->device);
+	if (!info->fix.smem_len) {
+		printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id);
+		goto out_err_regbase;
+	}
+
+	if (!request_mem_region(info->fix.smem_start,
+				pci_resource_len(pdev, 1), "tdfx smem")) {
+		printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
+		goto out_err_regbase;
+	}
+
+	info->screen_base = ioremap_nocache(info->fix.smem_start,
+					    info->fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
+				info->fix.id);
+		goto out_err_screenbase;
+	}
+
+	default_par->iobase = pci_resource_start(pdev, 2);
+
+	if (!request_region(pci_resource_start(pdev, 2),
+			    pci_resource_len(pdev, 2), "tdfx iobase")) {
+		printk(KERN_ERR "tdfxfb: Can't reserve iobase\n");
+		goto out_err_screenbase;
+	}
+
+	printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id,
+			info->fix.smem_len >> 10);
+
+	default_par->mtrr_handle = -1;
+	if (!nomtrr)
+		default_par->mtrr_handle =
+			mtrr_add(info->fix.smem_start, info->fix.smem_len,
+				 MTRR_TYPE_WRCOMB, 1);
+
+	info->fix.ypanstep	= nopan ? 0 : 1;
+	info->fix.ywrapstep	= nowrap ? 0 : 1;
+
+	info->fbops		= &tdfxfb_ops;
+	info->pseudo_palette	= default_par->palette;
+	info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+#ifdef CONFIG_FB_3DFX_ACCEL
+	info->flags		|= FBINFO_HWACCEL_FILLRECT |
+				   FBINFO_HWACCEL_COPYAREA |
+				   FBINFO_HWACCEL_IMAGEBLIT |
+				   FBINFO_READS_FAST;
+#endif
+	/* reserve 8192 bits for cursor */
+	/* the 2.4 driver says PAGE_MASK boundary is not enough for Voodoo4 */
+	if (hwcursor)
+		info->fix.smem_len = (info->fix.smem_len - 1024) &
+					(PAGE_MASK << 1);
+	specs = &info->monspecs;
+	found = false;
+	info->var.bits_per_pixel = 8;
+#ifdef CONFIG_FB_3DFX_I2C
+	tdfxfb_create_i2c_busses(info);
+	err = tdfxfb_probe_i2c_connector(default_par, specs);
+
+	if (!err) {
+		if (specs->modedb == NULL)
+			DPRINTK("Unable to get Mode Database\n");
+		else {
+			const struct fb_videomode *m;
+
+			fb_videomode_to_modelist(specs->modedb,
+						 specs->modedb_len,
+						 &info->modelist);
+			m = fb_find_best_display(specs, &info->modelist);
+			if (m) {
+				fb_videomode_to_var(&info->var, m);
+				/* fill all other info->var's fields */
+				if (tdfxfb_check_var(&info->var, info) < 0)
+					info->var = tdfx_var;
+				else
+					found = true;
+			}
+		}
+	}
+#endif
+	if (!mode_option && !found)
+		mode_option = "640x480@60";
+
+	if (mode_option) {
+		err = fb_find_mode(&info->var, info, mode_option,
+				   specs->modedb, specs->modedb_len,
+				   NULL, info->var.bits_per_pixel);
+		if (!err || err == 4)
+			info->var = tdfx_var;
+	}
+
+	if (found) {
+		fb_destroy_modedb(specs->modedb);
+		specs->modedb = NULL;
+	}
+
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len / lpitch;
+	if (info->var.yres_virtual < info->var.yres)
+		goto out_err_iobase;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		printk(KERN_ERR "tdfxfb: Can't allocate color map\n");
+		goto out_err_iobase;
+	}
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "tdfxfb: can't register framebuffer\n");
+		fb_dealloc_cmap(&info->cmap);
+		goto out_err_iobase;
+	}
+	/*
+	 * Our driver data
+	 */
+	pci_set_drvdata(pdev, info);
+	return 0;
+
+out_err_iobase:
+#ifdef CONFIG_FB_3DFX_I2C
+	tdfxfb_delete_i2c_busses(default_par);
+#endif
+	if (default_par->mtrr_handle >= 0)
+		mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
+			 info->fix.smem_len);
+	release_region(pci_resource_start(pdev, 2),
+		       pci_resource_len(pdev, 2));
+out_err_screenbase:
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1));
+out_err_regbase:
+	/*
+	 * Cleanup after anything that was remapped/allocated.
+	 */
+	if (default_par->regbase_virt)
+		iounmap(default_par->regbase_virt);
+	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+out_err:
+	framebuffer_release(info);
+	return -ENXIO;
+}
+
+#ifndef MODULE
+static void __init tdfxfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strcmp(this_opt, "nopan")) {
+			nopan = 1;
+		} else if (!strcmp(this_opt, "nowrap")) {
+			nowrap = 1;
+		} else if (!strncmp(this_opt, "hwcursor=", 9)) {
+			hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else {
+			mode_option = this_opt;
+		}
+	}
+}
+#endif
+
+/**
+ *      tdfxfb_remove - Device removal
+ *
+ *      @pdev:  PCI Device to cleanup
+ *
+ *      Releases all resources allocated during the course of the driver's
+ *      lifetime for the PCI device @pdev.
+ *
+ */
+static void tdfxfb_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct tdfx_par *par = info->par;
+
+	unregister_framebuffer(info);
+#ifdef CONFIG_FB_3DFX_I2C
+	tdfxfb_delete_i2c_busses(par);
+#endif
+	if (par->mtrr_handle >= 0)
+		mtrr_del(par->mtrr_handle, info->fix.smem_start,
+			 info->fix.smem_len);
+	iounmap(par->regbase_virt);
+	iounmap(info->screen_base);
+
+	/* Clean up after reserved regions */
+	release_region(pci_resource_start(pdev, 2),
+		       pci_resource_len(pdev, 2));
+	release_mem_region(pci_resource_start(pdev, 1),
+			   pci_resource_len(pdev, 1));
+	release_mem_region(pci_resource_start(pdev, 0),
+			   pci_resource_len(pdev, 0));
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(info);
+}
+
+static int __init tdfxfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tdfxfb", &option))
+		return -ENODEV;
+
+	tdfxfb_setup(option);
+#endif
+	return pci_register_driver(&tdfxfb_driver);
+}
+
+static void __exit tdfxfb_exit(void)
+{
+	pci_unregister_driver(&tdfxfb_driver);
+}
+
+MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
+MODULE_DESCRIPTION("3Dfx framebuffer device driver");
+MODULE_LICENSE("GPL");
+
+module_param(hwcursor, int, 0644);
+MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
+			"(1=enable, 0=disable, default=1)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
+#endif
+
+module_init(tdfxfb_init);
+module_exit(tdfxfb_exit);
diff --git a/drivers/video/fbdev/tgafb.c b/drivers/video/fbdev/tgafb.c
new file mode 100644
index 000000000000..65ba9921506e
--- /dev/null
+++ b/drivers/video/fbdev/tgafb.c
@@ -0,0 +1,1611 @@
+/*
+ *  linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
+ *
+ *	Copyright (C) 1995 Jay Estabrook
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *	Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
+ *	Copyright (C) 2002 Richard Henderson
+ *	Copyright (C) 2006, 2007  Maciej W. Rozycki
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/bitrev.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/selection.h>
+#include <linux/string.h>
+#include <linux/tc.h>
+
+#include <asm/io.h>
+
+#include <video/tgafb.h>
+
+#ifdef CONFIG_TC
+#define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type)
+#else
+#define TGA_BUS_TC(dev) 0
+#endif
+
+/*
+ * Local functions.
+ */
+
+static int tgafb_check_var(struct fb_var_screeninfo *, struct fb_info *);
+static int tgafb_set_par(struct fb_info *);
+static void tgafb_set_pll(struct tga_par *, int);
+static int tgafb_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			   unsigned, struct fb_info *);
+static int tgafb_blank(int, struct fb_info *);
+static void tgafb_init_fix(struct fb_info *);
+
+static void tgafb_imageblit(struct fb_info *, const struct fb_image *);
+static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
+static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
+static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+
+static int tgafb_register(struct device *dev);
+static void tgafb_unregister(struct device *dev);
+
+static const char *mode_option;
+static const char *mode_option_pci = "640x480@60";
+static const char *mode_option_tc = "1280x1024@72";
+
+
+static struct pci_driver tgafb_pci_driver;
+static struct tc_driver tgafb_tc_driver;
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops tgafb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_check_var		= tgafb_check_var,
+	.fb_set_par		= tgafb_set_par,
+	.fb_setcolreg		= tgafb_setcolreg,
+	.fb_blank		= tgafb_blank,
+	.fb_pan_display		= tgafb_pan_display,
+	.fb_fillrect		= tgafb_fillrect,
+	.fb_copyarea		= tgafb_copyarea,
+	.fb_imageblit		= tgafb_imageblit,
+};
+
+
+#ifdef CONFIG_PCI
+/*
+ *  PCI registration operations
+ */
+static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
+static void tgafb_pci_unregister(struct pci_dev *);
+
+static struct pci_device_id const tgafb_pci_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, tgafb_pci_table);
+
+static struct pci_driver tgafb_pci_driver = {
+	.name			= "tgafb",
+	.id_table		= tgafb_pci_table,
+	.probe			= tgafb_pci_register,
+	.remove			= tgafb_pci_unregister,
+};
+
+static int tgafb_pci_register(struct pci_dev *pdev,
+			      const struct pci_device_id *ent)
+{
+	return tgafb_register(&pdev->dev);
+}
+
+static void tgafb_pci_unregister(struct pci_dev *pdev)
+{
+	tgafb_unregister(&pdev->dev);
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_TC
+/*
+ *  TC registration operations
+ */
+static int tgafb_tc_register(struct device *);
+static int tgafb_tc_unregister(struct device *);
+
+static struct tc_device_id const tgafb_tc_table[] = {
+	{ "DEC     ", "PMAGD-AA" },
+	{ "DEC     ", "PMAGD   " },
+	{ }
+};
+MODULE_DEVICE_TABLE(tc, tgafb_tc_table);
+
+static struct tc_driver tgafb_tc_driver = {
+	.id_table		= tgafb_tc_table,
+	.driver			= {
+		.name		= "tgafb",
+		.bus		= &tc_bus_type,
+		.probe		= tgafb_tc_register,
+		.remove		= tgafb_tc_unregister,
+	},
+};
+
+static int tgafb_tc_register(struct device *dev)
+{
+	int status = tgafb_register(dev);
+	if (!status)
+		get_device(dev);
+	return status;
+}
+
+static int tgafb_tc_unregister(struct device *dev)
+{
+	put_device(dev);
+	tgafb_unregister(dev);
+	return 0;
+}
+#endif /* CONFIG_TC */
+
+
+/**
+ *      tgafb_check_var - Optional function.  Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct tga_par *par = (struct tga_par *)info->par;
+
+	if (par->tga_type == TGA_TYPE_8PLANE) {
+		if (var->bits_per_pixel != 8)
+			return -EINVAL;
+	} else {
+		if (var->bits_per_pixel != 32)
+			return -EINVAL;
+	}
+	var->red.length = var->green.length = var->blue.length = 8;
+	if (var->bits_per_pixel == 32) {
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+	}
+
+	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
+		return -EINVAL;
+	if (var->xres * var->yres * (var->bits_per_pixel >> 3) > info->fix.smem_len)
+		return -EINVAL;
+	if (var->nonstd)
+		return -EINVAL;
+	if (1000000000 / var->pixclock > TGA_PLL_MAX_FREQ)
+		return -EINVAL;
+	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	/* Some of the acceleration routines assume the line width is
+	   a multiple of 8 bytes.  */
+	if (var->xres * (par->tga_type == TGA_TYPE_8PLANE ? 1 : 4) % 8)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ *      tgafb_set_par - Optional function.  Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tgafb_set_par(struct fb_info *info)
+{
+	static unsigned int const deep_presets[4] = {
+		0x00004000,
+		0x0000440d,
+		0xffffffff,
+		0x0000441d
+	};
+	static unsigned int const rasterop_presets[4] = {
+		0x00000003,
+		0x00000303,
+		0xffffffff,
+		0x00000303
+	};
+	static unsigned int const mode_presets[4] = {
+		0x00000000,
+		0x00000300,
+		0xffffffff,
+		0x00000300
+	};
+	static unsigned int const base_addr_presets[4] = {
+		0x00000000,
+		0x00000001,
+		0xffffffff,
+		0x00000001
+	};
+
+	struct tga_par *par = (struct tga_par *) info->par;
+	int tga_bus_pci = dev_is_pci(par->dev);
+	int tga_bus_tc = TGA_BUS_TC(par->dev);
+	u32 htimings, vtimings, pll_freq;
+	u8 tga_type;
+	int i;
+
+	/* Encode video timings.  */
+	htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
+		    | (((info->var.xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB));
+	vtimings = (info->var.yres & TGA_VERT_ACTIVE);
+	htimings |= ((info->var.right_margin/4) << 9) & TGA_HORIZ_FP;
+	vtimings |= (info->var.lower_margin << 11) & TGA_VERT_FP;
+	htimings |= ((info->var.hsync_len/4) << 14) & TGA_HORIZ_SYNC;
+	vtimings |= (info->var.vsync_len << 16) & TGA_VERT_SYNC;
+	htimings |= ((info->var.left_margin/4) << 21) & TGA_HORIZ_BP;
+	vtimings |= (info->var.upper_margin << 22) & TGA_VERT_BP;
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		htimings |= TGA_HORIZ_POLARITY;
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		vtimings |= TGA_VERT_POLARITY;
+
+	par->htimings = htimings;
+	par->vtimings = vtimings;
+
+	par->sync_on_green = !!(info->var.sync & FB_SYNC_ON_GREEN);
+
+	/* Store other useful values in par.  */
+	par->xres = info->var.xres;
+	par->yres = info->var.yres;
+	par->pll_freq = pll_freq = 1000000000 / info->var.pixclock;
+	par->bits_per_pixel = info->var.bits_per_pixel;
+	info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
+
+	tga_type = par->tga_type;
+
+	/* First, disable video.  */
+	TGA_WRITE_REG(par, TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
+
+	/* Write the DEEP register.  */
+	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
+		continue;
+	mb();
+	TGA_WRITE_REG(par, deep_presets[tga_type] |
+			   (par->sync_on_green ? 0x0 : 0x00010000),
+		      TGA_DEEP_REG);
+	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
+		continue;
+	mb();
+
+	/* Write some more registers.  */
+	TGA_WRITE_REG(par, rasterop_presets[tga_type], TGA_RASTEROP_REG);
+	TGA_WRITE_REG(par, mode_presets[tga_type], TGA_MODE_REG);
+	TGA_WRITE_REG(par, base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
+
+	/* Calculate & write the PLL.  */
+	tgafb_set_pll(par, pll_freq);
+
+	/* Write some more registers.  */
+	TGA_WRITE_REG(par, 0xffffffff, TGA_PLANEMASK_REG);
+	TGA_WRITE_REG(par, 0xffffffff, TGA_PIXELMASK_REG);
+
+	/* Init video timing regs.  */
+	TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
+	TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
+
+	/* Initialise RAMDAC. */
+	if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
+
+		/* Init BT485 RAMDAC registers.  */
+		BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0),
+			    BT485_CMD_0);
+		BT485_WRITE(par, 0x01, BT485_ADDR_PAL_WRITE);
+		BT485_WRITE(par, 0x14, BT485_CMD_3); /* cursor 64x64 */
+		BT485_WRITE(par, 0x40, BT485_CMD_1);
+		BT485_WRITE(par, 0x20, BT485_CMD_2); /* cursor off, for now */
+		BT485_WRITE(par, 0xff, BT485_PIXEL_MASK);
+
+		/* Fill palette registers.  */
+		BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
+		TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+
+		for (i = 0; i < 256 * 3; i += 4) {
+			TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
+				      TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
+				      TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
+				      TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
+				      TGA_RAMDAC_REG);
+		}
+
+	} else if (tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
+
+		/* Init BT459 RAMDAC registers.  */
+		BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_0, 0x40);
+		BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_1, 0x00);
+		BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_2,
+			    (par->sync_on_green ? 0xc0 : 0x40));
+
+		BT459_WRITE(par, BT459_REG_ACC, BT459_CUR_CMD_REG, 0x00);
+
+		/* Fill the palette.  */
+		BT459_LOAD_ADDR(par, 0x0000);
+		TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+
+		for (i = 0; i < 256 * 3; i += 4) {
+			TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+		}
+
+	} else { /* 24-plane or 24plusZ */
+
+		/* Init BT463 RAMDAC registers.  */
+		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
+			    (par->sync_on_green ? 0xc0 : 0x40));
+
+		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
+
+		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
+		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
+
+		/* Fill the palette.  */
+		BT463_LOAD_ADDR(par, 0x0000);
+		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+
+#ifdef CONFIG_HW_CONSOLE
+		for (i = 0; i < 16; i++) {
+			int j = color_table[i];
+
+			TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
+		}
+		for (i = 0; i < 512 * 3; i += 4) {
+#else
+		for (i = 0; i < 528 * 3; i += 4) {
+#endif
+			TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+		}
+
+		/* Fill window type table after start of vertical retrace.  */
+		while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
+			continue;
+		TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
+		mb();
+		while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
+			continue;
+		TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
+
+		BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
+		TGA_WRITE_REG(par, BT463_REG_ACC << 2, TGA_RAMDAC_SETUP_REG);
+
+		for (i = 0; i < 16; i++) {
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x01, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+		}
+
+	}
+
+	/* Finally, enable video scan (and pray for the monitor... :-) */
+	TGA_WRITE_REG(par, TGA_VALID_VIDEO, TGA_VALID_REG);
+
+	return 0;
+}
+
+#define DIFFCHECK(X)							  \
+do {									  \
+	if (m <= 0x3f) {						  \
+		int delta = f - (TGA_PLL_BASE_FREQ * (X)) / (r << shift); \
+		if (delta < 0)						  \
+			delta = -delta;					  \
+		if (delta < min_diff)					  \
+			min_diff = delta, vm = m, va = a, vr = r;	  \
+	}								  \
+} while (0)
+
+static void
+tgafb_set_pll(struct tga_par *par, int f)
+{
+	int n, shift, base, min_diff, target;
+	int r,a,m,vm = 34, va = 1, vr = 30;
+
+	for (r = 0 ; r < 12 ; r++)
+		TGA_WRITE_REG(par, !r, TGA_CLOCK_REG);
+
+	if (f > TGA_PLL_MAX_FREQ)
+		f = TGA_PLL_MAX_FREQ;
+
+	if (f >= TGA_PLL_MAX_FREQ / 2)
+		shift = 0;
+	else if (f >= TGA_PLL_MAX_FREQ / 4)
+		shift = 1;
+	else
+		shift = 2;
+
+	TGA_WRITE_REG(par, shift & 1, TGA_CLOCK_REG);
+	TGA_WRITE_REG(par, shift >> 1, TGA_CLOCK_REG);
+
+	for (r = 0 ; r < 10 ; r++)
+		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+
+	if (f <= 120000) {
+		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+	}
+	else if (f <= 200000) {
+		TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+	}
+	else {
+		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+		TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+	}
+
+	TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+	TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+	TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+	TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+	TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+	TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+
+	target = (f << shift) / TGA_PLL_BASE_FREQ;
+	min_diff = TGA_PLL_MAX_FREQ;
+
+	r = 7 / target;
+	if (!r) r = 1;
+
+	base = target * r;
+	while (base < 449) {
+		for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) {
+			m = ((n + 3) / 7) - 1;
+			a = 0;
+			DIFFCHECK((m + 1) * 7);
+			m++;
+			DIFFCHECK((m + 1) * 7);
+			m = (n / 6) - 1;
+			if ((a = n % 6))
+				DIFFCHECK(n);
+		}
+		r++;
+		base += target;
+	}
+
+	vr--;
+
+	for (r = 0; r < 8; r++)
+		TGA_WRITE_REG(par, (vm >> r) & 1, TGA_CLOCK_REG);
+	for (r = 0; r < 8 ; r++)
+		TGA_WRITE_REG(par, (va >> r) & 1, TGA_CLOCK_REG);
+	for (r = 0; r < 7 ; r++)
+		TGA_WRITE_REG(par, (vr >> r) & 1, TGA_CLOCK_REG);
+	TGA_WRITE_REG(par, ((vr >> 7) & 1)|2, TGA_CLOCK_REG);
+}
+
+
+/**
+ *      tgafb_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int
+tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+		unsigned transp, struct fb_info *info)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	int tga_bus_pci = dev_is_pci(par->dev);
+	int tga_bus_tc = TGA_BUS_TC(par->dev);
+
+	if (regno > 255)
+		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
+		BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE);
+		TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+		TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+	} else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
+		BT459_LOAD_ADDR(par, regno);
+		TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+		TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
+	} else {
+		if (regno < 16) {
+			u32 value = (regno << 16) | (regno << 8) | regno;
+			((u32 *)info->pseudo_palette)[regno] = value;
+		}
+		BT463_LOAD_ADDR(par, regno);
+		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+		TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
+	}
+
+	return 0;
+}
+
+
+/**
+ *      tgafb_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tgafb_blank(int blank, struct fb_info *info)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	u32 vhcr, vvcr, vvvr;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	vhcr = TGA_READ_REG(par, TGA_HORIZ_REG);
+	vvcr = TGA_READ_REG(par, TGA_VERT_REG);
+	vvvr = TGA_READ_REG(par, TGA_VALID_REG);
+	vvvr &= ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK: /* Unblanking */
+		if (par->vesa_blanked) {
+			TGA_WRITE_REG(par, vhcr & 0xbfffffff, TGA_HORIZ_REG);
+			TGA_WRITE_REG(par, vvcr & 0xbfffffff, TGA_VERT_REG);
+			par->vesa_blanked = 0;
+		}
+		TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
+		break;
+
+	case FB_BLANK_NORMAL: /* Normal blanking */
+		TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK,
+			      TGA_VALID_REG);
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
+		TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
+		TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
+		par->vesa_blanked = 1;
+		break;
+
+	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
+		TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
+		TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
+		par->vesa_blanked = 1;
+		break;
+
+	case FB_BLANK_POWERDOWN: /* Poweroff */
+		TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
+		TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
+		TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
+		par->vesa_blanked = 1;
+		break;
+	}
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+
+/*
+ *  Acceleration.
+ */
+
+static void
+tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
+	unsigned long rincr, line_length, shift, pos, is8bpp;
+	unsigned long i, j;
+	const unsigned char *data;
+	void __iomem *regs_base;
+	void __iomem *fb_base;
+
+	is8bpp = info->var.bits_per_pixel == 8;
+
+	dx = image->dx;
+	dy = image->dy;
+	width = image->width;
+	height = image->height;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+	line_length = info->fix.line_length;
+	rincr = (width + 7) / 8;
+
+	/* A shift below cannot cope with.  */
+	if (unlikely(width == 0))
+		return;
+	/* Crop the image to the screen.  */
+	if (dx > vxres || dy > vyres)
+		return;
+	if (dx + width > vxres)
+		width = vxres - dx;
+	if (dy + height > vyres)
+		height = vyres - dy;
+
+	regs_base = par->tga_regs_base;
+	fb_base = par->tga_fb_base;
+
+	/* Expand the color values to fill 32-bits.  */
+	/* ??? Would be nice to notice colour changes elsewhere, so
+	   that we can do this only when necessary.  */
+	fgcolor = image->fg_color;
+	bgcolor = image->bg_color;
+	if (is8bpp) {
+		fgcolor |= fgcolor << 8;
+		fgcolor |= fgcolor << 16;
+		bgcolor |= bgcolor << 8;
+		bgcolor |= bgcolor << 16;
+	} else {
+		if (fgcolor < 16)
+			fgcolor = ((u32 *)info->pseudo_palette)[fgcolor];
+		if (bgcolor < 16)
+			bgcolor = ((u32 *)info->pseudo_palette)[bgcolor];
+	}
+	__raw_writel(fgcolor, regs_base + TGA_FOREGROUND_REG);
+	__raw_writel(bgcolor, regs_base + TGA_BACKGROUND_REG);
+
+	/* Acquire proper alignment; set up the PIXELMASK register
+	   so that we only write the proper character cell.  */
+	pos = dy * line_length;
+	if (is8bpp) {
+		pos += dx;
+		shift = pos & 3;
+		pos &= -4;
+	} else {
+		pos += dx * 4;
+		shift = (pos & 7) >> 2;
+		pos &= -8;
+	}
+
+	data = (const unsigned char *) image->data;
+
+	/* Enable opaque stipple mode.  */
+	__raw_writel((is8bpp
+		      ? TGA_MODE_SBM_8BPP | TGA_MODE_OPAQUE_STIPPLE
+		      : TGA_MODE_SBM_24BPP | TGA_MODE_OPAQUE_STIPPLE),
+		     regs_base + TGA_MODE_REG);
+
+	if (width + shift <= 32) {
+		unsigned long bwidth;
+
+		/* Handle common case of imaging a single character, in
+		   a font less than or 32 pixels wide.  */
+
+		/* Avoid a shift by 32; width > 0 implied.  */
+		pixelmask = (2ul << (width - 1)) - 1;
+		pixelmask <<= shift;
+		__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
+		wmb();
+
+		bwidth = (width + 7) / 8;
+
+		for (i = 0; i < height; ++i) {
+			u32 mask = 0;
+
+			/* The image data is bit big endian; we need
+			   little endian.  */
+			for (j = 0; j < bwidth; ++j)
+				mask |= bitrev8(data[j]) << (j * 8);
+
+			__raw_writel(mask << shift, fb_base + pos);
+
+			pos += line_length;
+			data += rincr;
+		}
+		wmb();
+		__raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
+	} else if (shift == 0) {
+		unsigned long pos0 = pos;
+		const unsigned char *data0 = data;
+		unsigned long bincr = (is8bpp ? 8 : 8*4);
+		unsigned long bwidth;
+
+		/* Handle another common case in which accel_putcs
+		   generates a large bitmap, which happens to be aligned.
+		   Allow the tail to be misaligned.  This case is 
+		   interesting because we've not got to hold partial
+		   bytes across the words being written.  */
+
+		wmb();
+
+		bwidth = (width / 8) & -4;
+		for (i = 0; i < height; ++i) {
+			for (j = 0; j < bwidth; j += 4) {
+				u32 mask = 0;
+				mask |= bitrev8(data[j+0]) << (0 * 8);
+				mask |= bitrev8(data[j+1]) << (1 * 8);
+				mask |= bitrev8(data[j+2]) << (2 * 8);
+				mask |= bitrev8(data[j+3]) << (3 * 8);
+				__raw_writel(mask, fb_base + pos + j*bincr);
+			}
+			pos += line_length;
+			data += rincr;
+		}
+		wmb();
+
+		pixelmask = (1ul << (width & 31)) - 1;
+		if (pixelmask) {
+			__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
+			wmb();
+
+			pos = pos0 + bwidth*bincr;
+			data = data0 + bwidth;
+			bwidth = ((width & 31) + 7) / 8;
+
+			for (i = 0; i < height; ++i) {
+				u32 mask = 0;
+				for (j = 0; j < bwidth; ++j)
+					mask |= bitrev8(data[j]) << (j * 8);
+				__raw_writel(mask, fb_base + pos);
+				pos += line_length;
+				data += rincr;
+			}
+			wmb();
+			__raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
+		}
+	} else {
+		unsigned long pos0 = pos;
+		const unsigned char *data0 = data;
+		unsigned long bincr = (is8bpp ? 8 : 8*4);
+		unsigned long bwidth;
+
+		/* Finally, handle the generic case of misaligned start.
+		   Here we split the write into 16-bit spans.  This allows
+		   us to use only one pixel mask, instead of four as would
+		   be required by writing 24-bit spans.  */
+
+		pixelmask = 0xffff << shift;
+		__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
+		wmb();
+
+		bwidth = (width / 8) & -2;
+		for (i = 0; i < height; ++i) {
+			for (j = 0; j < bwidth; j += 2) {
+				u32 mask = 0;
+				mask |= bitrev8(data[j+0]) << (0 * 8);
+				mask |= bitrev8(data[j+1]) << (1 * 8);
+				mask <<= shift;
+				__raw_writel(mask, fb_base + pos + j*bincr);
+			}
+			pos += line_length;
+			data += rincr;
+		}
+		wmb();
+
+		pixelmask = ((1ul << (width & 15)) - 1) << shift;
+		if (pixelmask) {
+			__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
+			wmb();
+
+			pos = pos0 + bwidth*bincr;
+			data = data0 + bwidth;
+			bwidth = (width & 15) > 8;
+
+			for (i = 0; i < height; ++i) {
+				u32 mask = bitrev8(data[0]);
+				if (bwidth)
+					mask |= bitrev8(data[1]) << 8;
+				mask <<= shift;
+				__raw_writel(mask, fb_base + pos);
+				pos += line_length;
+				data += rincr;
+			}
+			wmb();
+		}
+		__raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
+	}
+
+	/* Disable opaque stipple mode.  */
+	__raw_writel((is8bpp
+		      ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
+		      : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
+		     regs_base + TGA_MODE_REG);
+}
+
+static void
+tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	u32 color, dx, dy, width, height, vxres, vyres;
+	u32 *palette = ((u32 *)info->pseudo_palette);
+	unsigned long pos, line_length, i, j;
+	const unsigned char *data;
+	void __iomem *regs_base, *fb_base;
+
+	dx = image->dx;
+	dy = image->dy;
+	width = image->width;
+	height = image->height;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+	line_length = info->fix.line_length;
+
+	/* Crop the image to the screen.  */
+	if (dx > vxres || dy > vyres)
+		return;
+	if (dx + width > vxres)
+		width = vxres - dx;
+	if (dy + height > vyres)
+		height = vyres - dy;
+
+	regs_base = par->tga_regs_base;
+	fb_base = par->tga_fb_base;
+
+	pos = dy * line_length + (dx * 4);
+	data = image->data;
+
+	/* Now copy the image, color_expanding via the palette. */
+	for (i = 0; i < height; i++) {
+		for (j = 0; j < width; j++) {
+			color = palette[*data++];
+			__raw_writel(color, fb_base + pos + j*4);
+		}
+		pos += line_length;
+	}
+}
+
+/**
+ *      tgafb_imageblit - REQUIRED function. Can use generic routines if
+ *                        non acclerated hardware and packed pixel based.
+ *                        Copies a image from system memory to the screen.
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @image: structure defining the image.
+ */
+static void
+tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	unsigned int is8bpp = info->var.bits_per_pixel == 8;
+
+	/* If a mono image, regardless of FB depth, go do it. */
+	if (image->depth == 1) {
+		tgafb_mono_imageblit(info, image);
+		return;
+	}
+
+	/* For copies that aren't pixel expansion, there's little we
+	   can do better than the generic code.  */
+	/* ??? There is a DMA write mode; I wonder if that could be
+	   made to pull the data from the image buffer...  */
+	if (image->depth == info->var.bits_per_pixel) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	/* If 24-plane FB and the image is 8-plane with CLUT, we can do it. */
+	if (!is8bpp && image->depth == 8) {
+		tgafb_clut_imageblit(info, image);
+		return;
+	}
+
+	/* Silently return... */
+}
+
+/**
+ *      tgafb_fillrect - REQUIRED function. Can use generic routines if 
+ *                       non acclerated hardware and packed pixel based.
+ *                       Draws a rectangle on the screen.               
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @rect: structure defining the rectagle and operation.
+ */
+static void
+tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	int is8bpp = info->var.bits_per_pixel == 8;
+	u32 dx, dy, width, height, vxres, vyres, color;
+	unsigned long pos, align, line_length, i, j;
+	void __iomem *regs_base;
+	void __iomem *fb_base;
+
+	dx = rect->dx;
+	dy = rect->dy;
+	width = rect->width;
+	height = rect->height;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+	line_length = info->fix.line_length;
+	regs_base = par->tga_regs_base;
+	fb_base = par->tga_fb_base;
+
+	/* Crop the rectangle to the screen.  */
+	if (dx > vxres || dy > vyres || !width || !height)
+		return;
+	if (dx + width > vxres)
+		width = vxres - dx;
+	if (dy + height > vyres)
+		height = vyres - dy;
+
+	pos = dy * line_length + dx * (is8bpp ? 1 : 4);
+
+	/* ??? We could implement ROP_XOR with opaque fill mode
+	   and a RasterOp setting of GXxor, but as far as I can
+	   tell, this mode is not actually used in the kernel.
+	   Thus I am ignoring it for now.  */
+	if (rect->rop != ROP_COPY) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	/* Expand the color value to fill 8 pixels.  */
+	color = rect->color;
+	if (is8bpp) {
+		color |= color << 8;
+		color |= color << 16;
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
+	} else {
+		if (color < 16)
+			color = ((u32 *)info->pseudo_palette)[color];
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR2_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR3_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR4_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR5_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR6_REG);
+		__raw_writel(color, regs_base + TGA_BLOCK_COLOR7_REG);
+	}
+
+	/* The DATA register holds the fill mask for block fill mode.
+	   Since we're not stippling, this is all ones.  */
+	__raw_writel(0xffffffff, regs_base + TGA_DATA_REG);
+
+	/* Enable block fill mode.  */
+	__raw_writel((is8bpp
+		      ? TGA_MODE_SBM_8BPP | TGA_MODE_BLOCK_FILL
+		      : TGA_MODE_SBM_24BPP | TGA_MODE_BLOCK_FILL),
+		     regs_base + TGA_MODE_REG);
+	wmb();
+
+	/* We can fill 2k pixels per operation.  Notice blocks that fit
+	   the width of the screen so that we can take advantage of this
+	   and fill more than one line per write.  */
+	if (width == line_length)
+		width *= height, height = 1;
+
+	/* The write into the frame buffer must be aligned to 4 bytes,
+	   but we are allowed to encode the offset within the word in
+	   the data word written.  */
+	align = (pos & 3) << 16;
+	pos &= -4;
+
+	if (width <= 2048) {
+		u32 data;
+
+		data = (width - 1) | align;
+
+		for (i = 0; i < height; ++i) {
+			__raw_writel(data, fb_base + pos);
+			pos += line_length;
+		}
+	} else {
+		unsigned long Bpp = (is8bpp ? 1 : 4);
+		unsigned long nwidth = width & -2048;
+		u32 fdata, ldata;
+
+		fdata = (2048 - 1) | align;
+		ldata = ((width & 2047) - 1) | align;
+
+		for (i = 0; i < height; ++i) {
+			for (j = 0; j < nwidth; j += 2048)
+				__raw_writel(fdata, fb_base + pos + j*Bpp);
+			if (j < width)
+				__raw_writel(ldata, fb_base + pos + j*Bpp);
+			pos += line_length;
+		}
+	}
+	wmb();
+
+	/* Disable block fill mode.  */
+	__raw_writel((is8bpp
+		      ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
+		      : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
+		     regs_base + TGA_MODE_REG);
+}
+
+/**
+ *      tgafb_copyarea - REQUIRED function. Can use generic routines if
+ *                       non acclerated hardware and packed pixel based.
+ *                       Copies on area of the screen to another area.
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @area: structure defining the source and destination.
+ */
+
+/* Handle the special case of copying entire lines, e.g. during scrolling.
+   We can avoid a lot of needless computation in this case.  In the 8bpp
+   case we need to use the COPY64 registers instead of mask writes into 
+   the frame buffer to achieve maximum performance.  */
+
+static inline void
+copyarea_line_8bpp(struct fb_info *info, u32 dy, u32 sy,
+		   u32 height, u32 width)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	void __iomem *tga_regs = par->tga_regs_base;
+	unsigned long dpos, spos, i, n64;
+
+	/* Set up the MODE and PIXELSHIFT registers.  */
+	__raw_writel(TGA_MODE_SBM_8BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
+	__raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
+	wmb();
+
+	n64 = (height * width) / 64;
+
+	if (sy < dy) {
+		spos = (sy + height) * width;
+		dpos = (dy + height) * width;
+
+		for (i = 0; i < n64; ++i) {
+			spos -= 64;
+			dpos -= 64;
+			__raw_writel(spos, tga_regs+TGA_COPY64_SRC);
+			wmb();
+			__raw_writel(dpos, tga_regs+TGA_COPY64_DST);
+			wmb();
+		}
+	} else {
+		spos = sy * width;
+		dpos = dy * width;
+
+		for (i = 0; i < n64; ++i) {
+			__raw_writel(spos, tga_regs+TGA_COPY64_SRC);
+			wmb();
+			__raw_writel(dpos, tga_regs+TGA_COPY64_DST);
+			wmb();
+			spos += 64;
+			dpos += 64;
+		}
+	}
+
+	/* Reset the MODE register to normal.  */
+	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
+}
+
+static inline void
+copyarea_line_32bpp(struct fb_info *info, u32 dy, u32 sy,
+		    u32 height, u32 width)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	void __iomem *tga_regs = par->tga_regs_base;
+	void __iomem *tga_fb = par->tga_fb_base;
+	void __iomem *src;
+	void __iomem *dst;
+	unsigned long i, n16;
+
+	/* Set up the MODE and PIXELSHIFT registers.  */
+	__raw_writel(TGA_MODE_SBM_24BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
+	__raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
+	wmb();
+
+	n16 = (height * width) / 16;
+
+	if (sy < dy) {
+		src = tga_fb + (sy + height) * width * 4;
+		dst = tga_fb + (dy + height) * width * 4;
+
+		for (i = 0; i < n16; ++i) {
+			src -= 64;
+			dst -= 64;
+			__raw_writel(0xffff, src);
+			wmb();
+			__raw_writel(0xffff, dst);
+			wmb();
+		}
+	} else {
+		src = tga_fb + sy * width * 4;
+		dst = tga_fb + dy * width * 4;
+
+		for (i = 0; i < n16; ++i) {
+			__raw_writel(0xffff, src);
+			wmb();
+			__raw_writel(0xffff, dst);
+			wmb();
+			src += 64;
+			dst += 64;
+		}
+	}
+
+	/* Reset the MODE register to normal.  */
+	__raw_writel(TGA_MODE_SBM_24BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
+}
+
+/* The (almost) general case of backward copy in 8bpp mode.  */
+static inline void
+copyarea_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
+	      u32 height, u32 width, u32 line_length,
+	      const struct fb_copyarea *area)
+{
+	struct tga_par *par = (struct tga_par *) info->par;
+	unsigned i, yincr;
+	int depos, sepos, backward, last_step, step;
+	u32 mask_last;
+	unsigned n32;
+	void __iomem *tga_regs;
+	void __iomem *tga_fb;
+
+	/* Do acceleration only if we are aligned on 8 pixels */
+	if ((dx | sx | width) & 7) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	yincr = line_length;
+	if (dy > sy) {
+		dy += height - 1;
+		sy += height - 1;
+		yincr = -yincr;
+	}
+	backward = dy == sy && dx > sx && dx < sx + width;
+
+	/* Compute the offsets and alignments in the frame buffer.
+	   More than anything else, these control how we do copies.  */
+	depos = dy * line_length + dx;
+	sepos = sy * line_length + sx;
+	if (backward)
+		depos += width, sepos += width;
+
+	/* Next copy full words at a time.  */
+	n32 = width / 32;
+	last_step = width % 32;
+
+	/* Finally copy the unaligned head of the span.  */
+	mask_last = (1ul << last_step) - 1;
+
+	if (!backward) {
+		step = 32;
+		last_step = 32;
+	} else {
+		step = -32;
+		last_step = -last_step;
+		sepos -= 32;
+		depos -= 32;
+	}
+
+	tga_regs = par->tga_regs_base;
+	tga_fb = par->tga_fb_base;
+
+	/* Set up the MODE and PIXELSHIFT registers.  */
+	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
+	__raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
+	wmb();
+
+	for (i = 0; i < height; ++i) {
+		unsigned long j;
+		void __iomem *sfb;
+		void __iomem *dfb;
+
+		sfb = tga_fb + sepos;
+		dfb = tga_fb + depos;
+
+		for (j = 0; j < n32; j++) {
+			if (j < 2 && j + 1 < n32 && !backward &&
+			    !(((unsigned long)sfb | (unsigned long)dfb) & 63)) {
+				do {
+					__raw_writel(sfb - tga_fb, tga_regs+TGA_COPY64_SRC);
+					wmb();
+					__raw_writel(dfb - tga_fb, tga_regs+TGA_COPY64_DST);
+					wmb();
+					sfb += 64;
+					dfb += 64;
+					j += 2;
+				} while (j + 1 < n32);
+				j--;
+				continue;
+			}
+			__raw_writel(0xffffffff, sfb);
+			wmb();
+			__raw_writel(0xffffffff, dfb);
+			wmb();
+			sfb += step;
+			dfb += step;
+		}
+
+		if (mask_last) {
+			sfb += last_step - step;
+			dfb += last_step - step;
+			__raw_writel(mask_last, sfb);
+			wmb();
+			__raw_writel(mask_last, dfb);
+			wmb();
+		}
+
+		sepos += yincr;
+		depos += yincr;
+	}
+
+	/* Reset the MODE register to normal.  */
+	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
+}
+
+static void
+tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 
+{
+	unsigned long dx, dy, width, height, sx, sy, vxres, vyres;
+	unsigned long line_length, bpp;
+
+	dx = area->dx;
+	dy = area->dy;
+	width = area->width;
+	height = area->height;
+	sx = area->sx;
+	sy = area->sy;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+	line_length = info->fix.line_length;
+
+	/* The top left corners must be in the virtual screen.  */
+	if (dx > vxres || sx > vxres || dy > vyres || sy > vyres)
+		return;
+
+	/* Clip the destination.  */
+	if (dx + width > vxres)
+		width = vxres - dx;
+	if (dy + height > vyres)
+		height = vyres - dy;
+
+	/* The source must be completely inside the virtual screen.  */
+	if (sx + width > vxres || sy + height > vyres)
+		return;
+
+	bpp = info->var.bits_per_pixel;
+
+	/* Detect copies of the entire line.  */
+	if (!(line_length & 63) && width * (bpp >> 3) == line_length) {
+		if (bpp == 8)
+			copyarea_line_8bpp(info, dy, sy, height, width);
+		else
+			copyarea_line_32bpp(info, dy, sy, height, width);
+	}
+
+	/* ??? The documentation is unclear to me exactly how the pixelshift
+	   register works in 32bpp mode.  Since I don't have hardware to test,
+	   give up for now and fall back on the generic routines.  */
+	else if (bpp == 32)
+		cfb_copyarea(info, area);
+
+	else
+		copyarea_8bpp(info, dx, dy, sx, sy, height,
+			      width, line_length, area);
+}
+
+
+/*
+ *  Initialisation
+ */
+
+static void
+tgafb_init_fix(struct fb_info *info)
+{
+	struct tga_par *par = (struct tga_par *)info->par;
+	int tga_bus_pci = dev_is_pci(par->dev);
+	int tga_bus_tc = TGA_BUS_TC(par->dev);
+	u8 tga_type = par->tga_type;
+	const char *tga_type_name = NULL;
+	unsigned memory_size;
+
+	switch (tga_type) {
+	case TGA_TYPE_8PLANE:
+		if (tga_bus_pci)
+			tga_type_name = "Digital ZLXp-E1";
+		if (tga_bus_tc)
+			tga_type_name = "Digital ZLX-E1";
+		memory_size = 2097152;
+		break;
+	case TGA_TYPE_24PLANE:
+		if (tga_bus_pci)
+			tga_type_name = "Digital ZLXp-E2";
+		if (tga_bus_tc)
+			tga_type_name = "Digital ZLX-E2";
+		memory_size = 8388608;
+		break;
+	case TGA_TYPE_24PLUSZ:
+		if (tga_bus_pci)
+			tga_type_name = "Digital ZLXp-E3";
+		if (tga_bus_tc)
+			tga_type_name = "Digital ZLX-E3";
+		memory_size = 16777216;
+		break;
+	}
+	if (!tga_type_name) {
+		tga_type_name = "Unknown";
+		memory_size = 16777216;
+	}
+
+	strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.visual = (tga_type == TGA_TYPE_8PLANE
+			    ? FB_VISUAL_PSEUDOCOLOR
+			    : FB_VISUAL_DIRECTCOLOR);
+
+	info->fix.smem_start = (size_t) par->tga_fb_base;
+	info->fix.smem_len = memory_size;
+	info->fix.mmio_start = (size_t) par->tga_regs_base;
+	info->fix.mmio_len = 512;
+
+	info->fix.xpanstep = 0;
+	info->fix.ypanstep = 0;
+	info->fix.ywrapstep = 0;
+
+	info->fix.accel = FB_ACCEL_DEC_TGA;
+
+	/*
+	 * These are needed by fb_set_logo_truepalette(), so we
+	 * set them here for 24-plane cards.
+	 */
+	if (tga_type != TGA_TYPE_8PLANE) {
+		info->var.red.length = 8;
+		info->var.green.length = 8;
+		info->var.blue.length = 8;
+		info->var.red.offset = 16;
+		info->var.green.offset = 8;
+		info->var.blue.offset = 0;
+	}
+}
+
+static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	/* We just use this to catch switches out of graphics mode. */
+	tgafb_set_par(info); /* A bit of overkill for BASE_ADDR reset. */
+	return 0;
+}
+
+static int tgafb_register(struct device *dev)
+{
+	static const struct fb_videomode modedb_tc = {
+		/* 1280x1024 @ 72 Hz, 76.8 kHz hsync */
+		"1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3,
+		FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED
+	};
+
+	static unsigned int const fb_offset_presets[4] = {
+		TGA_8PLANE_FB_OFFSET,
+		TGA_24PLANE_FB_OFFSET,
+		0xffffffff,
+		TGA_24PLUSZ_FB_OFFSET
+	};
+
+	const struct fb_videomode *modedb_tga = NULL;
+	resource_size_t bar0_start = 0, bar0_len = 0;
+	const char *mode_option_tga = NULL;
+	int tga_bus_pci = dev_is_pci(dev);
+	int tga_bus_tc = TGA_BUS_TC(dev);
+	unsigned int modedbsize_tga = 0;
+	void __iomem *mem_base;
+	struct fb_info *info;
+	struct tga_par *par;
+	u8 tga_type;
+	int ret = 0;
+
+	/* Enable device in PCI config.  */
+	if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) {
+		printk(KERN_ERR "tgafb: Cannot enable PCI device\n");
+		return -ENODEV;
+	}
+
+	/* Allocate the fb and par structures.  */
+	info = framebuffer_alloc(sizeof(struct tga_par), dev);
+	if (!info) {
+		printk(KERN_ERR "tgafb: Cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	dev_set_drvdata(dev, info);
+
+	/* Request the mem regions.  */
+	ret = -ENODEV;
+	if (tga_bus_pci) {
+		bar0_start = pci_resource_start(to_pci_dev(dev), 0);
+		bar0_len = pci_resource_len(to_pci_dev(dev), 0);
+	}
+	if (tga_bus_tc) {
+		bar0_start = to_tc_dev(dev)->resource.start;
+		bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
+	}
+	if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {
+		printk(KERN_ERR "tgafb: cannot reserve FB region\n");
+		goto err0;
+	}
+
+	/* Map the framebuffer.  */
+	mem_base = ioremap_nocache(bar0_start, bar0_len);
+	if (!mem_base) {
+		printk(KERN_ERR "tgafb: Cannot map MMIO\n");
+		goto err1;
+	}
+
+	/* Grab info about the card.  */
+	tga_type = (readl(mem_base) >> 12) & 0x0f;
+	par->dev = dev;
+	par->tga_mem_base = mem_base;
+	par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
+	par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
+	par->tga_type = tga_type;
+	if (tga_bus_pci)
+		par->tga_chip_rev = (to_pci_dev(dev))->revision;
+	if (tga_bus_tc)
+		par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
+
+	/* Setup framebuffer.  */
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+		      FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
+	info->fbops = &tgafb_ops;
+	info->screen_base = par->tga_fb_base;
+	info->pseudo_palette = par->palette;
+
+	/* This should give a reasonable default video mode.  */
+	if (tga_bus_pci) {
+		mode_option_tga = mode_option_pci;
+	}
+	if (tga_bus_tc) {
+		mode_option_tga = mode_option_tc;
+		modedb_tga = &modedb_tc;
+		modedbsize_tga = 1;
+	}
+
+	tgafb_init_fix(info);
+
+	ret = fb_find_mode(&info->var, info,
+			   mode_option ? mode_option : mode_option_tga,
+			   modedb_tga, modedbsize_tga, NULL,
+			   tga_type == TGA_TYPE_8PLANE ? 8 : 32);
+	if (ret == 0 || ret == 4) {
+		printk(KERN_ERR "tgafb: Could not find valid video mode\n");
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+		printk(KERN_ERR "tgafb: Could not allocate color map\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	tgafb_set_par(info);
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "tgafb: Could not register framebuffer\n");
+		ret = -EINVAL;
+		goto err2;
+	}
+
+	if (tga_bus_pci) {
+		pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
+			par->tga_chip_rev);
+		pr_info("tgafb: at PCI bus %d, device %d, function %d\n",
+			to_pci_dev(dev)->bus->number,
+			PCI_SLOT(to_pci_dev(dev)->devfn),
+			PCI_FUNC(to_pci_dev(dev)->devfn));
+	}
+	if (tga_bus_tc)
+		pr_info("tgafb: SFB+ detected, rev=0x%02x\n",
+			par->tga_chip_rev);
+	fb_info(info, "%s frame buffer device at 0x%lx\n",
+		info->fix.id, (long)bar0_start);
+
+	return 0;
+
+ err2:
+	fb_dealloc_cmap(&info->cmap);
+ err1:
+	if (mem_base)
+		iounmap(mem_base);
+	release_mem_region(bar0_start, bar0_len);
+ err0:
+	framebuffer_release(info);
+	return ret;
+}
+
+static void tgafb_unregister(struct device *dev)
+{
+	resource_size_t bar0_start = 0, bar0_len = 0;
+	int tga_bus_pci = dev_is_pci(dev);
+	int tga_bus_tc = TGA_BUS_TC(dev);
+	struct fb_info *info = NULL;
+	struct tga_par *par;
+
+	info = dev_get_drvdata(dev);
+	if (!info)
+		return;
+
+	par = info->par;
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
+	iounmap(par->tga_mem_base);
+	if (tga_bus_pci) {
+		bar0_start = pci_resource_start(to_pci_dev(dev), 0);
+		bar0_len = pci_resource_len(to_pci_dev(dev), 0);
+	}
+	if (tga_bus_tc) {
+		bar0_start = to_tc_dev(dev)->resource.start;
+		bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
+	}
+	release_mem_region(bar0_start, bar0_len);
+	framebuffer_release(info);
+}
+
+static void tgafb_exit(void)
+{
+	tc_unregister_driver(&tgafb_tc_driver);
+	pci_unregister_driver(&tgafb_pci_driver);
+}
+
+#ifndef MODULE
+static int tgafb_setup(char *arg)
+{
+	char *this_opt;
+
+	if (arg && *arg) {
+		while ((this_opt = strsep(&arg, ","))) {
+			if (!*this_opt)
+				continue;
+			if (!strncmp(this_opt, "mode:", 5))
+				mode_option = this_opt+5;
+			else
+				printk(KERN_ERR
+				       "tgafb: unknown parameter %s\n",
+				       this_opt);
+		}
+	}
+
+	return 0;
+}
+#endif /* !MODULE */
+
+static int tgafb_init(void)
+{
+	int status;
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tgafb", &option))
+		return -ENODEV;
+	tgafb_setup(option);
+#endif
+	status = pci_register_driver(&tgafb_pci_driver);
+	if (!status)
+		status = tc_register_driver(&tgafb_tc_driver);
+	return status;
+}
+
+/*
+ *  Modularisation
+ */
+
+module_init(tgafb_init);
+module_exit(tgafb_exit);
+
+MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/tmiofb.c b/drivers/video/fbdev/tmiofb.c
new file mode 100644
index 000000000000..7fb4e321a431
--- /dev/null
+++ b/drivers/video/fbdev/tmiofb.c
@@ -0,0 +1,1048 @@
+/*
+ * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller
+ *
+ * Copyright(C) 2005-2006 Chris Humbert
+ * Copyright(C) 2005 Dirk Opfer
+ * Copytight(C) 2007,2008 Dmitry Baryshkov
+ *
+ * Based on:
+ *	drivers/video/w100fb.c
+ *	code written by Sharp/Lineo for 2.4 kernels
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+/* Why should fb driver call console functions? because console_lock() */
+#include <linux/console.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/uaccess.h>
+
+/*
+ * accelerator commands
+ */
+#define TMIOFB_ACC_CSADR(x)	(0x00000000 | ((x) & 0x001ffffe))
+#define TMIOFB_ACC_CHPIX(x)	(0x01000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_CVPIX(x)	(0x02000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PSADR(x)	(0x03000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_PHPIX(x)	(0x04000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PVPIX(x)	(0x05000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PHOFS(x)	(0x06000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PVOFS(x)	(0x07000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_POADR(x)	(0x08000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_RSTR(x)	(0x09000000 | ((x) & 0x000000ff))
+#define TMIOFB_ACC_TCLOR(x)	(0x0A000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_FILL(x)	(0x0B000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_DSADR(x)	(0x0C000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_SSADR(x)	(0x0D000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_DHPIX(x)	(0x0E000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_DVPIX(x)	(0x0F000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_SHPIX(x)	(0x10000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_SVPIX(x)	(0x11000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_LBINI(x)	(0x12000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_LBK2(x)	(0x13000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SHBINI(x)	(0x14000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SHBK2(x)	(0x15000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SVBINI(x)	(0x16000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SVBK2(x)	(0x17000000 | ((x) & 0x0000ffff))
+
+#define TMIOFB_ACC_CMGO		0x20000000
+#define TMIOFB_ACC_CMGO_CEND	0x00000001
+#define TMIOFB_ACC_CMGO_INT	0x00000002
+#define TMIOFB_ACC_CMGO_CMOD	0x00000010
+#define TMIOFB_ACC_CMGO_CDVRV	0x00000020
+#define TMIOFB_ACC_CMGO_CDHRV	0x00000040
+#define TMIOFB_ACC_CMGO_RUND	0x00008000
+#define TMIOFB_ACC_SCGO		0x21000000
+#define TMIOFB_ACC_SCGO_CEND	0x00000001
+#define TMIOFB_ACC_SCGO_INT	0x00000002
+#define TMIOFB_ACC_SCGO_ROP3	0x00000004
+#define TMIOFB_ACC_SCGO_TRNS	0x00000008
+#define TMIOFB_ACC_SCGO_DVRV	0x00000010
+#define TMIOFB_ACC_SCGO_DHRV	0x00000020
+#define TMIOFB_ACC_SCGO_SVRV	0x00000040
+#define TMIOFB_ACC_SCGO_SHRV	0x00000080
+#define TMIOFB_ACC_SCGO_DSTXY	0x00008000
+#define TMIOFB_ACC_SBGO		0x22000000
+#define TMIOFB_ACC_SBGO_CEND	0x00000001
+#define TMIOFB_ACC_SBGO_INT	0x00000002
+#define TMIOFB_ACC_SBGO_DVRV	0x00000010
+#define TMIOFB_ACC_SBGO_DHRV	0x00000020
+#define TMIOFB_ACC_SBGO_SVRV	0x00000040
+#define TMIOFB_ACC_SBGO_SHRV	0x00000080
+#define TMIOFB_ACC_SBGO_SBMD	0x00000100
+#define TMIOFB_ACC_FLGO		0x23000000
+#define TMIOFB_ACC_FLGO_CEND	0x00000001
+#define TMIOFB_ACC_FLGO_INT	0x00000002
+#define TMIOFB_ACC_FLGO_ROP3	0x00000004
+#define TMIOFB_ACC_LDGO		0x24000000
+#define TMIOFB_ACC_LDGO_CEND	0x00000001
+#define TMIOFB_ACC_LDGO_INT	0x00000002
+#define TMIOFB_ACC_LDGO_ROP3	0x00000004
+#define TMIOFB_ACC_LDGO_ENDPX	0x00000008
+#define TMIOFB_ACC_LDGO_LVRV	0x00000010
+#define TMIOFB_ACC_LDGO_LHRV	0x00000020
+#define TMIOFB_ACC_LDGO_LDMOD	0x00000040
+
+/* a FIFO is always allocated, even if acceleration is not used */
+#define TMIOFB_FIFO_SIZE	512
+
+/*
+ * LCD Host Controller Configuration Register
+ *
+ * This iomem area supports only 16-bit IO.
+ */
+#define CCR_CMD			0x04 /* Command				*/
+#define CCR_REVID		0x08 /* Revision ID			*/
+#define CCR_BASEL		0x10 /* LCD Control Reg Base Addr Low	*/
+#define CCR_BASEH		0x12 /* LCD Control Reg Base Addr High	*/
+#define CCR_UGCC		0x40 /* Unified Gated Clock Control	*/
+#define CCR_GCC			0x42 /* Gated Clock Control		*/
+#define CCR_USC			0x50 /* Unified Software Clear		*/
+#define CCR_VRAMRTC		0x60 /* VRAM Timing Control		*/
+				/* 0x61 VRAM Refresh Control		*/
+#define CCR_VRAMSAC		0x62 /* VRAM Access Control		*/
+				/* 0x63	VRAM Status			*/
+#define CCR_VRAMBC		0x64 /* VRAM Block Control		*/
+
+/*
+ * LCD Control Register
+ *
+ * This iomem area supports only 16-bit IO.
+ */
+#define LCR_UIS			0x000 /* Unified Interrupt Status	*/
+#define LCR_VHPN		0x008 /* VRAM Horizontal Pixel Number	*/
+#define LCR_CFSAL		0x00a /* Command FIFO Start Address Low	*/
+#define LCR_CFSAH		0x00c /* Command FIFO Start Address High */
+#define LCR_CFS			0x00e /* Command FIFO Size		*/
+#define LCR_CFWS		0x010 /* Command FIFO Writeable Size	*/
+#define LCR_BBIE		0x012 /* BitBLT Interrupt Enable	*/
+#define LCR_BBISC		0x014 /* BitBLT Interrupt Status and Clear */
+#define LCR_CCS			0x016 /* Command Count Status		*/
+#define LCR_BBES		0x018 /* BitBLT Execution Status	*/
+#define LCR_CMDL		0x01c /* Command Low			*/
+#define LCR_CMDH		0x01e /* Command High			*/
+#define LCR_CFC			0x022 /* Command FIFO Clear		*/
+#define LCR_CCIFC		0x024 /* CMOS Camera IF Control		*/
+#define LCR_HWT			0x026 /* Hardware Test			*/
+#define LCR_LCDCCRC		0x100 /* LCDC Clock and Reset Control	*/
+#define LCR_LCDCC		0x102 /* LCDC Control			*/
+#define LCR_LCDCOPC		0x104 /* LCDC Output Pin Control	*/
+#define LCR_LCDIS		0x108 /* LCD Interrupt Status		*/
+#define LCR_LCDIM		0x10a /* LCD Interrupt Mask		*/
+#define LCR_LCDIE		0x10c /* LCD Interrupt Enable		*/
+#define LCR_GDSAL		0x122 /* Graphics Display Start Address Low */
+#define LCR_GDSAH		0x124 /* Graphics Display Start Address High */
+#define LCR_VHPCL		0x12a /* VRAM Horizontal Pixel Count Low */
+#define LCR_VHPCH		0x12c /* VRAM Horizontal Pixel Count High */
+#define LCR_GM			0x12e /* Graphic Mode(VRAM access enable) */
+#define LCR_HT			0x140 /* Horizontal Total		*/
+#define LCR_HDS			0x142 /* Horizontal Display Start	*/
+#define LCR_HSS			0x144 /* H-Sync Start			*/
+#define LCR_HSE			0x146 /* H-Sync End			*/
+#define LCR_HNP			0x14c /* Horizontal Number of Pixels	*/
+#define LCR_VT			0x150 /* Vertical Total			*/
+#define LCR_VDS			0x152 /* Vertical Display Start		*/
+#define LCR_VSS			0x154 /* V-Sync Start			*/
+#define LCR_VSE			0x156 /* V-Sync End			*/
+#define LCR_CDLN		0x160 /* Current Display Line Number	*/
+#define LCR_ILN			0x162 /* Interrupt Line Number		*/
+#define LCR_SP			0x164 /* Sync Polarity			*/
+#define LCR_MISC		0x166 /* MISC(RGB565 mode)		*/
+#define LCR_VIHSS		0x16a /* Video Interface H-Sync Start	*/
+#define LCR_VIVS		0x16c /* Video Interface Vertical Start	*/
+#define LCR_VIVE		0x16e /* Video Interface Vertical End	*/
+#define LCR_VIVSS		0x170 /* Video Interface V-Sync Start	*/
+#define LCR_VCCIS		0x17e /* Video / CMOS Camera Interface Select */
+#define LCR_VIDWSAL		0x180 /* VI Data Write Start Address Low */
+#define LCR_VIDWSAH		0x182 /* VI Data Write Start Address High */
+#define LCR_VIDRSAL		0x184 /* VI Data Read Start Address Low	*/
+#define LCR_VIDRSAH		0x186 /* VI Data Read Start Address High */
+#define LCR_VIPDDST		0x188 /* VI Picture Data Display Start Timing */
+#define LCR_VIPDDET		0x186 /* VI Picture Data Display End Timing */
+#define LCR_VIE			0x18c /* Video Interface Enable		*/
+#define LCR_VCS			0x18e /* Video/Camera Select		*/
+#define LCR_VPHWC		0x194 /* Video Picture Horizontal Wait Count */
+#define LCR_VPHS		0x196 /* Video Picture Horizontal Size	*/
+#define LCR_VPVWC		0x198 /* Video Picture Vertical Wait Count */
+#define LCR_VPVS		0x19a /* Video Picture Vertical Size	*/
+#define LCR_PLHPIX		0x1a0 /* PLHPIX				*/
+#define LCR_XS			0x1a2 /* XStart				*/
+#define LCR_XCKHW		0x1a4 /* XCK High Width			*/
+#define LCR_STHS		0x1a8 /* STH Start			*/
+#define LCR_VT2			0x1aa /* Vertical Total			*/
+#define LCR_YCKSW		0x1ac /* YCK Start Wait			*/
+#define LCR_YSTS		0x1ae /* YST Start			*/
+#define LCR_PPOLS		0x1b0 /* #PPOL Start			*/
+#define LCR_PRECW		0x1b2 /* PREC Width			*/
+#define LCR_VCLKHW		0x1b4 /* VCLK High Width		*/
+#define LCR_OC			0x1b6 /* Output Control			*/
+
+static char *mode_option;
+
+struct tmiofb_par {
+	u32				pseudo_palette[16];
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+	wait_queue_head_t		wait_acc;
+	bool				use_polling;
+#endif
+
+	void __iomem			*ccr;
+	void __iomem			*lcr;
+};
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * reasons for an interrupt:
+ *	uis	bbisc	lcdis
+ *	0100	0001	accelerator command completed
+ * 	2000	0001	vsync start
+ * 	2000	0002	display start
+ * 	2000	0004	line number match(0x1ff mask???)
+ */
+static irqreturn_t tmiofb_irq(int irq, void *__info)
+{
+	struct fb_info *info = __info;
+	struct tmiofb_par *par = info->par;
+	unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
+
+
+	tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+	/*
+	 * We were in polling mode and now we got correct irq.
+	 * Switch back to IRQ-based sync of command FIFO
+	 */
+	if (unlikely(par->use_polling && irq != -1)) {
+		printk(KERN_INFO "tmiofb: switching to waitq\n");
+		par->use_polling = false;
+	}
+
+	if (bbisc & 1)
+		wake_up(&par->wait_acc);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+
+/*
+ * Turns off the LCD controller and LCD host controller.
+ */
+static int tmiofb_hw_stop(struct platform_device *dev)
+{
+	struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct tmiofb_par *par = info->par;
+
+	tmio_iowrite16(0, par->ccr + CCR_UGCC);
+	tmio_iowrite16(0, par->lcr + LCR_GM);
+	data->lcd_set_power(dev, 0);
+	tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+
+	return 0;
+}
+
+/*
+ * Initializes the LCD host controller.
+ */
+static int tmiofb_hw_init(struct platform_device *dev)
+{
+	const struct mfd_cell *cell = mfd_get_cell(dev);
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct tmiofb_par *par = info->par;
+	const struct resource *nlcr = &cell->resources[0];
+	const struct resource *vram = &cell->resources[2];
+	unsigned long base;
+
+	if (nlcr == NULL || vram == NULL)
+		return -EINVAL;
+
+	base = nlcr->start;
+
+	tmio_iowrite16(0x003a, par->ccr + CCR_UGCC);
+	tmio_iowrite16(0x003a, par->ccr + CCR_GCC);
+	tmio_iowrite16(0x3f00, par->ccr + CCR_USC);
+
+	msleep(2); /* wait for device to settle */
+
+	tmio_iowrite16(0x0000, par->ccr + CCR_USC);
+	tmio_iowrite16(base >> 16, par->ccr + CCR_BASEH);
+	tmio_iowrite16(base, par->ccr + CCR_BASEL);
+	tmio_iowrite16(0x0002, par->ccr + CCR_CMD); /* base address enable */
+	tmio_iowrite16(0x40a8, par->ccr + CCR_VRAMRTC); /* VRAMRC, VRAMTC */
+	tmio_iowrite16(0x0018, par->ccr + CCR_VRAMSAC); /* VRAMSTS, VRAMAC */
+	tmio_iowrite16(0x0002, par->ccr + CCR_VRAMBC);
+	msleep(2); /* wait for device to settle */
+	tmio_iowrite16(0x000b, par->ccr + CCR_VRAMBC);
+
+	base = vram->start + info->screen_size;
+	tmio_iowrite16(base >> 16, par->lcr + LCR_CFSAH);
+	tmio_iowrite16(base, par->lcr + LCR_CFSAL);
+	tmio_iowrite16(TMIOFB_FIFO_SIZE - 1, par->lcr + LCR_CFS);
+	tmio_iowrite16(1, par->lcr + LCR_CFC);
+	tmio_iowrite16(1, par->lcr + LCR_BBIE);
+	tmio_iowrite16(0, par->lcr + LCR_CFWS);
+
+	return 0;
+}
+
+/*
+ * Sets the LCD controller's output resolution and pixel clock
+ */
+static void tmiofb_hw_mode(struct platform_device *dev)
+{
+	struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct fb_videomode *mode = info->mode;
+	struct tmiofb_par *par = info->par;
+	unsigned int i;
+
+	tmio_iowrite16(0, par->lcr + LCR_GM);
+	data->lcd_set_power(dev, 0);
+	tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+	data->lcd_mode(dev, mode);
+	data->lcd_set_power(dev, 1);
+
+	tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPN);
+	tmio_iowrite16(0, par->lcr + LCR_GDSAH);
+	tmio_iowrite16(0, par->lcr + LCR_GDSAL);
+	tmio_iowrite16(info->fix.line_length >> 16, par->lcr + LCR_VHPCH);
+	tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPCL);
+	tmio_iowrite16(i = 0, par->lcr + LCR_HSS);
+	tmio_iowrite16(i += mode->hsync_len, par->lcr + LCR_HSE);
+	tmio_iowrite16(i += mode->left_margin, par->lcr + LCR_HDS);
+	tmio_iowrite16(i += mode->xres + mode->right_margin, par->lcr + LCR_HT);
+	tmio_iowrite16(mode->xres, par->lcr + LCR_HNP);
+	tmio_iowrite16(i = 0, par->lcr + LCR_VSS);
+	tmio_iowrite16(i += mode->vsync_len, par->lcr + LCR_VSE);
+	tmio_iowrite16(i += mode->upper_margin, par->lcr + LCR_VDS);
+	tmio_iowrite16(i += mode->yres, par->lcr + LCR_ILN);
+	tmio_iowrite16(i += mode->lower_margin, par->lcr + LCR_VT);
+	tmio_iowrite16(3, par->lcr + LCR_MISC); /* RGB565 mode */
+	tmio_iowrite16(1, par->lcr + LCR_GM); /* VRAM enable */
+	tmio_iowrite16(0x4007, par->lcr + LCR_LCDCC);
+	tmio_iowrite16(3, par->lcr + LCR_SP);  /* sync polarity */
+
+	tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+	msleep(5); /* wait for device to settle */
+	tmio_iowrite16(0x0014, par->lcr + LCR_LCDCCRC); /* STOP_CKP */
+	msleep(5); /* wait for device to settle */
+	tmio_iowrite16(0x0015, par->lcr + LCR_LCDCCRC); /* STOP_CKP|SOFT_RESET*/
+	tmio_iowrite16(0xfffa, par->lcr + LCR_VCS);
+}
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+static int __must_check
+tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
+{
+	struct tmiofb_par *par = info->par;
+	/*
+	 * This code can be called with interrupts disabled.
+	 * So instead of relaying on irq to trigger the event,
+	 * poll the state till the necessary command is executed.
+	 */
+	if (irqs_disabled() || par->use_polling) {
+		int i = 0;
+		while (tmio_ioread16(par->lcr + LCR_CCS) > ccs) {
+			udelay(1);
+			i++;
+			if (i > 10000) {
+				pr_err("tmiofb: timeout waiting for %d\n",
+						ccs);
+				return -ETIMEDOUT;
+			}
+			tmiofb_irq(-1, info);
+		}
+	} else {
+		if (!wait_event_interruptible_timeout(par->wait_acc,
+				tmio_ioread16(par->lcr + LCR_CCS) <= ccs,
+				1000)) {
+			pr_err("tmiofb: timeout waiting for %d\n", ccs);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Writes an accelerator command to the accelerator's FIFO.
+ */
+static int
+tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count)
+{
+	struct tmiofb_par *par = info->par;
+	int ret;
+
+	ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count);
+	if (ret)
+		return ret;
+
+	for (; count; count--, cmd++) {
+		tmio_iowrite16(*cmd >> 16, par->lcr + LCR_CMDH);
+		tmio_iowrite16(*cmd, par->lcr + LCR_CMDL);
+	}
+
+	return ret;
+}
+
+/*
+ * Wait for the accelerator to finish its operations before writing
+ * to the framebuffer for consistent display output.
+ */
+static int tmiofb_sync(struct fb_info *fbi)
+{
+	struct tmiofb_par *par = fbi->par;
+
+	int ret;
+	int i = 0;
+
+	ret = tmiofb_acc_wait(fbi, 0);
+
+	while (tmio_ioread16(par->lcr + LCR_BBES) & 2) { /* blit active */
+		udelay(1);
+		i++ ;
+		if (i > 10000) {
+			printk(KERN_ERR "timeout waiting for blit to end!\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return ret;
+}
+
+static void
+tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect)
+{
+	const u32 cmd[] = {
+		TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2),
+		TMIOFB_ACC_DHPIX(rect->width - 1),
+		TMIOFB_ACC_DVPIX(rect->height - 1),
+		TMIOFB_ACC_FILL(rect->color),
+		TMIOFB_ACC_FLGO,
+	};
+
+	if (fbi->state != FBINFO_STATE_RUNNING ||
+	    fbi->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(fbi, rect);
+		return;
+	}
+
+	tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
+}
+
+static void
+tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area)
+{
+	const u32 cmd[] = {
+		TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2),
+		TMIOFB_ACC_DHPIX(area->width - 1),
+		TMIOFB_ACC_DVPIX(area->height - 1),
+		TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2),
+		TMIOFB_ACC_SCGO,
+	};
+
+	if (fbi->state != FBINFO_STATE_RUNNING ||
+	    fbi->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(fbi, area);
+		return;
+	}
+
+	tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
+}
+#endif
+
+static void tmiofb_clearscreen(struct fb_info *info)
+{
+	const struct fb_fillrect rect = {
+		.dx	= 0,
+		.dy	= 0,
+		.width	= info->mode->xres,
+		.height	= info->mode->yres,
+		.color	= 0,
+		.rop	= ROP_COPY,
+	};
+
+	info->fbops->fb_fillrect(info, &rect);
+}
+
+static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank)
+{
+	struct tmiofb_par *par = fbi->par;
+	struct fb_videomode *mode = fbi->mode;
+	unsigned int vcount = tmio_ioread16(par->lcr + LCR_CDLN);
+	unsigned int vds = mode->vsync_len + mode->upper_margin;
+
+	vblank->vcount = vcount;
+	vblank->flags = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT
+						| FB_VBLANK_HAVE_VSYNC;
+
+	if (vcount < mode->vsync_len)
+		vblank->flags |= FB_VBLANK_VSYNCING;
+
+	if (vcount < vds || vcount > vds + mode->yres)
+		vblank->flags |= FB_VBLANK_VBLANKING;
+
+	return 0;
+}
+
+
+static int tmiofb_ioctl(struct fb_info *fbi,
+		unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case FBIOGET_VBLANK: {
+		struct fb_vblank vblank = {0};
+		void __user *argp = (void __user *) arg;
+
+		tmiofb_vblank(fbi, &vblank);
+		if (copy_to_user(argp, &vblank, sizeof vblank))
+			return -EFAULT;
+		return 0;
+	}
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+	case FBIO_TMIO_ACC_SYNC:
+		tmiofb_sync(fbi);
+		return 0;
+
+	case FBIO_TMIO_ACC_WRITE: {
+		u32 __user *argp = (void __user *) arg;
+		u32 len;
+		u32 acc[16];
+
+		if (get_user(len, argp))
+			return -EFAULT;
+		if (len > ARRAY_SIZE(acc))
+			return -EINVAL;
+		if (copy_from_user(acc, argp + 1, sizeof(u32) * len))
+			return -EFAULT;
+
+		return tmiofb_acc_write(fbi, acc, len);
+	}
+#endif
+	}
+
+	return -ENOTTY;
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Select the smallest mode that allows the desired resolution to be
+ * displayed.  If desired, the x and y parameters can be rounded up to
+ * match the selected mode.
+ */
+static struct fb_videomode *
+tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+	struct tmio_fb_data *data = dev_get_platdata(info->device);
+	struct fb_videomode *best = NULL;
+	int i;
+
+	for (i = 0; i < data->num_modes; i++) {
+		struct fb_videomode *mode = data->modes + i;
+
+		if (mode->xres >= var->xres && mode->yres >= var->yres
+				&& (!best || (mode->xres < best->xres
+					   && mode->yres < best->yres)))
+			best = mode;
+	}
+
+	return best;
+}
+
+static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+
+	struct fb_videomode *mode;
+	struct tmio_fb_data *data = dev_get_platdata(info->device);
+
+	mode = tmiofb_find_mode(info, var);
+	if (!mode || var->bits_per_pixel > 16)
+		return -EINVAL;
+
+	fb_videomode_to_var(var, mode);
+
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = info->screen_size / (mode->xres * 2);
+
+	if (var->yres_virtual < var->yres)
+		return -EINVAL;
+
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->bits_per_pixel = 16;
+	var->grayscale = 0;
+	var->red.offset = 11;
+	var->red.length = 5;
+	var->green.offset = 5;
+	var->green.length = 6;
+	var->blue.offset = 0;
+	var->blue.length = 5;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->nonstd = 0;
+	var->height = data->height; /* mm */
+	var->width = data->width; /* mm */
+	var->rotate = 0;
+	return 0;
+}
+
+static int tmiofb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_videomode *mode;
+
+	mode = tmiofb_find_mode(info, var);
+	if (!mode)
+		return -EINVAL;
+
+	info->mode = mode;
+	info->fix.line_length = info->mode->xres *
+			var->bits_per_pixel / 8;
+
+	tmiofb_hw_mode(to_platform_device(info->device));
+	tmiofb_clearscreen(info);
+	return 0;
+}
+
+static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct tmiofb_par *par = info->par;
+
+	if (regno < ARRAY_SIZE(par->pseudo_palette)) {
+		par->pseudo_palette[regno] =
+			((red & 0xf800)) |
+			((green & 0xfc00) >>  5) |
+			((blue & 0xf800) >> 11);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int tmiofb_blank(int blank, struct fb_info *info)
+{
+	/*
+	 * everything is done in lcd/bl drivers.
+	 * this is purely to make sysfs happy and work.
+	 */
+	return 0;
+}
+
+static struct fb_ops tmiofb_ops = {
+	.owner		= THIS_MODULE,
+
+	.fb_ioctl	= tmiofb_ioctl,
+	.fb_check_var	= tmiofb_check_var,
+	.fb_set_par	= tmiofb_set_par,
+	.fb_setcolreg	= tmiofb_setcolreg,
+	.fb_blank	= tmiofb_blank,
+	.fb_imageblit	= cfb_imageblit,
+#ifdef CONFIG_FB_TMIO_ACCELL
+	.fb_sync	= tmiofb_sync,
+	.fb_fillrect	= tmiofb_fillrect,
+	.fb_copyarea	= tmiofb_copyarea,
+#else
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+#endif
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int tmiofb_probe(struct platform_device *dev)
+{
+	const struct mfd_cell *cell = mfd_get_cell(dev);
+	struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
+	struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
+	int irq = platform_get_irq(dev, 0);
+	struct fb_info *info;
+	struct tmiofb_par *par;
+	int retval;
+
+	/*
+	 * This is the only way ATM to disable the fb
+	 */
+	if (data == NULL) {
+		dev_err(&dev->dev, "NULL platform data!\n");
+		return -EINVAL;
+	}
+	if (ccr == NULL || lcr == NULL || vram == NULL || irq < 0) {
+		dev_err(&dev->dev, "missing resources\n");
+		return -EINVAL;
+	}
+
+	info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev);
+
+	if (!info)
+		return -ENOMEM;
+
+	par = info->par;
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+	init_waitqueue_head(&par->wait_acc);
+
+	par->use_polling = true;
+
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA
+			| FBINFO_HWACCEL_FILLRECT;
+#else
+	info->flags = FBINFO_DEFAULT;
+#endif
+
+	info->fbops = &tmiofb_ops;
+
+	strcpy(info->fix.id, "tmio-fb");
+	info->fix.smem_start = vram->start;
+	info->fix.smem_len = resource_size(vram);
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.mmio_start = lcr->start;
+	info->fix.mmio_len = resource_size(lcr);
+	info->fix.accel = FB_ACCEL_NONE;
+	info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE);
+	info->pseudo_palette = par->pseudo_palette;
+
+	par->ccr = ioremap(ccr->start, resource_size(ccr));
+	if (!par->ccr) {
+		retval = -ENOMEM;
+		goto err_ioremap_ccr;
+	}
+
+	par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len);
+	if (!par->lcr) {
+		retval = -ENOMEM;
+		goto err_ioremap_lcr;
+	}
+
+	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+	if (!info->screen_base) {
+		retval = -ENOMEM;
+		goto err_ioremap_vram;
+	}
+
+	retval = request_irq(irq, &tmiofb_irq, 0,
+					dev_name(&dev->dev), info);
+
+	if (retval)
+		goto err_request_irq;
+
+	platform_set_drvdata(dev, info);
+
+	retval = fb_find_mode(&info->var, info, mode_option,
+			data->modes, data->num_modes,
+			data->modes, 16);
+	if (!retval) {
+		retval = -EINVAL;
+		goto err_find_mode;
+	}
+
+	if (cell->enable) {
+		retval = cell->enable(dev);
+		if (retval)
+			goto err_enable;
+	}
+
+	retval = tmiofb_hw_init(dev);
+	if (retval)
+		goto err_hw_init;
+
+	fb_videomode_to_modelist(data->modes, data->num_modes,
+				 &info->modelist);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_register_framebuffer;
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	return 0;
+
+err_register_framebuffer:
+/*err_set_par:*/
+	tmiofb_hw_stop(dev);
+err_hw_init:
+	if (cell->disable)
+		cell->disable(dev);
+err_enable:
+err_find_mode:
+	free_irq(irq, info);
+err_request_irq:
+	iounmap(info->screen_base);
+err_ioremap_vram:
+	iounmap(par->lcr);
+err_ioremap_lcr:
+	iounmap(par->ccr);
+err_ioremap_ccr:
+	framebuffer_release(info);
+	return retval;
+}
+
+static int tmiofb_remove(struct platform_device *dev)
+{
+	const struct mfd_cell *cell = mfd_get_cell(dev);
+	struct fb_info *info = platform_get_drvdata(dev);
+	int irq = platform_get_irq(dev, 0);
+	struct tmiofb_par *par;
+
+	if (info) {
+		par = info->par;
+		unregister_framebuffer(info);
+
+		tmiofb_hw_stop(dev);
+
+		if (cell->disable)
+			cell->disable(dev);
+
+		free_irq(irq, info);
+
+		iounmap(info->screen_base);
+		iounmap(par->lcr);
+		iounmap(par->ccr);
+
+		framebuffer_release(info);
+	}
+
+	return 0;
+}
+
+#ifdef DEBUG
+static void tmiofb_dump_regs(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct tmiofb_par *par = info->par;
+
+	printk(KERN_DEBUG "lhccr:\n");
+#define CCR_PR(n)	printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
+		tmio_ioread16(par->ccr + CCR_ ## n));
+	CCR_PR(CMD);
+	CCR_PR(REVID);
+	CCR_PR(BASEL);
+	CCR_PR(BASEH);
+	CCR_PR(UGCC);
+	CCR_PR(GCC);
+	CCR_PR(USC);
+	CCR_PR(VRAMRTC);
+	CCR_PR(VRAMSAC);
+	CCR_PR(VRAMBC);
+#undef CCR_PR
+
+	printk(KERN_DEBUG "lcr: \n");
+#define LCR_PR(n)	printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
+		tmio_ioread16(par->lcr + LCR_ ## n));
+	LCR_PR(UIS);
+	LCR_PR(VHPN);
+	LCR_PR(CFSAL);
+	LCR_PR(CFSAH);
+	LCR_PR(CFS);
+	LCR_PR(CFWS);
+	LCR_PR(BBIE);
+	LCR_PR(BBISC);
+	LCR_PR(CCS);
+	LCR_PR(BBES);
+	LCR_PR(CMDL);
+	LCR_PR(CMDH);
+	LCR_PR(CFC);
+	LCR_PR(CCIFC);
+	LCR_PR(HWT);
+	LCR_PR(LCDCCRC);
+	LCR_PR(LCDCC);
+	LCR_PR(LCDCOPC);
+	LCR_PR(LCDIS);
+	LCR_PR(LCDIM);
+	LCR_PR(LCDIE);
+	LCR_PR(GDSAL);
+	LCR_PR(GDSAH);
+	LCR_PR(VHPCL);
+	LCR_PR(VHPCH);
+	LCR_PR(GM);
+	LCR_PR(HT);
+	LCR_PR(HDS);
+	LCR_PR(HSS);
+	LCR_PR(HSE);
+	LCR_PR(HNP);
+	LCR_PR(VT);
+	LCR_PR(VDS);
+	LCR_PR(VSS);
+	LCR_PR(VSE);
+	LCR_PR(CDLN);
+	LCR_PR(ILN);
+	LCR_PR(SP);
+	LCR_PR(MISC);
+	LCR_PR(VIHSS);
+	LCR_PR(VIVS);
+	LCR_PR(VIVE);
+	LCR_PR(VIVSS);
+	LCR_PR(VCCIS);
+	LCR_PR(VIDWSAL);
+	LCR_PR(VIDWSAH);
+	LCR_PR(VIDRSAL);
+	LCR_PR(VIDRSAH);
+	LCR_PR(VIPDDST);
+	LCR_PR(VIPDDET);
+	LCR_PR(VIE);
+	LCR_PR(VCS);
+	LCR_PR(VPHWC);
+	LCR_PR(VPHS);
+	LCR_PR(VPVWC);
+	LCR_PR(VPVS);
+	LCR_PR(PLHPIX);
+	LCR_PR(XS);
+	LCR_PR(XCKHW);
+	LCR_PR(STHS);
+	LCR_PR(VT2);
+	LCR_PR(YCKSW);
+	LCR_PR(YSTS);
+	LCR_PR(PPOLS);
+	LCR_PR(PRECW);
+	LCR_PR(VCLKHW);
+	LCR_PR(OC);
+#undef LCR_PR
+}
+#endif
+
+#ifdef CONFIG_PM
+static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+#ifdef CONFIG_FB_TMIO_ACCELL
+	struct tmiofb_par *par = info->par;
+#endif
+	const struct mfd_cell *cell = mfd_get_cell(dev);
+	int retval = 0;
+
+	console_lock();
+
+	fb_set_suspend(info, 1);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+	/*
+	 * The fb should be usable even if interrupts are disabled (and they are
+	 * during suspend/resume). Switch temporary to forced polling.
+	 */
+	printk(KERN_INFO "tmiofb: switching to polling\n");
+	par->use_polling = true;
+#endif
+	tmiofb_hw_stop(dev);
+
+	if (cell->suspend)
+		retval = cell->suspend(dev);
+
+	console_unlock();
+
+	return retval;
+}
+
+static int tmiofb_resume(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	const struct mfd_cell *cell = mfd_get_cell(dev);
+	int retval = 0;
+
+	console_lock();
+
+	if (cell->resume) {
+		retval = cell->resume(dev);
+		if (retval)
+			goto out;
+	}
+
+	tmiofb_irq(-1, info);
+
+	tmiofb_hw_init(dev);
+
+	tmiofb_hw_mode(dev);
+
+	fb_set_suspend(info, 0);
+out:
+	console_unlock();
+	return retval;
+}
+#else
+#define tmiofb_suspend	NULL
+#define tmiofb_resume	NULL
+#endif
+
+static struct platform_driver tmiofb_driver = {
+	.driver.name	= "tmio-fb",
+	.driver.owner	= THIS_MODULE,
+	.probe		= tmiofb_probe,
+	.remove		= tmiofb_remove,
+	.suspend	= tmiofb_suspend,
+	.resume		= tmiofb_resume,
+};
+
+/*--------------------------------------------------------------------------*/
+
+#ifndef MODULE
+static void __init tmiofb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		/*
+		 * FIXME
+		 */
+	}
+}
+#endif
+
+static int __init tmiofb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tmiofb", &option))
+		return -ENODEV;
+	tmiofb_setup(option);
+#endif
+	return platform_driver_register(&tmiofb_driver);
+}
+
+static void __exit tmiofb_cleanup(void)
+{
+	platform_driver_unregister(&tmiofb_driver);
+}
+
+module_init(tmiofb_init);
+module_exit(tmiofb_cleanup);
+
+MODULE_DESCRIPTION("TMIO framebuffer driver");
+MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/tridentfb.c b/drivers/video/fbdev/tridentfb.c
new file mode 100644
index 000000000000..7ed9a227f5ea
--- /dev/null
+++ b/drivers/video/fbdev/tridentfb.c
@@ -0,0 +1,1659 @@
+/*
+ * Frame buffer driver for Trident TGUI, Blade and Image series
+ *
+ * Copyright 2001, 2002 - Jani Monoses   <jani@iv.ro>
+ * Copyright 2009 Krzysztof Helt <krzysztof.h1@wp.pl>
+ *
+ * CREDITS:(in order of appearance)
+ *	skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video
+ *	Special thanks ;) to Mattia Crivellini <tia@mclink.it>
+ *	much inspired by the XFree86 4.x Trident driver sources
+ *	by Alan Hourihane the FreeVGA project
+ *	Francesco Salvestrini <salvestrini@users.sf.net> XP support,
+ *	code, suggestions
+ * TODO:
+ *	timing value tweaking so it looks good on every monitor in every mode
+ */
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <linux/delay.h>
+#include <video/vga.h>
+#include <video/trident.h>
+
+struct tridentfb_par {
+	void __iomem *io_virt;	/* iospace virtual memory address */
+	u32 pseudo_pal[16];
+	int chip_id;
+	int flatpanel;
+	void (*init_accel) (struct tridentfb_par *, int, int);
+	void (*wait_engine) (struct tridentfb_par *);
+	void (*fill_rect)
+		(struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+	void (*copy_rect)
+		(struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+	void (*image_blit)
+		(struct tridentfb_par *par, const char*,
+		 u32, u32, u32, u32, u32, u32);
+	unsigned char eng_oper;	/* engine operation... */
+};
+
+static struct fb_fix_screeninfo tridentfb_fix = {
+	.id = "Trident",
+	.type = FB_TYPE_PACKED_PIXELS,
+	.ypanstep = 1,
+	.visual = FB_VISUAL_PSEUDOCOLOR,
+	.accel = FB_ACCEL_NONE,
+};
+
+/* defaults which are normally overriden by user values */
+
+/* video mode */
+static char *mode_option = "640x480-8@60";
+static int bpp = 8;
+
+static int noaccel;
+
+static int center;
+static int stretch;
+
+static int fp;
+static int crt;
+
+static int memsize;
+static int memdiff;
+static int nativex;
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+module_param_named(mode, mode_option, charp, 0);
+MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8@60' (deprecated)");
+module_param(bpp, int, 0);
+module_param(center, int, 0);
+module_param(stretch, int, 0);
+module_param(noaccel, int, 0);
+module_param(memsize, int, 0);
+module_param(memdiff, int, 0);
+module_param(nativex, int, 0);
+module_param(fp, int, 0);
+MODULE_PARM_DESC(fp, "Define if flatpanel is connected");
+module_param(crt, int, 0);
+MODULE_PARM_DESC(crt, "Define if CRT is connected");
+
+static inline int is_oldclock(int id)
+{
+	return	(id == TGUI9440) ||
+		(id == TGUI9660) ||
+		(id == CYBER9320);
+}
+
+static inline int is_oldprotect(int id)
+{
+	return	is_oldclock(id) ||
+		(id == PROVIDIA9685) ||
+		(id == CYBER9382) ||
+		(id == CYBER9385);
+}
+
+static inline int is_blade(int id)
+{
+	return	(id == BLADE3D) ||
+		(id == CYBERBLADEE4) ||
+		(id == CYBERBLADEi7) ||
+		(id == CYBERBLADEi7D) ||
+		(id == CYBERBLADEi1) ||
+		(id == CYBERBLADEi1D) ||
+		(id == CYBERBLADEAi1) ||
+		(id == CYBERBLADEAi1D);
+}
+
+static inline int is_xp(int id)
+{
+	return	(id == CYBERBLADEXPAi1) ||
+		(id == CYBERBLADEXPm8) ||
+		(id == CYBERBLADEXPm16);
+}
+
+static inline int is3Dchip(int id)
+{
+	return	is_blade(id) || is_xp(id) ||
+		(id == CYBER9397) || (id == CYBER9397DVD) ||
+		(id == CYBER9520) || (id == CYBER9525DVD) ||
+		(id == IMAGE975) || (id == IMAGE985);
+}
+
+static inline int iscyber(int id)
+{
+	switch (id) {
+	case CYBER9388:
+	case CYBER9382:
+	case CYBER9385:
+	case CYBER9397:
+	case CYBER9397DVD:
+	case CYBER9520:
+	case CYBER9525DVD:
+	case CYBERBLADEE4:
+	case CYBERBLADEi7D:
+	case CYBERBLADEi1:
+	case CYBERBLADEi1D:
+	case CYBERBLADEAi1:
+	case CYBERBLADEAi1D:
+	case CYBERBLADEXPAi1:
+		return 1;
+
+	case CYBER9320:
+	case CYBERBLADEi7:	/* VIA MPV4 integrated version */
+	default:
+		/* case CYBERBLDAEXPm8:  Strange */
+		/* case CYBERBLDAEXPm16: Strange */
+		return 0;
+	}
+}
+
+static inline void t_outb(struct tridentfb_par *p, u8 val, u16 reg)
+{
+	fb_writeb(val, p->io_virt + reg);
+}
+
+static inline u8 t_inb(struct tridentfb_par *p, u16 reg)
+{
+	return fb_readb(p->io_virt + reg);
+}
+
+static inline void writemmr(struct tridentfb_par *par, u16 r, u32 v)
+{
+	fb_writel(v, par->io_virt + r);
+}
+
+static inline u32 readmmr(struct tridentfb_par *par, u16 r)
+{
+	return fb_readl(par->io_virt + r);
+}
+
+/*
+ * Blade specific acceleration.
+ */
+
+#define point(x, y) ((y) << 16 | (x))
+
+static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp)
+{
+	int v1 = (pitch >> 3) << 20;
+	int tmp = bpp == 24 ? 2 : (bpp >> 4);
+	int v2 = v1 | (tmp << 29);
+
+	writemmr(par, 0x21C0, v2);
+	writemmr(par, 0x21C4, v2);
+	writemmr(par, 0x21B8, v2);
+	writemmr(par, 0x21BC, v2);
+	writemmr(par, 0x21D0, v1);
+	writemmr(par, 0x21D4, v1);
+	writemmr(par, 0x21C8, v1);
+	writemmr(par, 0x21CC, v1);
+	writemmr(par, 0x216C, 0);
+}
+
+static void blade_wait_engine(struct tridentfb_par *par)
+{
+	while (readmmr(par, STATUS) & 0xFA800000)
+		cpu_relax();
+}
+
+static void blade_fill_rect(struct tridentfb_par *par,
+			    u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+{
+	writemmr(par, COLOR, c);
+	writemmr(par, ROP, rop ? ROP_X : ROP_S);
+	writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+
+	writemmr(par, DST1, point(x, y));
+	writemmr(par, DST2, point(x + w - 1, y + h - 1));
+}
+
+static void blade_image_blit(struct tridentfb_par *par, const char *data,
+			     u32 x, u32 y, u32 w, u32 h, u32 c, u32 b)
+{
+	unsigned size = ((w + 31) >> 5) * h;
+
+	writemmr(par, COLOR, c);
+	writemmr(par, BGCOLOR, b);
+	writemmr(par, CMD, 0xa0000000 | 3 << 19);
+
+	writemmr(par, DST1, point(x, y));
+	writemmr(par, DST2, point(x + w - 1, y + h - 1));
+
+	memcpy(par->io_virt + 0x10000, data, 4 * size);
+}
+
+static void blade_copy_rect(struct tridentfb_par *par,
+			    u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+{
+	int direction = 2;
+	u32 s1 = point(x1, y1);
+	u32 s2 = point(x1 + w - 1, y1 + h - 1);
+	u32 d1 = point(x2, y2);
+	u32 d2 = point(x2 + w - 1, y2 + h - 1);
+
+	if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
+		direction = 0;
+
+	writemmr(par, ROP, ROP_S);
+	writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
+
+	writemmr(par, SRC1, direction ? s2 : s1);
+	writemmr(par, SRC2, direction ? s1 : s2);
+	writemmr(par, DST1, direction ? d2 : d1);
+	writemmr(par, DST2, direction ? d1 : d2);
+}
+
+/*
+ * BladeXP specific acceleration functions
+ */
+
+static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp)
+{
+	unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+	int v1 = pitch << (bpp == 24 ? 20 : (18 + x));
+
+	switch (pitch << (bpp >> 3)) {
+	case 8192:
+	case 512:
+		x |= 0x00;
+		break;
+	case 1024:
+		x |= 0x04;
+		break;
+	case 2048:
+		x |= 0x08;
+		break;
+	case 4096:
+		x |= 0x0C;
+		break;
+	}
+
+	t_outb(par, x, 0x2125);
+
+	par->eng_oper = x | 0x40;
+
+	writemmr(par, 0x2154, v1);
+	writemmr(par, 0x2150, v1);
+	t_outb(par, 3, 0x2126);
+}
+
+static void xp_wait_engine(struct tridentfb_par *par)
+{
+	int count = 0;
+	int timeout = 0;
+
+	while (t_inb(par, STATUS) & 0x80) {
+		count++;
+		if (count == 10000000) {
+			/* Timeout */
+			count = 9990000;
+			timeout++;
+			if (timeout == 8) {
+				/* Reset engine */
+				t_outb(par, 0x00, STATUS);
+				return;
+			}
+		}
+		cpu_relax();
+	}
+}
+
+static void xp_fill_rect(struct tridentfb_par *par,
+			 u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+{
+	writemmr(par, 0x2127, ROP_P);
+	writemmr(par, 0x2158, c);
+	writemmr(par, DRAWFL, 0x4000);
+	writemmr(par, OLDDIM, point(h, w));
+	writemmr(par, OLDDST, point(y, x));
+	t_outb(par, 0x01, OLDCMD);
+	t_outb(par, par->eng_oper, 0x2125);
+}
+
+static void xp_copy_rect(struct tridentfb_par *par,
+			 u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+{
+	u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
+	int direction = 0x0004;
+
+	if ((x1 < x2) && (y1 == y2)) {
+		direction |= 0x0200;
+		x1_tmp = x1 + w - 1;
+		x2_tmp = x2 + w - 1;
+	} else {
+		x1_tmp = x1;
+		x2_tmp = x2;
+	}
+
+	if (y1 < y2) {
+		direction |= 0x0100;
+		y1_tmp = y1 + h - 1;
+		y2_tmp = y2 + h - 1;
+	} else {
+		y1_tmp = y1;
+		y2_tmp = y2;
+	}
+
+	writemmr(par, DRAWFL, direction);
+	t_outb(par, ROP_S, 0x2127);
+	writemmr(par, OLDSRC, point(y1_tmp, x1_tmp));
+	writemmr(par, OLDDST, point(y2_tmp, x2_tmp));
+	writemmr(par, OLDDIM, point(h, w));
+	t_outb(par, 0x01, OLDCMD);
+}
+
+/*
+ * Image specific acceleration functions
+ */
+static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp)
+{
+	int tmp = bpp == 24 ? 2: (bpp >> 4);
+
+	writemmr(par, 0x2120, 0xF0000000);
+	writemmr(par, 0x2120, 0x40000000 | tmp);
+	writemmr(par, 0x2120, 0x80000000);
+	writemmr(par, 0x2144, 0x00000000);
+	writemmr(par, 0x2148, 0x00000000);
+	writemmr(par, 0x2150, 0x00000000);
+	writemmr(par, 0x2154, 0x00000000);
+	writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch);
+	writemmr(par, 0x216C, 0x00000000);
+	writemmr(par, 0x2170, 0x00000000);
+	writemmr(par, 0x217C, 0x00000000);
+	writemmr(par, 0x2120, 0x10000000);
+	writemmr(par, 0x2130, (2047 << 16) | 2047);
+}
+
+static void image_wait_engine(struct tridentfb_par *par)
+{
+	while (readmmr(par, 0x2164) & 0xF0000000)
+		cpu_relax();
+}
+
+static void image_fill_rect(struct tridentfb_par *par,
+			    u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+{
+	writemmr(par, 0x2120, 0x80000000);
+	writemmr(par, 0x2120, 0x90000000 | ROP_S);
+
+	writemmr(par, 0x2144, c);
+
+	writemmr(par, DST1, point(x, y));
+	writemmr(par, DST2, point(x + w - 1, y + h - 1));
+
+	writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
+}
+
+static void image_copy_rect(struct tridentfb_par *par,
+			    u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+{
+	int direction = 0x4;
+	u32 s1 = point(x1, y1);
+	u32 s2 = point(x1 + w - 1, y1 + h - 1);
+	u32 d1 = point(x2, y2);
+	u32 d2 = point(x2 + w - 1, y2 + h - 1);
+
+	if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
+		direction = 0;
+
+	writemmr(par, 0x2120, 0x80000000);
+	writemmr(par, 0x2120, 0x90000000 | ROP_S);
+
+	writemmr(par, SRC1, direction ? s2 : s1);
+	writemmr(par, SRC2, direction ? s1 : s2);
+	writemmr(par, DST1, direction ? d2 : d1);
+	writemmr(par, DST2, direction ? d1 : d2);
+	writemmr(par, 0x2124,
+		 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
+}
+
+/*
+ * TGUI 9440/96XX acceleration
+ */
+
+static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp)
+{
+	unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+
+	/* disable clipping */
+	writemmr(par, 0x2148, 0);
+	writemmr(par, 0x214C, point(4095, 2047));
+
+	switch ((pitch * bpp) / 8) {
+	case 8192:
+	case 512:
+		x |= 0x00;
+		break;
+	case 1024:
+		x |= 0x04;
+		break;
+	case 2048:
+		x |= 0x08;
+		break;
+	case 4096:
+		x |= 0x0C;
+		break;
+	}
+
+	fb_writew(x, par->io_virt + 0x2122);
+}
+
+static void tgui_fill_rect(struct tridentfb_par *par,
+			   u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+{
+	t_outb(par, ROP_P, 0x2127);
+	writemmr(par, OLDCLR, c);
+	writemmr(par, DRAWFL, 0x4020);
+	writemmr(par, OLDDIM, point(w - 1, h - 1));
+	writemmr(par, OLDDST, point(x, y));
+	t_outb(par, 1, OLDCMD);
+}
+
+static void tgui_copy_rect(struct tridentfb_par *par,
+			   u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+{
+	int flags = 0;
+	u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
+
+	if ((x1 < x2) && (y1 == y2)) {
+		flags |= 0x0200;
+		x1_tmp = x1 + w - 1;
+		x2_tmp = x2 + w - 1;
+	} else {
+		x1_tmp = x1;
+		x2_tmp = x2;
+	}
+
+	if (y1 < y2) {
+		flags |= 0x0100;
+		y1_tmp = y1 + h - 1;
+		y2_tmp = y2 + h - 1;
+	} else {
+		y1_tmp = y1;
+		y2_tmp = y2;
+	}
+
+	writemmr(par, DRAWFL, 0x4 | flags);
+	t_outb(par, ROP_S, 0x2127);
+	writemmr(par, OLDSRC, point(x1_tmp, y1_tmp));
+	writemmr(par, OLDDST, point(x2_tmp, y2_tmp));
+	writemmr(par, OLDDIM, point(w - 1, h - 1));
+	t_outb(par, 1, OLDCMD);
+}
+
+/*
+ * Accel functions called by the upper layers
+ */
+static void tridentfb_fillrect(struct fb_info *info,
+			       const struct fb_fillrect *fr)
+{
+	struct tridentfb_par *par = info->par;
+	int col;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(info, fr);
+		return;
+	}
+	if (info->var.bits_per_pixel == 8) {
+		col = fr->color;
+		col |= col << 8;
+		col |= col << 16;
+	} else
+		col = ((u32 *)(info->pseudo_palette))[fr->color];
+
+	par->wait_engine(par);
+	par->fill_rect(par, fr->dx, fr->dy, fr->width,
+		       fr->height, col, fr->rop);
+}
+
+static void tridentfb_imageblit(struct fb_info *info,
+				const struct fb_image *img)
+{
+	struct tridentfb_par *par = info->par;
+	int col, bgcol;
+
+	if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) {
+		cfb_imageblit(info, img);
+		return;
+	}
+	if (info->var.bits_per_pixel == 8) {
+		col = img->fg_color;
+		col |= col << 8;
+		col |= col << 16;
+		bgcol = img->bg_color;
+		bgcol |= bgcol << 8;
+		bgcol |= bgcol << 16;
+	} else {
+		col = ((u32 *)(info->pseudo_palette))[img->fg_color];
+		bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color];
+	}
+
+	par->wait_engine(par);
+	if (par->image_blit)
+		par->image_blit(par, img->data, img->dx, img->dy,
+				img->width, img->height, col, bgcol);
+	else
+		cfb_imageblit(info, img);
+}
+
+static void tridentfb_copyarea(struct fb_info *info,
+			       const struct fb_copyarea *ca)
+{
+	struct tridentfb_par *par = info->par;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, ca);
+		return;
+	}
+	par->wait_engine(par);
+	par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy,
+		       ca->width, ca->height);
+}
+
+static int tridentfb_sync(struct fb_info *info)
+{
+	struct tridentfb_par *par = info->par;
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+		par->wait_engine(par);
+	return 0;
+}
+
+/*
+ * Hardware access functions
+ */
+
+static inline unsigned char read3X4(struct tridentfb_par *par, int reg)
+{
+	return vga_mm_rcrt(par->io_virt, reg);
+}
+
+static inline void write3X4(struct tridentfb_par *par, int reg,
+			    unsigned char val)
+{
+	vga_mm_wcrt(par->io_virt, reg, val);
+}
+
+static inline unsigned char read3CE(struct tridentfb_par *par,
+				    unsigned char reg)
+{
+	return vga_mm_rgfx(par->io_virt, reg);
+}
+
+static inline void writeAttr(struct tridentfb_par *par, int reg,
+			     unsigned char val)
+{
+	fb_readb(par->io_virt + VGA_IS1_RC);	/* flip-flop to index */
+	vga_mm_wattr(par->io_virt, reg, val);
+}
+
+static inline void write3CE(struct tridentfb_par *par, int reg,
+			    unsigned char val)
+{
+	vga_mm_wgfx(par->io_virt, reg, val);
+}
+
+static void enable_mmio(struct tridentfb_par *par)
+{
+	/* Goto New Mode */
+	vga_io_rseq(0x0B);
+
+	/* Unprotect registers */
+	vga_io_wseq(NewMode1, 0x80);
+	if (!is_oldprotect(par->chip_id))
+		vga_io_wseq(Protection, 0x92);
+
+	/* Enable MMIO */
+	outb(PCIReg, 0x3D4);
+	outb(inb(0x3D5) | 0x01, 0x3D5);
+}
+
+static void disable_mmio(struct tridentfb_par *par)
+{
+	/* Goto New Mode */
+	vga_mm_rseq(par->io_virt, 0x0B);
+
+	/* Unprotect registers */
+	vga_mm_wseq(par->io_virt, NewMode1, 0x80);
+	if (!is_oldprotect(par->chip_id))
+		vga_mm_wseq(par->io_virt, Protection, 0x92);
+
+	/* Disable MMIO */
+	t_outb(par, PCIReg, 0x3D4);
+	t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);
+}
+
+static inline void crtc_unlock(struct tridentfb_par *par)
+{
+	write3X4(par, VGA_CRTC_V_SYNC_END,
+		 read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F);
+}
+
+/*  Return flat panel's maximum x resolution */
+static int get_nativex(struct tridentfb_par *par)
+{
+	int x, y, tmp;
+
+	if (nativex)
+		return nativex;
+
+	tmp = (read3CE(par, VertStretch) >> 4) & 3;
+
+	switch (tmp) {
+	case 0:
+		x = 1280; y = 1024;
+		break;
+	case 2:
+		x = 1024; y = 768;
+		break;
+	case 3:
+		x = 800; y = 600;
+		break;
+	case 4:
+		x = 1400; y = 1050;
+		break;
+	case 1:
+	default:
+		x = 640;  y = 480;
+		break;
+	}
+
+	output("%dx%d flat panel found\n", x, y);
+	return x;
+}
+
+/* Set pitch */
+static inline void set_lwidth(struct tridentfb_par *par, int width)
+{
+	write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);
+	write3X4(par, AddColReg,
+		 (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
+}
+
+/* For resolutions smaller than FP resolution stretch */
+static void screen_stretch(struct tridentfb_par *par)
+{
+	if (par->chip_id != CYBERBLADEXPAi1)
+		write3CE(par, BiosReg, 0);
+	else
+		write3CE(par, BiosReg, 8);
+	write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1);
+	write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1);
+}
+
+/* For resolutions smaller than FP resolution center */
+static inline void screen_center(struct tridentfb_par *par)
+{
+	write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80);
+	write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80);
+}
+
+/* Address of first shown pixel in display memory */
+static void set_screen_start(struct tridentfb_par *par, int base)
+{
+	u8 tmp;
+	write3X4(par, VGA_CRTC_START_LO, base & 0xFF);
+	write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8);
+	tmp = read3X4(par, CRTCModuleTest) & 0xDF;
+	write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11));
+	tmp = read3X4(par, CRTHiOrd) & 0xF8;
+	write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17));
+}
+
+/* Set dotclock frequency */
+static void set_vclk(struct tridentfb_par *par, unsigned long freq)
+{
+	int m, n, k;
+	unsigned long fi, d, di;
+	unsigned char best_m = 0, best_n = 0, best_k = 0;
+	unsigned char hi, lo;
+	unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1;
+
+	d = 20000;
+	for (k = shift; k >= 0; k--)
+		for (m = 1; m < 32; m++) {
+			n = ((m + 2) << shift) - 8;
+			for (n = (n < 0 ? 0 : n); n < 122; n++) {
+				fi = ((14318l * (n + 8)) / (m + 2)) >> k;
+				di = abs(fi - freq);
+				if (di < d || (di == d && k == best_k)) {
+					d = di;
+					best_n = n;
+					best_m = m;
+					best_k = k;
+				}
+				if (fi > freq)
+					break;
+			}
+		}
+
+	if (is_oldclock(par->chip_id)) {
+		lo = best_n | (best_m << 7);
+		hi = (best_m >> 1) | (best_k << 4);
+	} else {
+		lo = best_n;
+		hi = best_m | (best_k << 6);
+	}
+
+	if (is3Dchip(par->chip_id)) {
+		vga_mm_wseq(par->io_virt, ClockHigh, hi);
+		vga_mm_wseq(par->io_virt, ClockLow, lo);
+	} else {
+		t_outb(par, lo, 0x43C8);
+		t_outb(par, hi, 0x43C9);
+	}
+	debug("VCLK = %X %X\n", hi, lo);
+}
+
+/* Set number of lines for flat panels*/
+static void set_number_of_lines(struct tridentfb_par *par, int lines)
+{
+	int tmp = read3CE(par, CyberEnhance) & 0x8F;
+	if (lines > 1024)
+		tmp |= 0x50;
+	else if (lines > 768)
+		tmp |= 0x30;
+	else if (lines > 600)
+		tmp |= 0x20;
+	else if (lines > 480)
+		tmp |= 0x10;
+	write3CE(par, CyberEnhance, tmp);
+}
+
+/*
+ * If we see that FP is active we assume we have one.
+ * Otherwise we have a CRT display. User can override.
+ */
+static int is_flatpanel(struct tridentfb_par *par)
+{
+	if (fp)
+		return 1;
+	if (crt || !iscyber(par->chip_id))
+		return 0;
+	return (read3CE(par, FPConfig) & 0x10) ? 1 : 0;
+}
+
+/* Try detecting the video memory size */
+static unsigned int get_memsize(struct tridentfb_par *par)
+{
+	unsigned char tmp, tmp2;
+	unsigned int k;
+
+	/* If memory size provided by user */
+	if (memsize)
+		k = memsize * Kb;
+	else
+		switch (par->chip_id) {
+		case CYBER9525DVD:
+			k = 2560 * Kb;
+			break;
+		default:
+			tmp = read3X4(par, SPR) & 0x0F;
+			switch (tmp) {
+
+			case 0x01:
+				k = 512 * Kb;
+				break;
+			case 0x02:
+				k = 6 * Mb;	/* XP */
+				break;
+			case 0x03:
+				k = 1 * Mb;
+				break;
+			case 0x04:
+				k = 8 * Mb;
+				break;
+			case 0x06:
+				k = 10 * Mb;	/* XP */
+				break;
+			case 0x07:
+				k = 2 * Mb;
+				break;
+			case 0x08:
+				k = 12 * Mb;	/* XP */
+				break;
+			case 0x0A:
+				k = 14 * Mb;	/* XP */
+				break;
+			case 0x0C:
+				k = 16 * Mb;	/* XP */
+				break;
+			case 0x0E:		/* XP */
+
+				tmp2 = vga_mm_rseq(par->io_virt, 0xC1);
+				switch (tmp2) {
+				case 0x00:
+					k = 20 * Mb;
+					break;
+				case 0x01:
+					k = 24 * Mb;
+					break;
+				case 0x10:
+					k = 28 * Mb;
+					break;
+				case 0x11:
+					k = 32 * Mb;
+					break;
+				default:
+					k = 1 * Mb;
+					break;
+				}
+				break;
+
+			case 0x0F:
+				k = 4 * Mb;
+				break;
+			default:
+				k = 1 * Mb;
+				break;
+			}
+		}
+
+	k -= memdiff * Kb;
+	output("framebuffer size = %d Kb\n", k / Kb);
+	return k;
+}
+
+/* See if we can handle the video mode described in var */
+static int tridentfb_check_var(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	struct tridentfb_par *par = info->par;
+	int bpp = var->bits_per_pixel;
+	int line_length;
+	int ramdac = 230000; /* 230MHz for most 3D chips */
+	debug("enter\n");
+
+	/* check color depth */
+	if (bpp == 24)
+		bpp = var->bits_per_pixel = 32;
+	if (bpp != 8 && bpp != 16 && bpp != 32)
+		return -EINVAL;
+	if (par->chip_id == TGUI9440 && bpp == 32)
+		return -EINVAL;
+	/* check whether resolution fits on panel and in memory */
+	if (par->flatpanel && nativex && var->xres > nativex)
+		return -EINVAL;
+	/* various resolution checks */
+	var->xres = (var->xres + 7) & ~0x7;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->xres_virtual > 4095 || var->yres > 2048)
+		return -EINVAL;
+	/* prevent from position overflow for acceleration */
+	if (var->yres_virtual > 0xffff)
+		return -EINVAL;
+	line_length = var->xres_virtual * bpp / 8;
+
+	if (!is3Dchip(par->chip_id) &&
+	    !(info->flags & FBINFO_HWACCEL_DISABLED)) {
+		/* acceleration requires line length to be power of 2 */
+		if (line_length <= 512)
+			var->xres_virtual = 512 * 8 / bpp;
+		else if (line_length <= 1024)
+			var->xres_virtual = 1024 * 8 / bpp;
+		else if (line_length <= 2048)
+			var->xres_virtual = 2048 * 8 / bpp;
+		else if (line_length <= 4096)
+			var->xres_virtual = 4096 * 8 / bpp;
+		else if (line_length <= 8192)
+			var->xres_virtual = 8192 * 8 / bpp;
+		else
+			return -EINVAL;
+
+		line_length = var->xres_virtual * bpp / 8;
+	}
+
+	/* datasheet specifies how to set panning only up to 4 MB */
+	if (line_length * (var->yres_virtual - var->yres) > (4 << 20))
+		var->yres_virtual = ((4 << 20) / line_length) + var->yres;
+
+	if (line_length * var->yres_virtual > info->fix.smem_len)
+		return -EINVAL;
+
+	switch (bpp) {
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green = var->red;
+		var->blue = var->red;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (is_xp(par->chip_id))
+		ramdac = 350000;
+
+	switch (par->chip_id) {
+	case TGUI9440:
+		ramdac = (bpp >= 16) ? 45000 : 90000;
+		break;
+	case CYBER9320:
+	case TGUI9660:
+		ramdac = 135000;
+		break;
+	case PROVIDIA9685:
+	case CYBER9388:
+	case CYBER9382:
+	case CYBER9385:
+		ramdac = 170000;
+		break;
+	}
+
+	/* The clock is doubled for 32 bpp */
+	if (bpp == 32)
+		ramdac /= 2;
+
+	if (PICOS2KHZ(var->pixclock) > ramdac)
+		return -EINVAL;
+
+	debug("exit\n");
+
+	return 0;
+
+}
+
+/* Pan the display */
+static int tridentfb_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	struct tridentfb_par *par = info->par;
+	unsigned int offset;
+
+	debug("enter\n");
+	offset = (var->xoffset + (var->yoffset * info->var.xres_virtual))
+		* info->var.bits_per_pixel / 32;
+	set_screen_start(par, offset);
+	debug("exit\n");
+	return 0;
+}
+
+static inline void shadowmode_on(struct tridentfb_par *par)
+{
+	write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81);
+}
+
+static inline void shadowmode_off(struct tridentfb_par *par)
+{
+	write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E);
+}
+
+/* Set the hardware to the requested video mode */
+static int tridentfb_set_par(struct fb_info *info)
+{
+	struct tridentfb_par *par = info->par;
+	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
+	u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
+	struct fb_var_screeninfo *var = &info->var;
+	int bpp = var->bits_per_pixel;
+	unsigned char tmp;
+	unsigned long vclk;
+
+	debug("enter\n");
+	hdispend = var->xres / 8 - 1;
+	hsyncstart = (var->xres + var->right_margin) / 8;
+	hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;
+	htotal = (var->xres + var->left_margin + var->right_margin +
+		  var->hsync_len) / 8 - 5;
+	hblankstart = hdispend + 1;
+	hblankend = htotal + 3;
+
+	vdispend = var->yres - 1;
+	vsyncstart = var->yres + var->lower_margin;
+	vsyncend = vsyncstart + var->vsync_len;
+	vtotal = var->upper_margin + vsyncend - 2;
+	vblankstart = vdispend + 1;
+	vblankend = vtotal;
+
+	if (info->var.vmode & FB_VMODE_INTERLACED) {
+		vtotal /= 2;
+		vdispend /= 2;
+		vsyncstart /= 2;
+		vsyncend /= 2;
+		vblankstart /= 2;
+		vblankend /= 2;
+	}
+
+	enable_mmio(par);
+	crtc_unlock(par);
+	write3CE(par, CyberControl, 8);
+	tmp = 0xEB;
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		tmp &= ~0x40;
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		tmp &= ~0x80;
+
+	if (par->flatpanel && var->xres < nativex) {
+		/*
+		 * on flat panels with native size larger
+		 * than requested resolution decide whether
+		 * we stretch or center
+		 */
+		t_outb(par, tmp | 0xC0, VGA_MIS_W);
+
+		shadowmode_on(par);
+
+		if (center)
+			screen_center(par);
+		else if (stretch)
+			screen_stretch(par);
+
+	} else {
+		t_outb(par, tmp, VGA_MIS_W);
+		write3CE(par, CyberControl, 8);
+	}
+
+	/* vertical timing values */
+	write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF);
+	write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF);
+	write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF);
+	write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F));
+	write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF);
+	write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF);
+
+	/* horizontal timing values */
+	write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF);
+	write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF);
+	write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF);
+	write3X4(par, VGA_CRTC_H_SYNC_END,
+		 (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
+	write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF);
+	write3X4(par, VGA_CRTC_H_BLANK_END, hblankend & 0x1F);
+
+	/* higher bits of vertical timing values */
+	tmp = 0x10;
+	if (vtotal & 0x100) tmp |= 0x01;
+	if (vdispend & 0x100) tmp |= 0x02;
+	if (vsyncstart & 0x100) tmp |= 0x04;
+	if (vblankstart & 0x100) tmp |= 0x08;
+
+	if (vtotal & 0x200) tmp |= 0x20;
+	if (vdispend & 0x200) tmp |= 0x40;
+	if (vsyncstart & 0x200) tmp |= 0x80;
+	write3X4(par, VGA_CRTC_OVERFLOW, tmp);
+
+	tmp = read3X4(par, CRTHiOrd) & 0x07;
+	tmp |= 0x08;	/* line compare bit 10 */
+	if (vtotal & 0x400) tmp |= 0x80;
+	if (vblankstart & 0x400) tmp |= 0x40;
+	if (vsyncstart & 0x400) tmp |= 0x20;
+	if (vdispend & 0x400) tmp |= 0x10;
+	write3X4(par, CRTHiOrd, tmp);
+
+	tmp = (htotal >> 8) & 0x01;
+	tmp |= (hdispend >> 7) & 0x02;
+	tmp |= (hsyncstart >> 5) & 0x08;
+	tmp |= (hblankstart >> 4) & 0x10;
+	write3X4(par, HorizOverflow, tmp);
+
+	tmp = 0x40;
+	if (vblankstart & 0x200) tmp |= 0x20;
+//FIXME	if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80;  /* double scan for 200 line modes */
+	write3X4(par, VGA_CRTC_MAX_SCAN, tmp);
+
+	write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF);
+	write3X4(par, VGA_CRTC_PRESET_ROW, 0);
+	write3X4(par, VGA_CRTC_MODE, 0xC3);
+
+	write3X4(par, LinearAddReg, 0x20);	/* enable linear addressing */
+
+	tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
+	/* enable access extended memory */
+	write3X4(par, CRTCModuleTest, tmp);
+	tmp = read3CE(par, MiscIntContReg) & ~0x4;
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		tmp |= 0x4;
+	write3CE(par, MiscIntContReg, tmp);
+
+	/* enable GE for text acceleration */
+	write3X4(par, GraphEngReg, 0x80);
+
+	switch (bpp) {
+	case 8:
+		tmp = 0x00;
+		break;
+	case 16:
+		tmp = 0x05;
+		break;
+	case 24:
+		tmp = 0x29;
+		break;
+	case 32:
+		tmp = 0x09;
+		break;
+	}
+
+	write3X4(par, PixelBusReg, tmp);
+
+	tmp = read3X4(par, DRAMControl);
+	if (!is_oldprotect(par->chip_id))
+		tmp |= 0x10;
+	if (iscyber(par->chip_id))
+		tmp |= 0x20;
+	write3X4(par, DRAMControl, tmp);	/* both IO, linear enable */
+
+	write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40);
+	if (!is_xp(par->chip_id))
+		write3X4(par, Performance, read3X4(par, Performance) | 0x10);
+	/* MMIO & PCI read and write burst enable */
+	if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975)
+		write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06);
+
+	vga_mm_wseq(par->io_virt, 0, 3);
+	vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */
+	/* enable 4 maps because needed in chain4 mode */
+	vga_mm_wseq(par->io_virt, 2, 0x0F);
+	vga_mm_wseq(par->io_virt, 3, 0);
+	vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */
+
+	/* convert from picoseconds to kHz */
+	vclk = PICOS2KHZ(info->var.pixclock);
+
+	/* divide clock by 2 if 32bpp chain4 mode display and CPU path */
+	tmp = read3CE(par, MiscExtFunc) & 0xF0;
+	if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) {
+		tmp |= 8;
+		vclk *= 2;
+	}
+	set_vclk(par, vclk);
+	write3CE(par, MiscExtFunc, tmp | 0x12);
+	write3CE(par, 0x5, 0x40);	/* no CGA compat, allow 256 col */
+	write3CE(par, 0x6, 0x05);	/* graphics mode */
+	write3CE(par, 0x7, 0x0F);	/* planes? */
+
+	/* graphics mode and support 256 color modes */
+	writeAttr(par, 0x10, 0x41);
+	writeAttr(par, 0x12, 0x0F);	/* planes */
+	writeAttr(par, 0x13, 0);	/* horizontal pel panning */
+
+	/* colors */
+	for (tmp = 0; tmp < 0x10; tmp++)
+		writeAttr(par, tmp, tmp);
+	fb_readb(par->io_virt + VGA_IS1_RC);	/* flip-flop to index */
+	t_outb(par, 0x20, VGA_ATT_W);		/* enable attr */
+
+	switch (bpp) {
+	case 8:
+		tmp = 0;
+		break;
+	case 16:
+		tmp = 0x30;
+		break;
+	case 24:
+	case 32:
+		tmp = 0xD0;
+		break;
+	}
+
+	t_inb(par, VGA_PEL_IW);
+	t_inb(par, VGA_PEL_MSK);
+	t_inb(par, VGA_PEL_MSK);
+	t_inb(par, VGA_PEL_MSK);
+	t_inb(par, VGA_PEL_MSK);
+	t_outb(par, tmp, VGA_PEL_MSK);
+	t_inb(par, VGA_PEL_IW);
+
+	if (par->flatpanel)
+		set_number_of_lines(par, info->var.yres);
+	info->fix.line_length = info->var.xres_virtual * bpp / 8;
+	set_lwidth(par, info->fix.line_length / 8);
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+		par->init_accel(par, info->var.xres_virtual, bpp);
+
+	info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->cmap.len = (bpp == 8) ? 256 : 16;
+	debug("exit\n");
+	return 0;
+}
+
+/* Set one color register */
+static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			       unsigned blue, unsigned transp,
+			       struct fb_info *info)
+{
+	int bpp = info->var.bits_per_pixel;
+	struct tridentfb_par *par = info->par;
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	if (bpp == 8) {
+		t_outb(par, 0xFF, VGA_PEL_MSK);
+		t_outb(par, regno, VGA_PEL_IW);
+
+		t_outb(par, red >> 10, VGA_PEL_D);
+		t_outb(par, green >> 10, VGA_PEL_D);
+		t_outb(par, blue >> 10, VGA_PEL_D);
+
+	} else if (regno < 16) {
+		if (bpp == 16) {	/* RGB 565 */
+			u32 col;
+
+			col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
+				((blue & 0xF800) >> 11);
+			col |= col << 16;
+			((u32 *)(info->pseudo_palette))[regno] = col;
+		} else if (bpp == 32)		/* ARGB 8888 */
+			((u32 *)info->pseudo_palette)[regno] =
+				((transp & 0xFF00) << 16)	|
+				((red & 0xFF00) << 8)		|
+				((green & 0xFF00))		|
+				((blue & 0xFF00) >> 8);
+	}
+
+	return 0;
+}
+
+/* Try blanking the screen. For flat panels it does nothing */
+static int tridentfb_blank(int blank_mode, struct fb_info *info)
+{
+	unsigned char PMCont, DPMSCont;
+	struct tridentfb_par *par = info->par;
+
+	debug("enter\n");
+	if (par->flatpanel)
+		return 0;
+	t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */
+	PMCont = t_inb(par, 0x83C6) & 0xFC;
+	DPMSCont = read3CE(par, PowerStatus) & 0xFC;
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		/* Screen: On, HSync: On, VSync: On */
+	case FB_BLANK_NORMAL:
+		/* Screen: Off, HSync: On, VSync: On */
+		PMCont |= 0x03;
+		DPMSCont |= 0x00;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		/* Screen: Off, HSync: Off, VSync: On */
+		PMCont |= 0x02;
+		DPMSCont |= 0x01;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		/* Screen: Off, HSync: On, VSync: Off */
+		PMCont |= 0x02;
+		DPMSCont |= 0x02;
+		break;
+	case FB_BLANK_POWERDOWN:
+		/* Screen: Off, HSync: Off, VSync: Off */
+		PMCont |= 0x00;
+		DPMSCont |= 0x03;
+		break;
+	}
+
+	write3CE(par, PowerStatus, DPMSCont);
+	t_outb(par, 4, 0x83C8);
+	t_outb(par, PMCont, 0x83C6);
+
+	debug("exit\n");
+
+	/* let fbcon do a softblank for us */
+	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops tridentfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_setcolreg = tridentfb_setcolreg,
+	.fb_pan_display = tridentfb_pan_display,
+	.fb_blank = tridentfb_blank,
+	.fb_check_var = tridentfb_check_var,
+	.fb_set_par = tridentfb_set_par,
+	.fb_fillrect = tridentfb_fillrect,
+	.fb_copyarea = tridentfb_copyarea,
+	.fb_imageblit = tridentfb_imageblit,
+	.fb_sync = tridentfb_sync,
+};
+
+static int trident_pci_probe(struct pci_dev *dev,
+			     const struct pci_device_id *id)
+{
+	int err;
+	unsigned char revision;
+	struct fb_info *info;
+	struct tridentfb_par *default_par;
+	int chip3D;
+	int chip_id;
+
+	err = pci_enable_device(dev);
+	if (err)
+		return err;
+
+	info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev);
+	if (!info)
+		return -ENOMEM;
+	default_par = info->par;
+
+	chip_id = id->device;
+
+	/* If PCI id is 0x9660 then further detect chip type */
+
+	if (chip_id == TGUI9660) {
+		revision = vga_io_rseq(RevisionID);
+
+		switch (revision) {
+		case 0x21:
+			chip_id = PROVIDIA9685;
+			break;
+		case 0x22:
+		case 0x23:
+			chip_id = CYBER9397;
+			break;
+		case 0x2A:
+			chip_id = CYBER9397DVD;
+			break;
+		case 0x30:
+		case 0x33:
+		case 0x34:
+		case 0x35:
+		case 0x38:
+		case 0x3A:
+		case 0xB3:
+			chip_id = CYBER9385;
+			break;
+		case 0x40 ... 0x43:
+			chip_id = CYBER9382;
+			break;
+		case 0x4A:
+			chip_id = CYBER9388;
+			break;
+		default:
+			break;
+		}
+	}
+
+	chip3D = is3Dchip(chip_id);
+
+	if (is_xp(chip_id)) {
+		default_par->init_accel = xp_init_accel;
+		default_par->wait_engine = xp_wait_engine;
+		default_par->fill_rect = xp_fill_rect;
+		default_par->copy_rect = xp_copy_rect;
+		tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP;
+	} else if (is_blade(chip_id)) {
+		default_par->init_accel = blade_init_accel;
+		default_par->wait_engine = blade_wait_engine;
+		default_par->fill_rect = blade_fill_rect;
+		default_par->copy_rect = blade_copy_rect;
+		default_par->image_blit = blade_image_blit;
+		tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D;
+	} else if (chip3D) {			/* 3DImage family left */
+		default_par->init_accel = image_init_accel;
+		default_par->wait_engine = image_wait_engine;
+		default_par->fill_rect = image_fill_rect;
+		default_par->copy_rect = image_copy_rect;
+		tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE;
+	} else { 				/* TGUI 9440/96XX family */
+		default_par->init_accel = tgui_init_accel;
+		default_par->wait_engine = xp_wait_engine;
+		default_par->fill_rect = tgui_fill_rect;
+		default_par->copy_rect = tgui_copy_rect;
+		tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI;
+	}
+
+	default_par->chip_id = chip_id;
+
+	/* setup MMIO region */
+	tridentfb_fix.mmio_start = pci_resource_start(dev, 1);
+	tridentfb_fix.mmio_len = pci_resource_len(dev, 1);
+
+	if (!request_mem_region(tridentfb_fix.mmio_start,
+				tridentfb_fix.mmio_len, "tridentfb")) {
+		debug("request_region failed!\n");
+		framebuffer_release(info);
+		return -1;
+	}
+
+	default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start,
+					       tridentfb_fix.mmio_len);
+
+	if (!default_par->io_virt) {
+		debug("ioremap failed\n");
+		err = -1;
+		goto out_unmap1;
+	}
+
+	enable_mmio(default_par);
+
+	/* setup framebuffer memory */
+	tridentfb_fix.smem_start = pci_resource_start(dev, 0);
+	tridentfb_fix.smem_len = get_memsize(default_par);
+
+	if (!request_mem_region(tridentfb_fix.smem_start,
+				tridentfb_fix.smem_len, "tridentfb")) {
+		debug("request_mem_region failed!\n");
+		disable_mmio(info->par);
+		err = -1;
+		goto out_unmap1;
+	}
+
+	info->screen_base = ioremap_nocache(tridentfb_fix.smem_start,
+					    tridentfb_fix.smem_len);
+
+	if (!info->screen_base) {
+		debug("ioremap failed\n");
+		err = -1;
+		goto out_unmap2;
+	}
+
+	default_par->flatpanel = is_flatpanel(default_par);
+
+	if (default_par->flatpanel)
+		nativex = get_nativex(default_par);
+
+	info->fix = tridentfb_fix;
+	info->fbops = &tridentfb_ops;
+	info->pseudo_palette = default_par->pseudo_pal;
+
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	if (!noaccel && default_par->init_accel) {
+		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		info->flags |= FBINFO_HWACCEL_COPYAREA;
+		info->flags |= FBINFO_HWACCEL_FILLRECT;
+	} else
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+
+	if (is_blade(chip_id) && chip_id != BLADE3D)
+		info->flags |= FBINFO_READS_FAST;
+
+	info->pixmap.addr = kmalloc(4096, GFP_KERNEL);
+	if (!info->pixmap.addr) {
+		err = -ENOMEM;
+		goto out_unmap2;
+	}
+
+	info->pixmap.size = 4096;
+	info->pixmap.buf_align = 4;
+	info->pixmap.scan_align = 1;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if (default_par->image_blit) {
+		info->flags |= FBINFO_HWACCEL_IMAGEBLIT;
+		info->pixmap.scan_align = 4;
+	}
+
+	if (noaccel) {
+		printk(KERN_DEBUG "disabling acceleration\n");
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+		info->pixmap.scan_align = 1;
+	}
+
+	if (!fb_find_mode(&info->var, info,
+			  mode_option, NULL, 0, NULL, bpp)) {
+		err = -EINVAL;
+		goto out_unmap2;
+	}
+	err = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (err < 0)
+		goto out_unmap2;
+
+	info->var.activate |= FB_ACTIVATE_NOW;
+	info->device = &dev->dev;
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "tridentfb: could not register framebuffer\n");
+		fb_dealloc_cmap(&info->cmap);
+		err = -EINVAL;
+		goto out_unmap2;
+	}
+	output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
+	   info->node, info->fix.id, info->var.xres,
+	   info->var.yres, info->var.bits_per_pixel);
+
+	pci_set_drvdata(dev, info);
+	return 0;
+
+out_unmap2:
+	kfree(info->pixmap.addr);
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
+	disable_mmio(info->par);
+out_unmap1:
+	if (default_par->io_virt)
+		iounmap(default_par->io_virt);
+	release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+	framebuffer_release(info);
+	return err;
+}
+
+static void trident_pci_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct tridentfb_par *par = info->par;
+
+	unregister_framebuffer(info);
+	iounmap(par->io_virt);
+	iounmap(info->screen_base);
+	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
+	release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+	kfree(info->pixmap.addr);
+	fb_dealloc_cmap(&info->cmap);
+	framebuffer_release(info);
+}
+
+/* List of boards that we are trying to support */
+static struct pci_device_id trident_devices[] = {
+	{PCI_VENDOR_ID_TRIDENT,	BLADE3D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi7D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBER9320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBER9388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBER9520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBER9525DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBER9397, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBER9397DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPm8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPm16, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, trident_devices);
+
+static struct pci_driver tridentfb_pci_driver = {
+	.name = "tridentfb",
+	.id_table = trident_devices,
+	.probe = trident_pci_probe,
+	.remove = trident_pci_remove,
+};
+
+/*
+ * Parse user specified options (`video=trident:')
+ * example:
+ *	video=trident:800x600,bpp=16,noaccel
+ */
+#ifndef MODULE
+static int __init tridentfb_setup(char *options)
+{
+	char *opt;
+	if (!options || !*options)
+		return 0;
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+		if (!strncmp(opt, "noaccel", 7))
+			noaccel = 1;
+		else if (!strncmp(opt, "fp", 2))
+			fp = 1;
+		else if (!strncmp(opt, "crt", 3))
+			fp = 0;
+		else if (!strncmp(opt, "bpp=", 4))
+			bpp = simple_strtoul(opt + 4, NULL, 0);
+		else if (!strncmp(opt, "center", 6))
+			center = 1;
+		else if (!strncmp(opt, "stretch", 7))
+			stretch = 1;
+		else if (!strncmp(opt, "memsize=", 8))
+			memsize = simple_strtoul(opt + 8, NULL, 0);
+		else if (!strncmp(opt, "memdiff=", 8))
+			memdiff = simple_strtoul(opt + 8, NULL, 0);
+		else if (!strncmp(opt, "nativex=", 8))
+			nativex = simple_strtoul(opt + 8, NULL, 0);
+		else
+			mode_option = opt;
+	}
+	return 0;
+}
+#endif
+
+static int __init tridentfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tridentfb", &option))
+		return -ENODEV;
+	tridentfb_setup(option);
+#endif
+	return pci_register_driver(&tridentfb_pci_driver);
+}
+
+static void __exit tridentfb_exit(void)
+{
+	pci_unregister_driver(&tridentfb_pci_driver);
+}
+
+module_init(tridentfb_init);
+module_exit(tridentfb_exit);
+
+MODULE_AUTHOR("Jani Monoses <jani@iv.ro>");
+MODULE_DESCRIPTION("Framebuffer driver for Trident cards");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("cyblafb");
+
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
new file mode 100644
index 000000000000..77b890e4d296
--- /dev/null
+++ b/drivers/video/fbdev/udlfb.c
@@ -0,0 +1,1985 @@
+/*
+ * udlfb.c -- Framebuffer driver for DisplayLink USB controller
+ *
+ * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
+ * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
+ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
+ * usb-skeleton by GregKH.
+ *
+ * Device-specific portions based on information from Displaylink, with work
+ * from Florian Echtler, Henrik Bjerregaard Pedersen, and others.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/prefetch.h>
+#include <linux/delay.h>
+#include <video/udlfb.h>
+#include "edid.h"
+
+static struct fb_fix_screeninfo dlfb_fix = {
+	.id =           "udlfb",
+	.type =         FB_TYPE_PACKED_PIXELS,
+	.visual =       FB_VISUAL_TRUECOLOR,
+	.xpanstep =     0,
+	.ypanstep =     0,
+	.ywrapstep =    0,
+	.accel =        FB_ACCEL_NONE,
+};
+
+static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+		FBINFO_VIRTFB |
+		FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
+
+/*
+ * There are many DisplayLink-based graphics products, all with unique PIDs.
+ * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff)
+ * We also require a match on SubClass (0x00) and Protocol (0x00),
+ * which is compatible with all known USB 2.0 era graphics chips and firmware,
+ * but allows DisplayLink to increment those for any future incompatible chips
+ */
+static struct usb_device_id id_table[] = {
+	{.idVendor = 0x17e9,
+	 .bInterfaceClass = 0xff,
+	 .bInterfaceSubClass = 0x00,
+	 .bInterfaceProtocol = 0x00,
+	 .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
+		USB_DEVICE_ID_MATCH_INT_CLASS |
+		USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+		USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* module options */
+static bool console = 1; /* Allow fbcon to open framebuffer */
+static bool fb_defio = 1;  /* Detect mmap writes using page faults */
+static bool shadow = 1; /* Optionally disable shadow framebuffer */
+static int pixel_limit; /* Optionally force a pixel resolution limit */
+
+/* dlfb keeps a list of urbs for efficient bulk transfers */
+static void dlfb_urb_completion(struct urb *urb);
+static struct urb *dlfb_get_urb(struct dlfb_data *dev);
+static int dlfb_submit_urb(struct dlfb_data *dev, struct urb * urb, size_t len);
+static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size);
+static void dlfb_free_urb_list(struct dlfb_data *dev);
+
+/*
+ * All DisplayLink bulk operations start with 0xAF, followed by specific code
+ * All operations are written to buffers which then later get sent to device
+ */
+static char *dlfb_set_register(char *buf, u8 reg, u8 val)
+{
+	*buf++ = 0xAF;
+	*buf++ = 0x20;
+	*buf++ = reg;
+	*buf++ = val;
+	return buf;
+}
+
+static char *dlfb_vidreg_lock(char *buf)
+{
+	return dlfb_set_register(buf, 0xFF, 0x00);
+}
+
+static char *dlfb_vidreg_unlock(char *buf)
+{
+	return dlfb_set_register(buf, 0xFF, 0xFF);
+}
+
+/*
+ * Map FB_BLANK_* to DisplayLink register
+ * DLReg FB_BLANK_*
+ * ----- -----------------------------
+ *  0x00 FB_BLANK_UNBLANK (0)
+ *  0x01 FB_BLANK (1)
+ *  0x03 FB_BLANK_VSYNC_SUSPEND (2)
+ *  0x05 FB_BLANK_HSYNC_SUSPEND (3)
+ *  0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back
+ */
+static char *dlfb_blanking(char *buf, int fb_blank)
+{
+	u8 reg;
+
+	switch (fb_blank) {
+	case FB_BLANK_POWERDOWN:
+		reg = 0x07;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		reg = 0x05;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		reg = 0x03;
+		break;
+	case FB_BLANK_NORMAL:
+		reg = 0x01;
+		break;
+	default:
+		reg = 0x00;
+	}
+
+	buf = dlfb_set_register(buf, 0x1F, reg);
+
+	return buf;
+}
+
+static char *dlfb_set_color_depth(char *buf, u8 selection)
+{
+	return dlfb_set_register(buf, 0x00, selection);
+}
+
+static char *dlfb_set_base16bpp(char *wrptr, u32 base)
+{
+	/* the base pointer is 16 bits wide, 0x20 is hi byte. */
+	wrptr = dlfb_set_register(wrptr, 0x20, base >> 16);
+	wrptr = dlfb_set_register(wrptr, 0x21, base >> 8);
+	return dlfb_set_register(wrptr, 0x22, base);
+}
+
+/*
+ * DisplayLink HW has separate 16bpp and 8bpp framebuffers.
+ * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
+ */
+static char *dlfb_set_base8bpp(char *wrptr, u32 base)
+{
+	wrptr = dlfb_set_register(wrptr, 0x26, base >> 16);
+	wrptr = dlfb_set_register(wrptr, 0x27, base >> 8);
+	return dlfb_set_register(wrptr, 0x28, base);
+}
+
+static char *dlfb_set_register_16(char *wrptr, u8 reg, u16 value)
+{
+	wrptr = dlfb_set_register(wrptr, reg, value >> 8);
+	return dlfb_set_register(wrptr, reg+1, value);
+}
+
+/*
+ * This is kind of weird because the controller takes some
+ * register values in a different byte order than other registers.
+ */
+static char *dlfb_set_register_16be(char *wrptr, u8 reg, u16 value)
+{
+	wrptr = dlfb_set_register(wrptr, reg, value);
+	return dlfb_set_register(wrptr, reg+1, value >> 8);
+}
+
+/*
+ * LFSR is linear feedback shift register. The reason we have this is
+ * because the display controller needs to minimize the clock depth of
+ * various counters used in the display path. So this code reverses the
+ * provided value into the lfsr16 value by counting backwards to get
+ * the value that needs to be set in the hardware comparator to get the
+ * same actual count. This makes sense once you read above a couple of
+ * times and think about it from a hardware perspective.
+ */
+static u16 dlfb_lfsr16(u16 actual_count)
+{
+	u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */
+
+	while (actual_count--) {
+		lv =	 ((lv << 1) |
+			(((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1))
+			& 0xFFFF;
+	}
+
+	return (u16) lv;
+}
+
+/*
+ * This does LFSR conversion on the value that is to be written.
+ * See LFSR explanation above for more detail.
+ */
+static char *dlfb_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
+{
+	return dlfb_set_register_16(wrptr, reg, dlfb_lfsr16(value));
+}
+
+/*
+ * This takes a standard fbdev screeninfo struct and all of its monitor mode
+ * details and converts them into the DisplayLink equivalent register commands.
+ */
+static char *dlfb_set_vid_cmds(char *wrptr, struct fb_var_screeninfo *var)
+{
+	u16 xds, yds;
+	u16 xde, yde;
+	u16 yec;
+
+	/* x display start */
+	xds = var->left_margin + var->hsync_len;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x01, xds);
+	/* x display end */
+	xde = xds + var->xres;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x03, xde);
+
+	/* y display start */
+	yds = var->upper_margin + var->vsync_len;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x05, yds);
+	/* y display end */
+	yde = yds + var->yres;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x07, yde);
+
+	/* x end count is active + blanking - 1 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x09,
+			xde + var->right_margin - 1);
+
+	/* libdlo hardcodes hsync start to 1 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0B, 1);
+
+	/* hsync end is width of sync pulse + 1 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0D, var->hsync_len + 1);
+
+	/* hpixels is active pixels */
+	wrptr = dlfb_set_register_16(wrptr, 0x0F, var->xres);
+
+	/* yendcount is vertical active + vertical blanking */
+	yec = var->yres + var->upper_margin + var->lower_margin +
+			var->vsync_len;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x11, yec);
+
+	/* libdlo hardcodes vsync start to 0 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x13, 0);
+
+	/* vsync end is width of vsync pulse */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x15, var->vsync_len);
+
+	/* vpixels is active pixels */
+	wrptr = dlfb_set_register_16(wrptr, 0x17, var->yres);
+
+	/* convert picoseconds to 5kHz multiple for pclk5k = x * 1E12/5k */
+	wrptr = dlfb_set_register_16be(wrptr, 0x1B,
+			200*1000*1000/var->pixclock);
+
+	return wrptr;
+}
+
+/*
+ * This takes a standard fbdev screeninfo struct that was fetched or prepared
+ * and then generates the appropriate command sequence that then drives the
+ * display controller.
+ */
+static int dlfb_set_video_mode(struct dlfb_data *dev,
+				struct fb_var_screeninfo *var)
+{
+	char *buf;
+	char *wrptr;
+	int retval = 0;
+	int writesize;
+	struct urb *urb;
+
+	if (!atomic_read(&dev->usb_active))
+		return -EPERM;
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return -ENOMEM;
+
+	buf = (char *) urb->transfer_buffer;
+
+	/*
+	* This first section has to do with setting the base address on the
+	* controller * associated with the display. There are 2 base
+	* pointers, currently, we only * use the 16 bpp segment.
+	*/
+	wrptr = dlfb_vidreg_lock(buf);
+	wrptr = dlfb_set_color_depth(wrptr, 0x00);
+	/* set base for 16bpp segment to 0 */
+	wrptr = dlfb_set_base16bpp(wrptr, 0);
+	/* set base for 8bpp segment to end of fb */
+	wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
+
+	wrptr = dlfb_set_vid_cmds(wrptr, var);
+	wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK);
+	wrptr = dlfb_vidreg_unlock(wrptr);
+
+	writesize = wrptr - buf;
+
+	retval = dlfb_submit_urb(dev, urb, writesize);
+
+	dev->blank_mode = FB_BLANK_UNBLANK;
+
+	return retval;
+}
+
+static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long page, pos;
+
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	if (size > info->fix.smem_len)
+		return -EINVAL;
+	if (offset > info->fix.smem_len - size)
+		return -EINVAL;
+
+	pos = (unsigned long)info->fix.smem_start + offset;
+
+	pr_notice("mmap() framebuffer addr:%lu size:%lu\n",
+		  pos, size);
+
+	while (size > 0) {
+		page = vmalloc_to_pfn((void *)pos);
+		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * Trims identical data from front and back of line
+ * Sets new front buffer address and width
+ * And returns byte count of identical pixels
+ * Assumes CPU natural alignment (unsigned long)
+ * for back and front buffer ptrs and width
+ */
+static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
+{
+	int j, k;
+	const unsigned long *back = (const unsigned long *) bback;
+	const unsigned long *front = (const unsigned long *) *bfront;
+	const int width = *width_bytes / sizeof(unsigned long);
+	int identical = width;
+	int start = width;
+	int end = width;
+
+	prefetch((void *) front);
+	prefetch((void *) back);
+
+	for (j = 0; j < width; j++) {
+		if (back[j] != front[j]) {
+			start = j;
+			break;
+		}
+	}
+
+	for (k = width - 1; k > j; k--) {
+		if (back[k] != front[k]) {
+			end = k+1;
+			break;
+		}
+	}
+
+	identical = start + (width - end);
+	*bfront = (u8 *) &front[start];
+	*width_bytes = (end - start) * sizeof(unsigned long);
+
+	return identical * sizeof(unsigned long);
+}
+
+/*
+ * Render a command stream for an encoded horizontal line segment of pixels.
+ *
+ * A command buffer holds several commands.
+ * It always begins with a fresh command header
+ * (the protocol doesn't require this, but we enforce it to allow
+ * multiple buffers to be potentially encoded and sent in parallel).
+ * A single command encodes one contiguous horizontal line of pixels
+ *
+ * The function relies on the client to do all allocation, so that
+ * rendering can be done directly to output buffers (e.g. USB URBs).
+ * The function fills the supplied command buffer, providing information
+ * on where it left off, so the client may call in again with additional
+ * buffers if the line will take several buffers to complete.
+ *
+ * A single command can transmit a maximum of 256 pixels,
+ * regardless of the compression ratio (protocol design limit).
+ * To the hardware, 0 for a size byte means 256
+ *
+ * Rather than 256 pixel commands which are either rl or raw encoded,
+ * the rlx command simply assumes alternating raw and rl spans within one cmd.
+ * This has a slightly larger header overhead, but produces more even results.
+ * It also processes all data (read and write) in a single pass.
+ * Performance benchmarks of common cases show it having just slightly better
+ * compression than 256 pixel raw or rle commands, with similar CPU consumpion.
+ * But for very rl friendly data, will compress not quite as well.
+ */
+static void dlfb_compress_hline(
+	const uint16_t **pixel_start_ptr,
+	const uint16_t *const pixel_end,
+	uint32_t *device_address_ptr,
+	uint8_t **command_buffer_ptr,
+	const uint8_t *const cmd_buffer_end)
+{
+	const uint16_t *pixel = *pixel_start_ptr;
+	uint32_t dev_addr  = *device_address_ptr;
+	uint8_t *cmd = *command_buffer_ptr;
+	const int bpp = 2;
+
+	while ((pixel_end > pixel) &&
+	       (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) {
+		uint8_t *raw_pixels_count_byte = NULL;
+		uint8_t *cmd_pixels_count_byte = NULL;
+		const uint16_t *raw_pixel_start = NULL;
+		const uint16_t *cmd_pixel_start, *cmd_pixel_end = NULL;
+
+		prefetchw((void *) cmd); /* pull in one cache line at least */
+
+		*cmd++ = 0xAF;
+		*cmd++ = 0x6B;
+		*cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
+		*cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
+		*cmd++ = (uint8_t) ((dev_addr) & 0xFF);
+
+		cmd_pixels_count_byte = cmd++; /*  we'll know this later */
+		cmd_pixel_start = pixel;
+
+		raw_pixels_count_byte = cmd++; /*  we'll know this later */
+		raw_pixel_start = pixel;
+
+		cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
+			min((int)(pixel_end - pixel),
+			    (int)(cmd_buffer_end - cmd) / bpp));
+
+		prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
+
+		while (pixel < cmd_pixel_end) {
+			const uint16_t * const repeating_pixel = pixel;
+
+			*(uint16_t *)cmd = cpu_to_be16p(pixel);
+			cmd += 2;
+			pixel++;
+
+			if (unlikely((pixel < cmd_pixel_end) &&
+				     (*pixel == *repeating_pixel))) {
+				/* go back and fill in raw pixel count */
+				*raw_pixels_count_byte = ((repeating_pixel -
+						raw_pixel_start) + 1) & 0xFF;
+
+				while ((pixel < cmd_pixel_end)
+				       && (*pixel == *repeating_pixel)) {
+					pixel++;
+				}
+
+				/* immediately after raw data is repeat byte */
+				*cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
+
+				/* Then start another raw pixel span */
+				raw_pixel_start = pixel;
+				raw_pixels_count_byte = cmd++;
+			}
+		}
+
+		if (pixel > raw_pixel_start) {
+			/* finalize last RAW span */
+			*raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
+		}
+
+		*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
+		dev_addr += (pixel - cmd_pixel_start) * bpp;
+	}
+
+	if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
+		/* Fill leftover bytes with no-ops */
+		if (cmd_buffer_end > cmd)
+			memset(cmd, 0xAF, cmd_buffer_end - cmd);
+		cmd = (uint8_t *) cmd_buffer_end;
+	}
+
+	*command_buffer_ptr = cmd;
+	*pixel_start_ptr = pixel;
+	*device_address_ptr = dev_addr;
+
+	return;
+}
+
+/*
+ * There are 3 copies of every pixel: The front buffer that the fbdev
+ * client renders to, the actual framebuffer across the USB bus in hardware
+ * (that we can only write to, slowly, and can never read), and (optionally)
+ * our shadow copy that tracks what's been sent to that hardware buffer.
+ */
+static int dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
+			      const char *front, char **urb_buf_ptr,
+			      u32 byte_offset, u32 byte_width,
+			      int *ident_ptr, int *sent_ptr)
+{
+	const u8 *line_start, *line_end, *next_pixel;
+	u32 dev_addr = dev->base16 + byte_offset;
+	struct urb *urb = *urb_ptr;
+	u8 *cmd = *urb_buf_ptr;
+	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
+
+	line_start = (u8 *) (front + byte_offset);
+	next_pixel = line_start;
+	line_end = next_pixel + byte_width;
+
+	if (dev->backing_buffer) {
+		int offset;
+		const u8 *back_start = (u8 *) (dev->backing_buffer
+						+ byte_offset);
+
+		*ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
+			&byte_width);
+
+		offset = next_pixel - line_start;
+		line_end = next_pixel + byte_width;
+		dev_addr += offset;
+		back_start += offset;
+		line_start += offset;
+
+		memcpy((char *)back_start, (char *) line_start,
+		       byte_width);
+	}
+
+	while (next_pixel < line_end) {
+
+		dlfb_compress_hline((const uint16_t **) &next_pixel,
+			     (const uint16_t *) line_end, &dev_addr,
+			(u8 **) &cmd, (u8 *) cmd_end);
+
+		if (cmd >= cmd_end) {
+			int len = cmd - (u8 *) urb->transfer_buffer;
+			if (dlfb_submit_urb(dev, urb, len))
+				return 1; /* lost pixels is set */
+			*sent_ptr += len;
+			urb = dlfb_get_urb(dev);
+			if (!urb)
+				return 1; /* lost_pixels is set */
+			*urb_ptr = urb;
+			cmd = urb->transfer_buffer;
+			cmd_end = &cmd[urb->transfer_buffer_length];
+		}
+	}
+
+	*urb_buf_ptr = cmd;
+
+	return 0;
+}
+
+static int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+	       int width, int height, char *data)
+{
+	int i, ret;
+	char *cmd;
+	cycles_t start_cycles, end_cycles;
+	int bytes_sent = 0;
+	int bytes_identical = 0;
+	struct urb *urb;
+	int aligned_x;
+
+	start_cycles = get_cycles();
+
+	aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
+	width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
+	x = aligned_x;
+
+	if ((width <= 0) ||
+	    (x + width > dev->info->var.xres) ||
+	    (y + height > dev->info->var.yres))
+		return -EINVAL;
+
+	if (!atomic_read(&dev->usb_active))
+		return 0;
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return 0;
+	cmd = urb->transfer_buffer;
+
+	for (i = y; i < y + height ; i++) {
+		const int line_offset = dev->info->fix.line_length * i;
+		const int byte_offset = line_offset + (x * BPP);
+
+		if (dlfb_render_hline(dev, &urb,
+				      (char *) dev->info->fix.smem_start,
+				      &cmd, byte_offset, width * BPP,
+				      &bytes_identical, &bytes_sent))
+			goto error;
+	}
+
+	if (cmd > (char *) urb->transfer_buffer) {
+		/* Send partial buffer remaining before exiting */
+		int len = cmd - (char *) urb->transfer_buffer;
+		ret = dlfb_submit_urb(dev, urb, len);
+		bytes_sent += len;
+	} else
+		dlfb_urb_completion(urb);
+
+error:
+	atomic_add(bytes_sent, &dev->bytes_sent);
+	atomic_add(bytes_identical, &dev->bytes_identical);
+	atomic_add(width*height*2, &dev->bytes_rendered);
+	end_cycles = get_cycles();
+	atomic_add(((unsigned int) ((end_cycles - start_cycles)
+		    >> 10)), /* Kcycles */
+		   &dev->cpu_kcycles_used);
+
+	return 0;
+}
+
+/*
+ * Path triggered by usermode clients who write to filesystem
+ * e.g. cat filename > /dev/fb1
+ * Not used by X Windows or text-mode console. But useful for testing.
+ * Slow because of extra copy and we must assume all pixels dirty.
+ */
+static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
+			  size_t count, loff_t *ppos)
+{
+	ssize_t result;
+	struct dlfb_data *dev = info->par;
+	u32 offset = (u32) *ppos;
+
+	result = fb_sys_write(info, buf, count, ppos);
+
+	if (result > 0) {
+		int start = max((int)(offset / info->fix.line_length), 0);
+		int lines = min((u32)((result / info->fix.line_length) + 1),
+				(u32)info->var.yres);
+
+		dlfb_handle_damage(dev, 0, start, info->var.xres,
+			lines, info->screen_base);
+	}
+
+	return result;
+}
+
+/* hardware has native COPY command (see libdlo), but not worth it for fbcon */
+static void dlfb_ops_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+
+	struct dlfb_data *dev = info->par;
+
+	sys_copyarea(info, area);
+
+	dlfb_handle_damage(dev, area->dx, area->dy,
+			area->width, area->height, info->screen_base);
+}
+
+static void dlfb_ops_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	struct dlfb_data *dev = info->par;
+
+	sys_imageblit(info, image);
+
+	dlfb_handle_damage(dev, image->dx, image->dy,
+			image->width, image->height, info->screen_base);
+}
+
+static void dlfb_ops_fillrect(struct fb_info *info,
+			  const struct fb_fillrect *rect)
+{
+	struct dlfb_data *dev = info->par;
+
+	sys_fillrect(info, rect);
+
+	dlfb_handle_damage(dev, rect->dx, rect->dy, rect->width,
+			      rect->height, info->screen_base);
+}
+
+/*
+ * NOTE: fb_defio.c is holding info->fbdefio.mutex
+ *   Touching ANY framebuffer memory that triggers a page fault
+ *   in fb_defio will cause a deadlock, when it also tries to
+ *   grab the same mutex.
+ */
+static void dlfb_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	struct page *cur;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct dlfb_data *dev = info->par;
+	struct urb *urb;
+	char *cmd;
+	cycles_t start_cycles, end_cycles;
+	int bytes_sent = 0;
+	int bytes_identical = 0;
+	int bytes_rendered = 0;
+
+	if (!fb_defio)
+		return;
+
+	if (!atomic_read(&dev->usb_active))
+		return;
+
+	start_cycles = get_cycles();
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return;
+
+	cmd = urb->transfer_buffer;
+
+	/* walk the written page list and render each to device */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+
+		if (dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
+				  &cmd, cur->index << PAGE_SHIFT,
+				  PAGE_SIZE, &bytes_identical, &bytes_sent))
+			goto error;
+		bytes_rendered += PAGE_SIZE;
+	}
+
+	if (cmd > (char *) urb->transfer_buffer) {
+		/* Send partial buffer remaining before exiting */
+		int len = cmd - (char *) urb->transfer_buffer;
+		dlfb_submit_urb(dev, urb, len);
+		bytes_sent += len;
+	} else
+		dlfb_urb_completion(urb);
+
+error:
+	atomic_add(bytes_sent, &dev->bytes_sent);
+	atomic_add(bytes_identical, &dev->bytes_identical);
+	atomic_add(bytes_rendered, &dev->bytes_rendered);
+	end_cycles = get_cycles();
+	atomic_add(((unsigned int) ((end_cycles - start_cycles)
+		    >> 10)), /* Kcycles */
+		   &dev->cpu_kcycles_used);
+}
+
+static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
+{
+	int i;
+	int ret;
+	char *rbuf;
+
+	rbuf = kmalloc(2, GFP_KERNEL);
+	if (!rbuf)
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		ret = usb_control_msg(dev->udev,
+				    usb_rcvctrlpipe(dev->udev, 0), (0x02),
+				    (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
+				    HZ);
+		if (ret < 1) {
+			pr_err("Read EDID byte %d failed err %x\n", i, ret);
+			i--;
+			break;
+		}
+		edid[i] = rbuf[1];
+	}
+
+	kfree(rbuf);
+
+	return i;
+}
+
+static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
+				unsigned long arg)
+{
+
+	struct dlfb_data *dev = info->par;
+
+	if (!atomic_read(&dev->usb_active))
+		return 0;
+
+	/* TODO: Update X server to get this from sysfs instead */
+	if (cmd == DLFB_IOCTL_RETURN_EDID) {
+		void __user *edid = (void __user *)arg;
+		if (copy_to_user(edid, dev->edid, dev->edid_size))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+	if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
+		struct dloarea area;
+
+		if (copy_from_user(&area, (void __user *)arg,
+				  sizeof(struct dloarea)))
+			return -EFAULT;
+
+		/*
+		 * If we have a damage-aware client, turn fb_defio "off"
+		 * To avoid perf imact of unnecessary page fault handling.
+		 * Done by resetting the delay for this fb_info to a very
+		 * long period. Pages will become writable and stay that way.
+		 * Reset to normal value when all clients have closed this fb.
+		 */
+		if (info->fbdefio)
+			info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
+
+		if (area.x < 0)
+			area.x = 0;
+
+		if (area.x > info->var.xres)
+			area.x = info->var.xres;
+
+		if (area.y < 0)
+			area.y = 0;
+
+		if (area.y > info->var.yres)
+			area.y = info->var.yres;
+
+		dlfb_handle_damage(dev, area.x, area.y, area.w, area.h,
+			   info->screen_base);
+	}
+
+	return 0;
+}
+
+/* taken from vesafb */
+static int
+dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
+	       unsigned blue, unsigned transp, struct fb_info *info)
+{
+	int err = 0;
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	if (regno < 16) {
+		if (info->var.red.offset == 10) {
+			/* 1:5:5:5 */
+			((u32 *) (info->pseudo_palette))[regno] =
+			    ((red & 0xf800) >> 1) |
+			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
+		} else {
+			/* 0:5:6:5 */
+			((u32 *) (info->pseudo_palette))[regno] =
+			    ((red & 0xf800)) |
+			    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+		}
+	}
+
+	return err;
+}
+
+/*
+ * It's common for several clients to have framebuffer open simultaneously.
+ * e.g. both fbcon and X. Makes things interesting.
+ * Assumes caller is holding info->lock (for open and release at least)
+ */
+static int dlfb_ops_open(struct fb_info *info, int user)
+{
+	struct dlfb_data *dev = info->par;
+
+	/*
+	 * fbcon aggressively connects to first framebuffer it finds,
+	 * preventing other clients (X) from working properly. Usually
+	 * not what the user wants. Fail by default with option to enable.
+	 */
+	if ((user == 0) && (!console))
+		return -EBUSY;
+
+	/* If the USB device is gone, we don't accept new opens */
+	if (dev->virtualized)
+		return -ENODEV;
+
+	dev->fb_count++;
+
+	kref_get(&dev->kref);
+
+	if (fb_defio && (info->fbdefio == NULL)) {
+		/* enable defio at last moment if not disabled by client */
+
+		struct fb_deferred_io *fbdefio;
+
+		fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
+
+		if (fbdefio) {
+			fbdefio->delay = DL_DEFIO_WRITE_DELAY;
+			fbdefio->deferred_io = dlfb_dpy_deferred_io;
+		}
+
+		info->fbdefio = fbdefio;
+		fb_deferred_io_init(info);
+	}
+
+	pr_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
+	    info->node, user, info, dev->fb_count);
+
+	return 0;
+}
+
+/*
+ * Called when all client interfaces to start transactions have been disabled,
+ * and all references to our device instance (dlfb_data) are released.
+ * Every transaction must have a reference, so we know are fully spun down
+ */
+static void dlfb_free(struct kref *kref)
+{
+	struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
+
+	if (dev->backing_buffer)
+		vfree(dev->backing_buffer);
+
+	kfree(dev->edid);
+
+	pr_warn("freeing dlfb_data %p\n", dev);
+
+	kfree(dev);
+}
+
+static void dlfb_release_urb_work(struct work_struct *work)
+{
+	struct urb_node *unode = container_of(work, struct urb_node,
+					      release_urb_work.work);
+
+	up(&unode->dev->urbs.limit_sem);
+}
+
+static void dlfb_free_framebuffer(struct dlfb_data *dev)
+{
+	struct fb_info *info = dev->info;
+
+	if (info) {
+		int node = info->node;
+
+		unregister_framebuffer(info);
+
+		if (info->cmap.len != 0)
+			fb_dealloc_cmap(&info->cmap);
+		if (info->monspecs.modedb)
+			fb_destroy_modedb(info->monspecs.modedb);
+		if (info->screen_base)
+			vfree(info->screen_base);
+
+		fb_destroy_modelist(&info->modelist);
+
+		dev->info = NULL;
+
+		/* Assume info structure is freed after this point */
+		framebuffer_release(info);
+
+		pr_warn("fb_info for /dev/fb%d has been freed\n", node);
+	}
+
+	/* ref taken in probe() as part of registering framebfufer */
+	kref_put(&dev->kref, dlfb_free);
+}
+
+static void dlfb_free_framebuffer_work(struct work_struct *work)
+{
+	struct dlfb_data *dev = container_of(work, struct dlfb_data,
+					     free_framebuffer_work.work);
+	dlfb_free_framebuffer(dev);
+}
+/*
+ * Assumes caller is holding info->lock mutex (for open and release at least)
+ */
+static int dlfb_ops_release(struct fb_info *info, int user)
+{
+	struct dlfb_data *dev = info->par;
+
+	dev->fb_count--;
+
+	/* We can't free fb_info here - fbmem will touch it when we return */
+	if (dev->virtualized && (dev->fb_count == 0))
+		schedule_delayed_work(&dev->free_framebuffer_work, HZ);
+
+	if ((dev->fb_count == 0) && (info->fbdefio)) {
+		fb_deferred_io_cleanup(info);
+		kfree(info->fbdefio);
+		info->fbdefio = NULL;
+		info->fbops->fb_mmap = dlfb_ops_mmap;
+	}
+
+	pr_warn("released /dev/fb%d user=%d count=%d\n",
+		  info->node, user, dev->fb_count);
+
+	kref_put(&dev->kref, dlfb_free);
+
+	return 0;
+}
+
+/*
+ * Check whether a video mode is supported by the DisplayLink chip
+ * We start from monitor's modes, so don't need to filter that here
+ */
+static int dlfb_is_valid_mode(struct fb_videomode *mode,
+		struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+
+	if (mode->xres * mode->yres > dev->sku_pixel_limit) {
+		pr_warn("%dx%d beyond chip capabilities\n",
+		       mode->xres, mode->yres);
+		return 0;
+	}
+
+	pr_info("%dx%d @ %d Hz valid mode\n", mode->xres, mode->yres,
+		mode->refresh);
+
+	return 1;
+}
+
+static void dlfb_var_color_format(struct fb_var_screeninfo *var)
+{
+	const struct fb_bitfield red = { 11, 5, 0 };
+	const struct fb_bitfield green = { 5, 6, 0 };
+	const struct fb_bitfield blue = { 0, 5, 0 };
+
+	var->bits_per_pixel = 16;
+	var->red = red;
+	var->green = green;
+	var->blue = blue;
+}
+
+static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct fb_videomode mode;
+
+	/* TODO: support dynamically changing framebuffer size */
+	if ((var->xres * var->yres * 2) > info->fix.smem_len)
+		return -EINVAL;
+
+	/* set device-specific elements of var unrelated to mode */
+	dlfb_var_color_format(var);
+
+	fb_var_to_videomode(&mode, var);
+
+	if (!dlfb_is_valid_mode(&mode, info))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int dlfb_ops_set_par(struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+	int result;
+	u16 *pix_framebuffer;
+	int i;
+
+	pr_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
+
+	result = dlfb_set_video_mode(dev, &info->var);
+
+	if ((result == 0) && (dev->fb_count == 0)) {
+
+		/* paint greenscreen */
+
+		pix_framebuffer = (u16 *) info->screen_base;
+		for (i = 0; i < info->fix.smem_len / 2; i++)
+			pix_framebuffer[i] = 0x37e6;
+
+		dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
+				   info->screen_base);
+	}
+
+	return result;
+}
+
+/* To fonzi the jukebox (e.g. make blanking changes take effect) */
+static char *dlfb_dummy_render(char *buf)
+{
+	*buf++ = 0xAF;
+	*buf++ = 0x6A; /* copy */
+	*buf++ = 0x00; /* from address*/
+	*buf++ = 0x00;
+	*buf++ = 0x00;
+	*buf++ = 0x01; /* one pixel */
+	*buf++ = 0x00; /* to address */
+	*buf++ = 0x00;
+	*buf++ = 0x00;
+	return buf;
+}
+
+/*
+ * In order to come back from full DPMS off, we need to set the mode again
+ */
+static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+	char *bufptr;
+	struct urb *urb;
+
+	pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
+		info->node, dev->blank_mode, blank_mode);
+
+	if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
+	    (blank_mode != FB_BLANK_POWERDOWN)) {
+
+		/* returning from powerdown requires a fresh modeset */
+		dlfb_set_video_mode(dev, &info->var);
+	}
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return 0;
+
+	bufptr = (char *) urb->transfer_buffer;
+	bufptr = dlfb_vidreg_lock(bufptr);
+	bufptr = dlfb_blanking(bufptr, blank_mode);
+	bufptr = dlfb_vidreg_unlock(bufptr);
+
+	/* seems like a render op is needed to have blank change take effect */
+	bufptr = dlfb_dummy_render(bufptr);
+
+	dlfb_submit_urb(dev, urb, bufptr -
+			(char *) urb->transfer_buffer);
+
+	dev->blank_mode = blank_mode;
+
+	return 0;
+}
+
+static struct fb_ops dlfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_read = fb_sys_read,
+	.fb_write = dlfb_ops_write,
+	.fb_setcolreg = dlfb_ops_setcolreg,
+	.fb_fillrect = dlfb_ops_fillrect,
+	.fb_copyarea = dlfb_ops_copyarea,
+	.fb_imageblit = dlfb_ops_imageblit,
+	.fb_mmap = dlfb_ops_mmap,
+	.fb_ioctl = dlfb_ops_ioctl,
+	.fb_open = dlfb_ops_open,
+	.fb_release = dlfb_ops_release,
+	.fb_blank = dlfb_ops_blank,
+	.fb_check_var = dlfb_ops_check_var,
+	.fb_set_par = dlfb_ops_set_par,
+};
+
+
+/*
+ * Assumes &info->lock held by caller
+ * Assumes no active clients have framebuffer open
+ */
+static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
+{
+	int retval = -ENOMEM;
+	int old_len = info->fix.smem_len;
+	int new_len;
+	unsigned char *old_fb = info->screen_base;
+	unsigned char *new_fb;
+	unsigned char *new_back = NULL;
+
+	pr_warn("Reallocating framebuffer. Addresses will change!\n");
+
+	new_len = info->fix.line_length * info->var.yres;
+
+	if (PAGE_ALIGN(new_len) > old_len) {
+		/*
+		 * Alloc system memory for virtual framebuffer
+		 */
+		new_fb = vmalloc(new_len);
+		if (!new_fb) {
+			pr_err("Virtual framebuffer alloc failed\n");
+			goto error;
+		}
+
+		if (info->screen_base) {
+			memcpy(new_fb, old_fb, old_len);
+			vfree(info->screen_base);
+		}
+
+		info->screen_base = new_fb;
+		info->fix.smem_len = PAGE_ALIGN(new_len);
+		info->fix.smem_start = (unsigned long) new_fb;
+		info->flags = udlfb_info_flags;
+
+		/*
+		 * Second framebuffer copy to mirror the framebuffer state
+		 * on the physical USB device. We can function without this.
+		 * But with imperfect damage info we may send pixels over USB
+		 * that were, in fact, unchanged - wasting limited USB bandwidth
+		 */
+		if (shadow)
+			new_back = vzalloc(new_len);
+		if (!new_back)
+			pr_info("No shadow/backing buffer allocated\n");
+		else {
+			if (dev->backing_buffer)
+				vfree(dev->backing_buffer);
+			dev->backing_buffer = new_back;
+		}
+	}
+
+	retval = 0;
+
+error:
+	return retval;
+}
+
+/*
+ * 1) Get EDID from hw, or use sw default
+ * 2) Parse into various fb_info structs
+ * 3) Allocate virtual framebuffer memory to back highest res mode
+ *
+ * Parses EDID into three places used by various parts of fbdev:
+ * fb_var_screeninfo contains the timing of the monitor's preferred mode
+ * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
+ * fb_info.modelist is a linked list of all monitor & VESA modes which work
+ *
+ * If EDID is not readable/valid, then modelist is all VESA modes,
+ * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
+ * Returns 0 if successful
+ */
+static int dlfb_setup_modes(struct dlfb_data *dev,
+			   struct fb_info *info,
+			   char *default_edid, size_t default_edid_size)
+{
+	int i;
+	const struct fb_videomode *default_vmode = NULL;
+	int result = 0;
+	char *edid;
+	int tries = 3;
+
+	if (info->dev) /* only use mutex if info has been registered */
+		mutex_lock(&info->lock);
+
+	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!edid) {
+		result = -ENOMEM;
+		goto error;
+	}
+
+	fb_destroy_modelist(&info->modelist);
+	memset(&info->monspecs, 0, sizeof(info->monspecs));
+
+	/*
+	 * Try to (re)read EDID from hardware first
+	 * EDID data may return, but not parse as valid
+	 * Try again a few times, in case of e.g. analog cable noise
+	 */
+	while (tries--) {
+
+		i = dlfb_get_edid(dev, edid, EDID_LENGTH);
+
+		if (i >= EDID_LENGTH)
+			fb_edid_to_monspecs(edid, &info->monspecs);
+
+		if (info->monspecs.modedb_len > 0) {
+			dev->edid = edid;
+			dev->edid_size = i;
+			break;
+		}
+	}
+
+	/* If that fails, use a previously returned EDID if available */
+	if (info->monspecs.modedb_len == 0) {
+
+		pr_err("Unable to get valid EDID from device/display\n");
+
+		if (dev->edid) {
+			fb_edid_to_monspecs(dev->edid, &info->monspecs);
+			if (info->monspecs.modedb_len > 0)
+				pr_err("Using previously queried EDID\n");
+		}
+	}
+
+	/* If that fails, use the default EDID we were handed */
+	if (info->monspecs.modedb_len == 0) {
+		if (default_edid_size >= EDID_LENGTH) {
+			fb_edid_to_monspecs(default_edid, &info->monspecs);
+			if (info->monspecs.modedb_len > 0) {
+				memcpy(edid, default_edid, default_edid_size);
+				dev->edid = edid;
+				dev->edid_size = default_edid_size;
+				pr_err("Using default/backup EDID\n");
+			}
+		}
+	}
+
+	/* If we've got modes, let's pick a best default mode */
+	if (info->monspecs.modedb_len > 0) {
+
+		for (i = 0; i < info->monspecs.modedb_len; i++) {
+			if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info))
+				fb_add_videomode(&info->monspecs.modedb[i],
+					&info->modelist);
+			else {
+				if (i == 0)
+					/* if we've removed top/best mode */
+					info->monspecs.misc
+						&= ~FB_MISC_1ST_DETAIL;
+			}
+		}
+
+		default_vmode = fb_find_best_display(&info->monspecs,
+						     &info->modelist);
+	}
+
+	/* If everything else has failed, fall back to safe default mode */
+	if (default_vmode == NULL) {
+
+		struct fb_videomode fb_vmode = {0};
+
+		/*
+		 * Add the standard VESA modes to our modelist
+		 * Since we don't have EDID, there may be modes that
+		 * overspec monitor and/or are incorrect aspect ratio, etc.
+		 * But at least the user has a chance to choose
+		 */
+		for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+			if (dlfb_is_valid_mode((struct fb_videomode *)
+						&vesa_modes[i], info))
+				fb_add_videomode(&vesa_modes[i],
+						 &info->modelist);
+		}
+
+		/*
+		 * default to resolution safe for projectors
+		 * (since they are most common case without EDID)
+		 */
+		fb_vmode.xres = 800;
+		fb_vmode.yres = 600;
+		fb_vmode.refresh = 60;
+		default_vmode = fb_find_nearest_mode(&fb_vmode,
+						     &info->modelist);
+	}
+
+	/* If we have good mode and no active clients*/
+	if ((default_vmode != NULL) && (dev->fb_count == 0)) {
+
+		fb_videomode_to_var(&info->var, default_vmode);
+		dlfb_var_color_format(&info->var);
+
+		/*
+		 * with mode size info, we can now alloc our framebuffer.
+		 */
+		memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
+		info->fix.line_length = info->var.xres *
+			(info->var.bits_per_pixel / 8);
+
+		result = dlfb_realloc_framebuffer(dev, info);
+
+	} else
+		result = -EINVAL;
+
+error:
+	if (edid && (dev->edid != edid))
+		kfree(edid);
+
+	if (info->dev)
+		mutex_unlock(&info->lock);
+
+	return result;
+}
+
+static ssize_t metrics_bytes_rendered_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->bytes_rendered));
+}
+
+static ssize_t metrics_bytes_identical_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->bytes_identical));
+}
+
+static ssize_t metrics_bytes_sent_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->bytes_sent));
+}
+
+static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->cpu_kcycles_used));
+}
+
+static ssize_t edid_show(
+			struct file *filp,
+			struct kobject *kobj, struct bin_attribute *a,
+			 char *buf, loff_t off, size_t count) {
+	struct device *fbdev = container_of(kobj, struct device, kobj);
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+
+	if (dev->edid == NULL)
+		return 0;
+
+	if ((off >= dev->edid_size) || (count > dev->edid_size))
+		return 0;
+
+	if (off + count > dev->edid_size)
+		count = dev->edid_size - off;
+
+	pr_info("sysfs edid copy %p to %p, %d bytes\n",
+		dev->edid, buf, (int) count);
+
+	memcpy(buf, dev->edid, count);
+
+	return count;
+}
+
+static ssize_t edid_store(
+			struct file *filp,
+			struct kobject *kobj, struct bin_attribute *a,
+			char *src, loff_t src_off, size_t src_size) {
+	struct device *fbdev = container_of(kobj, struct device, kobj);
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	int ret;
+
+	/* We only support write of entire EDID at once, no offset*/
+	if ((src_size != EDID_LENGTH) || (src_off != 0))
+		return -EINVAL;
+
+	ret = dlfb_setup_modes(dev, fb_info, src, src_size);
+	if (ret)
+		return ret;
+
+	if (!dev->edid || memcmp(src, dev->edid, src_size))
+		return -EINVAL;
+
+	pr_info("sysfs written EDID is new default\n");
+	dlfb_ops_set_par(fb_info);
+	return src_size;
+}
+
+static ssize_t metrics_reset_store(struct device *fbdev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+
+	atomic_set(&dev->bytes_rendered, 0);
+	atomic_set(&dev->bytes_identical, 0);
+	atomic_set(&dev->bytes_sent, 0);
+	atomic_set(&dev->cpu_kcycles_used, 0);
+
+	return count;
+}
+
+static struct bin_attribute edid_attr = {
+	.attr.name = "edid",
+	.attr.mode = 0666,
+	.size = EDID_LENGTH,
+	.read = edid_show,
+	.write = edid_store
+};
+
+static struct device_attribute fb_device_attrs[] = {
+	__ATTR_RO(metrics_bytes_rendered),
+	__ATTR_RO(metrics_bytes_identical),
+	__ATTR_RO(metrics_bytes_sent),
+	__ATTR_RO(metrics_cpu_kcycles_used),
+	__ATTR(metrics_reset, S_IWUSR, NULL, metrics_reset_store),
+};
+
+/*
+ * This is necessary before we can communicate with the display controller.
+ */
+static int dlfb_select_std_channel(struct dlfb_data *dev)
+{
+	int ret;
+	u8 set_def_chn[] = {	   0x57, 0xCD, 0xDC, 0xA7,
+				0x1C, 0x88, 0x5E, 0x15,
+				0x60, 0xFE, 0xC6, 0x97,
+				0x16, 0x3D, 0x47, 0xF2  };
+
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			NR_USB_REQUEST_CHANNEL,
+			(USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
+			set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
+	return ret;
+}
+
+static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
+					struct usb_interface *interface)
+{
+	char *desc;
+	char *buf;
+	char *desc_end;
+
+	int total_len = 0;
+
+	buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
+	if (!buf)
+		return false;
+	desc = buf;
+
+	total_len = usb_get_descriptor(interface_to_usbdev(interface),
+					0x5f, /* vendor specific */
+					0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
+
+	/* if not found, look in configuration descriptor */
+	if (total_len < 0) {
+		if (0 == usb_get_extra_descriptor(interface->cur_altsetting,
+			0x5f, &desc))
+			total_len = (int) desc[0];
+	}
+
+	if (total_len > 5) {
+		pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
+			"%02x %02x %02x %02x %02x %02x %02x\n",
+			total_len, desc[0],
+			desc[1], desc[2], desc[3], desc[4], desc[5], desc[6],
+			desc[7], desc[8], desc[9], desc[10]);
+
+		if ((desc[0] != total_len) || /* descriptor length */
+		    (desc[1] != 0x5f) ||   /* vendor descriptor type */
+		    (desc[2] != 0x01) ||   /* version (2 bytes) */
+		    (desc[3] != 0x00) ||
+		    (desc[4] != total_len - 2)) /* length after type */
+			goto unrecognized;
+
+		desc_end = desc + total_len;
+		desc += 5; /* the fixed header we've already parsed */
+
+		while (desc < desc_end) {
+			u8 length;
+			u16 key;
+
+			key = le16_to_cpu(*((u16 *) desc));
+			desc += sizeof(u16);
+			length = *desc;
+			desc++;
+
+			switch (key) {
+			case 0x0200: { /* max_area */
+				u32 max_area;
+				max_area = le32_to_cpu(*((u32 *)desc));
+				pr_warn("DL chip limited to %d pixel modes\n",
+					max_area);
+				dev->sku_pixel_limit = max_area;
+				break;
+			}
+			default:
+				break;
+			}
+			desc += length;
+		}
+	} else {
+		pr_info("vendor descriptor not available (%d)\n", total_len);
+	}
+
+	goto success;
+
+unrecognized:
+	/* allow udlfb to load for now even if firmware unrecognized */
+	pr_err("Unrecognized vendor firmware descriptor\n");
+
+success:
+	kfree(buf);
+	return true;
+}
+
+static void dlfb_init_framebuffer_work(struct work_struct *work);
+
+static int dlfb_usb_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
+{
+	struct usb_device *usbdev;
+	struct dlfb_data *dev = NULL;
+	int retval = -ENOMEM;
+
+	/* usb initialization */
+
+	usbdev = interface_to_usbdev(interface);
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "dlfb_usb_probe: failed alloc of dev struct\n");
+		goto error;
+	}
+
+	kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
+
+	dev->udev = usbdev;
+	dev->gdev = &usbdev->dev; /* our generic struct device * */
+	usb_set_intfdata(interface, dev);
+
+	pr_info("%s %s - serial #%s\n",
+		usbdev->manufacturer, usbdev->product, usbdev->serial);
+	pr_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
+		usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
+		usbdev->descriptor.bcdDevice, dev);
+	pr_info("console enable=%d\n", console);
+	pr_info("fb_defio enable=%d\n", fb_defio);
+	pr_info("shadow enable=%d\n", shadow);
+
+	dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
+
+	if (!dlfb_parse_vendor_descriptor(dev, interface)) {
+		pr_err("firmware not recognized. Assume incompatible device\n");
+		goto error;
+	}
+
+	if (pixel_limit) {
+		pr_warn("DL chip limit of %d overridden"
+			" by module param to %d\n",
+			dev->sku_pixel_limit, pixel_limit);
+		dev->sku_pixel_limit = pixel_limit;
+	}
+
+
+	if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+		retval = -ENOMEM;
+		pr_err("dlfb_alloc_urb_list failed\n");
+		goto error;
+	}
+
+	kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
+
+	/* We don't register a new USB class. Our client interface is fbdev */
+
+	/* Workitem keep things fast & simple during USB enumeration */
+	INIT_DELAYED_WORK(&dev->init_framebuffer_work,
+			  dlfb_init_framebuffer_work);
+	schedule_delayed_work(&dev->init_framebuffer_work, 0);
+
+	return 0;
+
+error:
+	if (dev) {
+
+		kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
+		kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
+
+		/* dev has been deallocated. Do not dereference */
+	}
+
+	return retval;
+}
+
+static void dlfb_init_framebuffer_work(struct work_struct *work)
+{
+	struct dlfb_data *dev = container_of(work, struct dlfb_data,
+					     init_framebuffer_work.work);
+	struct fb_info *info;
+	int retval;
+	int i;
+
+	/* allocates framebuffer driver structure, not framebuffer memory */
+	info = framebuffer_alloc(0, dev->gdev);
+	if (!info) {
+		retval = -ENOMEM;
+		pr_err("framebuffer_alloc failed\n");
+		goto error;
+	}
+
+	dev->info = info;
+	info->par = dev;
+	info->pseudo_palette = dev->pseudo_palette;
+	info->fbops = &dlfb_ops;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0) {
+		pr_err("fb_alloc_cmap failed %x\n", retval);
+		goto error;
+	}
+
+	INIT_DELAYED_WORK(&dev->free_framebuffer_work,
+			  dlfb_free_framebuffer_work);
+
+	INIT_LIST_HEAD(&info->modelist);
+
+	retval = dlfb_setup_modes(dev, info, NULL, 0);
+	if (retval != 0) {
+		pr_err("unable to find common mode for display and adapter\n");
+		goto error;
+	}
+
+	/* ready to begin using device */
+
+	atomic_set(&dev->usb_active, 1);
+	dlfb_select_std_channel(dev);
+
+	dlfb_ops_check_var(&info->var, info);
+	dlfb_ops_set_par(info);
+
+	retval = register_framebuffer(info);
+	if (retval < 0) {
+		pr_err("register_framebuffer failed %d\n", retval);
+		goto error;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) {
+		retval = device_create_file(info->dev, &fb_device_attrs[i]);
+		if (retval) {
+			pr_warn("device_create_file failed %d\n", retval);
+		}
+	}
+
+	retval = device_create_bin_file(info->dev, &edid_attr);
+	if (retval) {
+		pr_warn("device_create_bin_file failed %d\n", retval);
+	}
+
+	pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
+			" Using %dK framebuffer memory\n", info->node,
+			info->var.xres, info->var.yres,
+			((dev->backing_buffer) ?
+			info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
+	return;
+
+error:
+	dlfb_free_framebuffer(dev);
+}
+
+static void dlfb_usb_disconnect(struct usb_interface *interface)
+{
+	struct dlfb_data *dev;
+	struct fb_info *info;
+	int i;
+
+	dev = usb_get_intfdata(interface);
+	info = dev->info;
+
+	pr_info("USB disconnect starting\n");
+
+	/* we virtualize until all fb clients release. Then we free */
+	dev->virtualized = true;
+
+	/* When non-active we'll update virtual framebuffer, but no new urbs */
+	atomic_set(&dev->usb_active, 0);
+
+	/* this function will wait for all in-flight urbs to complete */
+	dlfb_free_urb_list(dev);
+
+	if (info) {
+		/* remove udlfb's sysfs interfaces */
+		for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+			device_remove_file(info->dev, &fb_device_attrs[i]);
+		device_remove_bin_file(info->dev, &edid_attr);
+		unlink_framebuffer(info);
+	}
+
+	usb_set_intfdata(interface, NULL);
+	dev->udev = NULL;
+	dev->gdev = NULL;
+
+	/* if clients still have us open, will be freed on last close */
+	if (dev->fb_count == 0)
+		schedule_delayed_work(&dev->free_framebuffer_work, 0);
+
+	/* release reference taken by kref_init in probe() */
+	kref_put(&dev->kref, dlfb_free);
+
+	/* consider dlfb_data freed */
+
+	return;
+}
+
+static struct usb_driver dlfb_driver = {
+	.name = "udlfb",
+	.probe = dlfb_usb_probe,
+	.disconnect = dlfb_usb_disconnect,
+	.id_table = id_table,
+};
+
+module_usb_driver(dlfb_driver);
+
+static void dlfb_urb_completion(struct urb *urb)
+{
+	struct urb_node *unode = urb->context;
+	struct dlfb_data *dev = unode->dev;
+	unsigned long flags;
+
+	/* sync/async unlink faults aren't errors */
+	if (urb->status) {
+		if (!(urb->status == -ENOENT ||
+		    urb->status == -ECONNRESET ||
+		    urb->status == -ESHUTDOWN)) {
+			pr_err("%s - nonzero write bulk status received: %d\n",
+				__func__, urb->status);
+			atomic_set(&dev->lost_pixels, 1);
+		}
+	}
+
+	urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
+
+	spin_lock_irqsave(&dev->urbs.lock, flags);
+	list_add_tail(&unode->entry, &dev->urbs.list);
+	dev->urbs.available++;
+	spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+	/*
+	 * When using fb_defio, we deadlock if up() is called
+	 * while another is waiting. So queue to another process.
+	 */
+	if (fb_defio)
+		schedule_delayed_work(&unode->release_urb_work, 0);
+	else
+		up(&dev->urbs.limit_sem);
+}
+
+static void dlfb_free_urb_list(struct dlfb_data *dev)
+{
+	int count = dev->urbs.count;
+	struct list_head *node;
+	struct urb_node *unode;
+	struct urb *urb;
+	int ret;
+	unsigned long flags;
+
+	pr_notice("Freeing all render urbs\n");
+
+	/* keep waiting and freeing, until we've got 'em all */
+	while (count--) {
+
+		/* Getting interrupted means a leak, but ok at disconnect */
+		ret = down_interruptible(&dev->urbs.limit_sem);
+		if (ret)
+			break;
+
+		spin_lock_irqsave(&dev->urbs.lock, flags);
+
+		node = dev->urbs.list.next; /* have reserved one with sem */
+		list_del_init(node);
+
+		spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+		unode = list_entry(node, struct urb_node, entry);
+		urb = unode->urb;
+
+		/* Free each separately allocated piece */
+		usb_free_coherent(urb->dev, dev->urbs.size,
+				  urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+		kfree(node);
+	}
+
+	dev->urbs.count = 0;
+}
+
+static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
+{
+	int i = 0;
+	struct urb *urb;
+	struct urb_node *unode;
+	char *buf;
+
+	spin_lock_init(&dev->urbs.lock);
+
+	dev->urbs.size = size;
+	INIT_LIST_HEAD(&dev->urbs.list);
+
+	while (i < count) {
+		unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
+		if (!unode)
+			break;
+		unode->dev = dev;
+
+		INIT_DELAYED_WORK(&unode->release_urb_work,
+			  dlfb_release_urb_work);
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			kfree(unode);
+			break;
+		}
+		unode->urb = urb;
+
+		buf = usb_alloc_coherent(dev->udev, MAX_TRANSFER, GFP_KERNEL,
+					 &urb->transfer_dma);
+		if (!buf) {
+			kfree(unode);
+			usb_free_urb(urb);
+			break;
+		}
+
+		/* urb->transfer_buffer_length set to actual before submit */
+		usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
+			buf, size, dlfb_urb_completion, unode);
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		list_add_tail(&unode->entry, &dev->urbs.list);
+
+		i++;
+	}
+
+	sema_init(&dev->urbs.limit_sem, i);
+	dev->urbs.count = i;
+	dev->urbs.available = i;
+
+	pr_notice("allocated %d %d byte urbs\n", i, (int) size);
+
+	return i;
+}
+
+static struct urb *dlfb_get_urb(struct dlfb_data *dev)
+{
+	int ret = 0;
+	struct list_head *entry;
+	struct urb_node *unode;
+	struct urb *urb = NULL;
+	unsigned long flags;
+
+	/* Wait for an in-flight buffer to complete and get re-queued */
+	ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
+	if (ret) {
+		atomic_set(&dev->lost_pixels, 1);
+		pr_warn("wait for urb interrupted: %x available: %d\n",
+		       ret, dev->urbs.available);
+		goto error;
+	}
+
+	spin_lock_irqsave(&dev->urbs.lock, flags);
+
+	BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
+	entry = dev->urbs.list.next;
+	list_del_init(entry);
+	dev->urbs.available--;
+
+	spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+	unode = list_entry(entry, struct urb_node, entry);
+	urb = unode->urb;
+
+error:
+	return urb;
+}
+
+static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
+{
+	int ret;
+
+	BUG_ON(len > dev->urbs.size);
+
+	urb->transfer_buffer_length = len; /* set to actual payload len */
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret) {
+		dlfb_urb_completion(urb); /* because no one else will */
+		atomic_set(&dev->lost_pixels, 1);
+		pr_err("usb_submit_urb error %x\n", ret);
+	}
+	return ret;
+}
+
+module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(console, "Allow fbcon to open framebuffer");
+
+module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
+
+module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
+
+module_param(pixel_limit, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(pixel_limit, "Force limit on max mode (in x*y pixels)");
+
+MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
+	      "Jaya Kumar <jayakumar.lkml@gmail.com>, "
+	      "Bernie Thompson <bernie@plugable.com>");
+MODULE_DESCRIPTION("DisplayLink kernel framebuffer driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c
new file mode 100644
index 000000000000..509d452e8f91
--- /dev/null
+++ b/drivers/video/fbdev/uvesafb.c
@@ -0,0 +1,2028 @@
+/*
+ * A framebuffer driver for VBE 2.0+ compliant video cards
+ *
+ * (c) 2007 Michal Januszewski <spock@gentoo.org>
+ *     Loosely based upon the vesafb driver.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/connector.h>
+#include <linux/random.h>
+#include <linux/platform_device.h>
+#include <linux/limits.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <video/edid.h>
+#include <video/uvesafb.h>
+#ifdef CONFIG_X86
+#include <video/vga.h>
+#endif
+#include "edid.h"
+
+static struct cb_id uvesafb_cn_id = {
+	.idx = CN_IDX_V86D,
+	.val = CN_VAL_V86D_UVESAFB
+};
+static char v86d_path[PATH_MAX] = "/sbin/v86d";
+static char v86d_started;	/* has v86d been started by uvesafb? */
+
+static struct fb_fix_screeninfo uvesafb_fix = {
+	.id	= "VESA VGA",
+	.type	= FB_TYPE_PACKED_PIXELS,
+	.accel	= FB_ACCEL_NONE,
+	.visual = FB_VISUAL_TRUECOLOR,
+};
+
+static int mtrr		= 3;	/* enable mtrr by default */
+static bool blank	= 1;	/* enable blanking by default */
+static int ypan		= 1;	/* 0: scroll, 1: ypan, 2: ywrap */
+static bool pmi_setpal	= true; /* use PMI for palette changes */
+static bool nocrtc;		/* ignore CRTC settings */
+static bool noedid;		/* don't try DDC transfers */
+static int vram_remap;		/* set amt. of memory to be used */
+static int vram_total;		/* set total amount of memory */
+static u16 maxclk;		/* maximum pixel clock */
+static u16 maxvf;		/* maximum vertical frequency */
+static u16 maxhf;		/* maximum horizontal frequency */
+static u16 vbemode;		/* force use of a specific VBE mode */
+static char *mode_option;
+static u8  dac_width	= 6;
+
+static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
+static DEFINE_MUTEX(uvfb_lock);
+
+/*
+ * A handler for replies from userspace.
+ *
+ * Make sure each message passes consistency checks and if it does,
+ * find the kernel part of the task struct, copy the registers and
+ * the buffer contents and then complete the task.
+ */
+static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+{
+	struct uvesafb_task *utask;
+	struct uvesafb_ktask *task;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return;
+
+	if (msg->seq >= UVESAFB_TASKS_MAX)
+		return;
+
+	mutex_lock(&uvfb_lock);
+	task = uvfb_tasks[msg->seq];
+
+	if (!task || msg->ack != task->ack) {
+		mutex_unlock(&uvfb_lock);
+		return;
+	}
+
+	utask = (struct uvesafb_task *)msg->data;
+
+	/* Sanity checks for the buffer length. */
+	if (task->t.buf_len < utask->buf_len ||
+	    utask->buf_len > msg->len - sizeof(*utask)) {
+		mutex_unlock(&uvfb_lock);
+		return;
+	}
+
+	uvfb_tasks[msg->seq] = NULL;
+	mutex_unlock(&uvfb_lock);
+
+	memcpy(&task->t, utask, sizeof(*utask));
+
+	if (task->t.buf_len && task->buf)
+		memcpy(task->buf, utask + 1, task->t.buf_len);
+
+	complete(task->done);
+	return;
+}
+
+static int uvesafb_helper_start(void)
+{
+	char *envp[] = {
+		"HOME=/",
+		"PATH=/sbin:/bin",
+		NULL,
+	};
+
+	char *argv[] = {
+		v86d_path,
+		NULL,
+	};
+
+	return call_usermodehelper(v86d_path, argv, envp, UMH_WAIT_PROC);
+}
+
+/*
+ * Execute a uvesafb task.
+ *
+ * Returns 0 if the task is executed successfully.
+ *
+ * A message sent to the userspace consists of the uvesafb_task
+ * struct and (optionally) a buffer. The uvesafb_task struct is
+ * a simplified version of uvesafb_ktask (its kernel counterpart)
+ * containing only the register values, flags and the length of
+ * the buffer.
+ *
+ * Each message is assigned a sequence number (increased linearly)
+ * and a random ack number. The sequence number is used as a key
+ * for the uvfb_tasks array which holds pointers to uvesafb_ktask
+ * structs for all requests.
+ */
+static int uvesafb_exec(struct uvesafb_ktask *task)
+{
+	static int seq;
+	struct cn_msg *m;
+	int err;
+	int len = sizeof(task->t) + task->t.buf_len;
+
+	/*
+	 * Check whether the message isn't longer than the maximum
+	 * allowed by connector.
+	 */
+	if (sizeof(*m) + len > CONNECTOR_MAX_MSG_SIZE) {
+		printk(KERN_WARNING "uvesafb: message too long (%d), "
+			"can't execute task\n", (int)(sizeof(*m) + len));
+		return -E2BIG;
+	}
+
+	m = kzalloc(sizeof(*m) + len, GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	init_completion(task->done);
+
+	memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id));
+	m->seq = seq;
+	m->len = len;
+	m->ack = prandom_u32();
+
+	/* uvesafb_task structure */
+	memcpy(m + 1, &task->t, sizeof(task->t));
+
+	/* Buffer */
+	memcpy((u8 *)(m + 1) + sizeof(task->t), task->buf, task->t.buf_len);
+
+	/*
+	 * Save the message ack number so that we can find the kernel
+	 * part of this task when a reply is received from userspace.
+	 */
+	task->ack = m->ack;
+
+	mutex_lock(&uvfb_lock);
+
+	/* If all slots are taken -- bail out. */
+	if (uvfb_tasks[seq]) {
+		mutex_unlock(&uvfb_lock);
+		err = -EBUSY;
+		goto out;
+	}
+
+	/* Save a pointer to the kernel part of the task struct. */
+	uvfb_tasks[seq] = task;
+	mutex_unlock(&uvfb_lock);
+
+	err = cn_netlink_send(m, 0, 0, GFP_KERNEL);
+	if (err == -ESRCH) {
+		/*
+		 * Try to start the userspace helper if sending
+		 * the request failed the first time.
+		 */
+		err = uvesafb_helper_start();
+		if (err) {
+			printk(KERN_ERR "uvesafb: failed to execute %s\n",
+					v86d_path);
+			printk(KERN_ERR "uvesafb: make sure that the v86d "
+					"helper is installed and executable\n");
+		} else {
+			v86d_started = 1;
+			err = cn_netlink_send(m, 0, 0, gfp_any());
+			if (err == -ENOBUFS)
+				err = 0;
+		}
+	} else if (err == -ENOBUFS)
+		err = 0;
+
+	if (!err && !(task->t.flags & TF_EXIT))
+		err = !wait_for_completion_timeout(task->done,
+				msecs_to_jiffies(UVESAFB_TIMEOUT));
+
+	mutex_lock(&uvfb_lock);
+	uvfb_tasks[seq] = NULL;
+	mutex_unlock(&uvfb_lock);
+
+	seq++;
+	if (seq >= UVESAFB_TASKS_MAX)
+		seq = 0;
+out:
+	kfree(m);
+	return err;
+}
+
+/*
+ * Free a uvesafb_ktask struct.
+ */
+static void uvesafb_free(struct uvesafb_ktask *task)
+{
+	if (task) {
+		kfree(task->done);
+		kfree(task);
+	}
+}
+
+/*
+ * Prepare a uvesafb_ktask struct to be used again.
+ */
+static void uvesafb_reset(struct uvesafb_ktask *task)
+{
+	struct completion *cpl = task->done;
+
+	memset(task, 0, sizeof(*task));
+	task->done = cpl;
+}
+
+/*
+ * Allocate and prepare a uvesafb_ktask struct.
+ */
+static struct uvesafb_ktask *uvesafb_prep(void)
+{
+	struct uvesafb_ktask *task;
+
+	task = kzalloc(sizeof(*task), GFP_KERNEL);
+	if (task) {
+		task->done = kzalloc(sizeof(*task->done), GFP_KERNEL);
+		if (!task->done) {
+			kfree(task);
+			task = NULL;
+		}
+	}
+	return task;
+}
+
+static void uvesafb_setup_var(struct fb_var_screeninfo *var,
+		struct fb_info *info, struct vbe_mode_ib *mode)
+{
+	struct uvesafb_par *par = info->par;
+
+	var->vmode = FB_VMODE_NONINTERLACED;
+	var->sync = FB_SYNC_VERT_HIGH_ACT;
+
+	var->xres = mode->x_res;
+	var->yres = mode->y_res;
+	var->xres_virtual = mode->x_res;
+	var->yres_virtual = (par->ypan) ?
+			info->fix.smem_len / mode->bytes_per_scan_line :
+			mode->y_res;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->bits_per_pixel = mode->bits_per_pixel;
+
+	if (var->bits_per_pixel == 15)
+		var->bits_per_pixel = 16;
+
+	if (var->bits_per_pixel > 8) {
+		var->red.offset    = mode->red_off;
+		var->red.length    = mode->red_len;
+		var->green.offset  = mode->green_off;
+		var->green.length  = mode->green_len;
+		var->blue.offset   = mode->blue_off;
+		var->blue.length   = mode->blue_len;
+		var->transp.offset = mode->rsvd_off;
+		var->transp.length = mode->rsvd_len;
+	} else {
+		var->red.offset    = 0;
+		var->green.offset  = 0;
+		var->blue.offset   = 0;
+		var->transp.offset = 0;
+
+		var->red.length    = 8;
+		var->green.length  = 8;
+		var->blue.length   = 8;
+		var->transp.length = 0;
+	}
+}
+
+static int uvesafb_vbe_find_mode(struct uvesafb_par *par,
+		int xres, int yres, int depth, unsigned char flags)
+{
+	int i, match = -1, h = 0, d = 0x7fffffff;
+
+	for (i = 0; i < par->vbe_modes_cnt; i++) {
+		h = abs(par->vbe_modes[i].x_res - xres) +
+		    abs(par->vbe_modes[i].y_res - yres) +
+		    abs(depth - par->vbe_modes[i].depth);
+
+		/*
+		 * We have an exact match in terms of resolution
+		 * and depth.
+		 */
+		if (h == 0)
+			return i;
+
+		if (h < d || (h == d && par->vbe_modes[i].depth > depth)) {
+			d = h;
+			match = i;
+		}
+	}
+	i = 1;
+
+	if (flags & UVESAFB_EXACT_DEPTH &&
+			par->vbe_modes[match].depth != depth)
+		i = 0;
+
+	if (flags & UVESAFB_EXACT_RES && d > 24)
+		i = 0;
+
+	if (i != 0)
+		return match;
+	else
+		return -1;
+}
+
+static u8 *uvesafb_vbe_state_save(struct uvesafb_par *par)
+{
+	struct uvesafb_ktask *task;
+	u8 *state;
+	int err;
+
+	if (!par->vbe_state_size)
+		return NULL;
+
+	state = kmalloc(par->vbe_state_size, GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+
+	task = uvesafb_prep();
+	if (!task) {
+		kfree(state);
+		return NULL;
+	}
+
+	task->t.regs.eax = 0x4f04;
+	task->t.regs.ecx = 0x000f;
+	task->t.regs.edx = 0x0001;
+	task->t.flags = TF_BUF_RET | TF_BUF_ESBX;
+	task->t.buf_len = par->vbe_state_size;
+	task->buf = state;
+	err = uvesafb_exec(task);
+
+	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+		printk(KERN_WARNING "uvesafb: VBE get state call "
+				"failed (eax=0x%x, err=%d)\n",
+				task->t.regs.eax, err);
+		kfree(state);
+		state = NULL;
+	}
+
+	uvesafb_free(task);
+	return state;
+}
+
+static void uvesafb_vbe_state_restore(struct uvesafb_par *par, u8 *state_buf)
+{
+	struct uvesafb_ktask *task;
+	int err;
+
+	if (!state_buf)
+		return;
+
+	task = uvesafb_prep();
+	if (!task)
+		return;
+
+	task->t.regs.eax = 0x4f04;
+	task->t.regs.ecx = 0x000f;
+	task->t.regs.edx = 0x0002;
+	task->t.buf_len = par->vbe_state_size;
+	task->t.flags = TF_BUF_ESBX;
+	task->buf = state_buf;
+
+	err = uvesafb_exec(task);
+	if (err || (task->t.regs.eax & 0xffff) != 0x004f)
+		printk(KERN_WARNING "uvesafb: VBE state restore call "
+				"failed (eax=0x%x, err=%d)\n",
+				task->t.regs.eax, err);
+
+	uvesafb_free(task);
+}
+
+static int uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
+			       struct uvesafb_par *par)
+{
+	int err;
+
+	task->t.regs.eax = 0x4f00;
+	task->t.flags = TF_VBEIB;
+	task->t.buf_len = sizeof(struct vbe_ib);
+	task->buf = &par->vbe_ib;
+	strncpy(par->vbe_ib.vbe_signature, "VBE2", 4);
+
+	err = uvesafb_exec(task);
+	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+		printk(KERN_ERR "uvesafb: Getting VBE info block failed "
+				"(eax=0x%x, err=%d)\n", (u32)task->t.regs.eax,
+				err);
+		return -EINVAL;
+	}
+
+	if (par->vbe_ib.vbe_version < 0x0200) {
+		printk(KERN_ERR "uvesafb: Sorry, pre-VBE 2.0 cards are "
+				"not supported.\n");
+		return -EINVAL;
+	}
+
+	if (!par->vbe_ib.mode_list_ptr) {
+		printk(KERN_ERR "uvesafb: Missing mode list!\n");
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "uvesafb: ");
+
+	/*
+	 * Convert string pointers and the mode list pointer into
+	 * usable addresses. Print informational messages about the
+	 * video adapter and its vendor.
+	 */
+	if (par->vbe_ib.oem_vendor_name_ptr)
+		printk("%s, ",
+			((char *)task->buf) + par->vbe_ib.oem_vendor_name_ptr);
+
+	if (par->vbe_ib.oem_product_name_ptr)
+		printk("%s, ",
+			((char *)task->buf) + par->vbe_ib.oem_product_name_ptr);
+
+	if (par->vbe_ib.oem_product_rev_ptr)
+		printk("%s, ",
+			((char *)task->buf) + par->vbe_ib.oem_product_rev_ptr);
+
+	if (par->vbe_ib.oem_string_ptr)
+		printk("OEM: %s, ",
+			((char *)task->buf) + par->vbe_ib.oem_string_ptr);
+
+	printk("VBE v%d.%d\n", ((par->vbe_ib.vbe_version & 0xff00) >> 8),
+			par->vbe_ib.vbe_version & 0xff);
+
+	return 0;
+}
+
+static int uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
+				struct uvesafb_par *par)
+{
+	int off = 0, err;
+	u16 *mode;
+
+	par->vbe_modes_cnt = 0;
+
+	/* Count available modes. */
+	mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
+	while (*mode != 0xffff) {
+		par->vbe_modes_cnt++;
+		mode++;
+	}
+
+	par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) *
+				par->vbe_modes_cnt, GFP_KERNEL);
+	if (!par->vbe_modes)
+		return -ENOMEM;
+
+	/* Get info about all available modes. */
+	mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
+	while (*mode != 0xffff) {
+		struct vbe_mode_ib *mib;
+
+		uvesafb_reset(task);
+		task->t.regs.eax = 0x4f01;
+		task->t.regs.ecx = (u32) *mode;
+		task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
+		task->t.buf_len = sizeof(struct vbe_mode_ib);
+		task->buf = par->vbe_modes + off;
+
+		err = uvesafb_exec(task);
+		if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+			printk(KERN_WARNING "uvesafb: Getting mode info block "
+				"for mode 0x%x failed (eax=0x%x, err=%d)\n",
+				*mode, (u32)task->t.regs.eax, err);
+			mode++;
+			par->vbe_modes_cnt--;
+			continue;
+		}
+
+		mib = task->buf;
+		mib->mode_id = *mode;
+
+		/*
+		 * We only want modes that are supported with the current
+		 * hardware configuration, color, graphics and that have
+		 * support for the LFB.
+		 */
+		if ((mib->mode_attr & VBE_MODE_MASK) == VBE_MODE_MASK &&
+				 mib->bits_per_pixel >= 8)
+			off++;
+		else
+			par->vbe_modes_cnt--;
+
+		mode++;
+		mib->depth = mib->red_len + mib->green_len + mib->blue_len;
+
+		/*
+		 * Handle 8bpp modes and modes with broken color component
+		 * lengths.
+		 */
+		if (mib->depth == 0 || (mib->depth == 24 &&
+					mib->bits_per_pixel == 32))
+			mib->depth = mib->bits_per_pixel;
+	}
+
+	if (par->vbe_modes_cnt > 0)
+		return 0;
+	else
+		return -EINVAL;
+}
+
+/*
+ * The Protected Mode Interface is 32-bit x86 code, so we only run it on
+ * x86 and not x86_64.
+ */
+#ifdef CONFIG_X86_32
+static int uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
+			      struct uvesafb_par *par)
+{
+	int i, err;
+
+	uvesafb_reset(task);
+	task->t.regs.eax = 0x4f0a;
+	task->t.regs.ebx = 0x0;
+	err = uvesafb_exec(task);
+
+	if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) {
+		par->pmi_setpal = par->ypan = 0;
+	} else {
+		par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4)
+						+ task->t.regs.edi);
+		par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1];
+		par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2];
+		printk(KERN_INFO "uvesafb: protected mode interface info at "
+				 "%04x:%04x\n",
+				 (u16)task->t.regs.es, (u16)task->t.regs.edi);
+		printk(KERN_INFO "uvesafb: pmi: set display start = %p, "
+				 "set palette = %p\n", par->pmi_start,
+				 par->pmi_pal);
+
+		if (par->pmi_base[3]) {
+			printk(KERN_INFO "uvesafb: pmi: ports = ");
+			for (i = par->pmi_base[3]/2;
+					par->pmi_base[i] != 0xffff; i++)
+				printk("%x ", par->pmi_base[i]);
+			printk("\n");
+
+			if (par->pmi_base[i] != 0xffff) {
+				printk(KERN_INFO "uvesafb: can't handle memory"
+						 " requests, pmi disabled\n");
+				par->ypan = par->pmi_setpal = 0;
+			}
+		}
+	}
+	return 0;
+}
+#endif /* CONFIG_X86_32 */
+
+/*
+ * Check whether a video mode is supported by the Video BIOS and is
+ * compatible with the monitor limits.
+ */
+static int uvesafb_is_valid_mode(struct fb_videomode *mode,
+				 struct fb_info *info)
+{
+	if (info->monspecs.gtf) {
+		fb_videomode_to_var(&info->var, mode);
+		if (fb_validate_mode(&info->var, info))
+			return 0;
+	}
+
+	if (uvesafb_vbe_find_mode(info->par, mode->xres, mode->yres, 8,
+				UVESAFB_EXACT_RES) == -1)
+		return 0;
+
+	return 1;
+}
+
+static int uvesafb_vbe_getedid(struct uvesafb_ktask *task, struct fb_info *info)
+{
+	struct uvesafb_par *par = info->par;
+	int err = 0;
+
+	if (noedid || par->vbe_ib.vbe_version < 0x0300)
+		return -EINVAL;
+
+	task->t.regs.eax = 0x4f15;
+	task->t.regs.ebx = 0;
+	task->t.regs.ecx = 0;
+	task->t.buf_len = 0;
+	task->t.flags = 0;
+
+	err = uvesafb_exec(task);
+
+	if ((task->t.regs.eax & 0xffff) != 0x004f || err)
+		return -EINVAL;
+
+	if ((task->t.regs.ebx & 0x3) == 3) {
+		printk(KERN_INFO "uvesafb: VBIOS/hardware supports both "
+				 "DDC1 and DDC2 transfers\n");
+	} else if ((task->t.regs.ebx & 0x3) == 2) {
+		printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC2 "
+				 "transfers\n");
+	} else if ((task->t.regs.ebx & 0x3) == 1) {
+		printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC1 "
+				 "transfers\n");
+	} else {
+		printk(KERN_INFO "uvesafb: VBIOS/hardware doesn't support "
+				 "DDC transfers\n");
+		return -EINVAL;
+	}
+
+	task->t.regs.eax = 0x4f15;
+	task->t.regs.ebx = 1;
+	task->t.regs.ecx = task->t.regs.edx = 0;
+	task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
+	task->t.buf_len = EDID_LENGTH;
+	task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!task->buf)
+		return -ENOMEM;
+
+	err = uvesafb_exec(task);
+
+	if ((task->t.regs.eax & 0xffff) == 0x004f && !err) {
+		fb_edid_to_monspecs(task->buf, &info->monspecs);
+
+		if (info->monspecs.vfmax && info->monspecs.hfmax) {
+			/*
+			 * If the maximum pixel clock wasn't specified in
+			 * the EDID block, set it to 300 MHz.
+			 */
+			if (info->monspecs.dclkmax == 0)
+				info->monspecs.dclkmax = 300 * 1000000;
+			info->monspecs.gtf = 1;
+		}
+	} else {
+		err = -EINVAL;
+	}
+
+	kfree(task->buf);
+	return err;
+}
+
+static void uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
+				    struct fb_info *info)
+{
+	struct uvesafb_par *par = info->par;
+	int i;
+
+	memset(&info->monspecs, 0, sizeof(info->monspecs));
+
+	/*
+	 * If we don't get all necessary data from the EDID block,
+	 * mark it as incompatible with the GTF and set nocrtc so
+	 * that we always use the default BIOS refresh rate.
+	 */
+	if (uvesafb_vbe_getedid(task, info)) {
+		info->monspecs.gtf = 0;
+		par->nocrtc = 1;
+	}
+
+	/* Kernel command line overrides. */
+	if (maxclk)
+		info->monspecs.dclkmax = maxclk * 1000000;
+	if (maxvf)
+		info->monspecs.vfmax = maxvf;
+	if (maxhf)
+		info->monspecs.hfmax = maxhf * 1000;
+
+	/*
+	 * In case DDC transfers are not supported, the user can provide
+	 * monitor limits manually. Lower limits are set to "safe" values.
+	 */
+	if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) {
+		info->monspecs.dclkmin = 0;
+		info->monspecs.vfmin = 60;
+		info->monspecs.hfmin = 29000;
+		info->monspecs.gtf = 1;
+		par->nocrtc = 0;
+	}
+
+	if (info->monspecs.gtf)
+		printk(KERN_INFO
+			"uvesafb: monitor limits: vf = %d Hz, hf = %d kHz, "
+			"clk = %d MHz\n", info->monspecs.vfmax,
+			(int)(info->monspecs.hfmax / 1000),
+			(int)(info->monspecs.dclkmax / 1000000));
+	else
+		printk(KERN_INFO "uvesafb: no monitor limits have been set, "
+				 "default refresh rate will be used\n");
+
+	/* Add VBE modes to the modelist. */
+	for (i = 0; i < par->vbe_modes_cnt; i++) {
+		struct fb_var_screeninfo var;
+		struct vbe_mode_ib *mode;
+		struct fb_videomode vmode;
+
+		mode = &par->vbe_modes[i];
+		memset(&var, 0, sizeof(var));
+
+		var.xres = mode->x_res;
+		var.yres = mode->y_res;
+
+		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &var, info);
+		fb_var_to_videomode(&vmode, &var);
+		fb_add_videomode(&vmode, &info->modelist);
+	}
+
+	/* Add valid VESA modes to our modelist. */
+	for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+		if (uvesafb_is_valid_mode((struct fb_videomode *)
+						&vesa_modes[i], info))
+			fb_add_videomode(&vesa_modes[i], &info->modelist);
+	}
+
+	for (i = 0; i < info->monspecs.modedb_len; i++) {
+		if (uvesafb_is_valid_mode(&info->monspecs.modedb[i], info))
+			fb_add_videomode(&info->monspecs.modedb[i],
+					&info->modelist);
+	}
+
+	return;
+}
+
+static void uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
+				     struct uvesafb_par *par)
+{
+	int err;
+
+	uvesafb_reset(task);
+
+	/*
+	 * Get the VBE state buffer size. We want all available
+	 * hardware state data (CL = 0x0f).
+	 */
+	task->t.regs.eax = 0x4f04;
+	task->t.regs.ecx = 0x000f;
+	task->t.regs.edx = 0x0000;
+	task->t.flags = 0;
+
+	err = uvesafb_exec(task);
+
+	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+		printk(KERN_WARNING "uvesafb: VBE state buffer size "
+			"cannot be determined (eax=0x%x, err=%d)\n",
+			task->t.regs.eax, err);
+		par->vbe_state_size = 0;
+		return;
+	}
+
+	par->vbe_state_size = 64 * (task->t.regs.ebx & 0xffff);
+}
+
+static int uvesafb_vbe_init(struct fb_info *info)
+{
+	struct uvesafb_ktask *task = NULL;
+	struct uvesafb_par *par = info->par;
+	int err;
+
+	task = uvesafb_prep();
+	if (!task)
+		return -ENOMEM;
+
+	err = uvesafb_vbe_getinfo(task, par);
+	if (err)
+		goto out;
+
+	err = uvesafb_vbe_getmodes(task, par);
+	if (err)
+		goto out;
+
+	par->nocrtc = nocrtc;
+#ifdef CONFIG_X86_32
+	par->pmi_setpal = pmi_setpal;
+	par->ypan = ypan;
+
+	if (par->pmi_setpal || par->ypan) {
+		if (__supported_pte_mask & _PAGE_NX) {
+			par->pmi_setpal = par->ypan = 0;
+			printk(KERN_WARNING "uvesafb: NX protection is active, "
+					    "better not use the PMI.\n");
+		} else {
+			uvesafb_vbe_getpmi(task, par);
+		}
+	}
+#else
+	/* The protected mode interface is not available on non-x86. */
+	par->pmi_setpal = par->ypan = 0;
+#endif
+
+	INIT_LIST_HEAD(&info->modelist);
+	uvesafb_vbe_getmonspecs(task, info);
+	uvesafb_vbe_getstatesize(task, par);
+
+out:	uvesafb_free(task);
+	return err;
+}
+
+static int uvesafb_vbe_init_mode(struct fb_info *info)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *mode;
+	struct uvesafb_par *par = info->par;
+	int i, modeid;
+
+	/* Has the user requested a specific VESA mode? */
+	if (vbemode) {
+		for (i = 0; i < par->vbe_modes_cnt; i++) {
+			if (par->vbe_modes[i].mode_id == vbemode) {
+				modeid = i;
+				uvesafb_setup_var(&info->var, info,
+						&par->vbe_modes[modeid]);
+				fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
+						&info->var, info);
+				/*
+				 * With pixclock set to 0, the default BIOS
+				 * timings will be used in set_par().
+				 */
+				info->var.pixclock = 0;
+				goto gotmode;
+			}
+		}
+		printk(KERN_INFO "uvesafb: requested VBE mode 0x%x is "
+				 "unavailable\n", vbemode);
+		vbemode = 0;
+	}
+
+	/* Count the modes in the modelist */
+	i = 0;
+	list_for_each(pos, &info->modelist)
+		i++;
+
+	/*
+	 * Convert the modelist into a modedb so that we can use it with
+	 * fb_find_mode().
+	 */
+	mode = kzalloc(i * sizeof(*mode), GFP_KERNEL);
+	if (mode) {
+		i = 0;
+		list_for_each(pos, &info->modelist) {
+			modelist = list_entry(pos, struct fb_modelist, list);
+			mode[i] = modelist->mode;
+			i++;
+		}
+
+		if (!mode_option)
+			mode_option = UVESAFB_DEFAULT_MODE;
+
+		i = fb_find_mode(&info->var, info, mode_option, mode, i,
+			NULL, 8);
+
+		kfree(mode);
+	}
+
+	/* fb_find_mode() failed */
+	if (i == 0) {
+		info->var.xres = 640;
+		info->var.yres = 480;
+		mode = (struct fb_videomode *)
+				fb_find_best_mode(&info->var, &info->modelist);
+
+		if (mode) {
+			fb_videomode_to_var(&info->var, mode);
+		} else {
+			modeid = par->vbe_modes[0].mode_id;
+			uvesafb_setup_var(&info->var, info,
+					&par->vbe_modes[modeid]);
+			fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
+					&info->var, info);
+
+			goto gotmode;
+		}
+	}
+
+	/* Look for a matching VBE mode. */
+	modeid = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres,
+			info->var.bits_per_pixel, UVESAFB_EXACT_RES);
+
+	if (modeid == -1)
+		return -EINVAL;
+
+	uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]);
+
+gotmode:
+	/*
+	 * If we are not VBE3.0+ compliant, we're done -- the BIOS will
+	 * ignore our timings anyway.
+	 */
+	if (par->vbe_ib.vbe_version < 0x0300 || par->nocrtc)
+		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
+					&info->var, info);
+
+	return modeid;
+}
+
+static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count,
+		int start, struct fb_info *info)
+{
+	struct uvesafb_ktask *task;
+#ifdef CONFIG_X86
+	struct uvesafb_par *par = info->par;
+	int i = par->mode_idx;
+#endif
+	int err = 0;
+
+	/*
+	 * We support palette modifications for 8 bpp modes only, so
+	 * there can never be more than 256 entries.
+	 */
+	if (start + count > 256)
+		return -EINVAL;
+
+#ifdef CONFIG_X86
+	/* Use VGA registers if mode is VGA-compatible. */
+	if (i >= 0 && i < par->vbe_modes_cnt &&
+	    par->vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) {
+		for (i = 0; i < count; i++) {
+			outb_p(start + i,        dac_reg);
+			outb_p(entries[i].red,   dac_val);
+			outb_p(entries[i].green, dac_val);
+			outb_p(entries[i].blue,  dac_val);
+		}
+	}
+#ifdef CONFIG_X86_32
+	else if (par->pmi_setpal) {
+		__asm__ __volatile__(
+		"call *(%%esi)"
+		: /* no return value */
+		: "a" (0x4f09),         /* EAX */
+		  "b" (0),              /* EBX */
+		  "c" (count),          /* ECX */
+		  "d" (start),          /* EDX */
+		  "D" (entries),        /* EDI */
+		  "S" (&par->pmi_pal)); /* ESI */
+	}
+#endif /* CONFIG_X86_32 */
+	else
+#endif /* CONFIG_X86 */
+	{
+		task = uvesafb_prep();
+		if (!task)
+			return -ENOMEM;
+
+		task->t.regs.eax = 0x4f09;
+		task->t.regs.ebx = 0x0;
+		task->t.regs.ecx = count;
+		task->t.regs.edx = start;
+		task->t.flags = TF_BUF_ESDI;
+		task->t.buf_len = sizeof(struct uvesafb_pal_entry) * count;
+		task->buf = entries;
+
+		err = uvesafb_exec(task);
+		if ((task->t.regs.eax & 0xffff) != 0x004f)
+			err = 1;
+
+		uvesafb_free(task);
+	}
+	return err;
+}
+
+static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+		unsigned blue, unsigned transp,
+		struct fb_info *info)
+{
+	struct uvesafb_pal_entry entry;
+	int shift = 16 - dac_width;
+	int err = 0;
+
+	if (regno >= info->cmap.len)
+		return -EINVAL;
+
+	if (info->var.bits_per_pixel == 8) {
+		entry.red   = red   >> shift;
+		entry.green = green >> shift;
+		entry.blue  = blue  >> shift;
+		entry.pad   = 0;
+
+		err = uvesafb_setpalette(&entry, 1, regno, info);
+	} else if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 16:
+			if (info->var.red.offset == 10) {
+				/* 1:5:5:5 */
+				((u32 *) (info->pseudo_palette))[regno] =
+						((red   & 0xf800) >>  1) |
+						((green & 0xf800) >>  6) |
+						((blue  & 0xf800) >> 11);
+			} else {
+				/* 0:5:6:5 */
+				((u32 *) (info->pseudo_palette))[regno] =
+						((red   & 0xf800)      ) |
+						((green & 0xfc00) >>  5) |
+						((blue  & 0xf800) >> 11);
+			}
+			break;
+
+		case 24:
+		case 32:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((u32 *)(info->pseudo_palette))[regno] =
+				(red   << info->var.red.offset)   |
+				(green << info->var.green.offset) |
+				(blue  << info->var.blue.offset);
+			break;
+		}
+	}
+	return err;
+}
+
+static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	struct uvesafb_pal_entry *entries;
+	int shift = 16 - dac_width;
+	int i, err = 0;
+
+	if (info->var.bits_per_pixel == 8) {
+		if (cmap->start + cmap->len > info->cmap.start +
+		    info->cmap.len || cmap->start < info->cmap.start)
+			return -EINVAL;
+
+		entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL);
+		if (!entries)
+			return -ENOMEM;
+
+		for (i = 0; i < cmap->len; i++) {
+			entries[i].red   = cmap->red[i]   >> shift;
+			entries[i].green = cmap->green[i] >> shift;
+			entries[i].blue  = cmap->blue[i]  >> shift;
+			entries[i].pad   = 0;
+		}
+		err = uvesafb_setpalette(entries, cmap->len, cmap->start, info);
+		kfree(entries);
+	} else {
+		/*
+		 * For modes with bpp > 8, we only set the pseudo palette in
+		 * the fb_info struct. We rely on uvesafb_setcolreg to do all
+		 * sanity checking.
+		 */
+		for (i = 0; i < cmap->len; i++) {
+			err |= uvesafb_setcolreg(cmap->start + i, cmap->red[i],
+						cmap->green[i], cmap->blue[i],
+						0, info);
+		}
+	}
+	return err;
+}
+
+static int uvesafb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+#ifdef CONFIG_X86_32
+	int offset;
+	struct uvesafb_par *par = info->par;
+
+	offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
+
+	/*
+	 * It turns out it's not the best idea to do panning via vm86,
+	 * so we only allow it if we have a PMI.
+	 */
+	if (par->pmi_start) {
+		__asm__ __volatile__(
+			"call *(%%edi)"
+			: /* no return value */
+			: "a" (0x4f07),         /* EAX */
+			  "b" (0),              /* EBX */
+			  "c" (offset),         /* ECX */
+			  "d" (offset >> 16),   /* EDX */
+			  "D" (&par->pmi_start));    /* EDI */
+	}
+#endif
+	return 0;
+}
+
+static int uvesafb_blank(int blank, struct fb_info *info)
+{
+	struct uvesafb_ktask *task;
+	int err = 1;
+#ifdef CONFIG_X86
+	struct uvesafb_par *par = info->par;
+
+	if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
+		int loop = 10000;
+		u8 seq = 0, crtc17 = 0;
+
+		if (blank == FB_BLANK_POWERDOWN) {
+			seq = 0x20;
+			crtc17 = 0x00;
+			err = 0;
+		} else {
+			seq = 0x00;
+			crtc17 = 0x80;
+			err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
+		}
+
+		vga_wseq(NULL, 0x00, 0x01);
+		seq |= vga_rseq(NULL, 0x01) & ~0x20;
+		vga_wseq(NULL, 0x00, seq);
+
+		crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
+		while (loop--);
+		vga_wcrt(NULL, 0x17, crtc17);
+		vga_wseq(NULL, 0x00, 0x03);
+	} else
+#endif /* CONFIG_X86 */
+	{
+		task = uvesafb_prep();
+		if (!task)
+			return -ENOMEM;
+
+		task->t.regs.eax = 0x4f10;
+		switch (blank) {
+		case FB_BLANK_UNBLANK:
+			task->t.regs.ebx = 0x0001;
+			break;
+		case FB_BLANK_NORMAL:
+			task->t.regs.ebx = 0x0101;	/* standby */
+			break;
+		case FB_BLANK_POWERDOWN:
+			task->t.regs.ebx = 0x0401;	/* powerdown */
+			break;
+		default:
+			goto out;
+		}
+
+		err = uvesafb_exec(task);
+		if (err || (task->t.regs.eax & 0xffff) != 0x004f)
+			err = 1;
+out:		uvesafb_free(task);
+	}
+	return err;
+}
+
+static int uvesafb_open(struct fb_info *info, int user)
+{
+	struct uvesafb_par *par = info->par;
+	int cnt = atomic_read(&par->ref_count);
+	u8 *buf = NULL;
+
+	if (!cnt && par->vbe_state_size) {
+		buf =  uvesafb_vbe_state_save(par);
+		if (IS_ERR(buf)) {
+			printk(KERN_WARNING "uvesafb: save hardware state"
+				"failed, error code is %ld!\n", PTR_ERR(buf));
+		} else {
+			par->vbe_state_orig = buf;
+		}
+	}
+
+	atomic_inc(&par->ref_count);
+	return 0;
+}
+
+static int uvesafb_release(struct fb_info *info, int user)
+{
+	struct uvesafb_ktask *task = NULL;
+	struct uvesafb_par *par = info->par;
+	int cnt = atomic_read(&par->ref_count);
+
+	if (!cnt)
+		return -EINVAL;
+
+	if (cnt != 1)
+		goto out;
+
+	task = uvesafb_prep();
+	if (!task)
+		goto out;
+
+	/* First, try to set the standard 80x25 text mode. */
+	task->t.regs.eax = 0x0003;
+	uvesafb_exec(task);
+
+	/*
+	 * Now try to restore whatever hardware state we might have
+	 * saved when the fb device was first opened.
+	 */
+	uvesafb_vbe_state_restore(par, par->vbe_state_orig);
+out:
+	atomic_dec(&par->ref_count);
+	if (task)
+		uvesafb_free(task);
+	return 0;
+}
+
+static int uvesafb_set_par(struct fb_info *info)
+{
+	struct uvesafb_par *par = info->par;
+	struct uvesafb_ktask *task = NULL;
+	struct vbe_crtc_ib *crtc = NULL;
+	struct vbe_mode_ib *mode = NULL;
+	int i, err = 0, depth = info->var.bits_per_pixel;
+
+	if (depth > 8 && depth != 32)
+		depth = info->var.red.length + info->var.green.length +
+			info->var.blue.length;
+
+	i = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres, depth,
+				 UVESAFB_EXACT_RES | UVESAFB_EXACT_DEPTH);
+	if (i >= 0)
+		mode = &par->vbe_modes[i];
+	else
+		return -EINVAL;
+
+	task = uvesafb_prep();
+	if (!task)
+		return -ENOMEM;
+setmode:
+	task->t.regs.eax = 0x4f02;
+	task->t.regs.ebx = mode->mode_id | 0x4000;	/* use LFB */
+
+	if (par->vbe_ib.vbe_version >= 0x0300 && !par->nocrtc &&
+	    info->var.pixclock != 0) {
+		task->t.regs.ebx |= 0x0800;		/* use CRTC data */
+		task->t.flags = TF_BUF_ESDI;
+		crtc = kzalloc(sizeof(struct vbe_crtc_ib), GFP_KERNEL);
+		if (!crtc) {
+			err = -ENOMEM;
+			goto out;
+		}
+		crtc->horiz_start = info->var.xres + info->var.right_margin;
+		crtc->horiz_end	  = crtc->horiz_start + info->var.hsync_len;
+		crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
+
+		crtc->vert_start  = info->var.yres + info->var.lower_margin;
+		crtc->vert_end    = crtc->vert_start + info->var.vsync_len;
+		crtc->vert_total  = crtc->vert_end + info->var.upper_margin;
+
+		crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
+		crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock /
+				(crtc->vert_total * crtc->horiz_total)));
+
+		if (info->var.vmode & FB_VMODE_DOUBLE)
+			crtc->flags |= 0x1;
+		if (info->var.vmode & FB_VMODE_INTERLACED)
+			crtc->flags |= 0x2;
+		if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+			crtc->flags |= 0x4;
+		if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+			crtc->flags |= 0x8;
+		memcpy(&par->crtc, crtc, sizeof(*crtc));
+	} else {
+		memset(&par->crtc, 0, sizeof(*crtc));
+	}
+
+	task->t.buf_len = sizeof(struct vbe_crtc_ib);
+	task->buf = &par->crtc;
+
+	err = uvesafb_exec(task);
+	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
+		/*
+		 * The mode switch might have failed because we tried to
+		 * use our own timings.  Try again with the default timings.
+		 */
+		if (crtc != NULL) {
+			printk(KERN_WARNING "uvesafb: mode switch failed "
+				"(eax=0x%x, err=%d). Trying again with "
+				"default timings.\n", task->t.regs.eax, err);
+			uvesafb_reset(task);
+			kfree(crtc);
+			crtc = NULL;
+			info->var.pixclock = 0;
+			goto setmode;
+		} else {
+			printk(KERN_ERR "uvesafb: mode switch failed (eax="
+				"0x%x, err=%d)\n", task->t.regs.eax, err);
+			err = -EINVAL;
+			goto out;
+		}
+	}
+	par->mode_idx = i;
+
+	/* For 8bpp modes, always try to set the DAC to 8 bits. */
+	if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC &&
+	    mode->bits_per_pixel <= 8) {
+		uvesafb_reset(task);
+		task->t.regs.eax = 0x4f08;
+		task->t.regs.ebx = 0x0800;
+
+		err = uvesafb_exec(task);
+		if (err || (task->t.regs.eax & 0xffff) != 0x004f ||
+		    ((task->t.regs.ebx & 0xff00) >> 8) != 8) {
+			dac_width = 6;
+		} else {
+			dac_width = 8;
+		}
+	}
+
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = mode->bytes_per_scan_line;
+
+out:
+	kfree(crtc);
+	uvesafb_free(task);
+
+	return err;
+}
+
+static void uvesafb_check_limits(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	const struct fb_videomode *mode;
+	struct uvesafb_par *par = info->par;
+
+	/*
+	 * If pixclock is set to 0, then we're using default BIOS timings
+	 * and thus don't have to perform any checks here.
+	 */
+	if (!var->pixclock)
+		return;
+
+	if (par->vbe_ib.vbe_version < 0x0300) {
+		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info);
+		return;
+	}
+
+	if (!fb_validate_mode(var, info))
+		return;
+
+	mode = fb_find_best_mode(var, &info->modelist);
+	if (mode) {
+		if (mode->xres == var->xres && mode->yres == var->yres &&
+		    !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) {
+			fb_videomode_to_var(var, mode);
+			return;
+		}
+	}
+
+	if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+		return;
+	/* Use default refresh rate */
+	var->pixclock = 0;
+}
+
+static int uvesafb_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	struct uvesafb_par *par = info->par;
+	struct vbe_mode_ib *mode = NULL;
+	int match = -1;
+	int depth = var->red.length + var->green.length + var->blue.length;
+
+	/*
+	 * Various apps will use bits_per_pixel to set the color depth,
+	 * which is theoretically incorrect, but which we'll try to handle
+	 * here.
+	 */
+	if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8)
+		depth = var->bits_per_pixel;
+
+	match = uvesafb_vbe_find_mode(par, var->xres, var->yres, depth,
+						UVESAFB_EXACT_RES);
+	if (match == -1)
+		return -EINVAL;
+
+	mode = &par->vbe_modes[match];
+	uvesafb_setup_var(var, info, mode);
+
+	/*
+	 * Check whether we have remapped enough memory for this mode.
+	 * We might be called at an early stage, when we haven't remapped
+	 * any memory yet, in which case we simply skip the check.
+	 */
+	if (var->yres * mode->bytes_per_scan_line > info->fix.smem_len
+						&& info->fix.smem_len)
+		return -EINVAL;
+
+	if ((var->vmode & FB_VMODE_DOUBLE) &&
+				!(par->vbe_modes[match].mode_attr & 0x100))
+		var->vmode &= ~FB_VMODE_DOUBLE;
+
+	if ((var->vmode & FB_VMODE_INTERLACED) &&
+				!(par->vbe_modes[match].mode_attr & 0x200))
+		var->vmode &= ~FB_VMODE_INTERLACED;
+
+	uvesafb_check_limits(var, info);
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = (par->ypan) ?
+				info->fix.smem_len / mode->bytes_per_scan_line :
+				var->yres;
+	return 0;
+}
+
+static struct fb_ops uvesafb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= uvesafb_open,
+	.fb_release	= uvesafb_release,
+	.fb_setcolreg	= uvesafb_setcolreg,
+	.fb_setcmap	= uvesafb_setcmap,
+	.fb_pan_display	= uvesafb_pan_display,
+	.fb_blank	= uvesafb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_check_var	= uvesafb_check_var,
+	.fb_set_par	= uvesafb_set_par,
+};
+
+static void uvesafb_init_info(struct fb_info *info, struct vbe_mode_ib *mode)
+{
+	unsigned int size_vmode;
+	unsigned int size_remap;
+	unsigned int size_total;
+	struct uvesafb_par *par = info->par;
+	int i, h;
+
+	info->pseudo_palette = ((u8 *)info->par + sizeof(struct uvesafb_par));
+	info->fix = uvesafb_fix;
+	info->fix.ypanstep = par->ypan ? 1 : 0;
+	info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0;
+
+	/* Disable blanking if the user requested so. */
+	if (!blank)
+		info->fbops->fb_blank = NULL;
+
+	/*
+	 * Find out how much IO memory is required for the mode with
+	 * the highest resolution.
+	 */
+	size_remap = 0;
+	for (i = 0; i < par->vbe_modes_cnt; i++) {
+		h = par->vbe_modes[i].bytes_per_scan_line *
+					par->vbe_modes[i].y_res;
+		if (h > size_remap)
+			size_remap = h;
+	}
+	size_remap *= 2;
+
+	/*
+	 *   size_vmode -- that is the amount of memory needed for the
+	 *                 used video mode, i.e. the minimum amount of
+	 *                 memory we need.
+	 */
+	size_vmode = info->var.yres * mode->bytes_per_scan_line;
+
+	/*
+	 *   size_total -- all video memory we have. Used for mtrr
+	 *                 entries, resource allocation and bounds
+	 *                 checking.
+	 */
+	size_total = par->vbe_ib.total_memory * 65536;
+	if (vram_total)
+		size_total = vram_total * 1024 * 1024;
+	if (size_total < size_vmode)
+		size_total = size_vmode;
+
+	/*
+	 *   size_remap -- the amount of video memory we are going to
+	 *                 use for vesafb.  With modern cards it is no
+	 *                 option to simply use size_total as th
+	 *                 wastes plenty of kernel address space.
+	 */
+	if (vram_remap)
+		size_remap = vram_remap * 1024 * 1024;
+	if (size_remap < size_vmode)
+		size_remap = size_vmode;
+	if (size_remap > size_total)
+		size_remap = size_total;
+
+	info->fix.smem_len = size_remap;
+	info->fix.smem_start = mode->phys_base_ptr;
+
+	/*
+	 * We have to set yres_virtual here because when setup_var() was
+	 * called, smem_len wasn't defined yet.
+	 */
+	info->var.yres_virtual = info->fix.smem_len /
+				 mode->bytes_per_scan_line;
+
+	if (par->ypan && info->var.yres_virtual > info->var.yres) {
+		printk(KERN_INFO "uvesafb: scrolling: %s "
+			"using protected mode interface, "
+			"yres_virtual=%d\n",
+			(par->ypan > 1) ? "ywrap" : "ypan",
+			info->var.yres_virtual);
+	} else {
+		printk(KERN_INFO "uvesafb: scrolling: redraw\n");
+		info->var.yres_virtual = info->var.yres;
+		par->ypan = 0;
+	}
+
+	info->flags = FBINFO_FLAG_DEFAULT |
+			(par->ypan ? FBINFO_HWACCEL_YPAN : 0);
+
+	if (!par->ypan)
+		info->fbops->fb_pan_display = NULL;
+}
+
+static void uvesafb_init_mtrr(struct fb_info *info)
+{
+	struct uvesafb_par *par = info->par;
+
+	if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
+		int temp_size = info->fix.smem_len;
+
+		int rc;
+
+		/* Find the largest power-of-two */
+		temp_size = roundup_pow_of_two(temp_size);
+
+		/* Try and find a power of two to add */
+		do {
+			rc = arch_phys_wc_add(info->fix.smem_start, temp_size);
+			temp_size >>= 1;
+		} while (temp_size >= PAGE_SIZE && rc == -EINVAL);
+
+		if (rc >= 0)
+			par->mtrr_handle = rc;
+	}
+}
+
+static void uvesafb_ioremap(struct fb_info *info)
+{
+	info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len);
+}
+
+static ssize_t uvesafb_show_vbe_ver(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version);
+}
+
+static DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL);
+
+static ssize_t uvesafb_show_vbe_modes(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+	int ret = 0, i;
+
+	for (i = 0; i < par->vbe_modes_cnt && ret < PAGE_SIZE; i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"%dx%d-%d, 0x%.4x\n",
+			par->vbe_modes[i].x_res, par->vbe_modes[i].y_res,
+			par->vbe_modes[i].depth, par->vbe_modes[i].mode_id);
+	}
+
+	return ret;
+}
+
+static DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL);
+
+static ssize_t uvesafb_show_vendor(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+
+	if (par->vbe_ib.oem_vendor_name_ptr)
+		return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
+			(&par->vbe_ib) + par->vbe_ib.oem_vendor_name_ptr);
+	else
+		return 0;
+}
+
+static DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL);
+
+static ssize_t uvesafb_show_product_name(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+
+	if (par->vbe_ib.oem_product_name_ptr)
+		return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
+			(&par->vbe_ib) + par->vbe_ib.oem_product_name_ptr);
+	else
+		return 0;
+}
+
+static DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL);
+
+static ssize_t uvesafb_show_product_rev(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+
+	if (par->vbe_ib.oem_product_rev_ptr)
+		return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
+			(&par->vbe_ib) + par->vbe_ib.oem_product_rev_ptr);
+	else
+		return 0;
+}
+
+static DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL);
+
+static ssize_t uvesafb_show_oem_string(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+
+	if (par->vbe_ib.oem_string_ptr)
+		return snprintf(buf, PAGE_SIZE, "%s\n",
+			(char *)(&par->vbe_ib) + par->vbe_ib.oem_string_ptr);
+	else
+		return 0;
+}
+
+static DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL);
+
+static ssize_t uvesafb_show_nocrtc(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc);
+}
+
+static ssize_t uvesafb_store_nocrtc(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
+	struct uvesafb_par *par = info->par;
+
+	if (count > 0) {
+		if (buf[0] == '0')
+			par->nocrtc = 0;
+		else
+			par->nocrtc = 1;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(nocrtc, S_IRUGO | S_IWUSR, uvesafb_show_nocrtc,
+			uvesafb_store_nocrtc);
+
+static struct attribute *uvesafb_dev_attrs[] = {
+	&dev_attr_vbe_version.attr,
+	&dev_attr_vbe_modes.attr,
+	&dev_attr_oem_vendor.attr,
+	&dev_attr_oem_product_name.attr,
+	&dev_attr_oem_product_rev.attr,
+	&dev_attr_oem_string.attr,
+	&dev_attr_nocrtc.attr,
+	NULL,
+};
+
+static struct attribute_group uvesafb_dev_attgrp = {
+	.name = NULL,
+	.attrs = uvesafb_dev_attrs,
+};
+
+static int uvesafb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	struct vbe_mode_ib *mode = NULL;
+	struct uvesafb_par *par;
+	int err = 0, i;
+
+	info = framebuffer_alloc(sizeof(*par) +	sizeof(u32) * 256, &dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	par = info->par;
+
+	err = uvesafb_vbe_init(info);
+	if (err) {
+		printk(KERN_ERR "uvesafb: vbe_init() failed with %d\n", err);
+		goto out;
+	}
+
+	info->fbops = &uvesafb_ops;
+
+	i = uvesafb_vbe_init_mode(info);
+	if (i < 0) {
+		err = -EINVAL;
+		goto out;
+	} else {
+		mode = &par->vbe_modes[i];
+	}
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		err = -ENXIO;
+		goto out;
+	}
+
+	uvesafb_init_info(info, mode);
+
+	if (!request_region(0x3c0, 32, "uvesafb")) {
+		printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n");
+		err = -EIO;
+		goto out_mode;
+	}
+
+	if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
+				"uvesafb")) {
+		printk(KERN_ERR "uvesafb: cannot reserve video memory at "
+				"0x%lx\n", info->fix.smem_start);
+		err = -EIO;
+		goto out_reg;
+	}
+
+	uvesafb_init_mtrr(info);
+	uvesafb_ioremap(info);
+
+	if (!info->screen_base) {
+		printk(KERN_ERR
+			"uvesafb: abort, cannot ioremap 0x%x bytes of video "
+			"memory at 0x%lx\n",
+			info->fix.smem_len, info->fix.smem_start);
+		err = -EIO;
+		goto out_mem;
+	}
+
+	platform_set_drvdata(dev, info);
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR
+			"uvesafb: failed to register framebuffer device\n");
+		err = -EINVAL;
+		goto out_unmap;
+	}
+
+	printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, "
+			"using %dk, total %dk\n", info->fix.smem_start,
+			info->screen_base, info->fix.smem_len/1024,
+			par->vbe_ib.total_memory * 64);
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+
+	err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
+	if (err != 0)
+		fb_warn(info, "failed to register attributes\n");
+
+	return 0;
+
+out_unmap:
+	iounmap(info->screen_base);
+out_mem:
+	release_mem_region(info->fix.smem_start, info->fix.smem_len);
+out_reg:
+	release_region(0x3c0, 32);
+out_mode:
+	if (!list_empty(&info->modelist))
+		fb_destroy_modelist(&info->modelist);
+	fb_destroy_modedb(info->monspecs.modedb);
+	fb_dealloc_cmap(&info->cmap);
+out:
+	kfree(par->vbe_modes);
+
+	framebuffer_release(info);
+	return err;
+}
+
+static int uvesafb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		struct uvesafb_par *par = info->par;
+
+		sysfs_remove_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
+		unregister_framebuffer(info);
+		release_region(0x3c0, 32);
+		iounmap(info->screen_base);
+		arch_phys_wc_del(par->mtrr_handle);
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+		fb_destroy_modedb(info->monspecs.modedb);
+		fb_dealloc_cmap(&info->cmap);
+
+		kfree(par->vbe_modes);
+		kfree(par->vbe_state_orig);
+		kfree(par->vbe_state_saved);
+
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct platform_driver uvesafb_driver = {
+	.probe  = uvesafb_probe,
+	.remove = uvesafb_remove,
+	.driver = {
+		.name = "uvesafb",
+	},
+};
+
+static struct platform_device *uvesafb_device;
+
+#ifndef MODULE
+static int uvesafb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt) continue;
+
+		if (!strcmp(this_opt, "redraw"))
+			ypan = 0;
+		else if (!strcmp(this_opt, "ypan"))
+			ypan = 1;
+		else if (!strcmp(this_opt, "ywrap"))
+			ypan = 2;
+		else if (!strcmp(this_opt, "vgapal"))
+			pmi_setpal = 0;
+		else if (!strcmp(this_opt, "pmipal"))
+			pmi_setpal = 1;
+		else if (!strncmp(this_opt, "mtrr:", 5))
+			mtrr = simple_strtoul(this_opt+5, NULL, 0);
+		else if (!strcmp(this_opt, "nomtrr"))
+			mtrr = 0;
+		else if (!strcmp(this_opt, "nocrtc"))
+			nocrtc = 1;
+		else if (!strcmp(this_opt, "noedid"))
+			noedid = 1;
+		else if (!strcmp(this_opt, "noblank"))
+			blank = 0;
+		else if (!strncmp(this_opt, "vtotal:", 7))
+			vram_total = simple_strtoul(this_opt + 7, NULL, 0);
+		else if (!strncmp(this_opt, "vremap:", 7))
+			vram_remap = simple_strtoul(this_opt + 7, NULL, 0);
+		else if (!strncmp(this_opt, "maxhf:", 6))
+			maxhf = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "maxvf:", 6))
+			maxvf = simple_strtoul(this_opt + 6, NULL, 0);
+		else if (!strncmp(this_opt, "maxclk:", 7))
+			maxclk = simple_strtoul(this_opt + 7, NULL, 0);
+		else if (!strncmp(this_opt, "vbemode:", 8))
+			vbemode = simple_strtoul(this_opt + 8, NULL, 0);
+		else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
+			mode_option = this_opt;
+		} else {
+			printk(KERN_WARNING
+				"uvesafb: unrecognized option %s\n", this_opt);
+		}
+	}
+
+	if (mtrr != 3 && mtrr != 0)
+		pr_warn("uvesafb: mtrr should be set to 0 or 3; %d is unsupported", mtrr);
+
+	return 0;
+}
+#endif /* !MODULE */
+
+static ssize_t show_v86d(struct device_driver *dev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path);
+}
+
+static ssize_t store_v86d(struct device_driver *dev, const char *buf,
+		size_t count)
+{
+	strncpy(v86d_path, buf, PATH_MAX);
+	return count;
+}
+
+static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d);
+
+static int uvesafb_init(void)
+{
+	int err;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("uvesafb", &option))
+		return -ENODEV;
+	uvesafb_setup(option);
+#endif
+	err = cn_add_callback(&uvesafb_cn_id, "uvesafb", uvesafb_cn_callback);
+	if (err)
+		return err;
+
+	err = platform_driver_register(&uvesafb_driver);
+
+	if (!err) {
+		uvesafb_device = platform_device_alloc("uvesafb", 0);
+		if (uvesafb_device)
+			err = platform_device_add(uvesafb_device);
+		else
+			err = -ENOMEM;
+
+		if (err) {
+			if (uvesafb_device)
+				platform_device_put(uvesafb_device);
+			platform_driver_unregister(&uvesafb_driver);
+			cn_del_callback(&uvesafb_cn_id);
+			return err;
+		}
+
+		err = driver_create_file(&uvesafb_driver.driver,
+				&driver_attr_v86d);
+		if (err) {
+			printk(KERN_WARNING "uvesafb: failed to register "
+					"attributes\n");
+			err = 0;
+		}
+	}
+	return err;
+}
+
+module_init(uvesafb_init);
+
+static void uvesafb_exit(void)
+{
+	struct uvesafb_ktask *task;
+
+	if (v86d_started) {
+		task = uvesafb_prep();
+		if (task) {
+			task->t.flags = TF_EXIT;
+			uvesafb_exec(task);
+			uvesafb_free(task);
+		}
+	}
+
+	cn_del_callback(&uvesafb_cn_id);
+	driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d);
+	platform_device_unregister(uvesafb_device);
+	platform_driver_unregister(&uvesafb_driver);
+}
+
+module_exit(uvesafb_exit);
+
+static int param_set_scroll(const char *val, const struct kernel_param *kp)
+{
+	ypan = 0;
+
+	if (!strcmp(val, "redraw"))
+		ypan = 0;
+	else if (!strcmp(val, "ypan"))
+		ypan = 1;
+	else if (!strcmp(val, "ywrap"))
+		ypan = 2;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+static struct kernel_param_ops param_ops_scroll = {
+	.set = param_set_scroll,
+};
+#define param_check_scroll(name, p) __param_check(name, p, void)
+
+module_param_named(scroll, ypan, scroll, 0);
+MODULE_PARM_DESC(scroll,
+	"Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'");
+module_param_named(vgapal, pmi_setpal, invbool, 0);
+MODULE_PARM_DESC(vgapal, "Set palette using VGA registers");
+module_param_named(pmipal, pmi_setpal, bool, 0);
+MODULE_PARM_DESC(pmipal, "Set palette using PMI calls");
+module_param(mtrr, uint, 0);
+MODULE_PARM_DESC(mtrr,
+	"Memory Type Range Registers setting. Use 0 to disable.");
+module_param(blank, bool, 0);
+MODULE_PARM_DESC(blank, "Enable hardware blanking");
+module_param(nocrtc, bool, 0);
+MODULE_PARM_DESC(nocrtc, "Ignore CRTC timings when setting modes");
+module_param(noedid, bool, 0);
+MODULE_PARM_DESC(noedid,
+	"Ignore EDID-provided monitor limits when setting modes");
+module_param(vram_remap, uint, 0);
+MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]");
+module_param(vram_total, uint, 0);
+MODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]");
+module_param(maxclk, ushort, 0);
+MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data");
+module_param(maxhf, ushort, 0);
+MODULE_PARM_DESC(maxhf,
+	"Maximum horizontal frequency [kHz], overrides EDID data");
+module_param(maxvf, ushort, 0);
+MODULE_PARM_DESC(maxvf,
+	"Maximum vertical frequency [Hz], overrides EDID data");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option,
+	"Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
+module_param(vbemode, ushort, 0);
+MODULE_PARM_DESC(vbemode,
+	"VBE mode number to set, overrides the 'mode' option");
+module_param_string(v86d, v86d_path, PATH_MAX, 0660);
+MODULE_PARM_DESC(v86d, "Path to the v86d userspace helper.");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>");
+MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
+
diff --git a/drivers/video/fbdev/valkyriefb.c b/drivers/video/fbdev/valkyriefb.c
new file mode 100644
index 000000000000..97cb9bd1d1dd
--- /dev/null
+++ b/drivers/video/fbdev/valkyriefb.c
@@ -0,0 +1,589 @@
+/*
+ *  valkyriefb.c -- frame buffer device for the PowerMac 'valkyrie' display
+ *
+ *  Created 8 August 1998 by 
+ *  Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel
+ *
+ *  Vmode-switching changes and vmode 15/17 modifications created 29 August
+ *  1998 by Barry K. Nathan <barryn@pobox.com>.
+ *
+ *  Ported to m68k Macintosh by David Huggins-Daines <dhd@debian.org>
+ *
+ *  Derived directly from:
+ *
+ *   controlfb.c -- frame buffer device for the PowerMac 'control' display
+ *   Copyright (C) 1998 Dan Jacobowitz <dan@debian.org>
+ *
+ *   pmc-valkyrie.c -- Console support for PowerMac "valkyrie" display adaptor.
+ *   Copyright (C) 1997 Paul Mackerras.
+ *
+ *  and indirectly:
+ *
+ *  Frame buffer structure from:
+ *    drivers/video/chipsfb.c -- frame buffer device for
+ *    Chips & Technologies 65550 chip.
+ *
+ *    Copyright (C) 1998 Paul Mackerras
+ *
+ *    This file is derived from the Powermac "chips" driver:
+ *    Copyright (C) 1997 Fabio Riccardi.
+ *    And from the frame buffer device for Open Firmware-initialized devices:
+ *    Copyright (C) 1997 Geert Uytterhoeven.
+ *
+ *  Hardware information from:
+ *    control.c: Console support for PowerMac "control" display adaptor.
+ *    Copyright (C) 1996 Paul Mackerras
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/init.h>
+#include <linux/nvram.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <asm/io.h>
+#ifdef CONFIG_MAC
+#include <asm/macintosh.h>
+#else
+#include <asm/prom.h>
+#endif
+#include <asm/pgtable.h>
+
+#include "macmodes.h"
+#include "valkyriefb.h"
+
+#ifdef CONFIG_MAC
+/* We don't yet have functions to read the PRAM... perhaps we can
+   adapt them from the PPC code? */
+static int default_vmode = VMODE_CHOOSE;
+static int default_cmode = CMODE_8;
+#else
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+#endif
+
+struct fb_par_valkyrie {
+	int	vmode, cmode;
+	int	xres, yres;
+	int	vxres, vyres;
+	struct valkyrie_regvals *init;
+};
+
+struct fb_info_valkyrie {
+	struct fb_info		info;
+	struct fb_par_valkyrie	par;
+	struct cmap_regs	__iomem *cmap_regs;
+	unsigned long		cmap_regs_phys;
+	
+	struct valkyrie_regs	__iomem *valkyrie_regs;
+	unsigned long		valkyrie_regs_phys;
+	
+	__u8			__iomem *frame_buffer;
+	unsigned long		frame_buffer_phys;
+	
+	int			sense;
+	unsigned long		total_vram;
+
+	u32			pseudo_palette[16];
+};
+
+/*
+ * Exported functions
+ */
+int valkyriefb_init(void);
+int valkyriefb_setup(char*);
+
+static int valkyriefb_check_var(struct fb_var_screeninfo *var,
+				struct fb_info *info);
+static int valkyriefb_set_par(struct fb_info *info);
+static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info);
+static int valkyriefb_blank(int blank_mode, struct fb_info *info);
+
+static int read_valkyrie_sense(struct fb_info_valkyrie *p);
+static void set_valkyrie_clock(unsigned char *params);
+static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
+	struct fb_par_valkyrie *par, const struct fb_info *fb_info);
+
+static int valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p);
+static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix);
+static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
+
+static struct fb_ops valkyriefb_ops = {
+	.owner =	THIS_MODULE,
+	.fb_check_var =	valkyriefb_check_var,
+	.fb_set_par =	valkyriefb_set_par,
+	.fb_setcolreg =	valkyriefb_setcolreg,
+	.fb_blank =	valkyriefb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+/* Sets the video mode according to info->var */
+static int valkyriefb_set_par(struct fb_info *info)
+{
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+	volatile struct valkyrie_regs __iomem *valkyrie_regs = p->valkyrie_regs;
+	struct fb_par_valkyrie *par = info->par;
+	struct valkyrie_regvals	*init;
+	int err;
+
+	if ((err = valkyrie_var_to_par(&info->var, par, info)))
+		return err;
+
+	valkyrie_par_to_fix(par, &info->fix);
+
+	/* Reset the valkyrie */
+	out_8(&valkyrie_regs->status.r, 0);
+	udelay(100);
+
+	/* Initialize display timing registers */
+	init = par->init;
+	out_8(&valkyrie_regs->mode.r, init->mode | 0x80);
+	out_8(&valkyrie_regs->depth.r, par->cmode + 3);
+	set_valkyrie_clock(init->clock_params);
+	udelay(100);
+
+	/* Turn on display */
+	out_8(&valkyrie_regs->mode.r, init->mode);
+
+	return 0;
+}
+
+static inline int valkyrie_par_to_var(struct fb_par_valkyrie *par,
+				      struct fb_var_screeninfo *var)
+{
+	return mac_vmode_to_var(par->vmode, par->cmode, var);
+}
+
+static int
+valkyriefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int err;
+	struct fb_par_valkyrie par;
+
+	if ((err = valkyrie_var_to_par(var, &par, info)))
+		return err;
+	valkyrie_par_to_var(&par, var);
+	return 0;
+}
+
+/*
+ *  Blank the screen if blank_mode != 0, else unblank. If blank_mode == NULL
+ *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+ *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+ *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+ *  and powerdown modes on hardware that supports disabling hsync/vsync:
+ *    blank_mode == 2: suspend vsync
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ */
+static int valkyriefb_blank(int blank_mode, struct fb_info *info)
+{
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+	struct fb_par_valkyrie *par = info->par;
+	struct valkyrie_regvals	*init = par->init;
+
+	if (init == NULL)
+		return 1;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:			/* unblank */
+		out_8(&p->valkyrie_regs->mode.r, init->mode);
+		break;
+	case FB_BLANK_NORMAL:
+		return 1;	/* get caller to set CLUT to all black */
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+		/*
+		 * [kps] Value extracted from MacOS. I don't know
+		 * whether this bit disables hsync or vsync, or
+		 * whether the hardware can do the other as well.
+		 */
+		out_8(&p->valkyrie_regs->mode.r, init->mode | 0x40);
+		break;
+	case FB_BLANK_POWERDOWN:
+		out_8(&p->valkyrie_regs->mode.r, 0x66);
+		break;
+	}
+	return 0;
+}
+
+static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info)
+{
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+	volatile struct cmap_regs __iomem *cmap_regs = p->cmap_regs;
+	struct fb_par_valkyrie *par = info->par;
+
+	if (regno > 255)
+		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	/* tell clut which address to fill */
+	out_8(&p->cmap_regs->addr, regno);
+	udelay(1);
+	/* send one color channel at a time */
+	out_8(&cmap_regs->lut, red);
+	out_8(&cmap_regs->lut, green);
+	out_8(&cmap_regs->lut, blue);
+
+	if (regno < 16 && par->cmode == CMODE_16)
+		((u32 *)info->pseudo_palette)[regno] =
+			(regno << 10) | (regno << 5) | regno;
+
+	return 0;
+}
+
+static inline int valkyrie_vram_reqd(int video_mode, int color_mode)
+{
+	int pitch;
+	struct valkyrie_regvals *init = valkyrie_reg_init[video_mode-1];
+	
+	if ((pitch = init->pitch[color_mode]) == 0)
+		pitch = 2 * init->pitch[0];
+	return init->vres * pitch;
+}
+
+static void set_valkyrie_clock(unsigned char *params)
+{
+	struct adb_request req;
+	int i;
+
+#ifdef CONFIG_ADB_CUDA
+	for (i = 0; i < 3; ++i) {
+		cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
+			     0x50, i + 1, params[i]);
+		while (!req.complete)
+			cuda_poll();
+	}
+#endif
+}
+
+static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p)
+{
+	p->sense = read_valkyrie_sense(p);
+	printk(KERN_INFO "Monitor sense value = 0x%x\n", p->sense);
+
+	/* Try to pick a video mode out of NVRAM if we have one. */
+#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
+	if (default_vmode == VMODE_NVRAM) {
+		default_vmode = nvram_read_byte(NV_VMODE);
+		if (default_vmode <= 0
+		 || default_vmode > VMODE_MAX
+		 || !valkyrie_reg_init[default_vmode - 1])
+			default_vmode = VMODE_CHOOSE;
+	}
+#endif
+	if (default_vmode == VMODE_CHOOSE)
+		default_vmode = mac_map_monitor_sense(p->sense);
+	if (!valkyrie_reg_init[default_vmode - 1])
+		default_vmode = VMODE_640_480_67;
+#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
+	if (default_cmode == CMODE_NVRAM)
+		default_cmode = nvram_read_byte(NV_CMODE);
+#endif
+
+	/*
+	 * Reduce the pixel size if we don't have enough VRAM or bandwidth.
+	 */
+	if (default_cmode < CMODE_8 || default_cmode > CMODE_16
+	    || valkyrie_reg_init[default_vmode-1]->pitch[default_cmode] == 0
+	    || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram)
+		default_cmode = CMODE_8;
+
+	printk(KERN_INFO "using video mode %d and color mode %d.\n",
+	       default_vmode, default_cmode);
+}
+
+int __init valkyriefb_init(void)
+{
+	struct fb_info_valkyrie	*p;
+	unsigned long frame_buffer_phys, cmap_regs_phys, flags;
+	int err;
+	char *option = NULL;
+
+	if (fb_get_options("valkyriefb", &option))
+		return -ENODEV;
+	valkyriefb_setup(option);
+
+#ifdef CONFIG_MAC
+	if (!MACH_IS_MAC)
+		return -ENODEV;
+	if (!(mac_bi_data.id == MAC_MODEL_Q630
+	      /* I'm not sure about this one */
+	    || mac_bi_data.id == MAC_MODEL_P588))
+		return -ENODEV;
+
+	/* Hardcoded addresses... welcome to 68k Macintosh country :-) */
+	frame_buffer_phys = 0xf9000000;
+	cmap_regs_phys = 0x50f24000;
+	flags = IOMAP_NOCACHE_SER; /* IOMAP_WRITETHROUGH?? */
+#else /* ppc (!CONFIG_MAC) */
+	{
+		struct device_node *dp;
+		struct resource r;
+
+		dp = of_find_node_by_name(NULL, "valkyrie");
+		if (dp == 0)
+			return 0;
+
+		if (of_address_to_resource(dp, 0, &r)) {
+			printk(KERN_ERR "can't find address for valkyrie\n");
+			return 0;
+		}
+
+		frame_buffer_phys = r.start;
+		cmap_regs_phys = r.start + 0x304000;
+		flags = _PAGE_WRITETHRU;
+	}
+#endif /* ppc (!CONFIG_MAC) */
+
+	p = kzalloc(sizeof(*p), GFP_ATOMIC);
+	if (p == 0)
+		return -ENOMEM;
+
+	/* Map in frame buffer and registers */
+	if (!request_mem_region(frame_buffer_phys, 0x100000, "valkyriefb")) {
+		kfree(p);
+		return 0;
+	}
+	p->total_vram = 0x100000;
+	p->frame_buffer_phys = frame_buffer_phys;
+	p->frame_buffer = __ioremap(frame_buffer_phys, p->total_vram, flags);
+	p->cmap_regs_phys = cmap_regs_phys;
+	p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
+	p->valkyrie_regs_phys = cmap_regs_phys+0x6000;
+	p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, 0x1000);
+	err = -ENOMEM;
+	if (p->frame_buffer == NULL || p->cmap_regs == NULL
+	    || p->valkyrie_regs == NULL) {
+		printk(KERN_ERR "valkyriefb: couldn't map resources\n");
+		goto out_free;
+	}
+
+	valkyrie_choose_mode(p);
+	mac_vmode_to_var(default_vmode, default_cmode, &p->info.var);
+	err = valkyrie_init_info(&p->info, p);
+	if (err < 0)
+		goto out_free;
+	valkyrie_init_fix(&p->info.fix, p);
+	if (valkyriefb_set_par(&p->info))
+		/* "can't happen" */
+		printk(KERN_ERR "valkyriefb: can't set default video mode\n");
+
+	if ((err = register_framebuffer(&p->info)) != 0)
+		goto out_cmap_free;
+
+	fb_info(&p->info, "valkyrie frame buffer device\n");
+	return 0;
+
+ out_cmap_free:
+	fb_dealloc_cmap(&p->info.cmap);
+ out_free:
+	if (p->frame_buffer)
+		iounmap(p->frame_buffer);
+	if (p->cmap_regs)
+		iounmap(p->cmap_regs);
+	if (p->valkyrie_regs)
+		iounmap(p->valkyrie_regs);
+	kfree(p);
+	return err;
+}
+
+/*
+ * Get the monitor sense value.
+ */
+static int read_valkyrie_sense(struct fb_info_valkyrie *p)
+{
+	int sense, in;
+
+	out_8(&p->valkyrie_regs->msense.r, 0);   /* release all lines */
+	__delay(20000);
+	sense = ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x70) << 4;
+	/* drive each sense line low in turn and collect the other 2 */
+	out_8(&p->valkyrie_regs->msense.r, 4);   /* drive A low */
+	__delay(20000);
+	sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x30);
+	out_8(&p->valkyrie_regs->msense.r, 2);   /* drive B low */
+	__delay(20000);
+	sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x40) >> 3;
+	sense |= (in & 0x10) >> 2;
+	out_8(&p->valkyrie_regs->msense.r, 1);   /* drive C low */
+	__delay(20000);
+	sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x60) >> 5;
+
+	out_8(&p->valkyrie_regs->msense.r, 7);
+
+	return sense;
+}
+
+/*
+ * This routine takes a user-supplied var,
+ * and picks the best vmode/cmode from it.
+ */
+
+/* [bkn] I did a major overhaul of this function.
+ *
+ * Much of the old code was "swiped by jonh from atyfb.c". Because
+ * macmodes has mac_var_to_vmode, I felt that it would be better to
+ * rework this function to use that, instead of reinventing the wheel to
+ * add support for vmode 17. This was reinforced by the fact that
+ * the previously swiped atyfb.c code is no longer there.
+ *
+ * So, I swiped and adapted platinum_var_to_par (from platinumfb.c), replacing
+ * most, but not all, of the old code in the process. One side benefit of
+ * swiping the platinumfb code is that we now have more comprehensible error
+ * messages when a vmode/cmode switch fails. (Most of the error messages are
+ * platinumfb.c, but I added two of my own, and I also changed some commas
+ * into colons to make the messages more consistent with other Linux error
+ * messages.) In addition, I think the new code *might* fix some vmode-
+ * switching oddities, but I'm not sure.
+ *
+ * There may be some more opportunities for cleanup in here, but this is a
+ * good start...
+ */
+
+static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
+	struct fb_par_valkyrie *par, const struct fb_info *fb_info)
+{
+	int vmode, cmode;
+	struct valkyrie_regvals *init;
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) fb_info;
+
+	if (mac_var_to_vmode(var, &vmode, &cmode) != 0) {
+		printk(KERN_ERR "valkyriefb: can't do %dx%dx%d.\n",
+		       var->xres, var->yres, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* Check if we know about the wanted video mode */
+	if (vmode < 1 || vmode > VMODE_MAX || !valkyrie_reg_init[vmode-1]) {
+		printk(KERN_ERR "valkyriefb: vmode %d not valid.\n", vmode);
+		return -EINVAL;
+	}
+	
+	if (cmode != CMODE_8 && cmode != CMODE_16) {
+		printk(KERN_ERR "valkyriefb: cmode %d not valid.\n", cmode);
+		return -EINVAL;
+	}
+
+	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres
+	    || var->xoffset != 0 || var->yoffset != 0) {
+		return -EINVAL;
+	}
+
+	init = valkyrie_reg_init[vmode-1];
+	if (init->pitch[cmode] == 0) {
+		printk(KERN_ERR "valkyriefb: vmode %d does not support "
+		       "cmode %d.\n", vmode, cmode);
+		return -EINVAL;
+	}
+
+	if (valkyrie_vram_reqd(vmode, cmode) > p->total_vram) {
+		printk(KERN_ERR "valkyriefb: not enough ram for vmode %d, "
+		       "cmode %d.\n", vmode, cmode);
+		return -EINVAL;
+	}
+
+	par->vmode = vmode;
+	par->cmode = cmode;
+	par->init = init;
+	par->xres = var->xres;
+	par->yres = var->yres;
+	par->vxres = par->xres;
+	par->vyres = par->yres;
+
+	return 0;
+}
+
+static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
+{
+	memset(fix, 0, sizeof(*fix));
+	strcpy(fix->id, "valkyrie");
+	fix->mmio_start = p->valkyrie_regs_phys;
+	fix->mmio_len = sizeof(struct valkyrie_regs);
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->smem_start = p->frame_buffer_phys + 0x1000;
+	fix->smem_len = p->total_vram;
+
+	fix->type_aux = 0;
+	fix->ywrapstep = 0;
+	fix->ypanstep = 0;
+	fix->xpanstep = 0;
+	
+}
+
+/* Fix must already be inited above */
+static void valkyrie_par_to_fix(struct fb_par_valkyrie *par,
+	struct fb_fix_screeninfo *fix)
+{
+	fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode);
+	fix->visual = (par->cmode == CMODE_8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	fix->line_length = par->vxres << par->cmode;
+		/* ywrapstep, xpanstep, ypanstep */
+}
+
+static int __init valkyrie_init_info(struct fb_info *info,
+		struct fb_info_valkyrie *p)
+{
+	info->fbops = &valkyriefb_ops;
+	info->screen_base = p->frame_buffer + 0x1000;
+	info->flags = FBINFO_DEFAULT;
+	info->pseudo_palette = p->pseudo_palette;
+	info->par = &p->par;
+	return fb_alloc_cmap(&info->cmap, 256, 0);
+}
+
+
+/*
+ * Parse user specified options (`video=valkyriefb:')
+ */
+int __init valkyriefb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "vmode:", 6)) {
+	    		int vmode = simple_strtoul(this_opt+6, NULL, 0);
+			if (vmode > 0 && vmode <= VMODE_MAX)
+				default_vmode = vmode;
+		}
+		else if (!strncmp(this_opt, "cmode:", 6)) {
+			int depth = simple_strtoul(this_opt+6, NULL, 0);
+			switch (depth) {
+			case 8:
+				default_cmode = CMODE_8;
+				break;
+			case 15:
+			case 16:
+				default_cmode = CMODE_16;
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+module_init(valkyriefb_init);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/valkyriefb.h b/drivers/video/fbdev/valkyriefb.h
new file mode 100644
index 000000000000..d787441e5a42
--- /dev/null
+++ b/drivers/video/fbdev/valkyriefb.h
@@ -0,0 +1,200 @@
+/*
+ * valkyriefb.h: Constants of all sorts for valkyriefb
+ *
+ *  Created 8 August 1998 by 
+ *  Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel
+ *
+ * Vmode-switching changes and vmode 15/17 modifications created 29 August
+ * 1998 by Barry K. Nathan <barryn@pobox.com>.
+ * 
+ * vmode 10 changed by Steven Borley <sjb@salix.demon.co.uk>, 14 mai 2000
+ *
+ * Ported to 68k Macintosh by David Huggins-Daines <dhd@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Based directly on:
+ *
+ *  controlfb.h: Constants of all sorts for controlfb
+ *  Copyright (C) 1998 Daniel Jacobowitz <dan@debian.org>
+ *
+ *  pmc-valkyrie.h: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1997 Paul Mackerras.
+ *
+ *  pmc-valkyrie.c: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1997 Paul Mackerras.
+ *
+ * and indirectly from:
+ *
+ *  pmc-control.h: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1997 Paul Mackerras.
+ *
+ *  pmc-control.c: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1996 Paul Mackerras.
+ *
+ *  platinumfb.c: Console support for PowerMac "platinum" display adaptor.
+ *  Copyright (C) 1998 Jon Howell
+ */
+
+#ifdef CONFIG_MAC
+/* Valkyrie registers are word-aligned on m68k */
+#define VALKYRIE_REG_PADSIZE	3
+#else
+#define VALKYRIE_REG_PADSIZE	7
+#endif
+
+/*
+ * Structure of the registers for the Valkyrie colormap registers.
+ */
+struct cmap_regs {
+	unsigned char addr;
+	char pad1[VALKYRIE_REG_PADSIZE];
+	unsigned char lut;
+};
+
+/*
+ * Structure of the registers for the "valkyrie" display adaptor.
+ */
+
+struct vpreg {			/* padded register */
+	unsigned char r;
+	char pad[VALKYRIE_REG_PADSIZE];
+};
+
+
+struct valkyrie_regs {
+	struct vpreg mode;
+	struct vpreg depth;
+	struct vpreg status;
+	struct vpreg reg3;
+	struct vpreg intr;
+	struct vpreg reg5;
+	struct vpreg intr_enb;
+	struct vpreg msense;
+};
+
+/*
+ * Register initialization tables for the valkyrie display.
+ *
+ * Dot clock rate is
+ * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0].
+ */
+struct valkyrie_regvals {
+	unsigned char mode;
+	unsigned char clock_params[3];
+	int	pitch[2];		/* bytes/line, indexed by color_mode */
+	int	hres;
+	int	vres;
+};
+
+#ifndef CONFIG_MAC
+/* Register values for 1024x768, 75Hz mode (17) */
+/* I'm not sure which mode this is (16 or 17), so I'm defining it as 17,
+ * since the equivalent mode in controlfb (which I adapted this from) is
+ * also 17. Just because MacOS can't do this on Valkyrie doesn't mean we
+ * can't! :)
+ *
+ * I was going to use 12, 31, 3, which I found by myself, but instead I'm
+ * using 11, 28, 3 like controlfb, for consistency's sake.
+ */
+
+static struct valkyrie_regvals valkyrie_reg_init_17 = {
+    15, 
+    { 11, 28, 3 },  /* pixel clock = 79.55MHz for V=74.50Hz */
+    { 1024, 0 },
+	1024, 768
+};
+
+/* Register values for 1024x768, 72Hz mode (15) */
+/* This used to be 12, 30, 3 for pixel clock = 78.12MHz for V=72.12Hz, but
+ * that didn't match MacOS in the same video mode on this chip, and it also
+ * caused the 15" Apple Studio Display to not work in this mode. While this
+ * mode still doesn't match MacOS exactly (as far as I can tell), it's a lot
+ * closer now, and it works with the Apple Studio Display.
+ *
+ * Yes, even though MacOS calls it "72Hz", in reality it's about 70Hz.
+ */
+static struct valkyrie_regvals valkyrie_reg_init_15 = {
+    15,
+    { 12, 29, 3 },  /* pixel clock = 75.52MHz for V=69.71Hz? */
+		    /* I interpolated the V=69.71 from the vmode 14 and old 15
+		     * numbers. Is this result correct?
+		     */
+    { 1024, 0 },
+	1024, 768
+};
+
+/* Register values for 1024x768, 60Hz mode (14) */
+static struct valkyrie_regvals valkyrie_reg_init_14 = {
+    14,
+    { 15, 31, 3 },  /* pixel clock = 64.58MHz for V=59.62Hz */
+    { 1024, 0 },
+	1024, 768
+};
+#endif /* !defined CONFIG_MAC */
+
+/* Register values for 832x624, 75Hz mode (13) */
+static struct valkyrie_regvals valkyrie_reg_init_13 = {
+    9,
+    { 23, 42, 3 },  /* pixel clock = 57.07MHz for V=74.27Hz */
+    { 832, 0 },
+	832, 624
+};
+
+/* Register values for 800x600, 72Hz mode (11) */
+static struct valkyrie_regvals valkyrie_reg_init_11 = {
+    13,
+    { 17, 27, 3 },  /* pixel clock = 49.63MHz for V=71.66Hz */
+    { 800, 0 },
+	800, 600
+};
+
+/* Register values for 800x600, 60Hz mode (10) */
+static struct valkyrie_regvals valkyrie_reg_init_10 = {
+    12,
+    { 25, 32, 3 },  /* pixel clock = 40.0015MHz,
+                     used to be 20,53,2, pixel clock 41.41MHz for V=59.78Hz */
+    { 800, 1600 },
+	800, 600
+};
+
+/* Register values for 640x480, 67Hz mode (6) */
+static struct valkyrie_regvals valkyrie_reg_init_6 = {
+    6,
+    { 14, 27, 2 },  /* pixel clock = 30.13MHz for V=66.43Hz */
+    { 640, 1280 },
+	640, 480
+};
+
+/* Register values for 640x480, 60Hz mode (5) */
+static struct valkyrie_regvals valkyrie_reg_init_5 = {
+    11,
+    { 23, 37, 2 },  /* pixel clock = 25.14MHz for V=59.85Hz */
+    { 640, 1280 },
+	640, 480
+};
+
+static struct valkyrie_regvals *valkyrie_reg_init[VMODE_MAX] = {
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	&valkyrie_reg_init_5,
+	&valkyrie_reg_init_6,
+	NULL,
+	NULL,
+	NULL,
+	&valkyrie_reg_init_10,
+	&valkyrie_reg_init_11,
+	NULL,
+	&valkyrie_reg_init_13,
+#ifndef CONFIG_MAC
+	&valkyrie_reg_init_14,
+	&valkyrie_reg_init_15,
+	NULL,
+	&valkyrie_reg_init_17,
+#endif
+};
diff --git a/drivers/video/fbdev/vermilion/Makefile b/drivers/video/fbdev/vermilion/Makefile
new file mode 100644
index 000000000000..cc21a656153d
--- /dev/null
+++ b/drivers/video/fbdev/vermilion/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_FB_LE80578) += vmlfb.o
+obj-$(CONFIG_FB_CARILLO_RANCH) += crvml.o
+
+vmlfb-objs := vermilion.o
+crvml-objs := cr_pll.o
diff --git a/drivers/video/fbdev/vermilion/cr_pll.c b/drivers/video/fbdev/vermilion/cr_pll.c
new file mode 100644
index 000000000000..ebc6e6e0dd0f
--- /dev/null
+++ b/drivers/video/fbdev/vermilion/cr_pll.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) Intel Corp. 2007.
+ * All Rights Reserved.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ * This file is part of the Carillo Ranch video subsystem driver.
+ * The Carillo Ranch video subsystem driver is free software;
+ * you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Carillo Ranch video subsystem driver is distributed
+ * in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include "vermilion.h"
+
+/* The PLL Clock register sits on Host bridge */
+#define CRVML_DEVICE_MCH   0x5001
+#define CRVML_REG_MCHBAR   0x44
+#define CRVML_REG_MCHEN    0x54
+#define CRVML_MCHEN_BIT    (1 << 28)
+#define CRVML_MCHMAP_SIZE  4096
+#define CRVML_REG_CLOCK    0xc3c
+#define CRVML_CLOCK_SHIFT  8
+#define CRVML_CLOCK_MASK   0x00000f00
+
+static struct pci_dev *mch_dev;
+static u32 mch_bar;
+static void __iomem *mch_regs_base;
+static u32 saved_clock;
+
+static const unsigned crvml_clocks[] = {
+	6750,
+	13500,
+	27000,
+	29700,
+	37125,
+	54000,
+	59400,
+	74250,
+	120000
+	    /*
+	     * There are more clocks, but they are disabled on the CR board.
+	     */
+};
+
+static const u32 crvml_clock_bits[] = {
+	0x0a,
+	0x09,
+	0x08,
+	0x07,
+	0x06,
+	0x05,
+	0x04,
+	0x03,
+	0x0b
+};
+
+static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);
+
+static int crvml_sys_restore(struct vml_sys *sys)
+{
+	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
+
+	iowrite32(saved_clock, clock_reg);
+	ioread32(clock_reg);
+
+	return 0;
+}
+
+static int crvml_sys_save(struct vml_sys *sys)
+{
+	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
+
+	saved_clock = ioread32(clock_reg);
+
+	return 0;
+}
+
+static int crvml_nearest_index(const struct vml_sys *sys, int clock)
+{
+	int i;
+	int cur_index = 0;
+	int cur_diff;
+	int diff;
+
+	cur_diff = clock - crvml_clocks[0];
+	cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
+	for (i = 1; i < crvml_num_clocks; ++i) {
+		diff = clock - crvml_clocks[i];
+		diff = (diff < 0) ? -diff : diff;
+		if (diff < cur_diff) {
+			cur_index = i;
+			cur_diff = diff;
+		}
+	}
+	return cur_index;
+}
+
+static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
+{
+	return crvml_clocks[crvml_nearest_index(sys, clock)];
+}
+
+static int crvml_set_clock(struct vml_sys *sys, int clock)
+{
+	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
+	int index;
+	u32 clock_val;
+
+	index = crvml_nearest_index(sys, clock);
+
+	if (crvml_clocks[index] != clock)
+		return -EINVAL;
+
+	clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
+	clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
+	iowrite32(clock_val, clock_reg);
+	ioread32(clock_reg);
+
+	return 0;
+}
+
+static struct vml_sys cr_pll_ops = {
+	.name = "Carillo Ranch",
+	.save = crvml_sys_save,
+	.restore = crvml_sys_restore,
+	.set_clock = crvml_set_clock,
+	.nearest_clock = crvml_nearest_clock,
+};
+
+static int __init cr_pll_init(void)
+{
+	int err;
+	u32 dev_en;
+
+	mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+					CRVML_DEVICE_MCH, NULL);
+	if (!mch_dev) {
+		printk(KERN_ERR
+		       "Could not find Carillo Ranch MCH device.\n");
+		return -ENODEV;
+	}
+
+	pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
+	if (!(dev_en & CRVML_MCHEN_BIT)) {
+		printk(KERN_ERR
+		       "Carillo Ranch MCH device was not enabled.\n");
+		pci_dev_put(mch_dev);
+		return -ENODEV;
+	}
+
+	pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
+			      &mch_bar);
+	mch_regs_base =
+	    ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE);
+	if (!mch_regs_base) {
+		printk(KERN_ERR
+		       "Carillo Ranch MCH device was not enabled.\n");
+		pci_dev_put(mch_dev);
+		return -ENODEV;
+	}
+
+	err = vmlfb_register_subsys(&cr_pll_ops);
+	if (err) {
+		printk(KERN_ERR
+		       "Carillo Ranch failed to initialize vml_sys.\n");
+		pci_dev_put(mch_dev);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit cr_pll_exit(void)
+{
+	vmlfb_unregister_subsys(&cr_pll_ops);
+
+	iounmap(mch_regs_base);
+	pci_dev_put(mch_dev);
+}
+
+module_init(cr_pll_init);
+module_exit(cr_pll_exit);
+
+MODULE_AUTHOR("Tungsten Graphics Inc.");
+MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c
new file mode 100644
index 000000000000..048a66640b03
--- /dev/null
+++ b/drivers/video/fbdev/vermilion/vermilion.c
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (c) Intel Corp. 2007.
+ * All Rights Reserved.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ * This file is part of the Vermilion Range fb driver.
+ * The Vermilion Range fb driver is free software;
+ * you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Vermilion Range fb driver is distributed
+ * in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ *   Michel Dänzer <michel-at-tungstengraphics-dot-com>
+ *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <linux/mmzone.h>
+
+/* #define VERMILION_DEBUG */
+
+#include "vermilion.h"
+
+#define MODULE_NAME "vmlfb"
+
+#define VML_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+
+static struct mutex vml_mutex;
+static struct list_head global_no_mode;
+static struct list_head global_has_mode;
+static struct fb_ops vmlfb_ops;
+static struct vml_sys *subsys = NULL;
+static char *vml_default_mode = "1024x768@60";
+static struct fb_videomode defaultmode = {
+	NULL, 60, 1024, 768, 12896, 144, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+};
+
+static u32 vml_mem_requested = (10 * 1024 * 1024);
+static u32 vml_mem_contig = (4 * 1024 * 1024);
+static u32 vml_mem_min = (4 * 1024 * 1024);
+
+static u32 vml_clocks[] = {
+	6750,
+	13500,
+	27000,
+	29700,
+	37125,
+	54000,
+	59400,
+	74250,
+	120000,
+	148500
+};
+
+static u32 vml_num_clocks = ARRAY_SIZE(vml_clocks);
+
+/*
+ * Allocate a contiguous vram area and make its linear kernel map
+ * uncached.
+ */
+
+static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order,
+				 unsigned min_order)
+{
+	gfp_t flags;
+	unsigned long i;
+
+	max_order++;
+	do {
+		/*
+		 * Really try hard to get the needed memory.
+		 * We need memory below the first 32MB, so we
+		 * add the __GFP_DMA flag that guarantees that we are
+		 * below the first 16MB.
+		 */
+
+		flags = __GFP_DMA | __GFP_HIGH;
+		va->logical =
+			 __get_free_pages(flags, --max_order);
+	} while (va->logical == 0 && max_order > min_order);
+
+	if (!va->logical)
+		return -ENOMEM;
+
+	va->phys = virt_to_phys((void *)va->logical);
+	va->size = PAGE_SIZE << max_order;
+	va->order = max_order;
+
+	/*
+	 * It seems like __get_free_pages only ups the usage count
+	 * of the first page. This doesn't work with fault mapping, so
+	 * up the usage count once more (XXX: should use split_page or
+	 * compound page).
+	 */
+
+	memset((void *)va->logical, 0x00, va->size);
+	for (i = va->logical; i < va->logical + va->size; i += PAGE_SIZE) {
+		get_page(virt_to_page(i));
+	}
+
+	/*
+	 * Change caching policy of the linear kernel map to avoid
+	 * mapping type conflicts with user-space mappings.
+	 */
+	set_pages_uc(virt_to_page(va->logical), va->size >> PAGE_SHIFT);
+
+	printk(KERN_DEBUG MODULE_NAME
+	       ": Allocated %ld bytes vram area at 0x%08lx\n",
+	       va->size, va->phys);
+
+	return 0;
+}
+
+/*
+ * Free a contiguous vram area and reset its linear kernel map
+ * mapping type.
+ */
+
+static void vmlfb_free_vram_area(struct vram_area *va)
+{
+	unsigned long j;
+
+	if (va->logical) {
+
+		/*
+		 * Reset the linear kernel map caching policy.
+		 */
+
+		set_pages_wb(virt_to_page(va->logical),
+				 va->size >> PAGE_SHIFT);
+
+		/*
+		 * Decrease the usage count on the pages we've used
+		 * to compensate for upping when allocating.
+		 */
+
+		for (j = va->logical; j < va->logical + va->size;
+		     j += PAGE_SIZE) {
+			(void)put_page_testzero(virt_to_page(j));
+		}
+
+		printk(KERN_DEBUG MODULE_NAME
+		       ": Freeing %ld bytes vram area at 0x%08lx\n",
+		       va->size, va->phys);
+		free_pages(va->logical, va->order);
+
+		va->logical = 0;
+	}
+}
+
+/*
+ * Free allocated vram.
+ */
+
+static void vmlfb_free_vram(struct vml_info *vinfo)
+{
+	int i;
+
+	for (i = 0; i < vinfo->num_areas; ++i) {
+		vmlfb_free_vram_area(&vinfo->vram[i]);
+	}
+	vinfo->num_areas = 0;
+}
+
+/*
+ * Allocate vram. Currently we try to allocate contiguous areas from the
+ * __GFP_DMA zone and puzzle them together. A better approach would be to
+ * allocate one contiguous area for scanout and use one-page allocations for
+ * offscreen areas. This requires user-space and GPU virtual mappings.
+ */
+
+static int vmlfb_alloc_vram(struct vml_info *vinfo,
+			    size_t requested,
+			    size_t min_total, size_t min_contig)
+{
+	int i, j;
+	int order;
+	int contiguous;
+	int err;
+	struct vram_area *va;
+	struct vram_area *va2;
+
+	vinfo->num_areas = 0;
+	for (i = 0; i < VML_VRAM_AREAS; ++i) {
+		va = &vinfo->vram[i];
+		order = 0;
+
+		while (requested > (PAGE_SIZE << order) && order < MAX_ORDER)
+			order++;
+
+		err = vmlfb_alloc_vram_area(va, order, 0);
+
+		if (err)
+			break;
+
+		if (i == 0) {
+			vinfo->vram_start = va->phys;
+			vinfo->vram_logical = (void __iomem *) va->logical;
+			vinfo->vram_contig_size = va->size;
+			vinfo->num_areas = 1;
+		} else {
+			contiguous = 0;
+
+			for (j = 0; j < i; ++j) {
+				va2 = &vinfo->vram[j];
+				if (va->phys + va->size == va2->phys ||
+				    va2->phys + va2->size == va->phys) {
+					contiguous = 1;
+					break;
+				}
+			}
+
+			if (contiguous) {
+				vinfo->num_areas++;
+				if (va->phys < vinfo->vram_start) {
+					vinfo->vram_start = va->phys;
+					vinfo->vram_logical =
+						(void __iomem *)va->logical;
+				}
+				vinfo->vram_contig_size += va->size;
+			} else {
+				vmlfb_free_vram_area(va);
+				break;
+			}
+		}
+
+		if (requested < va->size)
+			break;
+		else
+			requested -= va->size;
+	}
+
+	if (vinfo->vram_contig_size > min_total &&
+	    vinfo->vram_contig_size > min_contig) {
+
+		printk(KERN_DEBUG MODULE_NAME
+		       ": Contiguous vram: %ld bytes at physical 0x%08lx.\n",
+		       (unsigned long)vinfo->vram_contig_size,
+		       (unsigned long)vinfo->vram_start);
+
+		return 0;
+	}
+
+	printk(KERN_ERR MODULE_NAME
+	       ": Could not allocate requested minimal amount of vram.\n");
+
+	vmlfb_free_vram(vinfo);
+
+	return -ENOMEM;
+}
+
+/*
+ * Find the GPU to use with our display controller.
+ */
+
+static int vmlfb_get_gpu(struct vml_par *par)
+{
+	mutex_lock(&vml_mutex);
+
+	par->gpu = pci_get_device(PCI_VENDOR_ID_INTEL, VML_DEVICE_GPU, NULL);
+
+	if (!par->gpu) {
+		mutex_unlock(&vml_mutex);
+		return -ENODEV;
+	}
+
+	mutex_unlock(&vml_mutex);
+
+	if (pci_enable_device(par->gpu) < 0)
+		return -ENODEV;
+
+	return 0;
+}
+
+/*
+ * Find a contiguous vram area that contains a given offset from vram start.
+ */
+static int vmlfb_vram_offset(struct vml_info *vinfo, unsigned long offset)
+{
+	unsigned long aoffset;
+	unsigned i;
+
+	for (i = 0; i < vinfo->num_areas; ++i) {
+		aoffset = offset - (vinfo->vram[i].phys - vinfo->vram_start);
+
+		if (aoffset < vinfo->vram[i].size) {
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * Remap the MMIO register spaces of the VDC and the GPU.
+ */
+
+static int vmlfb_enable_mmio(struct vml_par *par)
+{
+	int err;
+
+	par->vdc_mem_base = pci_resource_start(par->vdc, 0);
+	par->vdc_mem_size = pci_resource_len(par->vdc, 0);
+	if (!request_mem_region(par->vdc_mem_base, par->vdc_mem_size, "vmlfb")) {
+		printk(KERN_ERR MODULE_NAME
+		       ": Could not claim display controller MMIO.\n");
+		return -EBUSY;
+	}
+	par->vdc_mem = ioremap_nocache(par->vdc_mem_base, par->vdc_mem_size);
+	if (par->vdc_mem == NULL) {
+		printk(KERN_ERR MODULE_NAME
+		       ": Could not map display controller MMIO.\n");
+		err = -ENOMEM;
+		goto out_err_0;
+	}
+
+	par->gpu_mem_base = pci_resource_start(par->gpu, 0);
+	par->gpu_mem_size = pci_resource_len(par->gpu, 0);
+	if (!request_mem_region(par->gpu_mem_base, par->gpu_mem_size, "vmlfb")) {
+		printk(KERN_ERR MODULE_NAME ": Could not claim GPU MMIO.\n");
+		err = -EBUSY;
+		goto out_err_1;
+	}
+	par->gpu_mem = ioremap_nocache(par->gpu_mem_base, par->gpu_mem_size);
+	if (par->gpu_mem == NULL) {
+		printk(KERN_ERR MODULE_NAME ": Could not map GPU MMIO.\n");
+		err = -ENOMEM;
+		goto out_err_2;
+	}
+
+	return 0;
+
+out_err_2:
+	release_mem_region(par->gpu_mem_base, par->gpu_mem_size);
+out_err_1:
+	iounmap(par->vdc_mem);
+out_err_0:
+	release_mem_region(par->vdc_mem_base, par->vdc_mem_size);
+	return err;
+}
+
+/*
+ * Unmap the VDC and GPU register spaces.
+ */
+
+static void vmlfb_disable_mmio(struct vml_par *par)
+{
+	iounmap(par->gpu_mem);
+	release_mem_region(par->gpu_mem_base, par->gpu_mem_size);
+	iounmap(par->vdc_mem);
+	release_mem_region(par->vdc_mem_base, par->vdc_mem_size);
+}
+
+/*
+ * Release and uninit the VDC and GPU.
+ */
+
+static void vmlfb_release_devices(struct vml_par *par)
+{
+	if (atomic_dec_and_test(&par->refcount)) {
+		pci_disable_device(par->gpu);
+		pci_disable_device(par->vdc);
+	}
+}
+
+/*
+ * Free up allocated resources for a device.
+ */
+
+static void vml_pci_remove(struct pci_dev *dev)
+{
+	struct fb_info *info;
+	struct vml_info *vinfo;
+	struct vml_par *par;
+
+	info = pci_get_drvdata(dev);
+	if (info) {
+		vinfo = container_of(info, struct vml_info, info);
+		par = vinfo->par;
+		mutex_lock(&vml_mutex);
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		vmlfb_free_vram(vinfo);
+		vmlfb_disable_mmio(par);
+		vmlfb_release_devices(par);
+		kfree(vinfo);
+		kfree(par);
+		mutex_unlock(&vml_mutex);
+	}
+}
+
+static void vmlfb_set_pref_pixel_format(struct fb_var_screeninfo *var)
+{
+	switch (var->bits_per_pixel) {
+	case 16:
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->green.offset = 5;
+		var->green.length = 5;
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->transp.offset = 15;
+		var->transp.length = 1;
+		break;
+	case 32:
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 0;
+		break;
+	default:
+		break;
+	}
+
+	var->blue.msb_right = var->green.msb_right =
+	    var->red.msb_right = var->transp.msb_right = 0;
+}
+
+/*
+ * Device initialization.
+ * We initialize one vml_par struct per device and one vml_info
+ * struct per pipe. Currently we have only one pipe.
+ */
+
+static int vml_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct vml_info *vinfo;
+	struct fb_info *info;
+	struct vml_par *par;
+	int err = 0;
+
+	par = kzalloc(sizeof(*par), GFP_KERNEL);
+	if (par == NULL)
+		return -ENOMEM;
+
+	vinfo = kzalloc(sizeof(*vinfo), GFP_KERNEL);
+	if (vinfo == NULL) {
+		err = -ENOMEM;
+		goto out_err_0;
+	}
+
+	vinfo->par = par;
+	par->vdc = dev;
+	atomic_set(&par->refcount, 1);
+
+	switch (id->device) {
+	case VML_DEVICE_VDC:
+		if ((err = vmlfb_get_gpu(par)))
+			goto out_err_1;
+		pci_set_drvdata(dev, &vinfo->info);
+		break;
+	default:
+		err = -ENODEV;
+		goto out_err_1;
+		break;
+	}
+
+	info = &vinfo->info;
+	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK;
+
+	err = vmlfb_enable_mmio(par);
+	if (err)
+		goto out_err_2;
+
+	err = vmlfb_alloc_vram(vinfo, vml_mem_requested,
+			       vml_mem_contig, vml_mem_min);
+	if (err)
+		goto out_err_3;
+
+	strcpy(info->fix.id, "Vermilion Range");
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+	info->fix.smem_start = vinfo->vram_start;
+	info->fix.smem_len = vinfo->vram_contig_size;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.ypanstep = 1;
+	info->fix.xpanstep = 1;
+	info->fix.ywrapstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->screen_base = vinfo->vram_logical;
+	info->pseudo_palette = vinfo->pseudo_palette;
+	info->par = par;
+	info->fbops = &vmlfb_ops;
+	info->device = &dev->dev;
+
+	INIT_LIST_HEAD(&vinfo->head);
+	vinfo->pipe_disabled = 1;
+	vinfo->cur_blank_mode = FB_BLANK_UNBLANK;
+
+	info->var.grayscale = 0;
+	info->var.bits_per_pixel = 16;
+	vmlfb_set_pref_pixel_format(&info->var);
+
+	if (!fb_find_mode
+	    (&info->var, info, vml_default_mode, NULL, 0, &defaultmode, 16)) {
+		printk(KERN_ERR MODULE_NAME ": Could not find initial mode\n");
+	}
+
+	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
+		err = -ENOMEM;
+		goto out_err_4;
+	}
+
+	err = register_framebuffer(info);
+	if (err) {
+		printk(KERN_ERR MODULE_NAME ": Register framebuffer error.\n");
+		goto out_err_5;
+	}
+
+	printk("Initialized vmlfb\n");
+
+	return 0;
+
+out_err_5:
+	fb_dealloc_cmap(&info->cmap);
+out_err_4:
+	vmlfb_free_vram(vinfo);
+out_err_3:
+	vmlfb_disable_mmio(par);
+out_err_2:
+	vmlfb_release_devices(par);
+out_err_1:
+	kfree(vinfo);
+out_err_0:
+	kfree(par);
+	return err;
+}
+
+static int vmlfb_open(struct fb_info *info, int user)
+{
+	/*
+	 * Save registers here?
+	 */
+	return 0;
+}
+
+static int vmlfb_release(struct fb_info *info, int user)
+{
+	/*
+	 * Restore registers here.
+	 */
+
+	return 0;
+}
+
+static int vml_nearest_clock(int clock)
+{
+
+	int i;
+	int cur_index;
+	int cur_diff;
+	int diff;
+
+	cur_index = 0;
+	cur_diff = clock - vml_clocks[0];
+	cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
+	for (i = 1; i < vml_num_clocks; ++i) {
+		diff = clock - vml_clocks[i];
+		diff = (diff < 0) ? -diff : diff;
+		if (diff < cur_diff) {
+			cur_index = i;
+			cur_diff = diff;
+		}
+	}
+	return vml_clocks[cur_index];
+}
+
+static int vmlfb_check_var_locked(struct fb_var_screeninfo *var,
+				  struct vml_info *vinfo)
+{
+	u32 pitch;
+	u64 mem;
+	int nearest_clock;
+	int clock;
+	int clock_diff;
+	struct fb_var_screeninfo v;
+
+	v = *var;
+	clock = PICOS2KHZ(var->pixclock);
+
+	if (subsys && subsys->nearest_clock) {
+		nearest_clock = subsys->nearest_clock(subsys, clock);
+	} else {
+		nearest_clock = vml_nearest_clock(clock);
+	}
+
+	/*
+	 * Accept a 20% diff.
+	 */
+
+	clock_diff = nearest_clock - clock;
+	clock_diff = (clock_diff < 0) ? -clock_diff : clock_diff;
+	if (clock_diff > clock / 5) {
+#if 0
+		printk(KERN_DEBUG MODULE_NAME ": Diff failure. %d %d\n",clock_diff,clock);
+#endif
+		return -EINVAL;
+	}
+
+	v.pixclock = KHZ2PICOS(nearest_clock);
+
+	if (var->xres > VML_MAX_XRES || var->yres > VML_MAX_YRES) {
+		printk(KERN_DEBUG MODULE_NAME ": Resolution failure.\n");
+		return -EINVAL;
+	}
+	if (var->xres_virtual > VML_MAX_XRES_VIRTUAL) {
+		printk(KERN_DEBUG MODULE_NAME
+		       ": Virtual resolution failure.\n");
+		return -EINVAL;
+	}
+	switch (v.bits_per_pixel) {
+	case 0 ... 16:
+		v.bits_per_pixel = 16;
+		break;
+	case 17 ... 32:
+		v.bits_per_pixel = 32;
+		break;
+	default:
+		printk(KERN_DEBUG MODULE_NAME ": Invalid bpp: %d.\n",
+		       var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	pitch = ALIGN((var->xres * var->bits_per_pixel) >> 3, 0x40);
+	mem = pitch * var->yres_virtual;
+	if (mem > vinfo->vram_contig_size) {
+		return -ENOMEM;
+	}
+
+	switch (v.bits_per_pixel) {
+	case 16:
+		if (var->blue.offset != 0 ||
+		    var->blue.length != 5 ||
+		    var->green.offset != 5 ||
+		    var->green.length != 5 ||
+		    var->red.offset != 10 ||
+		    var->red.length != 5 ||
+		    var->transp.offset != 15 || var->transp.length != 1) {
+			vmlfb_set_pref_pixel_format(&v);
+		}
+		break;
+	case 32:
+		if (var->blue.offset != 0 ||
+		    var->blue.length != 8 ||
+		    var->green.offset != 8 ||
+		    var->green.length != 8 ||
+		    var->red.offset != 16 ||
+		    var->red.length != 8 ||
+		    (var->transp.length != 0 && var->transp.length != 8) ||
+		    (var->transp.length == 8 && var->transp.offset != 24)) {
+			vmlfb_set_pref_pixel_format(&v);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*var = v;
+
+	return 0;
+}
+
+static int vmlfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct vml_info *vinfo = container_of(info, struct vml_info, info);
+	int ret;
+
+	mutex_lock(&vml_mutex);
+	ret = vmlfb_check_var_locked(var, vinfo);
+	mutex_unlock(&vml_mutex);
+
+	return ret;
+}
+
+static void vml_wait_vblank(struct vml_info *vinfo)
+{
+	/* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
+	mdelay(20);
+}
+
+static void vmlfb_disable_pipe(struct vml_info *vinfo)
+{
+	struct vml_par *par = vinfo->par;
+
+	/* Disable the MDVO pad */
+	VML_WRITE32(par, VML_RCOMPSTAT, 0);
+	while (!(VML_READ32(par, VML_RCOMPSTAT) & VML_MDVO_VDC_I_RCOMP)) ;
+
+	/* Disable display planes */
+	VML_WRITE32(par, VML_DSPCCNTR,
+		    VML_READ32(par, VML_DSPCCNTR) & ~VML_GFX_ENABLE);
+	(void)VML_READ32(par, VML_DSPCCNTR);
+	/* Wait for vblank for the disable to take effect */
+	vml_wait_vblank(vinfo);
+
+	/* Next, disable display pipes */
+	VML_WRITE32(par, VML_PIPEACONF, 0);
+	(void)VML_READ32(par, VML_PIPEACONF);
+
+	vinfo->pipe_disabled = 1;
+}
+
+#ifdef VERMILION_DEBUG
+static void vml_dump_regs(struct vml_info *vinfo)
+{
+	struct vml_par *par = vinfo->par;
+
+	printk(KERN_DEBUG MODULE_NAME ": Modesetting register dump:\n");
+	printk(KERN_DEBUG MODULE_NAME ": \tHTOTAL_A         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_HTOTAL_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tHBLANK_A         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_HBLANK_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tHSYNC_A          : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_HSYNC_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tVTOTAL_A         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_VTOTAL_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tVBLANK_A         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_VBLANK_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tVSYNC_A          : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_VSYNC_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tDSPCSTRIDE       : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_DSPCSTRIDE));
+	printk(KERN_DEBUG MODULE_NAME ": \tDSPCSIZE         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_DSPCSIZE));
+	printk(KERN_DEBUG MODULE_NAME ": \tDSPCPOS          : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_DSPCPOS));
+	printk(KERN_DEBUG MODULE_NAME ": \tDSPARB           : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_DSPARB));
+	printk(KERN_DEBUG MODULE_NAME ": \tDSPCADDR         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_DSPCADDR));
+	printk(KERN_DEBUG MODULE_NAME ": \tBCLRPAT_A        : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_BCLRPAT_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tCANVSCLR_A       : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_CANVSCLR_A));
+	printk(KERN_DEBUG MODULE_NAME ": \tPIPEASRC         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_PIPEASRC));
+	printk(KERN_DEBUG MODULE_NAME ": \tPIPEACONF        : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_PIPEACONF));
+	printk(KERN_DEBUG MODULE_NAME ": \tDSPCCNTR         : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_DSPCCNTR));
+	printk(KERN_DEBUG MODULE_NAME ": \tRCOMPSTAT        : 0x%08x\n",
+	       (unsigned)VML_READ32(par, VML_RCOMPSTAT));
+	printk(KERN_DEBUG MODULE_NAME ": End of modesetting register dump.\n");
+}
+#endif
+
+static int vmlfb_set_par_locked(struct vml_info *vinfo)
+{
+	struct vml_par *par = vinfo->par;
+	struct fb_info *info = &vinfo->info;
+	struct fb_var_screeninfo *var = &info->var;
+	u32 htotal, hactive, hblank_start, hblank_end, hsync_start, hsync_end;
+	u32 vtotal, vactive, vblank_start, vblank_end, vsync_start, vsync_end;
+	u32 dspcntr;
+	int clock;
+
+	vinfo->bytes_per_pixel = var->bits_per_pixel >> 3;
+	vinfo->stride = ALIGN(var->xres_virtual * vinfo->bytes_per_pixel, 0x40);
+	info->fix.line_length = vinfo->stride;
+
+	if (!subsys)
+		return 0;
+
+	htotal =
+	    var->xres + var->right_margin + var->hsync_len + var->left_margin;
+	hactive = var->xres;
+	hblank_start = var->xres;
+	hblank_end = htotal;
+	hsync_start = hactive + var->right_margin;
+	hsync_end = hsync_start + var->hsync_len;
+
+	vtotal =
+	    var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
+	vactive = var->yres;
+	vblank_start = var->yres;
+	vblank_end = vtotal;
+	vsync_start = vactive + var->lower_margin;
+	vsync_end = vsync_start + var->vsync_len;
+
+	dspcntr = VML_GFX_ENABLE | VML_GFX_GAMMABYPASS;
+	clock = PICOS2KHZ(var->pixclock);
+
+	if (subsys->nearest_clock) {
+		clock = subsys->nearest_clock(subsys, clock);
+	} else {
+		clock = vml_nearest_clock(clock);
+	}
+	printk(KERN_DEBUG MODULE_NAME
+	       ": Set mode Hfreq : %d kHz, Vfreq : %d Hz.\n", clock / htotal,
+	       ((clock / htotal) * 1000) / vtotal);
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		dspcntr |= VML_GFX_ARGB1555;
+		break;
+	case 32:
+		if (var->transp.length == 8)
+			dspcntr |= VML_GFX_ARGB8888 | VML_GFX_ALPHAMULT;
+		else
+			dspcntr |= VML_GFX_RGB0888;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	vmlfb_disable_pipe(vinfo);
+	mb();
+
+	if (subsys->set_clock)
+		subsys->set_clock(subsys, clock);
+	else
+		return -EINVAL;
+
+	VML_WRITE32(par, VML_HTOTAL_A, ((htotal - 1) << 16) | (hactive - 1));
+	VML_WRITE32(par, VML_HBLANK_A,
+		    ((hblank_end - 1) << 16) | (hblank_start - 1));
+	VML_WRITE32(par, VML_HSYNC_A,
+		    ((hsync_end - 1) << 16) | (hsync_start - 1));
+	VML_WRITE32(par, VML_VTOTAL_A, ((vtotal - 1) << 16) | (vactive - 1));
+	VML_WRITE32(par, VML_VBLANK_A,
+		    ((vblank_end - 1) << 16) | (vblank_start - 1));
+	VML_WRITE32(par, VML_VSYNC_A,
+		    ((vsync_end - 1) << 16) | (vsync_start - 1));
+	VML_WRITE32(par, VML_DSPCSTRIDE, vinfo->stride);
+	VML_WRITE32(par, VML_DSPCSIZE,
+		    ((var->yres - 1) << 16) | (var->xres - 1));
+	VML_WRITE32(par, VML_DSPCPOS, 0x00000000);
+	VML_WRITE32(par, VML_DSPARB, VML_FIFO_DEFAULT);
+	VML_WRITE32(par, VML_BCLRPAT_A, 0x00000000);
+	VML_WRITE32(par, VML_CANVSCLR_A, 0x00000000);
+	VML_WRITE32(par, VML_PIPEASRC,
+		    ((var->xres - 1) << 16) | (var->yres - 1));
+
+	wmb();
+	VML_WRITE32(par, VML_PIPEACONF, VML_PIPE_ENABLE);
+	wmb();
+	VML_WRITE32(par, VML_DSPCCNTR, dspcntr);
+	wmb();
+	VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start +
+		    var->yoffset * vinfo->stride +
+		    var->xoffset * vinfo->bytes_per_pixel);
+
+	VML_WRITE32(par, VML_RCOMPSTAT, VML_MDVO_PAD_ENABLE);
+
+	while (!(VML_READ32(par, VML_RCOMPSTAT) &
+		 (VML_MDVO_VDC_I_RCOMP | VML_MDVO_PAD_ENABLE))) ;
+
+	vinfo->pipe_disabled = 0;
+#ifdef VERMILION_DEBUG
+	vml_dump_regs(vinfo);
+#endif
+
+	return 0;
+}
+
+static int vmlfb_set_par(struct fb_info *info)
+{
+	struct vml_info *vinfo = container_of(info, struct vml_info, info);
+	int ret;
+
+	mutex_lock(&vml_mutex);
+	list_move(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode);
+	ret = vmlfb_set_par_locked(vinfo);
+
+	mutex_unlock(&vml_mutex);
+	return ret;
+}
+
+static int vmlfb_blank_locked(struct vml_info *vinfo)
+{
+	struct vml_par *par = vinfo->par;
+	u32 cur = VML_READ32(par, VML_PIPEACONF);
+
+	switch (vinfo->cur_blank_mode) {
+	case FB_BLANK_UNBLANK:
+		if (vinfo->pipe_disabled) {
+			vmlfb_set_par_locked(vinfo);
+		}
+		VML_WRITE32(par, VML_PIPEACONF, cur & ~VML_PIPE_FORCE_BORDER);
+		(void)VML_READ32(par, VML_PIPEACONF);
+		break;
+	case FB_BLANK_NORMAL:
+		if (vinfo->pipe_disabled) {
+			vmlfb_set_par_locked(vinfo);
+		}
+		VML_WRITE32(par, VML_PIPEACONF, cur | VML_PIPE_FORCE_BORDER);
+		(void)VML_READ32(par, VML_PIPEACONF);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+		if (!vinfo->pipe_disabled) {
+			vmlfb_disable_pipe(vinfo);
+		}
+		break;
+	case FB_BLANK_POWERDOWN:
+		if (!vinfo->pipe_disabled) {
+			vmlfb_disable_pipe(vinfo);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vmlfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct vml_info *vinfo = container_of(info, struct vml_info, info);
+	int ret;
+
+	mutex_lock(&vml_mutex);
+	vinfo->cur_blank_mode = blank_mode;
+	ret = vmlfb_blank_locked(vinfo);
+	mutex_unlock(&vml_mutex);
+	return ret;
+}
+
+static int vmlfb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct vml_info *vinfo = container_of(info, struct vml_info, info);
+	struct vml_par *par = vinfo->par;
+
+	mutex_lock(&vml_mutex);
+	VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start +
+		    var->yoffset * vinfo->stride +
+		    var->xoffset * vinfo->bytes_per_pixel);
+	(void)VML_READ32(par, VML_DSPCADDR);
+	mutex_unlock(&vml_mutex);
+
+	return 0;
+}
+
+static int vmlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info)
+{
+	u32 v;
+
+	if (regno >= 16)
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (info->fix.visual != FB_VISUAL_TRUECOLOR)
+		return -EINVAL;
+
+	red = VML_TOHW(red, info->var.red.length);
+	blue = VML_TOHW(blue, info->var.blue.length);
+	green = VML_TOHW(green, info->var.green.length);
+	transp = VML_TOHW(transp, info->var.transp.length);
+
+	v = (red << info->var.red.offset) |
+	    (green << info->var.green.offset) |
+	    (blue << info->var.blue.offset) |
+	    (transp << info->var.transp.offset);
+
+	switch (info->var.bits_per_pixel) {
+	case 16:
+		((u32 *) info->pseudo_palette)[regno] = v;
+		break;
+	case 24:
+	case 32:
+		((u32 *) info->pseudo_palette)[regno] = v;
+		break;
+	}
+	return 0;
+}
+
+static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct vml_info *vinfo = container_of(info, struct vml_info, info);
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	int ret;
+
+	ret = vmlfb_vram_offset(vinfo, offset);
+	if (ret)
+		return -EINVAL;
+
+	pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+	pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
+
+	return vm_iomap_memory(vma, vinfo->vram_start,
+			vinfo->vram_contig_size);
+}
+
+static int vmlfb_sync(struct fb_info *info)
+{
+	return 0;
+}
+
+static int vmlfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static struct fb_ops vmlfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = vmlfb_open,
+	.fb_release = vmlfb_release,
+	.fb_check_var = vmlfb_check_var,
+	.fb_set_par = vmlfb_set_par,
+	.fb_blank = vmlfb_blank,
+	.fb_pan_display = vmlfb_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = vmlfb_cursor,
+	.fb_sync = vmlfb_sync,
+	.fb_mmap = vmlfb_mmap,
+	.fb_setcolreg = vmlfb_setcolreg
+};
+
+static struct pci_device_id vml_ids[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, VML_DEVICE_VDC)},
+	{0}
+};
+
+static struct pci_driver vmlfb_pci_driver = {
+	.name = "vmlfb",
+	.id_table = vml_ids,
+	.probe = vml_pci_probe,
+	.remove = vml_pci_remove,
+};
+
+static void __exit vmlfb_cleanup(void)
+{
+	pci_unregister_driver(&vmlfb_pci_driver);
+}
+
+static int __init vmlfb_init(void)
+{
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options(MODULE_NAME, &option))
+		return -ENODEV;
+#endif
+
+	printk(KERN_DEBUG MODULE_NAME ": initializing\n");
+	mutex_init(&vml_mutex);
+	INIT_LIST_HEAD(&global_no_mode);
+	INIT_LIST_HEAD(&global_has_mode);
+
+	return pci_register_driver(&vmlfb_pci_driver);
+}
+
+int vmlfb_register_subsys(struct vml_sys *sys)
+{
+	struct vml_info *entry;
+	struct list_head *list;
+	u32 save_activate;
+
+	mutex_lock(&vml_mutex);
+	if (subsys != NULL) {
+		subsys->restore(subsys);
+	}
+	subsys = sys;
+	subsys->save(subsys);
+
+	/*
+	 * We need to restart list traversal for each item, since we
+	 * release the list mutex in the loop.
+	 */
+
+	list = global_no_mode.next;
+	while (list != &global_no_mode) {
+		list_del_init(list);
+		entry = list_entry(list, struct vml_info, head);
+
+		/*
+		 * First, try the current mode which might not be
+		 * completely validated with respect to the pixel clock.
+		 */
+
+		if (!vmlfb_check_var_locked(&entry->info.var, entry)) {
+			vmlfb_set_par_locked(entry);
+			list_add_tail(list, &global_has_mode);
+		} else {
+
+			/*
+			 * Didn't work. Try to find another mode,
+			 * that matches this subsys.
+			 */
+
+			mutex_unlock(&vml_mutex);
+			save_activate = entry->info.var.activate;
+			entry->info.var.bits_per_pixel = 16;
+			vmlfb_set_pref_pixel_format(&entry->info.var);
+			if (fb_find_mode(&entry->info.var,
+					 &entry->info,
+					 vml_default_mode, NULL, 0, NULL, 16)) {
+				entry->info.var.activate |=
+				    FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
+				fb_set_var(&entry->info, &entry->info.var);
+			} else {
+				printk(KERN_ERR MODULE_NAME
+				       ": Sorry. no mode found for this subsys.\n");
+			}
+			entry->info.var.activate = save_activate;
+			mutex_lock(&vml_mutex);
+		}
+		vmlfb_blank_locked(entry);
+		list = global_no_mode.next;
+	}
+	mutex_unlock(&vml_mutex);
+
+	printk(KERN_DEBUG MODULE_NAME ": Registered %s subsystem.\n",
+				subsys->name ? subsys->name : "unknown");
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(vmlfb_register_subsys);
+
+void vmlfb_unregister_subsys(struct vml_sys *sys)
+{
+	struct vml_info *entry, *next;
+
+	mutex_lock(&vml_mutex);
+	if (subsys != sys) {
+		mutex_unlock(&vml_mutex);
+		return;
+	}
+	subsys->restore(subsys);
+	subsys = NULL;
+	list_for_each_entry_safe(entry, next, &global_has_mode, head) {
+		printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n");
+		vmlfb_disable_pipe(entry);
+		list_move_tail(&entry->head, &global_no_mode);
+	}
+	mutex_unlock(&vml_mutex);
+}
+
+EXPORT_SYMBOL_GPL(vmlfb_unregister_subsys);
+
+module_init(vmlfb_init);
+module_exit(vmlfb_cleanup);
+
+MODULE_AUTHOR("Tungsten Graphics");
+MODULE_DESCRIPTION("Initialization of the Vermilion display devices");
+MODULE_VERSION("1.0.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/vermilion/vermilion.h b/drivers/video/fbdev/vermilion/vermilion.h
new file mode 100644
index 000000000000..43d11ec197fc
--- /dev/null
+++ b/drivers/video/fbdev/vermilion/vermilion.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) Intel Corp. 2007.
+ * All Rights Reserved.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ * This file is part of the Vermilion Range fb driver.
+ * The Vermilion Range fb driver is free software;
+ * you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Vermilion Range fb driver is distributed
+ * in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _VERMILION_H_
+#define _VERMILION_H_
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/atomic.h>
+#include <linux/mutex.h>
+
+#define VML_DEVICE_GPU 0x5002
+#define VML_DEVICE_VDC 0x5009
+
+#define VML_VRAM_AREAS 3
+#define VML_MAX_XRES 1024
+#define VML_MAX_YRES 768
+#define VML_MAX_XRES_VIRTUAL 1040
+
+/*
+ * Display controller registers:
+ */
+
+/* Display controller 10-bit color representation */
+
+#define VML_R_MASK                   0x3FF00000
+#define VML_R_SHIFT                  20
+#define VML_G_MASK                   0x000FFC00
+#define VML_G_SHIFT                  10
+#define VML_B_MASK                   0x000003FF
+#define VML_B_SHIFT                  0
+
+/* Graphics plane control */
+#define VML_DSPCCNTR                 0x00072180
+#define VML_GFX_ENABLE               0x80000000
+#define VML_GFX_GAMMABYPASS          0x40000000
+#define VML_GFX_ARGB1555             0x0C000000
+#define VML_GFX_RGB0888              0x18000000
+#define VML_GFX_ARGB8888             0x1C000000
+#define VML_GFX_ALPHACONST           0x02000000
+#define VML_GFX_ALPHAMULT            0x01000000
+#define VML_GFX_CONST_ALPHA          0x000000FF
+
+/* Graphics plane start address. Pixel aligned. */
+#define VML_DSPCADDR                 0x00072184
+
+/* Graphics plane stride register. */
+#define VML_DSPCSTRIDE               0x00072188
+
+/* Graphics plane position register. */
+#define VML_DSPCPOS                  0x0007218C
+#define VML_POS_YMASK                0x0FFF0000
+#define VML_POS_YSHIFT               16
+#define VML_POS_XMASK                0x00000FFF
+#define VML_POS_XSHIFT               0
+
+/* Graphics plane height and width */
+#define VML_DSPCSIZE                 0x00072190
+#define VML_SIZE_HMASK               0x0FFF0000
+#define VML_SIZE_HSHIFT              16
+#define VML_SISE_WMASK               0x00000FFF
+#define VML_SIZE_WSHIFT              0
+
+/* Graphics plane gamma correction lookup table registers (129 * 32 bits) */
+#define VML_DSPCGAMLUT               0x00072200
+
+/* Pixel video output configuration register */
+#define VML_PVOCONFIG                0x00061140
+#define VML_CONFIG_BASE              0x80000000
+#define VML_CONFIG_PIXEL_SWAP        0x04000000
+#define VML_CONFIG_DE_INV            0x01000000
+#define VML_CONFIG_HREF_INV          0x00400000
+#define VML_CONFIG_VREF_INV          0x00100000
+#define VML_CONFIG_CLK_INV           0x00040000
+#define VML_CONFIG_CLK_DIV2          0x00010000
+#define VML_CONFIG_ESTRB_INV         0x00008000
+
+/* Pipe A Horizontal total register */
+#define VML_HTOTAL_A                 0x00060000
+#define VML_HTOTAL_MASK              0x1FFF0000
+#define VML_HTOTAL_SHIFT             16
+#define VML_HTOTAL_VAL               8192
+#define VML_HACTIVE_MASK             0x000007FF
+#define VML_HACTIVE_SHIFT            0
+#define VML_HACTIVE_VAL              4096
+
+/* Pipe A Horizontal Blank register */
+#define VML_HBLANK_A                 0x00060004
+#define VML_HBLANK_END_MASK          0x1FFF0000
+#define VML_HBLANK_END_SHIFT         16
+#define VML_HBLANK_END_VAL           8192
+#define VML_HBLANK_START_MASK        0x00001FFF
+#define VML_HBLANK_START_SHIFT       0
+#define VML_HBLANK_START_VAL         8192
+
+/* Pipe A Horizontal Sync register */
+#define VML_HSYNC_A                  0x00060008
+#define VML_HSYNC_END_MASK           0x1FFF0000
+#define VML_HSYNC_END_SHIFT          16
+#define VML_HSYNC_END_VAL            8192
+#define VML_HSYNC_START_MASK         0x00001FFF
+#define VML_HSYNC_START_SHIFT        0
+#define VML_HSYNC_START_VAL          8192
+
+/* Pipe A Vertical total register */
+#define VML_VTOTAL_A                 0x0006000C
+#define VML_VTOTAL_MASK              0x1FFF0000
+#define VML_VTOTAL_SHIFT             16
+#define VML_VTOTAL_VAL               8192
+#define VML_VACTIVE_MASK             0x000007FF
+#define VML_VACTIVE_SHIFT            0
+#define VML_VACTIVE_VAL              4096
+
+/* Pipe A Vertical Blank register */
+#define VML_VBLANK_A                 0x00060010
+#define VML_VBLANK_END_MASK          0x1FFF0000
+#define VML_VBLANK_END_SHIFT         16
+#define VML_VBLANK_END_VAL           8192
+#define VML_VBLANK_START_MASK        0x00001FFF
+#define VML_VBLANK_START_SHIFT       0
+#define VML_VBLANK_START_VAL         8192
+
+/* Pipe A Vertical Sync register */
+#define VML_VSYNC_A                  0x00060014
+#define VML_VSYNC_END_MASK           0x1FFF0000
+#define VML_VSYNC_END_SHIFT          16
+#define VML_VSYNC_END_VAL            8192
+#define VML_VSYNC_START_MASK         0x00001FFF
+#define VML_VSYNC_START_SHIFT        0
+#define VML_VSYNC_START_VAL          8192
+
+/* Pipe A Source Image size (minus one - equal to active size)
+ * Programmable while pipe is enabled.
+ */
+#define VML_PIPEASRC                 0x0006001C
+#define VML_PIPEASRC_HMASK           0x0FFF0000
+#define VML_PIPEASRC_HSHIFT          16
+#define VML_PIPEASRC_VMASK           0x00000FFF
+#define VML_PIPEASRC_VSHIFT          0
+
+/* Pipe A Border Color Pattern register (10 bit color) */
+#define VML_BCLRPAT_A                0x00060020
+
+/* Pipe A Canvas Color register  (10 bit color) */
+#define VML_CANVSCLR_A               0x00060024
+
+/* Pipe A Configuration register */
+#define VML_PIPEACONF                0x00070008
+#define VML_PIPE_BASE                0x00000000
+#define VML_PIPE_ENABLE              0x80000000
+#define VML_PIPE_FORCE_BORDER        0x02000000
+#define VML_PIPE_PLANES_OFF          0x00080000
+#define VML_PIPE_ARGB_OUTPUT_MODE    0x00040000
+
+/* Pipe A FIFO setting */
+#define VML_DSPARB                   0x00070030
+#define VML_FIFO_DEFAULT             0x00001D9C
+
+/* MDVO rcomp status & pads control register */
+#define VML_RCOMPSTAT                0x00070048
+#define VML_MDVO_VDC_I_RCOMP         0x80000000
+#define VML_MDVO_POWERSAVE_OFF       0x00000008
+#define VML_MDVO_PAD_ENABLE          0x00000004
+#define VML_MDVO_PULLDOWN_ENABLE     0x00000001
+
+struct vml_par {
+	struct pci_dev *vdc;
+	u64 vdc_mem_base;
+	u64 vdc_mem_size;
+	char __iomem *vdc_mem;
+
+	struct pci_dev *gpu;
+	u64 gpu_mem_base;
+	u64 gpu_mem_size;
+	char __iomem *gpu_mem;
+
+	atomic_t refcount;
+};
+
+struct vram_area {
+	unsigned long logical;
+	unsigned long phys;
+	unsigned long size;
+	unsigned order;
+};
+
+struct vml_info {
+	struct fb_info info;
+	struct vml_par *par;
+	struct list_head head;
+	struct vram_area vram[VML_VRAM_AREAS];
+	u64 vram_start;
+	u64 vram_contig_size;
+	u32 num_areas;
+	void __iomem *vram_logical;
+	u32 pseudo_palette[16];
+	u32 stride;
+	u32 bytes_per_pixel;
+	atomic_t vmas;
+	int cur_blank_mode;
+	int pipe_disabled;
+};
+
+/*
+ * Subsystem
+ */
+
+struct vml_sys {
+	char *name;
+
+	/*
+	 * Save / Restore;
+	 */
+
+	int (*save) (struct vml_sys * sys);
+	int (*restore) (struct vml_sys * sys);
+
+	/*
+	 * PLL programming;
+	 */
+
+	int (*set_clock) (struct vml_sys * sys, int clock);
+	int (*nearest_clock) (const struct vml_sys * sys, int clock);
+};
+
+extern int vmlfb_register_subsys(struct vml_sys *sys);
+extern void vmlfb_unregister_subsys(struct vml_sys *sys);
+
+#define VML_READ32(_par, _offset) \
+	(ioread32((_par)->vdc_mem + (_offset)))
+#define VML_WRITE32(_par, _offset, _value)				\
+	iowrite32(_value, (_par)->vdc_mem + (_offset))
+
+#endif
diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c
new file mode 100644
index 000000000000..6170e7f58640
--- /dev/null
+++ b/drivers/video/fbdev/vesafb.c
@@ -0,0 +1,522 @@
+/*
+ * framebuffer driver for VBE 2.0 compliant graphic boards
+ *
+ * switching to graphics mode happens at boot time (while
+ * running in real mode, see arch/i386/boot/video.S).
+ *
+ * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/screen_info.h>
+
+#include <video/vga.h>
+#include <asm/io.h>
+#include <asm/mtrr.h>
+
+#define dac_reg	(0x3c8)
+#define dac_val	(0x3c9)
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo vesafb_defined = {
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.right_margin	= 32,
+	.upper_margin	= 16,
+	.lower_margin	= 4,
+	.vsync_len	= 4,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo vesafb_fix = {
+	.id	= "VESA VGA",
+	.type	= FB_TYPE_PACKED_PIXELS,
+	.accel	= FB_ACCEL_NONE,
+};
+
+static int   inverse    __read_mostly;
+static int   mtrr       __read_mostly;		/* disable mtrr */
+static int   vram_remap;			/* Set amount of memory to be used */
+static int   vram_total;			/* Set total amount of memory */
+static int   pmi_setpal __read_mostly = 1;	/* pmi for palette changes ??? */
+static int   ypan       __read_mostly;		/* 0..nothing, 1..ypan, 2..ywrap */
+static void  (*pmi_start)(void) __read_mostly;
+static void  (*pmi_pal)  (void) __read_mostly;
+static int   depth      __read_mostly;
+static int   vga_compat __read_mostly;
+/* --------------------------------------------------------------------- */
+
+static int vesafb_pan_display(struct fb_var_screeninfo *var,
+                              struct fb_info *info)
+{
+#ifdef __i386__
+	int offset;
+
+	offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
+
+        __asm__ __volatile__(
+                "call *(%%edi)"
+                : /* no return value */
+                : "a" (0x4f07),         /* EAX */
+                  "b" (0),              /* EBX */
+                  "c" (offset),         /* ECX */
+                  "d" (offset >> 16),   /* EDX */
+                  "D" (&pmi_start));    /* EDI */
+#endif
+	return 0;
+}
+
+static int vesa_setpalette(int regno, unsigned red, unsigned green,
+			    unsigned blue)
+{
+	int shift = 16 - depth;
+	int err = -EINVAL;
+
+/*
+ * Try VGA registers first...
+ */
+	if (vga_compat) {
+		outb_p(regno,       dac_reg);
+		outb_p(red   >> shift, dac_val);
+		outb_p(green >> shift, dac_val);
+		outb_p(blue  >> shift, dac_val);
+		err = 0;
+	}
+
+#ifdef __i386__
+/*
+ * Fallback to the PMI....
+ */
+	if (err && pmi_setpal) {
+		struct { u_char blue, green, red, pad; } entry;
+
+		entry.red   = red   >> shift;
+		entry.green = green >> shift;
+		entry.blue  = blue  >> shift;
+		entry.pad   = 0;
+	        __asm__ __volatile__(
+                "call *(%%esi)"
+                : /* no return value */
+                : "a" (0x4f09),         /* EAX */
+                  "b" (0),              /* EBX */
+                  "c" (1),              /* ECX */
+                  "d" (regno),          /* EDX */
+                  "D" (&entry),         /* EDI */
+                  "S" (&pmi_pal));      /* ESI */
+		err = 0;
+	}
+#endif
+
+	return err;
+}
+
+static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp,
+			    struct fb_info *info)
+{
+	int err = 0;
+
+	/*
+	 *  Set a single color register. The values supplied are
+	 *  already rounded down to the hardware's capabilities
+	 *  (according to the entries in the `var' structure). Return
+	 *  != 0 for invalid regno.
+	 */
+	
+	if (regno >= info->cmap.len)
+		return 1;
+
+	if (info->var.bits_per_pixel == 8)
+		err = vesa_setpalette(regno,red,green,blue);
+	else if (regno < 16) {
+		switch (info->var.bits_per_pixel) {
+		case 16:
+			if (info->var.red.offset == 10) {
+				/* 1:5:5:5 */
+				((u32*) (info->pseudo_palette))[regno] =
+					((red   & 0xf800) >>  1) |
+					((green & 0xf800) >>  6) |
+					((blue  & 0xf800) >> 11);
+			} else {
+				/* 0:5:6:5 */
+				((u32*) (info->pseudo_palette))[regno] =
+					((red   & 0xf800)      ) |
+					((green & 0xfc00) >>  5) |
+					((blue  & 0xf800) >> 11);
+			}
+			break;
+		case 24:
+		case 32:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((u32 *)(info->pseudo_palette))[regno] =
+				(red   << info->var.red.offset)   |
+				(green << info->var.green.offset) |
+				(blue  << info->var.blue.offset);
+			break;
+		}
+	}
+
+	return err;
+}
+
+static void vesafb_destroy(struct fb_info *info)
+{
+	fb_dealloc_cmap(&info->cmap);
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
+}
+
+static struct fb_ops vesafb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_destroy     = vesafb_destroy,
+	.fb_setcolreg	= vesafb_setcolreg,
+	.fb_pan_display	= vesafb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int vesafb_setup(char *options)
+{
+	char *this_opt;
+	
+	if (!options || !*options)
+		return 0;
+	
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt) continue;
+		
+		if (! strcmp(this_opt, "inverse"))
+			inverse=1;
+		else if (! strcmp(this_opt, "redraw"))
+			ypan=0;
+		else if (! strcmp(this_opt, "ypan"))
+			ypan=1;
+		else if (! strcmp(this_opt, "ywrap"))
+			ypan=2;
+		else if (! strcmp(this_opt, "vgapal"))
+			pmi_setpal=0;
+		else if (! strcmp(this_opt, "pmipal"))
+			pmi_setpal=1;
+		else if (! strncmp(this_opt, "mtrr:", 5))
+			mtrr = simple_strtoul(this_opt+5, NULL, 0);
+		else if (! strcmp(this_opt, "nomtrr"))
+			mtrr=0;
+		else if (! strncmp(this_opt, "vtotal:", 7))
+			vram_total = simple_strtoul(this_opt+7, NULL, 0);
+		else if (! strncmp(this_opt, "vremap:", 7))
+			vram_remap = simple_strtoul(this_opt+7, NULL, 0);
+	}
+	return 0;
+}
+
+static int vesafb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int i, err;
+	unsigned int size_vmode;
+	unsigned int size_remap;
+	unsigned int size_total;
+	char *option = NULL;
+
+	/* ignore error return of fb_get_options */
+	fb_get_options("vesafb", &option);
+	vesafb_setup(option);
+
+	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
+		return -ENODEV;
+
+	vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
+	vesafb_fix.smem_start = screen_info.lfb_base;
+	vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
+	if (15 == vesafb_defined.bits_per_pixel)
+		vesafb_defined.bits_per_pixel = 16;
+	vesafb_defined.xres = screen_info.lfb_width;
+	vesafb_defined.yres = screen_info.lfb_height;
+	vesafb_fix.line_length = screen_info.lfb_linelength;
+	vesafb_fix.visual   = (vesafb_defined.bits_per_pixel == 8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+
+	/*   size_vmode -- that is the amount of memory needed for the
+	 *                 used video mode, i.e. the minimum amount of
+	 *                 memory we need. */
+	size_vmode = vesafb_defined.yres * vesafb_fix.line_length;
+
+	/*   size_total -- all video memory we have. Used for mtrr
+	 *                 entries, resource allocation and bounds
+	 *                 checking. */
+	size_total = screen_info.lfb_size * 65536;
+	if (vram_total)
+		size_total = vram_total * 1024 * 1024;
+	if (size_total < size_vmode)
+		size_total = size_vmode;
+
+	/*   size_remap -- the amount of video memory we are going to
+	 *                 use for vesafb.  With modern cards it is no
+	 *                 option to simply use size_total as that
+	 *                 wastes plenty of kernel address space. */
+	size_remap  = size_vmode * 2;
+	if (vram_remap)
+		size_remap = vram_remap * 1024 * 1024;
+	if (size_remap < size_vmode)
+		size_remap = size_vmode;
+	if (size_remap > size_total)
+		size_remap = size_total;
+	vesafb_fix.smem_len = size_remap;
+
+#ifndef __i386__
+	screen_info.vesapm_seg = 0;
+#endif
+
+	if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
+		printk(KERN_WARNING
+		       "vesafb: cannot reserve video memory at 0x%lx\n",
+			vesafb_fix.smem_start);
+		/* We cannot make this fatal. Sometimes this comes from magic
+		   spaces our resource handlers simply don't know about */
+	}
+
+	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+	if (!info) {
+		release_mem_region(vesafb_fix.smem_start, size_total);
+		return -ENOMEM;
+	}
+	platform_set_drvdata(dev, info);
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+
+	/* set vesafb aperture size for generic probing */
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures) {
+		err = -ENOMEM;
+		goto err;
+	}
+	info->apertures->ranges[0].base = screen_info.lfb_base;
+	info->apertures->ranges[0].size = size_total;
+
+	printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+	       vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
+
+	if (screen_info.vesapm_seg) {
+		printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
+		       screen_info.vesapm_seg,screen_info.vesapm_off);
+	}
+
+	if (screen_info.vesapm_seg < 0xc000)
+		ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
+
+	if (ypan || pmi_setpal) {
+		unsigned short *pmi_base;
+		pmi_base  = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+		pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
+		pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
+		printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+		if (pmi_base[3]) {
+			printk(KERN_INFO "vesafb: pmi: ports = ");
+				for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
+					printk("%x ",pmi_base[i]);
+			printk("\n");
+			if (pmi_base[i] != 0xffff) {
+				/*
+				 * memory areas not supported (yet?)
+				 *
+				 * Rules are: we have to set up a descriptor for the requested
+				 * memory area and pass it in the ES register to the BIOS function.
+				 */
+				printk(KERN_INFO "vesafb: can't handle memory requests, pmi disabled\n");
+				ypan = pmi_setpal = 0;
+			}
+		}
+	}
+
+	if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) {
+		printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n"
+		                    "        colors may be incorrect\n");
+		vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+	}
+
+	vesafb_defined.xres_virtual = vesafb_defined.xres;
+	vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
+	if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
+		printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
+		       (ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
+	} else {
+		printk(KERN_INFO "vesafb: scrolling: redraw\n");
+		vesafb_defined.yres_virtual = vesafb_defined.yres;
+		ypan = 0;
+	}
+
+	/* some dummy values for timing to make fbset happy */
+	vesafb_defined.pixclock     = 10000000 / vesafb_defined.xres * 1000 / vesafb_defined.yres;
+	vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
+	vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
+	
+	vesafb_defined.red.offset    = screen_info.red_pos;
+	vesafb_defined.red.length    = screen_info.red_size;
+	vesafb_defined.green.offset  = screen_info.green_pos;
+	vesafb_defined.green.length  = screen_info.green_size;
+	vesafb_defined.blue.offset   = screen_info.blue_pos;
+	vesafb_defined.blue.length   = screen_info.blue_size;
+	vesafb_defined.transp.offset = screen_info.rsvd_pos;
+	vesafb_defined.transp.length = screen_info.rsvd_size;
+
+	if (vesafb_defined.bits_per_pixel <= 8) {
+		depth = vesafb_defined.green.length;
+		vesafb_defined.red.length =
+		vesafb_defined.green.length =
+		vesafb_defined.blue.length =
+		vesafb_defined.bits_per_pixel;
+	}
+
+	printk(KERN_INFO "vesafb: %s: "
+	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+	       (vesafb_defined.bits_per_pixel > 8) ?
+	       "Truecolor" : (vga_compat || pmi_setpal) ?
+	       "Pseudocolor" : "Static Pseudocolor",
+	       screen_info.rsvd_size,
+	       screen_info.red_size,
+	       screen_info.green_size,
+	       screen_info.blue_size,
+	       screen_info.rsvd_pos,
+	       screen_info.red_pos,
+	       screen_info.green_pos,
+	       screen_info.blue_pos);
+
+	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
+	vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
+
+	/* request failure does not faze us, as vgacon probably has this
+	 * region already (FIXME) */
+	request_region(0x3c0, 32, "vesafb");
+
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		unsigned int temp_size = size_total;
+		unsigned int type = 0;
+
+		switch (mtrr) {
+		case 1:
+			type = MTRR_TYPE_UNCACHABLE;
+			break;
+		case 2:
+			type = MTRR_TYPE_WRBACK;
+			break;
+		case 3:
+			type = MTRR_TYPE_WRCOMB;
+			break;
+		case 4:
+			type = MTRR_TYPE_WRTHROUGH;
+			break;
+		default:
+			type = 0;
+			break;
+		}
+
+		if (type) {
+			int rc;
+
+			/* Find the largest power-of-two */
+			temp_size = roundup_pow_of_two(temp_size);
+
+			/* Try and find a power of two to add */
+			do {
+				rc = mtrr_add(vesafb_fix.smem_start, temp_size,
+					      type, 1);
+				temp_size >>= 1;
+			} while (temp_size >= PAGE_SIZE && rc == -EINVAL);
+		}
+	}
+#endif
+	
+	switch (mtrr) {
+	case 1: /* uncachable */
+		info->screen_base = ioremap_nocache(vesafb_fix.smem_start, vesafb_fix.smem_len);
+		break;
+	case 2: /* write-back */
+		info->screen_base = ioremap_cache(vesafb_fix.smem_start, vesafb_fix.smem_len);
+		break;
+	case 3: /* write-combining */
+		info->screen_base = ioremap_wc(vesafb_fix.smem_start, vesafb_fix.smem_len);
+		break;
+	case 4: /* write-through */
+	default:
+		info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
+		break;
+	}
+	if (!info->screen_base) {
+		printk(KERN_ERR
+		       "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
+			vesafb_fix.smem_len, vesafb_fix.smem_start);
+		err = -EIO;
+		goto err;
+	}
+
+	printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, "
+	       "using %dk, total %dk\n",
+	       vesafb_fix.smem_start, info->screen_base,
+	       size_remap/1024, size_total/1024);
+
+	info->fbops = &vesafb_ops;
+	info->var = vesafb_defined;
+	info->fix = vesafb_fix;
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE |
+		(ypan ? FBINFO_HWACCEL_YPAN : 0);
+
+	if (!ypan)
+		info->fbops->fb_pan_display = NULL;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		err = -ENOMEM;
+		goto err;
+	}
+	if (register_framebuffer(info)<0) {
+		err = -EINVAL;
+		fb_dealloc_cmap(&info->cmap);
+		goto err;
+	}
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	return 0;
+err:
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	framebuffer_release(info);
+	release_mem_region(vesafb_fix.smem_start, size_total);
+	return err;
+}
+
+static int vesafb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+
+	unregister_framebuffer(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver vesafb_driver = {
+	.driver = {
+		.name = "vesa-framebuffer",
+		.owner = THIS_MODULE,
+	},
+	.probe = vesafb_probe,
+	.remove = vesafb_remove,
+};
+
+module_platform_driver(vesafb_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/vfb.c b/drivers/video/fbdev/vfb.c
new file mode 100644
index 000000000000..70a897b1e458
--- /dev/null
+++ b/drivers/video/fbdev/vfb.c
@@ -0,0 +1,610 @@
+/*
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *      Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <linux/fb.h>
+#include <linux/init.h>
+
+    /*
+     *  RAM we reserve for the frame buffer. This defines the maximum screen
+     *  size
+     *
+     *  The default can be overridden if the driver is compiled as a module
+     */
+
+#define VIDEOMEMSIZE	(1*1024*1024)	/* 1 MB */
+
+static void *videomemory;
+static u_long videomemorysize = VIDEOMEMSIZE;
+module_param(videomemorysize, ulong, 0);
+
+/**********************************************************************
+ *
+ * Memory management
+ *
+ **********************************************************************/
+static void *rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		SetPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		ClearPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(mem);
+}
+
+static struct fb_var_screeninfo vfb_default = {
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual =	480,
+	.bits_per_pixel = 8,
+	.red =		{ 0, 8, 0 },
+      	.green =	{ 0, 8, 0 },
+      	.blue =		{ 0, 8, 0 },
+      	.activate =	FB_ACTIVATE_TEST,
+      	.height =	-1,
+      	.width =	-1,
+      	.pixclock =	20000,
+      	.left_margin =	64,
+      	.right_margin =	64,
+      	.upper_margin =	32,
+      	.lower_margin =	32,
+      	.hsync_len =	64,
+      	.vsync_len =	2,
+      	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo vfb_fix = {
+	.id =		"Virtual FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static bool vfb_enable __initdata = 0;	/* disabled by default */
+module_param(vfb_enable, bool, 0);
+
+static int vfb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info);
+static int vfb_set_par(struct fb_info *info);
+static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info);
+static int vfb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info);
+static int vfb_mmap(struct fb_info *info,
+		    struct vm_area_struct *vma);
+
+static struct fb_ops vfb_ops = {
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_check_var	= vfb_check_var,
+	.fb_set_par	= vfb_set_par,
+	.fb_setcolreg	= vfb_setcolreg,
+	.fb_pan_display	= vfb_pan_display,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_mmap	= vfb_mmap,
+};
+
+    /*
+     *  Internal routines
+     */
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+	u_long length;
+
+	length = xres_virtual * bpp;
+	length = (length + 31) & ~31;
+	length >>= 3;
+	return (length);
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var. 
+     */
+
+static int vfb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	u_long line_length;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/*
+	 *  Some very basic checks
+	 */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->bits_per_pixel <= 1)
+		var->bits_per_pixel = 1;
+	else if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xoffset + var->xres)
+		var->xres_virtual = var->xoffset + var->xres;
+	if (var->yres_virtual < var->yoffset + var->yres)
+		var->yres_virtual = var->yoffset + var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length =
+	    get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > videomemorysize)
+		return -ENOMEM;
+
+	/*
+	 * Now that we checked it we alter var. The reason being is that the video
+	 * mode passed in might not work but slight changes to it might make it 
+	 * work. This way we let the user know what is acceptable.
+	 */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGBA 5551 */
+		if (var->transp.length) {
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 10;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {	/* RGB 565 */
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 11;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:		/* RGB 888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/* This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the 
+ * change in par. For this driver it doesn't do much. 
+ */
+static int vfb_set_par(struct fb_info *info)
+{
+	info->fix.line_length = get_line_length(info->var.xres_virtual,
+						info->var.bits_per_pixel);
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info)
+{
+	if (regno >= 256)	/* no. of hw registers */
+		return 1;
+	/*
+	 * Program hardware... do anything you want with transp
+	 */
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of RAMDAC
+	 *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 *
+	 * Pseudocolor:
+	 *    var->{color}.offset is 0 unless the palette index takes less than
+	 *                        bits_per_pixel bits and is stored in the upper
+	 *                        bits of the pixel value
+	 *    var->{color}.length is set so that 1 << length is the number of available
+	 *                        palette entries
+	 *    cmap is not used
+	 *    RAMDAC[X] is programmed to (red, green, blue)
+	 *
+	 * Truecolor:
+	 *    does not use DAC. Usually 3 are present.
+	 *    var->{color}.offset contains start of bitfield
+	 *    var->{color}.length contains length of bitfield
+	 *    cmap is programmed to (red << red.offset) | (green << green.offset) |
+	 *                      (blue << blue.offset) | (transp << transp.offset)
+	 *    RAMDAC does not exist
+	 */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return 1;
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		case 24:
+		case 32:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+     */
+
+static int vfb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset >= info->var.yres_virtual ||
+		    var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+		    var->yoffset + info->var.yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+    /*
+     *  Most drivers don't need their own mmap function 
+     */
+
+static int vfb_mmap(struct fb_info *info,
+		    struct vm_area_struct *vma)
+{
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long page, pos;
+
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	if (size > info->fix.smem_len)
+		return -EINVAL;
+	if (offset > info->fix.smem_len - size)
+		return -EINVAL;
+
+	pos = (unsigned long)info->fix.smem_start + offset;
+
+	while (size > 0) {
+		page = vmalloc_to_pfn((void *)pos);
+		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	return 0;
+
+}
+
+#ifndef MODULE
+/*
+ * The virtual framebuffer driver is only enabled if explicitly
+ * requested by passing 'video=vfb:' (or any actual options).
+ */
+static int __init vfb_setup(char *options)
+{
+	char *this_opt;
+
+	vfb_enable = 0;
+
+	if (!options)
+		return 1;
+
+	vfb_enable = 1;
+
+	if (!*options)
+		return 1;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		/* Test disable for backwards compatibility */
+		if (!strcmp(this_opt, "disable"))
+			vfb_enable = 0;
+	}
+	return 1;
+}
+#endif  /*  MODULE  */
+
+    /*
+     *  Initialisation
+     */
+
+static int vfb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+
+	/*
+	 * For real video cards we use ioremap.
+	 */
+	if (!(videomemory = rvmalloc(videomemorysize)))
+		return retval;
+
+	/*
+	 * VFB must clear memory to prevent kernel info
+	 * leakage into userspace
+	 * VGA-based drivers MUST NOT clear memory if
+	 * they want to be able to take over vgacon
+	 */
+	memset(videomemory, 0, videomemorysize);
+
+	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+	if (!info)
+		goto err;
+
+	info->screen_base = (char __iomem *)videomemory;
+	info->fbops = &vfb_ops;
+
+	retval = fb_find_mode(&info->var, info, NULL,
+			      NULL, 0, NULL, 8);
+
+	if (!retval || (retval == 4))
+		info->var = vfb_default;
+	vfb_fix.smem_start = (unsigned long) videomemory;
+	vfb_fix.smem_len = videomemorysize;
+	info->fix = vfb_fix;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err1;
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err2;
+	platform_set_drvdata(dev, info);
+
+	fb_info(info, "Virtual frame buffer device, using %ldK of video memory\n",
+		videomemorysize >> 10);
+	return 0;
+err2:
+	fb_dealloc_cmap(&info->cmap);
+err1:
+	framebuffer_release(info);
+err:
+	rvfree(videomemory, videomemorysize);
+	return retval;
+}
+
+static int vfb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		rvfree(videomemory, videomemorysize);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct platform_driver vfb_driver = {
+	.probe	= vfb_probe,
+	.remove = vfb_remove,
+	.driver = {
+		.name	= "vfb",
+	},
+};
+
+static struct platform_device *vfb_device;
+
+static int __init vfb_init(void)
+{
+	int ret = 0;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("vfb", &option))
+		return -ENODEV;
+	vfb_setup(option);
+#endif
+
+	if (!vfb_enable)
+		return -ENXIO;
+
+	ret = platform_driver_register(&vfb_driver);
+
+	if (!ret) {
+		vfb_device = platform_device_alloc("vfb", 0);
+
+		if (vfb_device)
+			ret = platform_device_add(vfb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(vfb_device);
+			platform_driver_unregister(&vfb_driver);
+		}
+	}
+
+	return ret;
+}
+
+module_init(vfb_init);
+
+#ifdef MODULE
+static void __exit vfb_exit(void)
+{
+	platform_device_unregister(vfb_device);
+	platform_driver_unregister(&vfb_driver);
+}
+
+module_exit(vfb_exit);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c
new file mode 100644
index 000000000000..283d335a759f
--- /dev/null
+++ b/drivers/video/fbdev/vga16fb.c
@@ -0,0 +1,1464 @@
+/*
+ * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver
+ * 
+ * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
+ * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.  
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/screen_info.h>
+
+#include <asm/io.h>
+#include <video/vga.h>
+
+#define VGA_FB_PHYS 0xA0000
+#define VGA_FB_PHYS_LEN 65536
+
+#define MODE_SKIP4	1
+#define MODE_8BPP	2
+#define MODE_CFB	4
+#define MODE_TEXT	8
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * card parameters
+ */
+
+struct vga16fb_par {
+	/* structure holding original VGA register settings when the
+           screen is blanked */
+	struct {
+		unsigned char	SeqCtrlIndex;	  /* Sequencer Index reg.   */
+		unsigned char	CrtCtrlIndex;	  /* CRT-Contr. Index reg.  */
+		unsigned char	CrtMiscIO;	  /* Miscellaneous register */
+		unsigned char	HorizontalTotal;  /* CRT-Controller:00h */
+		unsigned char	HorizDisplayEnd;  /* CRT-Controller:01h */
+		unsigned char	StartHorizRetrace;/* CRT-Controller:04h */
+		unsigned char	EndHorizRetrace;  /* CRT-Controller:05h */
+		unsigned char	Overflow;	  /* CRT-Controller:07h */
+		unsigned char	StartVertRetrace; /* CRT-Controller:10h */
+		unsigned char	EndVertRetrace;	  /* CRT-Controller:11h */
+		unsigned char	ModeControl;	  /* CRT-Controller:17h */
+		unsigned char	ClockingMode;	  /* Seq-Controller:01h */
+	} vga_state;
+	struct vgastate state;
+	unsigned int ref_count;
+	int palette_blanked, vesa_blanked, mode, isVGA;
+	u8 misc, pel_msk, vss, clkdiv;
+	u8 crtc[VGA_CRT_C];
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo vga16fb_defined = {
+	.xres		= 640,
+	.yres		= 480,
+	.xres_virtual	= 640,
+	.yres_virtual	= 480,
+	.bits_per_pixel	= 4,	
+	.activate	= FB_ACTIVATE_TEST,
+	.height		= -1,
+	.width		= -1,
+	.pixclock	= 39721,
+	.left_margin	= 48,
+	.right_margin	= 16,
+	.upper_margin	= 33,
+	.lower_margin	= 10,
+	.hsync_len 	= 96,
+	.vsync_len	= 2,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+/* name should not depend on EGA/VGA */
+static struct fb_fix_screeninfo vga16fb_fix = {
+	.id		= "VGA16 VGA",
+	.smem_start	= VGA_FB_PHYS,
+	.smem_len	= VGA_FB_PHYS_LEN,
+	.type		= FB_TYPE_VGA_PLANES,
+	.type_aux	= FB_AUX_VGA_PLANES_VGA4,
+	.visual		= FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep	= 8,
+	.ypanstep	= 1,
+	.line_length	= 640 / 8,
+	.accel		= FB_ACCEL_NONE
+};
+
+/* The VGA's weird architecture often requires that we read a byte and
+   write a byte to the same location.  It doesn't matter *what* byte
+   we write, however.  This is because all the action goes on behind
+   the scenes in the VGA's 32-bit latch register, and reading and writing
+   video memory just invokes latch behavior.
+
+   To avoid race conditions (is this necessary?), reading and writing
+   the memory byte should be done with a single instruction.  One
+   suitable instruction is the x86 bitwise OR.  The following
+   read-modify-write routine should optimize to one such bitwise
+   OR. */
+static inline void rmw(volatile char __iomem *p)
+{
+	readb(p);
+	writeb(1, p);
+}
+
+/* Set the Graphics Mode Register, and return its previous value.
+   Bits 0-1 are write mode, bit 3 is read mode. */
+static inline int setmode(int mode)
+{
+	int oldmode;
+	
+	oldmode = vga_io_rgfx(VGA_GFX_MODE);
+	vga_io_w(VGA_GFX_D, mode);
+	return oldmode;
+}
+
+/* Select the Bit Mask Register and return its value. */
+static inline int selectmask(void)
+{
+	return vga_io_rgfx(VGA_GFX_BIT_MASK);
+}
+
+/* Set the value of the Bit Mask Register.  It must already have been
+   selected with selectmask(). */
+static inline void setmask(int mask)
+{
+	vga_io_w(VGA_GFX_D, mask);
+}
+
+/* Set the Data Rotate Register and return its old value. 
+   Bits 0-2 are rotate count, bits 3-4 are logical operation
+   (0=NOP, 1=AND, 2=OR, 3=XOR). */
+static inline int setop(int op)
+{
+	int oldop;
+	
+	oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
+	vga_io_w(VGA_GFX_D, op);
+	return oldop;
+}
+
+/* Set the Enable Set/Reset Register and return its old value.  
+   The code here always uses value 0xf for this register. */
+static inline int setsr(int sr)
+{
+	int oldsr;
+
+	oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
+	vga_io_w(VGA_GFX_D, sr);
+	return oldsr;
+}
+
+/* Set the Set/Reset Register and return its old value. */
+static inline int setcolor(int color)
+{
+	int oldcolor;
+
+	oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
+	vga_io_w(VGA_GFX_D, color);
+	return oldcolor;
+}
+
+/* Return the value in the Graphics Address Register. */
+static inline int getindex(void)
+{
+	return vga_io_r(VGA_GFX_I);
+}
+
+/* Set the value in the Graphics Address Register. */
+static inline void setindex(int index)
+{
+	vga_io_w(VGA_GFX_I, index);
+}
+
+static void vga16fb_pan_var(struct fb_info *info, 
+			    struct fb_var_screeninfo *var)
+{
+	struct vga16fb_par *par = info->par;
+	u32 xoffset, pos;
+
+	xoffset = var->xoffset;
+	if (info->var.bits_per_pixel == 8) {
+		pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2;
+	} else if (par->mode & MODE_TEXT) {
+		int fh = 16; // FIXME !!! font height. Fugde for now.
+		pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3;
+	} else {
+		if (info->var.nonstd)
+			xoffset--;
+		pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3;
+	}
+	vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8);
+	vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF);
+	/* if we support CFB4, then we must! support xoffset with pixel
+	 * granularity if someone supports xoffset in bit resolution */
+	vga_io_r(VGA_IS1_RC);		/* reset flip-flop */
+	vga_io_w(VGA_ATT_IW, VGA_ATC_PEL);
+	if (info->var.bits_per_pixel == 8)
+		vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1);
+	else
+		vga_io_w(VGA_ATT_IW, xoffset & 7);
+	vga_io_r(VGA_IS1_RC);
+	vga_io_w(VGA_ATT_IW, 0x20);
+}
+
+static void vga16fb_update_fix(struct fb_info *info)
+{
+	if (info->var.bits_per_pixel == 4) {
+		if (info->var.nonstd) {
+			info->fix.type = FB_TYPE_PACKED_PIXELS;
+			info->fix.line_length = info->var.xres_virtual / 2;
+		} else {
+			info->fix.type = FB_TYPE_VGA_PLANES;
+			info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4;
+			info->fix.line_length = info->var.xres_virtual / 8;
+		}
+	} else if (info->var.bits_per_pixel == 0) {
+		info->fix.type = FB_TYPE_TEXT;
+		info->fix.type_aux = FB_AUX_TEXT_CGA;
+		info->fix.line_length = info->var.xres_virtual / 4;
+	} else {	/* 8bpp */
+		if (info->var.nonstd) {
+			info->fix.type = FB_TYPE_VGA_PLANES;
+			info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8;
+			info->fix.line_length = info->var.xres_virtual / 4;
+		} else {
+			info->fix.type = FB_TYPE_PACKED_PIXELS;
+			info->fix.line_length = info->var.xres_virtual;
+		}
+	}
+}
+
+static void vga16fb_clock_chip(struct vga16fb_par *par,
+			       unsigned int pixclock,
+			       const struct fb_info *info,
+			       int mul, int div)
+{
+	static const struct {
+		u32 pixclock;
+		u8  misc;
+		u8  seq_clock_mode;
+	} *ptr, *best, vgaclocks[] = {
+		{ 79442 /* 12.587 */, 0x00, 0x08},
+		{ 70616 /* 14.161 */, 0x04, 0x08},
+		{ 39721 /* 25.175 */, 0x00, 0x00},
+		{ 35308 /* 28.322 */, 0x04, 0x00},
+		{     0 /* bad */,    0x00, 0x00}};
+	int err;
+
+	pixclock = (pixclock * mul) / div;
+	best = vgaclocks;
+	err = pixclock - best->pixclock;
+	if (err < 0) err = -err;
+	for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) {
+		int tmp;
+
+		tmp = pixclock - ptr->pixclock;
+		if (tmp < 0) tmp = -tmp;
+		if (tmp < err) {
+			err = tmp;
+			best = ptr;
+		}
+	}
+	par->misc |= best->misc;
+	par->clkdiv = best->seq_clock_mode;
+	pixclock = (best->pixclock * div) / mul;		
+}
+			       
+#define FAIL(X) return -EINVAL
+
+static int vga16fb_open(struct fb_info *info, int user)
+{
+	struct vga16fb_par *par = info->par;
+
+	if (!par->ref_count) {
+		memset(&par->state, 0, sizeof(struct vgastate));
+		par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
+			VGA_SAVE_CMAP;
+		save_vga(&par->state);
+	}
+	par->ref_count++;
+
+	return 0;
+}
+
+static int vga16fb_release(struct fb_info *info, int user)
+{
+	struct vga16fb_par *par = info->par;
+
+	if (!par->ref_count)
+		return -EINVAL;
+
+	if (par->ref_count == 1)
+		restore_vga(&par->state);
+	par->ref_count--;
+
+	return 0;
+}
+
+static int vga16fb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct vga16fb_par *par = info->par;
+	u32 xres, right, hslen, left, xtotal;
+	u32 yres, lower, vslen, upper, ytotal;
+	u32 vxres, xoffset, vyres, yoffset;
+	u32 pos;
+	u8 r7, rMode;
+	int shift;
+	int mode;
+	u32 maxmem;
+
+	par->pel_msk = 0xFF;
+
+	if (var->bits_per_pixel == 4) {
+		if (var->nonstd) {
+			if (!par->isVGA)
+				return -EINVAL;
+			shift = 3;
+			mode = MODE_SKIP4 | MODE_CFB;
+			maxmem = 16384;
+			par->pel_msk = 0x0F;
+		} else {
+			shift = 3;
+			mode = 0;
+			maxmem = 65536;
+		}
+	} else if (var->bits_per_pixel == 8) {
+		if (!par->isVGA)
+			return -EINVAL;	/* no support on EGA */
+		shift = 2;
+		if (var->nonstd) {
+			mode = MODE_8BPP | MODE_CFB;
+			maxmem = 65536;
+		} else {
+			mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB;
+			maxmem = 16384;
+		}
+	} else
+		return -EINVAL;
+
+	xres = (var->xres + 7) & ~7;
+	vxres = (var->xres_virtual + 0xF) & ~0xF;
+	xoffset = (var->xoffset + 7) & ~7;
+	left = (var->left_margin + 7) & ~7;
+	right = (var->right_margin + 7) & ~7;
+	hslen = (var->hsync_len + 7) & ~7;
+
+	if (vxres < xres)
+		vxres = xres;
+	if (xres + xoffset > vxres)
+		xoffset = vxres - xres;
+
+	var->xres = xres;
+	var->right_margin = right;
+	var->hsync_len = hslen;
+	var->left_margin = left;
+	var->xres_virtual = vxres;
+	var->xoffset = xoffset;
+
+	xres >>= shift;
+	right >>= shift;
+	hslen >>= shift;
+	left >>= shift;
+	vxres >>= shift;
+	xtotal = xres + right + hslen + left;
+	if (xtotal >= 256)
+		FAIL("xtotal too big");
+	if (hslen > 32)
+		FAIL("hslen too big");
+	if (right + hslen + left > 64)
+		FAIL("hblank too big");
+	par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5;
+	par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1;
+	par->crtc[VGA_CRTC_H_DISP] = xres - 1;
+	pos = xres + right;
+	par->crtc[VGA_CRTC_H_SYNC_START] = pos;
+	pos += hslen;
+	par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F;
+	pos += left - 2; /* blank_end + 2 <= total + 5 */
+	par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
+	if (pos & 0x20)
+		par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80;
+
+	yres = var->yres;
+	lower = var->lower_margin;
+	vslen = var->vsync_len;
+	upper = var->upper_margin;
+	vyres = var->yres_virtual;
+	yoffset = var->yoffset;
+
+	if (yres > vyres)
+		vyres = yres;
+	if (vxres * vyres > maxmem) {
+		vyres = maxmem / vxres;
+		if (vyres < yres)
+			return -ENOMEM;
+	}
+	if (yoffset + yres > vyres)
+		yoffset = vyres - yres;
+	var->yres = yres;
+	var->lower_margin = lower;
+	var->vsync_len = vslen;
+	var->upper_margin = upper;
+	var->yres_virtual = vyres;
+	var->yoffset = yoffset;
+
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		yres <<= 1;
+		lower <<= 1;
+		vslen <<= 1;
+		upper <<= 1;
+	}
+	ytotal = yres + lower + vslen + upper;
+	if (ytotal > 1024) {
+		ytotal >>= 1;
+		yres >>= 1;
+		lower >>= 1;
+		vslen >>= 1;
+		upper >>= 1;
+		rMode = 0x04;
+	} else
+		rMode = 0x00;
+	if (ytotal > 1024)
+		FAIL("ytotal too big");
+	if (vslen > 16)
+		FAIL("vslen too big");
+	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
+	r7 = 0x10;	/* disable linecompare */
+	if (ytotal & 0x100) r7 |= 0x01;
+	if (ytotal & 0x200) r7 |= 0x20;
+	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
+	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
+	if (var->vmode & FB_VMODE_DOUBLE)
+		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
+	par->crtc[VGA_CRTC_CURSOR_START] = 0x20;
+	par->crtc[VGA_CRTC_CURSOR_END]   = 0x00;
+	if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB)
+		xoffset--;
+	pos = yoffset * vxres + (xoffset >> shift);
+	par->crtc[VGA_CRTC_START_HI]     = pos >> 8;
+	par->crtc[VGA_CRTC_START_LO]     = pos & 0xFF;
+	par->crtc[VGA_CRTC_CURSOR_HI]    = 0x00;
+	par->crtc[VGA_CRTC_CURSOR_LO]    = 0x00;
+	pos = yres - 1;
+	par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF;
+	par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF;
+	if (pos & 0x100)
+		r7 |= 0x0A;	/* 0x02 -> DISP_END, 0x08 -> BLANK_START */
+	if (pos & 0x200) {
+		r7 |= 0x40;	/* 0x40 -> DISP_END */
+		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
+	}
+	pos += lower;
+	par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF;
+	if (pos & 0x100)
+		r7 |= 0x04;
+	if (pos & 0x200)
+		r7 |= 0x80;
+	pos += vslen;
+	par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */
+	pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
+	par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
+                     but some SVGA chips requires all 8 bits to set */
+	if (vxres >= 512)
+		FAIL("vxres too long");
+	par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
+	if (mode & MODE_SKIP4)
+		par->crtc[VGA_CRTC_UNDERLINE] = 0x5F;	/* 256, cfb8 */
+	else
+		par->crtc[VGA_CRTC_UNDERLINE] = 0x1F;	/* 16, vgap */
+	par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3);
+	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
+	par->crtc[VGA_CRTC_OVERFLOW] = r7;
+
+	par->vss = 0x00;	/* 3DA */
+
+	par->misc = 0xE3;	/* enable CPU, ports 0x3Dx, positive sync */
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		par->misc &= ~0x40;
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		par->misc &= ~0x80;
+	
+	par->mode = mode;
+
+	if (mode & MODE_8BPP)
+		/* pixel clock == vga clock / 2 */
+		vga16fb_clock_chip(par, var->pixclock, info, 1, 2);
+	else
+		/* pixel clock == vga clock */
+		vga16fb_clock_chip(par, var->pixclock, info, 1, 1);
+	
+	var->red.offset = var->green.offset = var->blue.offset = 
+	var->transp.offset = 0;
+	var->red.length = var->green.length = var->blue.length =
+		(par->isVGA) ? 6 : 2;
+	var->transp.length = 0;
+	var->activate = FB_ACTIVATE_NOW;
+	var->height = -1;
+	var->width = -1;
+	var->accel_flags = 0;
+	return 0;
+}
+#undef FAIL
+
+static int vga16fb_set_par(struct fb_info *info)
+{
+	struct vga16fb_par *par = info->par;
+	u8 gdc[VGA_GFX_C];
+	u8 seq[VGA_SEQ_C];
+	u8 atc[VGA_ATT_C];
+	int fh, i;
+
+	seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv;
+	if (par->mode & MODE_TEXT)
+		seq[VGA_SEQ_PLANE_WRITE] = 0x03;
+	else
+		seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
+	seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+	if (par->mode & MODE_TEXT)
+		seq[VGA_SEQ_MEMORY_MODE] = 0x03;
+	else if (par->mode & MODE_SKIP4)
+		seq[VGA_SEQ_MEMORY_MODE] = 0x0E;
+	else
+		seq[VGA_SEQ_MEMORY_MODE] = 0x06;
+
+	gdc[VGA_GFX_SR_VALUE] = 0x00;
+	gdc[VGA_GFX_SR_ENABLE] = 0x00;
+	gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
+	gdc[VGA_GFX_DATA_ROTATE] = 0x00;
+	gdc[VGA_GFX_PLANE_READ] = 0;
+	if (par->mode & MODE_TEXT) {
+		gdc[VGA_GFX_MODE] = 0x10;
+		gdc[VGA_GFX_MISC] = 0x06;
+	} else {
+		if (par->mode & MODE_CFB)
+			gdc[VGA_GFX_MODE] = 0x40;
+		else
+			gdc[VGA_GFX_MODE] = 0x00;
+		gdc[VGA_GFX_MISC] = 0x05;
+	}
+	gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
+	gdc[VGA_GFX_BIT_MASK] = 0xFF;
+
+	for (i = 0x00; i < 0x10; i++)
+		atc[i] = i;
+	if (par->mode & MODE_TEXT)
+		atc[VGA_ATC_MODE] = 0x04;
+	else if (par->mode & MODE_8BPP)
+		atc[VGA_ATC_MODE] = 0x41;
+	else
+		atc[VGA_ATC_MODE] = 0x81;
+	atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
+	atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
+	if (par->mode & MODE_8BPP)
+		atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1;
+	else
+		atc[VGA_ATC_PEL] = info->var.xoffset & 7;
+	atc[VGA_ATC_COLOR_PAGE] = 0x00;
+	
+	if (par->mode & MODE_TEXT) {
+		fh = 16; // FIXME !!! Fudge font height. 
+		par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] 
+					       & ~0x1F) | (fh - 1);
+	}
+
+	vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01);
+
+	/* Enable graphics register modification */
+	if (!par->isVGA) {
+		vga_io_w(EGA_GFX_E0, 0x00);
+		vga_io_w(EGA_GFX_E1, 0x01);
+	}
+	
+	/* update misc output register */
+	vga_io_w(VGA_MIS_W, par->misc);
+	
+	/* synchronous reset on */
+	vga_io_wseq(0x00, 0x01);
+
+	if (par->isVGA)
+		vga_io_w(VGA_PEL_MSK, par->pel_msk);
+
+	/* write sequencer registers */
+	vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20);
+	for (i = 2; i < VGA_SEQ_C; i++) {
+		vga_io_wseq(i, seq[i]);
+	}
+	
+	/* synchronous reset off */
+	vga_io_wseq(0x00, 0x03);
+
+	/* deprotect CRT registers 0-7 */
+	vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
+
+	/* write CRT registers */
+	for (i = 0; i < VGA_CRTC_REGS; i++) {
+		vga_io_wcrt(i, par->crtc[i]);
+	}
+	
+	/* write graphics controller registers */
+	for (i = 0; i < VGA_GFX_C; i++) {
+		vga_io_wgfx(i, gdc[i]);
+	}
+	
+	/* write attribute controller registers */
+	for (i = 0; i < VGA_ATT_C; i++) {
+		vga_io_r(VGA_IS1_RC);		/* reset flip-flop */
+		vga_io_wattr(i, atc[i]);
+	}
+
+	/* Wait for screen to stabilize. */
+	mdelay(50);
+
+	vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]);
+
+	vga_io_r(VGA_IS1_RC);
+	vga_io_w(VGA_ATT_IW, 0x20);
+
+	vga16fb_update_fix(info);
+	return 0;
+}
+
+static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+{
+	static const unsigned char map[] = { 000, 001, 010, 011 };
+	int val;
+	
+	if (regno >= 16)
+		return;
+	val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
+	vga_io_r(VGA_IS1_RC);   /* ! 0x3BA */
+	vga_io_wattr(regno, val);
+	vga_io_r(VGA_IS1_RC);   /* some clones need it */
+	vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */
+}
+
+static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+{
+	outb(regno,       VGA_PEL_IW);
+	outb(red   >> 10, VGA_PEL_D);
+	outb(green >> 10, VGA_PEL_D);
+	outb(blue  >> 10, VGA_PEL_D);
+}
+
+static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			     unsigned blue, unsigned transp,
+			     struct fb_info *info)
+{
+	struct vga16fb_par *par = info->par;
+	int gray;
+
+	/*
+	 *  Set a single color register. The values supplied are
+	 *  already rounded down to the hardware's capabilities
+	 *  (according to the entries in the `var' structure). Return
+	 *  != 0 for invalid regno.
+	 */
+	
+	if (regno >= 256)
+		return 1;
+
+	gray = info->var.grayscale;
+	
+	if (gray) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+	if (par->isVGA) 
+		vga16_setpalette(regno,red,green,blue);
+	else
+		ega16_setpalette(regno,red,green,blue);
+	return 0;
+}
+
+static int vga16fb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info) 
+{
+	vga16fb_pan_var(info, var);
+	return 0;
+}
+
+/* The following VESA blanking code is taken from vgacon.c.  The VGA
+   blanking code was originally by Huang shi chao, and modified by
+   Christoph Rimek (chrimek@toppoint.de) and todd j. derr
+   (tjd@barefoot.org) for Linux. */
+
+static void vga_vesa_blank(struct vga16fb_par *par, int mode)
+{
+	unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+	unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
+	
+	/* save original values of VGA controller registers */
+	if(!par->vesa_blanked) {
+		par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
+		//sti();
+
+		par->vga_state.HorizontalTotal = vga_io_rcrt(0x00);	/* HorizontalTotal */
+		par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01);	/* HorizDisplayEnd */
+		par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04);	/* StartHorizRetrace */
+		par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05);	/* EndHorizRetrace */
+		par->vga_state.Overflow = vga_io_rcrt(0x07);		/* Overflow */
+		par->vga_state.StartVertRetrace = vga_io_rcrt(0x10);	/* StartVertRetrace */
+		par->vga_state.EndVertRetrace = vga_io_rcrt(0x11);	/* EndVertRetrace */
+		par->vga_state.ModeControl = vga_io_rcrt(0x17);	/* ModeControl */
+		par->vga_state.ClockingMode = vga_io_rseq(0x01);	/* ClockingMode */
+	}
+
+	/* assure that video is enabled */
+	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
+	vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
+
+	/* test for vertical retrace in process.... */
+	if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
+		vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
+
+	/*
+	 * Set <End of vertical retrace> to minimum (0) and
+	 * <Start of vertical Retrace> to maximum (incl. overflow)
+	 * Result: turn off vertical sync (VSync) pulse.
+	 */
+	if (mode & FB_BLANK_VSYNC_SUSPEND) {
+		vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
+		vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
+		/* bits 9,10 of vert. retrace */
+		vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
+	}
+
+	if (mode & FB_BLANK_HSYNC_SUSPEND) {
+		/*
+		 * Set <End of horizontal retrace> to minimum (0) and
+		 *  <Start of horizontal Retrace> to maximum
+		 * Result: turn off horizontal sync (HSync) pulse.
+		 */
+		vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
+		vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
+	}
+
+	/* restore both index registers */
+	outb_p(SeqCtrlIndex, VGA_SEQ_I);
+	outb_p(CrtCtrlIndex, VGA_CRT_IC);
+}
+
+static void vga_vesa_unblank(struct vga16fb_par *par)
+{
+	unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+	unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
+	
+	/* restore original values of VGA controller registers */
+	vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
+
+	/* HorizontalTotal */
+	vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
+	/* HorizDisplayEnd */
+	vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd);
+	/* StartHorizRetrace */
+	vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace);
+	/* EndHorizRetrace */
+	vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace);
+	/* Overflow */
+	vga_io_wcrt(0x07, par->vga_state.Overflow);
+	/* StartVertRetrace */
+	vga_io_wcrt(0x10, par->vga_state.StartVertRetrace);
+	/* EndVertRetrace */
+	vga_io_wcrt(0x11, par->vga_state.EndVertRetrace);
+	/* ModeControl */
+	vga_io_wcrt(0x17, par->vga_state.ModeControl);
+	/* ClockingMode */
+	vga_io_wseq(0x01, par->vga_state.ClockingMode);
+
+	/* restore index/control registers */
+	vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
+	vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
+}
+
+static void vga_pal_blank(void)
+{
+	int i;
+
+	for (i=0; i<16; i++) {
+		outb_p(i, VGA_PEL_IW);
+		outb_p(0, VGA_PEL_D);
+		outb_p(0, VGA_PEL_D);
+		outb_p(0, VGA_PEL_D);
+	}
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+static int vga16fb_blank(int blank, struct fb_info *info)
+{
+	struct vga16fb_par *par = info->par;
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:				/* Unblank */
+		if (par->vesa_blanked) {
+			vga_vesa_unblank(par);
+			par->vesa_blanked = 0;
+		}
+		if (par->palette_blanked) {
+			par->palette_blanked = 0;
+		}
+		break;
+	case FB_BLANK_NORMAL:				/* blank */
+		vga_pal_blank();
+		par->palette_blanked = 1;
+		break;
+	default:			/* VESA blanking */
+		vga_vesa_blank(par, blank);
+		par->vesa_blanked = 1;
+		break;
+	}
+	return 0;
+}
+
+static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u32 dx = rect->dx, width = rect->width;
+        char oldindex = getindex();
+        char oldmode = setmode(0x40);
+        char oldmask = selectmask();
+        int line_ofs, height;
+        char oldop, oldsr;
+        char __iomem *where;
+
+        dx /= 4;
+        where = info->screen_base + dx + rect->dy * info->fix.line_length;
+
+        if (rect->rop == ROP_COPY) {
+                oldop = setop(0);
+                oldsr = setsr(0);
+
+                width /= 4;
+                line_ofs = info->fix.line_length - width;
+                setmask(0xff);
+
+                height = rect->height;
+
+                while (height--) {
+                        int x;
+
+                        /* we can do memset... */
+                        for (x = width; x > 0; --x) {
+                                writeb(rect->color, where);
+                                where++;
+                        }
+                        where += line_ofs;
+                }
+        } else {
+                char oldcolor = setcolor(0xf);
+                int y;
+
+                oldop = setop(0x18);
+                oldsr = setsr(0xf);
+                setmask(0x0F);
+                for (y = 0; y < rect->height; y++) {
+                        rmw(where);
+                        rmw(where+1);
+                        where += info->fix.line_length;
+                }
+                setcolor(oldcolor);
+        }
+        setmask(oldmask);
+        setsr(oldsr);
+        setop(oldop);
+        setmode(oldmode);
+        setindex(oldindex);
+}
+
+static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	int x, x2, y2, vxres, vyres, width, height, line_ofs;
+	char __iomem *dst;
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres)
+		return;
+
+	/* We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly. */
+
+	x2 = rect->dx + rect->width;
+	y2 = rect->dy + rect->height;
+	x2 = x2 < vxres ? x2 : vxres;
+	y2 = y2 < vyres ? y2 : vyres;
+	width = x2 - rect->dx;
+
+	switch (info->fix.type) {
+	case FB_TYPE_VGA_PLANES:
+		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
+
+			height = y2 - rect->dy;
+			width = rect->width/8;
+
+			line_ofs = info->fix.line_length - width;
+			dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length;
+
+			switch (rect->rop) {
+			case ROP_COPY:
+				setmode(0);
+				setop(0);
+				setsr(0xf);
+				setcolor(rect->color);
+				selectmask();
+
+				setmask(0xff);
+
+				while (height--) {
+					for (x = 0; x < width; x++) {
+						writeb(0, dst);
+						dst++;
+					}
+					dst += line_ofs;
+				}
+				break;
+			case ROP_XOR:
+				setmode(0);
+				setop(0x18);
+				setsr(0xf);
+				setcolor(0xf);
+				selectmask();
+
+				setmask(0xff);
+				while (height--) {
+					for (x = 0; x < width; x++) {
+						rmw(dst);
+						dst++;
+					}
+					dst += line_ofs;
+				}
+				break;
+			}
+		} else 
+			vga_8planes_fillrect(info, rect);
+		break;
+	case FB_TYPE_PACKED_PIXELS:
+	default:
+		cfb_fillrect(info, rect);
+		break;
+	}
+}
+
+static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+        char oldindex = getindex();
+        char oldmode = setmode(0x41);
+        char oldop = setop(0);
+        char oldsr = setsr(0xf);
+        int height, line_ofs, x;
+	u32 sx, dx, width;
+	char __iomem *dest;
+	char __iomem *src;
+
+        height = area->height;
+
+        sx = area->sx / 4;
+        dx = area->dx / 4;
+        width = area->width / 4;
+
+        if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) {
+                line_ofs = info->fix.line_length - width;
+                dest = info->screen_base + dx + area->dy * info->fix.line_length;
+                src = info->screen_base + sx + area->sy * info->fix.line_length;
+                while (height--) {
+                        for (x = 0; x < width; x++) {
+                                readb(src);
+                                writeb(0, dest);
+                                src++;
+                                dest++;
+                        }
+                        src += line_ofs;
+                        dest += line_ofs;
+                }
+        } else {
+                line_ofs = info->fix.line_length - width;
+                dest = info->screen_base + dx + width +
+			(area->dy + height - 1) * info->fix.line_length;
+                src = info->screen_base + sx + width +
+			(area->sy + height - 1) * info->fix.line_length;
+                while (height--) {
+                        for (x = 0; x < width; x++) {
+                                --src;
+                                --dest;
+                                readb(src);
+                                writeb(0, dest);
+                        }
+                        src -= line_ofs;
+                        dest -= line_ofs;
+                }
+        }
+
+        setsr(oldsr);
+        setop(oldop);
+        setmode(oldmode);
+        setindex(oldindex);
+}
+
+static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 
+	int x, x2, y2, old_dx, old_dy, vxres, vyres;
+	int height, width, line_ofs;
+	char __iomem *dst = NULL;
+	char __iomem *src = NULL;
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (area->dx > vxres || area->sx > vxres || area->dy > vyres ||
+	    area->sy > vyres)
+		return;
+
+	/* clip the destination */
+	old_dx = area->dx;
+	old_dy = area->dy;
+
+	/*
+	 * We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly.
+	 */
+	x2 = area->dx + area->width;
+	y2 = area->dy + area->height;
+	dx = area->dx > 0 ? area->dx : 0;
+	dy = area->dy > 0 ? area->dy : 0;
+	x2 = x2 < vxres ? x2 : vxres;
+	y2 = y2 < vyres ? y2 : vyres;
+	width = x2 - dx;
+	height = y2 - dy;
+
+	if (sx + dx < old_dx || sy + dy < old_dy)
+		return;
+
+	/* update sx1,sy1 */
+	sx += (dx - old_dx);
+	sy += (dy - old_dy);
+
+	/* the source must be completely inside the virtual screen */
+	if (sx + width > vxres || sy + height > vyres)
+		return;
+
+	switch (info->fix.type) {
+	case FB_TYPE_VGA_PLANES:
+		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
+			width = width/8;
+			height = height;
+			line_ofs = info->fix.line_length - width;
+
+			setmode(1);
+			setop(0);
+			setsr(0xf);
+
+			if (dy < sy || (dy == sy && dx < sx)) {
+				dst = info->screen_base + (dx/8) + dy * info->fix.line_length;
+				src = info->screen_base + (sx/8) + sy * info->fix.line_length;
+				while (height--) {
+					for (x = 0; x < width; x++) {
+						readb(src);
+						writeb(0, dst);
+						dst++;
+						src++;
+					}
+					src += line_ofs;
+					dst += line_ofs;
+				}
+			} else {
+				dst = info->screen_base + (dx/8) + width + 
+					(dy + height - 1) * info->fix.line_length;
+				src = info->screen_base + (sx/8) + width + 
+					(sy + height  - 1) * info->fix.line_length;
+				while (height--) {
+					for (x = 0; x < width; x++) {
+						dst--;
+						src--;
+						readb(src);
+						writeb(0, dst);
+					}
+					src -= line_ofs;
+					dst -= line_ofs;
+				}
+			}
+		} else 
+			vga_8planes_copyarea(info, area);
+		break;
+	case FB_TYPE_PACKED_PIXELS:
+	default:
+		cfb_copyarea(info, area);
+		break;
+	}
+}
+
+#define TRANS_MASK_LOW  {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
+#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
+			 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
+
+#if defined(__LITTLE_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_LOW;
+static const u16 transl_h[] = TRANS_MASK_HIGH;
+#elif defined(__BIG_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_HIGH;
+static const u16 transl_h[] = TRANS_MASK_LOW;
+#else
+#error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
+#endif
+
+static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+        char oldindex = getindex();
+        char oldmode = setmode(0x40);
+        char oldop = setop(0);
+        char oldsr = setsr(0);
+        char oldmask = selectmask();
+        const char *cdat = image->data;
+	u32 dx = image->dx;
+        char __iomem *where;
+        int y;
+
+        dx /= 4;
+        where = info->screen_base + dx + image->dy * info->fix.line_length;
+
+        setmask(0xff);
+        writeb(image->bg_color, where);
+        readb(where);
+        selectmask();
+        setmask(image->fg_color ^ image->bg_color);
+        setmode(0x42);
+        setop(0x18);
+        for (y = 0; y < image->height; y++, where += info->fix.line_length)
+                writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where);
+        setmask(oldmask);
+        setsr(oldsr);
+        setop(oldop);
+        setmode(oldmode);
+        setindex(oldindex);
+}
+
+static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
+{
+	char __iomem *where = info->screen_base + (image->dx/8) +
+		image->dy * info->fix.line_length;
+	struct vga16fb_par *par = info->par;
+	char *cdat = (char *) image->data;
+	char __iomem *dst;
+	int x, y;
+
+	switch (info->fix.type) {
+	case FB_TYPE_VGA_PLANES:
+		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
+			if (par->isVGA) {
+				setmode(2);
+				setop(0);
+				setsr(0xf);
+				setcolor(image->fg_color);
+				selectmask();
+				
+				setmask(0xff);
+				writeb(image->bg_color, where);
+				rmb();
+				readb(where); /* fill latches */
+				setmode(3);
+				wmb();
+				for (y = 0; y < image->height; y++) {
+					dst = where;
+					for (x = image->width/8; x--;) 
+						writeb(*cdat++, dst++);
+					where += info->fix.line_length;
+				}
+				wmb();
+			} else {
+				setmode(0);
+				setop(0);
+				setsr(0xf);
+				setcolor(image->bg_color);
+				selectmask();
+				
+				setmask(0xff);
+				for (y = 0; y < image->height; y++) {
+					dst = where;
+					for (x=image->width/8; x--;){
+						rmw(dst);
+						setcolor(image->fg_color);
+						selectmask();
+						if (*cdat) {
+							setmask(*cdat++);
+							rmw(dst++);
+						}
+					}
+					where += info->fix.line_length;
+				}
+			}
+		} else 
+			vga_8planes_imageblit(info, image);
+		break;
+	case FB_TYPE_PACKED_PIXELS:
+	default:
+		cfb_imageblit(info, image);
+		break;
+	}
+}
+
+static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
+{
+	/*
+	 * Draw logo 
+	 */
+	struct vga16fb_par *par = info->par;
+	char __iomem *where =
+		info->screen_base + image->dy * info->fix.line_length +
+		image->dx/8;
+	const char *cdat = image->data;
+	char __iomem *dst;
+	int x, y;
+
+	switch (info->fix.type) {
+	case FB_TYPE_VGA_PLANES:
+		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&
+		    par->isVGA) {
+			setsr(0xf);
+			setop(0);
+			setmode(0);
+			
+			for (y = 0; y < image->height; y++) {
+				for (x = 0; x < image->width; x++) {
+					dst = where + x/8;
+
+					setcolor(*cdat);
+					selectmask();
+					setmask(1 << (7 - (x % 8)));
+					fb_readb(dst);
+					fb_writeb(0, dst);
+
+					cdat++;
+				}
+				where += info->fix.line_length;
+			}
+		}
+		break;
+	case FB_TYPE_PACKED_PIXELS:
+		cfb_imageblit(info, image);
+		break;
+	default:
+		break;
+	}
+}
+				
+static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if (image->depth == 1)
+		vga_imageblit_expand(info, image);
+	else
+		vga_imageblit_color(info, image);
+}
+
+static void vga16fb_destroy(struct fb_info *info)
+{
+	iounmap(info->screen_base);
+	fb_dealloc_cmap(&info->cmap);
+	/* XXX unshare VGA regions */
+	framebuffer_release(info);
+}
+
+static struct fb_ops vga16fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open        = vga16fb_open,
+	.fb_release     = vga16fb_release,
+	.fb_destroy	= vga16fb_destroy,
+	.fb_check_var	= vga16fb_check_var,
+	.fb_set_par	= vga16fb_set_par,
+	.fb_setcolreg 	= vga16fb_setcolreg,
+	.fb_pan_display = vga16fb_pan_display,
+	.fb_blank 	= vga16fb_blank,
+	.fb_fillrect	= vga16fb_fillrect,
+	.fb_copyarea	= vga16fb_copyarea,
+	.fb_imageblit	= vga16fb_imageblit,
+};
+
+#ifndef MODULE
+static int __init vga16fb_setup(char *options)
+{
+	char *this_opt;
+	
+	if (!options || !*options)
+		return 0;
+	
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt) continue;
+	}
+	return 0;
+}
+#endif
+
+static int vga16fb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	struct vga16fb_par *par;
+	int i;
+	int ret = 0;
+
+	printk(KERN_DEBUG "vga16fb: initializing\n");
+	info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
+
+	if (!info) {
+		ret = -ENOMEM;
+		goto err_fb_alloc;
+	}
+	info->apertures = alloc_apertures(1);
+	if (!info->apertures) {
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
+	info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
+
+	if (!info->screen_base) {
+		printk(KERN_ERR "vga16fb: unable to map device\n");
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
+	par = info->par;
+
+	par->isVGA = screen_info.orig_video_isVGA;
+	par->palette_blanked = 0;
+	par->vesa_blanked = 0;
+
+	i = par->isVGA? 6 : 2;
+	
+	vga16fb_defined.red.length   = i;
+	vga16fb_defined.green.length = i;
+	vga16fb_defined.blue.length  = i;	
+
+	/* name should not depend on EGA/VGA */
+	info->fbops = &vga16fb_ops;
+	info->var = vga16fb_defined;
+	info->fix = vga16fb_fix;
+	/* supports rectangles with widths of multiples of 8 */
+	info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE |
+		FBINFO_HWACCEL_YPAN;
+
+	i = (info->var.bits_per_pixel == 8) ? 256 : 16;
+	ret = fb_alloc_cmap(&info->cmap, i, 0);
+	if (ret) {
+		printk(KERN_ERR "vga16fb: unable to allocate colormap\n");
+		ret = -ENOMEM;
+		goto err_alloc_cmap;
+	}
+
+	if (vga16fb_check_var(&info->var, info)) {
+		printk(KERN_ERR "vga16fb: unable to validate variable\n");
+		ret = -EINVAL;
+		goto err_check_var;
+	}
+
+	vga16fb_update_fix(info);
+
+	info->apertures->ranges[0].base = VGA_FB_PHYS;
+	info->apertures->ranges[0].size = VGA_FB_PHYS_LEN;
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
+		ret = -EINVAL;
+		goto err_check_var;
+	}
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	platform_set_drvdata(dev, info);
+
+	return 0;
+
+ err_check_var:
+	fb_dealloc_cmap(&info->cmap);
+ err_alloc_cmap:
+	iounmap(info->screen_base);
+ err_ioremap:
+	framebuffer_release(info);
+ err_fb_alloc:
+	return ret;
+}
+
+static int vga16fb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info)
+		unregister_framebuffer(info);
+
+	return 0;
+}
+
+static struct platform_driver vga16fb_driver = {
+	.probe = vga16fb_probe,
+	.remove = vga16fb_remove,
+	.driver = {
+		.name = "vga16fb",
+	},
+};
+
+static struct platform_device *vga16fb_device;
+
+static int __init vga16fb_init(void)
+{
+	int ret;
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("vga16fb", &option))
+		return -ENODEV;
+
+	vga16fb_setup(option);
+#endif
+	ret = platform_driver_register(&vga16fb_driver);
+
+	if (!ret) {
+		vga16fb_device = platform_device_alloc("vga16fb", 0);
+
+		if (vga16fb_device)
+			ret = platform_device_add(vga16fb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(vga16fb_device);
+			platform_driver_unregister(&vga16fb_driver);
+		}
+	}
+
+	return ret;
+}
+
+static void __exit vga16fb_exit(void)
+{
+	platform_device_unregister(vga16fb_device);
+	platform_driver_unregister(&vga16fb_driver);
+}
+
+MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
+MODULE_LICENSE("GPL");
+module_init(vga16fb_init);
+module_exit(vga16fb_exit);
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/drivers/video/fbdev/via/Makefile b/drivers/video/fbdev/via/Makefile
new file mode 100644
index 000000000000..159f26e6adb5
--- /dev/null
+++ b/drivers/video/fbdev/via/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the VIA framebuffer driver (for Linux Kernel 2.6)
+#
+
+obj-$(CONFIG_FB_VIA) += viafb.o
+
+viafb-y	:=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
+	via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \
+	via-core.o via-gpio.o via_modesetting.o via_clock.o \
+	via_aux.o via_aux_edid.o via_aux_vt1636.o via_aux_vt1632.o \
+	via_aux_vt1631.o via_aux_vt1625.o via_aux_vt1622.o via_aux_vt1621.o \
+	via_aux_sii164.o via_aux_ch7301.o
diff --git a/drivers/video/fbdev/via/accel.c b/drivers/video/fbdev/via/accel.c
new file mode 100644
index 000000000000..4b67b8e6030a
--- /dev/null
+++ b/drivers/video/fbdev/via/accel.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/via-core.h>
+#include "global.h"
+
+/*
+ * Figure out an appropriate bytes-per-pixel setting.
+ */
+static int viafb_set_bpp(void __iomem *engine, u8 bpp)
+{
+	u32 gemode;
+
+	/* Preserve the reserved bits */
+	/* Lowest 2 bits to zero gives us no rotation */
+	gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc;
+	switch (bpp) {
+	case 8:
+		gemode |= VIA_GEM_8bpp;
+		break;
+	case 16:
+		gemode |= VIA_GEM_16bpp;
+		break;
+	case 32:
+		gemode |= VIA_GEM_32bpp;
+		break;
+	default:
+		printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp);
+		return -EINVAL;
+	}
+	writel(gemode, engine + VIA_REG_GEMODE);
+	return 0;
+}
+
+
+static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
+	u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
+	u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
+	u32 fg_color, u32 bg_color, u8 fill_rop)
+{
+	u32 ge_cmd = 0, tmp, i;
+	int ret;
+
+	if (!op || op > 3) {
+		printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
+		return -EINVAL;
+	}
+
+	if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
+		if (src_x < dst_x) {
+			ge_cmd |= 0x00008000;
+			src_x += width - 1;
+			dst_x += width - 1;
+		}
+		if (src_y < dst_y) {
+			ge_cmd |= 0x00004000;
+			src_y += height - 1;
+			dst_y += height - 1;
+		}
+	}
+
+	if (op == VIA_BITBLT_FILL) {
+		switch (fill_rop) {
+		case 0x00: /* blackness */
+		case 0x5A: /* pattern inversion */
+		case 0xF0: /* pattern copy */
+		case 0xFF: /* whiteness */
+			break;
+		default:
+			printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
+				"%u\n", fill_rop);
+			return -EINVAL;
+		}
+	}
+
+	ret = viafb_set_bpp(engine, dst_bpp);
+	if (ret)
+		return ret;
+
+	if (op != VIA_BITBLT_FILL) {
+		if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
+			|| src_y & 0xFFFFF000) {
+			printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
+				"x/y %d %d\n", src_x, src_y);
+			return -EINVAL;
+		}
+		tmp = src_x | (src_y << 16);
+		writel(tmp, engine + 0x08);
+	}
+
+	if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
+		printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y "
+			"%d %d\n", dst_x, dst_y);
+		return -EINVAL;
+	}
+	tmp = dst_x | (dst_y << 16);
+	writel(tmp, engine + 0x0C);
+
+	if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
+		printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height "
+			"%d %d\n", width, height);
+		return -EINVAL;
+	}
+	tmp = (width - 1) | ((height - 1) << 16);
+	writel(tmp, engine + 0x10);
+
+	if (op != VIA_BITBLT_COLOR)
+		writel(fg_color, engine + 0x18);
+
+	if (op == VIA_BITBLT_MONO)
+		writel(bg_color, engine + 0x1C);
+
+	if (op != VIA_BITBLT_FILL) {
+		tmp = src_mem ? 0 : src_addr;
+		if (dst_addr & 0xE0000007) {
+			printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
+				"address %X\n", tmp);
+			return -EINVAL;
+		}
+		tmp >>= 3;
+		writel(tmp, engine + 0x30);
+	}
+
+	if (dst_addr & 0xE0000007) {
+		printk(KERN_WARNING "hw_bitblt_1: Unsupported destination "
+			"address %X\n", dst_addr);
+		return -EINVAL;
+	}
+	tmp = dst_addr >> 3;
+	writel(tmp, engine + 0x34);
+
+	if (op == VIA_BITBLT_FILL)
+		tmp = 0;
+	else
+		tmp = src_pitch;
+	if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
+		printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n",
+			tmp, dst_pitch);
+		return -EINVAL;
+	}
+	tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3));
+	writel(tmp, engine + 0x38);
+
+	if (op == VIA_BITBLT_FILL)
+		ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
+	else {
+		ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
+		if (src_mem)
+			ge_cmd |= 0x00000040;
+		if (op == VIA_BITBLT_MONO)
+			ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
+		else
+			ge_cmd |= 0x00000001;
+	}
+	writel(ge_cmd, engine);
+
+	if (op == VIA_BITBLT_FILL || !src_mem)
+		return 0;
+
+	tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
+		3) >> 2;
+
+	for (i = 0; i < tmp; i++)
+		writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
+
+	return 0;
+}
+
+static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
+	u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
+	u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
+	u32 fg_color, u32 bg_color, u8 fill_rop)
+{
+	u32 ge_cmd = 0, tmp, i;
+	int ret;
+
+	if (!op || op > 3) {
+		printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
+		return -EINVAL;
+	}
+
+	if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
+		if (src_x < dst_x) {
+			ge_cmd |= 0x00008000;
+			src_x += width - 1;
+			dst_x += width - 1;
+		}
+		if (src_y < dst_y) {
+			ge_cmd |= 0x00004000;
+			src_y += height - 1;
+			dst_y += height - 1;
+		}
+	}
+
+	if (op == VIA_BITBLT_FILL) {
+		switch (fill_rop) {
+		case 0x00: /* blackness */
+		case 0x5A: /* pattern inversion */
+		case 0xF0: /* pattern copy */
+		case 0xFF: /* whiteness */
+			break;
+		default:
+			printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
+				"%u\n", fill_rop);
+			return -EINVAL;
+		}
+	}
+
+	ret = viafb_set_bpp(engine, dst_bpp);
+	if (ret)
+		return ret;
+
+	if (op == VIA_BITBLT_FILL)
+		tmp = 0;
+	else
+		tmp = src_pitch;
+	if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
+		printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n",
+			tmp, dst_pitch);
+		return -EINVAL;
+	}
+	tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
+	writel(tmp, engine + 0x08);
+
+	if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
+		printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height "
+			"%d %d\n", width, height);
+		return -EINVAL;
+	}
+	tmp = (width - 1) | ((height - 1) << 16);
+	writel(tmp, engine + 0x0C);
+
+	if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
+		printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y "
+			"%d %d\n", dst_x, dst_y);
+		return -EINVAL;
+	}
+	tmp = dst_x | (dst_y << 16);
+	writel(tmp, engine + 0x10);
+
+	if (dst_addr & 0xE0000007) {
+		printk(KERN_WARNING "hw_bitblt_2: Unsupported destination "
+			"address %X\n", dst_addr);
+		return -EINVAL;
+	}
+	tmp = dst_addr >> 3;
+	writel(tmp, engine + 0x14);
+
+	if (op != VIA_BITBLT_FILL) {
+		if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
+			|| src_y & 0xFFFFF000) {
+			printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
+				"x/y %d %d\n", src_x, src_y);
+			return -EINVAL;
+		}
+		tmp = src_x | (src_y << 16);
+		writel(tmp, engine + 0x18);
+
+		tmp = src_mem ? 0 : src_addr;
+		if (dst_addr & 0xE0000007) {
+			printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
+				"address %X\n", tmp);
+			return -EINVAL;
+		}
+		tmp >>= 3;
+		writel(tmp, engine + 0x1C);
+	}
+
+	if (op == VIA_BITBLT_FILL) {
+		writel(fg_color, engine + 0x58);
+	} else if (op == VIA_BITBLT_MONO) {
+		writel(fg_color, engine + 0x4C);
+		writel(bg_color, engine + 0x50);
+	}
+
+	if (op == VIA_BITBLT_FILL)
+		ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
+	else {
+		ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
+		if (src_mem)
+			ge_cmd |= 0x00000040;
+		if (op == VIA_BITBLT_MONO)
+			ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
+		else
+			ge_cmd |= 0x00000001;
+	}
+	writel(ge_cmd, engine);
+
+	if (op == VIA_BITBLT_FILL || !src_mem)
+		return 0;
+
+	tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
+		3) >> 2;
+
+	for (i = 0; i < tmp; i++)
+		writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
+
+	return 0;
+}
+
+int viafb_setup_engine(struct fb_info *info)
+{
+	struct viafb_par *viapar = info->par;
+	void __iomem *engine;
+	u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
+
+	engine = viapar->shared->vdev->engine_mmio;
+	if (!engine) {
+		printk(KERN_WARNING "viafb_init_accel: ioremap failed, "
+			"hardware acceleration disabled\n");
+		return -ENOMEM;
+	}
+
+	switch (chip_name) {
+	case UNICHROME_CLE266:
+	case UNICHROME_K400:
+	case UNICHROME_K800:
+	case UNICHROME_PM800:
+	case UNICHROME_CN700:
+	case UNICHROME_CX700:
+	case UNICHROME_CN750:
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M890:
+	case UNICHROME_P4M900:
+		viapar->shared->hw_bitblt = hw_bitblt_1;
+		break;
+	case UNICHROME_VX800:
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		viapar->shared->hw_bitblt = hw_bitblt_2;
+		break;
+	default:
+		viapar->shared->hw_bitblt = NULL;
+	}
+
+	viapar->fbmem_free -= CURSOR_SIZE;
+	viapar->shared->cursor_vram_addr = viapar->fbmem_free;
+	viapar->fbmem_used += CURSOR_SIZE;
+
+	viapar->fbmem_free -= VQ_SIZE;
+	viapar->shared->vq_vram_addr = viapar->fbmem_free;
+	viapar->fbmem_used += VQ_SIZE;
+
+#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
+	/*
+	 * Set aside a chunk of framebuffer memory for the camera
+	 * driver.  Someday this driver probably needs a proper allocator
+	 * for fbmem; for now, we just have to do this before the
+	 * framebuffer initializes itself.
+	 *
+	 * As for the size: the engine can handle three frames,
+	 * 16 bits deep, up to VGA resolution.
+	 */
+	viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2;
+	viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size;
+	viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size;
+	viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
+#endif
+
+	viafb_reset_engine(viapar);
+	return 0;
+}
+
+void viafb_reset_engine(struct viafb_par *viapar)
+{
+	void __iomem *engine = viapar->shared->vdev->engine_mmio;
+	int highest_reg, i;
+	u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
+		vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
+
+	/* Initialize registers to reset the 2D engine */
+	switch (viapar->shared->chip_info.twod_engine) {
+	case VIA_2D_ENG_M1:
+		highest_reg = 0x5c;
+		break;
+	default:
+		highest_reg = 0x40;
+		break;
+	}
+	for (i = 0; i <= highest_reg; i += 4)
+		writel(0x0, engine + i);
+
+	/* Init AGP and VQ regs */
+	switch (chip_name) {
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M900:
+	case UNICHROME_VX800:
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		writel(0x00100000, engine + VIA_REG_CR_TRANSET);
+		writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
+		writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
+		break;
+
+	default:
+		writel(0x00100000, engine + VIA_REG_TRANSET);
+		writel(0x00000000, engine + VIA_REG_TRANSPACE);
+		writel(0x00333004, engine + VIA_REG_TRANSPACE);
+		writel(0x60000000, engine + VIA_REG_TRANSPACE);
+		writel(0x61000000, engine + VIA_REG_TRANSPACE);
+		writel(0x62000000, engine + VIA_REG_TRANSPACE);
+		writel(0x63000000, engine + VIA_REG_TRANSPACE);
+		writel(0x64000000, engine + VIA_REG_TRANSPACE);
+		writel(0x7D000000, engine + VIA_REG_TRANSPACE);
+
+		writel(0xFE020000, engine + VIA_REG_TRANSET);
+		writel(0x00000000, engine + VIA_REG_TRANSPACE);
+		break;
+	}
+
+	/* Enable VQ */
+	vq_start_addr = viapar->shared->vq_vram_addr;
+	vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1;
+
+	vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF);
+	vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF);
+	vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) |
+		((vq_end_addr & 0xFF000000) >> 16);
+	vq_len = 0x53000000 | (VQ_SIZE >> 3);
+
+	switch (chip_name) {
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M900:
+	case UNICHROME_VX800:
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		vq_start_low |= 0x20000000;
+		vq_end_low |= 0x20000000;
+		vq_high |= 0x20000000;
+		vq_len |= 0x20000000;
+
+		writel(0x00100000, engine + VIA_REG_CR_TRANSET);
+		writel(vq_high, engine + VIA_REG_CR_TRANSPACE);
+		writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE);
+		writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE);
+		writel(vq_len, engine + VIA_REG_CR_TRANSPACE);
+		writel(0x74301001, engine + VIA_REG_CR_TRANSPACE);
+		writel(0x00000000, engine + VIA_REG_CR_TRANSPACE);
+		break;
+	default:
+		writel(0x00FE0000, engine + VIA_REG_TRANSET);
+		writel(0x080003FE, engine + VIA_REG_TRANSPACE);
+		writel(0x0A00027C, engine + VIA_REG_TRANSPACE);
+		writel(0x0B000260, engine + VIA_REG_TRANSPACE);
+		writel(0x0C000274, engine + VIA_REG_TRANSPACE);
+		writel(0x0D000264, engine + VIA_REG_TRANSPACE);
+		writel(0x0E000000, engine + VIA_REG_TRANSPACE);
+		writel(0x0F000020, engine + VIA_REG_TRANSPACE);
+		writel(0x1000027E, engine + VIA_REG_TRANSPACE);
+		writel(0x110002FE, engine + VIA_REG_TRANSPACE);
+		writel(0x200F0060, engine + VIA_REG_TRANSPACE);
+
+		writel(0x00000006, engine + VIA_REG_TRANSPACE);
+		writel(0x40008C0F, engine + VIA_REG_TRANSPACE);
+		writel(0x44000000, engine + VIA_REG_TRANSPACE);
+		writel(0x45080C04, engine + VIA_REG_TRANSPACE);
+		writel(0x46800408, engine + VIA_REG_TRANSPACE);
+
+		writel(vq_high, engine + VIA_REG_TRANSPACE);
+		writel(vq_start_low, engine + VIA_REG_TRANSPACE);
+		writel(vq_end_low, engine + VIA_REG_TRANSPACE);
+		writel(vq_len, engine + VIA_REG_TRANSPACE);
+		break;
+	}
+
+	/* Set Cursor Image Base Address */
+	writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE);
+	writel(0x0, engine + VIA_REG_CURSOR_POS);
+	writel(0x0, engine + VIA_REG_CURSOR_ORG);
+	writel(0x0, engine + VIA_REG_CURSOR_BG);
+	writel(0x0, engine + VIA_REG_CURSOR_FG);
+	return;
+}
+
+void viafb_show_hw_cursor(struct fb_info *info, int Status)
+{
+	struct viafb_par *viapar = info->par;
+	u32 temp, iga_path = viapar->iga_path;
+
+	temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
+	switch (Status) {
+	case HW_Cursor_ON:
+		temp |= 0x1;
+		break;
+	case HW_Cursor_OFF:
+		temp &= 0xFFFFFFFE;
+		break;
+	}
+	switch (iga_path) {
+	case IGA2:
+		temp |= 0x80000000;
+		break;
+	case IGA1:
+	default:
+		temp &= 0x7FFFFFFF;
+	}
+	writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
+}
+
+void viafb_wait_engine_idle(struct fb_info *info)
+{
+	struct viafb_par *viapar = info->par;
+	int loop = 0;
+	u32 mask;
+	void __iomem *engine = viapar->shared->vdev->engine_mmio;
+
+	switch (viapar->shared->chip_info.twod_engine) {
+	case VIA_2D_ENG_H5:
+	case VIA_2D_ENG_M1:
+		mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 |
+			      VIA_3D_ENG_BUSY_M1;
+		break;
+	default:
+		while (!(readl(engine + VIA_REG_STATUS) &
+				VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
+			loop++;
+			cpu_relax();
+		}
+		mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY;
+		break;
+	}
+
+	while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) {
+		loop++;
+		cpu_relax();
+	}
+
+	if (loop >= MAXLOOP)
+		printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n");
+}
diff --git a/drivers/video/fbdev/via/accel.h b/drivers/video/fbdev/via/accel.h
new file mode 100644
index 000000000000..79d5e10cc835
--- /dev/null
+++ b/drivers/video/fbdev/via/accel.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ACCEL_H__
+#define __ACCEL_H__
+
+#define FB_ACCEL_VIA_UNICHROME  50
+
+/* MMIO Base Address Definition */
+#define MMIO_VGABASE                0x8000
+#define MMIO_CR_READ                (MMIO_VGABASE + 0x3D4)
+#define MMIO_CR_WRITE               (MMIO_VGABASE + 0x3D5)
+#define MMIO_SR_READ                (MMIO_VGABASE + 0x3C4)
+#define MMIO_SR_WRITE               (MMIO_VGABASE + 0x3C5)
+
+/* HW Cursor Status Define */
+#define HW_Cursor_ON    0
+#define HW_Cursor_OFF   1
+
+#define CURSOR_SIZE     (8 * 1024)
+#define VQ_SIZE         (256 * 1024)
+
+#define VIA_MMIO_BLTBASE        0x200000
+#define VIA_MMIO_BLTSIZE        0x200000
+
+/* Defines for 2D registers */
+#define VIA_REG_GECMD           0x000
+#define VIA_REG_GEMODE          0x004
+#define VIA_REG_SRCPOS          0x008
+#define VIA_REG_DSTPOS          0x00C
+/* width and height */
+#define VIA_REG_DIMENSION       0x010
+#define VIA_REG_PATADDR         0x014
+#define VIA_REG_FGCOLOR         0x018
+#define VIA_REG_BGCOLOR         0x01C
+/* top and left of clipping */
+#define VIA_REG_CLIPTL          0x020
+/* bottom and right of clipping */
+#define VIA_REG_CLIPBR          0x024
+#define VIA_REG_OFFSET          0x028
+/* color key control */
+#define VIA_REG_KEYCONTROL      0x02C
+#define VIA_REG_SRCBASE         0x030
+#define VIA_REG_DSTBASE         0x034
+/* pitch of src and dst */
+#define VIA_REG_PITCH           0x038
+#define VIA_REG_MONOPAT0        0x03C
+#define VIA_REG_MONOPAT1        0x040
+/* from 0x100 to 0x1ff */
+#define VIA_REG_COLORPAT        0x100
+
+/* defines for VIA 2D registers for vt3353/3409 (M1 engine)*/
+#define VIA_REG_GECMD_M1        0x000
+#define VIA_REG_GEMODE_M1       0x004
+#define VIA_REG_GESTATUS_M1     0x004       /* as same as VIA_REG_GEMODE */
+#define VIA_REG_PITCH_M1        0x008       /* pitch of src and dst */
+#define VIA_REG_DIMENSION_M1    0x00C       /* width and height */
+#define VIA_REG_DSTPOS_M1       0x010
+#define VIA_REG_LINE_XY_M1      0x010
+#define VIA_REG_DSTBASE_M1      0x014
+#define VIA_REG_SRCPOS_M1       0x018
+#define VIA_REG_LINE_K1K2_M1    0x018
+#define VIA_REG_SRCBASE_M1      0x01C
+#define VIA_REG_PATADDR_M1      0x020
+#define VIA_REG_MONOPAT0_M1     0x024
+#define VIA_REG_MONOPAT1_M1     0x028
+#define VIA_REG_OFFSET_M1       0x02C
+#define VIA_REG_LINE_ERROR_M1   0x02C
+#define VIA_REG_CLIPTL_M1       0x040       /* top and left of clipping */
+#define VIA_REG_CLIPBR_M1       0x044       /* bottom and right of clipping */
+#define VIA_REG_KEYCONTROL_M1   0x048       /* color key control */
+#define VIA_REG_FGCOLOR_M1      0x04C
+#define VIA_REG_DSTCOLORKEY_M1  0x04C       /* as same as VIA_REG_FG */
+#define VIA_REG_BGCOLOR_M1      0x050
+#define VIA_REG_SRCCOLORKEY_M1  0x050       /* as same as VIA_REG_BG */
+#define VIA_REG_MONOPATFGC_M1   0x058       /* Add BG color of Pattern. */
+#define VIA_REG_MONOPATBGC_M1   0x05C       /* Add FG color of Pattern. */
+#define VIA_REG_COLORPAT_M1     0x100       /* from 0x100 to 0x1ff */
+
+/* VIA_REG_PITCH(0x38): Pitch Setting */
+#define VIA_PITCH_ENABLE        0x80000000
+
+/* defines for VIA HW cursor registers */
+#define VIA_REG_CURSOR_MODE     0x2D0
+#define VIA_REG_CURSOR_POS      0x2D4
+#define VIA_REG_CURSOR_ORG      0x2D8
+#define VIA_REG_CURSOR_BG       0x2DC
+#define VIA_REG_CURSOR_FG       0x2E0
+
+/* VIA_REG_GEMODE(0x04): GE mode */
+#define VIA_GEM_8bpp            0x00000000
+#define VIA_GEM_16bpp           0x00000100
+#define VIA_GEM_32bpp           0x00000300
+
+/* VIA_REG_GECMD(0x00): 2D Engine Command  */
+#define VIA_GEC_NOOP            0x00000000
+#define VIA_GEC_BLT             0x00000001
+#define VIA_GEC_LINE            0x00000005
+
+/* Rotate Command */
+#define VIA_GEC_ROT             0x00000008
+
+#define VIA_GEC_SRC_XY          0x00000000
+#define VIA_GEC_SRC_LINEAR      0x00000010
+#define VIA_GEC_DST_XY          0x00000000
+#define VIA_GEC_DST_LINRAT      0x00000020
+
+#define VIA_GEC_SRC_FB          0x00000000
+#define VIA_GEC_SRC_SYS         0x00000040
+#define VIA_GEC_DST_FB          0x00000000
+#define VIA_GEC_DST_SYS         0x00000080
+
+/* source is mono */
+#define VIA_GEC_SRC_MONO        0x00000100
+/* pattern is mono */
+#define VIA_GEC_PAT_MONO        0x00000200
+/* mono src is opaque */
+#define VIA_GEC_MSRC_OPAQUE     0x00000000
+/* mono src is transparent */
+#define VIA_GEC_MSRC_TRANS      0x00000400
+/* pattern is in frame buffer */
+#define VIA_GEC_PAT_FB          0x00000000
+/* pattern is from reg setting */
+#define VIA_GEC_PAT_REG         0x00000800
+
+#define VIA_GEC_CLIP_DISABLE    0x00000000
+#define VIA_GEC_CLIP_ENABLE     0x00001000
+
+#define VIA_GEC_FIXCOLOR_PAT    0x00002000
+
+#define VIA_GEC_INCX            0x00000000
+#define VIA_GEC_DECY            0x00004000
+#define VIA_GEC_INCY            0x00000000
+#define VIA_GEC_DECX            0x00008000
+/* mono pattern is opaque */
+#define VIA_GEC_MPAT_OPAQUE     0x00000000
+/* mono pattern is transparent */
+#define VIA_GEC_MPAT_TRANS      0x00010000
+
+#define VIA_GEC_MONO_UNPACK     0x00000000
+#define VIA_GEC_MONO_PACK       0x00020000
+#define VIA_GEC_MONO_DWORD      0x00000000
+#define VIA_GEC_MONO_WORD       0x00040000
+#define VIA_GEC_MONO_BYTE       0x00080000
+
+#define VIA_GEC_LASTPIXEL_ON    0x00000000
+#define VIA_GEC_LASTPIXEL_OFF   0x00100000
+#define VIA_GEC_X_MAJOR         0x00000000
+#define VIA_GEC_Y_MAJOR         0x00200000
+#define VIA_GEC_QUICK_START     0x00800000
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS          0x400
+#define VIA_REG_CR_TRANSET      0x41C
+#define VIA_REG_CR_TRANSPACE	0x420
+#define VIA_REG_TRANSET         0x43C
+#define VIA_REG_TRANSPACE       0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+
+/* Command Regulator is busy */
+#define VIA_CMD_RGTR_BUSY       0x00000080
+/* 2D Engine is busy */
+#define VIA_2D_ENG_BUSY         0x00000002
+/* 3D Engine is busy */
+#define VIA_3D_ENG_BUSY         0x00000001
+/* Virtual Queue is busy */
+#define VIA_VR_QUEUE_BUSY       0x00020000
+
+/* VIA_REG_STATUS(0x400): Engine Status for H5 */
+#define VIA_CMD_RGTR_BUSY_H5   0x00000010  /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY_H5     0x00000002  /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY_H5     0x00001FE1  /* 3D Engine is busy */
+#define VIA_VR_QUEUE_BUSY_H5   0x00000004  /* Virtual Queue is busy */
+
+/* VIA_REG_STATUS(0x400): Engine Status for VT3353/3409 */
+#define VIA_CMD_RGTR_BUSY_M1   0x00000010  /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY_M1     0x00000002  /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY_M1     0x00001FE1  /* 3D Engine is busy */
+#define VIA_VR_QUEUE_BUSY_M1   0x00000004  /* Virtual Queue is busy */
+
+#define MAXLOOP                 0xFFFFFF
+
+#define VIA_BITBLT_COLOR	1
+#define VIA_BITBLT_MONO		2
+#define VIA_BITBLT_FILL		3
+
+int viafb_setup_engine(struct fb_info *info);
+void viafb_reset_engine(struct viafb_par *viapar);
+void viafb_show_hw_cursor(struct fb_info *info, int Status);
+void viafb_wait_engine_idle(struct fb_info *info);
+
+#endif /* __ACCEL_H__ */
diff --git a/drivers/video/fbdev/via/chip.h b/drivers/video/fbdev/via/chip.h
new file mode 100644
index 000000000000..d32a5076c20f
--- /dev/null
+++ b/drivers/video/fbdev/via/chip.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __CHIP_H__
+#define __CHIP_H__
+
+#include "global.h"
+
+/***************************************/
+/* Definition Graphic Chip Information */
+/***************************************/
+
+#define     PCI_VIA_VENDOR_ID       0x1106
+
+/* Define VIA Graphic Chip Name */
+#define     UNICHROME_CLE266        1
+#define     UNICHROME_CLE266_DID    0x3122
+#define     CLE266_REVISION_AX      0x0A
+#define     CLE266_REVISION_CX      0x0C
+
+#define     UNICHROME_K400          2
+#define     UNICHROME_K400_DID      0x7205
+
+#define     UNICHROME_K800          3
+#define     UNICHROME_K800_DID      0x3108
+
+#define     UNICHROME_PM800         4
+#define     UNICHROME_PM800_DID     0x3118
+
+#define     UNICHROME_CN700         5
+#define     UNICHROME_CN700_DID     0x3344
+
+#define     UNICHROME_CX700         6
+#define     UNICHROME_CX700_DID     0x3157
+#define     CX700_REVISION_700      0x0
+#define     CX700_REVISION_700M     0x1
+#define     CX700_REVISION_700M2    0x2
+
+#define     UNICHROME_CN750         7
+#define     UNICHROME_CN750_DID     0x3225
+
+#define     UNICHROME_K8M890        8
+#define     UNICHROME_K8M890_DID    0x3230
+
+#define     UNICHROME_P4M890        9
+#define     UNICHROME_P4M890_DID    0x3343
+
+#define     UNICHROME_P4M900        10
+#define     UNICHROME_P4M900_DID    0x3371
+
+#define     UNICHROME_VX800         11
+#define     UNICHROME_VX800_DID     0x1122
+
+#define     UNICHROME_VX855         12
+#define     UNICHROME_VX855_DID     0x5122
+
+#define     UNICHROME_VX900         13
+#define     UNICHROME_VX900_DID     0x7122
+
+/**************************************************/
+/* Definition TMDS Trasmitter Information         */
+/**************************************************/
+
+/* Definition TMDS Trasmitter Index */
+#define     NON_TMDS_TRANSMITTER    0x00
+#define     VT1632_TMDS             0x01
+#define     INTEGRATED_TMDS         0x42
+
+/* Definition TMDS Trasmitter I2C Slave Address */
+#define     VT1632_TMDS_I2C_ADDR    0x10
+
+/**************************************************/
+/* Definition LVDS Trasmitter Information         */
+/**************************************************/
+
+/* Definition LVDS Trasmitter Index */
+#define     NON_LVDS_TRANSMITTER    0x00
+#define     VT1631_LVDS             0x01
+#define     VT1636_LVDS             0x0E
+#define     INTEGRATED_LVDS         0x41
+
+/* Definition Digital Transmitter Mode */
+#define     TX_DATA_12_BITS         0x01
+#define     TX_DATA_24_BITS         0x02
+#define     TX_DATA_DDR_MODE        0x04
+#define     TX_DATA_SDR_MODE        0x08
+
+/* Definition LVDS Trasmitter I2C Slave Address */
+#define     VT1631_LVDS_I2C_ADDR    0x70
+#define     VT3271_LVDS_I2C_ADDR    0x80
+#define     VT1636_LVDS_I2C_ADDR    0x80
+
+struct tmds_chip_information {
+	int tmds_chip_name;
+	int tmds_chip_slave_addr;
+	int output_interface;
+	int i2c_port;
+};
+
+struct lvds_chip_information {
+	int lvds_chip_name;
+	int lvds_chip_slave_addr;
+	int output_interface;
+	int i2c_port;
+};
+
+/* The type of 2D engine */
+enum via_2d_engine {
+	VIA_2D_ENG_H2,
+	VIA_2D_ENG_H5,
+	VIA_2D_ENG_M1,
+};
+
+struct chip_information {
+	int gfx_chip_name;
+	int gfx_chip_revision;
+	enum via_2d_engine twod_engine;
+	struct tmds_chip_information tmds_chip_info;
+	struct lvds_chip_information lvds_chip_info;
+	struct lvds_chip_information lvds_chip_info2;
+};
+
+struct tmds_setting_information {
+	int iga_path;
+	int h_active;
+	int v_active;
+	int max_pixel_clock;
+};
+
+struct lvds_setting_information {
+	int iga_path;
+	int lcd_panel_hres;
+	int lcd_panel_vres;
+	int display_method;
+	int device_lcd_dualedge;
+	int LCDDithering;
+	int lcd_mode;
+	u32 vclk;		/*panel mode clock value */
+};
+
+struct GFX_DPA_SETTING {
+	int ClkRangeIndex;
+	u8 DVP0;		/* CR96[3:0] */
+	u8 DVP0DataDri_S1;	/* SR2A[5]   */
+	u8 DVP0DataDri_S;	/* SR1B[1]   */
+	u8 DVP0ClockDri_S1;	/* SR2A[4]   */
+	u8 DVP0ClockDri_S;	/* SR1E[2]   */
+	u8 DVP1;		/* CR9B[3:0] */
+	u8 DVP1Driving;		/* SR65[3:0], Data and Clock driving */
+	u8 DFPHigh;		/* CR97[3:0] */
+	u8 DFPLow;		/* CR99[3:0] */
+
+};
+
+struct VT1636_DPA_SETTING {
+	u8 CLK_SEL_ST1;
+	u8 CLK_SEL_ST2;
+};
+#endif /* __CHIP_H__ */
diff --git a/drivers/video/fbdev/via/debug.h b/drivers/video/fbdev/via/debug.h
new file mode 100644
index 000000000000..86eacc2017f3
--- /dev/null
+++ b/drivers/video/fbdev/via/debug.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#ifndef VIAFB_DEBUG
+#define VIAFB_DEBUG 0
+#endif
+
+#if VIAFB_DEBUG
+#define DEBUG_MSG(f, a...)   printk(f, ## a)
+#else
+#define DEBUG_MSG(f, a...)
+#endif
+
+#define VIAFB_WARN 0
+#if VIAFB_WARN
+#define WARN_MSG(f, a...)   printk(f, ## a)
+#else
+#define WARN_MSG(f, a...)
+#endif
+
+#endif /* __DEBUG_H__ */
diff --git a/drivers/video/fbdev/via/dvi.c b/drivers/video/fbdev/via/dvi.c
new file mode 100644
index 000000000000..7789553952d3
--- /dev/null
+++ b/drivers/video/fbdev/via/dvi.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/via-core.h>
+#include <linux/via_i2c.h>
+#include "global.h"
+
+static void tmds_register_write(int index, u8 data);
+static int tmds_register_read(int index);
+static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
+static void dvi_get_panel_size_from_DDCv1(
+	struct tmds_chip_information *tmds_chip,
+	struct tmds_setting_information *tmds_setting);
+static int viafb_dvi_query_EDID(void);
+
+static inline bool check_tmds_chip(int device_id_subaddr, int device_id)
+{
+	return tmds_register_read(device_id_subaddr) == device_id;
+}
+
+void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
+			 struct tmds_setting_information *tmds_setting)
+{
+	DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
+
+	viafb_dvi_sense();
+	if (viafb_dvi_query_EDID() == 1)
+		dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
+
+	return;
+}
+
+bool viafb_tmds_trasmitter_identify(void)
+{
+	unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
+
+	/* Turn on ouputting pad */
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_K8M890:
+	    /*=* DFP Low Pad on *=*/
+		sr2a = viafb_read_reg(VIASR, SR2A);
+		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+		break;
+
+	case UNICHROME_P4M900:
+	case UNICHROME_P4M890:
+		/* DFP Low Pad on */
+		sr2a = viafb_read_reg(VIASR, SR2A);
+		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+		/* DVP0 Pad on */
+		sr1e = viafb_read_reg(VIASR, SR1E);
+		viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
+		break;
+
+	default:
+	    /* DVP0/DVP1 Pad on */
+		sr1e = viafb_read_reg(VIASR, SR1E);
+		viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
+			BIT5 + BIT6 + BIT7);
+	    /* SR3E[1]Multi-function selection:
+	    0 = Emulate I2C and DDC bus by GPIO2/3/4. */
+		sr3e = viafb_read_reg(VIASR, SR3E);
+		viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
+		break;
+	}
+
+	/* Check for VT1632: */
+	viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
+	viaparinfo->chip_info->
+		tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
+	viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;
+	if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
+		/*
+		 * Currently only support 12bits,dual edge,add 24bits mode later
+		 */
+		tmds_register_write(0x08, 0x3b);
+
+		DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
+		DEBUG_MSG(KERN_INFO "\n %2d",
+			  viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
+		DEBUG_MSG(KERN_INFO "\n %2d",
+			  viaparinfo->chip_info->tmds_chip_info.i2c_port);
+		return true;
+	} else {
+		viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;
+		if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
+			tmds_register_write(0x08, 0x3b);
+			DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
+			DEBUG_MSG(KERN_INFO "\n %2d",
+				  viaparinfo->chip_info->
+				  tmds_chip_info.tmds_chip_name);
+			DEBUG_MSG(KERN_INFO "\n %2d",
+				  viaparinfo->chip_info->
+				  tmds_chip_info.i2c_port);
+			return true;
+		}
+	}
+
+	viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
+
+	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
+	    ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
+	     (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
+		DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
+		return true;
+	}
+
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_K8M890:
+		viafb_write_reg(SR2A, VIASR, sr2a);
+		break;
+
+	case UNICHROME_P4M900:
+	case UNICHROME_P4M890:
+		viafb_write_reg(SR2A, VIASR, sr2a);
+		viafb_write_reg(SR1E, VIASR, sr1e);
+		break;
+
+	default:
+		viafb_write_reg(SR1E, VIASR, sr1e);
+		viafb_write_reg(SR3E, VIASR, sr3e);
+		break;
+	}
+
+	viaparinfo->chip_info->
+		tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
+	viaparinfo->chip_info->tmds_chip_info.
+		tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
+	return false;
+}
+
+static void tmds_register_write(int index, u8 data)
+{
+	viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
+			    viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
+			    index, data);
+}
+
+static int tmds_register_read(int index)
+{
+	u8 data;
+
+	viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
+			   (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
+			   (u8) index, &data);
+	return data;
+}
+
+static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
+{
+	viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port,
+			    (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
+			    (u8) index, buff, buff_len);
+	return 0;
+}
+
+/* DVI Set Mode */
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
+	u16 cxres, u16 cyres, int iga)
+{
+	struct fb_var_screeninfo dvi_var = *var;
+	const struct fb_videomode *rb_mode;
+	int maxPixelClock;
+
+	maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
+	if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
+		rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
+		if (rb_mode)
+			viafb_fill_var_timing_info(&dvi_var, rb_mode);
+	}
+
+	viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga);
+}
+
+/* Sense DVI Connector */
+int viafb_dvi_sense(void)
+{
+	u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
+		RegCR93 = 0, RegCR9B = 0, data;
+	int ret = false;
+
+	DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
+
+	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+		/* DI1 Pad on */
+		RegSR1E = viafb_read_reg(VIASR, SR1E);
+		viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
+
+		/* CR6B[0]VCK Input Selection: 1 = External clock. */
+		RegCR6B = viafb_read_reg(VIACR, CR6B);
+		viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
+
+		/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
+		   [0] Software Control Power Sequence */
+		RegCR91 = viafb_read_reg(VIACR, CR91);
+		viafb_write_reg(CR91, VIACR, 0x1D);
+
+		/* CR93[7] DI1 Data Source Selection: 1 = DSP2.
+		   CR93[5] DI1 Clock Source: 1 = internal.
+		   CR93[4] DI1 Clock Polarity.
+		   CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
+		RegCR93 = viafb_read_reg(VIACR, CR93);
+		viafb_write_reg(CR93, VIACR, 0x01);
+	} else {
+		/* DVP0/DVP1 Pad on */
+		RegSR1E = viafb_read_reg(VIASR, SR1E);
+		viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
+
+		/* SR3E[1]Multi-function selection:
+		   0 = Emulate I2C and DDC bus by GPIO2/3/4. */
+		RegSR3E = viafb_read_reg(VIASR, SR3E);
+		viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
+
+		/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
+		   [0] Software Control Power Sequence */
+		RegCR91 = viafb_read_reg(VIACR, CR91);
+		viafb_write_reg(CR91, VIACR, 0x1D);
+
+		/*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
+		display.CR9B[2:0] DVP1 Clock Adjust */
+		RegCR9B = viafb_read_reg(VIACR, CR9B);
+		viafb_write_reg(CR9B, VIACR, 0x01);
+	}
+
+	data = (u8) tmds_register_read(0x09);
+	if (data & 0x04)
+		ret = true;
+
+	if (ret == false) {
+		if (viafb_dvi_query_EDID())
+			ret = true;
+	}
+
+	/* Restore status */
+	viafb_write_reg(SR1E, VIASR, RegSR1E);
+	viafb_write_reg(CR91, VIACR, RegCR91);
+	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+		viafb_write_reg(CR6B, VIACR, RegCR6B);
+		viafb_write_reg(CR93, VIACR, RegCR93);
+	} else {
+		viafb_write_reg(SR3E, VIASR, RegSR3E);
+		viafb_write_reg(CR9B, VIACR, RegCR9B);
+	}
+
+	return ret;
+}
+
+/* Query Flat Panel's EDID Table Version Through DVI Connector */
+static int viafb_dvi_query_EDID(void)
+{
+	u8 data0, data1;
+	int restore;
+
+	DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
+
+	restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
+	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
+
+	data0 = (u8) tmds_register_read(0x00);
+	data1 = (u8) tmds_register_read(0x01);
+	if ((data0 == 0) && (data1 == 0xFF)) {
+		viaparinfo->chip_info->
+			tmds_chip_info.tmds_chip_slave_addr = restore;
+		return EDID_VERSION_1;	/* Found EDID1 Table */
+	}
+
+	return false;
+}
+
+/* Get Panel Size Using EDID1 Table */
+static void dvi_get_panel_size_from_DDCv1(
+	struct tmds_chip_information *tmds_chip,
+	struct tmds_setting_information *tmds_setting)
+{
+	int i, restore;
+	unsigned char EDID_DATA[18];
+
+	DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
+
+	restore = tmds_chip->tmds_chip_slave_addr;
+	tmds_chip->tmds_chip_slave_addr = 0xA0;
+	for (i = 0x25; i < 0x6D; i++) {
+		switch (i) {
+		case 0x36:
+		case 0x48:
+		case 0x5A:
+		case 0x6C:
+			tmds_register_read_bytes(i, EDID_DATA, 10);
+			if (!(EDID_DATA[0] || EDID_DATA[1])) {
+				/* The first two byte must be zero. */
+				if (EDID_DATA[3] == 0xFD) {
+					/* To get max pixel clock. */
+					tmds_setting->max_pixel_clock =
+						EDID_DATA[9] * 10;
+				}
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
+		tmds_setting->max_pixel_clock);
+	tmds_chip->tmds_chip_slave_addr = restore;
+}
+
+/* If Disable DVI, turn off pad */
+void viafb_dvi_disable(void)
+{
+	if (viaparinfo->chip_info->
+		tmds_chip_info.output_interface == INTERFACE_TMDS)
+		/* Turn off TMDS power. */
+		viafb_write_reg(CRD2, VIACR,
+		viafb_read_reg(VIACR, CRD2) | 0x08);
+}
+
+static void dvi_patch_skew_dvp0(void)
+{
+	/* Reset data driving first: */
+	viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
+	viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
+
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_P4M890:
+		{
+			if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
+				(viaparinfo->tmds_setting_info->v_active ==
+				1200))
+				viafb_write_reg_mask(CR96, VIACR, 0x03,
+					       BIT0 + BIT1 + BIT2);
+			else
+				viafb_write_reg_mask(CR96, VIACR, 0x07,
+					       BIT0 + BIT1 + BIT2);
+			break;
+		}
+
+	case UNICHROME_P4M900:
+		{
+			viafb_write_reg_mask(CR96, VIACR, 0x07,
+				       BIT0 + BIT1 + BIT2 + BIT3);
+			viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
+			viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
+			break;
+		}
+
+	default:
+		{
+			break;
+		}
+	}
+}
+
+static void dvi_patch_skew_dvp_low(void)
+{
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_K8M890:
+		{
+			viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
+			break;
+		}
+
+	case UNICHROME_P4M900:
+		{
+			viafb_write_reg_mask(CR99, VIACR, 0x08,
+				       BIT0 + BIT1 + BIT2 + BIT3);
+			break;
+		}
+
+	case UNICHROME_P4M890:
+		{
+			viafb_write_reg_mask(CR99, VIACR, 0x0F,
+				       BIT0 + BIT1 + BIT2 + BIT3);
+			break;
+		}
+
+	default:
+		{
+			break;
+		}
+	}
+}
+
+/* If Enable DVI, turn off pad */
+void viafb_dvi_enable(void)
+{
+	u8 data;
+
+	switch (viaparinfo->chip_info->tmds_chip_info.output_interface) {
+	case INTERFACE_DVP0:
+		viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
+		viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
+		dvi_patch_skew_dvp0();
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+			tmds_register_write(0x88, 0x3b);
+		else
+			/*clear CR91[5] to direct on display period
+			   in the secondary diplay path */
+			via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
+		break;
+
+	case INTERFACE_DVP1:
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+			viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
+
+		/*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+			tmds_register_write(0x88, 0x3b);
+		else
+			/*clear CR91[5] to direct on display period
+			  in the secondary diplay path */
+			via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
+
+		/*fix DVI cannot enable on EPIA-M board */
+		if (viafb_platform_epia_dvi == 1) {
+			viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
+			viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
+			if (viafb_bus_width == 24) {
+				if (viafb_device_lcd_dualedge == 1)
+					data = 0x3F;
+				else
+					data = 0x37;
+				viafb_i2c_writebyte(viaparinfo->chip_info->
+					tmds_chip_info.i2c_port,
+					viaparinfo->chip_info->
+					tmds_chip_info.tmds_chip_slave_addr,
+					0x08, data);
+			}
+		}
+		break;
+
+	case INTERFACE_DFP_HIGH:
+		if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+			via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
+
+		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
+		break;
+
+	case INTERFACE_DFP_LOW:
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+			break;
+
+		dvi_patch_skew_dvp_low();
+		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
+		break;
+
+	case INTERFACE_TMDS:
+		/* Turn on Display period in the panel path. */
+		viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
+
+		/* Turn on TMDS power. */
+		viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
+		break;
+	}
+
+	if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
+		/* Disable LCD Scaling */
+		viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
+	}
+}
diff --git a/drivers/video/fbdev/via/dvi.h b/drivers/video/fbdev/via/dvi.h
new file mode 100644
index 000000000000..4c6bfba57d11
--- /dev/null
+++ b/drivers/video/fbdev/via/dvi.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __DVI_H__
+#define __DVI_H__
+
+/*Definition TMDS Device ID register*/
+#define     VT1632_DEVICE_ID_REG        0x02
+#define     VT1632_DEVICE_ID            0x92
+
+#define     GET_DVI_SIZE_BY_SYSTEM_BIOS     0x01
+#define     GET_DVI_SIZE_BY_VGA_BIOS        0x02
+#define     GET_DVI_SZIE_BY_HW_STRAPPING    0x03
+
+/* Definition DVI Panel ID*/
+/* Resolution: 640x480,   Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID0_640X480       0x00
+/* Resolution: 800x600,   Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID1_800x600       0x01
+/* Resolution: 1024x768,  Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID1_1024x768      0x02
+/* Resolution: 1280x768,  Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID1_1280x768      0x03
+/* Resolution: 1280x1024, Channel: dual,   Dithering: Enable */
+#define     DVI_PANEL_ID1_1280x1024     0x04
+/* Resolution: 1400x1050, Channel: dual,   Dithering: Enable */
+#define     DVI_PANEL_ID1_1400x1050     0x05
+/* Resolution: 1600x1200, Channel: dual,   Dithering: Enable */
+#define     DVI_PANEL_ID1_1600x1200     0x06
+
+/* Define the version of EDID*/
+#define     EDID_VERSION_1      1
+#define     EDID_VERSION_2      2
+
+#define     DEV_CONNECT_DVI     0x01
+#define     DEV_CONNECT_HDMI    0x02
+
+int viafb_dvi_sense(void);
+void viafb_dvi_disable(void);
+void viafb_dvi_enable(void);
+bool viafb_tmds_trasmitter_identify(void);
+void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
+	struct tmds_setting_information *tmds_setting);
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
+	u16 cxres, u16 cyres, int iga);
+
+#endif /* __DVI_H__ */
diff --git a/drivers/video/fbdev/via/global.c b/drivers/video/fbdev/via/global.c
new file mode 100644
index 000000000000..3102171c1674
--- /dev/null
+++ b/drivers/video/fbdev/via/global.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "global.h"
+int viafb_platform_epia_dvi = STATE_OFF;
+int viafb_device_lcd_dualedge = STATE_OFF;
+int viafb_bus_width = 12;
+int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
+int viafb_DeviceStatus = CRT_Device;
+int viafb_hotplug;
+int viafb_refresh = 60;
+int viafb_refresh1 = 60;
+int viafb_lcd_dsp_method = LCD_EXPANDSION;
+int viafb_lcd_mode = LCD_OPENLDI;
+int viafb_CRT_ON = 1;
+int viafb_DVI_ON;
+int viafb_LCD_ON ;
+int viafb_LCD2_ON;
+int viafb_SAMM_ON;
+int viafb_dual_fb;
+unsigned int viafb_second_xres = 640;
+unsigned int viafb_second_yres = 480;
+int viafb_hotplug_Xres = 640;
+int viafb_hotplug_Yres = 480;
+int viafb_hotplug_bpp = 32;
+int viafb_hotplug_refresh = 60;
+int viafb_primary_dev = None_Device;
+int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
+struct fb_info *viafbinfo;
+struct fb_info *viafbinfo1;
+struct viafb_par *viaparinfo;
+struct viafb_par *viaparinfo1;
+
diff --git a/drivers/video/fbdev/via/global.h b/drivers/video/fbdev/via/global.h
new file mode 100644
index 000000000000..275dbbbd6b81
--- /dev/null
+++ b/drivers/video/fbdev/via/global.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GLOBAL_H__
+#define __GLOBAL_H__
+
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/console.h>
+#include <linux/timer.h>
+
+#include "debug.h"
+
+#include "viafbdev.h"
+#include "chip.h"
+#include "accel.h"
+#include "share.h"
+#include "dvi.h"
+#include "viamode.h"
+#include "hw.h"
+
+#include "lcd.h"
+#include "ioctl.h"
+#include "via_utility.h"
+#include "vt1636.h"
+#include "tblDPASetting.h"
+
+/* External struct*/
+
+extern int viafb_platform_epia_dvi;
+extern int viafb_device_lcd_dualedge;
+extern int viafb_bus_width;
+extern int viafb_display_hardware_layout;
+extern struct offset offset_reg;
+extern struct viafb_par *viaparinfo;
+extern struct viafb_par *viaparinfo1;
+extern struct fb_info *viafbinfo;
+extern struct fb_info *viafbinfo1;
+extern int viafb_DeviceStatus;
+extern int viafb_refresh;
+extern int viafb_refresh1;
+extern int viafb_lcd_dsp_method;
+extern int viafb_lcd_mode;
+
+extern int viafb_CRT_ON;
+extern unsigned int viafb_second_xres;
+extern unsigned int viafb_second_yres;
+extern int viafb_hotplug_Xres;
+extern int viafb_hotplug_Yres;
+extern int viafb_hotplug_bpp;
+extern int viafb_hotplug_refresh;
+extern int viafb_primary_dev;
+
+extern int viafb_lcd_panel_id;
+
+#endif /* __GLOBAL_H__ */
diff --git a/drivers/video/fbdev/via/hw.c b/drivers/video/fbdev/via/hw.c
new file mode 100644
index 000000000000..22450908306c
--- /dev/null
+++ b/drivers/video/fbdev/via/hw.c
@@ -0,0 +1,2134 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/via-core.h>
+#include <asm/olpc.h>
+#include "global.h"
+#include "via_clock.h"
+
+static struct pll_limit cle266_pll_limits[] = {
+	{19, 19, 4, 0},
+	{26, 102, 5, 0},
+	{53, 112, 6, 0},
+	{41, 100, 7, 0},
+	{83, 108, 8, 0},
+	{87, 118, 9, 0},
+	{95, 115, 12, 0},
+	{108, 108, 13, 0},
+	{83, 83, 17, 0},
+	{67, 98, 20, 0},
+	{121, 121, 24, 0},
+	{99, 99, 29, 0},
+	{33, 33, 3, 1},
+	{15, 23, 4, 1},
+	{37, 121, 5, 1},
+	{82, 82, 6, 1},
+	{31, 84, 7, 1},
+	{83, 83, 8, 1},
+	{76, 127, 9, 1},
+	{33, 121, 4, 2},
+	{91, 118, 5, 2},
+	{83, 109, 6, 2},
+	{90, 90, 7, 2},
+	{93, 93, 2, 3},
+	{53, 53, 3, 3},
+	{73, 117, 4, 3},
+	{101, 127, 5, 3},
+	{99, 99, 7, 3}
+};
+
+static struct pll_limit k800_pll_limits[] = {
+	{22, 22, 2, 0},
+	{28, 28, 3, 0},
+	{81, 112, 3, 1},
+	{86, 166, 4, 1},
+	{109, 153, 5, 1},
+	{66, 116, 3, 2},
+	{93, 137, 4, 2},
+	{117, 208, 5, 2},
+	{30, 30, 2, 3},
+	{69, 125, 3, 3},
+	{89, 161, 4, 3},
+	{121, 208, 5, 3},
+	{66, 66, 2, 4},
+	{85, 85, 3, 4},
+	{141, 161, 4, 4},
+	{177, 177, 5, 4}
+};
+
+static struct pll_limit cx700_pll_limits[] = {
+	{98, 98, 3, 1},
+	{86, 86, 4, 1},
+	{109, 208, 5, 1},
+	{68, 68, 2, 2},
+	{95, 116, 3, 2},
+	{93, 166, 4, 2},
+	{110, 206, 5, 2},
+	{174, 174, 7, 2},
+	{82, 109, 3, 3},
+	{117, 161, 4, 3},
+	{112, 208, 5, 3},
+	{141, 202, 5, 4}
+};
+
+static struct pll_limit vx855_pll_limits[] = {
+	{86, 86, 4, 1},
+	{108, 208, 5, 1},
+	{110, 208, 5, 2},
+	{83, 112, 3, 3},
+	{103, 161, 4, 3},
+	{112, 209, 5, 3},
+	{142, 161, 4, 4},
+	{141, 176, 5, 4}
+};
+
+/* according to VIA Technologies these values are based on experiment */
+static struct io_reg scaling_parameters[] = {
+	{VIACR, CR7A, 0xFF, 0x01},	/* LCD Scaling Parameter 1 */
+	{VIACR, CR7B, 0xFF, 0x02},	/* LCD Scaling Parameter 2 */
+	{VIACR, CR7C, 0xFF, 0x03},	/* LCD Scaling Parameter 3 */
+	{VIACR, CR7D, 0xFF, 0x04},	/* LCD Scaling Parameter 4 */
+	{VIACR, CR7E, 0xFF, 0x07},	/* LCD Scaling Parameter 5 */
+	{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Scaling Parameter 6 */
+	{VIACR, CR80, 0xFF, 0x0D},	/* LCD Scaling Parameter 7 */
+	{VIACR, CR81, 0xFF, 0x13},	/* LCD Scaling Parameter 8 */
+	{VIACR, CR82, 0xFF, 0x16},	/* LCD Scaling Parameter 9 */
+	{VIACR, CR83, 0xFF, 0x19},	/* LCD Scaling Parameter 10 */
+	{VIACR, CR84, 0xFF, 0x1C},	/* LCD Scaling Parameter 11 */
+	{VIACR, CR85, 0xFF, 0x1D},	/* LCD Scaling Parameter 12 */
+	{VIACR, CR86, 0xFF, 0x1E},	/* LCD Scaling Parameter 13 */
+	{VIACR, CR87, 0xFF, 0x1F},	/* LCD Scaling Parameter 14 */
+};
+
+static struct io_reg common_vga[] = {
+	{VIACR, CR07, 0x10, 0x10}, /* [0] vertical total (bit 8)
+					[1] vertical display end (bit 8)
+					[2] vertical retrace start (bit 8)
+					[3] start vertical blanking (bit 8)
+					[4] line compare (bit 8)
+					[5] vertical total (bit 9)
+					[6] vertical display end (bit 9)
+					[7] vertical retrace start (bit 9) */
+	{VIACR, CR08, 0xFF, 0x00}, /* [0-4] preset row scan
+					[5-6] byte panning */
+	{VIACR, CR09, 0xDF, 0x40}, /* [0-4] max scan line
+					[5] start vertical blanking (bit 9)
+					[6] line compare (bit 9)
+					[7] scan doubling */
+	{VIACR, CR0A, 0xFF, 0x1E}, /* [0-4] cursor start
+					[5] cursor disable */
+	{VIACR, CR0B, 0xFF, 0x00}, /* [0-4] cursor end
+					[5-6] cursor skew */
+	{VIACR, CR0E, 0xFF, 0x00}, /* [0-7] cursor location (high) */
+	{VIACR, CR0F, 0xFF, 0x00}, /* [0-7] cursor location (low) */
+	{VIACR, CR11, 0xF0, 0x80}, /* [0-3] vertical retrace end
+					[6] memory refresh bandwidth
+					[7] CRTC register protect enable */
+	{VIACR, CR14, 0xFF, 0x00}, /* [0-4] underline location
+					[5] divide memory address clock by 4
+					[6] double word addressing */
+	{VIACR, CR17, 0xFF, 0x63}, /* [0-1] mapping of display address 13-14
+					[2] divide scan line clock by 2
+					[3] divide memory address clock by 2
+					[5] address wrap
+					[6] byte mode select
+					[7] sync enable */
+	{VIACR, CR18, 0xFF, 0xFF}, /* [0-7] line compare */
+};
+
+static struct fifo_depth_select display_fifo_depth_reg = {
+	/* IGA1 FIFO Depth_Select */
+	{IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
+	/* IGA2 FIFO Depth_Select */
+	{IGA2_FIFO_DEPTH_SELECT_REG_NUM,
+	 {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
+};
+
+static struct fifo_threshold_select fifo_threshold_select_reg = {
+	/* IGA1 FIFO Threshold Select */
+	{IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
+	/* IGA2 FIFO Threshold Select */
+	{IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
+};
+
+static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
+	/* IGA1 FIFO High Threshold Select */
+	{IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
+	/* IGA2 FIFO High Threshold Select */
+	{IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
+};
+
+static struct display_queue_expire_num display_queue_expire_num_reg = {
+	/* IGA1 Display Queue Expire Num */
+	{IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
+	/* IGA2 Display Queue Expire Num */
+	{IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
+};
+
+/* Definition Fetch Count Registers*/
+static struct fetch_count fetch_count_reg = {
+	/* IGA1 Fetch Count Register */
+	{IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
+	/* IGA2 Fetch Count Register */
+	{IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
+};
+
+static struct rgbLUT palLUT_table[] = {
+	/* {R,G,B} */
+	/* Index 0x00~0x03 */
+	{0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
+								     0x2A,
+								     0x2A},
+	/* Index 0x04~0x07 */
+	{0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
+								     0x2A,
+								     0x2A},
+	/* Index 0x08~0x0B */
+	{0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
+								     0x3F,
+								     0x3F},
+	/* Index 0x0C~0x0F */
+	{0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
+								     0x3F,
+								     0x3F},
+	/* Index 0x10~0x13 */
+	{0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
+								     0x0B,
+								     0x0B},
+	/* Index 0x14~0x17 */
+	{0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
+								     0x18,
+								     0x18},
+	/* Index 0x18~0x1B */
+	{0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
+								     0x28,
+								     0x28},
+	/* Index 0x1C~0x1F */
+	{0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
+								     0x3F,
+								     0x3F},
+	/* Index 0x20~0x23 */
+	{0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
+								     0x00,
+								     0x3F},
+	/* Index 0x24~0x27 */
+	{0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
+								     0x00,
+								     0x10},
+	/* Index 0x28~0x2B */
+	{0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
+								     0x2F,
+								     0x00},
+	/* Index 0x2C~0x2F */
+	{0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
+								     0x3F,
+								     0x00},
+	/* Index 0x30~0x33 */
+	{0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
+								     0x3F,
+								     0x2F},
+	/* Index 0x34~0x37 */
+	{0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
+								     0x10,
+								     0x3F},
+	/* Index 0x38~0x3B */
+	{0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
+								     0x1F,
+								     0x3F},
+	/* Index 0x3C~0x3F */
+	{0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
+								     0x1F,
+								     0x27},
+	/* Index 0x40~0x43 */
+	{0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
+								     0x3F,
+								     0x1F},
+	/* Index 0x44~0x47 */
+	{0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
+								     0x3F,
+								     0x1F},
+	/* Index 0x48~0x4B */
+	{0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
+								     0x3F,
+								     0x37},
+	/* Index 0x4C~0x4F */
+	{0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
+								     0x27,
+								     0x3F},
+	/* Index 0x50~0x53 */
+	{0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
+								     0x2D,
+								     0x3F},
+	/* Index 0x54~0x57 */
+	{0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
+								     0x2D,
+								     0x31},
+	/* Index 0x58~0x5B */
+	{0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
+								     0x3A,
+								     0x2D},
+	/* Index 0x5C~0x5F */
+	{0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
+								     0x3F,
+								     0x2D},
+	/* Index 0x60~0x63 */
+	{0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
+								     0x3F,
+								     0x3A},
+	/* Index 0x64~0x67 */
+	{0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
+								     0x31,
+								     0x3F},
+	/* Index 0x68~0x6B */
+	{0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
+								     0x00,
+								     0x1C},
+	/* Index 0x6C~0x6F */
+	{0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
+								     0x00,
+								     0x07},
+	/* Index 0x70~0x73 */
+	{0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
+								     0x15,
+								     0x00},
+	/* Index 0x74~0x77 */
+	{0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
+								     0x1C,
+								     0x00},
+	/* Index 0x78~0x7B */
+	{0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
+								     0x1C,
+								     0x15},
+	/* Index 0x7C~0x7F */
+	{0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
+								     0x07,
+								     0x1C},
+	/* Index 0x80~0x83 */
+	{0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
+								     0x0E,
+								     0x1C},
+	/* Index 0x84~0x87 */
+	{0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
+								     0x0E,
+								     0x11},
+	/* Index 0x88~0x8B */
+	{0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
+								     0x18,
+								     0x0E},
+	/* Index 0x8C~0x8F */
+	{0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
+								     0x1C,
+								     0x0E},
+	/* Index 0x90~0x93 */
+	{0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
+								     0x1C,
+								     0x18},
+	/* Index 0x94~0x97 */
+	{0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
+								     0x11,
+								     0x1C},
+	/* Index 0x98~0x9B */
+	{0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
+								     0x14,
+								     0x1C},
+	/* Index 0x9C~0x9F */
+	{0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
+								     0x14,
+								     0x16},
+	/* Index 0xA0~0xA3 */
+	{0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
+								     0x1A,
+								     0x14},
+	/* Index 0xA4~0xA7 */
+	{0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
+								     0x1C,
+								     0x14},
+	/* Index 0xA8~0xAB */
+	{0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
+								     0x1C,
+								     0x1A},
+	/* Index 0xAC~0xAF */
+	{0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
+								     0x16,
+								     0x1C},
+	/* Index 0xB0~0xB3 */
+	{0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
+								     0x00,
+								     0x10},
+	/* Index 0xB4~0xB7 */
+	{0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
+								     0x00,
+								     0x04},
+	/* Index 0xB8~0xBB */
+	{0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
+								     0x0C,
+								     0x00},
+	/* Index 0xBC~0xBF */
+	{0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
+								     0x10,
+								     0x00},
+	/* Index 0xC0~0xC3 */
+	{0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
+								     0x10,
+								     0x0C},
+	/* Index 0xC4~0xC7 */
+	{0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
+								     0x04,
+								     0x10},
+	/* Index 0xC8~0xCB */
+	{0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
+								     0x08,
+								     0x10},
+	/* Index 0xCC~0xCF */
+	{0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
+								     0x08,
+								     0x0A},
+	/* Index 0xD0~0xD3 */
+	{0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
+								     0x0E,
+								     0x08},
+	/* Index 0xD4~0xD7 */
+	{0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
+								     0x10,
+								     0x08},
+	/* Index 0xD8~0xDB */
+	{0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
+								     0x10,
+								     0x0E},
+	/* Index 0xDC~0xDF */
+	{0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
+								     0x0A,
+								     0x10},
+	/* Index 0xE0~0xE3 */
+	{0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
+								     0x0B,
+								     0x10},
+	/* Index 0xE4~0xE7 */
+	{0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
+								     0x0B,
+								     0x0C},
+	/* Index 0xE8~0xEB */
+	{0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
+								     0x0F,
+								     0x0B},
+	/* Index 0xEC~0xEF */
+	{0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
+								     0x10,
+								     0x0B},
+	/* Index 0xF0~0xF3 */
+	{0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
+								     0x10,
+								     0x0F},
+	/* Index 0xF4~0xF7 */
+	{0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
+								     0x0C,
+								     0x10},
+	/* Index 0xF8~0xFB */
+	{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
+								     0x00,
+								     0x00},
+	/* Index 0xFC~0xFF */
+	{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
+								     0x00,
+								     0x00}
+};
+
+static struct via_device_mapping device_mapping[] = {
+	{VIA_LDVP0, "LDVP0"},
+	{VIA_LDVP1, "LDVP1"},
+	{VIA_DVP0, "DVP0"},
+	{VIA_CRT, "CRT"},
+	{VIA_DVP1, "DVP1"},
+	{VIA_LVDS1, "LVDS1"},
+	{VIA_LVDS2, "LVDS2"}
+};
+
+/* structure with function pointers to support clock control */
+static struct via_clock clock;
+
+static void load_fix_bit_crtc_reg(void);
+static void init_gfx_chip_info(int chip_type);
+static void init_tmds_chip_info(void);
+static void init_lvds_chip_info(void);
+static void device_screen_off(void);
+static void device_screen_on(void);
+static void set_display_channel(void);
+static void device_off(void);
+static void device_on(void);
+static void enable_second_display_channel(void);
+static void disable_second_display_channel(void);
+
+void viafb_lock_crt(void)
+{
+	viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
+}
+
+void viafb_unlock_crt(void)
+{
+	viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
+	viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
+}
+
+static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
+{
+	outb(index, LUT_INDEX_WRITE);
+	outb(r, LUT_DATA);
+	outb(g, LUT_DATA);
+	outb(b, LUT_DATA);
+}
+
+static u32 get_dvi_devices(int output_interface)
+{
+	switch (output_interface) {
+	case INTERFACE_DVP0:
+		return VIA_DVP0 | VIA_LDVP0;
+
+	case INTERFACE_DVP1:
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+			return VIA_LDVP1;
+		else
+			return VIA_DVP1;
+
+	case INTERFACE_DFP_HIGH:
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+			return 0;
+		else
+			return VIA_LVDS2 | VIA_DVP0;
+
+	case INTERFACE_DFP_LOW:
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+			return 0;
+		else
+			return VIA_DVP1 | VIA_LVDS1;
+
+	case INTERFACE_TMDS:
+		return VIA_LVDS1;
+	}
+
+	return 0;
+}
+
+static u32 get_lcd_devices(int output_interface)
+{
+	switch (output_interface) {
+	case INTERFACE_DVP0:
+		return VIA_DVP0;
+
+	case INTERFACE_DVP1:
+		return VIA_DVP1;
+
+	case INTERFACE_DFP_HIGH:
+		return VIA_LVDS2 | VIA_DVP0;
+
+	case INTERFACE_DFP_LOW:
+		return VIA_LVDS1 | VIA_DVP1;
+
+	case INTERFACE_DFP:
+		return VIA_LVDS1 | VIA_LVDS2;
+
+	case INTERFACE_LVDS0:
+	case INTERFACE_LVDS0LVDS1:
+		return VIA_LVDS1;
+
+	case INTERFACE_LVDS1:
+		return VIA_LVDS2;
+	}
+
+	return 0;
+}
+
+/*Set IGA path for each device*/
+void viafb_set_iga_path(void)
+{
+	int crt_iga_path = 0;
+
+	if (viafb_SAMM_ON == 1) {
+		if (viafb_CRT_ON) {
+			if (viafb_primary_dev == CRT_Device)
+				crt_iga_path = IGA1;
+			else
+				crt_iga_path = IGA2;
+		}
+
+		if (viafb_DVI_ON) {
+			if (viafb_primary_dev == DVI_Device)
+				viaparinfo->tmds_setting_info->iga_path = IGA1;
+			else
+				viaparinfo->tmds_setting_info->iga_path = IGA2;
+		}
+
+		if (viafb_LCD_ON) {
+			if (viafb_primary_dev == LCD_Device) {
+				if (viafb_dual_fb &&
+					(viaparinfo->chip_info->gfx_chip_name ==
+					UNICHROME_CLE266)) {
+					viaparinfo->
+					lvds_setting_info->iga_path = IGA2;
+					crt_iga_path = IGA1;
+					viaparinfo->
+					tmds_setting_info->iga_path = IGA1;
+				} else
+					viaparinfo->
+					lvds_setting_info->iga_path = IGA1;
+			} else {
+				viaparinfo->lvds_setting_info->iga_path = IGA2;
+			}
+		}
+		if (viafb_LCD2_ON) {
+			if (LCD2_Device == viafb_primary_dev)
+				viaparinfo->lvds_setting_info2->iga_path = IGA1;
+			else
+				viaparinfo->lvds_setting_info2->iga_path = IGA2;
+		}
+	} else {
+		viafb_SAMM_ON = 0;
+
+		if (viafb_CRT_ON && viafb_LCD_ON) {
+			crt_iga_path = IGA1;
+			viaparinfo->lvds_setting_info->iga_path = IGA2;
+		} else if (viafb_CRT_ON && viafb_DVI_ON) {
+			crt_iga_path = IGA1;
+			viaparinfo->tmds_setting_info->iga_path = IGA2;
+		} else if (viafb_LCD_ON && viafb_DVI_ON) {
+			viaparinfo->tmds_setting_info->iga_path = IGA1;
+			viaparinfo->lvds_setting_info->iga_path = IGA2;
+		} else if (viafb_LCD_ON && viafb_LCD2_ON) {
+			viaparinfo->lvds_setting_info->iga_path = IGA2;
+			viaparinfo->lvds_setting_info2->iga_path = IGA2;
+		} else if (viafb_CRT_ON) {
+			crt_iga_path = IGA1;
+		} else if (viafb_LCD_ON) {
+			viaparinfo->lvds_setting_info->iga_path = IGA2;
+		} else if (viafb_DVI_ON) {
+			viaparinfo->tmds_setting_info->iga_path = IGA1;
+		}
+	}
+
+	viaparinfo->shared->iga1_devices = 0;
+	viaparinfo->shared->iga2_devices = 0;
+	if (viafb_CRT_ON) {
+		if (crt_iga_path == IGA1)
+			viaparinfo->shared->iga1_devices |= VIA_CRT;
+		else
+			viaparinfo->shared->iga2_devices |= VIA_CRT;
+	}
+
+	if (viafb_DVI_ON) {
+		if (viaparinfo->tmds_setting_info->iga_path == IGA1)
+			viaparinfo->shared->iga1_devices |= get_dvi_devices(
+				viaparinfo->chip_info->
+				tmds_chip_info.output_interface);
+		else
+			viaparinfo->shared->iga2_devices |= get_dvi_devices(
+				viaparinfo->chip_info->
+				tmds_chip_info.output_interface);
+	}
+
+	if (viafb_LCD_ON) {
+		if (viaparinfo->lvds_setting_info->iga_path == IGA1)
+			viaparinfo->shared->iga1_devices |= get_lcd_devices(
+				viaparinfo->chip_info->
+				lvds_chip_info.output_interface);
+		else
+			viaparinfo->shared->iga2_devices |= get_lcd_devices(
+				viaparinfo->chip_info->
+				lvds_chip_info.output_interface);
+	}
+
+	if (viafb_LCD2_ON) {
+		if (viaparinfo->lvds_setting_info2->iga_path == IGA1)
+			viaparinfo->shared->iga1_devices |= get_lcd_devices(
+				viaparinfo->chip_info->
+				lvds_chip_info2.output_interface);
+		else
+			viaparinfo->shared->iga2_devices |= get_lcd_devices(
+				viaparinfo->chip_info->
+				lvds_chip_info2.output_interface);
+	}
+
+	/* looks like the OLPC has its display wired to DVP1 and LVDS2 */
+	if (machine_is_olpc())
+		viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2;
+}
+
+static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+	outb(0xFF, 0x3C6); /* bit mask of palette */
+	outb(index, 0x3C8);
+	outb(red, 0x3C9);
+	outb(green, 0x3C9);
+	outb(blue, 0x3C9);
+}
+
+void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+	viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
+	set_color_register(index, red, green, blue);
+}
+
+void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+	viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
+	set_color_register(index, red, green, blue);
+}
+
+static void set_source_common(u8 index, u8 offset, u8 iga)
+{
+	u8 value, mask = 1 << offset;
+
+	switch (iga) {
+	case IGA1:
+		value = 0x00;
+		break;
+	case IGA2:
+		value = mask;
+		break;
+	default:
+		printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
+		return;
+	}
+
+	via_write_reg_mask(VIACR, index, value, mask);
+}
+
+static void set_crt_source(u8 iga)
+{
+	u8 value;
+
+	switch (iga) {
+	case IGA1:
+		value = 0x00;
+		break;
+	case IGA2:
+		value = 0x40;
+		break;
+	default:
+		printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x16, value, 0x40);
+}
+
+static inline void set_ldvp0_source(u8 iga)
+{
+	set_source_common(0x6C, 7, iga);
+}
+
+static inline void set_ldvp1_source(u8 iga)
+{
+	set_source_common(0x93, 7, iga);
+}
+
+static inline void set_dvp0_source(u8 iga)
+{
+	set_source_common(0x96, 4, iga);
+}
+
+static inline void set_dvp1_source(u8 iga)
+{
+	set_source_common(0x9B, 4, iga);
+}
+
+static inline void set_lvds1_source(u8 iga)
+{
+	set_source_common(0x99, 4, iga);
+}
+
+static inline void set_lvds2_source(u8 iga)
+{
+	set_source_common(0x97, 4, iga);
+}
+
+void via_set_source(u32 devices, u8 iga)
+{
+	if (devices & VIA_LDVP0)
+		set_ldvp0_source(iga);
+	if (devices & VIA_LDVP1)
+		set_ldvp1_source(iga);
+	if (devices & VIA_DVP0)
+		set_dvp0_source(iga);
+	if (devices & VIA_CRT)
+		set_crt_source(iga);
+	if (devices & VIA_DVP1)
+		set_dvp1_source(iga);
+	if (devices & VIA_LVDS1)
+		set_lvds1_source(iga);
+	if (devices & VIA_LVDS2)
+		set_lvds2_source(iga);
+}
+
+static void set_crt_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x00;
+		break;
+	case VIA_STATE_STANDBY:
+		value = 0x10;
+		break;
+	case VIA_STATE_SUSPEND:
+		value = 0x20;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x30;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIACR, 0x36, value, 0x30);
+}
+
+static void set_dvp0_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0xC0;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
+}
+
+static void set_dvp1_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x30;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1E, value, 0x30);
+}
+
+static void set_lvds1_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x03;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2A, value, 0x03);
+}
+
+static void set_lvds2_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x0C;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
+}
+
+void via_set_state(u32 devices, u8 state)
+{
+	/*
+	TODO: Can we enable/disable these devices? How?
+	if (devices & VIA_LDVP0)
+	if (devices & VIA_LDVP1)
+	*/
+	if (devices & VIA_DVP0)
+		set_dvp0_state(state);
+	if (devices & VIA_CRT)
+		set_crt_state(state);
+	if (devices & VIA_DVP1)
+		set_dvp1_state(state);
+	if (devices & VIA_LVDS1)
+		set_lvds1_state(state);
+	if (devices & VIA_LVDS2)
+		set_lvds2_state(state);
+}
+
+void via_set_sync_polarity(u32 devices, u8 polarity)
+{
+	if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
+		printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
+			polarity);
+		return;
+	}
+
+	if (devices & VIA_CRT)
+		via_write_misc_reg_mask(polarity << 6, 0xC0);
+	if (devices & VIA_DVP1)
+		via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
+	if (devices & VIA_LVDS1)
+		via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
+	if (devices & VIA_LVDS2)
+		via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
+}
+
+u32 via_parse_odev(char *input, char **end)
+{
+	char *ptr = input;
+	u32 odev = 0;
+	bool next = true;
+	int i, len;
+
+	while (next) {
+		next = false;
+		for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+			len = strlen(device_mapping[i].name);
+			if (!strncmp(ptr, device_mapping[i].name, len)) {
+				odev |= device_mapping[i].device;
+				ptr += len;
+				if (*ptr == ',') {
+					ptr++;
+					next = true;
+				}
+			}
+		}
+	}
+
+	*end = ptr;
+	return odev;
+}
+
+void via_odev_to_seq(struct seq_file *m, u32 odev)
+{
+	int i, count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
+		if (odev & device_mapping[i].device) {
+			if (count > 0)
+				seq_putc(m, ',');
+
+			seq_puts(m, device_mapping[i].name);
+			count++;
+		}
+	}
+
+	seq_putc(m, '\n');
+}
+
+static void load_fix_bit_crtc_reg(void)
+{
+	viafb_unlock_crt();
+
+	/* always set to 1 */
+	viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
+	/* line compare should set all bits = 1 (extend modes) */
+	viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
+	/* line compare should set all bits = 1 (extend modes) */
+	viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
+	/*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
+
+	viafb_lock_crt();
+
+	/* If K8M800, enable Prefetch Mode. */
+	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
+		|| (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
+		viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
+	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+	    && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
+		viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
+
+}
+
+void viafb_load_reg(int timing_value, int viafb_load_reg_num,
+	struct io_register *reg,
+	      int io_type)
+{
+	int reg_mask;
+	int bit_num = 0;
+	int data;
+	int i, j;
+	int shift_next_reg;
+	int start_index, end_index, cr_index;
+	u16 get_bit;
+
+	for (i = 0; i < viafb_load_reg_num; i++) {
+		reg_mask = 0;
+		data = 0;
+		start_index = reg[i].start_bit;
+		end_index = reg[i].end_bit;
+		cr_index = reg[i].io_addr;
+
+		shift_next_reg = bit_num;
+		for (j = start_index; j <= end_index; j++) {
+			/*if (bit_num==8) timing_value = timing_value >>8; */
+			reg_mask = reg_mask | (BIT0 << j);
+			get_bit = (timing_value & (BIT0 << bit_num));
+			data =
+			    data | ((get_bit >> shift_next_reg) << start_index);
+			bit_num++;
+		}
+		if (io_type == VIACR)
+			viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
+		else
+			viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
+	}
+
+}
+
+/* Write Registers */
+void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
+{
+	int i;
+
+	/*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
+
+	for (i = 0; i < ItemNum; i++)
+		via_write_reg_mask(RegTable[i].port, RegTable[i].index,
+			RegTable[i].value, RegTable[i].mask);
+}
+
+void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
+{
+	int reg_value;
+	int viafb_load_reg_num;
+	struct io_register *reg = NULL;
+
+	switch (set_iga) {
+	case IGA1:
+		reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+		viafb_load_reg_num = fetch_count_reg.
+			iga1_fetch_count_reg.reg_num;
+		reg = fetch_count_reg.iga1_fetch_count_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+		break;
+	case IGA2:
+		reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+		viafb_load_reg_num = fetch_count_reg.
+			iga2_fetch_count_reg.reg_num;
+		reg = fetch_count_reg.iga2_fetch_count_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+		break;
+	}
+
+}
+
+void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
+{
+	int reg_value;
+	int viafb_load_reg_num;
+	struct io_register *reg = NULL;
+	int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
+	    0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
+	int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
+	    0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
+
+	if (set_iga == IGA1) {
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+			iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    K800_IGA1_FIFO_HIGH_THRESHOLD;
+			/* If resolution > 1280x1024, expire length = 64, else
+			   expire length = 128 */
+			if ((hor_active > 1280) && (ver_active > 1024))
+				iga1_display_queue_expire_num = 16;
+			else
+				iga1_display_queue_expire_num =
+				    K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
+			iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    P880_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+			/* If resolution > 1280x1024, expire length = 64, else
+			   expire length = 128 */
+			if ((hor_active > 1280) && (ver_active > 1024))
+				iga1_display_queue_expire_num = 16;
+			else
+				iga1_display_queue_expire_num =
+				    P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
+			iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    CN700_IGA1_FIFO_HIGH_THRESHOLD;
+
+			/* If resolution > 1280x1024, expire length = 64,
+			   else expire length = 128 */
+			if ((hor_active > 1280) && (ver_active > 1024))
+				iga1_display_queue_expire_num = 16;
+			else
+				iga1_display_queue_expire_num =
+				    CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+			iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    CX700_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
+			iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    K8M890_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
+			iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    P4M890_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
+			iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    P4M900_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
+			iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    VX800_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
+			iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    VX855_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
+			iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH;
+			iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD;
+			iga1_fifo_high_threshold =
+			    VX900_IGA1_FIFO_HIGH_THRESHOLD;
+			iga1_display_queue_expire_num =
+			    VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		/* Set Display FIFO Depath Select */
+		reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
+		viafb_load_reg_num =
+		    display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
+		reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+		/* Set Display FIFO Threshold Select */
+		reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
+		viafb_load_reg_num =
+		    fifo_threshold_select_reg.
+		    iga1_fifo_threshold_select_reg.reg_num;
+		reg =
+		    fifo_threshold_select_reg.
+		    iga1_fifo_threshold_select_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+		/* Set FIFO High Threshold Select */
+		reg_value =
+		    IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
+		viafb_load_reg_num =
+		    fifo_high_threshold_select_reg.
+		    iga1_fifo_high_threshold_select_reg.reg_num;
+		reg =
+		    fifo_high_threshold_select_reg.
+		    iga1_fifo_high_threshold_select_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+		/* Set Display Queue Expire Num */
+		reg_value =
+		    IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
+		    (iga1_display_queue_expire_num);
+		viafb_load_reg_num =
+		    display_queue_expire_num_reg.
+		    iga1_display_queue_expire_num_reg.reg_num;
+		reg =
+		    display_queue_expire_num_reg.
+		    iga1_display_queue_expire_num_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+	} else {
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+			iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    K800_IGA2_FIFO_HIGH_THRESHOLD;
+
+			/* If resolution > 1280x1024, expire length = 64,
+			   else  expire length = 128 */
+			if ((hor_active > 1280) && (ver_active > 1024))
+				iga2_display_queue_expire_num = 16;
+			else
+				iga2_display_queue_expire_num =
+				    K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
+			iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    P880_IGA2_FIFO_HIGH_THRESHOLD;
+
+			/* If resolution > 1280x1024, expire length = 64,
+			   else  expire length = 128 */
+			if ((hor_active > 1280) && (ver_active > 1024))
+				iga2_display_queue_expire_num = 16;
+			else
+				iga2_display_queue_expire_num =
+				    P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
+			iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    CN700_IGA2_FIFO_HIGH_THRESHOLD;
+
+			/* If resolution > 1280x1024, expire length = 64,
+			   else expire length = 128 */
+			if ((hor_active > 1280) && (ver_active > 1024))
+				iga2_display_queue_expire_num = 16;
+			else
+				iga2_display_queue_expire_num =
+				    CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+			iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    CX700_IGA2_FIFO_HIGH_THRESHOLD;
+			iga2_display_queue_expire_num =
+			    CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
+			iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    K8M890_IGA2_FIFO_HIGH_THRESHOLD;
+			iga2_display_queue_expire_num =
+			    K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
+			iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    P4M890_IGA2_FIFO_HIGH_THRESHOLD;
+			iga2_display_queue_expire_num =
+			    P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
+			iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    P4M900_IGA2_FIFO_HIGH_THRESHOLD;
+			iga2_display_queue_expire_num =
+			    P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
+			iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    VX800_IGA2_FIFO_HIGH_THRESHOLD;
+			iga2_display_queue_expire_num =
+			    VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
+			iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    VX855_IGA2_FIFO_HIGH_THRESHOLD;
+			iga2_display_queue_expire_num =
+			    VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
+			iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH;
+			iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD;
+			iga2_fifo_high_threshold =
+			    VX900_IGA2_FIFO_HIGH_THRESHOLD;
+			iga2_display_queue_expire_num =
+			    VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+		}
+
+		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+			/* Set Display FIFO Depath Select */
+			reg_value =
+			    IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
+			    - 1;
+			/* Patch LCD in IGA2 case */
+			viafb_load_reg_num =
+			    display_fifo_depth_reg.
+			    iga2_fifo_depth_select_reg.reg_num;
+			reg =
+			    display_fifo_depth_reg.
+			    iga2_fifo_depth_select_reg.reg;
+			viafb_load_reg(reg_value,
+				viafb_load_reg_num, reg, VIACR);
+		} else {
+
+			/* Set Display FIFO Depath Select */
+			reg_value =
+			    IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
+			viafb_load_reg_num =
+			    display_fifo_depth_reg.
+			    iga2_fifo_depth_select_reg.reg_num;
+			reg =
+			    display_fifo_depth_reg.
+			    iga2_fifo_depth_select_reg.reg;
+			viafb_load_reg(reg_value,
+				viafb_load_reg_num, reg, VIACR);
+		}
+
+		/* Set Display FIFO Threshold Select */
+		reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
+		viafb_load_reg_num =
+		    fifo_threshold_select_reg.
+		    iga2_fifo_threshold_select_reg.reg_num;
+		reg =
+		    fifo_threshold_select_reg.
+		    iga2_fifo_threshold_select_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+		/* Set FIFO High Threshold Select */
+		reg_value =
+		    IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
+		viafb_load_reg_num =
+		    fifo_high_threshold_select_reg.
+		    iga2_fifo_high_threshold_select_reg.reg_num;
+		reg =
+		    fifo_high_threshold_select_reg.
+		    iga2_fifo_high_threshold_select_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+		/* Set Display Queue Expire Num */
+		reg_value =
+		    IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
+		    (iga2_display_queue_expire_num);
+		viafb_load_reg_num =
+		    display_queue_expire_num_reg.
+		    iga2_display_queue_expire_num_reg.reg_num;
+		reg =
+		    display_queue_expire_num_reg.
+		    iga2_display_queue_expire_num_reg.reg;
+		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+	}
+
+}
+
+static struct via_pll_config get_pll_config(struct pll_limit *limits, int size,
+	int clk)
+{
+	struct via_pll_config cur, up, down, best = {0, 1, 0};
+	const u32 f0 = 14318180; /* X1 frequency */
+	int i, f;
+
+	for (i = 0; i < size; i++) {
+		cur.rshift = limits[i].rshift;
+		cur.divisor = limits[i].divisor;
+		cur.multiplier = clk / ((f0 / cur.divisor)>>cur.rshift);
+		f = abs(get_pll_output_frequency(f0, cur) - clk);
+		up = down = cur;
+		up.multiplier++;
+		down.multiplier--;
+		if (abs(get_pll_output_frequency(f0, up) - clk) < f)
+			cur = up;
+		else if (abs(get_pll_output_frequency(f0, down) - clk) < f)
+			cur = down;
+
+		if (cur.multiplier < limits[i].multiplier_min)
+			cur.multiplier = limits[i].multiplier_min;
+		else if (cur.multiplier > limits[i].multiplier_max)
+			cur.multiplier = limits[i].multiplier_max;
+
+		f = abs(get_pll_output_frequency(f0, cur) - clk);
+		if (f < abs(get_pll_output_frequency(f0, best) - clk))
+			best = cur;
+	}
+
+	return best;
+}
+
+static struct via_pll_config get_best_pll_config(int clk)
+{
+	struct via_pll_config config;
+
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_CLE266:
+	case UNICHROME_K400:
+		config = get_pll_config(cle266_pll_limits,
+			ARRAY_SIZE(cle266_pll_limits), clk);
+		break;
+	case UNICHROME_K800:
+	case UNICHROME_PM800:
+	case UNICHROME_CN700:
+		config = get_pll_config(k800_pll_limits,
+			ARRAY_SIZE(k800_pll_limits), clk);
+		break;
+	case UNICHROME_CX700:
+	case UNICHROME_CN750:
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M890:
+	case UNICHROME_P4M900:
+	case UNICHROME_VX800:
+		config = get_pll_config(cx700_pll_limits,
+			ARRAY_SIZE(cx700_pll_limits), clk);
+		break;
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		config = get_pll_config(vx855_pll_limits,
+			ARRAY_SIZE(vx855_pll_limits), clk);
+		break;
+	}
+
+	return config;
+}
+
+/* Set VCLK*/
+void viafb_set_vclock(u32 clk, int set_iga)
+{
+	struct via_pll_config config = get_best_pll_config(clk);
+
+	if (set_iga == IGA1)
+		clock.set_primary_pll(config);
+	if (set_iga == IGA2)
+		clock.set_secondary_pll(config);
+
+	/* Fire! */
+	via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
+}
+
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
+	u16 cxres, u16 cyres)
+{
+	struct via_display_timing timing;
+	u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
+
+	timing.hor_addr = cxres;
+	timing.hor_sync_start = timing.hor_addr + var->right_margin + dx;
+	timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
+	timing.hor_total = timing.hor_sync_end + var->left_margin + dx;
+	timing.hor_blank_start = timing.hor_addr + dx;
+	timing.hor_blank_end = timing.hor_total - dx;
+	timing.ver_addr = cyres;
+	timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy;
+	timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
+	timing.ver_total = timing.ver_sync_end + var->upper_margin + dy;
+	timing.ver_blank_start = timing.ver_addr + dy;
+	timing.ver_blank_end = timing.ver_total - dy;
+	return timing;
+}
+
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
+	u16 cxres, u16 cyres, int iga)
+{
+	struct via_display_timing crt_reg = var_to_timing(var,
+		cxres ? cxres : var->xres, cyres ? cyres : var->yres);
+
+	if (iga == IGA1)
+		via_set_primary_timing(&crt_reg);
+	else if (iga == IGA2)
+		via_set_secondary_timing(&crt_reg);
+
+	viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
+	if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
+		&& viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
+		viafb_load_FIFO_reg(iga, var->xres, var->yres);
+
+	viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
+}
+
+void viafb_init_chip_info(int chip_type)
+{
+	via_clock_init(&clock, chip_type);
+	init_gfx_chip_info(chip_type);
+	init_tmds_chip_info();
+	init_lvds_chip_info();
+
+	/*Set IGA path for each device */
+	viafb_set_iga_path();
+
+	viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
+	viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
+	viaparinfo->lvds_setting_info2->display_method =
+		viaparinfo->lvds_setting_info->display_method;
+	viaparinfo->lvds_setting_info2->lcd_mode =
+		viaparinfo->lvds_setting_info->lcd_mode;
+}
+
+void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
+{
+	if (flag == 0) {
+		viaparinfo->tmds_setting_info->h_active = hres;
+		viaparinfo->tmds_setting_info->v_active = vres;
+	} else {
+
+		if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
+			viaparinfo->tmds_setting_info->h_active = hres;
+			viaparinfo->tmds_setting_info->v_active = vres;
+		}
+
+	}
+}
+
+static void init_gfx_chip_info(int chip_type)
+{
+	u8 tmp;
+
+	viaparinfo->chip_info->gfx_chip_name = chip_type;
+
+	/* Check revision of CLE266 Chip */
+	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+		/* CR4F only define in CLE266.CX chip */
+		tmp = viafb_read_reg(VIACR, CR4F);
+		viafb_write_reg(CR4F, VIACR, 0x55);
+		if (viafb_read_reg(VIACR, CR4F) != 0x55)
+			viaparinfo->chip_info->gfx_chip_revision =
+			CLE266_REVISION_AX;
+		else
+			viaparinfo->chip_info->gfx_chip_revision =
+			CLE266_REVISION_CX;
+		/* restore orignal CR4F value */
+		viafb_write_reg(CR4F, VIACR, tmp);
+	}
+
+	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+		tmp = viafb_read_reg(VIASR, SR43);
+		DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
+		if (tmp & 0x02) {
+			viaparinfo->chip_info->gfx_chip_revision =
+				CX700_REVISION_700M2;
+		} else if (tmp & 0x40) {
+			viaparinfo->chip_info->gfx_chip_revision =
+				CX700_REVISION_700M;
+		} else {
+			viaparinfo->chip_info->gfx_chip_revision =
+				CX700_REVISION_700;
+		}
+	}
+
+	/* Determine which 2D engine we have */
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_VX800:
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
+		break;
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M900:
+		viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5;
+		break;
+	default:
+		viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2;
+		break;
+	}
+}
+
+static void init_tmds_chip_info(void)
+{
+	viafb_tmds_trasmitter_identify();
+
+	if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
+		output_interface) {
+		switch (viaparinfo->chip_info->gfx_chip_name) {
+		case UNICHROME_CX700:
+			{
+				/* we should check support by hardware layout.*/
+				if ((viafb_display_hardware_layout ==
+				     HW_LAYOUT_DVI_ONLY)
+				    || (viafb_display_hardware_layout ==
+					HW_LAYOUT_LCD_DVI)) {
+					viaparinfo->chip_info->tmds_chip_info.
+					    output_interface = INTERFACE_TMDS;
+				} else {
+					viaparinfo->chip_info->tmds_chip_info.
+						output_interface =
+						INTERFACE_NONE;
+				}
+				break;
+			}
+		case UNICHROME_K8M890:
+		case UNICHROME_P4M900:
+		case UNICHROME_P4M890:
+			/* TMDS on PCIE, we set DFPLOW as default. */
+			viaparinfo->chip_info->tmds_chip_info.output_interface =
+			    INTERFACE_DFP_LOW;
+			break;
+		default:
+			{
+				/* set DVP1 default for DVI */
+				viaparinfo->chip_info->tmds_chip_info
+				.output_interface = INTERFACE_DVP1;
+			}
+		}
+	}
+
+	DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
+		  viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
+	viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
+		&viaparinfo->shared->tmds_setting_info);
+}
+
+static void init_lvds_chip_info(void)
+{
+	viafb_lvds_trasmitter_identify();
+	viafb_init_lcd_size();
+	viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
+				   viaparinfo->lvds_setting_info);
+	if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+		viafb_init_lvds_output_interface(&viaparinfo->chip_info->
+			lvds_chip_info2, viaparinfo->lvds_setting_info2);
+	}
+	/*If CX700,two singel LCD, we need to reassign
+	   LCD interface to different LVDS port */
+	if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
+	    && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
+		if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
+			lvds_chip_name) && (INTEGRATED_LVDS ==
+			viaparinfo->chip_info->
+			lvds_chip_info2.lvds_chip_name)) {
+			viaparinfo->chip_info->lvds_chip_info.output_interface =
+				INTERFACE_LVDS0;
+			viaparinfo->chip_info->lvds_chip_info2.
+				output_interface =
+			    INTERFACE_LVDS1;
+		}
+	}
+
+	DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
+		  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+	DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
+		  viaparinfo->chip_info->lvds_chip_info.output_interface);
+	DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
+		  viaparinfo->chip_info->lvds_chip_info.output_interface);
+}
+
+void viafb_init_dac(int set_iga)
+{
+	int i;
+	u8 tmp;
+
+	if (set_iga == IGA1) {
+		/* access Primary Display's LUT */
+		viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
+		/* turn off LCK */
+		viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
+		for (i = 0; i < 256; i++) {
+			write_dac_reg(i, palLUT_table[i].red,
+				      palLUT_table[i].green,
+				      palLUT_table[i].blue);
+		}
+		/* turn on LCK */
+		viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
+	} else {
+		tmp = viafb_read_reg(VIACR, CR6A);
+		/* access Secondary Display's LUT */
+		viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
+		viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
+		for (i = 0; i < 256; i++) {
+			write_dac_reg(i, palLUT_table[i].red,
+				      palLUT_table[i].green,
+				      palLUT_table[i].blue);
+		}
+		/* set IGA1 DAC for default */
+		viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
+		viafb_write_reg(CR6A, VIACR, tmp);
+	}
+}
+
+static void device_screen_off(void)
+{
+	/* turn off CRT screen (IGA1) */
+	viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
+}
+
+static void device_screen_on(void)
+{
+	/* turn on CRT screen (IGA1) */
+	viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
+}
+
+static void set_display_channel(void)
+{
+	/*If viafb_LCD2_ON, on cx700, internal lvds's information
+	is keeped on lvds_setting_info2 */
+	if (viafb_LCD2_ON &&
+		viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
+		/* For dual channel LCD: */
+		/* Set to Dual LVDS channel. */
+		viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
+	} else if (viafb_LCD_ON && viafb_DVI_ON) {
+		/* For LCD+DFP: */
+		/* Set to LVDS1 + TMDS channel. */
+		viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
+	} else if (viafb_DVI_ON) {
+		/* Set to single TMDS channel. */
+		viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
+	} else if (viafb_LCD_ON) {
+		if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
+			/* For dual channel LCD: */
+			/* Set to Dual LVDS channel. */
+			viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
+		} else {
+			/* Set to LVDS0 + LVDS1 channel. */
+			viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
+		}
+	}
+}
+
+static u8 get_sync(struct fb_var_screeninfo *var)
+{
+	u8 polarity = 0;
+
+	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+		polarity |= VIA_HSYNC_NEGATIVE;
+	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+		polarity |= VIA_VSYNC_NEGATIVE;
+	return polarity;
+}
+
+static void hw_init(void)
+{
+	int i;
+
+	inb(VIAStatus);
+	outb(0x00, VIAAR);
+
+	/* Write Common Setting for Video Mode */
+	viafb_write_regx(common_vga, ARRAY_SIZE(common_vga));
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_CLE266:
+		viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
+		break;
+
+	case UNICHROME_K400:
+		viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
+		break;
+
+	case UNICHROME_K800:
+	case UNICHROME_PM800:
+		viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
+		break;
+
+	case UNICHROME_CN700:
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M890:
+	case UNICHROME_P4M900:
+		viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
+		break;
+
+	case UNICHROME_CX700:
+	case UNICHROME_VX800:
+		viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
+		break;
+
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
+		break;
+	}
+
+	/* magic required on VX900 for correct modesetting on IGA1 */
+	via_write_reg_mask(VIACR, 0x45, 0x00, 0x01);
+
+	/* probably this should go to the scaling code one day */
+	via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */
+	viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
+
+	/* Fill VPIT Parameters */
+	/* Write Misc Register */
+	outb(VPIT.Misc, VIA_MISC_REG_WRITE);
+
+	/* Write Sequencer */
+	for (i = 1; i <= StdSR; i++)
+		via_write_reg(VIASR, i, VPIT.SR[i - 1]);
+
+	viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
+
+	/* Write Graphic Controller */
+	for (i = 0; i < StdGR; i++)
+		via_write_reg(VIAGR, i, VPIT.GR[i]);
+
+	/* Write Attribute Controller */
+	for (i = 0; i < StdAR; i++) {
+		inb(VIAStatus);
+		outb(i, VIAAR);
+		outb(VPIT.AR[i], VIAAR);
+	}
+
+	inb(VIAStatus);
+	outb(0x20, VIAAR);
+
+	load_fix_bit_crtc_reg();
+}
+
+int viafb_setmode(void)
+{
+	int j, cxres = 0, cyres = 0;
+	int port;
+	u32 devices = viaparinfo->shared->iga1_devices
+		| viaparinfo->shared->iga2_devices;
+	u8 value, index, mask;
+	struct fb_var_screeninfo var2;
+
+	device_screen_off();
+	device_off();
+	via_set_state(devices, VIA_STATE_OFF);
+
+	hw_init();
+
+	/* Update Patch Register */
+
+	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
+		|| viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
+		&& viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
+		for (j = 0; j < res_patch_table[0].table_length; j++) {
+			index = res_patch_table[0].io_reg_table[j].index;
+			port = res_patch_table[0].io_reg_table[j].port;
+			value = res_patch_table[0].io_reg_table[j].value;
+			mask = res_patch_table[0].io_reg_table[j].mask;
+			viafb_write_reg_mask(index, port, value, mask);
+		}
+	}
+
+	via_set_primary_pitch(viafbinfo->fix.line_length);
+	via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
+		: viafbinfo->fix.line_length);
+	via_set_primary_color_depth(viaparinfo->depth);
+	via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
+		: viaparinfo->depth);
+	via_set_source(viaparinfo->shared->iga1_devices, IGA1);
+	via_set_source(viaparinfo->shared->iga2_devices, IGA2);
+	if (viaparinfo->shared->iga2_devices)
+		enable_second_display_channel();
+	else
+		disable_second_display_channel();
+
+	/* Update Refresh Rate Setting */
+
+	/* Clear On Screen */
+
+	if (viafb_dual_fb) {
+		var2 = viafbinfo1->var;
+	} else if (viafb_SAMM_ON) {
+		viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
+			viafb_second_xres, viafb_second_yres, viafb_refresh1));
+		cxres = viafbinfo->var.xres;
+		cyres = viafbinfo->var.yres;
+		var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
+	}
+
+	/* CRT set mode */
+	if (viafb_CRT_ON) {
+		if (viaparinfo->shared->iga2_devices & VIA_CRT
+			&& viafb_SAMM_ON)
+			viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2);
+		else
+			viafb_fill_crtc_timing(&viafbinfo->var, 0, 0,
+				(viaparinfo->shared->iga1_devices & VIA_CRT)
+				? IGA1 : IGA2);
+
+		/* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
+		to 8 alignment (1368),there is several pixels (2 pixels)
+		on right side of screen. */
+		if (viafbinfo->var.xres % 8) {
+			viafb_unlock_crt();
+			viafb_write_reg(CR02, VIACR,
+				viafb_read_reg(VIACR, CR02) - 1);
+			viafb_lock_crt();
+		}
+	}
+
+	if (viafb_DVI_ON) {
+		if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
+			&& viafb_SAMM_ON)
+			viafb_dvi_set_mode(&var2, cxres, cyres, IGA2);
+		else
+			viafb_dvi_set_mode(&viafbinfo->var, 0, 0,
+				viaparinfo->tmds_setting_info->iga_path);
+	}
+
+	if (viafb_LCD_ON) {
+		if (viafb_SAMM_ON &&
+			(viaparinfo->lvds_setting_info->iga_path == IGA2)) {
+			viafb_lcd_set_mode(&var2, cxres, cyres,
+				viaparinfo->lvds_setting_info,
+				&viaparinfo->chip_info->lvds_chip_info);
+		} else {
+			/* IGA1 doesn't have LCD scaling, so set it center. */
+			if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+				viaparinfo->lvds_setting_info->display_method =
+				    LCD_CENTERING;
+			}
+			viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
+				viaparinfo->lvds_setting_info,
+				&viaparinfo->chip_info->lvds_chip_info);
+		}
+	}
+	if (viafb_LCD2_ON) {
+		if (viafb_SAMM_ON &&
+			(viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
+			viafb_lcd_set_mode(&var2, cxres, cyres,
+				viaparinfo->lvds_setting_info2,
+				&viaparinfo->chip_info->lvds_chip_info2);
+		} else {
+			/* IGA1 doesn't have LCD scaling, so set it center. */
+			if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
+				viaparinfo->lvds_setting_info2->display_method =
+				    LCD_CENTERING;
+			}
+			viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
+				viaparinfo->lvds_setting_info2,
+				&viaparinfo->chip_info->lvds_chip_info2);
+		}
+	}
+
+	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
+	    && (viafb_LCD_ON || viafb_DVI_ON))
+		set_display_channel();
+
+	/* If set mode normally, save resolution information for hot-plug . */
+	if (!viafb_hotplug) {
+		viafb_hotplug_Xres = viafbinfo->var.xres;
+		viafb_hotplug_Yres = viafbinfo->var.yres;
+		viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel;
+		viafb_hotplug_refresh = viafb_refresh;
+
+		if (viafb_DVI_ON)
+			viafb_DeviceStatus = DVI_Device;
+		else
+			viafb_DeviceStatus = CRT_Device;
+	}
+	device_on();
+	if (!viafb_SAMM_ON)
+		via_set_sync_polarity(devices, get_sync(&viafbinfo->var));
+	else {
+		via_set_sync_polarity(viaparinfo->shared->iga1_devices,
+			get_sync(&viafbinfo->var));
+		via_set_sync_polarity(viaparinfo->shared->iga2_devices,
+			get_sync(&var2));
+	}
+
+	clock.set_engine_pll_state(VIA_STATE_ON);
+	clock.set_primary_clock_source(VIA_CLKSRC_X1, true);
+	clock.set_secondary_clock_source(VIA_CLKSRC_X1, true);
+
+#ifdef CONFIG_FB_VIA_X_COMPATIBILITY
+	clock.set_primary_pll_state(VIA_STATE_ON);
+	clock.set_primary_clock_state(VIA_STATE_ON);
+	clock.set_secondary_pll_state(VIA_STATE_ON);
+	clock.set_secondary_clock_state(VIA_STATE_ON);
+#else
+	if (viaparinfo->shared->iga1_devices) {
+		clock.set_primary_pll_state(VIA_STATE_ON);
+		clock.set_primary_clock_state(VIA_STATE_ON);
+	} else {
+		clock.set_primary_pll_state(VIA_STATE_OFF);
+		clock.set_primary_clock_state(VIA_STATE_OFF);
+	}
+
+	if (viaparinfo->shared->iga2_devices) {
+		clock.set_secondary_pll_state(VIA_STATE_ON);
+		clock.set_secondary_clock_state(VIA_STATE_ON);
+	} else {
+		clock.set_secondary_pll_state(VIA_STATE_OFF);
+		clock.set_secondary_clock_state(VIA_STATE_OFF);
+	}
+#endif /*CONFIG_FB_VIA_X_COMPATIBILITY*/
+
+	via_set_state(devices, VIA_STATE_ON);
+	device_screen_on();
+	return 1;
+}
+
+int viafb_get_refresh(int hres, int vres, u32 long_refresh)
+{
+	const struct fb_videomode *best;
+
+	best = viafb_get_best_mode(hres, vres, long_refresh);
+	if (!best)
+		return 60;
+
+	if (abs(best->refresh - long_refresh) > 3) {
+		if (hres == 1200 && vres == 900)
+			return 49; /* OLPC DCON only supports 50 Hz */
+		else
+			return 60;
+	}
+
+	return best->refresh;
+}
+
+static void device_off(void)
+{
+	viafb_dvi_disable();
+	viafb_lcd_disable();
+}
+
+static void device_on(void)
+{
+	if (viafb_DVI_ON == 1)
+		viafb_dvi_enable();
+	if (viafb_LCD_ON == 1)
+		viafb_lcd_enable();
+}
+
+static void enable_second_display_channel(void)
+{
+	/* to enable second display channel. */
+	viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+	viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
+	viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+static void disable_second_display_channel(void)
+{
+	/* to disable second display channel. */
+	viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+	viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
+	viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
+					*p_gfx_dpa_setting)
+{
+	switch (output_interface) {
+	case INTERFACE_DVP0:
+		{
+			/* DVP0 Clock Polarity and Adjust: */
+			viafb_write_reg_mask(CR96, VIACR,
+				       p_gfx_dpa_setting->DVP0, 0x0F);
+
+			/* DVP0 Clock and Data Pads Driving: */
+			viafb_write_reg_mask(SR1E, VIASR,
+				       p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
+			viafb_write_reg_mask(SR2A, VIASR,
+				       p_gfx_dpa_setting->DVP0ClockDri_S1,
+				       BIT4);
+			viafb_write_reg_mask(SR1B, VIASR,
+				       p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
+			viafb_write_reg_mask(SR2A, VIASR,
+				       p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
+			break;
+		}
+
+	case INTERFACE_DVP1:
+		{
+			/* DVP1 Clock Polarity and Adjust: */
+			viafb_write_reg_mask(CR9B, VIACR,
+				       p_gfx_dpa_setting->DVP1, 0x0F);
+
+			/* DVP1 Clock and Data Pads Driving: */
+			viafb_write_reg_mask(SR65, VIASR,
+				       p_gfx_dpa_setting->DVP1Driving, 0x0F);
+			break;
+		}
+
+	case INTERFACE_DFP_HIGH:
+		{
+			viafb_write_reg_mask(CR97, VIACR,
+				       p_gfx_dpa_setting->DFPHigh, 0x0F);
+			break;
+		}
+
+	case INTERFACE_DFP_LOW:
+		{
+			viafb_write_reg_mask(CR99, VIACR,
+				       p_gfx_dpa_setting->DFPLow, 0x0F);
+			break;
+		}
+
+	case INTERFACE_DFP:
+		{
+			viafb_write_reg_mask(CR97, VIACR,
+				       p_gfx_dpa_setting->DFPHigh, 0x0F);
+			viafb_write_reg_mask(CR99, VIACR,
+				       p_gfx_dpa_setting->DFPLow, 0x0F);
+			break;
+		}
+	}
+}
+
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+	const struct fb_videomode *mode)
+{
+	var->pixclock = mode->pixclock;
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->left_margin = mode->left_margin;
+	var->right_margin = mode->right_margin;
+	var->hsync_len = mode->hsync_len;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->vsync_len = mode->vsync_len;
+	var->sync = mode->sync;
+}
diff --git a/drivers/video/fbdev/via/hw.h b/drivers/video/fbdev/via/hw.h
new file mode 100644
index 000000000000..3be073c58b03
--- /dev/null
+++ b/drivers/video/fbdev/via/hw.h
@@ -0,0 +1,676 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __HW_H__
+#define __HW_H__
+
+#include <linux/seq_file.h>
+
+#include "viamode.h"
+#include "global.h"
+#include "via_modesetting.h"
+
+#define viafb_read_reg(p, i)			via_read_reg(p, i)
+#define viafb_write_reg(i, p, d)		via_write_reg(p, i, d)
+#define viafb_write_reg_mask(i, p, d, m)	via_write_reg_mask(p, i, d, m)
+
+/* VIA output devices */
+#define VIA_LDVP0	0x00000001
+#define VIA_LDVP1	0x00000002
+#define VIA_DVP0	0x00000004
+#define VIA_CRT		0x00000010
+#define VIA_DVP1	0x00000020
+#define VIA_LVDS1	0x00000040
+#define VIA_LVDS2	0x00000080
+
+/* VIA output device power states */
+#define VIA_STATE_ON		0
+#define VIA_STATE_STANDBY	1
+#define VIA_STATE_SUSPEND	2
+#define VIA_STATE_OFF		3
+
+/* VIA output device sync polarity */
+#define VIA_HSYNC_NEGATIVE	0x01
+#define VIA_VSYNC_NEGATIVE	0x02
+
+/**********************************************************/
+/* Definition IGA2 Design Method of CRTC Shadow Registers */
+/**********************************************************/
+#define IGA2_HOR_TOTAL_SHADOW_FORMULA(x)           ((x/8)-5)
+#define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y)     (((x+y)/8)-1)
+#define IGA2_VER_TOTAL_SHADOW_FORMULA(x)           ((x)-2)
+#define IGA2_VER_ADDR_SHADOW_FORMULA(x)            ((x)-1)
+#define IGA2_VER_BLANK_START_SHADOW_FORMULA(x)     ((x)-1)
+#define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y)     ((x+y)-1)
+#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x)      (x)
+#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y)      (x+y)
+
+/* Define Register Number for IGA2 Shadow CRTC Timing */
+
+/* location: {CR6D,0,7},{CR71,3,3} */
+#define IGA2_SHADOW_HOR_TOTAL_REG_NUM       2
+/* location: {CR6E,0,7} */
+#define IGA2_SHADOW_HOR_BLANK_END_REG_NUM   1
+/* location: {CR6F,0,7},{CR71,0,2} */
+#define IGA2_SHADOW_VER_TOTAL_REG_NUM       2
+/* location: {CR70,0,7},{CR71,4,6} */
+#define IGA2_SHADOW_VER_ADDR_REG_NUM        2
+/* location: {CR72,0,7},{CR74,4,6} */
+#define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2
+/* location: {CR73,0,7},{CR74,0,2} */
+#define IGA2_SHADOW_VER_BLANK_END_REG_NUM   2
+/* location: {CR75,0,7},{CR76,4,6} */
+#define IGA2_SHADOW_VER_SYNC_START_REG_NUM  2
+/* location: {CR76,0,3} */
+#define IGA2_SHADOW_VER_SYNC_END_REG_NUM    1
+
+/* Define Fetch Count Register*/
+
+/* location: {SR1C,0,7},{SR1D,0,1} */
+#define IGA1_FETCH_COUNT_REG_NUM        2
+/* 16 bytes alignment. */
+#define IGA1_FETCH_COUNT_ALIGN_BYTE     16
+/* x: H resolution, y: color depth */
+#define IGA1_FETCH_COUNT_PATCH_VALUE    4
+#define IGA1_FETCH_COUNT_FORMULA(x, y)   \
+	(((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
+
+/* location: {CR65,0,7},{CR67,2,3} */
+#define IGA2_FETCH_COUNT_REG_NUM        2
+#define IGA2_FETCH_COUNT_ALIGN_BYTE     16
+#define IGA2_FETCH_COUNT_PATCH_VALUE    0
+#define IGA2_FETCH_COUNT_FORMULA(x, y)   \
+	(((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE)
+
+/* Staring Address*/
+
+/* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */
+#define IGA1_STARTING_ADDR_REG_NUM      4
+/* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */
+#define IGA2_STARTING_ADDR_REG_NUM      3
+
+/* Define Display OFFSET*/
+/* These value are by HW suggested value*/
+/* location: {SR17,0,7} */
+#define K800_IGA1_FIFO_MAX_DEPTH                384
+/* location: {SR16,0,5},{SR16,7,7} */
+#define K800_IGA1_FIFO_THRESHOLD                328
+/* location: {SR18,0,5},{SR18,7,7} */
+#define K800_IGA1_FIFO_HIGH_THRESHOLD           296
+/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
+				/* because HW only 5 bits */
+#define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      0
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define K800_IGA2_FIFO_MAX_DEPTH                384
+/* location: {CR68,0,3},{CR95,4,6} */
+#define K800_IGA2_FIFO_THRESHOLD                328
+/* location: {CR92,0,3},{CR95,0,2} */
+#define K800_IGA2_FIFO_HIGH_THRESHOLD           296
+/* location: {CR94,0,6} */
+#define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM      128
+
+/* location: {SR17,0,7} */
+#define P880_IGA1_FIFO_MAX_DEPTH                192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P880_IGA1_FIFO_THRESHOLD                128
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P880_IGA1_FIFO_HIGH_THRESHOLD           64
+/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
+				/* because HW only 5 bits */
+#define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      0
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P880_IGA2_FIFO_MAX_DEPTH                96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P880_IGA2_FIFO_THRESHOLD                64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P880_IGA2_FIFO_HIGH_THRESHOLD           32
+/* location: {CR94,0,6} */
+#define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM      128
+
+/* VT3314 chipset*/
+
+/* location: {SR17,0,7} */
+#define CN700_IGA1_FIFO_MAX_DEPTH               96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define CN700_IGA1_FIFO_THRESHOLD               80
+/* location: {SR18,0,5},{SR18,7,7} */
+#define CN700_IGA1_FIFO_HIGH_THRESHOLD          64
+/* location: {SR22,0,4}. (128/4) =64, P800 must be set zero,
+				because HW only 5 bits */
+#define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     0
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define CN700_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define CN700_IGA2_FIFO_THRESHOLD               80
+/* location: {CR92,0,3},{CR95,0,2} */
+#define CN700_IGA2_FIFO_HIGH_THRESHOLD          32
+/* location: {CR94,0,6} */
+#define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
+
+/* For VT3324, these values are suggested by HW */
+/* location: {SR17,0,7} */
+#define CX700_IGA1_FIFO_MAX_DEPTH               192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define CX700_IGA1_FIFO_THRESHOLD               128
+/* location: {SR18,0,5},{SR18,7,7} */
+#define CX700_IGA1_FIFO_HIGH_THRESHOLD          128
+/* location: {SR22,0,4} */
+#define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     124
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define CX700_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define CX700_IGA2_FIFO_THRESHOLD               64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define CX700_IGA2_FIFO_HIGH_THRESHOLD          32
+/* location: {CR94,0,6} */
+#define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
+
+/* VT3336 chipset*/
+/* location: {SR17,0,7} */
+#define K8M890_IGA1_FIFO_MAX_DEPTH               360
+/* location: {SR16,0,5},{SR16,7,7} */
+#define K8M890_IGA1_FIFO_THRESHOLD               328
+/* location: {SR18,0,5},{SR18,7,7} */
+#define K8M890_IGA1_FIFO_HIGH_THRESHOLD          296
+/* location: {SR22,0,4}. */
+#define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     124
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define K8M890_IGA2_FIFO_MAX_DEPTH               360
+/* location: {CR68,0,3},{CR95,4,6} */
+#define K8M890_IGA2_FIFO_THRESHOLD               328
+/* location: {CR92,0,3},{CR95,0,2} */
+#define K8M890_IGA2_FIFO_HIGH_THRESHOLD          296
+/* location: {CR94,0,6} */
+#define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     124
+
+/* VT3327 chipset*/
+/* location: {SR17,0,7} */
+#define P4M890_IGA1_FIFO_MAX_DEPTH               96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P4M890_IGA1_FIFO_THRESHOLD               76
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P4M890_IGA1_FIFO_HIGH_THRESHOLD          64
+/* location: {SR22,0,4}. (32/4) =8 */
+#define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     32
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P4M890_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P4M890_IGA2_FIFO_THRESHOLD               76
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P4M890_IGA2_FIFO_HIGH_THRESHOLD          64
+/* location: {CR94,0,6} */
+#define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     32
+
+/* VT3364 chipset*/
+/* location: {SR17,0,7} */
+#define P4M900_IGA1_FIFO_MAX_DEPTH               96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P4M900_IGA1_FIFO_THRESHOLD               76
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P4M900_IGA1_FIFO_HIGH_THRESHOLD          76
+/* location: {SR22,0,4}. */
+#define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     32
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P4M900_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P4M900_IGA2_FIFO_THRESHOLD               76
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P4M900_IGA2_FIFO_HIGH_THRESHOLD          76
+/* location: {CR94,0,6} */
+#define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     32
+
+/* For VT3353, these values are suggested by HW */
+/* location: {SR17,0,7} */
+#define VX800_IGA1_FIFO_MAX_DEPTH               192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define VX800_IGA1_FIFO_THRESHOLD               152
+/* location: {SR18,0,5},{SR18,7,7} */
+#define VX800_IGA1_FIFO_HIGH_THRESHOLD          152
+/* location: {SR22,0,4} */
+#define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      64
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define VX800_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define VX800_IGA2_FIFO_THRESHOLD               64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define VX800_IGA2_FIFO_HIGH_THRESHOLD          32
+/* location: {CR94,0,6} */
+#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
+
+/* For VT3409 */
+#define VX855_IGA1_FIFO_MAX_DEPTH               400
+#define VX855_IGA1_FIFO_THRESHOLD               320
+#define VX855_IGA1_FIFO_HIGH_THRESHOLD          320
+#define VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     160
+
+#define VX855_IGA2_FIFO_MAX_DEPTH               200
+#define VX855_IGA2_FIFO_THRESHOLD               160
+#define VX855_IGA2_FIFO_HIGH_THRESHOLD          160
+#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     320
+
+/* For VT3410 */
+#define VX900_IGA1_FIFO_MAX_DEPTH               400
+#define VX900_IGA1_FIFO_THRESHOLD               320
+#define VX900_IGA1_FIFO_HIGH_THRESHOLD          320
+#define VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     160
+
+#define VX900_IGA2_FIFO_MAX_DEPTH               192
+#define VX900_IGA2_FIFO_THRESHOLD               160
+#define VX900_IGA2_FIFO_HIGH_THRESHOLD          160
+#define VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     320
+
+#define IGA1_FIFO_DEPTH_SELECT_REG_NUM          1
+#define IGA1_FIFO_THRESHOLD_REG_NUM             2
+#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM        2
+#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM   1
+
+#define IGA2_FIFO_DEPTH_SELECT_REG_NUM          3
+#define IGA2_FIFO_THRESHOLD_REG_NUM             2
+#define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM        2
+#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM   1
+
+#define IGA1_FIFO_DEPTH_SELECT_FORMULA(x)                   ((x/2)-1)
+#define IGA1_FIFO_THRESHOLD_FORMULA(x)                      (x/4)
+#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x)            (x/4)
+#define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x)                 (x/4)
+#define IGA2_FIFO_DEPTH_SELECT_FORMULA(x)                   (((x/2)/4)-1)
+#define IGA2_FIFO_THRESHOLD_FORMULA(x)                      (x/4)
+#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x)            (x/4)
+#define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x)                 (x/4)
+
+/************************************************************************/
+/*  LCD Timing                                                          */
+/************************************************************************/
+
+/* 500 ms = 500000 us */
+#define LCD_POWER_SEQ_TD0               500000
+/* 50 ms = 50000 us */
+#define LCD_POWER_SEQ_TD1               50000
+/* 0 us */
+#define LCD_POWER_SEQ_TD2               0
+/* 210 ms = 210000 us */
+#define LCD_POWER_SEQ_TD3               210000
+/* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */
+#define CLE266_POWER_SEQ_UNIT           71
+/* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */
+#define K800_POWER_SEQ_UNIT             142
+/* 2^13 * (1/14.31818M) = 572.1 us */
+#define P880_POWER_SEQ_UNIT             572
+
+#define CLE266_POWER_SEQ_FORMULA(x)     ((x)/CLE266_POWER_SEQ_UNIT)
+#define K800_POWER_SEQ_FORMULA(x)       ((x)/K800_POWER_SEQ_UNIT)
+#define P880_POWER_SEQ_FORMULA(x)       ((x)/P880_POWER_SEQ_UNIT)
+
+/* location: {CR8B,0,7},{CR8F,0,3} */
+#define LCD_POWER_SEQ_TD0_REG_NUM       2
+/* location: {CR8C,0,7},{CR8F,4,7} */
+#define LCD_POWER_SEQ_TD1_REG_NUM       2
+/* location: {CR8D,0,7},{CR90,0,3} */
+#define LCD_POWER_SEQ_TD2_REG_NUM       2
+/* location: {CR8E,0,7},{CR90,4,7} */
+#define LCD_POWER_SEQ_TD3_REG_NUM       2
+
+/* LCD Scaling factor*/
+/* x: indicate setting horizontal size*/
+/* y: indicate panel horizontal size*/
+
+/* Horizontal scaling factor 10 bits (2^10) */
+#define CLE266_LCD_HOR_SCF_FORMULA(x, y)   (((x-1)*1024)/(y-1))
+/* Vertical scaling factor 10 bits (2^10) */
+#define CLE266_LCD_VER_SCF_FORMULA(x, y)   (((x-1)*1024)/(y-1))
+/* Horizontal scaling factor 10 bits (2^12) */
+#define K800_LCD_HOR_SCF_FORMULA(x, y)     (((x-1)*4096)/(y-1))
+/* Vertical scaling factor 10 bits (2^11) */
+#define K800_LCD_VER_SCF_FORMULA(x, y)     (((x-1)*2048)/(y-1))
+
+/* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */
+#define LCD_HOR_SCALING_FACTOR_REG_NUM  3
+/* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */
+#define LCD_VER_SCALING_FACTOR_REG_NUM  3
+/* location: {CR77,0,7},{CR79,4,5} */
+#define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE  2
+/* location: {CR78,0,7},{CR79,6,7} */
+#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE  2
+
+struct io_register {
+	u8 io_addr;
+	u8 start_bit;
+	u8 end_bit;
+};
+
+/*****************************************************
+**      Define IGA2 Shadow Display Timing         ****
+*****************************************************/
+
+/* IGA2 Shadow Horizontal Total */
+struct iga2_shadow_hor_total {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM];
+};
+
+/* IGA2 Shadow Horizontal Blank End */
+struct iga2_shadow_hor_blank_end {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Total */
+struct iga2_shadow_ver_total {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Addressable Video */
+struct iga2_shadow_ver_addr {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Blank Start */
+struct iga2_shadow_ver_blank_start {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Blank End */
+struct iga2_shadow_ver_blank_end {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Sync Start */
+struct iga2_shadow_ver_sync_start {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Sync End */
+struct iga2_shadow_ver_sync_end {
+	int reg_num;
+	struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
+};
+
+/* IGA1 Fetch Count Register */
+struct iga1_fetch_count {
+	int reg_num;
+	struct io_register reg[IGA1_FETCH_COUNT_REG_NUM];
+};
+
+/* IGA2 Fetch Count Register */
+struct iga2_fetch_count {
+	int reg_num;
+	struct io_register reg[IGA2_FETCH_COUNT_REG_NUM];
+};
+
+struct fetch_count {
+	struct iga1_fetch_count iga1_fetch_count_reg;
+	struct iga2_fetch_count iga2_fetch_count_reg;
+};
+
+/* Starting Address Register */
+struct iga1_starting_addr {
+	int reg_num;
+	struct io_register reg[IGA1_STARTING_ADDR_REG_NUM];
+};
+
+struct iga2_starting_addr {
+	int reg_num;
+	struct io_register reg[IGA2_STARTING_ADDR_REG_NUM];
+};
+
+struct starting_addr {
+	struct iga1_starting_addr iga1_starting_addr_reg;
+	struct iga2_starting_addr iga2_starting_addr_reg;
+};
+
+/* LCD Power Sequence Timer */
+struct lcd_pwd_seq_td0 {
+	int reg_num;
+	struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM];
+};
+
+struct lcd_pwd_seq_td1 {
+	int reg_num;
+	struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM];
+};
+
+struct lcd_pwd_seq_td2 {
+	int reg_num;
+	struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM];
+};
+
+struct lcd_pwd_seq_td3 {
+	int reg_num;
+	struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM];
+};
+
+struct _lcd_pwd_seq_timer {
+	struct lcd_pwd_seq_td0 td0;
+	struct lcd_pwd_seq_td1 td1;
+	struct lcd_pwd_seq_td2 td2;
+	struct lcd_pwd_seq_td3 td3;
+};
+
+/* LCD Scaling Factor */
+struct _lcd_hor_scaling_factor {
+	int reg_num;
+	struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM];
+};
+
+struct _lcd_ver_scaling_factor {
+	int reg_num;
+	struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM];
+};
+
+struct _lcd_scaling_factor {
+	struct _lcd_hor_scaling_factor lcd_hor_scaling_factor;
+	struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
+};
+
+struct pll_limit {
+	u16 multiplier_min;
+	u16 multiplier_max;
+	u8 divisor;
+	u8 rshift;
+};
+
+struct rgbLUT {
+	u8 red;
+	u8 green;
+	u8 blue;
+};
+
+struct lcd_pwd_seq_timer {
+	u16 td0;
+	u16 td1;
+	u16 td2;
+	u16 td3;
+};
+
+/* Display FIFO Relation Registers*/
+struct iga1_fifo_depth_select {
+	int reg_num;
+	struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM];
+};
+
+struct iga1_fifo_threshold_select {
+	int reg_num;
+	struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM];
+};
+
+struct iga1_fifo_high_threshold_select {
+	int reg_num;
+	struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM];
+};
+
+struct iga1_display_queue_expire_num {
+	int reg_num;
+	struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
+};
+
+struct iga2_fifo_depth_select {
+	int reg_num;
+	struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM];
+};
+
+struct iga2_fifo_threshold_select {
+	int reg_num;
+	struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM];
+};
+
+struct iga2_fifo_high_threshold_select {
+	int reg_num;
+	struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM];
+};
+
+struct iga2_display_queue_expire_num {
+	int reg_num;
+	struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
+};
+
+struct fifo_depth_select {
+	struct iga1_fifo_depth_select iga1_fifo_depth_select_reg;
+	struct iga2_fifo_depth_select iga2_fifo_depth_select_reg;
+};
+
+struct fifo_threshold_select {
+	struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg;
+	struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg;
+};
+
+struct fifo_high_threshold_select {
+	struct iga1_fifo_high_threshold_select
+	 iga1_fifo_high_threshold_select_reg;
+	struct iga2_fifo_high_threshold_select
+	 iga2_fifo_high_threshold_select_reg;
+};
+
+struct display_queue_expire_num {
+	struct iga1_display_queue_expire_num
+	 iga1_display_queue_expire_num_reg;
+	struct iga2_display_queue_expire_num
+	 iga2_display_queue_expire_num_reg;
+};
+
+struct iga2_shadow_crtc_timing {
+	struct iga2_shadow_hor_total hor_total_shadow;
+	struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
+	struct iga2_shadow_ver_total ver_total_shadow;
+	struct iga2_shadow_ver_addr ver_addr_shadow;
+	struct iga2_shadow_ver_blank_start ver_blank_start_shadow;
+	struct iga2_shadow_ver_blank_end ver_blank_end_shadow;
+	struct iga2_shadow_ver_sync_start ver_sync_start_shadow;
+	struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
+};
+
+/* device ID */
+#define CLE266_FUNCTION3    0x3123
+#define KM400_FUNCTION3     0x3205
+#define CN400_FUNCTION2     0x2259
+#define CN400_FUNCTION3     0x3259
+/* support VT3314 chipset */
+#define CN700_FUNCTION2     0x2314
+#define CN700_FUNCTION3     0x3208
+/* VT3324 chipset */
+#define CX700_FUNCTION2     0x2324
+#define CX700_FUNCTION3     0x3324
+/* VT3204 chipset*/
+#define KM800_FUNCTION3      0x3204
+/* VT3336 chipset*/
+#define KM890_FUNCTION3      0x3336
+/* VT3327 chipset*/
+#define P4M890_FUNCTION3     0x3327
+/* VT3293 chipset*/
+#define CN750_FUNCTION3     0x3208
+/* VT3364 chipset*/
+#define P4M900_FUNCTION3    0x3364
+/* VT3353 chipset*/
+#define VX800_FUNCTION3     0x3353
+/* VT3409 chipset*/
+#define VX855_FUNCTION3     0x3409
+/* VT3410 chipset*/
+#define VX900_FUNCTION3     0x3410
+
+struct IODATA {
+	u8 Index;
+	u8 Mask;
+	u8 Data;
+};
+
+struct pci_device_id_info {
+	u32 vendor;
+	u32 device;
+	u32 chip_index;
+};
+
+struct via_device_mapping {
+	u32 device;
+	const char *name;
+};
+
+extern int viafb_SAMM_ON;
+extern int viafb_dual_fb;
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+extern int viafb_hotplug;
+
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
+	u16 cxres, u16 cyres);
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
+	u16 cxres, u16 cyres, int iga);
+void viafb_set_vclock(u32 CLK, int set_iga);
+void viafb_load_reg(int timing_value, int viafb_load_reg_num,
+	struct io_register *reg,
+	      int io_type);
+void via_set_source(u32 devices, u8 iga);
+void via_set_state(u32 devices, u8 state);
+void via_set_sync_polarity(u32 devices, u8 polarity);
+u32 via_parse_odev(char *input, char **end);
+void via_odev_to_seq(struct seq_file *m, u32 odev);
+void init_ad9389(void);
+/* Access I/O Function */
+void viafb_lock_crt(void);
+void viafb_unlock_crt(void);
+void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
+void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
+void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
+void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
+					*p_gfx_dpa_setting);
+
+int viafb_setmode(void);
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+	const struct fb_videomode *mode);
+void viafb_init_chip_info(int chip_type);
+void viafb_init_dac(int set_iga);
+int viafb_get_refresh(int hres, int vres, u32 float_refresh);
+void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
+
+void viafb_set_iga_path(void);
+void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
+void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
+void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
+
+#endif /* __HW_H__ */
diff --git a/drivers/video/fbdev/via/ioctl.c b/drivers/video/fbdev/via/ioctl.c
new file mode 100644
index 000000000000..ea1c51428823
--- /dev/null
+++ b/drivers/video/fbdev/via/ioctl.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+int viafb_ioctl_get_viafb_info(u_long arg)
+{
+	struct viafb_ioctl_info viainfo;
+
+	memset(&viainfo, 0, sizeof(struct viafb_ioctl_info));
+
+	viainfo.viafb_id = VIAID;
+	viainfo.vendor_id = PCI_VIA_VENDOR_ID;
+
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_CLE266:
+		viainfo.device_id = UNICHROME_CLE266_DID;
+		break;
+
+	case UNICHROME_K400:
+		viainfo.device_id = UNICHROME_K400_DID;
+		break;
+
+	case UNICHROME_K800:
+		viainfo.device_id = UNICHROME_K800_DID;
+		break;
+
+	case UNICHROME_PM800:
+		viainfo.device_id = UNICHROME_PM800_DID;
+		break;
+
+	case UNICHROME_CN700:
+		viainfo.device_id = UNICHROME_CN700_DID;
+		break;
+
+	case UNICHROME_CX700:
+		viainfo.device_id = UNICHROME_CX700_DID;
+		break;
+
+	case UNICHROME_K8M890:
+		viainfo.device_id = UNICHROME_K8M890_DID;
+		break;
+
+	case UNICHROME_P4M890:
+		viainfo.device_id = UNICHROME_P4M890_DID;
+		break;
+
+	case UNICHROME_P4M900:
+		viainfo.device_id = UNICHROME_P4M900_DID;
+		break;
+	}
+
+	viainfo.version = VERSION_MAJOR;
+	viainfo.revision = VERSION_MINOR;
+
+	if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/* Hot-Plug Priority: DVI > CRT*/
+int viafb_ioctl_hotplug(int hres, int vres, int bpp)
+{
+	int DVIsense, status = 0;
+	DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n");
+
+	if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name !=
+		NON_TMDS_TRANSMITTER) {
+		DVIsense = viafb_dvi_sense();
+
+		if (DVIsense) {
+			DEBUG_MSG(KERN_INFO "DVI Attached...\n");
+			if (viafb_DeviceStatus != DVI_Device) {
+				viafb_DVI_ON = 1;
+				viafb_CRT_ON = 0;
+				viafb_LCD_ON = 0;
+				viafb_DeviceStatus = DVI_Device;
+				viafb_set_iga_path();
+				return viafb_DeviceStatus;
+			}
+			status = 1;
+		} else
+			DEBUG_MSG(KERN_INFO "DVI De-attached...\n");
+	}
+
+	if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) {
+		viafb_CRT_ON = 1;
+		viafb_DVI_ON = 0;
+		viafb_LCD_ON = 0;
+
+		viafb_DeviceStatus = CRT_Device;
+		viafb_set_iga_path();
+		return viafb_DeviceStatus;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/via/ioctl.h b/drivers/video/fbdev/via/ioctl.h
new file mode 100644
index 000000000000..6010d10b59e8
--- /dev/null
+++ b/drivers/video/fbdev/via/ioctl.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __IOCTL_H__
+#define __IOCTL_H__
+
+#ifndef __user
+#define __user
+#endif
+
+/* VIAFB IOCTL definition */
+#define VIAFB_GET_INFO_SIZE		0x56494101	/* 'VIA\01' */
+#define VIAFB_GET_INFO			0x56494102	/* 'VIA\02' */
+#define VIAFB_HOTPLUG			0x56494103	/* 'VIA\03' */
+#define VIAFB_SET_HOTPLUG_FLAG		0x56494104	/* 'VIA\04' */
+#define VIAFB_GET_RESOLUTION		0x56494105	/* 'VIA\05' */
+#define VIAFB_GET_SAMM_INFO		0x56494107	/* 'VIA\07' */
+#define VIAFB_TURN_ON_OUTPUT_DEVICE     0x56494108	/* 'VIA\08' */
+#define VIAFB_TURN_OFF_OUTPUT_DEVICE    0x56494109	/* 'VIA\09' */
+#define VIAFB_GET_DEVICE		0x5649410B
+#define VIAFB_GET_DRIVER_VERSION	0x56494112	/* 'VIA\12' */
+#define VIAFB_GET_CHIP_INFO		0x56494113	/* 'VIA\13' */
+#define VIAFB_GET_DEVICE_INFO           0x56494115
+
+#define VIAFB_GET_DEVICE_SUPPORT	0x56494118
+#define VIAFB_GET_DEVICE_CONNECT	0x56494119
+#define VIAFB_GET_PANEL_SUPPORT_EXPAND	0x5649411A
+#define VIAFB_GET_DRIVER_NAME		0x56494122
+#define VIAFB_GET_DEVICE_SUPPORT_STATE	0x56494123
+#define VIAFB_GET_GAMMA_LUT		0x56494124
+#define VIAFB_SET_GAMMA_LUT		0x56494125
+#define VIAFB_GET_GAMMA_SUPPORT_STATE	0x56494126
+#define VIAFB_SYNC_SURFACE		0x56494130
+#define VIAFB_GET_DRIVER_CAPS		0x56494131
+#define VIAFB_GET_IGA_SCALING_INFO	0x56494132
+#define VIAFB_GET_PANEL_MAX_SIZE	0x56494133
+#define VIAFB_GET_PANEL_MAX_POSITION	0x56494134
+#define VIAFB_SET_PANEL_SIZE		0x56494135
+#define VIAFB_SET_PANEL_POSITION        0x56494136
+#define VIAFB_GET_PANEL_POSITION        0x56494137
+#define VIAFB_GET_PANEL_SIZE		0x56494138
+
+#define None_Device 0x00
+#define CRT_Device  0x01
+#define LCD_Device  0x02
+#define DVI_Device  0x08
+#define CRT2_Device 0x10
+#define LCD2_Device 0x40
+
+#define OP_LCD_CENTERING   0x01
+#define OP_LCD_PANEL_ID    0x02
+#define OP_LCD_MODE        0x03
+
+/*SAMM operation flag*/
+#define OP_SAMM            0x80
+
+#define LCD_PANEL_ID_MAXIMUM	23
+
+#define STATE_ON            0x1
+#define STATE_OFF           0x0
+#define STATE_DEFAULT       0xFFFF
+
+#define MAX_ACTIVE_DEV_NUM  2
+
+struct device_t {
+	unsigned short crt:1;
+	unsigned short dvi:1;
+	unsigned short lcd:1;
+	unsigned short samm:1;
+	unsigned short lcd_dsp_cent:1;
+	unsigned char lcd_mode:1;
+	unsigned short epia_dvi:1;
+	unsigned short lcd_dual_edge:1;
+	unsigned short lcd2:1;
+
+	unsigned short primary_dev;
+	unsigned char lcd_panel_id;
+	unsigned short xres, yres;
+	unsigned short xres1, yres1;
+	unsigned short refresh;
+	unsigned short bpp;
+	unsigned short refresh1;
+	unsigned short bpp1;
+	unsigned short sequence;
+	unsigned short bus_width;
+};
+
+struct viafb_ioctl_info {
+	u32 viafb_id;		/* for identifying viafb */
+#define VIAID       0x56494146	/* Identify myself with 'VIAF' */
+	u16 vendor_id;
+	u16 device_id;
+	u8 version;
+	u8 revision;
+	u8 reserved[246];	/* for future use */
+};
+
+struct viafb_ioctl_mode {
+	u32 xres;
+	u32 yres;
+	u32 refresh;
+	u32 bpp;
+	u32 xres_sec;
+	u32 yres_sec;
+	u32 virtual_xres_sec;
+	u32 virtual_yres_sec;
+	u32 refresh_sec;
+	u32 bpp_sec;
+};
+struct viafb_ioctl_samm {
+	u32 samm_status;
+	u32 size_prim;
+	u32 size_sec;
+	u32 mem_base;
+	u32 offset_sec;
+};
+
+struct viafb_driver_version {
+	int iMajorNum;
+	int iKernelNum;
+	int iOSNum;
+	int iMinorNum;
+};
+
+struct viafb_ioctl_lcd_attribute {
+	unsigned int panel_id;
+	unsigned int display_center;
+	unsigned int lcd_mode;
+};
+
+struct viafb_ioctl_setting {
+	/* Enable or disable active devices */
+	unsigned short device_flag;
+	/* Indicate which device should be turn on or turn off. */
+	unsigned short device_status;
+	unsigned int reserved;
+	/* Indicate which LCD's attribute can be changed. */
+	unsigned short lcd_operation_flag;
+	/* 1: SAMM ON  0: SAMM OFF */
+	unsigned short samm_status;
+	/* horizontal resolution of first device */
+	unsigned short first_dev_hor_res;
+	/* vertical resolution of first device */
+	unsigned short first_dev_ver_res;
+	/* horizontal resolution of second device */
+	unsigned short second_dev_hor_res;
+	/* vertical resolution of second device */
+	unsigned short second_dev_ver_res;
+	/* refresh rate of first device */
+	unsigned short first_dev_refresh;
+	/* bpp of first device */
+	unsigned short first_dev_bpp;
+	/* refresh rate of second device */
+	unsigned short second_dev_refresh;
+	/* bpp of second device */
+	unsigned short second_dev_bpp;
+	/* Indicate which device are primary display device. */
+	unsigned int primary_device;
+	unsigned int struct_reserved[35];
+	struct viafb_ioctl_lcd_attribute lcd_attributes;
+};
+
+struct _UTFunctionCaps {
+	unsigned int dw3DScalingState;
+	unsigned int reserved[31];
+};
+
+struct _POSITIONVALUE {
+	unsigned int dwX;
+	unsigned int dwY;
+};
+
+struct _panel_size_pos_info {
+	unsigned int device_type;
+	int x;
+	int y;
+};
+
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+
+int viafb_ioctl_get_viafb_info(u_long arg);
+int viafb_ioctl_hotplug(int hres, int vres, int bpp);
+
+#endif /* __IOCTL_H__ */
diff --git a/drivers/video/fbdev/via/lcd.c b/drivers/video/fbdev/via/lcd.c
new file mode 100644
index 000000000000..5d21ff436ec8
--- /dev/null
+++ b/drivers/video/fbdev/via/lcd.c
@@ -0,0 +1,1005 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/via-core.h>
+#include <linux/via_i2c.h>
+#include "global.h"
+
+#define viafb_compact_res(x, y) (((x)<<16)|(y))
+
+/* CLE266 Software Power Sequence */
+/* {Mask}, {Data}, {Delay} */
+static const int PowerSequenceOn[3][3] = {
+	{0x10, 0x08, 0x06}, {0x10, 0x08, 0x06},	{0x19, 0x1FE, 0x01}
+};
+static const int PowerSequenceOff[3][3] = {
+	{0x06, 0x08, 0x10}, {0x00, 0x00, 0x00},	{0xD2, 0x19, 0x01}
+};
+
+static struct _lcd_scaling_factor lcd_scaling_factor = {
+	/* LCD Horizontal Scaling Factor Register */
+	{LCD_HOR_SCALING_FACTOR_REG_NUM,
+	 {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
+	/* LCD Vertical Scaling Factor Register */
+	{LCD_VER_SCALING_FACTOR_REG_NUM,
+	 {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
+};
+static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
+	/* LCD Horizontal Scaling Factor Register */
+	{LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
+	/* LCD Vertical Scaling Factor Register */
+	{LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
+};
+
+static bool lvds_identify_integratedlvds(void);
+static void fp_id_to_vindex(int panel_id);
+static int lvds_register_read(int index);
+static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
+		      int panel_vres);
+static void lcd_patch_skew_dvp0(struct lvds_setting_information
+			 *plvds_setting_info,
+			 struct lvds_chip_information *plvds_chip_info);
+static void lcd_patch_skew_dvp1(struct lvds_setting_information
+			 *plvds_setting_info,
+			 struct lvds_chip_information *plvds_chip_info);
+static void lcd_patch_skew(struct lvds_setting_information
+	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+
+static void integrated_lvds_disable(struct lvds_setting_information
+			     *plvds_setting_info,
+			     struct lvds_chip_information *plvds_chip_info);
+static void integrated_lvds_enable(struct lvds_setting_information
+			    *plvds_setting_info,
+			    struct lvds_chip_information *plvds_chip_info);
+static void lcd_powersequence_off(void);
+static void lcd_powersequence_on(void);
+static void fill_lcd_format(void);
+static void check_diport_of_integrated_lvds(
+	struct lvds_chip_information *plvds_chip_info,
+				     struct lvds_setting_information
+				     *plvds_setting_info);
+
+static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
+{
+	return lvds_register_read(device_id_subaddr) == device_id;
+}
+
+void viafb_init_lcd_size(void)
+{
+	DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
+
+	fp_id_to_vindex(viafb_lcd_panel_id);
+	viaparinfo->lvds_setting_info2->lcd_panel_hres =
+		viaparinfo->lvds_setting_info->lcd_panel_hres;
+	viaparinfo->lvds_setting_info2->lcd_panel_vres =
+		viaparinfo->lvds_setting_info->lcd_panel_vres;
+	viaparinfo->lvds_setting_info2->device_lcd_dualedge =
+	    viaparinfo->lvds_setting_info->device_lcd_dualedge;
+	viaparinfo->lvds_setting_info2->LCDDithering =
+		viaparinfo->lvds_setting_info->LCDDithering;
+}
+
+static bool lvds_identify_integratedlvds(void)
+{
+	if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
+		/* Two dual channel LCD (Internal LVDS + External LVDS): */
+		/* If we have an external LVDS, such as VT1636, we should
+		   have its chip ID already. */
+		if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
+			    INTEGRATED_LVDS;
+			DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
+				  "(Internal LVDS + External LVDS)\n");
+		} else {
+			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+			    INTEGRATED_LVDS;
+			DEBUG_MSG(KERN_INFO "Not found external LVDS, "
+				  "so can't support two dual channel LVDS!\n");
+		}
+	} else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
+		/* Two single channel LCD (Internal LVDS + Internal LVDS): */
+		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+		INTEGRATED_LVDS;
+		viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
+			INTEGRATED_LVDS;
+		DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
+			  "(Internal LVDS + Internal LVDS)\n");
+	} else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
+		/* If we have found external LVDS, just use it,
+		   otherwise, we will use internal LVDS as default. */
+		if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+			    INTEGRATED_LVDS;
+			DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
+		}
+	} else {
+		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+			NON_LVDS_TRANSMITTER;
+		DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
+		return false;
+	}
+
+	return true;
+}
+
+bool viafb_lvds_trasmitter_identify(void)
+{
+	if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
+		viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
+		DEBUG_MSG(KERN_INFO
+			  "Found VIA VT1636 LVDS on port i2c 0x31\n");
+	} else {
+		if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {
+			viaparinfo->chip_info->lvds_chip_info.i2c_port =
+				VIA_PORT_2C;
+			DEBUG_MSG(KERN_INFO
+				  "Found VIA VT1636 LVDS on port gpio 0x2c\n");
+		}
+	}
+
+	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
+		lvds_identify_integratedlvds();
+
+	if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+		return true;
+	/* Check for VT1631: */
+	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
+	viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+		VT1631_LVDS_I2C_ADDR;
+
+	if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) {
+		DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
+		DEBUG_MSG(KERN_INFO "\n %2d",
+			  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+		DEBUG_MSG(KERN_INFO "\n %2d",
+			  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+		return true;
+	}
+
+	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+		NON_LVDS_TRANSMITTER;
+	viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+		VT1631_LVDS_I2C_ADDR;
+	return false;
+}
+
+static void fp_id_to_vindex(int panel_id)
+{
+	DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
+
+	if (panel_id > LCD_PANEL_ID_MAXIMUM)
+		viafb_lcd_panel_id = panel_id =
+		viafb_read_reg(VIACR, CR3F) & 0x0F;
+
+	switch (panel_id) {
+	case 0x0:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x1:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x2:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x3:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x4:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x5:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x6:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x8:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x9:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0xA:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0xB:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0xC:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0xD:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0xE:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0xF:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0x10:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0x11:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x12:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x13:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x14:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0x15:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	case 0x16:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+		break;
+	case 0x17:
+		/* OLPC XO-1.5 panel */
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 0;
+		break;
+	default:
+		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+		viaparinfo->lvds_setting_info->LCDDithering = 1;
+	}
+}
+
+static int lvds_register_read(int index)
+{
+	u8 data;
+
+	viafb_i2c_readbyte(VIA_PORT_2C,
+			(u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
+			(u8) index, &data);
+	return data;
+}
+
+static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
+		      int panel_vres)
+{
+	int reg_value = 0;
+	int viafb_load_reg_num;
+	struct io_register *reg = NULL;
+
+	DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
+
+	/* LCD Scaling Enable */
+	viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
+
+	/* Check if expansion for horizontal */
+	if (set_hres < panel_hres) {
+		/* Load Horizontal Scaling Factor */
+		switch (viaparinfo->chip_info->gfx_chip_name) {
+		case UNICHROME_CLE266:
+		case UNICHROME_K400:
+			reg_value =
+			    CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+			viafb_load_reg_num =
+			    lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
+			    reg_num;
+			reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
+			viafb_load_reg(reg_value,
+				viafb_load_reg_num, reg, VIACR);
+			break;
+		case UNICHROME_K800:
+		case UNICHROME_PM800:
+		case UNICHROME_CN700:
+		case UNICHROME_CX700:
+		case UNICHROME_K8M890:
+		case UNICHROME_P4M890:
+		case UNICHROME_P4M900:
+		case UNICHROME_CN750:
+		case UNICHROME_VX800:
+		case UNICHROME_VX855:
+		case UNICHROME_VX900:
+			reg_value =
+			    K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+			/* Horizontal scaling enabled */
+			viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
+			viafb_load_reg_num =
+			    lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
+			reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
+			viafb_load_reg(reg_value,
+				viafb_load_reg_num, reg, VIACR);
+			break;
+		}
+
+		DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
+	} else {
+		/* Horizontal scaling disabled */
+		viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
+	}
+
+	/* Check if expansion for vertical */
+	if (set_vres < panel_vres) {
+		/* Load Vertical Scaling Factor */
+		switch (viaparinfo->chip_info->gfx_chip_name) {
+		case UNICHROME_CLE266:
+		case UNICHROME_K400:
+			reg_value =
+			    CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+			viafb_load_reg_num =
+			    lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
+			    reg_num;
+			reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
+			viafb_load_reg(reg_value,
+				viafb_load_reg_num, reg, VIACR);
+			break;
+		case UNICHROME_K800:
+		case UNICHROME_PM800:
+		case UNICHROME_CN700:
+		case UNICHROME_CX700:
+		case UNICHROME_K8M890:
+		case UNICHROME_P4M890:
+		case UNICHROME_P4M900:
+		case UNICHROME_CN750:
+		case UNICHROME_VX800:
+		case UNICHROME_VX855:
+		case UNICHROME_VX900:
+			reg_value =
+			    K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+			/* Vertical scaling enabled */
+			viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
+			viafb_load_reg_num =
+			    lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
+			reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
+			viafb_load_reg(reg_value,
+				viafb_load_reg_num, reg, VIACR);
+			break;
+		}
+
+		DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
+	} else {
+		/* Vertical scaling disabled */
+		viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
+	}
+}
+
+static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp)
+{
+	unsigned char cr13, cr35, cr65, cr66, cr67;
+	unsigned long dwScreenPitch = 0;
+	unsigned long dwPitch;
+
+	dwPitch = hres * (bpp >> 3);
+	if (dwPitch & 0x1F) {
+		dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
+		if (iga_path == IGA2) {
+			if (bpp > 8) {
+				cr66 = (unsigned char)(dwScreenPitch & 0xFF);
+				viafb_write_reg(CR66, VIACR, cr66);
+				cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
+				cr67 |=
+				    (unsigned
+				     char)((dwScreenPitch & 0x300) >> 8);
+				viafb_write_reg(CR67, VIACR, cr67);
+			}
+
+			/* Fetch Count */
+			cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
+			cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
+			viafb_write_reg(CR67, VIACR, cr67);
+			cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
+			cr65 += 2;
+			viafb_write_reg(CR65, VIACR, cr65);
+		} else {
+			if (bpp > 8) {
+				cr13 = (unsigned char)(dwScreenPitch & 0xFF);
+				viafb_write_reg(CR13, VIACR, cr13);
+				cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
+				cr35 |=
+				    (unsigned
+				     char)((dwScreenPitch & 0x700) >> 3);
+				viafb_write_reg(CR35, VIACR, cr35);
+			}
+		}
+	}
+}
+static void lcd_patch_skew_dvp0(struct lvds_setting_information
+			 *plvds_setting_info,
+			 struct lvds_chip_information *plvds_chip_info)
+{
+	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
+		switch (viaparinfo->chip_info->gfx_chip_name) {
+		case UNICHROME_P4M900:
+			viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
+						    plvds_chip_info);
+			break;
+		case UNICHROME_P4M890:
+			viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
+						    plvds_chip_info);
+			break;
+		}
+	}
+}
+static void lcd_patch_skew_dvp1(struct lvds_setting_information
+			 *plvds_setting_info,
+			 struct lvds_chip_information *plvds_chip_info)
+{
+	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
+		switch (viaparinfo->chip_info->gfx_chip_name) {
+		case UNICHROME_CX700:
+			viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
+						    plvds_chip_info);
+			break;
+		}
+	}
+}
+static void lcd_patch_skew(struct lvds_setting_information
+	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
+{
+	DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
+	switch (plvds_chip_info->output_interface) {
+	case INTERFACE_DVP0:
+		lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
+		break;
+	case INTERFACE_DVP1:
+		lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
+		break;
+	case INTERFACE_DFP_LOW:
+		if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
+			viafb_write_reg_mask(CR99, VIACR, 0x08,
+				       BIT0 + BIT1 + BIT2 + BIT3);
+		}
+		break;
+	}
+}
+
+/* LCD Set Mode */
+void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
+	u16 cyres, struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info)
+{
+	int set_iga = plvds_setting_info->iga_path;
+	int mode_bpp = var->bits_per_pixel;
+	int set_hres = cxres ? cxres : var->xres;
+	int set_vres = cyres ? cyres : var->yres;
+	int panel_hres = plvds_setting_info->lcd_panel_hres;
+	int panel_vres = plvds_setting_info->lcd_panel_vres;
+	u32 clock;
+	struct via_display_timing timing;
+	struct fb_var_screeninfo panel_var;
+	const struct fb_videomode *mode_crt_table, *panel_crt_table;
+
+	DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
+	/* Get mode table */
+	mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
+	/* Get panel table Pointer */
+	panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
+	viafb_fill_var_timing_info(&panel_var, panel_crt_table);
+	DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
+	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
+		viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
+	clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000;
+	plvds_setting_info->vclk = clock;
+
+	if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
+		&& plvds_setting_info->display_method == LCD_EXPANDSION) {
+		timing = var_to_timing(&panel_var, panel_hres, panel_vres);
+		load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
+	} else {
+		timing = var_to_timing(&panel_var, set_hres, set_vres);
+		if (set_iga == IGA2)
+			/* disable scaling */
+			via_write_reg_mask(VIACR, 0x79, 0x00,
+				BIT0 + BIT1 + BIT2);
+	}
+
+	if (set_iga == IGA1)
+		via_set_primary_timing(&timing);
+	else if (set_iga == IGA2)
+		via_set_secondary_timing(&timing);
+
+	/* Fetch count for IGA2 only */
+	viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
+
+	if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+		&& (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
+		viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
+
+	fill_lcd_format();
+	viafb_set_vclock(clock, set_iga);
+	lcd_patch_skew(plvds_setting_info, plvds_chip_info);
+
+	/* If K8M800, enable LCD Prefetch Mode. */
+	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
+	    || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
+		viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
+
+	/* Patch for non 32bit alignment mode */
+	via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres,
+		var->bits_per_pixel);
+}
+
+static void integrated_lvds_disable(struct lvds_setting_information
+			     *plvds_setting_info,
+			     struct lvds_chip_information *plvds_chip_info)
+{
+	bool turn_off_first_powersequence = false;
+	bool turn_off_second_powersequence = false;
+	if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
+		turn_off_first_powersequence = true;
+	if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
+		turn_off_first_powersequence = true;
+	if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
+		turn_off_second_powersequence = true;
+	if (turn_off_second_powersequence) {
+		/* Use second power sequence control: */
+
+		/* Turn off power sequence. */
+		viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
+
+		/* Turn off back light. */
+		viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
+	}
+	if (turn_off_first_powersequence) {
+		/* Use first power sequence control: */
+
+		/* Turn off power sequence. */
+		viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
+
+		/* Turn off back light. */
+		viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
+	}
+
+	/* Power off LVDS channel. */
+	switch (plvds_chip_info->output_interface) {
+	case INTERFACE_LVDS0:
+		{
+			viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
+			break;
+		}
+
+	case INTERFACE_LVDS1:
+		{
+			viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
+			break;
+		}
+
+	case INTERFACE_LVDS0LVDS1:
+		{
+			viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
+			break;
+		}
+	}
+}
+
+static void integrated_lvds_enable(struct lvds_setting_information
+			    *plvds_setting_info,
+			    struct lvds_chip_information *plvds_chip_info)
+{
+	DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
+		  plvds_chip_info->output_interface);
+	if (plvds_setting_info->lcd_mode == LCD_SPWG)
+		viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
+	else
+		viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
+
+	switch (plvds_chip_info->output_interface) {
+	case INTERFACE_LVDS0LVDS1:
+	case INTERFACE_LVDS0:
+		/* Use first power sequence control: */
+		/* Use hardware control power sequence. */
+		viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
+		/* Turn on back light. */
+		viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
+		/* Turn on hardware power sequence. */
+		viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+		break;
+	case INTERFACE_LVDS1:
+		/* Use second power sequence control: */
+		/* Use hardware control power sequence. */
+		viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
+		/* Turn on back light. */
+		viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
+		/* Turn on hardware power sequence. */
+		viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
+		break;
+	}
+
+	/* Power on LVDS channel. */
+	switch (plvds_chip_info->output_interface) {
+	case INTERFACE_LVDS0:
+		{
+			viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
+			break;
+		}
+
+	case INTERFACE_LVDS1:
+		{
+			viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
+			break;
+		}
+
+	case INTERFACE_LVDS0LVDS1:
+		{
+			viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
+			break;
+		}
+	}
+}
+
+void viafb_lcd_disable(void)
+{
+
+	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+		lcd_powersequence_off();
+		/* DI1 pad off */
+		viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
+	} else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+		if (viafb_LCD2_ON
+		    && (INTEGRATED_LVDS ==
+			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
+			integrated_lvds_disable(viaparinfo->lvds_setting_info,
+				&viaparinfo->chip_info->lvds_chip_info2);
+		if (INTEGRATED_LVDS ==
+			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+			integrated_lvds_disable(viaparinfo->lvds_setting_info,
+				&viaparinfo->chip_info->lvds_chip_info);
+		if (VT1636_LVDS == viaparinfo->chip_info->
+			lvds_chip_info.lvds_chip_name)
+			viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
+				&viaparinfo->chip_info->lvds_chip_info);
+	} else if (VT1636_LVDS ==
+	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+		viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
+				    &viaparinfo->chip_info->lvds_chip_info);
+	} else {
+		/* Backlight off           */
+		viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
+		/* 24 bit DI data paht off */
+		viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
+	}
+
+	/* Disable expansion bit   */
+	viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
+	/* Simultaneout disabled   */
+	viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
+}
+
+static void set_lcd_output_path(int set_iga, int output_interface)
+{
+	switch (output_interface) {
+	case INTERFACE_DFP:
+		if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
+		    || (UNICHROME_P4M890 ==
+		    viaparinfo->chip_info->gfx_chip_name))
+			viafb_write_reg_mask(CR97, VIACR, 0x84,
+				       BIT7 + BIT2 + BIT1 + BIT0);
+	case INTERFACE_DVP0:
+	case INTERFACE_DVP1:
+	case INTERFACE_DFP_HIGH:
+	case INTERFACE_DFP_LOW:
+		if (set_iga == IGA2)
+			viafb_write_reg(CR91, VIACR, 0x00);
+		break;
+	}
+}
+
+void viafb_lcd_enable(void)
+{
+	viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
+	viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+	set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path,
+		viaparinfo->chip_info->lvds_chip_info.output_interface);
+	if (viafb_LCD2_ON)
+		set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path,
+			viaparinfo->chip_info->
+			lvds_chip_info2.output_interface);
+
+	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+		/* DI1 pad on */
+		viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
+		lcd_powersequence_on();
+	} else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+		if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
+			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
+			integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
+				&viaparinfo->chip_info->lvds_chip_info2);
+		if (INTEGRATED_LVDS ==
+			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+			integrated_lvds_enable(viaparinfo->lvds_setting_info,
+				&viaparinfo->chip_info->lvds_chip_info);
+		if (VT1636_LVDS == viaparinfo->chip_info->
+			lvds_chip_info.lvds_chip_name)
+			viafb_enable_lvds_vt1636(viaparinfo->
+			lvds_setting_info, &viaparinfo->chip_info->
+			lvds_chip_info);
+	} else if (VT1636_LVDS ==
+	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+		viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
+				   &viaparinfo->chip_info->lvds_chip_info);
+	} else {
+		/* Backlight on            */
+		viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
+		/* 24 bit DI data paht on  */
+		viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
+		/* LCD enabled             */
+		viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
+	}
+}
+
+static void lcd_powersequence_off(void)
+{
+	int i, mask, data;
+
+	/* Software control power sequence */
+	viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
+
+	for (i = 0; i < 3; i++) {
+		mask = PowerSequenceOff[0][i];
+		data = PowerSequenceOff[1][i] & mask;
+		viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
+		udelay(PowerSequenceOff[2][i]);
+	}
+
+	/* Disable LCD */
+	viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
+}
+
+static void lcd_powersequence_on(void)
+{
+	int i, mask, data;
+
+	/* Software control power sequence */
+	viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
+
+	/* Enable LCD */
+	viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
+
+	for (i = 0; i < 3; i++) {
+		mask = PowerSequenceOn[0][i];
+		data = PowerSequenceOn[1][i] & mask;
+		viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
+		udelay(PowerSequenceOn[2][i]);
+	}
+
+	udelay(1);
+}
+
+static void fill_lcd_format(void)
+{
+	u8 bdithering = 0, bdual = 0;
+
+	if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
+		bdual = BIT4;
+	if (viaparinfo->lvds_setting_info->LCDDithering)
+		bdithering = BIT0;
+	/* Dual & Dithering */
+	viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
+}
+
+static void check_diport_of_integrated_lvds(
+	struct lvds_chip_information *plvds_chip_info,
+				     struct lvds_setting_information
+				     *plvds_setting_info)
+{
+	/* Determine LCD DI Port by hardware layout. */
+	switch (viafb_display_hardware_layout) {
+	case HW_LAYOUT_LCD_ONLY:
+		{
+			if (plvds_setting_info->device_lcd_dualedge) {
+				plvds_chip_info->output_interface =
+				    INTERFACE_LVDS0LVDS1;
+			} else {
+				plvds_chip_info->output_interface =
+				    INTERFACE_LVDS0;
+			}
+
+			break;
+		}
+
+	case HW_LAYOUT_DVI_ONLY:
+		{
+			plvds_chip_info->output_interface = INTERFACE_NONE;
+			break;
+		}
+
+	case HW_LAYOUT_LCD1_LCD2:
+	case HW_LAYOUT_LCD_EXTERNAL_LCD2:
+		{
+			plvds_chip_info->output_interface =
+			    INTERFACE_LVDS0LVDS1;
+			break;
+		}
+
+	case HW_LAYOUT_LCD_DVI:
+		{
+			plvds_chip_info->output_interface = INTERFACE_LVDS1;
+			break;
+		}
+
+	default:
+		{
+			plvds_chip_info->output_interface = INTERFACE_LVDS1;
+			break;
+		}
+	}
+
+	DEBUG_MSG(KERN_INFO
+		  "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
+		  viafb_display_hardware_layout,
+		  plvds_chip_info->output_interface);
+}
+
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+				*plvds_chip_info,
+				struct lvds_setting_information
+				*plvds_setting_info)
+{
+	if (INTERFACE_NONE != plvds_chip_info->output_interface) {
+		/*Do nothing, lcd port is specified by module parameter */
+		return;
+	}
+
+	switch (plvds_chip_info->lvds_chip_name) {
+
+	case VT1636_LVDS:
+		switch (viaparinfo->chip_info->gfx_chip_name) {
+		case UNICHROME_CX700:
+			plvds_chip_info->output_interface = INTERFACE_DVP1;
+			break;
+		case UNICHROME_CN700:
+			plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
+			break;
+		default:
+			plvds_chip_info->output_interface = INTERFACE_DVP0;
+			break;
+		}
+		break;
+
+	case INTEGRATED_LVDS:
+		check_diport_of_integrated_lvds(plvds_chip_info,
+						plvds_setting_info);
+		break;
+
+	default:
+		switch (viaparinfo->chip_info->gfx_chip_name) {
+		case UNICHROME_K8M890:
+		case UNICHROME_P4M900:
+		case UNICHROME_P4M890:
+			plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
+			break;
+		default:
+			plvds_chip_info->output_interface = INTERFACE_DFP;
+			break;
+		}
+		break;
+	}
+}
+
+bool viafb_lcd_get_mobile_state(bool *mobile)
+{
+	unsigned char __iomem *romptr, *tableptr, *biosptr;
+	u8 core_base;
+	/* Rom address */
+	const u32 romaddr = 0x000C0000;
+	u16 start_pattern;
+
+	biosptr = ioremap(romaddr, 0x10000);
+	start_pattern = readw(biosptr);
+
+	/* Compare pattern */
+	if (start_pattern == 0xAA55) {
+		/* Get the start of Table */
+		/* 0x1B means BIOS offset position */
+		romptr = biosptr + 0x1B;
+		tableptr = biosptr + readw(romptr);
+
+		/* Get the start of biosver structure */
+		/* 18 means BIOS version position. */
+		romptr = tableptr + 18;
+		romptr = biosptr + readw(romptr);
+
+		/* The offset should be 44, but the
+		   actual image is less three char. */
+		/* pRom += 44; */
+		romptr += 41;
+
+		core_base = readb(romptr);
+
+		if (core_base & 0x8)
+			*mobile = false;
+		else
+			*mobile = true;
+		/* release memory */
+		iounmap(biosptr);
+
+		return true;
+	} else {
+		iounmap(biosptr);
+		return false;
+	}
+}
diff --git a/drivers/video/fbdev/via/lcd.h b/drivers/video/fbdev/via/lcd.h
new file mode 100644
index 000000000000..5c988a063ad5
--- /dev/null
+++ b/drivers/video/fbdev/via/lcd.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __LCD_H__
+#define __LCD_H__
+
+/*Definition TMDS Device ID register*/
+#define     VT1631_DEVICE_ID_REG        0x02
+#define     VT1631_DEVICE_ID            0x92
+
+#define     VT3271_DEVICE_ID_REG        0x02
+#define     VT3271_DEVICE_ID            0x71
+
+/* Definition DVI Panel ID*/
+/* Resolution: 640x480,   Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID0_640X480       0x00
+/* Resolution: 800x600,   Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID1_800X600       0x01
+/* Resolution: 1024x768,  Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID2_1024X768      0x02
+/* Resolution: 1280x768,  Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID3_1280X768      0x03
+/* Resolution: 1280x1024, Channel: dual,   Dithering: Enable */
+#define     LCD_PANEL_ID4_1280X1024     0x04
+/* Resolution: 1400x1050, Channel: dual,   Dithering: Enable */
+#define     LCD_PANEL_ID5_1400X1050     0x05
+/* Resolution: 1600x1200, Channel: dual,   Dithering: Enable */
+#define     LCD_PANEL_ID6_1600X1200     0x06
+/* Resolution: 1366x768,  Channel: single, Dithering: Disable */
+#define     LCD_PANEL_ID7_1366X768      0x07
+/* Resolution: 1024x600,  Channel: single, Dithering: Enable*/
+#define     LCD_PANEL_ID8_1024X600      0x08
+/* Resolution: 1280x800,  Channel: single, Dithering: Enable*/
+#define     LCD_PANEL_ID9_1280X800      0x09
+/* Resolution: 800x480,   Channel: single, Dithering: Enable*/
+#define     LCD_PANEL_IDA_800X480       0x0A
+/* Resolution: 1360x768,   Channel: single, Dithering: Disable*/
+#define     LCD_PANEL_IDB_1360X768     0x0B
+/* Resolution: 480x640,  Channel: single, Dithering: Enable */
+#define     LCD_PANEL_IDC_480X640      0x0C
+/* Resolution: 1200x900,  Channel: single, Dithering: Disable */
+#define     LCD_PANEL_IDD_1200X900      0x0D
+
+
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+			 *plvds_setting_info,
+			 struct lvds_chip_information *plvds_chip_info);
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+			*plvds_setting_info,
+			struct lvds_chip_information *plvds_chip_info);
+void viafb_lcd_disable(void);
+void viafb_lcd_enable(void);
+void viafb_init_lcd_size(void);
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+				*plvds_chip_info,
+				struct lvds_setting_information
+				*plvds_setting_info);
+void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
+	u16 cyres, struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info);
+bool viafb_lvds_trasmitter_identify(void);
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+				*plvds_chip_info,
+				struct lvds_setting_information
+				*plvds_setting_info);
+bool viafb_lcd_get_mobile_state(bool *mobile);
+
+#endif /* __LCD_H__ */
diff --git a/drivers/video/fbdev/via/share.h b/drivers/video/fbdev/via/share.h
new file mode 100644
index 000000000000..65c65c611e0a
--- /dev/null
+++ b/drivers/video/fbdev/via/share.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SHARE_H__
+#define __SHARE_H__
+
+#include "via_modesetting.h"
+
+/* Define Bit Field */
+#define BIT0    0x01
+#define BIT1    0x02
+#define BIT2    0x04
+#define BIT3    0x08
+#define BIT4    0x10
+#define BIT5    0x20
+#define BIT6    0x40
+#define BIT7    0x80
+
+/* Video Memory Size */
+#define VIDEO_MEMORY_SIZE_16M    0x1000000
+
+/*
+ * Lengths of the VPIT structure arrays.
+ */
+#define StdCR       0x19
+#define StdSR       0x04
+#define StdGR       0x09
+#define StdAR       0x14
+
+#define PatchCR     11
+
+/* Display path */
+#define IGA1        1
+#define IGA2        2
+
+/* Define Color Depth  */
+#define MODE_8BPP       1
+#define MODE_16BPP      2
+#define MODE_32BPP      4
+
+#define GR20    0x20
+#define GR21    0x21
+#define GR22    0x22
+
+/* Sequencer Registers */
+#define SR01    0x01
+#define SR10    0x10
+#define SR12    0x12
+#define SR15    0x15
+#define SR16    0x16
+#define SR17    0x17
+#define SR18    0x18
+#define SR1B    0x1B
+#define SR1A    0x1A
+#define SR1C    0x1C
+#define SR1D    0x1D
+#define SR1E    0x1E
+#define SR1F    0x1F
+#define SR20    0x20
+#define SR21    0x21
+#define SR22    0x22
+#define SR2A    0x2A
+#define SR2D    0x2D
+#define SR2E    0x2E
+
+#define SR30    0x30
+#define SR39    0x39
+#define SR3D    0x3D
+#define SR3E    0x3E
+#define SR3F    0x3F
+#define SR40    0x40
+#define SR43    0x43
+#define SR44    0x44
+#define SR45    0x45
+#define SR46    0x46
+#define SR47    0x47
+#define SR48    0x48
+#define SR49    0x49
+#define SR4A    0x4A
+#define SR4B    0x4B
+#define SR4C    0x4C
+#define SR52    0x52
+#define SR57	0x57
+#define SR58	0x58
+#define SR59	0x59
+#define SR5D    0x5D
+#define SR5E    0x5E
+#define SR65    0x65
+
+/* CRT Controller Registers */
+#define CR00    0x00
+#define CR01    0x01
+#define CR02    0x02
+#define CR03    0x03
+#define CR04    0x04
+#define CR05    0x05
+#define CR06    0x06
+#define CR07    0x07
+#define CR08    0x08
+#define CR09    0x09
+#define CR0A    0x0A
+#define CR0B    0x0B
+#define CR0C    0x0C
+#define CR0D    0x0D
+#define CR0E    0x0E
+#define CR0F    0x0F
+#define CR10    0x10
+#define CR11    0x11
+#define CR12    0x12
+#define CR13    0x13
+#define CR14    0x14
+#define CR15    0x15
+#define CR16    0x16
+#define CR17    0x17
+#define CR18    0x18
+
+/* Extend CRT Controller Registers */
+#define CR30    0x30
+#define CR31    0x31
+#define CR32    0x32
+#define CR33    0x33
+#define CR34    0x34
+#define CR35    0x35
+#define CR36    0x36
+#define CR37    0x37
+#define CR38    0x38
+#define CR39    0x39
+#define CR3A    0x3A
+#define CR3B    0x3B
+#define CR3C    0x3C
+#define CR3D    0x3D
+#define CR3E    0x3E
+#define CR3F    0x3F
+#define CR40    0x40
+#define CR41    0x41
+#define CR42    0x42
+#define CR43    0x43
+#define CR44    0x44
+#define CR45    0x45
+#define CR46    0x46
+#define CR47    0x47
+#define CR48    0x48
+#define CR49    0x49
+#define CR4A    0x4A
+#define CR4B    0x4B
+#define CR4C    0x4C
+#define CR4D    0x4D
+#define CR4E    0x4E
+#define CR4F    0x4F
+#define CR50    0x50
+#define CR51    0x51
+#define CR52    0x52
+#define CR53    0x53
+#define CR54    0x54
+#define CR55    0x55
+#define CR56    0x56
+#define CR57    0x57
+#define CR58    0x58
+#define CR59    0x59
+#define CR5A    0x5A
+#define CR5B    0x5B
+#define CR5C    0x5C
+#define CR5D    0x5D
+#define CR5E    0x5E
+#define CR5F    0x5F
+#define CR60    0x60
+#define CR61    0x61
+#define CR62    0x62
+#define CR63    0x63
+#define CR64    0x64
+#define CR65    0x65
+#define CR66    0x66
+#define CR67    0x67
+#define CR68    0x68
+#define CR69    0x69
+#define CR6A    0x6A
+#define CR6B    0x6B
+#define CR6C    0x6C
+#define CR6D    0x6D
+#define CR6E    0x6E
+#define CR6F    0x6F
+#define CR70    0x70
+#define CR71    0x71
+#define CR72    0x72
+#define CR73    0x73
+#define CR74    0x74
+#define CR75    0x75
+#define CR76    0x76
+#define CR77    0x77
+#define CR78    0x78
+#define CR79    0x79
+#define CR7A    0x7A
+#define CR7B    0x7B
+#define CR7C    0x7C
+#define CR7D    0x7D
+#define CR7E    0x7E
+#define CR7F    0x7F
+#define CR80    0x80
+#define CR81    0x81
+#define CR82    0x82
+#define CR83    0x83
+#define CR84    0x84
+#define CR85    0x85
+#define CR86    0x86
+#define CR87    0x87
+#define CR88    0x88
+#define CR89    0x89
+#define CR8A    0x8A
+#define CR8B    0x8B
+#define CR8C    0x8C
+#define CR8D    0x8D
+#define CR8E    0x8E
+#define CR8F    0x8F
+#define CR90    0x90
+#define CR91    0x91
+#define CR92    0x92
+#define CR93    0x93
+#define CR94    0x94
+#define CR95    0x95
+#define CR96    0x96
+#define CR97    0x97
+#define CR98    0x98
+#define CR99    0x99
+#define CR9A    0x9A
+#define CR9B    0x9B
+#define CR9C    0x9C
+#define CR9D    0x9D
+#define CR9E    0x9E
+#define CR9F    0x9F
+#define CRA0    0xA0
+#define CRA1    0xA1
+#define CRA2    0xA2
+#define CRA3    0xA3
+#define CRD2    0xD2
+#define CRD3    0xD3
+#define CRD4    0xD4
+
+/* LUT Table*/
+#define LUT_DATA             0x3C9	/* DACDATA */
+#define LUT_INDEX_READ       0x3C7	/* DACRX */
+#define LUT_INDEX_WRITE      0x3C8	/* DACWX */
+#define DACMASK              0x3C6
+
+/* Definition Device */
+#define DEVICE_CRT  0x01
+#define DEVICE_DVI  0x03
+#define DEVICE_LCD  0x04
+
+/* Device output interface */
+#define INTERFACE_NONE          0x00
+#define INTERFACE_ANALOG_RGB    0x01
+#define INTERFACE_DVP0          0x02
+#define INTERFACE_DVP1          0x03
+#define INTERFACE_DFP_HIGH      0x04
+#define INTERFACE_DFP_LOW       0x05
+#define INTERFACE_DFP           0x06
+#define INTERFACE_LVDS0         0x07
+#define INTERFACE_LVDS1         0x08
+#define INTERFACE_LVDS0LVDS1    0x09
+#define INTERFACE_TMDS          0x0A
+
+#define HW_LAYOUT_LCD_ONLY      0x01
+#define HW_LAYOUT_DVI_ONLY      0x02
+#define HW_LAYOUT_LCD_DVI       0x03
+#define HW_LAYOUT_LCD1_LCD2     0x04
+#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
+
+/* Definition CRTC Timing Index */
+#define H_TOTAL_INDEX               0
+#define H_ADDR_INDEX                1
+#define H_BLANK_START_INDEX         2
+#define H_BLANK_END_INDEX           3
+#define H_SYNC_START_INDEX          4
+#define H_SYNC_END_INDEX            5
+#define V_TOTAL_INDEX               6
+#define V_ADDR_INDEX                7
+#define V_BLANK_START_INDEX         8
+#define V_BLANK_END_INDEX           9
+#define V_SYNC_START_INDEX          10
+#define V_SYNC_END_INDEX            11
+#define H_TOTAL_SHADOW_INDEX        12
+#define H_BLANK_END_SHADOW_INDEX    13
+#define V_TOTAL_SHADOW_INDEX        14
+#define V_ADDR_SHADOW_INDEX         15
+#define V_BLANK_SATRT_SHADOW_INDEX  16
+#define V_BLANK_END_SHADOW_INDEX    17
+#define V_SYNC_SATRT_SHADOW_INDEX   18
+#define V_SYNC_END_SHADOW_INDEX     19
+
+/* LCD display method
+*/
+#define     LCD_EXPANDSION              0x00
+#define     LCD_CENTERING               0x01
+
+/* LCD mode
+*/
+#define     LCD_OPENLDI               0x00
+#define     LCD_SPWG                  0x01
+
+struct crt_mode_table {
+	int refresh_rate;
+	int h_sync_polarity;
+	int v_sync_polarity;
+	struct via_display_timing crtc;
+};
+
+struct io_reg {
+	int port;
+	u8 index;
+	u8 mask;
+	u8 value;
+};
+
+#endif /* __SHARE_H__ */
diff --git a/drivers/video/fbdev/via/tblDPASetting.c b/drivers/video/fbdev/via/tblDPASetting.c
new file mode 100644
index 000000000000..73bb554e7c1e
--- /dev/null
+++ b/drivers/video/fbdev/via/tblDPASetting.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "global.h"
+
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
+/*  ClkRange, DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
+					DVP1Driving, DFPHigh, DFPLow */
+/*  CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+					SR65,        CR97,    CR99   */
+	/* LCK/VCK < 30000000 will use this value */
+	{DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+	 0x00},
+	/* 30000000 < LCK/VCK < 50000000 will use this value */
+	{DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+	 0x00},
+	/* 50000000 < LCK/VCK < 70000000 will use this value */
+	{DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	 0x00},
+	/* 70000000 < LCK/VCK < 100000000 will use this value */
+	{DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	 0x00},
+	/* 100000000 < LCK/VCK < 15000000 will use this value */
+	{DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	 0x00},
+	/* 15000000 < LCK/VCK will use this value */
+	{DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00,
+	 0x00},
+};
+
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
+/*  ClkRange,DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
+					DVP1Driving, DFPHigh,   DFPLow */
+/*   CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+					SR65,        CR97,      CR99   */
+/* LCK/VCK < 30000000 will use this value */
+{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 30000000 < LCK/VCK < 50000000 will use this value */
+{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 50000000 < LCK/VCK < 70000000 will use this value */
+{DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 70000000 < LCK/VCK < 100000000 will use this value */
+{DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03},
+/* 100000000 < LCK/VCK < 15000000 will use this value */
+{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02},
+/* 15000000 < LCK/VCK will use this value */
+{DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03},
+};
+
+/* For VT3364: */
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = {
+/*  ClkRange,DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
+					DVP1Driving, DFPHigh,   DFPLow */
+/*   CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+					SR65,        CR97,      CR99   */
+/* LCK/VCK < 30000000 will use this value */
+{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 30000000 < LCK/VCK < 50000000 will use this value */
+{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 50000000 < LCK/VCK < 70000000 will use this value */
+{DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 70000000 < LCK/VCK < 100000000 will use this value */
+{DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 100000000 < LCK/VCK < 15000000 will use this value */
+{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 15000000 < LCK/VCK will use this value */
+{DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08},
+};
diff --git a/drivers/video/fbdev/via/tblDPASetting.h b/drivers/video/fbdev/via/tblDPASetting.h
new file mode 100644
index 000000000000..6db61519cb5d
--- /dev/null
+++ b/drivers/video/fbdev/via/tblDPASetting.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _TBLDPASETTING_H_
+#define _TBLDPASETTING_H_
+#include "global.h"
+
+#define DPA_CLK_30M       30000000
+#define DPA_CLK_50M       50000000
+#define DPA_CLK_70M       70000000
+#define DPA_CLK_100M      100000000
+#define DPA_CLK_150M      150000000
+
+enum DPA_RANGE {
+	DPA_CLK_RANGE_30M,
+	DPA_CLK_RANGE_30_50M,
+	DPA_CLK_RANGE_50_70M,
+	DPA_CLK_RANGE_70_100M,
+	DPA_CLK_RANGE_100_150M,
+	DPA_CLK_RANGE_150M
+};
+
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
+
+#endif
diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c
new file mode 100644
index 000000000000..6e274825fb31
--- /dev/null
+++ b/drivers/video/fbdev/via/via-core.c
@@ -0,0 +1,790 @@
+/*
+ * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
+ */
+
+/*
+ * Core code for the Via multifunction framebuffer device.
+ */
+#include <linux/via-core.h>
+#include <linux/via_i2c.h>
+#include <linux/via-gpio.h>
+#include "global.h"
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/pm.h>
+#include <asm/olpc.h>
+
+/*
+ * The default port config.
+ */
+static struct via_port_cfg adap_configs[] = {
+	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
+	[VIA_PORT_31]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
+	[VIA_PORT_25]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
+	[VIA_PORT_2C]	= { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
+	[VIA_PORT_3D]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
+	{ 0, 0, 0, 0 }
+};
+
+/*
+ * The OLPC XO-1.5 puts the camera power and reset lines onto
+ * GPIO 2C.
+ */
+static struct via_port_cfg olpc_adap_configs[] = {
+	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
+	[VIA_PORT_31]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
+	[VIA_PORT_25]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
+	[VIA_PORT_2C]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
+	[VIA_PORT_3D]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
+	{ 0, 0, 0, 0 }
+};
+
+/*
+ * We currently only support one viafb device (will there ever be
+ * more than one?), so just declare it globally here.
+ */
+static struct viafb_dev global_dev;
+
+
+/*
+ * Basic register access; spinlock required.
+ */
+static inline void viafb_mmio_write(int reg, u32 v)
+{
+	iowrite32(v, global_dev.engine_mmio + reg);
+}
+
+static inline int viafb_mmio_read(int reg)
+{
+	return ioread32(global_dev.engine_mmio + reg);
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Interrupt management.  We have a single IRQ line for a lot of
+ * different functions, so we need to share it.  The design here
+ * is that we don't want to reimplement the shared IRQ code here;
+ * we also want to avoid having contention for a single handler thread.
+ * So each subdev driver which needs interrupts just requests
+ * them directly from the kernel.  We just have what's needed for
+ * overall access to the interrupt control register.
+ */
+
+/*
+ * Which interrupts are enabled now?
+ */
+static u32 viafb_enabled_ints;
+
+static void viafb_int_init(void)
+{
+	viafb_enabled_ints = 0;
+
+	viafb_mmio_write(VDE_INTERRUPT, 0);
+}
+
+/*
+ * Allow subdevs to ask for specific interrupts to be enabled.  These
+ * functions must be called with reg_lock held
+ */
+void viafb_irq_enable(u32 mask)
+{
+	viafb_enabled_ints |= mask;
+	viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE);
+}
+EXPORT_SYMBOL_GPL(viafb_irq_enable);
+
+void viafb_irq_disable(u32 mask)
+{
+	viafb_enabled_ints &= ~mask;
+	if (viafb_enabled_ints == 0)
+		viafb_mmio_write(VDE_INTERRUPT, 0);  /* Disable entirely */
+	else
+		viafb_mmio_write(VDE_INTERRUPT,
+				viafb_enabled_ints | VDE_I_ENABLE);
+}
+EXPORT_SYMBOL_GPL(viafb_irq_disable);
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Currently, the camera driver is the only user of the DMA code, so we
+ * only compile it in if the camera driver is being built.  Chances are,
+ * most viafb systems will not need to have this extra code for a while.
+ * As soon as another user comes long, the ifdef can be removed.
+ */
+#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
+/*
+ * Access to the DMA engine.  This currently provides what the camera
+ * driver needs (i.e. outgoing only) but is easily expandable if need
+ * be.
+ */
+
+/*
+ * There are four DMA channels in the vx855.  For now, we only
+ * use one of them, though.  Most of the time, the DMA channel
+ * will be idle, so we keep the IRQ handler unregistered except
+ * when some subsystem has indicated an interest.
+ */
+static int viafb_dma_users;
+static DECLARE_COMPLETION(viafb_dma_completion);
+/*
+ * This mutex protects viafb_dma_users and our global interrupt
+ * registration state; it also serializes access to the DMA
+ * engine.
+ */
+static DEFINE_MUTEX(viafb_dma_lock);
+
+/*
+ * The VX855 DMA descriptor (used for s/g transfers) looks
+ * like this.
+ */
+struct viafb_vx855_dma_descr {
+	u32	addr_low;	/* Low part of phys addr */
+	u32	addr_high;	/* High 12 bits of addr */
+	u32	fb_offset;	/* Offset into FB memory */
+	u32	seg_size;	/* Size, 16-byte units */
+	u32	tile_mode;	/* "tile mode" setting */
+	u32	next_desc_low;	/* Next descriptor addr */
+	u32	next_desc_high;
+	u32	pad;		/* Fill out to 64 bytes */
+};
+
+/*
+ * Flags added to the "next descriptor low" pointers
+ */
+#define VIAFB_DMA_MAGIC		0x01  /* ??? Just has to be there */
+#define VIAFB_DMA_FINAL_SEGMENT 0x02  /* Final segment */
+
+/*
+ * The completion IRQ handler.
+ */
+static irqreturn_t viafb_dma_irq(int irq, void *data)
+{
+	int csr;
+	irqreturn_t ret = IRQ_NONE;
+
+	spin_lock(&global_dev.reg_lock);
+	csr = viafb_mmio_read(VDMA_CSR0);
+	if (csr & VDMA_C_DONE) {
+		viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
+		complete(&viafb_dma_completion);
+		ret = IRQ_HANDLED;
+	}
+	spin_unlock(&global_dev.reg_lock);
+	return ret;
+}
+
+/*
+ * Indicate a need for DMA functionality.
+ */
+int viafb_request_dma(void)
+{
+	int ret = 0;
+
+	/*
+	 * Only VX855 is supported currently.
+	 */
+	if (global_dev.chip_type != UNICHROME_VX855)
+		return -ENODEV;
+	/*
+	 * Note the new user and set up our interrupt handler
+	 * if need be.
+	 */
+	mutex_lock(&viafb_dma_lock);
+	viafb_dma_users++;
+	if (viafb_dma_users == 1) {
+		ret = request_irq(global_dev.pdev->irq, viafb_dma_irq,
+				IRQF_SHARED, "via-dma", &viafb_dma_users);
+		if (ret)
+			viafb_dma_users--;
+		else
+			viafb_irq_enable(VDE_I_DMA0TDEN);
+	}
+	mutex_unlock(&viafb_dma_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(viafb_request_dma);
+
+void viafb_release_dma(void)
+{
+	mutex_lock(&viafb_dma_lock);
+	viafb_dma_users--;
+	if (viafb_dma_users == 0) {
+		viafb_irq_disable(VDE_I_DMA0TDEN);
+		free_irq(global_dev.pdev->irq, &viafb_dma_users);
+	}
+	mutex_unlock(&viafb_dma_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_release_dma);
+
+
+#if 0
+/*
+ * Copy a single buffer from FB memory, synchronously.  This code works
+ * but is not currently used.
+ */
+void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len)
+{
+	unsigned long flags;
+	int csr;
+
+	mutex_lock(&viafb_dma_lock);
+	init_completion(&viafb_dma_completion);
+	/*
+	 * Program the controller.
+	 */
+	spin_lock_irqsave(&global_dev.reg_lock, flags);
+	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
+	/* Enable ints; must happen after CSR0 write! */
+	viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE);
+	viafb_mmio_write(VDMA_MARL0, (int) (paddr & 0xfffffff0));
+	viafb_mmio_write(VDMA_MARH0, (int) ((paddr >> 28) & 0xfff));
+	/* Data sheet suggests DAR0 should be <<4, but it lies */
+	viafb_mmio_write(VDMA_DAR0, offset);
+	viafb_mmio_write(VDMA_DQWCR0, len >> 4);
+	viafb_mmio_write(VDMA_TMR0, 0);
+	viafb_mmio_write(VDMA_DPRL0, 0);
+	viafb_mmio_write(VDMA_DPRH0, 0);
+	viafb_mmio_write(VDMA_PMR0, 0);
+	csr = viafb_mmio_read(VDMA_CSR0);
+	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
+	spin_unlock_irqrestore(&global_dev.reg_lock, flags);
+	/*
+	 * Now we just wait until the interrupt handler says
+	 * we're done.
+	 */
+	wait_for_completion_interruptible(&viafb_dma_completion);
+	viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
+	mutex_unlock(&viafb_dma_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_dma_copy_out);
+#endif
+
+/*
+ * Do a scatter/gather DMA copy from FB memory.  You must have done
+ * a successful call to viafb_request_dma() first.
+ */
+int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
+{
+	struct viafb_vx855_dma_descr *descr;
+	void *descrpages;
+	dma_addr_t descr_handle;
+	unsigned long flags;
+	int i;
+	struct scatterlist *sgentry;
+	dma_addr_t nextdesc;
+
+	/*
+	 * Get a place to put the descriptors.
+	 */
+	descrpages = dma_alloc_coherent(&global_dev.pdev->dev,
+			nsg*sizeof(struct viafb_vx855_dma_descr),
+			&descr_handle, GFP_KERNEL);
+	if (descrpages == NULL) {
+		dev_err(&global_dev.pdev->dev, "Unable to get descr page.\n");
+		return -ENOMEM;
+	}
+	mutex_lock(&viafb_dma_lock);
+	/*
+	 * Fill them in.
+	 */
+	descr = descrpages;
+	nextdesc = descr_handle + sizeof(struct viafb_vx855_dma_descr);
+	for_each_sg(sg, sgentry, nsg, i) {
+		dma_addr_t paddr = sg_dma_address(sgentry);
+		descr->addr_low = paddr & 0xfffffff0;
+		descr->addr_high = ((u64) paddr >> 32) & 0x0fff;
+		descr->fb_offset = offset;
+		descr->seg_size = sg_dma_len(sgentry) >> 4;
+		descr->tile_mode = 0;
+		descr->next_desc_low = (nextdesc&0xfffffff0) | VIAFB_DMA_MAGIC;
+		descr->next_desc_high = ((u64) nextdesc >> 32) & 0x0fff;
+		descr->pad = 0xffffffff;  /* VIA driver does this */
+		offset += sg_dma_len(sgentry);
+		nextdesc += sizeof(struct viafb_vx855_dma_descr);
+		descr++;
+	}
+	descr[-1].next_desc_low = VIAFB_DMA_FINAL_SEGMENT|VIAFB_DMA_MAGIC;
+	/*
+	 * Program the engine.
+	 */
+	spin_lock_irqsave(&global_dev.reg_lock, flags);
+	init_completion(&viafb_dma_completion);
+	viafb_mmio_write(VDMA_DQWCR0, 0);
+	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
+	viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE | VDMA_MR_CHAIN);
+	viafb_mmio_write(VDMA_DPRL0, descr_handle | VIAFB_DMA_MAGIC);
+	viafb_mmio_write(VDMA_DPRH0,
+			(((u64)descr_handle >> 32) & 0x0fff) | 0xf0000);
+	(void) viafb_mmio_read(VDMA_CSR0);
+	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
+	spin_unlock_irqrestore(&global_dev.reg_lock, flags);
+	/*
+	 * Now we just wait until the interrupt handler says
+	 * we're done.  Except that, actually, we need to wait a little
+	 * longer: the interrupts seem to jump the gun a little and we
+	 * get corrupted frames sometimes.
+	 */
+	wait_for_completion_timeout(&viafb_dma_completion, 1);
+	msleep(1);
+	if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0)
+		printk(KERN_ERR "VIA DMA timeout!\n");
+	/*
+	 * Clean up and we're done.
+	 */
+	viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
+	viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
+	mutex_unlock(&viafb_dma_lock);
+	dma_free_coherent(&global_dev.pdev->dev,
+			nsg*sizeof(struct viafb_vx855_dma_descr), descrpages,
+			descr_handle);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
+#endif /* CONFIG_VIDEO_VIA_CAMERA */
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Figure out how big our framebuffer memory is.  Kind of ugly,
+ * but evidently we can't trust the information found in the
+ * fbdev configuration area.
+ */
+static u16 via_function3[] = {
+	CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
+	CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
+	P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3,
+};
+
+/* Get the BIOS-configured framebuffer size from PCI configuration space
+ * of function 3 in the respective chipset */
+static int viafb_get_fb_size_from_pci(int chip_type)
+{
+	int i;
+	u8 offset = 0;
+	u32 FBSize;
+	u32 VideoMemSize;
+
+	/* search for the "FUNCTION3" device in this chipset */
+	for (i = 0; i < ARRAY_SIZE(via_function3); i++) {
+		struct pci_dev *pdev;
+
+		pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
+				      NULL);
+		if (!pdev)
+			continue;
+
+		DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
+
+		switch (pdev->device) {
+		case CLE266_FUNCTION3:
+		case KM400_FUNCTION3:
+			offset = 0xE0;
+			break;
+		case CN400_FUNCTION3:
+		case CN700_FUNCTION3:
+		case CX700_FUNCTION3:
+		case KM800_FUNCTION3:
+		case KM890_FUNCTION3:
+		case P4M890_FUNCTION3:
+		case P4M900_FUNCTION3:
+		case VX800_FUNCTION3:
+		case VX855_FUNCTION3:
+		case VX900_FUNCTION3:
+		/*case CN750_FUNCTION3: */
+			offset = 0xA0;
+			break;
+		}
+
+		if (!offset)
+			break;
+
+		pci_read_config_dword(pdev, offset, &FBSize);
+		pci_dev_put(pdev);
+	}
+
+	if (!offset) {
+		printk(KERN_ERR "cannot determine framebuffer size\n");
+		return -EIO;
+	}
+
+	FBSize = FBSize & 0x00007000;
+	DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
+
+	if (chip_type < UNICHROME_CX700) {
+		switch (FBSize) {
+		case 0x00004000:
+			VideoMemSize = (16 << 20);	/*16M */
+			break;
+
+		case 0x00005000:
+			VideoMemSize = (32 << 20);	/*32M */
+			break;
+
+		case 0x00006000:
+			VideoMemSize = (64 << 20);	/*64M */
+			break;
+
+		default:
+			VideoMemSize = (32 << 20);	/*32M */
+			break;
+		}
+	} else {
+		switch (FBSize) {
+		case 0x00001000:
+			VideoMemSize = (8 << 20);	/*8M */
+			break;
+
+		case 0x00002000:
+			VideoMemSize = (16 << 20);	/*16M */
+			break;
+
+		case 0x00003000:
+			VideoMemSize = (32 << 20);	/*32M */
+			break;
+
+		case 0x00004000:
+			VideoMemSize = (64 << 20);	/*64M */
+			break;
+
+		case 0x00005000:
+			VideoMemSize = (128 << 20);	/*128M */
+			break;
+
+		case 0x00006000:
+			VideoMemSize = (256 << 20);	/*256M */
+			break;
+
+		case 0x00007000:	/* Only on VX855/875 */
+			VideoMemSize = (512 << 20);	/*512M */
+			break;
+
+		default:
+			VideoMemSize = (32 << 20);	/*32M */
+			break;
+		}
+	}
+
+	return VideoMemSize;
+}
+
+
+/*
+ * Figure out and map our MMIO regions.
+ */
+static int via_pci_setup_mmio(struct viafb_dev *vdev)
+{
+	int ret;
+	/*
+	 * Hook up to the device registers.  Note that we soldier
+	 * on if it fails; the framebuffer can operate (without
+	 * acceleration) without this region.
+	 */
+	vdev->engine_start = pci_resource_start(vdev->pdev, 1);
+	vdev->engine_len = pci_resource_len(vdev->pdev, 1);
+	vdev->engine_mmio = ioremap_nocache(vdev->engine_start,
+			vdev->engine_len);
+	if (vdev->engine_mmio == NULL)
+		dev_err(&vdev->pdev->dev,
+				"Unable to map engine MMIO; operation will be "
+				"slow and crippled.\n");
+	/*
+	 * Map in framebuffer memory.  For now, failure here is
+	 * fatal.  Unfortunately, in the absence of significant
+	 * vmalloc space, failure here is also entirely plausible.
+	 * Eventually we want to move away from mapping this
+	 * entire region.
+	 */
+	if (vdev->chip_type == UNICHROME_VX900)
+		vdev->fbmem_start = pci_resource_start(vdev->pdev, 2);
+	else
+		vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
+	ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
+	if (ret < 0)
+		goto out_unmap;
+
+	/* try to map less memory on failure, 8 MB should be still enough */
+	for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
+		vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
+		if (vdev->fbmem)
+			break;
+	}
+
+	if (vdev->fbmem == NULL) {
+		ret = -ENOMEM;
+		goto out_unmap;
+	}
+	return 0;
+out_unmap:
+	iounmap(vdev->engine_mmio);
+	return ret;
+}
+
+static void via_pci_teardown_mmio(struct viafb_dev *vdev)
+{
+	iounmap(vdev->fbmem);
+	iounmap(vdev->engine_mmio);
+}
+
+/*
+ * Create our subsidiary devices.
+ */
+static struct viafb_subdev_info {
+	char *name;
+	struct platform_device *platdev;
+} viafb_subdevs[] = {
+	{
+		.name = "viafb-gpio",
+	},
+	{
+		.name = "viafb-i2c",
+	},
+#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
+	{
+		.name = "viafb-camera",
+	},
+#endif
+};
+#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
+
+static int via_create_subdev(struct viafb_dev *vdev,
+			     struct viafb_subdev_info *info)
+{
+	int ret;
+
+	info->platdev = platform_device_alloc(info->name, -1);
+	if (!info->platdev) {
+		dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
+			info->name);
+		return -ENOMEM;
+	}
+	info->platdev->dev.parent = &vdev->pdev->dev;
+	info->platdev->dev.platform_data = vdev;
+	ret = platform_device_add(info->platdev);
+	if (ret) {
+		dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
+				info->name);
+		platform_device_put(info->platdev);
+		info->platdev = NULL;
+	}
+	return ret;
+}
+
+static int via_setup_subdevs(struct viafb_dev *vdev)
+{
+	int i;
+
+	/*
+	 * Ignore return values.  Even if some of the devices
+	 * fail to be created, we'll still be able to use some
+	 * of the rest.
+	 */
+	for (i = 0; i < N_SUBDEVS; i++)
+		via_create_subdev(vdev, viafb_subdevs + i);
+	return 0;
+}
+
+static void via_teardown_subdevs(void)
+{
+	int i;
+
+	for (i = 0; i < N_SUBDEVS; i++)
+		if (viafb_subdevs[i].platdev) {
+			viafb_subdevs[i].platdev->dev.platform_data = NULL;
+			platform_device_unregister(viafb_subdevs[i].platdev);
+		}
+}
+
+/*
+ * Power management functions
+ */
+#ifdef CONFIG_PM
+static LIST_HEAD(viafb_pm_hooks);
+static DEFINE_MUTEX(viafb_pm_hooks_lock);
+
+void viafb_pm_register(struct viafb_pm_hooks *hooks)
+{
+	INIT_LIST_HEAD(&hooks->list);
+
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_add_tail(&hooks->list, &viafb_pm_hooks);
+	mutex_unlock(&viafb_pm_hooks_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_pm_register);
+
+void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
+{
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_del(&hooks->list);
+	mutex_unlock(&viafb_pm_hooks_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_pm_unregister);
+
+static int via_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct viafb_pm_hooks *hooks;
+
+	if (state.event != PM_EVENT_SUSPEND)
+		return 0;
+	/*
+	 * "I've occasionally hit a few drivers that caused suspend
+	 * failures, and each and every time it was a driver bug, and
+	 * the right thing to do was to just ignore the error and suspend
+	 * anyway - returning an error code and trying to undo the suspend
+	 * is not what anybody ever really wants, even if our model
+	 *_allows_ for it."
+	 * -- Linus Torvalds, Dec. 7, 2009
+	 */
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
+		hooks->suspend(hooks->private);
+	mutex_unlock(&viafb_pm_hooks_lock);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return 0;
+}
+
+static int via_resume(struct pci_dev *pdev)
+{
+	struct viafb_pm_hooks *hooks;
+
+	/* Get the bus side powered up */
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	if (pci_enable_device(pdev))
+		return 0;
+
+	pci_set_master(pdev);
+
+	/* Now bring back any subdevs */
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_for_each_entry(hooks, &viafb_pm_hooks, list)
+		hooks->resume(hooks->private);
+	mutex_unlock(&viafb_pm_hooks_lock);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int ret;
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Global device initialization.
+	 */
+	memset(&global_dev, 0, sizeof(global_dev));
+	global_dev.pdev = pdev;
+	global_dev.chip_type = ent->driver_data;
+	global_dev.port_cfg = adap_configs;
+	if (machine_is_olpc())
+		global_dev.port_cfg = olpc_adap_configs;
+
+	spin_lock_init(&global_dev.reg_lock);
+	ret = via_pci_setup_mmio(&global_dev);
+	if (ret)
+		goto out_disable;
+	/*
+	 * Set up interrupts and create our subdevices.  Continue even if
+	 * some things fail.
+	 */
+	viafb_int_init();
+	via_setup_subdevs(&global_dev);
+	/*
+	 * Set up the framebuffer device
+	 */
+	ret = via_fb_pci_probe(&global_dev);
+	if (ret)
+		goto out_subdevs;
+	return 0;
+
+out_subdevs:
+	via_teardown_subdevs();
+	via_pci_teardown_mmio(&global_dev);
+out_disable:
+	pci_disable_device(pdev);
+	return ret;
+}
+
+static void via_pci_remove(struct pci_dev *pdev)
+{
+	via_teardown_subdevs();
+	via_fb_pci_remove(pdev);
+	via_pci_teardown_mmio(&global_dev);
+	pci_disable_device(pdev);
+}
+
+
+static struct pci_device_id via_pci_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
+	  .driver_data = UNICHROME_CLE266 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
+	  .driver_data = UNICHROME_K400 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
+	  .driver_data = UNICHROME_K800 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
+	  .driver_data = UNICHROME_PM800 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN700_DID),
+	  .driver_data = UNICHROME_CN700 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
+	  .driver_data = UNICHROME_CX700 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
+	  .driver_data = UNICHROME_CN750 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
+	  .driver_data = UNICHROME_K8M890 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
+	  .driver_data = UNICHROME_P4M890 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
+	  .driver_data = UNICHROME_P4M900 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
+	  .driver_data = UNICHROME_VX800 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
+	  .driver_data = UNICHROME_VX855 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID),
+	  .driver_data = UNICHROME_VX900 },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, via_pci_table);
+
+static struct pci_driver via_driver = {
+	.name		= "viafb",
+	.id_table	= via_pci_table,
+	.probe		= via_pci_probe,
+	.remove		= via_pci_remove,
+#ifdef CONFIG_PM
+	.suspend	= via_suspend,
+	.resume		= via_resume,
+#endif
+};
+
+static int __init via_core_init(void)
+{
+	int ret;
+
+	ret = viafb_init();
+	if (ret)
+		return ret;
+	viafb_i2c_init();
+	viafb_gpio_init();
+	return pci_register_driver(&via_driver);
+}
+
+static void __exit via_core_exit(void)
+{
+	pci_unregister_driver(&via_driver);
+	viafb_gpio_exit();
+	viafb_i2c_exit();
+	viafb_exit();
+}
+
+module_init(via_core_init);
+module_exit(via_core_exit);
diff --git a/drivers/video/fbdev/via/via-gpio.c b/drivers/video/fbdev/via/via-gpio.c
new file mode 100644
index 000000000000..e408679081ab
--- /dev/null
+++ b/drivers/video/fbdev/via/via-gpio.c
@@ -0,0 +1,316 @@
+/*
+ * Support for viafb GPIO ports.
+ *
+ * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
+ * Distributable under version 2 of the GNU General Public License.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/via-core.h>
+#include <linux/via-gpio.h>
+#include <linux/export.h>
+
+/*
+ * The ports we know about.  Note that the port-25 gpios are not
+ * mentioned in the datasheet.
+ */
+
+struct viafb_gpio {
+	char *vg_name;	/* Data sheet name */
+	u16 vg_io_port;
+	u8  vg_port_index;
+	int  vg_mask_shift;
+};
+
+static struct viafb_gpio viafb_all_gpios[] = {
+	{
+		.vg_name = "VGPIO0",  /* Guess - not in datasheet */
+		.vg_io_port = VIASR,
+		.vg_port_index = 0x25,
+		.vg_mask_shift = 1
+	},
+	{
+		.vg_name = "VGPIO1",
+		.vg_io_port = VIASR,
+		.vg_port_index = 0x25,
+		.vg_mask_shift = 0
+	},
+	{
+		.vg_name = "VGPIO2",  /* aka DISPCLKI0 */
+		.vg_io_port = VIASR,
+		.vg_port_index = 0x2c,
+		.vg_mask_shift = 1
+	},
+	{
+		.vg_name = "VGPIO3",  /* aka DISPCLKO0 */
+		.vg_io_port = VIASR,
+		.vg_port_index = 0x2c,
+		.vg_mask_shift = 0
+	},
+	{
+		.vg_name = "VGPIO4",  /* DISPCLKI1 */
+		.vg_io_port = VIASR,
+		.vg_port_index = 0x3d,
+		.vg_mask_shift = 1
+	},
+	{
+		.vg_name = "VGPIO5",  /* DISPCLKO1 */
+		.vg_io_port = VIASR,
+		.vg_port_index = 0x3d,
+		.vg_mask_shift = 0
+	},
+};
+
+#define VIAFB_NUM_GPIOS ARRAY_SIZE(viafb_all_gpios)
+
+/*
+ * This structure controls the active GPIOs, which may be a subset
+ * of those which are known.
+ */
+
+struct viafb_gpio_cfg {
+	struct gpio_chip gpio_chip;
+	struct viafb_dev *vdev;
+	struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS];
+	const char *gpio_names[VIAFB_NUM_GPIOS];
+};
+
+/*
+ * GPIO access functions
+ */
+static void via_gpio_set(struct gpio_chip *chip, unsigned int nr,
+			 int value)
+{
+	struct viafb_gpio_cfg *cfg = container_of(chip,
+						  struct viafb_gpio_cfg,
+						  gpio_chip);
+	u8 reg;
+	struct viafb_gpio *gpio;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
+	gpio = cfg->active_gpios[nr];
+	reg = via_read_reg(VIASR, gpio->vg_port_index);
+	reg |= 0x40 << gpio->vg_mask_shift;  /* output enable */
+	if (value)
+		reg |= 0x10 << gpio->vg_mask_shift;
+	else
+		reg &= ~(0x10 << gpio->vg_mask_shift);
+	via_write_reg(VIASR, gpio->vg_port_index, reg);
+	spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
+}
+
+static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr,
+			    int value)
+{
+	via_gpio_set(chip, nr, value);
+	return 0;
+}
+
+/*
+ * Set the input direction.  I'm not sure this is right; we should
+ * be able to do input without disabling output.
+ */
+static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr)
+{
+	struct viafb_gpio_cfg *cfg = container_of(chip,
+						  struct viafb_gpio_cfg,
+						  gpio_chip);
+	struct viafb_gpio *gpio;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
+	gpio = cfg->active_gpios[nr];
+	via_write_reg_mask(VIASR, gpio->vg_port_index, 0,
+			0x40 << gpio->vg_mask_shift);
+	spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
+	return 0;
+}
+
+static int via_gpio_get(struct gpio_chip *chip, unsigned int nr)
+{
+	struct viafb_gpio_cfg *cfg = container_of(chip,
+						  struct viafb_gpio_cfg,
+						  gpio_chip);
+	u8 reg;
+	struct viafb_gpio *gpio;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
+	gpio = cfg->active_gpios[nr];
+	reg = via_read_reg(VIASR, gpio->vg_port_index);
+	spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
+	return reg & (0x04 << gpio->vg_mask_shift);
+}
+
+
+static struct viafb_gpio_cfg viafb_gpio_config = {
+	.gpio_chip = {
+		.label = "VIAFB onboard GPIO",
+		.owner = THIS_MODULE,
+		.direction_output = via_gpio_dir_out,
+		.set = via_gpio_set,
+		.direction_input = via_gpio_dir_input,
+		.get = via_gpio_get,
+		.base = -1,
+		.ngpio = 0,
+		.can_sleep = 0
+	}
+};
+
+/*
+ * Manage the software enable bit.
+ */
+static void viafb_gpio_enable(struct viafb_gpio *gpio)
+{
+	via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02);
+}
+
+static void viafb_gpio_disable(struct viafb_gpio *gpio)
+{
+	via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
+}
+
+#ifdef CONFIG_PM
+
+static int viafb_gpio_suspend(void *private)
+{
+	return 0;
+}
+
+static int viafb_gpio_resume(void *private)
+{
+	int i;
+
+	for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
+		viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
+	return 0;
+}
+
+static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
+	.suspend = viafb_gpio_suspend,
+	.resume = viafb_gpio_resume
+};
+#endif /* CONFIG_PM */
+
+/*
+ * Look up a specific gpio and return the number it was assigned.
+ */
+int viafb_gpio_lookup(const char *name)
+{
+	int i;
+
+	for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++)
+		if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name))
+			return viafb_gpio_config.gpio_chip.base + i;
+	return -1;
+}
+EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
+
+/*
+ * Platform device stuff.
+ */
+static int viafb_gpio_probe(struct platform_device *platdev)
+{
+	struct viafb_dev *vdev = platdev->dev.platform_data;
+	struct via_port_cfg *port_cfg = vdev->port_cfg;
+	int i, ngpio = 0, ret;
+	struct viafb_gpio *gpio;
+	unsigned long flags;
+
+	/*
+	 * Set up entries for all GPIOs which have been configured to
+	 * operate as such (as opposed to as i2c ports).
+	 */
+	for (i = 0; i < VIAFB_NUM_PORTS; i++) {
+		if (port_cfg[i].mode != VIA_MODE_GPIO)
+			continue;
+		for (gpio = viafb_all_gpios;
+		     gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++)
+			if (gpio->vg_port_index == port_cfg[i].ioport_index) {
+				viafb_gpio_config.active_gpios[ngpio] = gpio;
+				viafb_gpio_config.gpio_names[ngpio] =
+					gpio->vg_name;
+				ngpio++;
+			}
+	}
+	viafb_gpio_config.gpio_chip.ngpio = ngpio;
+	viafb_gpio_config.gpio_chip.names = viafb_gpio_config.gpio_names;
+	viafb_gpio_config.vdev = vdev;
+	if (ngpio == 0) {
+		printk(KERN_INFO "viafb: no GPIOs configured\n");
+		return 0;
+	}
+	/*
+	 * Enable the ports.  They come in pairs, with a single
+	 * enable bit for both.
+	 */
+	spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
+	for (i = 0; i < ngpio; i += 2)
+		viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
+	spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
+	/*
+	 * Get registered.
+	 */
+	viafb_gpio_config.gpio_chip.base = -1;  /* Dynamic */
+	ret = gpiochip_add(&viafb_gpio_config.gpio_chip);
+	if (ret) {
+		printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
+		viafb_gpio_config.gpio_chip.ngpio = 0;
+	}
+#ifdef CONFIG_PM
+	viafb_pm_register(&viafb_gpio_pm_hooks);
+#endif
+	return ret;
+}
+
+
+static int viafb_gpio_remove(struct platform_device *platdev)
+{
+	unsigned long flags;
+	int ret = 0, i;
+
+#ifdef CONFIG_PM
+	viafb_pm_unregister(&viafb_gpio_pm_hooks);
+#endif
+
+	/*
+	 * Get unregistered.
+	 */
+	if (viafb_gpio_config.gpio_chip.ngpio > 0) {
+		ret = gpiochip_remove(&viafb_gpio_config.gpio_chip);
+		if (ret) { /* Somebody still using it? */
+			printk(KERN_ERR "Viafb: GPIO remove failed\n");
+			return ret;
+		}
+	}
+	/*
+	 * Disable the ports.
+	 */
+	spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
+	for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
+		viafb_gpio_disable(viafb_gpio_config.active_gpios[i]);
+	viafb_gpio_config.gpio_chip.ngpio = 0;
+	spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
+	return ret;
+}
+
+static struct platform_driver via_gpio_driver = {
+	.driver = {
+		.name = "viafb-gpio",
+	},
+	.probe = viafb_gpio_probe,
+	.remove = viafb_gpio_remove,
+};
+
+int viafb_gpio_init(void)
+{
+	return platform_driver_register(&via_gpio_driver);
+}
+
+void viafb_gpio_exit(void)
+{
+	platform_driver_unregister(&via_gpio_driver);
+}
diff --git a/drivers/video/fbdev/via/via_aux.c b/drivers/video/fbdev/via/via_aux.c
new file mode 100644
index 000000000000..4a0a55cdac3d
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * infrastructure for devices connected via I2C
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap)
+{
+	struct via_aux_bus *bus;
+
+	if (!adap)
+		return NULL;
+
+	bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+	if (!bus)
+		return NULL;
+
+	bus->adap = adap;
+	INIT_LIST_HEAD(&bus->drivers);
+
+	via_aux_edid_probe(bus);
+	via_aux_vt1636_probe(bus);
+	via_aux_vt1632_probe(bus);
+	via_aux_vt1631_probe(bus);
+	via_aux_vt1625_probe(bus);
+	via_aux_vt1622_probe(bus);
+	via_aux_vt1621_probe(bus);
+	via_aux_sii164_probe(bus);
+	via_aux_ch7301_probe(bus);
+
+	return bus;
+}
+
+void via_aux_free(struct via_aux_bus *bus)
+{
+	struct via_aux_drv *pos, *n;
+
+	if (!bus)
+		return;
+
+	list_for_each_entry_safe(pos, n, &bus->drivers, chain) {
+		if (pos->cleanup)
+			pos->cleanup(pos);
+
+		list_del(&pos->chain);
+		kfree(pos->data);
+		kfree(pos);
+	}
+
+	kfree(bus);
+}
+
+const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus)
+{
+	struct via_aux_drv *pos;
+	const struct fb_videomode *mode = NULL;
+
+	if (!bus)
+		return NULL;
+
+	list_for_each_entry(pos, &bus->drivers, chain) {
+		if (pos->get_preferred_mode)
+			mode = pos->get_preferred_mode(pos);
+	}
+
+	return mode;
+}
diff --git a/drivers/video/fbdev/via/via_aux.h b/drivers/video/fbdev/via/via_aux.h
new file mode 100644
index 000000000000..a8de3f038cea
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * infrastructure for devices connected via I2C
+ */
+
+#ifndef __VIA_AUX_H__
+#define __VIA_AUX_H__
+
+
+#include <linux/list.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+
+
+struct via_aux_bus {
+	struct i2c_adapter *adap;	/* the I2C device to access the bus */
+	struct list_head drivers;	/* drivers for devices on this bus */
+};
+
+struct via_aux_drv {
+	struct list_head chain;		/* chain to support multiple drivers */
+
+	struct via_aux_bus *bus;	/* the I2C bus used */
+	u8 addr;			/* the I2C slave address */
+
+	const char *name;	/* human readable name of the driver */
+	void *data;		/* private data of this driver */
+
+	void (*cleanup)(struct via_aux_drv *drv);
+	const struct fb_videomode* (*get_preferred_mode)
+		(struct via_aux_drv *drv);
+};
+
+
+struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap);
+void via_aux_free(struct via_aux_bus *bus);
+const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus);
+
+
+static inline bool via_aux_add(struct via_aux_drv *drv)
+{
+	struct via_aux_drv *data = kmalloc(sizeof(*data), GFP_KERNEL);
+
+	if (!data)
+		return false;
+
+	*data = *drv;
+	list_add_tail(&data->chain, &data->bus->drivers);
+	return true;
+}
+
+static inline bool via_aux_read(struct via_aux_drv *drv, u8 start, u8 *buf,
+	u8 len)
+{
+	struct i2c_msg msg[2] = {
+		{.addr = drv->addr, .flags = 0, .len = 1, .buf = &start},
+		{.addr = drv->addr, .flags = I2C_M_RD, .len = len, .buf = buf} };
+
+	return i2c_transfer(drv->bus->adap, msg, 2) == 2;
+}
+
+
+/* probe functions of existing drivers - should only be called in via_aux.c */
+void via_aux_ch7301_probe(struct via_aux_bus *bus);
+void via_aux_edid_probe(struct via_aux_bus *bus);
+void via_aux_sii164_probe(struct via_aux_bus *bus);
+void via_aux_vt1636_probe(struct via_aux_bus *bus);
+void via_aux_vt1632_probe(struct via_aux_bus *bus);
+void via_aux_vt1631_probe(struct via_aux_bus *bus);
+void via_aux_vt1625_probe(struct via_aux_bus *bus);
+void via_aux_vt1622_probe(struct via_aux_bus *bus);
+void via_aux_vt1621_probe(struct via_aux_bus *bus);
+
+
+#endif /* __VIA_AUX_H__ */
diff --git a/drivers/video/fbdev/via/via_aux_ch7301.c b/drivers/video/fbdev/via/via_aux_ch7301.c
new file mode 100644
index 000000000000..1cbe5037a6b0
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_ch7301.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for Chrontel CH7301 DVI Transmitter
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "CH7301 DVI Transmitter";
+
+
+static void probe(struct via_aux_bus *bus, u8 addr)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	addr,
+		.name	=	name};
+	u8 tmp;
+
+	if (!via_aux_read(&drv, 0x4B, &tmp, 1) || tmp != 0x17)
+		return;
+
+	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
+	via_aux_add(&drv);
+}
+
+void via_aux_ch7301_probe(struct via_aux_bus *bus)
+{
+	probe(bus, 0x75);
+	probe(bus, 0x76);
+}
diff --git a/drivers/video/fbdev/via/via_aux_edid.c b/drivers/video/fbdev/via/via_aux_edid.c
new file mode 100644
index 000000000000..754d4509033f
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_edid.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * generic EDID driver
+ */
+
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include "via_aux.h"
+#include "../edid.h"
+
+
+static const char *name = "EDID";
+
+
+static void query_edid(struct via_aux_drv *drv)
+{
+	struct fb_monspecs *spec = drv->data;
+	unsigned char edid[EDID_LENGTH];
+	bool valid = false;
+
+	if (spec) {
+		fb_destroy_modedb(spec->modedb);
+	} else {
+		spec = kmalloc(sizeof(*spec), GFP_KERNEL);
+		if (!spec)
+			return;
+	}
+
+	spec->version = spec->revision = 0;
+	if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
+		fb_edid_to_monspecs(edid, spec);
+		valid = spec->version || spec->revision;
+	}
+
+	if (!valid) {
+		kfree(spec);
+		spec = NULL;
+	} else
+		printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor);
+
+	drv->data = spec;
+}
+
+static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv)
+{
+	struct fb_monspecs *spec = drv->data;
+	int i;
+
+	if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))
+		return NULL;
+
+	for (i = 0; i < spec->modedb_len; i++) {
+		if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&
+			spec->modedb[i].flag & FB_MODE_IS_DETAILED)
+			return &spec->modedb[i];
+	}
+
+	return NULL;
+}
+
+static void cleanup(struct via_aux_drv *drv)
+{
+	struct fb_monspecs *spec = drv->data;
+
+	if (spec)
+		fb_destroy_modedb(spec->modedb);
+}
+
+void via_aux_edid_probe(struct via_aux_bus *bus)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	0x50,
+		.name	=	name,
+		.cleanup	=	cleanup,
+		.get_preferred_mode	=	get_preferred_mode};
+
+	query_edid(&drv);
+
+	/* as EDID devices can be connected/disconnected just add the driver */
+	via_aux_add(&drv);
+}
diff --git a/drivers/video/fbdev/via/via_aux_sii164.c b/drivers/video/fbdev/via/via_aux_sii164.c
new file mode 100644
index 000000000000..ca1b35f033b1
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_sii164.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for Silicon Image SiI 164 PanelLink Transmitter
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "SiI 164 PanelLink Transmitter";
+
+
+static void probe(struct via_aux_bus *bus, u8 addr)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	addr,
+		.name	=	name};
+	/* check vendor id and device id */
+	const u8 id[] = {0x01, 0x00, 0x06, 0x00}, len = ARRAY_SIZE(id);
+	u8 tmp[len];
+
+	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
+		return;
+
+	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
+	via_aux_add(&drv);
+}
+
+void via_aux_sii164_probe(struct via_aux_bus *bus)
+{
+	u8 i;
+
+	for (i = 0x38; i <= 0x3F; i++)
+		probe(bus, i);
+}
diff --git a/drivers/video/fbdev/via/via_aux_vt1621.c b/drivers/video/fbdev/via/via_aux_vt1621.c
new file mode 100644
index 000000000000..38eca8479898
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1621.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for VIA VT1621(M) TV Encoder
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "VT1621(M) TV Encoder";
+
+
+void via_aux_vt1621_probe(struct via_aux_bus *bus)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	0x20,
+		.name	=	name};
+	u8 tmp;
+
+	if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x02)
+		return;
+
+	printk(KERN_INFO "viafb: Found %s\n", name);
+	via_aux_add(&drv);
+}
diff --git a/drivers/video/fbdev/via/via_aux_vt1622.c b/drivers/video/fbdev/via/via_aux_vt1622.c
new file mode 100644
index 000000000000..8c79c68ba683
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1622.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for VIA VT1622(M) Digital TV Encoder
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "VT1622(M) Digital TV Encoder";
+
+
+static void probe(struct via_aux_bus *bus, u8 addr)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	addr,
+		.name	=	name};
+	u8 tmp;
+
+	if (!via_aux_read(&drv, 0x1B, &tmp, 1) ||  tmp != 0x03)
+		return;
+
+	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
+	via_aux_add(&drv);
+}
+
+void via_aux_vt1622_probe(struct via_aux_bus *bus)
+{
+	probe(bus, 0x20);
+	probe(bus, 0x21);
+}
diff --git a/drivers/video/fbdev/via/via_aux_vt1625.c b/drivers/video/fbdev/via/via_aux_vt1625.c
new file mode 100644
index 000000000000..03eb30165d36
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1625.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for VIA VT1625(M) HDTV Encoder
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "VT1625(M) HDTV Encoder";
+
+
+static void probe(struct via_aux_bus *bus, u8 addr)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	addr,
+		.name	=	name};
+	u8 tmp;
+
+	if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x50)
+		return;
+
+	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
+	via_aux_add(&drv);
+}
+
+void via_aux_vt1625_probe(struct via_aux_bus *bus)
+{
+	probe(bus, 0x20);
+	probe(bus, 0x21);
+}
diff --git a/drivers/video/fbdev/via/via_aux_vt1631.c b/drivers/video/fbdev/via/via_aux_vt1631.c
new file mode 100644
index 000000000000..06e742f1f723
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1631.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for VIA VT1631 LVDS Transmitter
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "VT1631 LVDS Transmitter";
+
+
+void via_aux_vt1631_probe(struct via_aux_bus *bus)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	0x38,
+		.name	=	name};
+	/* check vendor id and device id */
+	const u8 id[] = {0x06, 0x11, 0x91, 0x31}, len = ARRAY_SIZE(id);
+	u8 tmp[len];
+
+	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
+		return;
+
+	printk(KERN_INFO "viafb: Found %s\n", name);
+	via_aux_add(&drv);
+}
diff --git a/drivers/video/fbdev/via/via_aux_vt1632.c b/drivers/video/fbdev/via/via_aux_vt1632.c
new file mode 100644
index 000000000000..d24f4cd97401
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1632.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for VIA VT1632 DVI Transmitter
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "VT1632 DVI Transmitter";
+
+
+static void probe(struct via_aux_bus *bus, u8 addr)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	addr,
+		.name	=	name};
+	/* check vendor id and device id */
+	const u8 id[] = {0x06, 0x11, 0x92, 0x31}, len = ARRAY_SIZE(id);
+	u8 tmp[len];
+
+	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
+		return;
+
+	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
+	via_aux_add(&drv);
+}
+
+void via_aux_vt1632_probe(struct via_aux_bus *bus)
+{
+	u8 i;
+
+	for (i = 0x08; i <= 0x0F; i++)
+		probe(bus, i);
+}
diff --git a/drivers/video/fbdev/via/via_aux_vt1636.c b/drivers/video/fbdev/via/via_aux_vt1636.c
new file mode 100644
index 000000000000..9e015c101d4d
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1636.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * driver for VIA VT1636 LVDS Transmitter
+ */
+
+#include <linux/slab.h>
+#include "via_aux.h"
+
+
+static const char *name = "VT1636 LVDS Transmitter";
+
+
+void via_aux_vt1636_probe(struct via_aux_bus *bus)
+{
+	struct via_aux_drv drv = {
+		.bus	=	bus,
+		.addr	=	0x40,
+		.name	=	name};
+	/* check vendor id and device id */
+	const u8 id[] = {0x06, 0x11, 0x45, 0x33}, len = ARRAY_SIZE(id);
+	u8 tmp[len];
+
+	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
+		return;
+
+	printk(KERN_INFO "viafb: Found %s\n", name);
+	via_aux_add(&drv);
+}
diff --git a/drivers/video/fbdev/via/via_clock.c b/drivers/video/fbdev/via/via_clock.c
new file mode 100644
index 000000000000..db1e39277e32
--- /dev/null
+++ b/drivers/video/fbdev/via/via_clock.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * clock and PLL management functions
+ */
+
+#include <linux/kernel.h>
+#include <linux/via-core.h>
+#include <asm/olpc.h>
+#include "via_clock.h"
+#include "global.h"
+#include "debug.h"
+
+const char *via_slap = "Please slap VIA Technologies to motivate them "
+	"releasing full documentation for your platform!\n";
+
+static inline u32 cle266_encode_pll(struct via_pll_config pll)
+{
+	return (pll.multiplier << 8)
+		| (pll.rshift << 6)
+		| pll.divisor;
+}
+
+static inline u32 k800_encode_pll(struct via_pll_config pll)
+{
+	return ((pll.divisor - 2) << 16)
+		| (pll.rshift << 10)
+		| (pll.multiplier - 2);
+}
+
+static inline u32 vx855_encode_pll(struct via_pll_config pll)
+{
+	return (pll.divisor << 16)
+		| (pll.rshift << 10)
+		| pll.multiplier;
+}
+
+static inline void cle266_set_primary_pll_encoded(u32 data)
+{
+	via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
+	via_write_reg(VIASR, 0x46, data & 0xFF);
+	via_write_reg(VIASR, 0x47, (data >> 8) & 0xFF);
+	via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
+}
+
+static inline void k800_set_primary_pll_encoded(u32 data)
+{
+	via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
+	via_write_reg(VIASR, 0x44, data & 0xFF);
+	via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
+	via_write_reg(VIASR, 0x46, (data >> 16) & 0xFF);
+	via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
+}
+
+static inline void cle266_set_secondary_pll_encoded(u32 data)
+{
+	via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
+	via_write_reg(VIASR, 0x44, data & 0xFF);
+	via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
+	via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
+}
+
+static inline void k800_set_secondary_pll_encoded(u32 data)
+{
+	via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
+	via_write_reg(VIASR, 0x4A, data & 0xFF);
+	via_write_reg(VIASR, 0x4B, (data >> 8) & 0xFF);
+	via_write_reg(VIASR, 0x4C, (data >> 16) & 0xFF);
+	via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
+}
+
+static inline void set_engine_pll_encoded(u32 data)
+{
+	via_write_reg_mask(VIASR, 0x40, 0x01, 0x01); /* enable reset */
+	via_write_reg(VIASR, 0x47, data & 0xFF);
+	via_write_reg(VIASR, 0x48, (data >> 8) & 0xFF);
+	via_write_reg(VIASR, 0x49, (data >> 16) & 0xFF);
+	via_write_reg_mask(VIASR, 0x40, 0x00, 0x01); /* disable reset */
+}
+
+static void cle266_set_primary_pll(struct via_pll_config config)
+{
+	cle266_set_primary_pll_encoded(cle266_encode_pll(config));
+}
+
+static void k800_set_primary_pll(struct via_pll_config config)
+{
+	k800_set_primary_pll_encoded(k800_encode_pll(config));
+}
+
+static void vx855_set_primary_pll(struct via_pll_config config)
+{
+	k800_set_primary_pll_encoded(vx855_encode_pll(config));
+}
+
+static void cle266_set_secondary_pll(struct via_pll_config config)
+{
+	cle266_set_secondary_pll_encoded(cle266_encode_pll(config));
+}
+
+static void k800_set_secondary_pll(struct via_pll_config config)
+{
+	k800_set_secondary_pll_encoded(k800_encode_pll(config));
+}
+
+static void vx855_set_secondary_pll(struct via_pll_config config)
+{
+	k800_set_secondary_pll_encoded(vx855_encode_pll(config));
+}
+
+static void k800_set_engine_pll(struct via_pll_config config)
+{
+	set_engine_pll_encoded(k800_encode_pll(config));
+}
+
+static void vx855_set_engine_pll(struct via_pll_config config)
+{
+	set_engine_pll_encoded(vx855_encode_pll(config));
+}
+
+static void set_primary_pll_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x20;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2D, value, 0x30);
+}
+
+static void set_secondary_pll_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x08;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2D, value, 0x0C);
+}
+
+static void set_engine_pll_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x02;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x2D, value, 0x03);
+}
+
+static void set_primary_clock_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x20;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1B, value, 0x30);
+}
+
+static void set_secondary_clock_state(u8 state)
+{
+	u8 value;
+
+	switch (state) {
+	case VIA_STATE_ON:
+		value = 0x80;
+		break;
+	case VIA_STATE_OFF:
+		value = 0x00;
+		break;
+	default:
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x1B, value, 0xC0);
+}
+
+static inline u8 set_clock_source_common(enum via_clksrc source, bool use_pll)
+{
+	u8 data = 0;
+
+	switch (source) {
+	case VIA_CLKSRC_X1:
+		data = 0x00;
+		break;
+	case VIA_CLKSRC_TVX1:
+		data = 0x02;
+		break;
+	case VIA_CLKSRC_TVPLL:
+		data = 0x04; /* 0x06 should be the same */
+		break;
+	case VIA_CLKSRC_DVP1TVCLKR:
+		data = 0x0A;
+		break;
+	case VIA_CLKSRC_CAP0:
+		data = 0xC;
+		break;
+	case VIA_CLKSRC_CAP1:
+		data = 0x0E;
+		break;
+	}
+
+	if (!use_pll)
+		data |= 1;
+
+	return data;
+}
+
+static void set_primary_clock_source(enum via_clksrc source, bool use_pll)
+{
+	u8 data = set_clock_source_common(source, use_pll) << 4;
+	via_write_reg_mask(VIACR, 0x6C, data, 0xF0);
+}
+
+static void set_secondary_clock_source(enum via_clksrc source, bool use_pll)
+{
+	u8 data = set_clock_source_common(source, use_pll);
+	via_write_reg_mask(VIACR, 0x6C, data, 0x0F);
+}
+
+static void dummy_set_clock_state(u8 state)
+{
+	printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap);
+}
+
+static void dummy_set_clock_source(enum via_clksrc source, bool use_pll)
+{
+	printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap);
+}
+
+static void dummy_set_pll_state(u8 state)
+{
+	printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap);
+}
+
+static void dummy_set_pll(struct via_pll_config config)
+{
+	printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
+}
+
+static void noop_set_clock_state(u8 state)
+{
+}
+
+void via_clock_init(struct via_clock *clock, int gfx_chip)
+{
+	switch (gfx_chip) {
+	case UNICHROME_CLE266:
+	case UNICHROME_K400:
+		clock->set_primary_clock_state = dummy_set_clock_state;
+		clock->set_primary_clock_source = dummy_set_clock_source;
+		clock->set_primary_pll_state = dummy_set_pll_state;
+		clock->set_primary_pll = cle266_set_primary_pll;
+
+		clock->set_secondary_clock_state = dummy_set_clock_state;
+		clock->set_secondary_clock_source = dummy_set_clock_source;
+		clock->set_secondary_pll_state = dummy_set_pll_state;
+		clock->set_secondary_pll = cle266_set_secondary_pll;
+
+		clock->set_engine_pll_state = dummy_set_pll_state;
+		clock->set_engine_pll = dummy_set_pll;
+		break;
+	case UNICHROME_K800:
+	case UNICHROME_PM800:
+	case UNICHROME_CN700:
+	case UNICHROME_CX700:
+	case UNICHROME_CN750:
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M890:
+	case UNICHROME_P4M900:
+	case UNICHROME_VX800:
+		clock->set_primary_clock_state = set_primary_clock_state;
+		clock->set_primary_clock_source = set_primary_clock_source;
+		clock->set_primary_pll_state = set_primary_pll_state;
+		clock->set_primary_pll = k800_set_primary_pll;
+
+		clock->set_secondary_clock_state = set_secondary_clock_state;
+		clock->set_secondary_clock_source = set_secondary_clock_source;
+		clock->set_secondary_pll_state = set_secondary_pll_state;
+		clock->set_secondary_pll = k800_set_secondary_pll;
+
+		clock->set_engine_pll_state = set_engine_pll_state;
+		clock->set_engine_pll = k800_set_engine_pll;
+		break;
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		clock->set_primary_clock_state = set_primary_clock_state;
+		clock->set_primary_clock_source = set_primary_clock_source;
+		clock->set_primary_pll_state = set_primary_pll_state;
+		clock->set_primary_pll = vx855_set_primary_pll;
+
+		clock->set_secondary_clock_state = set_secondary_clock_state;
+		clock->set_secondary_clock_source = set_secondary_clock_source;
+		clock->set_secondary_pll_state = set_secondary_pll_state;
+		clock->set_secondary_pll = vx855_set_secondary_pll;
+
+		clock->set_engine_pll_state = set_engine_pll_state;
+		clock->set_engine_pll = vx855_set_engine_pll;
+		break;
+
+	}
+
+	if (machine_is_olpc()) {
+		/* The OLPC XO-1.5 cannot suspend/resume reliably if the
+		 * IGA1/IGA2 clocks are set as on or off (memory rot
+		 * occasionally happens during suspend under such
+		 * configurations).
+		 *
+		 * The only known stable scenario is to leave this bits as-is,
+		 * which in their default states are documented to enable the
+		 * clock only when it is needed.
+		 */
+		clock->set_primary_clock_state = noop_set_clock_state;
+		clock->set_secondary_clock_state = noop_set_clock_state;
+	}
+}
diff --git a/drivers/video/fbdev/via/via_clock.h b/drivers/video/fbdev/via/via_clock.h
new file mode 100644
index 000000000000..88714ae0d157
--- /dev/null
+++ b/drivers/video/fbdev/via/via_clock.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * clock and PLL management functions
+ */
+
+#ifndef __VIA_CLOCK_H__
+#define __VIA_CLOCK_H__
+
+#include <linux/types.h>
+
+enum via_clksrc {
+	VIA_CLKSRC_X1 = 0,
+	VIA_CLKSRC_TVX1,
+	VIA_CLKSRC_TVPLL,
+	VIA_CLKSRC_DVP1TVCLKR,
+	VIA_CLKSRC_CAP0,
+	VIA_CLKSRC_CAP1,
+};
+
+struct via_pll_config {
+	u16 multiplier;
+	u8 divisor;
+	u8 rshift;
+};
+
+struct via_clock {
+	void (*set_primary_clock_state)(u8 state);
+	void (*set_primary_clock_source)(enum via_clksrc src, bool use_pll);
+	void (*set_primary_pll_state)(u8 state);
+	void (*set_primary_pll)(struct via_pll_config config);
+
+	void (*set_secondary_clock_state)(u8 state);
+	void (*set_secondary_clock_source)(enum via_clksrc src, bool use_pll);
+	void (*set_secondary_pll_state)(u8 state);
+	void (*set_secondary_pll)(struct via_pll_config config);
+
+	void (*set_engine_pll_state)(u8 state);
+	void (*set_engine_pll)(struct via_pll_config config);
+};
+
+
+static inline u32 get_pll_internal_frequency(u32 ref_freq,
+	struct via_pll_config pll)
+{
+	return ref_freq / pll.divisor * pll.multiplier;
+}
+
+static inline u32 get_pll_output_frequency(u32 ref_freq,
+	struct via_pll_config pll)
+{
+	return get_pll_internal_frequency(ref_freq, pll) >> pll.rshift;
+}
+
+void via_clock_init(struct via_clock *clock, int gfx_chip);
+
+#endif /* __VIA_CLOCK_H__ */
diff --git a/drivers/video/fbdev/via/via_i2c.c b/drivers/video/fbdev/via/via_i2c.c
new file mode 100644
index 000000000000..dd53058bbbb7
--- /dev/null
+++ b/drivers/video/fbdev/via/via_i2c.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/via-core.h>
+#include <linux/via_i2c.h>
+
+/*
+ * There can only be one set of these, so there's no point in having
+ * them be dynamically allocated...
+ */
+#define VIAFB_NUM_I2C		5
+static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
+static struct viafb_dev *i2c_vdev;  /* Passed in from core */
+
+static void via_i2c_setscl(void *data, int state)
+{
+	u8 val;
+	struct via_port_cfg *adap_data = data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
+	val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
+	if (state)
+		val |= 0x20;
+	else
+		val &= ~0x20;
+	switch (adap_data->type) {
+	case VIA_PORT_I2C:
+		val |= 0x01;
+		break;
+	case VIA_PORT_GPIO:
+		val |= 0x82;
+		break;
+	default:
+		printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
+	}
+	via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
+	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
+}
+
+static int via_i2c_getscl(void *data)
+{
+	struct via_port_cfg *adap_data = data;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
+	if (adap_data->type == VIA_PORT_GPIO)
+		via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
+			0, 0x80);
+	if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08)
+		ret = 1;
+	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
+	return ret;
+}
+
+static int via_i2c_getsda(void *data)
+{
+	struct via_port_cfg *adap_data = data;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
+	if (adap_data->type == VIA_PORT_GPIO)
+		via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
+			0, 0x40);
+	if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04)
+		ret = 1;
+	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
+	return ret;
+}
+
+static void via_i2c_setsda(void *data, int state)
+{
+	u8 val;
+	struct via_port_cfg *adap_data = data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
+	val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
+	if (state)
+		val |= 0x10;
+	else
+		val &= ~0x10;
+	switch (adap_data->type) {
+	case VIA_PORT_I2C:
+		val |= 0x01;
+		break;
+	case VIA_PORT_GPIO:
+		val |= 0x42;
+		break;
+	default:
+		printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
+	}
+	via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
+	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
+}
+
+int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
+{
+	int ret;
+	u8 mm1[] = {0x00};
+	struct i2c_msg msgs[2];
+
+	if (!via_i2c_par[adap].is_active)
+		return -ENODEV;
+	*pdata = 0;
+	msgs[0].flags = 0;
+	msgs[1].flags = I2C_M_RD;
+	msgs[0].addr = msgs[1].addr = slave_addr / 2;
+	mm1[0] = index;
+	msgs[0].len = 1; msgs[1].len = 1;
+	msgs[0].buf = mm1; msgs[1].buf = pdata;
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	if (ret == 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
+{
+	int ret;
+	u8 msg[2] = { index, data };
+	struct i2c_msg msgs;
+
+	if (!via_i2c_par[adap].is_active)
+		return -ENODEV;
+	msgs.flags = 0;
+	msgs.addr = slave_addr / 2;
+	msgs.len = 2;
+	msgs.buf = msg;
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
+	if (ret == 1)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
+{
+	int ret;
+	u8 mm1[] = {0x00};
+	struct i2c_msg msgs[2];
+
+	if (!via_i2c_par[adap].is_active)
+		return -ENODEV;
+	msgs[0].flags = 0;
+	msgs[1].flags = I2C_M_RD;
+	msgs[0].addr = msgs[1].addr = slave_addr / 2;
+	mm1[0] = index;
+	msgs[0].len = 1; msgs[1].len = buff_len;
+	msgs[0].buf = mm1; msgs[1].buf = buff;
+	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
+	if (ret == 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+/*
+ * Allow other viafb subdevices to look up a specific adapter
+ * by port name.
+ */
+struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which)
+{
+	struct via_i2c_stuff *stuff = &via_i2c_par[which];
+
+	return &stuff->adapter;
+}
+EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter);
+
+
+static int create_i2c_bus(struct i2c_adapter *adapter,
+			  struct i2c_algo_bit_data *algo,
+			  struct via_port_cfg *adap_cfg,
+			  struct pci_dev *pdev)
+{
+	algo->setsda = via_i2c_setsda;
+	algo->setscl = via_i2c_setscl;
+	algo->getsda = via_i2c_getsda;
+	algo->getscl = via_i2c_getscl;
+	algo->udelay = 10;
+	algo->timeout = 2;
+	algo->data = adap_cfg;
+
+	sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
+		adap_cfg->ioport_index);
+	adapter->owner = THIS_MODULE;
+	adapter->class = I2C_CLASS_DDC;
+	adapter->algo_data = algo;
+	if (pdev)
+		adapter->dev.parent = &pdev->dev;
+	else
+		adapter->dev.parent = NULL;
+	/* i2c_set_adapdata(adapter, adap_cfg); */
+
+	/* Raise SCL and SDA */
+	via_i2c_setsda(adap_cfg, 1);
+	via_i2c_setscl(adap_cfg, 1);
+	udelay(20);
+
+	return i2c_bit_add_bus(adapter);
+}
+
+static int viafb_i2c_probe(struct platform_device *platdev)
+{
+	int i, ret;
+	struct via_port_cfg *configs;
+
+	i2c_vdev = platdev->dev.platform_data;
+	configs = i2c_vdev->port_cfg;
+
+	for (i = 0; i < VIAFB_NUM_PORTS; i++) {
+		struct via_port_cfg *adap_cfg = configs++;
+		struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
+
+		i2c_stuff->is_active = 0;
+		if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C)
+			continue;
+		ret = create_i2c_bus(&i2c_stuff->adapter,
+				     &i2c_stuff->algo, adap_cfg,
+				NULL); /* FIXME: PCIDEV */
+		if (ret < 0) {
+			printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n",
+				i, ret);
+			continue;  /* Still try to make the rest */
+		}
+		i2c_stuff->is_active = 1;
+	}
+
+	return 0;
+}
+
+static int viafb_i2c_remove(struct platform_device *platdev)
+{
+	int i;
+
+	for (i = 0; i < VIAFB_NUM_PORTS; i++) {
+		struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
+		/*
+		 * Only remove those entries in the array that we've
+		 * actually used (and thus initialized algo_data)
+		 */
+		if (i2c_stuff->is_active)
+			i2c_del_adapter(&i2c_stuff->adapter);
+	}
+	return 0;
+}
+
+static struct platform_driver via_i2c_driver = {
+	.driver = {
+		.name = "viafb-i2c",
+	},
+	.probe = viafb_i2c_probe,
+	.remove = viafb_i2c_remove,
+};
+
+int viafb_i2c_init(void)
+{
+	return platform_driver_register(&via_i2c_driver);
+}
+
+void viafb_i2c_exit(void)
+{
+	platform_driver_unregister(&via_i2c_driver);
+}
diff --git a/drivers/video/fbdev/via/via_modesetting.c b/drivers/video/fbdev/via/via_modesetting.c
new file mode 100644
index 000000000000..0b414b09b9b4
--- /dev/null
+++ b/drivers/video/fbdev/via/via_modesetting.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * basic modesetting functions
+ */
+
+#include <linux/kernel.h>
+#include <linux/via-core.h>
+#include "via_modesetting.h"
+#include "share.h"
+#include "debug.h"
+
+
+void via_set_primary_timing(const struct via_display_timing *timing)
+{
+	struct via_display_timing raw;
+
+	raw.hor_total = timing->hor_total / 8 - 5;
+	raw.hor_addr = timing->hor_addr / 8 - 1;
+	raw.hor_blank_start = timing->hor_blank_start / 8 - 1;
+	raw.hor_blank_end = timing->hor_blank_end / 8 - 1;
+	raw.hor_sync_start = timing->hor_sync_start / 8;
+	raw.hor_sync_end = timing->hor_sync_end / 8;
+	raw.ver_total = timing->ver_total - 2;
+	raw.ver_addr = timing->ver_addr - 1;
+	raw.ver_blank_start = timing->ver_blank_start - 1;
+	raw.ver_blank_end = timing->ver_blank_end - 1;
+	raw.ver_sync_start = timing->ver_sync_start - 1;
+	raw.ver_sync_end = timing->ver_sync_end - 1;
+
+	/* unlock timing registers */
+	via_write_reg_mask(VIACR, 0x11, 0x00, 0x80);
+
+	via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF);
+	via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF);
+	via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF);
+	via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F);
+	via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF);
+	via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F)
+		| (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F);
+	via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF);
+	via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01)
+		| (raw.ver_addr >> (8 - 1) & 0x02)
+		| (raw.ver_sync_start >> (8 - 2) & 0x04)
+		| (raw.ver_blank_start >> (8 - 3) & 0x08)
+		| (raw.ver_total >> (9 - 5) & 0x20)
+		| (raw.ver_addr >> (9 - 6) & 0x40)
+		| (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF);
+	via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20,
+		0x20);
+	via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF);
+	via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F);
+	via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF);
+	via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF);
+	via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF);
+	via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10)
+		| (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30);
+	via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01)
+		| (raw.ver_sync_start >> (10 - 1) & 0x02)
+		| (raw.ver_addr >> (10 - 2) & 0x04)
+		| (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F);
+	via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08);
+
+	/* lock timing registers */
+	via_write_reg_mask(VIACR, 0x11, 0x80, 0x80);
+
+	/* reset timing control */
+	via_write_reg_mask(VIACR, 0x17, 0x00, 0x80);
+	via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
+}
+
+void via_set_secondary_timing(const struct via_display_timing *timing)
+{
+	struct via_display_timing raw;
+
+	raw.hor_total = timing->hor_total - 1;
+	raw.hor_addr = timing->hor_addr - 1;
+	raw.hor_blank_start = timing->hor_blank_start - 1;
+	raw.hor_blank_end = timing->hor_blank_end - 1;
+	raw.hor_sync_start = timing->hor_sync_start - 1;
+	raw.hor_sync_end = timing->hor_sync_end - 1;
+	raw.ver_total = timing->ver_total - 1;
+	raw.ver_addr = timing->ver_addr - 1;
+	raw.ver_blank_start = timing->ver_blank_start - 1;
+	raw.ver_blank_end = timing->ver_blank_end - 1;
+	raw.ver_sync_start = timing->ver_sync_start - 1;
+	raw.ver_sync_end = timing->ver_sync_end - 1;
+
+	via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF);
+	via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF);
+	via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF);
+	via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF);
+	via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07)
+		| (raw.hor_blank_end >> (8 - 3) & 0x38)
+		| (raw.hor_sync_start >> (8 - 6) & 0xC0));
+	via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F)
+		| (raw.hor_addr >> (8 - 4) & 0x70), 0x7F);
+	via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF);
+	via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF);
+	via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF);
+	via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF);
+	via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF);
+	via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF);
+	via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07)
+		| (raw.ver_blank_end >> (8 - 3) & 0x38)
+		| (raw.hor_sync_end >> (8 - 6) & 0x40)
+		| (raw.hor_sync_start >> (10 - 7) & 0x80));
+	via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07)
+		| (raw.ver_addr >> (8 - 3) & 0x38)
+		| (raw.hor_blank_end >> (11 - 6) & 0x40)
+		| (raw.hor_sync_start >> (11 - 7) & 0x80));
+	via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF);
+	via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F)
+		| (raw.ver_sync_start >> (8 - 5) & 0xE0));
+}
+
+void via_set_primary_address(u32 addr)
+{
+	DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
+	via_write_reg(VIACR, 0x0D, addr & 0xFF);
+	via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF);
+	via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF);
+	via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F);
+}
+
+void via_set_secondary_address(u32 addr)
+{
+	DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr);
+	/* secondary display supports only quadword aligned memory */
+	via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE);
+	via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF);
+	via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF);
+	via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07);
+}
+
+void via_set_primary_pitch(u32 pitch)
+{
+	DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch);
+	/* spec does not say that first adapter skips 3 bits but old
+	 * code did it and seems to be reasonable in analogy to 2nd adapter
+	 */
+	pitch = pitch >> 3;
+	via_write_reg(VIACR, 0x13, pitch & 0xFF);
+	via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0);
+}
+
+void via_set_secondary_pitch(u32 pitch)
+{
+	DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch);
+	pitch = pitch >> 3;
+	via_write_reg(VIACR, 0x66, pitch & 0xFF);
+	via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03);
+	via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80);
+}
+
+void via_set_primary_color_depth(u8 depth)
+{
+	u8 value;
+
+	DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth);
+	switch (depth) {
+	case 8:
+		value = 0x00;
+		break;
+	case 15:
+		value = 0x04;
+		break;
+	case 16:
+		value = 0x14;
+		break;
+	case 24:
+		value = 0x0C;
+		break;
+	case 30:
+		value = 0x08;
+		break;
+	default:
+		printk(KERN_WARNING "via_set_primary_color_depth: "
+			"Unsupported depth: %d\n", depth);
+		return;
+	}
+
+	via_write_reg_mask(VIASR, 0x15, value, 0x1C);
+}
+
+void via_set_secondary_color_depth(u8 depth)
+{
+	u8 value;
+
+	DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth);
+	switch (depth) {
+	case 8:
+		value = 0x00;
+		break;
+	case 16:
+		value = 0x40;
+		break;
+	case 24:
+		value = 0xC0;
+		break;
+	case 30:
+		value = 0x80;
+		break;
+	default:
+		printk(KERN_WARNING "via_set_secondary_color_depth: "
+			"Unsupported depth: %d\n", depth);
+		return;
+	}
+
+	via_write_reg_mask(VIACR, 0x67, value, 0xC0);
+}
diff --git a/drivers/video/fbdev/via/via_modesetting.h b/drivers/video/fbdev/via/via_modesetting.h
new file mode 100644
index 000000000000..f6a6503da3b3
--- /dev/null
+++ b/drivers/video/fbdev/via/via_modesetting.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * basic modesetting functions
+ */
+
+#ifndef __VIA_MODESETTING_H__
+#define __VIA_MODESETTING_H__
+
+#include <linux/types.h>
+
+
+#define VIA_PITCH_SIZE	(1<<3)
+#define VIA_PITCH_MAX	0x3FF8
+
+
+struct via_display_timing {
+	u16 hor_total;
+	u16 hor_addr;
+	u16 hor_blank_start;
+	u16 hor_blank_end;
+	u16 hor_sync_start;
+	u16 hor_sync_end;
+	u16 ver_total;
+	u16 ver_addr;
+	u16 ver_blank_start;
+	u16 ver_blank_end;
+	u16 ver_sync_start;
+	u16 ver_sync_end;
+};
+
+
+void via_set_primary_timing(const struct via_display_timing *timing);
+void via_set_secondary_timing(const struct via_display_timing *timing);
+void via_set_primary_address(u32 addr);
+void via_set_secondary_address(u32 addr);
+void via_set_primary_pitch(u32 pitch);
+void via_set_secondary_pitch(u32 pitch);
+void via_set_primary_color_depth(u8 depth);
+void via_set_secondary_color_depth(u8 depth);
+
+#endif /* __VIA_MODESETTING_H__ */
diff --git a/drivers/video/fbdev/via/via_utility.c b/drivers/video/fbdev/via/via_utility.c
new file mode 100644
index 000000000000..35458a5eadc8
--- /dev/null
+++ b/drivers/video/fbdev/via/via_utility.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/via-core.h>
+#include "global.h"
+
+void viafb_get_device_support_state(u32 *support_state)
+{
+	*support_state = CRT_Device;
+
+	if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS)
+		*support_state |= DVI_Device;
+
+	if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS)
+		*support_state |= LCD_Device;
+}
+
+void viafb_get_device_connect_state(u32 *connect_state)
+{
+	bool mobile = false;
+
+	*connect_state = CRT_Device;
+
+	if (viafb_dvi_sense())
+		*connect_state |= DVI_Device;
+
+	viafb_lcd_get_mobile_state(&mobile);
+	if (mobile)
+		*connect_state |= LCD_Device;
+}
+
+bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres)
+{
+	unsigned int support_state = 0;
+
+	switch (viafb_lcd_panel_id) {
+	case LCD_PANEL_ID0_640X480:
+		if ((xres < 640) && (yres < 480))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID1_800X600:
+		if ((xres < 800) && (yres < 600))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID2_1024X768:
+		if ((xres < 1024) && (yres < 768))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID3_1280X768:
+		if ((xres < 1280) && (yres < 768))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID4_1280X1024:
+		if ((xres < 1280) && (yres < 1024))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID5_1400X1050:
+		if ((xres < 1400) && (yres < 1050))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID6_1600X1200:
+		if ((xres < 1600) && (yres < 1200))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID7_1366X768:
+		if ((xres < 1366) && (yres < 768))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID8_1024X600:
+		if ((xres < 1024) && (yres < 600))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_ID9_1280X800:
+		if ((xres < 1280) && (yres < 800))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_IDA_800X480:
+		if ((xres < 800) && (yres < 480))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_IDB_1360X768:
+		if ((xres < 1360) && (yres < 768))
+			support_state = true;
+		break;
+
+	case LCD_PANEL_IDC_480X640:
+		if ((xres < 480) && (yres < 640))
+			support_state = true;
+		break;
+
+	default:
+		support_state = false;
+		break;
+	}
+
+	return support_state;
+}
+
+/*====================================================================*/
+/*                      Gamma Function Implementation*/
+/*====================================================================*/
+
+void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
+{
+	int i, sr1a;
+	int active_device_amount = 0;
+	int device_status = viafb_DeviceStatus;
+
+	for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) {
+		if (device_status & 1)
+			active_device_amount++;
+		device_status >>= 1;
+	}
+
+	/* 8 bpp mode can't adjust gamma */
+	if (bpp == 8)
+		return ;
+
+	/* Enable Gamma */
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_CLE266:
+	case UNICHROME_K400:
+		viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
+		break;
+
+	case UNICHROME_K800:
+	case UNICHROME_PM800:
+	case UNICHROME_CN700:
+	case UNICHROME_CX700:
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M890:
+	case UNICHROME_P4M900:
+		viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
+		break;
+	}
+	sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A);
+	viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
+
+	/* Fill IGA1 Gamma Table */
+	outb(0, LUT_INDEX_WRITE);
+	for (i = 0; i < 256; i++) {
+		outb(gamma_table[i] >> 16, LUT_DATA);
+		outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
+		outb(gamma_table[i] & 0xFF, LUT_DATA);
+	}
+
+	/* If adjust Gamma value in SAMM, fill IGA1,
+	   IGA2 Gamma table simultaneous. */
+	/* Switch to IGA2 Gamma Table */
+	if ((active_device_amount > 1) &&
+		!((viaparinfo->chip_info->gfx_chip_name ==
+		UNICHROME_CLE266) &&
+		(viaparinfo->chip_info->gfx_chip_revision < 15))) {
+		viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
+		viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1);
+
+		/* Fill IGA2 Gamma Table */
+		outb(0, LUT_INDEX_WRITE);
+		for (i = 0; i < 256; i++) {
+			outb(gamma_table[i] >> 16, LUT_DATA);
+			outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
+			outb(gamma_table[i] & 0xFF, LUT_DATA);
+		}
+	}
+	viafb_write_reg(SR1A, VIASR, sr1a);
+}
+
+void viafb_get_gamma_table(unsigned int *gamma_table)
+{
+	unsigned char color_r, color_g, color_b;
+	unsigned char sr1a = 0;
+	int i;
+
+	/* Enable Gamma */
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_CLE266:
+	case UNICHROME_K400:
+		viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
+		break;
+
+	case UNICHROME_K800:
+	case UNICHROME_PM800:
+	case UNICHROME_CN700:
+	case UNICHROME_CX700:
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M890:
+	case UNICHROME_P4M900:
+		viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
+		break;
+	}
+	sr1a = viafb_read_reg(VIASR, SR1A);
+	viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
+
+	/* Reading gamma table to get color value */
+	outb(0, LUT_INDEX_READ);
+	for (i = 0; i < 256; i++) {
+		color_r = inb(LUT_DATA);
+		color_g = inb(LUT_DATA);
+		color_b = inb(LUT_DATA);
+		gamma_table[i] =
+		    ((((u32) color_r) << 16) |
+		     (((u16) color_g) << 8)) | color_b;
+	}
+	viafb_write_reg(SR1A, VIASR, sr1a);
+}
+
+void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
+{
+	if (bpp == 8)
+		*support_state = None_Device;
+	else
+		*support_state = CRT_Device | DVI_Device | LCD_Device;
+}
diff --git a/drivers/video/fbdev/via/via_utility.h b/drivers/video/fbdev/via/via_utility.h
new file mode 100644
index 000000000000..f23be1708c14
--- /dev/null
+++ b/drivers/video/fbdev/via/via_utility.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __VIAUTILITY_H__
+#define __VIAUTILITY_H__
+
+/* These functions are used to get information about device's state */
+void viafb_get_device_support_state(u32 *support_state);
+void viafb_get_device_connect_state(u32 *connect_state);
+bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
+
+/* These function are used to access gamma table */
+void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
+void viafb_get_gamma_table(unsigned int *gamma_table);
+void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
+
+#endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
new file mode 100644
index 000000000000..325c43c6ff97
--- /dev/null
+++ b/drivers/video/fbdev/via/viafbdev.c
@@ -0,0 +1,2176 @@
+/*
+ * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/via-core.h>
+#include <linux/via_i2c.h>
+#include <asm/olpc.h>
+
+#define _MASTER_FILE
+#include "global.h"
+
+static char *viafb_name = "Via";
+static u32 pseudo_pal[17];
+
+/* video mode */
+static char *viafb_mode;
+static char *viafb_mode1;
+static int viafb_bpp = 32;
+static int viafb_bpp1 = 32;
+
+static unsigned int viafb_second_offset;
+static int viafb_second_size;
+
+static int viafb_accel = 1;
+
+/* Added for specifying active devices.*/
+static char *viafb_active_dev;
+
+/*Added for specify lcd output port*/
+static char *viafb_lcd_port = "";
+static char *viafb_dvi_port = "";
+
+static void retrieve_device_setting(struct viafb_ioctl_setting
+	*setting_info);
+static int viafb_pan_display(struct fb_var_screeninfo *var,
+	struct fb_info *info);
+
+static struct fb_ops viafb_ops;
+
+/* supported output devices on each IGP
+ * only CX700, VX800, VX855, VX900 were documented
+ * VIA_CRT should be everywhere
+ * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
+ * source selection on CX700 and later
+ * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
+ */
+static const u32 supported_odev_map[] = {
+	[UNICHROME_CLE266]	= VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
+	[UNICHROME_K400]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_K800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_PM800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_CN700]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
+				| VIA_LVDS2,
+	[UNICHROME_CX700]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_CN750]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_K8M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_P4M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_P4M900]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_VX800]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_VX855]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+	[UNICHROME_VX900]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
+};
+
+static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
+{
+	var->grayscale = 0;
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	var->nonstd = 0;
+	switch (depth) {
+	case 8:
+		var->bits_per_pixel = 8;
+		var->red.offset = 0;
+		var->green.offset = 0;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case 15:
+		var->bits_per_pixel = 16;
+		var->red.offset = 10;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		break;
+	case 16:
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case 24:
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case 30:
+		var->bits_per_pixel = 32;
+		var->red.offset = 20;
+		var->green.offset = 10;
+		var->blue.offset = 0;
+		var->red.length = 10;
+		var->green.length = 10;
+		var->blue.length = 10;
+		break;
+	}
+}
+
+static void viafb_update_fix(struct fb_info *info)
+{
+	u32 bpp = info->var.bits_per_pixel;
+
+	info->fix.visual =
+		bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
+		VIA_PITCH_SIZE);
+}
+
+static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
+	struct viafb_par *viaparinfo)
+{
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strcpy(fix->id, viafb_name);
+
+	fix->smem_start = viaparinfo->fbmem;
+	fix->smem_len = viaparinfo->fbmem_free;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+
+	fix->xpanstep = fix->ywrapstep = 0;
+	fix->ypanstep = 1;
+
+	/* Just tell the accel name */
+	viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
+}
+static int viafb_open(struct fb_info *info, int user)
+{
+	DEBUG_MSG(KERN_INFO "viafb_open!\n");
+	return 0;
+}
+
+static int viafb_release(struct fb_info *info, int user)
+{
+	DEBUG_MSG(KERN_INFO "viafb_release!\n");
+	return 0;
+}
+
+static inline int get_var_refresh(struct fb_var_screeninfo *var)
+{
+	u32 htotal, vtotal;
+
+	htotal = var->left_margin + var->xres + var->right_margin
+		+ var->hsync_len;
+	vtotal = var->upper_margin + var->yres + var->lower_margin
+		+ var->vsync_len;
+	return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
+}
+
+static int viafb_check_var(struct fb_var_screeninfo *var,
+	struct fb_info *info)
+{
+	int depth, refresh;
+	struct viafb_par *ppar = info->par;
+	u32 line;
+
+	DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
+	/* Sanity check */
+	/* HW neither support interlacte nor double-scaned mode */
+	if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
+		return -EINVAL;
+
+	/* the refresh rate is not important here, as we only want to know
+	 * whether the resolution exists
+	 */
+	if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
+		DEBUG_MSG(KERN_INFO
+			  "viafb: Mode %dx%dx%d not supported!!\n",
+			  var->xres, var->yres, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	depth = fb_get_color_depth(var, &info->fix);
+	if (!depth)
+		depth = var->bits_per_pixel;
+
+	if (depth < 0 || depth > 32)
+		return -EINVAL;
+	else if (!depth)
+		depth = 24;
+	else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
+		depth = 15;
+	else if (depth == 30)
+		depth = 30;
+	else if (depth <= 8)
+		depth = 8;
+	else if (depth <= 16)
+		depth = 16;
+	else
+		depth = 24;
+
+	viafb_fill_var_color_info(var, depth);
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
+		VIA_PITCH_SIZE);
+	if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
+		return -EINVAL;
+
+	/* Based on var passed in to calculate the refresh,
+	 * because our driver use some modes special.
+	 */
+	refresh = viafb_get_refresh(var->xres, var->yres,
+		get_var_refresh(var));
+
+	/* Adjust var according to our driver's own table */
+	viafb_fill_var_timing_info(var,
+		viafb_get_best_mode(var->xres, var->yres, refresh));
+	if (var->accel_flags & FB_ACCELF_TEXT &&
+		!ppar->shared->vdev->engine_mmio)
+		var->accel_flags = 0;
+
+	return 0;
+}
+
+static int viafb_set_par(struct fb_info *info)
+{
+	struct viafb_par *viapar = info->par;
+	int refresh;
+	DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
+
+	viafb_update_fix(info);
+	viapar->depth = fb_get_color_depth(&info->var, &info->fix);
+	viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
+		viafbinfo->var.bits_per_pixel, 0);
+
+	if (viafb_dual_fb) {
+		viafb_update_device_setting(viafbinfo1->var.xres,
+			viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
+			1);
+	} else if (viafb_SAMM_ON == 1) {
+		DEBUG_MSG(KERN_INFO
+		"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
+			  viafb_second_xres, viafb_second_yres, viafb_bpp1);
+
+		viafb_update_device_setting(viafb_second_xres,
+			viafb_second_yres, viafb_bpp1, 1);
+	}
+
+	refresh = get_var_refresh(&info->var);
+	if (viafb_dual_fb && viapar->iga_path == IGA2) {
+		viafb_bpp1 = info->var.bits_per_pixel;
+		viafb_refresh1 = refresh;
+	} else {
+		viafb_bpp = info->var.bits_per_pixel;
+		viafb_refresh = refresh;
+	}
+
+	if (info->var.accel_flags & FB_ACCELF_TEXT)
+		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+	else
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+	viafb_setmode();
+	viafb_pan_display(&info->var, info);
+
+	return 0;
+}
+
+/* Set one color register */
+static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+unsigned blue, unsigned transp, struct fb_info *info)
+{
+	struct viafb_par *viapar = info->par;
+	u32 r, g, b;
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		if (regno > 255)
+			return -EINVAL;
+
+		if (!viafb_dual_fb || viapar->iga_path == IGA1)
+			viafb_set_primary_color_register(regno, red >> 8,
+				green >> 8, blue >> 8);
+
+		if (!viafb_dual_fb || viapar->iga_path == IGA2)
+			viafb_set_secondary_color_register(regno, red >> 8,
+				green >> 8, blue >> 8);
+	} else {
+		if (regno > 15)
+			return -EINVAL;
+
+		r = (red >> (16 - info->var.red.length))
+			<< info->var.red.offset;
+		b = (blue >> (16 - info->var.blue.length))
+			<< info->var.blue.offset;
+		g = (green >> (16 - info->var.green.length))
+			<< info->var.green.offset;
+		((u32 *) info->pseudo_palette)[regno] = r | g | b;
+	}
+
+	return 0;
+}
+
+static int viafb_pan_display(struct fb_var_screeninfo *var,
+	struct fb_info *info)
+{
+	struct viafb_par *viapar = info->par;
+	u32 vram_addr = viapar->vram_addr
+		+ var->yoffset * info->fix.line_length
+		+ var->xoffset * info->var.bits_per_pixel / 8;
+
+	DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
+	if (!viafb_dual_fb) {
+		via_set_primary_address(vram_addr);
+		via_set_secondary_address(vram_addr);
+	} else if (viapar->iga_path == IGA1)
+		via_set_primary_address(vram_addr);
+	else
+		via_set_secondary_address(vram_addr);
+
+	return 0;
+}
+
+static int viafb_blank(int blank_mode, struct fb_info *info)
+{
+	DEBUG_MSG(KERN_INFO "viafb_blank!\n");
+	/* clear DPMS setting */
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		/* Screen: On, HSync: On, VSync: On */
+		/* control CRT monitor power management */
+		via_set_state(VIA_CRT, VIA_STATE_ON);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		/* Screen: Off, HSync: Off, VSync: On */
+		/* control CRT monitor power management */
+		via_set_state(VIA_CRT, VIA_STATE_STANDBY);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		/* Screen: Off, HSync: On, VSync: Off */
+		/* control CRT monitor power management */
+		via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
+		break;
+	case FB_BLANK_POWERDOWN:
+		/* Screen: Off, HSync: Off, VSync: Off */
+		/* control CRT monitor power management */
+		via_set_state(VIA_CRT, VIA_STATE_OFF);
+		break;
+	}
+
+	return 0;
+}
+
+static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+{
+	union {
+		struct viafb_ioctl_mode viamode;
+		struct viafb_ioctl_samm viasamm;
+		struct viafb_driver_version driver_version;
+		struct fb_var_screeninfo sec_var;
+		struct _panel_size_pos_info panel_pos_size_para;
+		struct viafb_ioctl_setting viafb_setting;
+		struct device_t active_dev;
+	} u;
+	u32 state_info = 0;
+	u32 *viafb_gamma_table;
+	char driver_name[] = "viafb";
+
+	u32 __user *argp = (u32 __user *) arg;
+	u32 gpu32;
+
+	DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
+	printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
+	memset(&u, 0, sizeof(u));
+
+	switch (cmd) {
+	case VIAFB_GET_CHIP_INFO:
+		if (copy_to_user(argp, viaparinfo->chip_info,
+				sizeof(struct chip_information)))
+			return -EFAULT;
+		break;
+	case VIAFB_GET_INFO_SIZE:
+		return put_user((u32)sizeof(struct viafb_ioctl_info), argp);
+	case VIAFB_GET_INFO:
+		return viafb_ioctl_get_viafb_info(arg);
+	case VIAFB_HOTPLUG:
+		return put_user(viafb_ioctl_hotplug(info->var.xres,
+					      info->var.yres,
+					      info->var.bits_per_pixel), argp);
+	case VIAFB_SET_HOTPLUG_FLAG:
+		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+			return -EFAULT;
+		viafb_hotplug = (gpu32) ? 1 : 0;
+		break;
+	case VIAFB_GET_RESOLUTION:
+		u.viamode.xres = (u32) viafb_hotplug_Xres;
+		u.viamode.yres = (u32) viafb_hotplug_Yres;
+		u.viamode.refresh = (u32) viafb_hotplug_refresh;
+		u.viamode.bpp = (u32) viafb_hotplug_bpp;
+		if (viafb_SAMM_ON == 1) {
+			u.viamode.xres_sec = viafb_second_xres;
+			u.viamode.yres_sec = viafb_second_yres;
+			u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual;
+			u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual;
+			u.viamode.refresh_sec = viafb_refresh1;
+			u.viamode.bpp_sec = viafb_bpp1;
+		} else {
+			u.viamode.xres_sec = 0;
+			u.viamode.yres_sec = 0;
+			u.viamode.virtual_xres_sec = 0;
+			u.viamode.virtual_yres_sec = 0;
+			u.viamode.refresh_sec = 0;
+			u.viamode.bpp_sec = 0;
+		}
+		if (copy_to_user(argp, &u.viamode, sizeof(u.viamode)))
+			return -EFAULT;
+		break;
+	case VIAFB_GET_SAMM_INFO:
+		u.viasamm.samm_status = viafb_SAMM_ON;
+
+		if (viafb_SAMM_ON == 1) {
+			if (viafb_dual_fb) {
+				u.viasamm.size_prim = viaparinfo->fbmem_free;
+				u.viasamm.size_sec = viaparinfo1->fbmem_free;
+			} else {
+				if (viafb_second_size) {
+					u.viasamm.size_prim =
+					    viaparinfo->fbmem_free -
+					    viafb_second_size * 1024 * 1024;
+					u.viasamm.size_sec =
+					    viafb_second_size * 1024 * 1024;
+				} else {
+					u.viasamm.size_prim =
+					    viaparinfo->fbmem_free >> 1;
+					u.viasamm.size_sec =
+					    (viaparinfo->fbmem_free >> 1);
+				}
+			}
+			u.viasamm.mem_base = viaparinfo->fbmem;
+			u.viasamm.offset_sec = viafb_second_offset;
+		} else {
+			u.viasamm.size_prim =
+			    viaparinfo->memsize - viaparinfo->fbmem_used;
+			u.viasamm.size_sec = 0;
+			u.viasamm.mem_base = viaparinfo->fbmem;
+			u.viasamm.offset_sec = 0;
+		}
+
+		if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm)))
+			return -EFAULT;
+
+		break;
+	case VIAFB_TURN_ON_OUTPUT_DEVICE:
+		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+			return -EFAULT;
+		if (gpu32 & CRT_Device)
+			via_set_state(VIA_CRT, VIA_STATE_ON);
+		if (gpu32 & DVI_Device)
+			viafb_dvi_enable();
+		if (gpu32 & LCD_Device)
+			viafb_lcd_enable();
+		break;
+	case VIAFB_TURN_OFF_OUTPUT_DEVICE:
+		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+			return -EFAULT;
+		if (gpu32 & CRT_Device)
+			via_set_state(VIA_CRT, VIA_STATE_OFF);
+		if (gpu32 & DVI_Device)
+			viafb_dvi_disable();
+		if (gpu32 & LCD_Device)
+			viafb_lcd_disable();
+		break;
+	case VIAFB_GET_DEVICE:
+		u.active_dev.crt = viafb_CRT_ON;
+		u.active_dev.dvi = viafb_DVI_ON;
+		u.active_dev.lcd = viafb_LCD_ON;
+		u.active_dev.samm = viafb_SAMM_ON;
+		u.active_dev.primary_dev = viafb_primary_dev;
+
+		u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
+		u.active_dev.lcd_panel_id = viafb_lcd_panel_id;
+		u.active_dev.lcd_mode = viafb_lcd_mode;
+
+		u.active_dev.xres = viafb_hotplug_Xres;
+		u.active_dev.yres = viafb_hotplug_Yres;
+
+		u.active_dev.xres1 = viafb_second_xres;
+		u.active_dev.yres1 = viafb_second_yres;
+
+		u.active_dev.bpp = viafb_bpp;
+		u.active_dev.bpp1 = viafb_bpp1;
+		u.active_dev.refresh = viafb_refresh;
+		u.active_dev.refresh1 = viafb_refresh1;
+
+		u.active_dev.epia_dvi = viafb_platform_epia_dvi;
+		u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
+		u.active_dev.bus_width = viafb_bus_width;
+
+		if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev)))
+			return -EFAULT;
+		break;
+
+	case VIAFB_GET_DRIVER_VERSION:
+		u.driver_version.iMajorNum = VERSION_MAJOR;
+		u.driver_version.iKernelNum = VERSION_KERNEL;
+		u.driver_version.iOSNum = VERSION_OS;
+		u.driver_version.iMinorNum = VERSION_MINOR;
+
+		if (copy_to_user(argp, &u.driver_version,
+			sizeof(u.driver_version)))
+			return -EFAULT;
+
+		break;
+
+	case VIAFB_GET_DEVICE_INFO:
+
+		retrieve_device_setting(&u.viafb_setting);
+
+		if (copy_to_user(argp, &u.viafb_setting,
+				 sizeof(u.viafb_setting)))
+			return -EFAULT;
+
+		break;
+
+	case VIAFB_GET_DEVICE_SUPPORT:
+		viafb_get_device_support_state(&state_info);
+		if (put_user(state_info, argp))
+			return -EFAULT;
+		break;
+
+	case VIAFB_GET_DEVICE_CONNECT:
+		viafb_get_device_connect_state(&state_info);
+		if (put_user(state_info, argp))
+			return -EFAULT;
+		break;
+
+	case VIAFB_GET_PANEL_SUPPORT_EXPAND:
+		state_info =
+		    viafb_lcd_get_support_expand_state(info->var.xres,
+						 info->var.yres);
+		if (put_user(state_info, argp))
+			return -EFAULT;
+		break;
+
+	case VIAFB_GET_DRIVER_NAME:
+		if (copy_to_user(argp, driver_name, sizeof(driver_name)))
+			return -EFAULT;
+		break;
+
+	case VIAFB_SET_GAMMA_LUT:
+		viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32));
+		if (IS_ERR(viafb_gamma_table))
+			return PTR_ERR(viafb_gamma_table);
+		viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
+		kfree(viafb_gamma_table);
+		break;
+
+	case VIAFB_GET_GAMMA_LUT:
+		viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
+		if (!viafb_gamma_table)
+			return -ENOMEM;
+		viafb_get_gamma_table(viafb_gamma_table);
+		if (copy_to_user(argp, viafb_gamma_table,
+			256 * sizeof(u32))) {
+			kfree(viafb_gamma_table);
+			return -EFAULT;
+		}
+		kfree(viafb_gamma_table);
+		break;
+
+	case VIAFB_GET_GAMMA_SUPPORT_STATE:
+		viafb_get_gamma_support_state(viafb_bpp, &state_info);
+		if (put_user(state_info, argp))
+			return -EFAULT;
+		break;
+	case VIAFB_SYNC_SURFACE:
+		DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
+		break;
+	case VIAFB_GET_DRIVER_CAPS:
+		break;
+
+	case VIAFB_GET_PANEL_MAX_SIZE:
+		if (copy_from_user(&u.panel_pos_size_para, argp,
+				   sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+		if (copy_to_user(argp, &u.panel_pos_size_para,
+		     sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		break;
+	case VIAFB_GET_PANEL_MAX_POSITION:
+		if (copy_from_user(&u.panel_pos_size_para, argp,
+				   sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+		if (copy_to_user(argp, &u.panel_pos_size_para,
+				 sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		break;
+
+	case VIAFB_GET_PANEL_POSITION:
+		if (copy_from_user(&u.panel_pos_size_para, argp,
+				   sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+		if (copy_to_user(argp, &u.panel_pos_size_para,
+				 sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		break;
+	case VIAFB_GET_PANEL_SIZE:
+		if (copy_from_user(&u.panel_pos_size_para, argp,
+				   sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+		if (copy_to_user(argp, &u.panel_pos_size_para,
+				 sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		break;
+
+	case VIAFB_SET_PANEL_POSITION:
+		if (copy_from_user(&u.panel_pos_size_para, argp,
+				   sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		break;
+	case VIAFB_SET_PANEL_SIZE:
+		if (copy_from_user(&u.panel_pos_size_para, argp,
+				   sizeof(u.panel_pos_size_para)))
+			return -EFAULT;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void viafb_fillrect(struct fb_info *info,
+	const struct fb_fillrect *rect)
+{
+	struct viafb_par *viapar = info->par;
+	struct viafb_shared *shared = viapar->shared;
+	u32 fg_color;
+	u8 rop;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if (!rect->width || !rect->height)
+		return;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR)
+		fg_color = ((u32 *)info->pseudo_palette)[rect->color];
+	else
+		fg_color = rect->color;
+
+	if (rect->rop == ROP_XOR)
+		rop = 0x5A;
+	else
+		rop = 0xF0;
+
+	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
+	if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL,
+		rect->width, rect->height, info->var.bits_per_pixel,
+		viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
+		NULL, 0, 0, 0, 0, fg_color, 0, rop))
+		cfb_fillrect(info, rect);
+}
+
+static void viafb_copyarea(struct fb_info *info,
+	const struct fb_copyarea *area)
+{
+	struct viafb_par *viapar = info->par;
+	struct viafb_shared *shared = viapar->shared;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	if (!area->width || !area->height)
+		return;
+
+	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
+	if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR,
+		area->width, area->height, info->var.bits_per_pixel,
+		viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
+		NULL, viapar->vram_addr, info->fix.line_length,
+		area->sx, area->sy, 0, 0, 0))
+		cfb_copyarea(info, area);
+}
+
+static void viafb_imageblit(struct fb_info *info,
+	const struct fb_image *image)
+{
+	struct viafb_par *viapar = info->par;
+	struct viafb_shared *shared = viapar->shared;
+	u32 fg_color = 0, bg_color = 0;
+	u8 op;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt ||
+		(image->depth != 1 && image->depth != viapar->depth)) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	if (image->depth == 1) {
+		op = VIA_BITBLT_MONO;
+		if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+			fg_color =
+				((u32 *)info->pseudo_palette)[image->fg_color];
+			bg_color =
+				((u32 *)info->pseudo_palette)[image->bg_color];
+		} else {
+			fg_color = image->fg_color;
+			bg_color = image->bg_color;
+		}
+	} else
+		op = VIA_BITBLT_COLOR;
+
+	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
+	if (shared->hw_bitblt(shared->vdev->engine_mmio, op,
+		image->width, image->height, info->var.bits_per_pixel,
+		viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
+		(u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
+		cfb_imageblit(info, image);
+}
+
+static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct viafb_par *viapar = info->par;
+	void __iomem *engine = viapar->shared->vdev->engine_mmio;
+	u32 temp, xx, yy, bg_color = 0, fg_color = 0,
+		chip_name = viapar->shared->chip_info.gfx_chip_name;
+	int i, j = 0, cur_size = 64;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
+		return -ENODEV;
+
+	/* LCD ouput does not support hw cursors (at least on VN896) */
+	if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) ||
+		viafb_LCD_ON)
+		return -ENODEV;
+
+	viafb_show_hw_cursor(info, HW_Cursor_OFF);
+
+	if (cursor->set & FB_CUR_SETHOT) {
+		temp = (cursor->hot.x << 16) + cursor->hot.y;
+		writel(temp, engine + VIA_REG_CURSOR_ORG);
+	}
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		yy = cursor->image.dy - info->var.yoffset;
+		xx = cursor->image.dx - info->var.xoffset;
+		temp = yy & 0xFFFF;
+		temp |= (xx << 16);
+		writel(temp, engine + VIA_REG_CURSOR_POS);
+	}
+
+	if (cursor->image.width <= 32 && cursor->image.height <= 32)
+		cur_size = 32;
+	else if (cursor->image.width <= 64 && cursor->image.height <= 64)
+		cur_size = 64;
+	else {
+		printk(KERN_WARNING "viafb_cursor: The cursor is too large "
+			"%dx%d", cursor->image.width, cursor->image.height);
+		return -ENXIO;
+	}
+
+	if (cursor->set & FB_CUR_SETSIZE) {
+		temp = readl(engine + VIA_REG_CURSOR_MODE);
+		if (cur_size == 32)
+			temp |= 0x2;
+		else
+			temp &= ~0x2;
+
+		writel(temp, engine + VIA_REG_CURSOR_MODE);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		fg_color = cursor->image.fg_color;
+		bg_color = cursor->image.bg_color;
+		if (chip_name == UNICHROME_CX700 ||
+			chip_name == UNICHROME_VX800 ||
+			chip_name == UNICHROME_VX855 ||
+			chip_name == UNICHROME_VX900) {
+			fg_color =
+				((info->cmap.red[fg_color] & 0xFFC0) << 14) |
+				((info->cmap.green[fg_color] & 0xFFC0) << 4) |
+				((info->cmap.blue[fg_color] & 0xFFC0) >> 6);
+			bg_color =
+				((info->cmap.red[bg_color] & 0xFFC0) << 14) |
+				((info->cmap.green[bg_color] & 0xFFC0) << 4) |
+				((info->cmap.blue[bg_color] & 0xFFC0) >> 6);
+		} else {
+			fg_color =
+				((info->cmap.red[fg_color] & 0xFF00) << 8) |
+				(info->cmap.green[fg_color] & 0xFF00) |
+				((info->cmap.blue[fg_color] & 0xFF00) >> 8);
+			bg_color =
+				((info->cmap.red[bg_color] & 0xFF00) << 8) |
+				(info->cmap.green[bg_color] & 0xFF00) |
+				((info->cmap.blue[bg_color] & 0xFF00) >> 8);
+		}
+
+		writel(bg_color, engine + VIA_REG_CURSOR_BG);
+		writel(fg_color, engine + VIA_REG_CURSOR_FG);
+	}
+
+	if (cursor->set & FB_CUR_SETSHAPE) {
+		struct {
+			u8 data[CURSOR_SIZE];
+			u32 bak[CURSOR_SIZE / 4];
+		} *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
+		int size = ((cursor->image.width + 7) >> 3) *
+			cursor->image.height;
+
+		if (!cr_data)
+			return -ENOMEM;
+
+		if (cur_size == 32) {
+			for (i = 0; i < (CURSOR_SIZE / 4); i++) {
+				cr_data->bak[i] = 0x0;
+				cr_data->bak[i + 1] = 0xFFFFFFFF;
+				i += 1;
+			}
+		} else {
+			for (i = 0; i < (CURSOR_SIZE / 4); i++) {
+				cr_data->bak[i] = 0x0;
+				cr_data->bak[i + 1] = 0x0;
+				cr_data->bak[i + 2] = 0xFFFFFFFF;
+				cr_data->bak[i + 3] = 0xFFFFFFFF;
+				i += 3;
+			}
+		}
+
+		switch (cursor->rop) {
+		case ROP_XOR:
+			for (i = 0; i < size; i++)
+				cr_data->data[i] = cursor->mask[i];
+			break;
+		case ROP_COPY:
+
+			for (i = 0; i < size; i++)
+				cr_data->data[i] = cursor->mask[i];
+			break;
+		default:
+			break;
+		}
+
+		if (cur_size == 32) {
+			for (i = 0; i < size; i++) {
+				cr_data->bak[j] = (u32) cr_data->data[i];
+				cr_data->bak[j + 1] = ~cr_data->bak[j];
+				j += 2;
+			}
+		} else {
+			for (i = 0; i < size; i++) {
+				cr_data->bak[j] = (u32) cr_data->data[i];
+				cr_data->bak[j + 1] = 0x0;
+				cr_data->bak[j + 2] = ~cr_data->bak[j];
+				cr_data->bak[j + 3] = ~cr_data->bak[j + 1];
+				j += 4;
+			}
+		}
+
+		memcpy_toio(viafbinfo->screen_base + viapar->shared->
+			cursor_vram_addr, cr_data->bak, CURSOR_SIZE);
+		kfree(cr_data);
+	}
+
+	if (cursor->enable)
+		viafb_show_hw_cursor(info, HW_Cursor_ON);
+
+	return 0;
+}
+
+static int viafb_sync(struct fb_info *info)
+{
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+		viafb_wait_engine_idle(info);
+	return 0;
+}
+
+static int get_primary_device(void)
+{
+	int primary_device = 0;
+	/* Rule: device on iga1 path are the primary device. */
+	if (viafb_SAMM_ON) {
+		if (viafb_CRT_ON) {
+			if (viaparinfo->shared->iga1_devices & VIA_CRT) {
+				DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1);
+				primary_device = CRT_Device;
+			}
+		}
+		if (viafb_DVI_ON) {
+			if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
+				DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
+					viaparinfo->
+					tmds_setting_info->iga_path);
+				primary_device = DVI_Device;
+			}
+		}
+		if (viafb_LCD_ON) {
+			if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+				DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
+					viaparinfo->
+					lvds_setting_info->iga_path);
+				primary_device = LCD_Device;
+			}
+		}
+		if (viafb_LCD2_ON) {
+			if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
+				DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
+					viaparinfo->
+					lvds_setting_info2->iga_path);
+				primary_device = LCD2_Device;
+			}
+		}
+	}
+	return primary_device;
+}
+
+static void retrieve_device_setting(struct viafb_ioctl_setting
+	*setting_info)
+{
+
+	/* get device status */
+	if (viafb_CRT_ON == 1)
+		setting_info->device_status = CRT_Device;
+	if (viafb_DVI_ON == 1)
+		setting_info->device_status |= DVI_Device;
+	if (viafb_LCD_ON == 1)
+		setting_info->device_status |= LCD_Device;
+	if (viafb_LCD2_ON == 1)
+		setting_info->device_status |= LCD2_Device;
+
+	setting_info->samm_status = viafb_SAMM_ON;
+	setting_info->primary_device = get_primary_device();
+
+	setting_info->first_dev_bpp = viafb_bpp;
+	setting_info->second_dev_bpp = viafb_bpp1;
+
+	setting_info->first_dev_refresh = viafb_refresh;
+	setting_info->second_dev_refresh = viafb_refresh1;
+
+	setting_info->first_dev_hor_res = viafb_hotplug_Xres;
+	setting_info->first_dev_ver_res = viafb_hotplug_Yres;
+	setting_info->second_dev_hor_res = viafb_second_xres;
+	setting_info->second_dev_ver_res = viafb_second_yres;
+
+	/* Get lcd attributes */
+	setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
+	setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
+	setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
+}
+
+static int __init parse_active_dev(void)
+{
+	viafb_CRT_ON = STATE_OFF;
+	viafb_DVI_ON = STATE_OFF;
+	viafb_LCD_ON = STATE_OFF;
+	viafb_LCD2_ON = STATE_OFF;
+	/* 1. Modify the active status of devices. */
+	/* 2. Keep the order of devices, so we can set corresponding
+	   IGA path to devices in SAMM case. */
+	/*    Note: The previous of active_dev is primary device,
+	   and the following is secondary device. */
+	if (!viafb_active_dev) {
+		if (machine_is_olpc()) { /* LCD only */
+			viafb_LCD_ON = STATE_ON;
+			viafb_SAMM_ON = STATE_OFF;
+		} else {
+			viafb_CRT_ON = STATE_ON;
+			viafb_SAMM_ON = STATE_OFF;
+		}
+	} else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
+		/* CRT+DVI */
+		viafb_CRT_ON = STATE_ON;
+		viafb_DVI_ON = STATE_ON;
+		viafb_primary_dev = CRT_Device;
+	} else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
+		/* DVI+CRT */
+		viafb_CRT_ON = STATE_ON;
+		viafb_DVI_ON = STATE_ON;
+		viafb_primary_dev = DVI_Device;
+	} else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
+		/* CRT+LCD */
+		viafb_CRT_ON = STATE_ON;
+		viafb_LCD_ON = STATE_ON;
+		viafb_primary_dev = CRT_Device;
+	} else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
+		/* LCD+CRT */
+		viafb_CRT_ON = STATE_ON;
+		viafb_LCD_ON = STATE_ON;
+		viafb_primary_dev = LCD_Device;
+	} else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
+		/* DVI+LCD */
+		viafb_DVI_ON = STATE_ON;
+		viafb_LCD_ON = STATE_ON;
+		viafb_primary_dev = DVI_Device;
+	} else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
+		/* LCD+DVI */
+		viafb_DVI_ON = STATE_ON;
+		viafb_LCD_ON = STATE_ON;
+		viafb_primary_dev = LCD_Device;
+	} else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
+		viafb_LCD_ON = STATE_ON;
+		viafb_LCD2_ON = STATE_ON;
+		viafb_primary_dev = LCD_Device;
+	} else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
+		viafb_LCD_ON = STATE_ON;
+		viafb_LCD2_ON = STATE_ON;
+		viafb_primary_dev = LCD2_Device;
+	} else if (!strcmp(viafb_active_dev, "CRT")) {
+		/* CRT only */
+		viafb_CRT_ON = STATE_ON;
+		viafb_SAMM_ON = STATE_OFF;
+	} else if (!strcmp(viafb_active_dev, "DVI")) {
+		/* DVI only */
+		viafb_DVI_ON = STATE_ON;
+		viafb_SAMM_ON = STATE_OFF;
+	} else if (!strcmp(viafb_active_dev, "LCD")) {
+		/* LCD only */
+		viafb_LCD_ON = STATE_ON;
+		viafb_SAMM_ON = STATE_OFF;
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int parse_port(char *opt_str, int *output_interface)
+{
+	if (!strncmp(opt_str, "DVP0", 4))
+		*output_interface = INTERFACE_DVP0;
+	else if (!strncmp(opt_str, "DVP1", 4))
+		*output_interface = INTERFACE_DVP1;
+	else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
+		*output_interface = INTERFACE_DFP;
+	else if (!strncmp(opt_str, "DFP_HIGH", 8))
+		*output_interface = INTERFACE_DFP_HIGH;
+	else if (!strncmp(opt_str, "DFP_LOW", 7))
+		*output_interface = INTERFACE_DFP_LOW;
+	else
+		*output_interface = INTERFACE_NONE;
+	return 0;
+}
+
+static void parse_lcd_port(void)
+{
+	parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
+		output_interface);
+	/*Initialize to avoid unexpected behavior */
+	viaparinfo->chip_info->lvds_chip_info2.output_interface =
+	INTERFACE_NONE;
+
+	DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
+		  viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
+		  output_interface);
+}
+
+static void parse_dvi_port(void)
+{
+	parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
+		output_interface);
+
+	DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
+		  viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
+		  output_interface);
+}
+
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
+
+/*
+ * The proc filesystem read/write function, a simple proc implement to
+ * get/set the value of DPA  DVP0,   DVP0DataDriving,  DVP0ClockDriving, DVP1,
+ * DVP1Driving, DFPHigh, DFPLow CR96,   SR2A[5], SR1B[1], SR2A[4], SR1E[2],
+ * CR9B,    SR65,    CR97,    CR99
+ */
+static int viafb_dvp0_proc_show(struct seq_file *m, void *v)
+{
+	u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
+	dvp0_data_dri =
+	    (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
+	    (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
+	dvp0_clk_dri =
+	    (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
+	    (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
+	dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
+	seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
+	return 0;
+}
+
+static int viafb_dvp0_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_dvp0_proc_show, NULL);
+}
+
+static ssize_t viafb_dvp0_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	char buf[20], *value, *pbuf;
+	u8 reg_val = 0;
+	unsigned long length, i;
+	if (count < 1)
+		return -EINVAL;
+	length = count > 20 ? 20 : count;
+	if (copy_from_user(&buf[0], buffer, length))
+		return -EFAULT;
+	buf[length - 1] = '\0';	/*Ensure end string */
+	pbuf = &buf[0];
+	for (i = 0; i < 3; i++) {
+		value = strsep(&pbuf, " ");
+		if (value != NULL) {
+			if (kstrtou8(value, 0, &reg_val) < 0)
+				return -EINVAL;
+			DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
+				  reg_val);
+			switch (i) {
+			case 0:
+				viafb_write_reg_mask(CR96, VIACR,
+					reg_val, 0x0f);
+				break;
+			case 1:
+				viafb_write_reg_mask(SR2A, VIASR,
+					reg_val << 4, BIT5);
+				viafb_write_reg_mask(SR1B, VIASR,
+					reg_val << 1, BIT1);
+				break;
+			case 2:
+				viafb_write_reg_mask(SR2A, VIASR,
+					reg_val << 3, BIT4);
+				viafb_write_reg_mask(SR1E, VIASR,
+					reg_val << 2, BIT2);
+				break;
+			default:
+				break;
+			}
+		} else {
+			break;
+		}
+	}
+	return count;
+}
+
+static const struct file_operations viafb_dvp0_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_dvp0_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_dvp0_proc_write,
+};
+
+static int viafb_dvp1_proc_show(struct seq_file *m, void *v)
+{
+	u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
+	dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
+	dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
+	dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
+	seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
+	return 0;
+}
+
+static int viafb_dvp1_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_dvp1_proc_show, NULL);
+}
+
+static ssize_t viafb_dvp1_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	char buf[20], *value, *pbuf;
+	u8 reg_val = 0;
+	unsigned long length, i;
+	if (count < 1)
+		return -EINVAL;
+	length = count > 20 ? 20 : count;
+	if (copy_from_user(&buf[0], buffer, length))
+		return -EFAULT;
+	buf[length - 1] = '\0';	/*Ensure end string */
+	pbuf = &buf[0];
+	for (i = 0; i < 3; i++) {
+		value = strsep(&pbuf, " ");
+		if (value != NULL) {
+			if (kstrtou8(value, 0, &reg_val) < 0)
+				return -EINVAL;
+			switch (i) {
+			case 0:
+				viafb_write_reg_mask(CR9B, VIACR,
+					reg_val, 0x0f);
+				break;
+			case 1:
+				viafb_write_reg_mask(SR65, VIASR,
+					reg_val << 2, 0x0c);
+				break;
+			case 2:
+				viafb_write_reg_mask(SR65, VIASR,
+					reg_val, 0x03);
+				break;
+			default:
+				break;
+			}
+		} else {
+			break;
+		}
+	}
+	return count;
+}
+
+static const struct file_operations viafb_dvp1_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_dvp1_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_dvp1_proc_write,
+};
+
+static int viafb_dfph_proc_show(struct seq_file *m, void *v)
+{
+	u8 dfp_high = 0;
+	dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
+	seq_printf(m, "%x\n", dfp_high);
+	return 0;
+}
+
+static int viafb_dfph_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_dfph_proc_show, NULL);
+}
+
+static ssize_t viafb_dfph_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	int err;
+	u8 reg_val;
+	err = kstrtou8_from_user(buffer, count, 0, &reg_val);
+	if (err)
+		return err;
+
+	viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
+	return count;
+}
+
+static const struct file_operations viafb_dfph_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_dfph_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_dfph_proc_write,
+};
+
+static int viafb_dfpl_proc_show(struct seq_file *m, void *v)
+{
+	u8 dfp_low = 0;
+	dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
+	seq_printf(m, "%x\n", dfp_low);
+	return 0;
+}
+
+static int viafb_dfpl_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_dfpl_proc_show, NULL);
+}
+
+static ssize_t viafb_dfpl_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	int err;
+	u8 reg_val;
+	err = kstrtou8_from_user(buffer, count, 0, &reg_val);
+	if (err)
+		return err;
+
+	viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
+	return count;
+}
+
+static const struct file_operations viafb_dfpl_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_dfpl_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_dfpl_proc_write,
+};
+
+static int viafb_vt1636_proc_show(struct seq_file *m, void *v)
+{
+	u8 vt1636_08 = 0, vt1636_09 = 0;
+	switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+	case VT1636_LVDS:
+		vt1636_08 =
+		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
+		    &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
+		vt1636_09 =
+		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
+		    &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
+		seq_printf(m, "%x %x\n", vt1636_08, vt1636_09);
+		break;
+	default:
+		break;
+	}
+	switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+	case VT1636_LVDS:
+		vt1636_08 =
+		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
+			&viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
+		vt1636_09 =
+		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
+			&viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
+		seq_printf(m, " %x %x\n", vt1636_08, vt1636_09);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int viafb_vt1636_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_vt1636_proc_show, NULL);
+}
+
+static ssize_t viafb_vt1636_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	char buf[30], *value, *pbuf;
+	struct IODATA reg_val;
+	unsigned long length, i;
+	if (count < 1)
+		return -EINVAL;
+	length = count > 30 ? 30 : count;
+	if (copy_from_user(&buf[0], buffer, length))
+		return -EFAULT;
+	buf[length - 1] = '\0';	/*Ensure end string */
+	pbuf = &buf[0];
+	switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+	case VT1636_LVDS:
+		for (i = 0; i < 2; i++) {
+			value = strsep(&pbuf, " ");
+			if (value != NULL) {
+				if (kstrtou8(value, 0, &reg_val.Data) < 0)
+					return -EINVAL;
+				switch (i) {
+				case 0:
+					reg_val.Index = 0x08;
+					reg_val.Mask = 0x0f;
+					viafb_gpio_i2c_write_mask_lvds
+					    (viaparinfo->lvds_setting_info,
+					    &viaparinfo->
+					    chip_info->lvds_chip_info,
+					     reg_val);
+					break;
+				case 1:
+					reg_val.Index = 0x09;
+					reg_val.Mask = 0x1f;
+					viafb_gpio_i2c_write_mask_lvds
+					    (viaparinfo->lvds_setting_info,
+					    &viaparinfo->
+					    chip_info->lvds_chip_info,
+					     reg_val);
+					break;
+				default:
+					break;
+				}
+			} else {
+				break;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+	case VT1636_LVDS:
+		for (i = 0; i < 2; i++) {
+			value = strsep(&pbuf, " ");
+			if (value != NULL) {
+				if (kstrtou8(value, 0, &reg_val.Data) < 0)
+					return -EINVAL;
+				switch (i) {
+				case 0:
+					reg_val.Index = 0x08;
+					reg_val.Mask = 0x0f;
+					viafb_gpio_i2c_write_mask_lvds
+					    (viaparinfo->lvds_setting_info2,
+					    &viaparinfo->
+					    chip_info->lvds_chip_info2,
+					     reg_val);
+					break;
+				case 1:
+					reg_val.Index = 0x09;
+					reg_val.Mask = 0x1f;
+					viafb_gpio_i2c_write_mask_lvds
+					    (viaparinfo->lvds_setting_info2,
+					    &viaparinfo->
+					    chip_info->lvds_chip_info2,
+					     reg_val);
+					break;
+				default:
+					break;
+				}
+			} else {
+				break;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	return count;
+}
+
+static const struct file_operations viafb_vt1636_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_vt1636_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_vt1636_proc_write,
+};
+
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+
+static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, supported_odev_map[
+		viaparinfo->shared->chip_info.gfx_chip_name]);
+	return 0;
+}
+
+static int viafb_sup_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_sup_odev_proc_show, NULL);
+}
+
+static const struct file_operations viafb_sup_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_sup_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
+{
+	char buf[64], *ptr = buf;
+	u32 devices;
+	bool add, sub;
+
+	if (count < 1 || count > 63)
+		return -EINVAL;
+	if (copy_from_user(&buf[0], buffer, count))
+		return -EFAULT;
+	buf[count] = '\0';
+	add = buf[0] == '+';
+	sub = buf[0] == '-';
+	if (add || sub)
+		ptr++;
+	devices = via_parse_odev(ptr, &ptr);
+	if (*ptr == '\n')
+		ptr++;
+	if (*ptr != 0)
+		return -EINVAL;
+	if (add)
+		*odev |= devices;
+	else if (sub)
+		*odev &= ~devices;
+	else
+		*odev = devices;
+	return count;
+}
+
+static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
+	return 0;
+}
+
+static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga1_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga1_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga1_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga1_devices = dev_new;
+	viaparinfo->shared->iga2_devices &= ~dev_new;
+	via_set_state(dev_off, VIA_STATE_OFF);
+	via_set_source(dev_new, IGA1);
+	via_set_state(dev_on, VIA_STATE_ON);
+	return res;
+}
+
+static const struct file_operations viafb_iga1_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga1_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga1_odev_proc_write,
+};
+
+static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
+{
+	via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
+	return 0;
+}
+
+static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, viafb_iga2_odev_proc_show, NULL);
+}
+
+static ssize_t viafb_iga2_odev_proc_write(struct file *file,
+	const char __user *buffer, size_t count, loff_t *pos)
+{
+	u32 dev_on, dev_off, dev_old, dev_new;
+	ssize_t res;
+
+	dev_old = dev_new = viaparinfo->shared->iga2_devices;
+	res = odev_update(buffer, count, &dev_new);
+	if (res != count)
+		return res;
+	dev_off = dev_old & ~dev_new;
+	dev_on = dev_new & ~dev_old;
+	viaparinfo->shared->iga2_devices = dev_new;
+	viaparinfo->shared->iga1_devices &= ~dev_new;
+	via_set_state(dev_off, VIA_STATE_OFF);
+	via_set_source(dev_new, IGA2);
+	via_set_state(dev_on, VIA_STATE_ON);
+	return res;
+}
+
+static const struct file_operations viafb_iga2_odev_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= viafb_iga2_odev_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= viafb_iga2_odev_proc_write,
+};
+
+#define IS_VT1636(lvds_chip)	((lvds_chip).lvds_chip_name == VT1636_LVDS)
+static void viafb_init_proc(struct viafb_shared *shared)
+{
+	struct proc_dir_entry *iga1_entry, *iga2_entry,
+		*viafb_entry = proc_mkdir("viafb", NULL);
+
+	shared->proc_entry = viafb_entry;
+	if (viafb_entry) {
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
+		proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
+		proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
+		proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
+		proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
+		if (IS_VT1636(shared->chip_info.lvds_chip_info)
+			|| IS_VT1636(shared->chip_info.lvds_chip_info2))
+			proc_create("vt1636", 0, viafb_entry,
+				&viafb_vt1636_proc_fops);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+
+		proc_create("supported_output_devices", 0, viafb_entry,
+			&viafb_sup_odev_proc_fops);
+		iga1_entry = proc_mkdir("iga1", viafb_entry);
+		shared->iga1_proc_entry = iga1_entry;
+		proc_create("output_devices", 0, iga1_entry,
+			&viafb_iga1_odev_proc_fops);
+		iga2_entry = proc_mkdir("iga2", viafb_entry);
+		shared->iga2_proc_entry = iga2_entry;
+		proc_create("output_devices", 0, iga2_entry,
+			&viafb_iga2_odev_proc_fops);
+	}
+}
+static void viafb_remove_proc(struct viafb_shared *shared)
+{
+	struct proc_dir_entry *viafb_entry = shared->proc_entry,
+		*iga1_entry = shared->iga1_proc_entry,
+		*iga2_entry = shared->iga2_proc_entry;
+
+	if (!viafb_entry)
+		return;
+
+	remove_proc_entry("output_devices", iga2_entry);
+	remove_proc_entry("iga2", viafb_entry);
+	remove_proc_entry("output_devices", iga1_entry);
+	remove_proc_entry("iga1", viafb_entry);
+	remove_proc_entry("supported_output_devices", viafb_entry);
+
+#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
+	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
+	remove_proc_entry("dvp1", viafb_entry);
+	remove_proc_entry("dfph", viafb_entry);
+	remove_proc_entry("dfpl", viafb_entry);
+	if (IS_VT1636(shared->chip_info.lvds_chip_info)
+		|| IS_VT1636(shared->chip_info.lvds_chip_info2))
+		remove_proc_entry("vt1636", viafb_entry);
+#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
+
+	remove_proc_entry("viafb", NULL);
+}
+#undef IS_VT1636
+
+static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres)
+{
+	const struct fb_videomode *mode = NULL;
+	char *ptr;
+
+	if (!str) {
+		if (devices == VIA_CRT)
+			mode = via_aux_get_preferred_mode(
+				viaparinfo->shared->i2c_26);
+		else if (devices == VIA_DVP1)
+			mode = via_aux_get_preferred_mode(
+				viaparinfo->shared->i2c_31);
+
+		if (mode) {
+			*xres = mode->xres;
+			*yres = mode->yres;
+		} else if (machine_is_olpc()) {
+			*xres = 1200;
+			*yres = 900;
+		} else {
+			*xres = 640;
+			*yres = 480;
+		}
+		return 0;
+	}
+
+	*xres = simple_strtoul(str, &ptr, 10);
+	if (ptr[0] != 'x')
+		return -EINVAL;
+
+	*yres = simple_strtoul(&ptr[1], &ptr, 10);
+	if (ptr[0])
+		return -EINVAL;
+
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int viafb_suspend(void *unused)
+{
+	console_lock();
+	fb_set_suspend(viafbinfo, 1);
+	viafb_sync(viafbinfo);
+	console_unlock();
+
+	return 0;
+}
+
+static int viafb_resume(void *unused)
+{
+	console_lock();
+	if (viaparinfo->shared->vdev->engine_mmio)
+		viafb_reset_engine(viaparinfo);
+	viafb_set_par(viafbinfo);
+	if (viafb_dual_fb)
+		viafb_set_par(viafbinfo1);
+	fb_set_suspend(viafbinfo, 0);
+
+	console_unlock();
+	return 0;
+}
+
+static struct viafb_pm_hooks viafb_fb_pm_hooks = {
+	.suspend = viafb_suspend,
+	.resume = viafb_resume
+};
+
+#endif
+
+static void i2c_bus_probe(struct viafb_shared *shared)
+{
+	/* should be always CRT */
+	printk(KERN_INFO "viafb: Probing I2C bus 0x26\n");
+	shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26));
+
+	/* seems to be usually DVP1 */
+	printk(KERN_INFO "viafb: Probing I2C bus 0x31\n");
+	shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31));
+
+	/* FIXME: what is this? */
+	if (!machine_is_olpc()) {
+		printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n");
+		shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C));
+	}
+
+	printk(KERN_INFO "viafb: Finished I2C bus probing");
+}
+
+static void i2c_bus_free(struct viafb_shared *shared)
+{
+	via_aux_free(shared->i2c_26);
+	via_aux_free(shared->i2c_31);
+	via_aux_free(shared->i2c_2C);
+}
+
+int via_fb_pci_probe(struct viafb_dev *vdev)
+{
+	u32 default_xres, default_yres;
+	struct fb_var_screeninfo default_var;
+	int rc;
+	u32 viafb_par_length;
+
+	DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
+	memset(&default_var, 0, sizeof(default_var));
+	viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
+
+	/* Allocate fb_info and ***_par here, also including some other needed
+	 * variables
+	*/
+	viafbinfo = framebuffer_alloc(viafb_par_length +
+		ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8),
+		&vdev->pdev->dev);
+	if (!viafbinfo) {
+		printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
+		return -ENOMEM;
+	}
+
+	viaparinfo = (struct viafb_par *)viafbinfo->par;
+	viaparinfo->shared = viafbinfo->par + viafb_par_length;
+	viaparinfo->shared->vdev = vdev;
+	viaparinfo->vram_addr = 0;
+	viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
+	viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
+	viaparinfo->lvds_setting_info2 =
+		&viaparinfo->shared->lvds_setting_info2;
+	viaparinfo->chip_info = &viaparinfo->shared->chip_info;
+
+	i2c_bus_probe(viaparinfo->shared);
+	if (viafb_dual_fb)
+		viafb_SAMM_ON = 1;
+	parse_lcd_port();
+	parse_dvi_port();
+
+	viafb_init_chip_info(vdev->chip_type);
+	/*
+	 * The framebuffer will have been successfully mapped by
+	 * the core (or we'd not be here), but we still need to
+	 * set up our own accounting.
+	 */
+	viaparinfo->fbmem = vdev->fbmem_start;
+	viaparinfo->memsize = vdev->fbmem_len;
+	viaparinfo->fbmem_free = viaparinfo->memsize;
+	viaparinfo->fbmem_used = 0;
+	viafbinfo->screen_base = vdev->fbmem;
+
+	viafbinfo->fix.mmio_start = vdev->engine_start;
+	viafbinfo->fix.mmio_len = vdev->engine_len;
+	viafbinfo->node = 0;
+	viafbinfo->fbops = &viafb_ops;
+	viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	viafbinfo->pseudo_palette = pseudo_pal;
+	if (viafb_accel && !viafb_setup_engine(viafbinfo)) {
+		viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
+			FBINFO_HWACCEL_FILLRECT |  FBINFO_HWACCEL_IMAGEBLIT;
+		default_var.accel_flags = FB_ACCELF_TEXT;
+	} else {
+		viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
+		default_var.accel_flags = 0;
+	}
+
+	if (viafb_second_size && (viafb_second_size < 8)) {
+		viafb_second_offset = viaparinfo->fbmem_free -
+			viafb_second_size * 1024 * 1024;
+	} else {
+		viafb_second_size = 8;
+		viafb_second_offset = viaparinfo->fbmem_free -
+			viafb_second_size * 1024 * 1024;
+	}
+
+	parse_mode(viafb_mode, viaparinfo->shared->iga1_devices,
+		&default_xres, &default_yres);
+	if (viafb_SAMM_ON == 1)
+		parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices,
+			&viafb_second_xres, &viafb_second_yres);
+
+	default_var.xres = default_xres;
+	default_var.yres = default_yres;
+	default_var.xres_virtual = default_xres;
+	default_var.yres_virtual = default_yres;
+	default_var.bits_per_pixel = viafb_bpp;
+	viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+		default_var.xres, default_var.yres, viafb_refresh));
+	viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
+	viafbinfo->var = default_var;
+
+	if (viafb_dual_fb) {
+		viafbinfo1 = framebuffer_alloc(viafb_par_length,
+				&vdev->pdev->dev);
+		if (!viafbinfo1) {
+			printk(KERN_ERR
+			"allocate the second framebuffer struct error\n");
+			rc = -ENOMEM;
+			goto out_fb_release;
+		}
+		viaparinfo1 = viafbinfo1->par;
+		memcpy(viaparinfo1, viaparinfo, viafb_par_length);
+		viaparinfo1->vram_addr = viafb_second_offset;
+		viaparinfo1->memsize = viaparinfo->memsize -
+			viafb_second_offset;
+		viaparinfo->memsize = viafb_second_offset;
+		viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
+
+		viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
+		viaparinfo1->fbmem_free = viaparinfo1->memsize -
+			viaparinfo1->fbmem_used;
+		viaparinfo->fbmem_free = viaparinfo->memsize;
+		viaparinfo->fbmem_used = 0;
+
+		viaparinfo->iga_path = IGA1;
+		viaparinfo1->iga_path = IGA2;
+		memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
+		viafbinfo1->par = viaparinfo1;
+		viafbinfo1->screen_base = viafbinfo->screen_base +
+			viafb_second_offset;
+
+		default_var.xres = viafb_second_xres;
+		default_var.yres = viafb_second_yres;
+		default_var.xres_virtual = viafb_second_xres;
+		default_var.yres_virtual = viafb_second_yres;
+		default_var.bits_per_pixel = viafb_bpp1;
+		viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+			default_var.xres, default_var.yres, viafb_refresh1));
+
+		viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
+		viafb_check_var(&default_var, viafbinfo1);
+		viafbinfo1->var = default_var;
+		viafb_update_fix(viafbinfo1);
+		viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var,
+			&viafbinfo1->fix);
+	}
+
+	viafb_check_var(&viafbinfo->var, viafbinfo);
+	viafb_update_fix(viafbinfo);
+	viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
+		&viafbinfo->fix);
+	default_var.activate = FB_ACTIVATE_NOW;
+	rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
+	if (rc)
+		goto out_fb1_release;
+
+	if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
+	    && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
+		rc = register_framebuffer(viafbinfo1);
+		if (rc)
+			goto out_dealloc_cmap;
+	}
+	rc = register_framebuffer(viafbinfo);
+	if (rc)
+		goto out_fb1_unreg_lcd_cle266;
+
+	if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
+			|| (viaparinfo->chip_info->gfx_chip_name !=
+			UNICHROME_CLE266))) {
+		rc = register_framebuffer(viafbinfo1);
+		if (rc)
+			goto out_fb_unreg;
+	}
+	DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
+		  viafbinfo->node, viafbinfo->fix.id, default_var.xres,
+		  default_var.yres, default_var.bits_per_pixel);
+
+	viafb_init_proc(viaparinfo->shared);
+	viafb_init_dac(IGA2);
+
+#ifdef CONFIG_PM
+	viafb_pm_register(&viafb_fb_pm_hooks);
+#endif
+	return 0;
+
+out_fb_unreg:
+	unregister_framebuffer(viafbinfo);
+out_fb1_unreg_lcd_cle266:
+	if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
+	    && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
+		unregister_framebuffer(viafbinfo1);
+out_dealloc_cmap:
+	fb_dealloc_cmap(&viafbinfo->cmap);
+out_fb1_release:
+	if (viafbinfo1)
+		framebuffer_release(viafbinfo1);
+out_fb_release:
+	i2c_bus_free(viaparinfo->shared);
+	framebuffer_release(viafbinfo);
+	return rc;
+}
+
+void via_fb_pci_remove(struct pci_dev *pdev)
+{
+	DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
+	fb_dealloc_cmap(&viafbinfo->cmap);
+	unregister_framebuffer(viafbinfo);
+	if (viafb_dual_fb)
+		unregister_framebuffer(viafbinfo1);
+	viafb_remove_proc(viaparinfo->shared);
+	i2c_bus_free(viaparinfo->shared);
+	framebuffer_release(viafbinfo);
+	if (viafb_dual_fb)
+		framebuffer_release(viafbinfo1);
+}
+
+#ifndef MODULE
+static int __init viafb_setup(void)
+{
+	char *this_opt;
+	char *options;
+
+	DEBUG_MSG(KERN_INFO "viafb_setup!\n");
+
+	if (fb_get_options("viafb", &options))
+		return -ENODEV;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+
+		if (!strncmp(this_opt, "viafb_mode1=", 12)) {
+			viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
+		} else if (!strncmp(this_opt, "viafb_mode=", 11)) {
+			viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
+		} else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
+			if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
+			if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
+			if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
+			if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
+			if (kstrtoint(this_opt + 21, 0,
+				      &viafb_lcd_dsp_method) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
+			if (kstrtoint(this_opt + 19, 0,
+				      &viafb_lcd_panel_id) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_accel=", 12)) {
+			if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
+			if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
+			viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
+		} else if (!strncmp(this_opt,
+			"viafb_display_hardware_layout=", 30)) {
+			if (kstrtoint(this_opt + 30, 0,
+				      &viafb_display_hardware_layout) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
+			if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt,
+			"viafb_platform_epia_dvi=", 24)) {
+			if (kstrtoint(this_opt + 24, 0,
+				      &viafb_platform_epia_dvi) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt,
+			"viafb_device_lcd_dualedge=", 26)) {
+			if (kstrtoint(this_opt + 26, 0,
+				      &viafb_device_lcd_dualedge) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
+			if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
+			if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
+				return -EINVAL;
+		} else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
+			viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
+		} else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
+			viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
+		}
+	}
+	return 0;
+}
+#endif
+
+/*
+ * These are called out of via-core for now.
+ */
+int __init viafb_init(void)
+{
+	u32 dummy_x, dummy_y;
+	int r = 0;
+
+	if (machine_is_olpc())
+		/* Apply XO-1.5-specific configuration. */
+		viafb_lcd_panel_id = 23;
+
+#ifndef MODULE
+	r = viafb_setup();
+	if (r < 0)
+		return r;
+#endif
+	if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y)
+		|| !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
+		|| parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y)
+		|| !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
+		|| viafb_bpp < 0 || viafb_bpp > 32
+		|| viafb_bpp1 < 0 || viafb_bpp1 > 32
+		|| parse_active_dev())
+		return -EINVAL;
+
+	printk(KERN_INFO
+       "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
+	       VERSION_MAJOR, VERSION_MINOR);
+	return r;
+}
+
+void __exit viafb_exit(void)
+{
+	DEBUG_MSG(KERN_INFO "viafb_exit!\n");
+}
+
+static struct fb_ops viafb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = viafb_open,
+	.fb_release = viafb_release,
+	.fb_check_var = viafb_check_var,
+	.fb_set_par = viafb_set_par,
+	.fb_setcolreg = viafb_setcolreg,
+	.fb_pan_display = viafb_pan_display,
+	.fb_blank = viafb_blank,
+	.fb_fillrect = viafb_fillrect,
+	.fb_copyarea = viafb_copyarea,
+	.fb_imageblit = viafb_imageblit,
+	.fb_cursor = viafb_cursor,
+	.fb_ioctl = viafb_ioctl,
+	.fb_sync = viafb_sync,
+};
+
+
+#ifdef MODULE
+module_param(viafb_mode, charp, S_IRUSR);
+MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
+
+module_param(viafb_mode1, charp, S_IRUSR);
+MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
+
+module_param(viafb_bpp, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
+
+module_param(viafb_bpp1, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
+
+module_param(viafb_refresh, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_refresh,
+	"Set CRT viafb_refresh rate (default = 60)");
+
+module_param(viafb_refresh1, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_refresh1,
+	"Set CRT refresh rate (default = 60)");
+
+module_param(viafb_lcd_panel_id, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_lcd_panel_id,
+	"Set Flat Panel type(Default=1024x768)");
+
+module_param(viafb_lcd_dsp_method, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_lcd_dsp_method,
+	"Set Flat Panel display scaling method.(Default=Expandsion)");
+
+module_param(viafb_SAMM_ON, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_SAMM_ON,
+	"Turn on/off flag of SAMM(Default=OFF)");
+
+module_param(viafb_accel, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_accel,
+	"Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)");
+
+module_param(viafb_active_dev, charp, S_IRUSR);
+MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
+
+module_param(viafb_display_hardware_layout, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_display_hardware_layout,
+	"Display Hardware Layout (LCD Only, DVI Only...,etc)");
+
+module_param(viafb_second_size, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_second_size,
+	"Set secondary device memory size");
+
+module_param(viafb_dual_fb, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_dual_fb,
+	"Turn on/off flag of dual framebuffer devices.(Default = OFF)");
+
+module_param(viafb_platform_epia_dvi, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_platform_epia_dvi,
+	"Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
+
+module_param(viafb_device_lcd_dualedge, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_device_lcd_dualedge,
+	"Turn on/off flag of dual edge panel.(Default = OFF)");
+
+module_param(viafb_bus_width, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_bus_width,
+	"Set bus width of panel.(Default = 12)");
+
+module_param(viafb_lcd_mode, int, S_IRUSR);
+MODULE_PARM_DESC(viafb_lcd_mode,
+	"Set Flat Panel mode(Default=OPENLDI)");
+
+module_param(viafb_lcd_port, charp, S_IRUSR);
+MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
+
+module_param(viafb_dvi_port, charp, S_IRUSR);
+MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
+
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/video/fbdev/via/viafbdev.h b/drivers/video/fbdev/via/viafbdev.h
new file mode 100644
index 000000000000..f6b2ddf56e94
--- /dev/null
+++ b/drivers/video/fbdev/via/viafbdev.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VIAFBDEV_H__
+#define __VIAFBDEV_H__
+
+#include <linux/proc_fs.h>
+#include <linux/fb.h>
+#include <linux/spinlock.h>
+
+#include "via_aux.h"
+#include "ioctl.h"
+#include "share.h"
+#include "chip.h"
+#include "hw.h"
+
+#define VERSION_MAJOR       2
+#define VERSION_KERNEL      6	/* For kernel 2.6 */
+
+#define VERSION_OS          0	/* 0: for 32 bits OS, 1: for 64 bits OS */
+#define VERSION_MINOR       4
+
+#define VIAFB_NUM_I2C		5
+
+struct viafb_shared {
+	u32 iga1_devices;
+	u32 iga2_devices;
+
+	struct proc_dir_entry *proc_entry;	/*viafb proc entry */
+	struct proc_dir_entry *iga1_proc_entry;
+	struct proc_dir_entry *iga2_proc_entry;
+	struct viafb_dev *vdev;			/* Global dev info */
+
+	/* I2C busses that may have auxiliary devices */
+	struct via_aux_bus *i2c_26;
+	struct via_aux_bus *i2c_31;
+	struct via_aux_bus *i2c_2C;
+
+	/* All the information will be needed to set engine */
+	struct tmds_setting_information tmds_setting_info;
+	struct lvds_setting_information lvds_setting_info;
+	struct lvds_setting_information lvds_setting_info2;
+	struct chip_information chip_info;
+
+	/* hardware acceleration stuff */
+	u32 cursor_vram_addr;
+	u32 vq_vram_addr;	/* virtual queue address in video ram */
+	int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height,
+		u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
+		u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
+		u32 fg_color, u32 bg_color, u8 fill_rop);
+};
+
+struct viafb_par {
+	u8 depth;
+	u32 vram_addr;
+
+	unsigned int fbmem;	/*framebuffer physical memory address */
+	unsigned int memsize;	/*size of fbmem */
+	u32 fbmem_free;		/* Free FB memory */
+	u32 fbmem_used;		/* Use FB memory size */
+	u32 iga_path;
+
+	struct viafb_shared *shared;
+
+	/* All the information will be needed to set engine */
+	/* depreciated, use the ones in shared directly */
+	struct tmds_setting_information *tmds_setting_info;
+	struct lvds_setting_information *lvds_setting_info;
+	struct lvds_setting_information *lvds_setting_info2;
+	struct chip_information *chip_info;
+};
+
+extern int viafb_SAMM_ON;
+extern int viafb_dual_fb;
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+extern int viafb_hotplug;
+
+u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
+	*plvds_setting_info, struct lvds_chip_information
+	*plvds_chip_info, u8 index);
+void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
+			      *plvds_setting_info, struct lvds_chip_information
+			      *plvds_chip_info, struct IODATA io_data);
+int via_fb_pci_probe(struct viafb_dev *vdev);
+void via_fb_pci_remove(struct pci_dev *pdev);
+/* Temporary */
+int viafb_init(void);
+void viafb_exit(void);
+#endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/fbdev/via/viamode.c b/drivers/video/fbdev/via/viamode.c
new file mode 100644
index 000000000000..0666ab01cf4a
--- /dev/null
+++ b/drivers/video/fbdev/via/viamode.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/via-core.h>
+#include "global.h"
+
+struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1E, 0x0F, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                      */
+{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0                */
+{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1                */
+{VIACR, CR8B, 0xFF, 0x69},	/* LCD Power Sequence Control 0        */
+{VIACR, CR8C, 0xFF, 0x57},	/* LCD Power Sequence Control 1        */
+{VIACR, CR8D, 0xFF, 0x00},	/* LCD Power Sequence Control 2        */
+{VIACR, CR8E, 0xFF, 0x7B},	/* LCD Power Sequence Control 3        */
+{VIACR, CR8F, 0xFF, 0x03},	/* LCD Power Sequence Control 4        */
+{VIACR, CR90, 0xFF, 0x30},	/* LCD Power Sequence Control 5        */
+{VIACR, CR91, 0xFF, 0xA0},	/* 24/12 bit LVDS Data off             */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00}
+};
+
+/* Video Mode Table for VT3314 chipset*/
+/* Common Setting for Video Mode */
+struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x82},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1F, 0xFF, 0x00},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR22, 0xFF, 0x1F},
+{VIASR, SR2A, 0x0F, 0x00},
+{VIASR, SR2E, 0xFF, 0xFF},
+{VIASR, SR3F, 0xFF, 0xFF},
+{VIASR, SR40, 0xF7, 0x00},
+{VIASR, CR30, 0xFF, 0x04},
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0x7F, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0xFF, 0x31},
+{VIACR, CR41, 0xFF, 0x80},
+{VIACR, CR42, 0xFF, 0x00},
+{VIACR, CR55, 0x80, 0x00},
+{VIACR, CR5D, 0x80, 0x00},	/*Horizontal Retrace Start bit[11] should be 0*/
+{VIACR, CR68, 0xFF, 0x67},	/* Default FIFO For IGA2 */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFD, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR77, 0xFF, 0x00},	/* LCD scaling Factor */
+{VIACR, CR78, 0xFF, 0x00},	/* LCD scaling Factor */
+{VIACR, CR79, 0xFF, 0x00},	/* LCD scaling Factor */
+{VIACR, CR9F, 0x03, 0x00},	/* LCD scaling Factor */
+{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type */
+{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0 */
+{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1 */
+{VIACR, CR8B, 0xFF, 0x5D},	/* LCD Power Sequence Control 0 */
+{VIACR, CR8C, 0xFF, 0x2B},	/* LCD Power Sequence Control 1 */
+{VIACR, CR8D, 0xFF, 0x6F},	/* LCD Power Sequence Control 2 */
+{VIACR, CR8E, 0xFF, 0x2B},	/* LCD Power Sequence Control 3 */
+{VIACR, CR8F, 0xFF, 0x01},	/* LCD Power Sequence Control 4 */
+{VIACR, CR90, 0xFF, 0x01},	/* LCD Power Sequence Control 5 */
+{VIACR, CR91, 0xFF, 0xA0},	/* 24/12 bit LVDS Data off */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CR9D, 0xFF, 0x80},
+{VIACR, CR9E, 0xFF, 0x80}
+};
+
+struct io_reg KM400_ModeXregs[] = {
+	{VIASR, SR10, 0xFF, 0x01},	/* Unlock Register                 */
+	{VIASR, SR16, 0xFF, 0x08},	/* Display FIFO threshold Control  */
+	{VIASR, SR17, 0xFF, 0x1F},	/* Display FIFO Control            */
+	{VIASR, SR18, 0xFF, 0x4E},	/* GFX PREQ threshold              */
+	{VIASR, SR1A, 0xFF, 0x0a},	/* GFX PREQ threshold              */
+	{VIASR, SR1F, 0xFF, 0x00},	/* Memory Control 0                */
+	{VIASR, SR1B, 0xFF, 0xF0},	/* Power Management Control 0      */
+	{VIASR, SR1E, 0xFF, 0x01},	/* Power Management Control        */
+	{VIASR, SR20, 0xFF, 0x00},	/* Sequencer Arbiter Control 0     */
+	{VIASR, SR21, 0xFF, 0x00},	/* Sequencer Arbiter Control 1     */
+	{VIASR, SR22, 0xFF, 0x1F},	/* Display Arbiter Control 1       */
+	{VIASR, SR2A, 0xFF, 0x00},	/* Power Management Control 5      */
+	{VIASR, SR2D, 0xFF, 0xFF},	/* Power Management Control 1      */
+	{VIASR, SR2E, 0xFF, 0xFF},	/* Power Management Control 2      */
+	{VIACR, CR33, 0xFF, 0x00},
+	{VIACR, CR55, 0x80, 0x00},
+	{VIACR, CR5D, 0x80, 0x00},
+	{VIACR, CR36, 0xFF, 0x01},	/* Power Mangement 3                  */
+	{VIACR, CR68, 0xFF, 0x67},	/* Default FIFO For IGA2              */
+	{VIACR, CR6A, 0x20, 0x20},	/* Extended FIFO On                   */
+	{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                     */
+	{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0               */
+	{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1               */
+	{VIACR, CR8B, 0xFF, 0x2D},	/* LCD Power Sequence Control 0       */
+	{VIACR, CR8C, 0xFF, 0x2D},	/* LCD Power Sequence Control 1       */
+	{VIACR, CR8D, 0xFF, 0xC8},	/* LCD Power Sequence Control 2       */
+	{VIACR, CR8E, 0xFF, 0x36},	/* LCD Power Sequence Control 3       */
+	{VIACR, CR8F, 0xFF, 0x00},	/* LCD Power Sequence Control 4       */
+	{VIACR, CR90, 0xFF, 0x10},	/* LCD Power Sequence Control 5       */
+	{VIACR, CR91, 0xFF, 0xA0},	/* 24/12 bit LVDS Data off            */
+	{VIACR, CR96, 0xFF, 0x03},	/* DVP0        ; DVP0 Clock Skew */
+	{VIACR, CR97, 0xFF, 0x03},	/* DFP high    ; DFPH Clock Skew */
+	{VIACR, CR99, 0xFF, 0x03},	/* DFP low           ; DFPL Clock Skew*/
+	{VIACR, CR9B, 0xFF, 0x07}	/* DVI on DVP1       ; DVP1 Clock Skew*/
+};
+
+/* For VT3324: Common Setting for Video Mode */
+struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIASR, SR2D, 0xC0, 0xC0},	/* delayed E3_ECK */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR47, 0xC8, 0x00},	/* Clear VCK Plus. */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                      */
+{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0                */
+{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1                */
+{VIACR, CRD4, 0xFF, 0x81},	/* Second power sequence control       */
+{VIACR, CR8B, 0xFF, 0x5D},	/* LCD Power Sequence Control 0        */
+{VIACR, CR8C, 0xFF, 0x2B},	/* LCD Power Sequence Control 1        */
+{VIACR, CR8D, 0xFF, 0x6F},	/* LCD Power Sequence Control 2        */
+{VIACR, CR8E, 0xFF, 0x2B},	/* LCD Power Sequence Control 3        */
+{VIACR, CR8F, 0xFF, 0x01},	/* LCD Power Sequence Control 4        */
+{VIACR, CR90, 0xFF, 0x01},	/* LCD Power Sequence Control 5        */
+{VIACR, CR91, 0xFF, 0x80},	/* 24/12 bit LVDS Data off             */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00}
+};
+
+struct io_reg VX855_ModeXregs[] = {
+{VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1E, 0x07, 0x01},
+{VIASR, SR2A, 0xF0, 0x00},
+{VIASR, SR58, 0xFF, 0x00},
+{VIASR, SR59, 0xFF, 0x00},
+{VIASR, SR2D, 0xC0, 0xC0},	/* delayed E3_ECK */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0x7F, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFD, 0x60},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR88, 0xFF, 0x40},          /* LCD Panel Type                      */
+{VIACR, CR89, 0xFF, 0x00},          /* LCD Timing Control 0                */
+{VIACR, CR8A, 0xFF, 0x88},          /* LCD Timing Control 1                */
+{VIACR, CRD4, 0xFF, 0x81},          /* Second power sequence control       */
+{VIACR, CR91, 0xFF, 0x80},          /* 24/12 bit LVDS Data off             */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CRD2, 0xFF, 0xFF}           /* TMDS/LVDS control register.         */
+};
+
+/* Video Mode Table */
+/* Common Setting for Video Mode */
+struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
+{VIASR, SR2A, 0x0F, 0x00},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR6A, 0xFF, 0x80},
+{VIACR, CR6A, 0xFF, 0xC0},
+
+{VIACR, CR55, 0x80, 0x00},
+{VIACR, CR5D, 0x80, 0x00},
+
+{VIAGR, GR20, 0xFF, 0x00},
+{VIAGR, GR21, 0xFF, 0x00},
+{VIAGR, GR22, 0xFF, 0x00},
+
+};
+
+/* Mode:1024X768 */
+struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C},
+{VIASR, 0x18, 0xFF, 0x4C}
+};
+
+struct patch_table res_patch_table[] = {
+	{ARRAY_SIZE(PM1024x768), PM1024x768}
+};
+
+/* struct VPITTable {
+	unsigned char  Misc;
+	unsigned char  SR[StdSR];
+	unsigned char  CR[StdCR];
+	unsigned char  GR[StdGR];
+	unsigned char  AR[StdAR];
+ };*/
+
+struct VPITTable VPIT = {
+	/* Msic */
+	0xC7,
+	/* Sequencer */
+	{0x01, 0x0F, 0x00, 0x0E},
+	/* Graphic Controller */
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+	/* Attribute Controller */
+	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	 0x01, 0x00, 0x0F, 0x00}
+};
+
+/********************/
+/* Mode Table       */
+/********************/
+
+static const struct fb_videomode viafb_modes[] = {
+	{NULL, 60, 480, 640, 40285, 72, 24, 19, 1, 48, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, 0, 0},
+	{NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0, 0},
+	{NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3, 0, 0, 0},
+	{NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 120, 640, 480, 19081, 104, 40, 31, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 720, 480, 37426, 88, 16, 13, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 720, 576, 30611, 96, 24, 17, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 100, 800, 600, 14667, 136, 48, 32, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 120, 800, 600, 11911, 144, 56, 39, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 800, 480, 33602, 96, 24, 10, 3, 72, 7, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 848, 480, 31565, 104, 24, 12, 3, 80, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 856, 480, 31517, 104, 16, 13, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1024, 512, 24218, 136, 32, 15, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1024, 600, 20423, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, 0, 0, 0},
+	{NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1280, 768, 12478, 200, 64, 23, 1, 136, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 50, 1280, 768, 15342, 184, 56, 19, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 960, 600, 21964, 128, 32, 15, 3, 96, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1000, 600, 20803, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1024, 576, 21278, 144, 40, 17, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1088, 612, 18825, 152, 48, 16, 3, 104, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1152, 720, 14974, 168, 56, 19, 3, 112, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1200, 720, 14248, 184, 56, 22, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 49, 1200, 900, 17703, 21, 11, 1, 1, 32, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1280, 600, 16259, 184, 56, 18, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1280, 800, 11938, 200, 72, 22, 3, 128, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1360, 768, 11759, 208, 72, 22, 3, 136, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 50, 1368, 768, 14301, 200, 56, 19, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1440, 900, 9372, 232, 80, 25, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 75, 1440, 900, 7311, 248, 96, 33, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1440, 1040, 7993, 248, 96, 33, 1, 152, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1600, 900, 8449, 256, 88, 26, 3, 168, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1600, 1024, 7333, 272, 104, 32, 1, 168, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1680, 1050, 6832, 280, 104, 30, 3, 176, 6, 0, 0, 0},
+	{NULL, 75, 1680, 1050, 5339, 296, 120, 40, 3, 176, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1792, 1344, 4883, 328, 128, 46, 1, 200, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1856, 1392, 4581, 352, 96, 43, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 2048, 1536, 3738, 376, 152, 49, 3, 224, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1280, 720, 13484, 216, 112, 20, 5, 40, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 50, 1280, 720, 16538, 176, 48, 17, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1920, 1080, 5776, 328, 128, 32, 3, 200, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1920, 1200, 5164, 336, 136, 36, 3, 200, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 60, 1400, 1050, 8210, 232, 88, 32, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
+	{NULL, 75, 1400, 1050, 6398, 248, 104, 42, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0} };
+
+static const struct fb_videomode viafb_rb_modes[] = {
+	{NULL, 60, 1360, 768, 13879, 80, 48, 14, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
+	{NULL, 60, 1440, 900, 11249, 80, 48, 17, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
+	{NULL, 60, 1400, 1050, 9892, 80, 48, 23, 3, 32, 4, FB_SYNC_HOR_HIGH_ACT, 0, 0},
+	{NULL, 60, 1600, 900, 10226, 80, 48, 18, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
+	{NULL, 60, 1680, 1050, 8387, 80, 48, 21, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
+	{NULL, 60, 1920, 1080, 7212, 80, 48, 23, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
+	{NULL, 60, 1920, 1200, 6488, 80, 48, 26, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0} };
+
+int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
+int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
+int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs);
+int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs);
+int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs);
+int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
+int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
+
+
+static const struct fb_videomode *get_best_mode(
+	const struct fb_videomode *modes, int n,
+	int hres, int vres, int refresh)
+{
+	const struct fb_videomode *best = NULL;
+	int i;
+
+	for (i = 0; i < n; i++) {
+		if (modes[i].xres != hres || modes[i].yres != vres)
+			continue;
+
+		if (!best || abs(modes[i].refresh - refresh) <
+			abs(best->refresh - refresh))
+			best = &modes[i];
+	}
+
+	return best;
+}
+
+const struct fb_videomode *viafb_get_best_mode(int hres, int vres, int refresh)
+{
+	return get_best_mode(viafb_modes, ARRAY_SIZE(viafb_modes),
+		hres, vres, refresh);
+}
+
+const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
+	int refresh)
+{
+	return get_best_mode(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes),
+		hres, vres, refresh);
+}
diff --git a/drivers/video/fbdev/via/viamode.h b/drivers/video/fbdev/via/viamode.h
new file mode 100644
index 000000000000..dd19106698e7
--- /dev/null
+++ b/drivers/video/fbdev/via/viamode.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VIAMODE_H__
+#define __VIAMODE_H__
+
+#include "global.h"
+
+struct VPITTable {
+	unsigned char Misc;
+	unsigned char SR[StdSR];
+	unsigned char GR[StdGR];
+	unsigned char AR[StdAR];
+};
+
+struct patch_table {
+	int table_length;
+	struct io_reg *io_reg_table;
+};
+
+extern int NUM_TOTAL_CN400_ModeXregs;
+extern int NUM_TOTAL_CN700_ModeXregs;
+extern int NUM_TOTAL_KM400_ModeXregs;
+extern int NUM_TOTAL_CX700_ModeXregs;
+extern int NUM_TOTAL_VX855_ModeXregs;
+extern int NUM_TOTAL_CLE266_ModeXregs;
+extern int NUM_TOTAL_PATCH_MODE;
+
+extern struct io_reg CN400_ModeXregs[];
+extern struct io_reg CN700_ModeXregs[];
+extern struct io_reg KM400_ModeXregs[];
+extern struct io_reg CX700_ModeXregs[];
+extern struct io_reg VX800_ModeXregs[];
+extern struct io_reg VX855_ModeXregs[];
+extern struct io_reg CLE266_ModeXregs[];
+extern struct io_reg PM1024x768[];
+extern struct patch_table res_patch_table[];
+extern struct VPITTable VPIT;
+
+const struct fb_videomode *viafb_get_best_mode(int hres, int vres,
+	int refresh);
+const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
+	int refresh);
+
+#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/fbdev/via/vt1636.c b/drivers/video/fbdev/via/vt1636.c
new file mode 100644
index 000000000000..ee2903b472cf
--- /dev/null
+++ b/drivers/video/fbdev/via/vt1636.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/via-core.h>
+#include <linux/via_i2c.h>
+#include "global.h"
+
+static const struct IODATA common_init_data[] = {
+/*  Index, Mask, Value */
+	/* Set panel power sequence timing */
+	{0x10, 0xC0, 0x00},
+	/* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
+	{0x0B, 0xFF, 0x40},
+	/* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
+	{0x0C, 0xFF, 0x31},
+	/* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
+	{0x0D, 0xFF, 0x31},
+	/* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
+	{0x0E, 0xFF, 0x68},
+	/* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
+	{0x0F, 0xFF, 0x68},
+	/* LVDS output power up */
+	{0x09, 0xA0, 0xA0},
+	/* turn on back light */
+	{0x10, 0x33, 0x13}
+};
+
+/* Index, Mask, Value */
+static const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
+static const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
+static const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
+static const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
+static const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
+static const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
+
+u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
+	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
+	u8 index)
+{
+	u8 data;
+
+	viafb_i2c_readbyte(plvds_chip_info->i2c_port,
+			   plvds_chip_info->lvds_chip_slave_addr, index, &data);
+	return data;
+}
+
+void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
+			      *plvds_setting_info, struct lvds_chip_information
+			      *plvds_chip_info, struct IODATA io_data)
+{
+	int index, data;
+
+	index = io_data.Index;
+	data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
+		index);
+	data = (data & (~io_data.Mask)) | io_data.Data;
+
+	viafb_i2c_writebyte(plvds_chip_info->i2c_port,
+			    plvds_chip_info->lvds_chip_slave_addr, index, data);
+}
+
+void viafb_init_lvds_vt1636(struct lvds_setting_information
+	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
+{
+	int reg_num, i;
+
+	/* Common settings: */
+	reg_num = ARRAY_SIZE(common_init_data);
+	for (i = 0; i < reg_num; i++)
+		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+			plvds_chip_info, common_init_data[i]);
+
+	/* Input Data Mode Select */
+	if (plvds_setting_info->device_lcd_dualedge)
+		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+			plvds_chip_info, dual_channel_enable_data);
+	else
+		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+			plvds_chip_info, single_channel_enable_data);
+
+	if (plvds_setting_info->LCDDithering)
+		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+			plvds_chip_info, dithering_enable_data);
+	else
+		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+			plvds_chip_info, dithering_disable_data);
+}
+
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+			*plvds_setting_info,
+			struct lvds_chip_information *plvds_chip_info)
+{
+	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+		vdd_on_data);
+}
+
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+			 *plvds_setting_info,
+			 struct lvds_chip_information *plvds_chip_info)
+{
+	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+		vdd_off_data);
+}
+
+bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
+{
+	u8 Buffer[2];
+
+	DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
+
+	/* Sense VT1636 LVDS Transmiter */
+	viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+		VT1636_LVDS_I2C_ADDR;
+
+	/* Check vendor ID first: */
+	if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR,
+					0x00, &Buffer[0]))
+		return false;
+	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]);
+
+	if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
+		return false;
+
+	/* Check Chip ID: */
+	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]);
+	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]);
+	if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
+		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+			VT1636_LVDS;
+		return true;
+	}
+
+	return false;
+}
+
+static int get_clk_range_index(u32 Clk)
+{
+	if (Clk < DPA_CLK_30M)
+		return DPA_CLK_RANGE_30M;
+	else if (Clk < DPA_CLK_50M)
+		return DPA_CLK_RANGE_30_50M;
+	else if (Clk < DPA_CLK_70M)
+		return DPA_CLK_RANGE_50_70M;
+	else if (Clk < DPA_CLK_100M)
+		return DPA_CLK_RANGE_70_100M;
+	else if (Clk < DPA_CLK_150M)
+		return DPA_CLK_RANGE_100_150M;
+	else
+		return DPA_CLK_RANGE_150M;
+}
+
+static void set_dpa_vt1636(struct lvds_setting_information
+	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
+		    struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
+{
+	struct IODATA io_data;
+
+	io_data.Index = 0x09;
+	io_data.Mask = 0x1F;
+	io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
+	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+		plvds_chip_info, io_data);
+
+	io_data.Index = 0x08;
+	io_data.Mask = 0x0F;
+	io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
+	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+		io_data);
+}
+
+void viafb_vt1636_patch_skew_on_vt3324(
+	struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info)
+{
+	struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
+		*pdpa;
+	int index;
+
+	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
+
+	/* Graphics DPA settings: */
+	index = get_clk_range_index(plvds_setting_info->vclk);
+	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+		    &GFX_DPA_SETTING_TBL_VT3324[index]);
+
+	/* LVDS Transmitter DPA settings: */
+	if (plvds_setting_info->lcd_panel_hres == 1600 &&
+		plvds_setting_info->lcd_panel_vres == 1200)
+		pdpa = &dpa_16x12;
+	else
+		pdpa = &dpa;
+
+	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
+}
+
+void viafb_vt1636_patch_skew_on_vt3327(
+	struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info)
+{
+	struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
+	int index;
+
+	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
+
+	/* Graphics DPA settings: */
+	index = get_clk_range_index(plvds_setting_info->vclk);
+	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+		    &GFX_DPA_SETTING_TBL_VT3327[index]);
+
+	/* LVDS Transmitter DPA settings: */
+	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
+}
+
+void viafb_vt1636_patch_skew_on_vt3364(
+	struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info)
+{
+	int index;
+
+	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
+
+	/* Graphics DPA settings: */
+	index = get_clk_range_index(plvds_setting_info->vclk);
+	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+		    &GFX_DPA_SETTING_TBL_VT3364[index]);
+}
diff --git a/drivers/video/fbdev/via/vt1636.h b/drivers/video/fbdev/via/vt1636.h
new file mode 100644
index 000000000000..4c1314e57468
--- /dev/null
+++ b/drivers/video/fbdev/via/vt1636.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.See the GNU General Public License
+ * for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _VT1636_H_
+#define _VT1636_H_
+#include "chip.h"
+bool viafb_lvds_identify_vt1636(u8 i2c_adapter);
+void viafb_init_lvds_vt1636(struct lvds_setting_information
+	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+			*plvds_setting_info,
+			struct lvds_chip_information *plvds_chip_info);
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+			 *plvds_setting_info,
+			 struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3324(
+	struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3327(
+	struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3364(
+	struct lvds_setting_information *plvds_setting_info,
+	struct lvds_chip_information *plvds_chip_info);
+
+#endif
diff --git a/drivers/video/fbdev/vt8500lcdfb.c b/drivers/video/fbdev/vt8500lcdfb.c
new file mode 100644
index 000000000000..a8f2b280f796
--- /dev/null
+++ b/drivers/video/fbdev/vt8500lcdfb.c
@@ -0,0 +1,502 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on skeletonfb.c and pxafb.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <video/of_display_timing.h>
+
+#include "vt8500lcdfb.h"
+#include "wmt_ge_rops.h"
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/memblock.h>
+#endif
+
+
+#define to_vt8500lcd_info(__info) container_of(__info, \
+						struct vt8500lcd_info, fb)
+
+static int vt8500lcd_set_par(struct fb_info *info)
+{
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+	int reg_bpp = 5; /* 16bpp */
+	int i;
+	unsigned long control0;
+
+	if (!fbi)
+		return -EINVAL;
+
+	if (info->var.bits_per_pixel <= 8) {
+		/* palettized */
+		info->var.red.offset    = 0;
+		info->var.red.length    = info->var.bits_per_pixel;
+		info->var.red.msb_right = 0;
+
+		info->var.green.offset  = 0;
+		info->var.green.length  = info->var.bits_per_pixel;
+		info->var.green.msb_right = 0;
+
+		info->var.blue.offset   = 0;
+		info->var.blue.length   = info->var.bits_per_pixel;
+		info->var.blue.msb_right = 0;
+
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		info->var.transp.msb_right = 0;
+
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		info->fix.line_length = info->var.xres_virtual /
+						(8/info->var.bits_per_pixel);
+	} else {
+		/* non-palettized */
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		info->var.transp.msb_right = 0;
+
+		if (info->var.bits_per_pixel == 16) {
+			/* RGB565 */
+			info->var.red.offset = 11;
+			info->var.red.length = 5;
+			info->var.red.msb_right = 0;
+			info->var.green.offset = 5;
+			info->var.green.length = 6;
+			info->var.green.msb_right = 0;
+			info->var.blue.offset = 0;
+			info->var.blue.length = 5;
+			info->var.blue.msb_right = 0;
+		} else {
+			/* Equal depths per channel */
+			info->var.red.offset = info->var.bits_per_pixel
+							* 2 / 3;
+			info->var.red.length = info->var.bits_per_pixel / 3;
+			info->var.red.msb_right = 0;
+			info->var.green.offset = info->var.bits_per_pixel / 3;
+			info->var.green.length = info->var.bits_per_pixel / 3;
+			info->var.green.msb_right = 0;
+			info->var.blue.offset = 0;
+			info->var.blue.length = info->var.bits_per_pixel / 3;
+			info->var.blue.msb_right = 0;
+		}
+
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.line_length = info->var.bits_per_pixel > 16 ?
+					info->var.xres_virtual << 2 :
+					info->var.xres_virtual << 1;
+	}
+
+	for (i = 0; i < 8; i++) {
+		if (bpp_values[i] == info->var.bits_per_pixel) {
+			reg_bpp = i;
+			continue;
+		}
+	}
+
+	control0 = readl(fbi->regbase) & ~0xf;
+	writel(0, fbi->regbase);
+	while (readl(fbi->regbase + 0x38) & 0x10)
+		/* wait */;
+	writel((((info->var.hsync_len - 1) & 0x3f) << 26)
+		| ((info->var.left_margin & 0xff) << 18)
+		| (((info->var.xres - 1) & 0x3ff) << 8)
+		| (info->var.right_margin & 0xff), fbi->regbase + 0x4);
+	writel((((info->var.vsync_len - 1) & 0x3f) << 26)
+		| ((info->var.upper_margin & 0xff) << 18)
+		| (((info->var.yres - 1) & 0x3ff) << 8)
+		| (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
+	writel((((info->var.yres - 1) & 0x400) << 2)
+		| ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
+	writel(0x80000000, fbi->regbase + 0x20);
+	writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
+
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info) {
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+	int ret = 1;
+	unsigned int val;
+	if (regno >= 256)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			u32 *pal = fbi->fb.pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		writew((red & 0xf800)
+		      | ((green >> 5) & 0x7e0)
+		      | ((blue >> 11) & 0x1f),
+		       fbi->palette_cpu + sizeof(u16) * regno);
+		break;
+	}
+
+	return ret;
+}
+
+static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg)
+{
+	int ret = 0;
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+
+	if (cmd == FBIO_WAITFORVSYNC) {
+		/* Unmask End of Frame interrupt */
+		writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
+		ret = wait_event_interruptible_timeout(fbi->wait,
+			readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
+		/* Mask back to reduce unwanted interrupt traffic */
+		writel(0xffffffff, fbi->regbase + 0x3c);
+		if (ret < 0)
+			return ret;
+		if (ret == 0)
+			return -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
+	unsigned off = pixlen * var->xoffset
+		      + info->fix.line_length * var->yoffset;
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+
+	writel((1 << 31)
+	     | (((info->var.xres_virtual - info->var.xres) * pixlen / 4) << 20)
+	     | (off >> 2), fbi->regbase + 0x20);
+	return 0;
+}
+
+/*
+ * vt8500lcd_blank():
+ *	Blank the display by setting all palette values to zero.  Note,
+ * 	True Color modes do not really use the palette, so this will not
+ *      blank the display in all modes.
+ */
+static int vt8500lcd_blank(int blank, struct fb_info *info)
+{
+	int i;
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+		    info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			for (i = 0; i < 256; i++)
+				vt8500lcd_setcolreg(i, 0, 0, 0, 0, info);
+	case FB_BLANK_UNBLANK:
+		if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
+		    info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+			fb_set_cmap(&info->cmap, info);
+	}
+	return 0;
+}
+
+static struct fb_ops vt8500lcd_ops = {
+	.owner		= THIS_MODULE,
+	.fb_set_par	= vt8500lcd_set_par,
+	.fb_setcolreg	= vt8500lcd_setcolreg,
+	.fb_fillrect	= wmt_ge_fillrect,
+	.fb_copyarea	= wmt_ge_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_sync	= wmt_ge_sync,
+	.fb_ioctl	= vt8500lcd_ioctl,
+	.fb_pan_display	= vt8500lcd_pan_display,
+	.fb_blank	= vt8500lcd_blank,
+};
+
+static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
+{
+	struct vt8500lcd_info *fbi = dev_id;
+
+	if (readl(fbi->regbase + 0x38) & (1 << 3))
+		wake_up_interruptible(&fbi->wait);
+
+	writel(0xffffffff, fbi->regbase + 0x38);
+	return IRQ_HANDLED;
+}
+
+static int vt8500lcd_probe(struct platform_device *pdev)
+{
+	struct vt8500lcd_info *fbi;
+	struct resource *res;
+	struct display_timings *disp_timing;
+	void *addr;
+	int irq, ret;
+
+	struct fb_videomode	of_mode;
+	u32			bpp;
+	dma_addr_t fb_mem_phys;
+	unsigned long fb_mem_len;
+	void *fb_mem_virt;
+
+	ret = -ENOMEM;
+	fbi = NULL;
+
+	fbi = devm_kzalloc(&pdev->dev, sizeof(struct vt8500lcd_info)
+			+ sizeof(u32) * 16, GFP_KERNEL);
+	if (!fbi) {
+		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+		return -ENOMEM;
+	}
+
+	strcpy(fbi->fb.fix.id, "VT8500 LCD");
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.xpanstep	= 0;
+	fbi->fb.fix.ypanstep	= 1;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.var.nonstd	= 0;
+	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
+	fbi->fb.var.height	= -1;
+	fbi->fb.var.width	= -1;
+	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
+
+	fbi->fb.fbops		= &vt8500lcd_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT
+				| FBINFO_HWACCEL_COPYAREA
+				| FBINFO_HWACCEL_FILLRECT
+				| FBINFO_HWACCEL_YPAN
+				| FBINFO_VIRTFB
+				| FBINFO_PARTIAL_PAN_OK;
+	fbi->fb.node		= -1;
+
+	addr = fbi;
+	addr = addr + sizeof(struct vt8500lcd_info);
+	fbi->fb.pseudo_palette	= addr;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		return -ENODEV;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		return -EBUSY;
+	}
+
+	fbi->regbase = ioremap(res->start, resource_size(res));
+	if (fbi->regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto failed_free_res;
+	}
+
+	disp_timing = of_get_display_timings(pdev->dev.of_node);
+	if (!disp_timing) {
+		ret = -EINVAL;
+		goto failed_free_io;
+	}
+
+	ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
+							OF_USE_NATIVE_MODE);
+	if (ret)
+		goto failed_free_io;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+	if (ret)
+		goto failed_free_io;
+
+	/* try allocating the framebuffer */
+	fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
+	fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
+				GFP_KERNEL);
+	if (!fb_mem_virt) {
+		pr_err("%s: Failed to allocate framebuffer\n", __func__);
+		ret = -ENOMEM;
+		goto failed_free_io;
+	}
+
+	fbi->fb.fix.smem_start	= fb_mem_phys;
+	fbi->fb.fix.smem_len	= fb_mem_len;
+	fbi->fb.screen_base	= fb_mem_virt;
+
+	fbi->palette_size	= PAGE_ALIGN(512);
+	fbi->palette_cpu	= dma_alloc_coherent(&pdev->dev,
+						     fbi->palette_size,
+						     &fbi->palette_phys,
+						     GFP_KERNEL);
+	if (fbi->palette_cpu == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
+		ret = -ENOMEM;
+		goto failed_free_io;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		ret = -ENODEV;
+		goto failed_free_palette;
+	}
+
+	ret = request_irq(irq, vt8500lcd_handle_irq, 0, "LCD", fbi);
+	if (ret) {
+		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
+		ret = -EBUSY;
+		goto failed_free_palette;
+	}
+
+	init_waitqueue_head(&fbi->wait);
+
+	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+		dev_err(&pdev->dev, "Failed to allocate color map\n");
+		ret = -ENOMEM;
+		goto failed_free_irq;
+	}
+
+	fb_videomode_to_var(&fbi->fb.var, &of_mode);
+
+	fbi->fb.var.xres_virtual	= of_mode.xres;
+	fbi->fb.var.yres_virtual	= of_mode.yres * 2;
+	fbi->fb.var.bits_per_pixel	= bpp;
+
+	ret = vt8500lcd_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set parameters\n");
+		goto failed_free_cmap;
+	}
+
+	writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
+	writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
+
+	platform_set_drvdata(pdev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Failed to register framebuffer device: %d\n", ret);
+		goto failed_free_cmap;
+	}
+
+	/*
+	 * Ok, now enable the LCD controller
+	 */
+	writel(readl(fbi->regbase) | 1, fbi->regbase);
+
+	return 0;
+
+failed_free_cmap:
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_irq:
+	free_irq(irq, fbi);
+failed_free_palette:
+	dma_free_coherent(&pdev->dev, fbi->palette_size,
+			  fbi->palette_cpu, fbi->palette_phys);
+failed_free_io:
+	iounmap(fbi->regbase);
+failed_free_res:
+	release_mem_region(res->start, resource_size(res));
+	return ret;
+}
+
+static int vt8500lcd_remove(struct platform_device *pdev)
+{
+	struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
+	struct resource *res;
+	int irq;
+
+	unregister_framebuffer(&fbi->fb);
+
+	writel(0, fbi->regbase);
+
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, fbi);
+
+	dma_free_coherent(&pdev->dev, fbi->palette_size,
+			  fbi->palette_cpu, fbi->palette_phys);
+
+	iounmap(fbi->regbase);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(fbi);
+
+	return 0;
+}
+
+static const struct of_device_id via_dt_ids[] = {
+	{ .compatible = "via,vt8500-fb", },
+	{}
+};
+
+static struct platform_driver vt8500lcd_driver = {
+	.probe		= vt8500lcd_probe,
+	.remove		= vt8500lcd_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "vt8500-lcd",
+		.of_match_table = of_match_ptr(via_dt_ids),
+	},
+};
+
+module_platform_driver(vt8500lcd_driver);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, via_dt_ids);
diff --git a/drivers/video/fbdev/vt8500lcdfb.h b/drivers/video/fbdev/vt8500lcdfb.h
new file mode 100644
index 000000000000..36ca3ca09d83
--- /dev/null
+++ b/drivers/video/fbdev/vt8500lcdfb.h
@@ -0,0 +1,34 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+struct vt8500lcd_info {
+	struct fb_info		fb;
+	void __iomem		*regbase;
+	void __iomem		*palette_cpu;
+	dma_addr_t		palette_phys;
+	size_t			palette_size;
+	wait_queue_head_t	wait;
+};
+
+static int bpp_values[] = {
+	1,
+	2,
+	4,
+	8,
+	12,
+	16,
+	18,
+	24,
+};
diff --git a/drivers/video/fbdev/vt8623fb.c b/drivers/video/fbdev/vt8623fb.c
new file mode 100644
index 000000000000..5c7cbc6c6236
--- /dev/null
+++ b/drivers/video/fbdev/vt8623fb.c
@@ -0,0 +1,958 @@
+/*
+ * linux/drivers/video/vt8623fb.c - fbdev driver for
+ * integrated graphic core in VIA VT8623 [CLE266] chipset
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Code is based on s3fb, some parts are from David Boucher's viafb
+ * (http://davesdomain.org.uk/viafb/)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+struct vt8623fb_info {
+	char __iomem *mmio_base;
+	int mtrr_reg;
+	struct vgastate state;
+	struct mutex open_lock;
+	unsigned int ref_count;
+	u32 pseudo_palette[16];
+};
+
+
+
+/* ------------------------------------------------------------------------- */
+
+static const struct svga_fb_format vt8623fb_formats[] = {
+	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP8,	FB_VISUAL_PSEUDOCOLOR, 16, 16},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 16, 16},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
+		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 16, 16},
+	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 8},
+/*	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},	*/
+	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
+	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 2},
+	SVGA_FORMAT_END
+};
+
+static const struct svga_pll vt8623_pll = {2, 127, 2, 7, 0, 3,
+	60000, 300000, 14318};
+
+/* CRT timing register sets */
+
+static struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
+
+static struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
+
+static struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
+
+static struct svga_timing_regs vt8623_timing_regs     = {
+	vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
+	vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
+	vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
+	vt8623_v_blank_end_regs, vt8623_v_sync_start_regs, vt8623_v_sync_end_regs,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Module parameters */
+
+static char *mode_option = "640x480-8@60";
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for integrated graphics core in VIA VT8623 [CLE266]");
+
+module_param(mode_option, charp, 0644);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+module_param_named(mode, mode_option, charp, 0);
+MODULE_PARM_DESC(mode, "Default video mode e.g. '648x480-8@60' (deprecated)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
+
+
+/* ------------------------------------------------------------------------- */
+
+static void vt8623fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
+{
+	struct vt8623fb_info *par = info->par;
+
+	svga_tilecursor(par->state.vgabase, info, cursor);
+}
+
+static struct fb_tile_ops vt8623fb_tile_ops = {
+	.fb_settile	= svga_settile,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = vt8623fb_tilecursor,
+	.fb_get_tilemax = svga_get_tilemax,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* image data is MSB-first, fb structure is MSB-first too */
+static inline u32 expand_color(u32 c)
+{
+	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
+}
+
+/* vt8623fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void vt8623fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = expand_color(image->fg_color);
+	u32 bg = expand_color(image->bg_color);
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = *(src++) * 0x01010101;
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+}
+
+/* vt8623fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
+static void vt8623fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u32 fg = expand_color(rect->color);
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	int x, y;
+
+	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
+		 + ((rect->dx / 8) * 4);
+
+	for (y = 0; y < rect->height; y++) {
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < rect->width; x += 8) {
+			fb_writel(fg, dst++);
+		}
+		dst1 += info->fix.line_length;
+	}
+}
+
+
+/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
+static inline u32 expand_pixel(u32 c)
+{
+	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
+		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
+}
+
+/* vt8623fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void vt8623fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = image->fg_color * 0x11111111;
+	u32 bg = image->bg_color * 0x11111111;
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = expand_pixel(*(src++));
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+}
+
+static void vt8623fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
+	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
+		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
+			vt8623fb_iplan_imageblit(info, image);
+		else
+			vt8623fb_cfb4_imageblit(info, image);
+	} else
+		cfb_imageblit(info, image);
+}
+
+static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	if ((info->var.bits_per_pixel == 4)
+	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
+	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
+		vt8623fb_iplan_fillrect(info, rect);
+	 else
+		cfb_fillrect(info, rect);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock)
+{
+	struct vt8623fb_info *par = info->par;
+	u16 m, n, r;
+	u8 regval;
+	int rv;
+
+	rv = svga_compute_pll(&vt8623_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
+	if (rv < 0) {
+		fb_err(info, "cannot set requested pixclock, keeping old value\n");
+		return;
+	}
+
+	/* Set VGA misc register  */
+	regval = vga_r(par->state.vgabase, VGA_MIS_R);
+	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
+
+	/* Set clock registers */
+	vga_wseq(par->state.vgabase, 0x46, (n  | (r << 6)));
+	vga_wseq(par->state.vgabase, 0x47, m);
+
+	udelay(1000);
+
+	/* PLL reset */
+	svga_wseq_mask(par->state.vgabase, 0x40, 0x02, 0x02);
+	svga_wseq_mask(par->state.vgabase, 0x40, 0x00, 0x02);
+}
+
+
+static int vt8623fb_open(struct fb_info *info, int user)
+{
+	struct vt8623fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		void __iomem *vgabase = par->state.vgabase;
+
+		memset(&(par->state), 0, sizeof(struct vgastate));
+		par->state.vgabase = vgabase;
+		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
+		par->state.num_crtc = 0xA2;
+		par->state.num_seq = 0x50;
+		save_vga(&(par->state));
+	}
+
+	par->ref_count++;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+static int vt8623fb_release(struct fb_info *info, int user)
+{
+	struct vt8623fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		return -EINVAL;
+	}
+
+	if (par->ref_count == 1)
+		restore_vga(&(par->state));
+
+	par->ref_count--;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int rv, mem, step;
+
+	/* Find appropriate format */
+	rv = svga_match_format (vt8623fb_formats, var, NULL);
+	if (rv < 0)
+	{
+		fb_err(info, "unsupported mode requested\n");
+		return rv;
+	}
+
+	/* Do not allow to have real resoulution larger than virtual */
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	/* Round up xres_virtual to have proper alignment of lines */
+	step = vt8623fb_formats[rv].xresstep - 1;
+	var->xres_virtual = (var->xres_virtual+step) & ~step;
+
+	/* Check whether have enough memory */
+	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
+	if (mem > info->screen_size)
+	{
+		fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n",
+		       mem >> 10, (unsigned int) (info->screen_size >> 10));
+		return -EINVAL;
+	}
+
+	/* Text mode is limited to 256 kB of memory */
+	if ((var->bits_per_pixel == 0) && (mem > (256*1024)))
+	{
+		fb_err(info, "text framebuffer size too large (%d kB requested, 256 kB possible)\n",
+		       mem >> 10);
+		return -EINVAL;
+	}
+
+	rv = svga_check_timings (&vt8623_timing_regs, var, info->node);
+	if (rv < 0)
+	{
+		fb_err(info, "invalid timings requested\n");
+		return rv;
+	}
+
+	/* Interlaced mode not supported */
+	if (var->vmode & FB_VMODE_INTERLACED)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static int vt8623fb_set_par(struct fb_info *info)
+{
+	u32 mode, offset_value, fetch_value, screen_size;
+	struct vt8623fb_info *par = info->par;
+	u32 bpp = info->var.bits_per_pixel;
+
+	if (bpp != 0) {
+		info->fix.ypanstep = 1;
+		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
+
+		info->flags &= ~FBINFO_MISC_TILEBLITTING;
+		info->tileops = NULL;
+
+		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
+		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
+		info->pixmap.blit_y = ~(u32)0;
+
+		offset_value = (info->var.xres_virtual * bpp) / 64;
+		fetch_value  = ((info->var.xres * bpp) / 128) + 4;
+
+		if (bpp == 4)
+			fetch_value  = (info->var.xres / 8) + 8; /* + 0 is OK */
+
+		screen_size  = info->var.yres_virtual * info->fix.line_length;
+	} else {
+		info->fix.ypanstep = 16;
+		info->fix.line_length = 0;
+
+		info->flags |= FBINFO_MISC_TILEBLITTING;
+		info->tileops = &vt8623fb_tile_ops;
+
+		/* supports 8x16 tiles only */
+		info->pixmap.blit_x = 1 << (8 - 1);
+		info->pixmap.blit_y = 1 << (16 - 1);
+
+		offset_value = info->var.xres_virtual / 16;
+		fetch_value  = (info->var.xres / 8) + 8;
+		screen_size  = (info->var.xres_virtual * info->var.yres_virtual) / 64;
+	}
+
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	/* Unlock registers */
+	svga_wseq_mask(par->state.vgabase, 0x10, 0x01, 0x01);
+	svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
+	svga_wcrt_mask(par->state.vgabase, 0x47, 0x00, 0x01);
+
+	/* Device, screen and sync off */
+	svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+	svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
+	svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
+
+	/* Set default values */
+	svga_set_default_gfx_regs(par->state.vgabase);
+	svga_set_default_atc_regs(par->state.vgabase);
+	svga_set_default_seq_regs(par->state.vgabase);
+	svga_set_default_crt_regs(par->state.vgabase);
+	svga_wcrt_multi(par->state.vgabase, vt8623_line_compare_regs, 0xFFFFFFFF);
+	svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, 0);
+
+	svga_wcrt_multi(par->state.vgabase, vt8623_offset_regs, offset_value);
+	svga_wseq_multi(par->state.vgabase, vt8623_fetch_count_regs, fetch_value);
+
+	/* Clear H/V Skew */
+	svga_wcrt_mask(par->state.vgabase, 0x03, 0x00, 0x60);
+	svga_wcrt_mask(par->state.vgabase, 0x05, 0x00, 0x60);
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
+	else
+		svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
+
+	svga_wseq_mask(par->state.vgabase, 0x1E, 0xF0, 0xF0); // DI/DVP bus
+	svga_wseq_mask(par->state.vgabase, 0x2A, 0x0F, 0x0F); // DI/DVP bus
+	svga_wseq_mask(par->state.vgabase, 0x16, 0x08, 0xBF); // FIFO read threshold
+	vga_wseq(par->state.vgabase, 0x17, 0x1F);       // FIFO depth
+	vga_wseq(par->state.vgabase, 0x18, 0x4E);
+	svga_wseq_mask(par->state.vgabase, 0x1A, 0x08, 0x08); // enable MMIO ?
+
+	vga_wcrt(par->state.vgabase, 0x32, 0x00);
+	vga_wcrt(par->state.vgabase, 0x34, 0x00);
+	vga_wcrt(par->state.vgabase, 0x6A, 0x80);
+	vga_wcrt(par->state.vgabase, 0x6A, 0xC0);
+
+	vga_wgfx(par->state.vgabase, 0x20, 0x00);
+	vga_wgfx(par->state.vgabase, 0x21, 0x00);
+	vga_wgfx(par->state.vgabase, 0x22, 0x00);
+
+	/* Set SR15 according to number of bits per pixel */
+	mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix));
+	switch (mode) {
+	case 0:
+		fb_dbg(info, "text mode\n");
+		svga_set_textmode_vga_regs(par->state.vgabase);
+		svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
+		svga_wcrt_mask(par->state.vgabase, 0x11, 0x60, 0x70);
+		break;
+	case 1:
+		fb_dbg(info, "4 bit pseudocolor\n");
+		vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
+		svga_wseq_mask(par->state.vgabase, 0x15, 0x20, 0xFE);
+		svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
+		break;
+	case 2:
+		fb_dbg(info, "4 bit pseudocolor, planar\n");
+		svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
+		svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
+		break;
+	case 3:
+		fb_dbg(info, "8 bit pseudocolor\n");
+		svga_wseq_mask(par->state.vgabase, 0x15, 0x22, 0xFE);
+		break;
+	case 4:
+		fb_dbg(info, "5/6/5 truecolor\n");
+		svga_wseq_mask(par->state.vgabase, 0x15, 0xB6, 0xFE);
+		break;
+	case 5:
+		fb_dbg(info, "8/8/8 truecolor\n");
+		svga_wseq_mask(par->state.vgabase, 0x15, 0xAE, 0xFE);
+		break;
+	default:
+		printk(KERN_ERR "vt8623fb: unsupported mode - bug\n");
+		return (-EINVAL);
+	}
+
+	vt8623_set_pixclock(info, info->var.pixclock);
+	svga_set_timings(par->state.vgabase, &vt8623_timing_regs, &(info->var), 1, 1,
+			 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1,
+			 1, info->node);
+
+	memset_io(info->screen_base, 0x00, screen_size);
+
+	/* Device and screen back on */
+	svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
+	svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
+	svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
+
+	return 0;
+}
+
+
+static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+				u_int transp, struct fb_info *fb)
+{
+	switch (fb->var.bits_per_pixel) {
+	case 0:
+	case 4:
+		if (regno >= 16)
+			return -EINVAL;
+
+		outb(0x0F, VGA_PEL_MSK);
+		outb(regno, VGA_PEL_IW);
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 8:
+		if (regno >= 256)
+			return -EINVAL;
+
+		outb(0xFF, VGA_PEL_MSK);
+		outb(regno, VGA_PEL_IW);
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 16:
+		if (regno >= 16)
+			return 0;
+
+		if (fb->var.green.length == 5)
+			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
+				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+		else if (fb->var.green.length == 6)
+			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
+				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+		else
+			return -EINVAL;
+		break;
+	case 24:
+	case 32:
+		if (regno >= 16)
+			return 0;
+
+		/* ((transp & 0xFF00) << 16) */
+		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
+			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+static int vt8623fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct vt8623fb_info *par = info->par;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		fb_dbg(info, "unblank\n");
+		svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
+		break;
+	case FB_BLANK_NORMAL:
+		fb_dbg(info, "blank\n");
+		svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		fb_dbg(info, "DPMS standby (hsync off)\n");
+		svga_wcrt_mask(par->state.vgabase, 0x36, 0x10, 0x30);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		fb_dbg(info, "DPMS suspend (vsync off)\n");
+		svga_wcrt_mask(par->state.vgabase, 0x36, 0x20, 0x30);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_POWERDOWN:
+		fb_dbg(info, "DPMS off (no sync)\n");
+		svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
+		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
+		break;
+	}
+
+	return 0;
+}
+
+
+static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct vt8623fb_info *par = info->par;
+	unsigned int offset;
+
+	/* Calculate the offset */
+	if (info->var.bits_per_pixel == 0) {
+		offset = (var->yoffset / 16) * info->var.xres_virtual
+		       + var->xoffset;
+		offset = offset >> 3;
+	} else {
+		offset = (var->yoffset * info->fix.line_length) +
+			 (var->xoffset * info->var.bits_per_pixel / 8);
+		offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1);
+	}
+
+	/* Set the offset */
+	svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, offset);
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Frame buffer operations */
+
+static struct fb_ops vt8623fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= vt8623fb_open,
+	.fb_release	= vt8623fb_release,
+	.fb_check_var	= vt8623fb_check_var,
+	.fb_set_par	= vt8623fb_set_par,
+	.fb_setcolreg	= vt8623fb_setcolreg,
+	.fb_blank	= vt8623fb_blank,
+	.fb_pan_display	= vt8623fb_pan_display,
+	.fb_fillrect	= vt8623fb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= vt8623fb_imageblit,
+	.fb_get_caps    = svga_get_caps,
+};
+
+
+/* PCI probe */
+
+static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct pci_bus_region bus_reg;
+	struct resource vga_res;
+	struct fb_info *info;
+	struct vt8623fb_info *par;
+	unsigned int memsize1, memsize2;
+	int rc;
+
+	/* Ignore secondary VGA device because there is no VGA arbitration */
+	if (! svga_primary_device(dev)) {
+		dev_info(&(dev->dev), "ignoring secondary device\n");
+		return -ENODEV;
+	}
+
+	/* Allocate and fill driver data structure */
+	info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev));
+	if (! info) {
+		dev_err(&(dev->dev), "cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	mutex_init(&par->open_lock);
+
+	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+	info->fbops = &vt8623fb_ops;
+
+	/* Prepare PCI device */
+
+	rc = pci_enable_device(dev);
+	if (rc < 0) {
+		dev_err(info->device, "cannot enable PCI device\n");
+		goto err_enable_device;
+	}
+
+	rc = pci_request_regions(dev, "vt8623fb");
+	if (rc < 0) {
+		dev_err(info->device, "cannot reserve framebuffer region\n");
+		goto err_request_regions;
+	}
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = pci_resource_len(dev, 0);
+	info->fix.mmio_start = pci_resource_start(dev, 1);
+	info->fix.mmio_len = pci_resource_len(dev, 1);
+
+	/* Map physical IO memory address into kernel space */
+	info->screen_base = pci_iomap(dev, 0, 0);
+	if (! info->screen_base) {
+		rc = -ENOMEM;
+		dev_err(info->device, "iomap for framebuffer failed\n");
+		goto err_iomap_1;
+	}
+
+	par->mmio_base = pci_iomap(dev, 1, 0);
+	if (! par->mmio_base) {
+		rc = -ENOMEM;
+		dev_err(info->device, "iomap for MMIO failed\n");
+		goto err_iomap_2;
+	}
+
+	bus_reg.start = 0;
+	bus_reg.end = 64 * 1024;
+
+	vga_res.flags = IORESOURCE_IO;
+
+	pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
+
+	par->state.vgabase = (void __iomem *) vga_res.start;
+
+	/* Find how many physical memory there is on card */
+	memsize1 = (vga_rseq(par->state.vgabase, 0x34) + 1) >> 1;
+	memsize2 = vga_rseq(par->state.vgabase, 0x39) << 2;
+
+	if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
+		info->screen_size = memsize1 << 20;
+	else {
+		dev_err(info->device, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
+		info->screen_size = 16 << 20;
+	}
+
+	info->fix.smem_len = info->screen_size;
+	strcpy(info->fix.id, "VIA VT8623");
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	info->fix.ypanstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->pseudo_palette = (void*)par->pseudo_palette;
+
+	/* Prepare startup mode */
+
+	kparam_block_sysfs_write(mode_option);
+	rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
+	kparam_unblock_sysfs_write(mode_option);
+	if (! ((rc == 1) || (rc == 2))) {
+		rc = -EINVAL;
+		dev_err(info->device, "mode %s not found\n", mode_option);
+		goto err_find_mode;
+	}
+
+	rc = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (rc < 0) {
+		dev_err(info->device, "cannot allocate colormap\n");
+		goto err_alloc_cmap;
+	}
+
+	rc = register_framebuffer(info);
+	if (rc < 0) {
+		dev_err(info->device, "cannot register framebuffer\n");
+		goto err_reg_fb;
+	}
+
+	fb_info(info, "%s on %s, %d MB RAM\n",
+		info->fix.id, pci_name(dev), info->fix.smem_len >> 20);
+
+	/* Record a reference to the driver data */
+	pci_set_drvdata(dev, info);
+
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		par->mtrr_reg = -1;
+		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+	}
+#endif
+
+	return 0;
+
+	/* Error handling */
+err_reg_fb:
+	fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+	pci_iounmap(dev, par->mmio_base);
+err_iomap_2:
+	pci_iounmap(dev, info->screen_base);
+err_iomap_1:
+	pci_release_regions(dev);
+err_request_regions:
+/*	pci_disable_device(dev); */
+err_enable_device:
+	framebuffer_release(info);
+	return rc;
+}
+
+/* PCI remove */
+
+static void vt8623_pci_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+
+	if (info) {
+		struct vt8623fb_info *par = info->par;
+
+#ifdef CONFIG_MTRR
+		if (par->mtrr_reg >= 0) {
+			mtrr_del(par->mtrr_reg, 0, 0);
+			par->mtrr_reg = -1;
+		}
+#endif
+
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+		pci_iounmap(dev, info->screen_base);
+		pci_iounmap(dev, par->mmio_base);
+		pci_release_regions(dev);
+/*		pci_disable_device(dev); */
+
+		framebuffer_release(info);
+	}
+}
+
+
+#ifdef CONFIG_PM
+/* PCI suspend */
+
+static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct vt8623fb_info *par = info->par;
+
+	dev_info(info->device, "suspend\n");
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
+		mutex_unlock(&(par->open_lock));
+		console_unlock();
+		return 0;
+	}
+
+	fb_set_suspend(info, 1);
+
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
+
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+
+	return 0;
+}
+
+
+/* PCI resume */
+
+static int vt8623_pci_resume(struct pci_dev* dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct vt8623fb_info *par = info->par;
+
+	dev_info(info->device, "resume\n");
+
+	console_lock();
+	mutex_lock(&(par->open_lock));
+
+	if (par->ref_count == 0)
+		goto fail;
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+
+	if (pci_enable_device(dev))
+		goto fail;
+
+	pci_set_master(dev);
+
+	vt8623fb_set_par(info);
+	fb_set_suspend(info, 0);
+
+fail:
+	mutex_unlock(&(par->open_lock));
+	console_unlock();
+
+	return 0;
+}
+#else
+#define vt8623_pci_suspend NULL
+#define vt8623_pci_resume NULL
+#endif /* CONFIG_PM */
+
+/* List of boards that we are trying to support */
+
+static struct pci_device_id vt8623_devices[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)},
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, vt8623_devices);
+
+static struct pci_driver vt8623fb_pci_driver = {
+	.name		= "vt8623fb",
+	.id_table	= vt8623_devices,
+	.probe		= vt8623_pci_probe,
+	.remove		= vt8623_pci_remove,
+	.suspend	= vt8623_pci_suspend,
+	.resume		= vt8623_pci_resume,
+};
+
+/* Cleanup */
+
+static void __exit vt8623fb_cleanup(void)
+{
+	pr_debug("vt8623fb: cleaning up\n");
+	pci_unregister_driver(&vt8623fb_pci_driver);
+}
+
+/* Driver Initialisation */
+
+static int __init vt8623fb_init(void)
+{
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("vt8623fb", &option))
+		return -ENODEV;
+
+	if (option && *option)
+		mode_option = option;
+#endif
+
+	pr_debug("vt8623fb: initializing\n");
+	return pci_register_driver(&vt8623fb_pci_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Modularization */
+
+module_init(vt8623fb_init);
+module_exit(vt8623fb_cleanup);
diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c
new file mode 100644
index 000000000000..10951c82f6ed
--- /dev/null
+++ b/drivers/video/fbdev/w100fb.c
@@ -0,0 +1,1637 @@
+/*
+ * linux/drivers/video/w100fb.c
+ *
+ * Frame Buffer Device for ATI Imageon w100 (Wallaby)
+ *
+ * Copyright (C) 2002, ATI Corp.
+ * Copyright (C) 2004-2006 Richard Purdie
+ * Copyright (c) 2005 Ian Molton
+ * Copyright (c) 2006 Alberto Mardegan
+ *
+ * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
+ *
+ * Generic platform support by Ian Molton <spyro@f2s.com>
+ * and Richard Purdie <rpurdie@rpsys.net>
+ *
+ * w32xx support by Ian Molton
+ *
+ * Hardware acceleration support by Alberto Mardegan
+ * <mardy@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <video/w100fb.h>
+#include "w100fb.h"
+
+/*
+ * Prototypes
+ */
+static void w100_suspend(u32 mode);
+static void w100_vsync(void);
+static void w100_hw_init(struct w100fb_par*);
+static void w100_pwm_setup(struct w100fb_par*);
+static void w100_init_clocks(struct w100fb_par*);
+static void w100_setup_memory(struct w100fb_par*);
+static void w100_init_lcd(struct w100fb_par*);
+static void w100_set_dispregs(struct w100fb_par*);
+static void w100_update_enable(void);
+static void w100_update_disable(void);
+static void calc_hsync(struct w100fb_par *par);
+static void w100_init_graphic_engine(struct w100fb_par *par);
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
+
+/* Pseudo palette size */
+#define MAX_PALETTES      16
+
+#define W100_SUSPEND_EXTMEM 0
+#define W100_SUSPEND_ALL    1
+
+#define BITS_PER_PIXEL    16
+
+/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
+static void *remapped_base;
+static void *remapped_regs;
+static void *remapped_fbuf;
+
+#define REMAPPED_FB_LEN   0x15ffff
+
+/* This is the offset in the w100's address space we map the current
+   framebuffer memory to. We use the position of external memory as
+   we can remap internal memory to there if external isn't present. */
+#define W100_FB_BASE MEM_EXT_BASE_VALUE
+
+
+/*
+ * Sysfs functions
+ */
+static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+
+	return sprintf(buf, "%d\n",par->flip);
+}
+
+static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int flip;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+
+	flip = simple_strtoul(buf, NULL, 10);
+
+	if (flip > 0)
+		par->flip = 1;
+	else
+		par->flip = 0;
+
+	w100_update_disable();
+	w100_set_dispregs(par);
+	w100_update_enable();
+
+	calc_hsync(par);
+
+	return count;
+}
+
+static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
+
+static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long regs, param;
+	regs = simple_strtoul(buf, NULL, 16);
+	param = readl(remapped_regs + regs);
+	printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
+	return count;
+}
+
+static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
+
+static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long regs, param;
+	sscanf(buf, "%lx %lx", &regs, &param);
+
+	if (regs <= 0x2000) {
+		printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
+		writel(param, remapped_regs + regs);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
+
+
+static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+
+	return sprintf(buf, "%d\n",par->fastpll_mode);
+}
+
+static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+
+	if (simple_strtoul(buf, NULL, 10) > 0) {
+		par->fastpll_mode=1;
+		printk("w100fb: Using fast system clock (if possible)\n");
+	} else {
+		par->fastpll_mode=0;
+		printk("w100fb: Using normal system clock\n");
+	}
+
+	w100_init_clocks(par);
+	calc_hsync(par);
+
+	return count;
+}
+
+static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
+
+/*
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.
+ */
+unsigned long w100fb_get_hsynclen(struct device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+
+	/* If display is blanked/suspended, hsync isn't active */
+	if (par->blanked)
+		return 0;
+	else
+		return par->hsync_len;
+}
+EXPORT_SYMBOL(w100fb_get_hsynclen);
+
+static void w100fb_clear_screen(struct w100fb_par *par)
+{
+	memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
+}
+
+
+/*
+ * Set a palette value from rgb components
+ */
+static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int trans, struct fb_info *info)
+{
+	unsigned int val;
+	int ret = 1;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	/*
+	 * 16-bit True Colour.  We encode the RGB value
+	 * according to the RGB bitfield information.
+	 */
+	if (regno < MAX_PALETTES) {
+		u32 *pal = info->pseudo_palette;
+
+		val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+		pal[regno] = val;
+		ret = 0;
+	}
+	return ret;
+}
+
+
+/*
+ * Blank the display based on value in blank_mode
+ */
+static int w100fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct w100fb_par *par = info->par;
+	struct w100_tg_info *tg = par->mach->tg;
+
+	switch(blank_mode) {
+
+ 	case FB_BLANK_NORMAL:         /* Normal blanking */
+	case FB_BLANK_VSYNC_SUSPEND:  /* VESA blank (vsync off) */
+	case FB_BLANK_HSYNC_SUSPEND:  /* VESA blank (hsync off) */
+ 	case FB_BLANK_POWERDOWN:      /* Poweroff */
+  		if (par->blanked == 0) {
+			if(tg && tg->suspend)
+				tg->suspend(par);
+			par->blanked = 1;
+  		}
+  		break;
+
+ 	case FB_BLANK_UNBLANK: /* Unblanking */
+  		if (par->blanked != 0) {
+			if(tg && tg->resume)
+				tg->resume(par);
+			par->blanked = 0;
+  		}
+  		break;
+ 	}
+	return 0;
+}
+
+
+static void w100_fifo_wait(int entries)
+{
+	union rbbm_status_u status;
+	int i;
+
+	for (i = 0; i < 2000000; i++) {
+		status.val = readl(remapped_regs + mmRBBM_STATUS);
+		if (status.f.cmdfifo_avail >= entries)
+			return;
+		udelay(1);
+	}
+	printk(KERN_ERR "w100fb: FIFO Timeout!\n");
+}
+
+
+static int w100fb_sync(struct fb_info *info)
+{
+	union rbbm_status_u status;
+	int i;
+
+	for (i = 0; i < 2000000; i++) {
+		status.val = readl(remapped_regs + mmRBBM_STATUS);
+		if (!status.f.gui_active)
+			return 0;
+		udelay(1);
+	}
+	printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
+	return -EBUSY;
+}
+
+
+static void w100_init_graphic_engine(struct w100fb_par *par)
+{
+	union dp_gui_master_cntl_u gmc;
+	union dp_mix_u dp_mix;
+	union dp_datatype_u dp_datatype;
+	union dp_cntl_u dp_cntl;
+
+	w100_fifo_wait(4);
+	writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
+	writel(par->xres, remapped_regs + mmDST_PITCH);
+	writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
+	writel(par->xres, remapped_regs + mmSRC_PITCH);
+
+	w100_fifo_wait(3);
+	writel(0, remapped_regs + mmSC_TOP_LEFT);
+	writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
+	writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
+
+	w100_fifo_wait(4);
+	dp_cntl.val = 0;
+	dp_cntl.f.dst_x_dir = 1;
+	dp_cntl.f.dst_y_dir = 1;
+	dp_cntl.f.src_x_dir = 1;
+	dp_cntl.f.src_y_dir = 1;
+	dp_cntl.f.dst_major_x = 1;
+	dp_cntl.f.src_major_x = 1;
+	writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
+
+	gmc.val = 0;
+	gmc.f.gmc_src_pitch_offset_cntl = 1;
+	gmc.f.gmc_dst_pitch_offset_cntl = 1;
+	gmc.f.gmc_src_clipping = 1;
+	gmc.f.gmc_dst_clipping = 1;
+	gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
+	gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
+	gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
+	gmc.f.gmc_byte_pix_order = 1;
+	gmc.f.gmc_default_sel = 0;
+	gmc.f.gmc_rop3 = ROP3_SRCCOPY;
+	gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
+	gmc.f.gmc_clr_cmp_fcn_dis = 1;
+	gmc.f.gmc_wr_msk_dis = 1;
+	gmc.f.gmc_dp_op = DP_OP_ROP;
+	writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+
+	dp_datatype.val = dp_mix.val = 0;
+	dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
+	dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
+	dp_datatype.f.dp_src2_type = 0;
+	dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
+	dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
+	dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
+	writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
+
+	dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
+	dp_mix.f.dp_src2_source = 1;
+	dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
+	dp_mix.f.dp_op = gmc.f.gmc_dp_op;
+	writel(dp_mix.val, remapped_regs + mmDP_MIX);
+}
+
+
+static void w100fb_fillrect(struct fb_info *info,
+                            const struct fb_fillrect *rect)
+{
+	union dp_gui_master_cntl_u gmc;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
+	gmc.f.gmc_rop3 = ROP3_PATCOPY;
+	gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
+	w100_fifo_wait(2);
+	writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+	writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
+
+	w100_fifo_wait(2);
+	writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
+	writel((rect->width << 16) | (rect->height & 0xffff),
+	       remapped_regs + mmDST_WIDTH_HEIGHT);
+}
+
+
+static void w100fb_copyarea(struct fb_info *info,
+                            const struct fb_copyarea *area)
+{
+	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
+	u32 h = area->height, w = area->width;
+	union dp_gui_master_cntl_u gmc;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, area);
+		return;
+	}
+
+	gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
+	gmc.f.gmc_rop3 = ROP3_SRCCOPY;
+	gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
+	w100_fifo_wait(1);
+	writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+
+	w100_fifo_wait(3);
+	writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
+	writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
+	writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
+}
+
+
+/*
+ *  Change the resolution by calling the appropriate hardware functions
+ */
+static void w100fb_activate_var(struct w100fb_par *par)
+{
+	struct w100_tg_info *tg = par->mach->tg;
+
+	w100_pwm_setup(par);
+	w100_setup_memory(par);
+	w100_init_clocks(par);
+	w100fb_clear_screen(par);
+	w100_vsync();
+
+	w100_update_disable();
+	w100_init_lcd(par);
+	w100_set_dispregs(par);
+	w100_update_enable();
+	w100_init_graphic_engine(par);
+
+	calc_hsync(par);
+
+	if (!par->blanked && tg && tg->change)
+		tg->change(par);
+}
+
+
+/* Select the smallest mode that allows the desired resolution to be
+ * displayed. If desired, the x and y parameters can be rounded up to
+ * match the selected mode.
+ */
+static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
+{
+	struct w100_mode *mode = NULL;
+	struct w100_mode *modelist = par->mach->modelist;
+	unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
+	unsigned int i;
+
+	for (i = 0 ; i < par->mach->num_modes ; i++) {
+		if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
+				modelist[i].xres < best_x && modelist[i].yres < best_y) {
+			best_x = modelist[i].xres;
+			best_y = modelist[i].yres;
+			mode = &modelist[i];
+		} else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
+		        modelist[i].xres < best_y && modelist[i].yres < best_x) {
+			best_x = modelist[i].yres;
+			best_y = modelist[i].xres;
+			mode = &modelist[i];
+		}
+	}
+
+	if (mode && saveval) {
+		*x = best_x;
+		*y = best_y;
+	}
+
+	return mode;
+}
+
+
+/*
+ *  w100fb_check_var():
+ *  Get the video params out of 'var'. If a value doesn't fit, round it up,
+ *  if it's too big, return -EINVAL.
+ */
+static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct w100fb_par *par=info->par;
+
+	if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
+		return -EINVAL;
+
+	if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
+		return -EINVAL;
+
+	if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
+		return -EINVAL;
+
+	var->xres_virtual = max(var->xres_virtual, var->xres);
+	var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	if (var->bits_per_pixel > BITS_PER_PIXEL)
+		return -EINVAL;
+	else
+		var->bits_per_pixel = BITS_PER_PIXEL;
+
+	var->red.offset = 11;
+	var->red.length = 5;
+	var->green.offset = 5;
+	var->green.length = 6;
+	var->blue.offset = 0;
+	var->blue.length = 5;
+	var->transp.offset = var->transp.length = 0;
+
+	var->nonstd = 0;
+	var->height = -1;
+	var->width = -1;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	var->sync = 0;
+	var->pixclock = 0x04;  /* 171521; */
+
+	return 0;
+}
+
+
+/*
+ * w100fb_set_par():
+ *	Set the user defined part of the display for the specified console
+ *  by looking at the values in info.var
+ */
+static int w100fb_set_par(struct fb_info *info)
+{
+	struct w100fb_par *par=info->par;
+
+	if (par->xres != info->var.xres || par->yres != info->var.yres)	{
+		par->xres = info->var.xres;
+		par->yres = info->var.yres;
+		par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
+
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.ypanstep = 0;
+		info->fix.ywrapstep = 0;
+		info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
+
+		mutex_lock(&info->mm_lock);
+		if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
+			par->extmem_active = 1;
+			info->fix.smem_len = par->mach->mem->size+1;
+		} else {
+			par->extmem_active = 0;
+			info->fix.smem_len = MEM_INT_SIZE+1;
+		}
+		mutex_unlock(&info->mm_lock);
+
+		w100fb_activate_var(par);
+	}
+	return 0;
+}
+
+
+/*
+ *  Frame buffer operations
+ */
+static struct fb_ops w100fb_ops = {
+	.owner        = THIS_MODULE,
+	.fb_check_var = w100fb_check_var,
+	.fb_set_par   = w100fb_set_par,
+	.fb_setcolreg = w100fb_setcolreg,
+	.fb_blank     = w100fb_blank,
+	.fb_fillrect  = w100fb_fillrect,
+	.fb_copyarea  = w100fb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_sync      = w100fb_sync,
+};
+
+#ifdef CONFIG_PM
+static void w100fb_save_vidmem(struct w100fb_par *par)
+{
+	int memsize;
+
+	if (par->extmem_active) {
+		memsize=par->mach->mem->size;
+		par->saved_extmem = vmalloc(memsize);
+		if (par->saved_extmem)
+			memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
+	}
+	memsize=MEM_INT_SIZE;
+	par->saved_intmem = vmalloc(memsize);
+	if (par->saved_intmem && par->extmem_active)
+		memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
+	else if (par->saved_intmem)
+		memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
+}
+
+static void w100fb_restore_vidmem(struct w100fb_par *par)
+{
+	int memsize;
+
+	if (par->extmem_active && par->saved_extmem) {
+		memsize=par->mach->mem->size;
+		memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
+		vfree(par->saved_extmem);
+	}
+	if (par->saved_intmem) {
+		memsize=MEM_INT_SIZE;
+		if (par->extmem_active)
+			memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
+		else
+			memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
+		vfree(par->saved_intmem);
+	}
+}
+
+static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+	struct w100_tg_info *tg = par->mach->tg;
+
+	w100fb_save_vidmem(par);
+	if(tg && tg->suspend)
+		tg->suspend(par);
+	w100_suspend(W100_SUSPEND_ALL);
+	par->blanked = 1;
+
+	return 0;
+}
+
+static int w100fb_resume(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+	struct w100_tg_info *tg = par->mach->tg;
+
+	w100_hw_init(par);
+	w100fb_activate_var(par);
+	w100fb_restore_vidmem(par);
+	if(tg && tg->resume)
+		tg->resume(par);
+	par->blanked = 0;
+
+	return 0;
+}
+#else
+#define w100fb_suspend  NULL
+#define w100fb_resume   NULL
+#endif
+
+
+int w100fb_probe(struct platform_device *pdev)
+{
+	int err = -EIO;
+	struct w100fb_mach_info *inf;
+	struct fb_info *info = NULL;
+	struct w100fb_par *par;
+	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	unsigned int chip_id;
+
+	if (!mem)
+		return -EINVAL;
+
+	/* Remap the chip base address */
+	remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
+	if (remapped_base == NULL)
+		goto out;
+
+	/* Map the register space */
+	remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
+	if (remapped_regs == NULL)
+		goto out;
+
+	/* Identify the chip */
+	printk("Found ");
+	chip_id = readl(remapped_regs + mmCHIP_ID);
+	switch(chip_id) {
+		case CHIP_ID_W100:  printk("w100");  break;
+		case CHIP_ID_W3200: printk("w3200"); break;
+		case CHIP_ID_W3220: printk("w3220"); break;
+		default:
+			printk("Unknown imageon chip ID\n");
+			err = -ENODEV;
+			goto out;
+	}
+	printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
+
+	/* Remap the framebuffer */
+	remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
+	if (remapped_fbuf == NULL)
+		goto out;
+
+	info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
+	if (!info) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	par = info->par;
+	platform_set_drvdata(pdev, info);
+
+	inf = dev_get_platdata(&pdev->dev);
+	par->chip_id = chip_id;
+	par->mach = inf;
+	par->fastpll_mode = 0;
+	par->blanked = 0;
+
+	par->pll_table=w100_get_xtal_table(inf->xtal_freq);
+	if (!par->pll_table) {
+		printk(KERN_ERR "No matching Xtal definition found\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
+	if (!info->pseudo_palette) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	info->fbops = &w100fb_ops;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+		FBINFO_HWACCEL_FILLRECT;
+	info->node = -1;
+	info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
+	info->screen_size = REMAPPED_FB_LEN;
+
+	strcpy(info->fix.id, "w100fb");
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->fix.smem_start = mem->start+W100_FB_BASE;
+	info->fix.mmio_start = mem->start+W100_REG_BASE;
+	info->fix.mmio_len = W100_REG_LEN;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	par->mode = &inf->modelist[0];
+	if(inf->init_mode & INIT_MODE_ROTATED) {
+		info->var.xres = par->mode->yres;
+		info->var.yres = par->mode->xres;
+	}
+	else {
+		info->var.xres = par->mode->xres;
+		info->var.yres = par->mode->yres;
+	}
+
+	if(inf->init_mode &= INIT_MODE_FLIPPED)
+		par->flip = 1;
+	else
+		par->flip = 0;
+
+	info->var.xres_virtual = info->var.xres;
+	info->var.yres_virtual = info->var.yres;
+	info->var.pixclock = 0x04;  /* 171521; */
+	info->var.sync = 0;
+	info->var.grayscale = 0;
+	info->var.xoffset = info->var.yoffset = 0;
+	info->var.accel_flags = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	w100_hw_init(par);
+
+	if (w100fb_check_var(&info->var, info) < 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (register_framebuffer(info) < 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
+	err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
+	err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
+	err |= device_create_file(&pdev->dev, &dev_attr_flip);
+
+	if (err != 0)
+		fb_warn(info, "failed to register attributes (%d)\n", err);
+
+	fb_info(info, "%s frame buffer device\n", info->fix.id);
+	return 0;
+out:
+	if (info) {
+		fb_dealloc_cmap(&info->cmap);
+		kfree(info->pseudo_palette);
+	}
+	if (remapped_fbuf != NULL)
+		iounmap(remapped_fbuf);
+	if (remapped_regs != NULL)
+		iounmap(remapped_regs);
+	if (remapped_base != NULL)
+		iounmap(remapped_base);
+	if (info)
+		framebuffer_release(info);
+	return err;
+}
+
+
+static int w100fb_remove(struct platform_device *pdev)
+{
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct w100fb_par *par=info->par;
+
+	device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
+	device_remove_file(&pdev->dev, &dev_attr_reg_read);
+	device_remove_file(&pdev->dev, &dev_attr_reg_write);
+	device_remove_file(&pdev->dev, &dev_attr_flip);
+
+	unregister_framebuffer(info);
+
+	vfree(par->saved_intmem);
+	vfree(par->saved_extmem);
+	kfree(info->pseudo_palette);
+	fb_dealloc_cmap(&info->cmap);
+
+	iounmap(remapped_base);
+	iounmap(remapped_regs);
+	iounmap(remapped_fbuf);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
+
+/* ------------------- chipset specific functions -------------------------- */
+
+
+static void w100_soft_reset(void)
+{
+	u16 val = readw((u16 *) remapped_base + cfgSTATUS);
+	writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
+	udelay(100);
+	writew(0x00, (u16 *) remapped_base + cfgSTATUS);
+	udelay(100);
+}
+
+static void w100_update_disable(void)
+{
+	union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+	/* Prevent display updates */
+	disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+	disp_db_buf_wr_cntl.f.update_db_buf = 0;
+	disp_db_buf_wr_cntl.f.en_db_buf = 0;
+	writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+static void w100_update_enable(void)
+{
+	union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
+
+	/* Enable display updates */
+	disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
+	disp_db_buf_wr_cntl.f.update_db_buf = 1;
+	disp_db_buf_wr_cntl.f.en_db_buf = 1;
+	writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
+}
+
+unsigned long w100fb_gpio_read(int port)
+{
+	unsigned long value;
+
+	if (port==W100_GPIO_PORT_A)
+		value = readl(remapped_regs + mmGPIO_DATA);
+	else
+		value = readl(remapped_regs + mmGPIO_DATA2);
+
+	return value;
+}
+
+void w100fb_gpio_write(int port, unsigned long value)
+{
+	if (port==W100_GPIO_PORT_A)
+		writel(value, remapped_regs + mmGPIO_DATA);
+	else
+		writel(value, remapped_regs + mmGPIO_DATA2);
+}
+EXPORT_SYMBOL(w100fb_gpio_read);
+EXPORT_SYMBOL(w100fb_gpio_write);
+
+/*
+ * Initialization of critical w100 hardware
+ */
+static void w100_hw_init(struct w100fb_par *par)
+{
+	u32 temp32;
+	union cif_cntl_u cif_cntl;
+	union intf_cntl_u intf_cntl;
+	union cfgreg_base_u cfgreg_base;
+	union wrap_top_dir_u wrap_top_dir;
+	union cif_read_dbg_u cif_read_dbg;
+	union cpu_defaults_u cpu_default;
+	union cif_write_dbg_u cif_write_dbg;
+	union wrap_start_dir_u wrap_start_dir;
+	union cif_io_u cif_io;
+	struct w100_gpio_regs *gpio = par->mach->gpio;
+
+	w100_soft_reset();
+
+	/* This is what the fpga_init code does on reset. May be wrong
+	   but there is little info available */
+	writel(0x31, remapped_regs + mmSCRATCH_UMSK);
+	for (temp32 = 0; temp32 < 10000; temp32++)
+		readl(remapped_regs + mmSCRATCH_UMSK);
+	writel(0x30, remapped_regs + mmSCRATCH_UMSK);
+
+	/* Set up CIF */
+	cif_io.val = defCIF_IO;
+	writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
+
+	cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
+	cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
+	cif_write_dbg.f.en_dword_split_to_rbbm = 1;
+	cif_write_dbg.f.dis_timeout_during_rbbm = 1;
+	writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
+
+	cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
+	cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
+	writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
+
+	cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
+	cif_cntl.f.dis_system_bits = 1;
+	cif_cntl.f.dis_mr = 1;
+	cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
+	cif_cntl.f.intb_oe = 1;
+	cif_cntl.f.interrupt_active_high = 1;
+	writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
+
+	/* Setup cfgINTF_CNTL and cfgCPU defaults */
+	intf_cntl.val = defINTF_CNTL;
+	intf_cntl.f.ad_inc_a = 1;
+	intf_cntl.f.ad_inc_b = 1;
+	intf_cntl.f.rd_data_rdy_a = 0;
+	intf_cntl.f.rd_data_rdy_b = 0;
+	writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
+
+	cpu_default.val = defCPU_DEFAULTS;
+	cpu_default.f.access_ind_addr_a = 1;
+	cpu_default.f.access_ind_addr_b = 1;
+	cpu_default.f.access_scratch_reg = 1;
+	cpu_default.f.transition_size = 0;
+	writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
+
+	/* set up the apertures */
+	writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
+
+	cfgreg_base.val = defCFGREG_BASE;
+	cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
+	writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
+
+	wrap_start_dir.val = defWRAP_START_DIR;
+	wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
+	writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
+
+	wrap_top_dir.val = defWRAP_TOP_DIR;
+	wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
+	writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
+
+	writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
+
+	/* Set the hardware to 565 colour */
+	temp32 = readl(remapped_regs + mmDISP_DEBUG2);
+	temp32 &= 0xff7fffff;
+	temp32 |= 0x00800000;
+	writel(temp32, remapped_regs + mmDISP_DEBUG2);
+
+	/* Initialise the GPIO lines */
+	if (gpio) {
+		writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
+		writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
+		writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
+		writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
+		writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
+		writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
+	}
+}
+
+
+struct power_state {
+	union clk_pin_cntl_u clk_pin_cntl;
+	union pll_ref_fb_div_u pll_ref_fb_div;
+	union pll_cntl_u pll_cntl;
+	union sclk_cntl_u sclk_cntl;
+	union pclk_cntl_u pclk_cntl;
+	union pwrmgt_cntl_u pwrmgt_cntl;
+	int auto_mode;  /* system clock auto changing? */
+};
+
+
+static struct power_state w100_pwr_state;
+
+/* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
+
+/* 12.5MHz Crystal PLL Table */
+static struct w100_pll_info xtal_12500000[] = {
+	/*freq     M   N_int    N_fac  tfgoal  lock_time */
+	{ 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
+	{ 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
+	{100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
+	{125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
+	{150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
+	{  0,      0,   0,       0,        0,         0},  /* Terminator */
+};
+
+/* 14.318MHz Crystal PLL Table */
+static struct w100_pll_info xtal_14318000[] = {
+	/*freq     M   N_int    N_fac  tfgoal  lock_time */
+	{ 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
+	{ 50,      1,   6,       0,     0xe0,	     64}, /*  50.05 MHz */
+	{ 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
+	{ 75,      0,   4,       3,     0xe0,	     43}, /*  75.08 MHz */
+	{100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
+	{  0,      0,   0,       0,        0,         0},
+};
+
+/* 16MHz Crystal PLL Table */
+static struct w100_pll_info xtal_16000000[] = {
+	/*freq     M   N_int    N_fac  tfgoal  lock_time */
+	{ 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
+	{ 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
+	{ 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
+	{ 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
+	{  0,      0,   0,       0,        0,         0},
+};
+
+static struct pll_entries {
+	int xtal_freq;
+	struct w100_pll_info *pll_table;
+} w100_pll_tables[] = {
+	{ 12500000, &xtal_12500000[0] },
+	{ 14318000, &xtal_14318000[0] },
+	{ 16000000, &xtal_16000000[0] },
+	{ 0 },
+};
+
+struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
+{
+	struct pll_entries *pll_entry = w100_pll_tables;
+
+	do {
+		if (freq == pll_entry->xtal_freq)
+			return pll_entry->pll_table;
+		pll_entry++;
+	} while (pll_entry->xtal_freq);
+	return 0;
+}
+
+
+static unsigned int w100_get_testcount(unsigned int testclk_sel)
+{
+	union clk_test_cntl_u clk_test_cntl;
+
+	udelay(5);
+
+	/* Select the test clock source and reset */
+	clk_test_cntl.f.start_check_freq = 0x0;
+	clk_test_cntl.f.testclk_sel = testclk_sel;
+	clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
+	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+
+	clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
+	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+
+	/* Run clock test */
+	clk_test_cntl.f.start_check_freq = 0x1;
+	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+
+	/* Give the test time to complete */
+	udelay(20);
+
+	/* Return the result */
+	clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
+	clk_test_cntl.f.start_check_freq = 0x0;
+	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
+
+	return clk_test_cntl.f.test_count;
+}
+
+
+static int w100_pll_adjust(struct w100_pll_info *pll)
+{
+	unsigned int tf80;
+	unsigned int tf20;
+
+	/* Initial Settings */
+	w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
+	w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
+	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
+	w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
+	w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
+	w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
+	w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
+
+	/* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
+	 * therefore, commented out the following lines
+	 * tf80 meant tf100
+	 */
+	do {
+		/* set VCO input = 0.8 * VDD */
+		w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
+		writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+
+		tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
+		if (tf80 >= (pll->tfgoal)) {
+			/* set VCO input = 0.2 * VDD */
+			w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
+			writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+
+			tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
+			if (tf20 <= (pll->tfgoal))
+				return 1;  /* Success */
+
+			if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
+				((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
+				(w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
+				/* slow VCO config */
+				w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
+				w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
+				w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
+				continue;
+			}
+		}
+		if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
+			w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
+		} else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
+			w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
+			w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
+		} else {
+			return 0;  /* Error */
+		}
+	} while(1);
+}
+
+
+/*
+ * w100_pll_calibration
+ */
+static int w100_pll_calibration(struct w100_pll_info *pll)
+{
+	int status;
+
+	status = w100_pll_adjust(pll);
+
+	/* PLL Reset And Lock */
+	/* set VCO input = 0.5 * VDD */
+	w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
+	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+
+	udelay(1);  /* reset time */
+
+	/* enable charge pump */
+	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
+	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+
+	/* set VCO input = Hi-Z, disable DAC */
+	w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
+	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+
+	udelay(400);  /* lock time */
+
+	/* PLL locked */
+
+	return status;
+}
+
+
+static int w100_pll_set_clk(struct w100_pll_info *pll)
+{
+	int status;
+
+	if (w100_pwr_state.auto_mode == 1)  /* auto mode */
+	{
+		w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
+		w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
+		writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
+	}
+
+	/* Set system clock source to XTAL whilst adjusting the PLL! */
+	w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
+	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
+
+	w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
+	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
+	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
+	w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
+	writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
+
+	w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
+	writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
+
+	status = w100_pll_calibration(pll);
+
+	if (w100_pwr_state.auto_mode == 1)  /* auto mode */
+	{
+		w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
+		w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
+		writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
+	}
+	return status;
+}
+
+/* freq = target frequency of the PLL */
+static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
+{
+	struct w100_pll_info *pll = par->pll_table;
+
+	do {
+		if (freq == pll->freq) {
+			return w100_pll_set_clk(pll);
+		}
+		pll++;
+	} while(pll->freq);
+	return 0;
+}
+
+/* Set up an initial state.  Some values/fields set
+   here will be overwritten. */
+static void w100_pwm_setup(struct w100fb_par *par)
+{
+	w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
+	w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
+	w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
+	w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
+	w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
+	w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
+	writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
+
+	w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
+	w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
+	w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
+	w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
+	w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
+	w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
+	w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
+	w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
+	w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
+	w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
+	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
+
+	w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
+	w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
+	w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
+	writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
+
+	w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
+	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
+	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
+	w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
+	w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
+	writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
+
+	w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
+	w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
+	w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
+	w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
+	w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
+	w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
+	w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
+	w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
+	w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
+	w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
+	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
+
+	w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
+	w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
+	w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
+	w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
+	w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
+	w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
+	w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
+	w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
+	w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
+	writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
+
+	w100_pwr_state.auto_mode = 0;  /* manual mode */
+}
+
+
+/*
+ * Setup the w100 clocks for the specified mode
+ */
+static void w100_init_clocks(struct w100fb_par *par)
+{
+	struct w100_mode *mode = par->mode;
+
+	if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
+		w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
+
+	w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
+	w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
+	w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
+	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
+}
+
+static void w100_init_lcd(struct w100fb_par *par)
+{
+	u32 temp32;
+	struct w100_mode *mode = par->mode;
+	struct w100_gen_regs *regs = par->mach->regs;
+	union active_h_disp_u active_h_disp;
+	union active_v_disp_u active_v_disp;
+	union graphic_h_disp_u graphic_h_disp;
+	union graphic_v_disp_u graphic_v_disp;
+	union crtc_total_u crtc_total;
+
+	/* w3200 doesn't like undefined bits being set so zero register values first */
+
+	active_h_disp.val = 0;
+	active_h_disp.f.active_h_start=mode->left_margin;
+	active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
+	writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
+
+	active_v_disp.val = 0;
+	active_v_disp.f.active_v_start=mode->upper_margin;
+	active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
+	writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
+
+	graphic_h_disp.val = 0;
+	graphic_h_disp.f.graphic_h_start=mode->left_margin;
+	graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
+	writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
+
+	graphic_v_disp.val = 0;
+	graphic_v_disp.f.graphic_v_start=mode->upper_margin;
+	graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
+	writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
+
+	crtc_total.val = 0;
+	crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
+	crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
+	writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
+
+	writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
+	writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
+	writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
+	writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
+	writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
+	writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
+	writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
+	writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
+	writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
+
+	writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
+	writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
+	writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
+	writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
+	writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
+	writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
+
+	writel(0x00000000, remapped_regs + mmCRTC_FRAME);
+	writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
+	writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
+	writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
+
+	/* Hack for overlay in ext memory */
+	temp32 = readl(remapped_regs + mmDISP_DEBUG2);
+	temp32 |= 0xc0000000;
+	writel(temp32, remapped_regs + mmDISP_DEBUG2);
+}
+
+
+static void w100_setup_memory(struct w100fb_par *par)
+{
+	union mc_ext_mem_location_u extmem_location;
+	union mc_fb_location_u intmem_location;
+	struct w100_mem_info *mem = par->mach->mem;
+	struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
+
+	if (!par->extmem_active) {
+		w100_suspend(W100_SUSPEND_EXTMEM);
+
+		/* Map Internal Memory at FB Base */
+		intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
+		intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
+		writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
+
+		/* Unmap External Memory - value is *probably* irrelevant but may have meaning
+		   to acceleration libraries */
+		extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
+		extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
+		writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+	} else {
+		/* Map Internal Memory to its default location */
+		intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
+		intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
+		writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
+
+		/* Map External Memory at FB Base */
+		extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
+		extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
+		writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
+
+		writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
+		writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
+		writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+		udelay(100);
+		writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
+		udelay(100);
+		writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
+		udelay(100);
+		writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
+		writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
+		if (bm_mem) {
+			writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
+			writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
+			writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
+			writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
+			writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
+			writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
+			writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
+		}
+	}
+}
+
+static void w100_set_dispregs(struct w100fb_par *par)
+{
+	unsigned long rot=0, divider, offset=0;
+	union graphic_ctrl_u graphic_ctrl;
+
+	/* See if the mode has been rotated */
+	if (par->xres == par->mode->xres) {
+		if (par->flip) {
+			rot=3; /* 180 degree */
+			offset=(par->xres * par->yres) - 1;
+		} /* else 0 degree */
+		divider = par->mode->pixclk_divider;
+	} else {
+		if (par->flip) {
+			rot=2; /* 270 degree */
+			offset=par->xres - 1;
+		} else {
+			rot=1; /* 90 degree */
+			offset=par->xres * (par->yres - 1);
+		}
+		divider = par->mode->pixclk_divider_rotated;
+	}
+
+	graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
+	switch (par->chip_id) {
+		case CHIP_ID_W100:
+			graphic_ctrl.f_w100.color_depth=6;
+			graphic_ctrl.f_w100.en_crtc=1;
+			graphic_ctrl.f_w100.en_graphic_req=1;
+			graphic_ctrl.f_w100.en_graphic_crtc=1;
+			graphic_ctrl.f_w100.lcd_pclk_on=1;
+			graphic_ctrl.f_w100.lcd_sclk_on=1;
+			graphic_ctrl.f_w100.low_power_on=0;
+			graphic_ctrl.f_w100.req_freq=0;
+			graphic_ctrl.f_w100.portrait_mode=rot;
+
+			/* Zaurus needs this */
+			switch(par->xres) {
+				case 240:
+				case 320:
+				default:
+					graphic_ctrl.f_w100.total_req_graphic=0xa0;
+					break;
+				case 480:
+				case 640:
+					switch(rot) {
+						case 0:  /* 0 */
+						case 3:  /* 180 */
+							graphic_ctrl.f_w100.low_power_on=1;
+							graphic_ctrl.f_w100.req_freq=5;
+						break;
+						case 1:  /* 90 */
+						case 2:  /* 270 */
+							graphic_ctrl.f_w100.req_freq=4;
+							break;
+						default:
+							break;
+					}
+					graphic_ctrl.f_w100.total_req_graphic=0xf0;
+					break;
+			}
+			break;
+		case CHIP_ID_W3200:
+		case CHIP_ID_W3220:
+			graphic_ctrl.f_w32xx.color_depth=6;
+			graphic_ctrl.f_w32xx.en_crtc=1;
+			graphic_ctrl.f_w32xx.en_graphic_req=1;
+			graphic_ctrl.f_w32xx.en_graphic_crtc=1;
+			graphic_ctrl.f_w32xx.lcd_pclk_on=1;
+			graphic_ctrl.f_w32xx.lcd_sclk_on=1;
+			graphic_ctrl.f_w32xx.low_power_on=0;
+			graphic_ctrl.f_w32xx.req_freq=0;
+			graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
+			graphic_ctrl.f_w32xx.portrait_mode=rot;
+			break;
+	}
+
+	/* Set the pixel clock source and divider */
+	w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
+	w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
+	writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
+
+	writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
+	writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
+	writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
+}
+
+
+/*
+ * Work out how long the sync pulse lasts
+ * Value is 1/(time in seconds)
+ */
+static void calc_hsync(struct w100fb_par *par)
+{
+	unsigned long hsync;
+	struct w100_mode *mode = par->mode;
+	union crtc_ss_u crtc_ss;
+
+	if (mode->pixclk_src == CLK_SRC_XTAL)
+		hsync=par->mach->xtal_freq;
+	else
+		hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
+
+	hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
+
+	crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
+	if (crtc_ss.val)
+		par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
+	else
+		par->hsync_len = 0;
+}
+
+static void w100_suspend(u32 mode)
+{
+	u32 val;
+
+	writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
+	writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
+
+	val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
+	val &= ~(0x00100000);  /* bit20=0 */
+	val |= 0xFF000000;     /* bit31:24=0xff */
+	writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
+
+	val = readl(remapped_regs + mmMEM_EXT_CNTL);
+	val &= ~(0x00040000);  /* bit18=0 */
+	val |= 0x00080000;     /* bit19=1 */
+	writel(val, remapped_regs + mmMEM_EXT_CNTL);
+
+	udelay(1);  /* wait 1us */
+
+	if (mode == W100_SUSPEND_EXTMEM) {
+		/* CKE: Tri-State */
+		val = readl(remapped_regs + mmMEM_EXT_CNTL);
+		val |= 0x40000000;  /* bit30=1 */
+		writel(val, remapped_regs + mmMEM_EXT_CNTL);
+
+		/* CLK: Stop */
+		val = readl(remapped_regs + mmMEM_EXT_CNTL);
+		val &= ~(0x00000001);  /* bit0=0 */
+		writel(val, remapped_regs + mmMEM_EXT_CNTL);
+	} else {
+		writel(0x00000000, remapped_regs + mmSCLK_CNTL);
+		writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
+		writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
+
+		udelay(5);
+
+		val = readl(remapped_regs + mmPLL_CNTL);
+		val |= 0x00000004;  /* bit2=1 */
+		writel(val, remapped_regs + mmPLL_CNTL);
+
+		writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
+		writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
+		writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
+		writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
+		writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
+
+		val = readl(remapped_regs + mmMEM_EXT_CNTL);
+		val |= 0xF0000000;
+		val &= ~(0x00000001);
+		writel(val, remapped_regs + mmMEM_EXT_CNTL);
+
+		writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
+	}
+}
+
+static void w100_vsync(void)
+{
+	u32 tmp;
+	int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
+
+	tmp = readl(remapped_regs + mmACTIVE_V_DISP);
+
+	/* set vline pos  */
+	writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
+
+	/* disable vline irq */
+	tmp = readl(remapped_regs + mmGEN_INT_CNTL);
+
+	tmp &= ~0x00000002;
+	writel(tmp, remapped_regs + mmGEN_INT_CNTL);
+
+	/* clear vline irq status */
+	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
+
+	/* enable vline irq */
+	writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
+
+	/* clear vline irq status */
+	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
+
+	while(timeout > 0) {
+		if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
+			break;
+		udelay(1);
+		timeout--;
+	}
+
+	/* disable vline irq */
+	writel(tmp, remapped_regs + mmGEN_INT_CNTL);
+
+	/* clear vline irq status */
+	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
+}
+
+static struct platform_driver w100fb_driver = {
+	.probe		= w100fb_probe,
+	.remove		= w100fb_remove,
+	.suspend	= w100fb_suspend,
+	.resume		= w100fb_resume,
+	.driver		= {
+		.name	= "w100fb",
+	},
+};
+
+module_platform_driver(w100fb_driver);
+
+MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/w100fb.h b/drivers/video/fbdev/w100fb.h
new file mode 100644
index 000000000000..fffae7b4f6e9
--- /dev/null
+++ b/drivers/video/fbdev/w100fb.h
@@ -0,0 +1,928 @@
+/*
+ * linux/drivers/video/w100fb.h
+ *
+ * Frame Buffer Device for ATI w100 (Wallaby)
+ *
+ * Copyright (C) 2002, ATI Corp.
+ * Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (c) 2005 Ian Molton <spyro@f2s.com>
+ *
+ * Modified to work with 2.6 by Richard Purdie <rpurdie@rpsys.net>
+ *
+ * w32xx support by Ian Molton
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#if !defined (_W100FB_H)
+#define _W100FB_H
+
+/* Block CIF Start: */
+#define mmCHIP_ID           0x0000
+#define mmREVISION_ID       0x0004
+#define mmWRAP_BUF_A        0x0008
+#define mmWRAP_BUF_B        0x000C
+#define mmWRAP_TOP_DIR      0x0010
+#define mmWRAP_START_DIR    0x0014
+#define mmCIF_CNTL          0x0018
+#define mmCFGREG_BASE       0x001C
+#define mmCIF_IO            0x0020
+#define mmCIF_READ_DBG      0x0024
+#define mmCIF_WRITE_DBG     0x0028
+#define cfgIND_ADDR_A_0     0x0000
+#define cfgIND_ADDR_A_1     0x0001
+#define cfgIND_ADDR_A_2     0x0002
+#define cfgIND_DATA_A       0x0003
+#define cfgREG_BASE         0x0004
+#define cfgINTF_CNTL        0x0005
+#define cfgSTATUS           0x0006
+#define cfgCPU_DEFAULTS     0x0007
+#define cfgIND_ADDR_B_0     0x0008
+#define cfgIND_ADDR_B_1     0x0009
+#define cfgIND_ADDR_B_2     0x000A
+#define cfgIND_DATA_B       0x000B
+#define cfgPM4_RPTR         0x000C
+#define cfgSCRATCH          0x000D
+#define cfgPM4_WRPTR_0      0x000E
+#define cfgPM4_WRPTR_1      0x000F
+/* Block CIF End: */
+
+/* Block CP Start: */
+#define mmSCRATCH_UMSK      0x0280
+#define mmSCRATCH_ADDR      0x0284
+#define mmGEN_INT_CNTL      0x0200
+#define mmGEN_INT_STATUS    0x0204
+/* Block CP End: */
+
+/* Block DISPLAY Start: */
+#define mmLCD_FORMAT        0x0410
+#define mmGRAPHIC_CTRL      0x0414
+#define mmGRAPHIC_OFFSET    0x0418
+#define mmGRAPHIC_PITCH     0x041C
+#define mmCRTC_TOTAL        0x0420
+#define mmACTIVE_H_DISP     0x0424
+#define mmACTIVE_V_DISP     0x0428
+#define mmGRAPHIC_H_DISP    0x042C
+#define mmGRAPHIC_V_DISP    0x0430
+#define mmVIDEO_CTRL        0x0434
+#define mmGRAPHIC_KEY       0x0438
+#define mmBRIGHTNESS_CNTL   0x045C
+#define mmDISP_INT_CNTL     0x0488
+#define mmCRTC_SS           0x048C
+#define mmCRTC_LS           0x0490
+#define mmCRTC_REV          0x0494
+#define mmCRTC_DCLK         0x049C
+#define mmCRTC_GS           0x04A0
+#define mmCRTC_VPOS_GS      0x04A4
+#define mmCRTC_GCLK         0x04A8
+#define mmCRTC_GOE          0x04AC
+#define mmCRTC_FRAME        0x04B0
+#define mmCRTC_FRAME_VPOS   0x04B4
+#define mmGPIO_DATA         0x04B8
+#define mmGPIO_CNTL1        0x04BC
+#define mmGPIO_CNTL2        0x04C0
+#define mmLCDD_CNTL1        0x04C4
+#define mmLCDD_CNTL2        0x04C8
+#define mmGENLCD_CNTL1      0x04CC
+#define mmGENLCD_CNTL2      0x04D0
+#define mmDISP_DEBUG        0x04D4
+#define mmDISP_DB_BUF_CNTL  0x04D8
+#define mmDISP_CRC_SIG      0x04DC
+#define mmCRTC_DEFAULT_COUNT    0x04E0
+#define mmLCD_BACKGROUND_COLOR  0x04E4
+#define mmCRTC_PS2          0x04E8
+#define mmCRTC_PS2_VPOS     0x04EC
+#define mmCRTC_PS1_ACTIVE   0x04F0
+#define mmCRTC_PS1_NACTIVE  0x04F4
+#define mmCRTC_GCLK_EXT     0x04F8
+#define mmCRTC_ALW          0x04FC
+#define mmCRTC_ALW_VPOS     0x0500
+#define mmCRTC_PSK          0x0504
+#define mmCRTC_PSK_HPOS     0x0508
+#define mmCRTC_CV4_START    0x050C
+#define mmCRTC_CV4_END      0x0510
+#define mmCRTC_CV4_HPOS     0x0514
+#define mmCRTC_ECK          0x051C
+#define mmREFRESH_CNTL      0x0520
+#define mmGENLCD_CNTL3      0x0524
+#define mmGPIO_DATA2        0x0528
+#define mmGPIO_CNTL3        0x052C
+#define mmGPIO_CNTL4        0x0530
+#define mmCHIP_STRAP        0x0534
+#define mmDISP_DEBUG2       0x0538
+#define mmDEBUG_BUS_CNTL    0x053C
+#define mmGAMMA_VALUE1      0x0540
+#define mmGAMMA_VALUE2      0x0544
+#define mmGAMMA_SLOPE       0x0548
+#define mmGEN_STATUS        0x054C
+#define mmHW_INT            0x0550
+/* Block DISPLAY End: */
+
+/* Block GFX Start: */
+#define mmDST_OFFSET          0x1004
+#define mmDST_PITCH           0x1008
+#define mmDST_Y_X             0x1038
+#define mmDST_WIDTH_HEIGHT    0x1198
+#define mmDP_GUI_MASTER_CNTL  0x106C
+#define mmBRUSH_OFFSET        0x108C
+#define mmBRUSH_Y_X           0x1074
+#define mmDP_BRUSH_FRGD_CLR   0x107C
+#define mmSRC_OFFSET          0x11AC
+#define mmSRC_PITCH           0x11B0
+#define mmSRC_Y_X             0x1034
+#define mmDEFAULT_PITCH_OFFSET      0x10A0
+#define mmDEFAULT_SC_BOTTOM_RIGHT   0x10A8
+#define mmDEFAULT2_SC_BOTTOM_RIGHT  0x10AC
+#define mmSC_TOP_LEFT         0x11BC
+#define mmSC_BOTTOM_RIGHT     0x11C0
+#define mmSRC_SC_BOTTOM_RIGHT 0x11C4
+#define mmGLOBAL_ALPHA        0x1210
+#define mmFILTER_COEF         0x1214
+#define mmMVC_CNTL_START      0x11E0
+#define mmE2_ARITHMETIC_CNTL  0x1220
+#define mmDP_CNTL             0x11C8
+#define mmDP_CNTL_DST_DIR     0x11CC
+#define mmDP_DATATYPE         0x12C4
+#define mmDP_MIX              0x12C8
+#define mmDP_WRITE_MSK        0x12CC
+#define mmENG_CNTL            0x13E8
+#define mmENG_PERF_CNT        0x13F0
+/* Block GFX End: */
+
+/* Block IDCT Start: */
+#define mmIDCT_RUNS         0x0C00
+#define mmIDCT_LEVELS       0x0C04
+#define mmIDCT_CONTROL      0x0C3C
+#define mmIDCT_AUTH_CONTROL 0x0C08
+#define mmIDCT_AUTH         0x0C0C
+/* Block IDCT End: */
+
+/* Block MC Start: */
+#define mmMEM_CNTL             0x0180
+#define mmMEM_ARB              0x0184
+#define mmMC_FB_LOCATION       0x0188
+#define mmMEM_EXT_CNTL         0x018C
+#define mmMC_EXT_MEM_LOCATION  0x0190
+#define mmMEM_EXT_TIMING_CNTL  0x0194
+#define mmMEM_SDRAM_MODE_REG   0x0198
+#define mmMEM_IO_CNTL          0x019C
+#define mmMC_DEBUG             0x01A0
+#define mmMC_BIST_CTRL         0x01A4
+#define mmMC_BIST_COLLAR_READ  0x01A8
+#define mmTC_MISMATCH          0x01AC
+#define mmMC_PERF_MON_CNTL     0x01B0
+#define mmMC_PERF_COUNTERS     0x01B4
+/* Block MC End: */
+
+/* Block BM Start: */
+#define mmBM_EXT_MEM_BANDWIDTH    0x0A00
+#define mmBM_OFFSET               0x0A04
+#define mmBM_MEM_EXT_TIMING_CNTL  0x0A08
+#define mmBM_MEM_EXT_CNTL         0x0A0C
+#define mmBM_MEM_MODE_REG         0x0A10
+#define mmBM_MEM_IO_CNTL          0x0A18
+#define mmBM_CONFIG               0x0A1C
+#define mmBM_STATUS               0x0A20
+#define mmBM_DEBUG                0x0A24
+#define mmBM_PERF_MON_CNTL        0x0A28
+#define mmBM_PERF_COUNTERS        0x0A2C
+#define mmBM_PERF2_MON_CNTL       0x0A30
+#define mmBM_PERF2_COUNTERS       0x0A34
+/* Block BM End: */
+
+/* Block RBBM Start: */
+#define mmWAIT_UNTIL        0x1400
+#define mmISYNC_CNTL        0x1404
+#define mmRBBM_STATUS       0x0140
+#define mmRBBM_CNTL         0x0144
+#define mmNQWAIT_UNTIL      0x0150
+/* Block RBBM End: */
+
+/* Block CG Start: */
+#define mmCLK_PIN_CNTL      0x0080
+#define mmPLL_REF_FB_DIV    0x0084
+#define mmPLL_CNTL          0x0088
+#define mmSCLK_CNTL         0x008C
+#define mmPCLK_CNTL         0x0090
+#define mmCLK_TEST_CNTL     0x0094
+#define mmPWRMGT_CNTL       0x0098
+#define mmPWRMGT_STATUS     0x009C
+/* Block CG End: */
+
+/* default value definitions */
+#define defWRAP_TOP_DIR        0x00000000
+#define defWRAP_START_DIR      0x00000000
+#define defCFGREG_BASE         0x00000000
+#define defCIF_IO              0x000C0902
+#define defINTF_CNTL           0x00000011
+#define defCPU_DEFAULTS        0x00000006
+#define defHW_INT              0x00000000
+#define defMC_EXT_MEM_LOCATION 0x07ff0000
+#define defTC_MISMATCH         0x00000000
+
+#define W100_CFG_BASE          0x0
+#define W100_CFG_LEN           0x10
+#define W100_REG_BASE          0x10000
+#define W100_REG_LEN           0x2000
+#define MEM_INT_BASE_VALUE     0x100000
+#define MEM_EXT_BASE_VALUE     0x800000
+#define MEM_INT_SIZE           0x05ffff
+#define MEM_WINDOW_BASE        0x100000
+#define MEM_WINDOW_SIZE        0xf00000
+
+#define WRAP_BUF_BASE_VALUE    0x80000
+#define WRAP_BUF_TOP_VALUE     0xbffff
+
+#define CHIP_ID_W100           0x57411002
+#define CHIP_ID_W3200          0x56441002
+#define CHIP_ID_W3220          0x57441002
+
+/* Register structure definitions */
+
+struct wrap_top_dir_t {
+	u32 top_addr  : 23;
+	u32           : 9;
+} __attribute__((packed));
+
+union wrap_top_dir_u {
+	u32 val : 32;
+	struct wrap_top_dir_t f;
+} __attribute__((packed));
+
+struct wrap_start_dir_t {
+	u32 start_addr : 23;
+	u32            : 9;
+} __attribute__((packed));
+
+union wrap_start_dir_u {
+	u32 val : 32;
+	struct wrap_start_dir_t f;
+} __attribute__((packed));
+
+struct cif_cntl_t {
+	u32 swap_reg                 : 2;
+	u32 swap_fbuf_1              : 2;
+	u32 swap_fbuf_2              : 2;
+	u32 swap_fbuf_3              : 2;
+	u32 pmi_int_disable          : 1;
+	u32 pmi_schmen_disable       : 1;
+	u32 intb_oe                  : 1;
+	u32 en_wait_to_compensate_dq_prop_dly  : 1;
+	u32 compensate_wait_rd_size  : 2;
+	u32 wait_asserted_timeout_val  : 2;
+	u32 wait_masked_val          : 2;
+	u32 en_wait_timeout          : 1;
+	u32 en_one_clk_setup_before_wait  : 1;
+	u32 interrupt_active_high    : 1;
+	u32 en_overwrite_straps      : 1;
+	u32 strap_wait_active_hi     : 1;
+	u32 lat_busy_count           : 2;
+	u32 lat_rd_pm4_sclk_busy     : 1;
+	u32 dis_system_bits          : 1;
+	u32 dis_mr                   : 1;
+	u32 cif_spare_1              : 4;
+} __attribute__((packed));
+
+union cif_cntl_u {
+	u32 val : 32;
+	struct cif_cntl_t f;
+} __attribute__((packed));
+
+struct cfgreg_base_t {
+	u32 cfgreg_base  : 24;
+	u32              : 8;
+} __attribute__((packed));
+
+union cfgreg_base_u {
+	u32 val : 32;
+	struct cfgreg_base_t f;
+} __attribute__((packed));
+
+struct cif_io_t {
+	u32 dq_srp     : 1;
+	u32 dq_srn     : 1;
+	u32 dq_sp      : 4;
+	u32 dq_sn      : 4;
+	u32 waitb_srp  : 1;
+	u32 waitb_srn  : 1;
+	u32 waitb_sp   : 4;
+	u32 waitb_sn   : 4;
+	u32 intb_srp   : 1;
+	u32 intb_srn   : 1;
+	u32 intb_sp    : 4;
+	u32 intb_sn    : 4;
+	u32            : 2;
+} __attribute__((packed));
+
+union cif_io_u {
+	u32 val : 32;
+	struct cif_io_t f;
+} __attribute__((packed));
+
+struct cif_read_dbg_t {
+	u32 unpacker_pre_fetch_trig_gen  : 2;
+	u32 dly_second_rd_fetch_trig     : 1;
+	u32 rst_rd_burst_id              : 1;
+	u32 dis_rd_burst_id              : 1;
+	u32 en_block_rd_when_packer_is_not_emp : 1;
+	u32 dis_pre_fetch_cntl_sm        : 1;
+	u32 rbbm_chrncy_dis              : 1;
+	u32 rbbm_rd_after_wr_lat         : 2;
+	u32 dis_be_during_rd             : 1;
+	u32 one_clk_invalidate_pulse     : 1;
+	u32 dis_chnl_priority            : 1;
+	u32 rst_read_path_a_pls          : 1;
+	u32 rst_read_path_b_pls          : 1;
+	u32 dis_reg_rd_fetch_trig        : 1;
+	u32 dis_rd_fetch_trig_from_ind_addr : 1;
+	u32 dis_rd_same_byte_to_trig_fetch : 1;
+	u32 dis_dir_wrap                 : 1;
+	u32 dis_ring_buf_to_force_dec    : 1;
+	u32 dis_addr_comp_in_16bit       : 1;
+	u32 clr_w                        : 1;
+	u32 err_rd_tag_is_3              : 1;
+	u32 err_load_when_ful_a          : 1;
+	u32 err_load_when_ful_b          : 1;
+	u32                              : 7;
+} __attribute__((packed));
+
+union cif_read_dbg_u {
+	u32 val : 32;
+	struct cif_read_dbg_t f;
+} __attribute__((packed));
+
+struct cif_write_dbg_t {
+	u32 packer_timeout_count          : 2;
+	u32 en_upper_load_cond            : 1;
+	u32 en_chnl_change_cond           : 1;
+	u32 dis_addr_comp_cond            : 1;
+	u32 dis_load_same_byte_addr_cond  : 1;
+	u32 dis_timeout_cond              : 1;
+	u32 dis_timeout_during_rbbm       : 1;
+	u32 dis_packer_ful_during_rbbm_timeout : 1;
+	u32 en_dword_split_to_rbbm        : 1;
+	u32 en_dummy_val                  : 1;
+	u32 dummy_val_sel                 : 1;
+	u32 mask_pm4_wrptr_dec            : 1;
+	u32 dis_mc_clean_cond             : 1;
+	u32 err_two_reqi_during_ful       : 1;
+	u32 err_reqi_during_idle_clk      : 1;
+	u32 err_global                    : 1;
+	u32 en_wr_buf_dbg_load            : 1;
+	u32 en_wr_buf_dbg_path            : 1;
+	u32 sel_wr_buf_byte               : 3;
+	u32 dis_rd_flush_wr               : 1;
+	u32 dis_packer_ful_cond           : 1;
+	u32 dis_invalidate_by_ops_chnl    : 1;
+	u32 en_halt_when_reqi_err         : 1;
+	u32 cif_spare_2                   : 5;
+	u32                               : 1;
+} __attribute__((packed));
+
+union cif_write_dbg_u {
+	u32 val : 32;
+	struct cif_write_dbg_t f;
+} __attribute__((packed));
+
+
+struct intf_cntl_t {
+	unsigned char ad_inc_a            : 1;
+	unsigned char ring_buf_a          : 1;
+	unsigned char rd_fetch_trigger_a  : 1;
+	unsigned char rd_data_rdy_a       : 1;
+	unsigned char ad_inc_b            : 1;
+	unsigned char ring_buf_b          : 1;
+	unsigned char rd_fetch_trigger_b  : 1;
+	unsigned char rd_data_rdy_b       : 1;
+} __attribute__((packed));
+
+union intf_cntl_u {
+	unsigned char val : 8;
+	struct intf_cntl_t f;
+} __attribute__((packed));
+
+struct cpu_defaults_t {
+	unsigned char unpack_rd_data     : 1;
+	unsigned char access_ind_addr_a  : 1;
+	unsigned char access_ind_addr_b  : 1;
+	unsigned char access_scratch_reg : 1;
+	unsigned char pack_wr_data       : 1;
+	unsigned char transition_size    : 1;
+	unsigned char en_read_buf_mode   : 1;
+	unsigned char rd_fetch_scratch   : 1;
+} __attribute__((packed));
+
+union cpu_defaults_u {
+	unsigned char val : 8;
+	struct cpu_defaults_t f;
+} __attribute__((packed));
+
+struct crtc_total_t {
+	u32 crtc_h_total : 10;
+	u32              : 6;
+	u32 crtc_v_total : 10;
+	u32              : 6;
+} __attribute__((packed));
+
+union crtc_total_u {
+	u32 val : 32;
+	struct crtc_total_t f;
+} __attribute__((packed));
+
+struct crtc_ss_t {
+	u32 ss_start    : 10;
+	u32             : 6;
+	u32 ss_end      : 10;
+	u32             : 2;
+	u32 ss_align    : 1;
+	u32 ss_pol      : 1;
+	u32 ss_run_mode : 1;
+	u32 ss_en       : 1;
+} __attribute__((packed));
+
+union crtc_ss_u {
+	u32 val : 32;
+	struct crtc_ss_t f;
+} __attribute__((packed));
+
+struct active_h_disp_t {
+	u32 active_h_start  : 10;
+	u32                 : 6;
+	u32 active_h_end    : 10;
+	u32                 : 6;
+} __attribute__((packed));
+
+union active_h_disp_u {
+	u32 val : 32;
+	struct active_h_disp_t f;
+} __attribute__((packed));
+
+struct active_v_disp_t {
+	u32 active_v_start  : 10;
+	u32                 : 6;
+	u32 active_v_end    : 10;
+	u32                 : 6;
+} __attribute__((packed));
+
+union active_v_disp_u {
+	u32 val : 32;
+	struct active_v_disp_t f;
+} __attribute__((packed));
+
+struct graphic_h_disp_t {
+	u32 graphic_h_start : 10;
+	u32                 : 6;
+	u32 graphic_h_end   : 10;
+	u32                 : 6;
+} __attribute__((packed));
+
+union graphic_h_disp_u {
+	u32 val : 32;
+	struct graphic_h_disp_t f;
+} __attribute__((packed));
+
+struct graphic_v_disp_t {
+	u32 graphic_v_start : 10;
+	u32                 : 6;
+	u32 graphic_v_end   : 10;
+	u32                 : 6;
+} __attribute__((packed));
+
+union graphic_v_disp_u{
+	u32 val : 32;
+	struct graphic_v_disp_t f;
+} __attribute__((packed));
+
+struct graphic_ctrl_t_w100 {
+	u32 color_depth       : 3;
+	u32 portrait_mode     : 2;
+	u32 low_power_on      : 1;
+	u32 req_freq          : 4;
+	u32 en_crtc           : 1;
+	u32 en_graphic_req    : 1;
+	u32 en_graphic_crtc   : 1;
+	u32 total_req_graphic : 9;
+	u32 lcd_pclk_on       : 1;
+	u32 lcd_sclk_on       : 1;
+	u32 pclk_running      : 1;
+	u32 sclk_running      : 1;
+	u32                   : 6;
+} __attribute__((packed));
+
+struct graphic_ctrl_t_w32xx {
+	u32 color_depth       : 3;
+	u32 portrait_mode     : 2;
+	u32 low_power_on      : 1;
+	u32 req_freq          : 4;
+	u32 en_crtc           : 1;
+	u32 en_graphic_req    : 1;
+	u32 en_graphic_crtc   : 1;
+	u32 total_req_graphic : 10;
+	u32 lcd_pclk_on       : 1;
+	u32 lcd_sclk_on       : 1;
+	u32 pclk_running      : 1;
+	u32 sclk_running      : 1;
+	u32                   : 5;
+} __attribute__((packed));
+
+union graphic_ctrl_u {
+	u32 val : 32;
+	struct graphic_ctrl_t_w100 f_w100;
+	struct graphic_ctrl_t_w32xx f_w32xx;
+} __attribute__((packed));
+
+struct video_ctrl_t {
+	u32 video_mode       : 1;
+	u32 keyer_en         : 1;
+	u32 en_video_req     : 1;
+	u32 en_graphic_req_video  : 1;
+	u32 en_video_crtc    : 1;
+	u32 video_hor_exp    : 2;
+	u32 video_ver_exp    : 2;
+	u32 uv_combine       : 1;
+	u32 total_req_video  : 9;
+	u32 video_ch_sel     : 1;
+	u32 video_portrait   : 2;
+	u32 yuv2rgb_en       : 1;
+	u32 yuv2rgb_option   : 1;
+	u32 video_inv_hor    : 1;
+	u32 video_inv_ver    : 1;
+	u32 gamma_sel        : 2;
+	u32 dis_limit        : 1;
+	u32 en_uv_hblend     : 1;
+	u32 rgb_gamma_sel    : 2;
+} __attribute__((packed));
+
+union video_ctrl_u {
+	u32 val : 32;
+	struct video_ctrl_t f;
+} __attribute__((packed));
+
+struct disp_db_buf_cntl_rd_t {
+	u32 en_db_buf           : 1;
+	u32 update_db_buf_done  : 1;
+	u32 db_buf_cntl         : 6;
+	u32                     : 24;
+} __attribute__((packed));
+
+union disp_db_buf_cntl_rd_u {
+	u32 val : 32;
+	struct disp_db_buf_cntl_rd_t f;
+} __attribute__((packed));
+
+struct disp_db_buf_cntl_wr_t {
+	u32 en_db_buf      : 1;
+	u32 update_db_buf  : 1;
+	u32 db_buf_cntl    : 6;
+	u32                : 24;
+} __attribute__((packed));
+
+union disp_db_buf_cntl_wr_u {
+	u32 val : 32;
+	struct disp_db_buf_cntl_wr_t f;
+} __attribute__((packed));
+
+struct gamma_value1_t {
+	u32 gamma1   : 8;
+	u32 gamma2   : 8;
+	u32 gamma3   : 8;
+	u32 gamma4   : 8;
+} __attribute__((packed));
+
+union gamma_value1_u {
+	u32 val : 32;
+	struct gamma_value1_t f;
+} __attribute__((packed));
+
+struct gamma_value2_t {
+	u32 gamma5   : 8;
+	u32 gamma6   : 8;
+	u32 gamma7   : 8;
+	u32 gamma8   : 8;
+} __attribute__((packed));
+
+union gamma_value2_u {
+	u32 val : 32;
+	struct gamma_value2_t f;
+} __attribute__((packed));
+
+struct gamma_slope_t {
+	u32 slope1   : 3;
+	u32 slope2   : 3;
+	u32 slope3   : 3;
+	u32 slope4   : 3;
+	u32 slope5   : 3;
+	u32 slope6   : 3;
+	u32 slope7   : 3;
+	u32 slope8   : 3;
+	u32          : 8;
+} __attribute__((packed));
+
+union gamma_slope_u {
+	u32 val : 32;
+	struct gamma_slope_t f;
+} __attribute__((packed));
+
+struct mc_ext_mem_location_t {
+	u32 mc_ext_mem_start : 16;
+	u32 mc_ext_mem_top   : 16;
+} __attribute__((packed));
+
+union mc_ext_mem_location_u {
+	u32 val : 32;
+	struct mc_ext_mem_location_t f;
+} __attribute__((packed));
+
+struct mc_fb_location_t {
+	u32 mc_fb_start      : 16;
+	u32 mc_fb_top        : 16;
+} __attribute__((packed));
+
+union mc_fb_location_u {
+	u32 val : 32;
+	struct mc_fb_location_t f;
+} __attribute__((packed));
+
+struct clk_pin_cntl_t {
+	u32 osc_en           : 1;
+	u32 osc_gain         : 5;
+	u32 dont_use_xtalin  : 1;
+	u32 xtalin_pm_en     : 1;
+	u32 xtalin_dbl_en    : 1;
+	u32                  : 7;
+	u32 cg_debug         : 16;
+} __attribute__((packed));
+
+union clk_pin_cntl_u {
+	u32 val : 32;
+	struct clk_pin_cntl_t f;
+} __attribute__((packed));
+
+struct pll_ref_fb_div_t {
+	u32 pll_ref_div      : 4;
+	u32                  : 4;
+	u32 pll_fb_div_int   : 6;
+	u32                  : 2;
+	u32 pll_fb_div_frac  : 3;
+	u32                  : 1;
+	u32 pll_reset_time   : 4;
+	u32 pll_lock_time    : 8;
+} __attribute__((packed));
+
+union pll_ref_fb_div_u {
+	u32 val : 32;
+	struct pll_ref_fb_div_t f;
+} __attribute__((packed));
+
+struct pll_cntl_t {
+	u32 pll_pwdn        : 1;
+	u32 pll_reset       : 1;
+	u32 pll_pm_en       : 1;
+	u32 pll_mode        : 1;
+	u32 pll_refclk_sel  : 1;
+	u32 pll_fbclk_sel   : 1;
+	u32 pll_tcpoff      : 1;
+	u32 pll_pcp         : 3;
+	u32 pll_pvg         : 3;
+	u32 pll_vcofr       : 1;
+	u32 pll_ioffset     : 2;
+	u32 pll_pecc_mode   : 2;
+	u32 pll_pecc_scon   : 2;
+	u32 pll_dactal      : 4;
+	u32 pll_cp_clip     : 2;
+	u32 pll_conf        : 3;
+	u32 pll_mbctrl      : 2;
+	u32 pll_ring_off    : 1;
+} __attribute__((packed));
+
+union pll_cntl_u {
+	u32 val : 32;
+	struct pll_cntl_t f;
+} __attribute__((packed));
+
+struct sclk_cntl_t {
+	u32 sclk_src_sel         : 2;
+	u32                      : 2;
+	u32 sclk_post_div_fast   : 4;
+	u32 sclk_clkon_hys       : 3;
+	u32 sclk_post_div_slow   : 4;
+	u32 disp_cg_ok2switch_en : 1;
+	u32 sclk_force_reg       : 1;
+	u32 sclk_force_disp      : 1;
+	u32 sclk_force_mc        : 1;
+	u32 sclk_force_extmc     : 1;
+	u32 sclk_force_cp        : 1;
+	u32 sclk_force_e2        : 1;
+	u32 sclk_force_e3        : 1;
+	u32 sclk_force_idct      : 1;
+	u32 sclk_force_bist      : 1;
+	u32 busy_extend_cp       : 1;
+	u32 busy_extend_e2       : 1;
+	u32 busy_extend_e3       : 1;
+	u32 busy_extend_idct     : 1;
+	u32                      : 3;
+} __attribute__((packed));
+
+union sclk_cntl_u {
+	u32 val : 32;
+	struct sclk_cntl_t f;
+} __attribute__((packed));
+
+struct pclk_cntl_t {
+	u32 pclk_src_sel     : 2;
+	u32                  : 2;
+	u32 pclk_post_div    : 4;
+	u32                  : 8;
+	u32 pclk_force_disp  : 1;
+	u32                  : 15;
+} __attribute__((packed));
+
+union pclk_cntl_u {
+	u32 val : 32;
+	struct pclk_cntl_t f;
+} __attribute__((packed));
+
+
+#define TESTCLK_SRC_PLL   0x01
+#define TESTCLK_SRC_SCLK  0x02
+#define TESTCLK_SRC_PCLK  0x03
+/* 4 and 5 seem to by XTAL/M */
+#define TESTCLK_SRC_XTAL  0x06
+
+struct clk_test_cntl_t {
+	u32 testclk_sel      : 4;
+	u32                  : 3;
+	u32 start_check_freq : 1;
+	u32 tstcount_rst     : 1;
+	u32                  : 15;
+	u32 test_count       : 8;
+} __attribute__((packed));
+
+union clk_test_cntl_u {
+	u32 val : 32;
+	struct clk_test_cntl_t f;
+} __attribute__((packed));
+
+struct pwrmgt_cntl_t {
+	u32 pwm_enable           : 1;
+	u32                      : 1;
+	u32 pwm_mode_req         : 2;
+	u32 pwm_wakeup_cond      : 2;
+	u32 pwm_fast_noml_hw_en  : 1;
+	u32 pwm_noml_fast_hw_en  : 1;
+	u32 pwm_fast_noml_cond   : 4;
+	u32 pwm_noml_fast_cond   : 4;
+	u32 pwm_idle_timer       : 8;
+	u32 pwm_busy_timer       : 8;
+} __attribute__((packed));
+
+union pwrmgt_cntl_u {
+	u32 val : 32;
+	struct pwrmgt_cntl_t f;
+} __attribute__((packed));
+
+#define SRC_DATATYPE_EQU_DST	3
+
+#define ROP3_SRCCOPY	0xcc
+#define ROP3_PATCOPY	0xf0
+
+#define GMC_BRUSH_SOLID_COLOR	13
+#define GMC_BRUSH_NONE			15
+
+#define DP_SRC_MEM_RECTANGULAR	2
+
+#define DP_OP_ROP	0
+
+struct dp_gui_master_cntl_t {
+	u32 gmc_src_pitch_offset_cntl : 1;
+	u32 gmc_dst_pitch_offset_cntl : 1;
+	u32 gmc_src_clipping          : 1;
+	u32 gmc_dst_clipping          : 1;
+	u32 gmc_brush_datatype        : 4;
+	u32 gmc_dst_datatype          : 4;
+	u32 gmc_src_datatype          : 3;
+	u32 gmc_byte_pix_order        : 1;
+	u32 gmc_default_sel           : 1;
+	u32 gmc_rop3                  : 8;
+	u32 gmc_dp_src_source         : 3;
+	u32 gmc_clr_cmp_fcn_dis       : 1;
+	u32                           : 1;
+	u32 gmc_wr_msk_dis            : 1;
+	u32 gmc_dp_op                 : 1;
+} __attribute__((packed));
+
+union dp_gui_master_cntl_u {
+	u32 val : 32;
+	struct dp_gui_master_cntl_t f;
+} __attribute__((packed));
+
+struct rbbm_status_t {
+	u32 cmdfifo_avail   : 7;
+	u32                 : 1;
+	u32 hirq_on_rbb     : 1;
+	u32 cprq_on_rbb     : 1;
+	u32 cfrq_on_rbb     : 1;
+	u32 hirq_in_rtbuf   : 1;
+	u32 cprq_in_rtbuf   : 1;
+	u32 cfrq_in_rtbuf   : 1;
+	u32 cf_pipe_busy    : 1;
+	u32 eng_ev_busy     : 1;
+	u32 cp_cmdstrm_busy : 1;
+	u32 e2_busy         : 1;
+	u32 rb2d_busy       : 1;
+	u32 rb3d_busy       : 1;
+	u32 se_busy         : 1;
+	u32 re_busy         : 1;
+	u32 tam_busy        : 1;
+	u32 tdm_busy        : 1;
+	u32 pb_busy         : 1;
+	u32                 : 6;
+	u32 gui_active      : 1;
+} __attribute__((packed));
+
+union rbbm_status_u {
+	u32 val : 32;
+	struct rbbm_status_t f;
+} __attribute__((packed));
+
+struct dp_datatype_t {
+	u32 dp_dst_datatype   : 4;
+	u32                   : 4;
+	u32 dp_brush_datatype : 4;
+	u32 dp_src2_type      : 1;
+	u32 dp_src2_datatype  : 3;
+	u32 dp_src_datatype   : 3;
+	u32                   : 11;
+	u32 dp_byte_pix_order : 1;
+	u32                   : 1;
+} __attribute__((packed));
+
+union dp_datatype_u {
+	u32 val : 32;
+	struct dp_datatype_t f;
+} __attribute__((packed));
+
+struct dp_mix_t {
+	u32                : 8;
+	u32 dp_src_source  : 3;
+	u32 dp_src2_source : 3;
+	u32                : 2;
+	u32 dp_rop3        : 8;
+	u32 dp_op          : 1;
+	u32                : 7;
+} __attribute__((packed));
+
+union dp_mix_u {
+	u32 val : 32;
+	struct dp_mix_t f;
+} __attribute__((packed));
+
+struct eng_cntl_t {
+	u32 erc_reg_rd_ws            : 1;
+	u32 erc_reg_wr_ws            : 1;
+	u32 erc_idle_reg_wr          : 1;
+	u32 dis_engine_triggers      : 1;
+	u32 dis_rop_src_uses_dst_w_h : 1;
+	u32 dis_src_uses_dst_dirmaj  : 1;
+	u32                          : 6;
+	u32 force_3dclk_when_2dclk   : 1;
+	u32                          : 19;
+} __attribute__((packed));
+
+union eng_cntl_u {
+	u32 val : 32;
+	struct eng_cntl_t f;
+} __attribute__((packed));
+
+struct dp_cntl_t {
+	u32 dst_x_dir   : 1;
+	u32 dst_y_dir   : 1;
+	u32 src_x_dir   : 1;
+	u32 src_y_dir   : 1;
+	u32 dst_major_x : 1;
+	u32 src_major_x : 1;
+	u32             : 26;
+} __attribute__((packed));
+
+union dp_cntl_u {
+	u32 val : 32;
+	struct dp_cntl_t f;
+} __attribute__((packed));
+
+struct dp_cntl_dst_dir_t {
+	u32           : 15;
+	u32 dst_y_dir : 1;
+	u32           : 15;
+	u32 dst_x_dir : 1;
+} __attribute__((packed));
+
+union dp_cntl_dst_dir_u {
+	u32 val : 32;
+	struct dp_cntl_dst_dir_t f;
+} __attribute__((packed));
+
+#endif
+
diff --git a/drivers/video/fbdev/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c
new file mode 100644
index 000000000000..537d199612af
--- /dev/null
+++ b/drivers/video/fbdev/wm8505fb.c
@@ -0,0 +1,421 @@
+/*
+ *  WonderMedia WM8505 Frame Buffer device driver
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *    Based on vt8500lcdfb.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/memblock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <video/of_display_timing.h>
+
+#include "wm8505fb_regs.h"
+#include "wmt_ge_rops.h"
+
+#define DRIVER_NAME "wm8505-fb"
+
+#define to_wm8505fb_info(__info) container_of(__info, \
+						struct wm8505fb_info, fb)
+struct wm8505fb_info {
+	struct fb_info		fb;
+	void __iomem		*regbase;
+	unsigned int		contrast;
+};
+
+
+static int wm8505fb_init_hw(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	int i;
+
+	/* I know the purpose only of few registers, so clear unknown */
+	for (i = 0; i < 0x200; i += 4)
+		writel(0, fbi->regbase + i);
+
+	/* Set frame buffer address */
+	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
+	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
+
+	/*
+	 * Set in-memory picture format to RGB
+	 * 0x31C sets the correct color mode (RGB565) for WM8650
+	 * Bit 8+9 (0x300) are ignored on WM8505 as reserved
+	 */
+	writel(0x31c,		       fbi->regbase + WMT_GOVR_COLORSPACE);
+	writel(1,		       fbi->regbase + WMT_GOVR_COLORSPACE1);
+
+	/* Virtual buffer size */
+	writel(info->var.xres,	       fbi->regbase + WMT_GOVR_XRES);
+	writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
+
+	/* black magic ;) */
+	writel(0xf,		       fbi->regbase + WMT_GOVR_FHI);
+	writel(4,		       fbi->regbase + WMT_GOVR_DVO_SET);
+	writel(1,		       fbi->regbase + WMT_GOVR_MIF_ENABLE);
+	writel(1,		       fbi->regbase + WMT_GOVR_REG_UPDATE);
+
+	return 0;
+}
+
+static int wm8505fb_set_timing(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	int h_start = info->var.left_margin;
+	int h_end = h_start + info->var.xres;
+	int h_all = h_end + info->var.right_margin;
+	int h_sync = info->var.hsync_len;
+
+	int v_start = info->var.upper_margin;
+	int v_end = v_start + info->var.yres;
+	int v_all = v_end + info->var.lower_margin;
+	int v_sync = info->var.vsync_len;
+
+	writel(0, fbi->regbase + WMT_GOVR_TG);
+
+	writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
+	writel(h_end,   fbi->regbase + WMT_GOVR_TIMING_H_END);
+	writel(h_all,   fbi->regbase + WMT_GOVR_TIMING_H_ALL);
+	writel(h_sync,  fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
+
+	writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
+	writel(v_end,   fbi->regbase + WMT_GOVR_TIMING_V_END);
+	writel(v_all,   fbi->regbase + WMT_GOVR_TIMING_V_ALL);
+	writel(v_sync,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+
+	writel(1, fbi->regbase + WMT_GOVR_TG);
+
+	return 0;
+}
+
+
+static int wm8505fb_set_par(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	if (!fbi)
+		return -EINVAL;
+
+	if (info->var.bits_per_pixel == 32) {
+		info->var.red.offset = 16;
+		info->var.red.length = 8;
+		info->var.red.msb_right = 0;
+		info->var.green.offset = 8;
+		info->var.green.length = 8;
+		info->var.green.msb_right = 0;
+		info->var.blue.offset = 0;
+		info->var.blue.length = 8;
+		info->var.blue.msb_right = 0;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.line_length = info->var.xres_virtual << 2;
+	} else if (info->var.bits_per_pixel == 16) {
+		info->var.red.offset = 11;
+		info->var.red.length = 5;
+		info->var.red.msb_right = 0;
+		info->var.green.offset = 5;
+		info->var.green.length = 6;
+		info->var.green.msb_right = 0;
+		info->var.blue.offset = 0;
+		info->var.blue.length = 5;
+		info->var.blue.msb_right = 0;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.line_length = info->var.xres_virtual << 1;
+	}
+
+	wm8505fb_set_timing(info);
+
+	writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
+		fbi->regbase + WMT_GOVR_CONTRAST);
+
+	return 0;
+}
+
+static ssize_t contrast_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	return sprintf(buf, "%d\n", fbi->contrast);
+}
+
+static ssize_t contrast_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+	unsigned long tmp;
+
+	if (kstrtoul(buf, 10, &tmp) || (tmp > 0xff))
+		return -EINVAL;
+	fbi->contrast = tmp;
+
+	wm8505fb_set_par(info);
+
+	return count;
+}
+
+static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info) {
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+	int ret = 1;
+	unsigned int val;
+	if (regno >= 256)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
+	writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
+	return 0;
+}
+
+static int wm8505fb_blank(int blank, struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		wm8505fb_set_timing(info);
+		break;
+	default:
+		writel(0,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+		break;
+	}
+
+	return 0;
+}
+
+static struct fb_ops wm8505fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_set_par	= wm8505fb_set_par,
+	.fb_setcolreg	= wm8505fb_setcolreg,
+	.fb_fillrect	= wmt_ge_fillrect,
+	.fb_copyarea	= wmt_ge_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_sync	= wmt_ge_sync,
+	.fb_pan_display	= wm8505fb_pan_display,
+	.fb_blank	= wm8505fb_blank,
+};
+
+static int wm8505fb_probe(struct platform_device *pdev)
+{
+	struct wm8505fb_info	*fbi;
+	struct resource	*res;
+	struct display_timings *disp_timing;
+	void			*addr;
+	int ret;
+
+	struct fb_videomode	mode;
+	u32			bpp;
+	dma_addr_t fb_mem_phys;
+	unsigned long fb_mem_len;
+	void *fb_mem_virt;
+
+	fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
+			sizeof(u32) * 16, GFP_KERNEL);
+	if (!fbi) {
+		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+		return -ENOMEM;
+	}
+
+	strcpy(fbi->fb.fix.id, DRIVER_NAME);
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.xpanstep	= 1;
+	fbi->fb.fix.ypanstep	= 1;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.fbops		= &wm8505fb_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT
+				| FBINFO_HWACCEL_COPYAREA
+				| FBINFO_HWACCEL_FILLRECT
+				| FBINFO_HWACCEL_XPAN
+				| FBINFO_HWACCEL_YPAN
+				| FBINFO_VIRTFB
+				| FBINFO_PARTIAL_PAN_OK;
+	fbi->fb.node		= -1;
+
+	addr = fbi;
+	addr = addr + sizeof(struct wm8505fb_info);
+	fbi->fb.pseudo_palette	= addr;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fbi->regbase))
+		return PTR_ERR(fbi->regbase);
+
+	disp_timing = of_get_display_timings(pdev->dev.of_node);
+	if (!disp_timing)
+		return -EINVAL;
+
+	ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+	if (ret)
+		return ret;
+
+	fb_videomode_to_var(&fbi->fb.var, &mode);
+
+	fbi->fb.var.nonstd		= 0;
+	fbi->fb.var.activate		= FB_ACTIVATE_NOW;
+
+	fbi->fb.var.height		= -1;
+	fbi->fb.var.width		= -1;
+
+	/* try allocating the framebuffer */
+	fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8);
+	fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
+				GFP_KERNEL);
+	if (!fb_mem_virt) {
+		pr_err("%s: Failed to allocate framebuffer\n", __func__);
+		return -ENOMEM;
+	}
+
+	fbi->fb.var.xres_virtual	= mode.xres;
+	fbi->fb.var.yres_virtual	= mode.yres * 2;
+	fbi->fb.var.bits_per_pixel	= bpp;
+
+	fbi->fb.fix.smem_start		= fb_mem_phys;
+	fbi->fb.fix.smem_len		= fb_mem_len;
+	fbi->fb.screen_base		= fb_mem_virt;
+	fbi->fb.screen_size		= fb_mem_len;
+
+	fbi->contrast = 0x10;
+	ret = wm8505fb_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set parameters\n");
+		return ret;
+	}
+
+	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+		dev_err(&pdev->dev, "Failed to allocate color map\n");
+		return -ENOMEM;
+	}
+
+	wm8505fb_init_hw(&fbi->fb);
+
+	platform_set_drvdata(pdev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Failed to register framebuffer device: %d\n", ret);
+		if (fbi->fb.cmap.len)
+			fb_dealloc_cmap(&fbi->fb.cmap);
+		return ret;
+	}
+
+	ret = device_create_file(&pdev->dev, &dev_attr_contrast);
+	if (ret < 0)
+		fb_warn(&fbi->fb, "failed to register attributes (%d)\n", ret);
+
+	fb_info(&fbi->fb, "%s frame buffer at 0x%lx-0x%lx\n",
+		fbi->fb.fix.id, fbi->fb.fix.smem_start,
+		fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
+
+	return 0;
+}
+
+static int wm8505fb_remove(struct platform_device *pdev)
+{
+	struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
+
+	device_remove_file(&pdev->dev, &dev_attr_contrast);
+
+	unregister_framebuffer(&fbi->fb);
+
+	writel(0, fbi->regbase);
+
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+
+	return 0;
+}
+
+static const struct of_device_id wmt_dt_ids[] = {
+	{ .compatible = "wm,wm8505-fb", },
+	{}
+};
+
+static struct platform_driver wm8505fb_driver = {
+	.probe		= wm8505fb_probe,
+	.remove		= wm8505fb_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRIVER_NAME,
+		.of_match_table = wmt_dt_ids,
+	},
+};
+
+module_platform_driver(wm8505fb_driver);
+
+MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
+MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_dt_ids);
diff --git a/drivers/video/fbdev/wm8505fb_regs.h b/drivers/video/fbdev/wm8505fb_regs.h
new file mode 100644
index 000000000000..4dd41668c6d1
--- /dev/null
+++ b/drivers/video/fbdev/wm8505fb_regs.h
@@ -0,0 +1,76 @@
+/*
+ *  GOVR registers list for WM8505 chips
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *   Based on VIA/WonderMedia wm8510-govrh-reg.h
+ *   http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
+ *         drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _WM8505FB_REGS_H
+#define _WM8505FB_REGS_H
+
+/*
+ * Color space select register, default value 0x1c
+ *   BIT0 GOVRH_DVO_YUV2RGB_ENABLE
+ *   BIT1 GOVRH_VGA_YUV2RGB_ENABLE
+ *   BIT2 GOVRH_RGB_MODE
+ *   BIT3 GOVRH_DAC_CLKINV
+ *   BIT4 GOVRH_BLANK_ZERO
+ */
+#define WMT_GOVR_COLORSPACE	0x1e4
+/*
+ * Another colorspace select register, default value 1
+ *   BIT0 GOVRH_DVO_RGB
+ *   BIT1 GOVRH_DVO_YUV422
+ */
+#define WMT_GOVR_COLORSPACE1	 0x30
+
+#define WMT_GOVR_CONTRAST	0x1b8
+#define WMT_GOVR_BRGHTNESS	0x1bc /* incompatible with RGB? */
+
+/* Framubeffer address */
+#define WMT_GOVR_FBADDR		 0x90
+#define WMT_GOVR_FBADDR1	 0x94 /* UV offset in YUV mode */
+
+/* Offset of visible window */
+#define WMT_GOVR_XPAN		 0xa4
+#define WMT_GOVR_YPAN		 0xa0
+
+#define WMT_GOVR_XRES		 0x98
+#define WMT_GOVR_XRES_VIRTUAL	 0x9c
+
+#define WMT_GOVR_MIF_ENABLE	 0x80
+#define WMT_GOVR_FHI		 0xa8
+#define WMT_GOVR_REG_UPDATE	 0xe4
+
+/*
+ *   BIT0 GOVRH_DVO_OUTWIDTH
+ *   BIT1 GOVRH_DVO_SYNC_POLAR
+ *   BIT2 GOVRH_DVO_ENABLE
+ */
+#define WMT_GOVR_DVO_SET	0x148
+
+/* Timing generator? */
+#define WMT_GOVR_TG		0x100
+
+/* Timings */
+#define WMT_GOVR_TIMING_H_ALL	0x108
+#define WMT_GOVR_TIMING_V_ALL	0x10c
+#define WMT_GOVR_TIMING_V_START	0x110
+#define WMT_GOVR_TIMING_V_END	0x114
+#define WMT_GOVR_TIMING_H_START	0x118
+#define WMT_GOVR_TIMING_H_END	0x11c
+#define WMT_GOVR_TIMING_V_SYNC	0x128
+#define WMT_GOVR_TIMING_H_SYNC	0x12c
+
+#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/fbdev/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c
new file mode 100644
index 000000000000..9df6fe78a44b
--- /dev/null
+++ b/drivers/video/fbdev/wmt_ge_rops.c
@@ -0,0 +1,182 @@
+/*
+ *  linux/drivers/video/wmt_ge_rops.c
+ *
+ *  Accelerators for raster operations using WonderMedia Graphics Engine
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include "core/fb_draw.h"
+
+#define GE_COMMAND_OFF		0x00
+#define GE_DEPTH_OFF		0x04
+#define GE_HIGHCOLOR_OFF	0x08
+#define GE_ROPCODE_OFF		0x14
+#define GE_FIRE_OFF		0x18
+#define GE_SRCBASE_OFF		0x20
+#define GE_SRCDISPW_OFF		0x24
+#define GE_SRCDISPH_OFF		0x28
+#define GE_SRCAREAX_OFF		0x2c
+#define GE_SRCAREAY_OFF		0x30
+#define GE_SRCAREAW_OFF		0x34
+#define GE_SRCAREAH_OFF		0x38
+#define GE_DESTBASE_OFF		0x3c
+#define GE_DESTDISPW_OFF	0x40
+#define GE_DESTDISPH_OFF	0x44
+#define GE_DESTAREAX_OFF	0x48
+#define GE_DESTAREAY_OFF	0x4c
+#define GE_DESTAREAW_OFF	0x50
+#define GE_DESTAREAH_OFF	0x54
+#define GE_PAT0C_OFF		0x88	/* Pattern 0 color */
+#define GE_ENABLE_OFF		0xec
+#define GE_INTEN_OFF		0xf0
+#define GE_STATUS_OFF		0xf8
+
+static void __iomem *regbase;
+
+void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	unsigned long fg, pat;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    p->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		fg = ((u32 *) (p->pseudo_palette))[rect->color];
+	else
+		fg = rect->color;
+
+	pat = pixel_to_pat(p->var.bits_per_pixel, fg);
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	writel(p->var.bits_per_pixel == 32 ? 3 :
+	      (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
+	writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
+	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+	writel(rect->dx, regbase + GE_DESTAREAX_OFF);
+	writel(rect->dy, regbase + GE_DESTAREAY_OFF);
+	writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
+	writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
+
+	writel(pat, regbase + GE_PAT0C_OFF);
+	writel(1, regbase + GE_COMMAND_OFF);
+	writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
+	writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
+
+void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	writel(p->var.bits_per_pixel > 16 ? 3 :
+	      (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
+
+	writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
+	writel(area->sx, regbase + GE_SRCAREAX_OFF);
+	writel(area->sy, regbase + GE_SRCAREAY_OFF);
+	writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
+	writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
+
+	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+	writel(area->dx, regbase + GE_DESTAREAX_OFF);
+	writel(area->dy, regbase + GE_DESTAREAY_OFF);
+	writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
+	writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
+
+	writel(0xcc, regbase + GE_ROPCODE_OFF);
+	writel(1, regbase + GE_COMMAND_OFF);
+	writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
+
+int wmt_ge_sync(struct fb_info *p)
+{
+	int loops = 5000000;
+	while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
+		cpu_relax();
+	return loops > 0 ? 0 : -EBUSY;
+}
+EXPORT_SYMBOL_GPL(wmt_ge_sync);
+
+static int wmt_ge_rops_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		return -ENODEV;
+	}
+
+	/* Only one ROP engine is presently supported. */
+	if (unlikely(regbase)) {
+		WARN_ON(1);
+		return -EBUSY;
+	}
+
+	regbase = ioremap(res->start, resource_size(res));
+	if (regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		return -EBUSY;
+	}
+
+	writel(1, regbase + GE_ENABLE_OFF);
+	printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
+
+	return 0;
+}
+
+static int wmt_ge_rops_remove(struct platform_device *pdev)
+{
+	iounmap(regbase);
+	return 0;
+}
+
+static const struct of_device_id wmt_dt_ids[] = {
+	{ .compatible = "wm,prizm-ge-rops", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver wmt_ge_rops_driver = {
+	.probe		= wmt_ge_rops_probe,
+	.remove		= wmt_ge_rops_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "wmt_ge_rops",
+		.of_match_table = wmt_dt_ids,
+	},
+};
+
+module_platform_driver(wmt_ge_rops_driver);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("Accelerators for raster operations using "
+		   "WonderMedia Graphics Engine");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_dt_ids);
diff --git a/drivers/video/fbdev/wmt_ge_rops.h b/drivers/video/fbdev/wmt_ge_rops.h
new file mode 100644
index 000000000000..f73ec6377a46
--- /dev/null
+++ b/drivers/video/fbdev/wmt_ge_rops.h
@@ -0,0 +1,28 @@
+#ifdef CONFIG_FB_WMT_GE_ROPS
+
+extern void wmt_ge_fillrect(struct fb_info *info,
+			    const struct fb_fillrect *rect);
+extern void wmt_ge_copyarea(struct fb_info *info,
+			    const struct fb_copyarea *area);
+extern int wmt_ge_sync(struct fb_info *info);
+
+#else
+
+static inline int wmt_ge_sync(struct fb_info *p)
+{
+	return 0;
+}
+
+static inline void wmt_ge_fillrect(struct fb_info *p,
+				    const struct fb_fillrect *rect)
+{
+	sys_fillrect(p, rect);
+}
+
+static inline void wmt_ge_copyarea(struct fb_info *p,
+				     const struct fb_copyarea *area)
+{
+	sys_copyarea(p, area);
+}
+
+#endif
diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c
new file mode 100644
index 000000000000..901014bbc821
--- /dev/null
+++ b/drivers/video/fbdev/xen-fbfront.c
@@ -0,0 +1,719 @@
+/*
+ * Xen para-virtual frame buffer device
+ *
+ * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/video/q40fb.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+/*
+ * TODO:
+ *
+ * Switch to grant tables when they become capable of dealing with the
+ * frame buffer.
+ */
+
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+
+#include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
+#include <xen/events.h>
+#include <xen/page.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/protocols.h>
+#include <xen/xenbus.h>
+#include <xen/platform_pci.h>
+
+struct xenfb_info {
+	unsigned char		*fb;
+	struct fb_info		*fb_info;
+	int			x1, y1, x2, y2;	/* dirty rectangle,
+						   protected by dirty_lock */
+	spinlock_t		dirty_lock;
+	int			nr_pages;
+	int			irq;
+	struct xenfb_page	*page;
+	unsigned long 		*mfns;
+	int			update_wanted; /* XENFB_TYPE_UPDATE wanted */
+	int			feature_resize; /* XENFB_TYPE_RESIZE ok */
+	struct xenfb_resize	resize;		/* protected by resize_lock */
+	int			resize_dpy;	/* ditto */
+	spinlock_t		resize_lock;
+
+	struct xenbus_device	*xbdev;
+};
+
+#define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
+
+enum { KPARAM_MEM, KPARAM_WIDTH, KPARAM_HEIGHT, KPARAM_CNT };
+static int video[KPARAM_CNT] = { 2, XENFB_WIDTH, XENFB_HEIGHT };
+module_param_array(video, int, NULL, 0);
+MODULE_PARM_DESC(video,
+	"Video memory size in MB, width, height in pixels (default 2,800,600)");
+
+static void xenfb_make_preferred_console(void);
+static int xenfb_remove(struct xenbus_device *);
+static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *);
+static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
+static void xenfb_disconnect_backend(struct xenfb_info *);
+
+static void xenfb_send_event(struct xenfb_info *info,
+			     union xenfb_out_event *event)
+{
+	u32 prod;
+
+	prod = info->page->out_prod;
+	/* caller ensures !xenfb_queue_full() */
+	mb();			/* ensure ring space available */
+	XENFB_OUT_RING_REF(info->page, prod) = *event;
+	wmb();			/* ensure ring contents visible */
+	info->page->out_prod = prod + 1;
+
+	notify_remote_via_irq(info->irq);
+}
+
+static void xenfb_do_update(struct xenfb_info *info,
+			    int x, int y, int w, int h)
+{
+	union xenfb_out_event event;
+
+	memset(&event, 0, sizeof(event));
+	event.type = XENFB_TYPE_UPDATE;
+	event.update.x = x;
+	event.update.y = y;
+	event.update.width = w;
+	event.update.height = h;
+
+	/* caller ensures !xenfb_queue_full() */
+	xenfb_send_event(info, &event);
+}
+
+static void xenfb_do_resize(struct xenfb_info *info)
+{
+	union xenfb_out_event event;
+
+	memset(&event, 0, sizeof(event));
+	event.resize = info->resize;
+
+	/* caller ensures !xenfb_queue_full() */
+	xenfb_send_event(info, &event);
+}
+
+static int xenfb_queue_full(struct xenfb_info *info)
+{
+	u32 cons, prod;
+
+	prod = info->page->out_prod;
+	cons = info->page->out_cons;
+	return prod - cons == XENFB_OUT_RING_LEN;
+}
+
+static void xenfb_handle_resize_dpy(struct xenfb_info *info)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->resize_lock, flags);
+	if (info->resize_dpy) {
+		if (!xenfb_queue_full(info)) {
+			info->resize_dpy = 0;
+			xenfb_do_resize(info);
+		}
+	}
+	spin_unlock_irqrestore(&info->resize_lock, flags);
+}
+
+static void xenfb_refresh(struct xenfb_info *info,
+			  int x1, int y1, int w, int h)
+{
+	unsigned long flags;
+	int x2 = x1 + w - 1;
+	int y2 = y1 + h - 1;
+
+	xenfb_handle_resize_dpy(info);
+
+	if (!info->update_wanted)
+		return;
+
+	spin_lock_irqsave(&info->dirty_lock, flags);
+
+	/* Combine with dirty rectangle: */
+	if (info->y1 < y1)
+		y1 = info->y1;
+	if (info->y2 > y2)
+		y2 = info->y2;
+	if (info->x1 < x1)
+		x1 = info->x1;
+	if (info->x2 > x2)
+		x2 = info->x2;
+
+	if (xenfb_queue_full(info)) {
+		/* Can't send right now, stash it in the dirty rectangle */
+		info->x1 = x1;
+		info->x2 = x2;
+		info->y1 = y1;
+		info->y2 = y2;
+		spin_unlock_irqrestore(&info->dirty_lock, flags);
+		return;
+	}
+
+	/* Clear dirty rectangle: */
+	info->x1 = info->y1 = INT_MAX;
+	info->x2 = info->y2 = 0;
+
+	spin_unlock_irqrestore(&info->dirty_lock, flags);
+
+	if (x1 <= x2 && y1 <= y2)
+		xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+}
+
+static void xenfb_deferred_io(struct fb_info *fb_info,
+			      struct list_head *pagelist)
+{
+	struct xenfb_info *info = fb_info->par;
+	struct page *page;
+	unsigned long beg, end;
+	int y1, y2, miny, maxy;
+
+	miny = INT_MAX;
+	maxy = 0;
+	list_for_each_entry(page, pagelist, lru) {
+		beg = page->index << PAGE_SHIFT;
+		end = beg + PAGE_SIZE - 1;
+		y1 = beg / fb_info->fix.line_length;
+		y2 = end / fb_info->fix.line_length;
+		if (y2 >= fb_info->var.yres)
+			y2 = fb_info->var.yres - 1;
+		if (miny > y1)
+			miny = y1;
+		if (maxy < y2)
+			maxy = y2;
+	}
+	xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
+}
+
+static struct fb_deferred_io xenfb_defio = {
+	.delay		= HZ / 20,
+	.deferred_io	= xenfb_deferred_io,
+};
+
+static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	u32 v;
+
+	if (regno > info->cmap.len)
+		return 1;
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	red = CNVT_TOHW(red, info->var.red.length);
+	green = CNVT_TOHW(green, info->var.green.length);
+	blue = CNVT_TOHW(blue, info->var.blue.length);
+	transp = CNVT_TOHW(transp, info->var.transp.length);
+#undef CNVT_TOHW
+
+	v = (red << info->var.red.offset) |
+	    (green << info->var.green.offset) |
+	    (blue << info->var.blue.offset);
+
+	switch (info->var.bits_per_pixel) {
+	case 16:
+	case 24:
+	case 32:
+		((u32 *)info->pseudo_palette)[regno] = v;
+		break;
+	}
+
+	return 0;
+}
+
+static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	struct xenfb_info *info = p->par;
+
+	sys_fillrect(p, rect);
+	xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+	struct xenfb_info *info = p->par;
+
+	sys_imageblit(p, image);
+	xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
+}
+
+static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	struct xenfb_info *info = p->par;
+
+	sys_copyarea(p, area);
+	xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
+}
+
+static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
+			size_t count, loff_t *ppos)
+{
+	struct xenfb_info *info = p->par;
+	ssize_t res;
+
+	res = fb_sys_write(p, buf, count, ppos);
+	xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
+	return res;
+}
+
+static int
+xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct xenfb_info *xenfb_info;
+	int required_mem_len;
+
+	xenfb_info = info->par;
+
+	if (!xenfb_info->feature_resize) {
+		if (var->xres == video[KPARAM_WIDTH] &&
+		    var->yres == video[KPARAM_HEIGHT] &&
+		    var->bits_per_pixel == xenfb_info->page->depth) {
+			return 0;
+		}
+		return -EINVAL;
+	}
+
+	/* Can't resize past initial width and height */
+	if (var->xres > video[KPARAM_WIDTH] || var->yres > video[KPARAM_HEIGHT])
+		return -EINVAL;
+
+	required_mem_len = var->xres * var->yres * xenfb_info->page->depth / 8;
+	if (var->bits_per_pixel == xenfb_info->page->depth &&
+	    var->xres <= info->fix.line_length / (XENFB_DEPTH / 8) &&
+	    required_mem_len <= info->fix.smem_len) {
+		var->xres_virtual = var->xres;
+		var->yres_virtual = var->yres;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int xenfb_set_par(struct fb_info *info)
+{
+	struct xenfb_info *xenfb_info;
+	unsigned long flags;
+
+	xenfb_info = info->par;
+
+	spin_lock_irqsave(&xenfb_info->resize_lock, flags);
+	xenfb_info->resize.type = XENFB_TYPE_RESIZE;
+	xenfb_info->resize.width = info->var.xres;
+	xenfb_info->resize.height = info->var.yres;
+	xenfb_info->resize.stride = info->fix.line_length;
+	xenfb_info->resize.depth = info->var.bits_per_pixel;
+	xenfb_info->resize.offset = 0;
+	xenfb_info->resize_dpy = 1;
+	spin_unlock_irqrestore(&xenfb_info->resize_lock, flags);
+	return 0;
+}
+
+static struct fb_ops xenfb_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read	= fb_sys_read,
+	.fb_write	= xenfb_write,
+	.fb_setcolreg	= xenfb_setcolreg,
+	.fb_fillrect	= xenfb_fillrect,
+	.fb_copyarea	= xenfb_copyarea,
+	.fb_imageblit	= xenfb_imageblit,
+	.fb_check_var	= xenfb_check_var,
+	.fb_set_par     = xenfb_set_par,
+};
+
+static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
+{
+	/*
+	 * No in events recognized, simply ignore them all.
+	 * If you need to recognize some, see xen-kbdfront's
+	 * input_handler() for how to do that.
+	 */
+	struct xenfb_info *info = dev_id;
+	struct xenfb_page *page = info->page;
+
+	if (page->in_cons != page->in_prod) {
+		info->page->in_cons = info->page->in_prod;
+		notify_remote_via_irq(info->irq);
+	}
+
+	/* Flush dirty rectangle: */
+	xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
+
+	return IRQ_HANDLED;
+}
+
+static int xenfb_probe(struct xenbus_device *dev,
+		       const struct xenbus_device_id *id)
+{
+	struct xenfb_info *info;
+	struct fb_info *fb_info;
+	int fb_size;
+	int val;
+	int ret = 0;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+		return -ENOMEM;
+	}
+
+	/* Limit kernel param videoram amount to what is in xenstore */
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {
+		if (val < video[KPARAM_MEM])
+			video[KPARAM_MEM] = val;
+	}
+
+	/* If requested res does not fit in available memory, use default */
+	fb_size = video[KPARAM_MEM] * 1024 * 1024;
+	if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8
+	    > fb_size) {
+		video[KPARAM_WIDTH] = XENFB_WIDTH;
+		video[KPARAM_HEIGHT] = XENFB_HEIGHT;
+		fb_size = XENFB_DEFAULT_FB_LEN;
+	}
+
+	dev_set_drvdata(&dev->dev, info);
+	info->xbdev = dev;
+	info->irq = -1;
+	info->x1 = info->y1 = INT_MAX;
+	spin_lock_init(&info->dirty_lock);
+	spin_lock_init(&info->resize_lock);
+
+	info->fb = vzalloc(fb_size);
+	if (info->fb == NULL)
+		goto error_nomem;
+
+	info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
+	if (!info->mfns)
+		goto error_nomem;
+
+	/* set up shared page */
+	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+	if (!info->page)
+		goto error_nomem;
+
+	/* abusing framebuffer_alloc() to allocate pseudo_palette */
+	fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
+	if (fb_info == NULL)
+		goto error_nomem;
+
+	/* complete the abuse: */
+	fb_info->pseudo_palette = fb_info->par;
+	fb_info->par = info;
+
+	fb_info->screen_base = info->fb;
+
+	fb_info->fbops = &xenfb_fb_ops;
+	fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];
+	fb_info->var.yres_virtual = fb_info->var.yres = video[KPARAM_HEIGHT];
+	fb_info->var.bits_per_pixel = XENFB_DEPTH;
+
+	fb_info->var.red = (struct fb_bitfield){16, 8, 0};
+	fb_info->var.green = (struct fb_bitfield){8, 8, 0};
+	fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
+
+	fb_info->var.activate = FB_ACTIVATE_NOW;
+	fb_info->var.height = -1;
+	fb_info->var.width = -1;
+	fb_info->var.vmode = FB_VMODE_NONINTERLACED;
+
+	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
+	fb_info->fix.line_length = fb_info->var.xres * XENFB_DEPTH / 8;
+	fb_info->fix.smem_start = 0;
+	fb_info->fix.smem_len = fb_size;
+	strcpy(fb_info->fix.id, "xen");
+	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+	fb_info->fix.accel = FB_ACCEL_NONE;
+
+	fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+
+	ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
+	if (ret < 0) {
+		framebuffer_release(fb_info);
+		xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
+		goto error;
+	}
+
+	fb_info->fbdefio = &xenfb_defio;
+	fb_deferred_io_init(fb_info);
+
+	xenfb_init_shared_page(info, fb_info);
+
+	ret = xenfb_connect_backend(dev, info);
+	if (ret < 0) {
+		xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
+		goto error_fb;
+	}
+
+	ret = register_framebuffer(fb_info);
+	if (ret) {
+		xenbus_dev_fatal(dev, ret, "register_framebuffer");
+		goto error_fb;
+	}
+	info->fb_info = fb_info;
+
+	xenfb_make_preferred_console();
+	return 0;
+
+error_fb:
+	fb_deferred_io_cleanup(fb_info);
+	fb_dealloc_cmap(&fb_info->cmap);
+	framebuffer_release(fb_info);
+error_nomem:
+	if (!ret) {
+		ret = -ENOMEM;
+		xenbus_dev_fatal(dev, ret, "allocating device memory");
+	}
+error:
+	xenfb_remove(dev);
+	return ret;
+}
+
+static void xenfb_make_preferred_console(void)
+{
+	struct console *c;
+
+	if (console_set_on_cmdline)
+		return;
+
+	console_lock();
+	for_each_console(c) {
+		if (!strcmp(c->name, "tty") && c->index == 0)
+			break;
+	}
+	console_unlock();
+	if (c) {
+		unregister_console(c);
+		c->flags |= CON_CONSDEV;
+		c->flags &= ~CON_PRINTBUFFER; /* don't print again */
+		register_console(c);
+	}
+}
+
+static int xenfb_resume(struct xenbus_device *dev)
+{
+	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+
+	xenfb_disconnect_backend(info);
+	xenfb_init_shared_page(info, info->fb_info);
+	return xenfb_connect_backend(dev, info);
+}
+
+static int xenfb_remove(struct xenbus_device *dev)
+{
+	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+
+	xenfb_disconnect_backend(info);
+	if (info->fb_info) {
+		fb_deferred_io_cleanup(info->fb_info);
+		unregister_framebuffer(info->fb_info);
+		fb_dealloc_cmap(&info->fb_info->cmap);
+		framebuffer_release(info->fb_info);
+	}
+	free_page((unsigned long)info->page);
+	vfree(info->mfns);
+	vfree(info->fb);
+	kfree(info);
+
+	return 0;
+}
+
+static unsigned long vmalloc_to_mfn(void *address)
+{
+	return pfn_to_mfn(vmalloc_to_pfn(address));
+}
+
+static void xenfb_init_shared_page(struct xenfb_info *info,
+				   struct fb_info *fb_info)
+{
+	int i;
+	int epd = PAGE_SIZE / sizeof(info->mfns[0]);
+
+	for (i = 0; i < info->nr_pages; i++)
+		info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
+
+	for (i = 0; i * epd < info->nr_pages; i++)
+		info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * epd]);
+
+	info->page->width = fb_info->var.xres;
+	info->page->height = fb_info->var.yres;
+	info->page->depth = fb_info->var.bits_per_pixel;
+	info->page->line_length = fb_info->fix.line_length;
+	info->page->mem_length = fb_info->fix.smem_len;
+	info->page->in_cons = info->page->in_prod = 0;
+	info->page->out_cons = info->page->out_prod = 0;
+}
+
+static int xenfb_connect_backend(struct xenbus_device *dev,
+				 struct xenfb_info *info)
+{
+	int ret, evtchn, irq;
+	struct xenbus_transaction xbt;
+
+	ret = xenbus_alloc_evtchn(dev, &evtchn);
+	if (ret)
+		return ret;
+	irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
+					0, dev->devicetype, info);
+	if (irq < 0) {
+		xenbus_free_evtchn(dev, evtchn);
+		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
+		return irq;
+	}
+ again:
+	ret = xenbus_transaction_start(&xbt);
+	if (ret) {
+		xenbus_dev_fatal(dev, ret, "starting transaction");
+		goto unbind_irq;
+	}
+	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+			    virt_to_mfn(info->page));
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    evtchn);
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
+			    XEN_IO_PROTO_ABI_NATIVE);
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_transaction_end(xbt, 0);
+	if (ret) {
+		if (ret == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, ret, "completing transaction");
+		goto unbind_irq;
+	}
+
+	xenbus_switch_state(dev, XenbusStateInitialised);
+	info->irq = irq;
+	return 0;
+
+ error_xenbus:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, ret, "writing xenstore");
+ unbind_irq:
+	unbind_from_irqhandler(irq, info);
+	return ret;
+}
+
+static void xenfb_disconnect_backend(struct xenfb_info *info)
+{
+	/* Prevent xenfb refresh */
+	info->update_wanted = 0;
+	if (info->irq >= 0)
+		unbind_from_irqhandler(info->irq, info);
+	info->irq = -1;
+}
+
+static void xenfb_backend_changed(struct xenbus_device *dev,
+				  enum xenbus_state backend_state)
+{
+	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+	int val;
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+		break;
+
+	case XenbusStateInitWait:
+InitWait:
+		xenbus_switch_state(dev, XenbusStateConnected);
+		break;
+
+	case XenbusStateConnected:
+		/*
+		 * Work around xenbus race condition: If backend goes
+		 * through InitWait to Connected fast enough, we can
+		 * get Connected twice here.
+		 */
+		if (dev->state != XenbusStateConnected)
+			goto InitWait; /* no InitWait seen yet, fudge it */
+
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "request-update", "%d", &val) < 0)
+			val = 0;
+		if (val)
+			info->update_wanted = 1;
+
+		if (xenbus_scanf(XBT_NIL, dev->otherend,
+				 "feature-resize", "%d", &val) < 0)
+			val = 0;
+		info->feature_resize = val;
+		break;
+
+	case XenbusStateClosed:
+		if (dev->state == XenbusStateClosed)
+			break;
+		/* Missed the backend's CLOSING state -- fallthrough */
+	case XenbusStateClosing:
+		xenbus_frontend_closed(dev);
+		break;
+	}
+}
+
+static const struct xenbus_device_id xenfb_ids[] = {
+	{ "vfb" },
+	{ "" }
+};
+
+static DEFINE_XENBUS_DRIVER(xenfb, ,
+	.probe = xenfb_probe,
+	.remove = xenfb_remove,
+	.resume = xenfb_resume,
+	.otherend_changed = xenfb_backend_changed,
+);
+
+static int __init xenfb_init(void)
+{
+	if (!xen_domain())
+		return -ENODEV;
+
+	/* Nothing to do if running in dom0. */
+	if (xen_initial_domain())
+		return -ENODEV;
+
+	if (!xen_has_pv_devices())
+		return -ENODEV;
+
+	return xenbus_register_frontend(&xenfb_driver);
+}
+
+static void __exit xenfb_cleanup(void)
+{
+	xenbus_unregister_driver(&xenfb_driver);
+}
+
+module_init(xenfb_init);
+module_exit(xenfb_cleanup);
+
+MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vfb");
diff --git a/drivers/video/fbdev/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c
new file mode 100644
index 000000000000..553cff2f3f4c
--- /dev/null
+++ b/drivers/video/fbdev/xilinxfb.c
@@ -0,0 +1,509 @@
+/*
+ * Xilinx TFT frame buffer driver
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * 2002-2007 (c) MontaVista Software, Inc.
+ * 2007 (c) Secret Lab Technologies, Ltd.
+ * 2009 (c) Xilinx Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/*
+ * This driver was based on au1100fb.c by MontaVista rewritten for 2.6
+ * by Embedded Alley Solutions <source@embeddedalley.com>, which in turn
+ * was based on skeletonfb.c, Skeleton for a frame buffer device by
+ * Geert Uytterhoeven.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_PPC_DCR
+#include <asm/dcr.h>
+#endif
+
+#define DRIVER_NAME		"xilinxfb"
+
+
+/*
+ * Xilinx calls it "TFT LCD Controller" though it can also be used for
+ * the VGA port on the Xilinx ML40x board. This is a hardware display
+ * controller for a 640x480 resolution TFT or VGA screen.
+ *
+ * The interface to the framebuffer is nice and simple.  There are two
+ * control registers.  The first tells the LCD interface where in memory
+ * the frame buffer is (only the 11 most significant bits are used, so
+ * don't start thinking about scrolling).  The second allows the LCD to
+ * be turned on or off as well as rotated 180 degrees.
+ *
+ * In case of direct BUS access the second control register will be at
+ * an offset of 4 as compared to the DCR access where the offset is 1
+ * i.e. REG_CTRL. So this is taken care in the function
+ * xilinx_fb_out32 where it left shifts the offset 2 times in case of
+ * direct BUS access.
+ */
+#define NUM_REGS	2
+#define REG_FB_ADDR	0
+#define REG_CTRL	1
+#define REG_CTRL_ENABLE	 0x0001
+#define REG_CTRL_ROTATE	 0x0002
+
+/*
+ * The hardware only handles a single mode: 640x480 24 bit true
+ * color. Each pixel gets a word (32 bits) of memory.  Within each word,
+ * the 8 most significant bits are ignored, the next 8 bits are the red
+ * level, the next 8 bits are the green level and the 8 least
+ * significant bits are the blue level.  Each row of the LCD uses 1024
+ * words, but only the first 640 pixels are displayed with the other 384
+ * words being ignored.  There are 480 rows.
+ */
+#define BYTES_PER_PIXEL	4
+#define BITS_PER_PIXEL	(BYTES_PER_PIXEL * 8)
+
+#define RED_SHIFT	16
+#define GREEN_SHIFT	8
+#define BLUE_SHIFT	0
+
+#define PALETTE_ENTRIES_NO	16	/* passed to fb_alloc_cmap() */
+
+/* ML300/403 reference design framebuffer driver platform data struct */
+struct xilinxfb_platform_data {
+	u32 rotate_screen;      /* Flag to rotate display 180 degrees */
+	u32 screen_height_mm;   /* Physical dimensions of screen in mm */
+	u32 screen_width_mm;
+	u32 xres, yres;         /* resolution of screen in pixels */
+	u32 xvirt, yvirt;       /* resolution of memory buffer */
+
+	/* Physical address of framebuffer memory; If non-zero, driver
+	* will use provided memory address instead of allocating one from
+	* the consistent pool. */
+	u32 fb_phys;
+};
+
+/*
+ * Default xilinxfb configuration
+ */
+static struct xilinxfb_platform_data xilinx_fb_default_pdata = {
+	.xres = 640,
+	.yres = 480,
+	.xvirt = 1024,
+	.yvirt = 480,
+};
+
+/*
+ * Here are the default fb_fix_screeninfo and fb_var_screeninfo structures
+ */
+static struct fb_fix_screeninfo xilinx_fb_fix = {
+	.id =		"Xilinx",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE
+};
+
+static struct fb_var_screeninfo xilinx_fb_var = {
+	.bits_per_pixel =	BITS_PER_PIXEL,
+
+	.red =		{ RED_SHIFT, 8, 0 },
+	.green =	{ GREEN_SHIFT, 8, 0 },
+	.blue =		{ BLUE_SHIFT, 8, 0 },
+	.transp =	{ 0, 0, 0 },
+
+	.activate =	FB_ACTIVATE_NOW
+};
+
+
+#define BUS_ACCESS_FLAG		0x1 /* 1 = BUS, 0 = DCR */
+#define LITTLE_ENDIAN_ACCESS	0x2 /* LITTLE ENDIAN IO functions */
+
+struct xilinxfb_drvdata {
+
+	struct fb_info	info;		/* FB driver info record */
+
+	phys_addr_t	regs_phys;	/* phys. address of the control
+						registers */
+	void __iomem	*regs;		/* virt. address of the control
+						registers */
+#ifdef CONFIG_PPC_DCR
+	dcr_host_t      dcr_host;
+	unsigned int    dcr_len;
+#endif
+	void		*fb_virt;	/* virt. address of the frame buffer */
+	dma_addr_t	fb_phys;	/* phys. address of the frame buffer */
+	int		fb_alloced;	/* Flag, was the fb memory alloced? */
+
+	u8 		flags;		/* features of the driver */
+
+	u32		reg_ctrl_default;
+
+	u32		pseudo_palette[PALETTE_ENTRIES_NO];
+					/* Fake palette of 16 colors */
+};
+
+#define to_xilinxfb_drvdata(_info) \
+	container_of(_info, struct xilinxfb_drvdata, info)
+
+/*
+ * The XPS TFT Controller can be accessed through BUS or DCR interface.
+ * To perform the read/write on the registers we need to check on
+ * which bus its connected and call the appropriate write API.
+ */
+static void xilinx_fb_out32(struct xilinxfb_drvdata *drvdata, u32 offset,
+				u32 val)
+{
+	if (drvdata->flags & BUS_ACCESS_FLAG) {
+		if (drvdata->flags & LITTLE_ENDIAN_ACCESS)
+			iowrite32(val, drvdata->regs + (offset << 2));
+		else
+			iowrite32be(val, drvdata->regs + (offset << 2));
+	}
+#ifdef CONFIG_PPC_DCR
+	else
+		dcr_write(drvdata->dcr_host, offset, val);
+#endif
+}
+
+static u32 xilinx_fb_in32(struct xilinxfb_drvdata *drvdata, u32 offset)
+{
+	if (drvdata->flags & BUS_ACCESS_FLAG) {
+		if (drvdata->flags & LITTLE_ENDIAN_ACCESS)
+			return ioread32(drvdata->regs + (offset << 2));
+		else
+			return ioread32be(drvdata->regs + (offset << 2));
+	}
+#ifdef CONFIG_PPC_DCR
+	else
+		return dcr_read(drvdata->dcr_host, offset);
+#endif
+	return 0;
+}
+
+static int
+xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+	unsigned transp, struct fb_info *fbi)
+{
+	u32 *palette = fbi->pseudo_palette;
+
+	if (regno >= PALETTE_ENTRIES_NO)
+		return -EINVAL;
+
+	if (fbi->var.grayscale) {
+		/* Convert color to grayscale.
+		 * grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+			(red * 77 + green * 151 + blue * 28 + 127) >> 8;
+	}
+
+	/* fbi->fix.visual is always FB_VISUAL_TRUECOLOR */
+
+	/* We only handle 8 bits of each color. */
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	palette[regno] = (red << RED_SHIFT) | (green << GREEN_SHIFT) |
+			 (blue << BLUE_SHIFT);
+
+	return 0;
+}
+
+static int
+xilinx_fb_blank(int blank_mode, struct fb_info *fbi)
+{
+	struct xilinxfb_drvdata *drvdata = to_xilinxfb_drvdata(fbi);
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		/* turn on panel */
+		xilinx_fb_out32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
+		break;
+
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		/* turn off panel */
+		xilinx_fb_out32(drvdata, REG_CTRL, 0);
+	default:
+		break;
+
+	}
+	return 0; /* success */
+}
+
+static struct fb_ops xilinxfb_ops =
+{
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= xilinx_fb_setcolreg,
+	.fb_blank		= xilinx_fb_blank,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+};
+
+/* ---------------------------------------------------------------------
+ * Bus independent setup/teardown
+ */
+
+static int xilinxfb_assign(struct platform_device *pdev,
+			   struct xilinxfb_drvdata *drvdata,
+			   struct xilinxfb_platform_data *pdata)
+{
+	int rc;
+	struct device *dev = &pdev->dev;
+	int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL;
+
+	if (drvdata->flags & BUS_ACCESS_FLAG) {
+		struct resource *res;
+
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		drvdata->regs = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(drvdata->regs))
+			return PTR_ERR(drvdata->regs);
+
+		drvdata->regs_phys = res->start;
+	}
+
+	/* Allocate the framebuffer memory */
+	if (pdata->fb_phys) {
+		drvdata->fb_phys = pdata->fb_phys;
+		drvdata->fb_virt = ioremap(pdata->fb_phys, fbsize);
+	} else {
+		drvdata->fb_alloced = 1;
+		drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(fbsize),
+					&drvdata->fb_phys, GFP_KERNEL);
+	}
+
+	if (!drvdata->fb_virt) {
+		dev_err(dev, "Could not allocate frame buffer memory\n");
+		return -ENOMEM;
+	}
+
+	/* Clear (turn to black) the framebuffer */
+	memset_io((void __iomem *)drvdata->fb_virt, 0, fbsize);
+
+	/* Tell the hardware where the frame buffer is */
+	xilinx_fb_out32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
+	rc = xilinx_fb_in32(drvdata, REG_FB_ADDR);
+	/* Endianess detection */
+	if (rc != drvdata->fb_phys) {
+		drvdata->flags |= LITTLE_ENDIAN_ACCESS;
+		xilinx_fb_out32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
+	}
+
+	/* Turn on the display */
+	drvdata->reg_ctrl_default = REG_CTRL_ENABLE;
+	if (pdata->rotate_screen)
+		drvdata->reg_ctrl_default |= REG_CTRL_ROTATE;
+	xilinx_fb_out32(drvdata, REG_CTRL,
+					drvdata->reg_ctrl_default);
+
+	/* Fill struct fb_info */
+	drvdata->info.device = dev;
+	drvdata->info.screen_base = (void __iomem *)drvdata->fb_virt;
+	drvdata->info.fbops = &xilinxfb_ops;
+	drvdata->info.fix = xilinx_fb_fix;
+	drvdata->info.fix.smem_start = drvdata->fb_phys;
+	drvdata->info.fix.smem_len = fbsize;
+	drvdata->info.fix.line_length = pdata->xvirt * BYTES_PER_PIXEL;
+
+	drvdata->info.pseudo_palette = drvdata->pseudo_palette;
+	drvdata->info.flags = FBINFO_DEFAULT;
+	drvdata->info.var = xilinx_fb_var;
+	drvdata->info.var.height = pdata->screen_height_mm;
+	drvdata->info.var.width = pdata->screen_width_mm;
+	drvdata->info.var.xres = pdata->xres;
+	drvdata->info.var.yres = pdata->yres;
+	drvdata->info.var.xres_virtual = pdata->xvirt;
+	drvdata->info.var.yres_virtual = pdata->yvirt;
+
+	/* Allocate a colour map */
+	rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0);
+	if (rc) {
+		dev_err(dev, "Fail to allocate colormap (%d entries)\n",
+			PALETTE_ENTRIES_NO);
+		goto err_cmap;
+	}
+
+	/* Register new frame buffer */
+	rc = register_framebuffer(&drvdata->info);
+	if (rc) {
+		dev_err(dev, "Could not register frame buffer\n");
+		goto err_regfb;
+	}
+
+	if (drvdata->flags & BUS_ACCESS_FLAG) {
+		/* Put a banner in the log (for DEBUG) */
+		dev_dbg(dev, "regs: phys=%pa, virt=%p\n",
+			&drvdata->regs_phys, drvdata->regs);
+	}
+	/* Put a banner in the log (for DEBUG) */
+	dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n",
+		(unsigned long long)drvdata->fb_phys, drvdata->fb_virt, fbsize);
+
+	return 0;	/* success */
+
+err_regfb:
+	fb_dealloc_cmap(&drvdata->info.cmap);
+
+err_cmap:
+	if (drvdata->fb_alloced)
+		dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
+			drvdata->fb_phys);
+	else
+		iounmap(drvdata->fb_virt);
+
+	/* Turn off the display */
+	xilinx_fb_out32(drvdata, REG_CTRL, 0);
+
+	return rc;
+}
+
+static int xilinxfb_release(struct device *dev)
+{
+	struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+	xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info);
+#endif
+
+	unregister_framebuffer(&drvdata->info);
+
+	fb_dealloc_cmap(&drvdata->info.cmap);
+
+	if (drvdata->fb_alloced)
+		dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
+				  drvdata->fb_virt, drvdata->fb_phys);
+	else
+		iounmap(drvdata->fb_virt);
+
+	/* Turn off the display */
+	xilinx_fb_out32(drvdata, REG_CTRL, 0);
+
+#ifdef CONFIG_PPC_DCR
+	/* Release the resources, as allocated based on interface */
+	if (!(drvdata->flags & BUS_ACCESS_FLAG))
+		dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
+#endif
+
+	return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * OF bus binding
+ */
+
+static int xilinxfb_of_probe(struct platform_device *pdev)
+{
+	const u32 *prop;
+	u32 tft_access = 0;
+	struct xilinxfb_platform_data pdata;
+	int size;
+	struct xilinxfb_drvdata *drvdata;
+
+	/* Copy with the default pdata (not a ptr reference!) */
+	pdata = xilinx_fb_default_pdata;
+
+	/* Allocate the driver data region */
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	/*
+	 * To check whether the core is connected directly to DCR or BUS
+	 * interface and initialize the tft_access accordingly.
+	 */
+	of_property_read_u32(pdev->dev.of_node, "xlnx,dcr-splb-slave-if",
+			     &tft_access);
+
+	/*
+	 * Fill the resource structure if its direct BUS interface
+	 * otherwise fill the dcr_host structure.
+	 */
+	if (tft_access) {
+		drvdata->flags |= BUS_ACCESS_FLAG;
+	}
+#ifdef CONFIG_PPC_DCR
+	else {
+		int start;
+		start = dcr_resource_start(pdev->dev.of_node, 0);
+		drvdata->dcr_len = dcr_resource_len(pdev->dev.of_node, 0);
+		drvdata->dcr_host = dcr_map(pdev->dev.of_node, start, drvdata->dcr_len);
+		if (!DCR_MAP_OK(drvdata->dcr_host)) {
+			dev_err(&pdev->dev, "invalid DCR address\n");
+			return -ENODEV;
+		}
+	}
+#endif
+
+	prop = of_get_property(pdev->dev.of_node, "phys-size", &size);
+	if ((prop) && (size >= sizeof(u32)*2)) {
+		pdata.screen_width_mm = prop[0];
+		pdata.screen_height_mm = prop[1];
+	}
+
+	prop = of_get_property(pdev->dev.of_node, "resolution", &size);
+	if ((prop) && (size >= sizeof(u32)*2)) {
+		pdata.xres = prop[0];
+		pdata.yres = prop[1];
+	}
+
+	prop = of_get_property(pdev->dev.of_node, "virtual-resolution", &size);
+	if ((prop) && (size >= sizeof(u32)*2)) {
+		pdata.xvirt = prop[0];
+		pdata.yvirt = prop[1];
+	}
+
+	if (of_find_property(pdev->dev.of_node, "rotate-display", NULL))
+		pdata.rotate_screen = 1;
+
+	dev_set_drvdata(&pdev->dev, drvdata);
+	return xilinxfb_assign(pdev, drvdata, &pdata);
+}
+
+static int xilinxfb_of_remove(struct platform_device *op)
+{
+	return xilinxfb_release(&op->dev);
+}
+
+/* Match table for of_platform binding */
+static struct of_device_id xilinxfb_of_match[] = {
+	{ .compatible = "xlnx,xps-tft-1.00.a", },
+	{ .compatible = "xlnx,xps-tft-2.00.a", },
+	{ .compatible = "xlnx,xps-tft-2.01.a", },
+	{ .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", },
+	{ .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
+
+static struct platform_driver xilinxfb_of_driver = {
+	.probe = xilinxfb_of_probe,
+	.remove = xilinxfb_of_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = xilinxfb_of_match,
+	},
+};
+
+module_platform_driver(xilinxfb_of_driver);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
deleted file mode 100644
index b6d5008f361f..000000000000
--- a/drivers/video/fbmem.c
+++ /dev/null
@@ -1,2002 +0,0 @@
-/*
- *  linux/drivers/video/fbmem.c
- *
- *  Copyright (C) 1994 Martin Schaller
- *
- *	2001 - Documented with DocBook
- *	- Brad Douglas <brad@neruo.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-
-#include <linux/compat.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/vt.h>
-#include <linux/init.h>
-#include <linux/linux_logo.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/console.h>
-#include <linux/kmod.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/efi.h>
-#include <linux/fb.h>
-
-#include <asm/fb.h>
-
-
-    /*
-     *  Frame buffer device initialization and setup routines
-     */
-
-#define FBPIXMAPSIZE	(1024 * 8)
-
-static DEFINE_MUTEX(registration_lock);
-
-struct fb_info *registered_fb[FB_MAX] __read_mostly;
-EXPORT_SYMBOL(registered_fb);
-
-int num_registered_fb __read_mostly;
-EXPORT_SYMBOL(num_registered_fb);
-
-static struct fb_info *get_fb_info(unsigned int idx)
-{
-	struct fb_info *fb_info;
-
-	if (idx >= FB_MAX)
-		return ERR_PTR(-ENODEV);
-
-	mutex_lock(&registration_lock);
-	fb_info = registered_fb[idx];
-	if (fb_info)
-		atomic_inc(&fb_info->count);
-	mutex_unlock(&registration_lock);
-
-	return fb_info;
-}
-
-static void put_fb_info(struct fb_info *fb_info)
-{
-	if (!atomic_dec_and_test(&fb_info->count))
-		return;
-	if (fb_info->fbops->fb_destroy)
-		fb_info->fbops->fb_destroy(fb_info);
-}
-
-int lock_fb_info(struct fb_info *info)
-{
-	mutex_lock(&info->lock);
-	if (!info->fbops) {
-		mutex_unlock(&info->lock);
-		return 0;
-	}
-	return 1;
-}
-EXPORT_SYMBOL(lock_fb_info);
-
-/*
- * Helpers
- */
-
-int fb_get_color_depth(struct fb_var_screeninfo *var,
-		       struct fb_fix_screeninfo *fix)
-{
-	int depth = 0;
-
-	if (fix->visual == FB_VISUAL_MONO01 ||
-	    fix->visual == FB_VISUAL_MONO10)
-		depth = 1;
-	else {
-		if (var->green.length == var->blue.length &&
-		    var->green.length == var->red.length &&
-		    var->green.offset == var->blue.offset &&
-		    var->green.offset == var->red.offset)
-			depth = var->green.length;
-		else
-			depth = var->green.length + var->red.length +
-				var->blue.length;
-	}
-
-	return depth;
-}
-EXPORT_SYMBOL(fb_get_color_depth);
-
-/*
- * Data padding functions.
- */
-void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
-{
-	__fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
-}
-EXPORT_SYMBOL(fb_pad_aligned_buffer);
-
-void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
-				u32 shift_high, u32 shift_low, u32 mod)
-{
-	u8 mask = (u8) (0xfff << shift_high), tmp;
-	int i, j;
-
-	for (i = height; i--; ) {
-		for (j = 0; j < idx; j++) {
-			tmp = dst[j];
-			tmp &= mask;
-			tmp |= *src >> shift_low;
-			dst[j] = tmp;
-			tmp = *src << shift_high;
-			dst[j+1] = tmp;
-			src++;
-		}
-		tmp = dst[idx];
-		tmp &= mask;
-		tmp |= *src >> shift_low;
-		dst[idx] = tmp;
-		if (shift_high < mod) {
-			tmp = *src << shift_high;
-			dst[idx+1] = tmp;
-		}
-		src++;
-		dst += d_pitch;
-	}
-}
-EXPORT_SYMBOL(fb_pad_unaligned_buffer);
-
-/*
- * we need to lock this section since fb_cursor
- * may use fb_imageblit()
- */
-char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
-{
-	u32 align = buf->buf_align - 1, offset;
-	char *addr = buf->addr;
-
-	/* If IO mapped, we need to sync before access, no sharing of
-	 * the pixmap is done
-	 */
-	if (buf->flags & FB_PIXMAP_IO) {
-		if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
-			info->fbops->fb_sync(info);
-		return addr;
-	}
-
-	/* See if we fit in the remaining pixmap space */
-	offset = buf->offset + align;
-	offset &= ~align;
-	if (offset + size > buf->size) {
-		/* We do not fit. In order to be able to re-use the buffer,
-		 * we must ensure no asynchronous DMA'ing or whatever operation
-		 * is in progress, we sync for that.
-		 */
-		if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
-			info->fbops->fb_sync(info);
-		offset = 0;
-	}
-	buf->offset = offset + size;
-	addr += offset;
-
-	return addr;
-}
-EXPORT_SYMBOL(fb_get_buffer_offset);
-
-#ifdef CONFIG_LOGO
-
-static inline unsigned safe_shift(unsigned d, int n)
-{
-	return n < 0 ? d >> -n : d << n;
-}
-
-static void fb_set_logocmap(struct fb_info *info,
-				   const struct linux_logo *logo)
-{
-	struct fb_cmap palette_cmap;
-	u16 palette_green[16];
-	u16 palette_blue[16];
-	u16 palette_red[16];
-	int i, j, n;
-	const unsigned char *clut = logo->clut;
-
-	palette_cmap.start = 0;
-	palette_cmap.len = 16;
-	palette_cmap.red = palette_red;
-	palette_cmap.green = palette_green;
-	palette_cmap.blue = palette_blue;
-	palette_cmap.transp = NULL;
-
-	for (i = 0; i < logo->clutsize; i += n) {
-		n = logo->clutsize - i;
-		/* palette_cmap provides space for only 16 colors at once */
-		if (n > 16)
-			n = 16;
-		palette_cmap.start = 32 + i;
-		palette_cmap.len = n;
-		for (j = 0; j < n; ++j) {
-			palette_cmap.red[j] = clut[0] << 8 | clut[0];
-			palette_cmap.green[j] = clut[1] << 8 | clut[1];
-			palette_cmap.blue[j] = clut[2] << 8 | clut[2];
-			clut += 3;
-		}
-		fb_set_cmap(&palette_cmap, info);
-	}
-}
-
-static void  fb_set_logo_truepalette(struct fb_info *info,
-					    const struct linux_logo *logo,
-					    u32 *palette)
-{
-	static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
-	unsigned char redmask, greenmask, bluemask;
-	int redshift, greenshift, blueshift;
-	int i;
-	const unsigned char *clut = logo->clut;
-
-	/*
-	 * We have to create a temporary palette since console palette is only
-	 * 16 colors long.
-	 */
-	/* Bug: Doesn't obey msb_right ... (who needs that?) */
-	redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
-	greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
-	bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
-	redshift   = info->var.red.offset   - (8 - info->var.red.length);
-	greenshift = info->var.green.offset - (8 - info->var.green.length);
-	blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
-
-	for ( i = 0; i < logo->clutsize; i++) {
-		palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
-				 safe_shift((clut[1] & greenmask), greenshift) |
-				 safe_shift((clut[2] & bluemask), blueshift));
-		clut += 3;
-	}
-}
-
-static void fb_set_logo_directpalette(struct fb_info *info,
-					     const struct linux_logo *logo,
-					     u32 *palette)
-{
-	int redshift, greenshift, blueshift;
-	int i;
-
-	redshift = info->var.red.offset;
-	greenshift = info->var.green.offset;
-	blueshift = info->var.blue.offset;
-
-	for (i = 32; i < 32 + logo->clutsize; i++)
-		palette[i] = i << redshift | i << greenshift | i << blueshift;
-}
-
-static void fb_set_logo(struct fb_info *info,
-			       const struct linux_logo *logo, u8 *dst,
-			       int depth)
-{
-	int i, j, k;
-	const u8 *src = logo->data;
-	u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
-	u8 fg = 1, d;
-
-	switch (fb_get_color_depth(&info->var, &info->fix)) {
-	case 1:
-		fg = 1;
-		break;
-	case 2:
-		fg = 3;
-		break;
-	default:
-		fg = 7;
-		break;
-	}
-
-	if (info->fix.visual == FB_VISUAL_MONO01 ||
-	    info->fix.visual == FB_VISUAL_MONO10)
-		fg = ~((u8) (0xfff << info->var.green.length));
-
-	switch (depth) {
-	case 4:
-		for (i = 0; i < logo->height; i++)
-			for (j = 0; j < logo->width; src++) {
-				*dst++ = *src >> 4;
-				j++;
-				if (j < logo->width) {
-					*dst++ = *src & 0x0f;
-					j++;
-				}
-			}
-		break;
-	case 1:
-		for (i = 0; i < logo->height; i++) {
-			for (j = 0; j < logo->width; src++) {
-				d = *src ^ xor;
-				for (k = 7; k >= 0; k--) {
-					*dst++ = ((d >> k) & 1) ? fg : 0;
-					j++;
-				}
-			}
-		}
-		break;
-	}
-}
-
-/*
- * Three (3) kinds of logo maps exist.  linux_logo_clut224 (>16 colors),
- * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors).  Depending on
- * the visual format and color depth of the framebuffer, the DAC, the
- * pseudo_palette, and the logo data will be adjusted accordingly.
- *
- * Case 1 - linux_logo_clut224:
- * Color exceeds the number of console colors (16), thus we set the hardware DAC
- * using fb_set_cmap() appropriately.  The "needs_cmapreset"  flag will be set.
- *
- * For visuals that require color info from the pseudo_palette, we also construct
- * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
- * will be set.
- *
- * Case 2 - linux_logo_vga16:
- * The number of colors just matches the console colors, thus there is no need
- * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
- * each byte contains color information for two pixels (upper and lower nibble).
- * To be consistent with fb_imageblit() usage, we therefore separate the two
- * nibbles into separate bytes. The "depth" flag will be set to 4.
- *
- * Case 3 - linux_logo_mono:
- * This is similar with Case 2.  Each byte contains information for 8 pixels.
- * We isolate each bit and expand each into a byte. The "depth" flag will
- * be set to 1.
- */
-static struct logo_data {
-	int depth;
-	int needs_directpalette;
-	int needs_truepalette;
-	int needs_cmapreset;
-	const struct linux_logo *logo;
-} fb_logo __read_mostly;
-
-static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
-{
-	u32 size = width * height, i;
-
-	out += size - 1;
-
-	for (i = size; i--; )
-		*out-- = *in++;
-}
-
-static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
-{
-	int i, j, h = height - 1;
-
-	for (i = 0; i < height; i++)
-		for (j = 0; j < width; j++)
-				out[height * j + h - i] = *in++;
-}
-
-static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
-{
-	int i, j, w = width - 1;
-
-	for (i = 0; i < height; i++)
-		for (j = 0; j < width; j++)
-			out[height * (w - j) + i] = *in++;
-}
-
-static void fb_rotate_logo(struct fb_info *info, u8 *dst,
-			   struct fb_image *image, int rotate)
-{
-	u32 tmp;
-
-	if (rotate == FB_ROTATE_UD) {
-		fb_rotate_logo_ud(image->data, dst, image->width,
-				  image->height);
-		image->dx = info->var.xres - image->width - image->dx;
-		image->dy = info->var.yres - image->height - image->dy;
-	} else if (rotate == FB_ROTATE_CW) {
-		fb_rotate_logo_cw(image->data, dst, image->width,
-				  image->height);
-		tmp = image->width;
-		image->width = image->height;
-		image->height = tmp;
-		tmp = image->dy;
-		image->dy = image->dx;
-		image->dx = info->var.xres - image->width - tmp;
-	} else if (rotate == FB_ROTATE_CCW) {
-		fb_rotate_logo_ccw(image->data, dst, image->width,
-				   image->height);
-		tmp = image->width;
-		image->width = image->height;
-		image->height = tmp;
-		tmp = image->dx;
-		image->dx = image->dy;
-		image->dy = info->var.yres - image->height - tmp;
-	}
-
-	image->data = dst;
-}
-
-static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
-			    int rotate, unsigned int num)
-{
-	unsigned int x;
-
-	if (rotate == FB_ROTATE_UR) {
-		for (x = 0;
-		     x < num && image->dx + image->width <= info->var.xres;
-		     x++) {
-			info->fbops->fb_imageblit(info, image);
-			image->dx += image->width + 8;
-		}
-	} else if (rotate == FB_ROTATE_UD) {
-		for (x = 0; x < num && image->dx >= 0; x++) {
-			info->fbops->fb_imageblit(info, image);
-			image->dx -= image->width + 8;
-		}
-	} else if (rotate == FB_ROTATE_CW) {
-		for (x = 0;
-		     x < num && image->dy + image->height <= info->var.yres;
-		     x++) {
-			info->fbops->fb_imageblit(info, image);
-			image->dy += image->height + 8;
-		}
-	} else if (rotate == FB_ROTATE_CCW) {
-		for (x = 0; x < num && image->dy >= 0; x++) {
-			info->fbops->fb_imageblit(info, image);
-			image->dy -= image->height + 8;
-		}
-	}
-}
-
-static int fb_show_logo_line(struct fb_info *info, int rotate,
-			     const struct linux_logo *logo, int y,
-			     unsigned int n)
-{
-	u32 *palette = NULL, *saved_pseudo_palette = NULL;
-	unsigned char *logo_new = NULL, *logo_rotate = NULL;
-	struct fb_image image;
-
-	/* Return if the frame buffer is not mapped or suspended */
-	if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
-	    info->flags & FBINFO_MODULE)
-		return 0;
-
-	image.depth = 8;
-	image.data = logo->data;
-
-	if (fb_logo.needs_cmapreset)
-		fb_set_logocmap(info, logo);
-
-	if (fb_logo.needs_truepalette ||
-	    fb_logo.needs_directpalette) {
-		palette = kmalloc(256 * 4, GFP_KERNEL);
-		if (palette == NULL)
-			return 0;
-
-		if (fb_logo.needs_truepalette)
-			fb_set_logo_truepalette(info, logo, palette);
-		else
-			fb_set_logo_directpalette(info, logo, palette);
-
-		saved_pseudo_palette = info->pseudo_palette;
-		info->pseudo_palette = palette;
-	}
-
-	if (fb_logo.depth <= 4) {
-		logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
-		if (logo_new == NULL) {
-			kfree(palette);
-			if (saved_pseudo_palette)
-				info->pseudo_palette = saved_pseudo_palette;
-			return 0;
-		}
-		image.data = logo_new;
-		fb_set_logo(info, logo, logo_new, fb_logo.depth);
-	}
-
-	image.dx = 0;
-	image.dy = y;
-	image.width = logo->width;
-	image.height = logo->height;
-
-	if (rotate) {
-		logo_rotate = kmalloc(logo->width *
-				      logo->height, GFP_KERNEL);
-		if (logo_rotate)
-			fb_rotate_logo(info, logo_rotate, &image, rotate);
-	}
-
-	fb_do_show_logo(info, &image, rotate, n);
-
-	kfree(palette);
-	if (saved_pseudo_palette != NULL)
-		info->pseudo_palette = saved_pseudo_palette;
-	kfree(logo_new);
-	kfree(logo_rotate);
-	return logo->height;
-}
-
-
-#ifdef CONFIG_FB_LOGO_EXTRA
-
-#define FB_LOGO_EX_NUM_MAX 10
-static struct logo_data_extra {
-	const struct linux_logo *logo;
-	unsigned int n;
-} fb_logo_ex[FB_LOGO_EX_NUM_MAX];
-static unsigned int fb_logo_ex_num;
-
-void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
-{
-	if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
-		return;
-
-	fb_logo_ex[fb_logo_ex_num].logo = logo;
-	fb_logo_ex[fb_logo_ex_num].n = n;
-	fb_logo_ex_num++;
-}
-
-static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
-				  unsigned int yres)
-{
-	unsigned int i;
-
-	/* FIXME: logo_ex supports only truecolor fb. */
-	if (info->fix.visual != FB_VISUAL_TRUECOLOR)
-		fb_logo_ex_num = 0;
-
-	for (i = 0; i < fb_logo_ex_num; i++) {
-		if (fb_logo_ex[i].logo->type != fb_logo.logo->type) {
-			fb_logo_ex[i].logo = NULL;
-			continue;
-		}
-		height += fb_logo_ex[i].logo->height;
-		if (height > yres) {
-			height -= fb_logo_ex[i].logo->height;
-			fb_logo_ex_num = i;
-			break;
-		}
-	}
-	return height;
-}
-
-static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
-{
-	unsigned int i;
-
-	for (i = 0; i < fb_logo_ex_num; i++)
-		y += fb_show_logo_line(info, rotate,
-				       fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
-
-	return y;
-}
-
-#else /* !CONFIG_FB_LOGO_EXTRA */
-
-static inline int fb_prepare_extra_logos(struct fb_info *info,
-					 unsigned int height,
-					 unsigned int yres)
-{
-	return height;
-}
-
-static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
-{
-	return y;
-}
-
-#endif /* CONFIG_FB_LOGO_EXTRA */
-
-
-int fb_prepare_logo(struct fb_info *info, int rotate)
-{
-	int depth = fb_get_color_depth(&info->var, &info->fix);
-	unsigned int yres;
-
-	memset(&fb_logo, 0, sizeof(struct logo_data));
-
-	if (info->flags & FBINFO_MISC_TILEBLITTING ||
-	    info->flags & FBINFO_MODULE)
-		return 0;
-
-	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		depth = info->var.blue.length;
-		if (info->var.red.length < depth)
-			depth = info->var.red.length;
-		if (info->var.green.length < depth)
-			depth = info->var.green.length;
-	}
-
-	if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {
-		/* assume console colormap */
-		depth = 4;
-	}
-
-	/* Return if no suitable logo was found */
-	fb_logo.logo = fb_find_logo(depth);
-
-	if (!fb_logo.logo) {
-		return 0;
-	}
-
-	if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
-		yres = info->var.yres;
-	else
-		yres = info->var.xres;
-
-	if (fb_logo.logo->height > yres) {
-		fb_logo.logo = NULL;
-		return 0;
-	}
-
-	/* What depth we asked for might be different from what we get */
-	if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
-		fb_logo.depth = 8;
-	else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
-		fb_logo.depth = 4;
-	else
-		fb_logo.depth = 1;
-
-
- 	if (fb_logo.depth > 4 && depth > 4) {
- 		switch (info->fix.visual) {
- 		case FB_VISUAL_TRUECOLOR:
- 			fb_logo.needs_truepalette = 1;
- 			break;
- 		case FB_VISUAL_DIRECTCOLOR:
- 			fb_logo.needs_directpalette = 1;
- 			fb_logo.needs_cmapreset = 1;
- 			break;
- 		case FB_VISUAL_PSEUDOCOLOR:
- 			fb_logo.needs_cmapreset = 1;
- 			break;
- 		}
- 	}
-
-	return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
-}
-
-int fb_show_logo(struct fb_info *info, int rotate)
-{
-	int y;
-
-	y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
-			      num_online_cpus());
-	y = fb_show_extra_logos(info, y, rotate);
-
-	return y;
-}
-#else
-int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
-int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
-#endif /* CONFIG_LOGO */
-EXPORT_SYMBOL(fb_show_logo);
-
-static void *fb_seq_start(struct seq_file *m, loff_t *pos)
-{
-	mutex_lock(&registration_lock);
-	return (*pos < FB_MAX) ? pos : NULL;
-}
-
-static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	(*pos)++;
-	return (*pos < FB_MAX) ? pos : NULL;
-}
-
-static void fb_seq_stop(struct seq_file *m, void *v)
-{
-	mutex_unlock(&registration_lock);
-}
-
-static int fb_seq_show(struct seq_file *m, void *v)
-{
-	int i = *(loff_t *)v;
-	struct fb_info *fi = registered_fb[i];
-
-	if (fi)
-		seq_printf(m, "%d %s\n", fi->node, fi->fix.id);
-	return 0;
-}
-
-static const struct seq_operations proc_fb_seq_ops = {
-	.start	= fb_seq_start,
-	.next	= fb_seq_next,
-	.stop	= fb_seq_stop,
-	.show	= fb_seq_show,
-};
-
-static int proc_fb_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &proc_fb_seq_ops);
-}
-
-static const struct file_operations fb_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_fb_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-/*
- * We hold a reference to the fb_info in file->private_data,
- * but if the current registered fb has changed, we don't
- * actually want to use it.
- *
- * So look up the fb_info using the inode minor number,
- * and just verify it against the reference we have.
- */
-static struct fb_info *file_fb_info(struct file *file)
-{
-	struct inode *inode = file_inode(file);
-	int fbidx = iminor(inode);
-	struct fb_info *info = registered_fb[fbidx];
-
-	if (info != file->private_data)
-		info = NULL;
-	return info;
-}
-
-static ssize_t
-fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct fb_info *info = file_fb_info(file);
-	u8 *buffer, *dst;
-	u8 __iomem *src;
-	int c, cnt = 0, err = 0;
-	unsigned long total_size;
-
-	if (!info || ! info->screen_base)
-		return -ENODEV;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	if (info->fbops->fb_read)
-		return info->fbops->fb_read(info, buf, count, ppos);
-	
-	total_size = info->screen_size;
-
-	if (total_size == 0)
-		total_size = info->fix.smem_len;
-
-	if (p >= total_size)
-		return 0;
-
-	if (count >= total_size)
-		count = total_size;
-
-	if (count + p > total_size)
-		count = total_size - p;
-
-	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
-			 GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	src = (u8 __iomem *) (info->screen_base + p);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	while (count) {
-		c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-		dst = buffer;
-		fb_memcpy_fromfb(dst, src, c);
-		dst += c;
-		src += c;
-
-		if (copy_to_user(buf, buffer, c)) {
-			err = -EFAULT;
-			break;
-		}
-		*ppos += c;
-		buf += c;
-		cnt += c;
-		count -= c;
-	}
-
-	kfree(buffer);
-
-	return (err) ? err : cnt;
-}
-
-static ssize_t
-fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct fb_info *info = file_fb_info(file);
-	u8 *buffer, *src;
-	u8 __iomem *dst;
-	int c, cnt = 0, err = 0;
-	unsigned long total_size;
-
-	if (!info || !info->screen_base)
-		return -ENODEV;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	if (info->fbops->fb_write)
-		return info->fbops->fb_write(info, buf, count, ppos);
-	
-	total_size = info->screen_size;
-
-	if (total_size == 0)
-		total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EFBIG;
-
-	if (count > total_size) {
-		err = -EFBIG;
-		count = total_size;
-	}
-
-	if (count + p > total_size) {
-		if (!err)
-			err = -ENOSPC;
-
-		count = total_size - p;
-	}
-
-	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
-			 GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	dst = (u8 __iomem *) (info->screen_base + p);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	while (count) {
-		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
-		src = buffer;
-
-		if (copy_from_user(src, buf, c)) {
-			err = -EFAULT;
-			break;
-		}
-
-		fb_memcpy_tofb(dst, src, c);
-		dst += c;
-		src += c;
-		*ppos += c;
-		buf += c;
-		cnt += c;
-		count -= c;
-	}
-
-	kfree(buffer);
-
-	return (cnt) ? cnt : err;
-}
-
-int
-fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
-{
-	struct fb_fix_screeninfo *fix = &info->fix;
-	unsigned int yres = info->var.yres;
-	int err = 0;
-
-	if (var->yoffset > 0) {
-		if (var->vmode & FB_VMODE_YWRAP) {
-			if (!fix->ywrapstep || (var->yoffset % fix->ywrapstep))
-				err = -EINVAL;
-			else
-				yres = 0;
-		} else if (!fix->ypanstep || (var->yoffset % fix->ypanstep))
-			err = -EINVAL;
-	}
-
-	if (var->xoffset > 0 && (!fix->xpanstep ||
-				 (var->xoffset % fix->xpanstep)))
-		err = -EINVAL;
-
-	if (err || !info->fbops->fb_pan_display ||
-	    var->yoffset > info->var.yres_virtual - yres ||
-	    var->xoffset > info->var.xres_virtual - info->var.xres)
-		return -EINVAL;
-
-	if ((err = info->fbops->fb_pan_display(var, info)))
-		return err;
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-	return 0;
-}
-EXPORT_SYMBOL(fb_pan_display);
-
-static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
-			 u32 activate)
-{
-	struct fb_event event;
-	struct fb_blit_caps caps, fbcaps;
-	int err = 0;
-
-	memset(&caps, 0, sizeof(caps));
-	memset(&fbcaps, 0, sizeof(fbcaps));
-	caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
-	event.info = info;
-	event.data = &caps;
-	fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
-	info->fbops->fb_get_caps(info, &fbcaps, var);
-
-	if (((fbcaps.x ^ caps.x) & caps.x) ||
-	    ((fbcaps.y ^ caps.y) & caps.y) ||
-	    (fbcaps.len < caps.len))
-		err = -EINVAL;
-
-	return err;
-}
-
-int
-fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
-{
-	int flags = info->flags;
-	int ret = 0;
-
-	if (var->activate & FB_ACTIVATE_INV_MODE) {
-		struct fb_videomode mode1, mode2;
-
-		fb_var_to_videomode(&mode1, var);
-		fb_var_to_videomode(&mode2, &info->var);
-		/* make sure we don't delete the videomode of current var */
-		ret = fb_mode_is_equal(&mode1, &mode2);
-
-		if (!ret) {
-		    struct fb_event event;
-
-		    event.info = info;
-		    event.data = &mode1;
-		    ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event);
-		}
-
-		if (!ret)
-		    fb_delete_videomode(&mode1, &info->modelist);
-
-
-		ret = (ret) ? -EINVAL : 0;
-		goto done;
-	}
-
-	if ((var->activate & FB_ACTIVATE_FORCE) ||
-	    memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
-		u32 activate = var->activate;
-
-		/* When using FOURCC mode, make sure the red, green, blue and
-		 * transp fields are set to 0.
-		 */
-		if ((info->fix.capabilities & FB_CAP_FOURCC) &&
-		    var->grayscale > 1) {
-			if (var->red.offset     || var->green.offset    ||
-			    var->blue.offset    || var->transp.offset   ||
-			    var->red.length     || var->green.length    ||
-			    var->blue.length    || var->transp.length   ||
-			    var->red.msb_right  || var->green.msb_right ||
-			    var->blue.msb_right || var->transp.msb_right)
-				return -EINVAL;
-		}
-
-		if (!info->fbops->fb_check_var) {
-			*var = info->var;
-			goto done;
-		}
-
-		ret = info->fbops->fb_check_var(var, info);
-
-		if (ret)
-			goto done;
-
-		if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-			struct fb_var_screeninfo old_var;
-			struct fb_videomode mode;
-
-			if (info->fbops->fb_get_caps) {
-				ret = fb_check_caps(info, var, activate);
-
-				if (ret)
-					goto done;
-			}
-
-			old_var = info->var;
-			info->var = *var;
-
-			if (info->fbops->fb_set_par) {
-				ret = info->fbops->fb_set_par(info);
-
-				if (ret) {
-					info->var = old_var;
-					printk(KERN_WARNING "detected "
-						"fb_set_par error, "
-						"error code: %d\n", ret);
-					goto done;
-				}
-			}
-
-			fb_pan_display(info, &info->var);
-			fb_set_cmap(&info->cmap, info);
-			fb_var_to_videomode(&mode, &info->var);
-
-			if (info->modelist.prev && info->modelist.next &&
-			    !list_empty(&info->modelist))
-				ret = fb_add_videomode(&mode, &info->modelist);
-
-			if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
-				struct fb_event event;
-				int evnt = (activate & FB_ACTIVATE_ALL) ?
-					FB_EVENT_MODE_CHANGE_ALL :
-					FB_EVENT_MODE_CHANGE;
-
-				info->flags &= ~FBINFO_MISC_USEREVENT;
-				event.info = info;
-				event.data = &mode;
-				fb_notifier_call_chain(evnt, &event);
-			}
-		}
-	}
-
- done:
-	return ret;
-}
-EXPORT_SYMBOL(fb_set_var);
-
-int
-fb_blank(struct fb_info *info, int blank)
-{	
-	struct fb_event event;
-	int ret = -EINVAL, early_ret;
-
- 	if (blank > FB_BLANK_POWERDOWN)
- 		blank = FB_BLANK_POWERDOWN;
-
-	event.info = info;
-	event.data = &blank;
-
-	early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
-
-	if (info->fbops->fb_blank)
- 		ret = info->fbops->fb_blank(blank, info);
-
-	if (!ret)
-		fb_notifier_call_chain(FB_EVENT_BLANK, &event);
-	else {
-		/*
-		 * if fb_blank is failed then revert effects of
-		 * the early blank event.
-		 */
-		if (!early_ret)
-			fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
-	}
-
- 	return ret;
-}
-EXPORT_SYMBOL(fb_blank);
-
-static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
-			unsigned long arg)
-{
-	struct fb_ops *fb;
-	struct fb_var_screeninfo var;
-	struct fb_fix_screeninfo fix;
-	struct fb_con2fbmap con2fb;
-	struct fb_cmap cmap_from;
-	struct fb_cmap_user cmap;
-	struct fb_event event;
-	void __user *argp = (void __user *)arg;
-	long ret = 0;
-
-	switch (cmd) {
-	case FBIOGET_VSCREENINFO:
-		if (!lock_fb_info(info))
-			return -ENODEV;
-		var = info->var;
-		unlock_fb_info(info);
-
-		ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
-		break;
-	case FBIOPUT_VSCREENINFO:
-		if (copy_from_user(&var, argp, sizeof(var)))
-			return -EFAULT;
-		console_lock();
-		if (!lock_fb_info(info)) {
-			console_unlock();
-			return -ENODEV;
-		}
-		info->flags |= FBINFO_MISC_USEREVENT;
-		ret = fb_set_var(info, &var);
-		info->flags &= ~FBINFO_MISC_USEREVENT;
-		unlock_fb_info(info);
-		console_unlock();
-		if (!ret && copy_to_user(argp, &var, sizeof(var)))
-			ret = -EFAULT;
-		break;
-	case FBIOGET_FSCREENINFO:
-		if (!lock_fb_info(info))
-			return -ENODEV;
-		fix = info->fix;
-		unlock_fb_info(info);
-
-		ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
-		break;
-	case FBIOPUTCMAP:
-		if (copy_from_user(&cmap, argp, sizeof(cmap)))
-			return -EFAULT;
-		ret = fb_set_user_cmap(&cmap, info);
-		break;
-	case FBIOGETCMAP:
-		if (copy_from_user(&cmap, argp, sizeof(cmap)))
-			return -EFAULT;
-		if (!lock_fb_info(info))
-			return -ENODEV;
-		cmap_from = info->cmap;
-		unlock_fb_info(info);
-		ret = fb_cmap_to_user(&cmap_from, &cmap);
-		break;
-	case FBIOPAN_DISPLAY:
-		if (copy_from_user(&var, argp, sizeof(var)))
-			return -EFAULT;
-		console_lock();
-		if (!lock_fb_info(info)) {
-			console_unlock();
-			return -ENODEV;
-		}
-		ret = fb_pan_display(info, &var);
-		unlock_fb_info(info);
-		console_unlock();
-		if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
-			return -EFAULT;
-		break;
-	case FBIO_CURSOR:
-		ret = -EINVAL;
-		break;
-	case FBIOGET_CON2FBMAP:
-		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
-			return -EFAULT;
-		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
-			return -EINVAL;
-		con2fb.framebuffer = -1;
-		event.data = &con2fb;
-		if (!lock_fb_info(info))
-			return -ENODEV;
-		event.info = info;
-		fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
-		unlock_fb_info(info);
-		ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
-		break;
-	case FBIOPUT_CON2FBMAP:
-		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
-			return -EFAULT;
-		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
-			return -EINVAL;
-		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
-			return -EINVAL;
-		if (!registered_fb[con2fb.framebuffer])
-			request_module("fb%d", con2fb.framebuffer);
-		if (!registered_fb[con2fb.framebuffer]) {
-			ret = -EINVAL;
-			break;
-		}
-		event.data = &con2fb;
-		console_lock();
-		if (!lock_fb_info(info)) {
-			console_unlock();
-			return -ENODEV;
-		}
-		event.info = info;
-		ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
-		unlock_fb_info(info);
-		console_unlock();
-		break;
-	case FBIOBLANK:
-		console_lock();
-		if (!lock_fb_info(info)) {
-			console_unlock();
-			return -ENODEV;
-		}
-		info->flags |= FBINFO_MISC_USEREVENT;
-		ret = fb_blank(info, arg);
-		info->flags &= ~FBINFO_MISC_USEREVENT;
-		unlock_fb_info(info);
-		console_unlock();
-		break;
-	default:
-		if (!lock_fb_info(info))
-			return -ENODEV;
-		fb = info->fbops;
-		if (fb->fb_ioctl)
-			ret = fb->fb_ioctl(info, cmd, arg);
-		else
-			ret = -ENOTTY;
-		unlock_fb_info(info);
-	}
-	return ret;
-}
-
-static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct fb_info *info = file_fb_info(file);
-
-	if (!info)
-		return -ENODEV;
-	return do_fb_ioctl(info, cmd, arg);
-}
-
-#ifdef CONFIG_COMPAT
-struct fb_fix_screeninfo32 {
-	char			id[16];
-	compat_caddr_t		smem_start;
-	u32			smem_len;
-	u32			type;
-	u32			type_aux;
-	u32			visual;
-	u16			xpanstep;
-	u16			ypanstep;
-	u16			ywrapstep;
-	u32			line_length;
-	compat_caddr_t		mmio_start;
-	u32			mmio_len;
-	u32			accel;
-	u16			reserved[3];
-};
-
-struct fb_cmap32 {
-	u32			start;
-	u32			len;
-	compat_caddr_t	red;
-	compat_caddr_t	green;
-	compat_caddr_t	blue;
-	compat_caddr_t	transp;
-};
-
-static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
-			  unsigned long arg)
-{
-	struct fb_cmap_user __user *cmap;
-	struct fb_cmap32 __user *cmap32;
-	__u32 data;
-	int err;
-
-	cmap = compat_alloc_user_space(sizeof(*cmap));
-	cmap32 = compat_ptr(arg);
-
-	if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
-		return -EFAULT;
-
-	if (get_user(data, &cmap32->red) ||
-	    put_user(compat_ptr(data), &cmap->red) ||
-	    get_user(data, &cmap32->green) ||
-	    put_user(compat_ptr(data), &cmap->green) ||
-	    get_user(data, &cmap32->blue) ||
-	    put_user(compat_ptr(data), &cmap->blue) ||
-	    get_user(data, &cmap32->transp) ||
-	    put_user(compat_ptr(data), &cmap->transp))
-		return -EFAULT;
-
-	err = do_fb_ioctl(info, cmd, (unsigned long) cmap);
-
-	if (!err) {
-		if (copy_in_user(&cmap32->start,
-				 &cmap->start,
-				 2 * sizeof(__u32)))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
-				  struct fb_fix_screeninfo32 __user *fix32)
-{
-	__u32 data;
-	int err;
-
-	err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
-
-	data = (__u32) (unsigned long) fix->smem_start;
-	err |= put_user(data, &fix32->smem_start);
-
-	err |= put_user(fix->smem_len, &fix32->smem_len);
-	err |= put_user(fix->type, &fix32->type);
-	err |= put_user(fix->type_aux, &fix32->type_aux);
-	err |= put_user(fix->visual, &fix32->visual);
-	err |= put_user(fix->xpanstep, &fix32->xpanstep);
-	err |= put_user(fix->ypanstep, &fix32->ypanstep);
-	err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
-	err |= put_user(fix->line_length, &fix32->line_length);
-
-	data = (__u32) (unsigned long) fix->mmio_start;
-	err |= put_user(data, &fix32->mmio_start);
-
-	err |= put_user(fix->mmio_len, &fix32->mmio_len);
-	err |= put_user(fix->accel, &fix32->accel);
-	err |= copy_to_user(fix32->reserved, fix->reserved,
-			    sizeof(fix->reserved));
-
-	if (err)
-		return -EFAULT;
-	return 0;
-}
-
-static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
-			      unsigned long arg)
-{
-	mm_segment_t old_fs;
-	struct fb_fix_screeninfo fix;
-	struct fb_fix_screeninfo32 __user *fix32;
-	int err;
-
-	fix32 = compat_ptr(arg);
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = do_fb_ioctl(info, cmd, (unsigned long) &fix);
-	set_fs(old_fs);
-
-	if (!err)
-		err = do_fscreeninfo_to_user(&fix, fix32);
-
-	return err;
-}
-
-static long fb_compat_ioctl(struct file *file, unsigned int cmd,
-			    unsigned long arg)
-{
-	struct fb_info *info = file_fb_info(file);
-	struct fb_ops *fb;
-	long ret = -ENOIOCTLCMD;
-
-	if (!info)
-		return -ENODEV;
-	fb = info->fbops;
-	switch(cmd) {
-	case FBIOGET_VSCREENINFO:
-	case FBIOPUT_VSCREENINFO:
-	case FBIOPAN_DISPLAY:
-	case FBIOGET_CON2FBMAP:
-	case FBIOPUT_CON2FBMAP:
-		arg = (unsigned long) compat_ptr(arg);
-	case FBIOBLANK:
-		ret = do_fb_ioctl(info, cmd, arg);
-		break;
-
-	case FBIOGET_FSCREENINFO:
-		ret = fb_get_fscreeninfo(info, cmd, arg);
-		break;
-
-	case FBIOGETCMAP:
-	case FBIOPUTCMAP:
-		ret = fb_getput_cmap(info, cmd, arg);
-		break;
-
-	default:
-		if (fb->fb_compat_ioctl)
-			ret = fb->fb_compat_ioctl(info, cmd, arg);
-		break;
-	}
-	return ret;
-}
-#endif
-
-static int
-fb_mmap(struct file *file, struct vm_area_struct * vma)
-{
-	struct fb_info *info = file_fb_info(file);
-	struct fb_ops *fb;
-	unsigned long mmio_pgoff;
-	unsigned long start;
-	u32 len;
-
-	if (!info)
-		return -ENODEV;
-	fb = info->fbops;
-	if (!fb)
-		return -ENODEV;
-	mutex_lock(&info->mm_lock);
-	if (fb->fb_mmap) {
-		int res;
-		res = fb->fb_mmap(info, vma);
-		mutex_unlock(&info->mm_lock);
-		return res;
-	}
-
-	/*
-	 * Ugh. This can be either the frame buffer mapping, or
-	 * if pgoff points past it, the mmio mapping.
-	 */
-	start = info->fix.smem_start;
-	len = info->fix.smem_len;
-	mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
-	if (vma->vm_pgoff >= mmio_pgoff) {
-		if (info->var.accel_flags) {
-			mutex_unlock(&info->mm_lock);
-			return -EINVAL;
-		}
-
-		vma->vm_pgoff -= mmio_pgoff;
-		start = info->fix.mmio_start;
-		len = info->fix.mmio_len;
-	}
-	mutex_unlock(&info->mm_lock);
-
-	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-	fb_pgprotect(file, vma, start);
-
-	return vm_iomap_memory(vma, start, len);
-}
-
-static int
-fb_open(struct inode *inode, struct file *file)
-__acquires(&info->lock)
-__releases(&info->lock)
-{
-	int fbidx = iminor(inode);
-	struct fb_info *info;
-	int res = 0;
-
-	info = get_fb_info(fbidx);
-	if (!info) {
-		request_module("fb%d", fbidx);
-		info = get_fb_info(fbidx);
-		if (!info)
-			return -ENODEV;
-	}
-	if (IS_ERR(info))
-		return PTR_ERR(info);
-
-	mutex_lock(&info->lock);
-	if (!try_module_get(info->fbops->owner)) {
-		res = -ENODEV;
-		goto out;
-	}
-	file->private_data = info;
-	if (info->fbops->fb_open) {
-		res = info->fbops->fb_open(info,1);
-		if (res)
-			module_put(info->fbops->owner);
-	}
-#ifdef CONFIG_FB_DEFERRED_IO
-	if (info->fbdefio)
-		fb_deferred_io_open(info, inode, file);
-#endif
-out:
-	mutex_unlock(&info->lock);
-	if (res)
-		put_fb_info(info);
-	return res;
-}
-
-static int 
-fb_release(struct inode *inode, struct file *file)
-__acquires(&info->lock)
-__releases(&info->lock)
-{
-	struct fb_info * const info = file->private_data;
-
-	mutex_lock(&info->lock);
-	if (info->fbops->fb_release)
-		info->fbops->fb_release(info,1);
-	module_put(info->fbops->owner);
-	mutex_unlock(&info->lock);
-	put_fb_info(info);
-	return 0;
-}
-
-static const struct file_operations fb_fops = {
-	.owner =	THIS_MODULE,
-	.read =		fb_read,
-	.write =	fb_write,
-	.unlocked_ioctl = fb_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl = fb_compat_ioctl,
-#endif
-	.mmap =		fb_mmap,
-	.open =		fb_open,
-	.release =	fb_release,
-#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
-	.get_unmapped_area = get_fb_unmapped_area,
-#endif
-#ifdef CONFIG_FB_DEFERRED_IO
-	.fsync =	fb_deferred_io_fsync,
-#endif
-	.llseek =	default_llseek,
-};
-
-struct class *fb_class;
-EXPORT_SYMBOL(fb_class);
-
-static int fb_check_foreignness(struct fb_info *fi)
-{
-	const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
-
-	fi->flags &= ~FBINFO_FOREIGN_ENDIAN;
-
-#ifdef __BIG_ENDIAN
-	fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH;
-#else
-	fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0;
-#endif /* __BIG_ENDIAN */
-
-	if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) {
-		pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to "
-		       "support this framebuffer\n", fi->fix.id);
-		return -ENOSYS;
-	} else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) {
-		pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to "
-		       "support this framebuffer\n", fi->fix.id);
-		return -ENOSYS;
-	}
-
-	return 0;
-}
-
-static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
-{
-	/* is the generic aperture base the same as the HW one */
-	if (gen->base == hw->base)
-		return true;
-	/* is the generic aperture base inside the hw base->hw base+size */
-	if (gen->base > hw->base && gen->base < hw->base + hw->size)
-		return true;
-	return false;
-}
-
-static bool fb_do_apertures_overlap(struct apertures_struct *gena,
-				    struct apertures_struct *hwa)
-{
-	int i, j;
-	if (!hwa || !gena)
-		return false;
-
-	for (i = 0; i < hwa->count; ++i) {
-		struct aperture *h = &hwa->ranges[i];
-		for (j = 0; j < gena->count; ++j) {
-			struct aperture *g = &gena->ranges[j];
-			printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
-				(unsigned long long)g->base,
-				(unsigned long long)g->size,
-				(unsigned long long)h->base,
-				(unsigned long long)h->size);
-			if (apertures_overlap(g, h))
-				return true;
-		}
-	}
-
-	return false;
-}
-
-static int do_unregister_framebuffer(struct fb_info *fb_info);
-
-#define VGA_FB_PHYS 0xA0000
-static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
-					      const char *name, bool primary)
-{
-	int i, ret;
-
-	/* check all firmware fbs and kick off if the base addr overlaps */
-	for (i = 0 ; i < FB_MAX; i++) {
-		struct apertures_struct *gen_aper;
-		if (!registered_fb[i])
-			continue;
-
-		if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
-			continue;
-
-		gen_aper = registered_fb[i]->apertures;
-		if (fb_do_apertures_overlap(gen_aper, a) ||
-			(primary && gen_aper && gen_aper->count &&
-			 gen_aper->ranges[0].base == VGA_FB_PHYS)) {
-
-			printk(KERN_INFO "fb: switching to %s from %s\n",
-			       name, registered_fb[i]->fix.id);
-			ret = do_unregister_framebuffer(registered_fb[i]);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
-static int do_register_framebuffer(struct fb_info *fb_info)
-{
-	int i, ret;
-	struct fb_event event;
-	struct fb_videomode mode;
-
-	if (fb_check_foreignness(fb_info))
-		return -ENOSYS;
-
-	ret = do_remove_conflicting_framebuffers(fb_info->apertures,
-						 fb_info->fix.id,
-						 fb_is_primary_device(fb_info));
-	if (ret)
-		return ret;
-
-	if (num_registered_fb == FB_MAX)
-		return -ENXIO;
-
-	num_registered_fb++;
-	for (i = 0 ; i < FB_MAX; i++)
-		if (!registered_fb[i])
-			break;
-	fb_info->node = i;
-	atomic_set(&fb_info->count, 1);
-	mutex_init(&fb_info->lock);
-	mutex_init(&fb_info->mm_lock);
-
-	fb_info->dev = device_create(fb_class, fb_info->device,
-				     MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
-	if (IS_ERR(fb_info->dev)) {
-		/* Not fatal */
-		printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
-		fb_info->dev = NULL;
-	} else
-		fb_init_device(fb_info);
-
-	if (fb_info->pixmap.addr == NULL) {
-		fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
-		if (fb_info->pixmap.addr) {
-			fb_info->pixmap.size = FBPIXMAPSIZE;
-			fb_info->pixmap.buf_align = 1;
-			fb_info->pixmap.scan_align = 1;
-			fb_info->pixmap.access_align = 32;
-			fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
-		}
-	}	
-	fb_info->pixmap.offset = 0;
-
-	if (!fb_info->pixmap.blit_x)
-		fb_info->pixmap.blit_x = ~(u32)0;
-
-	if (!fb_info->pixmap.blit_y)
-		fb_info->pixmap.blit_y = ~(u32)0;
-
-	if (!fb_info->modelist.prev || !fb_info->modelist.next)
-		INIT_LIST_HEAD(&fb_info->modelist);
-
-	if (fb_info->skip_vt_switch)
-		pm_vt_switch_required(fb_info->dev, false);
-	else
-		pm_vt_switch_required(fb_info->dev, true);
-
-	fb_var_to_videomode(&mode, &fb_info->var);
-	fb_add_videomode(&mode, &fb_info->modelist);
-	registered_fb[i] = fb_info;
-
-	event.info = fb_info;
-	console_lock();
-	if (!lock_fb_info(fb_info)) {
-		console_unlock();
-		return -ENODEV;
-	}
-
-	fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
-	unlock_fb_info(fb_info);
-	console_unlock();
-	return 0;
-}
-
-static int do_unregister_framebuffer(struct fb_info *fb_info)
-{
-	struct fb_event event;
-	int i, ret = 0;
-
-	i = fb_info->node;
-	if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
-		return -EINVAL;
-
-	console_lock();
-	if (!lock_fb_info(fb_info)) {
-		console_unlock();
-		return -ENODEV;
-	}
-
-	event.info = fb_info;
-	ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
-	unlock_fb_info(fb_info);
-	console_unlock();
-
-	if (ret)
-		return -EINVAL;
-
-	pm_vt_switch_unregister(fb_info->dev);
-
-	unlink_framebuffer(fb_info);
-	if (fb_info->pixmap.addr &&
-	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
-		kfree(fb_info->pixmap.addr);
-	fb_destroy_modelist(&fb_info->modelist);
-	registered_fb[i] = NULL;
-	num_registered_fb--;
-	fb_cleanup_device(fb_info);
-	event.info = fb_info;
-	console_lock();
-	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
-	console_unlock();
-
-	/* this may free fb info */
-	put_fb_info(fb_info);
-	return 0;
-}
-
-int unlink_framebuffer(struct fb_info *fb_info)
-{
-	int i;
-
-	i = fb_info->node;
-	if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
-		return -EINVAL;
-
-	if (fb_info->dev) {
-		device_destroy(fb_class, MKDEV(FB_MAJOR, i));
-		fb_info->dev = NULL;
-	}
-	return 0;
-}
-EXPORT_SYMBOL(unlink_framebuffer);
-
-int remove_conflicting_framebuffers(struct apertures_struct *a,
-				    const char *name, bool primary)
-{
-	int ret;
-
-	mutex_lock(&registration_lock);
-	ret = do_remove_conflicting_framebuffers(a, name, primary);
-	mutex_unlock(&registration_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(remove_conflicting_framebuffers);
-
-/**
- *	register_framebuffer - registers a frame buffer device
- *	@fb_info: frame buffer info structure
- *
- *	Registers a frame buffer device @fb_info.
- *
- *	Returns negative errno on error, or zero for success.
- *
- */
-int
-register_framebuffer(struct fb_info *fb_info)
-{
-	int ret;
-
-	mutex_lock(&registration_lock);
-	ret = do_register_framebuffer(fb_info);
-	mutex_unlock(&registration_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(register_framebuffer);
-
-/**
- *	unregister_framebuffer - releases a frame buffer device
- *	@fb_info: frame buffer info structure
- *
- *	Unregisters a frame buffer device @fb_info.
- *
- *	Returns negative errno on error, or zero for success.
- *
- *      This function will also notify the framebuffer console
- *      to release the driver.
- *
- *      This is meant to be called within a driver's module_exit()
- *      function. If this is called outside module_exit(), ensure
- *      that the driver implements fb_open() and fb_release() to
- *      check that no processes are using the device.
- */
-int
-unregister_framebuffer(struct fb_info *fb_info)
-{
-	int ret;
-
-	mutex_lock(&registration_lock);
-	ret = do_unregister_framebuffer(fb_info);
-	mutex_unlock(&registration_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(unregister_framebuffer);
-
-/**
- *	fb_set_suspend - low level driver signals suspend
- *	@info: framebuffer affected
- *	@state: 0 = resuming, !=0 = suspending
- *
- *	This is meant to be used by low level drivers to
- * 	signal suspend/resume to the core & clients.
- *	It must be called with the console semaphore held
- */
-void fb_set_suspend(struct fb_info *info, int state)
-{
-	struct fb_event event;
-
-	event.info = info;
-	if (state) {
-		fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
-		info->state = FBINFO_STATE_SUSPENDED;
-	} else {
-		info->state = FBINFO_STATE_RUNNING;
-		fb_notifier_call_chain(FB_EVENT_RESUME, &event);
-	}
-}
-EXPORT_SYMBOL(fb_set_suspend);
-
-/**
- *	fbmem_init - init frame buffer subsystem
- *
- *	Initialize the frame buffer subsystem.
- *
- *	NOTE: This function is _only_ to be called by drivers/char/mem.c.
- *
- */
-
-static int __init
-fbmem_init(void)
-{
-	proc_create("fb", 0, NULL, &fb_proc_fops);
-
-	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
-		printk("unable to get major %d for fb devs\n", FB_MAJOR);
-
-	fb_class = class_create(THIS_MODULE, "graphics");
-	if (IS_ERR(fb_class)) {
-		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
-		fb_class = NULL;
-	}
-	return 0;
-}
-
-#ifdef MODULE
-module_init(fbmem_init);
-static void __exit
-fbmem_exit(void)
-{
-	remove_proc_entry("fb", NULL);
-	class_destroy(fb_class);
-	unregister_chrdev(FB_MAJOR, "fb");
-}
-
-module_exit(fbmem_exit);
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Framebuffer base");
-#else
-subsys_initcall(fbmem_init);
-#endif
-
-int fb_new_modelist(struct fb_info *info)
-{
-	struct fb_event event;
-	struct fb_var_screeninfo var = info->var;
-	struct list_head *pos, *n;
-	struct fb_modelist *modelist;
-	struct fb_videomode *m, mode;
-	int err = 1;
-
-	list_for_each_safe(pos, n, &info->modelist) {
-		modelist = list_entry(pos, struct fb_modelist, list);
-		m = &modelist->mode;
-		fb_videomode_to_var(&var, m);
-		var.activate = FB_ACTIVATE_TEST;
-		err = fb_set_var(info, &var);
-		fb_var_to_videomode(&mode, &var);
-		if (err || !fb_mode_is_equal(m, &mode)) {
-			list_del(pos);
-			kfree(pos);
-		}
-	}
-
-	err = 1;
-
-	if (!list_empty(&info->modelist)) {
-		event.info = info;
-		err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
-	}
-
-	return err;
-}
-
-static char *video_options[FB_MAX] __read_mostly;
-static int ofonly __read_mostly;
-
-/**
- * fb_get_options - get kernel boot parameters
- * @name:   framebuffer name as it would appear in
- *          the boot parameter line
- *          (video=<name>:<options>)
- * @option: the option will be stored here
- *
- * NOTE: Needed to maintain backwards compatibility
- */
-int fb_get_options(const char *name, char **option)
-{
-	char *opt, *options = NULL;
-	int retval = 0;
-	int name_len = strlen(name), i;
-
-	if (name_len && ofonly && strncmp(name, "offb", 4))
-		retval = 1;
-
-	if (name_len && !retval) {
-		for (i = 0; i < FB_MAX; i++) {
-			if (video_options[i] == NULL)
-				continue;
-			if (!video_options[i][0])
-				continue;
-			opt = video_options[i];
-			if (!strncmp(name, opt, name_len) &&
-			    opt[name_len] == ':')
-				options = opt + name_len + 1;
-		}
-	}
-	/* No match, pass global option */
-	if (!options && option && fb_mode_option)
-		options = kstrdup(fb_mode_option, GFP_KERNEL);
-	if (options && !strncmp(options, "off", 3))
-		retval = 1;
-
-	if (option)
-		*option = options;
-
-	return retval;
-}
-EXPORT_SYMBOL(fb_get_options);
-
-#ifndef MODULE
-/**
- *	video_setup - process command line options
- *	@options: string of options
- *
- *	Process command line options for frame buffer subsystem.
- *
- *	NOTE: This function is a __setup and __init function.
- *            It only stores the options.  Drivers have to call
- *            fb_get_options() as necessary.
- *
- *	Returns zero.
- *
- */
-static int __init video_setup(char *options)
-{
-	int i, global = 0;
-
-	if (!options || !*options)
- 		global = 1;
-
- 	if (!global && !strncmp(options, "ofonly", 6)) {
- 		ofonly = 1;
- 		global = 1;
- 	}
-
- 	if (!global && !strchr(options, ':')) {
- 		fb_mode_option = options;
- 		global = 1;
- 	}
-
- 	if (!global) {
- 		for (i = 0; i < FB_MAX; i++) {
- 			if (video_options[i] == NULL) {
- 				video_options[i] = options;
- 				break;
- 			}
-
-		}
-	}
-
-	return 1;
-}
-__setup("video=", video_setup);
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
deleted file mode 100644
index 6103fa6fb54f..000000000000
--- a/drivers/video/fbmon.c
+++ /dev/null
@@ -1,1592 +0,0 @@
-/*
- * linux/drivers/video/fbmon.c
- *
- * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
- *
- * Credits:
- *
- * The EDID Parser is a conglomeration from the following sources:
- *
- *   1. SciTech SNAP Graphics Architecture
- *      Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
- *
- *   2. XFree86 4.3.0, interpret_edid.c
- *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
- *
- *   3. John Fremlin <vii@users.sourceforge.net> and
- *      Ani Joshi <ajoshi@unixbox.com>
- *
- * Generalized Timing Formula is derived from:
- *
- *      GTF Spreadsheet by Andy Morrish (1/5/97)
- *      available at http://www.vesa.org
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-#include <linux/fb.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <video/edid.h>
-#include <video/of_videomode.h>
-#include <video/videomode.h>
-#ifdef CONFIG_PPC_OF
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif
-#include "edid.h"
-
-/*
- * EDID parser
- */
-
-#undef DEBUG  /* define this for verbose EDID parsing output */
-
-#ifdef DEBUG
-#define DPRINTK(fmt, args...) printk(fmt,## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#define FBMON_FIX_HEADER  1
-#define FBMON_FIX_INPUT   2
-#define FBMON_FIX_TIMINGS 3
-
-#ifdef CONFIG_FB_MODE_HELPERS
-struct broken_edid {
-	u8  manufacturer[4];
-	u32 model;
-	u32 fix;
-};
-
-static const struct broken_edid brokendb[] = {
-	/* DEC FR-PCXAV-YZ */
-	{
-		.manufacturer = "DEC",
-		.model        = 0x073a,
-		.fix          = FBMON_FIX_HEADER,
-	},
-	/* ViewSonic PF775a */
-	{
-		.manufacturer = "VSC",
-		.model        = 0x5a44,
-		.fix          = FBMON_FIX_INPUT,
-	},
-	/* Sharp UXGA? */
-	{
-		.manufacturer = "SHP",
-		.model        = 0x138e,
-		.fix          = FBMON_FIX_TIMINGS,
-	},
-};
-
-static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0x00
-};
-
-static void copy_string(unsigned char *c, unsigned char *s)
-{
-  int i;
-  c = c + 5;
-  for (i = 0; (i < 13 && *c != 0x0A); i++)
-    *(s++) = *(c++);
-  *s = 0;
-  while (i-- && (*--s == 0x20)) *s = 0;
-}
-
-static int edid_is_serial_block(unsigned char *block)
-{
-	if ((block[0] == 0x00) && (block[1] == 0x00) &&
-	    (block[2] == 0x00) && (block[3] == 0xff) &&
-	    (block[4] == 0x00))
-		return 1;
-	else
-		return 0;
-}
-
-static int edid_is_ascii_block(unsigned char *block)
-{
-	if ((block[0] == 0x00) && (block[1] == 0x00) &&
-	    (block[2] == 0x00) && (block[3] == 0xfe) &&
-	    (block[4] == 0x00))
-		return 1;
-	else
-		return 0;
-}
-
-static int edid_is_limits_block(unsigned char *block)
-{
-	if ((block[0] == 0x00) && (block[1] == 0x00) &&
-	    (block[2] == 0x00) && (block[3] == 0xfd) &&
-	    (block[4] == 0x00))
-		return 1;
-	else
-		return 0;
-}
-
-static int edid_is_monitor_block(unsigned char *block)
-{
-	if ((block[0] == 0x00) && (block[1] == 0x00) &&
-	    (block[2] == 0x00) && (block[3] == 0xfc) &&
-	    (block[4] == 0x00))
-		return 1;
-	else
-		return 0;
-}
-
-static int edid_is_timing_block(unsigned char *block)
-{
-	if ((block[0] != 0x00) || (block[1] != 0x00) ||
-	    (block[2] != 0x00) || (block[4] != 0x00))
-		return 1;
-	else
-		return 0;
-}
-
-static int check_edid(unsigned char *edid)
-{
-	unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
-	unsigned char *b;
-	u32 model;
-	int i, fix = 0, ret = 0;
-
-	manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
-	manufacturer[1] = ((block[0] & 0x03) << 3) +
-		((block[1] & 0xe0) >> 5) + '@';
-	manufacturer[2] = (block[1] & 0x1f) + '@';
-	manufacturer[3] = 0;
-	model = block[2] + (block[3] << 8);
-
-	for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
-		if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
-			brokendb[i].model == model) {
-			fix = brokendb[i].fix;
-			break;
-		}
-	}
-
-	switch (fix) {
-	case FBMON_FIX_HEADER:
-		for (i = 0; i < 8; i++) {
-			if (edid[i] != edid_v1_header[i]) {
-				ret = fix;
-				break;
-			}
-		}
-		break;
-	case FBMON_FIX_INPUT:
-		b = edid + EDID_STRUCT_DISPLAY;
-		/* Only if display is GTF capable will
-		   the input type be reset to analog */
-		if (b[4] & 0x01 && b[0] & 0x80)
-			ret = fix;
-		break;
-	case FBMON_FIX_TIMINGS:
-		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
-		ret = fix;
-
-		for (i = 0; i < 4; i++) {
-			if (edid_is_limits_block(b)) {
-				ret = 0;
-				break;
-			}
-
-			b += DETAILED_TIMING_DESCRIPTION_SIZE;
-		}
-
-		break;
-	}
-
-	if (ret)
-		printk("fbmon: The EDID Block of "
-		       "Manufacturer: %s Model: 0x%x is known to "
-		       "be broken,\n",  manufacturer, model);
-
-	return ret;
-}
-
-static void fix_edid(unsigned char *edid, int fix)
-{
-	int i;
-	unsigned char *b, csum = 0;
-
-	switch (fix) {
-	case FBMON_FIX_HEADER:
-		printk("fbmon: trying a header reconstruct\n");
-		memcpy(edid, edid_v1_header, 8);
-		break;
-	case FBMON_FIX_INPUT:
-		printk("fbmon: trying to fix input type\n");
-		b = edid + EDID_STRUCT_DISPLAY;
-		b[0] &= ~0x80;
-		edid[127] += 0x80;
-		break;
-	case FBMON_FIX_TIMINGS:
-		printk("fbmon: trying to fix monitor timings\n");
-		b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
-		for (i = 0; i < 4; i++) {
-			if (!(edid_is_serial_block(b) ||
-			      edid_is_ascii_block(b) ||
-			      edid_is_monitor_block(b) ||
-			      edid_is_timing_block(b))) {
-				b[0] = 0x00;
-				b[1] = 0x00;
-				b[2] = 0x00;
-				b[3] = 0xfd;
-				b[4] = 0x00;
-				b[5] = 60;   /* vfmin */
-				b[6] = 60;   /* vfmax */
-				b[7] = 30;   /* hfmin */
-				b[8] = 75;   /* hfmax */
-				b[9] = 17;   /* pixclock - 170 MHz*/
-				b[10] = 0;   /* GTF */
-				break;
-			}
-
-			b += DETAILED_TIMING_DESCRIPTION_SIZE;
-		}
-
-		for (i = 0; i < EDID_LENGTH - 1; i++)
-			csum += edid[i];
-
-		edid[127] = 256 - csum;
-		break;
-	}
-}
-
-static int edid_checksum(unsigned char *edid)
-{
-	unsigned char csum = 0, all_null = 0;
-	int i, err = 0, fix = check_edid(edid);
-
-	if (fix)
-		fix_edid(edid, fix);
-
-	for (i = 0; i < EDID_LENGTH; i++) {
-		csum += edid[i];
-		all_null |= edid[i];
-	}
-
-	if (csum == 0x00 && all_null) {
-		/* checksum passed, everything's good */
-		err = 1;
-	}
-
-	return err;
-}
-
-static int edid_check_header(unsigned char *edid)
-{
-	int i, err = 1, fix = check_edid(edid);
-
-	if (fix)
-		fix_edid(edid, fix);
-
-	for (i = 0; i < 8; i++) {
-		if (edid[i] != edid_v1_header[i])
-			err = 0;
-	}
-
-	return err;
-}
-
-static void parse_vendor_block(unsigned char *block, struct fb_monspecs *specs)
-{
-	specs->manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
-	specs->manufacturer[1] = ((block[0] & 0x03) << 3) +
-		((block[1] & 0xe0) >> 5) + '@';
-	specs->manufacturer[2] = (block[1] & 0x1f) + '@';
-	specs->manufacturer[3] = 0;
-	specs->model = block[2] + (block[3] << 8);
-	specs->serial = block[4] + (block[5] << 8) +
-	       (block[6] << 16) + (block[7] << 24);
-	specs->year = block[9] + 1990;
-	specs->week = block[8];
-	DPRINTK("   Manufacturer: %s\n", specs->manufacturer);
-	DPRINTK("   Model: %x\n", specs->model);
-	DPRINTK("   Serial#: %u\n", specs->serial);
-	DPRINTK("   Year: %u Week %u\n", specs->year, specs->week);
-}
-
-static void get_dpms_capabilities(unsigned char flags,
-				  struct fb_monspecs *specs)
-{
-	specs->dpms = 0;
-	if (flags & DPMS_ACTIVE_OFF)
-		specs->dpms |= FB_DPMS_ACTIVE_OFF;
-	if (flags & DPMS_SUSPEND)
-		specs->dpms |= FB_DPMS_SUSPEND;
-	if (flags & DPMS_STANDBY)
-		specs->dpms |= FB_DPMS_STANDBY;
-	DPRINTK("      DPMS: Active %s, Suspend %s, Standby %s\n",
-	       (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
-	       (flags & DPMS_SUSPEND)    ? "yes" : "no",
-	       (flags & DPMS_STANDBY)    ? "yes" : "no");
-}
-
-static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
-{
-	int tmp;
-
-	DPRINTK("      Chroma\n");
-	/* Chromaticity data */
-	tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.redx = tmp/1024;
-	DPRINTK("         RedX:     0.%03d ", specs->chroma.redx);
-
-	tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.redy = tmp/1024;
-	DPRINTK("RedY:     0.%03d\n", specs->chroma.redy);
-
-	tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.greenx = tmp/1024;
-	DPRINTK("         GreenX:   0.%03d ", specs->chroma.greenx);
-
-	tmp = (block[5] & 3) | (block[0xa] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.greeny = tmp/1024;
-	DPRINTK("GreenY:   0.%03d\n", specs->chroma.greeny);
-
-	tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.bluex = tmp/1024;
-	DPRINTK("         BlueX:    0.%03d ", specs->chroma.bluex);
-
-	tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.bluey = tmp/1024;
-	DPRINTK("BlueY:    0.%03d\n", specs->chroma.bluey);
-
-	tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.whitex = tmp/1024;
-	DPRINTK("         WhiteX:   0.%03d ", specs->chroma.whitex);
-
-	tmp = (block[6] & 3) | (block[0xe] << 2);
-	tmp *= 1000;
-	tmp += 512;
-	specs->chroma.whitey = tmp/1024;
-	DPRINTK("WhiteY:   0.%03d\n", specs->chroma.whitey);
-}
-
-static void calc_mode_timings(int xres, int yres, int refresh,
-			      struct fb_videomode *mode)
-{
-	struct fb_var_screeninfo *var;
-
-	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
-
-	if (var) {
-		var->xres = xres;
-		var->yres = yres;
-		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
-			    refresh, var, NULL);
-		mode->xres = xres;
-		mode->yres = yres;
-		mode->pixclock = var->pixclock;
-		mode->refresh = refresh;
-		mode->left_margin = var->left_margin;
-		mode->right_margin = var->right_margin;
-		mode->upper_margin = var->upper_margin;
-		mode->lower_margin = var->lower_margin;
-		mode->hsync_len = var->hsync_len;
-		mode->vsync_len = var->vsync_len;
-		mode->vmode = 0;
-		mode->sync = 0;
-		kfree(var);
-	}
-}
-
-static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
-{
-	int num = 0;
-	unsigned char c;
-
-	c = block[0];
-	if (c&0x80) {
-		calc_mode_timings(720, 400, 70, &mode[num]);
-		mode[num++].flag = FB_MODE_IS_CALCULATED;
-		DPRINTK("      720x400@70Hz\n");
-	}
-	if (c&0x40) {
-		calc_mode_timings(720, 400, 88, &mode[num]);
-		mode[num++].flag = FB_MODE_IS_CALCULATED;
-		DPRINTK("      720x400@88Hz\n");
-	}
-	if (c&0x20) {
-		mode[num++] = vesa_modes[3];
-		DPRINTK("      640x480@60Hz\n");
-	}
-	if (c&0x10) {
-		calc_mode_timings(640, 480, 67, &mode[num]);
-		mode[num++].flag = FB_MODE_IS_CALCULATED;
-		DPRINTK("      640x480@67Hz\n");
-	}
-	if (c&0x08) {
-		mode[num++] = vesa_modes[4];
-		DPRINTK("      640x480@72Hz\n");
-	}
-	if (c&0x04) {
-		mode[num++] = vesa_modes[5];
-		DPRINTK("      640x480@75Hz\n");
-	}
-	if (c&0x02) {
-		mode[num++] = vesa_modes[7];
-		DPRINTK("      800x600@56Hz\n");
-	}
-	if (c&0x01) {
-		mode[num++] = vesa_modes[8];
-		DPRINTK("      800x600@60Hz\n");
-	}
-
-	c = block[1];
-	if (c&0x80) {
-		mode[num++] = vesa_modes[9];
-		DPRINTK("      800x600@72Hz\n");
-	}
-	if (c&0x40) {
-		mode[num++] = vesa_modes[10];
-		DPRINTK("      800x600@75Hz\n");
-	}
-	if (c&0x20) {
-		calc_mode_timings(832, 624, 75, &mode[num]);
-		mode[num++].flag = FB_MODE_IS_CALCULATED;
-		DPRINTK("      832x624@75Hz\n");
-	}
-	if (c&0x10) {
-		mode[num++] = vesa_modes[12];
-		DPRINTK("      1024x768@87Hz Interlaced\n");
-	}
-	if (c&0x08) {
-		mode[num++] = vesa_modes[13];
-		DPRINTK("      1024x768@60Hz\n");
-	}
-	if (c&0x04) {
-		mode[num++] = vesa_modes[14];
-		DPRINTK("      1024x768@70Hz\n");
-	}
-	if (c&0x02) {
-		mode[num++] = vesa_modes[15];
-		DPRINTK("      1024x768@75Hz\n");
-	}
-	if (c&0x01) {
-		mode[num++] = vesa_modes[21];
-		DPRINTK("      1280x1024@75Hz\n");
-	}
-	c = block[2];
-	if (c&0x80) {
-		mode[num++] = vesa_modes[17];
-		DPRINTK("      1152x870@75Hz\n");
-	}
-	DPRINTK("      Manufacturer's mask: %x\n",c&0x7F);
-	return num;
-}
-
-static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
-		int ver, int rev)
-{
-	int xres, yres = 0, refresh, ratio, i;
-
-	xres = (block[0] + 31) * 8;
-	if (xres <= 256)
-		return 0;
-
-	ratio = (block[1] & 0xc0) >> 6;
-	switch (ratio) {
-	case 0:
-		/* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
-		if (ver < 1 || (ver == 1 && rev < 3))
-			yres = xres;
-		else
-			yres = (xres * 10)/16;
-		break;
-	case 1:
-		yres = (xres * 3)/4;
-		break;
-	case 2:
-		yres = (xres * 4)/5;
-		break;
-	case 3:
-		yres = (xres * 9)/16;
-		break;
-	}
-	refresh = (block[1] & 0x3f) + 60;
-
-	DPRINTK("      %dx%d@%dHz\n", xres, yres, refresh);
-	for (i = 0; i < VESA_MODEDB_SIZE; i++) {
-		if (vesa_modes[i].xres == xres &&
-		    vesa_modes[i].yres == yres &&
-		    vesa_modes[i].refresh == refresh) {
-			*mode = vesa_modes[i];
-			mode->flag |= FB_MODE_IS_STANDARD;
-			return 1;
-		}
-	}
-	calc_mode_timings(xres, yres, refresh, mode);
-	return 1;
-}
-
-static int get_dst_timing(unsigned char *block,
-			  struct fb_videomode *mode, int ver, int rev)
-{
-	int j, num = 0;
-
-	for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
-		num += get_std_timing(block, &mode[num], ver, rev);
-
-	return num;
-}
-
-static void get_detailed_timing(unsigned char *block,
-				struct fb_videomode *mode)
-{
-	mode->xres = H_ACTIVE;
-	mode->yres = V_ACTIVE;
-	mode->pixclock = PIXEL_CLOCK;
-	mode->pixclock /= 1000;
-	mode->pixclock = KHZ2PICOS(mode->pixclock);
-	mode->right_margin = H_SYNC_OFFSET;
-	mode->left_margin = (H_ACTIVE + H_BLANKING) -
-		(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
-	mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
-		V_SYNC_WIDTH;
-	mode->lower_margin = V_SYNC_OFFSET;
-	mode->hsync_len = H_SYNC_WIDTH;
-	mode->vsync_len = V_SYNC_WIDTH;
-	if (HSYNC_POSITIVE)
-		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (VSYNC_POSITIVE)
-		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
-	mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
-				     (V_ACTIVE + V_BLANKING));
-	if (INTERLACED) {
-		mode->yres *= 2;
-		mode->upper_margin *= 2;
-		mode->lower_margin *= 2;
-		mode->vsync_len *= 2;
-		mode->vmode |= FB_VMODE_INTERLACED;
-	}
-	mode->flag = FB_MODE_IS_DETAILED;
-
-	DPRINTK("      %d MHz ",  PIXEL_CLOCK/1000000);
-	DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
-	       H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
-	DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
-	       V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
-	DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
-	       (VSYNC_POSITIVE) ? "+" : "-");
-}
-
-/**
- * fb_create_modedb - create video mode database
- * @edid: EDID data
- * @dbsize: database size
- *
- * RETURNS: struct fb_videomode, @dbsize contains length of database
- *
- * DESCRIPTION:
- * This function builds a mode database using the contents of the EDID
- * data
- */
-static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
-{
-	struct fb_videomode *mode, *m;
-	unsigned char *block;
-	int num = 0, i, first = 1;
-	int ver, rev;
-
-	ver = edid[EDID_STRUCT_VERSION];
-	rev = edid[EDID_STRUCT_REVISION];
-
-	mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
-	if (mode == NULL)
-		return NULL;
-
-	if (edid == NULL || !edid_checksum(edid) ||
-	    !edid_check_header(edid)) {
-		kfree(mode);
-		return NULL;
-	}
-
-	*dbsize = 0;
-
-	DPRINTK("   Detailed Timings\n");
-	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
-	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
-		if (!(block[0] == 0x00 && block[1] == 0x00)) {
-			get_detailed_timing(block, &mode[num]);
-			if (first) {
-			        mode[num].flag |= FB_MODE_IS_FIRST;
-				first = 0;
-			}
-			num++;
-		}
-	}
-
-	DPRINTK("   Supported VESA Modes\n");
-	block = edid + ESTABLISHED_TIMING_1;
-	num += get_est_timing(block, &mode[num]);
-
-	DPRINTK("   Standard Timings\n");
-	block = edid + STD_TIMING_DESCRIPTIONS_START;
-	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
-		num += get_std_timing(block, &mode[num], ver, rev);
-
-	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
-	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
-		if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
-			num += get_dst_timing(block + 5, &mode[num], ver, rev);
-	}
-
-	/* Yikes, EDID data is totally useless */
-	if (!num) {
-		kfree(mode);
-		return NULL;
-	}
-
-	*dbsize = num;
-	m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
-	if (!m)
-		return mode;
-	memmove(m, mode, num * sizeof(struct fb_videomode));
-	kfree(mode);
-	return m;
-}
-
-/**
- * fb_destroy_modedb - destroys mode database
- * @modedb: mode database to destroy
- *
- * DESCRIPTION:
- * Destroy mode database created by fb_create_modedb
- */
-void fb_destroy_modedb(struct fb_videomode *modedb)
-{
-	kfree(modedb);
-}
-
-static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
-{
-	int i, retval = 1;
-	unsigned char *block;
-
-	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
-
-	DPRINTK("      Monitor Operating Limits: ");
-
-	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
-		if (edid_is_limits_block(block)) {
-			specs->hfmin = H_MIN_RATE * 1000;
-			specs->hfmax = H_MAX_RATE * 1000;
-			specs->vfmin = V_MIN_RATE;
-			specs->vfmax = V_MAX_RATE;
-			specs->dclkmax = MAX_PIXEL_CLOCK * 1000000;
-			specs->gtf = (GTF_SUPPORT) ? 1 : 0;
-			retval = 0;
-			DPRINTK("From EDID\n");
-			break;
-		}
-	}
-
-	/* estimate monitor limits based on modes supported */
-	if (retval) {
-		struct fb_videomode *modes, *mode;
-		int num_modes, hz, hscan, pixclock;
-		int vtotal, htotal;
-
-		modes = fb_create_modedb(edid, &num_modes);
-		if (!modes) {
-			DPRINTK("None Available\n");
-			return 1;
-		}
-
-		retval = 0;
-		for (i = 0; i < num_modes; i++) {
-			mode = &modes[i];
-			pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
-			htotal = mode->xres + mode->right_margin + mode->hsync_len
-				+ mode->left_margin;
-			vtotal = mode->yres + mode->lower_margin + mode->vsync_len
-				+ mode->upper_margin;
-
-			if (mode->vmode & FB_VMODE_INTERLACED)
-				vtotal /= 2;
-
-			if (mode->vmode & FB_VMODE_DOUBLE)
-				vtotal *= 2;
-
-			hscan = (pixclock + htotal / 2) / htotal;
-			hscan = (hscan + 500) / 1000 * 1000;
-			hz = (hscan + vtotal / 2) / vtotal;
-
-			if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
-				specs->dclkmax = pixclock;
-
-			if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
-				specs->dclkmin = pixclock;
-
-			if (specs->hfmax == 0 || specs->hfmax < hscan)
-				specs->hfmax = hscan;
-
-			if (specs->hfmin == 0 || specs->hfmin > hscan)
-				specs->hfmin = hscan;
-
-			if (specs->vfmax == 0 || specs->vfmax < hz)
-				specs->vfmax = hz;
-
-			if (specs->vfmin == 0 || specs->vfmin > hz)
-				specs->vfmin = hz;
-		}
-		DPRINTK("Extrapolated\n");
-		fb_destroy_modedb(modes);
-	}
-	DPRINTK("           H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n",
-		specs->hfmin/1000, specs->hfmax/1000, specs->vfmin,
-		specs->vfmax, specs->dclkmax/1000000);
-	return retval;
-}
-
-static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
-{
-	unsigned char c, *block;
-
-	block = edid + EDID_STRUCT_DISPLAY;
-
-	fb_get_monitor_limits(edid, specs);
-
-	c = block[0] & 0x80;
-	specs->input = 0;
-	if (c) {
-		specs->input |= FB_DISP_DDI;
-		DPRINTK("      Digital Display Input");
-	} else {
-		DPRINTK("      Analog Display Input: Input Voltage - ");
-		switch ((block[0] & 0x60) >> 5) {
-		case 0:
-			DPRINTK("0.700V/0.300V");
-			specs->input |= FB_DISP_ANA_700_300;
-			break;
-		case 1:
-			DPRINTK("0.714V/0.286V");
-			specs->input |= FB_DISP_ANA_714_286;
-			break;
-		case 2:
-			DPRINTK("1.000V/0.400V");
-			specs->input |= FB_DISP_ANA_1000_400;
-			break;
-		case 3:
-			DPRINTK("0.700V/0.000V");
-			specs->input |= FB_DISP_ANA_700_000;
-			break;
-		}
-	}
-	DPRINTK("\n      Sync: ");
-	c = block[0] & 0x10;
-	if (c)
-		DPRINTK("      Configurable signal level\n");
-	c = block[0] & 0x0f;
-	specs->signal = 0;
-	if (c & 0x10) {
-		DPRINTK("Blank to Blank ");
-		specs->signal |= FB_SIGNAL_BLANK_BLANK;
-	}
-	if (c & 0x08) {
-		DPRINTK("Separate ");
-		specs->signal |= FB_SIGNAL_SEPARATE;
-	}
-	if (c & 0x04) {
-		DPRINTK("Composite ");
-		specs->signal |= FB_SIGNAL_COMPOSITE;
-	}
-	if (c & 0x02) {
-		DPRINTK("Sync on Green ");
-		specs->signal |= FB_SIGNAL_SYNC_ON_GREEN;
-	}
-	if (c & 0x01) {
-		DPRINTK("Serration on ");
-		specs->signal |= FB_SIGNAL_SERRATION_ON;
-	}
-	DPRINTK("\n");
-	specs->max_x = block[1];
-	specs->max_y = block[2];
-	DPRINTK("      Max H-size in cm: ");
-	if (specs->max_x)
-		DPRINTK("%d\n", specs->max_x);
-	else
-		DPRINTK("variable\n");
-	DPRINTK("      Max V-size in cm: ");
-	if (specs->max_y)
-		DPRINTK("%d\n", specs->max_y);
-	else
-		DPRINTK("variable\n");
-
-	c = block[3];
-	specs->gamma = c+100;
-	DPRINTK("      Gamma: ");
-	DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100);
-
-	get_dpms_capabilities(block[4], specs);
-
-	switch ((block[4] & 0x18) >> 3) {
-	case 0:
-		DPRINTK("      Monochrome/Grayscale\n");
-		specs->input |= FB_DISP_MONO;
-		break;
-	case 1:
-		DPRINTK("      RGB Color Display\n");
-		specs->input |= FB_DISP_RGB;
-		break;
-	case 2:
-		DPRINTK("      Non-RGB Multicolor Display\n");
-		specs->input |= FB_DISP_MULTI;
-		break;
-	default:
-		DPRINTK("      Unknown\n");
-		specs->input |= FB_DISP_UNKNOWN;
-		break;
-	}
-
-	get_chroma(block, specs);
-
-	specs->misc = 0;
-	c = block[4] & 0x7;
-	if (c & 0x04) {
-		DPRINTK("      Default color format is primary\n");
-		specs->misc |= FB_MISC_PRIM_COLOR;
-	}
-	if (c & 0x02) {
-		DPRINTK("      First DETAILED Timing is preferred\n");
-		specs->misc |= FB_MISC_1ST_DETAIL;
-	}
-	if (c & 0x01) {
-		printk("      Display is GTF capable\n");
-		specs->gtf = 1;
-	}
-}
-
-int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
-{
-	int i;
-	unsigned char *block;
-
-	if (edid == NULL || var == NULL)
-		return 1;
-
-	if (!(edid_checksum(edid)))
-		return 1;
-
-	if (!(edid_check_header(edid)))
-		return 1;
-
-	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
-
-	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
-		if (edid_is_timing_block(block)) {
-			var->xres = var->xres_virtual = H_ACTIVE;
-			var->yres = var->yres_virtual = V_ACTIVE;
-			var->height = var->width = 0;
-			var->right_margin = H_SYNC_OFFSET;
-			var->left_margin = (H_ACTIVE + H_BLANKING) -
-				(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
-			var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
-				V_SYNC_WIDTH;
-			var->lower_margin = V_SYNC_OFFSET;
-			var->hsync_len = H_SYNC_WIDTH;
-			var->vsync_len = V_SYNC_WIDTH;
-			var->pixclock = PIXEL_CLOCK;
-			var->pixclock /= 1000;
-			var->pixclock = KHZ2PICOS(var->pixclock);
-
-			if (HSYNC_POSITIVE)
-				var->sync |= FB_SYNC_HOR_HIGH_ACT;
-			if (VSYNC_POSITIVE)
-				var->sync |= FB_SYNC_VERT_HIGH_ACT;
-			return 0;
-		}
-	}
-	return 1;
-}
-
-void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
-{
-	unsigned char *block;
-	int i, found = 0;
-
-	if (edid == NULL)
-		return;
-
-	if (!(edid_checksum(edid)))
-		return;
-
-	if (!(edid_check_header(edid)))
-		return;
-
-	memset(specs, 0, sizeof(struct fb_monspecs));
-
-	specs->version = edid[EDID_STRUCT_VERSION];
-	specs->revision = edid[EDID_STRUCT_REVISION];
-
-	DPRINTK("========================================\n");
-	DPRINTK("Display Information (EDID)\n");
-	DPRINTK("========================================\n");
-	DPRINTK("   EDID Version %d.%d\n", (int) specs->version,
-	       (int) specs->revision);
-
-	parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);
-
-	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
-	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
-		if (edid_is_serial_block(block)) {
-			copy_string(block, specs->serial_no);
-			DPRINTK("   Serial Number: %s\n", specs->serial_no);
-		} else if (edid_is_ascii_block(block)) {
-			copy_string(block, specs->ascii);
-			DPRINTK("   ASCII Block: %s\n", specs->ascii);
-		} else if (edid_is_monitor_block(block)) {
-			copy_string(block, specs->monitor);
-			DPRINTK("   Monitor Name: %s\n", specs->monitor);
-		}
-	}
-
-	DPRINTK("   Display Characteristics:\n");
-	get_monspecs(edid, specs);
-
-	specs->modedb = fb_create_modedb(edid, &specs->modedb_len);
-
-	/*
-	 * Workaround for buggy EDIDs that sets that the first
-	 * detailed timing is preferred but has not detailed
-	 * timing specified
-	 */
-	for (i = 0; i < specs->modedb_len; i++) {
-		if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found)
-		specs->misc &= ~FB_MISC_1ST_DETAIL;
-
-	DPRINTK("========================================\n");
-}
-
-/**
- * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
- * @edid:	128 byte array with an E-EDID block
- * @spacs:	monitor specs to be extended
- */
-void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
-{
-	unsigned char *block;
-	struct fb_videomode *m;
-	int num = 0, i;
-	u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
-	u8 pos = 4, svd_n = 0;
-
-	if (!edid)
-		return;
-
-	if (!edid_checksum(edid))
-		return;
-
-	if (edid[0] != 0x2 ||
-	    edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
-		return;
-
-	DPRINTK("  Short Video Descriptors\n");
-
-	while (pos < edid[2]) {
-		u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
-		pr_debug("Data block %u of %u bytes\n", type, len);
-		if (type == 2)
-			for (i = pos; i < pos + len; i++) {
-				u8 idx = edid[pos + i] & 0x7f;
-				svd[svd_n++] = idx;
-				pr_debug("N%sative mode #%d\n",
-					 edid[pos + i] & 0x80 ? "" : "on-n", idx);
-			}
-		pos += len + 1;
-	}
-
-	block = edid + edid[2];
-
-	DPRINTK("  Extended Detailed Timings\n");
-
-	for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
-	     i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
-		if (PIXEL_CLOCK)
-			edt[num++] = block - edid;
-
-	/* Yikes, EDID data is totally useless */
-	if (!(num + svd_n))
-		return;
-
-	m = kzalloc((specs->modedb_len + num + svd_n) *
-		       sizeof(struct fb_videomode), GFP_KERNEL);
-
-	if (!m)
-		return;
-
-	memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
-
-	for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
-		get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
-		if (i == specs->modedb_len)
-			m[i].flag |= FB_MODE_IS_FIRST;
-		pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
-	}
-
-	for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
-		int idx = svd[i - specs->modedb_len - num];
-		if (!idx || idx > 63) {
-			pr_warning("Reserved SVD code %d\n", idx);
-		} else if (idx > ARRAY_SIZE(cea_modes) || !cea_modes[idx].xres) {
-			pr_warning("Unimplemented SVD code %d\n", idx);
-		} else {
-			memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
-			pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
-				 m[i].xres, m[i].yres, m[i].refresh);
-		}
-	}
-
-	kfree(specs->modedb);
-	specs->modedb = m;
-	specs->modedb_len = specs->modedb_len + num + svd_n;
-}
-
-/*
- * VESA Generalized Timing Formula (GTF)
- */
-
-#define FLYBACK                     550
-#define V_FRONTPORCH                1
-#define H_OFFSET                    40
-#define H_SCALEFACTOR               20
-#define H_BLANKSCALE                128
-#define H_GRADIENT                  600
-#define C_VAL                       30
-#define M_VAL                       300
-
-struct __fb_timings {
-	u32 dclk;
-	u32 hfreq;
-	u32 vfreq;
-	u32 hactive;
-	u32 vactive;
-	u32 hblank;
-	u32 vblank;
-	u32 htotal;
-	u32 vtotal;
-};
-
-/**
- * fb_get_vblank - get vertical blank time
- * @hfreq: horizontal freq
- *
- * DESCRIPTION:
- * vblank = right_margin + vsync_len + left_margin
- *
- *    given: right_margin = 1 (V_FRONTPORCH)
- *           vsync_len    = 3
- *           flyback      = 550
- *
- *                          flyback * hfreq
- *           left_margin  = --------------- - vsync_len
- *                           1000000
- */
-static u32 fb_get_vblank(u32 hfreq)
-{
-	u32 vblank;
-
-	vblank = (hfreq * FLYBACK)/1000;
-	vblank = (vblank + 500)/1000;
-	return (vblank + V_FRONTPORCH);
-}
-
-/**
- * fb_get_hblank_by_freq - get horizontal blank time given hfreq
- * @hfreq: horizontal freq
- * @xres: horizontal resolution in pixels
- *
- * DESCRIPTION:
- *
- *           xres * duty_cycle
- * hblank = ------------------
- *           100 - duty_cycle
- *
- * duty cycle = percent of htotal assigned to inactive display
- * duty cycle = C - (M/Hfreq)
- *
- * where: C = ((offset - scale factor) * blank_scale)
- *            -------------------------------------- + scale factor
- *                        256
- *        M = blank_scale * gradient
- *
- */
-static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
-{
-	u32 c_val, m_val, duty_cycle, hblank;
-
-	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
-		 H_SCALEFACTOR) * 1000;
-	m_val = (H_BLANKSCALE * H_GRADIENT)/256;
-	m_val = (m_val * 1000000)/hfreq;
-	duty_cycle = c_val - m_val;
-	hblank = (xres * duty_cycle)/(100000 - duty_cycle);
-	return (hblank);
-}
-
-/**
- * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
- * @dclk: pixelclock in Hz
- * @xres: horizontal resolution in pixels
- *
- * DESCRIPTION:
- *
- *           xres * duty_cycle
- * hblank = ------------------
- *           100 - duty_cycle
- *
- * duty cycle = percent of htotal assigned to inactive display
- * duty cycle = C - (M * h_period)
- *
- * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
- *                   -----------------------------------------------
- *                                    2 * M
- *        M = 300;
- *        C = 30;
-
- */
-static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
-{
-	u32 duty_cycle, h_period, hblank;
-
-	dclk /= 1000;
-	h_period = 100 - C_VAL;
-	h_period *= h_period;
-	h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
-	h_period *= 10000;
-
-	h_period = int_sqrt(h_period);
-	h_period -= (100 - C_VAL) * 100;
-	h_period *= 1000;
-	h_period /= 2 * M_VAL;
-
-	duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
-	hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
-	hblank &= ~15;
-	return (hblank);
-}
-
-/**
- * fb_get_hfreq - estimate hsync
- * @vfreq: vertical refresh rate
- * @yres: vertical resolution
- *
- * DESCRIPTION:
- *
- *          (yres + front_port) * vfreq * 1000000
- * hfreq = -------------------------------------
- *          (1000000 - (vfreq * FLYBACK)
- *
- */
-
-static u32 fb_get_hfreq(u32 vfreq, u32 yres)
-{
-	u32 divisor, hfreq;
-
-	divisor = (1000000 - (vfreq * FLYBACK))/1000;
-	hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;
-	return (hfreq/divisor);
-}
-
-static void fb_timings_vfreq(struct __fb_timings *timings)
-{
-	timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
-	timings->vblank = fb_get_vblank(timings->hfreq);
-	timings->vtotal = timings->vactive + timings->vblank;
-	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
-						 timings->hactive);
-	timings->htotal = timings->hactive + timings->hblank;
-	timings->dclk = timings->htotal * timings->hfreq;
-}
-
-static void fb_timings_hfreq(struct __fb_timings *timings)
-{
-	timings->vblank = fb_get_vblank(timings->hfreq);
-	timings->vtotal = timings->vactive + timings->vblank;
-	timings->vfreq = timings->hfreq/timings->vtotal;
-	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
-						 timings->hactive);
-	timings->htotal = timings->hactive + timings->hblank;
-	timings->dclk = timings->htotal * timings->hfreq;
-}
-
-static void fb_timings_dclk(struct __fb_timings *timings)
-{
-	timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
-						timings->hactive);
-	timings->htotal = timings->hactive + timings->hblank;
-	timings->hfreq = timings->dclk/timings->htotal;
-	timings->vblank = fb_get_vblank(timings->hfreq);
-	timings->vtotal = timings->vactive + timings->vblank;
-	timings->vfreq = timings->hfreq/timings->vtotal;
-}
-
-/*
- * fb_get_mode - calculates video mode using VESA GTF
- * @flags: if: 0 - maximize vertical refresh rate
- *             1 - vrefresh-driven calculation;
- *             2 - hscan-driven calculation;
- *             3 - pixelclock-driven calculation;
- * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
- * @var: pointer to fb_var_screeninfo
- * @info: pointer to fb_info
- *
- * DESCRIPTION:
- * Calculates video mode based on monitor specs using VESA GTF.
- * The GTF is best for VESA GTF compliant monitors but is
- * specifically formulated to work for older monitors as well.
- *
- * If @flag==0, the function will attempt to maximize the
- * refresh rate.  Otherwise, it will calculate timings based on
- * the flag and accompanying value.
- *
- * If FB_IGNOREMON bit is set in @flags, monitor specs will be
- * ignored and @var will be filled with the calculated timings.
- *
- * All calculations are based on the VESA GTF Spreadsheet
- * available at VESA's public ftp (http://www.vesa.org).
- *
- * NOTES:
- * The timings generated by the GTF will be different from VESA
- * DMT.  It might be a good idea to keep a table of standard
- * VESA modes as well.  The GTF may also not work for some displays,
- * such as, and especially, analog TV.
- *
- * REQUIRES:
- * A valid info->monspecs, otherwise 'safe numbers' will be used.
- */
-int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct __fb_timings *timings;
-	u32 interlace = 1, dscan = 1;
-	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
-
-
-	timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
-
-	if (!timings)
-		return -ENOMEM;
-
-	/*
-	 * If monspecs are invalid, use values that are enough
-	 * for 640x480@60
-	 */
-	if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
-	    !info->monspecs.dclkmax ||
-	    info->monspecs.hfmax < info->monspecs.hfmin ||
-	    info->monspecs.vfmax < info->monspecs.vfmin ||
-	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
-		hfmin = 29000; hfmax = 30000;
-		vfmin = 60; vfmax = 60;
-		dclkmin = 0; dclkmax = 25000000;
-	} else {
-		hfmin = info->monspecs.hfmin;
-		hfmax = info->monspecs.hfmax;
-		vfmin = info->monspecs.vfmin;
-		vfmax = info->monspecs.vfmax;
-		dclkmin = info->monspecs.dclkmin;
-		dclkmax = info->monspecs.dclkmax;
-	}
-
-	timings->hactive = var->xres;
-	timings->vactive = var->yres;
-	if (var->vmode & FB_VMODE_INTERLACED) {
-		timings->vactive /= 2;
-		interlace = 2;
-	}
-	if (var->vmode & FB_VMODE_DOUBLE) {
-		timings->vactive *= 2;
-		dscan = 2;
-	}
-
-	switch (flags & ~FB_IGNOREMON) {
-	case FB_MAXTIMINGS: /* maximize refresh rate */
-		timings->hfreq = hfmax;
-		fb_timings_hfreq(timings);
-		if (timings->vfreq > vfmax) {
-			timings->vfreq = vfmax;
-			fb_timings_vfreq(timings);
-		}
-		if (timings->dclk > dclkmax) {
-			timings->dclk = dclkmax;
-			fb_timings_dclk(timings);
-		}
-		break;
-	case FB_VSYNCTIMINGS: /* vrefresh driven */
-		timings->vfreq = val;
-		fb_timings_vfreq(timings);
-		break;
-	case FB_HSYNCTIMINGS: /* hsync driven */
-		timings->hfreq = val;
-		fb_timings_hfreq(timings);
-		break;
-	case FB_DCLKTIMINGS: /* pixelclock driven */
-		timings->dclk = PICOS2KHZ(val) * 1000;
-		fb_timings_dclk(timings);
-		break;
-	default:
-		err = -EINVAL;
-
-	}
-
-	if (err || (!(flags & FB_IGNOREMON) &&
-	    (timings->vfreq < vfmin || timings->vfreq > vfmax ||
-	     timings->hfreq < hfmin || timings->hfreq > hfmax ||
-	     timings->dclk < dclkmin || timings->dclk > dclkmax))) {
-		err = -EINVAL;
-	} else {
-		var->pixclock = KHZ2PICOS(timings->dclk/1000);
-		var->hsync_len = (timings->htotal * 8)/100;
-		var->right_margin = (timings->hblank/2) - var->hsync_len;
-		var->left_margin = timings->hblank - var->right_margin -
-			var->hsync_len;
-		var->vsync_len = (3 * interlace)/dscan;
-		var->lower_margin = (1 * interlace)/dscan;
-		var->upper_margin = (timings->vblank * interlace)/dscan -
-			(var->vsync_len + var->lower_margin);
-	}
-
-	kfree(timings);
-	return err;
-}
-
-#ifdef CONFIG_VIDEOMODE_HELPERS
-int fb_videomode_from_videomode(const struct videomode *vm,
-				struct fb_videomode *fbmode)
-{
-	unsigned int htotal, vtotal;
-
-	fbmode->xres = vm->hactive;
-	fbmode->left_margin = vm->hback_porch;
-	fbmode->right_margin = vm->hfront_porch;
-	fbmode->hsync_len = vm->hsync_len;
-
-	fbmode->yres = vm->vactive;
-	fbmode->upper_margin = vm->vback_porch;
-	fbmode->lower_margin = vm->vfront_porch;
-	fbmode->vsync_len = vm->vsync_len;
-
-	/* prevent division by zero in KHZ2PICOS macro */
-	fbmode->pixclock = vm->pixelclock ?
-			KHZ2PICOS(vm->pixelclock / 1000) : 0;
-
-	fbmode->sync = 0;
-	fbmode->vmode = 0;
-	if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
-		fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
-		fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
-	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
-		fbmode->vmode |= FB_VMODE_INTERLACED;
-	if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
-		fbmode->vmode |= FB_VMODE_DOUBLE;
-	fbmode->flag = 0;
-
-	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
-		 vm->hsync_len;
-	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
-		 vm->vsync_len;
-	/* prevent division by zero */
-	if (htotal && vtotal) {
-		fbmode->refresh = vm->pixelclock / (htotal * vtotal);
-	/* a mode must have htotal and vtotal != 0 or it is invalid */
-	} else {
-		fbmode->refresh = 0;
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
-
-#ifdef CONFIG_OF
-static inline void dump_fb_videomode(const struct fb_videomode *m)
-{
-	pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
-		 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
-		 m->right_margin, m->upper_margin, m->lower_margin,
-		 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
-}
-
-/**
- * of_get_fb_videomode - get a fb_videomode from devicetree
- * @np: device_node with the timing specification
- * @fb: will be set to the return value
- * @index: index into the list of display timings in devicetree
- *
- * DESCRIPTION:
- * This function is expensive and should only be used, if only one mode is to be
- * read from DT. To get multiple modes start with of_get_display_timings ond
- * work with that instead.
- */
-int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
-			int index)
-{
-	struct videomode vm;
-	int ret;
-
-	ret = of_get_videomode(np, &vm, index);
-	if (ret)
-		return ret;
-
-	fb_videomode_from_videomode(&vm, fb);
-
-	pr_debug("%s: got %dx%d display mode from %s\n",
-		of_node_full_name(np), vm.hactive, vm.vactive, np->name);
-	dump_fb_videomode(fb);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(of_get_fb_videomode);
-#endif /* CONFIG_OF */
-#endif /* CONFIG_VIDEOMODE_HELPERS */
-
-#else
-int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
-{
-	return 1;
-}
-void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
-{
-	specs = NULL;
-}
-void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
-{
-}
-void fb_destroy_modedb(struct fb_videomode *modedb)
-{
-}
-int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-	return -EINVAL;
-}
-#endif /* CONFIG_FB_MODE_HELPERS */
-
-/*
- * fb_validate_mode - validates var against monitor capabilities
- * @var: pointer to fb_var_screeninfo
- * @info: pointer to fb_info
- *
- * DESCRIPTION:
- * Validates video mode against monitor capabilities specified in
- * info->monspecs.
- *
- * REQUIRES:
- * A valid info->monspecs.
- */
-int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	u32 hfreq, vfreq, htotal, vtotal, pixclock;
-	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
-
-	/*
-	 * If monspecs are invalid, use values that are enough
-	 * for 640x480@60
-	 */
-	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
-	    !info->monspecs.dclkmax ||
-	    info->monspecs.hfmax < info->monspecs.hfmin ||
-	    info->monspecs.vfmax < info->monspecs.vfmin ||
-	    info->monspecs.dclkmax < info->monspecs.dclkmin) {
-		hfmin = 29000; hfmax = 30000;
-		vfmin = 60; vfmax = 60;
-		dclkmin = 0; dclkmax = 25000000;
-	} else {
-		hfmin = info->monspecs.hfmin;
-		hfmax = info->monspecs.hfmax;
-		vfmin = info->monspecs.vfmin;
-		vfmax = info->monspecs.vfmax;
-		dclkmin = info->monspecs.dclkmin;
-		dclkmax = info->monspecs.dclkmax;
-	}
-
-	if (!var->pixclock)
-		return -EINVAL;
-	pixclock = PICOS2KHZ(var->pixclock) * 1000;
-
-	htotal = var->xres + var->right_margin + var->hsync_len +
-		var->left_margin;
-	vtotal = var->yres + var->lower_margin + var->vsync_len +
-		var->upper_margin;
-
-	if (var->vmode & FB_VMODE_INTERLACED)
-		vtotal /= 2;
-	if (var->vmode & FB_VMODE_DOUBLE)
-		vtotal *= 2;
-
-	hfreq = pixclock/htotal;
-	hfreq = (hfreq + 500) / 1000 * 1000;
-
-	vfreq = hfreq/vtotal;
-
-	return (vfreq < vfmin || vfreq > vfmax ||
-		hfreq < hfmin || hfreq > hfmax ||
-		pixclock < dclkmin || pixclock > dclkmax) ?
-		-EINVAL : 0;
-}
-
-#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
-
-/*
- * We need to ensure that the EDID block is only returned for
- * the primary graphics adapter.
- */
-
-const unsigned char *fb_firmware_edid(struct device *device)
-{
-	struct pci_dev *dev = NULL;
-	struct resource *res = NULL;
-	unsigned char *edid = NULL;
-
-	if (device)
-		dev = to_pci_dev(device);
-
-	if (dev)
-		res = &dev->resource[PCI_ROM_RESOURCE];
-
-	if (res && res->flags & IORESOURCE_ROM_SHADOW)
-		edid = edid_info.dummy;
-
-	return edid;
-}
-#else
-const unsigned char *fb_firmware_edid(struct device *device)
-{
-	return NULL;
-}
-#endif
-EXPORT_SYMBOL(fb_firmware_edid);
-
-EXPORT_SYMBOL(fb_parse_edid);
-EXPORT_SYMBOL(fb_edid_to_monspecs);
-EXPORT_SYMBOL(fb_edid_add_monspecs);
-EXPORT_SYMBOL(fb_get_mode);
-EXPORT_SYMBOL(fb_validate_mode);
-EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
deleted file mode 100644
index 53444ac19fe0..000000000000
--- a/drivers/video/fbsysfs.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * fbsysfs.c - framebuffer device class and attributes
- *
- * Copyright (c) 2004 James Simmons <jsimmons@infradead.org>
- * 
- *	This program is free software you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- */
-
-/*
- * Note:  currently there's only stubs for framebuffer_alloc and
- * framebuffer_release here.  The reson for that is that until all drivers
- * are converted to use it a sysfsification will open OOPSable races.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/module.h>
-
-#define FB_SYSFS_FLAG_ATTR 1
-
-/**
- * framebuffer_alloc - creates a new frame buffer info structure
- *
- * @size: size of driver private data, can be zero
- * @dev: pointer to the device for this fb, this can be NULL
- *
- * Creates a new frame buffer info structure. Also reserves @size bytes
- * for driver private data (info->par). info->par (if any) will be
- * aligned to sizeof(long).
- *
- * Returns the new structure, or NULL if an error occurred.
- *
- */
-struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
-{
-#define BYTES_PER_LONG (BITS_PER_LONG/8)
-#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
-	int fb_info_size = sizeof(struct fb_info);
-	struct fb_info *info;
-	char *p;
-
-	if (size)
-		fb_info_size += PADDING;
-
-	p = kzalloc(fb_info_size + size, GFP_KERNEL);
-
-	if (!p)
-		return NULL;
-
-	info = (struct fb_info *) p;
-
-	if (size)
-		info->par = p + fb_info_size;
-
-	info->device = dev;
-
-#ifdef CONFIG_FB_BACKLIGHT
-	mutex_init(&info->bl_curve_mutex);
-#endif
-
-	return info;
-#undef PADDING
-#undef BYTES_PER_LONG
-}
-EXPORT_SYMBOL(framebuffer_alloc);
-
-/**
- * framebuffer_release - marks the structure available for freeing
- *
- * @info: frame buffer info structure
- *
- * Drop the reference count of the device embedded in the
- * framebuffer info structure.
- *
- */
-void framebuffer_release(struct fb_info *info)
-{
-	if (!info)
-		return;
-	kfree(info->apertures);
-	kfree(info);
-}
-EXPORT_SYMBOL(framebuffer_release);
-
-static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
-{
-	int err;
-
-	var->activate |= FB_ACTIVATE_FORCE;
-	console_lock();
-	fb_info->flags |= FBINFO_MISC_USEREVENT;
-	err = fb_set_var(fb_info, var);
-	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
-	console_unlock();
-	if (err)
-		return err;
-	return 0;
-}
-
-static int mode_string(char *buf, unsigned int offset,
-		       const struct fb_videomode *mode)
-{
-	char m = 'U';
-	char v = 'p';
-
-	if (mode->flag & FB_MODE_IS_DETAILED)
-		m = 'D';
-	if (mode->flag & FB_MODE_IS_VESA)
-		m = 'V';
-	if (mode->flag & FB_MODE_IS_STANDARD)
-		m = 'S';
-
-	if (mode->vmode & FB_VMODE_INTERLACED)
-		v = 'i';
-	if (mode->vmode & FB_VMODE_DOUBLE)
-		v = 'd';
-
-	return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d%c-%d\n",
-	                m, mode->xres, mode->yres, v, mode->refresh);
-}
-
-static ssize_t store_mode(struct device *device, struct device_attribute *attr,
-			  const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	char mstr[100];
-	struct fb_var_screeninfo var;
-	struct fb_modelist *modelist;
-	struct fb_videomode *mode;
-	struct list_head *pos;
-	size_t i;
-	int err;
-
-	memset(&var, 0, sizeof(var));
-
-	list_for_each(pos, &fb_info->modelist) {
-		modelist = list_entry(pos, struct fb_modelist, list);
-		mode = &modelist->mode;
-		i = mode_string(mstr, 0, mode);
-		if (strncmp(mstr, buf, max(count, i)) == 0) {
-
-			var = fb_info->var;
-			fb_videomode_to_var(&var, mode);
-			if ((err = activate(fb_info, &var)))
-				return err;
-			fb_info->mode = mode;
-			return count;
-		}
-	}
-	return -EINVAL;
-}
-
-static ssize_t show_mode(struct device *device, struct device_attribute *attr,
-			 char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-
-	if (!fb_info->mode)
-		return 0;
-
-	return mode_string(buf, 0, fb_info->mode);
-}
-
-static ssize_t store_modes(struct device *device,
-			   struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	LIST_HEAD(old_list);
-	int i = count / sizeof(struct fb_videomode);
-
-	if (i * sizeof(struct fb_videomode) != count)
-		return -EINVAL;
-
-	console_lock();
-	if (!lock_fb_info(fb_info)) {
-		console_unlock();
-		return -ENODEV;
-	}
-
-	list_splice(&fb_info->modelist, &old_list);
-	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
-				 &fb_info->modelist);
-	if (fb_new_modelist(fb_info)) {
-		fb_destroy_modelist(&fb_info->modelist);
-		list_splice(&old_list, &fb_info->modelist);
-	} else
-		fb_destroy_modelist(&old_list);
-
-	unlock_fb_info(fb_info);
-	console_unlock();
-
-	return 0;
-}
-
-static ssize_t show_modes(struct device *device, struct device_attribute *attr,
-			  char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	unsigned int i;
-	struct list_head *pos;
-	struct fb_modelist *modelist;
-	const struct fb_videomode *mode;
-
-	i = 0;
-	list_for_each(pos, &fb_info->modelist) {
-		modelist = list_entry(pos, struct fb_modelist, list);
-		mode = &modelist->mode;
-		i += mode_string(buf, i, mode);
-	}
-	return i;
-}
-
-static ssize_t store_bpp(struct device *device, struct device_attribute *attr,
-			 const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	struct fb_var_screeninfo var;
-	char ** last = NULL;
-	int err;
-
-	var = fb_info->var;
-	var.bits_per_pixel = simple_strtoul(buf, last, 0);
-	if ((err = activate(fb_info, &var)))
-		return err;
-	return count;
-}
-
-static ssize_t show_bpp(struct device *device, struct device_attribute *attr,
-			char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
-}
-
-static ssize_t store_rotate(struct device *device,
-			    struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	struct fb_var_screeninfo var;
-	char **last = NULL;
-	int err;
-
-	var = fb_info->var;
-	var.rotate = simple_strtoul(buf, last, 0);
-
-	if ((err = activate(fb_info, &var)))
-		return err;
-
-	return count;
-}
-
-
-static ssize_t show_rotate(struct device *device,
-			   struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate);
-}
-
-static ssize_t store_virtual(struct device *device,
-			     struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	struct fb_var_screeninfo var;
-	char *last = NULL;
-	int err;
-
-	var = fb_info->var;
-	var.xres_virtual = simple_strtoul(buf, &last, 0);
-	last++;
-	if (last - buf >= count)
-		return -EINVAL;
-	var.yres_virtual = simple_strtoul(last, &last, 0);
-
-	if ((err = activate(fb_info, &var)))
-		return err;
-	return count;
-}
-
-static ssize_t show_virtual(struct device *device,
-			    struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
-			fb_info->var.yres_virtual);
-}
-
-static ssize_t show_stride(struct device *device,
-			   struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
-}
-
-static ssize_t store_blank(struct device *device,
-			   struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	char *last = NULL;
-	int err;
-
-	console_lock();
-	fb_info->flags |= FBINFO_MISC_USEREVENT;
-	err = fb_blank(fb_info, simple_strtoul(buf, &last, 0));
-	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
-	console_unlock();
-	if (err < 0)
-		return err;
-	return count;
-}
-
-static ssize_t show_blank(struct device *device,
-			  struct device_attribute *attr, char *buf)
-{
-//	struct fb_info *fb_info = dev_get_drvdata(device);
-	return 0;
-}
-
-static ssize_t store_console(struct device *device,
-			     struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-//	struct fb_info *fb_info = dev_get_drvdata(device);
-	return 0;
-}
-
-static ssize_t show_console(struct device *device,
-			    struct device_attribute *attr, char *buf)
-{
-//	struct fb_info *fb_info = dev_get_drvdata(device);
-	return 0;
-}
-
-static ssize_t store_cursor(struct device *device,
-			    struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-//	struct fb_info *fb_info = dev_get_drvdata(device);
-	return 0;
-}
-
-static ssize_t show_cursor(struct device *device,
-			   struct device_attribute *attr, char *buf)
-{
-//	struct fb_info *fb_info = dev_get_drvdata(device);
-	return 0;
-}
-
-static ssize_t store_pan(struct device *device,
-			 struct device_attribute *attr,
-			 const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	struct fb_var_screeninfo var;
-	char *last = NULL;
-	int err;
-
-	var = fb_info->var;
-	var.xoffset = simple_strtoul(buf, &last, 0);
-	last++;
-	if (last - buf >= count)
-		return -EINVAL;
-	var.yoffset = simple_strtoul(last, &last, 0);
-
-	console_lock();
-	err = fb_pan_display(fb_info, &var);
-	console_unlock();
-
-	if (err < 0)
-		return err;
-	return count;
-}
-
-static ssize_t show_pan(struct device *device,
-			struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
-			fb_info->var.yoffset);
-}
-
-static ssize_t show_name(struct device *device,
-			 struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
-}
-
-static ssize_t store_fbstate(struct device *device,
-			     struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	u32 state;
-	char *last = NULL;
-
-	state = simple_strtoul(buf, &last, 0);
-
-	console_lock();
-	if (!lock_fb_info(fb_info)) {
-		console_unlock();
-		return -ENODEV;
-	}
-
-	fb_set_suspend(fb_info, (int)state);
-
-	unlock_fb_info(fb_info);
-	console_unlock();
-
-	return count;
-}
-
-static ssize_t show_fbstate(struct device *device,
-			    struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
-}
-
-#ifdef CONFIG_FB_BACKLIGHT
-static ssize_t store_bl_curve(struct device *device,
-			      struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	u8 tmp_curve[FB_BACKLIGHT_LEVELS];
-	unsigned int i;
-
-	/* Some drivers don't use framebuffer_alloc(), but those also
-	 * don't have backlights.
-	 */
-	if (!fb_info || !fb_info->bl_dev)
-		return -ENODEV;
-
-	if (count != (FB_BACKLIGHT_LEVELS / 8 * 24))
-		return -EINVAL;
-
-	for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i)
-		if (sscanf(&buf[i * 24],
-			"%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx\n",
-			&tmp_curve[i * 8 + 0],
-			&tmp_curve[i * 8 + 1],
-			&tmp_curve[i * 8 + 2],
-			&tmp_curve[i * 8 + 3],
-			&tmp_curve[i * 8 + 4],
-			&tmp_curve[i * 8 + 5],
-			&tmp_curve[i * 8 + 6],
-			&tmp_curve[i * 8 + 7]) != 8)
-			return -EINVAL;
-
-	/* If there has been an error in the input data, we won't
-	 * reach this loop.
-	 */
-	mutex_lock(&fb_info->bl_curve_mutex);
-	for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
-		fb_info->bl_curve[i] = tmp_curve[i];
-	mutex_unlock(&fb_info->bl_curve_mutex);
-
-	return count;
-}
-
-static ssize_t show_bl_curve(struct device *device,
-			     struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fb_info = dev_get_drvdata(device);
-	ssize_t len = 0;
-	unsigned int i;
-
-	/* Some drivers don't use framebuffer_alloc(), but those also
-	 * don't have backlights.
-	 */
-	if (!fb_info || !fb_info->bl_dev)
-		return -ENODEV;
-
-	mutex_lock(&fb_info->bl_curve_mutex);
-	for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
-		len += snprintf(&buf[len], PAGE_SIZE,
-				"%02x %02x %02x %02x %02x %02x %02x %02x\n",
-				fb_info->bl_curve[i + 0],
-				fb_info->bl_curve[i + 1],
-				fb_info->bl_curve[i + 2],
-				fb_info->bl_curve[i + 3],
-				fb_info->bl_curve[i + 4],
-				fb_info->bl_curve[i + 5],
-				fb_info->bl_curve[i + 6],
-				fb_info->bl_curve[i + 7]);
-	mutex_unlock(&fb_info->bl_curve_mutex);
-
-	return len;
-}
-#endif
-
-/* When cmap is added back in it should be a binary attribute
- * not a text one. Consideration should also be given to converting
- * fbdev to use configfs instead of sysfs */
-static struct device_attribute device_attrs[] = {
-	__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
-	__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
-	__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
-	__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
-	__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
-	__ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
-	__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
-	__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
-	__ATTR(name, S_IRUGO, show_name, NULL),
-	__ATTR(stride, S_IRUGO, show_stride, NULL),
-	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
-	__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
-#ifdef CONFIG_FB_BACKLIGHT
-	__ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
-#endif
-};
-
-int fb_init_device(struct fb_info *fb_info)
-{
-	int i, error = 0;
-
-	dev_set_drvdata(fb_info->dev, fb_info);
-
-	fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
-
-	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
-		error = device_create_file(fb_info->dev, &device_attrs[i]);
-
-		if (error)
-			break;
-	}
-
-	if (error) {
-		while (--i >= 0)
-			device_remove_file(fb_info->dev, &device_attrs[i]);
-		fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
-	}
-
-	return 0;
-}
-
-void fb_cleanup_device(struct fb_info *fb_info)
-{
-	unsigned int i;
-
-	if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
-		for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
-			device_remove_file(fb_info->dev, &device_attrs[i]);
-
-		fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
-	}
-}
-
-#ifdef CONFIG_FB_BACKLIGHT
-/* This function generates a linear backlight curve
- *
- *     0: off
- *   1-7: min
- * 8-127: linear from min to max
- */
-void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
-{
-	unsigned int i, flat, count, range = (max - min);
-
-	mutex_lock(&fb_info->bl_curve_mutex);
-
-	fb_info->bl_curve[0] = off;
-
-	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
-		fb_info->bl_curve[flat] = min;
-
-	count = FB_BACKLIGHT_LEVELS * 15 / 16;
-	for (i = 0; i < count; ++i)
-		fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
-
-	mutex_unlock(&fb_info->bl_curve_mutex);
-}
-EXPORT_SYMBOL_GPL(fb_bl_default_curve);
-#endif
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
deleted file mode 100644
index 4c4ffa61ae26..000000000000
--- a/drivers/video/ffb.c
+++ /dev/null
@@ -1,1081 +0,0 @@
-/* ffb.c: Creator/Elite3D frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/upa.h>
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			 unsigned, struct fb_info *);
-static int ffb_blank(int, struct fb_info *);
-
-static void ffb_imageblit(struct fb_info *, const struct fb_image *);
-static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
-static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
-static int ffb_sync(struct fb_info *);
-static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
-static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
-static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops ffb_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= ffb_setcolreg,
-	.fb_blank		= ffb_blank,
-	.fb_pan_display		= ffb_pan_display,
-	.fb_fillrect		= ffb_fillrect,
-	.fb_copyarea		= ffb_copyarea,
-	.fb_imageblit		= ffb_imageblit,
-	.fb_sync		= ffb_sync,
-	.fb_mmap		= ffb_mmap,
-	.fb_ioctl		= ffb_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-/* Register layout and definitions */
-#define	FFB_SFB8R_VOFF		0x00000000
-#define	FFB_SFB8G_VOFF		0x00400000
-#define	FFB_SFB8B_VOFF		0x00800000
-#define	FFB_SFB8X_VOFF		0x00c00000
-#define	FFB_SFB32_VOFF		0x01000000
-#define	FFB_SFB64_VOFF		0x02000000
-#define	FFB_FBC_REGS_VOFF	0x04000000
-#define	FFB_BM_FBC_REGS_VOFF	0x04002000
-#define	FFB_DFB8R_VOFF		0x04004000
-#define	FFB_DFB8G_VOFF		0x04404000
-#define	FFB_DFB8B_VOFF		0x04804000
-#define	FFB_DFB8X_VOFF		0x04c04000
-#define	FFB_DFB24_VOFF		0x05004000
-#define	FFB_DFB32_VOFF		0x06004000
-#define	FFB_DFB422A_VOFF	0x07004000	/* DFB 422 mode write to A */
-#define	FFB_DFB422AD_VOFF	0x07804000	/* DFB 422 mode with line doubling */
-#define	FFB_DFB24B_VOFF		0x08004000	/* DFB 24bit mode write to B */
-#define	FFB_DFB422B_VOFF	0x09004000	/* DFB 422 mode write to B */
-#define	FFB_DFB422BD_VOFF	0x09804000	/* DFB 422 mode with line doubling */
-#define	FFB_SFB16Z_VOFF		0x0a004000	/* 16bit mode Z planes */
-#define	FFB_SFB8Z_VOFF		0x0a404000	/* 8bit mode Z planes */
-#define	FFB_SFB422_VOFF		0x0ac04000	/* SFB 422 mode write to A/B */
-#define	FFB_SFB422D_VOFF	0x0b404000	/* SFB 422 mode with line doubling */
-#define	FFB_FBC_KREGS_VOFF	0x0bc04000
-#define	FFB_DAC_VOFF		0x0bc06000
-#define	FFB_PROM_VOFF		0x0bc08000
-#define	FFB_EXP_VOFF		0x0bc18000
-
-#define	FFB_SFB8R_POFF		0x04000000UL
-#define	FFB_SFB8G_POFF		0x04400000UL
-#define	FFB_SFB8B_POFF		0x04800000UL
-#define	FFB_SFB8X_POFF		0x04c00000UL
-#define	FFB_SFB32_POFF		0x05000000UL
-#define	FFB_SFB64_POFF		0x06000000UL
-#define	FFB_FBC_REGS_POFF	0x00600000UL
-#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
-#define	FFB_DFB8R_POFF		0x01000000UL
-#define	FFB_DFB8G_POFF		0x01400000UL
-#define	FFB_DFB8B_POFF		0x01800000UL
-#define	FFB_DFB8X_POFF		0x01c00000UL
-#define	FFB_DFB24_POFF		0x02000000UL
-#define	FFB_DFB32_POFF		0x03000000UL
-#define	FFB_FBC_KREGS_POFF	0x00610000UL
-#define	FFB_DAC_POFF		0x00400000UL
-#define	FFB_PROM_POFF		0x00000000UL
-#define	FFB_EXP_POFF		0x00200000UL
-#define FFB_DFB422A_POFF	0x09000000UL
-#define FFB_DFB422AD_POFF	0x09800000UL
-#define FFB_DFB24B_POFF		0x0a000000UL
-#define FFB_DFB422B_POFF	0x0b000000UL
-#define FFB_DFB422BD_POFF	0x0b800000UL
-#define FFB_SFB16Z_POFF		0x0c800000UL
-#define FFB_SFB8Z_POFF		0x0c000000UL
-#define FFB_SFB422_POFF		0x0d000000UL
-#define FFB_SFB422D_POFF	0x0d800000UL
-
-/* Draw operations */
-#define FFB_DRAWOP_DOT		0x00
-#define FFB_DRAWOP_AADOT	0x01
-#define FFB_DRAWOP_BRLINECAP	0x02
-#define FFB_DRAWOP_BRLINEOPEN	0x03
-#define FFB_DRAWOP_DDLINE	0x04
-#define FFB_DRAWOP_AALINE	0x05
-#define FFB_DRAWOP_TRIANGLE	0x06
-#define FFB_DRAWOP_POLYGON	0x07
-#define FFB_DRAWOP_RECTANGLE	0x08
-#define FFB_DRAWOP_FASTFILL	0x09
-#define FFB_DRAWOP_BCOPY	0x0a
-#define FFB_DRAWOP_VSCROLL	0x0b
-
-/* Pixel processor control */
-/* Force WID */
-#define FFB_PPC_FW_DISABLE	0x800000
-#define FFB_PPC_FW_ENABLE	0xc00000
-/* Auxiliary clip */
-#define FFB_PPC_ACE_DISABLE	0x040000
-#define FFB_PPC_ACE_AUX_SUB	0x080000
-#define FFB_PPC_ACE_AUX_ADD	0x0c0000
-/* Depth cue */
-#define FFB_PPC_DCE_DISABLE	0x020000
-#define FFB_PPC_DCE_ENABLE	0x030000
-/* Alpha blend */
-#define FFB_PPC_ABE_DISABLE	0x008000
-#define FFB_PPC_ABE_ENABLE	0x00c000
-/* View clip */
-#define FFB_PPC_VCE_DISABLE	0x001000
-#define FFB_PPC_VCE_2D		0x002000
-#define FFB_PPC_VCE_3D		0x003000
-/* Area pattern */
-#define FFB_PPC_APE_DISABLE	0x000800
-#define FFB_PPC_APE_ENABLE	0x000c00
-/* Transparent background */
-#define FFB_PPC_TBE_OPAQUE	0x000200
-#define FFB_PPC_TBE_TRANSPARENT	0x000300
-/* Z source */
-#define FFB_PPC_ZS_VAR		0x000080
-#define FFB_PPC_ZS_CONST	0x0000c0
-/* Y source */
-#define FFB_PPC_YS_VAR		0x000020
-#define FFB_PPC_YS_CONST	0x000030
-/* X source */
-#define FFB_PPC_XS_WID		0x000004
-#define FFB_PPC_XS_VAR		0x000008
-#define FFB_PPC_XS_CONST	0x00000c
-/* Color (BGR) source */
-#define FFB_PPC_CS_VAR		0x000002
-#define FFB_PPC_CS_CONST	0x000003
-
-#define FFB_ROP_NEW		0x83
-#define FFB_ROP_OLD		0x85
-#define FFB_ROP_NEW_XOR_OLD	0x86
-
-#define FFB_UCSR_FIFO_MASK	0x00000fff
-#define FFB_UCSR_FB_BUSY	0x01000000
-#define FFB_UCSR_RP_BUSY	0x02000000
-#define FFB_UCSR_ALL_BUSY	(FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
-#define FFB_UCSR_READ_ERR	0x40000000
-#define FFB_UCSR_FIFO_OVFL	0x80000000
-#define FFB_UCSR_ALL_ERRORS	(FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
-
-struct ffb_fbc {
-	/* Next vertex registers */
-	u32	xxx1[3];
-	u32	alpha;
-	u32	red;
-	u32	green;
-	u32	blue;
-	u32	depth;
-	u32	y;
-	u32	x;
-	u32	xxx2[2];
-	u32	ryf;
-	u32	rxf;
-	u32	xxx3[2];
-
-	u32	dmyf;
-	u32	dmxf;
-	u32	xxx4[2];
-	u32	ebyi;
-	u32	ebxi;
-	u32	xxx5[2];
-	u32	by;
-	u32	bx;
-	u32	dy;
-	u32	dx;
-	u32	bh;
-	u32	bw;
-	u32	xxx6[2];
-
-	u32	xxx7[32];
-
-	/* Setup unit vertex state register */
-	u32	suvtx;
-	u32	xxx8[63];
-
-	/* Control registers */
-	u32	ppc;
-	u32	wid;
-	u32	fg;
-	u32	bg;
-	u32	consty;
-	u32	constz;
-	u32	xclip;
-	u32	dcss;
-	u32	vclipmin;
-	u32	vclipmax;
-	u32	vclipzmin;
-	u32	vclipzmax;
-	u32	dcsf;
-	u32	dcsb;
-	u32	dczf;
-	u32	dczb;
-
-	u32	xxx9;
-	u32	blendc;
-	u32	blendc1;
-	u32	blendc2;
-	u32	fbramitc;
-	u32	fbc;
-	u32	rop;
-	u32	cmp;
-	u32	matchab;
-	u32	matchc;
-	u32	magnab;
-	u32	magnc;
-	u32	fbcfg0;
-	u32	fbcfg1;
-	u32	fbcfg2;
-	u32	fbcfg3;
-
-	u32	ppcfg;
-	u32	pick;
-	u32	fillmode;
-	u32	fbramwac;
-	u32	pmask;
-	u32	xpmask;
-	u32	ypmask;
-	u32	zpmask;
-	u32	clip0min;
-	u32	clip0max;
-	u32	clip1min;
-	u32	clip1max;
-	u32	clip2min;
-	u32	clip2max;
-	u32	clip3min;
-	u32	clip3max;
-
-	/* New 3dRAM III support regs */
-	u32	rawblend2;
-	u32	rawpreblend;
-	u32	rawstencil;
-	u32	rawstencilctl;
-	u32	threedram1;
-	u32	threedram2;
-	u32	passin;
-	u32	rawclrdepth;
-	u32	rawpmask;
-	u32	rawcsrc;
-	u32	rawmatch;
-	u32	rawmagn;
-	u32	rawropblend;
-	u32	rawcmp;
-	u32	rawwac;
-	u32	fbramid;
-
-	u32	drawop;
-	u32	xxx10[2];
-	u32	fontlpat;
-	u32	xxx11;
-	u32	fontxy;
-	u32	fontw;
-	u32	fontinc;
-	u32	font;
-	u32	xxx12[3];
-	u32	blend2;
-	u32	preblend;
-	u32	stencil;
-	u32	stencilctl;
-
-	u32	xxx13[4];
-	u32	dcss1;
-	u32	dcss2;
-	u32	dcss3;
-	u32	widpmask;
-	u32	dcs2;
-	u32	dcs3;
-	u32	dcs4;
-	u32	xxx14;
-	u32	dcd2;
-	u32	dcd3;
-	u32	dcd4;
-	u32	xxx15;
-
-	u32	pattern[32];
-
-	u32	xxx16[256];
-
-	u32	devid;
-	u32	xxx17[63];
-
-	u32	ucsr;
-	u32	xxx18[31];
-
-	u32	mer;
-};
-
-struct ffb_dac {
-	u32	type;
-	u32	value;
-	u32	type2;
-	u32	value2;
-};
-
-#define FFB_DAC_UCTRL		0x1001 /* User Control */
-#define FFB_DAC_UCTRL_MANREV	0x00000f00 /* 4-bit Manufacturing Revision */
-#define FFB_DAC_UCTRL_MANREV_SHIFT 8
-#define FFB_DAC_TGEN		0x6000 /* Timing Generator */
-#define FFB_DAC_TGEN_VIDE	0x00000001 /* Video Enable */
-#define FFB_DAC_DID		0x8000 /* Device Identification */
-#define FFB_DAC_DID_PNUM	0x0ffff000 /* Device Part Number */
-#define FFB_DAC_DID_PNUM_SHIFT	12
-#define FFB_DAC_DID_REV		0xf0000000 /* Device Revision */
-#define FFB_DAC_DID_REV_SHIFT	28
-
-#define FFB_DAC_CUR_CTRL	0x100
-#define FFB_DAC_CUR_CTRL_P0	0x00000001
-#define FFB_DAC_CUR_CTRL_P1	0x00000002
-
-struct ffb_par {
-	spinlock_t		lock;
-	struct ffb_fbc __iomem	*fbc;
-	struct ffb_dac __iomem	*dac;
-
-	u32			flags;
-#define FFB_FLAG_AFB		0x00000001 /* AFB m3 or m6 */
-#define FFB_FLAG_BLANKED	0x00000002 /* screen is blanked */
-#define FFB_FLAG_INVCURSOR	0x00000004 /* DAC has inverted cursor logic */
-
-	u32			fg_cache __attribute__((aligned (8)));
-	u32			bg_cache;
-	u32			rop_cache;
-
-	int			fifo_cache;
-
-	unsigned long		physbase;
-	unsigned long		fbsize;
-
-	int			board_type;
-
-	u32			pseudo_palette[16];
-};
-
-static void FFBFifo(struct ffb_par *par, int n)
-{
-	struct ffb_fbc __iomem *fbc;
-	int cache = par->fifo_cache;
-
-	if (cache - n < 0) {
-		fbc = par->fbc;
-		do {
-			cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK);
-			cache -= 8;
-		} while (cache - n < 0);
-	}
-	par->fifo_cache = cache - n;
-}
-
-static void FFBWait(struct ffb_par *par)
-{
-	struct ffb_fbc __iomem *fbc;
-	int limit = 10000;
-
-	fbc = par->fbc;
-	do {
-		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
-			break;
-		if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
-			upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
-		}
-		udelay(10);
-	} while (--limit > 0);
-}
-
-static int ffb_sync(struct fb_info *p)
-{
-	struct ffb_par *par = (struct ffb_par *)p->par;
-
-	FFBWait(par);
-	return 0;
-}
-
-static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
-{
-	if (par->rop_cache != rop) {
-		FFBFifo(par, 1);
-		upa_writel(rop, &par->fbc->rop);
-		par->rop_cache = rop;
-	}
-}
-
-static void ffb_switch_from_graph(struct ffb_par *par)
-{
-	struct ffb_fbc __iomem *fbc = par->fbc;
-	struct ffb_dac __iomem *dac = par->dac;
-	unsigned long flags;
-
-	spin_lock_irqsave(&par->lock, flags);
-	FFBWait(par);
-	par->fifo_cache = 0;
-	FFBFifo(par, 7);
-	upa_writel(FFB_PPC_VCE_DISABLE | FFB_PPC_TBE_OPAQUE |
-		   FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
-		   &fbc->ppc);
-	upa_writel(0x2000707f, &fbc->fbc);
-	upa_writel(par->rop_cache, &fbc->rop);
-	upa_writel(0xffffffff, &fbc->pmask);
-	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
-	upa_writel(par->fg_cache, &fbc->fg);
-	upa_writel(par->bg_cache, &fbc->bg);
-	FFBWait(par);
-
-	/* Disable cursor.  */
-	upa_writel(FFB_DAC_CUR_CTRL, &dac->type2);
-	if (par->flags & FFB_FLAG_INVCURSOR)
-		upa_writel(0, &dac->value2);
-	else
-		upa_writel((FFB_DAC_CUR_CTRL_P0 |
-			    FFB_DAC_CUR_CTRL_P1), &dac->value2);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-
-	/* We just use this to catch switches out of
-	 * graphics mode.
-	 */
-	ffb_switch_from_graph(par);
-
-	if (var->xoffset || var->yoffset || var->vmode)
-		return -EINVAL;
-	return 0;
-}
-
-/**
- *	ffb_fillrect - Draws a rectangle on the screen.
- *
- *	@info: frame buffer structure that represents a single frame buffer
- *	@rect: structure defining the rectagle and operation.
- */
-static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-	struct ffb_fbc __iomem *fbc = par->fbc;
-	unsigned long flags;
-	u32 fg;
-
-	BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
-
-	fg = ((u32 *)info->pseudo_palette)[rect->color];
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	if (fg != par->fg_cache) {
-		FFBFifo(par, 1);
-		upa_writel(fg, &fbc->fg);
-		par->fg_cache = fg;
-	}
-
-	ffb_rop(par, rect->rop == ROP_COPY ?
-		     FFB_ROP_NEW :
-		     FFB_ROP_NEW_XOR_OLD);
-
-	FFBFifo(par, 5);
-	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
-	upa_writel(rect->dy, &fbc->by);
-	upa_writel(rect->dx, &fbc->bx);
-	upa_writel(rect->height, &fbc->bh);
-	upa_writel(rect->width, &fbc->bw);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-/**
- *	ffb_copyarea - Copies on area of the screen to another area.
- *
- *	@info: frame buffer structure that represents a single frame buffer
- *	@area: structure defining the source and destination.
- */
-
-static void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-	struct ffb_fbc __iomem *fbc = par->fbc;
-	unsigned long flags;
-
-	if (area->dx != area->sx ||
-	    area->dy == area->sy) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	ffb_rop(par, FFB_ROP_OLD);
-
-	FFBFifo(par, 7);
-	upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
-	upa_writel(area->sy, &fbc->by);
-	upa_writel(area->sx, &fbc->bx);
-	upa_writel(area->dy, &fbc->dy);
-	upa_writel(area->dx, &fbc->dx);
-	upa_writel(area->height, &fbc->bh);
-	upa_writel(area->width, &fbc->bw);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-/**
- *	ffb_imageblit - Copies a image from system memory to the screen.
- *
- *	@info: frame buffer structure that represents a single frame buffer
- *	@image: structure defining the image.
- */
-static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-	struct ffb_fbc __iomem *fbc = par->fbc;
-	const u8 *data = image->data;
-	unsigned long flags;
-	u32 fg, bg, xy;
-	u64 fgbg;
-	int i, width, stride;
-
-	if (image->depth > 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	fg = ((u32 *)info->pseudo_palette)[image->fg_color];
-	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
-	fgbg = ((u64) fg << 32) | (u64) bg;
-	xy = (image->dy << 16) | image->dx;
-	width = image->width;
-	stride = ((width + 7) >> 3);
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	if (fgbg != *(u64 *)&par->fg_cache) {
-		FFBFifo(par, 2);
-		upa_writeq(fgbg, &fbc->fg);
-		*(u64 *)&par->fg_cache = fgbg;
-	}
-
-	if (width >= 32) {
-		FFBFifo(par, 1);
-		upa_writel(32, &fbc->fontw);
-	}
-
-	while (width >= 32) {
-		const u8 *next_data = data + 4;
-
-		FFBFifo(par, 1);
-		upa_writel(xy, &fbc->fontxy);
-		xy += (32 << 0);
-
-		for (i = 0; i < image->height; i++) {
-			u32 val = (((u32)data[0] << 24) |
-				   ((u32)data[1] << 16) |
-				   ((u32)data[2] <<  8) |
-				   ((u32)data[3] <<  0));
-			FFBFifo(par, 1);
-			upa_writel(val, &fbc->font);
-
-			data += stride;
-		}
-
-		data = next_data;
-		width -= 32;
-	}
-
-	if (width) {
-		FFBFifo(par, 2);
-		upa_writel(width, &fbc->fontw);
-		upa_writel(xy, &fbc->fontxy);
-
-		for (i = 0; i < image->height; i++) {
-			u32 val = (((u32)data[0] << 24) |
-				   ((u32)data[1] << 16) |
-				   ((u32)data[2] <<  8) |
-				   ((u32)data[3] <<  0));
-			FFBFifo(par, 1);
-			upa_writel(val, &fbc->font);
-
-			data += stride;
-		}
-	}
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
-{
-	var->red.offset = 0;
-	var->red.length = 8;
-	var->green.offset = 8;
-	var->green.length = 8;
-	var->blue.offset = 16;
-	var->blue.length = 8;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-}
-
-/**
- *	ffb_setcolreg - Sets a color register.
- *
- *	@regno: boolean, 0 copy local, 1 get_user() function
- *	@red: frame buffer colormap structure
- *	@green: The green value which can be up to 16 bits wide
- *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.
- *	@info: frame buffer info structure
- */
-static int ffb_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	u32 value;
-
-	if (regno >= 16)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	value = (blue << 16) | (green << 8) | red;
-	((u32 *)info->pseudo_palette)[regno] = value;
-
-	return 0;
-}
-
-/**
- *	ffb_blank - Optional function.  Blanks the display.
- *	@blank_mode: the blank mode we want.
- *	@info: frame buffer structure that represents a single frame buffer
- */
-static int ffb_blank(int blank, struct fb_info *info)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-	struct ffb_dac __iomem *dac = par->dac;
-	unsigned long flags;
-	u32 val;
-	int i;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	FFBWait(par);
-
-	upa_writel(FFB_DAC_TGEN, &dac->type);
-	val = upa_readl(&dac->value);
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		val |= FFB_DAC_TGEN_VIDE;
-		par->flags &= ~FFB_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		val &= ~FFB_DAC_TGEN_VIDE;
-		par->flags |= FFB_FLAG_BLANKED;
-		break;
-	}
-	upa_writel(FFB_DAC_TGEN, &dac->type);
-	upa_writel(val, &dac->value);
-	for (i = 0; i < 10; i++) {
-		upa_writel(FFB_DAC_TGEN, &dac->type);
-		upa_readl(&dac->value);
-	}
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static struct sbus_mmap_map ffb_mmap_map[] = {
-	{
-		.voff	= FFB_SFB8R_VOFF,
-		.poff	= FFB_SFB8R_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_SFB8G_VOFF,
-		.poff	= FFB_SFB8G_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_SFB8B_VOFF,
-		.poff	= FFB_SFB8B_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_SFB8X_VOFF,
-		.poff	= FFB_SFB8X_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_SFB32_VOFF,
-		.poff	= FFB_SFB32_POFF,
-		.size	= 0x1000000
-	},
-	{
-		.voff	= FFB_SFB64_VOFF,
-		.poff	= FFB_SFB64_POFF,
-		.size	= 0x2000000
-	},
-	{
-		.voff	= FFB_FBC_REGS_VOFF,
-		.poff	= FFB_FBC_REGS_POFF,
-		.size	= 0x0002000
-	},
-	{
-		.voff	= FFB_BM_FBC_REGS_VOFF,
-		.poff	= FFB_BM_FBC_REGS_POFF,
-		.size	= 0x0002000
-	},
-	{
-		.voff	= FFB_DFB8R_VOFF,
-		.poff	= FFB_DFB8R_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_DFB8G_VOFF,
-		.poff	= FFB_DFB8G_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_DFB8B_VOFF,
-		.poff	= FFB_DFB8B_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_DFB8X_VOFF,
-		.poff	= FFB_DFB8X_POFF,
-		.size	= 0x0400000
-	},
-	{
-		.voff	= FFB_DFB24_VOFF,
-		.poff	= FFB_DFB24_POFF,
-		.size	= 0x1000000
-	},
-	{
-		.voff	= FFB_DFB32_VOFF,
-		.poff	= FFB_DFB32_POFF,
-		.size	= 0x1000000
-	},
-	{
-		.voff	= FFB_FBC_KREGS_VOFF,
-		.poff	= FFB_FBC_KREGS_POFF,
-		.size	= 0x0002000
-	},
-	{
-		.voff	= FFB_DAC_VOFF,
-		.poff	= FFB_DAC_POFF,
-		.size	= 0x0002000
-	},
-	{
-		.voff	= FFB_PROM_VOFF,
-		.poff	= FFB_PROM_POFF,
-		.size	= 0x0010000
-	},
-	{
-		.voff	= FFB_EXP_VOFF,
-		.poff	= FFB_EXP_POFF,
-		.size	= 0x0002000
-	},
-	{
-		.voff	= FFB_DFB422A_VOFF,
-		.poff	= FFB_DFB422A_POFF,
-		.size	= 0x0800000
-	},
-	{
-		.voff	= FFB_DFB422AD_VOFF,
-		.poff	= FFB_DFB422AD_POFF,
-		.size	= 0x0800000
-	},
-	{
-		.voff	= FFB_DFB24B_VOFF,
-		.poff	= FFB_DFB24B_POFF,
-		.size	= 0x1000000
-	},
-	{
-		.voff	= FFB_DFB422B_VOFF,
-		.poff	= FFB_DFB422B_POFF,
-		.size	= 0x0800000
-	},
-	{
-		.voff	= FFB_DFB422BD_VOFF,
-		.poff	= FFB_DFB422BD_POFF,
-		.size	= 0x0800000
-	},
-	{
-		.voff	= FFB_SFB16Z_VOFF,
-		.poff	= FFB_SFB16Z_POFF,
-		.size	= 0x0800000
-	},
-	{
-		.voff	= FFB_SFB8Z_VOFF,
-		.poff	= FFB_SFB8Z_POFF,
-		.size	= 0x0800000
-	},
-	{
-		.voff	= FFB_SFB422_VOFF,
-		.poff	= FFB_SFB422_POFF,
-		.size	= 0x0800000
-	},
-	{
-		.voff	= FFB_SFB422D_VOFF,
-		.poff	= FFB_SFB422D_POFF,
-		.size	= 0x0800000
-	},
-	{ .size = 0 }
-};
-
-static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-
-	return sbusfb_mmap_helper(ffb_mmap_map,
-				  par->physbase, par->fbsize,
-				  0, vma);
-}
-
-static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-
-	return sbusfb_ioctl_helper(cmd, arg, info,
-				   FBTYPE_CREATOR, 24, par->fbsize);
-}
-
-/*
- *  Initialisation
- */
-
-static void ffb_init_fix(struct fb_info *info)
-{
-	struct ffb_par *par = (struct ffb_par *)info->par;
-	const char *ffb_type_name;
-
-	if (!(par->flags & FFB_FLAG_AFB)) {
-		if ((par->board_type & 0x7) == 0x3)
-			ffb_type_name = "Creator 3D";
-		else
-			ffb_type_name = "Creator";
-	} else
-		ffb_type_name = "Elite 3D";
-
-	strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	/* Framebuffer length is the same regardless of resolution. */
-	info->fix.line_length = 8192;
-
-	info->fix.accel = FB_ACCEL_SUN_CREATOR;
-}
-
-static int ffb_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct ffb_fbc __iomem *fbc;
-	struct ffb_dac __iomem *dac;
-	struct fb_info *info;
-	struct ffb_par *par;
-	u32 dac_pnum, dac_rev, dac_mrev;
-	int err;
-
-	info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-	par->fbc = of_ioremap(&op->resource[2], 0,
-			      sizeof(struct ffb_fbc), "ffb fbc");
-	if (!par->fbc)
-		goto out_release_fb;
-
-	par->dac = of_ioremap(&op->resource[1], 0,
-			      sizeof(struct ffb_dac), "ffb dac");
-	if (!par->dac)
-		goto out_unmap_fbc;
-
-	par->rop_cache = FFB_ROP_NEW;
-	par->physbase = op->resource[0].start;
-
-	/* Don't mention copyarea, so SCROLL_REDRAW is always
-	 * used.  It is the fastest on this chip.
-	 */
-	info->flags = (FBINFO_DEFAULT |
-		       /* FBINFO_HWACCEL_COPYAREA | */
-		       FBINFO_HWACCEL_FILLRECT |
-		       FBINFO_HWACCEL_IMAGEBLIT);
-
-	info->fbops = &ffb_ops;
-
-	info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
-	info->pseudo_palette = par->pseudo_palette;
-
-	sbusfb_fill_var(&info->var, dp, 32);
-	par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
-	ffb_fixup_var_rgb(&info->var);
-
-	info->var.accel_flags = FB_ACCELF_TEXT;
-
-	if (!strcmp(dp->name, "SUNW,afb"))
-		par->flags |= FFB_FLAG_AFB;
-
-	par->board_type = of_getintprop_default(dp, "board_type", 0);
-
-	fbc = par->fbc;
-	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
-		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
-
-	dac = par->dac;
-	upa_writel(FFB_DAC_DID, &dac->type);
-	dac_pnum = upa_readl(&dac->value);
-	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
-	dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;
-
-	upa_writel(FFB_DAC_UCTRL, &dac->type);
-	dac_mrev = upa_readl(&dac->value);
-	dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>
-		FFB_DAC_UCTRL_MANREV_SHIFT;
-
-	/* Elite3D has different DAC revision numbering, and no DAC revisions
-	 * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1
-	 * ramdacs with manufacturing revision less than 3 have inverted
-	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
-	 * latter having a part number value of 0x236e.
-	 */
-	if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
-		par->flags &= ~FFB_FLAG_INVCURSOR;
-	} else {
-		if (dac_mrev < 3)
-			par->flags |= FFB_FLAG_INVCURSOR;
-	}
-
-	ffb_switch_from_graph(par);
-
-	/* Unblank it just to be sure.  When there are multiple
-	 * FFB/AFB cards in the system, or it is not the OBP
-	 * chosen console, it will have video outputs off in
-	 * the DAC.
-	 */
-	ffb_blank(FB_BLANK_UNBLANK, info);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0))
-		goto out_unmap_dac;
-
-	ffb_init_fix(info);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_dealloc_cmap;
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: %s at %016lx, type %d, "
-	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
-	       dp->full_name,
-	       ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
-	       par->physbase, par->board_type,
-	       dac_pnum, dac_rev, dac_mrev);
-
-	return 0;
-
-out_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-out_unmap_dac:
-	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
-
-out_unmap_fbc:
-	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
-
-out_release_fb:
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int ffb_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct ffb_par *par = info->par;
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
-	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id ffb_match[] = {
-	{
-		.name = "SUNW,ffb",
-	},
-	{
-		.name = "SUNW,afb",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, ffb_match);
-
-static struct platform_driver ffb_driver = {
-	.driver = {
-		.name = "ffb",
-		.owner = THIS_MODULE,
-		.of_match_table = ffb_match,
-	},
-	.probe		= ffb_probe,
-	.remove		= ffb_remove,
-};
-
-static int __init ffb_init(void)
-{
-	if (fb_get_options("ffb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&ffb_driver);
-}
-
-static void __exit ffb_exit(void)
-{
-	platform_driver_unregister(&ffb_driver);
-}
-
-module_init(ffb_init);
-module_exit(ffb_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
deleted file mode 100644
index e69d47af9932..000000000000
--- a/drivers/video/fm2fb.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- *  linux/drivers/video/fm2fb.c -- BSC FrameMaster II/Rainbow II frame buffer
- *				   device
- *
- *	Copyright (C) 1998 Steffen A. Mork (linux-dev@morknet.de)
- *	Copyright (C) 1999 Geert Uytterhoeven
- *
- *  Written for 2.0.x by Steffen A. Mork
- *  Ported to 2.1.x by Geert Uytterhoeven
- *  Ported to new api by James Simmons
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/zorro.h>
-#include <asm/io.h>
-
-/*
- *	Some technical notes:
- *
- *	The BSC FrameMaster II (or Rainbow II) is a simple very dumb
- *	frame buffer which allows to display 24 bit true color images.
- *	Each pixel is 32 bit width so it's very easy to maintain the
- *	frame buffer. One long word has the following layout:
- *	AARRGGBB which means: AA the alpha channel byte, RR the red
- *	channel, GG the green channel and BB the blue channel.
- *
- *	The FrameMaster II supports the following video modes.
- *	- PAL/NTSC
- *	- interlaced/non interlaced
- *	- composite sync/sync/sync over green
- *
- *	The resolution is to the following both ones:
- *	- 768x576 (PAL)
- *	- 768x480 (NTSC)
- *
- *	This means that pixel access per line is fixed due to the
- *	fixed line width. In case of maximal resolution the frame
- *	buffer needs an amount of memory of 1.769.472 bytes which
- *	is near to 2 MByte (the allocated address space of Zorro2).
- *	The memory is channel interleaved. That means every channel
- *	owns four VRAMs. Unfortunately most FrameMasters II are
- *	not assembled with memory for the alpha channel. In this
- *	case it could be possible to add the frame buffer into the
- *	normal memory pool.
- *
- *	At relative address 0x1ffff8 of the frame buffers base address
- *	there exists a control register with the number of
- *	four control bits. They have the following meaning:
- *	bit value meaning
- *
- *	 0    1   0=interlaced/1=non interlaced
- *	 1    2   0=video out disabled/1=video out enabled
- *	 2    4   0=normal mode as jumpered via JP8/1=complement mode
- *	 3    8   0=read  onboard ROM/1 normal operation (required)
- *
- *	As mentioned above there are several jumper. I think there
- *	is not very much information about the FrameMaster II in
- *	the world so I add these information for completeness.
- *
- *	JP1  interlace selection (1-2 non interlaced/2-3 interlaced)
- *	JP2  wait state creation (leave as is!)
- *	JP3  wait state creation (leave as is!)
- *	JP4  modulate composite sync on green output (1-2 composite
- *	     sync on green channel/2-3 normal composite sync)
- *	JP5  create test signal, shorting this jumper will create
- *	     a white screen
- *	JP6  sync creation (1-2 composite sync/2-3 H-sync output)
- *	JP8  video mode (1-2 PAL/2-3 NTSC)
- *
- *	With the following jumpering table you can connect the
- *	FrameMaster II to a normal TV via SCART connector:
- *	JP1:  2-3
- *	JP4:  2-3
- *	JP6:  2-3
- *	JP8:  1-2 (means PAL for Europe)
- *
- *	NOTE:
- *	There is no other possibility to change the video timings
- *	except the interlaced/non interlaced, sync control and the
- *	video mode PAL (50 Hz)/NTSC (60 Hz). Inside this
- *	FrameMaster II driver are assumed values to avoid anomalies
- *	to a future X server. Except the pixel clock is really
- *	constant at 30 MHz.
- *
- *	9 pin female video connector:
- *
- *	1  analog red 0.7 Vss
- *	2  analog green 0.7 Vss
- *	3  analog blue 0.7 Vss
- *	4  H-sync TTL
- *	5  V-sync TTL
- *	6  ground
- *	7  ground
- *	8  ground
- *	9  ground
- *
- *	Some performance notes:
- *	The FrameMaster II was not designed to display a console
- *	this driver would do! It was designed to display still true
- *	color images. Imagine: When scroll up a text line there
- *	must copied ca. 1.7 MBytes to another place inside this
- *	frame buffer. This means 1.7 MByte read and 1.7 MByte write
- *	over the slow 16 bit wide Zorro2 bus! A scroll of one
- *	line needs 1 second so do not expect to much from this
- *	driver - he is at the limit!
- *
- */
-
-/*
- *	definitions
- */
-
-#define FRAMEMASTER_SIZE	0x200000
-#define FRAMEMASTER_REG		0x1ffff8
-
-#define FRAMEMASTER_NOLACE	1
-#define FRAMEMASTER_ENABLE	2
-#define FRAMEMASTER_COMPL	4
-#define FRAMEMASTER_ROM		8
-
-static volatile unsigned char *fm2fb_reg;
-
-static struct fb_fix_screeninfo fb_fix = {
-	.smem_len =	FRAMEMASTER_REG,
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.line_length =	(768 << 2),
-	.mmio_len =	(8),
-	.accel =	FB_ACCEL_NONE,
-};
-
-static int fm2fb_mode = -1;
-
-#define FM2FB_MODE_PAL	0
-#define FM2FB_MODE_NTSC	1
-
-static struct fb_var_screeninfo fb_var_modes[] = {
-    {
-	/* 768 x 576, 32 bpp (PAL) */
-	768, 576, 768, 576, 0, 0, 32, 0,
-	{ 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
-	0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
-	33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
-    }, {
-	/* 768 x 480, 32 bpp (NTSC - not supported yet */
-	768, 480, 768, 480, 0, 0, 32, 0,
-	{ 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
-	0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
-	33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
-    }
-};
-
-    /*
-     *  Interface used by the world
-     */
-
-static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                           u_int transp, struct fb_info *info);
-static int fm2fb_blank(int blank, struct fb_info *info);
-
-static struct fb_ops fm2fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= fm2fb_setcolreg,
-	.fb_blank	= fm2fb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-    /*
-     *  Blank the display.
-     */
-static int fm2fb_blank(int blank, struct fb_info *info)
-{
-	unsigned char t = FRAMEMASTER_ROM;
-
-	if (!blank)
-		t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE;
-	fm2fb_reg[0] = t;
-	return 0;
-}
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                         u_int transp, struct fb_info *info)
-{
-	if (regno < 16) {
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-
-		((u32*)(info->pseudo_palette))[regno] = (red << 16) |
-			(green << 8) | blue;
-	}
-
-	return 0;
-}
-
-    /*
-     *  Initialisation
-     */
-
-static int fm2fb_probe(struct zorro_dev *z, const struct zorro_device_id *id);
-
-static struct zorro_device_id fm2fb_devices[] = {
-	{ ZORRO_PROD_BSC_FRAMEMASTER_II },
-	{ ZORRO_PROD_HELFRICH_RAINBOW_II },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(zorro, fm2fb_devices);
-
-static struct zorro_driver fm2fb_driver = {
-	.name		= "fm2fb",
-	.id_table	= fm2fb_devices,
-	.probe		= fm2fb_probe,
-};
-
-static int fm2fb_probe(struct zorro_dev *z, const struct zorro_device_id *id)
-{
-	struct fb_info *info;
-	unsigned long *ptr;
-	int is_fm;
-	int x, y;
-
-	is_fm = z->id == ZORRO_PROD_BSC_FRAMEMASTER_II;
-
-	if (!zorro_request_device(z,"fm2fb"))
-		return -ENXIO;
-
-	info = framebuffer_alloc(16 * sizeof(u32), &z->dev);
-	if (!info) {
-		zorro_release_device(z);
-		return -ENOMEM;
-	}
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		framebuffer_release(info);
-		zorro_release_device(z);
-		return -ENOMEM;
-	}
-
-	/* assigning memory to kernel space */
-	fb_fix.smem_start = zorro_resource_start(z);
-	info->screen_base = ioremap(fb_fix.smem_start, FRAMEMASTER_SIZE);
-	fb_fix.mmio_start = fb_fix.smem_start + FRAMEMASTER_REG;
-	fm2fb_reg  = (unsigned char *)(info->screen_base+FRAMEMASTER_REG);
-
-	strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II");
-
-	/* make EBU color bars on display */
-	ptr = (unsigned long *)fb_fix.smem_start;
-	for (y = 0; y < 576; y++) {
-		for (x = 0; x < 96; x++) *ptr++ = 0xffffff;/* white */
-		for (x = 0; x < 96; x++) *ptr++ = 0xffff00;/* yellow */
-		for (x = 0; x < 96; x++) *ptr++ = 0x00ffff;/* cyan */
-		for (x = 0; x < 96; x++) *ptr++ = 0x00ff00;/* green */
-		for (x = 0; x < 96; x++) *ptr++ = 0xff00ff;/* magenta */
-		for (x = 0; x < 96; x++) *ptr++ = 0xff0000;/* red */
-		for (x = 0; x < 96; x++) *ptr++ = 0x0000ff;/* blue */
-		for (x = 0; x < 96; x++) *ptr++ = 0x000000;/* black */
-	}
-	fm2fb_blank(0, info);
-
-	if (fm2fb_mode == -1)
-		fm2fb_mode = FM2FB_MODE_PAL;
-
-	info->fbops = &fm2fb_ops;
-	info->var = fb_var_modes[fm2fb_mode];
-	info->pseudo_palette = info->par;
-	info->par = NULL;
-	info->fix = fb_fix;
-	info->flags = FBINFO_DEFAULT;
-
-	if (register_framebuffer(info) < 0) {
-		fb_dealloc_cmap(&info->cmap);
-		iounmap(info->screen_base);
-		framebuffer_release(info);
-		zorro_release_device(z);
-		return -EINVAL;
-	}
-	fb_info(info, "%s frame buffer device\n", fb_fix.id);
-	return 0;
-}
-
-int __init fm2fb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "pal", 3))
-			fm2fb_mode = FM2FB_MODE_PAL;
-		else if (!strncmp(this_opt, "ntsc", 4))
-			fm2fb_mode = FM2FB_MODE_NTSC;
-	}
-	return 0;
-}
-
-int __init fm2fb_init(void)
-{
-	char *option = NULL;
-
-	if (fb_get_options("fm2fb", &option))
-		return -ENODEV;
-	fm2fb_setup(option);
-	return zorro_register_driver(&fm2fb_driver);
-}
-
-module_init(fm2fb_init);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
deleted file mode 100644
index e8758b9c3bcc..000000000000
--- a/drivers/video/fsl-diu-fb.c
+++ /dev/null
@@ -1,1994 +0,0 @@
-/*
- * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- *  Freescale DIU Frame Buffer device driver
- *
- *  Authors: Hongjun Chen <hong-jun.chen@freescale.com>
- *           Paul Widmer <paul.widmer@freescale.com>
- *           Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
- *           York Sun <yorksun@freescale.com>
- *
- *   Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/spinlock.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-
-#include <sysdev/fsl_soc.h>
-#include <linux/fsl-diu-fb.h>
-#include "edid.h"
-
-#define NUM_AOIS	5	/* 1 for plane 0, 2 for planes 1 & 2 each */
-
-/* HW cursor parameters */
-#define MAX_CURS		32
-
-/* INT_STATUS/INT_MASK field descriptions */
-#define INT_VSYNC	0x01	/* Vsync interrupt  */
-#define INT_VSYNC_WB	0x02	/* Vsync interrupt for write back operation */
-#define INT_UNDRUN	0x04	/* Under run exception interrupt */
-#define INT_PARERR	0x08	/* Display parameters error interrupt */
-#define INT_LS_BF_VS	0x10	/* Lines before vsync. interrupt */
-
-/*
- * List of supported video modes
- *
- * The first entry is the default video mode.  The remain entries are in
- * order if increasing resolution and frequency.  The 320x240-60 mode is
- * the initial AOI for the second and third planes.
- */
-static struct fb_videomode fsl_diu_mode_db[] = {
-	{
-		.refresh	= 60,
-		.xres		= 1024,
-		.yres		= 768,
-		.pixclock	= 15385,
-		.left_margin	= 160,
-		.right_margin	= 24,
-		.upper_margin	= 29,
-		.lower_margin	= 3,
-		.hsync_len	= 136,
-		.vsync_len	= 6,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 60,
-		.xres		= 320,
-		.yres		= 240,
-		.pixclock	= 79440,
-		.left_margin	= 16,
-		.right_margin	= 16,
-		.upper_margin	= 16,
-		.lower_margin	= 5,
-		.hsync_len	= 48,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh        = 60,
-		.xres           = 640,
-		.yres           = 480,
-		.pixclock       = 39722,
-		.left_margin    = 48,
-		.right_margin   = 16,
-		.upper_margin   = 33,
-		.lower_margin   = 10,
-		.hsync_len      = 96,
-		.vsync_len      = 2,
-		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode          = FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh        = 72,
-		.xres           = 640,
-		.yres           = 480,
-		.pixclock       = 32052,
-		.left_margin    = 128,
-		.right_margin   = 24,
-		.upper_margin   = 28,
-		.lower_margin   = 9,
-		.hsync_len      = 40,
-		.vsync_len      = 3,
-		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode          = FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh        = 75,
-		.xres           = 640,
-		.yres           = 480,
-		.pixclock       = 31747,
-		.left_margin    = 120,
-		.right_margin   = 16,
-		.upper_margin   = 16,
-		.lower_margin   = 1,
-		.hsync_len      = 64,
-		.vsync_len      = 3,
-		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode          = FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh        = 90,
-		.xres           = 640,
-		.yres           = 480,
-		.pixclock       = 25057,
-		.left_margin    = 120,
-		.right_margin   = 32,
-		.upper_margin   = 14,
-		.lower_margin   = 25,
-		.hsync_len      = 40,
-		.vsync_len      = 14,
-		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode          = FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh        = 100,
-		.xres           = 640,
-		.yres           = 480,
-		.pixclock       = 22272,
-		.left_margin    = 48,
-		.right_margin   = 32,
-		.upper_margin   = 17,
-		.lower_margin   = 22,
-		.hsync_len      = 128,
-		.vsync_len      = 12,
-		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode          = FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 60,
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= 33805,
-		.left_margin	= 96,
-		.right_margin	= 24,
-		.upper_margin	= 10,
-		.lower_margin	= 3,
-		.hsync_len	= 72,
-		.vsync_len	= 7,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh        = 60,
-		.xres           = 800,
-		.yres           = 600,
-		.pixclock       = 25000,
-		.left_margin    = 88,
-		.right_margin   = 40,
-		.upper_margin   = 23,
-		.lower_margin   = 1,
-		.hsync_len      = 128,
-		.vsync_len      = 4,
-		.sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode          = FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 60,
-		.xres		= 854,
-		.yres		= 480,
-		.pixclock	= 31518,
-		.left_margin	= 104,
-		.right_margin	= 16,
-		.upper_margin	= 13,
-		.lower_margin	= 1,
-		.hsync_len	= 88,
-		.vsync_len	= 3,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 70,
-		.xres		= 1024,
-		.yres		= 768,
-		.pixclock	= 16886,
-		.left_margin	= 3,
-		.right_margin	= 3,
-		.upper_margin	= 2,
-		.lower_margin	= 2,
-		.hsync_len	= 40,
-		.vsync_len	= 18,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 75,
-		.xres		= 1024,
-		.yres		= 768,
-		.pixclock	= 15009,
-		.left_margin	= 3,
-		.right_margin	= 3,
-		.upper_margin	= 2,
-		.lower_margin	= 2,
-		.hsync_len	= 80,
-		.vsync_len	= 32,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 60,
-		.xres		= 1280,
-		.yres		= 480,
-		.pixclock	= 18939,
-		.left_margin	= 353,
-		.right_margin	= 47,
-		.upper_margin	= 39,
-		.lower_margin	= 4,
-		.hsync_len	= 8,
-		.vsync_len	= 2,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 60,
-		.xres		= 1280,
-		.yres		= 720,
-		.pixclock	= 13426,
-		.left_margin	= 192,
-		.right_margin	= 64,
-		.upper_margin	= 22,
-		.lower_margin	= 1,
-		.hsync_len	= 136,
-		.vsync_len	= 3,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 60,
-		.xres		= 1280,
-		.yres		= 1024,
-		.pixclock	= 9375,
-		.left_margin	= 38,
-		.right_margin	= 128,
-		.upper_margin	= 2,
-		.lower_margin	= 7,
-		.hsync_len	= 216,
-		.vsync_len	= 37,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 70,
-		.xres		= 1280,
-		.yres		= 1024,
-		.pixclock	= 9380,
-		.left_margin	= 6,
-		.right_margin	= 6,
-		.upper_margin	= 4,
-		.lower_margin	= 4,
-		.hsync_len	= 60,
-		.vsync_len	= 94,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 75,
-		.xres		= 1280,
-		.yres		= 1024,
-		.pixclock	= 9380,
-		.left_margin	= 6,
-		.right_margin	= 6,
-		.upper_margin	= 4,
-		.lower_margin	= 4,
-		.hsync_len	= 60,
-		.vsync_len	= 15,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-	{
-		.refresh	= 60,
-		.xres		= 1920,
-		.yres		= 1080,
-		.pixclock	= 5787,
-		.left_margin	= 328,
-		.right_margin	= 120,
-		.upper_margin	= 34,
-		.lower_margin	= 1,
-		.hsync_len	= 208,
-		.vsync_len	= 3,
-		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED
-	},
-};
-
-static char *fb_mode;
-static unsigned long default_bpp = 32;
-static enum fsl_diu_monitor_port monitor_port;
-static char *monitor_string;
-
-#if defined(CONFIG_NOT_COHERENT_CACHE)
-static u8 *coherence_data;
-static size_t coherence_data_size;
-static unsigned int d_cache_line_size;
-#endif
-
-static DEFINE_SPINLOCK(diu_lock);
-
-enum mfb_index {
-	PLANE0 = 0,	/* Plane 0, only one AOI that fills the screen */
-	PLANE1_AOI0,	/* Plane 1, first AOI */
-	PLANE1_AOI1,	/* Plane 1, second AOI */
-	PLANE2_AOI0,	/* Plane 2, first AOI */
-	PLANE2_AOI1,	/* Plane 2, second AOI */
-};
-
-struct mfb_info {
-	enum mfb_index index;
-	char *id;
-	int registered;
-	unsigned long pseudo_palette[16];
-	struct diu_ad *ad;
-	unsigned char g_alpha;
-	unsigned int count;
-	int x_aoi_d;		/* aoi display x offset to physical screen */
-	int y_aoi_d;		/* aoi display y offset to physical screen */
-	struct fsl_diu_data *parent;
-};
-
-/**
- * struct fsl_diu_data - per-DIU data structure
- * @dma_addr: DMA address of this structure
- * @fsl_diu_info: fb_info objects, one per AOI
- * @dev_attr: sysfs structure
- * @irq: IRQ
- * @monitor_port: the monitor port this DIU is connected to
- * @diu_reg: pointer to the DIU hardware registers
- * @reg_lock: spinlock for register access
- * @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
- * dummy_ad: DIU Area Descriptor for the dummy AOI
- * @ad[]: Area Descriptors for each real AOI
- * @gamma: gamma color table
- * @cursor: hardware cursor data
- *
- * This data structure must be allocated with 32-byte alignment, so that the
- * internal fields can be aligned properly.
- */
-struct fsl_diu_data {
-	dma_addr_t dma_addr;
-	struct fb_info fsl_diu_info[NUM_AOIS];
-	struct mfb_info mfb[NUM_AOIS];
-	struct device_attribute dev_attr;
-	unsigned int irq;
-	enum fsl_diu_monitor_port monitor_port;
-	struct diu __iomem *diu_reg;
-	spinlock_t reg_lock;
-	u8 dummy_aoi[4 * 4 * 4];
-	struct diu_ad dummy_ad __aligned(8);
-	struct diu_ad ad[NUM_AOIS] __aligned(8);
-	u8 gamma[256 * 3] __aligned(32);
-	/* It's easier to parse the cursor data as little-endian */
-	__le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
-	/* Blank cursor data -- used to hide the cursor */
-	__le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
-	uint8_t edid_data[EDID_LENGTH];
-	bool has_edid;
-} __aligned(32);
-
-/* Determine the DMA address of a member of the fsl_diu_data structure */
-#define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
-
-static struct mfb_info mfb_template[] = {
-	{
-		.index = PLANE0,
-		.id = "Panel0",
-		.registered = 0,
-		.count = 0,
-		.x_aoi_d = 0,
-		.y_aoi_d = 0,
-	},
-	{
-		.index = PLANE1_AOI0,
-		.id = "Panel1 AOI0",
-		.registered = 0,
-		.g_alpha = 0xff,
-		.count = 0,
-		.x_aoi_d = 0,
-		.y_aoi_d = 0,
-	},
-	{
-		.index = PLANE1_AOI1,
-		.id = "Panel1 AOI1",
-		.registered = 0,
-		.g_alpha = 0xff,
-		.count = 0,
-		.x_aoi_d = 0,
-		.y_aoi_d = 480,
-	},
-	{
-		.index = PLANE2_AOI0,
-		.id = "Panel2 AOI0",
-		.registered = 0,
-		.g_alpha = 0xff,
-		.count = 0,
-		.x_aoi_d = 640,
-		.y_aoi_d = 0,
-	},
-	{
-		.index = PLANE2_AOI1,
-		.id = "Panel2 AOI1",
-		.registered = 0,
-		.g_alpha = 0xff,
-		.count = 0,
-		.x_aoi_d = 640,
-		.y_aoi_d = 480,
-	},
-};
-
-#ifdef DEBUG
-static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw)
-{
-	mb();
-	pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x "
-		 "cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x "
-		 "disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x "
-		 "thresholds=%08x int_mask=%08x plut=%08x\n",
-		 hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma,
-		 hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode,
-		 hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para,
-		 hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut);
-	rmb();
-}
-#endif
-
-/**
- * fsl_diu_name_to_port - convert a port name to a monitor port enum
- *
- * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
- * the enum fsl_diu_monitor_port that corresponds to that string.
- *
- * For compatibility with older versions, a number ("0", "1", or "2") is also
- * supported.
- *
- * If the string is unknown, DVI is assumed.
- *
- * If the particular port is not supported by the platform, another port
- * (platform-specific) is chosen instead.
- */
-static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
-{
-	enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI;
-	unsigned long val;
-
-	if (s) {
-		if (!kstrtoul(s, 10, &val) && (val <= 2))
-			port = (enum fsl_diu_monitor_port) val;
-		else if (strncmp(s, "lvds", 4) == 0)
-			port = FSL_DIU_PORT_LVDS;
-		else if (strncmp(s, "dlvds", 5) == 0)
-			port = FSL_DIU_PORT_DLVDS;
-	}
-
-	return diu_ops.valid_monitor_port(port);
-}
-
-/*
- * Workaround for failed writing desc register of planes.
- * Needed with MPC5121 DIU rev 2.0 silicon.
- */
-void wr_reg_wa(u32 *reg, u32 val)
-{
-	do {
-		out_be32(reg, val);
-	} while (in_be32(reg) != val);
-}
-
-static void fsl_diu_enable_panel(struct fb_info *info)
-{
-	struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
-	struct diu_ad *ad = mfbi->ad;
-	struct fsl_diu_data *data = mfbi->parent;
-	struct diu __iomem *hw = data->diu_reg;
-
-	switch (mfbi->index) {
-	case PLANE0:
-		wr_reg_wa(&hw->desc[0], ad->paddr);
-		break;
-	case PLANE1_AOI0:
-		cmfbi = &data->mfb[2];
-		if (hw->desc[1] != ad->paddr) {	/* AOI0 closed */
-			if (cmfbi->count > 0)	/* AOI1 open */
-				ad->next_ad =
-					cpu_to_le32(cmfbi->ad->paddr);
-			else
-				ad->next_ad = 0;
-			wr_reg_wa(&hw->desc[1], ad->paddr);
-		}
-		break;
-	case PLANE2_AOI0:
-		cmfbi = &data->mfb[4];
-		if (hw->desc[2] != ad->paddr) {	/* AOI0 closed */
-			if (cmfbi->count > 0)	/* AOI1 open */
-				ad->next_ad =
-					cpu_to_le32(cmfbi->ad->paddr);
-			else
-				ad->next_ad = 0;
-			wr_reg_wa(&hw->desc[2], ad->paddr);
-		}
-		break;
-	case PLANE1_AOI1:
-		pmfbi = &data->mfb[1];
-		ad->next_ad = 0;
-		if (hw->desc[1] == data->dummy_ad.paddr)
-			wr_reg_wa(&hw->desc[1], ad->paddr);
-		else					/* AOI0 open */
-			pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
-		break;
-	case PLANE2_AOI1:
-		pmfbi = &data->mfb[3];
-		ad->next_ad = 0;
-		if (hw->desc[2] == data->dummy_ad.paddr)
-			wr_reg_wa(&hw->desc[2], ad->paddr);
-		else				/* AOI0 was open */
-			pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
-		break;
-	}
-}
-
-static void fsl_diu_disable_panel(struct fb_info *info)
-{
-	struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
-	struct diu_ad *ad = mfbi->ad;
-	struct fsl_diu_data *data = mfbi->parent;
-	struct diu __iomem *hw = data->diu_reg;
-
-	switch (mfbi->index) {
-	case PLANE0:
-		wr_reg_wa(&hw->desc[0], 0);
-		break;
-	case PLANE1_AOI0:
-		cmfbi = &data->mfb[2];
-		if (cmfbi->count > 0)	/* AOI1 is open */
-			wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
-					/* move AOI1 to the first */
-		else			/* AOI1 was closed */
-			wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
-					/* close AOI 0 */
-		break;
-	case PLANE2_AOI0:
-		cmfbi = &data->mfb[4];
-		if (cmfbi->count > 0)	/* AOI1 is open */
-			wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
-					/* move AOI1 to the first */
-		else			/* AOI1 was closed */
-			wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
-					/* close AOI 0 */
-		break;
-	case PLANE1_AOI1:
-		pmfbi = &data->mfb[1];
-		if (hw->desc[1] != ad->paddr) {
-				/* AOI1 is not the first in the chain */
-			if (pmfbi->count > 0)
-					/* AOI0 is open, must be the first */
-				pmfbi->ad->next_ad = 0;
-		} else			/* AOI1 is the first in the chain */
-			wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
-					/* close AOI 1 */
-		break;
-	case PLANE2_AOI1:
-		pmfbi = &data->mfb[3];
-		if (hw->desc[2] != ad->paddr) {
-				/* AOI1 is not the first in the chain */
-			if (pmfbi->count > 0)
-				/* AOI0 is open, must be the first */
-				pmfbi->ad->next_ad = 0;
-		} else		/* AOI1 is the first in the chain */
-			wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
-				/* close AOI 1 */
-		break;
-	}
-}
-
-static void enable_lcdc(struct fb_info *info)
-{
-	struct mfb_info *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	struct diu __iomem *hw = data->diu_reg;
-
-	out_be32(&hw->diu_mode, MFB_MODE1);
-}
-
-static void disable_lcdc(struct fb_info *info)
-{
-	struct mfb_info *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	struct diu __iomem *hw = data->diu_reg;
-
-	out_be32(&hw->diu_mode, 0);
-}
-
-static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	int available_height, upper_aoi_bottom;
-	enum mfb_index index = mfbi->index;
-	int lower_aoi_is_open, upper_aoi_is_open;
-	__u32 base_plane_width, base_plane_height, upper_aoi_height;
-
-	base_plane_width = data->fsl_diu_info[0].var.xres;
-	base_plane_height = data->fsl_diu_info[0].var.yres;
-
-	if (mfbi->x_aoi_d < 0)
-		mfbi->x_aoi_d = 0;
-	if (mfbi->y_aoi_d < 0)
-		mfbi->y_aoi_d = 0;
-	switch (index) {
-	case PLANE0:
-		if (mfbi->x_aoi_d != 0)
-			mfbi->x_aoi_d = 0;
-		if (mfbi->y_aoi_d != 0)
-			mfbi->y_aoi_d = 0;
-		break;
-	case PLANE1_AOI0:
-	case PLANE2_AOI0:
-		lower_aoi_mfbi = data->fsl_diu_info[index+1].par;
-		lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
-		if (var->xres > base_plane_width)
-			var->xres = base_plane_width;
-		if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
-			mfbi->x_aoi_d = base_plane_width - var->xres;
-
-		if (lower_aoi_is_open)
-			available_height = lower_aoi_mfbi->y_aoi_d;
-		else
-			available_height = base_plane_height;
-		if (var->yres > available_height)
-			var->yres = available_height;
-		if ((mfbi->y_aoi_d + var->yres) > available_height)
-			mfbi->y_aoi_d = available_height - var->yres;
-		break;
-	case PLANE1_AOI1:
-	case PLANE2_AOI1:
-		upper_aoi_mfbi = data->fsl_diu_info[index-1].par;
-		upper_aoi_height = data->fsl_diu_info[index-1].var.yres;
-		upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
-		upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
-		if (var->xres > base_plane_width)
-			var->xres = base_plane_width;
-		if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
-			mfbi->x_aoi_d = base_plane_width - var->xres;
-		if (mfbi->y_aoi_d < 0)
-			mfbi->y_aoi_d = 0;
-		if (upper_aoi_is_open) {
-			if (mfbi->y_aoi_d < upper_aoi_bottom)
-				mfbi->y_aoi_d = upper_aoi_bottom;
-			available_height = base_plane_height
-						- upper_aoi_bottom;
-		} else
-			available_height = base_plane_height;
-		if (var->yres > available_height)
-			var->yres = available_height;
-		if ((mfbi->y_aoi_d + var->yres) > base_plane_height)
-			mfbi->y_aoi_d = base_plane_height - var->yres;
-		break;
-	}
-}
-/*
- * Checks to see if the hardware supports the state requested by var passed
- * in. This function does not alter the hardware state! If the var passed in
- * is slightly off by what the hardware can support then we alter the var
- * PASSED in to what we can do. If the hardware doesn't support mode change
- * a -EINVAL will be returned by the upper layers.
- */
-static int fsl_diu_check_var(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	if (var->xoffset < 0)
-		var->xoffset = 0;
-
-	if (var->yoffset < 0)
-		var->yoffset = 0;
-
-	if (var->xoffset + info->var.xres > info->var.xres_virtual)
-		var->xoffset = info->var.xres_virtual - info->var.xres;
-
-	if (var->yoffset + info->var.yres > info->var.yres_virtual)
-		var->yoffset = info->var.yres_virtual - info->var.yres;
-
-	if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
-	    (var->bits_per_pixel != 16))
-		var->bits_per_pixel = default_bpp;
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		var->red.length = 5;
-		var->red.offset = 11;
-		var->red.msb_right = 0;
-
-		var->green.length = 6;
-		var->green.offset = 5;
-		var->green.msb_right = 0;
-
-		var->blue.length = 5;
-		var->blue.offset = 0;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 0;
-		var->transp.offset = 0;
-		var->transp.msb_right = 0;
-		break;
-	case 24:
-		var->red.length = 8;
-		var->red.offset = 0;
-		var->red.msb_right = 0;
-
-		var->green.length = 8;
-		var->green.offset = 8;
-		var->green.msb_right = 0;
-
-		var->blue.length = 8;
-		var->blue.offset = 16;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 0;
-		var->transp.offset = 0;
-		var->transp.msb_right = 0;
-		break;
-	case 32:
-		var->red.length = 8;
-		var->red.offset = 16;
-		var->red.msb_right = 0;
-
-		var->green.length = 8;
-		var->green.offset = 8;
-		var->green.msb_right = 0;
-
-		var->blue.length = 8;
-		var->blue.offset = 0;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 8;
-		var->transp.offset = 24;
-		var->transp.msb_right = 0;
-
-		break;
-	}
-
-	var->height = -1;
-	var->width = -1;
-	var->grayscale = 0;
-
-	/* Copy nonstd field to/from sync for fbset usage */
-	var->sync |= var->nonstd;
-	var->nonstd |= var->sync;
-
-	adjust_aoi_size_position(var, info);
-	return 0;
-}
-
-static void set_fix(struct fb_info *info)
-{
-	struct fb_fix_screeninfo *fix = &info->fix;
-	struct fb_var_screeninfo *var = &info->var;
-	struct mfb_info *mfbi = info->par;
-
-	strncpy(fix->id, mfbi->id, sizeof(fix->id));
-	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->accel = FB_ACCEL_NONE;
-	fix->visual = FB_VISUAL_TRUECOLOR;
-	fix->xpanstep = 1;
-	fix->ypanstep = 1;
-}
-
-static void update_lcdc(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-	struct mfb_info *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	struct diu __iomem *hw;
-	int i, j;
-	u8 *gamma_table_base;
-
-	u32 temp;
-
-	hw = data->diu_reg;
-
-	if (diu_ops.set_monitor_port)
-		diu_ops.set_monitor_port(data->monitor_port);
-	gamma_table_base = data->gamma;
-
-	/* Prep for DIU init  - gamma table, cursor table */
-
-	for (i = 0; i <= 2; i++)
-		for (j = 0; j <= 255; j++)
-			*gamma_table_base++ = j;
-
-	if (diu_ops.set_gamma_table)
-		diu_ops.set_gamma_table(data->monitor_port, data->gamma);
-
-	disable_lcdc(info);
-
-	/* Program DIU registers */
-
-	out_be32(&hw->gamma, DMA_ADDR(data, gamma));
-
-	out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
-	out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
-
-	/* Horizontal and vertical configuration register */
-	temp = var->left_margin << 22 | /* BP_H */
-	       var->hsync_len << 11 |   /* PW_H */
-	       var->right_margin;       /* FP_H */
-
-	out_be32(&hw->hsyn_para, temp);
-
-	temp = var->upper_margin << 22 | /* BP_V */
-	       var->vsync_len << 11 |    /* PW_V  */
-	       var->lower_margin;        /* FP_V  */
-
-	out_be32(&hw->vsyn_para, temp);
-
-	diu_ops.set_pixel_clock(var->pixclock);
-
-#ifndef CONFIG_PPC_MPC512x
-	/*
-	 * The PLUT register is defined differently on the MPC5121 than it
-	 * is on other SOCs.  Unfortunately, there's no documentation that
-	 * explains how it's supposed to be programmed, so for now, we leave
-	 * it at the default value on the MPC5121.
-	 *
-	 * For other SOCs, program it for the highest priority, which will
-	 * reduce the chance of underrun. Technically, we should scale the
-	 * priority to match the screen resolution, but doing that properly
-	 * requires delicate fine-tuning for each use-case.
-	 */
-	out_be32(&hw->plut, 0x01F5F666);
-#endif
-
-	/* Enable the DIU */
-	enable_lcdc(info);
-}
-
-static int map_video_memory(struct fb_info *info)
-{
-	u32 smem_len = info->fix.line_length * info->var.yres_virtual;
-	void *p;
-
-	p = alloc_pages_exact(smem_len, GFP_DMA | __GFP_ZERO);
-	if (!p) {
-		dev_err(info->dev, "unable to allocate fb memory\n");
-		return -ENOMEM;
-	}
-	mutex_lock(&info->mm_lock);
-	info->screen_base = p;
-	info->fix.smem_start = virt_to_phys(info->screen_base);
-	info->fix.smem_len = smem_len;
-	mutex_unlock(&info->mm_lock);
-	info->screen_size = info->fix.smem_len;
-
-	return 0;
-}
-
-static void unmap_video_memory(struct fb_info *info)
-{
-	void *p = info->screen_base;
-	size_t l = info->fix.smem_len;
-
-	mutex_lock(&info->mm_lock);
-	info->screen_base = NULL;
-	info->fix.smem_start = 0;
-	info->fix.smem_len = 0;
-	mutex_unlock(&info->mm_lock);
-
-	if (p)
-		free_pages_exact(p, l);
-}
-
-/*
- * Using the fb_var_screeninfo in fb_info we set the aoi of this
- * particular framebuffer. It is a light version of fsl_diu_set_par.
- */
-static int fsl_diu_set_aoi(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-	struct mfb_info *mfbi = info->par;
-	struct diu_ad *ad = mfbi->ad;
-
-	/* AOI should not be greater than display size */
-	ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
-	ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
-	return 0;
-}
-
-/**
- * fsl_diu_get_pixel_format: return the pixel format for a given color depth
- *
- * The pixel format is a 32-bit value that determine which bits in each
- * pixel are to be used for each color.  This is the default function used
- * if the platform does not define its own version.
- */
-static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
-{
-#define PF_BYTE_F		0x10000000
-#define PF_ALPHA_C_MASK		0x0E000000
-#define PF_ALPHA_C_SHIFT	25
-#define PF_BLUE_C_MASK		0x01800000
-#define PF_BLUE_C_SHIFT		23
-#define PF_GREEN_C_MASK		0x00600000
-#define PF_GREEN_C_SHIFT	21
-#define PF_RED_C_MASK		0x00180000
-#define PF_RED_C_SHIFT		19
-#define PF_PALETTE		0x00040000
-#define PF_PIXEL_S_MASK		0x00030000
-#define PF_PIXEL_S_SHIFT	16
-#define PF_COMP_3_MASK		0x0000F000
-#define PF_COMP_3_SHIFT		12
-#define PF_COMP_2_MASK		0x00000F00
-#define PF_COMP_2_SHIFT		8
-#define PF_COMP_1_MASK		0x000000F0
-#define PF_COMP_1_SHIFT		4
-#define PF_COMP_0_MASK		0x0000000F
-#define PF_COMP_0_SHIFT		0
-
-#define MAKE_PF(alpha, red, green, blue, size, c0, c1, c2, c3) \
-	cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
-	(blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
-	(red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
-	(c2 << PF_COMP_2_SHIFT) | (c1 << PF_COMP_1_SHIFT) | \
-	(c0 << PF_COMP_0_SHIFT) | (size << PF_PIXEL_S_SHIFT))
-
-	switch (bits_per_pixel) {
-	case 32:
-		/* 0x88883316 */
-		return MAKE_PF(3, 2, 1, 0, 3, 8, 8, 8, 8);
-	case 24:
-		/* 0x88082219 */
-		return MAKE_PF(4, 0, 1, 2, 2, 8, 8, 8, 0);
-	case 16:
-		/* 0x65053118 */
-		return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
-	default:
-		pr_err("fsl-diu: unsupported color depth %u\n", bits_per_pixel);
-		return 0;
-	}
-}
-
-/*
- * Copies a cursor image from user space to the proper place in driver
- * memory so that the hardware can display the cursor image.
- *
- * Cursor data is represented as a sequence of 'width' bits packed into bytes.
- * That is, the first 8 bits are in the first byte, the second 8 bits in the
- * second byte, and so on.  Therefore, the each row of the cursor is (width +
- * 7) / 8 bytes of 'data'
- *
- * The DIU only supports cursors up to 32x32 (MAX_CURS).  We reject cursors
- * larger than this, so we already know that 'width' <= 32.  Therefore, we can
- * simplify our code by using a 32-bit big-endian integer ("line") to read in
- * a single line of pixels, and only look at the top 'width' bits of that
- * integer.
- *
- * This could result in an unaligned 32-bit read.  For example, if the cursor
- * is 24x24, then the first three bytes of 'image' contain the pixel data for
- * the top line of the cursor.  We do a 32-bit read of 'image', but we look
- * only at the top 24 bits.  Then we increment 'image' by 3 bytes.  The next
- * read is unaligned.  The only problem is that we might read past the end of
- * 'image' by 1-3 bytes, but that should not cause any problems.
- */
-static void fsl_diu_load_cursor_image(struct fb_info *info,
-	const void *image, uint16_t bg, uint16_t fg,
-	unsigned int width, unsigned int height)
-{
-	struct mfb_info *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	__le16 *cursor = data->cursor;
-	__le16 _fg = cpu_to_le16(fg);
-	__le16 _bg = cpu_to_le16(bg);
-	unsigned int h, w;
-
-	for (h = 0; h < height; h++) {
-		uint32_t mask = 1 << 31;
-		uint32_t line = be32_to_cpup(image);
-
-		for (w = 0; w < width; w++) {
-			cursor[w] = (line & mask) ? _fg : _bg;
-			mask >>= 1;
-		}
-
-		cursor += MAX_CURS;
-		image += DIV_ROUND_UP(width, 8);
-	}
-}
-
-/*
- * Set a hardware cursor.  The image data for the cursor is passed via the
- * fb_cursor object.
- */
-static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct mfb_info *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	struct diu __iomem *hw = data->diu_reg;
-
-	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
-		return -EINVAL;
-
-	/* The cursor size has changed */
-	if (cursor->set & FB_CUR_SETSIZE) {
-		/*
-		 * The DIU cursor is a fixed size, so when we get this
-		 * message, instead of resizing the cursor, we just clear
-		 * all the image data, in expectation of new data.  However,
-		 * in tests this control does not appear to be normally
-		 * called.
-		 */
-		memset(data->cursor, 0, sizeof(data->cursor));
-	}
-
-	/* The cursor position has changed (cursor->image.dx|dy) */
-	if (cursor->set & FB_CUR_SETPOS) {
-		uint32_t xx, yy;
-
-		yy = (cursor->image.dy - info->var.yoffset) & 0x7ff;
-		xx = (cursor->image.dx - info->var.xoffset) & 0x7ff;
-
-		out_be32(&hw->curs_pos, yy << 16 | xx);
-	}
-
-	/*
-	 * FB_CUR_SETIMAGE - the cursor image has changed
-	 * FB_CUR_SETCMAP  - the cursor colors has changed
-	 * FB_CUR_SETSHAPE - the cursor bitmask has changed
-	 */
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
-		unsigned int image_size =
-			DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
-		unsigned int image_words =
-			DIV_ROUND_UP(image_size, sizeof(uint32_t));
-		unsigned int bg_idx = cursor->image.bg_color;
-		unsigned int fg_idx = cursor->image.fg_color;
-		uint8_t buffer[image_size];
-		uint32_t *image, *source, *mask;
-		uint16_t fg, bg;
-		unsigned int i;
-
-		if (info->state != FBINFO_STATE_RUNNING)
-			return 0;
-
-		/*
-		 * Determine the size of the cursor image data.  Normally,
-		 * it's 8x16.
-		 */
-		image_size = DIV_ROUND_UP(cursor->image.width, 8) *
-			cursor->image.height;
-
-		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
-		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
-		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
-		     1 << 15;
-
-		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
-		     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
-		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
-		     1 << 15;
-
-		/* Use 32-bit operations on the data to improve performance */
-		image = (uint32_t *)buffer;
-		source = (uint32_t *)cursor->image.data;
-		mask = (uint32_t *)cursor->mask;
-
-		if (cursor->rop == ROP_XOR)
-			for (i = 0; i < image_words; i++)
-				image[i] = source[i] ^ mask[i];
-		else
-			for (i = 0; i < image_words; i++)
-				image[i] = source[i] & mask[i];
-
-		fsl_diu_load_cursor_image(info, image, bg, fg,
-			cursor->image.width, cursor->image.height);
-	}
-
-	/*
-	 * Show or hide the cursor.  The cursor data is always stored in the
-	 * 'cursor' memory block, and the actual cursor position is always in
-	 * the DIU's CURS_POS register.  To hide the cursor, we redirect the
-	 * CURSOR register to a blank cursor.  The show the cursor, we
-	 * redirect the CURSOR register to the real cursor data.
-	 */
-	if (cursor->enable)
-		out_be32(&hw->cursor, DMA_ADDR(data, cursor));
-	else
-		out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor));
-
-	return 0;
-}
-
-/*
- * Using the fb_var_screeninfo in fb_info we set the resolution of this
- * particular framebuffer. This function alters the fb_fix_screeninfo stored
- * in fb_info. It does not alter var in fb_info since we are using that
- * data. This means we depend on the data in var inside fb_info to be
- * supported by the hardware. fsl_diu_check_var is always called before
- * fsl_diu_set_par to ensure this.
- */
-static int fsl_diu_set_par(struct fb_info *info)
-{
-	unsigned long len;
-	struct fb_var_screeninfo *var = &info->var;
-	struct mfb_info *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	struct diu_ad *ad = mfbi->ad;
-	struct diu __iomem *hw;
-
-	hw = data->diu_reg;
-
-	set_fix(info);
-
-	len = info->var.yres_virtual * info->fix.line_length;
-	/* Alloc & dealloc each time resolution/bpp change */
-	if (len != info->fix.smem_len) {
-		if (info->fix.smem_start)
-			unmap_video_memory(info);
-
-		/* Memory allocation for framebuffer */
-		if (map_video_memory(info)) {
-			dev_err(info->dev, "unable to allocate fb memory 1\n");
-			return -ENOMEM;
-		}
-	}
-
-	if (diu_ops.get_pixel_format)
-		ad->pix_fmt = diu_ops.get_pixel_format(data->monitor_port,
-						       var->bits_per_pixel);
-	else
-		ad->pix_fmt = fsl_diu_get_pixel_format(var->bits_per_pixel);
-
-	ad->addr    = cpu_to_le32(info->fix.smem_start);
-	ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
-				var->xres_virtual) | mfbi->g_alpha;
-	/* AOI should not be greater than display size */
-	ad->aoi_size 	= cpu_to_le32((var->yres << 16) | var->xres);
-	ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
-	ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
-
-	/* Disable chroma keying function */
-	ad->ckmax_r = 0;
-	ad->ckmax_g = 0;
-	ad->ckmax_b = 0;
-
-	ad->ckmin_r = 255;
-	ad->ckmin_g = 255;
-	ad->ckmin_b = 255;
-
-	if (mfbi->index == PLANE0)
-		update_lcdc(info);
-	return 0;
-}
-
-static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
-{
-	return ((val << width) + 0x7FFF - val) >> 16;
-}
-
-/*
- * Set a single color register. The values supplied have a 16 bit magnitude
- * which needs to be scaled in this function for the hardware. Things to take
- * into consideration are how many color registers, if any, are supported with
- * the current color visual. With truecolor mode no color palettes are
- * supported. Here a pseudo palette is created which we store the value in
- * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
- * color palette.
- */
-static int fsl_diu_setcolreg(unsigned int regno, unsigned int red,
-			     unsigned int green, unsigned int blue,
-			     unsigned int transp, struct fb_info *info)
-{
-	int ret = 1;
-
-	/*
-	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no matter what visual we are using.
-	 */
-	if (info->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-				      7471 * blue) >> 16;
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 16-bit True Colour.  We encode the RGB value
-		 * according to the RGB bitfield information.
-		 */
-		if (regno < 16) {
-			u32 *pal = info->pseudo_palette;
-			u32 v;
-
-			red = CNVT_TOHW(red, info->var.red.length);
-			green = CNVT_TOHW(green, info->var.green.length);
-			blue = CNVT_TOHW(blue, info->var.blue.length);
-			transp = CNVT_TOHW(transp, info->var.transp.length);
-
-			v = (red << info->var.red.offset) |
-			    (green << info->var.green.offset) |
-			    (blue << info->var.blue.offset) |
-			    (transp << info->var.transp.offset);
-
-			pal[regno] = v;
-			ret = 0;
-		}
-		break;
-	}
-
-	return ret;
-}
-
-/*
- * Pan (or wrap, depending on the `vmode' field) the display using the
- * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values
- * don't fit, return -EINVAL.
- */
-static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	if ((info->var.xoffset == var->xoffset) &&
-	    (info->var.yoffset == var->yoffset))
-		return 0;	/* No change, do nothing */
-
-	if (var->xoffset < 0 || var->yoffset < 0
-	    || var->xoffset + info->var.xres > info->var.xres_virtual
-	    || var->yoffset + info->var.yres > info->var.yres_virtual)
-		return -EINVAL;
-
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-
-	fsl_diu_set_aoi(info);
-
-	return 0;
-}
-
-static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
-		       unsigned long arg)
-{
-	struct mfb_info *mfbi = info->par;
-	struct diu_ad *ad = mfbi->ad;
-	struct mfb_chroma_key ck;
-	unsigned char global_alpha;
-	struct aoi_display_offset aoi_d;
-	__u32 pix_fmt;
-	void __user *buf = (void __user *)arg;
-
-	if (!arg)
-		return -EINVAL;
-
-	dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd,
-		_IOC_DIR(cmd) & _IOC_READ ? "R" : "",
-		_IOC_DIR(cmd) & _IOC_WRITE ? "W" : "",
-		_IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
-
-	switch (cmd) {
-	case MFB_SET_PIXFMT_OLD:
-		dev_warn(info->dev,
-			 "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n",
-			 MFB_SET_PIXFMT_OLD);
-	case MFB_SET_PIXFMT:
-		if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt)))
-			return -EFAULT;
-		ad->pix_fmt = pix_fmt;
-		break;
-	case MFB_GET_PIXFMT_OLD:
-		dev_warn(info->dev,
-			 "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n",
-			 MFB_GET_PIXFMT_OLD);
-	case MFB_GET_PIXFMT:
-		pix_fmt = ad->pix_fmt;
-		if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt)))
-			return -EFAULT;
-		break;
-	case MFB_SET_AOID:
-		if (copy_from_user(&aoi_d, buf, sizeof(aoi_d)))
-			return -EFAULT;
-		mfbi->x_aoi_d = aoi_d.x_aoi_d;
-		mfbi->y_aoi_d = aoi_d.y_aoi_d;
-		fsl_diu_check_var(&info->var, info);
-		fsl_diu_set_aoi(info);
-		break;
-	case MFB_GET_AOID:
-		aoi_d.x_aoi_d = mfbi->x_aoi_d;
-		aoi_d.y_aoi_d = mfbi->y_aoi_d;
-		if (copy_to_user(buf, &aoi_d, sizeof(aoi_d)))
-			return -EFAULT;
-		break;
-	case MFB_GET_ALPHA:
-		global_alpha = mfbi->g_alpha;
-		if (copy_to_user(buf, &global_alpha, sizeof(global_alpha)))
-			return -EFAULT;
-		break;
-	case MFB_SET_ALPHA:
-		/* set panel information */
-		if (copy_from_user(&global_alpha, buf, sizeof(global_alpha)))
-			return -EFAULT;
-		ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) |
-							(global_alpha & 0xff);
-		mfbi->g_alpha = global_alpha;
-		break;
-	case MFB_SET_CHROMA_KEY:
-		/* set panel winformation */
-		if (copy_from_user(&ck, buf, sizeof(ck)))
-			return -EFAULT;
-
-		if (ck.enable &&
-		   (ck.red_max < ck.red_min ||
-		    ck.green_max < ck.green_min ||
-		    ck.blue_max < ck.blue_min))
-			return -EINVAL;
-
-		if (!ck.enable) {
-			ad->ckmax_r = 0;
-			ad->ckmax_g = 0;
-			ad->ckmax_b = 0;
-			ad->ckmin_r = 255;
-			ad->ckmin_g = 255;
-			ad->ckmin_b = 255;
-		} else {
-			ad->ckmax_r = ck.red_max;
-			ad->ckmax_g = ck.green_max;
-			ad->ckmax_b = ck.blue_max;
-			ad->ckmin_r = ck.red_min;
-			ad->ckmin_g = ck.green_min;
-			ad->ckmin_b = ck.blue_min;
-		}
-		break;
-#ifdef CONFIG_PPC_MPC512x
-	case MFB_SET_GAMMA: {
-		struct fsl_diu_data *data = mfbi->parent;
-
-		if (copy_from_user(data->gamma, buf, sizeof(data->gamma)))
-			return -EFAULT;
-		setbits32(&data->diu_reg->gamma, 0); /* Force table reload */
-		break;
-	}
-	case MFB_GET_GAMMA: {
-		struct fsl_diu_data *data = mfbi->parent;
-
-		if (copy_to_user(buf, data->gamma, sizeof(data->gamma)))
-			return -EFAULT;
-		break;
-	}
-#endif
-	default:
-		dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
-		return -ENOIOCTLCMD;
-	}
-
-	return 0;
-}
-
-static inline void fsl_diu_enable_interrupts(struct fsl_diu_data *data)
-{
-	u32 int_mask = INT_UNDRUN; /* enable underrun detection */
-
-	if (IS_ENABLED(CONFIG_NOT_COHERENT_CACHE))
-		int_mask |= INT_VSYNC; /* enable vertical sync */
-
-	clrbits32(&data->diu_reg->int_mask, int_mask);
-}
-
-/* turn on fb if count == 1
- */
-static int fsl_diu_open(struct fb_info *info, int user)
-{
-	struct mfb_info *mfbi = info->par;
-	int res = 0;
-
-	/* free boot splash memory on first /dev/fb0 open */
-	if ((mfbi->index == PLANE0) && diu_ops.release_bootmem)
-		diu_ops.release_bootmem();
-
-	spin_lock(&diu_lock);
-	mfbi->count++;
-	if (mfbi->count == 1) {
-		fsl_diu_check_var(&info->var, info);
-		res = fsl_diu_set_par(info);
-		if (res < 0)
-			mfbi->count--;
-		else {
-			fsl_diu_enable_interrupts(mfbi->parent);
-			fsl_diu_enable_panel(info);
-		}
-	}
-
-	spin_unlock(&diu_lock);
-	return res;
-}
-
-/* turn off fb if count == 0
- */
-static int fsl_diu_release(struct fb_info *info, int user)
-{
-	struct mfb_info *mfbi = info->par;
-	int res = 0;
-
-	spin_lock(&diu_lock);
-	mfbi->count--;
-	if (mfbi->count == 0) {
-		struct fsl_diu_data *data = mfbi->parent;
-		bool disable = true;
-		int i;
-
-		/* Disable interrupts only if all AOIs are closed */
-		for (i = 0; i < NUM_AOIS; i++) {
-			struct mfb_info *mi = data->fsl_diu_info[i].par;
-
-			if (mi->count)
-				disable = false;
-		}
-		if (disable)
-			out_be32(&data->diu_reg->int_mask, 0xffffffff);
-		fsl_diu_disable_panel(info);
-	}
-
-	spin_unlock(&diu_lock);
-	return res;
-}
-
-static struct fb_ops fsl_diu_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = fsl_diu_check_var,
-	.fb_set_par = fsl_diu_set_par,
-	.fb_setcolreg = fsl_diu_setcolreg,
-	.fb_pan_display = fsl_diu_pan_display,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_ioctl = fsl_diu_ioctl,
-	.fb_open = fsl_diu_open,
-	.fb_release = fsl_diu_release,
-	.fb_cursor = fsl_diu_cursor,
-};
-
-static int install_fb(struct fb_info *info)
-{
-	int rc;
-	struct mfb_info *mfbi = info->par;
-	struct fsl_diu_data *data = mfbi->parent;
-	const char *aoi_mode, *init_aoi_mode = "320x240";
-	struct fb_videomode *db = fsl_diu_mode_db;
-	unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
-	int has_default_mode = 1;
-
-	info->var.activate = FB_ACTIVATE_NOW;
-	info->fbops = &fsl_diu_ops;
-	info->flags = FBINFO_DEFAULT | FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK |
-		FBINFO_READS_FAST;
-	info->pseudo_palette = mfbi->pseudo_palette;
-
-	rc = fb_alloc_cmap(&info->cmap, 16, 0);
-	if (rc)
-		return rc;
-
-	if (mfbi->index == PLANE0) {
-		if (data->has_edid) {
-			/* Now build modedb from EDID */
-			fb_edid_to_monspecs(data->edid_data, &info->monspecs);
-			fb_videomode_to_modelist(info->monspecs.modedb,
-						 info->monspecs.modedb_len,
-						 &info->modelist);
-			db = info->monspecs.modedb;
-			dbsize = info->monspecs.modedb_len;
-		}
-		aoi_mode = fb_mode;
-	} else {
-		aoi_mode = init_aoi_mode;
-	}
-	rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, NULL,
-			  default_bpp);
-	if (!rc) {
-		/*
-		 * For plane 0 we continue and look into
-		 * driver's internal modedb.
-		 */
-		if ((mfbi->index == PLANE0) && data->has_edid)
-			has_default_mode = 0;
-		else
-			return -EINVAL;
-	}
-
-	if (!has_default_mode) {
-		rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
-			ARRAY_SIZE(fsl_diu_mode_db), NULL, default_bpp);
-		if (rc)
-			has_default_mode = 1;
-	}
-
-	/* Still not found, use preferred mode from database if any */
-	if (!has_default_mode && info->monspecs.modedb) {
-		struct fb_monspecs *specs = &info->monspecs;
-		struct fb_videomode *modedb = &specs->modedb[0];
-
-		/*
-		 * Get preferred timing. If not found,
-		 * first mode in database will be used.
-		 */
-		if (specs->misc & FB_MISC_1ST_DETAIL) {
-			int i;
-
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-					modedb = &specs->modedb[i];
-					break;
-				}
-			}
-		}
-
-		info->var.bits_per_pixel = default_bpp;
-		fb_videomode_to_var(&info->var, modedb);
-	}
-
-	if (fsl_diu_check_var(&info->var, info)) {
-		dev_err(info->dev, "fsl_diu_check_var failed\n");
-		unmap_video_memory(info);
-		fb_dealloc_cmap(&info->cmap);
-		return -EINVAL;
-	}
-
-	if (register_framebuffer(info) < 0) {
-		dev_err(info->dev, "register_framebuffer failed\n");
-		unmap_video_memory(info);
-		fb_dealloc_cmap(&info->cmap);
-		return -EINVAL;
-	}
-
-	mfbi->registered = 1;
-	dev_info(info->dev, "%s registered successfully\n", mfbi->id);
-
-	return 0;
-}
-
-static void uninstall_fb(struct fb_info *info)
-{
-	struct mfb_info *mfbi = info->par;
-
-	if (!mfbi->registered)
-		return;
-
-	unregister_framebuffer(info);
-	unmap_video_memory(info);
-	if (&info->cmap)
-		fb_dealloc_cmap(&info->cmap);
-
-	mfbi->registered = 0;
-}
-
-static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
-{
-	struct diu __iomem *hw = dev_id;
-	uint32_t status = in_be32(&hw->int_status);
-
-	if (status) {
-		/* This is the workaround for underrun */
-		if (status & INT_UNDRUN) {
-			out_be32(&hw->diu_mode, 0);
-			udelay(1);
-			out_be32(&hw->diu_mode, 1);
-		}
-#if defined(CONFIG_NOT_COHERENT_CACHE)
-		else if (status & INT_VSYNC) {
-			unsigned int i;
-
-			for (i = 0; i < coherence_data_size;
-				i += d_cache_line_size)
-				__asm__ __volatile__ (
-					"dcbz 0, %[input]"
-				::[input]"r"(&coherence_data[i]));
-		}
-#endif
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
-}
-
-#ifdef CONFIG_PM
-/*
- * Power management hooks. Note that we won't be called from IRQ context,
- * unlike the blank functions above, so we may sleep.
- */
-static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
-{
-	struct fsl_diu_data *data;
-
-	data = dev_get_drvdata(&ofdev->dev);
-	disable_lcdc(data->fsl_diu_info);
-
-	return 0;
-}
-
-static int fsl_diu_resume(struct platform_device *ofdev)
-{
-	struct fsl_diu_data *data;
-
-	data = dev_get_drvdata(&ofdev->dev);
-	enable_lcdc(data->fsl_diu_info);
-
-	return 0;
-}
-
-#else
-#define fsl_diu_suspend NULL
-#define fsl_diu_resume NULL
-#endif				/* CONFIG_PM */
-
-static ssize_t store_monitor(struct device *device,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	enum fsl_diu_monitor_port old_monitor_port;
-	struct fsl_diu_data *data =
-		container_of(attr, struct fsl_diu_data, dev_attr);
-
-	old_monitor_port = data->monitor_port;
-	data->monitor_port = fsl_diu_name_to_port(buf);
-
-	if (old_monitor_port != data->monitor_port) {
-		/* All AOIs need adjust pixel format
-		 * fsl_diu_set_par only change the pixsel format here
-		 * unlikely to fail. */
-		unsigned int i;
-
-		for (i=0; i < NUM_AOIS; i++)
-			fsl_diu_set_par(&data->fsl_diu_info[i]);
-	}
-	return count;
-}
-
-static ssize_t show_monitor(struct device *device,
-	struct device_attribute *attr, char *buf)
-{
-	struct fsl_diu_data *data =
-		container_of(attr, struct fsl_diu_data, dev_attr);
-
-	switch (data->monitor_port) {
-	case FSL_DIU_PORT_DVI:
-		return sprintf(buf, "DVI\n");
-	case FSL_DIU_PORT_LVDS:
-		return sprintf(buf, "Single-link LVDS\n");
-	case FSL_DIU_PORT_DLVDS:
-		return sprintf(buf, "Dual-link LVDS\n");
-	}
-
-	return 0;
-}
-
-static int fsl_diu_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	struct mfb_info *mfbi;
-	struct fsl_diu_data *data;
-	dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
-	const void *prop;
-	unsigned int i;
-	int ret;
-
-	data = dmam_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
-				   &dma_addr, GFP_DMA | __GFP_ZERO);
-	if (!data)
-		return -ENOMEM;
-	data->dma_addr = dma_addr;
-
-	/*
-	 * dma_alloc_coherent() uses a page allocator, so the address is
-	 * always page-aligned.  We need the memory to be 32-byte aligned,
-	 * so that's good.  However, if one day the allocator changes, we
-	 * need to catch that.  It's not worth the effort to handle unaligned
-	 * alloctions now because it's highly unlikely to ever be a problem.
-	 */
-	if ((unsigned long)data & 31) {
-		dev_err(&pdev->dev, "misaligned allocation");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	spin_lock_init(&data->reg_lock);
-
-	for (i = 0; i < NUM_AOIS; i++) {
-		struct fb_info *info = &data->fsl_diu_info[i];
-
-		info->device = &pdev->dev;
-		info->par = &data->mfb[i];
-
-		/*
-		 * We store the physical address of the AD in the reserved
-		 * 'paddr' field of the AD itself.
-		 */
-		data->ad[i].paddr = DMA_ADDR(data, ad[i]);
-
-		info->fix.smem_start = 0;
-
-		/* Initialize the AOI data structure */
-		mfbi = info->par;
-		memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
-		mfbi->parent = data;
-		mfbi->ad = &data->ad[i];
-	}
-
-	/* Get the EDID data from the device tree, if present */
-	prop = of_get_property(np, "edid", &ret);
-	if (prop && ret == EDID_LENGTH) {
-		memcpy(data->edid_data, prop, EDID_LENGTH);
-		data->has_edid = true;
-	}
-
-	data->diu_reg = of_iomap(np, 0);
-	if (!data->diu_reg) {
-		dev_err(&pdev->dev, "cannot map DIU registers\n");
-		ret = -EFAULT;
-		goto error;
-	}
-
-	/* Get the IRQ of the DIU */
-	data->irq = irq_of_parse_and_map(np, 0);
-
-	if (!data->irq) {
-		dev_err(&pdev->dev, "could not get DIU IRQ\n");
-		ret = -EINVAL;
-		goto error;
-	}
-	data->monitor_port = monitor_port;
-
-	/* Initialize the dummy Area Descriptor */
-	data->dummy_ad.addr = cpu_to_le32(DMA_ADDR(data, dummy_aoi));
-	data->dummy_ad.pix_fmt = 0x88882317;
-	data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
-	data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) |  2);
-	data->dummy_ad.offset_xyi = 0;
-	data->dummy_ad.offset_xyd = 0;
-	data->dummy_ad.next_ad = 0;
-	data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
-
-	/*
-	 * Let DIU continue to display splash screen if it was pre-initialized
-	 * by the bootloader; otherwise, clear the display.
-	 */
-	if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0)
-		out_be32(&data->diu_reg->desc[0], 0);
-
-	out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
-	out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
-
-	/*
-	 * Older versions of U-Boot leave interrupts enabled, so disable
-	 * all of them and clear the status register.
-	 */
-	out_be32(&data->diu_reg->int_mask, 0xffffffff);
-	in_be32(&data->diu_reg->int_status);
-
-	ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
-			  data->diu_reg);
-	if (ret) {
-		dev_err(&pdev->dev, "could not claim irq\n");
-		goto error;
-	}
-
-	for (i = 0; i < NUM_AOIS; i++) {
-		ret = install_fb(&data->fsl_diu_info[i]);
-		if (ret) {
-			dev_err(&pdev->dev, "could not register fb %d\n", i);
-			free_irq(data->irq, data->diu_reg);
-			goto error;
-		}
-	}
-
-	sysfs_attr_init(&data->dev_attr.attr);
-	data->dev_attr.attr.name = "monitor";
-	data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
-	data->dev_attr.show = show_monitor;
-	data->dev_attr.store = store_monitor;
-	ret = device_create_file(&pdev->dev, &data->dev_attr);
-	if (ret) {
-		dev_err(&pdev->dev, "could not create sysfs file %s\n",
-			data->dev_attr.attr.name);
-	}
-
-	dev_set_drvdata(&pdev->dev, data);
-	return 0;
-
-error:
-	for (i = 0; i < NUM_AOIS; i++)
-		uninstall_fb(&data->fsl_diu_info[i]);
-
-	iounmap(data->diu_reg);
-
-	return ret;
-}
-
-static int fsl_diu_remove(struct platform_device *pdev)
-{
-	struct fsl_diu_data *data;
-	int i;
-
-	data = dev_get_drvdata(&pdev->dev);
-	disable_lcdc(&data->fsl_diu_info[0]);
-
-	free_irq(data->irq, data->diu_reg);
-
-	for (i = 0; i < NUM_AOIS; i++)
-		uninstall_fb(&data->fsl_diu_info[i]);
-
-	iounmap(data->diu_reg);
-
-	return 0;
-}
-
-#ifndef MODULE
-static int __init fsl_diu_setup(char *options)
-{
-	char *opt;
-	unsigned long val;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-		if (!strncmp(opt, "monitor=", 8)) {
-			monitor_port = fsl_diu_name_to_port(opt + 8);
-		} else if (!strncmp(opt, "bpp=", 4)) {
-			if (!kstrtoul(opt + 4, 10, &val))
-				default_bpp = val;
-		} else
-			fb_mode = opt;
-	}
-
-	return 0;
-}
-#endif
-
-static struct of_device_id fsl_diu_match[] = {
-#ifdef CONFIG_PPC_MPC512x
-	{
-		.compatible = "fsl,mpc5121-diu",
-	},
-#endif
-	{
-		.compatible = "fsl,diu",
-	},
-	{}
-};
-MODULE_DEVICE_TABLE(of, fsl_diu_match);
-
-static struct platform_driver fsl_diu_driver = {
-	.driver = {
-		.name = "fsl-diu-fb",
-		.owner = THIS_MODULE,
-		.of_match_table = fsl_diu_match,
-	},
-	.probe  	= fsl_diu_probe,
-	.remove 	= fsl_diu_remove,
-	.suspend	= fsl_diu_suspend,
-	.resume		= fsl_diu_resume,
-};
-
-static int __init fsl_diu_init(void)
-{
-#ifdef CONFIG_NOT_COHERENT_CACHE
-	struct device_node *np;
-	const u32 *prop;
-#endif
-	int ret;
-#ifndef MODULE
-	char *option;
-
-	/*
-	 * For kernel boot options (in 'video=xxxfb:<options>' format)
-	 */
-	if (fb_get_options("fslfb", &option))
-		return -ENODEV;
-	fsl_diu_setup(option);
-#else
-	monitor_port = fsl_diu_name_to_port(monitor_string);
-#endif
-	pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n");
-
-#ifdef CONFIG_NOT_COHERENT_CACHE
-	np = of_find_node_by_type(NULL, "cpu");
-	if (!np) {
-		pr_err("fsl-diu-fb: can't find 'cpu' device node\n");
-		return -ENODEV;
-	}
-
-	prop = of_get_property(np, "d-cache-size", NULL);
-	if (prop == NULL) {
-		pr_err("fsl-diu-fb: missing 'd-cache-size' property' "
-		       "in 'cpu' node\n");
-		of_node_put(np);
-		return -ENODEV;
-	}
-
-	/*
-	 * Freescale PLRU requires 13/8 times the cache size to do a proper
-	 * displacement flush
-	 */
-	coherence_data_size = be32_to_cpup(prop) * 13;
-	coherence_data_size /= 8;
-
-	pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n",
-		 coherence_data_size);
-
-	prop = of_get_property(np, "d-cache-line-size", NULL);
-	if (prop == NULL) {
-		pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
-		       "in 'cpu' node\n");
-		of_node_put(np);
-		return -ENODEV;
-	}
-	d_cache_line_size = be32_to_cpup(prop);
-
-	pr_debug("fsl-diu-fb: cache lines size is %u bytes\n",
-		 d_cache_line_size);
-
-	of_node_put(np);
-	coherence_data = vmalloc(coherence_data_size);
-	if (!coherence_data) {
-		pr_err("fsl-diu-fb: could not allocate coherence data "
-		       "(size=%zu)\n", coherence_data_size);
-		return -ENOMEM;
-	}
-
-#endif
-
-	ret = platform_driver_register(&fsl_diu_driver);
-	if (ret) {
-		pr_err("fsl-diu-fb: failed to register platform driver\n");
-#if defined(CONFIG_NOT_COHERENT_CACHE)
-		vfree(coherence_data);
-#endif
-	}
-	return ret;
-}
-
-static void __exit fsl_diu_exit(void)
-{
-	platform_driver_unregister(&fsl_diu_driver);
-#if defined(CONFIG_NOT_COHERENT_CACHE)
-	vfree(coherence_data);
-#endif
-}
-
-module_init(fsl_diu_init);
-module_exit(fsl_diu_exit);
-
-MODULE_AUTHOR("York Sun <yorksun@freescale.com>");
-MODULE_DESCRIPTION("Freescale DIU framebuffer driver");
-MODULE_LICENSE("GPL");
-
-module_param_named(mode, fb_mode, charp, 0);
-MODULE_PARM_DESC(mode,
-	"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-module_param_named(bpp, default_bpp, ulong, 0);
-MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified in 'mode'");
-module_param_named(monitor, monitor_string, charp, 0);
-MODULE_PARM_DESC(monitor, "Specify the monitor port "
-	"(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform");
-
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
deleted file mode 100644
index 223896cc5f7d..000000000000
--- a/drivers/video/g364fb.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/* $Id: g364fb.c,v 1.3 1998/08/28 22:43:00 tsbogend Exp $
- *
- * linux/drivers/video/g364fb.c -- Mips Magnum frame buffer device
- *
- * (C) 1998 Thomas Bogendoerfer
- *
- *  This driver is based on tgafb.c
- *
- *	Copyright (C) 1997 Geert Uytterhoeven 
- *	Copyright (C) 1995  Jay Estabrook
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/jazz.h>
-
-/* 
- * Various defines for the G364
- */
-#define G364_MEM_BASE   0xe4400000
-#define G364_PORT_BASE  0xe4000000
-#define ID_REG 		0xe4000000	/* Read only */
-#define BOOT_REG 	0xe4080000
-#define TIMING_REG 	0xe4080108	/* to 0x080170 - DON'T TOUCH! */
-#define DISPLAY_REG 	0xe4080118
-#define VDISPLAY_REG 	0xe4080150
-#define MASK_REG 	0xe4080200
-#define CTLA_REG 	0xe4080300
-#define CURS_TOGGLE 	0x800000
-#define BIT_PER_PIX	0x700000	/* bits 22 to 20 of Control A */
-#define DELAY_SAMPLE    0x080000
-#define PORT_INTER	0x040000
-#define PIX_PIPE_DEL	0x030000	/* bits 17 and 16 of Control A */
-#define PIX_PIPE_DEL2	0x008000	/* same as above - don't ask me why */
-#define TR_CYCLE_TOG	0x004000
-#define VRAM_ADR_INC	0x003000	/* bits 13 and 12 of Control A */
-#define BLANK_OFF	0x000800
-#define FORCE_BLANK	0x000400
-#define BLK_FUN_SWTCH	0x000200
-#define BLANK_IO	0x000100
-#define BLANK_LEVEL	0x000080
-#define A_VID_FORM	0x000040
-#define D_SYNC_FORM	0x000020
-#define FRAME_FLY_PAT	0x000010
-#define OP_MODE		0x000008
-#define INTL_STAND	0x000004
-#define SCRN_FORM	0x000002
-#define ENABLE_VTG	0x000001
-#define TOP_REG 	0xe4080400
-#define CURS_PAL_REG 	0xe4080508	/* to 0x080518 */
-#define CHKSUM_REG 	0xe4080600	/* to 0x080610 - unused */
-#define CURS_POS_REG 	0xe4080638
-#define CLR_PAL_REG 	0xe4080800	/* to 0x080ff8 */
-#define CURS_PAT_REG 	0xe4081000	/* to 0x081ff8 */
-#define MON_ID_REG 	0xe4100000	/* unused */
-#define RESET_REG 	0xe4180000	/* Write only */
-
-static struct fb_info fb_info;
-
-static struct fb_fix_screeninfo fb_fix __initdata = {
-	.id 		= "G364 8plane",
-	.smem_start 	= 0x40000000,	/* physical address */
-	.type 		= FB_TYPE_PACKED_PIXELS,
-	.visual 	= FB_VISUAL_PSEUDOCOLOR,
-	.ypanstep 	= 1,
-	.accel 		= FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo fb_var __initdata = {
-	.bits_per_pixel = 8,
-	.red 		= { 0, 8, 0 },
-      	.green 		= { 0, 8, 0 },
-      	.blue		= { 0, 8, 0 },
-      	.activate	= FB_ACTIVATE_NOW,
-      	.height		= -1,
-      	.width		= -1,
-      	.pixclock	= 39722,
-      	.left_margin	= 40,
-      	.right_margin	= 24,
-      	.upper_margin	= 32,
-      	.lower_margin	= 11,
-      	.hsync_len 	= 96,
-      	.vsync_len 	= 2,
-      	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-/*
- *  Interface used by the world
- */
-int g364fb_init(void);
-
-static int g364fb_pan_display(struct fb_var_screeninfo *var,
-			      struct fb_info *info);
-static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
-			    u_int blue, u_int transp,
-			    struct fb_info *info);
-static int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-static int g364fb_blank(int blank, struct fb_info *info);
-
-static struct fb_ops g364fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= g364fb_setcolreg,
-	.fb_pan_display	= g364fb_pan_display,
-	.fb_blank	= g364fb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_cursor	= g364fb_cursor,
-};
-
-int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	
-	switch (cursor->enable) {
-	case CM_ERASE:
-		*(unsigned int *) CTLA_REG |= CURS_TOGGLE;
-		break;
-
-	case CM_MOVE:
-	case CM_DRAW:
-		*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
-		*(unsigned int *) CURS_POS_REG =
-		    ((x * fontwidth(p)) << 12) | ((y * fontheight(p)) -
-						  info->var.yoffset);
-		break;
-	}
-	return 0;
-}
-
-/*
- *  Pan or Wrap the Display
- *
- *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- */
-static int g364fb_pan_display(struct fb_var_screeninfo *var, 
-			      struct fb_info *info)
-{
-	if (var->xoffset ||
-	    var->yoffset + info->var.yres > info->var.yres_virtual)
-		return -EINVAL;
-
-	*(unsigned int *) TOP_REG = var->yoffset * info->var.xres;
-	return 0;
-}
-
-/*
- *  Blank the display.
- */
-static int g364fb_blank(int blank, struct fb_info *info)
-{
-	if (blank)
-		*(unsigned int *) CTLA_REG |= FORCE_BLANK;
-	else
-		*(unsigned int *) CTLA_REG &= ~FORCE_BLANK;
-	return 0;
-}
-
-/*
- *  Set a single color register. Return != 0 for invalid regno.
- */
-static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
-			    u_int blue, u_int transp, struct fb_info *info)
-{
-	volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
-
-	if (regno > 255)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	ptr[regno << 1] = (red << 16) | (green << 8) | blue;
-
-	return 0;
-}
-
-/*
- *  Initialisation
- */
-int __init g364fb_init(void)
-{
-	volatile unsigned int *pal_ptr =
-	    (volatile unsigned int *) CLR_PAL_REG;
-	volatile unsigned int *curs_pal_ptr =
-	    (volatile unsigned int *) CURS_PAL_REG;
-	int mem, i, j;
-
-	if (fb_get_options("g364fb", NULL))
-		return -ENODEV;
-
-	/* TBD: G364 detection */
-
-	/* get the resolution set by ARC console */
-	*(volatile unsigned int *) CTLA_REG &= ~ENABLE_VTG;
-	fb_var.xres =
-	    (*((volatile unsigned int *) DISPLAY_REG) & 0x00ffffff) * 4;
-	fb_var.yres =
-	    (*((volatile unsigned int *) VDISPLAY_REG) & 0x00ffffff) / 2;
-	*(volatile unsigned int *) CTLA_REG |= ENABLE_VTG;
-
-	/* setup cursor */
-	curs_pal_ptr[0] |= 0x00ffffff;
-	curs_pal_ptr[2] |= 0x00ffffff;
-	curs_pal_ptr[4] |= 0x00ffffff;
-
-	/*
-	 * first set the whole cursor to transparent
-	 */
-	for (i = 0; i < 512; i++)
-		*(unsigned short *) (CURS_PAT_REG + i * 8) = 0;
-
-	/*
-	 * switch the last two lines to cursor palette 3
-	 * we assume here, that FONTSIZE_X is 8
-	 */
-	*(unsigned short *) (CURS_PAT_REG + 14 * 64) = 0xffff;
-	*(unsigned short *) (CURS_PAT_REG + 15 * 64) = 0xffff;
-	fb_var.xres_virtual = fbvar.xres;
-	fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
-	fb_fix.smem_start = 0x40000000;	/* physical address */
-	/* get size of video memory; this is special for the JAZZ hardware */
-	mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3;
-	fb_fix.smem_len = (1 << (mem * 2)) * 512 * 1024;
-	fb_var.yres_virtual = fb_fix.smem_len / fb_var.xres;
-
-	fb_info.fbops = &g364fb_ops;
-	fb_info.screen_base = (char *) G364_MEM_BASE;	/* virtual kernel address */
-	fb_info.var = fb_var;
-	fb_info.fix = fb_fix;
-	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-
-	fb_alloc_cmap(&fb_info.cmap, 255, 0);
-
-	if (register_framebuffer(&fb_info) < 0)
-		return -EINVAL;
-	return 0;
-}
-
-module_init(g364fb_init);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
deleted file mode 100644
index 3ec65a878ac8..000000000000
--- a/drivers/video/gbefb.c
+++ /dev/null
@@ -1,1309 +0,0 @@
-/*
- *  SGI GBE frame buffer driver
- *
- *  Copyright (C) 1999 Silicon Graphics, Inc. - Jeffrey Newquist
- *  Copyright (C) 2002 Vivien Chappelier <vivien.chappelier@linux-mips.org>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/gfp.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#ifdef CONFIG_X86
-#include <asm/mtrr.h>
-#endif
-#ifdef CONFIG_MIPS
-#include <asm/addrspace.h>
-#endif
-#include <asm/byteorder.h>
-#include <asm/tlbflush.h>
-
-#include <video/gbe.h>
-
-static struct sgi_gbe *gbe;
-
-struct gbefb_par {
-	struct fb_var_screeninfo var;
-	struct gbe_timing_info timing;
-	int valid;
-};
-
-#ifdef CONFIG_SGI_IP32
-#define GBE_BASE	0x16000000 /* SGI O2 */
-#endif
-
-/* macro for fastest write-though access to the framebuffer */
-#ifdef CONFIG_MIPS
-#ifdef CONFIG_CPU_R10000
-#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_UNCACHED_ACCELERATED)
-#else
-#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA)
-#endif
-#endif
-#ifdef CONFIG_X86
-#define pgprot_fb(_prot) ((_prot) | _PAGE_PCD)
-#endif
-
-/*
- *  RAM we reserve for the frame buffer. This defines the maximum screen
- *  size
- */
-#if CONFIG_FB_GBE_MEM > 8
-#error GBE Framebuffer cannot use more than 8MB of memory
-#endif
-
-#define TILE_SHIFT 16
-#define TILE_SIZE (1 << TILE_SHIFT)
-#define TILE_MASK (TILE_SIZE - 1)
-
-static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
-static void *gbe_mem;
-static dma_addr_t gbe_dma_addr;
-static unsigned long gbe_mem_phys;
-
-static struct {
-	uint16_t *cpu;
-	dma_addr_t dma;
-} gbe_tiles;
-
-static int gbe_revision;
-
-static int ypan, ywrap;
-
-static uint32_t pseudo_palette[16];
-static uint32_t gbe_cmap[256];
-static int gbe_turned_on; /* 0 turned off, 1 turned on */
-
-static char *mode_option = NULL;
-
-/* default CRT mode */
-static struct fb_var_screeninfo default_var_CRT = {
-	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-	.xres		= 640,
-	.yres		= 480,
-	.xres_virtual	= 640,
-	.yres_virtual	= 480,
-	.xoffset	= 0,
-	.yoffset	= 0,
-	.bits_per_pixel	= 8,
-	.grayscale	= 0,
-	.red		= { 0, 8, 0 },
-	.green		= { 0, 8, 0 },
-	.blue		= { 0, 8, 0 },
-	.transp		= { 0, 0, 0 },
-	.nonstd		= 0,
-	.activate	= 0,
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= 0,
-	.pixclock	= 39722,	/* picoseconds */
-	.left_margin	= 48,
-	.right_margin	= 16,
-	.upper_margin	= 33,
-	.lower_margin	= 10,
-	.hsync_len	= 96,
-	.vsync_len	= 2,
-	.sync		= 0,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-/* default LCD mode */
-static struct fb_var_screeninfo default_var_LCD = {
-	/* 1600x1024, 8 bpp */
-	.xres		= 1600,
-	.yres		= 1024,
-	.xres_virtual	= 1600,
-	.yres_virtual	= 1024,
-	.xoffset	= 0,
-	.yoffset	= 0,
-	.bits_per_pixel	= 8,
-	.grayscale	= 0,
-	.red		= { 0, 8, 0 },
-	.green		= { 0, 8, 0 },
-	.blue		= { 0, 8, 0 },
-	.transp		= { 0, 0, 0 },
-	.nonstd		= 0,
-	.activate	= 0,
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= 0,
-	.pixclock	= 9353,
-	.left_margin	= 20,
-	.right_margin	= 30,
-	.upper_margin	= 37,
-	.lower_margin	= 3,
-	.hsync_len	= 20,
-	.vsync_len	= 3,
-	.sync		= 0,
-	.vmode		= FB_VMODE_NONINTERLACED
-};
-
-/* default modedb mode */
-/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
-static struct fb_videomode default_mode_CRT = {
-	.refresh	= 60,
-	.xres		= 640,
-	.yres		= 480,
-	.pixclock	= 39722,
-	.left_margin	= 48,
-	.right_margin	= 16,
-	.upper_margin	= 33,
-	.lower_margin	= 10,
-	.hsync_len	= 96,
-	.vsync_len	= 2,
-	.sync		= 0,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-/* 1600x1024 SGI flatpanel 1600sw */
-static struct fb_videomode default_mode_LCD = {
-	/* 1600x1024, 8 bpp */
-	.xres		= 1600,
-	.yres		= 1024,
-	.pixclock	= 9353,
-	.left_margin	= 20,
-	.right_margin	= 30,
-	.upper_margin	= 37,
-	.lower_margin	= 3,
-	.hsync_len	= 20,
-	.vsync_len	= 3,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_videomode *default_mode = &default_mode_CRT;
-static struct fb_var_screeninfo *default_var = &default_var_CRT;
-
-static int flat_panel_enabled = 0;
-
-static void gbe_reset(void)
-{
-	/* Turn on dotclock PLL */
-	gbe->ctrlstat = 0x300aa000;
-}
-
-
-/*
- * Function:	gbe_turn_off
- * Parameters:	(None)
- * Description:	This should turn off the monitor and gbe.  This is used
- *              when switching between the serial console and the graphics
- *              console.
- */
-
-static void gbe_turn_off(void)
-{
-	int i;
-	unsigned int val, x, y, vpixen_off;
-
-	gbe_turned_on = 0;
-
-	/* check if pixel counter is on */
-	val = gbe->vt_xy;
-	if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1)
-		return;
-
-	/* turn off DMA */
-	val = gbe->ovr_control;
-	SET_GBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, val, 0);
-	gbe->ovr_control = val;
-	udelay(1000);
-	val = gbe->frm_control;
-	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0);
-	gbe->frm_control = val;
-	udelay(1000);
-	val = gbe->did_control;
-	SET_GBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, val, 0);
-	gbe->did_control = val;
-	udelay(1000);
-
-	/* We have to wait through two vertical retrace periods before
-	 * the pixel DMA is turned off for sure. */
-	for (i = 0; i < 10000; i++) {
-		val = gbe->frm_inhwctrl;
-		if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val)) {
-			udelay(10);
-		} else {
-			val = gbe->ovr_inhwctrl;
-			if (GET_GBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, val)) {
-				udelay(10);
-			} else {
-				val = gbe->did_inhwctrl;
-				if (GET_GBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, val)) {
-					udelay(10);
-				} else
-					break;
-			}
-		}
-	}
-	if (i == 10000)
-		printk(KERN_ERR "gbefb: turn off DMA timed out\n");
-
-	/* wait for vpixen_off */
-	val = gbe->vt_vpixen;
-	vpixen_off = GET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val);
-
-	for (i = 0; i < 100000; i++) {
-		val = gbe->vt_xy;
-		x = GET_GBE_FIELD(VT_XY, X, val);
-		y = GET_GBE_FIELD(VT_XY, Y, val);
-		if (y < vpixen_off)
-			break;
-		udelay(1);
-	}
-	if (i == 100000)
-		printk(KERN_ERR
-		       "gbefb: wait for vpixen_off timed out\n");
-	for (i = 0; i < 10000; i++) {
-		val = gbe->vt_xy;
-		x = GET_GBE_FIELD(VT_XY, X, val);
-		y = GET_GBE_FIELD(VT_XY, Y, val);
-		if (y > vpixen_off)
-			break;
-		udelay(1);
-	}
-	if (i == 10000)
-		printk(KERN_ERR "gbefb: wait for vpixen_off timed out\n");
-
-	/* turn off pixel counter */
-	val = 0;
-	SET_GBE_FIELD(VT_XY, FREEZE, val, 1);
-	gbe->vt_xy = val;
-	udelay(10000);
-	for (i = 0; i < 10000; i++) {
-		val = gbe->vt_xy;
-		if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1)
-			udelay(10);
-		else
-			break;
-	}
-	if (i == 10000)
-		printk(KERN_ERR "gbefb: turn off pixel clock timed out\n");
-
-	/* turn off dot clock */
-	val = gbe->dotclock;
-	SET_GBE_FIELD(DOTCLK, RUN, val, 0);
-	gbe->dotclock = val;
-	udelay(10000);
-	for (i = 0; i < 10000; i++) {
-		val = gbe->dotclock;
-		if (GET_GBE_FIELD(DOTCLK, RUN, val))
-			udelay(10);
-		else
-			break;
-	}
-	if (i == 10000)
-		printk(KERN_ERR "gbefb: turn off dotclock timed out\n");
-
-	/* reset the frame DMA FIFO */
-	val = gbe->frm_size_tile;
-	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 1);
-	gbe->frm_size_tile = val;
-	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 0);
-	gbe->frm_size_tile = val;
-}
-
-static void gbe_turn_on(void)
-{
-	unsigned int val, i;
-
-	/*
-	 * Check if pixel counter is off, for unknown reason this
-	 * code hangs Visual Workstations
-	 */
-	if (gbe_revision < 2) {
-		val = gbe->vt_xy;
-		if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 0)
-			return;
-	}
-
-	/* turn on dot clock */
-	val = gbe->dotclock;
-	SET_GBE_FIELD(DOTCLK, RUN, val, 1);
-	gbe->dotclock = val;
-	udelay(10000);
-	for (i = 0; i < 10000; i++) {
-		val = gbe->dotclock;
-		if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1)
-			udelay(10);
-		else
-			break;
-	}
-	if (i == 10000)
-		printk(KERN_ERR "gbefb: turn on dotclock timed out\n");
-
-	/* turn on pixel counter */
-	val = 0;
-	SET_GBE_FIELD(VT_XY, FREEZE, val, 0);
-	gbe->vt_xy = val;
-	udelay(10000);
-	for (i = 0; i < 10000; i++) {
-		val = gbe->vt_xy;
-		if (GET_GBE_FIELD(VT_XY, FREEZE, val))
-			udelay(10);
-		else
-			break;
-	}
-	if (i == 10000)
-		printk(KERN_ERR "gbefb: turn on pixel clock timed out\n");
-
-	/* turn on DMA */
-	val = gbe->frm_control;
-	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 1);
-	gbe->frm_control = val;
-	udelay(1000);
-	for (i = 0; i < 10000; i++) {
-		val = gbe->frm_inhwctrl;
-		if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val) != 1)
-			udelay(10);
-		else
-			break;
-	}
-	if (i == 10000)
-		printk(KERN_ERR "gbefb: turn on DMA timed out\n");
-
-	gbe_turned_on = 1;
-}
-
-static void gbe_loadcmap(void)
-{
-	int i, j;
-
-	for (i = 0; i < 256; i++) {
-		for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
-			udelay(10);
-		if (j == 1000)
-			printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
-
-		gbe->cmap[i] = gbe_cmap[i];
-	}
-}
-
-/*
- *  Blank the display.
- */
-static int gbefb_blank(int blank, struct fb_info *info)
-{
-	/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-	switch (blank) {
-	case FB_BLANK_UNBLANK:		/* unblank */
-		gbe_turn_on();
-		gbe_loadcmap();
-		break;
-
-	case FB_BLANK_NORMAL:		/* blank */
-		gbe_turn_off();
-		break;
-
-	default:
-		/* Nothing */
-		break;
-	}
-	return 0;
-}
-
-/*
- *  Setup flatpanel related registers.
- */
-static void gbefb_setup_flatpanel(struct gbe_timing_info *timing)
-{
-	int fp_wid, fp_hgt, fp_vbs, fp_vbe;
-	u32 outputVal = 0;
-
-	SET_GBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal,
-		(timing->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
-	SET_GBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal,
-		(timing->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
-	gbe->vt_flags = outputVal;
-
-	/* Turn on the flat panel */
-	fp_wid = 1600;
-	fp_hgt = 1024;
-	fp_vbs = 0;
-	fp_vbe = 1600;
-	timing->pll_m = 4;
-	timing->pll_n = 1;
-	timing->pll_p = 0;
-
-	outputVal = 0;
-	SET_GBE_FIELD(FP_DE, ON, outputVal, fp_vbs);
-	SET_GBE_FIELD(FP_DE, OFF, outputVal, fp_vbe);
-	gbe->fp_de = outputVal;
-	outputVal = 0;
-	SET_GBE_FIELD(FP_HDRV, OFF, outputVal, fp_wid);
-	gbe->fp_hdrv = outputVal;
-	outputVal = 0;
-	SET_GBE_FIELD(FP_VDRV, ON, outputVal, 1);
-	SET_GBE_FIELD(FP_VDRV, OFF, outputVal, fp_hgt + 1);
-	gbe->fp_vdrv = outputVal;
-}
-
-struct gbe_pll_info {
-	int clock_rate;
-	int fvco_min;
-	int fvco_max;
-};
-
-static struct gbe_pll_info gbe_pll_table[2] = {
-	{ 20, 80, 220 },
-	{ 27, 80, 220 },
-};
-
-static int compute_gbe_timing(struct fb_var_screeninfo *var,
-			      struct gbe_timing_info *timing)
-{
-	int pll_m, pll_n, pll_p, error, best_m, best_n, best_p, best_error;
-	int pixclock;
-	struct gbe_pll_info *gbe_pll;
-
-	if (gbe_revision < 2)
-		gbe_pll = &gbe_pll_table[0];
-	else
-		gbe_pll = &gbe_pll_table[1];
-
-	/* Determine valid resolution and timing
-	 * GBE crystal runs at 20Mhz or 27Mhz
-	 * pll_m, pll_n, pll_p define the following frequencies
-	 * fvco = pll_m * 20Mhz / pll_n
-	 * fout = fvco / (2**pll_p) */
-	best_error = 1000000000;
-	best_n = best_m = best_p = 0;
-	for (pll_p = 0; pll_p < 4; pll_p++)
-		for (pll_m = 1; pll_m < 256; pll_m++)
-			for (pll_n = 1; pll_n < 64; pll_n++) {
-				pixclock = (1000000 / gbe_pll->clock_rate) *
-						(pll_n << pll_p) / pll_m;
-
-				error = var->pixclock - pixclock;
-
-				if (error < 0)
-					error = -error;
-
-				if (error < best_error &&
-				    pll_m / pll_n >
-				    gbe_pll->fvco_min / gbe_pll->clock_rate &&
- 				    pll_m / pll_n <
-				    gbe_pll->fvco_max / gbe_pll->clock_rate) {
-					best_error = error;
-					best_m = pll_m;
-					best_n = pll_n;
-					best_p = pll_p;
-				}
-			}
-
-	if (!best_n || !best_m)
-		return -EINVAL;	/* Resolution to high */
-
-	pixclock = (1000000 / gbe_pll->clock_rate) *
-		(best_n << best_p) / best_m;
-
-	/* set video timing information */
-	if (timing) {
-		timing->width = var->xres;
-		timing->height = var->yres;
-		timing->pll_m = best_m;
-		timing->pll_n = best_n;
-		timing->pll_p = best_p;
-		timing->cfreq = gbe_pll->clock_rate * 1000 * timing->pll_m /
-			(timing->pll_n << timing->pll_p);
-		timing->htotal = var->left_margin + var->xres +
-				var->right_margin + var->hsync_len;
-		timing->vtotal = var->upper_margin + var->yres +
-				var->lower_margin + var->vsync_len;
-		timing->fields_sec = 1000 * timing->cfreq / timing->htotal *
-				1000 / timing->vtotal;
-		timing->hblank_start = var->xres;
-		timing->vblank_start = var->yres;
-		timing->hblank_end = timing->htotal;
-		timing->hsync_start = var->xres + var->right_margin + 1;
-		timing->hsync_end = timing->hsync_start + var->hsync_len;
-		timing->vblank_end = timing->vtotal;
-		timing->vsync_start = var->yres + var->lower_margin + 1;
-		timing->vsync_end = timing->vsync_start + var->vsync_len;
-	}
-
-	return pixclock;
-}
-
-static void gbe_set_timing_info(struct gbe_timing_info *timing)
-{
-	int temp;
-	unsigned int val;
-
-	/* setup dot clock PLL */
-	val = 0;
-	SET_GBE_FIELD(DOTCLK, M, val, timing->pll_m - 1);
-	SET_GBE_FIELD(DOTCLK, N, val, timing->pll_n - 1);
-	SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p);
-	SET_GBE_FIELD(DOTCLK, RUN, val, 0);	/* do not start yet */
-	gbe->dotclock = val;
-	udelay(10000);
-
-	/* setup pixel counter */
-	val = 0;
-	SET_GBE_FIELD(VT_XYMAX, MAXX, val, timing->htotal);
-	SET_GBE_FIELD(VT_XYMAX, MAXY, val, timing->vtotal);
-	gbe->vt_xymax = val;
-
-	/* setup video timing signals */
-	val = 0;
-	SET_GBE_FIELD(VT_VSYNC, VSYNC_ON, val, timing->vsync_start);
-	SET_GBE_FIELD(VT_VSYNC, VSYNC_OFF, val, timing->vsync_end);
-	gbe->vt_vsync = val;
-	val = 0;
-	SET_GBE_FIELD(VT_HSYNC, HSYNC_ON, val, timing->hsync_start);
-	SET_GBE_FIELD(VT_HSYNC, HSYNC_OFF, val, timing->hsync_end);
-	gbe->vt_hsync = val;
-	val = 0;
-	SET_GBE_FIELD(VT_VBLANK, VBLANK_ON, val, timing->vblank_start);
-	SET_GBE_FIELD(VT_VBLANK, VBLANK_OFF, val, timing->vblank_end);
-	gbe->vt_vblank = val;
-	val = 0;
-	SET_GBE_FIELD(VT_HBLANK, HBLANK_ON, val,
-		      timing->hblank_start - 5);
-	SET_GBE_FIELD(VT_HBLANK, HBLANK_OFF, val,
-		      timing->hblank_end - 3);
-	gbe->vt_hblank = val;
-
-	/* setup internal timing signals */
-	val = 0;
-	SET_GBE_FIELD(VT_VCMAP, VCMAP_ON, val, timing->vblank_start);
-	SET_GBE_FIELD(VT_VCMAP, VCMAP_OFF, val, timing->vblank_end);
-	gbe->vt_vcmap = val;
-	val = 0;
-	SET_GBE_FIELD(VT_HCMAP, HCMAP_ON, val, timing->hblank_start);
-	SET_GBE_FIELD(VT_HCMAP, HCMAP_OFF, val, timing->hblank_end);
-	gbe->vt_hcmap = val;
-
-	val = 0;
-	temp = timing->vblank_start - timing->vblank_end - 1;
-	if (temp > 0)
-		temp = -temp;
-
-	if (flat_panel_enabled)
-		gbefb_setup_flatpanel(timing);
-
-	SET_GBE_FIELD(DID_START_XY, DID_STARTY, val, (u32) temp);
-	if (timing->hblank_end >= 20)
-		SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
-			      timing->hblank_end - 20);
-	else
-		SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
-			      timing->htotal - (20 - timing->hblank_end));
-	gbe->did_start_xy = val;
-
-	val = 0;
-	SET_GBE_FIELD(CRS_START_XY, CRS_STARTY, val, (u32) (temp + 1));
-	if (timing->hblank_end >= GBE_CRS_MAGIC)
-		SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
-			      timing->hblank_end - GBE_CRS_MAGIC);
-	else
-		SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
-			      timing->htotal - (GBE_CRS_MAGIC -
-						timing->hblank_end));
-	gbe->crs_start_xy = val;
-
-	val = 0;
-	SET_GBE_FIELD(VC_START_XY, VC_STARTY, val, (u32) temp);
-	SET_GBE_FIELD(VC_START_XY, VC_STARTX, val, timing->hblank_end - 4);
-	gbe->vc_start_xy = val;
-
-	val = 0;
-	temp = timing->hblank_end - GBE_PIXEN_MAGIC_ON;
-	if (temp < 0)
-		temp += timing->htotal;	/* allow blank to wrap around */
-
-	SET_GBE_FIELD(VT_HPIXEN, HPIXEN_ON, val, temp);
-	SET_GBE_FIELD(VT_HPIXEN, HPIXEN_OFF, val,
-		      ((temp + timing->width -
-			GBE_PIXEN_MAGIC_OFF) % timing->htotal));
-	gbe->vt_hpixen = val;
-
-	val = 0;
-	SET_GBE_FIELD(VT_VPIXEN, VPIXEN_ON, val, timing->vblank_end);
-	SET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val, timing->vblank_start);
-	gbe->vt_vpixen = val;
-
-	/* turn off sync on green */
-	val = 0;
-	SET_GBE_FIELD(VT_FLAGS, SYNC_LOW, val, 1);
-	gbe->vt_flags = val;
-}
-
-/*
- *  Set the hardware according to 'par'.
- */
-
-static int gbefb_set_par(struct fb_info *info)
-{
-	int i;
-	unsigned int val;
-	int wholeTilesX, partTilesX, maxPixelsPerTileX;
-	int height_pix;
-	int xpmax, ypmax;	/* Monitor resolution */
-	int bytesPerPixel;	/* Bytes per pixel */
-	struct gbefb_par *par = (struct gbefb_par *) info->par;
-
-	compute_gbe_timing(&info->var, &par->timing);
-
-	bytesPerPixel = info->var.bits_per_pixel / 8;
-	info->fix.line_length = info->var.xres_virtual * bytesPerPixel;
-	xpmax = par->timing.width;
-	ypmax = par->timing.height;
-
-	/* turn off GBE */
-	gbe_turn_off();
-
-	/* set timing info */
-	gbe_set_timing_info(&par->timing);
-
-	/* initialize DIDs */
-	val = 0;
-	switch (bytesPerPixel) {
-	case 1:
-		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8);
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 2:
-		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5);
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	case 4:
-		SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8);
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	}
-	SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH);
-
-	for (i = 0; i < 32; i++)
-		gbe->mode_regs[i] = val;
-
-	/* Initialize interrupts */
-	gbe->vt_intr01 = 0xffffffff;
-	gbe->vt_intr23 = 0xffffffff;
-
-	/* HACK:
-	   The GBE hardware uses a tiled memory to screen mapping. Tiles are
-	   blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
-	   16bit and 32 bit modes (64 kB). They cover the screen with partial
-	   tiles on the right and/or bottom of the screen if needed.
-	   For example in 640x480 8 bit mode the mapping is:
-
-	   <-------- 640 ----->
-	   <---- 512 ----><128|384 offscreen>
-	   ^  ^
-	   | 128    [tile 0]        [tile 1]
-	   |  v
-	   ^
-	   4 128    [tile 2]        [tile 3]
-	   8  v
-	   0  ^
-	   128    [tile 4]        [tile 5]
-	   |  v
-	   |  ^
-	   v  96    [tile 6]        [tile 7]
-	   32 offscreen
-
-	   Tiles have the advantage that they can be allocated individually in
-	   memory. However, this mapping is not linear at all, which is not
-	   really convenient. In order to support linear addressing, the GBE
-	   DMA hardware is fooled into thinking the screen is only one tile
-	   large and but has a greater height, so that the DMA transfer covers
-	   the same region.
-	   Tiles are still allocated as independent chunks of 64KB of
-	   continuous physical memory and remapped so that the kernel sees the
-	   framebuffer as a continuous virtual memory. The GBE tile table is
-	   set up so that each tile references one of these 64k blocks:
-
-	   GBE -> tile list    framebuffer           TLB   <------------ CPU
-	          [ tile 0 ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     ^
-	             ...           ...              ...       linear virtual FB
-	          [ tile n ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     v
-
-
-	   The GBE hardware is then told that the buffer is 512*tweaked_height,
-	   with tweaked_height = real_width*real_height/pixels_per_tile.
-	   Thus the GBE hardware will scan the first tile, filing the first 64k
-	   covered region of the screen, and then will proceed to the next
-	   tile, until the whole screen is covered.
-
-	   Here is what would happen at 640x480 8bit:
-
-	   normal tiling               linear
-	   ^   11111111111111112222    11111111111111111111  ^
-	   128 11111111111111112222    11111111111111111111 102 lines
-	       11111111111111112222    11111111111111111111  v
-	   V   11111111111111112222    11111111222222222222
-	       33333333333333334444    22222222222222222222
-	       33333333333333334444    22222222222222222222
-	       <      512     >        <  256 >               102*640+256 = 64k
-
-	   NOTE: The only mode for which this is not working is 800x600 8bit,
-	   as 800*600/512 = 937.5 which is not integer and thus causes
-	   flickering.
-	   I guess this is not so important as one can use 640x480 8bit or
-	   800x600 16bit anyway.
-	 */
-
-	/* Tell gbe about the tiles table location */
-	/* tile_ptr -> [ tile 1 ] -> FB mem */
-	/*             [ tile 2 ] -> FB mem */
-	/*               ...                */
-	val = 0;
-	SET_GBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, val, gbe_tiles.dma >> 9);
-	SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0); /* do not start */
-	SET_GBE_FIELD(FRM_CONTROL, FRM_LINEAR, val, 0);
-	gbe->frm_control = val;
-
-	maxPixelsPerTileX = 512 / bytesPerPixel;
-	wholeTilesX = 1;
-	partTilesX = 0;
-
-	/* Initialize the framebuffer */
-	val = 0;
-	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, val, wholeTilesX);
-	SET_GBE_FIELD(FRM_SIZE_TILE, FRM_RHS, val, partTilesX);
-
-	switch (bytesPerPixel) {
-	case 1:
-		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
-			      GBE_FRM_DEPTH_8);
-		break;
-	case 2:
-		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
-			      GBE_FRM_DEPTH_16);
-		break;
-	case 4:
-		SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
-			      GBE_FRM_DEPTH_32);
-		break;
-	}
-	gbe->frm_size_tile = val;
-
-	/* compute tweaked height */
-	height_pix = xpmax * ypmax / maxPixelsPerTileX;
-
-	val = 0;
-	SET_GBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, val, height_pix);
-	gbe->frm_size_pixel = val;
-
-	/* turn off DID and overlay DMA */
-	gbe->did_control = 0;
-	gbe->ovr_width_tile = 0;
-
-	/* Turn off mouse cursor */
-	gbe->crs_ctl = 0;
-
-	/* Turn on GBE */
-	gbe_turn_on();
-
-	/* Initialize the gamma map */
-	udelay(10);
-	for (i = 0; i < 256; i++)
-		gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8);
-
-	/* Initialize the color map */
-	for (i = 0; i < 256; i++)
-		gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24);
-
-	gbe_loadcmap();
-
-	return 0;
-}
-
-static void gbefb_encode_fix(struct fb_fix_screeninfo *fix,
-			     struct fb_var_screeninfo *var)
-{
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, "SGI GBE");
-	fix->smem_start = (unsigned long) gbe_mem;
-	fix->smem_len = gbe_mem_size;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	fix->accel = FB_ACCEL_NONE;
-	switch (var->bits_per_pixel) {
-	case 8:
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	default:
-		fix->visual = FB_VISUAL_TRUECOLOR;
-		break;
-	}
-	fix->ywrapstep = 0;
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
-	fix->mmio_start = GBE_BASE;
-	fix->mmio_len = sizeof(struct sgi_gbe);
-}
-
-/*
- *  Set a single color register. The values supplied are already
- *  rounded down to the hardware's capabilities (according to the
- *  entries in the var structure). Return != 0 for invalid regno.
- */
-
-static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info *info)
-{
-	int i;
-
-	if (regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	if (info->var.bits_per_pixel <= 8) {
-		gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
-		if (gbe_turned_on) {
-			/* wait for the color map FIFO to have a free entry */
-			for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
-				udelay(10);
-			if (i == 1000) {
-				printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
-				return 1;
-			}
-			gbe->cmap[regno] = gbe_cmap[regno];
-		}
-	} else if (regno < 16) {
-		switch (info->var.bits_per_pixel) {
-		case 15:
-		case 16:
-			red >>= 3;
-			green >>= 3;
-			blue >>= 3;
-			pseudo_palette[regno] =
-				(red << info->var.red.offset) |
-				(green << info->var.green.offset) |
-				(blue << info->var.blue.offset);
-			break;
-		case 32:
-			pseudo_palette[regno] =
-				(red << info->var.red.offset) |
-				(green << info->var.green.offset) |
-				(blue << info->var.blue.offset);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-/*
- *  Check video mode validity, eventually modify var to best match.
- */
-static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	unsigned int line_length;
-	struct gbe_timing_info timing;
-	int ret;
-
-	/* Limit bpp to 8, 16, and 32 */
-	if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel <= 32)
-		var->bits_per_pixel = 32;
-	else
-		return -EINVAL;
-
-	/* Check the mode can be mapped linearly with the tile table trick. */
-	/* This requires width x height x bytes/pixel be a multiple of 512 */
-	if ((var->xres * var->yres * var->bits_per_pixel) & 4095)
-		return -EINVAL;
-
-	var->grayscale = 0;	/* No grayscale for now */
-
-	ret = compute_gbe_timing(var, &timing);
-	var->pixclock = ret;
-	if (ret < 0)
-		return -EINVAL;
-
-	/* Adjust virtual resolution, if necessary */
-	if (var->xres > var->xres_virtual || (!ywrap && !ypan))
-		var->xres_virtual = var->xres;
-	if (var->yres > var->yres_virtual || (!ywrap && !ypan))
-		var->yres_virtual = var->yres;
-
-	if (var->vmode & FB_VMODE_CONUPDATE) {
-		var->vmode |= FB_VMODE_YWRAP;
-		var->xoffset = info->var.xoffset;
-		var->yoffset = info->var.yoffset;
-	}
-
-	/* No grayscale for now */
-	var->grayscale = 0;
-
-	/* Memory limit */
-	line_length = var->xres_virtual * var->bits_per_pixel / 8;
-	if (line_length * var->yres_virtual > gbe_mem_size)
-		return -ENOMEM;	/* Virtual resolution too high */
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:		/* RGB 1555 */
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 32:		/* RGB 8888 */
-		var->red.offset = 24;
-		var->red.length = 8;
-		var->green.offset = 16;
-		var->green.length = 8;
-		var->blue.offset = 8;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 8;
-		break;
-	}
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	var->left_margin = timing.htotal - timing.hsync_end;
-	var->right_margin = timing.hsync_start - timing.width;
-	var->upper_margin = timing.vtotal - timing.vsync_end;
-	var->lower_margin = timing.vsync_start - timing.height;
-	var->hsync_len = timing.hsync_end - timing.hsync_start;
-	var->vsync_len = timing.vsync_end - timing.vsync_start;
-
-	return 0;
-}
-
-static int gbefb_mmap(struct fb_info *info,
-			struct vm_area_struct *vma)
-{
-	unsigned long size = vma->vm_end - vma->vm_start;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	unsigned long addr;
-	unsigned long phys_addr, phys_size;
-	u16 *tile;
-
-	/* check range */
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-	if (size > gbe_mem_size)
-		return -EINVAL;
-	if (offset > gbe_mem_size - size)
-		return -EINVAL;
-
-	/* remap using the fastest write-through mode on architecture */
-	/* try not polluting the cache when possible */
-	pgprot_val(vma->vm_page_prot) =
-		pgprot_fb(pgprot_val(vma->vm_page_prot));
-
-	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
-
-	/* look for the starting tile */
-	tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
-	addr = vma->vm_start;
-	offset &= TILE_MASK;
-
-	/* remap each tile separately */
-	do {
-		phys_addr = (((unsigned long) (*tile)) << TILE_SHIFT) + offset;
-		if ((offset + size) < TILE_SIZE)
-			phys_size = size;
-		else
-			phys_size = TILE_SIZE - offset;
-
-		if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT,
-						phys_size, vma->vm_page_prot))
-			return -EAGAIN;
-
-		offset = 0;
-		size -= phys_size;
-		addr += phys_size;
-		tile++;
-	} while (size);
-
-	return 0;
-}
-
-static struct fb_ops gbefb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= gbefb_check_var,
-	.fb_set_par	= gbefb_set_par,
-	.fb_setcolreg	= gbefb_setcolreg,
-	.fb_mmap	= gbefb_mmap,
-	.fb_blank	= gbefb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-/*
- * sysfs
- */
-
-static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size);
-}
-
-static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
-
-static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
-}
-
-static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
-
-static void gbefb_remove_sysfs(struct device *dev)
-{
-	device_remove_file(dev, &dev_attr_size);
-	device_remove_file(dev, &dev_attr_revision);
-}
-
-static void gbefb_create_sysfs(struct device *dev)
-{
-	device_create_file(dev, &dev_attr_size);
-	device_create_file(dev, &dev_attr_revision);
-}
-
-/*
- * Initialization
- */
-
-static int gbefb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "monitor:", 8)) {
-			if (!strncmp(this_opt + 8, "crt", 3)) {
-				flat_panel_enabled = 0;
-				default_var = &default_var_CRT;
-				default_mode = &default_mode_CRT;
-			} else if (!strncmp(this_opt + 8, "1600sw", 6) ||
-				   !strncmp(this_opt + 8, "lcd", 3)) {
-				flat_panel_enabled = 1;
-				default_var = &default_var_LCD;
-				default_mode = &default_mode_LCD;
-			}
-		} else if (!strncmp(this_opt, "mem:", 4)) {
-			gbe_mem_size = memparse(this_opt + 4, &this_opt);
-			if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024)
-				gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024;
-			if (gbe_mem_size < TILE_SIZE)
-				gbe_mem_size = TILE_SIZE;
-		} else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-
-static int gbefb_probe(struct platform_device *p_dev)
-{
-	int i, ret = 0;
-	struct fb_info *info;
-	struct gbefb_par *par;
-#ifndef MODULE
-	char *options = NULL;
-#endif
-
-	info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev);
-	if (!info)
-		return -ENOMEM;
-
-#ifndef MODULE
-	if (fb_get_options("gbefb", &options)) {
-		ret = -ENODEV;
-		goto out_release_framebuffer;
-	}
-	gbefb_setup(options);
-#endif
-
-	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
-		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
-		ret = -EBUSY;
-		goto out_release_framebuffer;
-	}
-
-	gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE,
-					      sizeof(struct sgi_gbe));
-	if (!gbe) {
-		printk(KERN_ERR "gbefb: couldn't map mmio region\n");
-		ret = -ENXIO;
-		goto out_release_mem_region;
-	}
-	gbe_revision = gbe->ctrlstat & 15;
-
-	gbe_tiles.cpu =
-		dma_alloc_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
-				   &gbe_tiles.dma, GFP_KERNEL);
-	if (!gbe_tiles.cpu) {
-		printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
-		ret = -ENOMEM;
-		goto out_release_mem_region;
-	}
-
-	if (gbe_mem_phys) {
-		/* memory was allocated at boot time */
-		gbe_mem = devm_ioremap_nocache(&p_dev->dev, gbe_mem_phys,
-					       gbe_mem_size);
-		if (!gbe_mem) {
-			printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
-			ret = -ENOMEM;
-			goto out_tiles_free;
-		}
-
-		gbe_dma_addr = 0;
-	} else {
-		/* try to allocate memory with the classical allocator
-		 * this has high chance to fail on low memory machines */
-		gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,
-					     GFP_KERNEL);
-		if (!gbe_mem) {
-			printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
-			ret = -ENOMEM;
-			goto out_tiles_free;
-		}
-
-		gbe_mem_phys = (unsigned long) gbe_dma_addr;
-	}
-
-#ifdef CONFIG_X86
-	mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);
-#endif
-
-	/* map framebuffer memory into tiles table */
-	for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
-		gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
-
-	info->fbops = &gbefb_ops;
-	info->pseudo_palette = pseudo_palette;
-	info->flags = FBINFO_DEFAULT;
-	info->screen_base = gbe_mem;
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	/* reset GBE */
-	gbe_reset();
-
-	par = info->par;
-	/* turn on default video mode */
-	if (fb_find_mode(&par->var, info, mode_option, NULL, 0,
-			 default_mode, 8) == 0)
-		par->var = *default_var;
-	info->var = par->var;
-	gbefb_check_var(&par->var, info);
-	gbefb_encode_fix(&info->fix, &info->var);
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "gbefb: couldn't register framebuffer\n");
-		ret = -ENXIO;
-		goto out_gbe_unmap;
-	}
-
-	platform_set_drvdata(p_dev, info);
-	gbefb_create_sysfs(&p_dev->dev);
-
-	fb_info(info, "%s rev %d @ 0x%08x using %dkB memory\n",
-		info->fix.id, gbe_revision, (unsigned)GBE_BASE,
-		gbe_mem_size >> 10);
-
-	return 0;
-
-out_gbe_unmap:
-	if (gbe_dma_addr)
-		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
-out_tiles_free:
-	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
-			  (void *)gbe_tiles.cpu, gbe_tiles.dma);
-out_release_mem_region:
-	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
-out_release_framebuffer:
-	framebuffer_release(info);
-
-	return ret;
-}
-
-static int gbefb_remove(struct platform_device* p_dev)
-{
-	struct fb_info *info = platform_get_drvdata(p_dev);
-
-	unregister_framebuffer(info);
-	gbe_turn_off();
-	if (gbe_dma_addr)
-		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
-	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
-			  (void *)gbe_tiles.cpu, gbe_tiles.dma);
-	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
-	gbefb_remove_sysfs(&p_dev->dev);
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static struct platform_driver gbefb_driver = {
-	.probe = gbefb_probe,
-	.remove = gbefb_remove,
-	.driver	= {
-		.name = "gbefb",
-	},
-};
-
-static struct platform_device *gbefb_device;
-
-static int __init gbefb_init(void)
-{
-	int ret = platform_driver_register(&gbefb_driver);
-	if (!ret) {
-		gbefb_device = platform_device_alloc("gbefb", 0);
-		if (gbefb_device) {
-			ret = platform_device_add(gbefb_device);
-		} else {
-			ret = -ENOMEM;
-		}
-		if (ret) {
-			platform_device_put(gbefb_device);
-			platform_driver_unregister(&gbefb_driver);
-		}
-	}
-	return ret;
-}
-
-static void __exit gbefb_exit(void)
-{
-	platform_device_unregister(gbefb_device);
-	platform_driver_unregister(&gbefb_driver);
-}
-
-module_init(gbefb_init);
-module_exit(gbefb_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
deleted file mode 100644
index 1e8555284786..000000000000
--- a/drivers/video/geode/Kconfig
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# Geode family framebuffer configuration
-#
-config FB_GEODE
-	bool "AMD Geode family framebuffer support"
-	depends on FB && PCI && (X86_32 || (X86 && COMPILE_TEST))
-	---help---
-	  Say 'Y' here to allow you to select framebuffer drivers for
-	  the AMD Geode family of processors.
-
-config FB_GEODE_LX
-	tristate "AMD Geode LX framebuffer support"
-	depends on FB && FB_GEODE
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Framebuffer driver for the display controller integrated into the
-	  AMD Geode LX processors.
-
-	  To compile this driver as a module, choose M here: the module will
-	  be called lxfb.
-
-	  If unsure, say N.
-
-config FB_GEODE_GX
-	tristate "AMD Geode GX framebuffer support"
-	depends on FB && FB_GEODE
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Framebuffer driver for the display controller integrated into the
-	  AMD Geode GX processors.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called gxfb.
-
-	  If unsure, say N.
-
-config FB_GEODE_GX1
-	tristate "AMD Geode GX1 framebuffer support"
-	depends on FB && FB_GEODE
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Framebuffer driver for the display controller integrated into the
-	  AMD Geode GX1 processor.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called gx1fb.
-
-	  If unsure, say N.
diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
deleted file mode 100644
index 5c98da126883..000000000000
--- a/drivers/video/geode/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# Makefile for the Geode family framebuffer drivers
-
-obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
-obj-$(CONFIG_FB_GEODE_GX)  += gxfb.o
-obj-$(CONFIG_FB_GEODE_LX)  += lxfb.o
-
-gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
-gxfb-objs  := gxfb_core.o display_gx.o video_gx.o suspend_gx.o
-lxfb-objs  := lxfb_core.o lxfb_ops.o
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
deleted file mode 100644
index f0af911a096d..000000000000
--- a/drivers/video/geode/display_gx.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Geode GX display controller.
- *
- *   Copyright (C) 2005 Arcom Control Systems Ltd.
- *
- *   Portions from AMD's original 2.4 driver:
- *     Copyright (C) 2004 Advanced Micro Devices, Inc.
- *
- *   This program is free software; you can redistribute it and/or modify it
- *   under the terms of the GNU General Public License as published by * the
- *   Free Software Foundation; either version 2 of the License, or * (at your
- *   option) any later version.
- */
-#include <linux/spinlock.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/div64.h>
-#include <asm/delay.h>
-#include <linux/cs5535.h>
-
-#include "gxfb.h"
-
-unsigned int gx_frame_buffer_size(void)
-{
-	unsigned int val;
-
-	if (!cs5535_has_vsa2()) {
-		uint32_t hi, lo;
-
-		/* The number of pages is (PMAX - PMIN)+1 */
-		rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
-
-		/* PMAX */
-		val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
-		/* PMIN */
-		val -= (lo & 0x000fffff);
-		val += 1;
-
-		/* The page size is 4k */
-		return (val << 12);
-	}
-
-	/* FB size can be obtained from the VSA II */
-	/* Virtual register class = 0x02 */
-	/* VG_MEM_SIZE(512Kb units) = 0x00 */
-
-	outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
-	outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
-
-	val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFFl;
-	return (val << 19);
-}
-
-int gx_line_delta(int xres, int bpp)
-{
-	/* Must be a multiple of 8 bytes. */
-	return (xres * (bpp >> 3) + 7) & ~0x7;
-}
-
-void gx_set_mode(struct fb_info *info)
-{
-	struct gxfb_par *par = info->par;
-	u32 gcfg, dcfg;
-	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
-	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
-
-	/* Unlock the display controller registers. */
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-
-	gcfg = read_dc(par, DC_GENERAL_CFG);
-	dcfg = read_dc(par, DC_DISPLAY_CFG);
-
-	/* Disable the timing generator. */
-	dcfg &= ~DC_DISPLAY_CFG_TGEN;
-	write_dc(par, DC_DISPLAY_CFG, dcfg);
-
-	/* Wait for pending memory requests before disabling the FIFO load. */
-	udelay(100);
-
-	/* Disable FIFO load and compression. */
-	gcfg &= ~(DC_GENERAL_CFG_DFLE | DC_GENERAL_CFG_CMPE |
-			DC_GENERAL_CFG_DECE);
-	write_dc(par, DC_GENERAL_CFG, gcfg);
-
-	/* Setup DCLK and its divisor. */
-	gx_set_dclk_frequency(info);
-
-	/*
-	 * Setup new mode.
-	 */
-
-	/* Clear all unused feature bits. */
-	gcfg &= DC_GENERAL_CFG_YUVM | DC_GENERAL_CFG_VDSE;
-	dcfg = 0;
-
-	/* Set FIFO priority (default 6/5) and enable. */
-	/* FIXME: increase fifo priority for 1280x1024 and higher modes? */
-	gcfg |= (6 << DC_GENERAL_CFG_DFHPEL_SHIFT) |
-		(5 << DC_GENERAL_CFG_DFHPSL_SHIFT) | DC_GENERAL_CFG_DFLE;
-
-	/* Framebuffer start offset. */
-	write_dc(par, DC_FB_ST_OFFSET, 0);
-
-	/* Line delta and line buffer length. */
-	write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
-	write_dc(par, DC_LINE_SIZE,
-		((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2);
-
-
-	/* Enable graphics and video data and unmask address lines. */
-	dcfg |= DC_DISPLAY_CFG_GDEN | DC_DISPLAY_CFG_VDEN |
-		DC_DISPLAY_CFG_A20M | DC_DISPLAY_CFG_A18M;
-
-	/* Set pixel format. */
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
-		break;
-	case 16:
-		dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
-		break;
-	case 32:
-		dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
-		dcfg |= DC_DISPLAY_CFG_PALB;
-		break;
-	}
-
-	/* Enable timing generator. */
-	dcfg |= DC_DISPLAY_CFG_TGEN;
-
-	/* Horizontal and vertical timings. */
-	hactive = info->var.xres;
-	hblankstart = hactive;
-	hsyncstart = hblankstart + info->var.right_margin;
-	hsyncend =  hsyncstart + info->var.hsync_len;
-	hblankend = hsyncend + info->var.left_margin;
-	htotal = hblankend;
-
-	vactive = info->var.yres;
-	vblankstart = vactive;
-	vsyncstart = vblankstart + info->var.lower_margin;
-	vsyncend =  vsyncstart + info->var.vsync_len;
-	vblankend = vsyncend + info->var.upper_margin;
-	vtotal = vblankend;
-
-	write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1)    |
-			((htotal - 1) << 16));
-	write_dc(par, DC_H_BLANK_TIMING, (hblankstart - 1) |
-			((hblankend - 1) << 16));
-	write_dc(par, DC_H_SYNC_TIMING, (hsyncstart - 1)   |
-			((hsyncend - 1) << 16));
-
-	write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1)    |
-			((vtotal - 1) << 16));
-	write_dc(par, DC_V_BLANK_TIMING, (vblankstart - 1) |
-			((vblankend - 1) << 16));
-	write_dc(par, DC_V_SYNC_TIMING, (vsyncstart - 1)   |
-			((vsyncend - 1) << 16));
-
-	/* Write final register values. */
-	write_dc(par, DC_DISPLAY_CFG, dcfg);
-	write_dc(par, DC_GENERAL_CFG, gcfg);
-
-	gx_configure_display(info);
-
-	/* Relock display controller registers */
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
-}
-
-void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
-		unsigned red, unsigned green, unsigned blue)
-{
-	struct gxfb_par *par = info->par;
-	int val;
-
-	/* Hardware palette is in RGB 8-8-8 format. */
-	val  = (red   << 8) & 0xff0000;
-	val |= (green)      & 0x00ff00;
-	val |= (blue  >> 8) & 0x0000ff;
-
-	write_dc(par, DC_PAL_ADDRESS, regno);
-	write_dc(par, DC_PAL_DATA, val);
-}
diff --git a/drivers/video/geode/display_gx1.c b/drivers/video/geode/display_gx1.c
deleted file mode 100644
index 926d53eeb549..000000000000
--- a/drivers/video/geode/display_gx1.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * drivers/video/geode/display_gx1.c
- *   -- Geode GX1 display controller
- *
- * Copyright (C) 2005 Arcom Control Systems Ltd.
- *
- * Based on AMD's original 2.4 driver:
- *   Copyright (C) 2004 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/spinlock.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/div64.h>
-#include <asm/delay.h>
-
-#include "geodefb.h"
-#include "display_gx1.h"
-
-static DEFINE_SPINLOCK(gx1_conf_reg_lock);
-
-static u8 gx1_read_conf_reg(u8 reg)
-{
-	u8 val, ccr3;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gx1_conf_reg_lock, flags);
-
-	outb(CONFIG_CCR3, 0x22);
-	ccr3 = inb(0x23);
-	outb(CONFIG_CCR3, 0x22);
-	outb(ccr3 | CONFIG_CCR3_MAPEN, 0x23);
-	outb(reg, 0x22);
-	val = inb(0x23);
-	outb(CONFIG_CCR3, 0x22);
-	outb(ccr3, 0x23);
-
-	spin_unlock_irqrestore(&gx1_conf_reg_lock, flags);
-
-	return val;
-}
-
-unsigned gx1_gx_base(void)
-{
-	return (gx1_read_conf_reg(CONFIG_GCR) & 0x03) << 30;
-}
-
-int gx1_frame_buffer_size(void)
-{
-	void __iomem *mc_regs;
-	u32 bank_cfg;
-	int d;
-	unsigned dram_size = 0, fb_base;
-
-	mc_regs = ioremap(gx1_gx_base() + 0x8400, 0x100);
-	if (!mc_regs)
-		return -ENOMEM;
-
-
-	/* Calculate the total size of both DIMM0 and DIMM1. */
-	bank_cfg = readl(mc_regs + MC_BANK_CFG);
-
-	for (d = 0; d < 2; d++) {
-		if ((bank_cfg & MC_BCFG_DIMM0_PG_SZ_MASK) != MC_BCFG_DIMM0_PG_SZ_NO_DIMM)
-			dram_size += 0x400000 << ((bank_cfg & MC_BCFG_DIMM0_SZ_MASK) >> 8);
-		bank_cfg >>= 16; /* look at DIMM1 next */
-	}
-
-	fb_base = (readl(mc_regs + MC_GBASE_ADD) & MC_GADD_GBADD_MASK) << 19;
-
-	iounmap(mc_regs);
-
-	return dram_size - fb_base;
-}
-
-static void gx1_set_mode(struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-	u32 gcfg, tcfg, ocfg, dclk_div, val;
-	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
-	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
-
-	/* Unlock the display controller registers. */
-	readl(par->dc_regs + DC_UNLOCK);
-	writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
-
-	gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
-	tcfg = readl(par->dc_regs + DC_TIMING_CFG);
-
-	/* Blank the display and disable the timing generator. */
-	tcfg &= ~(DC_TCFG_BLKE | DC_TCFG_TGEN);
-	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
-
-	/* Wait for pending memory requests before disabling the FIFO load. */
-	udelay(100);
-
-	/* Disable FIFO load and compression. */
-	gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
-
-	/* Setup DCLK and its divisor. */
-	gcfg &= ~DC_GCFG_DCLK_MASK;
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
-
-	par->vid_ops->set_dclk(info);
-
-	dclk_div = DC_GCFG_DCLK_DIV_1; /* FIXME: may need to divide DCLK by 2 sometimes? */
-	gcfg |= dclk_div;
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
-
-	/* Wait for the clock generatation to settle.  This is needed since
-	 * some of the register writes that follow require that clock to be
-	 * present. */
-	udelay(1000); /* FIXME: seems a little long */
-
-	/*
-	 * Setup new mode.
-	 */
-
-	/* Clear all unused feature bits. */
-	gcfg = DC_GCFG_VRDY | dclk_div;
-
-	/* Set FIFO priority (default 6/5) and enable. */
-	/* FIXME: increase fifo priority for 1280x1024 modes? */
-	gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
-
-	/* FIXME: Set pixel and line double bits if necessary. */
-
-	/* Framebuffer start offset. */
-	writel(0, par->dc_regs + DC_FB_ST_OFFSET);
-
-	/* Line delta and line buffer length. */
-	writel(info->fix.line_length >> 2, par->dc_regs + DC_LINE_DELTA);
-	writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
-	       par->dc_regs + DC_BUF_SIZE);
-
-	/* Output configuration. Enable panel data, set pixel format. */
-	ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;
-	if (info->var.bits_per_pixel == 8) ocfg |= DC_OCFG_8BPP;
-
-	/* Enable timing generator, sync and FP data. */
-	tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE
-		| DC_TCFG_TGEN;
-
-	/* Horizontal and vertical timings. */
-	hactive = info->var.xres;
-	hblankstart = hactive;
-	hsyncstart = hblankstart + info->var.right_margin;
-	hsyncend =  hsyncstart + info->var.hsync_len;
-	hblankend = hsyncend + info->var.left_margin;
-	htotal = hblankend;
-
-	vactive = info->var.yres;
-	vblankstart = vactive;
-	vsyncstart = vblankstart + info->var.lower_margin;
-	vsyncend =  vsyncstart + info->var.vsync_len;
-	vblankend = vsyncend + info->var.upper_margin;
-	vtotal = vblankend;
-
-	val = (hactive - 1) | ((htotal - 1) << 16);
-	writel(val, par->dc_regs + DC_H_TIMING_1);
-	val = (hblankstart - 1) | ((hblankend - 1) << 16);
-	writel(val, par->dc_regs + DC_H_TIMING_2);
-	val = (hsyncstart - 1) | ((hsyncend - 1) << 16);
-	writel(val, par->dc_regs + DC_H_TIMING_3);
-	writel(val, par->dc_regs + DC_FP_H_TIMING);
-	val = (vactive - 1) | ((vtotal - 1) << 16);
-	writel(val, par->dc_regs + DC_V_TIMING_1);
-	val = (vblankstart - 1) | ((vblankend - 1) << 16);
-	writel(val, par->dc_regs + DC_V_TIMING_2);
-	val = (vsyncstart - 1) | ((vsyncend - 1) << 16);
-	writel(val, par->dc_regs + DC_V_TIMING_3);
-	val = (vsyncstart - 2) | ((vsyncend - 2) << 16);
-	writel(val, par->dc_regs + DC_FP_V_TIMING);
-
-	/* Write final register values. */
-	writel(ocfg, par->dc_regs + DC_OUTPUT_CFG);
-	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
-	udelay(1000); /* delay after TIMING_CFG. FIXME: perhaps a little long */
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
-
-	par->vid_ops->configure_display(info);
-
-	/* Relock display controller registers */
-	writel(0, par->dc_regs + DC_UNLOCK);
-
-	/* FIXME: write line_length and bpp to Graphics Pipeline GP_BLT_STATUS
-	 * register. */
-}
-
-static void gx1_set_hw_palette_reg(struct fb_info *info, unsigned regno,
-				   unsigned red, unsigned green, unsigned blue)
-{
-	struct geodefb_par *par = info->par;
-	int val;
-
-	/* Hardware palette is in RGB 6-6-6 format. */
-	val  = (red   <<  2) & 0x3f000;
-	val |= (green >>  4) & 0x00fc0;
-	val |= (blue  >> 10) & 0x0003f;
-
-	writel(regno, par->dc_regs + DC_PAL_ADDRESS);
-	writel(val, par->dc_regs + DC_PAL_DATA);
-}
-
-struct geode_dc_ops gx1_dc_ops = {
-	.set_mode	 = gx1_set_mode,
-	.set_palette_reg = gx1_set_hw_palette_reg,
-};
diff --git a/drivers/video/geode/display_gx1.h b/drivers/video/geode/display_gx1.h
deleted file mode 100644
index 671c05558c79..000000000000
--- a/drivers/video/geode/display_gx1.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * drivers/video/geode/display_gx1.h
- *   -- Geode GX1 display controller
- *
- * Copyright (C) 2005 Arcom Control Systems Ltd.
- *
- * Based on AMD's original 2.4 driver:
- *   Copyright (C) 2004 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __DISPLAY_GX1_H__
-#define __DISPLAY_GX1_H__
-
-unsigned gx1_gx_base(void);
-int gx1_frame_buffer_size(void);
-
-extern struct geode_dc_ops gx1_dc_ops;
-
-/* GX1 configuration I/O registers */
-
-#define CONFIG_CCR3 0xc3
-#  define CONFIG_CCR3_MAPEN 0x10
-#define CONFIG_GCR  0xb8
-
-/* Memory controller registers */
-
-#define MC_BANK_CFG		0x08
-#  define MC_BCFG_DIMM0_SZ_MASK		0x00000700
-#  define MC_BCFG_DIMM0_PG_SZ_MASK	0x00000070
-#  define MC_BCFG_DIMM0_PG_SZ_NO_DIMM	0x00000070
-
-#define MC_GBASE_ADD		0x14
-#  define MC_GADD_GBADD_MASK		0x000003ff
-
-/* Display controller registers */
-
-#define DC_PAL_ADDRESS		0x70
-#define DC_PAL_DATA		0x74
-
-#define DC_UNLOCK		0x00
-#  define DC_UNLOCK_CODE		0x00004758
-
-#define DC_GENERAL_CFG		0x04
-#  define DC_GCFG_DFLE			0x00000001
-#  define DC_GCFG_CURE			0x00000002
-#  define DC_GCFG_VCLK_DIV		0x00000004
-#  define DC_GCFG_PLNO			0x00000004
-#  define DC_GCFG_PPC			0x00000008
-#  define DC_GCFG_CMPE			0x00000010
-#  define DC_GCFG_DECE			0x00000020
-#  define DC_GCFG_DCLK_MASK		0x000000C0
-#  define DC_GCFG_DCLK_DIV_1		0x00000080
-#  define DC_GCFG_DFHPSL_MASK		0x00000F00
-#  define DC_GCFG_DFHPSL_POS			 8
-#  define DC_GCFG_DFHPEL_MASK		0x0000F000
-#  define DC_GCFG_DFHPEL_POS			12
-#  define DC_GCFG_CIM_MASK		0x00030000
-#  define DC_GCFG_CIM_POS			16
-#  define DC_GCFG_FDTY			0x00040000
-#  define DC_GCFG_RTPM			0x00080000
-#  define DC_GCFG_DAC_RS_MASK		0x00700000
-#  define DC_GCFG_DAC_RS_POS			20
-#  define DC_GCFG_CKWR			0x00800000
-#  define DC_GCFG_LDBL			0x01000000
-#  define DC_GCFG_DIAG			0x02000000
-#  define DC_GCFG_CH4S			0x04000000
-#  define DC_GCFG_SSLC			0x08000000
-#  define DC_GCFG_VIDE			0x10000000
-#  define DC_GCFG_VRDY			0x20000000
-#  define DC_GCFG_DPCK			0x40000000
-#  define DC_GCFG_DDCK			0x80000000
-
-#define DC_TIMING_CFG		0x08
-#  define DC_TCFG_FPPE			0x00000001
-#  define DC_TCFG_HSYE			0x00000002
-#  define DC_TCFG_VSYE			0x00000004
-#  define DC_TCFG_BLKE			0x00000008
-#  define DC_TCFG_DDCK			0x00000010
-#  define DC_TCFG_TGEN			0x00000020
-#  define DC_TCFG_VIEN			0x00000040
-#  define DC_TCFG_BLNK			0x00000080
-#  define DC_TCFG_CHSP			0x00000100
-#  define DC_TCFG_CVSP			0x00000200
-#  define DC_TCFG_FHSP			0x00000400
-#  define DC_TCFG_FVSP			0x00000800
-#  define DC_TCFG_FCEN			0x00001000
-#  define DC_TCFG_CDCE			0x00002000
-#  define DC_TCFG_PLNR			0x00002000
-#  define DC_TCFG_INTL			0x00004000
-#  define DC_TCFG_PXDB			0x00008000
-#  define DC_TCFG_BKRT			0x00010000
-#  define DC_TCFG_PSD_MASK		0x000E0000
-#  define DC_TCFG_PSD_POS			17
-#  define DC_TCFG_DDCI			0x08000000
-#  define DC_TCFG_SENS			0x10000000
-#  define DC_TCFG_DNA			0x20000000
-#  define DC_TCFG_VNA			0x40000000
-#  define DC_TCFG_VINT			0x80000000
-
-#define DC_OUTPUT_CFG		0x0C
-#  define DC_OCFG_8BPP			0x00000001
-#  define DC_OCFG_555			0x00000002
-#  define DC_OCFG_PCKE			0x00000004
-#  define DC_OCFG_FRME			0x00000008
-#  define DC_OCFG_DITE			0x00000010
-#  define DC_OCFG_2PXE			0x00000020
-#  define DC_OCFG_2XCK			0x00000040
-#  define DC_OCFG_2IND			0x00000080
-#  define DC_OCFG_34ADD			0x00000100
-#  define DC_OCFG_FRMS			0x00000200
-#  define DC_OCFG_CKSL			0x00000400
-#  define DC_OCFG_PRMP			0x00000800
-#  define DC_OCFG_PDEL			0x00001000
-#  define DC_OCFG_PDEH			0x00002000
-#  define DC_OCFG_CFRW			0x00004000
-#  define DC_OCFG_DIAG			0x00008000
-
-#define DC_FB_ST_OFFSET		0x10
-#define DC_CB_ST_OFFSET		0x14
-#define DC_CURS_ST_OFFSET	0x18
-#define DC_ICON_ST_OFFSET	0x1C
-#define DC_VID_ST_OFFSET	0x20
-#define DC_LINE_DELTA		0x24
-#define DC_BUF_SIZE		0x28
-
-#define DC_H_TIMING_1		0x30
-#define DC_H_TIMING_2		0x34
-#define DC_H_TIMING_3		0x38
-#define DC_FP_H_TIMING		0x3C
-
-#define DC_V_TIMING_1		0x40
-#define DC_V_TIMING_2		0x44
-#define DC_V_TIMING_3		0x48
-#define DC_FP_V_TIMING		0x4C
-
-#define DC_CURSOR_X		0x50
-#define DC_ICON_X		0x54
-#define DC_V_LINE_CNT		0x54
-#define DC_CURSOR_Y		0x58
-#define DC_ICON_Y		0x5C
-#define DC_SS_LINE_CMP		0x5C
-#define DC_CURSOR_COLOR		0x60
-#define DC_ICON_COLOR		0x64
-#define DC_BORDER_COLOR		0x68
-#define DC_PAL_ADDRESS		0x70
-#define DC_PAL_DATA		0x74
-#define DC_DFIFO_DIAG		0x78
-#define DC_CFIFO_DIAG		0x7C
-
-#endif /* !__DISPLAY_GX1_H__ */
diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
deleted file mode 100644
index ae04820e0c57..000000000000
--- a/drivers/video/geode/geodefb.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * drivers/video/geode/geodefb.h
- *   -- Geode framebuffer driver
- *
- * Copyright (C) 2005 Arcom Control Systems Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __GEODEFB_H__
-#define __GEODEFB_H__
-
-struct geodefb_info;
-
-struct geode_dc_ops {
-	void (*set_mode)(struct fb_info *);
-	void (*set_palette_reg)(struct fb_info *, unsigned, unsigned, unsigned, unsigned);
-};
-
-struct geode_vid_ops {
-	void (*set_dclk)(struct fb_info *);
-	void (*configure_display)(struct fb_info *);
-	int  (*blank_display)(struct fb_info *, int blank_mode);
-};
-
-struct geodefb_par {
-	int enable_crt;
-	int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
-	int panel_y;
-	void __iomem *dc_regs;
-	void __iomem *vid_regs;
-	struct geode_dc_ops  *dc_ops;
-	struct geode_vid_ops *vid_ops;
-};
-
-#endif /* !__GEODEFB_H__ */
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
deleted file mode 100644
index 2794ba11f332..000000000000
--- a/drivers/video/geode/gx1fb_core.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * drivers/video/geode/gx1fb_core.c
- *   -- Geode GX1 framebuffer driver
- *
- * Copyright (C) 2005 Arcom Control Systems Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#include "geodefb.h"
-#include "display_gx1.h"
-#include "video_cs5530.h"
-
-static char mode_option[32] = "640x480-16@60";
-static int  crt_option = 1;
-static char panel_option[32] = "";
-
-/* Modes relevant to the GX1 (taken from modedb.c) */
-static const struct fb_videomode gx1_modedb[] = {
-	/* 640x480-60 VESA */
-	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 640x480-75 VESA */
-	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 640x480-85 VESA */
-	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 800x600-60 VESA */
-	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 800x600-75 VESA */
-	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 800x600-85 VESA */
-	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1024x768-60 VESA */
-	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1024x768-75 VESA */
-	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1024x768-85 VESA */
-	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x960-60 VESA */
-	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x960-85 VESA */
-	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x1024-60 VESA */
-	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x1024-75 VESA */
-	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x1024-85 VESA */
-	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-};
-
-static int gx1_line_delta(int xres, int bpp)
-{
-	int line_delta = xres * (bpp >> 3);
-
-	if (line_delta > 2048)
-		line_delta = 4096;
-	else if (line_delta > 1024)
-		line_delta = 2048;
-	else
-		line_delta = 1024;
-	return line_delta;
-}
-
-static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-
-	/* Maximum resolution is 1280x1024. */
-	if (var->xres > 1280 || var->yres > 1024)
-		return -EINVAL;
-
-	if (par->panel_x && (var->xres > par->panel_x || var->yres > par->panel_y))
-		return -EINVAL;
-
-	/* Only 16 bpp and 8 bpp is supported by the hardware. */
-	if (var->bits_per_pixel == 16) {
-		var->red.offset   = 11; var->red.length   = 5;
-		var->green.offset =  5; var->green.length = 6;
-		var->blue.offset  =  0; var->blue.length  = 5;
-		var->transp.offset = 0; var->transp.length = 0;
-	} else if (var->bits_per_pixel == 8) {
-		var->red.offset   = 0; var->red.length   = 8;
-		var->green.offset = 0; var->green.length = 8;
-		var->blue.offset  = 0; var->blue.length  = 8;
-		var->transp.offset = 0; var->transp.length = 0;
-	} else
-		return -EINVAL;
-
-	/* Enough video memory? */
-	if (gx1_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
-		return -EINVAL;
-
-	/* FIXME: Check timing parameters here? */
-
-	return 0;
-}
-
-static int gx1fb_set_par(struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-
-	if (info->var.bits_per_pixel == 16)
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	else
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = gx1_line_delta(info->var.xres, info->var.bits_per_pixel);
-
-	par->dc_ops->set_mode(info);
-
-	return 0;
-}
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int gx1fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 *pal = info->pseudo_palette;
-		u32 v;
-
-		if (regno >= 16)
-			return -EINVAL;
-
-		v  = chan_to_field(red, &info->var.red);
-		v |= chan_to_field(green, &info->var.green);
-		v |= chan_to_field(blue, &info->var.blue);
-
-		pal[regno] = v;
-	} else {
-		if (regno >= 256)
-			return -EINVAL;
-
-		par->dc_ops->set_palette_reg(info, regno, red, green, blue);
-	}
-
-	return 0;
-}
-
-static int gx1fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-
-	return par->vid_ops->blank_display(info, blank_mode);
-}
-
-static int gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
-{
-	struct geodefb_par *par = info->par;
-	unsigned gx_base;
-	int fb_len;
-	int ret;
-
-	gx_base = gx1_gx_base();
-	if (!gx_base)
-		return -ENODEV;
-
-	ret = pci_enable_device(dev);
-	if (ret < 0)
-		return ret;
-
-	ret = pci_request_region(dev, 0, "gx1fb (video)");
-	if (ret < 0)
-		return ret;
-	par->vid_regs = pci_ioremap_bar(dev, 0);
-	if (!par->vid_regs)
-		return -ENOMEM;
-
-	if (!request_mem_region(gx_base + 0x8300, 0x100, "gx1fb (display controller)"))
-		return -EBUSY;
-	par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
-	if (!par->dc_regs)
-		return -ENOMEM;
-
-	if ((fb_len = gx1_frame_buffer_size()) < 0)
-		return -ENOMEM;
-	info->fix.smem_start = gx_base + 0x800000;
-	info->fix.smem_len = fb_len;
-	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-	if (!info->screen_base)
-		return -ENOMEM;
-
-	dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
-		 info->fix.smem_len / 1024, info->fix.smem_start);
-
-	return 0;
-}
-
-static int parse_panel_option(struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-
-	if (strcmp(panel_option, "") != 0) {
-		int x, y;
-		char *s;
-		x = simple_strtol(panel_option, &s, 10);
-		if (!x)
-			return -EINVAL;
-		y = simple_strtol(s + 1, NULL, 10);
-		if (!y)
-			return -EINVAL;
-		par->panel_x = x;
-		par->panel_y = y;
-	}
-	return 0;
-}
-
-static struct fb_ops gx1fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= gx1fb_check_var,
-	.fb_set_par	= gx1fb_set_par,
-	.fb_setcolreg	= gx1fb_setcolreg,
-	.fb_blank       = gx1fb_blank,
-	/* No HW acceleration for now. */
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static struct fb_info *gx1fb_init_fbinfo(struct device *dev)
-{
-	struct geodefb_par *par;
-	struct fb_info *info;
-
-	/* Alloc enough space for the pseudo palette. */
-	info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
-	if (!info)
-		return NULL;
-
-	par = info->par;
-
-	strcpy(info->fix.id, "GX1");
-
-	info->fix.type		= FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux	= 0;
-	info->fix.xpanstep	= 0;
-	info->fix.ypanstep	= 0;
-	info->fix.ywrapstep	= 0;
-	info->fix.accel		= FB_ACCEL_NONE;
-
-	info->var.nonstd	= 0;
-	info->var.activate	= FB_ACTIVATE_NOW;
-	info->var.height	= -1;
-	info->var.width	= -1;
-	info->var.accel_flags = 0;
-	info->var.vmode	= FB_VMODE_NONINTERLACED;
-
-	info->fbops		= &gx1fb_ops;
-	info->flags		= FBINFO_DEFAULT;
-	info->node		= -1;
-
-	info->pseudo_palette	= (void *)par + sizeof(struct geodefb_par);
-
-	info->var.grayscale	= 0;
-
-	/* CRT and panel options */
-	par->enable_crt = crt_option;
-	if (parse_panel_option(info) < 0)
-		printk(KERN_WARNING "gx1fb: invalid 'panel' option -- disabling flat panel\n");
-	if (!par->panel_x)
-		par->enable_crt = 1; /* fall back to CRT if no panel is specified */
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		framebuffer_release(info);
-		return NULL;
-	}
-	return info;
-}
-
-static int gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct geodefb_par *par;
-	struct fb_info *info;
-	int ret;
-
-	info = gx1fb_init_fbinfo(&pdev->dev);
-	if (!info)
-		return -ENOMEM;
-	par = info->par;
-
-	/* GX1 display controller and CS5530 video device */
-	par->dc_ops  = &gx1_dc_ops;
-	par->vid_ops = &cs5530_vid_ops;
-
-	if ((ret = gx1fb_map_video_memory(info, pdev)) < 0) {
-		dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
-		goto err;
-	}
-
-	ret = fb_find_mode(&info->var, info, mode_option,
-			   gx1_modedb, ARRAY_SIZE(gx1_modedb), NULL, 16);
-	if (ret == 0 || ret == 4) {
-		dev_err(&pdev->dev, "could not find valid video mode\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-        /* Clear the frame buffer of garbage. */
-        memset_io(info->screen_base, 0, info->fix.smem_len);
-
-	gx1fb_check_var(&info->var, info);
-	gx1fb_set_par(info);
-
-	if (register_framebuffer(info) < 0) {
-		ret = -EINVAL;
-		goto err;
-	}
-	pci_set_drvdata(pdev, info);
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	return 0;
-
-  err:
-	if (info->screen_base) {
-		iounmap(info->screen_base);
-		pci_release_region(pdev, 0);
-	}
-	if (par->vid_regs) {
-		iounmap(par->vid_regs);
-		pci_release_region(pdev, 1);
-	}
-	if (par->dc_regs) {
-		iounmap(par->dc_regs);
-		release_mem_region(gx1_gx_base() + 0x8300, 0x100);
-	}
-
-	if (info) {
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-
-	return ret;
-}
-
-static void gx1fb_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct geodefb_par *par = info->par;
-
-	unregister_framebuffer(info);
-
-	iounmap((void __iomem *)info->screen_base);
-	pci_release_region(pdev, 0);
-
-	iounmap(par->vid_regs);
-	pci_release_region(pdev, 1);
-
-	iounmap(par->dc_regs);
-	release_mem_region(gx1_gx_base() + 0x8300, 0x100);
-
-	fb_dealloc_cmap(&info->cmap);
-
-	framebuffer_release(info);
-}
-
-#ifndef MODULE
-static void __init gx1fb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return;
-
-	while ((this_opt = strsep(&options, ","))) {
-		if (!*this_opt)
-			continue;
-
-		if (!strncmp(this_opt, "mode:", 5))
-			strlcpy(mode_option, this_opt + 5, sizeof(mode_option));
-		else if (!strncmp(this_opt, "crt:", 4))
-			crt_option = !!simple_strtoul(this_opt + 4, NULL, 0);
-		else if (!strncmp(this_opt, "panel:", 6))
-			strlcpy(panel_option, this_opt + 6, sizeof(panel_option));
-		else
-			strlcpy(mode_option, this_opt, sizeof(mode_option));
-	}
-}
-#endif
-
-static struct pci_device_id gx1fb_id_table[] = {
-	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
-	  0xff0000, 0 },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, gx1fb_id_table);
-
-static struct pci_driver gx1fb_driver = {
-	.name		= "gx1fb",
-	.id_table	= gx1fb_id_table,
-	.probe		= gx1fb_probe,
-	.remove		= gx1fb_remove,
-};
-
-static int __init gx1fb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("gx1fb", &option))
-		return -ENODEV;
-	gx1fb_setup(option);
-#endif
-	return pci_register_driver(&gx1fb_driver);
-}
-
-static void gx1fb_cleanup(void)
-{
-	pci_unregister_driver(&gx1fb_driver);
-}
-
-module_init(gx1fb_init);
-module_exit(gx1fb_cleanup);
-
-module_param_string(mode, mode_option, sizeof(mode_option), 0444);
-MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
-
-module_param_named(crt, crt_option, int, 0444);
-MODULE_PARM_DESC(crt, "enable CRT output. 0 = off, 1 = on (default)");
-
-module_param_string(panel, panel_option, sizeof(panel_option), 0444);
-MODULE_PARM_DESC(panel, "size of attached flat panel (<x>x<y>)");
-
-MODULE_DESCRIPTION("framebuffer driver for the AMD Geode GX1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/gxfb.h b/drivers/video/geode/gxfb.h
deleted file mode 100644
index d19e9378b0c0..000000000000
--- a/drivers/video/geode/gxfb.h
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2008 Andres Salomon <dilinger@debian.org>
- *
- * Geode GX2 header information
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef _GXFB_H_
-#define _GXFB_H_
-
-#include <linux/io.h>
-
-#define GP_REG_COUNT   (0x50 / 4)
-#define DC_REG_COUNT   (0x90 / 4)
-#define VP_REG_COUNT   (0x138 / 8)
-#define FP_REG_COUNT   (0x68 / 8)
-
-#define DC_PAL_COUNT   0x104
-
-struct gxfb_par {
-	int enable_crt;
-	void __iomem *dc_regs;
-	void __iomem *vid_regs;
-	void __iomem *gp_regs;
-#ifdef CONFIG_PM
-	int powered_down;
-
-	/* register state, for power management functionality */
-	struct {
-		uint64_t padsel;
-		uint64_t dotpll;
-	} msr;
-
-	uint32_t gp[GP_REG_COUNT];
-	uint32_t dc[DC_REG_COUNT];
-	uint64_t vp[VP_REG_COUNT];
-	uint64_t fp[FP_REG_COUNT];
-
-	uint32_t pal[DC_PAL_COUNT];
-#endif
-};
-
-unsigned int gx_frame_buffer_size(void);
-int gx_line_delta(int xres, int bpp);
-void gx_set_mode(struct fb_info *info);
-void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
-		unsigned red, unsigned green, unsigned blue);
-
-void gx_set_dclk_frequency(struct fb_info *info);
-void gx_configure_display(struct fb_info *info);
-int gx_blank_display(struct fb_info *info, int blank_mode);
-
-#ifdef CONFIG_PM
-int gx_powerdown(struct fb_info *info);
-int gx_powerup(struct fb_info *info);
-#endif
-
-
-/* Graphics Processor registers (table 6-23 from the data book) */
-enum gp_registers {
-	GP_DST_OFFSET = 0,
-	GP_SRC_OFFSET,
-	GP_STRIDE,
-	GP_WID_HEIGHT,
-
-	GP_SRC_COLOR_FG,
-	GP_SRC_COLOR_BG,
-	GP_PAT_COLOR_0,
-	GP_PAT_COLOR_1,
-
-	GP_PAT_COLOR_2,
-	GP_PAT_COLOR_3,
-	GP_PAT_COLOR_4,
-	GP_PAT_COLOR_5,
-
-	GP_PAT_DATA_0,
-	GP_PAT_DATA_1,
-	GP_RASTER_MODE,
-	GP_VECTOR_MODE,
-
-	GP_BLT_MODE,
-	GP_BLT_STATUS,
-	GP_HST_SRC,
-	GP_BASE_OFFSET, /* 0x4c */
-};
-
-#define GP_BLT_STATUS_BLT_PENDING	(1 << 2)
-#define GP_BLT_STATUS_BLT_BUSY		(1 << 0)
-
-
-/* Display Controller registers (table 6-38 from the data book) */
-enum dc_registers {
-	DC_UNLOCK = 0,
-	DC_GENERAL_CFG,
-	DC_DISPLAY_CFG,
-	DC_RSVD_0,
-
-	DC_FB_ST_OFFSET,
-	DC_CB_ST_OFFSET,
-	DC_CURS_ST_OFFSET,
-	DC_ICON_ST_OFFSET,
-
-	DC_VID_Y_ST_OFFSET,
-	DC_VID_U_ST_OFFSET,
-	DC_VID_V_ST_OFFSET,
-	DC_RSVD_1,
-
-	DC_LINE_SIZE,
-	DC_GFX_PITCH,
-	DC_VID_YUV_PITCH,
-	DC_RSVD_2,
-
-	DC_H_ACTIVE_TIMING,
-	DC_H_BLANK_TIMING,
-	DC_H_SYNC_TIMING,
-	DC_RSVD_3,
-
-	DC_V_ACTIVE_TIMING,
-	DC_V_BLANK_TIMING,
-	DC_V_SYNC_TIMING,
-	DC_RSVD_4,
-
-	DC_CURSOR_X,
-	DC_CURSOR_Y,
-	DC_ICON_X,
-	DC_LINE_CNT,
-
-	DC_PAL_ADDRESS,
-	DC_PAL_DATA,
-	DC_DFIFO_DIAG,
-	DC_CFIFO_DIAG,
-
-	DC_VID_DS_DELTA,
-	DC_GLIU0_MEM_OFFSET,
-	DC_RSVD_5,
-	DC_DV_ACC, /* 0x8c */
-};
-
-#define DC_UNLOCK_LOCK			0x00000000
-#define DC_UNLOCK_UNLOCK		0x00004758	/* magic value */
-
-#define DC_GENERAL_CFG_YUVM		(1 << 20)
-#define DC_GENERAL_CFG_VDSE		(1 << 19)
-#define DC_GENERAL_CFG_DFHPEL_SHIFT	12
-#define DC_GENERAL_CFG_DFHPSL_SHIFT	8
-#define DC_GENERAL_CFG_DECE		(1 << 6)
-#define DC_GENERAL_CFG_CMPE		(1 << 5)
-#define DC_GENERAL_CFG_VIDE		(1 << 3)
-#define DC_GENERAL_CFG_ICNE		(1 << 2)
-#define DC_GENERAL_CFG_CURE		(1 << 1)
-#define DC_GENERAL_CFG_DFLE		(1 << 0)
-
-#define DC_DISPLAY_CFG_A20M		(1 << 31)
-#define DC_DISPLAY_CFG_A18M		(1 << 30)
-#define DC_DISPLAY_CFG_PALB		(1 << 25)
-#define DC_DISPLAY_CFG_DISP_MODE_24BPP	(1 << 9)
-#define DC_DISPLAY_CFG_DISP_MODE_16BPP	(1 << 8)
-#define DC_DISPLAY_CFG_DISP_MODE_8BPP	(0)
-#define DC_DISPLAY_CFG_VDEN		(1 << 4)
-#define DC_DISPLAY_CFG_GDEN		(1 << 3)
-#define DC_DISPLAY_CFG_TGEN		(1 << 0)
-
-
-/*
- * Video Processor registers (table 6-54).
- * There is space for 64 bit values, but we never use more than the
- * lower 32 bits.  The actual register save/restore code only bothers
- * to restore those 32 bits.
- */
-enum vp_registers {
-	VP_VCFG = 0,
-	VP_DCFG,
-
-	VP_VX,
-	VP_VY,
-
-	VP_VS,
-	VP_VCK,
-
-	VP_VCM,
-	VP_GAR,
-
-	VP_GDR,
-	VP_RSVD_0,
-
-	VP_MISC,
-	VP_CCS,
-
-	VP_RSVD_1,
-	VP_RSVD_2,
-
-	VP_RSVD_3,
-	VP_VDC,
-
-	VP_VCO,
-	VP_CRC,
-
-	VP_CRC32,
-	VP_VDE,
-
-	VP_CCK,
-	VP_CCM,
-
-	VP_CC1,
-	VP_CC2,
-
-	VP_A1X,
-	VP_A1Y,
-
-	VP_A1C,
-	VP_A1T,
-
-	VP_A2X,
-	VP_A2Y,
-
-	VP_A2C,
-	VP_A2T,
-
-	VP_A3X,
-	VP_A3Y,
-
-	VP_A3C,
-	VP_A3T,
-
-	VP_VRR,
-	VP_AWT,
-
-	VP_VTM, /* 0x130 */
-};
-
-#define VP_VCFG_VID_EN			(1 << 0)
-
-#define VP_DCFG_DAC_VREF		(1 << 26)
-#define VP_DCFG_GV_GAM			(1 << 21)
-#define VP_DCFG_VG_CK			(1 << 20)
-#define VP_DCFG_CRT_SYNC_SKW_DEFAULT	(1 << 16)
-#define VP_DCFG_CRT_SYNC_SKW		((1 << 14) | (1 << 15) | (1 << 16))
-#define VP_DCFG_CRT_VSYNC_POL		(1 << 9)
-#define VP_DCFG_CRT_HSYNC_POL		(1 << 8)
-#define VP_DCFG_FP_DATA_EN		(1 << 7)	/* undocumented */
-#define VP_DCFG_FP_PWR_EN		(1 << 6)	/* undocumented */
-#define VP_DCFG_DAC_BL_EN		(1 << 3)
-#define VP_DCFG_VSYNC_EN		(1 << 2)
-#define VP_DCFG_HSYNC_EN		(1 << 1)
-#define VP_DCFG_CRT_EN			(1 << 0)
-
-#define VP_MISC_GAM_EN			(1 << 0)
-#define VP_MISC_DACPWRDN		(1 << 10)
-#define VP_MISC_APWRDN			(1 << 11)
-
-
-/*
- * Flat Panel registers (table 6-55).
- * Also 64 bit registers; see above note about 32-bit handling.
- */
-
-/* we're actually in the VP register space, starting at address 0x400 */
-#define VP_FP_START		0x400
-
-enum fp_registers {
-	FP_PT1 = 0,
-	FP_PT2,
-
-	FP_PM,
-	FP_DFC,
-
-	FP_BLFSR,
-	FP_RLFSR,
-
-	FP_FMI,
-	FP_FMD,
-
-	FP_RSVD_0,
-	FP_DCA,
-
-	FP_DMD,
-	FP_CRC,
-
-	FP_FBB, /* 0x460 */
-};
-
-#define FP_PT1_VSIZE_SHIFT		16		/* undocumented? */
-#define FP_PT1_VSIZE_MASK		0x7FF0000	/* undocumented? */
-
-#define FP_PT2_HSP			(1 << 22)
-#define FP_PT2_VSP			(1 << 23)
-
-#define FP_PM_P				(1 << 24)       /* panel power on */
-#define FP_PM_PANEL_PWR_UP		(1 << 3)        /* r/o */
-#define FP_PM_PANEL_PWR_DOWN		(1 << 2)        /* r/o */
-#define FP_PM_PANEL_OFF			(1 << 1)        /* r/o */
-#define FP_PM_PANEL_ON			(1 << 0)        /* r/o */
-
-#define FP_DFC_NFI			((1 << 4) | (1 << 5) | (1 << 6))
-
-
-/* register access functions */
-
-static inline uint32_t read_gp(struct gxfb_par *par, int reg)
-{
-	return readl(par->gp_regs + 4*reg);
-}
-
-static inline void write_gp(struct gxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->gp_regs + 4*reg);
-}
-
-static inline uint32_t read_dc(struct gxfb_par *par, int reg)
-{
-	return readl(par->dc_regs + 4*reg);
-}
-
-static inline void write_dc(struct gxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->dc_regs + 4*reg);
-}
-
-static inline uint32_t read_vp(struct gxfb_par *par, int reg)
-{
-	return readl(par->vid_regs + 8*reg);
-}
-
-static inline void write_vp(struct gxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->vid_regs + 8*reg);
-}
-
-static inline uint32_t read_fp(struct gxfb_par *par, int reg)
-{
-	return readl(par->vid_regs + 8*reg + VP_FP_START);
-}
-
-static inline void write_fp(struct gxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->vid_regs + 8*reg + VP_FP_START);
-}
-
-
-/* MSRs are defined in linux/cs5535.h; their bitfields are here */
-
-#define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3	(1 << 3)
-#define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2	(1 << 2)
-#define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2	(1 << 1)
-
-#define MSR_GLCP_DOTPLL_LOCK		(1 << 25)	/* r/o */
-#define MSR_GLCP_DOTPLL_BYPASS		(1 << 15)
-#define MSR_GLCP_DOTPLL_DOTRESET	(1 << 0)
-
-#define MSR_GX_MSR_PADSEL_MASK		0x3FFFFFFF	/* undocumented? */
-#define MSR_GX_MSR_PADSEL_TFT		0x1FFFFFFF	/* undocumented? */
-
-#define MSR_GX_GLD_MSR_CONFIG_FP	(1 << 3)
-
-#endif
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
deleted file mode 100644
index 1790f14bab15..000000000000
--- a/drivers/video/geode/gxfb_core.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * Geode GX framebuffer driver.
- *
- *   Copyright (C) 2006 Arcom Control Systems Ltd.
- *
- *   This program is free software; you can redistribute it and/or modify it
- *   under the terms of the GNU General Public License as published by the
- *   Free Software Foundation; either version 2 of the License, or (at your
- *   option) any later version.
- *
- *
- * This driver assumes that the BIOS has created a virtual PCI device header
- * for the video device. The PCI header is assumed to contain the following
- * BARs:
- *
- *    BAR0 - framebuffer memory
- *    BAR1 - graphics processor registers
- *    BAR2 - display controller registers
- *    BAR3 - video processor and flat panel control registers.
- *
- * 16 MiB of framebuffer memory is assumed to be available.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/suspend.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/cs5535.h>
-
-#include "gxfb.h"
-
-static char *mode_option;
-static int vram;
-static int vt_switch;
-
-/* Modes relevant to the GX (taken from modedb.c) */
-static struct fb_videomode gx_modedb[] = {
-	/* 640x480-60 VESA */
-	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 640x480-75 VESA */
-	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 640x480-85 VESA */
-	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 800x600-60 VESA */
-	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 800x600-75 VESA */
-	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 800x600-85 VESA */
-	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1024x768-60 VESA */
-	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1024x768-75 VESA */
-	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1024x768-85 VESA */
-	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x960-60 VESA */
-	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x960-85 VESA */
-	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x1024-60 VESA */
-	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x1024-75 VESA */
-	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1280x1024-85 VESA */
-	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1600x1200-60 VESA */
-	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1600x1200-75 VESA */
-	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 1600x1200-85 VESA */
-	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-};
-
-#ifdef CONFIG_OLPC
-#include <asm/olpc.h>
-
-static struct fb_videomode gx_dcon_modedb[] = {
-	/* The only mode the DCON has is 1200x900 */
-	{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 }
-};
-
-static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
-{
-	if (olpc_has_dcon()) {
-		*modedb = (struct fb_videomode *) gx_dcon_modedb;
-		*size = ARRAY_SIZE(gx_dcon_modedb);
-	} else {
-		*modedb = (struct fb_videomode *) gx_modedb;
-		*size = ARRAY_SIZE(gx_modedb);
-	}
-}
-
-#else
-static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
-{
-	*modedb = (struct fb_videomode *) gx_modedb;
-	*size = ARRAY_SIZE(gx_modedb);
-}
-#endif
-
-static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->xres > 1600 || var->yres > 1200)
-		return -EINVAL;
-	if ((var->xres > 1280 || var->yres > 1024) && var->bits_per_pixel > 16)
-		return -EINVAL;
-
-	if (var->bits_per_pixel == 32) {
-		var->red.offset   = 16; var->red.length   = 8;
-		var->green.offset =  8; var->green.length = 8;
-		var->blue.offset  =  0; var->blue.length  = 8;
-	} else if (var->bits_per_pixel == 16) {
-		var->red.offset   = 11; var->red.length   = 5;
-		var->green.offset =  5; var->green.length = 6;
-		var->blue.offset  =  0; var->blue.length  = 5;
-	} else if (var->bits_per_pixel == 8) {
-		var->red.offset   = 0; var->red.length   = 8;
-		var->green.offset = 0; var->green.length = 8;
-		var->blue.offset  = 0; var->blue.length  = 8;
-	} else
-		return -EINVAL;
-	var->transp.offset = 0; var->transp.length = 0;
-
-	/* Enough video memory? */
-	if (gx_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
-		return -EINVAL;
-
-	/* FIXME: Check timing parameters here? */
-
-	return 0;
-}
-
-static int gxfb_set_par(struct fb_info *info)
-{
-	if (info->var.bits_per_pixel > 8)
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	else
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel);
-
-	gx_set_mode(info);
-
-	return 0;
-}
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 *pal = info->pseudo_palette;
-		u32 v;
-
-		if (regno >= 16)
-			return -EINVAL;
-
-		v  = chan_to_field(red, &info->var.red);
-		v |= chan_to_field(green, &info->var.green);
-		v |= chan_to_field(blue, &info->var.blue);
-
-		pal[regno] = v;
-	} else {
-		if (regno >= 256)
-			return -EINVAL;
-
-		gx_set_hw_palette_reg(info, regno, red, green, blue);
-	}
-
-	return 0;
-}
-
-static int gxfb_blank(int blank_mode, struct fb_info *info)
-{
-	return gx_blank_display(info, blank_mode);
-}
-
-static int gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
-{
-	struct gxfb_par *par = info->par;
-	int ret;
-
-	ret = pci_enable_device(dev);
-	if (ret < 0)
-		return ret;
-
-	ret = pci_request_region(dev, 3, "gxfb (video processor)");
-	if (ret < 0)
-		return ret;
-	par->vid_regs = pci_ioremap_bar(dev, 3);
-	if (!par->vid_regs)
-		return -ENOMEM;
-
-	ret = pci_request_region(dev, 2, "gxfb (display controller)");
-	if (ret < 0)
-		return ret;
-	par->dc_regs = pci_ioremap_bar(dev, 2);
-	if (!par->dc_regs)
-		return -ENOMEM;
-
-	ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
-	if (ret < 0)
-		return ret;
-	par->gp_regs = pci_ioremap_bar(dev, 1);
-
-	if (!par->gp_regs)
-		return -ENOMEM;
-
-	ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
-	if (ret < 0)
-		return ret;
-
-	info->fix.smem_start = pci_resource_start(dev, 0);
-	info->fix.smem_len = vram ? vram : gx_frame_buffer_size();
-	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-	if (!info->screen_base)
-		return -ENOMEM;
-
-	/* Set the 16MiB aligned base address of the graphics memory region
-	 * in the display controller */
-
-	write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000);
-
-	dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n",
-		 info->fix.smem_len / 1024, info->fix.smem_start);
-
-	return 0;
-}
-
-static struct fb_ops gxfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= gxfb_check_var,
-	.fb_set_par	= gxfb_set_par,
-	.fb_setcolreg	= gxfb_setcolreg,
-	.fb_blank       = gxfb_blank,
-	/* No HW acceleration for now. */
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static struct fb_info *gxfb_init_fbinfo(struct device *dev)
-{
-	struct gxfb_par *par;
-	struct fb_info *info;
-
-	/* Alloc enough space for the pseudo palette. */
-	info = framebuffer_alloc(sizeof(struct gxfb_par) + sizeof(u32) * 16,
-			dev);
-	if (!info)
-		return NULL;
-
-	par = info->par;
-
-	strcpy(info->fix.id, "Geode GX");
-
-	info->fix.type		= FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux	= 0;
-	info->fix.xpanstep	= 0;
-	info->fix.ypanstep	= 0;
-	info->fix.ywrapstep	= 0;
-	info->fix.accel		= FB_ACCEL_NONE;
-
-	info->var.nonstd	= 0;
-	info->var.activate	= FB_ACTIVATE_NOW;
-	info->var.height	= -1;
-	info->var.width	= -1;
-	info->var.accel_flags = 0;
-	info->var.vmode	= FB_VMODE_NONINTERLACED;
-
-	info->fbops		= &gxfb_ops;
-	info->flags		= FBINFO_DEFAULT;
-	info->node		= -1;
-
-	info->pseudo_palette	= (void *)par + sizeof(struct gxfb_par);
-
-	info->var.grayscale	= 0;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		framebuffer_release(info);
-		return NULL;
-	}
-
-	return info;
-}
-
-#ifdef CONFIG_PM
-static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-
-	if (state.event == PM_EVENT_SUSPEND) {
-		console_lock();
-		gx_powerdown(info);
-		fb_set_suspend(info, 1);
-		console_unlock();
-	}
-
-	/* there's no point in setting PCI states; we emulate PCI, so
-	 * we don't end up getting power savings anyways */
-
-	return 0;
-}
-
-static int gxfb_resume(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	int ret;
-
-	console_lock();
-	ret = gx_powerup(info);
-	if (ret) {
-		printk(KERN_ERR "gxfb:  power up failed!\n");
-		return ret;
-	}
-
-	fb_set_suspend(info, 0);
-	console_unlock();
-	return 0;
-}
-#endif
-
-static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct gxfb_par *par;
-	struct fb_info *info;
-	int ret;
-	unsigned long val;
-
-	struct fb_videomode *modedb_ptr;
-	unsigned int modedb_size;
-
-	info = gxfb_init_fbinfo(&pdev->dev);
-	if (!info)
-		return -ENOMEM;
-	par = info->par;
-
-	if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
-		dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
-		goto err;
-	}
-
-	/* Figure out if this is a TFT or CRT part */
-
-	rdmsrl(MSR_GX_GLD_MSR_CONFIG, val);
-
-	if ((val & MSR_GX_GLD_MSR_CONFIG_FP) == MSR_GX_GLD_MSR_CONFIG_FP)
-		par->enable_crt = 0;
-	else
-		par->enable_crt = 1;
-
-	get_modedb(&modedb_ptr, &modedb_size);
-	ret = fb_find_mode(&info->var, info, mode_option,
-			   modedb_ptr, modedb_size, NULL, 16);
-	if (ret == 0 || ret == 4) {
-		dev_err(&pdev->dev, "could not find valid video mode\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-
-	/* Clear the frame buffer of garbage. */
-        memset_io(info->screen_base, 0, info->fix.smem_len);
-
-	gxfb_check_var(&info->var, info);
-	gxfb_set_par(info);
-
-	pm_set_vt_switch(vt_switch);
-
-	if (register_framebuffer(info) < 0) {
-		ret = -EINVAL;
-		goto err;
-	}
-	pci_set_drvdata(pdev, info);
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	return 0;
-
-  err:
-	if (info->screen_base) {
-		iounmap(info->screen_base);
-		pci_release_region(pdev, 0);
-	}
-	if (par->vid_regs) {
-		iounmap(par->vid_regs);
-		pci_release_region(pdev, 3);
-	}
-	if (par->dc_regs) {
-		iounmap(par->dc_regs);
-		pci_release_region(pdev, 2);
-	}
-	if (par->gp_regs) {
-		iounmap(par->gp_regs);
-		pci_release_region(pdev, 1);
-	}
-
-	if (info) {
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	return ret;
-}
-
-static void gxfb_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct gxfb_par *par = info->par;
-
-	unregister_framebuffer(info);
-
-	iounmap((void __iomem *)info->screen_base);
-	pci_release_region(pdev, 0);
-
-	iounmap(par->vid_regs);
-	pci_release_region(pdev, 3);
-
-	iounmap(par->dc_regs);
-	pci_release_region(pdev, 2);
-
-	iounmap(par->gp_regs);
-	pci_release_region(pdev, 1);
-
-	fb_dealloc_cmap(&info->cmap);
-
-	framebuffer_release(info);
-}
-
-static struct pci_device_id gxfb_id_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, gxfb_id_table);
-
-static struct pci_driver gxfb_driver = {
-	.name		= "gxfb",
-	.id_table	= gxfb_id_table,
-	.probe		= gxfb_probe,
-	.remove		= gxfb_remove,
-#ifdef CONFIG_PM
-	.suspend	= gxfb_suspend,
-	.resume		= gxfb_resume,
-#endif
-};
-
-#ifndef MODULE
-static int __init gxfb_setup(char *options)
-{
-
-	char *opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-
-		mode_option = opt;
-	}
-
-	return 0;
-}
-#endif
-
-static int __init gxfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("gxfb", &option))
-		return -ENODEV;
-
-	gxfb_setup(option);
-#endif
-	return pci_register_driver(&gxfb_driver);
-}
-
-static void __exit gxfb_cleanup(void)
-{
-	pci_unregister_driver(&gxfb_driver);
-}
-
-module_init(gxfb_init);
-module_exit(gxfb_cleanup);
-
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
-
-module_param(vram, int, 0);
-MODULE_PARM_DESC(vram, "video memory size");
-
-module_param(vt_switch, int, 0);
-MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");
-
-MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
deleted file mode 100644
index cfcd8090f313..000000000000
--- a/drivers/video/geode/lxfb.h
+++ /dev/null
@@ -1,452 +0,0 @@
-/* Geode LX framebuffer driver
- *
- * Copyright (C) 2006-2007, Advanced Micro Devices,Inc.
- * Copyright (c) 2008  Andres Salomon <dilinger@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef _LXFB_H_
-#define _LXFB_H_
-
-#include <linux/fb.h>
-
-#define GP_REG_COUNT	(0x7c / 4)
-#define DC_REG_COUNT	(0xf0 / 4)
-#define VP_REG_COUNT	(0x158 / 8)
-#define FP_REG_COUNT	(0x60 / 8)
-
-#define DC_PAL_COUNT	0x104
-#define DC_HFILT_COUNT	0x100
-#define DC_VFILT_COUNT	0x100
-#define VP_COEFF_SIZE	0x1000
-#define VP_PAL_COUNT	0x100
-
-#define OUTPUT_CRT   0x01
-#define OUTPUT_PANEL 0x02
-
-struct lxfb_par {
-	int output;
-
-	void __iomem *gp_regs;
-	void __iomem *dc_regs;
-	void __iomem *vp_regs;
-#ifdef CONFIG_PM
-	int powered_down;
-
-	/* register state, for power mgmt functionality */
-	struct {
-		uint64_t padsel;
-		uint64_t dotpll;
-		uint64_t dfglcfg;
-		uint64_t dcspare;
-	} msr;
-
-	uint32_t gp[GP_REG_COUNT];
-	uint32_t dc[DC_REG_COUNT];
-	uint64_t vp[VP_REG_COUNT];
-	uint64_t fp[FP_REG_COUNT];
-
-	uint32_t dc_pal[DC_PAL_COUNT];
-	uint32_t vp_pal[VP_PAL_COUNT];
-	uint32_t hcoeff[DC_HFILT_COUNT * 2];
-	uint32_t vcoeff[DC_VFILT_COUNT];
-	uint32_t vp_coeff[VP_COEFF_SIZE / 4];
-#endif
-};
-
-static inline unsigned int lx_get_pitch(unsigned int xres, int bpp)
-{
-	return (((xres * (bpp >> 3)) + 7) & ~7);
-}
-
-void lx_set_mode(struct fb_info *);
-unsigned int lx_framebuffer_size(void);
-int lx_blank_display(struct fb_info *, int);
-void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
-			unsigned int, unsigned int);
-
-#ifdef CONFIG_PM
-int lx_powerdown(struct fb_info *info);
-int lx_powerup(struct fb_info *info);
-#endif
-
-
-/* Graphics Processor registers (table 6-29 from the data book) */
-enum gp_registers {
-	GP_DST_OFFSET = 0,
-	GP_SRC_OFFSET,
-	GP_STRIDE,
-	GP_WID_HEIGHT,
-
-	GP_SRC_COLOR_FG,
-	GP_SRC_COLOR_BG,
-	GP_PAT_COLOR_0,
-	GP_PAT_COLOR_1,
-
-	GP_PAT_COLOR_2,
-	GP_PAT_COLOR_3,
-	GP_PAT_COLOR_4,
-	GP_PAT_COLOR_5,
-
-	GP_PAT_DATA_0,
-	GP_PAT_DATA_1,
-	GP_RASTER_MODE,
-	GP_VECTOR_MODE,
-
-	GP_BLT_MODE,
-	GP_BLT_STATUS,
-	GP_HST_SRC,
-	GP_BASE_OFFSET,
-
-	GP_CMD_TOP,
-	GP_CMD_BOT,
-	GP_CMD_READ,
-	GP_CMD_WRITE,
-
-	GP_CH3_OFFSET,
-	GP_CH3_MODE_STR,
-	GP_CH3_WIDHI,
-	GP_CH3_HSRC,
-
-	GP_LUT_INDEX,
-	GP_LUT_DATA,
-	GP_INT_CNTRL, /* 0x78 */
-};
-
-#define GP_BLT_STATUS_CE		(1 << 4)	/* cmd buf empty */
-#define GP_BLT_STATUS_PB		(1 << 0)	/* primitive busy */
-
-
-/* Display Controller registers (table 6-47 from the data book) */
-enum dc_registers {
-	DC_UNLOCK = 0,
-	DC_GENERAL_CFG,
-	DC_DISPLAY_CFG,
-	DC_ARB_CFG,
-
-	DC_FB_ST_OFFSET,
-	DC_CB_ST_OFFSET,
-	DC_CURS_ST_OFFSET,
-	DC_RSVD_0,
-
-	DC_VID_Y_ST_OFFSET,
-	DC_VID_U_ST_OFFSET,
-	DC_VID_V_ST_OFFSET,
-	DC_DV_TOP,
-
-	DC_LINE_SIZE,
-	DC_GFX_PITCH,
-	DC_VID_YUV_PITCH,
-	DC_RSVD_1,
-
-	DC_H_ACTIVE_TIMING,
-	DC_H_BLANK_TIMING,
-	DC_H_SYNC_TIMING,
-	DC_RSVD_2,
-
-	DC_V_ACTIVE_TIMING,
-	DC_V_BLANK_TIMING,
-	DC_V_SYNC_TIMING,
-	DC_FB_ACTIVE,
-
-	DC_CURSOR_X,
-	DC_CURSOR_Y,
-	DC_RSVD_3,
-	DC_LINE_CNT,
-
-	DC_PAL_ADDRESS,
-	DC_PAL_DATA,
-	DC_DFIFO_DIAG,
-	DC_CFIFO_DIAG,
-
-	DC_VID_DS_DELTA,
-	DC_GLIU0_MEM_OFFSET,
-	DC_DV_CTL,
-	DC_DV_ACCESS,
-
-	DC_GFX_SCALE,
-	DC_IRQ_FILT_CTL,
-	DC_FILT_COEFF1,
-	DC_FILT_COEFF2,
-
-	DC_VBI_EVEN_CTL,
-	DC_VBI_ODD_CTL,
-	DC_VBI_HOR,
-	DC_VBI_LN_ODD,
-
-	DC_VBI_LN_EVEN,
-	DC_VBI_PITCH,
-	DC_CLR_KEY,
-	DC_CLR_KEY_MASK,
-
-	DC_CLR_KEY_X,
-	DC_CLR_KEY_Y,
-	DC_IRQ,
-	DC_RSVD_4,
-
-	DC_RSVD_5,
-	DC_GENLK_CTL,
-	DC_VID_EVEN_Y_ST_OFFSET,
-	DC_VID_EVEN_U_ST_OFFSET,
-
-	DC_VID_EVEN_V_ST_OFFSET,
-	DC_V_ACTIVE_EVEN_TIMING,
-	DC_V_BLANK_EVEN_TIMING,
-	DC_V_SYNC_EVEN_TIMING,	/* 0xec */
-};
-
-#define DC_UNLOCK_LOCK			0x00000000
-#define DC_UNLOCK_UNLOCK		0x00004758	/* magic value */
-
-#define DC_GENERAL_CFG_FDTY		(1 << 17)
-#define DC_GENERAL_CFG_DFHPEL_SHIFT	(12)
-#define DC_GENERAL_CFG_DFHPSL_SHIFT	(8)
-#define DC_GENERAL_CFG_VGAE		(1 << 7)
-#define DC_GENERAL_CFG_DECE		(1 << 6)
-#define DC_GENERAL_CFG_CMPE		(1 << 5)
-#define DC_GENERAL_CFG_VIDE		(1 << 3)
-#define DC_GENERAL_CFG_DFLE		(1 << 0)
-
-#define DC_DISPLAY_CFG_VISL		(1 << 27)
-#define DC_DISPLAY_CFG_PALB		(1 << 25)
-#define DC_DISPLAY_CFG_DCEN		(1 << 24)
-#define DC_DISPLAY_CFG_DISP_MODE_24BPP	(1 << 9)
-#define DC_DISPLAY_CFG_DISP_MODE_16BPP	(1 << 8)
-#define DC_DISPLAY_CFG_DISP_MODE_8BPP	(0)
-#define DC_DISPLAY_CFG_TRUP		(1 << 6)
-#define DC_DISPLAY_CFG_VDEN		(1 << 4)
-#define DC_DISPLAY_CFG_GDEN		(1 << 3)
-#define DC_DISPLAY_CFG_TGEN		(1 << 0)
-
-#define DC_DV_TOP_DV_TOP_EN		(1 << 0)
-
-#define DC_DV_CTL_DV_LINE_SIZE		((1 << 10) | (1 << 11))
-#define DC_DV_CTL_DV_LINE_SIZE_1K	(0)
-#define DC_DV_CTL_DV_LINE_SIZE_2K	(1 << 10)
-#define DC_DV_CTL_DV_LINE_SIZE_4K	(1 << 11)
-#define DC_DV_CTL_DV_LINE_SIZE_8K	((1 << 10) | (1 << 11))
-#define DC_DV_CTL_CLEAR_DV_RAM		(1 << 0)
-
-#define DC_IRQ_FILT_CTL_H_FILT_SEL	(1 << 10)
-
-#define DC_CLR_KEY_CLR_KEY_EN		(1 << 24)
-
-#define DC_IRQ_VIP_VSYNC_IRQ_STATUS	(1 << 21)	/* undocumented? */
-#define DC_IRQ_STATUS			(1 << 20)	/* undocumented? */
-#define DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK	(1 << 1)
-#define DC_IRQ_MASK			(1 << 0)
-
-#define DC_GENLK_CTL_FLICK_SEL_MASK	(0x0F << 28)
-#define DC_GENLK_CTL_ALPHA_FLICK_EN	(1 << 25)
-#define DC_GENLK_CTL_FLICK_EN		(1 << 24)
-#define DC_GENLK_CTL_GENLK_EN		(1 << 18)
-
-
-/*
- * Video Processor registers (table 6-71).
- * There is space for 64 bit values, but we never use more than the
- * lower 32 bits.  The actual register save/restore code only bothers
- * to restore those 32 bits.
- */
-enum vp_registers {
-	VP_VCFG = 0,
-	VP_DCFG,
-
-	VP_VX,
-	VP_VY,
-
-	VP_SCL,
-	VP_VCK,
-
-	VP_VCM,
-	VP_PAR,
-
-	VP_PDR,
-	VP_SLR,
-
-	VP_MISC,
-	VP_CCS,
-
-	VP_VYS,
-	VP_VXS,
-
-	VP_RSVD_0,
-	VP_VDC,
-
-	VP_RSVD_1,
-	VP_CRC,
-
-	VP_CRC32,
-	VP_VDE,
-
-	VP_CCK,
-	VP_CCM,
-
-	VP_CC1,
-	VP_CC2,
-
-	VP_A1X,
-	VP_A1Y,
-
-	VP_A1C,
-	VP_A1T,
-
-	VP_A2X,
-	VP_A2Y,
-
-	VP_A2C,
-	VP_A2T,
-
-	VP_A3X,
-	VP_A3Y,
-
-	VP_A3C,
-	VP_A3T,
-
-	VP_VRR,
-	VP_AWT,
-
-	VP_VTM,
-	VP_VYE,
-
-	VP_A1YE,
-	VP_A2YE,
-
-	VP_A3YE,	/* 0x150 */
-
-	VP_VCR = 0x1000, /* 0x1000 - 0x1fff */
-};
-
-#define VP_VCFG_VID_EN			(1 << 0)
-
-#define VP_DCFG_GV_GAM			(1 << 21)
-#define VP_DCFG_PWR_SEQ_DELAY		((1 << 17) | (1 << 18) | (1 << 19))
-#define VP_DCFG_PWR_SEQ_DELAY_DEFAULT	(1 << 19)	/* undocumented */
-#define VP_DCFG_CRT_SYNC_SKW		((1 << 14) | (1 << 15) | (1 << 16))
-#define VP_DCFG_CRT_SYNC_SKW_DEFAULT	(1 << 16)
-#define VP_DCFG_CRT_VSYNC_POL		(1 << 9)
-#define VP_DCFG_CRT_HSYNC_POL		(1 << 8)
-#define VP_DCFG_DAC_BL_EN		(1 << 3)
-#define VP_DCFG_VSYNC_EN		(1 << 2)
-#define VP_DCFG_HSYNC_EN		(1 << 1)
-#define VP_DCFG_CRT_EN			(1 << 0)
-
-#define VP_MISC_APWRDN			(1 << 11)
-#define VP_MISC_DACPWRDN		(1 << 10)
-#define VP_MISC_BYP_BOTH		(1 << 0)
-
-
-/*
- * Flat Panel registers (table 6-71).
- * Also 64 bit registers; see above note about 32-bit handling.
- */
-
-/* we're actually in the VP register space, starting at address 0x400 */
-#define VP_FP_START	0x400
-
-enum fp_registers {
-	FP_PT1 = 0,
-	FP_PT2,
-
-	FP_PM,
-	FP_DFC,
-
-	FP_RSVD_0,
-	FP_RSVD_1,
-
-	FP_RSVD_2,
-	FP_RSVD_3,
-
-	FP_RSVD_4,
-	FP_DCA,
-
-	FP_DMD,
-	FP_CRC, /* 0x458 */
-};
-
-#define FP_PT2_HSP			(1 << 22)
-#define FP_PT2_VSP			(1 << 23)
-#define FP_PT2_SCRC			(1 << 27)	/* shfclk free */
-
-#define FP_PM_P				(1 << 24)	/* panel power ctl */
-#define FP_PM_PANEL_PWR_UP		(1 << 3)	/* r/o */
-#define FP_PM_PANEL_PWR_DOWN		(1 << 2)	/* r/o */
-#define FP_PM_PANEL_OFF			(1 << 1)	/* r/o */
-#define FP_PM_PANEL_ON			(1 << 0)	/* r/o */
-
-#define FP_DFC_BC			((1 << 4) | (1 << 5) | (1 << 6))
-
-
-/* register access functions */
-
-static inline uint32_t read_gp(struct lxfb_par *par, int reg)
-{
-	return readl(par->gp_regs + 4*reg);
-}
-
-static inline void write_gp(struct lxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->gp_regs + 4*reg);
-}
-
-static inline uint32_t read_dc(struct lxfb_par *par, int reg)
-{
-	return readl(par->dc_regs + 4*reg);
-}
-
-static inline void write_dc(struct lxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->dc_regs + 4*reg);
-}
-
-static inline uint32_t read_vp(struct lxfb_par *par, int reg)
-{
-	return readl(par->vp_regs + 8*reg);
-}
-
-static inline void write_vp(struct lxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->vp_regs + 8*reg);
-}
-
-static inline uint32_t read_fp(struct lxfb_par *par, int reg)
-{
-	return readl(par->vp_regs + 8*reg + VP_FP_START);
-}
-
-static inline void write_fp(struct lxfb_par *par, int reg, uint32_t val)
-{
-	writel(val, par->vp_regs + 8*reg + VP_FP_START);
-}
-
-
-/* MSRs are defined in linux/cs5535.h; their bitfields are here */
-
-#define MSR_GLCP_DOTPLL_LOCK		(1 << 25)	/* r/o */
-#define MSR_GLCP_DOTPLL_HALFPIX		(1 << 24)
-#define MSR_GLCP_DOTPLL_BYPASS		(1 << 15)
-#define MSR_GLCP_DOTPLL_DOTRESET	(1 << 0)
-
-/* note: this is actually the VP's GLD_MSR_CONFIG */
-#define MSR_LX_GLD_MSR_CONFIG_FMT	((1 << 3) | (1 << 4) | (1 << 5))
-#define MSR_LX_GLD_MSR_CONFIG_FMT_FP	(1 << 3)
-#define MSR_LX_GLD_MSR_CONFIG_FMT_CRT	(0)
-#define MSR_LX_GLD_MSR_CONFIG_FPC	(1 << 15)	/* FP *and* CRT */
-
-#define MSR_LX_MSR_PADSEL_TFT_SEL_LOW	0xDFFFFFFF	/* ??? */
-#define MSR_LX_MSR_PADSEL_TFT_SEL_HIGH	0x0000003F	/* ??? */
-
-#define MSR_LX_SPARE_MSR_DIS_CFIFO_HGO	(1 << 11)	/* undocumented */
-#define MSR_LX_SPARE_MSR_VFIFO_ARB_SEL	(1 << 10)	/* undocumented */
-#define MSR_LX_SPARE_MSR_WM_LPEN_OVRD	(1 << 9)	/* undocumented */
-#define MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M	(1 << 8)	/* undocumented */
-#define MSR_LX_SPARE_MSR_DIS_INIT_V_PRI	(1 << 7)	/* undocumented */
-#define MSR_LX_SPARE_MSR_DIS_VIFO_WM	(1 << 6)
-#define MSR_LX_SPARE_MSR_DIS_CWD_CHECK	(1 << 5)	/* undocumented */
-#define MSR_LX_SPARE_MSR_PIX8_PAN_FIX	(1 << 4)	/* undocumented */
-#define MSR_LX_SPARE_MSR_FIRST_REQ_MASK	(1 << 1)	/* undocumented */
-
-#endif
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
deleted file mode 100644
index 9e1d19d673a1..000000000000
--- a/drivers/video/geode/lxfb_core.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Geode LX framebuffer driver.
- *
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
- * Built from gxfb (which is Copyright (C) 2006 Arcom Control Systems Ltd.)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/console.h>
-#include <linux/mm.h>
-#include <linux/suspend.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/uaccess.h>
-
-#include "lxfb.h"
-
-static char *mode_option;
-static int noclear, nopanel, nocrt;
-static int vram;
-static int vt_switch;
-
-/* Most of these modes are sorted in ascending order, but
- * since the first entry in this table is the "default" mode,
- * we try to make it something sane - 640x480-60 is sane
- */
-
-static struct fb_videomode geode_modedb[] = {
-	/* 640x480-60 */
-	{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 640x400-70 */
-	{ NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2,
-	  FB_SYNC_HOR_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 640x480-70 */
-	{ NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 640x480-72 */
-	{ NULL, 72, 640, 480, 32102, 120, 16, 20, 1, 40, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 640x480-75 */
-	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 640x480-85 */
-	{ NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 640x480-90 */
-	{ NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 640x480-100 */
-	{ NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 640x480-60 */
-	{ NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-56 */
-	{ NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-60 */
-	{ NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-70 */
-	{ NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-72 */
-	{ NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-75 */
-	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-85 */
-	{ NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-90 */
-	{ NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-100 */
-	{ NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 800x600-60 */
-	{ NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-60 */
-	{ NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-70 */
-	{ NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-72 */
-	{ NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-75 */
-	{ NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-85 */
-	{ NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-90 */
-	{ NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-100 */
-	{ NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1024x768-60 */
-	{ NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-60 */
-	{ NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-70 */
-	{ NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-72 */
-	{ NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-75 */
-	{ NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-85 */
-	{ NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-90 */
-	{ NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-100 */
-	{ NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1152x864-60 */
-	{ NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-60 */
-	{ NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-70 */
-	{ NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-72 */
-	{ NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-75 */
-	{ NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-85 */
-	{ NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-90 */
-	{ NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-100 */
-	{ NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1280x1024-60 */
-	{ NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-60 */
-	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-70 */
-	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-72 */
-	{ NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-75 */
-	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-85 */
-	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-90 */
-	{ NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-100 */
-	{ NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1600x1200-60 */
-	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 },
-	/* 1920x1440-60 */
-	{ NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1920x1440-70 */
-	{ NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1920x1440-72 */
-	{ NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1920x1440-75 */
-	{ NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-	/* 1920x1440-85 */
-	{ NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3,
-	  0, FB_VMODE_NONINTERLACED, 0 },
-};
-
-#ifdef CONFIG_OLPC
-#include <asm/olpc.h>
-
-static struct fb_videomode olpc_dcon_modedb[] = {
-	/* The only mode the DCON has is 1200x900 */
-	{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, 0 }
-};
-
-static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
-{
-	if (olpc_has_dcon()) {
-		*modedb = (struct fb_videomode *) olpc_dcon_modedb;
-		*size = ARRAY_SIZE(olpc_dcon_modedb);
-	} else {
-		*modedb = (struct fb_videomode *) geode_modedb;
-		*size = ARRAY_SIZE(geode_modedb);
-	}
-}
-
-#else
-static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
-{
-	*modedb = (struct fb_videomode *) geode_modedb;
-	*size = ARRAY_SIZE(geode_modedb);
-}
-#endif
-
-static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->xres > 1920 || var->yres > 1440)
-		return -EINVAL;
-
-	if (var->bits_per_pixel == 32) {
-		var->red.offset   = 16; var->red.length   = 8;
-		var->green.offset =  8; var->green.length = 8;
-		var->blue.offset  =  0; var->blue.length  = 8;
-	} else if (var->bits_per_pixel == 16) {
-		var->red.offset   = 11; var->red.length   = 5;
-		var->green.offset =  5; var->green.length = 6;
-		var->blue.offset  =  0; var->blue.length  = 5;
-	} else if (var->bits_per_pixel == 8) {
-		var->red.offset   = 0; var->red.length   = 8;
-		var->green.offset = 0; var->green.length = 8;
-		var->blue.offset  = 0; var->blue.length  = 8;
-	} else
-		return -EINVAL;
-
-	var->transp.offset = 0; var->transp.length = 0;
-
-	/* Enough video memory? */
-	if ((lx_get_pitch(var->xres, var->bits_per_pixel) * var->yres)
-	    > info->fix.smem_len)
-	  return -EINVAL;
-
-	return 0;
-}
-
-static int lxfb_set_par(struct fb_info *info)
-{
-	if (info->var.bits_per_pixel > 8)
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	else
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = lx_get_pitch(info->var.xres,
-		info->var.bits_per_pixel);
-
-	lx_set_mode(info);
-	return 0;
-}
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int lxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 *pal = info->pseudo_palette;
-		u32 v;
-
-		if (regno >= 16)
-			return -EINVAL;
-
-		v  = chan_to_field(red, &info->var.red);
-		v |= chan_to_field(green, &info->var.green);
-		v |= chan_to_field(blue, &info->var.blue);
-
-		pal[regno] = v;
-	} else {
-		if (regno >= 256)
-			return -EINVAL;
-
-		lx_set_palette_reg(info, regno, red, green, blue);
-	}
-
-	return 0;
-}
-
-static int lxfb_blank(int blank_mode, struct fb_info *info)
-{
-	return lx_blank_display(info, blank_mode);
-}
-
-
-static int lxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
-{
-	struct lxfb_par *par = info->par;
-	int ret;
-
-	ret = pci_enable_device(dev);
-
-	if (ret)
-		return ret;
-
-	ret = pci_request_region(dev, 0, "lxfb-framebuffer");
-
-	if (ret)
-		return ret;
-
-	ret = pci_request_region(dev, 1, "lxfb-gp");
-
-	if (ret)
-		return ret;
-
-	ret = pci_request_region(dev, 2, "lxfb-vg");
-
-	if (ret)
-		return ret;
-
-	ret = pci_request_region(dev, 3, "lxfb-vp");
-
-	if (ret)
-		return ret;
-
-	info->fix.smem_start = pci_resource_start(dev, 0);
-	info->fix.smem_len = vram ? vram : lx_framebuffer_size();
-
-	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-
-	ret = -ENOMEM;
-
-	if (info->screen_base == NULL)
-		return ret;
-
-	par->gp_regs = pci_ioremap_bar(dev, 1);
-
-	if (par->gp_regs == NULL)
-		return ret;
-
-	par->dc_regs = pci_ioremap_bar(dev, 2);
-
-	if (par->dc_regs == NULL)
-		return ret;
-
-	par->vp_regs = pci_ioremap_bar(dev, 3);
-
-	if (par->vp_regs == NULL)
-		return ret;
-
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-	write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000);
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
-
-	dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n",
-		 info->fix.smem_len / 1024, info->fix.smem_start);
-
-	return 0;
-}
-
-static struct fb_ops lxfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= lxfb_check_var,
-	.fb_set_par	= lxfb_set_par,
-	.fb_setcolreg	= lxfb_setcolreg,
-	.fb_blank       = lxfb_blank,
-	/* No HW acceleration for now. */
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static struct fb_info *lxfb_init_fbinfo(struct device *dev)
-{
-	struct lxfb_par *par;
-	struct fb_info *info;
-
-	/* Alloc enough space for the pseudo palette. */
-	info = framebuffer_alloc(sizeof(struct lxfb_par) + sizeof(u32) * 16,
-				 dev);
-	if (!info)
-		return NULL;
-
-	par = info->par;
-
-	strcpy(info->fix.id, "Geode LX");
-
-	info->fix.type		= FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux	= 0;
-	info->fix.xpanstep	= 0;
-	info->fix.ypanstep	= 0;
-	info->fix.ywrapstep	= 0;
-	info->fix.accel		= FB_ACCEL_NONE;
-
-	info->var.nonstd	= 0;
-	info->var.activate	= FB_ACTIVATE_NOW;
-	info->var.height	= -1;
-	info->var.width	= -1;
-	info->var.accel_flags = 0;
-	info->var.vmode	= FB_VMODE_NONINTERLACED;
-
-	info->fbops		= &lxfb_ops;
-	info->flags		= FBINFO_DEFAULT;
-	info->node		= -1;
-
-	info->pseudo_palette	= (void *)par + sizeof(struct lxfb_par);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		framebuffer_release(info);
-		return NULL;
-	}
-
-	info->var.grayscale	= 0;
-
-	return info;
-}
-
-#ifdef CONFIG_PM
-static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-
-	if (state.event == PM_EVENT_SUSPEND) {
-		console_lock();
-		lx_powerdown(info);
-		fb_set_suspend(info, 1);
-		console_unlock();
-	}
-
-	/* there's no point in setting PCI states; we emulate PCI, so
-	 * we don't end up getting power savings anyways */
-
-	return 0;
-}
-
-static int lxfb_resume(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	int ret;
-
-	console_lock();
-	ret = lx_powerup(info);
-	if (ret) {
-		printk(KERN_ERR "lxfb:  power up failed!\n");
-		return ret;
-	}
-
-	fb_set_suspend(info, 0);
-	console_unlock();
-	return 0;
-}
-#else
-#define lxfb_suspend NULL
-#define lxfb_resume NULL
-#endif
-
-static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct lxfb_par *par;
-	struct fb_info *info;
-	int ret;
-
-	struct fb_videomode *modedb_ptr;
-	unsigned int modedb_size;
-
-	info = lxfb_init_fbinfo(&pdev->dev);
-
-	if (info == NULL)
-		return -ENOMEM;
-
-	par = info->par;
-
-	ret = lxfb_map_video_memory(info, pdev);
-
-	if (ret < 0) {
-		dev_err(&pdev->dev,
-			"failed to map frame buffer or controller registers\n");
-		goto err;
-	}
-
-	/* Set up the desired outputs */
-
-	par->output = 0;
-	par->output |= (nopanel) ? 0 : OUTPUT_PANEL;
-	par->output |= (nocrt) ? 0 : OUTPUT_CRT;
-
-	/* Set up the mode database */
-
-	get_modedb(&modedb_ptr, &modedb_size);
-	ret = fb_find_mode(&info->var, info, mode_option,
-			   modedb_ptr, modedb_size, NULL, 16);
-
-	if (ret == 0 || ret == 4) {
-		dev_err(&pdev->dev, "could not find valid video mode\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* Clear the screen of garbage, unless noclear was specified,
-	 * in which case we assume the user knows what he is doing */
-
-	if (!noclear)
-		memset_io(info->screen_base, 0, info->fix.smem_len);
-
-	/* Set the mode */
-
-	lxfb_check_var(&info->var, info);
-	lxfb_set_par(info);
-
-	pm_set_vt_switch(vt_switch);
-
-	if (register_framebuffer(info) < 0) {
-		ret = -EINVAL;
-		goto err;
-	}
-	pci_set_drvdata(pdev, info);
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	return 0;
-
-err:
-	if (info->screen_base) {
-		iounmap(info->screen_base);
-		pci_release_region(pdev, 0);
-	}
-	if (par->gp_regs) {
-		iounmap(par->gp_regs);
-		pci_release_region(pdev, 1);
-	}
-	if (par->dc_regs) {
-		iounmap(par->dc_regs);
-		pci_release_region(pdev, 2);
-	}
-	if (par->vp_regs) {
-		iounmap(par->vp_regs);
-		pci_release_region(pdev, 3);
-	}
-
-	if (info) {
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-
-	return ret;
-}
-
-static void lxfb_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct lxfb_par *par = info->par;
-
-	unregister_framebuffer(info);
-
-	iounmap(info->screen_base);
-	pci_release_region(pdev, 0);
-
-	iounmap(par->gp_regs);
-	pci_release_region(pdev, 1);
-
-	iounmap(par->dc_regs);
-	pci_release_region(pdev, 2);
-
-	iounmap(par->vp_regs);
-	pci_release_region(pdev, 3);
-
-	fb_dealloc_cmap(&info->cmap);
-	framebuffer_release(info);
-}
-
-static struct pci_device_id lxfb_id_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_VIDEO) },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, lxfb_id_table);
-
-static struct pci_driver lxfb_driver = {
-	.name		= "lxfb",
-	.id_table	= lxfb_id_table,
-	.probe		= lxfb_probe,
-	.remove		= lxfb_remove,
-	.suspend	= lxfb_suspend,
-	.resume		= lxfb_resume,
-};
-
-#ifndef MODULE
-static int __init lxfb_setup(char *options)
-{
-	char *opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-
-		if (!strcmp(opt, "noclear"))
-			noclear = 1;
-		else if (!strcmp(opt, "nopanel"))
-			nopanel = 1;
-		else if (!strcmp(opt, "nocrt"))
-			nocrt = 1;
-		else
-			mode_option = opt;
-	}
-
-	return 0;
-}
-#endif
-
-static int __init lxfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("lxfb", &option))
-		return -ENODEV;
-
-	lxfb_setup(option);
-#endif
-	return pci_register_driver(&lxfb_driver);
-}
-static void __exit lxfb_cleanup(void)
-{
-	pci_unregister_driver(&lxfb_driver);
-}
-
-module_init(lxfb_init);
-module_exit(lxfb_cleanup);
-
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
-
-module_param(vram, int, 0);
-MODULE_PARM_DESC(vram, "video memory size");
-
-module_param(vt_switch, int, 0);
-MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");
-
-MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
deleted file mode 100644
index 79e9abc72b83..000000000000
--- a/drivers/video/geode/lxfb_ops.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/* Geode LX framebuffer driver
- *
- * Copyright (C) 2006-2007, Advanced Micro Devices,Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/uaccess.h>
-#include <linux/delay.h>
-#include <linux/cs5535.h>
-
-#include "lxfb.h"
-
-/* TODO
- * Support panel scaling
- * Add acceleration
- * Add support for interlacing (TV out)
- * Support compression
- */
-
-/* This is the complete list of PLL frequencies that we can set -
- * we will choose the closest match to the incoming clock.
- * freq is the frequency of the dotclock * 1000 (for example,
- * 24823 = 24.983 Mhz).
- * pllval is the corresponding PLL value
-*/
-
-static const struct {
-  unsigned int pllval;
-  unsigned int freq;
-} pll_table[] = {
-  { 0x000131AC,   6231 },
-  { 0x0001215D,   6294 },
-  { 0x00011087,   6750 },
-  { 0x0001216C,   7081 },
-  { 0x0001218D,   7140 },
-  { 0x000110C9,   7800 },
-  { 0x00013147,   7875 },
-  { 0x000110A7,   8258 },
-  { 0x00012159,   8778 },
-  { 0x00014249,   8875 },
-  { 0x00010057,   9000 },
-  { 0x0001219A,   9472 },
-  { 0x00012158,   9792 },
-  { 0x00010045,  10000 },
-  { 0x00010089,  10791 },
-  { 0x000110E7,  11225 },
-  { 0x00012136,  11430 },
-  { 0x00013207,  12375 },
-  { 0x00012187,  12500 },
-  { 0x00014286,  14063 },
-  { 0x000110E5,  15016 },
-  { 0x00014214,  16250 },
-  { 0x00011105,  17045 },
-  { 0x000131E4,  18563 },
-  { 0x00013183,  18750 },
-  { 0x00014284,  19688 },
-  { 0x00011104,  20400 },
-  { 0x00016363,  23625 },
-  { 0x000031AC,  24923 },
-  { 0x0000215D,  25175 },
-  { 0x00001087,  27000 },
-  { 0x0000216C,  28322 },
-  { 0x0000218D,  28560 },
-  { 0x000010C9,  31200 },
-  { 0x00003147,  31500 },
-  { 0x000010A7,  33032 },
-  { 0x00002159,  35112 },
-  { 0x00004249,  35500 },
-  { 0x00000057,  36000 },
-  { 0x0000219A,  37889 },
-  { 0x00002158,  39168 },
-  { 0x00000045,  40000 },
-  { 0x00000089,  43163 },
-  { 0x000010E7,  44900 },
-  { 0x00002136,  45720 },
-  { 0x00003207,  49500 },
-  { 0x00002187,  50000 },
-  { 0x00004286,  56250 },
-  { 0x000010E5,  60065 },
-  { 0x00004214,  65000 },
-  { 0x00001105,  68179 },
-  { 0x000031E4,  74250 },
-  { 0x00003183,  75000 },
-  { 0x00004284,  78750 },
-  { 0x00001104,  81600 },
-  { 0x00006363,  94500 },
-  { 0x00005303,  97520 },
-  { 0x00002183, 100187 },
-  { 0x00002122, 101420 },
-  { 0x00001081, 108000 },
-  { 0x00006201, 113310 },
-  { 0x00000041, 119650 },
-  { 0x000041A1, 129600 },
-  { 0x00002182, 133500 },
-  { 0x000041B1, 135000 },
-  { 0x00000051, 144000 },
-  { 0x000041E1, 148500 },
-  { 0x000062D1, 157500 },
-  { 0x000031A1, 162000 },
-  { 0x00000061, 169203 },
-  { 0x00004231, 172800 },
-  { 0x00002151, 175500 },
-  { 0x000052E1, 189000 },
-  { 0x00000071, 192000 },
-  { 0x00003201, 198000 },
-  { 0x00004291, 202500 },
-  { 0x00001101, 204750 },
-  { 0x00007481, 218250 },
-  { 0x00004170, 229500 },
-  { 0x00006210, 234000 },
-  { 0x00003140, 251182 },
-  { 0x00006250, 261000 },
-  { 0x000041C0, 278400 },
-  { 0x00005220, 280640 },
-  { 0x00000050, 288000 },
-  { 0x000041E0, 297000 },
-  { 0x00002130, 320207 }
-};
-
-
-static void lx_set_dotpll(u32 pllval)
-{
-	u32 dotpll_lo, dotpll_hi;
-	int i;
-
-	rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
-
-	if ((dotpll_lo & MSR_GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval))
-		return;
-
-	dotpll_hi = pllval;
-	dotpll_lo &= ~(MSR_GLCP_DOTPLL_BYPASS | MSR_GLCP_DOTPLL_HALFPIX);
-	dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
-
-	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
-
-	/* Wait 100us for the PLL to lock */
-
-	udelay(100);
-
-	/* Now, loop for the lock bit */
-
-	for (i = 0; i < 1000; i++) {
-		rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
-		if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
-			break;
-	}
-
-	/* Clear the reset bit */
-
-	dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
-	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
-}
-
-/* Set the clock based on the frequency specified by the current mode */
-
-static void lx_set_clock(struct fb_info *info)
-{
-	unsigned int diff, min, best = 0;
-	unsigned int freq, i;
-
-	freq = (unsigned int) (1000000000 / info->var.pixclock);
-
-	min = abs(pll_table[0].freq - freq);
-
-	for (i = 0; i < ARRAY_SIZE(pll_table); i++) {
-		diff = abs(pll_table[i].freq - freq);
-		if (diff < min) {
-			min = diff;
-			best = i;
-		}
-	}
-
-	lx_set_dotpll(pll_table[best].pllval & 0x00017FFF);
-}
-
-static void lx_graphics_disable(struct fb_info *info)
-{
-	struct lxfb_par *par = info->par;
-	unsigned int val, gcfg;
-
-	/* Note:  This assumes that the video is in a quitet state */
-
-	write_vp(par, VP_A1T, 0);
-	write_vp(par, VP_A2T, 0);
-	write_vp(par, VP_A3T, 0);
-
-	/* Turn off the VGA and video enable */
-	val = read_dc(par, DC_GENERAL_CFG) & ~(DC_GENERAL_CFG_VGAE |
-			DC_GENERAL_CFG_VIDE);
-
-	write_dc(par, DC_GENERAL_CFG, val);
-
-	val = read_vp(par, VP_VCFG) & ~VP_VCFG_VID_EN;
-	write_vp(par, VP_VCFG, val);
-
-	write_dc(par, DC_IRQ, DC_IRQ_MASK | DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK |
-			DC_IRQ_STATUS | DC_IRQ_VIP_VSYNC_IRQ_STATUS);
-
-	val = read_dc(par, DC_GENLK_CTL) & ~DC_GENLK_CTL_GENLK_EN;
-	write_dc(par, DC_GENLK_CTL, val);
-
-	val = read_dc(par, DC_CLR_KEY);
-	write_dc(par, DC_CLR_KEY, val & ~DC_CLR_KEY_CLR_KEY_EN);
-
-	/* turn off the panel */
-	write_fp(par, FP_PM, read_fp(par, FP_PM) & ~FP_PM_P);
-
-	val = read_vp(par, VP_MISC) | VP_MISC_DACPWRDN;
-	write_vp(par, VP_MISC, val);
-
-	/* Turn off the display */
-
-	val = read_vp(par, VP_DCFG);
-	write_vp(par, VP_DCFG, val & ~(VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN |
-			VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN));
-
-	gcfg = read_dc(par, DC_GENERAL_CFG);
-	gcfg &= ~(DC_GENERAL_CFG_CMPE | DC_GENERAL_CFG_DECE);
-	write_dc(par, DC_GENERAL_CFG, gcfg);
-
-	/* Turn off the TGEN */
-	val = read_dc(par, DC_DISPLAY_CFG);
-	val &= ~DC_DISPLAY_CFG_TGEN;
-	write_dc(par, DC_DISPLAY_CFG, val);
-
-	/* Wait 1000 usecs to ensure that the TGEN is clear */
-	udelay(1000);
-
-	/* Turn off the FIFO loader */
-
-	gcfg &= ~DC_GENERAL_CFG_DFLE;
-	write_dc(par, DC_GENERAL_CFG, gcfg);
-
-	/* Lastly, wait for the GP to go idle */
-
-	do {
-		val = read_gp(par, GP_BLT_STATUS);
-	} while ((val & GP_BLT_STATUS_PB) || !(val & GP_BLT_STATUS_CE));
-}
-
-static void lx_graphics_enable(struct fb_info *info)
-{
-	struct lxfb_par *par = info->par;
-	u32 temp, config;
-
-	/* Set the video request register */
-	write_vp(par, VP_VRR, 0);
-
-	/* Set up the polarities */
-
-	config = read_vp(par, VP_DCFG);
-
-	config &= ~(VP_DCFG_CRT_SYNC_SKW | VP_DCFG_PWR_SEQ_DELAY |
-			VP_DCFG_CRT_HSYNC_POL | VP_DCFG_CRT_VSYNC_POL);
-
-	config |= (VP_DCFG_CRT_SYNC_SKW_DEFAULT | VP_DCFG_PWR_SEQ_DELAY_DEFAULT
-			| VP_DCFG_GV_GAM);
-
-	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		config |= VP_DCFG_CRT_HSYNC_POL;
-
-	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		config |= VP_DCFG_CRT_VSYNC_POL;
-
-	if (par->output & OUTPUT_PANEL) {
-		u32 msrlo, msrhi;
-
-		write_fp(par, FP_PT1, 0);
-		temp = FP_PT2_SCRC;
-
-		if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-			temp |= FP_PT2_HSP;
-
-		if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-			temp |= FP_PT2_VSP;
-
-		write_fp(par, FP_PT2, temp);
-		write_fp(par, FP_DFC, FP_DFC_BC);
-
-		msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW;
-		msrhi = MSR_LX_MSR_PADSEL_TFT_SEL_HIGH;
-
-		wrmsr(MSR_LX_MSR_PADSEL, msrlo, msrhi);
-	}
-
-	if (par->output & OUTPUT_CRT) {
-		config |= VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN |
-				VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN;
-	}
-
-	write_vp(par, VP_DCFG, config);
-
-	/* Turn the CRT dacs back on */
-
-	if (par->output & OUTPUT_CRT) {
-		temp = read_vp(par, VP_MISC);
-		temp &= ~(VP_MISC_DACPWRDN | VP_MISC_APWRDN);
-		write_vp(par, VP_MISC, temp);
-	}
-
-	/* Turn the panel on (if it isn't already) */
-	if (par->output & OUTPUT_PANEL)
-		write_fp(par, FP_PM, read_fp(par, FP_PM) | FP_PM_P);
-}
-
-unsigned int lx_framebuffer_size(void)
-{
-	unsigned int val;
-
-	if (!cs5535_has_vsa2()) {
-		uint32_t hi, lo;
-
-		/* The number of pages is (PMAX - PMIN)+1 */
-		rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
-
-		/* PMAX */
-		val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
-		/* PMIN */
-		val -= (lo & 0x000fffff);
-		val += 1;
-
-		/* The page size is 4k */
-		return (val << 12);
-	}
-
-	/* The frame buffer size is reported by a VSM in VSA II */
-	/* Virtual Register Class    = 0x02                     */
-	/* VG_MEM_SIZE (1MB units)   = 0x00                     */
-
-	outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
-	outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
-
-	val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFE;
-	return (val << 20);
-}
-
-void lx_set_mode(struct fb_info *info)
-{
-	struct lxfb_par *par = info->par;
-	u64 msrval;
-
-	unsigned int max, dv, val, size;
-
-	unsigned int gcfg, dcfg;
-	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
-	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
-
-	/* Unlock the DC registers */
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-
-	lx_graphics_disable(info);
-
-	lx_set_clock(info);
-
-	/* Set output mode */
-
-	rdmsrl(MSR_LX_GLD_MSR_CONFIG, msrval);
-	msrval &= ~MSR_LX_GLD_MSR_CONFIG_FMT;
-
-	if (par->output & OUTPUT_PANEL) {
-		msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_FP;
-
-		if (par->output & OUTPUT_CRT)
-			msrval |= MSR_LX_GLD_MSR_CONFIG_FPC;
-		else
-			msrval &= ~MSR_LX_GLD_MSR_CONFIG_FPC;
-	} else
-		msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_CRT;
-
-	wrmsrl(MSR_LX_GLD_MSR_CONFIG, msrval);
-
-	/* Clear the various buffers */
-	/* FIXME:  Adjust for panning here */
-
-	write_dc(par, DC_FB_ST_OFFSET, 0);
-	write_dc(par, DC_CB_ST_OFFSET, 0);
-	write_dc(par, DC_CURS_ST_OFFSET, 0);
-
-	/* FIXME: Add support for interlacing */
-	/* FIXME: Add support for scaling */
-
-	val = read_dc(par, DC_GENLK_CTL);
-	val &= ~(DC_GENLK_CTL_ALPHA_FLICK_EN | DC_GENLK_CTL_FLICK_EN |
-			DC_GENLK_CTL_FLICK_SEL_MASK);
-
-	/* Default scaling params */
-
-	write_dc(par, DC_GFX_SCALE, (0x4000 << 16) | 0x4000);
-	write_dc(par, DC_IRQ_FILT_CTL, 0);
-	write_dc(par, DC_GENLK_CTL, val);
-
-	/* FIXME:  Support compression */
-
-	if (info->fix.line_length > 4096)
-		dv = DC_DV_CTL_DV_LINE_SIZE_8K;
-	else if (info->fix.line_length > 2048)
-		dv = DC_DV_CTL_DV_LINE_SIZE_4K;
-	else if (info->fix.line_length > 1024)
-		dv = DC_DV_CTL_DV_LINE_SIZE_2K;
-	else
-		dv = DC_DV_CTL_DV_LINE_SIZE_1K;
-
-	max = info->fix.line_length * info->var.yres;
-	max = (max + 0x3FF) & 0xFFFFFC00;
-
-	write_dc(par, DC_DV_TOP, max | DC_DV_TOP_DV_TOP_EN);
-
-	val = read_dc(par, DC_DV_CTL) & ~DC_DV_CTL_DV_LINE_SIZE;
-	write_dc(par, DC_DV_CTL, val | dv);
-
-	size = info->var.xres * (info->var.bits_per_pixel >> 3);
-
-	write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
-	write_dc(par, DC_LINE_SIZE, (size + 7) >> 3);
-
-	/* Set default watermark values */
-
-	rdmsrl(MSR_LX_SPARE_MSR, msrval);
-
-	msrval &= ~(MSR_LX_SPARE_MSR_DIS_CFIFO_HGO
-			| MSR_LX_SPARE_MSR_VFIFO_ARB_SEL
-			| MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M
-			| MSR_LX_SPARE_MSR_WM_LPEN_OVRD);
-	msrval |= MSR_LX_SPARE_MSR_DIS_VIFO_WM |
-			MSR_LX_SPARE_MSR_DIS_INIT_V_PRI;
-	wrmsrl(MSR_LX_SPARE_MSR, msrval);
-
-	gcfg = DC_GENERAL_CFG_DFLE;   /* Display fifo enable */
-	gcfg |= (0x6 << DC_GENERAL_CFG_DFHPSL_SHIFT) | /* default priority */
-			(0xb << DC_GENERAL_CFG_DFHPEL_SHIFT);
-	gcfg |= DC_GENERAL_CFG_FDTY;  /* Set the frame dirty mode */
-
-	dcfg  = DC_DISPLAY_CFG_VDEN;  /* Enable video data */
-	dcfg |= DC_DISPLAY_CFG_GDEN;  /* Enable graphics */
-	dcfg |= DC_DISPLAY_CFG_TGEN;  /* Turn on the timing generator */
-	dcfg |= DC_DISPLAY_CFG_TRUP;  /* Update timings immediately */
-	dcfg |= DC_DISPLAY_CFG_PALB;  /* Palette bypass in > 8 bpp modes */
-	dcfg |= DC_DISPLAY_CFG_VISL;
-	dcfg |= DC_DISPLAY_CFG_DCEN;  /* Always center the display */
-
-	/* Set the current BPP mode */
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
-		break;
-
-	case 16:
-		dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
-		break;
-
-	case 32:
-	case 24:
-		dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
-		break;
-	}
-
-	/* Now - set up the timings */
-
-	hactive = info->var.xres;
-	hblankstart = hactive;
-	hsyncstart = hblankstart + info->var.right_margin;
-	hsyncend =  hsyncstart + info->var.hsync_len;
-	hblankend = hsyncend + info->var.left_margin;
-	htotal = hblankend;
-
-	vactive = info->var.yres;
-	vblankstart = vactive;
-	vsyncstart = vblankstart + info->var.lower_margin;
-	vsyncend =  vsyncstart + info->var.vsync_len;
-	vblankend = vsyncend + info->var.upper_margin;
-	vtotal = vblankend;
-
-	write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) | ((htotal - 1) << 16));
-	write_dc(par, DC_H_BLANK_TIMING,
-			(hblankstart - 1) | ((hblankend - 1) << 16));
-	write_dc(par, DC_H_SYNC_TIMING,
-			(hsyncstart - 1) | ((hsyncend - 1) << 16));
-
-	write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) | ((vtotal - 1) << 16));
-	write_dc(par, DC_V_BLANK_TIMING,
-			(vblankstart - 1) | ((vblankend - 1) << 16));
-	write_dc(par, DC_V_SYNC_TIMING,
-			(vsyncstart - 1) | ((vsyncend - 1) << 16));
-
-	write_dc(par, DC_FB_ACTIVE,
-			(info->var.xres - 1) << 16 | (info->var.yres - 1));
-
-	/* And re-enable the graphics output */
-	lx_graphics_enable(info);
-
-	/* Write the two main configuration registers */
-	write_dc(par, DC_DISPLAY_CFG, dcfg);
-	write_dc(par, DC_ARB_CFG, 0);
-	write_dc(par, DC_GENERAL_CFG, gcfg);
-
-	/* Lock the DC registers */
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
-}
-
-void lx_set_palette_reg(struct fb_info *info, unsigned regno,
-			unsigned red, unsigned green, unsigned blue)
-{
-	struct lxfb_par *par = info->par;
-	int val;
-
-	/* Hardware palette is in RGB 8-8-8 format. */
-
-	val  = (red   << 8) & 0xff0000;
-	val |= (green)      & 0x00ff00;
-	val |= (blue  >> 8) & 0x0000ff;
-
-	write_dc(par, DC_PAL_ADDRESS, regno);
-	write_dc(par, DC_PAL_DATA, val);
-}
-
-int lx_blank_display(struct fb_info *info, int blank_mode)
-{
-	struct lxfb_par *par = info->par;
-	u32 dcfg, misc, fp_pm;
-	int blank, hsync, vsync;
-
-	/* CRT power saving modes. */
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		blank = 0; hsync = 1; vsync = 1;
-		break;
-	case FB_BLANK_NORMAL:
-		blank = 1; hsync = 1; vsync = 1;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		blank = 1; hsync = 1; vsync = 0;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		blank = 1; hsync = 0; vsync = 1;
-		break;
-	case FB_BLANK_POWERDOWN:
-		blank = 1; hsync = 0; vsync = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	dcfg = read_vp(par, VP_DCFG);
-	dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
-			VP_DCFG_CRT_EN);
-	if (!blank)
-		dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN;
-	if (hsync)
-		dcfg |= VP_DCFG_HSYNC_EN;
-	if (vsync)
-		dcfg |= VP_DCFG_VSYNC_EN;
-
-	write_vp(par, VP_DCFG, dcfg);
-
-	misc = read_vp(par, VP_MISC);
-
-	if (vsync && hsync)
-		misc &= ~VP_MISC_DACPWRDN;
-	else
-		misc |= VP_MISC_DACPWRDN;
-
-	write_vp(par, VP_MISC, misc);
-
-	/* Power on/off flat panel */
-
-	if (par->output & OUTPUT_PANEL) {
-		fp_pm = read_fp(par, FP_PM);
-		if (blank_mode == FB_BLANK_POWERDOWN)
-			fp_pm &= ~FP_PM_P;
-		else
-			fp_pm |= FP_PM_P;
-		write_fp(par, FP_PM, fp_pm);
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-static void lx_save_regs(struct lxfb_par *par)
-{
-	uint32_t filt;
-	int i;
-
-	/* wait for the BLT engine to stop being busy */
-	do {
-		i = read_gp(par, GP_BLT_STATUS);
-	} while ((i & GP_BLT_STATUS_PB) || !(i & GP_BLT_STATUS_CE));
-
-	/* save MSRs */
-	rdmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);
-	rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
-	rdmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);
-	rdmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);
-
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-
-	/* save registers */
-	memcpy(par->gp, par->gp_regs, sizeof(par->gp));
-	memcpy(par->dc, par->dc_regs, sizeof(par->dc));
-	memcpy(par->vp, par->vp_regs, sizeof(par->vp));
-	memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp));
-
-	/* save the display controller palette */
-	write_dc(par, DC_PAL_ADDRESS, 0);
-	for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
-		par->dc_pal[i] = read_dc(par, DC_PAL_DATA);
-
-	/* save the video processor palette */
-	write_vp(par, VP_PAR, 0);
-	for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
-		par->vp_pal[i] = read_vp(par, VP_PDR);
-
-	/* save the horizontal filter coefficients */
-	filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
-	for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
-		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
-		par->hcoeff[i] = read_dc(par, DC_FILT_COEFF1);
-		par->hcoeff[i + 1] = read_dc(par, DC_FILT_COEFF2);
-	}
-
-	/* save the vertical filter coefficients */
-	filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;
-	for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
-		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
-		par->vcoeff[i] = read_dc(par, DC_FILT_COEFF1);
-	}
-
-	/* save video coeff ram */
-	memcpy(par->vp_coeff, par->vp_regs + VP_VCR, sizeof(par->vp_coeff));
-}
-
-static void lx_restore_gfx_proc(struct lxfb_par *par)
-{
-	int i;
-
-	/* a bunch of registers require GP_RASTER_MODE to be set first */
-	write_gp(par, GP_RASTER_MODE, par->gp[GP_RASTER_MODE]);
-
-	for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
-		switch (i) {
-		case GP_RASTER_MODE:
-		case GP_VECTOR_MODE:
-		case GP_BLT_MODE:
-		case GP_BLT_STATUS:
-		case GP_HST_SRC:
-			/* FIXME: restore LUT data */
-		case GP_LUT_INDEX:
-		case GP_LUT_DATA:
-			/* don't restore these registers */
-			break;
-
-		default:
-			write_gp(par, i, par->gp[i]);
-		}
-	}
-}
-
-static void lx_restore_display_ctlr(struct lxfb_par *par)
-{
-	uint32_t filt;
-	int i;
-
-	wrmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);
-
-	for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
-		switch (i) {
-		case DC_UNLOCK:
-			/* unlock the DC; runs first */
-			write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-			break;
-
-		case DC_GENERAL_CFG:
-		case DC_DISPLAY_CFG:
-			/* disable all while restoring */
-			write_dc(par, i, 0);
-			break;
-
-		case DC_DV_CTL:
-			/* set all ram to dirty */
-			write_dc(par, i, par->dc[i] | DC_DV_CTL_CLEAR_DV_RAM);
-
-		case DC_RSVD_1:
-		case DC_RSVD_2:
-		case DC_RSVD_3:
-		case DC_LINE_CNT:
-		case DC_PAL_ADDRESS:
-		case DC_PAL_DATA:
-		case DC_DFIFO_DIAG:
-		case DC_CFIFO_DIAG:
-		case DC_FILT_COEFF1:
-		case DC_FILT_COEFF2:
-		case DC_RSVD_4:
-		case DC_RSVD_5:
-			/* don't restore these registers */
-			break;
-
-		default:
-			write_dc(par, i, par->dc[i]);
-		}
-	}
-
-	/* restore the palette */
-	write_dc(par, DC_PAL_ADDRESS, 0);
-	for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
-		write_dc(par, DC_PAL_DATA, par->dc_pal[i]);
-
-	/* restore the horizontal filter coefficients */
-	filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
-	for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
-		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
-		write_dc(par, DC_FILT_COEFF1, par->hcoeff[i]);
-		write_dc(par, DC_FILT_COEFF2, par->hcoeff[i + 1]);
-	}
-
-	/* restore the vertical filter coefficients */
-	filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;
-	for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
-		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
-		write_dc(par, DC_FILT_COEFF1, par->vcoeff[i]);
-	}
-}
-
-static void lx_restore_video_proc(struct lxfb_par *par)
-{
-	int i;
-
-	wrmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);
-	wrmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);
-
-	for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
-		switch (i) {
-		case VP_VCFG:
-		case VP_DCFG:
-		case VP_PAR:
-		case VP_PDR:
-		case VP_CCS:
-		case VP_RSVD_0:
-		/* case VP_VDC: */ /* why should this not be restored? */
-		case VP_RSVD_1:
-		case VP_CRC32:
-			/* don't restore these registers */
-			break;
-
-		default:
-			write_vp(par, i, par->vp[i]);
-		}
-	}
-
-	/* restore video processor palette */
-	write_vp(par, VP_PAR, 0);
-	for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
-		write_vp(par, VP_PDR, par->vp_pal[i]);
-
-	/* restore video coeff ram */
-	memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff));
-}
-
-static void lx_restore_regs(struct lxfb_par *par)
-{
-	int i;
-
-	lx_set_dotpll((u32) (par->msr.dotpll >> 32));
-	lx_restore_gfx_proc(par);
-	lx_restore_display_ctlr(par);
-	lx_restore_video_proc(par);
-
-	/* Flat Panel */
-	for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
-		switch (i) {
-		case FP_PM:
-		case FP_RSVD_0:
-		case FP_RSVD_1:
-		case FP_RSVD_2:
-		case FP_RSVD_3:
-		case FP_RSVD_4:
-			/* don't restore these registers */
-			break;
-
-		default:
-			write_fp(par, i, par->fp[i]);
-		}
-	}
-
-	/* control the panel */
-	if (par->fp[FP_PM] & FP_PM_P) {
-		/* power on the panel if not already power{ed,ing} on */
-		if (!(read_fp(par, FP_PM) &
-				(FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
-			write_fp(par, FP_PM, par->fp[FP_PM]);
-	} else {
-		/* power down the panel if not already power{ed,ing} down */
-		if (!(read_fp(par, FP_PM) &
-				(FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
-			write_fp(par, FP_PM, par->fp[FP_PM]);
-	}
-
-	/* turn everything on */
-	write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
-	write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
-	write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
-	/* do this last; it will enable the FIFO load */
-	write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
-
-	/* lock the door behind us */
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
-}
-
-int lx_powerdown(struct fb_info *info)
-{
-	struct lxfb_par *par = info->par;
-
-	if (par->powered_down)
-		return 0;
-
-	lx_save_regs(par);
-	lx_graphics_disable(info);
-
-	par->powered_down = 1;
-	return 0;
-}
-
-int lx_powerup(struct fb_info *info)
-{
-	struct lxfb_par *par = info->par;
-
-	if (!par->powered_down)
-		return 0;
-
-	lx_restore_regs(par);
-
-	par->powered_down = 0;
-	return 0;
-}
-
-#endif
diff --git a/drivers/video/geode/suspend_gx.c b/drivers/video/geode/suspend_gx.c
deleted file mode 100644
index 1bb043d70c64..000000000000
--- a/drivers/video/geode/suspend_gx.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- *   Copyright (C) 2007 Advanced Micro Devices, Inc.
- *   Copyright (C) 2008 Andres Salomon <dilinger@debian.org>
- *
- *   This program is free software; you can redistribute it and/or modify it
- *   under the terms of the GNU General Public License as published by the
- *   Free Software Foundation; either version 2 of the License, or (at your
- *   option) any later version.
- */
-#include <linux/fb.h>
-#include <asm/io.h>
-#include <asm/msr.h>
-#include <linux/cs5535.h>
-#include <asm/delay.h>
-
-#include "gxfb.h"
-
-#ifdef CONFIG_PM
-
-static void gx_save_regs(struct gxfb_par *par)
-{
-	int i;
-
-	/* wait for the BLT engine to stop being busy */
-	do {
-		i = read_gp(par, GP_BLT_STATUS);
-	} while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY));
-
-	/* save MSRs */
-	rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
-	rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
-
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-
-	/* save registers */
-	memcpy(par->gp, par->gp_regs, sizeof(par->gp));
-	memcpy(par->dc, par->dc_regs, sizeof(par->dc));
-	memcpy(par->vp, par->vid_regs, sizeof(par->vp));
-	memcpy(par->fp, par->vid_regs + VP_FP_START, sizeof(par->fp));
-
-	/* save the palette */
-	write_dc(par, DC_PAL_ADDRESS, 0);
-	for (i = 0; i < ARRAY_SIZE(par->pal); i++)
-		par->pal[i] = read_dc(par, DC_PAL_DATA);
-}
-
-static void gx_set_dotpll(uint32_t dotpll_hi)
-{
-	uint32_t dotpll_lo;
-	int i;
-
-	rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
-	dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
-	dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS;
-	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
-
-	/* wait for the PLL to lock */
-	for (i = 0; i < 200; i++) {
-		rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
-		if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
-			break;
-		udelay(1);
-	}
-
-	/* PLL set, unlock */
-	dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
-	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
-}
-
-static void gx_restore_gfx_proc(struct gxfb_par *par)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
-		switch (i) {
-		case GP_VECTOR_MODE:
-		case GP_BLT_MODE:
-		case GP_BLT_STATUS:
-		case GP_HST_SRC:
-			/* don't restore these registers */
-			break;
-		default:
-			write_gp(par, i, par->gp[i]);
-		}
-	}
-}
-
-static void gx_restore_display_ctlr(struct gxfb_par *par)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
-		switch (i) {
-		case DC_UNLOCK:
-			/* unlock the DC; runs first */
-			write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-			break;
-
-		case DC_GENERAL_CFG:
-			/* write without the enables */
-			write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE |
-					DC_GENERAL_CFG_ICNE |
-					DC_GENERAL_CFG_CURE |
-					DC_GENERAL_CFG_DFLE));
-			break;
-
-		case DC_DISPLAY_CFG:
-			/* write without the enables */
-			write_dc(par, i, par->dc[i] & ~(DC_DISPLAY_CFG_VDEN |
-					DC_DISPLAY_CFG_GDEN |
-					DC_DISPLAY_CFG_TGEN));
-			break;
-
-		case DC_RSVD_0:
-		case DC_RSVD_1:
-		case DC_RSVD_2:
-		case DC_RSVD_3:
-		case DC_RSVD_4:
-		case DC_LINE_CNT:
-		case DC_PAL_ADDRESS:
-		case DC_PAL_DATA:
-		case DC_DFIFO_DIAG:
-		case DC_CFIFO_DIAG:
-		case DC_RSVD_5:
-			/* don't restore these registers */
-			break;
-		default:
-			write_dc(par, i, par->dc[i]);
-		}
-	}
-
-	/* restore the palette */
-	write_dc(par, DC_PAL_ADDRESS, 0);
-	for (i = 0; i < ARRAY_SIZE(par->pal); i++)
-		write_dc(par, DC_PAL_DATA, par->pal[i]);
-}
-
-static void gx_restore_video_proc(struct gxfb_par *par)
-{
-	int i;
-
-	wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
-
-	for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
-		switch (i) {
-		case VP_VCFG:
-			/* don't enable video yet */
-			write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);
-			break;
-
-		case VP_DCFG:
-			/* don't enable CRT yet */
-			write_vp(par, i, par->vp[i] &
-					~(VP_DCFG_DAC_BL_EN | VP_DCFG_VSYNC_EN |
-					VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
-			break;
-
-		case VP_GAR:
-		case VP_GDR:
-		case VP_RSVD_0:
-		case VP_RSVD_1:
-		case VP_RSVD_2:
-		case VP_RSVD_3:
-		case VP_CRC32:
-		case VP_AWT:
-		case VP_VTM:
-			/* don't restore these registers */
-			break;
-		default:
-			write_vp(par, i, par->vp[i]);
-		}
-	}
-}
-
-static void gx_restore_regs(struct gxfb_par *par)
-{
-	int i;
-
-	gx_set_dotpll((uint32_t) (par->msr.dotpll >> 32));
-	gx_restore_gfx_proc(par);
-	gx_restore_display_ctlr(par);
-	gx_restore_video_proc(par);
-
-	/* Flat Panel */
-	for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
-		if (i != FP_PM && i != FP_RSVD_0)
-			write_fp(par, i, par->fp[i]);
-	}
-}
-
-static void gx_disable_graphics(struct gxfb_par *par)
-{
-	/* shut down the engine */
-	write_vp(par, VP_VCFG, par->vp[VP_VCFG] & ~VP_VCFG_VID_EN);
-	write_vp(par, VP_DCFG, par->vp[VP_DCFG] & ~(VP_DCFG_DAC_BL_EN |
-			VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
-
-	/* turn off the flat panel */
-	write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);
-
-
-	/* turn off display */
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
-	write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG] &
-			~(DC_GENERAL_CFG_VIDE | DC_GENERAL_CFG_ICNE |
-			DC_GENERAL_CFG_CURE | DC_GENERAL_CFG_DFLE));
-	write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG] &
-			~(DC_DISPLAY_CFG_VDEN | DC_DISPLAY_CFG_GDEN |
-			DC_DISPLAY_CFG_TGEN));
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
-}
-
-static void gx_enable_graphics(struct gxfb_par *par)
-{
-	uint32_t fp;
-
-	fp = read_fp(par, FP_PM);
-	if (par->fp[FP_PM] & FP_PM_P) {
-		/* power on the panel if not already power{ed,ing} on */
-		if (!(fp & (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
-			write_fp(par, FP_PM, par->fp[FP_PM]);
-	} else {
-		/* power down the panel if not already power{ed,ing} down */
-		if (!(fp & (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
-			write_fp(par, FP_PM, par->fp[FP_PM]);
-	}
-
-	/* turn everything on */
-	write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
-	write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
-	write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
-	/* do this last; it will enable the FIFO load */
-	write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
-
-	/* lock the door behind us */
-	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
-}
-
-int gx_powerdown(struct fb_info *info)
-{
-	struct gxfb_par *par = info->par;
-
-	if (par->powered_down)
-		return 0;
-
-	gx_save_regs(par);
-	gx_disable_graphics(par);
-
-	par->powered_down = 1;
-	return 0;
-}
-
-int gx_powerup(struct fb_info *info)
-{
-	struct gxfb_par *par = info->par;
-
-	if (!par->powered_down)
-		return 0;
-
-	gx_restore_regs(par);
-	gx_enable_graphics(par);
-
-	par->powered_down  = 0;
-	return 0;
-}
-
-#endif
diff --git a/drivers/video/geode/video_cs5530.c b/drivers/video/geode/video_cs5530.c
deleted file mode 100644
index 649c3943d431..000000000000
--- a/drivers/video/geode/video_cs5530.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * drivers/video/geode/video_cs5530.c
- *   -- CS5530 video device
- *
- * Copyright (C) 2005 Arcom Control Systems Ltd.
- *
- * Based on AMD's original 2.4 driver:
- *   Copyright (C) 2004 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-
-#include "geodefb.h"
-#include "video_cs5530.h"
-
-/*
- * CS5530 PLL table. This maps pixclocks to the appropriate PLL register
- * value.
- */
-struct cs5530_pll_entry {
-	long pixclock; /* ps */
-	u32 pll_value;
-};
-
-static const struct cs5530_pll_entry cs5530_pll_table[] = {
-	{ 39721, 0x31C45801, }, /*  25.1750 MHz */
-	{ 35308, 0x20E36802, }, /*  28.3220 */
-	{ 31746, 0x33915801, }, /*  31.5000 */
-	{ 27777, 0x31EC4801, }, /*  36.0000 */
-	{ 26666, 0x21E22801, }, /*  37.5000 */
-	{ 25000, 0x33088801, }, /*  40.0000 */
-	{ 22271, 0x33E22801, }, /*  44.9000 */
-	{ 20202, 0x336C4801, }, /*  49.5000 */
-	{ 20000, 0x23088801, }, /*  50.0000 */
-	{ 19860, 0x23088801, }, /*  50.3500 */
-	{ 18518, 0x3708A801, }, /*  54.0000 */
-	{ 17777, 0x23E36802, }, /*  56.2500 */
-	{ 17733, 0x23E36802, }, /*  56.3916 */
-	{ 17653, 0x23E36802, }, /*  56.6444 */
-	{ 16949, 0x37C45801, }, /*  59.0000 */
-	{ 15873, 0x23EC4801, }, /*  63.0000 */
-	{ 15384, 0x37911801, }, /*  65.0000 */
-	{ 14814, 0x37963803, }, /*  67.5000 */
-	{ 14124, 0x37058803, }, /*  70.8000 */
-	{ 13888, 0x3710C805, }, /*  72.0000 */
-	{ 13333, 0x37E22801, }, /*  75.0000 */
-	{ 12698, 0x27915801, }, /*  78.7500 */
-	{ 12500, 0x37D8D802, }, /*  80.0000 */
-	{ 11135, 0x27588802, }, /*  89.8000 */
-	{ 10582, 0x27EC4802, }, /*  94.5000 */
-	{ 10101, 0x27AC6803, }, /*  99.0000 */
-	{ 10000, 0x27088801, }, /* 100.0000 */
-	{  9259, 0x2710C805, }, /* 108.0000 */
-	{  8888, 0x27E36802, }, /* 112.5000 */
-	{  7692, 0x27C58803, }, /* 130.0000 */
-	{  7407, 0x27316803, }, /* 135.0000 */
-	{  6349, 0x2F915801, }, /* 157.5000 */
-	{  6172, 0x2F08A801, }, /* 162.0000 */
-	{  5714, 0x2FB11802, }, /* 175.0000 */
-	{  5291, 0x2FEC4802, }, /* 189.0000 */
-	{  4950, 0x2F963803, }, /* 202.0000 */
-	{  4310, 0x2FB1B802, }, /* 232.0000 */
-};
-
-static void cs5530_set_dclk_frequency(struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-	int i;
-	u32 value;
-	long min, diff;
-
-	/* Search the table for the closest pixclock. */
-	value = cs5530_pll_table[0].pll_value;
-	min = cs5530_pll_table[0].pixclock - info->var.pixclock;
-	if (min < 0) min = -min;
-	for (i = 1; i < ARRAY_SIZE(cs5530_pll_table); i++) {
-		diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
-		if (diff < 0L) diff = -diff;
-		if (diff < min) {
-			min = diff;
-			value = cs5530_pll_table[i].pll_value;
-		}
-	}
-
-	writel(value, par->vid_regs + CS5530_DOT_CLK_CONFIG);
-	writel(value | 0x80000100, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* set reset and bypass */
-	udelay(500); /* wait for PLL to settle */
-	writel(value & 0x7FFFFFFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear reset */
-	writel(value & 0x7FFFFEFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear bypass */
-}
-
-static void cs5530_configure_display(struct fb_info *info)
-{
-	struct geodefb_par *par = info->par;
-	u32 dcfg;
-
-	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
-
-	/* Clear bits from existing mode. */
-	dcfg &= ~(CS5530_DCFG_CRT_SYNC_SKW_MASK | CS5530_DCFG_PWR_SEQ_DLY_MASK
-		  | CS5530_DCFG_CRT_HSYNC_POL   | CS5530_DCFG_CRT_VSYNC_POL
-		  | CS5530_DCFG_FP_PWR_EN       | CS5530_DCFG_FP_DATA_EN
-		  | CS5530_DCFG_DAC_PWR_EN      | CS5530_DCFG_VSYNC_EN
-		  | CS5530_DCFG_HSYNC_EN);
-
-	/* Set default sync skew and power sequence delays.  */
-	dcfg |= (CS5530_DCFG_CRT_SYNC_SKW_INIT | CS5530_DCFG_PWR_SEQ_DLY_INIT
-		 | CS5530_DCFG_GV_PAL_BYP);
-
-	/* Enable DACs, hsync and vsync for CRTs */
-	if (par->enable_crt) {
-		dcfg |= CS5530_DCFG_DAC_PWR_EN;
-		dcfg |= CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN;
-	}
-	/* Enable panel power and data if using a flat panel. */
-	if (par->panel_x > 0) {
-		dcfg |= CS5530_DCFG_FP_PWR_EN;
-		dcfg |= CS5530_DCFG_FP_DATA_EN;
-	}
-
-	/* Sync polarities. */
-	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		dcfg |= CS5530_DCFG_CRT_HSYNC_POL;
-	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		dcfg |= CS5530_DCFG_CRT_VSYNC_POL;
-
-	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
-}
-
-static int cs5530_blank_display(struct fb_info *info, int blank_mode)
-{
-	struct geodefb_par *par = info->par;
-	u32 dcfg;
-	int blank, hsync, vsync;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		blank = 0; hsync = 1; vsync = 1;
-		break;
-	case FB_BLANK_NORMAL:
-		blank = 1; hsync = 1; vsync = 1;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		blank = 1; hsync = 1; vsync = 0;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		blank = 1; hsync = 0; vsync = 1;
-		break;
-	case FB_BLANK_POWERDOWN:
-		blank = 1; hsync = 0; vsync = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
-
-	dcfg &= ~(CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN
-		  | CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN
-		  | CS5530_DCFG_FP_DATA_EN | CS5530_DCFG_FP_PWR_EN);
-
-	if (par->enable_crt) {
-		if (!blank)
-			dcfg |= CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN;
-		if (hsync)
-			dcfg |= CS5530_DCFG_HSYNC_EN;
-		if (vsync)
-			dcfg |= CS5530_DCFG_VSYNC_EN;
-	}
-	if (par->panel_x > 0) {
-		if (!blank)
-			dcfg |= CS5530_DCFG_FP_DATA_EN;
-		if (hsync && vsync)
-			dcfg |= CS5530_DCFG_FP_PWR_EN;
-	}
-
-	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
-
-	return 0;
-}
-
-struct geode_vid_ops cs5530_vid_ops = {
-	.set_dclk          = cs5530_set_dclk_frequency,
-	.configure_display = cs5530_configure_display,
-	.blank_display     = cs5530_blank_display,
-};
diff --git a/drivers/video/geode/video_cs5530.h b/drivers/video/geode/video_cs5530.h
deleted file mode 100644
index 56cecca7f1ce..000000000000
--- a/drivers/video/geode/video_cs5530.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * drivers/video/geode/video_cs5530.h
- *   -- CS5530 video device
- *
- * Copyright (C) 2005 Arcom Control Systems Ltd.
- *
- * Based on AMD's original 2.4 driver:
- *   Copyright (C) 2004 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __VIDEO_CS5530_H__
-#define __VIDEO_CS5530_H__
-
-extern struct geode_vid_ops cs5530_vid_ops;
-
-/* CS5530 Video device registers */
-
-#define CS5530_VIDEO_CONFIG	0x0000
-#  define CS5530_VCFG_VID_EN			0x00000001
-#  define CS5530_VCFG_VID_REG_UPDATE		0x00000002
-#  define CS5530_VCFG_VID_INP_FORMAT		0x0000000C
-#  define CS5530_VCFG_8_BIT_4_2_0		0x00000004
-#  define CS5530_VCFG_16_BIT_4_2_0		0x00000008
-#  define CS5530_VCFG_GV_SEL			0x00000010
-#  define CS5530_VCFG_CSC_BYPASS		0x00000020
-#  define CS5530_VCFG_X_FILTER_EN		0x00000040
-#  define CS5530_VCFG_Y_FILTER_EN		0x00000080
-#  define CS5530_VCFG_LINE_SIZE_LOWER_MASK	0x0000FF00
-#  define CS5530_VCFG_INIT_READ_MASK		0x01FF0000
-#  define CS5530_VCFG_EARLY_VID_RDY		0x02000000
-#  define CS5530_VCFG_LINE_SIZE_UPPER		0x08000000
-#  define CS5530_VCFG_4_2_0_MODE		0x10000000
-#  define CS5530_VCFG_16_BIT_EN			0x20000000
-#  define CS5530_VCFG_HIGH_SPD_INT		0x40000000
-
-#define CS5530_DISPLAY_CONFIG	0x0004
-#  define CS5530_DCFG_DIS_EN			0x00000001
-#  define CS5530_DCFG_HSYNC_EN			0x00000002
-#  define CS5530_DCFG_VSYNC_EN			0x00000004
-#  define CS5530_DCFG_DAC_BL_EN			0x00000008
-#  define CS5530_DCFG_DAC_PWR_EN		0x00000020
-#  define CS5530_DCFG_FP_PWR_EN			0x00000040
-#  define CS5530_DCFG_FP_DATA_EN		0x00000080
-#  define CS5530_DCFG_CRT_HSYNC_POL		0x00000100
-#  define CS5530_DCFG_CRT_VSYNC_POL		0x00000200
-#  define CS5530_DCFG_FP_HSYNC_POL		0x00000400
-#  define CS5530_DCFG_FP_VSYNC_POL		0x00000800
-#  define CS5530_DCFG_XGA_FP			0x00001000
-#  define CS5530_DCFG_FP_DITH_EN		0x00002000
-#  define CS5530_DCFG_CRT_SYNC_SKW_MASK		0x0001C000
-#  define CS5530_DCFG_CRT_SYNC_SKW_INIT		0x00010000
-#  define CS5530_DCFG_PWR_SEQ_DLY_MASK		0x000E0000
-#  define CS5530_DCFG_PWR_SEQ_DLY_INIT		0x00080000
-#  define CS5530_DCFG_VG_CK			0x00100000
-#  define CS5530_DCFG_GV_PAL_BYP		0x00200000
-#  define CS5530_DCFG_DDC_SCL			0x00400000
-#  define CS5530_DCFG_DDC_SDA			0x00800000
-#  define CS5530_DCFG_DDC_OE			0x01000000
-#  define CS5530_DCFG_16_BIT_EN			0x02000000
-
-#define CS5530_VIDEO_X_POS	0x0008
-#define CS5530_VIDEO_Y_POS	0x000C
-#define CS5530_VIDEO_SCALE	0x0010
-#define CS5530_VIDEO_COLOR_KEY	0x0014
-#define CS5530_VIDEO_COLOR_MASK 0x0018
-#define CS5530_PALETTE_ADDRESS	0x001C
-#define CS5530_PALETTE_DATA	0x0020
-#define CS5530_DOT_CLK_CONFIG	0x0024
-#define CS5530_CRCSIG_TFT_TV	0x0028
-
-#endif /* !__VIDEO_CS5530_H__ */
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
deleted file mode 100644
index 6082f653c68a..000000000000
--- a/drivers/video/geode/video_gx.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Geode GX video processor device.
- *
- *   Copyright (C) 2006 Arcom Control Systems Ltd.
- *
- *   Portions from AMD's original 2.4 driver:
- *     Copyright (C) 2004 Advanced Micro Devices, Inc.
- *
- *   This program is free software; you can redistribute it and/or modify it
- *   under the terms of the GNU General Public License as published by the
- *   Free Software Foundation; either version 2 of the License, or (at your
- *   option) any later version.
- */
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/msr.h>
-#include <linux/cs5535.h>
-
-#include "gxfb.h"
-
-
-/*
- * Tables of register settings for various DOTCLKs.
- */
-struct gx_pll_entry {
-	long pixclock; /* ps */
-	u32 sys_rstpll_bits;
-	u32 dotpll_value;
-};
-
-#define POSTDIV3 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
-#define PREMULT2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPREMULT2)
-#define PREDIV2  ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
-
-static const struct gx_pll_entry gx_pll_table_48MHz[] = {
-	{ 40123, POSTDIV3,	    0x00000BF2 },	/*  24.9230 */
-	{ 39721, 0,		    0x00000037 },	/*  25.1750 */
-	{ 35308, POSTDIV3|PREMULT2, 0x00000B1A },	/*  28.3220 */
-	{ 31746, POSTDIV3,	    0x000002D2 },	/*  31.5000 */
-	{ 27777, POSTDIV3|PREMULT2, 0x00000FE2 },	/*  36.0000 */
-	{ 26666, POSTDIV3,	    0x0000057A },	/*  37.5000 */
-	{ 25000, POSTDIV3,	    0x0000030A },	/*  40.0000 */
-	{ 22271, 0,		    0x00000063 },	/*  44.9000 */
-	{ 20202, 0,		    0x0000054B },	/*  49.5000 */
-	{ 20000, 0,		    0x0000026E },	/*  50.0000 */
-	{ 19860, PREMULT2,	    0x00000037 },	/*  50.3500 */
-	{ 18518, POSTDIV3|PREMULT2, 0x00000B0D },	/*  54.0000 */
-	{ 17777, 0,		    0x00000577 },	/*  56.2500 */
-	{ 17733, 0,		    0x000007F7 },	/*  56.3916 */
-	{ 17653, 0,		    0x0000057B },	/*  56.6444 */
-	{ 16949, PREMULT2,	    0x00000707 },	/*  59.0000 */
-	{ 15873, POSTDIV3|PREMULT2, 0x00000B39 },	/*  63.0000 */
-	{ 15384, POSTDIV3|PREMULT2, 0x00000B45 },	/*  65.0000 */
-	{ 14814, POSTDIV3|PREMULT2, 0x00000FC1 },	/*  67.5000 */
-	{ 14124, POSTDIV3,	    0x00000561 },	/*  70.8000 */
-	{ 13888, POSTDIV3,	    0x000007E1 },	/*  72.0000 */
-	{ 13426, PREMULT2,	    0x00000F4A },	/*  74.4810 */
-	{ 13333, 0,		    0x00000052 },	/*  75.0000 */
-	{ 12698, 0,		    0x00000056 },	/*  78.7500 */
-	{ 12500, POSTDIV3|PREMULT2, 0x00000709 },	/*  80.0000 */
-	{ 11135, PREMULT2,	    0x00000262 },	/*  89.8000 */
-	{ 10582, 0,		    0x000002D2 },	/*  94.5000 */
-	{ 10101, PREMULT2,	    0x00000B4A },	/*  99.0000 */
-	{ 10000, PREMULT2,	    0x00000036 },	/* 100.0000 */
-	{  9259, 0,		    0x000007E2 },	/* 108.0000 */
-	{  8888, 0,		    0x000007F6 },	/* 112.5000 */
-	{  7692, POSTDIV3|PREMULT2, 0x00000FB0 },	/* 130.0000 */
-	{  7407, POSTDIV3|PREMULT2, 0x00000B50 },	/* 135.0000 */
-	{  6349, 0,		    0x00000055 },	/* 157.5000 */
-	{  6172, 0,		    0x000009C1 },	/* 162.0000 */
-	{  5787, PREMULT2,	    0x0000002D },	/* 172.798  */
-	{  5698, 0,		    0x000002C1 },	/* 175.5000 */
-	{  5291, 0,		    0x000002D1 },	/* 189.0000 */
-	{  4938, 0,		    0x00000551 },	/* 202.5000 */
-	{  4357, 0,		    0x0000057D },	/* 229.5000 */
-};
-
-static const struct gx_pll_entry gx_pll_table_14MHz[] = {
-	{ 39721, 0, 0x00000037 },	/*  25.1750 */
-	{ 35308, 0, 0x00000B7B },	/*  28.3220 */
-	{ 31746, 0, 0x000004D3 },	/*  31.5000 */
-	{ 27777, 0, 0x00000BE3 },	/*  36.0000 */
-	{ 26666, 0, 0x0000074F },	/*  37.5000 */
-	{ 25000, 0, 0x0000050B },	/*  40.0000 */
-	{ 22271, 0, 0x00000063 },	/*  44.9000 */
-	{ 20202, 0, 0x0000054B },	/*  49.5000 */
-	{ 20000, 0, 0x0000026E },	/*  50.0000 */
-	{ 19860, 0, 0x000007C3 },	/*  50.3500 */
-	{ 18518, 0, 0x000007E3 },	/*  54.0000 */
-	{ 17777, 0, 0x00000577 },	/*  56.2500 */
-	{ 17733, 0, 0x000002FB },	/*  56.3916 */
-	{ 17653, 0, 0x0000057B },	/*  56.6444 */
-	{ 16949, 0, 0x0000058B },	/*  59.0000 */
-	{ 15873, 0, 0x0000095E },	/*  63.0000 */
-	{ 15384, 0, 0x0000096A },	/*  65.0000 */
-	{ 14814, 0, 0x00000BC2 },	/*  67.5000 */
-	{ 14124, 0, 0x0000098A },	/*  70.8000 */
-	{ 13888, 0, 0x00000BE2 },	/*  72.0000 */
-	{ 13333, 0, 0x00000052 },	/*  75.0000 */
-	{ 12698, 0, 0x00000056 },	/*  78.7500 */
-	{ 12500, 0, 0x0000050A },	/*  80.0000 */
-	{ 11135, 0, 0x0000078E },	/*  89.8000 */
-	{ 10582, 0, 0x000002D2 },	/*  94.5000 */
-	{ 10101, 0, 0x000011F6 },	/*  99.0000 */
-	{ 10000, 0, 0x0000054E },	/* 100.0000 */
-	{  9259, 0, 0x000007E2 },	/* 108.0000 */
-	{  8888, 0, 0x000002FA },	/* 112.5000 */
-	{  7692, 0, 0x00000BB1 },	/* 130.0000 */
-	{  7407, 0, 0x00000975 },	/* 135.0000 */
-	{  6349, 0, 0x00000055 },	/* 157.5000 */
-	{  6172, 0, 0x000009C1 },	/* 162.0000 */
-	{  5698, 0, 0x000002C1 },	/* 175.5000 */
-	{  5291, 0, 0x00000539 },	/* 189.0000 */
-	{  4938, 0, 0x00000551 },	/* 202.5000 */
-	{  4357, 0, 0x0000057D },	/* 229.5000 */
-};
-
-void gx_set_dclk_frequency(struct fb_info *info)
-{
-	const struct gx_pll_entry *pll_table;
-	int pll_table_len;
-	int i, best_i;
-	long min, diff;
-	u64 dotpll, sys_rstpll;
-	int timeout = 1000;
-
-	/* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
-	if (cpu_data(0).x86_mask == 1) {
-		pll_table = gx_pll_table_14MHz;
-		pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
-	} else {
-		pll_table = gx_pll_table_48MHz;
-		pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
-	}
-
-	/* Search the table for the closest pixclock. */
-	best_i = 0;
-	min = abs(pll_table[0].pixclock - info->var.pixclock);
-	for (i = 1; i < pll_table_len; i++) {
-		diff = abs(pll_table[i].pixclock - info->var.pixclock);
-		if (diff < min) {
-			min = diff;
-			best_i = i;
-		}
-	}
-
-	rdmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
-	rdmsrl(MSR_GLCP_DOTPLL, dotpll);
-
-	/* Program new M, N and P. */
-	dotpll &= 0x00000000ffffffffull;
-	dotpll |= (u64)pll_table[best_i].dotpll_value << 32;
-	dotpll |= MSR_GLCP_DOTPLL_DOTRESET;
-	dotpll &= ~MSR_GLCP_DOTPLL_BYPASS;
-
-	wrmsrl(MSR_GLCP_DOTPLL, dotpll);
-
-	/* Program dividers. */
-	sys_rstpll &= ~( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2
-			 | MSR_GLCP_SYS_RSTPLL_DOTPREMULT2
-			 | MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 );
-	sys_rstpll |= pll_table[best_i].sys_rstpll_bits;
-
-	wrmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
-
-	/* Clear reset bit to start PLL. */
-	dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET);
-	wrmsrl(MSR_GLCP_DOTPLL, dotpll);
-
-	/* Wait for LOCK bit. */
-	do {
-		rdmsrl(MSR_GLCP_DOTPLL, dotpll);
-	} while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
-}
-
-static void
-gx_configure_tft(struct fb_info *info)
-{
-	struct gxfb_par *par = info->par;
-	unsigned long val;
-	unsigned long fp;
-
-	/* Set up the DF pad select MSR */
-
-	rdmsrl(MSR_GX_MSR_PADSEL, val);
-	val &= ~MSR_GX_MSR_PADSEL_MASK;
-	val |= MSR_GX_MSR_PADSEL_TFT;
-	wrmsrl(MSR_GX_MSR_PADSEL, val);
-
-	/* Turn off the panel */
-
-	fp = read_fp(par, FP_PM);
-	fp &= ~FP_PM_P;
-	write_fp(par, FP_PM, fp);
-
-	/* Set timing 1 */
-
-	fp = read_fp(par, FP_PT1);
-	fp &= FP_PT1_VSIZE_MASK;
-	fp |= info->var.yres << FP_PT1_VSIZE_SHIFT;
-	write_fp(par, FP_PT1, fp);
-
-	/* Timing 2 */
-	/* Set bits that are always on for TFT */
-
-	fp = 0x0F100000;
-
-	/* Configure sync polarity */
-
-	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-		fp |= FP_PT2_VSP;
-
-	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-		fp |= FP_PT2_HSP;
-
-	write_fp(par, FP_PT2, fp);
-
-	/*  Set the dither control */
-	write_fp(par, FP_DFC, FP_DFC_NFI);
-
-	/* Enable the FP data and power (in case the BIOS didn't) */
-
-	fp = read_vp(par, VP_DCFG);
-	fp |= VP_DCFG_FP_PWR_EN | VP_DCFG_FP_DATA_EN;
-	write_vp(par, VP_DCFG, fp);
-
-	/* Unblank the panel */
-
-	fp = read_fp(par, FP_PM);
-	fp |= FP_PM_P;
-	write_fp(par, FP_PM, fp);
-}
-
-void gx_configure_display(struct fb_info *info)
-{
-	struct gxfb_par *par = info->par;
-	u32 dcfg, misc;
-
-	/* Write the display configuration */
-	dcfg = read_vp(par, VP_DCFG);
-
-	/* Disable hsync and vsync */
-	dcfg &= ~(VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN);
-	write_vp(par, VP_DCFG, dcfg);
-
-	/* Clear bits from existing mode. */
-	dcfg &= ~(VP_DCFG_CRT_SYNC_SKW
-		  | VP_DCFG_CRT_HSYNC_POL   | VP_DCFG_CRT_VSYNC_POL
-		  | VP_DCFG_VSYNC_EN        | VP_DCFG_HSYNC_EN);
-
-	/* Set default sync skew.  */
-	dcfg |= VP_DCFG_CRT_SYNC_SKW_DEFAULT;
-
-	/* Enable hsync and vsync. */
-	dcfg |= VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN;
-
-	misc = read_vp(par, VP_MISC);
-
-	/* Disable gamma correction */
-	misc |= VP_MISC_GAM_EN;
-
-	if (par->enable_crt) {
-
-		/* Power up the CRT DACs */
-		misc &= ~(VP_MISC_APWRDN | VP_MISC_DACPWRDN);
-		write_vp(par, VP_MISC, misc);
-
-		/* Only change the sync polarities if we are running
-		 * in CRT mode.  The FP polarities will be handled in
-		 * gxfb_configure_tft */
-		if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-			dcfg |= VP_DCFG_CRT_HSYNC_POL;
-		if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-			dcfg |= VP_DCFG_CRT_VSYNC_POL;
-	} else {
-		/* Power down the CRT DACs if in FP mode */
-		misc |= (VP_MISC_APWRDN | VP_MISC_DACPWRDN);
-		write_vp(par, VP_MISC, misc);
-	}
-
-	/* Enable the display logic */
-	/* Set up the DACS to blank normally */
-
-	dcfg |= VP_DCFG_CRT_EN | VP_DCFG_DAC_BL_EN;
-
-	/* Enable the external DAC VREF? */
-
-	write_vp(par, VP_DCFG, dcfg);
-
-	/* Set up the flat panel (if it is enabled) */
-
-	if (par->enable_crt == 0)
-		gx_configure_tft(info);
-}
-
-int gx_blank_display(struct fb_info *info, int blank_mode)
-{
-	struct gxfb_par *par = info->par;
-	u32 dcfg, fp_pm;
-	int blank, hsync, vsync, crt;
-
-	/* CRT power saving modes. */
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		blank = 0; hsync = 1; vsync = 1; crt = 1;
-		break;
-	case FB_BLANK_NORMAL:
-		blank = 1; hsync = 1; vsync = 1; crt = 1;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		blank = 1; hsync = 1; vsync = 0; crt = 1;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		blank = 1; hsync = 0; vsync = 1; crt = 1;
-		break;
-	case FB_BLANK_POWERDOWN:
-		blank = 1; hsync = 0; vsync = 0; crt = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-	dcfg = read_vp(par, VP_DCFG);
-	dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
-			VP_DCFG_CRT_EN);
-	if (!blank)
-		dcfg |= VP_DCFG_DAC_BL_EN;
-	if (hsync)
-		dcfg |= VP_DCFG_HSYNC_EN;
-	if (vsync)
-		dcfg |= VP_DCFG_VSYNC_EN;
-	if (crt)
-		dcfg |= VP_DCFG_CRT_EN;
-	write_vp(par, VP_DCFG, dcfg);
-
-	/* Power on/off flat panel. */
-
-	if (par->enable_crt == 0) {
-		fp_pm = read_fp(par, FP_PM);
-		if (blank_mode == FB_BLANK_POWERDOWN)
-			fp_pm &= ~FP_PM_P;
-		else
-			fp_pm |= FP_PM_P;
-		write_fp(par, FP_PM, fp_pm);
-	}
-
-	return 0;
-}
diff --git a/drivers/video/goldfishfb.c b/drivers/video/goldfishfb.c
deleted file mode 100644
index 7f6c9e6cfc6c..000000000000
--- a/drivers/video/goldfishfb.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (C) 2012 Intel, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-
-enum {
-	FB_GET_WIDTH        = 0x00,
-	FB_GET_HEIGHT       = 0x04,
-	FB_INT_STATUS       = 0x08,
-	FB_INT_ENABLE       = 0x0c,
-	FB_SET_BASE         = 0x10,
-	FB_SET_ROTATION     = 0x14,
-	FB_SET_BLANK        = 0x18,
-	FB_GET_PHYS_WIDTH   = 0x1c,
-	FB_GET_PHYS_HEIGHT  = 0x20,
-
-	FB_INT_VSYNC             = 1U << 0,
-	FB_INT_BASE_UPDATE_DONE  = 1U << 1
-};
-
-struct goldfish_fb {
-	void __iomem *reg_base;
-	int irq;
-	spinlock_t lock;
-	wait_queue_head_t wait;
-	int base_update_count;
-	int rotation;
-	struct fb_info fb;
-	u32 cmap[16];
-};
-
-static irqreturn_t goldfish_fb_interrupt(int irq, void *dev_id)
-{
-	unsigned long irq_flags;
-	struct goldfish_fb *fb = dev_id;
-	u32 status;
-
-	spin_lock_irqsave(&fb->lock, irq_flags);
-	status = readl(fb->reg_base + FB_INT_STATUS);
-	if (status & FB_INT_BASE_UPDATE_DONE) {
-		fb->base_update_count++;
-		wake_up(&fb->wait);
-	}
-	spin_unlock_irqrestore(&fb->lock, irq_flags);
-	return status ? IRQ_HANDLED : IRQ_NONE;
-}
-
-static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
-{
-	unsigned int mask = (1 << bf->length) - 1;
-
-	return (val >> (16 - bf->length) & mask) << bf->offset;
-}
-
-static int
-goldfish_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
-		 unsigned int blue, unsigned int transp, struct fb_info *info)
-{
-	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
-
-	if (regno < 16) {
-		fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
-				  convert_bitfield(blue, &fb->fb.var.blue) |
-				  convert_bitfield(green, &fb->fb.var.green) |
-				  convert_bitfield(red, &fb->fb.var.red);
-		return 0;
-	} else {
-		return 1;
-	}
-}
-
-static int goldfish_fb_check_var(struct fb_var_screeninfo *var,
-							struct fb_info *info)
-{
-	if ((var->rotate & 1) != (info->var.rotate & 1)) {
-		if ((var->xres != info->var.yres) ||
-				(var->yres != info->var.xres) ||
-				(var->xres_virtual != info->var.yres) ||
-				(var->yres_virtual > info->var.xres * 2) ||
-				(var->yres_virtual < info->var.xres)) {
-			return -EINVAL;
-		}
-	} else {
-		if ((var->xres != info->var.xres) ||
-		   (var->yres != info->var.yres) ||
-		   (var->xres_virtual != info->var.xres) ||
-		   (var->yres_virtual > info->var.yres * 2) ||
-		   (var->yres_virtual < info->var.yres)) {
-			return -EINVAL;
-		}
-	}
-	if ((var->xoffset != info->var.xoffset) ||
-			(var->bits_per_pixel != info->var.bits_per_pixel) ||
-			(var->grayscale != info->var.grayscale)) {
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int goldfish_fb_set_par(struct fb_info *info)
-{
-	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
-	if (fb->rotation != fb->fb.var.rotate) {
-		info->fix.line_length = info->var.xres * 2;
-		fb->rotation = fb->fb.var.rotate;
-		writel(fb->rotation, fb->reg_base + FB_SET_ROTATION);
-	}
-	return 0;
-}
-
-
-static int goldfish_fb_pan_display(struct fb_var_screeninfo *var,
-							struct fb_info *info)
-{
-	unsigned long irq_flags;
-	int base_update_count;
-	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
-
-	spin_lock_irqsave(&fb->lock, irq_flags);
-	base_update_count = fb->base_update_count;
-	writel(fb->fb.fix.smem_start + fb->fb.var.xres * 2 * var->yoffset,
-						fb->reg_base + FB_SET_BASE);
-	spin_unlock_irqrestore(&fb->lock, irq_flags);
-	wait_event_timeout(fb->wait,
-			fb->base_update_count != base_update_count, HZ / 15);
-	if (fb->base_update_count == base_update_count)
-		pr_err("goldfish_fb_pan_display: timeout waiting for base update\n");
-	return 0;
-}
-
-static int goldfish_fb_blank(int blank, struct fb_info *info)
-{
-	struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
-	switch (blank) {
-	case FB_BLANK_NORMAL:
-		writel(1, fb->reg_base + FB_SET_BLANK);
-		break;
-	case FB_BLANK_UNBLANK:
-		writel(0, fb->reg_base + FB_SET_BLANK);
-		break;
-	}
-	return 0;
-}
-
-static struct fb_ops goldfish_fb_ops = {
-	.owner          = THIS_MODULE,
-	.fb_check_var   = goldfish_fb_check_var,
-	.fb_set_par     = goldfish_fb_set_par,
-	.fb_setcolreg   = goldfish_fb_setcolreg,
-	.fb_pan_display = goldfish_fb_pan_display,
-	.fb_blank	= goldfish_fb_blank,
-	.fb_fillrect    = cfb_fillrect,
-	.fb_copyarea    = cfb_copyarea,
-	.fb_imageblit   = cfb_imageblit,
-};
-
-
-static int goldfish_fb_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct resource *r;
-	struct goldfish_fb *fb;
-	size_t framesize;
-	u32 width, height;
-	dma_addr_t fbpaddr;
-
-	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-	if (fb == NULL) {
-		ret = -ENOMEM;
-		goto err_fb_alloc_failed;
-	}
-	spin_lock_init(&fb->lock);
-	init_waitqueue_head(&fb->wait);
-	platform_set_drvdata(pdev, fb);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		ret = -ENODEV;
-		goto err_no_io_base;
-	}
-	fb->reg_base = ioremap(r->start, PAGE_SIZE);
-	if (fb->reg_base == NULL) {
-		ret = -ENOMEM;
-		goto err_no_io_base;
-	}
-
-	fb->irq = platform_get_irq(pdev, 0);
-	if (fb->irq <= 0) {
-		ret = -ENODEV;
-		goto err_no_irq;
-	}
-
-	width = readl(fb->reg_base + FB_GET_WIDTH);
-	height = readl(fb->reg_base + FB_GET_HEIGHT);
-
-	fb->fb.fbops		= &goldfish_fb_ops;
-	fb->fb.flags		= FBINFO_FLAG_DEFAULT;
-	fb->fb.pseudo_palette	= fb->cmap;
-	fb->fb.fix.type		= FB_TYPE_PACKED_PIXELS;
-	fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-	fb->fb.fix.line_length = width * 2;
-	fb->fb.fix.accel	= FB_ACCEL_NONE;
-	fb->fb.fix.ypanstep = 1;
-
-	fb->fb.var.xres		= width;
-	fb->fb.var.yres		= height;
-	fb->fb.var.xres_virtual	= width;
-	fb->fb.var.yres_virtual	= height * 2;
-	fb->fb.var.bits_per_pixel = 16;
-	fb->fb.var.activate	= FB_ACTIVATE_NOW;
-	fb->fb.var.height	= readl(fb->reg_base + FB_GET_PHYS_HEIGHT);
-	fb->fb.var.width	= readl(fb->reg_base + FB_GET_PHYS_WIDTH);
-	fb->fb.var.pixclock	= 10000;
-
-	fb->fb.var.red.offset = 11;
-	fb->fb.var.red.length = 5;
-	fb->fb.var.green.offset = 5;
-	fb->fb.var.green.length = 6;
-	fb->fb.var.blue.offset = 0;
-	fb->fb.var.blue.length = 5;
-
-	framesize = width * height * 2 * 2;
-	fb->fb.screen_base = (char __force __iomem *)dma_alloc_coherent(
-						&pdev->dev, framesize,
-						&fbpaddr, GFP_KERNEL);
-	pr_debug("allocating frame buffer %d * %d, got %p\n",
-					width, height, fb->fb.screen_base);
-	if (fb->fb.screen_base == NULL) {
-		ret = -ENOMEM;
-		goto err_alloc_screen_base_failed;
-	}
-	fb->fb.fix.smem_start = fbpaddr;
-	fb->fb.fix.smem_len = framesize;
-
-	ret = fb_set_var(&fb->fb, &fb->fb.var);
-	if (ret)
-		goto err_fb_set_var_failed;
-
-	ret = request_irq(fb->irq, goldfish_fb_interrupt, IRQF_SHARED,
-							pdev->name, fb);
-	if (ret)
-		goto err_request_irq_failed;
-
-	writel(FB_INT_BASE_UPDATE_DONE, fb->reg_base + FB_INT_ENABLE);
-	goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */
-
-	ret = register_framebuffer(&fb->fb);
-	if (ret)
-		goto err_register_framebuffer_failed;
-	return 0;
-
-err_register_framebuffer_failed:
-	free_irq(fb->irq, fb);
-err_request_irq_failed:
-err_fb_set_var_failed:
-	dma_free_coherent(&pdev->dev, framesize,
-				(void *)fb->fb.screen_base,
-				fb->fb.fix.smem_start);
-err_alloc_screen_base_failed:
-err_no_irq:
-	iounmap(fb->reg_base);
-err_no_io_base:
-	kfree(fb);
-err_fb_alloc_failed:
-	return ret;
-}
-
-static int goldfish_fb_remove(struct platform_device *pdev)
-{
-	size_t framesize;
-	struct goldfish_fb *fb = platform_get_drvdata(pdev);
-
-	framesize = fb->fb.var.xres_virtual * fb->fb.var.yres_virtual * 2;
-	unregister_framebuffer(&fb->fb);
-	free_irq(fb->irq, fb);
-
-	dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base,
-						fb->fb.fix.smem_start);
-	iounmap(fb->reg_base);
-	return 0;
-}
-
-
-static struct platform_driver goldfish_fb_driver = {
-	.probe		= goldfish_fb_probe,
-	.remove		= goldfish_fb_remove,
-	.driver = {
-		.name = "goldfish_fb"
-	}
-};
-
-module_platform_driver(goldfish_fb_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
deleted file mode 100644
index c078701f15f6..000000000000
--- a/drivers/video/grvga.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
- *
- * 2011 (c) Aeroflex Gaisler AB
- *
- * Full documentation of the core can be found here:
- * http://www.gaisler.com/products/grlib/grip.pdf
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/io.h>
-
-struct grvga_regs {
-	u32 status; 		/* 0x00 */
-	u32 video_length; 	/* 0x04 */
-	u32 front_porch;	/* 0x08 */
-	u32 sync_length;	/* 0x0C */
-	u32 line_length;	/* 0x10 */
-	u32 fb_pos;		/* 0x14 */
-	u32 clk_vector[4];	/* 0x18 */
-	u32 clut;	        /* 0x20 */
-};
-
-struct grvga_par {
-	struct grvga_regs *regs;
-	u32 color_palette[16];  /* 16 entry pseudo palette used by fbcon in true color mode */
-	int clk_sel;
-	int fb_alloced;         /* = 1 if framebuffer is allocated in main memory */
-};
-
-
-static const struct fb_videomode grvga_modedb[] = {
-    {
-	/* 640x480 @ 60 Hz */
-	NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 800x600 @ 60 Hz */
-	NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 800x600 @ 72 Hz */
-	NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1024x768 @ 60 Hz */
-	NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
-	0, FB_VMODE_NONINTERLACED
-    }
- };
-
-static struct fb_fix_screeninfo grvga_fix = {
-	.id =		"AG SVGACTRL",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =       FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep =	0,
-	.ypanstep =	1,
-	.ywrapstep =	0,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static int grvga_check_var(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
-{
-	struct grvga_par *par = info->par;
-	int i;
-
-	if (!var->xres)
-		var->xres = 1;
-	if (!var->yres)
-		var->yres = 1;
-	if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel <= 24)
-		var->bits_per_pixel = 24;
-	else if (var->bits_per_pixel <= 32)
-		var->bits_per_pixel = 32;
-	else
-		return -EINVAL;
-
-	var->xres_virtual = var->xres;
-	var->yres_virtual = 2*var->yres;
-
-	if (info->fix.smem_len) {
-		if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
-			return -ENOMEM;
-	}
-
-	/* Which clocks that are available can be read out in these registers */
-	for (i = 0; i <= 3 ; i++) {
-		if (var->pixclock == par->regs->clk_vector[i])
-			break;
-	}
-	if (i <= 3)
-		par->clk_sel = i;
-	else
-		return -EINVAL;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		var->red   = (struct fb_bitfield) {0, 8, 0};      /* offset, length, msb-right */
-		var->green = (struct fb_bitfield) {0, 8, 0};
-		var->blue  = (struct fb_bitfield) {0, 8, 0};
-		var->transp = (struct fb_bitfield) {0, 0, 0};
-		break;
-	case 16:
-		var->red   = (struct fb_bitfield) {11, 5, 0};
-		var->green = (struct fb_bitfield) {5, 6, 0};
-		var->blue  = (struct fb_bitfield) {0, 5, 0};
-		var->transp = (struct fb_bitfield) {0, 0, 0};
-		break;
-	case 24:
-	case 32:
-		var->red   = (struct fb_bitfield) {16, 8, 0};
-		var->green = (struct fb_bitfield) {8, 8, 0};
-		var->blue  = (struct fb_bitfield) {0, 8, 0};
-		var->transp = (struct fb_bitfield) {24, 8, 0};
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int grvga_set_par(struct fb_info *info)
-{
-
-	u32 func = 0;
-	struct grvga_par *par = info->par;
-
-	__raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1),
-		     &par->regs->video_length);
-
-	__raw_writel((info->var.lower_margin << 16) | (info->var.right_margin),
-		     &par->regs->front_porch);
-
-	__raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len),
-		     &par->regs->sync_length);
-
-	__raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
-		     (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1),
-		     &par->regs->line_length);
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		func = 1;
-		break;
-	case 16:
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		func = 2;
-		break;
-	case 24:
-	case 32:
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		func = 3;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	__raw_writel((par->clk_sel << 6) | (func << 4) | 1,
-		     &par->regs->status);
-
-	info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
-	return 0;
-}
-
-static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
-{
-	struct grvga_par *par;
-	par = info->par;
-
-	if (regno >= 256)	/* Size of CLUT */
-		return -EINVAL;
-
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-
-
-#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
-
-	red    = CNVT_TOHW(red,   info->var.red.length);
-	green  = CNVT_TOHW(green, info->var.green.length);
-	blue   = CNVT_TOHW(blue,  info->var.blue.length);
-	transp = CNVT_TOHW(transp, info->var.transp.length);
-
-#undef CNVT_TOHW
-
-	/* In PSEUDOCOLOR we use the hardware CLUT */
-	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
-		__raw_writel((regno << 24) | (red << 16) | (green << 8) | blue,
-			     &par->regs->clut);
-
-	/* Truecolor uses the pseudo palette */
-	else if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 v;
-		if (regno >= 16)
-			return -EINVAL;
-
-
-		v =     (red    << info->var.red.offset)   |
-			(green  << info->var.green.offset) |
-			(blue   << info->var.blue.offset)  |
-			(transp << info->var.transp.offset);
-
-		((u32 *) (info->pseudo_palette))[regno] = v;
-	}
-	return 0;
-}
-
-static int grvga_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct grvga_par *par = info->par;
-	struct fb_fix_screeninfo *fix = &info->fix;
-	u32 base_addr;
-
-	if (var->xoffset != 0)
-		return -EINVAL;
-
-	base_addr = fix->smem_start + (var->yoffset * fix->line_length);
-	base_addr &= ~3UL;
-
-	/* Set framebuffer base address  */
-	__raw_writel(base_addr,
-		     &par->regs->fb_pos);
-
-	return 0;
-}
-
-static struct fb_ops grvga_ops = {
-	.owner          = THIS_MODULE,
-	.fb_check_var   = grvga_check_var,
-	.fb_set_par	= grvga_set_par,
-	.fb_setcolreg   = grvga_setcolreg,
-	.fb_pan_display = grvga_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit
-};
-
-static int grvga_parse_custom(char *options,
-			      struct fb_var_screeninfo *screendata)
-{
-	char *this_opt;
-	int count = 0;
-	if (!options || !*options)
-		return -1;
-
-	while ((this_opt = strsep(&options, " ")) != NULL) {
-		if (!*this_opt)
-			continue;
-
-		switch (count) {
-		case 0:
-			screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 1:
-			screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 2:
-			screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 3:
-			screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 4:
-			screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 5:
-			screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 6:
-			screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 7:
-			screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 8:
-			screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		case 9:
-			screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
-			count++;
-			break;
-		default:
-			return -1;
-		}
-	}
-	screendata->activate  = FB_ACTIVATE_NOW;
-	screendata->vmode     = FB_VMODE_NONINTERLACED;
-	return 0;
-}
-
-static int grvga_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	int retval = -ENOMEM;
-	unsigned long virtual_start;
-	unsigned long grvga_fix_addr = 0;
-	unsigned long physical_start = 0;
-	unsigned long grvga_mem_size = 0;
-	struct grvga_par *par = NULL;
-	char *options = NULL, *mode_opt = NULL;
-
-	info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
-	if (!info) {
-		dev_err(&dev->dev, "framebuffer_alloc failed\n");
-		return -ENOMEM;
-	}
-
-	/* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
-	 *
-	 * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
-	 * If address is left out, we allocate memory,
-	 * if size is left out we only allocate enough to support the given mode.
-	 */
-	if (fb_get_options("grvga", &options)) {
-		retval = -ENODEV;
-		goto free_fb;
-	}
-
-	if (!options || !*options)
-		options =  "640x480-8@60";
-
-	while (1) {
-		char *this_opt = strsep(&options, ",");
-
-		if (!this_opt)
-			break;
-
-		if (!strncmp(this_opt, "custom", 6)) {
-			if (grvga_parse_custom(this_opt, &info->var) < 0) {
-				dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt);
-				retval = -EINVAL;
-				goto free_fb;
-			}
-		} else if (!strncmp(this_opt, "addr", 4))
-			grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
-		else if (!strncmp(this_opt, "size", 4))
-			grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
-		else
-			mode_opt = this_opt;
-	}
-
-	par = info->par;
-	info->fbops = &grvga_ops;
-	info->fix = grvga_fix;
-	info->pseudo_palette = par->color_palette;
-	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
-	info->fix.smem_len = grvga_mem_size;
-
-	if (!devm_request_mem_region(&dev->dev, dev->resource[0].start,
-		    resource_size(&dev->resource[0]), "grlib-svgactrl regs")) {
-		dev_err(&dev->dev, "registers already mapped\n");
-		retval = -EBUSY;
-		goto free_fb;
-	}
-
-	par->regs = of_ioremap(&dev->resource[0], 0,
-			       resource_size(&dev->resource[0]),
-			       "grlib-svgactrl regs");
-
-	if (!par->regs) {
-		dev_err(&dev->dev, "failed to map registers\n");
-		retval = -ENOMEM;
-		goto free_fb;
-	}
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0) {
-		dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
-		retval = -ENOMEM;
-		goto unmap_regs;
-	}
-
-	if (mode_opt) {
-		retval = fb_find_mode(&info->var, info, mode_opt,
-				      grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
-		if (!retval || retval == 4) {
-			retval = -EINVAL;
-			goto dealloc_cmap;
-		}
-	}
-
-	if (!grvga_mem_size)
-		grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
-
-	if (grvga_fix_addr) {
-		/* Got framebuffer base address from argument list */
-
-		physical_start = grvga_fix_addr;
-
-		if (!devm_request_mem_region(&dev->dev, physical_start,
-					     grvga_mem_size, dev->name)) {
-			dev_err(&dev->dev, "failed to request memory region\n");
-			retval = -ENOMEM;
-			goto dealloc_cmap;
-		}
-
-		virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
-
-		if (!virtual_start) {
-			dev_err(&dev->dev, "error mapping framebuffer memory\n");
-			retval = -ENOMEM;
-			goto dealloc_cmap;
-		}
-	} else {	/* Allocate frambuffer memory */
-
-		unsigned long page;
-
-		virtual_start = (unsigned long) __get_free_pages(GFP_DMA,
-								 get_order(grvga_mem_size));
-		if (!virtual_start) {
-			dev_err(&dev->dev,
-				"unable to allocate framebuffer memory (%lu bytes)\n",
-				grvga_mem_size);
-			retval = -ENOMEM;
-			goto dealloc_cmap;
-		}
-
-		physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE);
-
-		/* Set page reserved so that mmap will work. This is necessary
-		 * since we'll be remapping normal memory.
-		 */
-		for (page = virtual_start;
-		     page < PAGE_ALIGN(virtual_start + grvga_mem_size);
-		     page += PAGE_SIZE) {
-			SetPageReserved(virt_to_page(page));
-		}
-
-		par->fb_alloced = 1;
-	}
-
-	memset((unsigned long *) virtual_start, 0, grvga_mem_size);
-
-	info->screen_base = (char __iomem *) virtual_start;
-	info->fix.smem_start = physical_start;
-	info->fix.smem_len   = grvga_mem_size;
-
-	dev_set_drvdata(&dev->dev, info);
-
-	dev_info(&dev->dev,
-		 "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n",
-		 info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
-		 grvga_mem_size >> 10, info->screen_base);
-
-	retval = register_framebuffer(info);
-	if (retval < 0) {
-		dev_err(&dev->dev, "failed to register framebuffer\n");
-		goto free_mem;
-	}
-
-	__raw_writel(physical_start, &par->regs->fb_pos);
-	__raw_writel(__raw_readl(&par->regs->status) | 1,  /* Enable framebuffer */
-		     &par->regs->status);
-
-	return 0;
-
-free_mem:
-	if (grvga_fix_addr)
-		iounmap((void *)virtual_start);
-	else
-		kfree((void *)virtual_start);
-dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-unmap_regs:
-	of_iounmap(&dev->resource[0], par->regs,
-		   resource_size(&dev->resource[0]));
-free_fb:
-	framebuffer_release(info);
-
-	return retval;
-}
-
-static int grvga_remove(struct platform_device *device)
-{
-	struct fb_info *info = dev_get_drvdata(&device->dev);
-	struct grvga_par *par = info->par;
-
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-
-		of_iounmap(&device->resource[0], par->regs,
-			   resource_size(&device->resource[0]));
-
-		if (!par->fb_alloced)
-			iounmap(info->screen_base);
-		else
-			kfree((void *)info->screen_base);
-
-		framebuffer_release(info);
-	}
-
-	return 0;
-}
-
-static struct of_device_id svgactrl_of_match[] = {
-	{
-		.name = "GAISLER_SVGACTRL",
-	},
-	{
-		.name = "01_063",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, svgactrl_of_match);
-
-static struct platform_driver grvga_driver = {
-	.driver = {
-		.name = "grlib-svgactrl",
-		.owner = THIS_MODULE,
-		.of_match_table = svgactrl_of_match,
-	},
-	.probe		= grvga_probe,
-	.remove		= grvga_remove,
-};
-
-module_platform_driver(grvga_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Aeroflex Gaisler");
-MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
deleted file mode 100644
index 135d78a02588..000000000000
--- a/drivers/video/gxt4500.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Frame buffer device for IBM GXT4500P/6500P and GXT4000P/6000P
- * display adaptors
- *
- * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-
-#define PCI_DEVICE_ID_IBM_GXT4500P	0x21c
-#define PCI_DEVICE_ID_IBM_GXT6500P	0x21b
-#define PCI_DEVICE_ID_IBM_GXT4000P	0x16e
-#define PCI_DEVICE_ID_IBM_GXT6000P	0x170
-
-/* GXT4500P registers */
-
-/* Registers in PCI config space */
-#define CFG_ENDIAN0		0x40
-
-/* Misc control/status registers */
-#define STATUS			0x1000
-#define CTRL_REG0		0x1004
-#define   CR0_HALT_DMA			0x4
-#define   CR0_RASTER_RESET		0x8
-#define   CR0_GEOM_RESET		0x10
-#define   CR0_MEM_CTRLER_RESET		0x20
-
-/* Framebuffer control registers */
-#define FB_AB_CTRL		0x1100
-#define FB_CD_CTRL		0x1104
-#define FB_WID_CTRL		0x1108
-#define FB_Z_CTRL		0x110c
-#define FB_VGA_CTRL		0x1110
-#define REFRESH_AB_CTRL		0x1114
-#define REFRESH_CD_CTRL		0x1118
-#define FB_OVL_CTRL		0x111c
-#define   FB_CTRL_TYPE			0x80000000
-#define   FB_CTRL_WIDTH_MASK		0x007f0000
-#define   FB_CTRL_WIDTH_SHIFT		16
-#define   FB_CTRL_START_SEG_MASK	0x00003fff
-
-#define REFRESH_START		0x1098
-#define REFRESH_SIZE		0x109c
-
-/* "Direct" framebuffer access registers */
-#define DFA_FB_A		0x11e0
-#define DFA_FB_B		0x11e4
-#define DFA_FB_C		0x11e8
-#define DFA_FB_D		0x11ec
-#define   DFA_FB_ENABLE			0x80000000
-#define   DFA_FB_BASE_MASK		0x03f00000
-#define   DFA_FB_STRIDE_1k		0x00000000
-#define   DFA_FB_STRIDE_2k		0x00000010
-#define   DFA_FB_STRIDE_4k		0x00000020
-#define   DFA_PIX_8BIT			0x00000000
-#define   DFA_PIX_16BIT_565		0x00000001
-#define   DFA_PIX_16BIT_1555		0x00000002
-#define   DFA_PIX_24BIT			0x00000004
-#define   DFA_PIX_32BIT			0x00000005
-
-/* maps DFA_PIX_* to pixel size in bytes */
-static const unsigned char pixsize[] = {
-	1, 2, 2, 2, 4, 4
-};
-
-/* Display timing generator registers */
-#define DTG_CONTROL		0x1900
-#define   DTG_CTL_SCREEN_REFRESH	2
-#define   DTG_CTL_ENABLE		1
-#define DTG_HORIZ_EXTENT	0x1904
-#define DTG_HORIZ_DISPLAY	0x1908
-#define DTG_HSYNC_START		0x190c
-#define DTG_HSYNC_END		0x1910
-#define DTG_HSYNC_END_COMP	0x1914
-#define DTG_VERT_EXTENT		0x1918
-#define DTG_VERT_DISPLAY	0x191c
-#define DTG_VSYNC_START		0x1920
-#define DTG_VSYNC_END		0x1924
-#define DTG_VERT_SHORT		0x1928
-
-/* PLL/RAMDAC registers */
-#define DISP_CTL		0x402c
-#define   DISP_CTL_OFF			2
-#define SYNC_CTL		0x4034
-#define   SYNC_CTL_SYNC_ON_RGB		1
-#define   SYNC_CTL_SYNC_OFF		2
-#define   SYNC_CTL_HSYNC_INV		8
-#define   SYNC_CTL_VSYNC_INV		0x10
-#define   SYNC_CTL_HSYNC_OFF		0x20
-#define   SYNC_CTL_VSYNC_OFF		0x40
-
-#define PLL_M			0x4040
-#define PLL_N			0x4044
-#define PLL_POSTDIV		0x4048
-#define PLL_C			0x404c
-
-/* Hardware cursor */
-#define CURSOR_X		0x4078
-#define CURSOR_Y		0x407c
-#define CURSOR_HOTSPOT		0x4080
-#define CURSOR_MODE		0x4084
-#define   CURSOR_MODE_OFF		0
-#define   CURSOR_MODE_4BPP		1
-#define CURSOR_PIXMAP		0x5000
-#define CURSOR_CMAP		0x7400
-
-/* Window attribute table */
-#define WAT_FMT			0x4100
-#define   WAT_FMT_24BIT			0
-#define   WAT_FMT_16BIT_565		1
-#define   WAT_FMT_16BIT_1555		2
-#define   WAT_FMT_32BIT			3	/* 0 vs. 3 is a guess */
-#define   WAT_FMT_8BIT_332		9
-#define   WAT_FMT_8BIT			0xa
-#define   WAT_FMT_NO_CMAP		4	/* ORd in to other values */
-#define WAT_CMAP_OFFSET		0x4104		/* 4-bit value gets << 6 */
-#define WAT_CTRL		0x4108
-#define   WAT_CTRL_SEL_B		1	/* select B buffer if 1 */
-#define   WAT_CTRL_NO_INC		2
-#define WAT_GAMMA_CTRL		0x410c
-#define   WAT_GAMMA_DISABLE		1	/* disables gamma cmap */
-#define WAT_OVL_CTRL		0x430c		/* controls overlay */
-
-/* Indexed by DFA_PIX_* values */
-static const unsigned char watfmt[] = {
-	WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0,
-	WAT_FMT_24BIT, WAT_FMT_32BIT
-};
-
-/* Colormap array; 1k entries of 4 bytes each */
-#define CMAP			0x6000
-
-#define readreg(par, reg)	readl((par)->regs + (reg))
-#define writereg(par, reg, val)	writel((val), (par)->regs + (reg))
-
-struct gxt4500_par {
-	void __iomem *regs;
-
-	int pixfmt;		/* pixel format, see DFA_PIX_* values */
-
-	/* PLL parameters */
-	int refclk_ps;		/* ref clock period in picoseconds */
-	int pll_m;		/* ref clock divisor */
-	int pll_n;		/* VCO divisor */
-	int pll_pd1;		/* first post-divisor */
-	int pll_pd2;		/* second post-divisor */
-
-	u32 pseudo_palette[16];	/* used in color blits */
-};
-
-/* mode requested by user */
-static char *mode_option;
-
-/* default mode: 1280x1024 @ 60 Hz, 8 bpp */
-static const struct fb_videomode defaultmode = {
-	.refresh = 60,
-	.xres = 1280,
-	.yres = 1024,
-	.pixclock = 9295,
-	.left_margin = 248,
-	.right_margin = 48,
-	.upper_margin = 38,
-	.lower_margin = 1,
-	.hsync_len = 112,
-	.vsync_len = 3,
-	.vmode = FB_VMODE_NONINTERLACED
-};
-
-/* List of supported cards */
-enum gxt_cards {
-	GXT4500P,
-	GXT6500P,
-	GXT4000P,
-	GXT6000P
-};
-
-/* Card-specific information */
-static const struct cardinfo {
-	int	refclk_ps;	/* period of PLL reference clock in ps */
-	const char *cardname;
-} cardinfo[] = {
-	[GXT4500P] = { .refclk_ps = 9259, .cardname = "IBM GXT4500P" },
-	[GXT6500P] = { .refclk_ps = 9259, .cardname = "IBM GXT6500P" },
-	[GXT4000P] = { .refclk_ps = 40000, .cardname = "IBM GXT4000P" },
-	[GXT6000P] = { .refclk_ps = 40000, .cardname = "IBM GXT6000P" },
-};
-
-/*
- * The refclk and VCO dividers appear to use a linear feedback shift
- * register, which gets reloaded when it reaches a terminal value, at
- * which point the divider output is toggled.  Thus one can obtain
- * whatever divisor is required by putting the appropriate value into
- * the reload register.  For a divisor of N, one puts the value from
- * the LFSR sequence that comes N-1 places before the terminal value
- * into the reload register.
- */
-
-static const unsigned char mdivtab[] = {
-/* 1 */		      0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a,
-/* 10 */	0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11,
-/* 20 */	0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d,
-/* 30 */	0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02,
-/* 40 */	0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e,
-/* 50 */	0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e,
-/* 60 */	0x1f, 0x0f, 0x07, 0x03, 0x01,
-};
-
-static const unsigned char ndivtab[] = {
-/* 2 */		            0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e,
-/* 10 */	0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e,
-/* 20 */	0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf,
-/* 30 */	0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc,
-/* 40 */	0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8,
-/* 50 */	0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6,
-/* 60 */	0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62,
-/* 70 */	0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57,
-/* 80 */	0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94,
-/* 90 */	0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79,
-/* 100 */	0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24,
-/* 110 */	0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45,
-/* 120 */	0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d,
-/* 130 */	0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e,
-/* 140 */	0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98,
-/* 150 */	0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2,
-/* 160 */	0x69,
-};
-
-static int calc_pll(int period_ps, struct gxt4500_par *par)
-{
-	int m, n, pdiv1, pdiv2, postdiv;
-	int pll_period, best_error, t, intf;
-
-	/* only deal with range 5MHz - 300MHz */
-	if (period_ps < 3333 || period_ps > 200000)
-		return -1;
-
-	best_error = 1000000;
-	for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) {
-		for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) {
-			postdiv = pdiv1 * pdiv2;
-			pll_period = DIV_ROUND_UP(period_ps, postdiv);
-			/* keep pll in range 350..600 MHz */
-			if (pll_period < 1666 || pll_period > 2857)
-				continue;
-			for (m = 1; m <= 64; ++m) {
-				intf = m * par->refclk_ps;
-				if (intf > 500000)
-					break;
-				n = intf * postdiv / period_ps;
-				if (n < 3 || n > 160)
-					continue;
-				t = par->refclk_ps * m * postdiv / n;
-				t -= period_ps;
-				if (t >= 0 && t < best_error) {
-					par->pll_m = m;
-					par->pll_n = n;
-					par->pll_pd1 = pdiv1;
-					par->pll_pd2 = pdiv2;
-					best_error = t;
-				}
-			}
-		}
-	}
-	if (best_error == 1000000)
-		return -1;
-	return 0;
-}
-
-static int calc_pixclock(struct gxt4500_par *par)
-{
-	return par->refclk_ps * par->pll_m * par->pll_pd1 * par->pll_pd2
-		/ par->pll_n;
-}
-
-static int gxt4500_var_to_par(struct fb_var_screeninfo *var,
-			      struct gxt4500_par *par)
-{
-	if (var->xres + var->xoffset > var->xres_virtual ||
-	    var->yres + var->yoffset > var->yres_virtual ||
-	    var->xres_virtual > 4096)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (calc_pll(var->pixclock, par) < 0)
-		return -EINVAL;
-
-	switch (var->bits_per_pixel) {
-	case 32:
-		if (var->transp.length)
-			par->pixfmt = DFA_PIX_32BIT;
-		else
-			par->pixfmt = DFA_PIX_24BIT;
-		break;
-	case 24:
-		par->pixfmt = DFA_PIX_24BIT;
-		break;
-	case 16:
-		if (var->green.length == 5)
-			par->pixfmt = DFA_PIX_16BIT_1555;
-		else
-			par->pixfmt = DFA_PIX_16BIT_565;
-		break;
-	case 8:
-		par->pixfmt = DFA_PIX_8BIT;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static const struct fb_bitfield eightbits = {0, 8};
-static const struct fb_bitfield nobits = {0, 0};
-
-static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var,
-				  int pixfmt)
-{
-	var->bits_per_pixel = pixsize[pixfmt] * 8;
-	var->red = eightbits;
-	var->green = eightbits;
-	var->blue = eightbits;
-	var->transp = nobits;
-
-	switch (pixfmt) {
-	case DFA_PIX_16BIT_565:
-		var->red.length = 5;
-		var->green.length = 6;
-		var->blue.length = 5;
-		break;
-	case DFA_PIX_16BIT_1555:
-		var->red.length = 5;
-		var->green.length = 5;
-		var->blue.length = 5;
-		var->transp.length = 1;
-		break;
-	case DFA_PIX_32BIT:
-		var->transp.length = 8;
-		break;
-	}
-	if (pixfmt != DFA_PIX_8BIT) {
-		var->green.offset = var->red.length;
-		var->blue.offset = var->green.offset + var->green.length;
-		if (var->transp.length)
-			var->transp.offset =
-				var->blue.offset + var->blue.length;
-	}
-}
-
-static int gxt4500_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct gxt4500_par par;
-	int err;
-
-	par = *(struct gxt4500_par *)info->par;
-	err = gxt4500_var_to_par(var, &par);
-	if (!err) {
-		var->pixclock = calc_pixclock(&par);
-		gxt4500_unpack_pixfmt(var, par.pixfmt);
-	}
-	return err;
-}
-
-static int gxt4500_set_par(struct fb_info *info)
-{
-	struct gxt4500_par *par = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	int err;
-	u32 ctrlreg, tmp;
-	unsigned int dfa_ctl, pixfmt, stride;
-	unsigned int wid_tiles, i;
-	unsigned int prefetch_pix, htot;
-	struct gxt4500_par save_par;
-
-	save_par = *par;
-	err = gxt4500_var_to_par(var, par);
-	if (err) {
-		*par = save_par;
-		return err;
-	}
-
-	/* turn off DTG for now */
-	ctrlreg = readreg(par, DTG_CONTROL);
-	ctrlreg &= ~(DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH);
-	writereg(par, DTG_CONTROL, ctrlreg);
-
-	/* set PLL registers */
-	tmp = readreg(par, PLL_C) & ~0x7f;
-	if (par->pll_n < 38)
-		tmp |= 0x29;
-	if (par->pll_n < 69)
-		tmp |= 0x35;
-	else if (par->pll_n < 100)
-		tmp |= 0x76;
-	else
-		tmp |= 0x7e;
-	writereg(par, PLL_C, tmp);
-	writereg(par, PLL_M, mdivtab[par->pll_m - 1]);
-	writereg(par, PLL_N, ndivtab[par->pll_n - 2]);
-	tmp = ((8 - par->pll_pd2) << 3) | (8 - par->pll_pd1);
-	if (par->pll_pd1 == 8 || par->pll_pd2 == 8) {
-		/* work around erratum */
-		writereg(par, PLL_POSTDIV, tmp | 0x9);
-		udelay(1);
-	}
-	writereg(par, PLL_POSTDIV, tmp);
-	msleep(20);
-
-	/* turn off hardware cursor */
-	writereg(par, CURSOR_MODE, CURSOR_MODE_OFF);
-
-	/* reset raster engine */
-	writereg(par, CTRL_REG0, CR0_RASTER_RESET | (CR0_RASTER_RESET << 16));
-	udelay(10);
-	writereg(par, CTRL_REG0, CR0_RASTER_RESET << 16);
-
-	/* set display timing generator registers */
-	htot = var->xres + var->left_margin + var->right_margin +
-		var->hsync_len;
-	writereg(par, DTG_HORIZ_EXTENT, htot - 1);
-	writereg(par, DTG_HORIZ_DISPLAY, var->xres - 1);
-	writereg(par, DTG_HSYNC_START, var->xres + var->right_margin - 1);
-	writereg(par, DTG_HSYNC_END,
-		 var->xres + var->right_margin + var->hsync_len - 1);
-	writereg(par, DTG_HSYNC_END_COMP,
-		 var->xres + var->right_margin + var->hsync_len - 1);
-	writereg(par, DTG_VERT_EXTENT,
-		 var->yres + var->upper_margin + var->lower_margin +
-		 var->vsync_len - 1);
-	writereg(par, DTG_VERT_DISPLAY, var->yres - 1);
-	writereg(par, DTG_VSYNC_START, var->yres + var->lower_margin - 1);
-	writereg(par, DTG_VSYNC_END,
-		 var->yres + var->lower_margin + var->vsync_len - 1);
-	prefetch_pix = 3300000 / var->pixclock;
-	if (prefetch_pix >= htot)
-		prefetch_pix = htot - 1;
-	writereg(par, DTG_VERT_SHORT, htot - prefetch_pix - 1);
-	ctrlreg |= DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH;
-	writereg(par, DTG_CONTROL, ctrlreg);
-
-	/* calculate stride in DFA aperture */
-	if (var->xres_virtual > 2048) {
-		stride = 4096;
-		dfa_ctl = DFA_FB_STRIDE_4k;
-	} else if (var->xres_virtual > 1024) {
-		stride = 2048;
-		dfa_ctl = DFA_FB_STRIDE_2k;
-	} else {
-		stride = 1024;
-		dfa_ctl = DFA_FB_STRIDE_1k;
-	}
-
-	/* Set up framebuffer definition */
-	wid_tiles = (var->xres_virtual + 63) >> 6;
-
-	/* XXX add proper FB allocation here someday */
-	writereg(par, FB_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
-	writereg(par, REFRESH_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
-	writereg(par, FB_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
-	writereg(par, REFRESH_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
-	writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
-	writereg(par, REFRESH_SIZE, (var->xres << 16) | var->yres);
-
-	/* Set up framebuffer access by CPU */
-
-	pixfmt = par->pixfmt;
-	dfa_ctl |= DFA_FB_ENABLE | pixfmt;
-	writereg(par, DFA_FB_A, dfa_ctl);
-
-	/*
-	 * Set up window attribute table.
-	 * We set all WAT entries the same so it doesn't matter what the
-	 * window ID (WID) plane contains.
-	 */
-	for (i = 0; i < 32; ++i) {
-		writereg(par, WAT_FMT + (i << 4), watfmt[pixfmt]);
-		writereg(par, WAT_CMAP_OFFSET + (i << 4), 0);
-		writereg(par, WAT_CTRL + (i << 4), 0);
-		writereg(par, WAT_GAMMA_CTRL + (i << 4), WAT_GAMMA_DISABLE);
-	}
-
-	/* Set sync polarity etc. */
-	ctrlreg = readreg(par, SYNC_CTL) &
-		~(SYNC_CTL_SYNC_ON_RGB | SYNC_CTL_HSYNC_INV |
-		  SYNC_CTL_VSYNC_INV);
-	if (var->sync & FB_SYNC_ON_GREEN)
-		ctrlreg |= SYNC_CTL_SYNC_ON_RGB;
-	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
-		ctrlreg |= SYNC_CTL_HSYNC_INV;
-	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
-		ctrlreg |= SYNC_CTL_VSYNC_INV;
-	writereg(par, SYNC_CTL, ctrlreg);
-
-	info->fix.line_length = stride * pixsize[pixfmt];
-	info->fix.visual = (pixfmt == DFA_PIX_8BIT)? FB_VISUAL_PSEUDOCOLOR:
-		FB_VISUAL_DIRECTCOLOR;
-
-	return 0;
-}
-
-static int gxt4500_setcolreg(unsigned int reg, unsigned int red,
-			     unsigned int green, unsigned int blue,
-			     unsigned int transp, struct fb_info *info)
-{
-	u32 cmap_entry;
-	struct gxt4500_par *par = info->par;
-
-	if (reg > 1023)
-		return 1;
-	cmap_entry = ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
-		(green & 0xff00) | (blue >> 8);
-	writereg(par, CMAP + reg * 4, cmap_entry);
-
-	if (reg < 16 && par->pixfmt != DFA_PIX_8BIT) {
-		u32 *pal = info->pseudo_palette;
-		u32 val = reg;
-		switch (par->pixfmt) {
-		case DFA_PIX_16BIT_565:
-			val |= (reg << 11) | (reg << 6);
-			break;
-		case DFA_PIX_16BIT_1555:
-			val |= (reg << 10) | (reg << 5);
-			break;
-		case DFA_PIX_32BIT:
-			val |= (reg << 24);
-			/* fall through */
-		case DFA_PIX_24BIT:
-			val |= (reg << 16) | (reg << 8);
-			break;
-		}
-		pal[reg] = val;
-	}
-
-	return 0;
-}
-
-static int gxt4500_pan_display(struct fb_var_screeninfo *var,
-			       struct fb_info *info)
-{
-	struct gxt4500_par *par = info->par;
-
-	if (var->xoffset & 7)
-		return -EINVAL;
-	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-	    var->yoffset + info->var.yres > info->var.yres_virtual)
-		return -EINVAL;
-
-	writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
-	return 0;
-}
-
-static int gxt4500_blank(int blank, struct fb_info *info)
-{
-	struct gxt4500_par *par = info->par;
-	int ctrl, dctl;
-
-	ctrl = readreg(par, SYNC_CTL);
-	ctrl &= ~(SYNC_CTL_SYNC_OFF | SYNC_CTL_HSYNC_OFF | SYNC_CTL_VSYNC_OFF);
-	dctl = readreg(par, DISP_CTL);
-	dctl |= DISP_CTL_OFF;
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-		dctl &= ~DISP_CTL_OFF;
-		break;
-	case FB_BLANK_POWERDOWN:
-		ctrl |= SYNC_CTL_SYNC_OFF;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		ctrl |= SYNC_CTL_HSYNC_OFF;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		ctrl |= SYNC_CTL_VSYNC_OFF;
-		break;
-	default: ;
-	}
-	writereg(par, SYNC_CTL, ctrl);
-	writereg(par, DISP_CTL, dctl);
-
-	return 0;
-}
-
-static const struct fb_fix_screeninfo gxt4500_fix = {
-	.id = "IBM GXT4500P",
-	.type = FB_TYPE_PACKED_PIXELS,
-	.visual = FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep = 8,
-	.ypanstep = 1,
-	.mmio_len = 0x20000,
-};
-
-static struct fb_ops gxt4500_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = gxt4500_check_var,
-	.fb_set_par = gxt4500_set_par,
-	.fb_setcolreg = gxt4500_setcolreg,
-	.fb_pan_display = gxt4500_pan_display,
-	.fb_blank = gxt4500_blank,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-};
-
-/* PCI functions */
-static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int err;
-	unsigned long reg_phys, fb_phys;
-	struct gxt4500_par *par;
-	struct fb_info *info;
-	struct fb_var_screeninfo var;
-	enum gxt_cards cardtype;
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n",
-			err);
-		return err;
-	}
-
-	reg_phys = pci_resource_start(pdev, 0);
-	if (!request_mem_region(reg_phys, pci_resource_len(pdev, 0),
-				"gxt4500 regs")) {
-		dev_err(&pdev->dev, "gxt4500: cannot get registers\n");
-		goto err_nodev;
-	}
-
-	fb_phys = pci_resource_start(pdev, 1);
-	if (!request_mem_region(fb_phys, pci_resource_len(pdev, 1),
-				"gxt4500 FB")) {
-		dev_err(&pdev->dev, "gxt4500: cannot get framebuffer\n");
-		goto err_free_regs;
-	}
-
-	info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev);
-	if (!info) {
-		dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record\n");
-		goto err_free_fb;
-	}
-	par = info->par;
-	cardtype = ent->driver_data;
-	par->refclk_ps = cardinfo[cardtype].refclk_ps;
-	info->fix = gxt4500_fix;
-	strlcpy(info->fix.id, cardinfo[cardtype].cardname,
-		sizeof(info->fix.id));
-	info->pseudo_palette = par->pseudo_palette;
-
-	info->fix.mmio_start = reg_phys;
-	par->regs = pci_ioremap_bar(pdev, 0);
-	if (!par->regs) {
-		dev_err(&pdev->dev, "gxt4500: cannot map registers\n");
-		goto err_free_all;
-	}
-
-	info->fix.smem_start = fb_phys;
-	info->fix.smem_len = pci_resource_len(pdev, 1);
-	info->screen_base = pci_ioremap_bar(pdev, 1);
-	if (!info->screen_base) {
-		dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n");
-		goto err_unmap_regs;
-	}
-
-	pci_set_drvdata(pdev, info);
-
-	/* Set byte-swapping for DFA aperture for all pixel sizes */
-	pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300);
-
-	info->fbops = &gxt4500_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
-
-	err = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (err) {
-		dev_err(&pdev->dev, "gxt4500: cannot allocate cmap\n");
-		goto err_unmap_all;
-	}
-
-	gxt4500_blank(FB_BLANK_UNBLANK, info);
-
-	if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8)) {
-		dev_err(&pdev->dev, "gxt4500: cannot find valid video mode\n");
-		goto err_free_cmap;
-	}
-	info->var = var;
-	if (gxt4500_set_par(info)) {
-		printk(KERN_ERR "gxt4500: cannot set video mode\n");
-		goto err_free_cmap;
-	}
-
-	if (register_framebuffer(info) < 0) {
-		dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n");
-		goto err_free_cmap;
-	}
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	return 0;
-
- err_free_cmap:
-	fb_dealloc_cmap(&info->cmap);
- err_unmap_all:
-	iounmap(info->screen_base);
- err_unmap_regs:
-	iounmap(par->regs);
- err_free_all:
-	framebuffer_release(info);
- err_free_fb:
-	release_mem_region(fb_phys, pci_resource_len(pdev, 1));
- err_free_regs:
-	release_mem_region(reg_phys, pci_resource_len(pdev, 0));
- err_nodev:
-	return -ENODEV;
-}
-
-static void gxt4500_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct gxt4500_par *par;
-
-	if (!info)
-		return;
-	par = info->par;
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-	iounmap(par->regs);
-	iounmap(info->screen_base);
-	release_mem_region(pci_resource_start(pdev, 0),
-			   pci_resource_len(pdev, 0));
-	release_mem_region(pci_resource_start(pdev, 1),
-			   pci_resource_len(pdev, 1));
-	framebuffer_release(info);
-}
-
-/* supported chipsets */
-static const struct pci_device_id gxt4500_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P),
-	  .driver_data = GXT4500P },
-	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT6500P),
-	  .driver_data = GXT6500P },
-	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4000P),
-	  .driver_data = GXT4000P },
-	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT6000P),
-	  .driver_data = GXT6000P },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, gxt4500_pci_tbl);
-
-static struct pci_driver gxt4500_driver = {
-	.name = "gxt4500",
-	.id_table = gxt4500_pci_tbl,
-	.probe = gxt4500_probe,
-	.remove = gxt4500_remove,
-};
-
-static int gxt4500_init(void)
-{
-#ifndef MODULE
-	if (fb_get_options("gxt4500", &mode_option))
-		return -ENODEV;
-#endif
-
-	return pci_register_driver(&gxt4500_driver);
-}
-module_init(gxt4500_init);
-
-static void __exit gxt4500_exit(void)
-{
-	pci_unregister_driver(&gxt4500_driver);
-}
-module_exit(gxt4500_exit);
-
-MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
-MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P/6500P and GXT4000P/6000P");
-MODULE_LICENSE("GPL");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
deleted file mode 100644
index f64120ec9192..000000000000
--- a/drivers/video/hecubafb.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * linux/drivers/video/hecubafb.c -- FB driver for Hecuba/Apollo controller
- *
- * Copyright (C) 2006, Jaya Kumar
- * This work was sponsored by CIS(M) Sdn Bhd
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- * This work was possible because of apollo display code from E-Ink's website
- * http://support.eink.com/community
- * All information used to write this code is from public material made
- * available by E-Ink on its support site. Some commands such as 0xA4
- * were found by looping through cmd=0x00 thru 0xFF and supplying random
- * values. There are other commands that the display is capable of,
- * beyond the 5 used here but they are more complex.
- *
- * This driver is written to be used with the Hecuba display architecture.
- * The actual display chip is called Apollo and the interface electronics
- * it needs is called Hecuba.
- *
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions. An example
- * is provided as n411.c
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/uaccess.h>
-
-#include <video/hecubafb.h>
-
-/* Display specific information */
-#define DPY_W 600
-#define DPY_H 800
-
-static struct fb_fix_screeninfo hecubafb_fix = {
-	.id =		"hecubafb",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_MONO01,
-	.xpanstep =	0,
-	.ypanstep =	0,
-	.ywrapstep =	0,
-	.line_length =	DPY_W,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo hecubafb_var = {
-	.xres		= DPY_W,
-	.yres		= DPY_H,
-	.xres_virtual	= DPY_W,
-	.yres_virtual	= DPY_H,
-	.bits_per_pixel	= 1,
-	.nonstd		= 1,
-};
-
-/* main hecubafb functions */
-
-static void apollo_send_data(struct hecubafb_par *par, unsigned char data)
-{
-	/* set data */
-	par->board->set_data(par, data);
-
-	/* set DS low */
-	par->board->set_ctl(par, HCB_DS_BIT, 0);
-
-	/* wait for ack */
-	par->board->wait_for_ack(par, 0);
-
-	/* set DS hi */
-	par->board->set_ctl(par, HCB_DS_BIT, 1);
-
-	/* wait for ack to clear */
-	par->board->wait_for_ack(par, 1);
-}
-
-static void apollo_send_command(struct hecubafb_par *par, unsigned char data)
-{
-	/* command so set CD to high */
-	par->board->set_ctl(par, HCB_CD_BIT, 1);
-
-	/* actually strobe with command */
-	apollo_send_data(par, data);
-
-	/* clear CD back to low */
-	par->board->set_ctl(par, HCB_CD_BIT, 0);
-}
-
-static void hecubafb_dpy_update(struct hecubafb_par *par)
-{
-	int i;
-	unsigned char *buf = (unsigned char __force *)par->info->screen_base;
-
-	apollo_send_command(par, APOLLO_START_NEW_IMG);
-
-	for (i=0; i < (DPY_W*DPY_H/8); i++) {
-		apollo_send_data(par, *(buf++));
-	}
-
-	apollo_send_command(par, APOLLO_STOP_IMG_DATA);
-	apollo_send_command(par, APOLLO_DISPLAY_IMG);
-}
-
-/* this is called back from the deferred io workqueue */
-static void hecubafb_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	hecubafb_dpy_update(info->par);
-}
-
-static void hecubafb_fillrect(struct fb_info *info,
-				   const struct fb_fillrect *rect)
-{
-	struct hecubafb_par *par = info->par;
-
-	sys_fillrect(info, rect);
-
-	hecubafb_dpy_update(par);
-}
-
-static void hecubafb_copyarea(struct fb_info *info,
-				   const struct fb_copyarea *area)
-{
-	struct hecubafb_par *par = info->par;
-
-	sys_copyarea(info, area);
-
-	hecubafb_dpy_update(par);
-}
-
-static void hecubafb_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	struct hecubafb_par *par = info->par;
-
-	sys_imageblit(info, image);
-
-	hecubafb_dpy_update(par);
-}
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it's inefficient to do anything less than a full screen draw
- */
-static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	struct hecubafb_par *par = info->par;
-	unsigned long p = *ppos;
-	void *dst;
-	int err = 0;
-	unsigned long total_size;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EFBIG;
-
-	if (count > total_size) {
-		err = -EFBIG;
-		count = total_size;
-	}
-
-	if (count + p > total_size) {
-		if (!err)
-			err = -ENOSPC;
-
-		count = total_size - p;
-	}
-
-	dst = (void __force *) (info->screen_base + p);
-
-	if (copy_from_user(dst, buf, count))
-		err = -EFAULT;
-
-	if  (!err)
-		*ppos += count;
-
-	hecubafb_dpy_update(par);
-
-	return (err) ? err : count;
-}
-
-static struct fb_ops hecubafb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_read        = fb_sys_read,
-	.fb_write	= hecubafb_write,
-	.fb_fillrect	= hecubafb_fillrect,
-	.fb_copyarea	= hecubafb_copyarea,
-	.fb_imageblit	= hecubafb_imageblit,
-};
-
-static struct fb_deferred_io hecubafb_defio = {
-	.delay		= HZ,
-	.deferred_io	= hecubafb_dpy_deferred_io,
-};
-
-static int hecubafb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	struct hecuba_board *board;
-	int retval = -ENOMEM;
-	int videomemorysize;
-	unsigned char *videomemory;
-	struct hecubafb_par *par;
-
-	/* pick up board specific routines */
-	board = dev->dev.platform_data;
-	if (!board)
-		return -EINVAL;
-
-	/* try to count device specific driver, if can't, platform recalls */
-	if (!try_module_get(board->owner))
-		return -ENODEV;
-
-	videomemorysize = (DPY_W*DPY_H)/8;
-
-	videomemory = vzalloc(videomemorysize);
-	if (!videomemory)
-		goto err_videomem_alloc;
-
-	info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
-	if (!info)
-		goto err_fballoc;
-
-	info->screen_base = (char __force __iomem *)videomemory;
-	info->fbops = &hecubafb_ops;
-
-	info->var = hecubafb_var;
-	info->fix = hecubafb_fix;
-	info->fix.smem_len = videomemorysize;
-	par = info->par;
-	par->info = info;
-	par->board = board;
-	par->send_command = apollo_send_command;
-	par->send_data = apollo_send_data;
-
-	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
-
-	info->fbdefio = &hecubafb_defio;
-	fb_deferred_io_init(info);
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err_fbreg;
-	platform_set_drvdata(dev, info);
-
-	fb_info(info, "Hecuba frame buffer device, using %dK of video memory\n",
-		videomemorysize >> 10);
-
-	/* this inits the dpy */
-	retval = par->board->init(par);
-	if (retval < 0)
-		goto err_fbreg;
-
-	return 0;
-err_fbreg:
-	framebuffer_release(info);
-err_fballoc:
-	vfree(videomemory);
-err_videomem_alloc:
-	module_put(board->owner);
-	return retval;
-}
-
-static int hecubafb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		struct hecubafb_par *par = info->par;
-		fb_deferred_io_cleanup(info);
-		unregister_framebuffer(info);
-		vfree((void __force *)info->screen_base);
-		if (par->board->remove)
-			par->board->remove(par);
-		module_put(par->board->owner);
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-static struct platform_driver hecubafb_driver = {
-	.probe	= hecubafb_probe,
-	.remove = hecubafb_remove,
-	.driver	= {
-		.owner	= THIS_MODULE,
-		.name	= "hecubafb",
-	},
-};
-module_platform_driver(hecubafb_driver);
-
-MODULE_DESCRIPTION("fbdev driver for Hecuba/Apollo controller");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
deleted file mode 100644
index 5ff9fe2116a4..000000000000
--- a/drivers/video/hgafb.c
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * linux/drivers/video/hgafb.c -- Hercules graphics adaptor frame buffer device
- * 
- *      Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu)
- *      Based on skeletonfb.c by Geert Uytterhoeven and
- *               mdacon.c by Andrew Apted
- *
- * History:
- *
- * - Revision 0.1.8 (23 Oct 2002): Ported to new framebuffer api.
- * 
- * - Revision 0.1.7 (23 Jan 2001): fix crash resulting from MDA only cards 
- *				   being detected as Hercules.	 (Paul G.)
- * - Revision 0.1.6 (17 Aug 2000): new style structs
- *                                 documentation
- * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
- *                                 minor fixes
- * - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for 
- *                                  HGA-only systems
- * - Revision 0.1.3 (22 Jan 2000): modified for the new fb_info structure
- *                                 screen is cleared after rmmod
- *                                 virtual resolutions
- *                                 module parameter 'nologo={0|1}'
- *                                 the most important: boot logo :)
- * - Revision 0.1.0  (6 Dec 1999): faster scrolling and minor fixes
- * - First release  (25 Nov 1999)
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/io.h>
-#include <asm/vga.h>
-
-#if 0
-#define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args)
-#else
-#define DPRINTK(args...)
-#endif
-
-#if 0
-#define CHKINFO(ret) if (info != &fb_info) { printk(KERN_DEBUG __FILE__": This should never happen, line:%d \n", __LINE__); return ret; }
-#else
-#define CHKINFO(ret)
-#endif
-
-/* Description of the hardware layout */
-
-static void __iomem *hga_vram;			/* Base of video memory */
-static unsigned long hga_vram_len;		/* Size of video memory */
-
-#define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90)
-#define HGA_TXT			0
-#define HGA_GFX			1
-
-static inline u8 __iomem * rowaddr(struct fb_info *info, u_int row)
-{
-	return info->screen_base + HGA_ROWADDR(row);
-}
-
-static int hga_mode = -1;			/* 0 = txt, 1 = gfx mode */
-
-static enum { TYPE_HERC, TYPE_HERCPLUS, TYPE_HERCCOLOR } hga_type;
-static char *hga_type_name;
-
-#define HGA_INDEX_PORT		0x3b4		/* Register select port */
-#define HGA_VALUE_PORT		0x3b5		/* Register value port */
-#define HGA_MODE_PORT		0x3b8		/* Mode control port */
-#define HGA_STATUS_PORT		0x3ba		/* Status and Config port */
-#define HGA_GFX_PORT		0x3bf		/* Graphics control port */
-
-/* HGA register values */
-
-#define HGA_CURSOR_BLINKING	0x00
-#define HGA_CURSOR_OFF		0x20
-#define HGA_CURSOR_SLOWBLINK	0x60
-
-#define HGA_MODE_GRAPHICS	0x02
-#define HGA_MODE_VIDEO_EN	0x08
-#define HGA_MODE_BLINK_EN	0x20
-#define HGA_MODE_GFX_PAGE1	0x80
-
-#define HGA_STATUS_HSYNC	0x01
-#define HGA_STATUS_VSYNC	0x80
-#define HGA_STATUS_VIDEO	0x08
-
-#define HGA_CONFIG_COL132	0x08
-#define HGA_GFX_MODE_EN		0x01
-#define HGA_GFX_PAGE_EN		0x02
-
-/* Global locks */
-
-static DEFINE_SPINLOCK(hga_reg_lock);
-
-/* Framebuffer driver structures */
-
-static struct fb_var_screeninfo hga_default_var = {
-	.xres		= 720,
-	.yres 		= 348,
-	.xres_virtual 	= 720,
-	.yres_virtual	= 348,
-	.bits_per_pixel = 1,
-	.red 		= {0, 1, 0},
-	.green 		= {0, 1, 0},
-	.blue 		= {0, 1, 0},
-	.transp 	= {0, 0, 0},
-	.height 	= -1,
-	.width 		= -1,
-};
-
-static struct fb_fix_screeninfo hga_fix = {
-	.id 		= "HGA",
-	.type 		= FB_TYPE_PACKED_PIXELS,	/* (not sure) */
-	.visual 	= FB_VISUAL_MONO10,
-	.xpanstep 	= 8,
-	.ypanstep 	= 8,
-	.line_length 	= 90,
-	.accel 		= FB_ACCEL_NONE
-};
-
-/* Don't assume that tty1 will be the initial current console. */
-static int release_io_port = 0;
-static int release_io_ports = 0;
-static bool nologo = 0;
-
-/* -------------------------------------------------------------------------
- *
- * Low level hardware functions
- *
- * ------------------------------------------------------------------------- */
-
-static void write_hga_b(unsigned int val, unsigned char reg)
-{
-	outb_p(reg, HGA_INDEX_PORT); 
-	outb_p(val, HGA_VALUE_PORT);
-}
-
-static void write_hga_w(unsigned int val, unsigned char reg)
-{
-	outb_p(reg,   HGA_INDEX_PORT); outb_p(val >> 8,   HGA_VALUE_PORT);
-	outb_p(reg+1, HGA_INDEX_PORT); outb_p(val & 0xff, HGA_VALUE_PORT);
-}
-
-static int test_hga_b(unsigned char val, unsigned char reg)
-{
-	outb_p(reg, HGA_INDEX_PORT); 
-	outb  (val, HGA_VALUE_PORT);
-	udelay(20); val = (inb_p(HGA_VALUE_PORT) == val);
-	return val;
-}
-
-static void hga_clear_screen(void)
-{
-	unsigned char fillchar = 0xbf; /* magic */
-	unsigned long flags;
-
-	spin_lock_irqsave(&hga_reg_lock, flags);
-	if (hga_mode == HGA_TXT)
-		fillchar = ' ';
-	else if (hga_mode == HGA_GFX)
-		fillchar = 0x00;
-	spin_unlock_irqrestore(&hga_reg_lock, flags);
-	if (fillchar != 0xbf)
-		memset_io(hga_vram, fillchar, hga_vram_len);
-}
-
-static void hga_txt_mode(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hga_reg_lock, flags);
-	outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_BLINK_EN, HGA_MODE_PORT);
-	outb_p(0x00, HGA_GFX_PORT);
-	outb_p(0x00, HGA_STATUS_PORT);
-
-	write_hga_b(0x61, 0x00);	/* horizontal total */
-	write_hga_b(0x50, 0x01);	/* horizontal displayed */
-	write_hga_b(0x52, 0x02);	/* horizontal sync pos */
-	write_hga_b(0x0f, 0x03);	/* horizontal sync width */
-
-	write_hga_b(0x19, 0x04);	/* vertical total */
-	write_hga_b(0x06, 0x05);	/* vertical total adjust */
-	write_hga_b(0x19, 0x06);	/* vertical displayed */
-	write_hga_b(0x19, 0x07);	/* vertical sync pos */
-
-	write_hga_b(0x02, 0x08);	/* interlace mode */
-	write_hga_b(0x0d, 0x09);	/* maximum scanline */
-	write_hga_b(0x0c, 0x0a);	/* cursor start */
-	write_hga_b(0x0d, 0x0b);	/* cursor end */
-
-	write_hga_w(0x0000, 0x0c);	/* start address */
-	write_hga_w(0x0000, 0x0e);	/* cursor location */
-
-	hga_mode = HGA_TXT;
-	spin_unlock_irqrestore(&hga_reg_lock, flags);
-}
-
-static void hga_gfx_mode(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hga_reg_lock, flags);
-	outb_p(0x00, HGA_STATUS_PORT);
-	outb_p(HGA_GFX_MODE_EN, HGA_GFX_PORT);
-	outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
-
-	write_hga_b(0x35, 0x00);	/* horizontal total */
-	write_hga_b(0x2d, 0x01);	/* horizontal displayed */
-	write_hga_b(0x2e, 0x02);	/* horizontal sync pos */
-	write_hga_b(0x07, 0x03);	/* horizontal sync width */
-
-	write_hga_b(0x5b, 0x04);	/* vertical total */
-	write_hga_b(0x02, 0x05);	/* vertical total adjust */
-	write_hga_b(0x57, 0x06);	/* vertical displayed */
-	write_hga_b(0x57, 0x07);	/* vertical sync pos */
-
-	write_hga_b(0x02, 0x08);	/* interlace mode */
-	write_hga_b(0x03, 0x09);	/* maximum scanline */
-	write_hga_b(0x00, 0x0a);	/* cursor start */
-	write_hga_b(0x00, 0x0b);	/* cursor end */
-
-	write_hga_w(0x0000, 0x0c);	/* start address */
-	write_hga_w(0x0000, 0x0e);	/* cursor location */
-
-	hga_mode = HGA_GFX;
-	spin_unlock_irqrestore(&hga_reg_lock, flags);
-}
-
-static void hga_show_logo(struct fb_info *info)
-{
-/*
-	void __iomem *dest = hga_vram;
-	char *logo = linux_logo_bw;
-	int x, y;
-	
-	for (y = 134; y < 134 + 80 ; y++) * this needs some cleanup *
-		for (x = 0; x < 10 ; x++)
-			writeb(~*(logo++),(dest + HGA_ROWADDR(y) + x + 40));
-*/
-}
-
-static void hga_pan(unsigned int xoffset, unsigned int yoffset)
-{
-	unsigned int base;
-	unsigned long flags;
-	
-	base = (yoffset / 8) * 90 + xoffset;
-	spin_lock_irqsave(&hga_reg_lock, flags);
-	write_hga_w(base, 0x0c);	/* start address */
-	spin_unlock_irqrestore(&hga_reg_lock, flags);
-	DPRINTK("hga_pan: base:%d\n", base);
-}
-
-static void hga_blank(int blank_mode)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hga_reg_lock, flags);
-	if (blank_mode) {
-		outb_p(0x00, HGA_MODE_PORT);	/* disable video */
-	} else {
-		outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
-	}
-	spin_unlock_irqrestore(&hga_reg_lock, flags);
-}
-
-static int hga_card_detect(void)
-{
-	int count = 0;
-	void __iomem *p, *q;
-	unsigned short p_save, q_save;
-
-	hga_vram_len  = 0x08000;
-
-	hga_vram = ioremap(0xb0000, hga_vram_len);
-
-	if (request_region(0x3b0, 12, "hgafb"))
-		release_io_ports = 1;
-	if (request_region(0x3bf, 1, "hgafb"))
-		release_io_port = 1;
-
-	/* do a memory check */
-
-	p = hga_vram;
-	q = hga_vram + 0x01000;
-
-	p_save = readw(p); q_save = readw(q);
-
-	writew(0xaa55, p); if (readw(p) == 0xaa55) count++;
-	writew(0x55aa, p); if (readw(p) == 0x55aa) count++;
-	writew(p_save, p);
-
-	if (count != 2)
-		goto error;
-
-	/* Ok, there is definitely a card registering at the correct
-	 * memory location, so now we do an I/O port test.
-	 */
-	
-	if (!test_hga_b(0x66, 0x0f))	    /* cursor low register */
-		goto error;
-
-	if (!test_hga_b(0x99, 0x0f))     /* cursor low register */
-		goto error;
-
-	/* See if the card is a Hercules, by checking whether the vsync
-	 * bit of the status register is changing.  This test lasts for
-	 * approximately 1/10th of a second.
-	 */
-	
-	p_save = q_save = inb_p(HGA_STATUS_PORT) & HGA_STATUS_VSYNC;
-
-	for (count=0; count < 50000 && p_save == q_save; count++) {
-		q_save = inb(HGA_STATUS_PORT) & HGA_STATUS_VSYNC;
-		udelay(2);
-	}
-
-	if (p_save == q_save) 
-		goto error;
-
-	switch (inb_p(HGA_STATUS_PORT) & 0x70) {
-		case 0x10:
-			hga_type = TYPE_HERCPLUS;
-			hga_type_name = "HerculesPlus";
-			break;
-		case 0x50:
-			hga_type = TYPE_HERCCOLOR;
-			hga_type_name = "HerculesColor";
-			break;
-		default:
-			hga_type = TYPE_HERC;
-			hga_type_name = "Hercules";
-			break;
-	}
-	return 1;
-error:
-	if (release_io_ports)
-		release_region(0x3b0, 12);
-	if (release_io_port)
-		release_region(0x3bf, 1);
-	return 0;
-}
-
-/**
- *	hgafb_open - open the framebuffer device
- *	@info:pointer to fb_info object containing info for current hga board
- *	@int:open by console system or userland.
- */
-
-static int hgafb_open(struct fb_info *info, int init)
-{
-	hga_gfx_mode();
-	hga_clear_screen();
-	if (!nologo) hga_show_logo(info);
-	return 0;
-}
-
-/**
- *	hgafb_open - open the framebuffer device
- *	@info:pointer to fb_info object containing info for current hga board
- *	@int:open by console system or userland.
- */
-
-static int hgafb_release(struct fb_info *info, int init)
-{
-	hga_txt_mode();
-	hga_clear_screen();
-	return 0;
-}
-
-/**
- *	hgafb_setcolreg - set color registers
- *	@regno:register index to set
- *	@red:red value, unused
- *	@green:green value, unused
- *	@blue:blue value, unused
- *	@transp:transparency value, unused
- *	@info:unused
- *
- *	This callback function is used to set the color registers of a HGA
- *	board. Since we have only two fixed colors only @regno is checked.
- *	A zero is returned on success and 1 for failure.
- */
-
-static int hgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	if (regno > 1)
-		return 1;
-	return 0;
-}
-
-/**
- *	hga_pan_display - pan or wrap the display
- *	@var:contains new xoffset, yoffset and vmode values
- *	@info:pointer to fb_info object containing info for current hga board
- *
- *	This function looks only at xoffset, yoffset and the %FB_VMODE_YWRAP
- *	flag in @var. If input parameters are correct it calls hga_pan() to 
- *	program the hardware. @info->var is updated to the new values.
- *	A zero is returned on success and %-EINVAL for failure.
- */
-
-static int hgafb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 || 
-		    var->yoffset >= info->var.yres_virtual ||
-		    var->xoffset)
-			return -EINVAL;
-	} else {
-		if (var->xoffset + info->var.xres > info->var.xres_virtual
-		 || var->yoffset + info->var.yres > info->var.yres_virtual
-		 || var->yoffset % 8)
-			return -EINVAL;
-	}
-
-	hga_pan(var->xoffset, var->yoffset);
-	return 0;
-}
-
-/**
- *	hgafb_blank - (un)blank the screen
- *	@blank_mode:blanking method to use
- *	@info:unused
- *	
- *	Blank the screen if blank_mode != 0, else unblank. 
- *	Implements VESA suspend and powerdown modes on hardware that supports 
- *	disabling hsync/vsync:
- *		@blank_mode == 2 means suspend vsync,
- *		@blank_mode == 3 means suspend hsync,
- *		@blank_mode == 4 means powerdown.
- */
-
-static int hgafb_blank(int blank_mode, struct fb_info *info)
-{
-	hga_blank(blank_mode);
-	return 0;
-}
-
-/*
- * Accel functions
- */
-static void hgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	u_int rows, y;
-	u8 __iomem *dest;
-
-	y = rect->dy;
-
-	for (rows = rect->height; rows--; y++) {
-		dest = rowaddr(info, y) + (rect->dx >> 3);
-		switch (rect->rop) {
-		case ROP_COPY:
-			memset_io(dest, rect->color, (rect->width >> 3));
-			break;
-		case ROP_XOR:
-			fb_writeb(~(fb_readb(dest)), dest);
-			break;
-		}
-	}
-}
-
-static void hgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	u_int rows, y1, y2;
-	u8 __iomem *src;
-	u8 __iomem *dest;
-
-	if (area->dy <= area->sy) {
-		y1 = area->sy;
-		y2 = area->dy;
-
-		for (rows = area->height; rows--; ) {
-			src = rowaddr(info, y1) + (area->sx >> 3);
-			dest = rowaddr(info, y2) + (area->dx >> 3);
-			memmove(dest, src, (area->width >> 3));
-			y1++;
-			y2++;
-		}
-	} else {
-		y1 = area->sy + area->height - 1;
-		y2 = area->dy + area->height - 1;
-
-		for (rows = area->height; rows--;) {
-			src = rowaddr(info, y1) + (area->sx >> 3);
-			dest = rowaddr(info, y2) + (area->dx >> 3);
-			memmove(dest, src, (area->width >> 3));
-			y1--;
-			y2--;
-		}
-	}
-}
-
-static void hgafb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	u8 __iomem *dest;
-	u8 *cdat = (u8 *) image->data;
-	u_int rows, y = image->dy;
-	u_int x;
-	u8 d;
-
-	for (rows = image->height; rows--; y++) {
-		for (x = 0; x < image->width; x+= 8) {
-			d = *cdat++;
-			dest = rowaddr(info, y) + ((image->dx + x)>> 3);
-			fb_writeb(d, dest);
-		}
-	}
-}
-
-static struct fb_ops hgafb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= hgafb_open,
-	.fb_release	= hgafb_release,
-	.fb_setcolreg	= hgafb_setcolreg,
-	.fb_pan_display	= hgafb_pan_display,
-	.fb_blank	= hgafb_blank,
-	.fb_fillrect	= hgafb_fillrect,
-	.fb_copyarea	= hgafb_copyarea,
-	.fb_imageblit	= hgafb_imageblit,
-};
-		
-/* ------------------------------------------------------------------------- *
- *
- * Functions in fb_info
- * 
- * ------------------------------------------------------------------------- */
-
-/* ------------------------------------------------------------------------- */
-    
-	/*
-	 *  Initialization
-	 */
-
-static int hgafb_probe(struct platform_device *pdev)
-{
-	struct fb_info *info;
-
-	if (! hga_card_detect()) {
-		printk(KERN_INFO "hgafb: HGA card not detected.\n");
-		if (hga_vram)
-			iounmap(hga_vram);
-		return -EINVAL;
-	}
-
-	printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
-		hga_type_name, hga_vram_len/1024);
-
-	info = framebuffer_alloc(0, &pdev->dev);
-	if (!info) {
-		iounmap(hga_vram);
-		return -ENOMEM;
-	}
-
-	hga_fix.smem_start = (unsigned long)hga_vram;
-	hga_fix.smem_len = hga_vram_len;
-
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	info->var = hga_default_var;
-	info->fix = hga_fix;
-	info->monspecs.hfmin = 0;
-	info->monspecs.hfmax = 0;
-	info->monspecs.vfmin = 10000;
-	info->monspecs.vfmax = 10000;
-	info->monspecs.dpms = 0;
-	info->fbops = &hgafb_ops;
-	info->screen_base = hga_vram;
-
-        if (register_framebuffer(info) < 0) {
-		framebuffer_release(info);
-		iounmap(hga_vram);
-		return -EINVAL;
-	}
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	platform_set_drvdata(pdev, info);
-	return 0;
-}
-
-static int hgafb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-
-	hga_txt_mode();
-	hga_clear_screen();
-
-	if (info) {
-		unregister_framebuffer(info);
-		framebuffer_release(info);
-	}
-
-	iounmap(hga_vram);
-
-	if (release_io_ports)
-		release_region(0x3b0, 12);
-
-	if (release_io_port)
-		release_region(0x3bf, 1);
-
-	return 0;
-}
-
-static struct platform_driver hgafb_driver = {
-	.probe = hgafb_probe,
-	.remove = hgafb_remove,
-	.driver = {
-		.name = "hgafb",
-	},
-};
-
-static struct platform_device *hgafb_device;
-
-static int __init hgafb_init(void)
-{
-	int ret;
-
-	if (fb_get_options("hgafb", NULL))
-		return -ENODEV;
-
-	ret = platform_driver_register(&hgafb_driver);
-
-	if (!ret) {
-		hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0);
-
-		if (IS_ERR(hgafb_device)) {
-			platform_driver_unregister(&hgafb_driver);
-			ret = PTR_ERR(hgafb_device);
-		}
-	}
-
-	return ret;
-}
-
-static void __exit hgafb_exit(void)
-{
-	platform_device_unregister(hgafb_device);
-	platform_driver_unregister(&hgafb_driver);
-}
-
-/* -------------------------------------------------------------------------
- *
- *  Modularization
- *
- * ------------------------------------------------------------------------- */
-
-MODULE_AUTHOR("Ferenc Bakonyi (fero@drama.obuda.kando.hu)");
-MODULE_DESCRIPTION("FBDev driver for Hercules Graphics Adaptor");
-MODULE_LICENSE("GPL");
-
-module_param(nologo, bool, 0);
-MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
-module_init(hgafb_init);
-module_exit(hgafb_exit);
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
deleted file mode 100644
index a648d5186c6e..000000000000
--- a/drivers/video/hitfb.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device
- *
- * (C) 1999 Mihai Spatar
- * (C) 2000 YAEGASHI Takeshi
- * (C) 2003, 2004 Paul Mundt
- * (C) 2003, 2004, 2006 Andriy Skulysh
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-
-#include <asm/machvec.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/hd64461.h>
-#include <cpu/dac.h>
-
-#define	WIDTH 640
-
-static struct fb_var_screeninfo hitfb_var = {
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo hitfb_fix = {
-	.id		= "Hitachi HD64461",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static inline void hitfb_accel_wait(void)
-{
-	while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ;
-}
-
-static inline void hitfb_accel_start(int truecolor)
-{
-	if (truecolor) {
-		fb_writew(6, HD64461_GRCFGR);
-	} else {
-		fb_writew(7, HD64461_GRCFGR);
-	}
-}
-
-static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy,
-					u16 width, u16 height)
-{
-	u32 saddr = WIDTH * dy + dx;
-	if (truecolor)
-		saddr <<= 1;
-
-	fb_writew(width-1, HD64461_BBTDWR);
-	fb_writew(height-1, HD64461_BBTDHR);
-
-	fb_writew(saddr & 0xffff, HD64461_BBTDSARL);
-	fb_writew(saddr >> 16, HD64461_BBTDSARH);
-
-}
-
-static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
-				      u16 dy, u16 width, u16 height, u16 rop,
-				      u32 mask_addr)
-{
-	u32 saddr, daddr;
-	u32 maddr = 0;
-
-	height--;
-	width--;
-	fb_writew(rop, HD64461_BBTROPR);
-	if ((sy < dy) || ((sy == dy) && (sx <= dx))) {
-		saddr = WIDTH * (sy + height) + sx + width;
-		daddr = WIDTH * (dy + height) + dx + width;
-		if (mask_addr) {
-			if (truecolor)
-				maddr = ((width >> 3) + 1) * (height + 1) - 1;
-			else
-				maddr =
-				    (((width >> 4) + 1) * (height + 1) - 1) * 2;
-
-			fb_writew((1 << 5) | 1, HD64461_BBTMDR);
-		} else
-			fb_writew(1, HD64461_BBTMDR);
-	} else {
-		saddr = WIDTH * sy + sx;
-		daddr = WIDTH * dy + dx;
-		if (mask_addr) {
-			fb_writew((1 << 5), HD64461_BBTMDR);
-		} else {
-			fb_writew(0, HD64461_BBTMDR);
-		}
-	}
-	if (truecolor) {
-		saddr <<= 1;
-		daddr <<= 1;
-	}
-	fb_writew(width, HD64461_BBTDWR);
-	fb_writew(height, HD64461_BBTDHR);
-	fb_writew(saddr & 0xffff, HD64461_BBTSSARL);
-	fb_writew(saddr >> 16, HD64461_BBTSSARH);
-	fb_writew(daddr & 0xffff, HD64461_BBTDSARL);
-	fb_writew(daddr >> 16, HD64461_BBTDSARH);
-	if (mask_addr) {
-		maddr += mask_addr;
-		fb_writew(maddr & 0xffff, HD64461_BBTMARL);
-		fb_writew(maddr >> 16, HD64461_BBTMARH);
-	}
-	hitfb_accel_start(truecolor);
-}
-
-static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
-{
-	if (rect->rop != ROP_COPY)
-		cfb_fillrect(p, rect);
-	else {
-		hitfb_accel_wait();
-		fb_writew(0x00f0, HD64461_BBTROPR);
-		fb_writew(16, HD64461_BBTMDR);
-
-		if (p->var.bits_per_pixel == 16) {
-			fb_writew(((u32 *) (p->pseudo_palette))[rect->color],
-				  HD64461_GRSCR);
-			hitfb_accel_set_dest(1, rect->dx, rect->dy, rect->width,
-					     rect->height);
-			hitfb_accel_start(1);
-		} else {
-			fb_writew(rect->color, HD64461_GRSCR);
-			hitfb_accel_set_dest(0, rect->dx, rect->dy, rect->width,
-					     rect->height);
-			hitfb_accel_start(0);
-		}
-	}
-}
-
-static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
-{
-	hitfb_accel_wait();
-	hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy,
-			   area->dx, area->dy, area->width, area->height,
-			   0x00cc, 0);
-}
-
-static int hitfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	int xoffset = var->xoffset;
-	int yoffset = var->yoffset;
-
-	if (xoffset != 0)
-		return -EINVAL;
-
-	fb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR);
-
-	return 0;
-}
-
-int hitfb_blank(int blank_mode, struct fb_info *info)
-{
-	unsigned short v;
-
-	if (blank_mode) {
-		v = fb_readw(HD64461_LDR1);
-		v &= ~HD64461_LDR1_DON;
-		fb_writew(v, HD64461_LDR1);
-
-		v = fb_readw(HD64461_LCDCCR);
-		v |= HD64461_LCDCCR_MOFF;
-		fb_writew(v, HD64461_LCDCCR);
-
-		v = fb_readw(HD64461_STBCR);
-		v |= HD64461_STBCR_SLCDST;
-		fb_writew(v, HD64461_STBCR);
-	} else {
-		v = fb_readw(HD64461_STBCR);
-		v &= ~HD64461_STBCR_SLCDST;
-		fb_writew(v, HD64461_STBCR);
-
-		v = fb_readw(HD64461_LCDCCR);
-		v &= ~(HD64461_LCDCCR_MOFF | HD64461_LCDCCR_STREQ);
-		fb_writew(v, HD64461_LCDCCR);
-
-		do {
-		    v = fb_readw(HD64461_LCDCCR);
-		} while(v&HD64461_LCDCCR_STBACK);
-
-		v = fb_readw(HD64461_LDR1);
-		v |= HD64461_LDR1_DON;
-		fb_writew(v, HD64461_LDR1);
-	}
-	return 0;
-}
-
-static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp, struct fb_info *info)
-{
-	if (regno >= 256)
-		return 1;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		fb_writew(regno << 8, HD64461_CPTWAR);
-		fb_writew(red >> 10, HD64461_CPTWDR);
-		fb_writew(green >> 10, HD64461_CPTWDR);
-		fb_writew(blue >> 10, HD64461_CPTWDR);
-		break;
-	case 16:
-		if (regno >= 16)
-			return 1;
-		((u32 *) (info->pseudo_palette))[regno] =
-		    ((red & 0xf800)) |
-		    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
-		break;
-	}
-	return 0;
-}
-
-static int hitfb_sync(struct fb_info *info)
-{
-	hitfb_accel_wait();
-
-	return 0;
-}
-
-static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int maxy;
-
-	var->xres = info->var.xres;
-	var->xres_virtual = info->var.xres;
-	var->yres = info->var.yres;
-
-	if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16))
-		var->bits_per_pixel = info->var.bits_per_pixel;
-
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	maxy = info->fix.smem_len / var->xres;
-
-	if (var->bits_per_pixel == 16)
-		maxy /= 2;
-
-	if (var->yres_virtual > maxy)
-		var->yres_virtual = maxy;
-
-	var->xoffset = 0;
-	var->yoffset = 0;
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:		/* RGB 565 */
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	}
-
-	return 0;
-}
-
-static int hitfb_set_par(struct fb_info *info)
-{
-	unsigned short ldr3;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		info->fix.line_length = info->var.xres;
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		info->fix.ypanstep = 16;
-		break;
-	case 16:
-		info->fix.line_length = info->var.xres*2;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		info->fix.ypanstep = 8;
-		break;
-	}
-
-	fb_writew(info->fix.line_length, HD64461_LCDCLOR);
-	ldr3 = fb_readw(HD64461_LDR3);
-	ldr3 &= ~15;
-	ldr3 |= (info->var.bits_per_pixel == 8) ? 4 : 8;
-	fb_writew(ldr3, HD64461_LDR3);
-	return 0;
-}
-
-static struct fb_ops hitfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= hitfb_check_var,
-	.fb_set_par		= hitfb_set_par,
-	.fb_setcolreg	= hitfb_setcolreg,
-	.fb_blank	= hitfb_blank,
-	.fb_sync	= hitfb_sync,
-	.fb_pan_display = hitfb_pan_display,
-	.fb_fillrect	= hitfb_fillrect,
-	.fb_copyarea	= hitfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int hitfb_probe(struct platform_device *dev)
-{
-	unsigned short lcdclor, ldr3, ldvndr;
-	struct fb_info *info;
-	int ret;
-
-	if (fb_get_options("hitfb", NULL))
-		return -ENODEV;
-
-	hitfb_fix.mmio_start = HD64461_IO_OFFSET(0x1000);
-	hitfb_fix.mmio_len = 0x1000;
-	hitfb_fix.smem_start = HD64461_IO_OFFSET(0x02000000);
-	hitfb_fix.smem_len = 512 * 1024;
-
-	lcdclor = fb_readw(HD64461_LCDCLOR);
-	ldvndr = fb_readw(HD64461_LDVNDR);
-	ldr3 = fb_readw(HD64461_LDR3);
-
-	switch (ldr3 & 15) {
-	default:
-	case 4:
-		hitfb_var.bits_per_pixel = 8;
-		hitfb_var.xres = lcdclor;
-		break;
-	case 8:
-		hitfb_var.bits_per_pixel = 16;
-		hitfb_var.xres = lcdclor / 2;
-		break;
-	}
-	hitfb_fix.line_length = lcdclor;
-	hitfb_fix.visual = (hitfb_var.bits_per_pixel == 8) ?
-	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	hitfb_var.yres = ldvndr + 1;
-	hitfb_var.xres_virtual = hitfb_var.xres;
-	hitfb_var.yres_virtual = hitfb_fix.smem_len / lcdclor;
-	switch (hitfb_var.bits_per_pixel) {
-	case 8:
-		hitfb_var.red.offset = 0;
-		hitfb_var.red.length = 8;
-		hitfb_var.green.offset = 0;
-		hitfb_var.green.length = 8;
-		hitfb_var.blue.offset = 0;
-		hitfb_var.blue.length = 8;
-		hitfb_var.transp.offset = 0;
-		hitfb_var.transp.length = 0;
-		break;
-	case 16:		/* RGB 565 */
-		hitfb_var.red.offset = 11;
-		hitfb_var.red.length = 5;
-		hitfb_var.green.offset = 5;
-		hitfb_var.green.length = 6;
-		hitfb_var.blue.offset = 0;
-		hitfb_var.blue.length = 5;
-		hitfb_var.transp.offset = 0;
-		hitfb_var.transp.length = 0;
-		break;
-	}
-
-	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
-	if (unlikely(!info))
-		return -ENOMEM;
-
-	info->fbops = &hitfb_ops;
-	info->var = hitfb_var;
-	info->fix = hitfb_fix;
-	info->pseudo_palette = info->par;
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
-		FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
-
-	info->screen_base = (void *)hitfb_fix.smem_start;
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (unlikely(ret < 0))
-		goto err_fb;
-
-	ret = register_framebuffer(info);
-	if (unlikely(ret < 0))
-		goto err;
-
-	platform_set_drvdata(dev, info);
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	return 0;
-
-err:
-	fb_dealloc_cmap(&info->cmap);
-err_fb:
-	framebuffer_release(info);
-	return ret;
-}
-
-static int hitfb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static int hitfb_suspend(struct device *dev)
-{
-	u16 v;
-
-	hitfb_blank(1,0);
-	v = fb_readw(HD64461_STBCR);
-	v |= HD64461_STBCR_SLCKE_IST;
-	fb_writew(v, HD64461_STBCR);
-
-	return 0;
-}
-
-static int hitfb_resume(struct device *dev)
-{
-	u16 v;
-
-	v = fb_readw(HD64461_STBCR);
-	v &= ~HD64461_STBCR_SLCKE_OST;
-	msleep(100);
-	v = fb_readw(HD64461_STBCR);
-	v &= ~HD64461_STBCR_SLCKE_IST;
-	fb_writew(v, HD64461_STBCR);
-	hitfb_blank(0,0);
-
-	return 0;
-}
-
-static const struct dev_pm_ops hitfb_dev_pm_ops = {
-	.suspend	= hitfb_suspend,
-	.resume		= hitfb_resume,
-};
-
-static struct platform_driver hitfb_driver = {
-	.probe		= hitfb_probe,
-	.remove		= hitfb_remove,
-	.driver		= {
-		.name	= "hitfb",
-		.owner	= THIS_MODULE,
-		.pm	= &hitfb_dev_pm_ops,
-	},
-};
-
-static struct platform_device hitfb_device = {
-	.name	= "hitfb",
-	.id	= -1,
-};
-
-static int __init hitfb_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&hitfb_driver);
-	if (!ret) {
-		ret = platform_device_register(&hitfb_device);
-		if (ret)
-			platform_driver_unregister(&hitfb_driver);
-	}
-	return ret;
-}
-
-
-static void __exit hitfb_exit(void)
-{
-	platform_device_unregister(&hitfb_device);
-	platform_driver_unregister(&hitfb_driver);
-}
-
-module_init(hitfb_init);
-module_exit(hitfb_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
deleted file mode 100644
index a1b7e5fa9b09..000000000000
--- a/drivers/video/hpfb.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- *	HP300 Topcat framebuffer support (derived from macfb of all things)
- *	Phil Blundell <philb@gnu.org> 1998
- *	DIO-II, colour map and Catseye support by
- *	Kars de Jong <jongk@linux-m68k.org>, May 2004.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/dio.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-static struct fb_info fb_info = {
-	.fix = {
-		.id		= "HP300 ",
-		.type		= FB_TYPE_PACKED_PIXELS,
-		.visual		= FB_VISUAL_PSEUDOCOLOR,
-		.accel		= FB_ACCEL_NONE,
-	}
-};
-
-static unsigned long fb_regs;
-static unsigned char fb_bitmask;
-
-#define TC_NBLANK	0x4080
-#define TC_WEN		0x4088
-#define TC_REN		0x408c
-#define TC_FBEN		0x4090
-#define TC_PRR		0x40ea
-
-/* These defines match the X window system */
-#define RR_CLEAR	0x0
-#define RR_COPY		0x3
-#define RR_NOOP		0x5
-#define RR_XOR		0x6
-#define RR_INVERT	0xa
-#define RR_COPYINVERTED 0xc
-#define RR_SET		0xf
-
-/* blitter regs */
-#define BUSY		0x4044
-#define WMRR		0x40ef
-#define SOURCE_X	0x40f2
-#define SOURCE_Y	0x40f6
-#define DEST_X		0x40fa
-#define DEST_Y		0x40fe
-#define WHEIGHT		0x4106
-#define WWIDTH		0x4102
-#define WMOVE		0x409c
-
-static struct fb_var_screeninfo hpfb_defined = {
-	.red		= {
-		.length = 8,
-	},
-	.green		= {
-		.length = 8,
-	},
-	.blue		= {
-		.length = 8,
-	},
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static int hpfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			  unsigned blue, unsigned transp,
-			  struct fb_info *info)
-{
-	/* use MSBs */
-	unsigned char _red  =red>>8;
-	unsigned char _green=green>>8;
-	unsigned char _blue =blue>>8;
-	unsigned char _regno=regno;
-
-	/*
-	 *  Set a single color register. The values supplied are
-	 *  already rounded down to the hardware's capabilities
-	 *  (according to the entries in the `var' structure). Return
-	 *  != 0 for invalid regno.
-	 */
-
-	if (regno >= info->cmap.len)
-		return 1;
-	
-	while (in_be16(fb_regs + 0x6002) & 0x4) udelay(1);
-
-	out_be16(fb_regs + 0x60ba, 0xff);
-
-	out_be16(fb_regs + 0x60b2, _red);
-	out_be16(fb_regs + 0x60b4, _green);
-	out_be16(fb_regs + 0x60b6, _blue);
-	out_be16(fb_regs + 0x60b8, ~_regno);
-	out_be16(fb_regs + 0x60f0, 0xff);
-
-	udelay(100);
-
-	while (in_be16(fb_regs + 0x6002) & 0x4) udelay(1);
-	out_be16(fb_regs + 0x60b2, 0);
-	out_be16(fb_regs + 0x60b4, 0);
-	out_be16(fb_regs + 0x60b6, 0);
-	out_be16(fb_regs + 0x60b8, 0);
-
-	return 0;
-}
-
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-
-static int hpfb_blank(int blank, struct fb_info *info)
-{
-	out_8(fb_regs + TC_NBLANK, (blank ? 0x00 : fb_bitmask));
-
-	return 0;
-}
-
-static void topcat_blit(int x0, int y0, int x1, int y1, int w, int h, int rr)
-{
-	if (rr >= 0) {
-		while (in_8(fb_regs + BUSY) & fb_bitmask)
-			;
-	}
-	out_8(fb_regs + TC_FBEN, fb_bitmask);
-	if (rr >= 0) {
-		out_8(fb_regs + TC_WEN, fb_bitmask);
-		out_8(fb_regs + WMRR, rr);
-	}
-	out_be16(fb_regs + SOURCE_X, x0);
-	out_be16(fb_regs + SOURCE_Y, y0);
-	out_be16(fb_regs + DEST_X, x1);
-	out_be16(fb_regs + DEST_Y, y1);
-	out_be16(fb_regs + WWIDTH, w);
-	out_be16(fb_regs + WHEIGHT, h);
-	out_8(fb_regs + WMOVE, fb_bitmask);
-}
-
-static void hpfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 
-{
-	topcat_blit(area->sx, area->sy, area->dx, area->dy, area->width, area->height, RR_COPY);
-}
-
-static void hpfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
-{
-	u8 clr;
-
-	clr = region->color & 0xff;
-
-	while (in_8(fb_regs + BUSY) & fb_bitmask)
-		;
-
-	/* Foreground */
-	out_8(fb_regs + TC_WEN, fb_bitmask & clr);
-	out_8(fb_regs + WMRR, (region->rop == ROP_COPY ? RR_SET : RR_INVERT));
-
-	/* Background */
-	out_8(fb_regs + TC_WEN, fb_bitmask & ~clr);
-	out_8(fb_regs + WMRR, (region->rop == ROP_COPY ? RR_CLEAR : RR_NOOP));
-
-	topcat_blit(region->dx, region->dy, region->dx, region->dy, region->width, region->height, -1);
-}
-
-static int hpfb_sync(struct fb_info *info)
-{
-	/*
-	 * Since we also access the framebuffer directly, we have to wait
-	 * until the block mover is finished
-	 */
-	while (in_8(fb_regs + BUSY) & fb_bitmask)
-		;
-
-	out_8(fb_regs + TC_WEN, fb_bitmask);
-	out_8(fb_regs + TC_PRR, RR_COPY);
-	out_8(fb_regs + TC_FBEN, fb_bitmask);
-
-	return 0;
-}
-
-static struct fb_ops hpfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= hpfb_setcolreg,
-	.fb_blank	= hpfb_blank,
-	.fb_fillrect	= hpfb_fillrect,
-	.fb_copyarea	= hpfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_sync	= hpfb_sync,
-};
-
-/* Common to all HP framebuffers */
-#define HPFB_FBWMSB	0x05	/* Frame buffer width 		*/
-#define HPFB_FBWLSB	0x07
-#define HPFB_FBHMSB	0x09	/* Frame buffer height		*/
-#define HPFB_FBHLSB	0x0b
-#define HPFB_DWMSB	0x0d	/* Display width		*/
-#define HPFB_DWLSB	0x0f
-#define HPFB_DHMSB	0x11	/* Display height		*/
-#define HPFB_DHLSB	0x13
-#define HPFB_NUMPLANES	0x5b	/* Number of colour planes	*/
-#define HPFB_FBOMSB	0x5d	/* Frame buffer offset		*/
-#define HPFB_FBOLSB	0x5f
-
-static int hpfb_init_one(unsigned long phys_base, unsigned long virt_base)
-{
-	unsigned long fboff, fb_width, fb_height, fb_start;
-	int ret;
-
-	fb_regs = virt_base;
-	fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB);
-
-	fb_info.fix.smem_start = (in_8(fb_regs + fboff) << 16);
-
-	if (phys_base >= DIOII_BASE) {
-		fb_info.fix.smem_start += phys_base;
-	}
-
-	if (DIO_SECID(fb_regs) != DIO_ID2_TOPCAT) {
-		/* This is the magic incantation the HP X server uses to make Catseye boards work. */
-		while (in_be16(fb_regs+0x4800) & 1)
-			;
-		out_be16(fb_regs+0x4800, 0);	/* Catseye status */
-		out_be16(fb_regs+0x4510, 0);	/* VB */
-		out_be16(fb_regs+0x4512, 0);	/* TCNTRL */
-		out_be16(fb_regs+0x4514, 0);	/* ACNTRL */
-		out_be16(fb_regs+0x4516, 0);	/* PNCNTRL */
-		out_be16(fb_regs+0x4206, 0x90);	/* RUG Command/Status */
-		out_be16(fb_regs+0x60a2, 0);	/* Overlay Mask */
-		out_be16(fb_regs+0x60bc, 0);	/* Ram Select */
-	}
-
-	/*
-	 *	Fill in the available video resolution
-	 */
-	fb_width = (in_8(fb_regs + HPFB_FBWMSB) << 8) | in_8(fb_regs + HPFB_FBWLSB);
-	fb_info.fix.line_length = fb_width;
-	fb_height = (in_8(fb_regs + HPFB_FBHMSB) << 8) | in_8(fb_regs + HPFB_FBHLSB);
-	fb_info.fix.smem_len = fb_width * fb_height;
-	fb_start = (unsigned long)ioremap_writethrough(fb_info.fix.smem_start,
-						       fb_info.fix.smem_len);
-	hpfb_defined.xres = (in_8(fb_regs + HPFB_DWMSB) << 8) | in_8(fb_regs + HPFB_DWLSB);
-	hpfb_defined.yres = (in_8(fb_regs + HPFB_DHMSB) << 8) | in_8(fb_regs + HPFB_DHLSB);
-	hpfb_defined.xres_virtual = hpfb_defined.xres;
-	hpfb_defined.yres_virtual = hpfb_defined.yres;
-	hpfb_defined.bits_per_pixel = in_8(fb_regs + HPFB_NUMPLANES);
-
-	printk(KERN_INFO "hpfb: framebuffer at 0x%lx, mapped to 0x%lx, size %dk\n",
-	       fb_info.fix.smem_start, fb_start, fb_info.fix.smem_len/1024);
-	printk(KERN_INFO "hpfb: mode is %dx%dx%d, linelength=%d\n",
-	       hpfb_defined.xres, hpfb_defined.yres, hpfb_defined.bits_per_pixel, fb_info.fix.line_length);
-
-	/*
-	 *	Give the hardware a bit of a prod and work out how many bits per
-	 *	pixel are supported.
-	 */
-	out_8(fb_regs + TC_WEN, 0xff);
-	out_8(fb_regs + TC_PRR, RR_COPY);
-	out_8(fb_regs + TC_FBEN, 0xff);
-	out_8(fb_start, 0xff);
-	fb_bitmask = in_8(fb_start);
-	out_8(fb_start, 0);
-
-	/*
-	 *	Enable reading/writing of all the planes.
-	 */
-	out_8(fb_regs + TC_WEN, fb_bitmask);
-	out_8(fb_regs + TC_PRR, RR_COPY);
-	out_8(fb_regs + TC_REN, fb_bitmask);
-	out_8(fb_regs + TC_FBEN, fb_bitmask);
-
-	/*
-	 *	Clear the screen.
-	 */
-	topcat_blit(0, 0, 0, 0, fb_width, fb_height, RR_CLEAR);
-
-	/*
-	 *	Let there be consoles..
-	 */
-	if (DIO_SECID(fb_regs) == DIO_ID2_TOPCAT)
-		strcat(fb_info.fix.id, "Topcat");
-	else
-		strcat(fb_info.fix.id, "Catseye");
-	fb_info.fbops = &hpfb_ops;
-	fb_info.flags = FBINFO_DEFAULT;
-	fb_info.var   = hpfb_defined;
-	fb_info.screen_base = (char *)fb_start;
-
-	ret = fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);
-	if (ret < 0)
-		goto unmap_screen_base;
-
-	ret = register_framebuffer(&fb_info);
-	if (ret < 0)
-		goto dealloc_cmap;
-
-	fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
-
-	return 0;
-
-dealloc_cmap:
-	fb_dealloc_cmap(&fb_info.cmap);
-
-unmap_screen_base:
-	if (fb_info.screen_base) {
-		iounmap(fb_info.screen_base);
-		fb_info.screen_base = NULL;
-	}
-
-	return ret;
-}
-
-/* 
- * Check that the secondary ID indicates that we have some hope of working with this
- * framebuffer.  The catseye boards are pretty much like topcats and we can muddle through.
- */
-
-#define topcat_sid_ok(x)  (((x) == DIO_ID2_LRCATSEYE) || ((x) == DIO_ID2_HRCCATSEYE)    \
-			   || ((x) == DIO_ID2_HRMCATSEYE) || ((x) == DIO_ID2_TOPCAT))
-
-/* 
- * Initialise the framebuffer
- */
-static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent)
-{
-	unsigned long paddr, vaddr;
-
-	paddr = d->resource.start;
-	if (!request_mem_region(d->resource.start, resource_size(&d->resource), d->name))
-                return -EBUSY;
-
-	if (d->scode >= DIOII_SCBASE) {
-		vaddr = (unsigned long)ioremap(paddr, resource_size(&d->resource));
-	} else {
-		vaddr = paddr + DIO_VIRADDRBASE;
-	}
-	printk(KERN_INFO "Topcat found at DIO select code %d "
-	       "(secondary id %02x)\n", d->scode, (d->id >> 8) & 0xff);
-	if (hpfb_init_one(paddr, vaddr)) {
-		if (d->scode >= DIOII_SCBASE)
-			iounmap((void *)vaddr);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static void hpfb_remove_one(struct dio_dev *d)
-{
-	unregister_framebuffer(&fb_info);
-	if (d->scode >= DIOII_SCBASE)
-		iounmap((void *)fb_regs);
-	release_mem_region(d->resource.start, resource_size(&d->resource));
-	fb_dealloc_cmap(&fb_info.cmap);
-	if (fb_info.screen_base)
-		iounmap(fb_info.screen_base);
-}
-
-static struct dio_device_id hpfb_dio_tbl[] = {
-    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_LRCATSEYE) },
-    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRCCATSEYE) },
-    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRMCATSEYE) },
-    { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_TOPCAT) },
-    { 0 }
-};
-
-static struct dio_driver hpfb_driver = {
-    .name      = "hpfb",
-    .id_table  = hpfb_dio_tbl,
-    .probe     = hpfb_dio_probe,
-    .remove    = hpfb_remove_one,
-};
-
-int __init hpfb_init(void)
-{
-	unsigned int sid;
-	mm_segment_t fs;
-	unsigned char i;
-	int err;
-
-	/* Topcats can be on the internal IO bus or real DIO devices.
-	 * The internal variant sits at 0x560000; it has primary
-	 * and secondary ID registers just like the DIO version.
-	 * So we merge the two detection routines.
-	 *
-	 * Perhaps this #define should be in a global header file:
-	 * I believe it's common to all internal fbs, not just topcat.
-	 */
-#define INTFBVADDR 0xf0560000
-#define INTFBPADDR 0x560000
-
-	if (!MACH_IS_HP300)
-		return -ENODEV;
-
-	if (fb_get_options("hpfb", NULL))
-		return -ENODEV;
-
-	err = dio_register_driver(&hpfb_driver);
-	if (err)
-		return err;
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = get_user(i, (unsigned char *)INTFBVADDR + DIO_IDOFF);
-	set_fs(fs);
-
-	if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) {
-		if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat"))
-			return -EBUSY;
-		printk(KERN_INFO "Internal Topcat found (secondary id %02x)\n", sid);
-		if (hpfb_init_one(INTFBPADDR, INTFBVADDR)) {
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-void __exit hpfb_cleanup_module(void)
-{
-	dio_unregister_driver(&hpfb_driver);
-}
-
-module_init(hpfb_init);
-module_exit(hpfb_cleanup_module);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c
deleted file mode 100644
index e23392ec5af3..000000000000
--- a/drivers/video/hyperv_fb.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * Copyright (c) 2012, Microsoft Corporation.
- *
- * Author:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/*
- * Hyper-V Synthetic Video Frame Buffer Driver
- *
- * This is the driver for the Hyper-V Synthetic Video, which supports
- * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows
- * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2
- * or earlier.
- *
- * It also solves the double mouse cursor issue of the emulated video mode.
- *
- * The default screen resolution is 1152x864, which may be changed by a
- * kernel parameter:
- *     video=hyperv_fb:<width>x<height>
- *     For example: video=hyperv_fb:1280x1024
- *
- * Portrait orientation is also supported:
- *     For example: video=hyperv_fb:864x1152
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/efi.h>
-
-#include <linux/hyperv.h>
-
-
-/* Hyper-V Synthetic Video Protocol definitions and structures */
-#define MAX_VMBUS_PKT_SIZE 0x4000
-
-#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
-#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
-#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
-
-#define SYNTHVID_DEPTH_WIN7 16
-#define SYNTHVID_DEPTH_WIN8 32
-
-#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024)
-#define SYNTHVID_WIDTH_MAX_WIN7 1600
-#define SYNTHVID_HEIGHT_MAX_WIN7 1200
-
-#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
-
-#define PCI_VENDOR_ID_MICROSOFT 0x1414
-#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353
-
-
-enum pipe_msg_type {
-	PIPE_MSG_INVALID,
-	PIPE_MSG_DATA,
-	PIPE_MSG_MAX
-};
-
-struct pipe_msg_hdr {
-	u32 type;
-	u32 size; /* size of message after this field */
-} __packed;
-
-
-enum synthvid_msg_type {
-	SYNTHVID_ERROR			= 0,
-	SYNTHVID_VERSION_REQUEST	= 1,
-	SYNTHVID_VERSION_RESPONSE	= 2,
-	SYNTHVID_VRAM_LOCATION		= 3,
-	SYNTHVID_VRAM_LOCATION_ACK	= 4,
-	SYNTHVID_SITUATION_UPDATE	= 5,
-	SYNTHVID_SITUATION_UPDATE_ACK	= 6,
-	SYNTHVID_POINTER_POSITION	= 7,
-	SYNTHVID_POINTER_SHAPE		= 8,
-	SYNTHVID_FEATURE_CHANGE		= 9,
-	SYNTHVID_DIRT			= 10,
-
-	SYNTHVID_MAX			= 11
-};
-
-struct synthvid_msg_hdr {
-	u32 type;
-	u32 size;  /* size of this header + payload after this field*/
-} __packed;
-
-
-struct synthvid_version_req {
-	u32 version;
-} __packed;
-
-struct synthvid_version_resp {
-	u32 version;
-	u8 is_accepted;
-	u8 max_video_outputs;
-} __packed;
-
-struct synthvid_vram_location {
-	u64 user_ctx;
-	u8 is_vram_gpa_specified;
-	u64 vram_gpa;
-} __packed;
-
-struct synthvid_vram_location_ack {
-	u64 user_ctx;
-} __packed;
-
-struct video_output_situation {
-	u8 active;
-	u32 vram_offset;
-	u8 depth_bits;
-	u32 width_pixels;
-	u32 height_pixels;
-	u32 pitch_bytes;
-} __packed;
-
-struct synthvid_situation_update {
-	u64 user_ctx;
-	u8 video_output_count;
-	struct video_output_situation video_output[1];
-} __packed;
-
-struct synthvid_situation_update_ack {
-	u64 user_ctx;
-} __packed;
-
-struct synthvid_pointer_position {
-	u8 is_visible;
-	u8 video_output;
-	s32 image_x;
-	s32 image_y;
-} __packed;
-
-
-#define CURSOR_MAX_X 96
-#define CURSOR_MAX_Y 96
-#define CURSOR_ARGB_PIXEL_SIZE 4
-#define CURSOR_MAX_SIZE (CURSOR_MAX_X * CURSOR_MAX_Y * CURSOR_ARGB_PIXEL_SIZE)
-#define CURSOR_COMPLETE (-1)
-
-struct synthvid_pointer_shape {
-	u8 part_idx;
-	u8 is_argb;
-	u32 width; /* CURSOR_MAX_X at most */
-	u32 height; /* CURSOR_MAX_Y at most */
-	u32 hot_x; /* hotspot relative to upper-left of pointer image */
-	u32 hot_y;
-	u8 data[4];
-} __packed;
-
-struct synthvid_feature_change {
-	u8 is_dirt_needed;
-	u8 is_ptr_pos_needed;
-	u8 is_ptr_shape_needed;
-	u8 is_situ_needed;
-} __packed;
-
-struct rect {
-	s32 x1, y1; /* top left corner */
-	s32 x2, y2; /* bottom right corner, exclusive */
-} __packed;
-
-struct synthvid_dirt {
-	u8 video_output;
-	u8 dirt_count;
-	struct rect rect[1];
-} __packed;
-
-struct synthvid_msg {
-	struct pipe_msg_hdr pipe_hdr;
-	struct synthvid_msg_hdr vid_hdr;
-	union {
-		struct synthvid_version_req ver_req;
-		struct synthvid_version_resp ver_resp;
-		struct synthvid_vram_location vram;
-		struct synthvid_vram_location_ack vram_ack;
-		struct synthvid_situation_update situ;
-		struct synthvid_situation_update_ack situ_ack;
-		struct synthvid_pointer_position ptr_pos;
-		struct synthvid_pointer_shape ptr_shape;
-		struct synthvid_feature_change feature_chg;
-		struct synthvid_dirt dirt;
-	};
-} __packed;
-
-
-
-/* FB driver definitions and structures */
-#define HVFB_WIDTH 1152 /* default screen width */
-#define HVFB_HEIGHT 864 /* default screen height */
-#define HVFB_WIDTH_MIN 640
-#define HVFB_HEIGHT_MIN 480
-
-#define RING_BUFSIZE (256 * 1024)
-#define VSP_TIMEOUT (10 * HZ)
-#define HVFB_UPDATE_DELAY (HZ / 20)
-
-struct hvfb_par {
-	struct fb_info *info;
-	struct resource mem;
-	bool fb_ready; /* fb device is ready */
-	struct completion wait;
-	u32 synthvid_version;
-
-	struct delayed_work dwork;
-	bool update;
-
-	u32 pseudo_palette[16];
-	u8 init_buf[MAX_VMBUS_PKT_SIZE];
-	u8 recv_buf[MAX_VMBUS_PKT_SIZE];
-};
-
-static uint screen_width = HVFB_WIDTH;
-static uint screen_height = HVFB_HEIGHT;
-static uint screen_depth;
-static uint screen_fb_size;
-
-/* Send message to Hyper-V host */
-static inline int synthvid_send(struct hv_device *hdev,
-				struct synthvid_msg *msg)
-{
-	static atomic64_t request_id = ATOMIC64_INIT(0);
-	int ret;
-
-	msg->pipe_hdr.type = PIPE_MSG_DATA;
-	msg->pipe_hdr.size = msg->vid_hdr.size;
-
-	ret = vmbus_sendpacket(hdev->channel, msg,
-			       msg->vid_hdr.size + sizeof(struct pipe_msg_hdr),
-			       atomic64_inc_return(&request_id),
-			       VM_PKT_DATA_INBAND, 0);
-
-	if (ret)
-		pr_err("Unable to send packet via vmbus\n");
-
-	return ret;
-}
-
-
-/* Send screen resolution info to host */
-static int synthvid_send_situ(struct hv_device *hdev)
-{
-	struct fb_info *info = hv_get_drvdata(hdev);
-	struct synthvid_msg msg;
-
-	if (!info)
-		return -ENODEV;
-
-	memset(&msg, 0, sizeof(struct synthvid_msg));
-
-	msg.vid_hdr.type = SYNTHVID_SITUATION_UPDATE;
-	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
-		sizeof(struct synthvid_situation_update);
-	msg.situ.user_ctx = 0;
-	msg.situ.video_output_count = 1;
-	msg.situ.video_output[0].active = 1;
-	msg.situ.video_output[0].vram_offset = 0;
-	msg.situ.video_output[0].depth_bits = info->var.bits_per_pixel;
-	msg.situ.video_output[0].width_pixels = info->var.xres;
-	msg.situ.video_output[0].height_pixels = info->var.yres;
-	msg.situ.video_output[0].pitch_bytes = info->fix.line_length;
-
-	synthvid_send(hdev, &msg);
-
-	return 0;
-}
-
-/* Send mouse pointer info to host */
-static int synthvid_send_ptr(struct hv_device *hdev)
-{
-	struct synthvid_msg msg;
-
-	memset(&msg, 0, sizeof(struct synthvid_msg));
-	msg.vid_hdr.type = SYNTHVID_POINTER_POSITION;
-	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
-		sizeof(struct synthvid_pointer_position);
-	msg.ptr_pos.is_visible = 1;
-	msg.ptr_pos.video_output = 0;
-	msg.ptr_pos.image_x = 0;
-	msg.ptr_pos.image_y = 0;
-	synthvid_send(hdev, &msg);
-
-	memset(&msg, 0, sizeof(struct synthvid_msg));
-	msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;
-	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
-		sizeof(struct synthvid_pointer_shape);
-	msg.ptr_shape.part_idx = CURSOR_COMPLETE;
-	msg.ptr_shape.is_argb = 1;
-	msg.ptr_shape.width = 1;
-	msg.ptr_shape.height = 1;
-	msg.ptr_shape.hot_x = 0;
-	msg.ptr_shape.hot_y = 0;
-	msg.ptr_shape.data[0] = 0;
-	msg.ptr_shape.data[1] = 1;
-	msg.ptr_shape.data[2] = 1;
-	msg.ptr_shape.data[3] = 1;
-	synthvid_send(hdev, &msg);
-
-	return 0;
-}
-
-/* Send updated screen area (dirty rectangle) location to host */
-static int synthvid_update(struct fb_info *info)
-{
-	struct hv_device *hdev = device_to_hv_device(info->device);
-	struct synthvid_msg msg;
-
-	memset(&msg, 0, sizeof(struct synthvid_msg));
-
-	msg.vid_hdr.type = SYNTHVID_DIRT;
-	msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
-		sizeof(struct synthvid_dirt);
-	msg.dirt.video_output = 0;
-	msg.dirt.dirt_count = 1;
-	msg.dirt.rect[0].x1 = 0;
-	msg.dirt.rect[0].y1 = 0;
-	msg.dirt.rect[0].x2 = info->var.xres;
-	msg.dirt.rect[0].y2 = info->var.yres;
-
-	synthvid_send(hdev, &msg);
-
-	return 0;
-}
-
-
-/*
- * Actions on received messages from host:
- * Complete the wait event.
- * Or, reply with screen and cursor info.
- */
-static void synthvid_recv_sub(struct hv_device *hdev)
-{
-	struct fb_info *info = hv_get_drvdata(hdev);
-	struct hvfb_par *par;
-	struct synthvid_msg *msg;
-
-	if (!info)
-		return;
-
-	par = info->par;
-	msg = (struct synthvid_msg *)par->recv_buf;
-
-	/* Complete the wait event */
-	if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||
-	    msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {
-		memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE);
-		complete(&par->wait);
-		return;
-	}
-
-	/* Reply with screen and cursor info */
-	if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {
-		if (par->fb_ready) {
-			synthvid_send_ptr(hdev);
-			synthvid_send_situ(hdev);
-		}
-
-		par->update = msg->feature_chg.is_dirt_needed;
-		if (par->update)
-			schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
-	}
-}
-
-/* Receive callback for messages from the host */
-static void synthvid_receive(void *ctx)
-{
-	struct hv_device *hdev = ctx;
-	struct fb_info *info = hv_get_drvdata(hdev);
-	struct hvfb_par *par;
-	struct synthvid_msg *recv_buf;
-	u32 bytes_recvd;
-	u64 req_id;
-	int ret;
-
-	if (!info)
-		return;
-
-	par = info->par;
-	recv_buf = (struct synthvid_msg *)par->recv_buf;
-
-	do {
-		ret = vmbus_recvpacket(hdev->channel, recv_buf,
-				       MAX_VMBUS_PKT_SIZE,
-				       &bytes_recvd, &req_id);
-		if (bytes_recvd > 0 &&
-		    recv_buf->pipe_hdr.type == PIPE_MSG_DATA)
-			synthvid_recv_sub(hdev);
-	} while (bytes_recvd > 0 && ret == 0);
-}
-
-/* Check synthetic video protocol version with the host */
-static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
-{
-	struct fb_info *info = hv_get_drvdata(hdev);
-	struct hvfb_par *par = info->par;
-	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
-	int t, ret = 0;
-
-	memset(msg, 0, sizeof(struct synthvid_msg));
-	msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST;
-	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
-		sizeof(struct synthvid_version_req);
-	msg->ver_req.version = ver;
-	synthvid_send(hdev, msg);
-
-	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
-	if (!t) {
-		pr_err("Time out on waiting version response\n");
-		ret = -ETIMEDOUT;
-		goto out;
-	}
-	if (!msg->ver_resp.is_accepted) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-	par->synthvid_version = ver;
-
-out:
-	return ret;
-}
-
-/* Connect to VSP (Virtual Service Provider) on host */
-static int synthvid_connect_vsp(struct hv_device *hdev)
-{
-	struct fb_info *info = hv_get_drvdata(hdev);
-	struct hvfb_par *par = info->par;
-	int ret;
-
-	ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,
-			 NULL, 0, synthvid_receive, hdev);
-	if (ret) {
-		pr_err("Unable to open vmbus channel\n");
-		return ret;
-	}
-
-	/* Negotiate the protocol version with host */
-	if (vmbus_proto_version == VERSION_WS2008 ||
-	    vmbus_proto_version == VERSION_WIN7)
-		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7);
-	else
-		ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8);
-
-	if (ret) {
-		pr_err("Synthetic video device version not accepted\n");
-		goto error;
-	}
-
-	if (par->synthvid_version == SYNTHVID_VERSION_WIN7)
-		screen_depth = SYNTHVID_DEPTH_WIN7;
-	else
-		screen_depth = SYNTHVID_DEPTH_WIN8;
-
-	screen_fb_size = hdev->channel->offermsg.offer.
-				mmio_megabytes * 1024 * 1024;
-
-	return 0;
-
-error:
-	vmbus_close(hdev->channel);
-	return ret;
-}
-
-/* Send VRAM and Situation messages to the host */
-static int synthvid_send_config(struct hv_device *hdev)
-{
-	struct fb_info *info = hv_get_drvdata(hdev);
-	struct hvfb_par *par = info->par;
-	struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
-	int t, ret = 0;
-
-	/* Send VRAM location */
-	memset(msg, 0, sizeof(struct synthvid_msg));
-	msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION;
-	msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
-		sizeof(struct synthvid_vram_location);
-	msg->vram.user_ctx = msg->vram.vram_gpa = info->fix.smem_start;
-	msg->vram.is_vram_gpa_specified = 1;
-	synthvid_send(hdev, msg);
-
-	t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
-	if (!t) {
-		pr_err("Time out on waiting vram location ack\n");
-		ret = -ETIMEDOUT;
-		goto out;
-	}
-	if (msg->vram_ack.user_ctx != info->fix.smem_start) {
-		pr_err("Unable to set VRAM location\n");
-		ret = -ENODEV;
-		goto out;
-	}
-
-	/* Send pointer and situation update */
-	synthvid_send_ptr(hdev);
-	synthvid_send_situ(hdev);
-
-out:
-	return ret;
-}
-
-
-/*
- * Delayed work callback:
- * It is called at HVFB_UPDATE_DELAY or longer time interval to process
- * screen updates. It is re-scheduled if further update is necessary.
- */
-static void hvfb_update_work(struct work_struct *w)
-{
-	struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work);
-	struct fb_info *info = par->info;
-
-	if (par->fb_ready)
-		synthvid_update(info);
-
-	if (par->update)
-		schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
-}
-
-
-/* Framebuffer operation handlers */
-
-static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->xres < HVFB_WIDTH_MIN || var->yres < HVFB_HEIGHT_MIN ||
-	    var->xres > screen_width || var->yres >  screen_height ||
-	    var->bits_per_pixel != screen_depth)
-		return -EINVAL;
-
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-
-	return 0;
-}
-
-static int hvfb_set_par(struct fb_info *info)
-{
-	struct hv_device *hdev = device_to_hv_device(info->device);
-
-	return synthvid_send_situ(hdev);
-}
-
-
-static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)
-{
-	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
-}
-
-static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			  unsigned blue, unsigned transp, struct fb_info *info)
-{
-	u32 *pal = info->pseudo_palette;
-
-	if (regno > 15)
-		return -EINVAL;
-
-	pal[regno] = chan_to_field(red, &info->var.red)
-		| chan_to_field(green, &info->var.green)
-		| chan_to_field(blue, &info->var.blue)
-		| chan_to_field(transp, &info->var.transp);
-
-	return 0;
-}
-
-static int hvfb_blank(int blank, struct fb_info *info)
-{
-	return 1;	/* get fb_blank to set the colormap to all black */
-}
-
-static struct fb_ops hvfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = hvfb_check_var,
-	.fb_set_par = hvfb_set_par,
-	.fb_setcolreg = hvfb_setcolreg,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_blank = hvfb_blank,
-};
-
-
-/* Get options from kernel paramenter "video=" */
-static void hvfb_get_option(struct fb_info *info)
-{
-	struct hvfb_par *par = info->par;
-	char *opt = NULL, *p;
-	uint x = 0, y = 0;
-
-	if (fb_get_options(KBUILD_MODNAME, &opt) || !opt || !*opt)
-		return;
-
-	p = strsep(&opt, "x");
-	if (!*p || kstrtouint(p, 0, &x) ||
-	    !opt || !*opt || kstrtouint(opt, 0, &y)) {
-		pr_err("Screen option is invalid: skipped\n");
-		return;
-	}
-
-	if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||
-	    (par->synthvid_version == SYNTHVID_VERSION_WIN8 &&
-	     x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) ||
-	    (par->synthvid_version == SYNTHVID_VERSION_WIN7 &&
-	     (x > SYNTHVID_WIDTH_MAX_WIN7 || y > SYNTHVID_HEIGHT_MAX_WIN7))) {
-		pr_err("Screen resolution option is out of range: skipped\n");
-		return;
-	}
-
-	screen_width = x;
-	screen_height = y;
-	return;
-}
-
-
-/* Get framebuffer memory from Hyper-V video pci space */
-static int hvfb_getmem(struct fb_info *info)
-{
-	struct hvfb_par *par = info->par;
-	struct pci_dev *pdev  = NULL;
-	void __iomem *fb_virt;
-	int gen2vm = efi_enabled(EFI_BOOT);
-	int ret;
-
-	par->mem.name = KBUILD_MODNAME;
-	par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-	if (gen2vm) {
-		ret = allocate_resource(&hyperv_mmio, &par->mem,
-					screen_fb_size,
-					0, -1,
-					screen_fb_size,
-					NULL, NULL);
-		if (ret != 0) {
-			pr_err("Unable to allocate framebuffer memory\n");
-			return -ENODEV;
-		}
-	} else {
-		pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
-			      PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
-		if (!pdev) {
-			pr_err("Unable to find PCI Hyper-V video\n");
-			return -ENODEV;
-		}
-
-		if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
-		    pci_resource_len(pdev, 0) < screen_fb_size)
-			goto err1;
-
-		par->mem.end = pci_resource_end(pdev, 0);
-		par->mem.start = par->mem.end - screen_fb_size + 1;
-		ret = request_resource(&pdev->resource[0], &par->mem);
-		if (ret != 0) {
-			pr_err("Unable to request framebuffer memory\n");
-			goto err1;
-		}
-	}
-
-	fb_virt = ioremap(par->mem.start, screen_fb_size);
-	if (!fb_virt)
-		goto err2;
-
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures)
-		goto err3;
-
-	if (gen2vm) {
-		info->apertures->ranges[0].base = screen_info.lfb_base;
-		info->apertures->ranges[0].size = screen_info.lfb_size;
-		remove_conflicting_framebuffers(info->apertures,
-						KBUILD_MODNAME, false);
-	} else {
-		info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
-		info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
-	}
-
-	info->fix.smem_start = par->mem.start;
-	info->fix.smem_len = screen_fb_size;
-	info->screen_base = fb_virt;
-	info->screen_size = screen_fb_size;
-
-	if (!gen2vm)
-		pci_dev_put(pdev);
-
-	return 0;
-
-err3:
-	iounmap(fb_virt);
-err2:
-	release_resource(&par->mem);
-err1:
-	if (!gen2vm)
-		pci_dev_put(pdev);
-
-	return -ENOMEM;
-}
-
-/* Release the framebuffer */
-static void hvfb_putmem(struct fb_info *info)
-{
-	struct hvfb_par *par = info->par;
-
-	iounmap(info->screen_base);
-	release_resource(&par->mem);
-}
-
-
-static int hvfb_probe(struct hv_device *hdev,
-		      const struct hv_vmbus_device_id *dev_id)
-{
-	struct fb_info *info;
-	struct hvfb_par *par;
-	int ret;
-
-	info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);
-	if (!info) {
-		pr_err("No memory for framebuffer info\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	par->info = info;
-	par->fb_ready = false;
-	init_completion(&par->wait);
-	INIT_DELAYED_WORK(&par->dwork, hvfb_update_work);
-
-	/* Connect to VSP */
-	hv_set_drvdata(hdev, info);
-	ret = synthvid_connect_vsp(hdev);
-	if (ret) {
-		pr_err("Unable to connect to VSP\n");
-		goto error1;
-	}
-
-	ret = hvfb_getmem(info);
-	if (ret) {
-		pr_err("No memory for framebuffer\n");
-		goto error2;
-	}
-
-	hvfb_get_option(info);
-	pr_info("Screen resolution: %dx%d, Color depth: %d\n",
-		screen_width, screen_height, screen_depth);
-
-
-	/* Set up fb_info */
-	info->flags = FBINFO_DEFAULT;
-
-	info->var.xres_virtual = info->var.xres = screen_width;
-	info->var.yres_virtual = info->var.yres = screen_height;
-	info->var.bits_per_pixel = screen_depth;
-
-	if (info->var.bits_per_pixel == 16) {
-		info->var.red = (struct fb_bitfield){11, 5, 0};
-		info->var.green = (struct fb_bitfield){5, 6, 0};
-		info->var.blue = (struct fb_bitfield){0, 5, 0};
-		info->var.transp = (struct fb_bitfield){0, 0, 0};
-	} else {
-		info->var.red = (struct fb_bitfield){16, 8, 0};
-		info->var.green = (struct fb_bitfield){8, 8, 0};
-		info->var.blue = (struct fb_bitfield){0, 8, 0};
-		info->var.transp = (struct fb_bitfield){24, 8, 0};
-	}
-
-	info->var.activate = FB_ACTIVATE_NOW;
-	info->var.height = -1;
-	info->var.width = -1;
-	info->var.vmode = FB_VMODE_NONINTERLACED;
-
-	strcpy(info->fix.id, KBUILD_MODNAME);
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = screen_width * screen_depth / 8;
-	info->fix.accel = FB_ACCEL_NONE;
-
-	info->fbops = &hvfb_ops;
-	info->pseudo_palette = par->pseudo_palette;
-
-	/* Send config to host */
-	ret = synthvid_send_config(hdev);
-	if (ret)
-		goto error;
-
-	ret = register_framebuffer(info);
-	if (ret) {
-		pr_err("Unable to register framebuffer\n");
-		goto error;
-	}
-
-	par->fb_ready = true;
-
-	return 0;
-
-error:
-	hvfb_putmem(info);
-error2:
-	vmbus_close(hdev->channel);
-error1:
-	cancel_delayed_work_sync(&par->dwork);
-	hv_set_drvdata(hdev, NULL);
-	framebuffer_release(info);
-	return ret;
-}
-
-
-static int hvfb_remove(struct hv_device *hdev)
-{
-	struct fb_info *info = hv_get_drvdata(hdev);
-	struct hvfb_par *par = info->par;
-
-	par->update = false;
-	par->fb_ready = false;
-
-	unregister_framebuffer(info);
-	cancel_delayed_work_sync(&par->dwork);
-
-	vmbus_close(hdev->channel);
-	hv_set_drvdata(hdev, NULL);
-
-	hvfb_putmem(info);
-	framebuffer_release(info);
-
-	return 0;
-}
-
-
-static DEFINE_PCI_DEVICE_TABLE(pci_stub_id_table) = {
-	{
-		.vendor      = PCI_VENDOR_ID_MICROSOFT,
-		.device      = PCI_DEVICE_ID_HYPERV_VIDEO,
-	},
-	{ /* end of list */ }
-};
-
-static const struct hv_vmbus_device_id id_table[] = {
-	/* Synthetic Video Device GUID */
-	{HV_SYNTHVID_GUID},
-	{}
-};
-
-MODULE_DEVICE_TABLE(pci, pci_stub_id_table);
-MODULE_DEVICE_TABLE(vmbus, id_table);
-
-static struct hv_driver hvfb_drv = {
-	.name = KBUILD_MODNAME,
-	.id_table = id_table,
-	.probe = hvfb_probe,
-	.remove = hvfb_remove,
-};
-
-static int hvfb_pci_stub_probe(struct pci_dev *pdev,
-			       const struct pci_device_id *ent)
-{
-	return 0;
-}
-
-static void hvfb_pci_stub_remove(struct pci_dev *pdev)
-{
-}
-
-static struct pci_driver hvfb_pci_stub_driver = {
-	.name =		KBUILD_MODNAME,
-	.id_table =	pci_stub_id_table,
-	.probe =	hvfb_pci_stub_probe,
-	.remove =	hvfb_pci_stub_remove,
-};
-
-static int __init hvfb_drv_init(void)
-{
-	int ret;
-
-	ret = vmbus_driver_register(&hvfb_drv);
-	if (ret != 0)
-		return ret;
-
-	ret = pci_register_driver(&hvfb_pci_stub_driver);
-	if (ret != 0) {
-		vmbus_driver_unregister(&hvfb_drv);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void __exit hvfb_drv_exit(void)
-{
-	pci_unregister_driver(&hvfb_pci_stub_driver);
-	vmbus_driver_unregister(&hvfb_drv);
-}
-
-module_init(hvfb_drv_init);
-module_exit(hvfb_drv_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");
diff --git a/drivers/video/i740_reg.h b/drivers/video/i740_reg.h
deleted file mode 100644
index 91bac76549d7..000000000000
--- a/drivers/video/i740_reg.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/**************************************************************************
-
-Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- *   Kevin E. Martin <kevin@precisioninsight.com>
- */
-
-/* I/O register offsets */
-#define SRX VGA_SEQ_I
-#define GRX VGA_GFX_I
-#define ARX VGA_ATT_IW
-#define XRX 0x3D6
-#define MRX 0x3D2
-
-/* VGA Color Palette Registers */
-#define DACMASK		0x3C6
-#define DACSTATE	0x3C7
-#define DACRX		0x3C7
-#define DACWX		0x3C8
-#define DACDATA		0x3C9
-
-/* CRT Controller Registers (CRX) */
-#define START_ADDR_HI		0x0C
-#define START_ADDR_LO		0x0D
-#define VERT_SYNC_END		0x11
-#define EXT_VERT_TOTAL		0x30
-#define EXT_VERT_DISPLAY	0x31
-#define EXT_VERT_SYNC_START	0x32
-#define EXT_VERT_BLANK_START	0x33
-#define EXT_HORIZ_TOTAL		0x35
-#define EXT_HORIZ_BLANK		0x39
-#define EXT_START_ADDR		0x40
-#define EXT_START_ADDR_ENABLE	0x80
-#define EXT_OFFSET		0x41
-#define EXT_START_ADDR_HI	0x42
-#define INTERLACE_CNTL		0x70
-#define INTERLACE_ENABLE	0x80
-#define INTERLACE_DISABLE	0x00
-
-/* Miscellaneous Output Register */
-#define MSR_R		0x3CC
-#define MSR_W		0x3C2
-#define IO_ADDR_SELECT	0x01
-
-#define MDA_BASE	0x3B0
-#define CGA_BASE	0x3D0
-
-/* System Configuration Extension Registers (XRX) */
-#define IO_CTNL		0x09
-#define EXTENDED_ATTR_CNTL	0x02
-#define EXTENDED_CRTC_CNTL	0x01
-
-#define ADDRESS_MAPPING	0x0A
-#define PACKED_MODE_ENABLE	0x04
-#define LINEAR_MODE_ENABLE	0x02
-#define PAGE_MAPPING_ENABLE	0x01
-
-#define BITBLT_CNTL	0x20
-#define COLEXP_MODE		0x30
-#define COLEXP_8BPP		0x00
-#define COLEXP_16BPP		0x10
-#define COLEXP_24BPP		0x20
-#define COLEXP_RESERVED		0x30
-#define CHIP_RESET		0x02
-#define BITBLT_STATUS		0x01
-
-#define DISPLAY_CNTL	0x40
-#define VGA_WRAP_MODE		0x02
-#define VGA_WRAP_AT_256KB	0x00
-#define VGA_NO_WRAP		0x02
-#define GUI_MODE		0x01
-#define STANDARD_VGA_MODE	0x00
-#define HIRES_MODE		0x01
-
-#define DRAM_ROW_TYPE	0x50
-#define DRAM_ROW_0		0x07
-#define DRAM_ROW_0_SDRAM	0x00
-#define DRAM_ROW_0_EMPTY	0x07
-#define DRAM_ROW_1		0x38
-#define DRAM_ROW_1_SDRAM	0x00
-#define DRAM_ROW_1_EMPTY	0x38
-#define DRAM_ROW_CNTL_LO 0x51
-#define DRAM_CAS_LATENCY	0x10
-#define DRAM_RAS_TIMING		0x08
-#define DRAM_RAS_PRECHARGE	0x04
-#define DRAM_ROW_CNTL_HI 0x52
-#define DRAM_EXT_CNTL	0x53
-#define DRAM_REFRESH_RATE	0x03
-#define DRAM_REFRESH_DISABLE	0x00
-#define DRAM_REFRESH_60HZ	0x01
-#define DRAM_REFRESH_FAST_TEST	0x02
-#define DRAM_REFRESH_RESERVED	0x03
-#define DRAM_TIMING	0x54
-#define DRAM_ROW_BNDRY_0 0x55
-#define DRAM_ROW_BNDRY_1 0x56
-
-#define DPMS_SYNC_SELECT 0x61
-#define VSYNC_CNTL		0x08
-#define VSYNC_ON		0x00
-#define VSYNC_OFF		0x08
-#define HSYNC_CNTL		0x02
-#define HSYNC_ON		0x00
-#define HSYNC_OFF		0x02
-
-#define PIXPIPE_CONFIG_0 0x80
-#define DAC_8_BIT		0x80
-#define DAC_6_BIT		0x00
-#define HW_CURSOR_ENABLE	0x10
-#define EXTENDED_PALETTE	0x01
-
-#define PIXPIPE_CONFIG_1 0x81
-#define DISPLAY_COLOR_MODE	0x0F
-#define DISPLAY_VGA_MODE	0x00
-#define DISPLAY_8BPP_MODE	0x02
-#define DISPLAY_15BPP_MODE	0x04
-#define DISPLAY_16BPP_MODE	0x05
-#define DISPLAY_24BPP_MODE	0x06
-#define DISPLAY_32BPP_MODE	0x07
-
-#define PIXPIPE_CONFIG_2 0x82
-#define DISPLAY_GAMMA_ENABLE	0x08
-#define DISPLAY_GAMMA_DISABLE	0x00
-#define OVERLAY_GAMMA_ENABLE	0x04
-#define OVERLAY_GAMMA_DISABLE	0x00
-
-#define CURSOR_CONTROL	0xA0
-#define CURSOR_ORIGIN_SCREEN	0x00
-#define CURSOR_ORIGIN_DISPLAY	0x10
-#define CURSOR_MODE		0x07
-#define CURSOR_MODE_DISABLE	0x00
-#define CURSOR_MODE_32_4C_AX	0x01
-#define CURSOR_MODE_128_2C	0x02
-#define CURSOR_MODE_128_1C	0x03
-#define CURSOR_MODE_64_3C	0x04
-#define CURSOR_MODE_64_4C_AX	0x05
-#define CURSOR_MODE_64_4C	0x06
-#define CURSOR_MODE_RESERVED	0x07
-#define CURSOR_BASEADDR_LO 0xA2
-#define CURSOR_BASEADDR_HI 0xA3
-#define CURSOR_X_LO	0xA4
-#define CURSOR_X_HI	0xA5
-#define CURSOR_X_POS		0x00
-#define CURSOR_X_NEG		0x80
-#define CURSOR_Y_LO	0xA6
-#define CURSOR_Y_HI	0xA7
-#define CURSOR_Y_POS		0x00
-#define CURSOR_Y_NEG		0x80
-
-#define VCLK2_VCO_M	0xC8
-#define VCLK2_VCO_N	0xC9
-#define VCLK2_VCO_MN_MSBS 0xCA
-#define VCO_N_MSBS		0x30
-#define VCO_M_MSBS		0x03
-#define VCLK2_VCO_DIV_SEL 0xCB
-#define POST_DIV_SELECT		0x70
-#define POST_DIV_1		0x00
-#define POST_DIV_2		0x10
-#define POST_DIV_4		0x20
-#define POST_DIV_8		0x30
-#define POST_DIV_16		0x40
-#define POST_DIV_32		0x50
-#define VCO_LOOP_DIV_BY_4M	0x00
-#define VCO_LOOP_DIV_BY_16M	0x04
-#define REF_CLK_DIV_BY_5	0x02
-#define REF_DIV_4		0x00
-#define REF_DIV_1		0x01
-
-#define PLL_CNTL	0xCE
-#define PLL_MEMCLK_SEL		0x03
-#define PLL_MEMCLK__66667KHZ	0x00
-#define PLL_MEMCLK__75000KHZ	0x01
-#define PLL_MEMCLK__88889KHZ	0x02
-#define PLL_MEMCLK_100000KHZ	0x03
-
-/* Multimedia Extension Registers (MRX) */
-#define ACQ_CNTL_1	0x02
-#define ACQ_CNTL_2	0x03
-#define FRAME_CAP_MODE		0x01
-#define CONT_CAP_MODE		0x00
-#define SINGLE_CAP_MODE		0x01
-#define ACQ_CNTL_3	0x04
-#define COL_KEY_CNTL_1		0x3C
-#define BLANK_DISP_OVERLAY	0x20
-
-/* FIFOs */
-#define LP_FIFO		0x1000
-#define HP_FIFO		0x2000
-#define INSTPNT		0x3040
-#define LP_FIFO_COUNT	0x3040
-#define HP_FIFO_COUNT	0x3041
-
-/* FIFO Commands */
-#define CLIENT		0xE0000000
-#define CLIENT_2D	0x60000000
-
-/* Command Parser Mode Register */
-#define COMPARS		0x3038
-#define TWO_D_INST_DISABLE		0x08
-#define THREE_D_INST_DISABLE		0x04
-#define STATE_VAR_UPDATE_DISABLE	0x02
-#define PAL_STIP_DISABLE		0x01
-
-/* Interrupt Control Registers */
-#define IER		0x3030
-#define IIR		0x3032
-#define IMR		0x3034
-#define ISR		0x3036
-#define VMIINTB_EVENT		0x2000
-#define GPIO4_INT		0x1000
-#define DISP_FLIP_EVENT		0x0800
-#define DVD_PORT_DMA		0x0400
-#define DISP_VBLANK		0x0200
-#define FIFO_EMPTY_DMA_DONE	0x0100
-#define INST_PARSER_ERROR	0x0080
-#define USER_DEFINED		0x0040
-#define BREAKPOINT		0x0020
-#define DISP_HORIZ_COUNT	0x0010
-#define DISP_VSYNC		0x0008
-#define CAPTURE_HORIZ_COUNT	0x0004
-#define CAPTURE_VSYNC		0x0002
-#define THREE_D_PIPE_FLUSHED	0x0001
-
-/* FIFO Watermark and Burst Length Control Register */
-#define FWATER_BLC	0x00006000
-#define LMI_BURST_LENGTH	0x7F000000
-#define LMI_FIFO_WATERMARK	0x003F0000
-#define AGP_BURST_LENGTH	0x00007F00
-#define AGP_FIFO_WATERMARK	0x0000003F
-
-/* BitBLT Registers */
-#define SRC_DST_PITCH	0x00040000
-#define DST_PITCH		0x1FFF0000
-#define SRC_PITCH		0x00001FFF
-#define COLEXP_BG_COLOR	0x00040004
-#define COLEXP_FG_COLOR	0x00040008
-#define MONO_SRC_CNTL	0x0004000C
-#define MONO_USE_COLEXP		0x00000000
-#define MONO_USE_SRCEXP		0x08000000
-#define MONO_DATA_ALIGN		0x07000000
-#define MONO_BIT_ALIGN		0x01000000
-#define MONO_BYTE_ALIGN		0x02000000
-#define MONO_WORD_ALIGN		0x03000000
-#define MONO_DWORD_ALIGN	0x04000000
-#define MONO_QWORD_ALIGN	0x05000000
-#define MONO_SRC_INIT_DSCRD	0x003F0000
-#define MONO_SRC_RIGHT_CLIP	0x00003F00
-#define MONO_SRC_LEFT_CLIP	0x0000003F
-#define BITBLT_CONTROL	0x00040010
-#define BLTR_STATUS		0x80000000
-#define DYN_DEPTH		0x03000000
-#define DYN_DEPTH_8BPP		0x00000000
-#define DYN_DEPTH_16BPP		0x01000000
-#define DYN_DEPTH_24BPP		0x02000000
-#define DYN_DEPTH_32BPP		0x03000000	/* Unimplemented on the i740 */
-#define DYN_DEPTH_ENABLE	0x00800000
-#define PAT_VERT_ALIGN		0x00700000
-#define SOLID_PAT_SELECT	0x00080000
-#define PAT_IS_IN_COLOR		0x00000000
-#define PAT_IS_MONO		0x00040000
-#define MONO_PAT_TRANSP		0x00020000
-#define COLOR_TRANSP_ROP	0x00000000
-#define COLOR_TRANSP_DST	0x00008000
-#define COLOR_TRANSP_EQ		0x00000000
-#define COLOR_TRANSP_NOT_EQ	0x00010000
-#define COLOR_TRANSP_ENABLE	0x00004000
-#define MONO_SRC_TRANSP		0x00002000
-#define SRC_IS_IN_COLOR		0x00000000
-#define SRC_IS_MONO		0x00001000
-#define SRC_USE_SRC_ADDR	0x00000000
-#define SRC_USE_BLTDATA		0x00000400
-#define BLT_TOP_TO_BOT		0x00000000
-#define BLT_BOT_TO_TOP		0x00000200
-#define BLT_LEFT_TO_RIGHT	0x00000000
-#define BLT_RIGHT_TO_LEFT	0x00000100
-#define BLT_ROP			0x000000FF
-#define BLT_PAT_ADDR	0x00040014
-#define BLT_SRC_ADDR	0x00040018
-#define BLT_DST_ADDR	0x0004001C
-#define BLT_DST_H_W	0x00040020
-#define BLT_DST_HEIGHT		0x1FFF0000
-#define BLT_DST_WIDTH		0x00001FFF
-#define SRCEXP_BG_COLOR	0x00040024
-#define SRCEXP_FG_COLOR	0x00040028
-#define BLTDATA		0x00050000
diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c
deleted file mode 100644
index ca7c9df193b0..000000000000
--- a/drivers/video/i740fb.c
+++ /dev/null
@@ -1,1333 +0,0 @@
-/*
- * i740fb - framebuffer driver for Intel740
- * Copyright (c) 2011 Ondrej Zary
- *
- * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
- * which was partially based on:
- *  VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
- *	and Petr Vandrovec <VANDROVE@vc.cvut.cz>
- *  i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
- *	Texas.
- *  i740fb by Patrick LERDA, v0.9
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/console.h>
-#include <video/vga.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include "i740_reg.h"
-
-static char *mode_option;
-
-#ifdef CONFIG_MTRR
-static int mtrr = 1;
-#endif
-
-struct i740fb_par {
-	unsigned char __iomem *regs;
-	bool has_sgram;
-#ifdef CONFIG_MTRR
-	int mtrr_reg;
-#endif
-	bool ddc_registered;
-	struct i2c_adapter ddc_adapter;
-	struct i2c_algo_bit_data ddc_algo;
-	u32 pseudo_palette[16];
-	struct mutex open_lock;
-	unsigned int ref_count;
-
-	u8 crtc[VGA_CRT_C];
-	u8 atc[VGA_ATT_C];
-	u8 gdc[VGA_GFX_C];
-	u8 seq[VGA_SEQ_C];
-	u8 misc;
-	u8 vss;
-
-	/* i740 specific registers */
-	u8 display_cntl;
-	u8 pixelpipe_cfg0;
-	u8 pixelpipe_cfg1;
-	u8 pixelpipe_cfg2;
-	u8 video_clk2_m;
-	u8 video_clk2_n;
-	u8 video_clk2_mn_msbs;
-	u8 video_clk2_div_sel;
-	u8 pll_cntl;
-	u8 address_mapping;
-	u8 io_cntl;
-	u8 bitblt_cntl;
-	u8 ext_vert_total;
-	u8 ext_vert_disp_end;
-	u8 ext_vert_sync_start;
-	u8 ext_vert_blank_start;
-	u8 ext_horiz_total;
-	u8 ext_horiz_blank;
-	u8 ext_offset;
-	u8 interlace_cntl;
-	u32 lmi_fifo_watermark;
-	u8 ext_start_addr;
-	u8 ext_start_addr_hi;
-};
-
-#define DACSPEED8	203
-#define DACSPEED16	163
-#define DACSPEED24_SG	136
-#define DACSPEED24_SD	128
-#define DACSPEED32	86
-
-static struct fb_fix_screeninfo i740fb_fix = {
-	.id =		"i740fb",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.xpanstep =	8,
-	.ypanstep =	1,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
-{
-	vga_mm_w(par->regs, port, val);
-}
-static inline u8 i740inb(struct i740fb_par *par, u16 port)
-{
-	return vga_mm_r(par->regs, port);
-}
-static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
-{
-	vga_mm_w_fast(par->regs, port, reg, val);
-}
-static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
-{
-	vga_mm_w(par->regs, port, reg);
-	return vga_mm_r(par->regs, port+1);
-}
-static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
-				   u8 val, u8 mask)
-{
-	vga_mm_w_fast(par->regs, port, reg, (val & mask)
-		| (i740inreg(par, port, reg) & ~mask));
-}
-
-#define REG_DDC_DRIVE	0x62
-#define REG_DDC_STATE	0x63
-#define DDC_SCL		(1 << 3)
-#define DDC_SDA		(1 << 2)
-
-static void i740fb_ddc_setscl(void *data, int val)
-{
-	struct i740fb_par *par = data;
-
-	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
-	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
-}
-
-static void i740fb_ddc_setsda(void *data, int val)
-{
-	struct i740fb_par *par = data;
-
-	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
-	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
-}
-
-static int i740fb_ddc_getscl(void *data)
-{
-	struct i740fb_par *par = data;
-
-	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
-
-	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
-}
-
-static int i740fb_ddc_getsda(void *data)
-{
-	struct i740fb_par *par = data;
-
-	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
-
-	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
-}
-
-static int i740fb_setup_ddc_bus(struct fb_info *info)
-{
-	struct i740fb_par *par = info->par;
-
-	strlcpy(par->ddc_adapter.name, info->fix.id,
-		sizeof(par->ddc_adapter.name));
-	par->ddc_adapter.owner		= THIS_MODULE;
-	par->ddc_adapter.class		= I2C_CLASS_DDC;
-	par->ddc_adapter.algo_data	= &par->ddc_algo;
-	par->ddc_adapter.dev.parent	= info->device;
-	par->ddc_algo.setsda		= i740fb_ddc_setsda;
-	par->ddc_algo.setscl		= i740fb_ddc_setscl;
-	par->ddc_algo.getsda		= i740fb_ddc_getsda;
-	par->ddc_algo.getscl		= i740fb_ddc_getscl;
-	par->ddc_algo.udelay		= 10;
-	par->ddc_algo.timeout		= 20;
-	par->ddc_algo.data		= par;
-
-	i2c_set_adapdata(&par->ddc_adapter, par);
-
-	return i2c_bit_add_bus(&par->ddc_adapter);
-}
-
-static int i740fb_open(struct fb_info *info, int user)
-{
-	struct i740fb_par *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	par->ref_count++;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-static int i740fb_release(struct fb_info *info, int user)
-{
-	struct i740fb_par *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	if (par->ref_count == 0) {
-		fb_err(info, "release called with zero refcount\n");
-		mutex_unlock(&(par->open_lock));
-		return -EINVAL;
-	}
-
-	par->ref_count--;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
-{
-	/*
-	 * Would like to calculate these values automatically, but a generic
-	 * algorithm does not seem possible.  Note: These FIFO water mark
-	 * values were tested on several cards and seem to eliminate the
-	 * all of the snow and vertical banding, but fine adjustments will
-	 * probably be required for other cards.
-	 */
-
-	u32 wm;
-
-	switch (bpp) {
-	case 8:
-		if	(freq > 200)
-			wm = 0x18120000;
-		else if (freq > 175)
-			wm = 0x16110000;
-		else if (freq > 135)
-			wm = 0x120E0000;
-		else
-			wm = 0x100D0000;
-		break;
-	case 15:
-	case 16:
-		if (par->has_sgram) {
-			if	(freq > 140)
-				wm = 0x2C1D0000;
-			else if (freq > 120)
-				wm = 0x2C180000;
-			else if (freq > 100)
-				wm = 0x24160000;
-			else if (freq >  90)
-				wm = 0x18120000;
-			else if (freq >  50)
-				wm = 0x16110000;
-			else if (freq >  32)
-				wm = 0x13100000;
-			else
-				wm = 0x120E0000;
-		} else {
-			if	(freq > 160)
-				wm = 0x28200000;
-			else if (freq > 140)
-				wm = 0x2A1E0000;
-			else if (freq > 130)
-				wm = 0x2B1A0000;
-			else if (freq > 120)
-				wm = 0x2C180000;
-			else if (freq > 100)
-				wm = 0x24180000;
-			else if (freq >  90)
-				wm = 0x18120000;
-			else if (freq >  50)
-				wm = 0x16110000;
-			else if (freq >  32)
-				wm = 0x13100000;
-			else
-				wm = 0x120E0000;
-		}
-		break;
-	case 24:
-		if (par->has_sgram) {
-			if	(freq > 130)
-				wm = 0x31200000;
-			else if (freq > 120)
-				wm = 0x2E200000;
-			else if (freq > 100)
-				wm = 0x2C1D0000;
-			else if (freq >  80)
-				wm = 0x25180000;
-			else if (freq >  64)
-				wm = 0x24160000;
-			else if (freq >  49)
-				wm = 0x18120000;
-			else if (freq >  32)
-				wm = 0x16110000;
-			else
-				wm = 0x13100000;
-		} else {
-			if	(freq > 120)
-				wm = 0x311F0000;
-			else if (freq > 100)
-				wm = 0x2C1D0000;
-			else if (freq >  80)
-				wm = 0x25180000;
-			else if (freq >  64)
-				wm = 0x24160000;
-			else if (freq >  49)
-				wm = 0x18120000;
-			else if (freq >  32)
-				wm = 0x16110000;
-			else
-				wm = 0x13100000;
-		}
-		break;
-	case 32:
-		if (par->has_sgram) {
-			if	(freq >  80)
-				wm = 0x2A200000;
-			else if (freq >  60)
-				wm = 0x281A0000;
-			else if (freq >  49)
-				wm = 0x25180000;
-			else if (freq >  32)
-				wm = 0x18120000;
-			else
-				wm = 0x16110000;
-		} else {
-			if	(freq >  80)
-				wm = 0x29200000;
-			else if (freq >  60)
-				wm = 0x281A0000;
-			else if (freq >  49)
-				wm = 0x25180000;
-			else if (freq >  32)
-				wm = 0x18120000;
-			else
-				wm = 0x16110000;
-		}
-		break;
-	}
-
-	return wm;
-}
-
-/* clock calculation from i740fb by Patrick LERDA */
-
-#define I740_RFREQ		1000000
-#define TARGET_MAX_N		30
-#define I740_FFIX		(1 << 8)
-#define I740_RFREQ_FIX		(I740_RFREQ / I740_FFIX)
-#define I740_REF_FREQ		(6667 * I740_FFIX / 100)	/* 66.67 MHz */
-#define I740_MAX_VCO_FREQ	(450 * I740_FFIX)		/* 450 MHz */
-
-static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
-{
-	const u32 err_max    = freq / (200  * I740_RFREQ / I740_FFIX);
-	const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
-	u32 err_best = 512 * I740_FFIX;
-	u32 f_err, f_vco;
-	int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
-	int m, n;
-
-	p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
-	d_best = 0;
-	f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
-	freq = freq / I740_RFREQ_FIX;
-
-	n = 2;
-	do {
-		n++;
-		m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
-
-		if (m < 3)
-			m = 3;
-
-		{
-			u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best))
-				 / n) + ((1 << p_best) / 2)) / (1 << p_best);
-
-			f_err = (freq - f_out);
-
-			if (abs(f_err) < err_max) {
-				m_best = m;
-				n_best = n;
-				err_best = f_err;
-			}
-		}
-	} while ((abs(f_err) >= err_target) &&
-		 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
-
-	if (abs(f_err) < err_target) {
-		m_best = m;
-		n_best = n;
-	}
-
-	par->video_clk2_m = (m_best - 2) & 0xFF;
-	par->video_clk2_n = (n_best - 2) & 0xFF;
-	par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
-				 | (((m_best - 2) >> 8) & VCO_M_MSBS));
-	par->video_clk2_div_sel =
-		((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
-}
-
-static int i740fb_decode_var(const struct fb_var_screeninfo *var,
-			     struct i740fb_par *par, struct fb_info *info)
-{
-	/*
-	 * Get the video params out of 'var'.
-	 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
-	 */
-
-	u32 xres, right, hslen, left, xtotal;
-	u32 yres, lower, vslen, upper, ytotal;
-	u32 vxres, xoffset, vyres, yoffset;
-	u32 bpp, base, dacspeed24, mem;
-	u8 r7;
-	int i;
-
-	dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
-		  var->xres, var->yres, var->xres_virtual, var->xres_virtual);
-	dev_dbg(info->device, "	xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
-		  var->xoffset, var->yoffset, var->bits_per_pixel,
-		  var->grayscale);
-	dev_dbg(info->device, "	activate: %i, nonstd: %i, vmode: %i\n",
-		  var->activate, var->nonstd, var->vmode);
-	dev_dbg(info->device, "	pixclock: %i, hsynclen:%i, vsynclen:%i\n",
-		  var->pixclock, var->hsync_len, var->vsync_len);
-	dev_dbg(info->device, "	left: %i, right: %i, up:%i, lower:%i\n",
-		  var->left_margin, var->right_margin, var->upper_margin,
-		  var->lower_margin);
-
-
-	bpp = var->bits_per_pixel;
-	switch (bpp) {
-	case 1 ... 8:
-		bpp = 8;
-		if ((1000000 / var->pixclock) > DACSPEED8) {
-			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
-				1000000 / var->pixclock, DACSPEED8);
-			return -EINVAL;
-		}
-		break;
-	case 9 ... 15:
-		bpp = 15;
-	case 16:
-		if ((1000000 / var->pixclock) > DACSPEED16) {
-			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
-				1000000 / var->pixclock, DACSPEED16);
-			return -EINVAL;
-		}
-		break;
-	case 17 ... 24:
-		bpp = 24;
-		dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
-		if ((1000000 / var->pixclock) > dacspeed24) {
-			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
-				1000000 / var->pixclock, dacspeed24);
-			return -EINVAL;
-		}
-		break;
-	case 25 ... 32:
-		bpp = 32;
-		if ((1000000 / var->pixclock) > DACSPEED32) {
-			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
-				1000000 / var->pixclock, DACSPEED32);
-			return -EINVAL;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	xres = ALIGN(var->xres, 8);
-	vxres = ALIGN(var->xres_virtual, 16);
-	if (vxres < xres)
-		vxres = xres;
-
-	xoffset = ALIGN(var->xoffset, 8);
-	if (xres + xoffset > vxres)
-		xoffset = vxres - xres;
-
-	left = ALIGN(var->left_margin, 8);
-	right = ALIGN(var->right_margin, 8);
-	hslen = ALIGN(var->hsync_len, 8);
-
-	yres = var->yres;
-	vyres = var->yres_virtual;
-	if (yres > vyres)
-		vyres = yres;
-
-	yoffset = var->yoffset;
-	if (yres + yoffset > vyres)
-		yoffset = vyres - yres;
-
-	lower = var->lower_margin;
-	vslen = var->vsync_len;
-	upper = var->upper_margin;
-
-	mem = vxres * vyres * ((bpp + 1) / 8);
-	if (mem > info->screen_size) {
-		dev_err(info->device, "not enough video memory (%d KB requested, %ld KB available)\n",
-			mem >> 10, info->screen_size >> 10);
-		return -ENOMEM;
-	}
-
-	if (yoffset + yres > vyres)
-		yoffset = vyres - yres;
-
-	xtotal = xres + right + hslen + left;
-	ytotal = yres + lower + vslen + upper;
-
-	par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
-	par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
-	par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
-	par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
-	par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
-		| ((((xres + right + hslen) >> 3) & 0x20) << 2);
-	par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
-		| 0x80;
-
-	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
-
-	r7 = 0x10;	/* disable linecompare */
-	if (ytotal & 0x100)
-		r7 |= 0x01;
-	if (ytotal & 0x200)
-		r7 |= 0x20;
-
-	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
-	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
-	if (var->vmode & FB_VMODE_DOUBLE)
-		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
-	par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
-	par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
-	par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
-	par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
-	par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
-	if ((yres-1) & 0x100)
-		r7 |= 0x02;
-	if ((yres-1) & 0x200)
-		r7 |= 0x40;
-
-	par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
-	par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
-	if ((yres + lower - 1) & 0x100)
-		r7 |= 0x0C;
-	if ((yres + lower - 1) & 0x200) {
-		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
-		r7 |= 0x80;
-	}
-
-	/* disabled IRQ */
-	par->crtc[VGA_CRTC_V_SYNC_END] =
-		((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
-	/* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
-	par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
-
-	par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
-	par->crtc[VGA_CRTC_MODE] = 0xC3 ;
-	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
-	par->crtc[VGA_CRTC_OVERFLOW] = r7;
-
-	par->vss = 0x00;	/* 3DA */
-
-	for (i = 0x00; i < 0x10; i++)
-		par->atc[i] = i;
-	par->atc[VGA_ATC_MODE] = 0x81;
-	par->atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
-	par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
-	par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
-
-	par->misc = 0xC3;
-	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-		par->misc &= ~0x40;
-	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-		par->misc &= ~0x80;
-
-	par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
-	par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
-	par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
-	par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
-
-	par->gdc[VGA_GFX_SR_VALUE] = 0x00;
-	par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
-	par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
-	par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
-	par->gdc[VGA_GFX_PLANE_READ] = 0;
-	par->gdc[VGA_GFX_MODE] = 0x02;
-	par->gdc[VGA_GFX_MISC] = 0x05;
-	par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
-	par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
-
-	base = (yoffset * vxres + (xoffset & ~7)) >> 2;
-	switch (bpp) {
-	case 8:
-		par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
-		par->ext_offset = vxres >> 11;
-		par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
-		par->bitblt_cntl = COLEXP_8BPP;
-		break;
-	case 15: /* 0rrrrrgg gggbbbbb */
-	case 16: /* rrrrrggg gggbbbbb */
-		par->pixelpipe_cfg1 = (var->green.length == 6) ?
-			DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
-		par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
-		par->ext_offset = vxres >> 10;
-		par->bitblt_cntl = COLEXP_16BPP;
-		base *= 2;
-		break;
-	case 24:
-		par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
-		par->ext_offset = (vxres * 3) >> 11;
-		par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
-		par->bitblt_cntl = COLEXP_24BPP;
-		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
-		base *= 3;
-		break;
-	case 32:
-		par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
-		par->ext_offset = vxres >> 9;
-		par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
-		par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
-		base *= 4;
-		break;
-	}
-
-	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
-	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
-	par->ext_start_addr =
-		((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
-	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
-
-	par->pixelpipe_cfg0 = DAC_8_BIT;
-
-	par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
-	par->io_cntl = EXTENDED_CRTC_CNTL;
-	par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
-	par->display_cntl = HIRES_MODE;
-
-	/* Set the MCLK freq */
-	par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
-
-	/* Calculate the extended CRTC regs */
-	par->ext_vert_total = (ytotal - 2) >> 8;
-	par->ext_vert_disp_end = (yres - 1) >> 8;
-	par->ext_vert_sync_start = (yres + lower) >> 8;
-	par->ext_vert_blank_start = (yres + lower) >> 8;
-	par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
-	par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
-
-	par->interlace_cntl = INTERLACE_DISABLE;
-
-	/* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
-	par->atc[VGA_ATC_OVERSCAN] = 0;
-
-	/* Calculate VCLK that most closely matches the requested dot clock */
-	i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
-
-	/* Since we program the clocks ourselves, always use VCLK2. */
-	par->misc |= 0x0C;
-
-	/* Calculate the FIFO Watermark and Burst Length. */
-	par->lmi_fifo_watermark =
-		i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
-
-	return 0;
-}
-
-static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.offset	= var->green.offset = var->blue.offset = 0;
-		var->red.length	= var->green.length = var->blue.length = 8;
-		break;
-	case 16:
-		switch (var->green.length) {
-		default:
-		case 5:
-			var->red.offset = 10;
-			var->green.offset = 5;
-			var->blue.offset = 0;
-			var->red.length	= 5;
-			var->green.length = 5;
-			var->blue.length = 5;
-			break;
-		case 6:
-			var->red.offset = 11;
-			var->green.offset = 5;
-			var->blue.offset = 0;
-			var->red.length = var->blue.length = 5;
-			break;
-		}
-		break;
-	case 24:
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length	= var->green.length = var->blue.length = 8;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->transp.length = 8;
-		var->red.length = var->green.length = var->blue.length = 8;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-
-	if (info->monspecs.hfmax && info->monspecs.vfmax &&
-	    info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-static void vga_protect(struct i740fb_par *par)
-{
-	/* disable the display */
-	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
-
-	i740inb(par, 0x3DA);
-	i740outb(par, VGA_ATT_W, 0x00);	/* enable palette access */
-}
-
-static void vga_unprotect(struct i740fb_par *par)
-{
-	/* reenable display */
-	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
-
-	i740inb(par, 0x3DA);
-	i740outb(par, VGA_ATT_W, 0x20);	/* disable palette access */
-}
-
-static int i740fb_set_par(struct fb_info *info)
-{
-	struct i740fb_par *par = info->par;
-	u32 itemp;
-	int i;
-
-	i = i740fb_decode_var(&info->var, par, info);
-	if (i)
-		return i;
-
-	memset(info->screen_base, 0, info->screen_size);
-
-	vga_protect(par);
-
-	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
-
-	mdelay(1);
-
-	i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
-	i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
-	i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
-	i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
-
-	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
-			par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
-
-	i740inb(par, 0x3DA);
-	i740outb(par, 0x3C0, 0x00);
-
-	/* update misc output register */
-	i740outb(par, VGA_MIS_W, par->misc | 0x01);
-
-	/* synchronous reset on */
-	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
-	/* write sequencer registers */
-	i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
-			par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
-	for (i = 2; i < VGA_SEQ_C; i++)
-		i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
-
-	/* synchronous reset off */
-	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
-
-	/* deprotect CRT registers 0-7 */
-	i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
-			par->crtc[VGA_CRTC_V_SYNC_END]);
-
-	/* write CRT registers */
-	for (i = 0; i < VGA_CRT_C; i++)
-		i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
-
-	/* write graphics controller registers */
-	for (i = 0; i < VGA_GFX_C; i++)
-		i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
-
-	/* write attribute controller registers */
-	for (i = 0; i < VGA_ATT_C; i++) {
-		i740inb(par, VGA_IS1_RC);		/* reset flip-flop */
-		i740outb(par, VGA_ATT_IW, i);
-		i740outb(par, VGA_ATT_IW, par->atc[i]);
-	}
-
-	i740inb(par, VGA_IS1_RC);
-	i740outb(par, VGA_ATT_IW, 0x20);
-
-	i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
-	i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
-	i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
-			par->ext_vert_sync_start);
-	i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
-			par->ext_vert_blank_start);
-	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
-	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
-	i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
-	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
-	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
-
-	i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
-			par->interlace_cntl, INTERLACE_ENABLE);
-	i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
-	i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
-	i740outreg_mask(par, XRX, DISPLAY_CNTL,
-			par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
-	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
-	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
-
-	i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
-
-	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
-			par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
-
-	itemp = readl(par->regs + FWATER_BLC);
-	itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
-	itemp |= par->lmi_fifo_watermark;
-	writel(itemp, par->regs + FWATER_BLC);
-
-	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
-
-	i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
-	i740outreg_mask(par, XRX, IO_CTNL,
-			par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
-
-	if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
-		i740outb(par, VGA_PEL_MSK, 0xFF);
-		i740outb(par, VGA_PEL_IW, 0x00);
-		for (i = 0; i < 256; i++) {
-			itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
-			i740outb(par, VGA_PEL_D, itemp);
-			i740outb(par, VGA_PEL_D, itemp);
-			i740outb(par, VGA_PEL_D, itemp);
-		}
-	}
-
-	/* Wait for screen to stabilize. */
-	mdelay(50);
-	vga_unprotect(par);
-
-	info->fix.line_length =
-			info->var.xres_virtual * info->var.bits_per_pixel / 8;
-	if (info->var.bits_per_pixel == 8)
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	return 0;
-}
-
-static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	u32 r, g, b;
-
-	dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
-		regno, red, green, blue, transp, info->var.bits_per_pixel);
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno >= 256)
-			return -EINVAL;
-		i740outb(info->par, VGA_PEL_IW, regno);
-		i740outb(info->par, VGA_PEL_D, red >> 8);
-		i740outb(info->par, VGA_PEL_D, green >> 8);
-		i740outb(info->par, VGA_PEL_D, blue >> 8);
-		break;
-	case FB_VISUAL_TRUECOLOR:
-		if (regno >= 16)
-			return -EINVAL;
-		r = (red >> (16 - info->var.red.length))
-			<< info->var.red.offset;
-		b = (blue >> (16 - info->var.blue.length))
-			<< info->var.blue.offset;
-		g = (green >> (16 - info->var.green.length))
-			<< info->var.green.offset;
-		((u32 *) info->pseudo_palette)[regno] = r | g | b;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int i740fb_pan_display(struct fb_var_screeninfo *var,
-				 struct fb_info *info)
-{
-	struct i740fb_par *par = info->par;
-	u32 base = (var->yoffset * info->var.xres_virtual
-		 + (var->xoffset & ~7)) >> 2;
-
-	dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
-		var->xoffset, var->yoffset, base);
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		break;
-	case 15:
-	case 16:
-		base *= 2;
-		break;
-	case 24:
-		/*
-		 * The last bit does not seem to have any effect on the start
-		 * address register in 24bpp mode, so...
-		 */
-		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
-		base *= 3;
-		break;
-	case 32:
-		base *= 4;
-		break;
-	}
-
-	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
-	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
-	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
-	par->ext_start_addr =
-			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
-
-	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO,  base & 0x000000FF);
-	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
-			(base & 0x0000FF00) >> 8);
-	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
-			(base & 0x3FC00000) >> 22);
-	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
-			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
-
-	return 0;
-}
-
-static int i740fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct i740fb_par *par = info->par;
-
-	unsigned char SEQ01;
-	int DPMSSyncSelect;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		SEQ01 = 0x00;
-		DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		SEQ01 = 0x20;
-		DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		SEQ01 = 0x20;
-		DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
-		break;
-	case FB_BLANK_POWERDOWN:
-		SEQ01 = 0x20;
-		DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
-		break;
-	default:
-		return -EINVAL;
-	}
-	/* Turn the screen on/off */
-	i740outb(par, SRX, 0x01);
-	SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
-	i740outb(par, SRX, 0x01);
-	i740outb(par, SRX + 1, SEQ01);
-
-	/* Set the DPMS mode */
-	i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
-
-	/* Let fbcon do a soft blank for us */
-	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
-}
-
-static struct fb_ops i740fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= i740fb_open,
-	.fb_release	= i740fb_release,
-	.fb_check_var	= i740fb_check_var,
-	.fb_set_par	= i740fb_set_par,
-	.fb_setcolreg	= i740fb_setcolreg,
-	.fb_blank	= i740fb_blank,
-	.fb_pan_display	= i740fb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-/* ------------------------------------------------------------------------- */
-
-static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	struct fb_info *info;
-	struct i740fb_par *par;
-	int ret, tmp;
-	bool found = false;
-	u8 *edid;
-
-	info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
-	if (!info) {
-		dev_err(&(dev->dev), "cannot allocate framebuffer\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	mutex_init(&par->open_lock);
-
-	info->var.activate = FB_ACTIVATE_NOW;
-	info->var.bits_per_pixel = 8;
-	info->fbops = &i740fb_ops;
-	info->pseudo_palette = par->pseudo_palette;
-
-	ret = pci_enable_device(dev);
-	if (ret) {
-		dev_err(info->device, "cannot enable PCI device\n");
-		goto err_enable_device;
-	}
-
-	ret = pci_request_regions(dev, info->fix.id);
-	if (ret) {
-		dev_err(info->device, "error requesting regions\n");
-		goto err_request_regions;
-	}
-
-	info->screen_base = pci_ioremap_bar(dev, 0);
-	if (!info->screen_base) {
-		dev_err(info->device, "error remapping base\n");
-		ret = -ENOMEM;
-		goto err_ioremap_1;
-	}
-
-	par->regs = pci_ioremap_bar(dev, 1);
-	if (!par->regs) {
-		dev_err(info->device, "error remapping MMIO\n");
-		ret = -ENOMEM;
-		goto err_ioremap_2;
-	}
-
-	/* detect memory size */
-	if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
-							== DRAM_ROW_1_SDRAM)
-		i740outb(par, XRX, DRAM_ROW_BNDRY_1);
-	else
-		i740outb(par, XRX, DRAM_ROW_BNDRY_0);
-	info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
-	/* detect memory type */
-	tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
-	par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
-			   (tmp & DRAM_RAS_PRECHARGE));
-
-	fb_info(info, "Intel740 on %s, %ld KB %s\n",
-		pci_name(dev), info->screen_size >> 10,
-		par->has_sgram ? "SGRAM" : "SDRAM");
-
-	info->fix = i740fb_fix;
-	info->fix.mmio_start = pci_resource_start(dev, 1);
-	info->fix.mmio_len = pci_resource_len(dev, 1);
-	info->fix.smem_start = pci_resource_start(dev, 0);
-	info->fix.smem_len = info->screen_size;
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-
-	if (i740fb_setup_ddc_bus(info) == 0) {
-		par->ddc_registered = true;
-		edid = fb_ddc_read(&par->ddc_adapter);
-		if (edid) {
-			fb_edid_to_monspecs(edid, &info->monspecs);
-			kfree(edid);
-			if (!info->monspecs.modedb)
-				dev_err(info->device,
-					"error getting mode database\n");
-			else {
-				const struct fb_videomode *m;
-
-				fb_videomode_to_modelist(
-					info->monspecs.modedb,
-					info->monspecs.modedb_len,
-					&info->modelist);
-				m = fb_find_best_display(&info->monspecs,
-							 &info->modelist);
-				if (m) {
-					fb_videomode_to_var(&info->var, m);
-					/* fill all other info->var's fields */
-					if (!i740fb_check_var(&info->var, info))
-						found = true;
-				}
-			}
-		}
-	}
-
-	if (!mode_option && !found)
-		mode_option = "640x480-8@60";
-
-	if (mode_option) {
-		ret = fb_find_mode(&info->var, info, mode_option,
-				   info->monspecs.modedb,
-				   info->monspecs.modedb_len,
-				   NULL, info->var.bits_per_pixel);
-		if (!ret || ret == 4) {
-			dev_err(info->device, "mode %s not found\n",
-				mode_option);
-			ret = -EINVAL;
-		}
-	}
-
-	fb_destroy_modedb(info->monspecs.modedb);
-	info->monspecs.modedb = NULL;
-
-	/* maximize virtual vertical size for fast scrolling */
-	info->var.yres_virtual = info->fix.smem_len * 8 /
-			(info->var.bits_per_pixel * info->var.xres_virtual);
-
-	if (ret == -EINVAL)
-		goto err_find_mode;
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret) {
-		dev_err(info->device, "cannot allocate colormap\n");
-		goto err_alloc_cmap;
-	}
-
-	ret = register_framebuffer(info);
-	if (ret) {
-		dev_err(info->device, "error registering framebuffer\n");
-		goto err_reg_framebuffer;
-	}
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	pci_set_drvdata(dev, info);
-#ifdef CONFIG_MTRR
-	if (mtrr) {
-		par->mtrr_reg = -1;
-		par->mtrr_reg = mtrr_add(info->fix.smem_start,
-				info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-	}
-#endif
-	return 0;
-
-err_reg_framebuffer:
-	fb_dealloc_cmap(&info->cmap);
-err_alloc_cmap:
-err_find_mode:
-	if (par->ddc_registered)
-		i2c_del_adapter(&par->ddc_adapter);
-	pci_iounmap(dev, par->regs);
-err_ioremap_2:
-	pci_iounmap(dev, info->screen_base);
-err_ioremap_1:
-	pci_release_regions(dev);
-err_request_regions:
-/*	pci_disable_device(dev); */
-err_enable_device:
-	framebuffer_release(info);
-	return ret;
-}
-
-static void i740fb_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-
-	if (info) {
-		struct i740fb_par *par = info->par;
-
-#ifdef CONFIG_MTRR
-		if (par->mtrr_reg >= 0) {
-			mtrr_del(par->mtrr_reg, 0, 0);
-			par->mtrr_reg = -1;
-		}
-#endif
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		if (par->ddc_registered)
-			i2c_del_adapter(&par->ddc_adapter);
-		pci_iounmap(dev, par->regs);
-		pci_iounmap(dev, info->screen_base);
-		pci_release_regions(dev);
-/*		pci_disable_device(dev); */
-		framebuffer_release(info);
-	}
-}
-
-#ifdef CONFIG_PM
-static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct i740fb_par *par = info->par;
-
-	/* don't disable console during hibernation and wakeup from it */
-	if (state.event == PM_EVENT_FREEZE || state.event == PM_EVENT_PRETHAW)
-		return 0;
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	/* do nothing if framebuffer is not active */
-	if (par->ref_count == 0) {
-		mutex_unlock(&(par->open_lock));
-		console_unlock();
-		return 0;
-	}
-
-	fb_set_suspend(info, 1);
-
-	pci_save_state(dev);
-	pci_disable_device(dev);
-	pci_set_power_state(dev, pci_choose_state(dev, state));
-
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-
-	return 0;
-}
-
-static int i740fb_resume(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct i740fb_par *par = info->par;
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	if (par->ref_count == 0)
-		goto fail;
-
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
-	if (pci_enable_device(dev))
-		goto fail;
-
-	i740fb_set_par(info);
-	fb_set_suspend(info, 0);
-
-fail:
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-	return 0;
-}
-#else
-#define i740fb_suspend NULL
-#define i740fb_resume NULL
-#endif /* CONFIG_PM */
-
-#define I740_ID_PCI 0x00d1
-#define I740_ID_AGP 0x7800
-
-static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, i740fb_id_table);
-
-static struct pci_driver i740fb_driver = {
-	.name		= "i740fb",
-	.id_table	= i740fb_id_table,
-	.probe		= i740fb_probe,
-	.remove		= i740fb_remove,
-	.suspend	= i740fb_suspend,
-	.resume		= i740fb_resume,
-};
-
-#ifndef MODULE
-static int  __init i740fb_setup(char *options)
-{
-	char *opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-#ifdef CONFIG_MTRR
-		else if (!strncmp(opt, "mtrr:", 5))
-			mtrr = simple_strtoul(opt + 5, NULL, 0);
-#endif
-		else
-			mode_option = opt;
-	}
-
-	return 0;
-}
-#endif
-
-static int __init i740fb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("i740fb", &option))
-		return -ENODEV;
-	i740fb_setup(option);
-#endif
-
-	return pci_register_driver(&i740fb_driver);
-}
-
-static void __exit i740fb_exit(void)
-{
-	pci_unregister_driver(&i740fb_driver);
-}
-
-module_init(i740fb_init);
-module_exit(i740fb_exit);
-
-MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("fbdev driver for Intel740");
-
-module_param(mode_option, charp, 0444);
-MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
-
-#ifdef CONFIG_MTRR
-module_param(mtrr, int, 0444);
-MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
-#endif
diff --git a/drivers/video/i810/Makefile b/drivers/video/i810/Makefile
deleted file mode 100644
index 96e08c8ded97..000000000000
--- a/drivers/video/i810/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Makefile for the Intel 810/815 framebuffer driver
-#
-
-obj-$(CONFIG_FB_I810)		+= i810fb.o
-
-i810fb-objs                     := i810_main.o i810_accel.o
-
-ifdef CONFIG_FB_I810_GTF
-i810fb-objs                     += i810_gtf.o
-else
-i810fb-objs                     += i810_dvt.o
-endif
-
-ifdef CONFIG_FB_I810_I2C
-i810fb-objs += i810-i2c.o
-endif
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
deleted file mode 100644
index 7db17d0d8a8c..000000000000
--- a/drivers/video/i810/i810-i2c.c
+++ /dev/null
@@ -1,175 +0,0 @@
- /*-*- linux-c -*-
- *  linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support
- *
- *      Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <linux/pci.h>
-#include <linux/fb.h>
-#include "i810.h"
-#include "i810_regs.h"
-#include "i810_main.h"
-#include "../edid.h"
-
-/* bit locations in the registers */
-#define SCL_DIR_MASK		0x0001
-#define SCL_DIR			0x0002
-#define SCL_VAL_MASK		0x0004
-#define SCL_VAL_OUT		0x0008
-#define SCL_VAL_IN		0x0010
-#define SDA_DIR_MASK		0x0100
-#define SDA_DIR			0x0200
-#define SDA_VAL_MASK		0x0400
-#define SDA_VAL_OUT		0x0800
-#define SDA_VAL_IN		0x1000
-
-#define DEBUG  /* define this for verbose EDID parsing output */
-
-#ifdef DEBUG
-#define DPRINTK(fmt, args...) printk(fmt,## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-static void i810i2c_setscl(void *data, int state)
-{
-        struct i810fb_i2c_chan    *chan = data;
-        struct i810fb_par         *par = chan->par;
-	u8                        __iomem *mmio = par->mmio_start_virtual;
-
-	if (state)
-		i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK);
-	else
-		i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
-	i810_readl(mmio, chan->ddc_base);	/* flush posted write */
-}
-
-static void i810i2c_setsda(void *data, int state)
-{
-        struct i810fb_i2c_chan    *chan = data;
-        struct i810fb_par         *par = chan->par;
-	u8                        __iomem *mmio = par->mmio_start_virtual;
-
-	if (state)
-		i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK);
-	else
-		i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
-	i810_readl(mmio, chan->ddc_base);	/* flush posted write */
-}
-
-static int i810i2c_getscl(void *data)
-{
-        struct i810fb_i2c_chan    *chan = data;
-        struct i810fb_par         *par = chan->par;
-	u8                        __iomem *mmio = par->mmio_start_virtual;
-
-	i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK);
-	i810_writel(mmio, chan->ddc_base, 0);
-	return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0);
-}
-
-static int i810i2c_getsda(void *data)
-{
-        struct i810fb_i2c_chan    *chan = data;
-        struct i810fb_par         *par = chan->par;
-	u8                        __iomem *mmio = par->mmio_start_virtual;
-
-	i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK);
-	i810_writel(mmio, chan->ddc_base, 0);
-	return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0);
-}
-
-static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
-{
-        int rc;
-
-        strcpy(chan->adapter.name, name);
-        chan->adapter.owner             = THIS_MODULE;
-        chan->adapter.algo_data         = &chan->algo;
-        chan->adapter.dev.parent        = &chan->par->dev->dev;
-	chan->algo.setsda               = i810i2c_setsda;
-	chan->algo.setscl               = i810i2c_setscl;
-	chan->algo.getsda               = i810i2c_getsda;
-	chan->algo.getscl               = i810i2c_getscl;
-	chan->algo.udelay               = 10;
-        chan->algo.timeout              = (HZ/2);
-        chan->algo.data                 = chan;
-
-        i2c_set_adapdata(&chan->adapter, chan);
-
-        /* Raise SCL and SDA */
-        chan->algo.setsda(chan, 1);
-        chan->algo.setscl(chan, 1);
-        udelay(20);
-
-        rc = i2c_bit_add_bus(&chan->adapter);
-
-        if (rc == 0)
-                dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name);
-        else {
-                dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
-			 "%s.\n", name);
-		chan->par = NULL;
-	}
-
-        return rc;
-}
-
-void i810_create_i2c_busses(struct i810fb_par *par)
-{
-        par->chan[0].par        = par;
-	par->chan[1].par        = par;
-	par->chan[2].par        = par;
-
-	par->chan[0].ddc_base = GPIOA;
-	i810_setup_i2c_bus(&par->chan[0], "I810-DDC");
-	par->chan[1].ddc_base = GPIOB;
-	i810_setup_i2c_bus(&par->chan[1], "I810-I2C");
-	par->chan[2].ddc_base = GPIOC;
-	i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC");
-}
-
-void i810_delete_i2c_busses(struct i810fb_par *par)
-{
-        if (par->chan[0].par)
-		i2c_del_adapter(&par->chan[0].adapter);
-        par->chan[0].par = NULL;
-
-	if (par->chan[1].par)
-		i2c_del_adapter(&par->chan[1].adapter);
-	par->chan[1].par = NULL;
-
-	if (par->chan[2].par)
-		i2c_del_adapter(&par->chan[2].adapter);
-	par->chan[2].par = NULL;
-}
-
-int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
-{
-	struct i810fb_par *par = info->par;
-        u8 *edid = NULL;
-
-	DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1);
-	if (conn < par->ddc_num) {
-		edid = fb_ddc_read(&par->chan[conn].adapter);
-	} else {
-		const u8 *e = fb_firmware_edid(info->device);
-
-		if (e != NULL) {
-			DPRINTK("i810-i2c: Getting EDID from BIOS\n");
-			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
-		}
-	}
-
-	*out_edid = edid;
-
-        return (edid) ? 0 : 1;
-}
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
deleted file mode 100644
index 1414b73ac55b..000000000000
--- a/drivers/video/i810/i810.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*-*- linux-c -*-
- *  linux/drivers/video/i810.h -- Intel 810 General Definitions/Declarations
- *
- *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
- *
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#ifndef __I810_H__
-#define __I810_H__
-
-#include <linux/list.h>
-#include <linux/agp_backend.h>
-#include <linux/fb.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <video/vga.h>
-
-/* Fence */
-#define TILEWALK_X            (0 << 12)
-#define TILEWALK_Y            (1 << 12)
-
-/* Raster ops */
-#define COLOR_COPY_ROP        0xF0
-#define PAT_COPY_ROP          0xCC
-#define CLEAR_ROP             0x00
-#define WHITE_ROP             0xFF
-#define INVERT_ROP            0x55
-#define XOR_ROP               0x5A
-
-/* 2D Engine definitions */
-#define SOLIDPATTERN          0x80000000
-#define NONSOLID              0x00000000
-#define BPP8                  (0 << 24)
-#define BPP16                 (1 << 24)
-#define BPP24                 (2 << 24)
-
-#define PIXCONF8              (2 << 16)
-#define PIXCONF15             (4 << 16)
-#define PIXCONF16             (5 << 16)
-#define PIXCONF24             (6 << 16)
-#define PIXCONF32             (7 << 16)
-
-#define DYN_COLOR_EN          (1 << 26)
-#define DYN_COLOR_DIS         (0 << 26)
-#define INCREMENT             0x00000000
-#define DECREMENT             (0x01 << 30)
-#define ARB_ON                0x00000001
-#define ARB_OFF               0x00000000
-#define SYNC_FLIP             0x00000000
-#define ASYNC_FLIP            0x00000040
-#define OPTYPE_MASK           0xE0000000
-#define PARSER_MASK           0x001F8000 
-#define D2_MASK               0x001FC000         /* 2D mask */
-
-/* Instruction type */
-/* There are more but pertains to 3D */
-#define PARSER                0x00000000
-#define BLIT                  (0x02 << 29)
-#define RENDER                (0x03 << 29)
-            
-/* Parser */
-#define NOP                   0x00               /* No operation, padding */
-#define BP_INT                (0x01 << 23)         /* Breakpoint interrupt */
-#define USR_INT               (0x02 << 23)         /* User interrupt */
-#define WAIT_FOR_EVNT         (0x03 << 23)         /* Wait for event */
-#define FLUSH                 (0x04 << 23)              
-#define CONTEXT_SEL           (0x05 << 23)
-#define REPORT_HEAD           (0x07 << 23)
-#define ARB_ON_OFF            (0x08 << 23)
-#define OVERLAY_FLIP          (0x11 << 23)
-#define LOAD_SCAN_INC         (0x12 << 23)
-#define LOAD_SCAN_EX          (0x13 << 23)
-#define FRONT_BUFFER          (0x14 << 23)
-#define DEST_BUFFER           (0x15 << 23)
-#define Z_BUFFER              (0x16 << 23)       
-
-#define STORE_DWORD_IMM       (0x20 << 23)
-#define STORE_DWORD_IDX       (0x21 << 23)
-#define BATCH_BUFFER          (0x30 << 23)
-
-/* Blit */
-#define SETUP_BLIT                      0x00
-#define SETUP_MONO_PATTERN_SL_BLT       (0x10 << 22)
-#define PIXEL_BLT                       (0x20 << 22)
-#define SCANLINE_BLT                    (0x21 << 22)
-#define TEXT_BLT                        (0x22 << 22)
-#define TEXT_IMM_BLT                    (0x30 << 22)
-#define COLOR_BLT                       (0x40 << 22)
-#define MONO_PAT_BLIT                   (0x42 << 22)
-#define SOURCE_COPY_BLIT                (0x43 << 22)
-#define MONO_SOURCE_COPY_BLIT           (0x44 << 22)
-#define SOURCE_COPY_IMMEDIATE           (0x60 << 22)
-#define MONO_SOURCE_COPY_IMMEDIATE      (0x61 << 22)
-
-#define VERSION_MAJOR            0
-#define VERSION_MINOR            9
-#define VERSION_TEENIE           0
-#define BRANCH_VERSION           ""
-
-
-/* mvo: intel i815 */
-#ifndef PCI_DEVICE_ID_INTEL_82815_100
-  #define PCI_DEVICE_ID_INTEL_82815_100           0x1102
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82815_NOAGP
-  #define PCI_DEVICE_ID_INTEL_82815_NOAGP         0x1112
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82815_FULL_CTRL
-  #define PCI_DEVICE_ID_INTEL_82815_FULL_CTRL     0x1130
-#endif 
-
-/* General Defines */
-#define I810_PAGESIZE               4096
-#define MAX_DMA_SIZE                (1024 * 4096)
-#define SAREA_SIZE                  4096
-#define PCI_I810_MISCC              0x72
-#define MMIO_SIZE                   (512*1024)
-#define GTT_SIZE                    (16*1024) 
-#define RINGBUFFER_SIZE             (64*1024)
-#define CURSOR_SIZE                 4096 
-#define OFF                         0
-#define ON                          1
-#define MAX_KEY                     256
-#define WAIT_COUNT                  10000000
-#define IRING_PAD                   8
-#define FONTDATAMAX                 8192
-/* Masks (AND ops) and OR's */
-#define FB_START_MASK               (0x3f << (32 - 6))
-#define MMIO_ADDR_MASK              (0x1FFF << (32 - 13))
-#define FREQ_MASK                   (1 << 4)
-#define SCR_OFF                     0x20
-#define DRAM_ON                     0x08            
-#define DRAM_OFF                    0xE7
-#define PG_ENABLE_MASK              0x01
-#define RING_SIZE_MASK              (RINGBUFFER_SIZE - 1)
-
-/* defines for restoring registers partially */
-#define ADDR_MAP_MASK               (0x07 << 5)
-#define DISP_CTRL                   ~0
-#define PIXCONF_0                   (0x64 << 8)
-#define PIXCONF_2                   (0xF3 << 24)
-#define PIXCONF_1                   (0xF0 << 16)
-#define MN_MASK                     0x3FF03FF
-#define P_OR                        (0x7 << 4)                    
-#define DAC_BIT                     (1 << 16)
-#define INTERLACE_BIT               (1 << 7)
-#define IER_MASK                    (3 << 13)
-#define IMR_MASK                    (3 << 13)
-
-/* Power Management */
-#define DPMS_MASK                   0xF0000
-#define POWERON                     0x00000
-#define STANDBY                     0x20000
-#define SUSPEND                     0x80000
-#define POWERDOWN                   0xA0000
-#define EMR_MASK                    ~0x3F
-#define FW_BLC_MASK                 ~(0x3F|(7 << 8)|(0x3F << 12)|(7 << 20))
-
-/* Ringbuffer */
-#define RBUFFER_START_MASK          0xFFFFF000
-#define RBUFFER_SIZE_MASK           0x001FF000
-#define RBUFFER_HEAD_MASK           0x001FFFFC
-#define RBUFFER_TAIL_MASK           0x001FFFF8
-
-/* Video Timings */
-#define REF_FREQ                    24000000
-#define TARGET_N_MAX                30
-
-#define MAX_PIXELCLOCK              230000000
-#define MIN_PIXELCLOCK               15000000
-#define VFMAX                       60
-#define VFMIN                       60
-#define HFMAX                       30000
-#define HFMIN                       29000
-
-/* Cursor */
-#define CURSOR_ENABLE_MASK          0x1000             
-#define CURSOR_MODE_64_TRANS        4
-#define CURSOR_MODE_64_XOR	    5
-#define CURSOR_MODE_64_3C	    6	
-#define COORD_INACTIVE              0
-#define COORD_ACTIVE                (1 << 4)
-#define EXTENDED_PALETTE	    1
-  
-/* AGP Memory Types*/
-#define AGP_NORMAL_MEMORY           0
-#define AGP_DCACHE_MEMORY	    1
-#define AGP_PHYSICAL_MEMORY         2
-
-/* Allocated resource Flags */
-#define FRAMEBUFFER_REQ             1
-#define MMIO_REQ                    2
-#define PCI_DEVICE_ENABLED          4
-#define HAS_FONTCACHE               8 
-
-/* driver flags */
-#define HAS_MTRR                    1
-#define HAS_ACCELERATION            2
-#define ALWAYS_SYNC                 4
-#define LOCKUP                      8
-
-struct gtt_data {
-	struct agp_memory *i810_fb_memory;
-	struct agp_memory *i810_cursor_memory;
-};
-
-struct mode_registers {
-	u32 pixclock, M, N, P;
-	u8 cr00, cr01, cr02, cr03;
-	u8 cr04, cr05, cr06, cr07;
-	u8 cr09, cr10, cr11, cr12;
-	u8 cr13, cr15, cr16, cr30;
-	u8 cr31, cr32, cr33, cr35, cr39;
-	u32 bpp8_100, bpp16_100;
-	u32 bpp24_100, bpp8_133;
-	u32 bpp16_133, bpp24_133;
-	u8 msr;
-};
-
-struct heap_data {
-        unsigned long physical;
-	__u8 __iomem *virtual;
-	u32 offset;
-	u32 size;
-};	
-
-struct state_registers {
-	u32 dclk_1d, dclk_2d, dclk_0ds;
-	u32 pixconf, fw_blc, pgtbl_ctl;
-	u32 fence0, hws_pga, dplystas;
-	u16 bltcntl, hwstam, ier, iir, imr;
-	u8 cr00, cr01, cr02, cr03, cr04;
-	u8 cr05, cr06, cr07, cr08, cr09;
-	u8 cr10, cr11, cr12, cr13, cr14;
-	u8 cr15, cr16, cr17, cr80, gr10;
-	u8 cr30, cr31, cr32, cr33, cr35;
-	u8 cr39, cr41, cr70, sr01, msr;
-};
-
-struct i810fb_par;
-
-struct i810fb_i2c_chan {
-	struct i810fb_par *par;
-	struct i2c_adapter adapter;
-	struct i2c_algo_bit_data algo;
-	unsigned long ddc_base;
-};
-
-struct i810fb_par {
-	struct mode_registers    regs;
-	struct state_registers   hw_state;
-	struct gtt_data          i810_gtt;
-	struct fb_ops            i810fb_ops;
-	struct pci_dev           *dev;
-	struct heap_data         aperture;
-	struct heap_data         fb;
-	struct heap_data         iring;
-	struct heap_data         cursor_heap;
-	struct vgastate          state;
-	struct i810fb_i2c_chan   chan[3];
-	struct mutex		 open_lock;
-	unsigned int		 use_count;
-	u32 pseudo_palette[16];
-	unsigned long mmio_start_phys;
-	u8 __iomem *mmio_start_virtual;
-	u8 *edid;
-	u32 pitch;
-	u32 pixconf;
-	u32 watermark;
-	u32 mem_freq;
-	u32 res_flags;
-	u32 dev_flags;
-	u32 cur_tail;
-	u32 depth;
-	u32 blit_bpp;
-	u32 ovract;
-	u32 cur_state;
-	u32 ddc_num;
-	int mtrr_reg;
-	u16 bltcntl;
-	u8 interlace;
-};
-
-/* 
- * Register I/O
- */
-#define i810_readb(where, mmio) readb(mmio + where)
-#define i810_readw(where, mmio) readw(mmio + where)
-#define i810_readl(where, mmio) readl(mmio + where)
-#define i810_writeb(where, mmio, val) writeb(val, mmio + where) 
-#define i810_writew(where, mmio, val) writew(val, mmio + where)
-#define i810_writel(where, mmio, val) writel(val, mmio + where)
-
-#endif /* __I810_H__ */
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c
deleted file mode 100644
index 7672d2ea9b35..000000000000
--- a/drivers/video/i810/i810_accel.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*-*- linux-c -*-
- *  linux/drivers/video/i810_accel.c -- Hardware Acceleration
- *
- *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include "i810_regs.h"
-#include "i810.h"
-#include "i810_main.h"
-
-static u32 i810fb_rop[] = {
-	COLOR_COPY_ROP, /* ROP_COPY */
-	XOR_ROP         /* ROP_XOR  */
-};
-
-/* Macros */
-#define PUT_RING(n) {                                        \
-	i810_writel(par->cur_tail, par->iring.virtual, n);   \
-        par->cur_tail += 4;                                  \
-        par->cur_tail &= RING_SIZE_MASK;                     \
-}                                                                      
-
-extern void flush_cache(void);
-
-/************************************************************/
-
-/* BLT Engine Routines */
-static inline void i810_report_error(u8 __iomem *mmio)
-{
-	printk("IIR     : 0x%04x\n"
-	       "EIR     : 0x%04x\n"
-	       "PGTBL_ER: 0x%04x\n"
-	       "IPEIR   : 0x%04x\n"
-	       "IPEHR   : 0x%04x\n",
-	       i810_readw(IIR, mmio),
-	       i810_readb(EIR, mmio),
-	       i810_readl(PGTBL_ER, mmio),
-	       i810_readl(IPEIR, mmio), 
-	       i810_readl(IPEHR, mmio));
-}
-
-/**
- * wait_for_space - check ring buffer free space
- * @space: amount of ringbuffer space needed in bytes
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * The function waits until a free space from the ringbuffer
- * is available 
- */	
-static inline int wait_for_space(struct fb_info *info, u32 space)
-{
-	struct i810fb_par *par = info->par;
-	u32 head, count = WAIT_COUNT, tail;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	tail = par->cur_tail;
-	while (count--) {
-		head = i810_readl(IRING + 4, mmio) & RBUFFER_HEAD_MASK;	
-		if ((tail == head) || 
-		    (tail > head && 
-		     (par->iring.size - tail + head) >= space) || 
-		    (tail < head && (head - tail) >= space)) {
-			return 0;	
-		}
-	}
-	printk("ringbuffer lockup!!!\n");
-	i810_report_error(mmio); 
-	par->dev_flags |= LOCKUP;
-	info->pixmap.scan_align = 1;
-	return 1;
-}
-
-/** 
- * wait_for_engine_idle - waits for all hardware engines to finish
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * This waits for lring(0), iring(1), and batch(3), etc to finish and
- * waits until ringbuffer is empty.
- */
-static inline int wait_for_engine_idle(struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	int count = WAIT_COUNT;
-
-	if (wait_for_space(info, par->iring.size)) /* flush */
-		return 1;
-
-	while((i810_readw(INSTDONE, mmio) & 0x7B) != 0x7B && --count); 
-	if (count) return 0;
-
-	printk("accel engine lockup!!!\n");
-	printk("INSTDONE: 0x%04x\n", i810_readl(INSTDONE, mmio));
-	i810_report_error(mmio); 
-	par->dev_flags |= LOCKUP;
-	info->pixmap.scan_align = 1;
-	return 1;
-}
-
-/* begin_iring - prepares the ringbuffer 
- * @space: length of sequence in dwords
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Checks/waits for sufficient space in ringbuffer of size
- * space.  Returns the tail of the buffer
- */ 
-static inline u32 begin_iring(struct fb_info *info, u32 space)
-{
-	struct i810fb_par *par = info->par;
-
-	if (par->dev_flags & ALWAYS_SYNC) 
-		wait_for_engine_idle(info);
-	return wait_for_space(info, space);
-}
-
-/**
- * end_iring - advances the buffer
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * This advances the tail of the ringbuffer, effectively
- * beginning the execution of the graphics instruction sequence.
- */
-static inline void end_iring(struct i810fb_par *par)
-{
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	i810_writel(IRING, mmio, par->cur_tail);
-}
-
-/**
- * source_copy_blit - BLIT transfer operation
- * @dwidth: width of rectangular graphics data
- * @dheight: height of rectangular graphics data
- * @dpitch: bytes per line of destination buffer
- * @xdir: direction of copy (left to right or right to left)
- * @src: address of first pixel to read from
- * @dest: address of first pixel to write to
- * @from: source address
- * @where: destination address
- * @rop: raster operation
- * @blit_bpp: pixel format which can be different from the 
- *            framebuffer's pixelformat
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * This is a BLIT operation typically used when doing
- * a 'Copy and Paste'
- */
-static inline void source_copy_blit(int dwidth, int dheight, int dpitch, 
-				    int xdir, int src, int dest, int rop, 
-				    int blit_bpp, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-
-	if (begin_iring(info, 24 + IRING_PAD)) return;
-
-	PUT_RING(BLIT | SOURCE_COPY_BLIT | 4);
-	PUT_RING(xdir | rop << 16 | dpitch | DYN_COLOR_EN | blit_bpp);
-	PUT_RING(dheight << 16 | dwidth);
-	PUT_RING(dest);
-	PUT_RING(dpitch);
-	PUT_RING(src);
-
-	end_iring(par);
-}	
-
-/**
- * color_blit - solid color BLIT operation
- * @width: width of destination
- * @height: height of destination
- * @pitch: pixels per line of the buffer
- * @dest: address of first pixel to write to
- * @where: destination
- * @rop: raster operation
- * @what: color to transfer
- * @blit_bpp: pixel format which can be different from the 
- *            framebuffer's pixelformat
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * A BLIT operation which can be used for  color fill/rectangular fill
- */
-static inline void color_blit(int width, int height, int pitch,  int dest, 
-			      int rop, int what, int blit_bpp, 
-			      struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-
-	if (begin_iring(info, 24 + IRING_PAD)) return;
-
-	PUT_RING(BLIT | COLOR_BLT | 3);
-	PUT_RING(rop << 16 | pitch | SOLIDPATTERN | DYN_COLOR_EN | blit_bpp);
-	PUT_RING(height << 16 | width);
-	PUT_RING(dest);
-	PUT_RING(what);
-	PUT_RING(NOP);
-
-	end_iring(par);
-}
- 
-/**
- * mono_src_copy_imm_blit - color expand from system memory to framebuffer
- * @dwidth: width of destination
- * @dheight: height of destination
- * @dpitch: pixels per line of the buffer
- * @dsize: size of bitmap in double words
- * @dest: address of first byte of pixel;
- * @rop: raster operation
- * @blit_bpp: pixelformat to use which can be different from the 
- *            framebuffer's pixelformat
- * @src: address of image data
- * @bg: backgound color
- * @fg: forground color
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * A color expand operation where the  source data is placed in the 
- * ringbuffer itself. Useful for drawing text. 
- *
- * REQUIREMENT:
- * The end of a scanline must be padded to the next word.
- */
-static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
-					  int dsize, int blit_bpp, int rop,
-					  int dest, const u32 *src, int bg,
-					  int fg, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-
-	if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
-
-	PUT_RING(BLIT | MONO_SOURCE_COPY_IMMEDIATE | (4 + dsize));
-	PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch);
-	PUT_RING(dheight << 16 | dwidth);
-	PUT_RING(dest);
-	PUT_RING(bg);
-	PUT_RING(fg);
-	while (dsize--) 
-		PUT_RING(*src++);
-
-	end_iring(par);
-}
-
-static inline void load_front(int offset, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-
-	if (begin_iring(info, 8 + IRING_PAD)) return;
-
-	PUT_RING(PARSER | FLUSH);
-	PUT_RING(NOP);
-
-	end_iring(par);
-
-	if (begin_iring(info, 8 + IRING_PAD)) return;
-
-	PUT_RING(PARSER | FRONT_BUFFER | ((par->pitch >> 3) << 8));
-	PUT_RING((par->fb.offset << 12) + offset);
-
-	end_iring(par);
-}
-
-/**
- * i810fb_iring_enable - enables/disables the ringbuffer
- * @mode: enable or disable
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Enables or disables the ringbuffer, effectively enabling or
- * disabling the instruction/acceleration engine.
- */
-static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
-{
-	u32 tmp;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	tmp = i810_readl(IRING + 12, mmio);
-	if (mode == OFF) 
-		tmp &= ~1;
-	else 
-		tmp |= 1;
-	flush_cache();
-	i810_writel(IRING + 12, mmio, tmp);
-}       
-
-void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct i810fb_par *par = info->par;
-	u32 dx, dy, width, height, dest, rop = 0, color = 0;
-
-	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
-	    par->depth == 4) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	if (par->depth == 1) 
-		color = rect->color;
-	else 
-		color = ((u32 *) (info->pseudo_palette))[rect->color];
-
-	rop = i810fb_rop[rect->rop];
-
-	dx = rect->dx * par->depth;
-	width = rect->width * par->depth;
-	dy = rect->dy;
-	height = rect->height;
-
-	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
-	color_blit(width, height, info->fix.line_length, dest, rop, color, 
-		   par->blit_bpp, info);
-}
-	
-void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) 
-{
-	struct i810fb_par *par = info->par;
-	u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
-
-	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
-	    par->depth == 4) {
-		cfb_copyarea(info, region);
-		return;
-	}
-
-	dx = region->dx * par->depth;
-	sx = region->sx * par->depth;
-	width = region->width * par->depth;
-	sy = region->sy;
-	dy = region->dy;
-	height = region->height;
-
-	if (dx <= sx) {
-		xdir = INCREMENT;
-	}
-	else {
-		xdir = DECREMENT;
-		sx += width - 1;
-		dx += width - 1;
-	}
-	if (dy <= sy) {
-		pitch = info->fix.line_length;
-	}
-	else {
-		pitch = (-(info->fix.line_length)) & 0xFFFF;
-		sy += height - 1;
-		dy += height - 1;
-	}
-	src = info->fix.smem_start + (sy * info->fix.line_length) + sx;
-	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
-
-	source_copy_blit(width, height, pitch, xdir, src, dest,
-			 PAT_COPY_ROP, par->blit_bpp, info);
-}
-
-void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct i810fb_par *par = info->par;
-	u32 fg = 0, bg = 0, size, dst;
-	
-	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
-	    par->depth == 4 || image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		fg = image->fg_color;
-		bg = image->bg_color;
-		break;
-	case 16:
-	case 24:
-		fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
-		bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
-		break;
-	}	
-	
-	dst = info->fix.smem_start + (image->dy * info->fix.line_length) + 
-		(image->dx * par->depth);
-
-	size = (image->width+7)/8 + 1;
-	size &= ~1;
-	size *= image->height;
-	size += 7;
-	size &= ~7;
-	mono_src_copy_imm_blit(image->width * par->depth, 
-			       image->height, info->fix.line_length, 
-			       size/4, par->blit_bpp,
-			       PAT_COPY_ROP, dst, (u32 *) image->data, 
-			       bg, fg, info);
-} 
-
-int i810fb_sync(struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	
-	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
-		return 0;
-
-	return wait_for_engine_idle(info);
-}
-
-void i810fb_load_front(u32 offset, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
-		i810_writel(DPLYBASE, mmio, par->fb.physical + offset);
-	else 
-		load_front(offset, info);
-}
-
-/**
- * i810fb_init_ringbuffer - initialize the ringbuffer
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Initializes the ringbuffer by telling the device the
- * size and location of the ringbuffer.  It also sets 
- * the head and tail pointers = 0
- */
-void i810fb_init_ringbuffer(struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u32 tmp1, tmp2;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	
-	wait_for_engine_idle(info);
-	i810fb_iring_enable(par, OFF);
-	i810_writel(IRING, mmio, 0);
-	i810_writel(IRING + 4, mmio, 0);
-	par->cur_tail = 0;
-
-	tmp2 = i810_readl(IRING + 8, mmio) & ~RBUFFER_START_MASK; 
-	tmp1 = par->iring.physical;
-	i810_writel(IRING + 8, mmio, tmp2 | tmp1);
-
-	tmp1 = i810_readl(IRING + 12, mmio);
-	tmp1 &= ~RBUFFER_SIZE_MASK;
-	tmp2 = (par->iring.size - I810_PAGESIZE) & RBUFFER_SIZE_MASK;
-	i810_writel(IRING + 12, mmio, tmp1 | tmp2);
-	i810fb_iring_enable(par, ON);
-}
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
deleted file mode 100644
index b4b3670667ab..000000000000
--- a/drivers/video/i810/i810_dvt.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*-*- linux-c -*-
- *  linux/drivers/video/i810_dvt.c -- Intel 810 Discrete Video Timings (Intel)
- *
- *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
- *
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/kernel.h>
-
-#include "i810_regs.h"
-#include "i810.h"
-
-struct mode_registers std_modes[] = {
-	/* 640x480 @ 60Hz */
-	{ 25000, 0x0013, 0x0003, 0x40, 0x5F, 0x4F, 0x50, 0x82, 0x51, 0x9D,
-	  0x0B, 0x10, 0x40, 0xE9, 0x0B, 0xDF, 0x50, 0xE7, 0x04, 0x02,
-	  0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22006000,
-	  0x22002000, 0x22004000, 0x22006000, 0xC0 }, 
-	  
-	/* 640x480 @ 70Hz */
-	{ 28000, 0x0053, 0x0010, 0x40, 0x61, 0x4F, 0x4F, 0x85, 0x52, 0x9A,
-	  0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01, 
-	  0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22005000,
-          0x22002000, 0x22004000, 0x22005000, 0xC0 },
-          
-        /* 640x480 @ 72Hz */
-        { 31000, 0x0013, 0x0002, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x52, 0x97,
-          0x06, 0x0F, 0x40, 0xE8, 0x0B, 0xDF, 0x50, 0xDF, 0x07, 0x02, 
-          0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000,
-          0x22003000, 0x22005000, 0x22007000, 0xC0 },
-          
-        /* 640x480 @ 75Hz */
-        { 31000, 0x0013, 0x0002, 0x40, 0x64, 0x4F, 0x4F, 0x88, 0x51, 0x99, 
-          0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01, 
-          0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000, 
-          0x22003000, 0x22005000, 0x22007000, 0xC0 },
-          
-        /* 640x480 @ 85Hz */
-        { 36000, 0x0010, 0x0001, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x56, 0x9D,
-          0xFB, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xFC, 0x01,
-          0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
-          0x22003000, 0x22005000, 0x22107000, 0xC0 },
-          
-        /* 800x600 @ 56Hz */
-        { 36000, 0x0010, 0x0001, 0x40, 0x7B, 0x63, 0x63, 0x9F, 0x66, 0x8F,
-          0x6F, 0x10, 0x40, 0x58, 0x0A, 0x57, 0xC8, 0x57, 0x70, 0x02, 
-          0x02, 0x02, 0x02, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
-          0x22003000, 0x22005000, 0x22107000, 0x00 },
-          
-        /* 800x600 @ 60Hz */
-        { 40000, 0x0008, 0x0001, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x68, 0x18, 
-          0x72, 0x10, 0x40, 0x58, 0x0C, 0x57, 0xC8, 0x57, 0x73, 0x02,
-          0x02, 0x02, 0x02, 0x00, 0x00, 0x22003000, 0x22006000, 0x22108000,
-          0x22003000, 0x22006000, 0x22108000, 0x00 },
-          
-        /* 800x600 @ 70Hz */
-        { 45000, 0x0054, 0x0015, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x68, 0x12,
-          0x6f, 0x10, 0x40, 0x58, 0x0b, 0x57, 0x64, 0x57, 0x70, 0x02, 
-          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000, 
-          0x22004000, 0x22007000, 0x2210A000, 0x00 },
-          
-        /* 800x600 @ 72Hz */
-        { 50000, 0x0017, 0x0004, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x6A, 0x19,
-          0x98, 0x10, 0x40, 0x7C, 0x02, 0x57, 0xC8, 0x57, 0x99, 0x02, 
-          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000,
-          0x22004000, 0x22007000, 0x2210A000, 0x00 }, 
-          
-        /* 800x600 @ 75Hz */
-        { 49000, 0x001F, 0x0006, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x65, 0x0F,
-          0x6F, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x70, 0x02, 
-          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210B000,
-          0x22004000, 0x22007000, 0x2210B000, 0x00 },
-          
-        /* 800x600 @ 85Hz */
-        { 56000, 0x0049, 0x000E, 0x30, 0x7E, 0x63, 0x63, 0x82, 0x67, 0x0F,
-          0x75, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x76, 0x02,
-          0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22108000, 0x2210b000, 
-          0x22004000, 0x22108000, 0x2210b000, 0x00 },
-          
-        /* 1024x768 @ 60Hz */
-        { 65000, 0x003F, 0x000A, 0x30, 0xA3, 0x7F, 0x7F, 0x87, 0x83, 0x94,
-          0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
-          0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x22109000, 0x2220D000,
-          0x22005000, 0x22109000, 0x2220D000, 0xC0 },
-          
-        /* 1024x768 @ 70Hz */
-	{ 75000, 0x0017, 0x0002, 0x30, 0xA1, 0x7F, 0x7F, 0x85, 0x82, 0x93,
-	  0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
-	  0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x2210A000, 0x2220F000,
-	  0x22005000, 0x2210A000, 0x2220F000, 0xC0 }, 
-	  
-	/* 1024x768 @ 75Hz */          
-	{ 78000, 0x0050, 0x0017, 0x20, 0x9F, 0x7F, 0x7F, 0x83, 0x81, 0x8D,
-	  0x1E, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x1F, 0x03,
-	  0x02, 0x03, 0x02, 0x00, 0x00, 0x22006000, 0x2210B000, 0x22210000,
-	  0x22006000, 0x2210B000, 0x22210000, 0x00 },
-	  
-	/* 1024x768 @ 85Hz */
-	{ 94000, 0x003D, 0x000E, 0x20, 0xA7, 0x7F, 0x7F, 0x8B, 0x85, 0x91,
-	  0x26, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x27, 0x03,
-	  0x02, 0x03, 0x02, 0x00, 0x00, 0x22007000, 0x2220E000, 0x22212000,
-	  0x22007000, 0x2220E000, 0x22212000, 0x00 },
-	  
-	/* 1152x864 @ 60Hz */ 
-	{ 80000, 0x0008, 0x0001, 0x20, 0xB3, 0x8F, 0x8F, 0x97, 0x93, 0x9f,
-	  0x87, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5f, 0x88, 0x03,
-	  0x03, 0x03, 0x03, 0x00, 0x00, 0x2220C000, 0x22210000, 0x22415000,   
-	  0x2220C000, 0x22210000, 0x22415000, 0x00 },
-	  
-	/* 1152x864 @ 70Hz */
-	{ 96000, 0x000a, 0x0001, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87, 
-	  0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03,
-	  0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
-	  0x22107000, 0x22210000, 0x22415000, 0x00 },
-	  
-	/* 1152x864 @ 72Hz */
-	{ 99000, 0x001f, 0x0006, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87,
-	  0x83, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x84, 0x03,
-	  0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
-	  0x22107000, 0x22210000, 0x22415000, 0x00 },
-	  
-	/* 1152x864 @ 75Hz */
-	{ 108000, 0x0010, 0x0002, 0x20, 0xC3, 0x8F, 0x8F, 0x87, 0x97, 0x07,
-	  0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03, 
-	  0x03, 0x03, 0x03, 0x00, 0x01, 0x22107000, 0x22210000, 0x22415000,
-	  0x22107000, 0x22210000, 0x22415000, 0x00 },
-	  
-	/* 1152x864 @ 85Hz */
-	{ 121000, 0x006D, 0x0014, 0x20, 0xc0, 0x8F, 0x8F, 0x84, 0x97, 0x07,
-	  0x93, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x94, 0x03, 
-	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2220C000, 0x22210000, 0x22415000,
-	  0x2220C000, 0x22210000, 0x22415000, 0x0 },
-	  
-	/* 1280x960 @ 60Hz */
-	{ 108000, 0x0010, 0x0002, 0x20, 0xDC, 0x9F, 0x9F, 0x80, 0xAB, 0x99,
-	  0xE6, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE7, 0x03,
-	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x22415000,
-	  0x2210A000, 0x22210000, 0x22415000, 0x00 },
-	  
-	/* 1280x960 @ 75Hz */
-	{ 129000, 0x0029, 0x0006, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xaa, 0x1b,
-	  0xE8, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE9, 0x03,
-	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x2241B000,
-	  0x2210A000, 0x22210000, 0x2241B000, 0x00 },
-	  
-	/* 1280x960 @ 85Hz */
-	{ 148000, 0x0042, 0x0009, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xA7, 0x1B,
-	  0xF1, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xF2, 0x03,
-	  0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22220000, 0x2241D000,       
-	  0x2210A000, 0x22220000, 0x2241D000, 0x00 },
-	  
-	/* 1600x1200 @ 60Hz */
-	{ 162000, 0x0019, 0x0006, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
-	  0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04, 
-	  0x04, 0x04, 0x04, 0x01, 0x00, 0x2210b000, 0x22416000, 0x44419000,
-	  0x2210b000, 0x22416000, 0x44419000, 0x00 },
-	  
-	/* 1600x1200 @ 65 Hz */
-	{ 175000, 0x005d, 0x0018, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
-	  0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04, 
-	  0x04, 0x04, 0x04, 0x01, 0x00, 0x2210c000, 0x22416000, 0x44419000,
-	  0x2210c000, 0x22416000, 0x44419000, 0x00 },
-	  
-	/* 1600x1200 @ 70 Hz */
-	{ 189000, 0x003D, 0x000e, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
-	  0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 
-	  0x04, 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
-	  0x2220e000, 0x22416000, 0x44419000, 0x00 },
-	  
- 	/* 1600x1200 @ 72 Hz */
- 	{ 195000, 0x003f, 0x000e, 0x10, 0x0b, 0xC7, 0xC7, 0x8f, 0xd5, 0x0b,
- 	  0xE1, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xe2, 0x04, 0x04,
- 	  0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
- 	  0x2220e000, 0x22416000, 0x44419000, 0x00 }, 
- 	  
- 	/* 1600x1200 @ 75 Hz */
- 	{ 202000, 0x0024, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
- 	  0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
- 	  0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,      
- 	  0x2220e000, 0x22416000, 0x44419000,  0x00 },
- 	  
- 	/* 1600x1200 @ 85 Hz */
-	{ 229000, 0x0029, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
-	  0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
-	  0x04, 0x04, 0x01, 0x00, 0x22210000, 0x22416000, 0x0,
-	  0x22210000, 0x22416000, 0x0, 0x00 },
-};	 
-
-void round_off_xres(u32 *xres) 
-{
-	if (*xres <= 640)
-		*xres = 640;
-	else if (*xres <= 800)
-		*xres = 800;
-	else if (*xres <= 1024)
-		*xres = 1024;
-	else if (*xres <= 1152)
-		*xres = 1152;
-	else if (*xres <= 1280)
-		*xres = 1280;
-	else
-		*xres = 1600;
-}
-
-inline void round_off_yres(u32 *xres, u32 *yres)
-{
-	*yres = (*xres * 3) >> 2;
-}
-
-static int i810fb_find_best_mode(u32 xres, u32 yres, u32 pixclock)
-{ 
-	u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0; 
-	u8 hfl = (u8) ((xres >> 3) - 1);
-
-	for (i = 0; i < ARRAY_SIZE(std_modes); i++) { 
-		if (std_modes[i].cr01 == hfl) { 
-			if (std_modes[i].pixclock <= pixclock)
-				diff = pixclock - std_modes[i].pixclock;
-			if (diff < diff_best) {	 
-		    		i_best = i;
-		    		diff_best = diff;
-			}
-		}
-	}
-	return i_best;
-}
-
-void i810fb_encode_registers(const struct fb_var_screeninfo *var,
-			     struct i810fb_par *par, u32 xres, u32 yres)
-{
-	u32 i_best = i810fb_find_best_mode(xres, yres, par->regs.pixclock);
-
-	par->regs = std_modes[i_best];
-
-	/* overlay */
-	par->ovract = ((xres + var->right_margin + var->hsync_len + 
-			var->left_margin - 32) | ((xres - 32) << 16));
-}
-
-void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
-{
-	u32 total, xres, yres;
-	u32 mode, pixclock;
-
-	xres = var->xres;
-	yres = var->yres;
-	
-	pixclock = 1000000000 / var->pixclock;
-	mode = i810fb_find_best_mode(xres, yres, pixclock);
-	
-	total = (std_modes[mode].cr00 | (std_modes[mode].cr35 & 1) << 8) + 3;
-	total <<= 3;
-	
-	var->pixclock = 1000000000 / std_modes[mode].pixclock;
-	var->right_margin = (std_modes[mode].cr04 << 3) - xres;
-	var->hsync_len = ((std_modes[mode].cr05 & 0x1F) -
-			 (std_modes[mode].cr04 & 0x1F)) << 3;
-	var->left_margin = (total - (xres + var->right_margin + 
-				     var->hsync_len));
-	var->sync = FB_SYNC_ON_GREEN;
-	if (~(std_modes[mode].msr & (1 << 6)))
-		var->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (~(std_modes[mode].msr & (1 << 7)))
-		var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
-	total = (std_modes[mode].cr06 | (std_modes[mode].cr30 & 0xF)  << 8) + 2;
-	var->lower_margin = (std_modes[mode].cr10 |
-			    (std_modes[mode].cr32 & 0x0F) << 8) - yres;
-	var->vsync_len = (std_modes[mode].cr11 & 0x0F) -
-			 (var->lower_margin & 0x0F);
-	var->upper_margin = total - (yres + var->lower_margin + var->vsync_len);
-}
-
-u32 i810_get_watermark(struct fb_var_screeninfo *var,
-		       struct i810fb_par *par)
-{
-	struct mode_registers *params = &par->regs;
-	u32 wmark = 0;
-	
-	if (par->mem_freq == 100) {
-		switch (var->bits_per_pixel) {
-		case 8:
-			wmark = params->bpp8_100;
-			break;
-		case 16:
-			wmark = params->bpp16_100;
-			break;
-		case 24:
-		case 32:
-			wmark = params->bpp24_100;
-		}
-	} else {					
-		switch (var->bits_per_pixel) {
-		case 8:
-			wmark = params->bpp8_133;
-			break;
-		case 16:
-			wmark = params->bpp16_133;
-			break;
-		case 24:
-		case 32:
-			wmark = params->bpp24_133;
-		}
-	}
-	return wmark;
-}	
-
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c
deleted file mode 100644
index 9743d51e7f8c..000000000000
--- a/drivers/video/i810/i810_gtf.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*-*- linux-c -*-
- *  linux/drivers/video/i810_main.h -- Intel 810 Non-discrete Video Timings 
- *                                     (VESA GTF)
- *
- *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
- *
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-#include <linux/kernel.h>
-
-#include "i810_regs.h"
-#include "i810.h"
-#include "i810_main.h"
-
-/*
- * FIFO and Watermark tables - based almost wholly on i810_wmark.c in 
- * XFree86 v4.03 by Precision Insight.  Slightly modified for integer 
- * operation, instead of float
- */
-
-struct wm_info {
-   u32 freq;
-   u32  wm;
-};
-
-static struct wm_info i810_wm_8_100[] = {
-	{ 15, 0x0070c000 },  { 19, 0x0070c000 },  { 25, 0x22003000 },
-	{ 28, 0x22003000 },  { 31, 0x22003000 },  { 36, 0x22007000 },
-	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22008000 },
-	{ 50, 0x22008000 },  { 56, 0x22008000 },  { 65, 0x22008000 },
-	{ 75, 0x22008000 },  { 78, 0x22008000 },  { 80, 0x22008000 },
-	{ 94, 0x22008000 },  { 96, 0x22107000 },  { 99, 0x22107000 },
-	{ 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
-	{ 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
-	{ 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
-	{ 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
-	{ 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 }, 
-};
-
-static struct wm_info i810_wm_16_100[] = {
-	{ 15, 0x0070c000 },  { 19, 0x0020c000 },  { 25, 0x22006000 },
-	{ 28, 0x22006000 },  { 31, 0x22007000 },  { 36, 0x22007000 },
-	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22009000 },
-	{ 50, 0x22009000 },  { 56, 0x22108000 },  { 65, 0x2210e000 },
-	{ 75, 0x2210e000 },  { 78, 0x2210e000 },  { 80, 0x22210000 },
-	{ 94, 0x22210000 },  { 96, 0x22210000 },  { 99, 0x22210000 },
-	{ 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
-	{ 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
-	{ 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
-	{ 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
-	{ 218, 0x22416000 }, { 229, 0x22416000 },
-};
-
-static struct wm_info i810_wm_24_100[] = {
-	{ 15, 0x0020c000 },  { 19, 0x0040c000 },  { 25, 0x22009000 },
-	{ 28, 0x22009000 },  { 31, 0x2200a000 },  { 36, 0x2210c000 },
-	{ 40, 0x2210c000 },  { 45, 0x2210c000 },  { 49, 0x22111000 },
-	{ 50, 0x22111000 },  { 56, 0x22111000 },  { 65, 0x22214000 },
-	{ 75, 0x22214000 },  { 78, 0x22215000 },  { 80, 0x22216000 },
-	{ 94, 0x22218000 },  { 96, 0x22418000 },  { 99, 0x22418000 },
-	{ 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
-	{ 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
-	{ 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
-	{ 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
-};
-
-static struct wm_info i810_wm_8_133[] = {
-	{ 15, 0x0070c000 },  { 19, 0x0070c000 },  { 25, 0x22003000 },
-	{ 28, 0x22003000 },  { 31, 0x22003000 },  { 36, 0x22007000 },
-	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22008000 },
-	{ 50, 0x22008000 },  { 56, 0x22008000 },  { 65, 0x22008000 },
-	{ 75, 0x22008000 },  { 78, 0x22008000 },  { 80, 0x22008000 },
-	{ 94, 0x22008000 },  { 96, 0x22107000 },  { 99, 0x22107000 },
-	{ 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
-	{ 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
-	{ 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
-	{ 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
-	{ 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 }, 
-};
-
-static struct wm_info i810_wm_16_133[] = {
-	{ 15, 0x0020c000 },  { 19, 0x0020c000 },  { 25, 0x22006000 },
-	{ 28, 0x22006000 },  { 31, 0x22007000 },  { 36, 0x22007000 },
-	{ 40, 0x22007000 },  { 45, 0x22007000 },  { 49, 0x22009000 },
-	{ 50, 0x22009000 },  { 56, 0x22108000 },  { 65, 0x2210e000 },
-	{ 75, 0x2210e000 },  { 78, 0x2210e000 },  { 80, 0x22210000 },
-	{ 94, 0x22210000 },  { 96, 0x22210000 },  { 99, 0x22210000 },
-	{ 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
-	{ 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
-	{ 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
-	{ 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
-	{ 218, 0x22416000 }, { 229, 0x22416000 },
-};
-
-static struct wm_info i810_wm_24_133[] = {
-	{ 15, 0x0020c000 },  { 19, 0x00408000 },  { 25, 0x22009000 },
-	{ 28, 0x22009000 },  { 31, 0x2200a000 },  { 36, 0x2210c000 },
-	{ 40, 0x2210c000 },  { 45, 0x2210c000 },  { 49, 0x22111000 },
-	{ 50, 0x22111000 },  { 56, 0x22111000 },  { 65, 0x22214000 },
-	{ 75, 0x22214000 },  { 78, 0x22215000 },  { 80, 0x22216000 },
-	{ 94, 0x22218000 },  { 96, 0x22418000 },  { 99, 0x22418000 },
-	{ 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
-	{ 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
-	{ 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
-	{ 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
-};
-
-void round_off_xres(u32 *xres) { }
-void round_off_yres(u32 *xres, u32 *yres) { }
-
-/**
- * i810fb_encode_registers - encode @var to hardware register values
- * @var: pointer to var structure
- * @par: pointer to hardware par structure
- * 
- * DESCRIPTION: 
- * Timing values in @var will be converted to appropriate
- * register values of @par.  
- */
-void i810fb_encode_registers(const struct fb_var_screeninfo *var,
-			     struct i810fb_par *par, u32 xres, u32 yres)
-{
-	int n, blank_s, blank_e;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	u8 msr = 0;
-
-	/* Horizontal */
-	/* htotal */
-	n = ((xres + var->right_margin + var->hsync_len + 
-	      var->left_margin) >> 3) - 5;
-	par->regs.cr00 =  (u8) n;
-	par->regs.cr35 = (u8) ((n >> 8) & 1);
-	
-	/* xres */
-	par->regs.cr01 = (u8) ((xres >> 3) - 1);
-
-	/* hblank */
-	blank_e = (xres + var->right_margin + var->hsync_len + 
-		   var->left_margin) >> 3;
-	blank_e--;
-	blank_s = blank_e - 127;
-	if (blank_s < (xres >> 3))
-		blank_s = xres >> 3;
-	par->regs.cr02 = (u8) blank_s;
-	par->regs.cr03 = (u8) (blank_e & 0x1F);
-	par->regs.cr05 = (u8) ((blank_e & (1 << 5)) << 2);
-	par->regs.cr39 = (u8) ((blank_e >> 6) & 1);
-
-	/* hsync */
-	par->regs.cr04 = (u8) ((xres + var->right_margin) >> 3);
-	par->regs.cr05 |= (u8) (((xres + var->right_margin + 
-				  var->hsync_len) >> 3) & 0x1F);
-	
-       	/* Vertical */
-	/* vtotal */
-	n = yres + var->lower_margin + var->vsync_len + var->upper_margin - 2;
-	par->regs.cr06 = (u8) (n & 0xFF);
-	par->regs.cr30 = (u8) ((n >> 8) & 0x0F);
-
-	/* vsync */ 
-	n = yres + var->lower_margin;
-	par->regs.cr10 = (u8) (n & 0xFF);
-	par->regs.cr32 = (u8) ((n >> 8) & 0x0F);
-	par->regs.cr11 = i810_readb(CR11, mmio) & ~0x0F;
-	par->regs.cr11 |= (u8) ((yres + var->lower_margin + 
-				 var->vsync_len) & 0x0F);
-
-	/* yres */
-	n = yres - 1;
-	par->regs.cr12 = (u8) (n & 0xFF);
-	par->regs.cr31 = (u8) ((n >> 8) & 0x0F);
-	
-	/* vblank */
-	blank_e = yres + var->lower_margin + var->vsync_len + 
-		var->upper_margin;
-	blank_e--;
-	blank_s = blank_e - 127;
-	if (blank_s < yres)
-		blank_s = yres;
-	par->regs.cr15 = (u8) (blank_s & 0xFF);
-	par->regs.cr33 = (u8) ((blank_s >> 8) & 0x0F);
-	par->regs.cr16 = (u8) (blank_e & 0xFF);
-	par->regs.cr09 = 0;	
-
-	/* sync polarity */
-	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
-		msr |= 1 << 6;
-	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
-		msr |= 1 << 7;
-	par->regs.msr = msr;
-
-	/* interlace */
-	if (var->vmode & FB_VMODE_INTERLACED) 
-		par->interlace = (1 << 7) | ((u8) (var->yres >> 4));
-	else 
-		par->interlace = 0;
-
-	if (var->vmode & FB_VMODE_DOUBLE)
-		par->regs.cr09 |= 1 << 7;
-
-	/* overlay */
-	par->ovract = ((var->xres + var->right_margin + var->hsync_len + 
-			var->left_margin - 32) | ((var->xres - 32) << 16));
-}	
-
-void i810fb_fill_var_timings(struct fb_var_screeninfo *var) { }
-
-/**
- * i810_get_watermark - gets watermark
- * @var: pointer to fb_var_screeninfo
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Gets the required watermark based on 
- * pixelclock and RAMBUS frequency.
- * 
- * RETURNS:
- * watermark
- */
-u32 i810_get_watermark(const struct fb_var_screeninfo *var,
-		       struct i810fb_par *par)
-{
-	struct wm_info *wmark = NULL;
-	u32 i, size = 0, pixclock, wm_best = 0, min, diff;
-
-	if (par->mem_freq == 100) {
-		switch (var->bits_per_pixel) { 
-		case 8:
-			wmark = i810_wm_8_100;
-			size = ARRAY_SIZE(i810_wm_8_100);
-			break;
-		case 16:
-			wmark = i810_wm_16_100;
-			size = ARRAY_SIZE(i810_wm_16_100);
-			break;
-		case 24:
-		case 32:
-			wmark = i810_wm_24_100;
-			size = ARRAY_SIZE(i810_wm_24_100);
-		}
-	} else {
-		switch(var->bits_per_pixel) {
-		case 8:
-			wmark = i810_wm_8_133;
-			size = ARRAY_SIZE(i810_wm_8_133);
-			break;
-		case 16:
-			wmark = i810_wm_16_133;
-			size = ARRAY_SIZE(i810_wm_16_133);
-			break;
-		case 24:
-		case 32:
-			wmark = i810_wm_24_133;
-			size = ARRAY_SIZE(i810_wm_24_133);
-		}
-	}
-
-	pixclock = 1000000/var->pixclock;
-	min = ~0;
-	for (i = 0; i < size; i++) {
-		if (pixclock <= wmark[i].freq) 
-			diff = wmark[i].freq - pixclock;
-		else 
-			diff = pixclock - wmark[i].freq;
-		if (diff < min) {
-			wm_best = wmark[i].wm;
-			min = diff;
-		}
-	}
-	return wm_best;		
-}	
-
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
deleted file mode 100644
index bb674e431741..000000000000
--- a/drivers/video/i810/i810_main.c
+++ /dev/null
@@ -1,2218 +0,0 @@
- /*-*- linux-c -*-
- *  linux/drivers/video/i810_main.c -- Intel 810 frame buffer device
- *
- *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
- *
- *      Contributors:
- *         Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets
- *                                        and enabling the power-on state of 
- *                                        external VGA connectors for 
- *                                        secondary displays
- *
- *         Fredrik Andersson <krueger@shell.linux.se> - alpha testing of
- *                                        the VESA GTF
- *
- *         Brad Corrion <bcorrion@web-co.com> - alpha testing of customized
- *                                        timings support
- *
- *	The code framework is a modification of vfb.c by Geert Uytterhoeven.
- *      DotClock and PLL calculations are partly based on i810_driver.c 
- *              in xfree86 v4.0.3 by Precision Insight.
- *      Watermark calculation and tables are based on i810_wmark.c 
- *              in xfre86 v4.0.3 by Precision Insight.  Slight modifications 
- *              only to allow for integer operations instead of floating point.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/resource.h>
-#include <linux/unistd.h>
-#include <linux/console.h>
-
-#include <asm/io.h>
-#include <asm/div64.h>
-#include <asm/page.h>
-
-#include "i810_regs.h"
-#include "i810.h"
-#include "i810_main.h"
-
-/*
- * voffset - framebuffer offset in MiB from aperture start address.  In order for
- * the driver to work with X, we must try to use memory holes left untouched by X. The
- * following table lists where X's different surfaces start at.
- *
- * ---------------------------------------------
- * :                :  64 MiB     : 32 MiB      :
- * ----------------------------------------------
- * : FrontBuffer    :   0         :  0          :
- * : DepthBuffer    :   48        :  16         :
- * : BackBuffer     :   56        :  24         :
- * ----------------------------------------------
- *
- * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
- * 15 + 1 MiB of Framebuffer memory.  For 32 MiB Aperture sizes, a v_offset of 8 MiB should
- * work, allowing 7 + 1 MiB of Framebuffer memory.
- * Note, the size of the hole may change depending on how much memory you allocate to X,
- * and how the memory is split up between these surfaces.
- *
- * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
- * DRI disabled.  But if the Frontbuffer is overlapped, X will fail to load.
- *
- * Experiment with v_offset to find out which works best for you.
- */
-static u32 v_offset_default; /* For 32 MiB Aper size, 8 should be the default */
-static u32 voffset;
-
-static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-static int i810fb_init_pci(struct pci_dev *dev,
-			   const struct pci_device_id *entry);
-static void __exit i810fb_remove_pci(struct pci_dev *dev);
-static int i810fb_resume(struct pci_dev *dev);
-static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
-
-/* Chipset Specific Functions */
-static int i810fb_set_par    (struct fb_info *info);
-static int i810fb_getcolreg  (u8 regno, u8 *red, u8 *green, u8 *blue,
-			      u8 *transp, struct fb_info *info);
-static int i810fb_setcolreg  (unsigned regno, unsigned red, unsigned green, unsigned blue,
-			      unsigned transp, struct fb_info *info);
-static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
-static int i810fb_blank      (int blank_mode, struct fb_info *info);
-
-/* Initialization */
-static void i810fb_release_resource       (struct fb_info *info, struct i810fb_par *par);
-
-/* PCI */
-static const char * const i810_pci_list[] = {
-	"Intel(R) 810 Framebuffer Device"                                 ,
-	"Intel(R) 810-DC100 Framebuffer Device"                           ,
-	"Intel(R) 810E Framebuffer Device"                                ,
-	"Intel(R) 815 (Internal Graphics 100Mhz FSB) Framebuffer Device"  ,
-	"Intel(R) 815 (Internal Graphics only) Framebuffer Device"        ,
-	"Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device"
-};
-
-static struct pci_device_id i810fb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1  },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
-	/* mvo: added i815 PCI-ID */
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_100,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_NOAGP,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
-	{ 0 },
-};
-
-static struct pci_driver i810fb_driver = {
-	.name     =	"i810fb",
-	.id_table =	i810fb_pci_tbl,
-	.probe    =	i810fb_init_pci,
-	.remove   =	__exit_p(i810fb_remove_pci),
-	.suspend  =     i810fb_suspend,
-	.resume   =     i810fb_resume,
-};
-
-static char *mode_option = NULL;
-static int vram = 4;
-static int bpp = 8;
-static bool mtrr;
-static bool accel;
-static int hsync1;
-static int hsync2;
-static int vsync1;
-static int vsync2;
-static int xres;
-static int yres;
-static int vyres;
-static bool sync;
-static bool extvga;
-static bool dcolor;
-static bool ddc3;
-
-/*------------------------------------------------------------*/
-
-/**************************************************************
- *                Hardware Low Level Routines                 *
- **************************************************************/
-
-/**
- * i810_screen_off - turns off/on display
- * @mmio: address of register space
- * @mode: on or off
- *
- * DESCRIPTION:
- * Blanks/unblanks the display
- */
-static void i810_screen_off(u8 __iomem *mmio, u8 mode)
-{
-	u32 count = WAIT_COUNT;
-	u8 val;
-
-	i810_writeb(SR_INDEX, mmio, SR01);
-	val = i810_readb(SR_DATA, mmio);
-	val = (mode == OFF) ? val | SCR_OFF :
-		val & ~SCR_OFF;
-
-	while((i810_readw(DISP_SL, mmio) & 0xFFF) && count--);
-	i810_writeb(SR_INDEX, mmio, SR01);
-	i810_writeb(SR_DATA, mmio, val);
-}
-
-/**
- * i810_dram_off - turns off/on dram refresh
- * @mmio: address of register space
- * @mode: on or off
- *
- * DESCRIPTION:
- * Turns off DRAM refresh.  Must be off for only 2 vsyncs
- * before data becomes corrupt
- */
-static void i810_dram_off(u8 __iomem *mmio, u8 mode)
-{
-	u8 val;
-
-	val = i810_readb(DRAMCH, mmio);
-	val &= DRAM_OFF;
-	val = (mode == OFF) ? val : val | DRAM_ON;
-	i810_writeb(DRAMCH, mmio, val);
-}
-
-/**
- * i810_protect_regs - allows rw/ro mode of certain VGA registers
- * @mmio: address of register space
- * @mode: protect/unprotect
- *
- * DESCRIPTION:
- * The IBM VGA standard allows protection of certain VGA registers.  
- * This will  protect or unprotect them. 
- */
-static void i810_protect_regs(u8 __iomem *mmio, int mode)
-{
-	u8 reg;
-
-	i810_writeb(CR_INDEX_CGA, mmio, CR11);
-	reg = i810_readb(CR_DATA_CGA, mmio);
-	reg = (mode == OFF) ? reg & ~0x80 :
-		reg | 0x80;
- 		
-	i810_writeb(CR_INDEX_CGA, mmio, CR11);
-	i810_writeb(CR_DATA_CGA, mmio, reg);
-}
-
-/**
- * i810_load_pll - loads values for the hardware PLL clock
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Loads the P, M, and N registers.  
- */
-static void i810_load_pll(struct i810fb_par *par)
-{
-	u32 tmp1, tmp2;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	
-	tmp1 = par->regs.M | par->regs.N << 16;
-	tmp2 = i810_readl(DCLK_2D, mmio);
-	tmp2 &= ~MN_MASK;
-	i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
-	
-	tmp1 = par->regs.P;
-	tmp2 = i810_readl(DCLK_0DS, mmio);
-	tmp2 &= ~(P_OR << 16);
-	i810_writel(DCLK_0DS, mmio, (tmp1 << 16) | tmp2);
-
-	i810_writeb(MSR_WRITE, mmio, par->regs.msr | 0xC8 | 1);
-
-}
-
-/**
- * i810_load_vga - load standard VGA registers
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Load values to VGA registers
- */
-static void i810_load_vga(struct i810fb_par *par)
-{	
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	/* interlace */
-	i810_writeb(CR_INDEX_CGA, mmio, CR70);
-	i810_writeb(CR_DATA_CGA, mmio, par->interlace);
-
-	i810_writeb(CR_INDEX_CGA, mmio, CR00);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr00);
-	i810_writeb(CR_INDEX_CGA, mmio, CR01);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr01);
-	i810_writeb(CR_INDEX_CGA, mmio, CR02);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr02);
-	i810_writeb(CR_INDEX_CGA, mmio, CR03);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr03);
-	i810_writeb(CR_INDEX_CGA, mmio, CR04);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr04);
-	i810_writeb(CR_INDEX_CGA, mmio, CR05);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr05);
-	i810_writeb(CR_INDEX_CGA, mmio, CR06);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr06);
-	i810_writeb(CR_INDEX_CGA, mmio, CR09);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr09);
-	i810_writeb(CR_INDEX_CGA, mmio, CR10);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr10);
-	i810_writeb(CR_INDEX_CGA, mmio, CR11);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr11);
-	i810_writeb(CR_INDEX_CGA, mmio, CR12);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr12);
-	i810_writeb(CR_INDEX_CGA, mmio, CR15);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr15);
-	i810_writeb(CR_INDEX_CGA, mmio, CR16);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr16);
-}
-
-/**
- * i810_load_vgax - load extended VGA registers
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Load values to extended VGA registers
- */
-static void i810_load_vgax(struct i810fb_par *par)
-{
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	i810_writeb(CR_INDEX_CGA, mmio, CR30);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30);
-	i810_writeb(CR_INDEX_CGA, mmio, CR31);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr31);
-	i810_writeb(CR_INDEX_CGA, mmio, CR32);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr32);
-	i810_writeb(CR_INDEX_CGA, mmio, CR33);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr33);
-	i810_writeb(CR_INDEX_CGA, mmio, CR35);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr35);
-	i810_writeb(CR_INDEX_CGA, mmio, CR39);
-	i810_writeb(CR_DATA_CGA, mmio, par->regs.cr39);
-}
-
-/**
- * i810_load_2d - load grahics registers
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Load values to graphics registers
- */
-static void i810_load_2d(struct i810fb_par *par)
-{
-	u32 tmp;
-	u8 tmp8;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-  	i810_writel(FW_BLC, mmio, par->watermark); 
-	tmp = i810_readl(PIXCONF, mmio);
-	tmp |= 1 | 1 << 20;
-	i810_writel(PIXCONF, mmio, tmp);
-
-	i810_writel(OVRACT, mmio, par->ovract);
-
-	i810_writeb(GR_INDEX, mmio, GR10);
-	tmp8 = i810_readb(GR_DATA, mmio);
-	tmp8 |= 2;
-	i810_writeb(GR_INDEX, mmio, GR10);
-	i810_writeb(GR_DATA, mmio, tmp8);
-}	
-
-/**
- * i810_hires - enables high resolution mode
- * @mmio: address of register space
- */
-static void i810_hires(u8 __iomem *mmio)
-{
-	u8 val;
-	
-	i810_writeb(CR_INDEX_CGA, mmio, CR80);
-	val = i810_readb(CR_DATA_CGA, mmio);
-	i810_writeb(CR_INDEX_CGA, mmio, CR80);
-	i810_writeb(CR_DATA_CGA, mmio, val | 1);
-	/* Stop LCD displays from flickering */
-	i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4);
-}
-
-/**
- * i810_load_pitch - loads the characters per line of the display
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Loads the characters per line
- */	
-static void i810_load_pitch(struct i810fb_par *par)
-{
-	u32 tmp, pitch;
-	u8 val;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-			
-	pitch = par->pitch >> 3;
-	i810_writeb(SR_INDEX, mmio, SR01);
-	val = i810_readb(SR_DATA, mmio);
-	val &= 0xE0;
-	val |= 1 | 1 << 2;
-	i810_writeb(SR_INDEX, mmio, SR01);
-	i810_writeb(SR_DATA, mmio, val);
-
-	tmp = pitch & 0xFF;
-	i810_writeb(CR_INDEX_CGA, mmio, CR13);
-	i810_writeb(CR_DATA_CGA, mmio, (u8) tmp);
-	
-	tmp = pitch >> 8;
-	i810_writeb(CR_INDEX_CGA, mmio, CR41);
-	val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F;
-	i810_writeb(CR_INDEX_CGA, mmio, CR41);
-	i810_writeb(CR_DATA_CGA, mmio, (u8) tmp | val);
-}
-
-/**
- * i810_load_color - loads the color depth of the display
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Loads the color depth of the display and the graphics engine
- */
-static void i810_load_color(struct i810fb_par *par)
-{
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	u32 reg1;
-	u16 reg2;
-
-	reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27);
-	reg2 = i810_readw(BLTCNTL, mmio) & ~0x30;
-
-	reg1 |= 0x8000 | par->pixconf;
-	reg2 |= par->bltcntl;
-	i810_writel(PIXCONF, mmio, reg1);
-	i810_writew(BLTCNTL, mmio, reg2);
-}
-
-/**
- * i810_load_regs - loads all registers for the mode
- * @par: pointer to i810fb_par structure
- * 
- * DESCRIPTION:
- * Loads registers
- */
-static void i810_load_regs(struct i810fb_par *par)
-{
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	i810_screen_off(mmio, OFF);
-	i810_protect_regs(mmio, OFF);
-	i810_dram_off(mmio, OFF);
-	i810_load_pll(par);
-	i810_load_vga(par);
-	i810_load_vgax(par);
-	i810_dram_off(mmio, ON);	
-	i810_load_2d(par);
-	i810_hires(mmio);
-	i810_screen_off(mmio, ON);
-	i810_protect_regs(mmio, ON);
-	i810_load_color(par);
-	i810_load_pitch(par);
-}
-
-static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue,
-			  u8 __iomem *mmio)
-{
-	i810_writeb(CLUT_INDEX_WRITE, mmio, regno);
-	i810_writeb(CLUT_DATA, mmio, red);
-	i810_writeb(CLUT_DATA, mmio, green);
-	i810_writeb(CLUT_DATA, mmio, blue); 	
-}
-
-static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue,
-			  u8 __iomem *mmio)
-{
-	i810_writeb(CLUT_INDEX_READ, mmio, regno);
-	*red = i810_readb(CLUT_DATA, mmio);
-	*green = i810_readb(CLUT_DATA, mmio);
-	*blue = i810_readb(CLUT_DATA, mmio);
-}
-
-/************************************************************
- *                   VGA State Restore                      * 
- ************************************************************/
-static void i810_restore_pll(struct i810fb_par *par)
-{
-	u32 tmp1, tmp2;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	
-	tmp1 = par->hw_state.dclk_2d;
-	tmp2 = i810_readl(DCLK_2D, mmio);
-	tmp1 &= ~MN_MASK;
-	tmp2 &= MN_MASK;
-	i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
-
-	tmp1 = par->hw_state.dclk_1d;
-	tmp2 = i810_readl(DCLK_1D, mmio);
-	tmp1 &= ~MN_MASK;
-	tmp2 &= MN_MASK;
-	i810_writel(DCLK_1D, mmio, tmp1 | tmp2);
-
-	i810_writel(DCLK_0DS, mmio, par->hw_state.dclk_0ds);
-}
-
-static void i810_restore_dac(struct i810fb_par *par)
-{
-	u32 tmp1, tmp2;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	tmp1 = par->hw_state.pixconf;
-	tmp2 = i810_readl(PIXCONF, mmio);
-	tmp1 &= DAC_BIT;
-	tmp2 &= ~DAC_BIT;
-	i810_writel(PIXCONF, mmio, tmp1 | tmp2);
-}
-
-static void i810_restore_vgax(struct i810fb_par *par)
-{
-	u8 i, j;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	
-	for (i = 0; i < 4; i++) {
-		i810_writeb(CR_INDEX_CGA, mmio, CR30+i);
-		i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i));
-	}
-	i810_writeb(CR_INDEX_CGA, mmio, CR35);
-	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr35);
-	i810_writeb(CR_INDEX_CGA, mmio, CR39);
-	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
-	i810_writeb(CR_INDEX_CGA, mmio, CR41);
-	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
-
-	/*restore interlace*/
-	i810_writeb(CR_INDEX_CGA, mmio, CR70);
-	i = par->hw_state.cr70;
-	i &= INTERLACE_BIT;
-	j = i810_readb(CR_DATA_CGA, mmio);
-	i810_writeb(CR_INDEX_CGA, mmio, CR70);
-	i810_writeb(CR_DATA_CGA, mmio, j | i);
-
-	i810_writeb(CR_INDEX_CGA, mmio, CR80);
-	i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr80);
-	i810_writeb(MSR_WRITE, mmio, par->hw_state.msr);
-	i810_writeb(SR_INDEX, mmio, SR01);
-	i = (par->hw_state.sr01) & ~0xE0 ;
-	j = i810_readb(SR_DATA, mmio) & 0xE0;
-	i810_writeb(SR_INDEX, mmio, SR01);
-	i810_writeb(SR_DATA, mmio, i | j);
-}
-
-static void i810_restore_vga(struct i810fb_par *par)
-{
-	u8 i;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	
-	for (i = 0; i < 10; i++) {
-		i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
-		i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i));
-	}
-	for (i = 0; i < 8; i++) {
-		i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
-		i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr10) + i));
-	}
-}
-
-static void i810_restore_addr_map(struct i810fb_par *par)
-{
-	u8 tmp;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	i810_writeb(GR_INDEX, mmio, GR10);
-	tmp = i810_readb(GR_DATA, mmio);
-	tmp &= ADDR_MAP_MASK;
-	tmp |= par->hw_state.gr10;
-	i810_writeb(GR_INDEX, mmio, GR10);
-	i810_writeb(GR_DATA, mmio, tmp);
-}
-
-static void i810_restore_2d(struct i810fb_par *par)
-{
-	u32 tmp_long;
-	u16 tmp_word;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	tmp_word = i810_readw(BLTCNTL, mmio);
-	tmp_word &= ~(3 << 4); 
-	tmp_word |= par->hw_state.bltcntl;
-	i810_writew(BLTCNTL, mmio, tmp_word);
-       
-	i810_dram_off(mmio, OFF);
-	i810_writel(PIXCONF, mmio, par->hw_state.pixconf);
-	i810_dram_off(mmio, ON);
-
-	tmp_word = i810_readw(HWSTAM, mmio);
-	tmp_word &= 3 << 13;
-	tmp_word |= par->hw_state.hwstam;
-	i810_writew(HWSTAM, mmio, tmp_word);
-
-	tmp_long = i810_readl(FW_BLC, mmio);
-	tmp_long &= FW_BLC_MASK;
-	tmp_long |= par->hw_state.fw_blc;
-	i810_writel(FW_BLC, mmio, tmp_long);
-
-	i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga); 
-	i810_writew(IER, mmio, par->hw_state.ier);
-	i810_writew(IMR, mmio, par->hw_state.imr);
-	i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas);
-}
-
-static void i810_restore_vga_state(struct i810fb_par *par)
-{
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	i810_screen_off(mmio, OFF);
-	i810_protect_regs(mmio, OFF);
-	i810_dram_off(mmio, OFF);
-	i810_restore_pll(par);
-	i810_restore_dac(par);
-	i810_restore_vga(par);
-	i810_restore_vgax(par);
-	i810_restore_addr_map(par);
-	i810_dram_off(mmio, ON);
-	i810_restore_2d(par);
-	i810_screen_off(mmio, ON);
-	i810_protect_regs(mmio, ON);
-}
-
-/***********************************************************************
- *                         VGA State Save                              *
- ***********************************************************************/
-
-static void i810_save_vgax(struct i810fb_par *par)
-{
-	u8 i;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	for (i = 0; i < 4; i++) {
-		i810_writeb(CR_INDEX_CGA, mmio, CR30 + i);
-		*(&(par->hw_state.cr30) + i) = i810_readb(CR_DATA_CGA, mmio);
-	}
-	i810_writeb(CR_INDEX_CGA, mmio, CR35);
-	par->hw_state.cr35 = i810_readb(CR_DATA_CGA, mmio);
-	i810_writeb(CR_INDEX_CGA, mmio, CR39);
-	par->hw_state.cr39 = i810_readb(CR_DATA_CGA, mmio);
-	i810_writeb(CR_INDEX_CGA, mmio, CR41);
-	par->hw_state.cr41 = i810_readb(CR_DATA_CGA, mmio);
-	i810_writeb(CR_INDEX_CGA, mmio, CR70);
-	par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio);	
-	par->hw_state.msr = i810_readb(MSR_READ, mmio);
-	i810_writeb(CR_INDEX_CGA, mmio, CR80);
-	par->hw_state.cr80 = i810_readb(CR_DATA_CGA, mmio);
-	i810_writeb(SR_INDEX, mmio, SR01);
-	par->hw_state.sr01 = i810_readb(SR_DATA, mmio);
-}
-
-static void i810_save_vga(struct i810fb_par *par)
-{
-	u8 i;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	for (i = 0; i < 10; i++) {
-		i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
-		*((&par->hw_state.cr00) + i) = i810_readb(CR_DATA_CGA, mmio);
-	}
-	for (i = 0; i < 8; i++) {
-		i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
-		*((&par->hw_state.cr10) + i) = i810_readb(CR_DATA_CGA, mmio);
-	}
-}
-
-static void i810_save_2d(struct i810fb_par *par)
-{
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	par->hw_state.dclk_2d = i810_readl(DCLK_2D, mmio);
-	par->hw_state.dclk_1d = i810_readl(DCLK_1D, mmio);
-	par->hw_state.dclk_0ds = i810_readl(DCLK_0DS, mmio);
-	par->hw_state.pixconf = i810_readl(PIXCONF, mmio);
-	par->hw_state.fw_blc = i810_readl(FW_BLC, mmio);
-	par->hw_state.bltcntl = i810_readw(BLTCNTL, mmio);
-	par->hw_state.hwstam = i810_readw(HWSTAM, mmio); 
-	par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio); 
-	par->hw_state.ier = i810_readw(IER, mmio);
-	par->hw_state.imr = i810_readw(IMR, mmio);
-	par->hw_state.dplystas = i810_readl(DPLYSTAS, mmio);
-}
-
-static void i810_save_vga_state(struct i810fb_par *par)
-{
-	i810_save_vga(par);
-	i810_save_vgax(par);
-	i810_save_2d(par);
-}
-
-/************************************************************
- *                    Helpers                               * 
- ************************************************************/
-/**
- * get_line_length - calculates buffer pitch in bytes
- * @par: pointer to i810fb_par structure
- * @xres_virtual: virtual resolution of the frame
- * @bpp: bits per pixel
- *
- * DESCRIPTION:
- * Calculates buffer pitch in bytes.  
- */
-static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
-{
-   	u32 length;
-	
-	length = xres_virtual*bpp;
-	length = (length+31)&-32;
-	length >>= 3;
-	return length;
-}
-
-/**
- * i810_calc_dclk - calculates the P, M, and N values of a pixelclock value
- * @freq: target pixelclock in picoseconds
- * @m: where to write M register
- * @n: where to write N register
- * @p: where to write P register
- *
- * DESCRIPTION:
- * Based on the formula Freq_actual = (4*M*Freq_ref)/(N^P)
- * Repeatedly computes the Freq until the actual Freq is equal to
- * the target Freq or until the loop count is zero.  In the latter
- * case, the actual frequency nearest the target will be used.
- */
-static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
-{
-	u32 m_reg, n_reg, p_divisor, n_target_max;
-	u32 m_target, n_target, p_target, n_best, m_best, mod;
-	u32 f_out, target_freq, diff = 0, mod_min, diff_min;
-
-	diff_min = mod_min = 0xFFFFFFFF;
-	n_best = m_best = m_target = f_out = 0;
-
-	target_freq =  freq;
-	n_target_max = 30;
-
-	/*
-	 * find P such that target freq is 16x reference freq (Hz). 
-	 */
-	p_divisor = 1;
-	p_target = 0;
-	while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) && 
-	      p_divisor <= 32) {
-		p_divisor <<= 1;
-		p_target++;
-	}
-
-	n_reg = m_reg = n_target = 3;	
-	while (diff_min && mod_min && (n_target < n_target_max)) {
-		f_out = (p_divisor * n_reg * 1000000)/(4 * 24 * m_reg);
-		mod = (p_divisor * n_reg * 1000000) % (4 * 24 * m_reg);
-		m_target = m_reg;
-		n_target = n_reg;
-		if (f_out <= target_freq) {
-			n_reg++;
-			diff = target_freq - f_out;
-		} else {
-			m_reg++;
-			diff = f_out - target_freq;
-		}
-
-		if (diff_min > diff) {
-			diff_min = diff;
-			n_best = n_target;
-			m_best = m_target;
-		}		 
-
-		if (!diff && mod_min > mod) {
-			mod_min = mod;
-			n_best = n_target;
-			m_best = m_target;
-		}
-	} 
-	if (m) *m = (m_best - 2) & 0x3FF;
-	if (n) *n = (n_best - 2) & 0x3FF;
-	if (p) *p = (p_target << 4);
-}
-
-/*************************************************************
- *                Hardware Cursor Routines                   *
- *************************************************************/
-
-/**
- * i810_enable_cursor - show or hide the hardware cursor
- * @mmio: address of register space
- * @mode: show (1) or hide (0)
- *
- * Description:
- * Shows or hides the hardware cursor
- */
-static void i810_enable_cursor(u8 __iomem *mmio, int mode)
-{
-	u32 temp;
-	
-	temp = i810_readl(PIXCONF, mmio);
-	temp = (mode == ON) ? temp | CURSOR_ENABLE_MASK :
-		temp & ~CURSOR_ENABLE_MASK;
-
-	i810_writel(PIXCONF, mmio, temp);
-}
-
-static void i810_reset_cursor_image(struct i810fb_par *par)
-{
-	u8 __iomem *addr = par->cursor_heap.virtual;
-	int i, j;
-
-	for (i = 64; i--; ) {
-		for (j = 0; j < 8; j++) {             
-			i810_writeb(j, addr, 0xff);   
-			i810_writeb(j+8, addr, 0x00); 
-		}	
-		addr +=16;
-	}
-}
-
-static void i810_load_cursor_image(int width, int height, u8 *data,
-				   struct i810fb_par *par)
-{
-	u8 __iomem *addr = par->cursor_heap.virtual;
-	int i, j, w = width/8;
-	int mod = width % 8, t_mask, d_mask;
-	
-	t_mask = 0xff >> mod;
-	d_mask = ~(0xff >> mod); 
-	for (i = height; i--; ) {
-		for (j = 0; j < w; j++) {
-			i810_writeb(j+0, addr, 0x00);
-			i810_writeb(j+8, addr, *data++);
-		}
-		if (mod) {
-			i810_writeb(j+0, addr, t_mask);
-			i810_writeb(j+8, addr, *data++ & d_mask);
-		}
-		addr += 16;
-	}
-}
-
-static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	u8 red, green, blue, trans, temp;
-
-	i810fb_getcolreg(bg, &red, &green, &blue, &trans, info);
-
-	temp = i810_readb(PIXCONF1, mmio);
-	i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
-
-	i810_write_dac(4, red, green, blue, mmio);
-
-	i810_writeb(PIXCONF1, mmio, temp);
-
-	i810fb_getcolreg(fg, &red, &green, &blue, &trans, info);
-	temp = i810_readb(PIXCONF1, mmio);
-	i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
-
-	i810_write_dac(5, red, green, blue, mmio);
-
-	i810_writeb(PIXCONF1, mmio, temp);
-}
-
-/**
- * i810_init_cursor - initializes the cursor
- * @par: pointer to i810fb_par structure
- *
- * DESCRIPTION:
- * Initializes the cursor registers
- */
-static void i810_init_cursor(struct i810fb_par *par)
-{
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	i810_enable_cursor(mmio, OFF);
-	i810_writel(CURBASE, mmio, par->cursor_heap.physical);
-	i810_writew(CURCNTR, mmio, COORD_ACTIVE | CURSOR_MODE_64_XOR);
-}	
-
-/*********************************************************************
- *                    Framebuffer hook helpers                       *
- *********************************************************************/
-/**
- * i810_round_off -  Round off values to capability of hardware
- * @var: pointer to fb_var_screeninfo structure
- *
- * DESCRIPTION:
- * @var contains user-defined information for the mode to be set.
- * This will try modify those values to ones nearest the
- * capability of the hardware
- */
-static void i810_round_off(struct fb_var_screeninfo *var)
-{
-	u32 xres, yres, vxres, vyres;
-
-	/*
-	 *  Presently supports only these configurations 
-	 */
-
-	xres = var->xres;
-	yres = var->yres;
-	vxres = var->xres_virtual;
-	vyres = var->yres_virtual;
-
-	var->bits_per_pixel += 7;
-	var->bits_per_pixel &= ~7;
-	
-	if (var->bits_per_pixel < 8)
-		var->bits_per_pixel = 8;
-	if (var->bits_per_pixel > 32) 
-		var->bits_per_pixel = 32;
-
-	round_off_xres(&xres);
-	if (xres < 40)
-		xres = 40;
-	if (xres > 2048) 
-		xres = 2048;
-	xres = (xres + 7) & ~7;
-
-	if (vxres < xres) 
-		vxres = xres;
-
-	round_off_yres(&xres, &yres);
-	if (yres < 1)
-		yres = 1;
-	if (yres >= 2048)
-		yres = 2048;
-
-	if (vyres < yres) 
-		vyres = yres;
-
-	if (var->bits_per_pixel == 32)
-		var->accel_flags = 0;
-
-	/* round of horizontal timings to nearest 8 pixels */
-	var->left_margin = (var->left_margin + 4) & ~7;
-	var->right_margin = (var->right_margin + 4) & ~7;
-	var->hsync_len = (var->hsync_len + 4) & ~7;
-
-	if (var->vmode & FB_VMODE_INTERLACED) {
-		if (!((yres + var->upper_margin + var->vsync_len + 
-		       var->lower_margin) & 1))
-			var->upper_margin++;
-	}
-	
-	var->xres = xres;
-	var->yres = yres;
-	var->xres_virtual = vxres;
-	var->yres_virtual = vyres;
-}	
-
-/**
- * set_color_bitfields - sets rgba fields
- * @var: pointer to fb_var_screeninfo
- *
- * DESCRIPTION:
- * The length, offset and ordering  for each color field 
- * (red, green, blue)  will be set as specified 
- * by the hardware
- */  
-static void set_color_bitfields(struct fb_var_screeninfo *var)
-{
-	switch (var->bits_per_pixel) {
-	case 8:       
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:
-		var->green.length = (var->green.length == 5) ? 5 : 6;
-		var->red.length = 5;
-		var->blue.length = 5;
-		var->transp.length = 6 - var->green.length;
-		var->blue.offset = 0;
-		var->green.offset = 5;
-		var->red.offset = 5 + var->green.length;
-		var->transp.offset =  (5 + var->red.offset) & 15;
-		break;
-	case 24:	/* RGB 888   */
-	case 32:	/* RGBA 8888 */
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.length = var->bits_per_pixel - 24;
-		var->transp.offset = (var->transp.length) ? 24 : 0;
-		break;
-	}
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-}
-
-/**
- * i810_check_params - check if contents in var are valid
- * @var: pointer to fb_var_screeninfo
- * @info: pointer to fb_info
- *
- * DESCRIPTION:
- * This will check if the framebuffer size is sufficient 
- * for the current mode and if the user's monitor has the 
- * required specifications to display the current mode.
- */
-static int i810_check_params(struct fb_var_screeninfo *var, 
-			     struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	int line_length, vidmem, mode_valid = 0, retval = 0;
-	u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
-
-	/*
-	 *  Memory limit
-	 */
-	line_length = get_line_length(par, vxres, var->bits_per_pixel);
-	vidmem = line_length*vyres;
-
-	if (vidmem > par->fb.size) {
-		vyres = par->fb.size/line_length;
-		if (vyres < var->yres) {
-			vyres = info->var.yres;
-			vxres = par->fb.size/vyres;
-			vxres /= var->bits_per_pixel >> 3;
-			line_length = get_line_length(par, vxres, 
-						      var->bits_per_pixel);
-			vidmem = line_length * info->var.yres;
-			if (vxres < var->xres) {
-				printk("i810fb: required video memory, "
-				       "%d bytes, for %dx%d-%d (virtual) "
-				       "is out of range\n", 
-				       vidmem, vxres, vyres, 
-				       var->bits_per_pixel);
-				return -ENOMEM;
-			}
-		}
-	}
-
-	var->xres_virtual = vxres;
-	var->yres_virtual = vyres;
-
-	/*
-	 * Monitor limit
-	 */
-	switch (var->bits_per_pixel) {
-	case 8:
-		info->monspecs.dclkmax = 234000000;
-		break;
-	case 16:
-		info->monspecs.dclkmax = 229000000;
-		break;
-	case 24:
-	case 32:
-		info->monspecs.dclkmax = 204000000;
-		break;
-	}
-
-	info->monspecs.dclkmin = 15000000;
-
-	if (!fb_validate_mode(var, info))
-		mode_valid = 1;
-
-#ifdef CONFIG_FB_I810_I2C
-	if (!mode_valid && info->monspecs.gtf &&
-	    !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
-		mode_valid = 1;
-
-	if (!mode_valid && info->monspecs.modedb_len) {
-		const struct fb_videomode *mode;
-
-		mode = fb_find_best_mode(var, &info->modelist);
-		if (mode) {
-			fb_videomode_to_var(var, mode);
-			mode_valid = 1;
-		}
-	}
-#endif
-	if (!mode_valid && info->monspecs.modedb_len == 0) {
-		if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) {
-			int default_sync = (info->monspecs.hfmin-HFMIN)
-				|(info->monspecs.hfmax-HFMAX)
-				|(info->monspecs.vfmin-VFMIN)
-				|(info->monspecs.vfmax-VFMAX);
-			printk("i810fb: invalid video mode%s\n",
-			       default_sync ? "" : ". Specifying "
-			       "vsyncN/hsyncN parameters may help");
-			retval = -EINVAL;
-		}
-	}
-
-	return retval;
-}	
-
-/**
- * encode_fix - fill up fb_fix_screeninfo structure
- * @fix: pointer to fb_fix_screeninfo
- * @info: pointer to fb_info
- *
- * DESCRIPTION:
- * This will set up parameters that are unmodifiable by the user.
- */
-static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-
-    	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-
-    	strcpy(fix->id, "I810");
-	mutex_lock(&info->mm_lock);
-    	fix->smem_start = par->fb.physical;
-    	fix->smem_len = par->fb.size;
-	mutex_unlock(&info->mm_lock);
-    	fix->type = FB_TYPE_PACKED_PIXELS;
-    	fix->type_aux = 0;
-	fix->xpanstep = 8;
-	fix->ypanstep = 1;
-
-    	switch (info->var.bits_per_pixel) {
-	case 8:
-	    	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	    	break;
-	case 16:
-	case 24:
-	case 32:
-		if (info->var.nonstd)
-			fix->visual = FB_VISUAL_DIRECTCOLOR;
-		else
-			fix->visual = FB_VISUAL_TRUECOLOR;
-	    	break;
-	default:
-		return -EINVAL;
-	}
-    	fix->ywrapstep = 0;
-	fix->line_length = par->pitch;
-	fix->mmio_start = par->mmio_start_phys;
-	fix->mmio_len = MMIO_SIZE;
-	fix->accel = FB_ACCEL_I810;
-
-	return 0;
-}
-
-/**
- * decode_var - modify par according to contents of var
- * @var: pointer to fb_var_screeninfo
- * @par: pointer to i810fb_par
- *
- * DESCRIPTION:
- * Based on the contents of @var, @par will be dynamically filled up.
- * @par contains all information necessary to modify the hardware. 
-*/
-static void decode_var(const struct fb_var_screeninfo *var, 
-		       struct i810fb_par *par)
-{
-	u32 xres, yres, vxres, vyres;
-
-	xres = var->xres;
-	yres = var->yres;
-	vxres = var->xres_virtual;
-	vyres = var->yres_virtual;
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		par->pixconf = PIXCONF8;
-		par->bltcntl = 0;
-		par->depth = 1;
-		par->blit_bpp = BPP8;
-		break;
-	case 16:
-		if (var->green.length == 5)
-			par->pixconf = PIXCONF15;
-		else
-			par->pixconf = PIXCONF16;
-		par->bltcntl = 16;
-		par->depth = 2;
-		par->blit_bpp = BPP16;
-		break;
-	case 24:
-		par->pixconf = PIXCONF24;
-		par->bltcntl = 32;
-		par->depth = 3;
-		par->blit_bpp = BPP24;
-		break;
-	case 32:
-		par->pixconf = PIXCONF32;
-		par->bltcntl = 0;
-		par->depth = 4;
-		par->blit_bpp = 3 << 24;
-		break;
-	}
-	if (var->nonstd && var->bits_per_pixel != 8)
-		par->pixconf |= 1 << 27;
-
-	i810_calc_dclk(var->pixclock, &par->regs.M, 
-		       &par->regs.N, &par->regs.P);
-	i810fb_encode_registers(var, par, xres, yres);
-
-	par->watermark = i810_get_watermark(var, par);
-	par->pitch = get_line_length(par, vxres, var->bits_per_pixel);
-}	
-
-/**
- * i810fb_getcolreg - gets red, green and blue values of the hardware DAC
- * @regno: DAC index
- * @red: red
- * @green: green
- * @blue: blue
- * @transp: transparency (alpha)
- * @info: pointer to fb_info
- *
- * DESCRIPTION:
- * Gets the red, green and blue values of the hardware DAC as pointed by @regno
- * and writes them to @red, @green and @blue respectively
- */
-static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, 
-			    u8 *transp, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	u8 temp;
-
-	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		if ((info->var.green.length == 5 && regno > 31) ||
-		    (info->var.green.length == 6 && regno > 63))
-			return 1;
-	}
-
-	temp = i810_readb(PIXCONF1, mmio);
-	i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
-
-	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
-	    info->var.green.length == 5) 
-		i810_read_dac(regno * 8, red, green, blue, mmio);
-
-	else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
-		 info->var.green.length == 6) {
-		u8 tmp;
-
-		i810_read_dac(regno * 8, red, &tmp, blue, mmio);
-		i810_read_dac(regno * 4, &tmp, green, &tmp, mmio);
-	}
-	else 
-		i810_read_dac(regno, red, green, blue, mmio);
-
-    	*transp = 0;
-	i810_writeb(PIXCONF1, mmio, temp);
-
-    	return 0;
-}
-
-/****************************************************************** 
- *           Framebuffer device-specific hooks                    *
- ******************************************************************/
-
-static int i810fb_open(struct fb_info *info, int user)
-{
-	struct i810fb_par *par = info->par;
-
-	mutex_lock(&par->open_lock);
-	if (par->use_count == 0) {
-		memset(&par->state, 0, sizeof(struct vgastate));
-		par->state.flags = VGA_SAVE_CMAP;
-		par->state.vgabase = par->mmio_start_virtual;
-		save_vga(&par->state);
-
-		i810_save_vga_state(par);
-	}
-
-	par->use_count++;
-	mutex_unlock(&par->open_lock);
-	
-	return 0;
-}
-
-static int i810fb_release(struct fb_info *info, int user)
-{
-	struct i810fb_par *par = info->par;
-
-	mutex_lock(&par->open_lock);
-	if (par->use_count == 0) {
-		mutex_unlock(&par->open_lock);
-		return -EINVAL;
-	}
-
-	if (par->use_count == 1) {
-		i810_restore_vga_state(par);
-		restore_vga(&par->state);
-	}
-
-	par->use_count--;
-	mutex_unlock(&par->open_lock);
-	
-	return 0;
-}
-
-
-static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, 
-			    unsigned blue, unsigned transp, 
-			    struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	u8 temp;
-	int i;
-
- 	if (regno > 255) return 1;
-
-	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		if ((info->var.green.length == 5 && regno > 31) ||
-		    (info->var.green.length == 6 && regno > 63))
-			return 1;
-	}
-
-	if (info->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-				      7471 * blue) >> 16;
-
-	temp = i810_readb(PIXCONF1, mmio);
-	i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
-
-	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
-	    info->var.green.length == 5) {
-		for (i = 0; i < 8; i++) 
-			i810_write_dac((u8) (regno * 8) + i, (u8) red, 
-				       (u8) green, (u8) blue, mmio);
-	} else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
-		 info->var.green.length == 6) {
-		u8 r, g, b;
-
-		if (regno < 32) {
-			for (i = 0; i < 8; i++) 
-				i810_write_dac((u8) (regno * 8) + i,
-					       (u8) red, (u8) green, 
-					       (u8) blue, mmio);
-		}
-		i810_read_dac((u8) (regno*4), &r, &g, &b, mmio);
-		for (i = 0; i < 4; i++) 
-			i810_write_dac((u8) (regno*4) + i, r, (u8) green, 
-				       b, mmio);
-	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
-		i810_write_dac((u8) regno, (u8) red, (u8) green,
-			       (u8) blue, mmio);
-	}
-
-	i810_writeb(PIXCONF1, mmio, temp);
-
-	if (regno < 16) {
-		switch (info->var.bits_per_pixel) {
-		case 16:	
-			if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-				if (info->var.green.length == 5) 
-					((u32 *)info->pseudo_palette)[regno] = 
-						(regno << 10) | (regno << 5) |
-						regno;
-				else
-					((u32 *)info->pseudo_palette)[regno] = 
-						(regno << 11) | (regno << 5) |
-						regno;
-			} else {
-				if (info->var.green.length == 5) {
-					/* RGB 555 */
-					((u32 *)info->pseudo_palette)[regno] = 
-						((red & 0xf800) >> 1) |
-						((green & 0xf800) >> 6) |
-						((blue & 0xf800) >> 11);
-				} else {
-					/* RGB 565 */
-					((u32 *)info->pseudo_palette)[regno] =
-						(red & 0xf800) |
-						((green & 0xf800) >> 5) |
-						((blue & 0xf800) >> 11);
-				}
-			}
-			break;
-		case 24:	/* RGB 888 */
-		case 32:	/* RGBA 8888 */
-			if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 
-				((u32 *)info->pseudo_palette)[regno] = 
-					(regno << 16) | (regno << 8) |
-					regno;
-			else 
-				((u32 *)info->pseudo_palette)[regno] = 
-					((red & 0xff00) << 8) |
-					(green & 0xff00) |
-					((blue & 0xff00) >> 8);
-			break;
-		}
-	}
-	return 0;
-}
-
-static int i810fb_pan_display(struct fb_var_screeninfo *var, 
-			      struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u32 total;
-	
-	total = var->xoffset * par->depth + 
-		var->yoffset * info->fix.line_length;
-	i810fb_load_front(total, info);
-
-	return 0;
-}
-
-static int i810fb_blank (int blank_mode, struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-	int mode = 0, pwr, scr_off = 0;
-	
-	pwr = i810_readl(PWR_CLKC, mmio);
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		mode = POWERON;
-		pwr |= 1;
-		scr_off = ON;
-		break;
-	case FB_BLANK_NORMAL:
-		mode = POWERON;
-		pwr |= 1;
-		scr_off = OFF;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		mode = STANDBY;
-		pwr |= 1;
-		scr_off = OFF;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		mode = SUSPEND;
-		pwr |= 1;
-		scr_off = OFF;
-		break;
-	case FB_BLANK_POWERDOWN:
-		mode = POWERDOWN;
-		pwr &= ~1;
-		scr_off = OFF;
-		break;
-	default:
-		return -EINVAL; 
-	}
-
-	i810_screen_off(mmio, scr_off);
-	i810_writel(HVSYNC, mmio, mode);
-	i810_writel(PWR_CLKC, mmio, pwr);
-
-	return 0;
-}
-
-static int i810fb_set_par(struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-
-	decode_var(&info->var, par);
-	i810_load_regs(par);
-	i810_init_cursor(par);
-	encode_fix(&info->fix, info);
-
-	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
-		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
-		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
-		FBINFO_HWACCEL_IMAGEBLIT;
-		info->pixmap.scan_align = 2;
-	} else {
-		info->pixmap.scan_align = 1;
-		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	}
-	return 0;
-}
-
-static int i810fb_check_var(struct fb_var_screeninfo *var, 
-			    struct fb_info *info)
-{
-	int err;
-
-	if (IS_DVT) {
-		var->vmode &= ~FB_VMODE_MASK;
-		var->vmode |= FB_VMODE_NONINTERLACED;
-	}
-	if (var->vmode & FB_VMODE_DOUBLE) {
-		var->vmode &= ~FB_VMODE_MASK;
-		var->vmode |= FB_VMODE_NONINTERLACED;
-	}
-
-	i810_round_off(var);
-	if ((err = i810_check_params(var, info)))
-		return err;
-
-	i810fb_fill_var_timings(var);
-	set_color_bitfields(var);
-	return 0;
-}
-
-static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct i810fb_par *par = info->par;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	if (par->dev_flags & LOCKUP)
-		return -ENXIO;
-
-	if (cursor->image.width > 64 || cursor->image.height > 64)
-		return -ENXIO;
-
-	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
-		i810_init_cursor(par);
-		cursor->set |= FB_CUR_SETALL;
-	}
-
-	i810_enable_cursor(mmio, OFF);
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		u32 tmp;
-
-		tmp = (cursor->image.dx - info->var.xoffset) & 0xffff;
-		tmp |= (cursor->image.dy - info->var.yoffset) << 16;
-		i810_writel(CURPOS, mmio, tmp);
-	}
-
-	if (cursor->set & FB_CUR_SETSIZE)
-		i810_reset_cursor_image(par);
-
-	if (cursor->set & FB_CUR_SETCMAP)
-		i810_load_cursor_colors(cursor->image.fg_color,
-					cursor->image.bg_color,
-					info);
-
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
-		int size = ((cursor->image.width + 7) >> 3) *
-			cursor->image.height;
-		int i;
-		u8 *data = kmalloc(64 * 8, GFP_ATOMIC);
-
-		if (data == NULL)
-			return -ENOMEM;
-
-		switch (cursor->rop) {
-		case ROP_XOR:
-			for (i = 0; i < size; i++)
-				data[i] = cursor->image.data[i] ^ cursor->mask[i];
-			break;
-		case ROP_COPY:
-		default:
-			for (i = 0; i < size; i++)
-				data[i] = cursor->image.data[i] & cursor->mask[i];
-			break;
-		}
-
-		i810_load_cursor_image(cursor->image.width,
-				       cursor->image.height, data,
-				       par);
-		kfree(data);
-	}
-
-	if (cursor->enable)
-		i810_enable_cursor(mmio, ON);
-
-	return 0;
-}
-
-static struct fb_ops i810fb_ops = {
-	.owner =             THIS_MODULE,
-	.fb_open =           i810fb_open,
-	.fb_release =        i810fb_release,
-	.fb_check_var =      i810fb_check_var,
-	.fb_set_par =        i810fb_set_par,
-	.fb_setcolreg =      i810fb_setcolreg,
-	.fb_blank =          i810fb_blank,
-	.fb_pan_display =    i810fb_pan_display, 
-	.fb_fillrect =       i810fb_fillrect,
-	.fb_copyarea =       i810fb_copyarea,
-	.fb_imageblit =      i810fb_imageblit,
-	.fb_cursor =         i810fb_cursor,
-	.fb_sync =           i810fb_sync,
-};
-
-/***********************************************************************
- *                         Power Management                            *
- ***********************************************************************/
-static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct i810fb_par *par = info->par;
-
-	par->cur_state = mesg.event;
-
-	switch (mesg.event) {
-	case PM_EVENT_FREEZE:
-	case PM_EVENT_PRETHAW:
-		dev->dev.power.power_state = mesg;
-		return 0;
-	}
-
-	console_lock();
-	fb_set_suspend(info, 1);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	i810fb_blank(FB_BLANK_POWERDOWN, info);
-	agp_unbind_memory(par->i810_gtt.i810_fb_memory);
-	agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
-
-	pci_save_state(dev);
-	pci_disable_device(dev);
-	pci_set_power_state(dev, pci_choose_state(dev, mesg));
-	console_unlock();
-
-	return 0;
-}
-
-static int i810fb_resume(struct pci_dev *dev) 
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct i810fb_par *par = info->par;
-	int cur_state = par->cur_state;
-
-	par->cur_state = PM_EVENT_ON;
-
-	if (cur_state == PM_EVENT_FREEZE) {
-		pci_set_power_state(dev, PCI_D0);
-		return 0;
-	}
-
-	console_lock();
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
-
-	if (pci_enable_device(dev))
-		goto fail;
-
-	pci_set_master(dev);
-	agp_bind_memory(par->i810_gtt.i810_fb_memory,
-			par->fb.offset);
-	agp_bind_memory(par->i810_gtt.i810_cursor_memory,
-			par->cursor_heap.offset);
-	i810fb_set_par(info);
-	fb_set_suspend (info, 0);
-	info->fbops->fb_blank(VESA_NO_BLANKING, info);
-fail:
-	console_unlock();
-	return 0;
-}
-/***********************************************************************
- *                  AGP resource allocation                            *
- ***********************************************************************/
-  
-static void i810_fix_pointers(struct i810fb_par *par)
-{
-      	par->fb.physical = par->aperture.physical+(par->fb.offset << 12);
-	par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);
-	par->iring.physical = par->aperture.physical + 
-		(par->iring.offset << 12);
-	par->iring.virtual = par->aperture.virtual + 
-		(par->iring.offset << 12);
-	par->cursor_heap.virtual = par->aperture.virtual+
-		(par->cursor_heap.offset << 12);
-}
-
-static void i810_fix_offsets(struct i810fb_par *par)
-{
-	if (vram + 1 > par->aperture.size >> 20)
-		vram = (par->aperture.size >> 20) - 1;
-	if (v_offset_default > (par->aperture.size >> 20))
-		v_offset_default = (par->aperture.size >> 20);
-	if (vram + v_offset_default + 1 > par->aperture.size >> 20)
-		v_offset_default = (par->aperture.size >> 20) - (vram + 1);
-
-	par->fb.size = vram << 20;
-	par->fb.offset = v_offset_default << 20;
-	par->fb.offset >>= 12;
-
-	par->iring.offset = par->fb.offset + (par->fb.size >> 12);
-	par->iring.size = RINGBUFFER_SIZE;
-
-	par->cursor_heap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12);
-	par->cursor_heap.size = 4096;
-}
-
-static int i810_alloc_agp_mem(struct fb_info *info)
-{
-	struct i810fb_par *par = info->par;
-	int size;
-	struct agp_bridge_data *bridge;
-	
-	i810_fix_offsets(par);
-	size = par->fb.size + par->iring.size;
-
-	if (!(bridge = agp_backend_acquire(par->dev))) {
-		printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
-		return -ENODEV;
-	}
-	if (!(par->i810_gtt.i810_fb_memory = 
-	      agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
-		printk("i810fb_alloc_fbmem: can't allocate framebuffer "
-		       "memory\n");
-		agp_backend_release(bridge);
-		return -ENOMEM;
-	}
-	if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
-			    par->fb.offset)) {
-		printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
-		agp_backend_release(bridge);
-		return -EBUSY;
-	}	
-	
-	if (!(par->i810_gtt.i810_cursor_memory = 
-	      agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
-				  AGP_PHYSICAL_MEMORY))) {
-		printk("i810fb_alloc_cursormem:  can't allocate" 
-		       "cursor memory\n");
-		agp_backend_release(bridge);
-		return -ENOMEM;
-	}
-	if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
-			    par->cursor_heap.offset)) {
-		printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
-		agp_backend_release(bridge);
-		return -EBUSY;
-	}	
-
-	par->cursor_heap.physical = par->i810_gtt.i810_cursor_memory->physical;
-
-	i810_fix_pointers(par);
-
-	agp_backend_release(bridge);
-
-	return 0;
-}
-
-/*************************************************************** 
- *                    Initialization                           * 
- ***************************************************************/
-
-/**
- * i810_init_monspecs
- * @info: pointer to device specific info structure
- *
- * DESCRIPTION:
- * Sets the user monitor's horizontal and vertical
- * frequency limits
- */
-static void i810_init_monspecs(struct fb_info *info)
-{
-	if (!hsync1)
-		hsync1 = HFMIN;
-	if (!hsync2) 
-		hsync2 = HFMAX;
-	if (!info->monspecs.hfmax)
-		info->monspecs.hfmax = hsync2;
-	if (!info->monspecs.hfmin)
-		info->monspecs.hfmin = hsync1;
-	if (hsync2 < hsync1)
-		info->monspecs.hfmin = hsync2;
-
-	if (!vsync1)
-		vsync1 = VFMIN;
-	if (!vsync2) 
-		vsync2 = VFMAX;
-	if (IS_DVT && vsync1 < 60)
-		vsync1 = 60;
-	if (!info->monspecs.vfmax)
-		info->monspecs.vfmax = vsync2;
-	if (!info->monspecs.vfmin)
-		info->monspecs.vfmin = vsync1;
-	if (vsync2 < vsync1) 
-		info->monspecs.vfmin = vsync2;
-}
-
-/**
- * i810_init_defaults - initializes default values to use
- * @par: pointer to i810fb_par structure
- * @info: pointer to current fb_info structure
- */
-static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info)
-{
-	mutex_init(&par->open_lock);
-
-	if (voffset) 
-		v_offset_default = voffset;
-	else if (par->aperture.size > 32 * 1024 * 1024)
-		v_offset_default = 16;
-	else
-		v_offset_default = 8;
-
-	if (!vram) 
-		vram = 1;
-
-	if (accel) 
-		par->dev_flags |= HAS_ACCELERATION;
-
-	if (sync) 
-		par->dev_flags |= ALWAYS_SYNC;
-
-	par->ddc_num = (ddc3 ? 3 : 2);
-
-	if (bpp < 8)
-		bpp = 8;
-	
-	par->i810fb_ops = i810fb_ops;
-
-	if (xres)
-		info->var.xres = xres;
-	else
-		info->var.xres = 640;
-
-	if (yres)
-		info->var.yres = yres;
-	else
-		info->var.yres = 480;
-
-	if (!vyres) 
-		vyres = (vram << 20)/(info->var.xres*bpp >> 3);
-
-	info->var.yres_virtual = vyres;
-	info->var.bits_per_pixel = bpp;
-
-	if (dcolor)
-		info->var.nonstd = 1;
-
-	if (par->dev_flags & HAS_ACCELERATION) 
-		info->var.accel_flags = 1;
-
-	i810_init_monspecs(info);
-}
-	
-/**
- * i810_init_device - initialize device
- * @par: pointer to i810fb_par structure
- */
-static void i810_init_device(struct i810fb_par *par)
-{
-	u8 reg;
-	u8 __iomem *mmio = par->mmio_start_virtual;
-
-	if (mtrr) set_mtrr(par);
-
-	i810_init_cursor(par);
-
-	/* mvo: enable external vga-connector (for laptops) */
-	if (extvga) {
-		i810_writel(HVSYNC, mmio, 0);
-		i810_writel(PWR_CLKC, mmio, 3);
-	}
-
-	pci_read_config_byte(par->dev, 0x50, &reg);
-	reg &= FREQ_MASK;
-	par->mem_freq = (reg) ? 133 : 100;
-
-}
-
-static int i810_allocate_pci_resource(struct i810fb_par *par,
-				      const struct pci_device_id *entry)
-{
-	int err;
-
-	if ((err = pci_enable_device(par->dev))) { 
-		printk("i810fb_init: cannot enable device\n");
-		return err;		
-	}
-	par->res_flags |= PCI_DEVICE_ENABLED;
-
-	if (pci_resource_len(par->dev, 0) > 512 * 1024) {
-		par->aperture.physical = pci_resource_start(par->dev, 0);
-		par->aperture.size = pci_resource_len(par->dev, 0);
-		par->mmio_start_phys = pci_resource_start(par->dev, 1);
-	} else {
-		par->aperture.physical = pci_resource_start(par->dev, 1);
-		par->aperture.size = pci_resource_len(par->dev, 1);
-		par->mmio_start_phys = pci_resource_start(par->dev, 0);
-	}
-	if (!par->aperture.size) {
-		printk("i810fb_init: device is disabled\n");
-		return -ENOMEM;
-	}
-
-	if (!request_mem_region(par->aperture.physical, 
-				par->aperture.size, 
-				i810_pci_list[entry->driver_data])) {
-		printk("i810fb_init: cannot request framebuffer region\n");
-		return -ENODEV;
-	}
-	par->res_flags |= FRAMEBUFFER_REQ;
-
-	par->aperture.virtual = ioremap_nocache(par->aperture.physical, 
-					par->aperture.size);
-	if (!par->aperture.virtual) {
-		printk("i810fb_init: cannot remap framebuffer region\n");
-		return -ENODEV;
-	}
-  
-	if (!request_mem_region(par->mmio_start_phys, 
-				MMIO_SIZE, 
-				i810_pci_list[entry->driver_data])) {
-		printk("i810fb_init: cannot request mmio region\n");
-		return -ENODEV;
-	}
-	par->res_flags |= MMIO_REQ;
-
-	par->mmio_start_virtual = ioremap_nocache(par->mmio_start_phys, 
-						  MMIO_SIZE);
-	if (!par->mmio_start_virtual) {
-		printk("i810fb_init: cannot remap mmio region\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void i810fb_find_init_mode(struct fb_info *info)
-{
-	struct fb_videomode mode;
-	struct fb_var_screeninfo var;
-	struct fb_monspecs *specs = &info->monspecs;
-	int found = 0;
-#ifdef CONFIG_FB_I810_I2C
-	int i;
-	int err = 1;
-	struct i810fb_par *par = info->par;
-#endif
-
-	INIT_LIST_HEAD(&info->modelist);
-	memset(&mode, 0, sizeof(struct fb_videomode));
-	var = info->var;
-#ifdef CONFIG_FB_I810_I2C
-	i810_create_i2c_busses(par);
-
-	for (i = 0; i < par->ddc_num + 1; i++) {
-		err = i810_probe_i2c_connector(info, &par->edid, i);
-		if (!err)
-			break;
-	}
-
-	if (!err)
-		printk("i810fb_init_pci: DDC probe successful\n");
-
-	fb_edid_to_monspecs(par->edid, specs);
-
-	if (specs->modedb == NULL)
-		printk("i810fb_init_pci: Unable to get Mode Database\n");
-
-	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
-				 &info->modelist);
-	if (specs->modedb != NULL) {
-		const struct fb_videomode *m;
-
-		if (xres && yres) {
-			if ((m = fb_find_best_mode(&var, &info->modelist))) {
-				mode = *m;
-				found  = 1;
-			}
-		}
-
-		if (!found) {
-			m = fb_find_best_display(&info->monspecs, &info->modelist);
-			mode = *m;
-			found = 1;
-		}
-
-		fb_videomode_to_var(&var, &mode);
-	}
-#endif
-	if (mode_option)
-		fb_find_mode(&var, info, mode_option, specs->modedb,
-			     specs->modedb_len, (found) ? &mode : NULL,
-			     info->var.bits_per_pixel);
-
-	info->var = var;
-	fb_destroy_modedb(specs->modedb);
-	specs->modedb = NULL;
-}
-
-#ifndef MODULE
-static int i810fb_setup(char *options)
-{
-	char *this_opt, *suffix = NULL;
-
-	if (!options || !*options)
-		return 0;
-	
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "mtrr", 4))
-			mtrr = 1;
-		else if (!strncmp(this_opt, "accel", 5))
-			accel = 1;
-		else if (!strncmp(this_opt, "extvga", 6))
-			extvga = 1;
-		else if (!strncmp(this_opt, "sync", 4))
-			sync = 1;
-		else if (!strncmp(this_opt, "vram:", 5))
-			vram = (simple_strtoul(this_opt+5, NULL, 0));
-		else if (!strncmp(this_opt, "voffset:", 8))
-			voffset = (simple_strtoul(this_opt+8, NULL, 0));
-		else if (!strncmp(this_opt, "xres:", 5))
-			xres = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "yres:", 5))
-			yres = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "vyres:", 6))
-			vyres = simple_strtoul(this_opt+6, NULL, 0);
-		else if (!strncmp(this_opt, "bpp:", 4))
-			bpp = simple_strtoul(this_opt+4, NULL, 0);
-		else if (!strncmp(this_opt, "hsync1:", 7)) {
-			hsync1 = simple_strtoul(this_opt+7, &suffix, 0);
-			if (strncmp(suffix, "H", 1)) 
-				hsync1 *= 1000;
-		} else if (!strncmp(this_opt, "hsync2:", 7)) {
-			hsync2 = simple_strtoul(this_opt+7, &suffix, 0);
-			if (strncmp(suffix, "H", 1)) 
-				hsync2 *= 1000;
-		} else if (!strncmp(this_opt, "vsync1:", 7)) 
-			vsync1 = simple_strtoul(this_opt+7, NULL, 0);
-		else if (!strncmp(this_opt, "vsync2:", 7))
-			vsync2 = simple_strtoul(this_opt+7, NULL, 0);
-		else if (!strncmp(this_opt, "dcolor", 6))
-			dcolor = 1;
-		else if (!strncmp(this_opt, "ddc3", 4))
-			ddc3 = true;
-		else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-#endif
-
-static int i810fb_init_pci(struct pci_dev *dev,
-			   const struct pci_device_id *entry)
-{
-	struct fb_info    *info;
-	struct i810fb_par *par = NULL;
-	struct fb_videomode mode;
-	int err = -1, vfreq, hfreq, pixclock;
-
-	info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	par = info->par;
-	par->dev = dev;
-
-	if (!(info->pixmap.addr = kzalloc(8*1024, GFP_KERNEL))) {
-		i810fb_release_resource(info, par);
-		return -ENOMEM;
-	}
-	info->pixmap.size = 8*1024;
-	info->pixmap.buf_align = 8;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-	if ((err = i810_allocate_pci_resource(par, entry))) {
-		i810fb_release_resource(info, par);
-		return err;
-	}
-
-	i810_init_defaults(par, info);
-
-	if ((err = i810_alloc_agp_mem(info))) {
-		i810fb_release_resource(info, par);
-		return err;
-	}
-
-	i810_init_device(par);        
-
-	info->screen_base = par->fb.virtual;
-	info->fbops = &par->i810fb_ops;
-	info->pseudo_palette = par->pseudo_palette;
-	fb_alloc_cmap(&info->cmap, 256, 0);
-	i810fb_find_init_mode(info);
-
-	if ((err = info->fbops->fb_check_var(&info->var, info))) {
-		i810fb_release_resource(info, par);
-		return err;
-	}
-
-	fb_var_to_videomode(&mode, &info->var);
-	fb_add_videomode(&mode, &info->modelist);
-
-	i810fb_init_ringbuffer(info);
-	err = register_framebuffer(info);
-
-	if (err < 0) {
-    		i810fb_release_resource(info, par); 
-		printk("i810fb_init: cannot register framebuffer device\n");
-    		return err;  
-    	}   
-
-	pci_set_drvdata(dev, info);
-	pixclock = 1000000000/(info->var.pixclock);
-	pixclock *= 1000;
-	hfreq = pixclock/(info->var.xres + info->var.left_margin + 
-			  info->var.hsync_len + info->var.right_margin);
-	vfreq = hfreq/(info->var.yres + info->var.upper_margin +
-		       info->var.vsync_len + info->var.lower_margin);
-
-      	printk("I810FB: fb%d         : %s v%d.%d.%d%s\n"
-      	       "I810FB: Video RAM   : %dK\n" 
-	       "I810FB: Monitor     : H: %d-%d KHz V: %d-%d Hz\n"
-	       "I810FB: Mode        : %dx%d-%dbpp@%dHz\n",
-	       info->node,
-	       i810_pci_list[entry->driver_data],
-	       VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION,
-	       (int) par->fb.size>>10, info->monspecs.hfmin/1000,
-	       info->monspecs.hfmax/1000, info->monspecs.vfmin,
-	       info->monspecs.vfmax, info->var.xres, 
-	       info->var.yres, info->var.bits_per_pixel, vfreq);
-	return 0;
-}
-
-/***************************************************************
- *                     De-initialization                        *
- ***************************************************************/
-
-static void i810fb_release_resource(struct fb_info *info, 
-				    struct i810fb_par *par)
-{
-	struct gtt_data *gtt = &par->i810_gtt;
-	unset_mtrr(par);
-
-	i810_delete_i2c_busses(par);
-
-	if (par->i810_gtt.i810_cursor_memory)
-		agp_free_memory(gtt->i810_cursor_memory);
-	if (par->i810_gtt.i810_fb_memory)
-		agp_free_memory(gtt->i810_fb_memory);
-
-	if (par->mmio_start_virtual)
-		iounmap(par->mmio_start_virtual);
-	if (par->aperture.virtual)
-		iounmap(par->aperture.virtual);
-	kfree(par->edid);
-	if (par->res_flags & FRAMEBUFFER_REQ)
-		release_mem_region(par->aperture.physical,
-				   par->aperture.size);
-	if (par->res_flags & MMIO_REQ)
-		release_mem_region(par->mmio_start_phys, MMIO_SIZE);
-
-	framebuffer_release(info);
-
-}
-
-static void __exit i810fb_remove_pci(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct i810fb_par *par = info->par;
-
-	unregister_framebuffer(info);  
-	i810fb_release_resource(info, par);
-	printk("cleanup_module:  unloaded i810 framebuffer device\n");
-}                                                	
-
-#ifndef MODULE
-static int i810fb_init(void)
-{
-	char *option = NULL;
-
-	if (fb_get_options("i810fb", &option))
-		return -ENODEV;
-	i810fb_setup(option);
-
-	return pci_register_driver(&i810fb_driver);
-}
-#endif 
-
-/*********************************************************************
- *                          Modularization                           *
- *********************************************************************/
-
-#ifdef MODULE
-
-static int i810fb_init(void)
-{
-	hsync1 *= 1000;
-	hsync2 *= 1000;
-
-	return pci_register_driver(&i810fb_driver);
-}
-
-module_param(vram, int, 0);
-MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB" 
-		 " (default=4)");
-module_param(voffset, int, 0);
-MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer "
-                 "memory (0 to maximum aperture size), in MiB (default = 48)");
-module_param(bpp, int, 0);
-MODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel"
-		 " (default = 8)");
-module_param(xres, int, 0);
-MODULE_PARM_DESC(xres, "Horizontal resolution in pixels (default = 640)");
-module_param(yres, int, 0);
-MODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)");
-module_param(vyres,int, 0);
-MODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines"
-		 " (default = 480)");
-module_param(hsync1, int, 0);
-MODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz"
-		 " (default = 29)");
-module_param(hsync2, int, 0);
-MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz"
-		 " (default = 30)");
-module_param(vsync1, int, 0);
-MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz"
-		 " (default = 50)");
-module_param(vsync2, int, 0);
-MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz" 
-		 " (default = 60)");
-module_param(accel, bool, 0);
-MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
-module_param(mtrr, bool, 0);
-MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-module_param(extvga, bool, 0);
-MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
-module_param(sync, bool, 0);
-MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
-		 " (default = 0)");
-module_param(dcolor, bool, 0);
-MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
-		 " (default = 0 = TrueColor)");
-module_param(ddc3, bool, 0);
-MODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Specify initial video mode");
-
-MODULE_AUTHOR("Tony A. Daplas");
-MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
-		   " compatible cards");
-MODULE_LICENSE("GPL"); 
-
-static void __exit i810fb_exit(void)
-{
-	pci_unregister_driver(&i810fb_driver);
-}
-module_exit(i810fb_exit);
-
-#endif /* MODULE */
-
-module_init(i810fb_init);
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
deleted file mode 100644
index a25afaa534ba..000000000000
--- a/drivers/video/i810/i810_main.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*-*- linux-c -*-
- *  linux/drivers/video/i810fb_main.h -- Intel 810 frame buffer device 
- *                                       main header file
- *
- *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
- *
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#ifndef __I810_MAIN_H__
-#define __I810_MAIN_H__
-
-/* Video Timings */
-extern void round_off_xres         (u32 *xres);
-extern void round_off_yres         (u32 *xres, u32 *yres);
-extern u32 i810_get_watermark      (const struct fb_var_screeninfo *var,
-			            struct i810fb_par *par);
-extern void i810fb_encode_registers(const struct fb_var_screeninfo *var,
-				    struct i810fb_par *par, u32 xres, u32 yres);
-extern void i810fb_fill_var_timings(struct fb_var_screeninfo *var);
-				    
-/* Accelerated Functions */
-extern void i810fb_fillrect (struct fb_info *p, 
-			     const struct fb_fillrect *rect);
-extern void i810fb_copyarea (struct fb_info *p, 
-			     const struct fb_copyarea *region);
-extern void i810fb_imageblit(struct fb_info *p, const struct fb_image *image);
-extern int  i810fb_sync     (struct fb_info *p);
-
-extern void i810fb_init_ringbuffer(struct fb_info *info);
-extern void i810fb_load_front     (u32 offset, struct fb_info *info);
-
-#ifdef CONFIG_FB_I810_I2C
-/* I2C */
-extern int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
-				    int conn);
-extern void i810_create_i2c_busses(struct i810fb_par *par);
-extern void i810_delete_i2c_busses(struct i810fb_par *par);
-#else
-static inline int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
-				    int conn)
-{
-	return 1;
-}
-static inline void i810_create_i2c_busses(struct i810fb_par *par) { }
-static inline void i810_delete_i2c_busses(struct i810fb_par *par) { }
-#endif
-
-/* Conditionals */
-#ifdef CONFIG_X86
-static inline void flush_cache(void)
-{
-	asm volatile ("wbinvd":::"memory");
-}
-#else
-#define flush_cache() do { } while(0)
-#endif 
-
-#ifdef CONFIG_MTRR
-
-#include <asm/mtrr.h>
-
-static inline void set_mtrr(struct i810fb_par *par)
-{
-	par->mtrr_reg = mtrr_add((u32) par->aperture.physical, 
-		 par->aperture.size, MTRR_TYPE_WRCOMB, 1);
-	if (par->mtrr_reg < 0) {
-		printk(KERN_ERR "set_mtrr: unable to set MTRR\n");
-		return;
-	}
-	par->dev_flags |= HAS_MTRR;
-}
-static inline void unset_mtrr(struct i810fb_par *par)
-{
-  	if (par->dev_flags & HAS_MTRR) 
-  		mtrr_del(par->mtrr_reg, (u32) par->aperture.physical, 
-			 par->aperture.size); 
-}
-#else
-#define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n")
-
-#define unset_mtrr(x) do { } while (0)
-#endif /* CONFIG_MTRR */
-
-#ifdef CONFIG_FB_I810_GTF
-#define IS_DVT (0)
-#else
-#define IS_DVT (1)
-#endif
-
-#endif /* __I810_MAIN_H__ */
diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/i810/i810_regs.h
deleted file mode 100644
index 91c6bd9d0d0d..000000000000
--- a/drivers/video/i810/i810_regs.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/*-*- linux-c -*-
- *  linux/drivers/video/i810_regs.h -- Intel 810/815 Register List
- *
- *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
- *
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-
-/*
- * Intel 810 Chipset Family PRM 15 3.1 
- * GC Register Memory Address Map 
- *
- * Based on:
- * Intel (R) 810 Chipset Family 
- * Programmer s Reference Manual 
- * November 1999 
- * Revision 1.0 
- * Order Number: 298026-001 R
- *
- * All GC registers are memory-mapped. In addition, the VGA and extended VGA registers 
- * are I/O mapped. 
- */
- 
-#ifndef __I810_REGS_H__
-#define __I810_REGS_H__
-
-/*  Instruction and Interrupt Control Registers (01000h 02FFFh) */
-#define FENCE                 0x02000                
-#define PGTBL_CTL             0x02020 
-#define PGTBL_ER              0x02024               
-#define    LRING              0x02030
-#define    IRING              0x02040
-#define HWS_PGA               0x02080 
-#define IPEIR                 0x02088
-#define IPEHR                 0x0208C 
-#define INSTDONE              0x02090 
-#define NOPID                 0x02094
-#define HWSTAM                0x02098 
-#define IER                   0x020A0
-#define IIR                   0x020A4
-#define IMR                   0x020A8 
-#define ISR                   0x020AC 
-#define EIR                   0x020B0 
-#define EMR                   0x020B4 
-#define ESR                   0x020B8 
-#define INSTPM                0x020C0
-#define INSTPS                0x020C4 
-#define BBP_PTR               0x020C8 
-#define ABB_SRT               0x020CC
-#define ABB_END               0x020D0
-#define DMA_FADD              0x020D4 
-#define FW_BLC                0x020D8
-#define MEM_MODE              0x020DC        
-
-/*  Memory Control Registers (03000h 03FFFh) */
-#define DRT                   0x03000
-#define DRAMCL                0x03001
-#define DRAMCH                0x03002
- 
-
-/* Span Cursor Registers (04000h 04FFFh) */
-#define UI_SC_CTL             0x04008 
-
-/* I/O Control Registers (05000h 05FFFh) */
-#define HVSYNC                0x05000 
-#define GPIOA                 0x05010
-#define GPIOB                 0x05014 
-#define GPIOC                 0x0501C
-
-/* Clock Control and Power Management Registers (06000h 06FFFh) */
-#define DCLK_0D               0x06000
-#define DCLK_1D               0x06004
-#define DCLK_2D               0x06008
-#define LCD_CLKD              0x0600C
-#define DCLK_0DS              0x06010
-#define PWR_CLKC              0x06014
-
-/* Graphics Translation Table Range Definition (10000h 1FFFFh) */
-#define GTT                   0x10000  
-
-/*  Overlay Registers (30000h 03FFFFh) */
-#define OVOADDR               0x30000
-#define DOVOSTA               0x30008
-#define GAMMA                 0x30010
-#define OBUF_0Y               0x30100
-#define OBUF_1Y               0x30104
-#define OBUF_0U               0x30108
-#define OBUF_0V               0x3010C
-#define OBUF_1U               0x30110
-#define OBUF_1V               0x30114 
-#define OVOSTRIDE             0x30118
-#define YRGB_VPH              0x3011C
-#define UV_VPH                0x30120
-#define HORZ_PH               0x30124
-#define INIT_PH               0x30128
-#define DWINPOS               0x3012C 
-#define DWINSZ                0x30130
-#define SWID                  0x30134
-#define SWIDQW                0x30138
-#define SHEIGHT               0x3013F
-#define YRGBSCALE             0x30140 
-#define UVSCALE               0x30144
-#define OVOCLRCO              0x30148
-#define OVOCLRC1              0x3014C
-#define DCLRKV                0x30150
-#define DLCRKM                0x30154
-#define SCLRKVH               0x30158
-#define SCLRKVL               0x3015C
-#define SCLRKM                0x30160
-#define OVOCONF               0x30164
-#define OVOCMD                0x30168
-#define AWINPOS               0x30170
-#define AWINZ                 0x30174
-
-/*  BLT Engine Status (40000h 4FFFFh) (Software Debug) */
-#define BR00                  0x40000
-#define BRO1                  0x40004
-#define BR02                  0x40008
-#define BR03                  0x4000C
-#define BR04                  0x40010
-#define BR05                  0x40014
-#define BR06                  0x40018
-#define BR07                  0x4001C
-#define BR08                  0x40020
-#define BR09                  0x40024
-#define BR10                  0x40028
-#define BR11                  0x4002C
-#define BR12                  0x40030
-#define BR13                  0x40034
-#define BR14                  0x40038
-#define BR15                  0x4003C
-#define BR16                  0x40040
-#define BR17                  0x40044
-#define BR18                  0x40048
-#define BR19                  0x4004C
-#define SSLADD                0x40074
-#define DSLH                  0x40078
-#define DSLRADD               0x4007C
-
-
-/* LCD/TV-Out and HW DVD Registers (60000h 6FFFFh) */
-/* LCD/TV-Out */
-#define HTOTAL                0x60000
-#define HBLANK                0x60004
-#define HSYNC                 0x60008
-#define VTOTAL                0x6000C
-#define VBLANK                0x60010
-#define VSYNC                 0x60014
-#define LCDTV_C               0x60018
-#define OVRACT                0x6001C
-#define BCLRPAT               0x60020
-
-/*  Display and Cursor Control Registers (70000h 7FFFFh) */
-#define DISP_SL               0x70000
-#define DISP_SLC              0x70004
-#define PIXCONF               0x70008
-#define PIXCONF1              0x70009
-#define BLTCNTL               0x7000C
-#define SWF                   0x70014
-#define DPLYBASE              0x70020
-#define DPLYSTAS              0x70024
-#define CURCNTR               0x70080
-#define CURBASE               0x70084
-#define CURPOS                0x70088
-
-
-/* VGA Registers */
-
-/* SMRAM Registers */
-#define SMRAM                 0x10
-
-/* Graphics Control Registers */
-#define GR_INDEX              0x3CE
-#define GR_DATA               0x3CF
-
-#define GR10                  0x10
-#define GR11                  0x11
-
-/* CRT Controller Registers */
-#define CR_INDEX_MDA          0x3B4
-#define CR_INDEX_CGA          0x3D4
-#define CR_DATA_MDA           0x3B5
-#define CR_DATA_CGA           0x3D5
-
-#define CR30                  0x30
-#define CR31                  0x31
-#define CR32                  0x32
-#define CR33                  0x33
-#define CR35                  0x35
-#define CR39                  0x39
-#define CR40                  0x40
-#define CR41                  0x41
-#define CR42                  0x42
-#define CR70                  0x70
-#define CR80                  0x80 
-#define CR81                  0x82
-
-/* Extended VGA Registers */
-
-/* General Control and Status Registers */
-#define ST00                  0x3C2
-#define ST01_MDA              0x3BA
-#define ST01_CGA              0x3DA
-#define FRC_READ              0x3CA
-#define FRC_WRITE_MDA         0x3BA
-#define FRC_WRITE_CGA         0x3DA
-#define MSR_READ              0x3CC
-#define MSR_WRITE             0x3C2
-
-/* Sequencer Registers */
-#define SR_INDEX              0x3C4
-#define SR_DATA               0x3C5
-
-#define SR01                  0x01
-#define SR02                  0x02
-#define SR03                  0x03
-#define SR04                  0x04
-#define SR07                  0x07
-
-/* Graphics Controller Registers */
-#define GR00                  0x00   
-#define GR01                  0x01
-#define GR02                  0x02
-#define GR03                  0x03
-#define GR04                  0x04
-#define GR05                  0x05
-#define GR06                  0x06
-#define GR07                  0x07
-#define GR08                  0x08  
-
-/* Attribute Controller Registers */
-#define ATTR_WRITE              0x3C0
-#define ATTR_READ               0x3C1
-
-/* VGA Color Palette Registers */
-
-/* CLUT */
-#define CLUT_DATA             0x3C9        /* DACDATA */
-#define CLUT_INDEX_READ       0x3C7        /* DACRX */
-#define CLUT_INDEX_WRITE      0x3C8        /* DACWX */
-#define DACMASK               0x3C6
-
-/* CRT Controller Registers */
-#define CR00                  0x00
-#define CR01                  0x01
-#define CR02                  0x02
-#define CR03                  0x03
-#define CR04                  0x04
-#define CR05                  0x05
-#define CR06                  0x06
-#define CR07                  0x07
-#define CR08                  0x08
-#define CR09                  0x09
-#define CR0A                  0x0A
-#define CR0B                  0x0B
-#define CR0C                  0x0C
-#define CR0D                  0x0D
-#define CR0E                  0x0E
-#define CR0F                  0x0F
-#define CR10                  0x10
-#define CR11                  0x11
-#define CR12                  0x12
-#define CR13                  0x13
-#define CR14                  0x14
-#define CR15                  0x15
-#define CR16                  0x16
-#define CR17                  0x17
-#define CR18                  0x18
-
-#endif /* __I810_REGS_H__ */
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
deleted file mode 100644
index 486f18897414..000000000000
--- a/drivers/video/igafb.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- *  linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
- *
- *      Copyright (C) 1998  Vladimir Roganov and Gleb Raiko
- *
- *  This driver is partly based on the Frame buffer device for ATI Mach64
- *  and partially on VESA-related code.
- *
- *      Copyright (C) 1997-1998  Geert Uytterhoeven
- *      Copyright (C) 1998  Bernd Harries
- *      Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-/******************************************************************************
-
-  TODO:
-       Despite of IGA Card has advanced graphic acceleration, 
-       initial version is almost dummy and does not support it.
-       Support for video modes and acceleration must be added
-       together with accelerated X-Windows driver implementation.
-
-       Most important thing at this moment is that we have working
-       JavaEngine1  console & X  with new console interface.
-
-******************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/nvram.h>
-
-#include <asm/io.h>
-
-#ifdef CONFIG_SPARC
-#include <asm/prom.h>
-#include <asm/pcic.h>
-#endif
-
-#include <video/iga.h>
-
-struct pci_mmap_map {
-    unsigned long voff;
-    unsigned long poff;
-    unsigned long size;
-    unsigned long prot_flag;
-    unsigned long prot_mask;
-};
-
-struct iga_par {
-	struct pci_mmap_map *mmap_map;
-	unsigned long frame_buffer_phys;
-	unsigned long io_base;
-};
-
-struct fb_info fb_info;
-
-struct fb_fix_screeninfo igafb_fix __initdata = {
-        .id		= "IGA 1682",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.mmio_len 	= 1000
-};
-
-struct fb_var_screeninfo default_var = {
-	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-	.xres		= 640,
-	.yres		= 480,
-	.xres_virtual	= 640,
-	.yres_virtual	= 480,
-	.bits_per_pixel	= 8,
-	.red		= {0, 8, 0 },
-	.green		= {0, 8, 0 },
-	.blue		= {0, 8, 0 },
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= FB_ACCEL_NONE,
-	.pixclock	= 39722,
-	.left_margin	= 48,
-	.right_margin	= 16,
-	.upper_margin	= 33,
-	.lower_margin	= 10,
-	.hsync_len	= 96,
-	.vsync_len	= 2,
-	.vmode		= FB_VMODE_NONINTERLACED
-};
-
-#ifdef CONFIG_SPARC
-struct fb_var_screeninfo default_var_1024x768 __initdata = {
-	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
-	.xres		= 1024,
-	.yres		= 768,
-	.xres_virtual	= 1024,
-	.yres_virtual	= 768,
-	.bits_per_pixel	= 8,
-	.red		= {0, 8, 0 },
-	.green		= {0, 8, 0 },
-	.blue		= {0, 8, 0 },
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= FB_ACCEL_NONE,
-	.pixclock	= 12699,
-	.left_margin	= 176,
-	.right_margin	= 16,
-	.upper_margin	= 28,
-	.lower_margin	= 1,
-	.hsync_len	= 96,
-	.vsync_len	= 3,
-	.vmode		= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-struct fb_var_screeninfo default_var_1152x900 __initdata = {
-	/* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
-	.xres		= 1152,
-	.yres		= 900,
-	.xres_virtual	= 1152,
-	.yres_virtual	= 900,
-	.bits_per_pixel	= 8,
-	.red		= { 0, 8, 0 },
-	.green		= { 0, 8, 0 },
-	.blue		= { 0, 8, 0 },
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= FB_ACCEL_NONE,
-	.pixclock	= 9091,
-	.left_margin	= 234,
-	.right_margin	= 24,
-	.upper_margin	= 34,
-	.lower_margin	= 3,
-	.hsync_len	= 100,
-	.vsync_len	= 3,
-	.vmode		= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-struct fb_var_screeninfo default_var_1280x1024 __initdata = {
-	/* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
-	.xres		= 1280,
-	.yres		= 1024,
-	.xres_virtual	= 1280,
-	.yres_virtual	= 1024,
-	.bits_per_pixel	= 8,
-	.red		= {0, 8, 0 }, 
-	.green		= {0, 8, 0 },
-	.blue		= {0, 8, 0 },
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= 0,
-	.pixclock	= 7408,
-	.left_margin	= 248,
-	.right_margin	= 16,
-	.upper_margin	= 38,
-	.lower_margin	= 1,
-	.hsync_len	= 144,
-	.vsync_len	= 3,
-	.vmode		= FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-/*
- *   Memory-mapped I/O functions for Sparc PCI
- *
- * On sparc we happen to access I/O with memory mapped functions too.
- */ 
-#define pci_inb(par, reg)        readb(par->io_base+(reg))
-#define pci_outb(par, val, reg)  writeb(val, par->io_base+(reg))
-
-static inline unsigned int iga_inb(struct iga_par *par, unsigned int reg,
-				   unsigned int idx)
-{
-        pci_outb(par, idx, reg);
-        return pci_inb(par, reg + 1);
-}
-
-static inline void iga_outb(struct iga_par *par, unsigned char val,
-			    unsigned int reg, unsigned int idx )
-{
-        pci_outb(par, idx, reg);
-        pci_outb(par, val, reg+1);
-}
-
-#endif /* CONFIG_SPARC */
-
-/*
- *  Very important functionality for the JavaEngine1 computer:
- *  make screen border black (usign special IGA registers) 
- */
-static void iga_blank_border(struct iga_par *par)
-{
-        int i;
-#if 0
-	/*
-	 * PROM does this for us, so keep this code as a reminder
-	 * about required read from 0x3DA and writing of 0x20 in the end.
-	 */
-	(void) pci_inb(par, 0x3DA);		/* required for every access */
-	pci_outb(par, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
-	(void) pci_inb(par, IGA_ATTR_CTL+1);
-	pci_outb(par, 0x38, IGA_ATTR_CTL);
-	pci_outb(par, 0x20, IGA_ATTR_CTL);	/* re-enable visual */
-#endif
-	/*
-	 * This does not work as it was designed because the overscan
-	 * color is looked up in the palette. Therefore, under X11
-	 * overscan changes color.
-	 */
-	for (i=0; i < 3; i++)
-		iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
-}
-
-#ifdef CONFIG_SPARC
-static int igafb_mmap(struct fb_info *info,
-		      struct vm_area_struct *vma)
-{
-	struct iga_par *par = (struct iga_par *)info->par;
-	unsigned int size, page, map_size = 0;
-	unsigned long map_offset = 0;
-	int i;
-
-	if (!par->mmap_map)
-		return -ENXIO;
-
-	size = vma->vm_end - vma->vm_start;
-
-	/* Each page, see which map applies */
-	for (page = 0; page < size; ) {
-		map_size = 0;
-		for (i = 0; par->mmap_map[i].size; i++) {
-			unsigned long start = par->mmap_map[i].voff;
-			unsigned long end = start + par->mmap_map[i].size;
-			unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
-
-			if (start > offset)
-				continue;
-			if (offset >= end)
-				continue;
-
-			map_size = par->mmap_map[i].size - (offset - start);
-			map_offset = par->mmap_map[i].poff + (offset - start);
-			break;
-		}
-		if (!map_size) {
-			page += PAGE_SIZE;
-			continue;
-		}
-		if (page + map_size > size)
-			map_size = size - page;
-
-		pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
-		pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
-
-		if (remap_pfn_range(vma, vma->vm_start + page,
-			map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
-			return -EAGAIN;
-
-		page += map_size;
-	}
-
-	if (!map_size)
-		return -EINVAL;
-
-	vma->vm_flags |= VM_IO;
-	return 0;
-}
-#endif /* CONFIG_SPARC */
-
-static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green,
-                           unsigned blue, unsigned transp,
-                           struct fb_info *info)
-{
-        /*
-         *  Set a single color register. The values supplied are
-         *  already rounded down to the hardware's capabilities
-         *  (according to the entries in the `var' structure). Return
-         *  != 0 for invalid regno.
-         */
-	struct iga_par *par = (struct iga_par *)info->par;
-
-        if (regno >= info->cmap.len)
-                return 1;
-
-	pci_outb(par, regno, DAC_W_INDEX);
-	pci_outb(par, red,   DAC_DATA);
-	pci_outb(par, green, DAC_DATA);
-	pci_outb(par, blue,  DAC_DATA);
-
-	if (regno < 16) {
-		switch (info->var.bits_per_pixel) {
-		case 16:
-			((u16*)(info->pseudo_palette))[regno] = 
-				(regno << 10) | (regno << 5) | regno;
-			break;
-		case 24:
-			((u32*)(info->pseudo_palette))[regno] = 
-				(regno << 16) | (regno << 8) | regno;
-		break;
-		case 32:
-			{ int i;
-			i = (regno << 8) | regno;
-			((u32*)(info->pseudo_palette))[regno] = (i << 16) | i;
-			}
-			break;
-		}
-	}
-	return 0;
-}
-
-/*
- * Framebuffer option structure
- */
-static struct fb_ops igafb_ops = {
-	.owner 		= THIS_MODULE,
-	.fb_setcolreg 	= igafb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-#ifdef CONFIG_SPARC
-	.fb_mmap 	= igafb_mmap,
-#endif
-};
-
-static int __init iga_init(struct fb_info *info, struct iga_par *par)
-{
-        char vramsz = iga_inb(par, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) 
-		                                         & MEM_SIZE_ALIAS;
-	int video_cmap_len;
-
-        switch (vramsz) {
-        case MEM_SIZE_1M:
-                info->fix.smem_len = 0x100000;
-                break;
-        case MEM_SIZE_2M:
-                info->fix.smem_len = 0x200000;
-                break;
-        case MEM_SIZE_4M:
-        case MEM_SIZE_RESERVED:
-                info->fix.smem_len = 0x400000;
-                break;
-        }
-
-        if (info->var.bits_per_pixel > 8) 
-                video_cmap_len = 16;
-        else 
-                video_cmap_len = 256;
-
-	info->fbops = &igafb_ops;
-	info->flags = FBINFO_DEFAULT;
-
-	fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
-
-	if (register_framebuffer(info) < 0)
-		return 0;
-
-	fb_info(info, "%s frame buffer device at 0x%08lx [%dMB VRAM]\n",
-		info->fix.id, par->frame_buffer_phys, info->fix.smem_len >> 20);
-
-	iga_blank_border(par); 
-	return 1;
-}
-
-static int __init igafb_init(void)
-{
-        struct fb_info *info;
-        struct pci_dev *pdev;
-        struct iga_par *par;
-	unsigned long addr;
-	int size, iga2000 = 0;
-
-	if (fb_get_options("igafb", NULL))
-		return -ENODEV;
-
-        pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
-                               PCI_DEVICE_ID_INTERG_1682, 0);
-	if (pdev == NULL) {
-		/*
-		 * XXX We tried to use cyber2000fb.c for IGS 2000.
-		 * But it does not initialize the chip in JavaStation-E, alas.
-		 */
-        	pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
-        	if(pdev == NULL) {
-        	        return -ENXIO;
-		}
-		iga2000 = 1;
-	}
-	/* We leak a reference here but as it cannot be unloaded this is
-	   fine. If you write unload code remember to free it in unload */
-	
-	size = sizeof(struct iga_par) + sizeof(u32)*16;
-
-	info = framebuffer_alloc(size, &pdev->dev);
-        if (!info) {
-                printk("igafb_init: can't alloc fb_info\n");
-		 pci_dev_put(pdev);
-                return -ENOMEM;
-        }
-
-	par = info->par;
-
-	if ((addr = pdev->resource[0].start) == 0) {
-                printk("igafb_init: no memory start\n");
-		kfree(info);
-		pci_dev_put(pdev);
-		return -ENXIO;
-	}
-
-	if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) {
-                printk("igafb_init: can't remap %lx[2M]\n", addr);
-		kfree(info);
-		pci_dev_put(pdev);
-		return -ENXIO;
-	}
-
-	par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
-
-#ifdef CONFIG_SPARC
-	/*
-	 * The following is sparc specific and this is why:
-	 *
-	 * IGS2000 has its I/O memory mapped and we want
-	 * to generate memory cycles on PCI, e.g. do ioremap(),
-	 * then readb/writeb() as in Documentation/io-mapping.txt.
-	 *
-	 * IGS1682 is more traditional, it responds to PCI I/O
-	 * cycles, so we want to access it with inb()/outb().
-	 *
-	 * On sparc, PCIC converts CPU memory access within
-	 * phys window 0x3000xxxx into PCI I/O cycles. Therefore
-	 * we may use readb/writeb to access them with IGS1682.
-	 *
-	 * We do not take io_base_phys from resource[n].start
-	 * on IGS1682 because that chip is BROKEN. It does not
-	 * have a base register for I/O. We just "know" what its
-	 * I/O addresses are.
-	 */
-	if (iga2000) {
-		igafb_fix.mmio_start = par->frame_buffer_phys | 0x00800000;
-	} else {
-		igafb_fix.mmio_start = 0x30000000;	/* XXX */
-	}
-	if ((par->io_base = (int) ioremap(igafb_fix.mmio_start, igafb_fix.smem_len)) == 0) {
-                printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start);
-		iounmap((void *)info->screen_base);
-		kfree(info);
-		pci_dev_put(pdev);
-		return -ENXIO;
-	}
-
-	/*
-	 * Figure mmap addresses from PCI config space.
-	 * We need two regions: for video memory and for I/O ports.
-	 * Later one can add region for video coprocessor registers.
-	 * However, mmap routine loops until size != 0, so we put
-	 * one additional region with size == 0. 
-	 */
-
-	par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
-	if (!par->mmap_map) {
-		printk("igafb_init: can't alloc mmap_map\n");
-		iounmap((void *)par->io_base);
-		iounmap(info->screen_base);
-		kfree(info);
-		pci_dev_put(pdev);
-		return -ENOMEM;
-	}
-
-	/*
-	 * Set default vmode and cmode from PROM properties.
-	 */
-	{
-		struct device_node *dp = pci_device_to_OF_node(pdev);
-                int node = dp->node;
-                int width = prom_getintdefault(node, "width", 1024);
-                int height = prom_getintdefault(node, "height", 768);
-                int depth = prom_getintdefault(node, "depth", 8);
-                switch (width) {
-                    case 1024:
-                        if (height == 768)
-                            default_var = default_var_1024x768;
-                        break;
-                    case 1152:
-                        if (height == 900)
-                            default_var = default_var_1152x900;
-                        break;
-                    case 1280:
-                        if (height == 1024)
-                            default_var = default_var_1280x1024;
-                        break;
-                    default:
-                        break;
-                }
-
-                switch (depth) {
-                    case 8:
-                        default_var.bits_per_pixel = 8;
-                        break;
-                    case 16:
-                        default_var.bits_per_pixel = 16;
-                        break;
-                    case 24:
-                        default_var.bits_per_pixel = 24;
-                        break;
-                    case 32:
-                        default_var.bits_per_pixel = 32;
-                        break;
-                    default:
-                        break;
-                }
-            }
-
-#endif
-	igafb_fix.smem_start = (unsigned long) info->screen_base;
-	igafb_fix.line_length = default_var.xres*(default_var.bits_per_pixel/8);
-	igafb_fix.visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
-	info->var = default_var;
-	info->fix = igafb_fix;
-	info->pseudo_palette = (void *)(par + 1);
-
-	if (!iga_init(info, par)) {
-		iounmap((void *)par->io_base);
-		iounmap(info->screen_base);
-		kfree(par->mmap_map);
-		kfree(info);
-		return -ENODEV;
-        }
-
-#ifdef CONFIG_SPARC
-	    /*
-	     * Add /dev/fb mmap values.
-	     */
-	    
-	    /* First region is for video memory */
-	    par->mmap_map[0].voff = 0x0;  
-	    par->mmap_map[0].poff = par->frame_buffer_phys & PAGE_MASK;
-	    par->mmap_map[0].size = info->fix.smem_len & PAGE_MASK;
-	    par->mmap_map[0].prot_mask = SRMMU_CACHE;
-	    par->mmap_map[0].prot_flag = SRMMU_WRITE;
-
-	    /* Second region is for I/O ports */
-	    par->mmap_map[1].voff = par->frame_buffer_phys & PAGE_MASK;
-	    par->mmap_map[1].poff = info->fix.smem_start & PAGE_MASK;
-	    par->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
-	    par->mmap_map[1].prot_mask = SRMMU_CACHE;
-	    par->mmap_map[1].prot_flag = SRMMU_WRITE;
-#endif /* CONFIG_SPARC */
-
-	return 0;
-}
-
-static int __init igafb_setup(char *options)
-{
-    char *this_opt;
-
-    if (!options || !*options)
-        return 0;
-
-    while ((this_opt = strsep(&options, ",")) != NULL) {
-    }
-    return 0;
-}
-
-module_init(igafb_init);
-MODULE_LICENSE("GPL");
-static struct pci_device_id igafb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, igafb_pci_tbl);
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
deleted file mode 100644
index aae10ce74f14..000000000000
--- a/drivers/video/imsttfb.c
+++ /dev/null
@@ -1,1626 +0,0 @@
-/*
- *  drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo
- *
- *  This file is derived from the powermac console "imstt" driver:
- *  Copyright (C) 1997 Sigurdur Asgeirsson
- *  With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu)
- *  Modified by Danilo Beuche 1998
- *  Some register values added by Damien Doligez, INRIA Rocquencourt
- *  Various cleanups by Paul Mundt (lethal@chaoticdreams.org)
- *
- *  This file was written by Ryan Nielsen (ran@krazynet.com)
- *  Most of the frame buffer device stuff was copied from atyfb.c
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-
-#if defined(CONFIG_PPC)
-#include <linux/nvram.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include "macmodes.h"
-#endif
-
-#ifndef __powerpc__
-#define eieio()		/* Enforce In-order Execution of I/O */
-#endif
-
-/* TwinTurbo (Cosmo) registers */
-enum {
-	S1SA	=  0, /* 0x00 */
-	S2SA	=  1, /* 0x04 */
-	SP	=  2, /* 0x08 */
-	DSA	=  3, /* 0x0C */
-	CNT	=  4, /* 0x10 */
-	DP_OCTL	=  5, /* 0x14 */
-	CLR	=  6, /* 0x18 */
-	BI	=  8, /* 0x20 */
-	MBC	=  9, /* 0x24 */
-	BLTCTL	= 10, /* 0x28 */
-
-	/* Scan Timing Generator Registers */
-	HES	= 12, /* 0x30 */
-	HEB	= 13, /* 0x34 */
-	HSB	= 14, /* 0x38 */
-	HT	= 15, /* 0x3C */
-	VES	= 16, /* 0x40 */
-	VEB	= 17, /* 0x44 */
-	VSB	= 18, /* 0x48 */
-	VT	= 19, /* 0x4C */
-	HCIV	= 20, /* 0x50 */
-	VCIV	= 21, /* 0x54 */
-	TCDR	= 22, /* 0x58 */
-	VIL	= 23, /* 0x5C */
-	STGCTL	= 24, /* 0x60 */
-
-	/* Screen Refresh Generator Registers */
-	SSR	= 25, /* 0x64 */
-	HRIR	= 26, /* 0x68 */
-	SPR	= 27, /* 0x6C */
-	CMR	= 28, /* 0x70 */
-	SRGCTL	= 29, /* 0x74 */
-
-	/* RAM Refresh Generator Registers */
-	RRCIV	= 30, /* 0x78 */
-	RRSC	= 31, /* 0x7C */
-	RRCR	= 34, /* 0x88 */
-
-	/* System Registers */
-	GIOE	= 32, /* 0x80 */
-	GIO	= 33, /* 0x84 */
-	SCR	= 35, /* 0x8C */
-	SSTATUS	= 36, /* 0x90 */
-	PRC	= 37, /* 0x94 */
-
-#if 0	
-	/* PCI Registers */
-	DVID	= 0x00000000L,
-	SC	= 0x00000004L,
-	CCR	= 0x00000008L,
-	OG	= 0x0000000CL,
-	BARM	= 0x00000010L,
-	BARER	= 0x00000030L,
-#endif
-};
-
-/* IBM 624 RAMDAC Direct Registers */
-enum {
-	PADDRW	= 0x00,
-	PDATA	= 0x04,
-	PPMASK	= 0x08,
-	PADDRR	= 0x0c,
-	PIDXLO	= 0x10,	
-	PIDXHI	= 0x14,	
-	PIDXDATA= 0x18,
-	PIDXCTL	= 0x1c
-};
-
-/* IBM 624 RAMDAC Indirect Registers */
-enum {
-	CLKCTL		= 0x02,	/* (0x01) Miscellaneous Clock Control */
-	SYNCCTL		= 0x03,	/* (0x00) Sync Control */
-	HSYNCPOS	= 0x04,	/* (0x00) Horizontal Sync Position */
-	PWRMNGMT	= 0x05,	/* (0x00) Power Management */
-	DACOP		= 0x06,	/* (0x02) DAC Operation */
-	PALETCTL	= 0x07,	/* (0x00) Palette Control */
-	SYSCLKCTL	= 0x08,	/* (0x01) System Clock Control */
-	PIXFMT		= 0x0a,	/* () Pixel Format  [bpp >> 3 + 2] */
-	BPP8		= 0x0b,	/* () 8 Bits/Pixel Control */
-	BPP16		= 0x0c, /* () 16 Bits/Pixel Control  [bit 1=1 for 565] */
-	BPP24		= 0x0d,	/* () 24 Bits/Pixel Control */
-	BPP32		= 0x0e,	/* () 32 Bits/Pixel Control */
-	PIXCTL1		= 0x10, /* (0x05) Pixel PLL Control 1 */
-	PIXCTL2		= 0x11,	/* (0x00) Pixel PLL Control 2 */
-	SYSCLKN		= 0x15,	/* () System Clock N (System PLL Reference Divider) */
-	SYSCLKM		= 0x16,	/* () System Clock M (System PLL VCO Divider) */
-	SYSCLKP		= 0x17,	/* () System Clock P */
-	SYSCLKC		= 0x18,	/* () System Clock C */
-	/*
-	 * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
-	 * c is charge pump bias which depends on the VCO frequency  
-	 */
-	PIXM0		= 0x20,	/* () Pixel M 0 */
-	PIXN0		= 0x21,	/* () Pixel N 0 */
-	PIXP0		= 0x22,	/* () Pixel P 0 */
-	PIXC0		= 0x23,	/* () Pixel C 0 */
-	CURSCTL		= 0x30,	/* (0x00) Cursor Control */
-	CURSXLO		= 0x31,	/* () Cursor X position, low 8 bits */
-	CURSXHI		= 0x32,	/* () Cursor X position, high 8 bits */
-	CURSYLO		= 0x33,	/* () Cursor Y position, low 8 bits */
-	CURSYHI		= 0x34,	/* () Cursor Y position, high 8 bits */
-	CURSHOTX	= 0x35,	/* () Cursor Hot Spot X */
-	CURSHOTY	= 0x36,	/* () Cursor Hot Spot Y */
-	CURSACCTL	= 0x37,	/* () Advanced Cursor Control Enable */
-	CURSACATTR	= 0x38,	/* () Advanced Cursor Attribute */
-	CURS1R		= 0x40,	/* () Cursor 1 Red */
-	CURS1G		= 0x41,	/* () Cursor 1 Green */
-	CURS1B		= 0x42,	/* () Cursor 1 Blue */
-	CURS2R		= 0x43,	/* () Cursor 2 Red */
-	CURS2G		= 0x44,	/* () Cursor 2 Green */
-	CURS2B		= 0x45,	/* () Cursor 2 Blue */
-	CURS3R		= 0x46,	/* () Cursor 3 Red */
-	CURS3G		= 0x47,	/* () Cursor 3 Green */
-	CURS3B		= 0x48,	/* () Cursor 3 Blue */
-	BORDR		= 0x60,	/* () Border Color Red */
-	BORDG		= 0x61,	/* () Border Color Green */
-	BORDB		= 0x62,	/* () Border Color Blue */
-	MISCTL1		= 0x70,	/* (0x00) Miscellaneous Control 1 */
-	MISCTL2		= 0x71,	/* (0x00) Miscellaneous Control 2 */
-	MISCTL3		= 0x72,	/* (0x00) Miscellaneous Control 3 */
-	KEYCTL		= 0x78	/* (0x00) Key Control/DB Operation */
-};
-
-/* TI TVP 3030 RAMDAC Direct Registers */
-enum {
-	TVPADDRW = 0x00,	/* 0  Palette/Cursor RAM Write Address/Index */
-	TVPPDATA = 0x04,	/* 1  Palette Data RAM Data */
-	TVPPMASK = 0x08,	/* 2  Pixel Read-Mask */
-	TVPPADRR = 0x0c,	/* 3  Palette/Cursor RAM Read Address */
-	TVPCADRW = 0x10,	/* 4  Cursor/Overscan Color Write Address */
-	TVPCDATA = 0x14,	/* 5  Cursor/Overscan Color Data */
-				/* 6  reserved */
-	TVPCADRR = 0x1c,	/* 7  Cursor/Overscan Color Read Address */
-				/* 8  reserved */
-	TVPDCCTL = 0x24,	/* 9  Direct Cursor Control */
-	TVPIDATA = 0x28,	/* 10 Index Data */
-	TVPCRDAT = 0x2c,	/* 11 Cursor RAM Data */
-	TVPCXPOL = 0x30,	/* 12 Cursor-Position X LSB */
-	TVPCXPOH = 0x34,	/* 13 Cursor-Position X MSB */
-	TVPCYPOL = 0x38,	/* 14 Cursor-Position Y LSB */
-	TVPCYPOH = 0x3c,	/* 15 Cursor-Position Y MSB */
-};
-
-/* TI TVP 3030 RAMDAC Indirect Registers */
-enum {
-	TVPIRREV = 0x01,	/* Silicon Revision [RO] */
-	TVPIRICC = 0x06,	/* Indirect Cursor Control 	(0x00) */
-	TVPIRBRC = 0x07,	/* Byte Router Control 	(0xe4) */
-	TVPIRLAC = 0x0f,	/* Latch Control 		(0x06) */
-	TVPIRTCC = 0x18,	/* True Color Control  	(0x80) */
-	TVPIRMXC = 0x19,	/* Multiplex Control		(0x98) */
-	TVPIRCLS = 0x1a,	/* Clock Selection		(0x07) */
-	TVPIRPPG = 0x1c,	/* Palette Page		(0x00) */
-	TVPIRGEC = 0x1d,	/* General Control 		(0x00) */
-	TVPIRMIC = 0x1e,	/* Miscellaneous Control	(0x00) */
-	TVPIRPLA = 0x2c,	/* PLL Address */
-	TVPIRPPD = 0x2d,	/* Pixel Clock PLL Data */
-	TVPIRMPD = 0x2e,	/* Memory Clock PLL Data */
-	TVPIRLPD = 0x2f,	/* Loop Clock PLL Data */
-	TVPIRCKL = 0x30,	/* Color-Key Overlay Low */
-	TVPIRCKH = 0x31,	/* Color-Key Overlay High */
-	TVPIRCRL = 0x32,	/* Color-Key Red Low */
-	TVPIRCRH = 0x33,	/* Color-Key Red High */
-	TVPIRCGL = 0x34,	/* Color-Key Green Low */
-	TVPIRCGH = 0x35,	/* Color-Key Green High */
-	TVPIRCBL = 0x36,	/* Color-Key Blue Low */
-	TVPIRCBH = 0x37,	/* Color-Key Blue High */
-	TVPIRCKC = 0x38,	/* Color-Key Control 		(0x00) */
-	TVPIRMLC = 0x39,	/* MCLK/Loop Clock Control	(0x18) */
-	TVPIRSEN = 0x3a,	/* Sense Test			(0x00) */
-	TVPIRTMD = 0x3b,	/* Test Mode Data */
-	TVPIRRML = 0x3c,	/* CRC Remainder LSB [RO] */
-	TVPIRRMM = 0x3d,	/* CRC Remainder MSB [RO] */
-	TVPIRRMS = 0x3e,	/* CRC  Bit Select [WO] */
-	TVPIRDID = 0x3f,	/* Device ID [RO] 		(0x30) */
-	TVPIRRES = 0xff		/* Software Reset [WO] */
-};
-
-struct initvalues {
-	__u8 addr, value;
-};
-
-static struct initvalues ibm_initregs[] = {
-	{ CLKCTL,	0x21 },
-	{ SYNCCTL,	0x00 },
-	{ HSYNCPOS,	0x00 },
-	{ PWRMNGMT,	0x00 },
-	{ DACOP,	0x02 },
-	{ PALETCTL,	0x00 },
-	{ SYSCLKCTL,	0x01 },
-
-	/*
-	 * Note that colors in X are correct only if all video data is
-	 * passed through the palette in the DAC.  That is, "indirect
-	 * color" must be configured.  This is the case for the IBM DAC
-	 * used in the 2MB and 4MB cards, at least.
-	 */
-	{ BPP8,		0x00 },
-	{ BPP16,	0x01 },
-	{ BPP24,	0x00 },
-	{ BPP32,	0x00 },
-
-	{ PIXCTL1,	0x05 },
-	{ PIXCTL2,	0x00 },
-	{ SYSCLKN,	0x08 },
-	{ SYSCLKM,	0x4f },
-	{ SYSCLKP,	0x00 },
-	{ SYSCLKC,	0x00 },
-	{ CURSCTL,	0x00 },
-	{ CURSACCTL,	0x01 },
-	{ CURSACATTR,	0xa8 },
-	{ CURS1R,	0xff },
-	{ CURS1G,	0xff },
-	{ CURS1B,	0xff },
-	{ CURS2R,	0xff },
-	{ CURS2G,	0xff },
-	{ CURS2B,	0xff },
-	{ CURS3R,	0xff },
-	{ CURS3G,	0xff },
-	{ CURS3B,	0xff },
-	{ BORDR,	0xff },
-	{ BORDG,	0xff },
-	{ BORDB,	0xff },
-	{ MISCTL1,	0x01 },
-	{ MISCTL2,	0x45 },
-	{ MISCTL3,	0x00 },
-	{ KEYCTL,	0x00 }
-};
-
-static struct initvalues tvp_initregs[] = {
-	{ TVPIRICC,	0x00 },
-	{ TVPIRBRC,	0xe4 },
-	{ TVPIRLAC,	0x06 },
-	{ TVPIRTCC,	0x80 },
-	{ TVPIRMXC,	0x4d },
-	{ TVPIRCLS,	0x05 },
-	{ TVPIRPPG,	0x00 },
-	{ TVPIRGEC,	0x00 },
-	{ TVPIRMIC,	0x08 },
-	{ TVPIRCKL,	0xff },
-	{ TVPIRCKH,	0xff },
-	{ TVPIRCRL,	0xff },
-	{ TVPIRCRH,	0xff },
-	{ TVPIRCGL,	0xff },
-	{ TVPIRCGH,	0xff },
-	{ TVPIRCBL,	0xff },
-	{ TVPIRCBH,	0xff },
-	{ TVPIRCKC,	0x00 },
-	{ TVPIRPLA,	0x00 },
-	{ TVPIRPPD,	0xc0 },
-	{ TVPIRPPD,	0xd5 },
-	{ TVPIRPPD,	0xea },
-	{ TVPIRPLA,	0x00 },
-	{ TVPIRMPD,	0xb9 },
-	{ TVPIRMPD,	0x3a },
-	{ TVPIRMPD,	0xb1 },
-	{ TVPIRPLA,	0x00 },
-	{ TVPIRLPD,	0xc1 },
-	{ TVPIRLPD,	0x3d },
-	{ TVPIRLPD,	0xf3 },
-};
-
-struct imstt_regvals {
-	__u32 pitch;
-	__u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
-	__u8 pclk_m, pclk_n, pclk_p;
-	/* Values of the tvp which change depending on colormode x resolution */
-	__u8 mlc[3];	/* Memory Loop Config 0x39 */
-	__u8 lckl_p[3];	/* P value of LCKL PLL */
-};
-
-struct imstt_par {
-	struct imstt_regvals init;
-	__u32 __iomem *dc_regs;
-	unsigned long cmap_regs_phys;
-	__u8 *cmap_regs;
-	__u32 ramdac;
-	__u32 palette[16];
-};
- 
-enum {
-	IBM = 0,
-	TVP = 1
-};
-
-#define USE_NV_MODES		1
-#define INIT_BPP		8
-#define INIT_XRES		640
-#define INIT_YRES		480
-
-static int inverse = 0;
-static char fontname[40] __initdata = { 0 };
-#if defined(CONFIG_PPC)
-static signed char init_vmode = -1, init_cmode = -1;
-#endif
-
-static struct imstt_regvals tvp_reg_init_2 = {
-	512,
-	0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
-	0xec, 0x2a, 0xf3,
-	{ 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
-};
-
-static struct imstt_regvals tvp_reg_init_6 = {
-	640,
-	0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
-	0xef, 0x2e, 0xb2,
-	{ 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
-};
-
-static struct imstt_regvals tvp_reg_init_12 = {
-	800,
-	0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
-	0xf6, 0x2e, 0xf2,
-	{ 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
-};
-
-static struct imstt_regvals tvp_reg_init_13 = {
-	832,
-	0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
-	0xfe, 0x3e, 0xf1,
-	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
-};
-
-static struct imstt_regvals tvp_reg_init_17 = {
-	1024,
-	0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
-	0xfc, 0x3a, 0xf1,
-	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
-};
-
-static struct imstt_regvals tvp_reg_init_18 = {
-	1152,
-  	0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 
-	0xfd, 0x3a, 0xf1,
-	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
-};
-
-static struct imstt_regvals tvp_reg_init_19 = {
-	1280,
-	0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
-	0xf7, 0x36, 0xf0,
-	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
-};
-
-static struct imstt_regvals tvp_reg_init_20 = {
-	1280,
-	0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
-	0xf0, 0x2d, 0xf0,
-	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
-};
-
-/*
- * PCI driver prototypes
- */
-static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void imsttfb_remove(struct pci_dev *pdev);
-
-/*
- * Register access
- */
-static inline u32 read_reg_le32(volatile u32 __iomem *base, int regindex)
-{
-#ifdef __powerpc__
-	return in_le32(base + regindex);
-#else
-	return readl(base + regindex);
-#endif
-}
-
-static inline void write_reg_le32(volatile u32 __iomem *base, int regindex, u32 val)
-{
-#ifdef __powerpc__
-	out_le32(base + regindex, val);
-#else
-	writel(val, base + regindex);
-#endif
-}
-
-static __u32
-getclkMHz(struct imstt_par *par)
-{
-	__u32 clk_m, clk_n, clk_p;
-
-	clk_m = par->init.pclk_m;
-	clk_n = par->init.pclk_n;
-	clk_p = par->init.pclk_p;
-
-	return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
-}
-
-static void
-setclkMHz(struct imstt_par *par, __u32 MHz)
-{
-	__u32 clk_m, clk_n, x, stage, spilled;
-
-	clk_m = clk_n = 0;
-	stage = spilled = 0;
-	for (;;) {
-		switch (stage) {
-			case 0:
-				clk_m++;
-				break;
-			case 1:
-				clk_n++;
-				break;
-		}
-		x = 20 * (clk_m + 1) / (clk_n + 1);
-		if (x == MHz)
-			break;
-		if (x > MHz) {
-			spilled = 1;
-			stage = 1;
-		} else if (spilled && x < MHz) {
-			stage = 0;
-		}
-	}
-
-	par->init.pclk_m = clk_m;
-	par->init.pclk_n = clk_n;
-	par->init.pclk_p = 0;
-}
-
-static struct imstt_regvals *
-compute_imstt_regvals_ibm(struct imstt_par *par, int xres, int yres)
-{
-	struct imstt_regvals *init = &par->init;
-	__u32 MHz, hes, heb, veb, htp, vtp;
-
-	switch (xres) {
-		case 640:
-			hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2;
-			MHz = 30 /* .25 */ ;
-			break;
-		case 832:
-			hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3;
-			MHz = 57 /* .27_ */ ;
-			break;
-		case 1024:
-			hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3;
-			MHz = 80;
-			break;
-		case 1152:
-			hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3;
-			MHz = 101 /* .6_ */ ;
-			break;
-		case 1280:
-			hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1;
-			MHz = yres == 960 ? 126 : 135;
-			break;
-		case 1600:
-			hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3;
-			MHz = 200;
-			break;
-		default:
-			return NULL;
-	}
-
-	setclkMHz(par, MHz);
-
-	init->hes = hes;
-	init->heb = heb;
-	init->hsb = init->heb + (xres >> 3);
-	init->ht = init->hsb + htp;
-	init->ves = 0x0003;
-	init->veb = veb;
-	init->vsb = init->veb + yres;
-	init->vt = init->vsb + vtp;
-	init->vil = init->vsb;
-
-	init->pitch = xres;
-	return init;
-}
-
-static struct imstt_regvals *
-compute_imstt_regvals_tvp(struct imstt_par *par, int xres, int yres)
-{
-	struct imstt_regvals *init;
-
-	switch (xres) {
-		case 512:
-			init = &tvp_reg_init_2;
-			break;
-		case 640:
-			init = &tvp_reg_init_6;
-			break;
-		case 800:
-			init = &tvp_reg_init_12;
-			break;
-		case 832:
-			init = &tvp_reg_init_13;
-			break;
-		case 1024:
-			init = &tvp_reg_init_17;
-			break;
-		case 1152:
-			init = &tvp_reg_init_18;
-			break;
-		case 1280:
-			init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
-			break;
-		default:
-			return NULL;
-	}
-	par->init = *init;
-	return init;
-}
-
-static struct imstt_regvals *
-compute_imstt_regvals (struct imstt_par *par, u_int xres, u_int yres)
-{
-	if (par->ramdac == IBM)
-		return compute_imstt_regvals_ibm(par, xres, yres);
-	else
-		return compute_imstt_regvals_tvp(par, xres, yres);
-}
-
-static void
-set_imstt_regvals_ibm (struct imstt_par *par, u_int bpp)
-{
-	struct imstt_regvals *init = &par->init;
-	__u8 pformat = (bpp >> 3) + 2;
-
-	par->cmap_regs[PIDXHI] = 0;		eieio();
-	par->cmap_regs[PIDXLO] = PIXM0;		eieio();
-	par->cmap_regs[PIDXDATA] = init->pclk_m;eieio();
-	par->cmap_regs[PIDXLO] = PIXN0;		eieio();
-	par->cmap_regs[PIDXDATA] = init->pclk_n;eieio();
-	par->cmap_regs[PIDXLO] = PIXP0;		eieio();
-	par->cmap_regs[PIDXDATA] = init->pclk_p;eieio();
-	par->cmap_regs[PIDXLO] = PIXC0;		eieio();
-	par->cmap_regs[PIDXDATA] = 0x02;	eieio();
-
-	par->cmap_regs[PIDXLO] = PIXFMT;	eieio();
-	par->cmap_regs[PIDXDATA] = pformat;	eieio();
-}
-
-static void
-set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp)
-{
-	struct imstt_regvals *init = &par->init;
-	__u8 tcc, mxc, lckl_n, mic;
-	__u8 mlc, lckl_p;
-
-	switch (bpp) {
-		default:
-		case 8:
-			tcc = 0x80;
-			mxc = 0x4d;
-			lckl_n = 0xc1;
-			mlc = init->mlc[0];
-			lckl_p = init->lckl_p[0];
-			break;
-		case 16:
-			tcc = 0x44;
-			mxc = 0x55;
-			lckl_n = 0xe1;
-			mlc = init->mlc[1];
-			lckl_p = init->lckl_p[1];
-			break;
-		case 24:
-			tcc = 0x5e;
-			mxc = 0x5d;
-			lckl_n = 0xf1;
-			mlc = init->mlc[2];
-			lckl_p = init->lckl_p[2];
-			break;
-		case 32:
-			tcc = 0x46;
-			mxc = 0x5d;
-			lckl_n = 0xf1;
-			mlc = init->mlc[2];
-			lckl_p = init->lckl_p[2];
-			break;
-	}
-	mic = 0x08;
-
-	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
-	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
-	par->cmap_regs[TVPIDATA] = init->pclk_m;	eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
-	par->cmap_regs[TVPIDATA] = init->pclk_n;	eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();
-	par->cmap_regs[TVPIDATA] = init->pclk_p;	eieio();
-
-	par->cmap_regs[TVPADDRW] = TVPIRTCC;		eieio();
-	par->cmap_regs[TVPIDATA] = tcc;			eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRMXC;		eieio();
-	par->cmap_regs[TVPIDATA] = mxc;			eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRMIC;		eieio();
-	par->cmap_regs[TVPIDATA] = mic;			eieio();
-
-	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
-	par->cmap_regs[TVPIDATA] = 0x00;		eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
-	par->cmap_regs[TVPIDATA] = lckl_n;		eieio();
-
-	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
-	par->cmap_regs[TVPIDATA] = 0x15;		eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRMLC;		eieio();
-	par->cmap_regs[TVPIDATA] = mlc;			eieio();
-
-	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();
-	par->cmap_regs[TVPIDATA] = 0x2a;		eieio();
-	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();
-	par->cmap_regs[TVPIDATA] = lckl_p;		eieio();
-}
-
-static void
-set_imstt_regvals (struct fb_info *info, u_int bpp)
-{
-	struct imstt_par *par = info->par;
-	struct imstt_regvals *init = &par->init;
-	__u32 ctl, pitch, byteswap, scr;
-
-	if (par->ramdac == IBM)
-		set_imstt_regvals_ibm(par, bpp);
-	else
-		set_imstt_regvals_tvp(par, bpp);
-
-  /*
-   * From what I (jsk) can gather poking around with MacsBug,
-   * bits 8 and 9 in the SCR register control endianness
-   * correction (byte swapping).  These bits must be set according
-   * to the color depth as follows:
-   *     Color depth    Bit 9   Bit 8
-   *     ==========     =====   =====
-   *        8bpp          0       0
-   *       16bpp          0       1
-   *       32bpp          1       1
-   */
-	switch (bpp) {
-		default:
-		case 8:
-			ctl = 0x17b1;
-			pitch = init->pitch >> 2;
-			byteswap = 0x000;
-			break;
-		case 16:
-			ctl = 0x17b3;
-			pitch = init->pitch >> 1;
-			byteswap = 0x100;
-			break;
-		case 24:
-			ctl = 0x17b9;
-			pitch = init->pitch - (init->pitch >> 2);
-			byteswap = 0x200;
-			break;
-		case 32:
-			ctl = 0x17b5;
-			pitch = init->pitch;
-			byteswap = 0x300;
-			break;
-	}
-	if (par->ramdac == TVP)
-		ctl -= 0x30;
-
-	write_reg_le32(par->dc_regs, HES, init->hes);
-	write_reg_le32(par->dc_regs, HEB, init->heb);
-	write_reg_le32(par->dc_regs, HSB, init->hsb);
-	write_reg_le32(par->dc_regs, HT, init->ht);
-	write_reg_le32(par->dc_regs, VES, init->ves);
-	write_reg_le32(par->dc_regs, VEB, init->veb);
-	write_reg_le32(par->dc_regs, VSB, init->vsb);
-	write_reg_le32(par->dc_regs, VT, init->vt);
-	write_reg_le32(par->dc_regs, VIL, init->vil);
-	write_reg_le32(par->dc_regs, HCIV, 1);
-	write_reg_le32(par->dc_regs, VCIV, 1);
-	write_reg_le32(par->dc_regs, TCDR, 4);
-	write_reg_le32(par->dc_regs, RRCIV, 1);
-	write_reg_le32(par->dc_regs, RRSC, 0x980);
-	write_reg_le32(par->dc_regs, RRCR, 0x11);
-
-	if (par->ramdac == IBM) {
-		write_reg_le32(par->dc_regs, HRIR, 0x0100);
-		write_reg_le32(par->dc_regs, CMR, 0x00ff);
-		write_reg_le32(par->dc_regs, SRGCTL, 0x0073);
-	} else {
-		write_reg_le32(par->dc_regs, HRIR, 0x0200);
-		write_reg_le32(par->dc_regs, CMR, 0x01ff);
-		write_reg_le32(par->dc_regs, SRGCTL, 0x0003);
-	}
-
-	switch (info->fix.smem_len) {
-		case 0x200000:
-			scr = 0x059d | byteswap;
-			break;
-		/* case 0x400000:
-		   case 0x800000: */
-		default:
-			pitch >>= 1;
-			scr = 0x150dd | byteswap;
-			break;
-	}
-
-	write_reg_le32(par->dc_regs, SCR, scr);
-	write_reg_le32(par->dc_regs, SPR, pitch);
-	write_reg_le32(par->dc_regs, STGCTL, ctl);
-}
-
-static inline void
-set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct imstt_par *par = info->par;
-	__u32 off = var->yoffset * (info->fix.line_length >> 3)
-		    + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
-	write_reg_le32(par->dc_regs, SSR, off);
-}
-
-static inline void
-set_555 (struct imstt_par *par)
-{
-	if (par->ramdac == IBM) {
-		par->cmap_regs[PIDXHI] = 0;		eieio();
-		par->cmap_regs[PIDXLO] = BPP16;		eieio();
-		par->cmap_regs[PIDXDATA] = 0x01;	eieio();
-	} else {
-		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
-		par->cmap_regs[TVPIDATA] = 0x44;	eieio();
-	}
-}
-
-static inline void
-set_565 (struct imstt_par *par)
-{
-	if (par->ramdac == IBM) {
-		par->cmap_regs[PIDXHI] = 0;		eieio();
-		par->cmap_regs[PIDXLO] = BPP16;		eieio();
-		par->cmap_regs[PIDXDATA] = 0x03;	eieio();
-	} else {
-		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
-		par->cmap_regs[TVPIDATA] = 0x45;	eieio();
-	}
-}
-
-static int
-imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16
-	    && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)
-	    || var->xres_virtual < var->xres || var->yres_virtual < var->yres
-	    || var->nonstd
-	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > info->fix.smem_len
-	    || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > info->fix.smem_len)
-		return -EINVAL;
-
-	switch (var->bits_per_pixel) {
-		case 8:
-			var->red.offset = 0;
-			var->red.length = 8;
-			var->green.offset = 0;
-			var->green.length = 8;
-			var->blue.offset = 0;
-			var->blue.length = 8;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-			break;
-		case 16:	/* RGB 555 or 565 */
-			if (var->green.length != 6)
-				var->red.offset = 10;
-			var->red.length = 5;
-			var->green.offset = 5;
-			if (var->green.length != 6)
-				var->green.length = 5;
-			var->blue.offset = 0;
-			var->blue.length = 5;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-			break;
-		case 24:	/* RGB 888 */
-			var->red.offset = 16;
-			var->red.length = 8;
-			var->green.offset = 8;
-			var->green.length = 8;
-			var->blue.offset = 0;
-			var->blue.length = 8;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-			break;
-		case 32:	/* RGBA 8888 */
-			var->red.offset = 16;
-			var->red.length = 8;
-			var->green.offset = 8;
-			var->green.length = 8;
-			var->blue.offset = 0;
-			var->blue.length = 8;
-			var->transp.offset = 24;
-			var->transp.length = 8;
-			break;
-	}
-
-	if (var->yres == var->yres_virtual) {
-		__u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));
-		var->yres_virtual = ((vram << 3) / var->bits_per_pixel) / var->xres_virtual;
-		if (var->yres_virtual < var->yres)
-			var->yres_virtual = var->yres;
-	}
-
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-	var->height = -1;
-	var->width = -1;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	var->left_margin = var->right_margin = 16;
-	var->upper_margin = var->lower_margin = 16;
-	var->hsync_len = var->vsync_len = 8;
-	return 0;
-}
-
-static int
-imsttfb_set_par(struct fb_info *info) 
-{
-	struct imstt_par *par = info->par;
-		
-	if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
-		return -EINVAL;
-
-	if (info->var.green.length == 6)
-		set_565(par);
-	else
-		set_555(par);
-	set_imstt_regvals(info, info->var.bits_per_pixel);
-	info->var.pixclock = 1000000 / getclkMHz(par);
-	return 0;
-}
-
-static int
-imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
-		   u_int transp, struct fb_info *info)
-{
-	struct imstt_par *par = info->par;
-	u_int bpp = info->var.bits_per_pixel;
-
-	if (regno > 255)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
-	if (0 && bpp == 16)	/* screws up X */
-		par->cmap_regs[PADDRW] = regno << 3;
-	else
-		par->cmap_regs[PADDRW] = regno;
-	eieio();
-
-	par->cmap_regs[PDATA] = red;	eieio();
-	par->cmap_regs[PDATA] = green;	eieio();
-	par->cmap_regs[PDATA] = blue;	eieio();
-
-	if (regno < 16)
-		switch (bpp) {
-			case 16:
-				par->palette[regno] =
-					(regno << (info->var.green.length ==
-					5 ? 10 : 11)) | (regno << 5) | regno;
-				break;
-			case 24:
-				par->palette[regno] =
-					(regno << 16) | (regno << 8) | regno;
-				break;
-			case 32: {
-				int i = (regno << 8) | regno;
-				par->palette[regno] = (i << 16) |i;
-				break;
-			}
-		}
-	return 0;
-}
-
-static int
-imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->xoffset + info->var.xres > info->var.xres_virtual
-	    || var->yoffset + info->var.yres > info->var.yres_virtual)
-		return -EINVAL;
-
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-	set_offset(var, info);
-	return 0;
-}
-
-static int 
-imsttfb_blank(int blank, struct fb_info *info)
-{
-	struct imstt_par *par = info->par;
-	__u32 ctrl;
-
-	ctrl = read_reg_le32(par->dc_regs, STGCTL);
-	if (blank > 0) {
-		switch (blank) {
-		case FB_BLANK_NORMAL:
-		case FB_BLANK_POWERDOWN:
-			ctrl &= ~0x00000380;
-			if (par->ramdac == IBM) {
-				par->cmap_regs[PIDXHI] = 0;		eieio();
-				par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
-				par->cmap_regs[PIDXDATA] = 0x55;	eieio();
-				par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
-				par->cmap_regs[PIDXDATA] = 0x11;	eieio();
-				par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
-				par->cmap_regs[PIDXDATA] = 0x0f;	eieio();
-				par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
-				par->cmap_regs[PIDXDATA] = 0x1f;	eieio();
-				par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
-				par->cmap_regs[PIDXDATA] = 0xc0;
-			}
-			break;
-		case FB_BLANK_VSYNC_SUSPEND:
-			ctrl &= ~0x00000020;
-			break;
-		case FB_BLANK_HSYNC_SUSPEND:
-			ctrl &= ~0x00000010;
-			break;
-		}
-	} else {
-		if (par->ramdac == IBM) {
-			ctrl |= 0x000017b0;
-			par->cmap_regs[PIDXHI] = 0;		eieio();
-			par->cmap_regs[PIDXLO] = CLKCTL;	eieio();
-			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
-			par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();
-			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
-			par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();
-			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
-			par->cmap_regs[PIDXLO] = MISCTL1;	eieio();
-			par->cmap_regs[PIDXDATA] = 0x01;	eieio();
-			par->cmap_regs[PIDXLO] = MISCTL2;	eieio();
-			par->cmap_regs[PIDXDATA] = 0x45;	eieio();
-		} else
-			ctrl |= 0x00001780;
-	}
-	write_reg_le32(par->dc_regs, STGCTL, ctrl);
-	return 0;
-}
-
-static void
-imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{ 
-	struct imstt_par *par = info->par;
-	__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
-
-	bgc = rect->color;
-	bgc |= (bgc << 8);
-	bgc |= (bgc << 16);
-
-	Bpp = info->var.bits_per_pixel >> 3,
-	line_pitch = info->fix.line_length;
-
-	dy = rect->dy * line_pitch;
-	dx = rect->dx * Bpp;
-	height = rect->height;
-	height--;
-	width = rect->width * Bpp;
-	width--;
-
-	if (rect->rop == ROP_COPY) {
-		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
-		write_reg_le32(par->dc_regs, DSA, dy + dx);
-		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
-		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
-		write_reg_le32(par->dc_regs, BI, 0xffffffff);
-		write_reg_le32(par->dc_regs, MBC, 0xffffffff);
-		write_reg_le32(par->dc_regs, CLR, bgc);
-		write_reg_le32(par->dc_regs, BLTCTL, 0x840); /* 0x200000 */
-		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
-		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
-	} else {
-		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
-		write_reg_le32(par->dc_regs, DSA, dy + dx);
-		write_reg_le32(par->dc_regs, S1SA, dy + dx);
-		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);
-		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);
-		write_reg_le32(par->dc_regs, SP, line_pitch);
-		write_reg_le32(par->dc_regs, BLTCTL, 0x40005);
-		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
-		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
-	}
-}
-
-static void
-imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct imstt_par *par = info->par;
-	__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
- 	__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
-
-	Bpp = info->var.bits_per_pixel >> 3,
-
-	sx = area->sx * Bpp;
-	sy = area->sy;
-	dx = area->dx * Bpp;
-	dy = area->dy;
-	height = area->height;
-	height--;
-	width = area->width * Bpp;
-	width--;
-
-	line_pitch = info->fix.line_length;
-	bltctl = 0x05;
-	sp = line_pitch << 16;
-	cnt = height << 16;
-
-	if (sy < dy) {
-		sy += height;
-		dy += height;
-		sp |= -(line_pitch) & 0xffff;
-		dp_octl = -(line_pitch) & 0xffff;
-	} else {
-		sp |= line_pitch;
-		dp_octl = line_pitch;
-	}
-	if (sx < dx) {
-		sx += width;
-		dx += width;
-		bltctl |= 0x80;
-		cnt |= -(width) & 0xffff;
-	} else {
-		cnt |= width;
-	}
-	fb_offset_old = sy * line_pitch + sx;
-	fb_offset_new = dy * line_pitch + dx;
-
-	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
-	write_reg_le32(par->dc_regs, S1SA, fb_offset_old);
-	write_reg_le32(par->dc_regs, SP, sp);
-	write_reg_le32(par->dc_regs, DSA, fb_offset_new);
-	write_reg_le32(par->dc_regs, CNT, cnt);
-	write_reg_le32(par->dc_regs, DP_OCTL, dp_octl);
-	write_reg_le32(par->dc_regs, BLTCTL, bltctl);
-	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);
-	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);
-}
-
-#if 0
-static int
-imsttfb_load_cursor_image(struct imstt_par *par, int width, int height, __u8 fgc)
-{
-	u_int x, y;
-
-	if (width > 32 || height > 32)
-		return -EINVAL;
-
-	if (par->ramdac == IBM) {
-		par->cmap_regs[PIDXHI] = 1;	eieio();
-		for (x = 0; x < 0x100; x++) {
-			par->cmap_regs[PIDXLO] = x;		eieio();
-			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
-		}
-		par->cmap_regs[PIDXHI] = 1;	eieio();
-		for (y = 0; y < height; y++)
-			for (x = 0; x < width >> 2; x++) {
-				par->cmap_regs[PIDXLO] = x + y * 8;	eieio();
-				par->cmap_regs[PIDXDATA] = 0xff;	eieio();
-			}
-		par->cmap_regs[PIDXHI] = 0;		eieio();
-		par->cmap_regs[PIDXLO] = CURS1R;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS1G;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS1B;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS2R;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS2G;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS2B;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS3R;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS3G;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-		par->cmap_regs[PIDXLO] = CURS3B;	eieio();
-		par->cmap_regs[PIDXDATA] = fgc;		eieio();
-	} else {
-		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
-		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
-		par->cmap_regs[TVPADDRW] = 0;		eieio();
-		for (x = 0; x < 0x200; x++) {
-			par->cmap_regs[TVPCRDAT] = 0x00;	eieio();
-		}
-		for (x = 0; x < 0x200; x++) {
-			par->cmap_regs[TVPCRDAT] = 0xff;	eieio();
-		}
-		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
-		par->cmap_regs[TVPIDATA] &= 0x03;	eieio();
-		for (y = 0; y < height; y++)
-			for (x = 0; x < width >> 3; x++) {
-				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
-				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
-			}
-		par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
-		par->cmap_regs[TVPIDATA] |= 0x08;	eieio();
-		for (y = 0; y < height; y++)
-			for (x = 0; x < width >> 3; x++) {
-				par->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
-				par->cmap_regs[TVPCRDAT] = 0xff;		eieio();
-			}
-		par->cmap_regs[TVPCADRW] = 0x00;	eieio();
-		for (x = 0; x < 12; x++) {
-			par->cmap_regs[TVPCDATA] = fgc;
-			eieio();
-		}
-	}
-	return 1;
-}
-
-static void
-imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
-{
-	if (par->ramdac == IBM) {
-		par->cmap_regs[PIDXHI] = 0;	eieio();
-		if (!on) {
-			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
-			par->cmap_regs[PIDXDATA] = 0x00;	eieio();
-		} else {
-			par->cmap_regs[PIDXLO] = CURSXHI;	eieio();
-			par->cmap_regs[PIDXDATA] = d->dx >> 8;	eieio();
-			par->cmap_regs[PIDXLO] = CURSXLO;	eieio();
-			par->cmap_regs[PIDXDATA] = d->dx & 0xff;eieio();
-			par->cmap_regs[PIDXLO] = CURSYHI;	eieio();
-			par->cmap_regs[PIDXDATA] = d->dy >> 8;	eieio();
-			par->cmap_regs[PIDXLO] = CURSYLO;	eieio();
-			par->cmap_regs[PIDXDATA] = d->dy & 0xff;eieio();
-			par->cmap_regs[PIDXLO] = CURSCTL;	eieio();
-			par->cmap_regs[PIDXDATA] = 0x02;	eieio();
-		}
-	} else {
-		if (!on) {
-			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
-			par->cmap_regs[TVPIDATA] = 0x00;	eieio();
-		} else {
-			__u16 x = d->dx + 0x40, y = d->dy + 0x40;
-
-			par->cmap_regs[TVPCXPOH] = x >> 8;	eieio();
-			par->cmap_regs[TVPCXPOL] = x & 0xff;	eieio();
-			par->cmap_regs[TVPCYPOH] = y >> 8;	eieio();
-			par->cmap_regs[TVPCYPOL] = y & 0xff;	eieio();
-			par->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
-			par->cmap_regs[TVPIDATA] = 0x02;	eieio();
-		}
-	}
-}
-
-static int 
-imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct imstt_par *par = info->par;
-        u32 flags = cursor->set, fg, bg, xx, yy;
-
-	if (cursor->dest == NULL && cursor->rop == ROP_XOR)
-		return 1;
-	
-	imstt_set_cursor(info, cursor, 0);
-
-	if (flags & FB_CUR_SETPOS) {
-		xx = cursor->image.dx - info->var.xoffset;
-		yy = cursor->image.dy - info->var.yoffset;
-	}
-
-	if (flags & FB_CUR_SETSIZE) {
-        }
-
-        if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
-                int fg_idx = cursor->image.fg_color;
-                int width = (cursor->image.width+7)/8;
-                u8 *dat = (u8 *) cursor->image.data;
-                u8 *dst = (u8 *) cursor->dest;
-                u8 *msk = (u8 *) cursor->mask;
-
-                switch (cursor->rop) {
-                case ROP_XOR:
-                        for (i = 0; i < cursor->image.height; i++) {
-                                for (j = 0; j < width; j++) {
-                                        d_idx = i * MAX_CURS/8  + j;
-                                        data[d_idx] =  byte_rev[dat[s_idx] ^
-                                                                dst[s_idx]];
-                                        mask[d_idx] = byte_rev[msk[s_idx]];
-                                        s_idx++;
-                                }
-                        }
-                        break;
-                case ROP_COPY:
-                default:
-                        for (i = 0; i < cursor->image.height; i++) {
-                                for (j = 0; j < width; j++) {
-                                        d_idx = i * MAX_CURS/8 + j;
-                                        data[d_idx] = byte_rev[dat[s_idx]];
-                                        mask[d_idx] = byte_rev[msk[s_idx]];
-                                        s_idx++;
-                                }
-			}
-			break;
-		}
-
-		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
-                     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
-                     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
-
-		imsttfb_load_cursor_image(par, xx, yy, fgc);
-	}
-	if (cursor->enable)
-		imstt_set_cursor(info, cursor, 1);
-	return 0;
-}
-#endif
-
-#define FBIMSTT_SETREG		0x545401
-#define FBIMSTT_GETREG		0x545402
-#define FBIMSTT_SETCMAPREG	0x545403
-#define FBIMSTT_GETCMAPREG	0x545404
-#define FBIMSTT_SETIDXREG	0x545405
-#define FBIMSTT_GETIDXREG	0x545406
-
-static int
-imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
-{
-	struct imstt_par *par = info->par;
-	void __user *argp = (void __user *)arg;
-	__u32 reg[2];
-	__u8 idx[2];
-
-	switch (cmd) {
-		case FBIMSTT_SETREG:
-			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
-				return -EFAULT;
-			write_reg_le32(par->dc_regs, reg[0], reg[1]);
-			return 0;
-		case FBIMSTT_GETREG:
-			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
-				return -EFAULT;
-			reg[1] = read_reg_le32(par->dc_regs, reg[0]);
-			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
-				return -EFAULT;
-			return 0;
-		case FBIMSTT_SETCMAPREG:
-			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
-				return -EFAULT;
-			write_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0], reg[1]);
-			return 0;
-		case FBIMSTT_GETCMAPREG:
-			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
-				return -EFAULT;
-			reg[1] = read_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0]);
-			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
-				return -EFAULT;
-			return 0;
-		case FBIMSTT_SETIDXREG:
-			if (copy_from_user(idx, argp, 2))
-				return -EFAULT;
-			par->cmap_regs[PIDXHI] = 0;		eieio();
-			par->cmap_regs[PIDXLO] = idx[0];	eieio();
-			par->cmap_regs[PIDXDATA] = idx[1];	eieio();
-			return 0;
-		case FBIMSTT_GETIDXREG:
-			if (copy_from_user(idx, argp, 1))
-				return -EFAULT;
-			par->cmap_regs[PIDXHI] = 0;		eieio();
-			par->cmap_regs[PIDXLO] = idx[0];	eieio();
-			idx[1] = par->cmap_regs[PIDXDATA];
-			if (copy_to_user((void __user *)(arg + 1), &idx[1], 1))
-				return -EFAULT;
-			return 0;
-		default:
-			return -ENOIOCTLCMD;
-	}
-}
-
-static struct pci_device_id imsttfb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT128,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, IBM },
-	{ PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT3D,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TVP },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, imsttfb_pci_tbl);
-
-static struct pci_driver imsttfb_pci_driver = {
-	.name =		"imsttfb",
-	.id_table =	imsttfb_pci_tbl,
-	.probe =	imsttfb_probe,
-	.remove =	imsttfb_remove,
-};
-
-static struct fb_ops imsttfb_ops = {
-	.owner 		= THIS_MODULE,
-	.fb_check_var	= imsttfb_check_var,
-	.fb_set_par 	= imsttfb_set_par,
-	.fb_setcolreg 	= imsttfb_setcolreg,
-	.fb_pan_display = imsttfb_pan_display,
-	.fb_blank 	= imsttfb_blank,
-	.fb_fillrect	= imsttfb_fillrect,
-	.fb_copyarea	= imsttfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_ioctl 	= imsttfb_ioctl,
-};
-
-static void init_imstt(struct fb_info *info)
-{
-	struct imstt_par *par = info->par;
-	__u32 i, tmp, *ip, *end;
-
-	tmp = read_reg_le32(par->dc_regs, PRC);
-	if (par->ramdac == IBM)
-		info->fix.smem_len = (tmp & 0x0004) ? 0x400000 : 0x200000;
-	else
-		info->fix.smem_len = 0x800000;
-
-	ip = (__u32 *)info->screen_base;
-	end = (__u32 *)(info->screen_base + info->fix.smem_len);
-	while (ip < end)
-		*ip++ = 0;
-
-	/* initialize the card */
-	tmp = read_reg_le32(par->dc_regs, STGCTL);
-	write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
-	write_reg_le32(par->dc_regs, SSR, 0);
-
-	/* set default values for DAC registers */
-	if (par->ramdac == IBM) {
-		par->cmap_regs[PPMASK] = 0xff;
-		eieio();
-		par->cmap_regs[PIDXHI] = 0;
-		eieio();
-		for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) {
-			par->cmap_regs[PIDXLO] = ibm_initregs[i].addr;
-			eieio();
-			par->cmap_regs[PIDXDATA] = ibm_initregs[i].value;
-			eieio();
-		}
-	} else {
-		for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) {
-			par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;
-			eieio();
-			par->cmap_regs[TVPIDATA] = tvp_initregs[i].value;
-			eieio();
-		}
-	}
-
-#if USE_NV_MODES && defined(CONFIG_PPC32)
-	{
-		int vmode = init_vmode, cmode = init_cmode;
-
-		if (vmode == -1) {
-			vmode = nvram_read_byte(NV_VMODE);
-			if (vmode <= 0 || vmode > VMODE_MAX)
-				vmode = VMODE_640_480_67;
-		}
-		if (cmode == -1) {
-			cmode = nvram_read_byte(NV_CMODE);
-			if (cmode < CMODE_8 || cmode > CMODE_32)
-				cmode = CMODE_8;
-		}
-		if (mac_vmode_to_var(vmode, cmode, &info->var)) {
-			info->var.xres = info->var.xres_virtual = INIT_XRES;
-			info->var.yres = info->var.yres_virtual = INIT_YRES;
-			info->var.bits_per_pixel = INIT_BPP;
-		}
-	}
-#else
-	info->var.xres = info->var.xres_virtual = INIT_XRES;
-	info->var.yres = info->var.yres_virtual = INIT_YRES;
-	info->var.bits_per_pixel = INIT_BPP;
-#endif
-
-	if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
-	    || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
-		printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
-		framebuffer_release(info);
-		return;
-	}
-
-	sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP");
-	info->fix.mmio_len = 0x1000;
-	info->fix.accel = FB_ACCEL_IMS_TWINTURBO;
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = info->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
-							: FB_VISUAL_DIRECTCOLOR;
-	info->fix.line_length = info->var.xres * (info->var.bits_per_pixel >> 3);
-	info->fix.xpanstep = 8;
-	info->fix.ypanstep = 1;
-	info->fix.ywrapstep = 0;
-
-	info->var.accel_flags = FB_ACCELF_TEXT;
-
-//	if (par->ramdac == IBM)
-//		imstt_cursor_init(info);
-	if (info->var.green.length == 6)
-		set_565(par);
-	else
-		set_555(par);
-	set_imstt_regvals(info, info->var.bits_per_pixel);
-
-	info->var.pixclock = 1000000 / getclkMHz(par);
-
-	info->fbops = &imsttfb_ops;
-	info->flags = FBINFO_DEFAULT |
-                      FBINFO_HWACCEL_COPYAREA |
-	              FBINFO_HWACCEL_FILLRECT |
-	              FBINFO_HWACCEL_YPAN;
-
-	fb_alloc_cmap(&info->cmap, 0, 0);
-
-	if (register_framebuffer(info) < 0) {
-		framebuffer_release(info);
-		return;
-	}
-
-	tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8;
-	fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n",
-		info->fix.id, info->fix.smem_len >> 20, tmp);
-}
-
-static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	unsigned long addr, size;
-	struct imstt_par *par;
-	struct fb_info *info;
-#ifdef CONFIG_PPC_OF
-	struct device_node *dp;
-	
-	dp = pci_device_to_OF_node(pdev);
-	if(dp)
-		printk(KERN_INFO "%s: OF name %s\n",__func__, dp->name);
-	else
-		printk(KERN_ERR "imsttfb: no OF node for pci device\n");
-#endif /* CONFIG_PPC_OF */
-
-	info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
-
-	if (!info) {
-		printk(KERN_ERR "imsttfb: Can't allocate memory\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-
-	addr = pci_resource_start (pdev, 0);
-	size = pci_resource_len (pdev, 0);
-
-	if (!request_mem_region(addr, size, "imsttfb")) {
-		printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
-		framebuffer_release(info);
-		return -ENODEV;
-	}
-
-	switch (pdev->device) {
-		case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */
-			par->ramdac = IBM;
-#ifdef CONFIG_PPC_OF
-			if (dp && ((strcmp(dp->name, "IMS,tt128mb8") == 0) ||
-				   (strcmp(dp->name, "IMS,tt128mb8A") == 0)))
-				par->ramdac = TVP;
-#endif /* CONFIG_PPC_OF */
-			break;
-		case PCI_DEVICE_ID_IMS_TT3D:  /* IMS,tt3d */
-			par->ramdac = TVP;
-			break;
-		default:
-			printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
-					 "contact maintainer.\n", pdev->device);
-			release_mem_region(addr, size);
-			framebuffer_release(info);
-			return -ENODEV;
-	}
-
-	info->fix.smem_start = addr;
-	info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
-					    0x400000 : 0x800000);
-	info->fix.mmio_start = addr + 0x800000;
-	par->dc_regs = ioremap(addr + 0x800000, 0x1000);
-	par->cmap_regs_phys = addr + 0x840000;
-	par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
-	info->pseudo_palette = par->palette;
-	init_imstt(info);
-
-	pci_set_drvdata(pdev, info);
-	return 0;
-}
-
-static void imsttfb_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct imstt_par *par = info->par;
-	int size = pci_resource_len(pdev, 0);
-
-	unregister_framebuffer(info);
-	iounmap(par->cmap_regs);
-	iounmap(par->dc_regs);
-	iounmap(info->screen_base);
-	release_mem_region(info->fix.smem_start, size);
-	framebuffer_release(info);
-}
-
-#ifndef MODULE
-static int __init
-imsttfb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "font:", 5)) {
-			char *p;
-			int i;
-
-			p = this_opt + 5;
-			for (i = 0; i < sizeof(fontname) - 1; i++)
-				if (!*p || *p == ' ' || *p == ',')
-					break;
-			memcpy(fontname, this_opt + 5, i);
-			fontname[i] = 0;
-		} else if (!strncmp(this_opt, "inverse", 7)) {
-			inverse = 1;
-			fb_invert_cmaps();
-		}
-#if defined(CONFIG_PPC)
-		else if (!strncmp(this_opt, "vmode:", 6)) {
-			int vmode = simple_strtoul(this_opt+6, NULL, 0);
-			if (vmode > 0 && vmode <= VMODE_MAX)
-				init_vmode = vmode;
-		} else if (!strncmp(this_opt, "cmode:", 6)) {
-			int cmode = simple_strtoul(this_opt+6, NULL, 0);
-			switch (cmode) {
-				case CMODE_8:
-				case 8:
-					init_cmode = CMODE_8;
-					break;
-				case CMODE_16:
-				case 15:
-				case 16:
-					init_cmode = CMODE_16;
-					break;
-				case CMODE_32:
-				case 24:
-				case 32:
-					init_cmode = CMODE_32;
-					break;
-			}
-		}
-#endif
-	}
-	return 0;
-}
-
-#endif /* MODULE */
-
-static int __init imsttfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("imsttfb", &option))
-		return -ENODEV;
-
-	imsttfb_setup(option);
-#endif
-	return pci_register_driver(&imsttfb_pci_driver);
-}
- 
-static void __exit imsttfb_exit(void)
-{
-	pci_unregister_driver(&imsttfb_pci_driver);
-}
-
-MODULE_LICENSE("GPL");
-
-module_init(imsttfb_init);
-module_exit(imsttfb_exit);
-
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
deleted file mode 100644
index f6e621684953..000000000000
--- a/drivers/video/imxfb.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- *  Freescale i.MX Frame Buffer device driver
- *
- *  Copyright (C) 2004 Sascha Hauer, Pengutronix
- *   Based on acornfb.c Copyright (C) Russell King.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Please direct your questions and comments on this driver to the following
- * email address:
- *
- *	linux-arm-kernel@lists.arm.linux.org.uk
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/lcd.h>
-#include <linux/math64.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#include <linux/regulator/consumer.h>
-
-#include <video/of_display_timing.h>
-#include <video/of_videomode.h>
-#include <video/videomode.h>
-
-#include <linux/platform_data/video-imxfb.h>
-
-/*
- * Complain if VAR is out of range.
- */
-#define DEBUG_VAR 1
-
-#define DRIVER_NAME "imx-fb"
-
-#define LCDC_SSA	0x00
-
-#define LCDC_SIZE	0x04
-#define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20)
-
-#define YMAX_MASK_IMX1	0x1ff
-#define YMAX_MASK_IMX21	0x3ff
-
-#define LCDC_VPW	0x08
-#define VPW_VPW(x)	((x) & 0x3ff)
-
-#define LCDC_CPOS	0x0C
-#define CPOS_CC1	(1<<31)
-#define CPOS_CC0	(1<<30)
-#define CPOS_OP		(1<<28)
-#define CPOS_CXP(x)	(((x) & 3ff) << 16)
-
-#define LCDC_LCWHB	0x10
-#define LCWHB_BK_EN	(1<<31)
-#define LCWHB_CW(w)	(((w) & 0x1f) << 24)
-#define LCWHB_CH(h)	(((h) & 0x1f) << 16)
-#define LCWHB_BD(x)	((x) & 0xff)
-
-#define LCDC_LCHCC	0x14
-
-#define LCDC_PCR	0x18
-
-#define LCDC_HCR	0x1C
-#define HCR_H_WIDTH(x)	(((x) & 0x3f) << 26)
-#define HCR_H_WAIT_1(x)	(((x) & 0xff) << 8)
-#define HCR_H_WAIT_2(x)	((x) & 0xff)
-
-#define LCDC_VCR	0x20
-#define VCR_V_WIDTH(x)	(((x) & 0x3f) << 26)
-#define VCR_V_WAIT_1(x)	(((x) & 0xff) << 8)
-#define VCR_V_WAIT_2(x)	((x) & 0xff)
-
-#define LCDC_POS	0x24
-#define POS_POS(x)	((x) & 1f)
-
-#define LCDC_LSCR1	0x28
-/* bit fields in imxfb.h */
-
-#define LCDC_PWMR	0x2C
-/* bit fields in imxfb.h */
-
-#define LCDC_DMACR	0x30
-/* bit fields in imxfb.h */
-
-#define LCDC_RMCR	0x34
-
-#define RMCR_LCDC_EN_MX1	(1<<1)
-
-#define RMCR_SELF_REF	(1<<0)
-
-#define LCDC_LCDICR	0x38
-#define LCDICR_INT_SYN	(1<<2)
-#define LCDICR_INT_CON	(1)
-
-#define LCDC_LCDISR	0x40
-#define LCDISR_UDR_ERR	(1<<3)
-#define LCDISR_ERR_RES	(1<<2)
-#define LCDISR_EOF	(1<<1)
-#define LCDISR_BOF	(1<<0)
-
-#define IMXFB_LSCR1_DEFAULT 0x00120300
-
-/* Used fb-mode. Can be set on kernel command line, therefore file-static. */
-static const char *fb_mode;
-
-/*
- * These are the bitfields for each
- * display depth that we support.
- */
-struct imxfb_rgb {
-	struct fb_bitfield	red;
-	struct fb_bitfield	green;
-	struct fb_bitfield	blue;
-	struct fb_bitfield	transp;
-};
-
-enum imxfb_type {
-	IMX1_FB,
-	IMX21_FB,
-};
-
-struct imxfb_info {
-	struct platform_device  *pdev;
-	void __iomem		*regs;
-	struct clk		*clk_ipg;
-	struct clk		*clk_ahb;
-	struct clk		*clk_per;
-	enum imxfb_type		devtype;
-	bool			enabled;
-
-	/*
-	 * These are the addresses we mapped
-	 * the framebuffer memory region to.
-	 */
-	dma_addr_t		map_dma;
-	u_int			map_size;
-
-	u_int			palette_size;
-
-	dma_addr_t		dbar1;
-	dma_addr_t		dbar2;
-
-	u_int			pcr;
-	u_int			pwmr;
-	u_int			lscr1;
-	u_int			dmacr;
-	bool			cmap_inverse;
-	bool			cmap_static;
-
-	struct imx_fb_videomode *mode;
-	int			num_modes;
-
-	struct regulator	*lcd_pwr;
-};
-
-static struct platform_device_id imxfb_devtype[] = {
-	{
-		.name = "imx1-fb",
-		.driver_data = IMX1_FB,
-	}, {
-		.name = "imx21-fb",
-		.driver_data = IMX21_FB,
-	}, {
-		/* sentinel */
-	}
-};
-MODULE_DEVICE_TABLE(platform, imxfb_devtype);
-
-static struct of_device_id imxfb_of_dev_id[] = {
-	{
-		.compatible = "fsl,imx1-fb",
-		.data = &imxfb_devtype[IMX1_FB],
-	}, {
-		.compatible = "fsl,imx21-fb",
-		.data = &imxfb_devtype[IMX21_FB],
-	}, {
-		/* sentinel */
-	}
-};
-MODULE_DEVICE_TABLE(of, imxfb_of_dev_id);
-
-static inline int is_imx1_fb(struct imxfb_info *fbi)
-{
-	return fbi->devtype == IMX1_FB;
-}
-
-#define IMX_NAME	"IMX"
-
-/*
- * Minimum X and Y resolutions
- */
-#define MIN_XRES	64
-#define MIN_YRES	64
-
-/* Actually this really is 18bit support, the lowest 2 bits of each colour
- * are unused in hardware. We claim to have 24bit support to make software
- * like X work, which does not support 18bit.
- */
-static struct imxfb_rgb def_rgb_18 = {
-	.red	= {.offset = 16, .length = 8,},
-	.green	= {.offset = 8, .length = 8,},
-	.blue	= {.offset = 0, .length = 8,},
-	.transp = {.offset = 0, .length = 0,},
-};
-
-static struct imxfb_rgb def_rgb_16_tft = {
-	.red	= {.offset = 11, .length = 5,},
-	.green	= {.offset = 5, .length = 6,},
-	.blue	= {.offset = 0, .length = 5,},
-	.transp = {.offset = 0, .length = 0,},
-};
-
-static struct imxfb_rgb def_rgb_16_stn = {
-	.red	= {.offset = 8, .length = 4,},
-	.green	= {.offset = 4, .length = 4,},
-	.blue	= {.offset = 0, .length = 4,},
-	.transp = {.offset = 0, .length = 0,},
-};
-
-static struct imxfb_rgb def_rgb_8 = {
-	.red	= {.offset = 0, .length = 8,},
-	.green	= {.offset = 0, .length = 8,},
-	.blue	= {.offset = 0, .length = 8,},
-	.transp = {.offset = 0, .length = 0,},
-};
-
-static int imxfb_activate_var(struct fb_var_screeninfo *var,
-		struct fb_info *info);
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int imxfb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
-		u_int trans, struct fb_info *info)
-{
-	struct imxfb_info *fbi = info->par;
-	u_int val, ret = 1;
-
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
-	if (regno < fbi->palette_size) {
-		val = (CNVT_TOHW(red, 4) << 8) |
-		      (CNVT_TOHW(green,4) << 4) |
-		      CNVT_TOHW(blue,  4);
-
-		writel(val, fbi->regs + 0x800 + (regno << 2));
-		ret = 0;
-	}
-	return ret;
-}
-
-static int imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		   u_int trans, struct fb_info *info)
-{
-	struct imxfb_info *fbi = info->par;
-	unsigned int val;
-	int ret = 1;
-
-	/*
-	 * If inverse mode was selected, invert all the colours
-	 * rather than the register number.  The register number
-	 * is what you poke into the framebuffer to produce the
-	 * colour you requested.
-	 */
-	if (fbi->cmap_inverse) {
-		red   = 0xffff - red;
-		green = 0xffff - green;
-		blue  = 0xffff - blue;
-	}
-
-	/*
-	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no mater what visual we are using.
-	 */
-	if (info->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-					7471 * blue) >> 16;
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 12 or 16-bit True Colour.  We encode the RGB value
-		 * according to the RGB bitfield information.
-		 */
-		if (regno < 16) {
-			u32 *pal = info->pseudo_palette;
-
-			val  = chan_to_field(red, &info->var.red);
-			val |= chan_to_field(green, &info->var.green);
-			val |= chan_to_field(blue, &info->var.blue);
-
-			pal[regno] = val;
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_STATIC_PSEUDOCOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		ret = imxfb_setpalettereg(regno, red, green, blue, trans, info);
-		break;
-	}
-
-	return ret;
-}
-
-static const struct imx_fb_videomode *imxfb_find_mode(struct imxfb_info *fbi)
-{
-	struct imx_fb_videomode *m;
-	int i;
-
-	if (!fb_mode)
-		return &fbi->mode[0];
-
-	for (i = 0, m = &fbi->mode[0]; i < fbi->num_modes; i++, m++) {
-		if (!strcmp(m->mode.name, fb_mode))
-			return m;
-	}
-	return NULL;
-}
-
-/*
- *  imxfb_check_var():
- *    Round up in the following order: bits_per_pixel, xres,
- *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
- *    bitfields, horizontal timing, vertical timing.
- */
-static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct imxfb_info *fbi = info->par;
-	struct imxfb_rgb *rgb;
-	const struct imx_fb_videomode *imxfb_mode;
-	unsigned long lcd_clk;
-	unsigned long long tmp;
-	u32 pcr = 0;
-
-	if (var->xres < MIN_XRES)
-		var->xres = MIN_XRES;
-	if (var->yres < MIN_YRES)
-		var->yres = MIN_YRES;
-
-	imxfb_mode = imxfb_find_mode(fbi);
-	if (!imxfb_mode)
-		return -EINVAL;
-
-	var->xres		= imxfb_mode->mode.xres;
-	var->yres		= imxfb_mode->mode.yres;
-	var->bits_per_pixel	= imxfb_mode->bpp;
-	var->pixclock		= imxfb_mode->mode.pixclock;
-	var->hsync_len		= imxfb_mode->mode.hsync_len;
-	var->left_margin	= imxfb_mode->mode.left_margin;
-	var->right_margin	= imxfb_mode->mode.right_margin;
-	var->vsync_len		= imxfb_mode->mode.vsync_len;
-	var->upper_margin	= imxfb_mode->mode.upper_margin;
-	var->lower_margin	= imxfb_mode->mode.lower_margin;
-	var->sync		= imxfb_mode->mode.sync;
-	var->xres_virtual	= max(var->xres_virtual, var->xres);
-	var->yres_virtual	= max(var->yres_virtual, var->yres);
-
-	pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
-
-	lcd_clk = clk_get_rate(fbi->clk_per);
-
-	tmp = var->pixclock * (unsigned long long)lcd_clk;
-
-	do_div(tmp, 1000000);
-
-	if (do_div(tmp, 1000000) > 500000)
-		tmp++;
-
-	pcr = (unsigned int)tmp;
-
-	if (--pcr > 0x3F) {
-		pcr = 0x3F;
-		printk(KERN_WARNING "Must limit pixel clock to %luHz\n",
-				lcd_clk / pcr);
-	}
-
-	switch (var->bits_per_pixel) {
-	case 32:
-		pcr |= PCR_BPIX_18;
-		rgb = &def_rgb_18;
-		break;
-	case 16:
-	default:
-		if (is_imx1_fb(fbi))
-			pcr |= PCR_BPIX_12;
-		else
-			pcr |= PCR_BPIX_16;
-
-		if (imxfb_mode->pcr & PCR_TFT)
-			rgb = &def_rgb_16_tft;
-		else
-			rgb = &def_rgb_16_stn;
-		break;
-	case 8:
-		pcr |= PCR_BPIX_8;
-		rgb = &def_rgb_8;
-		break;
-	}
-
-	/* add sync polarities */
-	pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
-
-	fbi->pcr = pcr;
-
-	/*
-	 * Copy the RGB parameters for this display
-	 * from the machine specific parameters.
-	 */
-	var->red    = rgb->red;
-	var->green  = rgb->green;
-	var->blue   = rgb->blue;
-	var->transp = rgb->transp;
-
-	pr_debug("RGBT length = %d:%d:%d:%d\n",
-		var->red.length, var->green.length, var->blue.length,
-		var->transp.length);
-
-	pr_debug("RGBT offset = %d:%d:%d:%d\n",
-		var->red.offset, var->green.offset, var->blue.offset,
-		var->transp.offset);
-
-	return 0;
-}
-
-/*
- * imxfb_set_par():
- *	Set the user defined part of the display for the specified console
- */
-static int imxfb_set_par(struct fb_info *info)
-{
-	struct imxfb_info *fbi = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-
-	if (var->bits_per_pixel == 16 || var->bits_per_pixel == 32)
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	else if (!fbi->cmap_static)
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else {
-		/*
-		 * Some people have weird ideas about wanting static
-		 * pseudocolor maps.  I suspect their user space
-		 * applications are broken.
-		 */
-		info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-	}
-
-	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
-	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
-
-	imxfb_activate_var(var, info);
-
-	return 0;
-}
-
-static void imxfb_enable_controller(struct imxfb_info *fbi)
-{
-
-	if (fbi->enabled)
-		return;
-
-	pr_debug("Enabling LCD controller\n");
-
-	writel(fbi->map_dma, fbi->regs + LCDC_SSA);
-
-	/* panning offset 0 (0 pixel offset)        */
-	writel(0x00000000, fbi->regs + LCDC_POS);
-
-	/* disable hardware cursor */
-	writel(readl(fbi->regs + LCDC_CPOS) & ~(CPOS_CC0 | CPOS_CC1),
-		fbi->regs + LCDC_CPOS);
-
-	/*
-	 * RMCR_LCDC_EN_MX1 is present on i.MX1 only, but doesn't hurt
-	 * on other SoCs
-	 */
-	writel(RMCR_LCDC_EN_MX1, fbi->regs + LCDC_RMCR);
-
-	clk_prepare_enable(fbi->clk_ipg);
-	clk_prepare_enable(fbi->clk_ahb);
-	clk_prepare_enable(fbi->clk_per);
-	fbi->enabled = true;
-}
-
-static void imxfb_disable_controller(struct imxfb_info *fbi)
-{
-	if (!fbi->enabled)
-		return;
-
-	pr_debug("Disabling LCD controller\n");
-
-	clk_disable_unprepare(fbi->clk_per);
-	clk_disable_unprepare(fbi->clk_ipg);
-	clk_disable_unprepare(fbi->clk_ahb);
-	fbi->enabled = false;
-
-	writel(0, fbi->regs + LCDC_RMCR);
-}
-
-static int imxfb_blank(int blank, struct fb_info *info)
-{
-	struct imxfb_info *fbi = info->par;
-
-	pr_debug("imxfb_blank: blank=%d\n", blank);
-
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		imxfb_disable_controller(fbi);
-		break;
-
-	case FB_BLANK_UNBLANK:
-		imxfb_enable_controller(fbi);
-		break;
-	}
-	return 0;
-}
-
-static struct fb_ops imxfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= imxfb_check_var,
-	.fb_set_par	= imxfb_set_par,
-	.fb_setcolreg	= imxfb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_blank	= imxfb_blank,
-};
-
-/*
- * imxfb_activate_var():
- *	Configures LCD Controller based on entries in var parameter.  Settings are
- *	only written to the controller if changes were made.
- */
-static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct imxfb_info *fbi = info->par;
-	u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21;
-
-	pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
-		var->xres, var->hsync_len,
-		var->left_margin, var->right_margin);
-	pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
-		var->yres, var->vsync_len,
-		var->upper_margin, var->lower_margin);
-
-#if DEBUG_VAR
-	if (var->xres < 16        || var->xres > 1024)
-		printk(KERN_ERR "%s: invalid xres %d\n",
-			info->fix.id, var->xres);
-	if (var->hsync_len < 1    || var->hsync_len > 64)
-		printk(KERN_ERR "%s: invalid hsync_len %d\n",
-			info->fix.id, var->hsync_len);
-	if (var->left_margin > 255)
-		printk(KERN_ERR "%s: invalid left_margin %d\n",
-			info->fix.id, var->left_margin);
-	if (var->right_margin > 255)
-		printk(KERN_ERR "%s: invalid right_margin %d\n",
-			info->fix.id, var->right_margin);
-	if (var->yres < 1 || var->yres > ymax_mask)
-		printk(KERN_ERR "%s: invalid yres %d\n",
-			info->fix.id, var->yres);
-	if (var->vsync_len > 100)
-		printk(KERN_ERR "%s: invalid vsync_len %d\n",
-			info->fix.id, var->vsync_len);
-	if (var->upper_margin > 63)
-		printk(KERN_ERR "%s: invalid upper_margin %d\n",
-			info->fix.id, var->upper_margin);
-	if (var->lower_margin > 255)
-		printk(KERN_ERR "%s: invalid lower_margin %d\n",
-			info->fix.id, var->lower_margin);
-#endif
-
-	/* physical screen start address	    */
-	writel(VPW_VPW(var->xres * var->bits_per_pixel / 8 / 4),
-		fbi->regs + LCDC_VPW);
-
-	writel(HCR_H_WIDTH(var->hsync_len - 1) |
-		HCR_H_WAIT_1(var->right_margin - 1) |
-		HCR_H_WAIT_2(var->left_margin - 3),
-		fbi->regs + LCDC_HCR);
-
-	writel(VCR_V_WIDTH(var->vsync_len) |
-		VCR_V_WAIT_1(var->lower_margin) |
-		VCR_V_WAIT_2(var->upper_margin),
-		fbi->regs + LCDC_VCR);
-
-	writel(SIZE_XMAX(var->xres) | (var->yres & ymax_mask),
-			fbi->regs + LCDC_SIZE);
-
-	writel(fbi->pcr, fbi->regs + LCDC_PCR);
-	if (fbi->pwmr)
-		writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
-	writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
-
-	/* dmacr = 0 is no valid value, as we need DMA control marks. */
-	if (fbi->dmacr)
-		writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
-
-	return 0;
-}
-
-static int imxfb_init_fbinfo(struct platform_device *pdev)
-{
-	struct imx_fb_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct fb_info *info = dev_get_drvdata(&pdev->dev);
-	struct imxfb_info *fbi = info->par;
-	struct device_node *np;
-
-	pr_debug("%s\n",__func__);
-
-	info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
-	if (!info->pseudo_palette)
-		return -ENOMEM;
-
-	memset(fbi, 0, sizeof(struct imxfb_info));
-
-	fbi->devtype = pdev->id_entry->driver_data;
-
-	strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
-
-	info->fix.type			= FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux		= 0;
-	info->fix.xpanstep		= 0;
-	info->fix.ypanstep		= 0;
-	info->fix.ywrapstep		= 0;
-	info->fix.accel			= FB_ACCEL_NONE;
-
-	info->var.nonstd		= 0;
-	info->var.activate		= FB_ACTIVATE_NOW;
-	info->var.height		= -1;
-	info->var.width	= -1;
-	info->var.accel_flags		= 0;
-	info->var.vmode			= FB_VMODE_NONINTERLACED;
-
-	info->fbops			= &imxfb_ops;
-	info->flags			= FBINFO_FLAG_DEFAULT |
-					  FBINFO_READS_FAST;
-	if (pdata) {
-		fbi->lscr1			= pdata->lscr1;
-		fbi->dmacr			= pdata->dmacr;
-		fbi->pwmr			= pdata->pwmr;
-	} else {
-		np = pdev->dev.of_node;
-		info->var.grayscale = of_property_read_bool(np,
-						"cmap-greyscale");
-		fbi->cmap_inverse = of_property_read_bool(np, "cmap-inverse");
-		fbi->cmap_static = of_property_read_bool(np, "cmap-static");
-
-		fbi->lscr1 = IMXFB_LSCR1_DEFAULT;
-
-		of_property_read_u32(np, "fsl,lpccr", &fbi->pwmr);
-
-		of_property_read_u32(np, "fsl,lscr1", &fbi->lscr1);
-
-		of_property_read_u32(np, "fsl,dmacr", &fbi->dmacr);
-	}
-
-	return 0;
-}
-
-static int imxfb_of_read_mode(struct device *dev, struct device_node *np,
-		struct imx_fb_videomode *imxfb_mode)
-{
-	int ret;
-	struct fb_videomode *of_mode = &imxfb_mode->mode;
-	u32 bpp;
-	u32 pcr;
-
-	ret = of_property_read_string(np, "model", &of_mode->name);
-	if (ret)
-		of_mode->name = NULL;
-
-	ret = of_get_fb_videomode(np, of_mode, OF_USE_NATIVE_MODE);
-	if (ret) {
-		dev_err(dev, "Failed to get videomode from DT\n");
-		return ret;
-	}
-
-	ret = of_property_read_u32(np, "bits-per-pixel", &bpp);
-	ret |= of_property_read_u32(np, "fsl,pcr", &pcr);
-
-	if (ret) {
-		dev_err(dev, "Failed to read bpp and pcr from DT\n");
-		return -EINVAL;
-	}
-
-	if (bpp < 1 || bpp > 255) {
-		dev_err(dev, "Bits per pixel have to be between 1 and 255\n");
-		return -EINVAL;
-	}
-
-	imxfb_mode->bpp = bpp;
-	imxfb_mode->pcr = pcr;
-
-	return 0;
-}
-
-static int imxfb_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi)
-{
-	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
-
-	if (!fi || fi->par == fbi)
-		return 1;
-
-	return 0;
-}
-
-static int imxfb_lcd_get_contrast(struct lcd_device *lcddev)
-{
-	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
-
-	return fbi->pwmr & 0xff;
-}
-
-static int imxfb_lcd_set_contrast(struct lcd_device *lcddev, int contrast)
-{
-	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
-
-	if (fbi->pwmr && fbi->enabled) {
-		if (contrast > 255)
-			contrast = 255;
-		else if (contrast < 0)
-			contrast = 0;
-
-		fbi->pwmr &= ~0xff;
-		fbi->pwmr |= contrast;
-
-		writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
-	}
-
-	return 0;
-}
-
-static int imxfb_lcd_get_power(struct lcd_device *lcddev)
-{
-	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
-
-	if (!IS_ERR(fbi->lcd_pwr))
-		return regulator_is_enabled(fbi->lcd_pwr);
-
-	return 1;
-}
-
-static int imxfb_lcd_set_power(struct lcd_device *lcddev, int power)
-{
-	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
-
-	if (!IS_ERR(fbi->lcd_pwr)) {
-		if (power)
-			return regulator_enable(fbi->lcd_pwr);
-		else
-			return regulator_disable(fbi->lcd_pwr);
-	}
-
-	return 0;
-}
-
-static struct lcd_ops imxfb_lcd_ops = {
-	.check_fb	= imxfb_lcd_check_fb,
-	.get_contrast	= imxfb_lcd_get_contrast,
-	.set_contrast	= imxfb_lcd_set_contrast,
-	.get_power	= imxfb_lcd_get_power,
-	.set_power	= imxfb_lcd_set_power,
-};
-
-static int imxfb_setup(void)
-{
-	char *opt, *options = NULL;
-
-	if (fb_get_options("imxfb", &options))
-		return -ENODEV;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-		else
-			fb_mode = opt;
-	}
-
-	return 0;
-}
-
-static int imxfb_probe(struct platform_device *pdev)
-{
-	struct imxfb_info *fbi;
-	struct lcd_device *lcd;
-	struct fb_info *info;
-	struct imx_fb_platform_data *pdata;
-	struct resource *res;
-	struct imx_fb_videomode *m;
-	const struct of_device_id *of_id;
-	int ret, i;
-	int bytes_per_pixel;
-
-	dev_info(&pdev->dev, "i.MX Framebuffer driver\n");
-
-	ret = imxfb_setup();
-	if (ret < 0)
-		return ret;
-
-	of_id = of_match_device(imxfb_of_dev_id, &pdev->dev);
-	if (of_id)
-		pdev->id_entry = of_id->data;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	fbi = info->par;
-
-	platform_set_drvdata(pdev, info);
-
-	ret = imxfb_init_fbinfo(pdev);
-	if (ret < 0)
-		goto failed_init;
-
-	if (pdata) {
-		if (!fb_mode)
-			fb_mode = pdata->mode[0].mode.name;
-
-		fbi->mode = pdata->mode;
-		fbi->num_modes = pdata->num_modes;
-	} else {
-		struct device_node *display_np;
-		fb_mode = NULL;
-
-		display_np = of_parse_phandle(pdev->dev.of_node, "display", 0);
-		if (!display_np) {
-			dev_err(&pdev->dev, "No display defined in devicetree\n");
-			ret = -EINVAL;
-			goto failed_of_parse;
-		}
-
-		/*
-		 * imxfb does not support more modes, we choose only the native
-		 * mode.
-		 */
-		fbi->num_modes = 1;
-
-		fbi->mode = devm_kzalloc(&pdev->dev,
-				sizeof(struct imx_fb_videomode), GFP_KERNEL);
-		if (!fbi->mode) {
-			ret = -ENOMEM;
-			goto failed_of_parse;
-		}
-
-		ret = imxfb_of_read_mode(&pdev->dev, display_np, fbi->mode);
-		if (ret)
-			goto failed_of_parse;
-	}
-
-	/* Calculate maximum bytes used per pixel. In most cases this should
-	 * be the same as m->bpp/8 */
-	m = &fbi->mode[0];
-	bytes_per_pixel = (m->bpp + 7) / 8;
-	for (i = 0; i < fbi->num_modes; i++, m++)
-		info->fix.smem_len = max_t(size_t, info->fix.smem_len,
-				m->mode.xres * m->mode.yres * bytes_per_pixel);
-
-	res = request_mem_region(res->start, resource_size(res),
-				DRIVER_NAME);
-	if (!res) {
-		ret = -EBUSY;
-		goto failed_req;
-	}
-
-	fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
-	if (IS_ERR(fbi->clk_ipg)) {
-		ret = PTR_ERR(fbi->clk_ipg);
-		goto failed_getclock;
-	}
-
-	fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
-	if (IS_ERR(fbi->clk_ahb)) {
-		ret = PTR_ERR(fbi->clk_ahb);
-		goto failed_getclock;
-	}
-
-	fbi->clk_per = devm_clk_get(&pdev->dev, "per");
-	if (IS_ERR(fbi->clk_per)) {
-		ret = PTR_ERR(fbi->clk_per);
-		goto failed_getclock;
-	}
-
-	fbi->regs = ioremap(res->start, resource_size(res));
-	if (fbi->regs == NULL) {
-		dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
-		ret = -ENOMEM;
-		goto failed_ioremap;
-	}
-
-	fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
-	info->screen_base = dma_alloc_writecombine(&pdev->dev, fbi->map_size,
-						   &fbi->map_dma, GFP_KERNEL);
-
-	if (!info->screen_base) {
-		dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
-		ret = -ENOMEM;
-		goto failed_map;
-	}
-
-	info->fix.smem_start = fbi->map_dma;
-
-	if (pdata && pdata->init) {
-		ret = pdata->init(fbi->pdev);
-		if (ret)
-			goto failed_platform_init;
-	}
-
-
-	INIT_LIST_HEAD(&info->modelist);
-	for (i = 0; i < fbi->num_modes; i++)
-		fb_add_videomode(&fbi->mode[i].mode, &info->modelist);
-
-	/*
-	 * This makes sure that our colour bitfield
-	 * descriptors are correctly initialised.
-	 */
-	imxfb_check_var(&info->var, info);
-
-	ret = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
-	if (ret < 0)
-		goto failed_cmap;
-
-	imxfb_set_par(info);
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to register framebuffer\n");
-		goto failed_register;
-	}
-
-	fbi->lcd_pwr = devm_regulator_get(&pdev->dev, "lcd");
-	if (IS_ERR(fbi->lcd_pwr) && (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER)) {
-		ret = -EPROBE_DEFER;
-		goto failed_lcd;
-	}
-
-	lcd = devm_lcd_device_register(&pdev->dev, "imxfb-lcd", &pdev->dev, fbi,
-				       &imxfb_lcd_ops);
-	if (IS_ERR(lcd)) {
-		ret = PTR_ERR(lcd);
-		goto failed_lcd;
-	}
-
-	lcd->props.max_contrast = 0xff;
-
-	imxfb_enable_controller(fbi);
-	fbi->pdev = pdev;
-
-	return 0;
-
-failed_lcd:
-	unregister_framebuffer(info);
-
-failed_register:
-	fb_dealloc_cmap(&info->cmap);
-failed_cmap:
-	if (pdata && pdata->exit)
-		pdata->exit(fbi->pdev);
-failed_platform_init:
-	dma_free_writecombine(&pdev->dev, fbi->map_size, info->screen_base,
-			      fbi->map_dma);
-failed_map:
-	iounmap(fbi->regs);
-failed_ioremap:
-failed_getclock:
-	release_mem_region(res->start, resource_size(res));
-failed_req:
-failed_of_parse:
-	kfree(info->pseudo_palette);
-failed_init:
-	framebuffer_release(info);
-	return ret;
-}
-
-static int imxfb_remove(struct platform_device *pdev)
-{
-	struct imx_fb_platform_data *pdata;
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct imxfb_info *fbi = info->par;
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	imxfb_disable_controller(fbi);
-
-	unregister_framebuffer(info);
-
-	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata && pdata->exit)
-		pdata->exit(fbi->pdev);
-
-	fb_dealloc_cmap(&info->cmap);
-	kfree(info->pseudo_palette);
-	framebuffer_release(info);
-
-	dma_free_writecombine(&pdev->dev, fbi->map_size, info->screen_base,
-			      fbi->map_dma);
-
-	iounmap(fbi->regs);
-	release_mem_region(res->start, resource_size(res));
-
-	return 0;
-}
-
-static int __maybe_unused imxfb_suspend(struct device *dev)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct imxfb_info *fbi = info->par;
-
-	imxfb_disable_controller(fbi);
-
-	return 0;
-}
-
-static int __maybe_unused imxfb_resume(struct device *dev)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct imxfb_info *fbi = info->par;
-
-	imxfb_enable_controller(fbi);
-
-	return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
-
-static struct platform_driver imxfb_driver = {
-	.driver		= {
-		.name	= DRIVER_NAME,
-		.of_match_table = imxfb_of_dev_id,
-		.owner	= THIS_MODULE,
-		.pm	= &imxfb_pm_ops,
-	},
-	.probe		= imxfb_probe,
-	.remove		= imxfb_remove,
-	.id_table	= imxfb_devtype,
-};
-module_platform_driver(imxfb_driver);
-
-MODULE_DESCRIPTION("Freescale i.MX framebuffer driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/intelfb/Makefile b/drivers/video/intelfb/Makefile
deleted file mode 100644
index f7d631ebee8e..000000000000
--- a/drivers/video/intelfb/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-obj-$(CONFIG_FB_INTEL) += intelfb.o
-
-intelfb-y := intelfbdrv.o intelfbhw.o
-intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
-intelfb-objs := $(intelfb-y)
-
-ccflags-$(CONFIG_FB_INTEL_DEBUG) := -DDEBUG -DREGDUMP
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
deleted file mode 100644
index 6b51175629c7..000000000000
--- a/drivers/video/intelfb/intelfb.h
+++ /dev/null
@@ -1,383 +0,0 @@
-#ifndef _INTELFB_H
-#define _INTELFB_H
-
-/* $DHD: intelfb/intelfb.h,v 1.40 2003/06/27 15:06:25 dawes Exp $ */
-
-#include <linux/agp_backend.h>
-#include <linux/fb.h>
-
-#ifdef CONFIG_FB_INTEL_I2C
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#endif
-
-/*** Version/name ***/
-#define INTELFB_VERSION			"0.9.6"
-#define INTELFB_MODULE_NAME		"intelfb"
-#define SUPPORTED_CHIPSETS		"830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
-
-
-/*** Debug/feature defines ***/
-
-#ifndef DEBUG
-#define DEBUG				0
-#endif
-
-#ifndef VERBOSE
-#define VERBOSE				0
-#endif
-
-#ifndef REGDUMP
-#define REGDUMP				0
-#endif
-
-#ifndef DETECT_VGA_CLASS_ONLY
-#define DETECT_VGA_CLASS_ONLY		1
-#endif
-
-#ifndef ALLOCATE_FOR_PANNING
-#define ALLOCATE_FOR_PANNING		1
-#endif
-
-#ifndef PREFERRED_MODE
-#define PREFERRED_MODE			"1024x768-32@70"
-#endif
-
-/*** hw-related values ***/
-
-/* Resource Allocation */
-#define INTELFB_FB_ACQUIRED                 1
-#define INTELFB_MMIO_ACQUIRED               2
-
-/* PCI ids for supported devices */
-#define PCI_DEVICE_ID_INTEL_830M	0x3577
-#define PCI_DEVICE_ID_INTEL_845G	0x2562
-#define PCI_DEVICE_ID_INTEL_85XGM	0x3582
-#define PCI_DEVICE_ID_INTEL_854		0x358E
-#define PCI_DEVICE_ID_INTEL_865G	0x2572
-#define PCI_DEVICE_ID_INTEL_915G	0x2582
-#define PCI_DEVICE_ID_INTEL_915GM	0x2592
-#define PCI_DEVICE_ID_INTEL_945G	0x2772
-#define PCI_DEVICE_ID_INTEL_945GM	0x27A2
-#define PCI_DEVICE_ID_INTEL_945GME	0x27AE
-#define PCI_DEVICE_ID_INTEL_965G	0x29A2
-#define PCI_DEVICE_ID_INTEL_965GM	0x2A02
-
-/* Size of MMIO region */
-#define INTEL_REG_SIZE			0x80000
-
-#define STRIDE_ALIGNMENT		16
-#define STRIDE_ALIGNMENT_I9XX		64
-
-#define PALETTE_8_ENTRIES		256
-
-
-/*** Macros ***/
-
-/* basic arithmetic */
-#define KB(x)			((x) * 1024)
-#define MB(x)			((x) * 1024 * 1024)
-#define BtoKB(x)		((x) / 1024)
-#define BtoMB(x)		((x) / 1024 / 1024)
-
-#define GTT_PAGE_SIZE           KB(4)
-
-#define ROUND_UP_TO(x, y)	(((x) + (y) - 1) / (y) * (y))
-#define ROUND_DOWN_TO(x, y)	((x) / (y) * (y))
-#define ROUND_UP_TO_PAGE(x)	ROUND_UP_TO((x), GTT_PAGE_SIZE)
-#define ROUND_DOWN_TO_PAGE(x)	ROUND_DOWN_TO((x), GTT_PAGE_SIZE)
-
-/* messages */
-#define PFX			INTELFB_MODULE_NAME ": "
-
-#define ERR_MSG(fmt, args...)	printk(KERN_ERR PFX fmt, ## args)
-#define WRN_MSG(fmt, args...)	printk(KERN_WARNING PFX fmt, ## args)
-#define NOT_MSG(fmt, args...)	printk(KERN_NOTICE PFX fmt, ## args)
-#define INF_MSG(fmt, args...)	printk(KERN_INFO PFX fmt, ## args)
-#if DEBUG
-#define DBG_MSG(fmt, args...)	printk(KERN_DEBUG PFX fmt, ## args)
-#else
-#define DBG_MSG(fmt, args...)	while (0) printk(fmt, ## args)
-#endif
-
-/* get commonly used pointers */
-#define GET_DINFO(info)		(info)->par
-
-/* misc macros */
-#define ACCEL(d, i)                                                     \
-	((d)->accel && !(d)->ring_lockup &&                             \
-	 ((i)->var.accel_flags & FB_ACCELF_TEXT))
-
-/*#define NOACCEL_CHIPSET(d)						\
-	((d)->chipset != INTEL_865G)*/
-#define NOACCEL_CHIPSET(d)						\
-	(0)
-
-#define FIXED_MODE(d) ((d)->fixed_mode)
-
-/*** Driver parameters ***/
-
-#define RINGBUFFER_SIZE		KB(64)
-#define HW_CURSOR_SIZE		KB(4)
-
-/* Intel agpgart driver */
-#define AGP_PHYSICAL_MEMORY     2
-
-/* store information about an Ixxx DVO */
-/* The i830->i865 use multiple DVOs with multiple i2cs */
-/* the i915, i945 have a single sDVO i2c bus - which is different */
-#define MAX_OUTPUTS 6
-
-/* these are outputs from the chip - integrated only
-   external chips are via DVO or SDVO output */
-#define INTELFB_OUTPUT_UNUSED 0
-#define INTELFB_OUTPUT_ANALOG 1
-#define INTELFB_OUTPUT_DVO 2
-#define INTELFB_OUTPUT_SDVO 3
-#define INTELFB_OUTPUT_LVDS 4
-#define INTELFB_OUTPUT_TVOUT 5
-
-#define INTELFB_DVO_CHIP_NONE 0
-#define INTELFB_DVO_CHIP_LVDS 1
-#define INTELFB_DVO_CHIP_TMDS 2
-#define INTELFB_DVO_CHIP_TVOUT 4
-
-#define INTELFB_OUTPUT_PIPE_NC  0
-#define INTELFB_OUTPUT_PIPE_A   1
-#define INTELFB_OUTPUT_PIPE_B   2
-
-/*** Data Types ***/
-
-/* supported chipsets */
-enum intel_chips {
-	INTEL_830M,
-	INTEL_845G,
-	INTEL_85XGM,
-	INTEL_852GM,
-	INTEL_852GME,
-	INTEL_854,
-	INTEL_855GM,
-	INTEL_855GME,
-	INTEL_865G,
-	INTEL_915G,
-	INTEL_915GM,
-	INTEL_945G,
-	INTEL_945GM,
-	INTEL_945GME,
-	INTEL_965G,
-	INTEL_965GM,
-};
-
-struct intelfb_hwstate {
-	u32 vga0_divisor;
-	u32 vga1_divisor;
-	u32 vga_pd;
-	u32 dpll_a;
-	u32 dpll_b;
-	u32 fpa0;
-	u32 fpa1;
-	u32 fpb0;
-	u32 fpb1;
-	u32 palette_a[PALETTE_8_ENTRIES];
-	u32 palette_b[PALETTE_8_ENTRIES];
-	u32 htotal_a;
-	u32 hblank_a;
-	u32 hsync_a;
-	u32 vtotal_a;
-	u32 vblank_a;
-	u32 vsync_a;
-	u32 src_size_a;
-	u32 bclrpat_a;
-	u32 htotal_b;
-	u32 hblank_b;
-	u32 hsync_b;
-	u32 vtotal_b;
-	u32 vblank_b;
-	u32 vsync_b;
-	u32 src_size_b;
-	u32 bclrpat_b;
-	u32 adpa;
-	u32 dvoa;
-	u32 dvob;
-	u32 dvoc;
-	u32 dvoa_srcdim;
-	u32 dvob_srcdim;
-	u32 dvoc_srcdim;
-	u32 lvds;
-	u32 pipe_a_conf;
-	u32 pipe_b_conf;
-	u32 disp_arb;
-	u32 cursor_a_control;
-	u32 cursor_b_control;
-	u32 cursor_a_base;
-	u32 cursor_b_base;
-	u32 cursor_size;
-	u32 disp_a_ctrl;
-	u32 disp_b_ctrl;
-	u32 disp_a_base;
-	u32 disp_b_base;
-	u32 cursor_a_palette[4];
-	u32 cursor_b_palette[4];
-	u32 disp_a_stride;
-	u32 disp_b_stride;
-	u32 vgacntrl;
-	u32 add_id;
-	u32 swf0x[7];
-	u32 swf1x[7];
-	u32 swf3x[3];
-	u32 fence[8];
-	u32 instpm;
-	u32 mem_mode;
-	u32 fw_blc_0;
-	u32 fw_blc_1;
-	u16 hwstam;
-	u16 ier;
-	u16 iir;
-	u16 imr;
-};
-
-struct intelfb_heap_data {
-	u32 physical;
-	u8 __iomem *virtual;
-	u32 offset;		/* in GATT pages */
-	u32 size;		/* in bytes */
-};
-
-#ifdef CONFIG_FB_INTEL_I2C
-struct intelfb_i2c_chan {
-    struct intelfb_info *dinfo;
-    u32 reg;
-    struct i2c_adapter adapter;
-    struct i2c_algo_bit_data algo;
-};
-#endif
-
-struct intelfb_output_rec {
-    int type;
-    int pipe;
-    int flags;
-
-#ifdef CONFIG_FB_INTEL_I2C
-    struct intelfb_i2c_chan i2c_bus;
-    struct intelfb_i2c_chan ddc_bus;
-#endif
-};
-
-struct intelfb_vsync {
-	wait_queue_head_t wait;
-	unsigned int count;
-	int pan_display;
-	u32 pan_offset;
-};
-
-struct intelfb_info {
-	struct fb_info *info;
-	struct fb_ops  *fbops;
-	struct pci_dev *pdev;
-
-	struct intelfb_hwstate save_state;
-
-	/* agpgart structs */
-	struct agp_memory *gtt_fb_mem;     /* use all stolen memory or vram */
-	struct agp_memory *gtt_ring_mem;   /* ring buffer */
-	struct agp_memory *gtt_cursor_mem; /* hw cursor */
-
-	/* use a gart reserved fb mem */
-	u8 fbmem_gart;
-
-	/* mtrr support */
-	int mtrr_reg;
-	u32 has_mtrr;
-
-	/* heap data */
-	struct intelfb_heap_data aperture;
-	struct intelfb_heap_data fb;
-	struct intelfb_heap_data ring;
-	struct intelfb_heap_data cursor;
-
-	/* mmio regs */
-	u32 mmio_base_phys;
-	u8 __iomem *mmio_base;
-
-	/* fb start offset (in bytes) */
-	u32 fb_start;
-
-	/* ring buffer */
-	u32 ring_head;
-	u32 ring_tail;
-	u32 ring_tail_mask;
-	u32 ring_space;
-	u32 ring_lockup;
-
-	/* palette */
-	u32 pseudo_palette[16];
-
-	/* chip info */
-	int pci_chipset;
-	int chipset;
-	const char *name;
-	int mobile;
-
-	/* current mode */
-	int bpp, depth;
-	u32 visual;
-	int xres, yres, pitch;
-	int pixclock;
-
-	/* current pipe */
-	int pipe;
-
-	/* some flags */
-	int accel;
-	int hwcursor;
-	int fixed_mode;
-	int ring_active;
-	int flag;
-	unsigned long irq_flags;
-	int open;
-
-	/* vsync */
-	struct intelfb_vsync vsync;
-	spinlock_t int_lock;
-
-	/* hw cursor */
-	int cursor_on;
-	int cursor_blanked;
-	u8  cursor_src[64];
-
-	/* initial parameters */
-	int initial_vga;
-	struct fb_var_screeninfo initial_var;
-	u32 initial_fb_base;
-	u32 initial_video_ram;
-	u32 initial_pitch;
-
-	/* driver registered */
-	int registered;
-
-	/* index into plls */
-	int pll_index;
-
-	/* outputs */
-	int num_outputs;
-	struct intelfb_output_rec output[MAX_OUTPUTS];
-};
-
-#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G) ||	\
-			((dinfo)->chipset == INTEL_915GM) ||	\
-			((dinfo)->chipset == INTEL_945G) ||	\
-			((dinfo)->chipset == INTEL_945GM) ||	\
-			((dinfo)->chipset == INTEL_945GME) ||	\
-			((dinfo)->chipset == INTEL_965G) ||	\
-			((dinfo)->chipset == INTEL_965GM))
-
-/*** function prototypes ***/
-
-extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
-
-#ifdef CONFIG_FB_INTEL_I2C
-extern void intelfb_create_i2c_busses(struct intelfb_info *dinfo);
-extern void intelfb_delete_i2c_busses(struct intelfb_info *dinfo);
-#endif
-
-#endif /* _INTELFB_H */
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
deleted file mode 100644
index 3300bd31d9d7..000000000000
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/**************************************************************************
-
- Copyright 2006 Dave Airlie <airlied@linux.ie>
-
-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
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/fb.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include <asm/io.h>
-
-#include "intelfb.h"
-#include "intelfbhw.h"
-
-/* bit locations in the registers */
-#define SCL_DIR_MASK		0x0001
-#define SCL_DIR			0x0002
-#define SCL_VAL_MASK		0x0004
-#define SCL_VAL_OUT		0x0008
-#define SCL_VAL_IN		0x0010
-#define SDA_DIR_MASK		0x0100
-#define SDA_DIR			0x0200
-#define SDA_VAL_MASK		0x0400
-#define SDA_VAL_OUT		0x0800
-#define SDA_VAL_IN		0x1000
-
-static void intelfb_gpio_setscl(void *data, int state)
-{
-	struct intelfb_i2c_chan *chan = data;
-	struct intelfb_info *dinfo = chan->dinfo;
-	u32 val;
-
-	OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) |
-	       SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
-	val = INREG(chan->reg);
-}
-
-static void intelfb_gpio_setsda(void *data, int state)
-{
-	struct intelfb_i2c_chan *chan = data;
-	struct intelfb_info *dinfo = chan->dinfo;
-	u32 val;
-
-	OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) |
-	       SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
-	val = INREG(chan->reg);
-}
-
-static int intelfb_gpio_getscl(void *data)
-{
-	struct intelfb_i2c_chan *chan = data;
-	struct intelfb_info *dinfo = chan->dinfo;
-	u32 val;
-
-	OUTREG(chan->reg, SCL_DIR_MASK);
-	OUTREG(chan->reg, 0);
-	val = INREG(chan->reg);
-	return ((val & SCL_VAL_IN) != 0);
-}
-
-static int intelfb_gpio_getsda(void *data)
-{
-	struct intelfb_i2c_chan *chan = data;
-	struct intelfb_info *dinfo = chan->dinfo;
-	u32 val;
-
-	OUTREG(chan->reg, SDA_DIR_MASK);
-	OUTREG(chan->reg, 0);
-	val = INREG(chan->reg);
-	return ((val & SDA_VAL_IN) != 0);
-}
-
-static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
-				 struct intelfb_i2c_chan *chan,
-				 const u32 reg, const char *name,
-				 int class)
-{
-	int rc;
-
-	chan->dinfo			= dinfo;
-	chan->reg			= reg;
-	snprintf(chan->adapter.name, sizeof(chan->adapter.name),
-		 "intelfb %s", name);
-	chan->adapter.class		= class;
-	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.algo_data		= &chan->algo;
-	chan->adapter.dev.parent	= &chan->dinfo->pdev->dev;
-	chan->algo.setsda		= intelfb_gpio_setsda;
-	chan->algo.setscl		= intelfb_gpio_setscl;
-	chan->algo.getsda		= intelfb_gpio_getsda;
-	chan->algo.getscl		= intelfb_gpio_getscl;
-	chan->algo.udelay		= 40;
-	chan->algo.timeout		= 20;
-	chan->algo.data			= chan;
-
-	i2c_set_adapdata(&chan->adapter, chan);
-
-	/* Raise SCL and SDA */
-	intelfb_gpio_setsda(chan, 1);
-	intelfb_gpio_setscl(chan, 1);
-	udelay(20);
-
-	rc = i2c_bit_add_bus(&chan->adapter);
-	if (rc == 0)
-		DBG_MSG("I2C bus %s registered.\n", name);
-	else
-		WRN_MSG("Failed to register I2C bus %s.\n", name);
-	return rc;
-}
-
-void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
-{
-	int i = 0;
-
-	/* everyone has at least a single analog output */
-	dinfo->num_outputs = 1;
-	dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;
-
-	/* setup the DDC bus for analog output */
-	intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
-			      "CRTDDC_A", I2C_CLASS_DDC);
-	i++;
-
-	/* need to add the output busses for each device
-	   - this function is very incomplete
-	   - i915GM has LVDS and TVOUT for example
-	*/
-	switch(dinfo->chipset) {
-	case INTEL_830M:
-	case INTEL_845G:
-	case INTEL_854:
-	case INTEL_855GM:
-	case INTEL_865G:
-		dinfo->output[i].type = INTELFB_OUTPUT_DVO;
-		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
-				      GPIOD, "DVODDC_D", I2C_CLASS_DDC);
-		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
-				      GPIOE, "DVOI2C_E", 0);
-		i++;
-		break;
-	case INTEL_915G:
-	case INTEL_915GM:
-		/* has some LVDS + tv-out */
-	case INTEL_945G:
-	case INTEL_945GM:
-	case INTEL_945GME:
-	case INTEL_965G:
-	case INTEL_965GM:
-		/* SDVO ports have a single control bus - 2 devices */
-		dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
-		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
-				      GPIOE, "SDVOCTRL_E", 0);
-		/* TODO: initialize the SDVO */
-		/* I830SDVOInit(pScrn, i, DVOB); */
-		i++;
-
-		/* set up SDVOC */
-		dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
-		dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
-		/* TODO: initialize the SDVO */
-		/* I830SDVOInit(pScrn, i, DVOC); */
-		i++;
-		break;
-	}
-	dinfo->num_outputs = i;
-}
-
-void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
-{
-	int i;
-
-	for (i = 0; i < MAX_OUTPUTS; i++) {
-		if (dinfo->output[i].i2c_bus.dinfo) {
-			i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
-			dinfo->output[i].i2c_bus.dinfo = NULL;
-		}
-		if (dinfo->output[i].ddc_bus.dinfo) {
-			i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
-			dinfo->output[i].ddc_bus.dinfo = NULL;
-		}
-	}
-}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
deleted file mode 100644
index b847d530471a..000000000000
--- a/drivers/video/intelfb/intelfbdrv.c
+++ /dev/null
@@ -1,1704 +0,0 @@
-/*
- * intelfb
- *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
- * 945G/945GM/945GME/965G/965GM integrated graphics chips.
- *
- * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
- *                   2004 Sylvain Meyer
- *                   2006 David Airlie
- *
- * This driver consists of two parts.  The first part (intelfbdrv.c) provides
- * the basic fbdev interfaces, is derived in part from the radeonfb and
- * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c)
- * provides the code to program the hardware.  Most of it is derived from
- * the i810/i830 XFree86 driver.  The HW-specific code is covered here
- * under a dual license (GPL and MIT/XFree86 license).
- *
- * Author: David Dawes
- *
- */
-
-/* $DHD: intelfb/intelfbdrv.c,v 1.20 2003/06/27 15:17:40 dawes Exp $ */
-
-/*
- * Changes:
- *    01/2003 - Initial driver (0.1.0), no mode switching, no acceleration.
- *		This initial version is a basic core that works a lot like
- *		the vesafb driver.  It must be built-in to the kernel,
- *		and the initial video mode must be set with vga=XXX at
- *		boot time.  (David Dawes)
- *
- *    01/2003 - Version 0.2.0: Mode switching added, colormap support
- *		implemented, Y panning, and soft screen blanking implemented.
- *		No acceleration yet.  (David Dawes)
- *
- *    01/2003 - Version 0.3.0: fbcon acceleration support added.  Module
- *		option handling added.  (David Dawes)
- *
- *    01/2003 - Version 0.4.0: fbcon HW cursor support added.  (David Dawes)
- *
- *    01/2003 - Version 0.4.1: Add auto-generation of built-in modes.
- *		(David Dawes)
- *
- *    02/2003 - Version 0.4.2: Add check for active non-CRT devices, and
- *		mode validation checks.  (David Dawes)
- *
- *    02/2003 - Version 0.4.3: Check when the VC is in graphics mode so that
- *		acceleration is disabled while an XFree86 server is running.
- *		(David Dawes)
- *
- *    02/2003 - Version 0.4.4: Monitor DPMS support.  (David Dawes)
- *
- *    02/2003 - Version 0.4.5: Basic XFree86 + fbdev working.  (David Dawes)
- *
- *    02/2003 - Version 0.5.0: Modify to work with the 2.5.32 kernel as well
- *		as 2.4.x kernels.  (David Dawes)
- *
- *    02/2003 - Version 0.6.0: Split out HW-specifics into a separate file.
- *		(David Dawes)
- *
- *    02/2003 - Version 0.7.0: Test on 852GM/855GM.  Acceleration and HW
- *		cursor are disabled on this platform.  (David Dawes)
- *
- *    02/2003 - Version 0.7.1: Test on 845G.  Acceleration is disabled
- *		on this platform.  (David Dawes)
- *
- *    02/2003 - Version 0.7.2: Test on 830M.  Acceleration and HW
- *		cursor are disabled on this platform.  (David Dawes)
- *
- *    02/2003 - Version 0.7.3: Fix 8-bit modes for mobile platforms
- *		(David Dawes)
- *
- *    02/2003 - Version 0.7.4: Add checks for FB and FBCON_HAS_CFB* configured
- *		in the kernel, and add mode bpp verification and default
- *		bpp selection based on which FBCON_HAS_CFB* are configured.
- *		(David Dawes)
- *
- *    02/2003 - Version 0.7.5: Add basic package/install scripts based on the
- *		DRI packaging scripts.  (David Dawes)
- *
- *    04/2003 - Version 0.7.6: Fix typo that affects builds with SMP-enabled
- *		kernels.  (David Dawes, reported by Anupam).
- *
- *    06/2003 - Version 0.7.7:
- *              Fix Makefile.kernel build problem (Tsutomu Yasuda).
- *		Fix mis-placed #endif (2.4.21 kernel).
- *
- *    09/2004 - Version 0.9.0 - by Sylvain Meyer
- *              Port to linux 2.6 kernel fbdev
- *              Fix HW accel and HW cursor on i845G
- *              Use of agpgart for fb memory reservation
- *              Add mtrr support
- *
- *    10/2004 - Version 0.9.1
- *              Use module_param instead of old MODULE_PARM
- *              Some cleanup
- *
- *    11/2004 - Version 0.9.2
- *              Add vram option to reserve more memory than stolen by BIOS
- *              Fix intelfbhw_pan_display typo
- *              Add __initdata annotations
- *
- *    04/2008 - Version 0.9.5
- *              Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
- *
- *    08/2008 - Version 0.9.6
- *              Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
-#include <linux/screen_info.h>
-
-#include <asm/io.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include "intelfb.h"
-#include "intelfbhw.h"
-#include "../edid.h"
-
-static void get_initial_mode(struct intelfb_info *dinfo);
-static void update_dinfo(struct intelfb_info *dinfo,
-			 struct fb_var_screeninfo *var);
-static int intelfb_open(struct fb_info *info, int user);
-static int intelfb_release(struct fb_info *info, int user);
-static int intelfb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info);
-static int intelfb_set_par(struct fb_info *info);
-static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info *info);
-
-static int intelfb_blank(int blank, struct fb_info *info);
-static int intelfb_pan_display(struct fb_var_screeninfo *var,
-			       struct fb_info *info);
-
-static void intelfb_fillrect(struct fb_info *info,
-			     const struct fb_fillrect *rect);
-static void intelfb_copyarea(struct fb_info *info,
-			     const struct fb_copyarea *region);
-static void intelfb_imageblit(struct fb_info *info,
-			      const struct fb_image *image);
-static int intelfb_cursor(struct fb_info *info,
-			   struct fb_cursor *cursor);
-
-static int intelfb_sync(struct fb_info *info);
-
-static int intelfb_ioctl(struct fb_info *info,
-			 unsigned int cmd, unsigned long arg);
-
-static int intelfb_pci_register(struct pci_dev *pdev,
-				const struct pci_device_id *ent);
-static void intelfb_pci_unregister(struct pci_dev *pdev);
-static int intelfb_set_fbinfo(struct intelfb_info *dinfo);
-
-/*
- * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
- * mobile chipsets from being registered.
- */
-#if DETECT_VGA_CLASS_ONLY
-#define INTELFB_CLASS_MASK ~0 << 8
-#else
-#define INTELFB_CLASS_MASK 0
-#endif
-
-static struct pci_device_id intelfb_pci_table[] = {
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_854, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_854 },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
-	{ 0, }
-};
-
-/* Global data */
-static int num_registered = 0;
-
-/* fb ops */
-static struct fb_ops intel_fb_ops = {
-	.owner =		THIS_MODULE,
-	.fb_open =              intelfb_open,
-	.fb_release =           intelfb_release,
-	.fb_check_var =         intelfb_check_var,
-	.fb_set_par =           intelfb_set_par,
-	.fb_setcolreg =		intelfb_setcolreg,
-	.fb_blank =		intelfb_blank,
-	.fb_pan_display =       intelfb_pan_display,
-	.fb_fillrect  =         intelfb_fillrect,
-	.fb_copyarea  =         intelfb_copyarea,
-	.fb_imageblit =         intelfb_imageblit,
-	.fb_cursor =            intelfb_cursor,
-	.fb_sync =              intelfb_sync,
-	.fb_ioctl =		intelfb_ioctl
-};
-
-/* PCI driver module table */
-static struct pci_driver intelfb_driver = {
-	.name =		"intelfb",
-	.id_table =	intelfb_pci_table,
-	.probe =	intelfb_pci_register,
-	.remove =	intelfb_pci_unregister,
-};
-
-/* Module description/parameters */
-MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
-	      "Sylvain Meyer <sylvain.meyer@worldonline.fr>");
-MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS
-		   " chipsets");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
-
-static bool accel       = 1;
-static int vram         = 4;
-static bool hwcursor    = 0;
-static bool mtrr        = 1;
-static bool fixed       = 0;
-static bool noinit      = 0;
-static bool noregister  = 0;
-static bool probeonly   = 0;
-static bool idonly      = 0;
-static int bailearly    = 0;
-static int voffset	= 48;
-static char *mode       = NULL;
-
-module_param(accel, bool, S_IRUGO);
-MODULE_PARM_DESC(accel, "Enable hardware acceleration");
-module_param(vram, int, S_IRUGO);
-MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
-module_param(voffset, int, S_IRUGO);
-MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
-module_param(hwcursor, bool, S_IRUGO);
-MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
-module_param(mtrr, bool, S_IRUGO);
-MODULE_PARM_DESC(mtrr, "Enable MTRR support");
-module_param(fixed, bool, S_IRUGO);
-MODULE_PARM_DESC(fixed, "Disable mode switching");
-module_param(noinit, bool, 0);
-MODULE_PARM_DESC(noinit, "Don't initialise graphics mode when loading");
-module_param(noregister, bool, 0);
-MODULE_PARM_DESC(noregister, "Don't register, just probe and exit (debug)");
-module_param(probeonly, bool, 0);
-MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");
-module_param(idonly, bool, 0);
-MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");
-module_param(bailearly, int, 0);
-MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
-module_param(mode, charp, S_IRUGO);
-MODULE_PARM_DESC(mode,
-		 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
-
-#ifndef MODULE
-#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
-#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
-#define OPT_STRVAL(opt, name) (opt + strlen(name))
-
-static __inline__ char * get_opt_string(const char *this_opt, const char *name)
-{
-	const char *p;
-	int i;
-	char *ret;
-
-	p = OPT_STRVAL(this_opt, name);
-	i = 0;
-	while (p[i] && p[i] != ' ' && p[i] != ',')
-		i++;
-	ret = kmalloc(i + 1, GFP_KERNEL);
-	if (ret) {
-		strncpy(ret, p, i);
-		ret[i] = '\0';
-	}
-	return ret;
-}
-
-static __inline__ int get_opt_int(const char *this_opt, const char *name,
-				  int *ret)
-{
-	if (!ret)
-		return 0;
-
-	if (!OPT_EQUAL(this_opt, name))
-		return 0;
-
-	*ret = OPT_INTVAL(this_opt, name);
-	return 1;
-}
-
-static __inline__ int get_opt_bool(const char *this_opt, const char *name,
-				   int *ret)
-{
-	if (!ret)
-		return 0;
-
-	if (OPT_EQUAL(this_opt, name)) {
-		if (this_opt[strlen(name)] == '=')
-			*ret = simple_strtoul(this_opt + strlen(name) + 1,
-					      NULL, 0);
-		else
-			*ret = 1;
-	} else {
-		if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
-			*ret = 0;
-		else
-			return 0;
-	}
-	return 1;
-}
-
-static int __init intelfb_setup(char *options)
-{
-	char *this_opt;
-
-	DBG_MSG("intelfb_setup\n");
-
-	if (!options || !*options) {
-		DBG_MSG("no options\n");
-		return 0;
-	} else
-		DBG_MSG("options: %s\n", options);
-
-	/*
-	 * These are the built-in options analogous to the module parameters
-	 * defined above.
-	 *
-	 * The syntax is:
-	 *
-	 *    video=intelfb:[mode][,<param>=<val>] ...
-	 *
-	 * e.g.,
-	 *
-	 *    video=intelfb:1024x768-16@75,accel=0
-	 */
-
-	while ((this_opt = strsep(&options, ","))) {
-		if (!*this_opt)
-			continue;
-		if (get_opt_bool(this_opt, "accel", &accel))
-			;
-		else if (get_opt_int(this_opt, "vram", &vram))
-			;
-		else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
-			;
-		else if (get_opt_bool(this_opt, "mtrr", &mtrr))
-			;
-		else if (get_opt_bool(this_opt, "fixed", &fixed))
-			;
-		else if (get_opt_bool(this_opt, "init", &noinit))
-			noinit = !noinit;
-		else if (OPT_EQUAL(this_opt, "mode="))
-			mode = get_opt_string(this_opt, "mode=");
-		else
-			mode = this_opt;
-	}
-
-	return 0;
-}
-
-#endif
-
-static int __init intelfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-#endif
-
-	DBG_MSG("intelfb_init\n");
-
-	INF_MSG("Framebuffer driver for "
-		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
-	INF_MSG("Version " INTELFB_VERSION "\n");
-
-	if (idonly)
-		return -ENODEV;
-
-#ifndef MODULE
-	if (fb_get_options("intelfb", &option))
-		return -ENODEV;
-	intelfb_setup(option);
-#endif
-
-	return pci_register_driver(&intelfb_driver);
-}
-
-static void __exit intelfb_exit(void)
-{
-	DBG_MSG("intelfb_exit\n");
-	pci_unregister_driver(&intelfb_driver);
-}
-
-module_init(intelfb_init);
-module_exit(intelfb_exit);
-
-/***************************************************************
- *                     mtrr support functions                  *
- ***************************************************************/
-
-#ifdef CONFIG_MTRR
-static inline void set_mtrr(struct intelfb_info *dinfo)
-{
-	dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,
-				   dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);
-	if (dinfo->mtrr_reg < 0) {
-		ERR_MSG("unable to set MTRR\n");
-		return;
-	}
-	dinfo->has_mtrr = 1;
-}
-static inline void unset_mtrr(struct intelfb_info *dinfo)
-{
-	if (dinfo->has_mtrr)
-		mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
-			 dinfo->aperture.size);
-}
-#else
-#define set_mtrr(x) WRN_MSG("MTRR is disabled in the kernel\n")
-
-#define unset_mtrr(x) do { } while (0)
-#endif /* CONFIG_MTRR */
-
-/***************************************************************
- *                        driver init / cleanup                *
- ***************************************************************/
-
-static void cleanup(struct intelfb_info *dinfo)
-{
-	DBG_MSG("cleanup\n");
-
-	if (!dinfo)
-		return;
-
-	intelfbhw_disable_irq(dinfo);
-
-	fb_dealloc_cmap(&dinfo->info->cmap);
-	kfree(dinfo->info->pixmap.addr);
-
-	if (dinfo->registered)
-		unregister_framebuffer(dinfo->info);
-
-	unset_mtrr(dinfo);
-
-	if (dinfo->fbmem_gart && dinfo->gtt_fb_mem) {
-		agp_unbind_memory(dinfo->gtt_fb_mem);
-		agp_free_memory(dinfo->gtt_fb_mem);
-	}
-	if (dinfo->gtt_cursor_mem) {
-		agp_unbind_memory(dinfo->gtt_cursor_mem);
-		agp_free_memory(dinfo->gtt_cursor_mem);
-	}
-	if (dinfo->gtt_ring_mem) {
-		agp_unbind_memory(dinfo->gtt_ring_mem);
-		agp_free_memory(dinfo->gtt_ring_mem);
-	}
-
-#ifdef CONFIG_FB_INTEL_I2C
-	/* un-register I2C bus */
-	intelfb_delete_i2c_busses(dinfo);
-#endif
-
-	if (dinfo->mmio_base)
-		iounmap((void __iomem *)dinfo->mmio_base);
-	if (dinfo->aperture.virtual)
-		iounmap((void __iomem *)dinfo->aperture.virtual);
-
-	if (dinfo->flag & INTELFB_MMIO_ACQUIRED)
-		release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
-	if (dinfo->flag & INTELFB_FB_ACQUIRED)
-		release_mem_region(dinfo->aperture.physical,
-				   dinfo->aperture.size);
-	framebuffer_release(dinfo->info);
-}
-
-#define bailout(dinfo) do {						\
-	DBG_MSG("bailout\n");						\
-	cleanup(dinfo);							\
-	INF_MSG("Not going to register framebuffer, exiting...\n");	\
-	return -ENODEV;							\
-} while (0)
-
-
-static int intelfb_pci_register(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
-{
-	struct fb_info *info;
-	struct intelfb_info *dinfo;
-	int i, err, dvo;
-	int aperture_size, stolen_size;
-	struct agp_kern_info gtt_info;
-	int agp_memtype;
-	const char *s;
-	struct agp_bridge_data *bridge;
-	int aperture_bar = 0;
-	int mmio_bar = 1;
-	int offset;
-
-	DBG_MSG("intelfb_pci_register\n");
-
-	num_registered++;
-	if (num_registered != 1) {
-		ERR_MSG("Attempted to register %d devices "
-			"(should be only 1).\n", num_registered);
-		return -ENODEV;
-	}
-
-	info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);
-	if (!info) {
-		ERR_MSG("Could not allocate memory for intelfb_info.\n");
-		return -ENODEV;
-	}
-	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
-		ERR_MSG("Could not allocate cmap for intelfb_info.\n");
-		goto err_out_cmap;
-	}
-
-	dinfo = info->par;
-	dinfo->info  = info;
-	dinfo->fbops = &intel_fb_ops;
-	dinfo->pdev  = pdev;
-
-	/* Reserve pixmap space. */
-	info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);
-	if (info->pixmap.addr == NULL) {
-		ERR_MSG("Cannot reserve pixmap memory.\n");
-		goto err_out_pixmap;
-	}
-
-	/* set early this option because it could be changed by tv encoder
-	   driver */
-	dinfo->fixed_mode = fixed;
-
-	/* Enable device. */
-	if ((err = pci_enable_device(pdev))) {
-		ERR_MSG("Cannot enable device.\n");
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	/* Set base addresses. */
-	if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
-	    (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
-	    (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
-	    (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
-	    (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
-	    (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
-	    (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
-
-		aperture_bar = 2;
-		mmio_bar = 0;
-	}
-	dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
-	dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);
-	dinfo->mmio_base_phys    = pci_resource_start(pdev, mmio_bar);
-	DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
-		(unsigned long long)pci_resource_start(pdev, aperture_bar),
-		(unsigned long long)pci_resource_len(pdev, aperture_bar),
-		(unsigned long long)pci_resource_start(pdev, mmio_bar),
-		(unsigned long long)pci_resource_len(pdev, mmio_bar));
-
-	/* Reserve the fb and MMIO regions */
-	if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
-				INTELFB_MODULE_NAME)) {
-		ERR_MSG("Cannot reserve FB region.\n");
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	dinfo->flag |= INTELFB_FB_ACQUIRED;
-
-	if (!request_mem_region(dinfo->mmio_base_phys,
-				INTEL_REG_SIZE,
-				INTELFB_MODULE_NAME)) {
-		ERR_MSG("Cannot reserve MMIO region.\n");
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	dinfo->flag |= INTELFB_MMIO_ACQUIRED;
-
-	/* Get the chipset info. */
-	dinfo->pci_chipset = pdev->device;
-
-	if (intelfbhw_get_chipset(pdev, dinfo)) {
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) {
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "
-		"stolen memory %dkB\n",
-		pdev->bus->number, PCI_SLOT(pdev->devfn),
-		PCI_FUNC(pdev->devfn), dinfo->name,
-		BtoMB(aperture_size), BtoKB(stolen_size));
-
-	/* Set these from the options. */
-	dinfo->accel    = accel;
-	dinfo->hwcursor = hwcursor;
-
-	if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {
-		INF_MSG("Acceleration is not supported for the %s chipset.\n",
-			dinfo->name);
-		dinfo->accel = 0;
-	}
-
-	/* Framebuffer parameters - Use all the stolen memory if >= vram */
-	if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
-		dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
-		dinfo->fbmem_gart = 0;
-	} else {
-		dinfo->fb.size =  MB(vram);
-		dinfo->fbmem_gart = 1;
-	}
-
-	/* Allocate space for the ring buffer and HW cursor if enabled. */
-	if (dinfo->accel) {
-		dinfo->ring.size = RINGBUFFER_SIZE;
-		dinfo->ring_tail_mask = dinfo->ring.size - 1;
-	}
-	if (dinfo->hwcursor)
-		dinfo->cursor.size = HW_CURSOR_SIZE;
-
-	/* Use agpgart to manage the GATT */
-	if (!(bridge = agp_backend_acquire(pdev))) {
-		ERR_MSG("cannot acquire agp\n");
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	/* get the current gatt info */
-	if (agp_copy_info(bridge, &gtt_info)) {
-		ERR_MSG("cannot get agp info\n");
-		agp_backend_release(bridge);
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	if (MB(voffset) < stolen_size)
-		offset = (stolen_size >> 12);
-	else
-		offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
-
-	/* set the mem offsets - set them after the already used pages */
-	if (dinfo->accel)
-		dinfo->ring.offset = offset + gtt_info.current_memory;
-	if (dinfo->hwcursor)
-		dinfo->cursor.offset = offset +
-			+ gtt_info.current_memory + (dinfo->ring.size >> 12);
-	if (dinfo->fbmem_gart)
-		dinfo->fb.offset = offset +
-			+ gtt_info.current_memory + (dinfo->ring.size >> 12)
-			+ (dinfo->cursor.size >> 12);
-
-	/* Allocate memories (which aren't stolen) */
-	/* Map the fb and MMIO regions */
-	/* ioremap only up to the end of used aperture */
-	dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
-		(dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
-		 + dinfo->fb.size);
-	if (!dinfo->aperture.virtual) {
-		ERR_MSG("Cannot remap FB region.\n");
-		agp_backend_release(bridge);
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	dinfo->mmio_base =
-		(u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
-					      INTEL_REG_SIZE);
-	if (!dinfo->mmio_base) {
-		ERR_MSG("Cannot remap MMIO region.\n");
-		agp_backend_release(bridge);
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	if (dinfo->accel) {
-		if (!(dinfo->gtt_ring_mem =
-		      agp_allocate_memory(bridge, dinfo->ring.size >> 12,
-					  AGP_NORMAL_MEMORY))) {
-			ERR_MSG("cannot allocate ring buffer memory\n");
-			agp_backend_release(bridge);
-			cleanup(dinfo);
-			return -ENOMEM;
-		}
-		if (agp_bind_memory(dinfo->gtt_ring_mem,
-				    dinfo->ring.offset)) {
-			ERR_MSG("cannot bind ring buffer memory\n");
-			agp_backend_release(bridge);
-			cleanup(dinfo);
-			return -EBUSY;
-		}
-		dinfo->ring.physical = dinfo->aperture.physical
-			+ (dinfo->ring.offset << 12);
-		dinfo->ring.virtual  = dinfo->aperture.virtual
-			+ (dinfo->ring.offset << 12);
-		dinfo->ring_head = 0;
-	}
-	if (dinfo->hwcursor) {
-		agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
-			: AGP_NORMAL_MEMORY;
-		if (!(dinfo->gtt_cursor_mem =
-		      agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
-					  agp_memtype))) {
-			ERR_MSG("cannot allocate cursor memory\n");
-			agp_backend_release(bridge);
-			cleanup(dinfo);
-			return -ENOMEM;
-		}
-		if (agp_bind_memory(dinfo->gtt_cursor_mem,
-				    dinfo->cursor.offset)) {
-			ERR_MSG("cannot bind cursor memory\n");
-			agp_backend_release(bridge);
-			cleanup(dinfo);
-			return -EBUSY;
-		}
-		if (dinfo->mobile)
-			dinfo->cursor.physical
-				= dinfo->gtt_cursor_mem->physical;
-		else
-			dinfo->cursor.physical = dinfo->aperture.physical
-				+ (dinfo->cursor.offset << 12);
-		dinfo->cursor.virtual = dinfo->aperture.virtual
-			+ (dinfo->cursor.offset << 12);
-	}
-	if (dinfo->fbmem_gart) {
-		if (!(dinfo->gtt_fb_mem =
-		      agp_allocate_memory(bridge, dinfo->fb.size >> 12,
-					  AGP_NORMAL_MEMORY))) {
-			WRN_MSG("cannot allocate framebuffer memory - use "
-				"the stolen one\n");
-			dinfo->fbmem_gart = 0;
-		}
-		if (agp_bind_memory(dinfo->gtt_fb_mem,
-				    dinfo->fb.offset)) {
-			WRN_MSG("cannot bind framebuffer memory - use "
-				"the stolen one\n");
-			dinfo->fbmem_gart = 0;
-		}
-	}
-
-	/* update framebuffer memory parameters */
-	if (!dinfo->fbmem_gart)
-		dinfo->fb.offset = 0;   /* starts at offset 0 */
-	dinfo->fb.physical = dinfo->aperture.physical
-		+ (dinfo->fb.offset << 12);
-	dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);
-	dinfo->fb_start = dinfo->fb.offset << 12;
-
-	/* release agpgart */
-	agp_backend_release(bridge);
-
-	if (mtrr)
-		set_mtrr(dinfo);
-
-	DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",
-		dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
-		dinfo->fb.virtual);
-	DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",
-		dinfo->mmio_base_phys, INTEL_REG_SIZE,
-		dinfo->mmio_base);
-	DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",
-		dinfo->ring.physical, dinfo->ring.size,
-		dinfo->ring.virtual);
-	DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",
-		dinfo->cursor.physical, dinfo->cursor.size,
-		dinfo->cursor.virtual, dinfo->cursor.offset,
-		dinfo->cursor.physical);
-
-	DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
-		"noinit = %d\n", vram, accel, hwcursor, fixed, noinit);
-	DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");
-
-	if (probeonly)
-		bailout(dinfo);
-
-	/*
-	 * Check if the LVDS port or any DVO ports are enabled.  If so,
-	 * don't allow mode switching
-	 */
-	dvo = intelfbhw_check_non_crt(dinfo);
-	if (dvo) {
-		dinfo->fixed_mode = 1;
-		WRN_MSG("Non-CRT device is enabled ( ");
-		i = 0;
-		while (dvo) {
-			if (dvo & 1) {
-				s = intelfbhw_dvo_to_string(1 << i);
-				if (s)
-					printk("%s ", s);
-			}
-			dvo >>= 1;
-			++i;
-		}
-		printk(").  Disabling mode switching.\n");
-	}
-
-	if (bailearly == 1)
-		bailout(dinfo);
-
-	if (FIXED_MODE(dinfo) &&
-	    screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) {
-		ERR_MSG("Video mode must be programmed at boot time.\n");
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	if (bailearly == 2)
-		bailout(dinfo);
-
-	/* Initialise dinfo and related data. */
-	/* If an initial mode was programmed at boot time, get its details. */
-	if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
-		get_initial_mode(dinfo);
-
-	if (bailearly == 3)
-		bailout(dinfo);
-
-	if (FIXED_MODE(dinfo))	/* remap fb address */
-		update_dinfo(dinfo, &dinfo->initial_var);
-
-	if (bailearly == 4)
-		bailout(dinfo);
-
-
-	if (intelfb_set_fbinfo(dinfo)) {
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	if (bailearly == 5)
-		bailout(dinfo);
-
-#ifdef CONFIG_FB_INTEL_I2C
-	/* register I2C bus */
-	intelfb_create_i2c_busses(dinfo);
-#endif
-
-	if (bailearly == 6)
-		bailout(dinfo);
-
-	pci_set_drvdata(pdev, dinfo);
-
-	/* Save the initial register state. */
-	i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,
-				    bailearly > 6 ? bailearly - 6 : 0);
-	if (i != 0) {
-		DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);
-		bailout(dinfo);
-	}
-
-	intelfbhw_print_hw_state(dinfo, &dinfo->save_state);
-
-	if (bailearly == 18)
-		bailout(dinfo);
-
-	/* read active pipe */
-	dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
-
-	/* Cursor initialisation */
-	if (dinfo->hwcursor) {
-		intelfbhw_cursor_init(dinfo);
-		intelfbhw_cursor_reset(dinfo);
-	}
-
-	if (bailearly == 19)
-		bailout(dinfo);
-
-	/* 2d acceleration init */
-	if (dinfo->accel)
-		intelfbhw_2d_start(dinfo);
-
-	if (bailearly == 20)
-		bailout(dinfo);
-
-	if (noregister)
-		bailout(dinfo);
-
-	if (register_framebuffer(dinfo->info) < 0) {
-		ERR_MSG("Cannot register framebuffer.\n");
-		cleanup(dinfo);
-		return -ENODEV;
-	}
-
-	dinfo->registered = 1;
-	dinfo->open = 0;
-
-	init_waitqueue_head(&dinfo->vsync.wait);
-	spin_lock_init(&dinfo->int_lock);
-	dinfo->irq_flags = 0;
-	dinfo->vsync.pan_display = 0;
-	dinfo->vsync.pan_offset = 0;
-
-	return 0;
-
-err_out_pixmap:
-	fb_dealloc_cmap(&info->cmap);
-err_out_cmap:
-	framebuffer_release(info);
-	return -ENODEV;
-}
-
-static void intelfb_pci_unregister(struct pci_dev *pdev)
-{
-	struct intelfb_info *dinfo = pci_get_drvdata(pdev);
-
-	DBG_MSG("intelfb_pci_unregister\n");
-
-	if (!dinfo)
-		return;
-
-	cleanup(dinfo);
-}
-
-/***************************************************************
- *                       helper functions                      *
- ***************************************************************/
-
-int __inline__ intelfb_var_to_depth(const struct fb_var_screeninfo *var)
-{
-	DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
-		var->bits_per_pixel, var->green.length);
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		return (var->green.length == 6) ? 16 : 15;
-	case 32:
-		return 24;
-	default:
-		return var->bits_per_pixel;
-	}
-}
-
-
-static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
-{
-	int xtot = var->xres + var->left_margin + var->right_margin +
-		   var->hsync_len;
-	int ytot = var->yres + var->upper_margin + var->lower_margin +
-		   var->vsync_len;
-
-	return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
-}
-
-/***************************************************************
- *                Various intialisation functions              *
- ***************************************************************/
-
-static void get_initial_mode(struct intelfb_info *dinfo)
-{
-	struct fb_var_screeninfo *var;
-	int xtot, ytot;
-
-	DBG_MSG("get_initial_mode\n");
-
-	dinfo->initial_vga = 1;
-	dinfo->initial_fb_base = screen_info.lfb_base;
-	dinfo->initial_video_ram = screen_info.lfb_size * KB(64);
-	dinfo->initial_pitch = screen_info.lfb_linelength;
-
-	var = &dinfo->initial_var;
-	memset(var, 0, sizeof(*var));
-	var->xres = screen_info.lfb_width;
-	var->yres = screen_info.lfb_height;
-	var->bits_per_pixel = screen_info.lfb_depth;
-	switch (screen_info.lfb_depth) {
-	case 15:
-		var->bits_per_pixel = 16;
-		break;
-	case 24:
-		var->bits_per_pixel = 32;
-		break;
-	}
-
-	DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",
-		dinfo->initial_fb_base, dinfo->initial_video_ram,
-		BtoKB(dinfo->initial_video_ram));
-
-	DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",
-		var->xres, var->yres, var->bits_per_pixel,
-		dinfo->initial_pitch);
-
-	/* Dummy timing values (assume 60Hz) */
-	var->left_margin = (var->xres / 8) & 0xf8;
-	var->right_margin = 32;
-	var->upper_margin = 16;
-	var->lower_margin = 4;
-	var->hsync_len = (var->xres / 8) & 0xf8;
-	var->vsync_len = 4;
-
-	xtot = var->xres + var->left_margin +
-		var->right_margin + var->hsync_len;
-	ytot = var->yres + var->upper_margin +
-		var->lower_margin + var->vsync_len;
-	var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;
-
-	var->height = -1;
-	var->width = -1;
-
-	if (var->bits_per_pixel > 8) {
-		var->red.offset = screen_info.red_pos;
-		var->red.length = screen_info.red_size;
-		var->green.offset = screen_info.green_pos;
-		var->green.length = screen_info.green_size;
-		var->blue.offset = screen_info.blue_pos;
-		var->blue.length = screen_info.blue_size;
-		var->transp.offset = screen_info.rsvd_pos;
-		var->transp.length = screen_info.rsvd_size;
-	} else {
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-	}
-}
-
-static int intelfb_init_var(struct intelfb_info *dinfo)
-{
-	struct fb_var_screeninfo *var;
-	int msrc = 0;
-
-	DBG_MSG("intelfb_init_var\n");
-
-	var = &dinfo->info->var;
-	if (FIXED_MODE(dinfo)) {
-	        memcpy(var, &dinfo->initial_var,
-		       sizeof(struct fb_var_screeninfo));
-		msrc = 5;
-	} else {
-		const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
-		u8 *edid_d = NULL;
-
-		if (edid_s) {
-			edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);
-
-			if (edid_d) {
-				fb_edid_to_monspecs(edid_d,
-						    &dinfo->info->monspecs);
-				kfree(edid_d);
-			}
-		}
-
-		if (mode) {
-			printk("intelfb: Looking for mode in private "
-			       "database\n");
-			msrc = fb_find_mode(var, dinfo->info, mode,
-					    dinfo->info->monspecs.modedb,
-					    dinfo->info->monspecs.modedb_len,
-					    NULL, 0);
-
-			if (msrc && msrc > 1) {
-				printk("intelfb: No mode in private database, "
-				       "intelfb: looking for mode in global "
-				       "database ");
-				msrc = fb_find_mode(var, dinfo->info, mode,
-						    NULL, 0, NULL, 0);
-
-				if (msrc)
-					msrc |= 8;
-			}
-
-		}
-
-		if (!msrc)
-			msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
-					    NULL, 0, NULL, 0);
-	}
-
-	if (!msrc) {
-		ERR_MSG("Cannot find a suitable video mode.\n");
-		return 1;
-	}
-
-	INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres,
-		var->bits_per_pixel, var_to_refresh(var));
-
-	DBG_MSG("Initial video mode is from %d.\n", msrc);
-
-#if ALLOCATE_FOR_PANNING
-	/* Allow use of half of the video ram for panning */
-	var->xres_virtual = var->xres;
-	var->yres_virtual =
-		dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres);
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-#else
-	var->yres_virtual = var->yres;
-#endif
-
-	if (dinfo->accel)
-		var->accel_flags |= FB_ACCELF_TEXT;
-	else
-		var->accel_flags &= ~FB_ACCELF_TEXT;
-
-	return 0;
-}
-
-static int intelfb_set_fbinfo(struct intelfb_info *dinfo)
-{
-	struct fb_info *info = dinfo->info;
-
-	DBG_MSG("intelfb_set_fbinfo\n");
-
-	info->flags = FBINFO_FLAG_DEFAULT;
-	info->fbops = &intel_fb_ops;
-	info->pseudo_palette = dinfo->pseudo_palette;
-
-	info->pixmap.size = 64*1024;
-	info->pixmap.buf_align = 8;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-	if (intelfb_init_var(dinfo))
-		return 1;
-
-	info->pixmap.scan_align = 1;
-	strcpy(info->fix.id, dinfo->name);
-	info->fix.smem_start = dinfo->fb.physical;
-	info->fix.smem_len = dinfo->fb.size;
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux = 0;
-	info->fix.xpanstep = 8;
-	info->fix.ypanstep = 1;
-	info->fix.ywrapstep = 0;
-	info->fix.mmio_start = dinfo->mmio_base_phys;
-	info->fix.mmio_len = INTEL_REG_SIZE;
-	info->fix.accel = FB_ACCEL_I830;
-	update_dinfo(dinfo, &info->var);
-
-	return 0;
-}
-
-/* Update dinfo to match the active video mode. */
-static void update_dinfo(struct intelfb_info *dinfo,
-			 struct fb_var_screeninfo *var)
-{
-	DBG_MSG("update_dinfo\n");
-
-	dinfo->bpp = var->bits_per_pixel;
-	dinfo->depth = intelfb_var_to_depth(var);
-	dinfo->xres = var->xres;
-	dinfo->yres = var->xres;
-	dinfo->pixclock = var->pixclock;
-
-	dinfo->info->fix.visual = dinfo->visual;
-	dinfo->info->fix.line_length = dinfo->pitch;
-
-	switch (dinfo->bpp) {
-	case 8:
-		dinfo->visual = FB_VISUAL_PSEUDOCOLOR;
-		dinfo->pitch = var->xres_virtual;
-		break;
-	case 16:
-		dinfo->visual = FB_VISUAL_TRUECOLOR;
-		dinfo->pitch = var->xres_virtual * 2;
-		break;
-	case 32:
-		dinfo->visual = FB_VISUAL_TRUECOLOR;
-		dinfo->pitch = var->xres_virtual * 4;
-		break;
-	}
-
-	/* Make sure the line length is a aligned correctly. */
-	if (IS_I9XX(dinfo))
-		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
-	else
-		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
-
-	if (FIXED_MODE(dinfo))
-		dinfo->pitch = dinfo->initial_pitch;
-
-	dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual;
-	dinfo->info->fix.line_length = dinfo->pitch;
-	dinfo->info->fix.visual = dinfo->visual;
-}
-
-/* fbops functions */
-
-/***************************************************************
- *                       fbdev interface                       *
- ***************************************************************/
-
-static int intelfb_open(struct fb_info *info, int user)
-{
-	struct intelfb_info *dinfo = GET_DINFO(info);
-
-	if (user)
-		dinfo->open++;
-
-	return 0;
-}
-
-static int intelfb_release(struct fb_info *info, int user)
-{
-	struct intelfb_info *dinfo = GET_DINFO(info);
-
-	if (user) {
-		dinfo->open--;
-		msleep(1);
-		if (!dinfo->open)
-			intelfbhw_disable_irq(dinfo);
-	}
-
-	return 0;
-}
-
-static int intelfb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	int change_var = 0;
-	struct fb_var_screeninfo v;
-	struct intelfb_info *dinfo;
-	static int first = 1;
-	int i;
-	/* Good pitches to allow tiling.  Don't care about pitches < 1024. */
-	static const int pitches[] = {
-		128 * 8,
-		128 * 16,
-		128 * 32,
-		128 * 64,
-		0
-	};
-
-	DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
-
-	dinfo = GET_DINFO(info);
-
-	/* update the pitch */
-	if (intelfbhw_validate_mode(dinfo, var) != 0)
-		return -EINVAL;
-
-	v = *var;
-
-	for (i = 0; pitches[i] != 0; i++) {
-		if (pitches[i] >= v.xres_virtual) {
-			v.xres_virtual = pitches[i];
-			break;
-		}
-	}
-
-	/* Check for a supported bpp. */
-	if (v.bits_per_pixel <= 8)
-		v.bits_per_pixel = 8;
-	else if (v.bits_per_pixel <= 16) {
-		if (v.bits_per_pixel == 16)
-			v.green.length = 6;
-		v.bits_per_pixel = 16;
-	} else if (v.bits_per_pixel <= 32)
-		v.bits_per_pixel = 32;
-	else
-		return -EINVAL;
-
-	change_var = ((info->var.xres != var->xres) ||
-		      (info->var.yres != var->yres) ||
-		      (info->var.xres_virtual != var->xres_virtual) ||
-		      (info->var.yres_virtual != var->yres_virtual) ||
-		      (info->var.bits_per_pixel != var->bits_per_pixel) ||
-		      memcmp(&info->var.red, &var->red, sizeof(var->red)) ||
-		      memcmp(&info->var.green, &var->green,
-			     sizeof(var->green)) ||
-		      memcmp(&info->var.blue, &var->blue, sizeof(var->blue)));
-
-	if (FIXED_MODE(dinfo) &&
-	    (change_var ||
-	     var->yres_virtual > dinfo->initial_var.yres_virtual ||
-	     var->yres_virtual < dinfo->initial_var.yres ||
-	     var->xoffset || var->nonstd)) {
-		if (first) {
-			ERR_MSG("Changing the video mode is not supported.\n");
-			first = 0;
-		}
-		return -EINVAL;
-	}
-
-	switch (intelfb_var_to_depth(&v)) {
-	case 8:
-		v.red.offset = v.green.offset = v.blue.offset = 0;
-		v.red.length = v.green.length = v.blue.length = 8;
-		v.transp.offset = v.transp.length = 0;
-		break;
-	case 15:
-		v.red.offset = 10;
-		v.green.offset = 5;
-		v.blue.offset = 0;
-		v.red.length = v.green.length = v.blue.length = 5;
-		v.transp.offset = v.transp.length = 0;
-		break;
-	case 16:
-		v.red.offset = 11;
-		v.green.offset = 5;
-		v.blue.offset = 0;
-		v.red.length = 5;
-		v.green.length = 6;
-		v.blue.length = 5;
-		v.transp.offset = v.transp.length = 0;
-		break;
-	case 24:
-		v.red.offset = 16;
-		v.green.offset = 8;
-		v.blue.offset = 0;
-		v.red.length = v.green.length = v.blue.length = 8;
-		v.transp.offset = v.transp.length = 0;
-		break;
-	case 32:
-		v.red.offset = 16;
-		v.green.offset = 8;
-		v.blue.offset = 0;
-		v.red.length = v.green.length = v.blue.length = 8;
-		v.transp.offset = 24;
-		v.transp.length = 8;
-		break;
-	}
-
-	if (v.xoffset < 0)
-		v.xoffset = 0;
-	if (v.yoffset < 0)
-		v.yoffset = 0;
-
-	if (v.xoffset > v.xres_virtual - v.xres)
-		v.xoffset = v.xres_virtual - v.xres;
-	if (v.yoffset > v.yres_virtual - v.yres)
-		v.yoffset = v.yres_virtual - v.yres;
-
-	v.red.msb_right = v.green.msb_right = v.blue.msb_right =
-			  v.transp.msb_right = 0;
-
-        *var = v;
-
-	return 0;
-}
-
-static int intelfb_set_par(struct fb_info *info)
-{
-	struct intelfb_hwstate *hw;
-        struct intelfb_info *dinfo = GET_DINFO(info);
-
-	if (FIXED_MODE(dinfo)) {
-		ERR_MSG("Changing the video mode is not supported.\n");
-		return -EINVAL;
-	}
-
-	hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
-	if (!hw)
-		return -ENOMEM;
-
-	DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
-		info->var.yres, info->var.bits_per_pixel);
-
-	/*
-	 * Disable VCO prior to timing register change.
-	 */
-	OUTREG(DPLL_A, INREG(DPLL_A) & ~DPLL_VCO_ENABLE);
-
-	intelfb_blank(FB_BLANK_POWERDOWN, info);
-
-	if (ACCEL(dinfo, info))
-		intelfbhw_2d_stop(dinfo);
-
-	memcpy(hw, &dinfo->save_state, sizeof(*hw));
-	if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
-		goto invalid_mode;
-	if (intelfbhw_program_mode(dinfo, hw, 0))
-		goto invalid_mode;
-
-#if REGDUMP > 0
-	intelfbhw_read_hw_state(dinfo, hw, 0);
-	intelfbhw_print_hw_state(dinfo, hw);
-#endif
-
-	update_dinfo(dinfo, &info->var);
-
-	if (ACCEL(dinfo, info))
-		intelfbhw_2d_start(dinfo);
-
-	intelfb_pan_display(&info->var, info);
-
-	intelfb_blank(FB_BLANK_UNBLANK, info);
-
-	if (ACCEL(dinfo, info)) {
-		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
-		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
-		FBINFO_HWACCEL_IMAGEBLIT;
-	} else
-		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-
-	kfree(hw);
-	return 0;
-invalid_mode:
-	kfree(hw);
-	return -EINVAL;
-}
-
-static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info *info)
-{
-	struct intelfb_info *dinfo = GET_DINFO(info);
-
-#if VERBOSE > 0
-	DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);
-#endif
-
-	if (regno > 255)
-		return 1;
-
-	if (dinfo->depth == 8) {
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-
-		intelfbhw_setcolreg(dinfo, regno, red, green, blue,
-				    transp);
-	}
-
-	if (regno < 16) {
-		switch (dinfo->depth) {
-		case 15:
-			dinfo->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
-				((green & 0xf800) >>  6) |
-				((blue & 0xf800) >> 11);
-			break;
-		case 16:
-			dinfo->pseudo_palette[regno] = (red & 0xf800) |
-				((green & 0xfc00) >>  5) |
-				((blue  & 0xf800) >> 11);
-			break;
-		case 24:
-			dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
-				(green & 0xff00) |
-				((blue  & 0xff00) >> 8);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static int intelfb_blank(int blank, struct fb_info *info)
-{
-	intelfbhw_do_blank(blank, info);
-	return 0;
-}
-
-static int intelfb_pan_display(struct fb_var_screeninfo *var,
-			       struct fb_info *info)
-{
-	intelfbhw_pan_display(var, info);
-	return 0;
-}
-
-/* When/if we have our own ioctls. */
-static int intelfb_ioctl(struct fb_info *info, unsigned int cmd,
-			 unsigned long arg)
-{
-	int retval = 0;
-	struct intelfb_info *dinfo = GET_DINFO(info);
-	u32 pipe = 0;
-
-	switch (cmd) {
-		case FBIO_WAITFORVSYNC:
-			if (get_user(pipe, (__u32 __user *)arg))
-				return -EFAULT;
-
-			retval = intelfbhw_wait_for_vsync(dinfo, pipe);
-			break;
-		default:
-			break;
-	}
-
-	return retval;
-}
-
-static void intelfb_fillrect (struct fb_info *info,
-			      const struct fb_fillrect *rect)
-{
-        struct intelfb_info *dinfo = GET_DINFO(info);
-	u32 rop, color;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfb_fillrect\n");
-#endif
-
-	if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	if (rect->rop == ROP_COPY)
-		rop = PAT_ROP_GXCOPY;
-	else /* ROP_XOR */
-		rop = PAT_ROP_GXXOR;
-
-	if (dinfo->depth != 8)
-		color = dinfo->pseudo_palette[rect->color];
-	else
-		color = rect->color;
-
-	intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy,
-			      rect->width, rect->height, color,
-			      dinfo->pitch, info->var.bits_per_pixel,
-			      rop);
-}
-
-static void intelfb_copyarea(struct fb_info *info,
-			     const struct fb_copyarea *region)
-{
-        struct intelfb_info *dinfo = GET_DINFO(info);
-
-#if VERBOSE > 0
-	DBG_MSG("intelfb_copyarea\n");
-#endif
-
-	if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
-		cfb_copyarea(info, region);
-		return;
-	}
-
-	intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
-			    region->dy, region->width, region->height,
-			    dinfo->pitch, info->var.bits_per_pixel);
-}
-
-static void intelfb_imageblit(struct fb_info *info,
-			      const struct fb_image *image)
-{
-        struct intelfb_info *dinfo = GET_DINFO(info);
-	u32 fgcolor, bgcolor;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfb_imageblit\n");
-#endif
-
-	if (!ACCEL(dinfo, info) || dinfo->depth == 4
-	    || image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	if (dinfo->depth != 8) {
-		fgcolor = dinfo->pseudo_palette[image->fg_color];
-		bgcolor = dinfo->pseudo_palette[image->bg_color];
-	} else {
-		fgcolor = image->fg_color;
-		bgcolor = image->bg_color;
-	}
-
-	if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width,
-				    image->height, image->data,
-				    image->dx, image->dy,
-				    dinfo->pitch, info->var.bits_per_pixel)) {
-		cfb_imageblit(info, image);
-		return;
-	}
-}
-
-static int intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-        struct intelfb_info *dinfo = GET_DINFO(info);
-	u32 physical;
-#if VERBOSE > 0
-	DBG_MSG("intelfb_cursor\n");
-#endif
-
-	if (!dinfo->hwcursor)
-		return -ENODEV;
-
-	intelfbhw_cursor_hide(dinfo);
-
-	/* If XFree killed the cursor - restore it */
-	physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
-		   (dinfo->cursor.offset << 12);
-
-	if (INREG(CURSOR_A_BASEADDR) != physical) {
-		u32 fg, bg;
-
-		DBG_MSG("the cursor was killed - restore it !!\n");
-		DBG_MSG("size %d, %d   pos %d, %d\n",
-			cursor->image.width, cursor->image.height,
-			cursor->image.dx, cursor->image.dy);
-
-		intelfbhw_cursor_init(dinfo);
-		intelfbhw_cursor_reset(dinfo);
-		intelfbhw_cursor_setpos(dinfo, cursor->image.dx,
-					cursor->image.dy);
-
-		if (dinfo->depth != 8) {
-			fg =dinfo->pseudo_palette[cursor->image.fg_color];
-			bg =dinfo->pseudo_palette[cursor->image.bg_color];
-		} else {
-			fg = cursor->image.fg_color;
-			bg = cursor->image.bg_color;
-		}
-		intelfbhw_cursor_setcolor(dinfo, bg, fg);
-		intelfbhw_cursor_load(dinfo, cursor->image.width,
-				      cursor->image.height,
-				      dinfo->cursor_src);
-
-		if (cursor->enable)
-			intelfbhw_cursor_show(dinfo);
-		return 0;
-	}
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		u32 dx, dy;
-
-		dx = cursor->image.dx - info->var.xoffset;
-		dy = cursor->image.dy - info->var.yoffset;
-
-		intelfbhw_cursor_setpos(dinfo, dx, dy);
-	}
-
-	if (cursor->set & FB_CUR_SETSIZE) {
-		if (cursor->image.width > 64 || cursor->image.height > 64)
-			return -ENXIO;
-
-		intelfbhw_cursor_reset(dinfo);
-	}
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		u32 fg, bg;
-
-		if (dinfo->depth != 8) {
-			fg = dinfo->pseudo_palette[cursor->image.fg_color];
-			bg = dinfo->pseudo_palette[cursor->image.bg_color];
-		} else {
-			fg = cursor->image.fg_color;
-			bg = cursor->image.bg_color;
-		}
-
-		intelfbhw_cursor_setcolor(dinfo, bg, fg);
-	}
-
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
-		u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8);
-		u32 size = s_pitch * cursor->image.height;
-		u8 *dat = (u8 *) cursor->image.data;
-		u8 *msk = (u8 *) cursor->mask;
-		u8 src[64];
-		u32 i;
-
-		if (cursor->image.depth != 1)
-			return -ENXIO;
-
-		switch (cursor->rop) {
-		case ROP_XOR:
-			for (i = 0; i < size; i++)
-				src[i] = dat[i] ^ msk[i];
-			break;
-		case ROP_COPY:
-		default:
-			for (i = 0; i < size; i++)
-				src[i] = dat[i] & msk[i];
-			break;
-		}
-
-		/* save the bitmap to restore it when XFree will
-		   make the cursor dirty */
-		memcpy(dinfo->cursor_src, src, size);
-
-		intelfbhw_cursor_load(dinfo, cursor->image.width,
-				      cursor->image.height, src);
-	}
-
-	if (cursor->enable)
-		intelfbhw_cursor_show(dinfo);
-
-	return 0;
-}
-
-static int intelfb_sync(struct fb_info *info)
-{
-        struct intelfb_info *dinfo = GET_DINFO(info);
-
-#if VERBOSE > 0
-	DBG_MSG("intelfb_sync\n");
-#endif
-
-	if (dinfo->ring_lockup)
-		return 0;
-
-	intelfbhw_do_sync(dinfo);
-	return 0;
-}
-
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
deleted file mode 100644
index fbad61da359f..000000000000
--- a/drivers/video/intelfb/intelfbhw.c
+++ /dev/null
@@ -1,2121 +0,0 @@
-/*
- * intelfb
- *
- * Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
- *
- * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
- *                   2004 Sylvain Meyer
- *
- * This driver consists of two parts.  The first part (intelfbdrv.c) provides
- * the basic fbdev interfaces, is derived in part from the radeonfb and
- * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c)
- * provides the code to program the hardware.  Most of it is derived from
- * the i810/i830 XFree86 driver.  The HW-specific code is covered here
- * under a dual license (GPL and MIT/XFree86 license).
- *
- * Author: David Dawes
- *
- */
-
-/* $DHD: intelfb/intelfbhw.c,v 1.9 2003/06/27 15:06:25 dawes Exp $ */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-
-#include "intelfb.h"
-#include "intelfbhw.h"
-
-struct pll_min_max {
-	int min_m, max_m, min_m1, max_m1;
-	int min_m2, max_m2, min_n, max_n;
-	int min_p, max_p, min_p1, max_p1;
-	int min_vco, max_vco, p_transition_clk, ref_clk;
-	int p_inc_lo, p_inc_hi;
-};
-
-#define PLLS_I8xx 0
-#define PLLS_I9xx 1
-#define PLLS_MAX 2
-
-static struct pll_min_max plls[PLLS_MAX] = {
-	{ 108, 140, 18, 26,
-	  6, 16, 3, 16,
-	  4, 128, 0, 31,
-	  930000, 1400000, 165000, 48000,
-	  4, 2 },		/* I8xx */
-
-	{ 75, 120, 10, 20,
-	  5, 9, 4, 7,
-	  5, 80, 1, 8,
-	  1400000, 2800000, 200000, 96000,
-	  10, 5 }		/* I9xx */
-};
-
-int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
-{
-	u32 tmp;
-	if (!pdev || !dinfo)
-		return 1;
-
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_INTEL_830M:
-		dinfo->name = "Intel(R) 830M";
-		dinfo->chipset = INTEL_830M;
-		dinfo->mobile = 1;
-		dinfo->pll_index = PLLS_I8xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_845G:
-		dinfo->name = "Intel(R) 845G";
-		dinfo->chipset = INTEL_845G;
-		dinfo->mobile = 0;
-		dinfo->pll_index = PLLS_I8xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_854:
-		dinfo->mobile = 1;
-		dinfo->name = "Intel(R) 854";
-		dinfo->chipset = INTEL_854;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_85XGM:
-		tmp = 0;
-		dinfo->mobile = 1;
-		dinfo->pll_index = PLLS_I8xx;
-		pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
-		switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
-			INTEL_85X_VARIANT_MASK) {
-		case INTEL_VAR_855GME:
-			dinfo->name = "Intel(R) 855GME";
-			dinfo->chipset = INTEL_855GME;
-			return 0;
-		case INTEL_VAR_855GM:
-			dinfo->name = "Intel(R) 855GM";
-			dinfo->chipset = INTEL_855GM;
-			return 0;
-		case INTEL_VAR_852GME:
-			dinfo->name = "Intel(R) 852GME";
-			dinfo->chipset = INTEL_852GME;
-			return 0;
-		case INTEL_VAR_852GM:
-			dinfo->name = "Intel(R) 852GM";
-			dinfo->chipset = INTEL_852GM;
-			return 0;
-		default:
-			dinfo->name = "Intel(R) 852GM/855GM";
-			dinfo->chipset = INTEL_85XGM;
-			return 0;
-		}
-		break;
-	case PCI_DEVICE_ID_INTEL_865G:
-		dinfo->name = "Intel(R) 865G";
-		dinfo->chipset = INTEL_865G;
-		dinfo->mobile = 0;
-		dinfo->pll_index = PLLS_I8xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_915G:
-		dinfo->name = "Intel(R) 915G";
-		dinfo->chipset = INTEL_915G;
-		dinfo->mobile = 0;
-		dinfo->pll_index = PLLS_I9xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_915GM:
-		dinfo->name = "Intel(R) 915GM";
-		dinfo->chipset = INTEL_915GM;
-		dinfo->mobile = 1;
-		dinfo->pll_index = PLLS_I9xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_945G:
-		dinfo->name = "Intel(R) 945G";
-		dinfo->chipset = INTEL_945G;
-		dinfo->mobile = 0;
-		dinfo->pll_index = PLLS_I9xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_945GM:
-		dinfo->name = "Intel(R) 945GM";
-		dinfo->chipset = INTEL_945GM;
-		dinfo->mobile = 1;
-		dinfo->pll_index = PLLS_I9xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_945GME:
-		dinfo->name = "Intel(R) 945GME";
-		dinfo->chipset = INTEL_945GME;
-		dinfo->mobile = 1;
-		dinfo->pll_index = PLLS_I9xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_965G:
-		dinfo->name = "Intel(R) 965G";
-		dinfo->chipset = INTEL_965G;
-		dinfo->mobile = 0;
-		dinfo->pll_index = PLLS_I9xx;
-		return 0;
-	case PCI_DEVICE_ID_INTEL_965GM:
-		dinfo->name = "Intel(R) 965GM";
-		dinfo->chipset = INTEL_965GM;
-		dinfo->mobile = 1;
-		dinfo->pll_index = PLLS_I9xx;
-		return 0;
-	default:
-		return 1;
-	}
-}
-
-int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
-			 int *stolen_size)
-{
-	struct pci_dev *bridge_dev;
-	u16 tmp;
-	int stolen_overhead;
-
-	if (!pdev || !aperture_size || !stolen_size)
-		return 1;
-
-	/* Find the bridge device.  It is always 0:0.0 */
-	if (!(bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)))) {
-		ERR_MSG("cannot find bridge device\n");
-		return 1;
-	}
-
-	/* Get the fb aperture size and "stolen" memory amount. */
-	tmp = 0;
-	pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
-	pci_dev_put(bridge_dev);
-
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_INTEL_915G:
-	case PCI_DEVICE_ID_INTEL_915GM:
-	case PCI_DEVICE_ID_INTEL_945G:
-	case PCI_DEVICE_ID_INTEL_945GM:
-	case PCI_DEVICE_ID_INTEL_945GME:
-	case PCI_DEVICE_ID_INTEL_965G:
-	case PCI_DEVICE_ID_INTEL_965GM:
-		/* 915, 945 and 965 chipsets support a 256MB aperture.
-		   Aperture size is determined by inspected the
-		   base address of the aperture. */
-		if (pci_resource_start(pdev, 2) & 0x08000000)
-			*aperture_size = MB(128);
-		else
-			*aperture_size = MB(256);
-		break;
-	default:
-		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
-			*aperture_size = MB(64);
-		else
-			*aperture_size = MB(128);
-		break;
-	}
-
-	/* Stolen memory size is reduced by the GTT and the popup.
-	   GTT is 1K per MB of aperture size, and popup is 4K. */
-	stolen_overhead = (*aperture_size / MB(1)) + 4;
-	switch(pdev->device) {
-	case PCI_DEVICE_ID_INTEL_830M:
-	case PCI_DEVICE_ID_INTEL_845G:
-		switch (tmp & INTEL_830_GMCH_GMS_MASK) {
-		case INTEL_830_GMCH_GMS_STOLEN_512:
-			*stolen_size = KB(512) - KB(stolen_overhead);
-			return 0;
-		case INTEL_830_GMCH_GMS_STOLEN_1024:
-			*stolen_size = MB(1) - KB(stolen_overhead);
-			return 0;
-		case INTEL_830_GMCH_GMS_STOLEN_8192:
-			*stolen_size = MB(8) - KB(stolen_overhead);
-			return 0;
-		case INTEL_830_GMCH_GMS_LOCAL:
-			ERR_MSG("only local memory found\n");
-			return 1;
-		case INTEL_830_GMCH_GMS_DISABLED:
-			ERR_MSG("video memory is disabled\n");
-			return 1;
-		default:
-			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
-				tmp & INTEL_830_GMCH_GMS_MASK);
-			return 1;
-		}
-		break;
-	default:
-		switch (tmp & INTEL_855_GMCH_GMS_MASK) {
-		case INTEL_855_GMCH_GMS_STOLEN_1M:
-			*stolen_size = MB(1) - KB(stolen_overhead);
-			return 0;
-		case INTEL_855_GMCH_GMS_STOLEN_4M:
-			*stolen_size = MB(4) - KB(stolen_overhead);
-			return 0;
-		case INTEL_855_GMCH_GMS_STOLEN_8M:
-			*stolen_size = MB(8) - KB(stolen_overhead);
-			return 0;
-		case INTEL_855_GMCH_GMS_STOLEN_16M:
-			*stolen_size = MB(16) - KB(stolen_overhead);
-			return 0;
-		case INTEL_855_GMCH_GMS_STOLEN_32M:
-			*stolen_size = MB(32) - KB(stolen_overhead);
-			return 0;
-		case INTEL_915G_GMCH_GMS_STOLEN_48M:
-			*stolen_size = MB(48) - KB(stolen_overhead);
-			return 0;
-		case INTEL_915G_GMCH_GMS_STOLEN_64M:
-			*stolen_size = MB(64) - KB(stolen_overhead);
-			return 0;
-		case INTEL_855_GMCH_GMS_DISABLED:
-			ERR_MSG("video memory is disabled\n");
-			return 0;
-		default:
-			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
-				tmp & INTEL_855_GMCH_GMS_MASK);
-			return 1;
-		}
-	}
-}
-
-int intelfbhw_check_non_crt(struct intelfb_info *dinfo)
-{
-	int dvo = 0;
-
-	if (INREG(LVDS) & PORT_ENABLE)
-		dvo |= LVDS_PORT;
-	if (INREG(DVOA) & PORT_ENABLE)
-		dvo |= DVOA_PORT;
-	if (INREG(DVOB) & PORT_ENABLE)
-		dvo |= DVOB_PORT;
-	if (INREG(DVOC) & PORT_ENABLE)
-		dvo |= DVOC_PORT;
-
-	return dvo;
-}
-
-const char * intelfbhw_dvo_to_string(int dvo)
-{
-	if (dvo & DVOA_PORT)
-		return "DVO port A";
-	else if (dvo & DVOB_PORT)
-		return "DVO port B";
-	else if (dvo & DVOC_PORT)
-		return "DVO port C";
-	else if (dvo & LVDS_PORT)
-		return "LVDS port";
-	else
-		return NULL;
-}
-
-
-int intelfbhw_validate_mode(struct intelfb_info *dinfo,
-			    struct fb_var_screeninfo *var)
-{
-	int bytes_per_pixel;
-	int tmp;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_validate_mode\n");
-#endif
-
-	bytes_per_pixel = var->bits_per_pixel / 8;
-	if (bytes_per_pixel == 3)
-		bytes_per_pixel = 4;
-
-	/* Check if enough video memory. */
-	tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;
-	if (tmp > dinfo->fb.size) {
-		WRN_MSG("Not enough video ram for mode "
-			"(%d KByte vs %d KByte).\n",
-			BtoKB(tmp), BtoKB(dinfo->fb.size));
-		return 1;
-	}
-
-	/* Check if x/y limits are OK. */
-	if (var->xres - 1 > HACTIVE_MASK) {
-		WRN_MSG("X resolution too large (%d vs %d).\n",
-			var->xres, HACTIVE_MASK + 1);
-		return 1;
-	}
-	if (var->yres - 1 > VACTIVE_MASK) {
-		WRN_MSG("Y resolution too large (%d vs %d).\n",
-			var->yres, VACTIVE_MASK + 1);
-		return 1;
-	}
-	if (var->xres < 4) {
-		WRN_MSG("X resolution too small (%d vs 4).\n", var->xres);
-		return 1;
-	}
-	if (var->yres < 4) {
-		WRN_MSG("Y resolution too small (%d vs 4).\n", var->yres);
-		return 1;
-	}
-
-	/* Check for doublescan modes. */
-	if (var->vmode & FB_VMODE_DOUBLE) {
-		WRN_MSG("Mode is double-scan.\n");
-		return 1;
-	}
-
-	if ((var->vmode & FB_VMODE_INTERLACED) && (var->yres & 1)) {
-		WRN_MSG("Odd number of lines in interlaced mode\n");
-		return 1;
-	}
-
-	/* Check if clock is OK. */
-	tmp = 1000000000 / var->pixclock;
-	if (tmp < MIN_CLOCK) {
-		WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",
-			(tmp + 500) / 1000, MIN_CLOCK / 1000);
-		return 1;
-	}
-	if (tmp > MAX_CLOCK) {
-		WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",
-			(tmp + 500) / 1000, MAX_CLOCK / 1000);
-		return 1;
-	}
-
-	return 0;
-}
-
-int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct intelfb_info *dinfo = GET_DINFO(info);
-	u32 offset, xoffset, yoffset;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_pan_display\n");
-#endif
-
-	xoffset = ROUND_DOWN_TO(var->xoffset, 8);
-	yoffset = var->yoffset;
-
-	if ((xoffset + info->var.xres > info->var.xres_virtual) ||
-	    (yoffset + info->var.yres > info->var.yres_virtual))
-		return -EINVAL;
-
-	offset = (yoffset * dinfo->pitch) +
-		 (xoffset * info->var.bits_per_pixel) / 8;
-
-	offset += dinfo->fb.offset << 12;
-
-	dinfo->vsync.pan_offset = offset;
-	if ((var->activate & FB_ACTIVATE_VBL) &&
-	    !intelfbhw_enable_irq(dinfo))
-		dinfo->vsync.pan_display = 1;
-	else {
-		dinfo->vsync.pan_display = 0;
-		OUTREG(DSPABASE, offset);
-	}
-
-	return 0;
-}
-
-/* Blank the screen. */
-void intelfbhw_do_blank(int blank, struct fb_info *info)
-{
-	struct intelfb_info *dinfo = GET_DINFO(info);
-	u32 tmp;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);
-#endif
-
-	/* Turn plane A on or off */
-	tmp = INREG(DSPACNTR);
-	if (blank)
-		tmp &= ~DISPPLANE_PLANE_ENABLE;
-	else
-		tmp |= DISPPLANE_PLANE_ENABLE;
-	OUTREG(DSPACNTR, tmp);
-	/* Flush */
-	tmp = INREG(DSPABASE);
-	OUTREG(DSPABASE, tmp);
-
-	/* Turn off/on the HW cursor */
-#if VERBOSE > 0
-	DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
-#endif
-	if (dinfo->cursor_on) {
-		if (blank)
-			intelfbhw_cursor_hide(dinfo);
-		else
-			intelfbhw_cursor_show(dinfo);
-		dinfo->cursor_on = 1;
-	}
-	dinfo->cursor_blanked = blank;
-
-	/* Set DPMS level */
-	tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		tmp |= ADPA_DPMS_D0;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		tmp |= ADPA_DPMS_D1;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		tmp |= ADPA_DPMS_D2;
-		break;
-	case FB_BLANK_POWERDOWN:
-		tmp |= ADPA_DPMS_D3;
-		break;
-	}
-	OUTREG(ADPA, tmp);
-
-	return;
-}
-
-
-/* Check which pipe is connected to an active display plane. */
-int intelfbhw_active_pipe(const struct intelfb_hwstate *hw)
-{
-	int pipe = -1;
-
-	/* keep old default behaviour - prefer PIPE_A */
-	if (hw->disp_b_ctrl & DISPPLANE_PLANE_ENABLE) {
-		pipe = (hw->disp_b_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
-		pipe &= PIPE_MASK;
-		if (unlikely(pipe == PIPE_A))
-			return PIPE_A;
-	}
-	if (hw->disp_a_ctrl & DISPPLANE_PLANE_ENABLE) {
-		pipe = (hw->disp_a_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
-		pipe &= PIPE_MASK;
-		if (likely(pipe == PIPE_A))
-			return PIPE_A;
-	}
-	/* Impossible that no pipe is selected - return PIPE_A */
-	WARN_ON(pipe == -1);
-	if (unlikely(pipe == -1))
-		pipe = PIPE_A;
-
-	return pipe;
-}
-
-void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp)
-{
-	u32 palette_reg = (dinfo->pipe == PIPE_A) ?
-			  PALETTE_A : PALETTE_B;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
-		regno, red, green, blue);
-#endif
-
-	OUTREG(palette_reg + (regno << 2),
-	       (red << PALETTE_8_RED_SHIFT) |
-	       (green << PALETTE_8_GREEN_SHIFT) |
-	       (blue << PALETTE_8_BLUE_SHIFT));
-}
-
-
-int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
-			    struct intelfb_hwstate *hw, int flag)
-{
-	int i;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_read_hw_state\n");
-#endif
-
-	if (!hw || !dinfo)
-		return -1;
-
-	/* Read in as much of the HW state as possible. */
-	hw->vga0_divisor = INREG(VGA0_DIVISOR);
-	hw->vga1_divisor = INREG(VGA1_DIVISOR);
-	hw->vga_pd = INREG(VGAPD);
-	hw->dpll_a = INREG(DPLL_A);
-	hw->dpll_b = INREG(DPLL_B);
-	hw->fpa0 = INREG(FPA0);
-	hw->fpa1 = INREG(FPA1);
-	hw->fpb0 = INREG(FPB0);
-	hw->fpb1 = INREG(FPB1);
-
-	if (flag == 1)
-		return flag;
-
-#if 0
-	/* This seems to be a problem with the 852GM/855GM */
-	for (i = 0; i < PALETTE_8_ENTRIES; i++) {
-		hw->palette_a[i] = INREG(PALETTE_A + (i << 2));
-		hw->palette_b[i] = INREG(PALETTE_B + (i << 2));
-	}
-#endif
-
-	if (flag == 2)
-		return flag;
-
-	hw->htotal_a = INREG(HTOTAL_A);
-	hw->hblank_a = INREG(HBLANK_A);
-	hw->hsync_a = INREG(HSYNC_A);
-	hw->vtotal_a = INREG(VTOTAL_A);
-	hw->vblank_a = INREG(VBLANK_A);
-	hw->vsync_a = INREG(VSYNC_A);
-	hw->src_size_a = INREG(SRC_SIZE_A);
-	hw->bclrpat_a = INREG(BCLRPAT_A);
-	hw->htotal_b = INREG(HTOTAL_B);
-	hw->hblank_b = INREG(HBLANK_B);
-	hw->hsync_b = INREG(HSYNC_B);
-	hw->vtotal_b = INREG(VTOTAL_B);
-	hw->vblank_b = INREG(VBLANK_B);
-	hw->vsync_b = INREG(VSYNC_B);
-	hw->src_size_b = INREG(SRC_SIZE_B);
-	hw->bclrpat_b = INREG(BCLRPAT_B);
-
-	if (flag == 3)
-		return flag;
-
-	hw->adpa = INREG(ADPA);
-	hw->dvoa = INREG(DVOA);
-	hw->dvob = INREG(DVOB);
-	hw->dvoc = INREG(DVOC);
-	hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
-	hw->dvob_srcdim = INREG(DVOB_SRCDIM);
-	hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
-	hw->lvds = INREG(LVDS);
-
-	if (flag == 4)
-		return flag;
-
-	hw->pipe_a_conf = INREG(PIPEACONF);
-	hw->pipe_b_conf = INREG(PIPEBCONF);
-	hw->disp_arb = INREG(DISPARB);
-
-	if (flag == 5)
-		return flag;
-
-	hw->cursor_a_control = INREG(CURSOR_A_CONTROL);
-	hw->cursor_b_control = INREG(CURSOR_B_CONTROL);
-	hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);
-	hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);
-
-	if (flag == 6)
-		return flag;
-
-	for (i = 0; i < 4; i++) {
-		hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));
-		hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));
-	}
-
-	if (flag == 7)
-		return flag;
-
-	hw->cursor_size = INREG(CURSOR_SIZE);
-
-	if (flag == 8)
-		return flag;
-
-	hw->disp_a_ctrl = INREG(DSPACNTR);
-	hw->disp_b_ctrl = INREG(DSPBCNTR);
-	hw->disp_a_base = INREG(DSPABASE);
-	hw->disp_b_base = INREG(DSPBBASE);
-	hw->disp_a_stride = INREG(DSPASTRIDE);
-	hw->disp_b_stride = INREG(DSPBSTRIDE);
-
-	if (flag == 9)
-		return flag;
-
-	hw->vgacntrl = INREG(VGACNTRL);
-
-	if (flag == 10)
-		return flag;
-
-	hw->add_id = INREG(ADD_ID);
-
-	if (flag == 11)
-		return flag;
-
-	for (i = 0; i < 7; i++) {
-		hw->swf0x[i] = INREG(SWF00 + (i << 2));
-		hw->swf1x[i] = INREG(SWF10 + (i << 2));
-		if (i < 3)
-			hw->swf3x[i] = INREG(SWF30 + (i << 2));
-	}
-
-	for (i = 0; i < 8; i++)
-		hw->fence[i] = INREG(FENCE + (i << 2));
-
-	hw->instpm = INREG(INSTPM);
-	hw->mem_mode = INREG(MEM_MODE);
-	hw->fw_blc_0 = INREG(FW_BLC_0);
-	hw->fw_blc_1 = INREG(FW_BLC_1);
-
-	hw->hwstam = INREG16(HWSTAM);
-	hw->ier = INREG16(IER);
-	hw->iir = INREG16(IIR);
-	hw->imr = INREG16(IMR);
-
-	return 0;
-}
-
-
-static int calc_vclock3(int index, int m, int n, int p)
-{
-	if (p == 0 || n == 0)
-		return 0;
-	return plls[index].ref_clk * m / n / p;
-}
-
-static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2,
-		       int lvds)
-{
-	struct pll_min_max *pll = &plls[index];
-	u32 m, vco, p;
-
-	m = (5 * (m1 + 2)) + (m2 + 2);
-	n += 2;
-	vco = pll->ref_clk * m / n;
-
-	if (index == PLLS_I8xx)
-		p = ((p1 + 2) * (1 << (p2 + 1)));
-	else
-		p = ((p1) * (p2 ? 5 : 10));
-	return vco / p;
-}
-
-#if REGDUMP
-static void intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll,
-			       int *o_p1, int *o_p2)
-{
-	int p1, p2;
-
-	if (IS_I9XX(dinfo)) {
-		if (dpll & DPLL_P1_FORCE_DIV2)
-			p1 = 1;
-		else
-			p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
-
-		p1 = ffs(p1);
-
-		p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
-	} else {
-		if (dpll & DPLL_P1_FORCE_DIV2)
-			p1 = 0;
-		else
-			p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
-		p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
-	}
-
-	*o_p1 = p1;
-	*o_p2 = p2;
-}
-#endif
-
-
-void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
-			      struct intelfb_hwstate *hw)
-{
-#if REGDUMP
-	int i, m1, m2, n, p1, p2;
-	int index = dinfo->pll_index;
-	DBG_MSG("intelfbhw_print_hw_state\n");
-
-	if (!hw)
-		return;
-	/* Read in as much of the HW state as possible. */
-	printk("hw state dump start\n");
-	printk("	VGA0_DIVISOR:		0x%08x\n", hw->vga0_divisor);
-	printk("	VGA1_DIVISOR:		0x%08x\n", hw->vga1_divisor);
-	printk("	VGAPD:			0x%08x\n", hw->vga_pd);
-	n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-
-	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
-
-	printk("	VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-	       m1, m2, n, p1, p2);
-	printk("	VGA0: clock is %d\n",
-	       calc_vclock(index, m1, m2, n, p1, p2, 0));
-
-	n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-
-	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
-	printk("	VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-	       m1, m2, n, p1, p2);
-	printk("	VGA1: clock is %d\n",
-	       calc_vclock(index, m1, m2, n, p1, p2, 0));
-
-	printk("	DPLL_A:			0x%08x\n", hw->dpll_a);
-	printk("	DPLL_B:			0x%08x\n", hw->dpll_b);
-	printk("	FPA0:			0x%08x\n", hw->fpa0);
-	printk("	FPA1:			0x%08x\n", hw->fpa1);
-	printk("	FPB0:			0x%08x\n", hw->fpb0);
-	printk("	FPB1:			0x%08x\n", hw->fpb1);
-
-	n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-
-	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
-
-	printk("	PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-	       m1, m2, n, p1, p2);
-	printk("	PLLA0: clock is %d\n",
-	       calc_vclock(index, m1, m2, n, p1, p2, 0));
-
-	n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-
-	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
-
-	printk("	PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-	       m1, m2, n, p1, p2);
-	printk("	PLLA1: clock is %d\n",
-	       calc_vclock(index, m1, m2, n, p1, p2, 0));
-
-#if 0
-	printk("	PALETTE_A:\n");
-	for (i = 0; i < PALETTE_8_ENTRIES)
-		printk("	%3d:	0x%08x\n", i, hw->palette_a[i]);
-	printk("	PALETTE_B:\n");
-	for (i = 0; i < PALETTE_8_ENTRIES)
-		printk("	%3d:	0x%08x\n", i, hw->palette_b[i]);
-#endif
-
-	printk("	HTOTAL_A:		0x%08x\n", hw->htotal_a);
-	printk("	HBLANK_A:		0x%08x\n", hw->hblank_a);
-	printk("	HSYNC_A:		0x%08x\n", hw->hsync_a);
-	printk("	VTOTAL_A:		0x%08x\n", hw->vtotal_a);
-	printk("	VBLANK_A:		0x%08x\n", hw->vblank_a);
-	printk("	VSYNC_A:		0x%08x\n", hw->vsync_a);
-	printk("	SRC_SIZE_A:		0x%08x\n", hw->src_size_a);
-	printk("	BCLRPAT_A:		0x%08x\n", hw->bclrpat_a);
-	printk("	HTOTAL_B:		0x%08x\n", hw->htotal_b);
-	printk("	HBLANK_B:		0x%08x\n", hw->hblank_b);
-	printk("	HSYNC_B:		0x%08x\n", hw->hsync_b);
-	printk("	VTOTAL_B:		0x%08x\n", hw->vtotal_b);
-	printk("	VBLANK_B:		0x%08x\n", hw->vblank_b);
-	printk("	VSYNC_B:		0x%08x\n", hw->vsync_b);
-	printk("	SRC_SIZE_B:		0x%08x\n", hw->src_size_b);
-	printk("	BCLRPAT_B:		0x%08x\n", hw->bclrpat_b);
-
-	printk("	ADPA:			0x%08x\n", hw->adpa);
-	printk("	DVOA:			0x%08x\n", hw->dvoa);
-	printk("	DVOB:			0x%08x\n", hw->dvob);
-	printk("	DVOC:			0x%08x\n", hw->dvoc);
-	printk("	DVOA_SRCDIM:		0x%08x\n", hw->dvoa_srcdim);
-	printk("	DVOB_SRCDIM:		0x%08x\n", hw->dvob_srcdim);
-	printk("	DVOC_SRCDIM:		0x%08x\n", hw->dvoc_srcdim);
-	printk("	LVDS:			0x%08x\n", hw->lvds);
-
-	printk("	PIPEACONF:		0x%08x\n", hw->pipe_a_conf);
-	printk("	PIPEBCONF:		0x%08x\n", hw->pipe_b_conf);
-	printk("	DISPARB:		0x%08x\n", hw->disp_arb);
-
-	printk("	CURSOR_A_CONTROL:	0x%08x\n", hw->cursor_a_control);
-	printk("	CURSOR_B_CONTROL:	0x%08x\n", hw->cursor_b_control);
-	printk("	CURSOR_A_BASEADDR:	0x%08x\n", hw->cursor_a_base);
-	printk("	CURSOR_B_BASEADDR:	0x%08x\n", hw->cursor_b_base);
-
-	printk("	CURSOR_A_PALETTE:	");
-	for (i = 0; i < 4; i++) {
-		printk("0x%08x", hw->cursor_a_palette[i]);
-		if (i < 3)
-			printk(", ");
-	}
-	printk("\n");
-	printk("	CURSOR_B_PALETTE:	");
-	for (i = 0; i < 4; i++) {
-		printk("0x%08x", hw->cursor_b_palette[i]);
-		if (i < 3)
-			printk(", ");
-	}
-	printk("\n");
-
-	printk("	CURSOR_SIZE:		0x%08x\n", hw->cursor_size);
-
-	printk("	DSPACNTR:		0x%08x\n", hw->disp_a_ctrl);
-	printk("	DSPBCNTR:		0x%08x\n", hw->disp_b_ctrl);
-	printk("	DSPABASE:		0x%08x\n", hw->disp_a_base);
-	printk("	DSPBBASE:		0x%08x\n", hw->disp_b_base);
-	printk("	DSPASTRIDE:		0x%08x\n", hw->disp_a_stride);
-	printk("	DSPBSTRIDE:		0x%08x\n", hw->disp_b_stride);
-
-	printk("	VGACNTRL:		0x%08x\n", hw->vgacntrl);
-	printk("	ADD_ID:			0x%08x\n", hw->add_id);
-
-	for (i = 0; i < 7; i++) {
-		printk("	SWF0%d			0x%08x\n", i,
-			hw->swf0x[i]);
-	}
-	for (i = 0; i < 7; i++) {
-		printk("	SWF1%d			0x%08x\n", i,
-			hw->swf1x[i]);
-	}
-	for (i = 0; i < 3; i++) {
-		printk("	SWF3%d			0x%08x\n", i,
-		       hw->swf3x[i]);
-	}
-	for (i = 0; i < 8; i++)
-		printk("	FENCE%d			0x%08x\n", i,
-		       hw->fence[i]);
-
-	printk("	INSTPM			0x%08x\n", hw->instpm);
-	printk("	MEM_MODE		0x%08x\n", hw->mem_mode);
-	printk("	FW_BLC_0		0x%08x\n", hw->fw_blc_0);
-	printk("	FW_BLC_1		0x%08x\n", hw->fw_blc_1);
-
-	printk("	HWSTAM			0x%04x\n", hw->hwstam);
-	printk("	IER			0x%04x\n", hw->ier);
-	printk("	IIR			0x%04x\n", hw->iir);
-	printk("	IMR			0x%04x\n", hw->imr);
-	printk("hw state dump end\n");
-#endif
-}
-
-
-
-/* Split the M parameter into M1 and M2. */
-static int splitm(int index, unsigned int m, unsigned int *retm1,
-		  unsigned int *retm2)
-{
-	int m1, m2;
-	int testm;
-	struct pll_min_max *pll = &plls[index];
-
-	/* no point optimising too much - brute force m */
-	for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {
-		for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {
-			testm = (5 * (m1 + 2)) + (m2 + 2);
-			if (testm == m) {
-				*retm1 = (unsigned int)m1;
-				*retm2 = (unsigned int)m2;
-				return 0;
-			}
-		}
-	}
-	return 1;
-}
-
-/* Split the P parameter into P1 and P2. */
-static int splitp(int index, unsigned int p, unsigned int *retp1,
-		  unsigned int *retp2)
-{
-	int p1, p2;
-	struct pll_min_max *pll = &plls[index];
-
-	if (index == PLLS_I9xx) {
-		p2 = (p % 10) ? 1 : 0;
-
-		p1 = p / (p2 ? 5 : 10);
-
-		*retp1 = (unsigned int)p1;
-		*retp2 = (unsigned int)p2;
-		return 0;
-	}
-
-	if (p % 4 == 0)
-		p2 = 1;
-	else
-		p2 = 0;
-	p1 = (p / (1 << (p2 + 1))) - 2;
-	if (p % 4 == 0 && p1 < pll->min_p1) {
-		p2 = 0;
-		p1 = (p / (1 << (p2 + 1))) - 2;
-	}
-	if (p1 < pll->min_p1 || p1 > pll->max_p1 ||
-	    (p1 + 2) * (1 << (p2 + 1)) != p) {
-		return 1;
-	} else {
-		*retp1 = (unsigned int)p1;
-		*retp2 = (unsigned int)p2;
-		return 0;
-	}
-}
-
-static int calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2,
-			   u32 *retn, u32 *retp1, u32 *retp2, u32 *retclock)
-{
-	u32 m1, m2, n, p1, p2, n1, testm;
-	u32 f_vco, p, p_best = 0, m, f_out = 0;
-	u32 err_max, err_target, err_best = 10000000;
-	u32 n_best = 0, m_best = 0, f_best, f_err;
-	u32 p_min, p_max, p_inc, div_max;
-	struct pll_min_max *pll = &plls[index];
-
-	/* Accept 0.5% difference, but aim for 0.1% */
-	err_max = 5 * clock / 1000;
-	err_target = clock / 1000;
-
-	DBG_MSG("Clock is %d\n", clock);
-
-	div_max = pll->max_vco / clock;
-
-	p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;
-	p_min = p_inc;
-	p_max = ROUND_DOWN_TO(div_max, p_inc);
-	if (p_min < pll->min_p)
-		p_min = pll->min_p;
-	if (p_max > pll->max_p)
-		p_max = pll->max_p;
-
-	DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
-
-	p = p_min;
-	do {
-		if (splitp(index, p, &p1, &p2)) {
-			WRN_MSG("cannot split p = %d\n", p);
-			p += p_inc;
-			continue;
-		}
-		n = pll->min_n;
-		f_vco = clock * p;
-
-		do {
-			m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;
-			if (m < pll->min_m)
-				m = pll->min_m + 1;
-			if (m > pll->max_m)
-				m = pll->max_m - 1;
-			for (testm = m - 1; testm <= m; testm++) {
-				f_out = calc_vclock3(index, testm, n, p);
-				if (splitm(index, testm, &m1, &m2)) {
-					WRN_MSG("cannot split m = %d\n",
-						testm);
-					continue;
-				}
-				if (clock > f_out)
-					f_err = clock - f_out;
-				else/* slightly bias the error for bigger clocks */
-					f_err = f_out - clock + 1;
-
-				if (f_err < err_best) {
-					m_best = testm;
-					n_best = n;
-					p_best = p;
-					f_best = f_out;
-					err_best = f_err;
-				}
-			}
-			n++;
-		} while ((n <= pll->max_n) && (f_out >= clock));
-		p += p_inc;
-	} while ((p <= p_max));
-
-	if (!m_best) {
-		WRN_MSG("cannot find parameters for clock %d\n", clock);
-		return 1;
-	}
-	m = m_best;
-	n = n_best;
-	p = p_best;
-	splitm(index, m, &m1, &m2);
-	splitp(index, p, &p1, &p2);
-	n1 = n - 2;
-
-	DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
-		"f: %d (%d), VCO: %d\n",
-		m, m1, m2, n, n1, p, p1, p2,
-		calc_vclock3(index, m, n, p),
-		calc_vclock(index, m1, m2, n1, p1, p2, 0),
-		calc_vclock3(index, m, n, p) * p);
-	*retm1 = m1;
-	*retm2 = m2;
-	*retn = n1;
-	*retp1 = p1;
-	*retp2 = p2;
-	*retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);
-
-	return 0;
-}
-
-static __inline__ int check_overflow(u32 value, u32 limit,
-				     const char *description)
-{
-	if (value > limit) {
-		WRN_MSG("%s value %d exceeds limit %d\n",
-			description, value, limit);
-		return 1;
-	}
-	return 0;
-}
-
-/* It is assumed that hw is filled in with the initial state information. */
-int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
-			 struct intelfb_hwstate *hw,
-			 struct fb_var_screeninfo *var)
-{
-	int pipe = intelfbhw_active_pipe(hw);
-	u32 *dpll, *fp0, *fp1;
-	u32 m1, m2, n, p1, p2, clock_target, clock;
-	u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
-	u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
-	u32 vsync_pol, hsync_pol;
-	u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
-	u32 stride_alignment;
-
-	DBG_MSG("intelfbhw_mode_to_hw\n");
-
-	/* Disable VGA */
-	hw->vgacntrl |= VGA_DISABLE;
-
-	/* Set which pipe's registers will be set. */
-	if (pipe == PIPE_B) {
-		dpll = &hw->dpll_b;
-		fp0 = &hw->fpb0;
-		fp1 = &hw->fpb1;
-		hs = &hw->hsync_b;
-		hb = &hw->hblank_b;
-		ht = &hw->htotal_b;
-		vs = &hw->vsync_b;
-		vb = &hw->vblank_b;
-		vt = &hw->vtotal_b;
-		ss = &hw->src_size_b;
-		pipe_conf = &hw->pipe_b_conf;
-	} else {
-		dpll = &hw->dpll_a;
-		fp0 = &hw->fpa0;
-		fp1 = &hw->fpa1;
-		hs = &hw->hsync_a;
-		hb = &hw->hblank_a;
-		ht = &hw->htotal_a;
-		vs = &hw->vsync_a;
-		vb = &hw->vblank_a;
-		vt = &hw->vtotal_a;
-		ss = &hw->src_size_a;
-		pipe_conf = &hw->pipe_a_conf;
-	}
-
-	/* Use ADPA register for sync control. */
-	hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
-
-	/* sync polarity */
-	hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ?
-			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
-	vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ?
-			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
-	hw->adpa &= ~((ADPA_SYNC_ACTIVE_MASK << ADPA_VSYNC_ACTIVE_SHIFT) |
-		      (ADPA_SYNC_ACTIVE_MASK << ADPA_HSYNC_ACTIVE_SHIFT));
-	hw->adpa |= (hsync_pol << ADPA_HSYNC_ACTIVE_SHIFT) |
-		    (vsync_pol << ADPA_VSYNC_ACTIVE_SHIFT);
-
-	/* Connect correct pipe to the analog port DAC */
-	hw->adpa &= ~(PIPE_MASK << ADPA_PIPE_SELECT_SHIFT);
-	hw->adpa |= (pipe << ADPA_PIPE_SELECT_SHIFT);
-
-	/* Set DPMS state to D0 (on) */
-	hw->adpa &= ~ADPA_DPMS_CONTROL_MASK;
-	hw->adpa |= ADPA_DPMS_D0;
-
-	hw->adpa |= ADPA_DAC_ENABLE;
-
-	*dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
-	*dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
-	*dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
-
-	/* Desired clock in kHz */
-	clock_target = 1000000000 / var->pixclock;
-
-	if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2,
-			    &n, &p1, &p2, &clock)) {
-		WRN_MSG("calc_pll_params failed\n");
-		return 1;
-	}
-
-	/* Check for overflow. */
-	if (check_overflow(p1, DPLL_P1_MASK, "PLL P1 parameter"))
-		return 1;
-	if (check_overflow(p2, DPLL_P2_MASK, "PLL P2 parameter"))
-		return 1;
-	if (check_overflow(m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
-		return 1;
-	if (check_overflow(m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
-		return 1;
-	if (check_overflow(n, FP_DIVISOR_MASK, "PLL N parameter"))
-		return 1;
-
-	*dpll &= ~DPLL_P1_FORCE_DIV2;
-	*dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
-		   (DPLL_P1_MASK << DPLL_P1_SHIFT));
-
-	if (IS_I9XX(dinfo)) {
-		*dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
-		*dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
-	} else
-		*dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
-
-	*fp0 = (n << FP_N_DIVISOR_SHIFT) |
-	       (m1 << FP_M1_DIVISOR_SHIFT) |
-	       (m2 << FP_M2_DIVISOR_SHIFT);
-	*fp1 = *fp0;
-
-	hw->dvob &= ~PORT_ENABLE;
-	hw->dvoc &= ~PORT_ENABLE;
-
-	/* Use display plane A. */
-	hw->disp_a_ctrl |= DISPPLANE_PLANE_ENABLE;
-	hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
-	hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
-	switch (intelfb_var_to_depth(var)) {
-	case 8:
-		hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
-		break;
-	case 15:
-		hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
-		break;
-	case 16:
-		hw->disp_a_ctrl |= DISPPLANE_16BPP;
-		break;
-	case 24:
-		hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
-		break;
-	}
-	hw->disp_a_ctrl &= ~(PIPE_MASK << DISPPLANE_SEL_PIPE_SHIFT);
-	hw->disp_a_ctrl |= (pipe << DISPPLANE_SEL_PIPE_SHIFT);
-
-	/* Set CRTC registers. */
-	hactive = var->xres;
-	hsync_start = hactive + var->right_margin;
-	hsync_end = hsync_start + var->hsync_len;
-	htotal = hsync_end + var->left_margin;
-	hblank_start = hactive;
-	hblank_end = htotal;
-
-	DBG_MSG("H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
-		hactive, hsync_start, hsync_end, htotal, hblank_start,
-		hblank_end);
-
-	vactive = var->yres;
-	if (var->vmode & FB_VMODE_INTERLACED)
-		vactive--; /* the chip adds 2 halflines automatically */
-	vsync_start = vactive + var->lower_margin;
-	vsync_end = vsync_start + var->vsync_len;
-	vtotal = vsync_end + var->upper_margin;
-	vblank_start = vactive;
-	vblank_end = vtotal;
-	vblank_end = vsync_end + 1;
-
-	DBG_MSG("V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
-		vactive, vsync_start, vsync_end, vtotal, vblank_start,
-		vblank_end);
-
-	/* Adjust for register values, and check for overflow. */
-	hactive--;
-	if (check_overflow(hactive, HACTIVE_MASK, "CRTC hactive"))
-		return 1;
-	hsync_start--;
-	if (check_overflow(hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
-		return 1;
-	hsync_end--;
-	if (check_overflow(hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
-		return 1;
-	htotal--;
-	if (check_overflow(htotal, HTOTAL_MASK, "CRTC htotal"))
-		return 1;
-	hblank_start--;
-	if (check_overflow(hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
-		return 1;
-	hblank_end--;
-	if (check_overflow(hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
-		return 1;
-
-	vactive--;
-	if (check_overflow(vactive, VACTIVE_MASK, "CRTC vactive"))
-		return 1;
-	vsync_start--;
-	if (check_overflow(vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
-		return 1;
-	vsync_end--;
-	if (check_overflow(vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
-		return 1;
-	vtotal--;
-	if (check_overflow(vtotal, VTOTAL_MASK, "CRTC vtotal"))
-		return 1;
-	vblank_start--;
-	if (check_overflow(vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
-		return 1;
-	vblank_end--;
-	if (check_overflow(vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
-		return 1;
-
-	*ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
-	*hb = (hblank_start << HBLANKSTART_SHIFT) |
-	      (hblank_end << HSYNCEND_SHIFT);
-	*hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
-
-	*vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
-	*vb = (vblank_start << VBLANKSTART_SHIFT) |
-	      (vblank_end << VSYNCEND_SHIFT);
-	*vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
-	*ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
-	      (vactive << SRC_SIZE_VERT_SHIFT);
-
-	hw->disp_a_stride = dinfo->pitch;
-	DBG_MSG("pitch is %d\n", hw->disp_a_stride);
-
-	hw->disp_a_base = hw->disp_a_stride * var->yoffset +
-			  var->xoffset * var->bits_per_pixel / 8;
-
-	hw->disp_a_base += dinfo->fb.offset << 12;
-
-	/* Check stride alignment. */
-	stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX :
-					    STRIDE_ALIGNMENT;
-	if (hw->disp_a_stride % stride_alignment != 0) {
-		WRN_MSG("display stride %d has bad alignment %d\n",
-			hw->disp_a_stride, stride_alignment);
-		return 1;
-	}
-
-	/* Set the palette to 8-bit mode. */
-	*pipe_conf &= ~PIPECONF_GAMMA;
-
-	if (var->vmode & FB_VMODE_INTERLACED)
-		*pipe_conf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
-	else
-		*pipe_conf &= ~PIPECONF_INTERLACE_MASK;
-
-	return 0;
-}
-
-/* Program a (non-VGA) video mode. */
-int intelfbhw_program_mode(struct intelfb_info *dinfo,
-			   const struct intelfb_hwstate *hw, int blank)
-{
-	u32 tmp;
-	const u32 *dpll, *fp0, *fp1, *pipe_conf;
-	const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
-	u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg, pipe_stat_reg;
-	u32 hsync_reg, htotal_reg, hblank_reg;
-	u32 vsync_reg, vtotal_reg, vblank_reg;
-	u32 src_size_reg;
-	u32 count, tmp_val[3];
-
-	/* Assume single pipe */
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_program_mode\n");
-#endif
-
-	/* Disable VGA */
-	tmp = INREG(VGACNTRL);
-	tmp |= VGA_DISABLE;
-	OUTREG(VGACNTRL, tmp);
-
-	dinfo->pipe = intelfbhw_active_pipe(hw);
-
-	if (dinfo->pipe == PIPE_B) {
-		dpll = &hw->dpll_b;
-		fp0 = &hw->fpb0;
-		fp1 = &hw->fpb1;
-		pipe_conf = &hw->pipe_b_conf;
-		hs = &hw->hsync_b;
-		hb = &hw->hblank_b;
-		ht = &hw->htotal_b;
-		vs = &hw->vsync_b;
-		vb = &hw->vblank_b;
-		vt = &hw->vtotal_b;
-		ss = &hw->src_size_b;
-		dpll_reg = DPLL_B;
-		fp0_reg = FPB0;
-		fp1_reg = FPB1;
-		pipe_conf_reg = PIPEBCONF;
-		pipe_stat_reg = PIPEBSTAT;
-		hsync_reg = HSYNC_B;
-		htotal_reg = HTOTAL_B;
-		hblank_reg = HBLANK_B;
-		vsync_reg = VSYNC_B;
-		vtotal_reg = VTOTAL_B;
-		vblank_reg = VBLANK_B;
-		src_size_reg = SRC_SIZE_B;
-	} else {
-		dpll = &hw->dpll_a;
-		fp0 = &hw->fpa0;
-		fp1 = &hw->fpa1;
-		pipe_conf = &hw->pipe_a_conf;
-		hs = &hw->hsync_a;
-		hb = &hw->hblank_a;
-		ht = &hw->htotal_a;
-		vs = &hw->vsync_a;
-		vb = &hw->vblank_a;
-		vt = &hw->vtotal_a;
-		ss = &hw->src_size_a;
-		dpll_reg = DPLL_A;
-		fp0_reg = FPA0;
-		fp1_reg = FPA1;
-		pipe_conf_reg = PIPEACONF;
-		pipe_stat_reg = PIPEASTAT;
-		hsync_reg = HSYNC_A;
-		htotal_reg = HTOTAL_A;
-		hblank_reg = HBLANK_A;
-		vsync_reg = VSYNC_A;
-		vtotal_reg = VTOTAL_A;
-		vblank_reg = VBLANK_A;
-		src_size_reg = SRC_SIZE_A;
-	}
-
-	/* turn off pipe */
-	tmp = INREG(pipe_conf_reg);
-	tmp &= ~PIPECONF_ENABLE;
-	OUTREG(pipe_conf_reg, tmp);
-
-	count = 0;
-	do {
-		tmp_val[count % 3] = INREG(PIPEA_DSL);
-		if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1] == tmp_val[2]))
-			break;
-		count++;
-		udelay(1);
-		if (count % 200 == 0) {
-			tmp = INREG(pipe_conf_reg);
-			tmp &= ~PIPECONF_ENABLE;
-			OUTREG(pipe_conf_reg, tmp);
-		}
-	} while (count < 2000);
-
-	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
-
-	/* Disable planes A and B. */
-	tmp = INREG(DSPACNTR);
-	tmp &= ~DISPPLANE_PLANE_ENABLE;
-	OUTREG(DSPACNTR, tmp);
-	tmp = INREG(DSPBCNTR);
-	tmp &= ~DISPPLANE_PLANE_ENABLE;
-	OUTREG(DSPBCNTR, tmp);
-
-	/* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
-	mdelay(20);
-
-	OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE);
-	OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE);
-	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
-
-	/* Disable Sync */
-	tmp = INREG(ADPA);
-	tmp &= ~ADPA_DPMS_CONTROL_MASK;
-	tmp |= ADPA_DPMS_D3;
-	OUTREG(ADPA, tmp);
-
-	/* do some funky magic - xyzzy */
-	OUTREG(0x61204, 0xabcd0000);
-
-	/* turn off PLL */
-	tmp = INREG(dpll_reg);
-	tmp &= ~DPLL_VCO_ENABLE;
-	OUTREG(dpll_reg, tmp);
-
-	/* Set PLL parameters */
-	OUTREG(fp0_reg, *fp0);
-	OUTREG(fp1_reg, *fp1);
-
-	/* Enable PLL */
-	OUTREG(dpll_reg, *dpll);
-
-	/* Set DVOs B/C */
-	OUTREG(DVOB, hw->dvob);
-	OUTREG(DVOC, hw->dvoc);
-
-	/* undo funky magic */
-	OUTREG(0x61204, 0x00000000);
-
-	/* Set ADPA */
-	OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE);
-	OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
-
-	/* Set pipe parameters */
-	OUTREG(hsync_reg, *hs);
-	OUTREG(hblank_reg, *hb);
-	OUTREG(htotal_reg, *ht);
-	OUTREG(vsync_reg, *vs);
-	OUTREG(vblank_reg, *vb);
-	OUTREG(vtotal_reg, *vt);
-	OUTREG(src_size_reg, *ss);
-
-	switch (dinfo->info->var.vmode & (FB_VMODE_INTERLACED |
-					  FB_VMODE_ODD_FLD_FIRST)) {
-	case FB_VMODE_INTERLACED | FB_VMODE_ODD_FLD_FIRST:
-		OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_ODD_EN);
-		break;
-	case FB_VMODE_INTERLACED: /* even lines first */
-		OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_EVEN_EN);
-		break;
-	default:		/* non-interlaced */
-		OUTREG(pipe_stat_reg, 0xFFFF); /* clear all status bits only */
-	}
-	/* Enable pipe */
-	OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
-
-	/* Enable sync */
-	tmp = INREG(ADPA);
-	tmp &= ~ADPA_DPMS_CONTROL_MASK;
-	tmp |= ADPA_DPMS_D0;
-	OUTREG(ADPA, tmp);
-
-	/* setup display plane */
-	if (dinfo->pdev->device == PCI_DEVICE_ID_INTEL_830M) {
-		/*
-		 *      i830M errata: the display plane must be enabled
-		 *      to allow writes to the other bits in the plane
-		 *      control register.
-		 */
-		tmp = INREG(DSPACNTR);
-		if ((tmp & DISPPLANE_PLANE_ENABLE) != DISPPLANE_PLANE_ENABLE) {
-			tmp |= DISPPLANE_PLANE_ENABLE;
-			OUTREG(DSPACNTR, tmp);
-			OUTREG(DSPACNTR,
-			       hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
-			mdelay(1);
-		}
-	}
-
-	OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
-	OUTREG(DSPASTRIDE, hw->disp_a_stride);
-	OUTREG(DSPABASE, hw->disp_a_base);
-
-	/* Enable plane */
-	if (!blank) {
-		tmp = INREG(DSPACNTR);
-		tmp |= DISPPLANE_PLANE_ENABLE;
-		OUTREG(DSPACNTR, tmp);
-		OUTREG(DSPABASE, hw->disp_a_base);
-	}
-
-	return 0;
-}
-
-/* forward declarations */
-static void refresh_ring(struct intelfb_info *dinfo);
-static void reset_state(struct intelfb_info *dinfo);
-static void do_flush(struct intelfb_info *dinfo);
-
-static  u32 get_ring_space(struct intelfb_info *dinfo)
-{
-	u32 ring_space;
-
-	if (dinfo->ring_tail >= dinfo->ring_head)
-		ring_space = dinfo->ring.size -
-			(dinfo->ring_tail - dinfo->ring_head);
-	else
-		ring_space = dinfo->ring_head - dinfo->ring_tail;
-
-	if (ring_space > RING_MIN_FREE)
-		ring_space -= RING_MIN_FREE;
-	else
-		ring_space = 0;
-
-	return ring_space;
-}
-
-static int wait_ring(struct intelfb_info *dinfo, int n)
-{
-	int i = 0;
-	unsigned long end;
-	u32 last_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
-
-#if VERBOSE > 0
-	DBG_MSG("wait_ring: %d\n", n);
-#endif
-
-	end = jiffies + (HZ * 3);
-	while (dinfo->ring_space < n) {
-		dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
-		dinfo->ring_space = get_ring_space(dinfo);
-
-		if (dinfo->ring_head != last_head) {
-			end = jiffies + (HZ * 3);
-			last_head = dinfo->ring_head;
-		}
-		i++;
-		if (time_before(end, jiffies)) {
-			if (!i) {
-				/* Try again */
-				reset_state(dinfo);
-				refresh_ring(dinfo);
-				do_flush(dinfo);
-				end = jiffies + (HZ * 3);
-				i = 1;
-			} else {
-				WRN_MSG("ring buffer : space: %d wanted %d\n",
-					dinfo->ring_space, n);
-				WRN_MSG("lockup - turning off hardware "
-					"acceleration\n");
-				dinfo->ring_lockup = 1;
-				break;
-			}
-		}
-		udelay(1);
-	}
-	return i;
-}
-
-static void do_flush(struct intelfb_info *dinfo)
-{
-	START_RING(2);
-	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
-	OUT_RING(MI_NOOP);
-	ADVANCE_RING();
-}
-
-void intelfbhw_do_sync(struct intelfb_info *dinfo)
-{
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_do_sync\n");
-#endif
-
-	if (!dinfo->accel)
-		return;
-
-	/*
-	 * Send a flush, then wait until the ring is empty.  This is what
-	 * the XFree86 driver does, and actually it doesn't seem a lot worse
-	 * than the recommended method (both have problems).
-	 */
-	do_flush(dinfo);
-	wait_ring(dinfo, dinfo->ring.size - RING_MIN_FREE);
-	dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
-}
-
-static void refresh_ring(struct intelfb_info *dinfo)
-{
-#if VERBOSE > 0
-	DBG_MSG("refresh_ring\n");
-#endif
-
-	dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
-	dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
-	dinfo->ring_space = get_ring_space(dinfo);
-}
-
-static void reset_state(struct intelfb_info *dinfo)
-{
-	int i;
-	u32 tmp;
-
-#if VERBOSE > 0
-	DBG_MSG("reset_state\n");
-#endif
-
-	for (i = 0; i < FENCE_NUM; i++)
-		OUTREG(FENCE + (i << 2), 0);
-
-	/* Flush the ring buffer if it's enabled. */
-	tmp = INREG(PRI_RING_LENGTH);
-	if (tmp & RING_ENABLE) {
-#if VERBOSE > 0
-		DBG_MSG("reset_state: ring was enabled\n");
-#endif
-		refresh_ring(dinfo);
-		intelfbhw_do_sync(dinfo);
-		DO_RING_IDLE();
-	}
-
-	OUTREG(PRI_RING_LENGTH, 0);
-	OUTREG(PRI_RING_HEAD, 0);
-	OUTREG(PRI_RING_TAIL, 0);
-	OUTREG(PRI_RING_START, 0);
-}
-
-/* Stop the 2D engine, and turn off the ring buffer. */
-void intelfbhw_2d_stop(struct intelfb_info *dinfo)
-{
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n",
-		dinfo->accel, dinfo->ring_active);
-#endif
-
-	if (!dinfo->accel)
-		return;
-
-	dinfo->ring_active = 0;
-	reset_state(dinfo);
-}
-
-/*
- * Enable the ring buffer, and initialise the 2D engine.
- * It is assumed that the graphics engine has been stopped by previously
- * calling intelfb_2d_stop().
- */
-void intelfbhw_2d_start(struct intelfb_info *dinfo)
-{
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
-		dinfo->accel, dinfo->ring_active);
-#endif
-
-	if (!dinfo->accel)
-		return;
-
-	/* Initialise the primary ring buffer. */
-	OUTREG(PRI_RING_LENGTH, 0);
-	OUTREG(PRI_RING_TAIL, 0);
-	OUTREG(PRI_RING_HEAD, 0);
-
-	OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);
-	OUTREG(PRI_RING_LENGTH,
-		((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |
-		RING_NO_REPORT | RING_ENABLE);
-	refresh_ring(dinfo);
-	dinfo->ring_active = 1;
-}
-
-/* 2D fillrect (solid fill or invert) */
-void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w,
-			   u32 h, u32 color, u32 pitch, u32 bpp, u32 rop)
-{
-	u32 br00, br09, br13, br14, br16;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "
-		"rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);
-#endif
-
-	br00 = COLOR_BLT_CMD;
-	br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));
-	br13 = (rop << ROP_SHIFT) | pitch;
-	br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);
-	br16 = color;
-
-	switch (bpp) {
-	case 8:
-		br13 |= COLOR_DEPTH_8;
-		break;
-	case 16:
-		br13 |= COLOR_DEPTH_16;
-		break;
-	case 32:
-		br13 |= COLOR_DEPTH_32;
-		br00 |= WRITE_ALPHA | WRITE_RGB;
-		break;
-	}
-
-	START_RING(6);
-	OUT_RING(br00);
-	OUT_RING(br13);
-	OUT_RING(br14);
-	OUT_RING(br09);
-	OUT_RING(br16);
-	OUT_RING(MI_NOOP);
-	ADVANCE_RING();
-
-#if VERBOSE > 0
-	DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,
-		dinfo->ring_tail, dinfo->ring_space);
-#endif
-}
-
-void
-intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
-		    u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp)
-{
-	u32 br00, br09, br11, br12, br13, br22, br23, br26;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",
-		curx, cury, dstx, dsty, w, h, pitch, bpp);
-#endif
-
-	br00 = XY_SRC_COPY_BLT_CMD;
-	br09 = dinfo->fb_start;
-	br11 = (pitch << PITCH_SHIFT);
-	br12 = dinfo->fb_start;
-	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
-	br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);
-	br23 = ((dstx + w) << WIDTH_SHIFT) |
-	       ((dsty + h) << HEIGHT_SHIFT);
-	br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);
-
-	switch (bpp) {
-	case 8:
-		br13 |= COLOR_DEPTH_8;
-		break;
-	case 16:
-		br13 |= COLOR_DEPTH_16;
-		break;
-	case 32:
-		br13 |= COLOR_DEPTH_32;
-		br00 |= WRITE_ALPHA | WRITE_RGB;
-		break;
-	}
-
-	START_RING(8);
-	OUT_RING(br00);
-	OUT_RING(br13);
-	OUT_RING(br22);
-	OUT_RING(br23);
-	OUT_RING(br09);
-	OUT_RING(br26);
-	OUT_RING(br11);
-	OUT_RING(br12);
-	ADVANCE_RING();
-}
-
-int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
-			   u32 h, const u8* cdat, u32 x, u32 y, u32 pitch,
-			   u32 bpp)
-{
-	int nbytes, ndwords, pad, tmp;
-	u32 br00, br09, br13, br18, br19, br22, br23;
-	int dat, ix, iy, iw;
-	int i, j;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);
-#endif
-
-	/* size in bytes of a padded scanline */
-	nbytes = ROUND_UP_TO(w, 16) / 8;
-
-	/* Total bytes of padded scanline data to write out. */
-	nbytes = nbytes * h;
-
-	/*
-	 * Check if the glyph data exceeds the immediate mode limit.
-	 * It would take a large font (1K pixels) to hit this limit.
-	 */
-	if (nbytes > MAX_MONO_IMM_SIZE)
-		return 0;
-
-	/* Src data is packaged a dword (32-bit) at a time. */
-	ndwords = ROUND_UP_TO(nbytes, 4) / 4;
-
-	/*
-	 * Ring has to be padded to a quad word. But because the command starts
-	   with 7 bytes, pad only if there is an even number of ndwords
-	 */
-	pad = !(ndwords % 2);
-
-	tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;
-	br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;
-	br09 = dinfo->fb_start;
-	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
-	br18 = bg;
-	br19 = fg;
-	br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);
-	br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);
-
-	switch (bpp) {
-	case 8:
-		br13 |= COLOR_DEPTH_8;
-		break;
-	case 16:
-		br13 |= COLOR_DEPTH_16;
-		break;
-	case 32:
-		br13 |= COLOR_DEPTH_32;
-		br00 |= WRITE_ALPHA | WRITE_RGB;
-		break;
-	}
-
-	START_RING(8 + ndwords);
-	OUT_RING(br00);
-	OUT_RING(br13);
-	OUT_RING(br22);
-	OUT_RING(br23);
-	OUT_RING(br09);
-	OUT_RING(br18);
-	OUT_RING(br19);
-	ix = iy = 0;
-	iw = ROUND_UP_TO(w, 8) / 8;
-	while (ndwords--) {
-		dat = 0;
-		for (j = 0; j < 2; ++j) {
-			for (i = 0; i < 2; ++i) {
-				if (ix != iw || i == 0)
-					dat |= cdat[iy*iw + ix++] << (i+j*2)*8;
-			}
-			if (ix == iw && iy != (h-1)) {
-				ix = 0;
-				++iy;
-			}
-		}
-		OUT_RING(dat);
-	}
-	if (pad)
-		OUT_RING(MI_NOOP);
-	ADVANCE_RING();
-
-	return 1;
-}
-
-/* HW cursor functions. */
-void intelfbhw_cursor_init(struct intelfb_info *dinfo)
-{
-	u32 tmp;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_cursor_init\n");
-#endif
-
-	if (dinfo->mobile || IS_I9XX(dinfo)) {
-		if (!dinfo->cursor.physical)
-			return;
-		tmp = INREG(CURSOR_A_CONTROL);
-		tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |
-			 CURSOR_MEM_TYPE_LOCAL |
-			 (1 << CURSOR_PIPE_SELECT_SHIFT));
-		tmp |= CURSOR_MODE_DISABLE;
-		OUTREG(CURSOR_A_CONTROL, tmp);
-		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
-	} else {
-		tmp = INREG(CURSOR_CONTROL);
-		tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
-			 CURSOR_ENABLE | CURSOR_STRIDE_MASK);
-		tmp = CURSOR_FORMAT_3C;
-		OUTREG(CURSOR_CONTROL, tmp);
-		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.offset << 12);
-		tmp = (64 << CURSOR_SIZE_H_SHIFT) |
-		      (64 << CURSOR_SIZE_V_SHIFT);
-		OUTREG(CURSOR_SIZE, tmp);
-	}
-}
-
-void intelfbhw_cursor_hide(struct intelfb_info *dinfo)
-{
-	u32 tmp;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_cursor_hide\n");
-#endif
-
-	dinfo->cursor_on = 0;
-	if (dinfo->mobile || IS_I9XX(dinfo)) {
-		if (!dinfo->cursor.physical)
-			return;
-		tmp = INREG(CURSOR_A_CONTROL);
-		tmp &= ~CURSOR_MODE_MASK;
-		tmp |= CURSOR_MODE_DISABLE;
-		OUTREG(CURSOR_A_CONTROL, tmp);
-		/* Flush changes */
-		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
-	} else {
-		tmp = INREG(CURSOR_CONTROL);
-		tmp &= ~CURSOR_ENABLE;
-		OUTREG(CURSOR_CONTROL, tmp);
-	}
-}
-
-void intelfbhw_cursor_show(struct intelfb_info *dinfo)
-{
-	u32 tmp;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_cursor_show\n");
-#endif
-
-	dinfo->cursor_on = 1;
-
-	if (dinfo->cursor_blanked)
-		return;
-
-	if (dinfo->mobile || IS_I9XX(dinfo)) {
-		if (!dinfo->cursor.physical)
-			return;
-		tmp = INREG(CURSOR_A_CONTROL);
-		tmp &= ~CURSOR_MODE_MASK;
-		tmp |= CURSOR_MODE_64_4C_AX;
-		OUTREG(CURSOR_A_CONTROL, tmp);
-		/* Flush changes */
-		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
-	} else {
-		tmp = INREG(CURSOR_CONTROL);
-		tmp |= CURSOR_ENABLE;
-		OUTREG(CURSOR_CONTROL, tmp);
-	}
-}
-
-void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
-{
-	u32 tmp;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);
-#endif
-
-	/*
-	 * Sets the position. The coordinates are assumed to already
-	 * have any offset adjusted. Assume that the cursor is never
-	 * completely off-screen, and that x, y are always >= 0.
-	 */
-
-	tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
-	      ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-	OUTREG(CURSOR_A_POSITION, tmp);
-
-	if (IS_I9XX(dinfo))
-		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
-}
-
-void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
-{
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_cursor_setcolor\n");
-#endif
-
-	OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);
-	OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);
-	OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);
-	OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
-}
-
-void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
-			   u8 *data)
-{
-	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
-	int i, j, w = width / 8;
-	int mod = width % 8, t_mask, d_mask;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_cursor_load\n");
-#endif
-
-	if (!dinfo->cursor.virtual)
-		return;
-
-	t_mask = 0xff >> mod;
-	d_mask = ~(0xff >> mod);
-	for (i = height; i--; ) {
-		for (j = 0; j < w; j++) {
-			writeb(0x00, addr + j);
-			writeb(*(data++), addr + j+8);
-		}
-		if (mod) {
-			writeb(t_mask, addr + j);
-			writeb(*(data++) & d_mask, addr + j+8);
-		}
-		addr += 16;
-	}
-}
-
-void intelfbhw_cursor_reset(struct intelfb_info *dinfo)
-{
-	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
-	int i, j;
-
-#if VERBOSE > 0
-	DBG_MSG("intelfbhw_cursor_reset\n");
-#endif
-
-	if (!dinfo->cursor.virtual)
-		return;
-
-	for (i = 64; i--; ) {
-		for (j = 0; j < 8; j++) {
-			writeb(0xff, addr + j+0);
-			writeb(0x00, addr + j+8);
-		}
-		addr += 16;
-	}
-}
-
-static irqreturn_t intelfbhw_irq(int irq, void *dev_id)
-{
-	u16 tmp;
-	struct intelfb_info *dinfo = dev_id;
-
-	spin_lock(&dinfo->int_lock);
-
-	tmp = INREG16(IIR);
-	if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
-		tmp &= PIPE_A_EVENT_INTERRUPT;
-	else
-		tmp &= VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
-
-	if (tmp == 0) {
-		spin_unlock(&dinfo->int_lock);
-		return IRQ_RETVAL(0); /* not us */
-	}
-
-	/* clear status bits 0-15 ASAP and don't touch bits 16-31 */
-	OUTREG(PIPEASTAT, INREG(PIPEASTAT));
-
-	OUTREG16(IIR, tmp);
-	if (dinfo->vsync.pan_display) {
-		dinfo->vsync.pan_display = 0;
-		OUTREG(DSPABASE, dinfo->vsync.pan_offset);
-	}
-
-	dinfo->vsync.count++;
-	wake_up_interruptible(&dinfo->vsync.wait);
-
-	spin_unlock(&dinfo->int_lock);
-
-	return IRQ_RETVAL(1);
-}
-
-int intelfbhw_enable_irq(struct intelfb_info *dinfo)
-{
-	u16 tmp;
-	if (!test_and_set_bit(0, &dinfo->irq_flags)) {
-		if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,
-				"intelfb", dinfo)) {
-			clear_bit(0, &dinfo->irq_flags);
-			return -EINVAL;
-		}
-
-		spin_lock_irq(&dinfo->int_lock);
-		OUTREG16(HWSTAM, 0xfffe); /* i830 DRM uses ffff */
-		OUTREG16(IMR, 0);
-	} else
-		spin_lock_irq(&dinfo->int_lock);
-
-	if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
-		tmp = PIPE_A_EVENT_INTERRUPT;
-	else
-		tmp = VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
-	if (tmp != INREG16(IER)) {
-		DBG_MSG("changing IER to 0x%X\n", tmp);
-		OUTREG16(IER, tmp);
-	}
-
-	spin_unlock_irq(&dinfo->int_lock);
-	return 0;
-}
-
-void intelfbhw_disable_irq(struct intelfb_info *dinfo)
-{
-	if (test_and_clear_bit(0, &dinfo->irq_flags)) {
-		if (dinfo->vsync.pan_display) {
-			dinfo->vsync.pan_display = 0;
-			OUTREG(DSPABASE, dinfo->vsync.pan_offset);
-		}
-		spin_lock_irq(&dinfo->int_lock);
-		OUTREG16(HWSTAM, 0xffff);
-		OUTREG16(IMR, 0xffff);
-		OUTREG16(IER, 0x0);
-
-		OUTREG16(IIR, INREG16(IIR)); /* clear IRQ requests */
-		spin_unlock_irq(&dinfo->int_lock);
-
-		free_irq(dinfo->pdev->irq, dinfo);
-	}
-}
-
-int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe)
-{
-	struct intelfb_vsync *vsync;
-	unsigned int count;
-	int ret;
-
-	switch (pipe) {
-		case 0:
-			vsync = &dinfo->vsync;
-			break;
-		default:
-			return -ENODEV;
-	}
-
-	ret = intelfbhw_enable_irq(dinfo);
-	if (ret)
-		return ret;
-
-	count = vsync->count;
-	ret = wait_event_interruptible_timeout(vsync->wait,
-					       count != vsync->count, HZ / 10);
-	if (ret < 0)
-		return ret;
-	if (ret == 0) {
-		DBG_MSG("wait_for_vsync timed out!\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
deleted file mode 100644
index 216ca20f259f..000000000000
--- a/drivers/video/intelfb/intelfbhw.h
+++ /dev/null
@@ -1,609 +0,0 @@
-#ifndef _INTELFBHW_H
-#define _INTELFBHW_H
-
-/* $DHD: intelfb/intelfbhw.h,v 1.5 2003/06/27 15:06:25 dawes Exp $ */
-
-
-/*** HW-specific data ***/
-
-/* Information about the 852GM/855GM variants */
-#define INTEL_85X_CAPID		0x44
-#define INTEL_85X_VARIANT_MASK		0x7
-#define INTEL_85X_VARIANT_SHIFT		5
-#define INTEL_VAR_855GME		0x0
-#define INTEL_VAR_855GM			0x4
-#define INTEL_VAR_852GME		0x2
-#define INTEL_VAR_852GM			0x5
-
-/* Information about DVO/LVDS Ports */
-#define DVOA_PORT  0x1
-#define DVOB_PORT  0x2
-#define DVOC_PORT  0x4
-#define LVDS_PORT  0x8
-
-/*
- * The Bridge device's PCI config space has information about the
- * fb aperture size and the amount of pre-reserved memory.
- */
-#define INTEL_GMCH_CTRL		0x52
-#define INTEL_GMCH_ENABLED		0x4
-#define INTEL_GMCH_MEM_MASK		0x1
-#define INTEL_GMCH_MEM_64M		0x1
-#define INTEL_GMCH_MEM_128M		0
-
-#define INTEL_830_GMCH_GMS_MASK		(0x7 << 4)
-#define INTEL_830_GMCH_GMS_DISABLED	(0x0 << 4)
-#define INTEL_830_GMCH_GMS_LOCAL	(0x1 << 4)
-#define INTEL_830_GMCH_GMS_STOLEN_512	(0x2 << 4)
-#define INTEL_830_GMCH_GMS_STOLEN_1024	(0x3 << 4)
-#define INTEL_830_GMCH_GMS_STOLEN_8192	(0x4 << 4)
-
-#define INTEL_855_GMCH_GMS_MASK		(0x7 << 4)
-#define INTEL_855_GMCH_GMS_DISABLED	(0x0 << 4)
-#define INTEL_855_GMCH_GMS_STOLEN_1M	(0x1 << 4)
-#define INTEL_855_GMCH_GMS_STOLEN_4M	(0x2 << 4)
-#define INTEL_855_GMCH_GMS_STOLEN_8M	(0x3 << 4)
-#define INTEL_855_GMCH_GMS_STOLEN_16M	(0x4 << 4)
-#define INTEL_855_GMCH_GMS_STOLEN_32M	(0x5 << 4)
-
-#define INTEL_915G_GMCH_GMS_STOLEN_48M	(0x6 << 4)
-#define INTEL_915G_GMCH_GMS_STOLEN_64M	(0x7 << 4)
-
-/* HW registers */
-
-/* Fence registers */
-#define FENCE			0x2000
-#define FENCE_NUM			8
-
-/* Primary ring buffer */
-#define PRI_RING_TAIL		0x2030
-#define RING_TAIL_MASK			0x001ffff8
-#define RING_INUSE			0x1
-
-#define PRI_RING_HEAD		0x2034
-#define RING_HEAD_WRAP_MASK		0x7ff
-#define RING_HEAD_WRAP_SHIFT		21
-#define RING_HEAD_MASK			0x001ffffc
-
-#define PRI_RING_START		0x2038
-#define RING_START_MASK			0xfffff000
-
-#define PRI_RING_LENGTH		0x203c
-#define RING_LENGTH_MASK		0x001ff000
-#define RING_REPORT_MASK		(0x3 << 1)
-#define RING_NO_REPORT			(0x0 << 1)
-#define RING_REPORT_64K			(0x1 << 1)
-#define RING_REPORT_4K			(0x2 << 1)
-#define RING_REPORT_128K		(0x3 << 1)
-#define RING_ENABLE			0x1
-
-/*
- * Tail can't wrap to any closer than RING_MIN_FREE bytes of the head,
- * and the last RING_MIN_FREE bytes need to be padded with MI_NOOP
- */
-#define RING_MIN_FREE			64
-
-#define IPEHR			0x2088
-
-#define INSTDONE		0x2090
-#define PRI_RING_EMPTY			1
-
-#define HWSTAM			0x2098
-#define IER			0x20A0
-#define IIR			0x20A4
-#define IMR			0x20A8
-#define VSYNC_PIPE_A_INTERRUPT		(1 << 7)
-#define PIPE_A_EVENT_INTERRUPT		(1 << 6)
-#define VSYNC_PIPE_B_INTERRUPT		(1 << 5)
-#define PIPE_B_EVENT_INTERRUPT		(1 << 4)
-#define HOST_PORT_EVENT_INTERRUPT	(1 << 3)
-#define CAPTURE_EVENT_INTERRUPT		(1 << 2)
-#define USER_DEFINED_INTERRUPT		(1 << 1)
-#define BREAKPOINT_INTERRUPT		1
-
-#define INSTPM			0x20c0
-#define SYNC_FLUSH_ENABLE		(1 << 5)
-
-#define INSTPS			0x20c4
-
-#define MEM_MODE		0x20cc
-
-#define MASK_SHIFT			16
-
-#define FW_BLC_0		0x20d8
-#define FW_DISPA_WM_SHIFT		0
-#define FW_DISPA_WM_MASK		0x3f
-#define FW_DISPA_BL_SHIFT		8
-#define FW_DISPA_BL_MASK		0xf
-#define FW_DISPB_WM_SHIFT		16
-#define FW_DISPB_WM_MASK		0x1f
-#define FW_DISPB_BL_SHIFT		24
-#define FW_DISPB_BL_MASK		0x7
-
-#define FW_BLC_1		0x20dc
-#define FW_DISPC_WM_SHIFT		0
-#define FW_DISPC_WM_MASK		0x1f
-#define FW_DISPC_BL_SHIFT		8
-#define FW_DISPC_BL_MASK		0x7
-
-#define GPIOA             0x5010
-#define GPIOB             0x5014
-#define GPIOC             0x5018 /* this may be external DDC on i830 */
-#define GPIOD             0x501C /* this is DVO DDC */
-#define GPIOE             0x5020 /* this is DVO i2C */
-#define GPIOF             0x5024
-
-/* PLL registers */
-#define VGA0_DIVISOR		0x06000
-#define VGA1_DIVISOR		0x06004
-#define VGAPD			0x06010
-#define VGAPD_0_P1_SHIFT		0
-#define VGAPD_0_P1_FORCE_DIV2		(1 << 5)
-#define VGAPD_0_P2_SHIFT		7
-#define VGAPD_1_P1_SHIFT		8
-#define VGAPD_1_P1_FORCE_DIV2		(1 << 13)
-#define VGAPD_1_P2_SHIFT		15
-
-#define DPLL_A			0x06014
-#define DPLL_B			0x06018
-#define DPLL_VCO_ENABLE			(1 << 31)
-#define DPLL_2X_CLOCK_ENABLE		(1 << 30)
-#define DPLL_SYNCLOCK_ENABLE		(1 << 29)
-#define DPLL_VGA_MODE_DISABLE		(1 << 28)
-#define DPLL_P2_MASK			1
-#define DPLL_P2_SHIFT			23
-#define DPLL_I9XX_P2_SHIFT              24
-#define DPLL_P1_FORCE_DIV2		(1 << 21)
-#define DPLL_P1_MASK			0x1f
-#define DPLL_P1_SHIFT			16
-#define DPLL_REFERENCE_SELECT_MASK	(0x3 << 13)
-#define DPLL_REFERENCE_DEFAULT		(0x0 << 13)
-#define DPLL_REFERENCE_TVCLK		(0x2 << 13)
-#define DPLL_RATE_SELECT_MASK		(1 << 8)
-#define DPLL_RATE_SELECT_FP0		(0 << 8)
-#define DPLL_RATE_SELECT_FP1		(1 << 8)
-
-#define FPA0			0x06040
-#define FPA1			0x06044
-#define FPB0			0x06048
-#define FPB1			0x0604c
-#define FP_DIVISOR_MASK			0x3f
-#define FP_N_DIVISOR_SHIFT		16
-#define FP_M1_DIVISOR_SHIFT		8
-#define FP_M2_DIVISOR_SHIFT		0
-
-/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
-/* Clock values are in units of kHz */
-#define PLL_REFCLK		48000
-#define MIN_CLOCK		25000
-#define MAX_CLOCK		350000
-
-/* Two pipes */
-#define PIPE_A			0
-#define PIPE_B			1
-#define PIPE_MASK		1
-
-/* palette registers */
-#define PALETTE_A		0x0a000
-#define PALETTE_B		0x0a800
-#ifndef PALETTE_8_ENTRIES
-#define PALETTE_8_ENTRIES		256
-#endif
-#define PALETTE_8_SIZE			(PALETTE_8_ENTRIES * 4)
-#define PALETTE_10_ENTRIES		128
-#define PALETTE_10_SIZE			(PALETTE_10_ENTRIES * 8)
-#define PALETTE_8_MASK			0xff
-#define PALETTE_8_RED_SHIFT		16
-#define PALETTE_8_GREEN_SHIFT		8
-#define PALETTE_8_BLUE_SHIFT		0
-
-/* CRTC registers */
-#define HTOTAL_A		0x60000
-#define HBLANK_A		0x60004
-#define HSYNC_A			0x60008
-#define VTOTAL_A		0x6000c
-#define VBLANK_A		0x60010
-#define VSYNC_A			0x60014
-#define SRC_SIZE_A		0x6001c
-#define BCLRPAT_A		0x60020
-
-#define HTOTAL_B		0x61000
-#define HBLANK_B		0x61004
-#define HSYNC_B			0x61008
-#define VTOTAL_B		0x6100c
-#define VBLANK_B		0x61010
-#define VSYNC_B			0x61014
-#define SRC_SIZE_B		0x6101c
-#define BCLRPAT_B		0x61020
-
-#define HTOTAL_MASK			0xfff
-#define HTOTAL_SHIFT			16
-#define HACTIVE_MASK			0x7ff
-#define HACTIVE_SHIFT			0
-#define HBLANKEND_MASK			0xfff
-#define HBLANKEND_SHIFT			16
-#define HBLANKSTART_MASK		0xfff
-#define HBLANKSTART_SHIFT		0
-#define HSYNCEND_MASK			0xfff
-#define HSYNCEND_SHIFT			16
-#define HSYNCSTART_MASK			0xfff
-#define HSYNCSTART_SHIFT		0
-#define VTOTAL_MASK			0xfff
-#define VTOTAL_SHIFT			16
-#define VACTIVE_MASK			0x7ff
-#define VACTIVE_SHIFT			0
-#define VBLANKEND_MASK			0xfff
-#define VBLANKEND_SHIFT			16
-#define VBLANKSTART_MASK		0xfff
-#define VBLANKSTART_SHIFT		0
-#define VSYNCEND_MASK			0xfff
-#define VSYNCEND_SHIFT			16
-#define VSYNCSTART_MASK			0xfff
-#define VSYNCSTART_SHIFT		0
-#define SRC_SIZE_HORIZ_MASK		0x7ff
-#define SRC_SIZE_HORIZ_SHIFT		16
-#define SRC_SIZE_VERT_MASK		0x7ff
-#define SRC_SIZE_VERT_SHIFT		0
-
-#define ADPA			0x61100
-#define ADPA_DAC_ENABLE			(1 << 31)
-#define ADPA_DAC_DISABLE		0
-#define ADPA_PIPE_SELECT_SHIFT		30
-#define ADPA_USE_VGA_HVPOLARITY		(1 << 15)
-#define ADPA_SETS_HVPOLARITY		0
-#define ADPA_DPMS_CONTROL_MASK		(0x3 << 10)
-#define ADPA_DPMS_D0			(0x0 << 10)
-#define ADPA_DPMS_D2			(0x1 << 10)
-#define ADPA_DPMS_D1			(0x2 << 10)
-#define ADPA_DPMS_D3			(0x3 << 10)
-#define ADPA_VSYNC_ACTIVE_SHIFT		4
-#define ADPA_HSYNC_ACTIVE_SHIFT		3
-#define ADPA_SYNC_ACTIVE_MASK		1
-#define ADPA_SYNC_ACTIVE_HIGH		1
-#define ADPA_SYNC_ACTIVE_LOW		0
-
-#define DVOA			0x61120
-#define DVOB			0x61140
-#define DVOC			0x61160
-#define LVDS			0x61180
-#define PORT_ENABLE		        (1 << 31)
-#define PORT_PIPE_SELECT_SHIFT	        30
-#define PORT_TV_FLAGS_MASK              0xFF
-#define PORT_TV_FLAGS                   0xC4	/* ripped from my BIOS
-						   to understand and correct */
-
-#define DVOA_SRCDIM		0x61124
-#define DVOB_SRCDIM		0x61144
-#define DVOC_SRCDIM		0x61164
-
-#define PIPEA_DSL		0x70000
-#define PIPEB_DSL		0x71000
-#define PIPEACONF		0x70008
-#define PIPEBCONF		0x71008
-#define PIPEASTAT		0x70024 /* bits 0-15 are "write 1 to clear" */
-#define PIPEBSTAT		0x71024
-
-#define PIPECONF_ENABLE			(1 << 31)
-#define PIPECONF_DISABLE		0
-#define PIPECONF_DOUBLE_WIDE		(1 << 30)
-#define PIPECONF_SINGLE_WIDE		0
-#define PIPECONF_LOCKED			(1 << 25)
-#define PIPECONF_UNLOCKED		0
-#define PIPECONF_GAMMA			(1 << 24)
-#define PIPECONF_PALETTE		0
-#define PIPECONF_PROGRESSIVE			(0 << 21)
-#define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
-#define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
-#define PIPECONF_INTERLACE_MASK			(7 << 21)
-
-/* enable bits, write 1 to enable */
-#define PIPESTAT_FIFO_UNDERRUN		(1 << 31)
-#define PIPESTAT_CRC_ERROR_EN		(1 << 29)
-#define PIPESTAT_CRC_DONE_EN		(1 << 28)
-#define PIPESTAT_HOTPLUG_EN		(1 << 26)
-#define PIPESTAT_VERTICAL_SYNC_EN	(1 << 25)
-#define PIPESTAT_DISPLINE_COMP_EN	(1 << 24)
-#define PIPESTAT_FLD_EVT_ODD_EN		(1 << 21)
-#define PIPESTAT_FLD_EVT_EVEN_EN	(1 << 20)
-#define PIPESTAT_TV_HOTPLUG_EN		(1 << 18)
-#define PIPESTAT_VBLANK_EN		(1 << 17)
-#define PIPESTAT_OVL_UPDATE_EN		(1 << 16)
-/* status bits, write 1 to clear */
-#define PIPESTAT_HOTPLUG_STATE		(1 << 15)
-#define PIPESTAT_CRC_ERROR		(1 << 13)
-#define PIPESTAT_CRC_DONE		(1 << 12)
-#define PIPESTAT_HOTPLUG		(1 << 10)
-#define PIPESTAT_VSYNC			(1 << 9)
-#define PIPESTAT_DISPLINE_COMP		(1 << 8)
-#define PIPESTAT_FLD_EVT_ODD		(1 << 5)
-#define PIPESTAT_FLD_EVT_EVEN		(1 << 4)
-#define PIPESTAT_TV_HOTPLUG		(1 << 2)
-#define PIPESTAT_VBLANK			(1 << 1)
-#define PIPESTAT_OVL_UPDATE		(1 << 0)
-
-#define DISPARB			0x70030
-#define DISPARB_AEND_MASK		0x1ff
-#define DISPARB_AEND_SHIFT		0
-#define DISPARB_BEND_MASK		0x3ff
-#define DISPARB_BEND_SHIFT		9
-
-/* Desktop HW cursor */
-#define CURSOR_CONTROL		0x70080
-#define CURSOR_ENABLE			(1 << 31)
-#define CURSOR_GAMMA_ENABLE		(1 << 30)
-#define CURSOR_STRIDE_MASK		(0x3 << 28)
-#define CURSOR_STRIDE_256		(0x0 << 28)
-#define CURSOR_STRIDE_512		(0x1 << 28)
-#define CURSOR_STRIDE_1K		(0x2 << 28)
-#define CURSOR_STRIDE_2K		(0x3 << 28)
-#define CURSOR_FORMAT_MASK		(0x7 << 24)
-#define CURSOR_FORMAT_2C		(0x0 << 24)
-#define CURSOR_FORMAT_3C		(0x1 << 24)
-#define CURSOR_FORMAT_4C		(0x2 << 24)
-#define CURSOR_FORMAT_ARGB		(0x4 << 24)
-#define CURSOR_FORMAT_XRGB		(0x5 << 24)
-
-/* Mobile HW cursor (and i810) */
-#define CURSOR_A_CONTROL	CURSOR_CONTROL
-#define CURSOR_B_CONTROL	0x700c0
-#define CURSOR_MODE_MASK		0x27
-#define CURSOR_MODE_DISABLE		0
-#define CURSOR_MODE_64_3C		0x04
-#define CURSOR_MODE_64_4C_AX		0x05
-#define CURSOR_MODE_64_4C		0x06
-#define CURSOR_MODE_64_32B_AX		0x07
-#define CURSOR_MODE_64_ARGB_AX		0x27
-#define CURSOR_PIPE_SELECT_SHIFT	28
-#define CURSOR_MOBILE_GAMMA_ENABLE	(1 << 26)
-#define CURSOR_MEM_TYPE_LOCAL		(1 << 25)
-
-/* All platforms (desktop has no pipe B) */
-#define CURSOR_A_BASEADDR	0x70084
-#define CURSOR_B_BASEADDR	0x700c4
-#define CURSOR_BASE_MASK		0xffffff00
-
-#define CURSOR_A_POSITION	0x70088
-#define CURSOR_B_POSITION	0x700c8
-#define CURSOR_POS_SIGN			(1 << 15)
-#define CURSOR_POS_MASK			0x7ff
-#define CURSOR_X_SHIFT			0
-#define CURSOR_Y_SHIFT			16
-
-#define CURSOR_A_PALETTE0	0x70090
-#define CURSOR_A_PALETTE1	0x70094
-#define CURSOR_A_PALETTE2	0x70098
-#define CURSOR_A_PALETTE3	0x7009c
-#define CURSOR_B_PALETTE0	0x700d0
-#define CURSOR_B_PALETTE1	0x700d4
-#define CURSOR_B_PALETTE2	0x700d8
-#define CURSOR_B_PALETTE3	0x700dc
-#define CURSOR_COLOR_MASK			0xff
-#define CURSOR_RED_SHIFT			16
-#define CURSOR_GREEN_SHIFT			8
-#define CURSOR_BLUE_SHIFT			0
-#define CURSOR_PALETTE_MASK			0xffffff
-
-/* Desktop only */
-#define CURSOR_SIZE		0x700a0
-#define CURSOR_SIZE_MASK		0x3ff
-#define CURSOR_SIZE_H_SHIFT		0
-#define CURSOR_SIZE_V_SHIFT		12
-
-#define DSPACNTR		0x70180
-#define DSPBCNTR		0x71180
-#define DISPPLANE_PLANE_ENABLE		(1 << 31)
-#define DISPPLANE_PLANE_DISABLE		0
-#define DISPPLANE_GAMMA_ENABLE		(1<<30)
-#define DISPPLANE_GAMMA_DISABLE		0
-#define DISPPLANE_PIXFORMAT_MASK	(0xf<<26)
-#define DISPPLANE_8BPP			(0x2<<26)
-#define DISPPLANE_15_16BPP		(0x4<<26)
-#define DISPPLANE_16BPP			(0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA	(0x6<<26)
-#define DISPPLANE_32BPP			(0x7<<26)
-#define DISPPLANE_STEREO_ENABLE		(1<<25)
-#define DISPPLANE_STEREO_DISABLE	0
-#define DISPPLANE_SEL_PIPE_SHIFT	24
-#define DISPPLANE_SRC_KEY_ENABLE	(1<<22)
-#define DISPPLANE_SRC_KEY_DISABLE	0
-#define DISPPLANE_LINE_DOUBLE		(1<<20)
-#define DISPPLANE_NO_LINE_DOUBLE	0
-#define DISPPLANE_STEREO_POLARITY_FIRST	0
-#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
-/* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE	(1<<15)
-#define DISPPLANE_ALPHA_TRANS_DISABLE	0
-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA	0
-#define DISPPLANE_SPRITE_ABOVE_OVERLAY	1
-
-#define DSPABASE		0x70184
-#define DSPASTRIDE		0x70188
-
-#define DSPBBASE		0x71184
-#define DSPBSTRIDE		0x71188
-
-#define VGACNTRL		0x71400
-#define VGA_DISABLE			(1 << 31)
-#define VGA_ENABLE			0
-#define VGA_PIPE_SELECT_SHIFT		29
-#define VGA_PALETTE_READ_SELECT		23
-#define VGA_PALETTE_A_WRITE_DISABLE	(1 << 22)
-#define VGA_PALETTE_B_WRITE_DISABLE	(1 << 21)
-#define VGA_LEGACY_PALETTE		(1 << 20)
-#define VGA_6BIT_DAC			0
-#define VGA_8BIT_DAC			(1 << 20)
-
-#define ADD_ID			0x71408
-#define ADD_ID_MASK			0xff
-
-/* BIOS scratch area registers (830M and 845G). */
-#define SWF0			0x71410
-#define SWF1			0x71414
-#define SWF2			0x71418
-#define SWF3			0x7141c
-#define SWF4			0x71420
-#define SWF5			0x71424
-#define SWF6			0x71428
-
-/* BIOS scratch area registers (852GM, 855GM, 865G). */
-#define SWF00			0x70410
-#define SWF01			0x70414
-#define SWF02			0x70418
-#define SWF03			0x7041c
-#define SWF04			0x70420
-#define SWF05			0x70424
-#define SWF06			0x70428
-
-#define SWF10			SWF0
-#define SWF11			SWF1
-#define SWF12			SWF2
-#define SWF13			SWF3
-#define SWF14			SWF4
-#define SWF15			SWF5
-#define SWF16			SWF6
-
-#define SWF30			0x72414
-#define SWF31			0x72418
-#define SWF32			0x7241c
-
-/* Memory Commands */
-#define MI_NOOP			(0x00 << 23)
-#define MI_NOOP_WRITE_ID		(1 << 22)
-#define MI_NOOP_ID_MASK			((1 << 22) - 1)
-
-#define MI_FLUSH		(0x04 << 23)
-#define MI_WRITE_DIRTY_STATE		(1 << 4)
-#define MI_END_SCENE			(1 << 3)
-#define MI_INHIBIT_RENDER_CACHE_FLUSH	(1 << 2)
-#define MI_INVALIDATE_MAP_CACHE		(1 << 0)
-
-#define MI_STORE_DWORD_IMM	((0x20 << 23) | 1)
-
-/* 2D Commands */
-#define COLOR_BLT_CMD		((2 << 29) | (0x40 << 22) | 3)
-#define XY_COLOR_BLT_CMD	((2 << 29) | (0x50 << 22) | 4)
-#define XY_SETUP_CLIP_BLT_CMD	((2 << 29) | (0x03 << 22) | 1)
-#define XY_SRC_COPY_BLT_CMD	((2 << 29) | (0x53 << 22) | 6)
-#define SRC_COPY_BLT_CMD	((2 << 29) | (0x43 << 22) | 4)
-#define XY_MONO_PAT_BLT_CMD	((2 << 29) | (0x52 << 22) | 7)
-#define XY_MONO_SRC_BLT_CMD	((2 << 29) | (0x54 << 22) | 6)
-#define XY_MONO_SRC_IMM_BLT_CMD	((2 << 29) | (0x71 << 22) | 5)
-#define TXT_IMM_BLT_CMD	        ((2 << 29) | (0x30 << 22) | 2)
-#define SETUP_BLT_CMD	        ((2 << 29) | (0x00 << 22) | 6)
-
-#define DW_LENGTH_MASK			0xff
-
-#define WRITE_ALPHA			(1 << 21)
-#define WRITE_RGB			(1 << 20)
-#define VERT_SEED			(3 << 8)
-#define HORIZ_SEED			(3 << 12)
-
-#define COLOR_DEPTH_8			(0 << 24)
-#define COLOR_DEPTH_16			(1 << 24)
-#define COLOR_DEPTH_32			(3 << 24)
-
-#define SRC_ROP_GXCOPY			0xcc
-#define SRC_ROP_GXXOR			0x66
-
-#define PAT_ROP_GXCOPY                  0xf0
-#define PAT_ROP_GXXOR                   0x5a
-
-#define PITCH_SHIFT			0
-#define ROP_SHIFT			16
-#define WIDTH_SHIFT			0
-#define HEIGHT_SHIFT			16
-
-/* in bytes */
-#define MAX_MONO_IMM_SIZE		128
-
-
-/*** Macros ***/
-
-/* I/O macros */
-#define INREG8(addr)	      readb((u8 __iomem *)(dinfo->mmio_base + (addr)))
-#define INREG16(addr)	      readw((u16 __iomem *)(dinfo->mmio_base + (addr)))
-#define INREG(addr)	      readl((u32 __iomem *)(dinfo->mmio_base + (addr)))
-#define OUTREG8(addr, val)    writeb((val),(u8 __iomem *)(dinfo->mmio_base + \
-							   (addr)))
-#define OUTREG16(addr, val)    writew((val),(u16 __iomem *)(dinfo->mmio_base + \
-							   (addr)))
-#define OUTREG(addr, val)     writel((val),(u32 __iomem *)(dinfo->mmio_base + \
-                                     (addr)))
-
-/* Ring buffer macros */
-#define OUT_RING(n)	do {						\
-	writel((n), (u32 __iomem *)(dinfo->ring.virtual + dinfo->ring_tail));\
-	dinfo->ring_tail += 4;						\
-	dinfo->ring_tail &= dinfo->ring_tail_mask;			\
-} while (0)
-
-#define START_RING(n)	do {						\
-	if (dinfo->ring_space < (n) * 4)				\
-		wait_ring(dinfo,(n) * 4);				\
-	dinfo->ring_space -= (n) * 4;					\
-} while (0)
-
-#define ADVANCE_RING()	do {						\
-	OUTREG(PRI_RING_TAIL, dinfo->ring_tail);                        \
-} while (0)
-
-#define DO_RING_IDLE()	do {						\
-	u32 head, tail;							\
-	do {								\
-		head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;		\
-		tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;		\
-		udelay(10);						\
-	} while (head != tail);						\
-} while (0)
-
-
-/* function protoypes */
-extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo);
-extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
-				int *stolen_size);
-extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
-extern const char *intelfbhw_dvo_to_string(int dvo);
-extern int intelfbhw_validate_mode(struct intelfb_info *dinfo,
-				   struct fb_var_screeninfo *var);
-extern int intelfbhw_pan_display(struct fb_var_screeninfo *var,
-				 struct fb_info *info);
-extern void intelfbhw_do_blank(int blank, struct fb_info *info);
-extern void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
-				unsigned red, unsigned green, unsigned blue,
-				unsigned transp);
-extern int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
-				   struct intelfb_hwstate *hw, int flag);
-extern void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
-				     struct intelfb_hwstate *hw);
-extern int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
-				struct intelfb_hwstate *hw,
-				struct fb_var_screeninfo *var);
-extern int intelfbhw_program_mode(struct intelfb_info *dinfo,
-				  const struct intelfb_hwstate *hw, int blank);
-extern void intelfbhw_do_sync(struct intelfb_info *dinfo);
-extern void intelfbhw_2d_stop(struct intelfb_info *dinfo);
-extern void intelfbhw_2d_start(struct intelfb_info *dinfo);
-extern void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y,
-				  u32 w, u32 h, u32 color, u32 pitch, u32 bpp,
-				  u32 rop);
-extern void intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
-				u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch,
-				u32 bpp);
-extern int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg,
-				  u32 w, u32 h, const u8* cdat, u32 x, u32 y,
-				  u32 pitch, u32 bpp);
-extern void intelfbhw_cursor_init(struct intelfb_info *dinfo);
-extern void intelfbhw_cursor_hide(struct intelfb_info *dinfo);
-extern void intelfbhw_cursor_show(struct intelfb_info *dinfo);
-extern void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y);
-extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,
-				      u32 fg);
-extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width,
-				  int height, u8 *data);
-extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
-extern int intelfbhw_enable_irq(struct intelfb_info *dinfo);
-extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
-extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
-extern int intelfbhw_active_pipe(const struct intelfb_hwstate *hw);
-
-#endif /* _INTELFBHW_H */
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
deleted file mode 100644
index 87790e9644d0..000000000000
--- a/drivers/video/jz4740_fb.c
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
- *	JZ4740 SoC LCD framebuffer driver
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under  the terms of  the GNU General Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-
-#include <linux/console.h>
-#include <linux/fb.h>
-
-#include <linux/dma-mapping.h>
-
-#include <asm/mach-jz4740/jz4740_fb.h>
-#include <asm/mach-jz4740/gpio.h>
-
-#define JZ_REG_LCD_CFG		0x00
-#define JZ_REG_LCD_VSYNC	0x04
-#define JZ_REG_LCD_HSYNC	0x08
-#define JZ_REG_LCD_VAT		0x0C
-#define JZ_REG_LCD_DAH		0x10
-#define JZ_REG_LCD_DAV		0x14
-#define JZ_REG_LCD_PS		0x18
-#define JZ_REG_LCD_CLS		0x1C
-#define JZ_REG_LCD_SPL		0x20
-#define JZ_REG_LCD_REV		0x24
-#define JZ_REG_LCD_CTRL		0x30
-#define JZ_REG_LCD_STATE	0x34
-#define JZ_REG_LCD_IID		0x38
-#define JZ_REG_LCD_DA0		0x40
-#define JZ_REG_LCD_SA0		0x44
-#define JZ_REG_LCD_FID0		0x48
-#define JZ_REG_LCD_CMD0		0x4C
-#define JZ_REG_LCD_DA1		0x50
-#define JZ_REG_LCD_SA1		0x54
-#define JZ_REG_LCD_FID1		0x58
-#define JZ_REG_LCD_CMD1		0x5C
-
-#define JZ_LCD_CFG_SLCD			BIT(31)
-#define JZ_LCD_CFG_PS_DISABLE		BIT(23)
-#define JZ_LCD_CFG_CLS_DISABLE		BIT(22)
-#define JZ_LCD_CFG_SPL_DISABLE		BIT(21)
-#define JZ_LCD_CFG_REV_DISABLE		BIT(20)
-#define JZ_LCD_CFG_HSYNCM		BIT(19)
-#define JZ_LCD_CFG_PCLKM		BIT(18)
-#define JZ_LCD_CFG_INV			BIT(17)
-#define JZ_LCD_CFG_SYNC_DIR		BIT(16)
-#define JZ_LCD_CFG_PS_POLARITY		BIT(15)
-#define JZ_LCD_CFG_CLS_POLARITY		BIT(14)
-#define JZ_LCD_CFG_SPL_POLARITY		BIT(13)
-#define JZ_LCD_CFG_REV_POLARITY		BIT(12)
-#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW	BIT(11)
-#define JZ_LCD_CFG_PCLK_FALLING_EDGE	BIT(10)
-#define JZ_LCD_CFG_DE_ACTIVE_LOW	BIT(9)
-#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW	BIT(8)
-#define JZ_LCD_CFG_18_BIT		BIT(7)
-#define JZ_LCD_CFG_PDW			(BIT(5) | BIT(4))
-#define JZ_LCD_CFG_MODE_MASK 0xf
-
-#define JZ_LCD_CTRL_BURST_4		(0x0 << 28)
-#define JZ_LCD_CTRL_BURST_8		(0x1 << 28)
-#define JZ_LCD_CTRL_BURST_16		(0x2 << 28)
-#define JZ_LCD_CTRL_RGB555		BIT(27)
-#define JZ_LCD_CTRL_OFUP		BIT(26)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_16	(0x0 << 24)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_4	(0x1 << 24)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_2	(0x2 << 24)
-#define JZ_LCD_CTRL_PDD_MASK		(0xff << 16)
-#define JZ_LCD_CTRL_EOF_IRQ		BIT(13)
-#define JZ_LCD_CTRL_SOF_IRQ		BIT(12)
-#define JZ_LCD_CTRL_OFU_IRQ		BIT(11)
-#define JZ_LCD_CTRL_IFU0_IRQ		BIT(10)
-#define JZ_LCD_CTRL_IFU1_IRQ		BIT(9)
-#define JZ_LCD_CTRL_DD_IRQ		BIT(8)
-#define JZ_LCD_CTRL_QDD_IRQ		BIT(7)
-#define JZ_LCD_CTRL_REVERSE_ENDIAN	BIT(6)
-#define JZ_LCD_CTRL_LSB_FISRT		BIT(5)
-#define JZ_LCD_CTRL_DISABLE		BIT(4)
-#define JZ_LCD_CTRL_ENABLE		BIT(3)
-#define JZ_LCD_CTRL_BPP_1		0x0
-#define JZ_LCD_CTRL_BPP_2		0x1
-#define JZ_LCD_CTRL_BPP_4		0x2
-#define JZ_LCD_CTRL_BPP_8		0x3
-#define JZ_LCD_CTRL_BPP_15_16		0x4
-#define JZ_LCD_CTRL_BPP_18_24		0x5
-
-#define JZ_LCD_CMD_SOF_IRQ BIT(31)
-#define JZ_LCD_CMD_EOF_IRQ BIT(30)
-#define JZ_LCD_CMD_ENABLE_PAL BIT(28)
-
-#define JZ_LCD_SYNC_MASK 0x3ff
-
-#define JZ_LCD_STATE_DISABLED BIT(0)
-
-struct jzfb_framedesc {
-	uint32_t next;
-	uint32_t addr;
-	uint32_t id;
-	uint32_t cmd;
-} __packed;
-
-struct jzfb {
-	struct fb_info *fb;
-	struct platform_device *pdev;
-	void __iomem *base;
-	struct resource *mem;
-	struct jz4740_fb_platform_data *pdata;
-
-	size_t vidmem_size;
-	void *vidmem;
-	dma_addr_t vidmem_phys;
-	struct jzfb_framedesc *framedesc;
-	dma_addr_t framedesc_phys;
-
-	struct clk *ldclk;
-	struct clk *lpclk;
-
-	unsigned is_enabled:1;
-	struct mutex lock;
-
-	uint32_t pseudo_palette[16];
-};
-
-static const struct fb_fix_screeninfo jzfb_fix = {
-	.id		= "JZ4740 FB",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_TRUECOLOR,
-	.xpanstep	= 0,
-	.ypanstep	= 0,
-	.ywrapstep	= 0,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
-	JZ_GPIO_BULK_PIN(LCD_PCLK),
-	JZ_GPIO_BULK_PIN(LCD_HSYNC),
-	JZ_GPIO_BULK_PIN(LCD_VSYNC),
-	JZ_GPIO_BULK_PIN(LCD_DE),
-	JZ_GPIO_BULK_PIN(LCD_PS),
-	JZ_GPIO_BULK_PIN(LCD_REV),
-	JZ_GPIO_BULK_PIN(LCD_CLS),
-	JZ_GPIO_BULK_PIN(LCD_SPL),
-};
-
-static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
-	JZ_GPIO_BULK_PIN(LCD_DATA0),
-	JZ_GPIO_BULK_PIN(LCD_DATA1),
-	JZ_GPIO_BULK_PIN(LCD_DATA2),
-	JZ_GPIO_BULK_PIN(LCD_DATA3),
-	JZ_GPIO_BULK_PIN(LCD_DATA4),
-	JZ_GPIO_BULK_PIN(LCD_DATA5),
-	JZ_GPIO_BULK_PIN(LCD_DATA6),
-	JZ_GPIO_BULK_PIN(LCD_DATA7),
-	JZ_GPIO_BULK_PIN(LCD_DATA8),
-	JZ_GPIO_BULK_PIN(LCD_DATA9),
-	JZ_GPIO_BULK_PIN(LCD_DATA10),
-	JZ_GPIO_BULK_PIN(LCD_DATA11),
-	JZ_GPIO_BULK_PIN(LCD_DATA12),
-	JZ_GPIO_BULK_PIN(LCD_DATA13),
-	JZ_GPIO_BULK_PIN(LCD_DATA14),
-	JZ_GPIO_BULK_PIN(LCD_DATA15),
-	JZ_GPIO_BULK_PIN(LCD_DATA16),
-	JZ_GPIO_BULK_PIN(LCD_DATA17),
-};
-
-static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
-{
-	unsigned int num;
-
-	switch (jzfb->pdata->lcd_type) {
-	case JZ_LCD_TYPE_GENERIC_16_BIT:
-		num = 4;
-		break;
-	case JZ_LCD_TYPE_GENERIC_18_BIT:
-		num = 4;
-		break;
-	case JZ_LCD_TYPE_8BIT_SERIAL:
-		num = 3;
-		break;
-	case JZ_LCD_TYPE_SPECIAL_TFT_1:
-	case JZ_LCD_TYPE_SPECIAL_TFT_2:
-	case JZ_LCD_TYPE_SPECIAL_TFT_3:
-		num = 8;
-		break;
-	default:
-		num = 0;
-		break;
-	}
-	return num;
-}
-
-static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
-{
-	unsigned int num;
-
-	switch (jzfb->pdata->lcd_type) {
-	case JZ_LCD_TYPE_GENERIC_16_BIT:
-		num = 16;
-		break;
-	case JZ_LCD_TYPE_GENERIC_18_BIT:
-		num = 18;
-		break;
-	case JZ_LCD_TYPE_8BIT_SERIAL:
-		num = 8;
-		break;
-	case JZ_LCD_TYPE_SPECIAL_TFT_1:
-	case JZ_LCD_TYPE_SPECIAL_TFT_2:
-	case JZ_LCD_TYPE_SPECIAL_TFT_3:
-		if (jzfb->pdata->bpp == 18)
-			num = 18;
-		else
-			num = 16;
-		break;
-	default:
-		num = 0;
-		break;
-	}
-	return num;
-}
-
-/* Based on CNVT_TOHW macro from skeletonfb.c */
-static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
-	struct fb_bitfield *bf)
-{
-	return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset;
-}
-
-static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			unsigned blue, unsigned transp, struct fb_info *fb)
-{
-	uint32_t color;
-
-	if (regno >= 16)
-		return -EINVAL;
-
-	color = jzfb_convert_color_to_hw(red, &fb->var.red);
-	color |= jzfb_convert_color_to_hw(green, &fb->var.green);
-	color |= jzfb_convert_color_to_hw(blue, &fb->var.blue);
-	color |= jzfb_convert_color_to_hw(transp, &fb->var.transp);
-
-	((uint32_t *)(fb->pseudo_palette))[regno] = color;
-
-	return 0;
-}
-
-static int jzfb_get_controller_bpp(struct jzfb *jzfb)
-{
-	switch (jzfb->pdata->bpp) {
-	case 18:
-	case 24:
-		return 32;
-	case 15:
-		return 16;
-	default:
-		return jzfb->pdata->bpp;
-	}
-}
-
-static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb,
-	struct fb_var_screeninfo *var)
-{
-	size_t i;
-	struct fb_videomode *mode = jzfb->pdata->modes;
-
-	for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
-		if (mode->xres == var->xres && mode->yres == var->yres)
-			return mode;
-	}
-
-	return NULL;
-}
-
-static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
-{
-	struct jzfb *jzfb = fb->par;
-	struct fb_videomode *mode;
-
-	if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
-		var->bits_per_pixel != jzfb->pdata->bpp)
-		return -EINVAL;
-
-	mode = jzfb_get_mode(jzfb, var);
-	if (mode == NULL)
-		return -EINVAL;
-
-	fb_videomode_to_var(var, mode);
-
-	switch (jzfb->pdata->bpp) {
-	case 8:
-		break;
-	case 15:
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->green.offset = 6;
-		var->green.length = 5;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		break;
-	case 16:
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		break;
-	case 18:
-		var->red.offset = 16;
-		var->red.length = 6;
-		var->green.offset = 8;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 6;
-		var->bits_per_pixel = 32;
-		break;
-	case 32:
-	case 24:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->bits_per_pixel = 32;
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int jzfb_set_par(struct fb_info *info)
-{
-	struct jzfb *jzfb = info->par;
-	struct jz4740_fb_platform_data *pdata = jzfb->pdata;
-	struct fb_var_screeninfo *var = &info->var;
-	struct fb_videomode *mode;
-	uint16_t hds, vds;
-	uint16_t hde, vde;
-	uint16_t ht, vt;
-	uint32_t ctrl;
-	uint32_t cfg;
-	unsigned long rate;
-
-	mode = jzfb_get_mode(jzfb, var);
-	if (mode == NULL)
-		return -EINVAL;
-
-	if (mode == info->mode)
-		return 0;
-
-	info->mode = mode;
-
-	hds = mode->hsync_len + mode->left_margin;
-	hde = hds + mode->xres;
-	ht = hde + mode->right_margin;
-
-	vds = mode->vsync_len + mode->upper_margin;
-	vde = vds + mode->yres;
-	vt = vde + mode->lower_margin;
-
-	ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
-
-	switch (pdata->bpp) {
-	case 1:
-		ctrl |= JZ_LCD_CTRL_BPP_1;
-		break;
-	case 2:
-		ctrl |= JZ_LCD_CTRL_BPP_2;
-		break;
-	case 4:
-		ctrl |= JZ_LCD_CTRL_BPP_4;
-		break;
-	case 8:
-		ctrl |= JZ_LCD_CTRL_BPP_8;
-	break;
-	case 15:
-		ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
-	case 16:
-		ctrl |= JZ_LCD_CTRL_BPP_15_16;
-		break;
-	case 18:
-	case 24:
-	case 32:
-		ctrl |= JZ_LCD_CTRL_BPP_18_24;
-		break;
-	default:
-		break;
-	}
-
-	cfg = pdata->lcd_type & 0xf;
-
-	if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
-		cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
-
-	if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
-		cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
-
-	if (pdata->pixclk_falling_edge)
-		cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
-
-	if (pdata->date_enable_active_low)
-		cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
-
-	if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
-		cfg |= JZ_LCD_CFG_18_BIT;
-
-	if (mode->pixclock) {
-		rate = PICOS2KHZ(mode->pixclock) * 1000;
-		mode->refresh = rate / vt / ht;
-	} else {
-		if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
-			rate = mode->refresh * (vt + 2 * mode->xres) * ht;
-		else
-			rate = mode->refresh * vt * ht;
-
-		mode->pixclock = KHZ2PICOS(rate / 1000);
-	}
-
-	mutex_lock(&jzfb->lock);
-	if (!jzfb->is_enabled)
-		clk_enable(jzfb->ldclk);
-	else
-		ctrl |= JZ_LCD_CTRL_ENABLE;
-
-	switch (pdata->lcd_type) {
-	case JZ_LCD_TYPE_SPECIAL_TFT_1:
-	case JZ_LCD_TYPE_SPECIAL_TFT_2:
-	case JZ_LCD_TYPE_SPECIAL_TFT_3:
-		writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL);
-		writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS);
-		writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS);
-		writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV);
-		break;
-	default:
-		cfg |= JZ_LCD_CFG_PS_DISABLE;
-		cfg |= JZ_LCD_CFG_CLS_DISABLE;
-		cfg |= JZ_LCD_CFG_SPL_DISABLE;
-		cfg |= JZ_LCD_CFG_REV_DISABLE;
-		break;
-	}
-
-	writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
-	writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
-
-	writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
-
-	writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
-	writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
-
-	writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
-
-	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
-
-	if (!jzfb->is_enabled)
-		clk_disable_unprepare(jzfb->ldclk);
-
-	mutex_unlock(&jzfb->lock);
-
-	clk_set_rate(jzfb->lpclk, rate);
-	clk_set_rate(jzfb->ldclk, rate * 3);
-
-	return 0;
-}
-
-static void jzfb_enable(struct jzfb *jzfb)
-{
-	uint32_t ctrl;
-
-	clk_prepare_enable(jzfb->ldclk);
-
-	jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
-	writel(0, jzfb->base + JZ_REG_LCD_STATE);
-
-	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
-
-	ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
-	ctrl |= JZ_LCD_CTRL_ENABLE;
-	ctrl &= ~JZ_LCD_CTRL_DISABLE;
-	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
-}
-
-static void jzfb_disable(struct jzfb *jzfb)
-{
-	uint32_t ctrl;
-
-	ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
-	ctrl |= JZ_LCD_CTRL_DISABLE;
-	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
-	do {
-		ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
-	} while (!(ctrl & JZ_LCD_STATE_DISABLED));
-
-	jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
-	clk_disable_unprepare(jzfb->ldclk);
-}
-
-static int jzfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct jzfb *jzfb = info->par;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		mutex_lock(&jzfb->lock);
-		if (jzfb->is_enabled) {
-			mutex_unlock(&jzfb->lock);
-			return 0;
-		}
-
-		jzfb_enable(jzfb);
-		jzfb->is_enabled = 1;
-
-		mutex_unlock(&jzfb->lock);
-		break;
-	default:
-		mutex_lock(&jzfb->lock);
-		if (!jzfb->is_enabled) {
-			mutex_unlock(&jzfb->lock);
-			return 0;
-		}
-
-		jzfb_disable(jzfb);
-		jzfb->is_enabled = 0;
-
-		mutex_unlock(&jzfb->lock);
-		break;
-	}
-
-	return 0;
-}
-
-static int jzfb_alloc_devmem(struct jzfb *jzfb)
-{
-	int max_videosize = 0;
-	struct fb_videomode *mode = jzfb->pdata->modes;
-	void *page;
-	int i;
-
-	for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
-		if (max_videosize < mode->xres * mode->yres)
-			max_videosize = mode->xres * mode->yres;
-	}
-
-	max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
-
-	jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
-					sizeof(*jzfb->framedesc),
-					&jzfb->framedesc_phys, GFP_KERNEL);
-
-	if (!jzfb->framedesc)
-		return -ENOMEM;
-
-	jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
-	jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
-					jzfb->vidmem_size,
-					&jzfb->vidmem_phys, GFP_KERNEL);
-
-	if (!jzfb->vidmem)
-		goto err_free_framedesc;
-
-	for (page = jzfb->vidmem;
-		 page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
-		 page += PAGE_SIZE) {
-		SetPageReserved(virt_to_page(page));
-	}
-
-	jzfb->framedesc->next = jzfb->framedesc_phys;
-	jzfb->framedesc->addr = jzfb->vidmem_phys;
-	jzfb->framedesc->id = 0xdeafbead;
-	jzfb->framedesc->cmd = 0;
-	jzfb->framedesc->cmd |= max_videosize / 4;
-
-	return 0;
-
-err_free_framedesc:
-	dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
-				jzfb->framedesc, jzfb->framedesc_phys);
-	return -ENOMEM;
-}
-
-static void jzfb_free_devmem(struct jzfb *jzfb)
-{
-	dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
-				jzfb->vidmem, jzfb->vidmem_phys);
-	dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
-				jzfb->framedesc, jzfb->framedesc_phys);
-}
-
-static struct  fb_ops jzfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = jzfb_check_var,
-	.fb_set_par = jzfb_set_par,
-	.fb_blank = jzfb_blank,
-	.fb_fillrect	= sys_fillrect,
-	.fb_copyarea	= sys_copyarea,
-	.fb_imageblit	= sys_imageblit,
-	.fb_setcolreg = jzfb_setcolreg,
-};
-
-static int jzfb_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct jzfb *jzfb;
-	struct fb_info *fb;
-	struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
-	struct resource *mem;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "Missing platform data\n");
-		return -ENXIO;
-	}
-
-	fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
-	if (!fb) {
-		dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
-		return -ENOMEM;
-	}
-
-	fb->fbops = &jzfb_ops;
-	fb->flags = FBINFO_DEFAULT;
-
-	jzfb = fb->par;
-	jzfb->pdev = pdev;
-	jzfb->pdata = pdata;
-
-	jzfb->ldclk = devm_clk_get(&pdev->dev, "lcd");
-	if (IS_ERR(jzfb->ldclk)) {
-		ret = PTR_ERR(jzfb->ldclk);
-		dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
-		goto err_framebuffer_release;
-	}
-
-	jzfb->lpclk = devm_clk_get(&pdev->dev, "lcd_pclk");
-	if (IS_ERR(jzfb->lpclk)) {
-		ret = PTR_ERR(jzfb->lpclk);
-		dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
-		goto err_framebuffer_release;
-	}
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	jzfb->base = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(jzfb->base)) {
-		ret = PTR_ERR(jzfb->base);
-		goto err_framebuffer_release;
-	}
-
-	platform_set_drvdata(pdev, jzfb);
-
-	mutex_init(&jzfb->lock);
-
-	fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
-				 &fb->modelist);
-	fb_videomode_to_var(&fb->var, pdata->modes);
-	fb->var.bits_per_pixel = pdata->bpp;
-	jzfb_check_var(&fb->var, fb);
-
-	ret = jzfb_alloc_devmem(jzfb);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to allocate video memory\n");
-		goto err_framebuffer_release;
-	}
-
-	fb->fix = jzfb_fix;
-	fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
-	fb->fix.mmio_start = mem->start;
-	fb->fix.mmio_len = resource_size(mem);
-	fb->fix.smem_start = jzfb->vidmem_phys;
-	fb->fix.smem_len =  fb->fix.line_length * fb->var.yres;
-	fb->screen_base = jzfb->vidmem;
-	fb->pseudo_palette = jzfb->pseudo_palette;
-
-	fb_alloc_cmap(&fb->cmap, 256, 0);
-
-	clk_prepare_enable(jzfb->ldclk);
-	jzfb->is_enabled = 1;
-
-	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
-
-	fb->mode = NULL;
-	jzfb_set_par(fb);
-
-	jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
-	ret = register_framebuffer(fb);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
-		goto err_free_devmem;
-	}
-
-	jzfb->fb = fb;
-
-	return 0;
-
-err_free_devmem:
-	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
-	fb_dealloc_cmap(&fb->cmap);
-	jzfb_free_devmem(jzfb);
-err_framebuffer_release:
-	framebuffer_release(fb);
-	return ret;
-}
-
-static int jzfb_remove(struct platform_device *pdev)
-{
-	struct jzfb *jzfb = platform_get_drvdata(pdev);
-
-	jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
-
-	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
-	fb_dealloc_cmap(&jzfb->fb->cmap);
-	jzfb_free_devmem(jzfb);
-
-	framebuffer_release(jzfb->fb);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int jzfb_suspend(struct device *dev)
-{
-	struct jzfb *jzfb = dev_get_drvdata(dev);
-
-	console_lock();
-	fb_set_suspend(jzfb->fb, 1);
-	console_unlock();
-
-	mutex_lock(&jzfb->lock);
-	if (jzfb->is_enabled)
-		jzfb_disable(jzfb);
-	mutex_unlock(&jzfb->lock);
-
-	return 0;
-}
-
-static int jzfb_resume(struct device *dev)
-{
-	struct jzfb *jzfb = dev_get_drvdata(dev);
-	clk_prepare_enable(jzfb->ldclk);
-
-	mutex_lock(&jzfb->lock);
-	if (jzfb->is_enabled)
-		jzfb_enable(jzfb);
-	mutex_unlock(&jzfb->lock);
-
-	console_lock();
-	fb_set_suspend(jzfb->fb, 0);
-	console_unlock();
-
-	return 0;
-}
-
-static const struct dev_pm_ops jzfb_pm_ops = {
-	.suspend	= jzfb_suspend,
-	.resume		= jzfb_resume,
-	.poweroff	= jzfb_suspend,
-	.restore	= jzfb_resume,
-};
-
-#define JZFB_PM_OPS (&jzfb_pm_ops)
-
-#else
-#define JZFB_PM_OPS NULL
-#endif
-
-static struct platform_driver jzfb_driver = {
-	.probe = jzfb_probe,
-	.remove = jzfb_remove,
-	.driver = {
-		.name = "jz4740-fb",
-		.pm = JZFB_PM_OPS,
-	},
-};
-module_platform_driver(jzfb_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver");
-MODULE_ALIAS("platform:jz4740-fb");
diff --git a/drivers/video/kyro/Makefile b/drivers/video/kyro/Makefile
deleted file mode 100644
index 2fd66f551bae..000000000000
--- a/drivers/video/kyro/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Kyro framebuffer driver
-#
-
-obj-$(CONFIG_FB_KYRO)	+= kyrofb.o
-
-kyrofb-objs	:= STG4000Ramdac.o STG4000VTG.o STG4000OverlayDevice.o \
-		   STG4000InitDevice.o fbdev.o
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
deleted file mode 100644
index 1d3f2080aa6f..000000000000
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- *  linux/drivers/video/kyro/STG4000InitDevice.c
- *
- *  Copyright (C) 2000 Imagination Technologies Ltd
- *  Copyright (C) 2002 STMicroelectronics
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include "STG4000Reg.h"
-#include "STG4000Interface.h"
-
-/* SDRAM fixed settings */
-#define SDRAM_CFG_0   0x49A1
-#define SDRAM_CFG_1   0xA732
-#define SDRAM_CFG_2   0x31
-#define SDRAM_ARB_CFG 0xA0
-#define SDRAM_REFRESH 0x20
-
-/* Reset values */
-#define PMX2_SOFTRESET_DAC_RST		0x0001
-#define PMX2_SOFTRESET_C1_RST		0x0004
-#define PMX2_SOFTRESET_C2_RST		0x0008
-#define PMX2_SOFTRESET_3D_RST		0x0010
-#define PMX2_SOFTRESET_VIDIN_RST	0x0020
-#define PMX2_SOFTRESET_TLB_RST		0x0040
-#define PMX2_SOFTRESET_SD_RST		0x0080
-#define PMX2_SOFTRESET_VGA_RST		0x0100
-#define PMX2_SOFTRESET_ROM_RST		0x0200	/* reserved bit, do not reset */
-#define PMX2_SOFTRESET_TA_RST		0x0400
-#define PMX2_SOFTRESET_REG_RST		0x4000
-#define PMX2_SOFTRESET_ALL		0x7fff
-
-/* Core clock freq */
-#define CORE_PLL_FREQ 1000000
-
-/* Reference Clock freq */
-#define REF_FREQ 14318
-
-/* PCI Registers */
-static u16 CorePllControl = 0x70;
-
-#define	PCI_CONFIG_SUBSYS_ID	0x2e
-
-/* Misc */
-#define CORE_PLL_MODE_REG_0_7      3
-#define CORE_PLL_MODE_REG_8_15     2
-#define CORE_PLL_MODE_CONFIG_REG   1
-#define DAC_PLL_CONFIG_REG         0
-
-#define STG_MAX_VCO 500000
-#define STG_MIN_VCO 100000
-
-/* PLL Clock */
-#define    STG4K3_PLL_SCALER      8	/* scale numbers by 2^8 for fixed point calc */
-#define    STG4K3_PLL_MIN_R       2	/* Minimum multiplier */
-#define    STG4K3_PLL_MAX_R       33	/* Max */
-#define    STG4K3_PLL_MIN_F       2	/* Minimum divisor */
-#define    STG4K3_PLL_MAX_F       513	/* Max */
-#define    STG4K3_PLL_MIN_OD      0	/* Min output divider (shift) */
-#define    STG4K3_PLL_MAX_OD      2	/* Max */
-#define    STG4K3_PLL_MIN_VCO_SC  (100000000 >> STG4K3_PLL_SCALER)	/* Min VCO rate */
-#define    STG4K3_PLL_MAX_VCO_SC  (500000000 >> STG4K3_PLL_SCALER)	/* Max VCO rate */
-#define    STG4K3_PLL_MINR_VCO_SC (100000000 >> STG4K3_PLL_SCALER)	/* Min VCO rate (restricted) */
-#define    STG4K3_PLL_MAXR_VCO_SC (500000000 >> STG4K3_PLL_SCALER)	/* Max VCO rate (restricted) */
-#define    STG4K3_PLL_MINR_VCO    100000000	/* Min VCO rate (restricted) */
-#define    STG4K3_PLL_MAX_VCO     500000000	/* Max VCO rate */
-#define    STG4K3_PLL_MAXR_VCO    500000000	/* Max VCO rate (restricted) */
-
-#define OS_DELAY(X) \
-{ \
-volatile u32 i,count=0; \
-    for(i=0;i<X;i++) count++; \
-}
-
-static u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg,
-			      u32 dwSubSysID, u32 dwRevID)
-{
-	u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
-	u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
-	u32 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
-	u32 adwSDRAMRsh[] = { 36, 39, 40 };
-	u32 adwChipSpeed[] = { 110, 120, 125 };
-	u32 dwMemTypeIdx;
-	u32 dwChipSpeedIdx;
-
-	/* Get memory tpye and chip speed indexs from the SubSysDevID */
-	dwMemTypeIdx = (dwSubSysID & 0x70) >> 4;
-	dwChipSpeedIdx = (dwSubSysID & 0x180) >> 7;
-
-	if (dwMemTypeIdx > 4 || dwChipSpeedIdx > 2)
-		return 0;
-
-	/* Program SD-RAM interface */
-	STG_WRITE_REG(SDRAMArbiterConf, adwSDRAMArgCfg0[dwMemTypeIdx]);
-	if (dwRevID < 5) {
-		STG_WRITE_REG(SDRAMConf0, 0x49A1);
-		STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg1[dwMemTypeIdx]);
-	} else {
-		STG_WRITE_REG(SDRAMConf0, 0x4DF1);
-		STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg2[dwMemTypeIdx]);
-	}
-
-	STG_WRITE_REG(SDRAMConf2, 0x31);
-	STG_WRITE_REG(SDRAMRefresh, adwSDRAMRsh[dwChipSpeedIdx]);
-
-	return adwChipSpeed[dwChipSpeedIdx] * 10000;
-}
-
-u32 ProgramClock(u32 refClock,
-		   u32 coreClock,
-		   u32 * FOut, u32 * ROut, u32 * POut)
-{
-	u32 R = 0, F = 0, OD = 0, ODIndex = 0;
-	u32 ulBestR = 0, ulBestF = 0, ulBestOD = 0;
-	u32 ulBestVCO = 0, ulBestClk = 0, ulBestScore = 0;
-	u32 ulScore, ulPhaseScore, ulVcoScore;
-	u32 ulTmp = 0, ulVCO;
-	u32 ulScaleClockReq, ulMinClock, ulMaxClock;
-	u32 ODValues[] = { 1, 2, 0 };
-
-	/* Translate clock in Hz */
-	coreClock *= 100;	/* in Hz */
-	refClock *= 1000;	/* in Hz */
-
-	/* Work out acceptable clock
-	 * The method calculates ~ +- 0.4% (1/256)
-	 */
-	ulMinClock = coreClock - (coreClock >> 8);
-	ulMaxClock = coreClock + (coreClock >> 8);
-
-	/* Scale clock required for use in calculations */
-	ulScaleClockReq = coreClock >> STG4K3_PLL_SCALER;
-
-	/* Iterate through post divider values */
-	for (ODIndex = 0; ODIndex < 3; ODIndex++) {
-		OD = ODValues[ODIndex];
-		R = STG4K3_PLL_MIN_R;
-
-		/* loop for pre-divider from min to max  */
-		while (R <= STG4K3_PLL_MAX_R) {
-			/* estimate required feedback multiplier */
-			ulTmp = R * (ulScaleClockReq << OD);
-
-			/* F = ClkRequired * R * (2^OD) / Fref */
-			F = (u32)(ulTmp / (refClock >> STG4K3_PLL_SCALER));
-
-			/* compensate for accuracy */
-			if (F > STG4K3_PLL_MIN_F)
-				F--;
-
-
-			/*
-			 * We should be close to our target frequency (if it's
-			 * achievable with current OD & R) let's iterate
-			 * through F for best fit
-			 */
-			while ((F >= STG4K3_PLL_MIN_F) &&
-			       (F <= STG4K3_PLL_MAX_F)) {
-				/* Calc VCO at full accuracy */
-				ulVCO = refClock / R;
-				ulVCO = F * ulVCO;
-
-				/*
-				 * Check it's within restricted VCO range
-				 * unless of course the desired frequency is
-				 * above the restricted range, then test
-				 * against VCO limit
-				 */
-				if ((ulVCO >= STG4K3_PLL_MINR_VCO) &&
-				    ((ulVCO <= STG4K3_PLL_MAXR_VCO) ||
-				     ((coreClock > STG4K3_PLL_MAXR_VCO)
-				      && (ulVCO <= STG4K3_PLL_MAX_VCO)))) {
-					ulTmp = (ulVCO >> OD);	/* Clock = VCO / (2^OD) */
-
-					/* Is this clock good enough? */
-					if ((ulTmp >= ulMinClock)
-					    && (ulTmp <= ulMaxClock)) {
-						ulPhaseScore = (((refClock / R) - (refClock / STG4K3_PLL_MAX_R))) / ((refClock - (refClock / STG4K3_PLL_MAX_R)) >> 10);
-
-						ulVcoScore = ((ulVCO - STG4K3_PLL_MINR_VCO)) / ((STG4K3_PLL_MAXR_VCO - STG4K3_PLL_MINR_VCO) >> 10);
-						ulScore = ulPhaseScore + ulVcoScore;
-
-						if (!ulBestScore) {
-							ulBestVCO = ulVCO;
-							ulBestOD = OD;
-							ulBestF = F;
-							ulBestR = R;
-							ulBestClk = ulTmp;
-							ulBestScore =
-							    ulScore;
-						}
-						/* is this better, ( aim for highest Score) */
-			/*--------------------------------------------------------------------------
-                             Here we want to use a scoring system which will take account of both the
-                            value at the phase comparater and the VCO output
-                             to do this we will use a cumulative score between the two
-                          The way this ends up is that we choose the first value in the loop anyway
-                          but we shall keep this code in case new restrictions come into play
-                          --------------------------------------------------------------------------*/
-						if ((ulScore >= ulBestScore) && (OD > 0)) {
-							ulBestVCO = ulVCO;
-							ulBestOD = OD;
-							ulBestF = F;
-							ulBestR = R;
-							ulBestClk = ulTmp;
-							ulBestScore =
-							    ulScore;
-						}
-					}
-				}
-				F++;
-			}
-			R++;
-		}
-	}
-
-	/*
-	   did we find anything?
-	   Then return RFOD
-	 */
-	if (ulBestScore) {
-		*ROut = ulBestR;
-		*FOut = ulBestF;
-
-		if ((ulBestOD == 2) || (ulBestOD == 3)) {
-			*POut = 3;
-		} else
-			*POut = ulBestOD;
-
-	}
-
-	return (ulBestClk);
-}
-
-int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev)
-{
-	u32 F, R, P;
-	u16 core_pll = 0, sub;
-	u32 ulCoreClock;
-	u32 tmp;
-	u32 ulChipSpeed;
-
-	STG_WRITE_REG(IntMask, 0xFFFF);
-
-	/* Disable Primary Core Thread0 */
-	tmp = STG_READ_REG(Thread0Enable);
-	CLEAR_BIT(0);
-	STG_WRITE_REG(Thread0Enable, tmp);
-
-	/* Disable Primary Core Thread1 */
-	tmp = STG_READ_REG(Thread1Enable);
-	CLEAR_BIT(0);
-	STG_WRITE_REG(Thread1Enable, tmp);
-
-	STG_WRITE_REG(SoftwareReset,
-		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
-	STG_WRITE_REG(SoftwareReset,
-		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
-		      PMX2_SOFTRESET_ROM_RST);
-
-	/* Need to play around to reset TA */
-	STG_WRITE_REG(TAConfiguration, 0);
-	STG_WRITE_REG(SoftwareReset,
-		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
-	STG_WRITE_REG(SoftwareReset,
-		      PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
-		      PMX2_SOFTRESET_ROM_RST);
-
-	pci_read_config_word(pDev, PCI_CONFIG_SUBSYS_ID, &sub);
-
-	ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub,
-		                         (u32)pDev->revision);
-
-	if (ulChipSpeed == 0)
-		return -EINVAL;
-
-	ulCoreClock = ProgramClock(REF_FREQ, CORE_PLL_FREQ, &F, &R, &P);
-
-	core_pll |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
-
-	/* Set Core PLL Control to Core PLL Mode  */
-
-	/* Send bits 0:7 of the Core PLL Mode register */
-	tmp = ((CORE_PLL_MODE_REG_0_7 << 8) | (core_pll & 0x00FF));
-	pci_write_config_word(pDev, CorePllControl, tmp);
-	/* Without some delay between the PCI config writes the clock does
-	   not reliably set when the code is compiled -O3
-	 */
-	OS_DELAY(1000000);
-
-	tmp |= SET_BIT(14);
-	pci_write_config_word(pDev, CorePllControl, tmp);
-	OS_DELAY(1000000);
-
-	/* Send bits 8:15 of the Core PLL Mode register */
-	tmp =
-	    ((CORE_PLL_MODE_REG_8_15 << 8) | ((core_pll & 0xFF00) >> 8));
-	pci_write_config_word(pDev, CorePllControl, tmp);
-	OS_DELAY(1000000);
-
-	tmp |= SET_BIT(14);
-	pci_write_config_word(pDev, CorePllControl, tmp);
-	OS_DELAY(1000000);
-
-	STG_WRITE_REG(SoftwareReset, PMX2_SOFTRESET_ALL);
-
-#if 0
-	/* Enable Primary Core Thread0 */
-	tmp = ((STG_READ_REG(Thread0Enable)) | SET_BIT(0));
-	STG_WRITE_REG(Thread0Enable, tmp);
-
-	/* Enable Primary Core Thread1 */
-	tmp = ((STG_READ_REG(Thread1Enable)) | SET_BIT(0));
-	STG_WRITE_REG(Thread1Enable, tmp);
-#endif
-
-	return 0;
-}
diff --git a/drivers/video/kyro/STG4000Interface.h b/drivers/video/kyro/STG4000Interface.h
deleted file mode 100644
index b7c83d5dfb13..000000000000
--- a/drivers/video/kyro/STG4000Interface.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  linux/drivers/video/kyro/STG4000Interface.h
- *
- *  Copyright (C) 2002 STMicroelectronics
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _STG4000INTERFACE_H
-#define _STG4000INTERFACE_H
-
-#include <linux/pci.h>
-#include <video/kyro.h>
-
-/*
- * Ramdac Setup
- */
-extern int InitialiseRamdac(volatile STG4000REG __iomem *pSTGReg, u32 displayDepth,
-			    u32 displayWidth, u32 displayHeight,
-			    s32 HSyncPolarity, s32 VSyncPolarity,
-			    u32 *pixelClock);
-
-extern void DisableRamdacOutput(volatile STG4000REG __iomem *pSTGReg);
-extern void EnableRamdacOutput(volatile STG4000REG __iomem *pSTGReg);
-
-/*
- * Timing generator setup
- */
-extern void DisableVGA(volatile STG4000REG __iomem *pSTGReg);
-extern void StopVTG(volatile STG4000REG __iomem *pSTGReg);
-extern void StartVTG(volatile STG4000REG __iomem *pSTGReg);
-extern void SetupVTG(volatile STG4000REG __iomem *pSTGReg,
-		     const struct kyrofb_info * pTiming);
-
-extern u32 ProgramClock(u32 refClock, u32 coreClock, u32 *FOut, u32 *ROut, u32 *POut);
-extern int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev);
-
-/*
- * Overlay setup
- */
-extern void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg);
-
-extern int CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg,
-				u32 ulWidth, u32 ulHeight,
-				int bLinear,
-				u32 ulOverlayOffset,
-				u32 * retStride, u32 * retUVStride);
-
-extern int SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg,
-			       OVRL_BLEND_MODE mode,
-			       u32 ulAlpha, u32 ulColorKey);
-
-extern int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
-			      u32 left, u32 top,
-			      u32 right, u32 bottom);
-
-extern void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg);
-
-#endif /* _STG4000INTERFACE_H */
diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c
deleted file mode 100644
index 0aeeaa10708b..000000000000
--- a/drivers/video/kyro/STG4000OverlayDevice.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- *  linux/drivers/video/kyro/STG4000OverlayDevice.c
- *
- *  Copyright (C) 2000 Imagination Technologies Ltd
- *  Copyright (C) 2002 STMicroelectronics
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-
-#include "STG4000Reg.h"
-#include "STG4000Interface.h"
-
-/* HW Defines */
-
-#define STG4000_NO_SCALING    0x800
-#define STG4000_NO_DECIMATION 0xFFFFFFFF
-
-/* Primary surface */
-#define STG4000_PRIM_NUM_PIX   5
-#define STG4000_PRIM_ALIGN     4
-#define STG4000_PRIM_ADDR_BITS 20
-
-#define STG4000_PRIM_MIN_WIDTH  640
-#define STG4000_PRIM_MAX_WIDTH  1600
-#define STG4000_PRIM_MIN_HEIGHT 480
-#define STG4000_PRIM_MAX_HEIGHT 1200
-
-/* Overlay surface */
-#define STG4000_OVRL_NUM_PIX   4
-#define STG4000_OVRL_ALIGN     2
-#define STG4000_OVRL_ADDR_BITS 20
-#define STG4000_OVRL_NUM_MODES 5
-
-#define STG4000_OVRL_MIN_WIDTH  0
-#define STG4000_OVRL_MAX_WIDTH  720
-#define STG4000_OVRL_MIN_HEIGHT 0
-#define STG4000_OVRL_MAX_HEIGHT 576
-
-/* Decimation and Scaling */
-static u32 adwDecim8[33] = {
-	    0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf,
-	    0xfbdf7bdf, 0xf7bbddef, 0xeeeeeeef, 0xeeddbb77, 0xedb76db7,
-	    0xdb6db6db, 0xdb5b5b5b, 0xdab5ad6b, 0xd5ab55ab, 0xd555aaab,
-	    0xaaaaaaab, 0xaaaa5555, 0xaa952a55, 0xa94a5295, 0xa5252525,
-	    0xa4924925, 0x92491249, 0x91224489, 0x91111111, 0x90884211,
-	    0x88410821, 0x88102041, 0x81010101, 0x80800801, 0x80010001,
-	    0x80000001, 0x00000001, 0x00000000
-};
-
-typedef struct _OVRL_SRC_DEST {
-	/*clipped on-screen pixel position of overlay */
-	u32 ulDstX1;
-	u32 ulDstY1;
-	u32 ulDstX2;
-	u32 ulDstY2;
-
-	/*clipped pixel pos of source data within buffer thses need to be 128 bit word aligned */
-	u32 ulSrcX1;
-	u32 ulSrcY1;
-	u32 ulSrcX2;
-	u32 ulSrcY2;
-
-	/* on-screen pixel position of overlay */
-	s32 lDstX1;
-	s32 lDstY1;
-	s32 lDstX2;
-	s32 lDstY2;
-} OVRL_SRC_DEST;
-
-static u32 ovlWidth, ovlHeight, ovlStride;
-static int ovlLinear;
-
-void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg)
-{
-	u32 tmp;
-
-	/* Set Overlay address to default */
-	tmp = STG_READ_REG(DACOverlayAddr);
-	CLEAR_BITS_FRM_TO(0, 20);
-	CLEAR_BIT(31);
-	STG_WRITE_REG(DACOverlayAddr, tmp);
-
-	/* Set Overlay U address */
-	tmp = STG_READ_REG(DACOverlayUAddr);
-	CLEAR_BITS_FRM_TO(0, 20);
-	STG_WRITE_REG(DACOverlayUAddr, tmp);
-
-	/* Set Overlay V address */
-	tmp = STG_READ_REG(DACOverlayVAddr);
-	CLEAR_BITS_FRM_TO(0, 20);
-	STG_WRITE_REG(DACOverlayVAddr, tmp);
-
-	/* Set Overlay Size */
-	tmp = STG_READ_REG(DACOverlaySize);
-	CLEAR_BITS_FRM_TO(0, 10);
-	CLEAR_BITS_FRM_TO(12, 31);
-	STG_WRITE_REG(DACOverlaySize, tmp);
-
-	/* Set Overlay Vt Decimation */
-	tmp = STG4000_NO_DECIMATION;
-	STG_WRITE_REG(DACOverlayVtDec, tmp);
-
-	/* Set Overlay format to default value */
-	tmp = STG_READ_REG(DACPixelFormat);
-	CLEAR_BITS_FRM_TO(4, 7);
-	CLEAR_BITS_FRM_TO(16, 22);
-	STG_WRITE_REG(DACPixelFormat, tmp);
-
-	/* Set Vertical scaling to default */
-	tmp = STG_READ_REG(DACVerticalScal);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 22);
-	tmp |= STG4000_NO_SCALING;	/* Set to no scaling */
-	STG_WRITE_REG(DACVerticalScal, tmp);
-
-	/* Set Horizontal Scaling to default */
-	tmp = STG_READ_REG(DACHorizontalScal);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 17);
-	tmp |= STG4000_NO_SCALING;	/* Set to no scaling */
-	STG_WRITE_REG(DACHorizontalScal, tmp);
-
-	/* Set Blend mode to Alpha Blend */
-	/* ????? SG 08/11/2001 Surely this isn't the alpha blend mode,
-	   hopefully its overwrite
-	 */
-	tmp = STG_READ_REG(DACBlendCtrl);
-	CLEAR_BITS_FRM_TO(0, 30);
-	tmp = (GRAPHICS_MODE << 28);
-	STG_WRITE_REG(DACBlendCtrl, tmp);
-
-}
-
-int CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg,
-			 u32 inWidth,
-			 u32 inHeight,
-			 int bLinear,
-			 u32 ulOverlayOffset,
-			 u32 * retStride, u32 * retUVStride)
-{
-	u32 tmp;
-	u32 ulStride;
-
-	if (inWidth > STG4000_OVRL_MAX_WIDTH ||
-	    inHeight > STG4000_OVRL_MAX_HEIGHT) {
-		return -EINVAL;
-	}
-
-	/* Stride in 16 byte words - 16Bpp */
-	if (bLinear) {
-		/* Format is 16bits so num 16 byte words is width/8 */
-		if ((inWidth & 0x7) == 0) {	/* inWidth % 8 */
-			ulStride = (inWidth / 8);
-		} else {
-			/* Round up to next 16byte boundary */
-			ulStride = ((inWidth + 8) / 8);
-		}
-	} else {
-		/* Y component is 8bits so num 16 byte words is width/16 */
-		if ((inWidth & 0xf) == 0) {	/* inWidth % 16 */
-			ulStride = (inWidth / 16);
-		} else {
-			/* Round up to next 16byte boundary */
-			ulStride = ((inWidth + 16) / 16);
-		}
-	}
-
-
-	/* Set Overlay address and Format mode */
-	tmp = STG_READ_REG(DACOverlayAddr);
-	CLEAR_BITS_FRM_TO(0, 20);
-	if (bLinear) {
-		CLEAR_BIT(31);	/* Overlay format to Linear */
-	} else {
-		tmp |= SET_BIT(31);	/* Overlay format to Planer */
-	}
-
-	/* Only bits 24:4 of the Overlay address */
-	tmp |= (ulOverlayOffset >> 4);
-	STG_WRITE_REG(DACOverlayAddr, tmp);
-
-	if (!bLinear) {
-		u32 uvSize =
-		    (inWidth & 0x1) ? (inWidth + 1 / 2) : (inWidth / 2);
-		u32 uvStride;
-		u32 ulOffset;
-		/* Y component is 8bits so num 32 byte words is width/32 */
-		if ((uvSize & 0xf) == 0) {	/* inWidth % 16 */
-			uvStride = (uvSize / 16);
-		} else {
-			/* Round up to next 32byte boundary */
-			uvStride = ((uvSize + 16) / 16);
-		}
-
-		ulOffset = ulOverlayOffset + (inHeight * (ulStride * 16));
-		/* Align U,V data to 32byte boundary */
-		if ((ulOffset & 0x1f) != 0)
-			ulOffset = (ulOffset + 32L) & 0xffffffE0L;
-
-		tmp = STG_READ_REG(DACOverlayUAddr);
-		CLEAR_BITS_FRM_TO(0, 20);
-		tmp |= (ulOffset >> 4);
-		STG_WRITE_REG(DACOverlayUAddr, tmp);
-
-		ulOffset += (inHeight / 2) * (uvStride * 16);
-		/* Align U,V data to 32byte boundary */
-		if ((ulOffset & 0x1f) != 0)
-			ulOffset = (ulOffset + 32L) & 0xffffffE0L;
-
-		tmp = STG_READ_REG(DACOverlayVAddr);
-		CLEAR_BITS_FRM_TO(0, 20);
-		tmp |= (ulOffset >> 4);
-		STG_WRITE_REG(DACOverlayVAddr, tmp);
-
-		*retUVStride = uvStride * 16;
-	}
-
-
-	/* Set Overlay YUV pixel format
-	 * Make sure that LUT not used - ??????
-	 */
-	tmp = STG_READ_REG(DACPixelFormat);
-	/* Only support Planer or UYVY linear formats */
-	CLEAR_BITS_FRM_TO(4, 9);
-	STG_WRITE_REG(DACPixelFormat, tmp);
-
-	ovlWidth = inWidth;
-	ovlHeight = inHeight;
-	ovlStride = ulStride;
-	ovlLinear = bLinear;
-	*retStride = ulStride << 4;	/* In bytes */
-
-	return 0;
-}
-
-int SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg,
-			OVRL_BLEND_MODE mode,
-			u32 ulAlpha, u32 ulColorKey)
-{
-	u32 tmp;
-
-	tmp = STG_READ_REG(DACBlendCtrl);
-	CLEAR_BITS_FRM_TO(28, 30);
-	tmp |= (mode << 28);
-
-	switch (mode) {
-	case COLOR_KEY:
-		CLEAR_BITS_FRM_TO(0, 23);
-		tmp |= (ulColorKey & 0x00FFFFFF);
-		break;
-
-	case GLOBAL_ALPHA:
-		CLEAR_BITS_FRM_TO(24, 27);
-		tmp |= ((ulAlpha & 0xF) << 24);
-		break;
-
-	case CK_PIXEL_ALPHA:
-		CLEAR_BITS_FRM_TO(0, 23);
-		tmp |= (ulColorKey & 0x00FFFFFF);
-		break;
-
-	case CK_GLOBAL_ALPHA:
-		CLEAR_BITS_FRM_TO(0, 23);
-		tmp |= (ulColorKey & 0x00FFFFFF);
-		CLEAR_BITS_FRM_TO(24, 27);
-		tmp |= ((ulAlpha & 0xF) << 24);
-		break;
-
-	case GRAPHICS_MODE:
-	case PER_PIXEL_ALPHA:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	STG_WRITE_REG(DACBlendCtrl, tmp);
-
-	return 0;
-}
-
-void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg)
-{
-	u32 tmp;
-	/* Enable Overlay */
-	tmp = STG_READ_REG(DACPixelFormat);
-	tmp |= SET_BIT(7);
-	STG_WRITE_REG(DACPixelFormat, tmp);
-
-	/* Set video stream control */
-	tmp = STG_READ_REG(DACStreamCtrl);
-	tmp |= SET_BIT(1);	/* video stream */
-	STG_WRITE_REG(DACStreamCtrl, tmp);
-}
-
-static u32 Overlap(u32 ulBits, u32 ulPattern)
-{
-	u32 ulCount = 0;
-
-	while (ulBits) {
-		if (!(ulPattern & 1))
-			ulCount++;
-		ulBits--;
-		ulPattern = ulPattern >> 1;
-	}
-
-	return ulCount;
-
-}
-
-int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
-		       u32 left, u32 top,
-		       u32 right, u32 bottom)
-{
-	OVRL_SRC_DEST srcDest;
-
-	u32 ulSrcTop, ulSrcBottom;
-	u32 ulSrc, ulDest;
-	u32 ulFxScale, ulFxOffset;
-	u32 ulHeight, ulWidth;
-	u32 ulPattern;
-	u32 ulDecimate, ulDecimated;
-	u32 ulApplied;
-	u32 ulDacXScale, ulDacYScale;
-	u32 ulScale;
-	u32 ulLeft, ulRight;
-	u32 ulSrcLeft, ulSrcRight;
-	u32 ulScaleLeft, ulScaleRight;
-	u32 ulhDecim;
-	u32 ulsVal;
-	u32 ulVertDecFactor;
-	int bResult;
-	u32 ulClipOff = 0;
-	u32 ulBits = 0;
-	u32 ulsAdd = 0;
-	u32 tmp, ulStride;
-	u32 ulExcessPixels, ulClip, ulExtraLines;
-
-
-	srcDest.ulSrcX1 = 0;
-	srcDest.ulSrcY1 = 0;
-	srcDest.ulSrcX2 = ovlWidth - 1;
-	srcDest.ulSrcY2 = ovlHeight - 1;
-
-	srcDest.ulDstX1 = left;
-	srcDest.ulDstY1 = top;
-	srcDest.ulDstX2 = right;
-	srcDest.ulDstY2 = bottom;
-
-	srcDest.lDstX1 = srcDest.ulDstX1;
-	srcDest.lDstY1 = srcDest.ulDstY1;
-	srcDest.lDstX2 = srcDest.ulDstX2;
-	srcDest.lDstY2 = srcDest.ulDstY2;
-
-    /************* Vertical decimation/scaling ******************/
-
-	/* Get Src Top and Bottom */
-	ulSrcTop = srcDest.ulSrcY1;
-	ulSrcBottom = srcDest.ulSrcY2;
-
-	ulSrc = ulSrcBottom - ulSrcTop;
-	ulDest = srcDest.lDstY2 - srcDest.lDstY1;	/* on-screen overlay */
-
-	if (ulSrc <= 1)
-		return -EINVAL;
-
-	/* First work out the position we are to display as offset from the
-	 * source of the buffer
-	 */
-	ulFxScale = (ulDest << 11) / ulSrc;	/* fixed point scale factor */
-	ulFxOffset = (srcDest.lDstY2 - srcDest.ulDstY2) << 11;
-
-	ulSrcBottom = ulSrcBottom - (ulFxOffset / ulFxScale);
-	ulSrc = ulSrcBottom - ulSrcTop;
-	ulHeight = ulSrc;
-
-	ulDest = srcDest.ulDstY2 - (srcDest.ulDstY1 - 1);
-	ulPattern = adwDecim8[ulBits];
-
-	/* At this point ulSrc represents the input decimator */
-	if (ulSrc > ulDest) {
-		ulDecimate = ulSrc - ulDest;
-		ulBits = 0;
-		ulApplied = ulSrc / 32;
-
-		while (((ulBits * ulApplied) +
-			Overlap((ulSrc % 32),
-				adwDecim8[ulBits])) < ulDecimate)
-			ulBits++;
-
-		ulPattern = adwDecim8[ulBits];
-		ulDecimated =
-		    (ulBits * ulApplied) + Overlap((ulSrc % 32),
-						   ulPattern);
-		ulSrc = ulSrc - ulDecimated;	/* the number number of lines that will go into the scaler */
-	}
-
-	if (ulBits && (ulBits != 32)) {
-		ulVertDecFactor = (63 - ulBits) / (32 - ulBits);	/* vertical decimation factor scaled up to nearest integer */
-	} else {
-		ulVertDecFactor = 1;
-	}
-
-	ulDacYScale = ((ulSrc - 1) * 2048) / (ulDest + 1);
-
-	tmp = STG_READ_REG(DACOverlayVtDec);	/* Decimation */
-	CLEAR_BITS_FRM_TO(0, 31);
-	tmp = ulPattern;
-	STG_WRITE_REG(DACOverlayVtDec, tmp);
-
-	/***************** Horizontal decimation/scaling ***************************/
-
-	/*
-	 * Now we handle the horizontal case, this is a simplified version of
-	 * the vertical case in that we decimate by factors of 2.  as we are
-	 * working in words we should always be able to decimate by these
-	 * factors.  as we always have to have a buffer which is aligned to a
-	 * whole number of 128 bit words, we must align the left side to the
-	 * lowest to the next lowest 128 bit boundary, and the right hand edge
-	 * to the next largets boundary, (in a similar way to how we didi it in
-	 * PMX1) as the left and right hand edges are aligned to these
-	 * boundaries normally this only becomes an issue when we are chopping
-	 * of one of the sides We shall work out vertical stuff first
-	 */
-	ulSrc = srcDest.ulSrcX2 - srcDest.ulSrcX1;
-	ulDest = srcDest.lDstX2 - srcDest.lDstX1;
-#ifdef _OLDCODE
-	ulLeft = srcDest.ulDstX1;
-	ulRight = srcDest.ulDstX2;
-#else
-	if (srcDest.ulDstX1 > 2) {
-		ulLeft = srcDest.ulDstX1 + 2;
-		ulRight = srcDest.ulDstX2 + 1;
-	} else {
-		ulLeft = srcDest.ulDstX1;
-		ulRight = srcDest.ulDstX2 + 1;
-	}
-#endif
-	/* first work out the position we are to display as offset from the source of the buffer */
-	bResult = 1;
-
-	do {
-		if (ulDest == 0)
-			return -EINVAL;
-
-		/* source pixels per dest pixel <<11 */
-		ulFxScale = ((ulSrc - 1) << 11) / (ulDest);
-
-		/* then number of destination pixels out we are */
-		ulFxOffset = ulFxScale * ((srcDest.ulDstX1 - srcDest.lDstX1) + ulClipOff);
-		ulFxOffset >>= 11;
-
-		/* this replaces the code which was making a decision as to use either ulFxOffset or ulSrcX1 */
-		ulSrcLeft = srcDest.ulSrcX1 + ulFxOffset;
-
-		/* then number of destination pixels out we are */
-		ulFxOffset = ulFxScale * (srcDest.lDstX2 - srcDest.ulDstX2);
-		ulFxOffset >>= 11;
-
-		ulSrcRight = srcDest.ulSrcX2 - ulFxOffset;
-
-		/*
-		 * we must align these to our 128 bit boundaries. we shall
-		 * round down the pixel pos to the nearest 8 pixels.
-		 */
-		ulScaleLeft = ulSrcLeft;
-		ulScaleRight = ulSrcRight;
-
-		/* shift fxscale until it is in the range of the scaler */
-		ulhDecim = 0;
-		ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
-
-		while (ulScale > 0x800) {
-			ulhDecim++;
-			ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
-		}
-
-		/*
-		 * to try and get the best values We first try and use
-		 * src/dwdest for the scale factor, then we move onto src-1
-		 *
-		 * we want to check to see if we will need to clip data, if so
-		 * then we should clip our source so that we don't need to
-		 */
-		if (!ovlLinear) {
-			ulSrcLeft &= ~0x1f;
-
-			/*
-			 * we must align the right hand edge to the next 32
-			 * pixel` boundary, must be on a 256 boundary so u, and
-			 * v are 128 bit aligned
-			 */
-			ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f;
-		} else {
-			ulSrcLeft &= ~0x7;
-
-			/*
-			 * we must align the right hand edge to the next
-			 * 8pixel` boundary
-			 */
-			ulSrcRight = (ulSrcRight + 0x7) & ~0x7;
-		}
-
-		/* this is the input size line store needs to cope with */
-		ulWidth = ulSrcRight - ulSrcLeft;
-
-		/*
-		 * use unclipped value to work out scale factror this is the
-		 * scale factor we want we shall now work out the horizonal
-		 * decimation and scaling
-		 */
-		ulsVal = ((ulWidth / 8) >> ulhDecim);
-
-		if ((ulWidth != (ulsVal << ulhDecim) * 8))
-			ulsAdd = 1;
-
-		/* input pixels to scaler; */
-		ulSrc = ulWidth >> ulhDecim;
-
-		if (ulSrc <= 2)
-			return -EINVAL;
-
-		ulExcessPixels = ((((ulScaleLeft - ulSrcLeft)) << (11 - ulhDecim)) / ulScale);
-
-		ulClip = (ulSrc << 11) / ulScale;
-		ulClip -= (ulRight - ulLeft);
-		ulClip += ulExcessPixels;
-
-		if (ulClip)
-			ulClip--;
-
-		/* We may need to do more here if we really have a HW rev < 5 */
-	} while (!bResult);
-
-	ulExtraLines = (1 << ulhDecim) * ulVertDecFactor;
-	ulExtraLines += 64;
-	ulHeight += ulExtraLines;
-
-	ulDacXScale = ulScale;
-
-
-	tmp = STG_READ_REG(DACVerticalScal);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 22);	/* Vertical Scaling */
-
-	/* Calculate new output line stride, this is always the number of 422
-	   words in the line buffer, so it doesn't matter if the
-	   mode is 420. Then set the vertical scale register.
-	 */
-	ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd;
-	tmp |= ((ulStride << 16) | (ulDacYScale));	/* DAC_LS_CTRL = stride */
-	STG_WRITE_REG(DACVerticalScal, tmp);
-
-	/* Now set up the overlay size using the modified width and height
-	   from decimate and scaling calculations
-	 */
-	tmp = STG_READ_REG(DACOverlaySize);
-	CLEAR_BITS_FRM_TO(0, 10);
-	CLEAR_BITS_FRM_TO(12, 31);
-
-	if (ovlLinear) {
-		tmp |=
-		    (ovlStride | ((ulHeight + 1) << 12) |
-		     (((ulWidth / 8) - 1) << 23));
-	} else {
-		tmp |=
-		    (ovlStride | ((ulHeight + 1) << 12) |
-		     (((ulWidth / 32) - 1) << 23));
-	}
-
-	STG_WRITE_REG(DACOverlaySize, tmp);
-
-	/* Set Video Window Start */
-	tmp = ((ulLeft << 16)) | (srcDest.ulDstY1);
-	STG_WRITE_REG(DACVidWinStart, tmp);
-
-	/* Set Video Window End */
-	tmp = ((ulRight) << 16) | (srcDest.ulDstY2);
-	STG_WRITE_REG(DACVidWinEnd, tmp);
-
-	/* Finally set up the rest of the overlay regs in the order
-	   done in the IMG driver
-	 */
-	tmp = STG_READ_REG(DACPixelFormat);
-	tmp = ((ulExcessPixels << 16) | tmp) & 0x7fffffff;
-	STG_WRITE_REG(DACPixelFormat, tmp);
-
-	tmp = STG_READ_REG(DACHorizontalScal);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 17);
-	tmp |= ((ulhDecim << 16) | (ulDacXScale));
-	STG_WRITE_REG(DACHorizontalScal, tmp);
-
-	return 0;
-}
diff --git a/drivers/video/kyro/STG4000Ramdac.c b/drivers/video/kyro/STG4000Ramdac.c
deleted file mode 100644
index e6ad037e4396..000000000000
--- a/drivers/video/kyro/STG4000Ramdac.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- *  linux/drivers/video/kyro/STG4000Ramdac.c
- *
- *  Copyright (C) 2002 STMicroelectronics
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <video/kyro.h>
-
-#include "STG4000Reg.h"
-#include "STG4000Interface.h"
-
-static u32 STG_PIXEL_BUS_WIDTH = 128;	/* 128 bit bus width      */
-static u32 REF_CLOCK = 14318;
-
-int InitialiseRamdac(volatile STG4000REG __iomem * pSTGReg,
-		     u32 displayDepth,
-		     u32 displayWidth,
-		     u32 displayHeight,
-		     s32 HSyncPolarity,
-		     s32 VSyncPolarity, u32 * pixelClock)
-{
-	u32 tmp = 0;
-	u32 F = 0, R = 0, P = 0;
-	u32 stride = 0;
-	u32 ulPdiv = 0;
-	u32 physicalPixelDepth = 0;
-	/* Make sure DAC is in Reset */
-	tmp = STG_READ_REG(SoftwareReset);
-
-	if (tmp & 0x1) {
-		CLEAR_BIT(1);
-		STG_WRITE_REG(SoftwareReset, tmp);
-	}
-
-	/* Set Pixel Format */
-	tmp = STG_READ_REG(DACPixelFormat);
-	CLEAR_BITS_FRM_TO(0, 2);
-
-	/* Set LUT not used from 16bpp to 32 bpp ??? */
-	CLEAR_BITS_FRM_TO(8, 9);
-
-	switch (displayDepth) {
-	case 16:
-		{
-			physicalPixelDepth = 16;
-			tmp |= _16BPP;
-			break;
-		}
-	case 32:
-		{
-			/* Set for 32 bits per pixel */
-			physicalPixelDepth = 32;
-			tmp |= _32BPP;
-			break;
-		}
-	default:
-		return -EINVAL;
-	}
-
-	STG_WRITE_REG(DACPixelFormat, tmp);
-
-	/* Workout Bus transfer bandwidth according to pixel format */
-	ulPdiv = STG_PIXEL_BUS_WIDTH / physicalPixelDepth;
-
-	/* Get Screen Stride in pixels */
-	stride = displayWidth;
-
-	/* Set Primary size info */
-	tmp = STG_READ_REG(DACPrimSize);
-	CLEAR_BITS_FRM_TO(0, 10);
-	CLEAR_BITS_FRM_TO(12, 31);
-	tmp |=
-	    ((((displayHeight - 1) << 12) | (((displayWidth / ulPdiv) -
-					      1) << 23))
-	     | (stride / ulPdiv));
-	STG_WRITE_REG(DACPrimSize, tmp);
-
-
-	/* Set Pixel Clock */
-	*pixelClock = ProgramClock(REF_CLOCK, *pixelClock, &F, &R, &P);
-
-	/* Set DAC PLL Mode */
-	tmp = STG_READ_REG(DACPLLMode);
-	CLEAR_BITS_FRM_TO(0, 15);
-	/* tmp |= ((P-1) | ((F-2) << 2) | ((R-2) << 11)); */
-	tmp |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
-	STG_WRITE_REG(DACPLLMode, tmp);
-
-	/* Set Prim Address */
-	tmp = STG_READ_REG(DACPrimAddress);
-	CLEAR_BITS_FRM_TO(0, 20);
-	CLEAR_BITS_FRM_TO(20, 31);
-	STG_WRITE_REG(DACPrimAddress, tmp);
-
-	/* Set Cursor details with HW Cursor disabled */
-	tmp = STG_READ_REG(DACCursorCtrl);
-	tmp &= ~SET_BIT(31);
-	STG_WRITE_REG(DACCursorCtrl, tmp);
-
-	tmp = STG_READ_REG(DACCursorAddr);
-	CLEAR_BITS_FRM_TO(0, 20);
-	STG_WRITE_REG(DACCursorAddr, tmp);
-
-	/* Set Video Window */
-	tmp = STG_READ_REG(DACVidWinStart);
-	CLEAR_BITS_FRM_TO(0, 10);
-	CLEAR_BITS_FRM_TO(16, 26);
-	STG_WRITE_REG(DACVidWinStart, tmp);
-
-	tmp = STG_READ_REG(DACVidWinEnd);
-	CLEAR_BITS_FRM_TO(0, 10);
-	CLEAR_BITS_FRM_TO(16, 26);
-	STG_WRITE_REG(DACVidWinEnd, tmp);
-
-	/* Set DAC Border Color to default */
-	tmp = STG_READ_REG(DACBorderColor);
-	CLEAR_BITS_FRM_TO(0, 23);
-	STG_WRITE_REG(DACBorderColor, tmp);
-
-	/* Set Graphics and Overlay Burst Control */
-	STG_WRITE_REG(DACBurstCtrl, 0x0404);
-
-	/* Set CRC Trigger to default */
-	tmp = STG_READ_REG(DACCrcTrigger);
-	CLEAR_BIT(0);
-	STG_WRITE_REG(DACCrcTrigger, tmp);
-
-	/* Set Video Port Control to default */
-	tmp = STG_READ_REG(DigVidPortCtrl);
-	CLEAR_BIT(8);
-	CLEAR_BITS_FRM_TO(16, 27);
-	CLEAR_BITS_FRM_TO(1, 3);
-	CLEAR_BITS_FRM_TO(10, 11);
-	STG_WRITE_REG(DigVidPortCtrl, tmp);
-
-	return 0;
-}
-
-/* Ramdac control, turning output to the screen on and off */
-void DisableRamdacOutput(volatile STG4000REG __iomem * pSTGReg)
-{
-	u32 tmp;
-
-	/* Disable DAC for Graphics Stream Control */
-	tmp = (STG_READ_REG(DACStreamCtrl)) & ~SET_BIT(0);
-	STG_WRITE_REG(DACStreamCtrl, tmp);
-}
-
-void EnableRamdacOutput(volatile STG4000REG __iomem * pSTGReg)
-{
-	u32 tmp;
-
-	/* Enable DAC for Graphics Stream Control */
-	tmp = (STG_READ_REG(DACStreamCtrl)) | SET_BIT(0);
-	STG_WRITE_REG(DACStreamCtrl, tmp);
-}
diff --git a/drivers/video/kyro/STG4000Reg.h b/drivers/video/kyro/STG4000Reg.h
deleted file mode 100644
index 50f4670e9252..000000000000
--- a/drivers/video/kyro/STG4000Reg.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- *  linux/drivers/video/kyro/STG4000Reg.h
- *
- *  Copyright (C) 2002 STMicroelectronics
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _STG4000REG_H
-#define _STG4000REG_H
-
-#define DWFILL unsigned long :32
-#define WFILL unsigned short :16
-
-/*
- * Macros that access memory mapped card registers in PCI space
- * Add an appropriate section for your OS or processor architecture.
- */
-#if defined(__KERNEL__)
-#include <asm/page.h>
-#include <asm/io.h>
-#define STG_WRITE_REG(reg,data) (writel(data,&pSTGReg->reg))
-#define STG_READ_REG(reg)      (readl(&pSTGReg->reg))
-#else
-#define STG_WRITE_REG(reg,data) (pSTGReg->reg = data)
-#define STG_READ_REG(reg)      (pSTGReg->reg)
-#endif /* __KERNEL__ */
-
-#define SET_BIT(n) (1<<(n))
-#define CLEAR_BIT(n) (tmp &= ~(1<<n))
-#define CLEAR_BITS_FRM_TO(frm, to) \
-{\
-int i; \
-    for(i = frm; i<= to; i++) \
-	{ \
-	    tmp &= ~(1<<i); \
-	} \
-}
-
-#define CLEAR_BIT_2(n) (usTemp &= ~(1<<n))
-#define CLEAR_BITS_FRM_TO_2(frm, to) \
-{\
-int i; \
-    for(i = frm; i<= to; i++) \
-	{ \
-	    usTemp &= ~(1<<i); \
-	} \
-}
-
-/* LUT select */
-typedef enum _LUT_USES {
-	NO_LUT = 0, RESERVED, GRAPHICS, OVERLAY
-} LUT_USES;
-
-/* Primary surface pixel format select */
-typedef enum _PIXEL_FORMAT {
-	_8BPP = 0, _15BPP, _16BPP, _24BPP, _32BPP
-} PIXEL_FORMAT;
-
-/* Overlay blending mode select */
-typedef enum _BLEND_MODE {
-	GRAPHICS_MODE = 0, COLOR_KEY, PER_PIXEL_ALPHA, GLOBAL_ALPHA,
-	CK_PIXEL_ALPHA, CK_GLOBAL_ALPHA
-} OVRL_BLEND_MODE;
-
-/* Overlay Pixel format select */
-typedef enum _OVRL_PIX_FORMAT {
-	UYVY, VYUY, YUYV, YVYU
-} OVRL_PIX_FORMAT;
-
-/* Register Table */
-typedef struct {
-	/* 0h  */
-	volatile u32 Thread0Enable;	/* 0x0000 */
-	volatile u32 Thread1Enable;	/* 0x0004 */
-	volatile u32 Thread0Recover;	/* 0x0008 */
-	volatile u32 Thread1Recover;	/* 0x000C */
-	volatile u32 Thread0Step;	/* 0x0010 */
-	volatile u32 Thread1Step;	/* 0x0014 */
-	volatile u32 VideoInStatus;	/* 0x0018 */
-	volatile u32 Core2InSignStart;	/* 0x001C */
-	volatile u32 Core1ResetVector;	/* 0x0020 */
-	volatile u32 Core1ROMOffset;	/* 0x0024 */
-	volatile u32 Core1ArbiterPriority;	/* 0x0028 */
-	volatile u32 VideoInControl;	/* 0x002C */
-	volatile u32 VideoInReg0CtrlA;	/* 0x0030 */
-	volatile u32 VideoInReg0CtrlB;	/* 0x0034 */
-	volatile u32 VideoInReg1CtrlA;	/* 0x0038 */
-	volatile u32 VideoInReg1CtrlB;	/* 0x003C */
-	volatile u32 Thread0Kicker;	/* 0x0040 */
-	volatile u32 Core2InputSign;	/* 0x0044 */
-	volatile u32 Thread0ProgCtr;	/* 0x0048 */
-	volatile u32 Thread1ProgCtr;	/* 0x004C */
-	volatile u32 Thread1Kicker;	/* 0x0050 */
-	volatile u32 GPRegister1;	/* 0x0054 */
-	volatile u32 GPRegister2;	/* 0x0058 */
-	volatile u32 GPRegister3;	/* 0x005C */
-	volatile u32 GPRegister4;	/* 0x0060 */
-	volatile u32 SerialIntA;	/* 0x0064 */
-
-	volatile u32 Fill0[6];	/* GAP 0x0068 - 0x007C */
-
-	volatile u32 SoftwareReset;	/* 0x0080 */
-	volatile u32 SerialIntB;	/* 0x0084 */
-
-	volatile u32 Fill1[37];	/* GAP 0x0088 - 0x011C */
-
-	volatile u32 ROMELQV;	/* 0x011C */
-	volatile u32 WLWH;	/* 0x0120 */
-	volatile u32 ROMELWL;	/* 0x0124 */
-
-	volatile u32 dwFill_1;	/* GAP 0x0128 */
-
-	volatile u32 IntStatus;	/* 0x012C */
-	volatile u32 IntMask;	/* 0x0130 */
-	volatile u32 IntClear;	/* 0x0134 */
-
-	volatile u32 Fill2[6];	/* GAP 0x0138 - 0x014C */
-
-	volatile u32 ROMGPIOA;	/* 0x0150 */
-	volatile u32 ROMGPIOB;	/* 0x0154 */
-	volatile u32 ROMGPIOC;	/* 0x0158 */
-	volatile u32 ROMGPIOD;	/* 0x015C */
-
-	volatile u32 Fill3[2];	/* GAP 0x0160 - 0x0168 */
-
-	volatile u32 AGPIntID;	/* 0x0168 */
-	volatile u32 AGPIntClassCode;	/* 0x016C */
-	volatile u32 AGPIntBIST;	/* 0x0170 */
-	volatile u32 AGPIntSSID;	/* 0x0174 */
-	volatile u32 AGPIntPMCSR;	/* 0x0178 */
-	volatile u32 VGAFrameBufBase;	/* 0x017C */
-	volatile u32 VGANotify;	/* 0x0180 */
-	volatile u32 DACPLLMode;	/* 0x0184 */
-	volatile u32 Core1VideoClockDiv;	/* 0x0188 */
-	volatile u32 AGPIntStat;	/* 0x018C */
-
-	/*
-	   volatile u32 Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400
-	   volatile u32 Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table
-	   volatile u32 Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604
-	   volatile u32 Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680
-	   volatile u32 Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC
-	 */
-	volatile u32 Fill4[412];	/* 0x0190 - 0x07FC */
-
-	volatile u32 TACtrlStreamBase;	/* 0x0800 */
-	volatile u32 TAObjDataBase;	/* 0x0804 */
-	volatile u32 TAPtrDataBase;	/* 0x0808 */
-	volatile u32 TARegionDataBase;	/* 0x080C */
-	volatile u32 TATailPtrBase;	/* 0x0810 */
-	volatile u32 TAPtrRegionSize;	/* 0x0814 */
-	volatile u32 TAConfiguration;	/* 0x0818 */
-	volatile u32 TAObjDataStartAddr;	/* 0x081C */
-	volatile u32 TAObjDataEndAddr;	/* 0x0820 */
-	volatile u32 TAXScreenClip;	/* 0x0824 */
-	volatile u32 TAYScreenClip;	/* 0x0828 */
-	volatile u32 TARHWClamp;	/* 0x082C */
-	volatile u32 TARHWCompare;	/* 0x0830 */
-	volatile u32 TAStart;	/* 0x0834 */
-	volatile u32 TAObjReStart;	/* 0x0838 */
-	volatile u32 TAPtrReStart;	/* 0x083C */
-	volatile u32 TAStatus1;	/* 0x0840 */
-	volatile u32 TAStatus2;	/* 0x0844 */
-	volatile u32 TAIntStatus;	/* 0x0848 */
-	volatile u32 TAIntMask;	/* 0x084C */
-
-	volatile u32 Fill5[235];	/* GAP 0x0850 - 0x0BF8 */
-
-	volatile u32 TextureAddrThresh;	/* 0x0BFC */
-	volatile u32 Core1Translation;	/* 0x0C00 */
-	volatile u32 TextureAddrReMap;	/* 0x0C04 */
-	volatile u32 RenderOutAGPRemap;	/* 0x0C08 */
-	volatile u32 _3DRegionReadTrans;	/* 0x0C0C */
-	volatile u32 _3DPtrReadTrans;	/* 0x0C10 */
-	volatile u32 _3DParamReadTrans;	/* 0x0C14 */
-	volatile u32 _3DRegionReadThresh;	/* 0x0C18 */
-	volatile u32 _3DPtrReadThresh;	/* 0x0C1C */
-	volatile u32 _3DParamReadThresh;	/* 0x0C20 */
-	volatile u32 _3DRegionReadAGPRemap;	/* 0x0C24 */
-	volatile u32 _3DPtrReadAGPRemap;	/* 0x0C28 */
-	volatile u32 _3DParamReadAGPRemap;	/* 0x0C2C */
-	volatile u32 ZBufferAGPRemap;	/* 0x0C30 */
-	volatile u32 TAIndexAGPRemap;	/* 0x0C34 */
-	volatile u32 TAVertexAGPRemap;	/* 0x0C38 */
-	volatile u32 TAUVAddrTrans;	/* 0x0C3C */
-	volatile u32 TATailPtrCacheTrans;	/* 0x0C40 */
-	volatile u32 TAParamWriteTrans;	/* 0x0C44 */
-	volatile u32 TAPtrWriteTrans;	/* 0x0C48 */
-	volatile u32 TAParamWriteThresh;	/* 0x0C4C */
-	volatile u32 TAPtrWriteThresh;	/* 0x0C50 */
-	volatile u32 TATailPtrCacheAGPRe;	/* 0x0C54 */
-	volatile u32 TAParamWriteAGPRe;	/* 0x0C58 */
-	volatile u32 TAPtrWriteAGPRe;	/* 0x0C5C */
-	volatile u32 SDRAMArbiterConf;	/* 0x0C60 */
-	volatile u32 SDRAMConf0;	/* 0x0C64 */
-	volatile u32 SDRAMConf1;	/* 0x0C68 */
-	volatile u32 SDRAMConf2;	/* 0x0C6C */
-	volatile u32 SDRAMRefresh;	/* 0x0C70 */
-	volatile u32 SDRAMPowerStat;	/* 0x0C74 */
-
-	volatile u32 Fill6[2];	/* GAP 0x0C78 - 0x0C7C */
-
-	volatile u32 RAMBistData;	/* 0x0C80 */
-	volatile u32 RAMBistCtrl;	/* 0x0C84 */
-	volatile u32 FIFOBistKey;	/* 0x0C88 */
-	volatile u32 RAMBistResult;	/* 0x0C8C */
-	volatile u32 FIFOBistResult;	/* 0x0C90 */
-
-	/*
-	   volatile u32 Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC
-	   volatile u32 Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters
-	 */
-
-	volatile u32 Fill7[16];	/* 0x0c94 - 0x0cd0 */
-
-	volatile u32 SDRAMAddrSign;	/* 0x0CD4 */
-	volatile u32 SDRAMDataSign;	/* 0x0CD8 */
-	volatile u32 SDRAMSignConf;	/* 0x0CDC */
-
-	/* DWFILL; //GAP 0x0CE0 */
-	volatile u32 dwFill_2;
-
-	volatile u32 ISPSignature;	/* 0x0CE4 */
-
-	volatile u32 Fill8[454];	/*GAP 0x0CE8 - 0x13FC */
-
-	volatile u32 DACPrimAddress;	/* 0x1400 */
-	volatile u32 DACPrimSize;	/* 0x1404 */
-	volatile u32 DACCursorAddr;	/* 0x1408 */
-	volatile u32 DACCursorCtrl;	/* 0x140C */
-	volatile u32 DACOverlayAddr;	/* 0x1410 */
-	volatile u32 DACOverlayUAddr;	/* 0x1414 */
-	volatile u32 DACOverlayVAddr;	/* 0x1418 */
-	volatile u32 DACOverlaySize;	/* 0x141C */
-	volatile u32 DACOverlayVtDec;	/* 0x1420 */
-
-	volatile u32 Fill9[9];	/* GAP 0x1424 - 0x1444 */
-
-	volatile u32 DACVerticalScal;	/* 0x1448 */
-	volatile u32 DACPixelFormat;	/* 0x144C */
-	volatile u32 DACHorizontalScal;	/* 0x1450 */
-	volatile u32 DACVidWinStart;	/* 0x1454 */
-	volatile u32 DACVidWinEnd;	/* 0x1458 */
-	volatile u32 DACBlendCtrl;	/* 0x145C */
-	volatile u32 DACHorTim1;	/* 0x1460 */
-	volatile u32 DACHorTim2;	/* 0x1464 */
-	volatile u32 DACHorTim3;	/* 0x1468 */
-	volatile u32 DACVerTim1;	/* 0x146C */
-	volatile u32 DACVerTim2;	/* 0x1470 */
-	volatile u32 DACVerTim3;	/* 0x1474 */
-	volatile u32 DACBorderColor;	/* 0x1478 */
-	volatile u32 DACSyncCtrl;	/* 0x147C */
-	volatile u32 DACStreamCtrl;	/* 0x1480 */
-	volatile u32 DACLUTAddress;	/* 0x1484 */
-	volatile u32 DACLUTData;	/* 0x1488 */
-	volatile u32 DACBurstCtrl;	/* 0x148C */
-	volatile u32 DACCrcTrigger;	/* 0x1490 */
-	volatile u32 DACCrcDone;	/* 0x1494 */
-	volatile u32 DACCrcResult1;	/* 0x1498 */
-	volatile u32 DACCrcResult2;	/* 0x149C */
-	volatile u32 DACLinecount;	/* 0x14A0 */
-
-	volatile u32 Fill10[151];	/*GAP 0x14A4 - 0x16FC */
-
-	volatile u32 DigVidPortCtrl;	/* 0x1700 */
-	volatile u32 DigVidPortStat;	/* 0x1704 */
-
-	/*
-	   volatile u32 Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC
-	   volatile u32 Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT
-	 */
-
-	volatile u32 Fill11[1598];
-
-	/* DWFILL; //GAP 0x3000          ALUT 256MB offset */
-	volatile u32 Fill_3;
-
-} STG4000REG;
-
-#endif /* _STG4000REG_H */
diff --git a/drivers/video/kyro/STG4000VTG.c b/drivers/video/kyro/STG4000VTG.c
deleted file mode 100644
index bd389709d234..000000000000
--- a/drivers/video/kyro/STG4000VTG.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *  linux/drivers/video/kyro/STG4000VTG.c
- *
- *  Copyright (C) 2002 STMicroelectronics
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/types.h>
-#include <video/kyro.h>
-
-#include "STG4000Reg.h"
-#include "STG4000Interface.h"
-
-void DisableVGA(volatile STG4000REG __iomem *pSTGReg)
-{
-	u32 tmp;
-	volatile u32 count = 0, i;
-
-	/* Reset the VGA registers */
-	tmp = STG_READ_REG(SoftwareReset);
-	CLEAR_BIT(8);
-	STG_WRITE_REG(SoftwareReset, tmp);
-
-	/* Just for Delay */
-	for (i = 0; i < 1000; i++) {
-		count++;
-	}
-
-	/* Pull-out the VGA registers from reset */
-	tmp = STG_READ_REG(SoftwareReset);
-	tmp |= SET_BIT(8);
-	STG_WRITE_REG(SoftwareReset, tmp);
-}
-
-void StopVTG(volatile STG4000REG __iomem *pSTGReg)
-{
-	u32 tmp = 0;
-
-	/* Stop Ver and Hor Sync Generator */
-	tmp = (STG_READ_REG(DACSyncCtrl)) | SET_BIT(0) | SET_BIT(2);
-	CLEAR_BIT(31);
-	STG_WRITE_REG(DACSyncCtrl, tmp);
-}
-
-void StartVTG(volatile STG4000REG __iomem *pSTGReg)
-{
-	u32 tmp = 0;
-
-	/* Start Ver and Hor Sync Generator */
-	tmp = ((STG_READ_REG(DACSyncCtrl)) | SET_BIT(31));
-	CLEAR_BIT(0);
-	CLEAR_BIT(2);
-	STG_WRITE_REG(DACSyncCtrl, tmp);
-}
-
-void SetupVTG(volatile STG4000REG __iomem *pSTGReg,
-	      const struct kyrofb_info * pTiming)
-{
-	u32 tmp = 0;
-	u32 margins = 0;
-	u32 ulBorder;
-	u32 xRes = pTiming->XRES;
-	u32 yRes = pTiming->YRES;
-
-	/* Horizontal */
-	u32 HAddrTime, HRightBorder, HLeftBorder;
-	u32 HBackPorcStrt, HFrontPorchStrt, HTotal,
-	    HLeftBorderStrt, HRightBorderStrt, HDisplayStrt;
-
-	/* Vertical */
-	u32 VDisplayStrt, VBottomBorder, VTopBorder;
-	u32 VBackPorchStrt, VTotal, VTopBorderStrt,
-	    VFrontPorchStrt, VBottomBorderStrt, VAddrTime;
-
-	/* Need to calculate the right border */
-	if ((xRes == 640) && (yRes == 480)) {
-		if ((pTiming->VFREQ == 60) || (pTiming->VFREQ == 72)) {
-			margins = 8;
-		}
-	}
-
-	/* Work out the Border */
-	ulBorder =
-	    (pTiming->HTot -
-	     (pTiming->HST + (pTiming->HBP - margins) + xRes +
-	      (pTiming->HFP - margins))) >> 1;
-
-	/* Border the same for Vertical and Horizontal */
-	VBottomBorder = HLeftBorder = VTopBorder = HRightBorder = ulBorder;
-
-    /************ Get Timing values for Horizontal ******************/
-	HAddrTime = xRes;
-	HBackPorcStrt = pTiming->HST;
-	HTotal = pTiming->HTot;
-	HDisplayStrt =
-	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder;
-	HLeftBorderStrt = HDisplayStrt - HLeftBorder;
-	HFrontPorchStrt =
-	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder +
-	    HAddrTime + HRightBorder;
-	HRightBorderStrt = HFrontPorchStrt - HRightBorder;
-
-    /************ Get Timing values for Vertical ******************/
-	VAddrTime = yRes;
-	VBackPorchStrt = pTiming->VST;
-	VTotal = pTiming->VTot;
-	VDisplayStrt =
-	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder;
-	VTopBorderStrt = VDisplayStrt - VTopBorder;
-	VFrontPorchStrt =
-	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder +
-	    VAddrTime + VBottomBorder;
-	VBottomBorderStrt = VFrontPorchStrt - VBottomBorder;
-
-	/* Set Hor Timing 1, 2, 3 */
-	tmp = STG_READ_REG(DACHorTim1);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 27);
-	tmp |= (HTotal) | (HBackPorcStrt << 16);
-	STG_WRITE_REG(DACHorTim1, tmp);
-
-	tmp = STG_READ_REG(DACHorTim2);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 27);
-	tmp |= (HDisplayStrt << 16) | HLeftBorderStrt;
-	STG_WRITE_REG(DACHorTim2, tmp);
-
-	tmp = STG_READ_REG(DACHorTim3);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 27);
-	tmp |= (HFrontPorchStrt << 16) | HRightBorderStrt;
-	STG_WRITE_REG(DACHorTim3, tmp);
-
-	/* Set Ver Timing 1, 2, 3 */
-	tmp = STG_READ_REG(DACVerTim1);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 27);
-	tmp |= (VBackPorchStrt << 16) | (VTotal);
-	STG_WRITE_REG(DACVerTim1, tmp);
-
-	tmp = STG_READ_REG(DACVerTim2);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 27);
-	tmp |= (VDisplayStrt << 16) | VTopBorderStrt;
-	STG_WRITE_REG(DACVerTim2, tmp);
-
-	tmp = STG_READ_REG(DACVerTim3);
-	CLEAR_BITS_FRM_TO(0, 11);
-	CLEAR_BITS_FRM_TO(16, 27);
-	tmp |= (VFrontPorchStrt << 16) | VBottomBorderStrt;
-	STG_WRITE_REG(DACVerTim3, tmp);
-
-	/* Set Verical and Horizontal Polarity */
-	tmp = STG_READ_REG(DACSyncCtrl) | SET_BIT(3) | SET_BIT(1);
-
-	if ((pTiming->HSP > 0) && (pTiming->VSP < 0)) {	/* +hsync -vsync */
-		tmp &= ~0x8;
-	} else if ((pTiming->HSP < 0) && (pTiming->VSP > 0)) {	/* -hsync +vsync */
-		tmp &= ~0x2;
-	} else if ((pTiming->HSP < 0) && (pTiming->VSP < 0)) {	/* -hsync -vsync */
-		tmp &= ~0xA;
-	} else if ((pTiming->HSP > 0) && (pTiming->VSP > 0)) {	/* +hsync -vsync */
-		tmp &= ~0x0;
-	}
-
-	STG_WRITE_REG(DACSyncCtrl, tmp);
-}
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
deleted file mode 100644
index 65041e15fd59..000000000000
--- a/drivers/video/kyro/fbdev.c
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
- *  linux/drivers/video/kyro/fbdev.c
- *
- *  Copyright (C) 2002 STMicroelectronics
- *  Copyright (C) 2003, 2004 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioctl.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/kyro.h>
-
-#include "STG4000Reg.h"
-#include "STG4000Interface.h"
-
-/*
- * PCI Definitions
- */
-#define PCI_VENDOR_ID_ST	0x104a
-#define PCI_DEVICE_ID_STG4000	0x0010
-
-#define KHZ2PICOS(a) (1000000000UL/(a))
-
-/****************************************************************************/
-static struct fb_fix_screeninfo kyro_fix = {
-	.id		= "ST Kyro",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_TRUECOLOR,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo kyro_var = {
-	/* 640x480, 16bpp @ 60 Hz */
-	.xres		= 640,
-	.yres		= 480,
-	.xres_virtual	= 640,
-	.yres_virtual	= 480,
-	.bits_per_pixel	= 16,
-	.red		= { 11, 5, 0 },
-	.green		= {  5, 6, 0 },
-	.blue		= {  0, 5, 0 },
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.pixclock	= KHZ2PICOS(25175),
-	.left_margin	= 48,
-	.right_margin	= 16,
-	.upper_margin	= 33,
-	.lower_margin	= 10,
-	.hsync_len	= 96,
-	.vsync_len	= 2,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-typedef struct {
-	STG4000REG __iomem *pSTGReg;	/* Virtual address of PCI register region */
-	u32 ulNextFreeVidMem;	/* Offset from start of vid mem to next free region */
-	u32 ulOverlayOffset;	/* Offset from start of vid mem to overlay */
-	u32 ulOverlayStride;	/* Interleaved YUV and 422 mode Y stride */
-	u32 ulOverlayUVStride;	/* 422 mode U & V stride */
-} device_info_t;
-
-/* global graphics card info structure (one per card) */
-static device_info_t deviceInfo;
-
-static char *mode_option = NULL;
-static int nopan = 0;
-static int nowrap = 1;
-#ifdef CONFIG_MTRR
-static int nomtrr = 0;
-#endif
-
-/* PCI driver prototypes */
-static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void kyrofb_remove(struct pci_dev *pdev);
-
-static struct fb_videomode kyro_modedb[] = {
-	{
-		/* 640x350 @ 85Hz */
-		NULL, 85, 640, 350, KHZ2PICOS(31500),
-		96, 32, 60, 32, 64, 3,
-		FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 640x400 @ 85Hz */
-		NULL, 85, 640, 400, KHZ2PICOS(31500),
-		96, 32, 41, 1, 64, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 720x400 @ 85Hz */
-		NULL, 85, 720, 400, KHZ2PICOS(35500),
-		108, 36, 42, 1, 72, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 640x480 @ 60Hz */
-		NULL, 60, 640, 480, KHZ2PICOS(25175),
-		48, 16, 33, 10, 96, 2,
-		0, FB_VMODE_NONINTERLACED
-	}, {
-		/* 640x480 @ 72Hz */
-		NULL, 72, 640, 480, KHZ2PICOS(31500),
-		128, 24, 28, 9, 40, 3,
-		0, FB_VMODE_NONINTERLACED
-	}, {
-		/* 640x480 @ 75Hz */
-		NULL, 75, 640, 480, KHZ2PICOS(31500),
-		120, 16, 16, 1, 64, 3,
-		0, FB_VMODE_NONINTERLACED
-	}, {
-		/* 640x480 @ 85Hz */
-		NULL, 85, 640, 480, KHZ2PICOS(36000),
-		80, 56, 25, 1, 56, 3,
-		0, FB_VMODE_NONINTERLACED
-	}, {
-		/* 800x600 @ 56Hz */
-		NULL, 56, 800, 600, KHZ2PICOS(36000),
-		128, 24, 22, 1, 72, 2,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 800x600 @ 60Hz */
-		NULL, 60, 800, 600, KHZ2PICOS(40000),
-		88, 40, 23, 1, 128, 4,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 800x600 @ 72Hz */
-		NULL, 72, 800, 600, KHZ2PICOS(50000),
-		64, 56, 23, 37, 120, 6,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 800x600 @ 75Hz */
-		NULL, 75, 800, 600, KHZ2PICOS(49500),
-		160, 16, 21, 1, 80, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 800x600 @ 85Hz */
-		NULL, 85, 800, 600, KHZ2PICOS(56250),
-		152, 32, 27, 1, 64, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1024x768 @ 60Hz */
-		NULL, 60, 1024, 768, KHZ2PICOS(65000),
-		160, 24, 29, 3, 136, 6,
-		0, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1024x768 @ 70Hz */
-		NULL, 70, 1024, 768, KHZ2PICOS(75000),
-		144, 24, 29, 3, 136, 6,
-		0, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1024x768 @ 75Hz */
-		NULL, 75, 1024, 768, KHZ2PICOS(78750),
-		176, 16, 28, 1, 96, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1024x768 @ 85Hz */
-		NULL, 85, 1024, 768, KHZ2PICOS(94500),
-		208, 48, 36, 1, 96, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1152x864 @ 75Hz */
-		NULL, 75, 1152, 864, KHZ2PICOS(108000),
-		256, 64, 32, 1, 128, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1280x960 @ 60Hz */
-		NULL, 60, 1280, 960, KHZ2PICOS(108000),
-		312, 96, 36, 1, 112, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1280x960 @ 85Hz */
-		NULL, 85, 1280, 960, KHZ2PICOS(148500),
-		224, 64, 47, 1, 160, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1280x1024 @ 60Hz */
-		NULL, 60, 1280, 1024, KHZ2PICOS(108000),
-		248, 48, 38, 1, 112, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1280x1024 @ 75Hz */
-		NULL, 75, 1280, 1024, KHZ2PICOS(135000),
-		248, 16, 38, 1, 144, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1280x1024 @ 85Hz */
-		NULL, 85, 1280, 1024, KHZ2PICOS(157500),
-		224, 64, 44, 1, 160, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1600x1200 @ 60Hz */
-		NULL, 60, 1600, 1200, KHZ2PICOS(162000),
-		304, 64, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1600x1200 @ 65Hz */
-		NULL, 65, 1600, 1200, KHZ2PICOS(175500),
-		304, 64, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1600x1200 @ 70Hz */
-		NULL, 70, 1600, 1200, KHZ2PICOS(189000),
-		304, 64, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1600x1200 @ 75Hz */
-		NULL, 75, 1600, 1200, KHZ2PICOS(202500),
-		304, 64, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1600x1200 @ 85Hz */
-		NULL, 85, 1600, 1200, KHZ2PICOS(229500),
-		304, 64, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1792x1344 @ 60Hz */
-		NULL, 60, 1792, 1344, KHZ2PICOS(204750),
-		328, 128, 46, 1, 200, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1792x1344 @ 75Hz */
-		NULL, 75, 1792, 1344, KHZ2PICOS(261000),
-		352, 96, 69, 1, 216, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1856x1392 @ 60Hz */
-		NULL, 60, 1856, 1392, KHZ2PICOS(218250),
-		352, 96, 43, 1, 224, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1856x1392 @ 75Hz */
-		NULL, 75, 1856, 1392, KHZ2PICOS(288000),
-		352, 128, 104, 1, 224, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1920x1440 @ 60Hz */
-		NULL, 60, 1920, 1440, KHZ2PICOS(234000),
-		344, 128, 56, 1, 208, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}, {
-		/* 1920x1440 @ 75Hz */
-		NULL, 75, 1920, 1440, KHZ2PICOS(297000),
-		352, 144, 56, 1, 224, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	},
-};
-#define NUM_TOTAL_MODES	ARRAY_SIZE(kyro_modedb)
-
-/*
- * This needs to be kept ordered corresponding to kyro_modedb.
- */
-enum {
-	VMODE_640_350_85,
-	VMODE_640_400_85,
-	VMODE_720_400_85,
-	VMODE_640_480_60,
-	VMODE_640_480_72,
-	VMODE_640_480_75,
-	VMODE_640_480_85,
-	VMODE_800_600_56,
-	VMODE_800_600_60,
-	VMODE_800_600_72,
-	VMODE_800_600_75,
-	VMODE_800_600_85,
-	VMODE_1024_768_60,
-	VMODE_1024_768_70,
-	VMODE_1024_768_75,
-	VMODE_1024_768_85,
-	VMODE_1152_864_75,
-	VMODE_1280_960_60,
-	VMODE_1280_960_85,
-	VMODE_1280_1024_60,
-	VMODE_1280_1024_75,
-	VMODE_1280_1024_85,
-	VMODE_1600_1200_60,
-	VMODE_1600_1200_65,
-	VMODE_1600_1200_70,
-	VMODE_1600_1200_75,
-	VMODE_1600_1200_85,
-	VMODE_1792_1344_60,
-	VMODE_1792_1344_75,
-	VMODE_1856_1392_60,
-	VMODE_1856_1392_75,
-	VMODE_1920_1440_60,
-	VMODE_1920_1440_75,
-};
-
-/* Accessors */
-static int kyro_dev_video_mode_set(struct fb_info *info)
-{
-	struct kyrofb_info *par = info->par;
-
-	/* Turn off display */
-	StopVTG(deviceInfo.pSTGReg);
-	DisableRamdacOutput(deviceInfo.pSTGReg);
-
-	/* Bring us out of VGA and into Hi-Res mode, if not already. */
-	DisableVGA(deviceInfo.pSTGReg);
-
-	if (InitialiseRamdac(deviceInfo.pSTGReg,
-			     info->var.bits_per_pixel,
-			     info->var.xres, info->var.yres,
-			     par->HSP, par->VSP, &par->PIXCLK) < 0)
-		return -EINVAL;
-
-	SetupVTG(deviceInfo.pSTGReg, par);
-
-	ResetOverlayRegisters(deviceInfo.pSTGReg);
-
-	/* Turn on display in new mode */
-	EnableRamdacOutput(deviceInfo.pSTGReg);
-	StartVTG(deviceInfo.pSTGReg);
-
-	deviceInfo.ulNextFreeVidMem = info->var.xres * info->var.yres *
-				      info->var.bits_per_pixel;
-	deviceInfo.ulOverlayOffset = 0;
-
-	return 0;
-}
-
-static int kyro_dev_overlay_create(u32 ulWidth,
-				   u32 ulHeight, int bLinear)
-{
-	u32 offset;
-	u32 stride, uvStride;
-
-	if (deviceInfo.ulOverlayOffset != 0)
-		/*
-		 * Can only create one overlay without resetting the card or
-		 * changing display mode
-		 */
-		return -EINVAL;
-
-	ResetOverlayRegisters(deviceInfo.pSTGReg);
-
-	/* Overlays are addressed in multiples of 16bytes or 32bytes, so make
-	 * sure the start offset is on an appropriate boundary.
-	 */
-	offset = deviceInfo.ulNextFreeVidMem;
-	if ((offset & 0x1f) != 0) {
-		offset = (offset + 32L) & 0xffffffE0L;
-	}
-
-	if (CreateOverlaySurface(deviceInfo.pSTGReg, ulWidth, ulHeight,
-				 bLinear, offset, &stride, &uvStride) < 0)
-		return -EINVAL;
-
-	deviceInfo.ulOverlayOffset = offset;
-	deviceInfo.ulOverlayStride = stride;
-	deviceInfo.ulOverlayUVStride = uvStride;
-	deviceInfo.ulNextFreeVidMem = offset + (ulHeight * stride) + (ulHeight * 2 * uvStride);
-
-	SetOverlayBlendMode(deviceInfo.pSTGReg, GLOBAL_ALPHA, 0xf, 0x0);
-
-	return 0;
-}
-
-static int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight)
-{
-	if (deviceInfo.ulOverlayOffset == 0)
-		/* probably haven't called CreateOverlay yet */
-		return -EINVAL;
-
-	/* Stop Ramdac Output */
-	DisableRamdacOutput(deviceInfo.pSTGReg);
-
-	SetOverlayViewPort(deviceInfo.pSTGReg,
-			   x, y, x + ulWidth - 1, y + ulHeight - 1);
-
-	EnableOverlayPlane(deviceInfo.pSTGReg);
-	/* Start Ramdac Output */
-	EnableRamdacOutput(deviceInfo.pSTGReg);
-
-	return 0;
-}
-
-static inline unsigned long get_line_length(int x, int bpp)
-{
-	return (unsigned long)((((x*bpp)+31)&~31) >> 3);
-}
-
-static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct kyrofb_info *par = info->par;
-
-	if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
-		printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.length = 5;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		var->transp.length = 8;
-		break;
-	}
-
-	/* Height/Width of picture in mm */
-	var->height = var->width = -1;
-
-	/* Timing information. All values are in picoseconds */
-
-	/* par->PIXCLK is in 100Hz units. Convert to picoseconds -
-	 * ensuring we do not exceed 32 bit precision
-	 */
-	/*
-	 * XXX: Enabling this really screws over the pixclock value when we
-	 * read it back with fbset. As such, leaving this commented out appears
-	 * to do the right thing (at least for now) .. bearing in mind that we
-	 * have infact already done the KHZ2PICOS conversion in both the modedb
-	 * and kyro_var. -- PFM.
-	 */
-//	var->pixclock = 1000000000 / (par->PIXCLK / 10);
-
-	/* the header file claims we should use picoseconds
-	 * - nobody else does though, the all use pixels and lines
-	 * of h and v sizes. Both options here.
-	 */
-
-	/*
-	 * If we're being called by __fb_try_mode(), then we don't want to
-	 * override any of the var settings that we've already parsed
-	 * from our modedb. -- PFM.
-	 */
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
-		return 0;
-
-	var->left_margin = par->HBP;
-	var->hsync_len = par->HST;
-	var->right_margin = par->HFP;
-
-	var->upper_margin = par->VBP;
-	var->vsync_len = par->VST;
-	var->lower_margin = par->VFP;
-
-	if (par->HSP == 1)
-		var->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (par->VSP == 1)
-		var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
-	return 0;
-}
-
-static int kyrofb_set_par(struct fb_info *info)
-{
-	struct kyrofb_info *par = info->par;
-	unsigned long lineclock;
-	unsigned long frameclock;
-
-	/* Actual resolution */
-	par->XRES = info->var.xres;
-	par->YRES = info->var.yres;
-
-	/* pixel depth */
-	par->PIXDEPTH = info->var.bits_per_pixel;
-
-	/* Refresh rate */
-	/* time for a line in ns */
-	lineclock = (info->var.pixclock * (info->var.xres +
-				    info->var.right_margin +
-				    info->var.hsync_len +
-				    info->var.left_margin)) / 1000;
-
-
-	/* time for a frame in ns (precision in 32bpp) */
-	frameclock = lineclock * (info->var.yres +
-				  info->var.lower_margin +
-				  info->var.vsync_len +
-				  info->var.upper_margin);
-
-	/* Calculate refresh rate and horrizontal clocks */
-	par->VFREQ = (1000000000 + (frameclock / 2)) / frameclock;
-	par->HCLK = (1000000000 + (lineclock / 2)) / lineclock;
-	par->PIXCLK = ((1000000000 + (info->var.pixclock / 2))
-					/ info->var.pixclock) * 10;
-
-	/* calculate horizontal timings */
-	par->HFP = info->var.right_margin;
-	par->HST = info->var.hsync_len;
-	par->HBP = info->var.left_margin;
-	par->HTot = par->XRES + par->HBP + par->HST + par->HFP;
-
-	/* calculate vertical timings */
-	par->VFP = info->var.lower_margin;
-	par->VST = info->var.vsync_len;
-	par->VBP = info->var.upper_margin;
-	par->VTot = par->YRES + par->VBP + par->VST + par->VFP;
-
-	par->HSP = (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0;
-	par->VSP = (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0;
-
-	kyro_dev_video_mode_set(info);
-
-	/* length of a line in bytes    */
-	info->fix.line_length = get_line_length(par->XRES, par->PIXDEPTH);
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	return 0;
-}
-
-static int kyrofb_setcolreg(u_int regno, u_int red, u_int green,
-			    u_int blue, u_int transp, struct fb_info *info)
-{
-	struct kyrofb_info *par = info->par;
-
-	if (regno > 255)
-		return 1;	/* Invalid register */
-
-	if (regno < 16) {
-		switch (info->var.bits_per_pixel) {
-		case 16:
-			par->palette[regno] =
-			     (red   & 0xf800) |
-			    ((green & 0xfc00) >> 5) |
-			    ((blue  & 0xf800) >> 11);
-			break;
-		case 32:
-			red >>= 8; green >>= 8; blue >>= 8; transp >>= 8;
-			par->palette[regno] =
-			    (transp << 24) | (red << 16) | (green << 8) | blue;
-			break;
-		}
-	}
-
-	return 0;
-}
-
-#ifndef MODULE
-static int __init kyrofb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ","))) {
-		if (!*this_opt)
-			continue;
-		if (strcmp(this_opt, "nopan") == 0) {
-			nopan = 1;
-		} else if (strcmp(this_opt, "nowrap") == 0) {
-			nowrap = 1;
-#ifdef CONFIG_MTRR
-		} else if (strcmp(this_opt, "nomtrr") == 0) {
-			nomtrr = 1;
-#endif
-		} else {
-			mode_option = this_opt;
-		}
-	}
-
-	return 0;
-}
-#endif
-
-static int kyrofb_ioctl(struct fb_info *info,
-			unsigned int cmd, unsigned long arg)
-{
-	overlay_create ol_create;
-	overlay_viewport_set ol_viewport_set;
-	void __user *argp = (void __user *)arg;
-
-	switch (cmd) {
-	case KYRO_IOCTL_OVERLAY_CREATE:
-		if (copy_from_user(&ol_create, argp, sizeof(overlay_create)))
-			return -EFAULT;
-
-		if (kyro_dev_overlay_create(ol_create.ulWidth,
-					    ol_create.ulHeight, 0) < 0) {
-			printk(KERN_ERR "Kyro FB: failed to create overlay surface.\n");
-
-			return -EINVAL;
-		}
-		break;
-	case KYRO_IOCTL_OVERLAY_VIEWPORT_SET:
-		if (copy_from_user(&ol_viewport_set, argp,
-			       sizeof(overlay_viewport_set)))
-			return -EFAULT;
-
-		if (kyro_dev_overlay_viewport_set(ol_viewport_set.xOrgin,
-						  ol_viewport_set.yOrgin,
-						  ol_viewport_set.xSize,
-						  ol_viewport_set.ySize) != 0)
-		{
-			printk(KERN_ERR "Kyro FB: failed to create overlay viewport.\n");
-			return -EINVAL;
-		}
-		break;
-	case KYRO_IOCTL_SET_VIDEO_MODE:
-		{
-			printk(KERN_ERR "Kyro FB: KYRO_IOCTL_SET_VIDEO_MODE is"
-				"obsolete, use the appropriate fb_ioctl()"
-				"command instead.\n");
-			return -EINVAL;
-		}
-	case KYRO_IOCTL_UVSTRIDE:
-		if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
-			return -EFAULT;
-		break;
-	case KYRO_IOCTL_STRIDE:
-		if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
-			return -EFAULT;
-		break;
-	case KYRO_IOCTL_OVERLAY_OFFSET:
-		if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
-			return -EFAULT;
-		break;
-	}
-
-	return 0;
-}
-
-static struct pci_device_id kyrofb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_ST, PCI_DEVICE_ID_STG4000,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, kyrofb_pci_tbl);
-
-static struct pci_driver kyrofb_pci_driver = {
-	.name		= "kyrofb",
-	.id_table	= kyrofb_pci_tbl,
-	.probe		= kyrofb_probe,
-	.remove		= kyrofb_remove,
-};
-
-static struct fb_ops kyrofb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= kyrofb_check_var,
-	.fb_set_par	= kyrofb_set_par,
-	.fb_setcolreg	= kyrofb_setcolreg,
-	.fb_ioctl	= kyrofb_ioctl,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	struct fb_info *info;
-	struct kyrofb_info *currentpar;
-	unsigned long size;
-	int err;
-
-	if ((err = pci_enable_device(pdev))) {
-		printk(KERN_WARNING "kyrofb: Can't enable pdev: %d\n", err);
-		return err;
-	}
-
-	info = framebuffer_alloc(sizeof(struct kyrofb_info), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	currentpar = info->par;
-
-	kyro_fix.smem_start = pci_resource_start(pdev, 0);
-	kyro_fix.smem_len   = pci_resource_len(pdev, 0);
-	kyro_fix.mmio_start = pci_resource_start(pdev, 1);
-	kyro_fix.mmio_len   = pci_resource_len(pdev, 1);
-
-	currentpar->regbase = deviceInfo.pSTGReg =
-		ioremap_nocache(kyro_fix.mmio_start, kyro_fix.mmio_len);
-
-	info->screen_base = ioremap_nocache(kyro_fix.smem_start,
-					    kyro_fix.smem_len);
-
-#ifdef CONFIG_MTRR
-	if (!nomtrr)
-		currentpar->mtrr_handle =
-			mtrr_add(kyro_fix.smem_start,
-				 kyro_fix.smem_len,
-				 MTRR_TYPE_WRCOMB, 1);
-#endif
-
-	kyro_fix.ypanstep	= nopan ? 0 : 1;
-	kyro_fix.ywrapstep	= nowrap ? 0 : 1;
-
-	info->fbops		= &kyrofb_ops;
-	info->fix		= kyro_fix;
-	info->pseudo_palette	= currentpar->palette;
-	info->flags		= FBINFO_DEFAULT;
-
-	SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
-
-	deviceInfo.ulNextFreeVidMem = 0;
-	deviceInfo.ulOverlayOffset = 0;
-
-	/* This should give a reasonable default video mode */
-	if (!fb_find_mode(&info->var, info, mode_option, kyro_modedb,
-			  NUM_TOTAL_MODES, &kyro_modedb[VMODE_1024_768_75], 32))
-		info->var = kyro_var;
-
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	kyrofb_set_par(info);
-	kyrofb_check_var(&info->var, info);
-
-	size = get_line_length(info->var.xres_virtual,
-			       info->var.bits_per_pixel);
-	size *= info->var.yres_virtual;
-
-	fb_memset(info->screen_base, 0, size);
-
-	if (register_framebuffer(info) < 0)
-		goto out_unmap;
-
-	fb_info(info, "%s frame buffer device, at %dx%d@%d using %ldk/%ldk of VRAM\n",
-		info->fix.id,
-		info->var.xres, info->var.yres, info->var.bits_per_pixel,
-		size >> 10, (unsigned long)info->fix.smem_len >> 10);
-
-	pci_set_drvdata(pdev, info);
-
-	return 0;
-
-out_unmap:
-	iounmap(currentpar->regbase);
-	iounmap(info->screen_base);
-	framebuffer_release(info);
-
-	return -EINVAL;
-}
-
-static void kyrofb_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct kyrofb_info *par = info->par;
-
-	/* Reset the board */
-	StopVTG(deviceInfo.pSTGReg);
-	DisableRamdacOutput(deviceInfo.pSTGReg);
-
-	/* Sync up the PLL */
-	SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
-
-	deviceInfo.ulNextFreeVidMem = 0;
-	deviceInfo.ulOverlayOffset = 0;
-
-	iounmap(info->screen_base);
-	iounmap(par->regbase);
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr_handle)
-		mtrr_del(par->mtrr_handle,
-			 info->fix.smem_start,
-			 info->fix.smem_len);
-#endif
-
-	unregister_framebuffer(info);
-	framebuffer_release(info);
-}
-
-static int __init kyrofb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("kyrofb", &option))
-		return -ENODEV;
-	kyrofb_setup(option);
-#endif
-	return pci_register_driver(&kyrofb_pci_driver);
-}
-
-static void __exit kyrofb_exit(void)
-{
-	pci_unregister_driver(&kyrofb_pci_driver);
-}
-
-module_init(kyrofb_init);
-
-#ifdef MODULE
-module_exit(kyrofb_exit);
-#endif
-
-MODULE_AUTHOR("STMicroelectronics; Paul Mundt <lethal@linux-sh.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
deleted file mode 100644
index 2c7f7d479fe2..000000000000
--- a/drivers/video/leo.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/* leo.c: LEO frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/of_device.h>
-#include <linux/io.h>
-
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			 unsigned, struct fb_info *);
-static int leo_blank(int, struct fb_info *);
-
-static int leo_mmap(struct fb_info *, struct vm_area_struct *);
-static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
-static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops leo_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= leo_setcolreg,
-	.fb_blank		= leo_blank,
-	.fb_pan_display		= leo_pan_display,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_mmap		= leo_mmap,
-	.fb_ioctl		= leo_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-#define LEO_OFF_LC_SS0_KRN	0x00200000UL
-#define LEO_OFF_LC_SS0_USR	0x00201000UL
-#define LEO_OFF_LC_SS1_KRN	0x01200000UL
-#define LEO_OFF_LC_SS1_USR	0x01201000UL
-#define LEO_OFF_LD_SS0		0x00400000UL
-#define LEO_OFF_LD_SS1		0x01400000UL
-#define LEO_OFF_LD_GBL		0x00401000UL
-#define LEO_OFF_LX_KRN		0x00600000UL
-#define LEO_OFF_LX_CURSOR	0x00601000UL
-#define LEO_OFF_SS0		0x00800000UL
-#define LEO_OFF_SS1		0x01800000UL
-#define LEO_OFF_UNK		0x00602000UL
-#define LEO_OFF_UNK2		0x00000000UL
-
-#define LEO_CUR_ENABLE		0x00000080
-#define LEO_CUR_UPDATE		0x00000030
-#define LEO_CUR_PROGRESS	0x00000006
-#define LEO_CUR_UPDATECMAP	0x00000003
-
-#define LEO_CUR_TYPE_MASK	0x00000000
-#define LEO_CUR_TYPE_IMAGE	0x00000020
-#define LEO_CUR_TYPE_CMAP	0x00000050
-
-struct leo_cursor {
-	u8	xxx0[16];
-	u32	cur_type;
-	u32	cur_misc;
-	u32	cur_cursxy;
-	u32	cur_data;
-};
-
-#define LEO_KRN_TYPE_CLUT0	0x00001000
-#define LEO_KRN_TYPE_CLUT1	0x00001001
-#define LEO_KRN_TYPE_CLUT2	0x00001002
-#define LEO_KRN_TYPE_WID	0x00001003
-#define LEO_KRN_TYPE_UNK	0x00001006
-#define LEO_KRN_TYPE_VIDEO	0x00002003
-#define LEO_KRN_TYPE_CLUTDATA	0x00004000
-#define LEO_KRN_CSR_ENABLE	0x00000008
-#define LEO_KRN_CSR_PROGRESS	0x00000004
-#define LEO_KRN_CSR_UNK		0x00000002
-#define LEO_KRN_CSR_UNK2	0x00000001
-
-struct leo_lx_krn {
-	u32	krn_type;
-	u32	krn_csr;
-	u32	krn_value;
-};
-
-struct leo_lc_ss0_krn {
-	u32 	misc;
-	u8	xxx0[0x800-4];
-	u32	rev;
-};
-
-struct leo_lc_ss0_usr {
-	u32	csr;
-	u32	addrspace;
-	u32 	fontmsk;
-	u32	fontt;
-	u32	extent;
-	u32	src;
-	u32	dst;
-	u32	copy;
-	u32	fill;
-};
-
-struct leo_lc_ss1_krn {
-	u8	unknown;
-};
-
-struct leo_lc_ss1_usr {
-	u8	unknown;
-};
-
-struct leo_ld_ss0 {
-	u8	xxx0[0xe00];
-	u32	csr;
-	u32	wid;
-	u32	wmask;
-	u32	widclip;
-	u32	vclipmin;
-	u32	vclipmax;
-	u32	pickmin;	/* SS1 only */
-	u32	pickmax;	/* SS1 only */
-	u32	fg;
-	u32	bg;
-	u32	src;		/* Copy/Scroll (SS0 only) */
-	u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
-	u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
-	u32	xxx1[3];
-	u32	setsem;		/* SS1 only */
-	u32	clrsem;		/* SS1 only */
-	u32	clrpick;	/* SS1 only */
-	u32	clrdat;		/* SS1 only */
-	u32	alpha;		/* SS1 only */
-	u8	xxx2[0x2c];
-	u32	winbg;
-	u32	planemask;
-	u32	rop;
-	u32	z;
-	u32	dczf;		/* SS1 only */
-	u32	dczb;		/* SS1 only */
-	u32	dcs;		/* SS1 only */
-	u32	dczs;		/* SS1 only */
-	u32	pickfb;		/* SS1 only */
-	u32	pickbb;		/* SS1 only */
-	u32	dcfc;		/* SS1 only */
-	u32	forcecol;	/* SS1 only */
-	u32	door[8];	/* SS1 only */
-	u32	pick[5];	/* SS1 only */
-};
-
-#define LEO_SS1_MISC_ENABLE	0x00000001
-#define LEO_SS1_MISC_STEREO	0x00000002
-struct leo_ld_ss1 {
-	u8	xxx0[0xef4];
-	u32	ss1_misc;
-};
-
-struct leo_ld_gbl {
-	u8	unknown;
-};
-
-struct leo_par {
-	spinlock_t		lock;
-	struct leo_lx_krn	__iomem *lx_krn;
-	struct leo_lc_ss0_usr	__iomem *lc_ss0_usr;
-	struct leo_ld_ss0	__iomem *ld_ss0;
-	struct leo_ld_ss1	__iomem *ld_ss1;
-	struct leo_cursor	__iomem *cursor;
-	u32			extent;
-	u32			clut_data[256];
-
-	u32			flags;
-#define LEO_FLAG_BLANKED	0x00000001
-
-	unsigned long		which_io;
-};
-
-static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
-{
-	int i;
-
-	for (i = 0;
-	     (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) &&
-	     i < 300000;
-	     i++)
-		udelay(1); /* Busy wait at most 0.3 sec */
-	return;
-}
-
-static void leo_switch_from_graph(struct fb_info *info)
-{
-	struct leo_par *par = (struct leo_par *) info->par;
-	struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
-	struct leo_cursor __iomem *cursor = par->cursor;
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	par->extent = ((info->var.xres - 1) |
-		       ((info->var.yres - 1) << 16));
-
-	sbus_writel(0xffffffff, &ss->wid);
-	sbus_writel(0xffff, &ss->wmask);
-	sbus_writel(0, &ss->vclipmin);
-	sbus_writel(par->extent, &ss->vclipmax);
-	sbus_writel(0, &ss->fg);
-	sbus_writel(0xff000000, &ss->planemask);
-	sbus_writel(0x310850, &ss->rop);
-	sbus_writel(0, &ss->widclip);
-	sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
-		    &par->lc_ss0_usr->extent);
-	sbus_writel(4, &par->lc_ss0_usr->addrspace);
-	sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
-	sbus_writel(0, &par->lc_ss0_usr->fontt);
-	do {
-		val = sbus_readl(&par->lc_ss0_usr->csr);
-	} while (val & 0x20000000);
-
-	/* setup screen buffer for cfb_* functions */
-	sbus_writel(1, &ss->wid);
-	sbus_writel(0x00ffffff, &ss->planemask);
-	sbus_writel(0x310b90, &ss->rop);
-	sbus_writel(0, &par->lc_ss0_usr->addrspace);
-
-	/* hide cursor */
-	sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	/* We just use this to catch switches out of
-	 * graphics mode.
-	 */
-	leo_switch_from_graph(info);
-
-	if (var->xoffset || var->yoffset || var->vmode)
-		return -EINVAL;
-	return 0;
-}
-
-/**
- *      leo_setcolreg - Optional function. Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *      @green: The green value which can be up to 16 bits wide
- *      @blue:  The blue value which can be up to 16 bits wide.
- *      @transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- */
-static int leo_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	struct leo_par *par = (struct leo_par *) info->par;
-	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
-	unsigned long flags;
-	u32 val;
-	int i;
-
-	if (regno >= 256)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	par->clut_data[regno] = red | (green << 8) | (blue << 16);
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	leo_wait(lx_krn);
-
-	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
-	for (i = 0; i < 256; i++)
-		sbus_writel(par->clut_data[i], &lx_krn->krn_value);
-	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
-
-	val = sbus_readl(&lx_krn->krn_csr);
-	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
-	sbus_writel(val, &lx_krn->krn_csr);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-/**
- *      leo_blank - Optional function.  Blanks the display.
- *      @blank_mode: the blank mode we want.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int leo_blank(int blank, struct fb_info *info)
-{
-	struct leo_par *par = (struct leo_par *) info->par;
-	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		val = sbus_readl(&lx_krn->krn_csr);
-		val |= LEO_KRN_CSR_ENABLE;
-		sbus_writel(val, &lx_krn->krn_csr);
-		par->flags &= ~LEO_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		val = sbus_readl(&lx_krn->krn_csr);
-		val &= ~LEO_KRN_CSR_ENABLE;
-		sbus_writel(val, &lx_krn->krn_csr);
-		par->flags |= LEO_FLAG_BLANKED;
-		break;
-	}
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static struct sbus_mmap_map leo_mmap_map[] = {
-	{
-		.voff	= LEO_SS0_MAP,
-		.poff	= LEO_OFF_SS0,
-		.size	= 0x800000
-	},
-	{
-		.voff	= LEO_LC_SS0_USR_MAP,
-		.poff	= LEO_OFF_LC_SS0_USR,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_LD_SS0_MAP,
-		.poff	= LEO_OFF_LD_SS0,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_LX_CURSOR_MAP,
-		.poff	= LEO_OFF_LX_CURSOR,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_SS1_MAP,
-		.poff	= LEO_OFF_SS1,
-		.size	= 0x800000
-	},
-	{
-		.voff	= LEO_LC_SS1_USR_MAP,
-		.poff	= LEO_OFF_LC_SS1_USR,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_LD_SS1_MAP,
-		.poff	= LEO_OFF_LD_SS1,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_UNK_MAP,
-		.poff	= LEO_OFF_UNK,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_LX_KRN_MAP,
-		.poff	= LEO_OFF_LX_KRN,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_LC_SS0_KRN_MAP,
-		.poff	= LEO_OFF_LC_SS0_KRN,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_LC_SS1_KRN_MAP,
-		.poff	= LEO_OFF_LC_SS1_KRN,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_LD_GBL_MAP,
-		.poff	= LEO_OFF_LD_GBL,
-		.size	= 0x1000
-	},
-	{
-		.voff	= LEO_UNK2_MAP,
-		.poff	= LEO_OFF_UNK2,
-		.size	= 0x100000
-	},
-	{ .size = 0 }
-};
-
-static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct leo_par *par = (struct leo_par *)info->par;
-
-	return sbusfb_mmap_helper(leo_mmap_map,
-				  info->fix.smem_start, info->fix.smem_len,
-				  par->which_io, vma);
-}
-
-static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	return sbusfb_ioctl_helper(cmd, arg, info,
-				   FBTYPE_SUNLEO, 32, info->fix.smem_len);
-}
-
-/*
- *  Initialisation
- */
-
-static void
-leo_init_fix(struct fb_info *info, struct device_node *dp)
-{
-	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	info->fix.line_length = 8192;
-
-	info->fix.accel = FB_ACCEL_SUN_LEO;
-}
-
-static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl)
-{
-	struct leo_par *par = (struct leo_par *) info->par;
-	struct leo_lx_krn __iomem *lx_krn = par->lx_krn;
-	struct fb_wid_item *wi;
-	unsigned long flags;
-	u32 val;
-	int i, j;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	leo_wait(lx_krn);
-
-	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
-		switch (wi->wi_type) {
-		case FB_WID_DBL_8:
-			j = (wi->wi_index & 0xf) + 0x40;
-			break;
-
-		case FB_WID_DBL_24:
-			j = wi->wi_index & 0x3f;
-			break;
-
-		default:
-			continue;
-		}
-		sbus_writel(0x5800 + j, &lx_krn->krn_type);
-		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
-	}
-	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
-
-	val = sbus_readl(&lx_krn->krn_csr);
-	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
-	sbus_writel(val, &lx_krn->krn_csr);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-static void leo_init_wids(struct fb_info *info)
-{
-	struct fb_wid_item wi;
-	struct fb_wid_list wl;
-
-	wl.wl_count = 1;
-	wl.wl_list = &wi;
-	wi.wi_type = FB_WID_DBL_8;
-	wi.wi_index = 0;
-	wi.wi_values [0] = 0x2c0;
-	leo_wid_put(info, &wl);
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put(info, &wl);
-	wi.wi_index = 2;
-	wi.wi_values [0] = 0x20;
-	leo_wid_put(info, &wl);
-	wi.wi_type = FB_WID_DBL_24;
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put(info, &wl);
-}
-
-static void leo_init_hw(struct fb_info *info)
-{
-	struct leo_par *par = (struct leo_par *) info->par;
-	u32 val;
-
-	val = sbus_readl(&par->ld_ss1->ss1_misc);
-	val |= LEO_SS1_MISC_ENABLE;
-	sbus_writel(val, &par->ld_ss1->ss1_misc);
-
-	leo_switch_from_graph(info);
-}
-
-static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
-{
-	var->red.offset = 0;
-	var->red.length = 8;
-	var->green.offset = 8;
-	var->green.length = 8;
-	var->blue.offset = 16;
-	var->blue.length = 8;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-}
-
-static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
-			   struct leo_par *par)
-{
-	if (par->lc_ss0_usr)
-		of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000);
-	if (par->ld_ss0)
-		of_iounmap(&op->resource[0], par->ld_ss0, 0x1000);
-	if (par->ld_ss1)
-		of_iounmap(&op->resource[0], par->ld_ss1, 0x1000);
-	if (par->lx_krn)
-		of_iounmap(&op->resource[0], par->lx_krn, 0x1000);
-	if (par->cursor)
-		of_iounmap(&op->resource[0],
-			   par->cursor, sizeof(struct leo_cursor));
-	if (info->screen_base)
-		of_iounmap(&op->resource[0], info->screen_base, 0x800000);
-}
-
-static int leo_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct leo_par *par;
-	int linebytes, err;
-
-	info = framebuffer_alloc(sizeof(struct leo_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-
-	info->fix.smem_start = op->resource[0].start;
-	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
-
-	sbusfb_fill_var(&info->var, dp, 32);
-	leo_fixup_var_rgb(&info->var);
-
-	linebytes = of_getintprop_default(dp, "linebytes",
-					  info->var.xres);
-	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
-
-	par->lc_ss0_usr =
-		of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
-			   0x1000, "leolc ss0usr");
-	par->ld_ss0 =
-		of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
-			   0x1000, "leold ss0");
-	par->ld_ss1 =
-		of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
-			   0x1000, "leold ss1");
-	par->lx_krn =
-		of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
-			   0x1000, "leolx krn");
-	par->cursor =
-		of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
-			   sizeof(struct leo_cursor), "leolx cursor");
-	info->screen_base =
-		of_ioremap(&op->resource[0], LEO_OFF_SS0,
-			   0x800000, "leo ram");
-	if (!par->lc_ss0_usr ||
-	    !par->ld_ss0 ||
-	    !par->ld_ss1 ||
-	    !par->lx_krn ||
-	    !par->cursor ||
-	    !info->screen_base)
-		goto out_unmap_regs;
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &leo_ops;
-	info->pseudo_palette = par->clut_data;
-
-	leo_init_wids(info);
-	leo_init_hw(info);
-
-	leo_blank(FB_BLANK_UNBLANK, info);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0))
-		goto out_unmap_regs;
-
-	leo_init_fix(info, dp);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_dealloc_cmap;
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: leo at %lx:%lx\n",
-	       dp->full_name,
-	       par->which_io, info->fix.smem_start);
-
-	return 0;
-
-out_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-out_unmap_regs:
-	leo_unmap_regs(op, info, par);
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int leo_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct leo_par *par = info->par;
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	leo_unmap_regs(op, info, par);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id leo_match[] = {
-	{
-		.name = "SUNW,leo",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, leo_match);
-
-static struct platform_driver leo_driver = {
-	.driver = {
-		.name = "leo",
-		.owner = THIS_MODULE,
-		.of_match_table = leo_match,
-	},
-	.probe		= leo_probe,
-	.remove		= leo_remove,
-};
-
-static int __init leo_init(void)
-{
-	if (fb_get_options("leofb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&leo_driver);
-}
-
-static void __exit leo_exit(void)
-{
-	platform_driver_unregister(&leo_driver);
-}
-
-module_init(leo_init);
-module_exit(leo_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
deleted file mode 100644
index cda7587cbc86..000000000000
--- a/drivers/video/macfb.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * macfb.c: Generic framebuffer for Macs whose colourmaps/modes we
- * don't know how to set.
- *
- * (c) 1999 David Huggins-Daines <dhd@debian.org>
- *
- * Primarily based on vesafb.c, by Gerd Knorr
- * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- *
- * Also uses information and code from:
- *
- * The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen
- * Mellinger, Mikael Forselius, Michael Schmitz, and others.
- *
- * valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan
- * Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven.
- *
- * The VideoToolbox "Bugs" web page at
- * http://rajsky.psych.nyu.edu/Tips/VideoBugs.html
- *
- * This code is free software.  You may copy, modify, and distribute
- * it subject to the terms and conditions of the GNU General Public
- * License, version 2, or any later version, at your convenience.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/nubus.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-
-#include <asm/setup.h>
-#include <asm/macintosh.h>
-#include <asm/io.h>
-
-/* Common DAC base address for the LC, RBV, Valkyrie, and IIvx */
-#define DAC_BASE 0x50f24000
-
-/* Some addresses for the DAFB */
-#define DAFB_BASE 0xf9800200
-
-/* Address for the built-in Civic framebuffer in Quadra AVs */
-#define CIVIC_BASE 0x50f30800
-
-/* GSC (Gray Scale Controller) base address */
-#define GSC_BASE 0x50F20000
-
-/* CSC (Color Screen Controller) base address */
-#define CSC_BASE 0x50F20000
-
-static int (*macfb_setpalette)(unsigned int regno, unsigned int red,
-			       unsigned int green, unsigned int blue,
-			       struct fb_info *info);
-
-static struct {
-	unsigned char addr;
-	unsigned char lut;
-} __iomem *v8_brazil_cmap_regs;
-
-static struct {
-	unsigned char addr;
-	char pad1[3]; /* word aligned */
-	unsigned char lut;
-	char pad2[3]; /* word aligned */
-	unsigned char cntl; /* a guess as to purpose */
-} __iomem *rbv_cmap_regs;
-
-static struct {
-	unsigned long reset;
-	unsigned long pad1[3];
-	unsigned char pad2[3];
-	unsigned char lut;
-} __iomem *dafb_cmap_regs;
-
-static struct {
-	unsigned char addr;	/* OFFSET: 0x00 */
-	unsigned char pad1[15];
-	unsigned char lut;	/* OFFSET: 0x10 */
-	unsigned char pad2[15];
-	unsigned char status;	/* OFFSET: 0x20 */
-	unsigned char pad3[7];
-	unsigned long vbl_addr;	/* OFFSET: 0x28 */
-	unsigned int  status2;	/* OFFSET: 0x2C */
-} __iomem *civic_cmap_regs;
-
-static struct {
-	char pad1[0x40];
-	unsigned char clut_waddr;	/* 0x40 */
-	char pad2;
-	unsigned char clut_data;	/* 0x42 */
-	char pad3[0x3];
-	unsigned char clut_raddr;	/* 0x46 */
-} __iomem *csc_cmap_regs;
-
-/* The registers in these structs are in NuBus slot space */
-struct mdc_cmap_regs {
-	char pad1[0x200200];
-	unsigned char addr;
-	char pad2[6];
-	unsigned char lut;
-};
-
-struct toby_cmap_regs {
-	char pad1[0x90018];
-	unsigned char lut; /* TFBClutWDataReg, offset 0x90018 */
-	char pad2[3];
-	unsigned char addr; /* TFBClutAddrReg, offset 0x9001C */
-};
-
-struct jet_cmap_regs {
-	char pad1[0xe0e000];
-	unsigned char addr;
-	unsigned char lut;
-};
-
-#define PIXEL_TO_MM(a)	(((a)*10)/28)	/* width in mm at 72 dpi */
-
-static struct fb_var_screeninfo macfb_defined = {
-	.bits_per_pixel	= 8,
-	.activate	= FB_ACTIVATE_NOW,
-	.width		= -1,
-	.height		= -1,
-	.right_margin	= 32,
-	.upper_margin	= 16,
-	.lower_margin	= 4,
-	.vsync_len	= 4,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo macfb_fix = {
-	.type	= FB_TYPE_PACKED_PIXELS,
-	.accel	= FB_ACCEL_NONE,
-};
-
-static void *slot_addr;
-static struct fb_info fb_info;
-static u32 pseudo_palette[16];
-static int inverse;
-static int vidtest;
-
-/*
- * Unlike the Valkyrie, the DAFB cannot set individual colormap
- * registers.  Therefore, we do what the MacOS driver does (no
- * kidding!) and simply set them one by one until we hit the one we
- * want.
- */
-static int dafb_setpalette(unsigned int regno, unsigned int red,
-			   unsigned int green, unsigned int blue,
-			   struct fb_info *info)
-{
-	static int lastreg = -1;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	/*
-	 * fbdev will set an entire colourmap, but X won't.  Hopefully
-	 * this should accommodate both of them
-	 */
-	if (regno != lastreg + 1) {
-		int i;
-
-		/* Stab in the dark trying to reset the CLUT pointer */
-		nubus_writel(0, &dafb_cmap_regs->reset);
-		nop();
-
-		/* Loop until we get to the register we want */
-		for (i = 0; i < regno; i++) {
-			nubus_writeb(info->cmap.red[i] >> 8,
-				     &dafb_cmap_regs->lut);
-			nop();
-			nubus_writeb(info->cmap.green[i] >> 8,
-				     &dafb_cmap_regs->lut);
-			nop();
-			nubus_writeb(info->cmap.blue[i] >> 8,
-				     &dafb_cmap_regs->lut);
-			nop();
-		}
-	}
-
-	nubus_writeb(red, &dafb_cmap_regs->lut);
-	nop();
-	nubus_writeb(green, &dafb_cmap_regs->lut);
-	nop();
-	nubus_writeb(blue, &dafb_cmap_regs->lut);
-
-	local_irq_restore(flags);
-	lastreg = regno;
-	return 0;
-}
-
-/* V8 and Brazil seem to use the same DAC.  Sonora does as well. */
-static int v8_brazil_setpalette(unsigned int regno, unsigned int red,
-				unsigned int green, unsigned int blue,
-				struct fb_info *info)
-{
-	unsigned int bpp = info->var.bits_per_pixel;
-	unsigned long flags;
-
-	if (bpp > 8)
-		return 1; /* failsafe */
-
-	local_irq_save(flags);
-
-	/* On these chips, the CLUT register numbers are spread out
-	 * across the register space.  Thus:
-	 * In 8bpp, all regnos are valid.
-	 * In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc
-	 * In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff
-	 */
-	regno = (regno << (8 - bpp)) | (0xFF >> bpp);
-	nubus_writeb(regno, &v8_brazil_cmap_regs->addr);
-	nop();
-
-	/* send one color channel at a time */
-	nubus_writeb(red, &v8_brazil_cmap_regs->lut);
-	nop();
-	nubus_writeb(green, &v8_brazil_cmap_regs->lut);
-	nop();
-	nubus_writeb(blue, &v8_brazil_cmap_regs->lut);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-/* RAM-Based Video */
-static int rbv_setpalette(unsigned int regno, unsigned int red,
-			  unsigned int green, unsigned int blue,
-			  struct fb_info *info)
-{
-	unsigned long flags;
-
-	if (info->var.bits_per_pixel > 8)
-		return 1; /* failsafe */
-
-	local_irq_save(flags);
-
-	/* From the VideoToolbox driver.  Seems to be saying that
-	 * regno #254 and #255 are the important ones for 1-bit color,
-	 * regno #252-255 are the important ones for 2-bit color, etc.
-	 */
-	regno += 256 - (1 << info->var.bits_per_pixel);
-
-	/* reset clut? (VideoToolbox sez "not necessary") */
-	nubus_writeb(0xFF, &rbv_cmap_regs->cntl);
-	nop();
-
-	/* tell clut which address to use. */
-	nubus_writeb(regno, &rbv_cmap_regs->addr);
-	nop();
-
-	/* send one color channel at a time. */
-	nubus_writeb(red, &rbv_cmap_regs->lut);
-	nop();
-	nubus_writeb(green, &rbv_cmap_regs->lut);
-	nop();
-	nubus_writeb(blue, &rbv_cmap_regs->lut);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-/* Macintosh Display Card (8*24) */
-static int mdc_setpalette(unsigned int regno, unsigned int red,
-			  unsigned int green, unsigned int blue,
-			  struct fb_info *info)
-{
-	struct mdc_cmap_regs *cmap_regs = slot_addr;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	/* the nop's are there to order writes. */
-	nubus_writeb(regno, &cmap_regs->addr);
-	nop();
-	nubus_writeb(red, &cmap_regs->lut);
-	nop();
-	nubus_writeb(green, &cmap_regs->lut);
-	nop();
-	nubus_writeb(blue, &cmap_regs->lut);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-/* Toby frame buffer */
-static int toby_setpalette(unsigned int regno, unsigned int red,
-			   unsigned int green, unsigned int blue,
-			   struct fb_info *info)
-{
-	struct toby_cmap_regs *cmap_regs = slot_addr;
-	unsigned int bpp = info->var.bits_per_pixel;
-	unsigned long flags;
-
-	red = ~red;
-	green = ~green;
-	blue = ~blue;
-	regno = (regno << (8 - bpp)) | (0xFF >> bpp);
-
-	local_irq_save(flags);
-
-	nubus_writeb(regno, &cmap_regs->addr);
-	nop();
-	nubus_writeb(red, &cmap_regs->lut);
-	nop();
-	nubus_writeb(green, &cmap_regs->lut);
-	nop();
-	nubus_writeb(blue, &cmap_regs->lut);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-/* Jet frame buffer */
-static int jet_setpalette(unsigned int regno, unsigned int red,
-			  unsigned int green, unsigned int blue,
-			  struct fb_info *info)
-{
-	struct jet_cmap_regs *cmap_regs = slot_addr;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	nubus_writeb(regno, &cmap_regs->addr);
-	nop();
-	nubus_writeb(red, &cmap_regs->lut);
-	nop();
-	nubus_writeb(green, &cmap_regs->lut);
-	nop();
-	nubus_writeb(blue, &cmap_regs->lut);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-/*
- * Civic framebuffer -- Quadra AV built-in video.  A chip
- * called Sebastian holds the actual color palettes, and
- * apparently, there are two different banks of 512K RAM
- * which can act as separate framebuffers for doing video
- * input and viewing the screen at the same time!  The 840AV
- * Can add another 1MB RAM to give the two framebuffers
- * 1MB RAM apiece.
- */
-static int civic_setpalette(unsigned int regno, unsigned int red,
-			    unsigned int green, unsigned int blue,
-			    struct fb_info *info)
-{
-	unsigned long flags;
-	int clut_status;
-	
-	if (info->var.bits_per_pixel > 8)
-		return 1; /* failsafe */
-
-	local_irq_save(flags);
-
-	/* Set the register address */
-	nubus_writeb(regno, &civic_cmap_regs->addr);
-	nop();
-
-	/*
-	 * Grab a status word and do some checking;
-	 * Then finally write the clut!
-	 */
-	clut_status =  nubus_readb(&civic_cmap_regs->status2);
-
-	if ((clut_status & 0x0008) == 0)
-	{
-#if 0
-		if ((clut_status & 0x000D) != 0)
-		{
-			nubus_writeb(0x00, &civic_cmap_regs->lut);
-			nop();
-			nubus_writeb(0x00, &civic_cmap_regs->lut);
-			nop();
-		}
-#endif
-
-		nubus_writeb(red, &civic_cmap_regs->lut);
-		nop();
-		nubus_writeb(green, &civic_cmap_regs->lut);
-		nop();
-		nubus_writeb(blue, &civic_cmap_regs->lut);
-		nop();
-		nubus_writeb(0x00, &civic_cmap_regs->lut);
-	}
-	else
-	{
-		unsigned char junk;
-
-		junk = nubus_readb(&civic_cmap_regs->lut);
-		nop();
-		junk = nubus_readb(&civic_cmap_regs->lut);
-		nop();
-		junk = nubus_readb(&civic_cmap_regs->lut);
-		nop();
-		junk = nubus_readb(&civic_cmap_regs->lut);
-		nop();
-
-		if ((clut_status & 0x000D) != 0)
-		{
-			nubus_writeb(0x00, &civic_cmap_regs->lut);
-			nop();
-			nubus_writeb(0x00, &civic_cmap_regs->lut);
-			nop();
-		}
-
-		nubus_writeb(red, &civic_cmap_regs->lut);
-		nop();
-		nubus_writeb(green, &civic_cmap_regs->lut);
-		nop();
-		nubus_writeb(blue, &civic_cmap_regs->lut);
-		nop();
-		nubus_writeb(junk, &civic_cmap_regs->lut);
-	}
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-/*
- * The CSC is the framebuffer on the PowerBook 190 series
- * (and the 5300 too, but that's a PowerMac). This function
- * brought to you in part by the ECSC driver for MkLinux.
- */
-static int csc_setpalette(unsigned int regno, unsigned int red,
-			  unsigned int green, unsigned int blue,
-			  struct fb_info *info)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	udelay(1); /* mklinux on PB 5300 waits for 260 ns */
-	nubus_writeb(regno, &csc_cmap_regs->clut_waddr);
-	nubus_writeb(red, &csc_cmap_regs->clut_data);
-	nubus_writeb(green, &csc_cmap_regs->clut_data);
-	nubus_writeb(blue, &csc_cmap_regs->clut_data);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *fb_info)
-{
-	/*
-	 * Set a single color register. The values supplied are
-	 * already rounded down to the hardware's capabilities
-	 * (according to the entries in the `var' structure).
-	 * Return non-zero for invalid regno.
-	 */
-	
-	if (regno >= fb_info->cmap.len)
-		return 1;
-
-	if (fb_info->var.bits_per_pixel <= 8) {
-		switch (fb_info->var.bits_per_pixel) {
-		case 1:
-			/* We shouldn't get here */
-			break;
-		case 2:
-		case 4:
-		case 8:
-			if (macfb_setpalette)
-				macfb_setpalette(regno, red >> 8, green >> 8,
-						 blue >> 8, fb_info);
-			else
-				return 1;
-			break;
-		}
-	} else if (regno < 16) {
-		switch (fb_info->var.bits_per_pixel) {
-		case 16:
-			if (fb_info->var.red.offset == 10) {
-				/* 1:5:5:5 */
-				((u32*) (fb_info->pseudo_palette))[regno] =
-					((red   & 0xf800) >>  1) |
-					((green & 0xf800) >>  6) |
-					((blue  & 0xf800) >> 11) |
-					((transp != 0) << 15);
-			} else {
-				/* 0:5:6:5 */
-				((u32*) (fb_info->pseudo_palette))[regno] =
-					((red   & 0xf800) >>  0) |
-					((green & 0xfc00) >>  5) |
-					((blue  & 0xf800) >> 11);
-			}
-			break;
-		/*
-		 * 24-bit colour almost doesn't exist on 68k Macs --
-		 * http://support.apple.com/kb/TA28634 (Old Article: 10992)
-		 */
-		case 24:
-		case 32:
-			red   >>= 8;
-			green >>= 8;
-			blue  >>= 8;
-			((u32 *)(fb_info->pseudo_palette))[regno] =
-				(red   << fb_info->var.red.offset) |
-				(green << fb_info->var.green.offset) |
-				(blue  << fb_info->var.blue.offset);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static struct fb_ops macfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= macfb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static void __init macfb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-
-		if (!strcmp(this_opt, "inverse"))
-			inverse = 1;
-		else
-			if (!strcmp(this_opt, "vidtest"))
-				vidtest = 1; /* enable experimental CLUT code */
-	}
-}
-
-static void __init iounmap_macfb(void)
-{
-	if (dafb_cmap_regs)
-		iounmap(dafb_cmap_regs);
-	if (v8_brazil_cmap_regs)
-		iounmap(v8_brazil_cmap_regs);
-	if (rbv_cmap_regs)
-		iounmap(rbv_cmap_regs);
-	if (civic_cmap_regs)
-		iounmap(civic_cmap_regs);
-	if (csc_cmap_regs)
-		iounmap(csc_cmap_regs);
-}
-
-static int __init macfb_init(void)
-{
-	int video_cmap_len, video_is_nubus = 0;
-	struct nubus_dev* ndev = NULL;
-	char *option = NULL;
-	int err;
-
-	if (fb_get_options("macfb", &option))
-		return -ENODEV;
-	macfb_setup(option);
-
-	if (!MACH_IS_MAC) 
-		return -ENODEV;
-
-	if (mac_bi_data.id == MAC_MODEL_Q630 ||
-	    mac_bi_data.id == MAC_MODEL_P588)
-		return -ENODEV; /* See valkyriefb.c */
-
-	macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF;
-	macfb_defined.yres = mac_bi_data.dimensions >> 16;
-	macfb_defined.bits_per_pixel = mac_bi_data.videodepth;
-
-	macfb_fix.line_length = mac_bi_data.videorow;
-	macfb_fix.smem_len    = macfb_fix.line_length * macfb_defined.yres;
-	/* Note: physical address (since 2.1.127) */
-	macfb_fix.smem_start  = mac_bi_data.videoaddr;
-
-	/*
-	 * This is actually redundant with the initial mappings.
-	 * However, there are some non-obvious aspects to the way
-	 * those mappings are set up, so this is in fact the safest
-	 * way to ensure that this driver will work on every possible Mac
-	 */
-	fb_info.screen_base = ioremap(mac_bi_data.videoaddr,
-				      macfb_fix.smem_len);
-	if (!fb_info.screen_base)
-		return -ENODEV;
-
-	pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
-	        macfb_fix.smem_start, fb_info.screen_base,
-	        macfb_fix.smem_len / 1024);
-	pr_info("macfb: mode is %dx%dx%d, linelength=%d\n",
-	        macfb_defined.xres, macfb_defined.yres,
-	        macfb_defined.bits_per_pixel, macfb_fix.line_length);
-
-	/* Fill in the available video resolution */
-	macfb_defined.xres_virtual = macfb_defined.xres;
-	macfb_defined.yres_virtual = macfb_defined.yres;
-	macfb_defined.height       = PIXEL_TO_MM(macfb_defined.yres);
-	macfb_defined.width        = PIXEL_TO_MM(macfb_defined.xres);
-
-	/* Some dummy values for timing to make fbset happy */
-	macfb_defined.pixclock     = 10000000 / macfb_defined.xres *
-				     1000 / macfb_defined.yres;
-	macfb_defined.left_margin  = (macfb_defined.xres / 8) & 0xf8;
-	macfb_defined.hsync_len    = (macfb_defined.xres / 8) & 0xf8;
-
-	switch (macfb_defined.bits_per_pixel) {
-	case 1:
-		macfb_defined.red.length = macfb_defined.bits_per_pixel;
-		macfb_defined.green.length = macfb_defined.bits_per_pixel;
-		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
-		video_cmap_len = 2;
-		macfb_fix.visual = FB_VISUAL_MONO01;
-		break;
-	case 2:
-	case 4:
-	case 8:
-		macfb_defined.red.length = macfb_defined.bits_per_pixel;
-		macfb_defined.green.length = macfb_defined.bits_per_pixel;
-		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
-		video_cmap_len = 1 << macfb_defined.bits_per_pixel;
-		macfb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 16:
-		macfb_defined.transp.offset = 15;
-		macfb_defined.transp.length = 1;
-		macfb_defined.red.offset = 10;
-		macfb_defined.red.length = 5;
-		macfb_defined.green.offset = 5;
-		macfb_defined.green.length = 5;
-		macfb_defined.blue.offset = 0;
-		macfb_defined.blue.length = 5;
-		video_cmap_len = 16;
-		/*
-		 * Should actually be FB_VISUAL_DIRECTCOLOR, but this
-		 * works too
-		 */
-		macfb_fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	case 24:
-	case 32:
-		macfb_defined.red.offset = 16;
-		macfb_defined.red.length = 8;
-		macfb_defined.green.offset = 8;
-		macfb_defined.green.length = 8;
-		macfb_defined.blue.offset = 0;
-		macfb_defined.blue.length = 8;
-		video_cmap_len = 16;
-		macfb_fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	default:
-		pr_err("macfb: unknown or unsupported bit depth: %d\n",
-		       macfb_defined.bits_per_pixel);
-		err = -EINVAL;
-		goto fail_unmap;
-	}
-	
-	/*
-	 * We take a wild guess that if the video physical address is
-	 * in nubus slot space, that the nubus card is driving video.
-	 * Penguin really ought to tell us whether we are using internal
-	 * video or not.
-	 * Hopefully we only find one of them.  Otherwise our NuBus
-	 * code is really broken :-)
-	 */
-
-	while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY,
-				       NUBUS_TYPE_VIDEO, ndev)))
-	{
-		unsigned long base = ndev->board->slot_addr;
-
-		if (mac_bi_data.videoaddr < base ||
-		    mac_bi_data.videoaddr - base > 0xFFFFFF)
-			continue;
-
-		video_is_nubus = 1;
-		slot_addr = (unsigned char *)base;
-
-		switch(ndev->dr_hw) {
-		case NUBUS_DRHW_APPLE_MDC:
-			strcpy(macfb_fix.id, "Mac Disp. Card");
-			macfb_setpalette = mdc_setpalette;
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-		case NUBUS_DRHW_APPLE_TFB:
-			strcpy(macfb_fix.id, "Toby");
-			macfb_setpalette = toby_setpalette;
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-		case NUBUS_DRHW_APPLE_JET:
-			strcpy(macfb_fix.id, "Jet");
-			macfb_setpalette = jet_setpalette;
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-		default:
-			strcpy(macfb_fix.id, "Generic NuBus");
-			break;
-		}
-	}
-
-	/* If it's not a NuBus card, it must be internal video */
-	if (!video_is_nubus)
-		switch (mac_bi_data.id) {
-		/*
-		 * DAFB Quadras
-		 * Note: these first four have the v7 DAFB, which is
-		 * known to be rather unlike the ones used in the
-		 * other models
-		 */
-		case MAC_MODEL_P475:
-		case MAC_MODEL_P475F:
-		case MAC_MODEL_P575:
-		case MAC_MODEL_Q605:
-
-		case MAC_MODEL_Q800:
-		case MAC_MODEL_Q650:
-		case MAC_MODEL_Q610:
-		case MAC_MODEL_C650:
-		case MAC_MODEL_C610:
-		case MAC_MODEL_Q700:
-		case MAC_MODEL_Q900:
-		case MAC_MODEL_Q950:
-			strcpy(macfb_fix.id, "DAFB");
-			macfb_setpalette = dafb_setpalette;
-			dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-
-		/*
-		 * LC II uses the V8 framebuffer
-		 */
-		case MAC_MODEL_LCII:
-			strcpy(macfb_fix.id, "V8");
-			macfb_setpalette = v8_brazil_setpalette;
-			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-
-		/*
-		 * IIvi, IIvx use the "Brazil" framebuffer (which is
-		 * very much like the V8, it seems, and probably uses
-		 * the same DAC)
-		 */
-		case MAC_MODEL_IIVI:
-		case MAC_MODEL_IIVX:
-		case MAC_MODEL_P600:
-			strcpy(macfb_fix.id, "Brazil");
-			macfb_setpalette = v8_brazil_setpalette;
-			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-
-		/*
-		 * LC III (and friends) use the Sonora framebuffer
-		 * Incidentally this is also used in the non-AV models
-		 * of the x100 PowerMacs
-		 * These do in fact seem to use the same DAC interface
-		 * as the LC II.
-		 */
-		case MAC_MODEL_LCIII:
-		case MAC_MODEL_P520:
-		case MAC_MODEL_P550:
-		case MAC_MODEL_P460:
-			strcpy(macfb_fix.id, "Sonora");
-			macfb_setpalette = v8_brazil_setpalette;
-			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-
-		/*
-		 * IIci and IIsi use the infamous RBV chip
-		 * (the IIsi is just a rebadged and crippled
-		 * IIci in a different case, BTW)
-		 */
-		case MAC_MODEL_IICI:
-		case MAC_MODEL_IISI:
-			strcpy(macfb_fix.id, "RBV");
-			macfb_setpalette = rbv_setpalette;
-			rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-
-		/*
-		 * AVs use the Civic framebuffer
-		 */
-		case MAC_MODEL_Q840:
-		case MAC_MODEL_C660:
-			strcpy(macfb_fix.id, "Civic");
-			macfb_setpalette = civic_setpalette;
-			civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-
-		
-		/*
-		 * Assorted weirdos
-		 * We think this may be like the LC II
-		 */
-		case MAC_MODEL_LC:
-			strcpy(macfb_fix.id, "LC");
-			if (vidtest) {
-				macfb_setpalette = v8_brazil_setpalette;
-				v8_brazil_cmap_regs =
-					ioremap(DAC_BASE, 0x1000);
-				macfb_defined.activate = FB_ACTIVATE_NOW;
-			}
-			break;
-
-		/*
-		 * We think this may be like the LC II
-		 */
-		case MAC_MODEL_CCL:
-			strcpy(macfb_fix.id, "Color Classic");
-			if (vidtest) {
-				macfb_setpalette = v8_brazil_setpalette;
-				v8_brazil_cmap_regs =
-					ioremap(DAC_BASE, 0x1000);
-				macfb_defined.activate = FB_ACTIVATE_NOW;
-			}
-			break;
-
-		/*
-		 * And we *do* mean "weirdos"
-		 */
-		case MAC_MODEL_TV:
-			strcpy(macfb_fix.id, "Mac TV");
-			break;
-
-		/*
-		 * These don't have colour, so no need to worry
-		 */
-		case MAC_MODEL_SE30:
-		case MAC_MODEL_CLII:
-			strcpy(macfb_fix.id, "Monochrome");
-			break;
-
-		/*
-		 * Powerbooks are particularly difficult.  Many of
-		 * them have separate framebuffers for external and
-		 * internal video, which is admittedly pretty cool,
-		 * but will be a bit of a headache to support here.
-		 * Also, many of them are grayscale, and we don't
-		 * really support that.
-		 */
-
-		/*
-		 * Slot 0 ROM says TIM. No external video. B&W.
-		 */
-		case MAC_MODEL_PB140:
-		case MAC_MODEL_PB145:
-		case MAC_MODEL_PB170:
-			strcpy(macfb_fix.id, "DDC");
-			break;
-
-		/*
-		 * Internal is GSC, External (if present) is ViSC
-		 */
-		case MAC_MODEL_PB150:	/* no external video */
-		case MAC_MODEL_PB160:
-		case MAC_MODEL_PB165:
-		case MAC_MODEL_PB180:
-		case MAC_MODEL_PB210:
-		case MAC_MODEL_PB230:
-			strcpy(macfb_fix.id, "GSC");
-			break;
-
-		/*
-		 * Internal is TIM, External is ViSC
-		 */
-		case MAC_MODEL_PB165C:
-		case MAC_MODEL_PB180C:
-			strcpy(macfb_fix.id, "TIM");
-			break;
-
-		/*
-		 * Internal is CSC, External is Keystone+Ariel.
-		 */
-		case MAC_MODEL_PB190:	/* external video is optional */
-		case MAC_MODEL_PB520:
-		case MAC_MODEL_PB250:
-		case MAC_MODEL_PB270C:
-		case MAC_MODEL_PB280:
-		case MAC_MODEL_PB280C:
-			strcpy(macfb_fix.id, "CSC");
-			macfb_setpalette = csc_setpalette;
-			csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
-			macfb_defined.activate = FB_ACTIVATE_NOW;
-			break;
-
-		default:
-			strcpy(macfb_fix.id, "Unknown");
-			break;
-		}
-
-	fb_info.fbops		= &macfb_ops;
-	fb_info.var		= macfb_defined;
-	fb_info.fix		= macfb_fix;
-	fb_info.pseudo_palette	= pseudo_palette;
-	fb_info.flags		= FBINFO_DEFAULT;
-
-	err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
-	if (err)
-		goto fail_unmap;
-
-	err = register_framebuffer(&fb_info);
-	if (err)
-		goto fail_dealloc;
-
-	fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
-
-	return 0;
-
-fail_dealloc:
-	fb_dealloc_cmap(&fb_info.cmap);
-fail_unmap:
-	iounmap(fb_info.screen_base);
-	iounmap_macfb();
-	return err;
-}
-
-module_init(macfb_init);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
deleted file mode 100644
index af86c081d2be..000000000000
--- a/drivers/video/macmodes.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- *  linux/drivers/video/macmodes.c -- Standard MacOS video modes
- *
- *	Copyright (C) 1998 Geert Uytterhoeven
- *
- *      2000 - Removal of OpenFirmware dependencies by:
- *      - Ani Joshi
- *      - Brad Douglas <brad@neruo.com>
- *
- *	2001 - Documented with DocBook
- *	- Brad Douglas <brad@neruo.com>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/string.h>
-#include <linux/module.h>
-
-#include "macmodes.h"
-
-    /*
-     *  MacOS video mode definitions
-     *
-     *  Order IS important! If you change these, don't forget to update
-     *  mac_modes[] below!
-     */
-
-#define DEFAULT_MODEDB_INDEX	0
-
-static const struct fb_videomode mac_modedb[] = {
-    {
-	/* 512x384, 60Hz, Non-Interlaced (15.67 MHz dot clock) */
-	"mac2", 60, 512, 384, 63828, 80, 16, 19, 1, 32, 3,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-	"mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */
-	"mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 640x870, 75Hz (portrait), Non-Interlaced (57.28 MHz dot clock) */
-	"mac7", 75, 640, 870, 17457, 80, 32, 42, 3, 80, 3,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
-	"mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */
-	"mac10", 60, 800, 600, 25000, 72, 56, 23, 1, 128, 4,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */
-	"mac11", 72, 800, 600, 20000, 48, 72, 23, 37, 120, 6,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */
-	"mac12", 75, 800, 600, 20203, 144, 32, 21, 1, 80, 3,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 832x624, 75Hz, Non-Interlaced (57.6 MHz dotclock) */
-	"mac13", 75, 832, 624, 17362, 208, 48, 39, 1, 64, 3,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */
-	"mac14", 60, 1024, 768, 15385, 144, 40, 29, 3, 136, 6,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */
-	"mac15", 72, 1024, 768, 13334, 128, 40, 29, 3, 136, 6,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
-	"mac16", 75, 1024, 768, 12699, 176, 16, 28, 1, 96, 3,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
-	"mac17", 75, 1024, 768, 12699, 160, 32, 28, 1, 96, 3,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */
-	"mac18", 75, 1152, 870, 10000, 128, 48, 39, 3, 128, 3,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */
-	"mac19", 75, 1280, 960, 7937, 224, 32, 36, 1, 144, 3,
-	0, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
-	"mac20", 75, 1280, 1024, 7408, 232, 64, 38, 1, 112, 3,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1152x768, 60 Hz, Titanium PowerBook */
-	"mac21", 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1600x1024, 60 Hz, Non-Interlaced (112.27 MHz dotclock) */
-	"mac22", 60, 1600, 1024, 8908, 88, 104, 1, 10, 16, 1,
-	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-    }
-
-#if 0
-    /* Anyone who has timings for these? */
-    {
-	/* VMODE_512_384_60I: 512x384, 60Hz, Interlaced (NTSC) */
-	"mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
-	sync, FB_VMODE_INTERLACED
-    }, {
-	/* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */
-	"mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
-	sync, FB_VMODE_INTERLACED
-    }, {
-	/* VMODE_640_480_60I: 640x480, 60Hz, Interlaced (NTSC) */
-	"mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
-	sync, FB_VMODE_INTERLACED
-    }, {
-	/* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */
-	"mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen,
-	sync, FB_VMODE_INTERLACED
-    },
-#endif
-};
-
-
-    /*
-     *  Mapping between MacOS video mode numbers and video mode definitions
-     *
-     *  These MUST be ordered in
-     *    - increasing resolution
-     *    - decreasing pixel clock period
-     */
-
-static const struct mode_map {
-    int vmode;
-    const struct fb_videomode *mode;
-} mac_modes[] = {
-    /* 512x384 */
-    { VMODE_512_384_60, &mac_modedb[0] },
-    /* 640x480 */
-    { VMODE_640_480_60, &mac_modedb[1] },
-    { VMODE_640_480_67, &mac_modedb[2] },
-    /* 640x870 */
-    { VMODE_640_870_75P, &mac_modedb[3] },
-    /* 800x600 */
-    { VMODE_800_600_56, &mac_modedb[4] },
-    { VMODE_800_600_60, &mac_modedb[5] },
-    { VMODE_800_600_75, &mac_modedb[7] },
-    { VMODE_800_600_72, &mac_modedb[6] },
-    /* 832x624 */
-    { VMODE_832_624_75, &mac_modedb[8] },
-    /* 1024x768 */
-    { VMODE_1024_768_60, &mac_modedb[9] },
-    { VMODE_1024_768_70, &mac_modedb[10] },
-    { VMODE_1024_768_75V, &mac_modedb[11] },
-    { VMODE_1024_768_75, &mac_modedb[12] },
-    /* 1152x768 */
-    { VMODE_1152_768_60, &mac_modedb[16] },
-    /* 1152x870 */
-    { VMODE_1152_870_75, &mac_modedb[13] },
-    /* 1280x960 */
-    { VMODE_1280_960_75, &mac_modedb[14] },
-    /* 1280x1024 */
-    { VMODE_1280_1024_75, &mac_modedb[15] },
-    /* 1600x1024 */
-    { VMODE_1600_1024_60, &mac_modedb[17] },
-    { -1, NULL }
-};
-
-
-    /*
-     *  Mapping between monitor sense values and MacOS video mode numbers
-     */
-
-static const struct monitor_map {
-    int sense;
-    int vmode;
-} mac_monitors[] = {
-    { 0x000, VMODE_1280_1024_75 },	/* 21" RGB */
-    { 0x114, VMODE_640_870_75P },	/* Portrait Monochrome */
-    { 0x221, VMODE_512_384_60 },	/* 12" RGB*/
-    { 0x331, VMODE_1280_1024_75 },	/* 21" RGB (Radius) */
-    { 0x334, VMODE_1280_1024_75 },	/* 21" mono (Radius) */
-    { 0x335, VMODE_1280_1024_75 },	/* 21" mono */
-    { 0x40A, VMODE_640_480_60I },	/* NTSC */
-    { 0x51E, VMODE_640_870_75P },	/* Portrait RGB */
-    { 0x603, VMODE_832_624_75 },	/* 12"-16" multiscan */
-    { 0x60b, VMODE_1024_768_70 },	/* 13"-19" multiscan */
-    { 0x623, VMODE_1152_870_75 },	/* 13"-21" multiscan */
-    { 0x62b, VMODE_640_480_67 },	/* 13"/14" RGB */
-    { 0x700, VMODE_640_480_50I },	/* PAL */
-    { 0x714, VMODE_640_480_60I },	/* NTSC */
-    { 0x717, VMODE_800_600_75 },	/* VGA */
-    { 0x72d, VMODE_832_624_75 },	/* 16" RGB (Goldfish) */
-    { 0x730, VMODE_768_576_50I },	/* PAL (Alternate) */
-    { 0x73a, VMODE_1152_870_75 },	/* 3rd party 19" */
-    { 0x73f, VMODE_640_480_67 },	/* no sense lines connected at all */
-    { 0xBEEF, VMODE_1600_1024_60 },	/* 22" Apple Cinema Display */
-    { -1,    VMODE_640_480_60 },	/* catch-all, must be last */
-};
-
-/**
- *	mac_vmode_to_var - converts vmode/cmode pair to var structure
- *	@vmode: MacOS video mode
- *	@cmode: MacOS color mode
- *	@var: frame buffer video mode structure
- *
- *	Converts a MacOS vmode/cmode pair to a frame buffer video
- *	mode structure.
- *
- *	Returns negative errno on error, or zero for success.
- *
- */
-
-int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
-{
-    const struct fb_videomode *mode = NULL;
-    const struct mode_map *map;
-
-    for (map = mac_modes; map->vmode != -1; map++)
-	if (map->vmode == vmode) {
-	    mode = map->mode;
-	    break;
-	}
-    if (!mode)
-	return -EINVAL;
-
-    memset(var, 0, sizeof(struct fb_var_screeninfo));
-    switch (cmode) {
-	case CMODE_8:
-	    var->bits_per_pixel = 8;
-	    var->red.offset = 0;
-	    var->red.length = 8;   
-	    var->green.offset = 0;
-	    var->green.length = 8;
-	    var->blue.offset = 0;
-	    var->blue.length = 8;
-	    break;
-
-	case CMODE_16:
-	    var->bits_per_pixel = 16;
-	    var->red.offset = 10;
-	    var->red.length = 5;
-	    var->green.offset = 5;
-	    var->green.length = 5;
-	    var->blue.offset = 0;
-	    var->blue.length = 5;
-	    break;
-
-	case CMODE_32:
-	    var->bits_per_pixel = 32;
-	    var->red.offset = 16;
-	    var->red.length = 8;
-	    var->green.offset = 8;
-	    var->green.length = 8;
-	    var->blue.offset = 0;
-	    var->blue.length = 8;
-	    var->transp.offset = 24;
-	    var->transp.length = 8;
-	    break;
-
-	default:
-	    return -EINVAL;
-    }
-    var->xres = mode->xres;
-    var->yres = mode->yres;
-    var->xres_virtual = mode->xres;
-    var->yres_virtual = mode->yres;
-    var->height = -1;
-    var->width = -1;
-    var->pixclock = mode->pixclock;
-    var->left_margin = mode->left_margin;
-    var->right_margin = mode->right_margin;
-    var->upper_margin = mode->upper_margin;
-    var->lower_margin = mode->lower_margin;
-    var->hsync_len = mode->hsync_len;
-    var->vsync_len = mode->vsync_len;
-    var->sync = mode->sync;
-    var->vmode = mode->vmode;
-    return 0;
-}
-EXPORT_SYMBOL(mac_vmode_to_var);
-
-/**
- *	mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair
- *	@var: frame buffer video mode structure
- *	@vmode: MacOS video mode
- *	@cmode: MacOS color mode
- *
- *	Converts a frame buffer video mode structure to a MacOS
- *	vmode/cmode pair.
- *
- *	Returns negative errno on error, or zero for success.
- *
- */
-
-int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
-		     int *cmode)
-{
-    const struct mode_map *map;
-
-    if (var->bits_per_pixel <= 8)
-	*cmode = CMODE_8;
-    else if (var->bits_per_pixel <= 16)
-	*cmode = CMODE_16;
-    else if (var->bits_per_pixel <= 32)
-	*cmode = CMODE_32;
-    else
-	return -EINVAL;
-
-    /*
-     * Find the mac_mode with a matching resolution or failing that, the
-     * closest larger resolution. Skip modes with a shorter pixel clock period.
-     */
-    for (map = mac_modes; map->vmode != -1; map++) {
-	const struct fb_videomode *mode = map->mode;
-
-	if (var->xres > mode->xres || var->yres > mode->yres)
-	    continue;
-	if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)
-	    continue;
-	if (var->pixclock > mode->pixclock)
-	    continue;
-	if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
-	    continue;
-	*vmode = map->vmode;
-
-	/*
-	 * Having found a good resolution, find the matching pixel clock
-	 * or failing that, the closest longer pixel clock period.
-	 */
-	map++;
-	while (map->vmode != -1) {
-	    const struct fb_videomode *clk_mode = map->mode;
-
-	    if (mode->xres != clk_mode->xres || mode->yres != clk_mode->yres)
-		break;
-	    if (var->pixclock > mode->pixclock)
-	        break;
-	    if (mode->vmode != clk_mode->vmode)
-		continue;
-	    *vmode = map->vmode;
-	    map++;
-	}
-	return 0;
-    }
-    return -EINVAL;
-}
-
-/**
- *	mac_map_monitor_sense - Convert monitor sense to vmode
- *	@sense: Macintosh monitor sense number
- *
- *	Converts a Macintosh monitor sense number to a MacOS
- *	vmode number.
- *
- *	Returns MacOS vmode video mode number.
- *
- */
-
-int mac_map_monitor_sense(int sense)
-{
-    const struct monitor_map *map;
-
-    for (map = mac_monitors; map->sense != -1; map++)
-	if (map->sense == sense)
-	    break;
-    return map->vmode;
-}
-EXPORT_SYMBOL(mac_map_monitor_sense);
-
-/**
- *	mac_find_mode - find a video mode
- *	@var: frame buffer user defined part of display
- *	@info: frame buffer info structure
- *	@mode_option: video mode name (see mac_modedb[])
- *	@default_bpp: default color depth in bits per pixel
- *
- *	Finds a suitable video mode.  Tries to set mode specified
- *	by @mode_option.  If the name of the wanted mode begins with
- *	'mac', the Mac video mode database will be used, otherwise it
- *	will fall back to the standard video mode database.
- *
- *	Note: Function marked as __init and can only be used during
- *	system boot.
- *
- *	Returns error code from fb_find_mode (see fb_find_mode
- *	function).
- *
- */
-
-int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
-		  const char *mode_option, unsigned int default_bpp)
-{
-    const struct fb_videomode *db = NULL;
-    unsigned int dbsize = 0;
-
-    if (mode_option && !strncmp(mode_option, "mac", 3)) {
-	mode_option += 3;
-	db = mac_modedb;
-	dbsize = ARRAY_SIZE(mac_modedb);
-    }
-    return fb_find_mode(var, info, mode_option, db, dbsize,
-			&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
-}
-EXPORT_SYMBOL(mac_find_mode);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h
deleted file mode 100644
index b86ba08aac9e..000000000000
--- a/drivers/video/macmodes.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  linux/drivers/video/macmodes.h -- Standard MacOS video modes
- *
- *	Copyright (C) 1998 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#ifndef _VIDEO_MACMODES_H
-#define _VIDEO_MACMODES_H
-
-    /*
-     *  Video mode values.
-     *  These are supposed to be the same as the values that Apple uses in
-     *  MacOS.
-     */
-
-#define VMODE_NVRAM		0
-#define VMODE_512_384_60I	1	/* 512x384, 60Hz interlaced (NTSC) */
-#define VMODE_512_384_60	2	/* 512x384, 60Hz */
-#define VMODE_640_480_50I	3	/* 640x480, 50Hz interlaced (PAL) */
-#define VMODE_640_480_60I	4	/* 640x480, 60Hz interlaced (NTSC) */
-#define VMODE_640_480_60	5	/* 640x480, 60Hz (VGA) */
-#define VMODE_640_480_67	6	/* 640x480, 67Hz */
-#define VMODE_640_870_75P	7	/* 640x870, 75Hz (portrait) */
-#define VMODE_768_576_50I	8	/* 768x576, 50Hz (PAL full frame) */
-#define VMODE_800_600_56	9	/* 800x600, 56Hz */
-#define VMODE_800_600_60	10	/* 800x600, 60Hz */
-#define VMODE_800_600_72	11	/* 800x600, 72Hz */
-#define VMODE_800_600_75	12	/* 800x600, 75Hz */
-#define VMODE_832_624_75	13	/* 832x624, 75Hz */
-#define VMODE_1024_768_60	14	/* 1024x768, 60Hz */
-#define VMODE_1024_768_70	15	/* 1024x768, 70Hz (or 72Hz?) */
-#define VMODE_1024_768_75V	16	/* 1024x768, 75Hz (VESA) */
-#define VMODE_1024_768_75	17	/* 1024x768, 75Hz */
-#define VMODE_1152_870_75	18	/* 1152x870, 75Hz */
-#define VMODE_1280_960_75	19	/* 1280x960, 75Hz */
-#define VMODE_1280_1024_75	20	/* 1280x1024, 75Hz */
-#define VMODE_1152_768_60	21	/* 1152x768, 60Hz     Titanium PowerBook */
-#define VMODE_1600_1024_60	22	/* 1600x1024, 60Hz 22" Cinema Display */
-#define VMODE_MAX		22
-#define VMODE_CHOOSE		99
-
-#define CMODE_NVRAM		-1
-#define CMODE_CHOOSE		-2
-#define CMODE_8			0	/* 8 bits/pixel */
-#define CMODE_16		1	/* 16 (actually 15) bits/pixel */
-#define CMODE_32		2	/* 32 (actually 24) bits/pixel */
-
-
-extern int mac_vmode_to_var(int vmode, int cmode,
-			    struct fb_var_screeninfo *var);
-extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
-			    int *cmode);
-extern int mac_map_monitor_sense(int sense);
-extern int mac_find_mode(struct fb_var_screeninfo *var,
-			 struct fb_info *info,
-			 const char *mode_option,
-			 unsigned int default_bpp);
-
-
-    /*
-     *  Addresses in NVRAM where video mode and pixel size are stored.
-     */
-
-#define NV_VMODE		0x140f
-#define NV_CMODE		0x1410
-
-#endif /* _VIDEO_MACMODES_H */
diff --git a/drivers/video/matrox/Makefile b/drivers/video/matrox/Makefile
deleted file mode 100644
index f9c00ebe2530..000000000000
--- a/drivers/video/matrox/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Makefile for the Linux video drivers.
-# 5 Aug 1999, James Simmons, <mailto:jsimmons@edgeglobal.com>
-# Rewritten to use lists instead of if-statements.
-
-# Each configuration option enables a list of files.
-
-my-obj-$(CONFIG_FB_MATROX_G)      += g450_pll.o matroxfb_g450.o matroxfb_crtc2.o
-
-obj-$(CONFIG_FB_MATROX)           += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o $(my-obj-y)
-obj-$(CONFIG_FB_MATROX_I2C)       += i2c-matroxfb.o
-obj-$(CONFIG_FB_MATROX_MAVEN)     += matroxfb_maven.o matroxfb_crtc2.o
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
deleted file mode 100644
index c15f8a57498e..000000000000
--- a/drivers/video/matrox/g450_pll.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox PCI cards - G450/G550 PLL control.
- *
- * (c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.64 2002/06/10
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- */
-
-#include "g450_pll.h"
-#include "matroxfb_DAC1064.h"
-
-static inline unsigned int g450_vco2f(unsigned char p, unsigned int fvco) {
-	return (p & 0x40) ? fvco : fvco >> ((p & 3) + 1);
-}
-
-static inline unsigned int g450_f2vco(unsigned char p, unsigned int fin) {
-	return (p & 0x40) ? fin : fin << ((p & 3) + 1);
-}
-
-static unsigned int g450_mnp2vco(const struct matrox_fb_info *minfo,
-				 unsigned int mnp)
-{
-	unsigned int m, n;
-
-	m = ((mnp >> 16) & 0x0FF) + 1;
-	n = ((mnp >>  7) & 0x1FE) + 4;
-	return (minfo->features.pll.ref_freq * n + (m >> 1)) / m;
-}
-
-unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp)
-{
-	return g450_vco2f(mnp, g450_mnp2vco(minfo, mnp));
-}
-
-static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) {
-	if (f2 < f1) {
-    		f2 = f1 - f2;
-	} else {
-		f2 = f2 - f1;
-	}
-	return f2;
-}
-
-#define NO_MORE_MNP	0x01FFFFFF
-#define G450_MNP_FREQBITS	(0xFFFFFF43)	/* do not mask high byte so we'll catch NO_MORE_MNP */
-
-static unsigned int g450_nextpll(const struct matrox_fb_info *minfo,
-				 const struct matrox_pll_limits *pi,
-				 unsigned int *fvco, unsigned int mnp)
-{
-	unsigned int m, n, p;
-	unsigned int tvco = *fvco;
-
-	m = (mnp >> 16) & 0xFF;
-	p = mnp & 0xFF;
-
-	do {
-		if (m == 0 || m == 0xFF) {
-			if (m == 0) {
-				if (p & 0x40) {
-					return NO_MORE_MNP;
-				}
-			        if (p & 3) {
-					p--;
-				} else {
-					p = 0x40;
-				}
-				tvco >>= 1;
-				if (tvco < pi->vcomin) {
-					return NO_MORE_MNP;
-				}
-				*fvco = tvco;
-			}
-
-			p &= 0x43;
-			if (tvco < 550000) {
-/*				p |= 0x00; */
-			} else if (tvco < 700000) {
-				p |= 0x08;
-			} else if (tvco < 1000000) {
-				p |= 0x10;
-			} else if (tvco < 1150000) {
-				p |= 0x18;
-			} else {
-				p |= 0x20;
-			}
-			m = 9;
-		} else {
-			m--;
-		}
-		n = ((tvco * (m+1) + minfo->features.pll.ref_freq) / (minfo->features.pll.ref_freq * 2)) - 2;
-	} while (n < 0x03 || n > 0x7A);
-	return (m << 16) | (n << 8) | p;
-}
-
-static unsigned int g450_firstpll(const struct matrox_fb_info *minfo,
-				  const struct matrox_pll_limits *pi,
-				  unsigned int *vco, unsigned int fout)
-{
-	unsigned int p;
-	unsigned int vcomax;
-
-	vcomax = pi->vcomax;
-	if (fout > (vcomax / 2)) {
-		if (fout > vcomax) {
-			*vco = vcomax;
-		} else {
-			*vco = fout;
-		}
-		p = 0x40;
-	} else {
-		unsigned int tvco;
-
-		p = 3;
-		tvco = g450_f2vco(p, fout);
-		while (p && (tvco > vcomax)) {
-			p--;
-			tvco >>= 1;
-		}
-		if (tvco < pi->vcomin) {
-			tvco = pi->vcomin;
-		}
-		*vco = tvco;
-	}
-	return g450_nextpll(minfo, pi, vco, 0xFF0000 | p);
-}
-
-static inline unsigned int g450_setpll(const struct matrox_fb_info *minfo,
-				       unsigned int mnp, unsigned int pll)
-{
-	switch (pll) {
-		case M_PIXEL_PLL_A:
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLAM, mnp >> 16);
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLAN, mnp >> 8);
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLAP, mnp);
-			return M1064_XPIXPLLSTAT;
-
-		case M_PIXEL_PLL_B:
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLBM, mnp >> 16);
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLBN, mnp >> 8);
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLBP, mnp);
-			return M1064_XPIXPLLSTAT;
-
-		case M_PIXEL_PLL_C:
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLCM, mnp >> 16);
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLCN, mnp >> 8);
-			matroxfb_DAC_out(minfo, M1064_XPIXPLLCP, mnp);
-			return M1064_XPIXPLLSTAT;
-
-		case M_SYSTEM_PLL:
-			matroxfb_DAC_out(minfo, DAC1064_XSYSPLLM, mnp >> 16);
-			matroxfb_DAC_out(minfo, DAC1064_XSYSPLLN, mnp >> 8);
-			matroxfb_DAC_out(minfo, DAC1064_XSYSPLLP, mnp);
-			return DAC1064_XSYSPLLSTAT;
-
-		case M_VIDEO_PLL:
-			matroxfb_DAC_out(minfo, M1064_XVIDPLLM, mnp >> 16);
-			matroxfb_DAC_out(minfo, M1064_XVIDPLLN, mnp >> 8);
-			matroxfb_DAC_out(minfo, M1064_XVIDPLLP, mnp);
-			return M1064_XVIDPLLSTAT;
-	}
-	return 0;
-}
-
-static inline unsigned int g450_cmppll(const struct matrox_fb_info *minfo,
-				       unsigned int mnp, unsigned int pll)
-{
-	unsigned char m = mnp >> 16;
-	unsigned char n = mnp >> 8;
-	unsigned char p = mnp;
-
-	switch (pll) {
-		case M_PIXEL_PLL_A:
-			return (matroxfb_DAC_in(minfo, M1064_XPIXPLLAM) != m ||
-				matroxfb_DAC_in(minfo, M1064_XPIXPLLAN) != n ||
-				matroxfb_DAC_in(minfo, M1064_XPIXPLLAP) != p);
-
-		case M_PIXEL_PLL_B:
-			return (matroxfb_DAC_in(minfo, M1064_XPIXPLLBM) != m ||
-				matroxfb_DAC_in(minfo, M1064_XPIXPLLBN) != n ||
-				matroxfb_DAC_in(minfo, M1064_XPIXPLLBP) != p);
-
-		case M_PIXEL_PLL_C:
-			return (matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) != m ||
-				matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) != n ||
-				matroxfb_DAC_in(minfo, M1064_XPIXPLLCP) != p);
-
-		case M_SYSTEM_PLL:
-			return (matroxfb_DAC_in(minfo, DAC1064_XSYSPLLM) != m ||
-				matroxfb_DAC_in(minfo, DAC1064_XSYSPLLN) != n ||
-				matroxfb_DAC_in(minfo, DAC1064_XSYSPLLP) != p);
-
-		case M_VIDEO_PLL:
-			return (matroxfb_DAC_in(minfo, M1064_XVIDPLLM) != m ||
-				matroxfb_DAC_in(minfo, M1064_XVIDPLLN) != n ||
-				matroxfb_DAC_in(minfo, M1064_XVIDPLLP) != p);
-	}
-	return 1;
-}
-
-static inline int g450_isplllocked(const struct matrox_fb_info *minfo,
-				   unsigned int regidx)
-{
-	unsigned int j;
-
-	for (j = 0; j < 1000; j++) {
-		if (matroxfb_DAC_in(minfo, regidx) & 0x40) {
-			unsigned int r = 0;
-			int i;
-
-			for (i = 0; i < 100; i++) {
-				r += matroxfb_DAC_in(minfo, regidx) & 0x40;
-			}
-			return r >= (90 * 0x40);
-		}
-		/* udelay(1)... but DAC_in is much slower... */
-	}
-	return 0;
-}
-
-static int g450_testpll(const struct matrox_fb_info *minfo, unsigned int mnp,
-			unsigned int pll)
-{
-	return g450_isplllocked(minfo, g450_setpll(minfo, mnp, pll));
-}
-
-static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) {
-	switch (pll) {
-		case M_SYSTEM_PLL:
-			hw->DACclk[3] = mnp >> 16;
-			hw->DACclk[4] = mnp >> 8;
-			hw->DACclk[5] = mnp;
-			break;
-	}
-}
-
-void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
-			       unsigned int pll)
-{
-	if (g450_cmppll(minfo, mnp, pll)) {
-		g450_setpll(minfo, mnp, pll);
-	}
-}
-
-static inline unsigned int g450_findworkingpll(struct matrox_fb_info *minfo,
-					       unsigned int pll,
-					       unsigned int *mnparray,
-					       unsigned int mnpcount)
-{
-	unsigned int found = 0;
-	unsigned int idx;
-	unsigned int mnpfound = mnparray[0];
-		
-	for (idx = 0; idx < mnpcount; idx++) {
-		unsigned int sarray[3];
-		unsigned int *sptr;
-		{
-			unsigned int mnp;
-		
-			sptr = sarray;
-			mnp = mnparray[idx];
-			if (mnp & 0x38) {
-				*sptr++ = mnp - 8;
-			}
-			if ((mnp & 0x38) != 0x38) {
-				*sptr++ = mnp + 8;
-			}
-			*sptr = mnp;
-		}
-		while (sptr >= sarray) {
-			unsigned int mnp = *sptr--;
-		
-			if (g450_testpll(minfo, mnp - 0x0300, pll) &&
-			    g450_testpll(minfo, mnp + 0x0300, pll) &&
-			    g450_testpll(minfo, mnp - 0x0200, pll) &&
-			    g450_testpll(minfo, mnp + 0x0200, pll) &&
-			    g450_testpll(minfo, mnp - 0x0100, pll) &&
-			    g450_testpll(minfo, mnp + 0x0100, pll)) {
-				if (g450_testpll(minfo, mnp, pll)) {
-					return mnp;
-				}
-			} else if (!found && g450_testpll(minfo, mnp, pll)) {
-				mnpfound = mnp;
-				found = 1;
-			}
-		}
-	}
-	g450_setpll(minfo, mnpfound, pll);
-	return mnpfound;
-}
-
-static void g450_addcache(struct matrox_pll_cache* ci, unsigned int mnp_key, unsigned int mnp_value) {
-	if (++ci->valid > ARRAY_SIZE(ci->data)) {
-		ci->valid = ARRAY_SIZE(ci->data);
-	}
-	memmove(ci->data + 1, ci->data, (ci->valid - 1) * sizeof(*ci->data));
-	ci->data[0].mnp_key = mnp_key & G450_MNP_FREQBITS;
-	ci->data[0].mnp_value = mnp_value;
-}
-
-static int g450_checkcache(struct matrox_fb_info *minfo,
-			   struct matrox_pll_cache *ci, unsigned int mnp_key)
-{
-	unsigned int i;
-	
-	mnp_key &= G450_MNP_FREQBITS;
-	for (i = 0; i < ci->valid; i++) {
-		if (ci->data[i].mnp_key == mnp_key) {
-			unsigned int mnp;
-			
-			mnp = ci->data[i].mnp_value;
-			if (i) {
-				memmove(ci->data + 1, ci->data, i * sizeof(*ci->data));
-				ci->data[0].mnp_key = mnp_key;
-				ci->data[0].mnp_value = mnp;
-			}
-			return mnp;
-		}
-	}
-	return NO_MORE_MNP;
-}
-
-static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
-			 unsigned int pll, unsigned int *mnparray,
-			 unsigned int *deltaarray)
-{
-	unsigned int mnpcount;
-	unsigned int pixel_vco;
-	const struct matrox_pll_limits* pi;
-	struct matrox_pll_cache* ci;
-
-	pixel_vco = 0;
-	switch (pll) {
-		case M_PIXEL_PLL_A:
-		case M_PIXEL_PLL_B:
-		case M_PIXEL_PLL_C:
-			{
-				u_int8_t tmp, xpwrctrl;
-				unsigned long flags;
-				
-				matroxfb_DAC_lock_irqsave(flags);
-
-				xpwrctrl = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
-				matroxfb_DAC_out(minfo, M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN);
-				mga_outb(M_SEQ_INDEX, M_SEQ1);
-				mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF);
-				tmp = matroxfb_DAC_in(minfo, M1064_XPIXCLKCTRL);
-				tmp |= M1064_XPIXCLKCTRL_DIS;
-				if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) {
-					tmp |= M1064_XPIXCLKCTRL_PLL_UP;
-				}
-				matroxfb_DAC_out(minfo, M1064_XPIXCLKCTRL, tmp);
-				/* DVI PLL preferred for frequencies up to
-				   panel link max, standard PLL otherwise */
-				if (fout >= minfo->max_pixel_clock_panellink)
-					tmp = 0;
-				else tmp =
-					M1064_XDVICLKCTRL_DVIDATAPATHSEL |
-					M1064_XDVICLKCTRL_C1DVICLKSEL |
-					M1064_XDVICLKCTRL_C1DVICLKEN |
-					M1064_XDVICLKCTRL_DVILOOPCTL |
-					M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
-                                /* Setting this breaks PC systems so don't do it */
-				/* matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); */
-				matroxfb_DAC_out(minfo, M1064_XPWRCTRL,
-						 xpwrctrl);
-
-				matroxfb_DAC_unlock_irqrestore(flags);
-			}
-			{
-				u_int8_t misc;
-		
-				misc = mga_inb(M_MISC_REG_READ) & ~0x0C;
-				switch (pll) {
-					case M_PIXEL_PLL_A:
-						break;
-					case M_PIXEL_PLL_B:
-						misc |=  0x04;
-						break;
-					default:
-						misc |=  0x0C;
-						break;
-				}
-				mga_outb(M_MISC_REG, misc);
-			}
-			pi = &minfo->limits.pixel;
-			ci = &minfo->cache.pixel;
-			break;
-		case M_SYSTEM_PLL:
-			{
-				u_int32_t opt;
-
-				pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &opt);
-				if (!(opt & 0x20)) {
-					pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, opt | 0x20);
-				}
-			}
-			pi = &minfo->limits.system;
-			ci = &minfo->cache.system;
-			break;
-		case M_VIDEO_PLL:
-			{
-				u_int8_t tmp;
-				unsigned int mnp;
-				unsigned long flags;
-				
-				matroxfb_DAC_lock_irqsave(flags);
-				tmp = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
-				if (!(tmp & 2)) {
-					matroxfb_DAC_out(minfo, M1064_XPWRCTRL, tmp | 2);
-				}
-				
-				mnp = matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) << 16;
-				mnp |= matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) << 8;
-				pixel_vco = g450_mnp2vco(minfo, mnp);
-				matroxfb_DAC_unlock_irqrestore(flags);
-			}
-			pi = &minfo->limits.video;
-			ci = &minfo->cache.video;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	mnpcount = 0;
-	{
-		unsigned int mnp;
-		unsigned int xvco;
-
-		for (mnp = g450_firstpll(minfo, pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(minfo, pi, &xvco, mnp)) {
-			unsigned int idx;
-			unsigned int vco;
-			unsigned int delta;
-
-			vco = g450_mnp2vco(minfo, mnp);
-#if 0			
-			if (pll == M_VIDEO_PLL) {
-				unsigned int big, small;
-
-				if (vco < pixel_vco) {
-					small = vco;
-					big = pixel_vco;
-				} else {
-					small = pixel_vco;
-					big = vco;
-				}
-				while (big > small) {
-					big >>= 1;
-				}
-				if (big == small) {
-					continue;
-				}
-			}
-#endif			
-			delta = pll_freq_delta(fout, g450_vco2f(mnp, vco));
-			for (idx = mnpcount; idx > 0; idx--) {
-				/* == is important; due to nextpll algorithm we get
-				   sorted equally good frequencies from lower VCO 
-				   frequency to higher - with <= lowest wins, while
-				   with < highest one wins */
-				if (delta <= deltaarray[idx-1]) {
-					/* all else being equal except VCO,
-					 * choose VCO not near (within 1/16th or so) VCOmin
-					 * (freqs near VCOmin aren't as stable)
-					 */
-					if (delta == deltaarray[idx-1]
-					    && vco != g450_mnp2vco(minfo, mnparray[idx-1])
-					    && vco < (pi->vcomin * 17 / 16)) {
-						break;
-					}
-					mnparray[idx] = mnparray[idx-1];
-					deltaarray[idx] = deltaarray[idx-1];
-				} else {
-					break;
-				}
-			}
-			mnparray[idx] = mnp;
-			deltaarray[idx] = delta;
-			mnpcount++;
-		}
-	}
-	/* VideoPLL and PixelPLL matched: do nothing... In all other cases we should get at least one frequency */
-	if (!mnpcount) {
-		return -EBUSY;
-	}
-	{
-		unsigned long flags;
-		unsigned int mnp;
-		
-		matroxfb_DAC_lock_irqsave(flags);
-		mnp = g450_checkcache(minfo, ci, mnparray[0]);
-		if (mnp != NO_MORE_MNP) {
-			matroxfb_g450_setpll_cond(minfo, mnp, pll);
-		} else {
-			mnp = g450_findworkingpll(minfo, pll, mnparray, mnpcount);
-			g450_addcache(ci, mnparray[0], mnp);
-		}
-		updatehwstate_clk(&minfo->hw, mnp, pll);
-		matroxfb_DAC_unlock_irqrestore(flags);
-		return mnp;
-	}
-}
-
-/* It must be greater than number of possible PLL values.
- * Currently there is 5(p) * 10(m) = 50 possible values. */
-#define MNP_TABLE_SIZE  64
-
-int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
-			 unsigned int pll)
-{
-	unsigned int* arr;
-	
-	arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL);
-	if (arr) {
-		int r;
-
-		r = __g450_setclk(minfo, fout, pll, arr, arr + MNP_TABLE_SIZE);
-		kfree(arr);
-		return r;
-	}
-	return -ENOMEM;
-}
-
-EXPORT_SYMBOL(matroxfb_g450_setclk);
-EXPORT_SYMBOL(g450_mnp2f);
-EXPORT_SYMBOL(matroxfb_g450_setpll_cond);
-
-MODULE_AUTHOR("(c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Matrox G450/G550 PLL driver");
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/matrox/g450_pll.h
deleted file mode 100644
index aac615d18440..000000000000
--- a/drivers/video/matrox/g450_pll.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __G450_PLL_H__
-#define __G450_PLL_H__
-
-#include "matroxfb_base.h"
-
-int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
-			 unsigned int pll);
-unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp);
-void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
-			       unsigned int pll);
-
-#endif	/* __G450_PLL_H__ */
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
deleted file mode 100644
index 0fb280ead3dc..000000000000
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Version: 1.64 2002/06/10
- *
- * See matroxfb_base.c for contributors.
- *
- */
-
-#include "matroxfb_base.h"
-#include "matroxfb_maven.h"
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/i2c-algo-bit.h>
-
-/* MGA-TVO I2C for G200, G400 */
-#define MAT_CLK		0x20
-#define MAT_DATA	0x10
-/* primary head DDC for Mystique(?), G100, G200, G400 */
-#define DDC1_CLK	0x08
-#define DDC1_DATA	0x02
-/* primary head DDC for Millennium, Millennium II */
-#define DDC1B_CLK	0x10
-#define DDC1B_DATA	0x04
-/* secondary head DDC for G400 */
-#define DDC2_CLK	0x04
-#define DDC2_DATA	0x01
-
-/******************************************************/
-
-struct matroxfb_dh_maven_info {
-	struct i2c_bit_adapter	maven;
-	struct i2c_bit_adapter	ddc1;
-	struct i2c_bit_adapter	ddc2;
-};
-
-static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
-	unsigned long flags;
-	int v;
-
-	matroxfb_DAC_lock_irqsave(flags);
-	v = matroxfb_DAC_in(minfo, DAC_XGENIODATA);
-	matroxfb_DAC_unlock_irqrestore(flags);
-	return v;
-}
-
-static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
-	unsigned long flags;
-	int v;
-
-	matroxfb_DAC_lock_irqsave(flags);
-	v = (matroxfb_DAC_in(minfo, DAC_XGENIOCTRL) & mask) | val;
-	matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, v);
-	/* We must reset GENIODATA very often... XFree plays with this register */
-	matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0x00);
-	matroxfb_DAC_unlock_irqrestore(flags);
-}
-
-/* software I2C functions */
-static inline void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
-	if (state)
-		state = 0;
-	else
-		state = mask;
-	matroxfb_set_gpio(minfo, ~mask, state);
-}
-
-static void matroxfb_gpio_setsda(void* data, int state) {
-	struct i2c_bit_adapter* b = data;
-	matroxfb_i2c_set(b->minfo, b->mask.data, state);
-}
-
-static void matroxfb_gpio_setscl(void* data, int state) {
-	struct i2c_bit_adapter* b = data;
-	matroxfb_i2c_set(b->minfo, b->mask.clock, state);
-}
-
-static int matroxfb_gpio_getsda(void* data) {
-	struct i2c_bit_adapter* b = data;
-	return (matroxfb_read_gpio(b->minfo) & b->mask.data) ? 1 : 0;
-}
-
-static int matroxfb_gpio_getscl(void* data) {
-	struct i2c_bit_adapter* b = data;
-	return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
-}
-
-static const struct i2c_algo_bit_data matrox_i2c_algo_template =
-{
-	.setsda		= matroxfb_gpio_setsda,
-	.setscl		= matroxfb_gpio_setscl,
-	.getsda		= matroxfb_gpio_getsda,
-	.getscl		= matroxfb_gpio_getscl,
-	.udelay		= 10,
-	.timeout	= 100,
-};
-
-static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 
-		unsigned int data, unsigned int clock, const char *name,
-		int class)
-{
-	int err;
-
-	b->minfo = minfo;
-	b->mask.data = data;
-	b->mask.clock = clock;
-	b->adapter.owner = THIS_MODULE;
-	snprintf(b->adapter.name, sizeof(b->adapter.name), name,
-		minfo->fbcon.node);
-	i2c_set_adapdata(&b->adapter, b);
-	b->adapter.class = class;
-	b->adapter.algo_data = &b->bac;
-	b->adapter.dev.parent = &minfo->pcidev->dev;
-	b->bac = matrox_i2c_algo_template;
-	b->bac.data = b;
-	err = i2c_bit_add_bus(&b->adapter);
-	b->initialized = !err;
-	return err;
-}
-
-static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
-	if (b->initialized) {
-		i2c_del_adapter(&b->adapter);
-		b->initialized = 0;
-	}
-}
-
-static inline void i2c_maven_done(struct matroxfb_dh_maven_info* minfo2) {
-	i2c_bit_bus_del(&minfo2->maven);
-}
-
-static inline void i2c_ddc1_done(struct matroxfb_dh_maven_info* minfo2) {
-	i2c_bit_bus_del(&minfo2->ddc1);
-}
-
-static inline void i2c_ddc2_done(struct matroxfb_dh_maven_info* minfo2) {
-	i2c_bit_bus_del(&minfo2->ddc2);
-}
-
-static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
-	int err;
-	unsigned long flags;
-	struct matroxfb_dh_maven_info* m2info;
-
-	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
-	if (!m2info)
-		return NULL;
-
-	matroxfb_DAC_lock_irqsave(flags);
-	matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0xFF);
-	matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, 0x00);
-	matroxfb_DAC_unlock_irqrestore(flags);
-
-	switch (minfo->chip) {
-		case MGA_2064:
-		case MGA_2164:
-			err = i2c_bus_reg(&m2info->ddc1, minfo,
-					  DDC1B_DATA, DDC1B_CLK,
-					  "DDC:fb%u #0", I2C_CLASS_DDC);
-			break;
-		default:
-			err = i2c_bus_reg(&m2info->ddc1, minfo,
-					  DDC1_DATA, DDC1_CLK,
-					  "DDC:fb%u #0", I2C_CLASS_DDC);
-			break;
-	}
-	if (err)
-		goto fail_ddc1;
-	if (minfo->devflags.dualhead) {
-		err = i2c_bus_reg(&m2info->ddc2, minfo,
-				  DDC2_DATA, DDC2_CLK,
-				  "DDC:fb%u #1", I2C_CLASS_DDC);
-		if (err == -ENODEV) {
-			printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
-		} else if (err)
-			printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
-		/* Register maven bus even on G450/G550 */
-		err = i2c_bus_reg(&m2info->maven, minfo,
-				  MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
-		if (err)
-			printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
-		else {
-			struct i2c_board_info maven_info = {
-				I2C_BOARD_INFO("maven", 0x1b),
-			};
-			unsigned short const addr_list[2] = {
-				0x1b, I2C_CLIENT_END
-			};
-
-			i2c_new_probed_device(&m2info->maven.adapter,
-					      &maven_info, addr_list, NULL);
-		}
-	}
-	return m2info;
-fail_ddc1:;
-	kfree(m2info);
-	printk(KERN_ERR "i2c-matroxfb: Could not register primary adapter DDC bus.\n");
-	return NULL;
-}
-
-static void i2c_matroxfb_remove(struct matrox_fb_info* minfo, void* data) {
-	struct matroxfb_dh_maven_info* m2info = data;
-
-	i2c_maven_done(m2info);
-	i2c_ddc2_done(m2info);
-	i2c_ddc1_done(m2info);
-	kfree(m2info);
-}
-
-static struct matroxfb_driver i2c_matroxfb = {
-	.node =		LIST_HEAD_INIT(i2c_matroxfb.node),
-	.name =		"i2c-matroxfb",
-	.probe = 	i2c_matroxfb_probe,
-	.remove =	i2c_matroxfb_remove,
-};
-
-static int __init i2c_matroxfb_init(void) {
-	if (matroxfb_register_driver(&i2c_matroxfb)) {
-		printk(KERN_ERR "i2c-matroxfb: failed to register driver\n");
-		return -ENXIO;
-	}
-	return 0;
-}
-
-static void __exit i2c_matroxfb_exit(void) {
-	matroxfb_unregister_driver(&i2c_matroxfb);
-}
-
-MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards");
-
-module_init(i2c_matroxfb_init);
-module_exit(i2c_matroxfb_exit);
-/* no __setup required */
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
deleted file mode 100644
index a01147fdf270..000000000000
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.65 2002/08/14
- *
- * See matroxfb_base.c for contributors.
- *
- */
-
-
-#include "matroxfb_DAC1064.h"
-#include "matroxfb_misc.h"
-#include "matroxfb_accel.h"
-#include "g450_pll.h"
-#include <linux/matroxfb.h>
-
-#ifdef NEED_DAC1064
-#define outDAC1064 matroxfb_DAC_out
-#define inDAC1064 matroxfb_DAC_in
-
-#define DAC1064_OPT_SCLK_PCI	0x00
-#define DAC1064_OPT_SCLK_PLL	0x01
-#define DAC1064_OPT_SCLK_EXT	0x02
-#define DAC1064_OPT_SCLK_MASK	0x03
-#define DAC1064_OPT_GDIV1	0x04	/* maybe it is GDIV2 on G100 ?! */
-#define DAC1064_OPT_GDIV3	0x00
-#define DAC1064_OPT_MDIV1	0x08
-#define DAC1064_OPT_MDIV2	0x00
-#define DAC1064_OPT_RESERVED	0x10
-
-static void DAC1064_calcclock(const struct matrox_fb_info *minfo,
-			      unsigned int freq, unsigned int fmax,
-			      unsigned int *in, unsigned int *feed,
-			      unsigned int *post)
-{
-	unsigned int fvco;
-	unsigned int p;
-
-	DBG(__func__)
-	
-	/* only for devices older than G450 */
-
-	fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p);
-	
-	p = (1 << p) - 1;
-	if (fvco <= 100000)
-		;
-	else if (fvco <= 140000)
-		p |= 0x08;
-	else if (fvco <= 180000)
-		p |= 0x10;
-	else
-		p |= 0x18;
-	*post = p;
-}
-
-/* they must be in POS order */
-static const unsigned char MGA1064_DAC_regs[] = {
-		M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL,
-		M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE,
-		M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE,
-		M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE,
-		DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL,
-		M1064_XMISCCTRL,
-		M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST,
-		M1064_XCRCBITSEL,
-		M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
-
-static const unsigned char MGA1064_DAC[] = {
-		0x00, 0x00, M1064_XCURCTRL_DIS,
-		0x00, 0x00, 0x00, 	/* black */
-		0xFF, 0xFF, 0xFF,	/* white */
-		0xFF, 0x00, 0x00,	/* red */
-		0x00, 0,
-		M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
-		M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
-		M1064_XMISCCTRL_DAC_8BIT,
-		0x00, 0x00, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
-		0x00,
-		0x00, 0x00, 0xFF, 0xFF};
-
-static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout)
-{
-	unsigned int m, n, p;
-
-	DBG(__func__)
-
-	DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p);
-	minfo->hw.DACclk[0] = m;
-	minfo->hw.DACclk[1] = n;
-	minfo->hw.DACclk[2] = p;
-}
-
-static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo,
-			    unsigned long fmem)
-{
-	u_int32_t mx;
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	if (minfo->devflags.noinit) {
-		/* read MCLK and give up... */
-		hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
-		hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
-		hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
-		return;
-	}
-	mx = hw->MXoptionReg | 0x00000004;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
-	mx &= ~0x000000BB;
-	if (oscinfo & DAC1064_OPT_GDIV1)
-		mx |= 0x00000008;
-	if (oscinfo & DAC1064_OPT_MDIV1)
-		mx |= 0x00000010;
-	if (oscinfo & DAC1064_OPT_RESERVED)
-		mx |= 0x00000080;
-	if ((oscinfo & DAC1064_OPT_SCLK_MASK) == DAC1064_OPT_SCLK_PLL) {
-		/* select PCI clock until we have setup oscilator... */
-		int clk;
-		unsigned int m, n, p;
-
-		/* powerup system PLL, select PCI clock */
-		mx |= 0x00000020;
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
-		mx &= ~0x00000004;
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
-
-		/* !!! you must not access device if MCLK is not running !!!
-		   Doing so cause immediate PCI lockup :-( Maybe they should
-		   generate ABORT or I/O (parity...) error and Linux should
-		   recover from this... (kill driver/process). But world is not
-		   perfect... */
-		/* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
-		   select PLL... because of PLL can be stopped at this time) */
-		DAC1064_calcclock(minfo, fmem, minfo->max_pixel_clock, &m, &n, &p);
-		outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3] = m);
-		outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4] = n);
-		outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5] = p);
-		for (clk = 65536; clk; --clk) {
-			if (inDAC1064(minfo, DAC1064_XSYSPLLSTAT) & 0x40)
-				break;
-		}
-		if (!clk)
-			printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n");
-		/* select PLL */
-		mx |= 0x00000005;
-	} else {
-		/* select specified system clock source */
-		mx |= oscinfo & DAC1064_OPT_SCLK_MASK;
-	}
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
-	mx &= ~0x00000004;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
-	hw->MXoptionReg = mx;
-}
-
-#ifdef CONFIG_FB_MATROX_G
-static void g450_set_plls(struct matrox_fb_info *minfo)
-{
-	u_int32_t c2_ctl;
-	unsigned int pxc;
-	struct matrox_hw_state *hw = &minfo->hw;
-	int pixelmnp;
-	int videomnp;
-	
-	c2_ctl = hw->crtc2.ctl & ~0x4007;	/* Clear PLL + enable for CRTC2 */
-	c2_ctl |= 0x0001;			/* Enable CRTC2 */
-	hw->DACreg[POS1064_XPWRCTRL] &= ~0x02;	/* Stop VIDEO PLL */
-	pixelmnp = minfo->crtc1.mnp;
-	videomnp = minfo->crtc2.mnp;
-	if (videomnp < 0) {
-		c2_ctl &= ~0x0001;			/* Disable CRTC2 */
-		hw->DACreg[POS1064_XPWRCTRL] &= ~0x10;	/* Powerdown CRTC2 */
-	} else if (minfo->crtc2.pixclock == minfo->features.pll.ref_freq) {
-		c2_ctl |=  0x4002;	/* Use reference directly */
-	} else if (videomnp == pixelmnp) {
-		c2_ctl |=  0x0004;	/* Use pixel PLL */
-	} else {
-		if (0 == ((videomnp ^ pixelmnp) & 0xFFFFFF00)) {
-			/* PIXEL and VIDEO PLL must not use same frequency. We modify N
-			   of PIXEL PLL in such case because of VIDEO PLL may be source
-			   of TVO clocks, and chroma subcarrier is derived from its
-			   pixel clocks */
-			pixelmnp += 0x000100;
-		}
-		c2_ctl |=  0x0006;	/* Use video PLL */
-		hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
-		
-		outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
-		matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL);
-	}
-
-	hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
-	if (pixelmnp >= 0) {
-		hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
-		
-		outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
-		matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C);
-	}
-	if (c2_ctl != hw->crtc2.ctl) {
-		hw->crtc2.ctl = c2_ctl;
-		mga_outl(0x3C10, c2_ctl);
-	}
-
-	pxc = minfo->crtc1.pixclock;
-	if (pxc == 0 || minfo->outputs[2].src == MATROXFB_SRC_CRTC2) {
-		pxc = minfo->crtc2.pixclock;
-	}
-	if (minfo->chip == MGA_G550) {
-		if (pxc < 45000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x00;	/* 0-50 */
-		} else if (pxc < 55000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x08;	/* 34-62 */
-		} else if (pxc < 70000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x10;	/* 42-78 */
-		} else if (pxc < 85000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x18;	/* 62-92 */
-		} else if (pxc < 100000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x20;	/* 74-108 */
-		} else if (pxc < 115000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x28;	/* 94-122 */
-		} else if (pxc < 125000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x30;	/* 108-132 */
-		} else {
-			hw->DACreg[POS1064_XPANMODE] = 0x38;	/* 120-168 */
-		}
-	} else {
-		/* G450 */
-		if (pxc < 45000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x00;	/* 0-54 */
-		} else if (pxc < 65000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x08;	/* 38-70 */
-		} else if (pxc < 85000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x10;	/* 56-96 */
-		} else if (pxc < 105000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x18;	/* 80-114 */
-		} else if (pxc < 135000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x20;	/* 102-144 */
-		} else if (pxc < 160000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x28;	/* 132-166 */
-		} else if (pxc < 175000) {
-			hw->DACreg[POS1064_XPANMODE] = 0x30;	/* 154-182 */
-		} else {
-			hw->DACreg[POS1064_XPANMODE] = 0x38;	/* 170-204 */
-		}
-	}
-}
-#endif
-
-void DAC1064_global_init(struct matrox_fb_info *minfo)
-{
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
-	hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
-	hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
-#ifdef CONFIG_FB_MATROX_G
-	if (minfo->devflags.g450dac) {
-		hw->DACreg[POS1064_XPWRCTRL] = 0x1F;	/* powerup everything */
-		hw->DACreg[POS1064_XOUTPUTCONN] = 0x00;	/* disable outputs */
-		hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
-		switch (minfo->outputs[0].src) {
-			case MATROXFB_SRC_CRTC1:
-			case MATROXFB_SRC_CRTC2:
-				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01;	/* enable output; CRTC1/2 selection is in CRTC2 ctl */
-				break;
-			case MATROXFB_SRC_NONE:
-				hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN;
-				break;
-		}
-		switch (minfo->outputs[1].src) {
-			case MATROXFB_SRC_CRTC1:
-				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
-				break;
-			case MATROXFB_SRC_CRTC2:
-				if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_MONITOR) {
-					hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08;
-				} else {
-					hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C;
-				}
-				break;
-			case MATROXFB_SRC_NONE:
-				hw->DACreg[POS1064_XPWRCTRL] &= ~0x01;		/* Poweroff DAC2 */
-				break;
-		}
-		switch (minfo->outputs[2].src) {
-			case MATROXFB_SRC_CRTC1:
-				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20;
-				break;
-			case MATROXFB_SRC_CRTC2:
-				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x40;
-				break;
-			case MATROXFB_SRC_NONE:
-#if 0
-				/* HELP! If we boot without DFP connected to DVI, we can
-				   poweroff TMDS. But if we boot with DFP connected,
-				   TMDS generated clocks are used instead of ALL pixclocks
-				   available... If someone knows which register
-				   handles it, please reveal this secret to me... */			
-				hw->DACreg[POS1064_XPWRCTRL] &= ~0x04;		/* Poweroff TMDS */
-#endif				
-				break;
-		}
-		/* Now set timming related variables... */
-		g450_set_plls(minfo);
-	} else
-#endif
-	{
-		if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) {
-			hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
-			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
-		} else if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
-			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
-		} else if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1)
-			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
-		else
-			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
-
-		if (minfo->outputs[0].src != MATROXFB_SRC_NONE)
-			hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
-	}
-}
-
-void DAC1064_global_restore(struct matrox_fb_info *minfo)
-{
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
-	outDAC1064(minfo, M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
-	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
-		outDAC1064(minfo, 0x20, 0x04);
-		outDAC1064(minfo, 0x1F, minfo->devflags.dfp_type);
-		if (minfo->devflags.g450dac) {
-			outDAC1064(minfo, M1064_XSYNCCTRL, 0xCC);
-			outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
-			outDAC1064(minfo, M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]);
-			outDAC1064(minfo, M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
-		}
-	}
-}
-
-static int DAC1064_init_1(struct matrox_fb_info *minfo, struct my_timming *m)
-{
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
-	switch (minfo->fbcon.var.bits_per_pixel) {
-		/* case 4: not supported by MGA1064 DAC */
-		case 8:
-			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
-			break;
-		case 16:
-			if (minfo->fbcon.var.green.length == 5)
-				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
-			else
-				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
-			break;
-		case 24:
-			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_24BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
-			break;
-		case 32:
-			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_32BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
-			break;
-		default:
-			return 1;	/* unsupported depth */
-	}
-	hw->DACreg[POS1064_XVREFCTRL] = minfo->features.DAC1064.xvrefctrl;
-	hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
-	hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
-	hw->DACreg[POS1064_XCURADDL] = 0;
-	hw->DACreg[POS1064_XCURADDH] = 0;
-
-	DAC1064_global_init(minfo);
-	return 0;
-}
-
-static int DAC1064_init_2(struct matrox_fb_info *minfo, struct my_timming *m)
-{
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	if (minfo->fbcon.var.bits_per_pixel > 16) {	/* 256 entries */
-		int i;
-
-		for (i = 0; i < 256; i++) {
-			hw->DACpal[i * 3 + 0] = i;
-			hw->DACpal[i * 3 + 1] = i;
-			hw->DACpal[i * 3 + 2] = i;
-		}
-	} else if (minfo->fbcon.var.bits_per_pixel > 8) {
-		if (minfo->fbcon.var.green.length == 5) {	/* 0..31, 128..159 */
-			int i;
-
-			for (i = 0; i < 32; i++) {
-				/* with p15 == 0 */
-				hw->DACpal[i * 3 + 0] = i << 3;
-				hw->DACpal[i * 3 + 1] = i << 3;
-				hw->DACpal[i * 3 + 2] = i << 3;
-				/* with p15 == 1 */
-				hw->DACpal[(i + 128) * 3 + 0] = i << 3;
-				hw->DACpal[(i + 128) * 3 + 1] = i << 3;
-				hw->DACpal[(i + 128) * 3 + 2] = i << 3;
-			}
-		} else {
-			int i;
-
-			for (i = 0; i < 64; i++) {		/* 0..63 */
-				hw->DACpal[i * 3 + 0] = i << 3;
-				hw->DACpal[i * 3 + 1] = i << 2;
-				hw->DACpal[i * 3 + 2] = i << 3;
-			}
-		}
-	} else {
-		memset(hw->DACpal, 0, 768);
-	}
-	return 0;
-}
-
-static void DAC1064_restore_1(struct matrox_fb_info *minfo)
-{
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	CRITFLAGS
-
-	DBG(__func__)
-
-	CRITBEGIN
-
-	if ((inDAC1064(minfo, DAC1064_XSYSPLLM) != hw->DACclk[3]) ||
-	    (inDAC1064(minfo, DAC1064_XSYSPLLN) != hw->DACclk[4]) ||
-	    (inDAC1064(minfo, DAC1064_XSYSPLLP) != hw->DACclk[5])) {
-		outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3]);
-		outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4]);
-		outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5]);
-	}
-	{
-		unsigned int i;
-
-		for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
-			if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL))
-				outDAC1064(minfo, MGA1064_DAC_regs[i], hw->DACreg[i]);
-		}
-	}
-
-	DAC1064_global_restore(minfo);
-
-	CRITEND
-};
-
-static void DAC1064_restore_2(struct matrox_fb_info *minfo)
-{
-#ifdef DEBUG
-	unsigned int i;
-#endif
-
-	DBG(__func__)
-
-#ifdef DEBUG
-	dprintk(KERN_DEBUG "DAC1064regs ");
-	for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
-		dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], minfo->hw.DACreg[i]);
-		if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
-	}
-	dprintk(KERN_DEBUG "DAC1064clk ");
-	for (i = 0; i < 6; i++)
-		dprintk("C%02X=%02X ", i, minfo->hw.DACclk[i]);
-	dprintk("\n");
-#endif
-}
-
-static int m1064_compute(void* out, struct my_timming* m) {
-#define minfo ((struct matrox_fb_info*)out)
-	{
-		int i;
-		int tmout;
-		CRITFLAGS
-
-		DAC1064_setpclk(minfo, m->pixclock);
-
-		CRITBEGIN
-
-		for (i = 0; i < 3; i++)
-			outDAC1064(minfo, M1064_XPIXPLLCM + i, minfo->hw.DACclk[i]);
-		for (tmout = 500000; tmout; tmout--) {
-			if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
-				break;
-			udelay(10);
-		}
-
-		CRITEND
-
-		if (!tmout)
-			printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
-	}
-#undef minfo
-	return 0;
-}
-
-static struct matrox_altout m1064 = {
-	.name	 = "Primary output",
-	.compute = m1064_compute,
-};
-
-#ifdef CONFIG_FB_MATROX_G
-static int g450_compute(void* out, struct my_timming* m) {
-#define minfo ((struct matrox_fb_info*)out)
-	if (m->mnp < 0) {
-		m->mnp = matroxfb_g450_setclk(minfo, m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
-		if (m->mnp >= 0) {
-			m->pixclock = g450_mnp2f(minfo, m->mnp);
-		}
-	}
-#undef minfo
-	return 0;
-}
-
-static struct matrox_altout g450out = {
-	.name	 = "Primary output",
-	.compute = g450_compute,
-};
-#endif
-
-#endif /* NEED_DAC1064 */
-
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-static int MGA1064_init(struct matrox_fb_info *minfo, struct my_timming *m)
-{
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	if (DAC1064_init_1(minfo, m)) return 1;
-	if (matroxfb_vgaHWinit(minfo, m)) return 1;
-
-	hw->MiscOutReg = 0xCB;
-	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
-		hw->MiscOutReg &= ~0x40;
-	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
-		hw->MiscOutReg &= ~0x80;
-	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
-		hw->CRTCEXT[3] |= 0x40;
-
-	if (DAC1064_init_2(minfo, m)) return 1;
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_FB_MATROX_G
-static int MGAG100_init(struct matrox_fb_info *minfo, struct my_timming *m)
-{
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	if (DAC1064_init_1(minfo, m)) return 1;
-	hw->MXoptionReg &= ~0x2000;
-	if (matroxfb_vgaHWinit(minfo, m)) return 1;
-
-	hw->MiscOutReg = 0xEF;
-	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
-		hw->MiscOutReg &= ~0x40;
-	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
-		hw->MiscOutReg &= ~0x80;
-	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
-		hw->CRTCEXT[3] |= 0x40;
-
-	if (DAC1064_init_2(minfo, m)) return 1;
-	return 0;
-}
-#endif	/* G */
-
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-static void MGA1064_ramdac_init(struct matrox_fb_info *minfo)
-{
-
-	DBG(__func__)
-
-	/* minfo->features.DAC1064.vco_freq_min = 120000; */
-	minfo->features.pll.vco_freq_min = 62000;
-	minfo->features.pll.ref_freq	 = 14318;
-	minfo->features.pll.feed_div_min = 100;
-	minfo->features.pll.feed_div_max = 127;
-	minfo->features.pll.in_div_min	 = 1;
-	minfo->features.pll.in_div_max	 = 31;
-	minfo->features.pll.post_shift_max = 3;
-	minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_EXTERNAL;
-	/* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
-	DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
-}
-#endif
-
-#ifdef CONFIG_FB_MATROX_G
-/* BIOS environ */
-static int x7AF4 = 0x10;	/* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
-				/* G100 wants 0x10, G200 SGRAM does not care... */
-#if 0
-static int def50 = 0;	/* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
-#endif
-
-static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags,
-				 int m, int n, int p)
-{
-	int reg;
-	int selClk;
-	int clk;
-
-	DBG(__func__)
-
-	outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
-		   M1064_XPIXCLKCTRL_PLL_UP);
-	switch (flags & 3) {
-		case 0:		reg = M1064_XPIXPLLAM; break;
-		case 1:		reg = M1064_XPIXPLLBM; break;
-		default:	reg = M1064_XPIXPLLCM; break;
-	}
-	outDAC1064(minfo, reg++, m);
-	outDAC1064(minfo, reg++, n);
-	outDAC1064(minfo, reg, p);
-	selClk = mga_inb(M_MISC_REG_READ) & ~0xC;
-	/* there should be flags & 0x03 & case 0/1/else */
-	/* and we should first select source and after that we should wait for PLL */
-	/* and we are waiting for PLL with oscilator disabled... Is it right? */
-	switch (flags & 0x03) {
-		case 0x00:	break;
-		case 0x01:	selClk |= 4; break;
-		default:	selClk |= 0x0C; break;
-	}
-	mga_outb(M_MISC_REG, selClk);
-	for (clk = 500000; clk; clk--) {
-		if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
-			break;
-		udelay(10);
-	}
-	if (!clk)
-		printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
-	selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
-	switch (flags & 0x0C) {
-		case 0x00:	selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break;
-		case 0x04:	selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break;
-		default:	selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break;
-	}
-	outDAC1064(minfo, M1064_XPIXCLKCTRL, selClk);
-	outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
-}
-
-static void MGAG100_setPixClock(const struct matrox_fb_info *minfo, int flags,
-				int freq)
-{
-	unsigned int m, n, p;
-
-	DBG(__func__)
-
-	DAC1064_calcclock(minfo, freq, minfo->max_pixel_clock, &m, &n, &p);
-	MGAG100_progPixClock(minfo, flags, m, n, p);
-}
-#endif
-
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-static int MGA1064_preinit(struct matrox_fb_info *minfo)
-{
-	static const int vxres_mystique[] = { 512,        640, 768,  800,  832,  960,
-					     1024, 1152, 1280,      1600, 1664, 1920,
-					     2048,    0};
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	/* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
-	minfo->capable.text = 1;
-	minfo->capable.vxres = vxres_mystique;
-
-	minfo->outputs[0].output = &m1064;
-	minfo->outputs[0].src = minfo->outputs[0].default_src;
-	minfo->outputs[0].data = minfo;
-	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-
-	if (minfo->devflags.noinit)
-		return 0;	/* do not modify settings */
-	hw->MXoptionReg &= 0xC0000100;
-	hw->MXoptionReg |= 0x00094E20;
-	if (minfo->devflags.novga)
-		hw->MXoptionReg &= ~0x00000100;
-	if (minfo->devflags.nobios)
-		hw->MXoptionReg &= ~0x40000000;
-	if (minfo->devflags.nopciretry)
-		hw->MXoptionReg |=  0x20000000;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-	mga_setr(M_SEQ_INDEX, 0x01, 0x20);
-	mga_outl(M_CTLWTST, 0x00000000);
-	udelay(200);
-	mga_outl(M_MACCESS, 0x00008000);
-	udelay(100);
-	mga_outl(M_MACCESS, 0x0000C000);
-	return 0;
-}
-
-static void MGA1064_reset(struct matrox_fb_info *minfo)
-{
-
-	DBG(__func__);
-
-	MGA1064_ramdac_init(minfo);
-}
-#endif
-
-#ifdef CONFIG_FB_MATROX_G
-static void g450_mclk_init(struct matrox_fb_info *minfo)
-{
-	/* switch all clocks to PCI source */
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3 & ~0x00300C03);
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
-
-	if (((minfo->values.reg.opt3 & 0x000003) == 0x000003) ||
-	    ((minfo->values.reg.opt3 & 0x000C00) == 0x000C00) ||
-	    ((minfo->values.reg.opt3 & 0x300000) == 0x300000)) {
-		matroxfb_g450_setclk(minfo, minfo->values.pll.video, M_VIDEO_PLL);
-	} else {
-		unsigned long flags;
-		unsigned int pwr;
-		
-		matroxfb_DAC_lock_irqsave(flags);
-		pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02;
-		outDAC1064(minfo, M1064_XPWRCTRL, pwr);
-		matroxfb_DAC_unlock_irqrestore(flags);
-	}
-	matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL);
-	
-	/* switch clocks to their real PLL source(s) */
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3);
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
-
-}
-
-static void g450_memory_init(struct matrox_fb_info *minfo)
-{
-	/* disable memory refresh */
-	minfo->hw.MXoptionReg &= ~0x001F8000;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
-	
-	/* set memory interface parameters */
-	minfo->hw.MXoptionReg &= ~0x00207E00;
-	minfo->hw.MXoptionReg |= 0x00207E00 & minfo->values.reg.opt;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, minfo->values.reg.opt2);
-	
-	mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
-	
-	/* first set up memory interface with disabled memory interface clocks */
-	pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc & ~0x80000000U);
-	mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
-	mga_outl(M_MACCESS, minfo->values.reg.maccess);
-	/* start memory clocks */
-	pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U);
-
-	udelay(200);
-	
-	if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) {
-		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000);
-	}
-	mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000);
-	
-	udelay(200);
-	
-	minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
-	
-	/* value is written to memory chips only if old != new */
-	mga_outl(M_PLNWT, 0);
-	mga_outl(M_PLNWT, ~0);
-	
-	if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) {
-		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core);
-	}
-	
-}
-
-static void g450_preinit(struct matrox_fb_info *minfo)
-{
-	u_int32_t c2ctl;
-	u_int8_t curctl;
-	u_int8_t c1ctl;
-	
-	/* minfo->hw.MXoptionReg = minfo->values.reg.opt; */
-	minfo->hw.MXoptionReg &= 0xC0000100;
-	minfo->hw.MXoptionReg |= 0x00000020;
-	if (minfo->devflags.novga)
-		minfo->hw.MXoptionReg &= ~0x00000100;
-	if (minfo->devflags.nobios)
-		minfo->hw.MXoptionReg &= ~0x40000000;
-	if (minfo->devflags.nopciretry)
-		minfo->hw.MXoptionReg |=  0x20000000;
-	minfo->hw.MXoptionReg |= minfo->values.reg.opt & 0x03400040;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
-
-	/* Init system clocks */
-		
-	/* stop crtc2 */
-	c2ctl = mga_inl(M_C2CTL);
-	mga_outl(M_C2CTL, c2ctl & ~1);
-	/* stop cursor */
-	curctl = inDAC1064(minfo, M1064_XCURCTRL);
-	outDAC1064(minfo, M1064_XCURCTRL, 0);
-	/* stop crtc1 */
-	c1ctl = mga_readr(M_SEQ_INDEX, 1);
-	mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
-
-	g450_mclk_init(minfo);
-	g450_memory_init(minfo);
-	
-	/* set legacy VGA clock sources for DOSEmu or VMware... */
-	matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A);
-	matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B);
-
-	/* restore crtc1 */
-	mga_setr(M_SEQ_INDEX, 1, c1ctl);
-	
-	/* restore cursor */
-	outDAC1064(minfo, M1064_XCURCTRL, curctl);
-
-	/* restore crtc2 */
-	mga_outl(M_C2CTL, c2ctl);
-	
-	return;
-}
-
-static int MGAG100_preinit(struct matrox_fb_info *minfo)
-{
-	static const int vxres_g100[] = {  512,        640, 768,  800,  832,  960,
-                                          1024, 1152, 1280,      1600, 1664, 1920,
-                                          2048, 0};
-	struct matrox_hw_state *hw = &minfo->hw;
-
-        u_int32_t reg50;
-#if 0
-	u_int32_t q;
-#endif
-
-	DBG(__func__)
-
-	/* there are some instabilities if in_div > 19 && vco < 61000 */
-	if (minfo->devflags.g450dac) {
-		minfo->features.pll.vco_freq_min = 130000;	/* my sample: >118 */
-	} else {
-		minfo->features.pll.vco_freq_min = 62000;
-	}
-	if (!minfo->features.pll.ref_freq) {
-		minfo->features.pll.ref_freq	 = 27000;
-	}
-	minfo->features.pll.feed_div_min = 7;
-	minfo->features.pll.feed_div_max = 127;
-	minfo->features.pll.in_div_min	 = 1;
-	minfo->features.pll.in_div_max	 = 31;
-	minfo->features.pll.post_shift_max = 3;
-	minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_G100_DEFAULT;
-	/* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
-	minfo->capable.text = 1;
-	minfo->capable.vxres = vxres_g100;
-	minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100
-			? minfo->devflags.sgram : 1;
-
-	if (minfo->devflags.g450dac) {
-		minfo->outputs[0].output = &g450out;
-	} else {
-		minfo->outputs[0].output = &m1064;
-	}
-	minfo->outputs[0].src = minfo->outputs[0].default_src;
-	minfo->outputs[0].data = minfo;
-	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-
-	if (minfo->devflags.g450dac) {
-		/* we must do this always, BIOS does not do it for us
-		   and accelerator dies without it */
-		mga_outl(0x1C0C, 0);
-	}
-	if (minfo->devflags.noinit)
-		return 0;
-	if (minfo->devflags.g450dac) {
-		g450_preinit(minfo);
-		return 0;
-	}
-	hw->MXoptionReg &= 0xC0000100;
-	hw->MXoptionReg |= 0x00000020;
-	if (minfo->devflags.novga)
-		hw->MXoptionReg &= ~0x00000100;
-	if (minfo->devflags.nobios)
-		hw->MXoptionReg &= ~0x40000000;
-	if (minfo->devflags.nopciretry)
-		hw->MXoptionReg |=  0x20000000;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-	DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
-
-	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) {
-		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
-		reg50 &= ~0x3000;
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
-
-		hw->MXoptionReg |= 0x1080;
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
-		udelay(100);
-		mga_outb(0x1C05, 0x00);
-		mga_outb(0x1C05, 0x80);
-		udelay(100);
-		mga_outb(0x1C05, 0x40);
-		mga_outb(0x1C05, 0xC0);
-		udelay(100);
-		reg50 &= ~0xFF;
-		reg50 |=  0x07;
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
-		/* it should help with G100 */
-		mga_outb(M_GRAPHICS_INDEX, 6);
-		mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
-		mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
-		mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
-		mga_writeb(minfo->video.vbase, 0x0000, 0xAA);
-		mga_writeb(minfo->video.vbase, 0x0800, 0x55);
-		mga_writeb(minfo->video.vbase, 0x4000, 0x55);
-#if 0
-		if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {
-			hw->MXoptionReg &= ~0x1000;
-		}
-#endif
-		hw->MXoptionReg |= 0x00078020;
-	} else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) {
-		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
-		reg50 &= ~0x3000;
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
-
-		if (minfo->devflags.memtype == -1)
-			hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
-		else
-			hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
-		if (minfo->devflags.sgram)
-			hw->MXoptionReg |= 0x4000;
-		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
-		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
-		udelay(200);
-		mga_outl(M_MACCESS, 0x00000000);
-		mga_outl(M_MACCESS, 0x00008000);
-		udelay(100);
-		mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk);
-		hw->MXoptionReg |= 0x00078020;
-	} else {
-		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
-		reg50 &= ~0x00000100;
-		reg50 |=  0x00000000;
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
-
-		if (minfo->devflags.memtype == -1)
-			hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
-		else
-			hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
-		if (minfo->devflags.sgram)
-			hw->MXoptionReg |= 0x4000;
-		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
-		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
-		udelay(200);
-		mga_outl(M_MACCESS, 0x00000000);
-		mga_outl(M_MACCESS, 0x00008000);
-		udelay(100);
-		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
-		hw->MXoptionReg |= 0x00040020;
-	}
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-	return 0;
-}
-
-static void MGAG100_reset(struct matrox_fb_info *minfo)
-{
-	u_int8_t b;
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	{
-#ifdef G100_BROKEN_IBM_82351
-		u_int32_t d;
-
-		find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
-		pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
-		if (b == minfo->pcidev->bus->number) {
-			pci_write_config_byte(ibm, PCI_COMMAND+1, 0);	/* disable back-to-back & SERR */
-			pci_write_config_byte(ibm, 0x41, 0xF4);		/* ??? */
-			pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0);	/* ??? */
-			pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00);	/* ??? */
-		}
-#endif
-		if (!minfo->devflags.noinit) {
-			if (x7AF4 & 8) {
-				hw->MXoptionReg |= 0x40;	/* FIXME... */
-				pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-			}
-			mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
-		}
-	}
-	if (minfo->devflags.g450dac) {
-		/* either leave MCLK as is... or they were set in preinit */
-		hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
-		hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
-		hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
-	} else {
-		DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
-	}
-	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
-		if (minfo->devflags.dfp_type == -1) {
-			minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F);
-		}
-	}
-	if (minfo->devflags.noinit)
-		return;
-	if (minfo->devflags.g450dac) {
-	} else {
-		MGAG100_setPixClock(minfo, 4, 25175);
-		MGAG100_setPixClock(minfo, 5, 28322);
-		if (x7AF4 & 0x10) {
-			b = inDAC1064(minfo, M1064_XGENIODATA) & ~1;
-			outDAC1064(minfo, M1064_XGENIODATA, b);
-			b = inDAC1064(minfo, M1064_XGENIOCTRL) | 1;
-			outDAC1064(minfo, M1064_XGENIOCTRL, b);
-		}
-	}
-}
-#endif
-
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-static void MGA1064_restore(struct matrox_fb_info *minfo)
-{
-	int i;
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	CRITFLAGS
-
-	DBG(__func__)
-
-	CRITBEGIN
-
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-	mga_outb(M_IEN, 0x00);
-	mga_outb(M_CACHEFLUSH, 0x00);
-
-	CRITEND
-
-	DAC1064_restore_1(minfo);
-	matroxfb_vgaHWrestore(minfo);
-	minfo->crtc1.panpos = -1;
-	for (i = 0; i < 6; i++)
-		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
-	DAC1064_restore_2(minfo);
-}
-#endif
-
-#ifdef CONFIG_FB_MATROX_G
-static void MGAG100_restore(struct matrox_fb_info *minfo)
-{
-	int i;
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	CRITFLAGS
-
-	DBG(__func__)
-
-	CRITBEGIN
-
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-	CRITEND
-
-	DAC1064_restore_1(minfo);
-	matroxfb_vgaHWrestore(minfo);
-	if (minfo->devflags.support32MB)
-		mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
-	minfo->crtc1.panpos = -1;
-	for (i = 0; i < 6; i++)
-		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
-	DAC1064_restore_2(minfo);
-}
-#endif
-
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-struct matrox_switch matrox_mystique = {
-	MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore,
-};
-EXPORT_SYMBOL(matrox_mystique);
-#endif
-
-#ifdef CONFIG_FB_MATROX_G
-struct matrox_switch matrox_G100 = {
-	MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore,
-};
-EXPORT_SYMBOL(matrox_G100);
-#endif
-
-#ifdef NEED_DAC1064
-EXPORT_SYMBOL(DAC1064_global_init);
-EXPORT_SYMBOL(DAC1064_global_restore);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h
deleted file mode 100644
index 1e6e45b57b78..000000000000
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ /dev/null
@@ -1,179 +0,0 @@
-#ifndef __MATROXFB_DAC1064_H__
-#define __MATROXFB_DAC1064_H__
-
-
-#include "matroxfb_base.h"
-
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-extern struct matrox_switch matrox_mystique;
-#endif
-#ifdef CONFIG_FB_MATROX_G
-extern struct matrox_switch matrox_G100;
-#endif
-#ifdef NEED_DAC1064
-void DAC1064_global_init(struct matrox_fb_info *minfo);
-void DAC1064_global_restore(struct matrox_fb_info *minfo);
-#endif
-
-#define M1064_INDEX	0x00
-#define M1064_PALWRADD	0x00
-#define M1064_PALDATA	0x01
-#define M1064_PIXRDMSK	0x02
-#define M1064_PALRDADD	0x03
-#define M1064_X_DATAREG	0x0A
-#define M1064_CURPOSXL	0x0C	/* can be accessed as DWORD */
-#define M1064_CURPOSXH	0x0D
-#define M1064_CURPOSYL	0x0E
-#define M1064_CURPOSYH	0x0F
-
-#define M1064_XCURADDL		0x04
-#define M1064_XCURADDH		0x05
-#define M1064_XCURCTRL		0x06
-#define     M1064_XCURCTRL_DIS		0x00	/* transparent, transparent, transparent, transparent */
-#define     M1064_XCURCTRL_3COLOR	0x01	/* transparent, 0, 1, 2 */
-#define     M1064_XCURCTRL_XGA		0x02	/* 0, 1, transparent, complement */
-#define     M1064_XCURCTRL_XWIN		0x03	/* transparent, transparent, 0, 1 */
-	/* drive DVI by standard(0)/DVI(1) PLL */
-	/* if set(1), C?DVICLKEN and C?DVICLKSEL must be set(1) */
-#define      M1064_XDVICLKCTRL_DVIDATAPATHSEL   0x01
-	/* drive CRTC1 by standard(0)/DVI(1) PLL */
-#define      M1064_XDVICLKCTRL_C1DVICLKSEL      0x02
-	/* drive CRTC2 by standard(0)/DVI(1) PLL */
-#define      M1064_XDVICLKCTRL_C2DVICLKSEL      0x04
-	/* pixel clock allowed to(0)/blocked from(1) driving CRTC1 */
-#define      M1064_XDVICLKCTRL_C1DVICLKEN       0x08
-	/* DVI PLL loop filter bandwidth selection bits */
-#define      M1064_XDVICLKCTRL_DVILOOPCTL       0x30
-	/* CRTC2 pixel clock allowed to(0)/blocked from(1) driving CRTC2 */
-#define      M1064_XDVICLKCTRL_C2DVICLKEN       0x40
-	/* P1PLL loop filter bandwidth selection */
-#define      M1064_XDVICLKCTRL_P1LOOPBWDTCTL    0x80
-#define M1064_XCURCOL0RED	0x08
-#define M1064_XCURCOL0GREEN	0x09
-#define M1064_XCURCOL0BLUE	0x0A
-#define M1064_XCURCOL1RED	0x0C
-#define M1064_XCURCOL1GREEN	0x0D
-#define M1064_XCURCOL1BLUE	0x0E
-#define M1064_XDVICLKCTRL	0x0F
-#define M1064_XCURCOL2RED	0x10
-#define M1064_XCURCOL2GREEN	0x11
-#define M1064_XCURCOL2BLUE	0x12
-#define DAC1064_XVREFCTRL	0x18
-#define      DAC1064_XVREFCTRL_INTERNAL		0x3F
-#define      DAC1064_XVREFCTRL_EXTERNAL		0x00
-#define      DAC1064_XVREFCTRL_G100_DEFAULT	0x03
-#define M1064_XMULCTRL		0x19
-#define      M1064_XMULCTRL_DEPTH_8BPP		0x00	/* 8 bpp paletized */
-#define      M1064_XMULCTRL_DEPTH_15BPP_1BPP	0x01	/* 15 bpp paletized + 1 bpp overlay */
-#define      M1064_XMULCTRL_DEPTH_16BPP		0x02	/* 16 bpp paletized */
-#define      M1064_XMULCTRL_DEPTH_24BPP		0x03	/* 24 bpp paletized */
-#define      M1064_XMULCTRL_DEPTH_24BPP_8BPP	0x04	/* 24 bpp direct + 8 bpp overlay paletized */
-#define      M1064_XMULCTRL_2G8V16		0x05	/* 15 bpp video direct, half xres, 8bpp paletized */
-#define      M1064_XMULCTRL_G16V16		0x06	/* 15 bpp video, 15bpp graphics, one of them paletized */
-#define      M1064_XMULCTRL_DEPTH_32BPP		0x07	/* 24 bpp paletized + 8 bpp unused */
-#define      M1064_XMULCTRL_GRAPHICS_PALETIZED	0x00
-#define      M1064_XMULCTRL_VIDEO_PALETIZED	0x08
-#define M1064_XPIXCLKCTRL	0x1A
-#define      M1064_XPIXCLKCTRL_SRC_PCI		0x00
-#define      M1064_XPIXCLKCTRL_SRC_PLL		0x01
-#define      M1064_XPIXCLKCTRL_SRC_EXT		0x02
-#define	     M1064_XPIXCLKCTRL_SRC_SYS		0x03	/* G200/G400 */
-#define      M1064_XPIXCLKCTRL_SRC_PLL2		0x03	/* G450 */
-#define      M1064_XPIXCLKCTRL_SRC_MASK		0x03
-#define      M1064_XPIXCLKCTRL_EN		0x00
-#define      M1064_XPIXCLKCTRL_DIS		0x04
-#define      M1064_XPIXCLKCTRL_PLL_DOWN		0x00
-#define      M1064_XPIXCLKCTRL_PLL_UP		0x08
-#define M1064_XGENCTRL		0x1D
-#define      M1064_XGENCTRL_VS_0		0x00
-#define      M1064_XGENCTRL_VS_1		0x01
-#define      M1064_XGENCTRL_ALPHA_DIS		0x00
-#define      M1064_XGENCTRL_ALPHA_EN		0x02
-#define      M1064_XGENCTRL_BLACK_0IRE		0x00
-#define      M1064_XGENCTRL_BLACK_75IRE		0x10
-#define      M1064_XGENCTRL_SYNC_ON_GREEN	0x00
-#define      M1064_XGENCTRL_NO_SYNC_ON_GREEN	0x20
-#define      M1064_XGENCTRL_SYNC_ON_GREEN_MASK	0x20
-#define M1064_XMISCCTRL		0x1E
-#define      M1064_XMISCCTRL_DAC_DIS		0x00
-#define      M1064_XMISCCTRL_DAC_EN		0x01
-#define      M1064_XMISCCTRL_MFC_VGA		0x00
-#define      M1064_XMISCCTRL_MFC_MAFC		0x02
-#define      M1064_XMISCCTRL_MFC_DIS		0x06
-#define      GX00_XMISCCTRL_MFC_MAFC		0x02
-#define      GX00_XMISCCTRL_MFC_PANELLINK	0x04
-#define      GX00_XMISCCTRL_MFC_DIS		0x06
-#define      GX00_XMISCCTRL_MFC_MASK		0x06
-#define      M1064_XMISCCTRL_DAC_6BIT		0x00
-#define      M1064_XMISCCTRL_DAC_8BIT		0x08
-#define      M1064_XMISCCTRL_DAC_WIDTHMASK	0x08
-#define      M1064_XMISCCTRL_LUT_DIS		0x00
-#define      M1064_XMISCCTRL_LUT_EN		0x10
-#define      G400_XMISCCTRL_VDO_MAFC12		0x00
-#define      G400_XMISCCTRL_VDO_BYPASS656	0x40
-#define      G400_XMISCCTRL_VDO_C2_MAFC12	0x80
-#define      G400_XMISCCTRL_VDO_C2_BYPASS656	0xC0
-#define      G400_XMISCCTRL_VDO_MASK		0xE0
-#define M1064_XGENIOCTRL	0x2A
-#define M1064_XGENIODATA	0x2B
-#define DAC1064_XSYSPLLM	0x2C
-#define DAC1064_XSYSPLLN	0x2D
-#define DAC1064_XSYSPLLP	0x2E
-#define DAC1064_XSYSPLLSTAT	0x2F
-#define M1064_XZOOMCTRL		0x38
-#define      M1064_XZOOMCTRL_1			0x00
-#define      M1064_XZOOMCTRL_2			0x01
-#define      M1064_XZOOMCTRL_4			0x03
-#define M1064_XSENSETEST	0x3A
-#define      M1064_XSENSETEST_BCOMP		0x01
-#define      M1064_XSENSETEST_GCOMP		0x02
-#define      M1064_XSENSETEST_RCOMP		0x04
-#define      M1064_XSENSETEST_PDOWN		0x00
-#define      M1064_XSENSETEST_PUP		0x80
-#define M1064_XCRCREML		0x3C
-#define M1064_XCRCREMH		0x3D
-#define M1064_XCRCBITSEL	0x3E
-#define M1064_XCOLKEYMASKL	0x40
-#define M1064_XCOLKEYMASKH	0x41
-#define M1064_XCOLKEYL		0x42
-#define M1064_XCOLKEYH		0x43
-#define M1064_XPIXPLLAM		0x44
-#define M1064_XPIXPLLAN		0x45
-#define M1064_XPIXPLLAP		0x46
-#define M1064_XPIXPLLBM		0x48
-#define M1064_XPIXPLLBN		0x49
-#define M1064_XPIXPLLBP		0x4A
-#define M1064_XPIXPLLCM		0x4C
-#define M1064_XPIXPLLCN		0x4D
-#define M1064_XPIXPLLCP		0x4E
-#define M1064_XPIXPLLSTAT	0x4F
-
-#define M1064_XTVO_IDX		0x87
-#define M1064_XTVO_DATA		0x88
-
-#define M1064_XOUTPUTCONN	0x8A
-#define M1064_XSYNCCTRL		0x8B
-#define M1064_XVIDPLLSTAT	0x8C
-#define M1064_XVIDPLLP		0x8D
-#define M1064_XVIDPLLM		0x8E
-#define M1064_XVIDPLLN		0x8F
-
-#define M1064_XPWRCTRL		0xA0
-#define     M1064_XPWRCTRL_PANELPDN	0x04
-
-#define M1064_XPANMODE		0xA2
-
-enum POS1064 {
-	POS1064_XCURADDL=0, POS1064_XCURADDH, POS1064_XCURCTRL,
-	POS1064_XCURCOL0RED, POS1064_XCURCOL0GREEN, POS1064_XCURCOL0BLUE,
-	POS1064_XCURCOL1RED, POS1064_XCURCOL1GREEN, POS1064_XCURCOL1BLUE,
-	POS1064_XCURCOL2RED, POS1064_XCURCOL2GREEN, POS1064_XCURCOL2BLUE,
-	POS1064_XVREFCTRL, POS1064_XMULCTRL, POS1064_XPIXCLKCTRL, POS1064_XGENCTRL,
-	POS1064_XMISCCTRL,
-	POS1064_XGENIOCTRL, POS1064_XGENIODATA, POS1064_XZOOMCTRL, POS1064_XSENSETEST,
-	POS1064_XCRCBITSEL,
-	POS1064_XCOLKEYMASKL, POS1064_XCOLKEYMASKH, POS1064_XCOLKEYL, POS1064_XCOLKEYH,
-	POS1064_XOUTPUTCONN, POS1064_XPANMODE, POS1064_XPWRCTRL };
-
-
-#endif	/* __MATROXFB_DAC1064_H__ */
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c
deleted file mode 100644
index 195ad7cac1ba..000000000000
--- a/drivers/video/matrox/matroxfb_Ti3026.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.65 2002/08/14
- *
- * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
- *
- * Contributors: "menion?" <menion@mindless.com>
- *                     Betatesting, fixes, ideas
- *
- *               "Kurt Garloff" <garloff@suse.de>
- *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
- *
- *               "Tom Rini" <trini@kernel.crashing.org>
- *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
- *
- *               "Bibek Sahu" <scorpio@dodds.net>
- *                     Access device through readb|w|l and write b|w|l
- *                     Extensive debugging stuff
- *
- *               "Daniel Haun" <haund@usa.net>
- *                     Testing, hardware cursor fixes
- *
- *               "Scott Wood" <sawst46+@pitt.edu>
- *                     Fixes
- *
- *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
- *                     Betatesting
- *
- *               "Kelly French" <targon@hazmat.com>
- *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
- *                     Betatesting, bug reporting
- *
- *               "Pablo Bianucci" <pbian@pccp.com.ar>
- *                     Fixes, ideas, betatesting
- *
- *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
- *                     Fixes, enhandcements, ideas, betatesting
- *
- *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
- *                     PPC betatesting, PPC support, backward compatibility
- *
- *               "Paul Womar" <Paul@pwomar.demon.co.uk>
- *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
- *                     PPC betatesting
- *
- *               "Thomas Pornin" <pornin@bolet.ens.fr>
- *                     Alpha betatesting
- *
- *               "Pieter van Leuven" <pvl@iae.nl>
- *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
- *                     G100 testing
- *
- *               "H. Peter Arvin" <hpa@transmeta.com>
- *                     Ideas
- *
- *               "Cort Dougan" <cort@cs.nmt.edu>
- *                     CHRP fixes and PReP cleanup
- *
- *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
- *                     G400 support
- *
- * (following author is not in any relation with this code, but his code
- *  is included in this driver)
- *
- * Based on framebuffer driver for VBE 2.0 compliant graphic boards
- *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- *
- * (following author is not in any relation with this code, but his ideas
- *  were used when writing this driver)
- *
- *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
- *
- */
-
-
-#include "matroxfb_Ti3026.h"
-#include "matroxfb_misc.h"
-#include "matroxfb_accel.h"
-#include <linux/matroxfb.h>
-
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-#define outTi3026 matroxfb_DAC_out
-#define inTi3026 matroxfb_DAC_in
-
-#define TVP3026_INDEX		0x00
-#define TVP3026_PALWRADD	0x00
-#define TVP3026_PALDATA		0x01
-#define TVP3026_PIXRDMSK	0x02
-#define TVP3026_PALRDADD	0x03
-#define TVP3026_CURCOLWRADD	0x04
-#define     TVP3026_CLOVERSCAN		0x00
-#define     TVP3026_CLCOLOR0		0x01
-#define     TVP3026_CLCOLOR1		0x02
-#define     TVP3026_CLCOLOR2		0x03
-#define TVP3026_CURCOLDATA	0x05
-#define TVP3026_CURCOLRDADD	0x07
-#define TVP3026_CURCTRL		0x09
-#define TVP3026_X_DATAREG	0x0A
-#define TVP3026_CURRAMDATA	0x0B
-#define TVP3026_CURPOSXL	0x0C
-#define TVP3026_CURPOSXH	0x0D
-#define TVP3026_CURPOSYL	0x0E
-#define TVP3026_CURPOSYH	0x0F
-
-#define TVP3026_XSILICONREV	0x01
-#define TVP3026_XCURCTRL	0x06
-#define     TVP3026_XCURCTRL_DIS	0x00	/* transparent, transparent, transparent, transparent */
-#define     TVP3026_XCURCTRL_3COLOR	0x01	/* transparent, 0, 1, 2 */
-#define     TVP3026_XCURCTRL_XGA	0x02	/* 0, 1, transparent, complement */
-#define     TVP3026_XCURCTRL_XWIN	0x03	/* transparent, transparent, 0, 1 */
-#define     TVP3026_XCURCTRL_BLANK2048	0x00
-#define     TVP3026_XCURCTRL_BLANK4096	0x10
-#define     TVP3026_XCURCTRL_INTERLACED	0x20
-#define     TVP3026_XCURCTRL_ODD	0x00 /* ext.signal ODD/\EVEN */
-#define     TVP3026_XCURCTRL_EVEN	0x40 /* ext.signal EVEN/\ODD */
-#define     TVP3026_XCURCTRL_INDIRECT	0x00
-#define     TVP3026_XCURCTRL_DIRECT	0x80
-#define TVP3026_XLATCHCTRL	0x0F
-#define     TVP3026_XLATCHCTRL_1_1	0x06
-#define     TVP3026_XLATCHCTRL_2_1	0x07
-#define     TVP3026_XLATCHCTRL_4_1	0x06
-#define     TVP3026_XLATCHCTRL_8_1	0x06
-#define     TVP3026_XLATCHCTRL_16_1	0x06
-#define     TVP3026A_XLATCHCTRL_4_3	0x06	/* ??? do not understand... but it works... !!! */
-#define     TVP3026A_XLATCHCTRL_8_3	0x07
-#define     TVP3026B_XLATCHCTRL_4_3	0x08
-#define     TVP3026B_XLATCHCTRL_8_3	0x06	/* ??? do not understand... but it works... !!! */
-#define TVP3026_XTRUECOLORCTRL	0x18
-#define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL	0x00
-#define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP	0x20
-#define     TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR		0x80
-#define     TVP3026_XTRUECOLORCTRL_TRUECOLOR		0x40 /* paletized */
-#define     TVP3026_XTRUECOLORCTRL_DIRECTCOLOR		0x00
-#define     TVP3026_XTRUECOLORCTRL_24_ALTERNATE		0x08 /* 5:4/5:2 instead of 4:3/8:3 */
-#define     TVP3026_XTRUECOLORCTRL_RGB_888		0x16 /* 4:3/8:3 (or 5:4/5:2) */
-#define	    TVP3026_XTRUECOLORCTRL_BGR_888		0x17
-#define     TVP3026_XTRUECOLORCTRL_ORGB_8888		0x06
-#define     TVP3026_XTRUECOLORCTRL_BGRO_8888		0x07
-#define     TVP3026_XTRUECOLORCTRL_RGB_565		0x05
-#define     TVP3026_XTRUECOLORCTRL_ORGB_1555		0x04
-#define     TVP3026_XTRUECOLORCTRL_RGB_664		0x03
-#define     TVP3026_XTRUECOLORCTRL_RGBO_4444		0x01
-#define TVP3026_XMUXCTRL	0x19
-#define     TVP3026_XMUXCTRL_MEMORY_8BIT			0x01 /* - */
-#define     TVP3026_XMUXCTRL_MEMORY_16BIT			0x02 /* - */
-#define     TVP3026_XMUXCTRL_MEMORY_32BIT			0x03 /* 2MB RAM, 512K * 4 */
-#define     TVP3026_XMUXCTRL_MEMORY_64BIT			0x04 /* >2MB RAM, 512K * 8 & more */
-#define     TVP3026_XMUXCTRL_PIXEL_4BIT				0x40 /* L0,H0,L1,H1... */
-#define     TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED			0x60 /* H0,L0,H1,L1... */
-#define     TVP3026_XMUXCTRL_PIXEL_8BIT				0x48
-#define     TVP3026_XMUXCTRL_PIXEL_16BIT			0x50
-#define     TVP3026_XMUXCTRL_PIXEL_32BIT			0x58
-#define     TVP3026_XMUXCTRL_VGA				0x98 /* VGA MEMORY, 8BIT PIXEL */
-#define TVP3026_XCLKCTRL	0x1A
-#define     TVP3026_XCLKCTRL_DIV1	0x00
-#define     TVP3026_XCLKCTRL_DIV2	0x10
-#define     TVP3026_XCLKCTRL_DIV4	0x20
-#define     TVP3026_XCLKCTRL_DIV8	0x30
-#define     TVP3026_XCLKCTRL_DIV16	0x40
-#define     TVP3026_XCLKCTRL_DIV32	0x50
-#define     TVP3026_XCLKCTRL_DIV64	0x60
-#define     TVP3026_XCLKCTRL_CLKSTOPPED	0x70
-#define     TVP3026_XCLKCTRL_SRC_CLK0	0x00
-#define     TVP3026_XCLKCTRL_SRC_CLK1   0x01
-#define     TVP3026_XCLKCTRL_SRC_CLK2	0x02	/* CLK2 is TTL source*/
-#define     TVP3026_XCLKCTRL_SRC_NCLK2	0x03	/* not CLK2 is TTL source */
-#define     TVP3026_XCLKCTRL_SRC_ECLK2	0x04	/* CLK2 and not CLK2 is ECL source */
-#define     TVP3026_XCLKCTRL_SRC_PLL	0x05
-#define     TVP3026_XCLKCTRL_SRC_DIS	0x06	/* disable & poweroff internal clock */
-#define     TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07
-#define TVP3026_XPALETTEPAGE	0x1C
-#define TVP3026_XGENCTRL	0x1D
-#define     TVP3026_XGENCTRL_HSYNC_POS	0x00
-#define     TVP3026_XGENCTRL_HSYNC_NEG	0x01
-#define     TVP3026_XGENCTRL_VSYNC_POS	0x00
-#define     TVP3026_XGENCTRL_VSYNC_NEG	0x02
-#define     TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00
-#define     TVP3026_XGENCTRL_BIG_ENDIAN    0x08
-#define     TVP3026_XGENCTRL_BLACK_0IRE		0x00
-#define     TVP3026_XGENCTRL_BLACK_75IRE	0x10
-#define     TVP3026_XGENCTRL_NO_SYNC_ON_GREEN	0x00
-#define     TVP3026_XGENCTRL_SYNC_ON_GREEN	0x20
-#define     TVP3026_XGENCTRL_OVERSCAN_DIS	0x00
-#define     TVP3026_XGENCTRL_OVERSCAN_EN	0x40
-#define TVP3026_XMISCCTRL	0x1E
-#define     TVP3026_XMISCCTRL_DAC_PUP	0x00
-#define     TVP3026_XMISCCTRL_DAC_PDOWN	0x01
-#define     TVP3026_XMISCCTRL_DAC_EXT	0x00 /* or 8, bit 3 is ignored */
-#define     TVP3026_XMISCCTRL_DAC_6BIT	0x04
-#define     TVP3026_XMISCCTRL_DAC_8BIT	0x0C
-#define     TVP3026_XMISCCTRL_PSEL_DIS	0x00
-#define     TVP3026_XMISCCTRL_PSEL_EN	0x10
-#define     TVP3026_XMISCCTRL_PSEL_LOW	0x00 /* PSEL high selects directcolor */
-#define     TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */
-#define TVP3026_XGENIOCTRL	0x2A
-#define TVP3026_XGENIODATA	0x2B
-#define TVP3026_XPLLADDR	0x2C
-#define     TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX))
-#define     TVP3026_XPLLDATA_N		0x00
-#define     TVP3026_XPLLDATA_M		0x01
-#define     TVP3026_XPLLDATA_P		0x02
-#define     TVP3026_XPLLDATA_STAT	0x03
-#define TVP3026_XPIXPLLDATA	0x2D
-#define TVP3026_XMEMPLLDATA	0x2E
-#define TVP3026_XLOOPPLLDATA	0x2F
-#define TVP3026_XCOLKEYOVRMIN	0x30
-#define TVP3026_XCOLKEYOVRMAX	0x31
-#define TVP3026_XCOLKEYREDMIN	0x32
-#define TVP3026_XCOLKEYREDMAX	0x33
-#define TVP3026_XCOLKEYGREENMIN	0x34
-#define TVP3026_XCOLKEYGREENMAX	0x35
-#define TVP3026_XCOLKEYBLUEMIN	0x36
-#define TVP3026_XCOLKEYBLUEMAX	0x37
-#define TVP3026_XCOLKEYCTRL	0x38
-#define     TVP3026_XCOLKEYCTRL_OVR_EN	0x01
-#define     TVP3026_XCOLKEYCTRL_RED_EN	0x02
-#define     TVP3026_XCOLKEYCTRL_GREEN_EN 0x04
-#define     TVP3026_XCOLKEYCTRL_BLUE_EN	0x08
-#define     TVP3026_XCOLKEYCTRL_NEGATE	0x10
-#define     TVP3026_XCOLKEYCTRL_ZOOM1	0x00
-#define     TVP3026_XCOLKEYCTRL_ZOOM2	0x20
-#define     TVP3026_XCOLKEYCTRL_ZOOM4	0x40
-#define     TVP3026_XCOLKEYCTRL_ZOOM8	0x60
-#define     TVP3026_XCOLKEYCTRL_ZOOM16	0x80
-#define     TVP3026_XCOLKEYCTRL_ZOOM32	0xA0
-#define TVP3026_XMEMPLLCTRL	0x39
-#define     TVP3026_XMEMPLLCTRL_DIV(X)	(((X)-1)>>1)	/* 2,4,6,8,10,12,14,16, division applied to LOOP PLL after divide by 2^P */
-#define     TVP3026_XMEMPLLCTRL_STROBEMKC4	0x08
-#define     TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK	0x00	/* MKC4 */
-#define     TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL	0x10	/* MKC4 */
-#define     TVP3026_XMEMPLLCTRL_RCLK_PIXPLL	0x00
-#define     TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL	0x20
-#define     TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN	0x40	/* dot clock divided by loop pclk N prescaler */
-#define TVP3026_XSENSETEST	0x3A
-#define TVP3026_XTESTMODEDATA	0x3B
-#define TVP3026_XCRCREML	0x3C
-#define TVP3026_XCRCREMH	0x3D
-#define TVP3026_XCRCBITSEL	0x3E
-#define TVP3026_XID		0x3F
-
-static const unsigned char DACseq[] =
-{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL,
-  TVP3026_XMUXCTRL, TVP3026_XCLKCTRL,
-  TVP3026_XPALETTEPAGE,
-  TVP3026_XGENCTRL,
-  TVP3026_XMISCCTRL,
-  TVP3026_XGENIOCTRL,
-  TVP3026_XGENIODATA,
-  TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX,
-  TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX,
-  TVP3026_XCOLKEYCTRL,
-  TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL };
-
-#define POS3026_XLATCHCTRL	0
-#define POS3026_XTRUECOLORCTRL	1
-#define POS3026_XMUXCTRL	2
-#define POS3026_XCLKCTRL	3
-#define POS3026_XGENCTRL	5
-#define POS3026_XMISCCTRL	6
-#define POS3026_XMEMPLLCTRL	18
-#define POS3026_XCURCTRL	20
-
-static const unsigned char MGADACbpp32[] =
-{ TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888,
-  0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL,
-  0x00,
-  TVP3026_XGENCTRL_HSYNC_POS | TVP3026_XGENCTRL_VSYNC_POS | TVP3026_XGENCTRL_LITTLE_ENDIAN | TVP3026_XGENCTRL_BLACK_0IRE | TVP3026_XGENCTRL_NO_SYNC_ON_GREEN | TVP3026_XGENCTRL_OVERSCAN_DIS,
-  TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH,
-  0x00,
-  0x1E,
-  0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF,
-  TVP3026_XCOLKEYCTRL_ZOOM1,
-  0x00, 0x00, TVP3026_XCURCTRL_DIS };
-
-static int Ti3026_calcclock(const struct matrox_fb_info *minfo,
-			    unsigned int freq, unsigned int fmax, int *in,
-			    int *feed, int *post)
-{
-	unsigned int fvco;
-	unsigned int lin, lfeed, lpost;
-
-	DBG(__func__)
-
-	fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost);
-	fvco >>= (*post = lpost);
-	*in = 64 - lin;
-	*feed = 64 - lfeed;
-	return fvco;
-}
-
-static int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk)
-{
-	unsigned int f_pll;
-	unsigned int pixfeed, pixin, pixpost;
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost);
-
-	hw->DACclk[0] = pixin | 0xC0;
-	hw->DACclk[1] = pixfeed;
-	hw->DACclk[2] = pixpost | 0xB0;
-
-	{
-		unsigned int loopfeed, loopin, looppost, loopdiv, z;
-		unsigned int Bpp;
-
-		Bpp = minfo->curr.final_bppShift;
-
-		if (minfo->fbcon.var.bits_per_pixel == 24) {
-			loopfeed = 3;		/* set lm to any possible value */
-			loopin = 3 * 32 / Bpp;
-		} else {
-			loopfeed = 4;
-			loopin = 4 * 32 / Bpp;
-		}
-		z = (110000 * loopin) / (f_pll * loopfeed);
-		loopdiv = 0; /* div 2 */
-		if (z < 2)
-			looppost = 0;
-		else if (z < 4)
-			looppost = 1;
-		else if (z < 8)
-			looppost = 2;
-		else {
-			looppost = 3;
-			loopdiv = z/16;
-		}
-		if (minfo->fbcon.var.bits_per_pixel == 24) {
-			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
-			hw->DACclk[4] = (65 - loopfeed) | 0x80;
-			if (minfo->accel.ramdac_rev > 0x20) {
-				if (isInterleave(minfo))
-					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
-				else {
-					hw->DACclk[4] &= ~0xC0;
-					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
-				}
-			} else {
-				if (isInterleave(minfo))
-					;	/* default... */
-				else {
-					hw->DACclk[4] ^= 0xC0;	/* change from 0x80 to 0x40 */
-					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
-				}
-			}
-			hw->DACclk[5] = looppost | 0xF8;
-			if (minfo->devflags.mga_24bpp_fix)
-				hw->DACclk[5] ^= 0x40;
-		} else {
-			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
-			hw->DACclk[4] = 65 - loopfeed;
-			hw->DACclk[5] = looppost | 0xF0;
-		}
-		hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
-	}
-	return 0;
-}
-
-static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
-{
-	u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
-	switch (minfo->fbcon.var.bits_per_pixel) {
-		case 4:	hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1;	/* or _8_1, they are same */
-			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
-			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
-			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8;
-			hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
-			break;
-		case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1;	/* or _4_1, they are same */
-			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
-			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT;
-			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
-			hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
-			break;
-		case 16:
-			/* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */
-			hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
-			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
-			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
-			break;
-		case 24:
-			/* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */
-			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888;
-			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
-			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
-			break;
-		case 32:
-			/* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */
-			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
-			break;
-		default:
-			return 1;	/* TODO: failed */
-	}
-	if (matroxfb_vgaHWinit(minfo, m)) return 1;
-
-	/* set SYNC */
-	hw->MiscOutReg = 0xCB;
-	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
-		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG;
-	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
-		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG;
-	if (m->sync & FB_SYNC_ON_GREEN)
-		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
-
-	/* set DELAY */
-	if (minfo->video.len < 0x400000)
-		hw->CRTCEXT[3] |= 0x08;
-	else if (minfo->video.len > 0x400000)
-		hw->CRTCEXT[3] |= 0x10;
-
-	/* set HWCURSOR */
-	if (m->interlaced) {
-		hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED;
-	}
-	if (m->HTotal >= 1536)
-		hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096;
-
-	/* set interleaving */
-	hw->MXoptionReg &= ~0x00001000;
-	if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000;
-
-	/* set DAC */
-	Ti3026_setpclk(minfo, m->pixclock);
-	return 0;
-}
-
-static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout)
-{
-	unsigned int f_pll;
-	unsigned int pclk_m, pclk_n, pclk_p;
-	unsigned int mclk_m, mclk_n, mclk_p;
-	unsigned int rfhcnt, mclk_ctl;
-	int tmout;
-
-	DBG(__func__)
-
-	f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p);
-
-	/* save pclk */
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
-	pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA);
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFD);
-	pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA);
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
-	pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA);
-
-	/* stop pclk */
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
-
-	/* set pclk to new mclk */
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0);
-
-	/* wait for PLL to lock */
-	for (tmout = 500000; tmout; tmout--) {
-		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
-			break;
-		udelay(10);
-	}
-	if (!tmout)
-		printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");
-
-	/* output pclk on mclk pin */
-	mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL);
-	outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
-	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);
-
-	/* stop MCLK */
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFB);
-	outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00);
-
-	/* set mclk to new freq */
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xF3);
-	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
-	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m);
-	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0);
-
-	/* wait for PLL to lock */
-	for (tmout = 500000; tmout; tmout--) {
-		if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40)
-			break;
-		udelay(10);
-	}
-	if (!tmout)
-		printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");
-
-	f_pll = f_pll * 333 / (10000 << mclk_p);
-	if (isMilleniumII(minfo)) {
-		rfhcnt = (f_pll - 128) / 256;
-		if (rfhcnt > 15)
-			rfhcnt = 15;
-	} else {
-		rfhcnt = (f_pll - 64) / 128;
-		if (rfhcnt > 15)
-			rfhcnt = 0;
-	}
-	minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
-
-	/* output MCLK to MCLK pin */
-	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
-	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl       ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);
-
-	/* stop PCLK */
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
-
-	/* restore pclk */
-	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p);
-
-	/* wait for PLL to lock */
-	for (tmout = 500000; tmout; tmout--) {
-		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
-			break;
-		udelay(10);
-	}
-	if (!tmout)
-		printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
-}
-
-static void ti3026_ramdac_init(struct matrox_fb_info *minfo)
-{
-	DBG(__func__)
-
-	minfo->features.pll.vco_freq_min = 110000;
-	minfo->features.pll.ref_freq	 = 114545;
-	minfo->features.pll.feed_div_min = 2;
-	minfo->features.pll.feed_div_max = 24;
-	minfo->features.pll.in_div_min	 = 2;
-	minfo->features.pll.in_div_max	 = 63;
-	minfo->features.pll.post_shift_max = 3;
-	if (minfo->devflags.noinit)
-		return;
-	ti3026_setMCLK(minfo, 60000);
-}
-
-static void Ti3026_restore(struct matrox_fb_info *minfo)
-{
-	int i;
-	unsigned char progdac[6];
-	struct matrox_hw_state *hw = &minfo->hw;
-	CRITFLAGS
-
-	DBG(__func__)
-
-#ifdef DEBUG
-	dprintk(KERN_INFO "EXTVGA regs: ");
-	for (i = 0; i < 6; i++)
-		dprintk("%02X:", hw->CRTCEXT[i]);
-	dprintk("\n");
-#endif
-
-	CRITBEGIN
-
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-
-	CRITEND
-
-	matroxfb_vgaHWrestore(minfo);
-
-	CRITBEGIN
-
-	minfo->crtc1.panpos = -1;
-	for (i = 0; i < 6; i++)
-		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
-
-	for (i = 0; i < 21; i++) {
-		outTi3026(minfo, DACseq[i], hw->DACreg[i]);
-	}
-
-	outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
-	progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
-	progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
-	outTi3026(minfo, TVP3026_XPLLADDR, 0x15);
-	progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
-	progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
-	outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
-	progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
-	progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
-
-	CRITEND
-	if (memcmp(hw->DACclk, progdac, 6)) {
-		/* agrhh... setting up PLL is very slow on Millennium... */
-		/* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
-		/* Maybe even we should call schedule() ? */
-
-		CRITBEGIN
-		outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
-		outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
-		outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0);
-		outTi3026(minfo, TVP3026_XPIXPLLDATA, 0);
-
-		outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
-		for (i = 0; i < 3; i++)
-			outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]);
-		/* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
-		if (hw->MiscOutReg & 0x08) {
-			int tmout;
-			outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
-			for (tmout = 500000; tmout; --tmout) {
-				if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
-					break;
-				udelay(10);
-			}
-
-			CRITEND
-
-			if (!tmout)
-				printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
-			else
-				dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
-			CRITBEGIN
-		}
-		outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
-		outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
-		for (i = 3; i < 6; i++)
-			outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
-		CRITEND
-		if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
-			int tmout;
-
-			CRITBEGIN
-			outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
-			for (tmout = 500000; tmout; --tmout) {
-				if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40)
-					break;
-				udelay(10);
-			}
-			CRITEND
-			if (!tmout)
-				printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
-			else
-				dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout);
-		}
-	}
-
-#ifdef DEBUG
-	dprintk(KERN_DEBUG "3026DACregs ");
-	for (i = 0; i < 21; i++) {
-		dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
-		if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
-	}
-	dprintk(KERN_DEBUG "DACclk ");
-	for (i = 0; i < 6; i++)
-		dprintk("C%02X=%02X ", i, hw->DACclk[i]);
-	dprintk("\n");
-#endif
-}
-
-static void Ti3026_reset(struct matrox_fb_info *minfo)
-{
-	DBG(__func__)
-
-	ti3026_ramdac_init(minfo);
-}
-
-static struct matrox_altout ti3026_output = {
-	.name	 = "Primary output",
-};
-
-static int Ti3026_preinit(struct matrox_fb_info *minfo)
-{
-	static const int vxres_mill2[] = { 512,        640, 768,  800,  832,  960,
-					  1024, 1152, 1280,      1600, 1664, 1920,
-					  2048, 0};
-	static const int vxres_mill1[] = {             640, 768,  800,        960,
-					  1024, 1152, 1280,      1600,       1920,
-					  2048, 0};
-	struct matrox_hw_state *hw = &minfo->hw;
-
-	DBG(__func__)
-
-	minfo->millenium = 1;
-	minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL);
-	minfo->capable.cfb4 = 1;
-	minfo->capable.text = 1; /* isMilleniumII(minfo); */
-	minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1;
-
-	minfo->outputs[0].data = minfo;
-	minfo->outputs[0].output = &ti3026_output;
-	minfo->outputs[0].src = minfo->outputs[0].default_src;
-	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-
-	if (minfo->devflags.noinit)
-		return 0;
-	/* preserve VGA I/O, BIOS and PPC */
-	hw->MXoptionReg &= 0xC0000100;
-	hw->MXoptionReg |= 0x002C0000;
-	if (minfo->devflags.novga)
-		hw->MXoptionReg &= ~0x00000100;
-	if (minfo->devflags.nobios)
-		hw->MXoptionReg &= ~0x40000000;
-	if (minfo->devflags.nopciretry)
-		hw->MXoptionReg |=  0x20000000;
-	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
-
-	minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV);
-
-	outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
-	outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR);
-	outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA);
-
-	outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
-	outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00);
-	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
-
-	mga_outb(M_MISC_REG, 0x67);
-
-	outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
-
-	mga_outl(M_RESET, 1);
-	udelay(250);
-	mga_outl(M_RESET, 0);
-	udelay(250);
-	mga_outl(M_MACCESS, 0x00008000);
-	udelay(10);
-	return 0;
-}
-
-struct matrox_switch matrox_millennium = {
-	Ti3026_preinit, Ti3026_reset, Ti3026_init, Ti3026_restore
-};
-EXPORT_SYMBOL(matrox_millennium);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_Ti3026.h b/drivers/video/matrox/matroxfb_Ti3026.h
deleted file mode 100644
index 27872aaa0a17..000000000000
--- a/drivers/video/matrox/matroxfb_Ti3026.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __MATROXFB_TI3026_H__
-#define __MATROXFB_TI3026_H__
-
-
-#include "matroxfb_base.h"
-
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-extern struct matrox_switch matrox_millennium;
-#endif
-
-#endif	/* __MATROXFB_TI3026_H__ */
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
deleted file mode 100644
index 0d5cb85d071a..000000000000
--- a/drivers/video/matrox/matroxfb_accel.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Version: 1.65 2002/08/14
- *
- * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
- *
- * Contributors: "menion?" <menion@mindless.com>
- *                     Betatesting, fixes, ideas
- *
- *               "Kurt Garloff" <garloff@suse.de>
- *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
- *
- *               "Tom Rini" <trini@kernel.crashing.org>
- *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
- *
- *               "Bibek Sahu" <scorpio@dodds.net>
- *                     Access device through readb|w|l and write b|w|l
- *                     Extensive debugging stuff
- *
- *               "Daniel Haun" <haund@usa.net>
- *                     Testing, hardware cursor fixes
- *
- *               "Scott Wood" <sawst46+@pitt.edu>
- *                     Fixes
- *
- *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
- *                     Betatesting
- *
- *               "Kelly French" <targon@hazmat.com>
- *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
- *                     Betatesting, bug reporting
- *
- *               "Pablo Bianucci" <pbian@pccp.com.ar>
- *                     Fixes, ideas, betatesting
- *
- *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
- *                     Fixes, enhandcements, ideas, betatesting
- *
- *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
- *                     PPC betatesting, PPC support, backward compatibility
- *
- *               "Paul Womar" <Paul@pwomar.demon.co.uk>
- *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
- *                     PPC betatesting
- *
- *               "Thomas Pornin" <pornin@bolet.ens.fr>
- *                     Alpha betatesting
- *
- *               "Pieter van Leuven" <pvl@iae.nl>
- *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
- *                     G100 testing
- *
- *               "H. Peter Arvin" <hpa@transmeta.com>
- *                     Ideas
- *
- *               "Cort Dougan" <cort@cs.nmt.edu>
- *                     CHRP fixes and PReP cleanup
- *
- *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
- *                     G400 support
- *
- * (following author is not in any relation with this code, but his code
- *  is included in this driver)
- *
- * Based on framebuffer driver for VBE 2.0 compliant graphic boards
- *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- *
- * (following author is not in any relation with this code, but his ideas
- *  were used when writing this driver)
- *
- *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
- *
- */
-
-#include "matroxfb_accel.h"
-#include "matroxfb_DAC1064.h"
-#include "matroxfb_Ti3026.h"
-#include "matroxfb_misc.h"
-
-#define curr_ydstorg(x)	((x)->curr.ydstorg.pixels)
-
-#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
-
-static inline void matrox_cfb4_pal(u_int32_t* pal) {
-	unsigned int i;
-	
-	for (i = 0; i < 16; i++) {
-		pal[i] = i * 0x11111111U;
-	}
-}
-
-static inline void matrox_cfb8_pal(u_int32_t* pal) {
-	unsigned int i;
-	
-	for (i = 0; i < 16; i++) {
-		pal[i] = i * 0x01010101U;
-	}
-}
-
-static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area);
-static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
-static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image);
-static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
-static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area);
-
-void matrox_cfbX_init(struct matrox_fb_info *minfo)
-{
-	u_int32_t maccess;
-	u_int32_t mpitch;
-	u_int32_t mopmode;
-	int accel;
-
-	DBG(__func__)
-
-	mpitch = minfo->fbcon.var.xres_virtual;
-
-	minfo->fbops.fb_copyarea = cfb_copyarea;
-	minfo->fbops.fb_fillrect = cfb_fillrect;
-	minfo->fbops.fb_imageblit = cfb_imageblit;
-	minfo->fbops.fb_cursor = NULL;
-
-	accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT;
-
-	switch (minfo->fbcon.var.bits_per_pixel) {
-		case 4:		maccess = 0x00000000;	/* accelerate as 8bpp video */
-				mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
-				mopmode = M_OPMODE_4BPP;
-				matrox_cfb4_pal(minfo->cmap);
-				if (accel && !(mpitch & 1)) {
-					minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea;
-					minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect;
-				}
-				break;
-		case 8:		maccess = 0x00000000;
-				mopmode = M_OPMODE_8BPP;
-				matrox_cfb8_pal(minfo->cmap);
-				if (accel) {
-					minfo->fbops.fb_copyarea = matroxfb_copyarea;
-					minfo->fbops.fb_fillrect = matroxfb_fillrect;
-					minfo->fbops.fb_imageblit = matroxfb_imageblit;
-				}
-				break;
-		case 16:	if (minfo->fbcon.var.green.length == 5)
-					maccess = 0xC0000001;
-				else
-					maccess = 0x40000001;
-				mopmode = M_OPMODE_16BPP;
-				if (accel) {
-					minfo->fbops.fb_copyarea = matroxfb_copyarea;
-					minfo->fbops.fb_fillrect = matroxfb_fillrect;
-					minfo->fbops.fb_imageblit = matroxfb_imageblit;
-				}
-				break;
-		case 24:	maccess = 0x00000003;
-				mopmode = M_OPMODE_24BPP;
-				if (accel) {
-					minfo->fbops.fb_copyarea = matroxfb_copyarea;
-					minfo->fbops.fb_fillrect = matroxfb_fillrect;
-					minfo->fbops.fb_imageblit = matroxfb_imageblit;
-				}
-				break;
-		case 32:	maccess = 0x00000002;
-				mopmode = M_OPMODE_32BPP;
-				if (accel) {
-					minfo->fbops.fb_copyarea = matroxfb_copyarea;
-					minfo->fbops.fb_fillrect = matroxfb_fillrect;
-					minfo->fbops.fb_imageblit = matroxfb_imageblit;
-				}
-				break;
-		default:	maccess = 0x00000000;
-				mopmode = 0x00000000;
-				break;	/* turn off acceleration!!! */
-	}
-	mga_fifo(8);
-	mga_outl(M_PITCH, mpitch);
-	mga_outl(M_YDSTORG, curr_ydstorg(minfo));
-	if (minfo->capable.plnwt)
-		mga_outl(M_PLNWT, -1);
-	if (minfo->capable.srcorg) {
-		mga_outl(M_SRCORG, 0);
-		mga_outl(M_DSTORG, 0);
-	}
-	mga_outl(M_OPMODE, mopmode);
-	mga_outl(M_CXBNDRY, 0xFFFF0000);
-	mga_outl(M_YTOP, 0);
-	mga_outl(M_YBOT, 0x01FFFFFF);
-	mga_outl(M_MACCESS, maccess);
-	minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
-	if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
-	minfo->accel.m_opmode = mopmode;
-	minfo->accel.m_access = maccess;
-	minfo->accel.m_pitch = mpitch;
-}
-
-EXPORT_SYMBOL(matrox_cfbX_init);
-
-static void matrox_accel_restore_maccess(struct matrox_fb_info *minfo)
-{
-	mga_outl(M_MACCESS, minfo->accel.m_access);
-	mga_outl(M_PITCH, minfo->accel.m_pitch);
-}
-
-static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
-			       int sx, int dy, int dx, int height, int width)
-{
-	int start, end;
-	CRITFLAGS
-
-	DBG(__func__)
-
-	CRITBEGIN
-
-	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
-		mga_fifo(4);
-		matrox_accel_restore_maccess(minfo);
-		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
-			 M_DWG_BFCOL | M_DWG_REPLACE);
-		mga_outl(M_AR5, vxres);
-		width--;
-		start = sy*vxres+sx+curr_ydstorg(minfo);
-		end = start+width;
-	} else {
-		mga_fifo(5);
-		matrox_accel_restore_maccess(minfo);
-		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
-		mga_outl(M_SGN, 5);
-		mga_outl(M_AR5, -vxres);
-		width--;
-		end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
-		start = end+width;
-		dy += height-1;
-	}
-	mga_fifo(6);
-	matrox_accel_restore_maccess(minfo);
-	mga_outl(M_AR0, end);
-	mga_outl(M_AR3, start);
-	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
-	mga_ydstlen(dy, height);
-	WaitTillIdle();
-
-	CRITEND
-}
-
-static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
-				   int sy, int sx, int dy, int dx, int height,
-				   int width)
-{
-	int start, end;
-	CRITFLAGS
-
-	DBG(__func__)
-
-	CRITBEGIN
-
-	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
-		mga_fifo(4);
-		matrox_accel_restore_maccess(minfo);
-		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
-			M_DWG_BFCOL | M_DWG_REPLACE);
-		mga_outl(M_AR5, vxres);
-		width--;
-		start = sy*vxres+sx+curr_ydstorg(minfo);
-		end = start+width;
-	} else {
-		mga_fifo(5);
-		matrox_accel_restore_maccess(minfo);
-		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
-		mga_outl(M_SGN, 5);
-		mga_outl(M_AR5, -vxres);
-		width--;
-		end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
-		start = end+width;
-		dy += height-1;
-	}
-	mga_fifo(7);
-	matrox_accel_restore_maccess(minfo);
-	mga_outl(M_AR0, end);
-	mga_outl(M_AR3, start);
-	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
-	mga_outl(M_YDST, dy*vxres >> 5);
-	mga_outl(M_LEN | M_EXEC, height);
-	WaitTillIdle();
-
-	CRITEND
-}
-
-static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	if ((area->sx | area->dx | area->width) & 1)
-		cfb_copyarea(info, area);
-	else
-		matrox_accel_bmove_lin(minfo, minfo->fbcon.var.xres_virtual >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1);
-}
-
-static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width);
-}
-
-static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
-				 int sy, int sx, int height, int width)
-{
-	CRITFLAGS
-
-	DBG(__func__)
-
-	CRITBEGIN
-
-	mga_fifo(7);
-	matrox_accel_restore_maccess(minfo);
-	mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
-	mga_outl(M_FCOL, color);
-	mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
-	mga_ydstlen(sy, height);
-	WaitTillIdle();
-
-	CRITEND
-}
-
-static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	switch (rect->rop) {
-		case ROP_COPY:
-			matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
-			break;
-	}
-}
-
-static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
-				int sy, int sx, int height, int width)
-{
-	int whattodo;
-	CRITFLAGS
-
-	DBG(__func__)
-
-	CRITBEGIN
-
-	whattodo = 0;
-	if (sx & 1) {
-		sx ++;
-		if (!width) return;
-		width --;
-		whattodo = 1;
-	}
-	if (width & 1) {
-		whattodo |= 2;
-	}
-	width >>= 1;
-	sx >>= 1;
-	if (width) {
-		mga_fifo(7);
-		matrox_accel_restore_maccess(minfo);
-		mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
-		mga_outl(M_FCOL, bgx);
-		mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
-		mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6);
-		mga_outl(M_LEN | M_EXEC, height);
-		WaitTillIdle();
-	}
-	if (whattodo) {
-		u_int32_t step = minfo->fbcon.var.xres_virtual >> 1;
-		vaddr_t vbase = minfo->video.vbase;
-		if (whattodo & 1) {
-			unsigned int uaddr = sy * step + sx - 1;
-			u_int32_t loop;
-			u_int8_t bgx2 = bgx & 0xF0;
-			for (loop = height; loop > 0; loop --) {
-				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
-				uaddr += step;
-			}
-		}
-		if (whattodo & 2) {
-			unsigned int uaddr = sy * step + sx + width;
-			u_int32_t loop;
-			u_int8_t bgx2 = bgx & 0x0F;
-			for (loop = height; loop > 0; loop --) {
-				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
-				uaddr += step;
-			}
-		}
-	}
-
-	CRITEND
-}
-
-static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	switch (rect->rop) {
-		case ROP_COPY:
-			matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
-			break;
-	}
-}
-
-static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
-				    u_int32_t bgx, const u_int8_t *chardata,
-				    int width, int height, int yy, int xx)
-{
-	u_int32_t step;
-	u_int32_t ydstlen;
-	u_int32_t xlen;
-	u_int32_t ar0;
-	u_int32_t charcell;
-	u_int32_t fxbndry;
-	vaddr_t mmio;
-	int easy;
-	CRITFLAGS
-
-	DBG_HEAVY(__func__);
-
-	step = (width + 7) >> 3;
-	charcell = height * step;
-	xlen = (charcell + 3) & ~3;
-	ydstlen = (yy << 16) | height;
-	if (width == step << 3) {
-		ar0 = height * width - 1;
-		easy = 1;
-	} else {
-		ar0 = width - 1;
-		easy = 0;
-	}
-
-	CRITBEGIN
-
-	mga_fifo(5);
-	matrox_accel_restore_maccess(minfo);
-	if (easy)
-		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
-	else
-		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
-	mga_outl(M_FCOL, fgx);
-	mga_outl(M_BCOL, bgx);
-	fxbndry = ((xx + width - 1) << 16) | xx;
-	mmio = minfo->mmio.vbase;
-
-	mga_fifo(8);
-	matrox_accel_restore_maccess(minfo);
-	mga_writel(mmio, M_FXBNDRY, fxbndry);
-	mga_writel(mmio, M_AR0, ar0);
-	mga_writel(mmio, M_AR3, 0);
-	if (easy) {
-		mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
-		mga_memcpy_toio(mmio, chardata, xlen);
-	} else {
-		mga_writel(mmio, M_AR5, 0);
-		mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
-		if ((step & 3) == 0) {
-			/* Great. Source has 32bit aligned lines, so we can feed them
-			   directly to the accelerator. */
-			mga_memcpy_toio(mmio, chardata, charcell);
-		} else if (step == 1) {
-			/* Special case for 1..8bit widths */
-			while (height--) {
-#if defined(__BIG_ENDIAN)
-				fb_writel((*chardata) << 24, mmio.vaddr);
-#else
-				fb_writel(*chardata, mmio.vaddr);
-#endif
-				chardata++;
-			}
-		} else if (step == 2) {
-			/* Special case for 9..15bit widths */
-			while (height--) {
-#if defined(__BIG_ENDIAN)
-				fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr);
-#else
-				fb_writel(*(u_int16_t*)chardata, mmio.vaddr);
-#endif
-				chardata += 2;
-			}
-		} else {
-			/* Tell... well, why bother... */
-			while (height--) {
-				size_t i;
-				
-				for (i = 0; i < step; i += 4) {
-					/* Hope that there are at least three readable bytes beyond the end of bitmap */
-					fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
-				}
-				chardata += step;
-			}
-		}
-	}
-	WaitTillIdle();
-	CRITEND
-}
-
-
-static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) {
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	DBG_HEAVY(__func__);
-
-	if (image->depth == 1) {
-		u_int32_t fgx, bgx;
-
-		fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color];
-		bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color];
-		matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx);
-	} else {
-		/* Danger! image->depth is useless: logo painting code always
-		   passes framebuffer color depth here, although logo data are
-		   always 8bpp and info->pseudo_palette is changed to contain
-		   logo palette to be used (but only for true/direct-color... sic...).
-		   So do it completely in software... */
-		cfb_imageblit(info, image);
-	}
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_accel.h b/drivers/video/matrox/matroxfb_accel.h
deleted file mode 100644
index 1e418e62c22d..000000000000
--- a/drivers/video/matrox/matroxfb_accel.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __MATROXFB_ACCEL_H__
-#define __MATROXFB_ACCEL_H__
-
-#include "matroxfb_base.h"
-
-void matrox_cfbX_init(struct matrox_fb_info *minfo);
-
-#endif
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
deleted file mode 100644
index 7116c5309c7d..000000000000
--- a/drivers/video/matrox/matroxfb_base.c
+++ /dev/null
@@ -1,2584 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.65 2002/08/14
- *
- * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
- *
- * Contributors: "menion?" <menion@mindless.com>
- *                     Betatesting, fixes, ideas
- *
- *               "Kurt Garloff" <garloff@suse.de>
- *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
- *
- *               "Tom Rini" <trini@kernel.crashing.org>
- *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
- *
- *               "Bibek Sahu" <scorpio@dodds.net>
- *                     Access device through readb|w|l and write b|w|l
- *                     Extensive debugging stuff
- *
- *               "Daniel Haun" <haund@usa.net>
- *                     Testing, hardware cursor fixes
- *
- *               "Scott Wood" <sawst46+@pitt.edu>
- *                     Fixes
- *
- *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
- *                     Betatesting
- *
- *               "Kelly French" <targon@hazmat.com>
- *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
- *                     Betatesting, bug reporting
- *
- *               "Pablo Bianucci" <pbian@pccp.com.ar>
- *                     Fixes, ideas, betatesting
- *
- *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
- *                     Fixes, enhandcements, ideas, betatesting
- *
- *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
- *                     PPC betatesting, PPC support, backward compatibility
- *
- *               "Paul Womar" <Paul@pwomar.demon.co.uk>
- *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
- *                     PPC betatesting
- *
- *               "Thomas Pornin" <pornin@bolet.ens.fr>
- *                     Alpha betatesting
- *
- *               "Pieter van Leuven" <pvl@iae.nl>
- *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
- *                     G100 testing
- *
- *               "H. Peter Arvin" <hpa@transmeta.com>
- *                     Ideas
- *
- *               "Cort Dougan" <cort@cs.nmt.edu>
- *                     CHRP fixes and PReP cleanup
- *
- *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
- *                     G400 support
- *
- *               "Samuel Hocevar" <sam@via.ecp.fr>
- *                     Fixes
- *
- *               "Anton Altaparmakov" <AntonA@bigfoot.com>
- *                     G400 MAX/non-MAX distinction
- *
- *               "Ken Aaker" <kdaaker@rchland.vnet.ibm.com>
- *                     memtype extension (needed for GXT130P RS/6000 adapter)
- *
- *               "Uns Lider" <unslider@miranda.org>
- *                     G100 PLNWT fixes
- *
- *               "Denis Zaitsev" <zzz@cd-club.ru>
- *                     Fixes
- *
- *               "Mike Pieper" <mike@pieper-family.de>
- *                     TVOut enhandcements, V4L2 control interface.
- *
- *               "Diego Biurrun" <diego@biurrun.de>
- *                     DFP testing
- *
- * (following author is not in any relation with this code, but his code
- *  is included in this driver)
- *
- * Based on framebuffer driver for VBE 2.0 compliant graphic boards
- *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- *
- * (following author is not in any relation with this code, but his ideas
- *  were used when writing this driver)
- *
- *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
- *
- */
-
-#include <linux/version.h>
-
-#include "matroxfb_base.h"
-#include "matroxfb_misc.h"
-#include "matroxfb_accel.h"
-#include "matroxfb_DAC1064.h"
-#include "matroxfb_Ti3026.h"
-#include "matroxfb_maven.h"
-#include "matroxfb_crtc2.h"
-#include "matroxfb_g450.h"
-#include <linux/matroxfb.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-unsigned char nvram_read_byte(int);
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
-#endif
-
-static void matroxfb_unregister_device(struct matrox_fb_info* minfo);
-
-/* --------------------------------------------------------------------- */
-
-/*
- * card parameters
- */
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo vesafb_defined = {
-	640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/
-	0,0,		/* virtual -> visible no offset */
-	8,		/* depth -> load bits_per_pixel */
-	0,		/* greyscale ? */
-	{0,0,0},	/* R */
-	{0,0,0},	/* G */
-	{0,0,0},	/* B */
-	{0,0,0},	/* transparency */
-	0,		/* standard pixel format */
-	FB_ACTIVATE_NOW,
-	-1,-1,
-	FB_ACCELF_TEXT,	/* accel flags */
-	39721L,48L,16L,33L,10L,
-	96L,2L,~0,	/* No sync info */
-	FB_VMODE_NONINTERLACED,
-};
-
-
-
-/* --------------------------------------------------------------------- */
-static void update_crtc2(struct matrox_fb_info *minfo, unsigned int pos)
-{
-	struct matroxfb_dh_fb_info *info = minfo->crtc2.info;
-
-	/* Make sure that displays are compatible */
-	if (info && (info->fbcon.var.bits_per_pixel == minfo->fbcon.var.bits_per_pixel)
-		 && (info->fbcon.var.xres_virtual == minfo->fbcon.var.xres_virtual)
-		 && (info->fbcon.var.green.length == minfo->fbcon.var.green.length)
-		 ) {
-		switch (minfo->fbcon.var.bits_per_pixel) {
-			case 16:
-			case 32:
-				pos = pos * 8;
-				if (info->interlaced) {
-					mga_outl(0x3C2C, pos);
-					mga_outl(0x3C28, pos + minfo->fbcon.var.xres_virtual * minfo->fbcon.var.bits_per_pixel / 8);
-				} else {
-					mga_outl(0x3C28, pos);
-				}
-				break;
-		}
-	}
-}
-
-static void matroxfb_crtc1_panpos(struct matrox_fb_info *minfo)
-{
-	if (minfo->crtc1.panpos >= 0) {
-		unsigned long flags;
-		int panpos;
-
-		matroxfb_DAC_lock_irqsave(flags);
-		panpos = minfo->crtc1.panpos;
-		if (panpos >= 0) {
-			unsigned int extvga_reg;
-
-			minfo->crtc1.panpos = -1; /* No update pending anymore */
-			extvga_reg = mga_inb(M_EXTVGA_INDEX);
-			mga_setr(M_EXTVGA_INDEX, 0x00, panpos);
-			if (extvga_reg != 0x00) {
-				mga_outb(M_EXTVGA_INDEX, extvga_reg);
-			}
-		}
-		matroxfb_DAC_unlock_irqrestore(flags);
-	}
-}
-
-static irqreturn_t matrox_irq(int irq, void *dev_id)
-{
-	u_int32_t status;
-	int handled = 0;
-	struct matrox_fb_info *minfo = dev_id;
-
-	status = mga_inl(M_STATUS);
-
-	if (status & 0x20) {
-		mga_outl(M_ICLEAR, 0x20);
-		minfo->crtc1.vsync.cnt++;
-		matroxfb_crtc1_panpos(minfo);
-		wake_up_interruptible(&minfo->crtc1.vsync.wait);
-		handled = 1;
-	}
-	if (status & 0x200) {
-		mga_outl(M_ICLEAR, 0x200);
-		minfo->crtc2.vsync.cnt++;
-		wake_up_interruptible(&minfo->crtc2.vsync.wait);
-		handled = 1;
-	}
-	return IRQ_RETVAL(handled);
-}
-
-int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable)
-{
-	u_int32_t bm;
-
-	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
-		bm = 0x220;
-	else
-		bm = 0x020;
-
-	if (!test_and_set_bit(0, &minfo->irq_flags)) {
-		if (request_irq(minfo->pcidev->irq, matrox_irq,
-				IRQF_SHARED, "matroxfb", minfo)) {
-			clear_bit(0, &minfo->irq_flags);
-			return -EINVAL;
-		}
-		/* Clear any pending field interrupts */
-		mga_outl(M_ICLEAR, bm);
-		mga_outl(M_IEN, mga_inl(M_IEN) | bm);
-	} else if (reenable) {
-		u_int32_t ien;
-
-		ien = mga_inl(M_IEN);
-		if ((ien & bm) != bm) {
-			printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
-			mga_outl(M_IEN, ien | bm);
-		}
-	}
-	return 0;
-}
-
-static void matroxfb_disable_irq(struct matrox_fb_info *minfo)
-{
-	if (test_and_clear_bit(0, &minfo->irq_flags)) {
-		/* Flush pending pan-at-vbl request... */
-		matroxfb_crtc1_panpos(minfo);
-		if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
-			mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220);
-		else
-			mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20);
-		free_irq(minfo->pcidev->irq, minfo);
-	}
-}
-
-int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc)
-{
-	struct matrox_vsync *vs;
-	unsigned int cnt;
-	int ret;
-
-	switch (crtc) {
-		case 0:
-			vs = &minfo->crtc1.vsync;
-			break;
-		case 1:
-			if (minfo->devflags.accelerator != FB_ACCEL_MATROX_MGAG400) {
-				return -ENODEV;
-			}
-			vs = &minfo->crtc2.vsync;
-			break;
-		default:
-			return -ENODEV;
-	}
-	ret = matroxfb_enable_irq(minfo, 0);
-	if (ret) {
-		return ret;
-	}
-
-	cnt = vs->cnt;
-	ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10);
-	if (ret < 0) {
-		return ret;
-	}
-	if (ret == 0) {
-		matroxfb_enable_irq(minfo, 1);
-		return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void matrox_pan_var(struct matrox_fb_info *minfo,
-			   struct fb_var_screeninfo *var)
-{
-	unsigned int pos;
-	unsigned short p0, p1, p2;
-	unsigned int p3;
-	int vbl;
-	unsigned long flags;
-
-	CRITFLAGS
-
-	DBG(__func__)
-
-	if (minfo->dead)
-		return;
-
-	minfo->fbcon.var.xoffset = var->xoffset;
-	minfo->fbcon.var.yoffset = var->yoffset;
-	pos = (minfo->fbcon.var.yoffset * minfo->fbcon.var.xres_virtual + minfo->fbcon.var.xoffset) * minfo->curr.final_bppShift / 32;
-	pos += minfo->curr.ydstorg.chunks;
-	p0 = minfo->hw.CRTC[0x0D] = pos & 0xFF;
-	p1 = minfo->hw.CRTC[0x0C] = (pos & 0xFF00) >> 8;
-	p2 = minfo->hw.CRTCEXT[0] = (minfo->hw.CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
-	p3 = minfo->hw.CRTCEXT[8] = pos >> 21;
-
-	/* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */
-	vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(minfo, 0) == 0);
-
-	CRITBEGIN
-
-	matroxfb_DAC_lock_irqsave(flags);
-	mga_setr(M_CRTC_INDEX, 0x0D, p0);
-	mga_setr(M_CRTC_INDEX, 0x0C, p1);
-	if (minfo->devflags.support32MB)
-		mga_setr(M_EXTVGA_INDEX, 0x08, p3);
-	if (vbl) {
-		minfo->crtc1.panpos = p2;
-	} else {
-		/* Abort any pending change */
-		minfo->crtc1.panpos = -1;
-		mga_setr(M_EXTVGA_INDEX, 0x00, p2);
-	}
-	matroxfb_DAC_unlock_irqrestore(flags);
-
-	update_crtc2(minfo, pos);
-
-	CRITEND
-}
-
-static void matroxfb_remove(struct matrox_fb_info *minfo, int dummy)
-{
-	/* Currently we are holding big kernel lock on all dead & usecount updates.
-	 * Destroy everything after all users release it. Especially do not unregister
-	 * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check
-	 * for device unplugged when in use.
-	 * In future we should point mmio.vbase & video.vbase somewhere where we can
-	 * write data without causing too much damage...
-	 */
-
-	minfo->dead = 1;
-	if (minfo->usecount) {
-		/* destroy it later */
-		return;
-	}
-	matroxfb_unregister_device(minfo);
-	unregister_framebuffer(&minfo->fbcon);
-	matroxfb_g450_shutdown(minfo);
-#ifdef CONFIG_MTRR
-	if (minfo->mtrr.vram_valid)
-		mtrr_del(minfo->mtrr.vram, minfo->video.base, minfo->video.len);
-#endif
-	mga_iounmap(minfo->mmio.vbase);
-	mga_iounmap(minfo->video.vbase);
-	release_mem_region(minfo->video.base, minfo->video.len_maximum);
-	release_mem_region(minfo->mmio.base, 16384);
-	kfree(minfo);
-}
-
-	/*
-	 * Open/Release the frame buffer device
-	 */
-
-static int matroxfb_open(struct fb_info *info, int user)
-{
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	DBG_LOOP(__func__)
-
-	if (minfo->dead) {
-		return -ENXIO;
-	}
-	minfo->usecount++;
-	if (user) {
-		minfo->userusecount++;
-	}
-	return(0);
-}
-
-static int matroxfb_release(struct fb_info *info, int user)
-{
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	DBG_LOOP(__func__)
-
-	if (user) {
-		if (0 == --minfo->userusecount) {
-			matroxfb_disable_irq(minfo);
-		}
-	}
-	if (!(--minfo->usecount) && minfo->dead) {
-		matroxfb_remove(minfo, 0);
-	}
-	return(0);
-}
-
-static int matroxfb_pan_display(struct fb_var_screeninfo *var,
-		struct fb_info* info) {
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	DBG(__func__)
-
-	matrox_pan_var(minfo, var);
-	return 0;
-}
-
-static int matroxfb_get_final_bppShift(const struct matrox_fb_info *minfo,
-				       int bpp)
-{
-	int bppshft2;
-
-	DBG(__func__)
-
-	bppshft2 = bpp;
-	if (!bppshft2) {
-		return 8;
-	}
-	if (isInterleave(minfo))
-		bppshft2 >>= 1;
-	if (minfo->devflags.video64bits)
-		bppshft2 >>= 1;
-	return bppshft2;
-}
-
-static int matroxfb_test_and_set_rounding(const struct matrox_fb_info *minfo,
-					  int xres, int bpp)
-{
-	int over;
-	int rounding;
-
-	DBG(__func__)
-
-	switch (bpp) {
-		case 0:		return xres;
-		case 4:		rounding = 128;
-				break;
-		case 8:		rounding = 64;	/* doc says 64; 32 is OK for G400 */
-				break;
-		case 16:	rounding = 32;
-				break;
-		case 24:	rounding = 64;	/* doc says 64; 32 is OK for G400 */
-				break;
-		default:	rounding = 16;
-				/* on G400, 16 really does not work */
-				if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
-					rounding = 32;
-				break;
-	}
-	if (isInterleave(minfo)) {
-		rounding *= 2;
-	}
-	over = xres % rounding;
-	if (over)
-		xres += rounding-over;
-	return xres;
-}
-
-static int matroxfb_pitch_adjust(const struct matrox_fb_info *minfo, int xres,
-				 int bpp)
-{
-	const int* width;
-	int xres_new;
-
-	DBG(__func__)
-
-	if (!bpp) return xres;
-
-	width = minfo->capable.vxres;
-
-	if (minfo->devflags.precise_width) {
-		while (*width) {
-			if ((*width >= xres) && (matroxfb_test_and_set_rounding(minfo, *width, bpp) == *width)) {
-				break;
-			}
-			width++;
-		}
-		xres_new = *width;
-	} else {
-		xres_new = matroxfb_test_and_set_rounding(minfo, xres, bpp);
-	}
-	return xres_new;
-}
-
-static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
-
-	DBG(__func__)
-
-	switch (var->bits_per_pixel) {
-		case 4:
-			return 16;	/* pseudocolor... 16 entries HW palette */
-		case 8:
-			return 256;	/* pseudocolor... 256 entries HW palette */
-		case 16:
-			return 16;	/* directcolor... 16 entries SW palette */
-					/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
-		case 24:
-			return 16;	/* directcolor... 16 entries SW palette */
-					/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
-		case 32:
-			return 16;	/* directcolor... 16 entries SW palette */
-					/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
-	}
-	return 16;	/* return something reasonable... or panic()? */
-}
-
-static int matroxfb_decode_var(const struct matrox_fb_info *minfo,
-			       struct fb_var_screeninfo *var, int *visual,
-			       int *video_cmap_len, unsigned int* ydstorg)
-{
-	struct RGBT {
-		unsigned char bpp;
-		struct {
-			unsigned char offset,
-				      length;
-		} red,
-		  green,
-		  blue,
-		  transp;
-		signed char visual;
-	};
-	static const struct RGBT table[]= {
-		{ 8,{ 0,8},{0,8},{0,8},{ 0,0},MX_VISUAL_PSEUDOCOLOR},
-		{15,{10,5},{5,5},{0,5},{15,1},MX_VISUAL_DIRECTCOLOR},
-		{16,{11,5},{5,6},{0,5},{ 0,0},MX_VISUAL_DIRECTCOLOR},
-		{24,{16,8},{8,8},{0,8},{ 0,0},MX_VISUAL_DIRECTCOLOR},
-		{32,{16,8},{8,8},{0,8},{24,8},MX_VISUAL_DIRECTCOLOR}
-	};
-	struct RGBT const *rgbt;
-	unsigned int bpp = var->bits_per_pixel;
-	unsigned int vramlen;
-	unsigned int memlen;
-
-	DBG(__func__)
-
-	switch (bpp) {
-		case 4:	 if (!minfo->capable.cfb4) return -EINVAL;
-			 break;
-		case 8:	 break;
-		case 16: break;
-		case 24: break;
-		case 32: break;
-		default: return -EINVAL;
-	}
-	*ydstorg = 0;
-	vramlen = minfo->video.len_usable;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	var->xres_virtual = matroxfb_pitch_adjust(minfo, var->xres_virtual, bpp);
-	memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
-	if (memlen > vramlen) {
-		var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp);
-		memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
-	}
-	/* There is hardware bug that no line can cross 4MB boundary */
-	/* give up for CFB24, it is impossible to easy workaround it */
-	/* for other try to do something */
-	if (!minfo->capable.cross4MB && (memlen > 0x400000)) {
-		if (bpp == 24) {
-			/* sorry */
-		} else {
-			unsigned int linelen;
-			unsigned int m1 = linelen = var->xres_virtual * bpp / 8;
-			unsigned int m2 = PAGE_SIZE;	/* or 128 if you do not need PAGE ALIGNED address */
-			unsigned int max_yres;
-
-			while (m1) {
-				int t;
-
-				while (m2 >= m1) m2 -= m1;
-				t = m1;
-				m1 = m2;
-				m2 = t;
-			}
-			m2 = linelen * PAGE_SIZE / m2;
-			*ydstorg = m2 = 0x400000 % m2;
-			max_yres = (vramlen - m2) / linelen;
-			if (var->yres_virtual > max_yres)
-				var->yres_virtual = max_yres;
-		}
-	}
-	/* YDSTLEN contains only signed 16bit value */
-	if (var->yres_virtual > 32767)
-		var->yres_virtual = 32767;
-	/* we must round yres/xres down, we already rounded y/xres_virtual up
-	   if it was possible. We should return -EINVAL, but I disagree */
-	if (var->yres_virtual < var->yres)
-		var->yres = var->yres_virtual;
-	if (var->xres_virtual < var->xres)
-		var->xres = var->xres_virtual;
-	if (var->xoffset + var->xres > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yoffset + var->yres > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	if (bpp == 16 && var->green.length == 5) {
-		bpp--; /* an artificial value - 15 */
-	}
-
-	for (rgbt = table; rgbt->bpp < bpp; rgbt++);
-#define	SETCLR(clr)\
-	var->clr.offset = rgbt->clr.offset;\
-	var->clr.length = rgbt->clr.length
-	SETCLR(red);
-	SETCLR(green);
-	SETCLR(blue);
-	SETCLR(transp);
-#undef	SETCLR
-	*visual = rgbt->visual;
-
-	if (bpp > 8)
-		dprintk("matroxfb: truecolor: "
-			"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
-			var->transp.length, var->red.length, var->green.length, var->blue.length,
-			var->transp.offset, var->red.offset, var->green.offset, var->blue.offset);
-
-	*video_cmap_len = matroxfb_get_cmap_len(var);
-	dprintk(KERN_INFO "requested %d*%d/%dbpp (%d*%d)\n", var->xres, var->yres, var->bits_per_pixel,
-				var->xres_virtual, var->yres_virtual);
-	return 0;
-}
-
-static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			      unsigned blue, unsigned transp,
-			      struct fb_info *fb_info)
-{
-	struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon);
-
-	DBG(__func__)
-
-	/*
-	 *  Set a single color register. The values supplied are
-	 *  already rounded down to the hardware's capabilities
-	 *  (according to the entries in the `var' structure). Return
-	 *  != 0 for invalid regno.
-	 */
-
-	if (regno >= minfo->curr.cmap_len)
-		return 1;
-
-	if (minfo->fbcon.var.grayscale) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	red = CNVT_TOHW(red, minfo->fbcon.var.red.length);
-	green = CNVT_TOHW(green, minfo->fbcon.var.green.length);
-	blue = CNVT_TOHW(blue, minfo->fbcon.var.blue.length);
-	transp = CNVT_TOHW(transp, minfo->fbcon.var.transp.length);
-
-	switch (minfo->fbcon.var.bits_per_pixel) {
-	case 4:
-	case 8:
-		mga_outb(M_DAC_REG, regno);
-		mga_outb(M_DAC_VAL, red);
-		mga_outb(M_DAC_VAL, green);
-		mga_outb(M_DAC_VAL, blue);
-		break;
-	case 16:
-		if (regno >= 16)
-			break;
-		{
-			u_int16_t col =
-				(red << minfo->fbcon.var.red.offset)     |
-				(green << minfo->fbcon.var.green.offset) |
-				(blue << minfo->fbcon.var.blue.offset)   |
-				(transp << minfo->fbcon.var.transp.offset); /* for 1:5:5:5 */
-			minfo->cmap[regno] = col | (col << 16);
-		}
-		break;
-	case 24:
-	case 32:
-		if (regno >= 16)
-			break;
-		minfo->cmap[regno] =
-			(red   << minfo->fbcon.var.red.offset)   |
-			(green << minfo->fbcon.var.green.offset) |
-			(blue  << minfo->fbcon.var.blue.offset)  |
-			(transp << minfo->fbcon.var.transp.offset);	/* 8:8:8:8 */
-		break;
-	}
-	return 0;
-}
-
-static void matroxfb_init_fix(struct matrox_fb_info *minfo)
-{
-	struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
-	DBG(__func__)
-
-	strcpy(fix->id,"MATROX");
-
-	fix->xpanstep = 8;	/* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
-	fix->ypanstep = 1;
-	fix->ywrapstep = 0;
-	fix->mmio_start = minfo->mmio.base;
-	fix->mmio_len = minfo->mmio.len;
-	fix->accel = minfo->devflags.accelerator;
-}
-
-static void matroxfb_update_fix(struct matrox_fb_info *minfo)
-{
-	struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
-	DBG(__func__)
-
-	mutex_lock(&minfo->fbcon.mm_lock);
-	fix->smem_start = minfo->video.base + minfo->curr.ydstorg.bytes;
-	fix->smem_len = minfo->video.len_usable - minfo->curr.ydstorg.bytes;
-	mutex_unlock(&minfo->fbcon.mm_lock);
-}
-
-static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int err;
-	int visual;
-	int cmap_len;
-	unsigned int ydstorg;
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	if (minfo->dead) {
-		return -ENXIO;
-	}
-	if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
-		return err;
-	return 0;
-}
-
-static int matroxfb_set_par(struct fb_info *info)
-{
-	int err;
-	int visual;
-	int cmap_len;
-	unsigned int ydstorg;
-	struct fb_var_screeninfo *var;
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	DBG(__func__)
-
-	if (minfo->dead) {
-		return -ENXIO;
-	}
-
-	var = &info->var;
-	if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
-		return err;
-	minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase) + ydstorg;
-	matroxfb_update_fix(minfo);
-	minfo->fbcon.fix.visual = visual;
-	minfo->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
-	minfo->fbcon.fix.type_aux = 0;
-	minfo->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
-	{
-		unsigned int pos;
-
-		minfo->curr.cmap_len = cmap_len;
-		ydstorg += minfo->devflags.ydstorg;
-		minfo->curr.ydstorg.bytes = ydstorg;
-		minfo->curr.ydstorg.chunks = ydstorg >> (isInterleave(minfo) ? 3 : 2);
-		if (var->bits_per_pixel == 4)
-			minfo->curr.ydstorg.pixels = ydstorg;
-		else
-			minfo->curr.ydstorg.pixels = (ydstorg * 8) / var->bits_per_pixel;
-		minfo->curr.final_bppShift = matroxfb_get_final_bppShift(minfo, var->bits_per_pixel);
-		{	struct my_timming mt;
-			struct matrox_hw_state* hw;
-			int out;
-
-			matroxfb_var2my(var, &mt);
-			mt.crtc = MATROXFB_SRC_CRTC1;
-			/* CRTC1 delays */
-			switch (var->bits_per_pixel) {
-				case  0:	mt.delay = 31 + 0; break;
-				case 16:	mt.delay = 21 + 8; break;
-				case 24:	mt.delay = 17 + 8; break;
-				case 32:	mt.delay = 16 + 8; break;
-				default:	mt.delay = 31 + 8; break;
-			}
-
-			hw = &minfo->hw;
-
-			down_read(&minfo->altout.lock);
-			for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-				if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
-				    minfo->outputs[out].output->compute) {
-					minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
-				}
-			}
-			up_read(&minfo->altout.lock);
-			minfo->crtc1.pixclock = mt.pixclock;
-			minfo->crtc1.mnp = mt.mnp;
-			minfo->hw_switch->init(minfo, &mt);
-			pos = (var->yoffset * var->xres_virtual + var->xoffset) * minfo->curr.final_bppShift / 32;
-			pos += minfo->curr.ydstorg.chunks;
-
-			hw->CRTC[0x0D] = pos & 0xFF;
-			hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
-			hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
-			hw->CRTCEXT[8] = pos >> 21;
-			minfo->hw_switch->restore(minfo);
-			update_crtc2(minfo, pos);
-			down_read(&minfo->altout.lock);
-			for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-				if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
-				    minfo->outputs[out].output->program) {
-					minfo->outputs[out].output->program(minfo->outputs[out].data);
-				}
-			}
-			for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-				if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
-				    minfo->outputs[out].output->start) {
-					minfo->outputs[out].output->start(minfo->outputs[out].data);
-				}
-			}
-			up_read(&minfo->altout.lock);
-			matrox_cfbX_init(minfo);
-		}
-	}
-	minfo->initialized = 1;
-	return 0;
-}
-
-static int matroxfb_get_vblank(struct matrox_fb_info *minfo,
-			       struct fb_vblank *vblank)
-{
-	unsigned int sts1;
-
-	matroxfb_enable_irq(minfo, 0);
-	memset(vblank, 0, sizeof(*vblank));
-	vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC |
-			FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK;
-	sts1 = mga_inb(M_INSTS1);
-	vblank->vcount = mga_inl(M_VCOUNT);
-	/* BTW, on my PIII/450 with G400, reading M_INSTS1
-	   byte makes this call about 12% slower (1.70 vs. 2.05 us
-	   per ioctl()) */
-	if (sts1 & 1)
-		vblank->flags |= FB_VBLANK_HBLANKING;
-	if (sts1 & 8)
-		vblank->flags |= FB_VBLANK_VSYNCING;
-	if (vblank->vcount >= minfo->fbcon.var.yres)
-		vblank->flags |= FB_VBLANK_VBLANKING;
-	if (test_bit(0, &minfo->irq_flags)) {
-		vblank->flags |= FB_VBLANK_HAVE_COUNT;
-		/* Only one writer, aligned int value...
-		   it should work without lock and without atomic_t */
-		vblank->count = minfo->crtc1.vsync.cnt;
-	}
-	return 0;
-}
-
-static struct matrox_altout panellink_output = {
-	.name	 = "Panellink output",
-};
-
-static int matroxfb_ioctl(struct fb_info *info,
-			  unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	DBG(__func__)
-
-	if (minfo->dead) {
-		return -ENXIO;
-	}
-
-	switch (cmd) {
-		case FBIOGET_VBLANK:
-			{
-				struct fb_vblank vblank;
-				int err;
-
-				err = matroxfb_get_vblank(minfo, &vblank);
-				if (err)
-					return err;
-				if (copy_to_user(argp, &vblank, sizeof(vblank)))
-					return -EFAULT;
-				return 0;
-			}
-		case FBIO_WAITFORVSYNC:
-			{
-				u_int32_t crt;
-
-				if (get_user(crt, (u_int32_t __user *)arg))
-					return -EFAULT;
-
-				return matroxfb_wait_for_sync(minfo, crt);
-			}
-		case MATROXFB_SET_OUTPUT_MODE:
-			{
-				struct matroxioc_output_mode mom;
-				struct matrox_altout *oproc;
-				int val;
-
-				if (copy_from_user(&mom, argp, sizeof(mom)))
-					return -EFAULT;
-				if (mom.output >= MATROXFB_MAX_OUTPUTS)
-					return -ENXIO;
-				down_read(&minfo->altout.lock);
-				oproc = minfo->outputs[mom.output].output;
-				if (!oproc) {
-					val = -ENXIO;
-				} else if (!oproc->verifymode) {
-					if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) {
-						val = 0;
-					} else {
-						val = -EINVAL;
-					}
-				} else {
-					val = oproc->verifymode(minfo->outputs[mom.output].data, mom.mode);
-				}
-				if (!val) {
-					if (minfo->outputs[mom.output].mode != mom.mode) {
-						minfo->outputs[mom.output].mode = mom.mode;
-						val = 1;
-					}
-				}
-				up_read(&minfo->altout.lock);
-				if (val != 1)
-					return val;
-				switch (minfo->outputs[mom.output].src) {
-					case MATROXFB_SRC_CRTC1:
-						matroxfb_set_par(info);
-						break;
-					case MATROXFB_SRC_CRTC2:
-						{
-							struct matroxfb_dh_fb_info* crtc2;
-
-							down_read(&minfo->crtc2.lock);
-							crtc2 = minfo->crtc2.info;
-							if (crtc2)
-								crtc2->fbcon.fbops->fb_set_par(&crtc2->fbcon);
-							up_read(&minfo->crtc2.lock);
-						}
-						break;
-				}
-				return 0;
-			}
-		case MATROXFB_GET_OUTPUT_MODE:
-			{
-				struct matroxioc_output_mode mom;
-				struct matrox_altout *oproc;
-				int val;
-
-				if (copy_from_user(&mom, argp, sizeof(mom)))
-					return -EFAULT;
-				if (mom.output >= MATROXFB_MAX_OUTPUTS)
-					return -ENXIO;
-				down_read(&minfo->altout.lock);
-				oproc = minfo->outputs[mom.output].output;
-				if (!oproc) {
-					val = -ENXIO;
-				} else {
-					mom.mode = minfo->outputs[mom.output].mode;
-					val = 0;
-				}
-				up_read(&minfo->altout.lock);
-				if (val)
-					return val;
-				if (copy_to_user(argp, &mom, sizeof(mom)))
-					return -EFAULT;
-				return 0;
-			}
-		case MATROXFB_SET_OUTPUT_CONNECTION:
-			{
-				u_int32_t tmp;
-				int i;
-				int changes;
-
-				if (copy_from_user(&tmp, argp, sizeof(tmp)))
-					return -EFAULT;
-				for (i = 0; i < 32; i++) {
-					if (tmp & (1 << i)) {
-						if (i >= MATROXFB_MAX_OUTPUTS)
-							return -ENXIO;
-						if (!minfo->outputs[i].output)
-							return -ENXIO;
-						switch (minfo->outputs[i].src) {
-							case MATROXFB_SRC_NONE:
-							case MATROXFB_SRC_CRTC1:
-								break;
-							default:
-								return -EBUSY;
-						}
-					}
-				}
-				if (minfo->devflags.panellink) {
-					if (tmp & MATROXFB_OUTPUT_CONN_DFP) {
-						if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY)
-							return -EINVAL;
-						for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
-							if (minfo->outputs[i].src == MATROXFB_SRC_CRTC2) {
-								return -EBUSY;
-							}
-						}
-					}
-				}
-				changes = 0;
-				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
-					if (tmp & (1 << i)) {
-						if (minfo->outputs[i].src != MATROXFB_SRC_CRTC1) {
-							changes = 1;
-							minfo->outputs[i].src = MATROXFB_SRC_CRTC1;
-						}
-					} else if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
-						changes = 1;
-						minfo->outputs[i].src = MATROXFB_SRC_NONE;
-					}
-				}
-				if (!changes)
-					return 0;
-				matroxfb_set_par(info);
-				return 0;
-			}
-		case MATROXFB_GET_OUTPUT_CONNECTION:
-			{
-				u_int32_t conn = 0;
-				int i;
-
-				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
-					if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
-						conn |= 1 << i;
-					}
-				}
-				if (put_user(conn, (u_int32_t __user *)arg))
-					return -EFAULT;
-				return 0;
-			}
-		case MATROXFB_GET_AVAILABLE_OUTPUTS:
-			{
-				u_int32_t conn = 0;
-				int i;
-
-				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
-					if (minfo->outputs[i].output) {
-						switch (minfo->outputs[i].src) {
-							case MATROXFB_SRC_NONE:
-							case MATROXFB_SRC_CRTC1:
-								conn |= 1 << i;
-								break;
-						}
-					}
-				}
-				if (minfo->devflags.panellink) {
-					if (conn & MATROXFB_OUTPUT_CONN_DFP)
-						conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
-					if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
-						conn &= ~MATROXFB_OUTPUT_CONN_DFP;
-				}
-				if (put_user(conn, (u_int32_t __user *)arg))
-					return -EFAULT;
-				return 0;
-			}
-		case MATROXFB_GET_ALL_OUTPUTS:
-			{
-				u_int32_t conn = 0;
-				int i;
-
-				for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
-					if (minfo->outputs[i].output) {
-						conn |= 1 << i;
-					}
-				}
-				if (put_user(conn, (u_int32_t __user *)arg))
-					return -EFAULT;
-				return 0;
-			}
-		case VIDIOC_QUERYCAP:
-			{
-				struct v4l2_capability r;
-
-				memset(&r, 0, sizeof(r));
-				strcpy(r.driver, "matroxfb");
-				strcpy(r.card, "Matrox");
-				sprintf(r.bus_info, "PCI:%s", pci_name(minfo->pcidev));
-				r.version = KERNEL_VERSION(1,0,0);
-				r.capabilities = V4L2_CAP_VIDEO_OUTPUT;
-				if (copy_to_user(argp, &r, sizeof(r)))
-					return -EFAULT;
-				return 0;
-
-			}
-		case VIDIOC_QUERYCTRL:
-			{
-				struct v4l2_queryctrl qctrl;
-				int err;
-
-				if (copy_from_user(&qctrl, argp, sizeof(qctrl)))
-					return -EFAULT;
-
-				down_read(&minfo->altout.lock);
-				if (!minfo->outputs[1].output) {
-					err = -ENXIO;
-				} else if (minfo->outputs[1].output->getqueryctrl) {
-					err = minfo->outputs[1].output->getqueryctrl(minfo->outputs[1].data, &qctrl);
-				} else {
-					err = -EINVAL;
-				}
-				up_read(&minfo->altout.lock);
-				if (err >= 0 &&
-				    copy_to_user(argp, &qctrl, sizeof(qctrl)))
-					return -EFAULT;
-				return err;
-			}
-		case VIDIOC_G_CTRL:
-			{
-				struct v4l2_control ctrl;
-				int err;
-
-				if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
-					return -EFAULT;
-
-				down_read(&minfo->altout.lock);
-				if (!minfo->outputs[1].output) {
-					err = -ENXIO;
-				} else if (minfo->outputs[1].output->getctrl) {
-					err = minfo->outputs[1].output->getctrl(minfo->outputs[1].data, &ctrl);
-				} else {
-					err = -EINVAL;
-				}
-				up_read(&minfo->altout.lock);
-				if (err >= 0 &&
-				    copy_to_user(argp, &ctrl, sizeof(ctrl)))
-					return -EFAULT;
-				return err;
-			}
-		case VIDIOC_S_CTRL:
-			{
-				struct v4l2_control ctrl;
-				int err;
-
-				if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
-					return -EFAULT;
-
-				down_read(&minfo->altout.lock);
-				if (!minfo->outputs[1].output) {
-					err = -ENXIO;
-				} else if (minfo->outputs[1].output->setctrl) {
-					err = minfo->outputs[1].output->setctrl(minfo->outputs[1].data, &ctrl);
-				} else {
-					err = -EINVAL;
-				}
-				up_read(&minfo->altout.lock);
-				return err;
-			}
-	}
-	return -ENOTTY;
-}
-
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-
-static int matroxfb_blank(int blank, struct fb_info *info)
-{
-	int seq;
-	int crtc;
-	CRITFLAGS
-	struct matrox_fb_info *minfo = info2minfo(info);
-
-	DBG(__func__)
-
-	if (minfo->dead)
-		return 1;
-
-	switch (blank) {
-	case FB_BLANK_NORMAL:  seq = 0x20; crtc = 0x00; break; /* works ??? */
-	case FB_BLANK_VSYNC_SUSPEND:  seq = 0x20; crtc = 0x10; break;
-	case FB_BLANK_HSYNC_SUSPEND:  seq = 0x20; crtc = 0x20; break;
-	case FB_BLANK_POWERDOWN:  seq = 0x20; crtc = 0x30; break;
-	default: seq = 0x00; crtc = 0x00; break;
-	}
-
-	CRITBEGIN
-
-	mga_outb(M_SEQ_INDEX, 1);
-	mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq);
-	mga_outb(M_EXTVGA_INDEX, 1);
-	mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc);
-
-	CRITEND
-	return 0;
-}
-
-static struct fb_ops matroxfb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_open =	matroxfb_open,
-	.fb_release =	matroxfb_release,
-	.fb_check_var =	matroxfb_check_var,
-	.fb_set_par =	matroxfb_set_par,
-	.fb_setcolreg =	matroxfb_setcolreg,
-	.fb_pan_display =matroxfb_pan_display,
-	.fb_blank =	matroxfb_blank,
-	.fb_ioctl =	matroxfb_ioctl,
-/*	.fb_fillrect =	<set by matrox_cfbX_init>, */
-/*	.fb_copyarea =	<set by matrox_cfbX_init>, */
-/*	.fb_imageblit =	<set by matrox_cfbX_init>, */
-/*	.fb_cursor =	<set by matrox_cfbX_init>, */
-};
-
-#define RSDepth(X)	(((X) >> 8) & 0x0F)
-#define RS8bpp		0x1
-#define RS15bpp		0x2
-#define RS16bpp		0x3
-#define RS32bpp		0x4
-#define RS4bpp		0x5
-#define RS24bpp		0x6
-#define RSText		0x7
-#define RSText8		0x8
-/* 9-F */
-static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; } colors[] = {
-	{ {  0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, {  0, 0, 0},  8 },
-	{ { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
-	{ { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0}, {  0, 0, 0}, 16 },
-	{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
-	{ {  0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, {  0, 0, 0},  4 },
-	{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {  0, 0, 0}, 24 },
-	{ {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 },	/* textmode with (default) VGA8x16 */
-	{ {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 },	/* textmode hardwired to VGA8x8 */
-};
-
-/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
-static unsigned int mem;		/* "matroxfb:mem:xxxxxM" */
-static int option_precise_width = 1;	/* cannot be changed, option_precise_width==0 must imply noaccel */
-static int inv24;			/* "matroxfb:inv24" */
-static int cross4MB = -1;		/* "matroxfb:cross4MB" */
-static int disabled;			/* "matroxfb:disabled" */
-static int noaccel;			/* "matroxfb:noaccel" */
-static int nopan;			/* "matroxfb:nopan" */
-static int no_pci_retry;		/* "matroxfb:nopciretry" */
-static int novga;			/* "matroxfb:novga" */
-static int nobios;			/* "matroxfb:nobios" */
-static int noinit = 1;			/* "matroxfb:init" */
-static int inverse;			/* "matroxfb:inverse" */
-static int sgram;			/* "matroxfb:sgram" */
-#ifdef CONFIG_MTRR
-static int mtrr = 1;			/* "matroxfb:nomtrr" */
-#endif
-static int grayscale;			/* "matroxfb:grayscale" */
-static int dev = -1;			/* "matroxfb:dev:xxxxx" */
-static unsigned int vesa = ~0;		/* "matroxfb:vesa:xxxxx" */
-static int depth = -1;			/* "matroxfb:depth:xxxxx" */
-static unsigned int xres;		/* "matroxfb:xres:xxxxx" */
-static unsigned int yres;		/* "matroxfb:yres:xxxxx" */
-static unsigned int upper = ~0;		/* "matroxfb:upper:xxxxx" */
-static unsigned int lower = ~0;		/* "matroxfb:lower:xxxxx" */
-static unsigned int vslen;		/* "matroxfb:vslen:xxxxx" */
-static unsigned int left = ~0;		/* "matroxfb:left:xxxxx" */
-static unsigned int right = ~0;		/* "matroxfb:right:xxxxx" */
-static unsigned int hslen;		/* "matroxfb:hslen:xxxxx" */
-static unsigned int pixclock;		/* "matroxfb:pixclock:xxxxx" */
-static int sync = -1;			/* "matroxfb:sync:xxxxx" */
-static unsigned int fv;			/* "matroxfb:fv:xxxxx" */
-static unsigned int fh;			/* "matroxfb:fh:xxxxxk" */
-static unsigned int maxclk;		/* "matroxfb:maxclk:xxxxM" */
-static int dfp;				/* "matroxfb:dfp */
-static int dfp_type = -1;		/* "matroxfb:dfp:xxx */
-static int memtype = -1;		/* "matroxfb:memtype:xxx" */
-static char outputs[8];			/* "matroxfb:outputs:xxx" */
-
-#ifndef MODULE
-static char videomode[64];		/* "matroxfb:mode:xxxxx" or "matroxfb:xxxxx" */
-#endif
-
-static int matroxfb_getmemory(struct matrox_fb_info *minfo,
-			      unsigned int maxSize, unsigned int *realSize)
-{
-	vaddr_t vm;
-	unsigned int offs;
-	unsigned int offs2;
-	unsigned char orig;
-	unsigned char bytes[32];
-	unsigned char* tmp;
-
-	DBG(__func__)
-
-	vm = minfo->video.vbase;
-	maxSize &= ~0x1FFFFF;	/* must be X*2MB (really it must be 2 or X*4MB) */
-	/* at least 2MB */
-	if (maxSize < 0x0200000) return 0;
-	if (maxSize > 0x2000000) maxSize = 0x2000000;
-
-	mga_outb(M_EXTVGA_INDEX, 0x03);
-	orig = mga_inb(M_EXTVGA_DATA);
-	mga_outb(M_EXTVGA_DATA, orig | 0x80);
-
-	tmp = bytes;
-	for (offs = 0x100000; offs < maxSize; offs += 0x200000)
-		*tmp++ = mga_readb(vm, offs);
-	for (offs = 0x100000; offs < maxSize; offs += 0x200000)
-		mga_writeb(vm, offs, 0x02);
-	mga_outb(M_CACHEFLUSH, 0x00);
-	for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
-		if (mga_readb(vm, offs) != 0x02)
-			break;
-		mga_writeb(vm, offs, mga_readb(vm, offs) - 0x02);
-		if (mga_readb(vm, offs))
-			break;
-	}
-	tmp = bytes;
-	for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
-		mga_writeb(vm, offs2, *tmp++);
-
-	mga_outb(M_EXTVGA_INDEX, 0x03);
-	mga_outb(M_EXTVGA_DATA, orig);
-
-	*realSize = offs - 0x100000;
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-	minfo->interleave = !(!isMillenium(minfo) || ((offs - 0x100000) & 0x3FFFFF));
-#endif
-	return 1;
-}
-
-struct video_board {
-	int maxvram;
-	int maxdisplayable;
-	int accelID;
-	struct matrox_switch* lowlevel;
-		 };
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-static struct video_board vbMillennium		= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA2064W,	&matrox_millennium};
-static struct video_board vbMillennium2		= {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W,	&matrox_millennium};
-static struct video_board vbMillennium2A	= {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W_AGP,	&matrox_millennium};
-#endif	/* CONFIG_FB_MATROX_MILLENIUM */
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-static struct video_board vbMystique		= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG,	&matrox_mystique};
-#endif	/* CONFIG_FB_MATROX_MYSTIQUE */
-#ifdef CONFIG_FB_MATROX_G
-static struct video_board vbG100		= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100,	&matrox_G100};
-static struct video_board vbG200		= {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200,	&matrox_G100};
-/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
-   whole 32MB */
-static struct video_board vbG400		= {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400,	&matrox_G100};
-#endif
-
-#define DEVF_VIDEO64BIT		0x0001
-#define	DEVF_SWAPS		0x0002
-#define DEVF_SRCORG		0x0004
-#define DEVF_DUALHEAD		0x0008
-#define DEVF_CROSS4MB		0x0010
-#define DEVF_TEXT4B		0x0020
-/* #define DEVF_recycled	0x0040	*/
-/* #define DEVF_recycled	0x0080	*/
-#define DEVF_SUPPORT32MB	0x0100
-#define DEVF_ANY_VXRES		0x0200
-#define DEVF_TEXT16B		0x0400
-#define DEVF_CRTC2		0x0800
-#define DEVF_MAVEN_CAPABLE	0x1000
-#define DEVF_PANELLINK_CAPABLE	0x2000
-#define DEVF_G450DAC		0x4000
-
-#define DEVF_GCORE	(DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB)
-#define DEVF_G2CORE	(DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE | DEVF_SRCORG | DEVF_DUALHEAD)
-#define DEVF_G100	(DEVF_GCORE) /* no doc, no vxres... */
-#define DEVF_G200	(DEVF_G2CORE)
-#define DEVF_G400	(DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2)
-/* if you'll find how to drive DFP... */
-#define DEVF_G450	(DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG | DEVF_DUALHEAD)
-#define DEVF_G550	(DEVF_G450)
-
-static struct board {
-	unsigned short vendor, device, rev, svid, sid;
-	unsigned int flags;
-	unsigned int maxclk;
-	enum mga_chip chip;
-	struct video_board* base;
-	const char* name;
-		} dev_list[] = {
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL,	0xFF,
-		0,			0,
-		DEVF_TEXT4B,
-		230000,
-		MGA_2064,
-		&vbMillennium,
-		"Millennium (PCI)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2,	0xFF,
-		0,			0,
-		DEVF_SWAPS,
-		220000,
-		MGA_2164,
-		&vbMillennium2,
-		"Millennium II (PCI)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2_AGP,	0xFF,
-		0,			0,
-		DEVF_SWAPS,
-		250000,
-		MGA_2164,
-		&vbMillennium2A,
-		"Millennium II (AGP)"},
-#endif
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,	0x02,
-		0,			0,
-		DEVF_VIDEO64BIT | DEVF_CROSS4MB,
-		180000,
-		MGA_1064,
-		&vbMystique,
-		"Mystique (PCI)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,	0xFF,
-		0,			0,
-		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
-		MGA_1164,
-		&vbMystique,
-		"Mystique 220 (PCI)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS_AGP,	0x02,
-		0,			0,
-		DEVF_VIDEO64BIT | DEVF_CROSS4MB,
-		180000,
-		MGA_1064,
-		&vbMystique,
-		"Mystique (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS_AGP,	0xFF,
-		0,			0,
-		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
-		MGA_1164,
-		&vbMystique,
-		"Mystique 220 (AGP)"},
-#endif
-#ifdef CONFIG_FB_MATROX_G
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_MM,	0xFF,
-		0,			0,
-		DEVF_G100,
-		230000,
-		MGA_G100,
-		&vbG100,
-		"MGA-G100 (PCI)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,	0xFF,
-		0,			0,
-		DEVF_G100,
-		230000,
-		MGA_G100,
-		&vbG100,
-		"MGA-G100 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_PCI,	0xFF,
-		0,			0,
-		DEVF_G200,
-		250000,
-		MGA_G200,
-		&vbG200,
-		"MGA-G200 (PCI)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
-		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_GENERIC,
-		DEVF_G200,
-		220000,
-		MGA_G200,
-		&vbG200,
-		"MGA-G200 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
-		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
-		DEVF_G200,
-		230000,
-		MGA_G200,
-		&vbG200,
-		"Mystique G200 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
-		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MILLENIUM_G200_AGP,
-		DEVF_G200,
-		250000,
-		MGA_G200,
-		&vbG200,
-		"Millennium G200 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
-		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MARVEL_G200_AGP,
-		DEVF_G200,
-		230000,
-		MGA_G200,
-		&vbG200,
-		"Marvel G200 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
-		PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,	PCI_SS_ID_SIEMENS_MGA_G200_AGP,
-		DEVF_G200,
-		230000,
-		MGA_G200,
-		&vbG200,
-		"MGA-G200 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
-		0,			0,
-		DEVF_G200,
-		230000,
-		MGA_G200,
-		&vbG200,
-		"G200 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,	0x80,
-		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP,
-		DEVF_G400,
-		360000,
-		MGA_G400,
-		&vbG400,
-		"Millennium G400 MAX (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,	0x80,
-		0,			0,
-		DEVF_G400,
-		300000,
-		MGA_G400,
-		&vbG400,
-		"G400 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,	0xFF,
-		0,			0,
-		DEVF_G450,
-		360000,
-		MGA_G450,
-		&vbG400,
-		"G450"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G550,	0xFF,
-		0,			0,
-		DEVF_G550,
-		360000,
-		MGA_G550,
-		&vbG400,
-		"G550"},
-#endif
-	{0,			0,				0xFF,
-		0,			0,
-		0,
-		0,
-		0,
-		NULL,
-		NULL}};
-
-#ifndef MODULE
-static struct fb_videomode defaultmode = {
-	/* 640x480 @ 60Hz, 31.5 kHz */
-	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
-#endif /* !MODULE */
-
-static int hotplug = 0;
-
-static void setDefaultOutputs(struct matrox_fb_info *minfo)
-{
-	unsigned int i;
-	const char* ptr;
-
-	minfo->outputs[0].default_src = MATROXFB_SRC_CRTC1;
-	if (minfo->devflags.g450dac) {
-		minfo->outputs[1].default_src = MATROXFB_SRC_CRTC1;
-		minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
-	} else if (dfp) {
-		minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
-	}
-	ptr = outputs;
-	for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
-		char c = *ptr++;
-
-		if (c == 0) {
-			break;
-		}
-		if (c == '0') {
-			minfo->outputs[i].default_src = MATROXFB_SRC_NONE;
-		} else if (c == '1') {
-			minfo->outputs[i].default_src = MATROXFB_SRC_CRTC1;
-		} else if (c == '2' && minfo->devflags.crtc2) {
-			minfo->outputs[i].default_src = MATROXFB_SRC_CRTC2;
-		} else {
-			printk(KERN_ERR "matroxfb: Unknown outputs setting\n");
-			break;
-		}
-	}
-	/* Nullify this option for subsequent adapters */
-	outputs[0] = 0;
-}
-
-static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
-{
-	unsigned long ctrlptr_phys = 0;
-	unsigned long video_base_phys = 0;
-	unsigned int memsize;
-	int err;
-
-	static struct pci_device_id intel_82437[] = {
-		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437) },
-		{ },
-	};
-
-	DBG(__func__)
-
-	/* set default values... */
-	vesafb_defined.accel_flags = FB_ACCELF_TEXT;
-
-	minfo->hw_switch = b->base->lowlevel;
-	minfo->devflags.accelerator = b->base->accelID;
-	minfo->max_pixel_clock = b->maxclk;
-
-	printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
-	minfo->capable.plnwt = 1;
-	minfo->chip = b->chip;
-	minfo->capable.srcorg = b->flags & DEVF_SRCORG;
-	minfo->devflags.video64bits = b->flags & DEVF_VIDEO64BIT;
-	if (b->flags & DEVF_TEXT4B) {
-		minfo->devflags.vgastep = 4;
-		minfo->devflags.textmode = 4;
-		minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
-	} else if (b->flags & DEVF_TEXT16B) {
-		minfo->devflags.vgastep = 16;
-		minfo->devflags.textmode = 1;
-		minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
-	} else {
-		minfo->devflags.vgastep = 8;
-		minfo->devflags.textmode = 1;
-		minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP8;
-	}
-	minfo->devflags.support32MB = (b->flags & DEVF_SUPPORT32MB) != 0;
-	minfo->devflags.precise_width = !(b->flags & DEVF_ANY_VXRES);
-	minfo->devflags.crtc2 = (b->flags & DEVF_CRTC2) != 0;
-	minfo->devflags.maven_capable = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
-	minfo->devflags.dualhead = (b->flags & DEVF_DUALHEAD) != 0;
-	minfo->devflags.dfp_type = dfp_type;
-	minfo->devflags.g450dac = (b->flags & DEVF_G450DAC) != 0;
-	minfo->devflags.textstep = minfo->devflags.vgastep * minfo->devflags.textmode;
-	minfo->devflags.textvram = 65536 / minfo->devflags.textmode;
-	setDefaultOutputs(minfo);
-	if (b->flags & DEVF_PANELLINK_CAPABLE) {
-		minfo->outputs[2].data = minfo;
-		minfo->outputs[2].output = &panellink_output;
-		minfo->outputs[2].src = minfo->outputs[2].default_src;
-		minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-		minfo->devflags.panellink = 1;
-	}
-
-	if (minfo->capable.cross4MB < 0)
-		minfo->capable.cross4MB = b->flags & DEVF_CROSS4MB;
-	if (b->flags & DEVF_SWAPS) {
-		ctrlptr_phys = pci_resource_start(minfo->pcidev, 1);
-		video_base_phys = pci_resource_start(minfo->pcidev, 0);
-		minfo->devflags.fbResource = PCI_BASE_ADDRESS_0;
-	} else {
-		ctrlptr_phys = pci_resource_start(minfo->pcidev, 0);
-		video_base_phys = pci_resource_start(minfo->pcidev, 1);
-		minfo->devflags.fbResource = PCI_BASE_ADDRESS_1;
-	}
-	err = -EINVAL;
-	if (!ctrlptr_phys) {
-		printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n");
-		goto fail;
-	}
-	if (!video_base_phys) {
-		printk(KERN_ERR "matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
-		goto fail;
-	}
-	memsize = b->base->maxvram;
-	if (!request_mem_region(ctrlptr_phys, 16384, "matroxfb MMIO")) {
-		goto fail;
-	}
-	if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) {
-		goto failCtrlMR;
-	}
-	minfo->video.len_maximum = memsize;
-	/* convert mem (autodetect k, M) */
-	if (mem < 1024) mem *= 1024;
-	if (mem < 0x00100000) mem *= 1024;
-
-	if (mem && (mem < memsize))
-		memsize = mem;
-	err = -ENOMEM;
-	if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &minfo->mmio.vbase)) {
-		printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
-		goto failVideoMR;
-	}
-	minfo->mmio.base = ctrlptr_phys;
-	minfo->mmio.len = 16384;
-	minfo->video.base = video_base_phys;
-	if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &minfo->video.vbase)) {
-		printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
-			video_base_phys, memsize);
-		goto failCtrlIO;
-	}
-	{
-		u_int32_t cmd;
-		u_int32_t mga_option;
-
-		pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &mga_option);
-		pci_read_config_dword(minfo->pcidev, PCI_COMMAND, &cmd);
-		mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
-		mga_option |= MX_OPTION_BSWAP;
-		/* disable palette snooping */
-		cmd &= ~PCI_COMMAND_VGA_PALETTE;
-		if (pci_dev_present(intel_82437)) {
-			if (!(mga_option & 0x20000000) && !minfo->devflags.nopciretry) {
-				printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
-			}
-			mga_option |= 0x20000000;
-			minfo->devflags.nopciretry = 1;
-		}
-		pci_write_config_dword(minfo->pcidev, PCI_COMMAND, cmd);
-		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mga_option);
-		minfo->hw.MXoptionReg = mga_option;
-
-		/* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
-		/* maybe preinit() candidate, but it is same... for all devices... at this time... */
-		pci_write_config_dword(minfo->pcidev, PCI_MGA_INDEX, 0x00003C00);
-	}
-
-	err = -ENXIO;
-	matroxfb_read_pins(minfo);
-	if (minfo->hw_switch->preinit(minfo)) {
-		goto failVideoIO;
-	}
-
-	err = -ENOMEM;
-	if (!matroxfb_getmemory(minfo, memsize, &minfo->video.len) || !minfo->video.len) {
-		printk(KERN_ERR "matroxfb: cannot determine memory size\n");
-		goto failVideoIO;
-	}
-	minfo->devflags.ydstorg = 0;
-
-	minfo->video.base = video_base_phys;
-	minfo->video.len_usable = minfo->video.len;
-	if (minfo->video.len_usable > b->base->maxdisplayable)
-		minfo->video.len_usable = b->base->maxdisplayable;
-#ifdef CONFIG_MTRR
-	if (mtrr) {
-		minfo->mtrr.vram = mtrr_add(video_base_phys, minfo->video.len, MTRR_TYPE_WRCOMB, 1);
-		minfo->mtrr.vram_valid = 1;
-		printk(KERN_INFO "matroxfb: MTRR's turned on\n");
-	}
-#endif	/* CONFIG_MTRR */
-
-	if (!minfo->devflags.novga)
-		request_region(0x3C0, 32, "matrox");
-	matroxfb_g450_connect(minfo);
-	minfo->hw_switch->reset(minfo);
-
-	minfo->fbcon.monspecs.hfmin = 0;
-	minfo->fbcon.monspecs.hfmax = fh;
-	minfo->fbcon.monspecs.vfmin = 0;
-	minfo->fbcon.monspecs.vfmax = fv;
-	minfo->fbcon.monspecs.dpms = 0;	/* TBD */
-
-	/* static settings */
-	vesafb_defined.red = colors[depth-1].red;
-	vesafb_defined.green = colors[depth-1].green;
-	vesafb_defined.blue = colors[depth-1].blue;
-	vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel;
-	vesafb_defined.grayscale = grayscale;
-	vesafb_defined.vmode = 0;
-	if (noaccel)
-		vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
-
-	minfo->fbops = matroxfb_ops;
-	minfo->fbcon.fbops = &minfo->fbops;
-	minfo->fbcon.pseudo_palette = minfo->cmap;
-	/* after __init time we are like module... no logo */
-	minfo->fbcon.flags = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT;
-	minfo->fbcon.flags |= FBINFO_PARTIAL_PAN_OK | 	 /* Prefer panning for scroll under MC viewer/edit */
-				      FBINFO_HWACCEL_COPYAREA |  /* We have hw-assisted bmove */
-				      FBINFO_HWACCEL_FILLRECT |  /* And fillrect */
-				      FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */
-				      FBINFO_HWACCEL_XPAN |      /* And we support both horizontal */
-				      FBINFO_HWACCEL_YPAN |      /* And vertical panning */
-				      FBINFO_READS_FAST;
-	minfo->video.len_usable &= PAGE_MASK;
-	fb_alloc_cmap(&minfo->fbcon.cmap, 256, 1);
-
-#ifndef MODULE
-	/* mode database is marked __init!!! */
-	if (!hotplug) {
-		fb_find_mode(&vesafb_defined, &minfo->fbcon, videomode[0] ? videomode : NULL,
-			NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
-	}
-#endif /* !MODULE */
-
-	/* mode modifiers */
-	if (hslen)
-		vesafb_defined.hsync_len = hslen;
-	if (vslen)
-		vesafb_defined.vsync_len = vslen;
-	if (left != ~0)
-		vesafb_defined.left_margin = left;
-	if (right != ~0)
-		vesafb_defined.right_margin = right;
-	if (upper != ~0)
-		vesafb_defined.upper_margin = upper;
-	if (lower != ~0)
-		vesafb_defined.lower_margin = lower;
-	if (xres)
-		vesafb_defined.xres = xres;
-	if (yres)
-		vesafb_defined.yres = yres;
-	if (sync != -1)
-		vesafb_defined.sync = sync;
-	else if (vesafb_defined.sync == ~0) {
-		vesafb_defined.sync = 0;
-		if (yres < 400)
-			vesafb_defined.sync |= FB_SYNC_HOR_HIGH_ACT;
-		else if (yres < 480)
-			vesafb_defined.sync |= FB_SYNC_VERT_HIGH_ACT;
-	}
-
-	/* fv, fh, maxclk limits was specified */
-	{
-		unsigned int tmp;
-
-		if (fv) {
-			tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
-				  + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
-			if ((tmp < fh) || (fh == 0)) fh = tmp;
-		}
-		if (fh) {
-			tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
-				  + vesafb_defined.right_margin + vesafb_defined.hsync_len);
-			if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
-		}
-		tmp = (maxclk + 499) / 500;
-		if (tmp) {
-			tmp = (2000000000 + tmp) / tmp;
-			if (tmp > pixclock) pixclock = tmp;
-		}
-	}
-	if (pixclock) {
-		if (pixclock < 2000)		/* > 500MHz */
-			pixclock = 4000;	/* 250MHz */
-		if (pixclock > 1000000)
-			pixclock = 1000000;	/* 1MHz */
-		vesafb_defined.pixclock = pixclock;
-	}
-
-	/* FIXME: Where to move this?! */
-#if defined(CONFIG_PPC_PMAC)
-#ifndef MODULE
-	if (machine_is(powermac)) {
-		struct fb_var_screeninfo var;
-		if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-			default_vmode = VMODE_640_480_60;
-#ifdef CONFIG_NVRAM
-		if (default_cmode == CMODE_NVRAM)
-			default_cmode = nvram_read_byte(NV_CMODE);
-#endif
-		if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
-			default_cmode = CMODE_8;
-		if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
-			var.accel_flags = vesafb_defined.accel_flags;
-			var.xoffset = var.yoffset = 0;
-			/* Note: mac_vmode_to_var() does not set all parameters */
-			vesafb_defined = var;
-		}
-	}
-#endif /* !MODULE */
-#endif /* CONFIG_PPC_PMAC */
-	vesafb_defined.xres_virtual = vesafb_defined.xres;
-	if (nopan) {
-		vesafb_defined.yres_virtual = vesafb_defined.yres;
-	} else {
-		vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
-							to yres_virtual * xres_virtual < 2^32 */
-	}
-	matroxfb_init_fix(minfo);
-	minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase);
-	/* Normalize values (namely yres_virtual) */
-	matroxfb_check_var(&vesafb_defined, &minfo->fbcon);
-	/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
-	 * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
-	 * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
-	 * anyway. But we at least tried... */
-	minfo->fbcon.var = vesafb_defined;
-	err = -EINVAL;
-
-	printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
-		vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
-		vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
-	printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
-		minfo->video.base, vaddr_va(minfo->video.vbase), minfo->video.len);
-
-/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
- * and we do not want currcon == 0 for subsequent framebuffers */
-
-	minfo->fbcon.device = &minfo->pcidev->dev;
-	if (register_framebuffer(&minfo->fbcon) < 0) {
-		goto failVideoIO;
-	}
-	fb_info(&minfo->fbcon, "%s frame buffer device\n", minfo->fbcon.fix.id);
-
-	/* there is no console on this fb... but we have to initialize hardware
-	 * until someone tells me what is proper thing to do */
-	if (!minfo->initialized) {
-		fb_info(&minfo->fbcon, "initializing hardware\n");
-		/* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
-		 * already before, so register_framebuffer works correctly. */
-		vesafb_defined.activate |= FB_ACTIVATE_FORCE;
-		fb_set_var(&minfo->fbcon, &vesafb_defined);
-	}
-
-	return 0;
-failVideoIO:;
-	matroxfb_g450_shutdown(minfo);
-	mga_iounmap(minfo->video.vbase);
-failCtrlIO:;
-	mga_iounmap(minfo->mmio.vbase);
-failVideoMR:;
-	release_mem_region(video_base_phys, minfo->video.len_maximum);
-failCtrlMR:;
-	release_mem_region(ctrlptr_phys, 16384);
-fail:;
-	return err;
-}
-
-static LIST_HEAD(matroxfb_list);
-static LIST_HEAD(matroxfb_driver_list);
-
-#define matroxfb_l(x) list_entry(x, struct matrox_fb_info, next_fb)
-#define matroxfb_driver_l(x) list_entry(x, struct matroxfb_driver, node)
-int matroxfb_register_driver(struct matroxfb_driver* drv) {
-	struct matrox_fb_info* minfo;
-
-	list_add(&drv->node, &matroxfb_driver_list);
-	for (minfo = matroxfb_l(matroxfb_list.next);
-	     minfo != matroxfb_l(&matroxfb_list);
-	     minfo = matroxfb_l(minfo->next_fb.next)) {
-		void* p;
-
-		if (minfo->drivers_count == MATROXFB_MAX_FB_DRIVERS)
-			continue;
-		p = drv->probe(minfo);
-		if (p) {
-			minfo->drivers_data[minfo->drivers_count] = p;
-			minfo->drivers[minfo->drivers_count++] = drv;
-		}
-	}
-	return 0;
-}
-
-void matroxfb_unregister_driver(struct matroxfb_driver* drv) {
-	struct matrox_fb_info* minfo;
-
-	list_del(&drv->node);
-	for (minfo = matroxfb_l(matroxfb_list.next);
-	     minfo != matroxfb_l(&matroxfb_list);
-	     minfo = matroxfb_l(minfo->next_fb.next)) {
-		int i;
-
-		for (i = 0; i < minfo->drivers_count; ) {
-			if (minfo->drivers[i] == drv) {
-				if (drv && drv->remove)
-					drv->remove(minfo, minfo->drivers_data[i]);
-				minfo->drivers[i] = minfo->drivers[--minfo->drivers_count];
-				minfo->drivers_data[i] = minfo->drivers_data[minfo->drivers_count];
-			} else
-				i++;
-		}
-	}
-}
-
-static void matroxfb_register_device(struct matrox_fb_info* minfo) {
-	struct matroxfb_driver* drv;
-	int i = 0;
-	list_add(&minfo->next_fb, &matroxfb_list);
-	for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
-	     drv != matroxfb_driver_l(&matroxfb_driver_list);
-	     drv = matroxfb_driver_l(drv->node.next)) {
-		if (drv && drv->probe) {
-			void *p = drv->probe(minfo);
-			if (p) {
-				minfo->drivers_data[i] = p;
-				minfo->drivers[i++] = drv;
-				if (i == MATROXFB_MAX_FB_DRIVERS)
-					break;
-			}
-		}
-	}
-	minfo->drivers_count = i;
-}
-
-static void matroxfb_unregister_device(struct matrox_fb_info* minfo) {
-	int i;
-
-	list_del(&minfo->next_fb);
-	for (i = 0; i < minfo->drivers_count; i++) {
-		struct matroxfb_driver* drv = minfo->drivers[i];
-
-		if (drv && drv->remove)
-			drv->remove(minfo, minfo->drivers_data[i]);
-	}
-}
-
-static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dummy) {
-	struct board* b;
-	u_int16_t svid;
-	u_int16_t sid;
-	struct matrox_fb_info* minfo;
-	int err;
-	u_int32_t cmd;
-	DBG(__func__)
-
-	svid = pdev->subsystem_vendor;
-	sid = pdev->subsystem_device;
-	for (b = dev_list; b->vendor; b++) {
-		if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < pdev->revision)) continue;
-		if (b->svid)
-			if ((b->svid != svid) || (b->sid != sid)) continue;
-		break;
-	}
-	/* not match... */
-	if (!b->vendor)
-		return -ENODEV;
-	if (dev > 0) {
-		/* not requested one... */
-		dev--;
-		return -ENODEV;
-	}
-	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
-	if (pci_enable_device(pdev)) {
-		return -1;
-	}
-
-	minfo = kzalloc(sizeof(*minfo), GFP_KERNEL);
-	if (!minfo)
-		return -1;
-
-	minfo->pcidev = pdev;
-	minfo->dead = 0;
-	minfo->usecount = 0;
-	minfo->userusecount = 0;
-
-	pci_set_drvdata(pdev, minfo);
-	/* DEVFLAGS */
-	minfo->devflags.memtype = memtype;
-	if (memtype != -1)
-		noinit = 0;
-	if (cmd & PCI_COMMAND_MEMORY) {
-		minfo->devflags.novga = novga;
-		minfo->devflags.nobios = nobios;
-		minfo->devflags.noinit = noinit;
-		/* subsequent heads always needs initialization and must not enable BIOS */
-		novga = 1;
-		nobios = 1;
-		noinit = 0;
-	} else {
-		minfo->devflags.novga = 1;
-		minfo->devflags.nobios = 1;
-		minfo->devflags.noinit = 0;
-	}
-
-	minfo->devflags.nopciretry = no_pci_retry;
-	minfo->devflags.mga_24bpp_fix = inv24;
-	minfo->devflags.precise_width = option_precise_width;
-	minfo->devflags.sgram = sgram;
-	minfo->capable.cross4MB = cross4MB;
-
-	spin_lock_init(&minfo->lock.DAC);
-	spin_lock_init(&minfo->lock.accel);
-	init_rwsem(&minfo->crtc2.lock);
-	init_rwsem(&minfo->altout.lock);
-	mutex_init(&minfo->fbcon.mm_lock);
-	minfo->irq_flags = 0;
-	init_waitqueue_head(&minfo->crtc1.vsync.wait);
-	init_waitqueue_head(&minfo->crtc2.vsync.wait);
-	minfo->crtc1.panpos = -1;
-
-	err = initMatrox2(minfo, b);
-	if (!err) {
-		matroxfb_register_device(minfo);
-		return 0;
-	}
-	kfree(minfo);
-	return -1;
-}
-
-static void pci_remove_matrox(struct pci_dev* pdev) {
-	struct matrox_fb_info* minfo;
-
-	minfo = pci_get_drvdata(pdev);
-	matroxfb_remove(minfo, 1);
-}
-
-static struct pci_device_id matroxfb_devices[] = {
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2_AGP,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-#endif
-#ifdef CONFIG_FB_MATROX_MYSTIQUE
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-#endif
-#ifdef CONFIG_FB_MATROX_G
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_MM,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_PCI,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G400,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G550,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-#endif
-	{0,			0,
-		0,		0,		0, 0, 0}
-};
-
-MODULE_DEVICE_TABLE(pci, matroxfb_devices);
-
-
-static struct pci_driver matroxfb_driver = {
-	.name =		"matroxfb",
-	.id_table =	matroxfb_devices,
-	.probe =	matroxfb_probe,
-	.remove =	pci_remove_matrox,
-};
-
-/* **************************** init-time only **************************** */
-
-#define RSResolution(X)	((X) & 0x0F)
-#define RS640x400	1
-#define RS640x480	2
-#define RS800x600	3
-#define RS1024x768	4
-#define RS1280x1024	5
-#define RS1600x1200	6
-#define RS768x576	7
-#define RS960x720	8
-#define RS1152x864	9
-#define RS1408x1056	10
-#define RS640x350	11
-#define RS1056x344	12	/* 132 x 43 text */
-#define RS1056x400	13	/* 132 x 50 text */
-#define RS1056x480	14	/* 132 x 60 text */
-#define RSNoxNo		15
-/* 10-FF */
-static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
-	{  640,  400,  48, 16, 39,  8,  96, 2, 70 },
-	{  640,  480,  48, 16, 33, 10,  96, 2, 60 },
-	{  800,  600, 144, 24, 28,  8, 112, 6, 60 },
-	{ 1024,  768, 160, 32, 30,  4, 128, 4, 60 },
-	{ 1280, 1024, 224, 32, 32,  4, 136, 4, 60 },
-	{ 1600, 1200, 272, 48, 32,  5, 152, 5, 60 },
-	{  768,  576, 144, 16, 28,  6, 112, 4, 60 },
-	{  960,  720, 144, 24, 28,  8, 112, 4, 60 },
-	{ 1152,  864, 192, 32, 30,  4, 128, 4, 60 },
-	{ 1408, 1056, 256, 40, 32,  5, 144, 5, 60 },
-	{  640,  350,  48, 16, 39,  8,  96, 2, 70 },
-	{ 1056,  344,  96, 24, 59, 44, 160, 2, 70 },
-	{ 1056,  400,  96, 24, 39,  8, 160, 2, 70 },
-	{ 1056,  480,  96, 24, 36, 12, 160, 3, 60 },
-	{    0,    0,  ~0, ~0, ~0, ~0,   0, 0,  0 }
-};
-
-#define RSCreate(X,Y)	((X) | ((Y) << 8))
-static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
-/* default must be first */
-	{    ~0, RSCreate(RSNoxNo,     RS8bpp ) },
-	{ 0x101, RSCreate(RS640x480,   RS8bpp ) },
-	{ 0x100, RSCreate(RS640x400,   RS8bpp ) },
-	{ 0x180, RSCreate(RS768x576,   RS8bpp ) },
-	{ 0x103, RSCreate(RS800x600,   RS8bpp ) },
-	{ 0x188, RSCreate(RS960x720,   RS8bpp ) },
-	{ 0x105, RSCreate(RS1024x768,  RS8bpp ) },
-	{ 0x190, RSCreate(RS1152x864,  RS8bpp ) },
-	{ 0x107, RSCreate(RS1280x1024, RS8bpp ) },
-	{ 0x198, RSCreate(RS1408x1056, RS8bpp ) },
-	{ 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
-	{ 0x110, RSCreate(RS640x480,   RS15bpp) },
-	{ 0x181, RSCreate(RS768x576,   RS15bpp) },
-	{ 0x113, RSCreate(RS800x600,   RS15bpp) },
-	{ 0x189, RSCreate(RS960x720,   RS15bpp) },
-	{ 0x116, RSCreate(RS1024x768,  RS15bpp) },
-	{ 0x191, RSCreate(RS1152x864,  RS15bpp) },
-	{ 0x119, RSCreate(RS1280x1024, RS15bpp) },
-	{ 0x199, RSCreate(RS1408x1056, RS15bpp) },
-	{ 0x11D, RSCreate(RS1600x1200, RS15bpp) },
-	{ 0x111, RSCreate(RS640x480,   RS16bpp) },
-	{ 0x182, RSCreate(RS768x576,   RS16bpp) },
-	{ 0x114, RSCreate(RS800x600,   RS16bpp) },
-	{ 0x18A, RSCreate(RS960x720,   RS16bpp) },
-	{ 0x117, RSCreate(RS1024x768,  RS16bpp) },
-	{ 0x192, RSCreate(RS1152x864,  RS16bpp) },
-	{ 0x11A, RSCreate(RS1280x1024, RS16bpp) },
-	{ 0x19A, RSCreate(RS1408x1056, RS16bpp) },
-	{ 0x11E, RSCreate(RS1600x1200, RS16bpp) },
-	{ 0x1B2, RSCreate(RS640x480,   RS24bpp) },
-	{ 0x184, RSCreate(RS768x576,   RS24bpp) },
-	{ 0x1B5, RSCreate(RS800x600,   RS24bpp) },
-	{ 0x18C, RSCreate(RS960x720,   RS24bpp) },
-	{ 0x1B8, RSCreate(RS1024x768,  RS24bpp) },
-	{ 0x194, RSCreate(RS1152x864,  RS24bpp) },
-	{ 0x1BB, RSCreate(RS1280x1024, RS24bpp) },
-	{ 0x19C, RSCreate(RS1408x1056, RS24bpp) },
-	{ 0x1BF, RSCreate(RS1600x1200, RS24bpp) },
-	{ 0x112, RSCreate(RS640x480,   RS32bpp) },
-	{ 0x183, RSCreate(RS768x576,   RS32bpp) },
-	{ 0x115, RSCreate(RS800x600,   RS32bpp) },
-	{ 0x18B, RSCreate(RS960x720,   RS32bpp) },
-	{ 0x118, RSCreate(RS1024x768,  RS32bpp) },
-	{ 0x193, RSCreate(RS1152x864,  RS32bpp) },
-	{ 0x11B, RSCreate(RS1280x1024, RS32bpp) },
-	{ 0x19B, RSCreate(RS1408x1056, RS32bpp) },
-	{ 0x11F, RSCreate(RS1600x1200, RS32bpp) },
-	{ 0x010, RSCreate(RS640x350,   RS4bpp ) },
-	{ 0x012, RSCreate(RS640x480,   RS4bpp ) },
-	{ 0x102, RSCreate(RS800x600,   RS4bpp ) },
-	{ 0x104, RSCreate(RS1024x768,  RS4bpp ) },
-	{ 0x106, RSCreate(RS1280x1024, RS4bpp ) },
-	{     0, 0				}};
-
-static void __init matroxfb_init_params(void) {
-	/* fh from kHz to Hz */
-	if (fh < 1000)
-		fh *= 1000;	/* 1kHz minimum */
-	/* maxclk */
-	if (maxclk < 1000) maxclk *= 1000;	/* kHz -> Hz, MHz -> kHz */
-	if (maxclk < 1000000) maxclk *= 1000;	/* kHz -> Hz, 1MHz minimum */
-	/* fix VESA number */
-	if (vesa != ~0)
-		vesa &= 0x1DFF;		/* mask out clearscreen, acceleration and so on */
-
-	/* static settings */
-	for (RSptr = vesamap; RSptr->vesa; RSptr++) {
-		if (RSptr->vesa == vesa) break;
-	}
-	if (!RSptr->vesa) {
-		printk(KERN_ERR "Invalid vesa mode 0x%04X\n", vesa);
-		RSptr = vesamap;
-	}
-	{
-		int res = RSResolution(RSptr->info)-1;
-		if (left == ~0)
-			left = timmings[res].left;
-		if (!xres)
-			xres = timmings[res].xres;
-		if (right == ~0)
-			right = timmings[res].right;
-		if (!hslen)
-			hslen = timmings[res].hslen;
-		if (upper == ~0)
-			upper = timmings[res].upper;
-		if (!yres)
-			yres = timmings[res].yres;
-		if (lower == ~0)
-			lower = timmings[res].lower;
-		if (!vslen)
-			vslen = timmings[res].vslen;
-		if (!(fv||fh||maxclk||pixclock))
-			fv = timmings[res].vfreq;
-		if (depth == -1)
-			depth = RSDepth(RSptr->info);
-	}
-}
-
-static int __init matrox_init(void) {
-	int err;
-
-	matroxfb_init_params();
-	err = pci_register_driver(&matroxfb_driver);
-	dev = -1;	/* accept all new devices... */
-	return err;
-}
-
-/* **************************** exit-time only **************************** */
-
-static void __exit matrox_done(void) {
-	pci_unregister_driver(&matroxfb_driver);
-}
-
-#ifndef MODULE
-
-/* ************************* init in-kernel code ************************** */
-
-static int __init matroxfb_setup(char *options) {
-	char *this_opt;
-
-	DBG(__func__)
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt) continue;
-
-		dprintk("matroxfb_setup: option %s\n", this_opt);
-
-		if (!strncmp(this_opt, "dev:", 4))
-			dev = simple_strtoul(this_opt+4, NULL, 0);
-		else if (!strncmp(this_opt, "depth:", 6)) {
-			switch (simple_strtoul(this_opt+6, NULL, 0)) {
-				case 0: depth = RSText; break;
-				case 4: depth = RS4bpp; break;
-				case 8: depth = RS8bpp; break;
-				case 15:depth = RS15bpp; break;
-				case 16:depth = RS16bpp; break;
-				case 24:depth = RS24bpp; break;
-				case 32:depth = RS32bpp; break;
-				default:
-					printk(KERN_ERR "matroxfb: unsupported color depth\n");
-			}
-		} else if (!strncmp(this_opt, "xres:", 5))
-			xres = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "yres:", 5))
-			yres = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "vslen:", 6))
-			vslen = simple_strtoul(this_opt+6, NULL, 0);
-		else if (!strncmp(this_opt, "hslen:", 6))
-			hslen = simple_strtoul(this_opt+6, NULL, 0);
-		else if (!strncmp(this_opt, "left:", 5))
-			left = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "right:", 6))
-			right = simple_strtoul(this_opt+6, NULL, 0);
-		else if (!strncmp(this_opt, "upper:", 6))
-			upper = simple_strtoul(this_opt+6, NULL, 0);
-		else if (!strncmp(this_opt, "lower:", 6))
-			lower = simple_strtoul(this_opt+6, NULL, 0);
-		else if (!strncmp(this_opt, "pixclock:", 9))
-			pixclock = simple_strtoul(this_opt+9, NULL, 0);
-		else if (!strncmp(this_opt, "sync:", 5))
-			sync = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "vesa:", 5))
-			vesa = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strncmp(this_opt, "maxclk:", 7))
-			maxclk = simple_strtoul(this_opt+7, NULL, 0);
-		else if (!strncmp(this_opt, "fh:", 3))
-			fh = simple_strtoul(this_opt+3, NULL, 0);
-		else if (!strncmp(this_opt, "fv:", 3))
-			fv = simple_strtoul(this_opt+3, NULL, 0);
-		else if (!strncmp(this_opt, "mem:", 4))
-			mem = simple_strtoul(this_opt+4, NULL, 0);
-		else if (!strncmp(this_opt, "mode:", 5))
-			strlcpy(videomode, this_opt+5, sizeof(videomode));
-		else if (!strncmp(this_opt, "outputs:", 8))
-			strlcpy(outputs, this_opt+8, sizeof(outputs));
-		else if (!strncmp(this_opt, "dfp:", 4)) {
-			dfp_type = simple_strtoul(this_opt+4, NULL, 0);
-			dfp = 1;
-		}
-#ifdef CONFIG_PPC_PMAC
-		else if (!strncmp(this_opt, "vmode:", 6)) {
-			unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
-			if (vmode > 0 && vmode <= VMODE_MAX)
-				default_vmode = vmode;
-		} else if (!strncmp(this_opt, "cmode:", 6)) {
-			unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
-			switch (cmode) {
-				case 0:
-				case 8:
-					default_cmode = CMODE_8;
-					break;
-				case 15:
-				case 16:
-					default_cmode = CMODE_16;
-					break;
-				case 24:
-				case 32:
-					default_cmode = CMODE_32;
-					break;
-			}
-		}
-#endif
-		else if (!strcmp(this_opt, "disabled"))	/* nodisabled does not exist */
-			disabled = 1;
-		else if (!strcmp(this_opt, "enabled"))	/* noenabled does not exist */
-			disabled = 0;
-		else if (!strcmp(this_opt, "sgram"))	/* nosgram == sdram */
-			sgram = 1;
-		else if (!strcmp(this_opt, "sdram"))
-			sgram = 0;
-		else if (!strncmp(this_opt, "memtype:", 8))
-			memtype = simple_strtoul(this_opt+8, NULL, 0);
-		else {
-			int value = 1;
-
-			if (!strncmp(this_opt, "no", 2)) {
-				value = 0;
-				this_opt += 2;
-			}
-			if (! strcmp(this_opt, "inverse"))
-				inverse = value;
-			else if (!strcmp(this_opt, "accel"))
-				noaccel = !value;
-			else if (!strcmp(this_opt, "pan"))
-				nopan = !value;
-			else if (!strcmp(this_opt, "pciretry"))
-				no_pci_retry = !value;
-			else if (!strcmp(this_opt, "vga"))
-				novga = !value;
-			else if (!strcmp(this_opt, "bios"))
-				nobios = !value;
-			else if (!strcmp(this_opt, "init"))
-				noinit = !value;
-#ifdef CONFIG_MTRR
-			else if (!strcmp(this_opt, "mtrr"))
-				mtrr = value;
-#endif
-			else if (!strcmp(this_opt, "inv24"))
-				inv24 = value;
-			else if (!strcmp(this_opt, "cross4MB"))
-				cross4MB = value;
-			else if (!strcmp(this_opt, "grayscale"))
-				grayscale = value;
-			else if (!strcmp(this_opt, "dfp"))
-				dfp = value;
-			else {
-				strlcpy(videomode, this_opt, sizeof(videomode));
-			}
-		}
-	}
-	return 0;
-}
-
-static int __initdata initialized = 0;
-
-static int __init matroxfb_init(void)
-{
-	char *option = NULL;
-	int err = 0;
-
-	DBG(__func__)
-
-	if (fb_get_options("matroxfb", &option))
-		return -ENODEV;
-	matroxfb_setup(option);
-
-	if (disabled)
-		return -ENXIO;
-	if (!initialized) {
-		initialized = 1;
-		err = matrox_init();
-	}
-	hotplug = 1;
-	/* never return failure, user can hotplug matrox later... */
-	return err;
-}
-
-module_init(matroxfb_init);
-
-#else
-
-/* *************************** init module code **************************** */
-
-MODULE_AUTHOR("(c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450/G550");
-MODULE_LICENSE("GPL");
-
-module_param(mem, int, 0);
-MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
-module_param(disabled, int, 0);
-MODULE_PARM_DESC(disabled, "Disabled (0 or 1=disabled) (default=0)");
-module_param(noaccel, int, 0);
-MODULE_PARM_DESC(noaccel, "Do not use accelerating engine (0 or 1=disabled) (default=0)");
-module_param(nopan, int, 0);
-MODULE_PARM_DESC(nopan, "Disable pan on startup (0 or 1=disabled) (default=0)");
-module_param(no_pci_retry, int, 0);
-MODULE_PARM_DESC(no_pci_retry, "PCI retries enabled (0 or 1=disabled) (default=0)");
-module_param(novga, int, 0);
-MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
-module_param(nobios, int, 0);
-MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
-module_param(noinit, int, 0);
-MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
-module_param(memtype, int, 0);
-MODULE_PARM_DESC(memtype, "Memory type for G200/G400 (see Documentation/fb/matroxfb.txt for explanation) (default=3 for G200, 0 for G400)");
-#ifdef CONFIG_MTRR
-module_param(mtrr, int, 0);
-MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
-#endif
-module_param(sgram, int, 0);
-MODULE_PARM_DESC(sgram, "Indicates that G100/G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
-module_param(inv24, int, 0);
-MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
-module_param(inverse, int, 0);
-MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)");
-module_param(dev, int, 0);
-MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)");
-module_param(vesa, int, 0);
-MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
-module_param(xres, int, 0);
-MODULE_PARM_DESC(xres, "Horizontal resolution (px), overrides xres from vesa (default=vesa)");
-module_param(yres, int, 0);
-MODULE_PARM_DESC(yres, "Vertical resolution (scans), overrides yres from vesa (default=vesa)");
-module_param(upper, int, 0);
-MODULE_PARM_DESC(upper, "Upper blank space (scans), overrides upper from vesa (default=vesa)");
-module_param(lower, int, 0);
-MODULE_PARM_DESC(lower, "Lower blank space (scans), overrides lower from vesa (default=vesa)");
-module_param(vslen, int, 0);
-MODULE_PARM_DESC(vslen, "Vertical sync length (scans), overrides lower from vesa (default=vesa)");
-module_param(left, int, 0);
-MODULE_PARM_DESC(left, "Left blank space (px), overrides left from vesa (default=vesa)");
-module_param(right, int, 0);
-MODULE_PARM_DESC(right, "Right blank space (px), overrides right from vesa (default=vesa)");
-module_param(hslen, int, 0);
-MODULE_PARM_DESC(hslen, "Horizontal sync length (px), overrides hslen from vesa (default=vesa)");
-module_param(pixclock, int, 0);
-MODULE_PARM_DESC(pixclock, "Pixelclock (ns), overrides pixclock from vesa (default=vesa)");
-module_param(sync, int, 0);
-MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
-module_param(depth, int, 0);
-MODULE_PARM_DESC(depth, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
-module_param(maxclk, int, 0);
-MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
-module_param(fh, int, 0);
-MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
-module_param(fv, int, 0);
-MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
-"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"");
-module_param(grayscale, int, 0);
-MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
-module_param(cross4MB, int, 0);
-MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
-module_param(dfp, int, 0);
-MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)");
-module_param(dfp_type, int, 0);
-MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)");
-module_param_string(outputs, outputs, sizeof(outputs), 0);
-MODULE_PARM_DESC(outputs, "Specifies which CRTC is mapped to which output (string of up to three letters, consisting of 0 (disabled), 1 (CRTC1), 2 (CRTC2)) (default=111 for Gx50, 101 for G200/G400 with DFP, and 100 for all other devices)");
-#ifdef CONFIG_PPC_PMAC
-module_param_named(vmode, default_vmode, int, 0);
-MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
-module_param_named(cmode, default_cmode, int, 0);
-MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit default)");
-#endif
-
-int __init init_module(void){
-
-	DBG(__func__)
-
-	if (disabled)
-		return -ENXIO;
-
-	if (depth == 0)
-		depth = RSText;
-	else if (depth == 4)
-		depth = RS4bpp;
-	else if (depth == 8)
-		depth = RS8bpp;
-	else if (depth == 15)
-		depth = RS15bpp;
-	else if (depth == 16)
-		depth = RS16bpp;
-	else if (depth == 24)
-		depth = RS24bpp;
-	else if (depth == 32)
-		depth = RS32bpp;
-	else if (depth != -1) {
-		printk(KERN_ERR "matroxfb: depth %d is not supported, using default\n", depth);
-		depth = -1;
-	}
-	matrox_init();
-	/* never return failure; user can hotplug matrox later... */
-	return 0;
-}
-#endif	/* MODULE */
-
-module_exit(matrox_done);
-EXPORT_SYMBOL(matroxfb_register_driver);
-EXPORT_SYMBOL(matroxfb_unregister_driver);
-EXPORT_SYMBOL(matroxfb_wait_for_sync);
-EXPORT_SYMBOL(matroxfb_enable_irq);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
deleted file mode 100644
index 556d96ce40bf..000000000000
--- a/drivers/video/matrox/matroxfb_base.h
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- */
-#ifndef __MATROXFB_H__
-#define __MATROXFB_H__
-
-/* general, but fairly heavy, debugging */
-#undef MATROXFB_DEBUG
-
-/* heavy debugging: */
-/* -- logs putc[s], so every time a char is displayed, it's logged */
-#undef MATROXFB_DEBUG_HEAVY
-
-/* This one _could_ cause infinite loops */
-/* It _does_ cause lots and lots of messages during idle loops */
-#undef MATROXFB_DEBUG_LOOP
-
-/* Debug register calls, too? */
-#undef MATROXFB_DEBUG_REG
-
-/* Guard accelerator accesses with spin_lock_irqsave... */
-#undef MATROXFB_USE_SPINLOCKS
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/kd.h>
-
-#include <asm/io.h>
-#include <asm/unaligned.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#if defined(CONFIG_PPC_PMAC)
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include "../macmodes.h"
-#endif
-
-#ifdef MATROXFB_DEBUG
-
-#define DEBUG
-#define DBG(x)		printk(KERN_DEBUG "matroxfb: %s\n", (x));
-
-#ifdef MATROXFB_DEBUG_HEAVY
-#define DBG_HEAVY(x)	DBG(x)
-#else /* MATROXFB_DEBUG_HEAVY */
-#define DBG_HEAVY(x)	/* DBG_HEAVY */
-#endif /* MATROXFB_DEBUG_HEAVY */
-
-#ifdef MATROXFB_DEBUG_LOOP
-#define DBG_LOOP(x)	DBG(x)
-#else /* MATROXFB_DEBUG_LOOP */
-#define DBG_LOOP(x)	/* DBG_LOOP */
-#endif /* MATROXFB_DEBUG_LOOP */
-
-#ifdef MATROXFB_DEBUG_REG
-#define DBG_REG(x)	DBG(x)
-#else /* MATROXFB_DEBUG_REG */
-#define DBG_REG(x)	/* DBG_REG */
-#endif /* MATROXFB_DEBUG_REG */
-
-#else /* MATROXFB_DEBUG */
-
-#define DBG(x)		/* DBG */
-#define DBG_HEAVY(x)	/* DBG_HEAVY */
-#define DBG_REG(x)	/* DBG_REG */
-#define DBG_LOOP(x)	/* DBG_LOOP */
-
-#endif /* MATROXFB_DEBUG */
-
-#ifdef DEBUG
-#define dprintk(X...)	printk(X)
-#else
-#define dprintk(X...)
-#endif
-
-#ifndef PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
-#define PCI_SS_VENDOR_ID_SIEMENS_NIXDORF	0x110A
-#endif
-#ifndef PCI_SS_VENDOR_ID_MATROX
-#define PCI_SS_VENDOR_ID_MATROX		PCI_VENDOR_ID_MATROX
-#endif
-
-#ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
-#define PCI_SS_ID_MATROX_GENERIC		0xFF00
-#define PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP	0xFF01
-#define PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP	0xFF02
-#define PCI_SS_ID_MATROX_MILLENIUM_G200_AGP	0xFF03
-#define PCI_SS_ID_MATROX_MARVEL_G200_AGP	0xFF04
-#define PCI_SS_ID_MATROX_MGA_G100_PCI		0xFF05
-#define PCI_SS_ID_MATROX_MGA_G100_AGP		0x1001
-#define PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP	0x2179
-#define PCI_SS_ID_SIEMENS_MGA_G100_AGP		0x001E /* 30 */
-#define PCI_SS_ID_SIEMENS_MGA_G200_AGP		0x0032 /* 50 */
-#endif
-
-#define MX_VISUAL_TRUECOLOR	FB_VISUAL_DIRECTCOLOR
-#define MX_VISUAL_DIRECTCOLOR	FB_VISUAL_TRUECOLOR
-#define MX_VISUAL_PSEUDOCOLOR	FB_VISUAL_PSEUDOCOLOR
-
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
-
-/* G-series and Mystique have (almost) same DAC */
-#undef NEED_DAC1064
-#if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G)
-#define NEED_DAC1064 1
-#endif
-
-typedef struct {
-	void __iomem*	vaddr;
-} vaddr_t;
-
-static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
-	return readb(va.vaddr + offs);
-}
-
-static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
-	writeb(value, va.vaddr + offs);
-}
-
-static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
-	writew(value, va.vaddr + offs);
-}
-
-static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
-	return readl(va.vaddr + offs);
-}
-
-static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
-	writel(value, va.vaddr + offs);
-}
-
-static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
-#if defined(__alpha__) || defined(__i386__) || defined(__x86_64__)
-	/*
-	 * iowrite32_rep works for us if:
-	 *  (1) Copies data as 32bit quantities, not byte after byte,
-	 *  (2) Performs LE ordered stores, and
-	 *  (3) It copes with unaligned source (destination is guaranteed to be page
-	 *      aligned and length is guaranteed to be multiple of 4).
-	 */
-	iowrite32_rep(va.vaddr, src, len >> 2);
-#else
-        u_int32_t __iomem* addr = va.vaddr;
-
-	if ((unsigned long)src & 3) {
-		while (len >= 4) {
-			fb_writel(get_unaligned((u32 *)src), addr);
-			addr++;
-			len -= 4;
-			src += 4;
-		}
-	} else {
-		while (len >= 4) {
-			fb_writel(*(u32 *)src, addr);
-			addr++;
-			len -= 4;
-			src += 4;
-		}
-	}
-#endif
-}
-
-static inline void vaddr_add(vaddr_t* va, unsigned long offs) {
-	va->vaddr += offs;
-}
-
-static inline void __iomem* vaddr_va(vaddr_t va) {
-	return va.vaddr;
-}
-
-#define MGA_IOREMAP_NORMAL	0
-#define MGA_IOREMAP_NOCACHE	1
-
-#define MGA_IOREMAP_FB		MGA_IOREMAP_NOCACHE
-#define MGA_IOREMAP_MMIO	MGA_IOREMAP_NOCACHE
-static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags, vaddr_t* virt) {
-	if (flags & MGA_IOREMAP_NOCACHE)
-		virt->vaddr = ioremap_nocache(phys, size);
-	else
-		virt->vaddr = ioremap(phys, size);
-	return (virt->vaddr == NULL); /* 0, !0... 0, error_code in future */
-}
-
-static inline void mga_iounmap(vaddr_t va) {
-	iounmap(va.vaddr);
-}
-
-struct my_timming {
-	unsigned int pixclock;
-	int mnp;
-	unsigned int crtc;
-	unsigned int HDisplay;
-	unsigned int HSyncStart;
-	unsigned int HSyncEnd;
-	unsigned int HTotal;
-	unsigned int VDisplay;
-	unsigned int VSyncStart;
-	unsigned int VSyncEnd;
-	unsigned int VTotal;
-	unsigned int sync;
-	int	     dblscan;
-	int	     interlaced;
-	unsigned int delay;	/* CRTC delay */
-};
-
-enum { M_SYSTEM_PLL, M_PIXEL_PLL_A, M_PIXEL_PLL_B, M_PIXEL_PLL_C, M_VIDEO_PLL };
-
-struct matrox_pll_cache {
-	unsigned int	valid;
-	struct {
-		unsigned int	mnp_key;
-		unsigned int	mnp_value;
-		      } data[4];
-};
-
-struct matrox_pll_limits {
-	unsigned int	vcomin;
-	unsigned int	vcomax;
-};
-
-struct matrox_pll_features {
-	unsigned int	vco_freq_min;
-	unsigned int	ref_freq;
-	unsigned int	feed_div_min;
-	unsigned int	feed_div_max;
-	unsigned int	in_div_min;
-	unsigned int	in_div_max;
-	unsigned int	post_shift_max;
-};
-
-struct matroxfb_par
-{
-	unsigned int	final_bppShift;
-	unsigned int	cmap_len;
-	struct {
-		unsigned int bytes;
-		unsigned int pixels;
-		unsigned int chunks;
-		      } ydstorg;
-};
-
-struct matrox_fb_info;
-
-struct matrox_DAC1064_features {
-	u_int8_t	xvrefctrl;
-	u_int8_t	xmiscctrl;
-};
-
-/* current hardware status */
-struct mavenregs {
-	u_int8_t regs[256];
-	int	 mode;
-	int	 vlines;
-	int	 xtal;
-	int	 fv;
-
-	u_int16_t htotal;
-	u_int16_t hcorr;
-};
-
-struct matrox_crtc2 {
-	u_int32_t ctl;
-};
-
-struct matrox_hw_state {
-	u_int32_t	MXoptionReg;
-	unsigned char	DACclk[6];
-	unsigned char	DACreg[80];
-	unsigned char	MiscOutReg;
-	unsigned char	DACpal[768];
-	unsigned char	CRTC[25];
-	unsigned char	CRTCEXT[9];
-	unsigned char	SEQ[5];
-	/* unused for MGA mode, but who knows... */
-	unsigned char	GCTL[9];
-	/* unused for MGA mode, but who knows... */
-	unsigned char	ATTR[21];
-
-	/* TVOut only */
-	struct mavenregs	maven;
-
-	struct matrox_crtc2	crtc2;
-};
-
-struct matrox_accel_data {
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-	unsigned char	ramdac_rev;
-#endif
-	u_int32_t	m_dwg_rect;
-	u_int32_t	m_opmode;
-	u_int32_t	m_access;
-	u_int32_t	m_pitch;
-};
-
-struct v4l2_queryctrl;
-struct v4l2_control;
-
-struct matrox_altout {
-	const char	*name;
-	int		(*compute)(void* altout_dev, struct my_timming* input);
-	int		(*program)(void* altout_dev);
-	int		(*start)(void* altout_dev);
-	int		(*verifymode)(void* altout_dev, u_int32_t mode);
-	int		(*getqueryctrl)(void* altout_dev,
-					struct v4l2_queryctrl* ctrl);
-	int		(*getctrl)(void* altout_dev, 
-				   struct v4l2_control* ctrl);
-	int		(*setctrl)(void* altout_dev, 
-				   struct v4l2_control* ctrl);
-};
-
-#define MATROXFB_SRC_NONE	0
-#define MATROXFB_SRC_CRTC1	1
-#define MATROXFB_SRC_CRTC2	2
-
-enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 };
-
-struct matrox_bios {
-	unsigned int	bios_valid : 1;
-	unsigned int	pins_len;
-	unsigned char	pins[128];
-	struct {
-		unsigned char vMaj, vMin, vRev;
-		      } version;
-	struct {
-		unsigned char state, tvout;
-		      } output;
-};
-
-struct matrox_switch;
-struct matroxfb_driver;
-struct matroxfb_dh_fb_info;
-
-struct matrox_vsync {
-	wait_queue_head_t	wait;
-	unsigned int		cnt;
-};
-
-struct matrox_fb_info {
-	struct fb_info		fbcon;
-
-	struct list_head	next_fb;
-
-	int			dead;
-	int                     initialized;
-	unsigned int		usecount;
-
-	unsigned int		userusecount;
-	unsigned long		irq_flags;
-
-	struct matroxfb_par	curr;
-	struct matrox_hw_state	hw;
-
-	struct matrox_accel_data accel;
-
-	struct pci_dev*		pcidev;
-
-	struct {
-		struct matrox_vsync	vsync;
-		unsigned int	pixclock;
-		int		mnp;
-		int		panpos;
-			      } crtc1;
-	struct {
-		struct matrox_vsync	vsync;
-		unsigned int 	pixclock;
-		int		mnp;
-	struct matroxfb_dh_fb_info*	info;
-	struct rw_semaphore	lock;
-			      } crtc2;
-	struct {
-	struct rw_semaphore	lock;
-	struct {
-		int brightness, contrast, saturation, hue, gamma;
-		int testout, deflicker;
-				} tvo_params;
-			      } altout;
-#define MATROXFB_MAX_OUTPUTS		3
-	struct {
-	unsigned int		src;
-	struct matrox_altout*	output;
-	void*			data;
-	unsigned int		mode;
-	unsigned int		default_src;
-			      } outputs[MATROXFB_MAX_OUTPUTS];
-
-#define MATROXFB_MAX_FB_DRIVERS		5
-	struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]);
-	void*			(drivers_data[MATROXFB_MAX_FB_DRIVERS]);
-	unsigned int		drivers_count;
-
-	struct {
-	unsigned long	base;	/* physical */
-	vaddr_t		vbase;	/* CPU view */
-	unsigned int	len;
-	unsigned int	len_usable;
-	unsigned int	len_maximum;
-		      } video;
-
-	struct {
-	unsigned long	base;	/* physical */
-	vaddr_t		vbase;	/* CPU view */
-	unsigned int	len;
-		      } mmio;
-
-	unsigned int	max_pixel_clock;
-	unsigned int	max_pixel_clock_panellink;
-
-	struct matrox_switch*	hw_switch;
-
-	struct {
-		struct matrox_pll_features pll;
-		struct matrox_DAC1064_features DAC1064;
-			      } features;
-	struct {
-		spinlock_t	DAC;
-		spinlock_t	accel;
-			      } lock;
-
-	enum mga_chip		chip;
-
-	int			interleave;
-	int			millenium;
-	int			milleniumII;
-	struct {
-		int		cfb4;
-		const int*	vxres;
-		int		cross4MB;
-		int		text;
-		int		plnwt;
-		int		srcorg;
-			      } capable;
-#ifdef CONFIG_MTRR
-	struct {
-		int		vram;
-		int		vram_valid;
-			      } mtrr;
-#endif
-	struct {
-		int		precise_width;
-		int		mga_24bpp_fix;
-		int		novga;
-		int		nobios;
-		int		nopciretry;
-		int		noinit;
-		int		sgram;
-		int		support32MB;
-
-		int		accelerator;
-		int		text_type_aux;
-		int		video64bits;
-		int		crtc2;
-		int		maven_capable;
-		unsigned int	vgastep;
-		unsigned int	textmode;
-		unsigned int	textstep;
-		unsigned int	textvram;	/* character cells */
-		unsigned int	ydstorg;	/* offset in bytes from video start to usable memory */
-						/* 0 except for 6MB Millenium */
-		int		memtype;
-		int		g450dac;
-		int		dfp_type;
-		int		panellink;	/* G400 DFP possible (not G450/G550) */
-		int		dualhead;
-		unsigned int	fbResource;
-			      } devflags;
-	struct fb_ops		fbops;
-	struct matrox_bios	bios;
-	struct {
-		struct matrox_pll_limits	pixel;
-		struct matrox_pll_limits	system;
-		struct matrox_pll_limits	video;
-			      } limits;
-	struct {
-		struct matrox_pll_cache	pixel;
-		struct matrox_pll_cache	system;
-		struct matrox_pll_cache	video;
-				      } cache;
-	struct {
-		struct {
-			unsigned int	video;
-			unsigned int	system;
-				      } pll;
-		struct {
-			u_int32_t	opt;
-			u_int32_t	opt2;
-			u_int32_t	opt3;
-			u_int32_t	mctlwtst;
-			u_int32_t	mctlwtst_core;
-			u_int32_t	memmisc;
-			u_int32_t	memrdbk;
-			u_int32_t	maccess;
-				      } reg;
-		struct {
-			unsigned int	ddr:1,
-			                emrswen:1,
-					dll:1;
-				      } memory;
-			      } values;
-	u_int32_t cmap[16];
-};
-
-#define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
-
-struct matrox_switch {
-	int	(*preinit)(struct matrox_fb_info *minfo);
-	void	(*reset)(struct matrox_fb_info *minfo);
-	int	(*init)(struct matrox_fb_info *minfo, struct my_timming*);
-	void	(*restore)(struct matrox_fb_info *minfo);
-};
-
-struct matroxfb_driver {
-	struct list_head	node;
-	char*			name;
-	void*			(*probe)(struct matrox_fb_info* info);
-	void			(*remove)(struct matrox_fb_info* info, void* data);
-};
-
-int matroxfb_register_driver(struct matroxfb_driver* drv);
-void matroxfb_unregister_driver(struct matroxfb_driver* drv);
-
-#define PCI_OPTION_REG	0x40
-#define   PCI_OPTION_ENABLE_ROM		0x40000000
-
-#define PCI_MGA_INDEX	0x44
-#define PCI_MGA_DATA	0x48
-#define PCI_OPTION2_REG	0x50
-#define PCI_OPTION3_REG	0x54
-#define PCI_MEMMISC_REG	0x58
-
-#define M_DWGCTL	0x1C00
-#define M_MACCESS	0x1C04
-#define M_CTLWTST	0x1C08
-
-#define M_PLNWT		0x1C1C
-
-#define M_BCOL		0x1C20
-#define M_FCOL		0x1C24
-
-#define M_SGN		0x1C58
-#define M_LEN		0x1C5C
-#define M_AR0		0x1C60
-#define M_AR1		0x1C64
-#define M_AR2		0x1C68
-#define M_AR3		0x1C6C
-#define M_AR4		0x1C70
-#define M_AR5		0x1C74
-#define M_AR6		0x1C78
-
-#define M_CXBNDRY	0x1C80
-#define M_FXBNDRY	0x1C84
-#define M_YDSTLEN	0x1C88
-#define M_PITCH		0x1C8C
-#define M_YDST		0x1C90
-#define M_YDSTORG	0x1C94
-#define M_YTOP		0x1C98
-#define M_YBOT		0x1C9C
-
-/* mystique only */
-#define M_CACHEFLUSH	0x1FFF
-
-#define M_EXEC		0x0100
-
-#define M_DWG_TRAP	0x04
-#define M_DWG_BITBLT	0x08
-#define M_DWG_ILOAD	0x09
-
-#define M_DWG_LINEAR	0x0080
-#define M_DWG_SOLID	0x0800
-#define M_DWG_ARZERO	0x1000
-#define M_DWG_SGNZERO	0x2000
-#define M_DWG_SHIFTZERO	0x4000
-
-#define M_DWG_REPLACE	0x000C0000
-#define M_DWG_REPLACE2	(M_DWG_REPLACE | 0x40)
-#define M_DWG_XOR	0x00060010
-
-#define M_DWG_BFCOL	0x04000000
-#define M_DWG_BMONOWF	0x08000000
-
-#define M_DWG_TRANSC	0x40000000
-
-#define M_FIFOSTATUS	0x1E10
-#define M_STATUS	0x1E14
-#define M_ICLEAR	0x1E18
-#define M_IEN		0x1E1C
-
-#define M_VCOUNT	0x1E20
-
-#define M_RESET		0x1E40
-#define M_MEMRDBK	0x1E44
-
-#define M_AGP2PLL	0x1E4C
-
-#define M_OPMODE	0x1E54
-#define     M_OPMODE_DMA_GEN_WRITE	0x00
-#define     M_OPMODE_DMA_BLIT		0x04
-#define     M_OPMODE_DMA_VECTOR_WRITE	0x08
-#define     M_OPMODE_DMA_LE		0x0000		/* little endian - no transformation */
-#define     M_OPMODE_DMA_BE_8BPP	0x0000
-#define     M_OPMODE_DMA_BE_16BPP	0x0100
-#define     M_OPMODE_DMA_BE_32BPP	0x0200
-#define     M_OPMODE_DIR_LE		0x000000	/* little endian - no transformation */
-#define     M_OPMODE_DIR_BE_8BPP	0x000000
-#define     M_OPMODE_DIR_BE_16BPP	0x010000
-#define     M_OPMODE_DIR_BE_32BPP	0x020000
-
-#define M_ATTR_INDEX	0x1FC0
-#define M_ATTR_DATA	0x1FC1
-
-#define M_MISC_REG	0x1FC2
-#define M_3C2_RD	0x1FC2
-
-#define M_SEQ_INDEX	0x1FC4
-#define M_SEQ_DATA	0x1FC5
-#define     M_SEQ1		0x01
-#define        M_SEQ1_SCROFF		0x20
-
-#define M_MISC_REG_READ	0x1FCC
-
-#define M_GRAPHICS_INDEX 0x1FCE
-#define M_GRAPHICS_DATA	0x1FCF
-
-#define M_CRTC_INDEX	0x1FD4
-
-#define M_ATTR_RESET	0x1FDA
-#define M_3DA_WR	0x1FDA
-#define M_INSTS1	0x1FDA
-
-#define M_EXTVGA_INDEX	0x1FDE
-#define M_EXTVGA_DATA	0x1FDF
-
-/* G200 only */
-#define M_SRCORG	0x2CB4
-#define M_DSTORG	0x2CB8
-
-#define M_RAMDAC_BASE	0x3C00
-
-/* fortunately, same on TVP3026 and MGA1064 */
-#define M_DAC_REG	(M_RAMDAC_BASE+0)
-#define M_DAC_VAL	(M_RAMDAC_BASE+1)
-#define M_PALETTE_MASK	(M_RAMDAC_BASE+2)
-
-#define M_X_INDEX	0x00
-#define M_X_DATAREG	0x0A
-
-#define DAC_XGENIOCTRL		0x2A
-#define DAC_XGENIODATA		0x2B
-
-#define M_C2CTL		0x3C10
-
-#define MX_OPTION_BSWAP         0x00000000
-
-#ifdef __LITTLE_ENDIAN
-#define M_OPMODE_4BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
-#define M_OPMODE_8BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
-#define M_OPMODE_16BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
-#define M_OPMODE_24BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
-#define M_OPMODE_32BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
-#else
-#ifdef __BIG_ENDIAN
-#define M_OPMODE_4BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_LE       | M_OPMODE_DMA_BLIT)	/* TODO */
-#define M_OPMODE_8BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP  | M_OPMODE_DMA_BLIT)
-#define M_OPMODE_16BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_16BPP | M_OPMODE_DMA_BLIT)
-#define M_OPMODE_24BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP  | M_OPMODE_DMA_BLIT)	/* TODO, ?32 */
-#define M_OPMODE_32BPP	(M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_32BPP | M_OPMODE_DMA_BLIT)
-#else
-#error "Byte ordering have to be defined. Cannot continue."
-#endif
-#endif
-
-#define mga_inb(addr)		mga_readb(minfo->mmio.vbase, (addr))
-#define mga_inl(addr)		mga_readl(minfo->mmio.vbase, (addr))
-#define mga_outb(addr,val)	mga_writeb(minfo->mmio.vbase, (addr), (val))
-#define mga_outw(addr,val)	mga_writew(minfo->mmio.vbase, (addr), (val))
-#define mga_outl(addr,val)	mga_writel(minfo->mmio.vbase, (addr), (val))
-#define mga_readr(port,idx)	(mga_outb((port),(idx)), mga_inb((port)+1))
-#define mga_setr(addr,port,val)	mga_outw(addr, ((val)<<8) | (port))
-
-#define mga_fifo(n)	do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
-
-#define WaitTillIdle()	do {} while (mga_inl(M_STATUS) & 0x10000)
-
-/* code speedup */
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-#define isInterleave(x)	 (x->interleave)
-#define isMillenium(x)	 (x->millenium)
-#define isMilleniumII(x) (x->milleniumII)
-#else
-#define isInterleave(x)  (0)
-#define isMillenium(x)	 (0)
-#define isMilleniumII(x) (0)
-#endif
-
-#define matroxfb_DAC_lock()                   spin_lock(&minfo->lock.DAC)
-#define matroxfb_DAC_unlock()                 spin_unlock(&minfo->lock.DAC)
-#define matroxfb_DAC_lock_irqsave(flags)      spin_lock_irqsave(&minfo->lock.DAC, flags)
-#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&minfo->lock.DAC, flags)
-extern void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg,
-			     int val);
-extern int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg);
-extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
-extern int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc);
-extern int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable);
-
-#ifdef MATROXFB_USE_SPINLOCKS
-#define CRITBEGIN  spin_lock_irqsave(&minfo->lock.accel, critflags);
-#define CRITEND	   spin_unlock_irqrestore(&minfo->lock.accel, critflags);
-#define CRITFLAGS  unsigned long critflags;
-#else
-#define CRITBEGIN
-#define CRITEND
-#define CRITFLAGS
-#endif
-
-#endif	/* __MATROXFB_H__ */
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
deleted file mode 100644
index 02796a4317a9..000000000000
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.65 2002/08/14
- *
- */
-
-#include "matroxfb_maven.h"
-#include "matroxfb_crtc2.h"
-#include "matroxfb_misc.h"
-#include "matroxfb_DAC1064.h"
-#include <linux/matroxfb.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-/* **************************************************** */
-
-static int mem = 8192;
-
-module_param(mem, int, 0);
-MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)");
-
-/* **************************************************** */
-
-static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,
-		unsigned blue, unsigned transp, struct fb_info* info) {
-	u_int32_t col;
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-
-	if (regno >= 16)
-		return 1;
-	if (m2info->fbcon.var.grayscale) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-	red = CNVT_TOHW(red, m2info->fbcon.var.red.length);
-	green = CNVT_TOHW(green, m2info->fbcon.var.green.length);
-	blue = CNVT_TOHW(blue, m2info->fbcon.var.blue.length);
-	transp = CNVT_TOHW(transp, m2info->fbcon.var.transp.length);
-
-	col = (red << m2info->fbcon.var.red.offset)     |
-	      (green << m2info->fbcon.var.green.offset) |
-	      (blue << m2info->fbcon.var.blue.offset)   |
-	      (transp << m2info->fbcon.var.transp.offset);
-
-	switch (m2info->fbcon.var.bits_per_pixel) {
-		case 16:
-			m2info->cmap[regno] = col | (col << 16);
-			break;
-		case 32:
-			m2info->cmap[regno] = col;
-			break;
-	}
-	return 0;
-#undef m2info
-}
-
-static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
-		struct my_timming* mt,
-		int mode,
-		unsigned int pos) {
-	u_int32_t tmp;
-	u_int32_t datactl;
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	switch (mode) {
-		case 15:
-			tmp = 0x00200000;
-			break;
-		case 16:
-			tmp = 0x00400000;
-			break;
-/*		case 32: */
-		default:
-			tmp = 0x00800000;
-			break;
-	}
-	tmp |= 0x00000001;	/* enable CRTC2 */
-	datactl = 0;
-	if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
-		if (minfo->devflags.g450dac) {
-			tmp |= 0x00000006; /* source from secondary pixel PLL */
-			/* no vidrst when in monitor mode */
-			if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
-				tmp |=  0xC0001000; /* Enable H/V vidrst */
-			}
-		} else {
-			tmp |= 0x00000002; /* source from VDOCLK */
-			tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
-			/* MGA TVO is our clock source */
-		}
-	} else if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
-		tmp |= 0x00000004; /* source from pixclock */
-		/* PIXPLL is our clock source */
-	}
-	if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
-		tmp |= 0x00100000;	/* connect CRTC2 to DAC */
-	}
-	if (mt->interlaced) {
-		tmp |= 0x02000000;	/* interlaced, second field is bigger, as G450 apparently ignores it */
-		mt->VDisplay >>= 1;
-		mt->VSyncStart >>= 1;
-		mt->VSyncEnd >>= 1;
-		mt->VTotal >>= 1;
-	}
-	if ((mt->HTotal & 7) == 2) {
-		datactl |= 0x00000010;
-		mt->HTotal &= ~7;
-	}
-	tmp |= 0x10000000;	/* 0x10000000 is VIDRST polarity */
-	mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8));
-	mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8));
-	mga_outl(0x3C1C, ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1));
-	mga_outl(0x3C20, ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1));
-	mga_outl(0x3C24, ((mt->VSyncStart) << 16) | (mt->HSyncStart));	/* preload */
-	{
-		u_int32_t linelen = m2info->fbcon.var.xres_virtual * (m2info->fbcon.var.bits_per_pixel >> 3);
-		if (tmp & 0x02000000) {
-			/* field #0 is smaller, so... */
-			mga_outl(0x3C2C, pos);			/* field #1 vmemory start */
-			mga_outl(0x3C28, pos + linelen);	/* field #0 vmemory start */
-			linelen <<= 1;
-			m2info->interlaced = 1;
-		} else {
-			mga_outl(0x3C28, pos);		/* vmemory start */
-			m2info->interlaced = 0;
-		}
-		mga_outl(0x3C40, linelen);
-	}
-	mga_outl(0x3C4C, datactl);	/* data control */
-	if (tmp & 0x02000000) {
-		int i;
-
-		mga_outl(0x3C10, tmp & ~0x02000000);
-		for (i = 0; i < 2; i++) {
-			unsigned int nl;
-			unsigned int lastl = 0;
-
-			while ((nl = mga_inl(0x3C48) & 0xFFF) >= lastl) {
-				lastl = nl;
-			}
-		}
-	}
-	mga_outl(0x3C10, tmp);
-	minfo->hw.crtc2.ctl = tmp;
-
-	tmp = mt->VDisplay << 16;	/* line compare */
-	if (mt->sync & FB_SYNC_HOR_HIGH_ACT)
-		tmp |= 0x00000100;
-	if (mt->sync & FB_SYNC_VERT_HIGH_ACT)
-		tmp |= 0x00000200;
-	mga_outl(0x3C44, tmp);
-}
-
-static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	mga_outl(0x3C10, 0x00000004);	/* disable CRTC2, CRTC1->DAC1, PLL as clock source */
-	minfo->hw.crtc2.ctl = 0x00000004;
-}
-
-static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
-		struct fb_var_screeninfo* var) {
-	unsigned int pos;
-	unsigned int linelen;
-	unsigned int pixelsize;
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	m2info->fbcon.var.xoffset = var->xoffset;
-	m2info->fbcon.var.yoffset = var->yoffset;
-	pixelsize = m2info->fbcon.var.bits_per_pixel >> 3;
-	linelen = m2info->fbcon.var.xres_virtual * pixelsize;
-	pos = m2info->fbcon.var.yoffset * linelen + m2info->fbcon.var.xoffset * pixelsize;
-	pos += m2info->video.offbase;
-	if (m2info->interlaced) {
-		mga_outl(0x3C2C, pos);
-		mga_outl(0x3C28, pos + linelen);
-	} else {
-		mga_outl(0x3C28, pos);
-	}
-}
-
-static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info,
-		struct fb_var_screeninfo* var,
-		int *visual,
-		int *video_cmap_len,
-		int *mode) {
-	unsigned int mask;
-	unsigned int memlen;
-	unsigned int vramlen;
-
-	switch (var->bits_per_pixel) {
-		case 16:	mask = 0x1F;
-				break;
-		case 32:	mask = 0x0F;
-				break;
-		default:	return -EINVAL;
-	}
-	vramlen = m2info->video.len_usable;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	var->xres_virtual = (var->xres_virtual + mask) & ~mask;
-	if (var->yres_virtual > 32767)
-		return -EINVAL;
-	memlen = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel >> 3);
-	if (memlen > vramlen)
-		return -EINVAL;
-	if (var->xoffset + var->xres > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yoffset + var->yres > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	var->xres &= ~7;
-	var->left_margin &= ~7;
-	var->right_margin &= ~7;
-	var->hsync_len &= ~7;
-
-	*mode = var->bits_per_pixel;
-	if (var->bits_per_pixel == 16) {
-		if (var->green.length == 5) {
-			var->red.offset = 10;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 5;
-			var->blue.offset = 0;
-			var->blue.length = 5;
-			var->transp.offset = 15;
-			var->transp.length = 1;
-			*mode = 15;
-		} else {
-			var->red.offset = 11;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 6;
-			var->blue.offset = 0;
-			var->blue.length = 5;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-		}
-	} else {
-			var->red.offset = 16;
-			var->red.length = 8;
-			var->green.offset = 8;
-			var->green.length = 8;
-			var->blue.offset = 0;
-			var->blue.length = 8;
-			var->transp.offset = 24;
-			var->transp.length = 8;
-	}
-	*visual = FB_VISUAL_TRUECOLOR;
-	*video_cmap_len = 16;
-	return 0;
-}
-
-static int matroxfb_dh_open(struct fb_info* info, int user) {
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	if (minfo) {
-		int err;
-
-		if (minfo->dead) {
-			return -ENXIO;
-		}
-		err = minfo->fbops.fb_open(&minfo->fbcon, user);
-		if (err) {
-			return err;
-		}
-	}
-	return 0;
-#undef m2info
-}
-
-static int matroxfb_dh_release(struct fb_info* info, int user) {
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-	int err = 0;
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	if (minfo) {
-		err = minfo->fbops.fb_release(&minfo->fbcon, user);
-	}
-	return err;
-#undef m2info
-}
-
-/*
- * This function is called before the register_framebuffer so
- * no locking is needed.
- */
-static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info)
-{
-	struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;
-
-	strcpy(fix->id, "MATROX DH");
-
-	fix->smem_start = m2info->video.base;
-	fix->smem_len = m2info->video.len_usable;
-	fix->ypanstep = 1;
-	fix->ywrapstep = 0;
-	fix->xpanstep = 8;	/* TBD */
-	fix->mmio_start = m2info->mmio.base;
-	fix->mmio_len = m2info->mmio.len;
-	fix->accel = 0;		/* no accel... */
-}
-
-static int matroxfb_dh_check_var(struct fb_var_screeninfo* var, struct fb_info* info) {
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-	int visual;
-	int cmap_len;
-	int mode;
-
-	return matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode);
-#undef m2info
-}
-
-static int matroxfb_dh_set_par(struct fb_info* info) {
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-	int visual;
-	int cmap_len;
-	int mode;
-	int err;
-	struct fb_var_screeninfo* var = &info->var;
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0)
-		return err;
-	/* cmap */
-	{
-		m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase);
-		m2info->fbcon.fix.visual = visual;
-		m2info->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
-		m2info->fbcon.fix.type_aux = 0;
-		m2info->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
-	}
-	{
-		struct my_timming mt;
-		unsigned int pos;
-		int out;
-		int cnt;
-
-		matroxfb_var2my(&m2info->fbcon.var, &mt);
-		mt.crtc = MATROXFB_SRC_CRTC2;
-		/* CRTC2 delay */
-		mt.delay = 34;
-
-		pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3;
-		pos += m2info->video.offbase;
-		cnt = 0;
-		down_read(&minfo->altout.lock);
-		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-			if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
-				cnt++;
-				if (minfo->outputs[out].output->compute) {
-					minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
-				}
-			}
-		}
-		minfo->crtc2.pixclock = mt.pixclock;
-		minfo->crtc2.mnp = mt.mnp;
-		up_read(&minfo->altout.lock);
-		if (cnt) {
-			matroxfb_dh_restore(m2info, &mt, mode, pos);
-		} else {
-			matroxfb_dh_disable(m2info);
-		}
-		DAC1064_global_init(minfo);
-		DAC1064_global_restore(minfo);
-		down_read(&minfo->altout.lock);
-		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-			if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
-			    minfo->outputs[out].output->program) {
-				minfo->outputs[out].output->program(minfo->outputs[out].data);
-			}
-		}
-		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-			if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
-			    minfo->outputs[out].output->start) {
-				minfo->outputs[out].output->start(minfo->outputs[out].data);
-			}
-		}
-		up_read(&minfo->altout.lock);
-	}
-	m2info->initialized = 1;
-	return 0;
-#undef m2info
-}
-
-static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, struct fb_info* info) {
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-	matroxfb_dh_pan_var(m2info, var);
-	return 0;
-#undef m2info
-}
-
-static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	matroxfb_enable_irq(minfo, 0);
-	memset(vblank, 0, sizeof(*vblank));
-	vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
-	/* mask out reserved bits + field number (odd/even) */
-	vblank->vcount = mga_inl(0x3C48) & 0x000007FF;
-	/* compatibility stuff */
-	if (vblank->vcount >= m2info->fbcon.var.yres)
-		vblank->flags |= FB_VBLANK_VBLANKING;
-	if (test_bit(0, &minfo->irq_flags)) {
-                vblank->flags |= FB_VBLANK_HAVE_COUNT;
-                /* Only one writer, aligned int value...
-                   it should work without lock and without atomic_t */
-		vblank->count = minfo->crtc2.vsync.cnt;
-        }
-	return 0;
-}
-
-static int matroxfb_dh_ioctl(struct fb_info *info,
-		unsigned int cmd,
-		unsigned long arg)
-{
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-	struct matrox_fb_info *minfo = m2info->primary_dev;
-
-	DBG(__func__)
-
-	switch (cmd) {
-		case FBIOGET_VBLANK:
-			{
-				struct fb_vblank vblank;
-				int err;
-
-				err = matroxfb_dh_get_vblank(m2info, &vblank);
-				if (err)
-					return err;
-				if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
-					return -EFAULT;
-				return 0;
-			}
-		case FBIO_WAITFORVSYNC:
-			{
-				u_int32_t crt;
-
-				if (get_user(crt, (u_int32_t __user *)arg))
-					return -EFAULT;
-
-				if (crt != 0)
-					return -ENODEV;
-				return matroxfb_wait_for_sync(minfo, 1);
-			}
-		case MATROXFB_SET_OUTPUT_MODE:
-		case MATROXFB_GET_OUTPUT_MODE:
-		case MATROXFB_GET_ALL_OUTPUTS:
-			{
-				return minfo->fbcon.fbops->fb_ioctl(&minfo->fbcon, cmd, arg);
-			}
-		case MATROXFB_SET_OUTPUT_CONNECTION:
-			{
-				u_int32_t tmp;
-				int out;
-				int changes;
-
-				if (get_user(tmp, (u_int32_t __user *)arg))
-					return -EFAULT;
-				for (out = 0; out < 32; out++) {
-					if (tmp & (1 << out)) {
-						if (out >= MATROXFB_MAX_OUTPUTS)
-							return -ENXIO;
-						if (!minfo->outputs[out].output)
-							return -ENXIO;
-						switch (minfo->outputs[out].src) {
-							case MATROXFB_SRC_NONE:
-							case MATROXFB_SRC_CRTC2:
-								break;
-							default:
-								return -EBUSY;
-						}
-					}
-				}
-				if (minfo->devflags.panellink) {
-					if (tmp & MATROXFB_OUTPUT_CONN_DFP)
-						return -EINVAL;
-					if ((minfo->outputs[2].src == MATROXFB_SRC_CRTC1) && tmp)
-						return -EBUSY;
-				}
-				changes = 0;
-				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-					if (tmp & (1 << out)) {
-						if (minfo->outputs[out].src != MATROXFB_SRC_CRTC2) {
-							changes = 1;
-							minfo->outputs[out].src = MATROXFB_SRC_CRTC2;
-						}
-					} else if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
-						changes = 1;
-						minfo->outputs[out].src = MATROXFB_SRC_NONE;
-					}
-				}
-				if (!changes)
-					return 0;
-				matroxfb_dh_set_par(info);
-				return 0;
-			}
-		case MATROXFB_GET_OUTPUT_CONNECTION:
-			{
-				u_int32_t conn = 0;
-				int out;
-
-				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-					if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
-						conn |= 1 << out;
-					}
-				}
-				if (put_user(conn, (u_int32_t __user *)arg))
-					return -EFAULT;
-				return 0;
-			}
-		case MATROXFB_GET_AVAILABLE_OUTPUTS:
-			{
-				u_int32_t tmp = 0;
-				int out;
-
-				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
-					if (minfo->outputs[out].output) {
-						switch (minfo->outputs[out].src) {
-							case MATROXFB_SRC_NONE:
-							case MATROXFB_SRC_CRTC2:
-								tmp |= 1 << out;
-								break;
-						}
-					}
-				}
-				if (minfo->devflags.panellink) {
-					tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
-					if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1) {
-						tmp = 0;
-					}
-				}
-				if (put_user(tmp, (u_int32_t __user *)arg))
-					return -EFAULT;
-				return 0;
-			}
-	}
-	return -ENOTTY;
-#undef m2info
-}
-
-static int matroxfb_dh_blank(int blank, struct fb_info* info) {
-#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
-	switch (blank) {
-		case 1:
-		case 2:
-		case 3:
-		case 4:
-		default:;
-	}
-	/* do something... */
-	return 0;
-#undef m2info
-}
-
-static struct fb_ops matroxfb_dh_ops = {
-	.owner =	THIS_MODULE,
-	.fb_open =	matroxfb_dh_open,
-	.fb_release =	matroxfb_dh_release,
-	.fb_check_var =	matroxfb_dh_check_var,
-	.fb_set_par =	matroxfb_dh_set_par,
-	.fb_setcolreg =	matroxfb_dh_setcolreg,
-	.fb_pan_display =matroxfb_dh_pan_display,
-	.fb_blank =	matroxfb_dh_blank,
-	.fb_ioctl =	matroxfb_dh_ioctl,
-	.fb_fillrect =	cfb_fillrect,
-	.fb_copyarea =	cfb_copyarea,
-	.fb_imageblit =	cfb_imageblit,
-};
-
-static struct fb_var_screeninfo matroxfb_dh_defined = {
-		640,480,640,480,/* W,H, virtual W,H */
-		0,0,		/* offset */
-		32,		/* depth */
-		0,		/* gray */
-		{0,0,0},	/* R */
-		{0,0,0},	/* G */
-		{0,0,0},	/* B */
-		{0,0,0},	/* alpha */
-		0,		/* nonstd */
-		FB_ACTIVATE_NOW,
-		-1,-1,		/* display size */
-		0,		/* accel flags */
-		39721L,48L,16L,33L,10L,
-		96L,2,0,	/* no sync info */
-		FB_VMODE_NONINTERLACED,
-};
-
-static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
-			     struct matroxfb_dh_fb_info *m2info)
-{
-#define minfo (m2info->primary_dev)
-	void* oldcrtc2;
-
-	m2info->fbcon.fbops = &matroxfb_dh_ops;
-	m2info->fbcon.flags = FBINFO_FLAG_DEFAULT;
-	m2info->fbcon.flags |= FBINFO_HWACCEL_XPAN |
-			       FBINFO_HWACCEL_YPAN;
-	m2info->fbcon.pseudo_palette = m2info->cmap;
-	fb_alloc_cmap(&m2info->fbcon.cmap, 256, 1);
-
-	if (mem < 64)
-		mem *= 1024;
-	if (mem < 64*1024)
-		mem *= 1024;
-	mem &= ~0x00000FFF;	/* PAGE_MASK? */
-	if (minfo->video.len_usable + mem <= minfo->video.len)
-		m2info->video.offbase = minfo->video.len - mem;
-	else if (minfo->video.len < mem) {
-		return -ENOMEM;
-	} else { /* check yres on first head... */
-		m2info->video.borrowed = mem;
-		minfo->video.len_usable -= mem;
-		m2info->video.offbase = minfo->video.len_usable;
-	}
-	m2info->video.base = minfo->video.base + m2info->video.offbase;
-	m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;
-	m2info->video.vbase.vaddr = vaddr_va(minfo->video.vbase) + m2info->video.offbase;
-	m2info->mmio.base = minfo->mmio.base;
-	m2info->mmio.vbase = minfo->mmio.vbase;
-	m2info->mmio.len = minfo->mmio.len;
-
-	matroxfb_dh_init_fix(m2info);
-	if (register_framebuffer(&m2info->fbcon)) {
-		return -ENXIO;
-	}
-	if (!m2info->initialized)
-		fb_set_var(&m2info->fbcon, &matroxfb_dh_defined);
-	down_write(&minfo->crtc2.lock);
-	oldcrtc2 = minfo->crtc2.info;
-	minfo->crtc2.info = m2info;
-	up_write(&minfo->crtc2.lock);
-	if (oldcrtc2) {
-		printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
-			oldcrtc2);
-	}
-	return 0;
-#undef minfo
-}
-
-/* ************************** */
-
-static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) {
-#define minfo (m2info->primary_dev)
-	if (matroxfb_dh_regit(minfo, m2info)) {
-		printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n");
-		return -1;
-	}
-	printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n",
-		minfo->fbcon.node, m2info->fbcon.node);
-	m2info->fbcon_registered = 1;
-	return 0;
-#undef minfo
-}
-
-static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
-#define minfo (m2info->primary_dev)
-	if (m2info->fbcon_registered) {
-		int id;
-		struct matroxfb_dh_fb_info* crtc2;
-
-		down_write(&minfo->crtc2.lock);
-		crtc2 = minfo->crtc2.info;
-		if (crtc2 == m2info)
-			minfo->crtc2.info = NULL;
-		up_write(&minfo->crtc2.lock);
-		if (crtc2 != m2info) {
-			printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
-				crtc2, m2info);
-			printk(KERN_ERR "matroxfb_crtc2: Expect kernel crash after module unload.\n");
-			return;
-		}
-		id = m2info->fbcon.node;
-		unregister_framebuffer(&m2info->fbcon);
-		/* return memory back to primary head */
-		minfo->video.len_usable += m2info->video.borrowed;
-		printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id);
-		m2info->fbcon_registered = 0;
-	}
-#undef minfo
-}
-
-static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
-	struct matroxfb_dh_fb_info* m2info;
-
-	/* hardware is CRTC2 incapable... */
-	if (!minfo->devflags.crtc2)
-		return NULL;
-	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
-	if (!m2info) {
-		printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
-		return NULL;
-	}
-	m2info->primary_dev = minfo;
-	if (matroxfb_dh_registerfb(m2info)) {
-		kfree(m2info);
-		printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");
-		return NULL;
-	}
-	return m2info;
-}
-
-static void matroxfb_crtc2_remove(struct matrox_fb_info* minfo, void* crtc2) {
-	matroxfb_dh_deregisterfb(crtc2);
-	kfree(crtc2);
-}
-
-static struct matroxfb_driver crtc2 = {
-		.name =		"Matrox G400 CRTC2",
-		.probe =	matroxfb_crtc2_probe,
-		.remove =	matroxfb_crtc2_remove };
-
-static int matroxfb_crtc2_init(void) {
-	if (fb_get_options("matrox_crtc2fb", NULL))
-		return -ENODEV;
-
-	matroxfb_register_driver(&crtc2);
-	return 0;
-}
-
-static void matroxfb_crtc2_exit(void) {
-	matroxfb_unregister_driver(&crtc2);
-}
-
-MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Matrox G400 CRTC2 driver");
-MODULE_LICENSE("GPL");
-module_init(matroxfb_crtc2_init);
-module_exit(matroxfb_crtc2_exit);
-/* we do not have __setup() yet */
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
deleted file mode 100644
index 1005582e843e..000000000000
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __MATROXFB_CRTC2_H__
-#define __MATROXFB_CRTC2_H__
-
-#include <linux/ioctl.h>
-#include "matroxfb_base.h"
-
-struct matroxfb_dh_fb_info {
-	struct fb_info		fbcon;
-	int			fbcon_registered;
-	int                     initialized;
-
-	struct matrox_fb_info*	primary_dev;
-
-	struct {
-		unsigned long	base;	/* physical */
-		vaddr_t		vbase;	/* virtual */
-		unsigned int	len;
-		unsigned int	len_usable;
-		unsigned int	len_maximum;
-		unsigned int 	offbase;
-		unsigned int	borrowed;
-			      } video;
-	struct {
-		unsigned long	base;
-		vaddr_t		vbase;
-		unsigned int	len;
-			      } mmio;
-
-	unsigned int		interlaced:1;
-
-	u_int32_t cmap[16];
-};
-
-#endif /* __MATROXFB_CRTC2_H__ */
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
deleted file mode 100644
index cff0546ea6fd..000000000000
--- a/drivers/video/matrox/matroxfb_g450.c
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.65 2002/08/14
- *
- * See matroxfb_base.c for contributors.
- *
- */
-
-#include "matroxfb_base.h"
-#include "matroxfb_misc.h"
-#include "matroxfb_DAC1064.h"
-#include "g450_pll.h"
-#include <linux/matroxfb.h>
-#include <asm/div64.h>
-
-#include "matroxfb_g450.h"
-
-/* Definition of the various controls */
-struct mctl {
-	struct v4l2_queryctrl desc;
-	size_t control;
-};
-
-#define BLMIN	0xF3
-#define WLMAX	0x3FF
-
-static const struct mctl g450_controls[] =
-{	{ { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, 
-	  "brightness",
-	  0, WLMAX-BLMIN, 1, 370-BLMIN, 
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
-	{ { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, 
-	  "contrast",
-	  0, 1023, 1, 127, 
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
-	{ { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
-	  "saturation",
-	  0, 255, 1, 165, 
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
-	{ { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
-	  "hue",
-	  0, 255, 1, 0, 
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
-	{ { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
-	  "test output",
-	  0, 1, 1, 0, 
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
-};
-
-#define G450CTRLS ARRAY_SIZE(g450_controls)
-
-/* Return: positive number: id found
-           -EINVAL:         id not found, return failure
-	   -ENOENT:         id not found, create fake disabled control */
-static int get_ctrl_id(__u32 v4l2_id) {
-	int i;
-
-	for (i = 0; i < G450CTRLS; i++) {
-		if (v4l2_id < g450_controls[i].desc.id) {
-			if (g450_controls[i].desc.id == 0x08000000) {
-				return -EINVAL;
-			}
-			return -ENOENT;
-		}
-		if (v4l2_id == g450_controls[i].desc.id) {
-			return i;
-		}
-	}
-	return -EINVAL;
-}
-
-static inline int *get_ctrl_ptr(struct matrox_fb_info *minfo, unsigned int idx)
-{
-	return (int*)((char*)minfo + g450_controls[idx].control);
-}
-
-static void tvo_fill_defaults(struct matrox_fb_info *minfo)
-{
-	unsigned int i;
-	
-	for (i = 0; i < G450CTRLS; i++) {
-		*get_ctrl_ptr(minfo, i) = g450_controls[i].desc.default_value;
-	}
-}
-
-static int cve2_get_reg(struct matrox_fb_info *minfo, int reg)
-{
-	unsigned long flags;
-	int val;
-	
-	matroxfb_DAC_lock_irqsave(flags);
-	matroxfb_DAC_out(minfo, 0x87, reg);
-	val = matroxfb_DAC_in(minfo, 0x88);
-	matroxfb_DAC_unlock_irqrestore(flags);
-	return val;
-}
-
-static void cve2_set_reg(struct matrox_fb_info *minfo, int reg, int val)
-{
-	unsigned long flags;
-
-	matroxfb_DAC_lock_irqsave(flags);
-	matroxfb_DAC_out(minfo, 0x87, reg);
-	matroxfb_DAC_out(minfo, 0x88, val);
-	matroxfb_DAC_unlock_irqrestore(flags);
-}
-
-static void cve2_set_reg10(struct matrox_fb_info *minfo, int reg, int val)
-{
-	unsigned long flags;
-
-	matroxfb_DAC_lock_irqsave(flags);
-	matroxfb_DAC_out(minfo, 0x87, reg);
-	matroxfb_DAC_out(minfo, 0x88, val >> 2);
-	matroxfb_DAC_out(minfo, 0x87, reg + 1);
-	matroxfb_DAC_out(minfo, 0x88, val & 3);
-	matroxfb_DAC_unlock_irqrestore(flags);
-}
-
-static void g450_compute_bwlevel(const struct matrox_fb_info *minfo, int *bl,
-				 int *wl)
-{
-	const int b = minfo->altout.tvo_params.brightness + BLMIN;
-	const int c = minfo->altout.tvo_params.contrast;
-
-	*bl = max(b - c, BLMIN);
-	*wl = min(b + c, WLMAX);
-}
-
-static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) {
-	int i;
-	
-	i = get_ctrl_id(p->id);
-	if (i >= 0) {
-		*p = g450_controls[i].desc;
-		return 0;
-	}
-	if (i == -ENOENT) {
-		static const struct v4l2_queryctrl disctrl = 
-			{ .flags = V4L2_CTRL_FLAG_DISABLED };
-			
-		i = p->id;
-		*p = disctrl;
-		p->id = i;
-		sprintf(p->name, "Ctrl #%08X", i);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int g450_set_ctrl(void* md, struct v4l2_control *p) {
-	int i;
-	struct matrox_fb_info *minfo = md;
-	
-	i = get_ctrl_id(p->id);
-	if (i < 0) return -EINVAL;
-
-	/*
-	 * Check if changed.
-	 */
-	if (p->value == *get_ctrl_ptr(minfo, i)) return 0;
-
-	/*
-	 * Check limits.
-	 */
-	if (p->value > g450_controls[i].desc.maximum) return -EINVAL;
-	if (p->value < g450_controls[i].desc.minimum) return -EINVAL;
-
-	/*
-	 * Store new value.
-	 */
-	*get_ctrl_ptr(minfo, i) = p->value;
-
-	switch (p->id) {
-		case V4L2_CID_BRIGHTNESS:
-		case V4L2_CID_CONTRAST:
-			{
-				int blacklevel, whitelevel;
-				g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
-				cve2_set_reg10(minfo, 0x0e, blacklevel);
-				cve2_set_reg10(minfo, 0x1e, whitelevel);
-			}
-			break;
-		case V4L2_CID_SATURATION:
-			cve2_set_reg(minfo, 0x20, p->value);
-			cve2_set_reg(minfo, 0x22, p->value);
-			break;
-		case V4L2_CID_HUE:
-			cve2_set_reg(minfo, 0x25, p->value);
-			break;
-		case MATROXFB_CID_TESTOUT:
-			{
-				unsigned char val = cve2_get_reg(minfo, 0x05);
-				if (p->value) val |=  0x02;
-				else          val &= ~0x02;
-				cve2_set_reg(minfo, 0x05, val);
-			}
-			break;
-	}
-	
-
-	return 0;
-}
-
-static int g450_get_ctrl(void* md, struct v4l2_control *p) {
-	int i;
-	struct matrox_fb_info *minfo = md;
-	
-	i = get_ctrl_id(p->id);
-	if (i < 0) return -EINVAL;
-	p->value = *get_ctrl_ptr(minfo, i);
-	return 0;
-}
-
-struct output_desc {
-	unsigned int	h_vis;
-	unsigned int	h_f_porch;
-	unsigned int	h_sync;
-	unsigned int	h_b_porch;
-	unsigned long long int	chromasc;
-	unsigned int	burst;
-	unsigned int	v_total;
-};
-
-static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r,
-			struct my_timming *mt, const struct output_desc *outd)
-{
-	u_int32_t chromasc;
-	u_int32_t hlen;
-	u_int32_t hsl;
-	u_int32_t hbp;
-	u_int32_t hfp;
-	u_int32_t hvis;
-	unsigned int pixclock;
-	unsigned long long piic;
-	int mnp;
-	int over;
-	
-	r->regs[0x80] = 0x03;	/* | 0x40 for SCART */
-
-	hvis = ((mt->HDisplay << 1) + 3) & ~3;
-	
-	if (hvis >= 2048) {
-		hvis = 2044;
-	}
-	
-	piic = 1000000000ULL * hvis;
-	do_div(piic, outd->h_vis);
-
-	dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic);
-	
-	mnp = matroxfb_g450_setclk(minfo, piic, M_VIDEO_PLL);
-	
-	mt->mnp = mnp;
-	mt->pixclock = g450_mnp2f(minfo, mnp);
-
-	dprintk(KERN_DEBUG "MNP=%08X\n", mnp);
-
-	pixclock = 1000000000U / mt->pixclock;
-
-	dprintk(KERN_DEBUG "Got %u ps pixclock\n", pixclock);
-
-	piic = outd->chromasc;
-	do_div(piic, mt->pixclock);
-	chromasc = piic;
-	
-	dprintk(KERN_DEBUG "Chroma is %08X\n", chromasc);
-
-	r->regs[0] = piic >> 24;
-	r->regs[1] = piic >> 16;
-	r->regs[2] = piic >>  8;
-	r->regs[3] = piic >>  0;
-	hbp = (((outd->h_b_porch + pixclock) / pixclock)) & ~1;
-	hfp = (((outd->h_f_porch + pixclock) / pixclock)) & ~1;
-	hsl = (((outd->h_sync + pixclock) / pixclock)) & ~1;
-	hlen = hvis + hfp + hsl + hbp;
-	over = hlen & 0x0F;
-	
-	dprintk(KERN_DEBUG "WL: vis=%u, hf=%u, hs=%u, hb=%u, total=%u\n", hvis, hfp, hsl, hbp, hlen);
-
-	if (over) {
-		hfp -= over;
-		hlen -= over;
-		if (over <= 2) {
-		} else if (over < 10) {
-			hfp += 4;
-			hlen += 4;
-		} else {
-			hfp += 16;
-			hlen += 16;
-		}
-	}
-
-	/* maybe cve2 has requirement 800 < hlen < 1184 */
-	r->regs[0x08] = hsl;
-	r->regs[0x09] = (outd->burst + pixclock - 1) / pixclock;	/* burst length */
-	r->regs[0x0A] = hbp;
-	r->regs[0x2C] = hfp;
-	r->regs[0x31] = hvis / 8;
-	r->regs[0x32] = hvis & 7;
-	
-	dprintk(KERN_DEBUG "PG: vis=%04X, hf=%02X, hs=%02X, hb=%02X, total=%04X\n", hvis, hfp, hsl, hbp, hlen);
-
-	r->regs[0x84] = 1;	/* x sync point */
-	r->regs[0x85] = 0;
-	hvis = hvis >> 1;
-	hlen = hlen >> 1;
-	
-	dprintk(KERN_DEBUG "hlen=%u hvis=%u\n", hlen, hvis);
-
-	mt->interlaced = 1;
-
-	mt->HDisplay = hvis & ~7;
-	mt->HSyncStart = mt->HDisplay + 8;
-	mt->HSyncEnd = (hlen & ~7) - 8;
-	mt->HTotal = hlen;
-
-	{
-		int upper;
-		unsigned int vtotal;
-		unsigned int vsyncend;
-		unsigned int vdisplay;
-		
-		vtotal = mt->VTotal;
-		vsyncend = mt->VSyncEnd;
-		vdisplay = mt->VDisplay;
-		if (vtotal < outd->v_total) {
-			unsigned int yovr = outd->v_total - vtotal;
-			
-			vsyncend += yovr >> 1;
-		} else if (vtotal > outd->v_total) {
-			vdisplay = outd->v_total - 4;
-			vsyncend = outd->v_total;
-		}
-		upper = (outd->v_total - vsyncend) >> 1;	/* in field lines */
-		r->regs[0x17] = outd->v_total / 4;
-		r->regs[0x18] = outd->v_total & 3;
-		r->regs[0x33] = upper - 1;	/* upper blanking */
-		r->regs[0x82] = upper;		/* y sync point */
-		r->regs[0x83] = upper >> 8;
-		
-		mt->VDisplay = vdisplay;
-		mt->VSyncStart = outd->v_total - 2;
-		mt->VSyncEnd = outd->v_total;
-		mt->VTotal = outd->v_total;
-	}
-}
-
-static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct output_desc** outd) {
-	static const struct output_desc paloutd = {
-		.h_vis	   = 52148148,	// ps
-		.h_f_porch =  1407407,	// ps
-		.h_sync    =  4666667,	// ps
-		.h_b_porch =  5777778,	// ps
-		.chromasc  = 19042247534182ULL,	// 4433618.750 Hz
-		.burst     =  2518518,	// ps
-		.v_total   =      625,
-	};
-	static const struct output_desc ntscoutd = {
-		.h_vis     = 52888889,	// ps
-		.h_f_porch =  1333333,	// ps
-		.h_sync    =  4666667,	// ps
-		.h_b_porch =  4666667,	// ps
-		.chromasc  = 15374030659475ULL,	// 3579545.454 Hz
-		.burst     =  2418418,	// ps
-		.v_total   =      525,	// lines
-	};
-
-	static const struct mavenregs palregs = { {
-		0x2A, 0x09, 0x8A, 0xCB,	/* 00: chroma subcarrier */
-		0x00,
-		0x00,	/* test */
-		0xF9,	/* modified by code (F9 written...) */
-		0x00,	/* ? not written */
-		0x7E,	/* 08 */
-		0x44,	/* 09 */
-		0x9C,	/* 0A */
-		0x2E,	/* 0B */
-		0x21,	/* 0C */
-		0x00,	/* ? not written */
-//		0x3F, 0x03, /* 0E-0F */
-		0x3C, 0x03,
-		0x3C, 0x03, /* 10-11 */
-		0x1A,	/* 12 */
-		0x2A,	/* 13 */
-		0x1C, 0x3D, 0x14, /* 14-16 */
-		0x9C, 0x01, /* 17-18 */
-		0x00,	/* 19 */
-		0xFE,	/* 1A */
-		0x7E,	/* 1B */
-		0x60,	/* 1C */
-		0x05,	/* 1D */
-//		0x89, 0x03, /* 1E-1F */
-		0xAD, 0x03,
-//		0x72,	/* 20 */
-		0xA5,
-		0x07,	/* 21 */
-//		0x72,	/* 22 */
-		0xA5,
-		0x00,	/* 23 */
-		0x00,	/* 24 */
-		0x00,	/* 25 */
-		0x08,	/* 26 */
-		0x04,	/* 27 */
-		0x00,	/* 28 */
-		0x1A,	/* 29 */
-		0x55, 0x01, /* 2A-2B */
-		0x26,	/* 2C */
-		0x07, 0x7E, /* 2D-2E */
-		0x02, 0x54, /* 2F-30 */
-		0xB0, 0x00, /* 31-32 */
-		0x14,	/* 33 */
-		0x49,	/* 34 */
-		0x00,	/* 35 written multiple times */
-		0x00,	/* 36 not written */
-		0xA3,	/* 37 */
-		0xC8,	/* 38 */
-		0x22,	/* 39 */
-		0x02,	/* 3A */
-		0x22,	/* 3B */
-		0x3F, 0x03, /* 3C-3D */
-		0x00,	/* 3E written multiple times */
-		0x00,	/* 3F not written */
-	} };
-	static struct mavenregs ntscregs = { {
-		0x21, 0xF0, 0x7C, 0x1F,	/* 00: chroma subcarrier */
-		0x00,
-		0x00,	/* test */
-		0xF9,	/* modified by code (F9 written...) */
-		0x00,	/* ? not written */
-		0x7E,	/* 08 */
-		0x43,	/* 09 */
-		0x7E,	/* 0A */
-		0x3D,	/* 0B */
-		0x00,	/* 0C */
-		0x00,	/* ? not written */
-		0x41, 0x00, /* 0E-0F */
-		0x3C, 0x00, /* 10-11 */
-		0x17,	/* 12 */
-		0x21,	/* 13 */
-		0x1B, 0x1B, 0x24, /* 14-16 */
-		0x83, 0x01, /* 17-18 */
-		0x00,	/* 19 */
-		0x0F,	/* 1A */
-		0x0F,	/* 1B */
-		0x60,	/* 1C */
-		0x05,	/* 1D */
-		//0x89, 0x02, /* 1E-1F */
-		0xC0, 0x02, /* 1E-1F */
-		//0x5F,	/* 20 */
-		0x9C,	/* 20 */
-		0x04,	/* 21 */
-		//0x5F,	/* 22 */
-		0x9C,	/* 22 */
-		0x01,	/* 23 */
-		0x02,	/* 24 */
-		0x00,	/* 25 */
-		0x0A,	/* 26 */
-		0x05,	/* 27 */
-		0x00,	/* 28 */
-		0x10,	/* 29 */
-		0xFF, 0x03, /* 2A-2B */
-		0x24,	/* 2C */
-		0x0F, 0x78, /* 2D-2E */
-		0x00, 0x00, /* 2F-30 */
-		0xB2, 0x04, /* 31-32 */
-		0x14,	/* 33 */
-		0x02,	/* 34 */
-		0x00,	/* 35 written multiple times */
-		0x00,	/* 36 not written */
-		0xA3,	/* 37 */
-		0xC8,	/* 38 */
-		0x15,	/* 39 */
-		0x05,	/* 3A */
-		0x3B,	/* 3B */
-		0x3C, 0x00, /* 3C-3D */
-		0x00,	/* 3E written multiple times */
-		0x00,	/* never written */
-	} };
-
-	if (norm == MATROXFB_OUTPUT_MODE_PAL) {
-		*data = palregs;
-		*outd = &paloutd;
-	} else {
-  		*data = ntscregs;
-		*outd = &ntscoutd;
-	}
- 	return;
-}
-
-#define LR(x) cve2_set_reg(minfo, (x), m->regs[(x)])
-static void cve2_init_TV(struct matrox_fb_info *minfo,
-			 const struct mavenregs *m)
-{
-	int i;
-
-	LR(0x80);
-	LR(0x82); LR(0x83);
-	LR(0x84); LR(0x85);
-	
-	cve2_set_reg(minfo, 0x3E, 0x01);
-	
-	for (i = 0; i < 0x3E; i++) {
-		LR(i);
-	}
-	cve2_set_reg(minfo, 0x3E, 0x00);
-}
-
-static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
-	struct matrox_fb_info *minfo = md;
-
-	dprintk(KERN_DEBUG "Computing, mode=%u\n", minfo->outputs[1].mode);
-
-	if (mt->crtc == MATROXFB_SRC_CRTC2 &&
-	    minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
-		const struct output_desc* outd;
-
-		cve2_init_TVdata(minfo->outputs[1].mode, &minfo->hw.maven, &outd);
-		{
-			int blacklevel, whitelevel;
-			g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
-			minfo->hw.maven.regs[0x0E] = blacklevel >> 2;
-			minfo->hw.maven.regs[0x0F] = blacklevel & 3;
-			minfo->hw.maven.regs[0x1E] = whitelevel >> 2;
-			minfo->hw.maven.regs[0x1F] = whitelevel & 3;
-
-			minfo->hw.maven.regs[0x20] =
-			minfo->hw.maven.regs[0x22] = minfo->altout.tvo_params.saturation;
-
-			minfo->hw.maven.regs[0x25] = minfo->altout.tvo_params.hue;
-
-			if (minfo->altout.tvo_params.testout) {
-				minfo->hw.maven.regs[0x05] |= 0x02;
-			}
-		}
-		computeRegs(minfo, &minfo->hw.maven, mt, outd);
-	} else if (mt->mnp < 0) {
-		/* We must program clocks before CRTC2, otherwise interlaced mode
-		   startup may fail */
-		mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
-		mt->pixclock = g450_mnp2f(minfo, mt->mnp);
-	}
-	dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock);
-	return 0;
-}
-
-static int matroxfb_g450_program(void* md) {
-	struct matrox_fb_info *minfo = md;
-	
-	if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
-		cve2_init_TV(minfo, &minfo->hw.maven);
-	}
-	return 0;
-}
-
-static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) {
-	switch (arg) {
-		case MATROXFB_OUTPUT_MODE_PAL:
-		case MATROXFB_OUTPUT_MODE_NTSC:
-		case MATROXFB_OUTPUT_MODE_MONITOR:
-			return 0;
-	}
-	return -EINVAL;
-}
-
-static int g450_dvi_compute(void* md, struct my_timming* mt) {
-	struct matrox_fb_info *minfo = md;
-
-	if (mt->mnp < 0) {
-		mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
-		mt->pixclock = g450_mnp2f(minfo, mt->mnp);
-	}
-	return 0;
-}
-
-static struct matrox_altout matroxfb_g450_altout = {
-	.name		= "Secondary output",
-	.compute	= matroxfb_g450_compute,
-	.program	= matroxfb_g450_program,
-	.verifymode	= matroxfb_g450_verify_mode,
-	.getqueryctrl	= g450_query_ctrl,
-	.getctrl	= g450_get_ctrl,
-	.setctrl	= g450_set_ctrl,
-};
-
-static struct matrox_altout matroxfb_g450_dvi = {
-	.name		= "DVI output",
-	.compute	= g450_dvi_compute,
-};
-
-void matroxfb_g450_connect(struct matrox_fb_info *minfo)
-{
-	if (minfo->devflags.g450dac) {
-		down_write(&minfo->altout.lock);
-		tvo_fill_defaults(minfo);
-		minfo->outputs[1].src = minfo->outputs[1].default_src;
-		minfo->outputs[1].data = minfo;
-		minfo->outputs[1].output = &matroxfb_g450_altout;
-		minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-		minfo->outputs[2].src = minfo->outputs[2].default_src;
-		minfo->outputs[2].data = minfo;
-		minfo->outputs[2].output = &matroxfb_g450_dvi;
-		minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-		up_write(&minfo->altout.lock);
-	}
-}
-
-void matroxfb_g450_shutdown(struct matrox_fb_info *minfo)
-{
-	if (minfo->devflags.g450dac) {
-		down_write(&minfo->altout.lock);
-		minfo->outputs[1].src = MATROXFB_SRC_NONE;
-		minfo->outputs[1].output = NULL;
-		minfo->outputs[1].data = NULL;
-		minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-		minfo->outputs[2].src = MATROXFB_SRC_NONE;
-		minfo->outputs[2].output = NULL;
-		minfo->outputs[2].data = NULL;
-		minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-		up_write(&minfo->altout.lock);
-	}
-}
-
-EXPORT_SYMBOL(matroxfb_g450_connect);
-EXPORT_SYMBOL(matroxfb_g450_shutdown);
-
-MODULE_AUTHOR("(c) 2000-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Matrox G450/G550 output driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_g450.h b/drivers/video/matrox/matroxfb_g450.h
deleted file mode 100644
index 3a3e654444b8..000000000000
--- a/drivers/video/matrox/matroxfb_g450.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __MATROXFB_G450_H__
-#define __MATROXFB_G450_H__
-
-#include "matroxfb_base.h"
-
-#ifdef CONFIG_FB_MATROX_G
-void matroxfb_g450_connect(struct matrox_fb_info *minfo);
-void matroxfb_g450_shutdown(struct matrox_fb_info *minfo);
-#else
-static inline void matroxfb_g450_connect(struct matrox_fb_info *minfo) { };
-static inline void matroxfb_g450_shutdown(struct matrox_fb_info *minfo) { };
-#endif
-
-#endif /* __MATROXFB_G450_H__ */
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
deleted file mode 100644
index ee41a0f276b2..000000000000
--- a/drivers/video/matrox/matroxfb_maven.c
+++ /dev/null
@@ -1,1301 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.65 2002/08/14
- *
- * See matroxfb_base.c for contributors.
- *
- */
-
-#include "matroxfb_maven.h"
-#include "matroxfb_misc.h"
-#include "matroxfb_DAC1064.h"
-#include <linux/i2c.h>
-#include <linux/matroxfb.h>
-#include <linux/slab.h>
-#include <asm/div64.h>
-
-#define MGATVO_B	1
-#define MGATVO_C	2
-
-static const struct maven_gamma {
-  unsigned char reg83;
-  unsigned char reg84;
-  unsigned char reg85;
-  unsigned char reg86;
-  unsigned char reg87;
-  unsigned char reg88;
-  unsigned char reg89;
-  unsigned char reg8a;
-  unsigned char reg8b;
-} maven_gamma[] = {
-  { 131, 57, 223, 15, 117, 212, 251, 91, 156},
-  { 133, 61, 128, 63, 180, 147, 195, 100, 180},
-  { 131, 19, 63, 31, 50, 66, 171, 64, 176},
-  { 0, 0, 0, 31, 16, 16, 16, 100, 200},
-  { 8, 23, 47, 73, 147, 244, 220, 80, 195},
-  { 22, 43, 64, 80, 147, 115, 58, 85, 168},
-  { 34, 60, 80, 214, 147, 212, 188, 85, 167},
-  { 45, 77, 96, 216, 147, 99, 91, 85, 159},
-  { 56, 76, 112, 107, 147, 212, 148, 64, 144},
-  { 65, 91, 128, 137, 147, 196, 17, 69, 148},
-  { 72, 104, 136, 138, 147, 180, 245, 73, 147},
-  { 87, 116, 143, 126, 16, 83, 229, 77, 144},
-  { 95, 119, 152, 254, 244, 83, 221, 77, 151},
-  { 100, 129, 159, 156, 244, 148, 197, 77, 160},
-  { 105, 141, 167, 247, 244, 132, 181, 84, 166},
-  { 105, 147, 168, 247, 244, 245, 181, 90, 170},
-  { 120, 153, 175, 248, 212, 229, 165, 90, 180},
-  { 119, 156, 176, 248, 244, 229, 84, 74, 160},
-  { 119, 158, 183, 248, 244, 229, 149, 78, 165}
-};
-
-/* Definition of the various controls */
-struct mctl {
-	struct v4l2_queryctrl desc;
-	size_t control;
-};
-
-#define BLMIN	0x0FF
-#define WLMAX	0x3FF
-
-static const struct mctl maven_controls[] =
-{	{ { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
-	  "brightness",
-	  0, WLMAX - BLMIN, 1, 379 - BLMIN, 
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
-	{ { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
-	  "contrast",
-	  0, 1023, 1, 127,
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
-	{ { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
-	  "saturation",
-	  0, 255, 1, 155,
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
-	{ { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
-	  "hue",
-	  0, 255, 1, 0,
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
-	{ { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER,
-	  "gamma",
-	  0, ARRAY_SIZE(maven_gamma) - 1, 1, 3,
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) },
-	{ { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
-	  "test output",
-	  0, 1, 1, 0,
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
-	{ { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER,
-	  "deflicker mode",
-	  0, 2, 1, 0,
-	  0,
-	}, offsetof(struct matrox_fb_info, altout.tvo_params.deflicker) },
-
-};
-
-#define MAVCTRLS ARRAY_SIZE(maven_controls)
-
-/* Return: positive number: id found
-           -EINVAL:         id not found, return failure
-	   -ENOENT:         id not found, create fake disabled control */
-static int get_ctrl_id(__u32 v4l2_id) {
-	int i;
-
-	for (i = 0; i < MAVCTRLS; i++) {
-		if (v4l2_id < maven_controls[i].desc.id) {
-			if (maven_controls[i].desc.id == 0x08000000) {
-				return -EINVAL;
-			}
-			return -ENOENT;
-		}
-		if (v4l2_id == maven_controls[i].desc.id) {
-			return i;
-		}
-	}
-	return -EINVAL;
-}
-
-struct maven_data {
-	struct matrox_fb_info*		primary_head;
-	struct i2c_client		*client;
-	int				version;
-};
-
-static int* get_ctrl_ptr(struct maven_data* md, int idx) {
-	return (int*)((char*)(md->primary_head) + maven_controls[idx].control);
-}
-
-static int maven_get_reg(struct i2c_client* c, char reg) {
-	char dst;
-	struct i2c_msg msgs[] = {
-		{
-			.addr = c->addr,
-			.flags = I2C_M_REV_DIR_ADDR,
-			.len = sizeof(reg),
-			.buf = &reg
-		},
-		{
-			.addr = c->addr,
-			.flags = I2C_M_RD | I2C_M_NOSTART,
-			.len = sizeof(dst),
-			.buf = &dst
-		}
-	};
-	s32 err;
-
-	err = i2c_transfer(c->adapter, msgs, 2);
-	if (err < 0)
-		printk(KERN_INFO "ReadReg(%d) failed\n", reg);
-	return dst & 0xFF;
-}
-
-static int maven_set_reg(struct i2c_client* c, int reg, int val) {
-	s32 err;
-
-	err = i2c_smbus_write_byte_data(c, reg, val);
-	if (err)
-		printk(KERN_INFO "WriteReg(%d) failed\n", reg);
-	return err;
-}
-
-static int maven_set_reg_pair(struct i2c_client* c, int reg, int val) {
-	s32 err;
-
-	err = i2c_smbus_write_word_data(c, reg, val);
-	if (err)
-		printk(KERN_INFO "WriteRegPair(%d) failed\n", reg);
-	return err;
-}
-
-static const struct matrox_pll_features maven_pll = {
-	50000,
-	27000,
-	4, 127,
-	2, 31,
-	3
-};
-
-struct matrox_pll_features2 {
-	unsigned int	vco_freq_min;
-	unsigned int	vco_freq_max;
-	unsigned int	feed_div_min;
-	unsigned int	feed_div_max;
-	unsigned int	in_div_min;
-	unsigned int	in_div_max;
-	unsigned int	post_shift_max;
-};
-
-struct matrox_pll_ctl {
-	unsigned int	ref_freq;
-	unsigned int	den;
-};
-
-static const struct matrox_pll_features2 maven1000_pll = {
-	 50000000,
-	300000000,
-	 5, 128,
-	 3,  32,
-	 3
-};
-
-static const struct matrox_pll_ctl maven_PAL = {
-	540000,
-	    50
-};
-
-static const struct matrox_pll_ctl maven_NTSC = {
-	450450,	/* 27027000/60 == 27000000/59.94005994 */
-	    60
-};
-
-static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
-		const struct matrox_pll_ctl* ctl,
-		unsigned int htotal, unsigned int vtotal,
-		unsigned int* in, unsigned int* feed, unsigned int* post,
-		unsigned int* h2) {
-	unsigned int besth2 = 0;
-	unsigned int fxtal = ctl->ref_freq;
-	unsigned int fmin = pll->vco_freq_min / ctl->den;
-	unsigned int fwant;
-	unsigned int p;
-	unsigned int scrlen;
-	unsigned int fmax;
-
-	DBG(__func__)
-
-	scrlen = htotal * (vtotal - 1);
-	fwant = htotal * vtotal;
-	fmax = pll->vco_freq_max / ctl->den;
-
-	dprintk(KERN_DEBUG "want: %u, xtal: %u, h: %u, v: %u, fmax: %u\n",
-		fwant, fxtal, htotal, vtotal, fmax);
-	for (p = 1; p <= pll->post_shift_max; p++) {
-		if (fwant * 2 > fmax)
-			break;
-		fwant *= 2;
-	}
-	if (fwant > fmax)
-		return 0;
-	for (; p-- > 0; fwant >>= 1) {
-		unsigned int m;
-
-		if (fwant < fmin) break;
-		for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
-			unsigned int n;
-			unsigned int dvd;
-			unsigned int ln;
-
-			n = (fwant * m) / fxtal;
-			if (n < pll->feed_div_min)
-				continue;
-			if (n > pll->feed_div_max)
-				break;
-
-			ln = fxtal * n;
-			dvd = m << p;
-
-			if (ln % dvd)
-				continue;
-			ln = ln / dvd;
-
-			if (ln < scrlen + 2)
-				continue;
-			ln = ln - scrlen;
-			if (ln > htotal)
-				continue;
-			dprintk(KERN_DEBUG "Match: %u / %u / %u / %u\n", n, m, p, ln);
-			if (ln > besth2) {
-				dprintk(KERN_DEBUG "Better...\n");
-				*h2 = besth2 = ln;
-				*post = p;
-				*in = m;
-				*feed = n;
-			}
-		}
-	}
-
-	/* if h2/post/in/feed have not been assigned, return zero (error) */
-	if (besth2 < 2)
-		return 0;
-
-	dprintk(KERN_ERR "clk: %02X %02X %02X %d %d\n", *in, *feed, *post, fxtal, fwant);
-	return fxtal * (*feed) / (*in) * ctl->den;
-}
-
-static int matroxfb_mavenclock(const struct matrox_pll_ctl *ctl,
-		unsigned int htotal, unsigned int vtotal,
-		unsigned int* in, unsigned int* feed, unsigned int* post,
-		unsigned int* htotal2) {
-	unsigned int fvco;
-	unsigned int uninitialized_var(p);
-
-	fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
-	if (!fvco)
-		return -EINVAL;
-	p = (1 << p) - 1;
-	if (fvco <= 100000000)
-		;
-	else if (fvco <= 140000000)
-		p |= 0x08;
-	else if (fvco <= 180000000)
-		p |= 0x10;
-	else
-		p |= 0x18;
-	*post = p;
-	return 0;
-}
-
-static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
-		unsigned int* in, unsigned int* feed, unsigned int* post) {
-	unsigned int fvco;
-	unsigned int p;
-
-	fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
-	p = (1 << p) - 1;
-	if (fvco <= 100000)
-		;
-	else if (fvco <= 140000)
-		p |= 0x08;
-	else if (fvco <= 180000)
-		p |= 0x10;
-	else
-		p |= 0x18;
-	*post = p;
-	return;
-}
-
-static unsigned char maven_compute_deflicker (const struct maven_data* md) {
-	unsigned char df;
-	
-	df = (md->version == MGATVO_B?0x40:0x00);
-	switch (md->primary_head->altout.tvo_params.deflicker) {
-		case 0:
-/*			df |= 0x00; */
-			break;
-		case 1:
-			df |= 0xB1;
-			break;
-		case 2:
-			df |= 0xA2;
-			break;
-	}
-	return df;
-}
-
-static void maven_compute_bwlevel (const struct maven_data* md,
-				   int *bl, int *wl) {
-	const int b = md->primary_head->altout.tvo_params.brightness + BLMIN;
-	const int c = md->primary_head->altout.tvo_params.contrast;
-
-	*bl = max(b - c, BLMIN);
-	*wl = min(b + c, WLMAX);
-}
-
-static const struct maven_gamma* maven_compute_gamma (const struct maven_data* md) {
- 	return maven_gamma + md->primary_head->altout.tvo_params.gamma;
-}
-
-
-static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* data) {
-	static struct mavenregs palregs = { {
-		0x2A, 0x09, 0x8A, 0xCB,	/* 00: chroma subcarrier */
-		0x00,
-		0x00,	/* ? not written */
-		0x00,	/* modified by code (F9 written...) */
-		0x00,	/* ? not written */
-		0x7E,	/* 08 */
-		0x44,	/* 09 */
-		0x9C,	/* 0A */
-		0x2E,	/* 0B */
-		0x21,	/* 0C */
-		0x00,	/* ? not written */
-		0x3F, 0x03, /* 0E-0F */
-		0x3F, 0x03, /* 10-11 */
-		0x1A,	/* 12 */
-		0x2A,	/* 13 */
-		0x1C, 0x3D, 0x14, /* 14-16 */
-		0x9C, 0x01, /* 17-18 */
-		0x00,	/* 19 */
-		0xFE,	/* 1A */
-		0x7E,	/* 1B */
-		0x60,	/* 1C */
-		0x05,	/* 1D */
-		0x89, 0x03, /* 1E-1F */
-		0x72,	/* 20 */
-		0x07,	/* 21 */
-		0x72,	/* 22 */
-		0x00,	/* 23 */
-		0x00,	/* 24 */
-		0x00,	/* 25 */
-		0x08,	/* 26 */
-		0x04,	/* 27 */
-		0x00,	/* 28 */
-		0x1A,	/* 29 */
-		0x55, 0x01, /* 2A-2B */
-		0x26,	/* 2C */
-		0x07, 0x7E, /* 2D-2E */
-		0x02, 0x54, /* 2F-30 */
-		0xB0, 0x00, /* 31-32 */
-		0x14,	/* 33 */
-		0x49,	/* 34 */
-		0x00,	/* 35 written multiple times */
-		0x00,	/* 36 not written */
-		0xA3,	/* 37 */
-		0xC8,	/* 38 */
-		0x22,	/* 39 */
-		0x02,	/* 3A */
-		0x22,	/* 3B */
-		0x3F, 0x03, /* 3C-3D */
-		0x00,	/* 3E written multiple times */
-		0x00,	/* 3F not written */
-	}, MATROXFB_OUTPUT_MODE_PAL, 625, 50 };
-	static struct mavenregs ntscregs = { {
-		0x21, 0xF0, 0x7C, 0x1F,	/* 00: chroma subcarrier */
-		0x00,
-		0x00,	/* ? not written */
-		0x00,	/* modified by code (F9 written...) */
-		0x00,	/* ? not written */
-		0x7E,	/* 08 */
-		0x43,	/* 09 */
-		0x7E,	/* 0A */
-		0x3D,	/* 0B */
-		0x00,	/* 0C */
-		0x00,	/* ? not written */
-		0x41, 0x00, /* 0E-0F */
-		0x3C, 0x00, /* 10-11 */
-		0x17,	/* 12 */
-		0x21,	/* 13 */
-		0x1B, 0x1B, 0x24, /* 14-16 */
-		0x83, 0x01, /* 17-18 */
-		0x00,	/* 19 */
-		0x0F,	/* 1A */
-		0x0F,	/* 1B */
-		0x60,	/* 1C */
-		0x05,	/* 1D */
-		0x89, 0x02, /* 1E-1F */
-		0x5F,	/* 20 */
-		0x04,	/* 21 */
-		0x5F,	/* 22 */
-		0x01,	/* 23 */
-		0x02,	/* 24 */
-		0x00,	/* 25 */
-		0x0A,	/* 26 */
-		0x05,	/* 27 */
-		0x00,	/* 28 */
-		0x10,	/* 29 */
-		0xFF, 0x03, /* 2A-2B */
-		0x24,	/* 2C */
-		0x0F, 0x78, /* 2D-2E */
-		0x00, 0x00, /* 2F-30 */
-		0xB2, 0x04, /* 31-32 */
-		0x14,	/* 33 */
-		0x02,	/* 34 */
-		0x00,	/* 35 written multiple times */
-		0x00,	/* 36 not written */
-		0xA3,	/* 37 */
-		0xC8,	/* 38 */
-		0x15,	/* 39 */
-		0x05,	/* 3A */
-		0x3B,	/* 3B */
-		0x3C, 0x00, /* 3C-3D */
-		0x00,	/* 3E written multiple times */
-		0x00,	/* never written */
-	}, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 };
-	struct matrox_fb_info *minfo = md->primary_head;
-
-	if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_PAL)
-		*data = palregs;
-	else
-		*data = ntscregs;
-
-	/* Set deflicker */
-	data->regs[0x93] = maven_compute_deflicker(md);
- 
-	/* set gamma */
-	{
-		const struct maven_gamma* g;
-		g = maven_compute_gamma(md);
-		data->regs[0x83] = g->reg83;
-		data->regs[0x84] = g->reg84;
-		data->regs[0x85] = g->reg85;
-		data->regs[0x86] = g->reg86;
-		data->regs[0x87] = g->reg87;
-		data->regs[0x88] = g->reg88;
-		data->regs[0x89] = g->reg89;
-		data->regs[0x8A] = g->reg8a;
-		data->regs[0x8B] = g->reg8b;
-	}
- 
-	/* Set contrast / brightness */
-	{
-		int bl, wl;
-		maven_compute_bwlevel (md, &bl, &wl);
-		data->regs[0x0e] = bl >> 2;
-		data->regs[0x0f] = bl & 3;
-		data->regs[0x1e] = wl >> 2;
-		data->regs[0x1f] = wl & 3;
-	}
-
-	/* Set saturation */
-	{
-		data->regs[0x20] =
-		data->regs[0x22] = minfo->altout.tvo_params.saturation;
-	}
- 
-	/* Set HUE */
-	data->regs[0x25] = minfo->altout.tvo_params.hue;
-	return;
-}
-
-#define LR(x) maven_set_reg(c, (x), m->regs[(x)])
-#define LRP(x) maven_set_reg_pair(c, (x), m->regs[(x)] | (m->regs[(x)+1] << 8))
-static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
-	int val;
-
-
-	maven_set_reg(c, 0x3E, 0x01);
-	maven_get_reg(c, 0x82);	/* fetch oscillator state? */
-	maven_set_reg(c, 0x8C, 0x00);
-	maven_get_reg(c, 0x94);	/* get 0x82 */
-	maven_set_reg(c, 0x94, 0xA2);
-	/* xmiscctrl */
-
-	maven_set_reg_pair(c, 0x8E, 0x1EFF);
-	maven_set_reg(c, 0xC6, 0x01);
-
-	/* removed code... */
-
-	maven_get_reg(c, 0x06);
-	maven_set_reg(c, 0x06, 0xF9);	/* or read |= 0xF0 ? */
-
-	/* removed code here... */
-
-	/* real code begins here? */
-	/* chroma subcarrier */
-	LR(0x00); LR(0x01); LR(0x02); LR(0x03);
-
-	LR(0x04);
-
-	LR(0x2C);
-	LR(0x08);
-	LR(0x0A);
-	LR(0x09);
-	LR(0x29);
-	LRP(0x31);
-	LRP(0x17);
-	LR(0x0B);
-	LR(0x0C);
-	if (m->mode == MATROXFB_OUTPUT_MODE_PAL) {
-		maven_set_reg(c, 0x35, 0x10); /* ... */
-	} else {
-		maven_set_reg(c, 0x35, 0x0F); /* ... */
-	}
-
-	LRP(0x10);
-
-	LRP(0x0E);
-	LRP(0x1E);
-
-	LR(0x20);	/* saturation #1 */
-	LR(0x22);	/* saturation #2 */
-	LR(0x25);	/* hue */
-	LR(0x34);
-	LR(0x33);
-	LR(0x19);
-	LR(0x12);
-	LR(0x3B);
-	LR(0x13);
-	LR(0x39);
-	LR(0x1D);
-	LR(0x3A);
-	LR(0x24);
-	LR(0x14);
-	LR(0x15);
-	LR(0x16);
-	LRP(0x2D);
-	LRP(0x2F);
-	LR(0x1A);
-	LR(0x1B);
-	LR(0x1C);
-	LR(0x23);
-	LR(0x26);
-	LR(0x28);
-	LR(0x27);
-	LR(0x21);
-	LRP(0x2A);
-	if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
-		maven_set_reg(c, 0x35, 0x1D);	/* ... */
-	else
-		maven_set_reg(c, 0x35, 0x1C);
-
-	LRP(0x3C);
-	LR(0x37);
-	LR(0x38);
-	maven_set_reg(c, 0xB3, 0x01);
-
-	maven_get_reg(c, 0xB0);	/* read 0x80 */
-	maven_set_reg(c, 0xB0, 0x08);	/* ugh... */
-	maven_get_reg(c, 0xB9);	/* read 0x7C */
-	maven_set_reg(c, 0xB9, 0x78);
-	maven_get_reg(c, 0xBF);	/* read 0x00 */
-	maven_set_reg(c, 0xBF, 0x02);
-	maven_get_reg(c, 0x94);	/* read 0x82 */
-	maven_set_reg(c, 0x94, 0xB3);
-
-	LR(0x80); /* 04 1A 91 or 05 21 91 */
-	LR(0x81);
-	LR(0x82);
-
-	maven_set_reg(c, 0x8C, 0x20);
-	maven_get_reg(c, 0x8D);
-	maven_set_reg(c, 0x8D, 0x10);
-
-	LR(0x90); /* 4D 50 52 or 4E 05 45 */
-	LR(0x91);
-	LR(0x92);
-
-	LRP(0x9A); /* 0049 or 004F */
-	LRP(0x9C); /* 0004 or 0004 */
-	LRP(0x9E); /* 0458 or 045E */
-	LRP(0xA0); /* 05DA or 051B */
-	LRP(0xA2); /* 00CC or 00CF */
-	LRP(0xA4); /* 007D or 007F */
-	LRP(0xA6); /* 007C or 007E */
-	LRP(0xA8); /* 03CB or 03CE */
-	LRP(0x98); /* 0000 or 0000 */
-	LRP(0xAE); /* 0044 or 003A */
-	LRP(0x96); /* 05DA or 051B */
-	LRP(0xAA); /* 04BC or 046A */
-	LRP(0xAC); /* 004D or 004E */
-
-	LR(0xBE);
-	LR(0xC2);
-
-	maven_get_reg(c, 0x8D);
-	maven_set_reg(c, 0x8D, 0x04);
-
-	LR(0x20);	/* saturation #1 */
-	LR(0x22);	/* saturation #2 */
-	LR(0x93);	/* whoops */
-	LR(0x20);	/* oh, saturation #1 again */
-	LR(0x22);	/* oh, saturation #2 again */
-	LR(0x25);	/* hue */
-	LRP(0x0E);
-	LRP(0x1E);
-	LRP(0x0E);	/* problems with memory? */
-	LRP(0x1E);	/* yes, matrox must have problems in memory area... */
-
-	/* load gamma correction stuff */
-	LR(0x83);
-	LR(0x84);
-	LR(0x85);
-	LR(0x86);
-	LR(0x87);
-	LR(0x88);
-	LR(0x89);
-	LR(0x8A);
-	LR(0x8B);
-
-	val = maven_get_reg(c, 0x8D);
-	val &= 0x14;			/* 0x10 or anything ored with it */
-	maven_set_reg(c, 0x8D, val);
-
-	LR(0x33);
-	LR(0x19);
-	LR(0x12);
-	LR(0x3B);
-	LR(0x13);
-	LR(0x39);
-	LR(0x1D);
-	LR(0x3A);
-	LR(0x24);
-	LR(0x14);
-	LR(0x15);
-	LR(0x16);
-	LRP(0x2D);
-	LRP(0x2F);
-	LR(0x1A);
-	LR(0x1B);
-	LR(0x1C);
-	LR(0x23);
-	LR(0x26);
-	LR(0x28);
-	LR(0x27);
-	LR(0x21);
-	LRP(0x2A);
-	if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
-		maven_set_reg(c, 0x35, 0x1D);
-	else
-		maven_set_reg(c, 0x35, 0x1C);
-	LRP(0x3C);
-	LR(0x37);
-	LR(0x38);
-
-	maven_get_reg(c, 0xB0);
-	LR(0xB0);	/* output mode */
-	LR(0x90);
-	LR(0xBE);
-	LR(0xC2);
-
-	LRP(0x9A);
-	LRP(0xA2);
-	LRP(0x9E);
-	LRP(0xA6);
-	LRP(0xAA);
-	LRP(0xAC);
-	maven_set_reg(c, 0x3E, 0x00);
-	maven_set_reg(c, 0x95, 0x20);
-}
-
-static int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
-		struct mavenregs* m) {
-	unsigned int x;
-	unsigned int err = ~0;
-
-	/* 1:1 */
-	m->regs[0x80] = 0x0F;
-	m->regs[0x81] = 0x07;
-	m->regs[0x82] = 0x81;
-
-	for (x = 0; x < 8; x++) {
-		unsigned int c;
-		unsigned int uninitialized_var(a), uninitialized_var(b),
-			     uninitialized_var(h2);
-		unsigned int h = ht + 2 + x;
-
-		if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
-			unsigned int diff = h - h2;
-
-			if (diff < err) {
-				err = diff;
-				m->regs[0x80] = a - 1;
-				m->regs[0x81] = b - 1;
-				m->regs[0x82] = c | 0x80;
-				m->hcorr = h2 - 2;
-				m->htotal = h - 2;
-			}
-		}
-	}
-	return err != ~0U;
-}
-
-static inline int maven_compute_timming(struct maven_data* md,
-		struct my_timming* mt,
-		struct mavenregs* m) {
-	unsigned int tmpi;
-	unsigned int a, bv, c;
-	struct matrox_fb_info *minfo = md->primary_head;
-
-	m->mode = minfo->outputs[1].mode;
-	if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) {
-		unsigned int lmargin;
-		unsigned int umargin;
-		unsigned int vslen;
-		unsigned int hcrt;
-		unsigned int slen;
-
-		maven_init_TVdata(md, m);
-
-		if (maven_find_exact_clocks(mt->HTotal, mt->VTotal, m) == 0)
-			return -EINVAL;
-
-		lmargin = mt->HTotal - mt->HSyncEnd;
-		slen = mt->HSyncEnd - mt->HSyncStart;
-		hcrt = mt->HTotal - slen - mt->delay;
-		umargin = mt->VTotal - mt->VSyncEnd;
-		vslen = mt->VSyncEnd - mt->VSyncStart;
-
-		if (m->hcorr < mt->HTotal)
-			hcrt += m->hcorr;
-		if (hcrt > mt->HTotal)
-			hcrt -= mt->HTotal;
-		if (hcrt + 2 > mt->HTotal)
-			hcrt = 0;	/* or issue warning? */
-
-		/* last (first? middle?) line in picture can have different length */
-		/* hlen - 2 */
-		m->regs[0x96] = m->hcorr;
-		m->regs[0x97] = m->hcorr >> 8;
-		/* ... */
-		m->regs[0x98] = 0x00; m->regs[0x99] = 0x00;
-		/* hblanking end */
-		m->regs[0x9A] = lmargin;	/* 100% */
-		m->regs[0x9B] = lmargin >> 8;	/* 100% */
-		/* who knows */
-		m->regs[0x9C] = 0x04;
-		m->regs[0x9D] = 0x00;
-		/* htotal - 2 */
-		m->regs[0xA0] = m->htotal;
-		m->regs[0xA1] = m->htotal >> 8;
-		/* vblanking end */
-		m->regs[0xA2] = mt->VTotal - mt->VSyncStart - 1;	/* stop vblanking */
-		m->regs[0xA3] = (mt->VTotal - mt->VSyncStart - 1) >> 8;
-		/* something end... [A6]+1..[A8] */
-		if (md->version == MGATVO_B) {
-			m->regs[0xA4] = 0x04;
-			m->regs[0xA5] = 0x00;
-		} else {
-			m->regs[0xA4] = 0x01;
-			m->regs[0xA5] = 0x00;
-		}
-		/* something start... 0..[A4]-1 */
-		m->regs[0xA6] = 0x00;
-		m->regs[0xA7] = 0x00;
-		/* vertical line count - 1 */
-		m->regs[0xA8] = mt->VTotal - 1;
-		m->regs[0xA9] = (mt->VTotal - 1) >> 8;
-		/* horizontal vidrst pos */
-		m->regs[0xAA] = hcrt;		/* 0 <= hcrt <= htotal - 2 */
-		m->regs[0xAB] = hcrt >> 8;
-		/* vertical vidrst pos */
-		m->regs[0xAC] = mt->VTotal - 2;
-		m->regs[0xAD] = (mt->VTotal - 2) >> 8;
-		/* moves picture up/down and so on... */
-		m->regs[0xAE] = 0x01; /* Fix this... 0..VTotal */
-		m->regs[0xAF] = 0x00;
-		{
-			int hdec;
-			int hlen;
-			unsigned int ibmin = 4 + lmargin + mt->HDisplay;
-			unsigned int ib;
-			int i;
-
-			/* Verify! */
-			/* Where 94208 came from? */
-			if (mt->HTotal)
-				hdec = 94208 / (mt->HTotal);
-			else
-				hdec = 0x81;
-			if (hdec > 0x81)
-				hdec = 0x81;
-			if (hdec < 0x41)
-				hdec = 0x41;
-			hdec--;
-			hlen = 98304 - 128 - ((lmargin + mt->HDisplay - 8) * hdec);
-			if (hlen < 0)
-				hlen = 0;
-			hlen = hlen >> 8;
-			if (hlen > 0xFF)
-				hlen = 0xFF;
-			/* Now we have to compute input buffer length.
-			   If you want any picture, it must be between
-			     4 + lmargin + xres
-			   and
-			     94208 / hdec
-			   If you want perfect picture even on the top
-			   of screen, it must be also
-			     0x3C0000 * i / hdec + Q - R / hdec
-			   where
-			        R      Qmin   Qmax
-			     0x07000   0x5AE  0x5BF
-			     0x08000   0x5CF  0x5FF
-			     0x0C000   0x653  0x67F
-			     0x10000   0x6F8  0x6FF
-			 */
-			i = 1;
-			do {
-				ib = ((0x3C0000 * i - 0x8000)/ hdec + 0x05E7) >> 8;
-				i++;
-			} while (ib < ibmin);
-			if (ib >= m->htotal + 2) {
-				ib = ibmin;
-			}
-
-			m->regs[0x90] = hdec;	/* < 0x40 || > 0x80 is bad... 0x80 is questionable */
-			m->regs[0xC2] = hlen;
-			/* 'valid' input line length */
-			m->regs[0x9E] = ib;
-			m->regs[0x9F] = ib >> 8;
-		}
-		{
-			int vdec;
-			int vlen;
-
-#define MATROX_USE64BIT_DIVIDE
-			if (mt->VTotal) {
-#ifdef MATROX_USE64BIT_DIVIDE
-				u64 f1;
-				u32 a;
-				u32 b;
-
-				a = m->vlines * (m->htotal + 2);
-				b = (mt->VTotal - 1) * (m->htotal + 2) + m->hcorr + 2;
-
-				f1 = ((u64)a) << 15;	/* *32768 */
-				do_div(f1, b);
-				vdec = f1;
-#else
-				vdec = m->vlines * 32768 / mt->VTotal;
-#endif
-			} else
-				vdec = 0x8000;
-			if (vdec > 0x8000)
-				vdec = 0x8000;
-			vlen = (vslen + umargin + mt->VDisplay) * vdec;
-			vlen = (vlen >> 16) - 146; /* FIXME: 146?! */
-			if (vlen < 0)
-				vlen = 0;
-			if (vlen > 0xFF)
-				vlen = 0xFF;
-			vdec--;
-			m->regs[0x91] = vdec;
-			m->regs[0x92] = vdec >> 8;
-			m->regs[0xBE] = vlen;
-		}
-		m->regs[0xB0] = 0x08;	/* output: SVideo/Composite */
-		return 0;
-	}
-
-	DAC1064_calcclock(mt->pixclock, 450000, &a, &bv, &c);
-	m->regs[0x80] = a;
-	m->regs[0x81] = bv;
-	m->regs[0x82] = c | 0x80;
-
-	m->regs[0xB3] = 0x01;
-	m->regs[0x94] = 0xB2;
-
-	/* htotal... */
-	m->regs[0x96] = mt->HTotal;
-	m->regs[0x97] = mt->HTotal >> 8;
-	/* ?? */
-	m->regs[0x98] = 0x00;
-	m->regs[0x99] = 0x00;
-	/* hsync len */
-	tmpi = mt->HSyncEnd - mt->HSyncStart;
-	m->regs[0x9A] = tmpi;
-	m->regs[0x9B] = tmpi >> 8;
-	/* hblank end */
-	tmpi = mt->HTotal - mt->HSyncStart;
-	m->regs[0x9C] = tmpi;
-	m->regs[0x9D] = tmpi >> 8;
-	/* hblank start */
-	tmpi += mt->HDisplay;
-	m->regs[0x9E] = tmpi;
-	m->regs[0x9F] = tmpi >> 8;
-	/* htotal + 1 */
-	tmpi = mt->HTotal + 1;
-	m->regs[0xA0] = tmpi;
-	m->regs[0xA1] = tmpi >> 8;
-	/* vsync?! */
-	tmpi = mt->VSyncEnd - mt->VSyncStart - 1;
-	m->regs[0xA2] = tmpi;
-	m->regs[0xA3] = tmpi >> 8;
-	/* ignored? */
-	tmpi = mt->VTotal - mt->VSyncStart;
-	m->regs[0xA4] = tmpi;
-	m->regs[0xA5] = tmpi >> 8;
-	/* ignored? */
-	tmpi = mt->VTotal - 1;
-	m->regs[0xA6] = tmpi;
-	m->regs[0xA7] = tmpi >> 8;
-	/* vtotal - 1 */
-	m->regs[0xA8] = tmpi;
-	m->regs[0xA9] = tmpi >> 8;
-	/* hor vidrst */
-	tmpi = mt->HTotal - mt->delay;
-	m->regs[0xAA] = tmpi;
-	m->regs[0xAB] = tmpi >> 8;
-	/* vert vidrst */
-	tmpi = mt->VTotal - 2;
-	m->regs[0xAC] = tmpi;
-	m->regs[0xAD] = tmpi >> 8;
-	/* ignored? */
-	m->regs[0xAE] = 0x00;
-	m->regs[0xAF] = 0x00;
-
-	m->regs[0xB0] = 0x03;	/* output: monitor */
-	m->regs[0xB1] = 0xA0;	/* ??? */
-	m->regs[0x8C] = 0x20;	/* must be set... */
-	m->regs[0x8D] = 0x04;	/* defaults to 0x10: test signal */
-	m->regs[0xB9] = 0x1A;	/* defaults to 0x2C: too bright */
-	m->regs[0xBF] = 0x22;	/* makes picture stable */
-
-	return 0;
-}
-
-static int maven_program_timming(struct maven_data* md,
-		const struct mavenregs* m) {
-	struct i2c_client *c = md->client;
-
-	if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
-		LR(0x80);
-		LR(0x81);
-		LR(0x82);
-
-		LR(0xB3);
-		LR(0x94);
-
-		LRP(0x96);
-		LRP(0x98);
-		LRP(0x9A);
-		LRP(0x9C);
-		LRP(0x9E);
-		LRP(0xA0);
-		LRP(0xA2);
-		LRP(0xA4);
-		LRP(0xA6);
-		LRP(0xA8);
-		LRP(0xAA);
-		LRP(0xAC);
-		LRP(0xAE);
-
-		LR(0xB0);	/* output: monitor */
-		LR(0xB1);	/* ??? */
-		LR(0x8C);	/* must be set... */
-		LR(0x8D);	/* defaults to 0x10: test signal */
-		LR(0xB9);	/* defaults to 0x2C: too bright */
-		LR(0xBF);	/* makes picture stable */
-	} else {
-		maven_init_TV(c, m);
-	}
-	return 0;
-}
-
-static inline int maven_resync(struct maven_data* md) {
-	struct i2c_client *c = md->client;
-	maven_set_reg(c, 0x95, 0x20);	/* start whole thing */
-	return 0;
-}
-
-static int maven_get_queryctrl (struct maven_data* md, 
-				struct v4l2_queryctrl *p) {
-	int i;
-	
-	i = get_ctrl_id(p->id);
-	if (i >= 0) {
-		*p = maven_controls[i].desc;
-		return 0;
-	}
-	if (i == -ENOENT) {
-		static const struct v4l2_queryctrl disctrl = 
-			{ .flags = V4L2_CTRL_FLAG_DISABLED };
-			
-		i = p->id;
-		*p = disctrl;
-		p->id = i;
-		sprintf(p->name, "Ctrl #%08X", i);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int maven_set_control (struct maven_data* md, 
-			      struct v4l2_control *p) {
-	int i;
-	
-	i = get_ctrl_id(p->id);
-	if (i < 0) return -EINVAL;
-
-	/*
-	 * Check if changed.
-	 */
-	if (p->value == *get_ctrl_ptr(md, i)) return 0;
-
-	/*
-	 * Check limits.
-	 */
-	if (p->value > maven_controls[i].desc.maximum) return -EINVAL;
-	if (p->value < maven_controls[i].desc.minimum) return -EINVAL;
-
-	/*
-	 * Store new value.
-	 */
-	*get_ctrl_ptr(md, i) = p->value;
-
-	switch (p->id) {
-		case V4L2_CID_BRIGHTNESS:
-		case V4L2_CID_CONTRAST:
-		{
-		  int blacklevel, whitelevel;
-		  maven_compute_bwlevel(md, &blacklevel, &whitelevel);
-		  blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
-		  whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
-		  maven_set_reg_pair(md->client, 0x0e, blacklevel);
-		  maven_set_reg_pair(md->client, 0x1e, whitelevel);
-		}
-		break;
-		case V4L2_CID_SATURATION:
-		{
-		  maven_set_reg(md->client, 0x20, p->value);
-		  maven_set_reg(md->client, 0x22, p->value);
-		}
-		break;
-		case V4L2_CID_HUE:
-		{
-		  maven_set_reg(md->client, 0x25, p->value);
-		}
-		break;
-		case V4L2_CID_GAMMA:
-		{
-		  const struct maven_gamma* g;
-		  g = maven_compute_gamma(md);
-		  maven_set_reg(md->client, 0x83, g->reg83);
-		  maven_set_reg(md->client, 0x84, g->reg84);
-		  maven_set_reg(md->client, 0x85, g->reg85);
-		  maven_set_reg(md->client, 0x86, g->reg86);
-		  maven_set_reg(md->client, 0x87, g->reg87);
-		  maven_set_reg(md->client, 0x88, g->reg88);
-		  maven_set_reg(md->client, 0x89, g->reg89);
-		  maven_set_reg(md->client, 0x8a, g->reg8a);
-		  maven_set_reg(md->client, 0x8b, g->reg8b);
-		}
-		break;
-		case MATROXFB_CID_TESTOUT:
-		{
-			unsigned char val 
-			  = maven_get_reg(md->client, 0x8d);
-			if (p->value) val |= 0x10;
-			else          val &= ~0x10;
-			maven_set_reg(md->client, 0x8d, val);
-		}
-		break;
-		case MATROXFB_CID_DEFLICKER:
-		{
-		  maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
-		}
-		break;
-	}
-	
-
-	return 0;
-}
-
-static int maven_get_control (struct maven_data* md, 
-			      struct v4l2_control *p) {
-	int i;
-	
-	i = get_ctrl_id(p->id);
-	if (i < 0) return -EINVAL;
-	p->value = *get_ctrl_ptr(md, i);
-	return 0;
-}
-
-/******************************************************/
-
-static int maven_out_compute(void* md, struct my_timming* mt) {
-#define mdinfo ((struct maven_data*)md)
-#define minfo (mdinfo->primary_head)
-	return maven_compute_timming(md, mt, &minfo->hw.maven);
-#undef minfo
-#undef mdinfo
-}
-
-static int maven_out_program(void* md) {
-#define mdinfo ((struct maven_data*)md)
-#define minfo (mdinfo->primary_head)
-	return maven_program_timming(md, &minfo->hw.maven);
-#undef minfo
-#undef mdinfo
-}
-
-static int maven_out_start(void* md) {
-	return maven_resync(md);
-}
-
-static int maven_out_verify_mode(void* md, u_int32_t arg) {
-	switch (arg) {
-		case MATROXFB_OUTPUT_MODE_PAL:
-		case MATROXFB_OUTPUT_MODE_NTSC:
-		case MATROXFB_OUTPUT_MODE_MONITOR:
-			return 0;
-	}
-	return -EINVAL;
-}
-
-static int maven_out_get_queryctrl(void* md, struct v4l2_queryctrl* p) {
-        return maven_get_queryctrl(md, p);
-}
-
-static int maven_out_get_ctrl(void* md, struct v4l2_control* p) {
-	return maven_get_control(md, p);
-}
-
-static int maven_out_set_ctrl(void* md, struct v4l2_control* p) {
-	return maven_set_control(md, p);
-}
-
-static struct matrox_altout maven_altout = {
-	.name		= "Secondary output",
-	.compute	= maven_out_compute,
-	.program	= maven_out_program,
-	.start		= maven_out_start,
-	.verifymode	= maven_out_verify_mode,
-	.getqueryctrl	= maven_out_get_queryctrl,
-	.getctrl	= maven_out_get_ctrl,
-	.setctrl	= maven_out_set_ctrl,
-};
-
-static int maven_init_client(struct i2c_client* clnt) {
-	struct maven_data* md = i2c_get_clientdata(clnt);
-	struct matrox_fb_info *minfo = container_of(clnt->adapter,
-						    struct i2c_bit_adapter,
-						    adapter)->minfo;
-
-	md->primary_head = minfo;
-	md->client = clnt;
-	down_write(&minfo->altout.lock);
-	minfo->outputs[1].output = &maven_altout;
-	minfo->outputs[1].src = minfo->outputs[1].default_src;
-	minfo->outputs[1].data = md;
-	minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-	up_write(&minfo->altout.lock);
-	if (maven_get_reg(clnt, 0xB2) < 0x14) {
-		md->version = MGATVO_B;
-		/* Tweak some things for this old chip */
-	} else {
-		md->version = MGATVO_C;
-	}
-	/*
-	 * Set all parameters to its initial values.
-	 */
-	{
-		unsigned int i;
-
-		for (i = 0; i < MAVCTRLS; ++i) {
-			*get_ctrl_ptr(md, i) = maven_controls[i].desc.default_value;
-		}
-	}
-
-	return 0;
-}
-
-static int maven_shutdown_client(struct i2c_client* clnt) {
-	struct maven_data* md = i2c_get_clientdata(clnt);
-
-	if (md->primary_head) {
-		struct matrox_fb_info *minfo = md->primary_head;
-
-		down_write(&minfo->altout.lock);
-		minfo->outputs[1].src = MATROXFB_SRC_NONE;
-		minfo->outputs[1].output = NULL;
-		minfo->outputs[1].data = NULL;
-		minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
-		up_write(&minfo->altout.lock);
-		md->primary_head = NULL;
-	}
-	return 0;
-}
-
-static int maven_probe(struct i2c_client *client,
-		       const struct i2c_device_id *id)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	int err = -ENODEV;
-	struct maven_data* data;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA |
-					      I2C_FUNC_SMBUS_BYTE_DATA |
-					      I2C_FUNC_NOSTART |
-					      I2C_FUNC_PROTOCOL_MANGLING))
-		goto ERROR0;
-	if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto ERROR0;
-	}
-	i2c_set_clientdata(client, data);
-	err = maven_init_client(client);
-	if (err)
-		goto ERROR4;
-	return 0;
-ERROR4:;
-	kfree(data);
-ERROR0:;
-	return err;
-}
-
-static int maven_remove(struct i2c_client *client)
-{
-	maven_shutdown_client(client);
-	kfree(i2c_get_clientdata(client));
-	return 0;
-}
-
-static const struct i2c_device_id maven_id[] = {
-	{ "maven", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, maven_id);
-
-static struct i2c_driver maven_driver={
-	.driver = {
-		.name	= "maven",
-	},
-	.probe		= maven_probe,
-	.remove		= maven_remove,
-	.id_table	= maven_id,
-};
-
-module_i2c_driver(maven_driver);
-MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_maven.h b/drivers/video/matrox/matroxfb_maven.h
deleted file mode 100644
index 99eddec9f30c..000000000000
--- a/drivers/video/matrox/matroxfb_maven.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __MATROXFB_MAVEN_H__
-#define __MATROXFB_MAVEN_H__
-
-#include <linux/ioctl.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include "matroxfb_base.h"
-
-struct i2c_bit_adapter {
-	struct i2c_adapter		adapter;
-	int				initialized;
-	struct i2c_algo_bit_data	bac;
-	struct matrox_fb_info*		minfo;
-	struct {
-		unsigned int		data;
-		unsigned int		clock;
-				      } mask;
-};
-
-#endif /* __MATROXFB_MAVEN_H__ */
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
deleted file mode 100644
index 9948ca2a3046..000000000000
--- a/drivers/video/matrox/matroxfb_misc.c
+++ /dev/null
@@ -1,815 +0,0 @@
-/*
- *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
- *
- * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
- *
- * Portions Copyright (c) 2001 Matrox Graphics Inc.
- *
- * Version: 1.65 2002/08/14
- *
- * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
- *
- * Contributors: "menion?" <menion@mindless.com>
- *                     Betatesting, fixes, ideas
- *
- *               "Kurt Garloff" <garloff@suse.de>
- *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
- *
- *               "Tom Rini" <trini@kernel.crashing.org>
- *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
- *
- *               "Bibek Sahu" <scorpio@dodds.net>
- *                     Access device through readb|w|l and write b|w|l
- *                     Extensive debugging stuff
- *
- *               "Daniel Haun" <haund@usa.net>
- *                     Testing, hardware cursor fixes
- *
- *               "Scott Wood" <sawst46+@pitt.edu>
- *                     Fixes
- *
- *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
- *                     Betatesting
- *
- *               "Kelly French" <targon@hazmat.com>
- *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
- *                     Betatesting, bug reporting
- *
- *               "Pablo Bianucci" <pbian@pccp.com.ar>
- *                     Fixes, ideas, betatesting
- *
- *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
- *                     Fixes, enhandcements, ideas, betatesting
- *
- *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
- *                     PPC betatesting, PPC support, backward compatibility
- *
- *               "Paul Womar" <Paul@pwomar.demon.co.uk>
- *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
- *                     PPC betatesting
- *
- *               "Thomas Pornin" <pornin@bolet.ens.fr>
- *                     Alpha betatesting
- *
- *               "Pieter van Leuven" <pvl@iae.nl>
- *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
- *                     G100 testing
- *
- *               "H. Peter Arvin" <hpa@transmeta.com>
- *                     Ideas
- *
- *               "Cort Dougan" <cort@cs.nmt.edu>
- *                     CHRP fixes and PReP cleanup
- *
- *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
- *                     G400 support
- *
- *               "David C. Hansen" <haveblue@us.ibm.com>
- *                     Fixes
- *
- *               "Ian Romanick" <idr@us.ibm.com>
- *                     Find PInS data in BIOS on PowerPC systems.
- *
- * (following author is not in any relation with this code, but his code
- *  is included in this driver)
- *
- * Based on framebuffer driver for VBE 2.0 compliant graphic boards
- *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- *
- * (following author is not in any relation with this code, but his ideas
- *  were used when writing this driver)
- *
- *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
- *
- */
-
-
-#include "matroxfb_misc.h"
-#include <linux/interrupt.h>
-#include <linux/matroxfb.h>
-
-void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg, int val)
-{
-	DBG_REG(__func__)
-	mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
-	mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
-}
-
-int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg)
-{
-	DBG_REG(__func__)
-	mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
-	return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
-}
-
-void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
-	unsigned int pixclock = var->pixclock;
-
-	DBG(__func__)
-
-	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
-	mt->pixclock = 1000000000 / pixclock;
-	if (mt->pixclock < 1) mt->pixclock = 1;
-	mt->mnp = -1;
-	mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
-	mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
-	mt->HDisplay = var->xres;
-	mt->HSyncStart = mt->HDisplay + var->right_margin;
-	mt->HSyncEnd = mt->HSyncStart + var->hsync_len;
-	mt->HTotal = mt->HSyncEnd + var->left_margin;
-	mt->VDisplay = var->yres;
-	mt->VSyncStart = mt->VDisplay + var->lower_margin;
-	mt->VSyncEnd = mt->VSyncStart + var->vsync_len;
-	mt->VTotal = mt->VSyncEnd + var->upper_margin;
-	mt->sync = var->sync;
-}
-
-int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
-		unsigned int* in, unsigned int* feed, unsigned int* post) {
-	unsigned int bestdiff = ~0;
-	unsigned int bestvco = 0;
-	unsigned int fxtal = pll->ref_freq;
-	unsigned int fwant;
-	unsigned int p;
-
-	DBG(__func__)
-
-	fwant = freq;
-
-#ifdef DEBUG
-	printk(KERN_ERR "post_shift_max: %d\n", pll->post_shift_max);
-	printk(KERN_ERR "ref_freq: %d\n", pll->ref_freq);
-	printk(KERN_ERR "freq: %d\n", freq);
-	printk(KERN_ERR "vco_freq_min: %d\n", pll->vco_freq_min);
-	printk(KERN_ERR "in_div_min: %d\n", pll->in_div_min);
-	printk(KERN_ERR "in_div_max: %d\n", pll->in_div_max);
-	printk(KERN_ERR "feed_div_min: %d\n", pll->feed_div_min);
-	printk(KERN_ERR "feed_div_max: %d\n", pll->feed_div_max);
-	printk(KERN_ERR "fmax: %d\n", fmax);
-#endif
-	for (p = 1; p <= pll->post_shift_max; p++) {
-		if (fwant * 2 > fmax)
-			break;
-		fwant *= 2;
-	}
-	if (fwant < pll->vco_freq_min) fwant = pll->vco_freq_min;
-	if (fwant > fmax) fwant = fmax;
-	for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
-		unsigned int m;
-
-		if (fwant < pll->vco_freq_min) break;
-		for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
-			unsigned int diff, fvco;
-			unsigned int n;
-
-			n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
-			if (n > pll->feed_div_max)
-				break;
-			if (n < pll->feed_div_min)
-				n = pll->feed_div_min;
-			fvco = (fxtal * (n + 1)) / (m + 1);
-			if (fvco < fwant)
-				diff = fwant - fvco;
-			else
-				diff = fvco - fwant;
-			if (diff < bestdiff) {
-				bestdiff = diff;
-				*post = p;
-				*in = m;
-				*feed = n;
-				bestvco = fvco;
-			}
-		}
-	}
-	dprintk(KERN_ERR "clk: %02X %02X %02X %d %d %d\n", *in, *feed, *post, fxtal, bestvco, fwant);
-	return bestvco;
-}
-
-int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming *m)
-{
-	unsigned int hd, hs, he, hbe, ht;
-	unsigned int vd, vs, ve, vt, lc;
-	unsigned int wd;
-	unsigned int divider;
-	int i;
-	struct matrox_hw_state * const hw = &minfo->hw;
-
-	DBG(__func__)
-
-	hw->SEQ[0] = 0x00;
-	hw->SEQ[1] = 0x01;	/* or 0x09 */
-	hw->SEQ[2] = 0x0F;	/* bitplanes */
-	hw->SEQ[3] = 0x00;
-	hw->SEQ[4] = 0x0E;
-	/* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millennium code... Hope that by MGA1064 too */
-	if (m->dblscan) {
-		m->VTotal <<= 1;
-		m->VDisplay <<= 1;
-		m->VSyncStart <<= 1;
-		m->VSyncEnd <<= 1;
-	}
-	if (m->interlaced) {
-		m->VTotal >>= 1;
-		m->VDisplay >>= 1;
-		m->VSyncStart >>= 1;
-		m->VSyncEnd >>= 1;
-	}
-
-	/* GCTL is ignored when not using 0xA0000 aperture */
-	hw->GCTL[0] = 0x00;
-	hw->GCTL[1] = 0x00;
-	hw->GCTL[2] = 0x00;
-	hw->GCTL[3] = 0x00;
-	hw->GCTL[4] = 0x00;
-	hw->GCTL[5] = 0x40;
-	hw->GCTL[6] = 0x05;
-	hw->GCTL[7] = 0x0F;
-	hw->GCTL[8] = 0xFF;
-
-	/* Whole ATTR is ignored in PowerGraphics mode */
-	for (i = 0; i < 16; i++)
-		hw->ATTR[i] = i;
-	hw->ATTR[16] = 0x41;
-	hw->ATTR[17] = 0xFF;
-	hw->ATTR[18] = 0x0F;
-	hw->ATTR[19] = 0x00;
-	hw->ATTR[20] = 0x00;
-
-	hd = m->HDisplay >> 3;
-	hs = m->HSyncStart >> 3;
-	he = m->HSyncEnd >> 3;
-	ht = m->HTotal >> 3;
-	/* standard timmings are in 8pixels, but for interleaved we cannot */
-	/* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
-	/* using 16 or more pixels per unit can save us */
-	divider = minfo->curr.final_bppShift;
-	while (divider & 3) {
-		hd >>= 1;
-		hs >>= 1;
-		he >>= 1;
-		ht >>= 1;
-		divider <<= 1;
-	}
-	divider = divider / 4;
-	/* divider can be from 1 to 8 */
-	while (divider > 8) {
-		hd <<= 1;
-		hs <<= 1;
-		he <<= 1;
-		ht <<= 1;
-		divider >>= 1;
-	}
-	hd = hd - 1;
-	hs = hs - 1;
-	he = he - 1;
-	ht = ht - 1;
-	vd = m->VDisplay - 1;
-	vs = m->VSyncStart - 1;
-	ve = m->VSyncEnd - 1;
-	vt = m->VTotal - 2;
-	lc = vd;
-	/* G200 cannot work with (ht & 7) == 6 */
-	if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
-		ht++;
-	hbe = ht;
-	wd = minfo->fbcon.var.xres_virtual * minfo->curr.final_bppShift / 64;
-
-	hw->CRTCEXT[0] = 0;
-	hw->CRTCEXT[5] = 0;
-	if (m->interlaced) {
-		hw->CRTCEXT[0] = 0x80;
-		hw->CRTCEXT[5] = (hs + he - ht) >> 1;
-		if (!m->dblscan)
-			wd <<= 1;
-		vt &= ~1;
-	}
-	hw->CRTCEXT[0] |=  (wd & 0x300) >> 4;
-	hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
-			  ((hd      & 0x100) >> 7) | /* blanking */
-			  ((hs      & 0x100) >> 6) | /* sync start */
-			   (hbe     & 0x040);	 /* end hor. blanking */
-	/* FIXME: Enable vidrst only on G400, and only if TV-out is used */
-	if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1)
-		hw->CRTCEXT[1] |= 0x88;		/* enable horizontal and vertical vidrst */
-	hw->CRTCEXT[2] =  ((vt & 0xC00) >> 10) |
-			  ((vd & 0x400) >>  8) |	/* disp end */
-			  ((vd & 0xC00) >>  7) |	/* vblanking start */
-			  ((vs & 0xC00) >>  5) |
-			  ((lc & 0x400) >>  3);
-	hw->CRTCEXT[3] = (divider - 1) | 0x80;
-	hw->CRTCEXT[4] = 0;
-
-	hw->CRTC[0] = ht-4;
-	hw->CRTC[1] = hd;
-	hw->CRTC[2] = hd;
-	hw->CRTC[3] = (hbe & 0x1F) | 0x80;
-	hw->CRTC[4] = hs;
-	hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
-	hw->CRTC[6] = vt & 0xFF;
-	hw->CRTC[7] = ((vt & 0x100) >> 8) |
-		      ((vd & 0x100) >> 7) |
-		      ((vs & 0x100) >> 6) |
-		      ((vd & 0x100) >> 5) |
-		      ((lc & 0x100) >> 4) |
-		      ((vt & 0x200) >> 4) |
-		      ((vd & 0x200) >> 3) |
-		      ((vs & 0x200) >> 2);
-	hw->CRTC[8] = 0x00;
-	hw->CRTC[9] = ((vd & 0x200) >> 4) |
-		      ((lc & 0x200) >> 3);
-	if (m->dblscan && !m->interlaced)
-		hw->CRTC[9] |= 0x80;
-	for (i = 10; i < 16; i++)
-		hw->CRTC[i] = 0x00;
-	hw->CRTC[16] = vs /* & 0xFF */;
-	hw->CRTC[17] = (ve & 0x0F) | 0x20;
-	hw->CRTC[18] = vd /* & 0xFF */;
-	hw->CRTC[19] = wd /* & 0xFF */;
-	hw->CRTC[20] = 0x00;
-	hw->CRTC[21] = vd /* & 0xFF */;
-	hw->CRTC[22] = (vt + 1) /* & 0xFF */;
-	hw->CRTC[23] = 0xC3;
-	hw->CRTC[24] = lc;
-	return 0;
-};
-
-void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo)
-{
-	int i;
-	struct matrox_hw_state * const hw = &minfo->hw;
-	CRITFLAGS
-
-	DBG(__func__)
-
-	dprintk(KERN_INFO "MiscOutReg: %02X\n", hw->MiscOutReg);
-	dprintk(KERN_INFO "SEQ regs:   ");
-	for (i = 0; i < 5; i++)
-		dprintk("%02X:", hw->SEQ[i]);
-	dprintk("\n");
-	dprintk(KERN_INFO "GDC regs:   ");
-	for (i = 0; i < 9; i++)
-		dprintk("%02X:", hw->GCTL[i]);
-	dprintk("\n");
-	dprintk(KERN_INFO "CRTC regs: ");
-	for (i = 0; i < 25; i++)
-		dprintk("%02X:", hw->CRTC[i]);
-	dprintk("\n");
-	dprintk(KERN_INFO "ATTR regs: ");
-	for (i = 0; i < 21; i++)
-		dprintk("%02X:", hw->ATTR[i]);
-	dprintk("\n");
-
-	CRITBEGIN
-
-	mga_inb(M_ATTR_RESET);
-	mga_outb(M_ATTR_INDEX, 0);
-	mga_outb(M_MISC_REG, hw->MiscOutReg);
-	for (i = 1; i < 5; i++)
-		mga_setr(M_SEQ_INDEX, i, hw->SEQ[i]);
-	mga_setr(M_CRTC_INDEX, 17, hw->CRTC[17] & 0x7F);
-	for (i = 0; i < 25; i++)
-		mga_setr(M_CRTC_INDEX, i, hw->CRTC[i]);
-	for (i = 0; i < 9; i++)
-		mga_setr(M_GRAPHICS_INDEX, i, hw->GCTL[i]);
-	for (i = 0; i < 21; i++) {
-		mga_inb(M_ATTR_RESET);
-		mga_outb(M_ATTR_INDEX, i);
-		mga_outb(M_ATTR_INDEX, hw->ATTR[i]);
-	}
-	mga_outb(M_PALETTE_MASK, 0xFF);
-	mga_outb(M_DAC_REG, 0x00);
-	for (i = 0; i < 768; i++)
-		mga_outb(M_DAC_VAL, hw->DACpal[i]);
-	mga_inb(M_ATTR_RESET);
-	mga_outb(M_ATTR_INDEX, 0x20);
-
-	CRITEND
-}
-
-static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) {
-	unsigned int b0 = readb(pins);
-	
-	if (b0 == 0x2E && readb(pins+1) == 0x41) {
-		unsigned int pins_len = readb(pins+2);
-		unsigned int i;
-		unsigned char cksum;
-		unsigned char* dst = bd->pins;
-
-		if (pins_len < 3 || pins_len > 128) {
-			return;
-		}
-		*dst++ = 0x2E;
-		*dst++ = 0x41;
-		*dst++ = pins_len;
-		cksum = 0x2E + 0x41 + pins_len;
-		for (i = 3; i < pins_len; i++) {
-			cksum += *dst++ = readb(pins+i);
-		}
-		if (cksum) {
-			return;
-		}
-		bd->pins_len = pins_len;
-	} else if (b0 == 0x40 && readb(pins+1) == 0x00) {
-		unsigned int i;
-		unsigned char* dst = bd->pins;
-
-		*dst++ = 0x40;
-		*dst++ = 0;
-		for (i = 2; i < 0x40; i++) {
-			*dst++ = readb(pins+i);
-		}
-		bd->pins_len = 0x40;
-	}
-}
-
-static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) {
-	unsigned int pcir_offset;
-	
-	pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
-	if (pcir_offset >= 26 && pcir_offset < 0xFFE0 &&
-	    readb(vbios + pcir_offset    ) == 'P' &&
-	    readb(vbios + pcir_offset + 1) == 'C' &&
-	    readb(vbios + pcir_offset + 2) == 'I' &&
-	    readb(vbios + pcir_offset + 3) == 'R') {
-		unsigned char h;
-
-		h = readb(vbios + pcir_offset + 0x12);
-		bd->version.vMaj = (h >> 4) & 0xF;
-		bd->version.vMin = h & 0xF;
-		bd->version.vRev = readb(vbios + pcir_offset + 0x13);
-	} else {
-		unsigned char h;
-
-		h = readb(vbios + 5);
-		bd->version.vMaj = (h >> 4) & 0xF;
-		bd->version.vMin = h & 0xF;
-		bd->version.vRev = 0;
-	}
-}
-
-static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) {
-	unsigned char b;
-	
-	b = readb(vbios + 0x7FF1);
-	if (b == 0xFF) {
-		b = 0;
-	}
-	bd->output.state = b;
-}
-
-static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) {
-	unsigned int i;
-	
-	/* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
-	bd->output.tvout = 0;
-	if (readb(vbios + 0x1D) != 'I' ||
-	    readb(vbios + 0x1E) != 'B' ||
-	    readb(vbios + 0x1F) != 'M' ||
-	    readb(vbios + 0x20) != ' ') {
-	    	return;
-	}
-	for (i = 0x2D; i < 0x2D + 128; i++) {
-		unsigned char b = readb(vbios + i);
-		
-		if (b == '(' && readb(vbios + i + 1) == 'V') {
-			if (readb(vbios + i + 6) == 'T' &&
-			    readb(vbios + i + 7) == 'V' &&
-			    readb(vbios + i + 8) == 'O') {
-				bd->output.tvout = 1;
-			}
-			return;
-		}
-		if (b == 0)
-			break;
-	}
-}
-
-static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
-	unsigned int pins_offset;
-	
-	if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
-		return;
-	}
-	bd->bios_valid = 1;
-	get_bios_version(vbios, bd);
-	get_bios_output(vbios, bd);
-	get_bios_tvout(vbios, bd);
-#if defined(__powerpc__)
-	/* On PowerPC cards, the PInS offset isn't stored at the end of the
-	 * BIOS image.  Instead, you must search the entire BIOS image for
-	 * the magic PInS signature.
-	 *
-	 * This actually applies to all OpenFirmware base cards.  Since these
-	 * cards could be put in a MIPS or SPARC system, should the condition
-	 * be something different?
-	 */
-	for ( pins_offset = 0 ; pins_offset <= 0xFF80 ; pins_offset++ ) {
-		unsigned char header[3];
-
-		header[0] = readb(vbios + pins_offset);
-		header[1] = readb(vbios + pins_offset + 1);
-		header[2] = readb(vbios + pins_offset + 2);
-		if ( (header[0] == 0x2E) && (header[1] == 0x41)
-		     && ((header[2] == 0x40) || (header[2] == 0x80)) ) {
-			printk(KERN_INFO "PInS data found at offset %u\n",
-			       pins_offset);
-			get_pins(vbios + pins_offset, bd);
-			break;
-		}
-	}
-#else
-	pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
-	if (pins_offset <= 0xFF80) {
-		get_pins(vbios + pins_offset, bd);
-	}
-#endif
-}
-
-static int parse_pins1(struct matrox_fb_info *minfo,
-		       const struct matrox_bios *bd)
-{
-	unsigned int maxdac;
-
-	switch (bd->pins[22]) {
-		case 0:		maxdac = 175000; break;
-		case 1:		maxdac = 220000; break;
-		default:	maxdac = 240000; break;
-	}
-	if (get_unaligned_le16(bd->pins + 24)) {
-		maxdac = get_unaligned_le16(bd->pins + 24) * 10;
-	}
-	minfo->limits.pixel.vcomax = maxdac;
-	minfo->values.pll.system = get_unaligned_le16(bd->pins + 28) ?
-		get_unaligned_le16(bd->pins + 28) * 10 : 50000;
-	/* ignore 4MB, 8MB, module clocks */
-	minfo->features.pll.ref_freq = 14318;
-	minfo->values.reg.mctlwtst	= 0x00030101;
-	return 0;
-}
-
-static void default_pins1(struct matrox_fb_info *minfo)
-{
-	/* Millennium */
-	minfo->limits.pixel.vcomax	= 220000;
-	minfo->values.pll.system	=  50000;
-	minfo->features.pll.ref_freq	=  14318;
-	minfo->values.reg.mctlwtst	= 0x00030101;
-}
-
-static int parse_pins2(struct matrox_fb_info *minfo,
-		       const struct matrox_bios *bd)
-{
-	minfo->limits.pixel.vcomax	=
-	minfo->limits.system.vcomax	= (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000);
-	minfo->values.reg.mctlwtst	= ((bd->pins[51] & 0x01) ? 0x00000001 : 0) |
-					  ((bd->pins[51] & 0x02) ? 0x00000100 : 0) |
-					  ((bd->pins[51] & 0x04) ? 0x00010000 : 0) |
-					  ((bd->pins[51] & 0x08) ? 0x00020000 : 0);
-	minfo->values.pll.system	= (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000);
-	minfo->features.pll.ref_freq	= 14318;
-	return 0;
-}
-
-static void default_pins2(struct matrox_fb_info *minfo)
-{
-	/* Millennium II, Mystique */
-	minfo->limits.pixel.vcomax	=
-	minfo->limits.system.vcomax	= 230000;
-	minfo->values.reg.mctlwtst	= 0x00030101;
-	minfo->values.pll.system	=  50000;
-	minfo->features.pll.ref_freq	=  14318;
-}
-
-static int parse_pins3(struct matrox_fb_info *minfo,
-		       const struct matrox_bios *bd)
-{
-	minfo->limits.pixel.vcomax	=
-	minfo->limits.system.vcomax	= (bd->pins[36] == 0xFF) ? 230000			: ((bd->pins[36] + 100) * 1000);
-	minfo->values.reg.mctlwtst	= get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ?
-		0x01250A21 : get_unaligned_le32(bd->pins + 48);
-	/* memory config */
-	minfo->values.reg.memrdbk	= ((bd->pins[57] << 21) & 0x1E000000) |
-					  ((bd->pins[57] << 22) & 0x00C00000) |
-					  ((bd->pins[56] <<  1) & 0x000001E0) |
-					  ( bd->pins[56]        & 0x0000000F);
-	minfo->values.reg.opt		= (bd->pins[54] & 7) << 10;
-	minfo->values.reg.opt2		= bd->pins[58] << 12;
-	minfo->features.pll.ref_freq	= (bd->pins[52] & 0x20) ? 14318 : 27000;
-	return 0;
-}
-
-static void default_pins3(struct matrox_fb_info *minfo)
-{
-	/* G100, G200 */
-	minfo->limits.pixel.vcomax	=
-	minfo->limits.system.vcomax	= 230000;
-	minfo->values.reg.mctlwtst	= 0x01250A21;
-	minfo->values.reg.memrdbk	= 0x00000000;
-	minfo->values.reg.opt		= 0x00000C00;
-	minfo->values.reg.opt2		= 0x00000000;
-	minfo->features.pll.ref_freq	=  27000;
-}
-
-static int parse_pins4(struct matrox_fb_info *minfo,
-		       const struct matrox_bios *bd)
-{
-	minfo->limits.pixel.vcomax	= (bd->pins[ 39] == 0xFF) ? 230000			: bd->pins[ 39] * 4000;
-	minfo->limits.system.vcomax	= (bd->pins[ 38] == 0xFF) ? minfo->limits.pixel.vcomax	: bd->pins[ 38] * 4000;
-	minfo->values.reg.mctlwtst	= get_unaligned_le32(bd->pins + 71);
-	minfo->values.reg.memrdbk	= ((bd->pins[87] << 21) & 0x1E000000) |
-					  ((bd->pins[87] << 22) & 0x00C00000) |
-					  ((bd->pins[86] <<  1) & 0x000001E0) |
-					  ( bd->pins[86]        & 0x0000000F);
-	minfo->values.reg.opt		= ((bd->pins[53] << 15) & 0x00400000) |
-					  ((bd->pins[53] << 22) & 0x10000000) |
-					  ((bd->pins[53] <<  7) & 0x00001C00);
-	minfo->values.reg.opt3		= get_unaligned_le32(bd->pins + 67);
-	minfo->values.pll.system	= (bd->pins[ 65] == 0xFF) ? 200000 			: bd->pins[ 65] * 4000;
-	minfo->features.pll.ref_freq	= (bd->pins[ 92] & 0x01) ? 14318 : 27000;
-	return 0;
-}
-
-static void default_pins4(struct matrox_fb_info *minfo)
-{
-	/* G400 */
-	minfo->limits.pixel.vcomax	=
-	minfo->limits.system.vcomax	= 252000;
-	minfo->values.reg.mctlwtst	= 0x04A450A1;
-	minfo->values.reg.memrdbk	= 0x000000E7;
-	minfo->values.reg.opt		= 0x10000400;
-	minfo->values.reg.opt3		= 0x0190A419;
-	minfo->values.pll.system	= 200000;
-	minfo->features.pll.ref_freq	= 27000;
-}
-
-static int parse_pins5(struct matrox_fb_info *minfo,
-		       const struct matrox_bios *bd)
-{
-	unsigned int mult;
-	
-	mult = bd->pins[4]?8000:6000;
-	
-	minfo->limits.pixel.vcomax	= (bd->pins[ 38] == 0xFF) ? 600000			: bd->pins[ 38] * mult;
-	minfo->limits.system.vcomax	= (bd->pins[ 36] == 0xFF) ? minfo->limits.pixel.vcomax	: bd->pins[ 36] * mult;
-	minfo->limits.video.vcomax	= (bd->pins[ 37] == 0xFF) ? minfo->limits.system.vcomax	: bd->pins[ 37] * mult;
-	minfo->limits.pixel.vcomin	= (bd->pins[123] == 0xFF) ? 256000			: bd->pins[123] * mult;
-	minfo->limits.system.vcomin	= (bd->pins[121] == 0xFF) ? minfo->limits.pixel.vcomin	: bd->pins[121] * mult;
-	minfo->limits.video.vcomin	= (bd->pins[122] == 0xFF) ? minfo->limits.system.vcomin	: bd->pins[122] * mult;
-	minfo->values.pll.system	=
-	minfo->values.pll.video		= (bd->pins[ 92] == 0xFF) ? 284000			: bd->pins[ 92] * 4000;
-	minfo->values.reg.opt		= get_unaligned_le32(bd->pins + 48);
-	minfo->values.reg.opt2		= get_unaligned_le32(bd->pins + 52);
-	minfo->values.reg.opt3		= get_unaligned_le32(bd->pins + 94);
-	minfo->values.reg.mctlwtst	= get_unaligned_le32(bd->pins + 98);
-	minfo->values.reg.memmisc	= get_unaligned_le32(bd->pins + 102);
-	minfo->values.reg.memrdbk	= get_unaligned_le32(bd->pins + 106);
-	minfo->features.pll.ref_freq	= (bd->pins[110] & 0x01) ? 14318 : 27000;
-	minfo->values.memory.ddr	= (bd->pins[114] & 0x60) == 0x20;
-	minfo->values.memory.dll	= (bd->pins[115] & 0x02) != 0;
-	minfo->values.memory.emrswen	= (bd->pins[115] & 0x01) != 0;
-	minfo->values.reg.maccess	= minfo->values.memory.emrswen ? 0x00004000 : 0x00000000;
-	if (bd->pins[115] & 4) {
-		minfo->values.reg.mctlwtst_core = minfo->values.reg.mctlwtst;
-	} else {
-		u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 };
-		minfo->values.reg.mctlwtst_core = (minfo->values.reg.mctlwtst & ~7) |
-						  wtst_xlat[minfo->values.reg.mctlwtst & 7];
-	}
-	minfo->max_pixel_clock_panellink = bd->pins[47] * 4000;
-	return 0;
-}
-
-static void default_pins5(struct matrox_fb_info *minfo)
-{
-	/* Mine 16MB G450 with SDRAM DDR */
-	minfo->limits.pixel.vcomax	=
-	minfo->limits.system.vcomax	=
-	minfo->limits.video.vcomax	= 600000;
-	minfo->limits.pixel.vcomin	=
-	minfo->limits.system.vcomin	=
-	minfo->limits.video.vcomin	= 256000;
-	minfo->values.pll.system	=
-	minfo->values.pll.video		= 284000;
-	minfo->values.reg.opt		= 0x404A1160;
-	minfo->values.reg.opt2		= 0x0000AC00;
-	minfo->values.reg.opt3		= 0x0090A409;
-	minfo->values.reg.mctlwtst_core	=
-	minfo->values.reg.mctlwtst	= 0x0C81462B;
-	minfo->values.reg.memmisc	= 0x80000004;
-	minfo->values.reg.memrdbk	= 0x01001103;
-	minfo->features.pll.ref_freq	= 27000;
-	minfo->values.memory.ddr	= 1;
-	minfo->values.memory.dll	= 1;
-	minfo->values.memory.emrswen	= 1;
-	minfo->values.reg.maccess	= 0x00004000;
-}
-
-static int matroxfb_set_limits(struct matrox_fb_info *minfo,
-			       const struct matrox_bios *bd)
-{
-	unsigned int pins_version;
-	static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 };
-
-	switch (minfo->chip) {
-		case MGA_2064:	default_pins1(minfo); break;
-		case MGA_2164:
-		case MGA_1064:
-		case MGA_1164:	default_pins2(minfo); break;
-		case MGA_G100:
-		case MGA_G200:	default_pins3(minfo); break;
-		case MGA_G400:	default_pins4(minfo); break;
-		case MGA_G450:
-		case MGA_G550:	default_pins5(minfo); break;
-	}
-	if (!bd->bios_valid) {
-		printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n");
-		return -1;
-	}
-	if (bd->pins_len < 64) {
-		printk(KERN_INFO "matroxfb: BIOS on your Matrox device does not contain powerup info\n");
-		return -1;
-	}
-	if (bd->pins[0] == 0x2E && bd->pins[1] == 0x41) {
-		pins_version = bd->pins[5];
-		if (pins_version < 2 || pins_version > 5) {
-			printk(KERN_INFO "matroxfb: Unknown version (%u) of powerup info\n", pins_version);
-			return -1;
-		}
-	} else {
-		pins_version = 1;
-	}
-	if (bd->pins_len != pinslen[pins_version - 1]) {
-		printk(KERN_INFO "matroxfb: Invalid powerup info\n");
-		return -1;
-	}
-	switch (pins_version) {
-		case 1:
-			return parse_pins1(minfo, bd);
-		case 2:
-			return parse_pins2(minfo, bd);
-		case 3:
-			return parse_pins3(minfo, bd);
-		case 4:
-			return parse_pins4(minfo, bd);
-		case 5:
-			return parse_pins5(minfo, bd);
-		default:
-			printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version);
-			return -1;
-	}
-}
-
-void matroxfb_read_pins(struct matrox_fb_info *minfo)
-{
-	u32 opt;
-	u32 biosbase;
-	u32 fbbase;
-	struct pci_dev *pdev = minfo->pcidev;
-	
-	memset(&minfo->bios, 0, sizeof(minfo->bios));
-	pci_read_config_dword(pdev, PCI_OPTION_REG, &opt);
-	pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM);
-	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase);
-	pci_read_config_dword(pdev, minfo->devflags.fbResource, &fbbase);
-	pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
-	parse_bios(vaddr_va(minfo->video.vbase), &minfo->bios);
-	pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase);
-	pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
-#ifdef CONFIG_X86
-	if (!minfo->bios.bios_valid) {
-		unsigned char __iomem* b;
-
-		b = ioremap(0x000C0000, 65536);
-		if (!b) {
-			printk(KERN_INFO "matroxfb: Unable to map legacy BIOS\n");
-		} else {
-			unsigned int ven = readb(b+0x64+0) | (readb(b+0x64+1) << 8);
-			unsigned int dev = readb(b+0x64+2) | (readb(b+0x64+3) << 8);
-			
-			if (ven != pdev->vendor || dev != pdev->device) {
-				printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n",
-					ven, dev, pdev->vendor, pdev->device);
-			} else {
-				parse_bios(b, &minfo->bios);
-			}
-			iounmap(b);
-		}
-	}
-#endif
-	matroxfb_set_limits(minfo, &minfo->bios);
-	printk(KERN_INFO "PInS memtype = %u\n",
-	       (minfo->values.reg.opt & 0x1C00) >> 10);
-}
-
-EXPORT_SYMBOL(matroxfb_DAC_in);
-EXPORT_SYMBOL(matroxfb_DAC_out);
-EXPORT_SYMBOL(matroxfb_var2my);
-EXPORT_SYMBOL(matroxfb_PLL_calcclock);
-EXPORT_SYMBOL(matroxfb_vgaHWinit);		/* DAC1064, Ti3026 */
-EXPORT_SYMBOL(matroxfb_vgaHWrestore);		/* DAC1064, Ti3026 */
-EXPORT_SYMBOL(matroxfb_read_pins);
-
-MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_misc.h b/drivers/video/matrox/matroxfb_misc.h
deleted file mode 100644
index 351c823f1f74..000000000000
--- a/drivers/video/matrox/matroxfb_misc.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __MATROXFB_MISC_H__
-#define __MATROXFB_MISC_H__
-
-#include "matroxfb_base.h"
-
-/* also for modules */
-int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
-	unsigned int* in, unsigned int* feed, unsigned int* post);
-static inline int PLL_calcclock(const struct matrox_fb_info *minfo,
-				unsigned int freq, unsigned int fmax,
-				unsigned int *in, unsigned int *feed,
-				unsigned int *post)
-{
-	return matroxfb_PLL_calcclock(&minfo->features.pll, freq, fmax, in, feed, post);
-}
-
-int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming* m);
-void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo);
-void matroxfb_read_pins(struct matrox_fb_info *minfo);
-
-#endif	/* __MATROXFB_MISC_H__ */
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
deleted file mode 100644
index 5cf52d3c8e75..000000000000
--- a/drivers/video/maxinefb.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *      linux/drivers/video/maxinefb.c
- *
- *	DECstation 5000/xx onboard framebuffer support ... derived from:
- *	"HP300 Topcat framebuffer support (derived from macfb of all things)
- *	Phil Blundell <philb@gnu.org> 1998", the original code can be
- *      found in the file hpfb.c in the same directory.
- *
- *      DECstation related code Copyright (C) 1999,2000,2001 by
- *      Michael Engel <engel@unix-ag.org> and
- *      Karsten Merker <merker@linuxtag.org>.
- *      This file is subject to the terms and conditions of the GNU General
- *      Public License.  See the file COPYING in the main directory of this
- *      archive for more details.
- *
- */
-
-/*
- * Changes:
- * 2001/01/27 removed debugging and testing code, fixed fb_ops
- *            initialization which had caused a crash before,
- *            general cleanup, first official release (KM)
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <video/maxinefb.h>
-
-/* bootinfo.h defines the machine type values, needed when checking */
-/* whether are really running on a maxine, KM                       */
-#include <asm/bootinfo.h>
-
-static struct fb_info fb_info;
-
-static struct fb_var_screeninfo maxinefb_defined = {
-	.xres =		1024,
-	.yres =		768,
-	.xres_virtual =	1024,
-	.yres_virtual =	768,
-	.bits_per_pixel =8,
-	.activate =	FB_ACTIVATE_NOW,
-	.height =	-1,
-	.width =	-1,
-	.vmode =	FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo maxinefb_fix = {
-	.id =		"Maxine",
-	.smem_len =	(1024*768),
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.line_length =	1024,
-};
-
-/* Handle the funny Inmos RamDAC/video controller ... */
-
-void maxinefb_ims332_write_register(int regno, register unsigned int val)
-{
-	register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
-	unsigned char *wptr;
-
-	wptr = regs + 0xa0000 + (regno << 4);
-	*((volatile unsigned int *) (regs)) = (val >> 8) & 0xff00;
-	*((volatile unsigned short *) (wptr)) = val;
-}
-
-unsigned int maxinefb_ims332_read_register(int regno)
-{
-	register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
-	unsigned char *rptr;
-	register unsigned int j, k;
-
-	rptr = regs + 0x80000 + (regno << 4);
-	j = *((volatile unsigned short *) rptr);
-	k = *((volatile unsigned short *) regs);
-
-	return (j & 0xffff) | ((k & 0xff00) << 8);
-}
-
-/* Set the palette */
-static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			      unsigned blue, unsigned transp, struct fb_info *info)
-{
-	/* value to be written into the palette reg. */
-	unsigned long hw_colorvalue = 0;
-
-	if (regno > 255)
-		return 1;
-
-	red   >>= 8;    /* The cmap fields are 16 bits    */
-	green >>= 8;    /* wide, but the harware colormap */
-	blue  >>= 8;    /* registers are only 8 bits wide */
-
-	hw_colorvalue = (blue << 16) + (green << 8) + (red);
-
-	maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE + regno,
-				       hw_colorvalue);
-	return 0;
-}
-
-static struct fb_ops maxinefb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= maxinefb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-int __init maxinefb_init(void)
-{
-	unsigned long fboff;
-	unsigned long fb_start;
-	int i;
-
-	if (fb_get_options("maxinefb", NULL))
-		return -ENODEV;
-
-	/* Validate we're on the proper machine type */
-	if (mips_machtype != MACH_DS5000_XX) {
-		return -EINVAL;
-	}
-
-	printk(KERN_INFO "Maxinefb: Personal DECstation detected\n");
-	printk(KERN_INFO "Maxinefb: initializing onboard framebuffer\n");
-
-	/* Framebuffer display memory base address */
-	fb_start = DS5000_xx_ONBOARD_FBMEM_START;
-
-	/* Clear screen */
-	for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++)
-		*(volatile unsigned char *)fboff = 0x0;
-
-	maxinefb_fix.smem_start = fb_start;
-	
-	/* erase hardware cursor */
-	for (i = 0; i < 512; i++) {
-		maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i,
-					       0);
-		/*
-		   if (i&0x8 == 0)
-		   maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0x0f);
-		   else
-		   maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0xf0);
-		 */
-	}
-
-	fb_info.fbops = &maxinefb_ops;
-	fb_info.screen_base = (char *)maxinefb_fix.smem_start;
-	fb_info.var = maxinefb_defined;
-	fb_info.fix = maxinefb_fix;
-	fb_info.flags = FBINFO_DEFAULT;
-
-	fb_alloc_cmap(&fb_info.cmap, 256, 0);
-
-	if (register_framebuffer(&fb_info) < 0)
-		return 1;
-	return 0;
-}
-
-static void __exit maxinefb_exit(void)
-{
-	unregister_framebuffer(&fb_info);
-}
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-#endif
-module_init(maxinefb_init);
-module_exit(maxinefb_exit);
-
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile
deleted file mode 100644
index 5707ed0e31a7..000000000000
--- a/drivers/video/mb862xx/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the MB862xx framebuffer driver
-#
-
-obj-$(CONFIG_FB_MB862XX) += mb862xxfb.o
-
-mb862xxfb-y := mb862xxfbdrv.o mb862xxfb_accel.o
-mb862xxfb-$(CONFIG_FB_MB862XX_I2C) += mb862xx-i2c.o
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
deleted file mode 100644
index c87e17afb3e2..000000000000
--- a/drivers/video/mb862xx/mb862xx-i2c.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Coral-P(A)/Lime I2C adapter driver
- *
- * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/fb.h>
-#include <linux/i2c.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/export.h>
-
-#include "mb862xxfb.h"
-#include "mb862xx_reg.h"
-
-static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
-{
-	struct mb862xxfb_par *par = adap->algo_data;
-	u32 reg;
-
-	do {
-		udelay(10);
-		reg = inreg(i2c, GC_I2C_BCR);
-		if (reg & (I2C_INT | I2C_BER))
-			break;
-	} while (1);
-
-	return (reg & I2C_BER) ? 0 : 1;
-}
-
-static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr)
-{
-	struct mb862xxfb_par *par = adap->algo_data;
-
-	outreg(i2c, GC_I2C_DAR, addr);
-	outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE);
-	outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START);
-	if (!mb862xx_i2c_wait_event(adap))
-		return -EIO;
-	par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
-	return par->i2c_rs;
-}
-
-static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte)
-{
-	struct mb862xxfb_par *par = adap->algo_data;
-
-	outreg(i2c, GC_I2C_DAR, byte);
-	outreg(i2c, GC_I2C_BCR, I2C_START);
-	if (!mb862xx_i2c_wait_event(adap))
-		return -EIO;
-	return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
-}
-
-static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last)
-{
-	struct mb862xxfb_par *par = adap->algo_data;
-
-	outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK));
-	if (!mb862xx_i2c_wait_event(adap))
-		return 0;
-	*byte = inreg(i2c, GC_I2C_DAR);
-	return 1;
-}
-
-static void mb862xx_i2c_stop(struct i2c_adapter *adap)
-{
-	struct mb862xxfb_par *par = adap->algo_data;
-
-	outreg(i2c, GC_I2C_BCR, I2C_STOP);
-	outreg(i2c, GC_I2C_CCR, I2C_DISABLE);
-	par->i2c_rs = 0;
-}
-
-static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m)
-{
-	int i, ret = 0;
-	int last = m->len - 1;
-
-	for (i = 0; i < m->len; i++) {
-		if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i == last)) {
-			ret = -EIO;
-			break;
-		}
-	}
-	return ret;
-}
-
-static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m)
-{
-	int i, ret = 0;
-
-	for (i = 0; i < m->len; i++) {
-		if (!mb862xx_i2c_write_byte(adap, m->buf[i])) {
-			ret = -EIO;
-			break;
-		}
-	}
-	return ret;
-}
-
-static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
-			int num)
-{
-	struct mb862xxfb_par *par = adap->algo_data;
-	struct i2c_msg *m;
-	int addr;
-	int i = 0, err = 0;
-
-	dev_dbg(par->dev, "%s: %d msgs\n", __func__, num);
-
-	for (i = 0; i < num; i++) {
-		m = &msgs[i];
-		if (!m->len) {
-			dev_dbg(par->dev, "%s: null msgs\n", __func__);
-			continue;
-		}
-		addr = m->addr;
-		if (m->flags & I2C_M_RD)
-			addr |= 1;
-
-		err = mb862xx_i2c_do_address(adap, addr);
-		if (err < 0)
-			break;
-		if (m->flags & I2C_M_RD)
-			err = mb862xx_i2c_read(adap, m);
-		else
-			err = mb862xx_i2c_write(adap, m);
-	}
-
-	if (i)
-		mb862xx_i2c_stop(adap);
-
-	return (err < 0) ? err : i;
-}
-
-static u32 mb862xx_func(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_SMBUS_BYTE_DATA;
-}
-
-static const struct i2c_algorithm mb862xx_algo = {
-	.master_xfer	= mb862xx_xfer,
-	.functionality	= mb862xx_func,
-};
-
-static struct i2c_adapter mb862xx_i2c_adapter = {
-	.name		= "MB862xx I2C adapter",
-	.algo		= &mb862xx_algo,
-	.owner		= THIS_MODULE,
-};
-
-int mb862xx_i2c_init(struct mb862xxfb_par *par)
-{
-	int ret;
-
-	mb862xx_i2c_adapter.algo_data = par;
-	par->adap = &mb862xx_i2c_adapter;
-
-	ret = i2c_add_adapter(par->adap);
-	if (ret < 0) {
-		dev_err(par->dev, "failed to add %s\n",
-			mb862xx_i2c_adapter.name);
-	}
-	return ret;
-}
-
-void mb862xx_i2c_exit(struct mb862xxfb_par *par)
-{
-	if (par->adap) {
-		i2c_del_adapter(par->adap);
-		par->adap = NULL;
-	}
-}
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h
deleted file mode 100644
index 9df48b8edc94..000000000000
--- a/drivers/video/mb862xx/mb862xx_reg.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Fujitsu MB862xx Graphics Controller Registers/Bits
- */
-
-#ifndef _MB862XX_REG_H
-#define _MB862XX_REG_H
-
-#define MB862XX_MMIO_BASE	0x01fc0000
-#define MB862XX_MMIO_HIGH_BASE	0x03fc0000
-#define MB862XX_I2C_BASE	0x0000c000
-#define MB862XX_DISP_BASE	0x00010000
-#define MB862XX_CAP_BASE	0x00018000
-#define MB862XX_DRAW_BASE	0x00030000
-#define MB862XX_GEO_BASE	0x00038000
-#define MB862XX_PIO_BASE	0x00038000
-#define MB862XX_MMIO_SIZE	0x40000
-
-/* Host interface/pio registers */
-#define GC_IST			0x00000020
-#define GC_IMASK		0x00000024
-#define GC_SRST			0x0000002c
-#define GC_CCF			0x00000038
-#define GC_RSW			0x0000005c
-#define GC_CID			0x000000f0
-#define GC_REVISION		0x00000084
-
-#define GC_CCF_CGE_100		0x00000000
-#define GC_CCF_CGE_133		0x00040000
-#define GC_CCF_CGE_166		0x00080000
-#define GC_CCF_COT_100		0x00000000
-#define GC_CCF_COT_133		0x00010000
-#define GC_CID_CNAME_MSK	0x0000ff00
-#define GC_CID_VERSION_MSK	0x000000ff
-
-/* define enabled interrupts hereby */
-#define GC_INT_EN		0x00000000
-
-/* Memory interface mode register */
-#define GC_MMR			0x0000fffc
-
-/* Display Controller registers */
-#define GC_DCM0			0x00000000
-#define GC_HTP			0x00000004
-#define GC_HDB_HDP		0x00000008
-#define GC_VSW_HSW_HSP		0x0000000c
-#define GC_VTR			0x00000010
-#define GC_VDP_VSP		0x00000014
-#define GC_WY_WX		0x00000018
-#define GC_WH_WW		0x0000001c
-#define GC_L0M			0x00000020
-#define GC_L0OA0		0x00000024
-#define GC_L0DA0		0x00000028
-#define GC_L0DY_L0DX		0x0000002c
-#define GC_L1M			0x00000030
-#define GC_L1DA			0x00000034
-#define GC_DCM1			0x00000100
-#define GC_L0EM			0x00000110
-#define GC_L0WY_L0WX		0x00000114
-#define GC_L0WH_L0WW		0x00000118
-#define GC_L1EM			0x00000120
-#define GC_L1WY_L1WX		0x00000124
-#define GC_L1WH_L1WW		0x00000128
-#define GC_DLS			0x00000180
-#define GC_DCM2			0x00000104
-#define GC_DCM3			0x00000108
-#define GC_CPM_CUTC		0x000000a0
-#define GC_CUOA0		0x000000a4
-#define GC_CUY0_CUX0		0x000000a8
-#define GC_CUOA1		0x000000ac
-#define GC_CUY1_CUX1		0x000000b0
-#define GC_L0PAL0		0x00000400
-
-#define GC_CPM_CEN0		0x00100000
-#define GC_CPM_CEN1		0x00200000
-#define GC_DCM1_DEN		0x80000000
-#define GC_DCM1_L1E		0x00020000
-#define GC_L1M_16		0x80000000
-#define GC_L1M_YC		0x40000000
-#define GC_L1M_CS		0x20000000
-
-#define GC_DCM01_ESY		0x00000004
-#define GC_DCM01_SC		0x00003f00
-#define GC_DCM01_RESV		0x00004000
-#define GC_DCM01_CKS		0x00008000
-#define GC_DCM01_L0E		0x00010000
-#define GC_DCM01_DEN		0x80000000
-#define GC_L0M_L0C_8		0x00000000
-#define GC_L0M_L0C_16		0x80000000
-#define GC_L0EM_L0EC_24		0x40000000
-#define GC_L0M_L0W_UNIT		64
-#define GC_L1EM_DM		0x02000000
-
-#define GC_DISP_REFCLK_400	400
-
-/* I2C */
-#define GC_I2C_BSR		0x00000000	/* BSR */
-#define GC_I2C_BCR		0x00000004	/* BCR */
-#define GC_I2C_CCR		0x00000008	/* CCR */
-#define GC_I2C_ADR		0x0000000C	/* ADR */
-#define GC_I2C_DAR		0x00000010	/* DAR */
-
-#define I2C_DISABLE		0x00000000
-#define I2C_STOP		0x00000000
-#define I2C_START		0x00000010
-#define I2C_REPEATED_START	0x00000030
-#define I2C_CLOCK_AND_ENABLE	0x0000003f
-#define I2C_READY		0x01
-#define I2C_INT			0x01
-#define I2C_INTE		0x02
-#define I2C_ACK			0x08
-#define I2C_BER			0x80
-#define I2C_BEIE		0x40
-#define I2C_TRX			0x80
-#define I2C_LRB			0x10
-
-/* Capture registers and bits */
-#define GC_CAP_VCM		0x00000000
-#define GC_CAP_CSC		0x00000004
-#define GC_CAP_VCS		0x00000008
-#define GC_CAP_CBM		0x00000010
-#define GC_CAP_CBOA		0x00000014
-#define GC_CAP_CBLA		0x00000018
-#define GC_CAP_IMG_START	0x0000001C
-#define GC_CAP_IMG_END		0x00000020
-#define GC_CAP_CMSS		0x00000048
-#define GC_CAP_CMDS		0x0000004C
-
-#define GC_VCM_VIE		0x80000000
-#define GC_VCM_CM		0x03000000
-#define GC_VCM_VS_PAL		0x00000002
-#define GC_CBM_OO		0x80000000
-#define GC_CBM_HRV		0x00000010
-#define GC_CBM_CBST		0x00000001
-
-/* Carmine specific */
-#define MB86297_DRAW_BASE		0x00020000
-#define MB86297_DISP0_BASE		0x00100000
-#define MB86297_DISP1_BASE		0x00140000
-#define MB86297_WRBACK_BASE		0x00180000
-#define MB86297_CAP0_BASE		0x00200000
-#define MB86297_CAP1_BASE		0x00280000
-#define MB86297_DRAMCTRL_BASE		0x00300000
-#define MB86297_CTRL_BASE		0x00400000
-#define MB86297_I2C_BASE		0x00500000
-
-#define GC_CTRL_STATUS			0x00000000
-#define GC_CTRL_INT_MASK		0x00000004
-#define GC_CTRL_CLK_ENABLE		0x0000000c
-#define GC_CTRL_SOFT_RST		0x00000010
-
-#define GC_CTRL_CLK_EN_DRAM		0x00000001
-#define GC_CTRL_CLK_EN_2D3D		0x00000002
-#define GC_CTRL_CLK_EN_DISP0		0x00000020
-#define GC_CTRL_CLK_EN_DISP1		0x00000040
-
-#define GC_2D3D_REV			0x000004b4
-#define GC_RE_REVISION			0x24240200
-
-/* define enabled interrupts hereby */
-#define GC_CARMINE_INT_EN		0x00000004
-
-/* DRAM controller */
-#define GC_DCTL_MODE_ADD		0x00000000
-#define GC_DCTL_SETTIME1_EMODE		0x00000004
-#define GC_DCTL_REFRESH_SETTIME2	0x00000008
-#define GC_DCTL_RSV0_STATES		0x0000000C
-#define GC_DCTL_RSV2_RSV1		0x00000010
-#define GC_DCTL_DDRIF2_DDRIF1		0x00000014
-#define GC_DCTL_IOCONT1_IOCONT0		0x00000024
-
-#define GC_DCTL_STATES_MSK		0x0000000f
-#define GC_DCTL_INIT_WAIT_CNT		3000
-#define GC_DCTL_INIT_WAIT_INTERVAL	1
-
-/* DRAM ctrl values for Carmine PCI Eval. board */
-#define GC_EVB_DCTL_MODE_ADD		0x012105c3
-#define GC_EVB_DCTL_MODE_ADD_AFT_RST	0x002105c3
-#define GC_EVB_DCTL_SETTIME1_EMODE	0x47498000
-#define GC_EVB_DCTL_REFRESH_SETTIME2	0x00422a22
-#define GC_EVB_DCTL_RSV0_STATES		0x00200003
-#define GC_EVB_DCTL_RSV0_STATES_AFT_RST	0x00200002
-#define GC_EVB_DCTL_RSV2_RSV1		0x0000000f
-#define GC_EVB_DCTL_DDRIF2_DDRIF1	0x00556646
-#define GC_EVB_DCTL_IOCONT1_IOCONT0	0x05550555
-
-#define GC_DISP_REFCLK_533		533
-
-#endif
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h
deleted file mode 100644
index 8550630c1e01..000000000000
--- a/drivers/video/mb862xx/mb862xxfb.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef __MB862XX_H__
-#define __MB862XX_H__
-
-struct mb862xx_l1_cfg {
-	unsigned short sx;
-	unsigned short sy;
-	unsigned short sw;
-	unsigned short sh;
-	unsigned short dx;
-	unsigned short dy;
-	unsigned short dw;
-	unsigned short dh;
-	int mirror;
-};
-
-#define MB862XX_BASE		'M'
-#define MB862XX_L1_GET_CFG	_IOR(MB862XX_BASE, 0, struct mb862xx_l1_cfg*)
-#define MB862XX_L1_SET_CFG	_IOW(MB862XX_BASE, 1, struct mb862xx_l1_cfg*)
-#define MB862XX_L1_ENABLE	_IOW(MB862XX_BASE, 2, int)
-#define MB862XX_L1_CAP_CTL	_IOW(MB862XX_BASE, 3, int)
-
-#ifdef __KERNEL__
-
-#define PCI_VENDOR_ID_FUJITSU_LIMITED	0x10cf
-#define PCI_DEVICE_ID_FUJITSU_CORALP	0x2019
-#define PCI_DEVICE_ID_FUJITSU_CORALPA	0x201e
-#define PCI_DEVICE_ID_FUJITSU_CARMINE	0x202b
-
-#define GC_MMR_CORALP_EVB_VAL		0x11d7fa13
-
-enum gdctype {
-	BT_NONE,
-	BT_LIME,
-	BT_MINT,
-	BT_CORAL,
-	BT_CORALP,
-	BT_CARMINE,
-};
-
-struct mb862xx_gc_mode {
-	struct fb_videomode	def_mode;	/* mode of connected display */
-	unsigned int		def_bpp;	/* default depth */
-	unsigned long		max_vram;	/* connected SDRAM size */
-	unsigned long		ccf;		/* gdc clk */
-	unsigned long		mmr;		/* memory mode for SDRAM */
-};
-
-/* private data */
-struct mb862xxfb_par {
-	struct fb_info		*info;		/* fb info head */
-	struct device		*dev;
-	struct pci_dev		*pdev;
-	struct resource		*res;		/* framebuffer/mmio resource */
-
-	resource_size_t		fb_base_phys;	/* fb base, 36-bit PPC440EPx */
-	resource_size_t		mmio_base_phys;	/* io base addr */
-	void __iomem		*fb_base;	/* remapped framebuffer */
-	void __iomem		*mmio_base;	/* remapped registers */
-	size_t			mapped_vram;	/* length of remapped vram */
-	size_t			mmio_len;	/* length of register region */
-	unsigned long		cap_buf;	/* capture buffers offset */
-	size_t			cap_len;	/* length of capture buffers */
-
-	void __iomem		*host;		/* relocatable reg. bases */
-	void __iomem		*i2c;
-	void __iomem		*disp;
-	void __iomem		*disp1;
-	void __iomem		*cap;
-	void __iomem		*cap1;
-	void __iomem		*draw;
-	void __iomem		*geo;
-	void __iomem		*pio;
-	void __iomem		*ctrl;
-	void __iomem		*dram_ctrl;
-	void __iomem		*wrback;
-
-	unsigned int		irq;
-	unsigned int		type;		/* GDC type */
-	unsigned int		refclk;		/* disp. reference clock */
-	struct mb862xx_gc_mode	*gc_mode;	/* GDC mode init data */
-	int			pre_init;	/* don't init display if 1 */
-	struct i2c_adapter	*adap;		/* GDC I2C bus adapter */
-	int			i2c_rs;
-
-	struct mb862xx_l1_cfg	l1_cfg;
-	int			l1_stride;
-
-	u32			pseudo_palette[16];
-};
-
-extern void mb862xxfb_init_accel(struct fb_info *info, int xres);
-#ifdef CONFIG_FB_MB862XX_I2C
-extern int mb862xx_i2c_init(struct mb862xxfb_par *par);
-extern void mb862xx_i2c_exit(struct mb862xxfb_par *par);
-#else
-static inline int mb862xx_i2c_init(struct mb862xxfb_par *par) { return 0; }
-static inline void mb862xx_i2c_exit(struct mb862xxfb_par *par) { }
-#endif
-
-#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC)
-#error	"Select Lime GDC or CoralP/Carmine support, but not both together"
-#endif
-#if defined(CONFIG_FB_MB862XX_LIME)
-#define gdc_read	__raw_readl
-#define gdc_write	__raw_writel
-#else
-#define gdc_read	readl
-#define gdc_write	writel
-#endif
-
-#define inreg(type, off)	\
-	gdc_read((par->type + (off)))
-
-#define outreg(type, off, val)	\
-	gdc_write((val), (par->type + (off)))
-
-#define pack(a, b)	(((a) << 16) | (b))
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.c b/drivers/video/mb862xx/mb862xxfb_accel.c
deleted file mode 100644
index fe92eed6da70..000000000000
--- a/drivers/video/mb862xx/mb862xxfb_accel.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * drivers/mb862xx/mb862xxfb_accel.c
- *
- * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
- *
- * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
- * (C) 2009 Valentin Sitdikov <v.sitdikov@gmail.com>
- * (C) 2009 Siemens AG
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#if defined(CONFIG_OF)
-#include <linux/of_platform.h>
-#endif
-#include "mb862xxfb.h"
-#include "mb862xx_reg.h"
-#include "mb862xxfb_accel.h"
-
-static void mb862xxfb_write_fifo(u32 count, u32 *data, struct fb_info *info)
-{
-	struct mb862xxfb_par *par = info->par;
-	static u32 free;
-
-	u32 total = 0;
-	while (total < count) {
-		if (free) {
-			outreg(geo, GDC_GEO_REG_INPUT_FIFO, data[total]);
-			total++;
-			free--;
-		} else {
-			free = (u32) inreg(draw, GDC_REG_FIFO_COUNT);
-		}
-	}
-}
-
-static void mb86290fb_copyarea(struct fb_info *info,
-			       const struct fb_copyarea *area)
-{
-	__u32 cmd[6];
-
-	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
-	/* Set raster operation */
-	cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
-	cmd[2] = GDC_TYPE_BLTCOPYP << 24;
-
-	if (area->sx >= area->dx && area->sy >= area->dy)
-		cmd[2] |= GDC_CMD_BLTCOPY_TOP_LEFT << 16;
-	else if (area->sx >= area->dx && area->sy <= area->dy)
-		cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT << 16;
-	else if (area->sx <= area->dx && area->sy >= area->dy)
-		cmd[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT << 16;
-	else
-		cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT << 16;
-
-	cmd[3] = (area->sy << 16) | area->sx;
-	cmd[4] = (area->dy << 16) | area->dx;
-	cmd[5] = (area->height << 16) | area->width;
-	mb862xxfb_write_fifo(6, cmd, info);
-}
-
-/*
- * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
- * Make sure cmd has enough room!
- */
-static void mb86290fb_imageblit1(u32 *cmd, u16 step, u16 dx, u16 dy,
-				 u16 width, u16 height, u32 fgcolor,
-				 u32 bgcolor, const struct fb_image *image,
-				 struct fb_info *info)
-{
-	int i;
-	unsigned const char *line;
-	u16 bytes;
-
-	/* set colors and raster operation regs */
-	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
-	/* Set raster operation */
-	cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
-	cmd[2] =
-	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
-	cmd[3] = fgcolor;
-	cmd[4] =
-	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_BACK_COLOR << 16);
-	cmd[5] = bgcolor;
-
-	i = 0;
-	line = image->data;
-	bytes = (image->width + 7) >> 3;
-
-	/* and the image */
-	cmd[6] = (GDC_TYPE_DRAWBITMAPP << 24) |
-	    (GDC_CMD_BITMAP << 16) | (2 + (step * height));
-	cmd[7] = (dy << 16) | dx;
-	cmd[8] = (height << 16) | width;
-
-	while (i < height) {
-		memcpy(&cmd[9 + i * step], line, step << 2);
-#ifdef __LITTLE_ENDIAN
-		{
-			int k = 0;
-			for (k = 0; k < step; k++)
-				cmd[9 + i * step + k] =
-				    cpu_to_be32(cmd[9 + i * step + k]);
-		}
-#endif
-		line += bytes;
-		i++;
-	}
-}
-
-/*
- * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
- * Make sure cmd has enough room!
- */
-static void mb86290fb_imageblit8(u32 *cmd, u16 step, u16 dx, u16 dy,
-				 u16 width, u16 height, u32 fgcolor,
-				 u32 bgcolor, const struct fb_image *image,
-				 struct fb_info *info)
-{
-	int i, j;
-	unsigned const char *line, *ptr;
-	u16 bytes;
-
-	cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
-	    (GDC_CMD_BLT_DRAW << 16) | (2 + (height * step));
-	cmd[1] = (dy << 16) | dx;
-	cmd[2] = (height << 16) | width;
-
-	i = 0;
-	line = ptr = image->data;
-	bytes = image->width;
-
-	while (i < height) {
-		ptr = line;
-		for (j = 0; j < step; j++) {
-			cmd[3 + i * step + j] =
-			    (((u32 *) (info->pseudo_palette))[*ptr]) & 0xffff;
-			ptr++;
-			cmd[3 + i * step + j] |=
-			    ((((u32 *) (info->
-					pseudo_palette))[*ptr]) & 0xffff) << 16;
-			ptr++;
-		}
-
-		line += bytes;
-		i++;
-	}
-}
-
-/*
- * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
- * Make sure cmd has enough room!
- */
-static void mb86290fb_imageblit16(u32 *cmd, u16 step, u16 dx, u16 dy,
-				  u16 width, u16 height, u32 fgcolor,
-				  u32 bgcolor, const struct fb_image *image,
-				  struct fb_info *info)
-{
-	int i;
-	unsigned const char *line;
-	u16 bytes;
-
-	i = 0;
-	line = image->data;
-	bytes = image->width << 1;
-
-	cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
-	    (GDC_CMD_BLT_DRAW << 16) | (2 + step * height);
-	cmd[1] = (dy << 16) | dx;
-	cmd[2] = (height << 16) | width;
-
-	while (i < height) {
-		memcpy(&cmd[3 + i * step], line, step);
-		line += bytes;
-		i++;
-	}
-}
-
-static void mb86290fb_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	int mdr;
-	u32 *cmd = NULL;
-	void (*cmdfn) (u32 *, u16, u16, u16, u16, u16, u32, u32,
-		       const struct fb_image *, struct fb_info *) = NULL;
-	u32 cmdlen;
-	u32 fgcolor = 0, bgcolor = 0;
-	u16 step;
-
-	u16 width = image->width, height = image->height;
-	u16 dx = image->dx, dy = image->dy;
-	int x2, y2, vxres, vyres;
-
-	mdr = (GDC_ROP_COPY << 9);
-	x2 = image->dx + image->width;
-	y2 = image->dy + image->height;
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-	x2 = min(x2, vxres);
-	y2 = min(y2, vyres);
-	width = x2 - dx;
-	height = y2 - dy;
-
-	switch (image->depth) {
-	case 1:
-		step = (width + 31) >> 5;
-		cmdlen = 9 + height * step;
-		cmdfn = mb86290fb_imageblit1;
-		if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-		    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-			fgcolor =
-			    ((u32 *) (info->pseudo_palette))[image->fg_color];
-			bgcolor =
-			    ((u32 *) (info->pseudo_palette))[image->bg_color];
-		} else {
-			fgcolor = image->fg_color;
-			bgcolor = image->bg_color;
-		}
-
-		break;
-
-	case 8:
-		step = (width + 1) >> 1;
-		cmdlen = 3 + height * step;
-		cmdfn = mb86290fb_imageblit8;
-		break;
-
-	case 16:
-		step = (width + 1) >> 1;
-		cmdlen = 3 + height * step;
-		cmdfn = mb86290fb_imageblit16;
-		break;
-
-	default:
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	cmd = kmalloc(cmdlen * 4, GFP_DMA);
-	if (!cmd)
-		return cfb_imageblit(info, image);
-	cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
-	mb862xxfb_write_fifo(cmdlen, cmd, info);
-	kfree(cmd);
-}
-
-static void mb86290fb_fillrect(struct fb_info *info,
-			       const struct fb_fillrect *rect)
-{
-
-	u32 x2, y2, vxres, vyres, height, width, fg;
-	u32 cmd[7];
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	if (!rect->width || !rect->height || rect->dx > vxres
-	    || rect->dy > vyres)
-		return;
-
-	/* We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly. */
-	x2 = rect->dx + rect->width;
-	y2 = rect->dy + rect->height;
-	x2 = min(x2, vxres);
-	y2 = min(y2, vyres);
-	width = x2 - rect->dx;
-	height = y2 - rect->dy;
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
-		fg = ((u32 *) (info->pseudo_palette))[rect->color];
-	else
-		fg = rect->color;
-
-	switch (rect->rop) {
-
-	case ROP_XOR:
-		/* Set raster operation */
-		cmd[1] = (2 << 7) | (GDC_ROP_XOR << 9);
-		break;
-
-	case ROP_COPY:
-		/* Set raster operation */
-		cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
-		break;
-
-	}
-
-	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
-	/* cmd[1] set earlier */
-	cmd[2] =
-	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
-	cmd[3] = fg;
-	cmd[4] = (GDC_TYPE_DRAWRECTP << 24) | (GDC_CMD_BLT_FILL << 16);
-	cmd[5] = (rect->dy << 16) | (rect->dx);
-	cmd[6] = (height << 16) | width;
-
-	mb862xxfb_write_fifo(7, cmd, info);
-}
-
-void mb862xxfb_init_accel(struct fb_info *info, int xres)
-{
-	struct mb862xxfb_par *par = info->par;
-
-	if (info->var.bits_per_pixel == 32) {
-		info->fbops->fb_fillrect = cfb_fillrect;
-		info->fbops->fb_copyarea = cfb_copyarea;
-		info->fbops->fb_imageblit = cfb_imageblit;
-	} else {
-		outreg(disp, GC_L0EM, 3);
-		info->fbops->fb_fillrect = mb86290fb_fillrect;
-		info->fbops->fb_copyarea = mb86290fb_copyarea;
-		info->fbops->fb_imageblit = mb86290fb_imageblit;
-	}
-	outreg(draw, GDC_REG_DRAW_BASE, 0);
-	outreg(draw, GDC_REG_MODE_MISC, 0x8000);
-	outreg(draw, GDC_REG_X_RESOLUTION, xres);
-
-	info->flags |=
-	    FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
-	    FBINFO_HWACCEL_IMAGEBLIT;
-	info->fix.accel = 0xff;	/*FIXME: add right define */
-}
-EXPORT_SYMBOL(mb862xxfb_init_accel);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.h b/drivers/video/mb862xx/mb862xxfb_accel.h
deleted file mode 100644
index 96a2dfef0f60..000000000000
--- a/drivers/video/mb862xx/mb862xxfb_accel.h
+++ /dev/null
@@ -1,203 +0,0 @@
-#ifndef __MB826XXFB_ACCEL_H__
-#define __MB826XXFB_ACCEL_H__
-
-/* registers */
-#define GDC_GEO_REG_INPUT_FIFO 0x00000400L
-
-/* Special Registers */
-#define GDC_REG_CTRL                0x00000400L
-#define GDC_REG_FIFO_STATUS         0x00000404L
-#define GDC_REG_FIFO_COUNT          0x00000408L
-#define GDC_REG_SETUP_STATUS        0x0000040CL
-#define GDC_REG_DDA_STATUS          0x00000410L
-#define GDC_REG_ENGINE_STATUS       0x00000414L
-#define GDC_REG_ERROR_STATUS        0x00000418L
-#define GDC_REG_MODE_MISC           0x00000420L	/* MDR0 */
-#define GDC_REG_MODE_LINE           0x00000424L	/* MDR1 */
-#define GDC_REG_MODE_POLYGON        0x00000428L	/* MDR2 */
-#define GDC_REG_MODE_TEXTURE        0x0000042CL	/* MDR3 */
-#define GDC_REG_MODE_BITMAP         0x00000430L	/* MDR4 */
-#define GDC_REG_MODE_EXTENSION      0x0000043CL	/* MDR7 */
-
-/* Configuration Registers */
-#define GDC_REG_DRAW_BASE           0x00000440L
-#define GDC_REG_X_RESOLUTION        0x00000444L
-#define GDC_REG_Z_BASE              0x00000448L
-#define GDC_REG_TEXTURE_BASE        0x0000044CL
-#define GDC_REG_POLYGON_FLAG_BASE   0x00000450L
-#define GDC_REG_CLIP_XMIN           0x00000454L
-#define GDC_REG_CLIP_XMAX           0x00000458L
-#define GDC_REG_CLIP_YMIN           0x0000045CL
-#define GDC_REG_CLIP_YMAX           0x00000460L
-#define GDC_REG_TEXURE_SIZE         0x00000464L
-#define GDC_REG_TILE_SIZE           0x00000468L
-#define GDC_REG_TEX_BUF_OFFSET      0x0000046CL
-
-/* for MB86293 or later */
-#define GDC_REG_ALPHA_MAP_BASE      0x00000474L	/* ABR */
-
-/* Constant Registers */
-#define GDC_REG_FOREGROUND_COLOR    0x00000480L
-#define GDC_REG_BACKGROUND_COLOR    0x00000484L
-#define GDC_REG_ALPHA               0x00000488L
-#define GDC_REG_LINE_PATTERN        0x0000048CL
-#define GDC_REG_TEX_BORDER_COLOR    0x00000494L
-#define GDC_REG_LINE_PATTERN_OFFSET 0x000003E0L
-
-/* Coomand Code */
-#define GDC_CMD_PIXEL                   0x00000000L
-#define GDC_CMD_PIXEL_Z                 0x00000001L
-
-#define GDC_CMD_X_VECTOR                0x00000020L
-#define GDC_CMD_Y_VECTOR                0x00000021L
-#define GDC_CMD_X_VECTOR_NOEND          0x00000022L
-#define GDC_CMD_Y_VECTOR_NOEND          0x00000023L
-#define GDC_CMD_X_VECTOR_BLPO           0x00000024L
-#define GDC_CMD_Y_VECTOR_BLPO           0x00000025L
-#define GDC_CMD_X_VECTOR_NOEND_BLPO     0x00000026L
-#define GDC_CMD_Y_VECTOR_NOEND_BLPO     0x00000027L
-#define GDC_CMD_AA_X_VECTOR             0x00000028L
-#define GDC_CMD_AA_Y_VECTOR             0x00000029L
-#define GDC_CMD_AA_X_VECTOR_NOEND       0x0000002AL
-#define GDC_CMD_AA_Y_VECTOR_NOEND       0x0000002BL
-#define GDC_CMD_AA_X_VECTOR_BLPO        0x0000002CL
-#define GDC_CMD_AA_Y_VECTOR_BLPO        0x0000002DL
-#define GDC_CMD_AA_X_VECTOR_NOEND_BLPO  0x0000002EL
-#define GDC_CMD_AA_Y_VECTOR_NOEND_BLPO  0x0000002FL
-
-#define GDC_CMD_0_VECTOR                0x00000030L
-#define GDC_CMD_1_VECTOR                0x00000031L
-#define GDC_CMD_0_VECTOR_NOEND          0x00000032L
-#define GDC_CMD_1_VECTOR_NOEND          0x00000033L
-#define GDC_CMD_0_VECTOR_BLPO           0x00000034L
-#define GDC_CMD_1_VECTOR_BLPO           0x00000035L
-#define GDC_CMD_0_VECTOR_NOEND_BLPO     0x00000036L
-#define GDC_CMD_1_VECTOR_NOEND_BLPO     0x00000037L
-#define GDC_CMD_AA_0_VECTOR             0x00000038L
-#define GDC_CMD_AA_1_VECTOR             0x00000039L
-#define GDC_CMD_AA_0_VECTOR_NOEND       0x0000003AL
-#define GDC_CMD_AA_1_VECTOR_NOEND       0x0000003BL
-#define GDC_CMD_AA_0_VECTOR_BLPO        0x0000003CL
-#define GDC_CMD_AA_1_VECTOR_BLPO        0x0000003DL
-#define GDC_CMD_AA_0_VECTOR_NOEND_BLPO  0x0000003EL
-#define GDC_CMD_AA_1_VECTOR_NOEND_BLPO  0x0000003FL
-
-#define GDC_CMD_BLT_FILL                0x00000041L
-#define GDC_CMD_BLT_DRAW                0x00000042L
-#define GDC_CMD_BITMAP                  0x00000043L
-#define GDC_CMD_BLTCOPY_TOP_LEFT        0x00000044L
-#define GDC_CMD_BLTCOPY_TOP_RIGHT       0x00000045L
-#define GDC_CMD_BLTCOPY_BOTTOM_LEFT     0x00000046L
-#define GDC_CMD_BLTCOPY_BOTTOM_RIGHT    0x00000047L
-#define GDC_CMD_LOAD_TEXTURE            0x00000048L
-#define GDC_CMD_LOAD_TILE               0x00000049L
-
-#define GDC_CMD_TRAP_RIGHT              0x00000060L
-#define GDC_CMD_TRAP_LEFT               0x00000061L
-#define GDC_CMD_TRIANGLE_FAN            0x00000062L
-#define GDC_CMD_FLAG_TRIANGLE_FAN       0x00000063L
-
-#define GDC_CMD_FLUSH_FB                0x000000C1L
-#define GDC_CMD_FLUSH_Z                 0x000000C2L
-
-#define GDC_CMD_POLYGON_BEGIN           0x000000E0L
-#define GDC_CMD_POLYGON_END             0x000000E1L
-#define GDC_CMD_CLEAR_POLY_FLAG         0x000000E2L
-#define GDC_CMD_NORMAL                  0x000000FFL
-
-#define GDC_CMD_VECTOR_BLPO_FLAG        0x00040000L
-#define GDC_CMD_FAST_VECTOR_BLPO_FLAG   0x00000004L
-
-/* for MB86293 or later */
-#define GDC_CMD_MDR1                            0x00000000L
-#define GDC_CMD_MDR1S                           0x00000002L
-#define GDC_CMD_MDR1B                           0x00000004L
-#define GDC_CMD_MDR2                            0x00000001L
-#define GDC_CMD_MDR2S                           0x00000003L
-#define GDC_CMD_MDR2TL                          0x00000007L
-#define GDC_CMD_GMDR1E                          0x00000010L
-#define GDC_CMD_GMDR2E                          0x00000020L
-#define GDC_CMD_OVERLAP_SHADOW_XY               0x00000000L
-#define GDC_CMD_OVERLAP_SHADOW_XY_COMPOSITION   0x00000001L
-#define GDC_CMD_OVERLAP_Z_PACKED_ONBS           0x00000007L
-#define GDC_CMD_OVERLAP_Z_ORIGIN                0x00000000L
-#define GDC_CMD_OVERLAP_Z_NON_TOPLEFT           0x00000001L
-#define GDC_CMD_OVERLAP_Z_BORDER                0x00000002L
-#define GDC_CMD_OVERLAP_Z_SHADOW                0x00000003L
-#define GDC_CMD_BLTCOPY_ALT_ALPHA               0x00000000L	/* Reserverd */
-#define GDC_CMD_DC_LOGOUT                       0x00000000L	/* Reserverd */
-#define GDC_CMD_BODY_FORE_COLOR                 0x00000000L
-#define GDC_CMD_BODY_BACK_COLOR                 0x00000001L
-#define GDC_CMD_SHADOW_FORE_COLOR               0x00000002L
-#define GDC_CMD_SHADOW_BACK_COLOR               0x00000003L
-#define GDC_CMD_BORDER_FORE_COLOR               0x00000004L
-#define GDC_CMD_BORDER_BACK_COLOR               0x00000005L
-
-/* Type Code Table */
-#define GDC_TYPE_G_NOP                                  0x00000020L
-#define GDC_TYPE_G_BEGIN                                0x00000021L
-#define GDC_TYPE_G_BEGINCONT                            0x00000022L
-#define GDC_TYPE_G_END                                  0x00000023L
-#define GDC_TYPE_G_VERTEX                               0x00000030L
-#define GDC_TYPE_G_VERTEXLOG                            0x00000032L
-#define GDC_TYPE_G_VERTEXNOPLOG                         0x00000033L
-#define GDC_TYPE_G_INIT                                 0x00000040L
-#define GDC_TYPE_G_VIEWPORT                             0x00000041L
-#define GDC_TYPE_G_DEPTHRANGE                           0x00000042L
-#define GDC_TYPE_G_LOADMATRIX                           0x00000043L
-#define GDC_TYPE_G_VIEWVOLUMEXYCLIP                     0x00000044L
-#define GDC_TYPE_G_VIEWVOLUMEZCLIP                      0x00000045L
-#define GDC_TYPE_G_VIEWVOLUMEWCLIP                      0x00000046L
-#define GDC_TYPE_SETLVERTEX2I                           0x00000072L
-#define GDC_TYPE_SETLVERTEX2IP                          0x00000073L
-#define GDC_TYPE_SETMODEREGISTER                        0x000000C0L
-#define GDC_TYPE_SETGMODEREGISTER                       0x000000C1L
-#define GDC_TYPE_OVERLAPXYOFFT                          0x000000C8L
-#define GDC_TYPE_OVERLAPZOFFT                           0x000000C9L
-#define GDC_TYPE_DC_LOGOUTADDR                          0x000000CCL
-#define GDC_TYPE_SETCOLORREGISTER                       0x000000CEL
-#define GDC_TYPE_G_BEGINE                               0x000000E1L
-#define GDC_TYPE_G_BEGINCONTE                           0x000000E2L
-#define GDC_TYPE_G_ENDE                                 0x000000E3L
-#define GDC_TYPE_DRAWPIXEL                              0x00000000L
-#define GDC_TYPE_DRAWPIXELZ                             0x00000001L
-#define GDC_TYPE_DRAWLINE                               0x00000002L
-#define GDC_TYPE_DRAWLINE2I                             0x00000003L
-#define GDC_TYPE_DRAWLINE2IP                            0x00000004L
-#define GDC_TYPE_DRAWTRAP                               0x00000005L
-#define GDC_TYPE_DRAWVERTEX2I                           0x00000006L
-#define GDC_TYPE_DRAWVERTEX2IP                          0x00000007L
-#define GDC_TYPE_DRAWRECTP                              0x00000009L
-#define GDC_TYPE_DRAWBITMAPP                            0x0000000BL
-#define GDC_TYPE_BLTCOPYP                               0x0000000DL
-#define GDC_TYPE_BLTCOPYALTERNATEP                      0x0000000FL
-#define GDC_TYPE_LOADTEXTUREP                           0x00000011L
-#define GDC_TYPE_BLTTEXTUREP                            0x00000013L
-#define GDC_TYPE_BLTCOPYALTALPHABLENDP                  0x0000001FL
-#define GDC_TYPE_SETVERTEX2I                            0x00000070L
-#define GDC_TYPE_SETVERTEX2IP                           0x00000071L
-#define GDC_TYPE_DRAW                                   0x000000F0L
-#define GDC_TYPE_SETREGISTER                            0x000000F1L
-#define GDC_TYPE_SYNC                                   0x000000FCL
-#define GDC_TYPE_INTERRUPT                              0x000000FDL
-#define GDC_TYPE_NOP                                    0x0
-
-/* Raster operation */
-#define GDC_ROP_CLEAR                   0x0000
-#define GDC_ROP_AND                     0x0001
-#define GDC_ROP_AND_REVERSE             0x0002
-#define GDC_ROP_COPY                    0x0003
-#define GDC_ROP_AND_INVERTED            0x0004
-#define GDC_ROP_NOP                     0x0005
-#define GDC_ROP_XOR                     0x0006
-#define GDC_ROP_OR                      0x0007
-#define GDC_ROP_NOR                     0x0008
-#define GDC_ROP_EQUIV                   0x0009
-#define GDC_ROP_INVERT                  0x000A
-#define GDC_ROP_OR_REVERSE              0x000B
-#define GDC_ROP_COPY_INVERTED           0x000C
-#define GDC_ROP_OR_INVERTED             0x000D
-#define GDC_ROP_NAND                    0x000E
-#define GDC_ROP_SET                     0x000F
-
-#endif
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
deleted file mode 100644
index 0cd4c3318511..000000000000
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ /dev/null
@@ -1,1206 +0,0 @@
-/*
- * drivers/mb862xx/mb862xxfb.c
- *
- * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver
- *
- * (C) 2008 Anatolij Gustschin <agust@denx.de>
- * DENX Software Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#undef DEBUG
-
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#if defined(CONFIG_OF)
-#include <linux/of_platform.h>
-#endif
-#include "mb862xxfb.h"
-#include "mb862xx_reg.h"
-
-#define NR_PALETTE		256
-#define MB862XX_MEM_SIZE	0x1000000
-#define CORALP_MEM_SIZE		0x2000000
-#define CARMINE_MEM_SIZE	0x8000000
-#define DRV_NAME		"mb862xxfb"
-
-#if defined(CONFIG_SOCRATES)
-static struct mb862xx_gc_mode socrates_gc_mode = {
-	/* Mode for Prime View PM070WL4 TFT LCD Panel */
-	{ "800x480", 45, 800, 480, 40000, 86, 42, 33, 10, 128, 2, 0, 0, 0 },
-	/* 16 bits/pixel, 16MB, 133MHz, SDRAM memory mode value */
-	16, 0x1000000, GC_CCF_COT_133, 0x4157ba63
-};
-#endif
-
-/* Helpers */
-static inline int h_total(struct fb_var_screeninfo *var)
-{
-	return var->xres + var->left_margin +
-		var->right_margin + var->hsync_len;
-}
-
-static inline int v_total(struct fb_var_screeninfo *var)
-{
-	return var->yres + var->upper_margin +
-		var->lower_margin + var->vsync_len;
-}
-
-static inline int hsp(struct fb_var_screeninfo *var)
-{
-	return var->xres + var->right_margin - 1;
-}
-
-static inline int vsp(struct fb_var_screeninfo *var)
-{
-	return var->yres + var->lower_margin - 1;
-}
-
-static inline int d_pitch(struct fb_var_screeninfo *var)
-{
-	return var->xres * var->bits_per_pixel / 8;
-}
-
-static inline unsigned int chan_to_field(unsigned int chan,
-					 struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int mb862xxfb_setcolreg(unsigned regno,
-			       unsigned red, unsigned green, unsigned blue,
-			       unsigned transp, struct fb_info *info)
-{
-	struct mb862xxfb_par *par = info->par;
-	unsigned int val;
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		if (regno < 16) {
-			val  = chan_to_field(red,   &info->var.red);
-			val |= chan_to_field(green, &info->var.green);
-			val |= chan_to_field(blue,  &info->var.blue);
-			par->pseudo_palette[regno] = val;
-		}
-		break;
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno < 256) {
-			val = (red >> 8) << 16;
-			val |= (green >> 8) << 8;
-			val |= blue >> 8;
-			outreg(disp, GC_L0PAL0 + (regno * 4), val);
-		}
-		break;
-	default:
-		return 1;   /* unsupported type */
-	}
-	return 0;
-}
-
-static int mb862xxfb_check_var(struct fb_var_screeninfo *var,
-			       struct fb_info *fbi)
-{
-	unsigned long tmp;
-
-	if (fbi->dev)
-		dev_dbg(fbi->dev, "%s\n", __func__);
-
-	/* check if these values fit into the registers */
-	if (var->hsync_len > 255 || var->vsync_len > 255)
-		return -EINVAL;
-
-	if ((var->xres + var->right_margin) >= 4096)
-		return -EINVAL;
-
-	if ((var->yres + var->lower_margin) > 4096)
-		return -EINVAL;
-
-	if (h_total(var) > 4096 || v_total(var) > 4096)
-		return -EINVAL;
-
-	if (var->xres_virtual > 4096 || var->yres_virtual > 4096)
-		return -EINVAL;
-
-	if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel <= 32)
-		var->bits_per_pixel = 32;
-
-	/*
-	 * can cope with 8,16 or 24/32bpp if resulting
-	 * pitch is divisible by 64 without remainder
-	 */
-	if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) {
-		int r;
-
-		var->bits_per_pixel = 0;
-		do {
-			var->bits_per_pixel += 8;
-			r = d_pitch(&fbi->var) % GC_L0M_L0W_UNIT;
-		} while (r && var->bits_per_pixel <= 32);
-
-		if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT)
-			return -EINVAL;
-	}
-
-	/* line length is going to be 128 bit aligned */
-	tmp = (var->xres * var->bits_per_pixel) / 8;
-	if ((tmp & 15) != 0)
-		return -EINVAL;
-
-	/* set r/g/b positions and validate bpp */
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.length		= var->bits_per_pixel;
-		var->green.length	= var->bits_per_pixel;
-		var->blue.length	= var->bits_per_pixel;
-		var->red.offset		= 0;
-		var->green.offset	= 0;
-		var->blue.offset	= 0;
-		var->transp.length	= 0;
-		break;
-	case 16:
-		var->red.length		= 5;
-		var->green.length	= 5;
-		var->blue.length	= 5;
-		var->red.offset		= 10;
-		var->green.offset	= 5;
-		var->blue.offset	= 0;
-		var->transp.length	= 0;
-		break;
-	case 24:
-	case 32:
-		var->transp.length	= 8;
-		var->red.length		= 8;
-		var->green.length	= 8;
-		var->blue.length	= 8;
-		var->transp.offset	= 24;
-		var->red.offset		= 16;
-		var->green.offset	= 8;
-		var->blue.offset	= 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/*
- * set display parameters
- */
-static int mb862xxfb_set_par(struct fb_info *fbi)
-{
-	struct mb862xxfb_par *par = fbi->par;
-	unsigned long reg, sc;
-
-	dev_dbg(par->dev, "%s\n", __func__);
-	if (par->type == BT_CORALP)
-		mb862xxfb_init_accel(fbi, fbi->var.xres);
-
-	if (par->pre_init)
-		return 0;
-
-	/* disp off */
-	reg = inreg(disp, GC_DCM1);
-	reg &= ~GC_DCM01_DEN;
-	outreg(disp, GC_DCM1, reg);
-
-	/* set display reference clock div. */
-	sc = par->refclk / (1000000 / fbi->var.pixclock) - 1;
-	reg = inreg(disp, GC_DCM1);
-	reg &= ~(GC_DCM01_CKS | GC_DCM01_RESV | GC_DCM01_SC);
-	reg |= sc << 8;
-	outreg(disp, GC_DCM1, reg);
-	dev_dbg(par->dev, "SC 0x%lx\n", sc);
-
-	/* disp dimension, format */
-	reg =  pack(d_pitch(&fbi->var) / GC_L0M_L0W_UNIT,
-		    (fbi->var.yres - 1));
-	if (fbi->var.bits_per_pixel == 16)
-		reg |= GC_L0M_L0C_16;
-	outreg(disp, GC_L0M, reg);
-
-	if (fbi->var.bits_per_pixel == 32) {
-		reg = inreg(disp, GC_L0EM);
-		outreg(disp, GC_L0EM, reg | GC_L0EM_L0EC_24);
-	}
-	outreg(disp, GC_WY_WX, 0);
-	reg = pack(fbi->var.yres - 1, fbi->var.xres);
-	outreg(disp, GC_WH_WW, reg);
-	outreg(disp, GC_L0OA0, 0);
-	outreg(disp, GC_L0DA0, 0);
-	outreg(disp, GC_L0DY_L0DX, 0);
-	outreg(disp, GC_L0WY_L0WX, 0);
-	outreg(disp, GC_L0WH_L0WW, reg);
-
-	/* both HW-cursors off */
-	reg = inreg(disp, GC_CPM_CUTC);
-	reg &= ~(GC_CPM_CEN0 | GC_CPM_CEN1);
-	outreg(disp, GC_CPM_CUTC, reg);
-
-	/* timings */
-	reg = pack(fbi->var.xres - 1, fbi->var.xres - 1);
-	outreg(disp, GC_HDB_HDP, reg);
-	reg = pack((fbi->var.yres - 1), vsp(&fbi->var));
-	outreg(disp, GC_VDP_VSP, reg);
-	reg = ((fbi->var.vsync_len - 1) << 24) |
-	      pack((fbi->var.hsync_len - 1), hsp(&fbi->var));
-	outreg(disp, GC_VSW_HSW_HSP, reg);
-	outreg(disp, GC_HTP, pack(h_total(&fbi->var) - 1, 0));
-	outreg(disp, GC_VTR, pack(v_total(&fbi->var) - 1, 0));
-
-	/* display on */
-	reg = inreg(disp, GC_DCM1);
-	reg |= GC_DCM01_DEN | GC_DCM01_L0E;
-	reg &= ~GC_DCM01_ESY;
-	outreg(disp, GC_DCM1, reg);
-	return 0;
-}
-
-static int mb862xxfb_pan(struct fb_var_screeninfo *var,
-			 struct fb_info *info)
-{
-	struct mb862xxfb_par *par = info->par;
-	unsigned long reg;
-
-	reg = pack(var->yoffset, var->xoffset);
-	outreg(disp, GC_L0WY_L0WX, reg);
-
-	reg = pack(info->var.yres_virtual, info->var.xres_virtual);
-	outreg(disp, GC_L0WH_L0WW, reg);
-	return 0;
-}
-
-static int mb862xxfb_blank(int mode, struct fb_info *fbi)
-{
-	struct mb862xxfb_par  *par = fbi->par;
-	unsigned long reg;
-
-	dev_dbg(fbi->dev, "blank mode=%d\n", mode);
-
-	switch (mode) {
-	case FB_BLANK_POWERDOWN:
-		reg = inreg(disp, GC_DCM1);
-		reg &= ~GC_DCM01_DEN;
-		outreg(disp, GC_DCM1, reg);
-		break;
-	case FB_BLANK_UNBLANK:
-		reg = inreg(disp, GC_DCM1);
-		reg |= GC_DCM01_DEN;
-		outreg(disp, GC_DCM1, reg);
-		break;
-	case FB_BLANK_NORMAL:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	default:
-		return 1;
-	}
-	return 0;
-}
-
-static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd,
-			   unsigned long arg)
-{
-	struct mb862xxfb_par *par = fbi->par;
-	struct mb862xx_l1_cfg *l1_cfg = &par->l1_cfg;
-	void __user *argp = (void __user *)arg;
-	int *enable;
-	u32 l1em = 0;
-
-	switch (cmd) {
-	case MB862XX_L1_GET_CFG:
-		if (copy_to_user(argp, l1_cfg, sizeof(*l1_cfg)))
-			return -EFAULT;
-		break;
-	case MB862XX_L1_SET_CFG:
-		if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
-			return -EFAULT;
-		if (l1_cfg->dh == 0 || l1_cfg->dw == 0)
-			return -EINVAL;
-		if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
-			/* downscaling */
-			outreg(cap, GC_CAP_CSC,
-				pack((l1_cfg->sh << 11) / l1_cfg->dh,
-				     (l1_cfg->sw << 11) / l1_cfg->dw));
-			l1em = inreg(disp, GC_L1EM);
-			l1em &= ~GC_L1EM_DM;
-		} else if ((l1_cfg->sw <= l1_cfg->dw) &&
-			   (l1_cfg->sh <= l1_cfg->dh)) {
-			/* upscaling */
-			outreg(cap, GC_CAP_CSC,
-				pack((l1_cfg->sh << 11) / l1_cfg->dh,
-				     (l1_cfg->sw << 11) / l1_cfg->dw));
-			outreg(cap, GC_CAP_CMSS,
-				pack(l1_cfg->sw >> 1, l1_cfg->sh));
-			outreg(cap, GC_CAP_CMDS,
-				pack(l1_cfg->dw >> 1, l1_cfg->dh));
-			l1em = inreg(disp, GC_L1EM);
-			l1em |= GC_L1EM_DM;
-		}
-
-		if (l1_cfg->mirror) {
-			outreg(cap, GC_CAP_CBM,
-				inreg(cap, GC_CAP_CBM) | GC_CBM_HRV);
-			l1em |= l1_cfg->dw * 2 - 8;
-		} else {
-			outreg(cap, GC_CAP_CBM,
-				inreg(cap, GC_CAP_CBM) & ~GC_CBM_HRV);
-			l1em &= 0xffff0000;
-		}
-		outreg(disp, GC_L1EM, l1em);
-		break;
-	case MB862XX_L1_ENABLE:
-		enable = (int *)arg;
-		if (*enable) {
-			outreg(disp, GC_L1DA, par->cap_buf);
-			outreg(cap, GC_CAP_IMG_START,
-				pack(l1_cfg->sy >> 1, l1_cfg->sx));
-			outreg(cap, GC_CAP_IMG_END,
-				pack(l1_cfg->sh, l1_cfg->sw));
-			outreg(disp, GC_L1M, GC_L1M_16 | GC_L1M_YC | GC_L1M_CS |
-					     (par->l1_stride << 16));
-			outreg(disp, GC_L1WY_L1WX,
-				pack(l1_cfg->dy, l1_cfg->dx));
-			outreg(disp, GC_L1WH_L1WW,
-				pack(l1_cfg->dh - 1, l1_cfg->dw));
-			outreg(disp, GC_DLS, 1);
-			outreg(cap, GC_CAP_VCM,
-				GC_VCM_VIE | GC_VCM_CM | GC_VCM_VS_PAL);
-			outreg(disp, GC_DCM1, inreg(disp, GC_DCM1) |
-					      GC_DCM1_DEN | GC_DCM1_L1E);
-		} else {
-			outreg(cap, GC_CAP_VCM,
-				inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
-			outreg(disp, GC_DCM1,
-				inreg(disp, GC_DCM1) & ~GC_DCM1_L1E);
-		}
-		break;
-	case MB862XX_L1_CAP_CTL:
-		enable = (int *)arg;
-		if (*enable) {
-			outreg(cap, GC_CAP_VCM,
-				inreg(cap, GC_CAP_VCM) | GC_VCM_VIE);
-		} else {
-			outreg(cap, GC_CAP_VCM,
-				inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/* framebuffer ops */
-static struct fb_ops mb862xxfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= mb862xxfb_check_var,
-	.fb_set_par	= mb862xxfb_set_par,
-	.fb_setcolreg	= mb862xxfb_setcolreg,
-	.fb_blank	= mb862xxfb_blank,
-	.fb_pan_display	= mb862xxfb_pan,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_ioctl	= mb862xxfb_ioctl,
-};
-
-/* initialize fb_info data */
-static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
-{
-	struct mb862xxfb_par *par = fbi->par;
-	struct mb862xx_gc_mode *mode = par->gc_mode;
-	unsigned long reg;
-	int stride;
-
-	fbi->fbops = &mb862xxfb_ops;
-	fbi->pseudo_palette = par->pseudo_palette;
-	fbi->screen_base = par->fb_base;
-	fbi->screen_size = par->mapped_vram;
-
-	strcpy(fbi->fix.id, DRV_NAME);
-	fbi->fix.smem_start = (unsigned long)par->fb_base_phys;
-	fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys;
-	fbi->fix.mmio_len = par->mmio_len;
-	fbi->fix.accel = FB_ACCEL_NONE;
-	fbi->fix.type = FB_TYPE_PACKED_PIXELS;
-	fbi->fix.type_aux = 0;
-	fbi->fix.xpanstep = 1;
-	fbi->fix.ypanstep = 1;
-	fbi->fix.ywrapstep = 0;
-
-	reg = inreg(disp, GC_DCM1);
-	if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) {
-		/* get the disp mode from active display cfg */
-		unsigned long sc = ((reg & GC_DCM01_SC) >> 8) + 1;
-		unsigned long hsp, vsp, ht, vt;
-
-		dev_dbg(par->dev, "using bootloader's disp. mode\n");
-		fbi->var.pixclock = (sc * 1000000) / par->refclk;
-		fbi->var.xres = (inreg(disp, GC_HDB_HDP) & 0x0fff) + 1;
-		reg = inreg(disp, GC_VDP_VSP);
-		fbi->var.yres = ((reg >> 16) & 0x0fff) + 1;
-		vsp = (reg & 0x0fff) + 1;
-		fbi->var.xres_virtual = fbi->var.xres;
-		fbi->var.yres_virtual = fbi->var.yres;
-		reg = inreg(disp, GC_L0EM);
-		if (reg & GC_L0EM_L0EC_24) {
-			fbi->var.bits_per_pixel = 32;
-		} else {
-			reg = inreg(disp, GC_L0M);
-			if (reg & GC_L0M_L0C_16)
-				fbi->var.bits_per_pixel = 16;
-			else
-				fbi->var.bits_per_pixel = 8;
-		}
-		reg = inreg(disp, GC_VSW_HSW_HSP);
-		fbi->var.hsync_len = ((reg & 0xff0000) >> 16) + 1;
-		fbi->var.vsync_len = ((reg & 0x3f000000) >> 24) + 1;
-		hsp = (reg & 0xffff) + 1;
-		ht = ((inreg(disp, GC_HTP) & 0xfff0000) >> 16) + 1;
-		fbi->var.right_margin = hsp - fbi->var.xres;
-		fbi->var.left_margin = ht - hsp - fbi->var.hsync_len;
-		vt = ((inreg(disp, GC_VTR) & 0xfff0000) >> 16) + 1;
-		fbi->var.lower_margin = vsp - fbi->var.yres;
-		fbi->var.upper_margin = vt - vsp - fbi->var.vsync_len;
-	} else if (mode) {
-		dev_dbg(par->dev, "using supplied mode\n");
-		fb_videomode_to_var(&fbi->var, (struct fb_videomode *)mode);
-		fbi->var.bits_per_pixel = mode->def_bpp ? mode->def_bpp : 8;
-	} else {
-		int ret;
-
-		ret = fb_find_mode(&fbi->var, fbi, "640x480-16@60",
-				   NULL, 0, NULL, 16);
-		if (ret == 0 || ret == 4) {
-			dev_err(par->dev,
-				"failed to get initial mode\n");
-			return -EINVAL;
-		}
-	}
-
-	fbi->var.xoffset = 0;
-	fbi->var.yoffset = 0;
-	fbi->var.grayscale = 0;
-	fbi->var.nonstd = 0;
-	fbi->var.height = -1;
-	fbi->var.width = -1;
-	fbi->var.accel_flags = 0;
-	fbi->var.vmode = FB_VMODE_NONINTERLACED;
-	fbi->var.activate = FB_ACTIVATE_NOW;
-	fbi->flags = FBINFO_DEFAULT |
-#ifdef __BIG_ENDIAN
-		     FBINFO_FOREIGN_ENDIAN |
-#endif
-		     FBINFO_HWACCEL_XPAN |
-		     FBINFO_HWACCEL_YPAN;
-
-	/* check and possibly fix bpp */
-	if ((fbi->fbops->fb_check_var)(&fbi->var, fbi))
-		dev_err(par->dev, "check_var() failed on initial setup?\n");
-
-	fbi->fix.visual = fbi->var.bits_per_pixel == 8 ?
-			 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	fbi->fix.line_length = (fbi->var.xres_virtual *
-				fbi->var.bits_per_pixel) / 8;
-	fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual;
-
-	/*
-	 * reserve space for capture buffers and two cursors
-	 * at the end of vram: 720x576 * 2 * 2.2 + 64x64 * 16.
-	 */
-	par->cap_buf = par->mapped_vram - 0x1bd800 - 0x10000;
-	par->cap_len = 0x1bd800;
-	par->l1_cfg.sx = 0;
-	par->l1_cfg.sy = 0;
-	par->l1_cfg.sw = 720;
-	par->l1_cfg.sh = 576;
-	par->l1_cfg.dx = 0;
-	par->l1_cfg.dy = 0;
-	par->l1_cfg.dw = 720;
-	par->l1_cfg.dh = 576;
-	stride = par->l1_cfg.sw * (fbi->var.bits_per_pixel / 8);
-	par->l1_stride = stride / 64 + ((stride % 64) ? 1 : 0);
-	outreg(cap, GC_CAP_CBM, GC_CBM_OO | GC_CBM_CBST |
-				(par->l1_stride << 16));
-	outreg(cap, GC_CAP_CBOA, par->cap_buf);
-	outreg(cap, GC_CAP_CBLA, par->cap_buf + par->cap_len);
-	return 0;
-}
-
-/*
- * show some display controller and cursor registers
- */
-static ssize_t mb862xxfb_show_dispregs(struct device *dev,
-				       struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct mb862xxfb_par *par = fbi->par;
-	char *ptr = buf;
-	unsigned int reg;
-
-	for (reg = GC_DCM0; reg <= GC_L0DY_L0DX; reg += 4)
-		ptr += sprintf(ptr, "%08x = %08x\n",
-			       reg, inreg(disp, reg));
-
-	for (reg = GC_CPM_CUTC; reg <= GC_CUY1_CUX1; reg += 4)
-		ptr += sprintf(ptr, "%08x = %08x\n",
-			       reg, inreg(disp, reg));
-
-	for (reg = GC_DCM1; reg <= GC_L0WH_L0WW; reg += 4)
-		ptr += sprintf(ptr, "%08x = %08x\n",
-			       reg, inreg(disp, reg));
-
-	for (reg = 0x400; reg <= 0x410; reg += 4)
-		ptr += sprintf(ptr, "geo %08x = %08x\n",
-			       reg, inreg(geo, reg));
-
-	for (reg = 0x400; reg <= 0x410; reg += 4)
-		ptr += sprintf(ptr, "draw %08x = %08x\n",
-			       reg, inreg(draw, reg));
-
-	for (reg = 0x440; reg <= 0x450; reg += 4)
-		ptr += sprintf(ptr, "draw %08x = %08x\n",
-			       reg, inreg(draw, reg));
-
-	return ptr - buf;
-}
-
-static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL);
-
-static irqreturn_t mb862xx_intr(int irq, void *dev_id)
-{
-	struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id;
-	unsigned long reg_ist, mask;
-
-	if (!par)
-		return IRQ_NONE;
-
-	if (par->type == BT_CARMINE) {
-		/* Get Interrupt Status */
-		reg_ist = inreg(ctrl, GC_CTRL_STATUS);
-		mask = inreg(ctrl, GC_CTRL_INT_MASK);
-		if (reg_ist == 0)
-			return IRQ_HANDLED;
-
-		reg_ist &= mask;
-		if (reg_ist == 0)
-			return IRQ_HANDLED;
-
-		/* Clear interrupt status */
-		outreg(ctrl, 0x0, reg_ist);
-	} else {
-		/* Get status */
-		reg_ist = inreg(host, GC_IST);
-		mask = inreg(host, GC_IMASK);
-
-		reg_ist &= mask;
-		if (reg_ist == 0)
-			return IRQ_HANDLED;
-
-		/* Clear status */
-		outreg(host, GC_IST, ~reg_ist);
-	}
-	return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_FB_MB862XX_LIME)
-/*
- * GDC (Lime, Coral(B/Q), Mint, ...) on host bus
- */
-static int mb862xx_gdc_init(struct mb862xxfb_par *par)
-{
-	unsigned long ccf, mmr;
-	unsigned long ver, rev;
-
-	if (!par)
-		return -ENODEV;
-
-#if defined(CONFIG_FB_PRE_INIT_FB)
-	par->pre_init = 1;
-#endif
-	par->host = par->mmio_base;
-	par->i2c = par->mmio_base + MB862XX_I2C_BASE;
-	par->disp = par->mmio_base + MB862XX_DISP_BASE;
-	par->cap = par->mmio_base + MB862XX_CAP_BASE;
-	par->draw = par->mmio_base + MB862XX_DRAW_BASE;
-	par->geo = par->mmio_base + MB862XX_GEO_BASE;
-	par->pio = par->mmio_base + MB862XX_PIO_BASE;
-
-	par->refclk = GC_DISP_REFCLK_400;
-
-	ver = inreg(host, GC_CID);
-	rev = inreg(pio, GC_REVISION);
-	if ((ver == 0x303) && (rev & 0xffffff00) == 0x20050100) {
-		dev_info(par->dev, "Fujitsu Lime v1.%d found\n",
-			 (int)rev & 0xff);
-		par->type = BT_LIME;
-		ccf = par->gc_mode ? par->gc_mode->ccf : GC_CCF_COT_100;
-		mmr = par->gc_mode ? par->gc_mode->mmr : 0x414fb7f2;
-	} else {
-		dev_info(par->dev, "? GDC, CID/Rev.: 0x%lx/0x%lx \n", ver, rev);
-		return -ENODEV;
-	}
-
-	if (!par->pre_init) {
-		outreg(host, GC_CCF, ccf);
-		udelay(200);
-		outreg(host, GC_MMR, mmr);
-		udelay(10);
-	}
-
-	/* interrupt status */
-	outreg(host, GC_IST, 0);
-	outreg(host, GC_IMASK, GC_INT_EN);
-	return 0;
-}
-
-static int of_platform_mb862xx_probe(struct platform_device *ofdev)
-{
-	struct device_node *np = ofdev->dev.of_node;
-	struct device *dev = &ofdev->dev;
-	struct mb862xxfb_par *par;
-	struct fb_info *info;
-	struct resource res;
-	resource_size_t res_size;
-	unsigned long ret = -ENODEV;
-
-	if (of_address_to_resource(np, 0, &res)) {
-		dev_err(dev, "Invalid address\n");
-		return -ENXIO;
-	}
-
-	info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
-	if (info == NULL) {
-		dev_err(dev, "cannot allocate framebuffer\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	par->info = info;
-	par->dev = dev;
-
-	par->irq = irq_of_parse_and_map(np, 0);
-	if (par->irq == NO_IRQ) {
-		dev_err(dev, "failed to map irq\n");
-		ret = -ENODEV;
-		goto fbrel;
-	}
-
-	res_size = resource_size(&res);
-	par->res = request_mem_region(res.start, res_size, DRV_NAME);
-	if (par->res == NULL) {
-		dev_err(dev, "Cannot claim framebuffer/mmio\n");
-		ret = -ENXIO;
-		goto irqdisp;
-	}
-
-#if defined(CONFIG_SOCRATES)
-	par->gc_mode = &socrates_gc_mode;
-#endif
-
-	par->fb_base_phys = res.start;
-	par->mmio_base_phys = res.start + MB862XX_MMIO_BASE;
-	par->mmio_len = MB862XX_MMIO_SIZE;
-	if (par->gc_mode)
-		par->mapped_vram = par->gc_mode->max_vram;
-	else
-		par->mapped_vram = MB862XX_MEM_SIZE;
-
-	par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
-	if (par->fb_base == NULL) {
-		dev_err(dev, "Cannot map framebuffer\n");
-		goto rel_reg;
-	}
-
-	par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
-	if (par->mmio_base == NULL) {
-		dev_err(dev, "Cannot map registers\n");
-		goto fb_unmap;
-	}
-
-	dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
-		(u64)par->fb_base_phys, (ulong)par->mapped_vram);
-	dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n",
-		(u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq);
-
-	if (mb862xx_gdc_init(par))
-		goto io_unmap;
-
-	if (request_irq(par->irq, mb862xx_intr, 0,
-			DRV_NAME, (void *)par)) {
-		dev_err(dev, "Cannot request irq\n");
-		goto io_unmap;
-	}
-
-	mb862xxfb_init_fbinfo(info);
-
-	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
-		dev_err(dev, "Could not allocate cmap for fb_info.\n");
-		goto free_irq;
-	}
-
-	if ((info->fbops->fb_set_par)(info))
-		dev_err(dev, "set_var() failed on initial setup?\n");
-
-	if (register_framebuffer(info)) {
-		dev_err(dev, "failed to register framebuffer\n");
-		goto rel_cmap;
-	}
-
-	dev_set_drvdata(dev, info);
-
-	if (device_create_file(dev, &dev_attr_dispregs))
-		dev_err(dev, "Can't create sysfs regdump file\n");
-	return 0;
-
-rel_cmap:
-	fb_dealloc_cmap(&info->cmap);
-free_irq:
-	outreg(host, GC_IMASK, 0);
-	free_irq(par->irq, (void *)par);
-io_unmap:
-	iounmap(par->mmio_base);
-fb_unmap:
-	iounmap(par->fb_base);
-rel_reg:
-	release_mem_region(res.start, res_size);
-irqdisp:
-	irq_dispose_mapping(par->irq);
-fbrel:
-	framebuffer_release(info);
-	return ret;
-}
-
-static int of_platform_mb862xx_remove(struct platform_device *ofdev)
-{
-	struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
-	struct mb862xxfb_par *par = fbi->par;
-	resource_size_t res_size = resource_size(par->res);
-	unsigned long reg;
-
-	dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
-
-	/* display off */
-	reg = inreg(disp, GC_DCM1);
-	reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
-	outreg(disp, GC_DCM1, reg);
-
-	/* disable interrupts */
-	outreg(host, GC_IMASK, 0);
-
-	free_irq(par->irq, (void *)par);
-	irq_dispose_mapping(par->irq);
-
-	device_remove_file(&ofdev->dev, &dev_attr_dispregs);
-
-	unregister_framebuffer(fbi);
-	fb_dealloc_cmap(&fbi->cmap);
-
-	iounmap(par->mmio_base);
-	iounmap(par->fb_base);
-
-	release_mem_region(par->res->start, res_size);
-	framebuffer_release(fbi);
-	return 0;
-}
-
-/*
- * common types
- */
-static struct of_device_id of_platform_mb862xx_tbl[] = {
-	{ .compatible = "fujitsu,MB86276", },
-	{ .compatible = "fujitsu,lime", },
-	{ .compatible = "fujitsu,MB86277", },
-	{ .compatible = "fujitsu,mint", },
-	{ .compatible = "fujitsu,MB86293", },
-	{ .compatible = "fujitsu,MB86294", },
-	{ .compatible = "fujitsu,coral", },
-	{ /* end */ }
-};
-
-static struct platform_driver of_platform_mb862xxfb_driver = {
-	.driver = {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
-		.of_match_table = of_platform_mb862xx_tbl,
-	},
-	.probe		= of_platform_mb862xx_probe,
-	.remove		= of_platform_mb862xx_remove,
-};
-#endif
-
-#if defined(CONFIG_FB_MB862XX_PCI_GDC)
-static int coralp_init(struct mb862xxfb_par *par)
-{
-	int cn, ver;
-
-	par->host = par->mmio_base;
-	par->i2c = par->mmio_base + MB862XX_I2C_BASE;
-	par->disp = par->mmio_base + MB862XX_DISP_BASE;
-	par->cap = par->mmio_base + MB862XX_CAP_BASE;
-	par->draw = par->mmio_base + MB862XX_DRAW_BASE;
-	par->geo = par->mmio_base + MB862XX_GEO_BASE;
-	par->pio = par->mmio_base + MB862XX_PIO_BASE;
-
-	par->refclk = GC_DISP_REFCLK_400;
-
-	if (par->mapped_vram >= 0x2000000) {
-		/* relocate gdc registers space */
-		writel(1, par->fb_base + MB862XX_MMIO_BASE + GC_RSW);
-		udelay(1); /* wait at least 20 bus cycles */
-	}
-
-	ver = inreg(host, GC_CID);
-	cn = (ver & GC_CID_CNAME_MSK) >> 8;
-	ver = ver & GC_CID_VERSION_MSK;
-	if (cn == 3) {
-		unsigned long reg;
-
-		dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\
-			 (ver == 6) ? "P" : (ver == 8) ? "PA" : "?",
-			 par->pdev->revision);
-		reg = inreg(disp, GC_DCM1);
-		if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E)
-			par->pre_init = 1;
-
-		if (!par->pre_init) {
-			outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133);
-			udelay(200);
-			outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL);
-			udelay(10);
-		}
-		/* Clear interrupt status */
-		outreg(host, GC_IST, 0);
-	} else {
-		return -ENODEV;
-	}
-
-	mb862xx_i2c_init(par);
-	return 0;
-}
-
-static int init_dram_ctrl(struct mb862xxfb_par *par)
-{
-	unsigned long i = 0;
-
-	/*
-	 * Set io mode first! Spec. says IC may be destroyed
-	 * if not set to SSTL2/LVCMOS before init.
-	 */
-	outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0);
-
-	/* DRAM init */
-	outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD);
-	outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE);
-	outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2,
-	       GC_EVB_DCTL_REFRESH_SETTIME2);
-	outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1);
-	outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1);
-	outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES);
-
-	/* DLL reset done? */
-	while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) {
-		udelay(GC_DCTL_INIT_WAIT_INTERVAL);
-		if (i++ > GC_DCTL_INIT_WAIT_CNT) {
-			dev_err(par->dev, "VRAM init failed.\n");
-			return -EINVAL;
-		}
-	}
-	outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST);
-	outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST);
-	return 0;
-}
-
-static int carmine_init(struct mb862xxfb_par *par)
-{
-	unsigned long reg;
-
-	par->ctrl = par->mmio_base + MB86297_CTRL_BASE;
-	par->i2c = par->mmio_base + MB86297_I2C_BASE;
-	par->disp = par->mmio_base + MB86297_DISP0_BASE;
-	par->disp1 = par->mmio_base + MB86297_DISP1_BASE;
-	par->cap = par->mmio_base + MB86297_CAP0_BASE;
-	par->cap1 = par->mmio_base + MB86297_CAP1_BASE;
-	par->draw = par->mmio_base + MB86297_DRAW_BASE;
-	par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE;
-	par->wrback = par->mmio_base + MB86297_WRBACK_BASE;
-
-	par->refclk = GC_DISP_REFCLK_533;
-
-	/* warm up */
-	reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0;
-	outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
-
-	/* check for engine module revision */
-	if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION)
-		dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n",
-			 par->pdev->revision);
-	else
-		goto err_init;
-
-	reg &= ~GC_CTRL_CLK_EN_2D3D;
-	outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
-
-	/* set up vram */
-	if (init_dram_ctrl(par) < 0)
-		goto err_init;
-
-	outreg(ctrl, GC_CTRL_INT_MASK, 0);
-	return 0;
-
-err_init:
-	outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
-	return -EINVAL;
-}
-
-static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par)
-{
-	switch (par->type) {
-	case BT_CORALP:
-		return coralp_init(par);
-	case BT_CARMINE:
-		return carmine_init(par);
-	default:
-		return -ENODEV;
-	}
-}
-
-#define CHIP_ID(id)	\
-	{ PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) }
-
-static struct pci_device_id mb862xx_pci_tbl[] = {
-	/* MB86295/MB86296 */
-	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP),
-	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA),
-	/* MB86297 */
-	CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE),
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl);
-
-static int mb862xx_pci_probe(struct pci_dev *pdev,
-			     const struct pci_device_id *ent)
-{
-	struct mb862xxfb_par *par;
-	struct fb_info *info;
-	struct device *dev = &pdev->dev;
-	int ret;
-
-	ret = pci_enable_device(pdev);
-	if (ret < 0) {
-		dev_err(dev, "Cannot enable PCI device\n");
-		goto out;
-	}
-
-	info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
-	if (!info) {
-		dev_err(dev, "framebuffer alloc failed\n");
-		ret = -ENOMEM;
-		goto dis_dev;
-	}
-
-	par = info->par;
-	par->info = info;
-	par->dev = dev;
-	par->pdev = pdev;
-	par->irq = pdev->irq;
-
-	ret = pci_request_regions(pdev, DRV_NAME);
-	if (ret < 0) {
-		dev_err(dev, "Cannot reserve region(s) for PCI device\n");
-		goto rel_fb;
-	}
-
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_FUJITSU_CORALP:
-	case PCI_DEVICE_ID_FUJITSU_CORALPA:
-		par->fb_base_phys = pci_resource_start(par->pdev, 0);
-		par->mapped_vram = CORALP_MEM_SIZE;
-		if (par->mapped_vram >= 0x2000000) {
-			par->mmio_base_phys = par->fb_base_phys +
-					      MB862XX_MMIO_HIGH_BASE;
-		} else {
-			par->mmio_base_phys = par->fb_base_phys +
-					      MB862XX_MMIO_BASE;
-		}
-		par->mmio_len = MB862XX_MMIO_SIZE;
-		par->type = BT_CORALP;
-		break;
-	case PCI_DEVICE_ID_FUJITSU_CARMINE:
-		par->fb_base_phys = pci_resource_start(par->pdev, 2);
-		par->mmio_base_phys = pci_resource_start(par->pdev, 3);
-		par->mmio_len = pci_resource_len(par->pdev, 3);
-		par->mapped_vram = CARMINE_MEM_SIZE;
-		par->type = BT_CARMINE;
-		break;
-	default:
-		/* should never occur */
-		ret = -EIO;
-		goto rel_reg;
-	}
-
-	par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
-	if (par->fb_base == NULL) {
-		dev_err(dev, "Cannot map framebuffer\n");
-		ret = -EIO;
-		goto rel_reg;
-	}
-
-	par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
-	if (par->mmio_base == NULL) {
-		dev_err(dev, "Cannot map registers\n");
-		ret = -EIO;
-		goto fb_unmap;
-	}
-
-	dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
-		(unsigned long long)par->fb_base_phys, (ulong)par->mapped_vram);
-	dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
-		(unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
-
-	ret = mb862xx_pci_gdc_init(par);
-	if (ret)
-		goto io_unmap;
-
-	ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
-			  DRV_NAME, (void *)par);
-	if (ret) {
-		dev_err(dev, "Cannot request irq\n");
-		goto io_unmap;
-	}
-
-	mb862xxfb_init_fbinfo(info);
-
-	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
-		dev_err(dev, "Could not allocate cmap for fb_info.\n");
-		ret = -ENOMEM;
-		goto free_irq;
-	}
-
-	if ((info->fbops->fb_set_par)(info))
-		dev_err(dev, "set_var() failed on initial setup?\n");
-
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		dev_err(dev, "failed to register framebuffer\n");
-		goto rel_cmap;
-	}
-
-	pci_set_drvdata(pdev, info);
-
-	if (device_create_file(dev, &dev_attr_dispregs))
-		dev_err(dev, "Can't create sysfs regdump file\n");
-
-	if (par->type == BT_CARMINE)
-		outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN);
-	else
-		outreg(host, GC_IMASK, GC_INT_EN);
-
-	return 0;
-
-rel_cmap:
-	fb_dealloc_cmap(&info->cmap);
-free_irq:
-	free_irq(par->irq, (void *)par);
-io_unmap:
-	iounmap(par->mmio_base);
-fb_unmap:
-	iounmap(par->fb_base);
-rel_reg:
-	pci_release_regions(pdev);
-rel_fb:
-	framebuffer_release(info);
-dis_dev:
-	pci_disable_device(pdev);
-out:
-	return ret;
-}
-
-static void mb862xx_pci_remove(struct pci_dev *pdev)
-{
-	struct fb_info *fbi = pci_get_drvdata(pdev);
-	struct mb862xxfb_par *par = fbi->par;
-	unsigned long reg;
-
-	dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
-
-	/* display off */
-	reg = inreg(disp, GC_DCM1);
-	reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
-	outreg(disp, GC_DCM1, reg);
-
-	if (par->type == BT_CARMINE) {
-		outreg(ctrl, GC_CTRL_INT_MASK, 0);
-		outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
-	} else {
-		outreg(host, GC_IMASK, 0);
-	}
-
-	mb862xx_i2c_exit(par);
-
-	device_remove_file(&pdev->dev, &dev_attr_dispregs);
-
-	unregister_framebuffer(fbi);
-	fb_dealloc_cmap(&fbi->cmap);
-
-	free_irq(par->irq, (void *)par);
-	iounmap(par->mmio_base);
-	iounmap(par->fb_base);
-
-	pci_release_regions(pdev);
-	framebuffer_release(fbi);
-	pci_disable_device(pdev);
-}
-
-static struct pci_driver mb862xxfb_pci_driver = {
-	.name		= DRV_NAME,
-	.id_table	= mb862xx_pci_tbl,
-	.probe		= mb862xx_pci_probe,
-	.remove		= mb862xx_pci_remove,
-};
-#endif
-
-static int mb862xxfb_init(void)
-{
-	int ret = -ENODEV;
-
-#if defined(CONFIG_FB_MB862XX_LIME)
-	ret = platform_driver_register(&of_platform_mb862xxfb_driver);
-#endif
-#if defined(CONFIG_FB_MB862XX_PCI_GDC)
-	ret = pci_register_driver(&mb862xxfb_pci_driver);
-#endif
-	return ret;
-}
-
-static void __exit mb862xxfb_exit(void)
-{
-#if defined(CONFIG_FB_MB862XX_LIME)
-	platform_driver_unregister(&of_platform_mb862xxfb_driver);
-#endif
-#if defined(CONFIG_FB_MB862XX_PCI_GDC)
-	pci_unregister_driver(&mb862xxfb_pci_driver);
-#endif
-}
-
-module_init(mb862xxfb_init);
-module_exit(mb862xxfb_exit);
-
-MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver");
-MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/mbx/Makefile b/drivers/video/mbx/Makefile
deleted file mode 100644
index 16c1165cf9c7..000000000000
--- a/drivers/video/mbx/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# Makefile for the 2700G controller driver.
-
-obj-$(CONFIG_FB_MBX)	   += mbxfb.o
-obj-$(CONFIG_FB_MBX_DEBUG) += mbxfbdebugfs.o
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
deleted file mode 100644
index 4449f249b0e7..000000000000
--- a/drivers/video/mbx/mbxdebugfs.c
+++ /dev/null
@@ -1,251 +0,0 @@
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-
-#define BIG_BUFFER_SIZE	(1024)
-
-static char big_buffer[BIG_BUFFER_SIZE];
-
-struct mbxfb_debugfs_data {
-	struct dentry *dir;
-	struct dentry *sysconf;
-	struct dentry *clock;
-	struct dentry *display;
-	struct dentry *gsctl;
-	struct dentry *sdram;
-	struct dentry *misc;
-};
-
-static int open_file_generic(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->u.generic_ip;
-	return 0;
-}
-
-static ssize_t write_file_dummy(struct file *file, const char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	return count;
-}
-
-static ssize_t sysconf_read_file(struct file *file, char __user *userbuf,
-				 size_t count, loff_t *ppos)
-{
-	char * s = big_buffer;
-
-	s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG));
-	s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE));
-	s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL));
-	s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG));
-	s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST));
-
-	return  simple_read_from_buffer(userbuf, count, ppos,
-					big_buffer, s-big_buffer);
-}
-
-
-static ssize_t gsctl_read_file(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	char * s = big_buffer;
-
-	s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL));
-	s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL));
-	s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE));
-	s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE));
-	s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL));
-	s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK));
-	s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR));
-	s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR));
-	s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE));
-	s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE));
-	s += sprintf(s, "GSADR = %08x\n", readl(GSADR));
-	s += sprintf(s, "VSADR = %08x\n", readl(VSADR));
-	s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL));
-	s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE));
-	s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS));
-	s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR));
-	s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK));
-	s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT));
-
-	return  simple_read_from_buffer(userbuf, count, ppos,
-					big_buffer, s-big_buffer);
-}
-
-static ssize_t display_read_file(struct file *file, char __user *userbuf,
-				 size_t count, loff_t *ppos)
-{
-	char * s = big_buffer;
-
-	s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL));
-	s += sprintf(s, "DHT01 = %08x\n", readl(DHT01));
-	s += sprintf(s, "DHT02 = %08x\n", readl(DHT02));
-	s += sprintf(s, "DHT03 = %08x\n", readl(DHT03));
-	s += sprintf(s, "DVT01 = %08x\n", readl(DVT01));
-	s += sprintf(s, "DVT02 = %08x\n", readl(DVT02));
-	s += sprintf(s, "DVT03 = %08x\n", readl(DVT03));
-	s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL));
-	s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR));
-	s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS));
-	s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE));
-	s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT));
-	s += sprintf(s, "DSIG = %08x\n", readl(DSIG));
-	s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL));
-	s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL));
-	s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL));
-	s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL));
-	s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS));
-	s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL));
-	s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM));
-	s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL));
-	s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL));
-	s += sprintf(s, "DHDET = %08x\n", readl(DHDET));
-	s += sprintf(s, "DVDET = %08x\n", readl(DVDET));
-	s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK));
-	s += sprintf(s, "CSC01 = %08x\n", readl(CSC01));
-	s += sprintf(s, "CSC02 = %08x\n", readl(CSC02));
-	s += sprintf(s, "CSC03 = %08x\n", readl(CSC03));
-	s += sprintf(s, "CSC04 = %08x\n", readl(CSC04));
-	s += sprintf(s, "CSC05 = %08x\n", readl(CSC05));
-
-	return  simple_read_from_buffer(userbuf, count, ppos,
-					big_buffer, s-big_buffer);
-}
-
-static ssize_t clock_read_file(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	char * s = big_buffer;
-
-	s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC));
-	s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC));
-	s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP));
-	s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL));
-	s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL));
-	s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT));
-	s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK));
-	s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK));
-	s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK));
-	s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK));
-	s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK));
-	s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK));
-	s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV));
-
-	return  simple_read_from_buffer(userbuf, count, ppos,
-					big_buffer, s-big_buffer);
-}
-
-static ssize_t sdram_read_file(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	char * s = big_buffer;
-
-	s += sprintf(s, "LMRST = %08x\n", readl(LMRST));
-	s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG));
-	s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR));
-	s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT));
-	s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR));
-	s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE));
-	s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM));
-	s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH));
-	s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN));
-	s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX));
-	s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG));
-	s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR));
-
-	return  simple_read_from_buffer(userbuf, count, ppos,
-					big_buffer, s-big_buffer);
-}
-
-static ssize_t misc_read_file(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	char * s = big_buffer;
-
-	s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG));
-	s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR));
-	s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT));
-	s += sprintf(s, "ID = %08x\n", readl(ID));
-
-	return  simple_read_from_buffer(userbuf, count, ppos,
-					big_buffer, s-big_buffer);
-}
-
-
-static const struct file_operations sysconf_fops = {
-	.read = sysconf_read_file,
-	.write = write_file_dummy,
-	.open = open_file_generic,
-	.llseek = default_llseek,
-};
-
-static const struct file_operations clock_fops = {
-	.read = clock_read_file,
-	.write = write_file_dummy,
-	.open = open_file_generic,
-	.llseek = default_llseek,
-};
-
-static const struct file_operations display_fops = {
-	.read = display_read_file,
-	.write = write_file_dummy,
-	.open = open_file_generic,
-	.llseek = default_llseek,
-};
-
-static const struct file_operations gsctl_fops = {
-	.read = gsctl_read_file,
-	.write = write_file_dummy,
-	.open = open_file_generic,
-	.llseek = default_llseek,
-};
-
-static const struct file_operations sdram_fops = {
-	.read = sdram_read_file,
-	.write = write_file_dummy,
-	.open = open_file_generic,
-	.llseek = default_llseek,
-};
-
-static const struct file_operations misc_fops = {
-	.read = misc_read_file,
-	.write = write_file_dummy,
-	.open = open_file_generic,
-	.llseek = default_llseek,
-};
-
-static void mbxfb_debugfs_init(struct fb_info *fbi)
-{
-	struct mbxfb_info *mfbi = fbi->par;
-	struct mbxfb_debugfs_data *dbg;
-
-	dbg = kzalloc(sizeof(struct mbxfb_debugfs_data), GFP_KERNEL);
-	mfbi->debugfs_data = dbg;
-
-	dbg->dir = debugfs_create_dir("mbxfb", NULL);
-	dbg->sysconf = debugfs_create_file("sysconf", 0444, dbg->dir,
-				      fbi, &sysconf_fops);
-	dbg->clock = debugfs_create_file("clock", 0444, dbg->dir,
-				    fbi, &clock_fops);
-	dbg->display = debugfs_create_file("display", 0444, dbg->dir,
-				      fbi, &display_fops);
-	dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir,
-				    fbi, &gsctl_fops);
-	dbg->sdram = debugfs_create_file("sdram", 0444, dbg->dir,
-					fbi, &sdram_fops);
-	dbg->misc = debugfs_create_file("misc", 0444, dbg->dir,
-					fbi, &misc_fops);
-}
-
-static void mbxfb_debugfs_remove(struct fb_info *fbi)
-{
-	struct mbxfb_info *mfbi = fbi->par;
-	struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data;
-
-	debugfs_remove(dbg->misc);
-	debugfs_remove(dbg->sdram);
-	debugfs_remove(dbg->gsctl);
-	debugfs_remove(dbg->display);
-	debugfs_remove(dbg->clock);
-	debugfs_remove(dbg->sysconf);
-	debugfs_remove(dbg->dir);
-}
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
deleted file mode 100644
index f0a5392f5fd3..000000000000
--- a/drivers/video/mbx/mbxfb.c
+++ /dev/null
@@ -1,1053 +0,0 @@
-/*
- *  linux/drivers/video/mbx/mbxfb.c
- *
- *  Copyright (C) 2006-2007 8D Technologies inc
- *  Raphael Assenat <raph@8d.com>
- *  	- Added video overlay support
- *  	- Various improvements
- *
- *  Copyright (C) 2006 Compulab, Ltd.
- *  Mike Rapoport <mike@compulab.co.il>
- *  	- Creation of driver
- *
- *   Based on pxafb.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- *   Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver
- *
- */
-
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-
-#include <video/mbxfb.h>
-
-#include "regs.h"
-#include "reg_bits.h"
-
-static void __iomem *virt_base_2700;
-
-#define write_reg(val, reg) do { writel((val), (reg)); } while(0)
-
-/* Without this delay, the graphics appears somehow scaled and
- * there is a lot of jitter in scanlines. This delay is probably
- * needed only after setting some specific register(s) somewhere,
- * not all over the place... */
-#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0)
-
-#define MIN_XRES	16
-#define MIN_YRES	16
-#define MAX_XRES	2048
-#define MAX_YRES	2048
-
-#define MAX_PALETTES	16
-
-/* FIXME: take care of different chip revisions with different sizes
-   of ODFB */
-#define MEMORY_OFFSET	0x60000
-
-struct mbxfb_info {
-	struct device *dev;
-
-	struct resource *fb_res;
-	struct resource *fb_req;
-
-	struct resource *reg_res;
-	struct resource *reg_req;
-
-	void __iomem *fb_virt_addr;
-	unsigned long fb_phys_addr;
-
-	void __iomem *reg_virt_addr;
-	unsigned long reg_phys_addr;
-
-	int (*platform_probe) (struct fb_info * fb);
-	int (*platform_remove) (struct fb_info * fb);
-
-	u32 pseudo_palette[MAX_PALETTES];
-#ifdef CONFIG_FB_MBX_DEBUG
-	void *debugfs_data;
-#endif
-
-};
-
-static struct fb_var_screeninfo mbxfb_default = {
-	.xres = 640,
-	.yres = 480,
-	.xres_virtual = 640,
-	.yres_virtual = 480,
-	.bits_per_pixel = 16,
-	.red = {11, 5, 0},
-	.green = {5, 6, 0},
-	.blue = {0, 5, 0},
-	.activate = FB_ACTIVATE_TEST,
-	.height = -1,
-	.width = -1,
-	.pixclock = 40000,
-	.left_margin = 48,
-	.right_margin = 16,
-	.upper_margin = 33,
-	.lower_margin = 10,
-	.hsync_len = 96,
-	.vsync_len = 2,
-	.vmode = FB_VMODE_NONINTERLACED,
-	.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-};
-
-static struct fb_fix_screeninfo mbxfb_fix = {
-	.id = "MBX",
-	.type = FB_TYPE_PACKED_PIXELS,
-	.visual = FB_VISUAL_TRUECOLOR,
-	.xpanstep = 0,
-	.ypanstep = 0,
-	.ywrapstep = 0,
-	.accel = FB_ACCEL_NONE,
-};
-
-struct pixclock_div {
-	u8 m;
-	u8 n;
-	u8 p;
-};
-
-static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps,
-				       struct pixclock_div *div)
-{
-	u8 m, n, p;
-	unsigned int err = 0;
-	unsigned int min_err = ~0x0;
-	unsigned int clk;
-	unsigned int best_clk = 0;
-	unsigned int ref_clk = 13000;	/* FIXME: take from platform data */
-	unsigned int pixclock;
-
-	/* convert pixclock to KHz */
-	pixclock = PICOS2KHZ(pixclock_ps);
-
-	/* PLL output freq = (ref_clk * M) / (N * 2^P)
-	 *
-	 * M: 1 to 63
-	 * N: 1 to 7
-	 * P: 0 to 7
-	 */
-
-	/* RAPH: When N==1, the resulting pixel clock appears to
-	 * get divided by 2. Preventing N=1 by starting the following
-	 * loop at 2 prevents this. Is this a bug with my chip
-	 * revision or something I dont understand? */
-	for (m = 1; m < 64; m++) {
-		for (n = 2; n < 8; n++) {
-			for (p = 0; p < 8; p++) {
-				clk = (ref_clk * m) / (n * (1 << p));
-				err = (clk > pixclock) ? (clk - pixclock) :
-					(pixclock - clk);
-				if (err < min_err) {
-					min_err = err;
-					best_clk = clk;
-					div->m = m;
-					div->n = n;
-					div->p = p;
-				}
-			}
-		}
-	}
-	return KHZ2PICOS(best_clk);
-}
-
-static int mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int trans, struct fb_info *info)
-{
-	u32 val, ret = 1;
-
-	if (regno < MAX_PALETTES) {
-		u32 *pal = info->pseudo_palette;
-
-		val = (red & 0xf800) | ((green & 0xfc00) >> 5) |
-			((blue & 0xf800) >> 11);
-		pal[regno] = val;
-		ret = 0;
-	}
-
-	return ret;
-}
-
-static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct pixclock_div div;
-
-	var->pixclock = mbxfb_get_pixclock(var->pixclock, &div);
-
-	if (var->xres < MIN_XRES)
-		var->xres = MIN_XRES;
-	if (var->yres < MIN_YRES)
-		var->yres = MIN_YRES;
-	if (var->xres > MAX_XRES)
-		return -EINVAL;
-	if (var->yres > MAX_YRES)
-		return -EINVAL;
-	var->xres_virtual = max(var->xres_virtual, var->xres);
-	var->yres_virtual = max(var->yres_virtual, var->yres);
-
-	switch (var->bits_per_pixel) {
-		/* 8 bits-per-pixel is not supported yet */
-	case 8:
-		return -EINVAL;
-	case 16:
-		var->green.length = (var->green.length == 5) ? 5 : 6;
-		var->red.length = 5;
-		var->blue.length = 5;
-		var->transp.length = 6 - var->green.length;
-		var->blue.offset = 0;
-		var->green.offset = 5;
-		var->red.offset = 5 + var->green.length;
-		var->transp.offset = (5 + var->red.offset) & 15;
-		break;
-	case 24:		/* RGB 888   */
-	case 32:		/* RGBA 8888 */
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.length = var->bits_per_pixel - 24;
-		var->transp.offset = (var->transp.length) ? 24 : 0;
-		break;
-	}
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	return 0;
-}
-
-static int mbxfb_set_par(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-	struct pixclock_div div;
-	ushort hbps, ht, hfps, has;
-	ushort vbps, vt, vfps, vas;
-	u32 gsctrl = readl(GSCTRL);
-	u32 gsadr = readl(GSADR);
-
-	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
-
-	/* setup color mode */
-	gsctrl &= ~(FMsk(GSCTRL_GPIXFMT));
-	/* FIXME: add *WORKING* support for 8-bits per color */
-	if (info->var.bits_per_pixel == 8) {
-		return -EINVAL;
-	} else {
-		fb_dealloc_cmap(&info->cmap);
-		gsctrl &= ~GSCTRL_LUT_EN;
-
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		switch (info->var.bits_per_pixel) {
-		case 16:
-			if (info->var.green.length == 5)
-				gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
-			else
-				gsctrl |= GSCTRL_GPIXFMT_RGB565;
-			break;
-		case 24:
-			gsctrl |= GSCTRL_GPIXFMT_RGB888;
-			break;
-		case 32:
-			gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
-			break;
-		}
-	}
-
-	/* setup resolution */
-	gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT));
-	gsctrl |= Gsctrl_Width(info->var.xres) |
-		Gsctrl_Height(info->var.yres);
-	write_reg_dly(gsctrl, GSCTRL);
-
-	gsadr &= ~(FMsk(GSADR_SRCSTRIDE));
-	gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel /
-				 (8 * 16) - 1);
-	write_reg_dly(gsadr, GSADR);
-
-	/* setup timings */
-	var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div);
-
-	write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
-		Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL);
-
-	hbps = var->hsync_len;
-	has = hbps + var->left_margin;
-	hfps = has + var->xres;
-	ht = hfps + var->right_margin;
-
-	vbps = var->vsync_len;
-	vas = vbps + var->upper_margin;
-	vfps = vas + var->yres;
-	vt = vfps + var->lower_margin;
-
-	write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
-	write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
-	write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
-	write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
-
-	write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
-	write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
-	write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
-	write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
-	write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
-
-	write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
-
-	write_reg_dly(DINTRE_VEVENT0_EN, DINTRE);
-
-	return 0;
-}
-
-static int mbxfb_blank(int blank, struct fb_info *info)
-{
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
-		write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
-		write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
-		break;
-	case FB_BLANK_UNBLANK:
-		write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
-		write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
-		break;
-	}
-	return 0;
-}
-
-static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
-{
-	u32 vsctrl, vscadr, vsadr;
-	u32 sssize, spoctrl, shctrl;
-	u32 vubase, vvbase;
-	u32 vovrclk;
-
-	if (set->scaled_width==0 || set->scaled_height==0)
-		return -EINVAL;
-
-	/* read registers which have reserved bits
-	 * so we can write them back as-is. */
-	vovrclk = readl(VOVRCLK);
-	vsctrl = readl(VSCTRL);
-	vscadr = readl(VSCADR);
-	vubase = readl(VUBASE);
-	vvbase = readl(VVBASE);
-	shctrl = readl(SHCTRL);
-
-	spoctrl = readl(SPOCTRL);
-	sssize = readl(SSSIZE);
-
-	vsctrl &= ~(	FMsk(VSCTRL_VSWIDTH) |
-					FMsk(VSCTRL_VSHEIGHT) |
-					FMsk(VSCTRL_VPIXFMT) |
-					VSCTRL_GAMMA_EN | VSCTRL_CSC_EN |
-					VSCTRL_COSITED );
-	vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) |
-				VSCTRL_CSC_EN;
-
-	vscadr &= ~(VSCADR_STR_EN | FMsk(VSCADR_VBASE_ADR) );
-	vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR));
-	vvbase &= ~(FMsk(VVBASE_VBASE_ADR));
-
-	switch (set->fmt) {
-	case MBXFB_FMT_YUV16:
-		vsctrl |= VSCTRL_VPIXFMT_YUV12;
-
-		set->Y_stride = ((set->width) + 0xf ) & ~0xf;
-		break;
-	case MBXFB_FMT_YUV12:
-		vsctrl |= VSCTRL_VPIXFMT_YUV12;
-
-		set->Y_stride = ((set->width) + 0xf ) & ~0xf;
-		vubase |= VUBASE_UVHALFSTR;
-
-		break;
-	case MBXFB_FMT_UY0VY1:
-		vsctrl |= VSCTRL_VPIXFMT_UY0VY1;
-		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
-		break;
-	case MBXFB_FMT_VY0UY1:
-		vsctrl |= VSCTRL_VPIXFMT_VY0UY1;
-		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
-		break;
-	case MBXFB_FMT_Y0UY1V:
-		vsctrl |= VSCTRL_VPIXFMT_Y0UY1V;
-		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
-		break;
-	case MBXFB_FMT_Y0VY1U:
-		vsctrl |= VSCTRL_VPIXFMT_Y0VY1U;
-		set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
-			break;
-	default:
-		return -EINVAL;
-	}
-
-	/* VSCTRL has the bits which sets the Video Pixel Format.
-	 * When passing from a packed to planar format,
-	 * if we write VSCTRL first, VVBASE and VUBASE would
-	 * be zero if we would not set them here. (And then,
-	 * the chips hangs and only a reset seems to fix it).
-	 *
-	 * If course, the values calculated here have no meaning
-	 * for packed formats.
-	 */
-	set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7;
-		set->U_offset = set->height * set->Y_stride;
-		set->V_offset = set->U_offset +
-						set->height * set->UV_stride;
-	vubase |= Vubase_Ubase_Adr(
-			(0x60000 + set->mem_offset + set->U_offset)>>3);
-	vvbase |= Vvbase_Vbase_Adr(
-			(0x60000 + set->mem_offset + set->V_offset)>>3);
-
-
-	vscadr |= Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4);
-
-	if (set->enable)
-		vscadr |= VSCADR_STR_EN;
-
-
-	vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) |
-		Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y);
-
-	sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT));
-	sssize = Sssize_Sc_Width(set->scaled_width-1) |
-			Sssize_Sc_Height(set->scaled_height-1);
-
-	spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP |
-			SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C |
-			FMsk(SPOCTRL_VPITCH));
-	spoctrl |= Spoctrl_Vpitch((set->height<<11)/set->scaled_height);
-
-	/* Bypass horiz/vert scaler when same size */
-	if (set->scaled_width == set->width)
-		spoctrl |= SPOCTRL_H_SC_BP;
-	if (set->scaled_height == set->height)
-		spoctrl |= SPOCTRL_V_SC_BP;
-
-	shctrl &= ~(FMsk(SHCTRL_HPITCH) | SHCTRL_HDECIM);
-	shctrl |= Shctrl_Hpitch((set->width<<11)/set->scaled_width);
-
-	/* Video plane registers */
-	write_reg(vsctrl, VSCTRL);
-	write_reg(vscadr, VSCADR);
-	write_reg(vubase, VUBASE);
-	write_reg(vvbase, VVBASE);
-	write_reg(vsadr, VSADR);
-
-	/* Video scaler registers */
-	write_reg(sssize, SSSIZE);
-	write_reg(spoctrl, SPOCTRL);
-	write_reg(shctrl, SHCTRL);
-
-	/* Clock */
-	if (set->enable)
-		vovrclk |= 1;
-	else
-		vovrclk &= ~1;
-
-	write_reg(vovrclk, VOVRCLK);
-
-	return 0;
-}
-
-static int mbxfb_ioctl_planeorder(struct mbxfb_planeorder *porder)
-{
-	unsigned long gscadr, vscadr;
-
-	if (porder->bottom == porder->top)
-		return -EINVAL;
-
-	gscadr = readl(GSCADR);
-	vscadr = readl(VSCADR);
-
-	gscadr &= ~(FMsk(GSCADR_BLEND_POS));
-	vscadr &= ~(FMsk(VSCADR_BLEND_POS));
-
-	switch (porder->bottom) {
-	case MBXFB_PLANE_GRAPHICS:
-		gscadr |= GSCADR_BLEND_GFX;
-		break;
-	case MBXFB_PLANE_VIDEO:
-		vscadr |= VSCADR_BLEND_GFX;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (porder->top) {
-	case MBXFB_PLANE_GRAPHICS:
-		gscadr |= GSCADR_BLEND_VID;
-		break;
-	case MBXFB_PLANE_VIDEO:
-		vscadr |= GSCADR_BLEND_VID;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	write_reg_dly(vscadr, VSCADR);
-	write_reg_dly(gscadr, GSCADR);
-
-	return 0;
-
-}
-
-static int mbxfb_ioctl_alphactl(struct mbxfb_alphaCtl *alpha)
-{
-	unsigned long vscadr, vbbase, vcmsk;
-	unsigned long gscadr, gbbase, gdrctrl;
-
-	vbbase = Vbbase_Glalpha(alpha->overlay_global_alpha) |
-				Vbbase_Colkey(alpha->overlay_colorkey);
-
-	gbbase = Gbbase_Glalpha(alpha->graphics_global_alpha) |
-				Gbbase_Colkey(alpha->graphics_colorkey);
-
-	vcmsk = readl(VCMSK);
-	vcmsk &= ~(FMsk(VCMSK_COLKEY_M));
-	vcmsk |= Vcmsk_colkey_m(alpha->overlay_colorkey_mask);
-
-	gdrctrl = readl(GDRCTRL);
-	gdrctrl &= ~(FMsk(GDRCTRL_COLKEYM));
-	gdrctrl |= Gdrctrl_Colkeym(alpha->graphics_colorkey_mask);
-
-	vscadr = readl(VSCADR);
-	vscadr &= ~(FMsk(VSCADR_BLEND_M) | VSCADR_COLKEYSRC | VSCADR_COLKEY_EN);
-
-	gscadr = readl(GSCADR);
-	gscadr &= ~(FMsk(GSCADR_BLEND_M) | GSCADR_COLKEY_EN | GSCADR_COLKEYSRC);
-
-	switch (alpha->overlay_colorkey_mode) {
-	case MBXFB_COLORKEY_DISABLED:
-		break;
-	case MBXFB_COLORKEY_PREVIOUS:
-		vscadr |= VSCADR_COLKEY_EN;
-		break;
-	case MBXFB_COLORKEY_CURRENT:
-		vscadr |= VSCADR_COLKEY_EN | VSCADR_COLKEYSRC;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (alpha->overlay_blend_mode) {
-	case MBXFB_ALPHABLEND_NONE:
-		vscadr |= VSCADR_BLEND_NONE;
-		break;
-	case MBXFB_ALPHABLEND_GLOBAL:
-		vscadr |= VSCADR_BLEND_GLOB;
-		break;
-	case MBXFB_ALPHABLEND_PIXEL:
-		vscadr |= VSCADR_BLEND_PIX;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (alpha->graphics_colorkey_mode) {
-	case MBXFB_COLORKEY_DISABLED:
-		break;
-	case MBXFB_COLORKEY_PREVIOUS:
-		gscadr |= GSCADR_COLKEY_EN;
-		break;
-	case MBXFB_COLORKEY_CURRENT:
-		gscadr |= GSCADR_COLKEY_EN | GSCADR_COLKEYSRC;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (alpha->graphics_blend_mode) {
-	case MBXFB_ALPHABLEND_NONE:
-		gscadr |= GSCADR_BLEND_NONE;
-		break;
-	case MBXFB_ALPHABLEND_GLOBAL:
-		gscadr |= GSCADR_BLEND_GLOB;
-		break;
-	case MBXFB_ALPHABLEND_PIXEL:
-		gscadr |= GSCADR_BLEND_PIX;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	write_reg_dly(vbbase, VBBASE);
-	write_reg_dly(gbbase, GBBASE);
-	write_reg_dly(vcmsk, VCMSK);
-	write_reg_dly(gdrctrl, GDRCTRL);
-	write_reg_dly(gscadr, GSCADR);
-	write_reg_dly(vscadr, VSCADR);
-
-	return 0;
-}
-
-static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd,
-				unsigned long arg)
-{
-	struct mbxfb_overlaySetup	setup;
-	struct mbxfb_planeorder 	porder;
-	struct mbxfb_alphaCtl 		alpha;
-	struct mbxfb_reg			reg;
-	int res;
-	__u32 tmp;
-
-	switch (cmd)
-	{
-		case MBXFB_IOCX_OVERLAY:
-			if (copy_from_user(&setup, (void __user*)arg,
-						sizeof(struct mbxfb_overlaySetup)))
-				return -EFAULT;
-
-			res = mbxfb_setupOverlay(&setup);
-			if (res)
-				return res;
-
-			if (copy_to_user((void __user*)arg, &setup,
-						sizeof(struct mbxfb_overlaySetup)))
-				return -EFAULT;
-
-			return 0;
-
-		case MBXFB_IOCS_PLANEORDER:
-			if (copy_from_user(&porder, (void __user*)arg,
-					sizeof(struct mbxfb_planeorder)))
-			return -EFAULT;
-
-			return mbxfb_ioctl_planeorder(&porder);
-
-		case MBXFB_IOCS_ALPHA:
-			if (copy_from_user(&alpha, (void __user*)arg,
-					sizeof(struct mbxfb_alphaCtl)))
-			return -EFAULT;
-
-			return mbxfb_ioctl_alphactl(&alpha);
-
-		case MBXFB_IOCS_REG:
-			if (copy_from_user(&reg, (void __user*)arg,
-						sizeof(struct mbxfb_reg)))
-				return -EFAULT;
-
-			if (reg.addr >= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
-				return -EINVAL;
-
-			tmp = readl(virt_base_2700 + reg.addr);
-			tmp &= ~reg.mask;
-			tmp |= reg.val & reg.mask;
-			writel(tmp, virt_base_2700 + reg.addr);
-
-			return 0;
-		case MBXFB_IOCX_REG:
-			if (copy_from_user(&reg, (void __user*)arg,
-						sizeof(struct mbxfb_reg)))
-				return -EFAULT;
-
-			if (reg.addr >= 0x10000)	/* regs are from 0x3fe0000 to 0x3feffff */
-				return -EINVAL;
-			reg.val = readl(virt_base_2700 + reg.addr);
-
-			if (copy_to_user((void __user*)arg, &reg,
-						sizeof(struct mbxfb_reg)))
-				return -EFAULT;
-
-			return 0;
-	}
-	return -EINVAL;
-}
-
-static struct fb_ops mbxfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = mbxfb_check_var,
-	.fb_set_par = mbxfb_set_par,
-	.fb_setcolreg = mbxfb_setcolreg,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_blank = mbxfb_blank,
-	.fb_ioctl = mbxfb_ioctl,
-};
-
-/*
-  Enable external SDRAM controller. Assume that all clocks are active
-  by now.
-*/
-static void setup_memc(struct fb_info *fbi)
-{
-	unsigned long tmp;
-	int i;
-
-	/* FIXME: use platform specific parameters */
-	/* setup SDRAM controller */
-	write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
-		LMCFG_LMA_TS),
-	       LMCFG);
-
-	write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
-
-	/* setup SDRAM timings */
-	write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
-		Lmtim_Trc(9) | Lmtim_Tdpl(2)),
-	       LMTIM);
-	/* setup SDRAM refresh rate */
-	write_reg_dly(0xc2b, LMREFRESH);
-	/* setup SDRAM type parameters */
-	write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
-		LMTYPE_COLSZ_8),
-	       LMTYPE);
-	/* enable memory controller */
-	write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
-	/* perform dummy reads */
-	for ( i = 0; i < 16; i++ ) {
-		tmp = readl(fbi->screen_base);
-	}
-}
-
-static void enable_clocks(struct fb_info *fbi)
-{
-	/* enable clocks */
-	write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC);
-	write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC);
-	write_reg_dly(0x00000000, CLKSLEEP);
-
-	/* PLL output = (Frefclk * M) / (N * 2^P )
-	 *
-	 * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
-	 * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
-	 * */
-	write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
-		CORE_PLL_EN),
-	       COREPLL);
-
-	write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
-		DISP_PLL_EN),
-	       DISPPLL);
-
-	write_reg_dly(0x00000000, VOVRCLK);
-	write_reg_dly(PIXCLK_EN, PIXCLK);
-	write_reg_dly(MEMCLK_EN, MEMCLK);
-	write_reg_dly(0x00000001, M24CLK);
-	write_reg_dly(0x00000001, MBXCLK);
-	write_reg_dly(SDCLK_EN, SDCLK);
-	write_reg_dly(0x00000001, PIXCLKDIV);
-}
-
-static void setup_graphics(struct fb_info *fbi)
-{
-	unsigned long gsctrl;
-	unsigned long vscadr;
-
-	gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres) |
-		Gsctrl_Height(fbi->var.yres);
-	switch (fbi->var.bits_per_pixel) {
-	case 16:
-		if (fbi->var.green.length == 5)
-			gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
-		else
-			gsctrl |= GSCTRL_GPIXFMT_RGB565;
-		break;
-	case 24:
-		gsctrl |= GSCTRL_GPIXFMT_RGB888;
-		break;
-	case 32:
-		gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
-		break;
-	}
-
-	write_reg_dly(gsctrl, GSCTRL);
-	write_reg_dly(0x00000000, GBBASE);
-	write_reg_dly(0x00ffffff, GDRCTRL);
-	write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
-	write_reg_dly(0x00000000, GPLUT);
-
-	vscadr = readl(VSCADR);
-	vscadr &= ~(FMsk(VSCADR_BLEND_POS) | FMsk(VSCADR_BLEND_M));
-	vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_NONE;
-	write_reg_dly(vscadr, VSCADR);
-}
-
-static void setup_display(struct fb_info *fbi)
-{
-	unsigned long dsctrl = 0;
-
-	dsctrl = DSCTRL_BLNK_POL;
-	if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		dsctrl |= DSCTRL_HS_POL;
-	if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		dsctrl |= DSCTRL_VS_POL;
-	write_reg_dly(dsctrl, DSCTRL);
-	write_reg_dly(0xd0303010, DMCTRL);
-	write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
-}
-
-static void enable_controller(struct fb_info *fbi)
-{
-	u32 svctrl, shctrl;
-
-	write_reg_dly(SYSRST_RST, SYSRST);
-
-	/* setup a timeout, raise drive strength */
-	write_reg_dly(0xffffff0c, SYSCFG);
-
-	enable_clocks(fbi);
-	setup_memc(fbi);
-	setup_graphics(fbi);
-	setup_display(fbi);
-
-	shctrl = readl(SHCTRL);
-	shctrl &= ~(FMsk(SHCTRL_HINITIAL));
-	shctrl |= Shctrl_Hinitial(4<<11);
-	writel(shctrl, SHCTRL);
-
-	svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
-	writel(svctrl, SVCTRL);
-
-	writel(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | SPOCTRL_VORDER_4TAP
-			, SPOCTRL);
-
-	/* Those coefficients are good for scaling up. For scaling
-	 * down, the application has to calculate them. */
-	write_reg(0xff000100, VSCOEFF0);
-	write_reg(0xfdfcfdfe, VSCOEFF1);
-	write_reg(0x170d0500, VSCOEFF2);
-	write_reg(0x3d372d22, VSCOEFF3);
-	write_reg(0x00000040, VSCOEFF4);
-
-	write_reg(0xff010100, HSCOEFF0);
-	write_reg(0x00000000, HSCOEFF1);
-	write_reg(0x02010000, HSCOEFF2);
-	write_reg(0x01020302, HSCOEFF3);
-	write_reg(0xf9fbfe00, HSCOEFF4);
-	write_reg(0xfbf7f6f7, HSCOEFF5);
-	write_reg(0x1c110700, HSCOEFF6);
-	write_reg(0x3e393127, HSCOEFF7);
-	write_reg(0x00000040, HSCOEFF8);
-
-}
-
-#ifdef CONFIG_PM
-/*
- * Power management hooks.  Note that we won't be called from IRQ context,
- * unlike the blank functions above, so we may sleep.
- */
-static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	/* make frame buffer memory enter self-refresh mode */
-	write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
-	while (readl(LMPWRSTAT) != LMPWRSTAT_MC_PWR_SRM)
-		; /* empty statement */
-
-	/* reset the device, since it's initial state is 'mostly sleeping' */
-	write_reg_dly(SYSRST_RST, SYSRST);
-	return 0;
-}
-
-static int mbxfb_resume(struct platform_device *dev)
-{
-	struct fb_info *fbi = platform_get_drvdata(dev);
-
-	enable_clocks(fbi);
-/* 	setup_graphics(fbi); */
-/* 	setup_display(fbi); */
-
-	write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
-	return 0;
-}
-#else
-#define mbxfb_suspend	NULL
-#define mbxfb_resume	NULL
-#endif
-
-/* debugfs entries */
-#ifndef CONFIG_FB_MBX_DEBUG
-#define mbxfb_debugfs_init(x)	do {} while(0)
-#define mbxfb_debugfs_remove(x)	do {} while(0)
-#endif
-
-#define res_size(_r) (((_r)->end - (_r)->start) + 1)
-
-static int mbxfb_probe(struct platform_device *dev)
-{
-	int ret;
-	struct fb_info *fbi;
-	struct mbxfb_info *mfbi;
-	struct mbxfb_platform_data *pdata;
-
-	dev_dbg(&dev->dev, "mbxfb_probe\n");
-
-	pdata = dev_get_platdata(&dev->dev);
-	if (!pdata) {
-		dev_err(&dev->dev, "platform data is required\n");
-		return -EINVAL;
-	}
-
-	fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev);
-	if (fbi == NULL) {
-		dev_err(&dev->dev, "framebuffer_alloc failed\n");
-		return -ENOMEM;
-	}
-
-	mfbi = fbi->par;
-	fbi->pseudo_palette = mfbi->pseudo_palette;
-
-
-	if (pdata->probe)
-		mfbi->platform_probe = pdata->probe;
-	if (pdata->remove)
-		mfbi->platform_remove = pdata->remove;
-
-	mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
-
-	if (!mfbi->fb_res || !mfbi->reg_res) {
-		dev_err(&dev->dev, "no resources found\n");
-		ret = -ENODEV;
-		goto err1;
-	}
-
-	mfbi->fb_req = request_mem_region(mfbi->fb_res->start,
-					  res_size(mfbi->fb_res), dev->name);
-	if (mfbi->fb_req == NULL) {
-		dev_err(&dev->dev, "failed to claim framebuffer memory\n");
-		ret = -EINVAL;
-		goto err1;
-	}
-	mfbi->fb_phys_addr = mfbi->fb_res->start;
-
-	mfbi->reg_req = request_mem_region(mfbi->reg_res->start,
-					   res_size(mfbi->reg_res), dev->name);
-	if (mfbi->reg_req == NULL) {
-		dev_err(&dev->dev, "failed to claim Marathon registers\n");
-		ret = -EINVAL;
-		goto err2;
-	}
-	mfbi->reg_phys_addr = mfbi->reg_res->start;
-
-	mfbi->reg_virt_addr = devm_ioremap_nocache(&dev->dev,
-						   mfbi->reg_phys_addr,
-						   res_size(mfbi->reg_req));
-	if (!mfbi->reg_virt_addr) {
-		dev_err(&dev->dev, "failed to ioremap Marathon registers\n");
-		ret = -EINVAL;
-		goto err3;
-	}
-	virt_base_2700 = mfbi->reg_virt_addr;
-
-	mfbi->fb_virt_addr = devm_ioremap_nocache(&dev->dev, mfbi->fb_phys_addr,
-						  res_size(mfbi->fb_req));
-	if (!mfbi->fb_virt_addr) {
-		dev_err(&dev->dev, "failed to ioremap frame buffer\n");
-		ret = -EINVAL;
-		goto err3;
-	}
-
-	fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
-	fbi->screen_size = pdata->memsize;
-	fbi->fbops = &mbxfb_ops;
-
-	fbi->var = mbxfb_default;
-	fbi->fix = mbxfb_fix;
-	fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000;
-	fbi->fix.smem_len = pdata->memsize;
-	fbi->fix.line_length = mbxfb_default.xres_virtual *
-					mbxfb_default.bits_per_pixel / 8;
-
-	ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
-	if (ret < 0) {
-		dev_err(&dev->dev, "fb_alloc_cmap failed\n");
-		ret = -EINVAL;
-		goto err3;
-	}
-
-	platform_set_drvdata(dev, fbi);
-
-	fb_info(fbi, "mbx frame buffer device\n");
-
-	if (mfbi->platform_probe)
-		mfbi->platform_probe(fbi);
-
-	enable_controller(fbi);
-
-	mbxfb_debugfs_init(fbi);
-
-	ret = register_framebuffer(fbi);
-	if (ret < 0) {
-		dev_err(&dev->dev, "register_framebuffer failed\n");
-		ret = -EINVAL;
-		goto err6;
-	}
-
-	return 0;
-
-err6:
-	fb_dealloc_cmap(&fbi->cmap);
-err3:
-	release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));
-err2:
-	release_mem_region(mfbi->fb_res->start, res_size(mfbi->fb_res));
-err1:
-	framebuffer_release(fbi);
-
-	return ret;
-}
-
-static int mbxfb_remove(struct platform_device *dev)
-{
-	struct fb_info *fbi = platform_get_drvdata(dev);
-
-	write_reg_dly(SYSRST_RST, SYSRST);
-
-	mbxfb_debugfs_remove(fbi);
-
-	if (fbi) {
-		struct mbxfb_info *mfbi = fbi->par;
-
-		unregister_framebuffer(fbi);
-		if (mfbi) {
-			if (mfbi->platform_remove)
-				mfbi->platform_remove(fbi);
-
-
-			if (mfbi->reg_req)
-				release_mem_region(mfbi->reg_req->start,
-						   res_size(mfbi->reg_req));
-			if (mfbi->fb_req)
-				release_mem_region(mfbi->fb_req->start,
-						   res_size(mfbi->fb_req));
-		}
-		framebuffer_release(fbi);
-	}
-
-	return 0;
-}
-
-static struct platform_driver mbxfb_driver = {
-	.probe = mbxfb_probe,
-	.remove = mbxfb_remove,
-	.suspend = mbxfb_suspend,
-	.resume = mbxfb_resume,
-	.driver = {
-		.name = "mbx-fb",
-	},
-};
-
-module_platform_driver(mbxfb_driver);
-
-MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
-MODULE_AUTHOR("Mike Rapoport, Compulab");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h
deleted file mode 100644
index 5f14b4befd71..000000000000
--- a/drivers/video/mbx/reg_bits.h
+++ /dev/null
@@ -1,613 +0,0 @@
-#ifndef __REG_BITS_2700G_
-#define __REG_BITS_2700G_
-
-/* use defines from asm-arm/arch-pxa/bitfields.h for bit fields access */
-#define UData(Data)	((unsigned long) (Data))
-#define Fld(Size, Shft)	(((Size) << 16) + (Shft))
-#define FSize(Field)	((Field) >> 16)
-#define FShft(Field)	((Field) & 0x0000FFFF)
-#define FMsk(Field)	(((UData (1) << FSize (Field)) - 1) << FShft (Field))
-#define FAlnMsk(Field)	((UData (1) << FSize (Field)) - 1)
-#define F1stBit(Field)	(UData (1) << FShft (Field))
-
-#define SYSRST_RST	(1 << 0)
-
-/* SYSCLKSRC - SYSCLK Source Control Register */
-#define SYSCLKSRC_SEL	Fld(2,0)
-#define SYSCLKSRC_REF	((0x0) << FShft(SYSCLKSRC_SEL))
-#define SYSCLKSRC_PLL_1	((0x1) << FShft(SYSCLKSRC_SEL))
-#define SYSCLKSRC_PLL_2	((0x2) << FShft(SYSCLKSRC_SEL))
-
-/* PIXCLKSRC - PIXCLK Source Control Register */
-#define PIXCLKSRC_SEL	Fld(2,0)
-#define PIXCLKSRC_REF	((0x0) << FShft(PIXCLKSRC_SEL))
-#define PIXCLKSRC_PLL_1	((0x1) << FShft(PIXCLKSRC_SEL))
-#define PIXCLKSRC_PLL_2	((0x2) << FShft(PIXCLKSRC_SEL))
-
-/* Clock Disable Register */
-#define CLKSLEEP_SLP	(1 << 0)
-
-/* Core PLL Control Register */
-#define CORE_PLL_M	Fld(6,7)
-#define Core_Pll_M(x)	((x) << FShft(CORE_PLL_M))
-#define CORE_PLL_N	Fld(3,4)
-#define Core_Pll_N(x)	((x) << FShft(CORE_PLL_N))
-#define CORE_PLL_P	Fld(3,1)
-#define Core_Pll_P(x)	((x) << FShft(CORE_PLL_P))
-#define CORE_PLL_EN	(1 << 0)
-
-/* Display PLL Control Register */
-#define DISP_PLL_M	Fld(6,7)
-#define Disp_Pll_M(x)	((x) << FShft(DISP_PLL_M))
-#define DISP_PLL_N	Fld(3,4)
-#define Disp_Pll_N(x)	((x) << FShft(DISP_PLL_N))
-#define DISP_PLL_P	Fld(3,1)
-#define Disp_Pll_P(x)	((x) << FShft(DISP_PLL_P))
-#define DISP_PLL_EN	(1 << 0)
-
-/* PLL status register */
-#define PLLSTAT_CORE_PLL_LOST_L	(1 << 3)
-#define PLLSTAT_CORE_PLL_LSTS	(1 << 2)
-#define PLLSTAT_DISP_PLL_LOST_L	(1 << 1)
-#define PLLSTAT_DISP_PLL_LSTS	(1 << 0)
-
-/* Video and scale clock control register */
-#define VOVRCLK_EN	(1 << 0)
-
-/* Pixel clock control register */
-#define PIXCLK_EN	(1 << 0)
-
-/* Memory clock control register */
-#define MEMCLK_EN	(1 << 0)
-
-/* MBX clock control register */
-#define MBXCLK_DIV	Fld(2,2)
-#define MBXCLK_DIV_1	((0x0) << FShft(MBXCLK_DIV))
-#define MBXCLK_DIV_2	((0x1) << FShft(MBXCLK_DIV))
-#define MBXCLK_DIV_3	((0x2) << FShft(MBXCLK_DIV))
-#define MBXCLK_DIV_4	((0x3) << FShft(MBXCLK_DIV))
-#define MBXCLK_EN	Fld(2,0)
-#define MBXCLK_EN_NONE	((0x0) << FShft(MBXCLK_EN))
-#define MBXCLK_EN_2D	((0x1) << FShft(MBXCLK_EN))
-#define MBXCLK_EN_BOTH	((0x2) << FShft(MBXCLK_EN))
-
-/* M24 clock control register */
-#define M24CLK_DIV	Fld(2,1)
-#define M24CLK_DIV_1	((0x0) << FShft(M24CLK_DIV))
-#define M24CLK_DIV_2	((0x1) << FShft(M24CLK_DIV))
-#define M24CLK_DIV_3	((0x2) << FShft(M24CLK_DIV))
-#define M24CLK_DIV_4	((0x3) << FShft(M24CLK_DIV))
-#define M24CLK_EN	(1 << 0)
-
-/* SDRAM clock control register */
-#define SDCLK_EN	(1 << 0)
-
-/* PixClk Divisor Register */
-#define PIXCLKDIV_PD	Fld(9,0)
-#define Pixclkdiv_Pd(x)	((x) << FShft(PIXCLKDIV_PD))
-
-/* LCD Config control register */
-#define LCDCFG_IN_FMT	Fld(3,28)
-#define Lcdcfg_In_Fmt(x)	((x) << FShft(LCDCFG_IN_FMT))
-#define LCDCFG_LCD1DEN_POL	(1 << 27)
-#define LCDCFG_LCD1FCLK_POL	(1 << 26)
-#define LCDCFG_LCD1LCLK_POL	(1 << 25)
-#define LCDCFG_LCD1D_POL	(1 << 24)
-#define LCDCFG_LCD2DEN_POL	(1 << 23)
-#define LCDCFG_LCD2FCLK_POL	(1 << 22)
-#define LCDCFG_LCD2LCLK_POL	(1 << 21)
-#define LCDCFG_LCD2D_POL	(1 << 20)
-#define LCDCFG_LCD1_TS		(1 << 19)
-#define LCDCFG_LCD1D_DS		(1 << 18)
-#define LCDCFG_LCD1C_DS		(1 << 17)
-#define LCDCFG_LCD1_IS_IN	(1 << 16)
-#define LCDCFG_LCD2_TS		(1 << 3)
-#define LCDCFG_LCD2D_DS		(1 << 2)
-#define LCDCFG_LCD2C_DS		(1 << 1)
-#define LCDCFG_LCD2_IS_IN	(1 << 0)
-
-/* On-Die Frame Buffer Power Control Register */
-#define ODFBPWR_SLOW	(1 << 2)
-#define ODFBPWR_MODE	Fld(2,0)
-#define ODFBPWR_MODE_ACT	((0x0) << FShft(ODFBPWR_MODE))
-#define ODFBPWR_MODE_ACT_LP	((0x1) << FShft(ODFBPWR_MODE))
-#define ODFBPWR_MODE_SLEEP	((0x2) << FShft(ODFBPWR_MODE))
-#define ODFBPWR_MODE_SHUTD	((0x3) << FShft(ODFBPWR_MODE))
-
-/* On-Die Frame Buffer Power State Status Register */
-#define ODFBSTAT_ACT	(1 << 2)
-#define ODFBSTAT_SLP	(1 << 1)
-#define ODFBSTAT_SDN	(1 << 0)
-
-/* LMRST - Local Memory (SDRAM) Reset */
-#define LMRST_MC_RST	(1 << 0)
-
-/* LMCFG - Local Memory (SDRAM) Configuration Register */
-#define LMCFG_LMC_DS	(1 << 5)
-#define LMCFG_LMD_DS	(1 << 4)
-#define LMCFG_LMA_DS	(1 << 3)
-#define LMCFG_LMC_TS	(1 << 2)
-#define LMCFG_LMD_TS	(1 << 1)
-#define LMCFG_LMA_TS	(1 << 0)
-
-/* LMPWR - Local Memory (SDRAM) Power Control Register */
-#define LMPWR_MC_PWR_CNT	Fld(2,0)
-#define LMPWR_MC_PWR_ACT	((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */
-#define LMPWR_MC_PWR_SRM	((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */
-#define LMPWR_MC_PWR_DPD	((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */
-
-/* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */
-#define LMPWRSTAT_MC_PWR_CNT	Fld(2,0)
-#define LMPWRSTAT_MC_PWR_ACT	((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */
-#define LMPWRSTAT_MC_PWR_SRM	((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */
-#define LMPWRSTAT_MC_PWR_DPD	((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */
-
-/* LMTYPE - Local Memory (SDRAM) Type Register */
-#define LMTYPE_CASLAT	Fld(3,10)
-#define LMTYPE_CASLAT_1	((0x1) << FShft(LMTYPE_CASLAT))
-#define LMTYPE_CASLAT_2	((0x2) << FShft(LMTYPE_CASLAT))
-#define LMTYPE_CASLAT_3	((0x3) << FShft(LMTYPE_CASLAT))
-#define LMTYPE_BKSZ	Fld(2,8)
-#define LMTYPE_BKSZ_1	((0x1) << FShft(LMTYPE_BKSZ))
-#define LMTYPE_BKSZ_2	((0x2) << FShft(LMTYPE_BKSZ))
-#define LMTYPE_ROWSZ	Fld(4,4)
-#define LMTYPE_ROWSZ_11	((0xb) << FShft(LMTYPE_ROWSZ))
-#define LMTYPE_ROWSZ_12	((0xc) << FShft(LMTYPE_ROWSZ))
-#define LMTYPE_ROWSZ_13	((0xd) << FShft(LMTYPE_ROWSZ))
-#define LMTYPE_COLSZ	Fld(4,0)
-#define LMTYPE_COLSZ_7	((0x7) << FShft(LMTYPE_COLSZ))
-#define LMTYPE_COLSZ_8	((0x8) << FShft(LMTYPE_COLSZ))
-#define LMTYPE_COLSZ_9	((0x9) << FShft(LMTYPE_COLSZ))
-#define LMTYPE_COLSZ_10	((0xa) << FShft(LMTYPE_COLSZ))
-#define LMTYPE_COLSZ_11	((0xb) << FShft(LMTYPE_COLSZ))
-#define LMTYPE_COLSZ_12	((0xc) << FShft(LMTYPE_COLSZ))
-
-/* LMTIM - Local Memory (SDRAM) Timing Register */
-#define LMTIM_TRAS	Fld(4,16)
-#define Lmtim_Tras(x)	((x) << FShft(LMTIM_TRAS))
-#define LMTIM_TRP	Fld(4,12)
-#define Lmtim_Trp(x)	((x) << FShft(LMTIM_TRP))
-#define LMTIM_TRCD	Fld(4,8)
-#define Lmtim_Trcd(x)	((x) << FShft(LMTIM_TRCD))
-#define LMTIM_TRC	Fld(4,4)
-#define Lmtim_Trc(x)	((x) << FShft(LMTIM_TRC))
-#define LMTIM_TDPL	Fld(4,0)
-#define Lmtim_Tdpl(x)	((x) << FShft(LMTIM_TDPL))
-
-/* LMREFRESH - Local Memory (SDRAM) tREF Control Register */
-#define LMREFRESH_TREF	Fld(2,0)
-#define Lmrefresh_Tref(x)	((x) << FShft(LMREFRESH_TREF))
-
-/* GSCTRL - Graphics surface control register */
-#define GSCTRL_LUT_EN	(1 << 31)
-#define GSCTRL_GPIXFMT	Fld(4,27)
-#define GSCTRL_GPIXFMT_INDEXED	((0x0) << FShft(GSCTRL_GPIXFMT))
-#define GSCTRL_GPIXFMT_ARGB4444	((0x4) << FShft(GSCTRL_GPIXFMT))
-#define GSCTRL_GPIXFMT_ARGB1555	((0x5) << FShft(GSCTRL_GPIXFMT))
-#define GSCTRL_GPIXFMT_RGB888	((0x6) << FShft(GSCTRL_GPIXFMT))
-#define GSCTRL_GPIXFMT_RGB565	((0x7) << FShft(GSCTRL_GPIXFMT))
-#define GSCTRL_GPIXFMT_ARGB8888	((0x8) << FShft(GSCTRL_GPIXFMT))
-#define GSCTRL_GAMMA_EN	(1 << 26)
-
-#define GSCTRL_GSWIDTH Fld(11,11)
-#define Gsctrl_Width(Pixel)	/* Display Width [1..2048 pix.]  */ \
-                        (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH))
-
-#define GSCTRL_GSHEIGHT Fld(11,0)
-#define Gsctrl_Height(Pixel)	/* Display Height [1..2048 pix.]  */ \
-                        (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT))
-
-/* GBBASE fileds */
-#define GBBASE_GLALPHA Fld(8,24)
-#define Gbbase_Glalpha(x)	((x) << FShft(GBBASE_GLALPHA))
-
-#define GBBASE_COLKEY Fld(24,0)
-#define Gbbase_Colkey(x)	((x) << FShft(GBBASE_COLKEY))
-
-/* GDRCTRL fields */
-#define GDRCTRL_PIXDBL	(1 << 31)
-#define GDRCTRL_PIXHLV	(1 << 30)
-#define GDRCTRL_LNDBL	(1 << 29)
-#define GDRCTRL_LNHLV	(1 << 28)
-#define GDRCTRL_COLKEYM	Fld(24,0)
-#define Gdrctrl_Colkeym(x)	((x) << FShft(GDRCTRL_COLKEYM))
-
-/* GSCADR graphics stream control address register fields */
-#define GSCADR_STR_EN	(1 << 31)
-#define GSCADR_COLKEY_EN	(1 << 30)
-#define GSCADR_COLKEYSRC	(1 << 29)
-#define GSCADR_BLEND_M	Fld(2,27)
-#define GSCADR_BLEND_NONE	((0x0) << FShft(GSCADR_BLEND_M))
-#define GSCADR_BLEND_INV	((0x1) << FShft(GSCADR_BLEND_M))
-#define GSCADR_BLEND_GLOB	((0x2) << FShft(GSCADR_BLEND_M))
-#define GSCADR_BLEND_PIX	((0x3) << FShft(GSCADR_BLEND_M))
-#define GSCADR_BLEND_POS	Fld(2,24)
-#define GSCADR_BLEND_GFX	((0x0) << FShft(GSCADR_BLEND_POS))
-#define GSCADR_BLEND_VID	((0x1) << FShft(GSCADR_BLEND_POS))
-#define GSCADR_BLEND_CUR	((0x2) << FShft(GSCADR_BLEND_POS))
-#define GSCADR_GBASE_ADR	Fld(23,0)
-#define Gscadr_Gbase_Adr(x)	((x) << FShft(GSCADR_GBASE_ADR))
-
-/* GSADR graphics stride address register fields */
-#define GSADR_SRCSTRIDE	Fld(10,22)
-#define Gsadr_Srcstride(x)	((x) << FShft(GSADR_SRCSTRIDE))
-#define GSADR_XSTART	Fld(11,11)
-#define Gsadr_Xstart(x)		((x) << FShft(GSADR_XSTART))
-#define GSADR_YSTART	Fld(11,0)
-#define Gsadr_Ystart(y)		((y) << FShft(GSADR_YSTART))
-
-/* GPLUT graphics palette register fields */
-#define GPLUT_LUTADR	Fld(8,24)
-#define Gplut_Lutadr(x)	((x) << FShft(GPLUT_LUTADR))
-#define GPLUT_LUTDATA	Fld(24,0)
-#define Gplut_Lutdata(x)	((x) << FShft(GPLUT_LUTDATA))
-
-/* VSCTRL - Video Surface Control Register */
-#define VSCTRL_VPIXFMT		Fld(4,27)
-#define VSCTRL_VPIXFMT_YUV12	((0x9) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_UY0VY1	((0xc) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_VY0UY1	((0xd) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_Y0UY1V	((0xe) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_Y0VY1U	((0xf) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_GAMMA_EN		(1 << 26)
-#define VSCTRL_CSC_EN		(1 << 25)
-#define VSCTRL_COSITED		(1 << 22)
-#define VSCTRL_VSWIDTH		Fld(11,11)
-#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \
-			(((Pixels) - 1) << FShft(VSCTRL_VSWIDTH))
-#define VSCTRL_VSHEIGHT		Fld(11,0)
-#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \
-			(((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT))
-
-/* VBBASE - Video Blending Base Register */
-#define VBBASE_GLALPHA		Fld(8,24)
-#define Vbbase_Glalpha(x)	((x) << FShft(VBBASE_GLALPHA))
-
-#define VBBASE_COLKEY		Fld(24,0)
-#define Vbbase_Colkey(x)	((x) << FShft(VBBASE_COLKEY))
-
-/* VCMSK - Video Color Key Mask Register */
-#define VCMSK_COLKEY_M		Fld(24,0)
-#define Vcmsk_colkey_m(x)	((x) << FShft(VCMSK_COLKEY_M))
-
-/* VSCADR - Video Stream Control Rddress Register */
-#define VSCADR_STR_EN		(1 << 31)
-#define VSCADR_COLKEY_EN	(1 << 30)
-#define VSCADR_COLKEYSRC	(1 << 29)
-#define VSCADR_BLEND_M		Fld(2,27)
-#define VSCADR_BLEND_NONE	((0x0) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_INV	((0x1) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_GLOB	((0x2) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_PIX	((0x3) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_POS	Fld(2,24)
-#define VSCADR_BLEND_GFX	((0x0) << FShft(VSCADR_BLEND_POS))
-#define VSCADR_BLEND_VID	((0x1) << FShft(VSCADR_BLEND_POS))
-#define VSCADR_BLEND_CUR	((0x2) << FShft(VSCADR_BLEND_POS))
-#define VSCADR_VBASE_ADR	Fld(23,0)
-#define Vscadr_Vbase_Adr(x)	((x) << FShft(VSCADR_VBASE_ADR))
-
-/* VUBASE - Video U Base Register */
-#define VUBASE_UVHALFSTR	(1 << 31)
-#define VUBASE_UBASE_ADR	Fld(24,0)
-#define Vubase_Ubase_Adr(x)	((x) << FShft(VUBASE_UBASE_ADR))
-
-/* VVBASE - Video V Base Register */
-#define VVBASE_VBASE_ADR	Fld(24,0)
-#define Vvbase_Vbase_Adr(x)	((x) << FShft(VVBASE_VBASE_ADR))
-
-/* VSADR - Video Stride Address Register */
-#define VSADR_SRCSTRIDE		Fld(10,22)
-#define Vsadr_Srcstride(x)	((x) << FShft(VSADR_SRCSTRIDE))
-#define VSADR_XSTART		Fld(11,11)
-#define Vsadr_Xstart(x)		((x) << FShft(VSADR_XSTART))
-#define VSADR_YSTART		Fld(11,0)
-#define Vsadr_Ystart(x)		((x) << FShft(VSADR_YSTART))
-
-/* VSCTRL - Video Surface Control Register */
-#define VSCTRL_VPIXFMT		Fld(4,27)
-#define VSCTRL_VPIXFMT_YUV12	((0x9) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_UY0VY1	((0xc) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_VY0UY1	((0xd) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_Y0UY1V	((0xe) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_VPIXFMT_Y0VY1U	((0xf) << FShft(VSCTRL_VPIXFMT))
-#define VSCTRL_GAMMA_EN		(1 << 26)
-#define VSCTRL_CSC_EN		(1 << 25)
-#define VSCTRL_COSITED		(1 << 22)
-#define VSCTRL_VSWIDTH		Fld(11,11)
-#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \
-			(((Pixels) - 1) << FShft(VSCTRL_VSWIDTH))
-#define VSCTRL_VSHEIGHT		Fld(11,0)
-#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \
-			(((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT))
-
-/* VBBASE - Video Blending Base Register */
-#define VBBASE_GLALPHA		Fld(8,24)
-#define Vbbase_Glalpha(x)	((x) << FShft(VBBASE_GLALPHA))
-
-#define VBBASE_COLKEY		Fld(24,0)
-#define Vbbase_Colkey(x)	((x) << FShft(VBBASE_COLKEY))
-
-/* VCMSK - Video Color Key Mask Register */
-#define VCMSK_COLKEY_M		Fld(24,0)
-#define Vcmsk_colkey_m(x)	((x) << FShft(VCMSK_COLKEY_M))
-
-/* VSCADR - Video Stream Control Rddress Register */
-#define VSCADR_STR_EN		(1 << 31)
-#define VSCADR_COLKEY_EN	(1 << 30)
-#define VSCADR_COLKEYSRC	(1 << 29)
-#define VSCADR_BLEND_M		Fld(2,27)
-#define VSCADR_BLEND_NONE	((0x0) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_INV	((0x1) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_GLOB	((0x2) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_PIX	((0x3) << FShft(VSCADR_BLEND_M))
-#define VSCADR_BLEND_POS	Fld(2,24)
-#define VSCADR_BLEND_GFX	((0x0) << FShft(VSCADR_BLEND_POS))
-#define VSCADR_BLEND_VID	((0x1) << FShft(VSCADR_BLEND_POS))
-#define VSCADR_BLEND_CUR	((0x2) << FShft(VSCADR_BLEND_POS))
-#define VSCADR_VBASE_ADR	Fld(23,0)
-#define Vscadr_Vbase_Adr(x)	((x) << FShft(VSCADR_VBASE_ADR))
-
-/* VUBASE - Video U Base Register */
-#define VUBASE_UVHALFSTR	(1 << 31)
-#define VUBASE_UBASE_ADR	Fld(24,0)
-#define Vubase_Ubase_Adr(x)	((x) << FShft(VUBASE_UBASE_ADR))
-
-/* VVBASE - Video V Base Register */
-#define VVBASE_VBASE_ADR	Fld(24,0)
-#define Vvbase_Vbase_Adr(x)	((x) << FShft(VVBASE_VBASE_ADR))
-
-/* VSADR - Video Stride Address Register */
-#define VSADR_SRCSTRIDE		Fld(10,22)
-#define Vsadr_Srcstride(x)	((x) << FShft(VSADR_SRCSTRIDE))
-#define VSADR_XSTART		Fld(11,11)
-#define Vsadr_Xstart(x)		((x) << FShft(VSADR_XSTART))
-#define VSADR_YSTART		Fld(11,0)
-#define Vsadr_Ystart(x)		((x) << FShft(VSADR_YSTART))
-
-/* HCCTRL - Hardware Cursor Register fields */
-#define HCCTRL_CUR_EN	(1 << 31)
-#define HCCTRL_COLKEY_EN	(1 << 29)
-#define HCCTRL_COLKEYSRC	(1 << 28)
-#define HCCTRL_BLEND_M	Fld(2,26)
-#define HCCTRL_BLEND_NONE	((0x0) << FShft(HCCTRL_BLEND_M))
-#define HCCTRL_BLEND_INV	((0x1) << FShft(HCCTRL_BLEND_M))
-#define HCCTRL_BLEND_GLOB	((0x2) << FShft(HCCTRL_BLEND_M))
-#define HCCTRL_BLEND_PIX	((0x3) << FShft(HCCTRL_BLEND_M))
-#define HCCTRL_CPIXFMT	Fld(3,23)
-#define HCCTRL_CPIXFMT_RGB332	((0x3) << FShft(HCCTRL_CPIXFMT))
-#define HCCTRL_CPIXFMT_ARGB4444	((0x4) << FShft(HCCTRL_CPIXFMT))
-#define HCCTRL_CPIXFMT_ARGB1555	((0x5) << FShft(HCCTRL_CPIXFMT))
-#define HCCTRL_CBASE_ADR	Fld(23,0)
-#define Hcctrl_Cbase_Adr(x)	((x) << FShft(HCCTRL_CBASE_ADR))
-
-/* HCSIZE Hardware Cursor Size Register fields */
-#define HCSIZE_BLEND_POS	Fld(2,29)
-#define HCSIZE_BLEND_GFX	((0x0) << FShft(HCSIZE_BLEND_POS))
-#define HCSIZE_BLEND_VID	((0x1) << FShft(HCSIZE_BLEND_POS))
-#define HCSIZE_BLEND_CUR	((0x2) << FShft(HCSIZE_BLEND_POS))
-#define HCSIZE_CWIDTH	Fld(3,16)
-#define Hcsize_Cwidth(x)	((x) << FShft(HCSIZE_CWIDTH))
-#define HCSIZE_CHEIGHT	Fld(3,0)
-#define Hcsize_Cheight(x)	((x) << FShft(HCSIZE_CHEIGHT))
-
-/* HCPOS Hardware Cursor Position Register fields */
-#define HCPOS_SWITCHSRC	(1 << 30)
-#define HCPOS_CURBLINK	Fld(6,24)
-#define Hcpos_Curblink(x)	((x) << FShft(HCPOS_CURBLINK))
-#define HCPOS_XSTART	Fld(12,12)
-#define Hcpos_Xstart(x)	((x) << FShft(HCPOS_XSTART))
-#define HCPOS_YSTART	Fld(12,0)
-#define Hcpos_Ystart(y)	((y) << FShft(HCPOS_YSTART))
-
-/* HCBADR Hardware Cursor Blend Address Register */
-#define HCBADR_GLALPHA	Fld(8,24)
-#define Hcbadr_Glalpha(x)	((x) << FShft(HCBADR_GLALPHA))
-#define HCBADR_COLKEY	Fld(24,0)
-#define Hcbadr_Colkey(x)	((x) << FShft(HCBADR_COLKEY))
-
-/* HCCKMSK - Hardware Cursor Color Key Mask Register */
-#define HCCKMSK_COLKEY_M	Fld(24,0)
-#define Hcckmsk_Colkey_M(x)	((x) << FShft(HCCKMSK_COLKEY_M))
-
-/* DSCTRL - Display sync control register */
-#define DSCTRL_SYNCGEN_EN	(1 << 31)
-#define DSCTRL_DPL_RST		(1 << 29)
-#define DSCTRL_PWRDN_M		(1 << 28)
-#define DSCTRL_UPDSYNCCNT	(1 << 26)
-#define DSCTRL_UPDINTCNT	(1 << 25)
-#define DSCTRL_UPDCNT		(1 << 24)
-#define DSCTRL_UPDWAIT	Fld(4,16)
-#define Dsctrl_Updwait(x)	((x) << FShft(DSCTRL_UPDWAIT))
-#define DSCTRL_CLKPOL		(1 << 11)
-#define DSCTRL_CSYNC_EN		(1 << 10)
-#define DSCTRL_VS_SLAVE		(1 << 7)
-#define DSCTRL_HS_SLAVE		(1 << 6)
-#define DSCTRL_BLNK_POL		(1 << 5)
-#define DSCTRL_BLNK_DIS		(1 << 4)
-#define DSCTRL_VS_POL		(1 << 3)
-#define DSCTRL_VS_DIS		(1 << 2)
-#define DSCTRL_HS_POL		(1 << 1)
-#define DSCTRL_HS_DIS		(1 << 0)
-
-/* DHT01 - Display horizontal timing register 01 */
-#define DHT01_HBPS	Fld(12,16)
-#define Dht01_Hbps(x)	((x) << FShft(DHT01_HBPS))
-#define DHT01_HT	Fld(12,0)
-#define Dht01_Ht(x)	((x) << FShft(DHT01_HT))
-
-/* DHT02 - Display horizontal timing register 02 */
-#define DHT02_HAS	Fld(12,16)
-#define Dht02_Has(x)	((x) << FShft(DHT02_HAS))
-#define DHT02_HLBS	Fld(12,0)
-#define Dht02_Hlbs(x)	((x) << FShft(DHT02_HLBS))
-
-/* DHT03 - Display horizontal timing register 03 */
-#define DHT03_HFPS	Fld(12,16)
-#define Dht03_Hfps(x)	((x) << FShft(DHT03_HFPS))
-#define DHT03_HRBS	Fld(12,0)
-#define Dht03_Hrbs(x)	((x) << FShft(DHT03_HRBS))
-
-/* DVT01 - Display vertical timing register 01 */
-#define DVT01_VBPS	Fld(12,16)
-#define Dvt01_Vbps(x)	((x) << FShft(DVT01_VBPS))
-#define DVT01_VT	Fld(12,0)
-#define Dvt01_Vt(x)	((x) << FShft(DVT01_VT))
-
-/* DVT02 - Display vertical timing register 02 */
-#define DVT02_VAS	Fld(12,16)
-#define Dvt02_Vas(x)	((x) << FShft(DVT02_VAS))
-#define DVT02_VTBS	Fld(12,0)
-#define Dvt02_Vtbs(x)	((x) << FShft(DVT02_VTBS))
-
-/* DVT03 - Display vertical timing register 03 */
-#define DVT03_VFPS	Fld(12,16)
-#define Dvt03_Vfps(x)	((x) << FShft(DVT03_VFPS))
-#define DVT03_VBBS	Fld(12,0)
-#define Dvt03_Vbbs(x)	((x) << FShft(DVT03_VBBS))
-
-/* DVECTRL - display vertical event control register */
-#define DVECTRL_VEVENT	Fld(12,16)
-#define Dvectrl_Vevent(x)	((x) << FShft(DVECTRL_VEVENT))
-#define DVECTRL_VFETCH	Fld(12,0)
-#define Dvectrl_Vfetch(x)	((x) << FShft(DVECTRL_VFETCH))
-
-/* DHDET - display horizontal DE timing register */
-#define DHDET_HDES	Fld(12,16)
-#define Dhdet_Hdes(x)	((x) << FShft(DHDET_HDES))
-#define DHDET_HDEF	Fld(12,0)
-#define Dhdet_Hdef(x)	((x) << FShft(DHDET_HDEF))
-
-/* DVDET - display vertical DE timing register */
-#define DVDET_VDES	Fld(12,16)
-#define Dvdet_Vdes(x)	((x) << FShft(DVDET_VDES))
-#define DVDET_VDEF	Fld(12,0)
-#define Dvdet_Vdef(x)	((x) << FShft(DVDET_VDEF))
-
-/* DODMSK - display output data mask register */
-#define DODMSK_MASK_LVL	(1 << 31)
-#define DODMSK_BLNK_LVL	(1 << 30)
-#define DODMSK_MASK_B	Fld(8,16)
-#define Dodmsk_Mask_B(x)	((x) << FShft(DODMSK_MASK_B))
-#define DODMSK_MASK_G	Fld(8,8)
-#define Dodmsk_Mask_G(x)	((x) << FShft(DODMSK_MASK_G))
-#define DODMSK_MASK_R	Fld(8,0)
-#define Dodmsk_Mask_R(x)	((x) << FShft(DODMSK_MASK_R))
-
-/* DBCOL - display border color control register */
-#define DBCOL_BORDCOL	Fld(24,0)
-#define Dbcol_Bordcol(x)	((x) << FShft(DBCOL_BORDCOL))
-
-/* DVLNUM - display vertical line number register */
-#define DVLNUM_VLINE	Fld(12,0)
-#define Dvlnum_Vline(x)	((x) << FShft(DVLNUM_VLINE))
-
-/* DMCTRL - Display Memory Control Register */
-#define DMCTRL_MEM_REF	Fld(2,30)
-#define DMCTRL_MEM_REF_ACT	((0x0) << FShft(DMCTRL_MEM_REF))
-#define DMCTRL_MEM_REF_HB	((0x1) << FShft(DMCTRL_MEM_REF))
-#define DMCTRL_MEM_REF_VB	((0x2) << FShft(DMCTRL_MEM_REF))
-#define DMCTRL_MEM_REF_BOTH	((0x3) << FShft(DMCTRL_MEM_REF))
-#define DMCTRL_UV_THRHLD	Fld(6,24)
-#define Dmctrl_Uv_Thrhld(x)	((x) << FShft(DMCTRL_UV_THRHLD))
-#define DMCTRL_V_THRHLD		Fld(7,16)
-#define Dmctrl_V_Thrhld(x)	((x) << FShft(DMCTRL_V_THRHLD))
-#define DMCTRL_D_THRHLD		Fld(7,8)
-#define Dmctrl_D_Thrhld(x)	((x) << FShft(DMCTRL_D_THRHLD))
-#define DMCTRL_BURSTLEN	Fld(6,0)
-#define Dmctrl_Burstlen(x)	((x) << FShft(DMCTRL_BURSTLEN))
-
-/* DINTRS - Display Interrupt Status Register */
-#define DINTRS_CUR_OR_S		(1 << 18)
-#define DINTRS_STR2_OR_S	(1 << 17)
-#define DINTRS_STR1_OR_S	(1 << 16)
-#define DINTRS_CUR_UR_S		(1 << 6)
-#define DINTRS_STR2_UR_S	(1 << 5)
-#define DINTRS_STR1_UR_S	(1 << 4)
-#define DINTRS_VEVENT1_S	(1 << 3)
-#define DINTRS_VEVENT0_S	(1 << 2)
-#define DINTRS_HBLNK1_S		(1 << 1)
-#define DINTRS_HBLNK0_S		(1 << 0)
-
-/* DINTRE - Display Interrupt Enable Register */
-#define DINTRE_CUR_OR_EN	(1 << 18)
-#define DINTRE_STR2_OR_EN	(1 << 17)
-#define DINTRE_STR1_OR_EN	(1 << 16)
-#define DINTRE_CUR_UR_EN	(1 << 6)
-#define DINTRE_STR2_UR_EN	(1 << 5)
-#define DINTRE_STR1_UR_EN	(1 << 4)
-#define DINTRE_VEVENT1_EN	(1 << 3)
-#define DINTRE_VEVENT0_EN	(1 << 2)
-#define DINTRE_HBLNK1_EN	(1 << 1)
-#define DINTRE_HBLNK0_EN	(1 << 0)
-
-/* DINTRS - Display Interrupt Status Register */
-#define DINTRS_CUR_OR_S		(1 << 18)
-#define DINTRS_STR2_OR_S	(1 << 17)
-#define DINTRS_STR1_OR_S	(1 << 16)
-#define DINTRS_CUR_UR_S		(1 << 6)
-#define DINTRS_STR2_UR_S	(1 << 5)
-#define DINTRS_STR1_UR_S	(1 << 4)
-#define DINTRS_VEVENT1_S	(1 << 3)
-#define DINTRS_VEVENT0_S	(1 << 2)
-#define DINTRS_HBLNK1_S		(1 << 1)
-#define DINTRS_HBLNK0_S		(1 << 0)
-
-/* DINTRE - Display Interrupt Enable Register */
-#define DINTRE_CUR_OR_EN	(1 << 18)
-#define DINTRE_STR2_OR_EN	(1 << 17)
-#define DINTRE_STR1_OR_EN	(1 << 16)
-#define DINTRE_CUR_UR_EN	(1 << 6)
-#define DINTRE_STR2_UR_EN	(1 << 5)
-#define DINTRE_STR1_UR_EN	(1 << 4)
-#define DINTRE_VEVENT1_EN	(1 << 3)
-#define DINTRE_VEVENT0_EN	(1 << 2)
-#define DINTRE_HBLNK1_EN	(1 << 1)
-#define DINTRE_HBLNK0_EN	(1 << 0)
-
-
-/* DLSTS - display load status register */
-#define DLSTS_RLD_ADONE	(1 << 23)
-/* #define DLSTS_RLD_ADOUT	Fld(23,0) */
-
-/* DLLCTRL - display list load control register */
-#define DLLCTRL_RLD_ADRLN	Fld(8,24)
-#define Dllctrl_Rld_Adrln(x)	((x) << FShft(DLLCTRL_RLD_ADRLN))
-
-/* CLIPCTRL - Clipping Control Register */
-#define CLIPCTRL_HSKIP		Fld(11,16)
-#define Clipctrl_Hskip		((x) << FShft(CLIPCTRL_HSKIP))
-#define CLIPCTRL_VSKIP		Fld(11,0)
-#define Clipctrl_Vskip		((x) << FShft(CLIPCTRL_VSKIP))
-
-/* SPOCTRL - Scale Pitch/Order Control Register */
-#define SPOCTRL_H_SC_BP		(1 << 31)
-#define SPOCTRL_V_SC_BP		(1 << 30)
-#define SPOCTRL_HV_SC_OR	(1 << 29)
-#define SPOCTRL_VS_UR_C		(1 << 27)
-#define SPOCTRL_VORDER		Fld(2,16)
-#define SPOCTRL_VORDER_1TAP	((0x0) << FShft(SPOCTRL_VORDER))
-#define SPOCTRL_VORDER_2TAP	((0x1) << FShft(SPOCTRL_VORDER))
-#define SPOCTRL_VORDER_4TAP	((0x3) << FShft(SPOCTRL_VORDER))
-#define SPOCTRL_VPITCH		Fld(16,0)
-#define Spoctrl_Vpitch(x)	((x) << FShft(SPOCTRL_VPITCH))
-
-/* SVCTRL - Scale Vertical Control Register */
-#define SVCTRL_INITIAL1		Fld(16,16)
-#define Svctrl_Initial1(x)	((x) << FShft(SVCTRL_INITIAL1))
-#define SVCTRL_INITIAL2		Fld(16,0)
-#define Svctrl_Initial2(x)	((x) << FShft(SVCTRL_INITIAL2))
-
-/* SHCTRL - Scale Horizontal Control Register */
-#define SHCTRL_HINITIAL		Fld(16,16)
-#define Shctrl_Hinitial(x)	((x) << FShft(SHCTRL_HINITIAL))
-#define SHCTRL_HDECIM		(1 << 15)
-#define SHCTRL_HPITCH		Fld(15,0)
-#define Shctrl_Hpitch(x)	((x) << FShft(SHCTRL_HPITCH))
-
-/* SSSIZE - Scale Surface Size Register */
-#define SSSIZE_SC_WIDTH		Fld(11,16)
-#define Sssize_Sc_Width(x)	((x) << FShft(SSSIZE_SC_WIDTH))
-#define SSSIZE_SC_HEIGHT	Fld(11,0)
-#define Sssize_Sc_Height(x)	((x) << FShft(SSSIZE_SC_HEIGHT))
-
-#endif /* __REG_BITS_2700G_ */
diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h
deleted file mode 100644
index 063099d48839..000000000000
--- a/drivers/video/mbx/regs.h
+++ /dev/null
@@ -1,195 +0,0 @@
-#ifndef __REGS_2700G_
-#define __REGS_2700G_
-
-/* extern unsigned long virt_base_2700; */
-/* #define __REG_2700G(x)	(*(volatile unsigned long*)((x)+virt_base_2700)) */
-#define __REG_2700G(x)	((x)+virt_base_2700)
-
-/* System Configuration Registers (0x0000_0000  0x0000_0010) */
-#define SYSCFG		__REG_2700G(0x00000000)
-#define PFBASE		__REG_2700G(0x00000004)
-#define PFCEIL		__REG_2700G(0x00000008)
-#define POLLFLAG	__REG_2700G(0x0000000c)
-#define SYSRST		__REG_2700G(0x00000010)
-
-/* Interrupt Control Registers (0x0000_0014  0x0000_002F) */
-#define NINTPW		__REG_2700G(0x00000014)
-#define MINTENABLE	__REG_2700G(0x00000018)
-#define MINTSTAT	__REG_2700G(0x0000001c)
-#define SINTENABLE	__REG_2700G(0x00000020)
-#define SINTSTAT	__REG_2700G(0x00000024)
-#define SINTCLR		__REG_2700G(0x00000028)
-
-/* Clock Control Registers (0x0000_002C  0x0000_005F) */
-#define SYSCLKSRC	__REG_2700G(0x0000002c)
-#define PIXCLKSRC	__REG_2700G(0x00000030)
-#define CLKSLEEP	__REG_2700G(0x00000034)
-#define COREPLL		__REG_2700G(0x00000038)
-#define DISPPLL		__REG_2700G(0x0000003c)
-#define PLLSTAT		__REG_2700G(0x00000040)
-#define VOVRCLK		__REG_2700G(0x00000044)
-#define PIXCLK		__REG_2700G(0x00000048)
-#define MEMCLK		__REG_2700G(0x0000004c)
-#define M24CLK		__REG_2700G(0x00000050)
-#define MBXCLK		__REG_2700G(0x00000054)
-#define SDCLK		__REG_2700G(0x00000058)
-#define PIXCLKDIV	__REG_2700G(0x0000005c)
-
-/* LCD Port Control Register (0x0000_0060  0x0000_006F) */
-#define LCD_CONFIG	__REG_2700G(0x00000060)
-
-/* On-Die Frame Buffer Registers (0x0000_0064  0x0000_006B) */
-#define ODFBPWR		__REG_2700G(0x00000064)
-#define ODFBSTAT	__REG_2700G(0x00000068)
-
-/* GPIO Registers (0x0000_006C  0x0000_007F) */
-#define GPIOCGF		__REG_2700G(0x0000006c)
-#define GPIOHI		__REG_2700G(0x00000070)
-#define GPIOLO		__REG_2700G(0x00000074)
-#define GPIOSTAT	__REG_2700G(0x00000078)
-
-/* Pulse Width Modulator (PWM) Registers (0x0000_0200  0x0000_02FF) */
-#define PWMRST		__REG_2700G(0x00000200)
-#define PWMCFG		__REG_2700G(0x00000204)
-#define PWM0DIV		__REG_2700G(0x00000210)
-#define PWM0DUTY	__REG_2700G(0x00000214)
-#define PWM0PER		__REG_2700G(0x00000218)
-#define PWM1DIV		__REG_2700G(0x00000220)
-#define PWM1DUTY	__REG_2700G(0x00000224)
-#define PWM1PER		__REG_2700G(0x00000228)
-
-/* Identification (ID) Registers (0x0000_0300  0x0000_0FFF) */
-#define ID		__REG_2700G(0x00000FF0)
-
-/* Local Memory (SDRAM) Interface Registers (0x0000_1000  0x0000_1FFF) */
-#define LMRST		__REG_2700G(0x00001000)
-#define LMCFG		__REG_2700G(0x00001004)
-#define LMPWR		__REG_2700G(0x00001008)
-#define LMPWRSTAT	__REG_2700G(0x0000100c)
-#define LMCEMR		__REG_2700G(0x00001010)
-#define LMTYPE		__REG_2700G(0x00001014)
-#define LMTIM		__REG_2700G(0x00001018)
-#define LMREFRESH	__REG_2700G(0x0000101c)
-#define LMPROTMIN	__REG_2700G(0x00001020)
-#define LMPROTMAX	__REG_2700G(0x00001024)
-#define LMPROTCFG	__REG_2700G(0x00001028)
-#define LMPROTERR	__REG_2700G(0x0000102c)
-
-/* Plane Controller Registers (0x0000_2000  0x0000_2FFF) */
-#define GSCTRL		__REG_2700G(0x00002000)
-#define VSCTRL		__REG_2700G(0x00002004)
-#define GBBASE		__REG_2700G(0x00002020)
-#define VBBASE		__REG_2700G(0x00002024)
-#define GDRCTRL		__REG_2700G(0x00002040)
-#define VCMSK		__REG_2700G(0x00002044)
-#define GSCADR		__REG_2700G(0x00002060)
-#define VSCADR		__REG_2700G(0x00002064)
-#define VUBASE		__REG_2700G(0x00002084)
-#define VVBASE		__REG_2700G(0x000020a4)
-#define GSADR		__REG_2700G(0x000020c0)
-#define VSADR		__REG_2700G(0x000020c4)
-#define HCCTRL		__REG_2700G(0x00002100)
-#define HCSIZE		__REG_2700G(0x00002110)
-#define HCPOS		__REG_2700G(0x00002120)
-#define HCBADR		__REG_2700G(0x00002130)
-#define HCCKMSK		__REG_2700G(0x00002140)
-#define GPLUT		__REG_2700G(0x00002150)
-#define DSCTRL		__REG_2700G(0x00002154)
-#define DHT01		__REG_2700G(0x00002158)
-#define DHT02		__REG_2700G(0x0000215c)
-#define DHT03		__REG_2700G(0x00002160)
-#define DVT01		__REG_2700G(0x00002164)
-#define DVT02		__REG_2700G(0x00002168)
-#define DVT03		__REG_2700G(0x0000216c)
-#define DBCOL		__REG_2700G(0x00002170)
-#define BGCOLOR		__REG_2700G(0x00002174)
-#define DINTRS		__REG_2700G(0x00002178)
-#define DINTRE		__REG_2700G(0x0000217c)
-#define DINTRCNT	__REG_2700G(0x00002180)
-#define DSIG		__REG_2700G(0x00002184)
-#define DMCTRL		__REG_2700G(0x00002188)
-#define CLIPCTRL	__REG_2700G(0x0000218c)
-#define SPOCTRL		__REG_2700G(0x00002190)
-#define SVCTRL		__REG_2700G(0x00002194)
-
-/* 0x0000_2198 */
-/* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */
-#define VSCOEFF0	__REG_2700G(0x00002198)
-#define VSCOEFF1	__REG_2700G(0x0000219c)
-#define VSCOEFF2	__REG_2700G(0x000021a0)
-#define VSCOEFF3	__REG_2700G(0x000021a4)
-#define VSCOEFF4	__REG_2700G(0x000021a8)
-
-#define SHCTRL		__REG_2700G(0x000021b0)
-
-/* 0x0000_21B4 */
-/* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */
-#define HSCOEFF0	__REG_2700G(0x000021b4)
-#define HSCOEFF1	__REG_2700G(0x000021b8)
-#define HSCOEFF2	__REG_2700G(0x000021bc)
-#define HSCOEFF3	__REG_2700G(0x000021c0)
-#define HSCOEFF4	__REG_2700G(0x000021c4)
-#define HSCOEFF5	__REG_2700G(0x000021c8)
-#define HSCOEFF6	__REG_2700G(0x000021cc)
-#define HSCOEFF7	__REG_2700G(0x000021d0)
-#define HSCOEFF8	__REG_2700G(0x000021d4)
-
-#define SSSIZE		__REG_2700G(0x000021D8)
-
-/* 0x0000_2200 */
-/* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */
-#define VIDGAM0		__REG_2700G(0x00002200)
-#define VIDGAM1		__REG_2700G(0x00002204)
-#define VIDGAM2		__REG_2700G(0x00002208)
-#define VIDGAM3		__REG_2700G(0x0000220c)
-#define VIDGAM4		__REG_2700G(0x00002210)
-#define VIDGAM5		__REG_2700G(0x00002214)
-#define VIDGAM6		__REG_2700G(0x00002218)
-#define VIDGAM7		__REG_2700G(0x0000221c)
-#define VIDGAM8		__REG_2700G(0x00002220)
-#define VIDGAM9		__REG_2700G(0x00002224)
-#define VIDGAM10	__REG_2700G(0x00002228)
-#define VIDGAM11	__REG_2700G(0x0000222c)
-#define VIDGAM12	__REG_2700G(0x00002230)
-#define VIDGAM13	__REG_2700G(0x00002234)
-#define VIDGAM14	__REG_2700G(0x00002238)
-#define VIDGAM15	__REG_2700G(0x0000223c)
-#define VIDGAM16	__REG_2700G(0x00002240)
-
-/* 0x0000_2250 */
-/* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */
-#define GFXGAM0		__REG_2700G(0x00002250)
-#define GFXGAM1		__REG_2700G(0x00002254)
-#define GFXGAM2		__REG_2700G(0x00002258)
-#define GFXGAM3		__REG_2700G(0x0000225c)
-#define GFXGAM4		__REG_2700G(0x00002260)
-#define GFXGAM5		__REG_2700G(0x00002264)
-#define GFXGAM6		__REG_2700G(0x00002268)
-#define GFXGAM7		__REG_2700G(0x0000226c)
-#define GFXGAM8		__REG_2700G(0x00002270)
-#define GFXGAM9		__REG_2700G(0x00002274)
-#define GFXGAM10	__REG_2700G(0x00002278)
-#define GFXGAM11	__REG_2700G(0x0000227c)
-#define GFXGAM12	__REG_2700G(0x00002280)
-#define GFXGAM13	__REG_2700G(0x00002284)
-#define GFXGAM14	__REG_2700G(0x00002288)
-#define GFXGAM15	__REG_2700G(0x0000228c)
-#define GFXGAM16	__REG_2700G(0x00002290)
-
-#define DLSTS		__REG_2700G(0x00002300)
-#define DLLCTRL		__REG_2700G(0x00002304)
-#define DVLNUM		__REG_2700G(0x00002308)
-#define DUCTRL		__REG_2700G(0x0000230c)
-#define DVECTRL		__REG_2700G(0x00002310)
-#define DHDET		__REG_2700G(0x00002314)
-#define DVDET		__REG_2700G(0x00002318)
-#define DODMSK		__REG_2700G(0x0000231c)
-#define CSC01		__REG_2700G(0x00002330)
-#define CSC02		__REG_2700G(0x00002334)
-#define CSC03		__REG_2700G(0x00002338)
-#define CSC04		__REG_2700G(0x0000233c)
-#define CSC05		__REG_2700G(0x00002340)
-
-#define FB_MEMORY_START	__REG_2700G(0x00060000)
-
-#endif /* __REGS_2700G_ */
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
deleted file mode 100644
index 195cc2db4c2c..000000000000
--- a/drivers/video/metronomefb.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- * linux/drivers/video/metronomefb.c -- FB driver for Metronome controller
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This work was made possible by help and equipment support from E-Ink
- * Corporation. http://www.eink.com/
- *
- * This driver is written to be used with the Metronome display controller.
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions. An example
- * is provided as am200epd.c
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/firmware.h>
-#include <linux/dma-mapping.h>
-#include <linux/uaccess.h>
-#include <linux/irq.h>
-
-#include <video/metronomefb.h>
-
-#include <asm/unaligned.h>
-
-/* Display specific information */
-#define DPY_W 832
-#define DPY_H 622
-
-static int user_wfm_size;
-
-/* frame differs from image. frame includes non-visible pixels */
-struct epd_frame {
-	int fw; /* frame width */
-	int fh; /* frame height */
-	u16 config[4];
-	int wfm_size;
-};
-
-static struct epd_frame epd_frame_table[] = {
-	{
-		.fw = 832,
-		.fh = 622,
-		.config = {
-			15 /* sdlew */
-			| 2 << 8 /* sdosz */
-			| 0 << 11 /* sdor */
-			| 0 << 12 /* sdces */
-			| 0 << 15, /* sdcer */
-			42 /* gdspl */
-			| 1 << 8 /* gdr1 */
-			| 1 << 9 /* sdshr */
-			| 0 << 15, /* gdspp */
-			18 /* gdspw */
-			| 0 << 15, /* dispc */
-			599 /* vdlc */
-			| 0 << 11 /* dsi */
-			| 0 << 12, /* dsic */
-		},
-		.wfm_size = 47001,
-	},
-	{
-		.fw = 1088,
-		.fh = 791,
-		.config = {
-			0x0104,
-			0x031f,
-			0x0088,
-			0x02ff,
-		},
-		.wfm_size = 46770,
-	},
-	{
-		.fw = 1200,
-		.fh = 842,
-		.config = {
-			0x0101,
-			0x030e,
-			0x0012,
-			0x0280,
-		},
-		.wfm_size = 46770,
-	},
-};
-
-static struct fb_fix_screeninfo metronomefb_fix = {
-	.id =		"metronomefb",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_STATIC_PSEUDOCOLOR,
-	.xpanstep =	0,
-	.ypanstep =	0,
-	.ywrapstep =	0,
-	.line_length =	DPY_W,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo metronomefb_var = {
-	.xres		= DPY_W,
-	.yres		= DPY_H,
-	.xres_virtual	= DPY_W,
-	.yres_virtual	= DPY_H,
-	.bits_per_pixel	= 8,
-	.grayscale	= 1,
-	.nonstd		= 1,
-	.red =		{ 4, 3, 0 },
-	.green =	{ 0, 0, 0 },
-	.blue =		{ 0, 0, 0 },
-	.transp =	{ 0, 0, 0 },
-};
-
-/* the waveform structure that is coming from userspace firmware */
-struct waveform_hdr {
-	u8 stuff[32];
-
-	u8 wmta[3];
-	u8 fvsn;
-
-	u8 luts;
-	u8 mc;
-	u8 trc;
-	u8 stuff3;
-
-	u8 endb;
-	u8 swtb;
-	u8 stuff2a[2];
-
-	u8 stuff2b[3];
-	u8 wfm_cs;
-} __attribute__ ((packed));
-
-/* main metronomefb functions */
-static u8 calc_cksum(int start, int end, u8 *mem)
-{
-	u8 tmp = 0;
-	int i;
-
-	for (i = start; i < end; i++)
-		tmp += mem[i];
-
-	return tmp;
-}
-
-static u16 calc_img_cksum(u16 *start, int length)
-{
-	u16 tmp = 0;
-
-	while (length--)
-		tmp += *start++;
-
-	return tmp;
-}
-
-/* here we decode the incoming waveform file and populate metromem */
-static int load_waveform(u8 *mem, size_t size, int m, int t,
-			 struct metronomefb_par *par)
-{
-	int tta;
-	int wmta;
-	int trn = 0;
-	int i;
-	unsigned char v;
-	u8 cksum;
-	int cksum_idx;
-	int wfm_idx, owfm_idx;
-	int mem_idx = 0;
-	struct waveform_hdr *wfm_hdr;
-	u8 *metromem = par->metromem_wfm;
-	struct device *dev = par->info->dev;
-
-	if (user_wfm_size)
-		epd_frame_table[par->dt].wfm_size = user_wfm_size;
-
-	if (size != epd_frame_table[par->dt].wfm_size) {
-		dev_err(dev, "Error: unexpected size %Zd != %d\n", size,
-					epd_frame_table[par->dt].wfm_size);
-		return -EINVAL;
-	}
-
-	wfm_hdr = (struct waveform_hdr *) mem;
-
-	if (wfm_hdr->fvsn != 1) {
-		dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
-		return -EINVAL;
-	}
-	if (wfm_hdr->luts != 0) {
-		dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
-		return -EINVAL;
-	}
-	cksum = calc_cksum(32, 47, mem);
-	if (cksum != wfm_hdr->wfm_cs) {
-		dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
-					wfm_hdr->wfm_cs);
-		return -EINVAL;
-	}
-	wfm_hdr->mc += 1;
-	wfm_hdr->trc += 1;
-	for (i = 0; i < 5; i++) {
-		if (*(wfm_hdr->stuff2a + i) != 0) {
-			dev_err(dev, "Error: unexpected value in padding\n");
-			return -EINVAL;
-		}
-	}
-
-	/* calculating trn. trn is something used to index into
-	the waveform. presumably selecting the right one for the
-	desired temperature. it works out the offset of the first
-	v that exceeds the specified temperature */
-	if ((sizeof(*wfm_hdr) + wfm_hdr->trc) > size)
-		return -EINVAL;
-
-	for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + wfm_hdr->trc; i++) {
-		if (mem[i] > t) {
-			trn = i - sizeof(*wfm_hdr) - 1;
-			break;
-		}
-	}
-
-	/* check temperature range table checksum */
-	cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1;
-	if (cksum_idx > size)
-		return -EINVAL;
-	cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
-	if (cksum != mem[cksum_idx]) {
-		dev_err(dev, "Error: bad temperature range table cksum"
-				" %x != %x\n", cksum, mem[cksum_idx]);
-		return -EINVAL;
-	}
-
-	/* check waveform mode table address checksum */
-	wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
-	cksum_idx = wmta + m*4 + 3;
-	if (cksum_idx > size)
-		return -EINVAL;
-	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
-	if (cksum != mem[cksum_idx]) {
-		dev_err(dev, "Error: bad mode table address cksum"
-				" %x != %x\n", cksum, mem[cksum_idx]);
-		return -EINVAL;
-	}
-
-	/* check waveform temperature table address checksum */
-	tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
-	cksum_idx = tta + trn*4 + 3;
-	if (cksum_idx > size)
-		return -EINVAL;
-	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
-	if (cksum != mem[cksum_idx]) {
-		dev_err(dev, "Error: bad temperature table address cksum"
-			" %x != %x\n", cksum, mem[cksum_idx]);
-		return -EINVAL;
-	}
-
-	/* here we do the real work of putting the waveform into the
-	metromem buffer. this does runlength decoding of the waveform */
-	wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
-	owfm_idx = wfm_idx;
-	if (wfm_idx > size)
-		return -EINVAL;
-	while (wfm_idx < size) {
-		unsigned char rl;
-		v = mem[wfm_idx++];
-		if (v == wfm_hdr->swtb) {
-			while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) &&
-				wfm_idx < size)
-				metromem[mem_idx++] = v;
-
-			continue;
-		}
-
-		if (v == wfm_hdr->endb)
-			break;
-
-		rl = mem[wfm_idx++];
-		for (i = 0; i <= rl; i++)
-			metromem[mem_idx++] = v;
-	}
-
-	cksum_idx = wfm_idx;
-	if (cksum_idx > size)
-		return -EINVAL;
-	cksum = calc_cksum(owfm_idx, cksum_idx, mem);
-	if (cksum != mem[cksum_idx]) {
-		dev_err(dev, "Error: bad waveform data cksum"
-				" %x != %x\n", cksum, mem[cksum_idx]);
-		return -EINVAL;
-	}
-	par->frame_count = (mem_idx/64);
-
-	return 0;
-}
-
-static int metronome_display_cmd(struct metronomefb_par *par)
-{
-	int i;
-	u16 cs;
-	u16 opcode;
-	static u8 borderval;
-
-	/* setup display command
-	we can't immediately set the opcode since the controller
-	will try parse the command before we've set it all up
-	so we just set cs here and set the opcode at the end */
-
-	if (par->metromem_cmd->opcode == 0xCC40)
-		opcode = cs = 0xCC41;
-	else
-		opcode = cs = 0xCC40;
-
-	/* set the args ( 2 bytes ) for display */
-	i = 0;
-	par->metromem_cmd->args[i] = 	1 << 3 /* border update */
-					| ((borderval++ % 4) & 0x0F) << 4
-					| (par->frame_count - 1) << 8;
-	cs += par->metromem_cmd->args[i++];
-
-	/* the rest are 0 */
-	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
-
-	par->metromem_cmd->csum = cs;
-	par->metromem_cmd->opcode = opcode; /* display cmd */
-
-	return par->board->met_wait_event_intr(par);
-}
-
-static int metronome_powerup_cmd(struct metronomefb_par *par)
-{
-	int i;
-	u16 cs;
-
-	/* setup power up command */
-	par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */
-	cs = par->metromem_cmd->opcode;
-
-	/* set pwr1,2,3 to 1024 */
-	for (i = 0; i < 3; i++) {
-		par->metromem_cmd->args[i] = 1024;
-		cs += par->metromem_cmd->args[i];
-	}
-
-	/* the rest are 0 */
-	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
-
-	par->metromem_cmd->csum = cs;
-
-	msleep(1);
-	par->board->set_rst(par, 1);
-
-	msleep(1);
-	par->board->set_stdby(par, 1);
-
-	return par->board->met_wait_event(par);
-}
-
-static int metronome_config_cmd(struct metronomefb_par *par)
-{
-	/* setup config command
-	we can't immediately set the opcode since the controller
-	will try parse the command before we've set it all up */
-
-	memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
-		sizeof(epd_frame_table[par->dt].config));
-	/* the rest are 0 */
-	memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
-
-	par->metromem_cmd->csum = 0xCC10;
-	par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
-	par->metromem_cmd->opcode = 0xCC10; /* config cmd */
-
-	return par->board->met_wait_event(par);
-}
-
-static int metronome_init_cmd(struct metronomefb_par *par)
-{
-	int i;
-	u16 cs;
-
-	/* setup init command
-	we can't immediately set the opcode since the controller
-	will try parse the command before we've set it all up
-	so we just set cs here and set the opcode at the end */
-
-	cs = 0xCC20;
-
-	/* set the args ( 2 bytes ) for init */
-	i = 0;
-	par->metromem_cmd->args[i] = 0;
-	cs += par->metromem_cmd->args[i++];
-
-	/* the rest are 0 */
-	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
-
-	par->metromem_cmd->csum = cs;
-	par->metromem_cmd->opcode = 0xCC20; /* init cmd */
-
-	return par->board->met_wait_event(par);
-}
-
-static int metronome_init_regs(struct metronomefb_par *par)
-{
-	int res;
-
-	res = par->board->setup_io(par);
-	if (res)
-		return res;
-
-	res = metronome_powerup_cmd(par);
-	if (res)
-		return res;
-
-	res = metronome_config_cmd(par);
-	if (res)
-		return res;
-
-	res = metronome_init_cmd(par);
-
-	return res;
-}
-
-static void metronomefb_dpy_update(struct metronomefb_par *par)
-{
-	int fbsize;
-	u16 cksum;
-	unsigned char *buf = (unsigned char __force *)par->info->screen_base;
-
-	fbsize = par->info->fix.smem_len;
-	/* copy from vm to metromem */
-	memcpy(par->metromem_img, buf, fbsize);
-
-	cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
-	*((u16 *)(par->metromem_img) + fbsize/2) = cksum;
-	metronome_display_cmd(par);
-}
-
-static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
-{
-	int i;
-	u16 csum = 0;
-	u16 *buf = (u16 __force *)(par->info->screen_base + index);
-	u16 *img = (u16 *)(par->metromem_img + index);
-
-	/* swizzle from vm to metromem and recalc cksum at the same time*/
-	for (i = 0; i < PAGE_SIZE/2; i++) {
-		*(img + i) = (buf[i] << 5) & 0xE0E0;
-		csum += *(img + i);
-	}
-	return csum;
-}
-
-/* this is called back from the deferred io workqueue */
-static void metronomefb_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	u16 cksum;
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct metronomefb_par *par = info->par;
-
-	/* walk the written page list and swizzle the data */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-		cksum = metronomefb_dpy_update_page(par,
-					(cur->index << PAGE_SHIFT));
-		par->metromem_img_csum -= par->csum_table[cur->index];
-		par->csum_table[cur->index] = cksum;
-		par->metromem_img_csum += cksum;
-	}
-
-	metronome_display_cmd(par);
-}
-
-static void metronomefb_fillrect(struct fb_info *info,
-				   const struct fb_fillrect *rect)
-{
-	struct metronomefb_par *par = info->par;
-
-	sys_fillrect(info, rect);
-	metronomefb_dpy_update(par);
-}
-
-static void metronomefb_copyarea(struct fb_info *info,
-				   const struct fb_copyarea *area)
-{
-	struct metronomefb_par *par = info->par;
-
-	sys_copyarea(info, area);
-	metronomefb_dpy_update(par);
-}
-
-static void metronomefb_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	struct metronomefb_par *par = info->par;
-
-	sys_imageblit(info, image);
-	metronomefb_dpy_update(par);
-}
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it is based on fb_sys_write
- */
-static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	struct metronomefb_par *par = info->par;
-	unsigned long p = *ppos;
-	void *dst;
-	int err = 0;
-	unsigned long total_size;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return -EPERM;
-
-	total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EFBIG;
-
-	if (count > total_size) {
-		err = -EFBIG;
-		count = total_size;
-	}
-
-	if (count + p > total_size) {
-		if (!err)
-			err = -ENOSPC;
-
-		count = total_size - p;
-	}
-
-	dst = (void __force *)(info->screen_base + p);
-
-	if (copy_from_user(dst, buf, count))
-		err = -EFAULT;
-
-	if  (!err)
-		*ppos += count;
-
-	metronomefb_dpy_update(par);
-
-	return (err) ? err : count;
-}
-
-static struct fb_ops metronomefb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_write	= metronomefb_write,
-	.fb_fillrect	= metronomefb_fillrect,
-	.fb_copyarea	= metronomefb_copyarea,
-	.fb_imageblit	= metronomefb_imageblit,
-};
-
-static struct fb_deferred_io metronomefb_defio = {
-	.delay		= HZ,
-	.deferred_io	= metronomefb_dpy_deferred_io,
-};
-
-static int metronomefb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	struct metronome_board *board;
-	int retval = -ENOMEM;
-	int videomemorysize;
-	unsigned char *videomemory;
-	struct metronomefb_par *par;
-	const struct firmware *fw_entry;
-	int i;
-	int panel_type;
-	int fw, fh;
-	int epd_dt_index;
-
-	/* pick up board specific routines */
-	board = dev->dev.platform_data;
-	if (!board)
-		return -EINVAL;
-
-	/* try to count device specific driver, if can't, platform recalls */
-	if (!try_module_get(board->owner))
-		return -ENODEV;
-
-	info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
-	if (!info)
-		goto err;
-
-	/* we have two blocks of memory.
-	info->screen_base which is vm, and is the fb used by apps.
-	par->metromem which is physically contiguous memory and
-	contains the display controller commands, waveform,
-	processed image data and padding. this is the data pulled
-	by the device's LCD controller and pushed to Metronome.
-	the metromem memory is allocated by the board driver and
-	is provided to us */
-
-	panel_type = board->get_panel_type();
-	switch (panel_type) {
-	case 6:
-		epd_dt_index = 0;
-		break;
-	case 8:
-		epd_dt_index = 1;
-		break;
-	case 97:
-		epd_dt_index = 2;
-		break;
-	default:
-		dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
-		epd_dt_index = 0;
-		break;
-	}
-
-	fw = epd_frame_table[epd_dt_index].fw;
-	fh = epd_frame_table[epd_dt_index].fh;
-
-	/* we need to add a spare page because our csum caching scheme walks
-	 * to the end of the page */
-	videomemorysize = PAGE_SIZE + (fw * fh);
-	videomemory = vzalloc(videomemorysize);
-	if (!videomemory)
-		goto err_fb_rel;
-
-	info->screen_base = (char __force __iomem *)videomemory;
-	info->fbops = &metronomefb_ops;
-
-	metronomefb_fix.line_length = fw;
-	metronomefb_var.xres = fw;
-	metronomefb_var.yres = fh;
-	metronomefb_var.xres_virtual = fw;
-	metronomefb_var.yres_virtual = fh;
-	info->var = metronomefb_var;
-	info->fix = metronomefb_fix;
-	info->fix.smem_len = videomemorysize;
-	par = info->par;
-	par->info = info;
-	par->board = board;
-	par->dt = epd_dt_index;
-	init_waitqueue_head(&par->waitq);
-
-	/* this table caches per page csum values. */
-	par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
-	if (!par->csum_table)
-		goto err_vfree;
-
-	/* the physical framebuffer that we use is setup by
-	 * the platform device driver. It will provide us
-	 * with cmd, wfm and image memory in a contiguous area. */
-	retval = board->setup_fb(par);
-	if (retval) {
-		dev_err(&dev->dev, "Failed to setup fb\n");
-		goto err_csum_table;
-	}
-
-	/* after this point we should have a framebuffer */
-	if ((!par->metromem_wfm) ||  (!par->metromem_img) ||
-		(!par->metromem_dma)) {
-		dev_err(&dev->dev, "fb access failure\n");
-		retval = -EINVAL;
-		goto err_csum_table;
-	}
-
-	info->fix.smem_start = par->metromem_dma;
-
-	/* load the waveform in. assume mode 3, temp 31 for now
-		a) request the waveform file from userspace
-		b) process waveform and decode into metromem */
-	retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
-	if (retval < 0) {
-		dev_err(&dev->dev, "Failed to get waveform\n");
-		goto err_csum_table;
-	}
-
-	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
-				par);
-	release_firmware(fw_entry);
-	if (retval < 0) {
-		dev_err(&dev->dev, "Failed processing waveform\n");
-		goto err_csum_table;
-	}
-
-	retval = board->setup_irq(info);
-	if (retval)
-		goto err_csum_table;
-
-	retval = metronome_init_regs(par);
-	if (retval < 0)
-		goto err_free_irq;
-
-	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
-
-	info->fbdefio = &metronomefb_defio;
-	fb_deferred_io_init(info);
-
-	retval = fb_alloc_cmap(&info->cmap, 8, 0);
-	if (retval < 0) {
-		dev_err(&dev->dev, "Failed to allocate colormap\n");
-		goto err_free_irq;
-	}
-
-	/* set cmap */
-	for (i = 0; i < 8; i++)
-		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/16;
-	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
-	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err_cmap;
-
-	platform_set_drvdata(dev, info);
-
-	dev_dbg(&dev->dev,
-		"fb%d: Metronome frame buffer device, using %dK of video"
-		" memory\n", info->node, videomemorysize >> 10);
-
-	return 0;
-
-err_cmap:
-	fb_dealloc_cmap(&info->cmap);
-err_free_irq:
-	board->cleanup(par);
-err_csum_table:
-	vfree(par->csum_table);
-err_vfree:
-	vfree(videomemory);
-err_fb_rel:
-	framebuffer_release(info);
-err:
-	module_put(board->owner);
-	return retval;
-}
-
-static int metronomefb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		struct metronomefb_par *par = info->par;
-
-		unregister_framebuffer(info);
-		fb_deferred_io_cleanup(info);
-		fb_dealloc_cmap(&info->cmap);
-		par->board->cleanup(par);
-		vfree(par->csum_table);
-		vfree((void __force *)info->screen_base);
-		module_put(par->board->owner);
-		dev_dbg(&dev->dev, "calling release\n");
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-static struct platform_driver metronomefb_driver = {
-	.probe	= metronomefb_probe,
-	.remove = metronomefb_remove,
-	.driver	= {
-		.owner	= THIS_MODULE,
-		.name	= "metronomefb",
-	},
-};
-module_platform_driver(metronomefb_driver);
-
-module_param(user_wfm_size, uint, 0);
-MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
-
-MODULE_DESCRIPTION("fbdev driver for Metronome controller");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/mmp/Kconfig b/drivers/video/mmp/Kconfig
deleted file mode 100644
index e9ea39e13722..000000000000
--- a/drivers/video/mmp/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-menuconfig MMP_DISP
-        tristate "Marvell MMP Display Subsystem support"
-        depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988
-        help
-	  Marvell Display Subsystem support.
-
-if MMP_DISP
-source "drivers/video/mmp/hw/Kconfig"
-source "drivers/video/mmp/panel/Kconfig"
-source "drivers/video/mmp/fb/Kconfig"
-endif
diff --git a/drivers/video/mmp/Makefile b/drivers/video/mmp/Makefile
deleted file mode 100644
index a014cb358bf8..000000000000
--- a/drivers/video/mmp/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-y += core.o hw/ panel/ fb/
diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c
deleted file mode 100644
index b563b920f159..000000000000
--- a/drivers/video/mmp/core.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * linux/drivers/video/mmp/common.c
- * This driver is a common framework for Marvell Display Controller
- *
- * Copyright (C) 2012 Marvell Technology Group Ltd.
- * Authors: Zhou Zhu <zzhu3@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/export.h>
-#include <video/mmp_disp.h>
-
-static struct mmp_overlay *path_get_overlay(struct mmp_path *path,
-		int overlay_id)
-{
-	if (path && overlay_id < path->overlay_num)
-		return &path->overlays[overlay_id];
-	return NULL;
-}
-
-static int path_check_status(struct mmp_path *path)
-{
-	int i;
-	for (i = 0; i < path->overlay_num; i++)
-		if (path->overlays[i].status)
-			return 1;
-
-	return 0;
-}
-
-/*
- * Get modelist write pointer of modelist.
- * It also returns modelist number
- * this function fetches modelist from phy/panel:
- *   for HDMI/parallel or dsi to hdmi cases, get from phy
- *   or get from panel
- */
-static int path_get_modelist(struct mmp_path *path,
-		struct mmp_mode **modelist)
-{
-	BUG_ON(!path || !modelist);
-
-	if (path->panel && path->panel->get_modelist)
-		return path->panel->get_modelist(path->panel, modelist);
-
-	return 0;
-}
-
-/*
- * panel list is used to pair panel/path when path/panel registered
- * path list is used for both buffer driver and platdriver
- * plat driver do path register/unregister
- * panel driver do panel register/unregister
- * buffer driver get registered path
- */
-static LIST_HEAD(panel_list);
-static LIST_HEAD(path_list);
-static DEFINE_MUTEX(disp_lock);
-
-/*
- * mmp_register_panel - register panel to panel_list and connect to path
- * @p: panel to be registered
- *
- * this function provides interface for panel drivers to register panel
- * to panel_list and connect to path which matchs panel->plat_path_name.
- * no error returns when no matching path is found as path register after
- * panel register is permitted.
- */
-void mmp_register_panel(struct mmp_panel *panel)
-{
-	struct mmp_path *path;
-
-	mutex_lock(&disp_lock);
-
-	/* add */
-	list_add_tail(&panel->node, &panel_list);
-
-	/* try to register to path */
-	list_for_each_entry(path, &path_list, node) {
-		if (!strcmp(panel->plat_path_name, path->name)) {
-			dev_info(panel->dev, "connect to path %s\n",
-				path->name);
-			path->panel = panel;
-			break;
-		}
-	}
-
-	mutex_unlock(&disp_lock);
-}
-EXPORT_SYMBOL_GPL(mmp_register_panel);
-
-/*
- * mmp_unregister_panel - unregister panel from panel_list and disconnect
- * @p: panel to be unregistered
- *
- * this function provides interface for panel drivers to unregister panel
- * from panel_list and disconnect from path.
- */
-void mmp_unregister_panel(struct mmp_panel *panel)
-{
-	struct mmp_path *path;
-
-	mutex_lock(&disp_lock);
-	list_del(&panel->node);
-
-	list_for_each_entry(path, &path_list, node) {
-		if (path->panel && path->panel == panel) {
-			dev_info(panel->dev, "disconnect from path %s\n",
-				path->name);
-			path->panel = NULL;
-			break;
-		}
-	}
-	mutex_unlock(&disp_lock);
-}
-EXPORT_SYMBOL_GPL(mmp_unregister_panel);
-
-/*
- * mmp_get_path - get path by name
- * @p: path name
- *
- * this function checks path name in path_list and return matching path
- * return NULL if no matching path
- */
-struct mmp_path *mmp_get_path(const char *name)
-{
-	struct mmp_path *path;
-	int found = 0;
-
-	mutex_lock(&disp_lock);
-	list_for_each_entry(path, &path_list, node) {
-		if (!strcmp(name, path->name)) {
-			found = 1;
-			break;
-		}
-	}
-	mutex_unlock(&disp_lock);
-
-	return found ? path : NULL;
-}
-EXPORT_SYMBOL_GPL(mmp_get_path);
-
-/*
- * mmp_register_path - init and register path by path_info
- * @p: path info provided by display controller
- *
- * this function init by path info and register path to path_list
- * this function also try to connect path with panel by name
- */
-struct mmp_path *mmp_register_path(struct mmp_path_info *info)
-{
-	int i;
-	size_t size;
-	struct mmp_path *path = NULL;
-	struct mmp_panel *panel;
-
-	size = sizeof(struct mmp_path)
-		+ sizeof(struct mmp_overlay) * info->overlay_num;
-	path = kzalloc(size, GFP_KERNEL);
-	if (!path)
-		return NULL;
-
-	/* path set */
-	mutex_init(&path->access_ok);
-	path->dev = info->dev;
-	path->id = info->id;
-	path->name = info->name;
-	path->output_type = info->output_type;
-	path->overlay_num = info->overlay_num;
-	path->plat_data = info->plat_data;
-	path->ops.set_mode = info->set_mode;
-
-	mutex_lock(&disp_lock);
-	/* get panel */
-	list_for_each_entry(panel, &panel_list, node) {
-		if (!strcmp(info->name, panel->plat_path_name)) {
-			dev_info(path->dev, "get panel %s\n", panel->name);
-			path->panel = panel;
-			break;
-		}
-	}
-
-	dev_info(path->dev, "register %s, overlay_num %d\n",
-			path->name, path->overlay_num);
-
-	/* default op set: if already set by driver, never cover it */
-	if (!path->ops.check_status)
-		path->ops.check_status = path_check_status;
-	if (!path->ops.get_overlay)
-		path->ops.get_overlay = path_get_overlay;
-	if (!path->ops.get_modelist)
-		path->ops.get_modelist = path_get_modelist;
-
-	/* step3: init overlays */
-	for (i = 0; i < path->overlay_num; i++) {
-		path->overlays[i].path = path;
-		path->overlays[i].id = i;
-		mutex_init(&path->overlays[i].access_ok);
-		path->overlays[i].ops = info->overlay_ops;
-	}
-
-	/* add to pathlist */
-	list_add_tail(&path->node, &path_list);
-
-	mutex_unlock(&disp_lock);
-	return path;
-}
-EXPORT_SYMBOL_GPL(mmp_register_path);
-
-/*
- * mmp_unregister_path - unregister and destory path
- * @p: path to be destoried.
- *
- * this function registers path and destorys it.
- */
-void mmp_unregister_path(struct mmp_path *path)
-{
-	int i;
-
-	if (!path)
-		return;
-
-	mutex_lock(&disp_lock);
-	/* del from pathlist */
-	list_del(&path->node);
-
-	/* deinit overlays */
-	for (i = 0; i < path->overlay_num; i++)
-		mutex_destroy(&path->overlays[i].access_ok);
-
-	mutex_destroy(&path->access_ok);
-
-	kfree(path);
-	mutex_unlock(&disp_lock);
-}
-EXPORT_SYMBOL_GPL(mmp_unregister_path);
diff --git a/drivers/video/mmp/fb/Kconfig b/drivers/video/mmp/fb/Kconfig
deleted file mode 100644
index 9b0141f105f5..000000000000
--- a/drivers/video/mmp/fb/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-if MMP_DISP
-
-config MMP_FB
-	bool "fb driver for Marvell MMP Display Subsystem"
-	depends on FB
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	default y
-	help
-		fb driver for Marvell MMP Display Subsystem
-
-endif
diff --git a/drivers/video/mmp/fb/Makefile b/drivers/video/mmp/fb/Makefile
deleted file mode 100644
index 709fd1f76abe..000000000000
--- a/drivers/video/mmp/fb/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_MMP_FB)  += mmpfb.o
diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/mmp/fb/mmpfb.c
deleted file mode 100644
index 7ab31eb76a8c..000000000000
--- a/drivers/video/mmp/fb/mmpfb.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * linux/drivers/video/mmp/fb/mmpfb.c
- * Framebuffer driver for Marvell Display controller.
- *
- * Copyright (C) 2012 Marvell Technology Group Ltd.
- * Authors: Zhou Zhu <zzhu3@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include "mmpfb.h"
-
-static int var_to_pixfmt(struct fb_var_screeninfo *var)
-{
-	/*
-	 * Pseudocolor mode?
-	 */
-	if (var->bits_per_pixel == 8)
-		return PIXFMT_PSEUDOCOLOR;
-
-	/*
-	 * Check for YUV422PLANAR.
-	 */
-	if (var->bits_per_pixel == 16 && var->red.length == 8 &&
-			var->green.length == 4 && var->blue.length == 4) {
-		if (var->green.offset >= var->blue.offset)
-			return PIXFMT_YUV422P;
-		else
-			return PIXFMT_YVU422P;
-	}
-
-	/*
-	 * Check for YUV420PLANAR.
-	 */
-	if (var->bits_per_pixel == 12 && var->red.length == 8 &&
-			var->green.length == 2 && var->blue.length == 2) {
-		if (var->green.offset >= var->blue.offset)
-			return PIXFMT_YUV420P;
-		else
-			return PIXFMT_YVU420P;
-	}
-
-	/*
-	 * Check for YUV422PACK.
-	 */
-	if (var->bits_per_pixel == 16 && var->red.length == 16 &&
-			var->green.length == 16 && var->blue.length == 16) {
-		if (var->red.offset == 0)
-			return PIXFMT_YUYV;
-		else if (var->green.offset >= var->blue.offset)
-			return PIXFMT_UYVY;
-		else
-			return PIXFMT_VYUY;
-	}
-
-	/*
-	 * Check for 565/1555.
-	 */
-	if (var->bits_per_pixel == 16 && var->red.length <= 5 &&
-			var->green.length <= 6 && var->blue.length <= 5) {
-		if (var->transp.length == 0) {
-			if (var->red.offset >= var->blue.offset)
-				return PIXFMT_RGB565;
-			else
-				return PIXFMT_BGR565;
-		}
-	}
-
-	/*
-	 * Check for 888/A888.
-	 */
-	if (var->bits_per_pixel <= 32 && var->red.length <= 8 &&
-			var->green.length <= 8 && var->blue.length <= 8) {
-		if (var->bits_per_pixel == 24 && var->transp.length == 0) {
-			if (var->red.offset >= var->blue.offset)
-				return PIXFMT_RGB888PACK;
-			else
-				return PIXFMT_BGR888PACK;
-		}
-
-		if (var->bits_per_pixel == 32 && var->transp.offset == 24) {
-			if (var->red.offset >= var->blue.offset)
-				return PIXFMT_RGBA888;
-			else
-				return PIXFMT_BGRA888;
-		} else {
-			if (var->red.offset >= var->blue.offset)
-				return PIXFMT_RGB888UNPACK;
-			else
-				return PIXFMT_BGR888UNPACK;
-		}
-
-		/* fall through */
-	}
-
-	return -EINVAL;
-}
-
-static void pixfmt_to_var(struct fb_var_screeninfo *var, int pix_fmt)
-{
-	switch (pix_fmt) {
-	case PIXFMT_RGB565:
-		var->bits_per_pixel = 16;
-		var->red.offset = 11;	var->red.length = 5;
-		var->green.offset = 5;   var->green.length = 6;
-		var->blue.offset = 0;	var->blue.length = 5;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_BGR565:
-		var->bits_per_pixel = 16;
-		var->red.offset = 0;	var->red.length = 5;
-		var->green.offset = 5;	 var->green.length = 6;
-		var->blue.offset = 11;	var->blue.length = 5;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_RGB888UNPACK:
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;	var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 0;	var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_BGR888UNPACK:
-		var->bits_per_pixel = 32;
-		var->red.offset = 0;	var->red.length = 8;
-		var->green.offset = 8;	 var->green.length = 8;
-		var->blue.offset = 16;	var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_RGBA888:
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;	var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 0;	var->blue.length = 8;
-		var->transp.offset = 24; var->transp.length = 8;
-		break;
-	case PIXFMT_BGRA888:
-		var->bits_per_pixel = 32;
-		var->red.offset = 0;	var->red.length = 8;
-		var->green.offset = 8;	 var->green.length = 8;
-		var->blue.offset = 16;	var->blue.length = 8;
-		var->transp.offset = 24; var->transp.length = 8;
-		break;
-	case PIXFMT_RGB888PACK:
-		var->bits_per_pixel = 24;
-		var->red.offset = 16;	var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 0;	var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_BGR888PACK:
-		var->bits_per_pixel = 24;
-		var->red.offset = 0;	var->red.length = 8;
-		var->green.offset = 8;	 var->green.length = 8;
-		var->blue.offset = 16;	var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_YUV420P:
-		var->bits_per_pixel = 12;
-		var->red.offset = 4;	 var->red.length = 8;
-		var->green.offset = 2;   var->green.length = 2;
-		var->blue.offset = 0;   var->blue.length = 2;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_YVU420P:
-		var->bits_per_pixel = 12;
-		var->red.offset = 4;	 var->red.length = 8;
-		var->green.offset = 0;	 var->green.length = 2;
-		var->blue.offset = 2;	var->blue.length = 2;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_YUV422P:
-		var->bits_per_pixel = 16;
-		var->red.offset = 8;	 var->red.length = 8;
-		var->green.offset = 4;   var->green.length = 4;
-		var->blue.offset = 0;   var->blue.length = 4;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_YVU422P:
-		var->bits_per_pixel = 16;
-		var->red.offset = 8;	 var->red.length = 8;
-		var->green.offset = 0;	 var->green.length = 4;
-		var->blue.offset = 4;	var->blue.length = 4;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_UYVY:
-		var->bits_per_pixel = 16;
-		var->red.offset = 8;	 var->red.length = 16;
-		var->green.offset = 4;   var->green.length = 16;
-		var->blue.offset = 0;   var->blue.length = 16;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_VYUY:
-		var->bits_per_pixel = 16;
-		var->red.offset = 8;	 var->red.length = 16;
-		var->green.offset = 0;	 var->green.length = 16;
-		var->blue.offset = 4;	var->blue.length = 16;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_YUYV:
-		var->bits_per_pixel = 16;
-		var->red.offset = 0;	 var->red.length = 16;
-		var->green.offset = 4;	 var->green.length = 16;
-		var->blue.offset = 8;	var->blue.length = 16;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIXFMT_PSEUDOCOLOR:
-		var->bits_per_pixel = 8;
-		var->red.offset = 0;	 var->red.length = 8;
-		var->green.offset = 0;   var->green.length = 8;
-		var->blue.offset = 0;	var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	}
-}
-
-/*
- * fb framework has its limitation:
- * 1. input color/output color is not seprated
- * 2. fb_videomode not include output color
- * so for fb usage, we keep a output format which is not changed
- *  then it's added for mmpmode
- */
-static void fbmode_to_mmpmode(struct mmp_mode *mode,
-		struct fb_videomode *videomode, int output_fmt)
-{
-	u64 div_result = 1000000000000ll;
-	mode->name = videomode->name;
-	mode->refresh = videomode->refresh;
-	mode->xres = videomode->xres;
-	mode->yres = videomode->yres;
-
-	do_div(div_result, videomode->pixclock);
-	mode->pixclock_freq = (u32)div_result;
-
-	mode->left_margin = videomode->left_margin;
-	mode->right_margin = videomode->right_margin;
-	mode->upper_margin = videomode->upper_margin;
-	mode->lower_margin = videomode->lower_margin;
-	mode->hsync_len = videomode->hsync_len;
-	mode->vsync_len = videomode->vsync_len;
-	mode->hsync_invert = !!(videomode->sync & FB_SYNC_HOR_HIGH_ACT);
-	mode->vsync_invert = !!(videomode->sync & FB_SYNC_VERT_HIGH_ACT);
-	/* no defined flag in fb, use vmode>>3*/
-	mode->invert_pixclock = !!(videomode->vmode & 8);
-	mode->pix_fmt_out = output_fmt;
-}
-
-static void mmpmode_to_fbmode(struct fb_videomode *videomode,
-		struct mmp_mode *mode)
-{
-	u64 div_result = 1000000000000ll;
-
-	videomode->name = mode->name;
-	videomode->refresh = mode->refresh;
-	videomode->xres = mode->xres;
-	videomode->yres = mode->yres;
-
-	do_div(div_result, mode->pixclock_freq);
-	videomode->pixclock = (u32)div_result;
-
-	videomode->left_margin = mode->left_margin;
-	videomode->right_margin = mode->right_margin;
-	videomode->upper_margin = mode->upper_margin;
-	videomode->lower_margin = mode->lower_margin;
-	videomode->hsync_len = mode->hsync_len;
-	videomode->vsync_len = mode->vsync_len;
-	videomode->sync = (mode->hsync_invert ? FB_SYNC_HOR_HIGH_ACT : 0)
-		| (mode->vsync_invert ? FB_SYNC_VERT_HIGH_ACT : 0);
-	videomode->vmode = mode->invert_pixclock ? 8 : 0;
-}
-
-static int mmpfb_check_var(struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-	struct mmpfb_info *fbi = info->par;
-
-	if (var->bits_per_pixel == 8)
-		return -EINVAL;
-	/*
-	 * Basic geometry sanity checks.
-	 */
-	if (var->xoffset + var->xres > var->xres_virtual)
-		return -EINVAL;
-	if (var->yoffset + var->yres > var->yres_virtual)
-		return -EINVAL;
-
-	/*
-	 * Check size of framebuffer.
-	 */
-	if (var->xres_virtual * var->yres_virtual *
-			(var->bits_per_pixel >> 3) > fbi->fb_size)
-		return -EINVAL;
-
-	return 0;
-}
-
-static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
-{
-	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
-}
-
-static u32 to_rgb(u16 red, u16 green, u16 blue)
-{
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	return (red << 16) | (green << 8) | blue;
-}
-
-static int mmpfb_setcolreg(unsigned int regno, unsigned int red,
-		unsigned int green, unsigned int blue,
-		unsigned int trans, struct fb_info *info)
-{
-	struct mmpfb_info *fbi = info->par;
-	u32 val;
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) {
-		val =  chan_to_field(red,   &info->var.red);
-		val |= chan_to_field(green, &info->var.green);
-		val |= chan_to_field(blue , &info->var.blue);
-		fbi->pseudo_palette[regno] = val;
-	}
-
-	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
-		val = to_rgb(red, green, blue);
-		/* TODO */
-	}
-
-	return 0;
-}
-
-static int mmpfb_pan_display(struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-	struct mmpfb_info *fbi = info->par;
-	struct mmp_addr addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.phys[0] = (var->yoffset * var->xres_virtual + var->xoffset)
-		* var->bits_per_pixel / 8 + fbi->fb_start_dma;
-	mmp_overlay_set_addr(fbi->overlay, &addr);
-
-	return 0;
-}
-
-static int var_update(struct fb_info *info)
-{
-	struct mmpfb_info *fbi = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	struct fb_videomode *m;
-	int pix_fmt;
-
-	/* set pix_fmt */
-	pix_fmt = var_to_pixfmt(var);
-	if (pix_fmt < 0)
-		return -EINVAL;
-	pixfmt_to_var(var, pix_fmt);
-	fbi->pix_fmt = pix_fmt;
-
-	/* set var according to best video mode*/
-	m = (struct fb_videomode *)fb_match_mode(var, &info->modelist);
-	if (!m) {
-		dev_err(fbi->dev, "set par: no match mode, use best mode\n");
-		m = (struct fb_videomode *)fb_find_best_mode(var,
-				&info->modelist);
-		fb_videomode_to_var(var, m);
-	}
-	memcpy(&fbi->mode, m, sizeof(struct fb_videomode));
-
-	/* fix to 2* yres */
-	var->yres_virtual = var->yres * 2;
-	info->fix.visual = (pix_fmt == PIXFMT_PSEUDOCOLOR) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
-	info->fix.ypanstep = var->yres;
-	return 0;
-}
-
-static void mmpfb_set_win(struct fb_info *info)
-{
-	struct mmpfb_info *fbi = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	struct mmp_win win;
-	u32 stride;
-
-	memset(&win, 0, sizeof(win));
-	win.xsrc = win.xdst = fbi->mode.xres;
-	win.ysrc = win.ydst = fbi->mode.yres;
-	win.pix_fmt = fbi->pix_fmt;
-	stride = pixfmt_to_stride(win.pix_fmt);
-	win.pitch[0] = var->xres_virtual * stride;
-	win.pitch[1] = win.pitch[2] =
-		(stride == 1) ? (var->xres_virtual >> 1) : 0;
-	mmp_overlay_set_win(fbi->overlay, &win);
-}
-
-static int mmpfb_set_par(struct fb_info *info)
-{
-	struct mmpfb_info *fbi = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	struct mmp_addr addr;
-	struct mmp_mode mode;
-	int ret;
-
-	ret = var_update(info);
-	if (ret != 0)
-		return ret;
-
-	/* set window/path according to new videomode */
-	fbmode_to_mmpmode(&mode, &fbi->mode, fbi->output_fmt);
-	mmp_path_set_mode(fbi->path, &mode);
-
-	/* set window related info */
-	mmpfb_set_win(info);
-
-	/* set address always */
-	memset(&addr, 0, sizeof(addr));
-	addr.phys[0] = (var->yoffset * var->xres_virtual + var->xoffset)
-		* var->bits_per_pixel / 8 + fbi->fb_start_dma;
-	mmp_overlay_set_addr(fbi->overlay, &addr);
-
-	return 0;
-}
-
-static void mmpfb_power(struct mmpfb_info *fbi, int power)
-{
-	struct mmp_addr addr;
-	struct fb_var_screeninfo *var = &fbi->fb_info->var;
-
-	/* for power on, always set address/window again */
-	if (power) {
-		/* set window related info */
-		mmpfb_set_win(fbi->fb_info);
-
-		/* set address always */
-		memset(&addr, 0, sizeof(addr));
-		addr.phys[0] = fbi->fb_start_dma +
-			(var->yoffset * var->xres_virtual + var->xoffset)
-			* var->bits_per_pixel / 8;
-		mmp_overlay_set_addr(fbi->overlay, &addr);
-	}
-	mmp_overlay_set_onoff(fbi->overlay, power);
-}
-
-static int mmpfb_blank(int blank, struct fb_info *info)
-{
-	struct mmpfb_info *fbi = info->par;
-
-	mmpfb_power(fbi, (blank == FB_BLANK_UNBLANK));
-
-	return 0;
-}
-
-static struct fb_ops mmpfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_blank	= mmpfb_blank,
-	.fb_check_var	= mmpfb_check_var,
-	.fb_set_par	= mmpfb_set_par,
-	.fb_setcolreg	= mmpfb_setcolreg,
-	.fb_pan_display	= mmpfb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int modes_setup(struct mmpfb_info *fbi)
-{
-	struct fb_videomode *videomodes;
-	struct mmp_mode *mmp_modes;
-	struct fb_info *info = fbi->fb_info;
-	int videomode_num, i;
-
-	/* get videomodes from path */
-	videomode_num = mmp_path_get_modelist(fbi->path, &mmp_modes);
-	if (!videomode_num) {
-		dev_warn(fbi->dev, "can't get videomode num\n");
-		return 0;
-	}
-	/* put videomode list to info structure */
-	videomodes = kzalloc(sizeof(struct fb_videomode) * videomode_num,
-			GFP_KERNEL);
-	if (!videomodes) {
-		dev_err(fbi->dev, "can't malloc video modes\n");
-		return -ENOMEM;
-	}
-	for (i = 0; i < videomode_num; i++)
-		mmpmode_to_fbmode(&videomodes[i], &mmp_modes[i]);
-	fb_videomode_to_modelist(videomodes, videomode_num, &info->modelist);
-
-	/* set videomode[0] as default mode */
-	memcpy(&fbi->mode, &videomodes[0], sizeof(struct fb_videomode));
-	fbi->output_fmt = mmp_modes[0].pix_fmt_out;
-	fb_videomode_to_var(&info->var, &fbi->mode);
-	mmp_path_set_mode(fbi->path, &mmp_modes[0]);
-
-	kfree(videomodes);
-	return videomode_num;
-}
-
-static int fb_info_setup(struct fb_info *info,
-			struct mmpfb_info *fbi)
-{
-	int ret = 0;
-	/* Initialise static fb parameters.*/
-	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
-		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
-	info->node = -1;
-	strcpy(info->fix.id, fbi->name);
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux = 0;
-	info->fix.xpanstep = 0;
-	info->fix.ypanstep = info->var.yres;
-	info->fix.ywrapstep = 0;
-	info->fix.accel = FB_ACCEL_NONE;
-	info->fix.smem_start = fbi->fb_start_dma;
-	info->fix.smem_len = fbi->fb_size;
-	info->fix.visual = (fbi->pix_fmt == PIXFMT_PSEUDOCOLOR) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = info->var.xres_virtual *
-		info->var.bits_per_pixel / 8;
-	info->fbops = &mmpfb_ops;
-	info->pseudo_palette = fbi->pseudo_palette;
-	info->screen_base = fbi->fb_start;
-	info->screen_size = fbi->fb_size;
-
-	/* For FB framework: Allocate color map and Register framebuffer*/
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
-		ret = -ENOMEM;
-
-	return ret;
-}
-
-static void fb_info_clear(struct fb_info *info)
-{
-	fb_dealloc_cmap(&info->cmap);
-}
-
-static int mmpfb_probe(struct platform_device *pdev)
-{
-	struct mmp_buffer_driver_mach_info *mi;
-	struct fb_info *info = 0;
-	struct mmpfb_info *fbi = 0;
-	int ret, modes_num;
-
-	mi = pdev->dev.platform_data;
-	if (mi == NULL) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
-
-	/* initialize fb */
-	info = framebuffer_alloc(sizeof(struct mmpfb_info), &pdev->dev);
-	if (info == NULL)
-		return -ENOMEM;
-	fbi = info->par;
-	if (!fbi) {
-		ret = -EINVAL;
-		goto failed;
-	}
-
-	/* init fb */
-	fbi->fb_info = info;
-	platform_set_drvdata(pdev, fbi);
-	fbi->dev = &pdev->dev;
-	fbi->name = mi->name;
-	fbi->pix_fmt = mi->default_pixfmt;
-	pixfmt_to_var(&info->var, fbi->pix_fmt);
-	mutex_init(&fbi->access_ok);
-
-	/* get display path by name */
-	fbi->path = mmp_get_path(mi->path_name);
-	if (!fbi->path) {
-		dev_err(&pdev->dev, "can't get the path %s\n", mi->path_name);
-		ret = -EINVAL;
-		goto failed_destroy_mutex;
-	}
-
-	dev_info(fbi->dev, "path %s get\n", fbi->path->name);
-
-	/* get overlay */
-	fbi->overlay = mmp_path_get_overlay(fbi->path, mi->overlay_id);
-	if (!fbi->overlay) {
-		ret = -EINVAL;
-		goto failed_destroy_mutex;
-	}
-	/* set fetch used */
-	mmp_overlay_set_fetch(fbi->overlay, mi->dmafetch_id);
-
-	modes_num = modes_setup(fbi);
-	if (modes_num < 0) {
-		ret = modes_num;
-		goto failed_destroy_mutex;
-	}
-
-	/*
-	 * if get modes success, means not hotplug panels, use caculated buffer
-	 * or use default size
-	 */
-	if (modes_num > 0) {
-		/* fix to 2* yres */
-		info->var.yres_virtual = info->var.yres * 2;
-
-		/* Allocate framebuffer memory: size = modes xy *4 */
-		fbi->fb_size = info->var.xres_virtual * info->var.yres_virtual
-				* info->var.bits_per_pixel / 8;
-	} else {
-		fbi->fb_size = MMPFB_DEFAULT_SIZE;
-	}
-
-	fbi->fb_start = dma_alloc_coherent(&pdev->dev, PAGE_ALIGN(fbi->fb_size),
-				&fbi->fb_start_dma, GFP_KERNEL);
-	if (fbi->fb_start == NULL) {
-		dev_err(&pdev->dev, "can't alloc framebuffer\n");
-		ret = -ENOMEM;
-		goto failed_destroy_mutex;
-	}
-	memset(fbi->fb_start, 0, fbi->fb_size);
-	dev_info(fbi->dev, "fb %dk allocated\n", fbi->fb_size/1024);
-
-	/* fb power on */
-	if (modes_num > 0)
-		mmpfb_power(fbi, 1);
-
-	ret = fb_info_setup(info, fbi);
-	if (ret < 0)
-		goto failed_free_buff;
-
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to register fb: %d\n", ret);
-		ret = -ENXIO;
-		goto failed_clear_info;
-	}
-
-	dev_info(fbi->dev, "loaded to /dev/fb%d <%s>.\n",
-		info->node, info->fix.id);
-
-#ifdef CONFIG_LOGO
-	if (fbi->fb_start) {
-		fb_prepare_logo(info, 0);
-		fb_show_logo(info, 0);
-	}
-#endif
-
-	return 0;
-
-failed_clear_info:
-	fb_info_clear(info);
-failed_free_buff:
-	dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbi->fb_size), fbi->fb_start,
-		fbi->fb_start_dma);
-failed_destroy_mutex:
-	mutex_destroy(&fbi->access_ok);
-failed:
-	dev_err(fbi->dev, "mmp-fb: frame buffer device init failed\n");
-
-	framebuffer_release(info);
-
-	return ret;
-}
-
-static struct platform_driver mmpfb_driver = {
-	.driver		= {
-		.name	= "mmp-fb",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= mmpfb_probe,
-};
-
-static int mmpfb_init(void)
-{
-	return platform_driver_register(&mmpfb_driver);
-}
-module_init(mmpfb_init);
-
-MODULE_AUTHOR("Zhou Zhu <zhou.zhu@marvell.com>");
-MODULE_DESCRIPTION("Framebuffer driver for Marvell displays");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/mmp/fb/mmpfb.h b/drivers/video/mmp/fb/mmpfb.h
deleted file mode 100644
index 88c23c10a9ec..000000000000
--- a/drivers/video/mmp/fb/mmpfb.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/drivers/video/mmp/fb/mmpfb.h
- * Framebuffer driver for Marvell Display controller.
- *
- * Copyright (C) 2012 Marvell Technology Group Ltd.
- * Authors: Zhou Zhu <zzhu3@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef _MMP_FB_H_
-#define _MMP_FB_H_
-
-#include <video/mmp_disp.h>
-#include <linux/fb.h>
-
-/* LCD controller private state. */
-struct mmpfb_info {
-	struct device	*dev;
-	int	id;
-	const char	*name;
-
-	struct fb_info	*fb_info;
-	/* basicaly videomode is for output */
-	struct fb_videomode	mode;
-	int	pix_fmt;
-
-	void	*fb_start;
-	int	fb_size;
-	dma_addr_t	fb_start_dma;
-
-	struct mmp_overlay	*overlay;
-	struct mmp_path	*path;
-
-	struct mutex	access_ok;
-
-	unsigned int		pseudo_palette[16];
-	int output_fmt;
-};
-
-#define MMPFB_DEFAULT_SIZE (PAGE_ALIGN(1920 * 1080 * 4 * 2))
-#endif /* _MMP_FB_H_ */
diff --git a/drivers/video/mmp/hw/Kconfig b/drivers/video/mmp/hw/Kconfig
deleted file mode 100644
index 02f109a20cd0..000000000000
--- a/drivers/video/mmp/hw/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-if MMP_DISP
-
-config MMP_DISP_CONTROLLER
-	bool "mmp display controller hw support"
-	depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988
-	default n
-	help
-		Marvell MMP display hw controller support
-		this controller is used on Marvell PXA910,
-		MMP2, MMP3, PXA988 chips
-
-config MMP_DISP_SPI
-	bool "mmp display controller spi port"
-	depends on MMP_DISP_CONTROLLER && SPI_MASTER
-	default y
-	help
-		Marvell MMP display hw controller spi port support
-		will register as a spi master for panel usage
-
-endif
diff --git a/drivers/video/mmp/hw/Makefile b/drivers/video/mmp/hw/Makefile
deleted file mode 100644
index 0000a714fedf..000000000000
--- a/drivers/video/mmp/hw/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_MMP_DISP_CONTROLLER)  += mmp_ctrl.o
-obj-$(CONFIG_MMP_DISP_SPI)	   += mmp_spi.o
diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c
deleted file mode 100644
index 8621a9f2bdcc..000000000000
--- a/drivers/video/mmp/hw/mmp_ctrl.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * linux/drivers/video/mmp/hw/mmp_ctrl.c
- * Marvell MMP series Display Controller support
- *
- * Copyright (C) 2012 Marvell Technology Group Ltd.
- * Authors:  Guoqing Li <ligq@marvell.com>
- *          Lisa Du <cldu@marvell.com>
- *          Zhou Zhu <zzhu3@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/vmalloc.h>
-#include <linux/uaccess.h>
-#include <linux/kthread.h>
-#include <linux/io.h>
-
-#include "mmp_ctrl.h"
-
-static irqreturn_t ctrl_handle_irq(int irq, void *dev_id)
-{
-	struct mmphw_ctrl *ctrl = (struct mmphw_ctrl *)dev_id;
-	u32 isr, imask, tmp;
-
-	isr = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR);
-	imask = readl_relaxed(ctrl->reg_base + SPU_IRQ_ENA);
-
-	do {
-		/* clear clock only */
-		tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR);
-		if (tmp & isr)
-			writel_relaxed(~isr, ctrl->reg_base + SPU_IRQ_ISR);
-	} while ((isr = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR)) & imask);
-
-	return IRQ_HANDLED;
-}
-
-static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt)
-{
-	u32 rbswap = 0, uvswap = 0, yuvswap = 0,
-		csc_en = 0, val = 0,
-		vid = overlay_is_vid(overlay);
-
-	switch (pix_fmt) {
-	case PIXFMT_RGB565:
-	case PIXFMT_RGB1555:
-	case PIXFMT_RGB888PACK:
-	case PIXFMT_RGB888UNPACK:
-	case PIXFMT_RGBA888:
-		rbswap = 1;
-		break;
-	case PIXFMT_VYUY:
-	case PIXFMT_YVU422P:
-	case PIXFMT_YVU420P:
-		uvswap = 1;
-		break;
-	case PIXFMT_YUYV:
-		yuvswap = 1;
-		break;
-	default:
-		break;
-	}
-
-	switch (pix_fmt) {
-	case PIXFMT_RGB565:
-	case PIXFMT_BGR565:
-		break;
-	case PIXFMT_RGB1555:
-	case PIXFMT_BGR1555:
-		val = 0x1;
-		break;
-	case PIXFMT_RGB888PACK:
-	case PIXFMT_BGR888PACK:
-		val = 0x2;
-		break;
-	case PIXFMT_RGB888UNPACK:
-	case PIXFMT_BGR888UNPACK:
-		val = 0x3;
-		break;
-	case PIXFMT_RGBA888:
-	case PIXFMT_BGRA888:
-		val = 0x4;
-		break;
-	case PIXFMT_UYVY:
-	case PIXFMT_VYUY:
-	case PIXFMT_YUYV:
-		val = 0x5;
-		csc_en = 1;
-		break;
-	case PIXFMT_YUV422P:
-	case PIXFMT_YVU422P:
-		val = 0x6;
-		csc_en = 1;
-		break;
-	case PIXFMT_YUV420P:
-	case PIXFMT_YVU420P:
-		val = 0x7;
-		csc_en = 1;
-		break;
-	default:
-		break;
-	}
-
-	return (dma_palette(0) | dma_fmt(vid, val) |
-		dma_swaprb(vid, rbswap) | dma_swapuv(vid, uvswap) |
-		dma_swapyuv(vid, yuvswap) | dma_csc(vid, csc_en));
-}
-
-static void dmafetch_set_fmt(struct mmp_overlay *overlay)
-{
-	u32 tmp;
-	struct mmp_path *path = overlay->path;
-	tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
-	tmp &= ~dma_mask(overlay_is_vid(overlay));
-	tmp |= fmt_to_reg(overlay, overlay->win.pix_fmt);
-	writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
-}
-
-static void overlay_set_win(struct mmp_overlay *overlay, struct mmp_win *win)
-{
-	struct lcd_regs *regs = path_regs(overlay->path);
-
-	/* assert win supported */
-	memcpy(&overlay->win, win, sizeof(struct mmp_win));
-
-	mutex_lock(&overlay->access_ok);
-
-	if (overlay_is_vid(overlay)) {
-		writel_relaxed(win->pitch[0], &regs->v_pitch_yc);
-		writel_relaxed(win->pitch[2] << 16 |
-				win->pitch[1], &regs->v_pitch_uv);
-
-		writel_relaxed((win->ysrc << 16) | win->xsrc, &regs->v_size);
-		writel_relaxed((win->ydst << 16) | win->xdst, &regs->v_size_z);
-		writel_relaxed(win->ypos << 16 | win->xpos, &regs->v_start);
-	} else {
-		writel_relaxed(win->pitch[0], &regs->g_pitch);
-
-		writel_relaxed((win->ysrc << 16) | win->xsrc, &regs->g_size);
-		writel_relaxed((win->ydst << 16) | win->xdst, &regs->g_size_z);
-		writel_relaxed(win->ypos << 16 | win->xpos, &regs->g_start);
-	}
-
-	dmafetch_set_fmt(overlay);
-	mutex_unlock(&overlay->access_ok);
-}
-
-static void dmafetch_onoff(struct mmp_overlay *overlay, int on)
-{
-	u32 mask = overlay_is_vid(overlay) ? CFG_DMA_ENA_MASK :
-		   CFG_GRA_ENA_MASK;
-	u32 enable = overlay_is_vid(overlay) ? CFG_DMA_ENA(1) : CFG_GRA_ENA(1);
-	u32 tmp;
-	struct mmp_path *path = overlay->path;
-
-	mutex_lock(&overlay->access_ok);
-	tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
-	tmp &= ~mask;
-	tmp |= (on ? enable : 0);
-	writel(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
-	mutex_unlock(&overlay->access_ok);
-}
-
-static void path_enabledisable(struct mmp_path *path, int on)
-{
-	u32 tmp;
-	mutex_lock(&path->access_ok);
-	tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path));
-	if (on)
-		tmp &= ~SCLK_DISABLE;
-	else
-		tmp |= SCLK_DISABLE;
-	writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path));
-	mutex_unlock(&path->access_ok);
-}
-
-static void path_onoff(struct mmp_path *path, int on)
-{
-	if (path->status == on) {
-		dev_info(path->dev, "path %s is already %s\n",
-				path->name, stat_name(path->status));
-		return;
-	}
-
-	if (on) {
-		path_enabledisable(path, 1);
-
-		if (path->panel && path->panel->set_onoff)
-			path->panel->set_onoff(path->panel, 1);
-	} else {
-		if (path->panel && path->panel->set_onoff)
-			path->panel->set_onoff(path->panel, 0);
-
-		path_enabledisable(path, 0);
-	}
-	path->status = on;
-}
-
-static void overlay_set_onoff(struct mmp_overlay *overlay, int on)
-{
-	if (overlay->status == on) {
-		dev_info(overlay_to_ctrl(overlay)->dev, "overlay %s is already %s\n",
-			overlay->path->name, stat_name(overlay->status));
-		return;
-	}
-	overlay->status = on;
-	dmafetch_onoff(overlay, on);
-	if (overlay->path->ops.check_status(overlay->path)
-			!= overlay->path->status)
-		path_onoff(overlay->path, on);
-}
-
-static void overlay_set_fetch(struct mmp_overlay *overlay, int fetch_id)
-{
-	overlay->dmafetch_id = fetch_id;
-}
-
-static int overlay_set_addr(struct mmp_overlay *overlay, struct mmp_addr *addr)
-{
-	struct lcd_regs *regs = path_regs(overlay->path);
-
-	/* FIXME: assert addr supported */
-	memcpy(&overlay->addr, addr, sizeof(struct mmp_addr));
-
-	if (overlay_is_vid(overlay)) {
-		writel_relaxed(addr->phys[0], &regs->v_y0);
-		writel_relaxed(addr->phys[1], &regs->v_u0);
-		writel_relaxed(addr->phys[2], &regs->v_v0);
-	} else
-		writel_relaxed(addr->phys[0], &regs->g_0);
-
-	return overlay->addr.phys[0];
-}
-
-static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode)
-{
-	struct lcd_regs *regs = path_regs(path);
-	u32 total_x, total_y, vsync_ctrl, tmp, sclk_src, sclk_div,
-		link_config = path_to_path_plat(path)->link_config,
-		dsi_rbswap = path_to_path_plat(path)->link_config;
-
-	/* FIXME: assert videomode supported */
-	memcpy(&path->mode, mode, sizeof(struct mmp_mode));
-
-	mutex_lock(&path->access_ok);
-
-	/* polarity of timing signals */
-	tmp = readl_relaxed(ctrl_regs(path) + intf_ctrl(path->id)) & 0x1;
-	tmp |= mode->vsync_invert ? 0 : 0x8;
-	tmp |= mode->hsync_invert ? 0 : 0x4;
-	tmp |= link_config & CFG_DUMBMODE_MASK;
-	tmp |= CFG_DUMB_ENA(1);
-	writel_relaxed(tmp, ctrl_regs(path) + intf_ctrl(path->id));
-
-	/* interface rb_swap setting */
-	tmp = readl_relaxed(ctrl_regs(path) + intf_rbswap_ctrl(path->id)) &
-		(~(CFG_INTFRBSWAP_MASK));
-	tmp |= dsi_rbswap & CFG_INTFRBSWAP_MASK;
-	writel_relaxed(tmp, ctrl_regs(path) + intf_rbswap_ctrl(path->id));
-
-	writel_relaxed((mode->yres << 16) | mode->xres, &regs->screen_active);
-	writel_relaxed((mode->left_margin << 16) | mode->right_margin,
-		&regs->screen_h_porch);
-	writel_relaxed((mode->upper_margin << 16) | mode->lower_margin,
-		&regs->screen_v_porch);
-	total_x = mode->xres + mode->left_margin + mode->right_margin +
-		mode->hsync_len;
-	total_y = mode->yres + mode->upper_margin + mode->lower_margin +
-		mode->vsync_len;
-	writel_relaxed((total_y << 16) | total_x, &regs->screen_size);
-
-	/* vsync ctrl */
-	if (path->output_type == PATH_OUT_DSI)
-		vsync_ctrl = 0x01330133;
-	else
-		vsync_ctrl = ((mode->xres + mode->right_margin) << 16)
-					| (mode->xres + mode->right_margin);
-	writel_relaxed(vsync_ctrl, &regs->vsync_ctrl);
-
-	/* set pixclock div */
-	sclk_src = clk_get_rate(path_to_ctrl(path)->clk);
-	sclk_div = sclk_src / mode->pixclock_freq;
-	if (sclk_div * mode->pixclock_freq < sclk_src)
-		sclk_div++;
-
-	dev_info(path->dev, "%s sclk_src %d sclk_div 0x%x pclk %d\n",
-			__func__, sclk_src, sclk_div, mode->pixclock_freq);
-
-	tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path));
-	tmp &= ~CLK_INT_DIV_MASK;
-	tmp |= sclk_div;
-	writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path));
-
-	mutex_unlock(&path->access_ok);
-}
-
-static struct mmp_overlay_ops mmphw_overlay_ops = {
-	.set_fetch = overlay_set_fetch,
-	.set_onoff = overlay_set_onoff,
-	.set_win = overlay_set_win,
-	.set_addr = overlay_set_addr,
-};
-
-static void ctrl_set_default(struct mmphw_ctrl *ctrl)
-{
-	u32 tmp, irq_mask;
-
-	/*
-	 * LCD Global control(LCD_TOP_CTRL) should be configed before
-	 * any other LCD registers read/write, or there maybe issues.
-	 */
-	tmp = readl_relaxed(ctrl->reg_base + LCD_TOP_CTRL);
-	tmp |= 0xfff0;
-	writel_relaxed(tmp, ctrl->reg_base + LCD_TOP_CTRL);
-
-
-	/* disable all interrupts */
-	irq_mask = path_imasks(0) | err_imask(0) |
-		   path_imasks(1) | err_imask(1);
-	tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ENA);
-	tmp &= ~irq_mask;
-	tmp |= irq_mask;
-	writel_relaxed(tmp, ctrl->reg_base + SPU_IRQ_ENA);
-}
-
-static void path_set_default(struct mmp_path *path)
-{
-	struct lcd_regs *regs = path_regs(path);
-	u32 dma_ctrl1, mask, tmp, path_config;
-
-	path_config = path_to_path_plat(path)->path_config;
-
-	/* Configure IOPAD: should be parallel only */
-	if (PATH_OUT_PARALLEL == path->output_type) {
-		mask = CFG_IOPADMODE_MASK | CFG_BURST_MASK | CFG_BOUNDARY_MASK;
-		tmp = readl_relaxed(ctrl_regs(path) + SPU_IOPAD_CONTROL);
-		tmp &= ~mask;
-		tmp |= path_config;
-		writel_relaxed(tmp, ctrl_regs(path) + SPU_IOPAD_CONTROL);
-	}
-
-	/* Select path clock source */
-	tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path));
-	tmp &= ~SCLK_SRC_SEL_MASK;
-	tmp |= path_config;
-	writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path));
-
-	/*
-	 * Configure default bits: vsync triggers DMA,
-	 * power save enable, configure alpha registers to
-	 * display 100% graphics, and set pixel command.
-	 */
-	dma_ctrl1 = 0x2032ff81;
-
-	dma_ctrl1 |= CFG_VSYNC_INV_MASK;
-	writel_relaxed(dma_ctrl1, ctrl_regs(path) + dma_ctrl(1, path->id));
-
-	/* Configure default register values */
-	writel_relaxed(0x00000000, &regs->blank_color);
-	writel_relaxed(0x00000000, &regs->g_1);
-	writel_relaxed(0x00000000, &regs->g_start);
-
-	/*
-	 * 1.enable multiple burst request in DMA AXI
-	 * bus arbiter for faster read if not tv path;
-	 * 2.enable horizontal smooth filter;
-	 */
-	mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK | CFG_ARBFAST_ENA(1);
-	tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
-	tmp |= mask;
-	if (PATH_TV == path->id)
-		tmp &= ~CFG_ARBFAST_ENA(1);
-	writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
-}
-
-static int path_init(struct mmphw_path_plat *path_plat,
-		struct mmp_mach_path_config *config)
-{
-	struct mmphw_ctrl *ctrl = path_plat->ctrl;
-	struct mmp_path_info *path_info;
-	struct mmp_path *path = NULL;
-
-	dev_info(ctrl->dev, "%s: %s\n", __func__, config->name);
-
-	/* init driver data */
-	path_info = kzalloc(sizeof(struct mmp_path_info), GFP_KERNEL);
-	if (!path_info) {
-		dev_err(ctrl->dev, "%s: unable to alloc path_info for %s\n",
-				__func__, config->name);
-		return 0;
-	}
-	path_info->name = config->name;
-	path_info->id = path_plat->id;
-	path_info->dev = ctrl->dev;
-	path_info->overlay_num = config->overlay_num;
-	path_info->overlay_ops = &mmphw_overlay_ops;
-	path_info->set_mode = path_set_mode;
-	path_info->plat_data = path_plat;
-
-	/* create/register platform device */
-	path = mmp_register_path(path_info);
-	if (!path) {
-		kfree(path_info);
-		return 0;
-	}
-	path_plat->path = path;
-	path_plat->path_config = config->path_config;
-	path_plat->link_config = config->link_config;
-	path_plat->dsi_rbswap = config->dsi_rbswap;
-	path_set_default(path);
-
-	kfree(path_info);
-	return 1;
-}
-
-static void path_deinit(struct mmphw_path_plat *path_plat)
-{
-	if (!path_plat)
-		return;
-
-	if (path_plat->path)
-		mmp_unregister_path(path_plat->path);
-}
-
-static int mmphw_probe(struct platform_device *pdev)
-{
-	struct mmp_mach_plat_info *mi;
-	struct resource *res;
-	int ret, i, size, irq;
-	struct mmphw_path_plat *path_plat;
-	struct mmphw_ctrl *ctrl = NULL;
-
-	/* get resources from platform data */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "%s: no IO memory defined\n", __func__);
-		ret = -ENOENT;
-		goto failed;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "%s: no IRQ defined\n", __func__);
-		ret = -ENOENT;
-		goto failed;
-	}
-
-	/* get configs from platform data */
-	mi = pdev->dev.platform_data;
-	if (mi == NULL || !mi->path_num || !mi->paths) {
-		dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
-		ret = -EINVAL;
-		goto failed;
-	}
-
-	/* allocate */
-	size = sizeof(struct mmphw_ctrl) + sizeof(struct mmphw_path_plat) *
-	       mi->path_num;
-	ctrl = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
-	if (!ctrl) {
-		ret = -ENOMEM;
-		goto failed;
-	}
-
-	ctrl->name = mi->name;
-	ctrl->path_num = mi->path_num;
-	ctrl->dev = &pdev->dev;
-	ctrl->irq = irq;
-	platform_set_drvdata(pdev, ctrl);
-	mutex_init(&ctrl->access_ok);
-
-	/* map registers.*/
-	if (!devm_request_mem_region(ctrl->dev, res->start,
-			resource_size(res), ctrl->name)) {
-		dev_err(ctrl->dev,
-			"can't request region for resource %pR\n", res);
-		ret = -EINVAL;
-		goto failed;
-	}
-
-	ctrl->reg_base = devm_ioremap_nocache(ctrl->dev,
-			res->start, resource_size(res));
-	if (ctrl->reg_base == NULL) {
-		dev_err(ctrl->dev, "%s: res %x - %x map failed\n", __func__,
-			res->start, res->end);
-		ret = -ENOMEM;
-		goto failed;
-	}
-
-	/* request irq */
-	ret = devm_request_irq(ctrl->dev, ctrl->irq, ctrl_handle_irq,
-		IRQF_SHARED, "lcd_controller", ctrl);
-	if (ret < 0) {
-		dev_err(ctrl->dev, "%s unable to request IRQ %d\n",
-				__func__, ctrl->irq);
-		ret = -ENXIO;
-		goto failed;
-	}
-
-	/* get clock */
-	ctrl->clk = devm_clk_get(ctrl->dev, mi->clk_name);
-	if (IS_ERR(ctrl->clk)) {
-		dev_err(ctrl->dev, "unable to get clk %s\n", mi->clk_name);
-		ret = -ENOENT;
-		goto failed;
-	}
-	clk_prepare_enable(ctrl->clk);
-
-	/* init global regs */
-	ctrl_set_default(ctrl);
-
-	/* init pathes from machine info and register them */
-	for (i = 0; i < ctrl->path_num; i++) {
-		/* get from config and machine info */
-		path_plat = &ctrl->path_plats[i];
-		path_plat->id = i;
-		path_plat->ctrl = ctrl;
-
-		/* path init */
-		if (!path_init(path_plat, &mi->paths[i])) {
-			ret = -EINVAL;
-			goto failed_path_init;
-		}
-	}
-
-#ifdef CONFIG_MMP_DISP_SPI
-	ret = lcd_spi_register(ctrl);
-	if (ret < 0)
-		goto failed_path_init;
-#endif
-
-	dev_info(ctrl->dev, "device init done\n");
-
-	return 0;
-
-failed_path_init:
-	for (i = 0; i < ctrl->path_num; i++) {
-		path_plat = &ctrl->path_plats[i];
-		path_deinit(path_plat);
-	}
-
-	clk_disable_unprepare(ctrl->clk);
-failed:
-	dev_err(&pdev->dev, "device init failed\n");
-
-	return ret;
-}
-
-static struct platform_driver mmphw_driver = {
-	.driver		= {
-		.name	= "mmp-disp",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= mmphw_probe,
-};
-
-static int mmphw_init(void)
-{
-	return platform_driver_register(&mmphw_driver);
-}
-module_init(mmphw_init);
-
-MODULE_AUTHOR("Li Guoqing<ligq@marvell.com>");
-MODULE_DESCRIPTION("Framebuffer driver for mmp");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/mmp/hw/mmp_ctrl.h
deleted file mode 100644
index 53301cfdb1ae..000000000000
--- a/drivers/video/mmp/hw/mmp_ctrl.h
+++ /dev/null
@@ -1,1502 +0,0 @@
-/*
- * drivers/video/mmp/hw/mmp_ctrl.h
- *
- *
- * Copyright (C) 2012 Marvell Technology Group Ltd.
- * Authors:  Guoqing Li <ligq@marvell.com>
- *          Lisa Du <cldu@marvell.com>
- *          Zhou Zhu <zzhu3@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef _MMP_CTRL_H_
-#define _MMP_CTRL_H_
-
-#include <video/mmp_disp.h>
-
-/* ------------< LCD register >------------ */
-struct lcd_regs {
-/* TV patch register for MMP2 */
-/* 32 bit		TV Video Frame0 Y Starting Address */
-#define LCD_TVD_START_ADDR_Y0			(0x0000)
-/* 32 bit		TV Video Frame0 U Starting Address */
-#define LCD_TVD_START_ADDR_U0			(0x0004)
-/* 32 bit		TV Video Frame0 V Starting Address */
-#define LCD_TVD_START_ADDR_V0			(0x0008)
-/* 32 bit		TV Video Frame0 Command Starting Address */
-#define LCD_TVD_START_ADDR_C0			(0x000C)
-/* 32 bit		TV Video Frame1 Y Starting Address Register*/
-#define LCD_TVD_START_ADDR_Y1			(0x0010)
-/* 32 bit		TV Video Frame1 U Starting Address Register*/
-#define LCD_TVD_START_ADDR_U1			(0x0014)
-/* 32 bit		TV Video Frame1 V Starting Address Register*/
-#define LCD_TVD_START_ADDR_V1			(0x0018)
-/* 32 bit		TV Video Frame1 Command Starting Address Register*/
-#define LCD_TVD_START_ADDR_C1			(0x001C)
-/* 32 bit		TV Video Y andC Line Length(Pitch)Register*/
-#define LCD_TVD_PITCH_YC			(0x0020)
-/* 32 bit		TV Video U andV Line Length(Pitch)Register*/
-#define LCD_TVD_PITCH_UV			(0x0024)
-/* 32 bit	  TV Video Starting Point on Screen Register*/
-#define LCD_TVD_OVSA_HPXL_VLN			(0x0028)
-/* 32 bit		TV Video Source Size Register*/
-#define LCD_TVD_HPXL_VLN			(0x002C)
-/* 32 bit	  TV Video Destination Size (After Zooming)Register*/
-#define LCD_TVDZM_HPXL_VLN			(0x0030)
-	u32 v_y0;
-	u32 v_u0;
-	u32 v_v0;
-	u32 v_c0;
-	u32 v_y1;
-	u32 v_u1;
-	u32 v_v1;
-	u32 v_c1;
-	u32 v_pitch_yc;		/* Video Y and C Line Length (Pitch) */
-	u32 v_pitch_uv;		/* Video U and V Line Length (Pitch) */
-	u32 v_start;		/* Video Starting Point on Screen */
-	u32 v_size;			/* Video Source Size */
-	u32 v_size_z;		/* Video Destination Size (After Zooming) */
-
-/* 32 bit	   TV Graphic Frame 0 Starting Address Register*/
-#define LCD_TVG_START_ADDR0				(0x0034)
-/* 32 bit	  TV Graphic Frame 1 Starting Address Register*/
-#define LCD_TVG_START_ADDR1				(0x0038)
-/* 32 bit		TV Graphic Line Length(Pitch)Register*/
-#define LCD_TVG_PITCH					(0x003C)
-/* 32 bit		TV Graphic Starting Point on Screen Register*/
-#define LCD_TVG_OVSA_HPXL_VLN				(0x0040)
-/* 32 bit		TV Graphic Source Size Register*/
-#define LCD_TVG_HPXL_VLN				(0x0044)
-/* 32 bit		TV Graphic Destination size (after Zooming)Register*/
-#define LCD_TVGZM_HPXL_VLN				(0x0048)
-	u32 g_0;			/* Graphic Frame 0/1 Starting Address */
-	u32 g_1;
-	u32 g_pitch;		/* Graphic Line Length (Pitch) */
-	u32 g_start;		/* Graphic Starting Point on Screen */
-	u32 g_size;			/* Graphic Source Size */
-	u32 g_size_z;		/* Graphic Destination Size (After Zooming) */
-
-/* 32 bit	  TV Hardware Cursor Starting Point on screen Register*/
-#define LCD_TVC_OVSA_HPXL_VLN				(0x004C)
-/* 32 bit		TV Hardware Cursor Size Register */
-#define LCD_TVC_HPXL_VLN				(0x0050)
-	u32 hc_start;			/* Hardware Cursor */
-	u32 hc_size;			/* Hardware Cursor */
-
-/* 32 bit		TV Total Screen Size Register*/
-#define LCD_TV_V_H_TOTAL				(0x0054)
-/* 32 bit		TV Screen Active Size Register*/
-#define LCD_TV_V_H_ACTIVE				(0x0058)
-/* 32 bit		TV Screen Horizontal Porch Register*/
-#define LCD_TV_H_PORCH					(0x005C)
-/* 32 bit		TV Screen Vertical Porch Register*/
-#define LCD_TV_V_PORCH					(0x0060)
-	u32 screen_size;		/* Screen Total Size */
-	u32 screen_active;		/* Screen Active Size */
-	u32 screen_h_porch;		/* Screen Horizontal Porch */
-	u32 screen_v_porch;		/* Screen Vertical Porch */
-
-/* 32 bit		TV Screen Blank Color Register*/
-#define LCD_TV_BLANKCOLOR				(0x0064)
-/* 32 bit		TV Hardware Cursor Color1 Register*/
-#define LCD_TV_ALPHA_COLOR1				(0x0068)
-/* 32 bit		TV Hardware Cursor Color2 Register*/
-#define LCD_TV_ALPHA_COLOR2				(0x006C)
-	u32 blank_color;		/* Screen Blank Color */
-	u32 hc_Alpha_color1;	/* Hardware Cursor Color1 */
-	u32 hc_Alpha_color2;	/* Hardware Cursor Color2 */
-
-/* 32 bit		TV Video Y Color Key Control*/
-#define LCD_TV_COLORKEY_Y				(0x0070)
-/* 32 bit		TV Video U Color Key Control*/
-#define LCD_TV_COLORKEY_U				(0x0074)
-/* 32 bit		TV Video V Color Key Control*/
-#define LCD_TV_COLORKEY_V				(0x0078)
-	u32 v_colorkey_y;		/* Video Y Color Key Control */
-	u32 v_colorkey_u;		/* Video U Color Key Control */
-	u32 v_colorkey_v;		/* Video V Color Key Control */
-
-/* 32 bit		TV VSYNC PulsePixel Edge Control Register*/
-#define LCD_TV_SEPXLCNT					(0x007C)
-	u32 vsync_ctrl;			/* VSYNC PulsePixel Edge Control */
-};
-
-#define intf_ctrl(id)		((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \
-				LCD_DUMB2_CTRL) : LCD_SPU_DUMB_CTRL)
-#define dma_ctrl0(id)	   ((id) ? (((id) & 1) ? LCD_TV_CTRL0 : \
-				LCD_PN2_CTRL0) : LCD_SPU_DMA_CTRL0)
-#define dma_ctrl1(id)	   ((id) ? (((id) & 1) ? LCD_TV_CTRL1 : \
-				LCD_PN2_CTRL1) : LCD_SPU_DMA_CTRL1)
-#define dma_ctrl(ctrl1, id)	 (ctrl1 ? dma_ctrl1(id) : dma_ctrl0(id))
-
-/* 32 bit		TV Path DMA Control 0*/
-#define LCD_TV_CTRL0					(0x0080)
-/* 32 bit		TV Path DMA Control 1*/
-#define LCD_TV_CTRL1					(0x0084)
-/* 32 bit		TV Path Video Contrast*/
-#define LCD_TV_CONTRAST					(0x0088)
-/* 32 bit		TV Path Video Saturation*/
-#define LCD_TV_SATURATION				(0x008C)
-/* 32 bit		TV Path Video Hue Adjust*/
-#define LCD_TV_CBSH_HUE					(0x0090)
-/* 32 bit TV Path TVIF Control	Register */
-#define LCD_TVIF_CTRL					(0x0094)
-#define TV_VBLNK_VALID_EN				(1 << 12)
-
-/* 32 bit TV Path I/O Pad Control*/
-#define LCD_TVIOPAD_CTRL				(0x0098)
-/* 32 bit TV Path Cloc	Divider  */
-#define LCD_TCLK_DIV					(0x009C)
-
-#define LCD_SCLK(path) ((PATH_PN == path->id) ? LCD_CFG_SCLK_DIV :\
-	((PATH_TV == path->id) ? LCD_TCLK_DIV : LCD_PN2_SCLK_DIV))
-#define intf_rbswap_ctrl(id)	((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \
-				PN2_IOPAD_CONTROL) : LCD_TOP_CTRL)
-
-/* dither configure */
-#ifdef CONFIG_CPU_PXA988
-#define LCD_DITHER_CTRL				(0x01EC)
-#else
-#define LCD_DITHER_CTRL				(0x00A0)
-#endif
-
-#define DITHER_TBL_INDEX_SEL(s)		((s) << 16)
-#define DITHER_MODE2(m)				((m) << 12)
-#define DITHER_MODE2_SHIFT			(12)
-#define DITHER_4X8_EN2				(1 << 9)
-#define DITHER_4X8_EN2_SHIFT		(9)
-#define DITHER_EN2					(1 << 8)
-#define DITHER_MODE1(m)				((m) << 4)
-#define DITHER_MODE1_SHIFT			(4)
-#define DITHER_4X8_EN1				(1 << 1)
-#define DITHER_4X8_EN1_SHIFT		(1)
-#define DITHER_EN1					(1)
-
-/* dither table data was fixed by video bpp of input and output*/
-#ifdef CONFIG_CPU_PXA988
-#define DITHER_TB_4X4_INDEX0		(0x6e4ca280)
-#define DITHER_TB_4X4_INDEX1		(0x5d7f91b3)
-#define DITHER_TB_4X8_INDEX0		(0xb391a280)
-#define DITHER_TB_4X8_INDEX1		(0x7f5d6e4c)
-#define DITHER_TB_4X8_INDEX2		(0x80a291b3)
-#define DITHER_TB_4X8_INDEX3		(0x4c6e5d7f)
-#define LCD_DITHER_TBL_DATA		(0x01F0)
-#else
-#define DITHER_TB_4X4_INDEX0		(0x3b19f7d5)
-#define DITHER_TB_4X4_INDEX1		(0x082ac4e6)
-#define DITHER_TB_4X8_INDEX0		(0xf7d508e6)
-#define DITHER_TB_4X8_INDEX1		(0x3b194c2a)
-#define DITHER_TB_4X8_INDEX2		(0xc4e6d5f7)
-#define DITHER_TB_4X8_INDEX3		(0x082a193b)
-#define LCD_DITHER_TBL_DATA		(0x00A4)
-#endif
-
-/* Video Frame 0&1 start address registers */
-#define	LCD_SPU_DMA_START_ADDR_Y0	0x00C0
-#define	LCD_SPU_DMA_START_ADDR_U0	0x00C4
-#define	LCD_SPU_DMA_START_ADDR_V0	0x00C8
-#define LCD_CFG_DMA_START_ADDR_0	0x00CC /* Cmd address */
-#define	LCD_SPU_DMA_START_ADDR_Y1	0x00D0
-#define	LCD_SPU_DMA_START_ADDR_U1	0x00D4
-#define	LCD_SPU_DMA_START_ADDR_V1	0x00D8
-#define LCD_CFG_DMA_START_ADDR_1	0x00DC /* Cmd address */
-
-/* YC & UV Pitch */
-#define LCD_SPU_DMA_PITCH_YC		0x00E0
-#define	 SPU_DMA_PITCH_C(c)		((c)<<16)
-#define	 SPU_DMA_PITCH_Y(y)		(y)
-#define LCD_SPU_DMA_PITCH_UV		0x00E4
-#define	 SPU_DMA_PITCH_V(v)		((v)<<16)
-#define	 SPU_DMA_PITCH_U(u)		(u)
-
-/* Video Starting Point on Screen Register */
-#define LCD_SPUT_DMA_OVSA_HPXL_VLN		0x00E8
-#define	 CFG_DMA_OVSA_VLN(y)			((y)<<16) /* 0~0xfff */
-#define	 CFG_DMA_OVSA_HPXL(x)			(x)	 /* 0~0xfff */
-
-/* Video Size Register */
-#define LCD_SPU_DMA_HPXL_VLN			0x00EC
-#define	 CFG_DMA_VLN(y)				((y)<<16)
-#define	 CFG_DMA_HPXL(x)			(x)
-
-/* Video Size After zooming Register */
-#define LCD_SPU_DZM_HPXL_VLN			0x00F0
-#define	 CFG_DZM_VLN(y)				((y)<<16)
-#define	 CFG_DZM_HPXL(x)			(x)
-
-/* Graphic Frame 0&1 Starting Address Register */
-#define LCD_CFG_GRA_START_ADDR0			0x00F4
-#define LCD_CFG_GRA_START_ADDR1			0x00F8
-
-/* Graphic Frame Pitch */
-#define LCD_CFG_GRA_PITCH			0x00FC
-
-/* Graphic Starting Point on Screen Register */
-#define LCD_SPU_GRA_OVSA_HPXL_VLN		0x0100
-#define	 CFG_GRA_OVSA_VLN(y)			((y)<<16)
-#define	 CFG_GRA_OVSA_HPXL(x)			(x)
-
-/* Graphic Size Register */
-#define LCD_SPU_GRA_HPXL_VLN			0x0104
-#define	 CFG_GRA_VLN(y)				((y)<<16)
-#define	 CFG_GRA_HPXL(x)			(x)
-
-/* Graphic Size after Zooming Register */
-#define LCD_SPU_GZM_HPXL_VLN			0x0108
-#define	 CFG_GZM_VLN(y)				((y)<<16)
-#define	 CFG_GZM_HPXL(x)			(x)
-
-/* HW Cursor Starting Point on Screen Register */
-#define LCD_SPU_HWC_OVSA_HPXL_VLN		0x010C
-#define	 CFG_HWC_OVSA_VLN(y)			((y)<<16)
-#define	 CFG_HWC_OVSA_HPXL(x)			(x)
-
-/* HW Cursor Size */
-#define LCD_SPU_HWC_HPXL_VLN			0x0110
-#define	 CFG_HWC_VLN(y)				((y)<<16)
-#define	 CFG_HWC_HPXL(x)			(x)
-
-/* Total Screen Size Register */
-#define LCD_SPUT_V_H_TOTAL			0x0114
-#define	 CFG_V_TOTAL(y)				((y)<<16)
-#define	 CFG_H_TOTAL(x)				(x)
-
-/* Total Screen Active Size Register */
-#define LCD_SPU_V_H_ACTIVE			0x0118
-#define	 CFG_V_ACTIVE(y)			((y)<<16)
-#define	 CFG_H_ACTIVE(x)			(x)
-
-/* Screen H&V Porch Register */
-#define LCD_SPU_H_PORCH				0x011C
-#define	 CFG_H_BACK_PORCH(b)			((b)<<16)
-#define	 CFG_H_FRONT_PORCH(f)			(f)
-#define LCD_SPU_V_PORCH				0x0120
-#define	 CFG_V_BACK_PORCH(b)			((b)<<16)
-#define	 CFG_V_FRONT_PORCH(f)			(f)
-
-/* Screen Blank Color Register */
-#define LCD_SPU_BLANKCOLOR			0x0124
-#define  CFG_BLANKCOLOR_MASK			0x00FFFFFF
-#define  CFG_BLANKCOLOR_R_MASK			0x000000FF
-#define  CFG_BLANKCOLOR_G_MASK			0x0000FF00
-#define  CFG_BLANKCOLOR_B_MASK			0x00FF0000
-
-/* HW Cursor Color 1&2 Register */
-#define LCD_SPU_ALPHA_COLOR1			0x0128
-#define	 CFG_HWC_COLOR1				0x00FFFFFF
-#define	 CFG_HWC_COLOR1_R(red)			((red)<<16)
-#define	 CFG_HWC_COLOR1_G(green)		((green)<<8)
-#define	 CFG_HWC_COLOR1_B(blue)			(blue)
-#define	 CFG_HWC_COLOR1_R_MASK			0x000000FF
-#define	 CFG_HWC_COLOR1_G_MASK			0x0000FF00
-#define	 CFG_HWC_COLOR1_B_MASK			0x00FF0000
-#define LCD_SPU_ALPHA_COLOR2			0x012C
-#define	 CFG_HWC_COLOR2				0x00FFFFFF
-#define	 CFG_HWC_COLOR2_R_MASK			0x000000FF
-#define	 CFG_HWC_COLOR2_G_MASK			0x0000FF00
-#define	 CFG_HWC_COLOR2_B_MASK			0x00FF0000
-
-/* Video YUV Color Key Control */
-#define LCD_SPU_COLORKEY_Y			0x0130
-#define	 CFG_CKEY_Y2(y2)			((y2)<<24)
-#define	 CFG_CKEY_Y2_MASK			0xFF000000
-#define	 CFG_CKEY_Y1(y1)			((y1)<<16)
-#define	 CFG_CKEY_Y1_MASK			0x00FF0000
-#define	 CFG_CKEY_Y(y)				((y)<<8)
-#define	 CFG_CKEY_Y_MASK			0x0000FF00
-#define	 CFG_ALPHA_Y(y)				(y)
-#define	 CFG_ALPHA_Y_MASK			0x000000FF
-#define LCD_SPU_COLORKEY_U			0x0134
-#define	 CFG_CKEY_U2(u2)			((u2)<<24)
-#define	 CFG_CKEY_U2_MASK			0xFF000000
-#define	 CFG_CKEY_U1(u1)			((u1)<<16)
-#define	 CFG_CKEY_U1_MASK			0x00FF0000
-#define	 CFG_CKEY_U(u)				((u)<<8)
-#define	 CFG_CKEY_U_MASK			0x0000FF00
-#define	 CFG_ALPHA_U(u)				(u)
-#define	 CFG_ALPHA_U_MASK			0x000000FF
-#define LCD_SPU_COLORKEY_V			0x0138
-#define	 CFG_CKEY_V2(v2)			((v2)<<24)
-#define	 CFG_CKEY_V2_MASK			0xFF000000
-#define	 CFG_CKEY_V1(v1)			((v1)<<16)
-#define	 CFG_CKEY_V1_MASK			0x00FF0000
-#define	 CFG_CKEY_V(v)				((v)<<8)
-#define	 CFG_CKEY_V_MASK			0x0000FF00
-#define	 CFG_ALPHA_V(v)				(v)
-#define	 CFG_ALPHA_V_MASK			0x000000FF
-
-/* Graphics/Video DMA color key enable bits in LCD_TV_CTRL1 */
-#define	 CFG_CKEY_GRA				0x2
-#define	 CFG_CKEY_DMA				0x1
-
-/* Interlace mode enable bits in LCD_TV_CTRL1 */
-#define     CFG_TV_INTERLACE_EN                 (1 << 22)
-#define     CFG_TV_NIB                          (1 << 0)
-
-#define LCD_PN_SEPXLCNT				0x013c /* MMP2 */
-
-/* SPI Read Data Register */
-#define LCD_SPU_SPI_RXDATA			0x0140
-
-/* Smart Panel Read Data Register */
-#define LCD_SPU_ISA_RSDATA			0x0144
-#define	 ISA_RXDATA_16BIT_1_DATA_MASK		0x000000FF
-#define	 ISA_RXDATA_16BIT_2_DATA_MASK		0x0000FF00
-#define	 ISA_RXDATA_16BIT_3_DATA_MASK		0x00FF0000
-#define	 ISA_RXDATA_16BIT_4_DATA_MASK		0xFF000000
-#define	 ISA_RXDATA_32BIT_1_DATA_MASK		0x00FFFFFF
-
-#define LCD_SPU_DBG_ISA				(0x0148) /* TTC */
-#define LCD_SPU_DMAVLD_YC			(0x014C)
-#define LCD_SPU_DMAVLD_UV			(0x0150)
-#define LCD_SPU_DMAVLD_UVSPU_GRAVLD		(0x0154)
-
-#define LCD_READ_IOPAD				(0x0148) /* MMP2*/
-#define LCD_DMAVLD_YC				(0x014C)
-#define LCD_DMAVLD_UV				(0x0150)
-#define LCD_TVGGRAVLD_HLEN			(0x0154)
-
-/* HWC SRAM Read Data Register */
-#define LCD_SPU_HWC_RDDAT			0x0158
-
-/* Gamma Table SRAM Read Data Register */
-#define LCD_SPU_GAMMA_RDDAT			0x015c
-#define	 CFG_GAMMA_RDDAT_MASK			0x000000FF
-
-/* Palette Table SRAM Read Data Register */
-#define LCD_SPU_PALETTE_RDDAT			0x0160
-#define	 CFG_PALETTE_RDDAT_MASK			0x00FFFFFF
-
-#define LCD_SPU_DBG_DMATOP			(0x0164) /* TTC */
-#define LCD_SPU_DBG_GRATOP			(0x0168)
-#define LCD_SPU_DBG_TXCTRL			(0x016C)
-#define LCD_SPU_DBG_SLVTOP			(0x0170)
-#define LCD_SPU_DBG_MUXTOP			(0x0174)
-
-#define LCD_SLV_DBG				(0x0164) /* MMP2 */
-#define LCD_TVDVLD_YC				(0x0168)
-#define LCD_TVDVLD_UV				(0x016C)
-#define LCD_TVC_RDDAT				(0x0170)
-#define LCD_TV_GAMMA_RDDAT			(0x0174)
-
-/* I/O Pads Input Read Only Register */
-#define LCD_SPU_IOPAD_IN			0x0178
-#define	 CFG_IOPAD_IN_MASK			0x0FFFFFFF
-
-#define LCD_TV_PALETTE_RDDAT			(0x0178) /* MMP2 */
-
-/* Reserved Read Only Registers */
-#define LCD_CFG_RDREG5F				0x017C
-#define	 IRE_FRAME_CNT_MASK			0x000000C0
-#define	 IPE_FRAME_CNT_MASK			0x00000030
-#define	 GRA_FRAME_CNT_MASK			0x0000000C /* Graphic */
-#define	 DMA_FRAME_CNT_MASK			0x00000003 /* Video */
-
-#define LCD_FRAME_CNT				(0x017C) /* MMP2 */
-
-/* SPI Control Register. */
-#define LCD_SPU_SPI_CTRL			0x0180
-#define	 CFG_SCLKCNT(div)			((div)<<24) /* 0xFF~0x2 */
-#define	 CFG_SCLKCNT_MASK			0xFF000000
-#define	 CFG_RXBITS(rx)				(((rx) - 1)<<16) /* 0x1F~0x1 */
-#define	 CFG_RXBITS_MASK			0x00FF0000
-#define	 CFG_TXBITS(tx)				(((tx) - 1)<<8) /* 0x1F~0x1 */
-#define	 CFG_TXBITS_MASK			0x0000FF00
-#define	 CFG_CLKINV(clk)			((clk)<<7)
-#define	 CFG_CLKINV_MASK			0x00000080
-#define	 CFG_KEEPXFER(transfer)			((transfer)<<6)
-#define	 CFG_KEEPXFER_MASK			0x00000040
-#define	 CFG_RXBITSTO0(rx)			((rx)<<5)
-#define	 CFG_RXBITSTO0_MASK			0x00000020
-#define	 CFG_TXBITSTO0(tx)			((tx)<<4)
-#define	 CFG_TXBITSTO0_MASK			0x00000010
-#define	 CFG_SPI_ENA(spi)			((spi)<<3)
-#define	 CFG_SPI_ENA_MASK			0x00000008
-#define	 CFG_SPI_SEL(spi)			((spi)<<2)
-#define	 CFG_SPI_SEL_MASK			0x00000004
-#define	 CFG_SPI_3W4WB(wire)			((wire)<<1)
-#define	 CFG_SPI_3W4WB_MASK			0x00000002
-#define	 CFG_SPI_START(start)			(start)
-#define	 CFG_SPI_START_MASK			0x00000001
-
-/* SPI Tx Data Register */
-#define LCD_SPU_SPI_TXDATA			0x0184
-
-/*
-   1. Smart Pannel 8-bit Bus Control Register.
-   2. AHB Slave Path Data Port Register
-*/
-#define LCD_SPU_SMPN_CTRL			0x0188
-
-/* DMA Control 0 Register */
-#define LCD_SPU_DMA_CTRL0			0x0190
-#define	 CFG_NOBLENDING(nb)			((nb)<<31)
-#define	 CFG_NOBLENDING_MASK			0x80000000
-#define	 CFG_GAMMA_ENA(gn)			((gn)<<30)
-#define	 CFG_GAMMA_ENA_MASK			0x40000000
-#define	 CFG_CBSH_ENA(cn)			((cn)<<29)
-#define	 CFG_CBSH_ENA_MASK			0x20000000
-#define	 CFG_PALETTE_ENA(pn)			((pn)<<28)
-#define	 CFG_PALETTE_ENA_MASK			0x10000000
-#define	 CFG_ARBFAST_ENA(an)			((an)<<27)
-#define	 CFG_ARBFAST_ENA_MASK			0x08000000
-#define	 CFG_HWC_1BITMOD(mode)			((mode)<<26)
-#define	 CFG_HWC_1BITMOD_MASK			0x04000000
-#define	 CFG_HWC_1BITENA(mn)			((mn)<<25)
-#define	 CFG_HWC_1BITENA_MASK			0x02000000
-#define	 CFG_HWC_ENA(cn)			((cn)<<24)
-#define	 CFG_HWC_ENA_MASK			0x01000000
-#define	 CFG_DMAFORMAT(dmaformat)		((dmaformat)<<20)
-#define	 CFG_DMAFORMAT_MASK			0x00F00000
-#define	 CFG_GRAFORMAT(graformat)		((graformat)<<16)
-#define	 CFG_GRAFORMAT_MASK			0x000F0000
-/* for graphic part */
-#define	 CFG_GRA_FTOGGLE(toggle)		((toggle)<<15)
-#define	 CFG_GRA_FTOGGLE_MASK			0x00008000
-#define	 CFG_GRA_HSMOOTH(smooth)		((smooth)<<14)
-#define	 CFG_GRA_HSMOOTH_MASK			0x00004000
-#define	 CFG_GRA_TSTMODE(test)			((test)<<13)
-#define	 CFG_GRA_TSTMODE_MASK			0x00002000
-#define	 CFG_GRA_SWAPRB(swap)			((swap)<<12)
-#define	 CFG_GRA_SWAPRB_MASK			0x00001000
-#define	 CFG_GRA_SWAPUV(swap)			((swap)<<11)
-#define	 CFG_GRA_SWAPUV_MASK			0x00000800
-#define	 CFG_GRA_SWAPYU(swap)			((swap)<<10)
-#define	 CFG_GRA_SWAPYU_MASK			0x00000400
-#define	 CFG_GRA_SWAP_MASK			0x00001C00
-#define	 CFG_YUV2RGB_GRA(cvrt)			((cvrt)<<9)
-#define	 CFG_YUV2RGB_GRA_MASK			0x00000200
-#define	 CFG_GRA_ENA(gra)			((gra)<<8)
-#define	 CFG_GRA_ENA_MASK			0x00000100
-#define dma0_gfx_masks	(CFG_GRAFORMAT_MASK | CFG_GRA_FTOGGLE_MASK | \
-	CFG_GRA_HSMOOTH_MASK | CFG_GRA_TSTMODE_MASK | CFG_GRA_SWAP_MASK | \
-	CFG_YUV2RGB_GRA_MASK | CFG_GRA_ENA_MASK)
-/* for video part */
-#define	 CFG_DMA_FTOGGLE(toggle)		((toggle)<<7)
-#define	 CFG_DMA_FTOGGLE_MASK			0x00000080
-#define	 CFG_DMA_HSMOOTH(smooth)		((smooth)<<6)
-#define	 CFG_DMA_HSMOOTH_MASK			0x00000040
-#define	 CFG_DMA_TSTMODE(test)			((test)<<5)
-#define	 CFG_DMA_TSTMODE_MASK			0x00000020
-#define	 CFG_DMA_SWAPRB(swap)			((swap)<<4)
-#define	 CFG_DMA_SWAPRB_MASK			0x00000010
-#define	 CFG_DMA_SWAPUV(swap)			((swap)<<3)
-#define	 CFG_DMA_SWAPUV_MASK			0x00000008
-#define	 CFG_DMA_SWAPYU(swap)			((swap)<<2)
-#define	 CFG_DMA_SWAPYU_MASK			0x00000004
-#define	 CFG_DMA_SWAP_MASK			0x0000001C
-#define	 CFG_YUV2RGB_DMA(cvrt)			((cvrt)<<1)
-#define	 CFG_YUV2RGB_DMA_MASK			0x00000002
-#define	 CFG_DMA_ENA(video)			(video)
-#define	 CFG_DMA_ENA_MASK			0x00000001
-#define dma0_vid_masks	(CFG_DMAFORMAT_MASK | CFG_DMA_FTOGGLE_MASK | \
-	CFG_DMA_HSMOOTH_MASK | CFG_DMA_TSTMODE_MASK | CFG_DMA_SWAP_MASK | \
-	CFG_YUV2RGB_DMA_MASK | CFG_DMA_ENA_MASK)
-#define dma_palette(val)		((val ? 1 : 0) << 28)
-#define dma_fmt(vid, val)		((val & 0xf) << ((vid) ? 20 : 16))
-#define dma_swaprb(vid, val)		((val ? 1 : 0) << ((vid) ? 4 : 12))
-#define dma_swapuv(vid, val)		((val ? 1 : 0) << ((vid) ? 3 : 11))
-#define dma_swapyuv(vid, val)		((val ? 1 : 0) << ((vid) ? 2 : 10))
-#define dma_csc(vid, val)		((val ? 1 : 0) << ((vid) ? 1 : 9))
-#define dma_hsmooth(vid, val)		((val ? 1 : 0) << ((vid) ? 6 : 14))
-#define dma_mask(vid)	(dma_palette(1) | dma_fmt(vid, 0xf) | dma_csc(vid, 1) \
-	| dma_swaprb(vid, 1) | dma_swapuv(vid, 1) | dma_swapyuv(vid, 1))
-
-/* DMA Control 1 Register */
-#define LCD_SPU_DMA_CTRL1			0x0194
-#define	 CFG_FRAME_TRIG(trig)			((trig)<<31)
-#define	 CFG_FRAME_TRIG_MASK			0x80000000
-#define	 CFG_VSYNC_TRIG(trig)			((trig)<<28)
-#define	 CFG_VSYNC_TRIG_MASK			0x70000000
-#define	 CFG_VSYNC_INV(inv)			((inv)<<27)
-#define	 CFG_VSYNC_INV_MASK			0x08000000
-#define	 CFG_COLOR_KEY_MODE(cmode)		((cmode)<<24)
-#define	 CFG_COLOR_KEY_MASK			0x07000000
-#define	 CFG_CARRY(carry)			((carry)<<23)
-#define	 CFG_CARRY_MASK				0x00800000
-#define	 CFG_LNBUF_ENA(lnbuf)			((lnbuf)<<22)
-#define	 CFG_LNBUF_ENA_MASK			0x00400000
-#define	 CFG_GATED_ENA(gated)			((gated)<<21)
-#define	 CFG_GATED_ENA_MASK			0x00200000
-#define	 CFG_PWRDN_ENA(power)			((power)<<20)
-#define	 CFG_PWRDN_ENA_MASK			0x00100000
-#define	 CFG_DSCALE(dscale)			((dscale)<<18)
-#define	 CFG_DSCALE_MASK			0x000C0000
-#define	 CFG_ALPHA_MODE(amode)			((amode)<<16)
-#define	 CFG_ALPHA_MODE_MASK			0x00030000
-#define	 CFG_ALPHA(alpha)			((alpha)<<8)
-#define	 CFG_ALPHA_MASK				0x0000FF00
-#define	 CFG_PXLCMD(pxlcmd)			(pxlcmd)
-#define	 CFG_PXLCMD_MASK			0x000000FF
-
-/* SRAM Control Register */
-#define LCD_SPU_SRAM_CTRL			0x0198
-#define	 CFG_SRAM_INIT_WR_RD(mode)		((mode)<<14)
-#define	 CFG_SRAM_INIT_WR_RD_MASK		0x0000C000
-#define	 CFG_SRAM_ADDR_LCDID(id)		((id)<<8)
-#define	 CFG_SRAM_ADDR_LCDID_MASK		0x00000F00
-#define	 CFG_SRAM_ADDR(addr)			(addr)
-#define	 CFG_SRAM_ADDR_MASK			0x000000FF
-
-/* SRAM Write Data Register */
-#define LCD_SPU_SRAM_WRDAT			0x019C
-
-/* SRAM RTC/WTC Control Register */
-#define LCD_SPU_SRAM_PARA0			0x01A0
-
-/* SRAM Power Down Control Register */
-#define LCD_SPU_SRAM_PARA1			0x01A4
-#define	 CFG_CSB_256x32(hwc)			((hwc)<<15)	/* HWC */
-#define	 CFG_CSB_256x32_MASK			0x00008000
-#define	 CFG_CSB_256x24(palette)		((palette)<<14)	/* Palette */
-#define	 CFG_CSB_256x24_MASK			0x00004000
-#define	 CFG_CSB_256x8(gamma)			((gamma)<<13)	/* Gamma */
-#define	 CFG_CSB_256x8_MASK			0x00002000
-#define	 CFG_PDWN256x32(pdwn)			((pdwn)<<7)	/* HWC */
-#define	 CFG_PDWN256x32_MASK			0x00000080
-#define	 CFG_PDWN256x24(pdwn)			((pdwn)<<6)	/* Palette */
-#define	 CFG_PDWN256x24_MASK			0x00000040
-#define	 CFG_PDWN256x8(pdwn)			((pdwn)<<5)	/* Gamma */
-#define	 CFG_PDWN256x8_MASK			0x00000020
-#define	 CFG_PDWN32x32(pdwn)			((pdwn)<<3)
-#define	 CFG_PDWN32x32_MASK			0x00000008
-#define	 CFG_PDWN16x66(pdwn)			((pdwn)<<2)
-#define	 CFG_PDWN16x66_MASK			0x00000004
-#define	 CFG_PDWN32x66(pdwn)			((pdwn)<<1)
-#define	 CFG_PDWN32x66_MASK			0x00000002
-#define	 CFG_PDWN64x66(pdwn)			(pdwn)
-#define	 CFG_PDWN64x66_MASK			0x00000001
-
-/* Smart or Dumb Panel Clock Divider */
-#define LCD_CFG_SCLK_DIV			0x01A8
-#define	 SCLK_SRC_SEL(src)		((src)<<31)
-#define	 SCLK_SRC_SEL_MASK		0x80000000
-#define  SCLK_DISABLE				(1<<28)
-#define	 CLK_FRACDIV(frac)			((frac)<<16)
-#define	 CLK_FRACDIV_MASK			0x0FFF0000
-#define	 DSI1_BITCLK_DIV(div)			(div<<8)
-#define	 DSI1_BITCLK_DIV_MASK			0x00000F00
-#define	 CLK_INT_DIV(div)			(div)
-#define	 CLK_INT_DIV_MASK			0x000000FF
-
-/* Video Contrast Register */
-#define LCD_SPU_CONTRAST			0x01AC
-#define	 CFG_BRIGHTNESS(bright)			((bright)<<16)
-#define	 CFG_BRIGHTNESS_MASK			0xFFFF0000
-#define	 CFG_CONTRAST(contrast)			(contrast)
-#define	 CFG_CONTRAST_MASK			0x0000FFFF
-
-/* Video Saturation Register */
-#define LCD_SPU_SATURATION			0x01B0
-#define	 CFG_C_MULTS(mult)			((mult)<<16)
-#define	 CFG_C_MULTS_MASK			0xFFFF0000
-#define	 CFG_SATURATION(sat)			(sat)
-#define	 CFG_SATURATION_MASK			0x0000FFFF
-
-/* Video Hue Adjust Register */
-#define LCD_SPU_CBSH_HUE			0x01B4
-#define	 CFG_SIN0(sin0)				((sin0)<<16)
-#define	 CFG_SIN0_MASK				0xFFFF0000
-#define	 CFG_COS0(con0)				(con0)
-#define	 CFG_COS0_MASK				0x0000FFFF
-
-/* Dump LCD Panel Control Register */
-#define LCD_SPU_DUMB_CTRL			0x01B8
-#define	 CFG_DUMBMODE(mode)			((mode)<<28)
-#define	 CFG_DUMBMODE_MASK			0xF0000000
-#define	 CFG_INTFRBSWAP(mode)			((mode)<<24)
-#define	 CFG_INTFRBSWAP_MASK			0x0F000000
-#define	 CFG_LCDGPIO_O(data)			((data)<<20)
-#define	 CFG_LCDGPIO_O_MASK			0x0FF00000
-#define	 CFG_LCDGPIO_ENA(gpio)			((gpio)<<12)
-#define	 CFG_LCDGPIO_ENA_MASK			0x000FF000
-#define	 CFG_BIAS_OUT(bias)			((bias)<<8)
-#define	 CFG_BIAS_OUT_MASK			0x00000100
-#define	 CFG_REVERSE_RGB(RGB)			((RGB)<<7)
-#define	 CFG_REVERSE_RGB_MASK			0x00000080
-#define	 CFG_INV_COMPBLANK(blank)		((blank)<<6)
-#define	 CFG_INV_COMPBLANK_MASK			0x00000040
-#define	 CFG_INV_COMPSYNC(sync)			((sync)<<5)
-#define	 CFG_INV_COMPSYNC_MASK			0x00000020
-#define	 CFG_INV_HENA(hena)			((hena)<<4)
-#define	 CFG_INV_HENA_MASK			0x00000010
-#define	 CFG_INV_VSYNC(vsync)			((vsync)<<3)
-#define	 CFG_INV_VSYNC_MASK			0x00000008
-#define	 CFG_INV_HSYNC(hsync)			((hsync)<<2)
-#define	 CFG_INV_HSYNC_MASK			0x00000004
-#define	 CFG_INV_PCLK(pclk)			((pclk)<<1)
-#define	 CFG_INV_PCLK_MASK			0x00000002
-#define	 CFG_DUMB_ENA(dumb)			(dumb)
-#define	 CFG_DUMB_ENA_MASK			0x00000001
-
-/* LCD I/O Pads Control Register */
-#define SPU_IOPAD_CONTROL			0x01BC
-#define	 CFG_GRA_VM_ENA(vm)			((vm)<<15)
-#define	 CFG_GRA_VM_ENA_MASK			0x00008000
-#define	 CFG_DMA_VM_ENA(vm)			((vm)<<13)
-#define	 CFG_DMA_VM_ENA_MASK			0x00002000
-#define	 CFG_CMD_VM_ENA(vm)			((vm)<<12)
-#define	 CFG_CMD_VM_ENA_MASK			0x00001000
-#define	 CFG_CSC(csc)				((csc)<<8)
-#define	 CFG_CSC_MASK				0x00000300
-#define	 CFG_BOUNDARY(size)			((size)<<5)
-#define	 CFG_BOUNDARY_MASK			0x00000020
-#define	 CFG_BURST(len)				((len)<<4)
-#define	 CFG_BURST_MASK				0x00000010
-#define	 CFG_IOPADMODE(iopad)			(iopad)
-#define	 CFG_IOPADMODE_MASK			0x0000000F
-
-/* LCD Interrupt Control Register */
-#define SPU_IRQ_ENA				0x01C0
-#define	 DMA_FRAME_IRQ0_ENA(irq)		((irq)<<31)
-#define	 DMA_FRAME_IRQ0_ENA_MASK		0x80000000
-#define	 DMA_FRAME_IRQ1_ENA(irq)		((irq)<<30)
-#define	 DMA_FRAME_IRQ1_ENA_MASK		0x40000000
-#define	 DMA_FF_UNDERFLOW_ENA(ff)		((ff)<<29)
-#define	 DMA_FF_UNDERFLOW_ENA_MASK		0x20000000
-#define	 AXI_BUS_ERROR_IRQ_ENA(irq)		((irq)<<28)
-#define	 AXI_BUS_ERROR_IRQ_ENA_MASK		0x10000000
-#define	 GRA_FRAME_IRQ0_ENA(irq)		((irq)<<27)
-#define	 GRA_FRAME_IRQ0_ENA_MASK		0x08000000
-#define	 GRA_FRAME_IRQ1_ENA(irq)		((irq)<<26)
-#define	 GRA_FRAME_IRQ1_ENA_MASK		0x04000000
-#define	 GRA_FF_UNDERFLOW_ENA(ff)		((ff)<<25)
-#define	 GRA_FF_UNDERFLOW_ENA_MASK		0x02000000
-#define	 VSYNC_IRQ_ENA(vsync_irq)		((vsync_irq)<<23)
-#define	 VSYNC_IRQ_ENA_MASK			0x00800000
-#define	 DUMB_FRAMEDONE_ENA(fdone)		((fdone)<<22)
-#define	 DUMB_FRAMEDONE_ENA_MASK		0x00400000
-#define	 TWC_FRAMEDONE_ENA(fdone)		((fdone)<<21)
-#define	 TWC_FRAMEDONE_ENA_MASK			0x00200000
-#define	 HWC_FRAMEDONE_ENA(fdone)		((fdone)<<20)
-#define	 HWC_FRAMEDONE_ENA_MASK			0x00100000
-#define	 SLV_IRQ_ENA(irq)			((irq)<<19)
-#define	 SLV_IRQ_ENA_MASK			0x00080000
-#define	 SPI_IRQ_ENA(irq)			((irq)<<18)
-#define	 SPI_IRQ_ENA_MASK			0x00040000
-#define	 PWRDN_IRQ_ENA(irq)			((irq)<<17)
-#define	 PWRDN_IRQ_ENA_MASK			0x00020000
-#define	 AXI_LATENCY_TOO_LONG_IRQ_ENA(irq)	((irq)<<16)
-#define  AXI_LATENCY_TOO_LONG_IRQ_ENA_MASK	0x00010000
-#define	 CLEAN_SPU_IRQ_ISR(irq)			(irq)
-#define	 CLEAN_SPU_IRQ_ISR_MASK			0x0000FFFF
-#define	 TV_DMA_FRAME_IRQ0_ENA(irq)		((irq)<<15)
-#define	 TV_DMA_FRAME_IRQ0_ENA_MASK		0x00008000
-#define	 TV_DMA_FRAME_IRQ1_ENA(irq)		((irq)<<14)
-#define	 TV_DMA_FRAME_IRQ1_ENA_MASK		0x00004000
-#define	 TV_DMA_FF_UNDERFLOW_ENA(unerrun)	((unerrun)<<13)
-#define	 TV_DMA_FF_UNDERFLOW_ENA_MASK		0x00002000
-#define	 TVSYNC_IRQ_ENA(irq)			((irq)<<12)
-#define	 TVSYNC_IRQ_ENA_MASK			0x00001000
-#define	 TV_FRAME_IRQ0_ENA(irq)			((irq)<<11)
-#define	 TV_FRAME_IRQ0_ENA_MASK			0x00000800
-#define	 TV_FRAME_IRQ1_ENA(irq)			((irq)<<10)
-#define	 TV_FRAME_IRQ1_ENA_MASK			0x00000400
-#define	 TV_GRA_FF_UNDERFLOW_ENA(unerrun)	((unerrun)<<9)
-#define	 TV_GRA_FF_UNDERFLOW_ENA_MASK		0x00000200
-#define	 TV_FRAMEDONE_ENA(irq)			((irq)<<8)
-#define	 TV_FRAMEDONE_ENA_MASK			0x00000100
-
-/* FIXME - JUST GUESS */
-#define	 PN2_DMA_FRAME_IRQ0_ENA(irq)		((irq)<<7)
-#define	 PN2_DMA_FRAME_IRQ0_ENA_MASK		0x00000080
-#define	 PN2_DMA_FRAME_IRQ1_ENA(irq)		((irq)<<6)
-#define	 PN2_DMA_FRAME_IRQ1_ENA_MASK		0x00000040
-#define	 PN2_DMA_FF_UNDERFLOW_ENA(ff)		((ff)<<5)
-#define	 PN2_DMA_FF_UNDERFLOW_ENA_MASK		0x00000020
-#define	 PN2_GRA_FRAME_IRQ0_ENA(irq)		((irq)<<3)
-#define	 PN2_GRA_FRAME_IRQ0_ENA_MASK		0x00000008
-#define	 PN2_GRA_FRAME_IRQ1_ENA(irq)		((irq)<<2)
-#define	 PN2_GRA_FRAME_IRQ1_ENA_MASK		0x04000004
-#define	 PN2_GRA_FF_UNDERFLOW_ENA(ff)		((ff)<<1)
-#define	 PN2_GRA_FF_UNDERFLOW_ENA_MASK		0x00000002
-#define	 PN2_VSYNC_IRQ_ENA(irq)			((irq)<<0)
-#define	 PN2_SYNC_IRQ_ENA_MASK			0x00000001
-
-#define gf0_imask(id)	((id) ? (((id) & 1) ? TV_FRAME_IRQ0_ENA_MASK \
-		: PN2_GRA_FRAME_IRQ0_ENA_MASK) : GRA_FRAME_IRQ0_ENA_MASK)
-#define gf1_imask(id)	((id) ? (((id) & 1) ? TV_FRAME_IRQ1_ENA_MASK \
-		: PN2_GRA_FRAME_IRQ1_ENA_MASK) : GRA_FRAME_IRQ1_ENA_MASK)
-#define vsync_imask(id)	((id) ? (((id) & 1) ? TVSYNC_IRQ_ENA_MASK \
-		: PN2_SYNC_IRQ_ENA_MASK) : VSYNC_IRQ_ENA_MASK)
-#define vsync_imasks	(vsync_imask(0) | vsync_imask(1))
-
-#define display_done_imask(id)	((id) ? (((id) & 1) ? TV_FRAMEDONE_ENA_MASK\
-	: (PN2_DMA_FRAME_IRQ0_ENA_MASK | PN2_DMA_FRAME_IRQ1_ENA_MASK))\
-	: DUMB_FRAMEDONE_ENA_MASK)
-
-#define display_done_imasks	(display_done_imask(0) | display_done_imask(1))
-
-#define vf0_imask(id)	((id) ? (((id) & 1) ? TV_DMA_FRAME_IRQ0_ENA_MASK \
-		: PN2_DMA_FRAME_IRQ0_ENA_MASK) : DMA_FRAME_IRQ0_ENA_MASK)
-#define vf1_imask(id)	((id) ? (((id) & 1) ? TV_DMA_FRAME_IRQ1_ENA_MASK \
-		: PN2_DMA_FRAME_IRQ1_ENA_MASK) : DMA_FRAME_IRQ1_ENA_MASK)
-
-#define gfx_imasks	(gf0_imask(0) | gf1_imask(0) | gf0_imask(1) | \
-		gf1_imask(1))
-#define vid_imasks	(vf0_imask(0) | vf1_imask(0) | vf0_imask(1) | \
-		vf1_imask(1))
-#define vid_imask(id)	(display_done_imask(id))
-
-#define pn1_imasks	(gf0_imask(0) | gf1_imask(0) | vsync_imask(0) | \
-		display_done_imask(0) | vf0_imask(0) | vf1_imask(0))
-#define tv_imasks	(gf0_imask(1) | gf1_imask(1) | vsync_imask(1) | \
-		display_done_imask(1) | vf0_imask(1) | vf1_imask(1))
-#define path_imasks(id)	((id) ? (tv_imasks) : (pn1_imasks))
-
-/* error indications */
-#define vid_udflow_imask(id)	((id) ? (((id) & 1) ? \
-	(TV_DMA_FF_UNDERFLOW_ENA_MASK) : (PN2_DMA_FF_UNDERFLOW_ENA_MASK)) : \
-	(DMA_FF_UNDERFLOW_ENA_MASK))
-#define gfx_udflow_imask(id)	((id) ? (((id) & 1) ? \
-	(TV_GRA_FF_UNDERFLOW_ENA_MASK) : (PN2_GRA_FF_UNDERFLOW_ENA_MASK)) : \
-	(GRA_FF_UNDERFLOW_ENA_MASK))
-
-#define err_imask(id) (vid_udflow_imask(id) | gfx_udflow_imask(id) | \
-	AXI_BUS_ERROR_IRQ_ENA_MASK | AXI_LATENCY_TOO_LONG_IRQ_ENA_MASK)
-#define err_imasks (err_imask(0) | err_imask(1) | err_imask(2))
-/* LCD Interrupt Status Register */
-#define SPU_IRQ_ISR			0x01C4
-#define	 DMA_FRAME_IRQ0(irq)		((irq)<<31)
-#define	 DMA_FRAME_IRQ0_MASK		0x80000000
-#define	 DMA_FRAME_IRQ1(irq)		((irq)<<30)
-#define	 DMA_FRAME_IRQ1_MASK		0x40000000
-#define	 DMA_FF_UNDERFLOW(ff)		((ff)<<29)
-#define	 DMA_FF_UNDERFLOW_MASK		0x20000000
-#define	 AXI_BUS_ERROR_IRQ(irq)		((irq)<<28)
-#define	 AXI_BUS_ERROR_IRQ_MASK		0x10000000
-#define	 GRA_FRAME_IRQ0(irq)		((irq)<<27)
-#define	 GRA_FRAME_IRQ0_MASK		0x08000000
-#define	 GRA_FRAME_IRQ1(irq)		((irq)<<26)
-#define	 GRA_FRAME_IRQ1_MASK		0x04000000
-#define	 GRA_FF_UNDERFLOW(ff)		((ff)<<25)
-#define	 GRA_FF_UNDERFLOW_MASK		0x02000000
-#define	 VSYNC_IRQ(vsync_irq)		((vsync_irq)<<23)
-#define	 VSYNC_IRQ_MASK			0x00800000
-#define	 DUMB_FRAMEDONE(fdone)		((fdone)<<22)
-#define	 DUMB_FRAMEDONE_MASK		0x00400000
-#define	 TWC_FRAMEDONE(fdone)		((fdone)<<21)
-#define	 TWC_FRAMEDONE_MASK		0x00200000
-#define	 HWC_FRAMEDONE(fdone)		((fdone)<<20)
-#define	 HWC_FRAMEDONE_MASK		0x00100000
-#define	 SLV_IRQ(irq)			((irq)<<19)
-#define	 SLV_IRQ_MASK			0x00080000
-#define	 SPI_IRQ(irq)			((irq)<<18)
-#define	 SPI_IRQ_MASK			0x00040000
-#define	 PWRDN_IRQ(irq)			((irq)<<17)
-#define	 PWRDN_IRQ_MASK			0x00020000
-#define	 AXI_LATENCY_TOO_LONGR_IRQ(irq)	((irq)<<16)
-#define	 AXI_LATENCY_TOO_LONGR_IRQ_MASK	0x00010000
-#define	 TV_DMA_FRAME_IRQ0(irq)		((irq)<<15)
-#define	 TV_DMA_FRAME_IRQ0_MASK		0x00008000
-#define	 TV_DMA_FRAME_IRQ1(irq)		((irq)<<14)
-#define	 TV_DMA_FRAME_IRQ1_MASK		0x00004000
-#define	 TV_DMA_FF_UNDERFLOW(unerrun)	((unerrun)<<13)
-#define	 TV_DMA_FF_UNDERFLOW_MASK	0x00002000
-#define	 TVSYNC_IRQ(irq)		((irq)<<12)
-#define	 TVSYNC_IRQ_MASK		0x00001000
-#define	 TV_FRAME_IRQ0(irq)		((irq)<<11)
-#define	 TV_FRAME_IRQ0_MASK		0x00000800
-#define	 TV_FRAME_IRQ1(irq)		((irq)<<10)
-#define	 TV_FRAME_IRQ1_MASK		0x00000400
-#define	 TV_GRA_FF_UNDERFLOW(unerrun)	((unerrun)<<9)
-#define	 TV_GRA_FF_UNDERFLOW_MASK	0x00000200
-#define	 PN2_DMA_FRAME_IRQ0(irq)	((irq)<<7)
-#define	 PN2_DMA_FRAME_IRQ0_MASK	0x00000080
-#define	 PN2_DMA_FRAME_IRQ1(irq)	((irq)<<6)
-#define	 PN2_DMA_FRAME_IRQ1_MASK	0x00000040
-#define	 PN2_DMA_FF_UNDERFLOW(ff)	((ff)<<5)
-#define	 PN2_DMA_FF_UNDERFLOW_MASK	0x00000020
-#define	 PN2_GRA_FRAME_IRQ0(irq)	((irq)<<3)
-#define	 PN2_GRA_FRAME_IRQ0_MASK	0x00000008
-#define	 PN2_GRA_FRAME_IRQ1(irq)	((irq)<<2)
-#define	 PN2_GRA_FRAME_IRQ1_MASK	0x04000004
-#define	 PN2_GRA_FF_UNDERFLOW(ff)	((ff)<<1)
-#define	 PN2_GRA_FF_UNDERFLOW_MASK	0x00000002
-#define	 PN2_VSYNC_IRQ(irq)		((irq)<<0)
-#define	 PN2_SYNC_IRQ_MASK		0x00000001
-
-/* LCD FIFO Depth register */
-#define LCD_FIFO_DEPTH			0x01c8
-#define	 VIDEO_FIFO(fi)			((fi) << 0)
-#define	 VIDEO_FIFO_MASK		0x00000003
-#define	 GRAPHIC_FIFO(fi)		((fi) << 2)
-#define	 GRAPHIC_FIFO_MASK		0x0000000c
-
-/* read-only */
-#define	 DMA_FRAME_IRQ0_LEVEL_MASK		0x00008000
-#define	 DMA_FRAME_IRQ1_LEVEL_MASK		0x00004000
-#define	 DMA_FRAME_CNT_ISR_MASK			0x00003000
-#define	 GRA_FRAME_IRQ0_LEVEL_MASK		0x00000800
-#define	 GRA_FRAME_IRQ1_LEVEL_MASK		0x00000400
-#define	 GRA_FRAME_CNT_ISR_MASK			0x00000300
-#define	 VSYNC_IRQ_LEVEL_MASK			0x00000080
-#define	 DUMB_FRAMEDONE_LEVEL_MASK		0x00000040
-#define	 TWC_FRAMEDONE_LEVEL_MASK		0x00000020
-#define	 HWC_FRAMEDONE_LEVEL_MASK		0x00000010
-#define	 SLV_FF_EMPTY_MASK			0x00000008
-#define	 DMA_FF_ALLEMPTY_MASK			0x00000004
-#define	 GRA_FF_ALLEMPTY_MASK			0x00000002
-#define	 PWRDN_IRQ_LEVEL_MASK			0x00000001
-
-/* 32 bit LCD Interrupt Reset Status*/
-#define SPU_IRQ_RSR				(0x01C8)
-/* 32 bit Panel Path Graphic Partial Display Horizontal Control Register*/
-#define LCD_GRA_CUTHPXL				(0x01CC)
-/* 32 bit Panel Path Graphic Partial Display Vertical Control Register*/
-#define LCD_GRA_CUTVLN				(0x01D0)
-/* 32 bit TV Path Graphic Partial Display	  Horizontal Control Register*/
-#define LCD_TVG_CUTHPXL				(0x01D4)
-/* 32 bit TV Path Graphic Partial Display Vertical Control Register*/
-#define LCD_TVG_CUTVLN				(0x01D8)
-/* 32 bit LCD Global Control Register*/
-#define LCD_TOP_CTRL				(0x01DC)
-/* 32 bit LCD SQU Line Buffer Control Register 1*/
-#define LCD_SQULN1_CTRL				(0x01E0)
-/* 32 bit LCD SQU Line Buffer Control Register 2*/
-#define LCD_SQULN2_CTRL				(0x01E4)
-#define squln_ctrl(id)	((id) ? (((id) & 1) ? LCD_SQULN2_CTRL : \
-			LCD_PN2_SQULN1_CTRL) : LCD_SQULN1_CTRL)
-
-/* 32 bit LCD Mixed Overlay Control Register */
-#define LCD_AFA_ALL2ONE				(0x01E8)
-
-#define LCD_PN2_SCLK_DIV			(0x01EC)
-#define LCD_PN2_TCLK_DIV			(0x01F0)
-#define LCD_LVDS_SCLK_DIV_WR			(0x01F4)
-#define LCD_LVDS_SCLK_DIV_RD			(0x01FC)
-#define PN2_LCD_DMA_START_ADDR_Y0		(0x0200)
-#define PN2_LCD_DMA_START_ADDR_U0		(0x0204)
-#define PN2_LCD_DMA_START_ADDR_V0		(0x0208)
-#define PN2_LCD_DMA_START_ADDR_C0		(0x020C)
-#define PN2_LCD_DMA_START_ADDR_Y1		(0x0210)
-#define PN2_LCD_DMA_START_ADDR_U1		(0x0214)
-#define PN2_LCD_DMA_START_ADDR_V1		(0x0218)
-#define PN2_LCD_DMA_START_ADDR_C1		(0x021C)
-#define PN2_LCD_DMA_PITCH_YC			(0x0220)
-#define PN2_LCD_DMA_PITCH_UV			(0x0224)
-#define PN2_LCD_DMA_OVSA_HPXL_VLN		(0x0228)
-#define PN2_LCD_DMA_HPXL_VLN			(0x022C)
-#define PN2_LCD_DMAZM_HPXL_VLN			(0x0230)
-#define PN2_LCD_GRA_START_ADDR0			(0x0234)
-#define PN2_LCD_GRA_START_ADDR1			(0x0238)
-#define PN2_LCD_GRA_PITCH			(0x023C)
-#define PN2_LCD_GRA_OVSA_HPXL_VLN		(0x0240)
-#define PN2_LCD_GRA_HPXL_VLN			(0x0244)
-#define PN2_LCD_GRAZM_HPXL_VLN			(0x0248)
-#define PN2_LCD_HWC_OVSA_HPXL_VLN		(0x024C)
-#define PN2_LCD_HWC_HPXL_VLN			(0x0250)
-#define LCD_PN2_V_H_TOTAL			(0x0254)
-#define LCD_PN2_V_H_ACTIVE			(0x0258)
-#define LCD_PN2_H_PORCH				(0x025C)
-#define LCD_PN2_V_PORCH				(0x0260)
-#define LCD_PN2_BLANKCOLOR			(0x0264)
-#define LCD_PN2_ALPHA_COLOR1			(0x0268)
-#define LCD_PN2_ALPHA_COLOR2			(0x026C)
-#define LCD_PN2_COLORKEY_Y			(0x0270)
-#define LCD_PN2_COLORKEY_U			(0x0274)
-#define LCD_PN2_COLORKEY_V			(0x0278)
-#define LCD_PN2_SEPXLCNT			(0x027C)
-#define LCD_TV_V_H_TOTAL_FLD			(0x0280)
-#define LCD_TV_V_PORCH_FLD			(0x0284)
-#define LCD_TV_SEPXLCNT_FLD			(0x0288)
-
-#define LCD_2ND_ALPHA				(0x0294)
-#define LCD_PN2_CONTRAST			(0x0298)
-#define LCD_PN2_SATURATION			(0x029c)
-#define LCD_PN2_CBSH_HUE			(0x02a0)
-#define LCD_TIMING_EXT				(0x02C0)
-#define LCD_PN2_LAYER_ALPHA_SEL1		(0x02c4)
-#define LCD_PN2_CTRL0				(0x02C8)
-#define TV_LAYER_ALPHA_SEL1			(0x02cc)
-#define LCD_SMPN2_CTRL				(0x02D0)
-#define LCD_IO_OVERL_MAP_CTRL			(0x02D4)
-#define LCD_DUMB2_CTRL				(0x02d8)
-#define LCD_PN2_CTRL1				(0x02DC)
-#define PN2_IOPAD_CONTROL			(0x02E0)
-#define LCD_PN2_SQULN1_CTRL			(0x02E4)
-#define PN2_LCD_GRA_CUTHPXL			(0x02e8)
-#define PN2_LCD_GRA_CUTVLN			(0x02ec)
-#define LCD_PN2_SQULN2_CTRL			(0x02F0)
-#define ALL_LAYER_ALPHA_SEL			(0x02F4)
-
-/* pxa988 has different MASTER_CTRL from MMP3/MMP2 */
-#ifdef CONFIG_CPU_PXA988
-#define TIMING_MASTER_CONTROL			(0x01F4)
-#define MASTER_ENH(id)				(1 << ((id) + 5))
-#define MASTER_ENV(id)				(1 << ((id) + 6))
-#else
-#define TIMING_MASTER_CONTROL			(0x02F8)
-#define MASTER_ENH(id)				(1 << (id))
-#define MASTER_ENV(id)				(1 << ((id) + 4))
-#endif
-
-#define DSI_START_SEL_SHIFT(id)		(((id) << 1) + 8)
-#define timing_master_config(path, dsi_id, lcd_id) \
-	(MASTER_ENH(path) | MASTER_ENV(path) | \
-	(((lcd_id) + ((dsi_id) << 1)) << DSI_START_SEL_SHIFT(path)))
-
-#define LCD_2ND_BLD_CTL				(0x02Fc)
-#define LVDS_SRC_MASK				(3 << 30)
-#define LVDS_SRC_SHIFT				(30)
-#define LVDS_FMT_MASK				(1 << 28)
-#define LVDS_FMT_SHIFT				(28)
-
-#define CLK_SCLK	(1 << 0)
-#define CLK_LVDS_RD	(1 << 1)
-#define CLK_LVDS_WR	(1 << 2)
-
-#define gra_partdisp_ctrl_hor(id)	((id) ? (((id) & 1) ? \
-	LCD_TVG_CUTHPXL : PN2_LCD_GRA_CUTHPXL) : LCD_GRA_CUTHPXL)
-#define gra_partdisp_ctrl_ver(id)	((id) ? (((id) & 1) ? \
-	LCD_TVG_CUTVLN : PN2_LCD_GRA_CUTVLN) : LCD_GRA_CUTVLN)
-
-/*
- * defined for Configure Dumb Mode
- * defined for Configure Dumb Mode
- * DUMB LCD Panel bit[31:28]
- */
-#define DUMB16_RGB565_0		0x0
-#define DUMB16_RGB565_1		0x1
-#define DUMB18_RGB666_0		0x2
-#define DUMB18_RGB666_1		0x3
-#define DUMB12_RGB444_0		0x4
-#define DUMB12_RGB444_1		0x5
-#define DUMB24_RGB888_0		0x6
-#define DUMB_BLANK		0x7
-
-/*
- * defined for Configure I/O Pin Allocation Mode
- * LCD LCD I/O Pads control register bit[3:0]
- */
-#define IOPAD_DUMB24		0x0
-#define IOPAD_DUMB18SPI		0x1
-#define IOPAD_DUMB18GPIO	0x2
-#define IOPAD_DUMB16SPI		0x3
-#define IOPAD_DUMB16GPIO	0x4
-#define IOPAD_DUMB12		0x5
-#define IOPAD_SMART18SPI	0x6
-#define IOPAD_SMART16SPI	0x7
-#define IOPAD_SMART8BOTH	0x8
-#define IOPAD_DUMB18_SMART8	0x9
-#define IOPAD_DUMB16_SMART8SPI	0xa
-#define IOPAD_DUMB16_SMART8GPIO	0xb
-#define IOPAD_DUMB16_DUMB16	0xc
-#define IOPAD_SMART8_SMART8	0xc
-
-/*
- *defined for indicating boundary and cycle burst length
- */
-#define  CFG_BOUNDARY_1KB			(1<<5)
-#define  CFG_BOUNDARY_4KB			(0<<5)
-#define	 CFG_CYC_BURST_LEN16			(1<<4)
-#define	 CFG_CYC_BURST_LEN8			(0<<4)
-
-/* SRAM ID */
-#define SRAMID_GAMMA_YR			0x0
-#define SRAMID_GAMMA_UG			0x1
-#define SRAMID_GAMMA_VB			0x2
-#define SRAMID_PALATTE			0x3
-#define SRAMID_HWC			0xf
-
-/* SRAM INIT Read/Write */
-#define SRAMID_INIT_READ		0x0
-#define SRAMID_INIT_WRITE		0x2
-#define SRAMID_INIT_DEFAULT		0x3
-
-/*
- * defined VSYNC selection mode for DMA control 1 register
- * DMA1 bit[30:28]
- */
-#define VMODE_SMPN			0x0
-#define VMODE_SMPNIRQ			0x1
-#define VMODE_DUMB			0x2
-#define VMODE_IPE			0x3
-#define VMODE_IRE			0x4
-
-/*
- * defined Configure Alpha and Alpha mode for DMA control 1 register
- * DMA1 bit[15:08](alpha) / bit[17:16](alpha mode)
- */
-/* ALPHA mode */
-#define MODE_ALPHA_DMA			0x0
-#define MODE_ALPHA_GRA			0x1
-#define MODE_ALPHA_CFG			0x2
-
-/* alpha value */
-#define ALPHA_NOGRAPHIC			0xFF	  /* all video, no graphic */
-#define ALPHA_NOVIDEO			0x00	  /* all graphic, no video */
-#define ALPHA_GRAPHNVIDEO		0x0F	  /* Selects graphic & video */
-
-/*
- * defined Pixel Command for DMA control 1 register
- * DMA1 bit[07:00]
- */
-#define PIXEL_CMD			0x81
-
-/* DSI */
-/* DSI1 - 4 Lane Controller base */
-#define DSI1_REGS_PHYSICAL_BASE		0xD420B800
-/* DSI2 - 3 Lane Controller base */
-#define DSI2_REGS_PHYSICAL_BASE		0xD420BA00
-
-/*	   DSI Controller Registers	   */
-struct dsi_lcd_regs {
-#define DSI_LCD1_CTRL_0  0x100   /* DSI Active Panel 1 Control register 0 */
-#define DSI_LCD1_CTRL_1  0x104   /* DSI Active Panel 1 Control register 1 */
-	u32 ctrl0;
-	u32 ctrl1;
-	u32 reserved1[2];
-
-#define DSI_LCD1_TIMING_0		0x110   /* Timing register 0 */
-#define DSI_LCD1_TIMING_1		0x114   /* Timing register 1 */
-#define DSI_LCD1_TIMING_2		0x118   /* Timing register 2 */
-#define DSI_LCD1_TIMING_3		0x11C   /* Timing register 3 */
-#define DSI_LCD1_WC_0			0x120   /* Word Count register 0 */
-#define DSI_LCD1_WC_1			0x124   /* Word Count register 1 */
-#define DSI_LCD1_WC_2			0x128	 /* Word Count register 2 */
-	u32 timing0;
-	u32 timing1;
-	u32 timing2;
-	u32 timing3;
-	u32 wc0;
-	u32 wc1;
-	u32 wc2;
-	u32 reserved2[1];
-	u32 slot_cnt0;
-	u32 slot_cnt1;
-	u32 reserved3[2];
-	u32 status_0;
-	u32 status_1;
-	u32 status_2;
-	u32 status_3;
-	u32 status_4;
-};
-
-struct dsi_regs {
-#define DSI_CTRL_0	  0x000   /* DSI control register 0 */
-#define DSI_CTRL_1	  0x004   /* DSI control register 1 */
-	u32 ctrl0;
-	u32 ctrl1;
-	u32 reserved1[2];
-	u32 irq_status;
-	u32 irq_mask;
-	u32 reserved2[2];
-
-#define DSI_CPU_CMD_0   0x020   /* DSI CPU packet command register 0 */
-#define DSI_CPU_CMD_1   0x024   /* DSU CPU Packet Command Register 1 */
-#define DSI_CPU_CMD_3	0x02C   /* DSU CPU Packet Command Register 3 */
-#define DSI_CPU_WDAT_0	0x030   /* DSI CUP */
-	u32 cmd0;
-	u32 cmd1;
-	u32 cmd2;
-	u32 cmd3;
-	u32 dat0;
-	u32 status0;
-	u32 status1;
-	u32 status2;
-	u32 status3;
-	u32 status4;
-	u32 reserved3[2];
-
-	u32 smt_cmd;
-	u32 smt_ctrl0;
-	u32 smt_ctrl1;
-	u32 reserved4[1];
-
-	u32 rx0_status;
-
-/* Rx Packet Header - data from slave device */
-#define DSI_RX_PKT_HDR_0 0x064
-	u32 rx0_header;
-	u32 rx1_status;
-	u32 rx1_header;
-	u32 rx_ctrl;
-	u32 rx_ctrl1;
-	u32 rx2_status;
-	u32 rx2_header;
-	u32 reserved5[1];
-
-	u32 phy_ctrl1;
-#define DSI_PHY_CTRL_2		0x088   /* DSI DPHI Control Register 2 */
-#define DSI_PHY_CTRL_3		0x08C   /* DPHY Control Register 3 */
-	u32 phy_ctrl2;
-	u32 phy_ctrl3;
-	u32 phy_status0;
-	u32 phy_status1;
-	u32 reserved6[5];
-	u32 phy_status2;
-
-#define DSI_PHY_RCOMP_0		0x0B0   /* DPHY Rcomp Control Register */
-	u32 phy_rcomp0;
-	u32 reserved7[3];
-#define DSI_PHY_TIME_0		0x0C0   /* DPHY Timing Control Register 0 */
-#define DSI_PHY_TIME_1		0x0C4   /* DPHY Timing Control Register 1 */
-#define DSI_PHY_TIME_2		0x0C8   /* DPHY Timing Control Register 2 */
-#define DSI_PHY_TIME_3		0x0CC   /* DPHY Timing Control Register 3 */
-#define DSI_PHY_TIME_4		0x0D0   /* DPHY Timing Control Register 4 */
-#define DSI_PHY_TIME_5		0x0D4   /* DPHY Timing Control Register 5 */
-	u32 phy_timing0;
-	u32 phy_timing1;
-	u32 phy_timing2;
-	u32 phy_timing3;
-	u32 phy_code_0;
-	u32 phy_code_1;
-	u32 reserved8[2];
-	u32 mem_ctrl;
-	u32 tx_timer;
-	u32 rx_timer;
-	u32 turn_timer;
-	u32 reserved9[4];
-
-#define DSI_LCD1_CTRL_0  0x100   /* DSI Active Panel 1 Control register 0 */
-#define DSI_LCD1_CTRL_1  0x104   /* DSI Active Panel 1 Control register 1 */
-#define DSI_LCD1_TIMING_0		0x110   /* Timing register 0 */
-#define DSI_LCD1_TIMING_1		0x114   /* Timing register 1 */
-#define DSI_LCD1_TIMING_2		0x118   /* Timing register 2 */
-#define DSI_LCD1_TIMING_3		0x11C   /* Timing register 3 */
-#define DSI_LCD1_WC_0			0x120   /* Word Count register 0 */
-#define DSI_LCD1_WC_1			0x124   /* Word Count register 1 */
-#define DSI_LCD1_WC_2			0x128   /* Word Count register 2 */
-	struct dsi_lcd_regs lcd1;
-	u32 reserved10[11];
-	struct dsi_lcd_regs lcd2;
-};
-
-#define DSI_LCD2_CTRL_0  0x180   /* DSI Active Panel 2 Control register 0 */
-#define DSI_LCD2_CTRL_1  0x184   /* DSI Active Panel 2 Control register 1 */
-#define DSI_LCD2_TIMING_0		0x190   /* Timing register 0 */
-#define DSI_LCD2_TIMING_1		0x194   /* Timing register 1 */
-#define DSI_LCD2_TIMING_2		0x198   /* Timing register 2 */
-#define DSI_LCD2_TIMING_3		0x19C   /* Timing register 3 */
-#define DSI_LCD2_WC_0			0x1A0   /* Word Count register 0 */
-#define DSI_LCD2_WC_1			0x1A4   /* Word Count register 1 */
-#define DSI_LCD2_WC_2			0x1A8	 /* Word Count register 2 */
-
-/*	DSI_CTRL_0		0x0000	DSI Control Register 0 */
-#define DSI_CTRL_0_CFG_SOFT_RST			(1<<31)
-#define DSI_CTRL_0_CFG_SOFT_RST_REG		(1<<30)
-#define DSI_CTRL_0_CFG_LCD1_TX_EN		(1<<8)
-#define DSI_CTRL_0_CFG_LCD1_SLV			(1<<4)
-#define DSI_CTRL_0_CFG_LCD1_EN			(1<<0)
-
-/*	DSI_CTRL_1		0x0004	DSI Control Register 1 */
-#define DSI_CTRL_1_CFG_EOTP			(1<<8)
-#define DSI_CTRL_1_CFG_RSVD			(2<<4)
-#define DSI_CTRL_1_CFG_LCD2_VCH_NO_MASK		(3<<2)
-#define DSI_CTRL_1_CFG_LCD2_VCH_NO_SHIFT	2
-#define DSI_CTRL_1_CFG_LCD1_VCH_NO_MASK		(3<<0)
-#define DSI_CTRL_1_CFG_LCD1_VCH_NO_SHIFT	0
-
-/*	DSI_LCD1_CTRL_1	0x0104	DSI Active Panel 1 Control Register 1 */
-/* LCD 1 Vsync Reset Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_VSYNC_RST_EN	(1<<31)
-/* LCD 1 2K Pixel Buffer Mode Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_M2K_EN		(1<<30)
-/*		Bit(s) DSI_LCD1_CTRL_1_RSRV_29_23 reserved */
-/* Long Blanking Packet Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HLP_PKT_EN	(1<<22)
-/* Extra Long Blanking Packet Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HEX_PKT_EN	(1<<21)
-/* Front Porch Packet Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HFP_PKT_EN	(1<<20)
-/* hact Packet Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HACT_PKT_EN	(1<<19)
-/* Back Porch Packet Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HBP_PKT_EN	(1<<18)
-/* hse Packet Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HSE_PKT_EN	(1<<17)
-/* hsa Packet Enable */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HSA_PKT_EN	(1<<16)
-/* All Item Enable after Pixel Data */
-#define	DSI_LCD1_CTRL_1_CFG_L1_ALL_SLOT_EN	(1<<15)
-/* Extra Long Packet Enable after Pixel Data */
-#define	DSI_LCD1_CTRL_1_CFG_L1_HEX_SLOT_EN	(1<<14)
-/*		Bit(s) DSI_LCD1_CTRL_1_RSRV_13_11 reserved */
-/* Turn Around Bus at Last h Line */
-#define	DSI_LCD1_CTRL_1_CFG_L1_LAST_LINE_TURN	(1<<10)
-/* Go to Low Power Every Frame */
-#define	DSI_LCD1_CTRL_1_CFG_L1_LPM_FRAME_EN	(1<<9)
-/* Go to Low Power Every Line */
-#define	DSI_LCD1_CTRL_1_CFG_L1_LPM_LINE_EN	(1<<8)
-/*		Bit(s) DSI_LCD1_CTRL_1_RSRV_7_4 reserved */
-/* DSI Transmission Mode for LCD 1 */
-#define DSI_LCD1_CTRL_1_CFG_L1_BURST_MODE_SHIFT	2
-#define DSI_LCD1_CTRL_1_CFG_L1_BURST_MODE_MASK	(3<<2)
-/* LCD 1 Input Data RGB Mode for LCD 1 */
-#define DSI_LCD2_CTRL_1_CFG_L1_RGB_TYPE_SHIFT	0
-#define DSI_LCD2_CTRL_1_CFG_L1_RGB_TYPE_MASK	(3<<2)
-
-/*	DSI_PHY_CTRL_2		0x0088	DPHY Control Register 2 */
-/*		Bit(s) DSI_PHY_CTRL_2_RSRV_31_12 reserved */
-/* DPHY LP Receiver Enable */
-#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_RESC_EN_MASK	(0xf<<8)
-#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_RESC_EN_SHIFT	8
-/* DPHY Data Lane Enable */
-#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_EN_MASK		(0xf<<4)
-#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_EN_SHIFT		4
-/* DPHY Bus Turn Around */
-#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_TURN_MASK		(0xf)
-#define	DSI_PHY_CTRL_2_CFG_CSR_LANE_TURN_SHIFT		0
-
-/*	DSI_CPU_CMD_1		0x0024	DSI CPU Packet Command Register 1 */
-/*		Bit(s) DSI_CPU_CMD_1_RSRV_31_24 reserved */
-/* LPDT TX Enable */
-#define	DSI_CPU_CMD_1_CFG_TXLP_LPDT_MASK		(0xf<<20)
-#define	DSI_CPU_CMD_1_CFG_TXLP_LPDT_SHIFT		20
-/* ULPS TX Enable */
-#define	DSI_CPU_CMD_1_CFG_TXLP_ULPS_MASK		(0xf<<16)
-#define	DSI_CPU_CMD_1_CFG_TXLP_ULPS_SHIFT		16
-/* Low Power TX Trigger Code */
-#define	DSI_CPU_CMD_1_CFG_TXLP_TRIGGER_CODE_MASK	(0xffff)
-#define	DSI_CPU_CMD_1_CFG_TXLP_TRIGGER_CODE_SHIFT	0
-
-/*	DSI_PHY_TIME_0	0x00c0	DPHY Timing Control Register 0 */
-/* Length of HS Exit Period in tx_clk_esc Cycles */
-#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_EXIT_MASK	(0xff<<24)
-#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_EXIT_SHIFT	24
-/* DPHY HS Trail Period Length */
-#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_TRAIL_MASK	(0xff<<16)
-#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_TRAIL_SHIFT	16
-/* DPHY HS Zero State Length */
-#define	DSI_PHY_TIME_0_CDG_CSR_TIME_HS_ZERO_MASK	(0xff<<8)
-#define	DSI_PHY_TIME_0_CDG_CSR_TIME_HS_ZERO_SHIFT	8
-/* DPHY HS Prepare State Length */
-#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_PREP_MASK	(0xff)
-#define	DSI_PHY_TIME_0_CFG_CSR_TIME_HS_PREP_SHIFT	0
-
-/*	DSI_PHY_TIME_1		0x00c4	DPHY Timing Control Register 1 */
-/* Time to Drive LP-00 by New Transmitter */
-#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GET_MASK		(0xff<<24)
-#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GET_SHIFT	24
-/* Time to Drive LP-00 after Turn Request */
-#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GO_MASK		(0xff<<16)
-#define	DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GO_SHIFT		16
-/* DPHY HS Wakeup Period Length */
-#define	DSI_PHY_TIME_1_CFG_CSR_TIME_WAKEUP_MASK		(0xffff)
-#define	DSI_PHY_TIME_1_CFG_CSR_TIME_WAKEUP_SHIFT	0
-
-/*	DSI_PHY_TIME_2		0x00c8	DPHY Timing Control Register 2 */
-/* DPHY CLK Exit Period Length */
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_EXIT_MASK	(0xff<<24)
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_EXIT_SHIFT	24
-/* DPHY CLK Trail Period Length */
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_TRAIL_MASK	(0xff<<16)
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_TRAIL_SHIFT	16
-/* DPHY CLK Zero State Length */
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_ZERO_MASK	(0xff<<8)
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_ZERO_SHIFT	8
-/* DPHY CLK LP Length */
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_LPX_MASK		(0xff)
-#define	DSI_PHY_TIME_2_CFG_CSR_TIME_CK_LPX_SHIFT	0
-
-/*	DSI_PHY_TIME_3		0x00cc	DPHY Timing Control Register 3 */
-/*		Bit(s) DSI_PHY_TIME_3_RSRV_31_16 reserved */
-/* DPHY LP Length */
-#define	DSI_PHY_TIME_3_CFG_CSR_TIME_LPX_MASK		(0xff<<8)
-#define	DSI_PHY_TIME_3_CFG_CSR_TIME_LPX_SHIFT		8
-/* DPHY HS req to rdy Length */
-#define	DSI_PHY_TIME_3_CFG_CSR_TIME_REQRDY_MASK		(0xff)
-#define	DSI_PHY_TIME_3_CFG_CSR_TIME_REQRDY_SHIFT	0
-
-/*
- * DSI timings
- * PXA988 has diffrent ESC CLK with MMP2/MMP3
- * it will be used in dsi_set_dphy() in pxa688_phy.c
- * as low power mode clock.
- */
-#ifdef CONFIG_CPU_PXA988
-#define DSI_ESC_CLK				52  /* Unit: Mhz */
-#define DSI_ESC_CLK_T				19  /* Unit: ns */
-#else
-#define DSI_ESC_CLK				66  /* Unit: Mhz */
-#define DSI_ESC_CLK_T				15  /* Unit: ns */
-#endif
-
-/* LVDS */
-/* LVDS_PHY_CTRL */
-#define LVDS_PHY_CTL				0x2A4
-#define LVDS_PLL_LOCK				(1 << 31)
-#define LVDS_PHY_EXT_MASK			(7 << 28)
-#define LVDS_PHY_EXT_SHIFT			(28)
-#define LVDS_CLK_PHASE_MASK			(0x7f << 16)
-#define LVDS_CLK_PHASE_SHIFT			(16)
-#define LVDS_SSC_RESET_EXT			(1 << 13)
-#define LVDS_SSC_MODE_DOWN_SPREAD		(1 << 12)
-#define LVDS_SSC_EN				(1 << 11)
-#define LVDS_PU_PLL				(1 << 10)
-#define LVDS_PU_TX				(1 << 9)
-#define LVDS_PU_IVREF				(1 << 8)
-#define LVDS_CLK_SEL				(1 << 7)
-#define LVDS_CLK_SEL_LVDS_PCLK			(1 << 7)
-#define LVDS_PD_CH_MASK				(0x3f << 1)
-#define LVDS_PD_CH(ch)				((ch) << 1)
-#define LVDS_RST				(1 << 0)
-
-#define LVDS_PHY_CTL_EXT	0x2A8
-
-/* LVDS_PHY_CTRL_EXT1 */
-#define LVDS_SSC_RNGE_MASK			(0x7ff << 16)
-#define LVDS_SSC_RNGE_SHIFT			(16)
-#define LVDS_RESERVE_IN_MASK			(0xf << 12)
-#define LVDS_RESERVE_IN_SHIFT			(12)
-#define LVDS_TEST_MON_MASK			(0x7 << 8)
-#define LVDS_TEST_MON_SHIFT			(8)
-#define LVDS_POL_SWAP_MASK			(0x3f << 0)
-#define LVDS_POL_SWAP_SHIFT			(0)
-
-/* LVDS_PHY_CTRL_EXT2 */
-#define LVDS_TX_DIF_AMP_MASK			(0xf << 24)
-#define LVDS_TX_DIF_AMP_SHIFT			(24)
-#define LVDS_TX_DIF_CM_MASK			(0x3 << 22)
-#define LVDS_TX_DIF_CM_SHIFT			(22)
-#define LVDS_SELLV_TXCLK_MASK			(0x1f << 16)
-#define LVDS_SELLV_TXCLK_SHIFT			(16)
-#define LVDS_TX_CMFB_EN				(0x1 << 15)
-#define LVDS_TX_TERM_EN				(0x1 << 14)
-#define LVDS_SELLV_TXDATA_MASK			(0x1f << 8)
-#define LVDS_SELLV_TXDATA_SHIFT			(8)
-#define LVDS_SELLV_OP7_MASK			(0x3 << 6)
-#define LVDS_SELLV_OP7_SHIFT			(6)
-#define LVDS_SELLV_OP6_MASK			(0x3 << 4)
-#define LVDS_SELLV_OP6_SHIFT			(4)
-#define LVDS_SELLV_OP9_MASK			(0x3 << 2)
-#define LVDS_SELLV_OP9_SHIFT			(2)
-#define LVDS_STRESSTST_EN			(0x1 << 0)
-
-/* LVDS_PHY_CTRL_EXT3 */
-#define LVDS_KVCO_MASK				(0xf << 28)
-#define LVDS_KVCO_SHIFT				(28)
-#define LVDS_CTUNE_MASK				(0x3 << 26)
-#define LVDS_CTUNE_SHIFT			(26)
-#define LVDS_VREG_IVREF_MASK			(0x3 << 24)
-#define LVDS_VREG_IVREF_SHIFT			(24)
-#define LVDS_VDDL_MASK				(0xf << 20)
-#define LVDS_VDDL_SHIFT				(20)
-#define LVDS_VDDM_MASK				(0x3 << 18)
-#define LVDS_VDDM_SHIFT				(18)
-#define LVDS_FBDIV_MASK				(0xf << 8)
-#define LVDS_FBDIV_SHIFT			(8)
-#define LVDS_REFDIV_MASK			(0x7f << 0)
-#define LVDS_REFDIV_SHIFT			(0)
-
-/* LVDS_PHY_CTRL_EXT4 */
-#define LVDS_SSC_FREQ_DIV_MASK			(0xffff << 16)
-#define LVDS_SSC_FREQ_DIV_SHIFT			(16)
-#define LVDS_INTPI_MASK				(0xf << 12)
-#define LVDS_INTPI_SHIFT			(12)
-#define LVDS_VCODIV_SEL_SE_MASK			(0xf << 8)
-#define LVDS_VCODIV_SEL_SE_SHIFT		(8)
-#define LVDS_RESET_INTP_EXT			(0x1 << 7)
-#define LVDS_VCO_VRNG_MASK			(0x7 << 4)
-#define LVDS_VCO_VRNG_SHIFT			(4)
-#define LVDS_PI_EN				(0x1 << 3)
-#define LVDS_ICP_MASK				(0x7 << 0)
-#define LVDS_ICP_SHIFT				(0)
-
-/* LVDS_PHY_CTRL_EXT5 */
-#define LVDS_FREQ_OFFSET_MASK			(0x1ffff << 15)
-#define LVDS_FREQ_OFFSET_SHIFT			(15)
-#define LVDS_FREQ_OFFSET_VALID			(0x1 << 2)
-#define LVDS_FREQ_OFFSET_MODE_CK_DIV4_OUT	(0x1 << 1)
-#define LVDS_FREQ_OFFSET_MODE_EN		(0x1 << 0)
-
-enum {
-	PATH_PN = 0,
-	PATH_TV,
-	PATH_P2,
-};
-
-/*
- * mmp path describes part of mmp path related info:
- * which is hiden in display driver and not exported to buffer driver
- */
-struct mmphw_ctrl;
-struct mmphw_path_plat {
-	int id;
-	struct mmphw_ctrl *ctrl;
-	struct mmp_path *path;
-	u32 path_config;
-	u32 link_config;
-	u32 dsi_rbswap;
-};
-
-/* mmp ctrl describes mmp controller related info */
-struct mmphw_ctrl {
-	/* platform related, get from config */
-	const char *name;
-	int irq;
-	void *reg_base;
-	struct clk *clk;
-
-	/* sys info */
-	struct device *dev;
-
-	/* state */
-	int open_count;
-	int status;
-	struct mutex access_ok;
-
-	/*pathes*/
-	int path_num;
-	struct mmphw_path_plat path_plats[0];
-};
-
-static inline int overlay_is_vid(struct mmp_overlay *overlay)
-{
-	return overlay->dmafetch_id & 1;
-}
-
-static inline struct mmphw_path_plat *path_to_path_plat(struct mmp_path *path)
-{
-	return (struct mmphw_path_plat *)path->plat_data;
-}
-
-static inline struct mmphw_ctrl *path_to_ctrl(struct mmp_path *path)
-{
-	return path_to_path_plat(path)->ctrl;
-}
-
-static inline struct mmphw_ctrl *overlay_to_ctrl(struct mmp_overlay *overlay)
-{
-	return path_to_ctrl(overlay->path);
-}
-
-static inline void *ctrl_regs(struct mmp_path *path)
-{
-	return path_to_ctrl(path)->reg_base;
-}
-
-/* path regs, for regs symmetrical for both pathes */
-static inline struct lcd_regs *path_regs(struct mmp_path *path)
-{
-	if (path->id == PATH_PN)
-		return (struct lcd_regs *)(ctrl_regs(path) + 0xc0);
-	else if (path->id == PATH_TV)
-		return (struct lcd_regs *)ctrl_regs(path);
-	else if (path->id == PATH_P2)
-		return (struct lcd_regs *)(ctrl_regs(path) + 0x200);
-	else {
-		dev_err(path->dev, "path id %d invalid\n", path->id);
-		BUG_ON(1);
-		return NULL;
-	}
-}
-
-#ifdef CONFIG_MMP_DISP_SPI
-extern int lcd_spi_register(struct mmphw_ctrl *ctrl);
-#endif
-#endif	/* _MMP_CTRL_H_ */
diff --git a/drivers/video/mmp/hw/mmp_spi.c b/drivers/video/mmp/hw/mmp_spi.c
deleted file mode 100644
index e62ca7bf0d5e..000000000000
--- a/drivers/video/mmp/hw/mmp_spi.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * linux/drivers/video/mmp/hw/mmp_spi.c
- * using the spi in LCD controler for commands send
- *
- * Copyright (C) 2012 Marvell Technology Group Ltd.
- * Authors:  Guoqing Li <ligq@marvell.com>
- *          Lisa Du <cldu@marvell.com>
- *          Zhou Zhu <zzhu3@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include "mmp_ctrl.h"
-
-/**
- * spi_write - write command to the SPI port
- * @data: can be 8/16/32-bit, MSB justified data to write.
- * @len:  data length.
- *
- * Wait bus transfer complete IRQ.
- * The caller is expected to perform the necessary locking.
- *
- * Returns:
- *   %-ETIMEDOUT	timeout occurred
- *   0			success
- */
-static inline int lcd_spi_write(struct spi_device *spi, u32 data)
-{
-	int timeout = 100000, isr, ret = 0;
-	u32 tmp;
-	void *reg_base =
-		*(void **)spi_master_get_devdata(spi->master);
-
-	/* clear ISR */
-	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
-
-	switch (spi->bits_per_word) {
-	case 8:
-		writel_relaxed((u8)data, reg_base + LCD_SPU_SPI_TXDATA);
-		break;
-	case 16:
-		writel_relaxed((u16)data, reg_base + LCD_SPU_SPI_TXDATA);
-		break;
-	case 32:
-		writel_relaxed((u32)data, reg_base + LCD_SPU_SPI_TXDATA);
-		break;
-	default:
-		dev_err(&spi->dev, "Wrong spi bit length\n");
-	}
-
-	/* SPI start to send command */
-	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
-	tmp &= ~CFG_SPI_START_MASK;
-	tmp |= CFG_SPI_START(1);
-	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
-
-	isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
-	while (!(isr & SPI_IRQ_ENA_MASK)) {
-		udelay(100);
-		isr = readl_relaxed(reg_base + SPU_IRQ_ISR);
-		if (!--timeout) {
-			ret = -ETIMEDOUT;
-			dev_err(&spi->dev, "spi cmd send time out\n");
-			break;
-		}
-	}
-
-	tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL);
-	tmp &= ~CFG_SPI_START_MASK;
-	tmp |= CFG_SPI_START(0);
-	writel_relaxed(tmp, reg_base + LCD_SPU_SPI_CTRL);
-
-	writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR);
-
-	return ret;
-}
-
-static int lcd_spi_setup(struct spi_device *spi)
-{
-	void *reg_base =
-		*(void **)spi_master_get_devdata(spi->master);
-	u32 tmp;
-
-	tmp = CFG_SCLKCNT(16) |
-		CFG_TXBITS(spi->bits_per_word) |
-		CFG_SPI_SEL(1) | CFG_SPI_ENA(1) |
-		CFG_SPI_3W4WB(1);
-	writel(tmp, reg_base + LCD_SPU_SPI_CTRL);
-
-	/*
-	 * After set mode it need a time to pull up the spi singals,
-	 * or it would cause the wrong waveform when send spi command,
-	 * especially on pxa910h
-	 */
-	tmp = readl_relaxed(reg_base + SPU_IOPAD_CONTROL);
-	if ((tmp & CFG_IOPADMODE_MASK) != IOPAD_DUMB18SPI)
-		writel_relaxed(IOPAD_DUMB18SPI |
-			(tmp & ~CFG_IOPADMODE_MASK),
-			reg_base + SPU_IOPAD_CONTROL);
-	udelay(20);
-	return 0;
-}
-
-static int lcd_spi_one_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct spi_transfer *t;
-	int i;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		switch (spi->bits_per_word) {
-		case 8:
-			for (i = 0; i < t->len; i++)
-				lcd_spi_write(spi, ((u8 *)t->tx_buf)[i]);
-			break;
-		case 16:
-			for (i = 0; i < t->len/2; i++)
-				lcd_spi_write(spi, ((u16 *)t->tx_buf)[i]);
-			break;
-		case 32:
-			for (i = 0; i < t->len/4; i++)
-				lcd_spi_write(spi, ((u32 *)t->tx_buf)[i]);
-			break;
-		default:
-			dev_err(&spi->dev, "Wrong spi bit length\n");
-		}
-	}
-
-	m->status = 0;
-	if (m->complete)
-		m->complete(m->context);
-	return 0;
-}
-
-int lcd_spi_register(struct mmphw_ctrl *ctrl)
-{
-	struct spi_master *master;
-	void **p_regbase;
-	int err;
-
-	master = spi_alloc_master(ctrl->dev, sizeof(void *));
-	if (!master) {
-		dev_err(ctrl->dev, "unable to allocate SPI master\n");
-		return -ENOMEM;
-	}
-	p_regbase = spi_master_get_devdata(master);
-	*p_regbase = ctrl->reg_base;
-
-	/* set bus num to 5 to avoid conflict with other spi hosts */
-	master->bus_num = 5;
-	master->num_chipselect = 1;
-	master->setup = lcd_spi_setup;
-	master->transfer = lcd_spi_one_transfer;
-
-	err = spi_register_master(master);
-	if (err < 0) {
-		dev_err(ctrl->dev, "unable to register SPI master\n");
-		spi_master_put(master);
-		return err;
-	}
-
-	dev_info(&master->dev, "registered\n");
-
-	return 0;
-}
diff --git a/drivers/video/mmp/panel/Kconfig b/drivers/video/mmp/panel/Kconfig
deleted file mode 100644
index 4b2c4f457b11..000000000000
--- a/drivers/video/mmp/panel/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-config MMP_PANEL_TPOHVGA
-	bool "tpohvga panel TJ032MD01BW support"
-	depends on SPI_MASTER
-	default n
-	help
-		tpohvga panel support
diff --git a/drivers/video/mmp/panel/Makefile b/drivers/video/mmp/panel/Makefile
deleted file mode 100644
index 2f91611c7e5e..000000000000
--- a/drivers/video/mmp/panel/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_MMP_PANEL_TPOHVGA)    += tpo_tj032md01bw.o
diff --git a/drivers/video/mmp/panel/tpo_tj032md01bw.c b/drivers/video/mmp/panel/tpo_tj032md01bw.c
deleted file mode 100644
index 998978b08f5e..000000000000
--- a/drivers/video/mmp/panel/tpo_tj032md01bw.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c
- * active panel using spi interface to do init
- *
- * Copyright (C) 2012 Marvell Technology Group Ltd.
- * Authors:  Guoqing Li <ligq@marvell.com>
- *          Lisa Du <cldu@marvell.com>
- *          Zhou Zhu <zzhu3@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/spi/spi.h>
-#include <video/mmp_disp.h>
-
-static u16 init[] = {
-	0x0801,
-	0x0800,
-	0x0200,
-	0x0304,
-	0x040e,
-	0x0903,
-	0x0b18,
-	0x0c53,
-	0x0d01,
-	0x0ee0,
-	0x0f01,
-	0x1058,
-	0x201e,
-	0x210a,
-	0x220a,
-	0x231e,
-	0x2400,
-	0x2532,
-	0x2600,
-	0x27ac,
-	0x2904,
-	0x2aa2,
-	0x2b45,
-	0x2c45,
-	0x2d15,
-	0x2e5a,
-	0x2fff,
-	0x306b,
-	0x310d,
-	0x3248,
-	0x3382,
-	0x34bd,
-	0x35e7,
-	0x3618,
-	0x3794,
-	0x3801,
-	0x395d,
-	0x3aae,
-	0x3bff,
-	0x07c9,
-};
-
-static u16 poweroff[] = {
-	0x07d9,
-};
-
-struct tpohvga_plat_data {
-	void (*plat_onoff)(int status);
-	struct spi_device *spi;
-};
-
-static void tpohvga_onoff(struct mmp_panel *panel, int status)
-{
-	struct tpohvga_plat_data *plat = panel->plat_data;
-	int ret;
-
-	if (status) {
-		plat->plat_onoff(1);
-
-		ret = spi_write(plat->spi, init, sizeof(init));
-		if (ret < 0)
-			dev_warn(panel->dev, "init cmd failed(%d)\n", ret);
-	} else {
-		ret = spi_write(plat->spi, poweroff, sizeof(poweroff));
-		if (ret < 0)
-			dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret);
-
-		plat->plat_onoff(0);
-	}
-}
-
-static struct mmp_mode mmp_modes_tpohvga[] = {
-	[0] = {
-		.pixclock_freq = 10394400,
-		.refresh = 60,
-		.xres = 320,
-		.yres = 480,
-		.hsync_len = 10,
-		.left_margin = 15,
-		.right_margin = 10,
-		.vsync_len = 2,
-		.upper_margin = 4,
-		.lower_margin = 2,
-		.invert_pixclock = 1,
-		.pix_fmt_out = PIXFMT_RGB565,
-	},
-};
-
-static int tpohvga_get_modelist(struct mmp_panel *panel,
-		struct mmp_mode **modelist)
-{
-	*modelist = mmp_modes_tpohvga;
-	return 1;
-}
-
-static struct mmp_panel panel_tpohvga = {
-	.name = "tpohvga",
-	.panel_type = PANELTYPE_ACTIVE,
-	.get_modelist = tpohvga_get_modelist,
-	.set_onoff = tpohvga_onoff,
-};
-
-static int tpohvga_probe(struct spi_device *spi)
-{
-	struct mmp_mach_panel_info *mi;
-	int ret;
-	struct tpohvga_plat_data *plat_data;
-
-	/* get configs from platform data */
-	mi = spi->dev.platform_data;
-	if (mi == NULL) {
-		dev_err(&spi->dev, "%s: no platform data defined\n", __func__);
-		return -EINVAL;
-	}
-
-	/* setup spi related info */
-	spi->bits_per_word = 16;
-	ret = spi_setup(spi);
-	if (ret < 0) {
-		dev_err(&spi->dev, "spi setup failed %d", ret);
-		return ret;
-	}
-
-	plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL);
-	if (plat_data == NULL)
-		return -ENOMEM;
-
-	plat_data->spi = spi;
-	plat_data->plat_onoff = mi->plat_set_onoff;
-	panel_tpohvga.plat_data = plat_data;
-	panel_tpohvga.plat_path_name = mi->plat_path_name;
-	panel_tpohvga.dev = &spi->dev;
-
-	mmp_register_panel(&panel_tpohvga);
-
-	return 0;
-}
-
-static struct spi_driver panel_tpohvga_driver = {
-	.driver		= {
-		.name	= "tpo-hvga",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= tpohvga_probe,
-};
-module_spi_driver(panel_tpohvga_driver);
-
-MODULE_AUTHOR("Lisa Du<cldu@marvell.com>");
-MODULE_DESCRIPTION("Panel driver for tpohvga");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
deleted file mode 100644
index a9a907c440d7..000000000000
--- a/drivers/video/modedb.c
+++ /dev/null
@@ -1,1137 +0,0 @@
-/*
- *  linux/drivers/video/modedb.c -- Standard video mode database management
- *
- *	Copyright (C) 1999 Geert Uytterhoeven
- *
- *	2001 - Documented with DocBook
- *	- Brad Douglas <brad@neruo.com>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/kernel.h>
-
-#undef DEBUG
-
-#define name_matches(v, s, l) \
-    ((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l))
-#define res_matches(v, x, y) \
-    ((v).xres == (x) && (v).yres == (y))
-
-#ifdef DEBUG
-#define DPRINTK(fmt, args...)	printk("modedb %s: " fmt, __func__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-const char *fb_mode_option;
-EXPORT_SYMBOL_GPL(fb_mode_option);
-
-/*
- *  Standard video mode definitions (taken from XFree86)
- */
-
-static const struct fb_videomode modedb[] = {
-
-	/* 640x400 @ 70 Hz, 31.5 kHz hsync */
-	{ NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
-	{ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,	0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 800x600 @ 56 Hz, 35.15 kHz hsync */
-	{ NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,	0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
-	{ NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 0,
-		FB_VMODE_INTERLACED },
-
-	/* 640x400 @ 85 Hz, 37.86 kHz hsync */
-	{ NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
-		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
-
-	/* 640x480 @ 72 Hz, 36.5 kHz hsync */
-	{ NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 640x480 @ 75 Hz, 37.50 kHz hsync */
-	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,	0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 800x600 @ 60 Hz, 37.8 kHz hsync */
-	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 640x480 @ 85 Hz, 43.27 kHz hsync */
-	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
-	{ NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 0,
-		FB_VMODE_INTERLACED },
-	/* 800x600 @ 72 Hz, 48.0 kHz hsync */
-	{ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1024x768 @ 60 Hz, 48.4 kHz hsync */
-	{ NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 640x480 @ 100 Hz, 53.01 kHz hsync */
-	{ NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,	0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1152x864 @ 60 Hz, 53.5 kHz hsync */
-	{ NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 800x600 @ 85 Hz, 55.84 kHz hsync */
-	{ NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1024x768 @ 70 Hz, 56.5 kHz hsync */
-	{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
-	{ NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,	0,
-		FB_VMODE_INTERLACED },
-
-	/* 800x600 @ 100 Hz, 64.02 kHz hsync */
-	{ NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1024x768 @ 76 Hz, 62.5 kHz hsync */
-	{ NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1152x864 @ 70 Hz, 62.4 kHz hsync */
-	{ NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
-	{ NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1400x1050 @ 60Hz, 63.9 kHz hsync */
-	{ NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
-	{ NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
-	{ NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1024x768 @ 85 Hz, 70.24 kHz hsync */
-	{ NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1152x864 @ 78 Hz, 70.8 kHz hsync */
-	{ NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
-	{ NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1600x1200 @ 60Hz, 75.00 kHz hsync */
-	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1152x864 @ 84 Hz, 76.0 kHz hsync */
-	{ NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
-	{ NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1024x768 @ 100Hz, 80.21 kHz hsync */
-	{ NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
-	{ NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
-	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1152x864 @ 100 Hz, 89.62 kHz hsync */
-	{ NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
-	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
-	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
-	{ NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
-	{ NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
-	{ NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1800x1440 @ 64Hz, 96.15 kHz hsync  */
-	{ NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1800x1440 @ 70Hz, 104.52 kHz hsync  */
-	{ NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 512x384 @ 78 Hz, 31.50 kHz hsync */
-	{ NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 512x384 @ 85 Hz, 34.38 kHz hsync */
-	{ NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
-	{ NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
-	{ NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 320x240 @ 72 Hz, 36.5 kHz hsync */
-	{ NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
-	{ NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 400x300 @ 60 Hz, 37.8 kHz hsync */
-	{ NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 400x300 @ 72 Hz, 48.0 kHz hsync */
-	{ NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,	0,
-		FB_VMODE_DOUBLE },
-
-	/* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
-	{ NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 480x300 @ 60 Hz, 37.8 kHz hsync */
-	{ NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 480x300 @ 63 Hz, 39.6 kHz hsync */
-	{ NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 480x300 @ 72 Hz, 48.0 kHz hsync */
-	{ NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0,
-		FB_VMODE_DOUBLE },
-
-	/* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
-	{ NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
-	{ NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
-	{ NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */
-	{ NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 0,
-		FB_VMODE_NONINTERLACED },
-
-	/* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
-	{ NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0,
-		FB_VMODE_INTERLACED },
-
-	/* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
-	{ NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 0,
-		FB_VMODE_INTERLACED },
-
-	/* 864x480 @ 60 Hz, 35.15 kHz hsync */
-	{ NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
-		0, FB_VMODE_NONINTERLACED },
-};
-
-#ifdef CONFIG_FB_MODE_HELPERS
-const struct fb_videomode cea_modes[64] = {
-	/* #1: 640x480p@59.94/60Hz */
-	[1] = {
-		NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
-		FB_VMODE_NONINTERLACED, 0,
-	},
-	/* #3: 720x480p@59.94/60Hz */
-	[3] = {
-		NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
-		FB_VMODE_NONINTERLACED, 0,
-	},
-	/* #5: 1920x1080i@59.94/60Hz */
-	[5] = {
-		NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_INTERLACED, 0,
-	},
-	/* #7: 720(1440)x480iH@59.94/60Hz */
-	[7] = {
-		NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
-		FB_VMODE_INTERLACED, 0,
-	},
-	/* #9: 720(1440)x240pH@59.94/60Hz */
-	[9] = {
-		NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
-		FB_VMODE_NONINTERLACED, 0,
-	},
-	/* #18: 720x576pH@50Hz */
-	[18] = {
-		NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
-		FB_VMODE_NONINTERLACED, 0,
-	},
-	/* #19: 1280x720p@50Hz */
-	[19] = {
-		NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED, 0,
-	},
-	/* #20: 1920x1080i@50Hz */
-	[20] = {
-		NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_INTERLACED, 0,
-	},
-	/* #32: 1920x1080p@23.98/24Hz */
-	[32] = {
-		NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
-		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED, 0,
-	},
-	/* #35: (2880)x480p4x@59.94/60Hz */
-	[35] = {
-		NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0,
-		FB_VMODE_NONINTERLACED, 0,
-	},
-};
-
-const struct fb_videomode vesa_modes[] = {
-	/* 0 640x350-85 VESA */
-	{ NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
-	  FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
-	/* 1 640x400-85 VESA */
-	{ NULL, 85, 640, 400, 31746,  96, 32, 41, 01, 64, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 2 720x400-85 VESA */
-	{ NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 3 640x480-60 VESA */
-	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 4 640x480-72 VESA */
-	{ NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 5 640x480-75 VESA */
-	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 6 640x480-85 VESA */
-	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 7 800x600-56 VESA */
-	{ NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 8 800x600-60 VESA */
-	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 9 800x600-72 VESA */
-	{ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 10 800x600-75 VESA */
-	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 11 800x600-85 VESA */
-	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-        /* 12 1024x768i-43 VESA */
-	{ NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_INTERLACED, FB_MODE_IS_VESA },
-	/* 13 1024x768-60 VESA */
-	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 14 1024x768-70 VESA */
-	{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
-	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 15 1024x768-75 VESA */
-	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 16 1024x768-85 VESA */
-	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 17 1152x864-75 VESA */
-	{ NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 18 1280x960-60 VESA */
-	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 19 1280x960-85 VESA */
-	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 20 1280x1024-60 VESA */
-	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 21 1280x1024-75 VESA */
-	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 22 1280x1024-85 VESA */
-	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 23 1600x1200-60 VESA */
-	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 24 1600x1200-65 VESA */
-	{ NULL, 65, 1600, 1200, 5698, 304,  64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 25 1600x1200-70 VESA */
-	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 26 1600x1200-75 VESA */
-	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 27 1600x1200-85 VESA */
-	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
-	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 28 1792x1344-60 VESA */
-	{ NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 29 1792x1344-75 VESA */
-	{ NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 30 1856x1392-60 VESA */
-	{ NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 31 1856x1392-75 VESA */
-	{ NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 32 1920x1440-60 VESA */
-	{ NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-	/* 33 1920x1440-75 VESA */
-	{ NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
-	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
-};
-EXPORT_SYMBOL(vesa_modes);
-#endif /* CONFIG_FB_MODE_HELPERS */
-
-/**
- *	fb_try_mode - test a video mode
- *	@var: frame buffer user defined part of display
- *	@info: frame buffer info structure
- *	@mode: frame buffer video mode structure
- *	@bpp: color depth in bits per pixel
- *
- *	Tries a video mode to test it's validity for device @info.
- *
- *	Returns 1 on success.
- *
- */
-
-static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
-		       const struct fb_videomode *mode, unsigned int bpp)
-{
-	int err = 0;
-
-	DPRINTK("Trying mode %s %dx%d-%d@%d\n",
-		mode->name ? mode->name : "noname",
-		mode->xres, mode->yres, bpp, mode->refresh);
-	var->xres = mode->xres;
-	var->yres = mode->yres;
-	var->xres_virtual = mode->xres;
-	var->yres_virtual = mode->yres;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->bits_per_pixel = bpp;
-	var->activate |= FB_ACTIVATE_TEST;
-	var->pixclock = mode->pixclock;
-	var->left_margin = mode->left_margin;
-	var->right_margin = mode->right_margin;
-	var->upper_margin = mode->upper_margin;
-	var->lower_margin = mode->lower_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
-	var->sync = mode->sync;
-	var->vmode = mode->vmode;
-	if (info->fbops->fb_check_var)
-		err = info->fbops->fb_check_var(var, info);
-	var->activate &= ~FB_ACTIVATE_TEST;
-	return err;
-}
-
-/**
- *     fb_find_mode - finds a valid video mode
- *     @var: frame buffer user defined part of display
- *     @info: frame buffer info structure
- *     @mode_option: string video mode to find
- *     @db: video mode database
- *     @dbsize: size of @db
- *     @default_mode: default video mode to fall back to
- *     @default_bpp: default color depth in bits per pixel
- *
- *     Finds a suitable video mode, starting with the specified mode
- *     in @mode_option with fallback to @default_mode.  If
- *     @default_mode fails, all modes in the video mode database will
- *     be tried.
- *
- *     Valid mode specifiers for @mode_option:
- *
- *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
- *     <name>[-<bpp>][@<refresh>]
- *
- *     with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
- *     <name> a string.
- *
- *      If 'M' is present after yres (and before refresh/bpp if present),
- *      the function will compute the timings using VESA(tm) Coordinated
- *      Video Timings (CVT).  If 'R' is present after 'M', will compute with
- *      reduced blanking (for flatpanels).  If 'i' is present, compute
- *      interlaced mode.  If 'm' is present, add margins equal to 1.8%
- *      of xres rounded down to 8 pixels, and 1.8% of yres. The char
- *      'i' and 'm' must be after 'M' and 'R'. Example:
- *
- *      1024x768MR-8@60m - Reduced blank with margins at 60Hz.
- *
- *     NOTE: The passed struct @var is _not_ cleared!  This allows you
- *     to supply values for e.g. the grayscale and accel_flags fields.
- *
- *     Returns zero for failure, 1 if using specified @mode_option,
- *     2 if using specified @mode_option with an ignored refresh rate,
- *     3 if default mode is used, 4 if fall back to any valid mode.
- *
- */
-
-int fb_find_mode(struct fb_var_screeninfo *var,
-		 struct fb_info *info, const char *mode_option,
-		 const struct fb_videomode *db, unsigned int dbsize,
-		 const struct fb_videomode *default_mode,
-		 unsigned int default_bpp)
-{
-	int i;
-
-	/* Set up defaults */
-	if (!db) {
-		db = modedb;
-		dbsize = ARRAY_SIZE(modedb);
-	}
-
-	if (!default_mode)
-		default_mode = &db[0];
-
-	if (!default_bpp)
-		default_bpp = 8;
-
-	/* Did the user specify a video mode? */
-	if (!mode_option)
-		mode_option = fb_mode_option;
-	if (mode_option) {
-		const char *name = mode_option;
-		unsigned int namelen = strlen(name);
-		int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
-		unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
-		int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
-		int margins = 0;
-		u32 best, diff, tdiff;
-
-		for (i = namelen-1; i >= 0; i--) {
-			switch (name[i]) {
-			case '@':
-				namelen = i;
-				if (!refresh_specified && !bpp_specified &&
-				    !yres_specified) {
-					refresh = simple_strtol(&name[i+1], NULL,
-								10);
-					refresh_specified = 1;
-					if (cvt || rb)
-						cvt = 0;
-				} else
-					goto done;
-				break;
-			case '-':
-				namelen = i;
-				if (!bpp_specified && !yres_specified) {
-					bpp = simple_strtol(&name[i+1], NULL,
-							    10);
-					bpp_specified = 1;
-					if (cvt || rb)
-						cvt = 0;
-				} else
-					goto done;
-				break;
-			case 'x':
-				if (!yres_specified) {
-					yres = simple_strtol(&name[i+1], NULL,
-							     10);
-					yres_specified = 1;
-				} else
-					goto done;
-				break;
-			case '0' ... '9':
-				break;
-			case 'M':
-				if (!yres_specified)
-					cvt = 1;
-				break;
-			case 'R':
-				if (!cvt)
-					rb = 1;
-				break;
-			case 'm':
-				if (!cvt)
-					margins = 1;
-				break;
-			case 'i':
-				if (!cvt)
-					interlace = 1;
-				break;
-			default:
-				goto done;
-			}
-		}
-		if (i < 0 && yres_specified) {
-			xres = simple_strtol(name, NULL, 10);
-			res_specified = 1;
-		}
-done:
-		if (cvt) {
-			struct fb_videomode cvt_mode;
-			int ret;
-
-			DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
-				(refresh) ? refresh : 60,
-				(rb) ? " reduced blanking" : "",
-				(margins) ? " with margins" : "",
-				(interlace) ? " interlaced" : "");
-
-			memset(&cvt_mode, 0, sizeof(cvt_mode));
-			cvt_mode.xres = xres;
-			cvt_mode.yres = yres;
-			cvt_mode.refresh = (refresh) ? refresh : 60;
-
-			if (interlace)
-				cvt_mode.vmode |= FB_VMODE_INTERLACED;
-			else
-				cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
-
-			ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
-
-			if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
-				DPRINTK("modedb CVT: CVT mode ok\n");
-				return 1;
-			}
-
-			DPRINTK("CVT mode invalid, getting mode from database\n");
-		}
-
-		DPRINTK("Trying specified video mode%s %ix%i\n",
-			refresh_specified ? "" : " (ignoring refresh rate)",
-			xres, yres);
-
-		if (!refresh_specified) {
-			/*
-			 * If the caller has provided a custom mode database and
-			 * a valid monspecs structure, we look for the mode with
-			 * the highest refresh rate.  Otherwise we play it safe
-			 * it and try to find a mode with a refresh rate closest
-			 * to the standard 60 Hz.
-			 */
-			if (db != modedb &&
-			    info->monspecs.vfmin && info->monspecs.vfmax &&
-			    info->monspecs.hfmin && info->monspecs.hfmax &&
-			    info->monspecs.dclkmax) {
-				refresh = 1000;
-			} else {
-				refresh = 60;
-			}
-		}
-
-		diff = -1;
-		best = -1;
-		for (i = 0; i < dbsize; i++) {
-			if ((name_matches(db[i], name, namelen) ||
-			     (res_specified && res_matches(db[i], xres, yres))) &&
-			    !fb_try_mode(var, info, &db[i], bpp)) {
-				if (refresh_specified && db[i].refresh == refresh)
-					return 1;
-
-				if (abs(db[i].refresh - refresh) < diff) {
-					diff = abs(db[i].refresh - refresh);
-					best = i;
-				}
-			}
-		}
-		if (best != -1) {
-			fb_try_mode(var, info, &db[best], bpp);
-			return (refresh_specified) ? 2 : 1;
-		}
-
-		diff = 2 * (xres + yres);
-		best = -1;
-		DPRINTK("Trying best-fit modes\n");
-		for (i = 0; i < dbsize; i++) {
-			DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
-			if (!fb_try_mode(var, info, &db[i], bpp)) {
-				tdiff = abs(db[i].xres - xres) +
-					abs(db[i].yres - yres);
-
-				/*
-				 * Penalize modes with resolutions smaller
-				 * than requested.
-				 */
-				if (xres > db[i].xres || yres > db[i].yres)
-					tdiff += xres + yres;
-
-				if (diff > tdiff) {
-					diff = tdiff;
-					best = i;
-				}
-			}
-		}
-		if (best != -1) {
-			fb_try_mode(var, info, &db[best], bpp);
-			return 5;
-		}
-	}
-
-	DPRINTK("Trying default video mode\n");
-	if (!fb_try_mode(var, info, default_mode, default_bpp))
-		return 3;
-
-	DPRINTK("Trying all modes\n");
-	for (i = 0; i < dbsize; i++)
-		if (!fb_try_mode(var, info, &db[i], default_bpp))
-			return 4;
-
-	DPRINTK("No valid mode found\n");
-	return 0;
-}
-
-/**
- * fb_var_to_videomode - convert fb_var_screeninfo to fb_videomode
- * @mode: pointer to struct fb_videomode
- * @var: pointer to struct fb_var_screeninfo
- */
-void fb_var_to_videomode(struct fb_videomode *mode,
-			 const struct fb_var_screeninfo *var)
-{
-	u32 pixclock, hfreq, htotal, vtotal;
-
-	mode->name = NULL;
-	mode->xres = var->xres;
-	mode->yres = var->yres;
-	mode->pixclock = var->pixclock;
-	mode->hsync_len = var->hsync_len;
-	mode->vsync_len = var->vsync_len;
-	mode->left_margin = var->left_margin;
-	mode->right_margin = var->right_margin;
-	mode->upper_margin = var->upper_margin;
-	mode->lower_margin = var->lower_margin;
-	mode->sync = var->sync;
-	mode->vmode = var->vmode & FB_VMODE_MASK;
-	mode->flag = FB_MODE_IS_FROM_VAR;
-	mode->refresh = 0;
-
-	if (!var->pixclock)
-		return;
-
-	pixclock = PICOS2KHZ(var->pixclock) * 1000;
-
-	htotal = var->xres + var->right_margin + var->hsync_len +
-		var->left_margin;
-	vtotal = var->yres + var->lower_margin + var->vsync_len +
-		var->upper_margin;
-
-	if (var->vmode & FB_VMODE_INTERLACED)
-		vtotal /= 2;
-	if (var->vmode & FB_VMODE_DOUBLE)
-		vtotal *= 2;
-
-	hfreq = pixclock/htotal;
-	mode->refresh = hfreq/vtotal;
-}
-
-/**
- * fb_videomode_to_var - convert fb_videomode to fb_var_screeninfo
- * @var: pointer to struct fb_var_screeninfo
- * @mode: pointer to struct fb_videomode
- */
-void fb_videomode_to_var(struct fb_var_screeninfo *var,
-			 const struct fb_videomode *mode)
-{
-	var->xres = mode->xres;
-	var->yres = mode->yres;
-	var->xres_virtual = mode->xres;
-	var->yres_virtual = mode->yres;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->pixclock = mode->pixclock;
-	var->left_margin = mode->left_margin;
-	var->right_margin = mode->right_margin;
-	var->upper_margin = mode->upper_margin;
-	var->lower_margin = mode->lower_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
-	var->sync = mode->sync;
-	var->vmode = mode->vmode & FB_VMODE_MASK;
-}
-
-/**
- * fb_mode_is_equal - compare 2 videomodes
- * @mode1: first videomode
- * @mode2: second videomode
- *
- * RETURNS:
- * 1 if equal, 0 if not
- */
-int fb_mode_is_equal(const struct fb_videomode *mode1,
-		     const struct fb_videomode *mode2)
-{
-	return (mode1->xres         == mode2->xres &&
-		mode1->yres         == mode2->yres &&
-		mode1->pixclock     == mode2->pixclock &&
-		mode1->hsync_len    == mode2->hsync_len &&
-		mode1->vsync_len    == mode2->vsync_len &&
-		mode1->left_margin  == mode2->left_margin &&
-		mode1->right_margin == mode2->right_margin &&
-		mode1->upper_margin == mode2->upper_margin &&
-		mode1->lower_margin == mode2->lower_margin &&
-		mode1->sync         == mode2->sync &&
-		mode1->vmode        == mode2->vmode);
-}
-
-/**
- * fb_find_best_mode - find best matching videomode
- * @var: pointer to struct fb_var_screeninfo
- * @head: pointer to struct list_head of modelist
- *
- * RETURNS:
- * struct fb_videomode, NULL if none found
- *
- * IMPORTANT:
- * This function assumes that all modelist entries in
- * info->modelist are valid.
- *
- * NOTES:
- * Finds best matching videomode which has an equal or greater dimension than
- * var->xres and var->yres.  If more than 1 videomode is found, will return
- * the videomode with the highest refresh rate
- */
-const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
-					     struct list_head *head)
-{
-	struct list_head *pos;
-	struct fb_modelist *modelist;
-	struct fb_videomode *mode, *best = NULL;
-	u32 diff = -1;
-
-	list_for_each(pos, head) {
-		u32 d;
-
-		modelist = list_entry(pos, struct fb_modelist, list);
-		mode = &modelist->mode;
-
-		if (mode->xres >= var->xres && mode->yres >= var->yres) {
-			d = (mode->xres - var->xres) +
-				(mode->yres - var->yres);
-			if (diff > d) {
-				diff = d;
-				best = mode;
-			} else if (diff == d && best &&
-				   mode->refresh > best->refresh)
-				best = mode;
-		}
-	}
-	return best;
-}
-
-/**
- * fb_find_nearest_mode - find closest videomode
- *
- * @mode: pointer to struct fb_videomode
- * @head: pointer to modelist
- *
- * Finds best matching videomode, smaller or greater in dimension.
- * If more than 1 videomode is found, will return the videomode with
- * the closest refresh rate.
- */
-const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
-					        struct list_head *head)
-{
-	struct list_head *pos;
-	struct fb_modelist *modelist;
-	struct fb_videomode *cmode, *best = NULL;
-	u32 diff = -1, diff_refresh = -1;
-
-	list_for_each(pos, head) {
-		u32 d;
-
-		modelist = list_entry(pos, struct fb_modelist, list);
-		cmode = &modelist->mode;
-
-		d = abs(cmode->xres - mode->xres) +
-			abs(cmode->yres - mode->yres);
-		if (diff > d) {
-			diff = d;
-			diff_refresh = abs(cmode->refresh - mode->refresh);
-			best = cmode;
-		} else if (diff == d) {
-			d = abs(cmode->refresh - mode->refresh);
-			if (diff_refresh > d) {
-				diff_refresh = d;
-				best = cmode;
-			}
-		}
-	}
-
-	return best;
-}
-
-/**
- * fb_match_mode - find a videomode which exactly matches the timings in var
- * @var: pointer to struct fb_var_screeninfo
- * @head: pointer to struct list_head of modelist
- *
- * RETURNS:
- * struct fb_videomode, NULL if none found
- */
-const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
-					 struct list_head *head)
-{
-	struct list_head *pos;
-	struct fb_modelist *modelist;
-	struct fb_videomode *m, mode;
-
-	fb_var_to_videomode(&mode, var);
-	list_for_each(pos, head) {
-		modelist = list_entry(pos, struct fb_modelist, list);
-		m = &modelist->mode;
-		if (fb_mode_is_equal(m, &mode))
-			return m;
-	}
-	return NULL;
-}
-
-/**
- * fb_add_videomode - adds videomode entry to modelist
- * @mode: videomode to add
- * @head: struct list_head of modelist
- *
- * NOTES:
- * Will only add unmatched mode entries
- */
-int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
-{
-	struct list_head *pos;
-	struct fb_modelist *modelist;
-	struct fb_videomode *m;
-	int found = 0;
-
-	list_for_each(pos, head) {
-		modelist = list_entry(pos, struct fb_modelist, list);
-		m = &modelist->mode;
-		if (fb_mode_is_equal(m, mode)) {
-			found = 1;
-			break;
-		}
-	}
-	if (!found) {
-		modelist = kmalloc(sizeof(struct fb_modelist),
-						  GFP_KERNEL);
-
-		if (!modelist)
-			return -ENOMEM;
-		modelist->mode = *mode;
-		list_add(&modelist->list, head);
-	}
-	return 0;
-}
-
-/**
- * fb_delete_videomode - removed videomode entry from modelist
- * @mode: videomode to remove
- * @head: struct list_head of modelist
- *
- * NOTES:
- * Will remove all matching mode entries
- */
-void fb_delete_videomode(const struct fb_videomode *mode,
-			 struct list_head *head)
-{
-	struct list_head *pos, *n;
-	struct fb_modelist *modelist;
-	struct fb_videomode *m;
-
-	list_for_each_safe(pos, n, head) {
-		modelist = list_entry(pos, struct fb_modelist, list);
-		m = &modelist->mode;
-		if (fb_mode_is_equal(m, mode)) {
-			list_del(pos);
-			kfree(pos);
-		}
-	}
-}
-
-/**
- * fb_destroy_modelist - destroy modelist
- * @head: struct list_head of modelist
- */
-void fb_destroy_modelist(struct list_head *head)
-{
-	struct list_head *pos, *n;
-
-	list_for_each_safe(pos, n, head) {
-		list_del(pos);
-		kfree(pos);
-	}
-}
-EXPORT_SYMBOL_GPL(fb_destroy_modelist);
-
-/**
- * fb_videomode_to_modelist - convert mode array to mode list
- * @modedb: array of struct fb_videomode
- * @num: number of entries in array
- * @head: struct list_head of modelist
- */
-void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
-			      struct list_head *head)
-{
-	int i;
-
-	INIT_LIST_HEAD(head);
-
-	for (i = 0; i < num; i++) {
-		if (fb_add_videomode(&modedb[i], head))
-			return;
-	}
-}
-
-const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
-					        struct list_head *head)
-{
-	struct list_head *pos;
-	struct fb_modelist *modelist;
-	const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
-	int first = 0;
-
-	if (!head->prev || !head->next || list_empty(head))
-		goto finished;
-
-	/* get the first detailed mode and the very first mode */
-	list_for_each(pos, head) {
-		modelist = list_entry(pos, struct fb_modelist, list);
-		m = &modelist->mode;
-
-		if (!first) {
-			m1 = m;
-			first = 1;
-		}
-
-		if (m->flag & FB_MODE_IS_FIRST) {
- 			md = m;
-			break;
-		}
-	}
-
-	/* first detailed timing is preferred */
-	if (specs->misc & FB_MISC_1ST_DETAIL) {
-		best = md;
-		goto finished;
-	}
-
-	/* find best mode based on display width and height */
-	if (specs->max_x && specs->max_y) {
-		struct fb_var_screeninfo var;
-
-		memset(&var, 0, sizeof(struct fb_var_screeninfo));
-		var.xres = (specs->max_x * 7200)/254;
-		var.yres = (specs->max_y * 7200)/254;
-		m = fb_find_best_mode(&var, head);
-		if (m) {
-			best = m;
-			goto finished;
-		}
-	}
-
-	/* use first detailed mode */
-	if (md) {
-		best = md;
-		goto finished;
-	}
-
-	/* last resort, use the very first mode */
-	best = m1;
-finished:
-	return best;
-}
-EXPORT_SYMBOL(fb_find_best_display);
-
-EXPORT_SYMBOL(fb_videomode_to_var);
-EXPORT_SYMBOL(fb_var_to_videomode);
-EXPORT_SYMBOL(fb_mode_is_equal);
-EXPORT_SYMBOL(fb_add_videomode);
-EXPORT_SYMBOL(fb_match_mode);
-EXPORT_SYMBOL(fb_find_best_mode);
-EXPORT_SYMBOL(fb_find_nearest_mode);
-EXPORT_SYMBOL(fb_videomode_to_modelist);
-EXPORT_SYMBOL(fb_find_mode);
-EXPORT_SYMBOL(fb_find_mode_cvt);
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
deleted file mode 100644
index 802d6ae523fb..000000000000
--- a/drivers/video/msm/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-
-# core framebuffer
-#
-obj-y := msm_fb.o
-
-# MDP DMA/PPP engine
-#
-obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
-
-# MDDI interface
-#
-obj-y += mddi.o
-
-# MDDI client/panel drivers
-#
-obj-y += mddi_client_dummy.o
-obj-y += mddi_client_toshiba.o
-obj-y += mddi_client_nt35399.o
-
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
deleted file mode 100644
index e0f8011a3c4b..000000000000
--- a/drivers/video/msm/mddi.c
+++ /dev/null
@@ -1,821 +0,0 @@
-/*
- * MSM MDDI Transport
- *
- * Copyright (C) 2007 Google Incorporated
- * Copyright (C) 2007 QUALCOMM Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <linux/spinlock.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/sched.h>
-#include <linux/platform_data/video-msm_fb.h>
-#include "mddi_hw.h"
-
-#define FLAG_DISABLE_HIBERNATION 0x0001
-#define FLAG_HAVE_CAPS		 0x0002
-#define FLAG_HAS_VSYNC_IRQ	 0x0004
-#define FLAG_HAVE_STATUS	 0x0008
-
-#define CMD_GET_CLIENT_CAP     0x0601
-#define CMD_GET_CLIENT_STATUS  0x0602
-
-union mddi_rev {
-	unsigned char raw[MDDI_REV_BUFFER_SIZE];
-	struct mddi_rev_packet hdr;
-	struct mddi_client_status status;
-	struct mddi_client_caps caps;
-	struct mddi_register_access reg;
-};
-
-struct reg_read_info {
-	struct completion done;
-	uint32_t reg;
-	uint32_t status;
-	uint32_t result;
-};
-
-struct mddi_info {
-	uint16_t flags;
-	uint16_t version;
-	char __iomem *base;
-	int irq;
-	struct clk *clk;
-	struct msm_mddi_client_data client_data;
-
-	/* buffer for rev encap packets */
-	void *rev_data;
-	dma_addr_t rev_addr;
-	struct mddi_llentry *reg_write_data;
-	dma_addr_t reg_write_addr;
-	struct mddi_llentry *reg_read_data;
-	dma_addr_t reg_read_addr;
-	size_t rev_data_curr;
-
-	spinlock_t int_lock;
-	uint32_t int_enable;
-	uint32_t got_int;
-	wait_queue_head_t int_wait;
-
-	struct mutex reg_write_lock;
-	struct mutex reg_read_lock;
-	struct reg_read_info *reg_read;
-
-	struct mddi_client_caps caps;
-	struct mddi_client_status status;
-
-	void (*power_client)(struct msm_mddi_client_data *, int);
-
-	/* client device published to bind us to the
-	 * appropriate mddi_client driver
-	 */
-	char client_name[20];
-
-	struct platform_device client_pdev;
-};
-
-static void mddi_init_rev_encap(struct mddi_info *mddi);
-
-#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
-#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
-
-void mddi_activate_link(struct msm_mddi_client_data *cdata)
-{
-	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
-					      client_data);
-
-	mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
-}
-
-static void mddi_handle_link_list_done(struct mddi_info *mddi)
-{
-}
-
-static void mddi_reset_rev_encap_ptr(struct mddi_info *mddi)
-{
-	printk(KERN_INFO "mddi: resetting rev ptr\n");
-	mddi->rev_data_curr = 0;
-	mddi_writel(mddi->rev_addr, REV_PTR);
-	mddi_writel(mddi->rev_addr, REV_PTR);
-	mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
-}
-
-static void mddi_handle_rev_data(struct mddi_info *mddi, union mddi_rev *rev)
-{
-	int i;
-	struct reg_read_info *ri;
-
-	if ((rev->hdr.length <= MDDI_REV_BUFFER_SIZE - 2) &&
-	   (rev->hdr.length >= sizeof(struct mddi_rev_packet) - 2)) {
-
-		switch (rev->hdr.type) {
-		case TYPE_CLIENT_CAPS:
-			memcpy(&mddi->caps, &rev->caps,
-			       sizeof(struct mddi_client_caps));
-			mddi->flags |= FLAG_HAVE_CAPS;
-			wake_up(&mddi->int_wait);
-			break;
-		case TYPE_CLIENT_STATUS:
-			memcpy(&mddi->status, &rev->status,
-			       sizeof(struct mddi_client_status));
-			mddi->flags |= FLAG_HAVE_STATUS;
-			wake_up(&mddi->int_wait);
-			break;
-		case TYPE_REGISTER_ACCESS:
-			ri = mddi->reg_read;
-			if (ri == 0) {
-				printk(KERN_INFO "rev: got reg %x = %x without "
-						 " pending read\n",
-				       rev->reg.register_address,
-				       rev->reg.register_data_list);
-				break;
-			}
-			if (ri->reg != rev->reg.register_address) {
-				printk(KERN_INFO "rev: got reg %x = %x for "
-						 "wrong register, expected "
-						 "%x\n",
-				       rev->reg.register_address,
-				       rev->reg.register_data_list, ri->reg);
-				break;
-			}
-			mddi->reg_read = NULL;
-			ri->status = 0;
-			ri->result = rev->reg.register_data_list;
-			complete(&ri->done);
-			break;
-		default:
-			printk(KERN_INFO "rev: unknown reverse packet: "
-					 "len=%04x type=%04x CURR_REV_PTR=%x\n",
-			       rev->hdr.length, rev->hdr.type,
-			       mddi_readl(CURR_REV_PTR));
-			for (i = 0; i < rev->hdr.length + 2; i++) {
-				if ((i % 16) == 0)
-					printk(KERN_INFO "\n");
-				printk(KERN_INFO " %02x", rev->raw[i]);
-			}
-			printk(KERN_INFO "\n");
-			mddi_reset_rev_encap_ptr(mddi);
-		}
-	} else {
-		printk(KERN_INFO "bad rev length, %d, CURR_REV_PTR %x\n",
-		       rev->hdr.length, mddi_readl(CURR_REV_PTR));
-		mddi_reset_rev_encap_ptr(mddi);
-	}
-}
-
-static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
-
-static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
-{
-	uint32_t rev_data_count;
-	uint32_t rev_crc_err_count;
-	struct reg_read_info *ri;
-	size_t prev_offset;
-	uint16_t length;
-
-	union mddi_rev *crev = mddi->rev_data + mddi->rev_data_curr;
-
-	/* clear the interrupt */
-	mddi_writel(MDDI_INT_REV_DATA_AVAIL, INT);
-	rev_data_count = mddi_readl(REV_PKT_CNT);
-	rev_crc_err_count = mddi_readl(REV_CRC_ERR);
-	if (rev_data_count > 1)
-		printk(KERN_INFO "rev_data_count %d\n", rev_data_count);
-
-	if (rev_crc_err_count) {
-		printk(KERN_INFO "rev_crc_err_count %d, INT %x\n",
-		       rev_crc_err_count,  mddi_readl(INT));
-		ri = mddi->reg_read;
-		if (ri == 0) {
-			printk(KERN_INFO "rev: got crc error without pending "
-			       "read\n");
-		} else {
-			mddi->reg_read = NULL;
-			ri->status = -EIO;
-			ri->result = -1;
-			complete(&ri->done);
-		}
-	}
-
-	if (rev_data_count == 0)
-		return;
-
-	prev_offset = mddi->rev_data_curr;
-
-	length = *((uint8_t *)mddi->rev_data + mddi->rev_data_curr);
-	mddi->rev_data_curr++;
-	if (mddi->rev_data_curr == MDDI_REV_BUFFER_SIZE)
-		mddi->rev_data_curr = 0;
-	length += *((uint8_t *)mddi->rev_data + mddi->rev_data_curr) << 8;
-	mddi->rev_data_curr += 1 + length;
-	if (mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE)
-		mddi->rev_data_curr =
-			mddi->rev_data_curr % MDDI_REV_BUFFER_SIZE;
-
-	if (length > MDDI_REV_BUFFER_SIZE - 2) {
-		printk(KERN_INFO "mddi: rev data length greater than buffer"
-			"size\n");
-		mddi_reset_rev_encap_ptr(mddi);
-		return;
-	}
-
-	if (prev_offset + 2 + length >= MDDI_REV_BUFFER_SIZE) {
-		union mddi_rev tmprev;
-		size_t rem = MDDI_REV_BUFFER_SIZE - prev_offset;
-		memcpy(&tmprev.raw[0], mddi->rev_data + prev_offset, rem);
-		memcpy(&tmprev.raw[rem], mddi->rev_data, 2 + length - rem);
-		mddi_handle_rev_data(mddi, &tmprev);
-	} else {
-		mddi_handle_rev_data(mddi, crev);
-	}
-
-	if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 &&
-	    mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) {
-		mddi_writel(mddi->rev_addr, REV_PTR);
-	}
-}
-
-static irqreturn_t mddi_isr(int irq, void *data)
-{
-	struct msm_mddi_client_data *cdata = data;
-	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
-					      client_data);
-	uint32_t active, status;
-
-	spin_lock(&mddi->int_lock);
-
-	active = mddi_readl(INT);
-	status = mddi_readl(STAT);
-
-	mddi_writel(active, INT);
-
-	/* ignore any interrupts we have disabled */
-	active &= mddi->int_enable;
-
-	mddi->got_int |= active;
-	wake_up(&mddi->int_wait);
-
-	if (active & MDDI_INT_PRI_LINK_LIST_DONE) {
-		mddi->int_enable &= (~MDDI_INT_PRI_LINK_LIST_DONE);
-		mddi_handle_link_list_done(mddi);
-	}
-	if (active & MDDI_INT_REV_DATA_AVAIL)
-		mddi_handle_rev_data_avail(mddi);
-
-	if (active & ~MDDI_INT_NEED_CLEAR)
-		mddi->int_enable &= ~(active & ~MDDI_INT_NEED_CLEAR);
-
-	if (active & MDDI_INT_LINK_ACTIVE) {
-		mddi->int_enable &= (~MDDI_INT_LINK_ACTIVE);
-		mddi->int_enable |= MDDI_INT_IN_HIBERNATION;
-	}
-
-	if (active & MDDI_INT_IN_HIBERNATION) {
-		mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION);
-		mddi->int_enable |= MDDI_INT_LINK_ACTIVE;
-	}
-
-	mddi_writel(mddi->int_enable, INTEN);
-	spin_unlock(&mddi->int_lock);
-
-	return IRQ_HANDLED;
-}
-
-static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
-					uint32_t intmask, int timeout)
-{
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&mddi->int_lock, irq_flags);
-	mddi->got_int &= ~intmask;
-	mddi->int_enable |= intmask;
-	mddi_writel(mddi->int_enable, INTEN);
-	spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
-	return wait_event_timeout(mddi->int_wait, mddi->got_int & intmask,
-				  timeout);
-}
-
-static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
-{
-	if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
-		printk(KERN_INFO "mddi_wait_interrupt %d, timeout "
-		       "waiting for %x, INT = %x, STAT = %x gotint = %x\n",
-		       current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
-		       mddi->got_int);
-}
-
-static void mddi_init_rev_encap(struct mddi_info *mddi)
-{
-	memset(mddi->rev_data, 0xee, MDDI_REV_BUFFER_SIZE);
-	mddi_writel(mddi->rev_addr, REV_PTR);
-	mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-}
-
-void mddi_set_auto_hibernate(struct msm_mddi_client_data *cdata, int on)
-{
-	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
-					      client_data);
-	mddi_writel(MDDI_CMD_POWERDOWN, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_IN_HIBERNATION);
-	mddi_writel(MDDI_CMD_HIBERNATE | !!on, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-}
-
-
-static uint16_t mddi_init_registers(struct mddi_info *mddi)
-{
-	mddi_writel(0x0001, VERSION);
-	mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
-	mddi_writel(0x0003, SPM); /* subframes per media */
-	mddi_writel(0x0005, TA1_LEN);
-	mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
-	mddi_writel(0x0096, DRIVE_HI);
-	/* 0x32 normal, 0x50 for Toshiba display */
-	mddi_writel(0x0050, DRIVE_LO);
-	mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
-	mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
-
-	mddi_writel(MDDI_REV_BUFFER_SIZE, REV_SIZE);
-	mddi_writel(MDDI_MAX_REV_PKT_SIZE, REV_ENCAP_SZ);
-
-	/* disable periodic rev encap */
-	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
-	if (mddi_readl(PAD_CTL) == 0) {
-		/* If we are turning on band gap, need to wait 5us before
-		 * turning on the rest of the PAD */
-		mddi_writel(0x08000, PAD_CTL);
-		udelay(5);
-	}
-
-	/* Recommendation from PAD hw team */
-	mddi_writel(0xa850f, PAD_CTL);
-
-
-	/* Need an even number for counts */
-	mddi_writel(0x60006, DRIVER_START_CNT);
-
-	mddi_set_auto_hibernate(&mddi->client_data, 0);
-
-	mddi_writel(MDDI_CMD_DISP_IGNORE, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
-	mddi_init_rev_encap(mddi);
-	return mddi_readl(CORE_VER) & 0xffff;
-}
-
-static void mddi_suspend(struct msm_mddi_client_data *cdata)
-{
-	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
-					      client_data);
-	/* turn off the client */
-	if (mddi->power_client)
-		mddi->power_client(&mddi->client_data, 0);
-	/* turn off the link */
-	mddi_writel(MDDI_CMD_RESET, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-	/* turn off the clock */
-	clk_disable(mddi->clk);
-}
-
-static void mddi_resume(struct msm_mddi_client_data *cdata)
-{
-	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
-					      client_data);
-	mddi_set_auto_hibernate(&mddi->client_data, 0);
-	/* turn on the client */
-	if (mddi->power_client)
-		mddi->power_client(&mddi->client_data, 1);
-	/* turn on the clock */
-	clk_enable(mddi->clk);
-	/* set up the local registers */
-	mddi->rev_data_curr = 0;
-	mddi_init_registers(mddi);
-	mddi_writel(mddi->int_enable, INTEN);
-	mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
-	mddi_writel(MDDI_CMD_SEND_RTD, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-	mddi_set_auto_hibernate(&mddi->client_data, 1);
-}
-
-static int mddi_get_client_caps(struct mddi_info *mddi)
-{
-	int i, j;
-
-	/* clear any stale interrupts */
-	mddi_writel(0xffffffff, INT);
-
-	mddi->int_enable = MDDI_INT_LINK_ACTIVE |
-			   MDDI_INT_IN_HIBERNATION |
-			   MDDI_INT_PRI_LINK_LIST_DONE |
-			   MDDI_INT_REV_DATA_AVAIL |
-			   MDDI_INT_REV_OVERFLOW |
-			   MDDI_INT_REV_OVERWRITE |
-			   MDDI_INT_RTD_FAILURE;
-	mddi_writel(mddi->int_enable, INTEN);
-
-	mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
-	for (j = 0; j < 3; j++) {
-		/* the toshiba vga panel does not respond to get
-		 * caps unless you SEND_RTD, but the first SEND_RTD
-		 * will fail...
-		 */
-		for (i = 0; i < 4; i++) {
-			uint32_t stat;
-
-			mddi_writel(MDDI_CMD_SEND_RTD, CMD);
-			mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-			stat = mddi_readl(STAT);
-			printk(KERN_INFO "mddi cmd send rtd: int %x, stat %x, "
-					"rtd val %x\n", mddi_readl(INT), stat,
-					mddi_readl(RTD_VAL));
-			if ((stat & MDDI_STAT_RTD_MEAS_FAIL) == 0)
-				break;
-			msleep(1);
-		}
-
-		mddi_writel(CMD_GET_CLIENT_CAP, CMD);
-		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-		wait_event_timeout(mddi->int_wait, mddi->flags & FLAG_HAVE_CAPS,
-				   HZ / 100);
-
-		if (mddi->flags & FLAG_HAVE_CAPS)
-			break;
-		printk(KERN_INFO "mddi_init, timeout waiting for caps\n");
-	}
-	return mddi->flags & FLAG_HAVE_CAPS;
-}
-
-/* link must be active when this is called */
-int mddi_check_status(struct mddi_info *mddi)
-{
-	int ret = -1, retry = 3;
-	mutex_lock(&mddi->reg_read_lock);
-	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-
-	do {
-		mddi->flags &= ~FLAG_HAVE_STATUS;
-		mddi_writel(CMD_GET_CLIENT_STATUS, CMD);
-		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-		wait_event_timeout(mddi->int_wait,
-				   mddi->flags & FLAG_HAVE_STATUS,
-				   HZ / 100);
-
-		if (mddi->flags & FLAG_HAVE_STATUS) {
-			if (mddi->status.crc_error_count)
-				printk(KERN_INFO "mddi status: crc_error "
-					"count: %d\n",
-					mddi->status.crc_error_count);
-			else
-				ret = 0;
-			break;
-		} else
-			printk(KERN_INFO "mddi status: failed to get client "
-				"status\n");
-		mddi_writel(MDDI_CMD_SEND_RTD, CMD);
-		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-	} while (--retry);
-
-	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-	mutex_unlock(&mddi->reg_read_lock);
-	return ret;
-}
-
-
-void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val,
-		       uint32_t reg)
-{
-	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
-					      client_data);
-	struct mddi_llentry *ll;
-	struct mddi_register_access *ra;
-
-	mutex_lock(&mddi->reg_write_lock);
-
-	ll = mddi->reg_write_data;
-
-	ra = &(ll->u.r);
-	ra->length = 14 + 4;
-	ra->type = TYPE_REGISTER_ACCESS;
-	ra->client_id = 0;
-	ra->read_write_info = MDDI_WRITE | 1;
-	ra->crc16 = 0;
-
-	ra->register_address = reg;
-	ra->register_data_list = val;
-
-	ll->flags = 1;
-	ll->header_count = 14;
-	ll->data_count = 4;
-	ll->data = mddi->reg_write_addr + offsetof(struct mddi_llentry,
-						   u.r.register_data_list);
-	ll->next = 0;
-	ll->reserved = 0;
-
-	mddi_writel(mddi->reg_write_addr, PRI_PTR);
-
-	mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
-	mutex_unlock(&mddi->reg_write_lock);
-}
-
-uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
-{
-	struct mddi_info *mddi = container_of(cdata, struct mddi_info,
-					      client_data);
-	struct mddi_llentry *ll;
-	struct mddi_register_access *ra;
-	struct reg_read_info ri;
-	unsigned s;
-	int retry_count = 2;
-	unsigned long irq_flags;
-
-	mutex_lock(&mddi->reg_read_lock);
-
-	ll = mddi->reg_read_data;
-
-	ra = &(ll->u.r);
-	ra->length = 14;
-	ra->type = TYPE_REGISTER_ACCESS;
-	ra->client_id = 0;
-	ra->read_write_info = MDDI_READ | 1;
-	ra->crc16 = 0;
-
-	ra->register_address = reg;
-
-	ll->flags = 0x11;
-	ll->header_count = 14;
-	ll->data_count = 0;
-	ll->data = 0;
-	ll->next = 0;
-	ll->reserved = 0;
-
-	s = mddi_readl(STAT);
-
-	ri.reg = reg;
-	ri.status = -1;
-
-	do {
-		init_completion(&ri.done);
-		mddi->reg_read = &ri;
-		mddi_writel(mddi->reg_read_addr, PRI_PTR);
-
-		mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
-
-		/* Enable Periodic Reverse Encapsulation. */
-		mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
-		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-		if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
-		    !ri.done.done) {
-			printk(KERN_INFO "mddi_remote_read(%x) timeout "
-					 "(%d %d %d)\n",
-			       reg, ri.status, ri.result, ri.done.done);
-			spin_lock_irqsave(&mddi->int_lock, irq_flags);
-			mddi->reg_read = NULL;
-			spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
-			ri.status = -1;
-			ri.result = -1;
-		}
-		if (ri.status == 0)
-			break;
-
-		mddi_writel(MDDI_CMD_SEND_RTD, CMD);
-		mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
-		mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-		printk(KERN_INFO "mddi_remote_read: failed, sent "
-		       "MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
-		       "curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
-		       mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
-	} while (retry_count-- > 0);
-	/* Disable Periodic Reverse Encapsulation. */
-	mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-	mddi->reg_read = NULL;
-	mutex_unlock(&mddi->reg_read_lock);
-	return ri.result;
-}
-
-static struct mddi_info mddi_info[2];
-
-static int mddi_clk_setup(struct platform_device *pdev, struct mddi_info *mddi,
-			  unsigned long clk_rate)
-{
-	int ret;
-
-	/* set up the clocks */
-	mddi->clk = clk_get(&pdev->dev, "mddi_clk");
-	if (IS_ERR(mddi->clk)) {
-		printk(KERN_INFO "mddi: failed to get clock\n");
-		return PTR_ERR(mddi->clk);
-	}
-	ret =  clk_enable(mddi->clk);
-	if (ret)
-		goto fail;
-	ret = clk_set_rate(mddi->clk, clk_rate);
-	if (ret)
-		goto fail;
-	return 0;
-
-fail:
-	clk_put(mddi->clk);
-	return ret;
-}
-
-static int __init mddi_rev_data_setup(struct mddi_info *mddi)
-{
-	void *dma;
-	dma_addr_t dma_addr;
-
-	/* set up dma buffer */
-	dma = dma_alloc_coherent(NULL, 0x1000, &dma_addr, GFP_KERNEL);
-	if (dma == 0)
-		return -ENOMEM;
-	mddi->rev_data = dma;
-	mddi->rev_data_curr = 0;
-	mddi->rev_addr = dma_addr;
-	mddi->reg_write_data = dma + MDDI_REV_BUFFER_SIZE;
-	mddi->reg_write_addr = dma_addr + MDDI_REV_BUFFER_SIZE;
-	mddi->reg_read_data = mddi->reg_write_data + 1;
-	mddi->reg_read_addr = mddi->reg_write_addr +
-			      sizeof(*mddi->reg_write_data);
-	return 0;
-}
-
-static int mddi_probe(struct platform_device *pdev)
-{
-	struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
-	struct mddi_info *mddi = &mddi_info[pdev->id];
-	struct resource *resource;
-	int ret, i;
-
-	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!resource) {
-		printk(KERN_ERR "mddi: no associated mem resource!\n");
-		return -ENOMEM;
-	}
-	mddi->base = ioremap(resource->start, resource_size(resource));
-	if (!mddi->base) {
-		printk(KERN_ERR "mddi: failed to remap base!\n");
-		ret = -EINVAL;
-		goto error_ioremap;
-	}
-	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!resource) {
-		printk(KERN_ERR "mddi: no associated irq resource!\n");
-		ret = -EINVAL;
-		goto error_get_irq_resource;
-	}
-	mddi->irq = resource->start;
-	printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
-	       mddi->irq);
-	mddi->power_client = pdata->power_client;
-
-	mutex_init(&mddi->reg_write_lock);
-	mutex_init(&mddi->reg_read_lock);
-	spin_lock_init(&mddi->int_lock);
-	init_waitqueue_head(&mddi->int_wait);
-
-	ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate);
-	if (ret) {
-		printk(KERN_ERR "mddi: failed to setup clock!\n");
-		goto error_clk_setup;
-	}
-
-	ret = mddi_rev_data_setup(mddi);
-	if (ret) {
-		printk(KERN_ERR "mddi: failed to setup rev data!\n");
-		goto error_rev_data;
-	}
-
-	mddi->int_enable = 0;
-	mddi_writel(mddi->int_enable, INTEN);
-	ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
-			  &mddi->client_data);
-	if (ret) {
-		printk(KERN_ERR "mddi: failed to request enable irq!\n");
-		goto error_request_irq;
-	}
-
-	/* turn on the mddi client bridge chip */
-	if (mddi->power_client)
-		mddi->power_client(&mddi->client_data, 1);
-
-	/* initialize the mddi registers */
-	mddi_set_auto_hibernate(&mddi->client_data, 0);
-	mddi_writel(MDDI_CMD_RESET, CMD);
-	mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
-	mddi->version = mddi_init_registers(mddi);
-	if (mddi->version < 0x20) {
-		printk(KERN_ERR "mddi: unsupported version 0x%x\n",
-		       mddi->version);
-		ret = -ENODEV;
-		goto error_mddi_version;
-	}
-
-	/* read the capabilities off the client */
-	if (!mddi_get_client_caps(mddi)) {
-		printk(KERN_INFO "mddi: no client found\n");
-		/* power down the panel */
-		mddi_writel(MDDI_CMD_POWERDOWN, CMD);
-		printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
-		msleep(100);
-		printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
-		return 0;
-	}
-	mddi_set_auto_hibernate(&mddi->client_data, 1);
-
-	if (mddi->caps.Mfr_Name == 0 && mddi->caps.Product_Code == 0)
-		pdata->fixup(&mddi->caps.Mfr_Name, &mddi->caps.Product_Code);
-
-	mddi->client_pdev.id = 0;
-	for (i = 0; i < pdata->num_clients; i++) {
-		if (pdata->client_platform_data[i].product_id ==
-		    (mddi->caps.Mfr_Name << 16 | mddi->caps.Product_Code)) {
-			mddi->client_data.private_client_data =
-				pdata->client_platform_data[i].client_data;
-			mddi->client_pdev.name =
-				pdata->client_platform_data[i].name;
-			mddi->client_pdev.id =
-				pdata->client_platform_data[i].id;
-			/* XXX: possibly set clock */
-			break;
-		}
-	}
-
-	if (i >= pdata->num_clients)
-		mddi->client_pdev.name = "mddi_c_dummy";
-	printk(KERN_INFO "mddi: registering panel %s\n",
-		mddi->client_pdev.name);
-
-	mddi->client_data.suspend = mddi_suspend;
-	mddi->client_data.resume = mddi_resume;
-	mddi->client_data.activate_link = mddi_activate_link;
-	mddi->client_data.remote_write = mddi_remote_write;
-	mddi->client_data.remote_read = mddi_remote_read;
-	mddi->client_data.auto_hibernate = mddi_set_auto_hibernate;
-	mddi->client_data.fb_resource = pdata->fb_resource;
-	if (pdev->id == 0)
-		mddi->client_data.interface_type = MSM_MDDI_PMDH_INTERFACE;
-	else if (pdev->id == 1)
-		mddi->client_data.interface_type = MSM_MDDI_EMDH_INTERFACE;
-	else {
-		printk(KERN_ERR "mddi: can not determine interface %d!\n",
-		       pdev->id);
-		ret = -EINVAL;
-		goto error_mddi_interface;
-	}
-
-	mddi->client_pdev.dev.platform_data = &mddi->client_data;
-	printk(KERN_INFO "mddi: publish: %s\n", mddi->client_name);
-	platform_device_register(&mddi->client_pdev);
-	return 0;
-
-error_mddi_interface:
-error_mddi_version:
-	free_irq(mddi->irq, 0);
-error_request_irq:
-	dma_free_coherent(NULL, 0x1000, mddi->rev_data, mddi->rev_addr);
-error_rev_data:
-error_clk_setup:
-error_get_irq_resource:
-	iounmap(mddi->base);
-error_ioremap:
-
-	printk(KERN_INFO "mddi: mddi_init() failed (%d)\n", ret);
-	return ret;
-}
-
-
-static struct platform_driver mddi_driver = {
-	.probe = mddi_probe,
-	.driver = { .name = "msm_mddi" },
-};
-
-static int __init _mddi_init(void)
-{
-	return platform_driver_register(&mddi_driver);
-}
-
-module_init(_mddi_init);
diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/msm/mddi_client_dummy.c
deleted file mode 100644
index f1b0dfcc9717..000000000000
--- a/drivers/video/msm/mddi_client_dummy.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* drivers/video/msm_fb/mddi_client_dummy.c
- *
- * Support for "dummy" mddi client devices which require no
- * special initialization code.
- *
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <linux/platform_data/video-msm_fb.h>
-
-struct panel_info {
-	struct platform_device pdev;
-	struct msm_panel_data panel_data;
-};
-
-static int mddi_dummy_suspend(struct msm_panel_data *panel_data)
-{
-	return 0;
-}
-
-static int mddi_dummy_resume(struct msm_panel_data *panel_data)
-{
-	return 0;
-}
-
-static int mddi_dummy_blank(struct msm_panel_data *panel_data)
-{
-	return 0;
-}
-
-static int mddi_dummy_unblank(struct msm_panel_data *panel_data)
-{
-	return 0;
-}
-
-static int mddi_dummy_probe(struct platform_device *pdev)
-{
-	struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
-	struct panel_info *panel =
-		kzalloc(sizeof(struct panel_info), GFP_KERNEL);
-	int ret;
-	if (!panel)
-		return -ENOMEM;
-	platform_set_drvdata(pdev, panel);
-	panel->panel_data.suspend = mddi_dummy_suspend;
-	panel->panel_data.resume = mddi_dummy_resume;
-	panel->panel_data.blank = mddi_dummy_blank;
-	panel->panel_data.unblank = mddi_dummy_unblank;
-	panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
-	panel->pdev.name = "msm_panel";
-	panel->pdev.id = pdev->id;
-	platform_device_add_resources(&panel->pdev,
-				      client_data->fb_resource, 1);
-	panel->panel_data.fb_data = client_data->private_client_data;
-	panel->pdev.dev.platform_data = &panel->panel_data;
-	ret = platform_device_register(&panel->pdev);
-	if (ret) {
-		kfree(panel);
-		return ret;
-	}
-	return 0;
-}
-
-static int mddi_dummy_remove(struct platform_device *pdev)
-{
-	struct panel_info *panel = platform_get_drvdata(pdev);
-	kfree(panel);
-	return 0;
-}
-
-static struct platform_driver mddi_client_dummy = {
-	.probe = mddi_dummy_probe,
-	.remove = mddi_dummy_remove,
-	.driver = { .name = "mddi_c_dummy" },
-};
-
-static int __init mddi_client_dummy_init(void)
-{
-	platform_driver_register(&mddi_client_dummy);
-	return 0;
-}
-
-module_init(mddi_client_dummy_init);
-
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
deleted file mode 100644
index f96df32e5509..000000000000
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* drivers/video/msm_fb/mddi_client_nt35399.c
- *
- * Support for Novatek NT35399 MDDI client of Sapphire
- *
- * Copyright (C) 2008 HTC Incorporated
- * Author: Solomon Chiu (solomon_chiu@htc.com)
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/platform_data/video-msm_fb.h>
-
-static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
-
-struct panel_info {
-	struct msm_mddi_client_data *client_data;
-	struct platform_device pdev;
-	struct msm_panel_data panel_data;
-	struct msmfb_callback *fb_callback;
-	struct work_struct panel_work;
-	struct workqueue_struct *fb_wq;
-	int nt35399_got_int;
-};
-
-static void
-nt35399_request_vsync(struct msm_panel_data *panel_data,
-		      struct msmfb_callback *callback)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	panel->fb_callback = callback;
-	if (panel->nt35399_got_int) {
-		panel->nt35399_got_int = 0;
-		client_data->activate_link(client_data); /* clears interrupt */
-	}
-}
-
-static void nt35399_wait_vsync(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	if (panel->nt35399_got_int) {
-		panel->nt35399_got_int = 0;
-		client_data->activate_link(client_data); /* clears interrupt */
-	}
-
-	if (wait_event_timeout(nt35399_vsync_wait, panel->nt35399_got_int,
-				HZ/2) == 0)
-		printk(KERN_ERR "timeout waiting for VSYNC\n");
-
-	panel->nt35399_got_int = 0;
-	/* interrupt clears when screen dma starts */
-}
-
-static int nt35399_suspend(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-	int ret;
-
-	ret = bridge_data->uninit(bridge_data, client_data);
-	if (ret) {
-		printk(KERN_INFO "mddi nt35399 client: non zero return from "
-			"uninit\n");
-		return ret;
-	}
-	client_data->suspend(client_data);
-	return 0;
-}
-
-static int nt35399_resume(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-	int ret;
-
-	client_data->resume(client_data);
-	ret = bridge_data->init(bridge_data, client_data);
-	if (ret)
-		return ret;
-	return 0;
-}
-
-static int nt35399_blank(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-
-	return bridge_data->blank(bridge_data, client_data);
-}
-
-static int nt35399_unblank(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-
-	return bridge_data->unblank(bridge_data, client_data);
-}
-
-irqreturn_t nt35399_vsync_interrupt(int irq, void *data)
-{
-	struct panel_info *panel = data;
-
-	panel->nt35399_got_int = 1;
-
-	if (panel->fb_callback) {
-		panel->fb_callback->func(panel->fb_callback);
-		panel->fb_callback = NULL;
-	}
-
-	wake_up(&nt35399_vsync_wait);
-
-	return IRQ_HANDLED;
-}
-
-static int setup_vsync(struct panel_info *panel, int init)
-{
-	int ret;
-	int gpio = 97;
-	unsigned int irq;
-
-	if (!init) {
-		ret = 0;
-		goto uninit;
-	}
-	ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
-	if (ret)
-		goto err_request_gpio_failed;
-
-	ret = irq = gpio_to_irq(gpio);
-	if (ret < 0)
-		goto err_get_irq_num_failed;
-
-	ret = request_irq(irq, nt35399_vsync_interrupt, IRQF_TRIGGER_RISING,
-			  "vsync", panel);
-	if (ret)
-		goto err_request_irq_failed;
-
-	printk(KERN_INFO "vsync on gpio %d now %d\n",
-	       gpio, gpio_get_value(gpio));
-	return 0;
-
-uninit:
-	free_irq(gpio_to_irq(gpio), panel->client_data);
-err_request_irq_failed:
-err_get_irq_num_failed:
-	gpio_free(gpio);
-err_request_gpio_failed:
-	return ret;
-}
-
-static int mddi_nt35399_probe(struct platform_device *pdev)
-{
-	struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-
-	int ret;
-
-	struct panel_info *panel = devm_kzalloc(&pdev->dev,
-						sizeof(struct panel_info),
-						GFP_KERNEL);
-
-	printk(KERN_DEBUG "%s: enter.\n", __func__);
-
-	if (!panel)
-		return -ENOMEM;
-	platform_set_drvdata(pdev, panel);
-
-	ret = setup_vsync(panel, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "mddi_nt35399_setup_vsync failed\n");
-		return ret;
-	}
-
-	panel->client_data = client_data;
-	panel->panel_data.suspend = nt35399_suspend;
-	panel->panel_data.resume = nt35399_resume;
-	panel->panel_data.wait_vsync = nt35399_wait_vsync;
-	panel->panel_data.request_vsync = nt35399_request_vsync;
-	panel->panel_data.blank = nt35399_blank;
-	panel->panel_data.unblank = nt35399_unblank;
-	panel->panel_data.fb_data = &bridge_data->fb_data;
-	panel->panel_data.caps = 0;
-
-	panel->pdev.name = "msm_panel";
-	panel->pdev.id = pdev->id;
-	panel->pdev.resource = client_data->fb_resource;
-	panel->pdev.num_resources = 1;
-	panel->pdev.dev.platform_data = &panel->panel_data;
-
-	if (bridge_data->init)
-		bridge_data->init(bridge_data, client_data);
-
-	platform_device_register(&panel->pdev);
-
-	return 0;
-}
-
-static int mddi_nt35399_remove(struct platform_device *pdev)
-{
-	struct panel_info *panel = platform_get_drvdata(pdev);
-
-	setup_vsync(panel, 0);
-	return 0;
-}
-
-static struct platform_driver mddi_client_0bda_8a47 = {
-	.probe = mddi_nt35399_probe,
-	.remove = mddi_nt35399_remove,
-	.driver = { .name = "mddi_c_0bda_8a47" },
-};
-
-static int __init mddi_client_nt35399_init(void)
-{
-	return platform_driver_register(&mddi_client_0bda_8a47);
-}
-
-module_init(mddi_client_nt35399_init);
-
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
deleted file mode 100644
index 061d7dfebbf3..000000000000
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/* drivers/video/msm_fb/mddi_client_toshiba.c
- *
- * Support for Toshiba TC358720XBG mddi client devices which require no
- * special initialization code.
- *
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/platform_data/video-msm_fb.h>
-
-
-#define LCD_CONTROL_BLOCK_BASE 0x110000
-#define CMN         (LCD_CONTROL_BLOCK_BASE|0x10)
-#define INTFLG      (LCD_CONTROL_BLOCK_BASE|0x18)
-#define HCYCLE      (LCD_CONTROL_BLOCK_BASE|0x34)
-#define HDE_START   (LCD_CONTROL_BLOCK_BASE|0x3C)
-#define VPOS        (LCD_CONTROL_BLOCK_BASE|0xC0)
-#define MPLFBUF     (LCD_CONTROL_BLOCK_BASE|0x20)
-#define WAKEUP      (LCD_CONTROL_BLOCK_BASE|0x54)
-#define WSYN_DLY    (LCD_CONTROL_BLOCK_BASE|0x58)
-#define REGENB      (LCD_CONTROL_BLOCK_BASE|0x5C)
-
-#define BASE5 0x150000
-#define BASE6 0x160000
-#define BASE7 0x170000
-
-#define GPIOIEV     (BASE5 + 0x10)
-#define GPIOIE      (BASE5 + 0x14)
-#define GPIORIS     (BASE5 + 0x18)
-#define GPIOMIS     (BASE5 + 0x1C)
-#define GPIOIC      (BASE5 + 0x20)
-
-#define INTMASK     (BASE6 + 0x0C)
-#define INTMASK_VWAKEOUT (1U << 0)
-#define INTMASK_VWAKEOUT_ACTIVE_LOW (1U << 8)
-#define GPIOSEL     (BASE7 + 0x00)
-#define GPIOSEL_VWAKEINT (1U << 0)
-
-static DECLARE_WAIT_QUEUE_HEAD(toshiba_vsync_wait);
-
-struct panel_info {
-	struct msm_mddi_client_data *client_data;
-	struct platform_device pdev;
-	struct msm_panel_data panel_data;
-	struct msmfb_callback *toshiba_callback;
-	int toshiba_got_int;
-};
-
-
-static void toshiba_request_vsync(struct msm_panel_data *panel_data,
-				  struct msmfb_callback *callback)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	panel->toshiba_callback = callback;
-	if (panel->toshiba_got_int) {
-		panel->toshiba_got_int = 0;
-		client_data->activate_link(client_data);
-	}
-}
-
-static void toshiba_clear_vsync(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	client_data->activate_link(client_data);
-}
-
-static void toshiba_wait_vsync(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	if (panel->toshiba_got_int) {
-		panel->toshiba_got_int = 0;
-		client_data->activate_link(client_data); /* clears interrupt */
-	}
-	if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int,
-				HZ/2) == 0)
-		printk(KERN_ERR "timeout waiting for VSYNC\n");
-	panel->toshiba_got_int = 0;
-	/* interrupt clears when screen dma starts */
-}
-
-static int toshiba_suspend(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-	int ret;
-
-	ret = bridge_data->uninit(bridge_data, client_data);
-	if (ret) {
-		printk(KERN_INFO "mddi toshiba client: non zero return from "
-			"uninit\n");
-		return ret;
-	}
-	client_data->suspend(client_data);
-	return 0;
-}
-
-static int toshiba_resume(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-	int ret;
-
-	client_data->resume(client_data);
-	ret = bridge_data->init(bridge_data, client_data);
-	if (ret)
-		return ret;
-	return 0;
-}
-
-static int toshiba_blank(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-
-	return bridge_data->blank(bridge_data, client_data);
-}
-
-static int toshiba_unblank(struct msm_panel_data *panel_data)
-{
-	struct panel_info *panel = container_of(panel_data, struct panel_info,
-						panel_data);
-	struct msm_mddi_client_data *client_data = panel->client_data;
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-
-	return bridge_data->unblank(bridge_data, client_data);
-}
-
-irqreturn_t toshiba_vsync_interrupt(int irq, void *data)
-{
-	struct panel_info *panel = data;
-
-	panel->toshiba_got_int = 1;
-	if (panel->toshiba_callback) {
-		panel->toshiba_callback->func(panel->toshiba_callback);
-		panel->toshiba_callback = 0;
-	}
-	wake_up(&toshiba_vsync_wait);
-	return IRQ_HANDLED;
-}
-
-static int setup_vsync(struct panel_info *panel,
-		       int init)
-{
-	int ret;
-	int gpio = 97;
-	unsigned int irq;
-
-	if (!init) {
-		ret = 0;
-		goto uninit;
-	}
-	ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
-	if (ret)
-		goto err_request_gpio_failed;
-
-	ret = irq = gpio_to_irq(gpio);
-	if (ret < 0)
-		goto err_get_irq_num_failed;
-
-	ret = request_irq(irq, toshiba_vsync_interrupt, IRQF_TRIGGER_RISING,
-			  "vsync", panel);
-	if (ret)
-		goto err_request_irq_failed;
-	printk(KERN_INFO "vsync on gpio %d now %d\n",
-	       gpio, gpio_get_value(gpio));
-	return 0;
-
-uninit:
-	free_irq(gpio_to_irq(gpio), panel);
-err_request_irq_failed:
-err_get_irq_num_failed:
-	gpio_free(gpio);
-err_request_gpio_failed:
-	return ret;
-}
-
-static int mddi_toshiba_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
-	struct msm_mddi_bridge_platform_data *bridge_data =
-		client_data->private_client_data;
-	struct panel_info *panel =
-		kzalloc(sizeof(struct panel_info), GFP_KERNEL);
-	if (!panel)
-		return -ENOMEM;
-	platform_set_drvdata(pdev, panel);
-
-	/* mddi_remote_write(mddi, 0, WAKEUP); */
-	client_data->remote_write(client_data, GPIOSEL_VWAKEINT, GPIOSEL);
-	client_data->remote_write(client_data, INTMASK_VWAKEOUT, INTMASK);
-
-	ret = setup_vsync(panel, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
-		return ret;
-	}
-
-	panel->client_data = client_data;
-	panel->panel_data.suspend = toshiba_suspend;
-	panel->panel_data.resume = toshiba_resume;
-	panel->panel_data.wait_vsync = toshiba_wait_vsync;
-	panel->panel_data.request_vsync = toshiba_request_vsync;
-	panel->panel_data.clear_vsync = toshiba_clear_vsync;
-	panel->panel_data.blank = toshiba_blank;
-	panel->panel_data.unblank = toshiba_unblank;
-	panel->panel_data.fb_data =  &bridge_data->fb_data;
-	panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
-
-	panel->pdev.name = "msm_panel";
-	panel->pdev.id = pdev->id;
-	panel->pdev.resource = client_data->fb_resource;
-	panel->pdev.num_resources = 1;
-	panel->pdev.dev.platform_data = &panel->panel_data;
-	bridge_data->init(bridge_data, client_data);
-	platform_device_register(&panel->pdev);
-
-	return 0;
-}
-
-static int mddi_toshiba_remove(struct platform_device *pdev)
-{
-	struct panel_info *panel = platform_get_drvdata(pdev);
-
-	setup_vsync(panel, 0);
-	kfree(panel);
-	return 0;
-}
-
-static struct platform_driver mddi_client_d263_0000 = {
-	.probe = mddi_toshiba_probe,
-	.remove = mddi_toshiba_remove,
-	.driver = { .name = "mddi_c_d263_0000" },
-};
-
-static int __init mddi_client_toshiba_init(void)
-{
-	platform_driver_register(&mddi_client_d263_0000);
-	return 0;
-}
-
-module_init(mddi_client_toshiba_init);
-
diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/msm/mddi_hw.h
deleted file mode 100644
index 45cc01fc1e7f..000000000000
--- a/drivers/video/msm/mddi_hw.h
+++ /dev/null
@@ -1,305 +0,0 @@
-/* drivers/video/msm_fb/mddi_hw.h
- *
- * MSM MDDI Hardware Registers and Structures
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _MDDI_HW_H_
-#define _MDDI_HW_H_
-
-#include <linux/types.h>
-
-#define MDDI_CMD                0x0000
-#define MDDI_VERSION            0x0004
-#define MDDI_PRI_PTR            0x0008
-#define MDDI_SEC_PTR            0x000c
-#define MDDI_BPS                0x0010
-#define MDDI_SPM                0x0014
-#define MDDI_INT                0x0018
-#define MDDI_INTEN              0x001c
-#define MDDI_REV_PTR            0x0020
-#define MDDI_REV_SIZE           0x0024
-#define MDDI_STAT               0x0028
-#define MDDI_REV_RATE_DIV       0x002c
-#define MDDI_REV_CRC_ERR        0x0030
-#define MDDI_TA1_LEN            0x0034
-#define MDDI_TA2_LEN            0x0038
-#define MDDI_TEST_BUS           0x003c
-#define MDDI_TEST               0x0040
-#define MDDI_REV_PKT_CNT        0x0044
-#define MDDI_DRIVE_HI           0x0048
-#define MDDI_DRIVE_LO           0x004c
-#define MDDI_DISP_WAKE          0x0050
-#define MDDI_REV_ENCAP_SZ       0x0054
-#define MDDI_RTD_VAL            0x0058
-#define MDDI_PAD_CTL            0x0068
-#define MDDI_DRIVER_START_CNT   0x006c
-#define MDDI_NEXT_PRI_PTR       0x0070
-#define MDDI_NEXT_SEC_PTR       0x0074
-#define MDDI_MISR_CTL           0x0078
-#define MDDI_MISR_DATA          0x007c
-#define MDDI_SF_CNT             0x0080
-#define MDDI_MF_CNT             0x0084
-#define MDDI_CURR_REV_PTR       0x0088
-#define MDDI_CORE_VER           0x008c
-
-#define MDDI_INT_PRI_PTR_READ       0x0001
-#define MDDI_INT_SEC_PTR_READ       0x0002
-#define MDDI_INT_REV_DATA_AVAIL     0x0004
-#define MDDI_INT_DISP_REQ           0x0008
-#define MDDI_INT_PRI_UNDERFLOW      0x0010
-#define MDDI_INT_SEC_UNDERFLOW      0x0020
-#define MDDI_INT_REV_OVERFLOW       0x0040
-#define MDDI_INT_CRC_ERROR          0x0080
-#define MDDI_INT_MDDI_IN            0x0100
-#define MDDI_INT_PRI_OVERWRITE      0x0200
-#define MDDI_INT_SEC_OVERWRITE      0x0400
-#define MDDI_INT_REV_OVERWRITE      0x0800
-#define MDDI_INT_DMA_FAILURE        0x1000
-#define MDDI_INT_LINK_ACTIVE        0x2000
-#define MDDI_INT_IN_HIBERNATION     0x4000
-#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
-#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
-#define MDDI_INT_NO_CMD_PKTS_PEND   0x20000
-#define MDDI_INT_RTD_FAILURE        0x40000
-#define MDDI_INT_REV_PKT_RECEIVED   0x80000
-#define MDDI_INT_REV_PKTS_AVAIL     0x100000
-
-#define MDDI_INT_NEED_CLEAR ( \
-	MDDI_INT_REV_DATA_AVAIL | \
-	MDDI_INT_PRI_UNDERFLOW | \
-	MDDI_INT_SEC_UNDERFLOW | \
-	MDDI_INT_REV_OVERFLOW | \
-	MDDI_INT_CRC_ERROR | \
-	MDDI_INT_REV_PKT_RECEIVED)
-
-
-#define MDDI_STAT_LINK_ACTIVE        0x0001
-#define MDDI_STAT_NEW_REV_PTR        0x0002
-#define MDDI_STAT_NEW_PRI_PTR        0x0004
-#define MDDI_STAT_NEW_SEC_PTR        0x0008
-#define MDDI_STAT_IN_HIBERNATION     0x0010
-#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
-#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
-#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
-#define MDDI_STAT_PENDING_REV_ENCAP  0x0100
-#define MDDI_STAT_PENDING_POWERDOWN  0x0200
-#define MDDI_STAT_RTD_MEAS_FAIL      0x0800
-#define MDDI_STAT_CLIENT_WAKEUP_REQ  0x1000
-
-
-#define MDDI_CMD_POWERDOWN           0x0100
-#define MDDI_CMD_POWERUP             0x0200
-#define MDDI_CMD_HIBERNATE           0x0300
-#define MDDI_CMD_RESET               0x0400
-#define MDDI_CMD_DISP_IGNORE         0x0501
-#define MDDI_CMD_DISP_LISTEN         0x0500
-#define MDDI_CMD_SEND_REV_ENCAP      0x0600
-#define MDDI_CMD_GET_CLIENT_CAP      0x0601
-#define MDDI_CMD_GET_CLIENT_STATUS   0x0602
-#define MDDI_CMD_SEND_RTD            0x0700
-#define MDDI_CMD_LINK_ACTIVE         0x0900
-#define MDDI_CMD_PERIODIC_REV_ENCAP  0x0A00
-#define MDDI_CMD_FORCE_NEW_REV_PTR   0x0C00
-
-
-
-#define MDDI_VIDEO_REV_PKT_SIZE              0x40
-#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE  0x60
-#define MDDI_MAX_REV_PKT_SIZE                0x60
-
-/* #define MDDI_REV_BUFFER_SIZE 128 */
-#define MDDI_REV_BUFFER_SIZE (MDDI_MAX_REV_PKT_SIZE * 4)
-
-/* MDP sends 256 pixel packets, so lower value hibernates more without
- * significantly increasing latency of waiting for next subframe */
-#define MDDI_HOST_BYTES_PER_SUBFRAME  0x3C00
-#define MDDI_HOST_TA2_LEN       0x000c
-#define MDDI_HOST_REV_RATE_DIV  0x0002
-
-
-struct __attribute__((packed)) mddi_rev_packet {
-	uint16_t length;
-	uint16_t type;
-	uint16_t client_id;
-};
-
-struct __attribute__((packed)) mddi_client_status {
-	uint16_t length;
-	uint16_t type;
-	uint16_t client_id;
-	uint16_t reverse_link_request;  /* bytes needed in rev encap message */
-	uint8_t  crc_error_count;
-	uint8_t  capability_change;
-	uint16_t graphics_busy_flags;
-	uint16_t crc16;
-};
-
-struct __attribute__((packed)) mddi_client_caps {
-	uint16_t length; /* length, exclusive of this field */
-	uint16_t type; /* 66 */
-	uint16_t client_id;
-
-	uint16_t Protocol_Version;
-	uint16_t Minimum_Protocol_Version;
-	uint16_t Data_Rate_Capability;
-	uint8_t  Interface_Type_Capability;
-	uint8_t  Number_of_Alt_Displays;
-	uint16_t PostCal_Data_Rate;
-	uint16_t Bitmap_Width;
-	uint16_t Bitmap_Height;
-	uint16_t Display_Window_Width;
-	uint16_t Display_Window_Height;
-	uint32_t Color_Map_Size;
-	uint16_t Color_Map_RGB_Width;
-	uint16_t RGB_Capability;
-	uint8_t  Monochrome_Capability;
-	uint8_t  Reserved_1;
-	uint16_t Y_Cb_Cr_Capability;
-	uint16_t Bayer_Capability;
-	uint16_t Alpha_Cursor_Image_Planes;
-	uint32_t Client_Feature_Capability_Indicators;
-	uint8_t  Maximum_Video_Frame_Rate_Capability;
-	uint8_t  Minimum_Video_Frame_Rate_Capability;
-	uint16_t Minimum_Sub_frame_Rate;
-	uint16_t Audio_Buffer_Depth;
-	uint16_t Audio_Channel_Capability;
-	uint16_t Audio_Sample_Rate_Capability;
-	uint8_t  Audio_Sample_Resolution;
-	uint8_t  Mic_Audio_Sample_Resolution;
-	uint16_t Mic_Sample_Rate_Capability;
-	uint8_t  Keyboard_Data_Format;
-	uint8_t  pointing_device_data_format;
-	uint16_t content_protection_type;
-	uint16_t Mfr_Name;
-	uint16_t Product_Code;
-	uint16_t Reserved_3;
-	uint32_t Serial_Number;
-	uint8_t  Week_of_Manufacture;
-	uint8_t  Year_of_Manufacture;
-
-	uint16_t crc16;
-} mddi_client_capability_type;
-
-
-struct __attribute__((packed)) mddi_video_stream {
-	uint16_t length;
-	uint16_t type; /* 16 */
-	uint16_t client_id; /* 0 */
-
-	uint16_t video_data_format_descriptor;
-/* format of each pixel in the Pixel Data in the present stream in the
- * present packet.
- * If bits [15:13] = 000 monochrome
- * If bits [15:13] = 001 color pixels (palette).
- * If bits [15:13] = 010 color pixels in raw RGB
- * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
- * If bits [15:13] = 100 Bayer pixels
- */
-
-	uint16_t pixel_data_attributes;
-/* interpreted as follows:
- * Bits [1:0] = 11  pixel data is displayed to both eyes
- * Bits [1:0] = 10  pixel data is routed to the left eye only.
- * Bits [1:0] = 01  pixel data is routed to the right eye only.
- * Bits [1:0] = 00  pixel data is routed to the alternate display.
- * Bit 2 is 0  Pixel Data is in the standard progressive format.
- * Bit 2 is 1  Pixel Data is in interlace format.
- * Bit 3 is 0  Pixel Data is in the standard progressive format.
- * Bit 3 is 1  Pixel Data is in alternate pixel format.
- * Bit 4 is 0  Pixel Data is to or from the display frame buffer.
- * Bit 4 is 1  Pixel Data is to or from the camera.
- * Bit 5 is 0  pixel data contains the next consecutive row of pixels.
- * Bit 5 is 1  X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
- *             X Start, and Y Start parameters are not defined and
- *             shall be ignored by the client.
- * Bits [7:6] = 01  Pixel data is written to the offline image buffer.
- * Bits [7:6] = 00  Pixel data is written to the buffer to refresh display.
- * Bits [7:6] = 11  Pixel data is written to all image buffers.
- * Bits [7:6] = 10  Invalid. Reserved for future use.
- * Bits 8 through 11 alternate display number.
- * Bits 12 through 14 are reserved for future use and shall be set to zero.
- * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
- */
-
-	uint16_t x_left_edge;
-	uint16_t y_top_edge;
-	/* X,Y coordinate of the top left edge of the screen window */
-
-	uint16_t x_right_edge;
-	uint16_t y_bottom_edge;
-	/* X,Y coordinate of the bottom right edge of the window being
-	 * updated. */
-
-	uint16_t x_start;
-	uint16_t y_start;
-	/* (X Start, Y Start) is the first pixel in the Pixel Data field
-	 * below. */
-
-	uint16_t pixel_count;
-	/* number of pixels in the Pixel Data field below. */
-
-	uint16_t parameter_CRC;
-	/* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
-
-	uint16_t reserved;
-	/* 16-bit variable to make structure align on 4 byte boundary */
-};
-
-#define TYPE_VIDEO_STREAM      16
-#define TYPE_CLIENT_CAPS       66
-#define TYPE_REGISTER_ACCESS   146
-#define TYPE_CLIENT_STATUS     70
-
-struct __attribute__((packed)) mddi_register_access {
-	uint16_t length;
-	uint16_t type; /* 146 */
-	uint16_t client_id;
-
-	uint16_t read_write_info;
-	/* Bits 13:0  a 14-bit unsigned integer that specifies the number of
-	 *            32-bit Register Data List items to be transferred in the
-	 *            Register Data List field.
-	 * Bits[15:14] = 00  Write to register(s);
-	 * Bits[15:14] = 10  Read from register(s);
-	 * Bits[15:14] = 11  Response to a Read.
-	 * Bits[15:14] = 01  this value is reserved for future use. */
-#define MDDI_WRITE     (0 << 14)
-#define MDDI_READ      (2 << 14)
-#define MDDI_READ_RESP (3 << 14)
-
-	uint32_t register_address;
-	/* the register address that is to be written to or read from. */
-
-	uint16_t crc16;
-
-	uint32_t register_data_list;
-	/* list of 4-byte register data values for/from client registers */
-};
-
-struct __attribute__((packed)) mddi_llentry {
-	uint16_t flags;
-	uint16_t header_count;
-	uint16_t data_count;
-	dma_addr_t data; /* 32 bit */
-	struct mddi_llentry *next;
-	uint16_t reserved;
-	union {
-		struct mddi_video_stream v;
-		struct mddi_register_access r;
-		uint32_t _[12];
-	} u;
-};
-
-#endif
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
deleted file mode 100644
index 113c7876c855..000000000000
--- a/drivers/video/msm/mdp.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* drivers/video/msm_fb/mdp.c
- *
- * MSM MDP Interface (used by framebuffer core)
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/msm_mdp.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/clk.h>
-#include <linux/file.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-
-#include <linux/platform_data/video-msm_fb.h>
-#include <linux/platform_device.h>
-#include <linux/export.h>
-
-#include "mdp_hw.h"
-
-struct class *mdp_class;
-
-#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
-
-static uint16_t mdp_default_ccs[] = {
-	0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
-	0x010, 0x080, 0x080
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
-static struct msmfb_callback *dma_callback;
-static struct clk *clk;
-static unsigned int mdp_irq_mask;
-static DEFINE_SPINLOCK(mdp_lock);
-DEFINE_MUTEX(mdp_mutex);
-
-static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
-{
-	unsigned long irq_flags;
-	int ret = 0;
-
-	BUG_ON(!mask);
-
-	spin_lock_irqsave(&mdp_lock, irq_flags);
-	/* if the mask bits are already set return an error, this interrupt
-	 * is already enabled */
-	if (mdp_irq_mask & mask) {
-		printk(KERN_ERR "mdp irq already on already on %x %x\n",
-		       mdp_irq_mask, mask);
-		ret = -1;
-	}
-	/* if the mdp irq is not already enabled enable it */
-	if (!mdp_irq_mask) {
-		if (clk)
-			clk_enable(clk);
-		enable_irq(mdp->irq);
-	}
-
-	/* update the irq mask to reflect the fact that the interrupt is
-	 * enabled */
-	mdp_irq_mask |= mask;
-	spin_unlock_irqrestore(&mdp_lock, irq_flags);
-	return ret;
-}
-
-static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
-{
-	/* this interrupt is already disabled! */
-	if (!(mdp_irq_mask & mask)) {
-		printk(KERN_ERR "mdp irq already off %x %x\n",
-		       mdp_irq_mask, mask);
-		return -1;
-	}
-	/* update the irq mask to reflect the fact that the interrupt is
-	 * disabled */
-	mdp_irq_mask &= ~(mask);
-	/* if no one is waiting on the interrupt, disable it */
-	if (!mdp_irq_mask) {
-		disable_irq_nosync(mdp->irq);
-		if (clk)
-			clk_disable(clk);
-	}
-	return 0;
-}
-
-static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
-{
-	unsigned long irq_flags;
-	int ret;
-
-	spin_lock_irqsave(&mdp_lock, irq_flags);
-	ret = locked_disable_mdp_irq(mdp, mask);
-	spin_unlock_irqrestore(&mdp_lock, irq_flags);
-	return ret;
-}
-
-static irqreturn_t mdp_isr(int irq, void *data)
-{
-	uint32_t status;
-	unsigned long irq_flags;
-	struct mdp_info *mdp = data;
-
-	spin_lock_irqsave(&mdp_lock, irq_flags);
-
-	status = mdp_readl(mdp, MDP_INTR_STATUS);
-	mdp_writel(mdp, status, MDP_INTR_CLEAR);
-
-	status &= mdp_irq_mask;
-	if (status & DL0_DMA2_TERM_DONE) {
-		if (dma_callback) {
-			dma_callback->func(dma_callback);
-			dma_callback = NULL;
-		}
-		wake_up(&mdp_dma2_waitqueue);
-	}
-
-	if (status & DL0_ROI_DONE)
-		wake_up(&mdp_ppp_waitqueue);
-
-	if (status)
-		locked_disable_mdp_irq(mdp, status);
-
-	spin_unlock_irqrestore(&mdp_lock, irq_flags);
-	return IRQ_HANDLED;
-}
-
-static uint32_t mdp_check_mask(uint32_t mask)
-{
-	uint32_t ret;
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&mdp_lock, irq_flags);
-	ret = mdp_irq_mask & mask;
-	spin_unlock_irqrestore(&mdp_lock, irq_flags);
-	return ret;
-}
-
-static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
-{
-	int ret = 0;
-	unsigned long irq_flags;
-
-	wait_event_timeout(*wq, !mdp_check_mask(mask), HZ);
-
-	spin_lock_irqsave(&mdp_lock, irq_flags);
-	if (mdp_irq_mask & mask) {
-		locked_disable_mdp_irq(mdp, mask);
-		printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
-		       mask);
-		ret = -ETIMEDOUT;
-	}
-	spin_unlock_irqrestore(&mdp_lock, irq_flags);
-
-	return ret;
-}
-
-void mdp_dma_wait(struct mdp_device *mdp_dev)
-{
-#define MDP_MAX_TIMEOUTS 20
-	static int timeout_count;
-	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-
-	if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT)
-		timeout_count++;
-	else
-		timeout_count = 0;
-
-	if (timeout_count > MDP_MAX_TIMEOUTS) {
-		printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n",
-		       MDP_MAX_TIMEOUTS);
-		BUG();
-	}
-}
-
-static int mdp_ppp_wait(struct mdp_info *mdp)
-{
-	return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
-}
-
-void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
-		     uint32_t width, uint32_t height, uint32_t x, uint32_t y,
-		     struct msmfb_callback *callback)
-{
-	uint32_t dma2_cfg;
-	uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
-
-	if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) {
-		printk(KERN_ERR "mdp_dma_to_mddi: busy\n");
-		return;
-	}
-
-	dma_callback = callback;
-
-	dma2_cfg = DMA_PACK_TIGHT |
-		DMA_PACK_ALIGN_LSB |
-		DMA_PACK_PATTERN_RGB |
-		DMA_OUT_SEL_AHB |
-		DMA_IBUF_NONCONTIGUOUS;
-
-	dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
-
-	dma2_cfg |= DMA_OUT_SEL_MDDI;
-
-	dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
-
-	dma2_cfg |= DMA_DITHER_EN;
-
-	/* setup size, address, and stride */
-	mdp_writel(mdp, (height << 16) | (width),
-		   MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
-	mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
-	mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
-
-	/* 666 18BPP */
-	dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
-
-	/* set y & x offset and MDDI transaction parameters */
-	mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
-	mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
-	mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
-		   MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
-
-	mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
-
-	/* start DMA2 */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
-}
-
-void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
-	     uint32_t width, uint32_t height, uint32_t x, uint32_t y,
-	     struct msmfb_callback *callback, int interface)
-{
-	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-
-	if (interface == MSM_MDDI_PMDH_INTERFACE) {
-		mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y,
-				callback);
-	}
-}
-
-int get_img(struct mdp_img *img, struct fb_info *info,
-	    unsigned long *start, unsigned long *len,
-	    struct file **filep)
-{
-	int ret = 0;
-	struct fd f = fdget(img->memory_id);
-	if (f.file == NULL)
-		return -1;
-
-	if (MAJOR(file_inode(f.file)->i_rdev) == FB_MAJOR) {
-		*start = info->fix.smem_start;
-		*len = info->fix.smem_len;
-	} else
-		ret = -1;
-	fdput(f);
-
-	return ret;
-}
-
-void put_img(struct file *src_file, struct file *dst_file)
-{
-}
-
-int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
-	     struct mdp_blit_req *req)
-{
-	int ret;
-	unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
-	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-	struct file *src_file = 0, *dst_file = 0;
-
-	/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
-	if (unlikely(req->src_rect.h == 0 ||
-		     req->src_rect.w == 0)) {
-		printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
-		return -EINVAL;
-	}
-	if (unlikely(req->dst_rect.h == 0 ||
-		     req->dst_rect.w == 0))
-		return -EINVAL;
-
-	/* do this first so that if this fails, the caller can always
-	 * safely call put_img */
-	if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
-		printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
-				"memory\n");
-		return -EINVAL;
-	}
-
-	if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
-		printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
-				"memory\n");
-		return -EINVAL;
-	}
-	mutex_lock(&mdp_mutex);
-
-	/* transp_masking unimplemented */
-	req->transp_mask = MDP_TRANSP_NOP;
-	if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
-		      req->alpha != MDP_ALPHA_NOP ||
-		      HAS_ALPHA(req->src.format)) &&
-		     (req->flags & MDP_ROT_90 &&
-		      req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
-		int i;
-		unsigned int tiles = req->dst_rect.h / 16;
-		unsigned int remainder = req->dst_rect.h % 16;
-		req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
-		req->dst_rect.h = 16;
-		for (i = 0; i < tiles; i++) {
-			enable_mdp_irq(mdp, DL0_ROI_DONE);
-			ret = mdp_ppp_blit(mdp, req, src_file, src_start,
-					   src_len, dst_file, dst_start,
-					   dst_len);
-			if (ret)
-				goto err_bad_blit;
-			ret = mdp_ppp_wait(mdp);
-			if (ret)
-				goto err_wait_failed;
-			req->dst_rect.y += 16;
-			req->src_rect.x += req->src_rect.w;
-		}
-		if (!remainder)
-			goto end;
-		req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
-		req->dst_rect.h = remainder;
-	}
-	enable_mdp_irq(mdp, DL0_ROI_DONE);
-	ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
-			   dst_start,
-			   dst_len);
-	if (ret)
-		goto err_bad_blit;
-	ret = mdp_ppp_wait(mdp);
-	if (ret)
-		goto err_wait_failed;
-end:
-	put_img(src_file, dst_file);
-	mutex_unlock(&mdp_mutex);
-	return 0;
-err_bad_blit:
-	disable_mdp_irq(mdp, DL0_ROI_DONE);
-err_wait_failed:
-	put_img(src_file, dst_file);
-	mutex_unlock(&mdp_mutex);
-	return ret;
-}
-
-void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
-{
-	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
-
-	disp_id &= 0xf;
-	mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43);
-}
-
-int register_mdp_client(struct class_interface *cint)
-{
-	if (!mdp_class) {
-		pr_err("mdp: no mdp_class when registering mdp client\n");
-		return -ENODEV;
-	}
-	cint->class = mdp_class;
-	return class_interface_register(cint);
-}
-
-#include "mdp_csc_table.h"
-#include "mdp_scale_tables.h"
-
-int mdp_probe(struct platform_device *pdev)
-{
-	struct resource *resource;
-	int ret;
-	int n;
-	struct mdp_info *mdp;
-
-	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!resource) {
-		pr_err("mdp: can not get mdp mem resource!\n");
-		return -ENOMEM;
-	}
-
-	mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
-	if (!mdp)
-		return -ENOMEM;
-
-	mdp->irq = platform_get_irq(pdev, 0);
-	if (mdp->irq < 0) {
-		pr_err("mdp: can not get mdp irq\n");
-		ret = mdp->irq;
-		goto error_get_irq;
-	}
-
-	mdp->base = ioremap(resource->start, resource_size(resource));
-	if (mdp->base == 0) {
-		printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
-		ret = -ENOMEM;
-		goto error_ioremap;
-	}
-
-	mdp->mdp_dev.dma = mdp_dma;
-	mdp->mdp_dev.dma_wait = mdp_dma_wait;
-	mdp->mdp_dev.blit = mdp_blit;
-	mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
-
-	clk = clk_get(&pdev->dev, "mdp_clk");
-	if (IS_ERR(clk)) {
-		printk(KERN_INFO "mdp: failed to get mdp clk");
-		ret = PTR_ERR(clk);
-		goto error_get_clk;
-	}
-
-	ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
-	if (ret)
-		goto error_request_irq;
-	disable_irq(mdp->irq);
-	mdp_irq_mask = 0;
-
-	/* debug interface write access */
-	mdp_writel(mdp, 1, 0x60);
-
-	mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
-	mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
-
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
-
-	for (n = 0; n < ARRAY_SIZE(csc_table); n++)
-		mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
-
-	/* clear up unused fg/main registers */
-	/* comp.plane 2&3 ystride */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
-
-	/* unpacked pattern */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
-
-	/* comp.plane 2 & 3 */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
-
-	/* clear unused bg registers */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
-
-	for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
-		mdp_writel(mdp, mdp_upscale_table[n].val,
-		       mdp_upscale_table[n].reg);
-
-	for (n = 0; n < 9; n++)
-		mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
-	mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
-	mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
-	mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
-
-	/* register mdp device */
-	mdp->mdp_dev.dev.parent = &pdev->dev;
-	mdp->mdp_dev.dev.class = mdp_class;
-	dev_set_name(&mdp->mdp_dev.dev, "mdp%d", pdev->id);
-
-	/* if you can remove the platform device you'd have to implement
-	 * this:
-	mdp_dev.release = mdp_class; */
-
-	ret = device_register(&mdp->mdp_dev.dev);
-	if (ret)
-		goto error_device_register;
-	return 0;
-
-error_device_register:
-	free_irq(mdp->irq, mdp);
-error_request_irq:
-error_get_clk:
-	iounmap(mdp->base);
-error_get_irq:
-error_ioremap:
-	kfree(mdp);
-	return ret;
-}
-
-static struct platform_driver msm_mdp_driver = {
-	.probe = mdp_probe,
-	.driver = {.name = "msm_mdp"},
-};
-
-static int __init mdp_init(void)
-{
-	mdp_class = class_create(THIS_MODULE, "msm_mdp");
-	if (IS_ERR(mdp_class)) {
-		printk(KERN_ERR "Error creating mdp class\n");
-		return PTR_ERR(mdp_class);
-	}
-	return platform_driver_register(&msm_mdp_driver);
-}
-
-subsys_initcall(mdp_init);
diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h
deleted file mode 100644
index d1cde30ead52..000000000000
--- a/drivers/video/msm/mdp_csc_table.h
+++ /dev/null
@@ -1,582 +0,0 @@
-/* drivers/video/msm_fb/mdp_csc_table.h
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-static struct {
-	uint32_t reg;
-	uint32_t val;
-} csc_table[] = {
-	{ 0x40400, 0x83 },
-	{ 0x40404, 0x102 },
-	{ 0x40408, 0x32 },
-	{ 0x4040c, 0xffffffb5 },
-	{ 0x40410, 0xffffff6c },
-	{ 0x40414, 0xe1 },
-	{ 0x40418, 0xe1 },
-	{ 0x4041c, 0xffffff45 },
-	{ 0x40420, 0xffffffdc },
-	{ 0x40440, 0x254 },
-	{ 0x40444, 0x0 },
-	{ 0x40448, 0x331 },
-	{ 0x4044c, 0x254 },
-	{ 0x40450, 0xffffff38 },
-	{ 0x40454, 0xfffffe61 },
-	{ 0x40458, 0x254 },
-	{ 0x4045c, 0x409 },
-	{ 0x40460, 0x0 },
-	{ 0x40480, 0x5d },
-	{ 0x40484, 0x13a },
-	{ 0x40488, 0x20 },
-	{ 0x4048c, 0xffffffcd },
-	{ 0x40490, 0xffffff54 },
-	{ 0x40494, 0xe1 },
-	{ 0x40498, 0xe1 },
-	{ 0x4049c, 0xffffff35 },
-	{ 0x404a0, 0xffffffec },
-	{ 0x404c0, 0x254 },
-	{ 0x404c4, 0x0 },
-	{ 0x404c8, 0x396 },
-	{ 0x404cc, 0x254 },
-	{ 0x404d0, 0xffffff94 },
-	{ 0x404d4, 0xfffffef0 },
-	{ 0x404d8, 0x254 },
-	{ 0x404dc, 0x43a },
-	{ 0x404e0, 0x0 },
-	{ 0x40500, 0x10 },
-	{ 0x40504, 0x80 },
-	{ 0x40508, 0x80 },
-	{ 0x40540, 0x10 },
-	{ 0x40544, 0x80 },
-	{ 0x40548, 0x80 },
-	{ 0x40580, 0x10 },
-	{ 0x40584, 0xeb },
-	{ 0x40588, 0x10 },
-	{ 0x4058c, 0xf0 },
-	{ 0x405c0, 0x10 },
-	{ 0x405c4, 0xeb },
-	{ 0x405c8, 0x10 },
-	{ 0x405cc, 0xf0 },
-	{ 0x40800, 0x0 },
-	{ 0x40804, 0x151515 },
-	{ 0x40808, 0x1d1d1d },
-	{ 0x4080c, 0x232323 },
-	{ 0x40810, 0x272727 },
-	{ 0x40814, 0x2b2b2b },
-	{ 0x40818, 0x2f2f2f },
-	{ 0x4081c, 0x333333 },
-	{ 0x40820, 0x363636 },
-	{ 0x40824, 0x393939 },
-	{ 0x40828, 0x3b3b3b },
-	{ 0x4082c, 0x3e3e3e },
-	{ 0x40830, 0x404040 },
-	{ 0x40834, 0x434343 },
-	{ 0x40838, 0x454545 },
-	{ 0x4083c, 0x474747 },
-	{ 0x40840, 0x494949 },
-	{ 0x40844, 0x4b4b4b },
-	{ 0x40848, 0x4d4d4d },
-	{ 0x4084c, 0x4f4f4f },
-	{ 0x40850, 0x515151 },
-	{ 0x40854, 0x535353 },
-	{ 0x40858, 0x555555 },
-	{ 0x4085c, 0x565656 },
-	{ 0x40860, 0x585858 },
-	{ 0x40864, 0x5a5a5a },
-	{ 0x40868, 0x5b5b5b },
-	{ 0x4086c, 0x5d5d5d },
-	{ 0x40870, 0x5e5e5e },
-	{ 0x40874, 0x606060 },
-	{ 0x40878, 0x616161 },
-	{ 0x4087c, 0x636363 },
-	{ 0x40880, 0x646464 },
-	{ 0x40884, 0x666666 },
-	{ 0x40888, 0x676767 },
-	{ 0x4088c, 0x686868 },
-	{ 0x40890, 0x6a6a6a },
-	{ 0x40894, 0x6b6b6b },
-	{ 0x40898, 0x6c6c6c },
-	{ 0x4089c, 0x6e6e6e },
-	{ 0x408a0, 0x6f6f6f },
-	{ 0x408a4, 0x707070 },
-	{ 0x408a8, 0x717171 },
-	{ 0x408ac, 0x727272 },
-	{ 0x408b0, 0x747474 },
-	{ 0x408b4, 0x757575 },
-	{ 0x408b8, 0x767676 },
-	{ 0x408bc, 0x777777 },
-	{ 0x408c0, 0x787878 },
-	{ 0x408c4, 0x797979 },
-	{ 0x408c8, 0x7a7a7a },
-	{ 0x408cc, 0x7c7c7c },
-	{ 0x408d0, 0x7d7d7d },
-	{ 0x408d4, 0x7e7e7e },
-	{ 0x408d8, 0x7f7f7f },
-	{ 0x408dc, 0x808080 },
-	{ 0x408e0, 0x818181 },
-	{ 0x408e4, 0x828282 },
-	{ 0x408e8, 0x838383 },
-	{ 0x408ec, 0x848484 },
-	{ 0x408f0, 0x858585 },
-	{ 0x408f4, 0x868686 },
-	{ 0x408f8, 0x878787 },
-	{ 0x408fc, 0x888888 },
-	{ 0x40900, 0x898989 },
-	{ 0x40904, 0x8a8a8a },
-	{ 0x40908, 0x8b8b8b },
-	{ 0x4090c, 0x8c8c8c },
-	{ 0x40910, 0x8d8d8d },
-	{ 0x40914, 0x8e8e8e },
-	{ 0x40918, 0x8f8f8f },
-	{ 0x4091c, 0x8f8f8f },
-	{ 0x40920, 0x909090 },
-	{ 0x40924, 0x919191 },
-	{ 0x40928, 0x929292 },
-	{ 0x4092c, 0x939393 },
-	{ 0x40930, 0x949494 },
-	{ 0x40934, 0x959595 },
-	{ 0x40938, 0x969696 },
-	{ 0x4093c, 0x969696 },
-	{ 0x40940, 0x979797 },
-	{ 0x40944, 0x989898 },
-	{ 0x40948, 0x999999 },
-	{ 0x4094c, 0x9a9a9a },
-	{ 0x40950, 0x9b9b9b },
-	{ 0x40954, 0x9c9c9c },
-	{ 0x40958, 0x9c9c9c },
-	{ 0x4095c, 0x9d9d9d },
-	{ 0x40960, 0x9e9e9e },
-	{ 0x40964, 0x9f9f9f },
-	{ 0x40968, 0xa0a0a0 },
-	{ 0x4096c, 0xa0a0a0 },
-	{ 0x40970, 0xa1a1a1 },
-	{ 0x40974, 0xa2a2a2 },
-	{ 0x40978, 0xa3a3a3 },
-	{ 0x4097c, 0xa4a4a4 },
-	{ 0x40980, 0xa4a4a4 },
-	{ 0x40984, 0xa5a5a5 },
-	{ 0x40988, 0xa6a6a6 },
-	{ 0x4098c, 0xa7a7a7 },
-	{ 0x40990, 0xa7a7a7 },
-	{ 0x40994, 0xa8a8a8 },
-	{ 0x40998, 0xa9a9a9 },
-	{ 0x4099c, 0xaaaaaa },
-	{ 0x409a0, 0xaaaaaa },
-	{ 0x409a4, 0xababab },
-	{ 0x409a8, 0xacacac },
-	{ 0x409ac, 0xadadad },
-	{ 0x409b0, 0xadadad },
-	{ 0x409b4, 0xaeaeae },
-	{ 0x409b8, 0xafafaf },
-	{ 0x409bc, 0xafafaf },
-	{ 0x409c0, 0xb0b0b0 },
-	{ 0x409c4, 0xb1b1b1 },
-	{ 0x409c8, 0xb2b2b2 },
-	{ 0x409cc, 0xb2b2b2 },
-	{ 0x409d0, 0xb3b3b3 },
-	{ 0x409d4, 0xb4b4b4 },
-	{ 0x409d8, 0xb4b4b4 },
-	{ 0x409dc, 0xb5b5b5 },
-	{ 0x409e0, 0xb6b6b6 },
-	{ 0x409e4, 0xb6b6b6 },
-	{ 0x409e8, 0xb7b7b7 },
-	{ 0x409ec, 0xb8b8b8 },
-	{ 0x409f0, 0xb8b8b8 },
-	{ 0x409f4, 0xb9b9b9 },
-	{ 0x409f8, 0xbababa },
-	{ 0x409fc, 0xbababa },
-	{ 0x40a00, 0xbbbbbb },
-	{ 0x40a04, 0xbcbcbc },
-	{ 0x40a08, 0xbcbcbc },
-	{ 0x40a0c, 0xbdbdbd },
-	{ 0x40a10, 0xbebebe },
-	{ 0x40a14, 0xbebebe },
-	{ 0x40a18, 0xbfbfbf },
-	{ 0x40a1c, 0xc0c0c0 },
-	{ 0x40a20, 0xc0c0c0 },
-	{ 0x40a24, 0xc1c1c1 },
-	{ 0x40a28, 0xc1c1c1 },
-	{ 0x40a2c, 0xc2c2c2 },
-	{ 0x40a30, 0xc3c3c3 },
-	{ 0x40a34, 0xc3c3c3 },
-	{ 0x40a38, 0xc4c4c4 },
-	{ 0x40a3c, 0xc5c5c5 },
-	{ 0x40a40, 0xc5c5c5 },
-	{ 0x40a44, 0xc6c6c6 },
-	{ 0x40a48, 0xc6c6c6 },
-	{ 0x40a4c, 0xc7c7c7 },
-	{ 0x40a50, 0xc8c8c8 },
-	{ 0x40a54, 0xc8c8c8 },
-	{ 0x40a58, 0xc9c9c9 },
-	{ 0x40a5c, 0xc9c9c9 },
-	{ 0x40a60, 0xcacaca },
-	{ 0x40a64, 0xcbcbcb },
-	{ 0x40a68, 0xcbcbcb },
-	{ 0x40a6c, 0xcccccc },
-	{ 0x40a70, 0xcccccc },
-	{ 0x40a74, 0xcdcdcd },
-	{ 0x40a78, 0xcecece },
-	{ 0x40a7c, 0xcecece },
-	{ 0x40a80, 0xcfcfcf },
-	{ 0x40a84, 0xcfcfcf },
-	{ 0x40a88, 0xd0d0d0 },
-	{ 0x40a8c, 0xd0d0d0 },
-	{ 0x40a90, 0xd1d1d1 },
-	{ 0x40a94, 0xd2d2d2 },
-	{ 0x40a98, 0xd2d2d2 },
-	{ 0x40a9c, 0xd3d3d3 },
-	{ 0x40aa0, 0xd3d3d3 },
-	{ 0x40aa4, 0xd4d4d4 },
-	{ 0x40aa8, 0xd4d4d4 },
-	{ 0x40aac, 0xd5d5d5 },
-	{ 0x40ab0, 0xd6d6d6 },
-	{ 0x40ab4, 0xd6d6d6 },
-	{ 0x40ab8, 0xd7d7d7 },
-	{ 0x40abc, 0xd7d7d7 },
-	{ 0x40ac0, 0xd8d8d8 },
-	{ 0x40ac4, 0xd8d8d8 },
-	{ 0x40ac8, 0xd9d9d9 },
-	{ 0x40acc, 0xd9d9d9 },
-	{ 0x40ad0, 0xdadada },
-	{ 0x40ad4, 0xdbdbdb },
-	{ 0x40ad8, 0xdbdbdb },
-	{ 0x40adc, 0xdcdcdc },
-	{ 0x40ae0, 0xdcdcdc },
-	{ 0x40ae4, 0xdddddd },
-	{ 0x40ae8, 0xdddddd },
-	{ 0x40aec, 0xdedede },
-	{ 0x40af0, 0xdedede },
-	{ 0x40af4, 0xdfdfdf },
-	{ 0x40af8, 0xdfdfdf },
-	{ 0x40afc, 0xe0e0e0 },
-	{ 0x40b00, 0xe0e0e0 },
-	{ 0x40b04, 0xe1e1e1 },
-	{ 0x40b08, 0xe1e1e1 },
-	{ 0x40b0c, 0xe2e2e2 },
-	{ 0x40b10, 0xe3e3e3 },
-	{ 0x40b14, 0xe3e3e3 },
-	{ 0x40b18, 0xe4e4e4 },
-	{ 0x40b1c, 0xe4e4e4 },
-	{ 0x40b20, 0xe5e5e5 },
-	{ 0x40b24, 0xe5e5e5 },
-	{ 0x40b28, 0xe6e6e6 },
-	{ 0x40b2c, 0xe6e6e6 },
-	{ 0x40b30, 0xe7e7e7 },
-	{ 0x40b34, 0xe7e7e7 },
-	{ 0x40b38, 0xe8e8e8 },
-	{ 0x40b3c, 0xe8e8e8 },
-	{ 0x40b40, 0xe9e9e9 },
-	{ 0x40b44, 0xe9e9e9 },
-	{ 0x40b48, 0xeaeaea },
-	{ 0x40b4c, 0xeaeaea },
-	{ 0x40b50, 0xebebeb },
-	{ 0x40b54, 0xebebeb },
-	{ 0x40b58, 0xececec },
-	{ 0x40b5c, 0xececec },
-	{ 0x40b60, 0xededed },
-	{ 0x40b64, 0xededed },
-	{ 0x40b68, 0xeeeeee },
-	{ 0x40b6c, 0xeeeeee },
-	{ 0x40b70, 0xefefef },
-	{ 0x40b74, 0xefefef },
-	{ 0x40b78, 0xf0f0f0 },
-	{ 0x40b7c, 0xf0f0f0 },
-	{ 0x40b80, 0xf1f1f1 },
-	{ 0x40b84, 0xf1f1f1 },
-	{ 0x40b88, 0xf2f2f2 },
-	{ 0x40b8c, 0xf2f2f2 },
-	{ 0x40b90, 0xf2f2f2 },
-	{ 0x40b94, 0xf3f3f3 },
-	{ 0x40b98, 0xf3f3f3 },
-	{ 0x40b9c, 0xf4f4f4 },
-	{ 0x40ba0, 0xf4f4f4 },
-	{ 0x40ba4, 0xf5f5f5 },
-	{ 0x40ba8, 0xf5f5f5 },
-	{ 0x40bac, 0xf6f6f6 },
-	{ 0x40bb0, 0xf6f6f6 },
-	{ 0x40bb4, 0xf7f7f7 },
-	{ 0x40bb8, 0xf7f7f7 },
-	{ 0x40bbc, 0xf8f8f8 },
-	{ 0x40bc0, 0xf8f8f8 },
-	{ 0x40bc4, 0xf9f9f9 },
-	{ 0x40bc8, 0xf9f9f9 },
-	{ 0x40bcc, 0xfafafa },
-	{ 0x40bd0, 0xfafafa },
-	{ 0x40bd4, 0xfafafa },
-	{ 0x40bd8, 0xfbfbfb },
-	{ 0x40bdc, 0xfbfbfb },
-	{ 0x40be0, 0xfcfcfc },
-	{ 0x40be4, 0xfcfcfc },
-	{ 0x40be8, 0xfdfdfd },
-	{ 0x40bec, 0xfdfdfd },
-	{ 0x40bf0, 0xfefefe },
-	{ 0x40bf4, 0xfefefe },
-	{ 0x40bf8, 0xffffff },
-	{ 0x40bfc, 0xffffff },
-	{ 0x40c00, 0x0 },
-	{ 0x40c04, 0x0 },
-	{ 0x40c08, 0x0 },
-	{ 0x40c0c, 0x0 },
-	{ 0x40c10, 0x0 },
-	{ 0x40c14, 0x0 },
-	{ 0x40c18, 0x0 },
-	{ 0x40c1c, 0x0 },
-	{ 0x40c20, 0x0 },
-	{ 0x40c24, 0x0 },
-	{ 0x40c28, 0x0 },
-	{ 0x40c2c, 0x0 },
-	{ 0x40c30, 0x0 },
-	{ 0x40c34, 0x0 },
-	{ 0x40c38, 0x0 },
-	{ 0x40c3c, 0x0 },
-	{ 0x40c40, 0x10101 },
-	{ 0x40c44, 0x10101 },
-	{ 0x40c48, 0x10101 },
-	{ 0x40c4c, 0x10101 },
-	{ 0x40c50, 0x10101 },
-	{ 0x40c54, 0x10101 },
-	{ 0x40c58, 0x10101 },
-	{ 0x40c5c, 0x10101 },
-	{ 0x40c60, 0x10101 },
-	{ 0x40c64, 0x10101 },
-	{ 0x40c68, 0x20202 },
-	{ 0x40c6c, 0x20202 },
-	{ 0x40c70, 0x20202 },
-	{ 0x40c74, 0x20202 },
-	{ 0x40c78, 0x20202 },
-	{ 0x40c7c, 0x20202 },
-	{ 0x40c80, 0x30303 },
-	{ 0x40c84, 0x30303 },
-	{ 0x40c88, 0x30303 },
-	{ 0x40c8c, 0x30303 },
-	{ 0x40c90, 0x30303 },
-	{ 0x40c94, 0x40404 },
-	{ 0x40c98, 0x40404 },
-	{ 0x40c9c, 0x40404 },
-	{ 0x40ca0, 0x40404 },
-	{ 0x40ca4, 0x40404 },
-	{ 0x40ca8, 0x50505 },
-	{ 0x40cac, 0x50505 },
-	{ 0x40cb0, 0x50505 },
-	{ 0x40cb4, 0x50505 },
-	{ 0x40cb8, 0x60606 },
-	{ 0x40cbc, 0x60606 },
-	{ 0x40cc0, 0x60606 },
-	{ 0x40cc4, 0x70707 },
-	{ 0x40cc8, 0x70707 },
-	{ 0x40ccc, 0x70707 },
-	{ 0x40cd0, 0x70707 },
-	{ 0x40cd4, 0x80808 },
-	{ 0x40cd8, 0x80808 },
-	{ 0x40cdc, 0x80808 },
-	{ 0x40ce0, 0x90909 },
-	{ 0x40ce4, 0x90909 },
-	{ 0x40ce8, 0xa0a0a },
-	{ 0x40cec, 0xa0a0a },
-	{ 0x40cf0, 0xa0a0a },
-	{ 0x40cf4, 0xb0b0b },
-	{ 0x40cf8, 0xb0b0b },
-	{ 0x40cfc, 0xb0b0b },
-	{ 0x40d00, 0xc0c0c },
-	{ 0x40d04, 0xc0c0c },
-	{ 0x40d08, 0xd0d0d },
-	{ 0x40d0c, 0xd0d0d },
-	{ 0x40d10, 0xe0e0e },
-	{ 0x40d14, 0xe0e0e },
-	{ 0x40d18, 0xe0e0e },
-	{ 0x40d1c, 0xf0f0f },
-	{ 0x40d20, 0xf0f0f },
-	{ 0x40d24, 0x101010 },
-	{ 0x40d28, 0x101010 },
-	{ 0x40d2c, 0x111111 },
-	{ 0x40d30, 0x111111 },
-	{ 0x40d34, 0x121212 },
-	{ 0x40d38, 0x121212 },
-	{ 0x40d3c, 0x131313 },
-	{ 0x40d40, 0x131313 },
-	{ 0x40d44, 0x141414 },
-	{ 0x40d48, 0x151515 },
-	{ 0x40d4c, 0x151515 },
-	{ 0x40d50, 0x161616 },
-	{ 0x40d54, 0x161616 },
-	{ 0x40d58, 0x171717 },
-	{ 0x40d5c, 0x171717 },
-	{ 0x40d60, 0x181818 },
-	{ 0x40d64, 0x191919 },
-	{ 0x40d68, 0x191919 },
-	{ 0x40d6c, 0x1a1a1a },
-	{ 0x40d70, 0x1b1b1b },
-	{ 0x40d74, 0x1b1b1b },
-	{ 0x40d78, 0x1c1c1c },
-	{ 0x40d7c, 0x1c1c1c },
-	{ 0x40d80, 0x1d1d1d },
-	{ 0x40d84, 0x1e1e1e },
-	{ 0x40d88, 0x1f1f1f },
-	{ 0x40d8c, 0x1f1f1f },
-	{ 0x40d90, 0x202020 },
-	{ 0x40d94, 0x212121 },
-	{ 0x40d98, 0x212121 },
-	{ 0x40d9c, 0x222222 },
-	{ 0x40da0, 0x232323 },
-	{ 0x40da4, 0x242424 },
-	{ 0x40da8, 0x242424 },
-	{ 0x40dac, 0x252525 },
-	{ 0x40db0, 0x262626 },
-	{ 0x40db4, 0x272727 },
-	{ 0x40db8, 0x272727 },
-	{ 0x40dbc, 0x282828 },
-	{ 0x40dc0, 0x292929 },
-	{ 0x40dc4, 0x2a2a2a },
-	{ 0x40dc8, 0x2b2b2b },
-	{ 0x40dcc, 0x2c2c2c },
-	{ 0x40dd0, 0x2c2c2c },
-	{ 0x40dd4, 0x2d2d2d },
-	{ 0x40dd8, 0x2e2e2e },
-	{ 0x40ddc, 0x2f2f2f },
-	{ 0x40de0, 0x303030 },
-	{ 0x40de4, 0x313131 },
-	{ 0x40de8, 0x323232 },
-	{ 0x40dec, 0x333333 },
-	{ 0x40df0, 0x333333 },
-	{ 0x40df4, 0x343434 },
-	{ 0x40df8, 0x353535 },
-	{ 0x40dfc, 0x363636 },
-	{ 0x40e00, 0x373737 },
-	{ 0x40e04, 0x383838 },
-	{ 0x40e08, 0x393939 },
-	{ 0x40e0c, 0x3a3a3a },
-	{ 0x40e10, 0x3b3b3b },
-	{ 0x40e14, 0x3c3c3c },
-	{ 0x40e18, 0x3d3d3d },
-	{ 0x40e1c, 0x3e3e3e },
-	{ 0x40e20, 0x3f3f3f },
-	{ 0x40e24, 0x404040 },
-	{ 0x40e28, 0x414141 },
-	{ 0x40e2c, 0x424242 },
-	{ 0x40e30, 0x434343 },
-	{ 0x40e34, 0x444444 },
-	{ 0x40e38, 0x464646 },
-	{ 0x40e3c, 0x474747 },
-	{ 0x40e40, 0x484848 },
-	{ 0x40e44, 0x494949 },
-	{ 0x40e48, 0x4a4a4a },
-	{ 0x40e4c, 0x4b4b4b },
-	{ 0x40e50, 0x4c4c4c },
-	{ 0x40e54, 0x4d4d4d },
-	{ 0x40e58, 0x4f4f4f },
-	{ 0x40e5c, 0x505050 },
-	{ 0x40e60, 0x515151 },
-	{ 0x40e64, 0x525252 },
-	{ 0x40e68, 0x535353 },
-	{ 0x40e6c, 0x545454 },
-	{ 0x40e70, 0x565656 },
-	{ 0x40e74, 0x575757 },
-	{ 0x40e78, 0x585858 },
-	{ 0x40e7c, 0x595959 },
-	{ 0x40e80, 0x5b5b5b },
-	{ 0x40e84, 0x5c5c5c },
-	{ 0x40e88, 0x5d5d5d },
-	{ 0x40e8c, 0x5e5e5e },
-	{ 0x40e90, 0x606060 },
-	{ 0x40e94, 0x616161 },
-	{ 0x40e98, 0x626262 },
-	{ 0x40e9c, 0x646464 },
-	{ 0x40ea0, 0x656565 },
-	{ 0x40ea4, 0x666666 },
-	{ 0x40ea8, 0x686868 },
-	{ 0x40eac, 0x696969 },
-	{ 0x40eb0, 0x6a6a6a },
-	{ 0x40eb4, 0x6c6c6c },
-	{ 0x40eb8, 0x6d6d6d },
-	{ 0x40ebc, 0x6f6f6f },
-	{ 0x40ec0, 0x707070 },
-	{ 0x40ec4, 0x717171 },
-	{ 0x40ec8, 0x737373 },
-	{ 0x40ecc, 0x747474 },
-	{ 0x40ed0, 0x767676 },
-	{ 0x40ed4, 0x777777 },
-	{ 0x40ed8, 0x797979 },
-	{ 0x40edc, 0x7a7a7a },
-	{ 0x40ee0, 0x7c7c7c },
-	{ 0x40ee4, 0x7d7d7d },
-	{ 0x40ee8, 0x7f7f7f },
-	{ 0x40eec, 0x808080 },
-	{ 0x40ef0, 0x828282 },
-	{ 0x40ef4, 0x838383 },
-	{ 0x40ef8, 0x858585 },
-	{ 0x40efc, 0x868686 },
-	{ 0x40f00, 0x888888 },
-	{ 0x40f04, 0x898989 },
-	{ 0x40f08, 0x8b8b8b },
-	{ 0x40f0c, 0x8d8d8d },
-	{ 0x40f10, 0x8e8e8e },
-	{ 0x40f14, 0x909090 },
-	{ 0x40f18, 0x919191 },
-	{ 0x40f1c, 0x939393 },
-	{ 0x40f20, 0x959595 },
-	{ 0x40f24, 0x969696 },
-	{ 0x40f28, 0x989898 },
-	{ 0x40f2c, 0x9a9a9a },
-	{ 0x40f30, 0x9b9b9b },
-	{ 0x40f34, 0x9d9d9d },
-	{ 0x40f38, 0x9f9f9f },
-	{ 0x40f3c, 0xa1a1a1 },
-	{ 0x40f40, 0xa2a2a2 },
-	{ 0x40f44, 0xa4a4a4 },
-	{ 0x40f48, 0xa6a6a6 },
-	{ 0x40f4c, 0xa7a7a7 },
-	{ 0x40f50, 0xa9a9a9 },
-	{ 0x40f54, 0xababab },
-	{ 0x40f58, 0xadadad },
-	{ 0x40f5c, 0xafafaf },
-	{ 0x40f60, 0xb0b0b0 },
-	{ 0x40f64, 0xb2b2b2 },
-	{ 0x40f68, 0xb4b4b4 },
-	{ 0x40f6c, 0xb6b6b6 },
-	{ 0x40f70, 0xb8b8b8 },
-	{ 0x40f74, 0xbababa },
-	{ 0x40f78, 0xbbbbbb },
-	{ 0x40f7c, 0xbdbdbd },
-	{ 0x40f80, 0xbfbfbf },
-	{ 0x40f84, 0xc1c1c1 },
-	{ 0x40f88, 0xc3c3c3 },
-	{ 0x40f8c, 0xc5c5c5 },
-	{ 0x40f90, 0xc7c7c7 },
-	{ 0x40f94, 0xc9c9c9 },
-	{ 0x40f98, 0xcbcbcb },
-	{ 0x40f9c, 0xcdcdcd },
-	{ 0x40fa0, 0xcfcfcf },
-	{ 0x40fa4, 0xd1d1d1 },
-	{ 0x40fa8, 0xd3d3d3 },
-	{ 0x40fac, 0xd5d5d5 },
-	{ 0x40fb0, 0xd7d7d7 },
-	{ 0x40fb4, 0xd9d9d9 },
-	{ 0x40fb8, 0xdbdbdb },
-	{ 0x40fbc, 0xdddddd },
-	{ 0x40fc0, 0xdfdfdf },
-	{ 0x40fc4, 0xe1e1e1 },
-	{ 0x40fc8, 0xe3e3e3 },
-	{ 0x40fcc, 0xe5e5e5 },
-	{ 0x40fd0, 0xe7e7e7 },
-	{ 0x40fd4, 0xe9e9e9 },
-	{ 0x40fd8, 0xebebeb },
-	{ 0x40fdc, 0xeeeeee },
-	{ 0x40fe0, 0xf0f0f0 },
-	{ 0x40fe4, 0xf2f2f2 },
-	{ 0x40fe8, 0xf4f4f4 },
-	{ 0x40fec, 0xf6f6f6 },
-	{ 0x40ff0, 0xf8f8f8 },
-	{ 0x40ff4, 0xfbfbfb },
-	{ 0x40ff8, 0xfdfdfd },
-	{ 0x40ffc, 0xffffff },
-};
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
deleted file mode 100644
index 35848d741001..000000000000
--- a/drivers/video/msm/mdp_hw.h
+++ /dev/null
@@ -1,627 +0,0 @@
-/* drivers/video/msm_fb/mdp_hw.h
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef _MDP_HW_H_
-#define _MDP_HW_H_
-
-#include <linux/platform_data/video-msm_fb.h>
-
-struct mdp_info {
-	struct mdp_device mdp_dev;
-	char * __iomem base;
-	int irq;
-};
-struct mdp_blit_req;
-struct mdp_device;
-int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
-		 struct file *src_file, unsigned long src_start,
-		 unsigned long src_len, struct file *dst_file,
-		 unsigned long dst_start, unsigned long dst_len);
-#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
-#define mdp_readl(mdp, offset) readl(mdp->base + offset)
-
-#define MDP_SYNC_CONFIG_0                (0x00000)
-#define MDP_SYNC_CONFIG_1                (0x00004)
-#define MDP_SYNC_CONFIG_2                (0x00008)
-#define MDP_SYNC_STATUS_0                (0x0000c)
-#define MDP_SYNC_STATUS_1                (0x00010)
-#define MDP_SYNC_STATUS_2                (0x00014)
-#define MDP_SYNC_THRESH_0                (0x00018)
-#define MDP_SYNC_THRESH_1                (0x0001c)
-#define MDP_INTR_ENABLE                  (0x00020)
-#define MDP_INTR_STATUS                  (0x00024)
-#define MDP_INTR_CLEAR                   (0x00028)
-#define MDP_DISPLAY0_START               (0x00030)
-#define MDP_DISPLAY1_START               (0x00034)
-#define MDP_DISPLAY_STATUS               (0x00038)
-#define MDP_EBI2_LCD0                    (0x0003c)
-#define MDP_EBI2_LCD1                    (0x00040)
-#define MDP_DISPLAY0_ADDR                (0x00054)
-#define MDP_DISPLAY1_ADDR                (0x00058)
-#define MDP_EBI2_PORTMAP_MODE            (0x0005c)
-#define MDP_MODE                         (0x00060)
-#define MDP_TV_OUT_STATUS                (0x00064)
-#define MDP_HW_VERSION                   (0x00070)
-#define MDP_SW_RESET                     (0x00074)
-#define MDP_AXI_ERROR_MASTER_STOP        (0x00078)
-#define MDP_SEL_CLK_OR_HCLK_TEST_BUS     (0x0007c)
-#define MDP_PRIMARY_VSYNC_OUT_CTRL       (0x00080)
-#define MDP_SECONDARY_VSYNC_OUT_CTRL     (0x00084)
-#define MDP_EXTERNAL_VSYNC_OUT_CTRL      (0x00088)
-#define MDP_VSYNC_CTRL                   (0x0008c)
-#define MDP_CGC_EN                       (0x00100)
-#define MDP_CMD_STATUS                   (0x10008)
-#define MDP_PROFILE_EN                   (0x10010)
-#define MDP_PROFILE_COUNT                (0x10014)
-#define MDP_DMA_START                    (0x10044)
-#define MDP_FULL_BYPASS_WORD0            (0x10100)
-#define MDP_FULL_BYPASS_WORD1            (0x10104)
-#define MDP_COMMAND_CONFIG               (0x10104)
-#define MDP_FULL_BYPASS_WORD2            (0x10108)
-#define MDP_FULL_BYPASS_WORD3            (0x1010c)
-#define MDP_FULL_BYPASS_WORD4            (0x10110)
-#define MDP_FULL_BYPASS_WORD6            (0x10118)
-#define MDP_FULL_BYPASS_WORD7            (0x1011c)
-#define MDP_FULL_BYPASS_WORD8            (0x10120)
-#define MDP_FULL_BYPASS_WORD9            (0x10124)
-#define MDP_PPP_SOURCE_CONFIG            (0x10124)
-#define MDP_FULL_BYPASS_WORD10           (0x10128)
-#define MDP_FULL_BYPASS_WORD11           (0x1012c)
-#define MDP_FULL_BYPASS_WORD12           (0x10130)
-#define MDP_FULL_BYPASS_WORD13           (0x10134)
-#define MDP_FULL_BYPASS_WORD14           (0x10138)
-#define MDP_PPP_OPERATION_CONFIG         (0x10138)
-#define MDP_FULL_BYPASS_WORD15           (0x1013c)
-#define MDP_FULL_BYPASS_WORD16           (0x10140)
-#define MDP_FULL_BYPASS_WORD17           (0x10144)
-#define MDP_FULL_BYPASS_WORD18           (0x10148)
-#define MDP_FULL_BYPASS_WORD19           (0x1014c)
-#define MDP_FULL_BYPASS_WORD20           (0x10150)
-#define MDP_PPP_DESTINATION_CONFIG       (0x10150)
-#define MDP_FULL_BYPASS_WORD21           (0x10154)
-#define MDP_FULL_BYPASS_WORD22           (0x10158)
-#define MDP_FULL_BYPASS_WORD23           (0x1015c)
-#define MDP_FULL_BYPASS_WORD24           (0x10160)
-#define MDP_FULL_BYPASS_WORD25           (0x10164)
-#define MDP_FULL_BYPASS_WORD26           (0x10168)
-#define MDP_FULL_BYPASS_WORD27           (0x1016c)
-#define MDP_FULL_BYPASS_WORD29           (0x10174)
-#define MDP_FULL_BYPASS_WORD30           (0x10178)
-#define MDP_FULL_BYPASS_WORD31           (0x1017c)
-#define MDP_FULL_BYPASS_WORD32           (0x10180)
-#define MDP_DMA_CONFIG                   (0x10180)
-#define MDP_FULL_BYPASS_WORD33           (0x10184)
-#define MDP_FULL_BYPASS_WORD34           (0x10188)
-#define MDP_FULL_BYPASS_WORD35           (0x1018c)
-#define MDP_FULL_BYPASS_WORD37           (0x10194)
-#define MDP_FULL_BYPASS_WORD39           (0x1019c)
-#define MDP_FULL_BYPASS_WORD40           (0x101a0)
-#define MDP_FULL_BYPASS_WORD41           (0x101a4)
-#define MDP_FULL_BYPASS_WORD43           (0x101ac)
-#define MDP_FULL_BYPASS_WORD46           (0x101b8)
-#define MDP_FULL_BYPASS_WORD47           (0x101bc)
-#define MDP_FULL_BYPASS_WORD48           (0x101c0)
-#define MDP_FULL_BYPASS_WORD49           (0x101c4)
-#define MDP_FULL_BYPASS_WORD50           (0x101c8)
-#define MDP_FULL_BYPASS_WORD51           (0x101cc)
-#define MDP_FULL_BYPASS_WORD52           (0x101d0)
-#define MDP_FULL_BYPASS_WORD53           (0x101d4)
-#define MDP_FULL_BYPASS_WORD54           (0x101d8)
-#define MDP_FULL_BYPASS_WORD55           (0x101dc)
-#define MDP_FULL_BYPASS_WORD56           (0x101e0)
-#define MDP_FULL_BYPASS_WORD57           (0x101e4)
-#define MDP_FULL_BYPASS_WORD58           (0x101e8)
-#define MDP_FULL_BYPASS_WORD59           (0x101ec)
-#define MDP_FULL_BYPASS_WORD60           (0x101f0)
-#define MDP_VSYNC_THRESHOLD              (0x101f0)
-#define MDP_FULL_BYPASS_WORD61           (0x101f4)
-#define MDP_FULL_BYPASS_WORD62           (0x101f8)
-#define MDP_FULL_BYPASS_WORD63           (0x101fc)
-#define MDP_TFETCH_TEST_MODE             (0x20004)
-#define MDP_TFETCH_STATUS                (0x20008)
-#define MDP_TFETCH_TILE_COUNT            (0x20010)
-#define MDP_TFETCH_FETCH_COUNT           (0x20014)
-#define MDP_TFETCH_CONSTANT_COLOR        (0x20040)
-#define MDP_CSC_BYPASS                   (0x40004)
-#define MDP_SCALE_COEFF_LSB              (0x5fffc)
-#define MDP_TV_OUT_CTL                   (0xc0000)
-#define MDP_TV_OUT_FIR_COEFF             (0xc0004)
-#define MDP_TV_OUT_BUF_ADDR              (0xc0008)
-#define MDP_TV_OUT_CC_DATA               (0xc000c)
-#define MDP_TV_OUT_SOBEL                 (0xc0010)
-#define MDP_TV_OUT_Y_CLAMP               (0xc0018)
-#define MDP_TV_OUT_CB_CLAMP              (0xc001c)
-#define MDP_TV_OUT_CR_CLAMP              (0xc0020)
-#define MDP_TEST_MODE_CLK                (0xd0000)
-#define MDP_TEST_MISR_RESET_CLK          (0xd0004)
-#define MDP_TEST_EXPORT_MISR_CLK         (0xd0008)
-#define MDP_TEST_MISR_CURR_VAL_CLK       (0xd000c)
-#define MDP_TEST_MODE_HCLK               (0xd0100)
-#define MDP_TEST_MISR_RESET_HCLK         (0xd0104)
-#define MDP_TEST_EXPORT_MISR_HCLK        (0xd0108)
-#define MDP_TEST_MISR_CURR_VAL_HCLK      (0xd010c)
-#define MDP_TEST_MODE_DCLK               (0xd0200)
-#define MDP_TEST_MISR_RESET_DCLK         (0xd0204)
-#define MDP_TEST_EXPORT_MISR_DCLK        (0xd0208)
-#define MDP_TEST_MISR_CURR_VAL_DCLK      (0xd020c)
-#define MDP_TEST_CAPTURED_DCLK           (0xd0210)
-#define MDP_TEST_MISR_CAPT_VAL_DCLK      (0xd0214)
-#define MDP_LCDC_CTL                     (0xe0000)
-#define MDP_LCDC_HSYNC_CTL               (0xe0004)
-#define MDP_LCDC_VSYNC_CTL               (0xe0008)
-#define MDP_LCDC_ACTIVE_HCTL             (0xe000c)
-#define MDP_LCDC_ACTIVE_VCTL             (0xe0010)
-#define MDP_LCDC_BORDER_CLR              (0xe0014)
-#define MDP_LCDC_H_BLANK                 (0xe0018)
-#define MDP_LCDC_V_BLANK                 (0xe001c)
-#define MDP_LCDC_UNDERFLOW_CLR           (0xe0020)
-#define MDP_LCDC_HSYNC_SKEW              (0xe0024)
-#define MDP_LCDC_TEST_CTL                (0xe0028)
-#define MDP_LCDC_LINE_IRQ                (0xe002c)
-#define MDP_LCDC_CTL_POLARITY            (0xe0030)
-#define MDP_LCDC_DMA_CONFIG              (0xe1000)
-#define MDP_LCDC_DMA_SIZE                (0xe1004)
-#define MDP_LCDC_DMA_IBUF_ADDR           (0xe1008)
-#define MDP_LCDC_DMA_IBUF_Y_STRIDE       (0xe100c)
-
-
-#define MDP_DMA2_TERM 0x1
-#define MDP_DMA3_TERM 0x2
-#define MDP_PPP_TERM 0x3
-
-/* MDP_INTR_ENABLE */
-#define DL0_ROI_DONE           (1<<0)
-#define DL1_ROI_DONE           (1<<1)
-#define DL0_DMA2_TERM_DONE     (1<<2)
-#define DL1_DMA2_TERM_DONE     (1<<3)
-#define DL0_PPP_TERM_DONE      (1<<4)
-#define DL1_PPP_TERM_DONE      (1<<5)
-#define TV_OUT_DMA3_DONE       (1<<6)
-#define TV_ENC_UNDERRUN        (1<<7)
-#define DL0_FETCH_DONE         (1<<11)
-#define DL1_FETCH_DONE         (1<<12)
-
-#define MDP_PPP_BUSY_STATUS (DL0_ROI_DONE| \
-			   DL1_ROI_DONE| \
-			   DL0_PPP_TERM_DONE| \
-			   DL1_PPP_TERM_DONE)
-
-#define MDP_ANY_INTR_MASK (DL0_ROI_DONE| \
-			   DL1_ROI_DONE| \
-			   DL0_DMA2_TERM_DONE| \
-			   DL1_DMA2_TERM_DONE| \
-			   DL0_PPP_TERM_DONE| \
-			   DL1_PPP_TERM_DONE| \
-			   DL0_FETCH_DONE| \
-			   DL1_FETCH_DONE| \
-			   TV_ENC_UNDERRUN)
-
-#define MDP_TOP_LUMA       16
-#define MDP_TOP_CHROMA     0
-#define MDP_BOTTOM_LUMA    19
-#define MDP_BOTTOM_CHROMA  3
-#define MDP_LEFT_LUMA      22
-#define MDP_LEFT_CHROMA    6
-#define MDP_RIGHT_LUMA     25
-#define MDP_RIGHT_CHROMA   9
-
-#define CLR_G 0x0
-#define CLR_B 0x1
-#define CLR_R 0x2
-#define CLR_ALPHA 0x3
-
-#define CLR_Y  CLR_G
-#define CLR_CB CLR_B
-#define CLR_CR CLR_R
-
-/* from lsb to msb */
-#define MDP_GET_PACK_PATTERN(a, x, y, z, bit) \
-	(((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
-
-/* MDP_SYNC_CONFIG_0/1/2 */
-#define MDP_SYNCFG_HGT_LOC 22
-#define MDP_SYNCFG_VSYNC_EXT_EN (1<<21)
-#define MDP_SYNCFG_VSYNC_INT_EN (1<<20)
-
-/* MDP_SYNC_THRESH_0 */
-#define MDP_PRIM_BELOW_LOC 0
-#define MDP_PRIM_ABOVE_LOC 8
-
-/* MDP_{PRIMARY,SECONDARY,EXTERNAL}_VSYNC_OUT_CRL */
-#define VSYNC_PULSE_EN (1<<31)
-#define VSYNC_PULSE_INV (1<<30)
-
-/* MDP_VSYNC_CTRL */
-#define DISP0_VSYNC_MAP_VSYNC0 0
-#define DISP0_VSYNC_MAP_VSYNC1 (1<<0)
-#define DISP0_VSYNC_MAP_VSYNC2 ((1<<0)|(1<<1))
-
-#define DISP1_VSYNC_MAP_VSYNC0 0
-#define DISP1_VSYNC_MAP_VSYNC1 (1<<2)
-#define DISP1_VSYNC_MAP_VSYNC2 ((1<<2)|(1<<3))
-
-#define PRIMARY_LCD_SYNC_EN (1<<4)
-#define PRIMARY_LCD_SYNC_DISABLE 0
-
-#define SECONDARY_LCD_SYNC_EN (1<<5)
-#define SECONDARY_LCD_SYNC_DISABLE 0
-
-#define EXTERNAL_LCD_SYNC_EN (1<<6)
-#define EXTERNAL_LCD_SYNC_DISABLE 0
-
-/* MDP_VSYNC_THRESHOLD / MDP_FULL_BYPASS_WORD60 */
-#define VSYNC_THRESHOLD_ABOVE_LOC 0
-#define VSYNC_THRESHOLD_BELOW_LOC 16
-#define VSYNC_ANTI_TEAR_EN (1<<31)
-
-/* MDP_COMMAND_CONFIG / MDP_FULL_BYPASS_WORD1 */
-#define MDP_CMD_DBGBUS_EN (1<<0)
-
-/* MDP_PPP_SOURCE_CONFIG / MDP_FULL_BYPASS_WORD9&53 */
-#define PPP_SRC_C0G_8BIT ((1<<1)|(1<<0))
-#define PPP_SRC_C1B_8BIT ((1<<3)|(1<<2))
-#define PPP_SRC_C2R_8BIT ((1<<5)|(1<<4))
-#define PPP_SRC_C3A_8BIT ((1<<7)|(1<<6))
-
-#define PPP_SRC_C0G_6BIT (1<<1)
-#define PPP_SRC_C1B_6BIT (1<<3)
-#define PPP_SRC_C2R_6BIT (1<<5)
-
-#define PPP_SRC_C0G_5BIT (1<<0)
-#define PPP_SRC_C1B_5BIT (1<<2)
-#define PPP_SRC_C2R_5BIT (1<<4)
-
-#define PPP_SRC_C3ALPHA_EN (1<<8)
-
-#define PPP_SRC_BPP_1BYTES 0
-#define PPP_SRC_BPP_2BYTES (1<<9)
-#define PPP_SRC_BPP_3BYTES (1<<10)
-#define PPP_SRC_BPP_4BYTES ((1<<10)|(1<<9))
-
-#define PPP_SRC_BPP_ROI_ODD_X (1<<11)
-#define PPP_SRC_BPP_ROI_ODD_Y (1<<12)
-#define PPP_SRC_INTERLVD_2COMPONENTS (1<<13)
-#define PPP_SRC_INTERLVD_3COMPONENTS (1<<14)
-#define PPP_SRC_INTERLVD_4COMPONENTS ((1<<14)|(1<<13))
-
-
-/* RGB666 unpack format
-** TIGHT means R6+G6+B6 together
-** LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
-**          or 2+R6 +2+G6 +2+B6 (with LSB)
-*/
-#define PPP_SRC_PACK_TIGHT (1<<17)
-#define PPP_SRC_PACK_LOOSE 0
-#define PPP_SRC_PACK_ALIGN_LSB 0
-#define PPP_SRC_PACK_ALIGN_MSB (1<<18)
-
-#define PPP_SRC_PLANE_INTERLVD 0
-#define PPP_SRC_PLANE_PSEUDOPLNR (1<<20)
-
-#define PPP_SRC_WMV9_MODE (1<<21)
-
-/* MDP_PPP_OPERATION_CONFIG / MDP_FULL_BYPASS_WORD14 */
-#define PPP_OP_SCALE_X_ON (1<<0)
-#define PPP_OP_SCALE_Y_ON (1<<1)
-
-#define PPP_OP_CONVERT_RGB2YCBCR 0
-#define PPP_OP_CONVERT_YCBCR2RGB (1<<2)
-#define PPP_OP_CONVERT_ON (1<<3)
-
-#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
-#define PPP_OP_CONVERT_MATRIX_SECONDARY (1<<4)
-
-#define PPP_OP_LUT_C0_ON (1<<5)
-#define PPP_OP_LUT_C1_ON (1<<6)
-#define PPP_OP_LUT_C2_ON (1<<7)
-
-/* rotate or blend enable */
-#define PPP_OP_ROT_ON (1<<8)
-
-#define PPP_OP_ROT_90 (1<<9)
-#define PPP_OP_FLIP_LR (1<<10)
-#define PPP_OP_FLIP_UD (1<<11)
-
-#define PPP_OP_BLEND_ON (1<<12)
-
-#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
-#define PPP_OP_BLEND_DSTPIXEL_ALPHA (1<<13)
-#define PPP_OP_BLEND_CONSTANT_ALPHA (1<<14)
-#define PPP_OP_BLEND_SRCPIXEL_TRANSP ((1<<13)|(1<<14))
-
-#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
-#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE (1<<15)
-
-#define PPP_OP_DITHER_EN (1<<16)
-
-#define PPP_OP_COLOR_SPACE_RGB 0
-#define PPP_OP_COLOR_SPACE_YCBCR (1<<17)
-
-#define PPP_OP_SRC_CHROMA_RGB 0
-#define PPP_OP_SRC_CHROMA_H2V1 (1<<18)
-#define PPP_OP_SRC_CHROMA_H1V2 (1<<19)
-#define PPP_OP_SRC_CHROMA_420 ((1<<18)|(1<<19))
-#define PPP_OP_SRC_CHROMA_COSITE 0
-#define PPP_OP_SRC_CHROMA_OFFSITE (1<<20)
-
-#define PPP_OP_DST_CHROMA_RGB 0
-#define PPP_OP_DST_CHROMA_H2V1 (1<<21)
-#define PPP_OP_DST_CHROMA_H1V2 (1<<22)
-#define PPP_OP_DST_CHROMA_420 ((1<<21)|(1<<22))
-#define PPP_OP_DST_CHROMA_COSITE 0
-#define PPP_OP_DST_CHROMA_OFFSITE (1<<23)
-
-#define PPP_BLEND_ALPHA_TRANSP (1<<24)
-
-#define PPP_OP_BG_CHROMA_RGB 0
-#define PPP_OP_BG_CHROMA_H2V1 (1<<25)
-#define PPP_OP_BG_CHROMA_H1V2 (1<<26)
-#define PPP_OP_BG_CHROMA_420 ((1<<25)|(1<<26))
-#define PPP_OP_BG_CHROMA_SITE_COSITE 0
-#define PPP_OP_BG_CHROMA_SITE_OFFSITE (1<<27)
-
-/* MDP_PPP_DESTINATION_CONFIG / MDP_FULL_BYPASS_WORD20 */
-#define PPP_DST_C0G_8BIT ((1<<0)|(1<<1))
-#define PPP_DST_C1B_8BIT ((1<<3)|(1<<2))
-#define PPP_DST_C2R_8BIT ((1<<5)|(1<<4))
-#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
-
-#define PPP_DST_C0G_6BIT (1<<1)
-#define PPP_DST_C1B_6BIT (1<<3)
-#define PPP_DST_C2R_6BIT (1<<5)
-
-#define PPP_DST_C0G_5BIT (1<<0)
-#define PPP_DST_C1B_5BIT (1<<2)
-#define PPP_DST_C2R_5BIT (1<<4)
-
-#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
-#define PPP_DST_C3ALPHA_EN (1<<8)
-
-#define PPP_DST_INTERLVD_2COMPONENTS (1<<9)
-#define PPP_DST_INTERLVD_3COMPONENTS (1<<10)
-#define PPP_DST_INTERLVD_4COMPONENTS ((1<<10)|(1<<9))
-#define PPP_DST_INTERLVD_6COMPONENTS ((1<<11)|(1<<9))
-
-#define PPP_DST_PACK_LOOSE 0
-#define PPP_DST_PACK_TIGHT (1<<13)
-#define PPP_DST_PACK_ALIGN_LSB 0
-#define PPP_DST_PACK_ALIGN_MSB (1<<14)
-
-#define PPP_DST_OUT_SEL_AXI 0
-#define PPP_DST_OUT_SEL_MDDI (1<<15)
-
-#define PPP_DST_BPP_2BYTES (1<<16)
-#define PPP_DST_BPP_3BYTES (1<<17)
-#define PPP_DST_BPP_4BYTES ((1<<17)|(1<<16))
-
-#define PPP_DST_PLANE_INTERLVD 0
-#define PPP_DST_PLANE_PLANAR (1<<18)
-#define PPP_DST_PLANE_PSEUDOPLNR (1<<19)
-
-#define PPP_DST_TO_TV (1<<20)
-
-#define PPP_DST_MDDI_PRIMARY 0
-#define PPP_DST_MDDI_SECONDARY (1<<21)
-#define PPP_DST_MDDI_EXTERNAL (1<<22)
-
-/* image configurations by image type */
-#define PPP_CFG_MDP_RGB_565(dir)       (PPP_##dir##_C2R_5BIT | \
-					PPP_##dir##_C0G_6BIT | \
-					PPP_##dir##_C1B_5BIT | \
-					PPP_##dir##_BPP_2BYTES | \
-					PPP_##dir##_INTERLVD_3COMPONENTS | \
-					PPP_##dir##_PACK_TIGHT | \
-					PPP_##dir##_PACK_ALIGN_LSB | \
-					PPP_##dir##_PLANE_INTERLVD)
-
-#define PPP_CFG_MDP_RGB_888(dir)       (PPP_##dir##_C2R_8BIT | \
-					PPP_##dir##_C0G_8BIT | \
-					PPP_##dir##_C1B_8BIT | \
-					PPP_##dir##_BPP_3BYTES | \
-					PPP_##dir##_INTERLVD_3COMPONENTS | \
-					PPP_##dir##_PACK_TIGHT | \
-					PPP_##dir##_PACK_ALIGN_LSB | \
-					PPP_##dir##_PLANE_INTERLVD)
-
-#define PPP_CFG_MDP_ARGB_8888(dir)     (PPP_##dir##_C2R_8BIT | \
-					PPP_##dir##_C0G_8BIT | \
-					PPP_##dir##_C1B_8BIT | \
-					PPP_##dir##_C3A_8BIT | \
-					PPP_##dir##_C3ALPHA_EN | \
-					PPP_##dir##_BPP_4BYTES | \
-					PPP_##dir##_INTERLVD_4COMPONENTS | \
-					PPP_##dir##_PACK_TIGHT | \
-					PPP_##dir##_PACK_ALIGN_LSB | \
-					PPP_##dir##_PLANE_INTERLVD)
-
-#define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
-#define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
-#define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
-#define PPP_CFG_MDP_RGBX_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
-
-#define PPP_CFG_MDP_Y_CBCR_H2V2(dir)   (PPP_##dir##_C2R_8BIT | \
-					PPP_##dir##_C0G_8BIT | \
-					PPP_##dir##_C1B_8BIT | \
-					PPP_##dir##_C3A_8BIT | \
-					PPP_##dir##_BPP_2BYTES | \
-					PPP_##dir##_INTERLVD_2COMPONENTS | \
-					PPP_##dir##_PACK_TIGHT | \
-					PPP_##dir##_PACK_ALIGN_LSB | \
-					PPP_##dir##_PLANE_PSEUDOPLNR)
-
-#define PPP_CFG_MDP_Y_CRCB_H2V2(dir)	PPP_CFG_MDP_Y_CBCR_H2V2(dir)
-
-#define PPP_CFG_MDP_YCRYCB_H2V1(dir)   (PPP_##dir##_C2R_8BIT | \
-					PPP_##dir##_C0G_8BIT | \
-					PPP_##dir##_C1B_8BIT | \
-					PPP_##dir##_C3A_8BIT | \
-					PPP_##dir##_BPP_2BYTES | \
-					PPP_##dir##_INTERLVD_4COMPONENTS | \
-					PPP_##dir##_PACK_TIGHT | \
-					PPP_##dir##_PACK_ALIGN_LSB |\
-					PPP_##dir##_PLANE_INTERLVD)
-
-#define PPP_CFG_MDP_Y_CBCR_H2V1(dir)   (PPP_##dir##_C2R_8BIT | \
-					PPP_##dir##_C0G_8BIT | \
-					PPP_##dir##_C1B_8BIT | \
-					PPP_##dir##_C3A_8BIT | \
-					PPP_##dir##_BPP_2BYTES |   \
-					PPP_##dir##_INTERLVD_2COMPONENTS |  \
-					PPP_##dir##_PACK_TIGHT | \
-					PPP_##dir##_PACK_ALIGN_LSB | \
-					PPP_##dir##_PLANE_PSEUDOPLNR)
-
-#define PPP_CFG_MDP_Y_CRCB_H2V1(dir)	PPP_CFG_MDP_Y_CBCR_H2V1(dir)
-
-#define PPP_PACK_PATTERN_MDP_RGB_565 \
-	MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8)
-#define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565
-#define PPP_PACK_PATTERN_MDP_XRGB_8888 \
-	MDP_GET_PACK_PATTERN(CLR_B, CLR_G, CLR_R, CLR_ALPHA, 8)
-#define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888
-#define PPP_PACK_PATTERN_MDP_RGBA_8888 \
-	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
-#define PPP_PACK_PATTERN_MDP_BGRA_8888 \
-	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
-#define PPP_PACK_PATTERN_MDP_RGBX_8888 \
-	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
-#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \
-	MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8)
-#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1
-#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1 \
-	MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8)
-#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V2 PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1
-#define PPP_PACK_PATTERN_MDP_YCRYCB_H2V1 \
-	MDP_GET_PACK_PATTERN(CLR_Y, CLR_R, CLR_Y, CLR_B, 8)
-
-#define PPP_CHROMA_SAMP_MDP_RGB_565(dir) PPP_OP_##dir##_CHROMA_RGB
-#define PPP_CHROMA_SAMP_MDP_RGB_888(dir) PPP_OP_##dir##_CHROMA_RGB
-#define PPP_CHROMA_SAMP_MDP_XRGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
-#define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
-#define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
-#define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
-#define PPP_CHROMA_SAMP_MDP_RGBX_8888(dir) PPP_OP_##dir##_CHROMA_RGB
-#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
-#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420
-#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
-#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V2(dir) PPP_OP_##dir##_CHROMA_420
-#define PPP_CHROMA_SAMP_MDP_YCRYCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
-
-/* Helpful array generation macros */
-#define PPP_ARRAY0(name) \
-	[MDP_RGB_565] = PPP_##name##_MDP_RGB_565,\
-	[MDP_RGB_888] = PPP_##name##_MDP_RGB_888,\
-	[MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888,\
-	[MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\
-	[MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\
-	[MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\
-	[MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888,\
-	[MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\
-	[MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\
-	[MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\
-	[MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2,\
-	[MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1
-
-#define PPP_ARRAY1(name, dir) \
-	[MDP_RGB_565] = PPP_##name##_MDP_RGB_565(dir),\
-	[MDP_RGB_888] = PPP_##name##_MDP_RGB_888(dir),\
-	[MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888(dir),\
-	[MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\
-	[MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\
-	[MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\
-	[MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888(dir),\
-	[MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\
-	[MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\
-	[MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\
-	[MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2(dir),\
-	[MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1(dir)
-
-#define IS_YCRCB(img) ((img == MDP_Y_CRCB_H2V2) | (img == MDP_Y_CBCR_H2V2) | \
-		       (img == MDP_Y_CRCB_H2V1) | (img == MDP_Y_CBCR_H2V1) | \
-		       (img == MDP_YCRYCB_H2V1))
-#define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \
-		     (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
-		     (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888) | \
-		     (img == MDP_RGBX_8888))
-#define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
-			(img == MDP_BGRA_8888))
-
-#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
-			    (img == MDP_Y_CBCR_H2V2) | \
-			    (img == MDP_Y_CRCB_H2V1) | \
-			    (img == MDP_Y_CBCR_H2V1))
-
-/* Mappings from addr to purpose */
-#define PPP_ADDR_SRC_ROI		MDP_FULL_BYPASS_WORD2
-#define PPP_ADDR_SRC0			MDP_FULL_BYPASS_WORD3
-#define PPP_ADDR_SRC1			MDP_FULL_BYPASS_WORD4
-#define PPP_ADDR_SRC_YSTRIDE		MDP_FULL_BYPASS_WORD7
-#define PPP_ADDR_SRC_CFG		MDP_FULL_BYPASS_WORD9
-#define PPP_ADDR_SRC_PACK_PATTERN	MDP_FULL_BYPASS_WORD10
-#define PPP_ADDR_OPERATION		MDP_FULL_BYPASS_WORD14
-#define PPP_ADDR_PHASEX_INIT		MDP_FULL_BYPASS_WORD15
-#define PPP_ADDR_PHASEY_INIT		MDP_FULL_BYPASS_WORD16
-#define PPP_ADDR_PHASEX_STEP		MDP_FULL_BYPASS_WORD17
-#define PPP_ADDR_PHASEY_STEP		MDP_FULL_BYPASS_WORD18
-#define PPP_ADDR_ALPHA_TRANSP		MDP_FULL_BYPASS_WORD19
-#define PPP_ADDR_DST_CFG		MDP_FULL_BYPASS_WORD20
-#define PPP_ADDR_DST_PACK_PATTERN	MDP_FULL_BYPASS_WORD21
-#define PPP_ADDR_DST_ROI		MDP_FULL_BYPASS_WORD25
-#define PPP_ADDR_DST0			MDP_FULL_BYPASS_WORD26
-#define PPP_ADDR_DST1			MDP_FULL_BYPASS_WORD27
-#define PPP_ADDR_DST_YSTRIDE		MDP_FULL_BYPASS_WORD30
-#define PPP_ADDR_EDGE			MDP_FULL_BYPASS_WORD46
-#define PPP_ADDR_BG0			MDP_FULL_BYPASS_WORD48
-#define PPP_ADDR_BG1			MDP_FULL_BYPASS_WORD49
-#define PPP_ADDR_BG_YSTRIDE		MDP_FULL_BYPASS_WORD51
-#define PPP_ADDR_BG_CFG			MDP_FULL_BYPASS_WORD53
-#define PPP_ADDR_BG_PACK_PATTERN	MDP_FULL_BYPASS_WORD54
-
-/* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */
-#define DMA_DSTC0G_6BITS (1<<1)
-#define DMA_DSTC1B_6BITS (1<<3)
-#define DMA_DSTC2R_6BITS (1<<5)
-#define DMA_DSTC0G_5BITS (1<<0)
-#define DMA_DSTC1B_5BITS (1<<2)
-#define DMA_DSTC2R_5BITS (1<<4)
-
-#define DMA_PACK_TIGHT (1<<6)
-#define DMA_PACK_LOOSE 0
-#define DMA_PACK_ALIGN_LSB 0
-#define DMA_PACK_ALIGN_MSB (1<<7)
-#define DMA_PACK_PATTERN_RGB \
-	(MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
-
-#define DMA_OUT_SEL_AHB  0
-#define DMA_OUT_SEL_MDDI (1<<14)
-#define DMA_AHBM_LCD_SEL_PRIMARY 0
-#define DMA_AHBM_LCD_SEL_SECONDARY (1<<15)
-#define DMA_IBUF_C3ALPHA_EN (1<<16)
-#define DMA_DITHER_EN (1<<17)
-
-#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
-#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (1<<18)
-#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (1<<19)
-
-#define DMA_IBUF_FORMAT_RGB565 (1<<20)
-#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
-
-#define DMA_IBUF_NONCONTIGUOUS (1<<21)
-
-/* MDDI REGISTER ? */
-#define MDDI_VDO_PACKET_DESC  0x5666
-#define MDDI_VDO_PACKET_PRIM  0xC3
-#define MDDI_VDO_PACKET_SECD  0xC0
-
-#endif
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
deleted file mode 100644
index be6079cdfbb6..000000000000
--- a/drivers/video/msm/mdp_ppp.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/* drivers/video/msm/mdp_ppp.c
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/fb.h>
-#include <linux/file.h>
-#include <linux/delay.h>
-#include <linux/msm_mdp.h>
-#include <linux/platform_data/video-msm_fb.h>
-
-#include "mdp_hw.h"
-#include "mdp_scale_tables.h"
-
-#define DLOG(x...) do {} while (0)
-
-#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1)
-static int downscale_y_table = MDP_DOWNSCALE_MAX;
-static int downscale_x_table = MDP_DOWNSCALE_MAX;
-
-struct mdp_regs {
-	uint32_t src0;
-	uint32_t src1;
-	uint32_t dst0;
-	uint32_t dst1;
-	uint32_t src_cfg;
-	uint32_t dst_cfg;
-	uint32_t src_pack;
-	uint32_t dst_pack;
-	uint32_t src_rect;
-	uint32_t dst_rect;
-	uint32_t src_ystride;
-	uint32_t dst_ystride;
-	uint32_t op;
-	uint32_t src_bpp;
-	uint32_t dst_bpp;
-	uint32_t edge;
-	uint32_t phasex_init;
-	uint32_t phasey_init;
-	uint32_t phasex_step;
-	uint32_t phasey_step;
-};
-
-static uint32_t pack_pattern[] = {
-	PPP_ARRAY0(PACK_PATTERN)
-};
-
-static uint32_t src_img_cfg[] = {
-	PPP_ARRAY1(CFG, SRC)
-};
-
-static uint32_t dst_img_cfg[] = {
-	PPP_ARRAY1(CFG, DST)
-};
-
-static uint32_t bytes_per_pixel[] = {
-	[MDP_RGB_565] = 2,
-	[MDP_RGB_888] = 3,
-	[MDP_XRGB_8888] = 4,
-	[MDP_ARGB_8888] = 4,
-	[MDP_RGBA_8888] = 4,
-	[MDP_BGRA_8888] = 4,
-	[MDP_RGBX_8888] = 4,
-	[MDP_Y_CBCR_H2V1] = 1,
-	[MDP_Y_CBCR_H2V2] = 1,
-	[MDP_Y_CRCB_H2V1] = 1,
-	[MDP_Y_CRCB_H2V2] = 1,
-	[MDP_YCRYCB_H2V1] = 2
-};
-
-static uint32_t dst_op_chroma[] = {
-	PPP_ARRAY1(CHROMA_SAMP, DST)
-};
-
-static uint32_t src_op_chroma[] = {
-	PPP_ARRAY1(CHROMA_SAMP, SRC)
-};
-
-static uint32_t bg_op_chroma[] = {
-	PPP_ARRAY1(CHROMA_SAMP, BG)
-};
-
-static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
-	regs->dst0 += (req->dst_rect.w -
-		       min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
-	regs->dst1 += (req->dst_rect.w -
-		       min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
-}
-
-static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
-	regs->dst0 += (req->dst_rect.h -
-		       min((uint32_t)16, req->dst_rect.h)) *
-		       regs->dst_ystride;
-	regs->dst1 += (req->dst_rect.h -
-		       min((uint32_t)16, req->dst_rect.h)) *
-		       regs->dst_ystride;
-}
-
-static void blit_rotate(struct mdp_blit_req *req,
-			struct mdp_regs *regs)
-{
-	if (req->flags == MDP_ROT_NOP)
-		return;
-
-	regs->op |= PPP_OP_ROT_ON;
-	if ((req->flags & MDP_ROT_90 || req->flags & MDP_FLIP_LR) &&
-	    !(req->flags & MDP_ROT_90 && req->flags & MDP_FLIP_LR))
-		rotate_dst_addr_x(req, regs);
-	if (req->flags & MDP_ROT_90)
-		regs->op |= PPP_OP_ROT_90;
-	if (req->flags & MDP_FLIP_UD) {
-		regs->op |= PPP_OP_FLIP_UD;
-		rotate_dst_addr_y(req, regs);
-	}
-	if (req->flags & MDP_FLIP_LR)
-		regs->op |= PPP_OP_FLIP_LR;
-}
-
-static void blit_convert(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
-	if (req->src.format == req->dst.format)
-		return;
-	if (IS_RGB(req->src.format) && IS_YCRCB(req->dst.format)) {
-		regs->op |= PPP_OP_CONVERT_RGB2YCBCR | PPP_OP_CONVERT_ON;
-	} else if (IS_YCRCB(req->src.format) && IS_RGB(req->dst.format)) {
-		regs->op |= PPP_OP_CONVERT_YCBCR2RGB | PPP_OP_CONVERT_ON;
-		if (req->dst.format == MDP_RGB_565)
-			regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY;
-	}
-}
-
-#define GET_BIT_RANGE(value, high, low) \
-	(((1 << (high - low + 1)) - 1) & (value >> low))
-static uint32_t transp_convert(struct mdp_blit_req *req)
-{
-	uint32_t transp = 0;
-	if (req->src.format == MDP_RGB_565) {
-		/* pad each value to 8 bits by copying the high bits into the
-		 * low end, convert RGB to RBG by switching low 2 components */
-		transp |= ((GET_BIT_RANGE(req->transp_mask, 15, 11) << 3) |
-			   (GET_BIT_RANGE(req->transp_mask, 15, 13))) << 16;
-
-		transp |= ((GET_BIT_RANGE(req->transp_mask, 4, 0) << 3) |
-			   (GET_BIT_RANGE(req->transp_mask, 4, 2))) << 8;
-
-		transp |= (GET_BIT_RANGE(req->transp_mask, 10, 5) << 2) |
-			  (GET_BIT_RANGE(req->transp_mask, 10, 9));
-	} else {
-		/* convert RGB to RBG */
-		transp |= (GET_BIT_RANGE(req->transp_mask, 15, 8)) |
-			  (GET_BIT_RANGE(req->transp_mask, 23, 16) << 16) |
-			  (GET_BIT_RANGE(req->transp_mask, 7, 0) << 8);
-	}
-	return transp;
-}
-#undef GET_BIT_RANGE
-
-static void blit_blend(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
-	/* TRANSP BLEND */
-	if (req->transp_mask != MDP_TRANSP_NOP) {
-		req->transp_mask = transp_convert(req);
-		if (req->alpha != MDP_ALPHA_NOP) {
-			/* use blended transparancy mode
-			 * pixel = (src == transp) ? dst : blend
-			 * blend is combo of blend_eq_sel and
-			 * blend_alpha_sel */
-			regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
-				PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
-				PPP_OP_BLEND_CONSTANT_ALPHA |
-				PPP_BLEND_ALPHA_TRANSP;
-		} else {
-			/* simple transparancy mode
-			 * pixel = (src == transp) ? dst : src */
-			regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
-				PPP_OP_BLEND_SRCPIXEL_TRANSP;
-		}
-	}
-
-	req->alpha &= 0xff;
-	/* ALPHA BLEND */
-	if (HAS_ALPHA(req->src.format)) {
-		regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
-			PPP_OP_BLEND_SRCPIXEL_ALPHA;
-	} else if (req->alpha < MDP_ALPHA_NOP) {
-		/* just blend by alpha */
-		regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
-			PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
-			PPP_OP_BLEND_CONSTANT_ALPHA;
-	}
-
-	regs->op |= bg_op_chroma[req->dst.format];
-}
-
-#define ONE_HALF	(1LL << 32)
-#define ONE		(1LL << 33)
-#define TWO		(2LL << 33)
-#define THREE		(3LL << 33)
-#define FRAC_MASK (ONE - 1)
-#define INT_MASK (~FRAC_MASK)
-
-static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
-			uint32_t *phase_init, uint32_t *phase_step)
-{
-	/* to improve precicsion calculations are done in U31.33 and converted
-	 * to U3.29 at the end */
-	int64_t k1, k2, k3, k4, tmp;
-	uint64_t n, d, os, os_p, od, od_p, oreq;
-	unsigned rpa = 0;
-	int64_t ip64, delta;
-
-	if (dim_out % 3 == 0)
-		rpa = !(dim_in % (dim_out / 3));
-
-	n = ((uint64_t)dim_out) << 34;
-	d = dim_in;
-	if (!d)
-		return -1;
-	do_div(n, d);
-	k3 = (n + 1) >> 1;
-	if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) {
-		DLOG("crap bad scale\n");
-		return -1;
-	}
-	n = ((uint64_t)dim_in) << 34;
-	d = (uint64_t)dim_out;
-	if (!d)
-		return -1;
-	do_div(n, d);
-	k1 = (n + 1) >> 1;
-	k2 = (k1 - ONE) >> 1;
-
-	*phase_init = (int)(k2 >> 4);
-	k4 = (k3 - ONE) >> 1;
-
-	if (rpa) {
-		os = ((uint64_t)origin << 33) - ONE_HALF;
-		tmp = (dim_out * os) + ONE_HALF;
-		if (!dim_in)
-			return -1;
-		do_div(tmp, dim_in);
-		od = tmp - ONE_HALF;
-	} else {
-		os = ((uint64_t)origin << 1) - 1;
-		od = (((k3 * os) >> 1) + k4);
-	}
-
-	od_p = od & INT_MASK;
-	if (od_p != od)
-		od_p += ONE;
-
-	if (rpa) {
-		tmp = (dim_in * od_p) + ONE_HALF;
-		if (!dim_in)
-			return -1;
-		do_div(tmp, dim_in);
-		os_p = tmp - ONE_HALF;
-	} else {
-		os_p = ((k1 * (od_p >> 33)) + k2);
-	}
-
-	oreq = (os_p & INT_MASK) - ONE;
-
-	ip64 = os_p - oreq;
-	delta = ((int64_t)(origin) << 33) - oreq;
-	ip64 -= delta;
-	/* limit to valid range before the left shift */
-	delta = (ip64 & (1LL << 63)) ? 4 : -4;
-	delta <<= 33;
-	while (abs((int)(ip64 >> 33)) > 4)
-		ip64 += delta;
-	*phase_init = (int)(ip64 >> 4);
-	*phase_step = (uint32_t)(k1 >> 4);
-	return 0;
-}
-
-static void load_scale_table(const struct mdp_info *mdp,
-			     struct mdp_table_entry *table, int len)
-{
-	int i;
-	for (i = 0; i < len; i++)
-		mdp_writel(mdp, table[i].val, table[i].reg);
-}
-
-enum {
-IMG_LEFT,
-IMG_RIGHT,
-IMG_TOP,
-IMG_BOTTOM,
-};
-
-static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
-			  uint32_t *interp1, uint32_t *interp2,
-			  uint32_t *repeat1, uint32_t *repeat2) {
-	if (src > 3 * dst) {
-		*interp1 = 0;
-		*interp2 = src - 1;
-		*repeat1 = 0;
-		*repeat2 = 0;
-	} else if (src == 3 * dst) {
-		*interp1 = 0;
-		*interp2 = src;
-		*repeat1 = 0;
-		*repeat2 = 1;
-	} else if (src > dst && src < 3 * dst) {
-		*interp1 = -1;
-		*interp2 = src;
-		*repeat1 = 1;
-		*repeat2 = 1;
-	} else if (src == dst) {
-		*interp1 = -1;
-		*interp2 = src + 1;
-		*repeat1 = 1;
-		*repeat2 = 2;
-	} else {
-		*interp1 = -2;
-		*interp2 = src + 1;
-		*repeat1 = 2;
-		*repeat2 = 2;
-	}
-	*interp1 += src_coord;
-	*interp2 += src_coord;
-}
-
-static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs)
-{
-	int32_t luma_interp[4];
-	int32_t luma_repeat[4];
-	int32_t chroma_interp[4];
-	int32_t chroma_bound[4];
-	int32_t chroma_repeat[4];
-	uint32_t dst_w, dst_h;
-
-	memset(&luma_interp, 0, sizeof(int32_t) * 4);
-	memset(&luma_repeat, 0, sizeof(int32_t) * 4);
-	memset(&chroma_interp, 0, sizeof(int32_t) * 4);
-	memset(&chroma_bound, 0, sizeof(int32_t) * 4);
-	memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
-	regs->edge = 0;
-
-	if (req->flags & MDP_ROT_90) {
-		dst_w = req->dst_rect.h;
-		dst_h = req->dst_rect.w;
-	} else {
-		dst_w = req->dst_rect.w;
-		dst_h = req->dst_rect.h;
-	}
-
-	if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
-		get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
-			      &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
-			      &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
-		get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
-			      &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
-			      &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
-	} else {
-		luma_interp[IMG_LEFT] = req->src_rect.x;
-		luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
-		luma_interp[IMG_TOP] = req->src_rect.y;
-		luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
-		luma_repeat[IMG_LEFT] = 0;
-		luma_repeat[IMG_TOP] = 0;
-		luma_repeat[IMG_RIGHT] = 0;
-		luma_repeat[IMG_BOTTOM] = 0;
-	}
-
-	chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
-	chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
-	chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
-	chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
-
-	chroma_bound[IMG_LEFT] = req->src_rect.x;
-	chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
-	chroma_bound[IMG_TOP] = req->src_rect.y;
-	chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
-
-	if (IS_YCRCB(req->src.format)) {
-		chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
-		chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
-
-		chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
-		chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
-	}
-
-	if (req->src.format == MDP_Y_CBCR_H2V2 ||
-	    req->src.format == MDP_Y_CRCB_H2V2) {
-		chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
-		chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
-					    >> 1;
-		chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
-		chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
-	}
-
-	chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
-				  chroma_interp[IMG_LEFT];
-	chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
-				  chroma_bound[IMG_RIGHT];
-	chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
-				  chroma_interp[IMG_TOP];
-	chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
-				  chroma_bound[IMG_BOTTOM];
-
-	if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
-	    chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
-	    chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
-	    chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
-	    luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
-	    luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
-	    luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
-	    luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
-		return -1;
-
-	regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
-	regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
-	regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
-	regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
-	regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
-	regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
-	regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
-	regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
-	return 0;
-}
-
-static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
-		      struct mdp_regs *regs)
-{
-	uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
-	uint32_t scale_factor_x, scale_factor_y;
-	uint32_t downscale;
-	uint32_t dst_w, dst_h;
-
-	if (req->flags & MDP_ROT_90) {
-		dst_w = req->dst_rect.h;
-		dst_h = req->dst_rect.w;
-	} else {
-		dst_w = req->dst_rect.w;
-		dst_h = req->dst_rect.h;
-	}
-	if ((req->src_rect.w == dst_w)  && (req->src_rect.h == dst_h) &&
-	    !(req->flags & MDP_BLUR)) {
-		regs->phasex_init = 0;
-		regs->phasey_init = 0;
-		regs->phasex_step = 0;
-		regs->phasey_step = 0;
-		return 0;
-	}
-
-	if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x,
-			 &phase_step_x) ||
-	    scale_params(req->src_rect.h, dst_h, 1, &phase_init_y,
-			 &phase_step_y))
-		return -1;
-
-	scale_factor_x = (dst_w * 10) / req->src_rect.w;
-	scale_factor_y = (dst_h * 10) / req->src_rect.h;
-
-	if (scale_factor_x > 8)
-		downscale = MDP_DOWNSCALE_PT8TO1;
-	else if (scale_factor_x > 6)
-		downscale = MDP_DOWNSCALE_PT6TOPT8;
-	else if (scale_factor_x > 4)
-		downscale = MDP_DOWNSCALE_PT4TOPT6;
-	else
-		downscale = MDP_DOWNSCALE_PT2TOPT4;
-	if (downscale != downscale_x_table) {
-		load_scale_table(mdp, mdp_downscale_x_table[downscale], 64);
-		downscale_x_table = downscale;
-	}
-
-	if (scale_factor_y > 8)
-		downscale = MDP_DOWNSCALE_PT8TO1;
-	else if (scale_factor_y > 6)
-		downscale = MDP_DOWNSCALE_PT6TOPT8;
-	else if (scale_factor_y > 4)
-		downscale = MDP_DOWNSCALE_PT4TOPT6;
-	else
-		downscale = MDP_DOWNSCALE_PT2TOPT4;
-	if (downscale != downscale_y_table) {
-		load_scale_table(mdp, mdp_downscale_y_table[downscale], 64);
-		downscale_y_table = downscale;
-	}
-
-	regs->phasex_init = phase_init_x;
-	regs->phasey_init = phase_init_y;
-	regs->phasex_step = phase_step_x;
-	regs->phasey_step = phase_step_y;
-	regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
-	return 0;
-
-}
-
-static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
-		      struct mdp_regs *regs)
-{
-	if (!(req->flags & MDP_BLUR))
-		return;
-
-	if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
-	      downscale_y_table == MDP_DOWNSCALE_BLUR)) {
-		load_scale_table(mdp, mdp_gaussian_blur_table, 128);
-		downscale_x_table = MDP_DOWNSCALE_BLUR;
-		downscale_y_table = MDP_DOWNSCALE_BLUR;
-	}
-
-	regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
-}
-
-
-#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
-
-#define Y_TO_CRCB_RATIO(format) \
-	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
-	 (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
-
-static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
-		    uint32_t *len0, uint32_t *len1)
-{
-	*len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
-	if (IS_PSEUDOPLNR(img->format))
-		*len1 = *len0/Y_TO_CRCB_RATIO(img->format);
-	else
-		*len1 = 0;
-}
-
-static int valid_src_dst(unsigned long src_start, unsigned long src_len,
-			 unsigned long dst_start, unsigned long dst_len,
-			 struct mdp_blit_req *req, struct mdp_regs *regs)
-{
-	unsigned long src_min_ok = src_start;
-	unsigned long src_max_ok = src_start + src_len;
-	unsigned long dst_min_ok = dst_start;
-	unsigned long dst_max_ok = dst_start + dst_len;
-	uint32_t src0_len, src1_len, dst0_len, dst1_len;
-	get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
-		 &src1_len);
-	get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
-		 &dst1_len);
-
-	if (regs->src0 < src_min_ok || regs->src0 > src_max_ok ||
-	    regs->src0 + src0_len > src_max_ok) {
-		DLOG("invalid_src %x %x %lx %lx\n", regs->src0,
-		      src0_len, src_min_ok, src_max_ok);
-		return 0;
-	}
-	if (regs->src_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
-		if (regs->src1 < src_min_ok || regs->src1 > src_max_ok ||
-		    regs->src1 + src1_len > src_max_ok) {
-			DLOG("invalid_src1");
-			return 0;
-		}
-	}
-	if (regs->dst0 < dst_min_ok || regs->dst0 > dst_max_ok ||
-	    regs->dst0 + dst0_len > dst_max_ok) {
-		DLOG("invalid_dst");
-		return 0;
-	}
-	if (regs->dst_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
-		if (regs->dst1 < dst_min_ok || regs->dst1 > dst_max_ok ||
-		    regs->dst1 + dst1_len > dst_max_ok) {
-			DLOG("invalid_dst1");
-			return 0;
-		}
-	}
-	return 1;
-}
-
-
-static void flush_imgs(struct mdp_blit_req *req, struct mdp_regs *regs,
-		       struct file *src_file, struct file *dst_file)
-{
-}
-
-static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
-			    uint32_t base, uint32_t bpp, uint32_t cfg,
-			    uint32_t *addr, uint32_t *ystride)
-{
-	uint32_t compress_v = Y_TO_CRCB_RATIO(img->format);
-	uint32_t compress_h = 2;
-	uint32_t  offset;
-
-	if (IS_PSEUDOPLNR(img->format)) {
-		offset = (rect->x / compress_h) * compress_h;
-		offset += rect->y == 0 ? 0 :
-			  ((rect->y + 1) / compress_v) * img->width;
-		*addr = base + (img->width * img->height * bpp);
-		*addr += offset * bpp;
-		*ystride |= *ystride << 16;
-	} else {
-		*addr = 0;
-	}
-}
-
-static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
-		     struct mdp_regs *regs, struct file *src_file,
-		     struct file *dst_file)
-{
-	mdp_writel(mdp, 1, 0x060);
-	mdp_writel(mdp, regs->src_rect, PPP_ADDR_SRC_ROI);
-	mdp_writel(mdp, regs->src0, PPP_ADDR_SRC0);
-	mdp_writel(mdp, regs->src1, PPP_ADDR_SRC1);
-	mdp_writel(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE);
-	mdp_writel(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG);
-	mdp_writel(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN);
-
-	mdp_writel(mdp, regs->op, PPP_ADDR_OPERATION);
-	mdp_writel(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT);
-	mdp_writel(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT);
-	mdp_writel(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
-	mdp_writel(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);
-
-	mdp_writel(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
-	       PPP_ADDR_ALPHA_TRANSP);
-
-	mdp_writel(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG);
-	mdp_writel(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN);
-	mdp_writel(mdp, regs->dst_rect, PPP_ADDR_DST_ROI);
-	mdp_writel(mdp, regs->dst0, PPP_ADDR_DST0);
-	mdp_writel(mdp, regs->dst1, PPP_ADDR_DST1);
-	mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE);
-
-	mdp_writel(mdp, regs->edge, PPP_ADDR_EDGE);
-	if (regs->op & PPP_OP_BLEND_ON) {
-		mdp_writel(mdp, regs->dst0, PPP_ADDR_BG0);
-		mdp_writel(mdp, regs->dst1, PPP_ADDR_BG1);
-		mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_BG_YSTRIDE);
-		mdp_writel(mdp, src_img_cfg[req->dst.format], PPP_ADDR_BG_CFG);
-		mdp_writel(mdp, pack_pattern[req->dst.format],
-			   PPP_ADDR_BG_PACK_PATTERN);
-	}
-	flush_imgs(req, regs, src_file, dst_file);
-	mdp_writel(mdp, 0x1000, MDP_DISPLAY0_START);
-	return 0;
-}
-
-int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
-		 struct file *src_file, unsigned long src_start, unsigned long src_len,
-		 struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
-{
-	struct mdp_regs regs = {0};
-
-	if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
-		     req->dst.format >= MDP_IMGTYPE_LIMIT)) {
-		printk(KERN_ERR "mpd_ppp: img is of wrong format\n");
-		return -EINVAL;
-	}
-
-	if (unlikely(req->src_rect.x > req->src.width ||
-		     req->src_rect.y > req->src.height ||
-		     req->dst_rect.x > req->dst.width ||
-		     req->dst_rect.y > req->dst.height)) {
-		printk(KERN_ERR "mpd_ppp: img rect is outside of img!\n");
-		return -EINVAL;
-	}
-
-	/* set the src image configuration */
-	regs.src_cfg = src_img_cfg[req->src.format];
-	regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0;
-	regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
-	regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w;
-	regs.src_pack = pack_pattern[req->src.format];
-
-	/* set the dest image configuration */
-	regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI;
-	regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w;
-	regs.dst_pack = pack_pattern[req->dst.format];
-
-	/* set src, bpp, start pixel and ystride */
-	regs.src_bpp = bytes_per_pixel[req->src.format];
-	regs.src0 = src_start + req->src.offset;
-	regs.src_ystride = req->src.width * regs.src_bpp;
-	get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
-			regs.src_cfg, &regs.src1, &regs.src_ystride);
-	regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) *
-		      regs.src_bpp;
-
-	/* set dst, bpp, start pixel and ystride */
-	regs.dst_bpp = bytes_per_pixel[req->dst.format];
-	regs.dst0 = dst_start + req->dst.offset;
-	regs.dst_ystride = req->dst.width * regs.dst_bpp;
-	get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
-			regs.dst_cfg, &regs.dst1, &regs.dst_ystride);
-	regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) *
-		      regs.dst_bpp;
-
-	if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
-			   &regs)) {
-		printk(KERN_ERR "mpd_ppp: final src or dst location is "
-			"invalid, are you trying to make an image too large "
-			"or to place it outside the screen?\n");
-		return -EINVAL;
-	}
-
-	/* set up operation register */
-	regs.op = 0;
-	blit_rotate(req, &regs);
-	blit_convert(req, &regs);
-	if (req->flags & MDP_DITHER)
-		regs.op |= PPP_OP_DITHER_EN;
-	blit_blend(req, &regs);
-	if (blit_scale(mdp, req, &regs)) {
-		printk(KERN_ERR "mpd_ppp: error computing scale for img.\n");
-		return -EINVAL;
-	}
-	blit_blur(mdp, req, &regs);
-	regs.op |= dst_op_chroma[req->dst.format] |
-		   src_op_chroma[req->src.format];
-
-	/* if the image is YCRYCB, the x and w must be even */
-	if (unlikely(req->src.format == MDP_YCRYCB_H2V1)) {
-		req->src_rect.x = req->src_rect.x & (~0x1);
-		req->src_rect.w = req->src_rect.w & (~0x1);
-		req->dst_rect.x = req->dst_rect.x & (~0x1);
-		req->dst_rect.w = req->dst_rect.w & (~0x1);
-	}
-	if (get_edge_cond(req, &regs))
-		return -EINVAL;
-
-	send_blit(mdp, req, &regs, src_file, dst_file);
-	return 0;
-}
diff --git a/drivers/video/msm/mdp_scale_tables.c b/drivers/video/msm/mdp_scale_tables.c
deleted file mode 100644
index 604783b2e17c..000000000000
--- a/drivers/video/msm/mdp_scale_tables.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/* drivers/video/msm_fb/mdp_scale_tables.c
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include "mdp_scale_tables.h"
-#include "mdp_hw.h"
-
-struct mdp_table_entry mdp_upscale_table[] = {
-	{ 0x5fffc, 0x0 },
-	{ 0x50200, 0x7fc00000 },
-	{ 0x5fffc, 0xff80000d },
-	{ 0x50204, 0x7ec003f9 },
-	{ 0x5fffc, 0xfec0001c },
-	{ 0x50208, 0x7d4003f3 },
-	{ 0x5fffc, 0xfe40002b },
-	{ 0x5020c, 0x7b8003ed },
-	{ 0x5fffc, 0xfd80003c },
-	{ 0x50210, 0x794003e8 },
-	{ 0x5fffc, 0xfcc0004d },
-	{ 0x50214, 0x76c003e4 },
-	{ 0x5fffc, 0xfc40005f },
-	{ 0x50218, 0x73c003e0 },
-	{ 0x5fffc, 0xfb800071 },
-	{ 0x5021c, 0x708003de },
-	{ 0x5fffc, 0xfac00085 },
-	{ 0x50220, 0x6d0003db },
-	{ 0x5fffc, 0xfa000098 },
-	{ 0x50224, 0x698003d9 },
-	{ 0x5fffc, 0xf98000ac },
-	{ 0x50228, 0x654003d8 },
-	{ 0x5fffc, 0xf8c000c1 },
-	{ 0x5022c, 0x610003d7 },
-	{ 0x5fffc, 0xf84000d5 },
-	{ 0x50230, 0x5c8003d7 },
-	{ 0x5fffc, 0xf7c000e9 },
-	{ 0x50234, 0x580003d7 },
-	{ 0x5fffc, 0xf74000fd },
-	{ 0x50238, 0x534003d8 },
-	{ 0x5fffc, 0xf6c00112 },
-	{ 0x5023c, 0x4e8003d8 },
-	{ 0x5fffc, 0xf6800126 },
-	{ 0x50240, 0x494003da },
-	{ 0x5fffc, 0xf600013a },
-	{ 0x50244, 0x448003db },
-	{ 0x5fffc, 0xf600014d },
-	{ 0x50248, 0x3f4003dd },
-	{ 0x5fffc, 0xf5c00160 },
-	{ 0x5024c, 0x3a4003df },
-	{ 0x5fffc, 0xf5c00172 },
-	{ 0x50250, 0x354003e1 },
-	{ 0x5fffc, 0xf5c00184 },
-	{ 0x50254, 0x304003e3 },
-	{ 0x5fffc, 0xf6000195 },
-	{ 0x50258, 0x2b0003e6 },
-	{ 0x5fffc, 0xf64001a6 },
-	{ 0x5025c, 0x260003e8 },
-	{ 0x5fffc, 0xf6c001b4 },
-	{ 0x50260, 0x214003eb },
-	{ 0x5fffc, 0xf78001c2 },
-	{ 0x50264, 0x1c4003ee },
-	{ 0x5fffc, 0xf80001cf },
-	{ 0x50268, 0x17c003f1 },
-	{ 0x5fffc, 0xf90001db },
-	{ 0x5026c, 0x134003f3 },
-	{ 0x5fffc, 0xfa0001e5 },
-	{ 0x50270, 0xf0003f6 },
-	{ 0x5fffc, 0xfb4001ee },
-	{ 0x50274, 0xac003f9 },
-	{ 0x5fffc, 0xfcc001f5 },
-	{ 0x50278, 0x70003fb },
-	{ 0x5fffc, 0xfe4001fb },
-	{ 0x5027c, 0x34003fe },
-};
-
-static struct mdp_table_entry mdp_downscale_x_table_PT2TOPT4[] = {
-	{ 0x5fffc, 0x740008c },
-	{ 0x50280, 0x33800088 },
-	{ 0x5fffc, 0x800008e },
-	{ 0x50284, 0x33400084 },
-	{ 0x5fffc, 0x8400092 },
-	{ 0x50288, 0x33000080 },
-	{ 0x5fffc, 0x9000094 },
-	{ 0x5028c, 0x3300007b },
-	{ 0x5fffc, 0x9c00098 },
-	{ 0x50290, 0x32400077 },
-	{ 0x5fffc, 0xa40009b },
-	{ 0x50294, 0x32000073 },
-	{ 0x5fffc, 0xb00009d },
-	{ 0x50298,  0x31c0006f },
-	{ 0x5fffc,  0xbc000a0 },
-	{ 0x5029c,  0x3140006b },
-	{ 0x5fffc,  0xc8000a2 },
-	{ 0x502a0,  0x31000067 },
-	{ 0x5fffc,  0xd8000a5 },
-	{ 0x502a4,  0x30800062 },
-	{ 0x5fffc,  0xe4000a8 },
-	{ 0x502a8,  0x2fc0005f },
-	{ 0x5fffc,  0xec000aa },
-	{ 0x502ac,  0x2fc0005b },
-	{ 0x5fffc,  0xf8000ad },
-	{ 0x502b0,  0x2f400057 },
-	{ 0x5fffc,  0x108000b0 },
-	{ 0x502b4,  0x2e400054 },
-	{ 0x5fffc,  0x114000b2 },
-	{ 0x502b8,  0x2e000050 },
-	{ 0x5fffc,  0x124000b4 },
-	{ 0x502bc,  0x2d80004c },
-	{ 0x5fffc,  0x130000b6 },
-	{ 0x502c0,  0x2d000049 },
-	{ 0x5fffc,  0x140000b8 },
-	{ 0x502c4,  0x2c800045 },
-	{ 0x5fffc,  0x150000b9 },
-	{ 0x502c8,  0x2c000042 },
-	{ 0x5fffc,  0x15c000bd },
-	{ 0x502cc,  0x2b40003e },
-	{ 0x5fffc,  0x16c000bf },
-	{ 0x502d0,  0x2a80003b },
-	{ 0x5fffc,  0x17c000bf },
-	{ 0x502d4,  0x2a000039 },
-	{ 0x5fffc,  0x188000c2 },
-	{ 0x502d8,  0x29400036 },
-	{ 0x5fffc,  0x19c000c4 },
-	{ 0x502dc,  0x28800032 },
-	{ 0x5fffc,  0x1ac000c5 },
-	{ 0x502e0,  0x2800002f },
-	{ 0x5fffc,  0x1bc000c7 },
-	{ 0x502e4,  0x2740002c },
-	{ 0x5fffc,  0x1cc000c8 },
-	{ 0x502e8,  0x26c00029 },
-	{ 0x5fffc,  0x1dc000c9 },
-	{ 0x502ec,  0x26000027 },
-	{ 0x5fffc,  0x1ec000cc },
-	{ 0x502f0,  0x25000024 },
-	{ 0x5fffc,  0x200000cc },
-	{ 0x502f4,  0x24800021 },
-	{ 0x5fffc,  0x210000cd },
-	{ 0x502f8,  0x23800020 },
-	{ 0x5fffc,  0x220000ce },
-	{ 0x502fc,  0x2300001d },
-};
-
-static struct mdp_table_entry mdp_downscale_x_table_PT4TOPT6[] = {
-	{ 0x5fffc,  0x740008c },
-	{ 0x50280,  0x33800088 },
-	{ 0x5fffc,  0x800008e },
-	{ 0x50284,  0x33400084 },
-	{ 0x5fffc,  0x8400092 },
-	{ 0x50288,  0x33000080 },
-	{ 0x5fffc,  0x9000094 },
-	{ 0x5028c,  0x3300007b },
-	{ 0x5fffc,  0x9c00098 },
-	{ 0x50290,  0x32400077 },
-	{ 0x5fffc,  0xa40009b },
-	{ 0x50294,  0x32000073 },
-	{ 0x5fffc,  0xb00009d },
-	{ 0x50298,  0x31c0006f },
-	{ 0x5fffc,  0xbc000a0 },
-	{ 0x5029c,  0x3140006b },
-	{ 0x5fffc,  0xc8000a2 },
-	{ 0x502a0,  0x31000067 },
-	{ 0x5fffc,  0xd8000a5 },
-	{ 0x502a4,  0x30800062 },
-	{ 0x5fffc,  0xe4000a8 },
-	{ 0x502a8,  0x2fc0005f },
-	{ 0x5fffc,  0xec000aa },
-	{ 0x502ac,  0x2fc0005b },
-	{ 0x5fffc,  0xf8000ad },
-	{ 0x502b0,  0x2f400057 },
-	{ 0x5fffc,  0x108000b0 },
-	{ 0x502b4,  0x2e400054 },
-	{ 0x5fffc,  0x114000b2 },
-	{ 0x502b8,  0x2e000050 },
-	{ 0x5fffc,  0x124000b4 },
-	{ 0x502bc,  0x2d80004c },
-	{ 0x5fffc,  0x130000b6 },
-	{ 0x502c0,  0x2d000049 },
-	{ 0x5fffc,  0x140000b8 },
-	{ 0x502c4,  0x2c800045 },
-	{ 0x5fffc,  0x150000b9 },
-	{ 0x502c8,  0x2c000042 },
-	{ 0x5fffc,  0x15c000bd },
-	{ 0x502cc,  0x2b40003e },
-	{ 0x5fffc,  0x16c000bf },
-	{ 0x502d0,  0x2a80003b },
-	{ 0x5fffc,  0x17c000bf },
-	{ 0x502d4,  0x2a000039 },
-	{ 0x5fffc,  0x188000c2 },
-	{ 0x502d8,  0x29400036 },
-	{ 0x5fffc,  0x19c000c4 },
-	{ 0x502dc,  0x28800032 },
-	{ 0x5fffc,  0x1ac000c5 },
-	{ 0x502e0,  0x2800002f },
-	{ 0x5fffc,  0x1bc000c7 },
-	{ 0x502e4,  0x2740002c },
-	{ 0x5fffc,  0x1cc000c8 },
-	{ 0x502e8,  0x26c00029 },
-	{ 0x5fffc,  0x1dc000c9 },
-	{ 0x502ec,  0x26000027 },
-	{ 0x5fffc,  0x1ec000cc },
-	{ 0x502f0,  0x25000024 },
-	{ 0x5fffc,  0x200000cc },
-	{ 0x502f4,  0x24800021 },
-	{ 0x5fffc,  0x210000cd },
-	{ 0x502f8,  0x23800020 },
-	{ 0x5fffc,  0x220000ce },
-	{ 0x502fc,  0x2300001d },
-};
-
-static struct mdp_table_entry mdp_downscale_x_table_PT6TOPT8[] = {
-	{ 0x5fffc,  0xfe000070 },
-	{ 0x50280,  0x4bc00068 },
-	{ 0x5fffc,  0xfe000078 },
-	{ 0x50284,  0x4bc00060 },
-	{ 0x5fffc,  0xfe000080 },
-	{ 0x50288,  0x4b800059 },
-	{ 0x5fffc,  0xfe000089 },
-	{ 0x5028c,  0x4b000052 },
-	{ 0x5fffc,  0xfe400091 },
-	{ 0x50290,  0x4a80004b },
-	{ 0x5fffc,  0xfe40009a },
-	{ 0x50294,  0x4a000044 },
-	{ 0x5fffc,  0xfe8000a3 },
-	{ 0x50298,  0x4940003d },
-	{ 0x5fffc,  0xfec000ac },
-	{ 0x5029c,  0x48400037 },
-	{ 0x5fffc,  0xff0000b4 },
-	{ 0x502a0,  0x47800031 },
-	{ 0x5fffc,  0xff8000bd },
-	{ 0x502a4,  0x4640002b },
-	{ 0x5fffc,  0xc5 },
-	{ 0x502a8,  0x45000026 },
-	{ 0x5fffc,  0x8000ce },
-	{ 0x502ac,  0x43800021 },
-	{ 0x5fffc,  0x10000d6 },
-	{ 0x502b0,  0x4240001c },
-	{ 0x5fffc,  0x18000df },
-	{ 0x502b4,  0x40800018 },
-	{ 0x5fffc,  0x24000e6 },
-	{ 0x502b8,  0x3f000014 },
-	{ 0x5fffc,  0x30000ee },
-	{ 0x502bc,  0x3d400010 },
-	{ 0x5fffc,  0x40000f5 },
-	{ 0x502c0,  0x3b80000c },
-	{ 0x5fffc,  0x50000fc },
-	{ 0x502c4,  0x39800009 },
-	{ 0x5fffc,  0x6000102 },
-	{ 0x502c8,  0x37c00006 },
-	{ 0x5fffc,  0x7000109 },
-	{ 0x502cc,  0x35800004 },
-	{ 0x5fffc,  0x840010e },
-	{ 0x502d0,  0x33800002 },
-	{ 0x5fffc,  0x9800114 },
-	{ 0x502d4,  0x31400000 },
-	{ 0x5fffc,  0xac00119 },
-	{ 0x502d8,  0x2f4003fe },
-	{ 0x5fffc,  0xc40011e },
-	{ 0x502dc,  0x2d0003fc },
-	{ 0x5fffc,  0xdc00121 },
-	{ 0x502e0,  0x2b0003fb },
-	{ 0x5fffc,  0xf400125 },
-	{ 0x502e4,  0x28c003fa },
-	{ 0x5fffc,  0x11000128 },
-	{ 0x502e8,  0x268003f9 },
-	{ 0x5fffc,  0x12c0012a },
-	{ 0x502ec,  0x244003f9 },
-	{ 0x5fffc,  0x1480012c },
-	{ 0x502f0,  0x224003f8 },
-	{ 0x5fffc,  0x1640012e },
-	{ 0x502f4,  0x200003f8 },
-	{ 0x5fffc,  0x1800012f },
-	{ 0x502f8,  0x1e0003f8 },
-	{ 0x5fffc,  0x1a00012f },
-	{ 0x502fc,  0x1c0003f8 },
-};
-
-static struct mdp_table_entry mdp_downscale_x_table_PT8TO1[] = {
-	{ 0x5fffc,  0x0 },
-	{ 0x50280,  0x7fc00000 },
-	{ 0x5fffc,  0xff80000d },
-	{ 0x50284,  0x7ec003f9 },
-	{ 0x5fffc,  0xfec0001c },
-	{ 0x50288,  0x7d4003f3 },
-	{ 0x5fffc,  0xfe40002b },
-	{ 0x5028c,  0x7b8003ed },
-	{ 0x5fffc,  0xfd80003c },
-	{ 0x50290,  0x794003e8 },
-	{ 0x5fffc,  0xfcc0004d },
-	{ 0x50294,  0x76c003e4 },
-	{ 0x5fffc,  0xfc40005f },
-	{ 0x50298,  0x73c003e0 },
-	{ 0x5fffc,  0xfb800071 },
-	{ 0x5029c,  0x708003de },
-	{ 0x5fffc,  0xfac00085 },
-	{ 0x502a0,  0x6d0003db },
-	{ 0x5fffc,  0xfa000098 },
-	{ 0x502a4,  0x698003d9 },
-	{ 0x5fffc,  0xf98000ac },
-	{ 0x502a8,  0x654003d8 },
-	{ 0x5fffc,  0xf8c000c1 },
-	{ 0x502ac,  0x610003d7 },
-	{ 0x5fffc,  0xf84000d5 },
-	{ 0x502b0,  0x5c8003d7 },
-	{ 0x5fffc,  0xf7c000e9 },
-	{ 0x502b4,  0x580003d7 },
-	{ 0x5fffc,  0xf74000fd },
-	{ 0x502b8,  0x534003d8 },
-	{ 0x5fffc,  0xf6c00112 },
-	{ 0x502bc,  0x4e8003d8 },
-	{ 0x5fffc,  0xf6800126 },
-	{ 0x502c0,  0x494003da },
-	{ 0x5fffc,  0xf600013a },
-	{ 0x502c4,  0x448003db },
-	{ 0x5fffc,  0xf600014d },
-	{ 0x502c8,  0x3f4003dd },
-	{ 0x5fffc,  0xf5c00160 },
-	{ 0x502cc,  0x3a4003df },
-	{ 0x5fffc,  0xf5c00172 },
-	{ 0x502d0,  0x354003e1 },
-	{ 0x5fffc,  0xf5c00184 },
-	{ 0x502d4,  0x304003e3 },
-	{ 0x5fffc,  0xf6000195 },
-	{ 0x502d8,  0x2b0003e6 },
-	{ 0x5fffc,  0xf64001a6 },
-	{ 0x502dc,  0x260003e8 },
-	{ 0x5fffc,  0xf6c001b4 },
-	{ 0x502e0,  0x214003eb },
-	{ 0x5fffc,  0xf78001c2 },
-	{ 0x502e4,  0x1c4003ee },
-	{ 0x5fffc,  0xf80001cf },
-	{ 0x502e8,  0x17c003f1 },
-	{ 0x5fffc,  0xf90001db },
-	{ 0x502ec,  0x134003f3 },
-	{ 0x5fffc,  0xfa0001e5 },
-	{ 0x502f0,  0xf0003f6 },
-	{ 0x5fffc,  0xfb4001ee },
-	{ 0x502f4,  0xac003f9 },
-	{ 0x5fffc,  0xfcc001f5 },
-	{ 0x502f8,  0x70003fb },
-	{ 0x5fffc,  0xfe4001fb },
-	{ 0x502fc,  0x34003fe },
-};
-
-struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX] = {
-	[MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_x_table_PT2TOPT4,
-	[MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_x_table_PT4TOPT6,
-	[MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_x_table_PT6TOPT8,
-	[MDP_DOWNSCALE_PT8TO1]  = mdp_downscale_x_table_PT8TO1,
-};
-
-static struct mdp_table_entry mdp_downscale_y_table_PT2TOPT4[] = {
-	{ 0x5fffc,  0x740008c },
-	{ 0x50300,  0x33800088 },
-	{ 0x5fffc,  0x800008e },
-	{ 0x50304,  0x33400084 },
-	{ 0x5fffc,  0x8400092 },
-	{ 0x50308,  0x33000080 },
-	{ 0x5fffc,  0x9000094 },
-	{ 0x5030c,  0x3300007b },
-	{ 0x5fffc,  0x9c00098 },
-	{ 0x50310,  0x32400077 },
-	{ 0x5fffc,  0xa40009b },
-	{ 0x50314,  0x32000073 },
-	{ 0x5fffc,  0xb00009d },
-	{ 0x50318,  0x31c0006f },
-	{ 0x5fffc,  0xbc000a0 },
-	{ 0x5031c,  0x3140006b },
-	{ 0x5fffc,  0xc8000a2 },
-	{ 0x50320,  0x31000067 },
-	{ 0x5fffc,  0xd8000a5 },
-	{ 0x50324,  0x30800062 },
-	{ 0x5fffc,  0xe4000a8 },
-	{ 0x50328,  0x2fc0005f },
-	{ 0x5fffc,  0xec000aa },
-	{ 0x5032c,  0x2fc0005b },
-	{ 0x5fffc,  0xf8000ad },
-	{ 0x50330,  0x2f400057 },
-	{ 0x5fffc,  0x108000b0 },
-	{ 0x50334,  0x2e400054 },
-	{ 0x5fffc,  0x114000b2 },
-	{ 0x50338,  0x2e000050 },
-	{ 0x5fffc,  0x124000b4 },
-	{ 0x5033c,  0x2d80004c },
-	{ 0x5fffc,  0x130000b6 },
-	{ 0x50340,  0x2d000049 },
-	{ 0x5fffc,  0x140000b8 },
-	{ 0x50344,  0x2c800045 },
-	{ 0x5fffc,  0x150000b9 },
-	{ 0x50348,  0x2c000042 },
-	{ 0x5fffc,  0x15c000bd },
-	{ 0x5034c,  0x2b40003e },
-	{ 0x5fffc,  0x16c000bf },
-	{ 0x50350,  0x2a80003b },
-	{ 0x5fffc,  0x17c000bf },
-	{ 0x50354,  0x2a000039 },
-	{ 0x5fffc,  0x188000c2 },
-	{ 0x50358,  0x29400036 },
-	{ 0x5fffc,  0x19c000c4 },
-	{ 0x5035c,  0x28800032 },
-	{ 0x5fffc,  0x1ac000c5 },
-	{ 0x50360,  0x2800002f },
-	{ 0x5fffc,  0x1bc000c7 },
-	{ 0x50364,  0x2740002c },
-	{ 0x5fffc,  0x1cc000c8 },
-	{ 0x50368,  0x26c00029 },
-	{ 0x5fffc,  0x1dc000c9 },
-	{ 0x5036c,  0x26000027 },
-	{ 0x5fffc,  0x1ec000cc },
-	{ 0x50370,  0x25000024 },
-	{ 0x5fffc,  0x200000cc },
-	{ 0x50374,  0x24800021 },
-	{ 0x5fffc,  0x210000cd },
-	{ 0x50378,  0x23800020 },
-	{ 0x5fffc,  0x220000ce },
-	{ 0x5037c,  0x2300001d },
-};
-
-static struct mdp_table_entry mdp_downscale_y_table_PT4TOPT6[] = {
-	{ 0x5fffc,  0x740008c },
-	{ 0x50300,  0x33800088 },
-	{ 0x5fffc,  0x800008e },
-	{ 0x50304,  0x33400084 },
-	{ 0x5fffc,  0x8400092 },
-	{ 0x50308,  0x33000080 },
-	{ 0x5fffc,  0x9000094 },
-	{ 0x5030c,  0x3300007b },
-	{ 0x5fffc,  0x9c00098 },
-	{ 0x50310,  0x32400077 },
-	{ 0x5fffc,  0xa40009b },
-	{ 0x50314,  0x32000073 },
-	{ 0x5fffc,  0xb00009d },
-	{ 0x50318,  0x31c0006f },
-	{ 0x5fffc,  0xbc000a0 },
-	{ 0x5031c,  0x3140006b },
-	{ 0x5fffc,  0xc8000a2 },
-	{ 0x50320,  0x31000067 },
-	{ 0x5fffc,  0xd8000a5 },
-	{ 0x50324,  0x30800062 },
-	{ 0x5fffc,  0xe4000a8 },
-	{ 0x50328,  0x2fc0005f },
-	{ 0x5fffc,  0xec000aa },
-	{ 0x5032c,  0x2fc0005b },
-	{ 0x5fffc,  0xf8000ad },
-	{ 0x50330,  0x2f400057 },
-	{ 0x5fffc,  0x108000b0 },
-	{ 0x50334,  0x2e400054 },
-	{ 0x5fffc,  0x114000b2 },
-	{ 0x50338,  0x2e000050 },
-	{ 0x5fffc,  0x124000b4 },
-	{ 0x5033c,  0x2d80004c },
-	{ 0x5fffc,  0x130000b6 },
-	{ 0x50340,  0x2d000049 },
-	{ 0x5fffc,  0x140000b8 },
-	{ 0x50344,  0x2c800045 },
-	{ 0x5fffc,  0x150000b9 },
-	{ 0x50348,  0x2c000042 },
-	{ 0x5fffc,  0x15c000bd },
-	{ 0x5034c,  0x2b40003e },
-	{ 0x5fffc,  0x16c000bf },
-	{ 0x50350,  0x2a80003b },
-	{ 0x5fffc,  0x17c000bf },
-	{ 0x50354,  0x2a000039 },
-	{ 0x5fffc,  0x188000c2 },
-	{ 0x50358,  0x29400036 },
-	{ 0x5fffc,  0x19c000c4 },
-	{ 0x5035c,  0x28800032 },
-	{ 0x5fffc,  0x1ac000c5 },
-	{ 0x50360,  0x2800002f },
-	{ 0x5fffc,  0x1bc000c7 },
-	{ 0x50364,  0x2740002c },
-	{ 0x5fffc,  0x1cc000c8 },
-	{ 0x50368,  0x26c00029 },
-	{ 0x5fffc,  0x1dc000c9 },
-	{ 0x5036c,  0x26000027 },
-	{ 0x5fffc,  0x1ec000cc },
-	{ 0x50370,  0x25000024 },
-	{ 0x5fffc,  0x200000cc },
-	{ 0x50374,  0x24800021 },
-	{ 0x5fffc,  0x210000cd },
-	{ 0x50378,  0x23800020 },
-	{ 0x5fffc,  0x220000ce },
-	{ 0x5037c,  0x2300001d },
-};
-
-static struct mdp_table_entry mdp_downscale_y_table_PT6TOPT8[] = {
-	{ 0x5fffc,  0xfe000070 },
-	{ 0x50300,  0x4bc00068 },
-	{ 0x5fffc,  0xfe000078 },
-	{ 0x50304,  0x4bc00060 },
-	{ 0x5fffc,  0xfe000080 },
-	{ 0x50308,  0x4b800059 },
-	{ 0x5fffc,  0xfe000089 },
-	{ 0x5030c,  0x4b000052 },
-	{ 0x5fffc,  0xfe400091 },
-	{ 0x50310,  0x4a80004b },
-	{ 0x5fffc,  0xfe40009a },
-	{ 0x50314,  0x4a000044 },
-	{ 0x5fffc,  0xfe8000a3 },
-	{ 0x50318,  0x4940003d },
-	{ 0x5fffc,  0xfec000ac },
-	{ 0x5031c,  0x48400037 },
-	{ 0x5fffc,  0xff0000b4 },
-	{ 0x50320,  0x47800031 },
-	{ 0x5fffc,  0xff8000bd },
-	{ 0x50324,  0x4640002b },
-	{ 0x5fffc,  0xc5 },
-	{ 0x50328,  0x45000026 },
-	{ 0x5fffc,  0x8000ce },
-	{ 0x5032c,  0x43800021 },
-	{ 0x5fffc,  0x10000d6 },
-	{ 0x50330,  0x4240001c },
-	{ 0x5fffc,  0x18000df },
-	{ 0x50334,  0x40800018 },
-	{ 0x5fffc,  0x24000e6 },
-	{ 0x50338,  0x3f000014 },
-	{ 0x5fffc,  0x30000ee },
-	{ 0x5033c,  0x3d400010 },
-	{ 0x5fffc,  0x40000f5 },
-	{ 0x50340,  0x3b80000c },
-	{ 0x5fffc,  0x50000fc },
-	{ 0x50344,  0x39800009 },
-	{ 0x5fffc,  0x6000102 },
-	{ 0x50348,  0x37c00006 },
-	{ 0x5fffc,  0x7000109 },
-	{ 0x5034c,  0x35800004 },
-	{ 0x5fffc,  0x840010e },
-	{ 0x50350,  0x33800002 },
-	{ 0x5fffc,  0x9800114 },
-	{ 0x50354,  0x31400000 },
-	{ 0x5fffc,  0xac00119 },
-	{ 0x50358,  0x2f4003fe },
-	{ 0x5fffc,  0xc40011e },
-	{ 0x5035c,  0x2d0003fc },
-	{ 0x5fffc,  0xdc00121 },
-	{ 0x50360,  0x2b0003fb },
-	{ 0x5fffc,  0xf400125 },
-	{ 0x50364,  0x28c003fa },
-	{ 0x5fffc,  0x11000128 },
-	{ 0x50368,  0x268003f9 },
-	{ 0x5fffc,  0x12c0012a },
-	{ 0x5036c,  0x244003f9 },
-	{ 0x5fffc,  0x1480012c },
-	{ 0x50370,  0x224003f8 },
-	{ 0x5fffc,  0x1640012e },
-	{ 0x50374,  0x200003f8 },
-	{ 0x5fffc,  0x1800012f },
-	{ 0x50378,  0x1e0003f8 },
-	{ 0x5fffc,  0x1a00012f },
-	{ 0x5037c,  0x1c0003f8 },
-};
-
-static struct mdp_table_entry mdp_downscale_y_table_PT8TO1[] = {
-	{ 0x5fffc,  0x0 },
-	{ 0x50300,  0x7fc00000 },
-	{ 0x5fffc,  0xff80000d },
-	{ 0x50304,  0x7ec003f9 },
-	{ 0x5fffc,  0xfec0001c },
-	{ 0x50308,  0x7d4003f3 },
-	{ 0x5fffc,  0xfe40002b },
-	{ 0x5030c,  0x7b8003ed },
-	{ 0x5fffc,  0xfd80003c },
-	{ 0x50310,  0x794003e8 },
-	{ 0x5fffc,  0xfcc0004d },
-	{ 0x50314,  0x76c003e4 },
-	{ 0x5fffc,  0xfc40005f },
-	{ 0x50318,  0x73c003e0 },
-	{ 0x5fffc,  0xfb800071 },
-	{ 0x5031c,  0x708003de },
-	{ 0x5fffc,  0xfac00085 },
-	{ 0x50320,  0x6d0003db },
-	{ 0x5fffc,  0xfa000098 },
-	{ 0x50324,  0x698003d9 },
-	{ 0x5fffc,  0xf98000ac },
-	{ 0x50328,  0x654003d8 },
-	{ 0x5fffc,  0xf8c000c1 },
-	{ 0x5032c,  0x610003d7 },
-	{ 0x5fffc,  0xf84000d5 },
-	{ 0x50330,  0x5c8003d7 },
-	{ 0x5fffc,  0xf7c000e9 },
-	{ 0x50334,  0x580003d7 },
-	{ 0x5fffc,  0xf74000fd },
-	{ 0x50338,  0x534003d8 },
-	{ 0x5fffc,  0xf6c00112 },
-	{ 0x5033c,  0x4e8003d8 },
-	{ 0x5fffc,  0xf6800126 },
-	{ 0x50340,  0x494003da },
-	{ 0x5fffc,  0xf600013a },
-	{ 0x50344,  0x448003db },
-	{ 0x5fffc,  0xf600014d },
-	{ 0x50348,  0x3f4003dd },
-	{ 0x5fffc,  0xf5c00160 },
-	{ 0x5034c,  0x3a4003df },
-	{ 0x5fffc,  0xf5c00172 },
-	{ 0x50350,  0x354003e1 },
-	{ 0x5fffc,  0xf5c00184 },
-	{ 0x50354,  0x304003e3 },
-	{ 0x5fffc,  0xf6000195 },
-	{ 0x50358,  0x2b0003e6 },
-	{ 0x5fffc,  0xf64001a6 },
-	{ 0x5035c,  0x260003e8 },
-	{ 0x5fffc,  0xf6c001b4 },
-	{ 0x50360,  0x214003eb },
-	{ 0x5fffc,  0xf78001c2 },
-	{ 0x50364,  0x1c4003ee },
-	{ 0x5fffc,  0xf80001cf },
-	{ 0x50368,  0x17c003f1 },
-	{ 0x5fffc,  0xf90001db },
-	{ 0x5036c,  0x134003f3 },
-	{ 0x5fffc,  0xfa0001e5 },
-	{ 0x50370,  0xf0003f6 },
-	{ 0x5fffc,  0xfb4001ee },
-	{ 0x50374,  0xac003f9 },
-	{ 0x5fffc,  0xfcc001f5 },
-	{ 0x50378,  0x70003fb },
-	{ 0x5fffc,  0xfe4001fb },
-	{ 0x5037c,  0x34003fe },
-};
-
-struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX] = {
-	[MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_y_table_PT2TOPT4,
-	[MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_y_table_PT4TOPT6,
-	[MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_y_table_PT6TOPT8,
-	[MDP_DOWNSCALE_PT8TO1]  = mdp_downscale_y_table_PT8TO1,
-};
-
-struct mdp_table_entry mdp_gaussian_blur_table[] = {
-	/* max variance */
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50280, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50284, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50288, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5028c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50290, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50294, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50298, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5029c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502a0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502a4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502a8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502ac, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502b0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502b4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502b8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502bc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502c0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502c4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502c8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502cc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502d0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502d4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502d8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502dc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502e0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502e4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502e8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502ec, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502f0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502f4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502f8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502fc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50300, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50304, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50308, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5030c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50310, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50314, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50318, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5031c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50320, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50324, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50328, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5032c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50330, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50334, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50338, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5033c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50340, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50344, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50348, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5034c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50350, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50354, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50358, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5035c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50360, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50364, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50368, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5036c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50370, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50374, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50378, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5037c, 0x20000080 },
-};
diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/msm/mdp_scale_tables.h
deleted file mode 100644
index 34077b1af603..000000000000
--- a/drivers/video/msm/mdp_scale_tables.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* drivers/video/msm_fb/mdp_scale_tables.h
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef _MDP_SCALE_TABLES_H_
-#define _MDP_SCALE_TABLES_H_
-
-#include <linux/types.h>
-struct mdp_table_entry {
-	uint32_t reg;
-	uint32_t val;
-};
-
-extern struct mdp_table_entry mdp_upscale_table[64];
-
-enum {
-	MDP_DOWNSCALE_PT2TOPT4,
-	MDP_DOWNSCALE_PT4TOPT6,
-	MDP_DOWNSCALE_PT6TOPT8,
-	MDP_DOWNSCALE_PT8TO1,
-	MDP_DOWNSCALE_MAX,
-};
-
-extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
-extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
-extern struct mdp_table_entry mdp_gaussian_blur_table[];
-
-#endif
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
deleted file mode 100644
index 1374803fbcd9..000000000000
--- a/drivers/video/msm/msm_fb.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/* drivers/video/msm/msm_fb.c
- *
- * Core MSM framebuffer driver.
- *
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/fb.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/freezer.h>
-#include <linux/wait.h>
-#include <linux/msm_mdp.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/platform_data/video-msm_fb.h>
-#include <linux/workqueue.h>
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/dma-mapping.h>
-
-#define PRINT_FPS 0
-#define PRINT_BLIT_TIME 0
-
-#define SLEEPING 0x4
-#define UPDATING 0x3
-#define FULL_UPDATE_DONE 0x2
-#define WAKING 0x1
-#define AWAKE 0x0
-
-#define NONE 0
-#define SUSPEND_RESUME 0x1
-#define FPS 0x2
-#define BLIT_TIME 0x4
-#define SHOW_UPDATES 0x8
-
-#define DLOG(mask, fmt, args...) \
-do { \
-	if (msmfb_debug_mask & mask) \
-		printk(KERN_INFO "msmfb: "fmt, ##args); \
-} while (0)
-
-static int msmfb_debug_mask;
-module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
-		   S_IRUGO | S_IWUSR | S_IWGRP);
-
-struct mdp_device *mdp;
-
-struct msmfb_info {
-	struct fb_info *fb;
-	struct msm_panel_data *panel;
-	int xres;
-	int yres;
-	unsigned output_format;
-	unsigned yoffset;
-	unsigned frame_requested;
-	unsigned frame_done;
-	int sleeping;
-	unsigned update_frame;
-	struct {
-		int left;
-		int top;
-		int eright; /* exclusive */
-		int ebottom; /* exclusive */
-	} update_info;
-	char *black;
-
-	spinlock_t update_lock;
-	struct mutex panel_init_lock;
-	wait_queue_head_t frame_wq;
-	struct work_struct resume_work;
-	struct msmfb_callback dma_callback;
-	struct msmfb_callback vsync_callback;
-	struct hrtimer fake_vsync;
-	ktime_t vsync_request_time;
-};
-
-static int msmfb_open(struct fb_info *info, int user)
-{
-	return 0;
-}
-
-static int msmfb_release(struct fb_info *info, int user)
-{
-	return 0;
-}
-
-/* Called from dma interrupt handler, must not sleep */
-static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
-{
-	unsigned long irq_flags;
-	struct msmfb_info *msmfb  = container_of(callback, struct msmfb_info,
-					       dma_callback);
-
-	spin_lock_irqsave(&msmfb->update_lock, irq_flags);
-	msmfb->frame_done = msmfb->frame_requested;
-	if (msmfb->sleeping == UPDATING &&
-	    msmfb->frame_done == msmfb->update_frame) {
-		DLOG(SUSPEND_RESUME, "full update completed\n");
-		schedule_work(&msmfb->resume_work);
-	}
-	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-	wake_up(&msmfb->frame_wq);
-}
-
-static int msmfb_start_dma(struct msmfb_info *msmfb)
-{
-	uint32_t x, y, w, h;
-	unsigned addr;
-	unsigned long irq_flags;
-	uint32_t yoffset;
-	s64 time_since_request;
-	struct msm_panel_data *panel = msmfb->panel;
-
-	spin_lock_irqsave(&msmfb->update_lock, irq_flags);
-	time_since_request = ktime_to_ns(ktime_sub(ktime_get(),
-			     msmfb->vsync_request_time));
-	if (time_since_request > 20 * NSEC_PER_MSEC) {
-		uint32_t us;
-		us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC;
-		printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync "
-			"request\n", time_since_request, us);
-	}
-	if (msmfb->frame_done == msmfb->frame_requested) {
-		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-		return -1;
-	}
-	if (msmfb->sleeping == SLEEPING) {
-		DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
-		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-		return -1;
-	}
-	x = msmfb->update_info.left;
-	y = msmfb->update_info.top;
-	w = msmfb->update_info.eright - x;
-	h = msmfb->update_info.ebottom - y;
-	yoffset = msmfb->yoffset;
-	msmfb->update_info.left = msmfb->xres + 1;
-	msmfb->update_info.top = msmfb->yres + 1;
-	msmfb->update_info.eright = 0;
-	msmfb->update_info.ebottom = 0;
-	if (unlikely(w > msmfb->xres || h > msmfb->yres ||
-		     w == 0 || h == 0)) {
-		printk(KERN_INFO "invalid update: %d %d %d "
-				"%d\n", x, y, w, h);
-		msmfb->frame_done = msmfb->frame_requested;
-		goto error;
-	}
-	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-
-	addr = ((msmfb->xres * (yoffset + y) + x) * 2);
-	mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
-		 msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
-		 panel->interface_type);
-	return 0;
-error:
-	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-	/* some clients need to clear their vsync interrupt */
-	if (panel->clear_vsync)
-		panel->clear_vsync(panel);
-	wake_up(&msmfb->frame_wq);
-	return 0;
-}
-
-/* Called from esync interrupt handler, must not sleep */
-static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback)
-{
-	struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
-					       vsync_callback);
-	msmfb_start_dma(msmfb);
-}
-
-static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer)
-{
-	struct msmfb_info *msmfb  = container_of(timer, struct msmfb_info,
-					       fake_vsync);
-	msmfb_start_dma(msmfb);
-	return HRTIMER_NORESTART;
-}
-
-static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
-			     uint32_t eright, uint32_t ebottom,
-			     uint32_t yoffset, int pan_display)
-{
-	struct msmfb_info *msmfb = info->par;
-	struct msm_panel_data *panel = msmfb->panel;
-	unsigned long irq_flags;
-	int sleeping;
-	int retry = 1;
-
-	DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
-		left, top, eright, ebottom, yoffset, pan_display);
-restart:
-	spin_lock_irqsave(&msmfb->update_lock, irq_flags);
-
-	/* if we are sleeping, on a pan_display wait 10ms (to throttle back
-	 * drawing otherwise return */
-	if (msmfb->sleeping == SLEEPING) {
-		DLOG(SUSPEND_RESUME, "drawing while asleep\n");
-		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-		if (pan_display)
-			wait_event_interruptible_timeout(msmfb->frame_wq,
-				msmfb->sleeping != SLEEPING, HZ/10);
-		return;
-	}
-
-	sleeping = msmfb->sleeping;
-	/* on a full update, if the last frame has not completed, wait for it */
-	if ((pan_display && msmfb->frame_requested != msmfb->frame_done) ||
-			    sleeping == UPDATING) {
-		int ret;
-		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-		ret = wait_event_interruptible_timeout(msmfb->frame_wq,
-			msmfb->frame_done == msmfb->frame_requested &&
-			msmfb->sleeping != UPDATING, 5 * HZ);
-		if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done ||
-				 msmfb->sleeping == UPDATING)) {
-			if (retry && panel->request_vsync &&
-			    (sleeping == AWAKE)) {
-				panel->request_vsync(panel,
-					&msmfb->vsync_callback);
-				retry = 0;
-				printk(KERN_WARNING "msmfb_pan_display timeout "
-					"rerequest vsync\n");
-			} else {
-				printk(KERN_WARNING "msmfb_pan_display timeout "
-					"waiting for frame start, %d %d\n",
-					msmfb->frame_requested,
-					msmfb->frame_done);
-				return;
-			}
-		}
-		goto restart;
-	}
-
-
-	msmfb->frame_requested++;
-	/* if necessary, update the y offset, if this is the
-	 * first full update on resume, set the sleeping state */
-	if (pan_display) {
-		msmfb->yoffset = yoffset;
-		if (left == 0 && top == 0 && eright == info->var.xres &&
-		    ebottom == info->var.yres) {
-			if (sleeping == WAKING) {
-				msmfb->update_frame = msmfb->frame_requested;
-				DLOG(SUSPEND_RESUME, "full update starting\n");
-				msmfb->sleeping = UPDATING;
-			}
-		}
-	}
-
-	/* set the update request */
-	if (left < msmfb->update_info.left)
-		msmfb->update_info.left = left;
-	if (top < msmfb->update_info.top)
-		msmfb->update_info.top = top;
-	if (eright > msmfb->update_info.eright)
-		msmfb->update_info.eright = eright;
-	if (ebottom > msmfb->update_info.ebottom)
-		msmfb->update_info.ebottom = ebottom;
-	DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n",
-		msmfb->update_info.left, msmfb->update_info.top,
-		msmfb->update_info.eright, msmfb->update_info.ebottom,
-		msmfb->yoffset);
-	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-
-	/* if the panel is all the way on wait for vsync, otherwise sleep
-	 * for 16 ms (long enough for the dma to panel) and then begin dma */
-	msmfb->vsync_request_time = ktime_get();
-	if (panel->request_vsync && (sleeping == AWAKE)) {
-		panel->request_vsync(panel, &msmfb->vsync_callback);
-	} else {
-		if (!hrtimer_active(&msmfb->fake_vsync)) {
-			hrtimer_start(&msmfb->fake_vsync,
-				      ktime_set(0, NSEC_PER_SEC/60),
-				      HRTIMER_MODE_REL);
-		}
-	}
-}
-
-static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
-			 uint32_t eright, uint32_t ebottom)
-{
-	msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
-}
-
-static void power_on_panel(struct work_struct *work)
-{
-	struct msmfb_info *msmfb =
-		container_of(work, struct msmfb_info, resume_work);
-	struct msm_panel_data *panel = msmfb->panel;
-	unsigned long irq_flags;
-
-	mutex_lock(&msmfb->panel_init_lock);
-	DLOG(SUSPEND_RESUME, "turning on panel\n");
-	if (msmfb->sleeping == UPDATING) {
-		if (panel->unblank(panel)) {
-			printk(KERN_INFO "msmfb: panel unblank failed,"
-			       "not starting drawing\n");
-			goto error;
-		}
-		spin_lock_irqsave(&msmfb->update_lock, irq_flags);
-		msmfb->sleeping = AWAKE;
-		wake_up(&msmfb->frame_wq);
-		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
-	}
-error:
-	mutex_unlock(&msmfb->panel_init_lock);
-}
-
-
-static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if ((var->xres != info->var.xres) ||
-	    (var->yres != info->var.yres) ||
-	    (var->xres_virtual != info->var.xres_virtual) ||
-	    (var->yres_virtual != info->var.yres_virtual) ||
-	    (var->xoffset != info->var.xoffset) ||
-	    (var->bits_per_pixel != info->var.bits_per_pixel) ||
-	    (var->grayscale != info->var.grayscale))
-		 return -EINVAL;
-	return 0;
-}
-
-int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct msmfb_info *msmfb = info->par;
-	struct msm_panel_data *panel = msmfb->panel;
-
-	/* "UPDT" */
-	if ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
-	    (var->reserved[0] == 0x54445055)) {
-		msmfb_pan_update(info, var->reserved[1] & 0xffff,
-				 var->reserved[1] >> 16,
-				 var->reserved[2] & 0xffff,
-				 var->reserved[2] >> 16, var->yoffset, 1);
-	} else {
-		msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres,
-				 var->yoffset, 1);
-	}
-	return 0;
-}
-
-static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
-{
-	cfb_fillrect(p, rect);
-	msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
-		     rect->dy + rect->height);
-}
-
-static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
-{
-	cfb_copyarea(p, area);
-	msmfb_update(p, area->dx, area->dy, area->dx + area->width,
-		     area->dy + area->height);
-}
-
-static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
-{
-	cfb_imageblit(p, image);
-	msmfb_update(p, image->dx, image->dy, image->dx + image->width,
-		     image->dy + image->height);
-}
-
-
-static int msmfb_blit(struct fb_info *info,
-		      void __user *p)
-{
-	struct mdp_blit_req req;
-	struct mdp_blit_req_list req_list;
-	int i;
-	int ret;
-
-	if (copy_from_user(&req_list, p, sizeof(req_list)))
-		return -EFAULT;
-
-	for (i = 0; i < req_list.count; i++) {
-		struct mdp_blit_req_list *list =
-			(struct mdp_blit_req_list *)p;
-		if (copy_from_user(&req, &list->req[i], sizeof(req)))
-			return -EFAULT;
-		ret = mdp->blit(mdp, info, &req);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
-
-DEFINE_MUTEX(mdp_ppp_lock);
-
-static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int ret;
-
-	switch (cmd) {
-	case MSMFB_GRP_DISP:
-		mdp->set_grp_disp(mdp, arg);
-		break;
-	case MSMFB_BLIT:
-		ret = msmfb_blit(p, argp);
-		if (ret)
-			return ret;
-		break;
-	default:
-			printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
-			return -EINVAL;
-	}
-	return 0;
-}
-
-static struct fb_ops msmfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = msmfb_open,
-	.fb_release = msmfb_release,
-	.fb_check_var = msmfb_check_var,
-	.fb_pan_display = msmfb_pan_display,
-	.fb_fillrect = msmfb_fillrect,
-	.fb_copyarea = msmfb_copyarea,
-	.fb_imageblit = msmfb_imageblit,
-	.fb_ioctl = msmfb_ioctl,
-};
-
-static unsigned PP[16];
-
-
-
-#define BITS_PER_PIXEL 16
-
-static void setup_fb_info(struct msmfb_info *msmfb)
-{
-	struct fb_info *fb_info = msmfb->fb;
-	int r;
-
-	/* finish setting up the fb_info struct */
-	strncpy(fb_info->fix.id, "msmfb", 16);
-	fb_info->fix.ypanstep = 1;
-
-	fb_info->fbops = &msmfb_ops;
-	fb_info->flags = FBINFO_DEFAULT;
-
-	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
-	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
-	fb_info->fix.line_length = msmfb->xres * 2;
-
-	fb_info->var.xres = msmfb->xres;
-	fb_info->var.yres = msmfb->yres;
-	fb_info->var.width = msmfb->panel->fb_data->width;
-	fb_info->var.height = msmfb->panel->fb_data->height;
-	fb_info->var.xres_virtual = msmfb->xres;
-	fb_info->var.yres_virtual = msmfb->yres * 2;
-	fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
-	fb_info->var.accel_flags = 0;
-
-	fb_info->var.yoffset = 0;
-
-	if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
-		/*
-		 * Set the param in the fixed screen, so userspace can't
-		 * change it. This will be used to check for the
-		 * capability.
-		 */
-		fb_info->fix.reserved[0] = 0x5444;
-		fb_info->fix.reserved[1] = 0x5055;
-
-		/*
-		 * This preloads the value so that if userspace doesn't
-		 * change it, it will be a full update
-		 */
-		fb_info->var.reserved[0] = 0x54445055;
-		fb_info->var.reserved[1] = 0;
-		fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
-					   ((uint32_t)msmfb->yres << 16);
-	}
-
-	fb_info->var.red.offset = 11;
-	fb_info->var.red.length = 5;
-	fb_info->var.red.msb_right = 0;
-	fb_info->var.green.offset = 5;
-	fb_info->var.green.length = 6;
-	fb_info->var.green.msb_right = 0;
-	fb_info->var.blue.offset = 0;
-	fb_info->var.blue.length = 5;
-	fb_info->var.blue.msb_right = 0;
-
-	r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
-	fb_info->pseudo_palette = PP;
-
-	PP[0] = 0;
-	for (r = 1; r < 16; r++)
-		PP[r] = 0xffffffff;
-}
-
-static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
-{
-	struct fb_info *fb = msmfb->fb;
-	struct resource *resource;
-	unsigned long size = msmfb->xres * msmfb->yres *
-			     (BITS_PER_PIXEL >> 3) * 2;
-	unsigned char *fbram;
-
-	/* board file might have attached a resource describing an fb */
-	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!resource)
-		return -EINVAL;
-
-	/* check the resource is large enough to fit the fb */
-	if (resource->end - resource->start < size) {
-		printk(KERN_ERR "allocated resource is too small for "
-				"fb\n");
-		return -ENOMEM;
-	}
-	fb->fix.smem_start = resource->start;
-	fb->fix.smem_len = resource_size(resource);
-	fbram = ioremap(resource->start, resource_size(resource));
-	if (fbram == NULL) {
-		printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
-		return -ENOMEM;
-	}
-	fb->screen_base = fbram;
-	return 0;
-}
-
-static int msmfb_probe(struct platform_device *pdev)
-{
-	struct fb_info *fb;
-	struct msmfb_info *msmfb;
-	struct msm_panel_data *panel = pdev->dev.platform_data;
-	int ret;
-
-	if (!panel) {
-		pr_err("msmfb_probe: no platform data\n");
-		return -EINVAL;
-	}
-	if (!panel->fb_data) {
-		pr_err("msmfb_probe: no fb_data\n");
-		return -EINVAL;
-	}
-
-	fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev);
-	if (!fb)
-		return -ENOMEM;
-	msmfb = fb->par;
-	msmfb->fb = fb;
-	msmfb->panel = panel;
-	msmfb->xres = panel->fb_data->xres;
-	msmfb->yres = panel->fb_data->yres;
-
-	ret = setup_fbmem(msmfb, pdev);
-	if (ret)
-		goto error_setup_fbmem;
-
-	setup_fb_info(msmfb);
-
-	spin_lock_init(&msmfb->update_lock);
-	mutex_init(&msmfb->panel_init_lock);
-	init_waitqueue_head(&msmfb->frame_wq);
-	INIT_WORK(&msmfb->resume_work, power_on_panel);
-	msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
-			       GFP_KERNEL);
-
-	printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n",
-	       msmfb->xres, msmfb->yres);
-
-	msmfb->dma_callback.func = msmfb_handle_dma_interrupt;
-	msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt;
-	hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC,
-		     HRTIMER_MODE_REL);
-
-
-	msmfb->fake_vsync.function = msmfb_fake_vsync;
-
-	ret = register_framebuffer(fb);
-	if (ret)
-		goto error_register_framebuffer;
-
-	msmfb->sleeping = WAKING;
-
-	return 0;
-
-error_register_framebuffer:
-	iounmap(fb->screen_base);
-error_setup_fbmem:
-	framebuffer_release(msmfb->fb);
-	return ret;
-}
-
-static struct platform_driver msm_panel_driver = {
-	/* need to write remove */
-	.probe = msmfb_probe,
-	.driver = {.name = "msm_panel"},
-};
-
-
-static int msmfb_add_mdp_device(struct device *dev,
-				struct class_interface *class_intf)
-{
-	/* might need locking if mulitple mdp devices */
-	if (mdp)
-		return 0;
-	mdp = container_of(dev, struct mdp_device, dev);
-	return platform_driver_register(&msm_panel_driver);
-}
-
-static void msmfb_remove_mdp_device(struct device *dev,
-				struct class_interface *class_intf)
-{
-	/* might need locking if mulitple mdp devices */
-	if (dev != &mdp->dev)
-		return;
-	platform_driver_unregister(&msm_panel_driver);
-	mdp = NULL;
-}
-
-static struct class_interface msm_fb_interface = {
-	.add_dev = &msmfb_add_mdp_device,
-	.remove_dev = &msmfb_remove_mdp_device,
-};
-
-static int __init msmfb_init(void)
-{
-	return register_mdp_client(&msm_fb_interface);
-}
-
-module_init(msmfb_init);
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
deleted file mode 100644
index 142e860fb527..000000000000
--- a/drivers/video/mx3fb.c
+++ /dev/null
@@ -1,1630 +0,0 @@
-/*
- * Copyright (C) 2008
- * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
- *
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-#include <linux/console.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/dma/ipu-dma.h>
-
-#include <linux/platform_data/dma-imx.h>
-#include <linux/platform_data/video-mx3fb.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define MX3FB_NAME		"mx3_sdc_fb"
-
-#define MX3FB_REG_OFFSET	0xB4
-
-/* SDC Registers */
-#define SDC_COM_CONF		(0xB4 - MX3FB_REG_OFFSET)
-#define SDC_GW_CTRL		(0xB8 - MX3FB_REG_OFFSET)
-#define SDC_FG_POS		(0xBC - MX3FB_REG_OFFSET)
-#define SDC_BG_POS		(0xC0 - MX3FB_REG_OFFSET)
-#define SDC_CUR_POS		(0xC4 - MX3FB_REG_OFFSET)
-#define SDC_PWM_CTRL		(0xC8 - MX3FB_REG_OFFSET)
-#define SDC_CUR_MAP		(0xCC - MX3FB_REG_OFFSET)
-#define SDC_HOR_CONF		(0xD0 - MX3FB_REG_OFFSET)
-#define SDC_VER_CONF		(0xD4 - MX3FB_REG_OFFSET)
-#define SDC_SHARP_CONF_1	(0xD8 - MX3FB_REG_OFFSET)
-#define SDC_SHARP_CONF_2	(0xDC - MX3FB_REG_OFFSET)
-
-/* Register bits */
-#define SDC_COM_TFT_COLOR	0x00000001UL
-#define SDC_COM_FG_EN		0x00000010UL
-#define SDC_COM_GWSEL		0x00000020UL
-#define SDC_COM_GLB_A		0x00000040UL
-#define SDC_COM_KEY_COLOR_G	0x00000080UL
-#define SDC_COM_BG_EN		0x00000200UL
-#define SDC_COM_SHARP		0x00001000UL
-
-#define SDC_V_SYNC_WIDTH_L	0x00000001UL
-
-/* Display Interface registers */
-#define DI_DISP_IF_CONF		(0x0124 - MX3FB_REG_OFFSET)
-#define DI_DISP_SIG_POL		(0x0128 - MX3FB_REG_OFFSET)
-#define DI_SER_DISP1_CONF	(0x012C - MX3FB_REG_OFFSET)
-#define DI_SER_DISP2_CONF	(0x0130 - MX3FB_REG_OFFSET)
-#define DI_HSP_CLK_PER		(0x0134 - MX3FB_REG_OFFSET)
-#define DI_DISP0_TIME_CONF_1	(0x0138 - MX3FB_REG_OFFSET)
-#define DI_DISP0_TIME_CONF_2	(0x013C - MX3FB_REG_OFFSET)
-#define DI_DISP0_TIME_CONF_3	(0x0140 - MX3FB_REG_OFFSET)
-#define DI_DISP1_TIME_CONF_1	(0x0144 - MX3FB_REG_OFFSET)
-#define DI_DISP1_TIME_CONF_2	(0x0148 - MX3FB_REG_OFFSET)
-#define DI_DISP1_TIME_CONF_3	(0x014C - MX3FB_REG_OFFSET)
-#define DI_DISP2_TIME_CONF_1	(0x0150 - MX3FB_REG_OFFSET)
-#define DI_DISP2_TIME_CONF_2	(0x0154 - MX3FB_REG_OFFSET)
-#define DI_DISP2_TIME_CONF_3	(0x0158 - MX3FB_REG_OFFSET)
-#define DI_DISP3_TIME_CONF	(0x015C - MX3FB_REG_OFFSET)
-#define DI_DISP0_DB0_MAP	(0x0160 - MX3FB_REG_OFFSET)
-#define DI_DISP0_DB1_MAP	(0x0164 - MX3FB_REG_OFFSET)
-#define DI_DISP0_DB2_MAP	(0x0168 - MX3FB_REG_OFFSET)
-#define DI_DISP0_CB0_MAP	(0x016C - MX3FB_REG_OFFSET)
-#define DI_DISP0_CB1_MAP	(0x0170 - MX3FB_REG_OFFSET)
-#define DI_DISP0_CB2_MAP	(0x0174 - MX3FB_REG_OFFSET)
-#define DI_DISP1_DB0_MAP	(0x0178 - MX3FB_REG_OFFSET)
-#define DI_DISP1_DB1_MAP	(0x017C - MX3FB_REG_OFFSET)
-#define DI_DISP1_DB2_MAP	(0x0180 - MX3FB_REG_OFFSET)
-#define DI_DISP1_CB0_MAP	(0x0184 - MX3FB_REG_OFFSET)
-#define DI_DISP1_CB1_MAP	(0x0188 - MX3FB_REG_OFFSET)
-#define DI_DISP1_CB2_MAP	(0x018C - MX3FB_REG_OFFSET)
-#define DI_DISP2_DB0_MAP	(0x0190 - MX3FB_REG_OFFSET)
-#define DI_DISP2_DB1_MAP	(0x0194 - MX3FB_REG_OFFSET)
-#define DI_DISP2_DB2_MAP	(0x0198 - MX3FB_REG_OFFSET)
-#define DI_DISP2_CB0_MAP	(0x019C - MX3FB_REG_OFFSET)
-#define DI_DISP2_CB1_MAP	(0x01A0 - MX3FB_REG_OFFSET)
-#define DI_DISP2_CB2_MAP	(0x01A4 - MX3FB_REG_OFFSET)
-#define DI_DISP3_B0_MAP		(0x01A8 - MX3FB_REG_OFFSET)
-#define DI_DISP3_B1_MAP		(0x01AC - MX3FB_REG_OFFSET)
-#define DI_DISP3_B2_MAP		(0x01B0 - MX3FB_REG_OFFSET)
-#define DI_DISP_ACC_CC		(0x01B4 - MX3FB_REG_OFFSET)
-#define DI_DISP_LLA_CONF	(0x01B8 - MX3FB_REG_OFFSET)
-#define DI_DISP_LLA_DATA	(0x01BC - MX3FB_REG_OFFSET)
-
-/* DI_DISP_SIG_POL bits */
-#define DI_D3_VSYNC_POL_SHIFT		28
-#define DI_D3_HSYNC_POL_SHIFT		27
-#define DI_D3_DRDY_SHARP_POL_SHIFT	26
-#define DI_D3_CLK_POL_SHIFT		25
-#define DI_D3_DATA_POL_SHIFT		24
-
-/* DI_DISP_IF_CONF bits */
-#define DI_D3_CLK_IDLE_SHIFT		26
-#define DI_D3_CLK_SEL_SHIFT		25
-#define DI_D3_DATAMSK_SHIFT		24
-
-enum ipu_panel {
-	IPU_PANEL_SHARP_TFT,
-	IPU_PANEL_TFT,
-};
-
-struct ipu_di_signal_cfg {
-	unsigned datamask_en:1;
-	unsigned clksel_en:1;
-	unsigned clkidle_en:1;
-	unsigned data_pol:1;	/* true = inverted */
-	unsigned clk_pol:1;	/* true = rising edge */
-	unsigned enable_pol:1;
-	unsigned Hsync_pol:1;	/* true = active high */
-	unsigned Vsync_pol:1;
-};
-
-static const struct fb_videomode mx3fb_modedb[] = {
-	{
-		/* 240x320 @ 60 Hz */
-		.name		= "Sharp-QVGA",
-		.refresh	= 60,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 185925,
-		.left_margin	= 9,
-		.right_margin	= 16,
-		.upper_margin	= 7,
-		.lower_margin	= 9,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
-				  FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT |
-				  FB_SYNC_CLK_IDLE_EN,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* 240x33 @ 60 Hz */
-		.name		= "Sharp-CLI",
-		.refresh	= 60,
-		.xres		= 240,
-		.yres		= 33,
-		.pixclock	= 185925,
-		.left_margin	= 9,
-		.right_margin	= 16,
-		.upper_margin	= 7,
-		.lower_margin	= 9 + 287,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
-				  FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT |
-				  FB_SYNC_CLK_IDLE_EN,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* 640x480 @ 60 Hz */
-		.name		= "NEC-VGA",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 38255,
-		.left_margin	= 144,
-		.right_margin	= 0,
-		.upper_margin	= 34,
-		.lower_margin	= 40,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* NTSC TV output */
-		.name		= "TV-NTSC",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 37538,
-		.left_margin	= 38,
-		.right_margin	= 858 - 640 - 38 - 3,
-		.upper_margin	= 36,
-		.lower_margin	= 518 - 480 - 36 - 1,
-		.hsync_len	= 3,
-		.vsync_len	= 1,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* PAL TV output */
-		.name		= "TV-PAL",
-		.refresh	= 50,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 37538,
-		.left_margin	= 38,
-		.right_margin	= 960 - 640 - 38 - 32,
-		.upper_margin	= 32,
-		.lower_margin	= 555 - 480 - 32 - 3,
-		.hsync_len	= 32,
-		.vsync_len	= 3,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* TV output VGA mode, 640x480 @ 65 Hz */
-		.name		= "TV-VGA",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 40574,
-		.left_margin	= 35,
-		.right_margin	= 45,
-		.upper_margin	= 9,
-		.lower_margin	= 1,
-		.hsync_len	= 46,
-		.vsync_len	= 5,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	},
-};
-
-struct mx3fb_data {
-	struct fb_info		*fbi;
-	int			backlight_level;
-	void __iomem		*reg_base;
-	spinlock_t		lock;
-	struct device		*dev;
-
-	uint32_t		h_start_width;
-	uint32_t		v_start_width;
-	enum disp_data_mapping	disp_data_fmt;
-};
-
-struct dma_chan_request {
-	struct mx3fb_data	*mx3fb;
-	enum ipu_channel	id;
-};
-
-/* MX3 specific framebuffer information. */
-struct mx3fb_info {
-	int				blank;
-	enum ipu_channel		ipu_ch;
-	uint32_t			cur_ipu_buf;
-
-	u32				pseudo_palette[16];
-
-	struct completion		flip_cmpl;
-	struct mutex			mutex;	/* Protects fb-ops */
-	struct mx3fb_data		*mx3fb;
-	struct idmac_channel		*idmac_channel;
-	struct dma_async_tx_descriptor	*txd;
-	dma_cookie_t			cookie;
-	struct scatterlist		sg[2];
-
-	struct fb_var_screeninfo	cur_var; /* current var info */
-};
-
-static void mx3fb_dma_done(void *);
-
-/* Used fb-mode and bpp. Can be set on kernel command line, therefore file-static. */
-static const char *fb_mode;
-static unsigned long default_bpp = 16;
-
-static u32 mx3fb_read_reg(struct mx3fb_data *mx3fb, unsigned long reg)
-{
-	return __raw_readl(mx3fb->reg_base + reg);
-}
-
-static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long reg)
-{
-	__raw_writel(value, mx3fb->reg_base + reg);
-}
-
-struct di_mapping {
-	uint32_t b0, b1, b2;
-};
-
-static const struct di_mapping di_mappings[] = {
-	[IPU_DISP_DATA_MAPPING_RGB666] = { 0x0005000f, 0x000b000f, 0x0011000f },
-	[IPU_DISP_DATA_MAPPING_RGB565] = { 0x0004003f, 0x000a000f, 0x000f003f },
-	[IPU_DISP_DATA_MAPPING_RGB888] = { 0x00070000, 0x000f0000, 0x00170000 },
-};
-
-static void sdc_fb_init(struct mx3fb_info *fbi)
-{
-	struct mx3fb_data *mx3fb = fbi->mx3fb;
-	uint32_t reg;
-
-	reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
-
-	mx3fb_write_reg(mx3fb, reg | SDC_COM_BG_EN, SDC_COM_CONF);
-}
-
-/* Returns enabled flag before uninit */
-static uint32_t sdc_fb_uninit(struct mx3fb_info *fbi)
-{
-	struct mx3fb_data *mx3fb = fbi->mx3fb;
-	uint32_t reg;
-
-	reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
-
-	mx3fb_write_reg(mx3fb, reg & ~SDC_COM_BG_EN, SDC_COM_CONF);
-
-	return reg & SDC_COM_BG_EN;
-}
-
-static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
-{
-	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
-	struct idmac_channel *ichan = mx3_fbi->idmac_channel;
-	struct dma_chan *dma_chan = &ichan->dma_chan;
-	unsigned long flags;
-	dma_cookie_t cookie;
-
-	if (mx3_fbi->txd)
-		dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
-			to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
-	else
-		dev_dbg(mx3fb->dev, "mx3fbi %p, txd = NULL\n", mx3_fbi);
-
-	/* This enables the channel */
-	if (mx3_fbi->cookie < 0) {
-		mx3_fbi->txd = dmaengine_prep_slave_sg(dma_chan,
-		      &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
-		if (!mx3_fbi->txd) {
-			dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n",
-				dma_chan->chan_id);
-			return;
-		}
-
-		mx3_fbi->txd->callback_param	= mx3_fbi->txd;
-		mx3_fbi->txd->callback		= mx3fb_dma_done;
-
-		cookie = mx3_fbi->txd->tx_submit(mx3_fbi->txd);
-		dev_dbg(mx3fb->dev, "%d: Submit %p #%d [%c]\n", __LINE__,
-		       mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+');
-	} else {
-		if (!mx3_fbi->txd || !mx3_fbi->txd->tx_submit) {
-			dev_err(mx3fb->dev, "Cannot enable channel %d\n",
-				dma_chan->chan_id);
-			return;
-		}
-
-		/* Just re-activate the same buffer */
-		dma_async_issue_pending(dma_chan);
-		cookie = mx3_fbi->cookie;
-		dev_dbg(mx3fb->dev, "%d: Re-submit %p #%d [%c]\n", __LINE__,
-		       mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+');
-	}
-
-	if (cookie >= 0) {
-		spin_lock_irqsave(&mx3fb->lock, flags);
-		sdc_fb_init(mx3_fbi);
-		mx3_fbi->cookie = cookie;
-		spin_unlock_irqrestore(&mx3fb->lock, flags);
-	}
-
-	/*
-	 * Attention! Without this msleep the channel keeps generating
-	 * interrupts. Next sdc_set_brightness() is going to be called
-	 * from mx3fb_blank().
-	 */
-	msleep(2);
-}
-
-static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
-{
-	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
-	uint32_t enabled;
-	unsigned long flags;
-
-	if (mx3_fbi->txd == NULL)
-		return;
-
-	spin_lock_irqsave(&mx3fb->lock, flags);
-
-	enabled = sdc_fb_uninit(mx3_fbi);
-
-	spin_unlock_irqrestore(&mx3fb->lock, flags);
-
-	mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan,
-						   DMA_TERMINATE_ALL, 0);
-	mx3_fbi->txd = NULL;
-	mx3_fbi->cookie = -EINVAL;
-}
-
-/**
- * sdc_set_window_pos() - set window position of the respective plane.
- * @mx3fb:	mx3fb context.
- * @channel:	IPU DMAC channel ID.
- * @x_pos:	X coordinate relative to the top left corner to place window at.
- * @y_pos:	Y coordinate relative to the top left corner to place window at.
- * @return:	0 on success or negative error code on failure.
- */
-static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel,
-			      int16_t x_pos, int16_t y_pos)
-{
-	if (channel != IDMAC_SDC_0)
-		return -EINVAL;
-
-	x_pos += mx3fb->h_start_width;
-	y_pos += mx3fb->v_start_width;
-
-	mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS);
-	return 0;
-}
-
-/**
- * sdc_init_panel() - initialize a synchronous LCD panel.
- * @mx3fb:		mx3fb context.
- * @panel:		panel type.
- * @pixel_clk:		desired pixel clock frequency in Hz.
- * @width:		width of panel in pixels.
- * @height:		height of panel in pixels.
- * @h_start_width:	number of pixel clocks between the HSYNC signal pulse
- *			and the start of valid data.
- * @h_sync_width:	width of the HSYNC signal in units of pixel clocks.
- * @h_end_width:	number of pixel clocks between the end of valid data
- *			and the HSYNC signal for next line.
- * @v_start_width:	number of lines between the VSYNC signal pulse and the
- *			start of valid data.
- * @v_sync_width:	width of the VSYNC signal in units of lines
- * @v_end_width:	number of lines between the end of valid data and the
- *			VSYNC signal for next frame.
- * @sig:		bitfield of signal polarities for LCD interface.
- * @return:		0 on success or negative error code on failure.
- */
-static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
-			  uint32_t pixel_clk,
-			  uint16_t width, uint16_t height,
-			  uint16_t h_start_width, uint16_t h_sync_width,
-			  uint16_t h_end_width, uint16_t v_start_width,
-			  uint16_t v_sync_width, uint16_t v_end_width,
-			  struct ipu_di_signal_cfg sig)
-{
-	unsigned long lock_flags;
-	uint32_t reg;
-	uint32_t old_conf;
-	uint32_t div;
-	struct clk *ipu_clk;
-	const struct di_mapping *map;
-
-	dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
-
-	if (v_sync_width == 0 || h_sync_width == 0)
-		return -EINVAL;
-
-	/* Init panel size and blanking periods */
-	reg = ((uint32_t) (h_sync_width - 1) << 26) |
-		((uint32_t) (width + h_start_width + h_end_width - 1) << 16);
-	mx3fb_write_reg(mx3fb, reg, SDC_HOR_CONF);
-
-#ifdef DEBUG
-	printk(KERN_CONT " hor_conf %x,", reg);
-#endif
-
-	reg = ((uint32_t) (v_sync_width - 1) << 26) | SDC_V_SYNC_WIDTH_L |
-	    ((uint32_t) (height + v_start_width + v_end_width - 1) << 16);
-	mx3fb_write_reg(mx3fb, reg, SDC_VER_CONF);
-
-#ifdef DEBUG
-	printk(KERN_CONT " ver_conf %x\n", reg);
-#endif
-
-	mx3fb->h_start_width = h_start_width;
-	mx3fb->v_start_width = v_start_width;
-
-	switch (panel) {
-	case IPU_PANEL_SHARP_TFT:
-		mx3fb_write_reg(mx3fb, 0x00FD0102L, SDC_SHARP_CONF_1);
-		mx3fb_write_reg(mx3fb, 0x00F500F4L, SDC_SHARP_CONF_2);
-		mx3fb_write_reg(mx3fb, SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF);
-		break;
-	case IPU_PANEL_TFT:
-		mx3fb_write_reg(mx3fb, SDC_COM_TFT_COLOR, SDC_COM_CONF);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Init clocking */
-
-	/*
-	 * Calculate divider: fractional part is 4 bits so simply multiple by
-	 * 2^4 to get fractional part, as long as we stay under ~250MHz and on
-	 * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
-	 */
-	ipu_clk = clk_get(mx3fb->dev, NULL);
-	if (!IS_ERR(ipu_clk)) {
-		div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
-		clk_put(ipu_clk);
-	} else {
-		div = 0;
-	}
-
-	if (div < 0x40) {	/* Divider less than 4 */
-		dev_dbg(mx3fb->dev,
-			"InitPanel() - Pixel clock divider less than 4\n");
-		div = 0x40;
-	}
-
-	dev_dbg(mx3fb->dev, "pixel clk = %u, divider %u.%u\n",
-		pixel_clk, div >> 4, (div & 7) * 125);
-
-	spin_lock_irqsave(&mx3fb->lock, lock_flags);
-
-	/*
-	 * DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits
-	 * fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing
-	 * debug. DISP3_IF_CLK_UP_WR is 0
-	 */
-	mx3fb_write_reg(mx3fb, (((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF);
-
-	/* DI settings */
-	old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF;
-	old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT |
-		sig.clksel_en << DI_D3_CLK_SEL_SHIFT |
-		sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT;
-	mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF);
-
-	old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF;
-	old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT |
-		sig.clk_pol << DI_D3_CLK_POL_SHIFT |
-		sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT |
-		sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT |
-		sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
-	mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
-
-	map = &di_mappings[mx3fb->disp_data_fmt];
-	mx3fb_write_reg(mx3fb, map->b0, DI_DISP3_B0_MAP);
-	mx3fb_write_reg(mx3fb, map->b1, DI_DISP3_B1_MAP);
-	mx3fb_write_reg(mx3fb, map->b2, DI_DISP3_B2_MAP);
-
-	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
-
-	dev_dbg(mx3fb->dev, "DI_DISP_IF_CONF = 0x%08X\n",
-		mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF));
-	dev_dbg(mx3fb->dev, "DI_DISP_SIG_POL = 0x%08X\n",
-		mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL));
-	dev_dbg(mx3fb->dev, "DI_DISP3_TIME_CONF = 0x%08X\n",
-		mx3fb_read_reg(mx3fb, DI_DISP3_TIME_CONF));
-
-	return 0;
-}
-
-/**
- * sdc_set_color_key() - set the transparent color key for SDC graphic plane.
- * @mx3fb:	mx3fb context.
- * @channel:	IPU DMAC channel ID.
- * @enable:	boolean to enable or disable color keyl.
- * @color_key:	24-bit RGB color to use as transparent color key.
- * @return:	0 on success or negative error code on failure.
- */
-static int sdc_set_color_key(struct mx3fb_data *mx3fb, enum ipu_channel channel,
-			     bool enable, uint32_t color_key)
-{
-	uint32_t reg, sdc_conf;
-	unsigned long lock_flags;
-
-	spin_lock_irqsave(&mx3fb->lock, lock_flags);
-
-	sdc_conf = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
-	if (channel == IDMAC_SDC_0)
-		sdc_conf &= ~SDC_COM_GWSEL;
-	else
-		sdc_conf |= SDC_COM_GWSEL;
-
-	if (enable) {
-		reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0xFF000000L;
-		mx3fb_write_reg(mx3fb, reg | (color_key & 0x00FFFFFFL),
-			     SDC_GW_CTRL);
-
-		sdc_conf |= SDC_COM_KEY_COLOR_G;
-	} else {
-		sdc_conf &= ~SDC_COM_KEY_COLOR_G;
-	}
-	mx3fb_write_reg(mx3fb, sdc_conf, SDC_COM_CONF);
-
-	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
-
-	return 0;
-}
-
-/**
- * sdc_set_global_alpha() - set global alpha blending modes.
- * @mx3fb:	mx3fb context.
- * @enable:	boolean to enable or disable global alpha blending. If disabled,
- *		per pixel blending is used.
- * @alpha:	global alpha value.
- * @return:	0 on success or negative error code on failure.
- */
-static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t alpha)
-{
-	uint32_t reg;
-	unsigned long lock_flags;
-
-	spin_lock_irqsave(&mx3fb->lock, lock_flags);
-
-	if (enable) {
-		reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0x00FFFFFFL;
-		mx3fb_write_reg(mx3fb, reg | ((uint32_t) alpha << 24), SDC_GW_CTRL);
-
-		reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
-		mx3fb_write_reg(mx3fb, reg | SDC_COM_GLB_A, SDC_COM_CONF);
-	} else {
-		reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
-		mx3fb_write_reg(mx3fb, reg & ~SDC_COM_GLB_A, SDC_COM_CONF);
-	}
-
-	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
-
-	return 0;
-}
-
-static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
-{
-	dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value);
-	/* This might be board-specific */
-	mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
-	return;
-}
-
-static uint32_t bpp_to_pixfmt(int bpp)
-{
-	uint32_t pixfmt = 0;
-	switch (bpp) {
-	case 24:
-		pixfmt = IPU_PIX_FMT_BGR24;
-		break;
-	case 32:
-		pixfmt = IPU_PIX_FMT_BGR32;
-		break;
-	case 16:
-		pixfmt = IPU_PIX_FMT_RGB565;
-		break;
-	}
-	return pixfmt;
-}
-
-static int mx3fb_blank(int blank, struct fb_info *fbi);
-static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
-				  bool lock);
-static int mx3fb_unmap_video_memory(struct fb_info *fbi);
-
-/**
- * mx3fb_set_fix() - set fixed framebuffer parameters from variable settings.
- * @info:	framebuffer information pointer
- * @return:	0 on success or negative error code on failure.
- */
-static int mx3fb_set_fix(struct fb_info *fbi)
-{
-	struct fb_fix_screeninfo *fix = &fbi->fix;
-	struct fb_var_screeninfo *var = &fbi->var;
-
-	strncpy(fix->id, "DISP3 BG", 8);
-
-	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->accel = FB_ACCEL_NONE;
-	fix->visual = FB_VISUAL_TRUECOLOR;
-	fix->xpanstep = 1;
-	fix->ypanstep = 1;
-
-	return 0;
-}
-
-static void mx3fb_dma_done(void *arg)
-{
-	struct idmac_tx_desc *tx_desc = to_tx_desc(arg);
-	struct dma_chan *chan = tx_desc->txd.chan;
-	struct idmac_channel *ichannel = to_idmac_chan(chan);
-	struct mx3fb_data *mx3fb = ichannel->client;
-	struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
-
-	dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq);
-
-	/* We only need one interrupt, it will be re-enabled as needed */
-	disable_irq_nosync(ichannel->eof_irq);
-
-	complete(&mx3_fbi->flip_cmpl);
-}
-
-static bool mx3fb_must_set_par(struct fb_info *fbi)
-{
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	struct fb_var_screeninfo old_var = mx3_fbi->cur_var;
-	struct fb_var_screeninfo new_var = fbi->var;
-
-	if ((fbi->var.activate & FB_ACTIVATE_FORCE) &&
-	    (fbi->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
-		return true;
-
-	/*
-	 * Ignore xoffset and yoffset update,
-	 * because pan display handles this case.
-	 */
-	old_var.xoffset = new_var.xoffset;
-	old_var.yoffset = new_var.yoffset;
-
-	return !!memcmp(&old_var, &new_var, sizeof(struct fb_var_screeninfo));
-}
-
-static int __set_par(struct fb_info *fbi, bool lock)
-{
-	u32 mem_len, cur_xoffset, cur_yoffset;
-	struct ipu_di_signal_cfg sig_cfg;
-	enum ipu_panel mode = IPU_PANEL_TFT;
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
-	struct idmac_channel *ichan = mx3_fbi->idmac_channel;
-	struct idmac_video_param *video = &ichan->params.video;
-	struct scatterlist *sg = mx3_fbi->sg;
-
-	/* Total cleanup */
-	if (mx3_fbi->txd)
-		sdc_disable_channel(mx3_fbi);
-
-	mx3fb_set_fix(fbi);
-
-	mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
-	if (mem_len > fbi->fix.smem_len) {
-		if (fbi->fix.smem_start)
-			mx3fb_unmap_video_memory(fbi);
-
-		if (mx3fb_map_video_memory(fbi, mem_len, lock) < 0)
-			return -ENOMEM;
-	}
-
-	sg_init_table(&sg[0], 1);
-	sg_init_table(&sg[1], 1);
-
-	sg_dma_address(&sg[0]) = fbi->fix.smem_start;
-	sg_set_page(&sg[0], virt_to_page(fbi->screen_base),
-		    fbi->fix.smem_len,
-		    offset_in_page(fbi->screen_base));
-
-	if (mx3_fbi->ipu_ch == IDMAC_SDC_0) {
-		memset(&sig_cfg, 0, sizeof(sig_cfg));
-		if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
-			sig_cfg.Hsync_pol = true;
-		if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
-			sig_cfg.Vsync_pol = true;
-		if (fbi->var.sync & FB_SYNC_CLK_INVERT)
-			sig_cfg.clk_pol = true;
-		if (fbi->var.sync & FB_SYNC_DATA_INVERT)
-			sig_cfg.data_pol = true;
-		if (fbi->var.sync & FB_SYNC_OE_ACT_HIGH)
-			sig_cfg.enable_pol = true;
-		if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
-			sig_cfg.clkidle_en = true;
-		if (fbi->var.sync & FB_SYNC_CLK_SEL_EN)
-			sig_cfg.clksel_en = true;
-		if (fbi->var.sync & FB_SYNC_SHARP_MODE)
-			mode = IPU_PANEL_SHARP_TFT;
-
-		dev_dbg(fbi->device, "pixclock = %ul Hz\n",
-			(u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
-
-		if (sdc_init_panel(mx3fb, mode,
-				   (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
-				   fbi->var.xres, fbi->var.yres,
-				   fbi->var.left_margin,
-				   fbi->var.hsync_len,
-				   fbi->var.right_margin +
-				   fbi->var.hsync_len,
-				   fbi->var.upper_margin,
-				   fbi->var.vsync_len,
-				   fbi->var.lower_margin +
-				   fbi->var.vsync_len, sig_cfg) != 0) {
-			dev_err(fbi->device,
-				"mx3fb: Error initializing panel.\n");
-			return -EINVAL;
-		}
-	}
-
-	sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0);
-
-	mx3_fbi->cur_ipu_buf	= 0;
-
-	video->out_pixel_fmt	= bpp_to_pixfmt(fbi->var.bits_per_pixel);
-	video->out_width	= fbi->var.xres;
-	video->out_height	= fbi->var.yres;
-	video->out_stride	= fbi->var.xres_virtual;
-
-	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
-		sdc_enable_channel(mx3_fbi);
-		/*
-		 * sg[0] points to fb smem_start address
-		 * and is actually active in controller.
-		 */
-		mx3_fbi->cur_var.xoffset = 0;
-		mx3_fbi->cur_var.yoffset = 0;
-	}
-
-	/*
-	 * Preserve xoffset and yoffest in case they are
-	 * inactive in controller as fb is blanked.
-	 */
-	cur_xoffset = mx3_fbi->cur_var.xoffset;
-	cur_yoffset = mx3_fbi->cur_var.yoffset;
-	mx3_fbi->cur_var = fbi->var;
-	mx3_fbi->cur_var.xoffset = cur_xoffset;
-	mx3_fbi->cur_var.yoffset = cur_yoffset;
-
-	return 0;
-}
-
-/**
- * mx3fb_set_par() - set framebuffer parameters and change the operating mode.
- * @fbi:	framebuffer information pointer.
- * @return:	0 on success or negative error code on failure.
- */
-static int mx3fb_set_par(struct fb_info *fbi)
-{
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
-	struct idmac_channel *ichan = mx3_fbi->idmac_channel;
-	int ret;
-
-	dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
-
-	mutex_lock(&mx3_fbi->mutex);
-
-	ret = mx3fb_must_set_par(fbi) ? __set_par(fbi, true) : 0;
-
-	mutex_unlock(&mx3_fbi->mutex);
-
-	return ret;
-}
-
-/**
- * mx3fb_check_var() - check and adjust framebuffer variable parameters.
- * @var:	framebuffer variable parameters
- * @fbi:	framebuffer information pointer
- */
-static int mx3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
-{
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	u32 vtotal;
-	u32 htotal;
-
-	dev_dbg(fbi->device, "%s\n", __func__);
-
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
-	    (var->bits_per_pixel != 16))
-		var->bits_per_pixel = default_bpp;
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		var->red.length = 5;
-		var->red.offset = 11;
-		var->red.msb_right = 0;
-
-		var->green.length = 6;
-		var->green.offset = 5;
-		var->green.msb_right = 0;
-
-		var->blue.length = 5;
-		var->blue.offset = 0;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 0;
-		var->transp.offset = 0;
-		var->transp.msb_right = 0;
-		break;
-	case 24:
-		var->red.length = 8;
-		var->red.offset = 16;
-		var->red.msb_right = 0;
-
-		var->green.length = 8;
-		var->green.offset = 8;
-		var->green.msb_right = 0;
-
-		var->blue.length = 8;
-		var->blue.offset = 0;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 0;
-		var->transp.offset = 0;
-		var->transp.msb_right = 0;
-		break;
-	case 32:
-		var->red.length = 8;
-		var->red.offset = 16;
-		var->red.msb_right = 0;
-
-		var->green.length = 8;
-		var->green.offset = 8;
-		var->green.msb_right = 0;
-
-		var->blue.length = 8;
-		var->blue.offset = 0;
-		var->blue.msb_right = 0;
-
-		var->transp.length = 8;
-		var->transp.offset = 24;
-		var->transp.msb_right = 0;
-		break;
-	}
-
-	if (var->pixclock < 1000) {
-		htotal = var->xres + var->right_margin + var->hsync_len +
-		    var->left_margin;
-		vtotal = var->yres + var->lower_margin + var->vsync_len +
-		    var->upper_margin;
-		var->pixclock = (vtotal * htotal * 6UL) / 100UL;
-		var->pixclock = KHZ2PICOS(var->pixclock);
-		dev_dbg(fbi->device, "pixclock set for 60Hz refresh = %u ps\n",
-			var->pixclock);
-	}
-
-	var->height = -1;
-	var->width = -1;
-	var->grayscale = 0;
-
-	/* Preserve sync flags */
-	var->sync |= mx3_fbi->cur_var.sync;
-	mx3_fbi->cur_var.sync |= var->sync;
-
-	return 0;
-}
-
-static u32 chan_to_field(unsigned int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
-			   unsigned int green, unsigned int blue,
-			   unsigned int trans, struct fb_info *fbi)
-{
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	u32 val;
-	int ret = 1;
-
-	dev_dbg(fbi->device, "%s, regno = %u\n", __func__, regno);
-
-	mutex_lock(&mx3_fbi->mutex);
-	/*
-	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no matter what visual we are using.
-	 */
-	if (fbi->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-				      7471 * blue) >> 16;
-	switch (fbi->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 16-bit True Colour.  We encode the RGB value
-		 * according to the RGB bitfield information.
-		 */
-		if (regno < 16) {
-			u32 *pal = fbi->pseudo_palette;
-
-			val = chan_to_field(red, &fbi->var.red);
-			val |= chan_to_field(green, &fbi->var.green);
-			val |= chan_to_field(blue, &fbi->var.blue);
-
-			pal[regno] = val;
-
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_STATIC_PSEUDOCOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		break;
-	}
-	mutex_unlock(&mx3_fbi->mutex);
-
-	return ret;
-}
-
-static void __blank(int blank, struct fb_info *fbi)
-{
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
-	int was_blank = mx3_fbi->blank;
-
-	mx3_fbi->blank = blank;
-
-	/* Attention!
-	 * Do not call sdc_disable_channel() for a channel that is disabled
-	 * already! This will result in a kernel NULL pointer dereference
-	 * (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are
-	 * handled equally by this driver.
-	 */
-	if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK)
-		return;
-
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		sdc_set_brightness(mx3fb, 0);
-		memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
-		/* Give LCD time to update - enough for 50 and 60 Hz */
-		msleep(25);
-		sdc_disable_channel(mx3_fbi);
-		break;
-	case FB_BLANK_UNBLANK:
-		sdc_enable_channel(mx3_fbi);
-		sdc_set_brightness(mx3fb, mx3fb->backlight_level);
-		break;
-	}
-}
-
-/**
- * mx3fb_blank() - blank the display.
- */
-static int mx3fb_blank(int blank, struct fb_info *fbi)
-{
-	struct mx3fb_info *mx3_fbi = fbi->par;
-
-	dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
-		blank, fbi->screen_base, fbi->fix.smem_len);
-
-	if (mx3_fbi->blank == blank)
-		return 0;
-
-	mutex_lock(&mx3_fbi->mutex);
-	__blank(blank, fbi);
-	mutex_unlock(&mx3_fbi->mutex);
-
-	return 0;
-}
-
-/**
- * mx3fb_pan_display() - pan or wrap the display
- * @var:	variable screen buffer information.
- * @info:	framebuffer information pointer.
- *
- * We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- */
-static int mx3fb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *fbi)
-{
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	u32 y_bottom;
-	unsigned long base;
-	off_t offset;
-	dma_cookie_t cookie;
-	struct scatterlist *sg = mx3_fbi->sg;
-	struct dma_chan *dma_chan = &mx3_fbi->idmac_channel->dma_chan;
-	struct dma_async_tx_descriptor *txd;
-	int ret;
-
-	dev_dbg(fbi->device, "%s [%c]\n", __func__,
-		list_empty(&mx3_fbi->idmac_channel->queue) ? '-' : '+');
-
-	if (var->xoffset > 0) {
-		dev_dbg(fbi->device, "x panning not supported\n");
-		return -EINVAL;
-	}
-
-	if (mx3_fbi->cur_var.xoffset == var->xoffset &&
-	    mx3_fbi->cur_var.yoffset == var->yoffset)
-		return 0;	/* No change, do nothing */
-
-	y_bottom = var->yoffset;
-
-	if (!(var->vmode & FB_VMODE_YWRAP))
-		y_bottom += fbi->var.yres;
-
-	if (y_bottom > fbi->var.yres_virtual)
-		return -EINVAL;
-
-	mutex_lock(&mx3_fbi->mutex);
-
-	offset = var->yoffset * fbi->fix.line_length
-	       + var->xoffset * (fbi->var.bits_per_pixel / 8);
-	base = fbi->fix.smem_start + offset;
-
-	dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n",
-		mx3_fbi->cur_ipu_buf, base);
-
-	/*
-	 * We enable the End of Frame interrupt, which will free a tx-descriptor,
-	 * which we will need for the next device_prep_slave_sg(). The
-	 * IRQ-handler will disable the IRQ again.
-	 */
-	init_completion(&mx3_fbi->flip_cmpl);
-	enable_irq(mx3_fbi->idmac_channel->eof_irq);
-
-	ret = wait_for_completion_timeout(&mx3_fbi->flip_cmpl, HZ / 10);
-	if (ret <= 0) {
-		mutex_unlock(&mx3_fbi->mutex);
-		dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ?
-			 "user interrupt" : "timeout");
-		disable_irq(mx3_fbi->idmac_channel->eof_irq);
-		return ret ? : -ETIMEDOUT;
-	}
-
-	mx3_fbi->cur_ipu_buf = !mx3_fbi->cur_ipu_buf;
-
-	sg_dma_address(&sg[mx3_fbi->cur_ipu_buf]) = base;
-	sg_set_page(&sg[mx3_fbi->cur_ipu_buf],
-		    virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len,
-		    offset_in_page(fbi->screen_base + offset));
-
-	if (mx3_fbi->txd)
-		async_tx_ack(mx3_fbi->txd);
-
-	txd = dmaengine_prep_slave_sg(dma_chan, sg +
-		mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
-	if (!txd) {
-		dev_err(fbi->device,
-			"Error preparing a DMA transaction descriptor.\n");
-		mutex_unlock(&mx3_fbi->mutex);
-		return -EIO;
-	}
-
-	txd->callback_param	= txd;
-	txd->callback		= mx3fb_dma_done;
-
-	/*
-	 * Emulate original mx3fb behaviour: each new call to idmac_tx_submit()
-	 * should switch to another buffer
-	 */
-	cookie = txd->tx_submit(txd);
-	dev_dbg(fbi->device, "%d: Submit %p #%d\n", __LINE__, txd, cookie);
-	if (cookie < 0) {
-		dev_err(fbi->device,
-			"Error updating SDC buf %d to address=0x%08lX\n",
-			mx3_fbi->cur_ipu_buf, base);
-		mutex_unlock(&mx3_fbi->mutex);
-		return -EIO;
-	}
-
-	mx3_fbi->txd = txd;
-
-	fbi->var.xoffset = var->xoffset;
-	fbi->var.yoffset = var->yoffset;
-
-	if (var->vmode & FB_VMODE_YWRAP)
-		fbi->var.vmode |= FB_VMODE_YWRAP;
-	else
-		fbi->var.vmode &= ~FB_VMODE_YWRAP;
-
-	mx3_fbi->cur_var = fbi->var;
-
-	mutex_unlock(&mx3_fbi->mutex);
-
-	dev_dbg(fbi->device, "Update complete\n");
-
-	return 0;
-}
-
-/*
- * This structure contains the pointers to the control functions that are
- * invoked by the core framebuffer driver to perform operations like
- * blitting, rectangle filling, copy regions and cursor definition.
- */
-static struct fb_ops mx3fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_set_par = mx3fb_set_par,
-	.fb_check_var = mx3fb_check_var,
-	.fb_setcolreg = mx3fb_setcolreg,
-	.fb_pan_display = mx3fb_pan_display,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_blank = mx3fb_blank,
-};
-
-#ifdef CONFIG_PM
-/*
- * Power management hooks.      Note that we won't be called from IRQ context,
- * unlike the blank functions above, so we may sleep.
- */
-
-/*
- * Suspends the framebuffer and blanks the screen. Power management support
- */
-static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
-	struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
-
-	console_lock();
-	fb_set_suspend(mx3fb->fbi, 1);
-	console_unlock();
-
-	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
-		sdc_disable_channel(mx3_fbi);
-		sdc_set_brightness(mx3fb, 0);
-
-	}
-	return 0;
-}
-
-/*
- * Resumes the framebuffer and unblanks the screen. Power management support
- */
-static int mx3fb_resume(struct platform_device *pdev)
-{
-	struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
-	struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
-
-	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
-		sdc_enable_channel(mx3_fbi);
-		sdc_set_brightness(mx3fb, mx3fb->backlight_level);
-	}
-
-	console_lock();
-	fb_set_suspend(mx3fb->fbi, 0);
-	console_unlock();
-
-	return 0;
-}
-#else
-#define mx3fb_suspend   NULL
-#define mx3fb_resume    NULL
-#endif
-
-/*
- * Main framebuffer functions
- */
-
-/**
- * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
- * @fbi:	framebuffer information pointer
- * @mem_len:	length of mapped memory
- * @lock:	do not lock during initialisation
- * @return:	Error code indicating success or failure
- *
- * This buffer is remapped into a non-cached, non-buffered, memory region to
- * allow palette and pixel writes to occur without flushing the cache. Once this
- * area is remapped, all virtual memory access to the video memory should occur
- * at the new region.
- */
-static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
-				  bool lock)
-{
-	int retval = 0;
-	dma_addr_t addr;
-
-	fbi->screen_base = dma_alloc_writecombine(fbi->device,
-						  mem_len,
-						  &addr, GFP_DMA | GFP_KERNEL);
-
-	if (!fbi->screen_base) {
-		dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
-			mem_len);
-		retval = -EBUSY;
-		goto err0;
-	}
-
-	if (lock)
-		mutex_lock(&fbi->mm_lock);
-	fbi->fix.smem_start = addr;
-	fbi->fix.smem_len = mem_len;
-	if (lock)
-		mutex_unlock(&fbi->mm_lock);
-
-	dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n",
-		(uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
-
-	fbi->screen_size = fbi->fix.smem_len;
-
-	/* Clear the screen */
-	memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
-
-	return 0;
-
-err0:
-	fbi->fix.smem_len = 0;
-	fbi->fix.smem_start = 0;
-	fbi->screen_base = NULL;
-	return retval;
-}
-
-/**
- * mx3fb_unmap_video_memory() - de-allocate frame buffer memory.
- * @fbi:	framebuffer information pointer
- * @return:	error code indicating success or failure
- */
-static int mx3fb_unmap_video_memory(struct fb_info *fbi)
-{
-	dma_free_writecombine(fbi->device, fbi->fix.smem_len,
-			      fbi->screen_base, fbi->fix.smem_start);
-
-	fbi->screen_base = NULL;
-	mutex_lock(&fbi->mm_lock);
-	fbi->fix.smem_start = 0;
-	fbi->fix.smem_len = 0;
-	mutex_unlock(&fbi->mm_lock);
-	return 0;
-}
-
-/**
- * mx3fb_init_fbinfo() - initialize framebuffer information object.
- * @return:	initialized framebuffer structure.
- */
-static struct fb_info *mx3fb_init_fbinfo(struct device *dev, struct fb_ops *ops)
-{
-	struct fb_info *fbi;
-	struct mx3fb_info *mx3fbi;
-	int ret;
-
-	/* Allocate sufficient memory for the fb structure */
-	fbi = framebuffer_alloc(sizeof(struct mx3fb_info), dev);
-	if (!fbi)
-		return NULL;
-
-	mx3fbi			= fbi->par;
-	mx3fbi->cookie		= -EINVAL;
-	mx3fbi->cur_ipu_buf	= 0;
-
-	fbi->var.activate	= FB_ACTIVATE_NOW;
-
-	fbi->fbops		= ops;
-	fbi->flags		= FBINFO_FLAG_DEFAULT;
-	fbi->pseudo_palette	= mx3fbi->pseudo_palette;
-
-	mutex_init(&mx3fbi->mutex);
-
-	/* Allocate colormap */
-	ret = fb_alloc_cmap(&fbi->cmap, 16, 0);
-	if (ret < 0) {
-		framebuffer_release(fbi);
-		return NULL;
-	}
-
-	return fbi;
-}
-
-static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
-{
-	struct device *dev = mx3fb->dev;
-	struct mx3fb_platform_data *mx3fb_pdata = dev_get_platdata(dev);
-	const char *name = mx3fb_pdata->name;
-	unsigned int irq;
-	struct fb_info *fbi;
-	struct mx3fb_info *mx3fbi;
-	const struct fb_videomode *mode;
-	int ret, num_modes;
-
-	if (mx3fb_pdata->disp_data_fmt >= ARRAY_SIZE(di_mappings)) {
-		dev_err(dev, "Illegal display data format %d\n",
-				mx3fb_pdata->disp_data_fmt);
-		return -EINVAL;
-	}
-
-	ichan->client = mx3fb;
-	irq = ichan->eof_irq;
-
-	if (ichan->dma_chan.chan_id != IDMAC_SDC_0)
-		return -EINVAL;
-
-	fbi = mx3fb_init_fbinfo(dev, &mx3fb_ops);
-	if (!fbi)
-		return -ENOMEM;
-
-	if (!fb_mode)
-		fb_mode = name;
-
-	if (!fb_mode) {
-		ret = -EINVAL;
-		goto emode;
-	}
-
-	if (mx3fb_pdata->mode && mx3fb_pdata->num_modes) {
-		mode = mx3fb_pdata->mode;
-		num_modes = mx3fb_pdata->num_modes;
-	} else {
-		mode = mx3fb_modedb;
-		num_modes = ARRAY_SIZE(mx3fb_modedb);
-	}
-
-	if (!fb_find_mode(&fbi->var, fbi, fb_mode, mode,
-			  num_modes, NULL, default_bpp)) {
-		ret = -EBUSY;
-		goto emode;
-	}
-
-	fb_videomode_to_modelist(mode, num_modes, &fbi->modelist);
-
-	/* Default Y virtual size is 2x panel size */
-	fbi->var.yres_virtual = fbi->var.yres * 2;
-
-	mx3fb->fbi = fbi;
-
-	/* set Display Interface clock period */
-	mx3fb_write_reg(mx3fb, 0x00100010L, DI_HSP_CLK_PER);
-	/* Might need to trigger HSP clock change - see 44.3.3.8.5 */
-
-	sdc_set_brightness(mx3fb, 255);
-	sdc_set_global_alpha(mx3fb, true, 0xFF);
-	sdc_set_color_key(mx3fb, IDMAC_SDC_0, false, 0);
-
-	mx3fbi			= fbi->par;
-	mx3fbi->idmac_channel	= ichan;
-	mx3fbi->ipu_ch		= ichan->dma_chan.chan_id;
-	mx3fbi->mx3fb		= mx3fb;
-	mx3fbi->blank		= FB_BLANK_NORMAL;
-
-	mx3fb->disp_data_fmt	= mx3fb_pdata->disp_data_fmt;
-
-	init_completion(&mx3fbi->flip_cmpl);
-	disable_irq(ichan->eof_irq);
-	dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
-	ret = __set_par(fbi, false);
-	if (ret < 0)
-		goto esetpar;
-
-	__blank(FB_BLANK_UNBLANK, fbi);
-
-	dev_info(dev, "registered, using mode %s\n", fb_mode);
-
-	ret = register_framebuffer(fbi);
-	if (ret < 0)
-		goto erfb;
-
-	return 0;
-
-erfb:
-esetpar:
-emode:
-	fb_dealloc_cmap(&fbi->cmap);
-	framebuffer_release(fbi);
-
-	return ret;
-}
-
-static bool chan_filter(struct dma_chan *chan, void *arg)
-{
-	struct dma_chan_request *rq = arg;
-	struct device *dev;
-	struct mx3fb_platform_data *mx3fb_pdata;
-
-	if (!imx_dma_is_ipu(chan))
-		return false;
-
-	if (!rq)
-		return false;
-
-	dev = rq->mx3fb->dev;
-	mx3fb_pdata = dev_get_platdata(dev);
-
-	return rq->id == chan->chan_id &&
-		mx3fb_pdata->dma_dev == chan->device->dev;
-}
-
-static void release_fbi(struct fb_info *fbi)
-{
-	mx3fb_unmap_video_memory(fbi);
-
-	fb_dealloc_cmap(&fbi->cmap);
-
-	unregister_framebuffer(fbi);
-	framebuffer_release(fbi);
-}
-
-static int mx3fb_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	int ret;
-	struct resource *sdc_reg;
-	struct mx3fb_data *mx3fb;
-	dma_cap_mask_t mask;
-	struct dma_chan *chan;
-	struct dma_chan_request rq;
-
-	/*
-	 * Display Interface (DI) and Synchronous Display Controller (SDC)
-	 * registers
-	 */
-	sdc_reg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!sdc_reg)
-		return -EINVAL;
-
-	mx3fb = kzalloc(sizeof(*mx3fb), GFP_KERNEL);
-	if (!mx3fb)
-		return -ENOMEM;
-
-	spin_lock_init(&mx3fb->lock);
-
-	mx3fb->reg_base = ioremap(sdc_reg->start, resource_size(sdc_reg));
-	if (!mx3fb->reg_base) {
-		ret = -ENOMEM;
-		goto eremap;
-	}
-
-	pr_debug("Remapped %pR at %p\n", sdc_reg, mx3fb->reg_base);
-
-	/* IDMAC interface */
-	dmaengine_get();
-
-	mx3fb->dev = dev;
-	platform_set_drvdata(pdev, mx3fb);
-
-	rq.mx3fb = mx3fb;
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	dma_cap_set(DMA_PRIVATE, mask);
-	rq.id = IDMAC_SDC_0;
-	chan = dma_request_channel(mask, chan_filter, &rq);
-	if (!chan) {
-		ret = -EBUSY;
-		goto ersdc0;
-	}
-
-	mx3fb->backlight_level = 255;
-
-	ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
-	if (ret < 0)
-		goto eisdc0;
-
-	return 0;
-
-eisdc0:
-	dma_release_channel(chan);
-ersdc0:
-	dmaengine_put();
-	iounmap(mx3fb->reg_base);
-eremap:
-	kfree(mx3fb);
-	dev_err(dev, "mx3fb: failed to register fb\n");
-	return ret;
-}
-
-static int mx3fb_remove(struct platform_device *dev)
-{
-	struct mx3fb_data *mx3fb = platform_get_drvdata(dev);
-	struct fb_info *fbi = mx3fb->fbi;
-	struct mx3fb_info *mx3_fbi = fbi->par;
-	struct dma_chan *chan;
-
-	chan = &mx3_fbi->idmac_channel->dma_chan;
-	release_fbi(fbi);
-
-	dma_release_channel(chan);
-	dmaengine_put();
-
-	iounmap(mx3fb->reg_base);
-	kfree(mx3fb);
-	return 0;
-}
-
-static struct platform_driver mx3fb_driver = {
-	.driver = {
-		.name = MX3FB_NAME,
-		.owner = THIS_MODULE,
-	},
-	.probe = mx3fb_probe,
-	.remove = mx3fb_remove,
-	.suspend = mx3fb_suspend,
-	.resume = mx3fb_resume,
-};
-
-/*
- * Parse user specified options (`video=mx3fb:')
- * example:
- * 	video=mx3fb:bpp=16
- */
-static int __init mx3fb_setup(void)
-{
-#ifndef MODULE
-	char *opt, *options = NULL;
-
-	if (fb_get_options("mx3fb", &options))
-		return -ENODEV;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-		if (!strncmp(opt, "bpp=", 4))
-			default_bpp = simple_strtoul(opt + 4, NULL, 0);
-		else
-			fb_mode = opt;
-	}
-#endif
-
-	return 0;
-}
-
-static int __init mx3fb_init(void)
-{
-	int ret = mx3fb_setup();
-
-	if (ret < 0)
-		return ret;
-
-	ret = platform_driver_register(&mx3fb_driver);
-	return ret;
-}
-
-static void __exit mx3fb_exit(void)
-{
-	platform_driver_unregister(&mx3fb_driver);
-}
-
-module_init(mx3fb_init);
-module_exit(mx3fb_exit);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("MX3 framebuffer driver");
-MODULE_ALIAS("platform:" MX3FB_NAME);
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
deleted file mode 100644
index accf48a2cce4..000000000000
--- a/drivers/video/mxsfb.c
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- * Copyright (C) 2010 Juergen Beisert, Pengutronix
- *
- * This code is based on:
- * Author: Vitaly Wool <vital@embeddedalley.com>
- *
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#define DRIVER_NAME "mxsfb"
-
-/**
- * @file
- * @brief LCDIF driver for i.MX23 and i.MX28
- *
- * The LCDIF support four modes of operation
- * - MPU interface (to drive smart displays) -> not supported yet
- * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
- * - Dotclock interface (to drive LC displays with RGB data and sync signals)
- * - DVI (to drive ITU-R BT656)  -> not supported yet
- *
- * This driver depends on a correct setup of the pins used for this purpose
- * (platform specific).
- *
- * For the developer: Don't forget to set the data bus width to the display
- * in the imx_fb_videomode structure. You will else end up with ugly colours.
- * If you fight against jitter you can vary the clock delay. This is a feature
- * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
- * the required value in the imx_fb_videomode structure.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/fb.h>
-#include <linux/regulator/consumer.h>
-#include <video/of_display_timing.h>
-#include <video/of_videomode.h>
-#include <video/videomode.h>
-
-#define REG_SET	4
-#define REG_CLR	8
-
-#define LCDC_CTRL			0x00
-#define LCDC_CTRL1			0x10
-#define LCDC_V4_CTRL2			0x20
-#define LCDC_V3_TRANSFER_COUNT		0x20
-#define LCDC_V4_TRANSFER_COUNT		0x30
-#define LCDC_V4_CUR_BUF			0x40
-#define LCDC_V4_NEXT_BUF		0x50
-#define LCDC_V3_CUR_BUF			0x30
-#define LCDC_V3_NEXT_BUF		0x40
-#define LCDC_TIMING			0x60
-#define LCDC_VDCTRL0			0x70
-#define LCDC_VDCTRL1			0x80
-#define LCDC_VDCTRL2			0x90
-#define LCDC_VDCTRL3			0xa0
-#define LCDC_VDCTRL4			0xb0
-#define LCDC_DVICTRL0			0xc0
-#define LCDC_DVICTRL1			0xd0
-#define LCDC_DVICTRL2			0xe0
-#define LCDC_DVICTRL3			0xf0
-#define LCDC_DVICTRL4			0x100
-#define LCDC_V4_DATA			0x180
-#define LCDC_V3_DATA			0x1b0
-#define LCDC_V4_DEBUG0			0x1d0
-#define LCDC_V3_DEBUG0			0x1f0
-
-#define CTRL_SFTRST			(1 << 31)
-#define CTRL_CLKGATE			(1 << 30)
-#define CTRL_BYPASS_COUNT		(1 << 19)
-#define CTRL_VSYNC_MODE			(1 << 18)
-#define CTRL_DOTCLK_MODE		(1 << 17)
-#define CTRL_DATA_SELECT		(1 << 16)
-#define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
-#define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
-#define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
-#define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
-#define CTRL_MASTER			(1 << 5)
-#define CTRL_DF16			(1 << 3)
-#define CTRL_DF18			(1 << 2)
-#define CTRL_DF24			(1 << 1)
-#define CTRL_RUN			(1 << 0)
-
-#define CTRL1_FIFO_CLEAR		(1 << 21)
-#define CTRL1_SET_BYTE_PACKAGING(x)	(((x) & 0xf) << 16)
-#define CTRL1_GET_BYTE_PACKAGING(x)	(((x) >> 16) & 0xf)
-
-#define TRANSFER_COUNT_SET_VCOUNT(x)	(((x) & 0xffff) << 16)
-#define TRANSFER_COUNT_GET_VCOUNT(x)	(((x) >> 16) & 0xffff)
-#define TRANSFER_COUNT_SET_HCOUNT(x)	((x) & 0xffff)
-#define TRANSFER_COUNT_GET_HCOUNT(x)	((x) & 0xffff)
-
-
-#define VDCTRL0_ENABLE_PRESENT		(1 << 28)
-#define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
-#define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
-#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
-#define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
-#define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
-#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
-#define VDCTRL0_HALF_LINE		(1 << 19)
-#define VDCTRL0_HALF_LINE_MODE		(1 << 18)
-#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
-#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
-
-#define VDCTRL2_SET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
-#define VDCTRL2_GET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
-
-#define VDCTRL3_MUX_SYNC_SIGNALS	(1 << 29)
-#define VDCTRL3_VSYNC_ONLY		(1 << 28)
-#define SET_HOR_WAIT_CNT(x)		(((x) & 0xfff) << 16)
-#define GET_HOR_WAIT_CNT(x)		(((x) >> 16) & 0xfff)
-#define SET_VERT_WAIT_CNT(x)		((x) & 0xffff)
-#define GET_VERT_WAIT_CNT(x)		((x) & 0xffff)
-
-#define VDCTRL4_SET_DOTCLK_DLY(x)	(((x) & 0x7) << 29) /* v4 only */
-#define VDCTRL4_GET_DOTCLK_DLY(x)	(((x) >> 29) & 0x7) /* v4 only */
-#define VDCTRL4_SYNC_SIGNALS_ON		(1 << 18)
-#define SET_DOTCLK_H_VALID_DATA_CNT(x)	((x) & 0x3ffff)
-
-#define DEBUG0_HSYNC			(1 < 26)
-#define DEBUG0_VSYNC			(1 < 25)
-
-#define MIN_XRES			120
-#define MIN_YRES			120
-
-#define RED 0
-#define GREEN 1
-#define BLUE 2
-#define TRANSP 3
-
-#define STMLCDIF_8BIT  1 /** pixel data bus to the display is of 8 bit width */
-#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
-#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
-#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
-
-#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
-#define MXSFB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* negtive edge sampling */
-
-enum mxsfb_devtype {
-	MXSFB_V3,
-	MXSFB_V4,
-};
-
-/* CPU dependent register offsets */
-struct mxsfb_devdata {
-	unsigned transfer_count;
-	unsigned cur_buf;
-	unsigned next_buf;
-	unsigned debug0;
-	unsigned hs_wdth_mask;
-	unsigned hs_wdth_shift;
-	unsigned ipversion;
-};
-
-struct mxsfb_info {
-	struct fb_info fb_info;
-	struct platform_device *pdev;
-	struct clk *clk;
-	void __iomem *base;	/* registers */
-	unsigned allocated_size;
-	int enabled;
-	unsigned ld_intf_width;
-	unsigned dotclk_delay;
-	const struct mxsfb_devdata *devdata;
-	u32 sync;
-	struct regulator *reg_lcd;
-};
-
-#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
-#define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
-
-static const struct mxsfb_devdata mxsfb_devdata[] = {
-	[MXSFB_V3] = {
-		.transfer_count = LCDC_V3_TRANSFER_COUNT,
-		.cur_buf = LCDC_V3_CUR_BUF,
-		.next_buf = LCDC_V3_NEXT_BUF,
-		.debug0 = LCDC_V3_DEBUG0,
-		.hs_wdth_mask = 0xff,
-		.hs_wdth_shift = 24,
-		.ipversion = 3,
-	},
-	[MXSFB_V4] = {
-		.transfer_count = LCDC_V4_TRANSFER_COUNT,
-		.cur_buf = LCDC_V4_CUR_BUF,
-		.next_buf = LCDC_V4_NEXT_BUF,
-		.debug0 = LCDC_V4_DEBUG0,
-		.hs_wdth_mask = 0x3fff,
-		.hs_wdth_shift = 18,
-		.ipversion = 4,
-	},
-};
-
-#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
-
-/* mask and shift depends on architecture */
-static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
-{
-	return (val & host->devdata->hs_wdth_mask) <<
-		host->devdata->hs_wdth_shift;
-}
-
-static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
-{
-	return (val >> host->devdata->hs_wdth_shift) &
-		host->devdata->hs_wdth_mask;
-}
-
-static const struct fb_bitfield def_rgb565[] = {
-	[RED] = {
-		.offset = 11,
-		.length = 5,
-	},
-	[GREEN] = {
-		.offset = 5,
-		.length = 6,
-	},
-	[BLUE] = {
-		.offset = 0,
-		.length = 5,
-	},
-	[TRANSP] = {	/* no support for transparency */
-		.length = 0,
-	}
-};
-
-static const struct fb_bitfield def_rgb888[] = {
-	[RED] = {
-		.offset = 16,
-		.length = 8,
-	},
-	[GREEN] = {
-		.offset = 8,
-		.length = 8,
-	},
-	[BLUE] = {
-		.offset = 0,
-		.length = 8,
-	},
-	[TRANSP] = {	/* no support for transparency */
-		.length = 0,
-	}
-};
-
-static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int mxsfb_check_var(struct fb_var_screeninfo *var,
-		struct fb_info *fb_info)
-{
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-	const struct fb_bitfield *rgb = NULL;
-
-	if (var->xres < MIN_XRES)
-		var->xres = MIN_XRES;
-	if (var->yres < MIN_YRES)
-		var->yres = MIN_YRES;
-
-	var->xres_virtual = var->xres;
-
-	var->yres_virtual = var->yres;
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		/* always expect RGB 565 */
-		rgb = def_rgb565;
-		break;
-	case 32:
-		switch (host->ld_intf_width) {
-		case STMLCDIF_8BIT:
-			pr_debug("Unsupported LCD bus width mapping\n");
-			break;
-		case STMLCDIF_16BIT:
-		case STMLCDIF_18BIT:
-		case STMLCDIF_24BIT:
-			/* real 24 bit */
-			rgb = def_rgb888;
-			break;
-		}
-		break;
-	default:
-		pr_err("Unsupported colour depth: %u\n", var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	/*
-	 * Copy the RGB parameters for this display
-	 * from the machine specific parameters.
-	 */
-	var->red    = rgb[RED];
-	var->green  = rgb[GREEN];
-	var->blue   = rgb[BLUE];
-	var->transp = rgb[TRANSP];
-
-	return 0;
-}
-
-static void mxsfb_enable_controller(struct fb_info *fb_info)
-{
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-	u32 reg;
-	int ret;
-
-	dev_dbg(&host->pdev->dev, "%s\n", __func__);
-
-	if (host->reg_lcd) {
-		ret = regulator_enable(host->reg_lcd);
-		if (ret) {
-			dev_err(&host->pdev->dev,
-				"lcd regulator enable failed:	%d\n", ret);
-			return;
-		}
-	}
-
-	clk_prepare_enable(host->clk);
-	clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
-
-	/* if it was disabled, re-enable the mode again */
-	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
-
-	/* enable the SYNC signals first, then the DMA engine */
-	reg = readl(host->base + LCDC_VDCTRL4);
-	reg |= VDCTRL4_SYNC_SIGNALS_ON;
-	writel(reg, host->base + LCDC_VDCTRL4);
-
-	writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
-
-	host->enabled = 1;
-}
-
-static void mxsfb_disable_controller(struct fb_info *fb_info)
-{
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-	unsigned loop;
-	u32 reg;
-	int ret;
-
-	dev_dbg(&host->pdev->dev, "%s\n", __func__);
-
-	/*
-	 * Even if we disable the controller here, it will still continue
-	 * until its FIFOs are running out of data
-	 */
-	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR);
-
-	loop = 1000;
-	while (loop) {
-		reg = readl(host->base + LCDC_CTRL);
-		if (!(reg & CTRL_RUN))
-			break;
-		loop--;
-	}
-
-	reg = readl(host->base + LCDC_VDCTRL4);
-	writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
-
-	clk_disable_unprepare(host->clk);
-
-	host->enabled = 0;
-
-	if (host->reg_lcd) {
-		ret = regulator_disable(host->reg_lcd);
-		if (ret)
-			dev_err(&host->pdev->dev,
-				"lcd regulator disable failed: %d\n", ret);
-	}
-}
-
-static int mxsfb_set_par(struct fb_info *fb_info)
-{
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-	u32 ctrl, vdctrl0, vdctrl4;
-	int line_size, fb_size;
-	int reenable = 0;
-
-	line_size =  fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
-	fb_size = fb_info->var.yres_virtual * line_size;
-
-	if (fb_size > fb_info->fix.smem_len)
-		return -ENOMEM;
-
-	fb_info->fix.line_length = line_size;
-
-	/*
-	 * It seems, you can't re-program the controller if it is still running.
-	 * This may lead into shifted pictures (FIFO issue?).
-	 * So, first stop the controller and drain its FIFOs
-	 */
-	if (host->enabled) {
-		reenable = 1;
-		mxsfb_disable_controller(fb_info);
-	}
-
-	/* clear the FIFOs */
-	writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
-
-	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
-		CTRL_SET_BUS_WIDTH(host->ld_intf_width);
-
-	switch (fb_info->var.bits_per_pixel) {
-	case 16:
-		dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
-		ctrl |= CTRL_SET_WORD_LENGTH(0);
-		writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
-		break;
-	case 32:
-		dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
-		ctrl |= CTRL_SET_WORD_LENGTH(3);
-		switch (host->ld_intf_width) {
-		case STMLCDIF_8BIT:
-			dev_err(&host->pdev->dev,
-					"Unsupported LCD bus width mapping\n");
-			return -EINVAL;
-		case STMLCDIF_16BIT:
-		case STMLCDIF_18BIT:
-		case STMLCDIF_24BIT:
-			/* real 24 bit */
-			break;
-		}
-		/* do not use packed pixels = one pixel per word instead */
-		writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
-		break;
-	default:
-		dev_err(&host->pdev->dev, "Unhandled color depth of %u\n",
-				fb_info->var.bits_per_pixel);
-		return -EINVAL;
-	}
-
-	writel(ctrl, host->base + LCDC_CTRL);
-
-	writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
-			TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
-			host->base + host->devdata->transfer_count);
-
-	vdctrl0 = VDCTRL0_ENABLE_PRESENT |	/* always in DOTCLOCK mode */
-		VDCTRL0_VSYNC_PERIOD_UNIT |
-		VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
-		VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
-	if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
-	if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
-	if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
-		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
-	if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT)
-		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
-
-	writel(vdctrl0, host->base + LCDC_VDCTRL0);
-
-	/* frame length in lines */
-	writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
-		fb_info->var.lower_margin + fb_info->var.yres,
-		host->base + LCDC_VDCTRL1);
-
-	/* line length in units of clocks or pixels */
-	writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
-		VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
-		fb_info->var.hsync_len + fb_info->var.right_margin +
-		fb_info->var.xres),
-		host->base + LCDC_VDCTRL2);
-
-	writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
-		fb_info->var.hsync_len) |
-		SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
-			fb_info->var.vsync_len),
-		host->base + LCDC_VDCTRL3);
-
-	vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
-	if (mxsfb_is_v4(host))
-		vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
-	writel(vdctrl4, host->base + LCDC_VDCTRL4);
-
-	writel(fb_info->fix.smem_start +
-			fb_info->fix.line_length * fb_info->var.yoffset,
-			host->base + host->devdata->next_buf);
-
-	if (reenable)
-		mxsfb_enable_controller(fb_info);
-
-	return 0;
-}
-
-static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		u_int transp, struct fb_info *fb_info)
-{
-	unsigned int val;
-	int ret = -EINVAL;
-
-	/*
-	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no matter what visual we are using.
-	 */
-	if (fb_info->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-					7471 * blue) >> 16;
-
-	switch (fb_info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 12 or 16-bit True Colour.  We encode the RGB value
-		 * according to the RGB bitfield information.
-		 */
-		if (regno < 16) {
-			u32 *pal = fb_info->pseudo_palette;
-
-			val  = chan_to_field(red, &fb_info->var.red);
-			val |= chan_to_field(green, &fb_info->var.green);
-			val |= chan_to_field(blue, &fb_info->var.blue);
-
-			pal[regno] = val;
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_STATIC_PSEUDOCOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		break;
-	}
-
-	return ret;
-}
-
-static int mxsfb_blank(int blank, struct fb_info *fb_info)
-{
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		if (host->enabled)
-			mxsfb_disable_controller(fb_info);
-		break;
-
-	case FB_BLANK_UNBLANK:
-		if (!host->enabled)
-			mxsfb_enable_controller(fb_info);
-		break;
-	}
-	return 0;
-}
-
-static int mxsfb_pan_display(struct fb_var_screeninfo *var,
-		struct fb_info *fb_info)
-{
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-	unsigned offset;
-
-	if (var->xoffset != 0)
-		return -EINVAL;
-
-	offset = fb_info->fix.line_length * var->yoffset;
-
-	/* update on next VSYNC */
-	writel(fb_info->fix.smem_start + offset,
-			host->base + host->devdata->next_buf);
-
-	return 0;
-}
-
-static struct fb_ops mxsfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = mxsfb_check_var,
-	.fb_set_par = mxsfb_set_par,
-	.fb_setcolreg = mxsfb_setcolreg,
-	.fb_blank = mxsfb_blank,
-	.fb_pan_display = mxsfb_pan_display,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-};
-
-static int mxsfb_restore_mode(struct mxsfb_info *host,
-			struct fb_videomode *vmode)
-{
-	struct fb_info *fb_info = &host->fb_info;
-	unsigned line_count;
-	unsigned period;
-	unsigned long pa, fbsize;
-	int bits_per_pixel, ofs;
-	u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
-
-	/* Only restore the mode when the controller is running */
-	ctrl = readl(host->base + LCDC_CTRL);
-	if (!(ctrl & CTRL_RUN))
-		return -EINVAL;
-
-	vdctrl0 = readl(host->base + LCDC_VDCTRL0);
-	vdctrl2 = readl(host->base + LCDC_VDCTRL2);
-	vdctrl3 = readl(host->base + LCDC_VDCTRL3);
-	vdctrl4 = readl(host->base + LCDC_VDCTRL4);
-
-	transfer_count = readl(host->base + host->devdata->transfer_count);
-
-	vmode->xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
-	vmode->yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
-
-	switch (CTRL_GET_WORD_LENGTH(ctrl)) {
-	case 0:
-		bits_per_pixel = 16;
-		break;
-	case 3:
-		bits_per_pixel = 32;
-		break;
-	case 1:
-	default:
-		return -EINVAL;
-	}
-
-	fb_info->var.bits_per_pixel = bits_per_pixel;
-
-	vmode->pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U);
-	vmode->hsync_len = get_hsync_pulse_width(host, vdctrl2);
-	vmode->left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode->hsync_len;
-	vmode->right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) -
-		vmode->hsync_len - vmode->left_margin - vmode->xres;
-	vmode->vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
-	period = readl(host->base + LCDC_VDCTRL1);
-	vmode->upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode->vsync_len;
-	vmode->lower_margin = period - vmode->vsync_len -
-		vmode->upper_margin - vmode->yres;
-
-	vmode->vmode = FB_VMODE_NONINTERLACED;
-
-	vmode->sync = 0;
-	if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
-		vmode->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
-		vmode->sync |= FB_SYNC_VERT_HIGH_ACT;
-
-	pr_debug("Reconstructed video mode:\n");
-	pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
-		vmode->xres, vmode->yres, vmode->hsync_len, vmode->left_margin,
-		vmode->right_margin, vmode->vsync_len, vmode->upper_margin,
-		vmode->lower_margin);
-	pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode->pixclock));
-
-	host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
-	host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
-
-	fb_info->fix.line_length = vmode->xres * (bits_per_pixel >> 3);
-
-	pa = readl(host->base + host->devdata->cur_buf);
-	fbsize = fb_info->fix.line_length * vmode->yres;
-	if (pa < fb_info->fix.smem_start)
-		return -EINVAL;
-	if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
-		return -EINVAL;
-	ofs = pa - fb_info->fix.smem_start;
-	if (ofs) {
-		memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
-		writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
-	}
-
-	line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
-	fb_info->fix.ypanstep = 1;
-
-	clk_prepare_enable(host->clk);
-	host->enabled = 1;
-
-	return 0;
-}
-
-static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host,
-				struct fb_videomode *vmode)
-{
-	struct fb_info *fb_info = &host->fb_info;
-	struct fb_var_screeninfo *var = &fb_info->var;
-	struct device *dev = &host->pdev->dev;
-	struct device_node *np = host->pdev->dev.of_node;
-	struct device_node *display_np;
-	struct videomode vm;
-	u32 width;
-	int ret;
-
-	display_np = of_parse_phandle(np, "display", 0);
-	if (!display_np) {
-		dev_err(dev, "failed to find display phandle\n");
-		return -ENOENT;
-	}
-
-	ret = of_property_read_u32(display_np, "bus-width", &width);
-	if (ret < 0) {
-		dev_err(dev, "failed to get property bus-width\n");
-		goto put_display_node;
-	}
-
-	switch (width) {
-	case 8:
-		host->ld_intf_width = STMLCDIF_8BIT;
-		break;
-	case 16:
-		host->ld_intf_width = STMLCDIF_16BIT;
-		break;
-	case 18:
-		host->ld_intf_width = STMLCDIF_18BIT;
-		break;
-	case 24:
-		host->ld_intf_width = STMLCDIF_24BIT;
-		break;
-	default:
-		dev_err(dev, "invalid bus-width value\n");
-		ret = -EINVAL;
-		goto put_display_node;
-	}
-
-	ret = of_property_read_u32(display_np, "bits-per-pixel",
-				   &var->bits_per_pixel);
-	if (ret < 0) {
-		dev_err(dev, "failed to get property bits-per-pixel\n");
-		goto put_display_node;
-	}
-
-	ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE);
-	if (ret) {
-		dev_err(dev, "failed to get videomode from DT\n");
-		goto put_display_node;
-	}
-
-	ret = fb_videomode_from_videomode(&vm, vmode);
-	if (ret < 0)
-		goto put_display_node;
-
-	if (vm.flags & DISPLAY_FLAGS_DE_HIGH)
-		host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
-	if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
-		host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT;
-
-put_display_node:
-	of_node_put(display_np);
-	return ret;
-}
-
-static int mxsfb_init_fbinfo(struct mxsfb_info *host,
-			struct fb_videomode *vmode)
-{
-	int ret;
-	struct fb_info *fb_info = &host->fb_info;
-	struct fb_var_screeninfo *var = &fb_info->var;
-	dma_addr_t fb_phys;
-	void *fb_virt;
-	unsigned fb_size;
-
-	fb_info->fbops = &mxsfb_ops;
-	fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
-	strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id));
-	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
-	fb_info->fix.ypanstep = 1;
-	fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
-	fb_info->fix.accel = FB_ACCEL_NONE;
-
-	ret = mxsfb_init_fbinfo_dt(host, vmode);
-	if (ret)
-		return ret;
-
-	var->nonstd = 0;
-	var->activate = FB_ACTIVATE_NOW;
-	var->accel_flags = 0;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	/* Memory allocation for framebuffer */
-	fb_size = SZ_2M;
-	fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
-	if (!fb_virt)
-		return -ENOMEM;
-
-	fb_phys = virt_to_phys(fb_virt);
-
-	fb_info->fix.smem_start = fb_phys;
-	fb_info->screen_base = fb_virt;
-	fb_info->screen_size = fb_info->fix.smem_len = fb_size;
-
-	if (mxsfb_restore_mode(host, vmode))
-		memset(fb_virt, 0, fb_size);
-
-	return 0;
-}
-
-static void mxsfb_free_videomem(struct mxsfb_info *host)
-{
-	struct fb_info *fb_info = &host->fb_info;
-
-	free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
-}
-
-static struct platform_device_id mxsfb_devtype[] = {
-	{
-		.name = "imx23-fb",
-		.driver_data = MXSFB_V3,
-	}, {
-		.name = "imx28-fb",
-		.driver_data = MXSFB_V4,
-	}, {
-		/* sentinel */
-	}
-};
-MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
-
-static const struct of_device_id mxsfb_dt_ids[] = {
-	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
-	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
-
-static int mxsfb_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-			of_match_device(mxsfb_dt_ids, &pdev->dev);
-	struct resource *res;
-	struct mxsfb_info *host;
-	struct fb_info *fb_info;
-	struct fb_videomode *mode;
-	int ret;
-
-	if (of_id)
-		pdev->id_entry = of_id->data;
-
-	fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
-	if (!fb_info) {
-		dev_err(&pdev->dev, "Failed to allocate fbdev\n");
-		return -ENOMEM;
-	}
-
-	mode = devm_kzalloc(&pdev->dev, sizeof(struct fb_videomode),
-			GFP_KERNEL);
-	if (mode == NULL)
-		return -ENOMEM;
-
-	host = to_imxfb_host(fb_info);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	host->base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(host->base)) {
-		ret = PTR_ERR(host->base);
-		goto fb_release;
-	}
-
-	host->pdev = pdev;
-	platform_set_drvdata(pdev, host);
-
-	host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
-
-	host->clk = devm_clk_get(&host->pdev->dev, NULL);
-	if (IS_ERR(host->clk)) {
-		ret = PTR_ERR(host->clk);
-		goto fb_release;
-	}
-
-	host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");
-	if (IS_ERR(host->reg_lcd))
-		host->reg_lcd = NULL;
-
-	fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
-					       GFP_KERNEL);
-	if (!fb_info->pseudo_palette) {
-		ret = -ENOMEM;
-		goto fb_release;
-	}
-
-	ret = mxsfb_init_fbinfo(host, mode);
-	if (ret != 0)
-		goto fb_release;
-
-	fb_videomode_to_var(&fb_info->var, mode);
-
-	/* init the color fields */
-	mxsfb_check_var(&fb_info->var, fb_info);
-
-	platform_set_drvdata(pdev, fb_info);
-
-	ret = register_framebuffer(fb_info);
-	if (ret != 0) {
-		dev_err(&pdev->dev,"Failed to register framebuffer\n");
-		goto fb_destroy;
-	}
-
-	if (!host->enabled) {
-		writel(0, host->base + LCDC_CTRL);
-		mxsfb_set_par(fb_info);
-		mxsfb_enable_controller(fb_info);
-	}
-
-	dev_info(&pdev->dev, "initialized\n");
-
-	return 0;
-
-fb_destroy:
-	if (host->enabled)
-		clk_disable_unprepare(host->clk);
-fb_release:
-	framebuffer_release(fb_info);
-
-	return ret;
-}
-
-static int mxsfb_remove(struct platform_device *pdev)
-{
-	struct fb_info *fb_info = platform_get_drvdata(pdev);
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-
-	if (host->enabled)
-		mxsfb_disable_controller(fb_info);
-
-	unregister_framebuffer(fb_info);
-	mxsfb_free_videomem(host);
-
-	framebuffer_release(fb_info);
-
-	return 0;
-}
-
-static void mxsfb_shutdown(struct platform_device *pdev)
-{
-	struct fb_info *fb_info = platform_get_drvdata(pdev);
-	struct mxsfb_info *host = to_imxfb_host(fb_info);
-
-	/*
-	 * Force stop the LCD controller as keeping it running during reboot
-	 * might interfere with the BootROM's boot mode pads sampling.
-	 */
-	writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
-}
-
-static struct platform_driver mxsfb_driver = {
-	.probe = mxsfb_probe,
-	.remove = mxsfb_remove,
-	.shutdown = mxsfb_shutdown,
-	.id_table = mxsfb_devtype,
-	.driver = {
-		   .name = DRIVER_NAME,
-		   .of_match_table = mxsfb_dt_ids,
-	},
-};
-
-module_platform_driver(mxsfb_driver);
-
-MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/n411.c b/drivers/video/n411.c
deleted file mode 100644
index 935830fea7b6..000000000000
--- a/drivers/video/n411.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * linux/drivers/video/n411.c -- Platform device for N411 EPD kit
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This driver is written to be used with the Hecuba display controller
- * board, and tested with the EInk 800x600 display in 1 bit mode.
- * The interface between Hecuba and the host is TTL based GPIO. The
- * GPIO requirements are 8 writable data lines and 6 lines for control.
- * Only 4 of the controls are actually used here but 6 for future use.
- * The driver requires the IO addresses for data and control GPIO at
- * load time. It is also possible to use this display with a standard
- * PC parallel port.
- *
- * General notes:
- * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/uaccess.h>
-#include <linux/irq.h>
-
-#include <video/hecubafb.h>
-
-static unsigned long dio_addr;
-static unsigned long cio_addr;
-static unsigned long c2io_addr;
-static unsigned long splashval;
-static unsigned int nosplash;
-static unsigned char ctl;
-
-static void n411_set_ctl(struct hecubafb_par *par, unsigned char bit, unsigned
-							char state)
-{
-	switch (bit) {
-	case HCB_CD_BIT:
-		if (state)
-			ctl &= ~(HCB_CD_BIT);
-		else
-			ctl |= HCB_CD_BIT;
-		break;
-	case HCB_DS_BIT:
-		if (state)
-			ctl &= ~(HCB_DS_BIT);
-		else
-			ctl |= HCB_DS_BIT;
-		break;
-	}
-	outb(ctl, cio_addr);
-}
-
-static unsigned char n411_get_ctl(struct hecubafb_par *par)
-{
-	return inb(c2io_addr);
-}
-
-static void n411_set_data(struct hecubafb_par *par, unsigned char value)
-{
-	outb(value, dio_addr);
-}
-
-static void n411_wait_for_ack(struct hecubafb_par *par, int clear)
-{
-	int timeout;
-	unsigned char tmp;
-
-	timeout = 500;
-	do {
-		tmp = n411_get_ctl(par);
-		if ((tmp & HCB_ACK_BIT) && (!clear))
-			return;
-		else if (!(tmp & HCB_ACK_BIT) && (clear))
-			return;
-		udelay(1);
-	} while (timeout--);
-	printk(KERN_ERR "timed out waiting for ack\n");
-}
-
-static int n411_init_control(struct hecubafb_par *par)
-{
-	unsigned char tmp;
-	/* for init, we want the following setup to be set:
-	WUP = lo
-	ACK = hi
-	DS = hi
-	RW = hi
-	CD = lo
-	*/
-
-	/* write WUP to lo, DS to hi, RW to hi, CD to lo */
-	ctl = HCB_WUP_BIT | HCB_RW_BIT | HCB_CD_BIT ;
-	n411_set_ctl(par, HCB_DS_BIT, 1);
-
-	/* check ACK is not lo */
-	tmp = n411_get_ctl(par);
-	if (tmp & HCB_ACK_BIT) {
-		printk(KERN_ERR "Fail because ACK is already low\n");
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-
-static int n411_init_board(struct hecubafb_par *par)
-{
-	int retval;
-
-	retval = n411_init_control(par);
-	if (retval)
-		return retval;
-
-	par->send_command(par, APOLLO_INIT_DISPLAY);
-	par->send_data(par, 0x81);
-
-	/* have to wait while display resets */
-	udelay(1000);
-
-	/* if we were told to splash the screen, we just clear it */
-	if (!nosplash) {
-		par->send_command(par, APOLLO_ERASE_DISPLAY);
-		par->send_data(par, splashval);
-	}
-
-	return 0;
-}
-
-static struct hecuba_board n411_board = {
-	.owner			= THIS_MODULE,
-	.init			= n411_init_board,
-	.set_ctl		= n411_set_ctl,
-	.set_data		= n411_set_data,
-	.wait_for_ack		= n411_wait_for_ack,
-};
-
-static struct platform_device *n411_device;
-static int __init n411_init(void)
-{
-	int ret;
-	if (!dio_addr || !cio_addr || !c2io_addr) {
-		printk(KERN_WARNING "no IO addresses supplied\n");
-		return -EINVAL;
-	}
-
-	/* request our platform independent driver */
-	request_module("hecubafb");
-
-	n411_device = platform_device_alloc("hecubafb", -1);
-	if (!n411_device)
-		return -ENOMEM;
-
-	platform_device_add_data(n411_device, &n411_board, sizeof(n411_board));
-
-	/* this _add binds hecubafb to n411. hecubafb refcounts n411 */
-	ret = platform_device_add(n411_device);
-
-	if (ret)
-		platform_device_put(n411_device);
-
-	return ret;
-
-}
-
-static void __exit n411_exit(void)
-{
-	platform_device_unregister(n411_device);
-}
-
-module_init(n411_init);
-module_exit(n411_exit);
-
-module_param(nosplash, uint, 0);
-MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
-module_param(dio_addr, ulong, 0);
-MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
-module_param(cio_addr, ulong, 0);
-MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
-module_param(c2io_addr, ulong, 0);
-MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
-module_param(splashval, ulong, 0);
-MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
-
-MODULE_DESCRIPTION("board driver for n411 hecuba/apollo epd kit");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
deleted file mode 100644
index 44f99a60bb9b..000000000000
--- a/drivers/video/neofb.c
+++ /dev/null
@@ -1,2247 +0,0 @@
-/*
- * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
- *
- * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
- *
- *
- * Card specific code is based on XFree86's neomagic driver.
- * Framebuffer framework code is based on code of cyber2000fb.
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- *
- * 0.4.1
- *  - Cosmetic changes (dok)
- *
- * 0.4
- *  - Toshiba Libretto support, allow modes larger than LCD size if
- *    LCD is disabled, keep BIOS settings if internal/external display
- *    haven't been enabled explicitly
- *                          (Thomas J. Moore <dark@mama.indstate.edu>)
- *
- * 0.3.3
- *  - Porting over to new fbdev api. (jsimmons)
- *  
- * 0.3.2
- *  - got rid of all floating point (dok) 
- *
- * 0.3.1
- *  - added module license (dok)
- *
- * 0.3
- *  - hardware accelerated clear and move for 2200 and above (dok)
- *  - maximum allowed dotclock is handled now (dok)
- *
- * 0.2.1
- *  - correct panning after X usage (dok)
- *  - added module and kernel parameters (dok)
- *  - no stretching if external display is enabled (dok)
- *
- * 0.2
- *  - initial version (dok)
- *
- *
- * TODO
- * - ioctl for internal/external switching
- * - blanking
- * - 32bit depth support, maybe impossible
- * - disable pan-on-sync, need specs
- *
- * BUGS
- * - white margin on bootup like with tdfxfb (colormap problem?)
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#ifdef CONFIG_TOSHIBA
-#include <linux/toshiba.h>
-#endif
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/vga.h>
-#include <video/neomagic.h>
-
-#define NEOFB_VERSION "0.4.2"
-
-/* --------------------------------------------------------------------- */
-
-static bool internal;
-static bool external;
-static bool libretto;
-static bool nostretch;
-static bool nopciburst;
-static char *mode_option = NULL;
-
-#ifdef MODULE
-
-MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@convergence.de>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
-module_param(internal, bool, 0);
-MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
-module_param(external, bool, 0);
-MODULE_PARM_DESC(external, "Enable output on external CRT.");
-module_param(libretto, bool, 0);
-MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD.");
-module_param(nostretch, bool, 0);
-MODULE_PARM_DESC(nostretch,
-		 "Disable stretching of modes smaller than LCD.");
-module_param(nopciburst, bool, 0);
-MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
-
-#endif
-
-
-/* --------------------------------------------------------------------- */
-
-static biosMode bios8[] = {
-	{320, 240, 0x40},
-	{300, 400, 0x42},
-	{640, 400, 0x20},
-	{640, 480, 0x21},
-	{800, 600, 0x23},
-	{1024, 768, 0x25},
-};
-
-static biosMode bios16[] = {
-	{320, 200, 0x2e},
-	{320, 240, 0x41},
-	{300, 400, 0x43},
-	{640, 480, 0x31},
-	{800, 600, 0x34},
-	{1024, 768, 0x37},
-};
-
-static biosMode bios24[] = {
-	{640, 480, 0x32},
-	{800, 600, 0x35},
-	{1024, 768, 0x38}
-};
-
-#ifdef NO_32BIT_SUPPORT_YET
-/* FIXME: guessed values, wrong */
-static biosMode bios32[] = {
-	{640, 480, 0x33},
-	{800, 600, 0x36},
-	{1024, 768, 0x39}
-};
-#endif
-
-static inline void write_le32(int regindex, u32 val, const struct neofb_par *par)
-{
-	writel(val, par->neo2200 + par->cursorOff + regindex);
-}
-
-static int neoFindMode(int xres, int yres, int depth)
-{
-	int xres_s;
-	int i, size;
-	biosMode *mode;
-
-	switch (depth) {
-	case 8:
-		size = ARRAY_SIZE(bios8);
-		mode = bios8;
-		break;
-	case 16:
-		size = ARRAY_SIZE(bios16);
-		mode = bios16;
-		break;
-	case 24:
-		size = ARRAY_SIZE(bios24);
-		mode = bios24;
-		break;
-#ifdef NO_32BIT_SUPPORT_YET
-	case 32:
-		size = ARRAY_SIZE(bios32);
-		mode = bios32;
-		break;
-#endif
-	default:
-		return 0;
-	}
-
-	for (i = 0; i < size; i++) {
-		if (xres <= mode[i].x_res) {
-			xres_s = mode[i].x_res;
-			for (; i < size; i++) {
-				if (mode[i].x_res != xres_s)
-					return mode[i - 1].mode;
-				if (yres <= mode[i].y_res)
-					return mode[i].mode;
-			}
-		}
-	}
-	return mode[size - 1].mode;
-}
-
-/*
- * neoCalcVCLK --
- *
- * Determine the closest clock frequency to the one requested.
- */
-#define MAX_N 127
-#define MAX_D 31
-#define MAX_F 1
-
-static void neoCalcVCLK(const struct fb_info *info,
-			struct neofb_par *par, long freq)
-{
-	int n, d, f;
-	int n_best = 0, d_best = 0, f_best = 0;
-	long f_best_diff = 0x7ffff;
-
-	for (f = 0; f <= MAX_F; f++)
-		for (d = 0; d <= MAX_D; d++)
-			for (n = 0; n <= MAX_N; n++) {
-				long f_out;
-				long f_diff;
-
-				f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
-				f_diff = abs(f_out - freq);
-				if (f_diff <= f_best_diff) {
-					f_best_diff = f_diff;
-					n_best = n;
-					d_best = d;
-					f_best = f;
-				}
-				if (f_out > freq)
-					break;
-			}
-
-	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
-		/* NOT_DONE:  We are trying the full range of the 2200 clock.
-		   We should be able to try n up to 2047 */
-		par->VCLK3NumeratorLow = n_best;
-		par->VCLK3NumeratorHigh = (f_best << 7);
-	} else
-		par->VCLK3NumeratorLow = n_best | (f_best << 7);
-
-	par->VCLK3Denominator = d_best;
-
-#ifdef NEOFB_DEBUG
-	printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
-	       freq,
-	       par->VCLK3NumeratorLow,
-	       par->VCLK3NumeratorHigh,
-	       par->VCLK3Denominator, f_best_diff);
-#endif
-}
-
-/*
- * vgaHWInit --
- *      Handle the initialization, etc. of a screen.
- *      Return FALSE on failure.
- */
-
-static int vgaHWInit(const struct fb_var_screeninfo *var,
-		     struct neofb_par *par)
-{
-	int hsync_end = var->xres + var->right_margin + var->hsync_len;
-	int htotal = (hsync_end + var->left_margin) >> 3;
-	int vsync_start = var->yres + var->lower_margin;
-	int vsync_end = vsync_start + var->vsync_len;
-	int vtotal = vsync_end + var->upper_margin;
-
-	par->MiscOutReg = 0x23;
-
-	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
-		par->MiscOutReg |= 0x40;
-
-	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
-		par->MiscOutReg |= 0x80;
-
-	/*
-	 * Time Sequencer
-	 */
-	par->Sequencer[0] = 0x00;
-	par->Sequencer[1] = 0x01;
-	par->Sequencer[2] = 0x0F;
-	par->Sequencer[3] = 0x00;	/* Font select */
-	par->Sequencer[4] = 0x0E;	/* Misc */
-
-	/*
-	 * CRTC Controller
-	 */
-	par->CRTC[0] = htotal - 5;
-	par->CRTC[1] = (var->xres >> 3) - 1;
-	par->CRTC[2] = (var->xres >> 3) - 1;
-	par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
-	par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
-	par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
-	    | (((hsync_end >> 3)) & 0x1F);
-	par->CRTC[6] = (vtotal - 2) & 0xFF;
-	par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
-	    | (((var->yres - 1) & 0x100) >> 7)
-	    | ((vsync_start & 0x100) >> 6)
-	    | (((var->yres - 1) & 0x100) >> 5)
-	    | 0x10 | (((vtotal - 2) & 0x200) >> 4)
-	    | (((var->yres - 1) & 0x200) >> 3)
-	    | ((vsync_start & 0x200) >> 2);
-	par->CRTC[8] = 0x00;
-	par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
-
-	if (var->vmode & FB_VMODE_DOUBLE)
-		par->CRTC[9] |= 0x80;
-
-	par->CRTC[10] = 0x00;
-	par->CRTC[11] = 0x00;
-	par->CRTC[12] = 0x00;
-	par->CRTC[13] = 0x00;
-	par->CRTC[14] = 0x00;
-	par->CRTC[15] = 0x00;
-	par->CRTC[16] = vsync_start & 0xFF;
-	par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
-	par->CRTC[18] = (var->yres - 1) & 0xFF;
-	par->CRTC[19] = var->xres_virtual >> 4;
-	par->CRTC[20] = 0x00;
-	par->CRTC[21] = (var->yres - 1) & 0xFF;
-	par->CRTC[22] = (vtotal - 1) & 0xFF;
-	par->CRTC[23] = 0xC3;
-	par->CRTC[24] = 0xFF;
-
-	/*
-	 * are these unnecessary?
-	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
-	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
-	 */
-
-	/*
-	 * Graphics Display Controller
-	 */
-	par->Graphics[0] = 0x00;
-	par->Graphics[1] = 0x00;
-	par->Graphics[2] = 0x00;
-	par->Graphics[3] = 0x00;
-	par->Graphics[4] = 0x00;
-	par->Graphics[5] = 0x40;
-	par->Graphics[6] = 0x05;	/* only map 64k VGA memory !!!! */
-	par->Graphics[7] = 0x0F;
-	par->Graphics[8] = 0xFF;
-
-
-	par->Attribute[0] = 0x00;	/* standard colormap translation */
-	par->Attribute[1] = 0x01;
-	par->Attribute[2] = 0x02;
-	par->Attribute[3] = 0x03;
-	par->Attribute[4] = 0x04;
-	par->Attribute[5] = 0x05;
-	par->Attribute[6] = 0x06;
-	par->Attribute[7] = 0x07;
-	par->Attribute[8] = 0x08;
-	par->Attribute[9] = 0x09;
-	par->Attribute[10] = 0x0A;
-	par->Attribute[11] = 0x0B;
-	par->Attribute[12] = 0x0C;
-	par->Attribute[13] = 0x0D;
-	par->Attribute[14] = 0x0E;
-	par->Attribute[15] = 0x0F;
-	par->Attribute[16] = 0x41;
-	par->Attribute[17] = 0xFF;
-	par->Attribute[18] = 0x0F;
-	par->Attribute[19] = 0x00;
-	par->Attribute[20] = 0x00;
-	return 0;
-}
-
-static void vgaHWLock(struct vgastate *state)
-{
-	/* Protect CRTC[0-7] */
-	vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80);
-}
-
-static void vgaHWUnlock(void)
-{
-	/* Unprotect CRTC[0-7] */
-	vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80);
-}
-
-static void neoLock(struct vgastate *state)
-{
-	vga_wgfx(state->vgabase, 0x09, 0x00);
-	vgaHWLock(state);
-}
-
-static void neoUnlock(void)
-{
-	vgaHWUnlock();
-	vga_wgfx(NULL, 0x09, 0x26);
-}
-
-/*
- * VGA Palette management
- */
-static int paletteEnabled = 0;
-
-static inline void VGAenablePalette(void)
-{
-	vga_r(NULL, VGA_IS1_RC);
-	vga_w(NULL, VGA_ATT_W, 0x00);
-	paletteEnabled = 1;
-}
-
-static inline void VGAdisablePalette(void)
-{
-	vga_r(NULL, VGA_IS1_RC);
-	vga_w(NULL, VGA_ATT_W, 0x20);
-	paletteEnabled = 0;
-}
-
-static inline void VGAwATTR(u8 index, u8 value)
-{
-	if (paletteEnabled)
-		index &= ~0x20;
-	else
-		index |= 0x20;
-
-	vga_r(NULL, VGA_IS1_RC);
-	vga_wattr(NULL, index, value);
-}
-
-static void vgaHWProtect(int on)
-{
-	unsigned char tmp;
-
-	tmp = vga_rseq(NULL, 0x01);
-	if (on) {
-		/*
-		 * Turn off screen and disable sequencer.
-		 */
-		vga_wseq(NULL, 0x00, 0x01);		/* Synchronous Reset */
-		vga_wseq(NULL, 0x01, tmp | 0x20);	/* disable the display */
-
-		VGAenablePalette();
-	} else {
-		/*
-		 * Reenable sequencer, then turn on screen.
-		 */
-		vga_wseq(NULL, 0x01, tmp & ~0x20);	/* reenable display */
-		vga_wseq(NULL, 0x00, 0x03);		/* clear synchronousreset */
-
-		VGAdisablePalette();
-	}
-}
-
-static void vgaHWRestore(const struct fb_info *info,
-			 const struct neofb_par *par)
-{
-	int i;
-
-	vga_w(NULL, VGA_MIS_W, par->MiscOutReg);
-
-	for (i = 1; i < 5; i++)
-		vga_wseq(NULL, i, par->Sequencer[i]);
-
-	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
-	vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80);
-
-	for (i = 0; i < 25; i++)
-		vga_wcrt(NULL, i, par->CRTC[i]);
-
-	for (i = 0; i < 9; i++)
-		vga_wgfx(NULL, i, par->Graphics[i]);
-
-	VGAenablePalette();
-
-	for (i = 0; i < 21; i++)
-		VGAwATTR(i, par->Attribute[i]);
-
-	VGAdisablePalette();
-}
-
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/*
- * Hardware Acceleration for Neo2200+
- */
-static inline int neo2200_sync(struct fb_info *info)
-{
-	struct neofb_par *par = info->par;
-
-	while (readl(&par->neo2200->bltStat) & 1)
-		cpu_relax();
-	return 0;
-}
-
-static inline void neo2200_wait_fifo(struct fb_info *info,
-				     int requested_fifo_space)
-{
-	//  ndev->neo.waitfifo_calls++;
-	//  ndev->neo.waitfifo_sum += requested_fifo_space;
-
-	/* FIXME: does not work
-	   if (neo_fifo_space < requested_fifo_space)
-	   {
-	   neo_fifo_waitcycles++;
-
-	   while (1)
-	   {
-	   neo_fifo_space = (neo2200->bltStat >> 8);
-	   if (neo_fifo_space >= requested_fifo_space)
-	   break;
-	   }
-	   }
-	   else
-	   {
-	   neo_fifo_cache_hits++;
-	   }
-
-	   neo_fifo_space -= requested_fifo_space;
-	 */
-
-	neo2200_sync(info);
-}
-
-static inline void neo2200_accel_init(struct fb_info *info,
-				      struct fb_var_screeninfo *var)
-{
-	struct neofb_par *par = info->par;
-	Neo2200 __iomem *neo2200 = par->neo2200;
-	u32 bltMod, pitch;
-
-	neo2200_sync(info);
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		bltMod = NEO_MODE1_DEPTH8;
-		pitch = var->xres_virtual;
-		break;
-	case 15:
-	case 16:
-		bltMod = NEO_MODE1_DEPTH16;
-		pitch = var->xres_virtual * 2;
-		break;
-	case 24:
-		bltMod = NEO_MODE1_DEPTH24;
-		pitch = var->xres_virtual * 3;
-		break;
-	default:
-		printk(KERN_ERR
-		       "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
-		return;
-	}
-
-	writel(bltMod << 16, &neo2200->bltStat);
-	writel((pitch << 16) | pitch, &neo2200->pitch);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int
-neofb_open(struct fb_info *info, int user)
-{
-	struct neofb_par *par = info->par;
-
-	if (!par->ref_count) {
-		memset(&par->state, 0, sizeof(struct vgastate));
-		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
-		save_vga(&par->state);
-	}
-	par->ref_count++;
-
-	return 0;
-}
-
-static int
-neofb_release(struct fb_info *info, int user)
-{
-	struct neofb_par *par = info->par;
-
-	if (!par->ref_count)
-		return -EINVAL;
-
-	if (par->ref_count == 1) {
-		restore_vga(&par->state);
-	}
-	par->ref_count--;
-
-	return 0;
-}
-
-static int
-neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct neofb_par *par = info->par;
-	int memlen, vramlen;
-	int mode_ok = 0;
-
-	DBG("neofb_check_var");
-
-	if (PICOS2KHZ(var->pixclock) > par->maxClock)
-		return -EINVAL;
-
-	/* Is the mode larger than the LCD panel? */
-	if (par->internal_display &&
-            ((var->xres > par->NeoPanelWidth) ||
-	     (var->yres > par->NeoPanelHeight))) {
-		printk(KERN_INFO
-		       "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
-		       var->xres, var->yres, par->NeoPanelWidth,
-		       par->NeoPanelHeight);
-		return -EINVAL;
-	}
-
-	/* Is the mode one of the acceptable sizes? */
-	if (!par->internal_display)
-		mode_ok = 1;
-	else {
-		switch (var->xres) {
-		case 1280:
-			if (var->yres == 1024)
-				mode_ok = 1;
-			break;
-		case 1024:
-			if (var->yres == 768)
-				mode_ok = 1;
-			break;
-		case 800:
-			if (var->yres == (par->libretto ? 480 : 600))
-				mode_ok = 1;
-			break;
-		case 640:
-			if (var->yres == 480)
-				mode_ok = 1;
-			break;
-		}
-	}
-
-	if (!mode_ok) {
-		printk(KERN_INFO
-		       "Mode (%dx%d) won't display properly on LCD\n",
-		       var->xres, var->yres);
-		return -EINVAL;
-	}
-
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	switch (var->bits_per_pixel) {
-	case 8:		/* PSEUDOCOLOUR, 256 */
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-
-	case 16:		/* DIRECTCOLOUR, 64k */
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		break;
-
-	case 24:		/* TRUECOLOUR, 16m */
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-
-#ifdef NO_32BIT_SUPPORT_YET
-	case 32:		/* TRUECOLOUR, 16m */
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-#endif
-	default:
-		printk(KERN_WARNING "neofb: no support for %dbpp\n",
-		       var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	vramlen = info->fix.smem_len;
-	if (vramlen > 4 * 1024 * 1024)
-		vramlen = 4 * 1024 * 1024;
-
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3;
-
-	if (memlen > vramlen) {
-		var->yres_virtual =  vramlen * 8 / (var->xres_virtual *
-				   	var->bits_per_pixel);
-		memlen = var->xres_virtual * var->bits_per_pixel *
-				var->yres_virtual / 8;
-	}
-
-	/* we must round yres/xres down, we already rounded y/xres_virtual up
-	   if it was possible. We should return -EINVAL, but I disagree */
-	if (var->yres_virtual < var->yres)
-		var->yres = var->yres_virtual;
-	if (var->xoffset + var->xres > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yoffset + var->yres > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	var->nonstd = 0;
-	var->height = -1;
-	var->width = -1;
-
-	if (var->bits_per_pixel >= 24 || !par->neo2200)
-		var->accel_flags &= ~FB_ACCELF_TEXT;
-	return 0;
-}
-
-static int neofb_set_par(struct fb_info *info)
-{
-	struct neofb_par *par = info->par;
-	unsigned char temp;
-	int i, clock_hi = 0;
-	int lcd_stretch;
-	int hoffset, voffset;
-	int vsync_start, vtotal;
-
-	DBG("neofb_set_par");
-
-	neoUnlock();
-
-	vgaHWProtect(1);	/* Blank the screen */
-
-	vsync_start = info->var.yres + info->var.lower_margin;
-	vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
-
-	/*
-	 * This will allocate the datastructure and initialize all of the
-	 * generic VGA registers.
-	 */
-
-	if (vgaHWInit(&info->var, par))
-		return -EINVAL;
-
-	/*
-	 * The default value assigned by vgaHW.c is 0x41, but this does
-	 * not work for NeoMagic.
-	 */
-	par->Attribute[16] = 0x01;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		par->CRTC[0x13] = info->var.xres_virtual >> 3;
-		par->ExtCRTOffset = info->var.xres_virtual >> 11;
-		par->ExtColorModeSelect = 0x11;
-		break;
-	case 16:
-		par->CRTC[0x13] = info->var.xres_virtual >> 2;
-		par->ExtCRTOffset = info->var.xres_virtual >> 10;
-		par->ExtColorModeSelect = 0x13;
-		break;
-	case 24:
-		par->CRTC[0x13] = (info->var.xres_virtual * 3) >> 3;
-		par->ExtCRTOffset = (info->var.xres_virtual * 3) >> 11;
-		par->ExtColorModeSelect = 0x14;
-		break;
-#ifdef NO_32BIT_SUPPORT_YET
-	case 32:		/* FIXME: guessed values */
-		par->CRTC[0x13] = info->var.xres_virtual >> 1;
-		par->ExtCRTOffset = info->var.xres_virtual >> 9;
-		par->ExtColorModeSelect = 0x15;
-		break;
-#endif
-	default:
-		break;
-	}
-
-	par->ExtCRTDispAddr = 0x10;
-
-	/* Vertical Extension */
-	par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
-	    | (((info->var.yres - 1) & 0x400) >> 9)
-	    | (((vsync_start) & 0x400) >> 8)
-	    | (((vsync_start) & 0x400) >> 7);
-
-	/* Fast write bursts on unless disabled. */
-	if (par->pci_burst)
-		par->SysIfaceCntl1 = 0x30;
-	else
-		par->SysIfaceCntl1 = 0x00;
-
-	par->SysIfaceCntl2 = 0xc0;	/* VESA Bios sets this to 0x80! */
-
-	/* Initialize: by default, we want display config register to be read */
-	par->PanelDispCntlRegRead = 1;
-
-	/* Enable any user specified display devices. */
-	par->PanelDispCntlReg1 = 0x00;
-	if (par->internal_display)
-		par->PanelDispCntlReg1 |= 0x02;
-	if (par->external_display)
-		par->PanelDispCntlReg1 |= 0x01;
-
-	/* If the user did not specify any display devices, then... */
-	if (par->PanelDispCntlReg1 == 0x00) {
-		/* Default to internal (i.e., LCD) only. */
-		par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
-	}
-
-	/* If we are using a fixed mode, then tell the chip we are. */
-	switch (info->var.xres) {
-	case 1280:
-		par->PanelDispCntlReg1 |= 0x60;
-		break;
-	case 1024:
-		par->PanelDispCntlReg1 |= 0x40;
-		break;
-	case 800:
-		par->PanelDispCntlReg1 |= 0x20;
-		break;
-	case 640:
-	default:
-		break;
-	}
-
-	/* Setup shadow register locking. */
-	switch (par->PanelDispCntlReg1 & 0x03) {
-	case 0x01:		/* External CRT only mode: */
-		par->GeneralLockReg = 0x00;
-		/* We need to program the VCLK for external display only mode. */
-		par->ProgramVCLK = 1;
-		break;
-	case 0x02:		/* Internal LCD only mode: */
-	case 0x03:		/* Simultaneous internal/external (LCD/CRT) mode: */
-		par->GeneralLockReg = 0x01;
-		/* Don't program the VCLK when using the LCD. */
-		par->ProgramVCLK = 0;
-		break;
-	}
-
-	/*
-	 * If the screen is to be stretched, turn on stretching for the
-	 * various modes.
-	 *
-	 * OPTION_LCD_STRETCH means stretching should be turned off!
-	 */
-	par->PanelDispCntlReg2 = 0x00;
-	par->PanelDispCntlReg3 = 0x00;
-
-	if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) &&	/* LCD only */
-	    (info->var.xres != par->NeoPanelWidth)) {
-		switch (info->var.xres) {
-		case 320:	/* Needs testing.  KEM -- 24 May 98 */
-		case 400:	/* Needs testing.  KEM -- 24 May 98 */
-		case 640:
-		case 800:
-		case 1024:
-			lcd_stretch = 1;
-			par->PanelDispCntlReg2 |= 0xC6;
-			break;
-		default:
-			lcd_stretch = 0;
-			/* No stretching in these modes. */
-		}
-	} else
-		lcd_stretch = 0;
-
-	/*
-	 * If the screen is to be centerd, turn on the centering for the
-	 * various modes.
-	 */
-	par->PanelVertCenterReg1 = 0x00;
-	par->PanelVertCenterReg2 = 0x00;
-	par->PanelVertCenterReg3 = 0x00;
-	par->PanelVertCenterReg4 = 0x00;
-	par->PanelVertCenterReg5 = 0x00;
-	par->PanelHorizCenterReg1 = 0x00;
-	par->PanelHorizCenterReg2 = 0x00;
-	par->PanelHorizCenterReg3 = 0x00;
-	par->PanelHorizCenterReg4 = 0x00;
-	par->PanelHorizCenterReg5 = 0x00;
-
-
-	if (par->PanelDispCntlReg1 & 0x02) {
-		if (info->var.xres == par->NeoPanelWidth) {
-			/*
-			 * No centering required when the requested display width
-			 * equals the panel width.
-			 */
-		} else {
-			par->PanelDispCntlReg2 |= 0x01;
-			par->PanelDispCntlReg3 |= 0x10;
-
-			/* Calculate the horizontal and vertical offsets. */
-			if (!lcd_stretch) {
-				hoffset =
-				    ((par->NeoPanelWidth -
-				      info->var.xres) >> 4) - 1;
-				voffset =
-				    ((par->NeoPanelHeight -
-				      info->var.yres) >> 1) - 2;
-			} else {
-				/* Stretched modes cannot be centered. */
-				hoffset = 0;
-				voffset = 0;
-			}
-
-			switch (info->var.xres) {
-			case 320:	/* Needs testing.  KEM -- 24 May 98 */
-				par->PanelHorizCenterReg3 = hoffset;
-				par->PanelVertCenterReg2 = voffset;
-				break;
-			case 400:	/* Needs testing.  KEM -- 24 May 98 */
-				par->PanelHorizCenterReg4 = hoffset;
-				par->PanelVertCenterReg1 = voffset;
-				break;
-			case 640:
-				par->PanelHorizCenterReg1 = hoffset;
-				par->PanelVertCenterReg3 = voffset;
-				break;
-			case 800:
-				par->PanelHorizCenterReg2 = hoffset;
-				par->PanelVertCenterReg4 = voffset;
-				break;
-			case 1024:
-				par->PanelHorizCenterReg5 = hoffset;
-				par->PanelVertCenterReg5 = voffset;
-				break;
-			case 1280:
-			default:
-				/* No centering in these modes. */
-				break;
-			}
-		}
-	}
-
-	par->biosMode =
-	    neoFindMode(info->var.xres, info->var.yres,
-			info->var.bits_per_pixel);
-
-	/*
-	 * Calculate the VCLK that most closely matches the requested dot
-	 * clock.
-	 */
-	neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
-
-	/* Since we program the clocks ourselves, always use VCLK3. */
-	par->MiscOutReg |= 0x0C;
-
-	/* alread unlocked above */
-	/* BOGUS  vga_wgfx(NULL, 0x09, 0x26); */
-
-	/* don't know what this is, but it's 0 from bootup anyway */
-	vga_wgfx(NULL, 0x15, 0x00);
-
-	/* was set to 0x01 by my bios in text and vesa modes */
-	vga_wgfx(NULL, 0x0A, par->GeneralLockReg);
-
-	/*
-	 * The color mode needs to be set before calling vgaHWRestore
-	 * to ensure the DAC is initialized properly.
-	 *
-	 * NOTE: Make sure we don't change bits make sure we don't change
-	 * any reserved bits.
-	 */
-	temp = vga_rgfx(NULL, 0x90);
-	switch (info->fix.accel) {
-	case FB_ACCEL_NEOMAGIC_NM2070:
-		temp &= 0xF0;	/* Save bits 7:4 */
-		temp |= (par->ExtColorModeSelect & ~0xF0);
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2090:
-	case FB_ACCEL_NEOMAGIC_NM2093:
-	case FB_ACCEL_NEOMAGIC_NM2097:
-	case FB_ACCEL_NEOMAGIC_NM2160:
-	case FB_ACCEL_NEOMAGIC_NM2200:
-	case FB_ACCEL_NEOMAGIC_NM2230:
-	case FB_ACCEL_NEOMAGIC_NM2360:
-	case FB_ACCEL_NEOMAGIC_NM2380:
-		temp &= 0x70;	/* Save bits 6:4 */
-		temp |= (par->ExtColorModeSelect & ~0x70);
-		break;
-	}
-
-	vga_wgfx(NULL, 0x90, temp);
-
-	/*
-	 * In some rare cases a lockup might occur if we don't delay
-	 * here. (Reported by Miles Lane)
-	 */
-	//mdelay(200);
-
-	/*
-	 * Disable horizontal and vertical graphics and text expansions so
-	 * that vgaHWRestore works properly.
-	 */
-	temp = vga_rgfx(NULL, 0x25);
-	temp &= 0x39;
-	vga_wgfx(NULL, 0x25, temp);
-
-	/*
-	 * Sleep for 200ms to make sure that the two operations above have
-	 * had time to take effect.
-	 */
-	mdelay(200);
-
-	/*
-	 * This function handles restoring the generic VGA registers.  */
-	vgaHWRestore(info, par);
-
-	/* linear colormap for non palettized modes */
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		/* PseudoColor, 256 */
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 16:
-		/* TrueColor, 64k */
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-		for (i = 0; i < 64; i++) {
-			outb(i, 0x3c8);
-
-			outb(i << 1, 0x3c9);
-			outb(i, 0x3c9);
-			outb(i << 1, 0x3c9);
-		}
-		break;
-	case 24:
-#ifdef NO_32BIT_SUPPORT_YET
-	case 32:
-#endif
-		/* TrueColor, 16m */
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-		for (i = 0; i < 256; i++) {
-			outb(i, 0x3c8);
-
-			outb(i, 0x3c9);
-			outb(i, 0x3c9);
-			outb(i, 0x3c9);
-		}
-		break;
-	}
-
-	vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
-	vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
-	temp = vga_rgfx(NULL, 0x10);
-	temp &= 0x0F;		/* Save bits 3:0 */
-	temp |= (par->SysIfaceCntl1 & ~0x0F);	/* VESA Bios sets bit 1! */
-	vga_wgfx(NULL, 0x10, temp);
-
-	vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);
-	vga_wgfx(NULL, 0x15, 0 /*par->SingleAddrPage */ );
-	vga_wgfx(NULL, 0x16, 0 /*par->DualAddrPage */ );
-
-	temp = vga_rgfx(NULL, 0x20);
-	switch (info->fix.accel) {
-	case FB_ACCEL_NEOMAGIC_NM2070:
-		temp &= 0xFC;	/* Save bits 7:2 */
-		temp |= (par->PanelDispCntlReg1 & ~0xFC);
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2090:
-	case FB_ACCEL_NEOMAGIC_NM2093:
-	case FB_ACCEL_NEOMAGIC_NM2097:
-	case FB_ACCEL_NEOMAGIC_NM2160:
-		temp &= 0xDC;	/* Save bits 7:6,4:2 */
-		temp |= (par->PanelDispCntlReg1 & ~0xDC);
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2200:
-	case FB_ACCEL_NEOMAGIC_NM2230:
-	case FB_ACCEL_NEOMAGIC_NM2360:
-	case FB_ACCEL_NEOMAGIC_NM2380:
-		temp &= 0x98;	/* Save bits 7,4:3 */
-		temp |= (par->PanelDispCntlReg1 & ~0x98);
-		break;
-	}
-	vga_wgfx(NULL, 0x20, temp);
-
-	temp = vga_rgfx(NULL, 0x25);
-	temp &= 0x38;		/* Save bits 5:3 */
-	temp |= (par->PanelDispCntlReg2 & ~0x38);
-	vga_wgfx(NULL, 0x25, temp);
-
-	if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
-		temp = vga_rgfx(NULL, 0x30);
-		temp &= 0xEF;	/* Save bits 7:5 and bits 3:0 */
-		temp |= (par->PanelDispCntlReg3 & ~0xEF);
-		vga_wgfx(NULL, 0x30, temp);
-	}
-
-	vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);
-	vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);
-	vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);
-
-	if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
-		vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);
-		vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);
-		vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);
-		vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);
-	}
-
-	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)
-		vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
-
-	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
-		vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
-		vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);
-		vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);
-
-		clock_hi = 1;
-	}
-
-	/* Program VCLK3 if needed. */
-	if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)
-				 || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)
-				 || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)
-						  != (par->VCLK3NumeratorHigh &
-						      ~0x0F))))) {
-		vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);
-		if (clock_hi) {
-			temp = vga_rgfx(NULL, 0x8F);
-			temp &= 0x0F;	/* Save bits 3:0 */
-			temp |= (par->VCLK3NumeratorHigh & ~0x0F);
-			vga_wgfx(NULL, 0x8F, temp);
-		}
-		vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);
-	}
-
-	if (par->biosMode)
-		vga_wcrt(NULL, 0x23, par->biosMode);
-
-	vga_wgfx(NULL, 0x93, 0xc0);	/* Gives 5x faster framebuffer writes !!! */
-
-	/* Program vertical extension register */
-	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
-	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
-		vga_wcrt(NULL, 0x70, par->VerticalExt);
-	}
-
-	vgaHWProtect(0);	/* Turn on screen */
-
-	/* Calling this also locks offset registers required in update_start */
-	neoLock(&par->state);
-
-	info->fix.line_length =
-	    info->var.xres_virtual * (info->var.bits_per_pixel >> 3);
-
-	switch (info->fix.accel) {
-		case FB_ACCEL_NEOMAGIC_NM2200:
-		case FB_ACCEL_NEOMAGIC_NM2230: 
-		case FB_ACCEL_NEOMAGIC_NM2360: 
-		case FB_ACCEL_NEOMAGIC_NM2380: 
-			neo2200_accel_init(info, &info->var);
-			break;
-		default:
-			break;
-	}	
-	return 0;
-}
-
-/*
- *    Pan or Wrap the Display
- */
-static int neofb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct neofb_par *par = info->par;
-	struct vgastate *state = &par->state;
-	int oldExtCRTDispAddr;
-	int Base;
-
-	DBG("neofb_update_start");
-
-	Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
-	Base *= (info->var.bits_per_pixel + 7) / 8;
-
-	neoUnlock();
-
-	/*
-	 * These are the generic starting address registers.
-	 */
-	vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);
-	vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));
-
-	/*
-	 * Make sure we don't clobber some other bits that might already
-	 * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
-	 * be needed.
-	 */
-	oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);
-	vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
-
-	neoLock(state);
-
-	return 0;
-}
-
-static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *fb)
-{
-	if (regno >= fb->cmap.len || regno > 255)
-		return -EINVAL;
-
-	if (fb->var.bits_per_pixel <= 8) {
-		outb(regno, 0x3c8);
-
-		outb(red >> 10, 0x3c9);
-		outb(green >> 10, 0x3c9);
-		outb(blue >> 10, 0x3c9);
-	} else if (regno < 16) {
-		switch (fb->var.bits_per_pixel) {
-		case 16:
-			((u32 *) fb->pseudo_palette)[regno] =
-				((red & 0xf800)) | ((green & 0xfc00) >> 5) |
-				((blue & 0xf800) >> 11);
-			break;
-		case 24:
-			((u32 *) fb->pseudo_palette)[regno] =
-				((red & 0xff00) << 8) | ((green & 0xff00)) |
-				((blue & 0xff00) >> 8);
-			break;
-#ifdef NO_32BIT_SUPPORT_YET
-		case 32:
-			((u32 *) fb->pseudo_palette)[regno] =
-				((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
-				((green & 0xff00)) | ((blue & 0xff00) >> 8);
-			break;
-#endif
-		default:
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/*
- *    (Un)Blank the display.
- */
-static int neofb_blank(int blank_mode, struct fb_info *info)
-{
-	/*
-	 *  Blank the screen if blank_mode != 0, else unblank.
-	 *  Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
-	 *  e.g. a video mode which doesn't support it. Implements VESA suspend
-	 *  and powerdown modes for monitors, and backlight control on LCDs.
-	 *    blank_mode == 0: unblanked (backlight on)
-	 *    blank_mode == 1: blank (backlight on)
-	 *    blank_mode == 2: suspend vsync (backlight off)
-	 *    blank_mode == 3: suspend hsync (backlight off)
-	 *    blank_mode == 4: powerdown (backlight off)
-	 *
-	 *  wms...Enable VESA DPMS compatible powerdown mode
-	 *  run "setterm -powersave powerdown" to take advantage
-	 */
-	struct neofb_par *par = info->par;
-	int seqflags, lcdflags, dpmsflags, reg, tmpdisp;
-
-	/*
-	 * Read back the register bits related to display configuration. They might
-	 * have been changed underneath the driver via Fn key stroke.
-	 */
-	neoUnlock();
-	tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;
-	neoLock(&par->state);
-
-	/* In case we blank the screen, we want to store the possibly new
-	 * configuration in the driver. During un-blank, we re-apply this setting,
-	 * since the LCD bit will be cleared in order to switch off the backlight.
-	 */
-	if (par->PanelDispCntlRegRead) {
-		par->PanelDispCntlReg1 = tmpdisp;
-	}
-	par->PanelDispCntlRegRead = !blank_mode;
-
-	switch (blank_mode) {
-	case FB_BLANK_POWERDOWN:	/* powerdown - both sync lines down */
-		seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
-		lcdflags = 0;			/* LCD off */
-		dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
-			    NEO_GR01_SUPPRESS_VSYNC;
-#ifdef CONFIG_TOSHIBA
-		/* Do we still need this ? */
-		/* attempt to turn off backlight on toshiba; also turns off external */
-		{
-			SMMRegisters regs;
-
-			regs.eax = 0xff00; /* HCI_SET */
-			regs.ebx = 0x0002; /* HCI_BACKLIGHT */
-			regs.ecx = 0x0000; /* HCI_DISABLE */
-			tosh_smm(&regs);
-		}
-#endif
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:		/* hsync off */
-		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
-		lcdflags = 0;			/* LCD off */
-		dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:		/* vsync off */
-		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
-		lcdflags = 0;			/* LCD off */
-		dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
-		break;
-	case FB_BLANK_NORMAL:		/* just blank screen (backlight stays on) */
-		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
-		/*
-		 * During a blank operation with the LID shut, we might store "LCD off"
-		 * by mistake. Due to timing issues, the BIOS may switch the lights
-		 * back on, and we turn it back off once we "unblank".
-		 *
-		 * So here is an attempt to implement ">=" - if we are in the process
-		 * of unblanking, and the LCD bit is unset in the driver but set in the
-		 * register, we must keep it.
-		 */
-		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
-		dpmsflags = 0x00;	/* no hsync/vsync suppression */
-		break;
-	case FB_BLANK_UNBLANK:		/* unblank */
-		seqflags = 0;			/* Enable sequencer */
-		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
-		dpmsflags = 0x00;	/* no hsync/vsync suppression */
-#ifdef CONFIG_TOSHIBA
-		/* Do we still need this ? */
-		/* attempt to re-enable backlight/external on toshiba */
-		{
-			SMMRegisters regs;
-
-			regs.eax = 0xff00; /* HCI_SET */
-			regs.ebx = 0x0002; /* HCI_BACKLIGHT */
-			regs.ecx = 0x0001; /* HCI_ENABLE */
-			tosh_smm(&regs);
-		}
-#endif
-		break;
-	default:	/* Anything else we don't understand; return 1 to tell
-			 * fb_blank we didn't aactually do anything */
-		return 1;
-	}
-
-	neoUnlock();
-	reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
-	vga_wseq(NULL, 0x01, reg);
-	reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
-	vga_wgfx(NULL, 0x20, reg);
-	reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
-	vga_wgfx(NULL, 0x01, reg);
-	neoLock(&par->state);
-	return 0;
-}
-
-static void
-neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct neofb_par *par = info->par;
-	u_long dst, rop;
-
-	dst = rect->dx + rect->dy * info->var.xres_virtual;
-	rop = rect->rop ? 0x060000 : 0x0c0000;
-
-	neo2200_wait_fifo(info, 4);
-
-	/* set blt control */
-	writel(NEO_BC3_FIFO_EN |
-	       NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |
-	       //               NEO_BC3_DST_XY_ADDR  |
-	       //               NEO_BC3_SRC_XY_ADDR  |
-	       rop, &par->neo2200->bltCntl);
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		writel(rect->color, &par->neo2200->fgColor);
-		break;
-	case 16:
-	case 24:
-		writel(((u32 *) (info->pseudo_palette))[rect->color],
-		       &par->neo2200->fgColor);
-		break;
-	}
-
-	writel(dst * ((info->var.bits_per_pixel + 7) >> 3),
-	       &par->neo2200->dstStart);
-	writel((rect->height << 16) | (rect->width & 0xffff),
-	       &par->neo2200->xyExt);
-}
-
-static void
-neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
-	struct neofb_par *par = info->par;
-	u_long src, dst, bltCntl;
-
-	bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
-
-	if ((dy > sy) || ((dy == sy) && (dx > sx))) {
-		/* Start with the lower right corner */
-		sy += (area->height - 1);
-		dy += (area->height - 1);
-		sx += (area->width - 1);
-		dx += (area->width - 1);
-
-		bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
-	}
-
-	src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;
-	dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length;
-
-	neo2200_wait_fifo(info, 4);
-
-	/* set blt control */
-	writel(bltCntl, &par->neo2200->bltCntl);
-
-	writel(src, &par->neo2200->srcStart);
-	writel(dst, &par->neo2200->dstStart);
-	writel((area->height << 16) | (area->width & 0xffff),
-	       &par->neo2200->xyExt);
-}
-
-static void
-neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct neofb_par *par = info->par;
-	int s_pitch = (image->width * image->depth + 7) >> 3;
-	int scan_align = info->pixmap.scan_align - 1;
-	int buf_align = info->pixmap.buf_align - 1;
-	int bltCntl_flags, d_pitch, data_len;
-
-	// The data is padded for the hardware
-	d_pitch = (s_pitch + scan_align) & ~scan_align;
-	data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
-
-	neo2200_sync(info);
-
-	if (image->depth == 1) {
-		if (info->var.bits_per_pixel == 24 && image->width < 16) {
-			/* FIXME. There is a bug with accelerated color-expanded
-			 * transfers in 24 bit mode if the image being transferred
-			 * is less than 16 bits wide. This is due to insufficient
-			 * padding when writing the image. We need to adjust
-			 * struct fb_pixmap. Not yet done. */
-			cfb_imageblit(info, image);
-			return;
-		}
-		bltCntl_flags = NEO_BC0_SRC_MONO;
-	} else if (image->depth == info->var.bits_per_pixel) {
-		bltCntl_flags = 0;
-	} else {
-		/* We don't currently support hardware acceleration if image
-		 * depth is different from display */
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		writel(image->fg_color, &par->neo2200->fgColor);
-		writel(image->bg_color, &par->neo2200->bgColor);
-		break;
-	case 16:
-	case 24:
-		writel(((u32 *) (info->pseudo_palette))[image->fg_color],
-		       &par->neo2200->fgColor);
-		writel(((u32 *) (info->pseudo_palette))[image->bg_color],
-		       &par->neo2200->bgColor);
-		break;
-	}
-
-	writel(NEO_BC0_SYS_TO_VID |
-		NEO_BC3_SKIP_MAPPING | bltCntl_flags |
-		// NEO_BC3_DST_XY_ADDR |
-		0x0c0000, &par->neo2200->bltCntl);
-
-	writel(0, &par->neo2200->srcStart);
-//      par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
-	writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +
-		image->dy * info->fix.line_length), &par->neo2200->dstStart);
-	writel((image->height << 16) | (image->width & 0xffff),
-	       &par->neo2200->xyExt);
-
-	memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);
-}
-
-static void
-neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	switch (info->fix.accel) {
-		case FB_ACCEL_NEOMAGIC_NM2200:
-		case FB_ACCEL_NEOMAGIC_NM2230: 
-		case FB_ACCEL_NEOMAGIC_NM2360: 
-		case FB_ACCEL_NEOMAGIC_NM2380:
-			neo2200_fillrect(info, rect);
-			break;
-		default:
-			cfb_fillrect(info, rect);
-			break;
-	}	
-}
-
-static void
-neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	switch (info->fix.accel) {
-		case FB_ACCEL_NEOMAGIC_NM2200:
-		case FB_ACCEL_NEOMAGIC_NM2230: 
-		case FB_ACCEL_NEOMAGIC_NM2360: 
-		case FB_ACCEL_NEOMAGIC_NM2380: 
-			neo2200_copyarea(info, area);
-			break;
-		default:
-			cfb_copyarea(info, area);
-			break;
-	}	
-}
-
-static void
-neofb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	switch (info->fix.accel) {
-		case FB_ACCEL_NEOMAGIC_NM2200:
-		case FB_ACCEL_NEOMAGIC_NM2230:
-		case FB_ACCEL_NEOMAGIC_NM2360:
-		case FB_ACCEL_NEOMAGIC_NM2380:
-			neo2200_imageblit(info, image);
-			break;
-		default:
-			cfb_imageblit(info, image);
-			break;
-	}
-}
-
-static int 
-neofb_sync(struct fb_info *info)
-{
-	switch (info->fix.accel) {
-		case FB_ACCEL_NEOMAGIC_NM2200:
-		case FB_ACCEL_NEOMAGIC_NM2230: 
-		case FB_ACCEL_NEOMAGIC_NM2360: 
-		case FB_ACCEL_NEOMAGIC_NM2380: 
-			neo2200_sync(info);
-			break;
-		default:
-			break;
-	}
-	return 0;		
-}
-
-/*
-static void
-neofb_draw_cursor(struct fb_info *info, u8 *dst, u8 *src, unsigned int width)
-{
-	//memset_io(info->sprite.addr, 0xff, 1);
-}
-
-static int
-neofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct neofb_par *par = (struct neofb_par *) info->par;
-
-	* Disable cursor *
-	write_le32(NEOREG_CURSCNTL, ~NEO_CURS_ENABLE, par);
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		u32 x = cursor->image.dx;
-		u32 y = cursor->image.dy;
-
-		info->cursor.image.dx = x;
-		info->cursor.image.dy = y;
-		write_le32(NEOREG_CURSX, x, par);
-		write_le32(NEOREG_CURSY, y, par);
-	}
-
-	if (cursor->set & FB_CUR_SETSIZE) {
-		info->cursor.image.height = cursor->image.height;
-		info->cursor.image.width = cursor->image.width;
-	}
-
-	if (cursor->set & FB_CUR_SETHOT)
-		info->cursor.hot = cursor->hot;
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		if (cursor->image.depth == 1) {
-			u32 fg = cursor->image.fg_color;
-			u32 bg = cursor->image.bg_color;
-
-			info->cursor.image.fg_color = fg;
-			info->cursor.image.bg_color = bg;
-
-			fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
-			bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
-			write_le32(NEOREG_CURSFGCOLOR, fg, par);
-			write_le32(NEOREG_CURSBGCOLOR, bg, par);
-		}
-	}
-
-	if (cursor->set & FB_CUR_SETSHAPE)
-		fb_load_cursor_image(info);
-
-	if (info->cursor.enable)
-		write_le32(NEOREG_CURSCNTL, NEO_CURS_ENABLE, par);
-	return 0;
-}
-*/
-
-static struct fb_ops neofb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= neofb_open,
-	.fb_release	= neofb_release,
-	.fb_check_var	= neofb_check_var,
-	.fb_set_par	= neofb_set_par,
-	.fb_setcolreg	= neofb_setcolreg,
-	.fb_pan_display	= neofb_pan_display,
-	.fb_blank	= neofb_blank,
-	.fb_sync	= neofb_sync,
-	.fb_fillrect	= neofb_fillrect,
-	.fb_copyarea	= neofb_copyarea,
-	.fb_imageblit	= neofb_imageblit,
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_videomode mode800x480 = {
-	.xres           = 800,
-	.yres           = 480,
-	.pixclock       = 25000,
-	.left_margin    = 88,
-	.right_margin   = 40,
-	.upper_margin   = 23,
-	.lower_margin   = 1,
-	.hsync_len      = 128,
-	.vsync_len      = 4,
-	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-
-static int neo_map_mmio(struct fb_info *info, struct pci_dev *dev)
-{
-	struct neofb_par *par = info->par;
-
-	DBG("neo_map_mmio");
-
-	switch (info->fix.accel) {
-		case FB_ACCEL_NEOMAGIC_NM2070:
-			info->fix.mmio_start = pci_resource_start(dev, 0)+
-				0x100000;
-			break;
-		case FB_ACCEL_NEOMAGIC_NM2090:
-		case FB_ACCEL_NEOMAGIC_NM2093:
-			info->fix.mmio_start = pci_resource_start(dev, 0)+
-				0x200000;
-			break;
-		case FB_ACCEL_NEOMAGIC_NM2160:
-		case FB_ACCEL_NEOMAGIC_NM2097:
-		case FB_ACCEL_NEOMAGIC_NM2200:
-		case FB_ACCEL_NEOMAGIC_NM2230:
-		case FB_ACCEL_NEOMAGIC_NM2360:
-		case FB_ACCEL_NEOMAGIC_NM2380:
-			info->fix.mmio_start = pci_resource_start(dev, 1);
-			break;
-		default:
-			info->fix.mmio_start = pci_resource_start(dev, 0);
-	}
-	info->fix.mmio_len = MMIO_SIZE;
-
-	if (!request_mem_region
-	    (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) {
-		printk("neofb: memory mapped IO in use\n");
-		return -EBUSY;
-	}
-
-	par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE);
-	if (!par->mmio_vbase) {
-		printk("neofb: unable to map memory mapped IO\n");
-		release_mem_region(info->fix.mmio_start,
-				   info->fix.mmio_len);
-		return -ENOMEM;
-	} else
-		printk(KERN_INFO "neofb: mapped io at %p\n",
-		       par->mmio_vbase);
-	return 0;
-}
-
-static void neo_unmap_mmio(struct fb_info *info)
-{
-	struct neofb_par *par = info->par;
-
-	DBG("neo_unmap_mmio");
-
-	iounmap(par->mmio_vbase);
-	par->mmio_vbase = NULL;
-
-	release_mem_region(info->fix.mmio_start,
-			   info->fix.mmio_len);
-}
-
-static int neo_map_video(struct fb_info *info, struct pci_dev *dev,
-			 int video_len)
-{
-	//unsigned long addr;
-
-	DBG("neo_map_video");
-
-	info->fix.smem_start = pci_resource_start(dev, 0);
-	info->fix.smem_len = video_len;
-
-	if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
-				"frame buffer")) {
-		printk("neofb: frame buffer in use\n");
-		return -EBUSY;
-	}
-
-	info->screen_base =
-	    ioremap(info->fix.smem_start, info->fix.smem_len);
-	if (!info->screen_base) {
-		printk("neofb: unable to map screen memory\n");
-		release_mem_region(info->fix.smem_start,
-				   info->fix.smem_len);
-		return -ENOMEM;
-	} else
-		printk(KERN_INFO "neofb: mapped framebuffer at %p\n",
-		       info->screen_base);
-
-#ifdef CONFIG_MTRR
-	((struct neofb_par *)(info->par))->mtrr =
-		mtrr_add(info->fix.smem_start, pci_resource_len(dev, 0),
-				MTRR_TYPE_WRCOMB, 1);
-#endif
-
-	/* Clear framebuffer, it's all white in memory after boot */
-	memset_io(info->screen_base, 0, info->fix.smem_len);
-
-	/* Allocate Cursor drawing pad.
-	info->fix.smem_len -= PAGE_SIZE;
-	addr = info->fix.smem_start + info->fix.smem_len;
-	write_le32(NEOREG_CURSMEMPOS, ((0x000f & (addr >> 10)) << 8) |
-					((0x0ff0 & (addr >> 10)) >> 4), par);
-	addr = (unsigned long) info->screen_base + info->fix.smem_len;
-	info->sprite.addr = (u8 *) addr; */
-	return 0;
-}
-
-static void neo_unmap_video(struct fb_info *info)
-{
-	DBG("neo_unmap_video");
-
-#ifdef CONFIG_MTRR
-	{
-		struct neofb_par *par = info->par;
-
-		mtrr_del(par->mtrr, info->fix.smem_start,
-			 info->fix.smem_len);
-	}
-#endif
-	iounmap(info->screen_base);
-	info->screen_base = NULL;
-
-	release_mem_region(info->fix.smem_start,
-			   info->fix.smem_len);
-}
-
-static int neo_scan_monitor(struct fb_info *info)
-{
-	struct neofb_par *par = info->par;
-	unsigned char type, display;
-	int w;
-
-	// Eventually we will have i2c support.
-	info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
-	if (!info->monspecs.modedb)
-		return -ENOMEM;
-	info->monspecs.modedb_len = 1;
-
-	/* Determine the panel type */
-	vga_wgfx(NULL, 0x09, 0x26);
-	type = vga_rgfx(NULL, 0x21);
-	display = vga_rgfx(NULL, 0x20);
-	if (!par->internal_display && !par->external_display) {
-		par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
-		par->external_display = display & 1;
-		printk (KERN_INFO "Autodetected %s display\n",
-			par->internal_display && par->external_display ? "simultaneous" :
-			par->internal_display ? "internal" : "external");
-	}
-
-	/* Determine panel width -- used in NeoValidMode. */
-	w = vga_rgfx(NULL, 0x20);
-	vga_wgfx(NULL, 0x09, 0x00);
-	switch ((w & 0x18) >> 3) {
-	case 0x00:
-		// 640x480@60
-		par->NeoPanelWidth = 640;
-		par->NeoPanelHeight = 480;
-		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
-		break;
-	case 0x01:
-		par->NeoPanelWidth = 800;
-		if (par->libretto) {
-			par->NeoPanelHeight = 480;
-			memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
-		} else {
-			// 800x600@60
-			par->NeoPanelHeight = 600;
-			memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
-		}
-		break;
-	case 0x02:
-		// 1024x768@60
-		par->NeoPanelWidth = 1024;
-		par->NeoPanelHeight = 768;
-		memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
-		break;
-	case 0x03:
-		/* 1280x1024@60 panel support needs to be added */
-#ifdef NOT_DONE
-		par->NeoPanelWidth = 1280;
-		par->NeoPanelHeight = 1024;
-		memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
-		break;
-#else
-		printk(KERN_ERR
-		       "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
-		return -1;
-#endif
-	default:
-		// 640x480@60
-		par->NeoPanelWidth = 640;
-		par->NeoPanelHeight = 480;
-		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
-		break;
-	}
-
-	printk(KERN_INFO "Panel is a %dx%d %s %s display\n",
-	       par->NeoPanelWidth,
-	       par->NeoPanelHeight,
-	       (type & 0x02) ? "color" : "monochrome",
-	       (type & 0x10) ? "TFT" : "dual scan");
-	return 0;
-}
-
-static int neo_init_hw(struct fb_info *info)
-{
-	struct neofb_par *par = info->par;
-	int videoRam = 896;
-	int maxClock = 65000;
-	int CursorMem = 1024;
-	int CursorOff = 0x100;
-
-	DBG("neo_init_hw");
-
-	neoUnlock();
-
-#if 0
-	printk(KERN_DEBUG "--- Neo extended register dump ---\n");
-	for (int w = 0; w < 0x85; w++)
-		printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
-		       (void *) vga_rcrt(NULL, w));
-	for (int w = 0; w < 0xC7; w++)
-		printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
-		       (void *) vga_rgfx(NULL, w));
-#endif
-	switch (info->fix.accel) {
-	case FB_ACCEL_NEOMAGIC_NM2070:
-		videoRam = 896;
-		maxClock = 65000;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2090:
-	case FB_ACCEL_NEOMAGIC_NM2093:
-	case FB_ACCEL_NEOMAGIC_NM2097:
-		videoRam = 1152;
-		maxClock = 80000;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2160:
-		videoRam = 2048;
-		maxClock = 90000;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2200:
-		videoRam = 2560;
-		maxClock = 110000;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2230:
-		videoRam = 3008;
-		maxClock = 110000;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2360:
-		videoRam = 4096;
-		maxClock = 110000;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2380:
-		videoRam = 6144;
-		maxClock = 110000;
-		break;
-	}
-	switch (info->fix.accel) {
-	case FB_ACCEL_NEOMAGIC_NM2070:
-	case FB_ACCEL_NEOMAGIC_NM2090:
-	case FB_ACCEL_NEOMAGIC_NM2093:
-		CursorMem = 2048;
-		CursorOff = 0x100;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2097:
-	case FB_ACCEL_NEOMAGIC_NM2160:
-		CursorMem = 1024;
-		CursorOff = 0x100;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2200:
-	case FB_ACCEL_NEOMAGIC_NM2230:
-	case FB_ACCEL_NEOMAGIC_NM2360:
-	case FB_ACCEL_NEOMAGIC_NM2380:
-		CursorMem = 1024;
-		CursorOff = 0x1000;
-
-		par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
-		break;
-	}
-/*
-	info->sprite.size = CursorMem;
-	info->sprite.scan_align = 1;
-	info->sprite.buf_align = 1;
-	info->sprite.flags = FB_PIXMAP_IO;
-	info->sprite.outbuf = neofb_draw_cursor;
-*/
-	par->maxClock = maxClock;
-	par->cursorOff = CursorOff;
-	return videoRam * 1024;
-}
-
-
-static struct fb_info *neo_alloc_fb_info(struct pci_dev *dev,
-					 const struct pci_device_id *id)
-{
-	struct fb_info *info;
-	struct neofb_par *par;
-
-	info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
-
-	if (!info)
-		return NULL;
-
-	par = info->par;
-
-	info->fix.accel = id->driver_data;
-
-	par->pci_burst = !nopciburst;
-	par->lcd_stretch = !nostretch;
-	par->libretto = libretto;
-
-	par->internal_display = internal;
-	par->external_display = external;
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-
-	switch (info->fix.accel) {
-	case FB_ACCEL_NEOMAGIC_NM2070:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 128");
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2090:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 128V");
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2093:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 128ZV");
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2097:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 128ZV+");
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2160:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 128XD");
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2200:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 256AV");
-		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
-		               FBINFO_HWACCEL_COPYAREA |
-                	       FBINFO_HWACCEL_FILLRECT;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2230:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 256AV+");
-		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
-		               FBINFO_HWACCEL_COPYAREA |
-                	       FBINFO_HWACCEL_FILLRECT;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2360:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 256ZX");
-		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
-		               FBINFO_HWACCEL_COPYAREA |
-                	       FBINFO_HWACCEL_FILLRECT;
-		break;
-	case FB_ACCEL_NEOMAGIC_NM2380:
-		snprintf(info->fix.id, sizeof(info->fix.id),
-				"MagicGraph 256XL+");
-		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
-		               FBINFO_HWACCEL_COPYAREA |
-                	       FBINFO_HWACCEL_FILLRECT;
-		break;
-	}
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux = 0;
-	info->fix.xpanstep = 0;
-	info->fix.ypanstep = 4;
-	info->fix.ywrapstep = 0;
-	info->fix.accel = id->driver_data;
-
-	info->fbops = &neofb_ops;
-	info->pseudo_palette = par->palette;
-	return info;
-}
-
-static void neo_free_fb_info(struct fb_info *info)
-{
-	if (info) {
-		/*
-		 * Free the colourmap
-		 */
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct fb_info *info;
-	u_int h_sync, v_sync;
-	int video_len, err;
-
-	DBG("neofb_probe");
-
-	err = pci_enable_device(dev);
-	if (err)
-		return err;
-
-	err = -ENOMEM;
-	info = neo_alloc_fb_info(dev, id);
-	if (!info)
-		return err;
-
-	err = neo_map_mmio(info, dev);
-	if (err)
-		goto err_map_mmio;
-
-	err = neo_scan_monitor(info);
-	if (err)
-		goto err_scan_monitor;
-
-	video_len = neo_init_hw(info);
-	if (video_len < 0) {
-		err = video_len;
-		goto err_init_hw;
-	}
-
-	err = neo_map_video(info, dev, video_len);
-	if (err)
-		goto err_init_hw;
-
-	if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
-			info->monspecs.modedb, 16)) {
-		printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
-		err = -EINVAL;
-		goto err_map_video;
-	}
-
-	/*
-	 * Calculate the hsync and vsync frequencies.  Note that
-	 * we split the 1e12 constant up so that we can preserve
-	 * the precision and fit the results into 32-bit registers.
-	 *  (1953125000 * 512 = 1e12)
-	 */
-	h_sync = 1953125000 / info->var.pixclock;
-	h_sync =
-	    h_sync * 512 / (info->var.xres + info->var.left_margin +
-			    info->var.right_margin + info->var.hsync_len);
-	v_sync =
-	    h_sync / (info->var.yres + info->var.upper_margin +
-		      info->var.lower_margin + info->var.vsync_len);
-
-	printk(KERN_INFO "neofb v" NEOFB_VERSION
-	       ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
-	       info->fix.smem_len >> 10, info->var.xres,
-	       info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);
-
-	err = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (err < 0)
-		goto err_map_video;
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto err_reg_fb;
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	/*
-	 * Our driver data
-	 */
-	pci_set_drvdata(dev, info);
-	return 0;
-
-err_reg_fb:
-	fb_dealloc_cmap(&info->cmap);
-err_map_video:
-	neo_unmap_video(info);
-err_init_hw:
-	fb_destroy_modedb(info->monspecs.modedb);
-err_scan_monitor:
-	neo_unmap_mmio(info);
-err_map_mmio:
-	neo_free_fb_info(info);
-	return err;
-}
-
-static void neofb_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-
-	DBG("neofb_remove");
-
-	if (info) {
-		/*
-		 * If unregister_framebuffer fails, then
-		 * we will be leaving hooks that could cause
-		 * oopsen laying around.
-		 */
-		if (unregister_framebuffer(info))
-			printk(KERN_WARNING
-			       "neofb: danger danger!  Oopsen imminent!\n");
-
-		neo_unmap_video(info);
-		fb_destroy_modedb(info->monspecs.modedb);
-		neo_unmap_mmio(info);
-		neo_free_fb_info(info);
-	}
-}
-
-static struct pci_device_id neofb_devices[] = {
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
-
-	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
-
-	{0, 0, 0, 0, 0, 0, 0}
-};
-
-MODULE_DEVICE_TABLE(pci, neofb_devices);
-
-static struct pci_driver neofb_driver = {
-	.name =		"neofb",
-	.id_table =	neofb_devices,
-	.probe =	neofb_probe,
-	.remove =	neofb_remove,
-};
-
-/* ************************* init in-kernel code ************************** */
-
-#ifndef MODULE
-static int __init neofb_setup(char *options)
-{
-	char *this_opt;
-
-	DBG("neofb_setup");
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-
-		if (!strncmp(this_opt, "internal", 8))
-			internal = 1;
-		else if (!strncmp(this_opt, "external", 8))
-			external = 1;
-		else if (!strncmp(this_opt, "nostretch", 9))
-			nostretch = 1;
-		else if (!strncmp(this_opt, "nopciburst", 10))
-			nopciburst = 1;
-		else if (!strncmp(this_opt, "libretto", 8))
-			libretto = 1;
-		else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-#endif  /*  MODULE  */
-
-static int __init neofb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("neofb", &option))
-		return -ENODEV;
-	neofb_setup(option);
-#endif
-	return pci_register_driver(&neofb_driver);
-}
-
-module_init(neofb_init);
-
-#ifdef MODULE
-static void __exit neofb_exit(void)
-{
-	pci_unregister_driver(&neofb_driver);
-}
-
-module_exit(neofb_exit);
-#endif				/* MODULE */
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
deleted file mode 100644
index 478f9808dee4..000000000000
--- a/drivers/video/nuc900fb.c
+++ /dev/null
@@ -1,765 +0,0 @@
-/*
- *
- * Copyright (c) 2009 Nuvoton technology corporation
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- *  Description:
- *    Nuvoton LCD Controller Driver
- *  Author:
- *    Wang Qiang (rurality.linux@gmail.com) 2009/12/11
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/wait.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/io.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-ldm.h>
-#include <linux/platform_data/video-nuc900fb.h>
-
-#include "nuc900fb.h"
-
-
-/*
- *  Initialize the nuc900 video (dual) buffer address
- */
-static void nuc900fb_set_lcdaddr(struct fb_info *info)
-{
-	struct nuc900fb_info *fbi = info->par;
-	void __iomem *regs = fbi->io;
-	unsigned long vbaddr1, vbaddr2;
-
-	vbaddr1  = info->fix.smem_start;
-	vbaddr2  = info->fix.smem_start;
-	vbaddr2 += info->fix.line_length * info->var.yres;
-
-	/* set frambuffer start phy addr*/
-	writel(vbaddr1, regs + REG_LCM_VA_BADDR0);
-	writel(vbaddr2, regs + REG_LCM_VA_BADDR1);
-
-	writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL);
-	writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE);
-}
-
-/*
- *	calculate divider for lcd div
- */
-static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi,
-					 unsigned long pixclk)
-{
-	unsigned long clk = fbi->clk_rate;
-	unsigned long long div;
-
-	/* pixclk is in picseconds. our clock is in Hz*/
-	/* div = (clk * pixclk)/10^12 */
-	div = (unsigned long long)clk * pixclk;
-	div >>= 12;
-	do_div(div, 625 * 625UL * 625);
-
-	dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div);
-
-	return div;
-}
-
-/*
- *	Check the video params of 'var'.
- */
-static int nuc900fb_check_var(struct fb_var_screeninfo *var,
-			       struct fb_info *info)
-{
-	struct nuc900fb_info *fbi = info->par;
-	struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
-	struct nuc900fb_display *display = NULL;
-	struct nuc900fb_display *default_display = mach_info->displays +
-						   mach_info->default_display;
-	int i;
-
-	dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info);
-
-	/* validate x/y resolution */
-	/* choose default mode if possible */
-	if (var->xres == default_display->xres &&
-	    var->yres == default_display->yres &&
-	    var->bits_per_pixel == default_display->bpp)
-		display = default_display;
-	else
-		for (i = 0; i < mach_info->num_displays; i++)
-			if (var->xres == mach_info->displays[i].xres &&
-			    var->yres == mach_info->displays[i].yres &&
-			    var->bits_per_pixel == mach_info->displays[i].bpp) {
-				display = mach_info->displays + i;
-				break;
-			}
-
-	if (display == NULL) {
-		printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n",
-			var->xres, var->yres, var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	/* it should be the same size as the display */
-	var->xres_virtual	= display->xres;
-	var->yres_virtual	= display->yres;
-	var->height		= display->height;
-	var->width		= display->width;
-
-	/* copy lcd settings */
-	var->pixclock		= display->pixclock;
-	var->left_margin	= display->left_margin;
-	var->right_margin	= display->right_margin;
-	var->upper_margin	= display->upper_margin;
-	var->lower_margin	= display->lower_margin;
-	var->vsync_len		= display->vsync_len;
-	var->hsync_len		= display->hsync_len;
-
-	var->transp.offset	= 0;
-	var->transp.length	= 0;
-
-	fbi->regs.lcd_dccs = display->dccs;
-	fbi->regs.lcd_device_ctrl = display->devctl;
-	fbi->regs.lcd_va_fbctrl = display->fbctrl;
-	fbi->regs.lcd_va_scale = display->scale;
-
-	/* set R/G/B possions */
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-	default:
-		var->red.offset 	= 0;
-		var->red.length 	= var->bits_per_pixel;
-		var->green 		= var->red;
-		var->blue		= var->red;
-		break;
-	case 12:
-		var->red.length		= 4;
-		var->green.length	= 4;
-		var->blue.length	= 4;
-		var->red.offset		= 8;
-		var->green.offset	= 4;
-		var->blue.offset	= 0;
-		break;
-	case 16:
-		var->red.length		= 5;
-		var->green.length	= 6;
-		var->blue.length	= 5;
-		var->red.offset		= 11;
-		var->green.offset	= 5;
-		var->blue.offset	= 0;
-		break;
-	case 18:
-		var->red.length		= 6;
-		var->green.length	= 6;
-		var->blue.length	= 6;
-		var->red.offset		= 12;
-		var->green.offset	= 6;
-		var->blue.offset	= 0;
-		break;
-	case 32:
-		var->red.length		= 8;
-		var->green.length	= 8;
-		var->blue.length	= 8;
-		var->red.offset		= 16;
-		var->green.offset	= 8;
-		var->blue.offset	= 0;
-		break;
-	}
-
-	return 0;
-}
-
-/*
- *	Calculate lcd register values from var setting & save into hw
- */
-static void nuc900fb_calculate_lcd_regs(const struct fb_info *info,
-					struct nuc900fb_hw *regs)
-{
-	const struct fb_var_screeninfo *var = &info->var;
-	int vtt = var->height + var->upper_margin + var->lower_margin;
-	int htt = var->width + var->left_margin + var->right_margin;
-	int hsync = var->width + var->right_margin;
-	int vsync = var->height + var->lower_margin;
-
-	regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) |
-			      LCM_CRTC_SIZE_HTTVAL(htt);
-	regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) |
-			      LCM_CRTC_DEND_HDENDVAL(var->width);
-	regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) |
-			    LCM_CRTC_HR_SVAL(var->width + 1);
-	regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) |
-			       LCM_CRTC_HSYNC_SVAL(hsync);
-	regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) |
-			    LCM_CRTC_VR_SVAL(vsync);
-
-}
-
-/*
- *	Activate (set) the controller from the given framebuffer
- *	information
- */
-static void nuc900fb_activate_var(struct fb_info *info)
-{
-	struct nuc900fb_info *fbi = info->par;
-	void __iomem *regs = fbi->io;
-	struct fb_var_screeninfo *var = &info->var;
-	int clkdiv;
-
-	clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1;
-	if (clkdiv < 0)
-		clkdiv = 0;
-
-	nuc900fb_calculate_lcd_regs(info, &fbi->regs);
-
-	/* set the new lcd registers*/
-
-	dev_dbg(fbi->dev, "new lcd register set:\n");
-	dev_dbg(fbi->dev, "dccs       = 0x%08x\n", fbi->regs.lcd_dccs);
-	dev_dbg(fbi->dev, "dev_ctl    = 0x%08x\n", fbi->regs.lcd_device_ctrl);
-	dev_dbg(fbi->dev, "crtc_size  = 0x%08x\n", fbi->regs.lcd_crtc_size);
-	dev_dbg(fbi->dev, "crtc_dend  = 0x%08x\n", fbi->regs.lcd_crtc_dend);
-	dev_dbg(fbi->dev, "crtc_hr    = 0x%08x\n", fbi->regs.lcd_crtc_hr);
-	dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync);
-	dev_dbg(fbi->dev, "crtc_vr    = 0x%08x\n", fbi->regs.lcd_crtc_vr);
-
-	writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL);
-	writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE);
-	writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND);
-	writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR);
-	writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC);
-	writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR);
-
-	/* set lcd address pointers */
-	nuc900fb_set_lcdaddr(info);
-
-	writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS);
-}
-
-/*
- *      Alters the hardware state.
- *
- */
-static int nuc900fb_set_par(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-
-	switch (var->bits_per_pixel) {
-	case 32:
-	case 24:
-	case 18:
-	case 16:
-	case 12:
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	case 1:
-		info->fix.visual = FB_VISUAL_MONO01;
-		break;
-	default:
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	}
-
-	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
-
-	/* activate this new configuration */
-	nuc900fb_activate_var(info);
-	return 0;
-}
-
-static inline unsigned int chan_to_field(unsigned int chan,
-					 struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int nuc900fb_setcolreg(unsigned regno,
-			       unsigned red, unsigned green, unsigned blue,
-			       unsigned transp, struct fb_info *info)
-{
-	unsigned int val;
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/* true-colour, use pseuo-palette */
-		if (regno < 16) {
-			u32 *pal = info->pseudo_palette;
-
-			val  = chan_to_field(red, &info->var.red);
-			val |= chan_to_field(green, &info->var.green);
-			val |= chan_to_field(blue, &info->var.blue);
-			pal[regno] = val;
-		}
-		break;
-
-	default:
-		return 1;   /* unknown type */
-	}
-	return 0;
-}
-
-/**
- *      nuc900fb_blank
- *
- */
-static int nuc900fb_blank(int blank_mode, struct fb_info *info)
-{
-
-	return 0;
-}
-
-static struct fb_ops nuc900fb_ops = {
-	.owner			= THIS_MODULE,
-	.fb_check_var		= nuc900fb_check_var,
-	.fb_set_par		= nuc900fb_set_par,
-	.fb_blank		= nuc900fb_blank,
-	.fb_setcolreg		= nuc900fb_setcolreg,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-};
-
-
-static inline void modify_gpio(void __iomem *reg,
-			       unsigned long set, unsigned long mask)
-{
-	unsigned long tmp;
-	tmp = readl(reg) & ~mask;
-	writel(tmp | set, reg);
-}
-
-/*
- * Initialise LCD-related registers
- */
-static int nuc900fb_init_registers(struct fb_info *info)
-{
-	struct nuc900fb_info *fbi = info->par;
-	struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
-	void __iomem *regs = fbi->io;
-
-	/*reset the display engine*/
-	writel(0, regs + REG_LCM_DCCS);
-	writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST,
-	       regs + REG_LCM_DCCS);
-	ndelay(100);
-	writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST),
-	       regs + REG_LCM_DCCS);
-	ndelay(100);
-
-	writel(0, regs + REG_LCM_DEV_CTRL);
-
-	/* config gpio output */
-	modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir,
-		    mach_info->gpio_dir_mask);
-	modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data,
-		    mach_info->gpio_data_mask);
-
-	return 0;
-}
-
-
-/*
- *    Alloc the SDRAM region of NUC900 for the frame buffer.
- *    The buffer should be a non-cached, non-buffered, memory region
- *    to allow palette and pixel writes without flushing the cache.
- */
-static int nuc900fb_map_video_memory(struct fb_info *info)
-{
-	struct nuc900fb_info *fbi = info->par;
-	dma_addr_t map_dma;
-	unsigned long map_size = PAGE_ALIGN(info->fix.smem_len);
-
-	dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n",
-		fbi, map_size);
-
-	info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
-							&map_dma, GFP_KERNEL);
-
-	if (!info->screen_base)
-		return -ENOMEM;
-
-	memset(info->screen_base, 0x00, map_size);
-	info->fix.smem_start = map_dma;
-
-	return 0;
-}
-
-static inline void nuc900fb_unmap_video_memory(struct fb_info *info)
-{
-	struct nuc900fb_info *fbi = info->par;
-	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
-			      info->screen_base, info->fix.smem_start);
-}
-
-static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id)
-{
-	struct nuc900fb_info *fbi = dev_id;
-	void __iomem *regs = fbi->io;
-	void __iomem *irq_base = fbi->irq_base;
-	unsigned long lcdirq = readl(regs + REG_LCM_INT_CS);
-
-	if (lcdirq & LCM_INT_CS_DISP_F_STATUS) {
-		writel(readl(irq_base) | 1<<30, irq_base);
-
-		/* wait VA_EN low */
-		if ((readl(regs + REG_LCM_DCCS) &
-		    LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE)
-			while ((readl(regs + REG_LCM_DCCS) &
-			       LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN)
-				;
-		/* display_out-enable */
-		writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN,
-			regs + REG_LCM_DCCS);
-		/* va-enable*/
-		writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN,
-			regs + REG_LCM_DCCS);
-	} else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) {
-		writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base);
-	} else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) {
-		writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base);
-	}
-
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_CPU_FREQ
-
-static int nuc900fb_cpufreq_transition(struct notifier_block *nb,
-				       unsigned long val, void *data)
-{
-	struct nuc900fb_info *info;
-	struct fb_info *fbinfo;
-	long delta_f;
-	info = container_of(nb, struct nuc900fb_info, freq_transition);
-	fbinfo = platform_get_drvdata(to_platform_device(info->dev));
-
-	delta_f = info->clk_rate - clk_get_rate(info->clk);
-
-	if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
-	   (val == CPUFREQ_PRECHANGE && delta_f < 0)) {
-		info->clk_rate = clk_get_rate(info->clk);
-		nuc900fb_activate_var(fbinfo);
-	}
-
-	return 0;
-}
-
-static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
-{
-	fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition;
-	return cpufreq_register_notifier(&fbi->freq_transition,
-				  CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi)
-{
-	cpufreq_unregister_notifier(&fbi->freq_transition,
-				    CPUFREQ_TRANSITION_NOTIFIER);
-}
-#else
-static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb,
-				       unsigned long val, void *data)
-{
-	return 0;
-}
-
-static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
-{
-	return 0;
-}
-
-static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info)
-{
-}
-#endif
-
-static char driver_name[] = "nuc900fb";
-
-static int nuc900fb_probe(struct platform_device *pdev)
-{
-	struct nuc900fb_info *fbi;
-	struct nuc900fb_display *display;
-	struct fb_info	   *fbinfo;
-	struct nuc900fb_mach_info *mach_info;
-	struct resource *res;
-	int ret;
-	int irq;
-	int i;
-	int size;
-
-	dev_dbg(&pdev->dev, "devinit\n");
-	mach_info = dev_get_platdata(&pdev->dev);
-	if (mach_info == NULL) {
-		dev_err(&pdev->dev,
-			"no platform data for lcd, cannot attach\n");
-		return -EINVAL;
-	}
-
-	if (mach_info->default_display > mach_info->num_displays) {
-		dev_err(&pdev->dev,
-			"default display No. is %d but only %d displays \n",
-			mach_info->default_display, mach_info->num_displays);
-		return -EINVAL;
-	}
-
-
-	display = mach_info->displays + mach_info->default_display;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no irq for device\n");
-		return -ENOENT;
-	}
-
-	fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev);
-	if (!fbinfo)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, fbinfo);
-
-	fbi = fbinfo->par;
-	fbi->dev = &pdev->dev;
-
-#ifdef CONFIG_CPU_NUC950
-	fbi->drv_type = LCDDRV_NUC950;
-#endif
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	size = resource_size(res);
-	fbi->mem = request_mem_region(res->start, size, pdev->name);
-	if (fbi->mem == NULL) {
-		dev_err(&pdev->dev, "failed to alloc memory region\n");
-		ret = -ENOENT;
-		goto free_fb;
-	}
-
-	fbi->io = ioremap(res->start, size);
-	if (fbi->io == NULL) {
-		dev_err(&pdev->dev, "ioremap() of lcd registers failed\n");
-		ret = -ENXIO;
-		goto release_mem_region;
-	}
-
-	fbi->irq_base = fbi->io + REG_LCM_INT_CS;
-
-
-	/* Stop the LCD */
-	writel(0, fbi->io + REG_LCM_DCCS);
-
-	/* fill the fbinfo*/
-	strcpy(fbinfo->fix.id, driver_name);
-	fbinfo->fix.type		= FB_TYPE_PACKED_PIXELS;
-	fbinfo->fix.type_aux		= 0;
-	fbinfo->fix.xpanstep		= 0;
-	fbinfo->fix.ypanstep		= 0;
-	fbinfo->fix.ywrapstep		= 0;
-	fbinfo->fix.accel		= FB_ACCEL_NONE;
-	fbinfo->var.nonstd		= 0;
-	fbinfo->var.activate		= FB_ACTIVATE_NOW;
-	fbinfo->var.accel_flags		= 0;
-	fbinfo->var.vmode		= FB_VMODE_NONINTERLACED;
-	fbinfo->fbops			= &nuc900fb_ops;
-	fbinfo->flags			= FBINFO_FLAG_DEFAULT;
-	fbinfo->pseudo_palette		= &fbi->pseudo_pal;
-
-	ret = request_irq(irq, nuc900fb_irqhandler, 0, pdev->name, fbi);
-	if (ret) {
-		dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
-			irq, ret);
-		ret = -EBUSY;
-		goto release_regs;
-	}
-
-	fbi->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(fbi->clk)) {
-		printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
-		ret = PTR_ERR(fbi->clk);
-		goto release_irq;
-	}
-
-	clk_enable(fbi->clk);
-	dev_dbg(&pdev->dev, "got and enabled clock\n");
-
-	fbi->clk_rate = clk_get_rate(fbi->clk);
-
-	/* calutate the video buffer size */
-	for (i = 0; i < mach_info->num_displays; i++) {
-		unsigned long smem_len = mach_info->displays[i].xres;
-		smem_len *= mach_info->displays[i].yres;
-		smem_len *= mach_info->displays[i].bpp;
-		smem_len >>= 3;
-		if (fbinfo->fix.smem_len < smem_len)
-			fbinfo->fix.smem_len = smem_len;
-	}
-
-	/* Initialize Video Memory */
-	ret = nuc900fb_map_video_memory(fbinfo);
-	if (ret) {
-		printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret);
-		goto release_clock;
-	}
-
-	dev_dbg(&pdev->dev, "got video memory\n");
-
-	fbinfo->var.xres = display->xres;
-	fbinfo->var.yres = display->yres;
-	fbinfo->var.bits_per_pixel = display->bpp;
-
-	nuc900fb_init_registers(fbinfo);
-
-	nuc900fb_check_var(&fbinfo->var, fbinfo);
-
-	ret = nuc900fb_cpufreq_register(fbi);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to register cpufreq\n");
-		goto free_video_memory;
-	}
-
-	ret = register_framebuffer(fbinfo);
-	if (ret) {
-		printk(KERN_ERR "failed to register framebuffer device: %d\n",
-			ret);
-		goto free_cpufreq;
-	}
-
-	fb_info(fbinfo, "%s frame buffer device\n", fbinfo->fix.id);
-
-	return 0;
-
-free_cpufreq:
-	nuc900fb_cpufreq_deregister(fbi);
-free_video_memory:
-	nuc900fb_unmap_video_memory(fbinfo);
-release_clock:
-	clk_disable(fbi->clk);
-	clk_put(fbi->clk);
-release_irq:
-	free_irq(irq, fbi);
-release_regs:
-	iounmap(fbi->io);
-release_mem_region:
-	release_mem_region(res->start, size);
-free_fb:
-	framebuffer_release(fbinfo);
-	return ret;
-}
-
-/*
- * shutdown the lcd controller
- */
-static void nuc900fb_stop_lcd(struct fb_info *info)
-{
-	struct nuc900fb_info *fbi = info->par;
-	void __iomem *regs = fbi->io;
-
-	writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN),
-		regs + REG_LCM_DCCS);
-}
-
-/*
- *  Cleanup
- */
-static int nuc900fb_remove(struct platform_device *pdev)
-{
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct nuc900fb_info *fbi = fbinfo->par;
-	int irq;
-
-	nuc900fb_stop_lcd(fbinfo);
-	msleep(1);
-
-	unregister_framebuffer(fbinfo);
-	nuc900fb_cpufreq_deregister(fbi);
-	nuc900fb_unmap_video_memory(fbinfo);
-
-	iounmap(fbi->io);
-
-	irq = platform_get_irq(pdev, 0);
-	free_irq(irq, fbi);
-
-	release_resource(fbi->mem);
-	kfree(fbi->mem);
-
-	framebuffer_release(fbinfo);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-/*
- *	suspend and resume support for the lcd controller
- */
-
-static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
-	struct nuc900fb_info *info = fbinfo->par;
-
-	nuc900fb_stop_lcd(fbinfo);
-	msleep(1);
-	clk_disable(info->clk);
-	return 0;
-}
-
-static int nuc900fb_resume(struct platform_device *dev)
-{
-	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
-	struct nuc900fb_info *fbi = fbinfo->par;
-
-	printk(KERN_INFO "nuc900fb resume\n");
-
-	clk_enable(fbi->clk);
-	msleep(1);
-
-	nuc900fb_init_registers(fbinfo);
-	nuc900fb_activate_var(fbinfo);
-
-	return 0;
-}
-
-#else
-#define nuc900fb_suspend NULL
-#define nuc900fb_resume  NULL
-#endif
-
-static struct platform_driver nuc900fb_driver = {
-	.probe		= nuc900fb_probe,
-	.remove		= nuc900fb_remove,
-	.suspend	= nuc900fb_suspend,
-	.resume		= nuc900fb_resume,
-	.driver		= {
-		.name	= "nuc900-lcd",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(nuc900fb_driver);
-
-MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h
deleted file mode 100644
index 9a1ca6dbb6b2..000000000000
--- a/drivers/video/nuc900fb.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * Copyright (c) 2009 Nuvoton technology corporation
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- *   Author:
- *        Wang Qiang(rurality.linux@gmail.com)  2009/12/16
- */
-
-#ifndef __NUC900FB_H
-#define __NUC900FB_H
-
-#include <mach/map.h>
-#include <linux/platform_data/video-nuc900fb.h>
-
-enum nuc900_lcddrv_type {
-	LCDDRV_NUC910,
-	LCDDRV_NUC930,
-	LCDDRV_NUC932,
-	LCDDRV_NUC950,
-	LCDDRV_NUC960,
-};
-
-
-#define PALETTE_BUFFER_SIZE	256
-#define PALETTE_BUFF_CLEAR 	(0x80000000) /* entry is clear/invalid */
-
-struct nuc900fb_info {
-	struct device		*dev;
-	struct clk		*clk;
-
-	struct resource		*mem;
-	void __iomem		*io;
-	void __iomem		*irq_base;
-	int 			drv_type;
-	struct nuc900fb_hw	regs;
-	unsigned long		clk_rate;
-
-#ifdef CONFIG_CPU_FREQ
-	struct notifier_block	freq_transition;
-#endif
-
-	/* keep these registers in case we need to re-write palette */
-	u32			palette_buffer[PALETTE_BUFFER_SIZE];
-	u32			pseudo_pal[16];
-};
-
-int nuc900fb_init(void);
-
-#endif /* __NUC900FB_H */
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile
deleted file mode 100644
index ca47432113e0..000000000000
--- a/drivers/video/nvidia/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Makefile for the nVidia framebuffer driver
-#
-
-obj-$(CONFIG_FB_NVIDIA)          += nvidiafb.o
-
-nvidiafb-y                       := nvidia.o nv_hw.o nv_setup.o \
-			            nv_accel.o
-nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
-nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT)  += nv_backlight.o
-nvidiafb-$(CONFIG_PPC_OF)	 += nv_of.o
-
-nvidiafb-objs                    := $(nvidiafb-y)
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
deleted file mode 100644
index ad6472a894ea..000000000000
--- a/drivers/video/nvidia/nv_accel.c
+++ /dev/null
@@ -1,416 +0,0 @@
- /***************************************************************************\
-|*                                                                           *|
-|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
- * XFree86 'nv' driver, this source code is provided under MIT-style licensing
- * where the source code is provided "as is" without warranty of any kind.
- * The only usage restriction is for the copyright notices to be retained
- * whenever code is used.
- *
- * Antonino Daplas <adaplas@pol.net> 2005-03-11
- */
-
-#include <linux/fb.h>
-#include "nv_type.h"
-#include "nv_proto.h"
-#include "nv_dma.h"
-#include "nv_local.h"
-
-/* There is a HW race condition with videoram command buffers.
-   You can't jump to the location of your put offset.  We write put
-   at the jump offset + SKIPS dwords with noop padding in between
-   to solve this problem */
-#define SKIPS  8
-
-static const int NVCopyROP[16] = {
-	0xCC,			/* copy   */
-	0x55			/* invert */
-};
-
-static const int NVCopyROP_PM[16] = {
-	0xCA,			/* copy  */
-	0x5A,			/* invert */
-};
-
-static inline void nvidiafb_safe_mode(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-
-	touch_softlockup_watchdog();
-	info->pixmap.scan_align = 1;
-	par->lockup = 1;
-}
-
-static inline void NVFlush(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	int count = 1000000000;
-
-	while (--count && READ_GET(par) != par->dmaPut) ;
-
-	if (!count) {
-		printk("nvidiafb: DMA Flush lockup\n");
-		nvidiafb_safe_mode(info);
-	}
-}
-
-static inline void NVSync(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	int count = 1000000000;
-
-	while (--count && NV_RD32(par->PGRAPH, 0x0700)) ;
-
-	if (!count) {
-		printk("nvidiafb: DMA Sync lockup\n");
-		nvidiafb_safe_mode(info);
-	}
-}
-
-static void NVDmaKickoff(struct nvidia_par *par)
-{
-	if (par->dmaCurrent != par->dmaPut) {
-		par->dmaPut = par->dmaCurrent;
-		WRITE_PUT(par, par->dmaPut);
-	}
-}
-
-static void NVDmaWait(struct fb_info *info, int size)
-{
-	struct nvidia_par *par = info->par;
-	int dmaGet;
-	int count = 1000000000, cnt;
-	size++;
-
-	while (par->dmaFree < size && --count && !par->lockup) {
-		dmaGet = READ_GET(par);
-
-		if (par->dmaPut >= dmaGet) {
-			par->dmaFree = par->dmaMax - par->dmaCurrent;
-			if (par->dmaFree < size) {
-				NVDmaNext(par, 0x20000000);
-				if (dmaGet <= SKIPS) {
-					if (par->dmaPut <= SKIPS)
-						WRITE_PUT(par, SKIPS + 1);
-					cnt = 1000000000;
-					do {
-						dmaGet = READ_GET(par);
-					} while (--cnt && dmaGet <= SKIPS);
-					if (!cnt) {
-						printk("DMA Get lockup\n");
-						par->lockup = 1;
-					}
-				}
-				WRITE_PUT(par, SKIPS);
-				par->dmaCurrent = par->dmaPut = SKIPS;
-				par->dmaFree = dmaGet - (SKIPS + 1);
-			}
-		} else
-			par->dmaFree = dmaGet - par->dmaCurrent - 1;
-	}
-
-	if (!count) {
-		printk("nvidiafb: DMA Wait Lockup\n");
-		nvidiafb_safe_mode(info);
-	}
-}
-
-static void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1,
-			 u32 pat0, u32 pat1)
-{
-	struct nvidia_par *par = info->par;
-
-	NVDmaStart(info, par, PATTERN_COLOR_0, 4);
-	NVDmaNext(par, clr0);
-	NVDmaNext(par, clr1);
-	NVDmaNext(par, pat0);
-	NVDmaNext(par, pat1);
-}
-
-static void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask)
-{
-	struct nvidia_par *par = info->par;
-
-	if (planemask != ~0) {
-		NVSetPattern(info, 0, planemask, ~0, ~0);
-		if (par->currentRop != (rop + 32)) {
-			NVDmaStart(info, par, ROP_SET, 1);
-			NVDmaNext(par, NVCopyROP_PM[rop]);
-			par->currentRop = rop + 32;
-		}
-	} else if (par->currentRop != rop) {
-		if (par->currentRop >= 16)
-			NVSetPattern(info, ~0, ~0, ~0, ~0);
-		NVDmaStart(info, par, ROP_SET, 1);
-		NVDmaNext(par, NVCopyROP[rop]);
-		par->currentRop = rop;
-	}
-}
-
-static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1,
-				   int x2, int y2)
-{
-	struct nvidia_par *par = info->par;
-	int h = y2 - y1 + 1;
-	int w = x2 - x1 + 1;
-
-	NVDmaStart(info, par, CLIP_POINT, 2);
-	NVDmaNext(par, (y1 << 16) | x1);
-	NVDmaNext(par, (h << 16) | w);
-}
-
-void NVResetGraphics(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	u32 surfaceFormat, patternFormat, rectFormat, lineFormat;
-	int pitch, i;
-
-	pitch = info->fix.line_length;
-
-	par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]);
-
-	for (i = 0; i < SKIPS; i++)
-		NV_WR32(&par->dmaBase[i], 0, 0x00000000);
-
-	NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000);
-	NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010);
-	NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000);
-	NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011);
-	NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000);
-	NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012);
-	NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000);
-	NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013);
-	NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000);
-	NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014);
-	NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000);
-	NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015);
-	NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000);
-	NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016);
-	NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000);
-	NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017);
-
-	par->dmaPut = 0;
-	par->dmaCurrent = 16 + SKIPS;
-	par->dmaMax = 8191;
-	par->dmaFree = par->dmaMax - par->dmaCurrent;
-
-	switch (info->var.bits_per_pixel) {
-	case 32:
-	case 24:
-		surfaceFormat = SURFACE_FORMAT_DEPTH24;
-		patternFormat = PATTERN_FORMAT_DEPTH24;
-		rectFormat = RECT_FORMAT_DEPTH24;
-		lineFormat = LINE_FORMAT_DEPTH24;
-		break;
-	case 16:
-		surfaceFormat = SURFACE_FORMAT_DEPTH16;
-		patternFormat = PATTERN_FORMAT_DEPTH16;
-		rectFormat = RECT_FORMAT_DEPTH16;
-		lineFormat = LINE_FORMAT_DEPTH16;
-		break;
-	default:
-		surfaceFormat = SURFACE_FORMAT_DEPTH8;
-		patternFormat = PATTERN_FORMAT_DEPTH8;
-		rectFormat = RECT_FORMAT_DEPTH8;
-		lineFormat = LINE_FORMAT_DEPTH8;
-		break;
-	}
-
-	NVDmaStart(info, par, SURFACE_FORMAT, 4);
-	NVDmaNext(par, surfaceFormat);
-	NVDmaNext(par, pitch | (pitch << 16));
-	NVDmaNext(par, 0);
-	NVDmaNext(par, 0);
-
-	NVDmaStart(info, par, PATTERN_FORMAT, 1);
-	NVDmaNext(par, patternFormat);
-
-	NVDmaStart(info, par, RECT_FORMAT, 1);
-	NVDmaNext(par, rectFormat);
-
-	NVDmaStart(info, par, LINE_FORMAT, 1);
-	NVDmaNext(par, lineFormat);
-
-	par->currentRop = ~0;	/* set to something invalid */
-	NVSetRopSolid(info, ROP_COPY, ~0);
-
-	NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual,
-			       info->var.yres_virtual);
-
-	NVDmaKickoff(par);
-}
-
-int nvidiafb_sync(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return 0;
-
-	if (!par->lockup)
-		NVFlush(info);
-
-	if (!par->lockup)
-		NVSync(info);
-
-	return 0;
-}
-
-void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
-	struct nvidia_par *par = info->par;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (par->lockup) {
-		cfb_copyarea(info, region);
-		return;
-	}
-
-	NVDmaStart(info, par, BLIT_POINT_SRC, 3);
-	NVDmaNext(par, (region->sy << 16) | region->sx);
-	NVDmaNext(par, (region->dy << 16) | region->dx);
-	NVDmaNext(par, (region->height << 16) | region->width);
-
-	NVDmaKickoff(par);
-}
-
-void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct nvidia_par *par = info->par;
-	u32 color;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (par->lockup) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	if (info->var.bits_per_pixel == 8)
-		color = rect->color;
-	else
-		color = ((u32 *) info->pseudo_palette)[rect->color];
-
-	if (rect->rop != ROP_COPY)
-		NVSetRopSolid(info, rect->rop, ~0);
-
-	NVDmaStart(info, par, RECT_SOLID_COLOR, 1);
-	NVDmaNext(par, color);
-
-	NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2);
-	NVDmaNext(par, (rect->dx << 16) | rect->dy);
-	NVDmaNext(par, (rect->width << 16) | rect->height);
-
-	NVDmaKickoff(par);
-
-	if (rect->rop != ROP_COPY)
-		NVSetRopSolid(info, ROP_COPY, ~0);
-}
-
-static void nvidiafb_mono_color_expand(struct fb_info *info,
-				       const struct fb_image *image)
-{
-	struct nvidia_par *par = info->par;
-	u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
-	u32 dsize, width, *data = (u32 *) image->data, tmp;
-	int j, k = 0;
-
-	width = (image->width + 31) & ~31;
-	dsize = (width * image->height) >> 5;
-
-	if (info->var.bits_per_pixel == 8) {
-		fg = image->fg_color | mask;
-		bg = image->bg_color | mask;
-	} else {
-		fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask;
-		bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask;
-	}
-
-	NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
-	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
-	NVDmaNext(par, ((image->dy + image->height) << 16) |
-		  ((image->dx + image->width) & 0xffff));
-	NVDmaNext(par, bg);
-	NVDmaNext(par, fg);
-	NVDmaNext(par, (image->height << 16) | width);
-	NVDmaNext(par, (image->height << 16) | width);
-	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
-
-	while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
-		NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0),
-			   RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
-
-		for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
-			tmp = data[k++];
-			reverse_order(&tmp);
-			NVDmaNext(par, tmp);
-		}
-
-		dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS;
-	}
-
-	if (dsize) {
-		NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
-
-		for (j = dsize; j--;) {
-			tmp = data[k++];
-			reverse_order(&tmp);
-			NVDmaNext(par, tmp);
-		}
-	}
-
-	NVDmaKickoff(par);
-}
-
-void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct nvidia_par *par = info->par;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (image->depth == 1 && !par->lockup)
-		nvidiafb_mono_color_expand(info, image);
-	else
-		cfb_imageblit(info, image);
-}
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
deleted file mode 100644
index 8471008aa6ff..000000000000
--- a/drivers/video/nvidia/nv_backlight.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Backlight code for nVidia based graphic cards
- *
- * Copyright 2004 Antonino Daplas <adaplas@pol.net>
- * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/backlight.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
-#include "nv_local.h"
-#include "nv_type.h"
-#include "nv_proto.h"
-
-/* We do not have any information about which values are allowed, thus
- * we used safe values.
- */
-#define MIN_LEVEL 0x158
-#define MAX_LEVEL 0x534
-#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
-
-static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
-		int level)
-{
-	struct fb_info *info = pci_get_drvdata(par->pci_dev);
-	int nlevel;
-
-	/* Get and convert the value */
-	/* No locking of bl_curve since we read a single value */
-	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
-
-	if (nlevel < 0)
-		nlevel = 0;
-	else if (nlevel < MIN_LEVEL)
-		nlevel = MIN_LEVEL;
-	else if (nlevel > MAX_LEVEL)
-		nlevel = MAX_LEVEL;
-
-	return nlevel;
-}
-
-static int nvidia_bl_update_status(struct backlight_device *bd)
-{
-	struct nvidia_par *par = bl_get_data(bd);
-	u32 tmp_pcrt, tmp_pmc, fpcontrol;
-	int level;
-
-	if (!par->FlatPanel)
-		return 0;
-
-	if (bd->props.power != FB_BLANK_UNBLANK ||
-	    bd->props.fb_blank != FB_BLANK_UNBLANK)
-		level = 0;
-	else
-		level = bd->props.brightness;
-
-	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
-	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
-	fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
-
-	if (level > 0) {
-		tmp_pcrt |= 0x1;
-		tmp_pmc |= (1 << 31); /* backlight bit */
-		tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
-		fpcontrol |= par->fpSyncs;
-	} else
-		fpcontrol |= 0x20000022;
-
-	NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
-	NV_WR32(par->PMC, 0x10F0, tmp_pmc);
-	NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
-
-	return 0;
-}
-
-static int nvidia_bl_get_brightness(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
-static const struct backlight_ops nvidia_bl_ops = {
-	.get_brightness = nvidia_bl_get_brightness,
-	.update_status	= nvidia_bl_update_status,
-};
-
-void nvidia_bl_init(struct nvidia_par *par)
-{
-	struct backlight_properties props;
-	struct fb_info *info = pci_get_drvdata(par->pci_dev);
-	struct backlight_device *bd;
-	char name[12];
-
-	if (!par->FlatPanel)
-		return;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (!machine_is(powermac) ||
-	    !pmac_has_backlight_type("mnca"))
-		return;
-#endif
-
-	snprintf(name, sizeof(name), "nvidiabl%d", info->node);
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
-	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
-				       &props);
-	if (IS_ERR(bd)) {
-		info->bl_dev = NULL;
-		printk(KERN_WARNING "nvidia: Backlight registration failed\n");
-		goto error;
-	}
-
-	info->bl_dev = bd;
-	fb_bl_default_curve(info, 0,
-		0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
-		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-
-	bd->props.brightness = bd->props.max_brightness;
-	bd->props.power = FB_BLANK_UNBLANK;
-	backlight_update_status(bd);
-
-	printk("nvidia: Backlight initialized (%s)\n", name);
-
-	return;
-
-error:
-	return;
-}
-
-void nvidia_bl_exit(struct nvidia_par *par)
-{
-	struct fb_info *info = pci_get_drvdata(par->pci_dev);
-	struct backlight_device *bd = info->bl_dev;
-
-	backlight_device_unregister(bd);
-	printk("nvidia: Backlight unloaded\n");
-}
diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h
deleted file mode 100644
index a7ed1c0acbbb..000000000000
--- a/drivers/video/nvidia/nv_dma.h
+++ /dev/null
@@ -1,188 +0,0 @@
-
- /***************************************************************************\
-|*                                                                           *|
-|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
- * XFree86 'nv' driver, this source code is provided under MIT-style licensing
- * where the source code is provided "as is" without warranty of any kind.
- * The only usage restriction is for the copyright notices to be retained
- * whenever code is used.
- *
- * Antonino Daplas <adaplas@pol.net> 2005-03-11
- */
-
-#define SURFACE_FORMAT                                              0x00000300
-#define SURFACE_FORMAT_DEPTH8                                       0x00000001
-#define SURFACE_FORMAT_DEPTH15                                      0x00000002
-#define SURFACE_FORMAT_DEPTH16                                      0x00000004
-#define SURFACE_FORMAT_DEPTH24                                      0x00000006
-#define SURFACE_PITCH                                               0x00000304
-#define SURFACE_PITCH_SRC                                           15:0
-#define SURFACE_PITCH_DST                                           31:16
-#define SURFACE_OFFSET_SRC                                          0x00000308
-#define SURFACE_OFFSET_DST                                          0x0000030C
-
-#define ROP_SET                                                     0x00002300
-
-#define PATTERN_FORMAT                                              0x00004300
-#define PATTERN_FORMAT_DEPTH8                                       0x00000003
-#define PATTERN_FORMAT_DEPTH16                                      0x00000001
-#define PATTERN_FORMAT_DEPTH24                                      0x00000003
-#define PATTERN_COLOR_0                                             0x00004310
-#define PATTERN_COLOR_1                                             0x00004314
-#define PATTERN_PATTERN_0                                           0x00004318
-#define PATTERN_PATTERN_1                                           0x0000431C
-
-#define CLIP_POINT                                                  0x00006300
-#define CLIP_POINT_X                                                15:0
-#define CLIP_POINT_Y                                                31:16
-#define CLIP_SIZE                                                   0x00006304
-#define CLIP_SIZE_WIDTH                                             15:0
-#define CLIP_SIZE_HEIGHT                                            31:16
-
-#define LINE_FORMAT                                                 0x00008300
-#define LINE_FORMAT_DEPTH8                                          0x00000003
-#define LINE_FORMAT_DEPTH16                                         0x00000001
-#define LINE_FORMAT_DEPTH24                                         0x00000003
-#define LINE_COLOR                                                  0x00008304
-#define LINE_MAX_LINES                                              16
-#define LINE_LINES(i)                                               0x00008400\
-                                                                    +(i)*8
-#define LINE_LINES_POINT0_X                                         15:0
-#define LINE_LINES_POINT0_Y                                         31:16
-#define LINE_LINES_POINT1_X                                         47:32
-#define LINE_LINES_POINT1_Y                                         63:48
-
-#define BLIT_POINT_SRC                                              0x0000A300
-#define BLIT_POINT_SRC_X                                            15:0
-#define BLIT_POINT_SRC_Y                                            31:16
-#define BLIT_POINT_DST                                              0x0000A304
-#define BLIT_POINT_DST_X                                            15:0
-#define BLIT_POINT_DST_Y                                            31:16
-#define BLIT_SIZE                                                   0x0000A308
-#define BLIT_SIZE_WIDTH                                             15:0
-#define BLIT_SIZE_HEIGHT                                            31:16
-
-#define RECT_FORMAT                                                 0x0000C300
-#define RECT_FORMAT_DEPTH8                                          0x00000003
-#define RECT_FORMAT_DEPTH16                                         0x00000001
-#define RECT_FORMAT_DEPTH24                                         0x00000003
-#define RECT_SOLID_COLOR                                            0x0000C3FC
-#define RECT_SOLID_RECTS_MAX_RECTS                                  32
-#define RECT_SOLID_RECTS(i)                                         0x0000C400\
-                                                                    +(i)*8
-#define RECT_SOLID_RECTS_Y                                          15:0
-#define RECT_SOLID_RECTS_X                                          31:16
-#define RECT_SOLID_RECTS_HEIGHT                                     47:32
-#define RECT_SOLID_RECTS_WIDTH                                      63:48
-
-#define RECT_EXPAND_ONE_COLOR_CLIP                                  0x0000C7EC
-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X                         15:0
-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y                         31:16
-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X                         47:32
-#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y                         63:48
-#define RECT_EXPAND_ONE_COLOR_COLOR                                 0x0000C7F4
-#define RECT_EXPAND_ONE_COLOR_SIZE                                  0x0000C7F8
-#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH                            15:0
-#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT                           31:16
-#define RECT_EXPAND_ONE_COLOR_POINT                                 0x0000C7FC
-#define RECT_EXPAND_ONE_COLOR_POINT_X                               15:0
-#define RECT_EXPAND_ONE_COLOR_POINT_Y                               31:16
-#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS                       128
-#define RECT_EXPAND_ONE_COLOR_DATA(i)                               0x0000C800\
-                                                                    +(i)*4
-
-#define RECT_EXPAND_TWO_COLOR_CLIP                                  0x0000CBE4
-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X                         15:0
-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y                         31:16
-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X                         47:32
-#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y                         63:48
-#define RECT_EXPAND_TWO_COLOR_COLOR_0                               0x0000CBEC
-#define RECT_EXPAND_TWO_COLOR_COLOR_1                               0x0000CBF0
-#define RECT_EXPAND_TWO_COLOR_SIZE_IN                               0x0000CBF4
-#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH                         15:0
-#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT                        31:16
-#define RECT_EXPAND_TWO_COLOR_SIZE_OUT                              0x0000CBF8
-#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH                        15:0
-#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT                       31:16
-#define RECT_EXPAND_TWO_COLOR_POINT                                 0x0000CBFC
-#define RECT_EXPAND_TWO_COLOR_POINT_X                               15:0
-#define RECT_EXPAND_TWO_COLOR_POINT_Y                               31:16
-#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS                       128
-#define RECT_EXPAND_TWO_COLOR_DATA(i)                               0x0000CC00\
-                                                                    +(i)*4
-
-#define STRETCH_BLIT_FORMAT                                         0x0000E300
-#define STRETCH_BLIT_FORMAT_DEPTH8                                  0x00000004
-#define STRETCH_BLIT_FORMAT_DEPTH16                                 0x00000007
-#define STRETCH_BLIT_FORMAT_DEPTH24                                 0x00000004
-#define STRETCH_BLIT_FORMAT_X8R8G8B8                                0x00000004
-#define STRETCH_BLIT_FORMAT_YUYV                                    0x00000005
-#define STRETCH_BLIT_FORMAT_UYVY                                    0x00000006
-#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
-#define STRETCH_BLIT_CLIP_POINT_X                                   15:0
-#define STRETCH_BLIT_CLIP_POINT_Y                                   31:16
-#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
-#define STRETCH_BLIT_CLIP_SIZE                                      0x0000E30C
-#define STRETCH_BLIT_CLIP_SIZE_WIDTH                                15:0
-#define STRETCH_BLIT_CLIP_SIZE_HEIGHT                               31:16
-#define STRETCH_BLIT_DST_POINT                                      0x0000E310
-#define STRETCH_BLIT_DST_POINT_X                                    15:0
-#define STRETCH_BLIT_DST_POINT_Y                                    31:16
-#define STRETCH_BLIT_DST_SIZE                                       0x0000E314
-#define STRETCH_BLIT_DST_SIZE_WIDTH                                 15:0
-#define STRETCH_BLIT_DST_SIZE_HEIGHT                                31:16
-#define STRETCH_BLIT_DU_DX                                          0x0000E318
-#define STRETCH_BLIT_DV_DY                                          0x0000E31C
-#define STRETCH_BLIT_SRC_SIZE                                       0x0000E400
-#define STRETCH_BLIT_SRC_SIZE_WIDTH                                 15:0
-#define STRETCH_BLIT_SRC_SIZE_HEIGHT                                31:16
-#define STRETCH_BLIT_SRC_FORMAT                                     0x0000E404
-#define STRETCH_BLIT_SRC_FORMAT_PITCH                               15:0
-#define STRETCH_BLIT_SRC_FORMAT_ORIGIN                              23:16
-#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER                       0x00000001
-#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER                       0x00000002
-#define STRETCH_BLIT_SRC_FORMAT_FILTER                              31:24
-#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE                 0x00000000
-#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR                     0x00000001
-#define STRETCH_BLIT_SRC_OFFSET                                     0x0000E408
-#define STRETCH_BLIT_SRC_POINT                                      0x0000E40C
-#define STRETCH_BLIT_SRC_POINT_U                                    15:0
-#define STRETCH_BLIT_SRC_POINT_V                                    31:16
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
deleted file mode 100644
index 81c80ac3c76f..000000000000
--- a/drivers/video/nvidia/nv_hw.c
+++ /dev/null
@@ -1,1687 +0,0 @@
- /***************************************************************************\
-|*                                                                           *|
-|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
- * XFree86 'nv' driver, this source code is provided under MIT-style licensing
- * where the source code is provided "as is" without warranty of any kind.
- * The only usage restriction is for the copyright notices to be retained
- * whenever code is used.
- *
- * Antonino Daplas <adaplas@pol.net> 2005-03-11
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */
-
-#include <linux/pci.h>
-#include "nv_type.h"
-#include "nv_local.h"
-#include "nv_proto.h"
-
-void NVLockUnlock(struct nvidia_par *par, int Lock)
-{
-	u8 cr11;
-
-	VGA_WR08(par->PCIO, 0x3D4, 0x1F);
-	VGA_WR08(par->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
-
-	VGA_WR08(par->PCIO, 0x3D4, 0x11);
-	cr11 = VGA_RD08(par->PCIO, 0x3D5);
-	if (Lock)
-		cr11 |= 0x80;
-	else
-		cr11 &= ~0x80;
-	VGA_WR08(par->PCIO, 0x3D5, cr11);
-}
-
-int NVShowHideCursor(struct nvidia_par *par, int ShowHide)
-{
-	int cur = par->CurrentState->cursor1;
-
-	par->CurrentState->cursor1 = (par->CurrentState->cursor1 & 0xFE) |
-	    (ShowHide & 0x01);
-	VGA_WR08(par->PCIO, 0x3D4, 0x31);
-	VGA_WR08(par->PCIO, 0x3D5, par->CurrentState->cursor1);
-
-	if (par->Architecture == NV_ARCH_40)
-		NV_WR32(par->PRAMDAC, 0x0300, NV_RD32(par->PRAMDAC, 0x0300));
-
-	return (cur & 0x01);
-}
-
-/****************************************************************************\
-*                                                                            *
-* The video arbitration routines calculate some "magic" numbers.  Fixes      *
-* the snow seen when accessing the framebuffer without it.                   *
-* It just works (I hope).                                                    *
-*                                                                            *
-\****************************************************************************/
-
-typedef struct {
-	int graphics_lwm;
-	int video_lwm;
-	int graphics_burst_size;
-	int video_burst_size;
-	int valid;
-} nv4_fifo_info;
-
-typedef struct {
-	int pclk_khz;
-	int mclk_khz;
-	int nvclk_khz;
-	char mem_page_miss;
-	char mem_latency;
-	int memory_width;
-	char enable_video;
-	char gr_during_vid;
-	char pix_bpp;
-	char mem_aligned;
-	char enable_mp;
-} nv4_sim_state;
-
-typedef struct {
-	int graphics_lwm;
-	int video_lwm;
-	int graphics_burst_size;
-	int video_burst_size;
-	int valid;
-} nv10_fifo_info;
-
-typedef struct {
-	int pclk_khz;
-	int mclk_khz;
-	int nvclk_khz;
-	char mem_page_miss;
-	char mem_latency;
-	u32 memory_type;
-	int memory_width;
-	char enable_video;
-	char gr_during_vid;
-	char pix_bpp;
-	char mem_aligned;
-	char enable_mp;
-} nv10_sim_state;
-
-static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
-			unsigned int *NVClk)
-{
-	unsigned int pll, N, M, MB, NB, P;
-
-	if (par->Architecture >= NV_ARCH_40) {
-		pll = NV_RD32(par->PMC, 0x4020);
-		P = (pll >> 16) & 0x07;
-		pll = NV_RD32(par->PMC, 0x4024);
-		M = pll & 0xFF;
-		N = (pll >> 8) & 0xFF;
-		if (((par->Chipset & 0xfff0) == 0x0290) ||
-		    ((par->Chipset & 0xfff0) == 0x0390)) {
-			MB = 1;
-			NB = 1;
-		} else {
-			MB = (pll >> 16) & 0xFF;
-			NB = (pll >> 24) & 0xFF;
-		}
-		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
-
-		pll = NV_RD32(par->PMC, 0x4000);
-		P = (pll >> 16) & 0x07;
-		pll = NV_RD32(par->PMC, 0x4004);
-		M = pll & 0xFF;
-		N = (pll >> 8) & 0xFF;
-		MB = (pll >> 16) & 0xFF;
-		NB = (pll >> 24) & 0xFF;
-
-		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
-	} else if (par->twoStagePLL) {
-		pll = NV_RD32(par->PRAMDAC0, 0x0504);
-		M = pll & 0xFF;
-		N = (pll >> 8) & 0xFF;
-		P = (pll >> 16) & 0x0F;
-		pll = NV_RD32(par->PRAMDAC0, 0x0574);
-		if (pll & 0x80000000) {
-			MB = pll & 0xFF;
-			NB = (pll >> 8) & 0xFF;
-		} else {
-			MB = 1;
-			NB = 1;
-		}
-		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
-
-		pll = NV_RD32(par->PRAMDAC0, 0x0500);
-		M = pll & 0xFF;
-		N = (pll >> 8) & 0xFF;
-		P = (pll >> 16) & 0x0F;
-		pll = NV_RD32(par->PRAMDAC0, 0x0570);
-		if (pll & 0x80000000) {
-			MB = pll & 0xFF;
-			NB = (pll >> 8) & 0xFF;
-		} else {
-			MB = 1;
-			NB = 1;
-		}
-		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
-	} else
-	    if (((par->Chipset & 0x0ff0) == 0x0300) ||
-		((par->Chipset & 0x0ff0) == 0x0330)) {
-		pll = NV_RD32(par->PRAMDAC0, 0x0504);
-		M = pll & 0x0F;
-		N = (pll >> 8) & 0xFF;
-		P = (pll >> 16) & 0x07;
-		if (pll & 0x00000080) {
-			MB = (pll >> 4) & 0x07;
-			NB = (pll >> 19) & 0x1f;
-		} else {
-			MB = 1;
-			NB = 1;
-		}
-		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
-
-		pll = NV_RD32(par->PRAMDAC0, 0x0500);
-		M = pll & 0x0F;
-		N = (pll >> 8) & 0xFF;
-		P = (pll >> 16) & 0x07;
-		if (pll & 0x00000080) {
-			MB = (pll >> 4) & 0x07;
-			NB = (pll >> 19) & 0x1f;
-		} else {
-			MB = 1;
-			NB = 1;
-		}
-		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
-	} else {
-		pll = NV_RD32(par->PRAMDAC0, 0x0504);
-		M = pll & 0xFF;
-		N = (pll >> 8) & 0xFF;
-		P = (pll >> 16) & 0x0F;
-		*MClk = (N * par->CrystalFreqKHz / M) >> P;
-
-		pll = NV_RD32(par->PRAMDAC0, 0x0500);
-		M = pll & 0xFF;
-		N = (pll >> 8) & 0xFF;
-		P = (pll >> 16) & 0x0F;
-		*NVClk = (N * par->CrystalFreqKHz / M) >> P;
-	}
-}
-
-static void nv4CalcArbitration(nv4_fifo_info * fifo, nv4_sim_state * arb)
-{
-	int data, pagemiss, cas, width, video_enable, bpp;
-	int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
-	int found, mclk_extra, mclk_loop, cbs, m1, p1;
-	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
-	int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
-	int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
-
-	fifo->valid = 1;
-	pclk_freq = arb->pclk_khz;
-	mclk_freq = arb->mclk_khz;
-	nvclk_freq = arb->nvclk_khz;
-	pagemiss = arb->mem_page_miss;
-	cas = arb->mem_latency;
-	width = arb->memory_width >> 6;
-	video_enable = arb->enable_video;
-	bpp = arb->pix_bpp;
-	mp_enable = arb->enable_mp;
-	clwm = 0;
-	vlwm = 0;
-	cbs = 128;
-	pclks = 2;
-	nvclks = 2;
-	nvclks += 2;
-	nvclks += 1;
-	mclks = 5;
-	mclks += 3;
-	mclks += 1;
-	mclks += cas;
-	mclks += 1;
-	mclks += 1;
-	mclks += 1;
-	mclks += 1;
-	mclk_extra = 3;
-	nvclks += 2;
-	nvclks += 1;
-	nvclks += 1;
-	nvclks += 1;
-	if (mp_enable)
-		mclks += 4;
-	nvclks += 0;
-	pclks += 0;
-	found = 0;
-	vbs = 0;
-	while (found != 1) {
-		fifo->valid = 1;
-		found = 1;
-		mclk_loop = mclks + mclk_extra;
-		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
-		us_n = nvclks * 1000 * 1000 / nvclk_freq;
-		us_p = nvclks * 1000 * 1000 / pclk_freq;
-		if (video_enable) {
-			video_drain_rate = pclk_freq * 2;
-			crtc_drain_rate = pclk_freq * bpp / 8;
-			vpagemiss = 2;
-			vpagemiss += 1;
-			crtpagemiss = 2;
-			vpm_us =
-			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
-			if (nvclk_freq * 2 > mclk_freq * width)
-				video_fill_us =
-				    cbs * 1000 * 1000 / 16 / nvclk_freq;
-			else
-				video_fill_us =
-				    cbs * 1000 * 1000 / (8 * width) /
-				    mclk_freq;
-			us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
-			vlwm = us_video * video_drain_rate / (1000 * 1000);
-			vlwm++;
-			vbs = 128;
-			if (vlwm > 128)
-				vbs = 64;
-			if (vlwm > (256 - 64))
-				vbs = 32;
-			if (nvclk_freq * 2 > mclk_freq * width)
-				video_fill_us =
-				    vbs * 1000 * 1000 / 16 / nvclk_freq;
-			else
-				video_fill_us =
-				    vbs * 1000 * 1000 / (8 * width) /
-				    mclk_freq;
-			cpm_us =
-			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
-			us_crt =
-			    us_video + video_fill_us + cpm_us + us_m + us_n +
-			    us_p;
-			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
-			clwm++;
-		} else {
-			crtc_drain_rate = pclk_freq * bpp / 8;
-			crtpagemiss = 2;
-			crtpagemiss += 1;
-			cpm_us =
-			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
-			us_crt = cpm_us + us_m + us_n + us_p;
-			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
-			clwm++;
-		}
-		m1 = clwm + cbs - 512;
-		p1 = m1 * pclk_freq / mclk_freq;
-		p1 = p1 * bpp / 8;
-		if ((p1 < m1) && (m1 > 0)) {
-			fifo->valid = 0;
-			found = 0;
-			if (mclk_extra == 0)
-				found = 1;
-			mclk_extra--;
-		} else if (video_enable) {
-			if ((clwm > 511) || (vlwm > 255)) {
-				fifo->valid = 0;
-				found = 0;
-				if (mclk_extra == 0)
-					found = 1;
-				mclk_extra--;
-			}
-		} else {
-			if (clwm > 519) {
-				fifo->valid = 0;
-				found = 0;
-				if (mclk_extra == 0)
-					found = 1;
-				mclk_extra--;
-			}
-		}
-		if (clwm < 384)
-			clwm = 384;
-		if (vlwm < 128)
-			vlwm = 128;
-		data = (int)(clwm);
-		fifo->graphics_lwm = data;
-		fifo->graphics_burst_size = 128;
-		data = (int)((vlwm + 15));
-		fifo->video_lwm = data;
-		fifo->video_burst_size = vbs;
-	}
-}
-
-static void nv4UpdateArbitrationSettings(unsigned VClk,
-					 unsigned pixelDepth,
-					 unsigned *burst,
-					 unsigned *lwm, struct nvidia_par *par)
-{
-	nv4_fifo_info fifo_data;
-	nv4_sim_state sim_data;
-	unsigned int MClk, NVClk, cfg1;
-
-	nvGetClocks(par, &MClk, &NVClk);
-
-	cfg1 = NV_RD32(par->PFB, 0x00000204);
-	sim_data.pix_bpp = (char)pixelDepth;
-	sim_data.enable_video = 0;
-	sim_data.enable_mp = 0;
-	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
-	    128 : 64;
-	sim_data.mem_latency = (char)cfg1 & 0x0F;
-	sim_data.mem_aligned = 1;
-	sim_data.mem_page_miss =
-	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
-	sim_data.gr_during_vid = 0;
-	sim_data.pclk_khz = VClk;
-	sim_data.mclk_khz = MClk;
-	sim_data.nvclk_khz = NVClk;
-	nv4CalcArbitration(&fifo_data, &sim_data);
-	if (fifo_data.valid) {
-		int b = fifo_data.graphics_burst_size >> 4;
-		*burst = 0;
-		while (b >>= 1)
-			(*burst)++;
-		*lwm = fifo_data.graphics_lwm >> 3;
-	}
-}
-
-static void nv10CalcArbitration(nv10_fifo_info * fifo, nv10_sim_state * arb)
-{
-	int data, pagemiss, width, video_enable, bpp;
-	int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
-	int nvclk_fill;
-	int found, mclk_extra, mclk_loop, cbs, m1;
-	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
-	int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
-	int vus_m;
-	int vpm_us, us_video, cpm_us, us_crt, clwm;
-	int clwm_rnd_down;
-	int m2us, us_pipe_min, p1clk, p2;
-	int min_mclk_extra;
-	int us_min_mclk_extra;
-
-	fifo->valid = 1;
-	pclk_freq = arb->pclk_khz;	/* freq in KHz */
-	mclk_freq = arb->mclk_khz;
-	nvclk_freq = arb->nvclk_khz;
-	pagemiss = arb->mem_page_miss;
-	width = arb->memory_width / 64;
-	video_enable = arb->enable_video;
-	bpp = arb->pix_bpp;
-	mp_enable = arb->enable_mp;
-	clwm = 0;
-
-	cbs = 512;
-
-	pclks = 4;	/* lwm detect. */
-
-	nvclks = 3;	/* lwm -> sync. */
-	nvclks += 2;	/* fbi bus cycles (1 req + 1 busy) */
-	/* 2 edge sync.  may be very close to edge so just put one. */
-	mclks = 1;
-	mclks += 1;	/* arb_hp_req */
-	mclks += 5;	/* ap_hp_req   tiling pipeline */
-
-	mclks += 2;	/* tc_req     latency fifo */
-	mclks += 2;	/* fb_cas_n_  memory request to fbio block */
-	mclks += 7;	/* sm_d_rdv   data returned from fbio block */
-
-	/* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
-	if (arb->memory_type == 0)
-		if (arb->memory_width == 64)	/* 64 bit bus */
-			mclks += 4;
-		else
-			mclks += 2;
-	else if (arb->memory_width == 64)	/* 64 bit bus */
-		mclks += 2;
-	else
-		mclks += 1;
-
-	if ((!video_enable) && (arb->memory_width == 128)) {
-		mclk_extra = (bpp == 32) ? 31 : 42;	/* Margin of error */
-		min_mclk_extra = 17;
-	} else {
-		mclk_extra = (bpp == 32) ? 8 : 4;	/* Margin of error */
-		/* mclk_extra = 4; *//* Margin of error */
-		min_mclk_extra = 18;
-	}
-
-	/* 2 edge sync.  may be very close to edge so just put one. */
-	nvclks += 1;
-	nvclks += 1;		/* fbi_d_rdv_n */
-	nvclks += 1;		/* Fbi_d_rdata */
-	nvclks += 1;		/* crtfifo load */
-
-	if (mp_enable)
-		mclks += 4;	/* Mp can get in with a burst of 8. */
-	/* Extra clocks determined by heuristics */
-
-	nvclks += 0;
-	pclks += 0;
-	found = 0;
-	while (found != 1) {
-		fifo->valid = 1;
-		found = 1;
-		mclk_loop = mclks + mclk_extra;
-		/* Mclk latency in us */
-		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
-		/* Minimum Mclk latency in us */
-		us_m_min = mclks * 1000 * 1000 / mclk_freq;
-		us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
-		/* nvclk latency in us */
-		us_n = nvclks * 1000 * 1000 / nvclk_freq;
-		/* nvclk latency in us */
-		us_p = pclks * 1000 * 1000 / pclk_freq;
-		us_pipe_min = us_m_min + us_n + us_p;
-
-		/* Mclk latency in us */
-		vus_m = mclk_loop * 1000 * 1000 / mclk_freq;
-
-		if (video_enable) {
-			crtc_drain_rate = pclk_freq * bpp / 8;	/* MB/s */
-
-			vpagemiss = 1;	/* self generating page miss */
-			vpagemiss += 1;	/* One higher priority before */
-
-			crtpagemiss = 2;	/* self generating page miss */
-			if (mp_enable)
-				crtpagemiss += 1;	/* if MA0 conflict */
-
-			vpm_us =
-			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
-
-			/* Video has separate read return path */
-			us_video = vpm_us + vus_m;
-
-			cpm_us =
-			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
-			/* Wait for video */
-			us_crt = us_video
-			    + cpm_us	/* CRT Page miss */
-			    + us_m + us_n + us_p	/* other latency */
-			    ;
-
-			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
-			/* fixed point <= float_point - 1.  Fixes that */
-			clwm++;
-		} else {
-		    /* bpp * pclk/8 */
-			crtc_drain_rate = pclk_freq * bpp / 8;
-
-			crtpagemiss = 1;	/* self generating page miss */
-			crtpagemiss += 1;	/* MA0 page miss */
-			if (mp_enable)
-				crtpagemiss += 1;	/* if MA0 conflict */
-			cpm_us =
-			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
-			us_crt = cpm_us + us_m + us_n + us_p;
-			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
-			/* fixed point <= float_point - 1.  Fixes that */
-			clwm++;
-
-			/* Finally, a heuristic check when width == 64 bits */
-			if (width == 1) {
-				nvclk_fill = nvclk_freq * 8;
-				if (crtc_drain_rate * 100 >= nvclk_fill * 102)
-					/*Large number to fail */
-					clwm = 0xfff;
-
-				else if (crtc_drain_rate * 100 >=
-					 nvclk_fill * 98) {
-					clwm = 1024;
-					cbs = 512;
-				}
-			}
-		}
-
-		/*
-		   Overfill check:
-		 */
-
-		clwm_rnd_down = ((int)clwm / 8) * 8;
-		if (clwm_rnd_down < clwm)
-			clwm += 8;
-
-		m1 = clwm + cbs - 1024;	/* Amount of overfill */
-		m2us = us_pipe_min + us_min_mclk_extra;
-
-		/* pclk cycles to drain */
-		p1clk = m2us * pclk_freq / (1000 * 1000);
-		p2 = p1clk * bpp / 8;	/* bytes drained. */
-
-		if ((p2 < m1) && (m1 > 0)) {
-			fifo->valid = 0;
-			found = 0;
-			if (min_mclk_extra == 0) {
-				if (cbs <= 32) {
-					/* Can't adjust anymore! */
-					found = 1;
-				} else {
-					/* reduce the burst size */
-					cbs = cbs / 2;
-				}
-			} else {
-				min_mclk_extra--;
-			}
-		} else {
-			if (clwm > 1023) {	/* Have some margin */
-				fifo->valid = 0;
-				found = 0;
-				if (min_mclk_extra == 0)
-					/* Can't adjust anymore! */
-					found = 1;
-				else
-					min_mclk_extra--;
-			}
-		}
-
-		if (clwm < (1024 - cbs + 8))
-			clwm = 1024 - cbs + 8;
-		data = (int)(clwm);
-		/*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n",
-		    clwm, data ); */
-		fifo->graphics_lwm = data;
-		fifo->graphics_burst_size = cbs;
-
-		fifo->video_lwm = 1024;
-		fifo->video_burst_size = 512;
-	}
-}
-
-static void nv10UpdateArbitrationSettings(unsigned VClk,
-					  unsigned pixelDepth,
-					  unsigned *burst,
-					  unsigned *lwm,
-					  struct nvidia_par *par)
-{
-	nv10_fifo_info fifo_data;
-	nv10_sim_state sim_data;
-	unsigned int MClk, NVClk, cfg1;
-
-	nvGetClocks(par, &MClk, &NVClk);
-
-	cfg1 = NV_RD32(par->PFB, 0x0204);
-	sim_data.pix_bpp = (char)pixelDepth;
-	sim_data.enable_video = 1;
-	sim_data.enable_mp = 0;
-	sim_data.memory_type = (NV_RD32(par->PFB, 0x0200) & 0x01) ? 1 : 0;
-	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
-	    128 : 64;
-	sim_data.mem_latency = (char)cfg1 & 0x0F;
-	sim_data.mem_aligned = 1;
-	sim_data.mem_page_miss =
-	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
-	sim_data.gr_during_vid = 0;
-	sim_data.pclk_khz = VClk;
-	sim_data.mclk_khz = MClk;
-	sim_data.nvclk_khz = NVClk;
-	nv10CalcArbitration(&fifo_data, &sim_data);
-	if (fifo_data.valid) {
-		int b = fifo_data.graphics_burst_size >> 4;
-		*burst = 0;
-		while (b >>= 1)
-			(*burst)++;
-		*lwm = fifo_data.graphics_lwm >> 3;
-	}
-}
-
-static void nv30UpdateArbitrationSettings (
-    struct nvidia_par *par,
-    unsigned int      *burst,
-    unsigned int      *lwm
-)
-{
-    unsigned int MClk, NVClk;
-    unsigned int fifo_size, burst_size, graphics_lwm;
-
-    fifo_size = 2048;
-    burst_size = 512;
-    graphics_lwm = fifo_size - burst_size;
-
-    nvGetClocks(par, &MClk, &NVClk);
-
-    *burst = 0;
-    burst_size >>= 5;
-    while(burst_size >>= 1) (*burst)++;
-    *lwm = graphics_lwm >> 3;
-}
-
-static void nForceUpdateArbitrationSettings(unsigned VClk,
-					    unsigned pixelDepth,
-					    unsigned *burst,
-					    unsigned *lwm,
-					    struct nvidia_par *par)
-{
-	nv10_fifo_info fifo_data;
-	nv10_sim_state sim_data;
-	unsigned int M, N, P, pll, MClk, NVClk, memctrl;
-	struct pci_dev *dev;
-
-	if ((par->Chipset & 0x0FF0) == 0x01A0) {
-		unsigned int uMClkPostDiv;
-		dev = pci_get_bus_and_slot(0, 3);
-		pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
-		uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
-
-		if (!uMClkPostDiv)
-			uMClkPostDiv = 4;
-		MClk = 400000 / uMClkPostDiv;
-	} else {
-		dev = pci_get_bus_and_slot(0, 5);
-		pci_read_config_dword(dev, 0x4c, &MClk);
-		MClk /= 1000;
-	}
-	pci_dev_put(dev);
-	pll = NV_RD32(par->PRAMDAC0, 0x0500);
-	M = (pll >> 0) & 0xFF;
-	N = (pll >> 8) & 0xFF;
-	P = (pll >> 16) & 0x0F;
-	NVClk = (N * par->CrystalFreqKHz / M) >> P;
-	sim_data.pix_bpp = (char)pixelDepth;
-	sim_data.enable_video = 0;
-	sim_data.enable_mp = 0;
-	dev = pci_get_bus_and_slot(0, 1);
-	pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
-	pci_dev_put(dev);
-	sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
-	sim_data.memory_width = 64;
-
-	dev = pci_get_bus_and_slot(0, 3);
-	pci_read_config_dword(dev, 0, &memctrl);
-	pci_dev_put(dev);
-	memctrl >>= 16;
-
-	if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
-		u32 dimm[3];
-
-		dev = pci_get_bus_and_slot(0, 2);
-		pci_read_config_dword(dev, 0x40, &dimm[0]);
-		dimm[0] = (dimm[0] >> 8) & 0x4f;
-		pci_read_config_dword(dev, 0x44, &dimm[1]);
-		dimm[1] = (dimm[1] >> 8) & 0x4f;
-		pci_read_config_dword(dev, 0x48, &dimm[2]);
-		dimm[2] = (dimm[2] >> 8) & 0x4f;
-
-		if ((dimm[0] + dimm[1]) != dimm[2]) {
-			printk("nvidiafb: your nForce DIMMs are not arranged "
-			       "in optimal banks!\n");
-		}
-		pci_dev_put(dev);
-	}
-
-	sim_data.mem_latency = 3;
-	sim_data.mem_aligned = 1;
-	sim_data.mem_page_miss = 10;
-	sim_data.gr_during_vid = 0;
-	sim_data.pclk_khz = VClk;
-	sim_data.mclk_khz = MClk;
-	sim_data.nvclk_khz = NVClk;
-	nv10CalcArbitration(&fifo_data, &sim_data);
-	if (fifo_data.valid) {
-		int b = fifo_data.graphics_burst_size >> 4;
-		*burst = 0;
-		while (b >>= 1)
-			(*burst)++;
-		*lwm = fifo_data.graphics_lwm >> 3;
-	}
-}
-
-/****************************************************************************\
-*                                                                            *
-*                          RIVA Mode State Routines                          *
-*                                                                            *
-\****************************************************************************/
-
-/*
- * Calculate the Video Clock parameters for the PLL.
- */
-static void CalcVClock(int clockIn,
-		       int *clockOut, u32 * pllOut, struct nvidia_par *par)
-{
-	unsigned lowM, highM;
-	unsigned DeltaNew, DeltaOld;
-	unsigned VClk, Freq;
-	unsigned M, N, P;
-
-	DeltaOld = 0xFFFFFFFF;
-
-	VClk = (unsigned)clockIn;
-
-	if (par->CrystalFreqKHz == 13500) {
-		lowM = 7;
-		highM = 13;
-	} else {
-		lowM = 8;
-		highM = 14;
-	}
-
-	for (P = 0; P <= 4; P++) {
-		Freq = VClk << P;
-		if ((Freq >= 128000) && (Freq <= 350000)) {
-			for (M = lowM; M <= highM; M++) {
-				N = ((VClk << P) * M) / par->CrystalFreqKHz;
-				if (N <= 255) {
-					Freq =
-					    ((par->CrystalFreqKHz * N) /
-					     M) >> P;
-					if (Freq > VClk)
-						DeltaNew = Freq - VClk;
-					else
-						DeltaNew = VClk - Freq;
-					if (DeltaNew < DeltaOld) {
-						*pllOut =
-						    (P << 16) | (N << 8) | M;
-						*clockOut = Freq;
-						DeltaOld = DeltaNew;
-					}
-				}
-			}
-		}
-	}
-}
-
-static void CalcVClock2Stage(int clockIn,
-			     int *clockOut,
-			     u32 * pllOut,
-			     u32 * pllBOut, struct nvidia_par *par)
-{
-	unsigned DeltaNew, DeltaOld;
-	unsigned VClk, Freq;
-	unsigned M, N, P;
-
-	DeltaOld = 0xFFFFFFFF;
-
-	*pllBOut = 0x80000401;	/* fixed at x4 for now */
-
-	VClk = (unsigned)clockIn;
-
-	for (P = 0; P <= 6; P++) {
-		Freq = VClk << P;
-		if ((Freq >= 400000) && (Freq <= 1000000)) {
-			for (M = 1; M <= 13; M++) {
-				N = ((VClk << P) * M) /
-				    (par->CrystalFreqKHz << 2);
-				if ((N >= 5) && (N <= 255)) {
-					Freq =
-					    (((par->CrystalFreqKHz << 2) * N) /
-					     M) >> P;
-					if (Freq > VClk)
-						DeltaNew = Freq - VClk;
-					else
-						DeltaNew = VClk - Freq;
-					if (DeltaNew < DeltaOld) {
-						*pllOut =
-						    (P << 16) | (N << 8) | M;
-						*clockOut = Freq;
-						DeltaOld = DeltaNew;
-					}
-				}
-			}
-		}
-	}
-}
-
-/*
- * Calculate extended mode parameters (SVGA) and save in a
- * mode state structure.
- */
-void NVCalcStateExt(struct nvidia_par *par,
-		    RIVA_HW_STATE * state,
-		    int bpp,
-		    int width,
-		    int hDisplaySize, int height, int dotClock, int flags)
-{
-	int pixelDepth, VClk = 0;
-	/*
-	 * Save mode parameters.
-	 */
-	state->bpp = bpp;	/* this is not bitsPerPixel, it's 8,15,16,32 */
-	state->width = width;
-	state->height = height;
-	/*
-	 * Extended RIVA registers.
-	 */
-	pixelDepth = (bpp + 1) / 8;
-	if (par->twoStagePLL)
-		CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB,
-				 par);
-	else
-		CalcVClock(dotClock, &VClk, &state->pll, par);
-
-	switch (par->Architecture) {
-	case NV_ARCH_04:
-		nv4UpdateArbitrationSettings(VClk,
-					     pixelDepth * 8,
-					     &(state->arbitration0),
-					     &(state->arbitration1), par);
-		state->cursor0 = 0x00;
-		state->cursor1 = 0xbC;
-		if (flags & FB_VMODE_DOUBLE)
-			state->cursor1 |= 2;
-		state->cursor2 = 0x00000000;
-		state->pllsel = 0x10000700;
-		state->config = 0x00001114;
-		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
-		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
-		break;
-	case NV_ARCH_40:
-		if (!par->FlatPanel)
-			state->control = NV_RD32(par->PRAMDAC0, 0x0580) &
-				0xeffffeff;
-		/* fallthrough */
-	case NV_ARCH_10:
-	case NV_ARCH_20:
-	case NV_ARCH_30:
-	default:
-		if ((par->Chipset & 0xfff0) == 0x0240 ||
-		    (par->Chipset & 0xfff0) == 0x03d0) {
-			state->arbitration0 = 256;
-			state->arbitration1 = 0x0480;
-		} else if (((par->Chipset & 0xffff) == 0x01A0) ||
-		    ((par->Chipset & 0xffff) == 0x01f0)) {
-			nForceUpdateArbitrationSettings(VClk,
-							pixelDepth * 8,
-							&(state->arbitration0),
-							&(state->arbitration1),
-							par);
-		} else if (par->Architecture < NV_ARCH_30) {
-			nv10UpdateArbitrationSettings(VClk,
-						      pixelDepth * 8,
-						      &(state->arbitration0),
-						      &(state->arbitration1),
-						      par);
-		} else {
-			nv30UpdateArbitrationSettings(par,
-						      &(state->arbitration0),
-						      &(state->arbitration1));
-		}
-
-		state->cursor0 = 0x80 | (par->CursorStart >> 17);
-		state->cursor1 = (par->CursorStart >> 11) << 2;
-		state->cursor2 = par->CursorStart >> 24;
-		if (flags & FB_VMODE_DOUBLE)
-			state->cursor1 |= 2;
-		state->pllsel = 0x10000700;
-		state->config = NV_RD32(par->PFB, 0x00000200);
-		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
-		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
-		break;
-	}
-
-	if (bpp != 8)		/* DirectColor */
-		state->general |= 0x00000030;
-
-	state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
-	state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
-}
-
-void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
-{
-	int i, j;
-
-	NV_WR32(par->PMC, 0x0140, 0x00000000);
-	NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
-	NV_WR32(par->PMC, 0x0200, 0xFFFFFFFF);
-
-	NV_WR32(par->PTIMER, 0x0200 * 4, 0x00000008);
-	NV_WR32(par->PTIMER, 0x0210 * 4, 0x00000003);
-	NV_WR32(par->PTIMER, 0x0140 * 4, 0x00000000);
-	NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
-
-	if (par->Architecture == NV_ARCH_04) {
-		if (state)
-			NV_WR32(par->PFB, 0x0200, state->config);
-	} else if ((par->Architecture < NV_ARCH_40) ||
-		   (par->Chipset & 0xfff0) == 0x0040) {
-		for (i = 0; i < 8; i++) {
-			NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
-			NV_WR32(par->PFB, 0x0244 + (i * 0x10),
-				par->FbMapSize - 1);
-		}
-	} else {
-		int regions = 12;
-
-		if (((par->Chipset & 0xfff0) == 0x0090) ||
-		    ((par->Chipset & 0xfff0) == 0x01D0) ||
-		    ((par->Chipset & 0xfff0) == 0x0290) ||
-		    ((par->Chipset & 0xfff0) == 0x0390) ||
-		    ((par->Chipset & 0xfff0) == 0x03D0))
-			regions = 15;
-		for(i = 0; i < regions; i++) {
-			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
-			NV_WR32(par->PFB, 0x0604 + (i * 0x10),
-				par->FbMapSize - 1);
-		}
-	}
-
-	if (par->Architecture >= NV_ARCH_40) {
-		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
-		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x00101202);
-		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
-		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x00101204);
-		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
-		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x00101206);
-		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
-		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x00101208);
-		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
-		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x0010120A);
-		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
-		NV_WR32(par->PRAMIN, 0x000B * 4, 0x0010120C);
-		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
-		NV_WR32(par->PRAMIN, 0x000D * 4, 0x0010120E);
-		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
-		NV_WR32(par->PRAMIN, 0x000F * 4, 0x00101210);
-		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
-		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
-		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
-		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x02080062);
-		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00001200);
-		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00001200);
-		NV_WR32(par->PRAMIN, 0x080C * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x02080043);
-		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0818 * 4, 0x02080044);
-		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x02000000);
-		NV_WR32(par->PRAMIN, 0x081A * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x081C * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x02080019);
-		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0828 * 4, 0x020A005C);
-		NV_WR32(par->PRAMIN, 0x0829 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x082A * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x082B * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x082C * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x082D * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0830 * 4, 0x0208009F);
-		NV_WR32(par->PRAMIN, 0x0831 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0832 * 4, 0x00001200);
-		NV_WR32(par->PRAMIN, 0x0833 * 4, 0x00001200);
-		NV_WR32(par->PRAMIN, 0x0834 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0835 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0838 * 4, 0x0208004A);
-		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x02000000);
-		NV_WR32(par->PRAMIN, 0x083A * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x083B * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x083C * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x083D * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0840 * 4, 0x02080077);
-		NV_WR32(par->PRAMIN, 0x0841 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0842 * 4, 0x00001200);
-		NV_WR32(par->PRAMIN, 0x0843 * 4, 0x00001200);
-		NV_WR32(par->PRAMIN, 0x0844 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0845 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x084C * 4, 0x00003002);
-		NV_WR32(par->PRAMIN, 0x084D * 4, 0x00007FFF);
-		NV_WR32(par->PRAMIN, 0x084E * 4,
-			par->FbUsableSize | 0x00000002);
-
-#ifdef __BIG_ENDIAN
-		NV_WR32(par->PRAMIN, 0x080A * 4,
-			NV_RD32(par->PRAMIN, 0x080A * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x0812 * 4,
-			NV_RD32(par->PRAMIN, 0x0812 * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x081A * 4,
-			NV_RD32(par->PRAMIN, 0x081A * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x0822 * 4,
-			NV_RD32(par->PRAMIN, 0x0822 * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x082A * 4,
-			NV_RD32(par->PRAMIN, 0x082A * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x0832 * 4,
-			NV_RD32(par->PRAMIN, 0x0832 * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x083A * 4,
-			NV_RD32(par->PRAMIN, 0x083A * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x0842 * 4,
-			NV_RD32(par->PRAMIN, 0x0842 * 4) | 0x01000000);
-		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x01000000);
-		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x01000000);
-#endif
-	} else {
-		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
-		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x80011201);
-		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
-		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x80011202);
-		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
-		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x80011203);
-		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
-		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x80011204);
-		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
-		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x80011205);
-		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
-		NV_WR32(par->PRAMIN, 0x000B * 4, 0x80011206);
-		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
-		NV_WR32(par->PRAMIN, 0x000D * 4, 0x80011207);
-		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
-		NV_WR32(par->PRAMIN, 0x000F * 4, 0x80011208);
-		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
-		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
-		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
-		NV_WR32(par->PRAMIN, 0x0803 * 4, 0x00000002);
-		if (par->Architecture >= NV_ARCH_10)
-			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008062);
-		else
-			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008042);
-		NV_WR32(par->PRAMIN, 0x0805 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0806 * 4, 0x12001200);
-		NV_WR32(par->PRAMIN, 0x0807 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x01008043);
-		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x080C * 4, 0x01008044);
-		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000002);
-		NV_WR32(par->PRAMIN, 0x080E * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x080F * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x01008019);
-		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x0100A05C);
-		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0816 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0817 * 4, 0x00000000);
-		if (par->WaitVSyncPossible)
-			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100809F);
-		else
-			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100805F);
-		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x081A * 4, 0x12001200);
-		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x081C * 4, 0x0100804A);
-		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000002);
-		NV_WR32(par->PRAMIN, 0x081E * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x081F * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x01018077);
-		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x12001200);
-		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
-		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00003002);
-		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00007FFF);
-		NV_WR32(par->PRAMIN, 0x0826 * 4,
-			par->FbUsableSize | 0x00000002);
-		NV_WR32(par->PRAMIN, 0x0827 * 4, 0x00000002);
-#ifdef __BIG_ENDIAN
-		NV_WR32(par->PRAMIN, 0x0804 * 4,
-			NV_RD32(par->PRAMIN, 0x0804 * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x0808 * 4,
-			NV_RD32(par->PRAMIN, 0x0808 * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x080C * 4,
-			NV_RD32(par->PRAMIN, 0x080C * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x0810 * 4,
-			NV_RD32(par->PRAMIN, 0x0810 * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x0814 * 4,
-			NV_RD32(par->PRAMIN, 0x0814 * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x0818 * 4,
-			NV_RD32(par->PRAMIN, 0x0818 * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x081C * 4,
-			NV_RD32(par->PRAMIN, 0x081C * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x0820 * 4,
-			NV_RD32(par->PRAMIN, 0x0820 * 4) | 0x00080000);
-		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000001);
-		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000001);
-#endif
-	}
-	if (par->Architecture < NV_ARCH_10) {
-		if ((par->Chipset & 0x0fff) == 0x0020) {
-			NV_WR32(par->PRAMIN, 0x0824 * 4,
-				NV_RD32(par->PRAMIN, 0x0824 * 4) | 0x00020000);
-			NV_WR32(par->PRAMIN, 0x0826 * 4,
-				NV_RD32(par->PRAMIN,
-					0x0826 * 4) + par->FbAddress);
-		}
-		NV_WR32(par->PGRAPH, 0x0080, 0x000001FF);
-		NV_WR32(par->PGRAPH, 0x0080, 0x1230C000);
-		NV_WR32(par->PGRAPH, 0x0084, 0x72111101);
-		NV_WR32(par->PGRAPH, 0x0088, 0x11D5F071);
-		NV_WR32(par->PGRAPH, 0x008C, 0x0004FF31);
-		NV_WR32(par->PGRAPH, 0x008C, 0x4004FF31);
-		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
-		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
-		NV_WR32(par->PGRAPH, 0x0170, 0x10010100);
-		NV_WR32(par->PGRAPH, 0x0710, 0xFFFFFFFF);
-		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
-		NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
-		NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
-	} else {
-		NV_WR32(par->PGRAPH, 0x0080, 0xFFFFFFFF);
-		NV_WR32(par->PGRAPH, 0x0080, 0x00000000);
-
-		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
-		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
-		NV_WR32(par->PGRAPH, 0x0144, 0x10010100);
-		NV_WR32(par->PGRAPH, 0x0714, 0xFFFFFFFF);
-		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
-		NV_WR32(par->PGRAPH, 0x0710,
-			NV_RD32(par->PGRAPH, 0x0710) & 0x0007ff00);
-		NV_WR32(par->PGRAPH, 0x0710,
-			NV_RD32(par->PGRAPH, 0x0710) | 0x00020100);
-
-		if (par->Architecture == NV_ARCH_10) {
-			NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
-			NV_WR32(par->PGRAPH, 0x0088, 0x24E00810);
-			NV_WR32(par->PGRAPH, 0x008C, 0x55DE0030);
-
-			for (i = 0; i < 32; i++)
-				NV_WR32(&par->PGRAPH[(0x0B00 / 4) + i], 0,
-					NV_RD32(&par->PFB[(0x0240 / 4) + i],
-						0));
-
-			NV_WR32(par->PGRAPH, 0x640, 0);
-			NV_WR32(par->PGRAPH, 0x644, 0);
-			NV_WR32(par->PGRAPH, 0x684, par->FbMapSize - 1);
-			NV_WR32(par->PGRAPH, 0x688, par->FbMapSize - 1);
-
-			NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
-			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
-		} else {
-			if (par->Architecture >= NV_ARCH_40) {
-				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
-				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
-				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
-				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
-				NV_WR32(par->PGRAPH, 0x0bc4,
-					NV_RD32(par->PGRAPH, 0x0bc4) |
-					0x00008000);
-
-				j = NV_RD32(par->REGS, 0x1540) & 0xff;
-
-				if (j) {
-					for (i = 0; !(j & 1); j >>= 1, i++);
-					NV_WR32(par->PGRAPH, 0x5000, i);
-				}
-
-				if ((par->Chipset & 0xfff0) == 0x0040) {
-					NV_WR32(par->PGRAPH, 0x09b0,
-						0x83280fff);
-					NV_WR32(par->PGRAPH, 0x09b4,
-						0x000000a0);
-				} else {
-					NV_WR32(par->PGRAPH, 0x0820,
-						0x83280eff);
-					NV_WR32(par->PGRAPH, 0x0824,
-						0x000000a0);
-				}
-
-				switch (par->Chipset & 0xfff0) {
-				case 0x0040:
-				case 0x0210:
-					NV_WR32(par->PGRAPH, 0x09b8,
-						0x0078e366);
-					NV_WR32(par->PGRAPH, 0x09bc,
-						0x0000014c);
-					NV_WR32(par->PFB, 0x033C,
-						NV_RD32(par->PFB, 0x33C) &
-						0xffff7fff);
-					break;
-				case 0x00C0:
-				case 0x0120:
-					NV_WR32(par->PGRAPH, 0x0828,
-						0x007596ff);
-					NV_WR32(par->PGRAPH, 0x082C,
-						0x00000108);
-					break;
-				case 0x0160:
-				case 0x01D0:
-				case 0x0240:
-				case 0x03D0:
-					NV_WR32(par->PMC, 0x1700,
-						NV_RD32(par->PFB, 0x020C));
-					NV_WR32(par->PMC, 0x1704, 0);
-					NV_WR32(par->PMC, 0x1708, 0);
-					NV_WR32(par->PMC, 0x170C,
-						NV_RD32(par->PFB, 0x020C));
-					NV_WR32(par->PGRAPH, 0x0860, 0);
-					NV_WR32(par->PGRAPH, 0x0864, 0);
-					NV_WR32(par->PRAMDAC, 0x0608,
-						NV_RD32(par->PRAMDAC,
-							0x0608) | 0x00100000);
-					break;
-				case 0x0140:
-					NV_WR32(par->PGRAPH, 0x0828,
-						0x0072cb77);
-					NV_WR32(par->PGRAPH, 0x082C,
-						0x00000108);
-					break;
-				case 0x0220:
-					NV_WR32(par->PGRAPH, 0x0860, 0);
-					NV_WR32(par->PGRAPH, 0x0864, 0);
-					NV_WR32(par->PRAMDAC, 0x0608,
-						NV_RD32(par->PRAMDAC, 0x0608) |
-						0x00100000);
-					break;
-				case 0x0090:
-				case 0x0290:
-				case 0x0390:
-					NV_WR32(par->PRAMDAC, 0x0608,
-						NV_RD32(par->PRAMDAC, 0x0608) |
-						0x00100000);
-					NV_WR32(par->PGRAPH, 0x0828,
-						0x07830610);
-					NV_WR32(par->PGRAPH, 0x082C,
-						0x0000016A);
-					break;
-				default:
-					break;
-				}
-
-				NV_WR32(par->PGRAPH, 0x0b38, 0x2ffff800);
-				NV_WR32(par->PGRAPH, 0x0b3c, 0x00006000);
-				NV_WR32(par->PGRAPH, 0x032C, 0x01000000);
-				NV_WR32(par->PGRAPH, 0x0220, 0x00001200);
-			} else if (par->Architecture == NV_ARCH_30) {
-				NV_WR32(par->PGRAPH, 0x0084, 0x40108700);
-				NV_WR32(par->PGRAPH, 0x0890, 0x00140000);
-				NV_WR32(par->PGRAPH, 0x008C, 0xf00e0431);
-				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
-				NV_WR32(par->PGRAPH, 0x0610, 0xf04b1f36);
-				NV_WR32(par->PGRAPH, 0x0B80, 0x1002d888);
-				NV_WR32(par->PGRAPH, 0x0B88, 0x62ff007f);
-			} else {
-				NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
-				NV_WR32(par->PGRAPH, 0x008C, 0xF20E0431);
-				NV_WR32(par->PGRAPH, 0x0090, 0x00000000);
-				NV_WR32(par->PGRAPH, 0x009C, 0x00000040);
-
-				if ((par->Chipset & 0x0ff0) >= 0x0250) {
-					NV_WR32(par->PGRAPH, 0x0890,
-						0x00080000);
-					NV_WR32(par->PGRAPH, 0x0610,
-						0x304B1FB6);
-					NV_WR32(par->PGRAPH, 0x0B80,
-						0x18B82880);
-					NV_WR32(par->PGRAPH, 0x0B84,
-						0x44000000);
-					NV_WR32(par->PGRAPH, 0x0098,
-						0x40000080);
-					NV_WR32(par->PGRAPH, 0x0B88,
-						0x000000ff);
-				} else {
-					NV_WR32(par->PGRAPH, 0x0880,
-						0x00080000);
-					NV_WR32(par->PGRAPH, 0x0094,
-						0x00000005);
-					NV_WR32(par->PGRAPH, 0x0B80,
-						0x45CAA208);
-					NV_WR32(par->PGRAPH, 0x0B84,
-						0x24000000);
-					NV_WR32(par->PGRAPH, 0x0098,
-						0x00000040);
-					NV_WR32(par->PGRAPH, 0x0750,
-						0x00E00038);
-					NV_WR32(par->PGRAPH, 0x0754,
-						0x00000030);
-					NV_WR32(par->PGRAPH, 0x0750,
-						0x00E10038);
-					NV_WR32(par->PGRAPH, 0x0754,
-						0x00000030);
-				}
-			}
-
-			if ((par->Architecture < NV_ARCH_40) ||
-			    ((par->Chipset & 0xfff0) == 0x0040)) {
-				for (i = 0; i < 32; i++) {
-					NV_WR32(par->PGRAPH, 0x0900 + i*4,
-						NV_RD32(par->PFB, 0x0240 +i*4));
-					NV_WR32(par->PGRAPH, 0x6900 + i*4,
-						NV_RD32(par->PFB, 0x0240 +i*4));
-				}
-			} else {
-				if (((par->Chipset & 0xfff0) == 0x0090) ||
-				    ((par->Chipset & 0xfff0) == 0x01D0) ||
-				    ((par->Chipset & 0xfff0) == 0x0290) ||
-				    ((par->Chipset & 0xfff0) == 0x0390) ||
-				    ((par->Chipset & 0xfff0) == 0x03D0)) {
-					for (i = 0; i < 60; i++) {
-						NV_WR32(par->PGRAPH,
-							0x0D00 + i*4,
-							NV_RD32(par->PFB,
-								0x0600 + i*4));
-						NV_WR32(par->PGRAPH,
-							0x6900 + i*4,
-							NV_RD32(par->PFB,
-								0x0600 + i*4));
-					}
-				} else {
-					for (i = 0; i < 48; i++) {
-						NV_WR32(par->PGRAPH,
-							0x0900 + i*4,
-							NV_RD32(par->PFB,
-								0x0600 + i*4));
-						if(((par->Chipset & 0xfff0)
-						    != 0x0160) &&
-						   ((par->Chipset & 0xfff0)
-						    != 0x0220) &&
-						   ((par->Chipset & 0xfff0)
-						    != 0x240))
-							NV_WR32(par->PGRAPH,
-								0x6900 + i*4,
-								NV_RD32(par->PFB,
-									0x0600 + i*4));
-					}
-				}
-			}
-
-			if (par->Architecture >= NV_ARCH_40) {
-				if ((par->Chipset & 0xfff0) == 0x0040) {
-					NV_WR32(par->PGRAPH, 0x09A4,
-						NV_RD32(par->PFB, 0x0200));
-					NV_WR32(par->PGRAPH, 0x09A8,
-						NV_RD32(par->PFB, 0x0204));
-					NV_WR32(par->PGRAPH, 0x69A4,
-						NV_RD32(par->PFB, 0x0200));
-					NV_WR32(par->PGRAPH, 0x69A8,
-						NV_RD32(par->PFB, 0x0204));
-
-					NV_WR32(par->PGRAPH, 0x0820, 0);
-					NV_WR32(par->PGRAPH, 0x0824, 0);
-					NV_WR32(par->PGRAPH, 0x0864,
-						par->FbMapSize - 1);
-					NV_WR32(par->PGRAPH, 0x0868,
-						par->FbMapSize - 1);
-				} else {
-					if ((par->Chipset & 0xfff0) == 0x0090 ||
-					    (par->Chipset & 0xfff0) == 0x01D0 ||
-					    (par->Chipset & 0xfff0) == 0x0290 ||
-					    (par->Chipset & 0xfff0) == 0x0390) {
-						NV_WR32(par->PGRAPH, 0x0DF0,
-							NV_RD32(par->PFB, 0x0200));
-						NV_WR32(par->PGRAPH, 0x0DF4,
-							NV_RD32(par->PFB, 0x0204));
-					} else {
-						NV_WR32(par->PGRAPH, 0x09F0,
-							NV_RD32(par->PFB, 0x0200));
-						NV_WR32(par->PGRAPH, 0x09F4,
-							NV_RD32(par->PFB, 0x0204));
-					}
-					NV_WR32(par->PGRAPH, 0x69F0,
-						NV_RD32(par->PFB, 0x0200));
-					NV_WR32(par->PGRAPH, 0x69F4,
-						NV_RD32(par->PFB, 0x0204));
-
-					NV_WR32(par->PGRAPH, 0x0840, 0);
-					NV_WR32(par->PGRAPH, 0x0844, 0);
-					NV_WR32(par->PGRAPH, 0x08a0,
-						par->FbMapSize - 1);
-					NV_WR32(par->PGRAPH, 0x08a4,
-						par->FbMapSize - 1);
-				}
-			} else {
-				NV_WR32(par->PGRAPH, 0x09A4,
-					NV_RD32(par->PFB, 0x0200));
-				NV_WR32(par->PGRAPH, 0x09A8,
-					NV_RD32(par->PFB, 0x0204));
-				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0000);
-				NV_WR32(par->PGRAPH, 0x0754,
-					NV_RD32(par->PFB, 0x0200));
-				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0004);
-				NV_WR32(par->PGRAPH, 0x0754,
-					NV_RD32(par->PFB, 0x0204));
-
-				NV_WR32(par->PGRAPH, 0x0820, 0);
-				NV_WR32(par->PGRAPH, 0x0824, 0);
-				NV_WR32(par->PGRAPH, 0x0864,
-					par->FbMapSize - 1);
-				NV_WR32(par->PGRAPH, 0x0868,
-					par->FbMapSize - 1);
-			}
-			NV_WR32(par->PGRAPH, 0x0B20, 0x00000000);
-			NV_WR32(par->PGRAPH, 0x0B04, 0xFFFFFFFF);
-		}
-	}
-	NV_WR32(par->PGRAPH, 0x053C, 0);
-	NV_WR32(par->PGRAPH, 0x0540, 0);
-	NV_WR32(par->PGRAPH, 0x0544, 0x00007FFF);
-	NV_WR32(par->PGRAPH, 0x0548, 0x00007FFF);
-
-	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000000);
-	NV_WR32(par->PFIFO, 0x0141 * 4, 0x00000001);
-	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000000);
-	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000000);
-	if (par->Architecture >= NV_ARCH_40)
-		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00010000);
-	else
-		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00000100);
-	NV_WR32(par->PFIFO, 0x0490 * 4, 0x00000000);
-	NV_WR32(par->PFIFO, 0x0491 * 4, 0x00000000);
-	if (par->Architecture >= NV_ARCH_40)
-		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001213);
-	else
-		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001209);
-	NV_WR32(par->PFIFO, 0x0400 * 4, 0x00000000);
-	NV_WR32(par->PFIFO, 0x0414 * 4, 0x00000000);
-	NV_WR32(par->PFIFO, 0x0084 * 4, 0x03000100);
-	NV_WR32(par->PFIFO, 0x0085 * 4, 0x00000110);
-	NV_WR32(par->PFIFO, 0x0086 * 4, 0x00000112);
-	NV_WR32(par->PFIFO, 0x0143 * 4, 0x0000FFFF);
-	NV_WR32(par->PFIFO, 0x0496 * 4, 0x0000FFFF);
-	NV_WR32(par->PFIFO, 0x0050 * 4, 0x00000000);
-	NV_WR32(par->PFIFO, 0x0040 * 4, 0xFFFFFFFF);
-	NV_WR32(par->PFIFO, 0x0415 * 4, 0x00000001);
-	NV_WR32(par->PFIFO, 0x048C * 4, 0x00000000);
-	NV_WR32(par->PFIFO, 0x04A0 * 4, 0x00000000);
-#ifdef __BIG_ENDIAN
-	NV_WR32(par->PFIFO, 0x0489 * 4, 0x800F0078);
-#else
-	NV_WR32(par->PFIFO, 0x0489 * 4, 0x000F0078);
-#endif
-	NV_WR32(par->PFIFO, 0x0488 * 4, 0x00000001);
-	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000001);
-	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
-	NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
-	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
-
-    if (!state) {
-	    par->CurrentState = NULL;
-	    return;
-    }
-
-	if (par->Architecture >= NV_ARCH_10) {
-		if (par->twoHeads) {
-			NV_WR32(par->PCRTC0, 0x0860, state->head);
-			NV_WR32(par->PCRTC0, 0x2860, state->head2);
-		}
-		NV_WR32(par->PRAMDAC, 0x0404, NV_RD32(par->PRAMDAC, 0x0404) |
-			(1 << 25));
-
-		NV_WR32(par->PMC, 0x8704, 1);
-		NV_WR32(par->PMC, 0x8140, 0);
-		NV_WR32(par->PMC, 0x8920, 0);
-		NV_WR32(par->PMC, 0x8924, 0);
-		NV_WR32(par->PMC, 0x8908, par->FbMapSize - 1);
-		NV_WR32(par->PMC, 0x890C, par->FbMapSize - 1);
-		NV_WR32(par->PMC, 0x1588, 0);
-
-		NV_WR32(par->PCRTC, 0x0810, state->cursorConfig);
-		NV_WR32(par->PCRTC, 0x0830, state->displayV - 3);
-		NV_WR32(par->PCRTC, 0x0834, state->displayV - 1);
-
-		if (par->FlatPanel) {
-			if ((par->Chipset & 0x0ff0) == 0x0110) {
-				NV_WR32(par->PRAMDAC, 0x0528, state->dither);
-			} else if (par->twoHeads) {
-				NV_WR32(par->PRAMDAC, 0x083C, state->dither);
-			}
-
-			VGA_WR08(par->PCIO, 0x03D4, 0x53);
-			VGA_WR08(par->PCIO, 0x03D5, state->timingH);
-			VGA_WR08(par->PCIO, 0x03D4, 0x54);
-			VGA_WR08(par->PCIO, 0x03D5, state->timingV);
-			VGA_WR08(par->PCIO, 0x03D4, 0x21);
-			VGA_WR08(par->PCIO, 0x03D5, 0xfa);
-		}
-
-		VGA_WR08(par->PCIO, 0x03D4, 0x41);
-		VGA_WR08(par->PCIO, 0x03D5, state->extra);
-	}
-
-	VGA_WR08(par->PCIO, 0x03D4, 0x19);
-	VGA_WR08(par->PCIO, 0x03D5, state->repaint0);
-	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
-	VGA_WR08(par->PCIO, 0x03D5, state->repaint1);
-	VGA_WR08(par->PCIO, 0x03D4, 0x25);
-	VGA_WR08(par->PCIO, 0x03D5, state->screen);
-	VGA_WR08(par->PCIO, 0x03D4, 0x28);
-	VGA_WR08(par->PCIO, 0x03D5, state->pixel);
-	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
-	VGA_WR08(par->PCIO, 0x03D5, state->horiz);
-	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
-	VGA_WR08(par->PCIO, 0x03D5, state->fifo);
-	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
-	VGA_WR08(par->PCIO, 0x03D5, state->arbitration0);
-	VGA_WR08(par->PCIO, 0x03D4, 0x20);
-	VGA_WR08(par->PCIO, 0x03D5, state->arbitration1);
-
-	if(par->Architecture >= NV_ARCH_30) {
-		VGA_WR08(par->PCIO, 0x03D4, 0x47);
-		VGA_WR08(par->PCIO, 0x03D5, state->arbitration1 >> 8);
-	}
-
-	VGA_WR08(par->PCIO, 0x03D4, 0x30);
-	VGA_WR08(par->PCIO, 0x03D5, state->cursor0);
-	VGA_WR08(par->PCIO, 0x03D4, 0x31);
-	VGA_WR08(par->PCIO, 0x03D5, state->cursor1);
-	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
-	VGA_WR08(par->PCIO, 0x03D5, state->cursor2);
-	VGA_WR08(par->PCIO, 0x03D4, 0x39);
-	VGA_WR08(par->PCIO, 0x03D5, state->interlace);
-
-	if (!par->FlatPanel) {
-		if (par->Architecture >= NV_ARCH_40)
-			NV_WR32(par->PRAMDAC0, 0x0580, state->control);
-
-		NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
-		NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
-		if (par->twoHeads)
-			NV_WR32(par->PRAMDAC0, 0x0520, state->vpll2);
-		if (par->twoStagePLL) {
-			NV_WR32(par->PRAMDAC0, 0x0578, state->vpllB);
-			NV_WR32(par->PRAMDAC0, 0x057C, state->vpll2B);
-		}
-	} else {
-		NV_WR32(par->PRAMDAC, 0x0848, state->scale);
-		NV_WR32(par->PRAMDAC, 0x0828, state->crtcSync +
-			par->PanelTweak);
-	}
-
-	NV_WR32(par->PRAMDAC, 0x0600, state->general);
-
-	NV_WR32(par->PCRTC, 0x0140, 0);
-	NV_WR32(par->PCRTC, 0x0100, 1);
-
-	par->CurrentState = state;
-}
-
-void NVUnloadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) {
-	VGA_WR08(par->PCIO, 0x03D4, 0x19);
-	state->repaint0 = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
-	state->repaint1 = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x25);
-	state->screen = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x28);
-	state->pixel = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
-	state->horiz = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
-	state->fifo         = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
-	state->arbitration0 = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x20);
-	state->arbitration1 = VGA_RD08(par->PCIO, 0x03D5);
-
-	if(par->Architecture >= NV_ARCH_30) {
-		VGA_WR08(par->PCIO, 0x03D4, 0x47);
-		state->arbitration1 |= (VGA_RD08(par->PCIO, 0x03D5) & 1) << 8;
-	}
-
-	VGA_WR08(par->PCIO, 0x03D4, 0x30);
-	state->cursor0 = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x31);
-	state->cursor1 = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
-	state->cursor2 = VGA_RD08(par->PCIO, 0x03D5);
-	VGA_WR08(par->PCIO, 0x03D4, 0x39);
-	state->interlace = VGA_RD08(par->PCIO, 0x03D5);
-	state->vpll = NV_RD32(par->PRAMDAC0, 0x0508);
-	if (par->twoHeads)
-		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
-	if (par->twoStagePLL) {
-		state->vpllB = NV_RD32(par->PRAMDAC0, 0x0578);
-		state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
-	}
-	state->pllsel = NV_RD32(par->PRAMDAC0, 0x050C);
-	state->general = NV_RD32(par->PRAMDAC, 0x0600);
-	state->scale = NV_RD32(par->PRAMDAC, 0x0848);
-	state->config = NV_RD32(par->PFB, 0x0200);
-
-	if (par->Architecture >= NV_ARCH_40 && !par->FlatPanel)
-		state->control  = NV_RD32(par->PRAMDAC0, 0x0580);
-
-	if (par->Architecture >= NV_ARCH_10) {
-		if (par->twoHeads) {
-			state->head = NV_RD32(par->PCRTC0, 0x0860);
-			state->head2 = NV_RD32(par->PCRTC0, 0x2860);
-			VGA_WR08(par->PCIO, 0x03D4, 0x44);
-			state->crtcOwner = VGA_RD08(par->PCIO, 0x03D5);
-		}
-		VGA_WR08(par->PCIO, 0x03D4, 0x41);
-		state->extra = VGA_RD08(par->PCIO, 0x03D5);
-		state->cursorConfig = NV_RD32(par->PCRTC, 0x0810);
-
-		if ((par->Chipset & 0x0ff0) == 0x0110) {
-			state->dither = NV_RD32(par->PRAMDAC, 0x0528);
-		} else if (par->twoHeads) {
-			state->dither = NV_RD32(par->PRAMDAC, 0x083C);
-		}
-
-		if (par->FlatPanel) {
-			VGA_WR08(par->PCIO, 0x03D4, 0x53);
-			state->timingH = VGA_RD08(par->PCIO, 0x03D5);
-			VGA_WR08(par->PCIO, 0x03D4, 0x54);
-			state->timingV = VGA_RD08(par->PCIO, 0x03D5);
-		}
-	}
-}
-
-void NVSetStartAddress(struct nvidia_par *par, u32 start)
-{
-	NV_WR32(par->PCRTC, 0x800, start);
-}
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
deleted file mode 100644
index d7994a173245..000000000000
--- a/drivers/video/nvidia/nv_i2c.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c
- *
- * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
- *
- * Based on rivafb-i2c.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <linux/pci.h>
-#include <linux/fb.h>
-
-#include <asm/io.h>
-
-#include "nv_type.h"
-#include "nv_local.h"
-#include "nv_proto.h"
-
-#include "../edid.h"
-
-static void nvidia_gpio_setscl(void *data, int state)
-{
-	struct nvidia_i2c_chan *chan = data;
-	struct nvidia_par *par = chan->par;
-	u32 val;
-
-	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
-
-	if (state)
-		val |= 0x20;
-	else
-		val &= ~0x20;
-
-	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
-}
-
-static void nvidia_gpio_setsda(void *data, int state)
-{
-	struct nvidia_i2c_chan *chan = data;
-	struct nvidia_par *par = chan->par;
-	u32 val;
-
-	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
-
-	if (state)
-		val |= 0x10;
-	else
-		val &= ~0x10;
-
-	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
-}
-
-static int nvidia_gpio_getscl(void *data)
-{
-	struct nvidia_i2c_chan *chan = data;
-	struct nvidia_par *par = chan->par;
-	u32 val = 0;
-
-	if (NVReadCrtc(par, chan->ddc_base) & 0x04)
-		val = 1;
-
-	return val;
-}
-
-static int nvidia_gpio_getsda(void *data)
-{
-	struct nvidia_i2c_chan *chan = data;
-	struct nvidia_par *par = chan->par;
-	u32 val = 0;
-
-	if (NVReadCrtc(par, chan->ddc_base) & 0x08)
-		val = 1;
-
-	return val;
-}
-
-static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,
-				unsigned int i2c_class)
-{
-	int rc;
-
-	strcpy(chan->adapter.name, name);
-	chan->adapter.owner = THIS_MODULE;
-	chan->adapter.class = i2c_class;
-	chan->adapter.algo_data = &chan->algo;
-	chan->adapter.dev.parent = &chan->par->pci_dev->dev;
-	chan->algo.setsda = nvidia_gpio_setsda;
-	chan->algo.setscl = nvidia_gpio_setscl;
-	chan->algo.getsda = nvidia_gpio_getsda;
-	chan->algo.getscl = nvidia_gpio_getscl;
-	chan->algo.udelay = 40;
-	chan->algo.timeout = msecs_to_jiffies(2);
-	chan->algo.data = chan;
-
-	i2c_set_adapdata(&chan->adapter, chan);
-
-	/* Raise SCL and SDA */
-	nvidia_gpio_setsda(chan, 1);
-	nvidia_gpio_setscl(chan, 1);
-	udelay(20);
-
-	rc = i2c_bit_add_bus(&chan->adapter);
-	if (rc == 0)
-		dev_dbg(&chan->par->pci_dev->dev,
-			"I2C bus %s registered.\n", name);
-	else {
-		dev_warn(&chan->par->pci_dev->dev,
-			 "Failed to register I2C bus %s.\n", name);
-		chan->par = NULL;
-	}
-
-	return rc;
-}
-
-void nvidia_create_i2c_busses(struct nvidia_par *par)
-{
-	par->chan[0].par = par;
-	par->chan[1].par = par;
-	par->chan[2].par = par;
-
-	par->chan[0].ddc_base = (par->reverse_i2c) ? 0x36 : 0x3e;
- 	nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0",
-			     (par->reverse_i2c) ? I2C_CLASS_HWMON : 0);
-
-	par->chan[1].ddc_base = (par->reverse_i2c) ? 0x3e : 0x36;
- 	nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1",
-			     (par->reverse_i2c) ? 0 : I2C_CLASS_HWMON);
-
-	par->chan[2].ddc_base = 0x50;
- 	nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0);
-}
-
-void nvidia_delete_i2c_busses(struct nvidia_par *par)
-{
-	int i;
-
-	for (i = 0; i < 3; i++) {
-		if (!par->chan[i].par)
-			continue;
-		i2c_del_adapter(&par->chan[i].adapter);
-		par->chan[i].par = NULL;
-	}
-}
-
-int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
-{
-	struct nvidia_par *par = info->par;
-	u8 *edid = NULL;
-
-	if (par->chan[conn - 1].par)
-		edid = fb_ddc_read(&par->chan[conn - 1].adapter);
-
-	if (!edid && conn == 1) {
-		/* try to get from firmware */
-		const u8 *e = fb_firmware_edid(info->device);
-
-		if (e != NULL)
-			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
-	}
-
-	*out_edid = edid;
-
-	return (edid) ? 0 : 1;
-}
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
deleted file mode 100644
index 68e508daa417..000000000000
--- a/drivers/video/nvidia/nv_local.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/***************************************************************************\
-|*                                                                           *|
-|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
- * XFree86 'nv' driver, this source code is provided under MIT-style licensing
- * where the source code is provided "as is" without warranty of any kind.
- * The only usage restriction is for the copyright notices to be retained
- * whenever code is used.
- *
- * Antonino Daplas <adaplas@pol.net> 2005-03-11
- */
-
-#ifndef __NV_LOCAL_H__
-#define __NV_LOCAL_H__
-
-/*
- * This file includes any environment or machine specific values to access the
- * HW.  Put all affected includes, typdefs, etc. here so the riva_hw.* files
- * can stay generic in nature.
- */
-
-/*
- * HW access macros.  These assume memory-mapped I/O, and not normal I/O space.
- */
-#define NV_WR08(p,i,d)  (__raw_writeb((d), (void __iomem *)(p) + (i)))
-#define NV_RD08(p,i)    (__raw_readb((void __iomem *)(p) + (i)))
-#define NV_WR16(p,i,d)  (__raw_writew((d), (void __iomem *)(p) + (i)))
-#define NV_RD16(p,i)    (__raw_readw((void __iomem *)(p) + (i)))
-#define NV_WR32(p,i,d)  (__raw_writel((d), (void __iomem *)(p) + (i)))
-#define NV_RD32(p,i)    (__raw_readl((void __iomem *)(p) + (i)))
-
-/* VGA I/O is now always done through MMIO */
-#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
-#define VGA_RD08(p,i)   (readb((void __iomem *)(p) + (i)))
-
-#define NVDmaNext(par, data) \
-     NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data))
-
-#define NVDmaStart(info, par, tag, size) {    \
-     if((par)->dmaFree <= (size))             \
-        NVDmaWait(info, size);                \
-     NVDmaNext(par, ((size) << 18) | (tag));  \
-     (par)->dmaFree -= ((size) + 1);          \
-}
-
-#if defined(__i386__)
-#define _NV_FENCE() outb(0, 0x3D0);
-#else
-#define _NV_FENCE() mb();
-#endif
-
-#define WRITE_PUT(par, data) {                   \
-  _NV_FENCE()                                    \
-  NV_RD08((par)->FbStart, 0);                    \
-  NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \
-  mb();                                          \
-}
-
-#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
-
-#ifdef __LITTLE_ENDIAN
-
-#include <linux/bitrev.h>
-
-#define reverse_order(l)        \
-do {                            \
-	u8 *a = (u8 *)(l);      \
-	a[0] = bitrev8(a[0]);   \
-	a[1] = bitrev8(a[1]);   \
-	a[2] = bitrev8(a[2]);   \
-	a[3] = bitrev8(a[3]);   \
-} while(0)
-#else
-#define reverse_order(l) do { } while(0)
-#endif                          /* __LITTLE_ENDIAN */
-
-#endif				/* __NV_LOCAL_H__ */
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
deleted file mode 100644
index 3bc13df4b120..000000000000
--- a/drivers/video/nvidia/nv_of.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * linux/drivers/video/nvidia/nv_of.c
- *
- * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
- *
- * Based on rivafb-i2c.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <linux/pci.h>
-#include <linux/fb.h>
-
-#include <asm/io.h>
-
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#include "nv_type.h"
-#include "nv_local.h"
-#include "nv_proto.h"
-
-#include "../edid.h"
-
-int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
-{
-	struct nvidia_par *par = info->par;
-	struct device_node *parent, *dp;
-	const unsigned char *pedid = NULL;
-	static char *propnames[] = {
-		"DFP,EDID", "LCD,EDID", "EDID", "EDID1",
-		"EDID,B", "EDID,A", NULL };
-	int i;
-
-	parent = pci_device_to_OF_node(par->pci_dev);
-	if (parent == NULL)
-		return -1;
-	if (par->twoHeads) {
-		const char *pname;
-		int len;
-
-		for (dp = NULL;
-		     (dp = of_get_next_child(parent, dp)) != NULL;) {
-			pname = of_get_property(dp, "name", NULL);
-			if (!pname)
-				continue;
-			len = strlen(pname);
-			if ((pname[len-1] == 'A' && conn == 1) ||
-			    (pname[len-1] == 'B' && conn == 2)) {
-				for (i = 0; propnames[i] != NULL; ++i) {
-					pedid = of_get_property(dp,
-							propnames[i], NULL);
-					if (pedid != NULL)
-						break;
-				}
-				of_node_put(dp);
-				break;
-			}
-		}
-	}
-	if (pedid == NULL) {
-		for (i = 0; propnames[i] != NULL; ++i) {
-			pedid = of_get_property(parent, propnames[i], NULL);
-			if (pedid != NULL)
-				break;
-		}
-	}
-	if (pedid) {
-		*out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
-		if (*out_edid == NULL)
-			return -1;
-		printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
-		return 0;
-	}
-	return -1;
-}
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
deleted file mode 100644
index ff5c410355ea..000000000000
--- a/drivers/video/nvidia/nv_proto.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_proto.h,v 1.10 2003/07/31 20:24:29 mvojkovi Exp $ */
-
-#ifndef __NV_PROTO_H__
-#define __NV_PROTO_H__
-
-/* in nv_setup.c */
-int NVCommonSetup(struct fb_info *info);
-void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value);
-u8 NVReadCrtc(struct nvidia_par *par, u8 index);
-void NVWriteGr(struct nvidia_par *par, u8 index, u8 value);
-u8 NVReadGr(struct nvidia_par *par, u8 index);
-void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value);
-u8 NVReadSeq(struct nvidia_par *par, u8 index);
-void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value);
-u8 NVReadAttr(struct nvidia_par *par, u8 index);
-void NVWriteMiscOut(struct nvidia_par *par, u8 value);
-u8 NVReadMiscOut(struct nvidia_par *par);
-void NVWriteDacMask(struct nvidia_par *par, u8 value);
-void NVWriteDacReadAddr(struct nvidia_par *par, u8 value);
-void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value);
-void NVWriteDacData(struct nvidia_par *par, u8 value);
-u8 NVReadDacData(struct nvidia_par *par);
-
-/* in nv_hw.c */
-void NVCalcStateExt(struct nvidia_par *par, struct _riva_hw_state *,
-		    int, int, int, int, int, int);
-void NVLoadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
-void NVUnloadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
-void NVSetStartAddress(struct nvidia_par *par, u32);
-int NVShowHideCursor(struct nvidia_par *par, int);
-void NVLockUnlock(struct nvidia_par *par, int);
-
-/* in nvidia-i2c.c */
-#ifdef CONFIG_FB_NVIDIA_I2C
-void nvidia_create_i2c_busses(struct nvidia_par *par);
-void nvidia_delete_i2c_busses(struct nvidia_par *par);
-int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
-			       u8 ** out_edid);
-#else
-#define nvidia_create_i2c_busses(...)
-#define nvidia_delete_i2c_busses(...)
-#define nvidia_probe_i2c_connector(p, c, edid) (-1)
-#endif
-
-#ifdef CONFIG_PPC_OF
-int nvidia_probe_of_connector(struct fb_info *info, int conn,
-			      u8 ** out_edid);
-#else
-static inline int nvidia_probe_of_connector(struct fb_info *info, int conn,
-				      u8 ** out_edid)
-{
-	return -1;
-}
-#endif
-
-/* in nv_accel.c */
-extern void NVResetGraphics(struct fb_info *info);
-extern void nvidiafb_copyarea(struct fb_info *info,
-			      const struct fb_copyarea *region);
-extern void nvidiafb_fillrect(struct fb_info *info,
-			      const struct fb_fillrect *rect);
-extern void nvidiafb_imageblit(struct fb_info *info,
-			       const struct fb_image *image);
-extern int nvidiafb_sync(struct fb_info *info);
-
-/* in nv_backlight.h */
-#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
-extern void nvidia_bl_init(struct nvidia_par *par);
-extern void nvidia_bl_exit(struct nvidia_par *par);
-#else
-static inline void nvidia_bl_init(struct nvidia_par *par) {}
-static inline void nvidia_bl_exit(struct nvidia_par *par) {}
-#endif
-
-#endif				/* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
deleted file mode 100644
index 2f2e162134fa..000000000000
--- a/drivers/video/nvidia/nv_setup.c
+++ /dev/null
@@ -1,675 +0,0 @@
- /***************************************************************************\
-|*                                                                           *|
-|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
- * XFree86 'nv' driver, this source code is provided under MIT-style licensing
- * where the source code is provided "as is" without warranty of any kind.
- * The only usage restriction is for the copyright notices to be retained
- * whenever code is used.
- *
- * Antonino Daplas <adaplas@pol.net> 2005-03-11
- */
-
-#include <video/vga.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include "nv_type.h"
-#include "nv_local.h"
-#include "nv_proto.h"
-/*
- * Override VGA I/O routines.
- */
-void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value)
-{
-	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
-	VGA_WR08(par->PCIO, par->IOBase + 0x05, value);
-}
-u8 NVReadCrtc(struct nvidia_par *par, u8 index)
-{
-	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
-	return (VGA_RD08(par->PCIO, par->IOBase + 0x05));
-}
-void NVWriteGr(struct nvidia_par *par, u8 index, u8 value)
-{
-	VGA_WR08(par->PVIO, VGA_GFX_I, index);
-	VGA_WR08(par->PVIO, VGA_GFX_D, value);
-}
-u8 NVReadGr(struct nvidia_par *par, u8 index)
-{
-	VGA_WR08(par->PVIO, VGA_GFX_I, index);
-	return (VGA_RD08(par->PVIO, VGA_GFX_D));
-}
-void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value)
-{
-	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
-	VGA_WR08(par->PVIO, VGA_SEQ_D, value);
-}
-u8 NVReadSeq(struct nvidia_par *par, u8 index)
-{
-	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
-	return (VGA_RD08(par->PVIO, VGA_SEQ_D));
-}
-void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value)
-{
-	volatile u8 tmp;
-
-	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
-	if (par->paletteEnabled)
-		index &= ~0x20;
-	else
-		index |= 0x20;
-	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
-	VGA_WR08(par->PCIO, VGA_ATT_W, value);
-}
-u8 NVReadAttr(struct nvidia_par *par, u8 index)
-{
-	volatile u8 tmp;
-
-	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
-	if (par->paletteEnabled)
-		index &= ~0x20;
-	else
-		index |= 0x20;
-	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
-	return (VGA_RD08(par->PCIO, VGA_ATT_R));
-}
-void NVWriteMiscOut(struct nvidia_par *par, u8 value)
-{
-	VGA_WR08(par->PVIO, VGA_MIS_W, value);
-}
-u8 NVReadMiscOut(struct nvidia_par *par)
-{
-	return (VGA_RD08(par->PVIO, VGA_MIS_R));
-}
-#if 0
-void NVEnablePalette(struct nvidia_par *par)
-{
-	volatile u8 tmp;
-
-	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
-	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x00);
-	par->paletteEnabled = 1;
-}
-void NVDisablePalette(struct nvidia_par *par)
-{
-	volatile u8 tmp;
-
-	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
-	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x20);
-	par->paletteEnabled = 0;
-}
-#endif  /*  0  */
-void NVWriteDacMask(struct nvidia_par *par, u8 value)
-{
-	VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
-}
-#if 0
-u8 NVReadDacMask(struct nvidia_par *par)
-{
-	return (VGA_RD08(par->PDIO, VGA_PEL_MSK));
-}
-#endif  /*  0  */
-void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
-{
-	VGA_WR08(par->PDIO, VGA_PEL_IR, value);
-}
-void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value)
-{
-	VGA_WR08(par->PDIO, VGA_PEL_IW, value);
-}
-void NVWriteDacData(struct nvidia_par *par, u8 value)
-{
-	VGA_WR08(par->PDIO, VGA_PEL_D, value);
-}
-u8 NVReadDacData(struct nvidia_par *par)
-{
-	return (VGA_RD08(par->PDIO, VGA_PEL_D));
-}
-
-static int NVIsConnected(struct nvidia_par *par, int output)
-{
-	volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
-	u32 reg52C, reg608, dac0_reg608 = 0;
-	int present;
-
-	if (output) {
-	    dac0_reg608 = NV_RD32(PRAMDAC, 0x0608);
-	    PRAMDAC += 0x800;
-	}
-
-	reg52C = NV_RD32(PRAMDAC, 0x052C);
-	reg608 = NV_RD32(PRAMDAC, 0x0608);
-
-	NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
-
-	NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
-	msleep(1);
-	NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
-
-	NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140);
-	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) |
-		0x00001000);
-
-	msleep(1);
-
-	present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
-
-	if (present)
-		printk("nvidiafb: CRTC%i analog found\n", output);
-	else
-		printk("nvidiafb: CRTC%i analog not found\n", output);
-
-	if (output)
-	    NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608);
-
-	NV_WR32(PRAMDAC, 0x052C, reg52C);
-	NV_WR32(PRAMDAC, 0x0608, reg608);
-
-	return present;
-}
-
-static void NVSelectHeadRegisters(struct nvidia_par *par, int head)
-{
-	if (head) {
-		par->PCIO = par->PCIO0 + 0x2000;
-		par->PCRTC = par->PCRTC0 + 0x800;
-		par->PRAMDAC = par->PRAMDAC0 + 0x800;
-		par->PDIO = par->PDIO0 + 0x2000;
-	} else {
-		par->PCIO = par->PCIO0;
-		par->PCRTC = par->PCRTC0;
-		par->PRAMDAC = par->PRAMDAC0;
-		par->PDIO = par->PDIO0;
-	}
-}
-
-static void nv4GetConfig(struct nvidia_par *par)
-{
-	if (NV_RD32(par->PFB, 0x0000) & 0x00000100) {
-		par->RamAmountKBytes =
-		    ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 +
-		    1024 * 2;
-	} else {
-		switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) {
-		case 0:
-			par->RamAmountKBytes = 1024 * 32;
-			break;
-		case 1:
-			par->RamAmountKBytes = 1024 * 4;
-			break;
-		case 2:
-			par->RamAmountKBytes = 1024 * 8;
-			break;
-		case 3:
-		default:
-			par->RamAmountKBytes = 1024 * 16;
-			break;
-		}
-	}
-	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ?
-	    14318 : 13500;
-	par->CURSOR = &par->PRAMIN[0x1E00];
-	par->MinVClockFreqKHz = 12000;
-	par->MaxVClockFreqKHz = 350000;
-}
-
-static void nv10GetConfig(struct nvidia_par *par)
-{
-	struct pci_dev *dev;
-	u32 implementation = par->Chipset & 0x0ff0;
-
-#ifdef __BIG_ENDIAN
-	/* turn on big endian register access */
-	if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) {
-		NV_WR32(par->PMC, 0x0004, 0x01000001);
-		mb();
-	}
-#endif
-
-	dev = pci_get_bus_and_slot(0, 1);
-	if ((par->Chipset & 0xffff) == 0x01a0) {
-		u32 amt;
-
-		pci_read_config_dword(dev, 0x7c, &amt);
-		par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
-	} else if ((par->Chipset & 0xffff) == 0x01f0) {
-		u32 amt;
-
-		pci_read_config_dword(dev, 0x84, &amt);
-		par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
-	} else {
-		par->RamAmountKBytes =
-		    (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
-	}
-	pci_dev_put(dev);
-
-	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
-	    14318 : 13500;
-
-	if (par->twoHeads && (implementation != 0x0110)) {
-		if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22))
-			par->CrystalFreqKHz = 27000;
-	}
-
-	par->CURSOR = NULL;	/* can't set this here */
-	par->MinVClockFreqKHz = 12000;
-	par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
-}
-
-int NVCommonSetup(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	struct fb_var_screeninfo *var;
-	u16 implementation = par->Chipset & 0x0ff0;
-	u8 *edidA = NULL, *edidB = NULL;
-	struct fb_monspecs *monitorA, *monitorB;
-	struct fb_monspecs *monA = NULL, *monB = NULL;
-	int mobile = 0;
-	int tvA = 0;
-	int tvB = 0;
-	int FlatPanel = -1;	/* really means the CRTC is slaved */
-	int Television = 0;
-	int err = 0;
-
-	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
-	monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
-	monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
-
-	if (!var || !monitorA || !monitorB) {
-		err = -ENOMEM;
-		goto done;
-	}
-
-	par->PRAMIN = par->REGS + (0x00710000 / 4);
-	par->PCRTC0 = par->REGS + (0x00600000 / 4);
-	par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
-	par->PFB = par->REGS + (0x00100000 / 4);
-	par->PFIFO = par->REGS + (0x00002000 / 4);
-	par->PGRAPH = par->REGS + (0x00400000 / 4);
-	par->PEXTDEV = par->REGS + (0x00101000 / 4);
-	par->PTIMER = par->REGS + (0x00009000 / 4);
-	par->PMC = par->REGS + (0x00000000 / 4);
-	par->FIFO = par->REGS + (0x00800000 / 4);
-
-	/* 8 bit registers */
-	par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000;
-	par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000;
-	par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000;
-
-	par->twoHeads = (par->Architecture >= NV_ARCH_10) &&
-	    (implementation != 0x0100) &&
-	    (implementation != 0x0150) &&
-	    (implementation != 0x01A0) && (implementation != 0x0200);
-
-	par->fpScaler = (par->FpScale && par->twoHeads &&
-			 (implementation != 0x0110));
-
-	par->twoStagePLL = (implementation == 0x0310) ||
-	    (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40);
-
-	par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) &&
-	    (implementation != 0x0100);
-
-	par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020);
-
-	/* look for known laptop chips */
-	switch (par->Chipset & 0xffff) {
-	case 0x0112:
-	case 0x0174:
-	case 0x0175:
-	case 0x0176:
-	case 0x0177:
-	case 0x0179:
-	case 0x017C:
-	case 0x017D:
-	case 0x0186:
-	case 0x0187:
-	case 0x018D:
-	case 0x01D7:
-	case 0x0228:
-	case 0x0286:
-	case 0x028C:
-	case 0x0316:
-	case 0x0317:
-	case 0x031A:
-	case 0x031B:
-	case 0x031C:
-	case 0x031D:
-	case 0x031E:
-	case 0x031F:
-	case 0x0324:
-	case 0x0325:
-	case 0x0328:
-	case 0x0329:
-	case 0x032C:
-	case 0x032D:
-	case 0x0347:
-	case 0x0348:
-	case 0x0349:
-	case 0x034B:
-	case 0x034C:
-	case 0x0160:
-	case 0x0166:
-	case 0x0169:
-	case 0x016B:
-	case 0x016C:
-	case 0x016D:
-	case 0x00C8:
-	case 0x00CC:
-	case 0x0144:
-	case 0x0146:
-	case 0x0147:
-	case 0x0148:
-	case 0x0098:
-	case 0x0099:
-		mobile = 1;
-		break;
-	default:
-		break;
-	}
-
-	if (par->Architecture == NV_ARCH_04)
-		nv4GetConfig(par);
-	else
-		nv10GetConfig(par);
-
-	NVSelectHeadRegisters(par, 0);
-
-	NVLockUnlock(par, 0);
-
-	par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0;
-
-	par->Television = 0;
-
-	nvidia_create_i2c_busses(par);
-	if (!par->twoHeads) {
-		par->CRTCnumber = 0;
-		if (nvidia_probe_i2c_connector(info, 1, &edidA))
-			nvidia_probe_of_connector(info, 1, &edidA);
-		if (edidA && !fb_parse_edid(edidA, var)) {
-			printk("nvidiafb: EDID found from BUS1\n");
-			monA = monitorA;
-			fb_edid_to_monspecs(edidA, monA);
-			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
-
-			/* NV4 doesn't support FlatPanels */
-			if ((par->Chipset & 0x0fff) <= 0x0020)
-				FlatPanel = 0;
-		} else {
-			VGA_WR08(par->PCIO, 0x03D4, 0x28);
-			if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) {
-				VGA_WR08(par->PCIO, 0x03D4, 0x33);
-				if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01))
-					Television = 1;
-				FlatPanel = 1;
-			} else {
-				FlatPanel = 0;
-			}
-			printk("nvidiafb: HW is currently programmed for %s\n",
-			       FlatPanel ? (Television ? "TV" : "DFP") :
-			       "CRT");
-		}
-
-		if (par->FlatPanel == -1) {
-			par->FlatPanel = FlatPanel;
-			par->Television = Television;
-		} else {
-			printk("nvidiafb: Forcing display type to %s as "
-			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
-		}
-	} else {
-		u8 outputAfromCRTC, outputBfromCRTC;
-		int CRTCnumber = -1;
-		u8 slaved_on_A, slaved_on_B;
-		int analog_on_A, analog_on_B;
-		u32 oldhead;
-		u8 cr44;
-
-		if (implementation != 0x0110) {
-			if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100)
-				outputAfromCRTC = 1;
-			else
-				outputAfromCRTC = 0;
-			if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100)
-				outputBfromCRTC = 1;
-			else
-				outputBfromCRTC = 0;
-			analog_on_A = NVIsConnected(par, 0);
-			analog_on_B = NVIsConnected(par, 1);
-		} else {
-			outputAfromCRTC = 0;
-			outputBfromCRTC = 1;
-			analog_on_A = 0;
-			analog_on_B = 0;
-		}
-
-		VGA_WR08(par->PCIO, 0x03D4, 0x44);
-		cr44 = VGA_RD08(par->PCIO, 0x03D5);
-
-		VGA_WR08(par->PCIO, 0x03D5, 3);
-		NVSelectHeadRegisters(par, 1);
-		NVLockUnlock(par, 0);
-
-		VGA_WR08(par->PCIO, 0x03D4, 0x28);
-		slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
-		if (slaved_on_B) {
-			VGA_WR08(par->PCIO, 0x03D4, 0x33);
-			tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
-		}
-
-		VGA_WR08(par->PCIO, 0x03D4, 0x44);
-		VGA_WR08(par->PCIO, 0x03D5, 0);
-		NVSelectHeadRegisters(par, 0);
-		NVLockUnlock(par, 0);
-
-		VGA_WR08(par->PCIO, 0x03D4, 0x28);
-		slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
-		if (slaved_on_A) {
-			VGA_WR08(par->PCIO, 0x03D4, 0x33);
-			tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
-		}
-
-		oldhead = NV_RD32(par->PCRTC0, 0x00000860);
-		NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
-
-		if (nvidia_probe_i2c_connector(info, 1, &edidA))
-			nvidia_probe_of_connector(info, 1, &edidA);
-		if (edidA && !fb_parse_edid(edidA, var)) {
-			printk("nvidiafb: EDID found from BUS1\n");
-			monA = monitorA;
-			fb_edid_to_monspecs(edidA, monA);
-		}
-
-		if (nvidia_probe_i2c_connector(info, 2, &edidB))
-			nvidia_probe_of_connector(info, 2, &edidB);
-		if (edidB && !fb_parse_edid(edidB, var)) {
-			printk("nvidiafb: EDID found from BUS2\n");
-			monB = monitorB;
-			fb_edid_to_monspecs(edidB, monB);
-		}
-
-		if (slaved_on_A && !tvA) {
-			CRTCnumber = 0;
-			FlatPanel = 1;
-			printk("nvidiafb: CRTC 0 is currently programmed for "
-			       "DFP\n");
-		} else if (slaved_on_B && !tvB) {
-			CRTCnumber = 1;
-			FlatPanel = 1;
-			printk("nvidiafb: CRTC 1 is currently programmed "
-			       "for DFP\n");
-		} else if (analog_on_A) {
-			CRTCnumber = outputAfromCRTC;
-			FlatPanel = 0;
-			printk("nvidiafb: CRTC %i appears to have a "
-			       "CRT attached\n", CRTCnumber);
-		} else if (analog_on_B) {
-			CRTCnumber = outputBfromCRTC;
-			FlatPanel = 0;
-			printk("nvidiafb: CRTC %i appears to have a "
-			       "CRT attached\n", CRTCnumber);
-		} else if (slaved_on_A) {
-			CRTCnumber = 0;
-			FlatPanel = 1;
-			Television = 1;
-			printk("nvidiafb: CRTC 0 is currently programmed "
-			       "for TV\n");
-		} else if (slaved_on_B) {
-			CRTCnumber = 1;
-			FlatPanel = 1;
-			Television = 1;
-			printk("nvidiafb: CRTC 1 is currently programmed for "
-			       "TV\n");
-		} else if (monA) {
-			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
-		} else if (monB) {
-			FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0;
-		}
-
-		if (par->FlatPanel == -1) {
-			if (FlatPanel != -1) {
-				par->FlatPanel = FlatPanel;
-				par->Television = Television;
-			} else {
-				printk("nvidiafb: Unable to detect display "
-				       "type...\n");
-				if (mobile) {
-					printk("...On a laptop, assuming "
-					       "DFP\n");
-					par->FlatPanel = 1;
-				} else {
-					printk("...Using default of CRT\n");
-					par->FlatPanel = 0;
-				}
-			}
-		} else {
-			printk("nvidiafb: Forcing display type to %s as "
-			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
-		}
-
-		if (par->CRTCnumber == -1) {
-			if (CRTCnumber != -1)
-				par->CRTCnumber = CRTCnumber;
-			else {
-				printk("nvidiafb: Unable to detect which "
-				       "CRTCNumber...\n");
-				if (par->FlatPanel)
-					par->CRTCnumber = 1;
-				else
-					par->CRTCnumber = 0;
-				printk("...Defaulting to CRTCNumber %i\n",
-				       par->CRTCnumber);
-			}
-		} else {
-			printk("nvidiafb: Forcing CRTCNumber %i as "
-			       "specified\n", par->CRTCnumber);
-		}
-
-		if (monA) {
-			if (((monA->input & FB_DISP_DDI) &&
-			     par->FlatPanel) ||
-			    ((!(monA->input & FB_DISP_DDI)) &&
-			     !par->FlatPanel)) {
-				if (monB) {
-					fb_destroy_modedb(monB->modedb);
-					monB = NULL;
-				}
-			} else {
-				fb_destroy_modedb(monA->modedb);
-				monA = NULL;
-			}
-		}
-
-		if (monB) {
-			if (((monB->input & FB_DISP_DDI) &&
-			     !par->FlatPanel) ||
-			    ((!(monB->input & FB_DISP_DDI)) &&
-			     par->FlatPanel)) {
-				fb_destroy_modedb(monB->modedb);
-				monB = NULL;
-			} else
-				monA = monB;
-		}
-
-		if (implementation == 0x0110)
-			cr44 = par->CRTCnumber * 0x3;
-
-		NV_WR32(par->PCRTC0, 0x00000860, oldhead);
-
-		VGA_WR08(par->PCIO, 0x03D4, 0x44);
-		VGA_WR08(par->PCIO, 0x03D5, cr44);
-		NVSelectHeadRegisters(par, par->CRTCnumber);
-	}
-
-	printk("nvidiafb: Using %s on CRTC %i\n",
-	       par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT",
-	       par->CRTCnumber);
-
-	if (par->FlatPanel && !par->Television) {
-		par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1;
-		par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1;
-		par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033;
-
-		printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight);
-	}
-
-	if (monA)
-		info->monspecs = *monA;
-
-	if (!par->FlatPanel || !par->twoHeads)
-		par->FPDither = 0;
-
-	par->LVDS = 0;
-	if (par->FlatPanel && par->twoHeads) {
-		NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004);
-		if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1)
-			par->LVDS = 1;
-		printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS");
-	}
-
-	kfree(edidA);
-	kfree(edidB);
-done:
-	kfree(var);
-	kfree(monitorA);
-	kfree(monitorB);
-	return err;
-}
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
deleted file mode 100644
index c03f7f55c76d..000000000000
--- a/drivers/video/nvidia/nv_type.h
+++ /dev/null
@@ -1,180 +0,0 @@
-#ifndef __NV_TYPE_H__
-#define __NV_TYPE_H__
-
-#include <linux/fb.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <video/vga.h>
-
-#define NV_ARCH_04  0x04
-#define NV_ARCH_10  0x10
-#define NV_ARCH_20  0x20
-#define NV_ARCH_30  0x30
-#define NV_ARCH_40  0x40
-
-#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1)  << (b))
-#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
-#define SetBF(mask,value) ((value) << (0?mask))
-#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
-#define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
-#define SetBit(n) (1<<(n))
-#define Set8Bits(value) ((value)&0xff)
-
-#define V_DBLSCAN  1
-
-typedef struct {
-	int bitsPerPixel;
-	int depth;
-	int displayWidth;
-	int weight;
-} NVFBLayout;
-
-#define NUM_SEQ_REGS		0x05
-#define NUM_CRT_REGS		0x41
-#define NUM_GRC_REGS		0x09
-#define NUM_ATC_REGS		0x15
-
-struct nvidia_par;
-
-struct nvidia_i2c_chan {
-	struct nvidia_par *par;
-	unsigned long ddc_base;
-	struct i2c_adapter adapter;
-	struct i2c_algo_bit_data algo;
-};
-
-typedef struct _riva_hw_state {
-	u8 attr[NUM_ATC_REGS];
-	u8 crtc[NUM_CRT_REGS];
-	u8 gra[NUM_GRC_REGS];
-	u8 seq[NUM_SEQ_REGS];
-	u8 misc_output;
-	u32 bpp;
-	u32 width;
-	u32 height;
-	u32 interlace;
-	u32 repaint0;
-	u32 repaint1;
-	u32 screen;
-	u32 scale;
-	u32 dither;
-	u32 extra;
-	u32 fifo;
-	u32 pixel;
-	u32 horiz;
-	u32 arbitration0;
-	u32 arbitration1;
-	u32 pll;
-	u32 pllB;
-	u32 vpll;
-	u32 vpll2;
-	u32 vpllB;
-	u32 vpll2B;
-	u32 pllsel;
-	u32 general;
-	u32 crtcOwner;
-	u32 head;
-	u32 head2;
-	u32 config;
-	u32 cursorConfig;
-	u32 cursor0;
-	u32 cursor1;
-	u32 cursor2;
-	u32 timingH;
-	u32 timingV;
-	u32 displayV;
-	u32 crtcSync;
-	u32 control;
-} RIVA_HW_STATE;
-
-struct riva_regs {
-	RIVA_HW_STATE ext;
-};
-
-struct nvidia_par {
-	RIVA_HW_STATE SavedReg;
-	RIVA_HW_STATE ModeReg;
-	RIVA_HW_STATE initial_state;
-	RIVA_HW_STATE *CurrentState;
-	struct vgastate vgastate;
-	u32 pseudo_palette[16];
-	struct pci_dev *pci_dev;
-	u32 Architecture;
-	u32 CursorStart;
-	int Chipset;
-	unsigned long FbAddress;
-	u8 __iomem *FbStart;
-	u32 FbMapSize;
-	u32 FbUsableSize;
-	u32 ScratchBufferSize;
-	u32 ScratchBufferStart;
-	int FpScale;
-	u32 MinVClockFreqKHz;
-	u32 MaxVClockFreqKHz;
-	u32 CrystalFreqKHz;
-	u32 RamAmountKBytes;
-	u32 IOBase;
-	NVFBLayout CurrentLayout;
-	int cursor_reset;
-	int lockup;
-	int videoKey;
-	int FlatPanel;
-	int FPDither;
-	int Television;
-	int CRTCnumber;
-	int alphaCursor;
-	int twoHeads;
-	int twoStagePLL;
-	int fpScaler;
-	int fpWidth;
-	int fpHeight;
-	int PanelTweak;
-	int paneltweak;
-	int LVDS;
-	int pm_state;
-	int reverse_i2c;
-	u32 crtcSync_read;
-	u32 fpSyncs;
-	u32 dmaPut;
-	u32 dmaCurrent;
-	u32 dmaFree;
-	u32 dmaMax;
-	u32 __iomem *dmaBase;
-	u32 currentRop;
-	int WaitVSyncPossible;
-	int BlendingPossible;
-	u32 paletteEnabled;
-	u32 forceCRTC;
-	u32 open_count;
-	u8 DDCBase;
-#ifdef CONFIG_MTRR
-	struct {
-		int vram;
-		int vram_valid;
-	} mtrr;
-#endif
-	struct nvidia_i2c_chan chan[3];
-
-	volatile u32 __iomem *REGS;
-	volatile u32 __iomem *PCRTC0;
-	volatile u32 __iomem *PCRTC;
-	volatile u32 __iomem *PRAMDAC0;
-	volatile u32 __iomem *PFB;
-	volatile u32 __iomem *PFIFO;
-	volatile u32 __iomem *PGRAPH;
-	volatile u32 __iomem *PEXTDEV;
-	volatile u32 __iomem *PTIMER;
-	volatile u32 __iomem *PMC;
-	volatile u32 __iomem *PRAMIN;
-	volatile u32 __iomem *FIFO;
-	volatile u32 __iomem *CURSOR;
-	volatile u8 __iomem *PCIO0;
-	volatile u8 __iomem *PCIO;
-	volatile u8 __iomem *PVIO;
-	volatile u8 __iomem *PDIO0;
-	volatile u8 __iomem *PDIO;
-	volatile u32 __iomem *PRAMDAC;
-};
-
-#endif				/* __NV_TYPE_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
deleted file mode 100644
index def041204676..000000000000
--- a/drivers/video/nvidia/nvidia.c
+++ /dev/null
@@ -1,1607 +0,0 @@
-/*
- * linux/drivers/video/nvidia/nvidia.c - nVidia fb driver
- *
- * Copyright 2004 Antonino Daplas <adaplas@pol.net>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/console.h>
-#include <linux/backlight.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-#ifdef CONFIG_PPC_OF
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif
-#ifdef CONFIG_BOOTX_TEXT
-#include <asm/btext.h>
-#endif
-
-#include "nv_local.h"
-#include "nv_type.h"
-#include "nv_proto.h"
-#include "nv_dma.h"
-
-#ifdef CONFIG_FB_NVIDIA_DEBUG
-#define NVTRACE          printk
-#else
-#define NVTRACE          if (0) printk
-#endif
-
-#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __func__)
-#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __func__)
-
-#ifdef CONFIG_FB_NVIDIA_DEBUG
-#define assert(expr) \
-	if (!(expr)) { \
-	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-	#expr,__FILE__,__func__,__LINE__); \
-	BUG(); \
-	}
-#else
-#define assert(expr)
-#endif
-
-#define PFX "nvidiafb: "
-
-/* HW cursor parameters */
-#define MAX_CURS		32
-
-static struct pci_device_id nvidiafb_pci_tbl[] = {
-	{PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-	 PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0},
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
-
-/* command line data, set in nvidiafb_setup() */
-static int flatpanel = -1;	/* Autodetect later */
-static int fpdither = -1;
-static int forceCRTC = -1;
-static int hwcur = 0;
-static int noaccel = 0;
-static int noscale = 0;
-static int paneltweak = 0;
-static int vram = 0;
-static int bpp = 8;
-static int reverse_i2c;
-#ifdef CONFIG_MTRR
-static bool nomtrr = false;
-#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight = 1;
-#else
-static int backlight = 0;
-#endif
-
-static char *mode_option = NULL;
-
-static struct fb_fix_screeninfo nvidiafb_fix = {
-	.type = FB_TYPE_PACKED_PIXELS,
-	.xpanstep = 8,
-	.ypanstep = 1,
-};
-
-static struct fb_var_screeninfo nvidiafb_default_var = {
-	.xres = 640,
-	.yres = 480,
-	.xres_virtual = 640,
-	.yres_virtual = 480,
-	.bits_per_pixel = 8,
-	.red = {0, 8, 0},
-	.green = {0, 8, 0},
-	.blue = {0, 8, 0},
-	.transp = {0, 0, 0},
-	.activate = FB_ACTIVATE_NOW,
-	.height = -1,
-	.width = -1,
-	.pixclock = 39721,
-	.left_margin = 40,
-	.right_margin = 24,
-	.upper_margin = 32,
-	.lower_margin = 11,
-	.hsync_len = 96,
-	.vsync_len = 2,
-	.vmode = FB_VMODE_NONINTERLACED
-};
-
-static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
-				       u16 bg, u16 fg, u32 w, u32 h)
-{
-	u32 *data = (u32 *) data8;
-	int i, j, k = 0;
-	u32 b, tmp;
-
-	w = (w + 1) & ~1;
-
-	for (i = 0; i < h; i++) {
-		b = *data++;
-		reverse_order(&b);
-
-		for (j = 0; j < w / 2; j++) {
-			tmp = 0;
-#if defined (__BIG_ENDIAN)
-			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
-			b <<= 1;
-			tmp |= (b & (1 << 31)) ? fg : bg;
-			b <<= 1;
-#else
-			tmp = (b & 1) ? fg : bg;
-			b >>= 1;
-			tmp |= (b & 1) ? fg << 16 : bg << 16;
-			b >>= 1;
-#endif
-			NV_WR32(&par->CURSOR[k++], 0, tmp);
-		}
-		k += (MAX_CURS - w) / 2;
-	}
-}
-
-static void nvidia_write_clut(struct nvidia_par *par,
-			      u8 regnum, u8 red, u8 green, u8 blue)
-{
-	NVWriteDacMask(par, 0xff);
-	NVWriteDacWriteAddr(par, regnum);
-	NVWriteDacData(par, red);
-	NVWriteDacData(par, green);
-	NVWriteDacData(par, blue);
-}
-
-static void nvidia_read_clut(struct nvidia_par *par,
-			     u8 regnum, u8 * red, u8 * green, u8 * blue)
-{
-	NVWriteDacMask(par, 0xff);
-	NVWriteDacReadAddr(par, regnum);
-	*red = NVReadDacData(par);
-	*green = NVReadDacData(par);
-	*blue = NVReadDacData(par);
-}
-
-static int nvidia_panel_tweak(struct nvidia_par *par,
-			      struct _riva_hw_state *state)
-{
-	int tweak = 0;
-
-   if (par->paneltweak) {
-	   tweak = par->paneltweak;
-   } else {
-	   /* begin flat panel hacks */
-	   /* This is unfortunate, but some chips need this register
-	      tweaked or else you get artifacts where adjacent pixels are
-	      swapped.  There are no hard rules for what to set here so all
-	      we can do is experiment and apply hacks. */
-
-	   if(((par->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
-		   /* At least one NV34 laptop needs this workaround. */
-		   tweak = -1;
-	   }
-
-	   if((par->Chipset & 0xfff0) == 0x0310) {
-		   tweak = 1;
-	   }
-	   /* end flat panel hacks */
-   }
-
-   return tweak;
-}
-
-static void nvidia_screen_off(struct nvidia_par *par, int on)
-{
-	unsigned char tmp;
-
-	if (on) {
-		/*
-		 * Turn off screen and disable sequencer.
-		 */
-		tmp = NVReadSeq(par, 0x01);
-
-		NVWriteSeq(par, 0x00, 0x01);		/* Synchronous Reset */
-		NVWriteSeq(par, 0x01, tmp | 0x20);	/* disable the display */
-	} else {
-		/*
-		 * Reenable sequencer, then turn on screen.
-		 */
-
-		tmp = NVReadSeq(par, 0x01);
-
-		NVWriteSeq(par, 0x01, tmp & ~0x20);	/* reenable display */
-		NVWriteSeq(par, 0x00, 0x03);		/* End Reset */
-	}
-}
-
-static void nvidia_save_vga(struct nvidia_par *par,
-			    struct _riva_hw_state *state)
-{
-	int i;
-
-	NVTRACE_ENTER();
-	NVLockUnlock(par, 0);
-
-	NVUnloadStateExt(par, state);
-
-	state->misc_output = NVReadMiscOut(par);
-
-	for (i = 0; i < NUM_CRT_REGS; i++)
-		state->crtc[i] = NVReadCrtc(par, i);
-
-	for (i = 0; i < NUM_ATC_REGS; i++)
-		state->attr[i] = NVReadAttr(par, i);
-
-	for (i = 0; i < NUM_GRC_REGS; i++)
-		state->gra[i] = NVReadGr(par, i);
-
-	for (i = 0; i < NUM_SEQ_REGS; i++)
-		state->seq[i] = NVReadSeq(par, i);
-	NVTRACE_LEAVE();
-}
-
-#undef DUMP_REG
-
-static void nvidia_write_regs(struct nvidia_par *par,
-			      struct _riva_hw_state *state)
-{
-	int i;
-
-	NVTRACE_ENTER();
-
-	NVLoadStateExt(par, state);
-
-	NVWriteMiscOut(par, state->misc_output);
-
-	for (i = 1; i < NUM_SEQ_REGS; i++) {
-#ifdef DUMP_REG
-		printk(" SEQ[%02x] = %08x\n", i, state->seq[i]);
-#endif
-		NVWriteSeq(par, i, state->seq[i]);
-	}
-
-	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
-	NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80);
-
-	for (i = 0; i < NUM_CRT_REGS; i++) {
-		switch (i) {
-		case 0x19:
-		case 0x20 ... 0x40:
-			break;
-		default:
-#ifdef DUMP_REG
-			printk("CRTC[%02x] = %08x\n", i, state->crtc[i]);
-#endif
-			NVWriteCrtc(par, i, state->crtc[i]);
-		}
-	}
-
-	for (i = 0; i < NUM_GRC_REGS; i++) {
-#ifdef DUMP_REG
-		printk(" GRA[%02x] = %08x\n", i, state->gra[i]);
-#endif
-		NVWriteGr(par, i, state->gra[i]);
-	}
-
-	for (i = 0; i < NUM_ATC_REGS; i++) {
-#ifdef DUMP_REG
-		printk("ATTR[%02x] = %08x\n", i, state->attr[i]);
-#endif
-		NVWriteAttr(par, i, state->attr[i]);
-	}
-
-	NVTRACE_LEAVE();
-}
-
-static int nvidia_calc_regs(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	struct _riva_hw_state *state = &par->ModeReg;
-	int i, depth = fb_get_color_depth(&info->var, &info->fix);
-	int h_display = info->var.xres / 8 - 1;
-	int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
-	int h_end = (info->var.xres + info->var.right_margin +
-		     info->var.hsync_len) / 8 - 1;
-	int h_total = (info->var.xres + info->var.right_margin +
-		       info->var.hsync_len + info->var.left_margin) / 8 - 5;
-	int h_blank_s = h_display;
-	int h_blank_e = h_total + 4;
-	int v_display = info->var.yres - 1;
-	int v_start = info->var.yres + info->var.lower_margin - 1;
-	int v_end = (info->var.yres + info->var.lower_margin +
-		     info->var.vsync_len) - 1;
-	int v_total = (info->var.yres + info->var.lower_margin +
-		       info->var.vsync_len + info->var.upper_margin) - 2;
-	int v_blank_s = v_display;
-	int v_blank_e = v_total + 1;
-
-	/*
-	 * Set all CRTC values.
-	 */
-
-	if (info->var.vmode & FB_VMODE_INTERLACED)
-		v_total |= 1;
-
-	if (par->FlatPanel == 1) {
-		v_start = v_total - 3;
-		v_end = v_total - 2;
-		v_blank_s = v_start;
-		h_start = h_total - 5;
-		h_end = h_total - 2;
-		h_blank_e = h_total + 4;
-	}
-
-	state->crtc[0x0] = Set8Bits(h_total);
-	state->crtc[0x1] = Set8Bits(h_display);
-	state->crtc[0x2] = Set8Bits(h_blank_s);
-	state->crtc[0x3] = SetBitField(h_blank_e, 4: 0, 4:0)
-		| SetBit(7);
-	state->crtc[0x4] = Set8Bits(h_start);
-	state->crtc[0x5] = SetBitField(h_blank_e, 5: 5, 7:7)
-		| SetBitField(h_end, 4: 0, 4:0);
-	state->crtc[0x6] = SetBitField(v_total, 7: 0, 7:0);
-	state->crtc[0x7] = SetBitField(v_total, 8: 8, 0:0)
-		| SetBitField(v_display, 8: 8, 1:1)
-		| SetBitField(v_start, 8: 8, 2:2)
-		| SetBitField(v_blank_s, 8: 8, 3:3)
-		| SetBit(4)
-		| SetBitField(v_total, 9: 9, 5:5)
-		| SetBitField(v_display, 9: 9, 6:6)
-		| SetBitField(v_start, 9: 9, 7:7);
-	state->crtc[0x9] = SetBitField(v_blank_s, 9: 9, 5:5)
-		| SetBit(6)
-		| ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0x00);
-	state->crtc[0x10] = Set8Bits(v_start);
-	state->crtc[0x11] = SetBitField(v_end, 3: 0, 3:0) | SetBit(5);
-	state->crtc[0x12] = Set8Bits(v_display);
-	state->crtc[0x13] = ((info->var.xres_virtual / 8) *
-			     (info->var.bits_per_pixel / 8));
-	state->crtc[0x15] = Set8Bits(v_blank_s);
-	state->crtc[0x16] = Set8Bits(v_blank_e);
-
-	state->attr[0x10] = 0x01;
-
-	if (par->Television)
-		state->attr[0x11] = 0x00;
-
-	state->screen = SetBitField(h_blank_e, 6: 6, 4:4)
-		| SetBitField(v_blank_s, 10: 10, 3:3)
-		| SetBitField(v_start, 10: 10, 2:2)
-		| SetBitField(v_display, 10: 10, 1:1)
-		| SetBitField(v_total, 10: 10, 0:0);
-
-	state->horiz = SetBitField(h_total, 8: 8, 0:0)
-		| SetBitField(h_display, 8: 8, 1:1)
-		| SetBitField(h_blank_s, 8: 8, 2:2)
-		| SetBitField(h_start, 8: 8, 3:3);
-
-	state->extra = SetBitField(v_total, 11: 11, 0:0)
-		| SetBitField(v_display, 11: 11, 2:2)
-		| SetBitField(v_start, 11: 11, 4:4)
-		| SetBitField(v_blank_s, 11: 11, 6:6);
-
-	if (info->var.vmode & FB_VMODE_INTERLACED) {
-		h_total = (h_total >> 1) & ~1;
-		state->interlace = Set8Bits(h_total);
-		state->horiz |= SetBitField(h_total, 8: 8, 4:4);
-	} else {
-		state->interlace = 0xff;	/* interlace off */
-	}
-
-	/*
-	 * Calculate the extended registers.
-	 */
-
-	if (depth < 24)
-		i = depth;
-	else
-		i = 32;
-
-	if (par->Architecture >= NV_ARCH_10)
-		par->CURSOR = (volatile u32 __iomem *)(info->screen_base +
-						       par->CursorStart);
-
-	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		state->misc_output &= ~0x40;
-	else
-		state->misc_output |= 0x40;
-	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		state->misc_output &= ~0x80;
-	else
-		state->misc_output |= 0x80;
-
-	NVCalcStateExt(par, state, i, info->var.xres_virtual,
-		       info->var.xres, info->var.yres_virtual,
-		       1000000000 / info->var.pixclock, info->var.vmode);
-
-	state->scale = NV_RD32(par->PRAMDAC, 0x00000848) & 0xfff000ff;
-	if (par->FlatPanel == 1) {
-		state->pixel |= (1 << 7);
-
-		if (!par->fpScaler || (par->fpWidth <= info->var.xres)
-		    || (par->fpHeight <= info->var.yres)) {
-			state->scale |= (1 << 8);
-		}
-
-		if (!par->crtcSync_read) {
-			state->crtcSync = NV_RD32(par->PRAMDAC, 0x0828);
-			par->crtcSync_read = 1;
-		}
-
-		par->PanelTweak = nvidia_panel_tweak(par, state);
-	}
-
-	state->vpll = state->pll;
-	state->vpll2 = state->pll;
-	state->vpllB = state->pllB;
-	state->vpll2B = state->pllB;
-
-	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
-	state->fifo = VGA_RD08(par->PCIO, 0x03D5) & ~(1<<5);
-
-	if (par->CRTCnumber) {
-		state->head = NV_RD32(par->PCRTC0, 0x00000860) & ~0x00001000;
-		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) | 0x00001000;
-		state->crtcOwner = 3;
-		state->pllsel |= 0x20000800;
-		state->vpll = NV_RD32(par->PRAMDAC0, 0x00000508);
-		if (par->twoStagePLL)
-			state->vpllB = NV_RD32(par->PRAMDAC0, 0x00000578);
-	} else if (par->twoHeads) {
-		state->head = NV_RD32(par->PCRTC0, 0x00000860) | 0x00001000;
-		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) & ~0x00001000;
-		state->crtcOwner = 0;
-		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
-		if (par->twoStagePLL)
-			state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
-	}
-
-	state->cursorConfig = 0x00000100;
-
-	if (info->var.vmode & FB_VMODE_DOUBLE)
-		state->cursorConfig |= (1 << 4);
-
-	if (par->alphaCursor) {
-		if ((par->Chipset & 0x0ff0) != 0x0110)
-			state->cursorConfig |= 0x04011000;
-		else
-			state->cursorConfig |= 0x14011000;
-		state->general |= (1 << 29);
-	} else
-		state->cursorConfig |= 0x02000000;
-
-	if (par->twoHeads) {
-		if ((par->Chipset & 0x0ff0) == 0x0110) {
-			state->dither = NV_RD32(par->PRAMDAC, 0x0528) &
-			    ~0x00010000;
-			if (par->FPDither)
-				state->dither |= 0x00010000;
-		} else {
-			state->dither = NV_RD32(par->PRAMDAC, 0x083C) & ~1;
-			if (par->FPDither)
-				state->dither |= 1;
-		}
-	}
-
-	state->timingH = 0;
-	state->timingV = 0;
-	state->displayV = info->var.xres;
-
-	return 0;
-}
-
-static void nvidia_init_vga(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	struct _riva_hw_state *state = &par->ModeReg;
-	int i;
-
-	for (i = 0; i < 0x10; i++)
-		state->attr[i] = i;
-	state->attr[0x10] = 0x41;
-	state->attr[0x11] = 0xff;
-	state->attr[0x12] = 0x0f;
-	state->attr[0x13] = 0x00;
-	state->attr[0x14] = 0x00;
-
-	memset(state->crtc, 0x00, NUM_CRT_REGS);
-	state->crtc[0x0a] = 0x20;
-	state->crtc[0x17] = 0xe3;
-	state->crtc[0x18] = 0xff;
-	state->crtc[0x28] = 0x40;
-
-	memset(state->gra, 0x00, NUM_GRC_REGS);
-	state->gra[0x05] = 0x40;
-	state->gra[0x06] = 0x05;
-	state->gra[0x07] = 0x0f;
-	state->gra[0x08] = 0xff;
-
-	state->seq[0x00] = 0x03;
-	state->seq[0x01] = 0x01;
-	state->seq[0x02] = 0x0f;
-	state->seq[0x03] = 0x00;
-	state->seq[0x04] = 0x0e;
-
-	state->misc_output = 0xeb;
-}
-
-static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct nvidia_par *par = info->par;
-	u8 data[MAX_CURS * MAX_CURS / 8];
-	int i, set = cursor->set;
-	u16 fg, bg;
-
-	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
-		return -ENXIO;
-
-	NVShowHideCursor(par, 0);
-
-	if (par->cursor_reset) {
-		set = FB_CUR_SETALL;
-		par->cursor_reset = 0;
-	}
-
-	if (set & FB_CUR_SETSIZE)
-		memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);
-
-	if (set & FB_CUR_SETPOS) {
-		u32 xx, yy, temp;
-
-		yy = cursor->image.dy - info->var.yoffset;
-		xx = cursor->image.dx - info->var.xoffset;
-		temp = xx & 0xFFFF;
-		temp |= yy << 16;
-
-		NV_WR32(par->PRAMDAC, 0x0000300, temp);
-	}
-
-	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
-		u32 bg_idx = cursor->image.bg_color;
-		u32 fg_idx = cursor->image.fg_color;
-		u32 s_pitch = (cursor->image.width + 7) >> 3;
-		u32 d_pitch = MAX_CURS / 8;
-		u8 *dat = (u8 *) cursor->image.data;
-		u8 *msk = (u8 *) cursor->mask;
-		u8 *src;
-
-		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
-
-		if (src) {
-			switch (cursor->rop) {
-			case ROP_XOR:
-				for (i = 0; i < s_pitch * cursor->image.height; i++)
-					src[i] = dat[i] ^ msk[i];
-				break;
-			case ROP_COPY:
-			default:
-				for (i = 0; i < s_pitch * cursor->image.height; i++)
-					src[i] = dat[i] & msk[i];
-				break;
-			}
-
-			fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
-						cursor->image.height);
-
-			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
-			    ((info->cmap.green[bg_idx] & 0xf8) << 2) |
-			    ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
-
-			fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
-			    ((info->cmap.green[fg_idx] & 0xf8) << 2) |
-			    ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
-
-			NVLockUnlock(par, 0);
-
-			nvidiafb_load_cursor_image(par, data, bg, fg,
-						   cursor->image.width,
-						   cursor->image.height);
-			kfree(src);
-		}
-	}
-
-	if (cursor->enable)
-		NVShowHideCursor(par, 1);
-
-	return 0;
-}
-
-static int nvidiafb_set_par(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-
-	NVTRACE_ENTER();
-
-	NVLockUnlock(par, 1);
-	if (!par->FlatPanel || !par->twoHeads)
-		par->FPDither = 0;
-
-	if (par->FPDither < 0) {
-		if ((par->Chipset & 0x0ff0) == 0x0110)
-			par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528)
-					   & 0x00010000);
-		else
-			par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1);
-		printk(KERN_INFO PFX "Flat panel dithering %s\n",
-		       par->FPDither ? "enabled" : "disabled");
-	}
-
-	info->fix.visual = (info->var.bits_per_pixel == 8) ?
-	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
-	nvidia_init_vga(info);
-	nvidia_calc_regs(info);
-
-	NVLockUnlock(par, 0);
-	if (par->twoHeads) {
-		VGA_WR08(par->PCIO, 0x03D4, 0x44);
-		VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);
-		NVLockUnlock(par, 0);
-	}
-
-	nvidia_screen_off(par, 1);
-
-	nvidia_write_regs(par, &par->ModeReg);
-	NVSetStartAddress(par, 0);
-
-#if defined (__BIG_ENDIAN)
-	/* turn on LFB swapping */
-	{
-		unsigned char tmp;
-
-		VGA_WR08(par->PCIO, 0x3d4, 0x46);
-		tmp = VGA_RD08(par->PCIO, 0x3d5);
-		tmp |= (1 << 7);
-		VGA_WR08(par->PCIO, 0x3d5, tmp);
-    }
-#endif
-
-	info->fix.line_length = (info->var.xres_virtual *
-				 info->var.bits_per_pixel) >> 3;
-	if (info->var.accel_flags) {
-		info->fbops->fb_imageblit = nvidiafb_imageblit;
-		info->fbops->fb_fillrect = nvidiafb_fillrect;
-		info->fbops->fb_copyarea = nvidiafb_copyarea;
-		info->fbops->fb_sync = nvidiafb_sync;
-		info->pixmap.scan_align = 4;
-		info->flags &= ~FBINFO_HWACCEL_DISABLED;
-		info->flags |= FBINFO_READS_FAST;
-		NVResetGraphics(info);
-	} else {
-		info->fbops->fb_imageblit = cfb_imageblit;
-		info->fbops->fb_fillrect = cfb_fillrect;
-		info->fbops->fb_copyarea = cfb_copyarea;
-		info->fbops->fb_sync = NULL;
-		info->pixmap.scan_align = 1;
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-		info->flags &= ~FBINFO_READS_FAST;
-	}
-
-	par->cursor_reset = 1;
-
-	nvidia_screen_off(par, 0);
-
-#ifdef CONFIG_BOOTX_TEXT
-	/* Update debug text engine */
-	btext_update_display(info->fix.smem_start,
-			     info->var.xres, info->var.yres,
-			     info->var.bits_per_pixel, info->fix.line_length);
-#endif
-
-	NVLockUnlock(par, 0);
-	NVTRACE_LEAVE();
-	return 0;
-}
-
-static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			      unsigned blue, unsigned transp,
-			      struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	int i;
-
-	NVTRACE_ENTER();
-	if (regno >= (1 << info->var.green.length))
-		return -EINVAL;
-
-	if (info->var.grayscale) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		((u32 *) info->pseudo_palette)[regno] =
-		    (regno << info->var.red.offset) |
-		    (regno << info->var.green.offset) |
-		    (regno << info->var.blue.offset);
-	}
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		/* "transparent" stuff is completely ignored. */
-		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
-		break;
-	case 16:
-		if (info->var.green.length == 5) {
-			for (i = 0; i < 8; i++) {
-				nvidia_write_clut(par, regno * 8 + i, red >> 8,
-						  green >> 8, blue >> 8);
-			}
-		} else {
-			u8 r, g, b;
-
-			if (regno < 32) {
-				for (i = 0; i < 8; i++) {
-					nvidia_write_clut(par, regno * 8 + i,
-							  red >> 8, green >> 8,
-							  blue >> 8);
-				}
-			}
-
-			nvidia_read_clut(par, regno * 4, &r, &g, &b);
-
-			for (i = 0; i < 4; i++)
-				nvidia_write_clut(par, regno * 4 + i, r,
-						  green >> 8, b);
-		}
-		break;
-	case 32:
-		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
-		break;
-	default:
-		/* do nothing */
-		break;
-	}
-
-	NVTRACE_LEAVE();
-	return 0;
-}
-
-static int nvidiafb_check_var(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	int memlen, vramlen, mode_valid = 0;
-	int pitch, err = 0;
-
-	NVTRACE_ENTER();
-
-	var->transp.offset = 0;
-	var->transp.length = 0;
-
-	var->xres &= ~7;
-
-	if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else
-		var->bits_per_pixel = 32;
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:
-		var->green.length = (var->green.length < 6) ? 5 : 6;
-		var->red.length = 5;
-		var->blue.length = 5;
-		var->transp.length = 6 - var->green.length;
-		var->blue.offset = 0;
-		var->green.offset = 5;
-		var->red.offset = 5 + var->green.length;
-		var->transp.offset = (5 + var->red.offset) & 15;
-		break;
-	case 32:		/* RGBA 8888 */
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.length = 8;
-		var->transp.offset = 24;
-		break;
-	}
-
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
-	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
-		mode_valid = 1;
-
-	/* calculate modeline if supported by monitor */
-	if (!mode_valid && info->monspecs.gtf) {
-		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
-			mode_valid = 1;
-	}
-
-	if (!mode_valid) {
-		const struct fb_videomode *mode;
-
-		mode = fb_find_best_mode(var, &info->modelist);
-		if (mode) {
-			fb_videomode_to_var(var, mode);
-			mode_valid = 1;
-		}
-	}
-
-	if (!mode_valid && info->monspecs.modedb_len)
-		return -EINVAL;
-
-	/*
-	 * If we're on a flat panel, check if the mode is outside of the
-	 * panel dimensions. If so, cap it and try for the next best mode
-	 * before bailing out.
-	 */
-	if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
-					      par->fpHeight < var->yres)) {
-		const struct fb_videomode *mode;
-
-		var->xres = par->fpWidth;
-		var->yres = par->fpHeight;
-
-		mode = fb_find_best_mode(var, &info->modelist);
-		if (!mode) {
-			printk(KERN_ERR PFX "mode out of range of flat "
-			       "panel dimensions\n");
-			return -EINVAL;
-		}
-
-		fb_videomode_to_var(var, mode);
-	}
-
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	var->xres_virtual = (var->xres_virtual + 63) & ~63;
-
-	vramlen = info->screen_size;
-	pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
-	memlen = pitch * var->yres_virtual;
-
-	if (memlen > vramlen) {
-		var->yres_virtual = vramlen / pitch;
-
-		if (var->yres_virtual < var->yres) {
-			var->yres_virtual = var->yres;
-			var->xres_virtual = vramlen / var->yres_virtual;
-			var->xres_virtual /= var->bits_per_pixel / 8;
-			var->xres_virtual &= ~63;
-			pitch = (var->xres_virtual *
-				 var->bits_per_pixel + 7) / 8;
-			memlen = pitch * var->yres;
-
-			if (var->xres_virtual < var->xres) {
-				printk("nvidiafb: required video memory, "
-				       "%d bytes, for %dx%d-%d (virtual) "
-				       "is out of range\n",
-				       memlen, var->xres_virtual,
-				       var->yres_virtual, var->bits_per_pixel);
-				err = -ENOMEM;
-			}
-		}
-	}
-
-	if (var->accel_flags) {
-		if (var->yres_virtual > 0x7fff)
-			var->yres_virtual = 0x7fff;
-		if (var->xres_virtual > 0x7fff)
-			var->xres_virtual = 0x7fff;
-	}
-
-	var->xres_virtual &= ~63;
-
-	NVTRACE_LEAVE();
-
-	return err;
-}
-
-static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	u32 total;
-
-	total = var->yoffset * info->fix.line_length + var->xoffset;
-
-	NVSetStartAddress(par, total);
-
-	return 0;
-}
-
-static int nvidiafb_blank(int blank, struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	unsigned char tmp, vesa;
-
-	tmp = NVReadSeq(par, 0x01) & ~0x20;	/* screen on/off */
-	vesa = NVReadCrtc(par, 0x1a) & ~0xc0;	/* sync on/off */
-
-	NVTRACE_ENTER();
-
-	if (blank)
-		tmp |= 0x20;
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		vesa |= 0x80;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		vesa |= 0x40;
-		break;
-	case FB_BLANK_POWERDOWN:
-		vesa |= 0xc0;
-		break;
-	}
-
-	NVWriteSeq(par, 0x01, tmp);
-	NVWriteCrtc(par, 0x1a, vesa);
-
-	NVTRACE_LEAVE();
-
-	return 0;
-}
-
-/*
- * Because the VGA registers are not mapped linearly in its MMIO space,
- * restrict VGA register saving and restore to x86 only, where legacy VGA IO
- * access is legal. Consequently, we must also check if the device is the
- * primary display.
- */
-#ifdef CONFIG_X86
-static void save_vga_x86(struct nvidia_par *par)
-{
-	struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
-
-	if (res && res->flags & IORESOURCE_ROM_SHADOW) {
-		memset(&par->vgastate, 0, sizeof(par->vgastate));
-		par->vgastate.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS |
-			VGA_SAVE_CMAP;
-		save_vga(&par->vgastate);
-	}
-}
-
-static void restore_vga_x86(struct nvidia_par *par)
-{
-	struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
-
-	if (res && res->flags & IORESOURCE_ROM_SHADOW)
-		restore_vga(&par->vgastate);
-}
-#else
-#define save_vga_x86(x) do {} while (0)
-#define restore_vga_x86(x) do {} while (0)
-#endif /* X86 */
-
-static int nvidiafb_open(struct fb_info *info, int user)
-{
-	struct nvidia_par *par = info->par;
-
-	if (!par->open_count) {
-		save_vga_x86(par);
-		nvidia_save_vga(par, &par->initial_state);
-	}
-
-	par->open_count++;
-	return 0;
-}
-
-static int nvidiafb_release(struct fb_info *info, int user)
-{
-	struct nvidia_par *par = info->par;
-	int err = 0;
-
-	if (!par->open_count) {
-		err = -EINVAL;
-		goto done;
-	}
-
-	if (par->open_count == 1) {
-		nvidia_write_regs(par, &par->initial_state);
-		restore_vga_x86(par);
-	}
-
-	par->open_count--;
-done:
-	return err;
-}
-
-static struct fb_ops nvidia_fb_ops = {
-	.owner          = THIS_MODULE,
-	.fb_open        = nvidiafb_open,
-	.fb_release     = nvidiafb_release,
-	.fb_check_var   = nvidiafb_check_var,
-	.fb_set_par     = nvidiafb_set_par,
-	.fb_setcolreg   = nvidiafb_setcolreg,
-	.fb_pan_display = nvidiafb_pan_display,
-	.fb_blank       = nvidiafb_blank,
-	.fb_fillrect    = nvidiafb_fillrect,
-	.fb_copyarea    = nvidiafb_copyarea,
-	.fb_imageblit   = nvidiafb_imageblit,
-	.fb_cursor      = nvidiafb_cursor,
-	.fb_sync        = nvidiafb_sync,
-};
-
-#ifdef CONFIG_PM
-static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t mesg)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct nvidia_par *par = info->par;
-
-	if (mesg.event == PM_EVENT_PRETHAW)
-		mesg.event = PM_EVENT_FREEZE;
-	console_lock();
-	par->pm_state = mesg.event;
-
-	if (mesg.event & PM_EVENT_SLEEP) {
-		fb_set_suspend(info, 1);
-		nvidiafb_blank(FB_BLANK_POWERDOWN, info);
-		nvidia_write_regs(par, &par->SavedReg);
-		pci_save_state(dev);
-		pci_disable_device(dev);
-		pci_set_power_state(dev, pci_choose_state(dev, mesg));
-	}
-	dev->dev.power.power_state = mesg;
-
-	console_unlock();
-	return 0;
-}
-
-static int nvidiafb_resume(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct nvidia_par *par = info->par;
-
-	console_lock();
-	pci_set_power_state(dev, PCI_D0);
-
-	if (par->pm_state != PM_EVENT_FREEZE) {
-		pci_restore_state(dev);
-
-		if (pci_enable_device(dev))
-			goto fail;
-
-		pci_set_master(dev);
-	}
-
-	par->pm_state = PM_EVENT_ON;
-	nvidiafb_set_par(info);
-	fb_set_suspend (info, 0);
-	nvidiafb_blank(FB_BLANK_UNBLANK, info);
-
-fail:
-	console_unlock();
-	return 0;
-}
-#else
-#define nvidiafb_suspend NULL
-#define nvidiafb_resume NULL
-#endif
-
-static int nvidia_set_fbinfo(struct fb_info *info)
-{
-	struct fb_monspecs *specs = &info->monspecs;
-	struct fb_videomode modedb;
-	struct nvidia_par *par = info->par;
-	int lpitch;
-
-	NVTRACE_ENTER();
-	info->flags = FBINFO_DEFAULT
-	    | FBINFO_HWACCEL_IMAGEBLIT
-	    | FBINFO_HWACCEL_FILLRECT
-	    | FBINFO_HWACCEL_COPYAREA
-	    | FBINFO_HWACCEL_YPAN;
-
-	fb_videomode_to_modelist(info->monspecs.modedb,
-				 info->monspecs.modedb_len, &info->modelist);
-	fb_var_to_videomode(&modedb, &nvidiafb_default_var);
-
-	switch (bpp) {
-	case 0 ... 8:
-		bpp = 8;
-		break;
-	case 9 ... 16:
-		bpp = 16;
-		break;
-	default:
-		bpp = 32;
-		break;
-	}
-
-	if (specs->modedb != NULL) {
-		const struct fb_videomode *mode;
-
-		mode = fb_find_best_display(specs, &info->modelist);
-		fb_videomode_to_var(&nvidiafb_default_var, mode);
-		nvidiafb_default_var.bits_per_pixel = bpp;
-	} else if (par->fpWidth && par->fpHeight) {
-		char buf[16];
-
-		memset(buf, 0, 16);
-		snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
-		fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
-			     specs->modedb_len, &modedb, bpp);
-	}
-
-	if (mode_option)
-		fb_find_mode(&nvidiafb_default_var, info, mode_option,
-			     specs->modedb, specs->modedb_len, &modedb, bpp);
-
-	info->var = nvidiafb_default_var;
-	info->fix.visual = (info->var.bits_per_pixel == 8) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-	info->pseudo_palette = par->pseudo_palette;
-	fb_alloc_cmap(&info->cmap, 256, 0);
-	fb_destroy_modedb(info->monspecs.modedb);
-	info->monspecs.modedb = NULL;
-
-	/* maximize virtual vertical length */
-	lpitch = info->var.xres_virtual *
-		((info->var.bits_per_pixel + 7) >> 3);
-	info->var.yres_virtual = info->screen_size / lpitch;
-
-	info->pixmap.scan_align = 4;
-	info->pixmap.buf_align = 4;
-	info->pixmap.access_align = 32;
-	info->pixmap.size = 8 * 1024;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-	if (!hwcur)
-	    info->fbops->fb_cursor = NULL;
-
-	info->var.accel_flags = (!noaccel);
-
-	switch (par->Architecture) {
-	case NV_ARCH_04:
-		info->fix.accel = FB_ACCEL_NV4;
-		break;
-	case NV_ARCH_10:
-		info->fix.accel = FB_ACCEL_NV_10;
-		break;
-	case NV_ARCH_20:
-		info->fix.accel = FB_ACCEL_NV_20;
-		break;
-	case NV_ARCH_30:
-		info->fix.accel = FB_ACCEL_NV_30;
-		break;
-	case NV_ARCH_40:
-		info->fix.accel = FB_ACCEL_NV_40;
-		break;
-	}
-
-	NVTRACE_LEAVE();
-
-	return nvidiafb_check_var(&info->var, info);
-}
-
-static u32 nvidia_get_chipset(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
-
-	printk(KERN_INFO PFX "Device ID: %x \n", id);
-
-	if ((id & 0xfff0) == 0x00f0 ||
-	    (id & 0xfff0) == 0x02e0) {
-		/* pci-e */
-		id = NV_RD32(par->REGS, 0x1800);
-
-		if ((id & 0x0000ffff) == 0x000010DE)
-			id = 0x10DE0000 | (id >> 16);
-		else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
-			id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
-                            ((id >> 8) & 0x000000ff);
-		printk(KERN_INFO PFX "Subsystem ID: %x \n", id);
-	}
-
-	return id;
-}
-
-static u32 nvidia_get_arch(struct fb_info *info)
-{
-	struct nvidia_par *par = info->par;
-	u32 arch = 0;
-
-	switch (par->Chipset & 0x0ff0) {
-	case 0x0100:		/* GeForce 256 */
-	case 0x0110:		/* GeForce2 MX */
-	case 0x0150:		/* GeForce2 */
-	case 0x0170:		/* GeForce4 MX */
-	case 0x0180:		/* GeForce4 MX (8x AGP) */
-	case 0x01A0:		/* nForce */
-	case 0x01F0:		/* nForce2 */
-		arch = NV_ARCH_10;
-		break;
-	case 0x0200:		/* GeForce3 */
-	case 0x0250:		/* GeForce4 Ti */
-	case 0x0280:		/* GeForce4 Ti (8x AGP) */
-		arch = NV_ARCH_20;
-		break;
-	case 0x0300:		/* GeForceFX 5800 */
-	case 0x0310:		/* GeForceFX 5600 */
-	case 0x0320:		/* GeForceFX 5200 */
-	case 0x0330:		/* GeForceFX 5900 */
-	case 0x0340:		/* GeForceFX 5700 */
-		arch = NV_ARCH_30;
-		break;
-	case 0x0040:		/* GeForce 6800 */
-	case 0x00C0:		/* GeForce 6800 */
-	case 0x0120:		/* GeForce 6800 */
-	case 0x0140:		/* GeForce 6600 */
-	case 0x0160:		/* GeForce 6200 */
-	case 0x01D0:		/* GeForce 7200, 7300, 7400 */
-	case 0x0090:		/* GeForce 7800 */
-	case 0x0210:		/* GeForce 6800 */
-	case 0x0220:		/* GeForce 6200 */
-	case 0x0240:		/* GeForce 6100 */
-	case 0x0290:		/* GeForce 7900 */
-	case 0x0390:		/* GeForce 7600 */
-	case 0x03D0:
-		arch = NV_ARCH_40;
-		break;
-	case 0x0020:		/* TNT, TNT2 */
-		arch = NV_ARCH_04;
-		break;
-	default:		/* unknown architecture */
-		break;
-	}
-
-	return arch;
-}
-
-static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
-{
-	struct nvidia_par *par;
-	struct fb_info *info;
-	unsigned short cmd;
-
-
-	NVTRACE_ENTER();
-	assert(pd != NULL);
-
-	info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
-
-	if (!info)
-		goto err_out;
-
-	par = info->par;
-	par->pci_dev = pd;
-	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
-
-	if (info->pixmap.addr == NULL)
-		goto err_out_kfree;
-
-	if (pci_enable_device(pd)) {
-		printk(KERN_ERR PFX "cannot enable PCI device\n");
-		goto err_out_enable;
-	}
-
-	if (pci_request_regions(pd, "nvidiafb")) {
-		printk(KERN_ERR PFX "cannot request PCI regions\n");
-		goto err_out_enable;
-	}
-
-	par->FlatPanel = flatpanel;
-	if (flatpanel == 1)
-		printk(KERN_INFO PFX "flatpanel support enabled\n");
-	par->FPDither = fpdither;
-
-	par->CRTCnumber = forceCRTC;
-	par->FpScale = (!noscale);
-	par->paneltweak = paneltweak;
-	par->reverse_i2c = reverse_i2c;
-
-	/* enable IO and mem if not already done */
-	pci_read_config_word(pd, PCI_COMMAND, &cmd);
-	cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-	pci_write_config_word(pd, PCI_COMMAND, cmd);
-
-	nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
-	nvidiafb_fix.smem_start = pci_resource_start(pd, 1);
-	nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
-
-	par->REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
-
-	if (!par->REGS) {
-		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
-		goto err_out_free_base0;
-	}
-
-	par->Chipset = nvidia_get_chipset(info);
-	par->Architecture = nvidia_get_arch(info);
-
-	if (par->Architecture == 0) {
-		printk(KERN_ERR PFX "unknown NV_ARCH\n");
-		goto err_out_arch;
-	}
-
-	sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
-
-	if (NVCommonSetup(info))
-		goto err_out_arch;
-
-	par->FbAddress = nvidiafb_fix.smem_start;
-	par->FbMapSize = par->RamAmountKBytes * 1024;
-	if (vram && vram * 1024 * 1024 < par->FbMapSize)
-		par->FbMapSize = vram * 1024 * 1024;
-
-	/* Limit amount of vram to 64 MB */
-	if (par->FbMapSize > 64 * 1024 * 1024)
-		par->FbMapSize = 64 * 1024 * 1024;
-
-	if(par->Architecture >= NV_ARCH_40)
-  	        par->FbUsableSize = par->FbMapSize - (560 * 1024);
-	else
-		par->FbUsableSize = par->FbMapSize - (128 * 1024);
-	par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
-	    16 * 1024;
-	par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
-	par->CursorStart = par->FbUsableSize + (32 * 1024);
-
-	info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
-	info->screen_size = par->FbUsableSize;
-	nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
-
-	if (!info->screen_base) {
-		printk(KERN_ERR PFX "cannot ioremap FB base\n");
-		goto err_out_free_base1;
-	}
-
-	par->FbStart = info->screen_base;
-
-#ifdef CONFIG_MTRR
-	if (!nomtrr) {
-		par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
-					  par->RamAmountKBytes * 1024,
-					  MTRR_TYPE_WRCOMB, 1);
-		if (par->mtrr.vram < 0) {
-			printk(KERN_ERR PFX "unable to setup MTRR\n");
-		} else {
-			par->mtrr.vram_valid = 1;
-			/* let there be speed */
-			printk(KERN_INFO PFX "MTRR set to ON\n");
-		}
-	}
-#endif				/* CONFIG_MTRR */
-
-	info->fbops = &nvidia_fb_ops;
-	info->fix = nvidiafb_fix;
-
-	if (nvidia_set_fbinfo(info) < 0) {
-		printk(KERN_ERR PFX "error setting initial video mode\n");
-		goto err_out_iounmap_fb;
-	}
-
-	nvidia_save_vga(par, &par->SavedReg);
-
-	pci_set_drvdata(pd, info);
-
-	if (backlight)
-		nvidia_bl_init(par);
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
-		goto err_out_iounmap_fb;
-	}
-
-
-	printk(KERN_INFO PFX
-	       "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
-	       info->fix.id,
-	       par->FbMapSize / (1024 * 1024), info->fix.smem_start);
-
-	NVTRACE_LEAVE();
-	return 0;
-
-err_out_iounmap_fb:
-	iounmap(info->screen_base);
-err_out_free_base1:
-	fb_destroy_modedb(info->monspecs.modedb);
-	nvidia_delete_i2c_busses(par);
-err_out_arch:
-	iounmap(par->REGS);
- err_out_free_base0:
-	pci_release_regions(pd);
-err_out_enable:
-	kfree(info->pixmap.addr);
-err_out_kfree:
-	framebuffer_release(info);
-err_out:
-	return -ENODEV;
-}
-
-static void nvidiafb_remove(struct pci_dev *pd)
-{
-	struct fb_info *info = pci_get_drvdata(pd);
-	struct nvidia_par *par = info->par;
-
-	NVTRACE_ENTER();
-
-	unregister_framebuffer(info);
-
-	nvidia_bl_exit(par);
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr.vram_valid)
-		mtrr_del(par->mtrr.vram, info->fix.smem_start,
-			 info->fix.smem_len);
-#endif				/* CONFIG_MTRR */
-
-	iounmap(info->screen_base);
-	fb_destroy_modedb(info->monspecs.modedb);
-	nvidia_delete_i2c_busses(par);
-	iounmap(par->REGS);
-	pci_release_regions(pd);
-	kfree(info->pixmap.addr);
-	framebuffer_release(info);
-	NVTRACE_LEAVE();
-}
-
-/* ------------------------------------------------------------------------- *
- *
- * initialization
- *
- * ------------------------------------------------------------------------- */
-
-#ifndef MODULE
-static int nvidiafb_setup(char *options)
-{
-	char *this_opt;
-
-	NVTRACE_ENTER();
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "forceCRTC", 9)) {
-			char *p;
-
-			p = this_opt + 9;
-			if (!*p || !*(++p))
-				continue;
-			forceCRTC = *p - '0';
-			if (forceCRTC < 0 || forceCRTC > 1)
-				forceCRTC = -1;
-		} else if (!strncmp(this_opt, "flatpanel", 9)) {
-			flatpanel = 1;
-		} else if (!strncmp(this_opt, "hwcur", 5)) {
-			hwcur = 1;
-		} else if (!strncmp(this_opt, "noaccel", 6)) {
-			noaccel = 1;
-		} else if (!strncmp(this_opt, "noscale", 7)) {
-			noscale = 1;
-		} else if (!strncmp(this_opt, "reverse_i2c", 11)) {
-			reverse_i2c = 1;
-		} else if (!strncmp(this_opt, "paneltweak:", 11)) {
-			paneltweak = simple_strtoul(this_opt+11, NULL, 0);
-		} else if (!strncmp(this_opt, "vram:", 5)) {
-			vram = simple_strtoul(this_opt+5, NULL, 0);
-		} else if (!strncmp(this_opt, "backlight:", 10)) {
-			backlight = simple_strtoul(this_opt+10, NULL, 0);
-#ifdef CONFIG_MTRR
-		} else if (!strncmp(this_opt, "nomtrr", 6)) {
-			nomtrr = true;
-#endif
-		} else if (!strncmp(this_opt, "fpdither:", 9)) {
-			fpdither = simple_strtol(this_opt+9, NULL, 0);
-		} else if (!strncmp(this_opt, "bpp:", 4)) {
-			bpp = simple_strtoul(this_opt+4, NULL, 0);
-		} else
-			mode_option = this_opt;
-	}
-	NVTRACE_LEAVE();
-	return 0;
-}
-#endif				/* !MODULE */
-
-static struct pci_driver nvidiafb_driver = {
-	.name = "nvidiafb",
-	.id_table = nvidiafb_pci_tbl,
-	.probe    = nvidiafb_probe,
-	.suspend  = nvidiafb_suspend,
-	.resume   = nvidiafb_resume,
-	.remove   = nvidiafb_remove,
-};
-
-/* ------------------------------------------------------------------------- *
- *
- * modularization
- *
- * ------------------------------------------------------------------------- */
-
-static int nvidiafb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("nvidiafb", &option))
-		return -ENODEV;
-	nvidiafb_setup(option);
-#endif
-	return pci_register_driver(&nvidiafb_driver);
-}
-
-module_init(nvidiafb_init);
-
-static void __exit nvidiafb_exit(void)
-{
-	pci_unregister_driver(&nvidiafb_driver);
-}
-
-module_exit(nvidiafb_exit);
-
-module_param(flatpanel, int, 0);
-MODULE_PARM_DESC(flatpanel,
-		 "Enables experimental flat panel support for some chipsets. "
-		 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
-module_param(fpdither, int, 0);
-MODULE_PARM_DESC(fpdither,
-		 "Enables dithering of flat panel for 6 bits panels. "
-		 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
-module_param(hwcur, int, 0);
-MODULE_PARM_DESC(hwcur,
-		 "Enables hardware cursor implementation. (0 or 1=enabled) "
-		 "(default=0)");
-module_param(noaccel, int, 0);
-MODULE_PARM_DESC(noaccel,
-		 "Disables hardware acceleration. (0 or 1=disable) "
-		 "(default=0)");
-module_param(noscale, int, 0);
-MODULE_PARM_DESC(noscale,
-		 "Disables screen scaleing. (0 or 1=disable) "
-		 "(default=0, do scaling)");
-module_param(paneltweak, int, 0);
-MODULE_PARM_DESC(paneltweak,
-		 "Tweak display settings for flatpanels. "
-		 "(default=0, no tweaks)");
-module_param(forceCRTC, int, 0);
-MODULE_PARM_DESC(forceCRTC,
-		 "Forces usage of a particular CRTC in case autodetection "
-		 "fails. (0 or 1) (default=autodetect)");
-module_param(vram, int, 0);
-MODULE_PARM_DESC(vram,
-		 "amount of framebuffer memory to remap in MiB"
-		 "(default=0 - remap entire memory)");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Specify initial video mode");
-module_param(bpp, int, 0);
-MODULE_PARM_DESC(bpp, "pixel width in bits"
-		 "(default=8)");
-module_param(reverse_i2c, int, 0);
-MODULE_PARM_DESC(reverse_i2c, "reverse port assignment of the i2c bus");
-#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, false);
-MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
-		 "(default=0)");
-#endif
-
-MODULE_AUTHOR("Antonino Daplas");
-MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/ocfb.c b/drivers/video/ocfb.c
deleted file mode 100644
index 7f9dc9bec309..000000000000
--- a/drivers/video/ocfb.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * OpenCores VGA/LCD 2.0 core frame buffer driver
- *
- * Copyright (C) 2013 Stefan Kristiansson, stefan.kristiansson@saunalahti.fi
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-/* OCFB register defines */
-#define OCFB_CTRL	0x000
-#define OCFB_STAT	0x004
-#define OCFB_HTIM	0x008
-#define OCFB_VTIM	0x00c
-#define OCFB_HVLEN	0x010
-#define OCFB_VBARA	0x014
-#define OCFB_PALETTE	0x800
-
-#define OCFB_CTRL_VEN	0x00000001 /* Video Enable */
-#define OCFB_CTRL_HIE	0x00000002 /* HSync Interrupt Enable */
-#define OCFB_CTRL_PC	0x00000800 /* 8-bit Pseudo Color Enable*/
-#define OCFB_CTRL_CD8	0x00000000 /* Color Depth 8 */
-#define OCFB_CTRL_CD16	0x00000200 /* Color Depth 16 */
-#define OCFB_CTRL_CD24	0x00000400 /* Color Depth 24 */
-#define OCFB_CTRL_CD32	0x00000600 /* Color Depth 32 */
-#define OCFB_CTRL_VBL1	0x00000000 /* Burst Length 1 */
-#define OCFB_CTRL_VBL2	0x00000080 /* Burst Length 2 */
-#define OCFB_CTRL_VBL4	0x00000100 /* Burst Length 4 */
-#define OCFB_CTRL_VBL8	0x00000180 /* Burst Length 8 */
-
-#define PALETTE_SIZE	256
-
-#define OCFB_NAME	"OC VGA/LCD"
-
-static char *mode_option;
-
-static const struct fb_videomode default_mode = {
-	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
-	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
-
-struct ocfb_dev {
-	struct fb_info info;
-	void __iomem *regs;
-	/* flag indicating whether the regs are little endian accessed */
-	int little_endian;
-	/* Physical and virtual addresses of framebuffer */
-	phys_addr_t fb_phys;
-	void __iomem *fb_virt;
-	u32 pseudo_palette[PALETTE_SIZE];
-};
-
-#ifndef MODULE
-static int __init ocfb_setup(char *options)
-{
-	char *curr_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((curr_opt = strsep(&options, ",")) != NULL) {
-		if (!*curr_opt)
-			continue;
-		mode_option = curr_opt;
-	}
-
-	return 0;
-}
-#endif
-
-static inline u32 ocfb_readreg(struct ocfb_dev *fbdev, loff_t offset)
-{
-	if (fbdev->little_endian)
-		return ioread32(fbdev->regs + offset);
-	else
-		return ioread32be(fbdev->regs + offset);
-}
-
-static void ocfb_writereg(struct ocfb_dev *fbdev, loff_t offset, u32 data)
-{
-	if (fbdev->little_endian)
-		iowrite32(data, fbdev->regs + offset);
-	else
-		iowrite32be(data, fbdev->regs + offset);
-}
-
-static int ocfb_setupfb(struct ocfb_dev *fbdev)
-{
-	unsigned long bpp_config;
-	struct fb_var_screeninfo *var = &fbdev->info.var;
-	struct device *dev = fbdev->info.device;
-	u32 hlen;
-	u32 vlen;
-
-	/* Disable display */
-	ocfb_writereg(fbdev, OCFB_CTRL, 0);
-
-	/* Register framebuffer address */
-	fbdev->little_endian = 0;
-	ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys);
-
-	/* Detect endianess */
-	if (ocfb_readreg(fbdev, OCFB_VBARA) != fbdev->fb_phys) {
-		fbdev->little_endian = 1;
-		ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys);
-	}
-
-	/* Horizontal timings */
-	ocfb_writereg(fbdev, OCFB_HTIM, (var->hsync_len - 1) << 24 |
-		      (var->right_margin - 1) << 16 | (var->xres - 1));
-
-	/* Vertical timings */
-	ocfb_writereg(fbdev, OCFB_VTIM, (var->vsync_len - 1) << 24 |
-		      (var->lower_margin - 1) << 16 | (var->yres - 1));
-
-	/* Total length of frame */
-	hlen = var->left_margin + var->right_margin + var->hsync_len +
-		var->xres;
-
-	vlen = var->upper_margin + var->lower_margin + var->vsync_len +
-		var->yres;
-
-	ocfb_writereg(fbdev, OCFB_HVLEN, (hlen - 1) << 16 | (vlen - 1));
-
-	bpp_config = OCFB_CTRL_CD8;
-	switch (var->bits_per_pixel) {
-	case 8:
-		if (!var->grayscale)
-			bpp_config |= OCFB_CTRL_PC;  /* enable palette */
-		break;
-
-	case 16:
-		bpp_config |= OCFB_CTRL_CD16;
-		break;
-
-	case 24:
-		bpp_config |= OCFB_CTRL_CD24;
-		break;
-
-	case 32:
-		bpp_config |= OCFB_CTRL_CD32;
-		break;
-
-	default:
-		dev_err(dev, "no bpp specified\n");
-		break;
-	}
-
-	/* maximum (8) VBL (video memory burst length) */
-	bpp_config |= OCFB_CTRL_VBL8;
-
-	/* Enable output */
-	ocfb_writereg(fbdev, OCFB_CTRL, (OCFB_CTRL_VEN | bpp_config));
-
-	return 0;
-}
-
-static int ocfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			  unsigned blue, unsigned transp,
-			  struct fb_info *info)
-{
-	struct ocfb_dev *fbdev = (struct ocfb_dev *)info->par;
-	u32 color;
-
-	if (regno >= info->cmap.len) {
-		dev_err(info->device, "regno >= cmap.len\n");
-		return 1;
-	}
-
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	red >>= (16 - info->var.red.length);
-	green >>= (16 - info->var.green.length);
-	blue >>= (16 - info->var.blue.length);
-	transp >>= (16 - info->var.transp.length);
-
-	if (info->var.bits_per_pixel == 8 && !info->var.grayscale) {
-		regno <<= 2;
-		color = (red << 16) | (green << 8) | blue;
-		ocfb_writereg(fbdev, OCFB_PALETTE + regno, color);
-	} else {
-		((u32 *)(info->pseudo_palette))[regno] =
-			(red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset) |
-			(transp << info->var.transp.offset);
-	}
-
-	return 0;
-}
-
-static int ocfb_init_fix(struct ocfb_dev *fbdev)
-{
-	struct fb_var_screeninfo *var = &fbdev->info.var;
-	struct fb_fix_screeninfo *fix = &fbdev->info.fix;
-
-	strcpy(fix->id, OCFB_NAME);
-
-	fix->line_length = var->xres * var->bits_per_pixel/8;
-	fix->smem_len = fix->line_length * var->yres;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-
-	if (var->bits_per_pixel == 8 && !var->grayscale)
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		fix->visual = FB_VISUAL_TRUECOLOR;
-
-	return 0;
-}
-
-static int ocfb_init_var(struct ocfb_dev *fbdev)
-{
-	struct fb_var_screeninfo *var = &fbdev->info.var;
-
-	var->accel_flags = FB_ACCEL_NONE;
-	var->activate = FB_ACTIVATE_NOW;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-
-	case 16:
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length  = 5;
-		break;
-
-	case 24:
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-	}
-
-	return 0;
-}
-
-static struct fb_ops ocfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= ocfb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int ocfb_probe(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct ocfb_dev *fbdev;
-	struct resource *res;
-	int fbsize;
-
-	fbdev = devm_kzalloc(&pdev->dev, sizeof(*fbdev), GFP_KERNEL);
-	if (!fbdev)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, fbdev);
-
-	fbdev->info.fbops = &ocfb_ops;
-	fbdev->info.device = &pdev->dev;
-	fbdev->info.par = fbdev;
-
-	/* Video mode setup */
-	if (!fb_find_mode(&fbdev->info.var, &fbdev->info, mode_option,
-			  NULL, 0, &default_mode, 16)) {
-		dev_err(&pdev->dev, "No valid video modes found\n");
-		return -EINVAL;
-	}
-	ocfb_init_var(fbdev);
-	ocfb_init_fix(fbdev);
-
-	/* Request I/O resource */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "I/O resource request failed\n");
-		return -ENXIO;
-	}
-	res->flags &= ~IORESOURCE_CACHEABLE;
-	fbdev->regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(fbdev->regs))
-		return PTR_ERR(fbdev->regs);
-
-	/* Allocate framebuffer memory */
-	fbsize = fbdev->info.fix.smem_len;
-	fbdev->fb_virt = dma_alloc_coherent(&pdev->dev, PAGE_ALIGN(fbsize),
-					    &fbdev->fb_phys, GFP_KERNEL);
-	if (!fbdev->fb_virt) {
-		dev_err(&pdev->dev,
-			"Frame buffer memory allocation failed\n");
-		return -ENOMEM;
-	}
-	fbdev->info.fix.smem_start = fbdev->fb_phys;
-	fbdev->info.screen_base = fbdev->fb_virt;
-	fbdev->info.pseudo_palette = fbdev->pseudo_palette;
-
-	/* Clear framebuffer */
-	memset_io(fbdev->fb_virt, 0, fbsize);
-
-	/* Setup and enable the framebuffer */
-	ocfb_setupfb(fbdev);
-
-	if (fbdev->little_endian)
-		fbdev->info.flags |= FBINFO_FOREIGN_ENDIAN;
-
-	/* Allocate color map */
-	ret = fb_alloc_cmap(&fbdev->info.cmap, PALETTE_SIZE, 0);
-	if (ret) {
-		dev_err(&pdev->dev, "Color map allocation failed\n");
-		goto err_dma_free;
-	}
-
-	/* Register framebuffer */
-	ret = register_framebuffer(&fbdev->info);
-	if (ret) {
-		dev_err(&pdev->dev, "Framebuffer registration failed\n");
-		goto err_dealloc_cmap;
-	}
-
-	return 0;
-
-err_dealloc_cmap:
-	fb_dealloc_cmap(&fbdev->info.cmap);
-
-err_dma_free:
-	dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbsize), fbdev->fb_virt,
-			  fbdev->fb_phys);
-
-	return ret;
-}
-
-static int ocfb_remove(struct platform_device *pdev)
-{
-	struct ocfb_dev *fbdev = platform_get_drvdata(pdev);
-
-	unregister_framebuffer(&fbdev->info);
-	fb_dealloc_cmap(&fbdev->info.cmap);
-	dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbdev->info.fix.smem_len),
-			  fbdev->fb_virt, fbdev->fb_phys);
-
-	/* Disable display */
-	ocfb_writereg(fbdev, OCFB_CTRL, 0);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-static struct of_device_id ocfb_match[] = {
-	{ .compatible = "opencores,ocfb", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ocfb_match);
-
-static struct platform_driver ocfb_driver = {
-	.probe  = ocfb_probe,
-	.remove	= ocfb_remove,
-	.driver = {
-		.name = "ocfb_fb",
-		.of_match_table = ocfb_match,
-	}
-};
-
-/*
- * Init and exit routines
- */
-static int __init ocfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("ocfb", &option))
-		return -ENODEV;
-	ocfb_setup(option);
-#endif
-	return platform_driver_register(&ocfb_driver);
-}
-
-static void __exit ocfb_exit(void)
-{
-	platform_driver_unregister(&ocfb_driver);
-}
-
-module_init(ocfb_init);
-module_exit(ocfb_exit);
-
-MODULE_AUTHOR("Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>");
-MODULE_DESCRIPTION("OpenCores VGA/LCD 2.0 frame buffer driver");
-MODULE_LICENSE("GPL v2");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Video mode ('<xres>x<yres>[-<bpp>][@refresh]')");
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
deleted file mode 100644
index 7d44d669d5b6..000000000000
--- a/drivers/video/offb.c
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- *  linux/drivers/video/offb.c -- Open Firmware based frame buffer device
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This driver is partly based on the PowerMac console driver:
- *
- *	Copyright (C) 1996 Paul Mackerras
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_PPC64
-#include <asm/pci-bridge.h>
-#endif
-
-#ifdef CONFIG_PPC32
-#include <asm/bootx.h>
-#endif
-
-#include "macmodes.h"
-
-/* Supported palette hacks */
-enum {
-	cmap_unknown,
-	cmap_simple,		/* ATI Mach64 */
-	cmap_r128,		/* ATI Rage128 */
-	cmap_M3A,		/* ATI Rage Mobility M3 Head A */
-	cmap_M3B,		/* ATI Rage Mobility M3 Head B */
-	cmap_radeon,		/* ATI Radeon */
-	cmap_gxt2000,		/* IBM GXT2000 */
-	cmap_avivo,		/* ATI R5xx */
-	cmap_qemu,		/* qemu vga */
-};
-
-struct offb_par {
-	volatile void __iomem *cmap_adr;
-	volatile void __iomem *cmap_data;
-	int cmap_type;
-	int blanked;
-};
-
-struct offb_par default_par;
-
-#ifdef CONFIG_PPC32
-extern boot_infos_t *boot_infos;
-#endif
-
-/* Definitions used by the Avivo palette hack */
-#define AVIVO_DC_LUT_RW_SELECT                  0x6480
-#define AVIVO_DC_LUT_RW_MODE                    0x6484
-#define AVIVO_DC_LUT_RW_INDEX                   0x6488
-#define AVIVO_DC_LUT_SEQ_COLOR                  0x648c
-#define AVIVO_DC_LUT_PWL_DATA                   0x6490
-#define AVIVO_DC_LUT_30_COLOR                   0x6494
-#define AVIVO_DC_LUT_READ_PIPE_SELECT           0x6498
-#define AVIVO_DC_LUT_WRITE_EN_MASK              0x649c
-#define AVIVO_DC_LUT_AUTOFILL                   0x64a0
-
-#define AVIVO_DC_LUTA_CONTROL                   0x64c0
-#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE         0x64c4
-#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN        0x64c8
-#define AVIVO_DC_LUTA_BLACK_OFFSET_RED          0x64cc
-#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE         0x64d0
-#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN        0x64d4
-#define AVIVO_DC_LUTA_WHITE_OFFSET_RED          0x64d8
-
-#define AVIVO_DC_LUTB_CONTROL                   0x6cc0
-#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE         0x6cc4
-#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN        0x6cc8
-#define AVIVO_DC_LUTB_BLACK_OFFSET_RED          0x6ccc
-#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE         0x6cd0
-#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4
-#define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8
-
-#define FB_RIGHT_POS(p, bpp)         (fb_be_math(p) ? 0 : (32 - (bpp)))
-
-static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value)
-{
-	u32 bpp = info->var.bits_per_pixel;
-
-	return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp);
-}
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			  u_int transp, struct fb_info *info)
-{
-	struct offb_par *par = (struct offb_par *) info->par;
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 *pal = info->pseudo_palette;
-		u32 cr = red >> (16 - info->var.red.length);
-		u32 cg = green >> (16 - info->var.green.length);
-		u32 cb = blue >> (16 - info->var.blue.length);
-		u32 value;
-
-		if (regno >= 16)
-			return -EINVAL;
-
-		value = (cr << info->var.red.offset) |
-			(cg << info->var.green.offset) |
-			(cb << info->var.blue.offset);
-		if (info->var.transp.length > 0) {
-			u32 mask = (1 << info->var.transp.length) - 1;
-			mask <<= info->var.transp.offset;
-			value |= mask;
-		}
-		pal[regno] = offb_cmap_byteswap(info, value);
-		return 0;
-	}
-
-	if (regno > 255)
-		return -EINVAL;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	if (!par->cmap_adr)
-		return 0;
-
-	switch (par->cmap_type) {
-	case cmap_simple:
-		writeb(regno, par->cmap_adr);
-		writeb(red, par->cmap_data);
-		writeb(green, par->cmap_data);
-		writeb(blue, par->cmap_data);
-		break;
-	case cmap_M3A:
-		/* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
-		out_le32(par->cmap_adr + 0x58,
-			 in_le32(par->cmap_adr + 0x58) & ~0x20);
-	case cmap_r128:
-		/* Set palette index & data */
-		out_8(par->cmap_adr + 0xb0, regno);
-		out_le32(par->cmap_adr + 0xb4,
-			 (red << 16 | green << 8 | blue));
-		break;
-	case cmap_M3B:
-		/* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
-		out_le32(par->cmap_adr + 0x58,
-			 in_le32(par->cmap_adr + 0x58) | 0x20);
-		/* Set palette index & data */
-		out_8(par->cmap_adr + 0xb0, regno);
-		out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue));
-		break;
-	case cmap_radeon:
-		/* Set palette index & data (could be smarter) */
-		out_8(par->cmap_adr + 0xb0, regno);
-		out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue));
-		break;
-	case cmap_gxt2000:
-		out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
-			 (red << 16 | green << 8 | blue));
-		break;
-	case cmap_avivo:
-		/* Write to both LUTs for now */
-		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
-		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
-		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
-		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
-		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
-		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
-		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
-		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
-		break;
-	}
-
-	return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static int offb_blank(int blank, struct fb_info *info)
-{
-	struct offb_par *par = (struct offb_par *) info->par;
-	int i, j;
-
-	if (!par->cmap_adr)
-		return 0;
-
-	if (!par->blanked)
-		if (!blank)
-			return 0;
-
-	par->blanked = blank;
-
-	if (blank)
-		for (i = 0; i < 256; i++) {
-			switch (par->cmap_type) {
-			case cmap_simple:
-				writeb(i, par->cmap_adr);
-				for (j = 0; j < 3; j++)
-					writeb(0, par->cmap_data);
-				break;
-			case cmap_M3A:
-				/* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
-				out_le32(par->cmap_adr + 0x58,
-					 in_le32(par->cmap_adr + 0x58) & ~0x20);
-			case cmap_r128:
-				/* Set palette index & data */
-				out_8(par->cmap_adr + 0xb0, i);
-				out_le32(par->cmap_adr + 0xb4, 0);
-				break;
-			case cmap_M3B:
-				/* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
-				out_le32(par->cmap_adr + 0x58,
-					 in_le32(par->cmap_adr + 0x58) | 0x20);
-				/* Set palette index & data */
-				out_8(par->cmap_adr + 0xb0, i);
-				out_le32(par->cmap_adr + 0xb4, 0);
-				break;
-			case cmap_radeon:
-				out_8(par->cmap_adr + 0xb0, i);
-				out_le32(par->cmap_adr + 0xb4, 0);
-				break;
-			case cmap_gxt2000:
-				out_le32(((unsigned __iomem *) par->cmap_adr) + i,
-					 0);
-				break;
-			case cmap_avivo:
-				writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
-				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
-				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
-				writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
-				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
-				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
-				break;
-			}
-	} else
-		fb_set_cmap(&info->cmap, info);
-	return 0;
-}
-
-static int offb_set_par(struct fb_info *info)
-{
-	struct offb_par *par = (struct offb_par *) info->par;
-
-	/* On avivo, initialize palette control */
-	if (par->cmap_type == cmap_avivo) {
-		writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);
-		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);
-		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);
-		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);
-		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);
-		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);
-		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);
-		writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);
-		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);
-		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);
-		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);
-		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);
-		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);
-		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);
-		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
-		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
-		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
-		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
-		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
-		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
-	}
-	return 0;
-}
-
-static void offb_destroy(struct fb_info *info)
-{
-	if (info->screen_base)
-		iounmap(info->screen_base);
-	release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
-	framebuffer_release(info);
-}
-
-static struct fb_ops offb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_destroy	= offb_destroy,
-	.fb_setcolreg	= offb_setcolreg,
-	.fb_set_par	= offb_set_par,
-	.fb_blank	= offb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static void __iomem *offb_map_reg(struct device_node *np, int index,
-				  unsigned long offset, unsigned long size)
-{
-	const __be32 *addrp;
-	u64 asize, taddr;
-	unsigned int flags;
-
-	addrp = of_get_pci_address(np, index, &asize, &flags);
-	if (addrp == NULL)
-		addrp = of_get_address(np, index, &asize, &flags);
-	if (addrp == NULL)
-		return NULL;
-	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
-		return NULL;
-	if ((offset + size) > asize)
-		return NULL;
-	taddr = of_translate_address(np, addrp);
-	if (taddr == OF_BAD_ADDR)
-		return NULL;
-	return ioremap(taddr + offset, size);
-}
-
-static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
-				    const char *name, unsigned long address)
-{
-	struct offb_par *par = (struct offb_par *) info->par;
-
-	if (dp && !strncmp(name, "ATY,Rage128", 11)) {
-		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-		if (par->cmap_adr)
-			par->cmap_type = cmap_r128;
-	} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
-			  || !strncmp(name, "ATY,RageM3p12A", 14))) {
-		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-		if (par->cmap_adr)
-			par->cmap_type = cmap_M3A;
-	} else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
-		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-		if (par->cmap_adr)
-			par->cmap_type = cmap_M3B;
-	} else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
-		par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
-		if (par->cmap_adr)
-			par->cmap_type = cmap_radeon;
-	} else if (!strncmp(name, "ATY,", 4)) {
-		unsigned long base = address & 0xff000000UL;
-		par->cmap_adr =
-			ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
-		par->cmap_data = par->cmap_adr + 1;
-		par->cmap_type = cmap_simple;
-	} else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
-			  of_device_is_compatible(dp, "pci1014,21c"))) {
-		par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
-		if (par->cmap_adr)
-			par->cmap_type = cmap_gxt2000;
-	} else if (dp && !strncmp(name, "vga,Display-", 12)) {
-		/* Look for AVIVO initialized by SLOF */
-		struct device_node *pciparent = of_get_parent(dp);
-		const u32 *vid, *did;
-		vid = of_get_property(pciparent, "vendor-id", NULL);
-		did = of_get_property(pciparent, "device-id", NULL);
-		/* This will match most R5xx */
-		if (vid && did && *vid == 0x1002 &&
-		    ((*did >= 0x7100 && *did < 0x7800) ||
-		     (*did >= 0x9400))) {
-			par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_avivo;
-		}
-		of_node_put(pciparent);
-	} else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) {
-#ifdef __BIG_ENDIAN
-		const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
-#else
-		const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 };
-#endif
-		u64 io_addr = of_translate_address(dp, io_of_addr);
-		if (io_addr != OF_BAD_ADDR) {
-			par->cmap_adr = ioremap(io_addr + 0x3c8, 2);
-			if (par->cmap_adr) {
-				par->cmap_type = cmap_simple;
-				par->cmap_data = par->cmap_adr + 1;
-			}
-		}
-	}
-	info->fix.visual = (par->cmap_type != cmap_unknown) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
-}
-
-static void __init offb_init_fb(const char *name, const char *full_name,
-				int width, int height, int depth,
-				int pitch, unsigned long address,
-				int foreign_endian, struct device_node *dp)
-{
-	unsigned long res_size = pitch * height;
-	struct offb_par *par = &default_par;
-	unsigned long res_start = address;
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	struct fb_info *info;
-
-	if (!request_mem_region(res_start, res_size, "offb"))
-		return;
-
-	printk(KERN_INFO
-	       "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
-	       width, height, name, address, depth, pitch);
-	if (depth != 8 && depth != 15 && depth != 16 && depth != 32) {
-		printk(KERN_ERR "%s: can't use depth = %d\n", full_name,
-		       depth);
-		release_mem_region(res_start, res_size);
-		return;
-	}
-
-	info = framebuffer_alloc(sizeof(u32) * 16, NULL);
-	
-	if (info == 0) {
-		release_mem_region(res_start, res_size);
-		return;
-	}
-
-	fix = &info->fix;
-	var = &info->var;
-	info->par = par;
-
-	strcpy(fix->id, "OFfb ");
-	strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
-	fix->id[sizeof(fix->id) - 1] = '\0';
-
-	var->xres = var->xres_virtual = width;
-	var->yres = var->yres_virtual = height;
-	fix->line_length = pitch;
-
-	fix->smem_start = address;
-	fix->smem_len = pitch * height;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-
-	par->cmap_type = cmap_unknown;
-	if (depth == 8)
-		offb_init_palette_hacks(info, dp, name, address);
-	else
-		fix->visual = FB_VISUAL_TRUECOLOR;
-
-	var->xoffset = var->yoffset = 0;
-	switch (depth) {
-	case 8:
-		var->bits_per_pixel = 8;
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 15:		/* RGB 555 */
-		var->bits_per_pixel = 16;
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:		/* RGB 565 */
-		var->bits_per_pixel = 16;
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 32:		/* RGB 888 */
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	}
-	var->red.msb_right = var->green.msb_right = var->blue.msb_right =
-	    var->transp.msb_right = 0;
-	var->grayscale = 0;
-	var->nonstd = 0;
-	var->activate = 0;
-	var->height = var->width = -1;
-	var->pixclock = 10000;
-	var->left_margin = var->right_margin = 16;
-	var->upper_margin = var->lower_margin = 16;
-	var->hsync_len = var->vsync_len = 8;
-	var->sync = 0;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	/* set offb aperture size for generic probing */
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures)
-		goto out_aper;
-	info->apertures->ranges[0].base = address;
-	info->apertures->ranges[0].size = fix->smem_len;
-
-	info->fbops = &offb_ops;
-	info->screen_base = ioremap(address, fix->smem_len);
-	info->pseudo_palette = (void *) (info + 1);
-	info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian;
-
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	if (register_framebuffer(info) < 0)
-		goto out_err;
-
-	fb_info(info, "Open Firmware frame buffer device on %s\n", full_name);
-	return;
-
-out_err:
-	iounmap(info->screen_base);
-out_aper:
-	iounmap(par->cmap_adr);
-	par->cmap_adr = NULL;
-	framebuffer_release(info);
-	release_mem_region(res_start, res_size);
-}
-
-
-static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
-{
-	unsigned int len;
-	int i, width = 640, height = 480, depth = 8, pitch = 640;
-	unsigned int flags, rsize, addr_prop = 0;
-	unsigned long max_size = 0;
-	u64 rstart, address = OF_BAD_ADDR;
-	const __be32 *pp, *addrp, *up;
-	u64 asize;
-	int foreign_endian = 0;
-
-#ifdef __BIG_ENDIAN
-	if (of_get_property(dp, "little-endian", NULL))
-		foreign_endian = FBINFO_FOREIGN_ENDIAN;
-#else
-	if (of_get_property(dp, "big-endian", NULL))
-		foreign_endian = FBINFO_FOREIGN_ENDIAN;
-#endif
-
-	pp = of_get_property(dp, "linux,bootx-depth", &len);
-	if (pp == NULL)
-		pp = of_get_property(dp, "depth", &len);
-	if (pp && len == sizeof(u32))
-		depth = be32_to_cpup(pp);
-
-	pp = of_get_property(dp, "linux,bootx-width", &len);
-	if (pp == NULL)
-		pp = of_get_property(dp, "width", &len);
-	if (pp && len == sizeof(u32))
-		width = be32_to_cpup(pp);
-
-	pp = of_get_property(dp, "linux,bootx-height", &len);
-	if (pp == NULL)
-		pp = of_get_property(dp, "height", &len);
-	if (pp && len == sizeof(u32))
-		height = be32_to_cpup(pp);
-
-	pp = of_get_property(dp, "linux,bootx-linebytes", &len);
-	if (pp == NULL)
-		pp = of_get_property(dp, "linebytes", &len);
-	if (pp && len == sizeof(u32) && (*pp != 0xffffffffu))
-		pitch = be32_to_cpup(pp);
-	else
-		pitch = width * ((depth + 7) / 8);
-
-	rsize = (unsigned long)pitch * (unsigned long)height;
-
-	/* Ok, now we try to figure out the address of the framebuffer.
-	 *
-	 * Unfortunately, Open Firmware doesn't provide a standard way to do
-	 * so. All we can do is a dodgy heuristic that happens to work in
-	 * practice. On most machines, the "address" property contains what
-	 * we need, though not on Matrox cards found in IBM machines. What I've
-	 * found that appears to give good results is to go through the PCI
-	 * ranges and pick one that is both big enough and if possible encloses
-	 * the "address" property. If none match, we pick the biggest
-	 */
-	up = of_get_property(dp, "linux,bootx-addr", &len);
-	if (up == NULL)
-		up = of_get_property(dp, "address", &len);
-	if (up && len == sizeof(u32))
-		addr_prop = *up;
-
-	/* Hack for when BootX is passing us */
-	if (no_real_node)
-		goto skip_addr;
-
-	for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
-		     != NULL; i++) {
-		int match_addrp = 0;
-
-		if (!(flags & IORESOURCE_MEM))
-			continue;
-		if (asize < rsize)
-			continue;
-		rstart = of_translate_address(dp, addrp);
-		if (rstart == OF_BAD_ADDR)
-			continue;
-		if (addr_prop && (rstart <= addr_prop) &&
-		    ((rstart + asize) >= (addr_prop + rsize)))
-			match_addrp = 1;
-		if (match_addrp) {
-			address = addr_prop;
-			break;
-		}
-		if (rsize > max_size) {
-			max_size = rsize;
-			address = OF_BAD_ADDR;
- 		}
-
-		if (address == OF_BAD_ADDR)
-			address = rstart;
-	}
- skip_addr:
-	if (address == OF_BAD_ADDR && addr_prop)
-		address = (u64)addr_prop;
-	if (address != OF_BAD_ADDR) {
-		/* kludge for valkyrie */
-		if (strcmp(dp->name, "valkyrie") == 0)
-			address += 0x1000;
-		offb_init_fb(no_real_node ? "bootx" : dp->name,
-			     no_real_node ? "display" : dp->full_name,
-			     width, height, depth, pitch, address,
-			     foreign_endian, no_real_node ? NULL : dp);
-	}
-}
-
-static int __init offb_init(void)
-{
-	struct device_node *dp = NULL, *boot_disp = NULL;
-
-	if (fb_get_options("offb", NULL))
-		return -ENODEV;
-
-	/* Check if we have a MacOS display without a node spec */
-	if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) {
-		/* The old code tried to work out which node was the MacOS
-		 * display based on the address. I'm dropping that since the
-		 * lack of a node spec only happens with old BootX versions
-		 * (users can update) and with this code, they'll still get
-		 * a display (just not the palette hacks).
-		 */
-		offb_init_nodriver(of_chosen, 1);
-	}
-
-	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-		if (of_get_property(dp, "linux,opened", NULL) &&
-		    of_get_property(dp, "linux,boot-display", NULL)) {
-			boot_disp = dp;
-			offb_init_nodriver(dp, 0);
-		}
-	}
-	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-		if (of_get_property(dp, "linux,opened", NULL) &&
-		    dp != boot_disp)
-			offb_init_nodriver(dp, 0);
-	}
-
-	return 0;
-}
-
-
-module_init(offb_init);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
deleted file mode 100644
index 0bc3a936ce2b..000000000000
--- a/drivers/video/omap/Kconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-config FB_OMAP
-	tristate "OMAP frame buffer support"
-	depends on FB
-	depends on ARCH_OMAP1
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-          Frame buffer driver for OMAP based boards.
-
-config FB_OMAP_LCDC_EXTERNAL
-	bool "External LCD controller support"
-	depends on FB_OMAP
-	help
-	  Say Y here, if you want to have support for boards with an
-	  external LCD controller connected to the SoSSI/RFBI interface.
-
-config FB_OMAP_LCDC_HWA742
-	bool "Epson HWA742 LCD controller support"
-	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
-	help
-	  Say Y here if you want to have support for the external
-	  Epson HWA742 LCD controller.
-
-config FB_OMAP_MANUAL_UPDATE
-	bool "Default to manual update mode"
-	depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
-	help
-	  Say Y here, if your user-space applications are capable of
-	  notifying the frame buffer driver when a change has occurred in
-	  the frame buffer content and thus a reload of the image data to
-	  the external frame buffer is required. If unsure, say N.
-
-config FB_OMAP_LCD_MIPID
-	bool "MIPI DBI-C/DCS compatible LCD support"
-	depends on FB_OMAP && SPI_MASTER
-	help
-	  Say Y here if you want to have support for LCDs compatible with
-	  the Mobile Industry Processor Interface DBI-C/DCS
-	  specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
-
-config FB_OMAP_DMA_TUNE
-        bool "Set DMA SDRAM access priority high"
-        depends on FB_OMAP
-        help
-          On systems in which video memory is in system memory
-          (SDRAM) this will speed up graphics DMA operations.
-          If you have such a system and want to use rotation
-          answer yes. Answer no if you have a dedicated video
-          memory, or don't use any of the accelerated features.
-
-
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
deleted file mode 100644
index 1927faffb5bc..000000000000
--- a/drivers/video/omap/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Makefile for the OMAP1 framebuffer device driver
-#
-
-obj-$(CONFIG_FB_OMAP) += omapfb.o
-
-objs-yy := omapfb_main.o lcdc.o
-
-objs-y$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
-
-objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
-
-objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
-objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
-objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
-objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
-objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o
-objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
-objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
-objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
-
-objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
-objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o
-
-omapfb-objs := $(objs-yy)
-
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
deleted file mode 100644
index a4ee65b8f918..000000000000
--- a/drivers/video/omap/hwa742.c
+++ /dev/null
@@ -1,1059 +0,0 @@
-/*
- * Epson HWA742 LCD controller driver
- *
- * Copyright (C) 2004-2005 Nokia Corporation
- * Authors:     Juha Yrjölä   <juha.yrjola@nokia.com>
- *	        Imre Deak     <imre.deak@nokia.com>
- * YUV support: Jussi Laako   <jussi.laako@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-
-#include "omapfb.h"
-
-#define HWA742_REV_CODE_REG       0x0
-#define HWA742_CONFIG_REG         0x2
-#define HWA742_PLL_DIV_REG        0x4
-#define HWA742_PLL_0_REG          0x6
-#define HWA742_PLL_1_REG          0x8
-#define HWA742_PLL_2_REG          0xa
-#define HWA742_PLL_3_REG          0xc
-#define HWA742_PLL_4_REG          0xe
-#define HWA742_CLK_SRC_REG        0x12
-#define HWA742_PANEL_TYPE_REG     0x14
-#define HWA742_H_DISP_REG         0x16
-#define HWA742_H_NDP_REG          0x18
-#define HWA742_V_DISP_1_REG       0x1a
-#define HWA742_V_DISP_2_REG       0x1c
-#define HWA742_V_NDP_REG          0x1e
-#define HWA742_HS_W_REG           0x20
-#define HWA742_HP_S_REG           0x22
-#define HWA742_VS_W_REG           0x24
-#define HWA742_VP_S_REG           0x26
-#define HWA742_PCLK_POL_REG       0x28
-#define HWA742_INPUT_MODE_REG     0x2a
-#define HWA742_TRANSL_MODE_REG1   0x2e
-#define HWA742_DISP_MODE_REG      0x34
-#define HWA742_WINDOW_TYPE        0x36
-#define HWA742_WINDOW_X_START_0   0x38
-#define HWA742_WINDOW_X_START_1   0x3a
-#define HWA742_WINDOW_Y_START_0   0x3c
-#define HWA742_WINDOW_Y_START_1   0x3e
-#define HWA742_WINDOW_X_END_0     0x40
-#define HWA742_WINDOW_X_END_1     0x42
-#define HWA742_WINDOW_Y_END_0     0x44
-#define HWA742_WINDOW_Y_END_1     0x46
-#define HWA742_MEMORY_WRITE_LSB   0x48
-#define HWA742_MEMORY_WRITE_MSB   0x49
-#define HWA742_MEMORY_READ_0      0x4a
-#define HWA742_MEMORY_READ_1      0x4c
-#define HWA742_MEMORY_READ_2      0x4e
-#define HWA742_POWER_SAVE         0x56
-#define HWA742_NDP_CTRL           0x58
-
-#define HWA742_AUTO_UPDATE_TIME		(HZ / 20)
-
-/* Reserve 4 request slots for requests in irq context */
-#define REQ_POOL_SIZE			24
-#define IRQ_REQ_POOL_SIZE		4
-
-#define REQ_FROM_IRQ_POOL 0x01
-
-#define REQ_COMPLETE	0
-#define REQ_PENDING	1
-
-struct update_param {
-	int	x, y, width, height;
-	int	color_mode;
-	int	flags;
-};
-
-struct hwa742_request {
-	struct list_head entry;
-	unsigned int	 flags;
-
-	int		 (*handler)(struct hwa742_request *req);
-	void		 (*complete)(void *data);
-	void		 *complete_data;
-
-	union {
-		struct update_param	update;
-		struct completion	*sync;
-	} par;
-};
-
-struct {
-	enum omapfb_update_mode	update_mode;
-	enum omapfb_update_mode	update_mode_before_suspend;
-
-	struct timer_list	auto_update_timer;
-	int			stop_auto_update;
-	struct omapfb_update_window	auto_update_window;
-	unsigned		te_connected:1;
-	unsigned		vsync_only:1;
-
-	struct hwa742_request	req_pool[REQ_POOL_SIZE];
-	struct list_head	pending_req_list;
-	struct list_head	free_req_list;
-	struct semaphore	req_sema;
-	spinlock_t		req_lock;
-
-	struct extif_timings	reg_timings, lut_timings;
-
-	int			prev_color_mode;
-	int			prev_flags;
-	int			window_type;
-
-	u32			max_transmit_size;
-	u32			extif_clk_period;
-	unsigned long		pix_tx_time;
-	unsigned long		line_upd_time;
-
-
-	struct omapfb_device	*fbdev;
-	struct lcd_ctrl_extif	*extif;
-	const struct lcd_ctrl	*int_ctrl;
-
-	struct clk		*sys_ck;
-} hwa742;
-
-struct lcd_ctrl hwa742_ctrl;
-
-static u8 hwa742_read_reg(u8 reg)
-{
-	u8 data;
-
-	hwa742.extif->set_bits_per_cycle(8);
-	hwa742.extif->write_command(&reg, 1);
-	hwa742.extif->read_data(&data, 1);
-
-	return data;
-}
-
-static void hwa742_write_reg(u8 reg, u8 data)
-{
-	hwa742.extif->set_bits_per_cycle(8);
-	hwa742.extif->write_command(&reg, 1);
-	hwa742.extif->write_data(&data, 1);
-}
-
-static void set_window_regs(int x_start, int y_start, int x_end, int y_end)
-{
-	u8 tmp[8];
-	u8 cmd;
-
-	x_end--;
-	y_end--;
-	tmp[0] = x_start;
-	tmp[1] = x_start >> 8;
-	tmp[2] = y_start;
-	tmp[3] = y_start >> 8;
-	tmp[4] = x_end;
-	tmp[5] = x_end >> 8;
-	tmp[6] = y_end;
-	tmp[7] = y_end >> 8;
-
-	hwa742.extif->set_bits_per_cycle(8);
-	cmd = HWA742_WINDOW_X_START_0;
-
-	hwa742.extif->write_command(&cmd, 1);
-
-	hwa742.extif->write_data(tmp, 8);
-}
-
-static void set_format_regs(int conv, int transl, int flags)
-{
-	if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
-		hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
-#ifdef VERBOSE
-		dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n");
-#endif
-	} else {
-		hwa742.window_type = (hwa742.window_type & 0xfc);
-#ifdef VERBOSE
-		dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n");
-#endif
-	}
-
-	hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
-	hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl);
-	hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type);
-}
-
-static void enable_tearsync(int y, int width, int height, int screen_height,
-			    int force_vsync)
-{
-	u8 b;
-
-	b = hwa742_read_reg(HWA742_NDP_CTRL);
-	b |= 1 << 2;
-	hwa742_write_reg(HWA742_NDP_CTRL, b);
-
-	if (likely(hwa742.vsync_only || force_vsync)) {
-		hwa742.extif->enable_tearsync(1, 0);
-		return;
-	}
-
-	if (width * hwa742.pix_tx_time < hwa742.line_upd_time) {
-		hwa742.extif->enable_tearsync(1, 0);
-		return;
-	}
-
-	if ((width * hwa742.pix_tx_time / 1000) * height <
-	    (y + height) * (hwa742.line_upd_time / 1000)) {
-		hwa742.extif->enable_tearsync(1, 0);
-		return;
-	}
-
-	hwa742.extif->enable_tearsync(1, y + 1);
-}
-
-static void disable_tearsync(void)
-{
-	u8 b;
-
-	hwa742.extif->enable_tearsync(0, 0);
-
-	b = hwa742_read_reg(HWA742_NDP_CTRL);
-	b &= ~(1 << 2);
-	hwa742_write_reg(HWA742_NDP_CTRL, b);
-}
-
-static inline struct hwa742_request *alloc_req(void)
-{
-	unsigned long flags;
-	struct hwa742_request *req;
-	int req_flags = 0;
-
-	if (!in_interrupt())
-		down(&hwa742.req_sema);
-	else
-		req_flags = REQ_FROM_IRQ_POOL;
-
-	spin_lock_irqsave(&hwa742.req_lock, flags);
-	BUG_ON(list_empty(&hwa742.free_req_list));
-	req = list_entry(hwa742.free_req_list.next,
-			 struct hwa742_request, entry);
-	list_del(&req->entry);
-	spin_unlock_irqrestore(&hwa742.req_lock, flags);
-
-	INIT_LIST_HEAD(&req->entry);
-	req->flags = req_flags;
-
-	return req;
-}
-
-static inline void free_req(struct hwa742_request *req)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hwa742.req_lock, flags);
-
-	list_move(&req->entry, &hwa742.free_req_list);
-	if (!(req->flags & REQ_FROM_IRQ_POOL))
-		up(&hwa742.req_sema);
-
-	spin_unlock_irqrestore(&hwa742.req_lock, flags);
-}
-
-static void process_pending_requests(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hwa742.req_lock, flags);
-
-	while (!list_empty(&hwa742.pending_req_list)) {
-		struct hwa742_request *req;
-		void (*complete)(void *);
-		void *complete_data;
-
-		req = list_entry(hwa742.pending_req_list.next,
-				 struct hwa742_request, entry);
-		spin_unlock_irqrestore(&hwa742.req_lock, flags);
-
-		if (req->handler(req) == REQ_PENDING)
-			return;
-
-		complete = req->complete;
-		complete_data = req->complete_data;
-		free_req(req);
-
-		if (complete)
-			complete(complete_data);
-
-		spin_lock_irqsave(&hwa742.req_lock, flags);
-	}
-
-	spin_unlock_irqrestore(&hwa742.req_lock, flags);
-}
-
-static void submit_req_list(struct list_head *head)
-{
-	unsigned long flags;
-	int process = 1;
-
-	spin_lock_irqsave(&hwa742.req_lock, flags);
-	if (likely(!list_empty(&hwa742.pending_req_list)))
-		process = 0;
-	list_splice_init(head, hwa742.pending_req_list.prev);
-	spin_unlock_irqrestore(&hwa742.req_lock, flags);
-
-	if (process)
-		process_pending_requests();
-}
-
-static void request_complete(void *data)
-{
-	struct hwa742_request	*req = (struct hwa742_request *)data;
-	void			(*complete)(void *);
-	void			*complete_data;
-
-	complete = req->complete;
-	complete_data = req->complete_data;
-
-	free_req(req);
-
-	if (complete)
-		complete(complete_data);
-
-	process_pending_requests();
-}
-
-static int send_frame_handler(struct hwa742_request *req)
-{
-	struct update_param *par = &req->par.update;
-	int x = par->x;
-	int y = par->y;
-	int w = par->width;
-	int h = par->height;
-	int bpp;
-	int conv, transl;
-	unsigned long offset;
-	int color_mode = par->color_mode;
-	int flags = par->flags;
-	int scr_width = hwa742.fbdev->panel->x_res;
-	int scr_height = hwa742.fbdev->panel->y_res;
-
-#ifdef VERBOSE
-	dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d "
-		"color_mode %d flags %d\n",
-		x, y, w, h, scr_width, color_mode, flags);
-#endif
-
-	switch (color_mode) {
-	case OMAPFB_COLOR_YUV422:
-		bpp = 16;
-		conv = 0x08;
-		transl = 0x25;
-		break;
-	case OMAPFB_COLOR_YUV420:
-		bpp = 12;
-		conv = 0x09;
-		transl = 0x25;
-		break;
-	case OMAPFB_COLOR_RGB565:
-		bpp = 16;
-		conv = 0x01;
-		transl = 0x05;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (hwa742.prev_flags != flags ||
-	    hwa742.prev_color_mode != color_mode) {
-		set_format_regs(conv, transl, flags);
-		hwa742.prev_color_mode = color_mode;
-		hwa742.prev_flags = flags;
-	}
-	flags = req->par.update.flags;
-	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
-		enable_tearsync(y, scr_width, h, scr_height,
-				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
-	else
-		disable_tearsync();
-
-	set_window_regs(x, y, x + w, y + h);
-
-	offset = (scr_width * y + x) * bpp / 8;
-
-	hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX,
-			OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h,
-			color_mode);
-
-	hwa742.extif->set_bits_per_cycle(16);
-
-	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
-	hwa742.extif->transfer_area(w, h, request_complete, req);
-
-	return REQ_PENDING;
-}
-
-static void send_frame_complete(void *data)
-{
-	hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
-}
-
-#define ADD_PREQ(_x, _y, _w, _h) do {		\
-	req = alloc_req();			\
-	req->handler	= send_frame_handler;	\
-	req->complete	= send_frame_complete;	\
-	req->par.update.x = _x;			\
-	req->par.update.y = _y;			\
-	req->par.update.width  = _w;		\
-	req->par.update.height = _h;		\
-	req->par.update.color_mode = color_mode;\
-	req->par.update.flags	  = flags;	\
-	list_add_tail(&req->entry, req_head);	\
-} while(0)
-
-static void create_req_list(struct omapfb_update_window *win,
-			    struct list_head *req_head)
-{
-	struct hwa742_request *req;
-	int x = win->x;
-	int y = win->y;
-	int width = win->width;
-	int height = win->height;
-	int color_mode;
-	int flags;
-
-	flags = win->format & ~OMAPFB_FORMAT_MASK;
-	color_mode = win->format & OMAPFB_FORMAT_MASK;
-
-	if (x & 1) {
-		ADD_PREQ(x, y, 1, height);
-		width--;
-		x++;
-		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
-	}
-	if (width & ~1) {
-		unsigned int xspan = width & ~1;
-		unsigned int ystart = y;
-		unsigned int yspan = height;
-
-		if (xspan * height * 2 > hwa742.max_transmit_size) {
-			yspan = hwa742.max_transmit_size / (xspan * 2);
-			ADD_PREQ(x, ystart, xspan, yspan);
-			ystart += yspan;
-			yspan = height - yspan;
-			flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
-		}
-
-		ADD_PREQ(x, ystart, xspan, yspan);
-		x += xspan;
-		width -= xspan;
-		flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
-	}
-	if (width)
-		ADD_PREQ(x, y, 1, height);
-}
-
-static void auto_update_complete(void *data)
-{
-	if (!hwa742.stop_auto_update)
-		mod_timer(&hwa742.auto_update_timer,
-			  jiffies + HWA742_AUTO_UPDATE_TIME);
-}
-
-static void hwa742_update_window_auto(unsigned long arg)
-{
-	LIST_HEAD(req_list);
-	struct hwa742_request *last;
-
-	create_req_list(&hwa742.auto_update_window, &req_list);
-	last = list_entry(req_list.prev, struct hwa742_request, entry);
-
-	last->complete = auto_update_complete;
-	last->complete_data = NULL;
-
-	submit_req_list(&req_list);
-}
-
-int hwa742_update_window_async(struct fb_info *fbi,
-				 struct omapfb_update_window *win,
-				 void (*complete_callback)(void *arg),
-				 void *complete_callback_data)
-{
-	LIST_HEAD(req_list);
-	struct hwa742_request *last;
-	int r = 0;
-
-	if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
-		dev_dbg(hwa742.fbdev->dev, "invalid update mode\n");
-		r = -EINVAL;
-		goto out;
-	}
-	if (unlikely(win->format &
-	    ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE |
-	    OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) {
-		dev_dbg(hwa742.fbdev->dev, "invalid window flag\n");
-		r = -EINVAL;
-		goto out;
-	}
-
-	create_req_list(win, &req_list);
-	last = list_entry(req_list.prev, struct hwa742_request, entry);
-
-	last->complete = complete_callback;
-	last->complete_data = (void *)complete_callback_data;
-
-	submit_req_list(&req_list);
-
-out:
-	return r;
-}
-EXPORT_SYMBOL(hwa742_update_window_async);
-
-static int hwa742_setup_plane(int plane, int channel_out,
-				  unsigned long offset, int screen_width,
-				  int pos_x, int pos_y, int width, int height,
-				  int color_mode)
-{
-	if (plane != OMAPFB_PLANE_GFX ||
-	    channel_out != OMAPFB_CHANNEL_OUT_LCD)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int hwa742_enable_plane(int plane, int enable)
-{
-	if (plane != 0)
-		return -EINVAL;
-
-	hwa742.int_ctrl->enable_plane(plane, enable);
-
-	return 0;
-}
-
-static int sync_handler(struct hwa742_request *req)
-{
-	complete(req->par.sync);
-	return REQ_COMPLETE;
-}
-
-static void hwa742_sync(void)
-{
-	LIST_HEAD(req_list);
-	struct hwa742_request *req;
-	struct completion comp;
-
-	req = alloc_req();
-
-	req->handler = sync_handler;
-	req->complete = NULL;
-	init_completion(&comp);
-	req->par.sync = &comp;
-
-	list_add(&req->entry, &req_list);
-	submit_req_list(&req_list);
-
-	wait_for_completion(&comp);
-}
-
-static void hwa742_bind_client(struct omapfb_notifier_block *nb)
-{
-	dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode);
-	if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
-		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
-	}
-}
-
-static int hwa742_set_update_mode(enum omapfb_update_mode mode)
-{
-	if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
-	    mode != OMAPFB_UPDATE_DISABLED)
-		return -EINVAL;
-
-	if (mode == hwa742.update_mode)
-		return 0;
-
-	dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n",
-			mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
-			(mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
-
-	switch (hwa742.update_mode) {
-	case OMAPFB_MANUAL_UPDATE:
-		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED);
-		break;
-	case OMAPFB_AUTO_UPDATE:
-		hwa742.stop_auto_update = 1;
-		del_timer_sync(&hwa742.auto_update_timer);
-		break;
-	case OMAPFB_UPDATE_DISABLED:
-		break;
-	}
-
-	hwa742.update_mode = mode;
-	hwa742_sync();
-	hwa742.stop_auto_update = 0;
-
-	switch (mode) {
-	case OMAPFB_MANUAL_UPDATE:
-		omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
-		break;
-	case OMAPFB_AUTO_UPDATE:
-		hwa742_update_window_auto(0);
-		break;
-	case OMAPFB_UPDATE_DISABLED:
-		break;
-	}
-
-	return 0;
-}
-
-static enum omapfb_update_mode hwa742_get_update_mode(void)
-{
-	return hwa742.update_mode;
-}
-
-static unsigned long round_to_extif_ticks(unsigned long ps, int div)
-{
-	int bus_tick = hwa742.extif_clk_period * div;
-	return (ps + bus_tick - 1) / bus_tick * bus_tick;
-}
-
-static int calc_reg_timing(unsigned long sysclk, int div)
-{
-	struct extif_timings *t;
-	unsigned long systim;
-
-	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
-	 * AccessTime 2 ns + 12.2 ns (regs),
-	 * WEOffTime = WEOnTime + 1 ns,
-	 * REOffTime = REOnTime + 16 ns (regs),
-	 * CSOffTime = REOffTime + 1 ns
-	 * ReadCycle = 2ns + 2*SYSCLK  (regs),
-	 * WriteCycle = 2*SYSCLK + 2 ns,
-	 * CSPulseWidth = 10 ns */
-	systim = 1000000000 / (sysclk / 1000);
-	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
-		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
-
-	t = &hwa742.reg_timings;
-	memset(t, 0, sizeof(*t));
-	t->clk_div = div;
-	t->cs_on_time = 0;
-	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
-	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
-	t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
-	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
-	t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div);
-	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
-	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
-	if (t->we_cycle_time < t->we_off_time)
-		t->we_cycle_time = t->we_off_time;
-	t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
-	if (t->re_cycle_time < t->re_off_time)
-		t->re_cycle_time = t->re_off_time;
-	t->cs_pulse_width = 0;
-
-	dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
-		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
-	dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
-		 t->we_on_time, t->we_off_time, t->re_cycle_time,
-		 t->we_cycle_time);
-	dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
-		 t->access_time, t->cs_pulse_width);
-
-	return hwa742.extif->convert_timings(t);
-}
-
-static int calc_lut_timing(unsigned long sysclk, int div)
-{
-	struct extif_timings *t;
-	unsigned long systim;
-
-	/* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
-	 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
-	 * WEOffTime = WEOnTime + 1 ns,
-	 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
-	 * CSOffTime = REOffTime + 1 ns
-	 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
-	 * WriteCycle = 2*SYSCLK + 2 ns,
-	 * CSPulseWidth = 10 ns
-	 */
-	systim = 1000000000 / (sysclk / 1000);
-	dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
-		  "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
-
-	t = &hwa742.lut_timings;
-	memset(t, 0, sizeof(*t));
-
-	t->clk_div = div;
-
-	t->cs_on_time = 0;
-	t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
-	t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
-	t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
-					      26000, div);
-	t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
-	t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
-					      26000, div);
-	t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
-	t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
-	if (t->we_cycle_time < t->we_off_time)
-		t->we_cycle_time = t->we_off_time;
-	t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
-	if (t->re_cycle_time < t->re_off_time)
-		t->re_cycle_time = t->re_off_time;
-	t->cs_pulse_width = 0;
-
-	dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n",
-		 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
-	dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
-		 t->we_on_time, t->we_off_time, t->re_cycle_time,
-		 t->we_cycle_time);
-	dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
-		 t->access_time, t->cs_pulse_width);
-
-	return hwa742.extif->convert_timings(t);
-}
-
-static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
-{
-	int max_clk_div;
-	int div;
-
-	hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div);
-	for (div = 1; div < max_clk_div; div++) {
-		if (calc_reg_timing(sysclk, div) == 0)
-			break;
-	}
-	if (div >= max_clk_div)
-		goto err;
-
-	*extif_mem_div = div;
-
-	for (div = 1; div < max_clk_div; div++) {
-		if (calc_lut_timing(sysclk, div) == 0)
-			break;
-	}
-
-	if (div >= max_clk_div)
-		goto err;
-
-	return 0;
-
-err:
-	dev_err(hwa742.fbdev->dev, "can't setup timings\n");
-	return -1;
-}
-
-static void calc_hwa742_clk_rates(unsigned long ext_clk,
-				unsigned long *sys_clk, unsigned long *pix_clk)
-{
-	int pix_clk_src;
-	int sys_div = 0, sys_mul = 0;
-	int pix_div;
-
-	pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG);
-	pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
-	if ((pix_clk_src & (0x3 << 1)) == 0) {
-		/* Source is the PLL */
-		sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1;
-		sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1;
-		*sys_clk = ext_clk * sys_mul / sys_div;
-	} else	/* else source is ext clk, or oscillator */
-		*sys_clk = ext_clk;
-
-	*pix_clk = *sys_clk / pix_div;			/* HZ */
-	dev_dbg(hwa742.fbdev->dev,
-		"ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
-		ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
-	dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
-		*sys_clk, *pix_clk);
-}
-
-
-static int setup_tearsync(unsigned long pix_clk, int extif_div)
-{
-	int hdisp, vdisp;
-	int hndp, vndp;
-	int hsw, vsw;
-	int hs, vs;
-	int hs_pol_inv, vs_pol_inv;
-	int use_hsvs, use_ndp;
-	u8  b;
-
-	hsw = hwa742_read_reg(HWA742_HS_W_REG);
-	vsw = hwa742_read_reg(HWA742_VS_W_REG);
-	hs_pol_inv = !(hsw & 0x80);
-	vs_pol_inv = !(vsw & 0x80);
-	hsw = hsw & 0x7f;
-	vsw = vsw & 0x3f;
-
-	hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8;
-	vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) +
-		((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8);
-
-	hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f;
-	vndp = hwa742_read_reg(HWA742_V_NDP_REG);
-
-	/* time to transfer one pixel (16bpp) in ps */
-	hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time;
-	if (hwa742.extif->get_max_tx_rate != NULL) {
-		/*
-		 * The external interface might have a rate limitation,
-		 * if so, we have to maximize our transfer rate.
-		 */
-		unsigned long min_tx_time;
-		unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate();
-
-		dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n",
-			max_tx_rate);
-		min_tx_time = 1000000000 / (max_tx_rate / 1000);  /* ps */
-		if (hwa742.pix_tx_time < min_tx_time)
-			hwa742.pix_tx_time = min_tx_time;
-	}
-
-	/* time to update one line in ps */
-	hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
-	hwa742.line_upd_time *= 1000;
-	if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time)
-		/*
-		 * transfer speed too low, we might have to use both
-		 * HS and VS
-		 */
-		use_hsvs = 1;
-	else
-		/* decent transfer speed, we'll always use only VS */
-		use_hsvs = 0;
-
-	if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
-		/*
-		 * HS or'ed with VS doesn't work, use the active high
-		 * TE signal based on HNDP / VNDP
-		 */
-		use_ndp = 1;
-		hs_pol_inv = 0;
-		vs_pol_inv = 0;
-		hs = hndp;
-		vs = vndp;
-	} else {
-		/*
-		 * Use HS or'ed with VS as a TE signal if both are needed
-		 * or VNDP if only vsync is needed.
-		 */
-		use_ndp = 0;
-		hs = hsw;
-		vs = vsw;
-		if (!use_hsvs) {
-			hs_pol_inv = 0;
-			vs_pol_inv = 0;
-		}
-	}
-
-	hs = hs * 1000000 / (pix_clk / 1000);			/* ps */
-	hs *= 1000;
-
-	vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000);	/* ps */
-	vs *= 1000;
-
-	if (vs <= hs)
-		return -EDOM;
-	/* set VS to 120% of HS to minimize VS detection time */
-	vs = hs * 12 / 10;
-	/* minimize HS too */
-	hs = 10000;
-
-	b = hwa742_read_reg(HWA742_NDP_CTRL);
-	b &= ~0x3;
-	b |= use_hsvs ? 1 : 0;
-	b |= (use_ndp && use_hsvs) ? 0 : 2;
-	hwa742_write_reg(HWA742_NDP_CTRL, b);
-
-	hwa742.vsync_only = !use_hsvs;
-
-	dev_dbg(hwa742.fbdev->dev,
-		"pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
-		pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time);
-	dev_dbg(hwa742.fbdev->dev,
-		"hs %d ps vs %d ps mode %d vsync_only %d\n",
-		hs, vs, (b & 0x3), !use_hsvs);
-
-	return hwa742.extif->setup_tearsync(1, hs, vs,
-					    hs_pol_inv, vs_pol_inv, extif_div);
-}
-
-static void hwa742_get_caps(int plane, struct omapfb_caps *caps)
-{
-	hwa742.int_ctrl->get_caps(plane, caps);
-	caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
-		      OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE;
-	if (hwa742.te_connected)
-		caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
-	caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
-			   (1 << OMAPFB_COLOR_YUV420);
-}
-
-static void hwa742_suspend(void)
-{
-	hwa742.update_mode_before_suspend = hwa742.update_mode;
-	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
-	/* Enable sleep mode */
-	hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1);
-	clk_disable(hwa742.sys_ck);
-}
-
-static void hwa742_resume(void)
-{
-	clk_enable(hwa742.sys_ck);
-
-	/* Disable sleep mode */
-	hwa742_write_reg(HWA742_POWER_SAVE, 0);
-	while (1) {
-		/* Loop until PLL output is stabilized */
-		if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7))
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(msecs_to_jiffies(5));
-	}
-	hwa742_set_update_mode(hwa742.update_mode_before_suspend);
-}
-
-static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
-		       struct omapfb_mem_desc *req_vram)
-{
-	int r = 0, i;
-	u8 rev, conf;
-	unsigned long ext_clk;
-	unsigned long sys_clk, pix_clk;
-	int extif_mem_div;
-	struct omapfb_platform_data *omapfb_conf;
-
-	BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
-
-	hwa742.fbdev = fbdev;
-	hwa742.extif = fbdev->ext_if;
-	hwa742.int_ctrl = fbdev->int_ctrl;
-
-	omapfb_conf = dev_get_platdata(fbdev->dev);
-
-	hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck");
-
-	spin_lock_init(&hwa742.req_lock);
-
-	if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0)
-		goto err1;
-
-	if ((r = hwa742.extif->init(fbdev)) < 0)
-		goto err2;
-
-	ext_clk = clk_get_rate(hwa742.sys_ck);
-	if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
-		goto err3;
-	hwa742.extif->set_timings(&hwa742.reg_timings);
-	clk_enable(hwa742.sys_ck);
-
-	calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
-	if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
-		goto err4;
-	hwa742.extif->set_timings(&hwa742.reg_timings);
-
-	rev = hwa742_read_reg(HWA742_REV_CODE_REG);
-	if ((rev & 0xfc) != 0x80) {
-		dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev);
-		r = -ENODEV;
-		goto err4;
-	}
-
-
-	if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
-		dev_err(fbdev->dev,
-		      "HWA742: controller not initialized by the bootloader\n");
-		r = -ENODEV;
-		goto err4;
-	}
-
-	if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
-		dev_err(hwa742.fbdev->dev,
-			"HWA742: can't setup tearing synchronization\n");
-		goto err4;
-	}
-	hwa742.te_connected = 1;
-
-	hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
-
-	hwa742.update_mode = OMAPFB_UPDATE_DISABLED;
-
-	hwa742.auto_update_window.x = 0;
-	hwa742.auto_update_window.y = 0;
-	hwa742.auto_update_window.width = fbdev->panel->x_res;
-	hwa742.auto_update_window.height = fbdev->panel->y_res;
-	hwa742.auto_update_window.format = 0;
-
-	init_timer(&hwa742.auto_update_timer);
-	hwa742.auto_update_timer.function = hwa742_update_window_auto;
-	hwa742.auto_update_timer.data = 0;
-
-	hwa742.prev_color_mode = -1;
-	hwa742.prev_flags = 0;
-
-	hwa742.fbdev = fbdev;
-
-	INIT_LIST_HEAD(&hwa742.free_req_list);
-	INIT_LIST_HEAD(&hwa742.pending_req_list);
-	for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
-		list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list);
-	BUG_ON(i <= IRQ_REQ_POOL_SIZE);
-	sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
-
-	conf = hwa742_read_reg(HWA742_CONFIG_REG);
-	dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d "
-			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
-
-	return 0;
-err4:
-	clk_disable(hwa742.sys_ck);
-err3:
-	hwa742.extif->cleanup();
-err2:
-	hwa742.int_ctrl->cleanup();
-err1:
-	return r;
-}
-
-static void hwa742_cleanup(void)
-{
-	hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
-	hwa742.extif->cleanup();
-	hwa742.int_ctrl->cleanup();
-	clk_disable(hwa742.sys_ck);
-}
-
-struct lcd_ctrl hwa742_ctrl = {
-	.name			= "hwa742",
-	.init			= hwa742_init,
-	.cleanup		= hwa742_cleanup,
-	.bind_client		= hwa742_bind_client,
-	.get_caps		= hwa742_get_caps,
-	.set_update_mode	= hwa742_set_update_mode,
-	.get_update_mode	= hwa742_get_update_mode,
-	.setup_plane		= hwa742_setup_plane,
-	.enable_plane		= hwa742_enable_plane,
-	.update_window		= hwa742_update_window_async,
-	.sync			= hwa742_sync,
-	.suspend		= hwa742_suspend,
-	.resume			= hwa742_resume,
-};
-
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
deleted file mode 100644
index 4a5f2cd3d3bf..000000000000
--- a/drivers/video/omap/lcd_ams_delta.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Based on drivers/video/omap/lcd_inn1510.c
- *
- * LCD panel support for the Amstrad E3 (Delta) videophone.
- *
- * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/lcd.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <mach/board-ams-delta.h>
-
-#include "omapfb.h"
-
-#define AMS_DELTA_DEFAULT_CONTRAST	112
-
-#define AMS_DELTA_MAX_CONTRAST		0x00FF
-#define AMS_DELTA_LCD_POWER		0x0100
-
-
-/* LCD class device section */
-
-static int ams_delta_lcd;
-
-static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
-{
-	if (power == FB_BLANK_UNBLANK) {
-		if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) {
-			omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST,
-					OMAP_PWL_ENABLE);
-			omap_writeb(1, OMAP_PWL_CLK_ENABLE);
-			ams_delta_lcd |= AMS_DELTA_LCD_POWER;
-		}
-	} else {
-		if (ams_delta_lcd & AMS_DELTA_LCD_POWER) {
-			omap_writeb(0, OMAP_PWL_ENABLE);
-			omap_writeb(0, OMAP_PWL_CLK_ENABLE);
-			ams_delta_lcd &= ~AMS_DELTA_LCD_POWER;
-		}
-	}
-	return 0;
-}
-
-static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value)
-{
-	if ((value >= 0) && (value <= AMS_DELTA_MAX_CONTRAST)) {
-		omap_writeb(value, OMAP_PWL_ENABLE);
-		ams_delta_lcd &= ~AMS_DELTA_MAX_CONTRAST;
-		ams_delta_lcd |= value;
-	}
-	return 0;
-}
-
-#ifdef CONFIG_LCD_CLASS_DEVICE
-static int ams_delta_lcd_get_power(struct lcd_device *dev)
-{
-	if (ams_delta_lcd & AMS_DELTA_LCD_POWER)
-		return FB_BLANK_UNBLANK;
-	else
-		return FB_BLANK_POWERDOWN;
-}
-
-static int ams_delta_lcd_get_contrast(struct lcd_device *dev)
-{
-	if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER))
-		return 0;
-
-	return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST;
-}
-
-static struct lcd_ops ams_delta_lcd_ops = {
-	.get_power = ams_delta_lcd_get_power,
-	.set_power = ams_delta_lcd_set_power,
-	.get_contrast = ams_delta_lcd_get_contrast,
-	.set_contrast = ams_delta_lcd_set_contrast,
-};
-#endif
-
-
-/* omapfb panel section */
-
-static const struct gpio _gpios[] = {
-	{
-		.gpio	= AMS_DELTA_GPIO_PIN_LCD_VBLEN,
-		.flags	= GPIOF_OUT_INIT_LOW,
-		.label	= "lcd_vblen",
-	},
-	{
-		.gpio	= AMS_DELTA_GPIO_PIN_LCD_NDISP,
-		.flags	= GPIOF_OUT_INIT_LOW,
-		.label	= "lcd_ndisp",
-	},
-};
-
-static int ams_delta_panel_init(struct lcd_panel *panel,
-		struct omapfb_device *fbdev)
-{
-	return gpio_request_array(_gpios, ARRAY_SIZE(_gpios));
-}
-
-static void ams_delta_panel_cleanup(struct lcd_panel *panel)
-{
-	gpio_free_array(_gpios, ARRAY_SIZE(_gpios));
-}
-
-static int ams_delta_panel_enable(struct lcd_panel *panel)
-{
-	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 1);
-	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 1);
-	return 0;
-}
-
-static void ams_delta_panel_disable(struct lcd_panel *panel)
-{
-	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 0);
-	gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 0);
-}
-
-static unsigned long ams_delta_panel_get_caps(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-static struct lcd_panel ams_delta_panel = {
-	.name		= "ams-delta",
-	.config		= 0,
-
-	.bpp		= 12,
-	.data_lines	= 16,
-	.x_res		= 480,
-	.y_res		= 320,
-	.pixel_clock	= 4687,
-	.hsw		= 3,
-	.hfp		= 1,
-	.hbp		= 1,
-	.vsw		= 1,
-	.vfp		= 0,
-	.vbp		= 0,
-	.pcd		= 0,
-	.acb		= 37,
-
-	.init		= ams_delta_panel_init,
-	.cleanup	= ams_delta_panel_cleanup,
-	.enable		= ams_delta_panel_enable,
-	.disable	= ams_delta_panel_disable,
-	.get_caps	= ams_delta_panel_get_caps,
-};
-
-
-/* platform driver section */
-
-static int ams_delta_panel_probe(struct platform_device *pdev)
-{
-	struct lcd_device *lcd_device = NULL;
-#ifdef CONFIG_LCD_CLASS_DEVICE
-	int ret;
-
-	lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
-						&ams_delta_lcd_ops);
-
-	if (IS_ERR(lcd_device)) {
-		ret = PTR_ERR(lcd_device);
-		dev_err(&pdev->dev, "failed to register device\n");
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, lcd_device);
-	lcd_device->props.max_contrast = AMS_DELTA_MAX_CONTRAST;
-#endif
-
-	ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST);
-	ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
-
-	omapfb_register_panel(&ams_delta_panel);
-	return 0;
-}
-
-static int ams_delta_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int ams_delta_panel_suspend(struct platform_device *pdev,
-		pm_message_t mesg)
-{
-	return 0;
-}
-
-static int ams_delta_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver ams_delta_panel_driver = {
-	.probe		= ams_delta_panel_probe,
-	.remove		= ams_delta_panel_remove,
-	.suspend	= ams_delta_panel_suspend,
-	.resume		= ams_delta_panel_resume,
-	.driver		= {
-		.name	= "lcd_ams_delta",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(ams_delta_panel_driver);
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
deleted file mode 100644
index 49bdeca81e50..000000000000
--- a/drivers/video/omap/lcd_h3.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * LCD panel support for the TI OMAP H3 board
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/tps65010.h>
-
-#include <asm/gpio.h>
-#include "omapfb.h"
-
-#define MODULE_NAME	"omapfb-lcd_h3"
-
-static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
-{
-	return 0;
-}
-
-static void h3_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int h3_panel_enable(struct lcd_panel *panel)
-{
-	int r = 0;
-
-	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
-	r = tps65010_set_gpio_out_value(GPIO1, HIGH);
-	if (!r)
-		r = tps65010_set_gpio_out_value(GPIO2, HIGH);
-	if (r)
-		pr_err(MODULE_NAME ": Unable to turn on LCD panel\n");
-
-	return r;
-}
-
-static void h3_panel_disable(struct lcd_panel *panel)
-{
-	int r = 0;
-
-	/* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
-	r = tps65010_set_gpio_out_value(GPIO1, LOW);
-	if (!r)
-		tps65010_set_gpio_out_value(GPIO2, LOW);
-	if (r)
-		pr_err(MODULE_NAME ": Unable to turn off LCD panel\n");
-}
-
-static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-struct lcd_panel h3_panel = {
-	.name		= "h3",
-	.config		= OMAP_LCDC_PANEL_TFT,
-
-	.data_lines	= 16,
-	.bpp		= 16,
-	.x_res		= 240,
-	.y_res		= 320,
-	.pixel_clock	= 12000,
-	.hsw		= 12,
-	.hfp		= 14,
-	.hbp		= 72 - 12,
-	.vsw		= 1,
-	.vfp		= 1,
-	.vbp		= 0,
-	.pcd		= 0,
-
-	.init		= h3_panel_init,
-	.cleanup	= h3_panel_cleanup,
-	.enable		= h3_panel_enable,
-	.disable	= h3_panel_disable,
-	.get_caps	= h3_panel_get_caps,
-};
-
-static int h3_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&h3_panel);
-	return 0;
-}
-
-static int h3_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int h3_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	return 0;
-}
-
-static int h3_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver h3_panel_driver = {
-	.probe		= h3_panel_probe,
-	.remove		= h3_panel_remove,
-	.suspend	= h3_panel_suspend,
-	.resume		= h3_panel_resume,
-	.driver		= {
-		.name	= "lcd_h3",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(h3_panel_driver);
diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/omap/lcd_htcherald.c
deleted file mode 100644
index 20f477851d54..000000000000
--- a/drivers/video/omap/lcd_htcherald.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * File: drivers/video/omap/lcd-htcherald.c
- *
- * LCD panel support for the HTC Herald
- *
- * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
- * Copyright (C) 2009 Wing Linux
- *
- * Based on the lcd_htcwizard.c file from the linwizard project:
- * Copyright (C) linwizard.sourceforge.net
- * Author: Angelo Arrifano <miknix@gmail.com>
- * Based on lcd_h4 by Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include "omapfb.h"
-
-static int htcherald_panel_init(struct lcd_panel *panel,
-					struct omapfb_device *fbdev)
-{
-	return 0;
-}
-
-static void htcherald_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int htcherald_panel_enable(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-static void htcherald_panel_disable(struct lcd_panel *panel)
-{
-}
-
-static unsigned long htcherald_panel_get_caps(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-/* Found on WIZ200 (miknix) and some HERA110 models (darkstar62) */
-struct lcd_panel htcherald_panel_1 = {
-	.name		= "lcd_herald",
-	.config		= OMAP_LCDC_PANEL_TFT |
-			  OMAP_LCDC_INV_HSYNC |
-			  OMAP_LCDC_INV_VSYNC |
-			  OMAP_LCDC_INV_PIX_CLOCK,
-	.bpp		= 16,
-	.data_lines	= 16,
-	.x_res		= 240,
-	.y_res		= 320,
-	.pixel_clock	= 6093,
-	.pcd		= 0, /* 15 */
-	.hsw		= 10,
-	.hfp		= 10,
-	.hbp		= 20,
-	.vsw		= 3,
-	.vfp		= 2,
-	.vbp		= 2,
-
-	.init		= htcherald_panel_init,
-	.cleanup	= htcherald_panel_cleanup,
-	.enable		= htcherald_panel_enable,
-	.disable	= htcherald_panel_disable,
-	.get_caps	= htcherald_panel_get_caps,
-};
-
-static int htcherald_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&htcherald_panel_1);
-	return 0;
-}
-
-static int htcherald_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int htcherald_panel_suspend(struct platform_device *pdev,
-						pm_message_t mesg)
-{
-	return 0;
-}
-
-static int htcherald_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver htcherald_panel_driver = {
-	.probe		= htcherald_panel_probe,
-	.remove		= htcherald_panel_remove,
-	.suspend	= htcherald_panel_suspend,
-	.resume		= htcherald_panel_resume,
-	.driver		= {
-		.name	= "lcd_htcherald",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(htcherald_panel_driver);
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
deleted file mode 100644
index 2ee423279e35..000000000000
--- a/drivers/video/omap/lcd_inn1510.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * LCD panel support for the TI OMAP1510 Innovator board
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#include "omapfb.h"
-
-static int innovator1510_panel_init(struct lcd_panel *panel,
-				    struct omapfb_device *fbdev)
-{
-	return 0;
-}
-
-static void innovator1510_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int innovator1510_panel_enable(struct lcd_panel *panel)
-{
-	__raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
-	return 0;
-}
-
-static void innovator1510_panel_disable(struct lcd_panel *panel)
-{
-	__raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
-}
-
-static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-struct lcd_panel innovator1510_panel = {
-	.name		= "inn1510",
-	.config		= OMAP_LCDC_PANEL_TFT,
-
-	.bpp		= 16,
-	.data_lines	= 16,
-	.x_res		= 240,
-	.y_res		= 320,
-	.pixel_clock	= 12500,
-	.hsw		= 40,
-	.hfp		= 40,
-	.hbp		= 72,
-	.vsw		= 1,
-	.vfp		= 1,
-	.vbp		= 0,
-	.pcd		= 12,
-
-	.init		= innovator1510_panel_init,
-	.cleanup	= innovator1510_panel_cleanup,
-	.enable		= innovator1510_panel_enable,
-	.disable	= innovator1510_panel_disable,
-	.get_caps	= innovator1510_panel_get_caps,
-};
-
-static int innovator1510_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&innovator1510_panel);
-	return 0;
-}
-
-static int innovator1510_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int innovator1510_panel_suspend(struct platform_device *pdev,
-				       pm_message_t mesg)
-{
-	return 0;
-}
-
-static int innovator1510_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver innovator1510_panel_driver = {
-	.probe		= innovator1510_panel_probe,
-	.remove		= innovator1510_panel_remove,
-	.suspend	= innovator1510_panel_suspend,
-	.resume		= innovator1510_panel_resume,
-	.driver		= {
-		.name	= "lcd_inn1510",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(innovator1510_panel_driver);
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
deleted file mode 100644
index e3d3d135aa48..000000000000
--- a/drivers/video/omap/lcd_inn1610.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * LCD panel support for the TI OMAP1610 Innovator board
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <linux/gpio.h>
-#include "omapfb.h"
-
-#define MODULE_NAME	"omapfb-lcd_h3"
-
-static int innovator1610_panel_init(struct lcd_panel *panel,
-				    struct omapfb_device *fbdev)
-{
-	int r = 0;
-
-	/* configure GPIO(14, 15) as outputs */
-	if (gpio_request_one(14, GPIOF_OUT_INIT_LOW, "lcd_en0")) {
-		pr_err(MODULE_NAME ": can't request GPIO 14\n");
-		r = -1;
-		goto exit;
-	}
-	if (gpio_request_one(15, GPIOF_OUT_INIT_LOW, "lcd_en1")) {
-		pr_err(MODULE_NAME ": can't request GPIO 15\n");
-		gpio_free(14);
-		r = -1;
-		goto exit;
-	}
-exit:
-	return r;
-}
-
-static void innovator1610_panel_cleanup(struct lcd_panel *panel)
-{
-	gpio_free(15);
-	gpio_free(14);
-}
-
-static int innovator1610_panel_enable(struct lcd_panel *panel)
-{
-	/* set GPIO14 and GPIO15 high */
-	gpio_set_value(14, 1);
-	gpio_set_value(15, 1);
-	return 0;
-}
-
-static void innovator1610_panel_disable(struct lcd_panel *panel)
-{
-	/* set GPIO13, GPIO14 and GPIO15 low */
-	gpio_set_value(14, 0);
-	gpio_set_value(15, 0);
-}
-
-static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-struct lcd_panel innovator1610_panel = {
-	.name		= "inn1610",
-	.config		= OMAP_LCDC_PANEL_TFT,
-
-	.bpp		= 16,
-	.data_lines	= 16,
-	.x_res		= 320,
-	.y_res		= 240,
-	.pixel_clock	= 12500,
-	.hsw		= 40,
-	.hfp		= 40,
-	.hbp		= 72,
-	.vsw		= 1,
-	.vfp		= 1,
-	.vbp		= 0,
-	.pcd		= 12,
-
-	.init		= innovator1610_panel_init,
-	.cleanup	= innovator1610_panel_cleanup,
-	.enable		= innovator1610_panel_enable,
-	.disable	= innovator1610_panel_disable,
-	.get_caps	= innovator1610_panel_get_caps,
-};
-
-static int innovator1610_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&innovator1610_panel);
-	return 0;
-}
-
-static int innovator1610_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int innovator1610_panel_suspend(struct platform_device *pdev,
-				       pm_message_t mesg)
-{
-	return 0;
-}
-
-static int innovator1610_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver innovator1610_panel_driver = {
-	.probe		= innovator1610_panel_probe,
-	.remove		= innovator1610_panel_remove,
-	.suspend	= innovator1610_panel_suspend,
-	.resume		= innovator1610_panel_resume,
-	.driver		= {
-		.name	= "lcd_inn1610",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(innovator1610_panel_driver);
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
deleted file mode 100644
index 803fee618d57..000000000000
--- a/drivers/video/omap/lcd_mipid.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * LCD driver for MIPI DBI-C / DCS compatible LCDs
- *
- * Copyright (C) 2006 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/spi/spi.h>
-#include <linux/module.h>
-
-#include <linux/platform_data/lcd-mipid.h>
-
-#include "omapfb.h"
-
-#define MIPID_MODULE_NAME		"lcd_mipid"
-
-#define MIPID_CMD_READ_DISP_ID		0x04
-#define MIPID_CMD_READ_RED		0x06
-#define MIPID_CMD_READ_GREEN		0x07
-#define MIPID_CMD_READ_BLUE		0x08
-#define MIPID_CMD_READ_DISP_STATUS	0x09
-#define MIPID_CMD_RDDSDR		0x0F
-#define MIPID_CMD_SLEEP_IN		0x10
-#define MIPID_CMD_SLEEP_OUT		0x11
-#define MIPID_CMD_DISP_OFF		0x28
-#define MIPID_CMD_DISP_ON		0x29
-
-#define MIPID_ESD_CHECK_PERIOD		msecs_to_jiffies(5000)
-
-#define to_mipid_device(p)		container_of(p, struct mipid_device, \
-						panel)
-struct mipid_device {
-	int		enabled;
-	int		revision;
-	unsigned int	saved_bklight_level;
-	unsigned long	hw_guard_end;		/* next value of jiffies
-						   when we can issue the
-						   next sleep in/out command */
-	unsigned long	hw_guard_wait;		/* max guard time in jiffies */
-
-	struct omapfb_device	*fbdev;
-	struct spi_device	*spi;
-	struct mutex		mutex;
-	struct lcd_panel	panel;
-
-	struct workqueue_struct	*esd_wq;
-	struct delayed_work	esd_work;
-	void			(*esd_check)(struct mipid_device *m);
-};
-
-static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf,
-			   int wlen, u8 *rbuf, int rlen)
-{
-	struct spi_message	m;
-	struct spi_transfer	*x, xfer[4];
-	u16			w;
-	int			r;
-
-	BUG_ON(md->spi == NULL);
-
-	spi_message_init(&m);
-
-	memset(xfer, 0, sizeof(xfer));
-	x = &xfer[0];
-
-	cmd &=  0xff;
-	x->tx_buf		= &cmd;
-	x->bits_per_word	= 9;
-	x->len			= 2;
-	spi_message_add_tail(x, &m);
-
-	if (wlen) {
-		x++;
-		x->tx_buf		= wbuf;
-		x->len			= wlen;
-		x->bits_per_word	= 9;
-		spi_message_add_tail(x, &m);
-	}
-
-	if (rlen) {
-		x++;
-		x->rx_buf	= &w;
-		x->len		= 1;
-		spi_message_add_tail(x, &m);
-
-		if (rlen > 1) {
-			/* Arrange for the extra clock before the first
-			 * data bit.
-			 */
-			x->bits_per_word = 9;
-			x->len		 = 2;
-
-			x++;
-			x->rx_buf	 = &rbuf[1];
-			x->len		 = rlen - 1;
-			spi_message_add_tail(x, &m);
-		}
-	}
-
-	r = spi_sync(md->spi, &m);
-	if (r < 0)
-		dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
-
-	if (rlen)
-		rbuf[0] = w & 0xff;
-}
-
-static inline void mipid_cmd(struct mipid_device *md, int cmd)
-{
-	mipid_transfer(md, cmd, NULL, 0, NULL, 0);
-}
-
-static inline void mipid_write(struct mipid_device *md,
-			       int reg, const u8 *buf, int len)
-{
-	mipid_transfer(md, reg, buf, len, NULL, 0);
-}
-
-static inline void mipid_read(struct mipid_device *md,
-			      int reg, u8 *buf, int len)
-{
-	mipid_transfer(md, reg, NULL, 0, buf, len);
-}
-
-static void set_data_lines(struct mipid_device *md, int data_lines)
-{
-	u16 par;
-
-	switch (data_lines) {
-	case 16:
-		par = 0x150;
-		break;
-	case 18:
-		par = 0x160;
-		break;
-	case 24:
-		par = 0x170;
-		break;
-	}
-	mipid_write(md, 0x3a, (u8 *)&par, 2);
-}
-
-static void send_init_string(struct mipid_device *md)
-{
-	u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
-
-	mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
-	set_data_lines(md, md->panel.data_lines);
-}
-
-static void hw_guard_start(struct mipid_device *md, int guard_msec)
-{
-	md->hw_guard_wait = msecs_to_jiffies(guard_msec);
-	md->hw_guard_end = jiffies + md->hw_guard_wait;
-}
-
-static void hw_guard_wait(struct mipid_device *md)
-{
-	unsigned long wait = md->hw_guard_end - jiffies;
-
-	if ((long)wait > 0 && wait <= md->hw_guard_wait) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(wait);
-	}
-}
-
-static void set_sleep_mode(struct mipid_device *md, int on)
-{
-	int cmd, sleep_time = 50;
-
-	if (on)
-		cmd = MIPID_CMD_SLEEP_IN;
-	else
-		cmd = MIPID_CMD_SLEEP_OUT;
-	hw_guard_wait(md);
-	mipid_cmd(md, cmd);
-	hw_guard_start(md, 120);
-	/*
-	 * When we enable the panel, it seems we _have_ to sleep
-	 * 120 ms before sending the init string. When disabling the
-	 * panel we'll sleep for the duration of 2 frames, so that the
-	 * controller can still provide the PCLK,HS,VS signals.
-	 */
-	if (!on)
-		sleep_time = 120;
-	msleep(sleep_time);
-}
-
-static void set_display_state(struct mipid_device *md, int enabled)
-{
-	int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
-
-	mipid_cmd(md, cmd);
-}
-
-static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-	struct mipid_platform_data *pd = md->spi->dev.platform_data;
-
-	if (pd->get_bklight_max == NULL || pd->set_bklight_level == NULL)
-		return -ENODEV;
-	if (level > pd->get_bklight_max(pd))
-		return -EINVAL;
-	if (!md->enabled) {
-		md->saved_bklight_level = level;
-		return 0;
-	}
-	pd->set_bklight_level(pd, level);
-
-	return 0;
-}
-
-static unsigned int mipid_get_bklight_level(struct lcd_panel *panel)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-	struct mipid_platform_data *pd = md->spi->dev.platform_data;
-
-	if (pd->get_bklight_level == NULL)
-		return -ENODEV;
-	return pd->get_bklight_level(pd);
-}
-
-static unsigned int mipid_get_bklight_max(struct lcd_panel *panel)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-	struct mipid_platform_data *pd = md->spi->dev.platform_data;
-
-	if (pd->get_bklight_max == NULL)
-		return -ENODEV;
-
-	return pd->get_bklight_max(pd);
-}
-
-static unsigned long mipid_get_caps(struct lcd_panel *panel)
-{
-	return OMAPFB_CAPS_SET_BACKLIGHT;
-}
-
-static u16 read_first_pixel(struct mipid_device *md)
-{
-	u16 pixel;
-	u8 red, green, blue;
-
-	mutex_lock(&md->mutex);
-	mipid_read(md, MIPID_CMD_READ_RED, &red, 1);
-	mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1);
-	mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1);
-	mutex_unlock(&md->mutex);
-
-	switch (md->panel.data_lines) {
-	case 16:
-		pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1);
-		break;
-	case 24:
-		/* 24 bit -> 16 bit */
-		pixel = ((red >> 3) << 11) | ((green >> 2) << 5) |
-			(blue >> 3);
-		break;
-	default:
-		pixel = 0;
-		BUG();
-	}
-
-	return pixel;
-}
-
-static int mipid_run_test(struct lcd_panel *panel, int test_num)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-	static const u16 test_values[4] = {
-		0x0000, 0xffff, 0xaaaa, 0x5555,
-	};
-	int i;
-
-	if (test_num != MIPID_TEST_RGB_LINES)
-		return MIPID_TEST_INVALID;
-
-	for (i = 0; i < ARRAY_SIZE(test_values); i++) {
-		int delay;
-		unsigned long tmo;
-
-		omapfb_write_first_pixel(md->fbdev, test_values[i]);
-		tmo = jiffies + msecs_to_jiffies(100);
-		delay = 25;
-		while (1) {
-			u16 pixel;
-
-			msleep(delay);
-			pixel = read_first_pixel(md);
-			if (pixel == test_values[i])
-				break;
-			if (time_after(jiffies, tmo)) {
-				dev_err(&md->spi->dev,
-					"MIPI LCD RGB I/F test failed: "
-					"expecting %04x, got %04x\n",
-					test_values[i], pixel);
-				return MIPID_TEST_FAILED;
-			}
-			delay = 10;
-		}
-	}
-
-	return 0;
-}
-
-static void ls041y3_esd_recover(struct mipid_device *md)
-{
-	dev_err(&md->spi->dev, "performing LCD ESD recovery\n");
-	set_sleep_mode(md, 1);
-	set_sleep_mode(md, 0);
-}
-
-static void ls041y3_esd_check_mode1(struct mipid_device *md)
-{
-	u8 state1, state2;
-
-	mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1);
-	set_sleep_mode(md, 0);
-	mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1);
-	dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n",
-		state1, state2);
-	/* Each sleep out command will trigger a self diagnostic and flip
-	* Bit6 if the test passes.
-	*/
-	if (!((state1 ^ state2) & (1 << 6)))
-		ls041y3_esd_recover(md);
-}
-
-static void ls041y3_esd_check_mode2(struct mipid_device *md)
-{
-	int i;
-	u8 rbuf[2];
-	static const struct {
-		int	cmd;
-		int	wlen;
-		u16	wbuf[3];
-	} *rd, rd_ctrl[7] = {
-		{ 0xb0, 4, { 0x0101, 0x01fe, } },
-		{ 0xb1, 4, { 0x01de, 0x0121, } },
-		{ 0xc2, 4, { 0x0100, 0x0100, } },
-		{ 0xbd, 2, { 0x0100, } },
-		{ 0xc2, 4, { 0x01fc, 0x0103, } },
-		{ 0xb4, 0, },
-		{ 0x00, 0, },
-	};
-
-	rd = rd_ctrl;
-	for (i = 0; i < 3; i++, rd++)
-		mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
-
-	udelay(10);
-	mipid_read(md, rd->cmd, rbuf, 2);
-	rd++;
-
-	for (i = 0; i < 3; i++, rd++) {
-		udelay(10);
-		mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
-	}
-
-	dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]);
-	if (rbuf[1] == 0x00)
-		ls041y3_esd_recover(md);
-}
-
-static void ls041y3_esd_check(struct mipid_device *md)
-{
-	ls041y3_esd_check_mode1(md);
-	if (md->revision >= 0x88)
-		ls041y3_esd_check_mode2(md);
-}
-
-static void mipid_esd_start_check(struct mipid_device *md)
-{
-	if (md->esd_check != NULL)
-		queue_delayed_work(md->esd_wq, &md->esd_work,
-				   MIPID_ESD_CHECK_PERIOD);
-}
-
-static void mipid_esd_stop_check(struct mipid_device *md)
-{
-	if (md->esd_check != NULL)
-		cancel_delayed_work_sync(&md->esd_work);
-}
-
-static void mipid_esd_work(struct work_struct *work)
-{
-	struct mipid_device *md = container_of(work, struct mipid_device,
-					       esd_work.work);
-
-	mutex_lock(&md->mutex);
-	md->esd_check(md);
-	mutex_unlock(&md->mutex);
-	mipid_esd_start_check(md);
-}
-
-static int mipid_enable(struct lcd_panel *panel)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-
-	mutex_lock(&md->mutex);
-
-	if (md->enabled) {
-		mutex_unlock(&md->mutex);
-		return 0;
-	}
-	set_sleep_mode(md, 0);
-	md->enabled = 1;
-	send_init_string(md);
-	set_display_state(md, 1);
-	mipid_set_bklight_level(panel, md->saved_bklight_level);
-	mipid_esd_start_check(md);
-
-	mutex_unlock(&md->mutex);
-	return 0;
-}
-
-static void mipid_disable(struct lcd_panel *panel)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-
-	/*
-	 * A final ESD work might be called before returning,
-	 * so do this without holding the lock.
-	 */
-	mipid_esd_stop_check(md);
-	mutex_lock(&md->mutex);
-
-	if (!md->enabled) {
-		mutex_unlock(&md->mutex);
-		return;
-	}
-	md->saved_bklight_level = mipid_get_bklight_level(panel);
-	mipid_set_bklight_level(panel, 0);
-	set_display_state(md, 0);
-	set_sleep_mode(md, 1);
-	md->enabled = 0;
-
-	mutex_unlock(&md->mutex);
-}
-
-static int panel_enabled(struct mipid_device *md)
-{
-	u32 disp_status;
-	int enabled;
-
-	mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
-	disp_status = __be32_to_cpu(disp_status);
-	enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
-	dev_dbg(&md->spi->dev,
-		"LCD panel %senabled by bootloader (status 0x%04x)\n",
-		enabled ? "" : "not ", disp_status);
-	return enabled;
-}
-
-static int mipid_init(struct lcd_panel *panel,
-			    struct omapfb_device *fbdev)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-
-	md->fbdev = fbdev;
-	md->esd_wq = create_singlethread_workqueue("mipid_esd");
-	if (md->esd_wq == NULL) {
-		dev_err(&md->spi->dev, "can't create ESD workqueue\n");
-		return -ENOMEM;
-	}
-	INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work);
-	mutex_init(&md->mutex);
-
-	md->enabled = panel_enabled(md);
-
-	if (md->enabled)
-		mipid_esd_start_check(md);
-	else
-		md->saved_bklight_level = mipid_get_bklight_level(panel);
-
-	return 0;
-}
-
-static void mipid_cleanup(struct lcd_panel *panel)
-{
-	struct mipid_device *md = to_mipid_device(panel);
-
-	if (md->enabled)
-		mipid_esd_stop_check(md);
-	destroy_workqueue(md->esd_wq);
-}
-
-static struct lcd_panel mipid_panel = {
-	.config		= OMAP_LCDC_PANEL_TFT,
-
-	.bpp		= 16,
-	.x_res		= 800,
-	.y_res		= 480,
-	.pixel_clock	= 21940,
-	.hsw		= 50,
-	.hfp		= 20,
-	.hbp		= 15,
-	.vsw		= 2,
-	.vfp		= 1,
-	.vbp		= 3,
-
-	.init			= mipid_init,
-	.cleanup		= mipid_cleanup,
-	.enable			= mipid_enable,
-	.disable		= mipid_disable,
-	.get_caps		= mipid_get_caps,
-	.set_bklight_level	= mipid_set_bklight_level,
-	.get_bklight_level	= mipid_get_bklight_level,
-	.get_bklight_max	= mipid_get_bklight_max,
-	.run_test		= mipid_run_test,
-};
-
-static int mipid_detect(struct mipid_device *md)
-{
-	struct mipid_platform_data *pdata;
-	u8 display_id[3];
-
-	pdata = md->spi->dev.platform_data;
-	if (pdata == NULL) {
-		dev_err(&md->spi->dev, "missing platform data\n");
-		return -ENOENT;
-	}
-
-	mipid_read(md, MIPID_CMD_READ_DISP_ID, display_id, 3);
-	dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
-		display_id[0], display_id[1], display_id[2]);
-
-	switch (display_id[0]) {
-	case 0x45:
-		md->panel.name = "lph8923";
-		break;
-	case 0x83:
-		md->panel.name = "ls041y3";
-		md->esd_check = ls041y3_esd_check;
-		break;
-	default:
-		md->panel.name = "unknown";
-		dev_err(&md->spi->dev, "invalid display ID\n");
-		return -ENODEV;
-	}
-
-	md->revision = display_id[1];
-	md->panel.data_lines = pdata->data_lines;
-	pr_info("omapfb: %s rev %02x LCD detected, %d data lines\n",
-			md->panel.name, md->revision, md->panel.data_lines);
-
-	return 0;
-}
-
-static int mipid_spi_probe(struct spi_device *spi)
-{
-	struct mipid_device *md;
-	int r;
-
-	md = kzalloc(sizeof(*md), GFP_KERNEL);
-	if (md == NULL) {
-		dev_err(&spi->dev, "out of memory\n");
-		return -ENOMEM;
-	}
-
-	spi->mode = SPI_MODE_0;
-	md->spi = spi;
-	dev_set_drvdata(&spi->dev, md);
-	md->panel = mipid_panel;
-
-	r = mipid_detect(md);
-	if (r < 0)
-		return r;
-
-	omapfb_register_panel(&md->panel);
-
-	return 0;
-}
-
-static int mipid_spi_remove(struct spi_device *spi)
-{
-	struct mipid_device *md = dev_get_drvdata(&spi->dev);
-
-	mipid_disable(&md->panel);
-	kfree(md);
-
-	return 0;
-}
-
-static struct spi_driver mipid_spi_driver = {
-	.driver = {
-		.name	= MIPID_MODULE_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe	= mipid_spi_probe,
-	.remove	= mipid_spi_remove,
-};
-
-module_spi_driver(mipid_spi_driver);
-
-MODULE_DESCRIPTION("MIPI display driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
deleted file mode 100644
index 7fbe04bce0ed..000000000000
--- a/drivers/video/omap/lcd_osk.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * LCD panel support for the TI OMAP OSK board
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- * Adapted for OSK by <dirk.behme@de.bosch.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/gpio.h>
-
-#include <mach/hardware.h>
-#include <mach/mux.h>
-
-#include "omapfb.h"
-
-static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
-{
-	/* gpio2 was allocated in board init */
-	return 0;
-}
-
-static void osk_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int osk_panel_enable(struct lcd_panel *panel)
-{
-	/* configure PWL pin */
-	omap_cfg_reg(PWL);
-
-	/* Enable PWL unit */
-	omap_writeb(0x01, OMAP_PWL_CLK_ENABLE);
-
-	/* Set PWL level */
-	omap_writeb(0xFF, OMAP_PWL_ENABLE);
-
-	/* set GPIO2 high (lcd power enabled) */
-	gpio_set_value(2, 1);
-
-	return 0;
-}
-
-static void osk_panel_disable(struct lcd_panel *panel)
-{
-	/* Set PWL level to zero */
-	omap_writeb(0x00, OMAP_PWL_ENABLE);
-
-	/* Disable PWL unit */
-	omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
-
-	/* set GPIO2 low */
-	gpio_set_value(2, 0);
-}
-
-static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-struct lcd_panel osk_panel = {
-	.name		= "osk",
-	.config		= OMAP_LCDC_PANEL_TFT,
-
-	.bpp		= 16,
-	.data_lines	= 16,
-	.x_res		= 240,
-	.y_res		= 320,
-	.pixel_clock	= 12500,
-	.hsw		= 40,
-	.hfp		= 40,
-	.hbp		= 72,
-	.vsw		= 1,
-	.vfp		= 1,
-	.vbp		= 0,
-	.pcd		= 12,
-
-	.init		= osk_panel_init,
-	.cleanup	= osk_panel_cleanup,
-	.enable		= osk_panel_enable,
-	.disable	= osk_panel_disable,
-	.get_caps	= osk_panel_get_caps,
-};
-
-static int osk_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&osk_panel);
-	return 0;
-}
-
-static int osk_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int osk_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	return 0;
-}
-
-static int osk_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver osk_panel_driver = {
-	.probe		= osk_panel_probe,
-	.remove		= osk_panel_remove,
-	.suspend	= osk_panel_suspend,
-	.resume		= osk_panel_resume,
-	.driver		= {
-		.name	= "lcd_osk",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(osk_panel_driver);
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
deleted file mode 100644
index ff4fb624b904..000000000000
--- a/drivers/video/omap/lcd_palmte.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * LCD panel support for the Palm Tungsten E
- *
- * Original version : Romain Goyet <r.goyet@gmail.com>
- * Current version : Laurent Gonzalez <palmte.linux@free.fr>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "omapfb.h"
-
-static int palmte_panel_init(struct lcd_panel *panel,
-				struct omapfb_device *fbdev)
-{
-	return 0;
-}
-
-static void palmte_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int palmte_panel_enable(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-static void palmte_panel_disable(struct lcd_panel *panel)
-{
-}
-
-static unsigned long palmte_panel_get_caps(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-struct lcd_panel palmte_panel = {
-	.name		= "palmte",
-	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
-			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
-			  OMAP_LCDC_HSVS_OPPOSITE,
-
-	.data_lines	= 16,
-	.bpp		= 8,
-	.pixel_clock	= 12000,
-	.x_res		= 320,
-	.y_res		= 320,
-	.hsw		= 4,
-	.hfp		= 8,
-	.hbp		= 28,
-	.vsw		= 1,
-	.vfp		= 8,
-	.vbp		= 7,
-	.pcd		= 0,
-
-	.init		= palmte_panel_init,
-	.cleanup	= palmte_panel_cleanup,
-	.enable		= palmte_panel_enable,
-	.disable	= palmte_panel_disable,
-	.get_caps	= palmte_panel_get_caps,
-};
-
-static int palmte_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&palmte_panel);
-	return 0;
-}
-
-static int palmte_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int palmte_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	return 0;
-}
-
-static int palmte_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver palmte_panel_driver = {
-	.probe		= palmte_panel_probe,
-	.remove		= palmte_panel_remove,
-	.suspend	= palmte_panel_suspend,
-	.resume		= palmte_panel_resume,
-	.driver		= {
-		.name	= "lcd_palmte",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(palmte_panel_driver);
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
deleted file mode 100644
index aaf3c8ba1243..000000000000
--- a/drivers/video/omap/lcd_palmtt.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * LCD panel support for Palm Tungsten|T
- * Current version : Marek Vasut <marek.vasut@gmail.com>
- *
- * Modified from lcd_inn1510.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
-GPIO11 - backlight
-GPIO12 - screen blanking
-GPIO13 - screen blanking
-*/
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#include <asm/gpio.h>
-#include "omapfb.h"
-
-static int palmtt_panel_init(struct lcd_panel *panel,
-	struct omapfb_device *fbdev)
-{
-	return 0;
-}
-
-static void palmtt_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int palmtt_panel_enable(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-static void palmtt_panel_disable(struct lcd_panel *panel)
-{
-}
-
-static unsigned long palmtt_panel_get_caps(struct lcd_panel *panel)
-{
-	return OMAPFB_CAPS_SET_BACKLIGHT;
-}
-
-struct lcd_panel palmtt_panel = {
-	.name		= "palmtt",
-	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
-			OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
-			OMAP_LCDC_HSVS_OPPOSITE,
-	.bpp		= 16,
-	.data_lines	= 16,
-	.x_res		= 320,
-	.y_res		= 320,
-	.pixel_clock	= 10000,
-	.hsw		= 4,
-	.hfp		= 8,
-	.hbp		= 28,
-	.vsw		= 1,
-	.vfp		= 8,
-	.vbp		= 7,
-	.pcd		= 0,
-
-	.init		= palmtt_panel_init,
-	.cleanup	= palmtt_panel_cleanup,
-	.enable		= palmtt_panel_enable,
-	.disable	= palmtt_panel_disable,
-	.get_caps	= palmtt_panel_get_caps,
-};
-
-static int palmtt_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&palmtt_panel);
-	return 0;
-}
-
-static int palmtt_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int palmtt_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	return 0;
-}
-
-static int palmtt_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver palmtt_panel_driver = {
-	.probe		= palmtt_panel_probe,
-	.remove		= palmtt_panel_remove,
-	.suspend	= palmtt_panel_suspend,
-	.resume		= palmtt_panel_resume,
-	.driver		= {
-		.name	= "lcd_palmtt",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(palmtt_panel_driver);
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
deleted file mode 100644
index 3b7d8aa1cf34..000000000000
--- a/drivers/video/omap/lcd_palmz71.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * LCD panel support for the Palm Zire71
- *
- * Original version : Romain Goyet
- * Current version : Laurent Gonzalez
- * Modified for zire71 : Marek Vasut
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "omapfb.h"
-
-static int palmz71_panel_init(struct lcd_panel *panel,
-			      struct omapfb_device *fbdev)
-{
-	return 0;
-}
-
-static void palmz71_panel_cleanup(struct lcd_panel *panel)
-{
-
-}
-
-static int palmz71_panel_enable(struct lcd_panel *panel)
-{
-	return 0;
-}
-
-static void palmz71_panel_disable(struct lcd_panel *panel)
-{
-}
-
-static unsigned long palmz71_panel_get_caps(struct lcd_panel *panel)
-{
-	return OMAPFB_CAPS_SET_BACKLIGHT;
-}
-
-struct lcd_panel palmz71_panel = {
-	.name		= "palmz71",
-	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
-			  OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
-			  OMAP_LCDC_HSVS_OPPOSITE,
-	.data_lines	= 16,
-	.bpp		= 16,
-	.pixel_clock	= 24000,
-	.x_res		= 320,
-	.y_res		= 320,
-	.hsw		= 4,
-	.hfp		= 8,
-	.hbp		= 28,
-	.vsw		= 1,
-	.vfp		= 8,
-	.vbp		= 7,
-	.pcd		= 0,
-
-	.init		= palmz71_panel_init,
-	.cleanup	= palmz71_panel_cleanup,
-	.enable		= palmz71_panel_enable,
-	.disable	= palmz71_panel_disable,
-	.get_caps	= palmz71_panel_get_caps,
-};
-
-static int palmz71_panel_probe(struct platform_device *pdev)
-{
-	omapfb_register_panel(&palmz71_panel);
-	return 0;
-}
-
-static int palmz71_panel_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int palmz71_panel_suspend(struct platform_device *pdev,
-				 pm_message_t mesg)
-{
-	return 0;
-}
-
-static int palmz71_panel_resume(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver palmz71_panel_driver = {
-	.probe		= palmz71_panel_probe,
-	.remove		= palmz71_panel_remove,
-	.suspend	= palmz71_panel_suspend,
-	.resume		= palmz71_panel_resume,
-	.driver		= {
-		.name	= "lcd_palmz71",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(palmz71_panel_driver);
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
deleted file mode 100644
index b52f62595f65..000000000000
--- a/drivers/video/omap/lcdc.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/*
- * OMAP1 internal LCD controller
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/err.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#include <mach/lcdc.h>
-#include <linux/omap-dma.h>
-
-#include <asm/mach-types.h>
-
-#include "omapfb.h"
-
-#include "lcdc.h"
-
-#define MODULE_NAME			"lcdc"
-
-#define MAX_PALETTE_SIZE		PAGE_SIZE
-
-enum lcdc_load_mode {
-	OMAP_LCDC_LOAD_PALETTE,
-	OMAP_LCDC_LOAD_FRAME,
-	OMAP_LCDC_LOAD_PALETTE_AND_FRAME
-};
-
-static struct omap_lcd_controller {
-	enum omapfb_update_mode	update_mode;
-	int			ext_mode;
-
-	unsigned long		frame_offset;
-	int			screen_width;
-	int			xres;
-	int			yres;
-
-	enum omapfb_color_format	color_mode;
-	int			bpp;
-	void			*palette_virt;
-	dma_addr_t		palette_phys;
-	int			palette_code;
-	int			palette_size;
-
-	unsigned int		irq_mask;
-	struct completion	last_frame_complete;
-	struct completion	palette_load_complete;
-	struct clk		*lcd_ck;
-	struct omapfb_device	*fbdev;
-
-	void			(*dma_callback)(void *data);
-	void			*dma_callback_data;
-
-	int			fbmem_allocated;
-	dma_addr_t		vram_phys;
-	void			*vram_virt;
-	unsigned long		vram_size;
-} lcdc;
-
-static void inline enable_irqs(int mask)
-{
-	lcdc.irq_mask |= mask;
-}
-
-static void inline disable_irqs(int mask)
-{
-	lcdc.irq_mask &= ~mask;
-}
-
-static void set_load_mode(enum lcdc_load_mode mode)
-{
-	u32 l;
-
-	l = omap_readl(OMAP_LCDC_CONTROL);
-	l &= ~(3 << 20);
-	switch (mode) {
-	case OMAP_LCDC_LOAD_PALETTE:
-		l |= 1 << 20;
-		break;
-	case OMAP_LCDC_LOAD_FRAME:
-		l |= 2 << 20;
-		break;
-	case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:
-		break;
-	default:
-		BUG();
-	}
-	omap_writel(l, OMAP_LCDC_CONTROL);
-}
-
-static void enable_controller(void)
-{
-	u32 l;
-
-	l = omap_readl(OMAP_LCDC_CONTROL);
-	l |= OMAP_LCDC_CTRL_LCD_EN;
-	l &= ~OMAP_LCDC_IRQ_MASK;
-	l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;	/* enabled IRQs */
-	omap_writel(l, OMAP_LCDC_CONTROL);
-}
-
-static void disable_controller_async(void)
-{
-	u32 l;
-	u32 mask;
-
-	l = omap_readl(OMAP_LCDC_CONTROL);
-	mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;
-	/*
-	 * Preserve the DONE mask, since we still want to get the
-	 * final DONE irq. It will be disabled in the IRQ handler.
-	 */
-	mask &= ~OMAP_LCDC_IRQ_DONE;
-	l &= ~mask;
-	omap_writel(l, OMAP_LCDC_CONTROL);
-}
-
-static void disable_controller(void)
-{
-	init_completion(&lcdc.last_frame_complete);
-	disable_controller_async();
-	if (!wait_for_completion_timeout(&lcdc.last_frame_complete,
-				msecs_to_jiffies(500)))
-		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
-}
-
-static void reset_controller(u32 status)
-{
-	static unsigned long reset_count;
-	static unsigned long last_jiffies;
-
-	disable_controller_async();
-	reset_count++;
-	if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
-		dev_err(lcdc.fbdev->dev,
-			  "resetting (status %#010x,reset count %lu)\n",
-			  status, reset_count);
-		last_jiffies = jiffies;
-	}
-	if (reset_count < 100) {
-		enable_controller();
-	} else {
-		reset_count = 0;
-		dev_err(lcdc.fbdev->dev,
-			"too many reset attempts, giving up.\n");
-	}
-}
-
-/*
- * Configure the LCD DMA according to the current mode specified by parameters
- * in lcdc.fbdev and fbdev->var.
- */
-static void setup_lcd_dma(void)
-{
-	static const int dma_elem_type[] = {
-		0,
-		OMAP_DMA_DATA_TYPE_S8,
-		OMAP_DMA_DATA_TYPE_S16,
-		0,
-		OMAP_DMA_DATA_TYPE_S32,
-	};
-	struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;
-	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
-	unsigned long	src;
-	int		esize, xelem, yelem;
-
-	src = lcdc.vram_phys + lcdc.frame_offset;
-
-	switch (var->rotate) {
-	case 0:
-		if (plane->info.mirror || (src & 3) ||
-		    lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
-		    (lcdc.xres & 1))
-			esize = 2;
-		else
-			esize = 4;
-		xelem = lcdc.xres * lcdc.bpp / 8 / esize;
-		yelem = lcdc.yres;
-		break;
-	case 90:
-	case 180:
-	case 270:
-		if (cpu_is_omap15xx()) {
-			BUG();
-		}
-		esize = 2;
-		xelem = lcdc.yres * lcdc.bpp / 16;
-		yelem = lcdc.xres;
-		break;
-	default:
-		BUG();
-		return;
-	}
-#ifdef VERBOSE
-	dev_dbg(lcdc.fbdev->dev,
-		 "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
-		 src, esize, xelem, yelem);
-#endif
-	omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
-	if (!cpu_is_omap15xx()) {
-		int bpp = lcdc.bpp;
-
-		/*
-		 * YUV support is only for external mode when we have the
-		 * YUV window embedded in a 16bpp frame buffer.
-		 */
-		if (lcdc.color_mode == OMAPFB_COLOR_YUV420)
-			bpp = 16;
-		/* Set virtual xres elem size */
-		omap_set_lcd_dma_b1_vxres(
-			lcdc.screen_width * bpp / 8 / esize);
-		/* Setup transformations */
-		omap_set_lcd_dma_b1_rotation(var->rotate);
-		omap_set_lcd_dma_b1_mirror(plane->info.mirror);
-	}
-	omap_setup_lcd_dma();
-}
-
-static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)
-{
-	u32 status;
-
-	status = omap_readl(OMAP_LCDC_STATUS);
-
-	if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))
-		reset_controller(status);
-	else {
-		if (status & OMAP_LCDC_STAT_DONE) {
-			u32 l;
-
-			/*
-			 * Disable IRQ_DONE. The status bit will be cleared
-			 * only when the controller is reenabled and we don't
-			 * want to get more interrupts.
-			 */
-			l = omap_readl(OMAP_LCDC_CONTROL);
-			l &= ~OMAP_LCDC_IRQ_DONE;
-			omap_writel(l, OMAP_LCDC_CONTROL);
-			complete(&lcdc.last_frame_complete);
-		}
-		if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
-			disable_controller_async();
-			complete(&lcdc.palette_load_complete);
-		}
-	}
-
-	/*
-	 * Clear these interrupt status bits.
-	 * Sync_lost, FUF bits were cleared by disabling the LCD controller
-	 * LOADED_PALETTE can be cleared this way only in palette only
-	 * load mode. In other load modes it's cleared by disabling the
-	 * controller.
-	 */
-	status &= ~(OMAP_LCDC_STAT_VSYNC |
-		    OMAP_LCDC_STAT_LOADED_PALETTE |
-		    OMAP_LCDC_STAT_ABC |
-		    OMAP_LCDC_STAT_LINE_INT);
-	omap_writel(status, OMAP_LCDC_STATUS);
-	return IRQ_HANDLED;
-}
-
-/*
- * Change to a new video mode. We defer this to a later time to avoid any
- * flicker and not to mess up the current LCD DMA context. For this we disable
- * the LCD controller, which will generate a DONE irq after the last frame has
- * been transferred. Then it'll be safe to reconfigure both the LCD controller
- * as well as the LCD DMA.
- */
-static int omap_lcdc_setup_plane(int plane, int channel_out,
-				 unsigned long offset, int screen_width,
-				 int pos_x, int pos_y, int width, int height,
-				 int color_mode)
-{
-	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
-	struct lcd_panel *panel = lcdc.fbdev->panel;
-	int rot_x, rot_y;
-
-	if (var->rotate == 0) {
-		rot_x = panel->x_res;
-		rot_y = panel->y_res;
-	} else {
-		rot_x = panel->y_res;
-		rot_y = panel->x_res;
-	}
-	if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
-	    width > rot_x || height > rot_y) {
-#ifdef VERBOSE
-		dev_dbg(lcdc.fbdev->dev,
-			"invalid plane params plane %d pos_x %d pos_y %d "
-			"w %d h %d\n", plane, pos_x, pos_y, width, height);
-#endif
-		return -EINVAL;
-	}
-
-	lcdc.frame_offset = offset;
-	lcdc.xres = width;
-	lcdc.yres = height;
-	lcdc.screen_width = screen_width;
-	lcdc.color_mode = color_mode;
-
-	switch (color_mode) {
-	case OMAPFB_COLOR_CLUT_8BPP:
-		lcdc.bpp = 8;
-		lcdc.palette_code = 0x3000;
-		lcdc.palette_size = 512;
-		break;
-	case OMAPFB_COLOR_RGB565:
-		lcdc.bpp = 16;
-		lcdc.palette_code = 0x4000;
-		lcdc.palette_size = 32;
-		break;
-	case OMAPFB_COLOR_RGB444:
-		lcdc.bpp = 16;
-		lcdc.palette_code = 0x4000;
-		lcdc.palette_size = 32;
-		break;
-	case OMAPFB_COLOR_YUV420:
-		if (lcdc.ext_mode) {
-			lcdc.bpp = 12;
-			break;
-		}
-		/* fallthrough */
-	case OMAPFB_COLOR_YUV422:
-		if (lcdc.ext_mode) {
-			lcdc.bpp = 16;
-			break;
-		}
-		/* fallthrough */
-	default:
-		/* FIXME: other BPPs.
-		 * bpp1: code  0,     size 256
-		 * bpp2: code  0x1000 size 256
-		 * bpp4: code  0x2000 size 256
-		 * bpp12: code 0x4000 size 32
-		 */
-		dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);
-		BUG();
-		return -1;
-	}
-
-	if (lcdc.ext_mode) {
-		setup_lcd_dma();
-		return 0;
-	}
-
-	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
-		disable_controller();
-		omap_stop_lcd_dma();
-		setup_lcd_dma();
-		enable_controller();
-	}
-
-	return 0;
-}
-
-static int omap_lcdc_enable_plane(int plane, int enable)
-{
-	dev_dbg(lcdc.fbdev->dev,
-		"plane %d enable %d update_mode %d ext_mode %d\n",
-		plane, enable, lcdc.update_mode, lcdc.ext_mode);
-	if (plane != OMAPFB_PLANE_GFX)
-		return -EINVAL;
-
-	return 0;
-}
-
-/*
- * Configure the LCD DMA for a palette load operation and do the palette
- * downloading synchronously. We don't use the frame+palette load mode of
- * the controller, since the palette can always be downloaded separately.
- */
-static void load_palette(void)
-{
-	u16	*palette;
-
-	palette = (u16 *)lcdc.palette_virt;
-
-	*(u16 *)palette &= 0x0fff;
-	*(u16 *)palette |= lcdc.palette_code;
-
-	omap_set_lcd_dma_b1(lcdc.palette_phys,
-		lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
-
-	omap_set_lcd_dma_single_transfer(1);
-	omap_setup_lcd_dma();
-
-	init_completion(&lcdc.palette_load_complete);
-	enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
-	set_load_mode(OMAP_LCDC_LOAD_PALETTE);
-	enable_controller();
-	if (!wait_for_completion_timeout(&lcdc.palette_load_complete,
-				msecs_to_jiffies(500)))
-		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
-	/* The controller gets disabled in the irq handler */
-	disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
-	omap_stop_lcd_dma();
-
-	omap_set_lcd_dma_single_transfer(lcdc.ext_mode);
-}
-
-/* Used only in internal controller mode */
-static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
-			       u16 transp, int update_hw_pal)
-{
-	u16 *palette;
-
-	if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
-		return -EINVAL;
-
-	palette = (u16 *)lcdc.palette_virt;
-
-	palette[regno] &= ~0x0fff;
-	palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
-			   (blue >> 12);
-
-	if (update_hw_pal) {
-		disable_controller();
-		omap_stop_lcd_dma();
-		load_palette();
-		setup_lcd_dma();
-		set_load_mode(OMAP_LCDC_LOAD_FRAME);
-		enable_controller();
-	}
-
-	return 0;
-}
-
-static void calc_ck_div(int is_tft, int pck, int *pck_div)
-{
-	unsigned long lck;
-
-	pck = max(1, pck);
-	lck = clk_get_rate(lcdc.lcd_ck);
-	*pck_div = (lck + pck - 1) / pck;
-	if (is_tft)
-		*pck_div = max(2, *pck_div);
-	else
-		*pck_div = max(3, *pck_div);
-	if (*pck_div > 255) {
-		/* FIXME: try to adjust logic clock divider as well */
-		*pck_div = 255;
-		dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",
-			 pck / 1000);
-	}
-}
-
-static void inline setup_regs(void)
-{
-	u32 l;
-	struct lcd_panel *panel = lcdc.fbdev->panel;
-	int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
-	unsigned long lck;
-	int pcd;
-
-	l = omap_readl(OMAP_LCDC_CONTROL);
-	l &= ~OMAP_LCDC_CTRL_LCD_TFT;
-	l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;
-#ifdef CONFIG_MACH_OMAP_PALMTE
-/* FIXME:if (machine_is_omap_palmte()) { */
-		/* PalmTE uses alternate TFT setting in 8BPP mode */
-		l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0;
-/*	} */
-#endif
-	omap_writel(l, OMAP_LCDC_CONTROL);
-
-	l = omap_readl(OMAP_LCDC_TIMING2);
-	l &= ~(((1 << 6) - 1) << 20);
-	l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;
-	omap_writel(l, OMAP_LCDC_TIMING2);
-
-	l = panel->x_res - 1;
-	l |= (panel->hsw - 1) << 10;
-	l |= (panel->hfp - 1) << 16;
-	l |= (panel->hbp - 1) << 24;
-	omap_writel(l, OMAP_LCDC_TIMING0);
-
-	l = panel->y_res - 1;
-	l |= (panel->vsw - 1) << 10;
-	l |= panel->vfp << 16;
-	l |= panel->vbp << 24;
-	omap_writel(l, OMAP_LCDC_TIMING1);
-
-	l = omap_readl(OMAP_LCDC_TIMING2);
-	l &= ~0xff;
-
-	lck = clk_get_rate(lcdc.lcd_ck);
-
-	if (!panel->pcd)
-		calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
-	else {
-		dev_warn(lcdc.fbdev->dev,
-		    "Pixel clock divider value is obsolete.\n"
-		    "Try to set pixel_clock to %lu and pcd to 0 "
-		    "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
-			lck / panel->pcd / 1000, panel->name);
-
-		pcd = panel->pcd;
-	}
-	l |= pcd & 0xff;
-	l |= panel->acb << 8;
-	omap_writel(l, OMAP_LCDC_TIMING2);
-
-	/* update panel info with the exact clock */
-	panel->pixel_clock = lck / pcd / 1000;
-}
-
-/*
- * Configure the LCD controller, download the color palette and start a looped
- * DMA transfer of the frame image data. Called only in internal
- * controller mode.
- */
-static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
-{
-	int r = 0;
-
-	if (mode != lcdc.update_mode) {
-		switch (mode) {
-		case OMAPFB_AUTO_UPDATE:
-			setup_regs();
-			load_palette();
-
-			/* Setup and start LCD DMA */
-			setup_lcd_dma();
-
-			set_load_mode(OMAP_LCDC_LOAD_FRAME);
-			enable_irqs(OMAP_LCDC_IRQ_DONE);
-			/* This will start the actual DMA transfer */
-			enable_controller();
-			lcdc.update_mode = mode;
-			break;
-		case OMAPFB_UPDATE_DISABLED:
-			disable_controller();
-			omap_stop_lcd_dma();
-			lcdc.update_mode = mode;
-			break;
-		default:
-			r = -EINVAL;
-		}
-	}
-
-	return r;
-}
-
-static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
-{
-	return lcdc.update_mode;
-}
-
-/* PM code called only in internal controller mode */
-static void omap_lcdc_suspend(void)
-{
-	omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);
-}
-
-static void omap_lcdc_resume(void)
-{
-	omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);
-}
-
-static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
-{
-	return;
-}
-
-int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)
-{
-	BUG_ON(callback == NULL);
-
-	if (lcdc.dma_callback)
-		return -EBUSY;
-	else {
-		lcdc.dma_callback = callback;
-		lcdc.dma_callback_data = data;
-	}
-	return 0;
-}
-EXPORT_SYMBOL(omap_lcdc_set_dma_callback);
-
-void omap_lcdc_free_dma_callback(void)
-{
-	lcdc.dma_callback = NULL;
-}
-EXPORT_SYMBOL(omap_lcdc_free_dma_callback);
-
-static void lcdc_dma_handler(u16 status, void *data)
-{
-	if (lcdc.dma_callback)
-		lcdc.dma_callback(lcdc.dma_callback_data);
-}
-
-static int mmap_kern(void)
-{
-	struct vm_struct	*kvma;
-	struct vm_area_struct	vma;
-	pgprot_t		pgprot;
-	unsigned long		vaddr;
-
-	kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP);
-	if (kvma == NULL) {
-		dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n");
-		return -ENOMEM;
-	}
-	vma.vm_mm = &init_mm;
-
-	vaddr = (unsigned long)kvma->addr;
-	vma.vm_start = vaddr;
-	vma.vm_end = vaddr + lcdc.vram_size;
-
-	pgprot = pgprot_writecombine(pgprot_kernel);
-	if (io_remap_pfn_range(&vma, vaddr,
-			   lcdc.vram_phys >> PAGE_SHIFT,
-			   lcdc.vram_size, pgprot) < 0) {
-		dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n");
-		return -EAGAIN;
-	}
-
-	lcdc.vram_virt = (void *)vaddr;
-
-	return 0;
-}
-
-static void unmap_kern(void)
-{
-	vunmap(lcdc.vram_virt);
-}
-
-static int alloc_palette_ram(void)
-{
-	lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
-		MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL);
-	if (lcdc.palette_virt == NULL) {
-		dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
-		return -ENOMEM;
-	}
-	memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
-
-	return 0;
-}
-
-static void free_palette_ram(void)
-{
-	dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
-			lcdc.palette_virt, lcdc.palette_phys);
-}
-
-static int alloc_fbmem(struct omapfb_mem_region *region)
-{
-	int bpp;
-	int frame_size;
-	struct lcd_panel *panel = lcdc.fbdev->panel;
-
-	bpp = panel->bpp;
-	if (bpp == 12)
-		bpp = 16;
-	frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);
-	if (region->size > frame_size)
-		frame_size = region->size;
-	lcdc.vram_size = frame_size;
-	lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
-			lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL);
-	if (lcdc.vram_virt == NULL) {
-		dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
-		return -ENOMEM;
-	}
-	region->size = frame_size;
-	region->paddr = lcdc.vram_phys;
-	region->vaddr = lcdc.vram_virt;
-	region->alloc = 1;
-
-	memset(lcdc.vram_virt, 0, lcdc.vram_size);
-
-	return 0;
-}
-
-static void free_fbmem(void)
-{
-	dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size,
-			      lcdc.vram_virt, lcdc.vram_phys);
-}
-
-static int setup_fbmem(struct omapfb_mem_desc *req_md)
-{
-	int r;
-
-	if (!req_md->region_cnt) {
-		dev_err(lcdc.fbdev->dev, "no memory regions defined\n");
-		return -EINVAL;
-	}
-
-	if (req_md->region_cnt > 1) {
-		dev_err(lcdc.fbdev->dev, "only one plane is supported\n");
-		req_md->region_cnt = 1;
-	}
-
-	if (req_md->region[0].paddr == 0) {
-		lcdc.fbmem_allocated = 1;
-		if ((r = alloc_fbmem(&req_md->region[0])) < 0)
-			return r;
-		return 0;
-	}
-
-	lcdc.vram_phys = req_md->region[0].paddr;
-	lcdc.vram_size = req_md->region[0].size;
-
-	if ((r = mmap_kern()) < 0)
-		return r;
-
-	dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n",
-		 lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt);
-
-	return 0;
-}
-
-static void cleanup_fbmem(void)
-{
-	if (lcdc.fbmem_allocated)
-		free_fbmem();
-	else
-		unmap_kern();
-}
-
-static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
-			  struct omapfb_mem_desc *req_vram)
-{
-	int r;
-	u32 l;
-	int rate;
-	struct clk *tc_ck;
-
-	lcdc.irq_mask = 0;
-
-	lcdc.fbdev = fbdev;
-	lcdc.ext_mode = ext_mode;
-
-	l = 0;
-	omap_writel(l, OMAP_LCDC_CONTROL);
-
-	/* FIXME:
-	 * According to errata some platforms have a clock rate limitiation
-	 */
-	lcdc.lcd_ck = clk_get(fbdev->dev, "lcd_ck");
-	if (IS_ERR(lcdc.lcd_ck)) {
-		dev_err(fbdev->dev, "unable to access LCD clock\n");
-		r = PTR_ERR(lcdc.lcd_ck);
-		goto fail0;
-	}
-
-	tc_ck = clk_get(fbdev->dev, "tc_ck");
-	if (IS_ERR(tc_ck)) {
-		dev_err(fbdev->dev, "unable to access TC clock\n");
-		r = PTR_ERR(tc_ck);
-		goto fail1;
-	}
-
-	rate = clk_get_rate(tc_ck);
-	clk_put(tc_ck);
-
-	if (machine_is_ams_delta())
-		rate /= 4;
-	if (machine_is_omap_h3())
-		rate /= 3;
-	r = clk_set_rate(lcdc.lcd_ck, rate);
-	if (r) {
-		dev_err(fbdev->dev, "failed to adjust LCD rate\n");
-		goto fail1;
-	}
-	clk_enable(lcdc.lcd_ck);
-
-	r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
-	if (r) {
-		dev_err(fbdev->dev, "unable to get IRQ\n");
-		goto fail2;
-	}
-
-	r = omap_request_lcd_dma(lcdc_dma_handler, NULL);
-	if (r) {
-		dev_err(fbdev->dev, "unable to get LCD DMA\n");
-		goto fail3;
-	}
-
-	omap_set_lcd_dma_single_transfer(ext_mode);
-	omap_set_lcd_dma_ext_controller(ext_mode);
-
-	if (!ext_mode)
-		if ((r = alloc_palette_ram()) < 0)
-			goto fail4;
-
-	if ((r = setup_fbmem(req_vram)) < 0)
-		goto fail5;
-
-	pr_info("omapfb: LCDC initialized\n");
-
-	return 0;
-fail5:
-	if (!ext_mode)
-		free_palette_ram();
-fail4:
-	omap_free_lcd_dma();
-fail3:
-	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
-fail2:
-	clk_disable(lcdc.lcd_ck);
-fail1:
-	clk_put(lcdc.lcd_ck);
-fail0:
-	return r;
-}
-
-static void omap_lcdc_cleanup(void)
-{
-	if (!lcdc.ext_mode)
-		free_palette_ram();
-	cleanup_fbmem();
-	omap_free_lcd_dma();
-	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
-	clk_disable(lcdc.lcd_ck);
-	clk_put(lcdc.lcd_ck);
-}
-
-const struct lcd_ctrl omap1_int_ctrl = {
-	.name			= "internal",
-	.init			= omap_lcdc_init,
-	.cleanup		= omap_lcdc_cleanup,
-	.get_caps		= omap_lcdc_get_caps,
-	.set_update_mode	= omap_lcdc_set_update_mode,
-	.get_update_mode	= omap_lcdc_get_update_mode,
-	.update_window		= NULL,
-	.suspend		= omap_lcdc_suspend,
-	.resume			= omap_lcdc_resume,
-	.setup_plane		= omap_lcdc_setup_plane,
-	.enable_plane		= omap_lcdc_enable_plane,
-	.setcolreg		= omap_lcdc_setcolreg,
-};
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h
deleted file mode 100644
index 845222270db3..000000000000
--- a/drivers/video/omap/lcdc.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef LCDC_H
-#define LCDC_H
-
-int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
-void omap_lcdc_free_dma_callback(void);
-
-extern const struct lcd_ctrl omap1_int_ctrl;
-
-#endif
diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h
deleted file mode 100644
index 2921d20e4fba..000000000000
--- a/drivers/video/omap/omapfb.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * File: drivers/video/omap/omapfb.h
- *
- * Framebuffer driver for TI OMAP boards
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef __OMAPFB_H
-#define __OMAPFB_H
-
-#include <linux/fb.h>
-#include <linux/mutex.h>
-#include <linux/omapfb.h>
-
-#define OMAPFB_EVENT_READY	1
-#define OMAPFB_EVENT_DISABLED	2
-
-#define OMAP_LCDC_INV_VSYNC             0x0001
-#define OMAP_LCDC_INV_HSYNC             0x0002
-#define OMAP_LCDC_INV_PIX_CLOCK         0x0004
-#define OMAP_LCDC_INV_OUTPUT_EN         0x0008
-#define OMAP_LCDC_HSVS_RISING_EDGE      0x0010
-#define OMAP_LCDC_HSVS_OPPOSITE         0x0020
-
-#define OMAP_LCDC_SIGNAL_MASK		0x003f
-
-#define OMAP_LCDC_PANEL_TFT		0x0100
-
-#define OMAPFB_PLANE_XRES_MIN		8
-#define OMAPFB_PLANE_YRES_MIN		8
-
-struct omapfb_device;
-
-#define OMAPFB_PLANE_NUM		1
-
-struct omapfb_mem_region {
-	u32		paddr;
-	void __iomem	*vaddr;
-	unsigned long	size;
-	u8		type;		/* OMAPFB_PLANE_MEM_* */
-	enum omapfb_color_format format;/* OMAPFB_COLOR_* */
-	unsigned	format_used:1;	/* Must be set when format is set.
-					 * Needed b/c of the badly chosen 0
-					 * base for OMAPFB_COLOR_* values
-					 */
-	unsigned	alloc:1;	/* allocated by the driver */
-	unsigned	map:1;		/* kernel mapped by the driver */
-};
-
-struct omapfb_mem_desc {
-	int				region_cnt;
-	struct omapfb_mem_region	region[OMAPFB_PLANE_NUM];
-};
-
-struct lcd_panel {
-	const char	*name;
-	int		config;		/* TFT/STN, signal inversion */
-	int		bpp;		/* Pixel format in fb mem */
-	int		data_lines;	/* Lines on LCD HW interface */
-
-	int		x_res, y_res;
-	int		pixel_clock;	/* In kHz */
-	int		hsw;		/* Horizontal synchronization
-					   pulse width */
-	int		hfp;		/* Horizontal front porch */
-	int		hbp;		/* Horizontal back porch */
-	int		vsw;		/* Vertical synchronization
-					   pulse width */
-	int		vfp;		/* Vertical front porch */
-	int		vbp;		/* Vertical back porch */
-	int		acb;		/* ac-bias pin frequency */
-	int		pcd;		/* pixel clock divider.
-					   Obsolete use pixel_clock instead */
-
-	int		(*init)		(struct lcd_panel *panel,
-					 struct omapfb_device *fbdev);
-	void		(*cleanup)	(struct lcd_panel *panel);
-	int		(*enable)	(struct lcd_panel *panel);
-	void		(*disable)	(struct lcd_panel *panel);
-	unsigned long	(*get_caps)	(struct lcd_panel *panel);
-	int		(*set_bklight_level)(struct lcd_panel *panel,
-					     unsigned int level);
-	unsigned int	(*get_bklight_level)(struct lcd_panel *panel);
-	unsigned int	(*get_bklight_max)  (struct lcd_panel *panel);
-	int		(*run_test)	(struct lcd_panel *panel, int test_num);
-};
-
-struct extif_timings {
-	int cs_on_time;
-	int cs_off_time;
-	int we_on_time;
-	int we_off_time;
-	int re_on_time;
-	int re_off_time;
-	int we_cycle_time;
-	int re_cycle_time;
-	int cs_pulse_width;
-	int access_time;
-
-	int clk_div;
-
-	u32 tim[5];		/* set by extif->convert_timings */
-
-	int converted;
-};
-
-struct lcd_ctrl_extif {
-	int  (*init)		(struct omapfb_device *fbdev);
-	void (*cleanup)		(void);
-	void (*get_clk_info)	(u32 *clk_period, u32 *max_clk_div);
-	unsigned long (*get_max_tx_rate)(void);
-	int  (*convert_timings)	(struct extif_timings *timings);
-	void (*set_timings)	(const struct extif_timings *timings);
-	void (*set_bits_per_cycle)(int bpc);
-	void (*write_command)	(const void *buf, unsigned int len);
-	void (*read_data)	(void *buf, unsigned int len);
-	void (*write_data)	(const void *buf, unsigned int len);
-	void (*transfer_area)	(int width, int height,
-				 void (callback)(void *data), void *data);
-	int  (*setup_tearsync)	(unsigned pin_cnt,
-				 unsigned hs_pulse_time, unsigned vs_pulse_time,
-				 int hs_pol_inv, int vs_pol_inv, int div);
-	int  (*enable_tearsync) (int enable, unsigned line);
-
-	unsigned long		max_transmit_size;
-};
-
-struct omapfb_notifier_block {
-	struct notifier_block	nb;
-	void			*data;
-	int			plane_idx;
-};
-
-typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
-					  unsigned long event,
-					  void *fbi);
-
-struct lcd_ctrl {
-	const char	*name;
-	void		*data;
-
-	int		(*init)		  (struct omapfb_device *fbdev,
-					   int ext_mode,
-					   struct omapfb_mem_desc *req_md);
-	void		(*cleanup)	  (void);
-	void		(*bind_client)	  (struct omapfb_notifier_block *nb);
-	void		(*get_caps)	  (int plane, struct omapfb_caps *caps);
-	int		(*set_update_mode)(enum omapfb_update_mode mode);
-	enum omapfb_update_mode (*get_update_mode)(void);
-	int		(*setup_plane)	  (int plane, int channel_out,
-					   unsigned long offset,
-					   int screen_width,
-					   int pos_x, int pos_y, int width,
-					   int height, int color_mode);
-	int		(*set_rotate)	  (int angle);
-	int		(*setup_mem)	  (int plane, size_t size,
-					   int mem_type, unsigned long *paddr);
-	int		(*mmap)		  (struct fb_info *info,
-					   struct vm_area_struct *vma);
-	int		(*set_scale)	  (int plane,
-					   int orig_width, int orig_height,
-					   int out_width, int out_height);
-	int		(*enable_plane)	  (int plane, int enable);
-	int		(*update_window)  (struct fb_info *fbi,
-					   struct omapfb_update_window *win,
-					   void (*callback)(void *),
-					   void *callback_data);
-	void		(*sync)		  (void);
-	void		(*suspend)	  (void);
-	void		(*resume)	  (void);
-	int		(*run_test)	  (int test_num);
-	int		(*setcolreg)	  (u_int regno, u16 red, u16 green,
-					   u16 blue, u16 transp,
-					   int update_hw_mem);
-	int		(*set_color_key)  (struct omapfb_color_key *ck);
-	int		(*get_color_key)  (struct omapfb_color_key *ck);
-};
-
-enum omapfb_state {
-	OMAPFB_DISABLED		= 0,
-	OMAPFB_SUSPENDED	= 99,
-	OMAPFB_ACTIVE		= 100
-};
-
-struct omapfb_plane_struct {
-	int				idx;
-	struct omapfb_plane_info	info;
-	enum omapfb_color_format	color_mode;
-	struct omapfb_device		*fbdev;
-};
-
-struct omapfb_device {
-	int			state;
-	int                     ext_lcdc;		/* Using external
-							   LCD controller */
-	struct mutex		rqueue_mutex;
-
-	int			palette_size;
-	u32			pseudo_palette[17];
-
-	struct lcd_panel	*panel;			/* LCD panel */
-	const struct lcd_ctrl	*ctrl;			/* LCD controller */
-	const struct lcd_ctrl	*int_ctrl;		/* internal LCD ctrl */
-	struct lcd_ctrl_extif	*ext_if;		/* LCD ctrl external
-							   interface */
-	struct device		*dev;
-	struct fb_var_screeninfo	new_var;	/* for mode changes */
-
-	struct omapfb_mem_desc		mem_desc;
-	struct fb_info			*fb_info[OMAPFB_PLANE_NUM];
-
-	struct platform_device	*dssdev;	/* dummy dev for clocks */
-};
-
-extern struct lcd_ctrl omap1_lcd_ctrl;
-
-extern void omapfb_register_panel(struct lcd_panel *panel);
-extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
-extern void omapfb_notify_clients(struct omapfb_device *fbdev,
-				  unsigned long event);
-extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
-				   omapfb_notifier_callback_t callback,
-				   void *callback_data);
-extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
-extern int  omapfb_update_window_async(struct fb_info *fbi,
-				       struct omapfb_update_window *win,
-				       void (*callback)(void *),
-				       void *callback_data);
-
-#endif /* __OMAPFB_H */
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
deleted file mode 100644
index e4fc6d9b5371..000000000000
--- a/drivers/video/omap/omapfb_main.c
+++ /dev/null
@@ -1,1971 +0,0 @@
-/*
- * Framebuffer driver for TI OMAP boards
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * Acknowledgements:
- *   Alex McMains <aam@ridgerun.com>       - Original driver
- *   Juha Yrjola <juha.yrjola@nokia.com>   - Original driver and improvements
- *   Dirk Behme <dirk.behme@de.bosch.com>  - changes for 2.6 kernel API
- *   Texas Instruments                     - H3 support
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#include <linux/platform_device.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-
-#include <linux/omap-dma.h>
-
-#include <mach/hardware.h>
-
-#include "omapfb.h"
-#include "lcdc.h"
-
-#define MODULE_NAME	"omapfb"
-
-static unsigned int	def_accel;
-static unsigned long	def_vram[OMAPFB_PLANE_NUM];
-static unsigned int	def_vram_cnt;
-static unsigned long	def_vxres;
-static unsigned long	def_vyres;
-static unsigned int	def_rotate;
-static unsigned int	def_mirror;
-
-#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
-static bool		manual_update = 1;
-#else
-static bool		manual_update;
-#endif
-
-static struct platform_device	*fbdev_pdev;
-static struct lcd_panel		*fbdev_panel;
-static struct omapfb_device	*omapfb_dev;
-
-struct caps_table_struct {
-	unsigned long flag;
-	const char *name;
-};
-
-static struct caps_table_struct ctrl_caps[] = {
-	{ OMAPFB_CAPS_MANUAL_UPDATE,  "manual update" },
-	{ OMAPFB_CAPS_TEARSYNC,       "tearing synchronization" },
-	{ OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" },
-	{ OMAPFB_CAPS_PLANE_SCALE,    "scale plane" },
-	{ OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
-	{ OMAPFB_CAPS_WINDOW_SCALE,   "scale window" },
-	{ OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
-	{ OMAPFB_CAPS_WINDOW_ROTATE,  "rotate window" },
-	{ OMAPFB_CAPS_SET_BACKLIGHT,  "backlight setting" },
-};
-
-static struct caps_table_struct color_caps[] = {
-	{ 1 << OMAPFB_COLOR_RGB565,	"RGB565", },
-	{ 1 << OMAPFB_COLOR_YUV422,	"YUV422", },
-	{ 1 << OMAPFB_COLOR_YUV420,	"YUV420", },
-	{ 1 << OMAPFB_COLOR_CLUT_8BPP,	"CLUT8", },
-	{ 1 << OMAPFB_COLOR_CLUT_4BPP,	"CLUT4", },
-	{ 1 << OMAPFB_COLOR_CLUT_2BPP,	"CLUT2", },
-	{ 1 << OMAPFB_COLOR_CLUT_1BPP,	"CLUT1", },
-	{ 1 << OMAPFB_COLOR_RGB444,	"RGB444", },
-	{ 1 << OMAPFB_COLOR_YUY422,	"YUY422", },
-};
-
-static void omapdss_release(struct device *dev)
-{
-}
-
-/* dummy device for clocks */
-static struct platform_device omapdss_device = {
-	.name		= "omapdss_dss",
-	.id		= -1,
-	.dev            = {
-		.release = omapdss_release,
-	},
-};
-
-/*
- * ---------------------------------------------------------------------------
- * LCD panel
- * ---------------------------------------------------------------------------
- */
-extern struct lcd_ctrl hwa742_ctrl;
-
-static const struct lcd_ctrl *ctrls[] = {
-	&omap1_int_ctrl,
-
-#ifdef CONFIG_FB_OMAP_LCDC_HWA742
-	&hwa742_ctrl,
-#endif
-};
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-extern struct lcd_ctrl_extif omap1_ext_if;
-#endif
-
-static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
-{
-	mutex_lock(&fbdev->rqueue_mutex);
-}
-
-static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
-{
-	mutex_unlock(&fbdev->rqueue_mutex);
-}
-
-/*
- * ---------------------------------------------------------------------------
- * LCD controller and LCD DMA
- * ---------------------------------------------------------------------------
- */
-/*
- * Allocate resources needed for LCD controller and LCD DMA operations. Video
- * memory is allocated from system memory according to the virtual display
- * size, except if a bigger memory size is specified explicitly as a kernel
- * parameter.
- */
-static int ctrl_init(struct omapfb_device *fbdev)
-{
-	int r;
-	int i;
-
-	/* kernel/module vram parameters override boot tags/board config */
-	if (def_vram_cnt) {
-		for (i = 0; i < def_vram_cnt; i++)
-			fbdev->mem_desc.region[i].size =
-				PAGE_ALIGN(def_vram[i]);
-		fbdev->mem_desc.region_cnt = i;
-	}
-
-	if (!fbdev->mem_desc.region_cnt) {
-		struct lcd_panel *panel = fbdev->panel;
-		int def_size;
-		int bpp = panel->bpp;
-
-		/* 12 bpp is packed in 16 bits */
-		if (bpp == 12)
-			bpp = 16;
-		def_size = def_vxres * def_vyres * bpp / 8;
-		fbdev->mem_desc.region_cnt = 1;
-		fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size);
-	}
-	r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc);
-	if (r < 0) {
-		dev_err(fbdev->dev, "controller initialization failed (%d)\n",
-			r);
-		return r;
-	}
-
-#ifdef DEBUG
-	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
-		dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n",
-			 i,
-			 fbdev->mem_desc.region[i].paddr,
-			 fbdev->mem_desc.region[i].vaddr,
-			 fbdev->mem_desc.region[i].size);
-	}
-#endif
-	return 0;
-}
-
-static void ctrl_cleanup(struct omapfb_device *fbdev)
-{
-	fbdev->ctrl->cleanup();
-}
-
-/* Must be called with fbdev->rqueue_mutex held. */
-static int ctrl_change_mode(struct fb_info *fbi)
-{
-	int r;
-	unsigned long offset;
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct fb_var_screeninfo *var = &fbi->var;
-
-	offset = var->yoffset * fbi->fix.line_length +
-		 var->xoffset * var->bits_per_pixel / 8;
-
-	if (fbdev->ctrl->sync)
-		fbdev->ctrl->sync();
-	r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out,
-				 offset, var->xres_virtual,
-				 plane->info.pos_x, plane->info.pos_y,
-				 var->xres, var->yres, plane->color_mode);
-	if (r < 0)
-		return r;
-
-	if (fbdev->ctrl->set_rotate != NULL) {
-		r = fbdev->ctrl->set_rotate(var->rotate);
-		if (r < 0)
-			return r;
-	}
-
-	if (fbdev->ctrl->set_scale != NULL)
-		r = fbdev->ctrl->set_scale(plane->idx,
-				   var->xres, var->yres,
-				   plane->info.out_width,
-				   plane->info.out_height);
-
-	return r;
-}
-
-/*
- * ---------------------------------------------------------------------------
- * fbdev framework callbacks and the ioctl interface
- * ---------------------------------------------------------------------------
- */
-/* Called each time the omapfb device is opened */
-static int omapfb_open(struct fb_info *info, int user)
-{
-	return 0;
-}
-
-static void omapfb_sync(struct fb_info *info);
-
-/* Called when the omapfb device is closed. We make sure that any pending
- * gfx DMA operations are ended, before we return. */
-static int omapfb_release(struct fb_info *info, int user)
-{
-	omapfb_sync(info);
-	return 0;
-}
-
-/* Store a single color palette entry into a pseudo palette or the hardware
- * palette if one is available. For now we support only 16bpp and thus store
- * the entry only to the pseudo palette.
- */
-static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
-			u_int blue, u_int transp, int update_hw_pal)
-{
-	struct omapfb_plane_struct *plane = info->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct fb_var_screeninfo *var = &info->var;
-	int r = 0;
-
-	switch (plane->color_mode) {
-	case OMAPFB_COLOR_YUV422:
-	case OMAPFB_COLOR_YUV420:
-	case OMAPFB_COLOR_YUY422:
-		r = -EINVAL;
-		break;
-	case OMAPFB_COLOR_CLUT_8BPP:
-	case OMAPFB_COLOR_CLUT_4BPP:
-	case OMAPFB_COLOR_CLUT_2BPP:
-	case OMAPFB_COLOR_CLUT_1BPP:
-		if (fbdev->ctrl->setcolreg)
-			r = fbdev->ctrl->setcolreg(regno, red, green, blue,
-							transp, update_hw_pal);
-		/* Fallthrough */
-	case OMAPFB_COLOR_RGB565:
-	case OMAPFB_COLOR_RGB444:
-		if (r != 0)
-			break;
-
-		if (regno < 0) {
-			r = -EINVAL;
-			break;
-		}
-
-		if (regno < 16) {
-			u16 pal;
-			pal = ((red >> (16 - var->red.length)) <<
-					var->red.offset) |
-			      ((green >> (16 - var->green.length)) <<
-					var->green.offset) |
-			      (blue >> (16 - var->blue.length));
-			((u32 *)(info->pseudo_palette))[regno] = pal;
-		}
-		break;
-	default:
-		BUG();
-	}
-	return r;
-}
-
-static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			    u_int transp, struct fb_info *info)
-{
-	return _setcolreg(info, regno, red, green, blue, transp, 1);
-}
-
-static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
-	int count, index, r;
-	u16 *red, *green, *blue, *transp;
-	u16 trans = 0xffff;
-
-	red     = cmap->red;
-	green   = cmap->green;
-	blue    = cmap->blue;
-	transp  = cmap->transp;
-	index   = cmap->start;
-
-	for (count = 0; count < cmap->len; count++) {
-		if (transp)
-			trans = *transp++;
-		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
-				count == cmap->len - 1);
-		if (r != 0)
-			return r;
-	}
-
-	return 0;
-}
-
-static int omapfb_update_full_screen(struct fb_info *fbi);
-
-static int omapfb_blank(int blank, struct fb_info *fbi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	int do_update = 0;
-	int r = 0;
-
-	omapfb_rqueue_lock(fbdev);
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-		if (fbdev->state == OMAPFB_SUSPENDED) {
-			if (fbdev->ctrl->resume)
-				fbdev->ctrl->resume();
-			fbdev->panel->enable(fbdev->panel);
-			fbdev->state = OMAPFB_ACTIVE;
-			if (fbdev->ctrl->get_update_mode() ==
-					OMAPFB_MANUAL_UPDATE)
-				do_update = 1;
-		}
-		break;
-	case FB_BLANK_POWERDOWN:
-		if (fbdev->state == OMAPFB_ACTIVE) {
-			fbdev->panel->disable(fbdev->panel);
-			if (fbdev->ctrl->suspend)
-				fbdev->ctrl->suspend();
-			fbdev->state = OMAPFB_SUSPENDED;
-		}
-		break;
-	default:
-		r = -EINVAL;
-	}
-	omapfb_rqueue_unlock(fbdev);
-
-	if (r == 0 && do_update)
-		r = omapfb_update_full_screen(fbi);
-
-	return r;
-}
-
-static void omapfb_sync(struct fb_info *fbi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-
-	omapfb_rqueue_lock(fbdev);
-	if (fbdev->ctrl->sync)
-		fbdev->ctrl->sync();
-	omapfb_rqueue_unlock(fbdev);
-}
-
-/*
- * Set fb_info.fix fields and also updates fbdev.
- * When calling this fb_info.var must be set up already.
- */
-static void set_fb_fix(struct fb_info *fbi, int from_init)
-{
-	struct fb_fix_screeninfo *fix = &fbi->fix;
-	struct fb_var_screeninfo *var = &fbi->var;
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_mem_region *rg;
-	int bpp;
-
-	rg = &plane->fbdev->mem_desc.region[plane->idx];
-	fbi->screen_base	= rg->vaddr;
-
-	if (!from_init) {
-		mutex_lock(&fbi->mm_lock);
-		fix->smem_start		= rg->paddr;
-		fix->smem_len		= rg->size;
-		mutex_unlock(&fbi->mm_lock);
-	} else {
-		fix->smem_start		= rg->paddr;
-		fix->smem_len		= rg->size;
-	}
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	bpp = var->bits_per_pixel;
-	if (var->nonstd)
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else switch (var->bits_per_pixel) {
-	case 16:
-	case 12:
-		fix->visual = FB_VISUAL_TRUECOLOR;
-		/* 12bpp is stored in 16 bits */
-		bpp = 16;
-		break;
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	}
-	fix->accel		= FB_ACCEL_OMAP1610;
-	fix->line_length	= var->xres_virtual * bpp / 8;
-}
-
-static int set_color_mode(struct omapfb_plane_struct *plane,
-			  struct fb_var_screeninfo *var)
-{
-	switch (var->nonstd) {
-	case 0:
-		break;
-	case OMAPFB_COLOR_YUV422:
-		var->bits_per_pixel = 16;
-		plane->color_mode = var->nonstd;
-		return 0;
-	case OMAPFB_COLOR_YUV420:
-		var->bits_per_pixel = 12;
-		plane->color_mode = var->nonstd;
-		return 0;
-	case OMAPFB_COLOR_YUY422:
-		var->bits_per_pixel = 16;
-		plane->color_mode = var->nonstd;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-
-	switch (var->bits_per_pixel) {
-	case 1:
-		plane->color_mode = OMAPFB_COLOR_CLUT_1BPP;
-		return 0;
-	case 2:
-		plane->color_mode = OMAPFB_COLOR_CLUT_2BPP;
-		return 0;
-	case 4:
-		plane->color_mode = OMAPFB_COLOR_CLUT_4BPP;
-		return 0;
-	case 8:
-		plane->color_mode = OMAPFB_COLOR_CLUT_8BPP;
-		return 0;
-	case 12:
-		var->bits_per_pixel = 16;
-	case 16:
-		if (plane->fbdev->panel->bpp == 12)
-			plane->color_mode = OMAPFB_COLOR_RGB444;
-		else
-			plane->color_mode = OMAPFB_COLOR_RGB565;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-/*
- * Check the values in var against our capabilities and in case of out of
- * bound values try to adjust them.
- */
-static int set_fb_var(struct fb_info *fbi,
-		      struct fb_var_screeninfo *var)
-{
-	int		bpp;
-	unsigned long	max_frame_size;
-	unsigned long	line_size;
-	int		xres_min, xres_max;
-	int		yres_min, yres_max;
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct lcd_panel *panel = fbdev->panel;
-
-	if (set_color_mode(plane, var) < 0)
-		return -EINVAL;
-
-	bpp = var->bits_per_pixel;
-	if (plane->color_mode == OMAPFB_COLOR_RGB444)
-		bpp = 16;
-
-	switch (var->rotate) {
-	case 0:
-	case 180:
-		xres_min = OMAPFB_PLANE_XRES_MIN;
-		xres_max = panel->x_res;
-		yres_min = OMAPFB_PLANE_YRES_MIN;
-		yres_max = panel->y_res;
-		if (cpu_is_omap15xx()) {
-			var->xres = panel->x_res;
-			var->yres = panel->y_res;
-		}
-		break;
-	case 90:
-	case 270:
-		xres_min = OMAPFB_PLANE_YRES_MIN;
-		xres_max = panel->y_res;
-		yres_min = OMAPFB_PLANE_XRES_MIN;
-		yres_max = panel->x_res;
-		if (cpu_is_omap15xx()) {
-			var->xres = panel->y_res;
-			var->yres = panel->x_res;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (var->xres < xres_min)
-		var->xres = xres_min;
-	if (var->yres < yres_min)
-		var->yres = yres_min;
-	if (var->xres > xres_max)
-		var->xres = xres_max;
-	if (var->yres > yres_max)
-		var->yres = yres_max;
-
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-	max_frame_size = fbdev->mem_desc.region[plane->idx].size;
-	line_size = var->xres_virtual * bpp / 8;
-	if (line_size * var->yres_virtual > max_frame_size) {
-		/* Try to keep yres_virtual first */
-		line_size = max_frame_size / var->yres_virtual;
-		var->xres_virtual = line_size * 8 / bpp;
-		if (var->xres_virtual < var->xres) {
-			/* Still doesn't fit. Shrink yres_virtual too */
-			var->xres_virtual = var->xres;
-			line_size = var->xres * bpp / 8;
-			var->yres_virtual = max_frame_size / line_size;
-		}
-		/* Recheck this, as the virtual size changed. */
-		if (var->xres_virtual < var->xres)
-			var->xres = var->xres_virtual;
-		if (var->yres_virtual < var->yres)
-			var->yres = var->yres_virtual;
-		if (var->xres < xres_min || var->yres < yres_min)
-			return -EINVAL;
-	}
-	if (var->xres + var->xoffset > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yres + var->yoffset > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	if (plane->color_mode == OMAPFB_COLOR_RGB444) {
-		var->red.offset	  = 8; var->red.length	 = 4;
-						var->red.msb_right   = 0;
-		var->green.offset = 4; var->green.length = 4;
-						var->green.msb_right = 0;
-		var->blue.offset  = 0; var->blue.length  = 4;
-						var->blue.msb_right  = 0;
-	} else {
-		var->red.offset	 = 11; var->red.length	 = 5;
-						var->red.msb_right   = 0;
-		var->green.offset = 5;  var->green.length = 6;
-						var->green.msb_right = 0;
-		var->blue.offset = 0;  var->blue.length  = 5;
-						var->blue.msb_right  = 0;
-	}
-
-	var->height		= -1;
-	var->width		= -1;
-	var->grayscale		= 0;
-
-	/* pixclock in ps, the rest in pixclock */
-	var->pixclock		= 10000000 / (panel->pixel_clock / 100);
-	var->left_margin	= panel->hfp;
-	var->right_margin	= panel->hbp;
-	var->upper_margin	= panel->vfp;
-	var->lower_margin	= panel->vbp;
-	var->hsync_len		= panel->hsw;
-	var->vsync_len		= panel->vsw;
-
-	/* TODO: get these from panel->config */
-	var->vmode		= FB_VMODE_NONINTERLACED;
-	var->sync		= 0;
-
-	return 0;
-}
-
-
-/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
-static void omapfb_rotate(struct fb_info *fbi, int rotate)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-
-	omapfb_rqueue_lock(fbdev);
-	if (rotate != fbi->var.rotate) {
-		struct fb_var_screeninfo *new_var = &fbdev->new_var;
-
-		memcpy(new_var, &fbi->var, sizeof(*new_var));
-		new_var->rotate = rotate;
-		if (set_fb_var(fbi, new_var) == 0 &&
-		    memcmp(new_var, &fbi->var, sizeof(*new_var))) {
-			memcpy(&fbi->var, new_var, sizeof(*new_var));
-			ctrl_change_mode(fbi);
-		}
-	}
-	omapfb_rqueue_unlock(fbdev);
-}
-
-/*
- * Set new x,y offsets in the virtual display for the visible area and switch
- * to the new mode.
- */
-static int omapfb_pan_display(struct fb_var_screeninfo *var,
-			       struct fb_info *fbi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	int r = 0;
-
-	omapfb_rqueue_lock(fbdev);
-	if (var->xoffset != fbi->var.xoffset ||
-	    var->yoffset != fbi->var.yoffset) {
-		struct fb_var_screeninfo *new_var = &fbdev->new_var;
-
-		memcpy(new_var, &fbi->var, sizeof(*new_var));
-		new_var->xoffset = var->xoffset;
-		new_var->yoffset = var->yoffset;
-		if (set_fb_var(fbi, new_var))
-			r = -EINVAL;
-		else {
-			memcpy(&fbi->var, new_var, sizeof(*new_var));
-			ctrl_change_mode(fbi);
-		}
-	}
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-/* Set mirror to vertical axis and switch to the new mode. */
-static int omapfb_mirror(struct fb_info *fbi, int mirror)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	int r = 0;
-
-	omapfb_rqueue_lock(fbdev);
-	mirror = mirror ? 1 : 0;
-	if (cpu_is_omap15xx())
-		r = -EINVAL;
-	else if (mirror != plane->info.mirror) {
-		plane->info.mirror = mirror;
-		r = ctrl_change_mode(fbi);
-	}
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-/*
- * Check values in var, try to adjust them in case of out of bound values if
- * possible, or return error.
- */
-static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	int r;
-
-	omapfb_rqueue_lock(fbdev);
-	if (fbdev->ctrl->sync != NULL)
-		fbdev->ctrl->sync();
-	r = set_fb_var(fbi, var);
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-/*
- * Switch to a new mode. The parameters for it has been check already by
- * omapfb_check_var.
- */
-static int omapfb_set_par(struct fb_info *fbi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	int r = 0;
-
-	omapfb_rqueue_lock(fbdev);
-	set_fb_fix(fbi, 0);
-	r = ctrl_change_mode(fbi);
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-int omapfb_update_window_async(struct fb_info *fbi,
-				struct omapfb_update_window *win,
-				void (*callback)(void *),
-				void *callback_data)
-{
-	int xres, yres;
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct fb_var_screeninfo *var = &fbi->var;
-
-	switch (var->rotate) {
-	case 0:
-	case 180:
-		xres = fbdev->panel->x_res;
-		yres = fbdev->panel->y_res;
-		break;
-	case 90:
-	case 270:
-		xres = fbdev->panel->y_res;
-		yres = fbdev->panel->x_res;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (win->x >= xres || win->y >= yres ||
-	    win->out_x > xres || win->out_y > yres)
-		return -EINVAL;
-
-	if (!fbdev->ctrl->update_window ||
-	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
-		return -ENODEV;
-
-	if (win->x + win->width > xres)
-		win->width = xres - win->x;
-	if (win->y + win->height > yres)
-		win->height = yres - win->y;
-	if (win->out_x + win->out_width > xres)
-		win->out_width = xres - win->out_x;
-	if (win->out_y + win->out_height > yres)
-		win->out_height = yres - win->out_y;
-	if (!win->width || !win->height || !win->out_width || !win->out_height)
-		return 0;
-
-	return fbdev->ctrl->update_window(fbi, win, callback, callback_data);
-}
-EXPORT_SYMBOL(omapfb_update_window_async);
-
-static int omapfb_update_win(struct fb_info *fbi,
-				struct omapfb_update_window *win)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	int ret;
-
-	omapfb_rqueue_lock(plane->fbdev);
-	ret = omapfb_update_window_async(fbi, win, NULL, NULL);
-	omapfb_rqueue_unlock(plane->fbdev);
-
-	return ret;
-}
-
-static int omapfb_update_full_screen(struct fb_info *fbi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct omapfb_update_window win;
-	int r;
-
-	if (!fbdev->ctrl->update_window ||
-	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
-		return -ENODEV;
-
-	win.x = 0;
-	win.y = 0;
-	win.width = fbi->var.xres;
-	win.height = fbi->var.yres;
-	win.out_x = 0;
-	win.out_y = 0;
-	win.out_width = fbi->var.xres;
-	win.out_height = fbi->var.yres;
-	win.format = 0;
-
-	omapfb_rqueue_lock(fbdev);
-	r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct lcd_panel *panel = fbdev->panel;
-	struct omapfb_plane_info old_info;
-	int r = 0;
-
-	if (pi->pos_x + pi->out_width > panel->x_res ||
-	    pi->pos_y + pi->out_height > panel->y_res)
-		return -EINVAL;
-
-	omapfb_rqueue_lock(fbdev);
-	if (pi->enabled && !fbdev->mem_desc.region[plane->idx].size) {
-		/*
-		 * This plane's memory was freed, can't enable it
-		 * until it's reallocated.
-		 */
-		r = -EINVAL;
-		goto out;
-	}
-	old_info = plane->info;
-	plane->info = *pi;
-	if (pi->enabled) {
-		r = ctrl_change_mode(fbi);
-		if (r < 0) {
-			plane->info = old_info;
-			goto out;
-		}
-	}
-	r = fbdev->ctrl->enable_plane(plane->idx, pi->enabled);
-	if (r < 0) {
-		plane->info = old_info;
-		goto out;
-	}
-out:
-	omapfb_rqueue_unlock(fbdev);
-	return r;
-}
-
-static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-
-	*pi = plane->info;
-	return 0;
-}
-
-static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct omapfb_mem_region *rg = &fbdev->mem_desc.region[plane->idx];
-	size_t size;
-	int r = 0;
-
-	if (fbdev->ctrl->setup_mem == NULL)
-		return -ENODEV;
-	if (mi->type != OMAPFB_MEMTYPE_SDRAM)
-		return -EINVAL;
-
-	size = PAGE_ALIGN(mi->size);
-	omapfb_rqueue_lock(fbdev);
-	if (plane->info.enabled) {
-		r = -EBUSY;
-		goto out;
-	}
-	if (rg->size != size || rg->type != mi->type) {
-		struct fb_var_screeninfo *new_var = &fbdev->new_var;
-		unsigned long old_size = rg->size;
-		u8	      old_type = rg->type;
-		unsigned long paddr;
-
-		rg->size = size;
-		rg->type = mi->type;
-		/*
-		 * size == 0 is a special case, for which we
-		 * don't check / adjust the screen parameters.
-		 * This isn't a problem since the plane can't
-		 * be reenabled unless its size is > 0.
-		 */
-		if (old_size != size && size) {
-			if (size) {
-				memcpy(new_var, &fbi->var, sizeof(*new_var));
-				r = set_fb_var(fbi, new_var);
-				if (r < 0)
-					goto out;
-			}
-		}
-
-		if (fbdev->ctrl->sync)
-			fbdev->ctrl->sync();
-		r = fbdev->ctrl->setup_mem(plane->idx, size, mi->type, &paddr);
-		if (r < 0) {
-			/* Revert changes. */
-			rg->size = old_size;
-			rg->type = old_type;
-			goto out;
-		}
-		rg->paddr = paddr;
-
-		if (old_size != size) {
-			if (size) {
-				memcpy(&fbi->var, new_var, sizeof(fbi->var));
-				set_fb_fix(fbi, 0);
-			} else {
-				/*
-				 * Set these explicitly to indicate that the
-				 * plane memory is dealloce'd, the other
-				 * screen parameters in var / fix are invalid.
-				 */
-				mutex_lock(&fbi->mm_lock);
-				fbi->fix.smem_start = 0;
-				fbi->fix.smem_len = 0;
-				mutex_unlock(&fbi->mm_lock);
-			}
-		}
-	}
-out:
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	struct omapfb_mem_region *rg;
-
-	rg = &fbdev->mem_desc.region[plane->idx];
-	memset(mi, 0, sizeof(*mi));
-	mi->size = rg->size;
-	mi->type = rg->type;
-
-	return 0;
-}
-
-static int omapfb_set_color_key(struct omapfb_device *fbdev,
-				struct omapfb_color_key *ck)
-{
-	int r;
-
-	if (!fbdev->ctrl->set_color_key)
-		return -ENODEV;
-
-	omapfb_rqueue_lock(fbdev);
-	r = fbdev->ctrl->set_color_key(ck);
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-static int omapfb_get_color_key(struct omapfb_device *fbdev,
-				struct omapfb_color_key *ck)
-{
-	int r;
-
-	if (!fbdev->ctrl->get_color_key)
-		return -ENODEV;
-
-	omapfb_rqueue_lock(fbdev);
-	r = fbdev->ctrl->get_color_key(ck);
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM];
-static int notifier_inited;
-
-static void omapfb_init_notifier(void)
-{
-	int i;
-
-	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
-		BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]);
-}
-
-int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
-				omapfb_notifier_callback_t callback,
-				void *callback_data)
-{
-	int r;
-
-	if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
-		return -EINVAL;
-
-	if (!notifier_inited) {
-		omapfb_init_notifier();
-		notifier_inited = 1;
-	}
-
-	omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,
-					unsigned long, void *))callback;
-	omapfb_nb->data = callback_data;
-	r = blocking_notifier_chain_register(
-				&omapfb_client_list[omapfb_nb->plane_idx],
-				&omapfb_nb->nb);
-	if (r)
-		return r;
-	if (omapfb_dev != NULL &&
-	    omapfb_dev->ctrl && omapfb_dev->ctrl->bind_client) {
-		omapfb_dev->ctrl->bind_client(omapfb_nb);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(omapfb_register_client);
-
-int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb)
-{
-	return blocking_notifier_chain_unregister(
-		&omapfb_client_list[omapfb_nb->plane_idx], &omapfb_nb->nb);
-}
-EXPORT_SYMBOL(omapfb_unregister_client);
-
-void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event)
-{
-	int i;
-
-	if (!notifier_inited)
-		/* no client registered yet */
-		return;
-
-	for (i = 0; i < OMAPFB_PLANE_NUM; i++)
-		blocking_notifier_call_chain(&omapfb_client_list[i], event,
-				    fbdev->fb_info[i]);
-}
-EXPORT_SYMBOL(omapfb_notify_clients);
-
-static int omapfb_set_update_mode(struct omapfb_device *fbdev,
-				   enum omapfb_update_mode mode)
-{
-	int r;
-
-	omapfb_rqueue_lock(fbdev);
-	r = fbdev->ctrl->set_update_mode(mode);
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
-{
-	int r;
-
-	omapfb_rqueue_lock(fbdev);
-	r = fbdev->ctrl->get_update_mode();
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-static void omapfb_get_caps(struct omapfb_device *fbdev, int plane,
-				     struct omapfb_caps *caps)
-{
-	memset(caps, 0, sizeof(*caps));
-	fbdev->ctrl->get_caps(plane, caps);
-	caps->ctrl |= fbdev->panel->get_caps(fbdev->panel);
-}
-
-/* For lcd testing */
-void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
-{
-	omapfb_rqueue_lock(fbdev);
-	*(u16 *)fbdev->mem_desc.region[0].vaddr = pixval;
-	if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
-		struct omapfb_update_window win;
-
-		memset(&win, 0, sizeof(win));
-		win.width = 2;
-		win.height = 2;
-		win.out_width = 2;
-		win.out_height = 2;
-		fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL);
-	}
-	omapfb_rqueue_unlock(fbdev);
-}
-EXPORT_SYMBOL(omapfb_write_first_pixel);
-
-/*
- * Ioctl interface. Part of the kernel mode frame buffer API is duplicated
- * here to be accessible by user mode code.
- */
-static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
-			unsigned long arg)
-{
-	struct omapfb_plane_struct *plane = fbi->par;
-	struct omapfb_device	*fbdev = plane->fbdev;
-	struct fb_ops		*ops = fbi->fbops;
-	union {
-		struct omapfb_update_window	update_window;
-		struct omapfb_plane_info	plane_info;
-		struct omapfb_mem_info		mem_info;
-		struct omapfb_color_key		color_key;
-		enum omapfb_update_mode		update_mode;
-		struct omapfb_caps		caps;
-		unsigned int		mirror;
-		int			plane_out;
-		int			enable_plane;
-	} p;
-	int r = 0;
-
-	BUG_ON(!ops);
-	switch (cmd) {
-	case OMAPFB_MIRROR:
-		if (get_user(p.mirror, (int __user *)arg))
-			r = -EFAULT;
-		else
-			omapfb_mirror(fbi, p.mirror);
-		break;
-	case OMAPFB_SYNC_GFX:
-		omapfb_sync(fbi);
-		break;
-	case OMAPFB_VSYNC:
-		break;
-	case OMAPFB_SET_UPDATE_MODE:
-		if (get_user(p.update_mode, (int __user *)arg))
-			r = -EFAULT;
-		else
-			r = omapfb_set_update_mode(fbdev, p.update_mode);
-		break;
-	case OMAPFB_GET_UPDATE_MODE:
-		p.update_mode = omapfb_get_update_mode(fbdev);
-		if (put_user(p.update_mode,
-					(enum omapfb_update_mode __user *)arg))
-			r = -EFAULT;
-		break;
-	case OMAPFB_UPDATE_WINDOW_OLD:
-		if (copy_from_user(&p.update_window, (void __user *)arg,
-				   sizeof(struct omapfb_update_window_old)))
-			r = -EFAULT;
-		else {
-			struct omapfb_update_window *u = &p.update_window;
-			u->out_x = u->x;
-			u->out_y = u->y;
-			u->out_width = u->width;
-			u->out_height = u->height;
-			memset(u->reserved, 0, sizeof(u->reserved));
-			r = omapfb_update_win(fbi, u);
-		}
-		break;
-	case OMAPFB_UPDATE_WINDOW:
-		if (copy_from_user(&p.update_window, (void __user *)arg,
-				   sizeof(p.update_window)))
-			r = -EFAULT;
-		else
-			r = omapfb_update_win(fbi, &p.update_window);
-		break;
-	case OMAPFB_SETUP_PLANE:
-		if (copy_from_user(&p.plane_info, (void __user *)arg,
-				   sizeof(p.plane_info)))
-			r = -EFAULT;
-		else
-			r = omapfb_setup_plane(fbi, &p.plane_info);
-		break;
-	case OMAPFB_QUERY_PLANE:
-		if ((r = omapfb_query_plane(fbi, &p.plane_info)) < 0)
-			break;
-		if (copy_to_user((void __user *)arg, &p.plane_info,
-				   sizeof(p.plane_info)))
-			r = -EFAULT;
-		break;
-	case OMAPFB_SETUP_MEM:
-		if (copy_from_user(&p.mem_info, (void __user *)arg,
-				   sizeof(p.mem_info)))
-			r = -EFAULT;
-		else
-			r = omapfb_setup_mem(fbi, &p.mem_info);
-		break;
-	case OMAPFB_QUERY_MEM:
-		if ((r = omapfb_query_mem(fbi, &p.mem_info)) < 0)
-			break;
-		if (copy_to_user((void __user *)arg, &p.mem_info,
-				   sizeof(p.mem_info)))
-			r = -EFAULT;
-		break;
-	case OMAPFB_SET_COLOR_KEY:
-		if (copy_from_user(&p.color_key, (void __user *)arg,
-				   sizeof(p.color_key)))
-			r = -EFAULT;
-		else
-			r = omapfb_set_color_key(fbdev, &p.color_key);
-		break;
-	case OMAPFB_GET_COLOR_KEY:
-		if ((r = omapfb_get_color_key(fbdev, &p.color_key)) < 0)
-			break;
-		if (copy_to_user((void __user *)arg, &p.color_key,
-				 sizeof(p.color_key)))
-			r = -EFAULT;
-		break;
-	case OMAPFB_GET_CAPS:
-		omapfb_get_caps(fbdev, plane->idx, &p.caps);
-		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
-			r = -EFAULT;
-		break;
-	case OMAPFB_LCD_TEST:
-		{
-			int test_num;
-
-			if (get_user(test_num, (int __user *)arg)) {
-				r = -EFAULT;
-				break;
-			}
-			if (!fbdev->panel->run_test) {
-				r = -EINVAL;
-				break;
-			}
-			r = fbdev->panel->run_test(fbdev->panel, test_num);
-			break;
-		}
-	case OMAPFB_CTRL_TEST:
-		{
-			int test_num;
-
-			if (get_user(test_num, (int __user *)arg)) {
-				r = -EFAULT;
-				break;
-			}
-			if (!fbdev->ctrl->run_test) {
-				r = -EINVAL;
-				break;
-			}
-			r = fbdev->ctrl->run_test(test_num);
-			break;
-		}
-	default:
-		r = -EINVAL;
-	}
-
-	return r;
-}
-
-static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct omapfb_plane_struct *plane = info->par;
-	struct omapfb_device *fbdev = plane->fbdev;
-	int r;
-
-	omapfb_rqueue_lock(fbdev);
-	r = fbdev->ctrl->mmap(info, vma);
-	omapfb_rqueue_unlock(fbdev);
-
-	return r;
-}
-
-/*
- * Callback table for the frame buffer framework. Some of these pointers
- * will be changed according to the current setting of fb_info->accel_flags.
- */
-static struct fb_ops omapfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open        = omapfb_open,
-	.fb_release     = omapfb_release,
-	.fb_setcolreg	= omapfb_setcolreg,
-	.fb_setcmap	= omapfb_setcmap,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_blank       = omapfb_blank,
-	.fb_ioctl	= omapfb_ioctl,
-	.fb_check_var	= omapfb_check_var,
-	.fb_set_par	= omapfb_set_par,
-	.fb_rotate	= omapfb_rotate,
-	.fb_pan_display = omapfb_pan_display,
-};
-
-/*
- * ---------------------------------------------------------------------------
- * Sysfs interface
- * ---------------------------------------------------------------------------
- */
-/* omapfbX sysfs entries */
-static ssize_t omapfb_show_caps_num(struct device *dev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct omapfb_device *fbdev = dev_get_drvdata(dev);
-	int plane;
-	size_t size;
-	struct omapfb_caps caps;
-
-	plane = 0;
-	size = 0;
-	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
-		omapfb_get_caps(fbdev, plane, &caps);
-		size += snprintf(&buf[size], PAGE_SIZE - size,
-			"plane#%d %#010x %#010x %#010x\n",
-			plane, caps.ctrl, caps.plane_color, caps.wnd_color);
-		plane++;
-	}
-	return size;
-}
-
-static ssize_t omapfb_show_caps_text(struct device *dev,
-				     struct device_attribute *attr, char *buf)
-{
-	struct omapfb_device *fbdev = dev_get_drvdata(dev);
-	int i;
-	struct omapfb_caps caps;
-	int plane;
-	size_t size;
-
-	plane = 0;
-	size = 0;
-	while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
-		omapfb_get_caps(fbdev, plane, &caps);
-		size += snprintf(&buf[size], PAGE_SIZE - size,
-				 "plane#%d:\n", plane);
-		for (i = 0; i < ARRAY_SIZE(ctrl_caps) &&
-		     size < PAGE_SIZE; i++) {
-			if (ctrl_caps[i].flag & caps.ctrl)
-				size += snprintf(&buf[size], PAGE_SIZE - size,
-					" %s\n", ctrl_caps[i].name);
-		}
-		size += snprintf(&buf[size], PAGE_SIZE - size,
-				 " plane colors:\n");
-		for (i = 0; i < ARRAY_SIZE(color_caps) &&
-		     size < PAGE_SIZE; i++) {
-			if (color_caps[i].flag & caps.plane_color)
-				size += snprintf(&buf[size], PAGE_SIZE - size,
-					"  %s\n", color_caps[i].name);
-		}
-		size += snprintf(&buf[size], PAGE_SIZE - size,
-				 " window colors:\n");
-		for (i = 0; i < ARRAY_SIZE(color_caps) &&
-		     size < PAGE_SIZE; i++) {
-			if (color_caps[i].flag & caps.wnd_color)
-				size += snprintf(&buf[size], PAGE_SIZE - size,
-					"  %s\n", color_caps[i].name);
-		}
-
-		plane++;
-	}
-	return size;
-}
-
-static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
-static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
-
-/* panel sysfs entries */
-static ssize_t omapfb_show_panel_name(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct omapfb_device *fbdev = dev_get_drvdata(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
-}
-
-static ssize_t omapfb_show_bklight_level(struct device *dev,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	struct omapfb_device *fbdev = dev_get_drvdata(dev);
-	int r;
-
-	if (fbdev->panel->get_bklight_level) {
-		r = snprintf(buf, PAGE_SIZE, "%d\n",
-			     fbdev->panel->get_bklight_level(fbdev->panel));
-	} else
-		r = -ENODEV;
-	return r;
-}
-
-static ssize_t omapfb_store_bklight_level(struct device *dev,
-					  struct device_attribute *attr,
-					  const char *buf, size_t size)
-{
-	struct omapfb_device *fbdev = dev_get_drvdata(dev);
-	int r;
-
-	if (fbdev->panel->set_bklight_level) {
-		unsigned int level;
-
-		if (sscanf(buf, "%10d", &level) == 1) {
-			r = fbdev->panel->set_bklight_level(fbdev->panel,
-							    level);
-		} else
-			r = -EINVAL;
-	} else
-		r = -ENODEV;
-	return r ? r : size;
-}
-
-static ssize_t omapfb_show_bklight_max(struct device *dev,
-				       struct device_attribute *attr, char *buf)
-{
-	struct omapfb_device *fbdev = dev_get_drvdata(dev);
-	int r;
-
-	if (fbdev->panel->get_bklight_level) {
-		r = snprintf(buf, PAGE_SIZE, "%d\n",
-			     fbdev->panel->get_bklight_max(fbdev->panel));
-	} else
-		r = -ENODEV;
-	return r;
-}
-
-static struct device_attribute dev_attr_panel_name =
-	__ATTR(name, 0444, omapfb_show_panel_name, NULL);
-static DEVICE_ATTR(backlight_level, 0664,
-		   omapfb_show_bklight_level, omapfb_store_bklight_level);
-static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
-
-static struct attribute *panel_attrs[] = {
-	&dev_attr_panel_name.attr,
-	&dev_attr_backlight_level.attr,
-	&dev_attr_backlight_max.attr,
-	NULL,
-};
-
-static struct attribute_group panel_attr_grp = {
-	.name  = "panel",
-	.attrs = panel_attrs,
-};
-
-/* ctrl sysfs entries */
-static ssize_t omapfb_show_ctrl_name(struct device *dev,
-				     struct device_attribute *attr, char *buf)
-{
-	struct omapfb_device *fbdev = dev_get_drvdata(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
-}
-
-static struct device_attribute dev_attr_ctrl_name =
-	__ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
-
-static struct attribute *ctrl_attrs[] = {
-	&dev_attr_ctrl_name.attr,
-	NULL,
-};
-
-static struct attribute_group ctrl_attr_grp = {
-	.name  = "ctrl",
-	.attrs = ctrl_attrs,
-};
-
-static int omapfb_register_sysfs(struct omapfb_device *fbdev)
-{
-	int r;
-
-	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
-		goto fail0;
-
-	if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
-		goto fail1;
-
-	if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
-		goto fail2;
-
-	if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
-		goto fail3;
-
-	return 0;
-fail3:
-	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
-fail2:
-	device_remove_file(fbdev->dev, &dev_attr_caps_text);
-fail1:
-	device_remove_file(fbdev->dev, &dev_attr_caps_num);
-fail0:
-	dev_err(fbdev->dev, "unable to register sysfs interface\n");
-	return r;
-}
-
-static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
-{
-	sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
-	sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
-	device_remove_file(fbdev->dev, &dev_attr_caps_num);
-	device_remove_file(fbdev->dev, &dev_attr_caps_text);
-}
-
-/*
- * ---------------------------------------------------------------------------
- * LDM callbacks
- * ---------------------------------------------------------------------------
- */
-/* Initialize system fb_info object and set the default video mode.
- * The frame buffer memory already allocated by lcddma_init
- */
-static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
-{
-	struct fb_var_screeninfo	*var = &info->var;
-	struct fb_fix_screeninfo	*fix = &info->fix;
-	int				r = 0;
-
-	info->fbops = &omapfb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
-
-	strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
-
-	info->pseudo_palette = fbdev->pseudo_palette;
-
-	var->accel_flags  = def_accel ? FB_ACCELF_TEXT : 0;
-	var->xres = def_vxres;
-	var->yres = def_vyres;
-	var->xres_virtual = def_vxres;
-	var->yres_virtual = def_vyres;
-	var->rotate	  = def_rotate;
-	var->bits_per_pixel = fbdev->panel->bpp;
-
-	set_fb_var(info, var);
-	set_fb_fix(info, 1);
-
-	r = fb_alloc_cmap(&info->cmap, 16, 0);
-	if (r != 0)
-		dev_err(fbdev->dev, "unable to allocate color map memory\n");
-
-	return r;
-}
-
-/* Release the fb_info object */
-static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi)
-{
-	fb_dealloc_cmap(&fbi->cmap);
-}
-
-static void planes_cleanup(struct omapfb_device *fbdev)
-{
-	int i;
-
-	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
-		if (fbdev->fb_info[i] == NULL)
-			break;
-		fbinfo_cleanup(fbdev, fbdev->fb_info[i]);
-		framebuffer_release(fbdev->fb_info[i]);
-	}
-}
-
-static int planes_init(struct omapfb_device *fbdev)
-{
-	struct fb_info *fbi;
-	int i;
-	int r;
-
-	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
-		struct omapfb_plane_struct *plane;
-		fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct),
-					fbdev->dev);
-		if (fbi == NULL) {
-			dev_err(fbdev->dev,
-				"unable to allocate memory for plane info\n");
-			planes_cleanup(fbdev);
-			return -ENOMEM;
-		}
-		plane = fbi->par;
-		plane->idx = i;
-		plane->fbdev = fbdev;
-		plane->info.mirror = def_mirror;
-		fbdev->fb_info[i] = fbi;
-
-		if ((r = fbinfo_init(fbdev, fbi)) < 0) {
-			framebuffer_release(fbi);
-			planes_cleanup(fbdev);
-			return r;
-		}
-		plane->info.out_width = fbi->var.xres;
-		plane->info.out_height = fbi->var.yres;
-	}
-	return 0;
-}
-
-/*
- * Free driver resources. Can be called to rollback an aborted initialization
- * sequence.
- */
-static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
-{
-	int i;
-
-	switch (state) {
-	case OMAPFB_ACTIVE:
-		for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
-			unregister_framebuffer(fbdev->fb_info[i]);
-	case 7:
-		omapfb_unregister_sysfs(fbdev);
-	case 6:
-		fbdev->panel->disable(fbdev->panel);
-	case 5:
-		omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
-	case 4:
-		planes_cleanup(fbdev);
-	case 3:
-		ctrl_cleanup(fbdev);
-	case 2:
-		fbdev->panel->cleanup(fbdev->panel);
-	case 1:
-		dev_set_drvdata(fbdev->dev, NULL);
-		kfree(fbdev);
-	case 0:
-		/* nothing to free */
-		break;
-	default:
-		BUG();
-	}
-}
-
-static int omapfb_find_ctrl(struct omapfb_device *fbdev)
-{
-	struct omapfb_platform_data *conf;
-	char name[17];
-	int i;
-
-	conf = dev_get_platdata(fbdev->dev);
-
-	fbdev->ctrl = NULL;
-
-	strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1);
-	name[sizeof(name) - 1] = '\0';
-
-	if (strcmp(name, "internal") == 0) {
-		fbdev->ctrl = fbdev->int_ctrl;
-		return 0;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
-		dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name);
-		if (strcmp(ctrls[i]->name, name) == 0) {
-			fbdev->ctrl = ctrls[i];
-			break;
-		}
-	}
-
-	if (fbdev->ctrl == NULL) {
-		dev_dbg(fbdev->dev, "ctrl %s not supported\n", name);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void check_required_callbacks(struct omapfb_device *fbdev)
-{
-#define _C(x) (fbdev->ctrl->x != NULL)
-#define _P(x) (fbdev->panel->x != NULL)
-	BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL);
-	BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
-		 _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) &&
-		 _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
-		 _P(get_caps)));
-#undef _P
-#undef _C
-}
-
-/*
- * Called by LDM binding to probe and attach a new device.
- * Initialization sequence:
- *   1. allocate system omapfb_device structure
- *   2. select controller type according to platform configuration
- *      init LCD panel
- *   3. init LCD controller and LCD DMA
- *   4. init system fb_info structure for all planes
- *   5. setup video mode for first plane and enable it
- *   6. enable LCD panel
- *   7. register sysfs attributes
- *   OMAPFB_ACTIVE: register system fb_info structure for all planes
- */
-static int omapfb_do_probe(struct platform_device *pdev,
-				struct lcd_panel *panel)
-{
-	struct omapfb_device	*fbdev = NULL;
-	int			init_state;
-	unsigned long		phz, hhz, vhz;
-	unsigned long		vram;
-	int			i;
-	int			r = 0;
-
-	init_state = 0;
-
-	if (pdev->num_resources != 0) {
-		dev_err(&pdev->dev, "probed for an unknown device\n");
-		r = -ENODEV;
-		goto cleanup;
-	}
-
-	if (dev_get_platdata(&pdev->dev) == NULL) {
-		dev_err(&pdev->dev, "missing platform data\n");
-		r = -ENOENT;
-		goto cleanup;
-	}
-
-	fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL);
-	if (fbdev == NULL) {
-		dev_err(&pdev->dev,
-			"unable to allocate memory for device info\n");
-		r = -ENOMEM;
-		goto cleanup;
-	}
-	init_state++;
-
-	fbdev->dev = &pdev->dev;
-	fbdev->panel = panel;
-	fbdev->dssdev = &omapdss_device;
-	platform_set_drvdata(pdev, fbdev);
-
-	mutex_init(&fbdev->rqueue_mutex);
-
-	fbdev->int_ctrl = &omap1_int_ctrl;
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-	fbdev->ext_if = &omap1_ext_if;
-#endif
-	if (omapfb_find_ctrl(fbdev) < 0) {
-		dev_err(fbdev->dev,
-			"LCD controller not found, board not supported\n");
-		r = -ENODEV;
-		goto cleanup;
-	}
-
-	r = fbdev->panel->init(fbdev->panel, fbdev);
-	if (r)
-		goto cleanup;
-
-	pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
-
-	def_vxres = def_vxres ? def_vxres : fbdev->panel->x_res;
-	def_vyres = def_vyres ? def_vyres : fbdev->panel->y_res;
-
-	init_state++;
-
-	r = ctrl_init(fbdev);
-	if (r)
-		goto cleanup;
-	if (fbdev->ctrl->mmap != NULL)
-		omapfb_ops.fb_mmap = omapfb_mmap;
-	init_state++;
-
-	check_required_callbacks(fbdev);
-
-	r = planes_init(fbdev);
-	if (r)
-		goto cleanup;
-	init_state++;
-
-#ifdef CONFIG_FB_OMAP_DMA_TUNE
-	/* Set DMA priority for EMIFF access to highest */
-	omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
-#endif
-
-	r = ctrl_change_mode(fbdev->fb_info[0]);
-	if (r) {
-		dev_err(fbdev->dev, "mode setting failed\n");
-		goto cleanup;
-	}
-
-	/* GFX plane is enabled by default */
-	r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
-	if (r)
-		goto cleanup;
-
-	omapfb_set_update_mode(fbdev, manual_update ?
-				   OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
-	init_state++;
-
-	r = fbdev->panel->enable(fbdev->panel);
-	if (r)
-		goto cleanup;
-	init_state++;
-
-	r = omapfb_register_sysfs(fbdev);
-	if (r)
-		goto cleanup;
-	init_state++;
-
-	vram = 0;
-	for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
-		r = register_framebuffer(fbdev->fb_info[i]);
-		if (r != 0) {
-			dev_err(fbdev->dev,
-				"registering framebuffer %d failed\n", i);
-			goto cleanup;
-		}
-		vram += fbdev->mem_desc.region[i].size;
-	}
-
-	fbdev->state = OMAPFB_ACTIVE;
-
-	panel = fbdev->panel;
-	phz = panel->pixel_clock * 1000;
-	hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
-	vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
-
-	omapfb_dev = fbdev;
-
-	pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n",
-			vram, fbdev->mem_desc.region_cnt);
-	pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz "
-			"vfreq %lu.%lu Hz\n",
-			phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
-
-	return 0;
-
-cleanup:
-	omapfb_free_resources(fbdev, init_state);
-
-	return r;
-}
-
-static int omapfb_probe(struct platform_device *pdev)
-{
-	int r;
-
-	BUG_ON(fbdev_pdev != NULL);
-
-	r = platform_device_register(&omapdss_device);
-	if (r) {
-		dev_err(&pdev->dev, "can't register omapdss device\n");
-		return r;
-	}
-
-	/* Delay actual initialization until the LCD is registered */
-	fbdev_pdev = pdev;
-	if (fbdev_panel != NULL)
-		omapfb_do_probe(fbdev_pdev, fbdev_panel);
-	return 0;
-}
-
-void omapfb_register_panel(struct lcd_panel *panel)
-{
-	BUG_ON(fbdev_panel != NULL);
-
-	fbdev_panel = panel;
-	if (fbdev_pdev != NULL)
-		omapfb_do_probe(fbdev_pdev, fbdev_panel);
-}
-
-/* Called when the device is being detached from the driver */
-static int omapfb_remove(struct platform_device *pdev)
-{
-	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
-	enum omapfb_state saved_state = fbdev->state;
-
-	/* FIXME: wait till completion of pending events */
-
-	fbdev->state = OMAPFB_DISABLED;
-	omapfb_free_resources(fbdev, saved_state);
-
-	platform_device_unregister(&omapdss_device);
-	fbdev->dssdev = NULL;
-
-	return 0;
-}
-
-/* PM suspend */
-static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
-
-	if (fbdev != NULL)
-		omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]);
-	return 0;
-}
-
-/* PM resume */
-static int omapfb_resume(struct platform_device *pdev)
-{
-	struct omapfb_device *fbdev = platform_get_drvdata(pdev);
-
-	if (fbdev != NULL)
-		omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]);
-	return 0;
-}
-
-static struct platform_driver omapfb_driver = {
-	.probe		= omapfb_probe,
-	.remove		= omapfb_remove,
-	.suspend	= omapfb_suspend,
-	.resume		= omapfb_resume,
-	.driver		= {
-		.name	= MODULE_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-#ifndef MODULE
-
-/* Process kernel command line parameters */
-static int __init omapfb_setup(char *options)
-{
-	char *this_opt = NULL;
-	int r = 0;
-
-	pr_debug("omapfb: options %s\n", options);
-
-	if (!options || !*options)
-		return 0;
-
-	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "accel", 5))
-			def_accel = 1;
-		else if (!strncmp(this_opt, "vram:", 5)) {
-			char *suffix;
-			unsigned long vram;
-			vram = (simple_strtoul(this_opt + 5, &suffix, 0));
-			switch (suffix[0]) {
-			case '\0':
-				break;
-			case 'm':
-			case 'M':
-				vram *= 1024;
-				/* Fall through */
-			case 'k':
-			case 'K':
-				vram *= 1024;
-				break;
-			default:
-				pr_debug("omapfb: invalid vram suffix %c\n",
-					 suffix[0]);
-				r = -1;
-			}
-			def_vram[def_vram_cnt++] = vram;
-		}
-		else if (!strncmp(this_opt, "vxres:", 6))
-			def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
-		else if (!strncmp(this_opt, "vyres:", 6))
-			def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
-		else if (!strncmp(this_opt, "rotate:", 7))
-			def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
-		else if (!strncmp(this_opt, "mirror:", 7))
-			def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
-		else if (!strncmp(this_opt, "manual_update", 13))
-			manual_update = 1;
-		else {
-			pr_debug("omapfb: invalid option\n");
-			r = -1;
-		}
-	}
-
-	return r;
-}
-
-#endif
-
-/* Register both the driver and the device */
-static int __init omapfb_init(void)
-{
-#ifndef MODULE
-	char *option;
-
-	if (fb_get_options("omapfb", &option))
-		return -ENODEV;
-	omapfb_setup(option);
-#endif
-	/* Register the driver with LDM */
-	if (platform_driver_register(&omapfb_driver)) {
-		pr_debug("failed to register omapfb driver\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void __exit omapfb_cleanup(void)
-{
-	platform_driver_unregister(&omapfb_driver);
-}
-
-module_param_named(accel, def_accel, uint, 0664);
-module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664);
-module_param_named(vxres, def_vxres, long, 0664);
-module_param_named(vyres, def_vyres, long, 0664);
-module_param_named(rotate, def_rotate, uint, 0664);
-module_param_named(mirror, def_mirror, uint, 0664);
-module_param_named(manual_update, manual_update, bool, 0664);
-
-module_init(omapfb_init);
-module_exit(omapfb_cleanup);
-
-MODULE_DESCRIPTION("TI OMAP framebuffer driver");
-MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
deleted file mode 100644
index d4e7684e7045..000000000000
--- a/drivers/video/omap/sossi.c
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * OMAP1 Special OptimiSed Screen Interface support
- *
- * Copyright (C) 2004-2005 Nokia Corporation
- * Author: Juha Yrjölä <juha.yrjola@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-
-#include <linux/omap-dma.h>
-
-#include "omapfb.h"
-#include "lcdc.h"
-
-#define MODULE_NAME		"omapfb-sossi"
-
-#define OMAP_SOSSI_BASE         0xfffbac00
-#define SOSSI_ID_REG		0x00
-#define SOSSI_INIT1_REG		0x04
-#define SOSSI_INIT2_REG		0x08
-#define SOSSI_INIT3_REG		0x0c
-#define SOSSI_FIFO_REG		0x10
-#define SOSSI_REOTABLE_REG	0x14
-#define SOSSI_TEARING_REG	0x18
-#define SOSSI_INIT1B_REG	0x1c
-#define SOSSI_FIFOB_REG		0x20
-
-#define DMA_GSCR          0xfffedc04
-#define DMA_LCD_CCR       0xfffee3c2
-#define DMA_LCD_CTRL      0xfffee3c4
-#define DMA_LCD_LCH_CTRL  0xfffee3ea
-
-#define CONF_SOSSI_RESET_R      (1 << 23)
-
-#define RD_ACCESS		0
-#define WR_ACCESS		1
-
-#define SOSSI_MAX_XMIT_BYTES	(512 * 1024)
-
-static struct {
-	void __iomem	*base;
-	struct clk	*fck;
-	unsigned long	fck_hz;
-	spinlock_t	lock;
-	int		bus_pick_count;
-	int		bus_pick_width;
-	int		tearsync_mode;
-	int		tearsync_line;
-	void		(*lcdc_callback)(void *data);
-	void		*lcdc_callback_data;
-	int		vsync_dma_pending;
-	/* timing for read and write access */
-	int		clk_div;
-	u8		clk_tw0[2];
-	u8		clk_tw1[2];
-	/*
-	 * if last_access is the same as current we don't have to change
-	 * the timings
-	 */
-	int		last_access;
-
-	struct omapfb_device	*fbdev;
-} sossi;
-
-static inline u32 sossi_read_reg(int reg)
-{
-	return readl(sossi.base + reg);
-}
-
-static inline u16 sossi_read_reg16(int reg)
-{
-	return readw(sossi.base + reg);
-}
-
-static inline u8 sossi_read_reg8(int reg)
-{
-	return readb(sossi.base + reg);
-}
-
-static inline void sossi_write_reg(int reg, u32 value)
-{
-	writel(value, sossi.base + reg);
-}
-
-static inline void sossi_write_reg16(int reg, u16 value)
-{
-	writew(value, sossi.base + reg);
-}
-
-static inline void sossi_write_reg8(int reg, u8 value)
-{
-	writeb(value, sossi.base + reg);
-}
-
-static void sossi_set_bits(int reg, u32 bits)
-{
-	sossi_write_reg(reg, sossi_read_reg(reg) | bits);
-}
-
-static void sossi_clear_bits(int reg, u32 bits)
-{
-	sossi_write_reg(reg, sossi_read_reg(reg) & ~bits);
-}
-
-#define HZ_TO_PS(x)	(1000000000 / (x / 1000))
-
-static u32 ps_to_sossi_ticks(u32 ps, int div)
-{
-	u32 clk_period = HZ_TO_PS(sossi.fck_hz) * div;
-	return (clk_period + ps - 1) / clk_period;
-}
-
-static int calc_rd_timings(struct extif_timings *t)
-{
-	u32 tw0, tw1;
-	int reon, reoff, recyc, actim;
-	int div = t->clk_div;
-
-	/*
-	 * Make sure that after conversion it still holds that:
-	 * reoff > reon, recyc >= reoff, actim > reon
-	 */
-	reon = ps_to_sossi_ticks(t->re_on_time, div);
-	/* reon will be exactly one sossi tick */
-	if (reon > 1)
-		return -1;
-
-	reoff = ps_to_sossi_ticks(t->re_off_time, div);
-
-	if (reoff <= reon)
-		reoff = reon + 1;
-
-	tw0 = reoff - reon;
-	if (tw0 > 0x10)
-		return -1;
-
-	recyc = ps_to_sossi_ticks(t->re_cycle_time, div);
-	if (recyc <= reoff)
-		recyc = reoff + 1;
-
-	tw1 = recyc - tw0;
-	/* values less then 3 result in the SOSSI block resetting itself */
-	if (tw1 < 3)
-		tw1 = 3;
-	if (tw1 > 0x40)
-		return -1;
-
-	actim = ps_to_sossi_ticks(t->access_time, div);
-	if (actim < reoff)
-		actim++;
-	/*
-	 * access time (data hold time) will be exactly one sossi
-	 * tick
-	 */
-	if (actim - reoff > 1)
-		return -1;
-
-	t->tim[0] = tw0 - 1;
-	t->tim[1] = tw1 - 1;
-
-	return 0;
-}
-
-static int calc_wr_timings(struct extif_timings *t)
-{
-	u32 tw0, tw1;
-	int weon, weoff, wecyc;
-	int div = t->clk_div;
-
-	/*
-	 * Make sure that after conversion it still holds that:
-	 * weoff > weon, wecyc >= weoff
-	 */
-	weon = ps_to_sossi_ticks(t->we_on_time, div);
-	/* weon will be exactly one sossi tick */
-	if (weon > 1)
-		return -1;
-
-	weoff = ps_to_sossi_ticks(t->we_off_time, div);
-	if (weoff <= weon)
-		weoff = weon + 1;
-	tw0 = weoff - weon;
-	if (tw0 > 0x10)
-		return -1;
-
-	wecyc = ps_to_sossi_ticks(t->we_cycle_time, div);
-	if (wecyc <= weoff)
-		wecyc = weoff + 1;
-
-	tw1 = wecyc - tw0;
-	/* values less then 3 result in the SOSSI block resetting itself */
-	if (tw1 < 3)
-		tw1 = 3;
-	if (tw1 > 0x40)
-		return -1;
-
-	t->tim[2] = tw0 - 1;
-	t->tim[3] = tw1 - 1;
-
-	return 0;
-}
-
-static void _set_timing(int div, int tw0, int tw1)
-{
-	u32 l;
-
-#ifdef VERBOSE
-	dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n",
-		 tw0 + 1, tw1 + 1, div);
-#endif
-
-	clk_set_rate(sossi.fck, sossi.fck_hz / div);
-	clk_enable(sossi.fck);
-	l = sossi_read_reg(SOSSI_INIT1_REG);
-	l &= ~((0x0f << 20) | (0x3f << 24));
-	l |= (tw0 << 20) | (tw1 << 24);
-	sossi_write_reg(SOSSI_INIT1_REG, l);
-	clk_disable(sossi.fck);
-}
-
-static void _set_bits_per_cycle(int bus_pick_count, int bus_pick_width)
-{
-	u32 l;
-
-	l = sossi_read_reg(SOSSI_INIT3_REG);
-	l &= ~0x3ff;
-	l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
-	sossi_write_reg(SOSSI_INIT3_REG, l);
-}
-
-static void _set_tearsync_mode(int mode, unsigned line)
-{
-	u32 l;
-
-	l = sossi_read_reg(SOSSI_TEARING_REG);
-	l &= ~(((1 << 11) - 1) << 15);
-	l |= line << 15;
-	l &= ~(0x3 << 26);
-	l |= mode << 26;
-	sossi_write_reg(SOSSI_TEARING_REG, l);
-	if (mode)
-		sossi_set_bits(SOSSI_INIT2_REG, 1 << 6);	/* TE logic */
-	else
-		sossi_clear_bits(SOSSI_INIT2_REG, 1 << 6);
-}
-
-static inline void set_timing(int access)
-{
-	if (access != sossi.last_access) {
-		sossi.last_access = access;
-		_set_timing(sossi.clk_div,
-			    sossi.clk_tw0[access], sossi.clk_tw1[access]);
-	}
-}
-
-static void sossi_start_transfer(void)
-{
-	/* WE */
-	sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4);
-	/* CS active low */
-	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30);
-}
-
-static void sossi_stop_transfer(void)
-{
-	/* WE */
-	sossi_set_bits(SOSSI_INIT2_REG, 1 << 4);
-	/* CS active low */
-	sossi_set_bits(SOSSI_INIT1_REG, 1 << 30);
-}
-
-static void wait_end_of_write(void)
-{
-	/* Before reading we must check if some writings are going on */
-	while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3)));
-}
-
-static void send_data(const void *data, unsigned int len)
-{
-	while (len >= 4) {
-		sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data);
-		len -= 4;
-		data += 4;
-	}
-	while (len >= 2) {
-		sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data);
-		len -= 2;
-		data += 2;
-	}
-	while (len) {
-		sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data);
-		len--;
-		data++;
-	}
-}
-
-static void set_cycles(unsigned int len)
-{
-	unsigned long nr_cycles = len / (sossi.bus_pick_width / 8);
-
-	BUG_ON((nr_cycles - 1) & ~0x3ffff);
-
-	sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff);
-	sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
-}
-
-static int sossi_convert_timings(struct extif_timings *t)
-{
-	int r = 0;
-	int div = t->clk_div;
-
-	t->converted = 0;
-
-	if (div <= 0 || div > 8)
-		return -1;
-
-	/* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */
-	if ((r = calc_rd_timings(t)) < 0)
-		return r;
-
-	if ((r = calc_wr_timings(t)) < 0)
-		return r;
-
-	t->tim[4] = div;
-
-	t->converted = 1;
-
-	return 0;
-}
-
-static void sossi_set_timings(const struct extif_timings *t)
-{
-	BUG_ON(!t->converted);
-
-	sossi.clk_tw0[RD_ACCESS] = t->tim[0];
-	sossi.clk_tw1[RD_ACCESS] = t->tim[1];
-
-	sossi.clk_tw0[WR_ACCESS] = t->tim[2];
-	sossi.clk_tw1[WR_ACCESS] = t->tim[3];
-
-	sossi.clk_div = t->tim[4];
-}
-
-static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
-{
-	*clk_period = HZ_TO_PS(sossi.fck_hz);
-	*max_clk_div = 8;
-}
-
-static void sossi_set_bits_per_cycle(int bpc)
-{
-	int bus_pick_count, bus_pick_width;
-
-	/*
-	 * We set explicitly the the bus_pick_count as well, although
-	 * with remapping/reordering disabled it will be calculated by HW
-	 * as (32 / bus_pick_width).
-	 */
-	switch (bpc) {
-	case 8:
-		bus_pick_count = 4;
-		bus_pick_width = 8;
-		break;
-	case 16:
-		bus_pick_count = 2;
-		bus_pick_width = 16;
-		break;
-	default:
-		BUG();
-		return;
-	}
-	sossi.bus_pick_width = bus_pick_width;
-	sossi.bus_pick_count = bus_pick_count;
-}
-
-static int sossi_setup_tearsync(unsigned pin_cnt,
-				unsigned hs_pulse_time, unsigned vs_pulse_time,
-				int hs_pol_inv, int vs_pol_inv, int div)
-{
-	int hs, vs;
-	u32 l;
-
-	if (pin_cnt != 1 || div < 1 || div > 8)
-		return -EINVAL;
-
-	hs = ps_to_sossi_ticks(hs_pulse_time, div);
-	vs = ps_to_sossi_ticks(vs_pulse_time, div);
-	if (vs < 8 || vs <= hs || vs >= (1 << 12))
-		return -EDOM;
-	vs /= 8;
-	vs--;
-	if (hs > 8)
-		hs = 8;
-	if (hs)
-		hs--;
-
-	dev_dbg(sossi.fbdev->dev,
-		"setup_tearsync: hs %d vs %d hs_inv %d vs_inv %d\n",
-		hs, vs, hs_pol_inv, vs_pol_inv);
-
-	clk_enable(sossi.fck);
-	l = sossi_read_reg(SOSSI_TEARING_REG);
-	l &= ~((1 << 15) - 1);
-	l |= vs << 3;
-	l |= hs;
-	if (hs_pol_inv)
-		l |= 1 << 29;
-	else
-		l &= ~(1 << 29);
-	if (vs_pol_inv)
-		l |= 1 << 28;
-	else
-		l &= ~(1 << 28);
-	sossi_write_reg(SOSSI_TEARING_REG, l);
-	clk_disable(sossi.fck);
-
-	return 0;
-}
-
-static int sossi_enable_tearsync(int enable, unsigned line)
-{
-	int mode;
-
-	dev_dbg(sossi.fbdev->dev, "tearsync %d line %d\n", enable, line);
-	if (line >= 1 << 11)
-		return -EINVAL;
-	if (enable) {
-		if (line)
-			mode = 2;		/* HS or VS */
-		else
-			mode = 3;		/* VS only */
-	} else
-		mode = 0;
-	sossi.tearsync_line = line;
-	sossi.tearsync_mode = mode;
-
-	return 0;
-}
-
-static void sossi_write_command(const void *data, unsigned int len)
-{
-	clk_enable(sossi.fck);
-	set_timing(WR_ACCESS);
-	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
-	/* CMD#/DATA */
-	sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18);
-	set_cycles(len);
-	sossi_start_transfer();
-	send_data(data, len);
-	sossi_stop_transfer();
-	wait_end_of_write();
-	clk_disable(sossi.fck);
-}
-
-static void sossi_write_data(const void *data, unsigned int len)
-{
-	clk_enable(sossi.fck);
-	set_timing(WR_ACCESS);
-	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
-	/* CMD#/DATA */
-	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
-	set_cycles(len);
-	sossi_start_transfer();
-	send_data(data, len);
-	sossi_stop_transfer();
-	wait_end_of_write();
-	clk_disable(sossi.fck);
-}
-
-static void sossi_transfer_area(int width, int height,
-				void (callback)(void *data), void *data)
-{
-	BUG_ON(callback == NULL);
-
-	sossi.lcdc_callback = callback;
-	sossi.lcdc_callback_data = data;
-
-	clk_enable(sossi.fck);
-	set_timing(WR_ACCESS);
-	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
-	_set_tearsync_mode(sossi.tearsync_mode, sossi.tearsync_line);
-	/* CMD#/DATA */
-	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
-	set_cycles(width * height * sossi.bus_pick_width / 8);
-
-	sossi_start_transfer();
-	if (sossi.tearsync_mode) {
-		/*
-		 * Wait for the sync signal and start the transfer only
-		 * then. We can't seem to be able to use HW sync DMA for
-		 * this since LCD DMA shows huge latencies, as if it
-		 * would ignore some of the DMA requests from SoSSI.
-		 */
-		unsigned long flags;
-
-		spin_lock_irqsave(&sossi.lock, flags);
-		sossi.vsync_dma_pending++;
-		spin_unlock_irqrestore(&sossi.lock, flags);
-	} else
-		/* Just start the transfer right away. */
-		omap_enable_lcd_dma();
-}
-
-static void sossi_dma_callback(void *data)
-{
-	omap_stop_lcd_dma();
-	sossi_stop_transfer();
-	clk_disable(sossi.fck);
-	sossi.lcdc_callback(sossi.lcdc_callback_data);
-}
-
-static void sossi_read_data(void *data, unsigned int len)
-{
-	clk_enable(sossi.fck);
-	set_timing(RD_ACCESS);
-	_set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
-	/* CMD#/DATA */
-	sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
-	set_cycles(len);
-	sossi_start_transfer();
-	while (len >= 4) {
-		*(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG);
-		len -= 4;
-		data += 4;
-	}
-	while (len >= 2) {
-		*(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG);
-		len -= 2;
-		data += 2;
-	}
-	while (len) {
-		*(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG);
-		len--;
-		data++;
-	}
-	sossi_stop_transfer();
-	clk_disable(sossi.fck);
-}
-
-static irqreturn_t sossi_match_irq(int irq, void *data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&sossi.lock, flags);
-	if (sossi.vsync_dma_pending) {
-		sossi.vsync_dma_pending--;
-		omap_enable_lcd_dma();
-	}
-	spin_unlock_irqrestore(&sossi.lock, flags);
-	return IRQ_HANDLED;
-}
-
-static int sossi_init(struct omapfb_device *fbdev)
-{
-	u32 l, k;
-	struct clk *fck;
-	struct clk *dpll1out_ck;
-	int r;
-
-	sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K);
-	if (!sossi.base) {
-		dev_err(fbdev->dev, "can't ioremap SoSSI\n");
-		return -ENOMEM;
-	}
-
-	sossi.fbdev = fbdev;
-	spin_lock_init(&sossi.lock);
-
-	dpll1out_ck = clk_get(fbdev->dev, "ck_dpll1out");
-	if (IS_ERR(dpll1out_ck)) {
-		dev_err(fbdev->dev, "can't get DPLL1OUT clock\n");
-		return PTR_ERR(dpll1out_ck);
-	}
-	/*
-	 * We need the parent clock rate, which we might divide further
-	 * depending on the timing requirements of the controller. See
-	 * _set_timings.
-	 */
-	sossi.fck_hz = clk_get_rate(dpll1out_ck);
-	clk_put(dpll1out_ck);
-
-	fck = clk_get(fbdev->dev, "ck_sossi");
-	if (IS_ERR(fck)) {
-		dev_err(fbdev->dev, "can't get SoSSI functional clock\n");
-		return PTR_ERR(fck);
-	}
-	sossi.fck = fck;
-
-	/* Reset and enable the SoSSI module */
-	l = omap_readl(MOD_CONF_CTRL_1);
-	l |= CONF_SOSSI_RESET_R;
-	omap_writel(l, MOD_CONF_CTRL_1);
-	l &= ~CONF_SOSSI_RESET_R;
-	omap_writel(l, MOD_CONF_CTRL_1);
-
-	clk_enable(sossi.fck);
-	l = omap_readl(ARM_IDLECT2);
-	l &= ~(1 << 8);			/* DMACK_REQ */
-	omap_writel(l, ARM_IDLECT2);
-
-	l = sossi_read_reg(SOSSI_INIT2_REG);
-	/* Enable and reset the SoSSI block */
-	l |= (1 << 0) | (1 << 1);
-	sossi_write_reg(SOSSI_INIT2_REG, l);
-	/* Take SoSSI out of reset */
-	l &= ~(1 << 1);
-	sossi_write_reg(SOSSI_INIT2_REG, l);
-
-	sossi_write_reg(SOSSI_ID_REG, 0);
-	l = sossi_read_reg(SOSSI_ID_REG);
-	k = sossi_read_reg(SOSSI_ID_REG);
-
-	if (l != 0x55555555 || k != 0xaaaaaaaa) {
-		dev_err(fbdev->dev,
-			"invalid SoSSI sync pattern: %08x, %08x\n", l, k);
-		r = -ENODEV;
-		goto err;
-	}
-
-	if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) {
-		dev_err(fbdev->dev, "can't get LCDC IRQ\n");
-		r = -ENODEV;
-		goto err;
-	}
-
-	l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
-	l = sossi_read_reg(SOSSI_ID_REG);
-	dev_info(fbdev->dev, "SoSSI version %d.%d initialized\n",
-		l >> 16, l & 0xffff);
-
-	l = sossi_read_reg(SOSSI_INIT1_REG);
-	l |= (1 << 19); /* DMA_MODE */
-	l &= ~(1 << 31); /* REORDERING */
-	sossi_write_reg(SOSSI_INIT1_REG, l);
-
-	if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
-			     IRQ_TYPE_EDGE_FALLING,
-	     "sossi_match", sossi.fbdev->dev)) < 0) {
-		dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
-		goto err;
-	}
-
-	clk_disable(sossi.fck);
-	return 0;
-
-err:
-	clk_disable(sossi.fck);
-	clk_put(sossi.fck);
-	return r;
-}
-
-static void sossi_cleanup(void)
-{
-	omap_lcdc_free_dma_callback();
-	clk_put(sossi.fck);
-	iounmap(sossi.base);
-}
-
-struct lcd_ctrl_extif omap1_ext_if = {
-	.init			= sossi_init,
-	.cleanup		= sossi_cleanup,
-	.get_clk_info		= sossi_get_clk_info,
-	.convert_timings	= sossi_convert_timings,
-	.set_timings		= sossi_set_timings,
-	.set_bits_per_cycle	= sossi_set_bits_per_cycle,
-	.setup_tearsync		= sossi_setup_tearsync,
-	.enable_tearsync	= sossi_enable_tearsync,
-	.write_command		= sossi_write_command,
-	.read_data		= sossi_read_data,
-	.write_data		= sossi_write_data,
-	.transfer_area		= sossi_transfer_area,
-
-	.max_transmit_size	= SOSSI_MAX_XMIT_BYTES,
-};
-
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
deleted file mode 100644
index 63b23f87081d..000000000000
--- a/drivers/video/omap2/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config OMAP2_VRFB
-	bool
-
-if ARCH_OMAP2PLUS
-
-source "drivers/video/omap2/dss/Kconfig"
-source "drivers/video/omap2/omapfb/Kconfig"
-source "drivers/video/omap2/displays-new/Kconfig"
-
-endif
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
deleted file mode 100644
index bf8127df8c71..000000000000
--- a/drivers/video/omap2/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
-
-obj-$(CONFIG_OMAP2_DSS) += dss/
-obj-y += displays-new/
-obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/omap2/displays-new/Kconfig b/drivers/video/omap2/displays-new/Kconfig
deleted file mode 100644
index e6cfc38160d3..000000000000
--- a/drivers/video/omap2/displays-new/Kconfig
+++ /dev/null
@@ -1,80 +0,0 @@
-menu "OMAP Display Device Drivers (new device model)"
-        depends on OMAP2_DSS
-
-config DISPLAY_ENCODER_TFP410
-        tristate "TFP410 DPI to DVI Encoder"
-	help
-	  Driver for TFP410 DPI to DVI encoder.
-
-config DISPLAY_ENCODER_TPD12S015
-        tristate "TPD12S015 HDMI ESD protection and level shifter"
-	help
-	  Driver for TPD12S015, which offers HDMI ESD protection and level
-	  shifting.
-
-config DISPLAY_CONNECTOR_DVI
-        tristate "DVI Connector"
-	depends on I2C
-	help
-	  Driver for a generic DVI connector.
-
-config DISPLAY_CONNECTOR_HDMI
-        tristate "HDMI Connector"
-	help
-	  Driver for a generic HDMI connector.
-
-config DISPLAY_CONNECTOR_ANALOG_TV
-        tristate "Analog TV Connector"
-	help
-	  Driver for a generic analog TV connector.
-
-config DISPLAY_PANEL_DPI
-	tristate "Generic DPI panel"
-	help
-	  Driver for generic DPI panels.
-
-config DISPLAY_PANEL_DSI_CM
-	tristate "Generic DSI Command Mode Panel"
-	depends on BACKLIGHT_CLASS_DEVICE
-	help
-	  Driver for generic DSI command mode panels.
-
-config DISPLAY_PANEL_SONY_ACX565AKM
-	tristate "ACX565AKM Panel"
-	depends on SPI && BACKLIGHT_CLASS_DEVICE
-	help
-	  This is the LCD panel used on Nokia N900
-
-config DISPLAY_PANEL_LGPHILIPS_LB035Q02
-	tristate "LG.Philips LB035Q02 LCD Panel"
-	depends on SPI
-	help
-	  LCD Panel used on the Gumstix Overo Palo35
-
-config DISPLAY_PANEL_SHARP_LS037V7DW01
-        tristate "Sharp LS037V7DW01 LCD Panel"
-        depends on BACKLIGHT_CLASS_DEVICE
-        help
-          LCD Panel used in TI's SDP3430 and EVM boards
-
-config DISPLAY_PANEL_TPO_TD028TTEC1
-        tristate "TPO TD028TTEC1 LCD Panel"
-        depends on SPI
-        help
-          LCD panel used in Openmoko.
-
-config DISPLAY_PANEL_TPO_TD043MTEA1
-        tristate "TPO TD043MTEA1 LCD Panel"
-        depends on SPI
-        help
-          LCD Panel used in OMAP3 Pandora
-
-config DISPLAY_PANEL_NEC_NL8048HL11
-	tristate "NEC NL8048HL11 Panel"
-	depends on SPI
-	depends on BACKLIGHT_CLASS_DEVICE
-	help
-		This NEC NL8048HL11 panel is TFT LCD used in the
-		Zoom2/3/3630 sdp boards.
-
-endmenu
diff --git a/drivers/video/omap2/displays-new/Makefile b/drivers/video/omap2/displays-new/Makefile
deleted file mode 100644
index 0323a8a1c682..000000000000
--- a/drivers/video/omap2/displays-new/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o
-obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o
-obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o
-obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o
-obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
-obj-$(CONFIG_DISPLAY_PANEL_DPI) += panel-dpi.o
-obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o
-obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
-obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
-obj-$(CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
-obj-$(CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
-obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
-obj-$(CONFIG_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
diff --git a/drivers/video/omap2/displays-new/connector-analog-tv.c b/drivers/video/omap2/displays-new/connector-analog-tv.c
deleted file mode 100644
index 5ee3b5505f7f..000000000000
--- a/drivers/video/omap2/displays-new/connector-analog-tv.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Analog TV Connector driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	struct device *dev;
-
-	struct omap_video_timings timings;
-
-	enum omap_dss_venc_type connector_type;
-	bool invert_polarity;
-};
-
-static const struct omap_video_timings tvc_pal_timings = {
-	.x_res		= 720,
-	.y_res		= 574,
-	.pixelclock	= 13500000,
-	.hsw		= 64,
-	.hfp		= 12,
-	.hbp		= 68,
-	.vsw		= 5,
-	.vfp		= 5,
-	.vbp		= 41,
-
-	.interlace	= true,
-};
-
-static const struct of_device_id tvc_of_match[];
-
-struct tvc_of_data {
-	enum omap_dss_venc_type connector_type;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int tvc_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(ddata->dev, "connect\n");
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.atv->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void tvc_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(ddata->dev, "disconnect\n");
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.atv->disconnect(in, dssdev);
-}
-
-static int tvc_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(ddata->dev, "enable\n");
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.atv->set_timings(in, &ddata->timings);
-
-	if (!ddata->dev->of_node) {
-		in->ops.atv->set_type(in, ddata->connector_type);
-
-		in->ops.atv->invert_vid_out_polarity(in,
-			ddata->invert_polarity);
-	}
-
-	r = in->ops.atv->enable(in);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return r;
-}
-
-static void tvc_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(ddata->dev, "disable\n");
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	in->ops.atv->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void tvc_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.atv->set_timings(in, timings);
-}
-
-static void tvc_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->timings;
-}
-
-static int tvc_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.atv->check_timings(in, timings);
-}
-
-static u32 tvc_get_wss(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.atv->get_wss(in);
-}
-
-static int tvc_set_wss(struct omap_dss_device *dssdev, u32 wss)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.atv->set_wss(in, wss);
-}
-
-static struct omap_dss_driver tvc_driver = {
-	.connect		= tvc_connect,
-	.disconnect		= tvc_disconnect,
-
-	.enable			= tvc_enable,
-	.disable		= tvc_disable,
-
-	.set_timings		= tvc_set_timings,
-	.get_timings		= tvc_get_timings,
-	.check_timings		= tvc_check_timings,
-
-	.get_resolution		= omapdss_default_get_resolution,
-
-	.get_wss		= tvc_get_wss,
-	.set_wss		= tvc_set_wss,
-};
-
-static int tvc_probe_pdata(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct connector_atv_platform_data *pdata;
-	struct omap_dss_device *in, *dssdev;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&pdev->dev, "Failed to find video source\n");
-		return -EPROBE_DEFER;
-	}
-
-	ddata->in = in;
-
-	ddata->connector_type = pdata->connector_type;
-	ddata->invert_polarity = ddata->invert_polarity;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int tvc_probe_of(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct device_node *node = pdev->dev.of_node;
-	struct omap_dss_device *in;
-
-	in = omapdss_of_find_source_for_first_ep(node);
-	if (IS_ERR(in)) {
-		dev_err(&pdev->dev, "failed to find video source\n");
-		return PTR_ERR(in);
-	}
-
-	ddata->in = in;
-
-	return 0;
-}
-
-static int tvc_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-	ddata->dev = &pdev->dev;
-
-	if (dev_get_platdata(&pdev->dev)) {
-		r = tvc_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else if (pdev->dev.of_node) {
-		r = tvc_probe_of(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	ddata->timings = tvc_pal_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->driver = &tvc_driver;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = tvc_pal_timings;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&pdev->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-err_reg:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int __exit tvc_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_display(&ddata->dssdev);
-
-	tvc_disable(dssdev);
-	tvc_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static const struct of_device_id tvc_of_match[] = {
-	{ .compatible = "omapdss,svideo-connector", },
-	{ .compatible = "omapdss,composite-video-connector", },
-	{},
-};
-
-static struct platform_driver tvc_connector_driver = {
-	.probe	= tvc_probe,
-	.remove	= __exit_p(tvc_remove),
-	.driver	= {
-		.name	= "connector-analog-tv",
-		.owner	= THIS_MODULE,
-		.of_match_table = tvc_of_match,
-	},
-};
-
-module_platform_driver(tvc_connector_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Analog TV Connector driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/connector-dvi.c b/drivers/video/omap2/displays-new/connector-dvi.c
deleted file mode 100644
index 74de2bc50c4f..000000000000
--- a/drivers/video/omap2/displays-new/connector-dvi.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Generic DVI Connector driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <drm/drm_edid.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-static const struct omap_video_timings dvic_default_timings = {
-	.x_res		= 640,
-	.y_res		= 480,
-
-	.pixelclock	= 23500000,
-
-	.hfp		= 48,
-	.hsw		= 32,
-	.hbp		= 80,
-
-	.vfp		= 3,
-	.vsw		= 4,
-	.vbp		= 7,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
-};
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	struct omap_video_timings timings;
-
-	struct i2c_adapter *i2c_adapter;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int dvic_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dvi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void dvic_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dvi->disconnect(in, dssdev);
-}
-
-static int dvic_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dvi->set_timings(in, &ddata->timings);
-
-	r = in->ops.dvi->enable(in);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void dvic_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	in->ops.dvi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void dvic_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dvi->set_timings(in, timings);
-}
-
-static void dvic_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->timings;
-}
-
-static int dvic_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dvi->check_timings(in, timings);
-}
-
-static int dvic_ddc_read(struct i2c_adapter *adapter,
-		unsigned char *buf, u16 count, u8 offset)
-{
-	int r, retries;
-
-	for (retries = 3; retries > 0; retries--) {
-		struct i2c_msg msgs[] = {
-			{
-				.addr   = DDC_ADDR,
-				.flags  = 0,
-				.len    = 1,
-				.buf    = &offset,
-			}, {
-				.addr   = DDC_ADDR,
-				.flags  = I2C_M_RD,
-				.len    = count,
-				.buf    = buf,
-			}
-		};
-
-		r = i2c_transfer(adapter, msgs, 2);
-		if (r == 2)
-			return 0;
-
-		if (r != -EAGAIN)
-			break;
-	}
-
-	return r < 0 ? r : -EIO;
-}
-
-static int dvic_read_edid(struct omap_dss_device *dssdev,
-		u8 *edid, int len)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	int r, l, bytes_read;
-
-	if (!ddata->i2c_adapter)
-		return -ENODEV;
-
-	l = min(EDID_LENGTH, len);
-	r = dvic_ddc_read(ddata->i2c_adapter, edid, l, 0);
-	if (r)
-		return r;
-
-	bytes_read = l;
-
-	/* if there are extensions, read second block */
-	if (len > EDID_LENGTH && edid[0x7e] > 0) {
-		l = min(EDID_LENGTH, len - EDID_LENGTH);
-
-		r = dvic_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
-				l, EDID_LENGTH);
-		if (r)
-			return r;
-
-		bytes_read += l;
-	}
-
-	return bytes_read;
-}
-
-static bool dvic_detect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	unsigned char out;
-	int r;
-
-	if (!ddata->i2c_adapter)
-		return true;
-
-	r = dvic_ddc_read(ddata->i2c_adapter, &out, 1, 0);
-
-	return r == 0;
-}
-
-static struct omap_dss_driver dvic_driver = {
-	.connect	= dvic_connect,
-	.disconnect	= dvic_disconnect,
-
-	.enable		= dvic_enable,
-	.disable	= dvic_disable,
-
-	.set_timings	= dvic_set_timings,
-	.get_timings	= dvic_get_timings,
-	.check_timings	= dvic_check_timings,
-
-	.get_resolution	= omapdss_default_get_resolution,
-
-	.read_edid	= dvic_read_edid,
-	.detect		= dvic_detect,
-};
-
-static int dvic_probe_pdata(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct connector_dvi_platform_data *pdata;
-	struct omap_dss_device *in, *dssdev;
-	int i2c_bus_num;
-
-	pdata = dev_get_platdata(&pdev->dev);
-	i2c_bus_num = pdata->i2c_bus_num;
-
-	if (i2c_bus_num != -1) {
-		struct i2c_adapter *adapter;
-
-		adapter = i2c_get_adapter(i2c_bus_num);
-		if (!adapter) {
-			dev_err(&pdev->dev,
-					"Failed to get I2C adapter, bus %d\n",
-					i2c_bus_num);
-			return -EPROBE_DEFER;
-		}
-
-		ddata->i2c_adapter = adapter;
-	}
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		if (ddata->i2c_adapter)
-			i2c_put_adapter(ddata->i2c_adapter);
-
-		dev_err(&pdev->dev, "Failed to find video source\n");
-		return -EPROBE_DEFER;
-	}
-
-	ddata->in = in;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int dvic_probe_of(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct device_node *node = pdev->dev.of_node;
-	struct omap_dss_device *in;
-	struct device_node *adapter_node;
-	struct i2c_adapter *adapter;
-
-	in = omapdss_of_find_source_for_first_ep(node);
-	if (IS_ERR(in)) {
-		dev_err(&pdev->dev, "failed to find video source\n");
-		return PTR_ERR(in);
-	}
-
-	ddata->in = in;
-
-	adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0);
-	if (adapter_node) {
-		adapter = of_find_i2c_adapter_by_node(adapter_node);
-		if (adapter == NULL) {
-			dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n");
-			omap_dss_put_device(ddata->in);
-			return -EPROBE_DEFER;
-		}
-
-		ddata->i2c_adapter = adapter;
-	}
-
-	return 0;
-}
-
-static int dvic_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-
-	if (dev_get_platdata(&pdev->dev)) {
-		r = dvic_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else if (pdev->dev.of_node) {
-		r = dvic_probe_of(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	ddata->timings = dvic_default_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->driver = &dvic_driver;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_DVI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = dvic_default_timings;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&pdev->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-	omap_dss_put_device(ddata->in);
-
-	if (ddata->i2c_adapter)
-		i2c_put_adapter(ddata->i2c_adapter);
-
-	return r;
-}
-
-static int __exit dvic_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_display(&ddata->dssdev);
-
-	dvic_disable(dssdev);
-	dvic_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	if (ddata->i2c_adapter)
-		i2c_put_adapter(ddata->i2c_adapter);
-
-	return 0;
-}
-
-static const struct of_device_id dvic_of_match[] = {
-	{ .compatible = "omapdss,dvi-connector", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, dvic_of_match);
-
-static struct platform_driver dvi_connector_driver = {
-	.probe	= dvic_probe,
-	.remove	= __exit_p(dvic_remove),
-	.driver	= {
-		.name	= "connector-dvi",
-		.owner	= THIS_MODULE,
-		.of_match_table = dvic_of_match,
-	},
-};
-
-module_platform_driver(dvi_connector_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Generic DVI Connector driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/connector-hdmi.c b/drivers/video/omap2/displays-new/connector-hdmi.c
deleted file mode 100644
index 29ed21b9dce5..000000000000
--- a/drivers/video/omap2/displays-new/connector-hdmi.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * HDMI Connector driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-
-#include <drm/drm_edid.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-static const struct omap_video_timings hdmic_default_timings = {
-	.x_res		= 640,
-	.y_res		= 480,
-	.pixelclock	= 25175000,
-	.hsw		= 96,
-	.hfp		= 16,
-	.hbp		= 48,
-	.vsw		= 2,
-	.vfp		= 11,
-	.vbp		= 31,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-
-	.interlace	= false,
-};
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	struct device *dev;
-
-	struct omap_video_timings timings;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int hdmic_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(ddata->dev, "connect\n");
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.hdmi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void hdmic_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(ddata->dev, "disconnect\n");
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.hdmi->disconnect(in, dssdev);
-}
-
-static int hdmic_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(ddata->dev, "enable\n");
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.hdmi->set_timings(in, &ddata->timings);
-
-	r = in->ops.hdmi->enable(in);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return r;
-}
-
-static void hdmic_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(ddata->dev, "disable\n");
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	in->ops.hdmi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void hdmic_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.hdmi->set_timings(in, timings);
-}
-
-static void hdmic_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->timings;
-}
-
-static int hdmic_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.hdmi->check_timings(in, timings);
-}
-
-static int hdmic_read_edid(struct omap_dss_device *dssdev,
-		u8 *edid, int len)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.hdmi->read_edid(in, edid, len);
-}
-
-static bool hdmic_detect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.hdmi->detect(in);
-}
-
-static int hdmic_audio_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	/* enable audio only if the display is active */
-	if (!omapdss_device_is_enabled(dssdev))
-		return -EPERM;
-
-	r = in->ops.hdmi->audio_enable(in);
-	if (r)
-		return r;
-
-	dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
-
-	return 0;
-}
-
-static void hdmic_audio_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	in->ops.hdmi->audio_disable(in);
-
-	dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
-}
-
-static int hdmic_audio_start(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	/*
-	 * No need to check the panel state. It was checked when trasitioning
-	 * to AUDIO_ENABLED.
-	 */
-	if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED)
-		return -EPERM;
-
-	r = in->ops.hdmi->audio_start(in);
-	if (r)
-		return r;
-
-	dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
-
-	return 0;
-}
-
-static void hdmic_audio_stop(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	in->ops.hdmi->audio_stop(in);
-
-	dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
-}
-
-static bool hdmic_audio_supported(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return false;
-
-	return in->ops.hdmi->audio_supported(in);
-}
-
-static int hdmic_audio_config(struct omap_dss_device *dssdev,
-		struct omap_dss_audio *audio)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	/* config audio only if the display is active */
-	if (!omapdss_device_is_enabled(dssdev))
-		return -EPERM;
-
-	r = in->ops.hdmi->audio_config(in, audio);
-	if (r)
-		return r;
-
-	dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
-
-	return 0;
-}
-
-static struct omap_dss_driver hdmic_driver = {
-	.connect		= hdmic_connect,
-	.disconnect		= hdmic_disconnect,
-
-	.enable			= hdmic_enable,
-	.disable		= hdmic_disable,
-
-	.set_timings		= hdmic_set_timings,
-	.get_timings		= hdmic_get_timings,
-	.check_timings		= hdmic_check_timings,
-
-	.get_resolution		= omapdss_default_get_resolution,
-
-	.read_edid		= hdmic_read_edid,
-	.detect			= hdmic_detect,
-
-	.audio_enable		= hdmic_audio_enable,
-	.audio_disable		= hdmic_audio_disable,
-	.audio_start		= hdmic_audio_start,
-	.audio_stop		= hdmic_audio_stop,
-	.audio_supported	= hdmic_audio_supported,
-	.audio_config		= hdmic_audio_config,
-};
-
-static int hdmic_probe_pdata(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct connector_hdmi_platform_data *pdata;
-	struct omap_dss_device *in, *dssdev;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&pdev->dev, "Failed to find video source\n");
-		return -EPROBE_DEFER;
-	}
-
-	ddata->in = in;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int hdmic_probe_of(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct device_node *node = pdev->dev.of_node;
-	struct omap_dss_device *in;
-
-	in = omapdss_of_find_source_for_first_ep(node);
-	if (IS_ERR(in)) {
-		dev_err(&pdev->dev, "failed to find video source\n");
-		return PTR_ERR(in);
-	}
-
-	ddata->in = in;
-
-	return 0;
-}
-
-static int hdmic_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-	ddata->dev = &pdev->dev;
-
-	if (dev_get_platdata(&pdev->dev)) {
-		r = hdmic_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else if (pdev->dev.of_node) {
-		r = hdmic_probe_of(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	ddata->timings = hdmic_default_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->driver = &hdmic_driver;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = hdmic_default_timings;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&pdev->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-err_reg:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int __exit hdmic_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_display(&ddata->dssdev);
-
-	hdmic_disable(dssdev);
-	hdmic_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static const struct of_device_id hdmic_of_match[] = {
-	{ .compatible = "omapdss,hdmi-connector", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, hdmic_of_match);
-
-static struct platform_driver hdmi_connector_driver = {
-	.probe	= hdmic_probe,
-	.remove	= __exit_p(hdmic_remove),
-	.driver	= {
-		.name	= "connector-hdmi",
-		.owner	= THIS_MODULE,
-		.of_match_table = hdmic_of_match,
-	},
-};
-
-module_platform_driver(hdmi_connector_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("HDMI Connector driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/omap2/displays-new/encoder-tfp410.c
deleted file mode 100644
index b4e9a42a79e6..000000000000
--- a/drivers/video/omap2/displays-new/encoder-tfp410.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * TFP410 DPI-to-DVI encoder driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of_gpio.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	int pd_gpio;
-	int data_lines;
-
-	struct omap_video_timings timings;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int tfp410_connect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return -EBUSY;
-
-	r = in->ops.dpi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	dst->src = dssdev;
-	dssdev->dst = dst;
-
-	return 0;
-}
-
-static void tfp410_disconnect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	WARN_ON(!omapdss_device_is_connected(dssdev));
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	WARN_ON(dst != dssdev->dst);
-	if (dst != dssdev->dst)
-		return;
-
-	dst->src = NULL;
-	dssdev->dst = NULL;
-
-	in->ops.dpi->disconnect(in, &ddata->dssdev);
-}
-
-static int tfp410_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dpi->set_timings(in, &ddata->timings);
-	if (ddata->data_lines)
-		in->ops.dpi->set_data_lines(in, ddata->data_lines);
-
-	r = in->ops.dpi->enable(in);
-	if (r)
-		return r;
-
-	if (gpio_is_valid(ddata->pd_gpio))
-		gpio_set_value_cansleep(ddata->pd_gpio, 1);
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void tfp410_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	if (gpio_is_valid(ddata->pd_gpio))
-		gpio_set_value_cansleep(ddata->pd_gpio, 0);
-
-	in->ops.dpi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void tfp410_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dpi->set_timings(in, timings);
-}
-
-static void tfp410_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->timings;
-}
-
-static int tfp410_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dpi->check_timings(in, timings);
-}
-
-static const struct omapdss_dvi_ops tfp410_dvi_ops = {
-	.connect	= tfp410_connect,
-	.disconnect	= tfp410_disconnect,
-
-	.enable		= tfp410_enable,
-	.disable	= tfp410_disable,
-
-	.check_timings	= tfp410_check_timings,
-	.set_timings	= tfp410_set_timings,
-	.get_timings	= tfp410_get_timings,
-};
-
-static int tfp410_probe_pdata(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct encoder_tfp410_platform_data *pdata;
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	ddata->pd_gpio = pdata->power_down_gpio;
-
-	ddata->data_lines = pdata->data_lines;
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&pdev->dev, "Failed to find video source\n");
-		return -ENODEV;
-	}
-
-	ddata->in = in;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int tfp410_probe_of(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct device_node *node = pdev->dev.of_node;
-	struct omap_dss_device *in;
-	int gpio;
-
-	gpio = of_get_named_gpio(node, "powerdown-gpios", 0);
-
-	if (gpio_is_valid(gpio) || gpio == -ENOENT) {
-		ddata->pd_gpio = gpio;
-	} else {
-		dev_err(&pdev->dev, "failed to parse PD gpio\n");
-		return gpio;
-	}
-
-	in = omapdss_of_find_source_for_first_ep(node);
-	if (IS_ERR(in)) {
-		dev_err(&pdev->dev, "failed to find video source\n");
-		return PTR_ERR(in);
-	}
-
-	ddata->in = in;
-
-	return 0;
-}
-
-static int tfp410_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-
-	if (dev_get_platdata(&pdev->dev)) {
-		r = tfp410_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else if (pdev->dev.of_node) {
-		r = tfp410_probe_of(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	if (gpio_is_valid(ddata->pd_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->pd_gpio,
-				GPIOF_OUT_INIT_LOW, "tfp410 PD");
-		if (r) {
-			dev_err(&pdev->dev, "Failed to request PD GPIO %d\n",
-					ddata->pd_gpio);
-			goto err_gpio;
-		}
-	}
-
-	dssdev = &ddata->dssdev;
-	dssdev->ops.dvi = &tfp410_dvi_ops;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
-	dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->phy.dpi.data_lines = ddata->data_lines;
-
-	r = omapdss_register_output(dssdev);
-	if (r) {
-		dev_err(&pdev->dev, "Failed to register output\n");
-		goto err_reg;
-	}
-
-	return 0;
-err_reg:
-err_gpio:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int __exit tfp410_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_output(&ddata->dssdev);
-
-	WARN_ON(omapdss_device_is_enabled(dssdev));
-	if (omapdss_device_is_enabled(dssdev))
-		tfp410_disable(dssdev);
-
-	WARN_ON(omapdss_device_is_connected(dssdev));
-	if (omapdss_device_is_connected(dssdev))
-		tfp410_disconnect(dssdev, dssdev->dst);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static const struct of_device_id tfp410_of_match[] = {
-	{ .compatible = "omapdss,ti,tfp410", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, tfp410_of_match);
-
-static struct platform_driver tfp410_driver = {
-	.probe	= tfp410_probe,
-	.remove	= __exit_p(tfp410_remove),
-	.driver	= {
-		.name	= "tfp410",
-		.owner	= THIS_MODULE,
-		.of_match_table = tfp410_of_match,
-	},
-};
-
-module_platform_driver(tfp410_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/omap2/displays-new/encoder-tpd12s015.c
deleted file mode 100644
index 7e33686171e3..000000000000
--- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * TPD12S015 HDMI ESD protection & level shifter chip driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/of_gpio.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	int ct_cp_hpd_gpio;
-	int ls_oe_gpio;
-	int hpd_gpio;
-
-	struct omap_video_timings timings;
-
-	struct completion hpd_completion;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static irqreturn_t tpd_hpd_irq_handler(int irq, void *data)
-{
-	struct panel_drv_data *ddata = data;
-	bool hpd;
-
-	hpd = gpio_get_value_cansleep(ddata->hpd_gpio);
-
-	dev_dbg(ddata->dssdev.dev, "hpd %d\n", hpd);
-
-	if (gpio_is_valid(ddata->ls_oe_gpio)) {
-		if (hpd)
-			gpio_set_value_cansleep(ddata->ls_oe_gpio, 1);
-		else
-			gpio_set_value_cansleep(ddata->ls_oe_gpio, 0);
-	}
-
-	complete_all(&ddata->hpd_completion);
-
-	return IRQ_HANDLED;
-}
-
-static int tpd_connect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	r = in->ops.hdmi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	dst->src = dssdev;
-	dssdev->dst = dst;
-
-	reinit_completion(&ddata->hpd_completion);
-
-	gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1);
-	/* DC-DC converter needs at max 300us to get to 90% of 5V */
-	udelay(300);
-
-	/*
-	 * If there's a cable connected, wait for the hpd irq to trigger,
-	 * which turns on the level shifters.
-	 */
-	if (gpio_get_value_cansleep(ddata->hpd_gpio)) {
-		unsigned long to;
-		to = wait_for_completion_timeout(&ddata->hpd_completion,
-				msecs_to_jiffies(250));
-		WARN_ON_ONCE(to == 0);
-	}
-
-	return 0;
-}
-
-static void tpd_disconnect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	WARN_ON(dst != dssdev->dst);
-
-	if (dst != dssdev->dst)
-		return;
-
-	gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0);
-
-	dst->src = NULL;
-	dssdev->dst = NULL;
-
-	in->ops.hdmi->disconnect(in, &ddata->dssdev);
-}
-
-static int tpd_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
-		return 0;
-
-	in->ops.hdmi->set_timings(in, &ddata->timings);
-
-	r = in->ops.hdmi->enable(in);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return r;
-}
-
-static void tpd_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-		return;
-
-	in->ops.hdmi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void tpd_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.hdmi->set_timings(in, timings);
-}
-
-static void tpd_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->timings;
-}
-
-static int tpd_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	r = in->ops.hdmi->check_timings(in, timings);
-
-	return r;
-}
-
-static int tpd_read_edid(struct omap_dss_device *dssdev,
-		u8 *edid, int len)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!gpio_get_value_cansleep(ddata->hpd_gpio))
-		return -ENODEV;
-
-	return in->ops.hdmi->read_edid(in, edid, len);
-}
-
-static bool tpd_detect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	return gpio_get_value_cansleep(ddata->hpd_gpio);
-}
-
-static int tpd_audio_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.hdmi->audio_enable(in);
-}
-
-static void tpd_audio_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	in->ops.hdmi->audio_disable(in);
-}
-
-static int tpd_audio_start(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.hdmi->audio_start(in);
-}
-
-static void tpd_audio_stop(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	in->ops.hdmi->audio_stop(in);
-}
-
-static bool tpd_audio_supported(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.hdmi->audio_supported(in);
-}
-
-static int tpd_audio_config(struct omap_dss_device *dssdev,
-		struct omap_dss_audio *audio)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.hdmi->audio_config(in, audio);
-}
-
-static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
-	.connect		= tpd_connect,
-	.disconnect		= tpd_disconnect,
-
-	.enable			= tpd_enable,
-	.disable		= tpd_disable,
-
-	.check_timings		= tpd_check_timings,
-	.set_timings		= tpd_set_timings,
-	.get_timings		= tpd_get_timings,
-
-	.read_edid		= tpd_read_edid,
-	.detect			= tpd_detect,
-
-	.audio_enable		= tpd_audio_enable,
-	.audio_disable		= tpd_audio_disable,
-	.audio_start		= tpd_audio_start,
-	.audio_stop		= tpd_audio_stop,
-	.audio_supported	= tpd_audio_supported,
-	.audio_config		= tpd_audio_config,
-};
-
-static int tpd_probe_pdata(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct encoder_tpd12s015_platform_data *pdata;
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	ddata->ct_cp_hpd_gpio = pdata->ct_cp_hpd_gpio;
-	ddata->ls_oe_gpio = pdata->ls_oe_gpio;
-	ddata->hpd_gpio = pdata->hpd_gpio;
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&pdev->dev, "Failed to find video source\n");
-		return -ENODEV;
-	}
-
-	ddata->in = in;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int tpd_probe_of(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct device_node *node = pdev->dev.of_node;
-	struct omap_dss_device *in;
-	int gpio;
-
-	/* CT CP HPD GPIO */
-	gpio = of_get_gpio(node, 0);
-	if (!gpio_is_valid(gpio)) {
-		dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n");
-		return gpio;
-	}
-	ddata->ct_cp_hpd_gpio = gpio;
-
-	/* LS OE GPIO */
-	gpio = of_get_gpio(node, 1);
-	if (gpio_is_valid(gpio) || gpio == -ENOENT) {
-		ddata->ls_oe_gpio = gpio;
-	} else {
-		dev_err(&pdev->dev, "failed to parse LS OE gpio\n");
-		return gpio;
-	}
-
-	/* HPD GPIO */
-	gpio = of_get_gpio(node, 2);
-	if (!gpio_is_valid(gpio)) {
-		dev_err(&pdev->dev, "failed to parse HPD gpio\n");
-		return gpio;
-	}
-	ddata->hpd_gpio = gpio;
-
-	in = omapdss_of_find_source_for_first_ep(node);
-	if (IS_ERR(in)) {
-		dev_err(&pdev->dev, "failed to find video source\n");
-		return PTR_ERR(in);
-	}
-
-	ddata->in = in;
-
-	return 0;
-}
-
-static int tpd_probe(struct platform_device *pdev)
-{
-	struct omap_dss_device *in, *dssdev;
-	struct panel_drv_data *ddata;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-
-	init_completion(&ddata->hpd_completion);
-
-	if (dev_get_platdata(&pdev->dev)) {
-		r = tpd_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else if (pdev->dev.of_node) {
-		r = tpd_probe_of(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	r = devm_gpio_request_one(&pdev->dev, ddata->ct_cp_hpd_gpio,
-			GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd");
-	if (r)
-		goto err_gpio;
-
-	if (gpio_is_valid(ddata->ls_oe_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->ls_oe_gpio,
-				GPIOF_OUT_INIT_LOW, "hdmi_ls_oe");
-		if (r)
-			goto err_gpio;
-	}
-
-	r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
-			GPIOF_DIR_IN, "hdmi_hpd");
-	if (r)
-		goto err_gpio;
-
-	r = devm_request_threaded_irq(&pdev->dev, gpio_to_irq(ddata->hpd_gpio),
-				 NULL, tpd_hpd_irq_handler,
-				 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
-				 IRQF_ONESHOT, "hpd", ddata);
-	if (r)
-		goto err_irq;
-
-	dssdev = &ddata->dssdev;
-	dssdev->ops.hdmi = &tpd_hdmi_ops;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
-	dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
-	dssdev->owner = THIS_MODULE;
-
-	in = ddata->in;
-
-	r = omapdss_register_output(dssdev);
-	if (r) {
-		dev_err(&pdev->dev, "Failed to register output\n");
-		goto err_reg;
-	}
-
-	return 0;
-err_reg:
-err_irq:
-err_gpio:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int __exit tpd_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_output(&ddata->dssdev);
-
-	WARN_ON(omapdss_device_is_enabled(dssdev));
-	if (omapdss_device_is_enabled(dssdev))
-		tpd_disable(dssdev);
-
-	WARN_ON(omapdss_device_is_connected(dssdev));
-	if (omapdss_device_is_connected(dssdev))
-		tpd_disconnect(dssdev, dssdev->dst);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static const struct of_device_id tpd_of_match[] = {
-	{ .compatible = "omapdss,ti,tpd12s015", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, tpd_of_match);
-
-static struct platform_driver tpd_driver = {
-	.probe	= tpd_probe,
-	.remove	= __exit_p(tpd_remove),
-	.driver	= {
-		.name	= "tpd12s015",
-		.owner	= THIS_MODULE,
-		.of_match_table = tpd_of_match,
-	},
-};
-
-module_platform_driver(tpd_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("TPD12S015 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-dpi.c b/drivers/video/omap2/displays-new/panel-dpi.c
deleted file mode 100644
index 5f8f7e7c81ef..000000000000
--- a/drivers/video/omap2/displays-new/panel-dpi.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Generic MIPI DPI Panel Driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	int data_lines;
-
-	struct omap_video_timings videomode;
-
-	int backlight_gpio;
-	int enable_gpio;
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static int panel_dpi_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dpi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void panel_dpi_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dpi->disconnect(in, dssdev);
-}
-
-static int panel_dpi_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
-
-	r = in->ops.dpi->enable(in);
-	if (r)
-		return r;
-
-	if (gpio_is_valid(ddata->enable_gpio))
-		gpio_set_value_cansleep(ddata->enable_gpio, 1);
-
-	if (gpio_is_valid(ddata->backlight_gpio))
-		gpio_set_value_cansleep(ddata->backlight_gpio, 1);
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void panel_dpi_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	if (gpio_is_valid(ddata->enable_gpio))
-		gpio_set_value_cansleep(ddata->enable_gpio, 0);
-
-	if (gpio_is_valid(ddata->backlight_gpio))
-		gpio_set_value_cansleep(ddata->backlight_gpio, 0);
-
-	in->ops.dpi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void panel_dpi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dpi->set_timings(in, timings);
-}
-
-static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->videomode;
-}
-
-static int panel_dpi_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dpi->check_timings(in, timings);
-}
-
-static struct omap_dss_driver panel_dpi_ops = {
-	.connect	= panel_dpi_connect,
-	.disconnect	= panel_dpi_disconnect,
-
-	.enable		= panel_dpi_enable,
-	.disable	= panel_dpi_disable,
-
-	.set_timings	= panel_dpi_set_timings,
-	.get_timings	= panel_dpi_get_timings,
-	.check_timings	= panel_dpi_check_timings,
-
-	.get_resolution	= omapdss_default_get_resolution,
-};
-
-static int panel_dpi_probe_pdata(struct platform_device *pdev)
-{
-	const struct panel_dpi_platform_data *pdata;
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev, *in;
-	struct videomode vm;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&pdev->dev, "failed to find video source '%s'\n",
-				pdata->source);
-		return -EPROBE_DEFER;
-	}
-
-	ddata->in = in;
-
-	ddata->data_lines = pdata->data_lines;
-
-	videomode_from_timing(pdata->display_timing, &vm);
-	videomode_to_omap_video_timings(&vm, &ddata->videomode);
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	ddata->enable_gpio = pdata->enable_gpio;
-	ddata->backlight_gpio = pdata->backlight_gpio;
-
-	return 0;
-}
-
-static int panel_dpi_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (ddata == NULL)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-
-	if (dev_get_platdata(&pdev->dev)) {
-		r = panel_dpi_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	if (gpio_is_valid(ddata->enable_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->enable_gpio,
-				GPIOF_OUT_INIT_LOW, "panel enable");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->backlight_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->backlight_gpio,
-				GPIOF_OUT_INIT_LOW, "panel backlight");
-		if (r)
-			goto err_gpio;
-	}
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = &pdev->dev;
-	dssdev->driver = &panel_dpi_ops;
-	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
-	dssdev->phy.dpi.data_lines = ddata->data_lines;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&pdev->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-err_gpio:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int __exit panel_dpi_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_display(dssdev);
-
-	panel_dpi_disable(dssdev);
-	panel_dpi_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static struct platform_driver panel_dpi_driver = {
-	.probe = panel_dpi_probe,
-	.remove = __exit_p(panel_dpi_remove),
-	.driver = {
-		.name = "panel-dpi",
-		.owner = THIS_MODULE,
-	},
-};
-
-module_platform_driver(panel_dpi_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Generic MIPI DPI Panel Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-dsi-cm.c b/drivers/video/omap2/displays-new/panel-dsi-cm.c
deleted file mode 100644
index d6f14e8717e8..000000000000
--- a/drivers/video/omap2/displays-new/panel-dsi-cm.c
+++ /dev/null
@@ -1,1388 +0,0 @@
-/*
- * Generic DSI Command Mode panel driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-/* #define DEBUG */
-
-#include <linux/backlight.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-#include <video/mipi_display.h>
-
-/* DSI Virtual channel. Hardcoded for now. */
-#define TCH 0
-
-#define DCS_READ_NUM_ERRORS	0x05
-#define DCS_BRIGHTNESS		0x51
-#define DCS_CTRL_DISPLAY	0x53
-#define DCS_GET_ID1		0xda
-#define DCS_GET_ID2		0xdb
-#define DCS_GET_ID3		0xdc
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	struct omap_video_timings timings;
-
-	struct platform_device *pdev;
-
-	struct mutex lock;
-
-	struct backlight_device *bldev;
-
-	unsigned long	hw_guard_end;	/* next value of jiffies when we can
-					 * issue the next sleep in/out command
-					 */
-	unsigned long	hw_guard_wait;	/* max guard time in jiffies */
-
-	/* panel HW configuration from DT or platform data */
-	int reset_gpio;
-	int ext_te_gpio;
-
-	bool use_dsi_backlight;
-
-	struct omap_dsi_pin_config pin_config;
-
-	/* runtime variables */
-	bool enabled;
-
-	bool te_enabled;
-
-	atomic_t do_update;
-	int channel;
-
-	struct delayed_work te_timeout_work;
-
-	bool intro_printed;
-
-	struct workqueue_struct *workqueue;
-
-	bool ulps_enabled;
-	unsigned ulps_timeout;
-	struct delayed_work ulps_work;
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static irqreturn_t dsicm_te_isr(int irq, void *data);
-static void dsicm_te_timeout_work_callback(struct work_struct *work);
-static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
-
-static int dsicm_panel_reset(struct panel_drv_data *ddata);
-
-static void dsicm_ulps_work(struct work_struct *work);
-
-static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
-{
-	ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
-	ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
-}
-
-static void hw_guard_wait(struct panel_drv_data *ddata)
-{
-	unsigned long wait = ddata->hw_guard_end - jiffies;
-
-	if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(wait);
-	}
-}
-
-static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
-{
-	struct omap_dss_device *in = ddata->in;
-	int r;
-	u8 buf[1];
-
-	r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd, buf, 1);
-
-	if (r < 0)
-		return r;
-
-	*data = buf[0];
-
-	return 0;
-}
-
-static int dsicm_dcs_write_0(struct panel_drv_data *ddata, u8 dcs_cmd)
-{
-	struct omap_dss_device *in = ddata->in;
-	return in->ops.dsi->dcs_write(in, ddata->channel, &dcs_cmd, 1);
-}
-
-static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
-{
-	struct omap_dss_device *in = ddata->in;
-	u8 buf[2] = { dcs_cmd, param };
-
-	return in->ops.dsi->dcs_write(in, ddata->channel, buf, 2);
-}
-
-static int dsicm_sleep_in(struct panel_drv_data *ddata)
-
-{
-	struct omap_dss_device *in = ddata->in;
-	u8 cmd;
-	int r;
-
-	hw_guard_wait(ddata);
-
-	cmd = MIPI_DCS_ENTER_SLEEP_MODE;
-	r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, &cmd, 1);
-	if (r)
-		return r;
-
-	hw_guard_start(ddata, 120);
-
-	usleep_range(5000, 10000);
-
-	return 0;
-}
-
-static int dsicm_sleep_out(struct panel_drv_data *ddata)
-{
-	int r;
-
-	hw_guard_wait(ddata);
-
-	r = dsicm_dcs_write_0(ddata, MIPI_DCS_EXIT_SLEEP_MODE);
-	if (r)
-		return r;
-
-	hw_guard_start(ddata, 120);
-
-	usleep_range(5000, 10000);
-
-	return 0;
-}
-
-static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
-{
-	int r;
-
-	r = dsicm_dcs_read_1(ddata, DCS_GET_ID1, id1);
-	if (r)
-		return r;
-	r = dsicm_dcs_read_1(ddata, DCS_GET_ID2, id2);
-	if (r)
-		return r;
-	r = dsicm_dcs_read_1(ddata, DCS_GET_ID3, id3);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static int dsicm_set_update_window(struct panel_drv_data *ddata,
-		u16 x, u16 y, u16 w, u16 h)
-{
-	struct omap_dss_device *in = ddata->in;
-	int r;
-	u16 x1 = x;
-	u16 x2 = x + w - 1;
-	u16 y1 = y;
-	u16 y2 = y + h - 1;
-
-	u8 buf[5];
-	buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
-	buf[1] = (x1 >> 8) & 0xff;
-	buf[2] = (x1 >> 0) & 0xff;
-	buf[3] = (x2 >> 8) & 0xff;
-	buf[4] = (x2 >> 0) & 0xff;
-
-	r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
-	if (r)
-		return r;
-
-	buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
-	buf[1] = (y1 >> 8) & 0xff;
-	buf[2] = (y1 >> 0) & 0xff;
-	buf[3] = (y2 >> 8) & 0xff;
-	buf[4] = (y2 >> 0) & 0xff;
-
-	r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
-	if (r)
-		return r;
-
-	in->ops.dsi->bta_sync(in, ddata->channel);
-
-	return r;
-}
-
-static void dsicm_queue_ulps_work(struct panel_drv_data *ddata)
-{
-	if (ddata->ulps_timeout > 0)
-		queue_delayed_work(ddata->workqueue, &ddata->ulps_work,
-				msecs_to_jiffies(ddata->ulps_timeout));
-}
-
-static void dsicm_cancel_ulps_work(struct panel_drv_data *ddata)
-{
-	cancel_delayed_work(&ddata->ulps_work);
-}
-
-static int dsicm_enter_ulps(struct panel_drv_data *ddata)
-{
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (ddata->ulps_enabled)
-		return 0;
-
-	dsicm_cancel_ulps_work(ddata);
-
-	r = _dsicm_enable_te(ddata, false);
-	if (r)
-		goto err;
-
-	if (gpio_is_valid(ddata->ext_te_gpio))
-		disable_irq(gpio_to_irq(ddata->ext_te_gpio));
-
-	in->ops.dsi->disable(in, false, true);
-
-	ddata->ulps_enabled = true;
-
-	return 0;
-
-err:
-	dev_err(&ddata->pdev->dev, "enter ULPS failed");
-	dsicm_panel_reset(ddata);
-
-	ddata->ulps_enabled = false;
-
-	dsicm_queue_ulps_work(ddata);
-
-	return r;
-}
-
-static int dsicm_exit_ulps(struct panel_drv_data *ddata)
-{
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!ddata->ulps_enabled)
-		return 0;
-
-	r = in->ops.dsi->enable(in);
-	if (r) {
-		dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
-		goto err1;
-	}
-
-	in->ops.dsi->enable_hs(in, ddata->channel, true);
-
-	r = _dsicm_enable_te(ddata, true);
-	if (r) {
-		dev_err(&ddata->pdev->dev, "failed to re-enable TE");
-		goto err2;
-	}
-
-	if (gpio_is_valid(ddata->ext_te_gpio))
-		enable_irq(gpio_to_irq(ddata->ext_te_gpio));
-
-	dsicm_queue_ulps_work(ddata);
-
-	ddata->ulps_enabled = false;
-
-	return 0;
-
-err2:
-	dev_err(&ddata->pdev->dev, "failed to exit ULPS");
-
-	r = dsicm_panel_reset(ddata);
-	if (!r) {
-		if (gpio_is_valid(ddata->ext_te_gpio))
-			enable_irq(gpio_to_irq(ddata->ext_te_gpio));
-		ddata->ulps_enabled = false;
-	}
-err1:
-	dsicm_queue_ulps_work(ddata);
-
-	return r;
-}
-
-static int dsicm_wake_up(struct panel_drv_data *ddata)
-{
-	if (ddata->ulps_enabled)
-		return dsicm_exit_ulps(ddata);
-
-	dsicm_cancel_ulps_work(ddata);
-	dsicm_queue_ulps_work(ddata);
-	return 0;
-}
-
-static int dsicm_bl_update_status(struct backlight_device *dev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-	int level;
-
-	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-			dev->props.power == FB_BLANK_UNBLANK)
-		level = dev->props.brightness;
-	else
-		level = 0;
-
-	dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level);
-
-	mutex_lock(&ddata->lock);
-
-	if (ddata->enabled) {
-		in->ops.dsi->bus_lock(in);
-
-		r = dsicm_wake_up(ddata);
-		if (!r)
-			r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level);
-
-		in->ops.dsi->bus_unlock(in);
-	} else {
-		r = 0;
-	}
-
-	mutex_unlock(&ddata->lock);
-
-	return r;
-}
-
-static int dsicm_bl_get_intensity(struct backlight_device *dev)
-{
-	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-			dev->props.power == FB_BLANK_UNBLANK)
-		return dev->props.brightness;
-
-	return 0;
-}
-
-static const struct backlight_ops dsicm_bl_ops = {
-	.get_brightness = dsicm_bl_get_intensity,
-	.update_status  = dsicm_bl_update_status,
-};
-
-static void dsicm_get_resolution(struct omap_dss_device *dssdev,
-		u16 *xres, u16 *yres)
-{
-	*xres = dssdev->panel.timings.x_res;
-	*yres = dssdev->panel.timings.y_res;
-}
-
-static ssize_t dsicm_num_errors_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *in = ddata->in;
-	u8 errors = 0;
-	int r;
-
-	mutex_lock(&ddata->lock);
-
-	if (ddata->enabled) {
-		in->ops.dsi->bus_lock(in);
-
-		r = dsicm_wake_up(ddata);
-		if (!r)
-			r = dsicm_dcs_read_1(ddata, DCS_READ_NUM_ERRORS,
-					&errors);
-
-		in->ops.dsi->bus_unlock(in);
-	} else {
-		r = -ENODEV;
-	}
-
-	mutex_unlock(&ddata->lock);
-
-	if (r)
-		return r;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", errors);
-}
-
-static ssize_t dsicm_hw_revision_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *in = ddata->in;
-	u8 id1, id2, id3;
-	int r;
-
-	mutex_lock(&ddata->lock);
-
-	if (ddata->enabled) {
-		in->ops.dsi->bus_lock(in);
-
-		r = dsicm_wake_up(ddata);
-		if (!r)
-			r = dsicm_get_id(ddata, &id1, &id2, &id3);
-
-		in->ops.dsi->bus_unlock(in);
-	} else {
-		r = -ENODEV;
-	}
-
-	mutex_unlock(&ddata->lock);
-
-	if (r)
-		return r;
-
-	return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
-}
-
-static ssize_t dsicm_store_ulps(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *in = ddata->in;
-	unsigned long t;
-	int r;
-
-	r = kstrtoul(buf, 0, &t);
-	if (r)
-		return r;
-
-	mutex_lock(&ddata->lock);
-
-	if (ddata->enabled) {
-		in->ops.dsi->bus_lock(in);
-
-		if (t)
-			r = dsicm_enter_ulps(ddata);
-		else
-			r = dsicm_wake_up(ddata);
-
-		in->ops.dsi->bus_unlock(in);
-	}
-
-	mutex_unlock(&ddata->lock);
-
-	if (r)
-		return r;
-
-	return count;
-}
-
-static ssize_t dsicm_show_ulps(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	unsigned t;
-
-	mutex_lock(&ddata->lock);
-	t = ddata->ulps_enabled;
-	mutex_unlock(&ddata->lock);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", t);
-}
-
-static ssize_t dsicm_store_ulps_timeout(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *in = ddata->in;
-	unsigned long t;
-	int r;
-
-	r = kstrtoul(buf, 0, &t);
-	if (r)
-		return r;
-
-	mutex_lock(&ddata->lock);
-	ddata->ulps_timeout = t;
-
-	if (ddata->enabled) {
-		/* dsicm_wake_up will restart the timer */
-		in->ops.dsi->bus_lock(in);
-		r = dsicm_wake_up(ddata);
-		in->ops.dsi->bus_unlock(in);
-	}
-
-	mutex_unlock(&ddata->lock);
-
-	if (r)
-		return r;
-
-	return count;
-}
-
-static ssize_t dsicm_show_ulps_timeout(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	unsigned t;
-
-	mutex_lock(&ddata->lock);
-	t = ddata->ulps_timeout;
-	mutex_unlock(&ddata->lock);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", t);
-}
-
-static DEVICE_ATTR(num_dsi_errors, S_IRUGO, dsicm_num_errors_show, NULL);
-static DEVICE_ATTR(hw_revision, S_IRUGO, dsicm_hw_revision_show, NULL);
-static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
-		dsicm_show_ulps, dsicm_store_ulps);
-static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
-		dsicm_show_ulps_timeout, dsicm_store_ulps_timeout);
-
-static struct attribute *dsicm_attrs[] = {
-	&dev_attr_num_dsi_errors.attr,
-	&dev_attr_hw_revision.attr,
-	&dev_attr_ulps.attr,
-	&dev_attr_ulps_timeout.attr,
-	NULL,
-};
-
-static struct attribute_group dsicm_attr_group = {
-	.attrs = dsicm_attrs,
-};
-
-static void dsicm_hw_reset(struct panel_drv_data *ddata)
-{
-	if (!gpio_is_valid(ddata->reset_gpio))
-		return;
-
-	gpio_set_value(ddata->reset_gpio, 1);
-	udelay(10);
-	/* reset the panel */
-	gpio_set_value(ddata->reset_gpio, 0);
-	/* assert reset */
-	udelay(10);
-	gpio_set_value(ddata->reset_gpio, 1);
-	/* wait after releasing reset */
-	usleep_range(5000, 10000);
-}
-
-static int dsicm_power_on(struct panel_drv_data *ddata)
-{
-	struct omap_dss_device *in = ddata->in;
-	u8 id1, id2, id3;
-	int r;
-	struct omap_dss_dsi_config dsi_config = {
-		.mode = OMAP_DSS_DSI_CMD_MODE,
-		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
-		.timings = &ddata->timings,
-		.hs_clk_min = 150000000,
-		.hs_clk_max = 300000000,
-		.lp_clk_min = 7000000,
-		.lp_clk_max = 10000000,
-	};
-
-	if (ddata->pin_config.num_pins > 0) {
-		r = in->ops.dsi->configure_pins(in, &ddata->pin_config);
-		if (r) {
-			dev_err(&ddata->pdev->dev,
-				"failed to configure DSI pins\n");
-			goto err0;
-		}
-	}
-
-	r = in->ops.dsi->set_config(in, &dsi_config);
-	if (r) {
-		dev_err(&ddata->pdev->dev, "failed to configure DSI\n");
-		goto err0;
-	}
-
-	r = in->ops.dsi->enable(in);
-	if (r) {
-		dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
-		goto err0;
-	}
-
-	dsicm_hw_reset(ddata);
-
-	in->ops.dsi->enable_hs(in, ddata->channel, false);
-
-	r = dsicm_sleep_out(ddata);
-	if (r)
-		goto err;
-
-	r = dsicm_get_id(ddata, &id1, &id2, &id3);
-	if (r)
-		goto err;
-
-	r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, 0xff);
-	if (r)
-		goto err;
-
-	r = dsicm_dcs_write_1(ddata, DCS_CTRL_DISPLAY,
-			(1<<2) | (1<<5));	/* BL | BCTRL */
-	if (r)
-		goto err;
-
-	r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_PIXEL_FORMAT,
-		MIPI_DCS_PIXEL_FMT_24BIT);
-	if (r)
-		goto err;
-
-	r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_ON);
-	if (r)
-		goto err;
-
-	r = _dsicm_enable_te(ddata, ddata->te_enabled);
-	if (r)
-		goto err;
-
-	r = in->ops.dsi->enable_video_output(in, ddata->channel);
-	if (r)
-		goto err;
-
-	ddata->enabled = 1;
-
-	if (!ddata->intro_printed) {
-		dev_info(&ddata->pdev->dev, "panel revision %02x.%02x.%02x\n",
-			id1, id2, id3);
-		ddata->intro_printed = true;
-	}
-
-	in->ops.dsi->enable_hs(in, ddata->channel, true);
-
-	return 0;
-err:
-	dev_err(&ddata->pdev->dev, "error while enabling panel, issuing HW reset\n");
-
-	dsicm_hw_reset(ddata);
-
-	in->ops.dsi->disable(in, true, false);
-err0:
-	return r;
-}
-
-static void dsicm_power_off(struct panel_drv_data *ddata)
-{
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	in->ops.dsi->disable_video_output(in, ddata->channel);
-
-	r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_OFF);
-	if (!r)
-		r = dsicm_sleep_in(ddata);
-
-	if (r) {
-		dev_err(&ddata->pdev->dev,
-				"error disabling panel, issuing HW reset\n");
-		dsicm_hw_reset(ddata);
-	}
-
-	in->ops.dsi->disable(in, true, false);
-
-	ddata->enabled = 0;
-}
-
-static int dsicm_panel_reset(struct panel_drv_data *ddata)
-{
-	dev_err(&ddata->pdev->dev, "performing LCD reset\n");
-
-	dsicm_power_off(ddata);
-	dsicm_hw_reset(ddata);
-	return dsicm_power_on(ddata);
-}
-
-static int dsicm_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	struct device *dev = &ddata->pdev->dev;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dsi->connect(in, dssdev);
-	if (r) {
-		dev_err(dev, "Failed to connect to video source\n");
-		return r;
-	}
-
-	r = in->ops.dsi->request_vc(ddata->in, &ddata->channel);
-	if (r) {
-		dev_err(dev, "failed to get virtual channel\n");
-		goto err_req_vc;
-	}
-
-	r = in->ops.dsi->set_vc_id(ddata->in, ddata->channel, TCH);
-	if (r) {
-		dev_err(dev, "failed to set VC_ID\n");
-		goto err_vc_id;
-	}
-
-	return 0;
-
-err_vc_id:
-	in->ops.dsi->release_vc(ddata->in, ddata->channel);
-err_req_vc:
-	in->ops.dsi->disconnect(in, dssdev);
-	return r;
-}
-
-static void dsicm_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dsi->release_vc(in, ddata->channel);
-	in->ops.dsi->disconnect(in, dssdev);
-}
-
-static int dsicm_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(&ddata->pdev->dev, "enable\n");
-
-	mutex_lock(&ddata->lock);
-
-	if (!omapdss_device_is_connected(dssdev)) {
-		r = -ENODEV;
-		goto err;
-	}
-
-	if (omapdss_device_is_enabled(dssdev)) {
-		r = 0;
-		goto err;
-	}
-
-	in->ops.dsi->bus_lock(in);
-
-	r = dsicm_power_on(ddata);
-
-	in->ops.dsi->bus_unlock(in);
-
-	if (r)
-		goto err;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-err:
-	dev_dbg(&ddata->pdev->dev, "enable failed\n");
-	mutex_unlock(&ddata->lock);
-	return r;
-}
-
-static void dsicm_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(&ddata->pdev->dev, "disable\n");
-
-	mutex_lock(&ddata->lock);
-
-	dsicm_cancel_ulps_work(ddata);
-
-	in->ops.dsi->bus_lock(in);
-
-	if (omapdss_device_is_enabled(dssdev)) {
-		r = dsicm_wake_up(ddata);
-		if (!r)
-			dsicm_power_off(ddata);
-	}
-
-	in->ops.dsi->bus_unlock(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
-	mutex_unlock(&ddata->lock);
-}
-
-static void dsicm_framedone_cb(int err, void *data)
-{
-	struct panel_drv_data *ddata = data;
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(&ddata->pdev->dev, "framedone, err %d\n", err);
-	in->ops.dsi->bus_unlock(ddata->in);
-}
-
-static irqreturn_t dsicm_te_isr(int irq, void *data)
-{
-	struct panel_drv_data *ddata = data;
-	struct omap_dss_device *in = ddata->in;
-	int old;
-	int r;
-
-	old = atomic_cmpxchg(&ddata->do_update, 1, 0);
-
-	if (old) {
-		cancel_delayed_work(&ddata->te_timeout_work);
-
-		r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
-				ddata);
-		if (r)
-			goto err;
-	}
-
-	return IRQ_HANDLED;
-err:
-	dev_err(&ddata->pdev->dev, "start update failed\n");
-	in->ops.dsi->bus_unlock(in);
-	return IRQ_HANDLED;
-}
-
-static void dsicm_te_timeout_work_callback(struct work_struct *work)
-{
-	struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
-					te_timeout_work.work);
-	struct omap_dss_device *in = ddata->in;
-
-	dev_err(&ddata->pdev->dev, "TE not received for 250ms!\n");
-
-	atomic_set(&ddata->do_update, 0);
-	in->ops.dsi->bus_unlock(in);
-}
-
-static int dsicm_update(struct omap_dss_device *dssdev,
-				    u16 x, u16 y, u16 w, u16 h)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(&ddata->pdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
-
-	mutex_lock(&ddata->lock);
-	in->ops.dsi->bus_lock(in);
-
-	r = dsicm_wake_up(ddata);
-	if (r)
-		goto err;
-
-	if (!ddata->enabled) {
-		r = 0;
-		goto err;
-	}
-
-	/* XXX no need to send this every frame, but dsi break if not done */
-	r = dsicm_set_update_window(ddata, 0, 0,
-			dssdev->panel.timings.x_res,
-			dssdev->panel.timings.y_res);
-	if (r)
-		goto err;
-
-	if (ddata->te_enabled && gpio_is_valid(ddata->ext_te_gpio)) {
-		schedule_delayed_work(&ddata->te_timeout_work,
-				msecs_to_jiffies(250));
-		atomic_set(&ddata->do_update, 1);
-	} else {
-		r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
-				ddata);
-		if (r)
-			goto err;
-	}
-
-	/* note: no bus_unlock here. unlock is in framedone_cb */
-	mutex_unlock(&ddata->lock);
-	return 0;
-err:
-	in->ops.dsi->bus_unlock(in);
-	mutex_unlock(&ddata->lock);
-	return r;
-}
-
-static int dsicm_sync(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(&ddata->pdev->dev, "sync\n");
-
-	mutex_lock(&ddata->lock);
-	in->ops.dsi->bus_lock(in);
-	in->ops.dsi->bus_unlock(in);
-	mutex_unlock(&ddata->lock);
-
-	dev_dbg(&ddata->pdev->dev, "sync done\n");
-
-	return 0;
-}
-
-static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
-{
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (enable)
-		r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_TEAR_ON, 0);
-	else
-		r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF);
-
-	if (!gpio_is_valid(ddata->ext_te_gpio))
-		in->ops.dsi->enable_te(in, enable);
-
-	/* possible panel bug */
-	msleep(100);
-
-	return r;
-}
-
-static int dsicm_enable_te(struct omap_dss_device *dssdev, bool enable)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	mutex_lock(&ddata->lock);
-
-	if (ddata->te_enabled == enable)
-		goto end;
-
-	in->ops.dsi->bus_lock(in);
-
-	if (ddata->enabled) {
-		r = dsicm_wake_up(ddata);
-		if (r)
-			goto err;
-
-		r = _dsicm_enable_te(ddata, enable);
-		if (r)
-			goto err;
-	}
-
-	ddata->te_enabled = enable;
-
-	in->ops.dsi->bus_unlock(in);
-end:
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-err:
-	in->ops.dsi->bus_unlock(in);
-	mutex_unlock(&ddata->lock);
-
-	return r;
-}
-
-static int dsicm_get_te(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	int r;
-
-	mutex_lock(&ddata->lock);
-	r = ddata->te_enabled;
-	mutex_unlock(&ddata->lock);
-
-	return r;
-}
-
-static int dsicm_memory_read(struct omap_dss_device *dssdev,
-		void *buf, size_t size,
-		u16 x, u16 y, u16 w, u16 h)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-	int first = 1;
-	int plen;
-	unsigned buf_used = 0;
-
-	if (size < w * h * 3)
-		return -ENOMEM;
-
-	mutex_lock(&ddata->lock);
-
-	if (!ddata->enabled) {
-		r = -ENODEV;
-		goto err1;
-	}
-
-	size = min(w * h * 3,
-			dssdev->panel.timings.x_res *
-			dssdev->panel.timings.y_res * 3);
-
-	in->ops.dsi->bus_lock(in);
-
-	r = dsicm_wake_up(ddata);
-	if (r)
-		goto err2;
-
-	/* plen 1 or 2 goes into short packet. until checksum error is fixed,
-	 * use short packets. plen 32 works, but bigger packets seem to cause
-	 * an error. */
-	if (size % 2)
-		plen = 1;
-	else
-		plen = 2;
-
-	dsicm_set_update_window(ddata, x, y, w, h);
-
-	r = in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, plen);
-	if (r)
-		goto err2;
-
-	while (buf_used < size) {
-		u8 dcs_cmd = first ? 0x2e : 0x3e;
-		first = 0;
-
-		r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd,
-				buf + buf_used, size - buf_used);
-
-		if (r < 0) {
-			dev_err(dssdev->dev, "read error\n");
-			goto err3;
-		}
-
-		buf_used += r;
-
-		if (r < plen) {
-			dev_err(&ddata->pdev->dev, "short read\n");
-			break;
-		}
-
-		if (signal_pending(current)) {
-			dev_err(&ddata->pdev->dev, "signal pending, "
-					"aborting memory read\n");
-			r = -ERESTARTSYS;
-			goto err3;
-		}
-	}
-
-	r = buf_used;
-
-err3:
-	in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, 1);
-err2:
-	in->ops.dsi->bus_unlock(in);
-err1:
-	mutex_unlock(&ddata->lock);
-	return r;
-}
-
-static void dsicm_ulps_work(struct work_struct *work)
-{
-	struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
-			ulps_work.work);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	mutex_lock(&ddata->lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !ddata->enabled) {
-		mutex_unlock(&ddata->lock);
-		return;
-	}
-
-	in->ops.dsi->bus_lock(in);
-
-	dsicm_enter_ulps(ddata);
-
-	in->ops.dsi->bus_unlock(in);
-	mutex_unlock(&ddata->lock);
-}
-
-static struct omap_dss_driver dsicm_ops = {
-	.connect	= dsicm_connect,
-	.disconnect	= dsicm_disconnect,
-
-	.enable		= dsicm_enable,
-	.disable	= dsicm_disable,
-
-	.update		= dsicm_update,
-	.sync		= dsicm_sync,
-
-	.get_resolution	= dsicm_get_resolution,
-	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
-
-	.enable_te	= dsicm_enable_te,
-	.get_te		= dsicm_get_te,
-
-	.memory_read	= dsicm_memory_read,
-};
-
-static int dsicm_probe_pdata(struct platform_device *pdev)
-{
-	const struct panel_dsicm_platform_data *pdata;
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&pdev->dev, "failed to find video source\n");
-		return -EPROBE_DEFER;
-	}
-	ddata->in = in;
-
-	ddata->reset_gpio = pdata->reset_gpio;
-
-	if (pdata->use_ext_te)
-		ddata->ext_te_gpio = pdata->ext_te_gpio;
-	else
-		ddata->ext_te_gpio = -1;
-
-	ddata->ulps_timeout = pdata->ulps_timeout;
-
-	ddata->use_dsi_backlight = pdata->use_dsi_backlight;
-
-	ddata->pin_config = pdata->pin_config;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int dsicm_probe_of(struct platform_device *pdev)
-{
-	struct device_node *node = pdev->dev.of_node;
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *in;
-	int gpio;
-
-	gpio = of_get_named_gpio(node, "reset-gpios", 0);
-	if (!gpio_is_valid(gpio)) {
-		dev_err(&pdev->dev, "failed to parse reset gpio\n");
-		return gpio;
-	}
-	ddata->reset_gpio = gpio;
-
-	gpio = of_get_named_gpio(node, "te-gpios", 0);
-	if (gpio_is_valid(gpio) || gpio == -ENOENT) {
-		ddata->ext_te_gpio = gpio;
-	} else {
-		dev_err(&pdev->dev, "failed to parse TE gpio\n");
-		return gpio;
-	}
-
-	in = omapdss_of_find_source_for_first_ep(node);
-	if (IS_ERR(in)) {
-		dev_err(&pdev->dev, "failed to find video source\n");
-		return PTR_ERR(in);
-	}
-
-	ddata->in = in;
-
-	/* TODO: ulps, backlight */
-
-	return 0;
-}
-
-static int dsicm_probe(struct platform_device *pdev)
-{
-	struct backlight_properties props;
-	struct panel_drv_data *ddata;
-	struct backlight_device *bldev = NULL;
-	struct device *dev = &pdev->dev;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	dev_dbg(dev, "probe\n");
-
-	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-	ddata->pdev = pdev;
-
-	if (dev_get_platdata(dev)) {
-		r = dsicm_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else if (pdev->dev.of_node) {
-		r = dsicm_probe_of(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	ddata->timings.x_res = 864;
-	ddata->timings.y_res = 480;
-	ddata->timings.pixelclock = 864 * 480 * 60;
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = dev;
-	dssdev->driver = &dsicm_ops;
-	dssdev->panel.timings = ddata->timings;
-	dssdev->type = OMAP_DISPLAY_TYPE_DSI;
-	dssdev->owner = THIS_MODULE;
-
-	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
-	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
-		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	mutex_init(&ddata->lock);
-
-	atomic_set(&ddata->do_update, 0);
-
-	if (gpio_is_valid(ddata->reset_gpio)) {
-		r = devm_gpio_request_one(dev, ddata->reset_gpio,
-				GPIOF_OUT_INIT_LOW, "taal rst");
-		if (r) {
-			dev_err(dev, "failed to request reset gpio\n");
-			return r;
-		}
-	}
-
-	if (gpio_is_valid(ddata->ext_te_gpio)) {
-		r = devm_gpio_request_one(dev, ddata->ext_te_gpio,
-				GPIOF_IN, "taal irq");
-		if (r) {
-			dev_err(dev, "GPIO request failed\n");
-			return r;
-		}
-
-		r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio),
-				dsicm_te_isr,
-				IRQF_TRIGGER_RISING,
-				"taal vsync", ddata);
-
-		if (r) {
-			dev_err(dev, "IRQ request failed\n");
-			return r;
-		}
-
-		INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
-					dsicm_te_timeout_work_callback);
-
-		dev_dbg(dev, "Using GPIO TE\n");
-	}
-
-	ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
-	if (ddata->workqueue == NULL) {
-		dev_err(dev, "can't create workqueue\n");
-		return -ENOMEM;
-	}
-	INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
-
-	dsicm_hw_reset(ddata);
-
-	if (ddata->use_dsi_backlight) {
-		memset(&props, 0, sizeof(struct backlight_properties));
-		props.max_brightness = 255;
-
-		props.type = BACKLIGHT_RAW;
-		bldev = backlight_device_register(dev_name(dev),
-				dev, ddata, &dsicm_bl_ops, &props);
-		if (IS_ERR(bldev)) {
-			r = PTR_ERR(bldev);
-			goto err_bl;
-		}
-
-		ddata->bldev = bldev;
-
-		bldev->props.fb_blank = FB_BLANK_UNBLANK;
-		bldev->props.power = FB_BLANK_UNBLANK;
-		bldev->props.brightness = 255;
-
-		dsicm_bl_update_status(bldev);
-	}
-
-	r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
-	if (r) {
-		dev_err(dev, "failed to create sysfs files\n");
-		goto err_sysfs_create;
-	}
-
-	return 0;
-
-err_sysfs_create:
-	if (bldev != NULL)
-		backlight_device_unregister(bldev);
-err_bl:
-	destroy_workqueue(ddata->workqueue);
-err_reg:
-	return r;
-}
-
-static int __exit dsicm_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct backlight_device *bldev;
-
-	dev_dbg(&pdev->dev, "remove\n");
-
-	omapdss_unregister_display(dssdev);
-
-	dsicm_disable(dssdev);
-	dsicm_disconnect(dssdev);
-
-	sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
-
-	bldev = ddata->bldev;
-	if (bldev != NULL) {
-		bldev->props.power = FB_BLANK_POWERDOWN;
-		dsicm_bl_update_status(bldev);
-		backlight_device_unregister(bldev);
-	}
-
-	omap_dss_put_device(ddata->in);
-
-	dsicm_cancel_ulps_work(ddata);
-	destroy_workqueue(ddata->workqueue);
-
-	/* reset, to be sure that the panel is in a valid state */
-	dsicm_hw_reset(ddata);
-
-	return 0;
-}
-
-static const struct of_device_id dsicm_of_match[] = {
-	{ .compatible = "omapdss,panel-dsi-cm", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, dsicm_of_match);
-
-static struct platform_driver dsicm_driver = {
-	.probe = dsicm_probe,
-	.remove = __exit_p(dsicm_remove),
-	.driver = {
-		.name = "panel-dsi-cm",
-		.owner = THIS_MODULE,
-		.of_match_table = dsicm_of_match,
-	},
-};
-
-module_platform_driver(dsicm_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c
deleted file mode 100644
index 2e6b513222d9..000000000000
--- a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * LG.Philips LB035Q02 LCD Panel driver
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- * Based on a driver by: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/mutex.h>
-#include <linux/gpio.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-static struct omap_video_timings lb035q02_timings = {
-	.x_res = 320,
-	.y_res = 240,
-
-	.pixelclock	= 6500000,
-
-	.hsw		= 2,
-	.hfp		= 20,
-	.hbp		= 68,
-
-	.vsw		= 2,
-	.vfp		= 4,
-	.vbp		= 18,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
-};
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	struct spi_device *spi;
-
-	int data_lines;
-
-	struct omap_video_timings videomode;
-
-	int reset_gpio;
-	int backlight_gpio;
-	int enable_gpio;
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val)
-{
-	struct spi_message msg;
-	struct spi_transfer index_xfer = {
-		.len		= 3,
-		.cs_change	= 1,
-	};
-	struct spi_transfer value_xfer = {
-		.len		= 3,
-	};
-	u8	buffer[16];
-
-	spi_message_init(&msg);
-
-	/* register index */
-	buffer[0] = 0x70;
-	buffer[1] = 0x00;
-	buffer[2] = reg & 0x7f;
-	index_xfer.tx_buf = buffer;
-	spi_message_add_tail(&index_xfer, &msg);
-
-	/* register value */
-	buffer[4] = 0x72;
-	buffer[5] = val >> 8;
-	buffer[6] = val;
-	value_xfer.tx_buf = buffer + 4;
-	spi_message_add_tail(&value_xfer, &msg);
-
-	return spi_sync(spi, &msg);
-}
-
-static void init_lb035q02_panel(struct spi_device *spi)
-{
-	/* Init sequence from page 28 of the lb035q02 spec */
-	lb035q02_write_reg(spi, 0x01, 0x6300);
-	lb035q02_write_reg(spi, 0x02, 0x0200);
-	lb035q02_write_reg(spi, 0x03, 0x0177);
-	lb035q02_write_reg(spi, 0x04, 0x04c7);
-	lb035q02_write_reg(spi, 0x05, 0xffc0);
-	lb035q02_write_reg(spi, 0x06, 0xe806);
-	lb035q02_write_reg(spi, 0x0a, 0x4008);
-	lb035q02_write_reg(spi, 0x0b, 0x0000);
-	lb035q02_write_reg(spi, 0x0d, 0x0030);
-	lb035q02_write_reg(spi, 0x0e, 0x2800);
-	lb035q02_write_reg(spi, 0x0f, 0x0000);
-	lb035q02_write_reg(spi, 0x16, 0x9f80);
-	lb035q02_write_reg(spi, 0x17, 0x0a0f);
-	lb035q02_write_reg(spi, 0x1e, 0x00c1);
-	lb035q02_write_reg(spi, 0x30, 0x0300);
-	lb035q02_write_reg(spi, 0x31, 0x0007);
-	lb035q02_write_reg(spi, 0x32, 0x0000);
-	lb035q02_write_reg(spi, 0x33, 0x0000);
-	lb035q02_write_reg(spi, 0x34, 0x0707);
-	lb035q02_write_reg(spi, 0x35, 0x0004);
-	lb035q02_write_reg(spi, 0x36, 0x0302);
-	lb035q02_write_reg(spi, 0x37, 0x0202);
-	lb035q02_write_reg(spi, 0x3a, 0x0a0d);
-	lb035q02_write_reg(spi, 0x3b, 0x0806);
-}
-
-static int lb035q02_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dpi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	init_lb035q02_panel(ddata->spi);
-
-	return 0;
-}
-
-static void lb035q02_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dpi->disconnect(in, dssdev);
-}
-
-static int lb035q02_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
-
-	r = in->ops.dpi->enable(in);
-	if (r)
-		return r;
-
-	if (gpio_is_valid(ddata->enable_gpio))
-		gpio_set_value_cansleep(ddata->enable_gpio, 1);
-
-	if (gpio_is_valid(ddata->backlight_gpio))
-		gpio_set_value_cansleep(ddata->backlight_gpio, 1);
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void lb035q02_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	if (gpio_is_valid(ddata->enable_gpio))
-		gpio_set_value_cansleep(ddata->enable_gpio, 0);
-
-	if (gpio_is_valid(ddata->backlight_gpio))
-		gpio_set_value_cansleep(ddata->backlight_gpio, 0);
-
-	in->ops.dpi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void lb035q02_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dpi->set_timings(in, timings);
-}
-
-static void lb035q02_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->videomode;
-}
-
-static int lb035q02_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dpi->check_timings(in, timings);
-}
-
-static struct omap_dss_driver lb035q02_ops = {
-	.connect	= lb035q02_connect,
-	.disconnect	= lb035q02_disconnect,
-
-	.enable		= lb035q02_enable,
-	.disable	= lb035q02_disable,
-
-	.set_timings	= lb035q02_set_timings,
-	.get_timings	= lb035q02_get_timings,
-	.check_timings	= lb035q02_check_timings,
-
-	.get_resolution	= omapdss_default_get_resolution,
-};
-
-static int lb035q02_probe_pdata(struct spi_device *spi)
-{
-	const struct panel_lb035q02_platform_data *pdata;
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&spi->dev);
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&spi->dev, "failed to find video source '%s'\n",
-				pdata->source);
-		return -EPROBE_DEFER;
-	}
-
-	ddata->in = in;
-
-	ddata->data_lines = pdata->data_lines;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	ddata->enable_gpio = pdata->enable_gpio;
-	ddata->backlight_gpio = pdata->backlight_gpio;
-
-	return 0;
-}
-
-static int lb035q02_panel_spi_probe(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
-	if (ddata == NULL)
-		return -ENOMEM;
-
-	dev_set_drvdata(&spi->dev, ddata);
-
-	ddata->spi = spi;
-
-	if (dev_get_platdata(&spi->dev)) {
-		r = lb035q02_probe_pdata(spi);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	if (gpio_is_valid(ddata->enable_gpio)) {
-		r = devm_gpio_request_one(&spi->dev, ddata->enable_gpio,
-				GPIOF_OUT_INIT_LOW, "panel enable");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->backlight_gpio)) {
-		r = devm_gpio_request_one(&spi->dev, ddata->backlight_gpio,
-				GPIOF_OUT_INIT_LOW, "panel backlight");
-		if (r)
-			goto err_gpio;
-	}
-
-	ddata->videomode = lb035q02_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = &spi->dev;
-	dssdev->driver = &lb035q02_ops;
-	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
-	dssdev->phy.dpi.data_lines = ddata->data_lines;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&spi->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-err_gpio:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int lb035q02_panel_spi_remove(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_display(dssdev);
-
-	lb035q02_disable(dssdev);
-	lb035q02_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static struct spi_driver lb035q02_spi_driver = {
-	.probe		= lb035q02_panel_spi_probe,
-	.remove		= lb035q02_panel_spi_remove,
-	.driver		= {
-		.name	= "panel_lgphilips_lb035q02",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_spi_driver(lb035q02_spi_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("LG.Philips LB035Q02 LCD Panel driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c
deleted file mode 100644
index 996fa004b48c..000000000000
--- a/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * NEC NL8048HL11 Panel driver
- *
- * Copyright (C) 2010 Texas Instruments Inc.
- * Author: Erik Gilling <konkers@android.com>
- * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-struct panel_drv_data {
-	struct omap_dss_device	dssdev;
-	struct omap_dss_device *in;
-
-	struct omap_video_timings videomode;
-
-	int data_lines;
-
-	int res_gpio;
-	int qvga_gpio;
-
-	struct spi_device *spi;
-};
-
-#define LCD_XRES		800
-#define LCD_YRES		480
-/*
- * NEC PIX Clock Ratings
- * MIN:21.8MHz TYP:23.8MHz MAX:25.7MHz
- */
-#define LCD_PIXEL_CLOCK		23800000
-
-static const struct {
-	unsigned char addr;
-	unsigned char dat;
-} nec_8048_init_seq[] = {
-	{ 3, 0x01 }, { 0, 0x00 }, { 1, 0x01 }, { 4, 0x00 }, { 5, 0x14 },
-	{ 6, 0x24 }, { 16, 0xD7 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x55 },
-	{ 20, 0x01 }, { 21, 0x70 }, { 22, 0x1E }, { 23, 0x25 },	{ 24, 0x25 },
-	{ 25, 0x02 }, { 26, 0x02 }, { 27, 0xA0 }, { 32, 0x2F }, { 33, 0x0F },
-	{ 34, 0x0F }, { 35, 0x0F }, { 36, 0x0F }, { 37, 0x0F },	{ 38, 0x0F },
-	{ 39, 0x00 }, { 40, 0x02 }, { 41, 0x02 }, { 42, 0x02 },	{ 43, 0x0F },
-	{ 44, 0x0F }, { 45, 0x0F }, { 46, 0x0F }, { 47, 0x0F },	{ 48, 0x0F },
-	{ 49, 0x0F }, { 50, 0x00 }, { 51, 0x02 }, { 52, 0x02 }, { 53, 0x02 },
-	{ 80, 0x0C }, { 83, 0x42 }, { 84, 0x42 }, { 85, 0x41 },	{ 86, 0x14 },
-	{ 89, 0x88 }, { 90, 0x01 }, { 91, 0x00 }, { 92, 0x02 },	{ 93, 0x0C },
-	{ 94, 0x1C }, { 95, 0x27 }, { 98, 0x49 }, { 99, 0x27 }, { 102, 0x76 },
-	{ 103, 0x27 }, { 112, 0x01 }, { 113, 0x0E }, { 114, 0x02 },
-	{ 115, 0x0C }, { 118, 0x0C }, { 121, 0x30 }, { 130, 0x00 },
-	{ 131, 0x00 }, { 132, 0xFC }, { 134, 0x00 }, { 136, 0x00 },
-	{ 138, 0x00 }, { 139, 0x00 }, { 140, 0x00 }, { 141, 0xFC },
-	{ 143, 0x00 }, { 145, 0x00 }, { 147, 0x00 }, { 148, 0x00 },
-	{ 149, 0x00 }, { 150, 0xFC }, { 152, 0x00 }, { 154, 0x00 },
-	{ 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
-};
-
-static const struct omap_video_timings nec_8048_panel_timings = {
-	.x_res		= LCD_XRES,
-	.y_res		= LCD_YRES,
-	.pixelclock	= LCD_PIXEL_CLOCK,
-	.hfp		= 6,
-	.hsw		= 1,
-	.hbp		= 4,
-	.vfp		= 3,
-	.vsw		= 1,
-	.vbp		= 4,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static int nec_8048_spi_send(struct spi_device *spi, unsigned char reg_addr,
-			unsigned char reg_data)
-{
-	int ret = 0;
-	unsigned int cmd = 0, data = 0;
-
-	cmd = 0x0000 | reg_addr; /* register address write */
-	data = 0x0100 | reg_data; /* register data write */
-	data = (cmd << 16) | data;
-
-	ret = spi_write(spi, (unsigned char *)&data, 4);
-	if (ret)
-		pr_err("error in spi_write %x\n", data);
-
-	return ret;
-}
-
-static int init_nec_8048_wvga_lcd(struct spi_device *spi)
-{
-	unsigned int i;
-	/* Initialization Sequence */
-	/* nec_8048_spi_send(spi, REG, VAL) */
-	for (i = 0; i < (ARRAY_SIZE(nec_8048_init_seq) - 1); i++)
-		nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
-				nec_8048_init_seq[i].dat);
-	udelay(20);
-	nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
-				nec_8048_init_seq[i].dat);
-	return 0;
-}
-
-static int nec_8048_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dpi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void nec_8048_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dpi->disconnect(in, dssdev);
-}
-
-static int nec_8048_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
-
-	r = in->ops.dpi->enable(in);
-	if (r)
-		return r;
-
-	if (gpio_is_valid(ddata->res_gpio))
-		gpio_set_value_cansleep(ddata->res_gpio, 1);
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void nec_8048_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	if (gpio_is_valid(ddata->res_gpio))
-		gpio_set_value_cansleep(ddata->res_gpio, 0);
-
-	in->ops.dpi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void nec_8048_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dpi->set_timings(in, timings);
-}
-
-static void nec_8048_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->videomode;
-}
-
-static int nec_8048_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dpi->check_timings(in, timings);
-}
-
-static struct omap_dss_driver nec_8048_ops = {
-	.connect	= nec_8048_connect,
-	.disconnect	= nec_8048_disconnect,
-
-	.enable		= nec_8048_enable,
-	.disable	= nec_8048_disable,
-
-	.set_timings	= nec_8048_set_timings,
-	.get_timings	= nec_8048_get_timings,
-	.check_timings	= nec_8048_check_timings,
-
-	.get_resolution	= omapdss_default_get_resolution,
-};
-
-
-static int nec_8048_probe_pdata(struct spi_device *spi)
-{
-	const struct panel_nec_nl8048hl11_platform_data *pdata;
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&spi->dev);
-
-	ddata->qvga_gpio = pdata->qvga_gpio;
-	ddata->res_gpio = pdata->res_gpio;
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&spi->dev, "failed to find video source '%s'\n",
-				pdata->source);
-		return -EPROBE_DEFER;
-	}
-	ddata->in = in;
-
-	ddata->data_lines = pdata->data_lines;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int nec_8048_probe(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	dev_dbg(&spi->dev, "%s\n", __func__);
-
-	spi->mode = SPI_MODE_0;
-	spi->bits_per_word = 32;
-
-	r = spi_setup(spi);
-	if (r < 0) {
-		dev_err(&spi->dev, "spi_setup failed: %d\n", r);
-		return r;
-	}
-
-	init_nec_8048_wvga_lcd(spi);
-
-	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
-	if (ddata == NULL)
-		return -ENOMEM;
-
-	dev_set_drvdata(&spi->dev, ddata);
-
-	ddata->spi = spi;
-
-	if (dev_get_platdata(&spi->dev)) {
-		r = nec_8048_probe_pdata(spi);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	if (gpio_is_valid(ddata->qvga_gpio)) {
-		r = devm_gpio_request_one(&spi->dev, ddata->qvga_gpio,
-				GPIOF_OUT_INIT_HIGH, "lcd QVGA");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->res_gpio)) {
-		r = devm_gpio_request_one(&spi->dev, ddata->res_gpio,
-				GPIOF_OUT_INIT_LOW, "lcd RES");
-		if (r)
-			goto err_gpio;
-	}
-
-	ddata->videomode = nec_8048_panel_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = &spi->dev;
-	dssdev->driver = &nec_8048_ops;
-	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&spi->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-err_gpio:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int nec_8048_remove(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
-
-	omapdss_unregister_display(dssdev);
-
-	nec_8048_disable(dssdev);
-	nec_8048_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int nec_8048_suspend(struct device *dev)
-{
-	struct spi_device *spi = to_spi_device(dev);
-
-	nec_8048_spi_send(spi, 2, 0x01);
-	mdelay(40);
-
-	return 0;
-}
-
-static int nec_8048_resume(struct device *dev)
-{
-	struct spi_device *spi = to_spi_device(dev);
-
-	/* reinitialize the panel */
-	spi_setup(spi);
-	nec_8048_spi_send(spi, 2, 0x00);
-	init_nec_8048_wvga_lcd(spi);
-
-	return 0;
-}
-static SIMPLE_DEV_PM_OPS(nec_8048_pm_ops, nec_8048_suspend,
-		nec_8048_resume);
-#define NEC_8048_PM_OPS (&nec_8048_pm_ops)
-#else
-#define NEC_8048_PM_OPS NULL
-#endif
-
-static struct spi_driver nec_8048_driver = {
-	.driver = {
-		.name	= "panel-nec-nl8048hl11",
-		.owner	= THIS_MODULE,
-		.pm	= NEC_8048_PM_OPS,
-	},
-	.probe	= nec_8048_probe,
-	.remove	= nec_8048_remove,
-};
-
-module_spi_driver(nec_8048_driver);
-
-MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
-MODULE_DESCRIPTION("NEC-NL8048HL11 Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c
deleted file mode 100644
index b2f710be565d..000000000000
--- a/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * LCD panel driver for Sharp LS037V7DW01
- *
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	int data_lines;
-
-	struct omap_video_timings videomode;
-
-	int resb_gpio;
-	int ini_gpio;
-	int mo_gpio;
-	int lr_gpio;
-	int ud_gpio;
-};
-
-static const struct omap_video_timings sharp_ls_timings = {
-	.x_res = 480,
-	.y_res = 640,
-
-	.pixelclock	= 19200000,
-
-	.hsw		= 2,
-	.hfp		= 1,
-	.hbp		= 28,
-
-	.vsw		= 1,
-	.vfp		= 1,
-	.vbp		= 1,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static int sharp_ls_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dpi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void sharp_ls_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dpi->disconnect(in, dssdev);
-}
-
-static int sharp_ls_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
-
-	r = in->ops.dpi->enable(in);
-	if (r)
-		return r;
-
-	/* wait couple of vsyncs until enabling the LCD */
-	msleep(50);
-
-	if (gpio_is_valid(ddata->resb_gpio))
-		gpio_set_value_cansleep(ddata->resb_gpio, 1);
-
-	if (gpio_is_valid(ddata->ini_gpio))
-		gpio_set_value_cansleep(ddata->ini_gpio, 1);
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void sharp_ls_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	if (gpio_is_valid(ddata->ini_gpio))
-		gpio_set_value_cansleep(ddata->ini_gpio, 0);
-
-	if (gpio_is_valid(ddata->resb_gpio))
-		gpio_set_value_cansleep(ddata->resb_gpio, 0);
-
-	/* wait at least 5 vsyncs after disabling the LCD */
-
-	msleep(100);
-
-	in->ops.dpi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void sharp_ls_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dpi->set_timings(in, timings);
-}
-
-static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->videomode;
-}
-
-static int sharp_ls_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dpi->check_timings(in, timings);
-}
-
-static struct omap_dss_driver sharp_ls_ops = {
-	.connect	= sharp_ls_connect,
-	.disconnect	= sharp_ls_disconnect,
-
-	.enable		= sharp_ls_enable,
-	.disable	= sharp_ls_disable,
-
-	.set_timings	= sharp_ls_set_timings,
-	.get_timings	= sharp_ls_get_timings,
-	.check_timings	= sharp_ls_check_timings,
-
-	.get_resolution	= omapdss_default_get_resolution,
-};
-
-static int sharp_ls_probe_pdata(struct platform_device *pdev)
-{
-	const struct panel_sharp_ls037v7dw01_platform_data *pdata;
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&pdev->dev);
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&pdev->dev, "failed to find video source '%s'\n",
-				pdata->source);
-		return -EPROBE_DEFER;
-	}
-
-	ddata->in = in;
-
-	ddata->data_lines = pdata->data_lines;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	ddata->resb_gpio = pdata->resb_gpio;
-	ddata->ini_gpio = pdata->ini_gpio;
-	ddata->mo_gpio = pdata->mo_gpio;
-	ddata->lr_gpio = pdata->lr_gpio;
-	ddata->ud_gpio = pdata->ud_gpio;
-
-	return 0;
-}
-
-static int sharp_ls_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (ddata == NULL)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-
-	if (dev_get_platdata(&pdev->dev)) {
-		r = sharp_ls_probe_pdata(pdev);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	if (gpio_is_valid(ddata->mo_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->mo_gpio,
-				GPIOF_OUT_INIT_LOW, "lcd MO");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->lr_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->lr_gpio,
-				GPIOF_OUT_INIT_HIGH, "lcd LR");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->ud_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->ud_gpio,
-				GPIOF_OUT_INIT_HIGH, "lcd UD");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->resb_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->resb_gpio,
-				GPIOF_OUT_INIT_LOW, "lcd RESB");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->ini_gpio)) {
-		r = devm_gpio_request_one(&pdev->dev, ddata->ini_gpio,
-				GPIOF_OUT_INIT_LOW, "lcd INI");
-		if (r)
-			goto err_gpio;
-	}
-
-	ddata->videomode = sharp_ls_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = &pdev->dev;
-	dssdev->driver = &sharp_ls_ops;
-	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
-	dssdev->phy.dpi.data_lines = ddata->data_lines;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&pdev->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-err_gpio:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int __exit sharp_ls_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	omapdss_unregister_display(dssdev);
-
-	sharp_ls_disable(dssdev);
-	sharp_ls_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static struct platform_driver sharp_ls_driver = {
-	.probe = sharp_ls_probe,
-	.remove = __exit_p(sharp_ls_remove),
-	.driver = {
-		.name = "panel-sharp-ls037v7dw01",
-		.owner = THIS_MODULE,
-	},
-};
-
-module_platform_driver(sharp_ls_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
deleted file mode 100644
index c7ba4d8b928a..000000000000
--- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
+++ /dev/null
@@ -1,911 +0,0 @@
-/*
- * Sony ACX565AKM LCD Panel driver
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * Original Driver Author: Imre Deak <imre.deak@nokia.com>
- * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
- * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/jiffies.h>
-#include <linux/sched.h>
-#include <linux/backlight.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#define MIPID_CMD_READ_DISP_ID		0x04
-#define MIPID_CMD_READ_RED		0x06
-#define MIPID_CMD_READ_GREEN		0x07
-#define MIPID_CMD_READ_BLUE		0x08
-#define MIPID_CMD_READ_DISP_STATUS	0x09
-#define MIPID_CMD_RDDSDR		0x0F
-#define MIPID_CMD_SLEEP_IN		0x10
-#define MIPID_CMD_SLEEP_OUT		0x11
-#define MIPID_CMD_DISP_OFF		0x28
-#define MIPID_CMD_DISP_ON		0x29
-#define MIPID_CMD_WRITE_DISP_BRIGHTNESS	0x51
-#define MIPID_CMD_READ_DISP_BRIGHTNESS	0x52
-#define MIPID_CMD_WRITE_CTRL_DISP	0x53
-
-#define CTRL_DISP_BRIGHTNESS_CTRL_ON	(1 << 5)
-#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON	(1 << 4)
-#define CTRL_DISP_BACKLIGHT_ON		(1 << 2)
-#define CTRL_DISP_AUTO_BRIGHTNESS_ON	(1 << 1)
-
-#define MIPID_CMD_READ_CTRL_DISP	0x54
-#define MIPID_CMD_WRITE_CABC		0x55
-#define MIPID_CMD_READ_CABC		0x56
-
-#define MIPID_VER_LPH8923		3
-#define MIPID_VER_LS041Y3		4
-#define MIPID_VER_L4F00311		8
-#define MIPID_VER_ACX565AKM		9
-
-struct panel_drv_data {
-	struct omap_dss_device	dssdev;
-	struct omap_dss_device *in;
-
-	int reset_gpio;
-	int datapairs;
-
-	struct omap_video_timings videomode;
-
-	char		*name;
-	int		enabled;
-	int		model;
-	int		revision;
-	u8		display_id[3];
-	unsigned	has_bc:1;
-	unsigned	has_cabc:1;
-	unsigned	cabc_mode;
-	unsigned long	hw_guard_end;		/* next value of jiffies
-						   when we can issue the
-						   next sleep in/out command */
-	unsigned long	hw_guard_wait;		/* max guard time in jiffies */
-
-	struct spi_device	*spi;
-	struct mutex		mutex;
-
-	struct backlight_device *bl_dev;
-};
-
-static const struct omap_video_timings acx565akm_panel_timings = {
-	.x_res		= 800,
-	.y_res		= 480,
-	.pixelclock	= 24000000,
-	.hfp		= 28,
-	.hsw		= 4,
-	.hbp		= 24,
-	.vfp		= 3,
-	.vsw		= 3,
-	.vbp		= 4,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd,
-			      const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-	struct spi_message	m;
-	struct spi_transfer	*x, xfer[5];
-	int			r;
-
-	BUG_ON(ddata->spi == NULL);
-
-	spi_message_init(&m);
-
-	memset(xfer, 0, sizeof(xfer));
-	x = &xfer[0];
-
-	cmd &=  0xff;
-	x->tx_buf = &cmd;
-	x->bits_per_word = 9;
-	x->len = 2;
-
-	if (rlen > 1 && wlen == 0) {
-		/*
-		 * Between the command and the response data there is a
-		 * dummy clock cycle. Add an extra bit after the command
-		 * word to account for this.
-		 */
-		x->bits_per_word = 10;
-		cmd <<= 1;
-	}
-	spi_message_add_tail(x, &m);
-
-	if (wlen) {
-		x++;
-		x->tx_buf = wbuf;
-		x->len = wlen;
-		x->bits_per_word = 9;
-		spi_message_add_tail(x, &m);
-	}
-
-	if (rlen) {
-		x++;
-		x->rx_buf	= rbuf;
-		x->len		= rlen;
-		spi_message_add_tail(x, &m);
-	}
-
-	r = spi_sync(ddata->spi, &m);
-	if (r < 0)
-		dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r);
-}
-
-static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd)
-{
-	acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0);
-}
-
-static inline void acx565akm_write(struct panel_drv_data *ddata,
-			       int reg, const u8 *buf, int len)
-{
-	acx565akm_transfer(ddata, reg, buf, len, NULL, 0);
-}
-
-static inline void acx565akm_read(struct panel_drv_data *ddata,
-			      int reg, u8 *buf, int len)
-{
-	acx565akm_transfer(ddata, reg, NULL, 0, buf, len);
-}
-
-static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
-{
-	ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
-	ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
-}
-
-static void hw_guard_wait(struct panel_drv_data *ddata)
-{
-	unsigned long wait = ddata->hw_guard_end - jiffies;
-
-	if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(wait);
-	}
-}
-
-static void set_sleep_mode(struct panel_drv_data *ddata, int on)
-{
-	int cmd;
-
-	if (on)
-		cmd = MIPID_CMD_SLEEP_IN;
-	else
-		cmd = MIPID_CMD_SLEEP_OUT;
-	/*
-	 * We have to keep 120msec between sleep in/out commands.
-	 * (8.2.15, 8.2.16).
-	 */
-	hw_guard_wait(ddata);
-	acx565akm_cmd(ddata, cmd);
-	hw_guard_start(ddata, 120);
-}
-
-static void set_display_state(struct panel_drv_data *ddata, int enabled)
-{
-	int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
-
-	acx565akm_cmd(ddata, cmd);
-}
-
-static int panel_enabled(struct panel_drv_data *ddata)
-{
-	u32 disp_status;
-	int enabled;
-
-	acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS,
-			(u8 *)&disp_status, 4);
-	disp_status = __be32_to_cpu(disp_status);
-	enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
-	dev_dbg(&ddata->spi->dev,
-		"LCD panel %senabled by bootloader (status 0x%04x)\n",
-		enabled ? "" : "not ", disp_status);
-	return enabled;
-}
-
-static int panel_detect(struct panel_drv_data *ddata)
-{
-	acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3);
-	dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n",
-		ddata->display_id[0],
-		ddata->display_id[1],
-		ddata->display_id[2]);
-
-	switch (ddata->display_id[0]) {
-	case 0x10:
-		ddata->model = MIPID_VER_ACX565AKM;
-		ddata->name = "acx565akm";
-		ddata->has_bc = 1;
-		ddata->has_cabc = 1;
-		break;
-	case 0x29:
-		ddata->model = MIPID_VER_L4F00311;
-		ddata->name = "l4f00311";
-		break;
-	case 0x45:
-		ddata->model = MIPID_VER_LPH8923;
-		ddata->name = "lph8923";
-		break;
-	case 0x83:
-		ddata->model = MIPID_VER_LS041Y3;
-		ddata->name = "ls041y3";
-		break;
-	default:
-		ddata->name = "unknown";
-		dev_err(&ddata->spi->dev, "invalid display ID\n");
-		return -ENODEV;
-	}
-
-	ddata->revision = ddata->display_id[1];
-
-	dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n",
-			ddata->name, ddata->revision);
-
-	return 0;
-}
-
-/*----------------------Backlight Control-------------------------*/
-
-static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable)
-{
-	u16 ctrl;
-
-	acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
-	if (enable) {
-		ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
-			CTRL_DISP_BACKLIGHT_ON;
-	} else {
-		ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
-			  CTRL_DISP_BACKLIGHT_ON);
-	}
-
-	ctrl |= 1 << 8;
-	acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
-}
-
-static void set_cabc_mode(struct panel_drv_data *ddata, unsigned mode)
-{
-	u16 cabc_ctrl;
-
-	ddata->cabc_mode = mode;
-	if (!ddata->enabled)
-		return;
-	cabc_ctrl = 0;
-	acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
-	cabc_ctrl &= ~3;
-	cabc_ctrl |= (1 << 8) | (mode & 3);
-	acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
-}
-
-static unsigned get_cabc_mode(struct panel_drv_data *ddata)
-{
-	return ddata->cabc_mode;
-}
-
-static unsigned get_hw_cabc_mode(struct panel_drv_data *ddata)
-{
-	u8 cabc_ctrl;
-
-	acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
-	return cabc_ctrl & 3;
-}
-
-static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level)
-{
-	int bv;
-
-	bv = level | (1 << 8);
-	acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
-
-	if (level)
-		enable_backlight_ctrl(ddata, 1);
-	else
-		enable_backlight_ctrl(ddata, 0);
-}
-
-static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata)
-{
-	u8 bv;
-
-	acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
-
-	return bv;
-}
-
-
-static int acx565akm_bl_update_status(struct backlight_device *dev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
-	int level;
-
-	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
-
-	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-			dev->props.power == FB_BLANK_UNBLANK)
-		level = dev->props.brightness;
-	else
-		level = 0;
-
-	if (ddata->has_bc)
-		acx565akm_set_brightness(ddata, level);
-	else
-		return -ENODEV;
-
-	return 0;
-}
-
-static int acx565akm_bl_get_intensity(struct backlight_device *dev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
-
-	dev_dbg(&dev->dev, "%s\n", __func__);
-
-	if (!ddata->has_bc)
-		return -ENODEV;
-
-	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-			dev->props.power == FB_BLANK_UNBLANK) {
-		if (ddata->has_bc)
-			return acx565akm_get_actual_brightness(ddata);
-		else
-			return dev->props.brightness;
-	}
-
-	return 0;
-}
-
-static int acx565akm_bl_update_status_locked(struct backlight_device *dev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
-	int r;
-
-	mutex_lock(&ddata->mutex);
-	r = acx565akm_bl_update_status(dev);
-	mutex_unlock(&ddata->mutex);
-
-	return r;
-}
-
-static int acx565akm_bl_get_intensity_locked(struct backlight_device *dev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
-	int r;
-
-	mutex_lock(&ddata->mutex);
-	r = acx565akm_bl_get_intensity(dev);
-	mutex_unlock(&ddata->mutex);
-
-	return r;
-}
-
-static const struct backlight_ops acx565akm_bl_ops = {
-	.get_brightness = acx565akm_bl_get_intensity_locked,
-	.update_status  = acx565akm_bl_update_status_locked,
-};
-
-/*--------------------Auto Brightness control via Sysfs---------------------*/
-
-static const char * const cabc_modes[] = {
-	"off",		/* always used when CABC is not supported */
-	"ui",
-	"still-image",
-	"moving-image",
-};
-
-static ssize_t show_cabc_mode(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	const char *mode_str;
-	int mode;
-	int len;
-
-	if (!ddata->has_cabc)
-		mode = 0;
-	else
-		mode = get_cabc_mode(ddata);
-	mode_str = "unknown";
-	if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
-		mode_str = cabc_modes[mode];
-	len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
-
-	return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
-}
-
-static ssize_t store_cabc_mode(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
-		const char *mode_str = cabc_modes[i];
-		int cmp_len = strlen(mode_str);
-
-		if (count > 0 && buf[count - 1] == '\n')
-			count--;
-		if (count != cmp_len)
-			continue;
-
-		if (strncmp(buf, mode_str, cmp_len) == 0)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(cabc_modes))
-		return -EINVAL;
-
-	if (!ddata->has_cabc && i != 0)
-		return -EINVAL;
-
-	mutex_lock(&ddata->mutex);
-	set_cabc_mode(ddata, i);
-	mutex_unlock(&ddata->mutex);
-
-	return count;
-}
-
-static ssize_t show_cabc_available_modes(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	int len;
-	int i;
-
-	if (!ddata->has_cabc)
-		return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
-
-	for (i = 0, len = 0;
-	     len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
-		len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
-			i ? " " : "", cabc_modes[i],
-			i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
-
-	return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
-}
-
-static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
-		show_cabc_mode, store_cabc_mode);
-static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
-		show_cabc_available_modes, NULL);
-
-static struct attribute *bldev_attrs[] = {
-	&dev_attr_cabc_mode.attr,
-	&dev_attr_cabc_available_modes.attr,
-	NULL,
-};
-
-static struct attribute_group bldev_attr_group = {
-	.attrs = bldev_attrs,
-};
-
-static int acx565akm_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.sdi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void acx565akm_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.sdi->disconnect(in, dssdev);
-}
-
-static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
-
-	in->ops.sdi->set_timings(in, &ddata->videomode);
-
-	if (ddata->datapairs > 0)
-		in->ops.sdi->set_datapairs(in, ddata->datapairs);
-
-	r = in->ops.sdi->enable(in);
-	if (r) {
-		pr_err("%s sdi enable failed\n", __func__);
-		return r;
-	}
-
-	/*FIXME tweak me */
-	msleep(50);
-
-	if (gpio_is_valid(ddata->reset_gpio))
-		gpio_set_value(ddata->reset_gpio, 1);
-
-	if (ddata->enabled) {
-		dev_dbg(&ddata->spi->dev, "panel already enabled\n");
-		return 0;
-	}
-
-	/*
-	 * We have to meet all the following delay requirements:
-	 * 1. tRW: reset pulse width 10usec (7.12.1)
-	 * 2. tRT: reset cancel time 5msec (7.12.1)
-	 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
-	 *    case (7.6.2)
-	 * 4. 120msec before the sleep out command (7.12.1)
-	 */
-	msleep(120);
-
-	set_sleep_mode(ddata, 0);
-	ddata->enabled = 1;
-
-	/* 5msec between sleep out and the next command. (8.2.16) */
-	usleep_range(5000, 10000);
-	set_display_state(ddata, 1);
-	set_cabc_mode(ddata, ddata->cabc_mode);
-
-	return acx565akm_bl_update_status(ddata->bl_dev);
-}
-
-static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(dssdev->dev, "%s\n", __func__);
-
-	if (!ddata->enabled)
-		return;
-
-	set_display_state(ddata, 0);
-	set_sleep_mode(ddata, 1);
-	ddata->enabled = 0;
-	/*
-	 * We have to provide PCLK,HS,VS signals for 2 frames (worst case
-	 * ~50msec) after sending the sleep in command and asserting the
-	 * reset signal. We probably could assert the reset w/o the delay
-	 * but we still delay to avoid possible artifacts. (7.6.1)
-	 */
-	msleep(50);
-
-	if (gpio_is_valid(ddata->reset_gpio))
-		gpio_set_value(ddata->reset_gpio, 0);
-
-	/* FIXME need to tweak this delay */
-	msleep(100);
-
-	in->ops.sdi->disable(in);
-}
-
-static int acx565akm_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	int r;
-
-	dev_dbg(dssdev->dev, "%s\n", __func__);
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	mutex_lock(&ddata->mutex);
-	r = acx565akm_panel_power_on(dssdev);
-	mutex_unlock(&ddata->mutex);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void acx565akm_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	dev_dbg(dssdev->dev, "%s\n", __func__);
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	mutex_lock(&ddata->mutex);
-	acx565akm_panel_power_off(dssdev);
-	mutex_unlock(&ddata->mutex);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void acx565akm_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.sdi->set_timings(in, timings);
-}
-
-static void acx565akm_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->videomode;
-}
-
-static int acx565akm_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.sdi->check_timings(in, timings);
-}
-
-static struct omap_dss_driver acx565akm_ops = {
-	.connect	= acx565akm_connect,
-	.disconnect	= acx565akm_disconnect,
-
-	.enable		= acx565akm_enable,
-	.disable	= acx565akm_disable,
-
-	.set_timings	= acx565akm_set_timings,
-	.get_timings	= acx565akm_get_timings,
-	.check_timings	= acx565akm_check_timings,
-
-	.get_resolution	= omapdss_default_get_resolution,
-};
-
-static int acx565akm_probe_pdata(struct spi_device *spi)
-{
-	const struct panel_acx565akm_platform_data *pdata;
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&spi->dev);
-
-	ddata->reset_gpio = pdata->reset_gpio;
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&spi->dev, "failed to find video source '%s'\n",
-				pdata->source);
-		return -EPROBE_DEFER;
-	}
-	ddata->in = in;
-
-	ddata->datapairs = pdata->datapairs;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int acx565akm_probe_of(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct device_node *np = spi->dev.of_node;
-
-	ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
-
-	ddata->in = omapdss_of_find_source_for_first_ep(np);
-	if (IS_ERR(ddata->in)) {
-		dev_err(&spi->dev, "failed to find video source\n");
-		return PTR_ERR(ddata->in);
-	}
-
-	return 0;
-}
-
-static int acx565akm_probe(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	struct backlight_device *bldev;
-	int max_brightness, brightness;
-	struct backlight_properties props;
-	int r;
-
-	dev_dbg(&spi->dev, "%s\n", __func__);
-
-	spi->mode = SPI_MODE_3;
-
-	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
-	if (ddata == NULL)
-		return -ENOMEM;
-
-	dev_set_drvdata(&spi->dev, ddata);
-
-	ddata->spi = spi;
-
-	mutex_init(&ddata->mutex);
-
-	if (dev_get_platdata(&spi->dev)) {
-		r = acx565akm_probe_pdata(spi);
-		if (r)
-			return r;
-	} else if (spi->dev.of_node) {
-		r = acx565akm_probe_of(spi);
-		if (r)
-			return r;
-	} else {
-		dev_err(&spi->dev, "platform data missing!\n");
-		return -ENODEV;
-	}
-
-	if (gpio_is_valid(ddata->reset_gpio)) {
-		r = devm_gpio_request_one(&spi->dev, ddata->reset_gpio,
-				GPIOF_OUT_INIT_LOW, "lcd reset");
-		if (r)
-			goto err_gpio;
-	}
-
-	if (gpio_is_valid(ddata->reset_gpio))
-		gpio_set_value(ddata->reset_gpio, 1);
-
-	/*
-	 * After reset we have to wait 5 msec before the first
-	 * command can be sent.
-	 */
-	usleep_range(5000, 10000);
-
-	ddata->enabled = panel_enabled(ddata);
-
-	r = panel_detect(ddata);
-
-	if (!ddata->enabled && gpio_is_valid(ddata->reset_gpio))
-		gpio_set_value(ddata->reset_gpio, 0);
-
-	if (r) {
-		dev_err(&spi->dev, "%s panel detect error\n", __func__);
-		goto err_detect;
-	}
-
-	memset(&props, 0, sizeof(props));
-	props.fb_blank = FB_BLANK_UNBLANK;
-	props.power = FB_BLANK_UNBLANK;
-	props.type = BACKLIGHT_RAW;
-
-	bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
-			ddata, &acx565akm_bl_ops, &props);
-	ddata->bl_dev = bldev;
-	if (ddata->has_cabc) {
-		r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
-		if (r) {
-			dev_err(&bldev->dev,
-				"%s failed to create sysfs files\n", __func__);
-			goto err_sysfs;
-		}
-		ddata->cabc_mode = get_hw_cabc_mode(ddata);
-	}
-
-	max_brightness = 255;
-
-	if (ddata->has_bc)
-		brightness = acx565akm_get_actual_brightness(ddata);
-	else
-		brightness = 0;
-
-	bldev->props.max_brightness = max_brightness;
-	bldev->props.brightness = brightness;
-
-	acx565akm_bl_update_status(bldev);
-
-
-	ddata->videomode = acx565akm_panel_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = &spi->dev;
-	dssdev->driver = &acx565akm_ops;
-	dssdev->type = OMAP_DISPLAY_TYPE_SDI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&spi->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-	sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group);
-err_sysfs:
-	backlight_device_unregister(bldev);
-err_detect:
-err_gpio:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int acx565akm_remove(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
-
-	sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group);
-	backlight_device_unregister(ddata->bl_dev);
-
-	omapdss_unregister_display(dssdev);
-
-	acx565akm_disable(dssdev);
-	acx565akm_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static const struct of_device_id acx565akm_of_match[] = {
-	{ .compatible = "omapdss,sony,acx565akm", },
-	{},
-};
-
-static struct spi_driver acx565akm_driver = {
-	.driver = {
-		.name	= "acx565akm",
-		.owner	= THIS_MODULE,
-		.of_match_table = acx565akm_of_match,
-	},
-	.probe	= acx565akm_probe,
-	.remove	= acx565akm_remove,
-};
-
-module_spi_driver(acx565akm_driver);
-
-MODULE_AUTHOR("Nokia Corporation");
-MODULE_DESCRIPTION("acx565akm LCD Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c
deleted file mode 100644
index fae6adc005a7..000000000000
--- a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Toppoly TD028TTEC1 panel support
- *
- * Copyright (C) 2008 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Neo 1973 code (jbt6k74.c):
- * Copyright (C) 2006-2007 by OpenMoko, Inc.
- * Author: Harald Welte <laforge@openmoko.org>
- *
- * Ported and adapted from Neo 1973 U-Boot by:
- * H. Nikolaus Schaller <hns@goldelico.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *in;
-
-	int data_lines;
-
-	struct omap_video_timings videomode;
-
-	struct spi_device *spi_dev;
-};
-
-static struct omap_video_timings td028ttec1_panel_timings = {
-	.x_res		= 480,
-	.y_res		= 640,
-	.pixelclock	= 22153000,
-	.hfp		= 24,
-	.hsw		= 8,
-	.hbp		= 8,
-	.vfp		= 4,
-	.vsw		= 2,
-	.vbp		= 2,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
-};
-
-#define JBT_COMMAND	0x000
-#define JBT_DATA	0x100
-
-static int jbt_ret_write_0(struct panel_drv_data *ddata, u8 reg)
-{
-	int rc;
-	u16 tx_buf = JBT_COMMAND | reg;
-
-	rc = spi_write(ddata->spi_dev, (u8 *)&tx_buf,
-			1*sizeof(u16));
-	if (rc != 0)
-		dev_err(&ddata->spi_dev->dev,
-			"jbt_ret_write_0 spi_write ret %d\n", rc);
-
-	return rc;
-}
-
-static int jbt_reg_write_1(struct panel_drv_data *ddata, u8 reg, u8 data)
-{
-	int rc;
-	u16 tx_buf[2];
-
-	tx_buf[0] = JBT_COMMAND | reg;
-	tx_buf[1] = JBT_DATA | data;
-	rc = spi_write(ddata->spi_dev, (u8 *)tx_buf,
-			2*sizeof(u16));
-	if (rc != 0)
-		dev_err(&ddata->spi_dev->dev,
-			"jbt_reg_write_1 spi_write ret %d\n", rc);
-
-	return rc;
-}
-
-static int jbt_reg_write_2(struct panel_drv_data *ddata, u8 reg, u16 data)
-{
-	int rc;
-	u16 tx_buf[3];
-
-	tx_buf[0] = JBT_COMMAND | reg;
-	tx_buf[1] = JBT_DATA | (data >> 8);
-	tx_buf[2] = JBT_DATA | (data & 0xff);
-
-	rc = spi_write(ddata->spi_dev, (u8 *)tx_buf,
-			3*sizeof(u16));
-
-	if (rc != 0)
-		dev_err(&ddata->spi_dev->dev,
-			"jbt_reg_write_2 spi_write ret %d\n", rc);
-
-	return rc;
-}
-
-enum jbt_register {
-	JBT_REG_SLEEP_IN		= 0x10,
-	JBT_REG_SLEEP_OUT		= 0x11,
-
-	JBT_REG_DISPLAY_OFF		= 0x28,
-	JBT_REG_DISPLAY_ON		= 0x29,
-
-	JBT_REG_RGB_FORMAT		= 0x3a,
-	JBT_REG_QUAD_RATE		= 0x3b,
-
-	JBT_REG_POWER_ON_OFF		= 0xb0,
-	JBT_REG_BOOSTER_OP		= 0xb1,
-	JBT_REG_BOOSTER_MODE		= 0xb2,
-	JBT_REG_BOOSTER_FREQ		= 0xb3,
-	JBT_REG_OPAMP_SYSCLK		= 0xb4,
-	JBT_REG_VSC_VOLTAGE		= 0xb5,
-	JBT_REG_VCOM_VOLTAGE		= 0xb6,
-	JBT_REG_EXT_DISPL		= 0xb7,
-	JBT_REG_OUTPUT_CONTROL		= 0xb8,
-	JBT_REG_DCCLK_DCEV		= 0xb9,
-	JBT_REG_DISPLAY_MODE1		= 0xba,
-	JBT_REG_DISPLAY_MODE2		= 0xbb,
-	JBT_REG_DISPLAY_MODE		= 0xbc,
-	JBT_REG_ASW_SLEW		= 0xbd,
-	JBT_REG_DUMMY_DISPLAY		= 0xbe,
-	JBT_REG_DRIVE_SYSTEM		= 0xbf,
-
-	JBT_REG_SLEEP_OUT_FR_A		= 0xc0,
-	JBT_REG_SLEEP_OUT_FR_B		= 0xc1,
-	JBT_REG_SLEEP_OUT_FR_C		= 0xc2,
-	JBT_REG_SLEEP_IN_LCCNT_D	= 0xc3,
-	JBT_REG_SLEEP_IN_LCCNT_E	= 0xc4,
-	JBT_REG_SLEEP_IN_LCCNT_F	= 0xc5,
-	JBT_REG_SLEEP_IN_LCCNT_G	= 0xc6,
-
-	JBT_REG_GAMMA1_FINE_1		= 0xc7,
-	JBT_REG_GAMMA1_FINE_2		= 0xc8,
-	JBT_REG_GAMMA1_INCLINATION	= 0xc9,
-	JBT_REG_GAMMA1_BLUE_OFFSET	= 0xca,
-
-	JBT_REG_BLANK_CONTROL		= 0xcf,
-	JBT_REG_BLANK_TH_TV		= 0xd0,
-	JBT_REG_CKV_ON_OFF		= 0xd1,
-	JBT_REG_CKV_1_2			= 0xd2,
-	JBT_REG_OEV_TIMING		= 0xd3,
-	JBT_REG_ASW_TIMING_1		= 0xd4,
-	JBT_REG_ASW_TIMING_2		= 0xd5,
-
-	JBT_REG_HCLOCK_VGA		= 0xec,
-	JBT_REG_HCLOCK_QVGA		= 0xed,
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static int td028ttec1_panel_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dpi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void td028ttec1_panel_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dpi->disconnect(in, dssdev);
-}
-
-static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
-
-	r = in->ops.dpi->enable(in);
-	if (r)
-		return r;
-
-	dev_dbg(dssdev->dev, "td028ttec1_panel_enable() - state %d\n",
-		dssdev->state);
-
-	/* three times command zero */
-	r |= jbt_ret_write_0(ddata, 0x00);
-	usleep_range(1000, 2000);
-	r |= jbt_ret_write_0(ddata, 0x00);
-	usleep_range(1000, 2000);
-	r |= jbt_ret_write_0(ddata, 0x00);
-	usleep_range(1000, 2000);
-
-	if (r) {
-		dev_warn(dssdev->dev, "transfer error\n");
-		goto transfer_err;
-	}
-
-	/* deep standby out */
-	r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x17);
-
-	/* RGB I/F on, RAM write off, QVGA through, SIGCON enable */
-	r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE, 0x80);
-
-	/* Quad mode off */
-	r |= jbt_reg_write_1(ddata, JBT_REG_QUAD_RATE, 0x00);
-
-	/* AVDD on, XVDD on */
-	r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x16);
-
-	/* Output control */
-	r |= jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0xfff9);
-
-	/* Sleep mode off */
-	r |= jbt_ret_write_0(ddata, JBT_REG_SLEEP_OUT);
-
-	/* at this point we have like 50% grey */
-
-	/* initialize register set */
-	r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE1, 0x01);
-	r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE2, 0x00);
-	r |= jbt_reg_write_1(ddata, JBT_REG_RGB_FORMAT, 0x60);
-	r |= jbt_reg_write_1(ddata, JBT_REG_DRIVE_SYSTEM, 0x10);
-	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_OP, 0x56);
-	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_MODE, 0x33);
-	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11);
-	r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11);
-	r |= jbt_reg_write_1(ddata, JBT_REG_OPAMP_SYSCLK, 0x02);
-	r |= jbt_reg_write_1(ddata, JBT_REG_VSC_VOLTAGE, 0x2b);
-	r |= jbt_reg_write_1(ddata, JBT_REG_VCOM_VOLTAGE, 0x40);
-	r |= jbt_reg_write_1(ddata, JBT_REG_EXT_DISPL, 0x03);
-	r |= jbt_reg_write_1(ddata, JBT_REG_DCCLK_DCEV, 0x04);
-	/*
-	 * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement
-	 * to avoid red / blue flicker
-	 */
-	r |= jbt_reg_write_1(ddata, JBT_REG_ASW_SLEW, 0x04);
-	r |= jbt_reg_write_1(ddata, JBT_REG_DUMMY_DISPLAY, 0x00);
-
-	r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_A, 0x11);
-	r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_B, 0x11);
-	r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_C, 0x11);
-	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040);
-	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0);
-	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020);
-	r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0);
-
-	r |= jbt_reg_write_2(ddata, JBT_REG_GAMMA1_FINE_1, 0x5533);
-	r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_FINE_2, 0x00);
-	r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_INCLINATION, 0x00);
-	r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
-
-	r |= jbt_reg_write_2(ddata, JBT_REG_HCLOCK_VGA, 0x1f0);
-	r |= jbt_reg_write_1(ddata, JBT_REG_BLANK_CONTROL, 0x02);
-	r |= jbt_reg_write_2(ddata, JBT_REG_BLANK_TH_TV, 0x0804);
-
-	r |= jbt_reg_write_1(ddata, JBT_REG_CKV_ON_OFF, 0x01);
-	r |= jbt_reg_write_2(ddata, JBT_REG_CKV_1_2, 0x0000);
-
-	r |= jbt_reg_write_2(ddata, JBT_REG_OEV_TIMING, 0x0d0e);
-	r |= jbt_reg_write_2(ddata, JBT_REG_ASW_TIMING_1, 0x11a4);
-	r |= jbt_reg_write_1(ddata, JBT_REG_ASW_TIMING_2, 0x0e);
-
-	r |= jbt_ret_write_0(ddata, JBT_REG_DISPLAY_ON);
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-transfer_err:
-
-	return r ? -EIO : 0;
-}
-
-static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	dev_dbg(dssdev->dev, "td028ttec1_panel_disable()\n");
-
-	jbt_ret_write_0(ddata, JBT_REG_DISPLAY_OFF);
-	jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0x8002);
-	jbt_ret_write_0(ddata, JBT_REG_SLEEP_IN);
-	jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00);
-
-	in->ops.dpi->disable(in);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dpi->set_timings(in, timings);
-}
-
-static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->videomode;
-}
-
-static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dpi->check_timings(in, timings);
-}
-
-static struct omap_dss_driver td028ttec1_ops = {
-	.connect	= td028ttec1_panel_connect,
-	.disconnect	= td028ttec1_panel_disconnect,
-
-	.enable		= td028ttec1_panel_enable,
-	.disable	= td028ttec1_panel_disable,
-
-	.set_timings	= td028ttec1_panel_set_timings,
-	.get_timings	= td028ttec1_panel_get_timings,
-	.check_timings	= td028ttec1_panel_check_timings,
-};
-
-static int td028ttec1_panel_probe_pdata(struct spi_device *spi)
-{
-	const struct panel_tpo_td028ttec1_platform_data *pdata;
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&spi->dev);
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&spi->dev, "failed to find video source '%s'\n",
-				pdata->source);
-		return -EPROBE_DEFER;
-	}
-
-	ddata->in = in;
-
-	ddata->data_lines = pdata->data_lines;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int td028ttec1_panel_probe(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	dev_dbg(&spi->dev, "%s\n", __func__);
-
-	spi->bits_per_word = 9;
-	spi->mode = SPI_MODE_3;
-
-	r = spi_setup(spi);
-	if (r < 0) {
-		dev_err(&spi->dev, "spi_setup failed: %d\n", r);
-		return r;
-	}
-
-	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
-	if (ddata == NULL)
-		return -ENOMEM;
-
-	dev_set_drvdata(&spi->dev, ddata);
-
-	ddata->spi_dev = spi;
-
-	if (dev_get_platdata(&spi->dev)) {
-		r = td028ttec1_panel_probe_pdata(spi);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	ddata->videomode = td028ttec1_panel_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = &spi->dev;
-	dssdev->driver = &td028ttec1_ops;
-	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
-	dssdev->phy.dpi.data_lines = ddata->data_lines;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&spi->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int td028ttec1_panel_remove(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(&ddata->spi_dev->dev, "%s\n", __func__);
-
-	omapdss_unregister_display(dssdev);
-
-	td028ttec1_panel_disable(dssdev);
-	td028ttec1_panel_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	return 0;
-}
-
-static struct spi_driver td028ttec1_spi_driver = {
-	.probe		= td028ttec1_panel_probe,
-	.remove		= td028ttec1_panel_remove,
-
-	.driver         = {
-		.name   = "panel-tpo-td028ttec1",
-		.owner  = THIS_MODULE,
-	},
-};
-
-module_spi_driver(td028ttec1_spi_driver);
-
-MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
-MODULE_DESCRIPTION("Toppoly TD028TTEC1 panel driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c
deleted file mode 100644
index 875b40263b33..000000000000
--- a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * TPO TD043MTEA1 Panel driver
- *
- * Author: Gražvydas Ignotas <notasas@gmail.com>
- * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/regulator/consumer.h>
-#include <linux/gpio.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#define TPO_R02_MODE(x)		((x) & 7)
-#define TPO_R02_MODE_800x480	7
-#define TPO_R02_NCLK_RISING	BIT(3)
-#define TPO_R02_HSYNC_HIGH	BIT(4)
-#define TPO_R02_VSYNC_HIGH	BIT(5)
-
-#define TPO_R03_NSTANDBY	BIT(0)
-#define TPO_R03_EN_CP_CLK	BIT(1)
-#define TPO_R03_EN_VGL_PUMP	BIT(2)
-#define TPO_R03_EN_PWM		BIT(3)
-#define TPO_R03_DRIVING_CAP_100	BIT(4)
-#define TPO_R03_EN_PRE_CHARGE	BIT(6)
-#define TPO_R03_SOFTWARE_CTL	BIT(7)
-
-#define TPO_R04_NFLIP_H		BIT(0)
-#define TPO_R04_NFLIP_V		BIT(1)
-#define TPO_R04_CP_CLK_FREQ_1H	BIT(2)
-#define TPO_R04_VGL_FREQ_1H	BIT(4)
-
-#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
-			TPO_R03_EN_VGL_PUMP |  TPO_R03_EN_PWM | \
-			TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
-			TPO_R03_SOFTWARE_CTL)
-
-#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
-			TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
-
-static const u16 tpo_td043_def_gamma[12] = {
-	105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
-};
-
-struct panel_drv_data {
-	struct omap_dss_device	dssdev;
-	struct omap_dss_device *in;
-
-	struct omap_video_timings videomode;
-
-	int data_lines;
-
-	struct spi_device *spi;
-	struct regulator *vcc_reg;
-	int nreset_gpio;
-	u16 gamma[12];
-	u32 mode;
-	u32 hmirror:1;
-	u32 vmirror:1;
-	u32 powered_on:1;
-	u32 spi_suspended:1;
-	u32 power_on_resume:1;
-};
-
-static const struct omap_video_timings tpo_td043_timings = {
-	.x_res		= 800,
-	.y_res		= 480,
-
-	.pixelclock	= 36000000,
-
-	.hsw		= 1,
-	.hfp		= 68,
-	.hbp		= 214,
-
-	.vsw		= 1,
-	.vfp		= 39,
-	.vbp		= 34,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
-{
-	struct spi_message	m;
-	struct spi_transfer	xfer;
-	u16			w;
-	int			r;
-
-	spi_message_init(&m);
-
-	memset(&xfer, 0, sizeof(xfer));
-
-	w = ((u16)addr << 10) | (1 << 8) | data;
-	xfer.tx_buf = &w;
-	xfer.bits_per_word = 16;
-	xfer.len = 2;
-	spi_message_add_tail(&xfer, &m);
-
-	r = spi_sync(spi, &m);
-	if (r < 0)
-		dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
-	return r;
-}
-
-static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
-{
-	u8 i, val;
-
-	/* gamma bits [9:8] */
-	for (val = i = 0; i < 4; i++)
-		val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
-	tpo_td043_write(spi, 0x11, val);
-
-	for (val = i = 0; i < 4; i++)
-		val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
-	tpo_td043_write(spi, 0x12, val);
-
-	for (val = i = 0; i < 4; i++)
-		val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
-	tpo_td043_write(spi, 0x13, val);
-
-	/* gamma bits [7:0] */
-	for (val = i = 0; i < 12; i++)
-		tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
-}
-
-static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
-{
-	u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V |
-		TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
-	if (h)
-		reg4 &= ~TPO_R04_NFLIP_H;
-	if (v)
-		reg4 &= ~TPO_R04_NFLIP_V;
-
-	return tpo_td043_write(spi, 4, reg4);
-}
-
-static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
-
-	ddata->hmirror = enable;
-	return tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
-			ddata->vmirror);
-}
-
-static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
-
-	return ddata->hmirror;
-}
-
-static ssize_t tpo_td043_vmirror_show(struct device *dev,
-	struct device_attribute *attr, char *buf)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", ddata->vmirror);
-}
-
-static ssize_t tpo_td043_vmirror_store(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	int val;
-	int ret;
-
-	ret = kstrtoint(buf, 0, &val);
-	if (ret < 0)
-		return ret;
-
-	val = !!val;
-
-	ret = tpo_td043_write_mirror(ddata->spi, ddata->hmirror, val);
-	if (ret < 0)
-		return ret;
-
-	ddata->vmirror = val;
-
-	return count;
-}
-
-static ssize_t tpo_td043_mode_show(struct device *dev,
-	struct device_attribute *attr, char *buf)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", ddata->mode);
-}
-
-static ssize_t tpo_td043_mode_store(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	long val;
-	int ret;
-
-	ret = kstrtol(buf, 0, &val);
-	if (ret != 0 || val & ~7)
-		return -EINVAL;
-
-	ddata->mode = val;
-
-	val |= TPO_R02_NCLK_RISING;
-	tpo_td043_write(ddata->spi, 2, val);
-
-	return count;
-}
-
-static ssize_t tpo_td043_gamma_show(struct device *dev,
-	struct device_attribute *attr, char *buf)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	ssize_t len = 0;
-	int ret;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ddata->gamma); i++) {
-		ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
-				ddata->gamma[i]);
-		if (ret < 0)
-			return ret;
-		len += ret;
-	}
-	buf[len - 1] = '\n';
-
-	return len;
-}
-
-static ssize_t tpo_td043_gamma_store(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	unsigned int g[12];
-	int ret;
-	int i;
-
-	ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
-			&g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
-			&g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
-
-	if (ret != 12)
-		return -EINVAL;
-
-	for (i = 0; i < 12; i++)
-		ddata->gamma[i] = g[i];
-
-	tpo_td043_write_gamma(ddata->spi, ddata->gamma);
-
-	return count;
-}
-
-static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
-		tpo_td043_vmirror_show, tpo_td043_vmirror_store);
-static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
-		tpo_td043_mode_show, tpo_td043_mode_store);
-static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
-		tpo_td043_gamma_show, tpo_td043_gamma_store);
-
-static struct attribute *tpo_td043_attrs[] = {
-	&dev_attr_vmirror.attr,
-	&dev_attr_mode.attr,
-	&dev_attr_gamma.attr,
-	NULL,
-};
-
-static struct attribute_group tpo_td043_attr_group = {
-	.attrs = tpo_td043_attrs,
-};
-
-static int tpo_td043_power_on(struct panel_drv_data *ddata)
-{
-	int r;
-
-	if (ddata->powered_on)
-		return 0;
-
-	r = regulator_enable(ddata->vcc_reg);
-	if (r != 0)
-		return r;
-
-	/* wait for panel to stabilize */
-	msleep(160);
-
-	if (gpio_is_valid(ddata->nreset_gpio))
-		gpio_set_value(ddata->nreset_gpio, 1);
-
-	tpo_td043_write(ddata->spi, 2,
-			TPO_R02_MODE(ddata->mode) | TPO_R02_NCLK_RISING);
-	tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_NORMAL);
-	tpo_td043_write(ddata->spi, 0x20, 0xf0);
-	tpo_td043_write(ddata->spi, 0x21, 0xf0);
-	tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
-			ddata->vmirror);
-	tpo_td043_write_gamma(ddata->spi, ddata->gamma);
-
-	ddata->powered_on = 1;
-	return 0;
-}
-
-static void tpo_td043_power_off(struct panel_drv_data *ddata)
-{
-	if (!ddata->powered_on)
-		return;
-
-	tpo_td043_write(ddata->spi, 3,
-			TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
-
-	if (gpio_is_valid(ddata->nreset_gpio))
-		gpio_set_value(ddata->nreset_gpio, 0);
-
-	/* wait for at least 2 vsyncs before cutting off power */
-	msleep(50);
-
-	tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_STANDBY);
-
-	regulator_disable(ddata->vcc_reg);
-
-	ddata->powered_on = 0;
-}
-
-static int tpo_td043_connect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (omapdss_device_is_connected(dssdev))
-		return 0;
-
-	r = in->ops.dpi->connect(in, dssdev);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static void tpo_td043_disconnect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return;
-
-	in->ops.dpi->disconnect(in, dssdev);
-}
-
-static int tpo_td043_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-	int r;
-
-	if (!omapdss_device_is_connected(dssdev))
-		return -ENODEV;
-
-	if (omapdss_device_is_enabled(dssdev))
-		return 0;
-
-	in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
-
-	r = in->ops.dpi->enable(in);
-	if (r)
-		return r;
-
-	/*
-	 * If we are resuming from system suspend, SPI clocks might not be
-	 * enabled yet, so we'll program the LCD from SPI PM resume callback.
-	 */
-	if (!ddata->spi_suspended) {
-		r = tpo_td043_power_on(ddata);
-		if (r) {
-			in->ops.dpi->disable(in);
-			return r;
-		}
-	}
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
-static void tpo_td043_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	if (!omapdss_device_is_enabled(dssdev))
-		return;
-
-	in->ops.dpi->disable(in);
-
-	if (!ddata->spi_suspended)
-		tpo_td043_power_off(ddata);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
-
-	in->ops.dpi->set_timings(in, timings);
-}
-
-static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	*timings = ddata->videomode;
-}
-
-static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *in = ddata->in;
-
-	return in->ops.dpi->check_timings(in, timings);
-}
-
-static struct omap_dss_driver tpo_td043_ops = {
-	.connect	= tpo_td043_connect,
-	.disconnect	= tpo_td043_disconnect,
-
-	.enable		= tpo_td043_enable,
-	.disable	= tpo_td043_disable,
-
-	.set_timings	= tpo_td043_set_timings,
-	.get_timings	= tpo_td043_get_timings,
-	.check_timings	= tpo_td043_check_timings,
-
-	.set_mirror	= tpo_td043_set_hmirror,
-	.get_mirror	= tpo_td043_get_hmirror,
-
-	.get_resolution	= omapdss_default_get_resolution,
-};
-
-
-static int tpo_td043_probe_pdata(struct spi_device *spi)
-{
-	const struct panel_tpo_td043mtea1_platform_data *pdata;
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev, *in;
-
-	pdata = dev_get_platdata(&spi->dev);
-
-	ddata->nreset_gpio = pdata->nreset_gpio;
-
-	in = omap_dss_find_output(pdata->source);
-	if (in == NULL) {
-		dev_err(&spi->dev, "failed to find video source '%s'\n",
-				pdata->source);
-		return -EPROBE_DEFER;
-	}
-	ddata->in = in;
-
-	ddata->data_lines = pdata->data_lines;
-
-	dssdev = &ddata->dssdev;
-	dssdev->name = pdata->name;
-
-	return 0;
-}
-
-static int tpo_td043_probe(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	int r;
-
-	dev_dbg(&spi->dev, "%s\n", __func__);
-
-	spi->bits_per_word = 16;
-	spi->mode = SPI_MODE_0;
-
-	r = spi_setup(spi);
-	if (r < 0) {
-		dev_err(&spi->dev, "spi_setup failed: %d\n", r);
-		return r;
-	}
-
-	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
-	if (ddata == NULL)
-		return -ENOMEM;
-
-	dev_set_drvdata(&spi->dev, ddata);
-
-	ddata->spi = spi;
-
-	if (dev_get_platdata(&spi->dev)) {
-		r = tpo_td043_probe_pdata(spi);
-		if (r)
-			return r;
-	} else {
-		return -ENODEV;
-	}
-
-	ddata->mode = TPO_R02_MODE_800x480;
-	memcpy(ddata->gamma, tpo_td043_def_gamma, sizeof(ddata->gamma));
-
-	ddata->vcc_reg = devm_regulator_get(&spi->dev, "vcc");
-	if (IS_ERR(ddata->vcc_reg)) {
-		dev_err(&spi->dev, "failed to get LCD VCC regulator\n");
-		r = PTR_ERR(ddata->vcc_reg);
-		goto err_regulator;
-	}
-
-	if (gpio_is_valid(ddata->nreset_gpio)) {
-		r = devm_gpio_request_one(&spi->dev,
-				ddata->nreset_gpio, GPIOF_OUT_INIT_LOW,
-				"lcd reset");
-		if (r < 0) {
-			dev_err(&spi->dev, "couldn't request reset GPIO\n");
-			goto err_gpio_req;
-		}
-	}
-
-	r = sysfs_create_group(&spi->dev.kobj, &tpo_td043_attr_group);
-	if (r) {
-		dev_err(&spi->dev, "failed to create sysfs files\n");
-		goto err_sysfs;
-	}
-
-	ddata->videomode = tpo_td043_timings;
-
-	dssdev = &ddata->dssdev;
-	dssdev->dev = &spi->dev;
-	dssdev->driver = &tpo_td043_ops;
-	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
-
-	r = omapdss_register_display(dssdev);
-	if (r) {
-		dev_err(&spi->dev, "Failed to register panel\n");
-		goto err_reg;
-	}
-
-	return 0;
-
-err_reg:
-	sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
-err_sysfs:
-err_gpio_req:
-err_regulator:
-	omap_dss_put_device(ddata->in);
-	return r;
-}
-
-static int tpo_td043_remove(struct spi_device *spi)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-	struct omap_dss_device *in = ddata->in;
-
-	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
-
-	omapdss_unregister_display(dssdev);
-
-	tpo_td043_disable(dssdev);
-	tpo_td043_disconnect(dssdev);
-
-	omap_dss_put_device(in);
-
-	sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int tpo_td043_spi_suspend(struct device *dev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-
-	dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", ddata);
-
-	ddata->power_on_resume = ddata->powered_on;
-	tpo_td043_power_off(ddata);
-	ddata->spi_suspended = 1;
-
-	return 0;
-}
-
-static int tpo_td043_spi_resume(struct device *dev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(dev);
-	int ret;
-
-	dev_dbg(dev, "tpo_td043_spi_resume\n");
-
-	if (ddata->power_on_resume) {
-		ret = tpo_td043_power_on(ddata);
-		if (ret)
-			return ret;
-	}
-	ddata->spi_suspended = 0;
-
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
-	tpo_td043_spi_suspend, tpo_td043_spi_resume);
-
-static struct spi_driver tpo_td043_spi_driver = {
-	.driver = {
-		.name	= "panel-tpo-td043mtea1",
-		.owner	= THIS_MODULE,
-		.pm	= &tpo_td043_spi_pm,
-	},
-	.probe	= tpo_td043_probe,
-	.remove	= tpo_td043_remove,
-};
-
-module_spi_driver(tpo_td043_spi_driver);
-
-MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
-MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
deleted file mode 100644
index dde4281663b1..000000000000
--- a/drivers/video/omap2/dss/Kconfig
+++ /dev/null
@@ -1,121 +0,0 @@
-menuconfig OMAP2_DSS
-        tristate "OMAP2+ Display Subsystem support"
-	select VIDEOMODE_HELPERS
-        help
-	  OMAP2+ Display Subsystem support.
-
-if OMAP2_DSS
-
-config OMAP2_DSS_DEBUG
-	bool "Debug support"
-	default n
-	help
-	  This enables printing of debug messages. Alternatively, debug messages
-	  can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
-	  appropriate flags in <debugfs>/dynamic_debug/control.
-
-config OMAP2_DSS_DEBUGFS
-	bool "Debugfs filesystem support"
-	depends on DEBUG_FS
-	default n
-	help
-	  This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
-	  querying about clock configuration and register configuration of dss,
-	  dispc, dsi, hdmi and rfbi.
-
-config OMAP2_DSS_COLLECT_IRQ_STATS
-	bool "Collect DSS IRQ statistics"
-	depends on OMAP2_DSS_DEBUGFS
-	default n
-	help
-	  Collect DSS IRQ statistics, printable via debugfs.
-
-	  The statistics can be found from
-	  <debugfs>/omapdss/dispc_irq for DISPC interrupts, and
-	  <debugfs>/omapdss/dsi_irq for DSI interrupts.
-
-config OMAP2_DSS_DPI
-	bool "DPI support"
-	default y
-	help
-	  DPI Interface. This is the Parallel Display Interface.
-
-config OMAP2_DSS_RFBI
-	bool "RFBI support"
-	depends on BROKEN
-        default n
-	help
-	  MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
-	  Instrument's terminology).
-
-	  DBI is a bus between the host processor and a peripheral,
-	  such as a display or a framebuffer chip.
-
-	  See http://www.mipi.org/ for DBI specifications.
-
-config OMAP2_DSS_VENC
-	bool "VENC support"
-        default y
-	help
-	  OMAP Video Encoder support for S-Video and composite TV-out.
-
-config OMAP4_DSS_HDMI
-	bool "HDMI support"
-        default y
-	help
-	  HDMI Interface. This adds the High Definition Multimedia Interface.
-	  See http://www.hdmi.org/ for HDMI specification.
-
-config OMAP4_DSS_HDMI_AUDIO
-	bool
-
-config OMAP2_DSS_SDI
-	bool "SDI support"
-        default n
-	help
-	  SDI (Serial Display Interface) support.
-
-	  SDI is a high speed one-way display serial bus between the host
-	  processor and a display.
-
-config OMAP2_DSS_DSI
-	bool "DSI support"
-        default n
-	help
-	  MIPI DSI (Display Serial Interface) support.
-
-	  DSI is a high speed half-duplex serial interface between the host
-	  processor and a peripheral, such as a display or a framebuffer chip.
-
-	  See http://www.mipi.org/ for DSI specifications.
-
-config OMAP2_DSS_MIN_FCK_PER_PCK
-	int "Minimum FCK/PCK ratio (for scaling)"
-	range 0 32
-	default 0
-	help
-	  This can be used to adjust the minimum FCK/PCK ratio.
-
-	  With this you can make sure that DISPC FCK is at least
-	  n x PCK. Video plane scaling requires higher FCK than
-	  normally.
-
-	  If this is set to 0, there's no extra constraint on the
-	  DISPC FCK. However, the FCK will at minimum be
-	  2xPCK (if active matrix) or 3xPCK (if passive matrix).
-
-	  Max FCK is 173MHz, so this doesn't work if your PCK
-	  is very high.
-
-config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
-	bool "Sleep 20ms after VENC reset"
-	default y
-	help
-	  There is a 20ms sleep after VENC reset which seemed to fix the
-	  reset. The reason for the bug is unclear, and it's also unclear
-	  on what platforms this happens.
-
-	  This option enables the sleep, and is enabled by default. You can
-	  disable the sleep if it doesn't cause problems on your platform.
-
-endif
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
deleted file mode 100644
index 8aec8bda27cc..000000000000
--- a/drivers/video/omap2/dss/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-obj-$(CONFIG_OMAP2_DSS) += omapdss.o
-# Core DSS files
-omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
-	output.o dss-of.o
-# DSS compat layer files
-omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
-	dispc-compat.o display-sysfs.o
-omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
-omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
-omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
-omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
-omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
-omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_common.o hdmi_wp.o hdmi_pll.o \
-	hdmi_phy.o hdmi4_core.o
-ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
deleted file mode 100644
index 0a0b084ce65d..000000000000
--- a/drivers/video/omap2/dss/apply.c
+++ /dev/null
@@ -1,1700 +0,0 @@
-/*
- * Copyright (C) 2011 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "APPLY"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/jiffies.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-#include "dispc-compat.h"
-
-/*
- * We have 4 levels of cache for the dispc settings. First two are in SW and
- * the latter two in HW.
- *
- *       set_info()
- *          v
- * +--------------------+
- * |     user_info      |
- * +--------------------+
- *          v
- *        apply()
- *          v
- * +--------------------+
- * |       info         |
- * +--------------------+
- *          v
- *      write_regs()
- *          v
- * +--------------------+
- * |  shadow registers  |
- * +--------------------+
- *          v
- * VFP or lcd/digit_enable
- *          v
- * +--------------------+
- * |      registers     |
- * +--------------------+
- */
-
-struct ovl_priv_data {
-
-	bool user_info_dirty;
-	struct omap_overlay_info user_info;
-
-	bool info_dirty;
-	struct omap_overlay_info info;
-
-	bool shadow_info_dirty;
-
-	bool extra_info_dirty;
-	bool shadow_extra_info_dirty;
-
-	bool enabled;
-	u32 fifo_low, fifo_high;
-
-	/*
-	 * True if overlay is to be enabled. Used to check and calculate configs
-	 * for the overlay before it is enabled in the HW.
-	 */
-	bool enabling;
-};
-
-struct mgr_priv_data {
-
-	bool user_info_dirty;
-	struct omap_overlay_manager_info user_info;
-
-	bool info_dirty;
-	struct omap_overlay_manager_info info;
-
-	bool shadow_info_dirty;
-
-	/* If true, GO bit is up and shadow registers cannot be written.
-	 * Never true for manual update displays */
-	bool busy;
-
-	/* If true, dispc output is enabled */
-	bool updating;
-
-	/* If true, a display is enabled using this manager */
-	bool enabled;
-
-	bool extra_info_dirty;
-	bool shadow_extra_info_dirty;
-
-	struct omap_video_timings timings;
-	struct dss_lcd_mgr_config lcd_config;
-
-	void (*framedone_handler)(void *);
-	void *framedone_handler_data;
-};
-
-static struct {
-	struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
-	struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
-
-	bool irq_enabled;
-} dss_data;
-
-/* protects dss_data */
-static spinlock_t data_lock;
-/* lock for blocking functions */
-static DEFINE_MUTEX(apply_lock);
-static DECLARE_COMPLETION(extra_updated_completion);
-
-static void dss_register_vsync_isr(void);
-
-static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
-{
-	return &dss_data.ovl_priv_data_array[ovl->id];
-}
-
-static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
-{
-	return &dss_data.mgr_priv_data_array[mgr->id];
-}
-
-static void apply_init_priv(void)
-{
-	const int num_ovls = dss_feat_get_num_ovls();
-	struct mgr_priv_data *mp;
-	int i;
-
-	spin_lock_init(&data_lock);
-
-	for (i = 0; i < num_ovls; ++i) {
-		struct ovl_priv_data *op;
-
-		op = &dss_data.ovl_priv_data_array[i];
-
-		op->info.color_mode = OMAP_DSS_COLOR_RGB16;
-		op->info.rotation_type = OMAP_DSS_ROT_DMA;
-
-		op->info.global_alpha = 255;
-
-		switch (i) {
-		case 0:
-			op->info.zorder = 0;
-			break;
-		case 1:
-			op->info.zorder =
-				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
-			break;
-		case 2:
-			op->info.zorder =
-				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
-			break;
-		case 3:
-			op->info.zorder =
-				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
-			break;
-		}
-
-		op->user_info = op->info;
-	}
-
-	/*
-	 * Initialize some of the lcd_config fields for TV manager, this lets
-	 * us prevent checking if the manager is LCD or TV at some places
-	 */
-	mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
-
-	mp->lcd_config.video_port_width = 24;
-	mp->lcd_config.clock_info.lck_div = 1;
-	mp->lcd_config.clock_info.pck_div = 1;
-}
-
-/*
- * A LCD manager's stallmode decides whether it is in manual or auto update. TV
- * manager is always auto update, stallmode field for TV manager is false by
- * default
- */
-static bool ovl_manual_update(struct omap_overlay *ovl)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
-
-	return mp->lcd_config.stallmode;
-}
-
-static bool mgr_manual_update(struct omap_overlay_manager *mgr)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	return mp->lcd_config.stallmode;
-}
-
-static int dss_check_settings_low(struct omap_overlay_manager *mgr,
-		bool applying)
-{
-	struct omap_overlay_info *oi;
-	struct omap_overlay_manager_info *mi;
-	struct omap_overlay *ovl;
-	struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
-	struct ovl_priv_data *op;
-	struct mgr_priv_data *mp;
-
-	mp = get_mgr_priv(mgr);
-
-	if (!mp->enabled)
-		return 0;
-
-	if (applying && mp->user_info_dirty)
-		mi = &mp->user_info;
-	else
-		mi = &mp->info;
-
-	/* collect the infos to be tested into the array */
-	list_for_each_entry(ovl, &mgr->overlays, list) {
-		op = get_ovl_priv(ovl);
-
-		if (!op->enabled && !op->enabling)
-			oi = NULL;
-		else if (applying && op->user_info_dirty)
-			oi = &op->user_info;
-		else
-			oi = &op->info;
-
-		ois[ovl->id] = oi;
-	}
-
-	return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
-}
-
-/*
- * check manager and overlay settings using overlay_info from data->info
- */
-static int dss_check_settings(struct omap_overlay_manager *mgr)
-{
-	return dss_check_settings_low(mgr, false);
-}
-
-/*
- * check manager and overlay settings using overlay_info from ovl->info if
- * dirty and from data->info otherwise
- */
-static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
-{
-	return dss_check_settings_low(mgr, true);
-}
-
-static bool need_isr(void)
-{
-	const int num_mgrs = dss_feat_get_num_mgrs();
-	int i;
-
-	for (i = 0; i < num_mgrs; ++i) {
-		struct omap_overlay_manager *mgr;
-		struct mgr_priv_data *mp;
-		struct omap_overlay *ovl;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (!mp->enabled)
-			continue;
-
-		if (mgr_manual_update(mgr)) {
-			/* to catch FRAMEDONE */
-			if (mp->updating)
-				return true;
-		} else {
-			/* to catch GO bit going down */
-			if (mp->busy)
-				return true;
-
-			/* to write new values to registers */
-			if (mp->info_dirty)
-				return true;
-
-			/* to set GO bit */
-			if (mp->shadow_info_dirty)
-				return true;
-
-			/*
-			 * NOTE: we don't check extra_info flags for disabled
-			 * managers, once the manager is enabled, the extra_info
-			 * related manager changes will be taken in by HW.
-			 */
-
-			/* to write new values to registers */
-			if (mp->extra_info_dirty)
-				return true;
-
-			/* to set GO bit */
-			if (mp->shadow_extra_info_dirty)
-				return true;
-
-			list_for_each_entry(ovl, &mgr->overlays, list) {
-				struct ovl_priv_data *op;
-
-				op = get_ovl_priv(ovl);
-
-				/*
-				 * NOTE: we check extra_info flags even for
-				 * disabled overlays, as extra_infos need to be
-				 * always written.
-				 */
-
-				/* to write new values to registers */
-				if (op->extra_info_dirty)
-					return true;
-
-				/* to set GO bit */
-				if (op->shadow_extra_info_dirty)
-					return true;
-
-				if (!op->enabled)
-					continue;
-
-				/* to write new values to registers */
-				if (op->info_dirty)
-					return true;
-
-				/* to set GO bit */
-				if (op->shadow_info_dirty)
-					return true;
-			}
-		}
-	}
-
-	return false;
-}
-
-static bool need_go(struct omap_overlay_manager *mgr)
-{
-	struct omap_overlay *ovl;
-	struct mgr_priv_data *mp;
-	struct ovl_priv_data *op;
-
-	mp = get_mgr_priv(mgr);
-
-	if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
-		return true;
-
-	list_for_each_entry(ovl, &mgr->overlays, list) {
-		op = get_ovl_priv(ovl);
-		if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
-			return true;
-	}
-
-	return false;
-}
-
-/* returns true if an extra_info field is currently being updated */
-static bool extra_info_update_ongoing(void)
-{
-	const int num_mgrs = dss_feat_get_num_mgrs();
-	int i;
-
-	for (i = 0; i < num_mgrs; ++i) {
-		struct omap_overlay_manager *mgr;
-		struct omap_overlay *ovl;
-		struct mgr_priv_data *mp;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (!mp->enabled)
-			continue;
-
-		if (!mp->updating)
-			continue;
-
-		if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
-			return true;
-
-		list_for_each_entry(ovl, &mgr->overlays, list) {
-			struct ovl_priv_data *op = get_ovl_priv(ovl);
-
-			if (op->extra_info_dirty || op->shadow_extra_info_dirty)
-				return true;
-		}
-	}
-
-	return false;
-}
-
-/* wait until no extra_info updates are pending */
-static void wait_pending_extra_info_updates(void)
-{
-	bool updating;
-	unsigned long flags;
-	unsigned long t;
-	int r;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	updating = extra_info_update_ongoing();
-
-	if (!updating) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		return;
-	}
-
-	init_completion(&extra_updated_completion);
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	t = msecs_to_jiffies(500);
-	r = wait_for_completion_timeout(&extra_updated_completion, t);
-	if (r == 0)
-		DSSWARN("timeout in wait_pending_extra_info_updates\n");
-}
-
-static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
-{
-	struct omap_dss_device *dssdev;
-
-	dssdev = mgr->output;
-	if (dssdev == NULL)
-		return NULL;
-
-	while (dssdev->dst)
-		dssdev = dssdev->dst;
-
-	if (dssdev->driver)
-		return dssdev;
-	else
-		return NULL;
-}
-
-static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
-{
-	return ovl->manager ? dss_mgr_get_device(ovl->manager) : NULL;
-}
-
-static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
-{
-	unsigned long timeout = msecs_to_jiffies(500);
-	u32 irq;
-	int r;
-
-	if (mgr->output == NULL)
-		return -ENODEV;
-
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
-	switch (mgr->output->id) {
-	case OMAP_DSS_OUTPUT_VENC:
-		irq = DISPC_IRQ_EVSYNC_ODD;
-		break;
-	case OMAP_DSS_OUTPUT_HDMI:
-		irq = DISPC_IRQ_EVSYNC_EVEN;
-		break;
-	default:
-		irq = dispc_mgr_get_vsync_irq(mgr->id);
-		break;
-	}
-
-	r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
-
-	dispc_runtime_put();
-
-	return r;
-}
-
-static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
-{
-	unsigned long timeout = msecs_to_jiffies(500);
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	u32 irq;
-	unsigned long flags;
-	int r;
-	int i;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (mgr_manual_update(mgr)) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		return 0;
-	}
-
-	if (!mp->enabled) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		return 0;
-	}
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
-	irq = dispc_mgr_get_vsync_irq(mgr->id);
-
-	i = 0;
-	while (1) {
-		bool shadow_dirty, dirty;
-
-		spin_lock_irqsave(&data_lock, flags);
-		dirty = mp->info_dirty;
-		shadow_dirty = mp->shadow_info_dirty;
-		spin_unlock_irqrestore(&data_lock, flags);
-
-		if (!dirty && !shadow_dirty) {
-			r = 0;
-			break;
-		}
-
-		/* 4 iterations is the worst case:
-		 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
-		 * 2 - first VSYNC, dirty = true
-		 * 3 - dirty = false, shadow_dirty = true
-		 * 4 - shadow_dirty = false */
-		if (i++ == 3) {
-			DSSERR("mgr(%d)->wait_for_go() not finishing\n",
-					mgr->id);
-			r = 0;
-			break;
-		}
-
-		r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
-		if (r == -ERESTARTSYS)
-			break;
-
-		if (r) {
-			DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
-			break;
-		}
-	}
-
-	dispc_runtime_put();
-
-	return r;
-}
-
-static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
-{
-	unsigned long timeout = msecs_to_jiffies(500);
-	struct ovl_priv_data *op;
-	struct mgr_priv_data *mp;
-	u32 irq;
-	unsigned long flags;
-	int r;
-	int i;
-
-	if (!ovl->manager)
-		return 0;
-
-	mp = get_mgr_priv(ovl->manager);
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (ovl_manual_update(ovl)) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		return 0;
-	}
-
-	if (!mp->enabled) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		return 0;
-	}
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
-	irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
-
-	op = get_ovl_priv(ovl);
-	i = 0;
-	while (1) {
-		bool shadow_dirty, dirty;
-
-		spin_lock_irqsave(&data_lock, flags);
-		dirty = op->info_dirty;
-		shadow_dirty = op->shadow_info_dirty;
-		spin_unlock_irqrestore(&data_lock, flags);
-
-		if (!dirty && !shadow_dirty) {
-			r = 0;
-			break;
-		}
-
-		/* 4 iterations is the worst case:
-		 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
-		 * 2 - first VSYNC, dirty = true
-		 * 3 - dirty = false, shadow_dirty = true
-		 * 4 - shadow_dirty = false */
-		if (i++ == 3) {
-			DSSERR("ovl(%d)->wait_for_go() not finishing\n",
-					ovl->id);
-			r = 0;
-			break;
-		}
-
-		r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
-		if (r == -ERESTARTSYS)
-			break;
-
-		if (r) {
-			DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
-			break;
-		}
-	}
-
-	dispc_runtime_put();
-
-	return r;
-}
-
-static void dss_ovl_write_regs(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	struct omap_overlay_info *oi;
-	bool replication;
-	struct mgr_priv_data *mp;
-	int r;
-
-	DSSDBG("writing ovl %d regs\n", ovl->id);
-
-	if (!op->enabled || !op->info_dirty)
-		return;
-
-	oi = &op->info;
-
-	mp = get_mgr_priv(ovl->manager);
-
-	replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
-
-	r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
-	if (r) {
-		/*
-		 * We can't do much here, as this function can be called from
-		 * vsync interrupt.
-		 */
-		DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
-
-		/* This will leave fifo configurations in a nonoptimal state */
-		op->enabled = false;
-		dispc_ovl_enable(ovl->id, false);
-		return;
-	}
-
-	op->info_dirty = false;
-	if (mp->updating)
-		op->shadow_info_dirty = true;
-}
-
-static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	struct mgr_priv_data *mp;
-
-	DSSDBG("writing ovl %d regs extra\n", ovl->id);
-
-	if (!op->extra_info_dirty)
-		return;
-
-	/* note: write also when op->enabled == false, so that the ovl gets
-	 * disabled */
-
-	dispc_ovl_enable(ovl->id, op->enabled);
-	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
-
-	mp = get_mgr_priv(ovl->manager);
-
-	op->extra_info_dirty = false;
-	if (mp->updating)
-		op->shadow_extra_info_dirty = true;
-}
-
-static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	struct omap_overlay *ovl;
-
-	DSSDBG("writing mgr %d regs\n", mgr->id);
-
-	if (!mp->enabled)
-		return;
-
-	WARN_ON(mp->busy);
-
-	/* Commit overlay settings */
-	list_for_each_entry(ovl, &mgr->overlays, list) {
-		dss_ovl_write_regs(ovl);
-		dss_ovl_write_regs_extra(ovl);
-	}
-
-	if (mp->info_dirty) {
-		dispc_mgr_setup(mgr->id, &mp->info);
-
-		mp->info_dirty = false;
-		if (mp->updating)
-			mp->shadow_info_dirty = true;
-	}
-}
-
-static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	DSSDBG("writing mgr %d regs extra\n", mgr->id);
-
-	if (!mp->extra_info_dirty)
-		return;
-
-	dispc_mgr_set_timings(mgr->id, &mp->timings);
-
-	/* lcd_config parameters */
-	if (dss_mgr_is_lcd(mgr->id))
-		dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
-
-	mp->extra_info_dirty = false;
-	if (mp->updating)
-		mp->shadow_extra_info_dirty = true;
-}
-
-static void dss_write_regs(void)
-{
-	const int num_mgrs = omap_dss_get_num_overlay_managers();
-	int i;
-
-	for (i = 0; i < num_mgrs; ++i) {
-		struct omap_overlay_manager *mgr;
-		struct mgr_priv_data *mp;
-		int r;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
-			continue;
-
-		r = dss_check_settings(mgr);
-		if (r) {
-			DSSERR("cannot write registers for manager %s: "
-					"illegal configuration\n", mgr->name);
-			continue;
-		}
-
-		dss_mgr_write_regs(mgr);
-		dss_mgr_write_regs_extra(mgr);
-	}
-}
-
-static void dss_set_go_bits(void)
-{
-	const int num_mgrs = omap_dss_get_num_overlay_managers();
-	int i;
-
-	for (i = 0; i < num_mgrs; ++i) {
-		struct omap_overlay_manager *mgr;
-		struct mgr_priv_data *mp;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
-			continue;
-
-		if (!need_go(mgr))
-			continue;
-
-		mp->busy = true;
-
-		if (!dss_data.irq_enabled && need_isr())
-			dss_register_vsync_isr();
-
-		dispc_mgr_go(mgr->id);
-	}
-
-}
-
-static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
-{
-	struct omap_overlay *ovl;
-	struct mgr_priv_data *mp;
-	struct ovl_priv_data *op;
-
-	mp = get_mgr_priv(mgr);
-	mp->shadow_info_dirty = false;
-	mp->shadow_extra_info_dirty = false;
-
-	list_for_each_entry(ovl, &mgr->overlays, list) {
-		op = get_ovl_priv(ovl);
-		op->shadow_info_dirty = false;
-		op->shadow_extra_info_dirty = false;
-	}
-}
-
-static int dss_mgr_connect_compat(struct omap_overlay_manager *mgr,
-		struct omap_dss_device *dst)
-{
-	return mgr->set_output(mgr, dst);
-}
-
-static void dss_mgr_disconnect_compat(struct omap_overlay_manager *mgr,
-		struct omap_dss_device *dst)
-{
-	mgr->unset_output(mgr);
-}
-
-static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	WARN_ON(mp->updating);
-
-	r = dss_check_settings(mgr);
-	if (r) {
-		DSSERR("cannot start manual update: illegal configuration\n");
-		spin_unlock_irqrestore(&data_lock, flags);
-		return;
-	}
-
-	dss_mgr_write_regs(mgr);
-	dss_mgr_write_regs_extra(mgr);
-
-	mp->updating = true;
-
-	if (!dss_data.irq_enabled && need_isr())
-		dss_register_vsync_isr();
-
-	dispc_mgr_enable_sync(mgr->id);
-
-	spin_unlock_irqrestore(&data_lock, flags);
-}
-
-static void dss_apply_irq_handler(void *data, u32 mask);
-
-static void dss_register_vsync_isr(void)
-{
-	const int num_mgrs = dss_feat_get_num_mgrs();
-	u32 mask;
-	int r, i;
-
-	mask = 0;
-	for (i = 0; i < num_mgrs; ++i)
-		mask |= dispc_mgr_get_vsync_irq(i);
-
-	for (i = 0; i < num_mgrs; ++i)
-		mask |= dispc_mgr_get_framedone_irq(i);
-
-	r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
-	WARN_ON(r);
-
-	dss_data.irq_enabled = true;
-}
-
-static void dss_unregister_vsync_isr(void)
-{
-	const int num_mgrs = dss_feat_get_num_mgrs();
-	u32 mask;
-	int r, i;
-
-	mask = 0;
-	for (i = 0; i < num_mgrs; ++i)
-		mask |= dispc_mgr_get_vsync_irq(i);
-
-	for (i = 0; i < num_mgrs; ++i)
-		mask |= dispc_mgr_get_framedone_irq(i);
-
-	r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
-	WARN_ON(r);
-
-	dss_data.irq_enabled = false;
-}
-
-static void dss_apply_irq_handler(void *data, u32 mask)
-{
-	const int num_mgrs = dss_feat_get_num_mgrs();
-	int i;
-	bool extra_updating;
-
-	spin_lock(&data_lock);
-
-	/* clear busy, updating flags, shadow_dirty flags */
-	for (i = 0; i < num_mgrs; i++) {
-		struct omap_overlay_manager *mgr;
-		struct mgr_priv_data *mp;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (!mp->enabled)
-			continue;
-
-		mp->updating = dispc_mgr_is_enabled(i);
-
-		if (!mgr_manual_update(mgr)) {
-			bool was_busy = mp->busy;
-			mp->busy = dispc_mgr_go_busy(i);
-
-			if (was_busy && !mp->busy)
-				mgr_clear_shadow_dirty(mgr);
-		}
-	}
-
-	dss_write_regs();
-	dss_set_go_bits();
-
-	extra_updating = extra_info_update_ongoing();
-	if (!extra_updating)
-		complete_all(&extra_updated_completion);
-
-	/* call framedone handlers for manual update displays */
-	for (i = 0; i < num_mgrs; i++) {
-		struct omap_overlay_manager *mgr;
-		struct mgr_priv_data *mp;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (!mgr_manual_update(mgr) || !mp->framedone_handler)
-			continue;
-
-		if (mask & dispc_mgr_get_framedone_irq(i))
-			mp->framedone_handler(mp->framedone_handler_data);
-	}
-
-	if (!need_isr())
-		dss_unregister_vsync_isr();
-
-	spin_unlock(&data_lock);
-}
-
-static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op;
-
-	op = get_ovl_priv(ovl);
-
-	if (!op->user_info_dirty)
-		return;
-
-	op->user_info_dirty = false;
-	op->info_dirty = true;
-	op->info = op->user_info;
-}
-
-static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
-{
-	struct mgr_priv_data *mp;
-
-	mp = get_mgr_priv(mgr);
-
-	if (!mp->user_info_dirty)
-		return;
-
-	mp->user_info_dirty = false;
-	mp->info_dirty = true;
-	mp->info = mp->user_info;
-}
-
-static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
-{
-	unsigned long flags;
-	struct omap_overlay *ovl;
-	int r;
-
-	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	r = dss_check_settings_apply(mgr);
-	if (r) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		DSSERR("failed to apply settings: illegal configuration.\n");
-		return r;
-	}
-
-	/* Configure overlays */
-	list_for_each_entry(ovl, &mgr->overlays, list)
-		omap_dss_mgr_apply_ovl(ovl);
-
-	/* Configure manager */
-	omap_dss_mgr_apply_mgr(mgr);
-
-	dss_write_regs();
-	dss_set_go_bits();
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	return 0;
-}
-
-static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
-{
-	struct ovl_priv_data *op;
-
-	op = get_ovl_priv(ovl);
-
-	if (op->enabled == enable)
-		return;
-
-	op->enabled = enable;
-	op->extra_info_dirty = true;
-}
-
-static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
-		u32 fifo_low, u32 fifo_high)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-
-	if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
-		return;
-
-	op->fifo_low = fifo_low;
-	op->fifo_high = fifo_high;
-	op->extra_info_dirty = true;
-}
-
-static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	u32 fifo_low, fifo_high;
-	bool use_fifo_merge = false;
-
-	if (!op->enabled && !op->enabling)
-		return;
-
-	dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
-			use_fifo_merge, ovl_manual_update(ovl));
-
-	dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
-}
-
-static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
-{
-	struct omap_overlay *ovl;
-	struct mgr_priv_data *mp;
-
-	mp = get_mgr_priv(mgr);
-
-	if (!mp->enabled)
-		return;
-
-	list_for_each_entry(ovl, &mgr->overlays, list)
-		dss_ovl_setup_fifo(ovl);
-}
-
-static void dss_setup_fifos(void)
-{
-	const int num_mgrs = omap_dss_get_num_overlay_managers();
-	struct omap_overlay_manager *mgr;
-	int i;
-
-	for (i = 0; i < num_mgrs; ++i) {
-		mgr = omap_dss_get_overlay_manager(i);
-		dss_mgr_setup_fifos(mgr);
-	}
-}
-
-static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	unsigned long flags;
-	int r;
-
-	mutex_lock(&apply_lock);
-
-	if (mp->enabled)
-		goto out;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	mp->enabled = true;
-
-	r = dss_check_settings(mgr);
-	if (r) {
-		DSSERR("failed to enable manager %d: check_settings failed\n",
-				mgr->id);
-		goto err;
-	}
-
-	dss_setup_fifos();
-
-	dss_write_regs();
-	dss_set_go_bits();
-
-	if (!mgr_manual_update(mgr))
-		mp->updating = true;
-
-	if (!dss_data.irq_enabled && need_isr())
-		dss_register_vsync_isr();
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	if (!mgr_manual_update(mgr))
-		dispc_mgr_enable_sync(mgr->id);
-
-out:
-	mutex_unlock(&apply_lock);
-
-	return 0;
-
-err:
-	mp->enabled = false;
-	spin_unlock_irqrestore(&data_lock, flags);
-	mutex_unlock(&apply_lock);
-	return r;
-}
-
-static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	unsigned long flags;
-
-	mutex_lock(&apply_lock);
-
-	if (!mp->enabled)
-		goto out;
-
-	if (!mgr_manual_update(mgr))
-		dispc_mgr_disable_sync(mgr->id);
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	mp->updating = false;
-	mp->enabled = false;
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-out:
-	mutex_unlock(&apply_lock);
-}
-
-static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
-		struct omap_overlay_manager_info *info)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	unsigned long flags;
-	int r;
-
-	r = dss_mgr_simple_check(mgr, info);
-	if (r)
-		return r;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	mp->user_info = *info;
-	mp->user_info_dirty = true;
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	return 0;
-}
-
-static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
-		struct omap_overlay_manager_info *info)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	unsigned long flags;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	*info = mp->user_info;
-
-	spin_unlock_irqrestore(&data_lock, flags);
-}
-
-static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
-		struct omap_dss_device *output)
-{
-	int r;
-
-	mutex_lock(&apply_lock);
-
-	if (mgr->output) {
-		DSSERR("manager %s is already connected to an output\n",
-			mgr->name);
-		r = -EINVAL;
-		goto err;
-	}
-
-	if ((mgr->supported_outputs & output->id) == 0) {
-		DSSERR("output does not support manager %s\n",
-			mgr->name);
-		r = -EINVAL;
-		goto err;
-	}
-
-	output->manager = mgr;
-	mgr->output = output;
-
-	mutex_unlock(&apply_lock);
-
-	return 0;
-err:
-	mutex_unlock(&apply_lock);
-	return r;
-}
-
-static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
-{
-	int r;
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	unsigned long flags;
-
-	mutex_lock(&apply_lock);
-
-	if (!mgr->output) {
-		DSSERR("failed to unset output, output not set\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (mp->enabled) {
-		DSSERR("output can't be unset when manager is enabled\n");
-		r = -EINVAL;
-		goto err1;
-	}
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	mgr->output->manager = NULL;
-	mgr->output = NULL;
-
-	mutex_unlock(&apply_lock);
-
-	return 0;
-err1:
-	spin_unlock_irqrestore(&data_lock, flags);
-err:
-	mutex_unlock(&apply_lock);
-
-	return r;
-}
-
-static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
-		const struct omap_video_timings *timings)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	mp->timings = *timings;
-	mp->extra_info_dirty = true;
-}
-
-static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
-		const struct omap_video_timings *timings)
-{
-	unsigned long flags;
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (mp->updating) {
-		DSSERR("cannot set timings for %s: manager needs to be disabled\n",
-			mgr->name);
-		goto out;
-	}
-
-	dss_apply_mgr_timings(mgr, timings);
-out:
-	spin_unlock_irqrestore(&data_lock, flags);
-}
-
-static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
-		const struct dss_lcd_mgr_config *config)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	mp->lcd_config = *config;
-	mp->extra_info_dirty = true;
-}
-
-static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
-		const struct dss_lcd_mgr_config *config)
-{
-	unsigned long flags;
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (mp->enabled) {
-		DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
-			mgr->name);
-		goto out;
-	}
-
-	dss_apply_mgr_lcd_config(mgr, config);
-out:
-	spin_unlock_irqrestore(&data_lock, flags);
-}
-
-static int dss_ovl_set_info(struct omap_overlay *ovl,
-		struct omap_overlay_info *info)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	unsigned long flags;
-	int r;
-
-	r = dss_ovl_simple_check(ovl, info);
-	if (r)
-		return r;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	op->user_info = *info;
-	op->user_info_dirty = true;
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	return 0;
-}
-
-static void dss_ovl_get_info(struct omap_overlay *ovl,
-		struct omap_overlay_info *info)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	unsigned long flags;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	*info = op->user_info;
-
-	spin_unlock_irqrestore(&data_lock, flags);
-}
-
-static int dss_ovl_set_manager(struct omap_overlay *ovl,
-		struct omap_overlay_manager *mgr)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	unsigned long flags;
-	int r;
-
-	if (!mgr)
-		return -EINVAL;
-
-	mutex_lock(&apply_lock);
-
-	if (ovl->manager) {
-		DSSERR("overlay '%s' already has a manager '%s'\n",
-				ovl->name, ovl->manager->name);
-		r = -EINVAL;
-		goto err;
-	}
-
-	r = dispc_runtime_get();
-	if (r)
-		goto err;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (op->enabled) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		DSSERR("overlay has to be disabled to change the manager\n");
-		r = -EINVAL;
-		goto err1;
-	}
-
-	dispc_ovl_set_channel_out(ovl->id, mgr->id);
-
-	ovl->manager = mgr;
-	list_add_tail(&ovl->list, &mgr->overlays);
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	dispc_runtime_put();
-
-	mutex_unlock(&apply_lock);
-
-	return 0;
-
-err1:
-	dispc_runtime_put();
-err:
-	mutex_unlock(&apply_lock);
-	return r;
-}
-
-static int dss_ovl_unset_manager(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	unsigned long flags;
-	int r;
-
-	mutex_lock(&apply_lock);
-
-	if (!ovl->manager) {
-		DSSERR("failed to detach overlay: manager not set\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (op->enabled) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		DSSERR("overlay has to be disabled to unset the manager\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	/* wait for pending extra_info updates to ensure the ovl is disabled */
-	wait_pending_extra_info_updates();
-
-	/*
-	 * For a manual update display, there is no guarantee that the overlay
-	 * is really disabled in HW, we may need an extra update from this
-	 * manager before the configurations can go in. Return an error if the
-	 * overlay needed an update from the manager.
-	 *
-	 * TODO: Instead of returning an error, try to do a dummy manager update
-	 * here to disable the overlay in hardware. Use the *GATED fields in
-	 * the DISPC_CONFIG registers to do a dummy update.
-	 */
-	spin_lock_irqsave(&data_lock, flags);
-
-	if (ovl_manual_update(ovl) && op->extra_info_dirty) {
-		spin_unlock_irqrestore(&data_lock, flags);
-		DSSERR("need an update to change the manager\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	ovl->manager = NULL;
-	list_del(&ovl->list);
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	mutex_unlock(&apply_lock);
-
-	return 0;
-err:
-	mutex_unlock(&apply_lock);
-	return r;
-}
-
-static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	unsigned long flags;
-	bool e;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	e = op->enabled;
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	return e;
-}
-
-static int dss_ovl_enable(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	unsigned long flags;
-	int r;
-
-	mutex_lock(&apply_lock);
-
-	if (op->enabled) {
-		r = 0;
-		goto err1;
-	}
-
-	if (ovl->manager == NULL || ovl->manager->output == NULL) {
-		r = -EINVAL;
-		goto err1;
-	}
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	op->enabling = true;
-
-	r = dss_check_settings(ovl->manager);
-	if (r) {
-		DSSERR("failed to enable overlay %d: check_settings failed\n",
-				ovl->id);
-		goto err2;
-	}
-
-	dss_setup_fifos();
-
-	op->enabling = false;
-	dss_apply_ovl_enable(ovl, true);
-
-	dss_write_regs();
-	dss_set_go_bits();
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	mutex_unlock(&apply_lock);
-
-	return 0;
-err2:
-	op->enabling = false;
-	spin_unlock_irqrestore(&data_lock, flags);
-err1:
-	mutex_unlock(&apply_lock);
-	return r;
-}
-
-static int dss_ovl_disable(struct omap_overlay *ovl)
-{
-	struct ovl_priv_data *op = get_ovl_priv(ovl);
-	unsigned long flags;
-	int r;
-
-	mutex_lock(&apply_lock);
-
-	if (!op->enabled) {
-		r = 0;
-		goto err;
-	}
-
-	if (ovl->manager == NULL || ovl->manager->output == NULL) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	dss_apply_ovl_enable(ovl, false);
-	dss_write_regs();
-	dss_set_go_bits();
-
-	spin_unlock_irqrestore(&data_lock, flags);
-
-	mutex_unlock(&apply_lock);
-
-	return 0;
-
-err:
-	mutex_unlock(&apply_lock);
-	return r;
-}
-
-static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
-		void (*handler)(void *), void *data)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	if (mp->framedone_handler)
-		return -EBUSY;
-
-	mp->framedone_handler = handler;
-	mp->framedone_handler_data = data;
-
-	return 0;
-}
-
-static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
-		void (*handler)(void *), void *data)
-{
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-
-	WARN_ON(mp->framedone_handler != handler ||
-			mp->framedone_handler_data != data);
-
-	mp->framedone_handler = NULL;
-	mp->framedone_handler_data = NULL;
-}
-
-static const struct dss_mgr_ops apply_mgr_ops = {
-	.connect = dss_mgr_connect_compat,
-	.disconnect = dss_mgr_disconnect_compat,
-	.start_update = dss_mgr_start_update_compat,
-	.enable = dss_mgr_enable_compat,
-	.disable = dss_mgr_disable_compat,
-	.set_timings = dss_mgr_set_timings_compat,
-	.set_lcd_config = dss_mgr_set_lcd_config_compat,
-	.register_framedone_handler = dss_mgr_register_framedone_handler_compat,
-	.unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
-};
-
-static int compat_refcnt;
-static DEFINE_MUTEX(compat_init_lock);
-
-int omapdss_compat_init(void)
-{
-	struct platform_device *pdev = dss_get_core_pdev();
-	int i, r;
-
-	mutex_lock(&compat_init_lock);
-
-	if (compat_refcnt++ > 0)
-		goto out;
-
-	apply_init_priv();
-
-	dss_init_overlay_managers_sysfs(pdev);
-	dss_init_overlays(pdev);
-
-	for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
-		struct omap_overlay_manager *mgr;
-
-		mgr = omap_dss_get_overlay_manager(i);
-
-		mgr->set_output = &dss_mgr_set_output;
-		mgr->unset_output = &dss_mgr_unset_output;
-		mgr->apply = &omap_dss_mgr_apply;
-		mgr->set_manager_info = &dss_mgr_set_info;
-		mgr->get_manager_info = &dss_mgr_get_info;
-		mgr->wait_for_go = &dss_mgr_wait_for_go;
-		mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
-		mgr->get_device = &dss_mgr_get_device;
-	}
-
-	for (i = 0; i < omap_dss_get_num_overlays(); i++) {
-		struct omap_overlay *ovl = omap_dss_get_overlay(i);
-
-		ovl->is_enabled = &dss_ovl_is_enabled;
-		ovl->enable = &dss_ovl_enable;
-		ovl->disable = &dss_ovl_disable;
-		ovl->set_manager = &dss_ovl_set_manager;
-		ovl->unset_manager = &dss_ovl_unset_manager;
-		ovl->set_overlay_info = &dss_ovl_set_info;
-		ovl->get_overlay_info = &dss_ovl_get_info;
-		ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
-		ovl->get_device = &dss_ovl_get_device;
-	}
-
-	r = dss_install_mgr_ops(&apply_mgr_ops);
-	if (r)
-		goto err_mgr_ops;
-
-	r = display_init_sysfs(pdev);
-	if (r)
-		goto err_disp_sysfs;
-
-	dispc_runtime_get();
-
-	r = dss_dispc_initialize_irq();
-	if (r)
-		goto err_init_irq;
-
-	dispc_runtime_put();
-
-out:
-	mutex_unlock(&compat_init_lock);
-
-	return 0;
-
-err_init_irq:
-	dispc_runtime_put();
-	display_uninit_sysfs(pdev);
-
-err_disp_sysfs:
-	dss_uninstall_mgr_ops();
-
-err_mgr_ops:
-	dss_uninit_overlay_managers_sysfs(pdev);
-	dss_uninit_overlays(pdev);
-
-	compat_refcnt--;
-
-	mutex_unlock(&compat_init_lock);
-
-	return r;
-}
-EXPORT_SYMBOL(omapdss_compat_init);
-
-void omapdss_compat_uninit(void)
-{
-	struct platform_device *pdev = dss_get_core_pdev();
-
-	mutex_lock(&compat_init_lock);
-
-	if (--compat_refcnt > 0)
-		goto out;
-
-	dss_dispc_uninitialize_irq();
-
-	display_uninit_sysfs(pdev);
-
-	dss_uninstall_mgr_ops();
-
-	dss_uninit_overlay_managers_sysfs(pdev);
-	dss_uninit_overlays(pdev);
-out:
-	mutex_unlock(&compat_init_lock);
-}
-EXPORT_SYMBOL(omapdss_compat_uninit);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
deleted file mode 100644
index ffa45c894cd4..000000000000
--- a/drivers/video/omap2/dss/core.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/core.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "CORE"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-#include <linux/debugfs.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/suspend.h>
-#include <linux/slab.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-static struct {
-	struct platform_device *pdev;
-
-	const char *default_display_name;
-} core;
-
-static char *def_disp_name;
-module_param_named(def_disp, def_disp_name, charp, 0);
-MODULE_PARM_DESC(def_disp, "default display name");
-
-static bool dss_initialized;
-
-const char *omapdss_get_default_display_name(void)
-{
-	return core.default_display_name;
-}
-EXPORT_SYMBOL(omapdss_get_default_display_name);
-
-enum omapdss_version omapdss_get_version(void)
-{
-	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
-	return pdata->version;
-}
-EXPORT_SYMBOL(omapdss_get_version);
-
-bool omapdss_is_initialized(void)
-{
-	return dss_initialized;
-}
-EXPORT_SYMBOL(omapdss_is_initialized);
-
-struct platform_device *dss_get_core_pdev(void)
-{
-	return core.pdev;
-}
-
-int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
-{
-	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
-
-	if (!board_data->dsi_enable_pads)
-		return -ENOENT;
-
-	return board_data->dsi_enable_pads(dsi_id, lane_mask);
-}
-
-void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
-{
-	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
-
-	if (!board_data->dsi_disable_pads)
-		return;
-
-	return board_data->dsi_disable_pads(dsi_id, lane_mask);
-}
-
-int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
-{
-	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
-
-	if (pdata->set_min_bus_tput)
-		return pdata->set_min_bus_tput(dev, tput);
-	else
-		return 0;
-}
-
-#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
-static int dss_debug_show(struct seq_file *s, void *unused)
-{
-	void (*func)(struct seq_file *) = s->private;
-	func(s);
-	return 0;
-}
-
-static int dss_debug_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, dss_debug_show, inode->i_private);
-}
-
-static const struct file_operations dss_debug_fops = {
-	.open           = dss_debug_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release        = single_release,
-};
-
-static struct dentry *dss_debugfs_dir;
-
-static int dss_initialize_debugfs(void)
-{
-	dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
-	if (IS_ERR(dss_debugfs_dir)) {
-		int err = PTR_ERR(dss_debugfs_dir);
-		dss_debugfs_dir = NULL;
-		return err;
-	}
-
-	debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
-			&dss_debug_dump_clocks, &dss_debug_fops);
-
-	return 0;
-}
-
-static void dss_uninitialize_debugfs(void)
-{
-	if (dss_debugfs_dir)
-		debugfs_remove_recursive(dss_debugfs_dir);
-}
-
-int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
-{
-	struct dentry *d;
-
-	d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
-			write, &dss_debug_fops);
-
-	return PTR_ERR_OR_ZERO(d);
-}
-#else /* CONFIG_OMAP2_DSS_DEBUGFS */
-static inline int dss_initialize_debugfs(void)
-{
-	return 0;
-}
-static inline void dss_uninitialize_debugfs(void)
-{
-}
-int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
-{
-	return 0;
-}
-#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
-
-/* PLATFORM DEVICE */
-static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
-{
-	DSSDBG("pm notif %lu\n", v);
-
-	switch (v) {
-	case PM_SUSPEND_PREPARE:
-		DSSDBG("suspending displays\n");
-		return dss_suspend_all_devices();
-
-	case PM_POST_SUSPEND:
-		DSSDBG("resuming displays\n");
-		return dss_resume_all_devices();
-
-	default:
-		return 0;
-	}
-}
-
-static struct notifier_block omap_dss_pm_notif_block = {
-	.notifier_call = omap_dss_pm_notif,
-};
-
-static int __init omap_dss_probe(struct platform_device *pdev)
-{
-	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	int r;
-
-	core.pdev = pdev;
-
-	dss_features_init(omapdss_get_version());
-
-	r = dss_initialize_debugfs();
-	if (r)
-		goto err_debugfs;
-
-	if (def_disp_name)
-		core.default_display_name = def_disp_name;
-	else if (pdata->default_display_name)
-		core.default_display_name = pdata->default_display_name;
-	else if (pdata->default_device)
-		core.default_display_name = pdata->default_device->name;
-
-	register_pm_notifier(&omap_dss_pm_notif_block);
-
-	return 0;
-
-err_debugfs:
-
-	return r;
-}
-
-static int omap_dss_remove(struct platform_device *pdev)
-{
-	unregister_pm_notifier(&omap_dss_pm_notif_block);
-
-	dss_uninitialize_debugfs();
-
-	return 0;
-}
-
-static void omap_dss_shutdown(struct platform_device *pdev)
-{
-	DSSDBG("shutdown\n");
-	dss_disable_all_devices();
-}
-
-static struct platform_driver omap_dss_driver = {
-	.remove         = omap_dss_remove,
-	.shutdown	= omap_dss_shutdown,
-	.driver         = {
-		.name   = "omapdss",
-		.owner  = THIS_MODULE,
-	},
-};
-
-/* INIT */
-static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_init_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_DPI
-	dpi_init_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_SDI
-	sdi_init_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_RFBI
-	rfbi_init_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_VENC
-	venc_init_platform_driver,
-#endif
-#ifdef CONFIG_OMAP4_DSS_HDMI
-	hdmi4_init_platform_driver,
-#endif
-};
-
-static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_uninit_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_DPI
-	dpi_uninit_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_SDI
-	sdi_uninit_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_RFBI
-	rfbi_uninit_platform_driver,
-#endif
-#ifdef CONFIG_OMAP2_DSS_VENC
-	venc_uninit_platform_driver,
-#endif
-#ifdef CONFIG_OMAP4_DSS_HDMI
-	hdmi4_uninit_platform_driver,
-#endif
-};
-
-static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
-
-static int __init omap_dss_init(void)
-{
-	int r;
-	int i;
-
-	r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
-	if (r)
-		return r;
-
-	r = dss_init_platform_driver();
-	if (r) {
-		DSSERR("Failed to initialize DSS platform driver\n");
-		goto err_dss;
-	}
-
-	r = dispc_init_platform_driver();
-	if (r) {
-		DSSERR("Failed to initialize dispc platform driver\n");
-		goto err_dispc;
-	}
-
-	/*
-	 * It's ok if the output-driver register fails. It happens, for example,
-	 * when there is no output-device (e.g. SDI for OMAP4).
-	 */
-	for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
-		r = dss_output_drv_reg_funcs[i]();
-		if (r == 0)
-			dss_output_drv_loaded[i] = true;
-	}
-
-	dss_initialized = true;
-
-	return 0;
-
-err_dispc:
-	dss_uninit_platform_driver();
-err_dss:
-	platform_driver_unregister(&omap_dss_driver);
-
-	return r;
-}
-
-static void __exit omap_dss_exit(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) {
-		if (dss_output_drv_loaded[i])
-			dss_output_drv_unreg_funcs[i]();
-	}
-
-	dispc_uninit_platform_driver();
-	dss_uninit_platform_driver();
-
-	platform_driver_unregister(&omap_dss_driver);
-}
-
-module_init(omap_dss_init);
-module_exit(omap_dss_exit);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
-MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
-MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/omap2/dss/dispc-compat.c
deleted file mode 100644
index 83779c2b292a..000000000000
--- a/drivers/video/omap2/dss/dispc-compat.c
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "APPLY"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/jiffies.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/seq_file.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-#include "dispc-compat.h"
-
-#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
-					 DISPC_IRQ_OCP_ERR | \
-					 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
-					 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
-					 DISPC_IRQ_SYNC_LOST | \
-					 DISPC_IRQ_SYNC_LOST_DIGIT)
-
-#define DISPC_MAX_NR_ISRS		8
-
-struct omap_dispc_isr_data {
-	omap_dispc_isr_t	isr;
-	void			*arg;
-	u32			mask;
-};
-
-struct dispc_irq_stats {
-	unsigned long last_reset;
-	unsigned irq_count;
-	unsigned irqs[32];
-};
-
-static struct {
-	spinlock_t irq_lock;
-	u32 irq_error_mask;
-	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
-	u32 error_irqs;
-	struct work_struct error_work;
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spinlock_t irq_stats_lock;
-	struct dispc_irq_stats irq_stats;
-#endif
-} dispc_compat;
-
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-static void dispc_dump_irqs(struct seq_file *s)
-{
-	unsigned long flags;
-	struct dispc_irq_stats stats;
-
-	spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
-
-	stats = dispc_compat.irq_stats;
-	memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
-	dispc_compat.irq_stats.last_reset = jiffies;
-
-	spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
-
-	seq_printf(s, "period %u ms\n",
-			jiffies_to_msecs(jiffies - stats.last_reset));
-
-	seq_printf(s, "irqs %d\n", stats.irq_count);
-#define PIS(x) \
-	seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
-
-	PIS(FRAMEDONE);
-	PIS(VSYNC);
-	PIS(EVSYNC_EVEN);
-	PIS(EVSYNC_ODD);
-	PIS(ACBIAS_COUNT_STAT);
-	PIS(PROG_LINE_NUM);
-	PIS(GFX_FIFO_UNDERFLOW);
-	PIS(GFX_END_WIN);
-	PIS(PAL_GAMMA_MASK);
-	PIS(OCP_ERR);
-	PIS(VID1_FIFO_UNDERFLOW);
-	PIS(VID1_END_WIN);
-	PIS(VID2_FIFO_UNDERFLOW);
-	PIS(VID2_END_WIN);
-	if (dss_feat_get_num_ovls() > 3) {
-		PIS(VID3_FIFO_UNDERFLOW);
-		PIS(VID3_END_WIN);
-	}
-	PIS(SYNC_LOST);
-	PIS(SYNC_LOST_DIGIT);
-	PIS(WAKEUP);
-	if (dss_has_feature(FEAT_MGR_LCD2)) {
-		PIS(FRAMEDONE2);
-		PIS(VSYNC2);
-		PIS(ACBIAS_COUNT_STAT2);
-		PIS(SYNC_LOST2);
-	}
-	if (dss_has_feature(FEAT_MGR_LCD3)) {
-		PIS(FRAMEDONE3);
-		PIS(VSYNC3);
-		PIS(ACBIAS_COUNT_STAT3);
-		PIS(SYNC_LOST3);
-	}
-#undef PIS
-}
-#endif
-
-/* dispc.irq_lock has to be locked by the caller */
-static void _omap_dispc_set_irqs(void)
-{
-	u32 mask;
-	int i;
-	struct omap_dispc_isr_data *isr_data;
-
-	mask = dispc_compat.irq_error_mask;
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc_compat.registered_isr[i];
-
-		if (isr_data->isr == NULL)
-			continue;
-
-		mask |= isr_data->mask;
-	}
-
-	dispc_write_irqenable(mask);
-}
-
-int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
-{
-	int i;
-	int ret;
-	unsigned long flags;
-	struct omap_dispc_isr_data *isr_data;
-
-	if (isr == NULL)
-		return -EINVAL;
-
-	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
-
-	/* check for duplicate entry */
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc_compat.registered_isr[i];
-		if (isr_data->isr == isr && isr_data->arg == arg &&
-				isr_data->mask == mask) {
-			ret = -EINVAL;
-			goto err;
-		}
-	}
-
-	isr_data = NULL;
-	ret = -EBUSY;
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc_compat.registered_isr[i];
-
-		if (isr_data->isr != NULL)
-			continue;
-
-		isr_data->isr = isr;
-		isr_data->arg = arg;
-		isr_data->mask = mask;
-		ret = 0;
-
-		break;
-	}
-
-	if (ret)
-		goto err;
-
-	_omap_dispc_set_irqs();
-
-	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
-
-	return 0;
-err:
-	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(omap_dispc_register_isr);
-
-int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
-{
-	int i;
-	unsigned long flags;
-	int ret = -EINVAL;
-	struct omap_dispc_isr_data *isr_data;
-
-	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc_compat.registered_isr[i];
-		if (isr_data->isr != isr || isr_data->arg != arg ||
-				isr_data->mask != mask)
-			continue;
-
-		/* found the correct isr */
-
-		isr_data->isr = NULL;
-		isr_data->arg = NULL;
-		isr_data->mask = 0;
-
-		ret = 0;
-		break;
-	}
-
-	if (ret == 0)
-		_omap_dispc_set_irqs();
-
-	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(omap_dispc_unregister_isr);
-
-static void print_irq_status(u32 status)
-{
-	if ((status & dispc_compat.irq_error_mask) == 0)
-		return;
-
-#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
-
-	pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
-		status,
-		PIS(OCP_ERR),
-		PIS(GFX_FIFO_UNDERFLOW),
-		PIS(VID1_FIFO_UNDERFLOW),
-		PIS(VID2_FIFO_UNDERFLOW),
-		dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
-		PIS(SYNC_LOST),
-		PIS(SYNC_LOST_DIGIT),
-		dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
-		dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
-#undef PIS
-}
-
-/* Called from dss.c. Note that we don't touch clocks here,
- * but we presume they are on because we got an IRQ. However,
- * an irq handler may turn the clocks off, so we may not have
- * clock later in the function. */
-static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
-{
-	int i;
-	u32 irqstatus, irqenable;
-	u32 handledirqs = 0;
-	u32 unhandled_errors;
-	struct omap_dispc_isr_data *isr_data;
-	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
-
-	spin_lock(&dispc_compat.irq_lock);
-
-	irqstatus = dispc_read_irqstatus();
-	irqenable = dispc_read_irqenable();
-
-	/* IRQ is not for us */
-	if (!(irqstatus & irqenable)) {
-		spin_unlock(&dispc_compat.irq_lock);
-		return IRQ_NONE;
-	}
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spin_lock(&dispc_compat.irq_stats_lock);
-	dispc_compat.irq_stats.irq_count++;
-	dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
-	spin_unlock(&dispc_compat.irq_stats_lock);
-#endif
-
-	print_irq_status(irqstatus);
-
-	/* Ack the interrupt. Do it here before clocks are possibly turned
-	 * off */
-	dispc_clear_irqstatus(irqstatus);
-	/* flush posted write */
-	dispc_read_irqstatus();
-
-	/* make a copy and unlock, so that isrs can unregister
-	 * themselves */
-	memcpy(registered_isr, dispc_compat.registered_isr,
-			sizeof(registered_isr));
-
-	spin_unlock(&dispc_compat.irq_lock);
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &registered_isr[i];
-
-		if (!isr_data->isr)
-			continue;
-
-		if (isr_data->mask & irqstatus) {
-			isr_data->isr(isr_data->arg, irqstatus);
-			handledirqs |= isr_data->mask;
-		}
-	}
-
-	spin_lock(&dispc_compat.irq_lock);
-
-	unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
-
-	if (unhandled_errors) {
-		dispc_compat.error_irqs |= unhandled_errors;
-
-		dispc_compat.irq_error_mask &= ~unhandled_errors;
-		_omap_dispc_set_irqs();
-
-		schedule_work(&dispc_compat.error_work);
-	}
-
-	spin_unlock(&dispc_compat.irq_lock);
-
-	return IRQ_HANDLED;
-}
-
-static void dispc_error_worker(struct work_struct *work)
-{
-	int i;
-	u32 errors;
-	unsigned long flags;
-	static const unsigned fifo_underflow_bits[] = {
-		DISPC_IRQ_GFX_FIFO_UNDERFLOW,
-		DISPC_IRQ_VID1_FIFO_UNDERFLOW,
-		DISPC_IRQ_VID2_FIFO_UNDERFLOW,
-		DISPC_IRQ_VID3_FIFO_UNDERFLOW,
-	};
-
-	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
-	errors = dispc_compat.error_irqs;
-	dispc_compat.error_irqs = 0;
-	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
-
-	dispc_runtime_get();
-
-	for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-		struct omap_overlay *ovl;
-		unsigned bit;
-
-		ovl = omap_dss_get_overlay(i);
-		bit = fifo_underflow_bits[i];
-
-		if (bit & errors) {
-			DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
-					ovl->name);
-			ovl->disable(ovl);
-			msleep(50);
-		}
-	}
-
-	for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-		struct omap_overlay_manager *mgr;
-		unsigned bit;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		bit = dispc_mgr_get_sync_lost_irq(i);
-
-		if (bit & errors) {
-			int j;
-
-			DSSERR("SYNC_LOST on channel %s, restarting the output "
-					"with video overlays disabled\n",
-					mgr->name);
-
-			dss_mgr_disable(mgr);
-
-			for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
-				struct omap_overlay *ovl;
-				ovl = omap_dss_get_overlay(j);
-
-				if (ovl->id != OMAP_DSS_GFX &&
-						ovl->manager == mgr)
-					ovl->disable(ovl);
-			}
-
-			dss_mgr_enable(mgr);
-		}
-	}
-
-	if (errors & DISPC_IRQ_OCP_ERR) {
-		DSSERR("OCP_ERR\n");
-		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-			struct omap_overlay_manager *mgr;
-
-			mgr = omap_dss_get_overlay_manager(i);
-			dss_mgr_disable(mgr);
-		}
-	}
-
-	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
-	dispc_compat.irq_error_mask |= errors;
-	_omap_dispc_set_irqs();
-	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
-
-	dispc_runtime_put();
-}
-
-int dss_dispc_initialize_irq(void)
-{
-	int r;
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spin_lock_init(&dispc_compat.irq_stats_lock);
-	dispc_compat.irq_stats.last_reset = jiffies;
-	dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
-#endif
-
-	spin_lock_init(&dispc_compat.irq_lock);
-
-	memset(dispc_compat.registered_isr, 0,
-			sizeof(dispc_compat.registered_isr));
-
-	dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
-	if (dss_has_feature(FEAT_MGR_LCD2))
-		dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
-	if (dss_has_feature(FEAT_MGR_LCD3))
-		dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
-	if (dss_feat_get_num_ovls() > 3)
-		dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
-
-	/*
-	 * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
-	 * so clear it
-	 */
-	dispc_clear_irqstatus(dispc_read_irqstatus());
-
-	INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
-
-	_omap_dispc_set_irqs();
-
-	r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
-	if (r) {
-		DSSERR("dispc_request_irq failed\n");
-		return r;
-	}
-
-	return 0;
-}
-
-void dss_dispc_uninitialize_irq(void)
-{
-	dispc_free_irq(&dispc_compat);
-}
-
-static void dispc_mgr_disable_isr(void *data, u32 mask)
-{
-	struct completion *compl = data;
-	complete(compl);
-}
-
-static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
-{
-	dispc_mgr_enable(channel, true);
-}
-
-static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
-{
-	DECLARE_COMPLETION_ONSTACK(framedone_compl);
-	int r;
-	u32 irq;
-
-	if (dispc_mgr_is_enabled(channel) == false)
-		return;
-
-	/*
-	 * When we disable LCD output, we need to wait for FRAMEDONE to know
-	 * that DISPC has finished with the LCD output.
-	 */
-
-	irq = dispc_mgr_get_framedone_irq(channel);
-
-	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
-			irq);
-	if (r)
-		DSSERR("failed to register FRAMEDONE isr\n");
-
-	dispc_mgr_enable(channel, false);
-
-	/* if we couldn't register for framedone, just sleep and exit */
-	if (r) {
-		msleep(100);
-		return;
-	}
-
-	if (!wait_for_completion_timeout(&framedone_compl,
-				msecs_to_jiffies(100)))
-		DSSERR("timeout waiting for FRAME DONE\n");
-
-	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
-			irq);
-	if (r)
-		DSSERR("failed to unregister FRAMEDONE isr\n");
-}
-
-static void dispc_digit_out_enable_isr(void *data, u32 mask)
-{
-	struct completion *compl = data;
-
-	/* ignore any sync lost interrupts */
-	if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
-		complete(compl);
-}
-
-static void dispc_mgr_enable_digit_out(void)
-{
-	DECLARE_COMPLETION_ONSTACK(vsync_compl);
-	int r;
-	u32 irq_mask;
-
-	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
-		return;
-
-	/*
-	 * Digit output produces some sync lost interrupts during the first
-	 * frame when enabling. Those need to be ignored, so we register for the
-	 * sync lost irq to prevent the error handler from triggering.
-	 */
-
-	irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
-		dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
-
-	r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
-			irq_mask);
-	if (r) {
-		DSSERR("failed to register %x isr\n", irq_mask);
-		return;
-	}
-
-	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
-
-	/* wait for the first evsync */
-	if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
-		DSSERR("timeout waiting for digit out to start\n");
-
-	r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
-			irq_mask);
-	if (r)
-		DSSERR("failed to unregister %x isr\n", irq_mask);
-}
-
-static void dispc_mgr_disable_digit_out(void)
-{
-	DECLARE_COMPLETION_ONSTACK(framedone_compl);
-	int r, i;
-	u32 irq_mask;
-	int num_irqs;
-
-	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
-		return;
-
-	/*
-	 * When we disable the digit output, we need to wait for FRAMEDONE to
-	 * know that DISPC has finished with the output.
-	 */
-
-	irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
-	num_irqs = 1;
-
-	if (!irq_mask) {
-		/*
-		 * omap 2/3 don't have framedone irq for TV, so we need to use
-		 * vsyncs for this.
-		 */
-
-		irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
-		/*
-		 * We need to wait for both even and odd vsyncs. Note that this
-		 * is not totally reliable, as we could get a vsync interrupt
-		 * before we disable the output, which leads to timeout in the
-		 * wait_for_completion.
-		 */
-		num_irqs = 2;
-	}
-
-	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
-			irq_mask);
-	if (r)
-		DSSERR("failed to register %x isr\n", irq_mask);
-
-	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
-
-	/* if we couldn't register the irq, just sleep and exit */
-	if (r) {
-		msleep(100);
-		return;
-	}
-
-	for (i = 0; i < num_irqs; ++i) {
-		if (!wait_for_completion_timeout(&framedone_compl,
-					msecs_to_jiffies(100)))
-			DSSERR("timeout waiting for digit out to stop\n");
-	}
-
-	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
-			irq_mask);
-	if (r)
-		DSSERR("failed to unregister %x isr\n", irq_mask);
-}
-
-void dispc_mgr_enable_sync(enum omap_channel channel)
-{
-	if (dss_mgr_is_lcd(channel))
-		dispc_mgr_enable_lcd_out(channel);
-	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
-		dispc_mgr_enable_digit_out();
-	else
-		WARN_ON(1);
-}
-
-void dispc_mgr_disable_sync(enum omap_channel channel)
-{
-	if (dss_mgr_is_lcd(channel))
-		dispc_mgr_disable_lcd_out(channel);
-	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
-		dispc_mgr_disable_digit_out();
-	else
-		WARN_ON(1);
-}
-
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
-		unsigned long timeout)
-{
-	void dispc_irq_wait_handler(void *data, u32 mask)
-	{
-		complete((struct completion *)data);
-	}
-
-	int r;
-	DECLARE_COMPLETION_ONSTACK(completion);
-
-	r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
-			irqmask);
-
-	if (r)
-		return r;
-
-	timeout = wait_for_completion_interruptible_timeout(&completion,
-			timeout);
-
-	omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
-
-	if (timeout == 0)
-		return -ETIMEDOUT;
-
-	if (timeout == -ERESTARTSYS)
-		return -ERESTARTSYS;
-
-	return 0;
-}
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/omap2/dss/dispc-compat.h
deleted file mode 100644
index 14a69b3d4fb0..000000000000
--- a/drivers/video/omap2/dss/dispc-compat.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP2_DSS_DISPC_COMPAT_H
-#define __OMAP2_DSS_DISPC_COMPAT_H
-
-void dispc_mgr_enable_sync(enum omap_channel channel);
-void dispc_mgr_disable_sync(enum omap_channel channel);
-
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
-		unsigned long timeout);
-
-int dss_dispc_initialize_irq(void);
-void dss_dispc_uninitialize_irq(void);
-
-#endif
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
deleted file mode 100644
index 2bbdb7ff7daf..000000000000
--- a/drivers/video/omap2/dss/dispc.c
+++ /dev/null
@@ -1,3806 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dispc.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "DISPC"
-
-#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
-#include <linux/export.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/hardirq.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/sizes.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-#include "dispc.h"
-
-/* DISPC */
-#define DISPC_SZ_REGS			SZ_4K
-
-enum omap_burst_size {
-	BURST_SIZE_X2 = 0,
-	BURST_SIZE_X4 = 1,
-	BURST_SIZE_X8 = 2,
-};
-
-#define REG_GET(idx, start, end) \
-	FLD_GET(dispc_read_reg(idx), start, end)
-
-#define REG_FLD_MOD(idx, val, start, end)				\
-	dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
-
-struct dispc_features {
-	u8 sw_start;
-	u8 fp_start;
-	u8 bp_start;
-	u16 sw_max;
-	u16 vp_max;
-	u16 hp_max;
-	u8 mgr_width_start;
-	u8 mgr_height_start;
-	u16 mgr_width_max;
-	u16 mgr_height_max;
-	unsigned long max_lcd_pclk;
-	unsigned long max_tv_pclk;
-	int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
-		u16 width, u16 height, u16 out_width, u16 out_height,
-		enum omap_color_mode color_mode, bool *five_taps,
-		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
-		u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
-	unsigned long (*calc_core_clk) (unsigned long pclk,
-		u16 width, u16 height, u16 out_width, u16 out_height,
-		bool mem_to_mem);
-	u8 num_fifos;
-
-	/* swap GFX & WB fifos */
-	bool gfx_fifo_workaround:1;
-
-	/* no DISPC_IRQ_FRAMEDONETV on this SoC */
-	bool no_framedone_tv:1;
-
-	/* revert to the OMAP4 mechanism of DISPC Smart Standby operation */
-	bool mstandby_workaround:1;
-
-	bool set_max_preload:1;
-};
-
-#define DISPC_MAX_NR_FIFOS 5
-
-static struct {
-	struct platform_device *pdev;
-	void __iomem    *base;
-
-	int irq;
-
-	unsigned long core_clk_rate;
-	unsigned long tv_pclk_rate;
-
-	u32 fifo_size[DISPC_MAX_NR_FIFOS];
-	/* maps which plane is using a fifo. fifo-id -> plane-id */
-	int fifo_assignment[DISPC_MAX_NR_FIFOS];
-
-	bool		ctx_valid;
-	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
-
-	const struct dispc_features *feat;
-} dispc;
-
-enum omap_color_component {
-	/* used for all color formats for OMAP3 and earlier
-	 * and for RGB and Y color component on OMAP4
-	 */
-	DISPC_COLOR_COMPONENT_RGB_Y		= 1 << 0,
-	/* used for UV component for
-	 * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12
-	 * color formats on OMAP4
-	 */
-	DISPC_COLOR_COMPONENT_UV		= 1 << 1,
-};
-
-enum mgr_reg_fields {
-	DISPC_MGR_FLD_ENABLE,
-	DISPC_MGR_FLD_STNTFT,
-	DISPC_MGR_FLD_GO,
-	DISPC_MGR_FLD_TFTDATALINES,
-	DISPC_MGR_FLD_STALLMODE,
-	DISPC_MGR_FLD_TCKENABLE,
-	DISPC_MGR_FLD_TCKSELECTION,
-	DISPC_MGR_FLD_CPR,
-	DISPC_MGR_FLD_FIFOHANDCHECK,
-	/* used to maintain a count of the above fields */
-	DISPC_MGR_FLD_NUM,
-};
-
-static const struct {
-	const char *name;
-	u32 vsync_irq;
-	u32 framedone_irq;
-	u32 sync_lost_irq;
-	struct reg_field reg_desc[DISPC_MGR_FLD_NUM];
-} mgr_desc[] = {
-	[OMAP_DSS_CHANNEL_LCD] = {
-		.name		= "LCD",
-		.vsync_irq	= DISPC_IRQ_VSYNC,
-		.framedone_irq	= DISPC_IRQ_FRAMEDONE,
-		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST,
-		.reg_desc	= {
-			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL,  0,  0 },
-			[DISPC_MGR_FLD_STNTFT]		= { DISPC_CONTROL,  3,  3 },
-			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL,  5,  5 },
-			[DISPC_MGR_FLD_TFTDATALINES]	= { DISPC_CONTROL,  9,  8 },
-			[DISPC_MGR_FLD_STALLMODE]	= { DISPC_CONTROL, 11, 11 },
-			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG,  10, 10 },
-			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG,  11, 11 },
-			[DISPC_MGR_FLD_CPR]		= { DISPC_CONFIG,  15, 15 },
-			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG,  16, 16 },
-		},
-	},
-	[OMAP_DSS_CHANNEL_DIGIT] = {
-		.name		= "DIGIT",
-		.vsync_irq	= DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
-		.framedone_irq	= DISPC_IRQ_FRAMEDONETV,
-		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST_DIGIT,
-		.reg_desc	= {
-			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL,  1,  1 },
-			[DISPC_MGR_FLD_STNTFT]		= { },
-			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL,  6,  6 },
-			[DISPC_MGR_FLD_TFTDATALINES]	= { },
-			[DISPC_MGR_FLD_STALLMODE]	= { },
-			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG,  12, 12 },
-			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG,  13, 13 },
-			[DISPC_MGR_FLD_CPR]		= { },
-			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG,  16, 16 },
-		},
-	},
-	[OMAP_DSS_CHANNEL_LCD2] = {
-		.name		= "LCD2",
-		.vsync_irq	= DISPC_IRQ_VSYNC2,
-		.framedone_irq	= DISPC_IRQ_FRAMEDONE2,
-		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST2,
-		.reg_desc	= {
-			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL2,  0,  0 },
-			[DISPC_MGR_FLD_STNTFT]		= { DISPC_CONTROL2,  3,  3 },
-			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL2,  5,  5 },
-			[DISPC_MGR_FLD_TFTDATALINES]	= { DISPC_CONTROL2,  9,  8 },
-			[DISPC_MGR_FLD_STALLMODE]	= { DISPC_CONTROL2, 11, 11 },
-			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG2,  10, 10 },
-			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG2,  11, 11 },
-			[DISPC_MGR_FLD_CPR]		= { DISPC_CONFIG2,  15, 15 },
-			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG2,  16, 16 },
-		},
-	},
-	[OMAP_DSS_CHANNEL_LCD3] = {
-		.name		= "LCD3",
-		.vsync_irq	= DISPC_IRQ_VSYNC3,
-		.framedone_irq	= DISPC_IRQ_FRAMEDONE3,
-		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST3,
-		.reg_desc	= {
-			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL3,  0,  0 },
-			[DISPC_MGR_FLD_STNTFT]		= { DISPC_CONTROL3,  3,  3 },
-			[DISPC_MGR_FLD_GO]		= { DISPC_CONTROL3,  5,  5 },
-			[DISPC_MGR_FLD_TFTDATALINES]	= { DISPC_CONTROL3,  9,  8 },
-			[DISPC_MGR_FLD_STALLMODE]	= { DISPC_CONTROL3, 11, 11 },
-			[DISPC_MGR_FLD_TCKENABLE]	= { DISPC_CONFIG3,  10, 10 },
-			[DISPC_MGR_FLD_TCKSELECTION]	= { DISPC_CONFIG3,  11, 11 },
-			[DISPC_MGR_FLD_CPR]		= { DISPC_CONFIG3,  15, 15 },
-			[DISPC_MGR_FLD_FIFOHANDCHECK]	= { DISPC_CONFIG3,  16, 16 },
-		},
-	},
-};
-
-struct color_conv_coef {
-	int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
-	int full_range;
-};
-
-static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
-static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
-
-static inline void dispc_write_reg(const u16 idx, u32 val)
-{
-	__raw_writel(val, dispc.base + idx);
-}
-
-static inline u32 dispc_read_reg(const u16 idx)
-{
-	return __raw_readl(dispc.base + idx);
-}
-
-static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
-{
-	const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld];
-	return REG_GET(rfld.reg, rfld.high, rfld.low);
-}
-
-static void mgr_fld_write(enum omap_channel channel,
-					enum mgr_reg_fields regfld, int val) {
-	const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld];
-	REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
-}
-
-#define SR(reg) \
-	dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
-#define RR(reg) \
-	dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
-
-static void dispc_save_context(void)
-{
-	int i, j;
-
-	DSSDBG("dispc_save_context\n");
-
-	SR(IRQENABLE);
-	SR(CONTROL);
-	SR(CONFIG);
-	SR(LINE_NUMBER);
-	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
-			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
-		SR(GLOBAL_ALPHA);
-	if (dss_has_feature(FEAT_MGR_LCD2)) {
-		SR(CONTROL2);
-		SR(CONFIG2);
-	}
-	if (dss_has_feature(FEAT_MGR_LCD3)) {
-		SR(CONTROL3);
-		SR(CONFIG3);
-	}
-
-	for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
-		SR(DEFAULT_COLOR(i));
-		SR(TRANS_COLOR(i));
-		SR(SIZE_MGR(i));
-		if (i == OMAP_DSS_CHANNEL_DIGIT)
-			continue;
-		SR(TIMING_H(i));
-		SR(TIMING_V(i));
-		SR(POL_FREQ(i));
-		SR(DIVISORo(i));
-
-		SR(DATA_CYCLE1(i));
-		SR(DATA_CYCLE2(i));
-		SR(DATA_CYCLE3(i));
-
-		if (dss_has_feature(FEAT_CPR)) {
-			SR(CPR_COEF_R(i));
-			SR(CPR_COEF_G(i));
-			SR(CPR_COEF_B(i));
-		}
-	}
-
-	for (i = 0; i < dss_feat_get_num_ovls(); i++) {
-		SR(OVL_BA0(i));
-		SR(OVL_BA1(i));
-		SR(OVL_POSITION(i));
-		SR(OVL_SIZE(i));
-		SR(OVL_ATTRIBUTES(i));
-		SR(OVL_FIFO_THRESHOLD(i));
-		SR(OVL_ROW_INC(i));
-		SR(OVL_PIXEL_INC(i));
-		if (dss_has_feature(FEAT_PRELOAD))
-			SR(OVL_PRELOAD(i));
-		if (i == OMAP_DSS_GFX) {
-			SR(OVL_WINDOW_SKIP(i));
-			SR(OVL_TABLE_BA(i));
-			continue;
-		}
-		SR(OVL_FIR(i));
-		SR(OVL_PICTURE_SIZE(i));
-		SR(OVL_ACCU0(i));
-		SR(OVL_ACCU1(i));
-
-		for (j = 0; j < 8; j++)
-			SR(OVL_FIR_COEF_H(i, j));
-
-		for (j = 0; j < 8; j++)
-			SR(OVL_FIR_COEF_HV(i, j));
-
-		for (j = 0; j < 5; j++)
-			SR(OVL_CONV_COEF(i, j));
-
-		if (dss_has_feature(FEAT_FIR_COEF_V)) {
-			for (j = 0; j < 8; j++)
-				SR(OVL_FIR_COEF_V(i, j));
-		}
-
-		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-			SR(OVL_BA0_UV(i));
-			SR(OVL_BA1_UV(i));
-			SR(OVL_FIR2(i));
-			SR(OVL_ACCU2_0(i));
-			SR(OVL_ACCU2_1(i));
-
-			for (j = 0; j < 8; j++)
-				SR(OVL_FIR_COEF_H2(i, j));
-
-			for (j = 0; j < 8; j++)
-				SR(OVL_FIR_COEF_HV2(i, j));
-
-			for (j = 0; j < 8; j++)
-				SR(OVL_FIR_COEF_V2(i, j));
-		}
-		if (dss_has_feature(FEAT_ATTR2))
-			SR(OVL_ATTRIBUTES2(i));
-	}
-
-	if (dss_has_feature(FEAT_CORE_CLK_DIV))
-		SR(DIVISOR);
-
-	dispc.ctx_valid = true;
-
-	DSSDBG("context saved\n");
-}
-
-static void dispc_restore_context(void)
-{
-	int i, j;
-
-	DSSDBG("dispc_restore_context\n");
-
-	if (!dispc.ctx_valid)
-		return;
-
-	/*RR(IRQENABLE);*/
-	/*RR(CONTROL);*/
-	RR(CONFIG);
-	RR(LINE_NUMBER);
-	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
-			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
-		RR(GLOBAL_ALPHA);
-	if (dss_has_feature(FEAT_MGR_LCD2))
-		RR(CONFIG2);
-	if (dss_has_feature(FEAT_MGR_LCD3))
-		RR(CONFIG3);
-
-	for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
-		RR(DEFAULT_COLOR(i));
-		RR(TRANS_COLOR(i));
-		RR(SIZE_MGR(i));
-		if (i == OMAP_DSS_CHANNEL_DIGIT)
-			continue;
-		RR(TIMING_H(i));
-		RR(TIMING_V(i));
-		RR(POL_FREQ(i));
-		RR(DIVISORo(i));
-
-		RR(DATA_CYCLE1(i));
-		RR(DATA_CYCLE2(i));
-		RR(DATA_CYCLE3(i));
-
-		if (dss_has_feature(FEAT_CPR)) {
-			RR(CPR_COEF_R(i));
-			RR(CPR_COEF_G(i));
-			RR(CPR_COEF_B(i));
-		}
-	}
-
-	for (i = 0; i < dss_feat_get_num_ovls(); i++) {
-		RR(OVL_BA0(i));
-		RR(OVL_BA1(i));
-		RR(OVL_POSITION(i));
-		RR(OVL_SIZE(i));
-		RR(OVL_ATTRIBUTES(i));
-		RR(OVL_FIFO_THRESHOLD(i));
-		RR(OVL_ROW_INC(i));
-		RR(OVL_PIXEL_INC(i));
-		if (dss_has_feature(FEAT_PRELOAD))
-			RR(OVL_PRELOAD(i));
-		if (i == OMAP_DSS_GFX) {
-			RR(OVL_WINDOW_SKIP(i));
-			RR(OVL_TABLE_BA(i));
-			continue;
-		}
-		RR(OVL_FIR(i));
-		RR(OVL_PICTURE_SIZE(i));
-		RR(OVL_ACCU0(i));
-		RR(OVL_ACCU1(i));
-
-		for (j = 0; j < 8; j++)
-			RR(OVL_FIR_COEF_H(i, j));
-
-		for (j = 0; j < 8; j++)
-			RR(OVL_FIR_COEF_HV(i, j));
-
-		for (j = 0; j < 5; j++)
-			RR(OVL_CONV_COEF(i, j));
-
-		if (dss_has_feature(FEAT_FIR_COEF_V)) {
-			for (j = 0; j < 8; j++)
-				RR(OVL_FIR_COEF_V(i, j));
-		}
-
-		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-			RR(OVL_BA0_UV(i));
-			RR(OVL_BA1_UV(i));
-			RR(OVL_FIR2(i));
-			RR(OVL_ACCU2_0(i));
-			RR(OVL_ACCU2_1(i));
-
-			for (j = 0; j < 8; j++)
-				RR(OVL_FIR_COEF_H2(i, j));
-
-			for (j = 0; j < 8; j++)
-				RR(OVL_FIR_COEF_HV2(i, j));
-
-			for (j = 0; j < 8; j++)
-				RR(OVL_FIR_COEF_V2(i, j));
-		}
-		if (dss_has_feature(FEAT_ATTR2))
-			RR(OVL_ATTRIBUTES2(i));
-	}
-
-	if (dss_has_feature(FEAT_CORE_CLK_DIV))
-		RR(DIVISOR);
-
-	/* enable last, because LCD & DIGIT enable are here */
-	RR(CONTROL);
-	if (dss_has_feature(FEAT_MGR_LCD2))
-		RR(CONTROL2);
-	if (dss_has_feature(FEAT_MGR_LCD3))
-		RR(CONTROL3);
-	/* clear spurious SYNC_LOST_DIGIT interrupts */
-	dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
-
-	/*
-	 * enable last so IRQs won't trigger before
-	 * the context is fully restored
-	 */
-	RR(IRQENABLE);
-
-	DSSDBG("context restored\n");
-}
-
-#undef SR
-#undef RR
-
-int dispc_runtime_get(void)
-{
-	int r;
-
-	DSSDBG("dispc_runtime_get\n");
-
-	r = pm_runtime_get_sync(&dispc.pdev->dev);
-	WARN_ON(r < 0);
-	return r < 0 ? r : 0;
-}
-EXPORT_SYMBOL(dispc_runtime_get);
-
-void dispc_runtime_put(void)
-{
-	int r;
-
-	DSSDBG("dispc_runtime_put\n");
-
-	r = pm_runtime_put_sync(&dispc.pdev->dev);
-	WARN_ON(r < 0 && r != -ENOSYS);
-}
-EXPORT_SYMBOL(dispc_runtime_put);
-
-u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
-{
-	return mgr_desc[channel].vsync_irq;
-}
-EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
-
-u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
-{
-	if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
-		return 0;
-
-	return mgr_desc[channel].framedone_irq;
-}
-EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
-
-u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
-{
-	return mgr_desc[channel].sync_lost_irq;
-}
-EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
-
-u32 dispc_wb_get_framedone_irq(void)
-{
-	return DISPC_IRQ_FRAMEDONEWB;
-}
-
-bool dispc_mgr_go_busy(enum omap_channel channel)
-{
-	return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
-}
-EXPORT_SYMBOL(dispc_mgr_go_busy);
-
-void dispc_mgr_go(enum omap_channel channel)
-{
-	WARN_ON(dispc_mgr_is_enabled(channel) == false);
-	WARN_ON(dispc_mgr_go_busy(channel));
-
-	DSSDBG("GO %s\n", mgr_desc[channel].name);
-
-	mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
-}
-EXPORT_SYMBOL(dispc_mgr_go);
-
-bool dispc_wb_go_busy(void)
-{
-	return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
-}
-
-void dispc_wb_go(void)
-{
-	enum omap_plane plane = OMAP_DSS_WB;
-	bool enable, go;
-
-	enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
-
-	if (!enable)
-		return;
-
-	go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
-	if (go) {
-		DSSERR("GO bit not down for WB\n");
-		return;
-	}
-
-	REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
-}
-
-static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
-{
-	dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
-}
-
-static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
-{
-	dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
-}
-
-static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value)
-{
-	dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
-}
-
-static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
-{
-	BUG_ON(plane == OMAP_DSS_GFX);
-
-	dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
-}
-
-static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg,
-		u32 value)
-{
-	BUG_ON(plane == OMAP_DSS_GFX);
-
-	dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
-}
-
-static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
-{
-	BUG_ON(plane == OMAP_DSS_GFX);
-
-	dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
-}
-
-static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
-				int fir_vinc, int five_taps,
-				enum omap_color_component color_comp)
-{
-	const struct dispc_coef *h_coef, *v_coef;
-	int i;
-
-	h_coef = dispc_ovl_get_scale_coef(fir_hinc, true);
-	v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps);
-
-	for (i = 0; i < 8; i++) {
-		u32 h, hv;
-
-		h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0)
-			| FLD_VAL(h_coef[i].hc1_vc0, 15, 8)
-			| FLD_VAL(h_coef[i].hc2_vc1, 23, 16)
-			| FLD_VAL(h_coef[i].hc3_vc2, 31, 24);
-		hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0)
-			| FLD_VAL(v_coef[i].hc1_vc0, 15, 8)
-			| FLD_VAL(v_coef[i].hc2_vc1, 23, 16)
-			| FLD_VAL(v_coef[i].hc3_vc2, 31, 24);
-
-		if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
-			dispc_ovl_write_firh_reg(plane, i, h);
-			dispc_ovl_write_firhv_reg(plane, i, hv);
-		} else {
-			dispc_ovl_write_firh2_reg(plane, i, h);
-			dispc_ovl_write_firhv2_reg(plane, i, hv);
-		}
-
-	}
-
-	if (five_taps) {
-		for (i = 0; i < 8; i++) {
-			u32 v;
-			v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0)
-				| FLD_VAL(v_coef[i].hc4_vc22, 15, 8);
-			if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
-				dispc_ovl_write_firv_reg(plane, i, v);
-			else
-				dispc_ovl_write_firv2_reg(plane, i, v);
-		}
-	}
-}
-
-
-static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
-		const struct color_conv_coef *ct)
-{
-#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
-
-	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
-	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy,  ct->rcb));
-	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
-	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
-	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
-
-#undef CVAL
-}
-
-static void dispc_setup_color_conv_coef(void)
-{
-	int i;
-	int num_ovl = dss_feat_get_num_ovls();
-	int num_wb = dss_feat_get_num_wbs();
-	const struct color_conv_coef ctbl_bt601_5_ovl = {
-		298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
-	};
-	const struct color_conv_coef ctbl_bt601_5_wb = {
-		66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
-	};
-
-	for (i = 1; i < num_ovl; i++)
-		dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
-
-	for (; i < num_wb; i++)
-		dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
-}
-
-static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
-{
-	dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
-}
-
-static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr)
-{
-	dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
-}
-
-static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr)
-{
-	dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
-}
-
-static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
-{
-	dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
-}
-
-static void dispc_ovl_set_pos(enum omap_plane plane,
-		enum omap_overlay_caps caps, int x, int y)
-{
-	u32 val;
-
-	if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
-		return;
-
-	val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
-
-	dispc_write_reg(DISPC_OVL_POSITION(plane), val);
-}
-
-static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
-		int height)
-{
-	u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-
-	if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
-		dispc_write_reg(DISPC_OVL_SIZE(plane), val);
-	else
-		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
-}
-
-static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
-		int height)
-{
-	u32 val;
-
-	BUG_ON(plane == OMAP_DSS_GFX);
-
-	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-
-	if (plane == OMAP_DSS_WB)
-		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
-	else
-		dispc_write_reg(DISPC_OVL_SIZE(plane), val);
-}
-
-static void dispc_ovl_set_zorder(enum omap_plane plane,
-		enum omap_overlay_caps caps, u8 zorder)
-{
-	if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
-		return;
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
-}
-
-static void dispc_ovl_enable_zorder_planes(void)
-{
-	int i;
-
-	if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
-		return;
-
-	for (i = 0; i < dss_feat_get_num_ovls(); i++)
-		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
-}
-
-static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
-		enum omap_overlay_caps caps, bool enable)
-{
-	if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
-		return;
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
-}
-
-static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
-		enum omap_overlay_caps caps, u8 global_alpha)
-{
-	static const unsigned shifts[] = { 0, 8, 16, 24, };
-	int shift;
-
-	if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
-		return;
-
-	shift = shifts[plane];
-	REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
-}
-
-static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc)
-{
-	dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
-}
-
-static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc)
-{
-	dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
-}
-
-static void dispc_ovl_set_color_mode(enum omap_plane plane,
-		enum omap_color_mode color_mode)
-{
-	u32 m = 0;
-	if (plane != OMAP_DSS_GFX) {
-		switch (color_mode) {
-		case OMAP_DSS_COLOR_NV12:
-			m = 0x0; break;
-		case OMAP_DSS_COLOR_RGBX16:
-			m = 0x1; break;
-		case OMAP_DSS_COLOR_RGBA16:
-			m = 0x2; break;
-		case OMAP_DSS_COLOR_RGB12U:
-			m = 0x4; break;
-		case OMAP_DSS_COLOR_ARGB16:
-			m = 0x5; break;
-		case OMAP_DSS_COLOR_RGB16:
-			m = 0x6; break;
-		case OMAP_DSS_COLOR_ARGB16_1555:
-			m = 0x7; break;
-		case OMAP_DSS_COLOR_RGB24U:
-			m = 0x8; break;
-		case OMAP_DSS_COLOR_RGB24P:
-			m = 0x9; break;
-		case OMAP_DSS_COLOR_YUV2:
-			m = 0xa; break;
-		case OMAP_DSS_COLOR_UYVY:
-			m = 0xb; break;
-		case OMAP_DSS_COLOR_ARGB32:
-			m = 0xc; break;
-		case OMAP_DSS_COLOR_RGBA32:
-			m = 0xd; break;
-		case OMAP_DSS_COLOR_RGBX32:
-			m = 0xe; break;
-		case OMAP_DSS_COLOR_XRGB16_1555:
-			m = 0xf; break;
-		default:
-			BUG(); return;
-		}
-	} else {
-		switch (color_mode) {
-		case OMAP_DSS_COLOR_CLUT1:
-			m = 0x0; break;
-		case OMAP_DSS_COLOR_CLUT2:
-			m = 0x1; break;
-		case OMAP_DSS_COLOR_CLUT4:
-			m = 0x2; break;
-		case OMAP_DSS_COLOR_CLUT8:
-			m = 0x3; break;
-		case OMAP_DSS_COLOR_RGB12U:
-			m = 0x4; break;
-		case OMAP_DSS_COLOR_ARGB16:
-			m = 0x5; break;
-		case OMAP_DSS_COLOR_RGB16:
-			m = 0x6; break;
-		case OMAP_DSS_COLOR_ARGB16_1555:
-			m = 0x7; break;
-		case OMAP_DSS_COLOR_RGB24U:
-			m = 0x8; break;
-		case OMAP_DSS_COLOR_RGB24P:
-			m = 0x9; break;
-		case OMAP_DSS_COLOR_RGBX16:
-			m = 0xa; break;
-		case OMAP_DSS_COLOR_RGBA16:
-			m = 0xb; break;
-		case OMAP_DSS_COLOR_ARGB32:
-			m = 0xc; break;
-		case OMAP_DSS_COLOR_RGBA32:
-			m = 0xd; break;
-		case OMAP_DSS_COLOR_RGBX32:
-			m = 0xe; break;
-		case OMAP_DSS_COLOR_XRGB16_1555:
-			m = 0xf; break;
-		default:
-			BUG(); return;
-		}
-	}
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
-}
-
-static void dispc_ovl_configure_burst_type(enum omap_plane plane,
-		enum omap_dss_rotation_type rotation_type)
-{
-	if (dss_has_feature(FEAT_BURST_2D) == 0)
-		return;
-
-	if (rotation_type == OMAP_DSS_ROT_TILER)
-		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
-	else
-		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
-}
-
-void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
-{
-	int shift;
-	u32 val;
-	int chan = 0, chan2 = 0;
-
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		shift = 8;
-		break;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-	case OMAP_DSS_VIDEO3:
-		shift = 16;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
-	if (dss_has_feature(FEAT_MGR_LCD2)) {
-		switch (channel) {
-		case OMAP_DSS_CHANNEL_LCD:
-			chan = 0;
-			chan2 = 0;
-			break;
-		case OMAP_DSS_CHANNEL_DIGIT:
-			chan = 1;
-			chan2 = 0;
-			break;
-		case OMAP_DSS_CHANNEL_LCD2:
-			chan = 0;
-			chan2 = 1;
-			break;
-		case OMAP_DSS_CHANNEL_LCD3:
-			if (dss_has_feature(FEAT_MGR_LCD3)) {
-				chan = 0;
-				chan2 = 2;
-			} else {
-				BUG();
-				return;
-			}
-			break;
-		default:
-			BUG();
-			return;
-		}
-
-		val = FLD_MOD(val, chan, shift, shift);
-		val = FLD_MOD(val, chan2, 31, 30);
-	} else {
-		val = FLD_MOD(val, channel, shift, shift);
-	}
-	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
-}
-EXPORT_SYMBOL(dispc_ovl_set_channel_out);
-
-static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
-{
-	int shift;
-	u32 val;
-	enum omap_channel channel;
-
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		shift = 8;
-		break;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-	case OMAP_DSS_VIDEO3:
-		shift = 16;
-		break;
-	default:
-		BUG();
-		return 0;
-	}
-
-	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
-
-	if (dss_has_feature(FEAT_MGR_LCD3)) {
-		if (FLD_GET(val, 31, 30) == 0)
-			channel = FLD_GET(val, shift, shift);
-		else if (FLD_GET(val, 31, 30) == 1)
-			channel = OMAP_DSS_CHANNEL_LCD2;
-		else
-			channel = OMAP_DSS_CHANNEL_LCD3;
-	} else if (dss_has_feature(FEAT_MGR_LCD2)) {
-		if (FLD_GET(val, 31, 30) == 0)
-			channel = FLD_GET(val, shift, shift);
-		else
-			channel = OMAP_DSS_CHANNEL_LCD2;
-	} else {
-		channel = FLD_GET(val, shift, shift);
-	}
-
-	return channel;
-}
-
-void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
-{
-	enum omap_plane plane = OMAP_DSS_WB;
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
-}
-
-static void dispc_ovl_set_burst_size(enum omap_plane plane,
-		enum omap_burst_size burst_size)
-{
-	static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
-	int shift;
-
-	shift = shifts[plane];
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
-}
-
-static void dispc_configure_burst_sizes(void)
-{
-	int i;
-	const int burst_size = BURST_SIZE_X8;
-
-	/* Configure burst size always to maximum size */
-	for (i = 0; i < dss_feat_get_num_ovls(); ++i)
-		dispc_ovl_set_burst_size(i, burst_size);
-}
-
-static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
-{
-	unsigned unit = dss_feat_get_burst_size_unit();
-	/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
-	return unit * 8;
-}
-
-void dispc_enable_gamma_table(bool enable)
-{
-	/*
-	 * This is partially implemented to support only disabling of
-	 * the gamma table.
-	 */
-	if (enable) {
-		DSSWARN("Gamma table enabling for TV not yet supported");
-		return;
-	}
-
-	REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
-}
-
-static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
-{
-	if (channel == OMAP_DSS_CHANNEL_DIGIT)
-		return;
-
-	mgr_fld_write(channel, DISPC_MGR_FLD_CPR, enable);
-}
-
-static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
-		const struct omap_dss_cpr_coefs *coefs)
-{
-	u32 coef_r, coef_g, coef_b;
-
-	if (!dss_mgr_is_lcd(channel))
-		return;
-
-	coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
-		FLD_VAL(coefs->rb, 9, 0);
-	coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) |
-		FLD_VAL(coefs->gb, 9, 0);
-	coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) |
-		FLD_VAL(coefs->bb, 9, 0);
-
-	dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r);
-	dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g);
-	dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
-}
-
-static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
-{
-	u32 val;
-
-	BUG_ON(plane == OMAP_DSS_GFX);
-
-	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
-	val = FLD_MOD(val, enable, 9, 9);
-	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
-}
-
-static void dispc_ovl_enable_replication(enum omap_plane plane,
-		enum omap_overlay_caps caps, bool enable)
-{
-	static const unsigned shifts[] = { 5, 10, 10, 10 };
-	int shift;
-
-	if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
-		return;
-
-	shift = shifts[plane];
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
-}
-
-static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
-		u16 height)
-{
-	u32 val;
-
-	val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
-		FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
-
-	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
-}
-
-static void dispc_init_fifos(void)
-{
-	u32 size;
-	int fifo;
-	u8 start, end;
-	u32 unit;
-
-	unit = dss_feat_get_buffer_size_unit();
-
-	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
-
-	for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
-		size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
-		size *= unit;
-		dispc.fifo_size[fifo] = size;
-
-		/*
-		 * By default fifos are mapped directly to overlays, fifo 0 to
-		 * ovl 0, fifo 1 to ovl 1, etc.
-		 */
-		dispc.fifo_assignment[fifo] = fifo;
-	}
-
-	/*
-	 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
-	 * causes problems with certain use cases, like using the tiler in 2D
-	 * mode. The below hack swaps the fifos of GFX and WB planes, thus
-	 * giving GFX plane a larger fifo. WB but should work fine with a
-	 * smaller fifo.
-	 */
-	if (dispc.feat->gfx_fifo_workaround) {
-		u32 v;
-
-		v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
-
-		v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
-		v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
-		v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
-		v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
-
-		dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
-
-		dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
-		dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
-	}
-}
-
-static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
-{
-	int fifo;
-	u32 size = 0;
-
-	for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
-		if (dispc.fifo_assignment[fifo] == plane)
-			size += dispc.fifo_size[fifo];
-	}
-
-	return size;
-}
-
-void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
-{
-	u8 hi_start, hi_end, lo_start, lo_end;
-	u32 unit;
-
-	unit = dss_feat_get_buffer_size_unit();
-
-	WARN_ON(low % unit != 0);
-	WARN_ON(high % unit != 0);
-
-	low /= unit;
-	high /= unit;
-
-	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
-	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
-
-	DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n",
-			plane,
-			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
-				lo_start, lo_end) * unit,
-			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
-				hi_start, hi_end) * unit,
-			low * unit, high * unit);
-
-	dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
-			FLD_VAL(high, hi_start, hi_end) |
-			FLD_VAL(low, lo_start, lo_end));
-
-	/*
-	 * configure the preload to the pipeline's high threhold, if HT it's too
-	 * large for the preload field, set the threshold to the maximum value
-	 * that can be held by the preload register
-	 */
-	if (dss_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload &&
-			plane != OMAP_DSS_WB)
-		dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu));
-}
-EXPORT_SYMBOL(dispc_ovl_set_fifo_threshold);
-
-void dispc_enable_fifomerge(bool enable)
-{
-	if (!dss_has_feature(FEAT_FIFO_MERGE)) {
-		WARN_ON(enable);
-		return;
-	}
-
-	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
-	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
-}
-
-void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
-		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
-		bool manual_update)
-{
-	/*
-	 * All sizes are in bytes. Both the buffer and burst are made of
-	 * buffer_units, and the fifo thresholds must be buffer_unit aligned.
-	 */
-
-	unsigned buf_unit = dss_feat_get_buffer_size_unit();
-	unsigned ovl_fifo_size, total_fifo_size, burst_size;
-	int i;
-
-	burst_size = dispc_ovl_get_burst_size(plane);
-	ovl_fifo_size = dispc_ovl_get_fifo_size(plane);
-
-	if (use_fifomerge) {
-		total_fifo_size = 0;
-		for (i = 0; i < dss_feat_get_num_ovls(); ++i)
-			total_fifo_size += dispc_ovl_get_fifo_size(i);
-	} else {
-		total_fifo_size = ovl_fifo_size;
-	}
-
-	/*
-	 * We use the same low threshold for both fifomerge and non-fifomerge
-	 * cases, but for fifomerge we calculate the high threshold using the
-	 * combined fifo size
-	 */
-
-	if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
-		*fifo_low = ovl_fifo_size - burst_size * 2;
-		*fifo_high = total_fifo_size - burst_size;
-	} else if (plane == OMAP_DSS_WB) {
-		/*
-		 * Most optimal configuration for writeback is to push out data
-		 * to the interconnect the moment writeback pushes enough pixels
-		 * in the FIFO to form a burst
-		 */
-		*fifo_low = 0;
-		*fifo_high = burst_size;
-	} else {
-		*fifo_low = ovl_fifo_size - burst_size;
-		*fifo_high = total_fifo_size - buf_unit;
-	}
-}
-EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds);
-
-static void dispc_ovl_set_fir(enum omap_plane plane,
-				int hinc, int vinc,
-				enum omap_color_component color_comp)
-{
-	u32 val;
-
-	if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
-		u8 hinc_start, hinc_end, vinc_start, vinc_end;
-
-		dss_feat_get_reg_field(FEAT_REG_FIRHINC,
-					&hinc_start, &hinc_end);
-		dss_feat_get_reg_field(FEAT_REG_FIRVINC,
-					&vinc_start, &vinc_end);
-		val = FLD_VAL(vinc, vinc_start, vinc_end) |
-				FLD_VAL(hinc, hinc_start, hinc_end);
-
-		dispc_write_reg(DISPC_OVL_FIR(plane), val);
-	} else {
-		val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
-		dispc_write_reg(DISPC_OVL_FIR2(plane), val);
-	}
-}
-
-static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
-{
-	u32 val;
-	u8 hor_start, hor_end, vert_start, vert_end;
-
-	dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
-	dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
-
-	val = FLD_VAL(vaccu, vert_start, vert_end) |
-			FLD_VAL(haccu, hor_start, hor_end);
-
-	dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
-}
-
-static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
-{
-	u32 val;
-	u8 hor_start, hor_end, vert_start, vert_end;
-
-	dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
-	dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
-
-	val = FLD_VAL(vaccu, vert_start, vert_end) |
-			FLD_VAL(haccu, hor_start, hor_end);
-
-	dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
-}
-
-static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu,
-		int vaccu)
-{
-	u32 val;
-
-	val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
-	dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
-}
-
-static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu,
-		int vaccu)
-{
-	u32 val;
-
-	val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
-	dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
-}
-
-static void dispc_ovl_set_scale_param(enum omap_plane plane,
-		u16 orig_width, u16 orig_height,
-		u16 out_width, u16 out_height,
-		bool five_taps, u8 rotation,
-		enum omap_color_component color_comp)
-{
-	int fir_hinc, fir_vinc;
-
-	fir_hinc = 1024 * orig_width / out_width;
-	fir_vinc = 1024 * orig_height / out_height;
-
-	dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps,
-				color_comp);
-	dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
-}
-
-static void dispc_ovl_set_accu_uv(enum omap_plane plane,
-		u16 orig_width,	u16 orig_height, u16 out_width, u16 out_height,
-		bool ilace, enum omap_color_mode color_mode, u8 rotation)
-{
-	int h_accu2_0, h_accu2_1;
-	int v_accu2_0, v_accu2_1;
-	int chroma_hinc, chroma_vinc;
-	int idx;
-
-	struct accu {
-		s8 h0_m, h0_n;
-		s8 h1_m, h1_n;
-		s8 v0_m, v0_n;
-		s8 v1_m, v1_n;
-	};
-
-	const struct accu *accu_table;
-	const struct accu *accu_val;
-
-	static const struct accu accu_nv12[4] = {
-		{  0, 1,  0, 1 , -1, 2, 0, 1 },
-		{  1, 2, -3, 4 ,  0, 1, 0, 1 },
-		{ -1, 1,  0, 1 , -1, 2, 0, 1 },
-		{ -1, 2, -1, 2 , -1, 1, 0, 1 },
-	};
-
-	static const struct accu accu_nv12_ilace[4] = {
-		{  0, 1,  0, 1 , -3, 4, -1, 4 },
-		{ -1, 4, -3, 4 ,  0, 1,  0, 1 },
-		{ -1, 1,  0, 1 , -1, 4, -3, 4 },
-		{ -3, 4, -3, 4 , -1, 1,  0, 1 },
-	};
-
-	static const struct accu accu_yuv[4] = {
-		{  0, 1, 0, 1,  0, 1, 0, 1 },
-		{  0, 1, 0, 1,  0, 1, 0, 1 },
-		{ -1, 1, 0, 1,  0, 1, 0, 1 },
-		{  0, 1, 0, 1, -1, 1, 0, 1 },
-	};
-
-	switch (rotation) {
-	case OMAP_DSS_ROT_0:
-		idx = 0;
-		break;
-	case OMAP_DSS_ROT_90:
-		idx = 1;
-		break;
-	case OMAP_DSS_ROT_180:
-		idx = 2;
-		break;
-	case OMAP_DSS_ROT_270:
-		idx = 3;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	switch (color_mode) {
-	case OMAP_DSS_COLOR_NV12:
-		if (ilace)
-			accu_table = accu_nv12_ilace;
-		else
-			accu_table = accu_nv12;
-		break;
-	case OMAP_DSS_COLOR_YUV2:
-	case OMAP_DSS_COLOR_UYVY:
-		accu_table = accu_yuv;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	accu_val = &accu_table[idx];
-
-	chroma_hinc = 1024 * orig_width / out_width;
-	chroma_vinc = 1024 * orig_height / out_height;
-
-	h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024;
-	h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024;
-	v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024;
-	v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024;
-
-	dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0);
-	dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1);
-}
-
-static void dispc_ovl_set_scaling_common(enum omap_plane plane,
-		u16 orig_width, u16 orig_height,
-		u16 out_width, u16 out_height,
-		bool ilace, bool five_taps,
-		bool fieldmode, enum omap_color_mode color_mode,
-		u8 rotation)
-{
-	int accu0 = 0;
-	int accu1 = 0;
-	u32 l;
-
-	dispc_ovl_set_scale_param(plane, orig_width, orig_height,
-				out_width, out_height, five_taps,
-				rotation, DISPC_COLOR_COMPONENT_RGB_Y);
-	l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
-
-	/* RESIZEENABLE and VERTICALTAPS */
-	l &= ~((0x3 << 5) | (0x1 << 21));
-	l |= (orig_width != out_width) ? (1 << 5) : 0;
-	l |= (orig_height != out_height) ? (1 << 6) : 0;
-	l |= five_taps ? (1 << 21) : 0;
-
-	/* VRESIZECONF and HRESIZECONF */
-	if (dss_has_feature(FEAT_RESIZECONF)) {
-		l &= ~(0x3 << 7);
-		l |= (orig_width <= out_width) ? 0 : (1 << 7);
-		l |= (orig_height <= out_height) ? 0 : (1 << 8);
-	}
-
-	/* LINEBUFFERSPLIT */
-	if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
-		l &= ~(0x1 << 22);
-		l |= five_taps ? (1 << 22) : 0;
-	}
-
-	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
-
-	/*
-	 * field 0 = even field = bottom field
-	 * field 1 = odd field = top field
-	 */
-	if (ilace && !fieldmode) {
-		accu1 = 0;
-		accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff;
-		if (accu0 >= 1024/2) {
-			accu1 = 1024/2;
-			accu0 -= accu1;
-		}
-	}
-
-	dispc_ovl_set_vid_accu0(plane, 0, accu0);
-	dispc_ovl_set_vid_accu1(plane, 0, accu1);
-}
-
-static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
-		u16 orig_width, u16 orig_height,
-		u16 out_width, u16 out_height,
-		bool ilace, bool five_taps,
-		bool fieldmode, enum omap_color_mode color_mode,
-		u8 rotation)
-{
-	int scale_x = out_width != orig_width;
-	int scale_y = out_height != orig_height;
-	bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
-
-	if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
-		return;
-	if ((color_mode != OMAP_DSS_COLOR_YUV2 &&
-			color_mode != OMAP_DSS_COLOR_UYVY &&
-			color_mode != OMAP_DSS_COLOR_NV12)) {
-		/* reset chroma resampling for RGB formats  */
-		if (plane != OMAP_DSS_WB)
-			REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
-		return;
-	}
-
-	dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width,
-			out_height, ilace, color_mode, rotation);
-
-	switch (color_mode) {
-	case OMAP_DSS_COLOR_NV12:
-		if (chroma_upscale) {
-			/* UV is subsampled by 2 horizontally and vertically */
-			orig_height >>= 1;
-			orig_width >>= 1;
-		} else {
-			/* UV is downsampled by 2 horizontally and vertically */
-			orig_height <<= 1;
-			orig_width <<= 1;
-		}
-
-		break;
-	case OMAP_DSS_COLOR_YUV2:
-	case OMAP_DSS_COLOR_UYVY:
-		/* For YUV422 with 90/270 rotation, we don't upsample chroma */
-		if (rotation == OMAP_DSS_ROT_0 ||
-				rotation == OMAP_DSS_ROT_180) {
-			if (chroma_upscale)
-				/* UV is subsampled by 2 horizontally */
-				orig_width >>= 1;
-			else
-				/* UV is downsampled by 2 horizontally */
-				orig_width <<= 1;
-		}
-
-		/* must use FIR for YUV422 if rotated */
-		if (rotation != OMAP_DSS_ROT_0)
-			scale_x = scale_y = true;
-
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	if (out_width != orig_width)
-		scale_x = true;
-	if (out_height != orig_height)
-		scale_y = true;
-
-	dispc_ovl_set_scale_param(plane, orig_width, orig_height,
-			out_width, out_height, five_taps,
-				rotation, DISPC_COLOR_COMPONENT_UV);
-
-	if (plane != OMAP_DSS_WB)
-		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
-			(scale_x || scale_y) ? 1 : 0, 8, 8);
-
-	/* set H scaling */
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
-	/* set V scaling */
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
-}
-
-static void dispc_ovl_set_scaling(enum omap_plane plane,
-		u16 orig_width, u16 orig_height,
-		u16 out_width, u16 out_height,
-		bool ilace, bool five_taps,
-		bool fieldmode, enum omap_color_mode color_mode,
-		u8 rotation)
-{
-	BUG_ON(plane == OMAP_DSS_GFX);
-
-	dispc_ovl_set_scaling_common(plane,
-			orig_width, orig_height,
-			out_width, out_height,
-			ilace, five_taps,
-			fieldmode, color_mode,
-			rotation);
-
-	dispc_ovl_set_scaling_uv(plane,
-		orig_width, orig_height,
-		out_width, out_height,
-		ilace, five_taps,
-		fieldmode, color_mode,
-		rotation);
-}
-
-static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
-		enum omap_dss_rotation_type rotation_type,
-		bool mirroring, enum omap_color_mode color_mode)
-{
-	bool row_repeat = false;
-	int vidrot = 0;
-
-	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY) {
-
-		if (mirroring) {
-			switch (rotation) {
-			case OMAP_DSS_ROT_0:
-				vidrot = 2;
-				break;
-			case OMAP_DSS_ROT_90:
-				vidrot = 1;
-				break;
-			case OMAP_DSS_ROT_180:
-				vidrot = 0;
-				break;
-			case OMAP_DSS_ROT_270:
-				vidrot = 3;
-				break;
-			}
-		} else {
-			switch (rotation) {
-			case OMAP_DSS_ROT_0:
-				vidrot = 0;
-				break;
-			case OMAP_DSS_ROT_90:
-				vidrot = 1;
-				break;
-			case OMAP_DSS_ROT_180:
-				vidrot = 2;
-				break;
-			case OMAP_DSS_ROT_270:
-				vidrot = 3;
-				break;
-			}
-		}
-
-		if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
-			row_repeat = true;
-		else
-			row_repeat = false;
-	}
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
-	if (dss_has_feature(FEAT_ROWREPEATENABLE))
-		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
-			row_repeat ? 1 : 0, 18, 18);
-
-	if (color_mode == OMAP_DSS_COLOR_NV12) {
-		bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) &&
-					(rotation == OMAP_DSS_ROT_0 ||
-					rotation == OMAP_DSS_ROT_180);
-		/* DOUBLESTRIDE */
-		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22);
-	}
-
-}
-
-static int color_mode_to_bpp(enum omap_color_mode color_mode)
-{
-	switch (color_mode) {
-	case OMAP_DSS_COLOR_CLUT1:
-		return 1;
-	case OMAP_DSS_COLOR_CLUT2:
-		return 2;
-	case OMAP_DSS_COLOR_CLUT4:
-		return 4;
-	case OMAP_DSS_COLOR_CLUT8:
-	case OMAP_DSS_COLOR_NV12:
-		return 8;
-	case OMAP_DSS_COLOR_RGB12U:
-	case OMAP_DSS_COLOR_RGB16:
-	case OMAP_DSS_COLOR_ARGB16:
-	case OMAP_DSS_COLOR_YUV2:
-	case OMAP_DSS_COLOR_UYVY:
-	case OMAP_DSS_COLOR_RGBA16:
-	case OMAP_DSS_COLOR_RGBX16:
-	case OMAP_DSS_COLOR_ARGB16_1555:
-	case OMAP_DSS_COLOR_XRGB16_1555:
-		return 16;
-	case OMAP_DSS_COLOR_RGB24P:
-		return 24;
-	case OMAP_DSS_COLOR_RGB24U:
-	case OMAP_DSS_COLOR_ARGB32:
-	case OMAP_DSS_COLOR_RGBA32:
-	case OMAP_DSS_COLOR_RGBX32:
-		return 32;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static s32 pixinc(int pixels, u8 ps)
-{
-	if (pixels == 1)
-		return 1;
-	else if (pixels > 1)
-		return 1 + (pixels - 1) * ps;
-	else if (pixels < 0)
-		return 1 - (-pixels + 1) * ps;
-	else
-		BUG();
-		return 0;
-}
-
-static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
-		u16 screen_width,
-		u16 width, u16 height,
-		enum omap_color_mode color_mode, bool fieldmode,
-		unsigned int field_offset,
-		unsigned *offset0, unsigned *offset1,
-		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
-{
-	u8 ps;
-
-	/* FIXME CLUT formats */
-	switch (color_mode) {
-	case OMAP_DSS_COLOR_CLUT1:
-	case OMAP_DSS_COLOR_CLUT2:
-	case OMAP_DSS_COLOR_CLUT4:
-	case OMAP_DSS_COLOR_CLUT8:
-		BUG();
-		return;
-	case OMAP_DSS_COLOR_YUV2:
-	case OMAP_DSS_COLOR_UYVY:
-		ps = 4;
-		break;
-	default:
-		ps = color_mode_to_bpp(color_mode) / 8;
-		break;
-	}
-
-	DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
-			width, height);
-
-	/*
-	 * field 0 = even field = bottom field
-	 * field 1 = odd field = top field
-	 */
-	switch (rotation + mirror * 4) {
-	case OMAP_DSS_ROT_0:
-	case OMAP_DSS_ROT_180:
-		/*
-		 * If the pixel format is YUV or UYVY divide the width
-		 * of the image by 2 for 0 and 180 degree rotation.
-		 */
-		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY)
-			width = width >> 1;
-	case OMAP_DSS_ROT_90:
-	case OMAP_DSS_ROT_270:
-		*offset1 = 0;
-		if (field_offset)
-			*offset0 = field_offset * screen_width * ps;
-		else
-			*offset0 = 0;
-
-		*row_inc = pixinc(1 +
-			(y_predecim * screen_width - x_predecim * width) +
-			(fieldmode ? screen_width : 0), ps);
-		*pix_inc = pixinc(x_predecim, ps);
-		break;
-
-	case OMAP_DSS_ROT_0 + 4:
-	case OMAP_DSS_ROT_180 + 4:
-		/* If the pixel format is YUV or UYVY divide the width
-		 * of the image by 2  for 0 degree and 180 degree
-		 */
-		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY)
-			width = width >> 1;
-	case OMAP_DSS_ROT_90 + 4:
-	case OMAP_DSS_ROT_270 + 4:
-		*offset1 = 0;
-		if (field_offset)
-			*offset0 = field_offset * screen_width * ps;
-		else
-			*offset0 = 0;
-		*row_inc = pixinc(1 -
-			(y_predecim * screen_width + x_predecim * width) -
-			(fieldmode ? screen_width : 0), ps);
-		*pix_inc = pixinc(x_predecim, ps);
-		break;
-
-	default:
-		BUG();
-		return;
-	}
-}
-
-static void calc_dma_rotation_offset(u8 rotation, bool mirror,
-		u16 screen_width,
-		u16 width, u16 height,
-		enum omap_color_mode color_mode, bool fieldmode,
-		unsigned int field_offset,
-		unsigned *offset0, unsigned *offset1,
-		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
-{
-	u8 ps;
-	u16 fbw, fbh;
-
-	/* FIXME CLUT formats */
-	switch (color_mode) {
-	case OMAP_DSS_COLOR_CLUT1:
-	case OMAP_DSS_COLOR_CLUT2:
-	case OMAP_DSS_COLOR_CLUT4:
-	case OMAP_DSS_COLOR_CLUT8:
-		BUG();
-		return;
-	default:
-		ps = color_mode_to_bpp(color_mode) / 8;
-		break;
-	}
-
-	DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
-			width, height);
-
-	/* width & height are overlay sizes, convert to fb sizes */
-
-	if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) {
-		fbw = width;
-		fbh = height;
-	} else {
-		fbw = height;
-		fbh = width;
-	}
-
-	/*
-	 * field 0 = even field = bottom field
-	 * field 1 = odd field = top field
-	 */
-	switch (rotation + mirror * 4) {
-	case OMAP_DSS_ROT_0:
-		*offset1 = 0;
-		if (field_offset)
-			*offset0 = *offset1 + field_offset * screen_width * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(1 +
-			(y_predecim * screen_width - fbw * x_predecim) +
-			(fieldmode ? screen_width : 0),	ps);
-		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY)
-			*pix_inc = pixinc(x_predecim, 2 * ps);
-		else
-			*pix_inc = pixinc(x_predecim, ps);
-		break;
-	case OMAP_DSS_ROT_90:
-		*offset1 = screen_width * (fbh - 1) * ps;
-		if (field_offset)
-			*offset0 = *offset1 + field_offset * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(screen_width * (fbh * x_predecim - 1) +
-				y_predecim + (fieldmode ? 1 : 0), ps);
-		*pix_inc = pixinc(-x_predecim * screen_width, ps);
-		break;
-	case OMAP_DSS_ROT_180:
-		*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
-		if (field_offset)
-			*offset0 = *offset1 - field_offset * screen_width * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(-1 -
-			(y_predecim * screen_width - fbw * x_predecim) -
-			(fieldmode ? screen_width : 0),	ps);
-		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY)
-			*pix_inc = pixinc(-x_predecim, 2 * ps);
-		else
-			*pix_inc = pixinc(-x_predecim, ps);
-		break;
-	case OMAP_DSS_ROT_270:
-		*offset1 = (fbw - 1) * ps;
-		if (field_offset)
-			*offset0 = *offset1 - field_offset * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) -
-				y_predecim - (fieldmode ? 1 : 0), ps);
-		*pix_inc = pixinc(x_predecim * screen_width, ps);
-		break;
-
-	/* mirroring */
-	case OMAP_DSS_ROT_0 + 4:
-		*offset1 = (fbw - 1) * ps;
-		if (field_offset)
-			*offset0 = *offset1 + field_offset * screen_width * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(y_predecim * screen_width * 2 - 1 +
-				(fieldmode ? screen_width : 0),
-				ps);
-		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY)
-			*pix_inc = pixinc(-x_predecim, 2 * ps);
-		else
-			*pix_inc = pixinc(-x_predecim, ps);
-		break;
-
-	case OMAP_DSS_ROT_90 + 4:
-		*offset1 = 0;
-		if (field_offset)
-			*offset0 = *offset1 + field_offset * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) +
-				y_predecim + (fieldmode ? 1 : 0),
-				ps);
-		*pix_inc = pixinc(x_predecim * screen_width, ps);
-		break;
-
-	case OMAP_DSS_ROT_180 + 4:
-		*offset1 = screen_width * (fbh - 1) * ps;
-		if (field_offset)
-			*offset0 = *offset1 - field_offset * screen_width * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(1 - y_predecim * screen_width * 2 -
-				(fieldmode ? screen_width : 0),
-				ps);
-		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY)
-			*pix_inc = pixinc(x_predecim, 2 * ps);
-		else
-			*pix_inc = pixinc(x_predecim, ps);
-		break;
-
-	case OMAP_DSS_ROT_270 + 4:
-		*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
-		if (field_offset)
-			*offset0 = *offset1 - field_offset * ps;
-		else
-			*offset0 = *offset1;
-		*row_inc = pixinc(screen_width * (fbh * x_predecim - 1) -
-				y_predecim - (fieldmode ? 1 : 0),
-				ps);
-		*pix_inc = pixinc(-x_predecim * screen_width, ps);
-		break;
-
-	default:
-		BUG();
-		return;
-	}
-}
-
-static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
-		enum omap_color_mode color_mode, bool fieldmode,
-		unsigned int field_offset, unsigned *offset0, unsigned *offset1,
-		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
-{
-	u8 ps;
-
-	switch (color_mode) {
-	case OMAP_DSS_COLOR_CLUT1:
-	case OMAP_DSS_COLOR_CLUT2:
-	case OMAP_DSS_COLOR_CLUT4:
-	case OMAP_DSS_COLOR_CLUT8:
-		BUG();
-		return;
-	default:
-		ps = color_mode_to_bpp(color_mode) / 8;
-		break;
-	}
-
-	DSSDBG("scrw %d, width %d\n", screen_width, width);
-
-	/*
-	 * field 0 = even field = bottom field
-	 * field 1 = odd field = top field
-	 */
-	*offset1 = 0;
-	if (field_offset)
-		*offset0 = *offset1 + field_offset * screen_width * ps;
-	else
-		*offset0 = *offset1;
-	*row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) +
-			(fieldmode ? screen_width : 0), ps);
-	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-		color_mode == OMAP_DSS_COLOR_UYVY)
-		*pix_inc = pixinc(x_predecim, 2 * ps);
-	else
-		*pix_inc = pixinc(x_predecim, ps);
-}
-
-/*
- * This function is used to avoid synclosts in OMAP3, because of some
- * undocumented horizontal position and timing related limitations.
- */
-static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *t, u16 pos_x,
-		u16 width, u16 height, u16 out_width, u16 out_height,
-		bool five_taps)
-{
-	const int ds = DIV_ROUND_UP(height, out_height);
-	unsigned long nonactive;
-	static const u8 limits[3] = { 8, 10, 20 };
-	u64 val, blank;
-	int i;
-
-	nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
-
-	i = 0;
-	if (out_height < height)
-		i++;
-	if (out_width < width)
-		i++;
-	blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
-	DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
-	if (blank <= limits[i])
-		return -EINVAL;
-
-	/* FIXME add checks for 3-tap filter once the limitations are known */
-	if (!five_taps)
-		return 0;
-
-	/*
-	 * Pixel data should be prepared before visible display point starts.
-	 * So, atleast DS-2 lines must have already been fetched by DISPC
-	 * during nonactive - pos_x period.
-	 */
-	val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
-	DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
-		val, max(0, ds - 2) * width);
-	if (val < max(0, ds - 2) * width)
-		return -EINVAL;
-
-	/*
-	 * All lines need to be refilled during the nonactive period of which
-	 * only one line can be loaded during the active period. So, atleast
-	 * DS - 1 lines should be loaded during nonactive period.
-	 */
-	val =  div_u64((u64)nonactive * lclk, pclk);
-	DSSDBG("nonactive * pcd  = %llu, max(0, DS - 1) * width = %d\n",
-		val, max(0, ds - 1) * width);
-	if (val < max(0, ds - 1) * width)
-		return -EINVAL;
-
-	return 0;
-}
-
-static unsigned long calc_core_clk_five_taps(unsigned long pclk,
-		const struct omap_video_timings *mgr_timings, u16 width,
-		u16 height, u16 out_width, u16 out_height,
-		enum omap_color_mode color_mode)
-{
-	u32 core_clk = 0;
-	u64 tmp;
-
-	if (height <= out_height && width <= out_width)
-		return (unsigned long) pclk;
-
-	if (height > out_height) {
-		unsigned int ppl = mgr_timings->x_res;
-
-		tmp = pclk * height * out_width;
-		do_div(tmp, 2 * out_height * ppl);
-		core_clk = tmp;
-
-		if (height > 2 * out_height) {
-			if (ppl == out_width)
-				return 0;
-
-			tmp = pclk * (height - 2 * out_height) * out_width;
-			do_div(tmp, 2 * out_height * (ppl - out_width));
-			core_clk = max_t(u32, core_clk, tmp);
-		}
-	}
-
-	if (width > out_width) {
-		tmp = pclk * width;
-		do_div(tmp, out_width);
-		core_clk = max_t(u32, core_clk, tmp);
-
-		if (color_mode == OMAP_DSS_COLOR_RGB24U)
-			core_clk <<= 1;
-	}
-
-	return core_clk;
-}
-
-static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width,
-		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
-{
-	if (height > out_height && width > out_width)
-		return pclk * 4;
-	else
-		return pclk * 2;
-}
-
-static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
-		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
-{
-	unsigned int hf, vf;
-
-	/*
-	 * FIXME how to determine the 'A' factor
-	 * for the no downscaling case ?
-	 */
-
-	if (width > 3 * out_width)
-		hf = 4;
-	else if (width > 2 * out_width)
-		hf = 3;
-	else if (width > out_width)
-		hf = 2;
-	else
-		hf = 1;
-	if (height > out_height)
-		vf = 2;
-	else
-		vf = 1;
-
-	return pclk * vf * hf;
-}
-
-static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
-		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
-{
-	/*
-	 * If the overlay/writeback is in mem to mem mode, there are no
-	 * downscaling limitations with respect to pixel clock, return 1 as
-	 * required core clock to represent that we have sufficient enough
-	 * core clock to do maximum downscaling
-	 */
-	if (mem_to_mem)
-		return 1;
-
-	if (width > out_width)
-		return DIV_ROUND_UP(pclk, out_width) * width;
-	else
-		return pclk;
-}
-
-static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
-		u16 width, u16 height, u16 out_width, u16 out_height,
-		enum omap_color_mode color_mode, bool *five_taps,
-		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
-		u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
-{
-	int error;
-	u16 in_width, in_height;
-	int min_factor = min(*decim_x, *decim_y);
-	const int maxsinglelinewidth =
-			dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
-
-	*five_taps = false;
-
-	do {
-		in_height = height / *decim_y;
-		in_width = width / *decim_x;
-		*core_clk = dispc.feat->calc_core_clk(pclk, in_width,
-				in_height, out_width, out_height, mem_to_mem);
-		error = (in_width > maxsinglelinewidth || !*core_clk ||
-			*core_clk > dispc_core_clk_rate());
-		if (error) {
-			if (*decim_x == *decim_y) {
-				*decim_x = min_factor;
-				++*decim_y;
-			} else {
-				swap(*decim_x, *decim_y);
-				if (*decim_x < *decim_y)
-					++*decim_x;
-			}
-		}
-	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
-
-	if (in_width > maxsinglelinewidth) {
-		DSSERR("Cannot scale max input width exceeded");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
-		u16 width, u16 height, u16 out_width, u16 out_height,
-		enum omap_color_mode color_mode, bool *five_taps,
-		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
-		u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
-{
-	int error;
-	u16 in_width, in_height;
-	int min_factor = min(*decim_x, *decim_y);
-	const int maxsinglelinewidth =
-			dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
-
-	do {
-		in_height = height / *decim_y;
-		in_width = width / *decim_x;
-		*five_taps = in_height > out_height;
-
-		if (in_width > maxsinglelinewidth)
-			if (in_height > out_height &&
-						in_height < out_height * 2)
-				*five_taps = false;
-again:
-		if (*five_taps)
-			*core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
-						in_width, in_height, out_width,
-						out_height, color_mode);
-		else
-			*core_clk = dispc.feat->calc_core_clk(pclk, in_width,
-					in_height, out_width, out_height,
-					mem_to_mem);
-
-		error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
-				pos_x, in_width, in_height, out_width,
-				out_height, *five_taps);
-		if (error && *five_taps) {
-			*five_taps = false;
-			goto again;
-		}
-
-		error = (error || in_width > maxsinglelinewidth * 2 ||
-			(in_width > maxsinglelinewidth && *five_taps) ||
-			!*core_clk || *core_clk > dispc_core_clk_rate());
-		if (error) {
-			if (*decim_x == *decim_y) {
-				*decim_x = min_factor;
-				++*decim_y;
-			} else {
-				swap(*decim_x, *decim_y);
-				if (*decim_x < *decim_y)
-					++*decim_x;
-			}
-		}
-	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
-
-	if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
-				height, out_width, out_height, *five_taps)) {
-			DSSERR("horizontal timing too tight\n");
-			return -EINVAL;
-	}
-
-	if (in_width > (maxsinglelinewidth * 2)) {
-		DSSERR("Cannot setup scaling");
-		DSSERR("width exceeds maximum width possible");
-		return -EINVAL;
-	}
-
-	if (in_width > maxsinglelinewidth && *five_taps) {
-		DSSERR("cannot setup scaling with five taps");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
-		u16 width, u16 height, u16 out_width, u16 out_height,
-		enum omap_color_mode color_mode, bool *five_taps,
-		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
-		u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
-{
-	u16 in_width, in_width_max;
-	int decim_x_min = *decim_x;
-	u16 in_height = height / *decim_y;
-	const int maxsinglelinewidth =
-				dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
-	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
-
-	if (mem_to_mem) {
-		in_width_max = out_width * maxdownscale;
-	} else {
-		in_width_max = dispc_core_clk_rate() /
-					DIV_ROUND_UP(pclk, out_width);
-	}
-
-	*decim_x = DIV_ROUND_UP(width, in_width_max);
-
-	*decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
-	if (*decim_x > *x_predecim)
-		return -EINVAL;
-
-	do {
-		in_width = width / *decim_x;
-	} while (*decim_x <= *x_predecim &&
-			in_width > maxsinglelinewidth && ++*decim_x);
-
-	if (in_width > maxsinglelinewidth) {
-		DSSERR("Cannot scale width exceeds max line width");
-		return -EINVAL;
-	}
-
-	*core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
-				out_width, out_height, mem_to_mem);
-	return 0;
-}
-
-static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
-		enum omap_overlay_caps caps,
-		const struct omap_video_timings *mgr_timings,
-		u16 width, u16 height, u16 out_width, u16 out_height,
-		enum omap_color_mode color_mode, bool *five_taps,
-		int *x_predecim, int *y_predecim, u16 pos_x,
-		enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
-{
-	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
-	const int max_decim_limit = 16;
-	unsigned long core_clk = 0;
-	int decim_x, decim_y, ret;
-
-	if (width == out_width && height == out_height)
-		return 0;
-
-	if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
-		return -EINVAL;
-
-	if (mem_to_mem) {
-		*x_predecim = *y_predecim = 1;
-	} else {
-		*x_predecim = max_decim_limit;
-		*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
-				dss_has_feature(FEAT_BURST_2D)) ?
-				2 : max_decim_limit;
-	}
-
-	if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
-	    color_mode == OMAP_DSS_COLOR_CLUT2 ||
-	    color_mode == OMAP_DSS_COLOR_CLUT4 ||
-	    color_mode == OMAP_DSS_COLOR_CLUT8) {
-		*x_predecim = 1;
-		*y_predecim = 1;
-		*five_taps = false;
-		return 0;
-	}
-
-	decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
-	decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
-
-	if (decim_x > *x_predecim || out_width > width * 8)
-		return -EINVAL;
-
-	if (decim_y > *y_predecim || out_height > height * 8)
-		return -EINVAL;
-
-	ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
-		out_width, out_height, color_mode, five_taps,
-		x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
-		mem_to_mem);
-	if (ret)
-		return ret;
-
-	DSSDBG("required core clk rate = %lu Hz\n", core_clk);
-	DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
-
-	if (!core_clk || core_clk > dispc_core_clk_rate()) {
-		DSSERR("failed to set up scaling, "
-			"required core clk rate = %lu Hz, "
-			"current core clk rate = %lu Hz\n",
-			core_clk, dispc_core_clk_rate());
-		return -EINVAL;
-	}
-
-	*x_predecim = decim_x;
-	*y_predecim = decim_y;
-	return 0;
-}
-
-int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
-		const struct omap_overlay_info *oi,
-		const struct omap_video_timings *timings,
-		int *x_predecim, int *y_predecim)
-{
-	enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
-	bool five_taps = true;
-	bool fieldmode = false;
-	u16 in_height = oi->height;
-	u16 in_width = oi->width;
-	bool ilace = timings->interlace;
-	u16 out_width, out_height;
-	int pos_x = oi->pos_x;
-	unsigned long pclk = dispc_mgr_pclk_rate(channel);
-	unsigned long lclk = dispc_mgr_lclk_rate(channel);
-
-	out_width = oi->out_width == 0 ? oi->width : oi->out_width;
-	out_height = oi->out_height == 0 ? oi->height : oi->out_height;
-
-	if (ilace && oi->height == out_height)
-		fieldmode = true;
-
-	if (ilace) {
-		if (fieldmode)
-			in_height /= 2;
-		out_height /= 2;
-
-		DSSDBG("adjusting for ilace: height %d, out_height %d\n",
-				in_height, out_height);
-	}
-
-	if (!dss_feat_color_mode_supported(plane, oi->color_mode))
-		return -EINVAL;
-
-	return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
-			in_height, out_width, out_height, oi->color_mode,
-			&five_taps, x_predecim, y_predecim, pos_x,
-			oi->rotation_type, false);
-}
-EXPORT_SYMBOL(dispc_ovl_check);
-
-static int dispc_ovl_setup_common(enum omap_plane plane,
-		enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
-		u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
-		u16 out_width, u16 out_height, enum omap_color_mode color_mode,
-		u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
-		u8 global_alpha, enum omap_dss_rotation_type rotation_type,
-		bool replication, const struct omap_video_timings *mgr_timings,
-		bool mem_to_mem)
-{
-	bool five_taps = true;
-	bool fieldmode = false;
-	int r, cconv = 0;
-	unsigned offset0, offset1;
-	s32 row_inc;
-	s32 pix_inc;
-	u16 frame_width, frame_height;
-	unsigned int field_offset = 0;
-	u16 in_height = height;
-	u16 in_width = width;
-	int x_predecim = 1, y_predecim = 1;
-	bool ilace = mgr_timings->interlace;
-	unsigned long pclk = dispc_plane_pclk_rate(plane);
-	unsigned long lclk = dispc_plane_lclk_rate(plane);
-
-	if (paddr == 0)
-		return -EINVAL;
-
-	out_width = out_width == 0 ? width : out_width;
-	out_height = out_height == 0 ? height : out_height;
-
-	if (ilace && height == out_height)
-		fieldmode = true;
-
-	if (ilace) {
-		if (fieldmode)
-			in_height /= 2;
-		pos_y /= 2;
-		out_height /= 2;
-
-		DSSDBG("adjusting for ilace: height %d, pos_y %d, "
-			"out_height %d\n", in_height, pos_y,
-			out_height);
-	}
-
-	if (!dss_feat_color_mode_supported(plane, color_mode))
-		return -EINVAL;
-
-	r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
-			in_height, out_width, out_height, color_mode,
-			&five_taps, &x_predecim, &y_predecim, pos_x,
-			rotation_type, mem_to_mem);
-	if (r)
-		return r;
-
-	in_width = in_width / x_predecim;
-	in_height = in_height / y_predecim;
-
-	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-			color_mode == OMAP_DSS_COLOR_UYVY ||
-			color_mode == OMAP_DSS_COLOR_NV12)
-		cconv = 1;
-
-	if (ilace && !fieldmode) {
-		/*
-		 * when downscaling the bottom field may have to start several
-		 * source lines below the top field. Unfortunately ACCUI
-		 * registers will only hold the fractional part of the offset
-		 * so the integer part must be added to the base address of the
-		 * bottom field.
-		 */
-		if (!in_height || in_height == out_height)
-			field_offset = 0;
-		else
-			field_offset = in_height / out_height / 2;
-	}
-
-	/* Fields are independent but interleaved in memory. */
-	if (fieldmode)
-		field_offset = 1;
-
-	offset0 = 0;
-	offset1 = 0;
-	row_inc = 0;
-	pix_inc = 0;
-
-	if (plane == OMAP_DSS_WB) {
-		frame_width = out_width;
-		frame_height = out_height;
-	} else {
-		frame_width = in_width;
-		frame_height = height;
-	}
-
-	if (rotation_type == OMAP_DSS_ROT_TILER)
-		calc_tiler_rotation_offset(screen_width, frame_width,
-				color_mode, fieldmode, field_offset,
-				&offset0, &offset1, &row_inc, &pix_inc,
-				x_predecim, y_predecim);
-	else if (rotation_type == OMAP_DSS_ROT_DMA)
-		calc_dma_rotation_offset(rotation, mirror, screen_width,
-				frame_width, frame_height,
-				color_mode, fieldmode, field_offset,
-				&offset0, &offset1, &row_inc, &pix_inc,
-				x_predecim, y_predecim);
-	else
-		calc_vrfb_rotation_offset(rotation, mirror,
-				screen_width, frame_width, frame_height,
-				color_mode, fieldmode, field_offset,
-				&offset0, &offset1, &row_inc, &pix_inc,
-				x_predecim, y_predecim);
-
-	DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
-			offset0, offset1, row_inc, pix_inc);
-
-	dispc_ovl_set_color_mode(plane, color_mode);
-
-	dispc_ovl_configure_burst_type(plane, rotation_type);
-
-	dispc_ovl_set_ba0(plane, paddr + offset0);
-	dispc_ovl_set_ba1(plane, paddr + offset1);
-
-	if (OMAP_DSS_COLOR_NV12 == color_mode) {
-		dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
-		dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
-	}
-
-	dispc_ovl_set_row_inc(plane, row_inc);
-	dispc_ovl_set_pix_inc(plane, pix_inc);
-
-	DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
-			in_height, out_width, out_height);
-
-	dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
-
-	dispc_ovl_set_input_size(plane, in_width, in_height);
-
-	if (caps & OMAP_DSS_OVL_CAP_SCALE) {
-		dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
-				   out_height, ilace, five_taps, fieldmode,
-				   color_mode, rotation);
-		dispc_ovl_set_output_size(plane, out_width, out_height);
-		dispc_ovl_set_vid_color_conv(plane, cconv);
-	}
-
-	dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror,
-			color_mode);
-
-	dispc_ovl_set_zorder(plane, caps, zorder);
-	dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
-	dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
-
-	dispc_ovl_enable_replication(plane, caps, replication);
-
-	return 0;
-}
-
-int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
-		bool replication, const struct omap_video_timings *mgr_timings,
-		bool mem_to_mem)
-{
-	int r;
-	enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
-	enum omap_channel channel;
-
-	channel = dispc_ovl_get_channel_out(plane);
-
-	DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
-		"%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
-		plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
-		oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
-		oi->color_mode, oi->rotation, oi->mirror, channel, replication);
-
-	r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
-		oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
-		oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
-		oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
-		oi->rotation_type, replication, mgr_timings, mem_to_mem);
-
-	return r;
-}
-EXPORT_SYMBOL(dispc_ovl_setup);
-
-int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
-		bool mem_to_mem, const struct omap_video_timings *mgr_timings)
-{
-	int r;
-	u32 l;
-	enum omap_plane plane = OMAP_DSS_WB;
-	const int pos_x = 0, pos_y = 0;
-	const u8 zorder = 0, global_alpha = 0;
-	const bool replication = false;
-	bool truncation;
-	int in_width = mgr_timings->x_res;
-	int in_height = mgr_timings->y_res;
-	enum omap_overlay_caps caps =
-		OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
-
-	DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
-		"rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
-		in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
-		wi->mirror);
-
-	r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
-		wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
-		wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
-		wi->pre_mult_alpha, global_alpha, wi->rotation_type,
-		replication, mgr_timings, mem_to_mem);
-
-	switch (wi->color_mode) {
-	case OMAP_DSS_COLOR_RGB16:
-	case OMAP_DSS_COLOR_RGB24P:
-	case OMAP_DSS_COLOR_ARGB16:
-	case OMAP_DSS_COLOR_RGBA16:
-	case OMAP_DSS_COLOR_RGB12U:
-	case OMAP_DSS_COLOR_ARGB16_1555:
-	case OMAP_DSS_COLOR_XRGB16_1555:
-	case OMAP_DSS_COLOR_RGBX16:
-		truncation = true;
-		break;
-	default:
-		truncation = false;
-		break;
-	}
-
-	/* setup extra DISPC_WB_ATTRIBUTES */
-	l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
-	l = FLD_MOD(l, truncation, 10, 10);	/* TRUNCATIONENABLE */
-	l = FLD_MOD(l, mem_to_mem, 19, 19);	/* WRITEBACKMODE */
-	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
-
-	return r;
-}
-
-int dispc_ovl_enable(enum omap_plane plane, bool enable)
-{
-	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
-
-	return 0;
-}
-EXPORT_SYMBOL(dispc_ovl_enable);
-
-bool dispc_ovl_enabled(enum omap_plane plane)
-{
-	return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
-}
-EXPORT_SYMBOL(dispc_ovl_enabled);
-
-void dispc_mgr_enable(enum omap_channel channel, bool enable)
-{
-	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
-	/* flush posted write */
-	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
-}
-EXPORT_SYMBOL(dispc_mgr_enable);
-
-bool dispc_mgr_is_enabled(enum omap_channel channel)
-{
-	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
-}
-EXPORT_SYMBOL(dispc_mgr_is_enabled);
-
-void dispc_wb_enable(bool enable)
-{
-	dispc_ovl_enable(OMAP_DSS_WB, enable);
-}
-
-bool dispc_wb_is_enabled(void)
-{
-	return dispc_ovl_enabled(OMAP_DSS_WB);
-}
-
-static void dispc_lcd_enable_signal_polarity(bool act_high)
-{
-	if (!dss_has_feature(FEAT_LCDENABLEPOL))
-		return;
-
-	REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
-}
-
-void dispc_lcd_enable_signal(bool enable)
-{
-	if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
-		return;
-
-	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
-}
-
-void dispc_pck_free_enable(bool enable)
-{
-	if (!dss_has_feature(FEAT_PCKFREEENABLE))
-		return;
-
-	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
-}
-
-static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
-{
-	mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
-}
-
-
-static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
-{
-	mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
-}
-
-void dispc_set_loadmode(enum omap_dss_load_mode mode)
-{
-	REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
-}
-
-
-static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
-{
-	dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
-}
-
-static void dispc_mgr_set_trans_key(enum omap_channel ch,
-		enum omap_dss_trans_key_type type,
-		u32 trans_key)
-{
-	mgr_fld_write(ch, DISPC_MGR_FLD_TCKSELECTION, type);
-
-	dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
-}
-
-static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
-{
-	mgr_fld_write(ch, DISPC_MGR_FLD_TCKENABLE, enable);
-}
-
-static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
-		bool enable)
-{
-	if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
-		return;
-
-	if (ch == OMAP_DSS_CHANNEL_LCD)
-		REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
-	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
-		REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
-}
-
-void dispc_mgr_setup(enum omap_channel channel,
-		const struct omap_overlay_manager_info *info)
-{
-	dispc_mgr_set_default_color(channel, info->default_color);
-	dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
-	dispc_mgr_enable_trans_key(channel, info->trans_enabled);
-	dispc_mgr_enable_alpha_fixed_zorder(channel,
-			info->partial_alpha_enabled);
-	if (dss_has_feature(FEAT_CPR)) {
-		dispc_mgr_enable_cpr(channel, info->cpr_enable);
-		dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
-	}
-}
-EXPORT_SYMBOL(dispc_mgr_setup);
-
-static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
-{
-	int code;
-
-	switch (data_lines) {
-	case 12:
-		code = 0;
-		break;
-	case 16:
-		code = 1;
-		break;
-	case 18:
-		code = 2;
-		break;
-	case 24:
-		code = 3;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
-}
-
-static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
-{
-	u32 l;
-	int gpout0, gpout1;
-
-	switch (mode) {
-	case DSS_IO_PAD_MODE_RESET:
-		gpout0 = 0;
-		gpout1 = 0;
-		break;
-	case DSS_IO_PAD_MODE_RFBI:
-		gpout0 = 1;
-		gpout1 = 0;
-		break;
-	case DSS_IO_PAD_MODE_BYPASS:
-		gpout0 = 1;
-		gpout1 = 1;
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	l = dispc_read_reg(DISPC_CONTROL);
-	l = FLD_MOD(l, gpout0, 15, 15);
-	l = FLD_MOD(l, gpout1, 16, 16);
-	dispc_write_reg(DISPC_CONTROL, l);
-}
-
-static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
-{
-	mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
-}
-
-void dispc_mgr_set_lcd_config(enum omap_channel channel,
-		const struct dss_lcd_mgr_config *config)
-{
-	dispc_mgr_set_io_pad_mode(config->io_pad_mode);
-
-	dispc_mgr_enable_stallmode(channel, config->stallmode);
-	dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
-
-	dispc_mgr_set_clock_div(channel, &config->clock_info);
-
-	dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
-
-	dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
-
-	dispc_mgr_set_lcd_type_tft(channel);
-}
-EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
-
-static bool _dispc_mgr_size_ok(u16 width, u16 height)
-{
-	return width <= dispc.feat->mgr_width_max &&
-		height <= dispc.feat->mgr_height_max;
-}
-
-static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
-		int vsw, int vfp, int vbp)
-{
-	if (hsw < 1 || hsw > dispc.feat->sw_max ||
-			hfp < 1 || hfp > dispc.feat->hp_max ||
-			hbp < 1 || hbp > dispc.feat->hp_max ||
-			vsw < 1 || vsw > dispc.feat->sw_max ||
-			vfp < 0 || vfp > dispc.feat->vp_max ||
-			vbp < 0 || vbp > dispc.feat->vp_max)
-		return false;
-	return true;
-}
-
-static bool _dispc_mgr_pclk_ok(enum omap_channel channel,
-		unsigned long pclk)
-{
-	if (dss_mgr_is_lcd(channel))
-		return pclk <= dispc.feat->max_lcd_pclk ? true : false;
-	else
-		return pclk <= dispc.feat->max_tv_pclk ? true : false;
-}
-
-bool dispc_mgr_timings_ok(enum omap_channel channel,
-		const struct omap_video_timings *timings)
-{
-	bool timings_ok;
-
-	timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
-
-	timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixelclock);
-
-	if (dss_mgr_is_lcd(channel)) {
-		timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
-				timings->hbp, timings->vsw, timings->vfp,
-				timings->vbp);
-	}
-
-	return timings_ok;
-}
-
-static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
-		int hfp, int hbp, int vsw, int vfp, int vbp,
-		enum omap_dss_signal_level vsync_level,
-		enum omap_dss_signal_level hsync_level,
-		enum omap_dss_signal_edge data_pclk_edge,
-		enum omap_dss_signal_level de_level,
-		enum omap_dss_signal_edge sync_pclk_edge)
-
-{
-	u32 timing_h, timing_v, l;
-	bool onoff, rf, ipc;
-
-	timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
-			FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
-			FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
-	timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
-			FLD_VAL(vfp, dispc.feat->fp_start, 8) |
-			FLD_VAL(vbp, dispc.feat->bp_start, 20);
-
-	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
-	dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
-
-	switch (data_pclk_edge) {
-	case OMAPDSS_DRIVE_SIG_RISING_EDGE:
-		ipc = false;
-		break;
-	case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
-		ipc = true;
-		break;
-	case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
-	default:
-		BUG();
-	}
-
-	switch (sync_pclk_edge) {
-	case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
-		onoff = false;
-		rf = false;
-		break;
-	case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
-		onoff = true;
-		rf = false;
-		break;
-	case OMAPDSS_DRIVE_SIG_RISING_EDGE:
-		onoff = true;
-		rf = true;
-		break;
-	default:
-		BUG();
-	}
-
-	l = dispc_read_reg(DISPC_POL_FREQ(channel));
-	l |= FLD_VAL(onoff, 17, 17);
-	l |= FLD_VAL(rf, 16, 16);
-	l |= FLD_VAL(de_level, 15, 15);
-	l |= FLD_VAL(ipc, 14, 14);
-	l |= FLD_VAL(hsync_level, 13, 13);
-	l |= FLD_VAL(vsync_level, 12, 12);
-	dispc_write_reg(DISPC_POL_FREQ(channel), l);
-}
-
-/* change name to mode? */
-void dispc_mgr_set_timings(enum omap_channel channel,
-		const struct omap_video_timings *timings)
-{
-	unsigned xtot, ytot;
-	unsigned long ht, vt;
-	struct omap_video_timings t = *timings;
-
-	DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
-
-	if (!dispc_mgr_timings_ok(channel, &t)) {
-		BUG();
-		return;
-	}
-
-	if (dss_mgr_is_lcd(channel)) {
-		_dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
-				t.vfp, t.vbp, t.vsync_level, t.hsync_level,
-				t.data_pclk_edge, t.de_level, t.sync_pclk_edge);
-
-		xtot = t.x_res + t.hfp + t.hsw + t.hbp;
-		ytot = t.y_res + t.vfp + t.vsw + t.vbp;
-
-		ht = timings->pixelclock / xtot;
-		vt = timings->pixelclock / xtot / ytot;
-
-		DSSDBG("pck %u\n", timings->pixelclock);
-		DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
-			t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
-		DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n",
-			t.vsync_level, t.hsync_level, t.data_pclk_edge,
-			t.de_level, t.sync_pclk_edge);
-
-		DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
-	} else {
-		if (t.interlace == true)
-			t.y_res /= 2;
-	}
-
-	dispc_mgr_set_size(channel, t.x_res, t.y_res);
-}
-EXPORT_SYMBOL(dispc_mgr_set_timings);
-
-static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
-		u16 pck_div)
-{
-	BUG_ON(lck_div < 1);
-	BUG_ON(pck_div < 1);
-
-	dispc_write_reg(DISPC_DIVISORo(channel),
-			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
-
-	if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
-			channel == OMAP_DSS_CHANNEL_LCD)
-		dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
-}
-
-static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
-		int *pck_div)
-{
-	u32 l;
-	l = dispc_read_reg(DISPC_DIVISORo(channel));
-	*lck_div = FLD_GET(l, 23, 16);
-	*pck_div = FLD_GET(l, 7, 0);
-}
-
-unsigned long dispc_fclk_rate(void)
-{
-	struct platform_device *dsidev;
-	unsigned long r = 0;
-
-	switch (dss_get_dispc_clk_source()) {
-	case OMAP_DSS_CLK_SRC_FCK:
-		r = dss_get_dispc_clk_rate();
-		break;
-	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-		dsidev = dsi_get_dsidev_from_id(0);
-		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-		dsidev = dsi_get_dsidev_from_id(1);
-		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-		break;
-	default:
-		BUG();
-		return 0;
-	}
-
-	return r;
-}
-
-unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
-{
-	struct platform_device *dsidev;
-	int lcd;
-	unsigned long r;
-	u32 l;
-
-	if (dss_mgr_is_lcd(channel)) {
-		l = dispc_read_reg(DISPC_DIVISORo(channel));
-
-		lcd = FLD_GET(l, 23, 16);
-
-		switch (dss_get_lcd_clk_source(channel)) {
-		case OMAP_DSS_CLK_SRC_FCK:
-			r = dss_get_dispc_clk_rate();
-			break;
-		case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-			dsidev = dsi_get_dsidev_from_id(0);
-			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-			break;
-		case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-			dsidev = dsi_get_dsidev_from_id(1);
-			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-			break;
-		default:
-			BUG();
-			return 0;
-		}
-
-		return r / lcd;
-	} else {
-		return dispc_fclk_rate();
-	}
-}
-
-unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
-{
-	unsigned long r;
-
-	if (dss_mgr_is_lcd(channel)) {
-		int pcd;
-		u32 l;
-
-		l = dispc_read_reg(DISPC_DIVISORo(channel));
-
-		pcd = FLD_GET(l, 7, 0);
-
-		r = dispc_mgr_lclk_rate(channel);
-
-		return r / pcd;
-	} else {
-		return dispc.tv_pclk_rate;
-	}
-}
-
-void dispc_set_tv_pclk(unsigned long pclk)
-{
-	dispc.tv_pclk_rate = pclk;
-}
-
-unsigned long dispc_core_clk_rate(void)
-{
-	return dispc.core_clk_rate;
-}
-
-static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
-{
-	enum omap_channel channel;
-
-	if (plane == OMAP_DSS_WB)
-		return 0;
-
-	channel = dispc_ovl_get_channel_out(plane);
-
-	return dispc_mgr_pclk_rate(channel);
-}
-
-static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
-{
-	enum omap_channel channel;
-
-	if (plane == OMAP_DSS_WB)
-		return 0;
-
-	channel	= dispc_ovl_get_channel_out(plane);
-
-	return dispc_mgr_lclk_rate(channel);
-}
-
-static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
-{
-	int lcd, pcd;
-	enum omap_dss_clk_source lcd_clk_src;
-
-	seq_printf(s, "- %s -\n", mgr_desc[channel].name);
-
-	lcd_clk_src = dss_get_lcd_clk_source(channel);
-
-	seq_printf(s, "%s clk source = %s (%s)\n", mgr_desc[channel].name,
-		dss_get_generic_clk_source_name(lcd_clk_src),
-		dss_feat_get_clk_source_name(lcd_clk_src));
-
-	dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd);
-
-	seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
-		dispc_mgr_lclk_rate(channel), lcd);
-	seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
-		dispc_mgr_pclk_rate(channel), pcd);
-}
-
-void dispc_dump_clocks(struct seq_file *s)
-{
-	int lcd;
-	u32 l;
-	enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
-
-	if (dispc_runtime_get())
-		return;
-
-	seq_printf(s, "- DISPC -\n");
-
-	seq_printf(s, "dispc fclk source = %s (%s)\n",
-			dss_get_generic_clk_source_name(dispc_clk_src),
-			dss_feat_get_clk_source_name(dispc_clk_src));
-
-	seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
-
-	if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
-		seq_printf(s, "- DISPC-CORE-CLK -\n");
-		l = dispc_read_reg(DISPC_DIVISOR);
-		lcd = FLD_GET(l, 23, 16);
-
-		seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
-				(dispc_fclk_rate()/lcd), lcd);
-	}
-
-	dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD);
-
-	if (dss_has_feature(FEAT_MGR_LCD2))
-		dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2);
-	if (dss_has_feature(FEAT_MGR_LCD3))
-		dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3);
-
-	dispc_runtime_put();
-}
-
-static void dispc_dump_regs(struct seq_file *s)
-{
-	int i, j;
-	const char *mgr_names[] = {
-		[OMAP_DSS_CHANNEL_LCD]		= "LCD",
-		[OMAP_DSS_CHANNEL_DIGIT]	= "TV",
-		[OMAP_DSS_CHANNEL_LCD2]		= "LCD2",
-		[OMAP_DSS_CHANNEL_LCD3]		= "LCD3",
-	};
-	const char *ovl_names[] = {
-		[OMAP_DSS_GFX]		= "GFX",
-		[OMAP_DSS_VIDEO1]	= "VID1",
-		[OMAP_DSS_VIDEO2]	= "VID2",
-		[OMAP_DSS_VIDEO3]	= "VID3",
-	};
-	const char **p_names;
-
-#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
-
-	if (dispc_runtime_get())
-		return;
-
-	/* DISPC common registers */
-	DUMPREG(DISPC_REVISION);
-	DUMPREG(DISPC_SYSCONFIG);
-	DUMPREG(DISPC_SYSSTATUS);
-	DUMPREG(DISPC_IRQSTATUS);
-	DUMPREG(DISPC_IRQENABLE);
-	DUMPREG(DISPC_CONTROL);
-	DUMPREG(DISPC_CONFIG);
-	DUMPREG(DISPC_CAPABLE);
-	DUMPREG(DISPC_LINE_STATUS);
-	DUMPREG(DISPC_LINE_NUMBER);
-	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
-			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
-		DUMPREG(DISPC_GLOBAL_ALPHA);
-	if (dss_has_feature(FEAT_MGR_LCD2)) {
-		DUMPREG(DISPC_CONTROL2);
-		DUMPREG(DISPC_CONFIG2);
-	}
-	if (dss_has_feature(FEAT_MGR_LCD3)) {
-		DUMPREG(DISPC_CONTROL3);
-		DUMPREG(DISPC_CONFIG3);
-	}
-	if (dss_has_feature(FEAT_MFLAG))
-		DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE);
-
-#undef DUMPREG
-
-#define DISPC_REG(i, name) name(i)
-#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
-	(int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
-	dispc_read_reg(DISPC_REG(i, r)))
-
-	p_names = mgr_names;
-
-	/* DISPC channel specific registers */
-	for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
-		DUMPREG(i, DISPC_DEFAULT_COLOR);
-		DUMPREG(i, DISPC_TRANS_COLOR);
-		DUMPREG(i, DISPC_SIZE_MGR);
-
-		if (i == OMAP_DSS_CHANNEL_DIGIT)
-			continue;
-
-		DUMPREG(i, DISPC_DEFAULT_COLOR);
-		DUMPREG(i, DISPC_TRANS_COLOR);
-		DUMPREG(i, DISPC_TIMING_H);
-		DUMPREG(i, DISPC_TIMING_V);
-		DUMPREG(i, DISPC_POL_FREQ);
-		DUMPREG(i, DISPC_DIVISORo);
-		DUMPREG(i, DISPC_SIZE_MGR);
-
-		DUMPREG(i, DISPC_DATA_CYCLE1);
-		DUMPREG(i, DISPC_DATA_CYCLE2);
-		DUMPREG(i, DISPC_DATA_CYCLE3);
-
-		if (dss_has_feature(FEAT_CPR)) {
-			DUMPREG(i, DISPC_CPR_COEF_R);
-			DUMPREG(i, DISPC_CPR_COEF_G);
-			DUMPREG(i, DISPC_CPR_COEF_B);
-		}
-	}
-
-	p_names = ovl_names;
-
-	for (i = 0; i < dss_feat_get_num_ovls(); i++) {
-		DUMPREG(i, DISPC_OVL_BA0);
-		DUMPREG(i, DISPC_OVL_BA1);
-		DUMPREG(i, DISPC_OVL_POSITION);
-		DUMPREG(i, DISPC_OVL_SIZE);
-		DUMPREG(i, DISPC_OVL_ATTRIBUTES);
-		DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD);
-		DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS);
-		DUMPREG(i, DISPC_OVL_ROW_INC);
-		DUMPREG(i, DISPC_OVL_PIXEL_INC);
-		if (dss_has_feature(FEAT_PRELOAD))
-			DUMPREG(i, DISPC_OVL_PRELOAD);
-
-		if (i == OMAP_DSS_GFX) {
-			DUMPREG(i, DISPC_OVL_WINDOW_SKIP);
-			DUMPREG(i, DISPC_OVL_TABLE_BA);
-			continue;
-		}
-
-		DUMPREG(i, DISPC_OVL_FIR);
-		DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
-		DUMPREG(i, DISPC_OVL_ACCU0);
-		DUMPREG(i, DISPC_OVL_ACCU1);
-		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-			DUMPREG(i, DISPC_OVL_BA0_UV);
-			DUMPREG(i, DISPC_OVL_BA1_UV);
-			DUMPREG(i, DISPC_OVL_FIR2);
-			DUMPREG(i, DISPC_OVL_ACCU2_0);
-			DUMPREG(i, DISPC_OVL_ACCU2_1);
-		}
-		if (dss_has_feature(FEAT_ATTR2))
-			DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
-		if (dss_has_feature(FEAT_PRELOAD))
-			DUMPREG(i, DISPC_OVL_PRELOAD);
-		if (dss_has_feature(FEAT_MFLAG))
-			DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
-	}
-
-#undef DISPC_REG
-#undef DUMPREG
-
-#define DISPC_REG(plane, name, i) name(plane, i)
-#define DUMPREG(plane, name, i) \
-	seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
-	(int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
-	dispc_read_reg(DISPC_REG(plane, name, i)))
-
-	/* Video pipeline coefficient registers */
-
-	/* start from OMAP_DSS_VIDEO1 */
-	for (i = 1; i < dss_feat_get_num_ovls(); i++) {
-		for (j = 0; j < 8; j++)
-			DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
-
-		for (j = 0; j < 8; j++)
-			DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j);
-
-		for (j = 0; j < 5; j++)
-			DUMPREG(i, DISPC_OVL_CONV_COEF, j);
-
-		if (dss_has_feature(FEAT_FIR_COEF_V)) {
-			for (j = 0; j < 8; j++)
-				DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
-		}
-
-		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-			for (j = 0; j < 8; j++)
-				DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
-
-			for (j = 0; j < 8; j++)
-				DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j);
-
-			for (j = 0; j < 8; j++)
-				DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j);
-		}
-	}
-
-	dispc_runtime_put();
-
-#undef DISPC_REG
-#undef DUMPREG
-}
-
-/* calculate clock rates using dividers in cinfo */
-int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
-		struct dispc_clock_info *cinfo)
-{
-	if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
-		return -EINVAL;
-	if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
-		return -EINVAL;
-
-	cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
-	cinfo->pck = cinfo->lck / cinfo->pck_div;
-
-	return 0;
-}
-
-bool dispc_div_calc(unsigned long dispc,
-		unsigned long pck_min, unsigned long pck_max,
-		dispc_div_calc_func func, void *data)
-{
-	int lckd, lckd_start, lckd_stop;
-	int pckd, pckd_start, pckd_stop;
-	unsigned long pck, lck;
-	unsigned long lck_max;
-	unsigned long pckd_hw_min, pckd_hw_max;
-	unsigned min_fck_per_pck;
-	unsigned long fck;
-
-#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-#else
-	min_fck_per_pck = 0;
-#endif
-
-	pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
-	pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
-
-	lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	pck_min = pck_min ? pck_min : 1;
-	pck_max = pck_max ? pck_max : ULONG_MAX;
-
-	lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
-	lckd_stop = min(dispc / pck_min, 255ul);
-
-	for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
-		lck = dispc / lckd;
-
-		pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
-		pckd_stop = min(lck / pck_min, pckd_hw_max);
-
-		for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
-			pck = lck / pckd;
-
-			/*
-			 * For OMAP2/3 the DISPC fclk is the same as LCD's logic
-			 * clock, which means we're configuring DISPC fclk here
-			 * also. Thus we need to use the calculated lck. For
-			 * OMAP4+ the DISPC fclk is a separate clock.
-			 */
-			if (dss_has_feature(FEAT_CORE_CLK_DIV))
-				fck = dispc_core_clk_rate();
-			else
-				fck = lck;
-
-			if (fck < pck * min_fck_per_pck)
-				continue;
-
-			if (func(lckd, pckd, lck, pck, data))
-				return true;
-		}
-	}
-
-	return false;
-}
-
-void dispc_mgr_set_clock_div(enum omap_channel channel,
-		const struct dispc_clock_info *cinfo)
-{
-	DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
-	DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
-
-	dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
-}
-
-int dispc_mgr_get_clock_div(enum omap_channel channel,
-		struct dispc_clock_info *cinfo)
-{
-	unsigned long fck;
-
-	fck = dispc_fclk_rate();
-
-	cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
-	cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
-
-	cinfo->lck = fck / cinfo->lck_div;
-	cinfo->pck = cinfo->lck / cinfo->pck_div;
-
-	return 0;
-}
-
-u32 dispc_read_irqstatus(void)
-{
-	return dispc_read_reg(DISPC_IRQSTATUS);
-}
-EXPORT_SYMBOL(dispc_read_irqstatus);
-
-void dispc_clear_irqstatus(u32 mask)
-{
-	dispc_write_reg(DISPC_IRQSTATUS, mask);
-}
-EXPORT_SYMBOL(dispc_clear_irqstatus);
-
-u32 dispc_read_irqenable(void)
-{
-	return dispc_read_reg(DISPC_IRQENABLE);
-}
-EXPORT_SYMBOL(dispc_read_irqenable);
-
-void dispc_write_irqenable(u32 mask)
-{
-	u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
-
-	/* clear the irqstatus for newly enabled irqs */
-	dispc_clear_irqstatus((mask ^ old_mask) & mask);
-
-	dispc_write_reg(DISPC_IRQENABLE, mask);
-}
-EXPORT_SYMBOL(dispc_write_irqenable);
-
-void dispc_enable_sidle(void)
-{
-	REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3);	/* SIDLEMODE: smart idle */
-}
-
-void dispc_disable_sidle(void)
-{
-	REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3);	/* SIDLEMODE: no idle */
-}
-
-static void _omap_dispc_initial_config(void)
-{
-	u32 l;
-
-	/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
-	if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
-		l = dispc_read_reg(DISPC_DIVISOR);
-		/* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
-		l = FLD_MOD(l, 1, 0, 0);
-		l = FLD_MOD(l, 1, 23, 16);
-		dispc_write_reg(DISPC_DIVISOR, l);
-
-		dispc.core_clk_rate = dispc_fclk_rate();
-	}
-
-	/* FUNCGATED */
-	if (dss_has_feature(FEAT_FUNCGATED))
-		REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
-
-	dispc_setup_color_conv_coef();
-
-	dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
-
-	dispc_init_fifos();
-
-	dispc_configure_burst_sizes();
-
-	dispc_ovl_enable_zorder_planes();
-
-	if (dispc.feat->mstandby_workaround)
-		REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);
-}
-
-static const struct dispc_features omap24xx_dispc_feats __initconst = {
-	.sw_start		=	5,
-	.fp_start		=	15,
-	.bp_start		=	27,
-	.sw_max			=	64,
-	.vp_max			=	255,
-	.hp_max			=	256,
-	.mgr_width_start	=	10,
-	.mgr_height_start	=	26,
-	.mgr_width_max		=	2048,
-	.mgr_height_max		=	2048,
-	.max_lcd_pclk		=	66500000,
-	.calc_scaling		=	dispc_ovl_calc_scaling_24xx,
-	.calc_core_clk		=	calc_core_clk_24xx,
-	.num_fifos		=	3,
-	.no_framedone_tv	=	true,
-	.set_max_preload	=	false,
-};
-
-static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
-	.sw_start		=	5,
-	.fp_start		=	15,
-	.bp_start		=	27,
-	.sw_max			=	64,
-	.vp_max			=	255,
-	.hp_max			=	256,
-	.mgr_width_start	=	10,
-	.mgr_height_start	=	26,
-	.mgr_width_max		=	2048,
-	.mgr_height_max		=	2048,
-	.max_lcd_pclk		=	173000000,
-	.max_tv_pclk		=	59000000,
-	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
-	.calc_core_clk		=	calc_core_clk_34xx,
-	.num_fifos		=	3,
-	.no_framedone_tv	=	true,
-	.set_max_preload	=	false,
-};
-
-static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
-	.sw_start		=	7,
-	.fp_start		=	19,
-	.bp_start		=	31,
-	.sw_max			=	256,
-	.vp_max			=	4095,
-	.hp_max			=	4096,
-	.mgr_width_start	=	10,
-	.mgr_height_start	=	26,
-	.mgr_width_max		=	2048,
-	.mgr_height_max		=	2048,
-	.max_lcd_pclk		=	173000000,
-	.max_tv_pclk		=	59000000,
-	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
-	.calc_core_clk		=	calc_core_clk_34xx,
-	.num_fifos		=	3,
-	.no_framedone_tv	=	true,
-	.set_max_preload	=	false,
-};
-
-static const struct dispc_features omap44xx_dispc_feats __initconst = {
-	.sw_start		=	7,
-	.fp_start		=	19,
-	.bp_start		=	31,
-	.sw_max			=	256,
-	.vp_max			=	4095,
-	.hp_max			=	4096,
-	.mgr_width_start	=	10,
-	.mgr_height_start	=	26,
-	.mgr_width_max		=	2048,
-	.mgr_height_max		=	2048,
-	.max_lcd_pclk		=	170000000,
-	.max_tv_pclk		=	185625000,
-	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
-	.calc_core_clk		=	calc_core_clk_44xx,
-	.num_fifos		=	5,
-	.gfx_fifo_workaround	=	true,
-	.set_max_preload	=	true,
-};
-
-static const struct dispc_features omap54xx_dispc_feats __initconst = {
-	.sw_start		=	7,
-	.fp_start		=	19,
-	.bp_start		=	31,
-	.sw_max			=	256,
-	.vp_max			=	4095,
-	.hp_max			=	4096,
-	.mgr_width_start	=	11,
-	.mgr_height_start	=	27,
-	.mgr_width_max		=	4096,
-	.mgr_height_max		=	4096,
-	.max_lcd_pclk		=	170000000,
-	.max_tv_pclk		=	186000000,
-	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
-	.calc_core_clk		=	calc_core_clk_44xx,
-	.num_fifos		=	5,
-	.gfx_fifo_workaround	=	true,
-	.mstandby_workaround	=	true,
-	.set_max_preload	=	true,
-};
-
-static int __init dispc_init_features(struct platform_device *pdev)
-{
-	const struct dispc_features *src;
-	struct dispc_features *dst;
-
-	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
-	if (!dst) {
-		dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
-		return -ENOMEM;
-	}
-
-	switch (omapdss_get_version()) {
-	case OMAPDSS_VER_OMAP24xx:
-		src = &omap24xx_dispc_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP34xx_ES1:
-		src = &omap34xx_rev1_0_dispc_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP34xx_ES3:
-	case OMAPDSS_VER_OMAP3630:
-	case OMAPDSS_VER_AM35xx:
-		src = &omap34xx_rev3_0_dispc_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP4430_ES1:
-	case OMAPDSS_VER_OMAP4430_ES2:
-	case OMAPDSS_VER_OMAP4:
-		src = &omap44xx_dispc_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP5:
-		src = &omap54xx_dispc_feats;
-		break;
-
-	default:
-		return -ENODEV;
-	}
-
-	memcpy(dst, src, sizeof(*dst));
-	dispc.feat = dst;
-
-	return 0;
-}
-
-int dispc_request_irq(irq_handler_t handler, void *dev_id)
-{
-	return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
-			     IRQF_SHARED, "OMAP DISPC", dev_id);
-}
-EXPORT_SYMBOL(dispc_request_irq);
-
-void dispc_free_irq(void *dev_id)
-{
-	devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
-}
-EXPORT_SYMBOL(dispc_free_irq);
-
-/* DISPC HW IP initialisation */
-static int __init omap_dispchw_probe(struct platform_device *pdev)
-{
-	u32 rev;
-	int r = 0;
-	struct resource *dispc_mem;
-
-	dispc.pdev = pdev;
-
-	r = dispc_init_features(dispc.pdev);
-	if (r)
-		return r;
-
-	dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
-	if (!dispc_mem) {
-		DSSERR("can't get IORESOURCE_MEM DISPC\n");
-		return -EINVAL;
-	}
-
-	dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start,
-				  resource_size(dispc_mem));
-	if (!dispc.base) {
-		DSSERR("can't ioremap DISPC\n");
-		return -ENOMEM;
-	}
-
-	dispc.irq = platform_get_irq(dispc.pdev, 0);
-	if (dispc.irq < 0) {
-		DSSERR("platform_get_irq failed\n");
-		return -ENODEV;
-	}
-
-	pm_runtime_enable(&pdev->dev);
-
-	r = dispc_runtime_get();
-	if (r)
-		goto err_runtime_get;
-
-	_omap_dispc_initial_config();
-
-	rev = dispc_read_reg(DISPC_REVISION);
-	dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
-	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-	dispc_runtime_put();
-
-	dss_init_overlay_managers();
-
-	dss_debugfs_create_file("dispc", dispc_dump_regs);
-
-	return 0;
-
-err_runtime_get:
-	pm_runtime_disable(&pdev->dev);
-	return r;
-}
-
-static int __exit omap_dispchw_remove(struct platform_device *pdev)
-{
-	pm_runtime_disable(&pdev->dev);
-
-	dss_uninit_overlay_managers();
-
-	return 0;
-}
-
-static int dispc_runtime_suspend(struct device *dev)
-{
-	dispc_save_context();
-
-	return 0;
-}
-
-static int dispc_runtime_resume(struct device *dev)
-{
-	/*
-	 * The reset value for load mode is 0 (OMAP_DSS_LOAD_CLUT_AND_FRAME)
-	 * but we always initialize it to 2 (OMAP_DSS_LOAD_FRAME_ONLY) in
-	 * _omap_dispc_initial_config(). We can thus use it to detect if
-	 * we have lost register context.
-	 */
-	if (REG_GET(DISPC_CONFIG, 2, 1) == OMAP_DSS_LOAD_FRAME_ONLY)
-		return 0;
-
-	_omap_dispc_initial_config();
-
-	dispc_restore_context();
-
-	return 0;
-}
-
-static const struct dev_pm_ops dispc_pm_ops = {
-	.runtime_suspend = dispc_runtime_suspend,
-	.runtime_resume = dispc_runtime_resume,
-};
-
-static const struct of_device_id dispc_of_match[] = {
-	{ .compatible = "ti,omap2-dispc", },
-	{ .compatible = "ti,omap3-dispc", },
-	{ .compatible = "ti,omap4-dispc", },
-	{},
-};
-
-static struct platform_driver omap_dispchw_driver = {
-	.remove         = __exit_p(omap_dispchw_remove),
-	.driver         = {
-		.name   = "omapdss_dispc",
-		.owner  = THIS_MODULE,
-		.pm	= &dispc_pm_ops,
-		.of_match_table = dispc_of_match,
-	},
-};
-
-int __init dispc_init_platform_driver(void)
-{
-	return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe);
-}
-
-void __exit dispc_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omap_dispchw_driver);
-}
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
deleted file mode 100644
index 78edb449c763..000000000000
--- a/drivers/video/omap2/dss/dispc.h
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dispc.h
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Archit Taneja <archit@ti.com>
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP2_DISPC_REG_H
-#define __OMAP2_DISPC_REG_H
-
-/* DISPC common registers */
-#define DISPC_REVISION			0x0000
-#define DISPC_SYSCONFIG			0x0010
-#define DISPC_SYSSTATUS			0x0014
-#define DISPC_IRQSTATUS			0x0018
-#define DISPC_IRQENABLE			0x001C
-#define DISPC_CONTROL			0x0040
-#define DISPC_CONFIG			0x0044
-#define DISPC_CAPABLE			0x0048
-#define DISPC_LINE_STATUS		0x005C
-#define DISPC_LINE_NUMBER		0x0060
-#define DISPC_GLOBAL_ALPHA		0x0074
-#define DISPC_CONTROL2			0x0238
-#define DISPC_CONFIG2			0x0620
-#define DISPC_DIVISOR			0x0804
-#define DISPC_GLOBAL_BUFFER		0x0800
-#define DISPC_CONTROL3                  0x0848
-#define DISPC_CONFIG3                   0x084C
-#define DISPC_MSTANDBY_CTRL		0x0858
-#define DISPC_GLOBAL_MFLAG_ATTRIBUTE	0x085C
-
-/* DISPC overlay registers */
-#define DISPC_OVL_BA0(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_BA0_OFFSET(n))
-#define DISPC_OVL_BA1(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_BA1_OFFSET(n))
-#define DISPC_OVL_BA0_UV(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_BA0_UV_OFFSET(n))
-#define DISPC_OVL_BA1_UV(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_BA1_UV_OFFSET(n))
-#define DISPC_OVL_POSITION(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_POS_OFFSET(n))
-#define DISPC_OVL_SIZE(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_SIZE_OFFSET(n))
-#define DISPC_OVL_ATTRIBUTES(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_ATTR_OFFSET(n))
-#define DISPC_OVL_ATTRIBUTES2(n)	(DISPC_OVL_BASE(n) + \
-					DISPC_ATTR2_OFFSET(n))
-#define DISPC_OVL_FIFO_THRESHOLD(n)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIFO_THRESH_OFFSET(n))
-#define DISPC_OVL_FIFO_SIZE_STATUS(n)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIFO_SIZE_STATUS_OFFSET(n))
-#define DISPC_OVL_ROW_INC(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_ROW_INC_OFFSET(n))
-#define DISPC_OVL_PIXEL_INC(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_PIX_INC_OFFSET(n))
-#define DISPC_OVL_WINDOW_SKIP(n)	(DISPC_OVL_BASE(n) + \
-					DISPC_WINDOW_SKIP_OFFSET(n))
-#define DISPC_OVL_TABLE_BA(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_TABLE_BA_OFFSET(n))
-#define DISPC_OVL_FIR(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_FIR_OFFSET(n))
-#define DISPC_OVL_FIR2(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_FIR2_OFFSET(n))
-#define DISPC_OVL_PICTURE_SIZE(n)	(DISPC_OVL_BASE(n) + \
-					DISPC_PIC_SIZE_OFFSET(n))
-#define DISPC_OVL_ACCU0(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_ACCU0_OFFSET(n))
-#define DISPC_OVL_ACCU1(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_ACCU1_OFFSET(n))
-#define DISPC_OVL_ACCU2_0(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_ACCU2_0_OFFSET(n))
-#define DISPC_OVL_ACCU2_1(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_ACCU2_1_OFFSET(n))
-#define DISPC_OVL_FIR_COEF_H(n, i)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIR_COEF_H_OFFSET(n, i))
-#define DISPC_OVL_FIR_COEF_HV(n, i)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIR_COEF_HV_OFFSET(n, i))
-#define DISPC_OVL_FIR_COEF_H2(n, i)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIR_COEF_H2_OFFSET(n, i))
-#define DISPC_OVL_FIR_COEF_HV2(n, i)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIR_COEF_HV2_OFFSET(n, i))
-#define DISPC_OVL_CONV_COEF(n, i)	(DISPC_OVL_BASE(n) + \
-					DISPC_CONV_COEF_OFFSET(n, i))
-#define DISPC_OVL_FIR_COEF_V(n, i)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIR_COEF_V_OFFSET(n, i))
-#define DISPC_OVL_FIR_COEF_V2(n, i)	(DISPC_OVL_BASE(n) + \
-					DISPC_FIR_COEF_V2_OFFSET(n, i))
-#define DISPC_OVL_PRELOAD(n)		(DISPC_OVL_BASE(n) + \
-					DISPC_PRELOAD_OFFSET(n))
-#define DISPC_OVL_MFLAG_THRESHOLD(n)	(DISPC_OVL_BASE(n) + \
-					DISPC_MFLAG_THRESHOLD_OFFSET(n))
-
-/* DISPC up/downsampling FIR filter coefficient structure */
-struct dispc_coef {
-	s8 hc4_vc22;
-	s8 hc3_vc2;
-	u8 hc2_vc1;
-	s8 hc1_vc0;
-	s8 hc0_vc00;
-};
-
-const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps);
-
-/* DISPC manager/channel specific registers */
-static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x004C;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		return 0x0050;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03AC;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0814;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x0054;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		return 0x0058;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03B0;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0818;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_TIMING_H(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x0064;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x0400;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0840;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_TIMING_V(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x0068;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x0404;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0844;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x006C;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x0408;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x083C;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_DIVISORo(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x0070;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x040C;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0838;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* Named as DISPC_SIZE_LCD, DISPC_SIZE_DIGIT and DISPC_SIZE_LCD2 in TRM */
-static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x007C;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		return 0x0078;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03CC;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0834;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x01D4;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03C0;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0828;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x01D8;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03C4;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x082C;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x01DC;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03C8;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0830;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x0220;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03BC;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0824;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x0224;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03B8;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x0820;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return 0x0228;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		BUG();
-		return 0;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return 0x03B4;
-	case OMAP_DSS_CHANNEL_LCD3:
-		return 0x081C;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* DISPC overlay register base addresses */
-static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0080;
-	case OMAP_DSS_VIDEO1:
-		return 0x00BC;
-	case OMAP_DSS_VIDEO2:
-		return 0x014C;
-	case OMAP_DSS_VIDEO3:
-		return 0x0300;
-	case OMAP_DSS_WB:
-		return 0x0500;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* DISPC overlay register offsets */
-static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0000;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0008;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0004;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x000C;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0544;
-	case OMAP_DSS_VIDEO2:
-		return 0x04BC;
-	case OMAP_DSS_VIDEO3:
-		return 0x0310;
-	case OMAP_DSS_WB:
-		return 0x0118;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0548;
-	case OMAP_DSS_VIDEO2:
-		return 0x04C0;
-	case OMAP_DSS_VIDEO3:
-		return 0x0314;
-	case OMAP_DSS_WB:
-		return 0x011C;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0008;
-	case OMAP_DSS_VIDEO3:
-		return 0x009C;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x000C;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x00A8;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0020;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0010;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0070;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0568;
-	case OMAP_DSS_VIDEO2:
-		return 0x04DC;
-	case OMAP_DSS_VIDEO3:
-		return 0x032C;
-	case OMAP_DSS_WB:
-		return 0x0310;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0024;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0014;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x008C;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0028;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0018;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0088;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x002C;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x001C;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x00A4;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0030;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0020;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0098;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0034;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-	case OMAP_DSS_VIDEO3:
-		BUG();
-		return 0;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0038;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-	case OMAP_DSS_VIDEO3:
-		BUG();
-		return 0;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0024;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0090;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0580;
-	case OMAP_DSS_VIDEO2:
-		return 0x055C;
-	case OMAP_DSS_VIDEO3:
-		return 0x0424;
-	case OMAP_DSS_WB:
-		return 0x290;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0028;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0094;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-
-static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x002C;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0000;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0584;
-	case OMAP_DSS_VIDEO2:
-		return 0x0560;
-	case OMAP_DSS_VIDEO3:
-		return 0x0428;
-	case OMAP_DSS_WB:
-		return 0x0294;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0030;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0004;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0588;
-	case OMAP_DSS_VIDEO2:
-		return 0x0564;
-	case OMAP_DSS_VIDEO3:
-		return 0x042C;
-	case OMAP_DSS_WB:
-		return 0x0298;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
-static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0034 + i * 0x8;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0010 + i * 0x8;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
-static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x058C + i * 0x8;
-	case OMAP_DSS_VIDEO2:
-		return 0x0568 + i * 0x8;
-	case OMAP_DSS_VIDEO3:
-		return 0x0430 + i * 0x8;
-	case OMAP_DSS_WB:
-		return 0x02A0 + i * 0x8;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
-static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-		return 0x0038 + i * 0x8;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0014 + i * 0x8;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
-static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0590 + i * 8;
-	case OMAP_DSS_VIDEO2:
-		return 0x056C + i * 0x8;
-	case OMAP_DSS_VIDEO3:
-		return 0x0434 + i * 0x8;
-	case OMAP_DSS_WB:
-		return 0x02A4 + i * 0x8;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* coef index i = {0, 1, 2, 3, 4,} */
-static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-	case OMAP_DSS_VIDEO2:
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0074 + i * 0x4;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
-static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x0124 + i * 0x4;
-	case OMAP_DSS_VIDEO2:
-		return 0x00B4 + i * 0x4;
-	case OMAP_DSS_VIDEO3:
-	case OMAP_DSS_WB:
-		return 0x0050 + i * 0x4;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
-static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		BUG();
-		return 0;
-	case OMAP_DSS_VIDEO1:
-		return 0x05CC + i * 0x4;
-	case OMAP_DSS_VIDEO2:
-		return 0x05A8 + i * 0x4;
-	case OMAP_DSS_VIDEO3:
-		return 0x0470 + i * 0x4;
-	case OMAP_DSS_WB:
-		return 0x02E0 + i * 0x4;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x01AC;
-	case OMAP_DSS_VIDEO1:
-		return 0x0174;
-	case OMAP_DSS_VIDEO2:
-		return 0x00E8;
-	case OMAP_DSS_VIDEO3:
-		return 0x00A0;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane plane)
-{
-	switch (plane) {
-	case OMAP_DSS_GFX:
-		return 0x0860;
-	case OMAP_DSS_VIDEO1:
-		return 0x0864;
-	case OMAP_DSS_VIDEO2:
-		return 0x0868;
-	case OMAP_DSS_VIDEO3:
-		return 0x086c;
-	default:
-		BUG();
-		return 0;
-	}
-}
-#endif
diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/omap2/dss/dispc_coefs.c
deleted file mode 100644
index 038c15b04215..000000000000
--- a/drivers/video/omap2/dss/dispc_coefs.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dispc_coefs.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Chandrabhanu Mahapatra <cmahapatra@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <video/omapdss.h>
-
-#include "dispc.h"
-
-static const struct dispc_coef coef3_M8[8] = {
-	{ 0,  0, 128,  0, 0 },
-	{ 0, -4, 123,  9, 0 },
-	{ 0, -4, 108, 24, 0 },
-	{ 0, -2,  87, 43, 0 },
-	{ 0, 64,  64,  0, 0 },
-	{ 0, 43,  87, -2, 0 },
-	{ 0, 24, 108, -4, 0 },
-	{ 0,  9, 123, -4, 0 },
-};
-
-static const struct dispc_coef coef3_M9[8] = {
-	{ 0,  6, 116,  6, 0 },
-	{ 0,  0, 112, 16, 0 },
-	{ 0, -2, 100, 30, 0 },
-	{ 0, -2,  83, 47, 0 },
-	{ 0, 64,  64,  0, 0 },
-	{ 0, 47,  83, -2, 0 },
-	{ 0, 30, 100, -2, 0 },
-	{ 0, 16, 112,  0, 0 },
-};
-
-static const struct dispc_coef coef3_M10[8] = {
-	{ 0, 10, 108, 10, 0 },
-	{ 0,  3, 104, 21, 0 },
-	{ 0,  0,  94, 34, 0 },
-	{ 0, -1,  80, 49, 0 },
-	{ 0, 64,  64,  0, 0 },
-	{ 0, 49,  80, -1, 0 },
-	{ 0, 34,  94,  0, 0 },
-	{ 0, 21, 104,  3, 0 },
-};
-
-static const struct dispc_coef coef3_M11[8] = {
-	{ 0, 14, 100, 14, 0 },
-	{ 0,  6,  98, 24, 0 },
-	{ 0,  2,  90, 36, 0 },
-	{ 0,  0,  78, 50, 0 },
-	{ 0, 64,  64,  0, 0 },
-	{ 0, 50,  78,  0, 0 },
-	{ 0, 36,  90,  2, 0 },
-	{ 0, 24,  98,  6, 0 },
-};
-
-static const struct dispc_coef coef3_M12[8] = {
-	{ 0, 16,  96, 16, 0 },
-	{ 0,  9,  93, 26, 0 },
-	{ 0,  4,  86, 38, 0 },
-	{ 0,  1,  76, 51, 0 },
-	{ 0, 64,  64,  0, 0 },
-	{ 0, 51,  76,  1, 0 },
-	{ 0, 38,  86,  4, 0 },
-	{ 0, 26,  93,  9, 0 },
-};
-
-static const struct dispc_coef coef3_M13[8] = {
-	{ 0, 18,  92, 18, 0 },
-	{ 0, 10,  90, 28, 0 },
-	{ 0,  5,  83, 40, 0 },
-	{ 0,  1,  75, 52, 0 },
-	{ 0, 64,  64,  0, 0 },
-	{ 0, 52,  75,  1, 0 },
-	{ 0, 40,  83,  5, 0 },
-	{ 0, 28,  90, 10, 0 },
-};
-
-static const struct dispc_coef coef3_M14[8] = {
-	{ 0, 20, 88, 20, 0 },
-	{ 0, 12, 86, 30, 0 },
-	{ 0,  6, 81, 41, 0 },
-	{ 0,  2, 74, 52, 0 },
-	{ 0, 64, 64,  0, 0 },
-	{ 0, 52, 74,  2, 0 },
-	{ 0, 41, 81,  6, 0 },
-	{ 0, 30, 86, 12, 0 },
-};
-
-static const struct dispc_coef coef3_M16[8] = {
-	{ 0, 22, 84, 22, 0 },
-	{ 0, 14, 82, 32, 0 },
-	{ 0,  8, 78, 42, 0 },
-	{ 0,  3, 72, 53, 0 },
-	{ 0, 64, 64,  0, 0 },
-	{ 0, 53, 72,  3, 0 },
-	{ 0, 42, 78,  8, 0 },
-	{ 0, 32, 82, 14, 0 },
-};
-
-static const struct dispc_coef coef3_M19[8] = {
-	{ 0, 24, 80, 24, 0 },
-	{ 0, 16, 79, 33, 0 },
-	{ 0,  9, 76, 43, 0 },
-	{ 0,  4, 70, 54, 0 },
-	{ 0, 64, 64,  0, 0 },
-	{ 0, 54, 70,  4, 0 },
-	{ 0, 43, 76,  9, 0 },
-	{ 0, 33, 79, 16, 0 },
-};
-
-static const struct dispc_coef coef3_M22[8] = {
-	{ 0, 25, 78, 25, 0 },
-	{ 0, 17, 77, 34, 0 },
-	{ 0, 10, 74, 44, 0 },
-	{ 0,  5, 69, 54, 0 },
-	{ 0, 64, 64,  0, 0 },
-	{ 0, 54, 69,  5, 0 },
-	{ 0, 44, 74, 10, 0 },
-	{ 0, 34, 77, 17, 0 },
-};
-
-static const struct dispc_coef coef3_M26[8] = {
-	{ 0, 26, 76, 26, 0 },
-	{ 0, 19, 74, 35, 0 },
-	{ 0, 11, 72, 45, 0 },
-	{ 0,  5, 69, 54, 0 },
-	{ 0, 64, 64,  0, 0 },
-	{ 0, 54, 69,  5, 0 },
-	{ 0, 45, 72, 11, 0 },
-	{ 0, 35, 74, 19, 0 },
-};
-
-static const struct dispc_coef coef3_M32[8] = {
-	{ 0, 27, 74, 27, 0 },
-	{ 0, 19, 73, 36, 0 },
-	{ 0, 12, 71, 45, 0 },
-	{ 0,  6, 68, 54, 0 },
-	{ 0, 64, 64,  0, 0 },
-	{ 0, 54, 68,  6, 0 },
-	{ 0, 45, 71, 12, 0 },
-	{ 0, 36, 73, 19, 0 },
-};
-
-static const struct dispc_coef coef5_M8[8] = {
-	{   0,   0, 128,   0,   0 },
-	{  -2,  14, 125, -10,   1 },
-	{  -6,  33, 114, -15,   2 },
-	{ -10,  55,  98, -16,   1 },
-	{   0, -14,  78,  78, -14 },
-	{   1, -16,  98,  55, -10 },
-	{   2, -15, 114,  33,  -6 },
-	{   1, -10, 125,  14,  -2 },
-};
-
-static const struct dispc_coef coef5_M9[8] = {
-	{  -3,  10, 114,  10,  -3 },
-	{  -6,  24, 111,   0,  -1 },
-	{  -8,  40, 103,  -7,   0 },
-	{ -11,  58,  91, -11,   1 },
-	{   0, -12,  76,  76, -12 },
-	{   1, -11,  91,  58, -11 },
-	{   0,  -7, 103,  40,  -8 },
-	{  -1,   0, 111,  24,  -6 },
-};
-
-static const struct dispc_coef coef5_M10[8] = {
-	{  -4,  18, 100,  18,  -4 },
-	{  -6,  30,  99,   8,  -3 },
-	{  -8,  44,  93,   0,  -1 },
-	{  -9,  58,  84,  -5,   0 },
-	{   0,  -8,  72,  72,  -8 },
-	{   0,  -5,  84,  58,  -9 },
-	{  -1,   0,  93,  44,  -8 },
-	{  -3,   8,  99,  30,  -6 },
-};
-
-static const struct dispc_coef coef5_M11[8] = {
-	{  -5,  23,  92,  23,  -5 },
-	{  -6,  34,  90,  13,  -3 },
-	{  -6,  45,  85,   6,  -2 },
-	{  -6,  57,  78,   0,  -1 },
-	{   0,  -4,  68,  68,  -4 },
-	{  -1,   0,  78,  57,  -6 },
-	{  -2,   6,  85,  45,  -6 },
-	{  -3,  13,  90,  34,  -6 },
-};
-
-static const struct dispc_coef coef5_M12[8] = {
-	{  -4,  26,  84,  26,  -4 },
-	{  -5,  36,  82,  18,  -3 },
-	{  -4,  46,  78,  10,  -2 },
-	{  -3,  55,  72,   5,  -1 },
-	{   0,   0,  64,  64,   0 },
-	{  -1,   5,  72,  55,  -3 },
-	{  -2,  10,  78,  46,  -4 },
-	{  -3,  18,  82,  36,  -5 },
-};
-
-static const struct dispc_coef coef5_M13[8] = {
-	{  -3,  28,  78,  28,  -3 },
-	{  -3,  37,  76,  21,  -3 },
-	{  -2,  45,  73,  14,  -2 },
-	{   0,  53,  68,   8,  -1 },
-	{   0,   3,  61,  61,   3 },
-	{  -1,   8,  68,  53,   0 },
-	{  -2,  14,  73,  45,  -2 },
-	{  -3,  21,  76,  37,  -3 },
-};
-
-static const struct dispc_coef coef5_M14[8] = {
-	{  -2,  30,  72,  30,  -2 },
-	{  -1,  37,  71,  23,  -2 },
-	{   0,  45,  69,  16,  -2 },
-	{   3,  52,  64,  10,  -1 },
-	{   0,   6,  58,  58,   6 },
-	{  -1,  10,  64,  52,   3 },
-	{  -2,  16,  69,  45,   0 },
-	{  -2,  23,  71,  37,  -1 },
-};
-
-static const struct dispc_coef coef5_M16[8] = {
-	{   0,  31,  66,  31,   0 },
-	{   1,  38,  65,  25,  -1 },
-	{   3,  44,  62,  20,  -1 },
-	{   6,  49,  59,  14,   0 },
-	{   0,  10,  54,  54,  10 },
-	{   0,  14,  59,  49,   6 },
-	{  -1,  20,  62,  44,   3 },
-	{  -1,  25,  65,  38,   1 },
-};
-
-static const struct dispc_coef coef5_M19[8] = {
-	{   3,  32,  58,  32,   3 },
-	{   4,  38,  58,  27,   1 },
-	{   7,  42,  55,  23,   1 },
-	{  10,  46,  54,  18,   0 },
-	{   0,  14,  50,  50,  14 },
-	{   0,  18,  54,  46,  10 },
-	{   1,  23,  55,  42,   7 },
-	{   1,  27,  58,  38,   4 },
-};
-
-static const struct dispc_coef coef5_M22[8] = {
-	{   4,  33,  54,  33,   4 },
-	{   6,  37,  54,  28,   3 },
-	{   9,  41,  53,  24,   1 },
-	{  12,  45,  51,  20,   0 },
-	{   0,  16,  48,  48,  16 },
-	{   0,  20,  51,  45,  12 },
-	{   1,  24,  53,  41,   9 },
-	{   3,  28,  54,  37,   6 },
-};
-
-static const struct dispc_coef coef5_M26[8] = {
-	{   6,  33,  50,  33,   6 },
-	{   8,  36,  51,  29,   4 },
-	{  11,  40,  50,  25,   2 },
-	{  14,  43,  48,  22,   1 },
-	{   0,  18,  46,  46,  18 },
-	{   1,  22,  48,  43,  14 },
-	{   2,  25,  50,  40,  11 },
-	{   4,  29,  51,  36,   8 },
-};
-
-static const struct dispc_coef coef5_M32[8] = {
-	{   7,  33,  48,  33,   7 },
-	{  10,  36,  48,  29,   5 },
-	{  13,  39,  47,  26,   3 },
-	{  16,  42,  46,  23,   1 },
-	{   0,  19,  45,  45,  19 },
-	{   1,  23,  46,  42,  16 },
-	{   3,  26,  47,  39,  13 },
-	{   5,  29,  48,  36,  10 },
-};
-
-const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
-{
-	int i;
-	static const struct {
-		int Mmin;
-		int Mmax;
-		const struct dispc_coef *coef_3;
-		const struct dispc_coef *coef_5;
-	} coefs[] = {
-		{ 27, 32, coef3_M32, coef5_M32 },
-		{ 23, 26, coef3_M26, coef5_M26 },
-		{ 20, 22, coef3_M22, coef5_M22 },
-		{ 17, 19, coef3_M19, coef5_M19 },
-		{ 15, 16, coef3_M16, coef5_M16 },
-		{ 14, 14, coef3_M14, coef5_M14 },
-		{ 13, 13, coef3_M13, coef5_M13 },
-		{ 12, 12, coef3_M12, coef5_M12 },
-		{ 11, 11, coef3_M11, coef5_M11 },
-		{ 10, 10, coef3_M10, coef5_M10 },
-		{  9,  9,  coef3_M9,  coef5_M9 },
-		{  4,  8,  coef3_M8,  coef5_M8 },
-		/*
-		 * When upscaling more than two times, blockiness and outlines
-		 * around the image are observed when M8 tables are used. M11,
-		 * M16 and M19 tables are used to prevent this.
-		 */
-		{  3,  3, coef3_M11, coef5_M11 },
-		{  2,  2, coef3_M16, coef5_M16 },
-		{  0,  1, coef3_M19, coef5_M19 },
-	};
-
-	inc /= 128;
-	for (i = 0; i < ARRAY_SIZE(coefs); ++i)
-		if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
-			return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
-	return NULL;
-}
diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c
deleted file mode 100644
index 5a2095a98ed8..000000000000
--- a/drivers/video/omap2/dss/display-sysfs.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "DISPLAY"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sysfs.h>
-
-#include <video/omapdss.h>
-#include "dss.h"
-
-static struct omap_dss_device *to_dss_device_sysfs(struct device *dev)
-{
-	struct omap_dss_device *dssdev = NULL;
-
-	for_each_dss_dev(dssdev) {
-		if (dssdev->dev == dev) {
-			omap_dss_put_device(dssdev);
-			return dssdev;
-		}
-	}
-
-	return NULL;
-}
-
-static ssize_t display_name_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			dssdev->name ?
-			dssdev->name : "");
-}
-
-static ssize_t display_enabled_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			omapdss_device_is_enabled(dssdev));
-}
-
-static ssize_t display_enabled_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	int r;
-	bool enable;
-
-	r = strtobool(buf, &enable);
-	if (r)
-		return r;
-
-	if (enable == omapdss_device_is_enabled(dssdev))
-		return size;
-
-	if (omapdss_device_is_connected(dssdev) == false)
-		return -ENODEV;
-
-	if (enable) {
-		r = dssdev->driver->enable(dssdev);
-		if (r)
-			return r;
-	} else {
-		dssdev->driver->disable(dssdev);
-	}
-
-	return size;
-}
-
-static ssize_t display_tear_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			dssdev->driver->get_te ?
-			dssdev->driver->get_te(dssdev) : 0);
-}
-
-static ssize_t display_tear_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	int r;
-	bool te;
-
-	if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
-		return -ENOENT;
-
-	r = strtobool(buf, &te);
-	if (r)
-		return r;
-
-	r = dssdev->driver->enable_te(dssdev, te);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_timings_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	struct omap_video_timings t;
-
-	if (!dssdev->driver->get_timings)
-		return -ENOENT;
-
-	dssdev->driver->get_timings(dssdev, &t);
-
-	return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
-			t.pixelclock,
-			t.x_res, t.hfp, t.hbp, t.hsw,
-			t.y_res, t.vfp, t.vbp, t.vsw);
-}
-
-static ssize_t display_timings_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	struct omap_video_timings t = dssdev->panel.timings;
-	int r, found;
-
-	if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
-		return -ENOENT;
-
-	found = 0;
-#ifdef CONFIG_OMAP2_DSS_VENC
-	if (strncmp("pal", buf, 3) == 0) {
-		t = omap_dss_pal_timings;
-		found = 1;
-	} else if (strncmp("ntsc", buf, 4) == 0) {
-		t = omap_dss_ntsc_timings;
-		found = 1;
-	}
-#endif
-	if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
-				&t.pixelclock,
-				&t.x_res, &t.hfp, &t.hbp, &t.hsw,
-				&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
-		return -EINVAL;
-
-	r = dssdev->driver->check_timings(dssdev, &t);
-	if (r)
-		return r;
-
-	dssdev->driver->disable(dssdev);
-	dssdev->driver->set_timings(dssdev, &t);
-	r = dssdev->driver->enable(dssdev);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_rotate_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	int rotate;
-	if (!dssdev->driver->get_rotate)
-		return -ENOENT;
-	rotate = dssdev->driver->get_rotate(dssdev);
-	return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
-}
-
-static ssize_t display_rotate_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	int rot, r;
-
-	if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
-		return -ENOENT;
-
-	r = kstrtoint(buf, 0, &rot);
-	if (r)
-		return r;
-
-	r = dssdev->driver->set_rotate(dssdev, rot);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_mirror_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	int mirror;
-	if (!dssdev->driver->get_mirror)
-		return -ENOENT;
-	mirror = dssdev->driver->get_mirror(dssdev);
-	return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
-}
-
-static ssize_t display_mirror_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	int r;
-	bool mirror;
-
-	if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
-		return -ENOENT;
-
-	r = strtobool(buf, &mirror);
-	if (r)
-		return r;
-
-	r = dssdev->driver->set_mirror(dssdev, mirror);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_wss_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	unsigned int wss;
-
-	if (!dssdev->driver->get_wss)
-		return -ENOENT;
-
-	wss = dssdev->driver->get_wss(dssdev);
-
-	return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
-}
-
-static ssize_t display_wss_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device_sysfs(dev);
-	u32 wss;
-	int r;
-
-	if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
-		return -ENOENT;
-
-	r = kstrtou32(buf, 0, &wss);
-	if (r)
-		return r;
-
-	if (wss > 0xfffff)
-		return -EINVAL;
-
-	r = dssdev->driver->set_wss(dssdev, wss);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static DEVICE_ATTR(display_name, S_IRUGO, display_name_show, NULL);
-static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
-		display_enabled_show, display_enabled_store);
-static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
-		display_tear_show, display_tear_store);
-static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
-		display_timings_show, display_timings_store);
-static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
-		display_rotate_show, display_rotate_store);
-static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
-		display_mirror_show, display_mirror_store);
-static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
-		display_wss_show, display_wss_store);
-
-static const struct attribute *display_sysfs_attrs[] = {
-	&dev_attr_display_name.attr,
-	&dev_attr_enabled.attr,
-	&dev_attr_tear_elim.attr,
-	&dev_attr_timings.attr,
-	&dev_attr_rotate.attr,
-	&dev_attr_mirror.attr,
-	&dev_attr_wss.attr,
-	NULL
-};
-
-int display_init_sysfs(struct platform_device *pdev)
-{
-	struct omap_dss_device *dssdev = NULL;
-	int r;
-
-	for_each_dss_dev(dssdev) {
-		struct kobject *kobj = &dssdev->dev->kobj;
-
-		r = sysfs_create_files(kobj, display_sysfs_attrs);
-		if (r) {
-			DSSERR("failed to create sysfs files\n");
-			goto err;
-		}
-
-		r = sysfs_create_link(&pdev->dev.kobj, kobj, dssdev->alias);
-		if (r) {
-			sysfs_remove_files(kobj, display_sysfs_attrs);
-
-			DSSERR("failed to create sysfs display link\n");
-			goto err;
-		}
-	}
-
-	return 0;
-
-err:
-	display_uninit_sysfs(pdev);
-
-	return r;
-}
-
-void display_uninit_sysfs(struct platform_device *pdev)
-{
-	struct omap_dss_device *dssdev = NULL;
-
-	for_each_dss_dev(dssdev) {
-		sysfs_remove_link(&pdev->dev.kobj, dssdev->alias);
-		sysfs_remove_files(&dssdev->dev->kobj,
-				display_sysfs_attrs);
-	}
-}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
deleted file mode 100644
index 2412a0dd0c13..000000000000
--- a/drivers/video/omap2/dss/display.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/display.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "DISPLAY"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-
-#include <video/omapdss.h>
-#include "dss.h"
-#include "dss_features.h"
-
-void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
-			u16 *xres, u16 *yres)
-{
-	*xres = dssdev->panel.timings.x_res;
-	*yres = dssdev->panel.timings.y_res;
-}
-EXPORT_SYMBOL(omapdss_default_get_resolution);
-
-int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
-{
-	switch (dssdev->type) {
-	case OMAP_DISPLAY_TYPE_DPI:
-		if (dssdev->phy.dpi.data_lines == 24)
-			return 24;
-		else
-			return 16;
-
-	case OMAP_DISPLAY_TYPE_DBI:
-		if (dssdev->ctrl.pixel_size == 24)
-			return 24;
-		else
-			return 16;
-	case OMAP_DISPLAY_TYPE_DSI:
-		if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
-			return 24;
-		else
-			return 16;
-	case OMAP_DISPLAY_TYPE_VENC:
-	case OMAP_DISPLAY_TYPE_SDI:
-	case OMAP_DISPLAY_TYPE_HDMI:
-	case OMAP_DISPLAY_TYPE_DVI:
-		return 24;
-	default:
-		BUG();
-		return 0;
-	}
-}
-EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
-
-void omapdss_default_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	*timings = dssdev->panel.timings;
-}
-EXPORT_SYMBOL(omapdss_default_get_timings);
-
-int dss_suspend_all_devices(void)
-{
-	struct omap_dss_device *dssdev = NULL;
-
-	for_each_dss_dev(dssdev) {
-		if (!dssdev->driver)
-			continue;
-
-		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-			dssdev->driver->disable(dssdev);
-			dssdev->activate_after_resume = true;
-		} else {
-			dssdev->activate_after_resume = false;
-		}
-	}
-
-	return 0;
-}
-
-int dss_resume_all_devices(void)
-{
-	struct omap_dss_device *dssdev = NULL;
-
-	for_each_dss_dev(dssdev) {
-		if (!dssdev->driver)
-			continue;
-
-		if (dssdev->activate_after_resume) {
-			dssdev->driver->enable(dssdev);
-			dssdev->activate_after_resume = false;
-		}
-	}
-
-	return 0;
-}
-
-void dss_disable_all_devices(void)
-{
-	struct omap_dss_device *dssdev = NULL;
-
-	for_each_dss_dev(dssdev) {
-		if (!dssdev->driver)
-			continue;
-
-		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
-			dssdev->driver->disable(dssdev);
-	}
-}
-
-static LIST_HEAD(panel_list);
-static DEFINE_MUTEX(panel_list_mutex);
-static int disp_num_counter;
-
-int omapdss_register_display(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_driver *drv = dssdev->driver;
-	int id;
-
-	/*
-	 * Note: this presumes all the displays are either using DT or non-DT,
-	 * which normally should be the case. This also presumes that all
-	 * displays either have an DT alias, or none has.
-	 */
-
-	if (dssdev->dev->of_node) {
-		id = of_alias_get_id(dssdev->dev->of_node, "display");
-
-		if (id < 0)
-			id = disp_num_counter++;
-	} else {
-		id = disp_num_counter++;
-	}
-
-	snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id);
-
-	/* Use 'label' property for name, if it exists */
-	if (dssdev->dev->of_node)
-		of_property_read_string(dssdev->dev->of_node, "label",
-			&dssdev->name);
-
-	if (dssdev->name == NULL)
-		dssdev->name = dssdev->alias;
-
-	if (drv && drv->get_resolution == NULL)
-		drv->get_resolution = omapdss_default_get_resolution;
-	if (drv && drv->get_recommended_bpp == NULL)
-		drv->get_recommended_bpp = omapdss_default_get_recommended_bpp;
-	if (drv && drv->get_timings == NULL)
-		drv->get_timings = omapdss_default_get_timings;
-
-	mutex_lock(&panel_list_mutex);
-	list_add_tail(&dssdev->panel_list, &panel_list);
-	mutex_unlock(&panel_list_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(omapdss_register_display);
-
-void omapdss_unregister_display(struct omap_dss_device *dssdev)
-{
-	mutex_lock(&panel_list_mutex);
-	list_del(&dssdev->panel_list);
-	mutex_unlock(&panel_list_mutex);
-}
-EXPORT_SYMBOL(omapdss_unregister_display);
-
-struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev)
-{
-	if (!try_module_get(dssdev->owner))
-		return NULL;
-
-	if (get_device(dssdev->dev) == NULL) {
-		module_put(dssdev->owner);
-		return NULL;
-	}
-
-	return dssdev;
-}
-EXPORT_SYMBOL(omap_dss_get_device);
-
-void omap_dss_put_device(struct omap_dss_device *dssdev)
-{
-	put_device(dssdev->dev);
-	module_put(dssdev->owner);
-}
-EXPORT_SYMBOL(omap_dss_put_device);
-
-/*
- * ref count of the found device is incremented.
- * ref count of from-device is decremented.
- */
-struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
-{
-	struct list_head *l;
-	struct omap_dss_device *dssdev;
-
-	mutex_lock(&panel_list_mutex);
-
-	if (list_empty(&panel_list)) {
-		dssdev = NULL;
-		goto out;
-	}
-
-	if (from == NULL) {
-		dssdev = list_first_entry(&panel_list, struct omap_dss_device,
-				panel_list);
-		omap_dss_get_device(dssdev);
-		goto out;
-	}
-
-	omap_dss_put_device(from);
-
-	list_for_each(l, &panel_list) {
-		dssdev = list_entry(l, struct omap_dss_device, panel_list);
-		if (dssdev == from) {
-			if (list_is_last(l, &panel_list)) {
-				dssdev = NULL;
-				goto out;
-			}
-
-			dssdev = list_entry(l->next, struct omap_dss_device,
-					panel_list);
-			omap_dss_get_device(dssdev);
-			goto out;
-		}
-	}
-
-	WARN(1, "'from' dssdev not found\n");
-
-	dssdev = NULL;
-out:
-	mutex_unlock(&panel_list_mutex);
-	return dssdev;
-}
-EXPORT_SYMBOL(omap_dss_get_next_device);
-
-struct omap_dss_device *omap_dss_find_device(void *data,
-		int (*match)(struct omap_dss_device *dssdev, void *data))
-{
-	struct omap_dss_device *dssdev = NULL;
-
-	while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
-		if (match(dssdev, data))
-			return dssdev;
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(omap_dss_find_device);
-
-void videomode_to_omap_video_timings(const struct videomode *vm,
-		struct omap_video_timings *ovt)
-{
-	memset(ovt, 0, sizeof(*ovt));
-
-	ovt->pixelclock = vm->pixelclock;
-	ovt->x_res = vm->hactive;
-	ovt->hbp = vm->hback_porch;
-	ovt->hfp = vm->hfront_porch;
-	ovt->hsw = vm->hsync_len;
-	ovt->y_res = vm->vactive;
-	ovt->vbp = vm->vback_porch;
-	ovt->vfp = vm->vfront_porch;
-	ovt->vsw = vm->vsync_len;
-
-	ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
-		OMAPDSS_SIG_ACTIVE_HIGH :
-		OMAPDSS_SIG_ACTIVE_LOW;
-	ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
-		OMAPDSS_SIG_ACTIVE_HIGH :
-		OMAPDSS_SIG_ACTIVE_LOW;
-	ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ?
-		OMAPDSS_SIG_ACTIVE_HIGH :
-		OMAPDSS_SIG_ACTIVE_LOW;
-	ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
-		OMAPDSS_DRIVE_SIG_RISING_EDGE :
-		OMAPDSS_DRIVE_SIG_FALLING_EDGE;
-
-	ovt->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
-}
-EXPORT_SYMBOL(videomode_to_omap_video_timings);
-
-void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
-		struct videomode *vm)
-{
-	memset(vm, 0, sizeof(*vm));
-
-	vm->pixelclock = ovt->pixelclock;
-
-	vm->hactive = ovt->x_res;
-	vm->hback_porch = ovt->hbp;
-	vm->hfront_porch = ovt->hfp;
-	vm->hsync_len = ovt->hsw;
-	vm->vactive = ovt->y_res;
-	vm->vback_porch = ovt->vbp;
-	vm->vfront_porch = ovt->vfp;
-	vm->vsync_len = ovt->vsw;
-
-	if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
-	else
-		vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
-
-	if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
-	else
-		vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
-
-	if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		vm->flags |= DISPLAY_FLAGS_DE_HIGH;
-	else
-		vm->flags |= DISPLAY_FLAGS_DE_LOW;
-
-	if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE)
-		vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
-	else
-		vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
-}
-EXPORT_SYMBOL(omap_video_timings_to_videomode);
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
deleted file mode 100644
index 157921db447a..000000000000
--- a/drivers/video/omap2/dss/dpi.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dpi.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "DPI"
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/export.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/string.h>
-#include <linux/of.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-static struct {
-	struct platform_device *pdev;
-
-	struct regulator *vdds_dsi_reg;
-	struct platform_device *dsidev;
-
-	struct mutex lock;
-
-	struct omap_video_timings timings;
-	struct dss_lcd_mgr_config mgr_config;
-	int data_lines;
-
-	struct omap_dss_device output;
-
-	bool port_initialized;
-} dpi;
-
-static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
-{
-	/*
-	 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
-	 * would also be used for DISPC fclk. Meaning, when the DPI output is
-	 * disabled, DISPC clock will be disabled, and TV out will stop.
-	 */
-	switch (omapdss_get_version()) {
-	case OMAPDSS_VER_OMAP24xx:
-	case OMAPDSS_VER_OMAP34xx_ES1:
-	case OMAPDSS_VER_OMAP34xx_ES3:
-	case OMAPDSS_VER_OMAP3630:
-	case OMAPDSS_VER_AM35xx:
-		return NULL;
-
-	case OMAPDSS_VER_OMAP4430_ES1:
-	case OMAPDSS_VER_OMAP4430_ES2:
-	case OMAPDSS_VER_OMAP4:
-		switch (channel) {
-		case OMAP_DSS_CHANNEL_LCD:
-			return dsi_get_dsidev_from_id(0);
-		case OMAP_DSS_CHANNEL_LCD2:
-			return dsi_get_dsidev_from_id(1);
-		default:
-			return NULL;
-		}
-
-	case OMAPDSS_VER_OMAP5:
-		switch (channel) {
-		case OMAP_DSS_CHANNEL_LCD:
-			return dsi_get_dsidev_from_id(0);
-		case OMAP_DSS_CHANNEL_LCD3:
-			return dsi_get_dsidev_from_id(1);
-		default:
-			return NULL;
-		}
-
-	default:
-		return NULL;
-	}
-}
-
-static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
-{
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
-	case OMAP_DSS_CHANNEL_LCD2:
-		return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
-	default:
-		/* this shouldn't happen */
-		WARN_ON(1);
-		return OMAP_DSS_CLK_SRC_FCK;
-	}
-}
-
-struct dpi_clk_calc_ctx {
-	struct platform_device *dsidev;
-
-	/* inputs */
-
-	unsigned long pck_min, pck_max;
-
-	/* outputs */
-
-	struct dsi_clock_info dsi_cinfo;
-	unsigned long fck;
-	struct dispc_clock_info dispc_cinfo;
-};
-
-static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
-		unsigned long pck, void *data)
-{
-	struct dpi_clk_calc_ctx *ctx = data;
-
-	/*
-	 * Odd dividers give us uneven duty cycle, causing problem when level
-	 * shifted. So skip all odd dividers when the pixel clock is on the
-	 * higher side.
-	 */
-	if (ctx->pck_min >= 100000000) {
-		if (lckd > 1 && lckd % 2 != 0)
-			return false;
-
-		if (pckd > 1 && pckd % 2 != 0)
-			return false;
-	}
-
-	ctx->dispc_cinfo.lck_div = lckd;
-	ctx->dispc_cinfo.pck_div = pckd;
-	ctx->dispc_cinfo.lck = lck;
-	ctx->dispc_cinfo.pck = pck;
-
-	return true;
-}
-
-
-static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
-		void *data)
-{
-	struct dpi_clk_calc_ctx *ctx = data;
-
-	/*
-	 * Odd dividers give us uneven duty cycle, causing problem when level
-	 * shifted. So skip all odd dividers when the pixel clock is on the
-	 * higher side.
-	 */
-	if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 100000000)
-		return false;
-
-	ctx->dsi_cinfo.regm_dispc = regm_dispc;
-	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
-
-	return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
-			dpi_calc_dispc_cb, ctx);
-}
-
-
-static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
-		unsigned long pll,
-		void *data)
-{
-	struct dpi_clk_calc_ctx *ctx = data;
-
-	ctx->dsi_cinfo.regn = regn;
-	ctx->dsi_cinfo.regm = regm;
-	ctx->dsi_cinfo.fint = fint;
-	ctx->dsi_cinfo.clkin4ddr = pll;
-
-	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
-			dpi_calc_hsdiv_cb, ctx);
-}
-
-static bool dpi_calc_dss_cb(unsigned long fck, void *data)
-{
-	struct dpi_clk_calc_ctx *ctx = data;
-
-	ctx->fck = fck;
-
-	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
-			dpi_calc_dispc_cb, ctx);
-}
-
-static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
-{
-	unsigned long clkin;
-	unsigned long pll_min, pll_max;
-
-	clkin = dsi_get_pll_clkin(dpi.dsidev);
-
-	memset(ctx, 0, sizeof(*ctx));
-	ctx->dsidev = dpi.dsidev;
-	ctx->pck_min = pck - 1000;
-	ctx->pck_max = pck + 1000;
-	ctx->dsi_cinfo.clkin = clkin;
-
-	pll_min = 0;
-	pll_max = 0;
-
-	return dsi_pll_calc(dpi.dsidev, clkin,
-			pll_min, pll_max,
-			dpi_calc_pll_cb, ctx);
-}
-
-static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
-{
-	int i;
-
-	/*
-	 * DSS fck gives us very few possibilities, so finding a good pixel
-	 * clock may not be possible. We try multiple times to find the clock,
-	 * each time widening the pixel clock range we look for, up to
-	 * +/- ~15MHz.
-	 */
-
-	for (i = 0; i < 25; ++i) {
-		bool ok;
-
-		memset(ctx, 0, sizeof(*ctx));
-		if (pck > 1000 * i * i * i)
-			ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
-		else
-			ctx->pck_min = 0;
-		ctx->pck_max = pck + 1000 * i * i * i;
-
-		ok = dss_div_calc(pck, ctx->pck_min, dpi_calc_dss_cb, ctx);
-		if (ok)
-			return ok;
-	}
-
-	return false;
-}
-
-
-
-static int dpi_set_dsi_clk(enum omap_channel channel,
-		unsigned long pck_req, unsigned long *fck, int *lck_div,
-		int *pck_div)
-{
-	struct dpi_clk_calc_ctx ctx;
-	int r;
-	bool ok;
-
-	ok = dpi_dsi_clk_calc(pck_req, &ctx);
-	if (!ok)
-		return -EINVAL;
-
-	r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
-	if (r)
-		return r;
-
-	dss_select_lcd_clk_source(channel,
-			dpi_get_alt_clk_src(channel));
-
-	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
-
-	*fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
-	*lck_div = ctx.dispc_cinfo.lck_div;
-	*pck_div = ctx.dispc_cinfo.pck_div;
-
-	return 0;
-}
-
-static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
-		int *lck_div, int *pck_div)
-{
-	struct dpi_clk_calc_ctx ctx;
-	int r;
-	bool ok;
-
-	ok = dpi_dss_clk_calc(pck_req, &ctx);
-	if (!ok)
-		return -EINVAL;
-
-	r = dss_set_fck_rate(ctx.fck);
-	if (r)
-		return r;
-
-	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
-
-	*fck = ctx.fck;
-	*lck_div = ctx.dispc_cinfo.lck_div;
-	*pck_div = ctx.dispc_cinfo.pck_div;
-
-	return 0;
-}
-
-static int dpi_set_mode(struct omap_overlay_manager *mgr)
-{
-	struct omap_video_timings *t = &dpi.timings;
-	int lck_div = 0, pck_div = 0;
-	unsigned long fck = 0;
-	unsigned long pck;
-	int r = 0;
-
-	if (dpi.dsidev)
-		r = dpi_set_dsi_clk(mgr->id, t->pixelclock, &fck,
-				&lck_div, &pck_div);
-	else
-		r = dpi_set_dispc_clk(t->pixelclock, &fck,
-				&lck_div, &pck_div);
-	if (r)
-		return r;
-
-	pck = fck / lck_div / pck_div;
-
-	if (pck != t->pixelclock) {
-		DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
-			t->pixelclock, pck);
-
-		t->pixelclock = pck;
-	}
-
-	dss_mgr_set_timings(mgr, t);
-
-	return 0;
-}
-
-static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
-{
-	dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
-
-	dpi.mgr_config.stallmode = false;
-	dpi.mgr_config.fifohandcheck = false;
-
-	dpi.mgr_config.video_port_width = dpi.data_lines;
-
-	dpi.mgr_config.lcden_sig_polarity = 0;
-
-	dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
-}
-
-static int dpi_display_enable(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_device *out = &dpi.output;
-	int r;
-
-	mutex_lock(&dpi.lock);
-
-	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
-		DSSERR("no VDSS_DSI regulator\n");
-		r = -ENODEV;
-		goto err_no_reg;
-	}
-
-	if (out == NULL || out->manager == NULL) {
-		DSSERR("failed to enable display: no output/manager\n");
-		r = -ENODEV;
-		goto err_no_out_mgr;
-	}
-
-	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
-		r = regulator_enable(dpi.vdds_dsi_reg);
-		if (r)
-			goto err_reg_enable;
-	}
-
-	r = dispc_runtime_get();
-	if (r)
-		goto err_get_dispc;
-
-	r = dss_dpi_select_source(out->manager->id);
-	if (r)
-		goto err_src_sel;
-
-	if (dpi.dsidev) {
-		r = dsi_runtime_get(dpi.dsidev);
-		if (r)
-			goto err_get_dsi;
-
-		r = dsi_pll_init(dpi.dsidev, 0, 1);
-		if (r)
-			goto err_dsi_pll_init;
-	}
-
-	r = dpi_set_mode(out->manager);
-	if (r)
-		goto err_set_mode;
-
-	dpi_config_lcd_manager(out->manager);
-
-	mdelay(2);
-
-	r = dss_mgr_enable(out->manager);
-	if (r)
-		goto err_mgr_enable;
-
-	mutex_unlock(&dpi.lock);
-
-	return 0;
-
-err_mgr_enable:
-err_set_mode:
-	if (dpi.dsidev)
-		dsi_pll_uninit(dpi.dsidev, true);
-err_dsi_pll_init:
-	if (dpi.dsidev)
-		dsi_runtime_put(dpi.dsidev);
-err_get_dsi:
-err_src_sel:
-	dispc_runtime_put();
-err_get_dispc:
-	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
-		regulator_disable(dpi.vdds_dsi_reg);
-err_reg_enable:
-err_no_out_mgr:
-err_no_reg:
-	mutex_unlock(&dpi.lock);
-	return r;
-}
-
-static void dpi_display_disable(struct omap_dss_device *dssdev)
-{
-	struct omap_overlay_manager *mgr = dpi.output.manager;
-
-	mutex_lock(&dpi.lock);
-
-	dss_mgr_disable(mgr);
-
-	if (dpi.dsidev) {
-		dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
-		dsi_pll_uninit(dpi.dsidev, true);
-		dsi_runtime_put(dpi.dsidev);
-	}
-
-	dispc_runtime_put();
-
-	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
-		regulator_disable(dpi.vdds_dsi_reg);
-
-	mutex_unlock(&dpi.lock);
-}
-
-static void dpi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	DSSDBG("dpi_set_timings\n");
-
-	mutex_lock(&dpi.lock);
-
-	dpi.timings = *timings;
-
-	mutex_unlock(&dpi.lock);
-}
-
-static void dpi_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	mutex_lock(&dpi.lock);
-
-	*timings = dpi.timings;
-
-	mutex_unlock(&dpi.lock);
-}
-
-static int dpi_check_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings)
-{
-	struct omap_overlay_manager *mgr = dpi.output.manager;
-	int lck_div, pck_div;
-	unsigned long fck;
-	unsigned long pck;
-	struct dpi_clk_calc_ctx ctx;
-	bool ok;
-
-	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
-		return -EINVAL;
-
-	if (timings->pixelclock == 0)
-		return -EINVAL;
-
-	if (dpi.dsidev) {
-		ok = dpi_dsi_clk_calc(timings->pixelclock, &ctx);
-		if (!ok)
-			return -EINVAL;
-
-		fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
-	} else {
-		ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
-		if (!ok)
-			return -EINVAL;
-
-		fck = ctx.fck;
-	}
-
-	lck_div = ctx.dispc_cinfo.lck_div;
-	pck_div = ctx.dispc_cinfo.pck_div;
-
-	pck = fck / lck_div / pck_div;
-
-	timings->pixelclock = pck;
-
-	return 0;
-}
-
-static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
-{
-	mutex_lock(&dpi.lock);
-
-	dpi.data_lines = data_lines;
-
-	mutex_unlock(&dpi.lock);
-}
-
-static int dpi_verify_dsi_pll(struct platform_device *dsidev)
-{
-	int r;
-
-	/* do initial setup with the PLL to see if it is operational */
-
-	r = dsi_runtime_get(dsidev);
-	if (r)
-		return r;
-
-	r = dsi_pll_init(dsidev, 0, 1);
-	if (r) {
-		dsi_runtime_put(dsidev);
-		return r;
-	}
-
-	dsi_pll_uninit(dsidev, true);
-	dsi_runtime_put(dsidev);
-
-	return 0;
-}
-
-static int dpi_init_regulator(void)
-{
-	struct regulator *vdds_dsi;
-
-	if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
-		return 0;
-
-	if (dpi.vdds_dsi_reg)
-		return 0;
-
-	vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi");
-	if (IS_ERR(vdds_dsi)) {
-		if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
-			DSSERR("can't get VDDS_DSI regulator\n");
-		return PTR_ERR(vdds_dsi);
-	}
-
-	dpi.vdds_dsi_reg = vdds_dsi;
-
-	return 0;
-}
-
-static void dpi_init_pll(void)
-{
-	struct platform_device *dsidev;
-
-	if (dpi.dsidev)
-		return;
-
-	dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
-	if (!dsidev)
-		return;
-
-	if (dpi_verify_dsi_pll(dsidev)) {
-		DSSWARN("DSI PLL not operational\n");
-		return;
-	}
-
-	dpi.dsidev = dsidev;
-}
-
-/*
- * Return a hardcoded channel for the DPI output. This should work for
- * current use cases, but this can be later expanded to either resolve
- * the channel in some more dynamic manner, or get the channel as a user
- * parameter.
- */
-static enum omap_channel dpi_get_channel(void)
-{
-	switch (omapdss_get_version()) {
-	case OMAPDSS_VER_OMAP24xx:
-	case OMAPDSS_VER_OMAP34xx_ES1:
-	case OMAPDSS_VER_OMAP34xx_ES3:
-	case OMAPDSS_VER_OMAP3630:
-	case OMAPDSS_VER_AM35xx:
-		return OMAP_DSS_CHANNEL_LCD;
-
-	case OMAPDSS_VER_OMAP4430_ES1:
-	case OMAPDSS_VER_OMAP4430_ES2:
-	case OMAPDSS_VER_OMAP4:
-		return OMAP_DSS_CHANNEL_LCD2;
-
-	case OMAPDSS_VER_OMAP5:
-		return OMAP_DSS_CHANNEL_LCD3;
-
-	default:
-		DSSWARN("unsupported DSS version\n");
-		return OMAP_DSS_CHANNEL_LCD;
-	}
-}
-
-static int dpi_connect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct omap_overlay_manager *mgr;
-	int r;
-
-	r = dpi_init_regulator();
-	if (r)
-		return r;
-
-	dpi_init_pll();
-
-	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
-	if (!mgr)
-		return -ENODEV;
-
-	r = dss_mgr_connect(mgr, dssdev);
-	if (r)
-		return r;
-
-	r = omapdss_output_set_device(dssdev, dst);
-	if (r) {
-		DSSERR("failed to connect output to new device: %s\n",
-				dst->name);
-		dss_mgr_disconnect(mgr, dssdev);
-		return r;
-	}
-
-	return 0;
-}
-
-static void dpi_disconnect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	WARN_ON(dst != dssdev->dst);
-
-	if (dst != dssdev->dst)
-		return;
-
-	omapdss_output_unset_device(dssdev);
-
-	if (dssdev->manager)
-		dss_mgr_disconnect(dssdev->manager, dssdev);
-}
-
-static const struct omapdss_dpi_ops dpi_ops = {
-	.connect = dpi_connect,
-	.disconnect = dpi_disconnect,
-
-	.enable = dpi_display_enable,
-	.disable = dpi_display_disable,
-
-	.check_timings = dpi_check_timings,
-	.set_timings = dpi_set_timings,
-	.get_timings = dpi_get_timings,
-
-	.set_data_lines = dpi_set_data_lines,
-};
-
-static void dpi_init_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &dpi.output;
-
-	out->dev = &pdev->dev;
-	out->id = OMAP_DSS_OUTPUT_DPI;
-	out->output_type = OMAP_DISPLAY_TYPE_DPI;
-	out->name = "dpi.0";
-	out->dispc_channel = dpi_get_channel();
-	out->ops.dpi = &dpi_ops;
-	out->owner = THIS_MODULE;
-
-	omapdss_register_output(out);
-}
-
-static void __exit dpi_uninit_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &dpi.output;
-
-	omapdss_unregister_output(out);
-}
-
-static int omap_dpi_probe(struct platform_device *pdev)
-{
-	dpi.pdev = pdev;
-
-	mutex_init(&dpi.lock);
-
-	dpi_init_output(pdev);
-
-	return 0;
-}
-
-static int __exit omap_dpi_remove(struct platform_device *pdev)
-{
-	dpi_uninit_output(pdev);
-
-	return 0;
-}
-
-static struct platform_driver omap_dpi_driver = {
-	.probe		= omap_dpi_probe,
-	.remove         = __exit_p(omap_dpi_remove),
-	.driver         = {
-		.name   = "omapdss_dpi",
-		.owner  = THIS_MODULE,
-	},
-};
-
-int __init dpi_init_platform_driver(void)
-{
-	return platform_driver_register(&omap_dpi_driver);
-}
-
-void __exit dpi_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omap_dpi_driver);
-}
-
-int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
-{
-	struct device_node *ep;
-	u32 datalines;
-	int r;
-
-	ep = omapdss_of_get_next_endpoint(port, NULL);
-	if (!ep)
-		return 0;
-
-	r = of_property_read_u32(ep, "data-lines", &datalines);
-	if (r) {
-		DSSERR("failed to parse datalines\n");
-		goto err_datalines;
-	}
-
-	dpi.data_lines = datalines;
-
-	of_node_put(ep);
-
-	dpi.pdev = pdev;
-
-	mutex_init(&dpi.lock);
-
-	dpi_init_output(pdev);
-
-	dpi.port_initialized = true;
-
-	return 0;
-
-err_datalines:
-	of_node_put(ep);
-
-	return r;
-}
-
-void __exit dpi_uninit_port(void)
-{
-	if (!dpi.port_initialized)
-		return;
-
-	dpi_uninit_output(dpi.pdev);
-}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
deleted file mode 100644
index 121d1049d0bc..000000000000
--- a/drivers/video/omap2/dss/dsi.c
+++ /dev/null
@@ -1,5731 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dsi.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "DSI"
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/semaphore.h>
-#include <linux/seq_file.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-#include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-
-#include <video/omapdss.h>
-#include <video/mipi_display.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-#define DSI_CATCH_MISSING_TE
-
-struct dsi_reg { u16 module; u16 idx; };
-
-#define DSI_REG(mod, idx)		((const struct dsi_reg) { mod, idx })
-
-/* DSI Protocol Engine */
-
-#define DSI_PROTO			0
-#define DSI_PROTO_SZ			0x200
-
-#define DSI_REVISION			DSI_REG(DSI_PROTO, 0x0000)
-#define DSI_SYSCONFIG			DSI_REG(DSI_PROTO, 0x0010)
-#define DSI_SYSSTATUS			DSI_REG(DSI_PROTO, 0x0014)
-#define DSI_IRQSTATUS			DSI_REG(DSI_PROTO, 0x0018)
-#define DSI_IRQENABLE			DSI_REG(DSI_PROTO, 0x001C)
-#define DSI_CTRL			DSI_REG(DSI_PROTO, 0x0040)
-#define DSI_GNQ				DSI_REG(DSI_PROTO, 0x0044)
-#define DSI_COMPLEXIO_CFG1		DSI_REG(DSI_PROTO, 0x0048)
-#define DSI_COMPLEXIO_IRQ_STATUS	DSI_REG(DSI_PROTO, 0x004C)
-#define DSI_COMPLEXIO_IRQ_ENABLE	DSI_REG(DSI_PROTO, 0x0050)
-#define DSI_CLK_CTRL			DSI_REG(DSI_PROTO, 0x0054)
-#define DSI_TIMING1			DSI_REG(DSI_PROTO, 0x0058)
-#define DSI_TIMING2			DSI_REG(DSI_PROTO, 0x005C)
-#define DSI_VM_TIMING1			DSI_REG(DSI_PROTO, 0x0060)
-#define DSI_VM_TIMING2			DSI_REG(DSI_PROTO, 0x0064)
-#define DSI_VM_TIMING3			DSI_REG(DSI_PROTO, 0x0068)
-#define DSI_CLK_TIMING			DSI_REG(DSI_PROTO, 0x006C)
-#define DSI_TX_FIFO_VC_SIZE		DSI_REG(DSI_PROTO, 0x0070)
-#define DSI_RX_FIFO_VC_SIZE		DSI_REG(DSI_PROTO, 0x0074)
-#define DSI_COMPLEXIO_CFG2		DSI_REG(DSI_PROTO, 0x0078)
-#define DSI_RX_FIFO_VC_FULLNESS		DSI_REG(DSI_PROTO, 0x007C)
-#define DSI_VM_TIMING4			DSI_REG(DSI_PROTO, 0x0080)
-#define DSI_TX_FIFO_VC_EMPTINESS	DSI_REG(DSI_PROTO, 0x0084)
-#define DSI_VM_TIMING5			DSI_REG(DSI_PROTO, 0x0088)
-#define DSI_VM_TIMING6			DSI_REG(DSI_PROTO, 0x008C)
-#define DSI_VM_TIMING7			DSI_REG(DSI_PROTO, 0x0090)
-#define DSI_STOPCLK_TIMING		DSI_REG(DSI_PROTO, 0x0094)
-#define DSI_VC_CTRL(n)			DSI_REG(DSI_PROTO, 0x0100 + (n * 0x20))
-#define DSI_VC_TE(n)			DSI_REG(DSI_PROTO, 0x0104 + (n * 0x20))
-#define DSI_VC_LONG_PACKET_HEADER(n)	DSI_REG(DSI_PROTO, 0x0108 + (n * 0x20))
-#define DSI_VC_LONG_PACKET_PAYLOAD(n)	DSI_REG(DSI_PROTO, 0x010C + (n * 0x20))
-#define DSI_VC_SHORT_PACKET_HEADER(n)	DSI_REG(DSI_PROTO, 0x0110 + (n * 0x20))
-#define DSI_VC_IRQSTATUS(n)		DSI_REG(DSI_PROTO, 0x0118 + (n * 0x20))
-#define DSI_VC_IRQENABLE(n)		DSI_REG(DSI_PROTO, 0x011C + (n * 0x20))
-
-/* DSIPHY_SCP */
-
-#define DSI_PHY				1
-#define DSI_PHY_OFFSET			0x200
-#define DSI_PHY_SZ			0x40
-
-#define DSI_DSIPHY_CFG0			DSI_REG(DSI_PHY, 0x0000)
-#define DSI_DSIPHY_CFG1			DSI_REG(DSI_PHY, 0x0004)
-#define DSI_DSIPHY_CFG2			DSI_REG(DSI_PHY, 0x0008)
-#define DSI_DSIPHY_CFG5			DSI_REG(DSI_PHY, 0x0014)
-#define DSI_DSIPHY_CFG10		DSI_REG(DSI_PHY, 0x0028)
-
-/* DSI_PLL_CTRL_SCP */
-
-#define DSI_PLL				2
-#define DSI_PLL_OFFSET			0x300
-#define DSI_PLL_SZ			0x20
-
-#define DSI_PLL_CONTROL			DSI_REG(DSI_PLL, 0x0000)
-#define DSI_PLL_STATUS			DSI_REG(DSI_PLL, 0x0004)
-#define DSI_PLL_GO			DSI_REG(DSI_PLL, 0x0008)
-#define DSI_PLL_CONFIGURATION1		DSI_REG(DSI_PLL, 0x000C)
-#define DSI_PLL_CONFIGURATION2		DSI_REG(DSI_PLL, 0x0010)
-
-#define REG_GET(dsidev, idx, start, end) \
-	FLD_GET(dsi_read_reg(dsidev, idx), start, end)
-
-#define REG_FLD_MOD(dsidev, idx, val, start, end) \
-	dsi_write_reg(dsidev, idx, FLD_MOD(dsi_read_reg(dsidev, idx), val, start, end))
-
-/* Global interrupts */
-#define DSI_IRQ_VC0		(1 << 0)
-#define DSI_IRQ_VC1		(1 << 1)
-#define DSI_IRQ_VC2		(1 << 2)
-#define DSI_IRQ_VC3		(1 << 3)
-#define DSI_IRQ_WAKEUP		(1 << 4)
-#define DSI_IRQ_RESYNC		(1 << 5)
-#define DSI_IRQ_PLL_LOCK	(1 << 7)
-#define DSI_IRQ_PLL_UNLOCK	(1 << 8)
-#define DSI_IRQ_PLL_RECALL	(1 << 9)
-#define DSI_IRQ_COMPLEXIO_ERR	(1 << 10)
-#define DSI_IRQ_HS_TX_TIMEOUT	(1 << 14)
-#define DSI_IRQ_LP_RX_TIMEOUT	(1 << 15)
-#define DSI_IRQ_TE_TRIGGER	(1 << 16)
-#define DSI_IRQ_ACK_TRIGGER	(1 << 17)
-#define DSI_IRQ_SYNC_LOST	(1 << 18)
-#define DSI_IRQ_LDO_POWER_GOOD	(1 << 19)
-#define DSI_IRQ_TA_TIMEOUT	(1 << 20)
-#define DSI_IRQ_ERROR_MASK \
-	(DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
-	DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST)
-#define DSI_IRQ_CHANNEL_MASK	0xf
-
-/* Virtual channel interrupts */
-#define DSI_VC_IRQ_CS		(1 << 0)
-#define DSI_VC_IRQ_ECC_CORR	(1 << 1)
-#define DSI_VC_IRQ_PACKET_SENT	(1 << 2)
-#define DSI_VC_IRQ_FIFO_TX_OVF	(1 << 3)
-#define DSI_VC_IRQ_FIFO_RX_OVF	(1 << 4)
-#define DSI_VC_IRQ_BTA		(1 << 5)
-#define DSI_VC_IRQ_ECC_NO_CORR	(1 << 6)
-#define DSI_VC_IRQ_FIFO_TX_UDF	(1 << 7)
-#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
-#define DSI_VC_IRQ_ERROR_MASK \
-	(DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
-	DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
-	DSI_VC_IRQ_FIFO_TX_UDF)
-
-/* ComplexIO interrupts */
-#define DSI_CIO_IRQ_ERRSYNCESC1		(1 << 0)
-#define DSI_CIO_IRQ_ERRSYNCESC2		(1 << 1)
-#define DSI_CIO_IRQ_ERRSYNCESC3		(1 << 2)
-#define DSI_CIO_IRQ_ERRSYNCESC4		(1 << 3)
-#define DSI_CIO_IRQ_ERRSYNCESC5		(1 << 4)
-#define DSI_CIO_IRQ_ERRESC1		(1 << 5)
-#define DSI_CIO_IRQ_ERRESC2		(1 << 6)
-#define DSI_CIO_IRQ_ERRESC3		(1 << 7)
-#define DSI_CIO_IRQ_ERRESC4		(1 << 8)
-#define DSI_CIO_IRQ_ERRESC5		(1 << 9)
-#define DSI_CIO_IRQ_ERRCONTROL1		(1 << 10)
-#define DSI_CIO_IRQ_ERRCONTROL2		(1 << 11)
-#define DSI_CIO_IRQ_ERRCONTROL3		(1 << 12)
-#define DSI_CIO_IRQ_ERRCONTROL4		(1 << 13)
-#define DSI_CIO_IRQ_ERRCONTROL5		(1 << 14)
-#define DSI_CIO_IRQ_STATEULPS1		(1 << 15)
-#define DSI_CIO_IRQ_STATEULPS2		(1 << 16)
-#define DSI_CIO_IRQ_STATEULPS3		(1 << 17)
-#define DSI_CIO_IRQ_STATEULPS4		(1 << 18)
-#define DSI_CIO_IRQ_STATEULPS5		(1 << 19)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1	(1 << 20)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1	(1 << 21)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2	(1 << 22)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2	(1 << 23)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3	(1 << 24)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3	(1 << 25)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP0_4	(1 << 26)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP1_4	(1 << 27)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP0_5	(1 << 28)
-#define DSI_CIO_IRQ_ERRCONTENTIONLP1_5	(1 << 29)
-#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0	(1 << 30)
-#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1	(1 << 31)
-#define DSI_CIO_IRQ_ERROR_MASK \
-	(DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
-	 DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRSYNCESC4 | \
-	 DSI_CIO_IRQ_ERRSYNCESC5 | \
-	 DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
-	 DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRESC4 | \
-	 DSI_CIO_IRQ_ERRESC5 | \
-	 DSI_CIO_IRQ_ERRCONTROL1 | DSI_CIO_IRQ_ERRCONTROL2 | \
-	 DSI_CIO_IRQ_ERRCONTROL3 | DSI_CIO_IRQ_ERRCONTROL4 | \
-	 DSI_CIO_IRQ_ERRCONTROL5 | \
-	 DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
-	 DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
-	 DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3 | \
-	 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
-	 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
-
-typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
-
-static int dsi_display_init_dispc(struct platform_device *dsidev,
-	struct omap_overlay_manager *mgr);
-static void dsi_display_uninit_dispc(struct platform_device *dsidev,
-	struct omap_overlay_manager *mgr);
-
-static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
-
-#define DSI_MAX_NR_ISRS                2
-#define DSI_MAX_NR_LANES	5
-
-enum dsi_lane_function {
-	DSI_LANE_UNUSED	= 0,
-	DSI_LANE_CLK,
-	DSI_LANE_DATA1,
-	DSI_LANE_DATA2,
-	DSI_LANE_DATA3,
-	DSI_LANE_DATA4,
-};
-
-struct dsi_lane_config {
-	enum dsi_lane_function function;
-	u8 polarity;
-};
-
-struct dsi_isr_data {
-	omap_dsi_isr_t	isr;
-	void		*arg;
-	u32		mask;
-};
-
-enum fifo_size {
-	DSI_FIFO_SIZE_0		= 0,
-	DSI_FIFO_SIZE_32	= 1,
-	DSI_FIFO_SIZE_64	= 2,
-	DSI_FIFO_SIZE_96	= 3,
-	DSI_FIFO_SIZE_128	= 4,
-};
-
-enum dsi_vc_source {
-	DSI_VC_SOURCE_L4 = 0,
-	DSI_VC_SOURCE_VP,
-};
-
-struct dsi_irq_stats {
-	unsigned long last_reset;
-	unsigned irq_count;
-	unsigned dsi_irqs[32];
-	unsigned vc_irqs[4][32];
-	unsigned cio_irqs[32];
-};
-
-struct dsi_isr_tables {
-	struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
-	struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
-	struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
-};
-
-struct dsi_clk_calc_ctx {
-	struct platform_device *dsidev;
-
-	/* inputs */
-
-	const struct omap_dss_dsi_config *config;
-
-	unsigned long req_pck_min, req_pck_nom, req_pck_max;
-
-	/* outputs */
-
-	struct dsi_clock_info dsi_cinfo;
-	struct dispc_clock_info dispc_cinfo;
-
-	struct omap_video_timings dispc_vm;
-	struct omap_dss_dsi_videomode_timings dsi_vm;
-};
-
-struct dsi_data {
-	struct platform_device *pdev;
-	void __iomem *proto_base;
-	void __iomem *phy_base;
-	void __iomem *pll_base;
-
-	int module_id;
-
-	int irq;
-
-	struct clk *dss_clk;
-	struct clk *sys_clk;
-
-	struct dispc_clock_info user_dispc_cinfo;
-	struct dsi_clock_info user_dsi_cinfo;
-
-	struct dsi_clock_info current_cinfo;
-
-	bool vdds_dsi_enabled;
-	struct regulator *vdds_dsi_reg;
-
-	struct {
-		enum dsi_vc_source source;
-		struct omap_dss_device *dssdev;
-		enum fifo_size tx_fifo_size;
-		enum fifo_size rx_fifo_size;
-		int vc_id;
-	} vc[4];
-
-	struct mutex lock;
-	struct semaphore bus_lock;
-
-	unsigned pll_locked;
-
-	spinlock_t irq_lock;
-	struct dsi_isr_tables isr_tables;
-	/* space for a copy used by the interrupt handler */
-	struct dsi_isr_tables isr_tables_copy;
-
-	int update_channel;
-#ifdef DSI_PERF_MEASURE
-	unsigned update_bytes;
-#endif
-
-	bool te_enabled;
-	bool ulps_enabled;
-
-	void (*framedone_callback)(int, void *);
-	void *framedone_data;
-
-	struct delayed_work framedone_timeout_work;
-
-#ifdef DSI_CATCH_MISSING_TE
-	struct timer_list te_timer;
-#endif
-
-	unsigned long cache_req_pck;
-	unsigned long cache_clk_freq;
-	struct dsi_clock_info cache_cinfo;
-
-	u32		errors;
-	spinlock_t	errors_lock;
-#ifdef DSI_PERF_MEASURE
-	ktime_t perf_setup_time;
-	ktime_t perf_start_time;
-#endif
-	int debug_read;
-	int debug_write;
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spinlock_t irq_stats_lock;
-	struct dsi_irq_stats irq_stats;
-#endif
-	/* DSI PLL Parameter Ranges */
-	unsigned long regm_max, regn_max;
-	unsigned long  regm_dispc_max, regm_dsi_max;
-	unsigned long  fint_min, fint_max;
-	unsigned long lpdiv_max;
-
-	unsigned num_lanes_supported;
-	unsigned line_buffer_size;
-
-	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
-	unsigned num_lanes_used;
-
-	unsigned scp_clk_refcount;
-
-	struct dss_lcd_mgr_config mgr_config;
-	struct omap_video_timings timings;
-	enum omap_dss_dsi_pixel_format pix_fmt;
-	enum omap_dss_dsi_mode mode;
-	struct omap_dss_dsi_videomode_timings vm_timings;
-
-	struct omap_dss_device output;
-};
-
-struct dsi_packet_sent_handler_data {
-	struct platform_device *dsidev;
-	struct completion *completion;
-};
-
-struct dsi_module_id_data {
-	u32 address;
-	int id;
-};
-
-static const struct of_device_id dsi_of_match[];
-
-#ifdef DSI_PERF_MEASURE
-static bool dsi_perf;
-module_param(dsi_perf, bool, 0644);
-#endif
-
-static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev)
-{
-	return dev_get_drvdata(&dsidev->dev);
-}
-
-static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
-{
-	return to_platform_device(dssdev->dev);
-}
-
-struct platform_device *dsi_get_dsidev_from_id(int module)
-{
-	struct omap_dss_device *out;
-	enum omap_dss_output_id	id;
-
-	switch (module) {
-	case 0:
-		id = OMAP_DSS_OUTPUT_DSI1;
-		break;
-	case 1:
-		id = OMAP_DSS_OUTPUT_DSI2;
-		break;
-	default:
-		return NULL;
-	}
-
-	out = omap_dss_get_output(id);
-
-	return out ? to_platform_device(out->dev) : NULL;
-}
-
-static inline void dsi_write_reg(struct platform_device *dsidev,
-		const struct dsi_reg idx, u32 val)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	void __iomem *base;
-
-	switch(idx.module) {
-		case DSI_PROTO: base = dsi->proto_base; break;
-		case DSI_PHY: base = dsi->phy_base; break;
-		case DSI_PLL: base = dsi->pll_base; break;
-		default: return;
-	}
-
-	__raw_writel(val, base + idx.idx);
-}
-
-static inline u32 dsi_read_reg(struct platform_device *dsidev,
-		const struct dsi_reg idx)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	void __iomem *base;
-
-	switch(idx.module) {
-		case DSI_PROTO: base = dsi->proto_base; break;
-		case DSI_PHY: base = dsi->phy_base; break;
-		case DSI_PLL: base = dsi->pll_base; break;
-		default: return 0;
-	}
-
-	return __raw_readl(base + idx.idx);
-}
-
-static void dsi_bus_lock(struct omap_dss_device *dssdev)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	down(&dsi->bus_lock);
-}
-
-static void dsi_bus_unlock(struct omap_dss_device *dssdev)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	up(&dsi->bus_lock);
-}
-
-static bool dsi_bus_is_locked(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	return dsi->bus_lock.count == 0;
-}
-
-static void dsi_completion_handler(void *data, u32 mask)
-{
-	complete((struct completion *)data);
-}
-
-static inline int wait_for_bit_change(struct platform_device *dsidev,
-		const struct dsi_reg idx, int bitnum, int value)
-{
-	unsigned long timeout;
-	ktime_t wait;
-	int t;
-
-	/* first busyloop to see if the bit changes right away */
-	t = 100;
-	while (t-- > 0) {
-		if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
-			return value;
-	}
-
-	/* then loop for 500ms, sleeping for 1ms in between */
-	timeout = jiffies + msecs_to_jiffies(500);
-	while (time_before(jiffies, timeout)) {
-		if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
-			return value;
-
-		wait = ns_to_ktime(1000 * 1000);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
-	}
-
-	return !value;
-}
-
-u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
-{
-	switch (fmt) {
-	case OMAP_DSS_DSI_FMT_RGB888:
-	case OMAP_DSS_DSI_FMT_RGB666:
-		return 24;
-	case OMAP_DSS_DSI_FMT_RGB666_PACKED:
-		return 18;
-	case OMAP_DSS_DSI_FMT_RGB565:
-		return 16;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-#ifdef DSI_PERF_MEASURE
-static void dsi_perf_mark_setup(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	dsi->perf_setup_time = ktime_get();
-}
-
-static void dsi_perf_mark_start(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	dsi->perf_start_time = ktime_get();
-}
-
-static void dsi_perf_show(struct platform_device *dsidev, const char *name)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	ktime_t t, setup_time, trans_time;
-	u32 total_bytes;
-	u32 setup_us, trans_us, total_us;
-
-	if (!dsi_perf)
-		return;
-
-	t = ktime_get();
-
-	setup_time = ktime_sub(dsi->perf_start_time, dsi->perf_setup_time);
-	setup_us = (u32)ktime_to_us(setup_time);
-	if (setup_us == 0)
-		setup_us = 1;
-
-	trans_time = ktime_sub(t, dsi->perf_start_time);
-	trans_us = (u32)ktime_to_us(trans_time);
-	if (trans_us == 0)
-		trans_us = 1;
-
-	total_us = setup_us + trans_us;
-
-	total_bytes = dsi->update_bytes;
-
-	printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
-			"%u bytes, %u kbytes/sec\n",
-			name,
-			setup_us,
-			trans_us,
-			total_us,
-			1000*1000 / total_us,
-			total_bytes,
-			total_bytes * 1000 / total_us);
-}
-#else
-static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
-{
-}
-
-static inline void dsi_perf_mark_start(struct platform_device *dsidev)
-{
-}
-
-static inline void dsi_perf_show(struct platform_device *dsidev,
-		const char *name)
-{
-}
-#endif
-
-static int verbose_irq;
-
-static void print_irq_status(u32 status)
-{
-	if (status == 0)
-		return;
-
-	if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
-		return;
-
-#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
-
-	pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-		status,
-		verbose_irq ? PIS(VC0) : "",
-		verbose_irq ? PIS(VC1) : "",
-		verbose_irq ? PIS(VC2) : "",
-		verbose_irq ? PIS(VC3) : "",
-		PIS(WAKEUP),
-		PIS(RESYNC),
-		PIS(PLL_LOCK),
-		PIS(PLL_UNLOCK),
-		PIS(PLL_RECALL),
-		PIS(COMPLEXIO_ERR),
-		PIS(HS_TX_TIMEOUT),
-		PIS(LP_RX_TIMEOUT),
-		PIS(TE_TRIGGER),
-		PIS(ACK_TRIGGER),
-		PIS(SYNC_LOST),
-		PIS(LDO_POWER_GOOD),
-		PIS(TA_TIMEOUT));
-#undef PIS
-}
-
-static void print_irq_status_vc(int channel, u32 status)
-{
-	if (status == 0)
-		return;
-
-	if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
-		return;
-
-#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
-
-	pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
-		channel,
-		status,
-		PIS(CS),
-		PIS(ECC_CORR),
-		PIS(ECC_NO_CORR),
-		verbose_irq ? PIS(PACKET_SENT) : "",
-		PIS(BTA),
-		PIS(FIFO_TX_OVF),
-		PIS(FIFO_RX_OVF),
-		PIS(FIFO_TX_UDF),
-		PIS(PP_BUSY_CHANGE));
-#undef PIS
-}
-
-static void print_irq_status_cio(u32 status)
-{
-	if (status == 0)
-		return;
-
-#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
-
-	pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-		status,
-		PIS(ERRSYNCESC1),
-		PIS(ERRSYNCESC2),
-		PIS(ERRSYNCESC3),
-		PIS(ERRESC1),
-		PIS(ERRESC2),
-		PIS(ERRESC3),
-		PIS(ERRCONTROL1),
-		PIS(ERRCONTROL2),
-		PIS(ERRCONTROL3),
-		PIS(STATEULPS1),
-		PIS(STATEULPS2),
-		PIS(STATEULPS3),
-		PIS(ERRCONTENTIONLP0_1),
-		PIS(ERRCONTENTIONLP1_1),
-		PIS(ERRCONTENTIONLP0_2),
-		PIS(ERRCONTENTIONLP1_2),
-		PIS(ERRCONTENTIONLP0_3),
-		PIS(ERRCONTENTIONLP1_3),
-		PIS(ULPSACTIVENOT_ALL0),
-		PIS(ULPSACTIVENOT_ALL1));
-#undef PIS
-}
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-static void dsi_collect_irq_stats(struct platform_device *dsidev, u32 irqstatus,
-		u32 *vcstatus, u32 ciostatus)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int i;
-
-	spin_lock(&dsi->irq_stats_lock);
-
-	dsi->irq_stats.irq_count++;
-	dss_collect_irq_stats(irqstatus, dsi->irq_stats.dsi_irqs);
-
-	for (i = 0; i < 4; ++i)
-		dss_collect_irq_stats(vcstatus[i], dsi->irq_stats.vc_irqs[i]);
-
-	dss_collect_irq_stats(ciostatus, dsi->irq_stats.cio_irqs);
-
-	spin_unlock(&dsi->irq_stats_lock);
-}
-#else
-#define dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus)
-#endif
-
-static int debug_irq;
-
-static void dsi_handle_irq_errors(struct platform_device *dsidev, u32 irqstatus,
-		u32 *vcstatus, u32 ciostatus)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int i;
-
-	if (irqstatus & DSI_IRQ_ERROR_MASK) {
-		DSSERR("DSI error, irqstatus %x\n", irqstatus);
-		print_irq_status(irqstatus);
-		spin_lock(&dsi->errors_lock);
-		dsi->errors |= irqstatus & DSI_IRQ_ERROR_MASK;
-		spin_unlock(&dsi->errors_lock);
-	} else if (debug_irq) {
-		print_irq_status(irqstatus);
-	}
-
-	for (i = 0; i < 4; ++i) {
-		if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
-			DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
-				       i, vcstatus[i]);
-			print_irq_status_vc(i, vcstatus[i]);
-		} else if (debug_irq) {
-			print_irq_status_vc(i, vcstatus[i]);
-		}
-	}
-
-	if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
-		DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
-		print_irq_status_cio(ciostatus);
-	} else if (debug_irq) {
-		print_irq_status_cio(ciostatus);
-	}
-}
-
-static void dsi_call_isrs(struct dsi_isr_data *isr_array,
-		unsigned isr_array_size, u32 irqstatus)
-{
-	struct dsi_isr_data *isr_data;
-	int i;
-
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
-		if (isr_data->isr && isr_data->mask & irqstatus)
-			isr_data->isr(isr_data->arg, irqstatus);
-	}
-}
-
-static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
-		u32 irqstatus, u32 *vcstatus, u32 ciostatus)
-{
-	int i;
-
-	dsi_call_isrs(isr_tables->isr_table,
-			ARRAY_SIZE(isr_tables->isr_table),
-			irqstatus);
-
-	for (i = 0; i < 4; ++i) {
-		if (vcstatus[i] == 0)
-			continue;
-		dsi_call_isrs(isr_tables->isr_table_vc[i],
-				ARRAY_SIZE(isr_tables->isr_table_vc[i]),
-				vcstatus[i]);
-	}
-
-	if (ciostatus != 0)
-		dsi_call_isrs(isr_tables->isr_table_cio,
-				ARRAY_SIZE(isr_tables->isr_table_cio),
-				ciostatus);
-}
-
-static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
-{
-	struct platform_device *dsidev;
-	struct dsi_data *dsi;
-	u32 irqstatus, vcstatus[4], ciostatus;
-	int i;
-
-	dsidev = (struct platform_device *) arg;
-	dsi = dsi_get_dsidrv_data(dsidev);
-
-	spin_lock(&dsi->irq_lock);
-
-	irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS);
-
-	/* IRQ is not for us */
-	if (!irqstatus) {
-		spin_unlock(&dsi->irq_lock);
-		return IRQ_NONE;
-	}
-
-	dsi_write_reg(dsidev, DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
-	/* flush posted write */
-	dsi_read_reg(dsidev, DSI_IRQSTATUS);
-
-	for (i = 0; i < 4; ++i) {
-		if ((irqstatus & (1 << i)) == 0) {
-			vcstatus[i] = 0;
-			continue;
-		}
-
-		vcstatus[i] = dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
-
-		dsi_write_reg(dsidev, DSI_VC_IRQSTATUS(i), vcstatus[i]);
-		/* flush posted write */
-		dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
-	}
-
-	if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
-		ciostatus = dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
-
-		dsi_write_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
-		/* flush posted write */
-		dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
-	} else {
-		ciostatus = 0;
-	}
-
-#ifdef DSI_CATCH_MISSING_TE
-	if (irqstatus & DSI_IRQ_TE_TRIGGER)
-		del_timer(&dsi->te_timer);
-#endif
-
-	/* make a copy and unlock, so that isrs can unregister
-	 * themselves */
-	memcpy(&dsi->isr_tables_copy, &dsi->isr_tables,
-		sizeof(dsi->isr_tables));
-
-	spin_unlock(&dsi->irq_lock);
-
-	dsi_handle_isrs(&dsi->isr_tables_copy, irqstatus, vcstatus, ciostatus);
-
-	dsi_handle_irq_errors(dsidev, irqstatus, vcstatus, ciostatus);
-
-	dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus);
-
-	return IRQ_HANDLED;
-}
-
-/* dsi->irq_lock has to be locked by the caller */
-static void _omap_dsi_configure_irqs(struct platform_device *dsidev,
-		struct dsi_isr_data *isr_array,
-		unsigned isr_array_size, u32 default_mask,
-		const struct dsi_reg enable_reg,
-		const struct dsi_reg status_reg)
-{
-	struct dsi_isr_data *isr_data;
-	u32 mask;
-	u32 old_mask;
-	int i;
-
-	mask = default_mask;
-
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
-
-		if (isr_data->isr == NULL)
-			continue;
-
-		mask |= isr_data->mask;
-	}
-
-	old_mask = dsi_read_reg(dsidev, enable_reg);
-	/* clear the irqstatus for newly enabled irqs */
-	dsi_write_reg(dsidev, status_reg, (mask ^ old_mask) & mask);
-	dsi_write_reg(dsidev, enable_reg, mask);
-
-	/* flush posted writes */
-	dsi_read_reg(dsidev, enable_reg);
-	dsi_read_reg(dsidev, status_reg);
-}
-
-/* dsi->irq_lock has to be locked by the caller */
-static void _omap_dsi_set_irqs(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 mask = DSI_IRQ_ERROR_MASK;
-#ifdef DSI_CATCH_MISSING_TE
-	mask |= DSI_IRQ_TE_TRIGGER;
-#endif
-	_omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table,
-			ARRAY_SIZE(dsi->isr_tables.isr_table), mask,
-			DSI_IRQENABLE, DSI_IRQSTATUS);
-}
-
-/* dsi->irq_lock has to be locked by the caller */
-static void _omap_dsi_set_irqs_vc(struct platform_device *dsidev, int vc)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	_omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_vc[vc],
-			ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]),
-			DSI_VC_IRQ_ERROR_MASK,
-			DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
-}
-
-/* dsi->irq_lock has to be locked by the caller */
-static void _omap_dsi_set_irqs_cio(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	_omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_cio,
-			ARRAY_SIZE(dsi->isr_tables.isr_table_cio),
-			DSI_CIO_IRQ_ERROR_MASK,
-			DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
-}
-
-static void _dsi_initialize_irq(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	int vc;
-
-	spin_lock_irqsave(&dsi->irq_lock, flags);
-
-	memset(&dsi->isr_tables, 0, sizeof(dsi->isr_tables));
-
-	_omap_dsi_set_irqs(dsidev);
-	for (vc = 0; vc < 4; ++vc)
-		_omap_dsi_set_irqs_vc(dsidev, vc);
-	_omap_dsi_set_irqs_cio(dsidev);
-
-	spin_unlock_irqrestore(&dsi->irq_lock, flags);
-}
-
-static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
-		struct dsi_isr_data *isr_array, unsigned isr_array_size)
-{
-	struct dsi_isr_data *isr_data;
-	int free_idx;
-	int i;
-
-	BUG_ON(isr == NULL);
-
-	/* check for duplicate entry and find a free slot */
-	free_idx = -1;
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
-
-		if (isr_data->isr == isr && isr_data->arg == arg &&
-				isr_data->mask == mask) {
-			return -EINVAL;
-		}
-
-		if (isr_data->isr == NULL && free_idx == -1)
-			free_idx = i;
-	}
-
-	if (free_idx == -1)
-		return -EBUSY;
-
-	isr_data = &isr_array[free_idx];
-	isr_data->isr = isr;
-	isr_data->arg = arg;
-	isr_data->mask = mask;
-
-	return 0;
-}
-
-static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
-		struct dsi_isr_data *isr_array, unsigned isr_array_size)
-{
-	struct dsi_isr_data *isr_data;
-	int i;
-
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
-		if (isr_data->isr != isr || isr_data->arg != arg ||
-				isr_data->mask != mask)
-			continue;
-
-		isr_data->isr = NULL;
-		isr_data->arg = NULL;
-		isr_data->mask = 0;
-
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int dsi_register_isr(struct platform_device *dsidev, omap_dsi_isr_t isr,
-		void *arg, u32 mask)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi->irq_lock, flags);
-
-	r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table,
-			ARRAY_SIZE(dsi->isr_tables.isr_table));
-
-	if (r == 0)
-		_omap_dsi_set_irqs(dsidev);
-
-	spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_unregister_isr(struct platform_device *dsidev,
-		omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi->irq_lock, flags);
-
-	r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table,
-			ARRAY_SIZE(dsi->isr_tables.isr_table));
-
-	if (r == 0)
-		_omap_dsi_set_irqs(dsidev);
-
-	spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_register_isr_vc(struct platform_device *dsidev, int channel,
-		omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi->irq_lock, flags);
-
-	r = _dsi_register_isr(isr, arg, mask,
-			dsi->isr_tables.isr_table_vc[channel],
-			ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_vc(dsidev, channel);
-
-	spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_unregister_isr_vc(struct platform_device *dsidev, int channel,
-		omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi->irq_lock, flags);
-
-	r = _dsi_unregister_isr(isr, arg, mask,
-			dsi->isr_tables.isr_table_vc[channel],
-			ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_vc(dsidev, channel);
-
-	spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_register_isr_cio(struct platform_device *dsidev,
-		omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi->irq_lock, flags);
-
-	r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
-			ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_cio(dsidev);
-
-	spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_unregister_isr_cio(struct platform_device *dsidev,
-		omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi->irq_lock, flags);
-
-	r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
-			ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_cio(dsidev);
-
-	spin_unlock_irqrestore(&dsi->irq_lock, flags);
-
-	return r;
-}
-
-static u32 dsi_get_errors(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	u32 e;
-	spin_lock_irqsave(&dsi->errors_lock, flags);
-	e = dsi->errors;
-	dsi->errors = 0;
-	spin_unlock_irqrestore(&dsi->errors_lock, flags);
-	return e;
-}
-
-int dsi_runtime_get(struct platform_device *dsidev)
-{
-	int r;
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	DSSDBG("dsi_runtime_get\n");
-
-	r = pm_runtime_get_sync(&dsi->pdev->dev);
-	WARN_ON(r < 0);
-	return r < 0 ? r : 0;
-}
-
-void dsi_runtime_put(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r;
-
-	DSSDBG("dsi_runtime_put\n");
-
-	r = pm_runtime_put_sync(&dsi->pdev->dev);
-	WARN_ON(r < 0 && r != -ENOSYS);
-}
-
-static int dsi_regulator_init(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct regulator *vdds_dsi;
-
-	if (dsi->vdds_dsi_reg != NULL)
-		return 0;
-
-	vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdd");
-
-	if (IS_ERR(vdds_dsi)) {
-		if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
-			DSSERR("can't get DSI VDD regulator\n");
-		return PTR_ERR(vdds_dsi);
-	}
-
-	dsi->vdds_dsi_reg = vdds_dsi;
-
-	return 0;
-}
-
-/* source clock for DSI PLL. this could also be PCLKFREE */
-static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
-		bool enable)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (enable)
-		clk_prepare_enable(dsi->sys_clk);
-	else
-		clk_disable_unprepare(dsi->sys_clk);
-
-	if (enable && dsi->pll_locked) {
-		if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
-			DSSERR("cannot lock PLL when enabling clocks\n");
-	}
-}
-
-static void _dsi_print_reset_status(struct platform_device *dsidev)
-{
-	u32 l;
-	int b0, b1, b2;
-
-	/* A dummy read using the SCP interface to any DSIPHY register is
-	 * required after DSIPHY reset to complete the reset of the DSI complex
-	 * I/O. */
-	l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
-
-	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
-		b0 = 28;
-		b1 = 27;
-		b2 = 26;
-	} else {
-		b0 = 24;
-		b1 = 25;
-		b2 = 26;
-	}
-
-#define DSI_FLD_GET(fld, start, end)\
-	FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
-
-	pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
-		DSI_FLD_GET(PLL_STATUS, 0, 0),
-		DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
-		DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
-		DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
-		DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
-		DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
-		DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
-		DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
-
-#undef DSI_FLD_GET
-}
-
-static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
-{
-	DSSDBG("dsi_if_enable(%d)\n", enable);
-
-	enable = enable ? 1 : 0;
-	REG_FLD_MOD(dsidev, DSI_CTRL, enable, 0, 0); /* IF_EN */
-
-	if (wait_for_bit_change(dsidev, DSI_CTRL, 0, enable) != enable) {
-			DSSERR("Failed to set dsi_if_enable to %d\n", enable);
-			return -EIO;
-	}
-
-	return 0;
-}
-
-unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk;
-}
-
-static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk;
-}
-
-static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	return dsi->current_cinfo.clkin4ddr / 16;
-}
-
-static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
-{
-	unsigned long r;
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) {
-		/* DSI FCLK source is DSS_CLK_FCK */
-		r = clk_get_rate(dsi->dss_clk);
-	} else {
-		/* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
-		r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
-	}
-
-	return r;
-}
-
-static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
-		unsigned long lp_clk_min, unsigned long lp_clk_max)
-{
-	unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
-	unsigned lp_clk_div;
-	unsigned long lp_clk;
-
-	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
-	lp_clk = dsi_fclk / 2 / lp_clk_div;
-
-	if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
-		return -EINVAL;
-
-	cinfo->lp_clk_div = lp_clk_div;
-	cinfo->lp_clk = lp_clk;
-
-	return 0;
-}
-
-static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long dsi_fclk;
-	unsigned lp_clk_div;
-	unsigned long lp_clk;
-
-	lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div;
-
-	if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max)
-		return -EINVAL;
-
-	dsi_fclk = dsi_fclk_rate(dsidev);
-
-	lp_clk = dsi_fclk / 2 / lp_clk_div;
-
-	DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
-	dsi->current_cinfo.lp_clk = lp_clk;
-	dsi->current_cinfo.lp_clk_div = lp_clk_div;
-
-	/* LP_CLK_DIVISOR */
-	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0);
-
-	/* LP_RX_SYNCHRO_ENABLE */
-	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, 21, 21);
-
-	return 0;
-}
-
-static void dsi_enable_scp_clk(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (dsi->scp_clk_refcount++ == 0)
-		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */
-}
-
-static void dsi_disable_scp_clk(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	WARN_ON(dsi->scp_clk_refcount == 0);
-	if (--dsi->scp_clk_refcount == 0)
-		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */
-}
-
-enum dsi_pll_power_state {
-	DSI_PLL_POWER_OFF	= 0x0,
-	DSI_PLL_POWER_ON_HSCLK	= 0x1,
-	DSI_PLL_POWER_ON_ALL	= 0x2,
-	DSI_PLL_POWER_ON_DIV	= 0x3,
-};
-
-static int dsi_pll_power(struct platform_device *dsidev,
-		enum dsi_pll_power_state state)
-{
-	int t = 0;
-
-	/* DSI-PLL power command 0x3 is not working */
-	if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
-			state == DSI_PLL_POWER_ON_DIV)
-		state = DSI_PLL_POWER_ON_ALL;
-
-	/* PLL_PWR_CMD */
-	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, state, 31, 30);
-
-	/* PLL_PWR_STATUS */
-	while (FLD_GET(dsi_read_reg(dsidev, DSI_CLK_CTRL), 29, 28) != state) {
-		if (++t > 1000) {
-			DSSERR("Failed to set DSI PLL power mode to %d\n",
-					state);
-			return -ENODEV;
-		}
-		udelay(1);
-	}
-
-	return 0;
-}
-
-unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	return clk_get_rate(dsi->sys_clk);
-}
-
-bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
-		unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int regm, regm_start, regm_stop;
-	unsigned long out_max;
-	unsigned long out;
-
-	out_min = out_min ? out_min : 1;
-	out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
-	regm_stop = min(pll / out_min, dsi->regm_dispc_max);
-
-	for (regm = regm_start; regm <= regm_stop; ++regm) {
-		out = pll / regm;
-
-		if (func(regm, out, data))
-			return true;
-	}
-
-	return false;
-}
-
-bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
-		unsigned long pll_min, unsigned long pll_max,
-		dsi_pll_calc_func func, void *data)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int regn, regn_start, regn_stop;
-	int regm, regm_start, regm_stop;
-	unsigned long fint, pll;
-	const unsigned long pll_hw_max = 1800000000;
-	unsigned long fint_hw_min, fint_hw_max;
-
-	fint_hw_min = dsi->fint_min;
-	fint_hw_max = dsi->fint_max;
-
-	regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
-	regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
-
-	pll_max = pll_max ? pll_max : ULONG_MAX;
-
-	for (regn = regn_start; regn <= regn_stop; ++regn) {
-		fint = clkin / regn;
-
-		regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
-				1ul);
-		regm_stop = min3(pll_max / fint / 2,
-				pll_hw_max / fint / 2,
-				dsi->regm_max);
-
-		for (regm = regm_start; regm <= regm_stop; ++regm) {
-			pll = 2 * regm * fint;
-
-			if (func(regn, regm, fint, pll, data))
-				return true;
-		}
-	}
-
-	return false;
-}
-
-/* calculate clock rates using dividers in cinfo */
-static int dsi_calc_clock_rates(struct platform_device *dsidev,
-		struct dsi_clock_info *cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
-		return -EINVAL;
-
-	if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max)
-		return -EINVAL;
-
-	if (cinfo->regm_dispc > dsi->regm_dispc_max)
-		return -EINVAL;
-
-	if (cinfo->regm_dsi > dsi->regm_dsi_max)
-		return -EINVAL;
-
-	cinfo->clkin = clk_get_rate(dsi->sys_clk);
-	cinfo->fint = cinfo->clkin / cinfo->regn;
-
-	if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
-		return -EINVAL;
-
-	cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
-
-	if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
-		return -EINVAL;
-
-	if (cinfo->regm_dispc > 0)
-		cinfo->dsi_pll_hsdiv_dispc_clk =
-			cinfo->clkin4ddr / cinfo->regm_dispc;
-	else
-		cinfo->dsi_pll_hsdiv_dispc_clk = 0;
-
-	if (cinfo->regm_dsi > 0)
-		cinfo->dsi_pll_hsdiv_dsi_clk =
-			cinfo->clkin4ddr / cinfo->regm_dsi;
-	else
-		cinfo->dsi_pll_hsdiv_dsi_clk = 0;
-
-	return 0;
-}
-
-static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
-{
-	unsigned long max_dsi_fck;
-
-	max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
-
-	cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
-	cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
-}
-
-int dsi_pll_set_clock_div(struct platform_device *dsidev,
-		struct dsi_clock_info *cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r = 0;
-	u32 l;
-	int f = 0;
-	u8 regn_start, regn_end, regm_start, regm_end;
-	u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
-
-	DSSDBG("DSI PLL clock config starts");
-
-	dsi->current_cinfo.clkin = cinfo->clkin;
-	dsi->current_cinfo.fint = cinfo->fint;
-	dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
-	dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
-			cinfo->dsi_pll_hsdiv_dispc_clk;
-	dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk =
-			cinfo->dsi_pll_hsdiv_dsi_clk;
-
-	dsi->current_cinfo.regn = cinfo->regn;
-	dsi->current_cinfo.regm = cinfo->regm;
-	dsi->current_cinfo.regm_dispc = cinfo->regm_dispc;
-	dsi->current_cinfo.regm_dsi = cinfo->regm_dsi;
-
-	DSSDBG("DSI Fint %ld\n", cinfo->fint);
-
-	DSSDBG("clkin rate %ld\n", cinfo->clkin);
-
-	/* DSIPHY == CLKIN4DDR */
-	DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",
-			cinfo->regm,
-			cinfo->regn,
-			cinfo->clkin,
-			cinfo->clkin4ddr);
-
-	DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
-			cinfo->clkin4ddr / 1000 / 1000 / 2);
-
-	DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
-
-	DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
-		dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-		dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-		cinfo->dsi_pll_hsdiv_dispc_clk);
-	DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
-		dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-		dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-		cinfo->dsi_pll_hsdiv_dsi_clk);
-
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
-			&regm_dispc_end);
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
-			&regm_dsi_end);
-
-	/* DSI_PLL_AUTOMODE = manual */
-	REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0);
-
-	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1);
-	l = FLD_MOD(l, 1, 0, 0);		/* DSI_PLL_STOPMODE */
-	/* DSI_PLL_REGN */
-	l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
-	/* DSI_PLL_REGM */
-	l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
-	/* DSI_CLOCK_DIV */
-	l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
-			regm_dispc_start, regm_dispc_end);
-	/* DSIPROTO_CLOCK_DIV */
-	l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
-			regm_dsi_start, regm_dsi_end);
-	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l);
-
-	BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
-
-	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
-
-	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
-		f = cinfo->fint < 1000000 ? 0x3 :
-			cinfo->fint < 1250000 ? 0x4 :
-			cinfo->fint < 1500000 ? 0x5 :
-			cinfo->fint < 1750000 ? 0x6 :
-			0x7;
-
-		l = FLD_MOD(l, f, 4, 1);	/* DSI_PLL_FREQSEL */
-	} else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
-		f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
-
-		l = FLD_MOD(l, f, 4, 1);	/* PLL_SELFREQDCO */
-	}
-
-	l = FLD_MOD(l, 1, 13, 13);		/* DSI_PLL_REFEN */
-	l = FLD_MOD(l, 0, 14, 14);		/* DSIPHY_CLKINEN */
-	l = FLD_MOD(l, 1, 20, 20);		/* DSI_HSDIVBYPASS */
-	if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
-		l = FLD_MOD(l, 3, 22, 21);	/* REF_SYSCLK = sysclk */
-	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
-
-	REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0);	/* DSI_PLL_GO */
-
-	if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) {
-		DSSERR("dsi pll go bit not going down.\n");
-		r = -EIO;
-		goto err;
-	}
-
-	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) {
-		DSSERR("cannot lock PLL\n");
-		r = -EIO;
-		goto err;
-	}
-
-	dsi->pll_locked = 1;
-
-	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
-	l = FLD_MOD(l, 0, 0, 0);	/* DSI_PLL_IDLE */
-	l = FLD_MOD(l, 0, 5, 5);	/* DSI_PLL_PLLLPMODE */
-	l = FLD_MOD(l, 0, 6, 6);	/* DSI_PLL_LOWCURRSTBY */
-	l = FLD_MOD(l, 0, 7, 7);	/* DSI_PLL_TIGHTPHASELOCK */
-	l = FLD_MOD(l, 0, 8, 8);	/* DSI_PLL_DRIFTGUARDEN */
-	l = FLD_MOD(l, 0, 10, 9);	/* DSI_PLL_LOCKSEL */
-	l = FLD_MOD(l, 1, 13, 13);	/* DSI_PLL_REFEN */
-	l = FLD_MOD(l, 1, 14, 14);	/* DSIPHY_CLKINEN */
-	l = FLD_MOD(l, 0, 15, 15);	/* DSI_BYPASSEN */
-	l = FLD_MOD(l, 1, 16, 16);	/* DSS_CLOCK_EN */
-	l = FLD_MOD(l, 0, 17, 17);	/* DSS_CLOCK_PWDN */
-	l = FLD_MOD(l, 1, 18, 18);	/* DSI_PROTO_CLOCK_EN */
-	l = FLD_MOD(l, 0, 19, 19);	/* DSI_PROTO_CLOCK_PWDN */
-	l = FLD_MOD(l, 0, 20, 20);	/* DSI_HSDIVBYPASS */
-	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
-
-	DSSDBG("PLL config done\n");
-err:
-	return r;
-}
-
-int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
-		bool enable_hsdiv)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r = 0;
-	enum dsi_pll_power_state pwstate;
-
-	DSSDBG("PLL init\n");
-
-	/*
-	 * It seems that on many OMAPs we need to enable both to have a
-	 * functional HSDivider.
-	 */
-	enable_hsclk = enable_hsdiv = true;
-
-	r = dsi_regulator_init(dsidev);
-	if (r)
-		return r;
-
-	dsi_enable_pll_clock(dsidev, 1);
-	/*
-	 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
-	 */
-	dsi_enable_scp_clk(dsidev);
-
-	if (!dsi->vdds_dsi_enabled) {
-		r = regulator_enable(dsi->vdds_dsi_reg);
-		if (r)
-			goto err0;
-		dsi->vdds_dsi_enabled = true;
-	}
-
-	/* XXX PLL does not come out of reset without this... */
-	dispc_pck_free_enable(1);
-
-	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 0, 1) != 1) {
-		DSSERR("PLL not coming out of reset.\n");
-		r = -ENODEV;
-		dispc_pck_free_enable(0);
-		goto err1;
-	}
-
-	/* XXX ... but if left on, we get problems when planes do not
-	 * fill the whole display. No idea about this */
-	dispc_pck_free_enable(0);
-
-	if (enable_hsclk && enable_hsdiv)
-		pwstate = DSI_PLL_POWER_ON_ALL;
-	else if (enable_hsclk)
-		pwstate = DSI_PLL_POWER_ON_HSCLK;
-	else if (enable_hsdiv)
-		pwstate = DSI_PLL_POWER_ON_DIV;
-	else
-		pwstate = DSI_PLL_POWER_OFF;
-
-	r = dsi_pll_power(dsidev, pwstate);
-
-	if (r)
-		goto err1;
-
-	DSSDBG("PLL init done\n");
-
-	return 0;
-err1:
-	if (dsi->vdds_dsi_enabled) {
-		regulator_disable(dsi->vdds_dsi_reg);
-		dsi->vdds_dsi_enabled = false;
-	}
-err0:
-	dsi_disable_scp_clk(dsidev);
-	dsi_enable_pll_clock(dsidev, 0);
-	return r;
-}
-
-void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	dsi->pll_locked = 0;
-	dsi_pll_power(dsidev, DSI_PLL_POWER_OFF);
-	if (disconnect_lanes) {
-		WARN_ON(!dsi->vdds_dsi_enabled);
-		regulator_disable(dsi->vdds_dsi_reg);
-		dsi->vdds_dsi_enabled = false;
-	}
-
-	dsi_disable_scp_clk(dsidev);
-	dsi_enable_pll_clock(dsidev, 0);
-
-	DSSDBG("PLL uninit done\n");
-}
-
-static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
-		struct seq_file *s)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info *cinfo = &dsi->current_cinfo;
-	enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
-	int dsi_module = dsi->module_id;
-
-	dispc_clk_src = dss_get_dispc_clk_source();
-	dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
-
-	if (dsi_runtime_get(dsidev))
-		return;
-
-	seq_printf(s,	"- DSI%d PLL -\n", dsi_module + 1);
-
-	seq_printf(s,	"dsi pll clkin\t%lu\n", cinfo->clkin);
-
-	seq_printf(s,	"Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
-
-	seq_printf(s,	"CLKIN4DDR\t%-16luregm %u\n",
-			cinfo->clkin4ddr, cinfo->regm);
-
-	seq_printf(s,	"DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n",
-			dss_feat_get_clk_source_name(dsi_module == 0 ?
-				OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
-				OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
-			cinfo->dsi_pll_hsdiv_dispc_clk,
-			cinfo->regm_dispc,
-			dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
-			"off" : "on");
-
-	seq_printf(s,	"DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n",
-			dss_feat_get_clk_source_name(dsi_module == 0 ?
-				OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
-				OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
-			cinfo->dsi_pll_hsdiv_dsi_clk,
-			cinfo->regm_dsi,
-			dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
-			"off" : "on");
-
-	seq_printf(s,	"- DSI%d -\n", dsi_module + 1);
-
-	seq_printf(s,	"dsi fclk source = %s (%s)\n",
-			dss_get_generic_clk_source_name(dsi_clk_src),
-			dss_feat_get_clk_source_name(dsi_clk_src));
-
-	seq_printf(s,	"DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
-
-	seq_printf(s,	"DDR_CLK\t\t%lu\n",
-			cinfo->clkin4ddr / 4);
-
-	seq_printf(s,	"TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev));
-
-	seq_printf(s,	"LP_CLK\t\t%lu\n", cinfo->lp_clk);
-
-	dsi_runtime_put(dsidev);
-}
-
-void dsi_dump_clocks(struct seq_file *s)
-{
-	struct platform_device *dsidev;
-	int i;
-
-	for  (i = 0; i < MAX_NUM_DSI; i++) {
-		dsidev = dsi_get_dsidev_from_id(i);
-		if (dsidev)
-			dsi_dump_dsidev_clocks(dsidev, s);
-	}
-}
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
-		struct seq_file *s)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned long flags;
-	struct dsi_irq_stats stats;
-
-	spin_lock_irqsave(&dsi->irq_stats_lock, flags);
-
-	stats = dsi->irq_stats;
-	memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats));
-	dsi->irq_stats.last_reset = jiffies;
-
-	spin_unlock_irqrestore(&dsi->irq_stats_lock, flags);
-
-	seq_printf(s, "period %u ms\n",
-			jiffies_to_msecs(jiffies - stats.last_reset));
-
-	seq_printf(s, "irqs %d\n", stats.irq_count);
-#define PIS(x) \
-	seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
-
-	seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1);
-	PIS(VC0);
-	PIS(VC1);
-	PIS(VC2);
-	PIS(VC3);
-	PIS(WAKEUP);
-	PIS(RESYNC);
-	PIS(PLL_LOCK);
-	PIS(PLL_UNLOCK);
-	PIS(PLL_RECALL);
-	PIS(COMPLEXIO_ERR);
-	PIS(HS_TX_TIMEOUT);
-	PIS(LP_RX_TIMEOUT);
-	PIS(TE_TRIGGER);
-	PIS(ACK_TRIGGER);
-	PIS(SYNC_LOST);
-	PIS(LDO_POWER_GOOD);
-	PIS(TA_TIMEOUT);
-#undef PIS
-
-#define PIS(x) \
-	seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \
-			stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \
-			stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \
-			stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \
-			stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);
-
-	seq_printf(s, "-- VC interrupts --\n");
-	PIS(CS);
-	PIS(ECC_CORR);
-	PIS(PACKET_SENT);
-	PIS(FIFO_TX_OVF);
-	PIS(FIFO_RX_OVF);
-	PIS(BTA);
-	PIS(ECC_NO_CORR);
-	PIS(FIFO_TX_UDF);
-	PIS(PP_BUSY_CHANGE);
-#undef PIS
-
-#define PIS(x) \
-	seq_printf(s, "%-20s %10d\n", #x, \
-			stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);
-
-	seq_printf(s, "-- CIO interrupts --\n");
-	PIS(ERRSYNCESC1);
-	PIS(ERRSYNCESC2);
-	PIS(ERRSYNCESC3);
-	PIS(ERRESC1);
-	PIS(ERRESC2);
-	PIS(ERRESC3);
-	PIS(ERRCONTROL1);
-	PIS(ERRCONTROL2);
-	PIS(ERRCONTROL3);
-	PIS(STATEULPS1);
-	PIS(STATEULPS2);
-	PIS(STATEULPS3);
-	PIS(ERRCONTENTIONLP0_1);
-	PIS(ERRCONTENTIONLP1_1);
-	PIS(ERRCONTENTIONLP0_2);
-	PIS(ERRCONTENTIONLP1_2);
-	PIS(ERRCONTENTIONLP0_3);
-	PIS(ERRCONTENTIONLP1_3);
-	PIS(ULPSACTIVENOT_ALL0);
-	PIS(ULPSACTIVENOT_ALL1);
-#undef PIS
-}
-
-static void dsi1_dump_irqs(struct seq_file *s)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
-
-	dsi_dump_dsidev_irqs(dsidev, s);
-}
-
-static void dsi2_dump_irqs(struct seq_file *s)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
-
-	dsi_dump_dsidev_irqs(dsidev, s);
-}
-#endif
-
-static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
-		struct seq_file *s)
-{
-#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
-
-	if (dsi_runtime_get(dsidev))
-		return;
-	dsi_enable_scp_clk(dsidev);
-
-	DUMPREG(DSI_REVISION);
-	DUMPREG(DSI_SYSCONFIG);
-	DUMPREG(DSI_SYSSTATUS);
-	DUMPREG(DSI_IRQSTATUS);
-	DUMPREG(DSI_IRQENABLE);
-	DUMPREG(DSI_CTRL);
-	DUMPREG(DSI_COMPLEXIO_CFG1);
-	DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
-	DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
-	DUMPREG(DSI_CLK_CTRL);
-	DUMPREG(DSI_TIMING1);
-	DUMPREG(DSI_TIMING2);
-	DUMPREG(DSI_VM_TIMING1);
-	DUMPREG(DSI_VM_TIMING2);
-	DUMPREG(DSI_VM_TIMING3);
-	DUMPREG(DSI_CLK_TIMING);
-	DUMPREG(DSI_TX_FIFO_VC_SIZE);
-	DUMPREG(DSI_RX_FIFO_VC_SIZE);
-	DUMPREG(DSI_COMPLEXIO_CFG2);
-	DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
-	DUMPREG(DSI_VM_TIMING4);
-	DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
-	DUMPREG(DSI_VM_TIMING5);
-	DUMPREG(DSI_VM_TIMING6);
-	DUMPREG(DSI_VM_TIMING7);
-	DUMPREG(DSI_STOPCLK_TIMING);
-
-	DUMPREG(DSI_VC_CTRL(0));
-	DUMPREG(DSI_VC_TE(0));
-	DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
-	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
-	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
-	DUMPREG(DSI_VC_IRQSTATUS(0));
-	DUMPREG(DSI_VC_IRQENABLE(0));
-
-	DUMPREG(DSI_VC_CTRL(1));
-	DUMPREG(DSI_VC_TE(1));
-	DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
-	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
-	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
-	DUMPREG(DSI_VC_IRQSTATUS(1));
-	DUMPREG(DSI_VC_IRQENABLE(1));
-
-	DUMPREG(DSI_VC_CTRL(2));
-	DUMPREG(DSI_VC_TE(2));
-	DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
-	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
-	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
-	DUMPREG(DSI_VC_IRQSTATUS(2));
-	DUMPREG(DSI_VC_IRQENABLE(2));
-
-	DUMPREG(DSI_VC_CTRL(3));
-	DUMPREG(DSI_VC_TE(3));
-	DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
-	DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
-	DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
-	DUMPREG(DSI_VC_IRQSTATUS(3));
-	DUMPREG(DSI_VC_IRQENABLE(3));
-
-	DUMPREG(DSI_DSIPHY_CFG0);
-	DUMPREG(DSI_DSIPHY_CFG1);
-	DUMPREG(DSI_DSIPHY_CFG2);
-	DUMPREG(DSI_DSIPHY_CFG5);
-
-	DUMPREG(DSI_PLL_CONTROL);
-	DUMPREG(DSI_PLL_STATUS);
-	DUMPREG(DSI_PLL_GO);
-	DUMPREG(DSI_PLL_CONFIGURATION1);
-	DUMPREG(DSI_PLL_CONFIGURATION2);
-
-	dsi_disable_scp_clk(dsidev);
-	dsi_runtime_put(dsidev);
-#undef DUMPREG
-}
-
-static void dsi1_dump_regs(struct seq_file *s)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
-
-	dsi_dump_dsidev_regs(dsidev, s);
-}
-
-static void dsi2_dump_regs(struct seq_file *s)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
-
-	dsi_dump_dsidev_regs(dsidev, s);
-}
-
-enum dsi_cio_power_state {
-	DSI_COMPLEXIO_POWER_OFF		= 0x0,
-	DSI_COMPLEXIO_POWER_ON		= 0x1,
-	DSI_COMPLEXIO_POWER_ULPS	= 0x2,
-};
-
-static int dsi_cio_power(struct platform_device *dsidev,
-		enum dsi_cio_power_state state)
-{
-	int t = 0;
-
-	/* PWR_CMD */
-	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG1, state, 28, 27);
-
-	/* PWR_STATUS */
-	while (FLD_GET(dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1),
-			26, 25) != state) {
-		if (++t > 1000) {
-			DSSERR("failed to set complexio power state to "
-					"%d\n", state);
-			return -ENODEV;
-		}
-		udelay(1);
-	}
-
-	return 0;
-}
-
-static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
-{
-	int val;
-
-	/* line buffer on OMAP3 is 1024 x 24bits */
-	/* XXX: for some reason using full buffer size causes
-	 * considerable TX slowdown with update sizes that fill the
-	 * whole buffer */
-	if (!dss_has_feature(FEAT_DSI_GNQ))
-		return 1023 * 3;
-
-	val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */
-
-	switch (val) {
-	case 1:
-		return 512 * 3;		/* 512x24 bits */
-	case 2:
-		return 682 * 3;		/* 682x24 bits */
-	case 3:
-		return 853 * 3;		/* 853x24 bits */
-	case 4:
-		return 1024 * 3;	/* 1024x24 bits */
-	case 5:
-		return 1194 * 3;	/* 1194x24 bits */
-	case 6:
-		return 1365 * 3;	/* 1365x24 bits */
-	case 7:
-		return 1920 * 3;	/* 1920x24 bits */
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static int dsi_set_lane_config(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	static const u8 offsets[] = { 0, 4, 8, 12, 16 };
-	static const enum dsi_lane_function functions[] = {
-		DSI_LANE_CLK,
-		DSI_LANE_DATA1,
-		DSI_LANE_DATA2,
-		DSI_LANE_DATA3,
-		DSI_LANE_DATA4,
-	};
-	u32 r;
-	int i;
-
-	r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
-
-	for (i = 0; i < dsi->num_lanes_used; ++i) {
-		unsigned offset = offsets[i];
-		unsigned polarity, lane_number;
-		unsigned t;
-
-		for (t = 0; t < dsi->num_lanes_supported; ++t)
-			if (dsi->lanes[t].function == functions[i])
-				break;
-
-		if (t == dsi->num_lanes_supported)
-			return -EINVAL;
-
-		lane_number = t;
-		polarity = dsi->lanes[t].polarity;
-
-		r = FLD_MOD(r, lane_number + 1, offset + 2, offset);
-		r = FLD_MOD(r, polarity, offset + 3, offset + 3);
-	}
-
-	/* clear the unused lanes */
-	for (; i < dsi->num_lanes_supported; ++i) {
-		unsigned offset = offsets[i];
-
-		r = FLD_MOD(r, 0, offset + 2, offset);
-		r = FLD_MOD(r, 0, offset + 3, offset + 3);
-	}
-
-	dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
-
-	return 0;
-}
-
-static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	/* convert time in ns to ddr ticks, rounding up */
-	unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
-	return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
-}
-
-static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
-	return ddr * 1000 * 1000 / (ddr_clk / 1000);
-}
-
-static void dsi_cio_timings(struct platform_device *dsidev)
-{
-	u32 r;
-	u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
-	u32 tlpx_half, tclk_trail, tclk_zero;
-	u32 tclk_prepare;
-
-	/* calculate timings */
-
-	/* 1 * DDR_CLK = 2 * UI */
-
-	/* min 40ns + 4*UI	max 85ns + 6*UI */
-	ths_prepare = ns2ddr(dsidev, 70) + 2;
-
-	/* min 145ns + 10*UI */
-	ths_prepare_ths_zero = ns2ddr(dsidev, 175) + 2;
-
-	/* min max(8*UI, 60ns+4*UI) */
-	ths_trail = ns2ddr(dsidev, 60) + 5;
-
-	/* min 100ns */
-	ths_exit = ns2ddr(dsidev, 145);
-
-	/* tlpx min 50n */
-	tlpx_half = ns2ddr(dsidev, 25);
-
-	/* min 60ns */
-	tclk_trail = ns2ddr(dsidev, 60) + 2;
-
-	/* min 38ns, max 95ns */
-	tclk_prepare = ns2ddr(dsidev, 65);
-
-	/* min tclk-prepare + tclk-zero = 300ns */
-	tclk_zero = ns2ddr(dsidev, 260);
-
-	DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
-		ths_prepare, ddr2ns(dsidev, ths_prepare),
-		ths_prepare_ths_zero, ddr2ns(dsidev, ths_prepare_ths_zero));
-	DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
-			ths_trail, ddr2ns(dsidev, ths_trail),
-			ths_exit, ddr2ns(dsidev, ths_exit));
-
-	DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
-			"tclk_zero %u (%uns)\n",
-			tlpx_half, ddr2ns(dsidev, tlpx_half),
-			tclk_trail, ddr2ns(dsidev, tclk_trail),
-			tclk_zero, ddr2ns(dsidev, tclk_zero));
-	DSSDBG("tclk_prepare %u (%uns)\n",
-			tclk_prepare, ddr2ns(dsidev, tclk_prepare));
-
-	/* program timings */
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
-	r = FLD_MOD(r, ths_prepare, 31, 24);
-	r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
-	r = FLD_MOD(r, ths_trail, 15, 8);
-	r = FLD_MOD(r, ths_exit, 7, 0);
-	dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
-	r = FLD_MOD(r, tlpx_half, 20, 16);
-	r = FLD_MOD(r, tclk_trail, 15, 8);
-	r = FLD_MOD(r, tclk_zero, 7, 0);
-
-	if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
-		r = FLD_MOD(r, 0, 21, 21);	/* DCCEN = disable */
-		r = FLD_MOD(r, 1, 22, 22);	/* CLKINP_DIVBY2EN = enable */
-		r = FLD_MOD(r, 1, 23, 23);	/* CLKINP_SEL = enable */
-	}
-
-	dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
-	r = FLD_MOD(r, tclk_prepare, 7, 0);
-	dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
-}
-
-/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
-static void dsi_cio_enable_lane_override(struct platform_device *dsidev,
-		unsigned mask_p, unsigned mask_n)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int i;
-	u32 l;
-	u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26;
-
-	l = 0;
-
-	for (i = 0; i < dsi->num_lanes_supported; ++i) {
-		unsigned p = dsi->lanes[i].polarity;
-
-		if (mask_p & (1 << i))
-			l |= 1 << (i * 2 + (p ? 0 : 1));
-
-		if (mask_n & (1 << i))
-			l |= 1 << (i * 2 + (p ? 1 : 0));
-	}
-
-	/*
-	 * Bits in REGLPTXSCPDAT4TO0DXDY:
-	 * 17: DY0 18: DX0
-	 * 19: DY1 20: DX1
-	 * 21: DY2 22: DX2
-	 * 23: DY3 24: DX3
-	 * 25: DY4 26: DX4
-	 */
-
-	/* Set the lane override configuration */
-
-	/* REGLPTXSCPDAT4TO0DXDY */
-	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, lptxscp_start, 17);
-
-	/* Enable lane override */
-
-	/* ENLPTXSCPDAT */
-	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 1, 27, 27);
-}
-
-static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
-{
-	/* Disable lane override */
-	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
-	/* Reset the lane override configuration */
-	/* REGLPTXSCPDAT4TO0DXDY */
-	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
-}
-
-static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int t, i;
-	bool in_use[DSI_MAX_NR_LANES];
-	static const u8 offsets_old[] = { 28, 27, 26 };
-	static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
-	const u8 *offsets;
-
-	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
-		offsets = offsets_old;
-	else
-		offsets = offsets_new;
-
-	for (i = 0; i < dsi->num_lanes_supported; ++i)
-		in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED;
-
-	t = 100000;
-	while (true) {
-		u32 l;
-		int ok;
-
-		l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
-
-		ok = 0;
-		for (i = 0; i < dsi->num_lanes_supported; ++i) {
-			if (!in_use[i] || (l & (1 << offsets[i])))
-				ok++;
-		}
-
-		if (ok == dsi->num_lanes_supported)
-			break;
-
-		if (--t == 0) {
-			for (i = 0; i < dsi->num_lanes_supported; ++i) {
-				if (!in_use[i] || (l & (1 << offsets[i])))
-					continue;
-
-				DSSERR("CIO TXCLKESC%d domain not coming " \
-						"out of reset\n", i);
-			}
-			return -EIO;
-		}
-	}
-
-	return 0;
-}
-
-/* return bitmask of enabled lanes, lane0 being the lsb */
-static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned mask = 0;
-	int i;
-
-	for (i = 0; i < dsi->num_lanes_supported; ++i) {
-		if (dsi->lanes[i].function != DSI_LANE_UNUSED)
-			mask |= 1 << i;
-	}
-
-	return mask;
-}
-
-static int dsi_cio_init(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r;
-	u32 l;
-
-	DSSDBG("DSI CIO init starts");
-
-	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
-	if (r)
-		return r;
-
-	dsi_enable_scp_clk(dsidev);
-
-	/* A dummy read using the SCP interface to any DSIPHY register is
-	 * required after DSIPHY reset to complete the reset of the DSI complex
-	 * I/O. */
-	dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
-
-	if (wait_for_bit_change(dsidev, DSI_DSIPHY_CFG5, 30, 1) != 1) {
-		DSSERR("CIO SCP Clock domain not coming out of reset.\n");
-		r = -EIO;
-		goto err_scp_clk_dom;
-	}
-
-	r = dsi_set_lane_config(dsidev);
-	if (r)
-		goto err_scp_clk_dom;
-
-	/* set TX STOP MODE timer to maximum for this operation */
-	l = dsi_read_reg(dsidev, DSI_TIMING1);
-	l = FLD_MOD(l, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
-	l = FLD_MOD(l, 1, 14, 14);	/* STOP_STATE_X16_IO */
-	l = FLD_MOD(l, 1, 13, 13);	/* STOP_STATE_X4_IO */
-	l = FLD_MOD(l, 0x1fff, 12, 0);	/* STOP_STATE_COUNTER_IO */
-	dsi_write_reg(dsidev, DSI_TIMING1, l);
-
-	if (dsi->ulps_enabled) {
-		unsigned mask_p;
-		int i;
-
-		DSSDBG("manual ulps exit\n");
-
-		/* ULPS is exited by Mark-1 state for 1ms, followed by
-		 * stop state. DSS HW cannot do this via the normal
-		 * ULPS exit sequence, as after reset the DSS HW thinks
-		 * that we are not in ULPS mode, and refuses to send the
-		 * sequence. So we need to send the ULPS exit sequence
-		 * manually by setting positive lines high and negative lines
-		 * low for 1ms.
-		 */
-
-		mask_p = 0;
-
-		for (i = 0; i < dsi->num_lanes_supported; ++i) {
-			if (dsi->lanes[i].function == DSI_LANE_UNUSED)
-				continue;
-			mask_p |= 1 << i;
-		}
-
-		dsi_cio_enable_lane_override(dsidev, mask_p, 0);
-	}
-
-	r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
-	if (r)
-		goto err_cio_pwr;
-
-	if (wait_for_bit_change(dsidev, DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
-		DSSERR("CIO PWR clock domain not coming out of reset.\n");
-		r = -ENODEV;
-		goto err_cio_pwr_dom;
-	}
-
-	dsi_if_enable(dsidev, true);
-	dsi_if_enable(dsidev, false);
-	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
-
-	r = dsi_cio_wait_tx_clk_esc_reset(dsidev);
-	if (r)
-		goto err_tx_clk_esc_rst;
-
-	if (dsi->ulps_enabled) {
-		/* Keep Mark-1 state for 1ms (as per DSI spec) */
-		ktime_t wait = ns_to_ktime(1000 * 1000);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
-
-		/* Disable the override. The lanes should be set to Mark-11
-		 * state by the HW */
-		dsi_cio_disable_lane_override(dsidev);
-	}
-
-	/* FORCE_TX_STOP_MODE_IO */
-	REG_FLD_MOD(dsidev, DSI_TIMING1, 0, 15, 15);
-
-	dsi_cio_timings(dsidev);
-
-	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-		/* DDR_CLK_ALWAYS_ON */
-		REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
-			dsi->vm_timings.ddr_clk_always_on, 13, 13);
-	}
-
-	dsi->ulps_enabled = false;
-
-	DSSDBG("CIO init done\n");
-
-	return 0;
-
-err_tx_clk_esc_rst:
-	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 20, 20); /* LP_CLK_ENABLE */
-err_cio_pwr_dom:
-	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
-err_cio_pwr:
-	if (dsi->ulps_enabled)
-		dsi_cio_disable_lane_override(dsidev);
-err_scp_clk_dom:
-	dsi_disable_scp_clk(dsidev);
-	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
-	return r;
-}
-
-static void dsi_cio_uninit(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	/* DDR_CLK_ALWAYS_ON */
-	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
-
-	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
-	dsi_disable_scp_clk(dsidev);
-	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
-}
-
-static void dsi_config_tx_fifo(struct platform_device *dsidev,
-		enum fifo_size size1, enum fifo_size size2,
-		enum fifo_size size3, enum fifo_size size4)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 r = 0;
-	int add = 0;
-	int i;
-
-	dsi->vc[0].tx_fifo_size = size1;
-	dsi->vc[1].tx_fifo_size = size2;
-	dsi->vc[2].tx_fifo_size = size3;
-	dsi->vc[3].tx_fifo_size = size4;
-
-	for (i = 0; i < 4; i++) {
-		u8 v;
-		int size = dsi->vc[i].tx_fifo_size;
-
-		if (add + size > 4) {
-			DSSERR("Illegal FIFO configuration\n");
-			BUG();
-			return;
-		}
-
-		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
-		r |= v << (8 * i);
-		/*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
-		add += size;
-	}
-
-	dsi_write_reg(dsidev, DSI_TX_FIFO_VC_SIZE, r);
-}
-
-static void dsi_config_rx_fifo(struct platform_device *dsidev,
-		enum fifo_size size1, enum fifo_size size2,
-		enum fifo_size size3, enum fifo_size size4)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 r = 0;
-	int add = 0;
-	int i;
-
-	dsi->vc[0].rx_fifo_size = size1;
-	dsi->vc[1].rx_fifo_size = size2;
-	dsi->vc[2].rx_fifo_size = size3;
-	dsi->vc[3].rx_fifo_size = size4;
-
-	for (i = 0; i < 4; i++) {
-		u8 v;
-		int size = dsi->vc[i].rx_fifo_size;
-
-		if (add + size > 4) {
-			DSSERR("Illegal FIFO configuration\n");
-			BUG();
-			return;
-		}
-
-		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
-		r |= v << (8 * i);
-		/*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
-		add += size;
-	}
-
-	dsi_write_reg(dsidev, DSI_RX_FIFO_VC_SIZE, r);
-}
-
-static int dsi_force_tx_stop_mode_io(struct platform_device *dsidev)
-{
-	u32 r;
-
-	r = dsi_read_reg(dsidev, DSI_TIMING1);
-	r = FLD_MOD(r, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
-	dsi_write_reg(dsidev, DSI_TIMING1, r);
-
-	if (wait_for_bit_change(dsidev, DSI_TIMING1, 15, 0) != 0) {
-		DSSERR("TX_STOP bit not going down\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static bool dsi_vc_is_enabled(struct platform_device *dsidev, int channel)
-{
-	return REG_GET(dsidev, DSI_VC_CTRL(channel), 0, 0);
-}
-
-static void dsi_packet_sent_handler_vp(void *data, u32 mask)
-{
-	struct dsi_packet_sent_handler_data *vp_data =
-		(struct dsi_packet_sent_handler_data *) data;
-	struct dsi_data *dsi = dsi_get_dsidrv_data(vp_data->dsidev);
-	const int channel = dsi->update_channel;
-	u8 bit = dsi->te_enabled ? 30 : 31;
-
-	if (REG_GET(vp_data->dsidev, DSI_VC_TE(channel), bit, bit) == 0)
-		complete(vp_data->completion);
-}
-
-static int dsi_sync_vc_vp(struct platform_device *dsidev, int channel)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	DECLARE_COMPLETION_ONSTACK(completion);
-	struct dsi_packet_sent_handler_data vp_data = { dsidev, &completion };
-	int r = 0;
-	u8 bit;
-
-	bit = dsi->te_enabled ? 30 : 31;
-
-	r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
-		&vp_data, DSI_VC_IRQ_PACKET_SENT);
-	if (r)
-		goto err0;
-
-	/* Wait for completion only if TE_EN/TE_START is still set */
-	if (REG_GET(dsidev, DSI_VC_TE(channel), bit, bit)) {
-		if (wait_for_completion_timeout(&completion,
-				msecs_to_jiffies(10)) == 0) {
-			DSSERR("Failed to complete previous frame transfer\n");
-			r = -EIO;
-			goto err1;
-		}
-	}
-
-	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
-		&vp_data, DSI_VC_IRQ_PACKET_SENT);
-
-	return 0;
-err1:
-	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
-		&vp_data, DSI_VC_IRQ_PACKET_SENT);
-err0:
-	return r;
-}
-
-static void dsi_packet_sent_handler_l4(void *data, u32 mask)
-{
-	struct dsi_packet_sent_handler_data *l4_data =
-		(struct dsi_packet_sent_handler_data *) data;
-	struct dsi_data *dsi = dsi_get_dsidrv_data(l4_data->dsidev);
-	const int channel = dsi->update_channel;
-
-	if (REG_GET(l4_data->dsidev, DSI_VC_CTRL(channel), 5, 5) == 0)
-		complete(l4_data->completion);
-}
-
-static int dsi_sync_vc_l4(struct platform_device *dsidev, int channel)
-{
-	DECLARE_COMPLETION_ONSTACK(completion);
-	struct dsi_packet_sent_handler_data l4_data = { dsidev, &completion };
-	int r = 0;
-
-	r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
-		&l4_data, DSI_VC_IRQ_PACKET_SENT);
-	if (r)
-		goto err0;
-
-	/* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */
-	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 5, 5)) {
-		if (wait_for_completion_timeout(&completion,
-				msecs_to_jiffies(10)) == 0) {
-			DSSERR("Failed to complete previous l4 transfer\n");
-			r = -EIO;
-			goto err1;
-		}
-	}
-
-	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
-		&l4_data, DSI_VC_IRQ_PACKET_SENT);
-
-	return 0;
-err1:
-	dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
-		&l4_data, DSI_VC_IRQ_PACKET_SENT);
-err0:
-	return r;
-}
-
-static int dsi_sync_vc(struct platform_device *dsidev, int channel)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	WARN_ON(in_interrupt());
-
-	if (!dsi_vc_is_enabled(dsidev, channel))
-		return 0;
-
-	switch (dsi->vc[channel].source) {
-	case DSI_VC_SOURCE_VP:
-		return dsi_sync_vc_vp(dsidev, channel);
-	case DSI_VC_SOURCE_L4:
-		return dsi_sync_vc_l4(dsidev, channel);
-	default:
-		BUG();
-		return -EINVAL;
-	}
-}
-
-static int dsi_vc_enable(struct platform_device *dsidev, int channel,
-		bool enable)
-{
-	DSSDBG("dsi_vc_enable channel %d, enable %d\n",
-			channel, enable);
-
-	enable = enable ? 1 : 0;
-
-	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 0, 0);
-
-	if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel),
-		0, enable) != enable) {
-			DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
-			return -EIO;
-	}
-
-	return 0;
-}
-
-static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 r;
-
-	DSSDBG("Initial config of virtual channel %d", channel);
-
-	r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
-
-	if (FLD_GET(r, 15, 15)) /* VC_BUSY */
-		DSSERR("VC(%d) busy when trying to configure it!\n",
-				channel);
-
-	r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
-	r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN  */
-	r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
-	r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
-	r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
-	r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
-	r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
-	if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
-		r = FLD_MOD(r, 3, 11, 10);	/* OCP_WIDTH = 32 bit */
-
-	r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
-	r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
-
-	dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
-
-	dsi->vc[channel].source = DSI_VC_SOURCE_L4;
-}
-
-static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
-		enum dsi_vc_source source)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (dsi->vc[channel].source == source)
-		return 0;
-
-	DSSDBG("Source config of virtual channel %d", channel);
-
-	dsi_sync_vc(dsidev, channel);
-
-	dsi_vc_enable(dsidev, channel, 0);
-
-	/* VC_BUSY */
-	if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
-		DSSERR("vc(%d) busy when trying to config for VP\n", channel);
-		return -EIO;
-	}
-
-	/* SOURCE, 0 = L4, 1 = video port */
-	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
-
-	/* DCS_CMD_ENABLE */
-	if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
-		bool enable = source == DSI_VC_SOURCE_VP;
-		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
-	}
-
-	dsi_vc_enable(dsidev, channel, 1);
-
-	dsi->vc[channel].source = source;
-
-	return 0;
-}
-
-static void dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
-		bool enable)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	dsi_vc_enable(dsidev, channel, 0);
-	dsi_if_enable(dsidev, 0);
-
-	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 9, 9);
-
-	dsi_vc_enable(dsidev, channel, 1);
-	dsi_if_enable(dsidev, 1);
-
-	dsi_force_tx_stop_mode_io(dsidev);
-
-	/* start the DDR clock by sending a NULL packet */
-	if (dsi->vm_timings.ddr_clk_always_on && enable)
-		dsi_vc_send_null(dssdev, channel);
-}
-
-static void dsi_vc_flush_long_data(struct platform_device *dsidev, int channel)
-{
-	while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
-		u32 val;
-		val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
-		DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
-				(val >> 0) & 0xff,
-				(val >> 8) & 0xff,
-				(val >> 16) & 0xff,
-				(val >> 24) & 0xff);
-	}
-}
-
-static void dsi_show_rx_ack_with_err(u16 err)
-{
-	DSSERR("\tACK with ERROR (%#x):\n", err);
-	if (err & (1 << 0))
-		DSSERR("\t\tSoT Error\n");
-	if (err & (1 << 1))
-		DSSERR("\t\tSoT Sync Error\n");
-	if (err & (1 << 2))
-		DSSERR("\t\tEoT Sync Error\n");
-	if (err & (1 << 3))
-		DSSERR("\t\tEscape Mode Entry Command Error\n");
-	if (err & (1 << 4))
-		DSSERR("\t\tLP Transmit Sync Error\n");
-	if (err & (1 << 5))
-		DSSERR("\t\tHS Receive Timeout Error\n");
-	if (err & (1 << 6))
-		DSSERR("\t\tFalse Control Error\n");
-	if (err & (1 << 7))
-		DSSERR("\t\t(reserved7)\n");
-	if (err & (1 << 8))
-		DSSERR("\t\tECC Error, single-bit (corrected)\n");
-	if (err & (1 << 9))
-		DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
-	if (err & (1 << 10))
-		DSSERR("\t\tChecksum Error\n");
-	if (err & (1 << 11))
-		DSSERR("\t\tData type not recognized\n");
-	if (err & (1 << 12))
-		DSSERR("\t\tInvalid VC ID\n");
-	if (err & (1 << 13))
-		DSSERR("\t\tInvalid Transmission Length\n");
-	if (err & (1 << 14))
-		DSSERR("\t\t(reserved14)\n");
-	if (err & (1 << 15))
-		DSSERR("\t\tDSI Protocol Violation\n");
-}
-
-static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
-		int channel)
-{
-	/* RX_FIFO_NOT_EMPTY */
-	while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
-		u32 val;
-		u8 dt;
-		val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
-		DSSERR("\trawval %#08x\n", val);
-		dt = FLD_GET(val, 5, 0);
-		if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
-			u16 err = FLD_GET(val, 23, 8);
-			dsi_show_rx_ack_with_err(err);
-		} else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {
-			DSSERR("\tDCS short response, 1 byte: %#x\n",
-					FLD_GET(val, 23, 8));
-		} else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
-			DSSERR("\tDCS short response, 2 byte: %#x\n",
-					FLD_GET(val, 23, 8));
-		} else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
-			DSSERR("\tDCS long response, len %d\n",
-					FLD_GET(val, 23, 8));
-			dsi_vc_flush_long_data(dsidev, channel);
-		} else {
-			DSSERR("\tunknown datatype 0x%02x\n", dt);
-		}
-	}
-	return 0;
-}
-
-static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (dsi->debug_write || dsi->debug_read)
-		DSSDBG("dsi_vc_send_bta %d\n", channel);
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	/* RX_FIFO_NOT_EMPTY */
-	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
-		DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
-		dsi_vc_flush_receive_data(dsidev, channel);
-	}
-
-	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
-
-	/* flush posted write */
-	dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
-
-	return 0;
-}
-
-static int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	DECLARE_COMPLETION_ONSTACK(completion);
-	int r = 0;
-	u32 err;
-
-	r = dsi_register_isr_vc(dsidev, channel, dsi_completion_handler,
-			&completion, DSI_VC_IRQ_BTA);
-	if (r)
-		goto err0;
-
-	r = dsi_register_isr(dsidev, dsi_completion_handler, &completion,
-			DSI_IRQ_ERROR_MASK);
-	if (r)
-		goto err1;
-
-	r = dsi_vc_send_bta(dsidev, channel);
-	if (r)
-		goto err2;
-
-	if (wait_for_completion_timeout(&completion,
-				msecs_to_jiffies(500)) == 0) {
-		DSSERR("Failed to receive BTA\n");
-		r = -EIO;
-		goto err2;
-	}
-
-	err = dsi_get_errors(dsidev);
-	if (err) {
-		DSSERR("Error while sending BTA: %x\n", err);
-		r = -EIO;
-		goto err2;
-	}
-err2:
-	dsi_unregister_isr(dsidev, dsi_completion_handler, &completion,
-			DSI_IRQ_ERROR_MASK);
-err1:
-	dsi_unregister_isr_vc(dsidev, channel, dsi_completion_handler,
-			&completion, DSI_VC_IRQ_BTA);
-err0:
-	return r;
-}
-
-static inline void dsi_vc_write_long_header(struct platform_device *dsidev,
-		int channel, u8 data_type, u16 len, u8 ecc)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 val;
-	u8 data_id;
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	data_id = data_type | dsi->vc[channel].vc_id << 6;
-
-	val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
-		FLD_VAL(ecc, 31, 24);
-
-	dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_HEADER(channel), val);
-}
-
-static inline void dsi_vc_write_long_payload(struct platform_device *dsidev,
-		int channel, u8 b1, u8 b2, u8 b3, u8 b4)
-{
-	u32 val;
-
-	val = b4 << 24 | b3 << 16 | b2 << 8  | b1 << 0;
-
-/*	DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
-			b1, b2, b3, b4, val); */
-
-	dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
-}
-
-static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
-		u8 data_type, u8 *data, u16 len, u8 ecc)
-{
-	/*u32 val; */
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int i;
-	u8 *p;
-	int r = 0;
-	u8 b1, b2, b3, b4;
-
-	if (dsi->debug_write)
-		DSSDBG("dsi_vc_send_long, %d bytes\n", len);
-
-	/* len + header */
-	if (dsi->vc[channel].tx_fifo_size * 32 * 4 < len + 4) {
-		DSSERR("unable to send long packet: packet too long.\n");
-		return -EINVAL;
-	}
-
-	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
-
-	dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
-
-	p = data;
-	for (i = 0; i < len >> 2; i++) {
-		if (dsi->debug_write)
-			DSSDBG("\tsending full packet %d\n", i);
-
-		b1 = *p++;
-		b2 = *p++;
-		b3 = *p++;
-		b4 = *p++;
-
-		dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, b4);
-	}
-
-	i = len % 4;
-	if (i) {
-		b1 = 0; b2 = 0; b3 = 0;
-
-		if (dsi->debug_write)
-			DSSDBG("\tsending remainder bytes %d\n", i);
-
-		switch (i) {
-		case 3:
-			b1 = *p++;
-			b2 = *p++;
-			b3 = *p++;
-			break;
-		case 2:
-			b1 = *p++;
-			b2 = *p++;
-			break;
-		case 1:
-			b1 = *p++;
-			break;
-		}
-
-		dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, 0);
-	}
-
-	return r;
-}
-
-static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
-		u8 data_type, u16 data, u8 ecc)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 r;
-	u8 data_id;
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	if (dsi->debug_write)
-		DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
-				channel,
-				data_type, data & 0xff, (data >> 8) & 0xff);
-
-	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
-
-	if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
-		DSSERR("ERROR FIFO FULL, aborting transfer\n");
-		return -EINVAL;
-	}
-
-	data_id = data_type | dsi->vc[channel].vc_id << 6;
-
-	r = (data_id << 0) | (data << 8) | (ecc << 24);
-
-	dsi_write_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel), r);
-
-	return 0;
-}
-
-static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-
-	return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL,
-		0, 0);
-}
-
-static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
-		int channel, u8 *data, int len, enum dss_dsi_content_type type)
-{
-	int r;
-
-	if (len == 0) {
-		BUG_ON(type == DSS_DSI_CONTENT_DCS);
-		r = dsi_vc_send_short(dsidev, channel,
-				MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0);
-	} else if (len == 1) {
-		r = dsi_vc_send_short(dsidev, channel,
-				type == DSS_DSI_CONTENT_GENERIC ?
-				MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
-				MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
-	} else if (len == 2) {
-		r = dsi_vc_send_short(dsidev, channel,
-				type == DSS_DSI_CONTENT_GENERIC ?
-				MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
-				MIPI_DSI_DCS_SHORT_WRITE_PARAM,
-				data[0] | (data[1] << 8), 0);
-	} else {
-		r = dsi_vc_send_long(dsidev, channel,
-				type == DSS_DSI_CONTENT_GENERIC ?
-				MIPI_DSI_GENERIC_LONG_WRITE :
-				MIPI_DSI_DCS_LONG_WRITE, data, len, 0);
-	}
-
-	return r;
-}
-
-static int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
-		u8 *data, int len)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-
-	return dsi_vc_write_nosync_common(dsidev, channel, data, len,
-			DSS_DSI_CONTENT_DCS);
-}
-
-static int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
-		u8 *data, int len)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-
-	return dsi_vc_write_nosync_common(dsidev, channel, data, len,
-			DSS_DSI_CONTENT_GENERIC);
-}
-
-static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
-		u8 *data, int len, enum dss_dsi_content_type type)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	int r;
-
-	r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);
-	if (r)
-		goto err;
-
-	r = dsi_vc_send_bta_sync(dssdev, channel);
-	if (r)
-		goto err;
-
-	/* RX_FIFO_NOT_EMPTY */
-	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
-		DSSERR("rx fifo not empty after write, dumping data:\n");
-		dsi_vc_flush_receive_data(dsidev, channel);
-		r = -EIO;
-		goto err;
-	}
-
-	return 0;
-err:
-	DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n",
-			channel, data[0], len);
-	return r;
-}
-
-static int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
-		int len)
-{
-	return dsi_vc_write_common(dssdev, channel, data, len,
-			DSS_DSI_CONTENT_DCS);
-}
-
-static int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
-		int len)
-{
-	return dsi_vc_write_common(dssdev, channel, data, len,
-			DSS_DSI_CONTENT_GENERIC);
-}
-
-static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
-		int channel, u8 dcs_cmd)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r;
-
-	if (dsi->debug_read)
-		DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n",
-			channel, dcs_cmd);
-
-	r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
-	if (r) {
-		DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)"
-			" failed\n", channel, dcs_cmd);
-		return r;
-	}
-
-	return 0;
-}
-
-static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,
-		int channel, u8 *reqdata, int reqlen)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u16 data;
-	u8 data_type;
-	int r;
-
-	if (dsi->debug_read)
-		DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n",
-			channel, reqlen);
-
-	if (reqlen == 0) {
-		data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
-		data = 0;
-	} else if (reqlen == 1) {
-		data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
-		data = reqdata[0];
-	} else if (reqlen == 2) {
-		data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
-		data = reqdata[0] | (reqdata[1] << 8);
-	} else {
-		BUG();
-		return -EINVAL;
-	}
-
-	r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
-	if (r) {
-		DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)"
-			" failed\n", channel, reqlen);
-		return r;
-	}
-
-	return 0;
-}
-
-static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
-		u8 *buf, int buflen, enum dss_dsi_content_type type)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 val;
-	u8 dt;
-	int r;
-
-	/* RX_FIFO_NOT_EMPTY */
-	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
-		DSSERR("RX fifo empty when trying to read.\n");
-		r = -EIO;
-		goto err;
-	}
-
-	val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
-	if (dsi->debug_read)
-		DSSDBG("\theader: %08x\n", val);
-	dt = FLD_GET(val, 5, 0);
-	if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
-		u16 err = FLD_GET(val, 23, 8);
-		dsi_show_rx_ack_with_err(err);
-		r = -EIO;
-		goto err;
-
-	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
-			MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE :
-			MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {
-		u8 data = FLD_GET(val, 15, 8);
-		if (dsi->debug_read)
-			DSSDBG("\t%s short response, 1 byte: %02x\n",
-				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
-				"DCS", data);
-
-		if (buflen < 1) {
-			r = -EIO;
-			goto err;
-		}
-
-		buf[0] = data;
-
-		return 1;
-	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
-			MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE :
-			MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {
-		u16 data = FLD_GET(val, 23, 8);
-		if (dsi->debug_read)
-			DSSDBG("\t%s short response, 2 byte: %04x\n",
-				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
-				"DCS", data);
-
-		if (buflen < 2) {
-			r = -EIO;
-			goto err;
-		}
-
-		buf[0] = data & 0xff;
-		buf[1] = (data >> 8) & 0xff;
-
-		return 2;
-	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
-			MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE :
-			MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {
-		int w;
-		int len = FLD_GET(val, 23, 8);
-		if (dsi->debug_read)
-			DSSDBG("\t%s long response, len %d\n",
-				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
-				"DCS", len);
-
-		if (len > buflen) {
-			r = -EIO;
-			goto err;
-		}
-
-		/* two byte checksum ends the packet, not included in len */
-		for (w = 0; w < len + 2;) {
-			int b;
-			val = dsi_read_reg(dsidev,
-				DSI_VC_SHORT_PACKET_HEADER(channel));
-			if (dsi->debug_read)
-				DSSDBG("\t\t%02x %02x %02x %02x\n",
-						(val >> 0) & 0xff,
-						(val >> 8) & 0xff,
-						(val >> 16) & 0xff,
-						(val >> 24) & 0xff);
-
-			for (b = 0; b < 4; ++b) {
-				if (w < len)
-					buf[w] = (val >> (b * 8)) & 0xff;
-				/* we discard the 2 byte checksum */
-				++w;
-			}
-		}
-
-		return len;
-	} else {
-		DSSERR("\tunknown datatype 0x%02x\n", dt);
-		r = -EIO;
-		goto err;
-	}
-
-err:
-	DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
-		type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
-
-	return r;
-}
-
-static int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
-		u8 *buf, int buflen)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	int r;
-
-	r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
-	if (r)
-		goto err;
-
-	r = dsi_vc_send_bta_sync(dssdev, channel);
-	if (r)
-		goto err;
-
-	r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
-		DSS_DSI_CONTENT_DCS);
-	if (r < 0)
-		goto err;
-
-	if (r != buflen) {
-		r = -EIO;
-		goto err;
-	}
-
-	return 0;
-err:
-	DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
-	return r;
-}
-
-static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
-		u8 *reqdata, int reqlen, u8 *buf, int buflen)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	int r;
-
-	r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);
-	if (r)
-		return r;
-
-	r = dsi_vc_send_bta_sync(dssdev, channel);
-	if (r)
-		return r;
-
-	r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
-		DSS_DSI_CONTENT_GENERIC);
-	if (r < 0)
-		return r;
-
-	if (r != buflen) {
-		r = -EIO;
-		return r;
-	}
-
-	return 0;
-}
-
-static int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
-		u16 len)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-
-	return dsi_vc_send_short(dsidev, channel,
-			MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
-}
-
-static int dsi_enter_ulps(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	DECLARE_COMPLETION_ONSTACK(completion);
-	int r, i;
-	unsigned mask;
-
-	DSSDBG("Entering ULPS");
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	WARN_ON(dsi->ulps_enabled);
-
-	if (dsi->ulps_enabled)
-		return 0;
-
-	/* DDR_CLK_ALWAYS_ON */
-	if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
-		dsi_if_enable(dsidev, 0);
-		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
-		dsi_if_enable(dsidev, 1);
-	}
-
-	dsi_sync_vc(dsidev, 0);
-	dsi_sync_vc(dsidev, 1);
-	dsi_sync_vc(dsidev, 2);
-	dsi_sync_vc(dsidev, 3);
-
-	dsi_force_tx_stop_mode_io(dsidev);
-
-	dsi_vc_enable(dsidev, 0, false);
-	dsi_vc_enable(dsidev, 1, false);
-	dsi_vc_enable(dsidev, 2, false);
-	dsi_vc_enable(dsidev, 3, false);
-
-	if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 16, 16)) {	/* HS_BUSY */
-		DSSERR("HS busy when enabling ULPS\n");
-		return -EIO;
-	}
-
-	if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 17, 17)) {	/* LP_BUSY */
-		DSSERR("LP busy when enabling ULPS\n");
-		return -EIO;
-	}
-
-	r = dsi_register_isr_cio(dsidev, dsi_completion_handler, &completion,
-			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
-	if (r)
-		return r;
-
-	mask = 0;
-
-	for (i = 0; i < dsi->num_lanes_supported; ++i) {
-		if (dsi->lanes[i].function == DSI_LANE_UNUSED)
-			continue;
-		mask |= 1 << i;
-	}
-	/* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
-	/* LANEx_ULPS_SIG2 */
-	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5);
-
-	/* flush posted write and wait for SCP interface to finish the write */
-	dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
-
-	if (wait_for_completion_timeout(&completion,
-				msecs_to_jiffies(1000)) == 0) {
-		DSSERR("ULPS enable timeout\n");
-		r = -EIO;
-		goto err;
-	}
-
-	dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
-			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
-
-	/* Reset LANEx_ULPS_SIG2 */
-	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5);
-
-	/* flush posted write and wait for SCP interface to finish the write */
-	dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
-
-	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
-
-	dsi_if_enable(dsidev, false);
-
-	dsi->ulps_enabled = true;
-
-	return 0;
-
-err:
-	dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
-			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
-	return r;
-}
-
-static void dsi_set_lp_rx_timeout(struct platform_device *dsidev,
-		unsigned ticks, bool x4, bool x16)
-{
-	unsigned long fck;
-	unsigned long total_ticks;
-	u32 r;
-
-	BUG_ON(ticks > 0x1fff);
-
-	/* ticks in DSI_FCK */
-	fck = dsi_fclk_rate(dsidev);
-
-	r = dsi_read_reg(dsidev, DSI_TIMING2);
-	r = FLD_MOD(r, 1, 15, 15);	/* LP_RX_TO */
-	r = FLD_MOD(r, x16 ? 1 : 0, 14, 14);	/* LP_RX_TO_X16 */
-	r = FLD_MOD(r, x4 ? 1 : 0, 13, 13);	/* LP_RX_TO_X4 */
-	r = FLD_MOD(r, ticks, 12, 0);	/* LP_RX_COUNTER */
-	dsi_write_reg(dsidev, DSI_TIMING2, r);
-
-	total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
-
-	DSSDBG("LP_RX_TO %lu ticks (%#x%s%s) = %lu ns\n",
-			total_ticks,
-			ticks, x4 ? " x4" : "", x16 ? " x16" : "",
-			(total_ticks * 1000) / (fck / 1000 / 1000));
-}
-
-static void dsi_set_ta_timeout(struct platform_device *dsidev, unsigned ticks,
-		bool x8, bool x16)
-{
-	unsigned long fck;
-	unsigned long total_ticks;
-	u32 r;
-
-	BUG_ON(ticks > 0x1fff);
-
-	/* ticks in DSI_FCK */
-	fck = dsi_fclk_rate(dsidev);
-
-	r = dsi_read_reg(dsidev, DSI_TIMING1);
-	r = FLD_MOD(r, 1, 31, 31);	/* TA_TO */
-	r = FLD_MOD(r, x16 ? 1 : 0, 30, 30);	/* TA_TO_X16 */
-	r = FLD_MOD(r, x8 ? 1 : 0, 29, 29);	/* TA_TO_X8 */
-	r = FLD_MOD(r, ticks, 28, 16);	/* TA_TO_COUNTER */
-	dsi_write_reg(dsidev, DSI_TIMING1, r);
-
-	total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1);
-
-	DSSDBG("TA_TO %lu ticks (%#x%s%s) = %lu ns\n",
-			total_ticks,
-			ticks, x8 ? " x8" : "", x16 ? " x16" : "",
-			(total_ticks * 1000) / (fck / 1000 / 1000));
-}
-
-static void dsi_set_stop_state_counter(struct platform_device *dsidev,
-		unsigned ticks, bool x4, bool x16)
-{
-	unsigned long fck;
-	unsigned long total_ticks;
-	u32 r;
-
-	BUG_ON(ticks > 0x1fff);
-
-	/* ticks in DSI_FCK */
-	fck = dsi_fclk_rate(dsidev);
-
-	r = dsi_read_reg(dsidev, DSI_TIMING1);
-	r = FLD_MOD(r, 1, 15, 15);	/* FORCE_TX_STOP_MODE_IO */
-	r = FLD_MOD(r, x16 ? 1 : 0, 14, 14);	/* STOP_STATE_X16_IO */
-	r = FLD_MOD(r, x4 ? 1 : 0, 13, 13);	/* STOP_STATE_X4_IO */
-	r = FLD_MOD(r, ticks, 12, 0);	/* STOP_STATE_COUNTER_IO */
-	dsi_write_reg(dsidev, DSI_TIMING1, r);
-
-	total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
-
-	DSSDBG("STOP_STATE_COUNTER %lu ticks (%#x%s%s) = %lu ns\n",
-			total_ticks,
-			ticks, x4 ? " x4" : "", x16 ? " x16" : "",
-			(total_ticks * 1000) / (fck / 1000 / 1000));
-}
-
-static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
-		unsigned ticks, bool x4, bool x16)
-{
-	unsigned long fck;
-	unsigned long total_ticks;
-	u32 r;
-
-	BUG_ON(ticks > 0x1fff);
-
-	/* ticks in TxByteClkHS */
-	fck = dsi_get_txbyteclkhs(dsidev);
-
-	r = dsi_read_reg(dsidev, DSI_TIMING2);
-	r = FLD_MOD(r, 1, 31, 31);	/* HS_TX_TO */
-	r = FLD_MOD(r, x16 ? 1 : 0, 30, 30);	/* HS_TX_TO_X16 */
-	r = FLD_MOD(r, x4 ? 1 : 0, 29, 29);	/* HS_TX_TO_X8 (4 really) */
-	r = FLD_MOD(r, ticks, 28, 16);	/* HS_TX_TO_COUNTER */
-	dsi_write_reg(dsidev, DSI_TIMING2, r);
-
-	total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
-
-	DSSDBG("HS_TX_TO %lu ticks (%#x%s%s) = %lu ns\n",
-			total_ticks,
-			ticks, x4 ? " x4" : "", x16 ? " x16" : "",
-			(total_ticks * 1000) / (fck / 1000 / 1000));
-}
-
-static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int num_line_buffers;
-
-	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-		struct omap_video_timings *timings = &dsi->timings;
-		/*
-		 * Don't use line buffers if width is greater than the video
-		 * port's line buffer size
-		 */
-		if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
-			num_line_buffers = 0;
-		else
-			num_line_buffers = 2;
-	} else {
-		/* Use maximum number of line buffers in command mode */
-		num_line_buffers = 2;
-	}
-
-	/* LINE_BUFFER */
-	REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
-}
-
-static void dsi_config_vp_sync_events(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	bool sync_end;
-	u32 r;
-
-	if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE)
-		sync_end = true;
-	else
-		sync_end = false;
-
-	r = dsi_read_reg(dsidev, DSI_CTRL);
-	r = FLD_MOD(r, 1, 9, 9);		/* VP_DE_POL */
-	r = FLD_MOD(r, 1, 10, 10);		/* VP_HSYNC_POL */
-	r = FLD_MOD(r, 1, 11, 11);		/* VP_VSYNC_POL */
-	r = FLD_MOD(r, 1, 15, 15);		/* VP_VSYNC_START */
-	r = FLD_MOD(r, sync_end, 16, 16);	/* VP_VSYNC_END */
-	r = FLD_MOD(r, 1, 17, 17);		/* VP_HSYNC_START */
-	r = FLD_MOD(r, sync_end, 18, 18);	/* VP_HSYNC_END */
-	dsi_write_reg(dsidev, DSI_CTRL, r);
-}
-
-static void dsi_config_blanking_modes(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int blanking_mode = dsi->vm_timings.blanking_mode;
-	int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
-	int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
-	int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
-	u32 r;
-
-	/*
-	 * 0 = TX FIFO packets sent or LPS in corresponding blanking periods
-	 * 1 = Long blanking packets are sent in corresponding blanking periods
-	 */
-	r = dsi_read_reg(dsidev, DSI_CTRL);
-	r = FLD_MOD(r, blanking_mode, 20, 20);		/* BLANKING_MODE */
-	r = FLD_MOD(r, hfp_blanking_mode, 21, 21);	/* HFP_BLANKING */
-	r = FLD_MOD(r, hbp_blanking_mode, 22, 22);	/* HBP_BLANKING */
-	r = FLD_MOD(r, hsa_blanking_mode, 23, 23);	/* HSA_BLANKING */
-	dsi_write_reg(dsidev, DSI_CTRL, r);
-}
-
-/*
- * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3
- * results in maximum transition time for data and clock lanes to enter and
- * exit HS mode. Hence, this is the scenario where the least amount of command
- * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS
- * clock cycles that can be used to interleave command mode data in HS so that
- * all scenarios are satisfied.
- */
-static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs,
-		int exit_hs, int exiths_clk, int ddr_pre, int ddr_post)
-{
-	int transition;
-
-	/*
-	 * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition
-	 * time of data lanes only, if it isn't set, we need to consider HS
-	 * transition time of both data and clock lanes. HS transition time
-	 * of Scenario 3 is considered.
-	 */
-	if (ddr_alwon) {
-		transition = enter_hs + exit_hs + max(enter_hs, 2) + 1;
-	} else {
-		int trans1, trans2;
-		trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1;
-		trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre +
-				enter_hs + 1;
-		transition = max(trans1, trans2);
-	}
-
-	return blank > transition ? blank - transition : 0;
-}
-
-/*
- * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1
- * results in maximum transition time for data lanes to enter and exit LP mode.
- * Hence, this is the scenario where the least amount of command mode data can
- * be interleaved. We program the minimum amount of bytes that can be
- * interleaved in LP so that all scenarios are satisfied.
- */
-static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
-		int lp_clk_div, int tdsi_fclk)
-{
-	int trans_lp;	/* time required for a LP transition, in TXBYTECLKHS */
-	int tlp_avail;	/* time left for interleaving commands, in CLKIN4DDR */
-	int ttxclkesc;	/* period of LP transmit escape clock, in CLKIN4DDR */
-	int thsbyte_clk = 16;	/* Period of TXBYTECLKHS clock, in CLKIN4DDR */
-	int lp_inter;	/* cmd mode data that can be interleaved, in bytes */
-
-	/* maximum LP transition time according to Scenario 1 */
-	trans_lp = exit_hs + max(enter_hs, 2) + 1;
-
-	/* CLKIN4DDR = 16 * TXBYTECLKHS */
-	tlp_avail = thsbyte_clk * (blank - trans_lp);
-
-	ttxclkesc = tdsi_fclk * lp_clk_div;
-
-	lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc -
-			26) / 16;
-
-	return max(lp_inter, 0);
-}
-
-static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int blanking_mode;
-	int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
-	int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div;
-	int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
-	int tclk_trail, ths_exit, exiths_clk;
-	bool ddr_alwon;
-	struct omap_video_timings *timings = &dsi->timings;
-	int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-	int ndl = dsi->num_lanes_used - 1;
-	int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1;
-	int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
-	int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
-	int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
-	int bl_interleave_hs = 0, bl_interleave_lp = 0;
-	u32 r;
-
-	r = dsi_read_reg(dsidev, DSI_CTRL);
-	blanking_mode = FLD_GET(r, 20, 20);
-	hfp_blanking_mode = FLD_GET(r, 21, 21);
-	hbp_blanking_mode = FLD_GET(r, 22, 22);
-	hsa_blanking_mode = FLD_GET(r, 23, 23);
-
-	r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
-	hbp = FLD_GET(r, 11, 0);
-	hfp = FLD_GET(r, 23, 12);
-	hsa = FLD_GET(r, 31, 24);
-
-	r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
-	ddr_clk_post = FLD_GET(r, 7, 0);
-	ddr_clk_pre = FLD_GET(r, 15, 8);
-
-	r = dsi_read_reg(dsidev, DSI_VM_TIMING7);
-	exit_hs_mode_lat = FLD_GET(r, 15, 0);
-	enter_hs_mode_lat = FLD_GET(r, 31, 16);
-
-	r = dsi_read_reg(dsidev, DSI_CLK_CTRL);
-	lp_clk_div = FLD_GET(r, 12, 0);
-	ddr_alwon = FLD_GET(r, 13, 13);
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
-	ths_exit = FLD_GET(r, 7, 0);
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
-	tclk_trail = FLD_GET(r, 15, 8);
-
-	exiths_clk = ths_exit + tclk_trail;
-
-	width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
-	bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
-
-	if (!hsa_blanking_mode) {
-		hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					exiths_clk, ddr_clk_pre, ddr_clk_post);
-		hsa_interleave_lp = dsi_compute_interleave_lp(hsa,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					lp_clk_div, dsi_fclk_hsdiv);
-	}
-
-	if (!hfp_blanking_mode) {
-		hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					exiths_clk, ddr_clk_pre, ddr_clk_post);
-		hfp_interleave_lp = dsi_compute_interleave_lp(hfp,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					lp_clk_div, dsi_fclk_hsdiv);
-	}
-
-	if (!hbp_blanking_mode) {
-		hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					exiths_clk, ddr_clk_pre, ddr_clk_post);
-
-		hbp_interleave_lp = dsi_compute_interleave_lp(hbp,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					lp_clk_div, dsi_fclk_hsdiv);
-	}
-
-	if (!blanking_mode) {
-		bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					exiths_clk, ddr_clk_pre, ddr_clk_post);
-
-		bl_interleave_lp = dsi_compute_interleave_lp(bllp,
-					enter_hs_mode_lat, exit_hs_mode_lat,
-					lp_clk_div, dsi_fclk_hsdiv);
-	}
-
-	DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n",
-		hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs,
-		bl_interleave_hs);
-
-	DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n",
-		hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp,
-		bl_interleave_lp);
-
-	r = dsi_read_reg(dsidev, DSI_VM_TIMING4);
-	r = FLD_MOD(r, hsa_interleave_hs, 23, 16);
-	r = FLD_MOD(r, hfp_interleave_hs, 15, 8);
-	r = FLD_MOD(r, hbp_interleave_hs, 7, 0);
-	dsi_write_reg(dsidev, DSI_VM_TIMING4, r);
-
-	r = dsi_read_reg(dsidev, DSI_VM_TIMING5);
-	r = FLD_MOD(r, hsa_interleave_lp, 23, 16);
-	r = FLD_MOD(r, hfp_interleave_lp, 15, 8);
-	r = FLD_MOD(r, hbp_interleave_lp, 7, 0);
-	dsi_write_reg(dsidev, DSI_VM_TIMING5, r);
-
-	r = dsi_read_reg(dsidev, DSI_VM_TIMING6);
-	r = FLD_MOD(r, bl_interleave_hs, 31, 15);
-	r = FLD_MOD(r, bl_interleave_lp, 16, 0);
-	dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
-}
-
-static int dsi_proto_config(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u32 r;
-	int buswidth = 0;
-
-	dsi_config_tx_fifo(dsidev, DSI_FIFO_SIZE_32,
-			DSI_FIFO_SIZE_32,
-			DSI_FIFO_SIZE_32,
-			DSI_FIFO_SIZE_32);
-
-	dsi_config_rx_fifo(dsidev, DSI_FIFO_SIZE_32,
-			DSI_FIFO_SIZE_32,
-			DSI_FIFO_SIZE_32,
-			DSI_FIFO_SIZE_32);
-
-	/* XXX what values for the timeouts? */
-	dsi_set_stop_state_counter(dsidev, 0x1000, false, false);
-	dsi_set_ta_timeout(dsidev, 0x1fff, true, true);
-	dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
-	dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
-
-	switch (dsi_get_pixel_size(dsi->pix_fmt)) {
-	case 16:
-		buswidth = 0;
-		break;
-	case 18:
-		buswidth = 1;
-		break;
-	case 24:
-		buswidth = 2;
-		break;
-	default:
-		BUG();
-		return -EINVAL;
-	}
-
-	r = dsi_read_reg(dsidev, DSI_CTRL);
-	r = FLD_MOD(r, 1, 1, 1);	/* CS_RX_EN */
-	r = FLD_MOD(r, 1, 2, 2);	/* ECC_RX_EN */
-	r = FLD_MOD(r, 1, 3, 3);	/* TX_FIFO_ARBITRATION */
-	r = FLD_MOD(r, 1, 4, 4);	/* VP_CLK_RATIO, always 1, see errata*/
-	r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
-	r = FLD_MOD(r, 0, 8, 8);	/* VP_CLK_POL */
-	r = FLD_MOD(r, 1, 14, 14);	/* TRIGGER_RESET_MODE */
-	r = FLD_MOD(r, 1, 19, 19);	/* EOT_ENABLE */
-	if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
-		r = FLD_MOD(r, 1, 24, 24);	/* DCS_CMD_ENABLE */
-		/* DCS_CMD_CODE, 1=start, 0=continue */
-		r = FLD_MOD(r, 0, 25, 25);
-	}
-
-	dsi_write_reg(dsidev, DSI_CTRL, r);
-
-	dsi_config_vp_num_line_buffers(dsidev);
-
-	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-		dsi_config_vp_sync_events(dsidev);
-		dsi_config_blanking_modes(dsidev);
-		dsi_config_cmd_mode_interleaving(dsidev);
-	}
-
-	dsi_vc_initial_config(dsidev, 0);
-	dsi_vc_initial_config(dsidev, 1);
-	dsi_vc_initial_config(dsidev, 2);
-	dsi_vc_initial_config(dsidev, 3);
-
-	return 0;
-}
-
-static void dsi_proto_timings(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
-	unsigned tclk_pre, tclk_post;
-	unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
-	unsigned ths_trail, ths_exit;
-	unsigned ddr_clk_pre, ddr_clk_post;
-	unsigned enter_hs_mode_lat, exit_hs_mode_lat;
-	unsigned ths_eot;
-	int ndl = dsi->num_lanes_used - 1;
-	u32 r;
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
-	ths_prepare = FLD_GET(r, 31, 24);
-	ths_prepare_ths_zero = FLD_GET(r, 23, 16);
-	ths_zero = ths_prepare_ths_zero - ths_prepare;
-	ths_trail = FLD_GET(r, 15, 8);
-	ths_exit = FLD_GET(r, 7, 0);
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
-	tlpx = FLD_GET(r, 20, 16) * 2;
-	tclk_trail = FLD_GET(r, 15, 8);
-	tclk_zero = FLD_GET(r, 7, 0);
-
-	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
-	tclk_prepare = FLD_GET(r, 7, 0);
-
-	/* min 8*UI */
-	tclk_pre = 20;
-	/* min 60ns + 52*UI */
-	tclk_post = ns2ddr(dsidev, 60) + 26;
-
-	ths_eot = DIV_ROUND_UP(4, ndl);
-
-	ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
-			4);
-	ddr_clk_post = DIV_ROUND_UP(tclk_post + ths_trail, 4) + ths_eot;
-
-	BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
-	BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
-
-	r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
-	r = FLD_MOD(r, ddr_clk_pre, 15, 8);
-	r = FLD_MOD(r, ddr_clk_post, 7, 0);
-	dsi_write_reg(dsidev, DSI_CLK_TIMING, r);
-
-	DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
-			ddr_clk_pre,
-			ddr_clk_post);
-
-	enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
-		DIV_ROUND_UP(ths_prepare, 4) +
-		DIV_ROUND_UP(ths_zero + 3, 4);
-
-	exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
-
-	r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
-		FLD_VAL(exit_hs_mode_lat, 15, 0);
-	dsi_write_reg(dsidev, DSI_VM_TIMING7, r);
-
-	DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
-			enter_hs_mode_lat, exit_hs_mode_lat);
-
-	 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-		/* TODO: Implement a video mode check_timings function */
-		int hsa = dsi->vm_timings.hsa;
-		int hfp = dsi->vm_timings.hfp;
-		int hbp = dsi->vm_timings.hbp;
-		int vsa = dsi->vm_timings.vsa;
-		int vfp = dsi->vm_timings.vfp;
-		int vbp = dsi->vm_timings.vbp;
-		int window_sync = dsi->vm_timings.window_sync;
-		bool hsync_end;
-		struct omap_video_timings *timings = &dsi->timings;
-		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-		int tl, t_he, width_bytes;
-
-		hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE;
-		t_he = hsync_end ?
-			((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
-
-		width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
-
-		/* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
-		tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
-			DIV_ROUND_UP(width_bytes + 6, ndl) + hbp;
-
-		DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
-			hfp, hsync_end ? hsa : 0, tl);
-		DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
-			vsa, timings->y_res);
-
-		r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
-		r = FLD_MOD(r, hbp, 11, 0);	/* HBP */
-		r = FLD_MOD(r, hfp, 23, 12);	/* HFP */
-		r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24);	/* HSA */
-		dsi_write_reg(dsidev, DSI_VM_TIMING1, r);
-
-		r = dsi_read_reg(dsidev, DSI_VM_TIMING2);
-		r = FLD_MOD(r, vbp, 7, 0);	/* VBP */
-		r = FLD_MOD(r, vfp, 15, 8);	/* VFP */
-		r = FLD_MOD(r, vsa, 23, 16);	/* VSA */
-		r = FLD_MOD(r, window_sync, 27, 24);	/* WINDOW_SYNC */
-		dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
-
-		r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
-		r = FLD_MOD(r, timings->y_res, 14, 0);	/* VACT */
-		r = FLD_MOD(r, tl, 31, 16);		/* TL */
-		dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
-	}
-}
-
-static int dsi_configure_pins(struct omap_dss_device *dssdev,
-		const struct omap_dsi_pin_config *pin_cfg)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int num_pins;
-	const int *pins;
-	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
-	int num_lanes;
-	int i;
-
-	static const enum dsi_lane_function functions[] = {
-		DSI_LANE_CLK,
-		DSI_LANE_DATA1,
-		DSI_LANE_DATA2,
-		DSI_LANE_DATA3,
-		DSI_LANE_DATA4,
-	};
-
-	num_pins = pin_cfg->num_pins;
-	pins = pin_cfg->pins;
-
-	if (num_pins < 4 || num_pins > dsi->num_lanes_supported * 2
-			|| num_pins % 2 != 0)
-		return -EINVAL;
-
-	for (i = 0; i < DSI_MAX_NR_LANES; ++i)
-		lanes[i].function = DSI_LANE_UNUSED;
-
-	num_lanes = 0;
-
-	for (i = 0; i < num_pins; i += 2) {
-		u8 lane, pol;
-		int dx, dy;
-
-		dx = pins[i];
-		dy = pins[i + 1];
-
-		if (dx < 0 || dx >= dsi->num_lanes_supported * 2)
-			return -EINVAL;
-
-		if (dy < 0 || dy >= dsi->num_lanes_supported * 2)
-			return -EINVAL;
-
-		if (dx & 1) {
-			if (dy != dx - 1)
-				return -EINVAL;
-			pol = 1;
-		} else {
-			if (dy != dx + 1)
-				return -EINVAL;
-			pol = 0;
-		}
-
-		lane = dx / 2;
-
-		lanes[lane].function = functions[i / 2];
-		lanes[lane].polarity = pol;
-		num_lanes++;
-	}
-
-	memcpy(dsi->lanes, lanes, sizeof(dsi->lanes));
-	dsi->num_lanes_used = num_lanes;
-
-	return 0;
-}
-
-static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dsi->output.manager;
-	int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-	struct omap_dss_device *out = &dsi->output;
-	u8 data_type;
-	u16 word_count;
-	int r;
-
-	if (out == NULL || out->manager == NULL) {
-		DSSERR("failed to enable display: no output/manager\n");
-		return -ENODEV;
-	}
-
-	r = dsi_display_init_dispc(dsidev, mgr);
-	if (r)
-		goto err_init_dispc;
-
-	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-		switch (dsi->pix_fmt) {
-		case OMAP_DSS_DSI_FMT_RGB888:
-			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
-			break;
-		case OMAP_DSS_DSI_FMT_RGB666:
-			data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
-			break;
-		case OMAP_DSS_DSI_FMT_RGB666_PACKED:
-			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
-			break;
-		case OMAP_DSS_DSI_FMT_RGB565:
-			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
-			break;
-		default:
-			r = -EINVAL;
-			goto err_pix_fmt;
-		}
-
-		dsi_if_enable(dsidev, false);
-		dsi_vc_enable(dsidev, channel, false);
-
-		/* MODE, 1 = video mode */
-		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
-
-		word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
-
-		dsi_vc_write_long_header(dsidev, channel, data_type,
-				word_count, 0);
-
-		dsi_vc_enable(dsidev, channel, true);
-		dsi_if_enable(dsidev, true);
-	}
-
-	r = dss_mgr_enable(mgr);
-	if (r)
-		goto err_mgr_enable;
-
-	return 0;
-
-err_mgr_enable:
-	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-		dsi_if_enable(dsidev, false);
-		dsi_vc_enable(dsidev, channel, false);
-	}
-err_pix_fmt:
-	dsi_display_uninit_dispc(dsidev, mgr);
-err_init_dispc:
-	return r;
-}
-
-static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dsi->output.manager;
-
-	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
-		dsi_if_enable(dsidev, false);
-		dsi_vc_enable(dsidev, channel, false);
-
-		/* MODE, 0 = command mode */
-		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
-
-		dsi_vc_enable(dsidev, channel, true);
-		dsi_if_enable(dsidev, true);
-	}
-
-	dss_mgr_disable(mgr);
-
-	dsi_display_uninit_dispc(dsidev, mgr);
-}
-
-static void dsi_update_screen_dispc(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_overlay_manager *mgr = dsi->output.manager;
-	unsigned bytespp;
-	unsigned bytespl;
-	unsigned bytespf;
-	unsigned total_len;
-	unsigned packet_payload;
-	unsigned packet_len;
-	u32 l;
-	int r;
-	const unsigned channel = dsi->update_channel;
-	const unsigned line_buf_size = dsi->line_buffer_size;
-	u16 w = dsi->timings.x_res;
-	u16 h = dsi->timings.y_res;
-
-	DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
-
-	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
-
-	bytespp	= dsi_get_pixel_size(dsi->pix_fmt) / 8;
-	bytespl = w * bytespp;
-	bytespf = bytespl * h;
-
-	/* NOTE: packet_payload has to be equal to N * bytespl, where N is
-	 * number of lines in a packet.  See errata about VP_CLK_RATIO */
-
-	if (bytespf < line_buf_size)
-		packet_payload = bytespf;
-	else
-		packet_payload = (line_buf_size) / bytespl * bytespl;
-
-	packet_len = packet_payload + 1;	/* 1 byte for DCS cmd */
-	total_len = (bytespf / packet_payload) * packet_len;
-
-	if (bytespf % packet_payload)
-		total_len += (bytespf % packet_payload) + 1;
-
-	l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
-	dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
-
-	dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
-		packet_len, 0);
-
-	if (dsi->te_enabled)
-		l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
-	else
-		l = FLD_MOD(l, 1, 31, 31); /* TE_START */
-	dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
-
-	/* We put SIDLEMODE to no-idle for the duration of the transfer,
-	 * because DSS interrupts are not capable of waking up the CPU and the
-	 * framedone interrupt could be delayed for quite a long time. I think
-	 * the same goes for any DSS interrupts, but for some reason I have not
-	 * seen the problem anywhere else than here.
-	 */
-	dispc_disable_sidle();
-
-	dsi_perf_mark_start(dsidev);
-
-	r = schedule_delayed_work(&dsi->framedone_timeout_work,
-		msecs_to_jiffies(250));
-	BUG_ON(r == 0);
-
-	dss_mgr_set_timings(mgr, &dsi->timings);
-
-	dss_mgr_start_update(mgr);
-
-	if (dsi->te_enabled) {
-		/* disable LP_RX_TO, so that we can receive TE.  Time to wait
-		 * for TE is longer than the timer allows */
-		REG_FLD_MOD(dsidev, DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
-
-		dsi_vc_send_bta(dsidev, channel);
-
-#ifdef DSI_CATCH_MISSING_TE
-		mod_timer(&dsi->te_timer, jiffies + msecs_to_jiffies(250));
-#endif
-	}
-}
-
-#ifdef DSI_CATCH_MISSING_TE
-static void dsi_te_timeout(unsigned long arg)
-{
-	DSSERR("TE not received for 250ms!\n");
-}
-#endif
-
-static void dsi_handle_framedone(struct platform_device *dsidev, int error)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	/* SIDLEMODE back to smart-idle */
-	dispc_enable_sidle();
-
-	if (dsi->te_enabled) {
-		/* enable LP_RX_TO again after the TE */
-		REG_FLD_MOD(dsidev, DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
-	}
-
-	dsi->framedone_callback(error, dsi->framedone_data);
-
-	if (!error)
-		dsi_perf_show(dsidev, "DISPC");
-}
-
-static void dsi_framedone_timeout_work_callback(struct work_struct *work)
-{
-	struct dsi_data *dsi = container_of(work, struct dsi_data,
-			framedone_timeout_work.work);
-	/* XXX While extremely unlikely, we could get FRAMEDONE interrupt after
-	 * 250ms which would conflict with this timeout work. What should be
-	 * done is first cancel the transfer on the HW, and then cancel the
-	 * possibly scheduled framedone work. However, cancelling the transfer
-	 * on the HW is buggy, and would probably require resetting the whole
-	 * DSI */
-
-	DSSERR("Framedone not received for 250ms!\n");
-
-	dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
-}
-
-static void dsi_framedone_irq_callback(void *data)
-{
-	struct platform_device *dsidev = (struct platform_device *) data;
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	/* Note: We get FRAMEDONE when DISPC has finished sending pixels and
-	 * turns itself off. However, DSI still has the pixels in its buffers,
-	 * and is sending the data.
-	 */
-
-	cancel_delayed_work(&dsi->framedone_timeout_work);
-
-	dsi_handle_framedone(dsidev, 0);
-}
-
-static int dsi_update(struct omap_dss_device *dssdev, int channel,
-		void (*callback)(int, void *), void *data)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	u16 dw, dh;
-
-	dsi_perf_mark_setup(dsidev);
-
-	dsi->update_channel = channel;
-
-	dsi->framedone_callback = callback;
-	dsi->framedone_data = data;
-
-	dw = dsi->timings.x_res;
-	dh = dsi->timings.y_res;
-
-#ifdef DSI_PERF_MEASURE
-	dsi->update_bytes = dw * dh *
-		dsi_get_pixel_size(dsi->pix_fmt) / 8;
-#endif
-	dsi_update_screen_dispc(dsidev);
-
-	return 0;
-}
-
-/* Display funcs */
-
-static int dsi_configure_dispc_clocks(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dispc_clock_info dispc_cinfo;
-	int r;
-	unsigned long fck;
-
-	fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-
-	dispc_cinfo.lck_div = dsi->user_dispc_cinfo.lck_div;
-	dispc_cinfo.pck_div = dsi->user_dispc_cinfo.pck_div;
-
-	r = dispc_calc_clock_rates(fck, &dispc_cinfo);
-	if (r) {
-		DSSERR("Failed to calc dispc clocks\n");
-		return r;
-	}
-
-	dsi->mgr_config.clock_info = dispc_cinfo;
-
-	return 0;
-}
-
-static int dsi_display_init_dispc(struct platform_device *dsidev,
-		struct omap_overlay_manager *mgr)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r;
-
-	dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ?
-			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
-			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
-
-	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
-		r = dss_mgr_register_framedone_handler(mgr,
-				dsi_framedone_irq_callback, dsidev);
-		if (r) {
-			DSSERR("can't register FRAMEDONE handler\n");
-			goto err;
-		}
-
-		dsi->mgr_config.stallmode = true;
-		dsi->mgr_config.fifohandcheck = true;
-	} else {
-		dsi->mgr_config.stallmode = false;
-		dsi->mgr_config.fifohandcheck = false;
-	}
-
-	/*
-	 * override interlace, logic level and edge related parameters in
-	 * omap_video_timings with default values
-	 */
-	dsi->timings.interlace = false;
-	dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
-
-	dss_mgr_set_timings(mgr, &dsi->timings);
-
-	r = dsi_configure_dispc_clocks(dsidev);
-	if (r)
-		goto err1;
-
-	dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
-	dsi->mgr_config.video_port_width =
-			dsi_get_pixel_size(dsi->pix_fmt);
-	dsi->mgr_config.lcden_sig_polarity = 0;
-
-	dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);
-
-	return 0;
-err1:
-	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
-		dss_mgr_unregister_framedone_handler(mgr,
-				dsi_framedone_irq_callback, dsidev);
-err:
-	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
-	return r;
-}
-
-static void dsi_display_uninit_dispc(struct platform_device *dsidev,
-		struct omap_overlay_manager *mgr)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
-		dss_mgr_unregister_framedone_handler(mgr,
-				dsi_framedone_irq_callback, dsidev);
-
-	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
-}
-
-static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cinfo;
-	int r;
-
-	cinfo = dsi->user_dsi_cinfo;
-
-	r = dsi_calc_clock_rates(dsidev, &cinfo);
-	if (r) {
-		DSSERR("Failed to calc dsi clocks\n");
-		return r;
-	}
-
-	r = dsi_pll_set_clock_div(dsidev, &cinfo);
-	if (r) {
-		DSSERR("Failed to set dsi clocks\n");
-		return r;
-	}
-
-	return 0;
-}
-
-static int dsi_display_init_dsi(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r;
-
-	r = dsi_pll_init(dsidev, true, true);
-	if (r)
-		goto err0;
-
-	r = dsi_configure_dsi_clocks(dsidev);
-	if (r)
-		goto err1;
-
-	dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
-			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
-			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
-
-	DSSDBG("PLL OK\n");
-
-	r = dsi_cio_init(dsidev);
-	if (r)
-		goto err2;
-
-	_dsi_print_reset_status(dsidev);
-
-	dsi_proto_timings(dsidev);
-	dsi_set_lp_clk_divisor(dsidev);
-
-	if (1)
-		_dsi_print_reset_status(dsidev);
-
-	r = dsi_proto_config(dsidev);
-	if (r)
-		goto err3;
-
-	/* enable interface */
-	dsi_vc_enable(dsidev, 0, 1);
-	dsi_vc_enable(dsidev, 1, 1);
-	dsi_vc_enable(dsidev, 2, 1);
-	dsi_vc_enable(dsidev, 3, 1);
-	dsi_if_enable(dsidev, 1);
-	dsi_force_tx_stop_mode_io(dsidev);
-
-	return 0;
-err3:
-	dsi_cio_uninit(dsidev);
-err2:
-	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
-err1:
-	dsi_pll_uninit(dsidev, true);
-err0:
-	return r;
-}
-
-static void dsi_display_uninit_dsi(struct platform_device *dsidev,
-		bool disconnect_lanes, bool enter_ulps)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (enter_ulps && !dsi->ulps_enabled)
-		dsi_enter_ulps(dsidev);
-
-	/* disable interface */
-	dsi_if_enable(dsidev, 0);
-	dsi_vc_enable(dsidev, 0, 0);
-	dsi_vc_enable(dsidev, 1, 0);
-	dsi_vc_enable(dsidev, 2, 0);
-	dsi_vc_enable(dsidev, 3, 0);
-
-	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
-	dsi_cio_uninit(dsidev);
-	dsi_pll_uninit(dsidev, disconnect_lanes);
-}
-
-static int dsi_display_enable(struct omap_dss_device *dssdev)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int r = 0;
-
-	DSSDBG("dsi_display_enable\n");
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	mutex_lock(&dsi->lock);
-
-	r = dsi_runtime_get(dsidev);
-	if (r)
-		goto err_get_dsi;
-
-	dsi_enable_pll_clock(dsidev, 1);
-
-	_dsi_initialize_irq(dsidev);
-
-	r = dsi_display_init_dsi(dsidev);
-	if (r)
-		goto err_init_dsi;
-
-	mutex_unlock(&dsi->lock);
-
-	return 0;
-
-err_init_dsi:
-	dsi_enable_pll_clock(dsidev, 0);
-	dsi_runtime_put(dsidev);
-err_get_dsi:
-	mutex_unlock(&dsi->lock);
-	DSSDBG("dsi_display_enable FAILED\n");
-	return r;
-}
-
-static void dsi_display_disable(struct omap_dss_device *dssdev,
-		bool disconnect_lanes, bool enter_ulps)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	DSSDBG("dsi_display_disable\n");
-
-	WARN_ON(!dsi_bus_is_locked(dsidev));
-
-	mutex_lock(&dsi->lock);
-
-	dsi_sync_vc(dsidev, 0);
-	dsi_sync_vc(dsidev, 1);
-	dsi_sync_vc(dsidev, 2);
-	dsi_sync_vc(dsidev, 3);
-
-	dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps);
-
-	dsi_runtime_put(dsidev);
-	dsi_enable_pll_clock(dsidev, 0);
-
-	mutex_unlock(&dsi->lock);
-}
-
-static int dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	dsi->te_enabled = enable;
-	return 0;
-}
-
-#ifdef PRINT_VERBOSE_VM_TIMINGS
-static void print_dsi_vm(const char *str,
-		const struct omap_dss_dsi_videomode_timings *t)
-{
-	unsigned long byteclk = t->hsclk / 4;
-	int bl, wc, pps, tot;
-
-	wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
-	pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
-	bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
-	tot = bl + pps;
-
-#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
-
-	pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
-			"%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
-			str,
-			byteclk,
-			t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
-			bl, pps, tot,
-			TO_DSI_T(t->hss),
-			TO_DSI_T(t->hsa),
-			TO_DSI_T(t->hse),
-			TO_DSI_T(t->hbp),
-			TO_DSI_T(pps),
-			TO_DSI_T(t->hfp),
-
-			TO_DSI_T(bl),
-			TO_DSI_T(pps),
-
-			TO_DSI_T(tot));
-#undef TO_DSI_T
-}
-
-static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
-{
-	unsigned long pck = t->pixelclock;
-	int hact, bl, tot;
-
-	hact = t->x_res;
-	bl = t->hsw + t->hbp + t->hfp;
-	tot = hact + bl;
-
-#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
-
-	pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
-			"%u/%u/%u/%u = %u + %u = %u\n",
-			str,
-			pck,
-			t->hsw, t->hbp, hact, t->hfp,
-			bl, hact, tot,
-			TO_DISPC_T(t->hsw),
-			TO_DISPC_T(t->hbp),
-			TO_DISPC_T(hact),
-			TO_DISPC_T(t->hfp),
-			TO_DISPC_T(bl),
-			TO_DISPC_T(hact),
-			TO_DISPC_T(tot));
-#undef TO_DISPC_T
-}
-
-/* note: this is not quite accurate */
-static void print_dsi_dispc_vm(const char *str,
-		const struct omap_dss_dsi_videomode_timings *t)
-{
-	struct omap_video_timings vm = { 0 };
-	unsigned long byteclk = t->hsclk / 4;
-	unsigned long pck;
-	u64 dsi_tput;
-	int dsi_hact, dsi_htot;
-
-	dsi_tput = (u64)byteclk * t->ndl * 8;
-	pck = (u32)div64_u64(dsi_tput, t->bitspp);
-	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
-	dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
-
-	vm.pixelclock = pck;
-	vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
-	vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
-	vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
-	vm.x_res = t->hact;
-
-	print_dispc_vm(str, &vm);
-}
-#endif /* PRINT_VERBOSE_VM_TIMINGS */
-
-static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
-		unsigned long pck, void *data)
-{
-	struct dsi_clk_calc_ctx *ctx = data;
-	struct omap_video_timings *t = &ctx->dispc_vm;
-
-	ctx->dispc_cinfo.lck_div = lckd;
-	ctx->dispc_cinfo.pck_div = pckd;
-	ctx->dispc_cinfo.lck = lck;
-	ctx->dispc_cinfo.pck = pck;
-
-	*t = *ctx->config->timings;
-	t->pixelclock = pck;
-	t->x_res = ctx->config->timings->x_res;
-	t->y_res = ctx->config->timings->y_res;
-	t->hsw = t->hfp = t->hbp = t->vsw = 1;
-	t->vfp = t->vbp = 0;
-
-	return true;
-}
-
-static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
-		void *data)
-{
-	struct dsi_clk_calc_ctx *ctx = data;
-
-	ctx->dsi_cinfo.regm_dispc = regm_dispc;
-	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
-
-	return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
-			dsi_cm_calc_dispc_cb, ctx);
-}
-
-static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
-		unsigned long pll, void *data)
-{
-	struct dsi_clk_calc_ctx *ctx = data;
-
-	ctx->dsi_cinfo.regn = regn;
-	ctx->dsi_cinfo.regm = regm;
-	ctx->dsi_cinfo.fint = fint;
-	ctx->dsi_cinfo.clkin4ddr = pll;
-
-	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
-			dsi_cm_calc_hsdiv_cb, ctx);
-}
-
-static bool dsi_cm_calc(struct dsi_data *dsi,
-		const struct omap_dss_dsi_config *cfg,
-		struct dsi_clk_calc_ctx *ctx)
-{
-	unsigned long clkin;
-	int bitspp, ndl;
-	unsigned long pll_min, pll_max;
-	unsigned long pck, txbyteclk;
-
-	clkin = clk_get_rate(dsi->sys_clk);
-	bitspp = dsi_get_pixel_size(cfg->pixel_format);
-	ndl = dsi->num_lanes_used - 1;
-
-	/*
-	 * Here we should calculate minimum txbyteclk to be able to send the
-	 * frame in time, and also to handle TE. That's not very simple, though,
-	 * especially as we go to LP between each pixel packet due to HW
-	 * "feature". So let's just estimate very roughly and multiply by 1.5.
-	 */
-	pck = cfg->timings->pixelclock;
-	pck = pck * 3 / 2;
-	txbyteclk = pck * bitspp / 8 / ndl;
-
-	memset(ctx, 0, sizeof(*ctx));
-	ctx->dsidev = dsi->pdev;
-	ctx->config = cfg;
-	ctx->req_pck_min = pck;
-	ctx->req_pck_nom = pck;
-	ctx->req_pck_max = pck * 3 / 2;
-	ctx->dsi_cinfo.clkin = clkin;
-
-	pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
-	pll_max = cfg->hs_clk_max * 4;
-
-	return dsi_pll_calc(dsi->pdev, clkin,
-			pll_min, pll_max,
-			dsi_cm_calc_pll_cb, ctx);
-}
-
-static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
-	const struct omap_dss_dsi_config *cfg = ctx->config;
-	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
-	int ndl = dsi->num_lanes_used - 1;
-	unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
-	unsigned long byteclk = hsclk / 4;
-
-	unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
-	int xres;
-	int panel_htot, panel_hbl; /* pixels */
-	int dispc_htot, dispc_hbl; /* pixels */
-	int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
-	int hfp, hsa, hbp;
-	const struct omap_video_timings *req_vm;
-	struct omap_video_timings *dispc_vm;
-	struct omap_dss_dsi_videomode_timings *dsi_vm;
-	u64 dsi_tput, dispc_tput;
-
-	dsi_tput = (u64)byteclk * ndl * 8;
-
-	req_vm = cfg->timings;
-	req_pck_min = ctx->req_pck_min;
-	req_pck_max = ctx->req_pck_max;
-	req_pck_nom = ctx->req_pck_nom;
-
-	dispc_pck = ctx->dispc_cinfo.pck;
-	dispc_tput = (u64)dispc_pck * bitspp;
-
-	xres = req_vm->x_res;
-
-	panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
-	panel_htot = xres + panel_hbl;
-
-	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
-
-	/*
-	 * When there are no line buffers, DISPC and DSI must have the
-	 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
-	 */
-	if (dsi->line_buffer_size < xres * bitspp / 8) {
-		if (dispc_tput != dsi_tput)
-			return false;
-	} else {
-		if (dispc_tput < dsi_tput)
-			return false;
-	}
-
-	/* DSI tput must be over the min requirement */
-	if (dsi_tput < (u64)bitspp * req_pck_min)
-		return false;
-
-	/* When non-burst mode, DSI tput must be below max requirement. */
-	if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
-		if (dsi_tput > (u64)bitspp * req_pck_max)
-			return false;
-	}
-
-	hss = DIV_ROUND_UP(4, ndl);
-
-	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
-		if (ndl == 3 && req_vm->hsw == 0)
-			hse = 1;
-		else
-			hse = DIV_ROUND_UP(4, ndl);
-	} else {
-		hse = 0;
-	}
-
-	/* DSI htot to match the panel's nominal pck */
-	dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
-
-	/* fail if there would be no time for blanking */
-	if (dsi_htot < hss + hse + dsi_hact)
-		return false;
-
-	/* total DSI blanking needed to achieve panel's TL */
-	dsi_hbl = dsi_htot - dsi_hact;
-
-	/* DISPC htot to match the DSI TL */
-	dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
-
-	/* verify that the DSI and DISPC TLs are the same */
-	if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
-		return false;
-
-	dispc_hbl = dispc_htot - xres;
-
-	/* setup DSI videomode */
-
-	dsi_vm = &ctx->dsi_vm;
-	memset(dsi_vm, 0, sizeof(*dsi_vm));
-
-	dsi_vm->hsclk = hsclk;
-
-	dsi_vm->ndl = ndl;
-	dsi_vm->bitspp = bitspp;
-
-	if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
-		hsa = 0;
-	} else if (ndl == 3 && req_vm->hsw == 0) {
-		hsa = 0;
-	} else {
-		hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
-		hsa = max(hsa - hse, 1);
-	}
-
-	hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
-	hbp = max(hbp, 1);
-
-	hfp = dsi_hbl - (hss + hsa + hse + hbp);
-	if (hfp < 1) {
-		int t;
-		/* we need to take cycles from hbp */
-
-		t = 1 - hfp;
-		hbp = max(hbp - t, 1);
-		hfp = dsi_hbl - (hss + hsa + hse + hbp);
-
-		if (hfp < 1 && hsa > 0) {
-			/* we need to take cycles from hsa */
-			t = 1 - hfp;
-			hsa = max(hsa - t, 1);
-			hfp = dsi_hbl - (hss + hsa + hse + hbp);
-		}
-	}
-
-	if (hfp < 1)
-		return false;
-
-	dsi_vm->hss = hss;
-	dsi_vm->hsa = hsa;
-	dsi_vm->hse = hse;
-	dsi_vm->hbp = hbp;
-	dsi_vm->hact = xres;
-	dsi_vm->hfp = hfp;
-
-	dsi_vm->vsa = req_vm->vsw;
-	dsi_vm->vbp = req_vm->vbp;
-	dsi_vm->vact = req_vm->y_res;
-	dsi_vm->vfp = req_vm->vfp;
-
-	dsi_vm->trans_mode = cfg->trans_mode;
-
-	dsi_vm->blanking_mode = 0;
-	dsi_vm->hsa_blanking_mode = 1;
-	dsi_vm->hfp_blanking_mode = 1;
-	dsi_vm->hbp_blanking_mode = 1;
-
-	dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
-	dsi_vm->window_sync = 4;
-
-	/* setup DISPC videomode */
-
-	dispc_vm = &ctx->dispc_vm;
-	*dispc_vm = *req_vm;
-	dispc_vm->pixelclock = dispc_pck;
-
-	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
-		hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
-				req_pck_nom);
-		hsa = max(hsa, 1);
-	} else {
-		hsa = 1;
-	}
-
-	hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
-	hbp = max(hbp, 1);
-
-	hfp = dispc_hbl - hsa - hbp;
-	if (hfp < 1) {
-		int t;
-		/* we need to take cycles from hbp */
-
-		t = 1 - hfp;
-		hbp = max(hbp - t, 1);
-		hfp = dispc_hbl - hsa - hbp;
-
-		if (hfp < 1) {
-			/* we need to take cycles from hsa */
-			t = 1 - hfp;
-			hsa = max(hsa - t, 1);
-			hfp = dispc_hbl - hsa - hbp;
-		}
-	}
-
-	if (hfp < 1)
-		return false;
-
-	dispc_vm->hfp = hfp;
-	dispc_vm->hsw = hsa;
-	dispc_vm->hbp = hbp;
-
-	return true;
-}
-
-
-static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
-		unsigned long pck, void *data)
-{
-	struct dsi_clk_calc_ctx *ctx = data;
-
-	ctx->dispc_cinfo.lck_div = lckd;
-	ctx->dispc_cinfo.pck_div = pckd;
-	ctx->dispc_cinfo.lck = lck;
-	ctx->dispc_cinfo.pck = pck;
-
-	if (dsi_vm_calc_blanking(ctx) == false)
-		return false;
-
-#ifdef PRINT_VERBOSE_VM_TIMINGS
-	print_dispc_vm("dispc", &ctx->dispc_vm);
-	print_dsi_vm("dsi  ", &ctx->dsi_vm);
-	print_dispc_vm("req  ", ctx->config->timings);
-	print_dsi_dispc_vm("act  ", &ctx->dsi_vm);
-#endif
-
-	return true;
-}
-
-static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
-		void *data)
-{
-	struct dsi_clk_calc_ctx *ctx = data;
-	unsigned long pck_max;
-
-	ctx->dsi_cinfo.regm_dispc = regm_dispc;
-	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
-
-	/*
-	 * In burst mode we can let the dispc pck be arbitrarily high, but it
-	 * limits our scaling abilities. So for now, don't aim too high.
-	 */
-
-	if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
-		pck_max = ctx->req_pck_max + 10000000;
-	else
-		pck_max = ctx->req_pck_max;
-
-	return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
-			dsi_vm_calc_dispc_cb, ctx);
-}
-
-static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
-		unsigned long pll, void *data)
-{
-	struct dsi_clk_calc_ctx *ctx = data;
-
-	ctx->dsi_cinfo.regn = regn;
-	ctx->dsi_cinfo.regm = regm;
-	ctx->dsi_cinfo.fint = fint;
-	ctx->dsi_cinfo.clkin4ddr = pll;
-
-	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
-			dsi_vm_calc_hsdiv_cb, ctx);
-}
-
-static bool dsi_vm_calc(struct dsi_data *dsi,
-		const struct omap_dss_dsi_config *cfg,
-		struct dsi_clk_calc_ctx *ctx)
-{
-	const struct omap_video_timings *t = cfg->timings;
-	unsigned long clkin;
-	unsigned long pll_min;
-	unsigned long pll_max;
-	int ndl = dsi->num_lanes_used - 1;
-	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
-	unsigned long byteclk_min;
-
-	clkin = clk_get_rate(dsi->sys_clk);
-
-	memset(ctx, 0, sizeof(*ctx));
-	ctx->dsidev = dsi->pdev;
-	ctx->config = cfg;
-
-	ctx->dsi_cinfo.clkin = clkin;
-
-	/* these limits should come from the panel driver */
-	ctx->req_pck_min = t->pixelclock - 1000;
-	ctx->req_pck_nom = t->pixelclock;
-	ctx->req_pck_max = t->pixelclock + 1000;
-
-	byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
-	pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
-
-	if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
-		pll_max = cfg->hs_clk_max * 4;
-	} else {
-		unsigned long byteclk_max;
-		byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
-				ndl * 8);
-
-		pll_max = byteclk_max * 4 * 4;
-	}
-
-	return dsi_pll_calc(dsi->pdev, clkin,
-			pll_min, pll_max,
-			dsi_vm_calc_pll_cb, ctx);
-}
-
-static int dsi_set_config(struct omap_dss_device *dssdev,
-		const struct omap_dss_dsi_config *config)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clk_calc_ctx ctx;
-	bool ok;
-	int r;
-
-	mutex_lock(&dsi->lock);
-
-	dsi->pix_fmt = config->pixel_format;
-	dsi->mode = config->mode;
-
-	if (config->mode == OMAP_DSS_DSI_VIDEO_MODE)
-		ok = dsi_vm_calc(dsi, config, &ctx);
-	else
-		ok = dsi_cm_calc(dsi, config, &ctx);
-
-	if (!ok) {
-		DSSERR("failed to find suitable DSI clock settings\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
-
-	r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
-			config->lp_clk_max);
-	if (r) {
-		DSSERR("failed to find suitable DSI LP clock settings\n");
-		goto err;
-	}
-
-	dsi->user_dsi_cinfo = ctx.dsi_cinfo;
-	dsi->user_dispc_cinfo = ctx.dispc_cinfo;
-
-	dsi->timings = ctx.dispc_vm;
-	dsi->vm_timings = ctx.dsi_vm;
-
-	mutex_unlock(&dsi->lock);
-
-	return 0;
-err:
-	mutex_unlock(&dsi->lock);
-
-	return r;
-}
-
-/*
- * Return a hardcoded channel for the DSI output. This should work for
- * current use cases, but this can be later expanded to either resolve
- * the channel in some more dynamic manner, or get the channel as a user
- * parameter.
- */
-static enum omap_channel dsi_get_channel(int module_id)
-{
-	switch (omapdss_get_version()) {
-	case OMAPDSS_VER_OMAP24xx:
-		DSSWARN("DSI not supported\n");
-		return OMAP_DSS_CHANNEL_LCD;
-
-	case OMAPDSS_VER_OMAP34xx_ES1:
-	case OMAPDSS_VER_OMAP34xx_ES3:
-	case OMAPDSS_VER_OMAP3630:
-	case OMAPDSS_VER_AM35xx:
-		return OMAP_DSS_CHANNEL_LCD;
-
-	case OMAPDSS_VER_OMAP4430_ES1:
-	case OMAPDSS_VER_OMAP4430_ES2:
-	case OMAPDSS_VER_OMAP4:
-		switch (module_id) {
-		case 0:
-			return OMAP_DSS_CHANNEL_LCD;
-		case 1:
-			return OMAP_DSS_CHANNEL_LCD2;
-		default:
-			DSSWARN("unsupported module id\n");
-			return OMAP_DSS_CHANNEL_LCD;
-		}
-
-	case OMAPDSS_VER_OMAP5:
-		switch (module_id) {
-		case 0:
-			return OMAP_DSS_CHANNEL_LCD;
-		case 1:
-			return OMAP_DSS_CHANNEL_LCD3;
-		default:
-			DSSWARN("unsupported module id\n");
-			return OMAP_DSS_CHANNEL_LCD;
-		}
-
-	default:
-		DSSWARN("unsupported DSS version\n");
-		return OMAP_DSS_CHANNEL_LCD;
-	}
-}
-
-static int dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
-		if (!dsi->vc[i].dssdev) {
-			dsi->vc[i].dssdev = dssdev;
-			*channel = i;
-			return 0;
-		}
-	}
-
-	DSSERR("cannot get VC for display %s", dssdev->name);
-	return -ENOSPC;
-}
-
-static int dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if (vc_id < 0 || vc_id > 3) {
-		DSSERR("VC ID out of range\n");
-		return -EINVAL;
-	}
-
-	if (channel < 0 || channel > 3) {
-		DSSERR("Virtual Channel out of range\n");
-		return -EINVAL;
-	}
-
-	if (dsi->vc[channel].dssdev != dssdev) {
-		DSSERR("Virtual Channel not allocated to display %s\n",
-			dssdev->name);
-		return -EINVAL;
-	}
-
-	dsi->vc[channel].vc_id = vc_id;
-
-	return 0;
-}
-
-static void dsi_release_vc(struct omap_dss_device *dssdev, int channel)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	if ((channel >= 0 && channel <= 3) &&
-		dsi->vc[channel].dssdev == dssdev) {
-		dsi->vc[channel].dssdev = NULL;
-		dsi->vc[channel].vc_id = 0;
-	}
-}
-
-void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
-{
-	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1)
-		DSSERR("%s (%s) not active\n",
-			dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-			dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
-}
-
-void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
-{
-	if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1)
-		DSSERR("%s (%s) not active\n",
-			dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-			dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
-}
-
-static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
-	dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
-	dsi->regm_dispc_max =
-		dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
-	dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
-	dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
-	dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
-	dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
-}
-
-static int dsi_get_clocks(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct clk *clk;
-
-	clk = devm_clk_get(&dsidev->dev, "fck");
-	if (IS_ERR(clk)) {
-		DSSERR("can't get fck\n");
-		return PTR_ERR(clk);
-	}
-
-	dsi->dss_clk = clk;
-
-	clk = devm_clk_get(&dsidev->dev, "sys_clk");
-	if (IS_ERR(clk)) {
-		DSSERR("can't get sys_clk\n");
-		return PTR_ERR(clk);
-	}
-
-	dsi->sys_clk = clk;
-
-	return 0;
-}
-
-static int dsi_connect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct omap_overlay_manager *mgr;
-	int r;
-
-	r = dsi_regulator_init(dsidev);
-	if (r)
-		return r;
-
-	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
-	if (!mgr)
-		return -ENODEV;
-
-	r = dss_mgr_connect(mgr, dssdev);
-	if (r)
-		return r;
-
-	r = omapdss_output_set_device(dssdev, dst);
-	if (r) {
-		DSSERR("failed to connect output to new device: %s\n",
-				dssdev->name);
-		dss_mgr_disconnect(mgr, dssdev);
-		return r;
-	}
-
-	return 0;
-}
-
-static void dsi_disconnect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	WARN_ON(dst != dssdev->dst);
-
-	if (dst != dssdev->dst)
-		return;
-
-	omapdss_output_unset_device(dssdev);
-
-	if (dssdev->manager)
-		dss_mgr_disconnect(dssdev->manager, dssdev);
-}
-
-static const struct omapdss_dsi_ops dsi_ops = {
-	.connect = dsi_connect,
-	.disconnect = dsi_disconnect,
-
-	.bus_lock = dsi_bus_lock,
-	.bus_unlock = dsi_bus_unlock,
-
-	.enable = dsi_display_enable,
-	.disable = dsi_display_disable,
-
-	.enable_hs = dsi_vc_enable_hs,
-
-	.configure_pins = dsi_configure_pins,
-	.set_config = dsi_set_config,
-
-	.enable_video_output = dsi_enable_video_output,
-	.disable_video_output = dsi_disable_video_output,
-
-	.update = dsi_update,
-
-	.enable_te = dsi_enable_te,
-
-	.request_vc = dsi_request_vc,
-	.set_vc_id = dsi_set_vc_id,
-	.release_vc = dsi_release_vc,
-
-	.dcs_write = dsi_vc_dcs_write,
-	.dcs_write_nosync = dsi_vc_dcs_write_nosync,
-	.dcs_read = dsi_vc_dcs_read,
-
-	.gen_write = dsi_vc_generic_write,
-	.gen_write_nosync = dsi_vc_generic_write_nosync,
-	.gen_read = dsi_vc_generic_read,
-
-	.bta_sync = dsi_vc_send_bta_sync,
-
-	.set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size,
-};
-
-static void dsi_init_output(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_dss_device *out = &dsi->output;
-
-	out->dev = &dsidev->dev;
-	out->id = dsi->module_id == 0 ?
-			OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
-
-	out->output_type = OMAP_DISPLAY_TYPE_DSI;
-	out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
-	out->dispc_channel = dsi_get_channel(dsi->module_id);
-	out->ops.dsi = &dsi_ops;
-	out->owner = THIS_MODULE;
-
-	omapdss_register_output(out);
-}
-
-static void dsi_uninit_output(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct omap_dss_device *out = &dsi->output;
-
-	omapdss_unregister_output(out);
-}
-
-static int dsi_probe_of(struct platform_device *pdev)
-{
-	struct device_node *node = pdev->dev.of_node;
-	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
-	struct property *prop;
-	u32 lane_arr[10];
-	int len, num_pins;
-	int r, i;
-	struct device_node *ep;
-	struct omap_dsi_pin_config pin_cfg;
-
-	ep = omapdss_of_get_first_endpoint(node);
-	if (!ep)
-		return 0;
-
-	prop = of_find_property(ep, "lanes", &len);
-	if (prop == NULL) {
-		dev_err(&pdev->dev, "failed to find lane data\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	num_pins = len / sizeof(u32);
-
-	if (num_pins < 4 || num_pins % 2 != 0 ||
-		num_pins > dsi->num_lanes_supported * 2) {
-		dev_err(&pdev->dev, "bad number of lanes\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins);
-	if (r) {
-		dev_err(&pdev->dev, "failed to read lane data\n");
-		goto err;
-	}
-
-	pin_cfg.num_pins = num_pins;
-	for (i = 0; i < num_pins; ++i)
-		pin_cfg.pins[i] = (int)lane_arr[i];
-
-	r = dsi_configure_pins(&dsi->output, &pin_cfg);
-	if (r) {
-		dev_err(&pdev->dev, "failed to configure pins");
-		goto err;
-	}
-
-	of_node_put(ep);
-
-	return 0;
-
-err:
-	of_node_put(ep);
-	return r;
-}
-
-/* DSI1 HW IP initialisation */
-static int omap_dsihw_probe(struct platform_device *dsidev)
-{
-	u32 rev;
-	int r, i;
-	struct dsi_data *dsi;
-	struct resource *dsi_mem;
-	struct resource *res;
-	struct resource temp_res;
-
-	dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL);
-	if (!dsi)
-		return -ENOMEM;
-
-	dsi->pdev = dsidev;
-	dev_set_drvdata(&dsidev->dev, dsi);
-
-	spin_lock_init(&dsi->irq_lock);
-	spin_lock_init(&dsi->errors_lock);
-	dsi->errors = 0;
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spin_lock_init(&dsi->irq_stats_lock);
-	dsi->irq_stats.last_reset = jiffies;
-#endif
-
-	mutex_init(&dsi->lock);
-	sema_init(&dsi->bus_lock, 1);
-
-	INIT_DEFERRABLE_WORK(&dsi->framedone_timeout_work,
-			     dsi_framedone_timeout_work_callback);
-
-#ifdef DSI_CATCH_MISSING_TE
-	init_timer(&dsi->te_timer);
-	dsi->te_timer.function = dsi_te_timeout;
-	dsi->te_timer.data = 0;
-#endif
-
-	res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "proto");
-	if (!res) {
-		res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
-		if (!res) {
-			DSSERR("can't get IORESOURCE_MEM DSI\n");
-			return -EINVAL;
-		}
-
-		temp_res.start = res->start;
-		temp_res.end = temp_res.start + DSI_PROTO_SZ - 1;
-		res = &temp_res;
-	}
-
-	dsi_mem = res;
-
-	dsi->proto_base = devm_ioremap(&dsidev->dev, res->start,
-		resource_size(res));
-	if (!dsi->proto_base) {
-		DSSERR("can't ioremap DSI protocol engine\n");
-		return -ENOMEM;
-	}
-
-	res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "phy");
-	if (!res) {
-		res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
-		if (!res) {
-			DSSERR("can't get IORESOURCE_MEM DSI\n");
-			return -EINVAL;
-		}
-
-		temp_res.start = res->start + DSI_PHY_OFFSET;
-		temp_res.end = temp_res.start + DSI_PHY_SZ - 1;
-		res = &temp_res;
-	}
-
-	dsi->phy_base = devm_ioremap(&dsidev->dev, res->start,
-		resource_size(res));
-	if (!dsi->proto_base) {
-		DSSERR("can't ioremap DSI PHY\n");
-		return -ENOMEM;
-	}
-
-	res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "pll");
-	if (!res) {
-		res = platform_get_resource(dsidev, IORESOURCE_MEM, 0);
-		if (!res) {
-			DSSERR("can't get IORESOURCE_MEM DSI\n");
-			return -EINVAL;
-		}
-
-		temp_res.start = res->start + DSI_PLL_OFFSET;
-		temp_res.end = temp_res.start + DSI_PLL_SZ - 1;
-		res = &temp_res;
-	}
-
-	dsi->pll_base = devm_ioremap(&dsidev->dev, res->start,
-		resource_size(res));
-	if (!dsi->proto_base) {
-		DSSERR("can't ioremap DSI PLL\n");
-		return -ENOMEM;
-	}
-
-	dsi->irq = platform_get_irq(dsi->pdev, 0);
-	if (dsi->irq < 0) {
-		DSSERR("platform_get_irq failed\n");
-		return -ENODEV;
-	}
-
-	r = devm_request_irq(&dsidev->dev, dsi->irq, omap_dsi_irq_handler,
-			     IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev);
-	if (r < 0) {
-		DSSERR("request_irq failed\n");
-		return r;
-	}
-
-	if (dsidev->dev.of_node) {
-		const struct of_device_id *match;
-		const struct dsi_module_id_data *d;
-
-		match = of_match_node(dsi_of_match, dsidev->dev.of_node);
-		if (!match) {
-			DSSERR("unsupported DSI module\n");
-			return -ENODEV;
-		}
-
-		d = match->data;
-
-		while (d->address != 0 && d->address != dsi_mem->start)
-			d++;
-
-		if (d->address == 0) {
-			DSSERR("unsupported DSI module\n");
-			return -ENODEV;
-		}
-
-		dsi->module_id = d->id;
-	} else {
-		dsi->module_id = dsidev->id;
-	}
-
-	/* DSI VCs initialization */
-	for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
-		dsi->vc[i].source = DSI_VC_SOURCE_L4;
-		dsi->vc[i].dssdev = NULL;
-		dsi->vc[i].vc_id = 0;
-	}
-
-	dsi_calc_clock_param_ranges(dsidev);
-
-	r = dsi_get_clocks(dsidev);
-	if (r)
-		return r;
-
-	pm_runtime_enable(&dsidev->dev);
-
-	r = dsi_runtime_get(dsidev);
-	if (r)
-		goto err_runtime_get;
-
-	rev = dsi_read_reg(dsidev, DSI_REVISION);
-	dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
-	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-	/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
-	 * of data to 3 by default */
-	if (dss_has_feature(FEAT_DSI_GNQ))
-		/* NB_DATA_LANES */
-		dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
-	else
-		dsi->num_lanes_supported = 3;
-
-	dsi->line_buffer_size = dsi_get_line_buf_size(dsidev);
-
-	dsi_init_output(dsidev);
-
-	if (dsidev->dev.of_node) {
-		r = dsi_probe_of(dsidev);
-		if (r) {
-			DSSERR("Invalid DSI DT data\n");
-			goto err_probe_of;
-		}
-
-		r = of_platform_populate(dsidev->dev.of_node, NULL, NULL,
-			&dsidev->dev);
-		if (r)
-			DSSERR("Failed to populate DSI child devices: %d\n", r);
-	}
-
-	dsi_runtime_put(dsidev);
-
-	if (dsi->module_id == 0)
-		dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs);
-	else if (dsi->module_id == 1)
-		dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs);
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	if (dsi->module_id == 0)
-		dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs);
-	else if (dsi->module_id == 1)
-		dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs);
-#endif
-
-	return 0;
-
-err_probe_of:
-	dsi_uninit_output(dsidev);
-	dsi_runtime_put(dsidev);
-
-err_runtime_get:
-	pm_runtime_disable(&dsidev->dev);
-	return r;
-}
-
-static int dsi_unregister_child(struct device *dev, void *data)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	platform_device_unregister(pdev);
-	return 0;
-}
-
-static int __exit omap_dsihw_remove(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	device_for_each_child(&dsidev->dev, NULL, dsi_unregister_child);
-
-	WARN_ON(dsi->scp_clk_refcount > 0);
-
-	dsi_uninit_output(dsidev);
-
-	pm_runtime_disable(&dsidev->dev);
-
-	if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
-		regulator_disable(dsi->vdds_dsi_reg);
-		dsi->vdds_dsi_enabled = false;
-	}
-
-	return 0;
-}
-
-static int dsi_runtime_suspend(struct device *dev)
-{
-	dispc_runtime_put();
-
-	return 0;
-}
-
-static int dsi_runtime_resume(struct device *dev)
-{
-	int r;
-
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static const struct dev_pm_ops dsi_pm_ops = {
-	.runtime_suspend = dsi_runtime_suspend,
-	.runtime_resume = dsi_runtime_resume,
-};
-
-static const struct dsi_module_id_data dsi_of_data_omap3[] = {
-	{ .address = 0x4804fc00, .id = 0, },
-	{ },
-};
-
-static const struct dsi_module_id_data dsi_of_data_omap4[] = {
-	{ .address = 0x58004000, .id = 0, },
-	{ .address = 0x58005000, .id = 1, },
-	{ },
-};
-
-static const struct of_device_id dsi_of_match[] = {
-	{ .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, },
-	{ .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, },
-	{},
-};
-
-static struct platform_driver omap_dsihw_driver = {
-	.probe		= omap_dsihw_probe,
-	.remove         = __exit_p(omap_dsihw_remove),
-	.driver         = {
-		.name   = "omapdss_dsi",
-		.owner  = THIS_MODULE,
-		.pm	= &dsi_pm_ops,
-		.of_match_table = dsi_of_match,
-	},
-};
-
-int __init dsi_init_platform_driver(void)
-{
-	return platform_driver_register(&omap_dsihw_driver);
-}
-
-void __exit dsi_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omap_dsihw_driver);
-}
diff --git a/drivers/video/omap2/dss/dss-of.c b/drivers/video/omap2/dss/dss-of.c
deleted file mode 100644
index a4b20aaf6142..000000000000
--- a/drivers/video/omap2/dss/dss-of.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2013 Texas Instruments
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/seq_file.h>
-
-#include <video/omapdss.h>
-
-struct device_node *
-omapdss_of_get_next_port(const struct device_node *parent,
-			 struct device_node *prev)
-{
-	struct device_node *port = NULL;
-
-	if (!parent)
-		return NULL;
-
-	if (!prev) {
-		struct device_node *ports;
-		/*
-		 * It's the first call, we have to find a port subnode
-		 * within this node or within an optional 'ports' node.
-		 */
-		ports = of_get_child_by_name(parent, "ports");
-		if (ports)
-			parent = ports;
-
-		port = of_get_child_by_name(parent, "port");
-
-		/* release the 'ports' node */
-		of_node_put(ports);
-	} else {
-		struct device_node *ports;
-
-		ports = of_get_parent(prev);
-		if (!ports)
-			return NULL;
-
-		do {
-			port = of_get_next_child(ports, prev);
-			if (!port) {
-				of_node_put(ports);
-				return NULL;
-			}
-			prev = port;
-		} while (of_node_cmp(port->name, "port") != 0);
-	}
-
-	return port;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_next_port);
-
-struct device_node *
-omapdss_of_get_next_endpoint(const struct device_node *parent,
-			     struct device_node *prev)
-{
-	struct device_node *ep = NULL;
-
-	if (!parent)
-		return NULL;
-
-	do {
-		ep = of_get_next_child(parent, prev);
-		if (!ep)
-			return NULL;
-		prev = ep;
-	} while (of_node_cmp(ep->name, "endpoint") != 0);
-
-	return ep;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
-
-static struct device_node *
-omapdss_of_get_remote_device_node(const struct device_node *node)
-{
-	struct device_node *np;
-	int i;
-
-	np = of_parse_phandle(node, "remote-endpoint", 0);
-
-	if (!np)
-		return NULL;
-
-	np = of_get_next_parent(np);
-
-	for (i = 0; i < 3 && np; ++i) {
-		struct property *prop;
-
-		prop = of_find_property(np, "compatible", NULL);
-
-		if (prop)
-			return np;
-
-		np = of_get_next_parent(np);
-	}
-
-	return NULL;
-}
-
-struct device_node *
-omapdss_of_get_first_endpoint(const struct device_node *parent)
-{
-	struct device_node *port, *ep;
-
-	port = omapdss_of_get_next_port(parent, NULL);
-
-	if (!port)
-		return NULL;
-
-	ep = omapdss_of_get_next_endpoint(port, NULL);
-
-	of_node_put(port);
-
-	return ep;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint);
-
-struct omap_dss_device *
-omapdss_of_find_source_for_first_ep(struct device_node *node)
-{
-	struct device_node *ep;
-	struct device_node *src_node;
-	struct omap_dss_device *src;
-
-	ep = omapdss_of_get_first_endpoint(node);
-	if (!ep)
-		return ERR_PTR(-EINVAL);
-
-	src_node = omapdss_of_get_remote_device_node(ep);
-
-	of_node_put(ep);
-
-	if (!src_node)
-		return ERR_PTR(-EINVAL);
-
-	src = omap_dss_find_output_by_node(src_node);
-
-	of_node_put(src_node);
-
-	if (!src)
-		return ERR_PTR(-EPROBE_DEFER);
-
-	return src;
-}
-EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
deleted file mode 100644
index 825c019ddee7..000000000000
--- a/drivers/video/omap2/dss/dss.c
+++ /dev/null
@@ -1,972 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dss.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "DSS"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/export.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/gfp.h>
-#include <linux/sizes.h>
-#include <linux/of.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-#define DSS_SZ_REGS			SZ_512
-
-struct dss_reg {
-	u16 idx;
-};
-
-#define DSS_REG(idx)			((const struct dss_reg) { idx })
-
-#define DSS_REVISION			DSS_REG(0x0000)
-#define DSS_SYSCONFIG			DSS_REG(0x0010)
-#define DSS_SYSSTATUS			DSS_REG(0x0014)
-#define DSS_CONTROL			DSS_REG(0x0040)
-#define DSS_SDI_CONTROL			DSS_REG(0x0044)
-#define DSS_PLL_CONTROL			DSS_REG(0x0048)
-#define DSS_SDI_STATUS			DSS_REG(0x005C)
-
-#define REG_GET(idx, start, end) \
-	FLD_GET(dss_read_reg(idx), start, end)
-
-#define REG_FLD_MOD(idx, val, start, end) \
-	dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
-
-static int dss_runtime_get(void);
-static void dss_runtime_put(void);
-
-struct dss_features {
-	u8 fck_div_max;
-	u8 dss_fck_multiplier;
-	const char *parent_clk_name;
-	int (*dpi_select_source)(enum omap_channel channel);
-};
-
-static struct {
-	struct platform_device *pdev;
-	void __iomem    *base;
-
-	struct clk	*parent_clk;
-	struct clk	*dss_clk;
-	unsigned long	dss_clk_rate;
-
-	unsigned long	cache_req_pck;
-	unsigned long	cache_prate;
-	struct dispc_clock_info cache_dispc_cinfo;
-
-	enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
-	enum omap_dss_clk_source dispc_clk_source;
-	enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
-
-	bool		ctx_valid;
-	u32		ctx[DSS_SZ_REGS / sizeof(u32)];
-
-	const struct dss_features *feat;
-} dss;
-
-static const char * const dss_generic_clk_source_names[] = {
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC",
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI_PLL_HSDIV_DSI",
-	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
-	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DSI_PLL2_HSDIV_DISPC",
-	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DSI_PLL2_HSDIV_DSI",
-};
-
-static inline void dss_write_reg(const struct dss_reg idx, u32 val)
-{
-	__raw_writel(val, dss.base + idx.idx);
-}
-
-static inline u32 dss_read_reg(const struct dss_reg idx)
-{
-	return __raw_readl(dss.base + idx.idx);
-}
-
-#define SR(reg) \
-	dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
-#define RR(reg) \
-	dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
-
-static void dss_save_context(void)
-{
-	DSSDBG("dss_save_context\n");
-
-	SR(CONTROL);
-
-	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
-			OMAP_DISPLAY_TYPE_SDI) {
-		SR(SDI_CONTROL);
-		SR(PLL_CONTROL);
-	}
-
-	dss.ctx_valid = true;
-
-	DSSDBG("context saved\n");
-}
-
-static void dss_restore_context(void)
-{
-	DSSDBG("dss_restore_context\n");
-
-	if (!dss.ctx_valid)
-		return;
-
-	RR(CONTROL);
-
-	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
-			OMAP_DISPLAY_TYPE_SDI) {
-		RR(SDI_CONTROL);
-		RR(PLL_CONTROL);
-	}
-
-	DSSDBG("context restored\n");
-}
-
-#undef SR
-#undef RR
-
-void dss_sdi_init(int datapairs)
-{
-	u32 l;
-
-	BUG_ON(datapairs > 3 || datapairs < 1);
-
-	l = dss_read_reg(DSS_SDI_CONTROL);
-	l = FLD_MOD(l, 0xf, 19, 15);		/* SDI_PDIV */
-	l = FLD_MOD(l, datapairs-1, 3, 2);	/* SDI_PRSEL */
-	l = FLD_MOD(l, 2, 1, 0);		/* SDI_BWSEL */
-	dss_write_reg(DSS_SDI_CONTROL, l);
-
-	l = dss_read_reg(DSS_PLL_CONTROL);
-	l = FLD_MOD(l, 0x7, 25, 22);	/* SDI_PLL_FREQSEL */
-	l = FLD_MOD(l, 0xb, 16, 11);	/* SDI_PLL_REGN */
-	l = FLD_MOD(l, 0xb4, 10, 1);	/* SDI_PLL_REGM */
-	dss_write_reg(DSS_PLL_CONTROL, l);
-}
-
-int dss_sdi_enable(void)
-{
-	unsigned long timeout;
-
-	dispc_pck_free_enable(1);
-
-	/* Reset SDI PLL */
-	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
-	udelay(1);	/* wait 2x PCLK */
-
-	/* Lock SDI PLL */
-	REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
-
-	/* Waiting for PLL lock request to complete */
-	timeout = jiffies + msecs_to_jiffies(500);
-	while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
-		if (time_after_eq(jiffies, timeout)) {
-			DSSERR("PLL lock request timed out\n");
-			goto err1;
-		}
-	}
-
-	/* Clearing PLL_GO bit */
-	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
-
-	/* Waiting for PLL to lock */
-	timeout = jiffies + msecs_to_jiffies(500);
-	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
-		if (time_after_eq(jiffies, timeout)) {
-			DSSERR("PLL lock timed out\n");
-			goto err1;
-		}
-	}
-
-	dispc_lcd_enable_signal(1);
-
-	/* Waiting for SDI reset to complete */
-	timeout = jiffies + msecs_to_jiffies(500);
-	while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
-		if (time_after_eq(jiffies, timeout)) {
-			DSSERR("SDI reset timed out\n");
-			goto err2;
-		}
-	}
-
-	return 0;
-
- err2:
-	dispc_lcd_enable_signal(0);
- err1:
-	/* Reset SDI PLL */
-	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
-
-	dispc_pck_free_enable(0);
-
-	return -ETIMEDOUT;
-}
-
-void dss_sdi_disable(void)
-{
-	dispc_lcd_enable_signal(0);
-
-	dispc_pck_free_enable(0);
-
-	/* Reset SDI PLL */
-	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
-}
-
-const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
-{
-	return dss_generic_clk_source_names[clk_src];
-}
-
-void dss_dump_clocks(struct seq_file *s)
-{
-	const char *fclk_name, *fclk_real_name;
-	unsigned long fclk_rate;
-
-	if (dss_runtime_get())
-		return;
-
-	seq_printf(s, "- DSS -\n");
-
-	fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
-	fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
-	fclk_rate = clk_get_rate(dss.dss_clk);
-
-	seq_printf(s, "%s (%s) = %lu\n",
-			fclk_name, fclk_real_name,
-			fclk_rate);
-
-	dss_runtime_put();
-}
-
-static void dss_dump_regs(struct seq_file *s)
-{
-#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
-
-	if (dss_runtime_get())
-		return;
-
-	DUMPREG(DSS_REVISION);
-	DUMPREG(DSS_SYSCONFIG);
-	DUMPREG(DSS_SYSSTATUS);
-	DUMPREG(DSS_CONTROL);
-
-	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
-			OMAP_DISPLAY_TYPE_SDI) {
-		DUMPREG(DSS_SDI_CONTROL);
-		DUMPREG(DSS_PLL_CONTROL);
-		DUMPREG(DSS_SDI_STATUS);
-	}
-
-	dss_runtime_put();
-#undef DUMPREG
-}
-
-static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
-{
-	struct platform_device *dsidev;
-	int b;
-	u8 start, end;
-
-	switch (clk_src) {
-	case OMAP_DSS_CLK_SRC_FCK:
-		b = 0;
-		break;
-	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-		b = 1;
-		dsidev = dsi_get_dsidev_from_id(0);
-		dsi_wait_pll_hsdiv_dispc_active(dsidev);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-		b = 2;
-		dsidev = dsi_get_dsidev_from_id(1);
-		dsi_wait_pll_hsdiv_dispc_active(dsidev);
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
-
-	REG_FLD_MOD(DSS_CONTROL, b, start, end);	/* DISPC_CLK_SWITCH */
-
-	dss.dispc_clk_source = clk_src;
-}
-
-void dss_select_dsi_clk_source(int dsi_module,
-		enum omap_dss_clk_source clk_src)
-{
-	struct platform_device *dsidev;
-	int b, pos;
-
-	switch (clk_src) {
-	case OMAP_DSS_CLK_SRC_FCK:
-		b = 0;
-		break;
-	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
-		BUG_ON(dsi_module != 0);
-		b = 1;
-		dsidev = dsi_get_dsidev_from_id(0);
-		dsi_wait_pll_hsdiv_dsi_active(dsidev);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
-		BUG_ON(dsi_module != 1);
-		b = 1;
-		dsidev = dsi_get_dsidev_from_id(1);
-		dsi_wait_pll_hsdiv_dsi_active(dsidev);
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	pos = dsi_module == 0 ? 1 : 10;
-	REG_FLD_MOD(DSS_CONTROL, b, pos, pos);	/* DSIx_CLK_SWITCH */
-
-	dss.dsi_clk_source[dsi_module] = clk_src;
-}
-
-void dss_select_lcd_clk_source(enum omap_channel channel,
-		enum omap_dss_clk_source clk_src)
-{
-	struct platform_device *dsidev;
-	int b, ix, pos;
-
-	if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
-		dss_select_dispc_clk_source(clk_src);
-		return;
-	}
-
-	switch (clk_src) {
-	case OMAP_DSS_CLK_SRC_FCK:
-		b = 0;
-		break;
-	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-		BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
-		b = 1;
-		dsidev = dsi_get_dsidev_from_id(0);
-		dsi_wait_pll_hsdiv_dispc_active(dsidev);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-		BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
-		       channel != OMAP_DSS_CHANNEL_LCD3);
-		b = 1;
-		dsidev = dsi_get_dsidev_from_id(1);
-		dsi_wait_pll_hsdiv_dispc_active(dsidev);
-		break;
-	default:
-		BUG();
-		return;
-	}
-
-	pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
-	     (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
-	REG_FLD_MOD(DSS_CONTROL, b, pos, pos);	/* LCDx_CLK_SWITCH */
-
-	ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
-	    (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
-	dss.lcd_clk_source[ix] = clk_src;
-}
-
-enum omap_dss_clk_source dss_get_dispc_clk_source(void)
-{
-	return dss.dispc_clk_source;
-}
-
-enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
-{
-	return dss.dsi_clk_source[dsi_module];
-}
-
-enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
-{
-	if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
-		int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
-			(channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
-		return dss.lcd_clk_source[ix];
-	} else {
-		/* LCD_CLK source is the same as DISPC_FCLK source for
-		 * OMAP2 and OMAP3 */
-		return dss.dispc_clk_source;
-	}
-}
-
-bool dss_div_calc(unsigned long pck, unsigned long fck_min,
-		dss_div_calc_func func, void *data)
-{
-	int fckd, fckd_start, fckd_stop;
-	unsigned long fck;
-	unsigned long fck_hw_max;
-	unsigned long fckd_hw_max;
-	unsigned long prate;
-	unsigned m;
-
-	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	if (dss.parent_clk == NULL) {
-		unsigned pckd;
-
-		pckd = fck_hw_max / pck;
-
-		fck = pck * pckd;
-
-		fck = clk_round_rate(dss.dss_clk, fck);
-
-		return func(fck, data);
-	}
-
-	fckd_hw_max = dss.feat->fck_div_max;
-
-	m = dss.feat->dss_fck_multiplier;
-	prate = clk_get_rate(dss.parent_clk);
-
-	fck_min = fck_min ? fck_min : 1;
-
-	fckd_start = min(prate * m / fck_min, fckd_hw_max);
-	fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
-
-	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
-		fck = prate / fckd * m;
-
-		if (func(fck, data))
-			return true;
-	}
-
-	return false;
-}
-
-int dss_set_fck_rate(unsigned long rate)
-{
-	int r;
-
-	DSSDBG("set fck to %lu\n", rate);
-
-	r = clk_set_rate(dss.dss_clk, rate);
-	if (r)
-		return r;
-
-	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
-
-	WARN_ONCE(dss.dss_clk_rate != rate,
-			"clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
-			rate);
-
-	return 0;
-}
-
-unsigned long dss_get_dispc_clk_rate(void)
-{
-	return dss.dss_clk_rate;
-}
-
-static int dss_setup_default_clock(void)
-{
-	unsigned long max_dss_fck, prate;
-	unsigned long fck;
-	unsigned fck_div;
-	int r;
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	if (dss.parent_clk == NULL) {
-		fck = clk_round_rate(dss.dss_clk, max_dss_fck);
-	} else {
-		prate = clk_get_rate(dss.parent_clk);
-
-		fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
-				max_dss_fck);
-		fck = prate / fck_div * dss.feat->dss_fck_multiplier;
-	}
-
-	r = dss_set_fck_rate(fck);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-void dss_set_venc_output(enum omap_dss_venc_type type)
-{
-	int l = 0;
-
-	if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
-		l = 0;
-	else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
-		l = 1;
-	else
-		BUG();
-
-	/* venc out selection. 0 = comp, 1 = svideo */
-	REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
-}
-
-void dss_set_dac_pwrdn_bgz(bool enable)
-{
-	REG_FLD_MOD(DSS_CONTROL, enable, 5, 5);	/* DAC Power-Down Control */
-}
-
-void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
-{
-	enum omap_display_type dp;
-	dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
-
-	/* Complain about invalid selections */
-	WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
-	WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
-
-	/* Select only if we have options */
-	if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
-		REG_FLD_MOD(DSS_CONTROL, src, 15, 15);	/* VENC_HDMI_SWITCH */
-}
-
-enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
-{
-	enum omap_display_type displays;
-
-	displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
-	if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
-		return DSS_VENC_TV_CLK;
-
-	if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
-		return DSS_HDMI_M_PCLK;
-
-	return REG_GET(DSS_CONTROL, 15, 15);
-}
-
-static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
-{
-	if (channel != OMAP_DSS_CHANNEL_LCD)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int dss_dpi_select_source_omap4(enum omap_channel channel)
-{
-	int val;
-
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD2:
-		val = 0;
-		break;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		val = 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
-
-	return 0;
-}
-
-static int dss_dpi_select_source_omap5(enum omap_channel channel)
-{
-	int val;
-
-	switch (channel) {
-	case OMAP_DSS_CHANNEL_LCD:
-		val = 1;
-		break;
-	case OMAP_DSS_CHANNEL_LCD2:
-		val = 2;
-		break;
-	case OMAP_DSS_CHANNEL_LCD3:
-		val = 3;
-		break;
-	case OMAP_DSS_CHANNEL_DIGIT:
-		val = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
-
-	return 0;
-}
-
-int dss_dpi_select_source(enum omap_channel channel)
-{
-	return dss.feat->dpi_select_source(channel);
-}
-
-static int dss_get_clocks(void)
-{
-	struct clk *clk;
-
-	clk = devm_clk_get(&dss.pdev->dev, "fck");
-	if (IS_ERR(clk)) {
-		DSSERR("can't get clock fck\n");
-		return PTR_ERR(clk);
-	}
-
-	dss.dss_clk = clk;
-
-	if (dss.feat->parent_clk_name) {
-		clk = clk_get(NULL, dss.feat->parent_clk_name);
-		if (IS_ERR(clk)) {
-			DSSERR("Failed to get %s\n", dss.feat->parent_clk_name);
-			return PTR_ERR(clk);
-		}
-	} else {
-		clk = NULL;
-	}
-
-	dss.parent_clk = clk;
-
-	return 0;
-}
-
-static void dss_put_clocks(void)
-{
-	if (dss.parent_clk)
-		clk_put(dss.parent_clk);
-}
-
-static int dss_runtime_get(void)
-{
-	int r;
-
-	DSSDBG("dss_runtime_get\n");
-
-	r = pm_runtime_get_sync(&dss.pdev->dev);
-	WARN_ON(r < 0);
-	return r < 0 ? r : 0;
-}
-
-static void dss_runtime_put(void)
-{
-	int r;
-
-	DSSDBG("dss_runtime_put\n");
-
-	r = pm_runtime_put_sync(&dss.pdev->dev);
-	WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
-}
-
-/* DEBUGFS */
-#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
-void dss_debug_dump_clocks(struct seq_file *s)
-{
-	dss_dump_clocks(s);
-	dispc_dump_clocks(s);
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_dump_clocks(s);
-#endif
-}
-#endif
-
-static const struct dss_features omap24xx_dss_feats __initconst = {
-	/*
-	 * fck div max is really 16, but the divider range has gaps. The range
-	 * from 1 to 6 has no gaps, so let's use that as a max.
-	 */
-	.fck_div_max		=	6,
-	.dss_fck_multiplier	=	2,
-	.parent_clk_name	=	"core_ck",
-	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
-};
-
-static const struct dss_features omap34xx_dss_feats __initconst = {
-	.fck_div_max		=	16,
-	.dss_fck_multiplier	=	2,
-	.parent_clk_name	=	"dpll4_ck",
-	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
-};
-
-static const struct dss_features omap3630_dss_feats __initconst = {
-	.fck_div_max		=	32,
-	.dss_fck_multiplier	=	1,
-	.parent_clk_name	=	"dpll4_ck",
-	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
-};
-
-static const struct dss_features omap44xx_dss_feats __initconst = {
-	.fck_div_max		=	32,
-	.dss_fck_multiplier	=	1,
-	.parent_clk_name	=	"dpll_per_x2_ck",
-	.dpi_select_source	=	&dss_dpi_select_source_omap4,
-};
-
-static const struct dss_features omap54xx_dss_feats __initconst = {
-	.fck_div_max		=	64,
-	.dss_fck_multiplier	=	1,
-	.parent_clk_name	=	"dpll_per_x2_ck",
-	.dpi_select_source	=	&dss_dpi_select_source_omap5,
-};
-
-static int __init dss_init_features(struct platform_device *pdev)
-{
-	const struct dss_features *src;
-	struct dss_features *dst;
-
-	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
-	if (!dst) {
-		dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
-		return -ENOMEM;
-	}
-
-	switch (omapdss_get_version()) {
-	case OMAPDSS_VER_OMAP24xx:
-		src = &omap24xx_dss_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP34xx_ES1:
-	case OMAPDSS_VER_OMAP34xx_ES3:
-	case OMAPDSS_VER_AM35xx:
-		src = &omap34xx_dss_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP3630:
-		src = &omap3630_dss_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP4430_ES1:
-	case OMAPDSS_VER_OMAP4430_ES2:
-	case OMAPDSS_VER_OMAP4:
-		src = &omap44xx_dss_feats;
-		break;
-
-	case OMAPDSS_VER_OMAP5:
-		src = &omap54xx_dss_feats;
-		break;
-
-	default:
-		return -ENODEV;
-	}
-
-	memcpy(dst, src, sizeof(*dst));
-	dss.feat = dst;
-
-	return 0;
-}
-
-static int __init dss_init_ports(struct platform_device *pdev)
-{
-	struct device_node *parent = pdev->dev.of_node;
-	struct device_node *port;
-	int r;
-
-	if (parent == NULL)
-		return 0;
-
-	port = omapdss_of_get_next_port(parent, NULL);
-	if (!port) {
-#ifdef CONFIG_OMAP2_DSS_DPI
-		dpi_init_port(pdev, parent);
-#endif
-		return 0;
-	}
-
-	do {
-		u32 reg;
-
-		r = of_property_read_u32(port, "reg", &reg);
-		if (r)
-			reg = 0;
-
-#ifdef CONFIG_OMAP2_DSS_DPI
-		if (reg == 0)
-			dpi_init_port(pdev, port);
-#endif
-
-#ifdef CONFIG_OMAP2_DSS_SDI
-		if (reg == 1)
-			sdi_init_port(pdev, port);
-#endif
-
-	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
-
-	return 0;
-}
-
-static void dss_uninit_ports(void)
-{
-#ifdef CONFIG_OMAP2_DSS_DPI
-	dpi_uninit_port();
-#endif
-
-#ifdef CONFIG_OMAP2_DSS_SDI
-	sdi_uninit_port();
-#endif
-}
-
-/* DSS HW IP initialisation */
-static int __init omap_dsshw_probe(struct platform_device *pdev)
-{
-	struct resource *dss_mem;
-	u32 rev;
-	int r;
-
-	dss.pdev = pdev;
-
-	r = dss_init_features(dss.pdev);
-	if (r)
-		return r;
-
-	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
-	if (!dss_mem) {
-		DSSERR("can't get IORESOURCE_MEM DSS\n");
-		return -EINVAL;
-	}
-
-	dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
-				resource_size(dss_mem));
-	if (!dss.base) {
-		DSSERR("can't ioremap DSS\n");
-		return -ENOMEM;
-	}
-
-	r = dss_get_clocks();
-	if (r)
-		return r;
-
-	r = dss_setup_default_clock();
-	if (r)
-		goto err_setup_clocks;
-
-	pm_runtime_enable(&pdev->dev);
-
-	r = dss_runtime_get();
-	if (r)
-		goto err_runtime_get;
-
-	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
-
-	/* Select DPLL */
-	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
-
-	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
-
-#ifdef CONFIG_OMAP2_DSS_VENC
-	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
-	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
-	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
-#endif
-	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
-	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-
-	dss_init_ports(pdev);
-
-	rev = dss_read_reg(DSS_REVISION);
-	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
-			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-	dss_runtime_put();
-
-	dss_debugfs_create_file("dss", dss_dump_regs);
-
-	return 0;
-
-err_runtime_get:
-	pm_runtime_disable(&pdev->dev);
-err_setup_clocks:
-	dss_put_clocks();
-	return r;
-}
-
-static int __exit omap_dsshw_remove(struct platform_device *pdev)
-{
-	dss_uninit_ports();
-
-	pm_runtime_disable(&pdev->dev);
-
-	dss_put_clocks();
-
-	return 0;
-}
-
-static int dss_runtime_suspend(struct device *dev)
-{
-	dss_save_context();
-	dss_set_min_bus_tput(dev, 0);
-	return 0;
-}
-
-static int dss_runtime_resume(struct device *dev)
-{
-	int r;
-	/*
-	 * Set an arbitrarily high tput request to ensure OPP100.
-	 * What we should really do is to make a request to stay in OPP100,
-	 * without any tput requirements, but that is not currently possible
-	 * via the PM layer.
-	 */
-
-	r = dss_set_min_bus_tput(dev, 1000000000);
-	if (r)
-		return r;
-
-	dss_restore_context();
-	return 0;
-}
-
-static const struct dev_pm_ops dss_pm_ops = {
-	.runtime_suspend = dss_runtime_suspend,
-	.runtime_resume = dss_runtime_resume,
-};
-
-static const struct of_device_id dss_of_match[] = {
-	{ .compatible = "ti,omap2-dss", },
-	{ .compatible = "ti,omap3-dss", },
-	{ .compatible = "ti,omap4-dss", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, dss_of_match);
-
-static struct platform_driver omap_dsshw_driver = {
-	.remove         = __exit_p(omap_dsshw_remove),
-	.driver         = {
-		.name   = "omapdss_dss",
-		.owner  = THIS_MODULE,
-		.pm	= &dss_pm_ops,
-		.of_match_table = dss_of_match,
-	},
-};
-
-int __init dss_init_platform_driver(void)
-{
-	return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe);
-}
-
-void dss_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omap_dsshw_driver);
-}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
deleted file mode 100644
index 918fec182424..000000000000
--- a/drivers/video/omap2/dss/dss.h
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dss.h
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP2_DSS_H
-#define __OMAP2_DSS_H
-
-#include <linux/interrupt.h>
-
-#ifdef pr_fmt
-#undef pr_fmt
-#endif
-
-#ifdef DSS_SUBSYS_NAME
-#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
-#else
-#define pr_fmt(fmt) fmt
-#endif
-
-#define DSSDBG(format, ...) \
-	pr_debug(format, ## __VA_ARGS__)
-
-#ifdef DSS_SUBSYS_NAME
-#define DSSERR(format, ...) \
-	printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
-	## __VA_ARGS__)
-#else
-#define DSSERR(format, ...) \
-	printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
-#endif
-
-#ifdef DSS_SUBSYS_NAME
-#define DSSINFO(format, ...) \
-	printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
-	## __VA_ARGS__)
-#else
-#define DSSINFO(format, ...) \
-	printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
-#endif
-
-#ifdef DSS_SUBSYS_NAME
-#define DSSWARN(format, ...) \
-	printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
-	## __VA_ARGS__)
-#else
-#define DSSWARN(format, ...) \
-	printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
-#endif
-
-/* OMAP TRM gives bitfields as start:end, where start is the higher bit
-   number. For example 7:0 */
-#define FLD_MASK(start, end)	(((1 << ((start) - (end) + 1)) - 1) << (end))
-#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
-#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
-#define FLD_MOD(orig, val, start, end) \
-	(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
-
-enum dss_io_pad_mode {
-	DSS_IO_PAD_MODE_RESET,
-	DSS_IO_PAD_MODE_RFBI,
-	DSS_IO_PAD_MODE_BYPASS,
-};
-
-enum dss_hdmi_venc_clk_source_select {
-	DSS_VENC_TV_CLK = 0,
-	DSS_HDMI_M_PCLK = 1,
-};
-
-enum dss_dsi_content_type {
-	DSS_DSI_CONTENT_DCS,
-	DSS_DSI_CONTENT_GENERIC,
-};
-
-enum dss_writeback_channel {
-	DSS_WB_LCD1_MGR =	0,
-	DSS_WB_LCD2_MGR =	1,
-	DSS_WB_TV_MGR =		2,
-	DSS_WB_OVL0 =		3,
-	DSS_WB_OVL1 =		4,
-	DSS_WB_OVL2 =		5,
-	DSS_WB_OVL3 =		6,
-	DSS_WB_LCD3_MGR =	7,
-};
-
-struct dispc_clock_info {
-	/* rates that we get with dividers below */
-	unsigned long lck;
-	unsigned long pck;
-
-	/* dividers */
-	u16 lck_div;
-	u16 pck_div;
-};
-
-struct dsi_clock_info {
-	/* rates that we get with dividers below */
-	unsigned long fint;
-	unsigned long clkin4ddr;
-	unsigned long clkin;
-	unsigned long dsi_pll_hsdiv_dispc_clk;	/* OMAP3: DSI1_PLL_CLK
-						 * OMAP4: PLLx_CLK1 */
-	unsigned long dsi_pll_hsdiv_dsi_clk;	/* OMAP3: DSI2_PLL_CLK
-						 * OMAP4: PLLx_CLK2 */
-	unsigned long lp_clk;
-
-	/* dividers */
-	u16 regn;
-	u16 regm;
-	u16 regm_dispc;	/* OMAP3: REGM3
-			 * OMAP4: REGM4 */
-	u16 regm_dsi;	/* OMAP3: REGM4
-			 * OMAP4: REGM5 */
-	u16 lp_clk_div;
-};
-
-struct reg_field {
-	u16 reg;
-	u8 high;
-	u8 low;
-};
-
-struct dss_lcd_mgr_config {
-	enum dss_io_pad_mode io_pad_mode;
-
-	bool stallmode;
-	bool fifohandcheck;
-
-	struct dispc_clock_info clock_info;
-
-	int video_port_width;
-
-	int lcden_sig_polarity;
-};
-
-struct seq_file;
-struct platform_device;
-
-/* core */
-struct platform_device *dss_get_core_pdev(void);
-int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
-void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
-int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
-int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
-
-/* display */
-int dss_suspend_all_devices(void);
-int dss_resume_all_devices(void);
-void dss_disable_all_devices(void);
-
-int display_init_sysfs(struct platform_device *pdev);
-void display_uninit_sysfs(struct platform_device *pdev);
-
-/* manager */
-int dss_init_overlay_managers(void);
-void dss_uninit_overlay_managers(void);
-int dss_init_overlay_managers_sysfs(struct platform_device *pdev);
-void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev);
-int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
-		const struct omap_overlay_manager_info *info);
-int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
-		const struct omap_video_timings *timings);
-int dss_mgr_check(struct omap_overlay_manager *mgr,
-		struct omap_overlay_manager_info *info,
-		const struct omap_video_timings *mgr_timings,
-		const struct dss_lcd_mgr_config *config,
-		struct omap_overlay_info **overlay_infos);
-
-static inline bool dss_mgr_is_lcd(enum omap_channel id)
-{
-	if (id == OMAP_DSS_CHANNEL_LCD || id == OMAP_DSS_CHANNEL_LCD2 ||
-			id == OMAP_DSS_CHANNEL_LCD3)
-		return true;
-	else
-		return false;
-}
-
-int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
-		struct platform_device *pdev);
-void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
-
-/* overlay */
-void dss_init_overlays(struct platform_device *pdev);
-void dss_uninit_overlays(struct platform_device *pdev);
-void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
-int dss_ovl_simple_check(struct omap_overlay *ovl,
-		const struct omap_overlay_info *info);
-int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
-		const struct omap_video_timings *mgr_timings);
-bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
-		enum omap_color_mode mode);
-int dss_overlay_kobj_init(struct omap_overlay *ovl,
-		struct platform_device *pdev);
-void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
-
-/* DSS */
-int dss_init_platform_driver(void) __init;
-void dss_uninit_platform_driver(void);
-
-unsigned long dss_get_dispc_clk_rate(void);
-int dss_dpi_select_source(enum omap_channel channel);
-void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
-enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
-const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
-void dss_dump_clocks(struct seq_file *s);
-
-#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
-void dss_debug_dump_clocks(struct seq_file *s);
-#endif
-
-void dss_sdi_init(int datapairs);
-int dss_sdi_enable(void);
-void dss_sdi_disable(void);
-
-void dss_select_dsi_clk_source(int dsi_module,
-		enum omap_dss_clk_source clk_src);
-void dss_select_lcd_clk_source(enum omap_channel channel,
-		enum omap_dss_clk_source clk_src);
-enum omap_dss_clk_source dss_get_dispc_clk_source(void);
-enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module);
-enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
-
-void dss_set_venc_output(enum omap_dss_venc_type type);
-void dss_set_dac_pwrdn_bgz(bool enable);
-
-int dss_set_fck_rate(unsigned long rate);
-
-typedef bool (*dss_div_calc_func)(unsigned long fck, void *data);
-bool dss_div_calc(unsigned long pck, unsigned long fck_min,
-		dss_div_calc_func func, void *data);
-
-/* SDI */
-int sdi_init_platform_driver(void) __init;
-void sdi_uninit_platform_driver(void) __exit;
-
-int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init;
-void sdi_uninit_port(void) __exit;
-
-/* DSI */
-
-typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
-		unsigned long pll, void *data);
-typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
-		void *data);
-
-#ifdef CONFIG_OMAP2_DSS_DSI
-
-struct dentry;
-struct file_operations;
-
-int dsi_init_platform_driver(void) __init;
-void dsi_uninit_platform_driver(void) __exit;
-
-int dsi_runtime_get(struct platform_device *dsidev);
-void dsi_runtime_put(struct platform_device *dsidev);
-
-void dsi_dump_clocks(struct seq_file *s);
-
-void dsi_irq_handler(void);
-u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
-
-unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
-
-bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
-		unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
-bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
-		unsigned long pll_min, unsigned long pll_max,
-		dsi_pll_calc_func func, void *data);
-
-unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
-int dsi_pll_set_clock_div(struct platform_device *dsidev,
-		struct dsi_clock_info *cinfo);
-int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
-		bool enable_hsdiv);
-void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
-void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
-void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
-struct platform_device *dsi_get_dsidev_from_id(int module);
-#else
-static inline int dsi_runtime_get(struct platform_device *dsidev)
-{
-	return 0;
-}
-static inline void dsi_runtime_put(struct platform_device *dsidev)
-{
-}
-static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
-{
-	WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
-	return 0;
-}
-static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
-{
-	WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
-	return 0;
-}
-static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
-		struct dsi_clock_info *cinfo)
-{
-	WARN("%s: DSI not compiled in\n", __func__);
-	return -ENODEV;
-}
-static inline int dsi_pll_init(struct platform_device *dsidev,
-		bool enable_hsclk, bool enable_hsdiv)
-{
-	WARN("%s: DSI not compiled in\n", __func__);
-	return -ENODEV;
-}
-static inline void dsi_pll_uninit(struct platform_device *dsidev,
-		bool disconnect_lanes)
-{
-}
-static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
-{
-}
-static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
-{
-}
-static inline struct platform_device *dsi_get_dsidev_from_id(int module)
-{
-	return NULL;
-}
-
-static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
-{
-	return 0;
-}
-
-static inline bool dsi_hsdiv_calc(struct platform_device *dsidev,
-		unsigned long pll, unsigned long out_min,
-		dsi_hsdiv_calc_func func, void *data)
-{
-	return false;
-}
-
-static inline bool dsi_pll_calc(struct platform_device *dsidev,
-		unsigned long clkin,
-		unsigned long pll_min, unsigned long pll_max,
-		dsi_pll_calc_func func, void *data)
-{
-	return false;
-}
-
-#endif
-
-/* DPI */
-int dpi_init_platform_driver(void) __init;
-void dpi_uninit_platform_driver(void) __exit;
-
-int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init;
-void dpi_uninit_port(void) __exit;
-
-/* DISPC */
-int dispc_init_platform_driver(void) __init;
-void dispc_uninit_platform_driver(void) __exit;
-void dispc_dump_clocks(struct seq_file *s);
-
-void dispc_enable_sidle(void);
-void dispc_disable_sidle(void);
-
-void dispc_lcd_enable_signal(bool enable);
-void dispc_pck_free_enable(bool enable);
-void dispc_enable_fifomerge(bool enable);
-void dispc_enable_gamma_table(bool enable);
-void dispc_set_loadmode(enum omap_dss_load_mode mode);
-
-typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
-		unsigned long pck, void *data);
-bool dispc_div_calc(unsigned long dispc,
-		unsigned long pck_min, unsigned long pck_max,
-		dispc_div_calc_func func, void *data);
-
-bool dispc_mgr_timings_ok(enum omap_channel channel,
-		const struct omap_video_timings *timings);
-unsigned long dispc_fclk_rate(void);
-int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
-		struct dispc_clock_info *cinfo);
-
-
-void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
-void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
-		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
-		bool manual_update);
-
-unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
-unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
-unsigned long dispc_core_clk_rate(void);
-void dispc_mgr_set_clock_div(enum omap_channel channel,
-		const struct dispc_clock_info *cinfo);
-int dispc_mgr_get_clock_div(enum omap_channel channel,
-		struct dispc_clock_info *cinfo);
-void dispc_set_tv_pclk(unsigned long pclk);
-
-u32 dispc_wb_get_framedone_irq(void);
-bool dispc_wb_go_busy(void);
-void dispc_wb_go(void);
-void dispc_wb_enable(bool enable);
-bool dispc_wb_is_enabled(void);
-void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
-int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
-		bool mem_to_mem, const struct omap_video_timings *timings);
-
-/* VENC */
-int venc_init_platform_driver(void) __init;
-void venc_uninit_platform_driver(void) __exit;
-
-/* HDMI */
-int hdmi4_init_platform_driver(void) __init;
-void hdmi4_uninit_platform_driver(void) __exit;
-
-/* RFBI */
-int rfbi_init_platform_driver(void) __init;
-void rfbi_uninit_platform_driver(void) __exit;
-
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
-{
-	int b;
-	for (b = 0; b < 32; ++b) {
-		if (irqstatus & (1 << b))
-			irq_arr[b]++;
-	}
-}
-#endif
-
-#endif
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
deleted file mode 100644
index 7f8969191dc6..000000000000
--- a/drivers/video/omap2/dss/dss_features.c
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dss_features.c
- *
- * Copyright (C) 2010 Texas Instruments
- * Author: Archit Taneja <archit@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-/* Defines a generic omap register field */
-struct dss_reg_field {
-	u8 start, end;
-};
-
-struct dss_param_range {
-	int min, max;
-};
-
-struct omap_dss_features {
-	const struct dss_reg_field *reg_fields;
-	const int num_reg_fields;
-
-	const enum dss_feat_id *features;
-	const int num_features;
-
-	const int num_mgrs;
-	const int num_ovls;
-	const int num_wbs;
-	const enum omap_display_type *supported_displays;
-	const enum omap_dss_output_id *supported_outputs;
-	const enum omap_color_mode *supported_color_modes;
-	const enum omap_overlay_caps *overlay_caps;
-	const char * const *clksrc_names;
-	const struct dss_param_range *dss_params;
-
-	const enum omap_dss_rotation_type supported_rotation_types;
-
-	const u32 buffer_size_unit;
-	const u32 burst_size_unit;
-};
-
-/* This struct is assigned to one of the below during initialization */
-static const struct omap_dss_features *omap_current_dss_features;
-
-static const struct dss_reg_field omap2_dss_reg_fields[] = {
-	[FEAT_REG_FIRHINC]			= { 11, 0 },
-	[FEAT_REG_FIRVINC]			= { 27, 16 },
-	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 8, 0 },
-	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 24, 16 },
-	[FEAT_REG_FIFOSIZE]			= { 8, 0 },
-	[FEAT_REG_HORIZONTALACCU]		= { 9, 0 },
-	[FEAT_REG_VERTICALACCU]			= { 25, 16 },
-	[FEAT_REG_DISPC_CLK_SWITCH]		= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGN]			= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGM]			= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGM_DSI]		= { 0, 0 },
-};
-
-static const struct dss_reg_field omap3_dss_reg_fields[] = {
-	[FEAT_REG_FIRHINC]			= { 12, 0 },
-	[FEAT_REG_FIRVINC]			= { 28, 16 },
-	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 11, 0 },
-	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 27, 16 },
-	[FEAT_REG_FIFOSIZE]			= { 10, 0 },
-	[FEAT_REG_HORIZONTALACCU]		= { 9, 0 },
-	[FEAT_REG_VERTICALACCU]			= { 25, 16 },
-	[FEAT_REG_DISPC_CLK_SWITCH]		= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGN]			= { 7, 1 },
-	[FEAT_REG_DSIPLL_REGM]			= { 18, 8 },
-	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 22, 19 },
-	[FEAT_REG_DSIPLL_REGM_DSI]		= { 26, 23 },
-};
-
-static const struct dss_reg_field omap4_dss_reg_fields[] = {
-	[FEAT_REG_FIRHINC]			= { 12, 0 },
-	[FEAT_REG_FIRVINC]			= { 28, 16 },
-	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 15, 0 },
-	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 31, 16 },
-	[FEAT_REG_FIFOSIZE]			= { 15, 0 },
-	[FEAT_REG_HORIZONTALACCU]		= { 10, 0 },
-	[FEAT_REG_VERTICALACCU]			= { 26, 16 },
-	[FEAT_REG_DISPC_CLK_SWITCH]		= { 9, 8 },
-	[FEAT_REG_DSIPLL_REGN]			= { 8, 1 },
-	[FEAT_REG_DSIPLL_REGM]			= { 20, 9 },
-	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 25, 21 },
-	[FEAT_REG_DSIPLL_REGM_DSI]		= { 30, 26 },
-};
-
-static const struct dss_reg_field omap5_dss_reg_fields[] = {
-	[FEAT_REG_FIRHINC]			= { 12, 0 },
-	[FEAT_REG_FIRVINC]			= { 28, 16 },
-	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 15, 0 },
-	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 31, 16 },
-	[FEAT_REG_FIFOSIZE]			= { 15, 0 },
-	[FEAT_REG_HORIZONTALACCU]		= { 10, 0 },
-	[FEAT_REG_VERTICALACCU]			= { 26, 16 },
-	[FEAT_REG_DISPC_CLK_SWITCH]		= { 9, 7 },
-	[FEAT_REG_DSIPLL_REGN]			= { 8, 1 },
-	[FEAT_REG_DSIPLL_REGM]			= { 20, 9 },
-	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 25, 21 },
-	[FEAT_REG_DSIPLL_REGM_DSI]		= { 30, 26 },
-};
-
-static const enum omap_display_type omap2_dss_supported_displays[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DISPLAY_TYPE_VENC,
-};
-
-static const enum omap_display_type omap3430_dss_supported_displays[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-	OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DISPLAY_TYPE_VENC,
-};
-
-static const enum omap_display_type omap3630_dss_supported_displays[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-	OMAP_DISPLAY_TYPE_DSI,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DISPLAY_TYPE_VENC,
-};
-
-static const enum omap_display_type omap4_dss_supported_displays[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI,
-
-	/* OMAP_DSS_CHANNEL_LCD2 */
-	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-	OMAP_DISPLAY_TYPE_DSI,
-};
-
-static const enum omap_display_type omap5_dss_supported_displays[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-	OMAP_DISPLAY_TYPE_DSI,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
-
-	/* OMAP_DSS_CHANNEL_LCD2 */
-	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-	OMAP_DISPLAY_TYPE_DSI,
-};
-
-static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DSS_OUTPUT_VENC,
-};
-
-static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
-	OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DSS_OUTPUT_VENC,
-};
-
-static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
-	OMAP_DSS_OUTPUT_DSI1,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DSS_OUTPUT_VENC,
-};
-
-static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
-
-	/* OMAP_DSS_CHANNEL_LCD2 */
-	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
-	OMAP_DSS_OUTPUT_DSI2,
-};
-
-static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
-	/* OMAP_DSS_CHANNEL_LCD */
-	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
-	OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
-
-	/* OMAP_DSS_CHANNEL_DIGIT */
-	OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
-
-	/* OMAP_DSS_CHANNEL_LCD2 */
-	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
-	OMAP_DSS_OUTPUT_DSI1,
-
-	/* OMAP_DSS_CHANNEL_LCD3 */
-	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
-	OMAP_DSS_OUTPUT_DSI2,
-};
-
-static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
-	/* OMAP_DSS_GFX */
-	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
-	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
-	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
-	OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
-
-	/* OMAP_DSS_VIDEO1 */
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
-	OMAP_DSS_COLOR_UYVY,
-
-	/* OMAP_DSS_VIDEO2 */
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
-	OMAP_DSS_COLOR_UYVY,
-};
-
-static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
-	/* OMAP_DSS_GFX */
-	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
-	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
-	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
-	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
-
-	/* OMAP_DSS_VIDEO1 */
-	OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
-	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
-	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
-
-	/* OMAP_DSS_VIDEO2 */
-	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
-	OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
-	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
-};
-
-static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
-	/* OMAP_DSS_GFX */
-	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
-	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
-	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
-	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
-	OMAP_DSS_COLOR_ARGB16_1555 | OMAP_DSS_COLOR_RGBX16 |
-	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_XRGB16_1555,
-
-	/* OMAP_DSS_VIDEO1 */
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
-	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
-	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
-	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
-	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
-	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
-	OMAP_DSS_COLOR_RGBX32,
-
-       /* OMAP_DSS_VIDEO2 */
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
-	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
-	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
-	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
-	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
-	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
-	OMAP_DSS_COLOR_RGBX32,
-
-	/* OMAP_DSS_VIDEO3 */
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
-	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
-	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
-	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
-	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
-	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
-	OMAP_DSS_COLOR_RGBX32,
-
-	/* OMAP_DSS_WB */
-	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
-	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
-	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
-	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
-	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
-	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
-	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
-	OMAP_DSS_COLOR_RGBX32,
-};
-
-static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
-	/* OMAP_DSS_GFX */
-	OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO1 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
-		OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO2 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
-		OMAP_DSS_OVL_CAP_REPLICATION,
-};
-
-static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
-	/* OMAP_DSS_GFX */
-	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
-		OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO1 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
-		OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO2 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
-};
-
-static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
-	/* OMAP_DSS_GFX */
-	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
-		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO1 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
-		OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO2 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
-		OMAP_DSS_OVL_CAP_REPLICATION,
-};
-
-static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
-	/* OMAP_DSS_GFX */
-	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
-		OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
-		OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO1 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
-		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO2 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
-		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
-
-	/* OMAP_DSS_VIDEO3 */
-	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
-		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
-		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
-};
-
-static const char * const omap2_dss_clk_source_names[] = {
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "N/A",
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "N/A",
-	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCLK1",
-};
-
-static const char * const omap3_dss_clk_source_names[] = {
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI1_PLL_FCLK",
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI2_PLL_FCLK",
-	[OMAP_DSS_CLK_SRC_FCK]			= "DSS1_ALWON_FCLK",
-};
-
-static const char * const omap4_dss_clk_source_names[] = {
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "PLL1_CLK1",
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "PLL1_CLK2",
-	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCLK",
-	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "PLL2_CLK1",
-	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "PLL2_CLK2",
-};
-
-static const char * const omap5_dss_clk_source_names[] = {
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DPLL_DSI1_A_CLK1",
-	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DPLL_DSI1_A_CLK2",
-	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_CLK",
-	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DPLL_DSI1_C_CLK1",
-	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DPLL_DSI1_C_CLK2",
-};
-
-static const struct dss_param_range omap2_dss_param_range[] = {
-	[FEAT_PARAM_DSS_FCK]			= { 0, 133000000 },
-	[FEAT_PARAM_DSS_PCD]			= { 2, 255 },
-	[FEAT_PARAM_DSIPLL_REGN]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_REGM]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_FINT]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, 0 },
-	[FEAT_PARAM_DOWNSCALE]			= { 1, 2 },
-	/*
-	 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
-	 * scaler cannot scale a image with width more than 768.
-	 */
-	[FEAT_PARAM_LINEWIDTH]			= { 1, 768 },
-};
-
-static const struct dss_param_range omap3_dss_param_range[] = {
-	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 },
-	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
-	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 7) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 11) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 4) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 4) - 1 },
-	[FEAT_PARAM_DSIPLL_FINT]		= { 750000, 2100000 },
-	[FEAT_PARAM_DSIPLL_LPDIV]		= { 1, (1 << 13) - 1},
-	[FEAT_PARAM_DSI_FCK]			= { 0, 173000000 },
-	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
-	[FEAT_PARAM_LINEWIDTH]			= { 1, 1024 },
-};
-
-static const struct dss_param_range omap4_dss_param_range[] = {
-	[FEAT_PARAM_DSS_FCK]			= { 0, 186000000 },
-	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
-	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 8) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 12) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 5) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 5) - 1 },
-	[FEAT_PARAM_DSIPLL_FINT]		= { 500000, 2500000 },
-	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, (1 << 13) - 1 },
-	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
-	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
-	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
-};
-
-static const struct dss_param_range omap5_dss_param_range[] = {
-	[FEAT_PARAM_DSS_FCK]			= { 0, 209250000 },
-	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
-	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 8) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 12) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 5) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 5) - 1 },
-	[FEAT_PARAM_DSIPLL_FINT]		= { 150000, 52000000 },
-	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, (1 << 13) - 1 },
-	[FEAT_PARAM_DSI_FCK]			= { 0, 209250000 },
-	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
-	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
-};
-
-static const enum dss_feat_id omap2_dss_feat_list[] = {
-	FEAT_LCDENABLEPOL,
-	FEAT_LCDENABLESIGNAL,
-	FEAT_PCKFREEENABLE,
-	FEAT_FUNCGATED,
-	FEAT_ROWREPEATENABLE,
-	FEAT_RESIZECONF,
-};
-
-static const enum dss_feat_id omap3430_dss_feat_list[] = {
-	FEAT_LCDENABLEPOL,
-	FEAT_LCDENABLESIGNAL,
-	FEAT_PCKFREEENABLE,
-	FEAT_FUNCGATED,
-	FEAT_LINEBUFFERSPLIT,
-	FEAT_ROWREPEATENABLE,
-	FEAT_RESIZECONF,
-	FEAT_DSI_PLL_FREQSEL,
-	FEAT_DSI_REVERSE_TXCLKESC,
-	FEAT_VENC_REQUIRES_TV_DAC_CLK,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FIXED_ZORDER,
-	FEAT_FIFO_MERGE,
-	FEAT_OMAP3_DSI_FIFO_BUG,
-	FEAT_DPI_USES_VDDS_DSI,
-};
-
-static const enum dss_feat_id am35xx_dss_feat_list[] = {
-	FEAT_LCDENABLEPOL,
-	FEAT_LCDENABLESIGNAL,
-	FEAT_PCKFREEENABLE,
-	FEAT_FUNCGATED,
-	FEAT_LINEBUFFERSPLIT,
-	FEAT_ROWREPEATENABLE,
-	FEAT_RESIZECONF,
-	FEAT_DSI_PLL_FREQSEL,
-	FEAT_DSI_REVERSE_TXCLKESC,
-	FEAT_VENC_REQUIRES_TV_DAC_CLK,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FIXED_ZORDER,
-	FEAT_FIFO_MERGE,
-	FEAT_OMAP3_DSI_FIFO_BUG,
-};
-
-static const enum dss_feat_id omap3630_dss_feat_list[] = {
-	FEAT_LCDENABLEPOL,
-	FEAT_LCDENABLESIGNAL,
-	FEAT_PCKFREEENABLE,
-	FEAT_FUNCGATED,
-	FEAT_LINEBUFFERSPLIT,
-	FEAT_ROWREPEATENABLE,
-	FEAT_RESIZECONF,
-	FEAT_DSI_PLL_PWR_BUG,
-	FEAT_DSI_PLL_FREQSEL,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FIXED_ZORDER,
-	FEAT_FIFO_MERGE,
-	FEAT_OMAP3_DSI_FIFO_BUG,
-	FEAT_DPI_USES_VDDS_DSI,
-};
-
-static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
-	FEAT_MGR_LCD2,
-	FEAT_CORE_CLK_DIV,
-	FEAT_LCD_CLK_SRC,
-	FEAT_DSI_DCS_CMD_CONFIG_VC,
-	FEAT_DSI_VC_OCP_WIDTH,
-	FEAT_DSI_GNQ,
-	FEAT_HANDLE_UV_SEPARATE,
-	FEAT_ATTR2,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FREE_ZORDER,
-	FEAT_FIFO_MERGE,
-	FEAT_BURST_2D,
-};
-
-static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
-	FEAT_MGR_LCD2,
-	FEAT_CORE_CLK_DIV,
-	FEAT_LCD_CLK_SRC,
-	FEAT_DSI_DCS_CMD_CONFIG_VC,
-	FEAT_DSI_VC_OCP_WIDTH,
-	FEAT_DSI_GNQ,
-	FEAT_HDMI_CTS_SWMODE,
-	FEAT_HANDLE_UV_SEPARATE,
-	FEAT_ATTR2,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FREE_ZORDER,
-	FEAT_FIFO_MERGE,
-	FEAT_BURST_2D,
-};
-
-static const enum dss_feat_id omap4_dss_feat_list[] = {
-	FEAT_MGR_LCD2,
-	FEAT_CORE_CLK_DIV,
-	FEAT_LCD_CLK_SRC,
-	FEAT_DSI_DCS_CMD_CONFIG_VC,
-	FEAT_DSI_VC_OCP_WIDTH,
-	FEAT_DSI_GNQ,
-	FEAT_HDMI_CTS_SWMODE,
-	FEAT_HDMI_AUDIO_USE_MCLK,
-	FEAT_HANDLE_UV_SEPARATE,
-	FEAT_ATTR2,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FREE_ZORDER,
-	FEAT_FIFO_MERGE,
-	FEAT_BURST_2D,
-};
-
-static const enum dss_feat_id omap5_dss_feat_list[] = {
-	FEAT_MGR_LCD2,
-	FEAT_CORE_CLK_DIV,
-	FEAT_LCD_CLK_SRC,
-	FEAT_DSI_DCS_CMD_CONFIG_VC,
-	FEAT_DSI_VC_OCP_WIDTH,
-	FEAT_DSI_GNQ,
-	FEAT_HDMI_CTS_SWMODE,
-	FEAT_HDMI_AUDIO_USE_MCLK,
-	FEAT_HANDLE_UV_SEPARATE,
-	FEAT_ATTR2,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FREE_ZORDER,
-	FEAT_FIFO_MERGE,
-	FEAT_BURST_2D,
-	FEAT_DSI_PLL_SELFREQDCO,
-	FEAT_DSI_PLL_REFSEL,
-	FEAT_DSI_PHY_DCC,
-	FEAT_MFLAG,
-};
-
-/* OMAP2 DSS Features */
-static const struct omap_dss_features omap2_dss_features = {
-	.reg_fields = omap2_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
-
-	.features = omap2_dss_feat_list,
-	.num_features = ARRAY_SIZE(omap2_dss_feat_list),
-
-	.num_mgrs = 2,
-	.num_ovls = 3,
-	.supported_displays = omap2_dss_supported_displays,
-	.supported_outputs = omap2_dss_supported_outputs,
-	.supported_color_modes = omap2_dss_supported_color_modes,
-	.overlay_caps = omap2_dss_overlay_caps,
-	.clksrc_names = omap2_dss_clk_source_names,
-	.dss_params = omap2_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
-	.buffer_size_unit = 1,
-	.burst_size_unit = 8,
-};
-
-/* OMAP3 DSS Features */
-static const struct omap_dss_features omap3430_dss_features = {
-	.reg_fields = omap3_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
-
-	.features = omap3430_dss_feat_list,
-	.num_features = ARRAY_SIZE(omap3430_dss_feat_list),
-
-	.num_mgrs = 2,
-	.num_ovls = 3,
-	.supported_displays = omap3430_dss_supported_displays,
-	.supported_outputs = omap3430_dss_supported_outputs,
-	.supported_color_modes = omap3_dss_supported_color_modes,
-	.overlay_caps = omap3430_dss_overlay_caps,
-	.clksrc_names = omap3_dss_clk_source_names,
-	.dss_params = omap3_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
-	.buffer_size_unit = 1,
-	.burst_size_unit = 8,
-};
-
-/*
- * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
- * vdds_dsi regulator.
- */
-static const struct omap_dss_features am35xx_dss_features = {
-	.reg_fields = omap3_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
-
-	.features = am35xx_dss_feat_list,
-	.num_features = ARRAY_SIZE(am35xx_dss_feat_list),
-
-	.num_mgrs = 2,
-	.num_ovls = 3,
-	.supported_displays = omap3430_dss_supported_displays,
-	.supported_outputs = omap3430_dss_supported_outputs,
-	.supported_color_modes = omap3_dss_supported_color_modes,
-	.overlay_caps = omap3430_dss_overlay_caps,
-	.clksrc_names = omap3_dss_clk_source_names,
-	.dss_params = omap3_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
-	.buffer_size_unit = 1,
-	.burst_size_unit = 8,
-};
-
-static const struct omap_dss_features omap3630_dss_features = {
-	.reg_fields = omap3_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
-
-	.features = omap3630_dss_feat_list,
-	.num_features = ARRAY_SIZE(omap3630_dss_feat_list),
-
-	.num_mgrs = 2,
-	.num_ovls = 3,
-	.supported_displays = omap3630_dss_supported_displays,
-	.supported_outputs = omap3630_dss_supported_outputs,
-	.supported_color_modes = omap3_dss_supported_color_modes,
-	.overlay_caps = omap3630_dss_overlay_caps,
-	.clksrc_names = omap3_dss_clk_source_names,
-	.dss_params = omap3_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
-	.buffer_size_unit = 1,
-	.burst_size_unit = 8,
-};
-
-/* OMAP4 DSS Features */
-/* For OMAP4430 ES 1.0 revision */
-static const struct omap_dss_features omap4430_es1_0_dss_features  = {
-	.reg_fields = omap4_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
-
-	.features = omap4430_es1_0_dss_feat_list,
-	.num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list),
-
-	.num_mgrs = 3,
-	.num_ovls = 4,
-	.num_wbs = 1,
-	.supported_displays = omap4_dss_supported_displays,
-	.supported_outputs = omap4_dss_supported_outputs,
-	.supported_color_modes = omap4_dss_supported_color_modes,
-	.overlay_caps = omap4_dss_overlay_caps,
-	.clksrc_names = omap4_dss_clk_source_names,
-	.dss_params = omap4_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
-	.buffer_size_unit = 16,
-	.burst_size_unit = 16,
-};
-
-/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
-static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
-	.reg_fields = omap4_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
-
-	.features = omap4430_es2_0_1_2_dss_feat_list,
-	.num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list),
-
-	.num_mgrs = 3,
-	.num_ovls = 4,
-	.num_wbs = 1,
-	.supported_displays = omap4_dss_supported_displays,
-	.supported_outputs = omap4_dss_supported_outputs,
-	.supported_color_modes = omap4_dss_supported_color_modes,
-	.overlay_caps = omap4_dss_overlay_caps,
-	.clksrc_names = omap4_dss_clk_source_names,
-	.dss_params = omap4_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
-	.buffer_size_unit = 16,
-	.burst_size_unit = 16,
-};
-
-/* For all the other OMAP4 versions */
-static const struct omap_dss_features omap4_dss_features = {
-	.reg_fields = omap4_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
-
-	.features = omap4_dss_feat_list,
-	.num_features = ARRAY_SIZE(omap4_dss_feat_list),
-
-	.num_mgrs = 3,
-	.num_ovls = 4,
-	.num_wbs = 1,
-	.supported_displays = omap4_dss_supported_displays,
-	.supported_outputs = omap4_dss_supported_outputs,
-	.supported_color_modes = omap4_dss_supported_color_modes,
-	.overlay_caps = omap4_dss_overlay_caps,
-	.clksrc_names = omap4_dss_clk_source_names,
-	.dss_params = omap4_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
-	.buffer_size_unit = 16,
-	.burst_size_unit = 16,
-};
-
-/* OMAP5 DSS Features */
-static const struct omap_dss_features omap5_dss_features = {
-	.reg_fields = omap5_dss_reg_fields,
-	.num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
-
-	.features = omap5_dss_feat_list,
-	.num_features = ARRAY_SIZE(omap5_dss_feat_list),
-
-	.num_mgrs = 3,
-	.num_ovls = 4,
-	.supported_displays = omap5_dss_supported_displays,
-	.supported_outputs = omap5_dss_supported_outputs,
-	.supported_color_modes = omap4_dss_supported_color_modes,
-	.overlay_caps = omap4_dss_overlay_caps,
-	.clksrc_names = omap5_dss_clk_source_names,
-	.dss_params = omap5_dss_param_range,
-	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
-	.buffer_size_unit = 16,
-	.burst_size_unit = 16,
-};
-
-/* Functions returning values related to a DSS feature */
-int dss_feat_get_num_mgrs(void)
-{
-	return omap_current_dss_features->num_mgrs;
-}
-EXPORT_SYMBOL(dss_feat_get_num_mgrs);
-
-int dss_feat_get_num_ovls(void)
-{
-	return omap_current_dss_features->num_ovls;
-}
-EXPORT_SYMBOL(dss_feat_get_num_ovls);
-
-int dss_feat_get_num_wbs(void)
-{
-	return omap_current_dss_features->num_wbs;
-}
-
-unsigned long dss_feat_get_param_min(enum dss_range_param param)
-{
-	return omap_current_dss_features->dss_params[param].min;
-}
-
-unsigned long dss_feat_get_param_max(enum dss_range_param param)
-{
-	return omap_current_dss_features->dss_params[param].max;
-}
-
-enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
-{
-	return omap_current_dss_features->supported_displays[channel];
-}
-EXPORT_SYMBOL(dss_feat_get_supported_displays);
-
-enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
-{
-	return omap_current_dss_features->supported_outputs[channel];
-}
-EXPORT_SYMBOL(dss_feat_get_supported_outputs);
-
-enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
-{
-	return omap_current_dss_features->supported_color_modes[plane];
-}
-EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
-
-enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
-{
-	return omap_current_dss_features->overlay_caps[plane];
-}
-
-bool dss_feat_color_mode_supported(enum omap_plane plane,
-		enum omap_color_mode color_mode)
-{
-	return omap_current_dss_features->supported_color_modes[plane] &
-			color_mode;
-}
-
-const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
-{
-	return omap_current_dss_features->clksrc_names[id];
-}
-
-u32 dss_feat_get_buffer_size_unit(void)
-{
-	return omap_current_dss_features->buffer_size_unit;
-}
-
-u32 dss_feat_get_burst_size_unit(void)
-{
-	return omap_current_dss_features->burst_size_unit;
-}
-
-/* DSS has_feature check */
-bool dss_has_feature(enum dss_feat_id id)
-{
-	int i;
-	const enum dss_feat_id *features = omap_current_dss_features->features;
-	const int num_features = omap_current_dss_features->num_features;
-
-	for (i = 0; i < num_features; i++) {
-		if (features[i] == id)
-			return true;
-	}
-
-	return false;
-}
-
-void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
-{
-	if (id >= omap_current_dss_features->num_reg_fields)
-		BUG();
-
-	*start = omap_current_dss_features->reg_fields[id].start;
-	*end = omap_current_dss_features->reg_fields[id].end;
-}
-
-bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
-{
-	return omap_current_dss_features->supported_rotation_types & rot_type;
-}
-
-void dss_features_init(enum omapdss_version version)
-{
-	switch (version) {
-	case OMAPDSS_VER_OMAP24xx:
-		omap_current_dss_features = &omap2_dss_features;
-		break;
-
-	case OMAPDSS_VER_OMAP34xx_ES1:
-	case OMAPDSS_VER_OMAP34xx_ES3:
-		omap_current_dss_features = &omap3430_dss_features;
-		break;
-
-	case OMAPDSS_VER_OMAP3630:
-		omap_current_dss_features = &omap3630_dss_features;
-		break;
-
-	case OMAPDSS_VER_OMAP4430_ES1:
-		omap_current_dss_features = &omap4430_es1_0_dss_features;
-		break;
-
-	case OMAPDSS_VER_OMAP4430_ES2:
-		omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
-		break;
-
-	case OMAPDSS_VER_OMAP4:
-		omap_current_dss_features = &omap4_dss_features;
-		break;
-
-	case OMAPDSS_VER_OMAP5:
-		omap_current_dss_features = &omap5_dss_features;
-		break;
-
-	case OMAPDSS_VER_AM35xx:
-		omap_current_dss_features = &am35xx_dss_features;
-		break;
-
-	default:
-		DSSWARN("Unsupported OMAP version");
-		break;
-	}
-}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
deleted file mode 100644
index e3ef3b714896..000000000000
--- a/drivers/video/omap2/dss/dss_features.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/dss_features.h
- *
- * Copyright (C) 2010 Texas Instruments
- * Author: Archit Taneja <archit@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP2_DSS_FEATURES_H
-#define __OMAP2_DSS_FEATURES_H
-
-#define MAX_DSS_MANAGERS	4
-#define MAX_DSS_OVERLAYS	4
-#define MAX_DSS_LCD_MANAGERS	3
-#define MAX_NUM_DSI		2
-
-/* DSS has feature id */
-enum dss_feat_id {
-	FEAT_LCDENABLEPOL,
-	FEAT_LCDENABLESIGNAL,
-	FEAT_PCKFREEENABLE,
-	FEAT_FUNCGATED,
-	FEAT_MGR_LCD2,
-	FEAT_MGR_LCD3,
-	FEAT_LINEBUFFERSPLIT,
-	FEAT_ROWREPEATENABLE,
-	FEAT_RESIZECONF,
-	/* Independent core clk divider */
-	FEAT_CORE_CLK_DIV,
-	FEAT_LCD_CLK_SRC,
-	/* DSI-PLL power command 0x3 is not working */
-	FEAT_DSI_PLL_PWR_BUG,
-	FEAT_DSI_PLL_FREQSEL,
-	FEAT_DSI_DCS_CMD_CONFIG_VC,
-	FEAT_DSI_VC_OCP_WIDTH,
-	FEAT_DSI_REVERSE_TXCLKESC,
-	FEAT_DSI_GNQ,
-	FEAT_DPI_USES_VDDS_DSI,
-	FEAT_HDMI_CTS_SWMODE,
-	FEAT_HDMI_AUDIO_USE_MCLK,
-	FEAT_HANDLE_UV_SEPARATE,
-	FEAT_ATTR2,
-	FEAT_VENC_REQUIRES_TV_DAC_CLK,
-	FEAT_CPR,
-	FEAT_PRELOAD,
-	FEAT_FIR_COEF_V,
-	FEAT_ALPHA_FIXED_ZORDER,
-	FEAT_ALPHA_FREE_ZORDER,
-	FEAT_FIFO_MERGE,
-	/* An unknown HW bug causing the normal FIFO thresholds not to work */
-	FEAT_OMAP3_DSI_FIFO_BUG,
-	FEAT_BURST_2D,
-	FEAT_DSI_PLL_SELFREQDCO,
-	FEAT_DSI_PLL_REFSEL,
-	FEAT_DSI_PHY_DCC,
-	FEAT_MFLAG,
-};
-
-/* DSS register field id */
-enum dss_feat_reg_field {
-	FEAT_REG_FIRHINC,
-	FEAT_REG_FIRVINC,
-	FEAT_REG_FIFOHIGHTHRESHOLD,
-	FEAT_REG_FIFOLOWTHRESHOLD,
-	FEAT_REG_FIFOSIZE,
-	FEAT_REG_HORIZONTALACCU,
-	FEAT_REG_VERTICALACCU,
-	FEAT_REG_DISPC_CLK_SWITCH,
-	FEAT_REG_DSIPLL_REGN,
-	FEAT_REG_DSIPLL_REGM,
-	FEAT_REG_DSIPLL_REGM_DISPC,
-	FEAT_REG_DSIPLL_REGM_DSI,
-};
-
-enum dss_range_param {
-	FEAT_PARAM_DSS_FCK,
-	FEAT_PARAM_DSS_PCD,
-	FEAT_PARAM_DSIPLL_REGN,
-	FEAT_PARAM_DSIPLL_REGM,
-	FEAT_PARAM_DSIPLL_REGM_DISPC,
-	FEAT_PARAM_DSIPLL_REGM_DSI,
-	FEAT_PARAM_DSIPLL_FINT,
-	FEAT_PARAM_DSIPLL_LPDIV,
-	FEAT_PARAM_DSI_FCK,
-	FEAT_PARAM_DOWNSCALE,
-	FEAT_PARAM_LINEWIDTH,
-};
-
-/* DSS Feature Functions */
-int dss_feat_get_num_wbs(void);
-unsigned long dss_feat_get_param_min(enum dss_range_param param);
-unsigned long dss_feat_get_param_max(enum dss_range_param param);
-enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
-bool dss_feat_color_mode_supported(enum omap_plane plane,
-		enum omap_color_mode color_mode);
-const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
-
-u32 dss_feat_get_buffer_size_unit(void);	/* in bytes */
-u32 dss_feat_get_burst_size_unit(void);		/* in bytes */
-
-bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
-
-bool dss_has_feature(enum dss_feat_id id);
-void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
-void dss_features_init(enum omapdss_version version);
-#endif
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
deleted file mode 100644
index e25681ff5a70..000000000000
--- a/drivers/video/omap2/dss/hdmi.h
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * HDMI driver definition for TI OMAP4 Processor.
- *
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _HDMI_H
-#define _HDMI_H
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <video/omapdss.h>
-
-#include "dss.h"
-
-/* HDMI Wrapper */
-
-#define HDMI_WP_REVISION			0x0
-#define HDMI_WP_SYSCONFIG			0x10
-#define HDMI_WP_IRQSTATUS_RAW			0x24
-#define HDMI_WP_IRQSTATUS			0x28
-#define HDMI_WP_IRQENABLE_SET			0x2C
-#define HDMI_WP_IRQENABLE_CLR			0x30
-#define HDMI_WP_IRQWAKEEN			0x34
-#define HDMI_WP_PWR_CTRL			0x40
-#define HDMI_WP_DEBOUNCE			0x44
-#define HDMI_WP_VIDEO_CFG			0x50
-#define HDMI_WP_VIDEO_SIZE			0x60
-#define HDMI_WP_VIDEO_TIMING_H			0x68
-#define HDMI_WP_VIDEO_TIMING_V			0x6C
-#define HDMI_WP_CLK				0x70
-#define HDMI_WP_AUDIO_CFG			0x80
-#define HDMI_WP_AUDIO_CFG2			0x84
-#define HDMI_WP_AUDIO_CTRL			0x88
-#define HDMI_WP_AUDIO_DATA			0x8C
-
-/* HDMI WP IRQ flags */
-#define HDMI_IRQ_CORE				(1 << 0)
-#define HDMI_IRQ_OCP_TIMEOUT			(1 << 4)
-#define HDMI_IRQ_AUDIO_FIFO_UNDERFLOW		(1 << 8)
-#define HDMI_IRQ_AUDIO_FIFO_OVERFLOW		(1 << 9)
-#define HDMI_IRQ_AUDIO_FIFO_SAMPLE_REQ		(1 << 10)
-#define HDMI_IRQ_VIDEO_VSYNC			(1 << 16)
-#define HDMI_IRQ_VIDEO_FRAME_DONE		(1 << 17)
-#define HDMI_IRQ_PHY_LINE5V_ASSERT		(1 << 24)
-#define HDMI_IRQ_LINK_CONNECT			(1 << 25)
-#define HDMI_IRQ_LINK_DISCONNECT		(1 << 26)
-#define HDMI_IRQ_PLL_LOCK			(1 << 29)
-#define HDMI_IRQ_PLL_UNLOCK			(1 << 30)
-#define HDMI_IRQ_PLL_RECAL			(1 << 31)
-
-/* HDMI PLL */
-
-#define PLLCTRL_PLL_CONTROL			0x0
-#define PLLCTRL_PLL_STATUS			0x4
-#define PLLCTRL_PLL_GO				0x8
-#define PLLCTRL_CFG1				0xC
-#define PLLCTRL_CFG2				0x10
-#define PLLCTRL_CFG3				0x14
-#define PLLCTRL_SSC_CFG1			0x18
-#define PLLCTRL_SSC_CFG2			0x1C
-#define PLLCTRL_CFG4				0x20
-
-/* HDMI PHY */
-
-#define HDMI_TXPHY_TX_CTRL			0x0
-#define HDMI_TXPHY_DIGITAL_CTRL			0x4
-#define HDMI_TXPHY_POWER_CTRL			0x8
-#define HDMI_TXPHY_PAD_CFG_CTRL			0xC
-
-enum hdmi_pll_pwr {
-	HDMI_PLLPWRCMD_ALLOFF = 0,
-	HDMI_PLLPWRCMD_PLLONLY = 1,
-	HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
-	HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
-};
-
-enum hdmi_phy_pwr {
-	HDMI_PHYPWRCMD_OFF = 0,
-	HDMI_PHYPWRCMD_LDOON = 1,
-	HDMI_PHYPWRCMD_TXON = 2
-};
-
-enum hdmi_core_hdmi_dvi {
-	HDMI_DVI = 0,
-	HDMI_HDMI = 1
-};
-
-enum hdmi_clk_refsel {
-	HDMI_REFSEL_PCLK = 0,
-	HDMI_REFSEL_REF1 = 1,
-	HDMI_REFSEL_REF2 = 2,
-	HDMI_REFSEL_SYSCLK = 3
-};
-
-enum hdmi_packing_mode {
-	HDMI_PACK_10b_RGB_YUV444 = 0,
-	HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
-	HDMI_PACK_20b_YUV422 = 2,
-	HDMI_PACK_ALREADYPACKED = 7
-};
-
-enum hdmi_stereo_channels {
-	HDMI_AUDIO_STEREO_NOCHANNELS = 0,
-	HDMI_AUDIO_STEREO_ONECHANNEL = 1,
-	HDMI_AUDIO_STEREO_TWOCHANNELS = 2,
-	HDMI_AUDIO_STEREO_THREECHANNELS = 3,
-	HDMI_AUDIO_STEREO_FOURCHANNELS = 4
-};
-
-enum hdmi_audio_type {
-	HDMI_AUDIO_TYPE_LPCM = 0,
-	HDMI_AUDIO_TYPE_IEC = 1
-};
-
-enum hdmi_audio_justify {
-	HDMI_AUDIO_JUSTIFY_LEFT = 0,
-	HDMI_AUDIO_JUSTIFY_RIGHT = 1
-};
-
-enum hdmi_audio_sample_order {
-	HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0,
-	HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1
-};
-
-enum hdmi_audio_samples_perword {
-	HDMI_AUDIO_ONEWORD_ONESAMPLE = 0,
-	HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
-};
-
-enum hdmi_audio_sample_size {
-	HDMI_AUDIO_SAMPLE_16BITS = 0,
-	HDMI_AUDIO_SAMPLE_24BITS = 1
-};
-
-enum hdmi_audio_transf_mode {
-	HDMI_AUDIO_TRANSF_DMA = 0,
-	HDMI_AUDIO_TRANSF_IRQ = 1
-};
-
-enum hdmi_audio_blk_strt_end_sig {
-	HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0,
-	HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1
-};
-
-enum hdmi_core_audio_layout {
-	HDMI_AUDIO_LAYOUT_2CH = 0,
-	HDMI_AUDIO_LAYOUT_8CH = 1
-};
-
-enum hdmi_core_cts_mode {
-	HDMI_AUDIO_CTS_MODE_HW = 0,
-	HDMI_AUDIO_CTS_MODE_SW = 1
-};
-
-enum hdmi_audio_mclk_mode {
-	HDMI_AUDIO_MCLK_128FS = 0,
-	HDMI_AUDIO_MCLK_256FS = 1,
-	HDMI_AUDIO_MCLK_384FS = 2,
-	HDMI_AUDIO_MCLK_512FS = 3,
-	HDMI_AUDIO_MCLK_768FS = 4,
-	HDMI_AUDIO_MCLK_1024FS = 5,
-	HDMI_AUDIO_MCLK_1152FS = 6,
-	HDMI_AUDIO_MCLK_192FS = 7
-};
-
-/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
-enum hdmi_core_infoframe {
-	HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
-	HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
-	HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2,
-	HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0,
-	HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON =  1,
-	HDMI_INFOFRAME_AVI_DB1B_NO = 0,
-	HDMI_INFOFRAME_AVI_DB1B_VERT = 1,
-	HDMI_INFOFRAME_AVI_DB1B_HORI = 2,
-	HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3,
-	HDMI_INFOFRAME_AVI_DB1S_0 = 0,
-	HDMI_INFOFRAME_AVI_DB1S_1 = 1,
-	HDMI_INFOFRAME_AVI_DB1S_2 = 2,
-	HDMI_INFOFRAME_AVI_DB2C_NO = 0,
-	HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1,
-	HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2,
-	HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3,
-	HDMI_INFOFRAME_AVI_DB2M_NO = 0,
-	HDMI_INFOFRAME_AVI_DB2M_43 = 1,
-	HDMI_INFOFRAME_AVI_DB2M_169 = 2,
-	HDMI_INFOFRAME_AVI_DB2R_SAME = 8,
-	HDMI_INFOFRAME_AVI_DB2R_43 = 9,
-	HDMI_INFOFRAME_AVI_DB2R_169 = 10,
-	HDMI_INFOFRAME_AVI_DB2R_149 = 11,
-	HDMI_INFOFRAME_AVI_DB3ITC_NO = 0,
-	HDMI_INFOFRAME_AVI_DB3ITC_YES = 1,
-	HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0,
-	HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1,
-	HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0,
-	HDMI_INFOFRAME_AVI_DB3Q_LR = 1,
-	HDMI_INFOFRAME_AVI_DB3Q_FR = 2,
-	HDMI_INFOFRAME_AVI_DB3SC_NO = 0,
-	HDMI_INFOFRAME_AVI_DB3SC_HORI = 1,
-	HDMI_INFOFRAME_AVI_DB3SC_VERT = 2,
-	HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3,
-	HDMI_INFOFRAME_AVI_DB5PR_NO = 0,
-	HDMI_INFOFRAME_AVI_DB5PR_2 = 1,
-	HDMI_INFOFRAME_AVI_DB5PR_3 = 2,
-	HDMI_INFOFRAME_AVI_DB5PR_4 = 3,
-	HDMI_INFOFRAME_AVI_DB5PR_5 = 4,
-	HDMI_INFOFRAME_AVI_DB5PR_6 = 5,
-	HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
-	HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
-	HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
-	HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
-};
-
-struct hdmi_cm {
-	int	code;
-	int	mode;
-};
-
-struct hdmi_video_format {
-	enum hdmi_packing_mode	packing_mode;
-	u32			y_res;	/* Line per panel */
-	u32			x_res;	/* pixel per line */
-};
-
-struct hdmi_config {
-	struct omap_video_timings timings;
-	struct hdmi_cm cm;
-};
-
-/* HDMI PLL structure */
-struct hdmi_pll_info {
-	u16 regn;
-	u16 regm;
-	u32 regmf;
-	u16 regm2;
-	u16 regsd;
-	u16 dcofreq;
-	enum hdmi_clk_refsel refsel;
-};
-
-struct hdmi_audio_format {
-	enum hdmi_stereo_channels		stereo_channels;
-	u8					active_chnnls_msk;
-	enum hdmi_audio_type			type;
-	enum hdmi_audio_justify			justification;
-	enum hdmi_audio_sample_order		sample_order;
-	enum hdmi_audio_samples_perword		samples_per_word;
-	enum hdmi_audio_sample_size		sample_size;
-	enum hdmi_audio_blk_strt_end_sig	en_sig_blk_strt_end;
-};
-
-struct hdmi_audio_dma {
-	u8				transfer_size;
-	u8				block_size;
-	enum hdmi_audio_transf_mode	mode;
-	u16				fifo_threshold;
-};
-
-struct hdmi_core_audio_i2s_config {
-	u8 in_length_bits;
-	u8 justification;
-	u8 sck_edge_mode;
-	u8 vbit;
-	u8 direction;
-	u8 shift;
-	u8 active_sds;
-};
-
-struct hdmi_core_audio_config {
-	struct hdmi_core_audio_i2s_config	i2s_cfg;
-	struct snd_aes_iec958			*iec60958_cfg;
-	bool					fs_override;
-	u32					n;
-	u32					cts;
-	u32					aud_par_busclk;
-	enum hdmi_core_audio_layout		layout;
-	enum hdmi_core_cts_mode			cts_mode;
-	bool					use_mclk;
-	enum hdmi_audio_mclk_mode		mclk_mode;
-	bool					en_acr_pkt;
-	bool					en_dsd_audio;
-	bool					en_parallel_aud_input;
-	bool					en_spdif;
-};
-
-/*
- * Refer to section 8.2 in HDMI 1.3 specification for
- * details about infoframe databytes
- */
-struct hdmi_core_infoframe_avi {
-	/* Y0, Y1 rgb,yCbCr */
-	u8	db1_format;
-	/* A0  Active information Present */
-	u8	db1_active_info;
-	/* B0, B1 Bar info data valid */
-	u8	db1_bar_info_dv;
-	/* S0, S1 scan information */
-	u8	db1_scan_info;
-	/* C0, C1 colorimetry */
-	u8	db2_colorimetry;
-	/* M0, M1 Aspect ratio (4:3, 16:9) */
-	u8	db2_aspect_ratio;
-	/* R0...R3 Active format aspect ratio */
-	u8	db2_active_fmt_ar;
-	/* ITC IT content. */
-	u8	db3_itc;
-	/* EC0, EC1, EC2 Extended colorimetry */
-	u8	db3_ec;
-	/* Q1, Q0 Quantization range */
-	u8	db3_q_range;
-	/* SC1, SC0 Non-uniform picture scaling */
-	u8	db3_nup_scaling;
-	/* VIC0..6 Video format identification */
-	u8	db4_videocode;
-	/* PR0..PR3 Pixel repetition factor */
-	u8	db5_pixel_repeat;
-	/* Line number end of top bar */
-	u16	db6_7_line_eoftop;
-	/* Line number start of bottom bar */
-	u16	db8_9_line_sofbottom;
-	/* Pixel number end of left bar */
-	u16	db10_11_pixel_eofleft;
-	/* Pixel number start of right bar */
-	u16	db12_13_pixel_sofright;
-};
-
-struct hdmi_wp_data {
-	void __iomem *base;
-};
-
-struct hdmi_pll_data {
-	void __iomem *base;
-
-	struct hdmi_pll_info info;
-};
-
-struct hdmi_phy_data {
-	void __iomem *base;
-
-	int irq;
-};
-
-struct hdmi_core_data {
-	void __iomem *base;
-
-	struct hdmi_core_infoframe_avi avi_cfg;
-};
-
-static inline void hdmi_write_reg(void __iomem *base_addr, const u16 idx,
-		u32 val)
-{
-	__raw_writel(val, base_addr + idx);
-}
-
-static inline u32 hdmi_read_reg(void __iomem *base_addr, const u16 idx)
-{
-	return __raw_readl(base_addr + idx);
-}
-
-#define REG_FLD_MOD(base, idx, val, start, end) \
-	hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
-							val, start, end))
-#define REG_GET(base, idx, start, end) \
-	FLD_GET(hdmi_read_reg(base, idx), start, end)
-
-static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
-		const u32 idx, int b2, int b1, u32 val)
-{
-	u32 t = 0, v;
-	while (val != (v = REG_GET(base_addr, idx, b2, b1))) {
-		if (t++ > 10000)
-			return v;
-		udelay(1);
-	}
-	return v;
-}
-
-/* HDMI wrapper funcs */
-int hdmi_wp_video_start(struct hdmi_wp_data *wp);
-void hdmi_wp_video_stop(struct hdmi_wp_data *wp);
-void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s);
-u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp);
-void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus);
-void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask);
-void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask);
-int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val);
-int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val);
-void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
-		struct hdmi_video_format *video_fmt);
-void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings);
-void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings);
-void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
-		struct omap_video_timings *timings, struct hdmi_config *param);
-int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
-
-/* HDMI PLL funcs */
-int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
-void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
-void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
-void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy);
-int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll);
-
-/* HDMI PHY funcs */
-int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
-		struct hdmi_config *cfg);
-void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp);
-void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
-int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
-
-/* HDMI common funcs */
-const struct hdmi_config *hdmi_default_timing(void);
-const struct hdmi_config *hdmi_get_timings(int mode, int code);
-struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing);
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
-int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
-int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
-void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
-		struct hdmi_audio_format *aud_fmt);
-void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
-		struct hdmi_audio_dma *aud_dma);
-static inline bool hdmi_mode_has_audio(int mode)
-{
-	return mode == HDMI_HDMI ? true : false;
-}
-#endif
-#endif
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c
deleted file mode 100644
index f5f7944a1fd1..000000000000
--- a/drivers/video/omap2/dss/hdmi4.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * HDMI interface DSS driver for TI's OMAP4 family of SoCs.
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
- * Authors: Yong Zhi
- *	Mythri pk <mythripk@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "HDMI"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
-#include <video/omapdss.h>
-
-#include "hdmi4_core.h"
-#include "dss.h"
-#include "dss_features.h"
-
-static struct {
-	struct mutex lock;
-	struct platform_device *pdev;
-
-	struct hdmi_wp_data	wp;
-	struct hdmi_pll_data	pll;
-	struct hdmi_phy_data	phy;
-	struct hdmi_core_data	core;
-
-	struct hdmi_config cfg;
-
-	struct clk *sys_clk;
-	struct regulator *vdda_hdmi_dac_reg;
-
-	bool core_enabled;
-
-	struct omap_dss_device output;
-} hdmi;
-
-static int hdmi_runtime_get(void)
-{
-	int r;
-
-	DSSDBG("hdmi_runtime_get\n");
-
-	r = pm_runtime_get_sync(&hdmi.pdev->dev);
-	WARN_ON(r < 0);
-	if (r < 0)
-		return r;
-
-	return 0;
-}
-
-static void hdmi_runtime_put(void)
-{
-	int r;
-
-	DSSDBG("hdmi_runtime_put\n");
-
-	r = pm_runtime_put_sync(&hdmi.pdev->dev);
-	WARN_ON(r < 0 && r != -ENOSYS);
-}
-
-static int hdmi_init_regulator(void)
-{
-	struct regulator *reg;
-
-	if (hdmi.vdda_hdmi_dac_reg != NULL)
-		return 0;
-
-	reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
-
-	if (IS_ERR(reg)) {
-		if (PTR_ERR(reg) != -EPROBE_DEFER)
-			DSSERR("can't get VDDA regulator\n");
-		return PTR_ERR(reg);
-	}
-
-	hdmi.vdda_hdmi_dac_reg = reg;
-
-	return 0;
-}
-
-static int hdmi_power_on_core(struct omap_dss_device *dssdev)
-{
-	int r;
-
-	r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
-	if (r)
-		return r;
-
-	r = hdmi_runtime_get();
-	if (r)
-		goto err_runtime_get;
-
-	/* Make selection of HDMI in DSS */
-	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
-
-	hdmi.core_enabled = true;
-
-	return 0;
-
-err_runtime_get:
-	regulator_disable(hdmi.vdda_hdmi_dac_reg);
-
-	return r;
-}
-
-static void hdmi_power_off_core(struct omap_dss_device *dssdev)
-{
-	hdmi.core_enabled = false;
-
-	hdmi_runtime_put();
-	regulator_disable(hdmi.vdda_hdmi_dac_reg);
-}
-
-static int hdmi_power_on_full(struct omap_dss_device *dssdev)
-{
-	int r;
-	struct omap_video_timings *p;
-	struct omap_overlay_manager *mgr = hdmi.output.manager;
-	unsigned long phy;
-
-	r = hdmi_power_on_core(dssdev);
-	if (r)
-		return r;
-
-	p = &hdmi.cfg.timings;
-
-	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
-
-	/* the functions below use kHz pixel clock. TODO: change to Hz */
-	phy = p->pixelclock / 1000;
-
-	hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
-
-	/* config the PLL and PHY hdmi_set_pll_pwrfirst */
-	r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
-	if (r) {
-		DSSDBG("Failed to lock PLL\n");
-		goto err_pll_enable;
-	}
-
-	r = hdmi_phy_enable(&hdmi.phy, &hdmi.wp, &hdmi.cfg);
-	if (r) {
-		DSSDBG("Failed to start PHY\n");
-		goto err_phy_enable;
-	}
-
-	hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
-
-	/* bypass TV gamma table */
-	dispc_enable_gamma_table(0);
-
-	/* tv size */
-	dss_mgr_set_timings(mgr, p);
-
-	r = hdmi_wp_video_start(&hdmi.wp);
-	if (r)
-		goto err_vid_enable;
-
-	r = dss_mgr_enable(mgr);
-	if (r)
-		goto err_mgr_enable;
-
-	return 0;
-
-err_mgr_enable:
-	hdmi_wp_video_stop(&hdmi.wp);
-err_vid_enable:
-	hdmi_phy_disable(&hdmi.phy, &hdmi.wp);
-err_phy_enable:
-	hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
-err_pll_enable:
-	hdmi_power_off_core(dssdev);
-	return -EIO;
-}
-
-static void hdmi_power_off_full(struct omap_dss_device *dssdev)
-{
-	struct omap_overlay_manager *mgr = hdmi.output.manager;
-
-	dss_mgr_disable(mgr);
-
-	hdmi_wp_video_stop(&hdmi.wp);
-	hdmi_phy_disable(&hdmi.phy, &hdmi.wp);
-	hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
-
-	hdmi_power_off_core(dssdev);
-}
-
-static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
-					struct omap_video_timings *timings)
-{
-	struct omap_dss_device *out = &hdmi.output;
-
-	if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
-		return -EINVAL;
-
-	return 0;
-}
-
-static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	struct hdmi_cm cm;
-	const struct hdmi_config *t;
-
-	mutex_lock(&hdmi.lock);
-
-	cm = hdmi_get_code(timings);
-	hdmi.cfg.cm = cm;
-
-	t = hdmi_get_timings(cm.mode, cm.code);
-	if (t != NULL) {
-		hdmi.cfg = *t;
-
-		dispc_set_tv_pclk(t->timings.pixelclock);
-	} else {
-		hdmi.cfg.timings = *timings;
-		hdmi.cfg.cm.code = 0;
-		hdmi.cfg.cm.mode = HDMI_DVI;
-
-		dispc_set_tv_pclk(timings->pixelclock);
-	}
-
-	DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ?
-			"DVI" : "HDMI", hdmi.cfg.cm.code);
-
-	mutex_unlock(&hdmi.lock);
-}
-
-static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	const struct hdmi_config *cfg;
-	struct hdmi_cm cm = hdmi.cfg.cm;
-
-	cfg = hdmi_get_timings(cm.mode, cm.code);
-	if (cfg == NULL)
-		cfg = hdmi_default_timing();
-
-	memcpy(timings, &cfg->timings, sizeof(cfg->timings));
-}
-
-static void hdmi_dump_regs(struct seq_file *s)
-{
-	mutex_lock(&hdmi.lock);
-
-	if (hdmi_runtime_get()) {
-		mutex_unlock(&hdmi.lock);
-		return;
-	}
-
-	hdmi_wp_dump(&hdmi.wp, s);
-	hdmi_pll_dump(&hdmi.pll, s);
-	hdmi_phy_dump(&hdmi.phy, s);
-	hdmi4_core_dump(&hdmi.core, s);
-
-	hdmi_runtime_put();
-	mutex_unlock(&hdmi.lock);
-}
-
-static int read_edid(u8 *buf, int len)
-{
-	int r;
-
-	mutex_lock(&hdmi.lock);
-
-	r = hdmi_runtime_get();
-	BUG_ON(r);
-
-	r = hdmi4_read_edid(&hdmi.core,  buf, len);
-
-	hdmi_runtime_put();
-	mutex_unlock(&hdmi.lock);
-
-	return r;
-}
-
-static int hdmi_display_enable(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_device *out = &hdmi.output;
-	int r = 0;
-
-	DSSDBG("ENTER hdmi_display_enable\n");
-
-	mutex_lock(&hdmi.lock);
-
-	if (out == NULL || out->manager == NULL) {
-		DSSERR("failed to enable display: no output/manager\n");
-		r = -ENODEV;
-		goto err0;
-	}
-
-	r = hdmi_power_on_full(dssdev);
-	if (r) {
-		DSSERR("failed to power on device\n");
-		goto err0;
-	}
-
-	mutex_unlock(&hdmi.lock);
-	return 0;
-
-err0:
-	mutex_unlock(&hdmi.lock);
-	return r;
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
-	DSSDBG("Enter hdmi_display_disable\n");
-
-	mutex_lock(&hdmi.lock);
-
-	hdmi_power_off_full(dssdev);
-
-	mutex_unlock(&hdmi.lock);
-}
-
-static int hdmi_core_enable(struct omap_dss_device *dssdev)
-{
-	int r = 0;
-
-	DSSDBG("ENTER omapdss_hdmi_core_enable\n");
-
-	mutex_lock(&hdmi.lock);
-
-	r = hdmi_power_on_core(dssdev);
-	if (r) {
-		DSSERR("failed to power on device\n");
-		goto err0;
-	}
-
-	mutex_unlock(&hdmi.lock);
-	return 0;
-
-err0:
-	mutex_unlock(&hdmi.lock);
-	return r;
-}
-
-static void hdmi_core_disable(struct omap_dss_device *dssdev)
-{
-	DSSDBG("Enter omapdss_hdmi_core_disable\n");
-
-	mutex_lock(&hdmi.lock);
-
-	hdmi_power_off_core(dssdev);
-
-	mutex_unlock(&hdmi.lock);
-}
-
-static int hdmi_get_clocks(struct platform_device *pdev)
-{
-	struct clk *clk;
-
-	clk = devm_clk_get(&pdev->dev, "sys_clk");
-	if (IS_ERR(clk)) {
-		DSSERR("can't get sys_clk\n");
-		return PTR_ERR(clk);
-	}
-
-	hdmi.sys_clk = clk;
-
-	return 0;
-}
-
-static int hdmi_connect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct omap_overlay_manager *mgr;
-	int r;
-
-	r = hdmi_init_regulator();
-	if (r)
-		return r;
-
-	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
-	if (!mgr)
-		return -ENODEV;
-
-	r = dss_mgr_connect(mgr, dssdev);
-	if (r)
-		return r;
-
-	r = omapdss_output_set_device(dssdev, dst);
-	if (r) {
-		DSSERR("failed to connect output to new device: %s\n",
-				dst->name);
-		dss_mgr_disconnect(mgr, dssdev);
-		return r;
-	}
-
-	return 0;
-}
-
-static void hdmi_disconnect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	WARN_ON(dst != dssdev->dst);
-
-	if (dst != dssdev->dst)
-		return;
-
-	omapdss_output_unset_device(dssdev);
-
-	if (dssdev->manager)
-		dss_mgr_disconnect(dssdev->manager, dssdev);
-}
-
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
-		u8 *edid, int len)
-{
-	bool need_enable;
-	int r;
-
-	need_enable = hdmi.core_enabled == false;
-
-	if (need_enable) {
-		r = hdmi_core_enable(dssdev);
-		if (r)
-			return r;
-	}
-
-	r = read_edid(edid, len);
-
-	if (need_enable)
-		hdmi_core_disable(dssdev);
-
-	return r;
-}
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-static int hdmi_audio_enable(struct omap_dss_device *dssdev)
-{
-	int r;
-
-	mutex_lock(&hdmi.lock);
-
-	if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
-		r = -EPERM;
-		goto err;
-	}
-
-	r = hdmi_wp_audio_enable(&hdmi.wp, true);
-	if (r)
-		goto err;
-
-	mutex_unlock(&hdmi.lock);
-	return 0;
-
-err:
-	mutex_unlock(&hdmi.lock);
-	return r;
-}
-
-static void hdmi_audio_disable(struct omap_dss_device *dssdev)
-{
-	hdmi_wp_audio_enable(&hdmi.wp, false);
-}
-
-static int hdmi_audio_start(struct omap_dss_device *dssdev)
-{
-	return hdmi4_audio_start(&hdmi.core, &hdmi.wp);
-}
-
-static void hdmi_audio_stop(struct omap_dss_device *dssdev)
-{
-	hdmi4_audio_stop(&hdmi.core, &hdmi.wp);
-}
-
-static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
-{
-	bool r;
-
-	mutex_lock(&hdmi.lock);
-
-	r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
-
-	mutex_unlock(&hdmi.lock);
-	return r;
-}
-
-static int hdmi_audio_config(struct omap_dss_device *dssdev,
-		struct omap_dss_audio *audio)
-{
-	int r;
-	u32 pclk = hdmi.cfg.timings.pixelclock;
-
-	mutex_lock(&hdmi.lock);
-
-	if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
-		r = -EPERM;
-		goto err;
-	}
-
-	r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
-	if (r)
-		goto err;
-
-	mutex_unlock(&hdmi.lock);
-	return 0;
-
-err:
-	mutex_unlock(&hdmi.lock);
-	return r;
-}
-#else
-static int hdmi_audio_enable(struct omap_dss_device *dssdev)
-{
-	return -EPERM;
-}
-
-static void hdmi_audio_disable(struct omap_dss_device *dssdev)
-{
-}
-
-static int hdmi_audio_start(struct omap_dss_device *dssdev)
-{
-	return -EPERM;
-}
-
-static void hdmi_audio_stop(struct omap_dss_device *dssdev)
-{
-}
-
-static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
-{
-	return false;
-}
-
-static int hdmi_audio_config(struct omap_dss_device *dssdev,
-		struct omap_dss_audio *audio)
-{
-	return -EPERM;
-}
-#endif
-
-static const struct omapdss_hdmi_ops hdmi_ops = {
-	.connect		= hdmi_connect,
-	.disconnect		= hdmi_disconnect,
-
-	.enable			= hdmi_display_enable,
-	.disable		= hdmi_display_disable,
-
-	.check_timings		= hdmi_display_check_timing,
-	.set_timings		= hdmi_display_set_timing,
-	.get_timings		= hdmi_display_get_timings,
-
-	.read_edid		= hdmi_read_edid,
-
-	.audio_enable		= hdmi_audio_enable,
-	.audio_disable		= hdmi_audio_disable,
-	.audio_start		= hdmi_audio_start,
-	.audio_stop		= hdmi_audio_stop,
-	.audio_supported	= hdmi_audio_supported,
-	.audio_config		= hdmi_audio_config,
-};
-
-static void hdmi_init_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &hdmi.output;
-
-	out->dev = &pdev->dev;
-	out->id = OMAP_DSS_OUTPUT_HDMI;
-	out->output_type = OMAP_DISPLAY_TYPE_HDMI;
-	out->name = "hdmi.0";
-	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-	out->ops.hdmi = &hdmi_ops;
-	out->owner = THIS_MODULE;
-
-	omapdss_register_output(out);
-}
-
-static void __exit hdmi_uninit_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &hdmi.output;
-
-	omapdss_unregister_output(out);
-}
-
-/* HDMI HW IP initialisation */
-static int omapdss_hdmihw_probe(struct platform_device *pdev)
-{
-	int r;
-
-	hdmi.pdev = pdev;
-
-	mutex_init(&hdmi.lock);
-
-	r = hdmi_wp_init(pdev, &hdmi.wp);
-	if (r)
-		return r;
-
-	r = hdmi_pll_init(pdev, &hdmi.pll);
-	if (r)
-		return r;
-
-	r = hdmi_phy_init(pdev, &hdmi.phy);
-	if (r)
-		return r;
-
-	r = hdmi4_core_init(pdev, &hdmi.core);
-	if (r)
-		return r;
-
-	r = hdmi_get_clocks(pdev);
-	if (r) {
-		DSSERR("can't get clocks\n");
-		return r;
-	}
-
-	pm_runtime_enable(&pdev->dev);
-
-	hdmi_init_output(pdev);
-
-	dss_debugfs_create_file("hdmi", hdmi_dump_regs);
-
-	return 0;
-}
-
-static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
-{
-	hdmi_uninit_output(pdev);
-
-	pm_runtime_disable(&pdev->dev);
-
-	return 0;
-}
-
-static int hdmi_runtime_suspend(struct device *dev)
-{
-	clk_disable_unprepare(hdmi.sys_clk);
-
-	dispc_runtime_put();
-
-	return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
-	int r;
-
-	r = dispc_runtime_get();
-	if (r < 0)
-		return r;
-
-	clk_prepare_enable(hdmi.sys_clk);
-
-	return 0;
-}
-
-static const struct dev_pm_ops hdmi_pm_ops = {
-	.runtime_suspend = hdmi_runtime_suspend,
-	.runtime_resume = hdmi_runtime_resume,
-};
-
-static const struct of_device_id hdmi_of_match[] = {
-	{ .compatible = "ti,omap4-hdmi", },
-	{},
-};
-
-static struct platform_driver omapdss_hdmihw_driver = {
-	.probe		= omapdss_hdmihw_probe,
-	.remove         = __exit_p(omapdss_hdmihw_remove),
-	.driver         = {
-		.name   = "omapdss_hdmi",
-		.owner  = THIS_MODULE,
-		.pm	= &hdmi_pm_ops,
-		.of_match_table = hdmi_of_match,
-	},
-};
-
-int __init hdmi4_init_platform_driver(void)
-{
-	return platform_driver_register(&omapdss_hdmihw_driver);
-}
-
-void __exit hdmi4_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omapdss_hdmihw_driver);
-}
diff --git a/drivers/video/omap2/dss/hdmi4_core.c b/drivers/video/omap2/dss/hdmi4_core.c
deleted file mode 100644
index 2eb04dcf807c..000000000000
--- a/drivers/video/omap2/dss/hdmi4_core.c
+++ /dev/null
@@ -1,1036 +0,0 @@
-/*
- * ti_hdmi_4xxx_ip.c
- *
- * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
- * Authors: Yong Zhi
- *	Mythri pk <mythripk@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "HDMICORE"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/seq_file.h>
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-#include <sound/asound.h>
-#include <sound/asoundef.h>
-#endif
-
-#include "hdmi4_core.h"
-#include "dss_features.h"
-
-#define HDMI_CORE_AV		0x500
-
-static inline void __iomem *hdmi_av_base(struct hdmi_core_data *core)
-{
-	return core->base + HDMI_CORE_AV;
-}
-
-static int hdmi_core_ddc_init(struct hdmi_core_data *core)
-{
-	void __iomem *base = core->base;
-
-	/* Turn on CLK for DDC */
-	REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0);
-
-	/* IN_PROG */
-	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
-		/* Abort transaction */
-		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0);
-		/* IN_PROG */
-		if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
-					4, 4, 0) != 0) {
-			DSSERR("Timeout aborting DDC transaction\n");
-			return -ETIMEDOUT;
-		}
-	}
-
-	/* Clk SCL Devices */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0);
-
-	/* HDMI_CORE_DDC_STATUS_IN_PROG */
-	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
-				4, 4, 0) != 0) {
-		DSSERR("Timeout starting SCL clock\n");
-		return -ETIMEDOUT;
-	}
-
-	/* Clear FIFO */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0);
-
-	/* HDMI_CORE_DDC_STATUS_IN_PROG */
-	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
-				4, 4, 0) != 0) {
-		DSSERR("Timeout clearing DDC fifo\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
-		u8 *pedid, int ext)
-{
-	void __iomem *base = core->base;
-	u32 i;
-	char checksum;
-	u32 offset = 0;
-
-	/* HDMI_CORE_DDC_STATUS_IN_PROG */
-	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
-				4, 4, 0) != 0) {
-		DSSERR("Timeout waiting DDC to be ready\n");
-		return -ETIMEDOUT;
-	}
-
-	if (ext % 2 != 0)
-		offset = 0x80;
-
-	/* Load Segment Address Register */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
-
-	/* Load Slave Address Register */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
-
-	/* Load Offset Address Register */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
-
-	/* Load Byte Count */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
-	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
-
-	/* Set DDC_CMD */
-	if (ext)
-		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
-	else
-		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
-
-	/* HDMI_CORE_DDC_STATUS_BUS_LOW */
-	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
-		DSSERR("I2C Bus Low?\n");
-		return -EIO;
-	}
-	/* HDMI_CORE_DDC_STATUS_NO_ACK */
-	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
-		DSSERR("I2C No Ack\n");
-		return -EIO;
-	}
-
-	for (i = 0; i < 0x80; ++i) {
-		int t;
-
-		/* IN_PROG */
-		if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
-			DSSERR("operation stopped when reading edid\n");
-			return -EIO;
-		}
-
-		t = 0;
-		/* FIFO_EMPTY */
-		while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
-			if (t++ > 10000) {
-				DSSERR("timeout reading edid\n");
-				return -ETIMEDOUT;
-			}
-			udelay(1);
-		}
-
-		pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
-	}
-
-	checksum = 0;
-	for (i = 0; i < 0x80; ++i)
-		checksum += pedid[i];
-
-	if (checksum != 0) {
-		DSSERR("E-EDID checksum failed!!\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len)
-{
-	int r, l;
-
-	if (len < 128)
-		return -EINVAL;
-
-	r = hdmi_core_ddc_init(core);
-	if (r)
-		return r;
-
-	r = hdmi_core_ddc_edid(core, edid, 0);
-	if (r)
-		return r;
-
-	l = 128;
-
-	if (len >= 128 * 2 && edid[0x7e] > 0) {
-		r = hdmi_core_ddc_edid(core, edid + 0x80, 1);
-		if (r)
-			return r;
-		l += 128;
-	}
-
-	return l;
-}
-
-static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
-			struct hdmi_core_infoframe_avi *avi_cfg,
-			struct hdmi_core_packet_enable_repeat *repeat_cfg)
-{
-	DSSDBG("Enter hdmi_core_init\n");
-
-	/* video core */
-	video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
-	video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
-	video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
-	video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
-	video_cfg->hdmi_dvi = HDMI_DVI;
-	video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
-
-	/* info frame */
-	avi_cfg->db1_format = 0;
-	avi_cfg->db1_active_info = 0;
-	avi_cfg->db1_bar_info_dv = 0;
-	avi_cfg->db1_scan_info = 0;
-	avi_cfg->db2_colorimetry = 0;
-	avi_cfg->db2_aspect_ratio = 0;
-	avi_cfg->db2_active_fmt_ar = 0;
-	avi_cfg->db3_itc = 0;
-	avi_cfg->db3_ec = 0;
-	avi_cfg->db3_q_range = 0;
-	avi_cfg->db3_nup_scaling = 0;
-	avi_cfg->db4_videocode = 0;
-	avi_cfg->db5_pixel_repeat = 0;
-	avi_cfg->db6_7_line_eoftop = 0;
-	avi_cfg->db8_9_line_sofbottom = 0;
-	avi_cfg->db10_11_pixel_eofleft = 0;
-	avi_cfg->db12_13_pixel_sofright = 0;
-
-	/* packet enable and repeat */
-	repeat_cfg->audio_pkt = 0;
-	repeat_cfg->audio_pkt_repeat = 0;
-	repeat_cfg->avi_infoframe = 0;
-	repeat_cfg->avi_infoframe_repeat = 0;
-	repeat_cfg->gen_cntrl_pkt = 0;
-	repeat_cfg->gen_cntrl_pkt_repeat = 0;
-	repeat_cfg->generic_pkt = 0;
-	repeat_cfg->generic_pkt_repeat = 0;
-}
-
-static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
-{
-	DSSDBG("Enter hdmi_core_powerdown_disable\n");
-	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
-}
-
-static void hdmi_core_swreset_release(struct hdmi_core_data *core)
-{
-	DSSDBG("Enter hdmi_core_swreset_release\n");
-	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x0, 0, 0);
-}
-
-static void hdmi_core_swreset_assert(struct hdmi_core_data *core)
-{
-	DSSDBG("Enter hdmi_core_swreset_assert\n");
-	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x1, 0, 0);
-}
-
-/* HDMI_CORE_VIDEO_CONFIG */
-static void hdmi_core_video_config(struct hdmi_core_data *core,
-				struct hdmi_core_video_config *cfg)
-{
-	u32 r = 0;
-	void __iomem *core_sys_base = core->base;
-	void __iomem *core_av_base = hdmi_av_base(core);
-
-	/* sys_ctrl1 default configuration not tunable */
-	r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1);
-	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
-	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
-	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS, 2, 2);
-	r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE, 1, 1);
-	hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1, r);
-
-	REG_FLD_MOD(core_sys_base,
-			HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
-
-	/* Vid_Mode */
-	r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE);
-
-	/* dither truncation configuration */
-	if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
-		r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
-		r = FLD_MOD(r, 1, 5, 5);
-	} else {
-		r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
-		r = FLD_MOD(r, 0, 5, 5);
-	}
-	hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r);
-
-	/* HDMI_Ctrl */
-	r = hdmi_read_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL);
-	r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
-	r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
-	r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
-	hdmi_write_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL, r);
-
-	/* TMDS_CTRL */
-	REG_FLD_MOD(core_sys_base,
-			HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
-}
-
-static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core)
-{
-	u32 val;
-	char sum = 0, checksum = 0;
-	void __iomem *av_base = hdmi_av_base(core);
-	struct hdmi_core_infoframe_avi info_avi = core->avi_cfg;
-
-	sum += 0x82 + 0x002 + 0x00D;
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D);
-
-	val = (info_avi.db1_format << 5) |
-		(info_avi.db1_active_info << 4) |
-		(info_avi.db1_bar_info_dv << 2) |
-		(info_avi.db1_scan_info);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val);
-	sum += val;
-
-	val = (info_avi.db2_colorimetry << 6) |
-		(info_avi.db2_aspect_ratio << 4) |
-		(info_avi.db2_active_fmt_ar);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val);
-	sum += val;
-
-	val = (info_avi.db3_itc << 7) |
-		(info_avi.db3_ec << 4) |
-		(info_avi.db3_q_range << 2) |
-		(info_avi.db3_nup_scaling);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
-	sum += val;
-
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
-					info_avi.db4_videocode);
-	sum += info_avi.db4_videocode;
-
-	val = info_avi.db5_pixel_repeat;
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
-	sum += val;
-
-	val = info_avi.db6_7_line_eoftop & 0x00FF;
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
-	sum += val;
-
-	val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
-	sum += val;
-
-	val = info_avi.db8_9_line_sofbottom & 0x00FF;
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
-	sum += val;
-
-	val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
-	sum += val;
-
-	val = info_avi.db10_11_pixel_eofleft & 0x00FF;
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
-	sum += val;
-
-	val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
-	sum += val;
-
-	val = info_avi.db12_13_pixel_sofright & 0x00FF;
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
-	sum += val;
-
-	val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
-	sum += val;
-
-	checksum = 0x100 - sum;
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
-}
-
-static void hdmi_core_av_packet_config(struct hdmi_core_data *core,
-		struct hdmi_core_packet_enable_repeat repeat_cfg)
-{
-	/* enable/repeat the infoframe */
-	hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL1,
-		(repeat_cfg.audio_pkt << 5) |
-		(repeat_cfg.audio_pkt_repeat << 4) |
-		(repeat_cfg.avi_infoframe << 1) |
-		(repeat_cfg.avi_infoframe_repeat));
-
-	/* enable/repeat the packet */
-	hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL2,
-		(repeat_cfg.gen_cntrl_pkt << 3) |
-		(repeat_cfg.gen_cntrl_pkt_repeat << 2) |
-		(repeat_cfg.generic_pkt << 1) |
-		(repeat_cfg.generic_pkt_repeat));
-}
-
-void hdmi4_configure(struct hdmi_core_data *core,
-	struct hdmi_wp_data *wp, struct hdmi_config *cfg)
-{
-	/* HDMI */
-	struct omap_video_timings video_timing;
-	struct hdmi_video_format video_format;
-	/* HDMI core */
-	struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg;
-	struct hdmi_core_video_config v_core_cfg;
-	struct hdmi_core_packet_enable_repeat repeat_cfg;
-
-	hdmi_core_init(&v_core_cfg, avi_cfg, &repeat_cfg);
-
-	hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
-
-	hdmi_wp_video_config_timing(wp, &video_timing);
-
-	/* video config */
-	video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
-
-	hdmi_wp_video_config_format(wp, &video_format);
-
-	hdmi_wp_video_config_interface(wp, &video_timing);
-
-	/*
-	 * configure core video part
-	 * set software reset in the core
-	 */
-	hdmi_core_swreset_assert(core);
-
-	/* power down off */
-	hdmi_core_powerdown_disable(core);
-
-	v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
-	v_core_cfg.hdmi_dvi = cfg->cm.mode;
-
-	hdmi_core_video_config(core, &v_core_cfg);
-
-	/* release software reset in the core */
-	hdmi_core_swreset_release(core);
-
-	/*
-	 * configure packet
-	 * info frame video see doc CEA861-D page 65
-	 */
-	avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
-	avi_cfg->db1_active_info =
-			HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
-	avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
-	avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
-	avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
-	avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
-	avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
-	avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
-	avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
-	avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
-	avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
-	avi_cfg->db4_videocode = cfg->cm.code;
-	avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
-	avi_cfg->db6_7_line_eoftop = 0;
-	avi_cfg->db8_9_line_sofbottom = 0;
-	avi_cfg->db10_11_pixel_eofleft = 0;
-	avi_cfg->db12_13_pixel_sofright = 0;
-
-	hdmi_core_aux_infoframe_avi_config(core);
-
-	/* enable/repeat the infoframe */
-	repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
-	repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
-	/* wakeup */
-	repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
-	repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
-	hdmi_core_av_packet_config(core, repeat_cfg);
-}
-
-void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s)
-{
-	int i;
-
-#define CORE_REG(i, name) name(i)
-#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
-		hdmi_read_reg(core->base, r))
-#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
-		hdmi_read_reg(hdmi_av_base(core), r))
-#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
-		(i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
-		hdmi_read_reg(hdmi_av_base(core), CORE_REG(i, r)))
-
-	DUMPCORE(HDMI_CORE_SYS_VND_IDL);
-	DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
-	DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
-	DUMPCORE(HDMI_CORE_SYS_DEV_REV);
-	DUMPCORE(HDMI_CORE_SYS_SRST);
-	DUMPCORE(HDMI_CORE_SYS_SYS_CTRL1);
-	DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
-	DUMPCORE(HDMI_CORE_SYS_SYS_CTRL3);
-	DUMPCORE(HDMI_CORE_SYS_DE_DLY);
-	DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
-	DUMPCORE(HDMI_CORE_SYS_DE_TOP);
-	DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
-	DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
-	DUMPCORE(HDMI_CORE_SYS_DE_LINL);
-	DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
-	DUMPCORE(HDMI_CORE_SYS_HRES_L);
-	DUMPCORE(HDMI_CORE_SYS_HRES_H);
-	DUMPCORE(HDMI_CORE_SYS_VRES_L);
-	DUMPCORE(HDMI_CORE_SYS_VRES_H);
-	DUMPCORE(HDMI_CORE_SYS_IADJUST);
-	DUMPCORE(HDMI_CORE_SYS_POLDETECT);
-	DUMPCORE(HDMI_CORE_SYS_HWIDTH1);
-	DUMPCORE(HDMI_CORE_SYS_HWIDTH2);
-	DUMPCORE(HDMI_CORE_SYS_VWIDTH);
-	DUMPCORE(HDMI_CORE_SYS_VID_CTRL);
-	DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
-	DUMPCORE(HDMI_CORE_SYS_VID_MODE);
-	DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
-	DUMPCORE(HDMI_CORE_SYS_VID_BLANK3);
-	DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
-	DUMPCORE(HDMI_CORE_SYS_DC_HEADER);
-	DUMPCORE(HDMI_CORE_SYS_VID_DITHER);
-	DUMPCORE(HDMI_CORE_SYS_RGB2XVYCC_CT);
-	DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_LOW);
-	DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_UP);
-	DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_LOW);
-	DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_UP);
-	DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_LOW);
-	DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_UP);
-	DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_LOW);
-	DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_UP);
-	DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
-	DUMPCORE(HDMI_CORE_SYS_INTR1);
-	DUMPCORE(HDMI_CORE_SYS_INTR2);
-	DUMPCORE(HDMI_CORE_SYS_INTR3);
-	DUMPCORE(HDMI_CORE_SYS_INTR4);
-	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK1);
-	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK2);
-	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK3);
-	DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK4);
-	DUMPCORE(HDMI_CORE_SYS_INTR_CTRL);
-	DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
-
-	DUMPCORE(HDMI_CORE_DDC_ADDR);
-	DUMPCORE(HDMI_CORE_DDC_SEGM);
-	DUMPCORE(HDMI_CORE_DDC_OFFSET);
-	DUMPCORE(HDMI_CORE_DDC_COUNT1);
-	DUMPCORE(HDMI_CORE_DDC_COUNT2);
-	DUMPCORE(HDMI_CORE_DDC_STATUS);
-	DUMPCORE(HDMI_CORE_DDC_CMD);
-	DUMPCORE(HDMI_CORE_DDC_DATA);
-
-	DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL);
-	DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL);
-	DUMPCOREAV(HDMI_CORE_AV_N_SVAL1);
-	DUMPCOREAV(HDMI_CORE_AV_N_SVAL2);
-	DUMPCOREAV(HDMI_CORE_AV_N_SVAL3);
-	DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1);
-	DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2);
-	DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3);
-	DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1);
-	DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2);
-	DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3);
-	DUMPCOREAV(HDMI_CORE_AV_AUD_MODE);
-	DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL);
-	DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS);
-	DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S);
-	DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5);
-	DUMPCOREAV(HDMI_CORE_AV_ASRC);
-	DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN);
-	DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL);
-	DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT);
-	DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
-	DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
-	DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
-	DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL);
-	DUMPCOREAV(HDMI_CORE_AV_DPD);
-	DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1);
-	DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2);
-	DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE);
-	DUMPCOREAV(HDMI_CORE_AV_AVI_VERS);
-	DUMPCOREAV(HDMI_CORE_AV_AVI_LEN);
-	DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM);
-
-	for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
-		DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE);
-
-	DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE);
-	DUMPCOREAV(HDMI_CORE_AV_SPD_VERS);
-	DUMPCOREAV(HDMI_CORE_AV_SPD_LEN);
-	DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM);
-
-	for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
-		DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE);
-
-	DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE);
-	DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS);
-	DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN);
-	DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM);
-
-	for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
-		DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE);
-
-	DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE);
-	DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS);
-	DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN);
-	DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM);
-
-	for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
-		DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE);
-
-	for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
-		DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE);
-
-	DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1);
-
-	for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
-		DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE);
-
-	DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
-}
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-static void hdmi_core_audio_config(struct hdmi_core_data *core,
-					struct hdmi_core_audio_config *cfg)
-{
-	u32 r;
-	void __iomem *av_base = hdmi_av_base(core);
-
-	/*
-	 * Parameters for generation of Audio Clock Recovery packets
-	 */
-	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
-	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
-	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
-
-	if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
-		REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
-		REG_FLD_MOD(av_base,
-				HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
-		REG_FLD_MOD(av_base,
-				HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
-	} else {
-		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
-				cfg->aud_par_busclk, 7, 0);
-		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
-				(cfg->aud_par_busclk >> 8), 7, 0);
-		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
-				(cfg->aud_par_busclk >> 16), 7, 0);
-	}
-
-	/* Set ACR clock divisor */
-	REG_FLD_MOD(av_base,
-			HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
-
-	r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
-	/*
-	 * Use TMDS clock for ACR packets. For devices that use
-	 * the MCLK, this is the first part of the MCLK initialization.
-	 */
-	r = FLD_MOD(r, 0, 2, 2);
-
-	r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
-	r = FLD_MOD(r, cfg->cts_mode, 0, 0);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
-
-	/* For devices using MCLK, this completes its initialization. */
-	if (cfg->use_mclk)
-		REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2);
-
-	/* Override of SPDIF sample frequency with value in I2S_CHST4 */
-	REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
-						cfg->fs_override, 1, 1);
-
-	/*
-	 * Set IEC-60958-3 channel status word. It is passed to the IP
-	 * just as it is received. The user of the driver is responsible
-	 * for its contents.
-	 */
-	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0,
-		       cfg->iec60958_cfg->status[0]);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1,
-		       cfg->iec60958_cfg->status[1]);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2,
-		       cfg->iec60958_cfg->status[2]);
-	/* yes, this is correct: status[3] goes to CHST4 register */
-	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4,
-		       cfg->iec60958_cfg->status[3]);
-	/* yes, this is correct: status[4] goes to CHST5 register */
-	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5,
-		       cfg->iec60958_cfg->status[4]);
-
-	/* set I2S parameters */
-	r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
-	r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
-	r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
-	r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
-	r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
-	r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
-
-	REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
-			cfg->i2s_cfg.in_length_bits, 3, 0);
-
-	/* Audio channels and mode parameters */
-	REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
-	r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE);
-	r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
-	r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
-	r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
-	r = FLD_MOD(r, cfg->en_spdif, 1, 1);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
-
-	/* Audio channel mappings */
-	/* TODO: Make channel mapping dynamic. For now, map channels
-	 * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
-	 * HDMI speaker order is different. See CEA-861 Section 6.6.2.
-	 */
-	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78);
-	REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5);
-}
-
-static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core,
-		struct snd_cea_861_aud_if *info_aud)
-{
-	u8 sum = 0, checksum = 0;
-	void __iomem *av_base = hdmi_av_base(core);
-
-	/*
-	 * Set audio info frame type, version and length as
-	 * described in HDMI 1.4a Section 8.2.2 specification.
-	 * Checksum calculation is defined in Section 5.3.5.
-	 */
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
-	sum += 0x84 + 0x001 + 0x00a;
-
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0),
-		       info_aud->db1_ct_cc);
-	sum += info_aud->db1_ct_cc;
-
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1),
-		       info_aud->db2_sf_ss);
-	sum += info_aud->db2_sf_ss;
-
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
-	sum += info_aud->db3;
-
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
-	sum += info_aud->db4_ca;
-
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4),
-		       info_aud->db5_dminh_lsv);
-	sum += info_aud->db5_dminh_lsv;
-
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
-	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
-
-	checksum = 0x100 - sum;
-	hdmi_write_reg(av_base,
-					HDMI_CORE_AV_AUDIO_CHSUM, checksum);
-
-	/*
-	 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
-	 * is available.
-	 */
-}
-
-int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
-		struct omap_dss_audio *audio, u32 pclk)
-{
-	struct hdmi_audio_format audio_format;
-	struct hdmi_audio_dma audio_dma;
-	struct hdmi_core_audio_config acore;
-	int err, n, cts, channel_count;
-	unsigned int fs_nr;
-	bool word_length_16b = false;
-
-	if (!audio || !audio->iec || !audio->cea || !core)
-		return -EINVAL;
-
-	acore.iec60958_cfg = audio->iec;
-	/*
-	 * In the IEC-60958 status word, check if the audio sample word length
-	 * is 16-bit as several optimizations can be performed in such case.
-	 */
-	if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
-		if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
-			word_length_16b = true;
-
-	/* I2S configuration. See Phillips' specification */
-	if (word_length_16b)
-		acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
-	else
-		acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
-	/*
-	 * The I2S input word length is twice the lenght given in the IEC-60958
-	 * status word. If the word size is greater than
-	 * 20 bits, increment by one.
-	 */
-	acore.i2s_cfg.in_length_bits = audio->iec->status[4]
-		& IEC958_AES4_CON_WORDLEN;
-	if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
-		acore.i2s_cfg.in_length_bits++;
-	acore.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
-	acore.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
-	acore.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
-	acore.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
-
-	/* convert sample frequency to a number */
-	switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
-	case IEC958_AES3_CON_FS_32000:
-		fs_nr = 32000;
-		break;
-	case IEC958_AES3_CON_FS_44100:
-		fs_nr = 44100;
-		break;
-	case IEC958_AES3_CON_FS_48000:
-		fs_nr = 48000;
-		break;
-	case IEC958_AES3_CON_FS_88200:
-		fs_nr = 88200;
-		break;
-	case IEC958_AES3_CON_FS_96000:
-		fs_nr = 96000;
-		break;
-	case IEC958_AES3_CON_FS_176400:
-		fs_nr = 176400;
-		break;
-	case IEC958_AES3_CON_FS_192000:
-		fs_nr = 192000;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	err = hdmi_compute_acr(pclk, fs_nr, &n, &cts);
-
-	/* Audio clock regeneration settings */
-	acore.n = n;
-	acore.cts = cts;
-	if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
-		acore.aud_par_busclk = 0;
-		acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
-		acore.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
-	} else {
-		acore.aud_par_busclk = (((128 * 31) - 1) << 8);
-		acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
-		acore.use_mclk = true;
-	}
-
-	if (acore.use_mclk)
-		acore.mclk_mode = HDMI_AUDIO_MCLK_128FS;
-
-	/* Audio channels settings */
-	channel_count = (audio->cea->db1_ct_cc &
-			 CEA861_AUDIO_INFOFRAME_DB1CC) + 1;
-
-	switch (channel_count) {
-	case 2:
-		audio_format.active_chnnls_msk = 0x03;
-		break;
-	case 3:
-		audio_format.active_chnnls_msk = 0x07;
-		break;
-	case 4:
-		audio_format.active_chnnls_msk = 0x0f;
-		break;
-	case 5:
-		audio_format.active_chnnls_msk = 0x1f;
-		break;
-	case 6:
-		audio_format.active_chnnls_msk = 0x3f;
-		break;
-	case 7:
-		audio_format.active_chnnls_msk = 0x7f;
-		break;
-	case 8:
-		audio_format.active_chnnls_msk = 0xff;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * the HDMI IP needs to enable four stereo channels when transmitting
-	 * more than 2 audio channels
-	 */
-	if (channel_count == 2) {
-		audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
-		acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
-		acore.layout = HDMI_AUDIO_LAYOUT_2CH;
-	} else {
-		audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
-		acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
-				HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
-				HDMI_AUDIO_I2S_SD3_EN;
-		acore.layout = HDMI_AUDIO_LAYOUT_8CH;
-	}
-
-	acore.en_spdif = false;
-	/* use sample frequency from channel status word */
-	acore.fs_override = true;
-	/* enable ACR packets */
-	acore.en_acr_pkt = true;
-	/* disable direct streaming digital audio */
-	acore.en_dsd_audio = false;
-	/* use parallel audio interface */
-	acore.en_parallel_aud_input = true;
-
-	/* DMA settings */
-	if (word_length_16b)
-		audio_dma.transfer_size = 0x10;
-	else
-		audio_dma.transfer_size = 0x20;
-	audio_dma.block_size = 0xC0;
-	audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
-	audio_dma.fifo_threshold = 0x20; /* in number of samples */
-
-	/* audio FIFO format settings */
-	if (word_length_16b) {
-		audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
-		audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
-		audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
-	} else {
-		audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
-		audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
-		audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
-	}
-	audio_format.type = HDMI_AUDIO_TYPE_LPCM;
-	audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
-	/* disable start/stop signals of IEC 60958 blocks */
-	audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
-
-	/* configure DMA and audio FIFO format*/
-	hdmi_wp_audio_config_dma(wp, &audio_dma);
-	hdmi_wp_audio_config_format(wp, &audio_format);
-
-	/* configure the core*/
-	hdmi_core_audio_config(core, &acore);
-
-	/* configure CEA 861 audio infoframe*/
-	hdmi_core_audio_infoframe_cfg(core, audio->cea);
-
-	return 0;
-}
-
-int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
-{
-	REG_FLD_MOD(hdmi_av_base(core),
-		    HDMI_CORE_AV_AUD_MODE, true, 0, 0);
-
-	hdmi_wp_audio_core_req_enable(wp, true);
-
-	return 0;
-}
-
-void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
-{
-	REG_FLD_MOD(hdmi_av_base(core),
-		    HDMI_CORE_AV_AUD_MODE, false, 0, 0);
-
-	hdmi_wp_audio_core_req_enable(wp, false);
-}
-
-int hdmi4_audio_get_dma_port(u32 *offset, u32 *size)
-{
-	if (!offset || !size)
-		return -EINVAL;
-	*offset = HDMI_WP_AUDIO_DATA;
-	*size = 4;
-	return 0;
-}
-
-#endif
-
-#define CORE_OFFSET		0x400
-#define CORE_SIZE		0xc00
-
-int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
-{
-	struct resource *res;
-	struct resource temp_res;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
-	if (!res) {
-		DSSDBG("can't get CORE mem resource by name\n");
-		/*
-		 * if hwmod/DT doesn't have the memory resource information
-		 * split into HDMI sub blocks by name, we try again by getting
-		 * the platform's first resource. this code will be removed when
-		 * the driver can get the mem resources by name
-		 */
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!res) {
-			DSSERR("can't get CORE mem resource\n");
-			return -EINVAL;
-		}
-
-		temp_res.start = res->start + CORE_OFFSET;
-		temp_res.end = temp_res.start + CORE_SIZE - 1;
-		res = &temp_res;
-	}
-
-	core->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!core->base) {
-		DSSERR("can't ioremap CORE\n");
-		return -ENOMEM;
-	}
-
-	return 0;
-}
diff --git a/drivers/video/omap2/dss/hdmi4_core.h b/drivers/video/omap2/dss/hdmi4_core.h
deleted file mode 100644
index bb646896fa82..000000000000
--- a/drivers/video/omap2/dss/hdmi4_core.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * HDMI header definition for OMAP4 HDMI core IP
- *
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _HDMI4_CORE_H_
-#define _HDMI4_CORE_H_
-
-#include "hdmi.h"
-
-/* OMAP4 HDMI IP Core System */
-
-#define HDMI_CORE_SYS_VND_IDL			0x0
-#define HDMI_CORE_SYS_DEV_IDL			0x8
-#define HDMI_CORE_SYS_DEV_IDH			0xC
-#define HDMI_CORE_SYS_DEV_REV			0x10
-#define HDMI_CORE_SYS_SRST			0x14
-#define HDMI_CORE_SYS_SYS_CTRL1			0x20
-#define HDMI_CORE_SYS_SYS_STAT			0x24
-#define HDMI_CORE_SYS_SYS_CTRL3			0x28
-#define HDMI_CORE_SYS_DCTL			0x34
-#define HDMI_CORE_SYS_DE_DLY			0xC8
-#define HDMI_CORE_SYS_DE_CTRL			0xCC
-#define HDMI_CORE_SYS_DE_TOP			0xD0
-#define HDMI_CORE_SYS_DE_CNTL			0xD8
-#define HDMI_CORE_SYS_DE_CNTH			0xDC
-#define HDMI_CORE_SYS_DE_LINL			0xE0
-#define HDMI_CORE_SYS_DE_LINH_1			0xE4
-#define HDMI_CORE_SYS_HRES_L			0xE8
-#define HDMI_CORE_SYS_HRES_H			0xEC
-#define HDMI_CORE_SYS_VRES_L			0xF0
-#define HDMI_CORE_SYS_VRES_H			0xF4
-#define HDMI_CORE_SYS_IADJUST			0xF8
-#define HDMI_CORE_SYS_POLDETECT			0xFC
-#define HDMI_CORE_SYS_HWIDTH1			0x110
-#define HDMI_CORE_SYS_HWIDTH2			0x114
-#define HDMI_CORE_SYS_VWIDTH			0x11C
-#define HDMI_CORE_SYS_VID_CTRL			0x120
-#define HDMI_CORE_SYS_VID_ACEN			0x124
-#define HDMI_CORE_SYS_VID_MODE			0x128
-#define HDMI_CORE_SYS_VID_BLANK1		0x12C
-#define HDMI_CORE_SYS_VID_BLANK2		0x130
-#define HDMI_CORE_SYS_VID_BLANK3		0x134
-#define HDMI_CORE_SYS_DC_HEADER			0x138
-#define HDMI_CORE_SYS_VID_DITHER		0x13C
-#define HDMI_CORE_SYS_RGB2XVYCC_CT		0x140
-#define HDMI_CORE_SYS_R2Y_COEFF_LOW		0x144
-#define HDMI_CORE_SYS_R2Y_COEFF_UP		0x148
-#define HDMI_CORE_SYS_G2Y_COEFF_LOW		0x14C
-#define HDMI_CORE_SYS_G2Y_COEFF_UP		0x150
-#define HDMI_CORE_SYS_B2Y_COEFF_LOW		0x154
-#define HDMI_CORE_SYS_B2Y_COEFF_UP		0x158
-#define HDMI_CORE_SYS_R2CB_COEFF_LOW		0x15C
-#define HDMI_CORE_SYS_R2CB_COEFF_UP		0x160
-#define HDMI_CORE_SYS_G2CB_COEFF_LOW		0x164
-#define HDMI_CORE_SYS_G2CB_COEFF_UP		0x168
-#define HDMI_CORE_SYS_B2CB_COEFF_LOW		0x16C
-#define HDMI_CORE_SYS_B2CB_COEFF_UP		0x170
-#define HDMI_CORE_SYS_R2CR_COEFF_LOW		0x174
-#define HDMI_CORE_SYS_R2CR_COEFF_UP		0x178
-#define HDMI_CORE_SYS_G2CR_COEFF_LOW		0x17C
-#define HDMI_CORE_SYS_G2CR_COEFF_UP		0x180
-#define HDMI_CORE_SYS_B2CR_COEFF_LOW		0x184
-#define HDMI_CORE_SYS_B2CR_COEFF_UP		0x188
-#define HDMI_CORE_SYS_RGB_OFFSET_LOW		0x18C
-#define HDMI_CORE_SYS_RGB_OFFSET_UP		0x190
-#define HDMI_CORE_SYS_Y_OFFSET_LOW		0x194
-#define HDMI_CORE_SYS_Y_OFFSET_UP		0x198
-#define HDMI_CORE_SYS_CBCR_OFFSET_LOW		0x19C
-#define HDMI_CORE_SYS_CBCR_OFFSET_UP		0x1A0
-#define HDMI_CORE_SYS_INTR_STATE		0x1C0
-#define HDMI_CORE_SYS_INTR1			0x1C4
-#define HDMI_CORE_SYS_INTR2			0x1C8
-#define HDMI_CORE_SYS_INTR3			0x1CC
-#define HDMI_CORE_SYS_INTR4			0x1D0
-#define HDMI_CORE_SYS_INTR_UNMASK1		0x1D4
-#define HDMI_CORE_SYS_INTR_UNMASK2		0x1D8
-#define HDMI_CORE_SYS_INTR_UNMASK3		0x1DC
-#define HDMI_CORE_SYS_INTR_UNMASK4		0x1E0
-#define HDMI_CORE_SYS_INTR_CTRL			0x1E4
-#define HDMI_CORE_SYS_TMDS_CTRL			0x208
-
-/* value definitions for HDMI_CORE_SYS_SYS_CTRL1 fields */
-#define HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC	0x1
-#define HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC	0x1
-#define HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS	0x1
-#define HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE	0x1
-
-/* HDMI DDC E-DID */
-#define HDMI_CORE_DDC_ADDR			0x3B4
-#define HDMI_CORE_DDC_SEGM			0x3B8
-#define HDMI_CORE_DDC_OFFSET			0x3BC
-#define HDMI_CORE_DDC_COUNT1			0x3C0
-#define HDMI_CORE_DDC_COUNT2			0x3C4
-#define HDMI_CORE_DDC_STATUS			0x3C8
-#define HDMI_CORE_DDC_CMD			0x3CC
-#define HDMI_CORE_DDC_DATA			0x3D0
-
-/* HDMI IP Core Audio Video */
-
-#define HDMI_CORE_AV_ACR_CTRL			0x4
-#define HDMI_CORE_AV_FREQ_SVAL			0x8
-#define HDMI_CORE_AV_N_SVAL1			0xC
-#define HDMI_CORE_AV_N_SVAL2			0x10
-#define HDMI_CORE_AV_N_SVAL3			0x14
-#define HDMI_CORE_AV_CTS_SVAL1			0x18
-#define HDMI_CORE_AV_CTS_SVAL2			0x1C
-#define HDMI_CORE_AV_CTS_SVAL3			0x20
-#define HDMI_CORE_AV_CTS_HVAL1			0x24
-#define HDMI_CORE_AV_CTS_HVAL2			0x28
-#define HDMI_CORE_AV_CTS_HVAL3			0x2C
-#define HDMI_CORE_AV_AUD_MODE			0x50
-#define HDMI_CORE_AV_SPDIF_CTRL			0x54
-#define HDMI_CORE_AV_HW_SPDIF_FS		0x60
-#define HDMI_CORE_AV_SWAP_I2S			0x64
-#define HDMI_CORE_AV_SPDIF_ERTH			0x6C
-#define HDMI_CORE_AV_I2S_IN_MAP			0x70
-#define HDMI_CORE_AV_I2S_IN_CTRL		0x74
-#define HDMI_CORE_AV_I2S_CHST0			0x78
-#define HDMI_CORE_AV_I2S_CHST1			0x7C
-#define HDMI_CORE_AV_I2S_CHST2			0x80
-#define HDMI_CORE_AV_I2S_CHST4			0x84
-#define HDMI_CORE_AV_I2S_CHST5			0x88
-#define HDMI_CORE_AV_ASRC			0x8C
-#define HDMI_CORE_AV_I2S_IN_LEN			0x90
-#define HDMI_CORE_AV_HDMI_CTRL			0xBC
-#define HDMI_CORE_AV_AUDO_TXSTAT		0xC0
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1		0xCC
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2		0xD0
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3		0xD4
-#define HDMI_CORE_AV_TEST_TXCTRL		0xF0
-#define HDMI_CORE_AV_DPD			0xF4
-#define HDMI_CORE_AV_PB_CTRL1			0xF8
-#define HDMI_CORE_AV_PB_CTRL2			0xFC
-#define HDMI_CORE_AV_AVI_TYPE			0x100
-#define HDMI_CORE_AV_AVI_VERS			0x104
-#define HDMI_CORE_AV_AVI_LEN			0x108
-#define HDMI_CORE_AV_AVI_CHSUM			0x10C
-#define HDMI_CORE_AV_AVI_DBYTE(n)		(n * 4 + 0x110)
-#define HDMI_CORE_AV_SPD_TYPE			0x180
-#define HDMI_CORE_AV_SPD_VERS			0x184
-#define HDMI_CORE_AV_SPD_LEN			0x188
-#define HDMI_CORE_AV_SPD_CHSUM			0x18C
-#define HDMI_CORE_AV_SPD_DBYTE(n)		(n * 4 + 0x190)
-#define HDMI_CORE_AV_AUDIO_TYPE			0x200
-#define HDMI_CORE_AV_AUDIO_VERS			0x204
-#define HDMI_CORE_AV_AUDIO_LEN			0x208
-#define HDMI_CORE_AV_AUDIO_CHSUM		0x20C
-#define HDMI_CORE_AV_AUD_DBYTE(n)		(n * 4 + 0x210)
-#define HDMI_CORE_AV_MPEG_TYPE			0x280
-#define HDMI_CORE_AV_MPEG_VERS			0x284
-#define HDMI_CORE_AV_MPEG_LEN			0x288
-#define HDMI_CORE_AV_MPEG_CHSUM			0x28C
-#define HDMI_CORE_AV_MPEG_DBYTE(n)		(n * 4 + 0x290)
-#define HDMI_CORE_AV_GEN_DBYTE(n)		(n * 4 + 0x300)
-#define HDMI_CORE_AV_CP_BYTE1			0x37C
-#define HDMI_CORE_AV_GEN2_DBYTE(n)		(n * 4 + 0x380)
-#define HDMI_CORE_AV_CEC_ADDR_ID		0x3FC
-
-#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE		0x4
-#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE		0x4
-#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE		0x4
-#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE		0x4
-
-#define HDMI_CORE_AV_AVI_DBYTE_NELEMS		15
-#define HDMI_CORE_AV_SPD_DBYTE_NELEMS		27
-#define HDMI_CORE_AV_AUD_DBYTE_NELEMS		10
-#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS		27
-#define HDMI_CORE_AV_GEN_DBYTE_NELEMS		31
-#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS		31
-
-enum hdmi_core_inputbus_width {
-	HDMI_INPUT_8BIT = 0,
-	HDMI_INPUT_10BIT = 1,
-	HDMI_INPUT_12BIT = 2
-};
-
-enum hdmi_core_dither_trunc {
-	HDMI_OUTPUTTRUNCATION_8BIT = 0,
-	HDMI_OUTPUTTRUNCATION_10BIT = 1,
-	HDMI_OUTPUTTRUNCATION_12BIT = 2,
-	HDMI_OUTPUTDITHER_8BIT = 3,
-	HDMI_OUTPUTDITHER_10BIT = 4,
-	HDMI_OUTPUTDITHER_12BIT = 5
-};
-
-enum hdmi_core_deepcolor_ed {
-	HDMI_DEEPCOLORPACKECTDISABLE = 0,
-	HDMI_DEEPCOLORPACKECTENABLE = 1
-};
-
-enum hdmi_core_packet_mode {
-	HDMI_PACKETMODERESERVEDVALUE = 0,
-	HDMI_PACKETMODE24BITPERPIXEL = 4,
-	HDMI_PACKETMODE30BITPERPIXEL = 5,
-	HDMI_PACKETMODE36BITPERPIXEL = 6,
-	HDMI_PACKETMODE48BITPERPIXEL = 7
-};
-
-enum hdmi_core_tclkselclkmult {
-	HDMI_FPLL05IDCK = 0,
-	HDMI_FPLL10IDCK = 1,
-	HDMI_FPLL20IDCK = 2,
-	HDMI_FPLL40IDCK = 3
-};
-
-enum hdmi_core_packet_ctrl {
-	HDMI_PACKETENABLE = 1,
-	HDMI_PACKETDISABLE = 0,
-	HDMI_PACKETREPEATON = 1,
-	HDMI_PACKETREPEATOFF = 0
-};
-
-enum hdmi_audio_i2s_config {
-	HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
-	HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
-	HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
-	HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
-	HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
-	HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
-	HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
-	HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
-	HDMI_AUDIO_I2S_SD0_EN = 1,
-	HDMI_AUDIO_I2S_SD1_EN = 1 << 1,
-	HDMI_AUDIO_I2S_SD2_EN = 1 << 2,
-	HDMI_AUDIO_I2S_SD3_EN = 1 << 3,
-};
-
-struct hdmi_core_video_config {
-	enum hdmi_core_inputbus_width	ip_bus_width;
-	enum hdmi_core_dither_trunc	op_dither_truc;
-	enum hdmi_core_deepcolor_ed	deep_color_pkt;
-	enum hdmi_core_packet_mode	pkt_mode;
-	enum hdmi_core_hdmi_dvi		hdmi_dvi;
-	enum hdmi_core_tclkselclkmult	tclk_sel_clkmult;
-};
-
-struct hdmi_core_packet_enable_repeat {
-	u32	audio_pkt;
-	u32	audio_pkt_repeat;
-	u32	avi_infoframe;
-	u32	avi_infoframe_repeat;
-	u32	gen_cntrl_pkt;
-	u32	gen_cntrl_pkt_repeat;
-	u32	generic_pkt;
-	u32	generic_pkt_repeat;
-};
-
-int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len);
-void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
-		struct hdmi_config *cfg);
-void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s);
-int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
-void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
-int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
-		struct omap_dss_audio *audio, u32 pclk);
-int hdmi4_audio_get_dma_port(u32 *offset, u32 *size);
-#endif
-
-#endif
diff --git a/drivers/video/omap2/dss/hdmi_common.c b/drivers/video/omap2/dss/hdmi_common.c
deleted file mode 100644
index b11afac8e068..000000000000
--- a/drivers/video/omap2/dss/hdmi_common.c
+++ /dev/null
@@ -1,425 +0,0 @@
-
-/*
- * Logic for the below structure :
- * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
- * There is a correspondence between CEA/VESA timing and code, please
- * refer to section 6.3 in HDMI 1.3 specification for timing code.
- *
- * In the below structure, cea_vesa_timings corresponds to all OMAP4
- * supported CEA and VESA timing values.code_cea corresponds to the CEA
- * code, It is used to get the timing from cea_vesa_timing array.Similarly
- * with code_vesa. Code_index is used for back mapping, that is once EDID
- * is read from the TV, EDID is parsed to find the timing values and then
- * map it to corresponding CEA or VESA index.
- */
-
-#define DSS_SUBSYS_NAME "HDMI"
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <video/omapdss.h>
-
-#include "hdmi.h"
-
-static const struct hdmi_config cea_timings[] = {
-	{
-		{ 640, 480, 25200000, 96, 16, 48, 2, 10, 33,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 1, HDMI_HDMI },
-	},
-	{
-		{ 720, 480, 27027000, 62, 16, 60, 6, 9, 30,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 2, HDMI_HDMI },
-	},
-	{
-		{ 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 4, HDMI_HDMI },
-	},
-	{
-		{ 1920, 540, 74250000, 44, 88, 148, 5, 2, 15,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			true, },
-		{ 5, HDMI_HDMI },
-	},
-	{
-		{ 1440, 240, 27027000, 124, 38, 114, 3, 4, 15,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			true, },
-		{ 6, HDMI_HDMI },
-	},
-	{
-		{ 1920, 1080, 148500000, 44, 88, 148, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 16, HDMI_HDMI },
-	},
-	{
-		{ 720, 576, 27000000, 64, 12, 68, 5, 5, 39,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 17, HDMI_HDMI },
-	},
-	{
-		{ 1280, 720, 74250000, 40, 440, 220, 5, 5, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 19, HDMI_HDMI },
-	},
-	{
-		{ 1920, 540, 74250000, 44, 528, 148, 5, 2, 15,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			true, },
-		{ 20, HDMI_HDMI },
-	},
-	{
-		{ 1440, 288, 27000000, 126, 24, 138, 3, 2, 19,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			true, },
-		{ 21, HDMI_HDMI },
-	},
-	{
-		{ 1440, 576, 54000000, 128, 24, 136, 5, 5, 39,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 29, HDMI_HDMI },
-	},
-	{
-		{ 1920, 1080, 148500000, 44, 528, 148, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 31, HDMI_HDMI },
-	},
-	{
-		{ 1920, 1080, 74250000, 44, 638, 148, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 32, HDMI_HDMI },
-	},
-	{
-		{ 2880, 480, 108108000, 248, 64, 240, 6, 9, 30,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 35, HDMI_HDMI },
-	},
-	{
-		{ 2880, 576, 108000000, 256, 48, 272, 5, 5, 39,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 37, HDMI_HDMI },
-	},
-};
-
-static const struct hdmi_config vesa_timings[] = {
-/* VESA From Here */
-	{
-		{ 640, 480, 25175000, 96, 16, 48, 2, 11, 31,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 4, HDMI_DVI },
-	},
-	{
-		{ 800, 600, 40000000, 128, 40, 88, 4, 1, 23,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 9, HDMI_DVI },
-	},
-	{
-		{ 848, 480, 33750000, 112, 16, 112, 8, 6, 23,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0xE, HDMI_DVI },
-	},
-	{
-		{ 1280, 768, 79500000, 128, 64, 192, 7, 3, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x17, HDMI_DVI },
-	},
-	{
-		{ 1280, 800, 83500000, 128, 72, 200, 6, 3, 22,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x1C, HDMI_DVI },
-	},
-	{
-		{ 1360, 768, 85500000, 112, 64, 256, 6, 3, 18,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x27, HDMI_DVI },
-	},
-	{
-		{ 1280, 960, 108000000, 112, 96, 312, 3, 1, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x20, HDMI_DVI },
-	},
-	{
-		{ 1280, 1024, 108000000, 112, 48, 248, 3, 1, 38,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x23, HDMI_DVI },
-	},
-	{
-		{ 1024, 768, 65000000, 136, 24, 160, 6, 3, 29,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x10, HDMI_DVI },
-	},
-	{
-		{ 1400, 1050, 121750000, 144, 88, 232, 4, 3, 32,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x2A, HDMI_DVI },
-	},
-	{
-		{ 1440, 900, 106500000, 152, 80, 232, 6, 3, 25,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x2F, HDMI_DVI },
-	},
-	{
-		{ 1680, 1050, 146250000, 176 , 104, 280, 6, 3, 30,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
-			false, },
-		{ 0x3A, HDMI_DVI },
-	},
-	{
-		{ 1366, 768, 85500000, 143, 70, 213, 3, 3, 24,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x51, HDMI_DVI },
-	},
-	{
-		{ 1920, 1080, 148500000, 44, 148, 80, 5, 4, 36,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x52, HDMI_DVI },
-	},
-	{
-		{ 1280, 768, 68250000, 32, 48, 80, 7, 3, 12,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x16, HDMI_DVI },
-	},
-	{
-		{ 1400, 1050, 101000000, 32, 48, 80, 4, 3, 23,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x29, HDMI_DVI },
-	},
-	{
-		{ 1680, 1050, 119000000, 32, 48, 80, 6, 3, 21,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x39, HDMI_DVI },
-	},
-	{
-		{ 1280, 800, 79500000, 32, 48, 80, 6, 3, 14,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x1B, HDMI_DVI },
-	},
-	{
-		{ 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
-			OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x55, HDMI_DVI },
-	},
-	{
-		{ 1920, 1200, 154000000, 32, 48, 80, 6, 3, 26,
-			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
-			false, },
-		{ 0x44, HDMI_DVI },
-	},
-};
-
-const struct hdmi_config *hdmi_default_timing(void)
-{
-	return &vesa_timings[0];
-}
-
-static const struct hdmi_config *hdmi_find_timing(int code,
-			const struct hdmi_config *timings_arr, int len)
-{
-	int i;
-
-	for (i = 0; i < len; i++) {
-		if (timings_arr[i].cm.code == code)
-			return &timings_arr[i];
-	}
-
-	return NULL;
-}
-
-const struct hdmi_config *hdmi_get_timings(int mode, int code)
-{
-	const struct hdmi_config *arr;
-	int len;
-
-	if (mode == HDMI_DVI) {
-		arr = vesa_timings;
-		len = ARRAY_SIZE(vesa_timings);
-	} else {
-		arr = cea_timings;
-		len = ARRAY_SIZE(cea_timings);
-	}
-
-	return hdmi_find_timing(code, arr, len);
-}
-
-static bool hdmi_timings_compare(struct omap_video_timings *timing1,
-			const struct omap_video_timings *timing2)
-{
-	int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
-
-	if ((DIV_ROUND_CLOSEST(timing2->pixelclock, 1000000) ==
-			DIV_ROUND_CLOSEST(timing1->pixelclock, 1000000)) &&
-		(timing2->x_res == timing1->x_res) &&
-		(timing2->y_res == timing1->y_res)) {
-
-		timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
-		timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
-		timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
-		timing1_vsync = timing1->vfp + timing1->vsw + timing1->vbp;
-
-		DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
-			"timing2_hsync = %d timing2_vsync = %d\n",
-			timing1_hsync, timing1_vsync,
-			timing2_hsync, timing2_vsync);
-
-		if ((timing1_hsync == timing2_hsync) &&
-			(timing1_vsync == timing2_vsync)) {
-			return true;
-		}
-	}
-	return false;
-}
-
-struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
-{
-	int i;
-	struct hdmi_cm cm = {-1};
-	DSSDBG("hdmi_get_code\n");
-
-	for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
-		if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
-			cm = cea_timings[i].cm;
-			goto end;
-		}
-	}
-	for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
-		if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
-			cm = vesa_timings[i].cm;
-			goto end;
-		}
-	}
-
-end:
-	return cm;
-}
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
-{
-	u32 deep_color;
-	bool deep_color_correct = false;
-
-	if (n == NULL || cts == NULL)
-		return -EINVAL;
-
-	/* TODO: When implemented, query deep color mode here. */
-	deep_color = 100;
-
-	/*
-	 * When using deep color, the default N value (as in the HDMI
-	 * specification) yields to an non-integer CTS. Hence, we
-	 * modify it while keeping the restrictions described in
-	 * section 7.2.1 of the HDMI 1.4a specification.
-	 */
-	switch (sample_freq) {
-	case 32000:
-	case 48000:
-	case 96000:
-	case 192000:
-		if (deep_color == 125)
-			if (pclk == 27027 || pclk == 74250)
-				deep_color_correct = true;
-		if (deep_color == 150)
-			if (pclk == 27027)
-				deep_color_correct = true;
-		break;
-	case 44100:
-	case 88200:
-	case 176400:
-		if (deep_color == 125)
-			if (pclk == 27027)
-				deep_color_correct = true;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (deep_color_correct) {
-		switch (sample_freq) {
-		case 32000:
-			*n = 8192;
-			break;
-		case 44100:
-			*n = 12544;
-			break;
-		case 48000:
-			*n = 8192;
-			break;
-		case 88200:
-			*n = 25088;
-			break;
-		case 96000:
-			*n = 16384;
-			break;
-		case 176400:
-			*n = 50176;
-			break;
-		case 192000:
-			*n = 32768;
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
-		switch (sample_freq) {
-		case 32000:
-			*n = 4096;
-			break;
-		case 44100:
-			*n = 6272;
-			break;
-		case 48000:
-			*n = 6144;
-			break;
-		case 88200:
-			*n = 12544;
-			break;
-		case 96000:
-			*n = 12288;
-			break;
-		case 176400:
-			*n = 25088;
-			break;
-		case 192000:
-			*n = 24576;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-	/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
-	*cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
-
-	return 0;
-}
-#endif
diff --git a/drivers/video/omap2/dss/hdmi_phy.c b/drivers/video/omap2/dss/hdmi_phy.c
deleted file mode 100644
index dd376ce8da01..000000000000
--- a/drivers/video/omap2/dss/hdmi_phy.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * HDMI PHY
- *
- * Copyright (C) 2013 Texas Instruments Incorporated
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "hdmi.h"
-
-void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
-{
-#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
-		hdmi_read_reg(phy->base, r))
-
-	DUMPPHY(HDMI_TXPHY_TX_CTRL);
-	DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
-	DUMPPHY(HDMI_TXPHY_POWER_CTRL);
-	DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
-}
-
-static irqreturn_t hdmi_irq_handler(int irq, void *data)
-{
-	struct hdmi_wp_data *wp = data;
-	u32 irqstatus;
-
-	irqstatus = hdmi_wp_get_irqstatus(wp);
-	hdmi_wp_set_irqstatus(wp, irqstatus);
-
-	if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
-			irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
-		/*
-		 * If we get both connect and disconnect interrupts at the same
-		 * time, turn off the PHY, clear interrupts, and restart, which
-		 * raises connect interrupt if a cable is connected, or nothing
-		 * if cable is not connected.
-		 */
-		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
-
-		hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
-				HDMI_IRQ_LINK_DISCONNECT);
-
-		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
-	} else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
-		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
-	} else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
-		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
-	}
-
-	return IRQ_HANDLED;
-}
-
-int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
-			struct hdmi_config *cfg)
-{
-	u16 r = 0;
-	u32 irqstatus;
-
-	hdmi_wp_clear_irqenable(wp, 0xffffffff);
-
-	irqstatus = hdmi_wp_get_irqstatus(wp);
-	hdmi_wp_set_irqstatus(wp, irqstatus);
-
-	r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
-	if (r)
-		return r;
-
-	/*
-	 * Read address 0 in order to get the SCP reset done completed
-	 * Dummy access performed to make sure reset is done
-	 */
-	hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL);
-
-	/*
-	 * Write to phy address 0 to configure the clock
-	 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
-	 */
-	REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
-
-	/* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
-	hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
-
-	/* Setup max LDO voltage */
-	REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
-
-	/* Write to phy address 3 to change the polarity control */
-	REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
-
-	r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler,
-				IRQF_ONESHOT, "OMAP HDMI", wp);
-	if (r) {
-		DSSERR("HDMI IRQ request failed\n");
-		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
-		return r;
-	}
-
-	hdmi_wp_set_irqenable(wp,
-		HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
-
-	return 0;
-}
-
-void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp)
-{
-	free_irq(phy->irq, wp);
-
-	hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
-}
-
-#define PHY_OFFSET	0x300
-#define PHY_SIZE	0x100
-
-int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy)
-{
-	struct resource *res;
-	struct resource temp_res;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
-	if (!res) {
-		DSSDBG("can't get PHY mem resource by name\n");
-		/*
-		 * if hwmod/DT doesn't have the memory resource information
-		 * split into HDMI sub blocks by name, we try again by getting
-		 * the platform's first resource. this code will be removed when
-		 * the driver can get the mem resources by name
-		 */
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!res) {
-			DSSERR("can't get PHY mem resource\n");
-			return -EINVAL;
-		}
-
-		temp_res.start = res->start + PHY_OFFSET;
-		temp_res.end = temp_res.start + PHY_SIZE - 1;
-		res = &temp_res;
-	}
-
-	phy->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!phy->base) {
-		DSSERR("can't ioremap TX PHY\n");
-		return -ENOMEM;
-	}
-
-	phy->irq = platform_get_irq(pdev, 0);
-	if (phy->irq < 0) {
-		DSSERR("platform_get_irq failed\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
diff --git a/drivers/video/omap2/dss/hdmi_pll.c b/drivers/video/omap2/dss/hdmi_pll.c
deleted file mode 100644
index 5fc71215c303..000000000000
--- a/drivers/video/omap2/dss/hdmi_pll.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * HDMI PLL
- *
- * Copyright (C) 2013 Texas Instruments Incorporated
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#define DSS_SUBSYS_NAME "HDMIPLL"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "hdmi.h"
-
-#define HDMI_DEFAULT_REGN 16
-#define HDMI_DEFAULT_REGM2 1
-
-void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
-{
-#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
-		hdmi_read_reg(pll->base, r))
-
-	DUMPPLL(PLLCTRL_PLL_CONTROL);
-	DUMPPLL(PLLCTRL_PLL_STATUS);
-	DUMPPLL(PLLCTRL_PLL_GO);
-	DUMPPLL(PLLCTRL_CFG1);
-	DUMPPLL(PLLCTRL_CFG2);
-	DUMPPLL(PLLCTRL_CFG3);
-	DUMPPLL(PLLCTRL_SSC_CFG1);
-	DUMPPLL(PLLCTRL_SSC_CFG2);
-	DUMPPLL(PLLCTRL_CFG4);
-}
-
-void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy)
-{
-	struct hdmi_pll_info *pi = &pll->info;
-	unsigned long refclk;
-	u32 mf;
-
-	/* use our funky units */
-	clkin /= 10000;
-
-	/*
-	 * Input clock is predivided by N + 1
-	 * out put of which is reference clk
-	 */
-
-	pi->regn = HDMI_DEFAULT_REGN;
-
-	refclk = clkin / pi->regn;
-
-	pi->regm2 = HDMI_DEFAULT_REGM2;
-
-	/*
-	 * multiplier is pixel_clk/ref_clk
-	 * Multiplying by 100 to avoid fractional part removal
-	 */
-	pi->regm = phy * pi->regm2 / refclk;
-
-	/*
-	 * fractional multiplier is remainder of the difference between
-	 * multiplier and actual phy(required pixel clock thus should be
-	 * multiplied by 2^18(262144) divided by the reference clock
-	 */
-	mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
-	pi->regmf = pi->regm2 * mf / refclk;
-
-	/*
-	 * Dcofreq should be set to 1 if required pixel clock
-	 * is greater than 1000MHz
-	 */
-	pi->dcofreq = phy > 1000 * 100;
-	pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
-
-	/* Set the reference clock to sysclk reference */
-	pi->refsel = HDMI_REFSEL_SYSCLK;
-
-	DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
-	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
-}
-
-
-static int hdmi_pll_config(struct hdmi_pll_data *pll)
-{
-	u32 r;
-	struct hdmi_pll_info *fmt = &pll->info;
-
-	/* PLL start always use manual mode */
-	REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
-
-	r = hdmi_read_reg(pll->base, PLLCTRL_CFG1);
-	r = FLD_MOD(r, fmt->regm, 20, 9);	/* CFG1_PLL_REGM */
-	r = FLD_MOD(r, fmt->regn - 1, 8, 1);	/* CFG1_PLL_REGN */
-	hdmi_write_reg(pll->base, PLLCTRL_CFG1, r);
-
-	r = hdmi_read_reg(pll->base, PLLCTRL_CFG2);
-
-	r = FLD_MOD(r, 0x0, 12, 12);	/* PLL_HIGHFREQ divide by 2 */
-	r = FLD_MOD(r, 0x1, 13, 13);	/* PLL_REFEN */
-	r = FLD_MOD(r, 0x0, 14, 14);	/* PHY_CLKINEN de-assert during locking */
-	r = FLD_MOD(r, fmt->refsel, 22, 21);	/* REFSEL */
-
-	if (fmt->dcofreq) {
-		/* divider programming for frequency beyond 1000Mhz */
-		REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
-		r = FLD_MOD(r, 0x4, 3, 1);	/* 1000MHz and 2000MHz */
-	} else {
-		r = FLD_MOD(r, 0x2, 3, 1);	/* 500MHz and 1000MHz */
-	}
-
-	hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
-
-	r = hdmi_read_reg(pll->base, PLLCTRL_CFG4);
-	r = FLD_MOD(r, fmt->regm2, 24, 18);
-	r = FLD_MOD(r, fmt->regmf, 17, 0);
-	hdmi_write_reg(pll->base, PLLCTRL_CFG4, r);
-
-	/* go now */
-	REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0);
-
-	/* wait for bit change */
-	if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
-			0, 0, 1) != 1) {
-		DSSERR("PLL GO bit not set\n");
-		return -ETIMEDOUT;
-	}
-
-	/* Wait till the lock bit is set in PLL status */
-	if (hdmi_wait_for_bit_change(pll->base,
-			PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
-		DSSERR("cannot lock PLL\n");
-		DSSERR("CFG1 0x%x\n",
-			hdmi_read_reg(pll->base, PLLCTRL_CFG1));
-		DSSERR("CFG2 0x%x\n",
-			hdmi_read_reg(pll->base, PLLCTRL_CFG2));
-		DSSERR("CFG4 0x%x\n",
-			hdmi_read_reg(pll->base, PLLCTRL_CFG4));
-		return -ETIMEDOUT;
-	}
-
-	DSSDBG("PLL locked!\n");
-
-	return 0;
-}
-
-static int hdmi_pll_reset(struct hdmi_pll_data *pll)
-{
-	/* SYSRESET  controlled by power FSM */
-	REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
-
-	/* READ 0x0 reset is in progress */
-	if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
-			!= 1) {
-		DSSERR("Failed to sysreset PLL\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
-{
-	u16 r = 0;
-
-	r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
-	if (r)
-		return r;
-
-	r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
-	if (r)
-		return r;
-
-	r = hdmi_pll_reset(pll);
-	if (r)
-		return r;
-
-	r = hdmi_pll_config(pll);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
-{
-	hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
-}
-
-#define PLL_OFFSET	0x200
-#define PLL_SIZE	0x100
-
-int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
-{
-	struct resource *res;
-	struct resource temp_res;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
-	if (!res) {
-		DSSDBG("can't get PLL mem resource by name\n");
-		/*
-		 * if hwmod/DT doesn't have the memory resource information
-		 * split into HDMI sub blocks by name, we try again by getting
-		 * the platform's first resource. this code will be removed when
-		 * the driver can get the mem resources by name
-		 */
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!res) {
-			DSSERR("can't get PLL mem resource\n");
-			return -EINVAL;
-		}
-
-		temp_res.start = res->start + PLL_OFFSET;
-		temp_res.end = temp_res.start + PLL_SIZE - 1;
-		res = &temp_res;
-	}
-
-	pll->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!pll->base) {
-		DSSERR("can't ioremap PLLCTRL\n");
-		return -ENOMEM;
-	}
-
-	return 0;
-}
diff --git a/drivers/video/omap2/dss/hdmi_wp.c b/drivers/video/omap2/dss/hdmi_wp.c
deleted file mode 100644
index f5f4ccf50d90..000000000000
--- a/drivers/video/omap2/dss/hdmi_wp.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * HDMI wrapper
- *
- * Copyright (C) 2013 Texas Instruments Incorporated
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#define DSS_SUBSYS_NAME "HDMIWP"
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "hdmi.h"
-
-void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s)
-{
-#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r))
-
-	DUMPREG(HDMI_WP_REVISION);
-	DUMPREG(HDMI_WP_SYSCONFIG);
-	DUMPREG(HDMI_WP_IRQSTATUS_RAW);
-	DUMPREG(HDMI_WP_IRQSTATUS);
-	DUMPREG(HDMI_WP_IRQENABLE_SET);
-	DUMPREG(HDMI_WP_IRQENABLE_CLR);
-	DUMPREG(HDMI_WP_IRQWAKEEN);
-	DUMPREG(HDMI_WP_PWR_CTRL);
-	DUMPREG(HDMI_WP_DEBOUNCE);
-	DUMPREG(HDMI_WP_VIDEO_CFG);
-	DUMPREG(HDMI_WP_VIDEO_SIZE);
-	DUMPREG(HDMI_WP_VIDEO_TIMING_H);
-	DUMPREG(HDMI_WP_VIDEO_TIMING_V);
-	DUMPREG(HDMI_WP_CLK);
-	DUMPREG(HDMI_WP_AUDIO_CFG);
-	DUMPREG(HDMI_WP_AUDIO_CFG2);
-	DUMPREG(HDMI_WP_AUDIO_CTRL);
-	DUMPREG(HDMI_WP_AUDIO_DATA);
-}
-
-u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp)
-{
-	return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
-}
-
-void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus)
-{
-	hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus);
-	/* flush posted write */
-	hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
-}
-
-void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask)
-{
-	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask);
-}
-
-void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask)
-{
-	hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask);
-}
-
-/* PHY_PWR_CMD */
-int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val)
-{
-	/* Return if already the state */
-	if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val)
-		return 0;
-
-	/* Command for power control of HDMI PHY */
-	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6);
-
-	/* Status of the power control of HDMI PHY */
-	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val)
-			!= val) {
-		DSSERR("Failed to set PHY power mode to %d\n", val);
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-/* PLL_PWR_CMD */
-int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val)
-{
-	/* Command for power control of HDMI PLL */
-	REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2);
-
-	/* wait till PHY_PWR_STATUS is set */
-	if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val)
-			!= val) {
-		DSSERR("Failed to set PLL_PWR_STATUS\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-int hdmi_wp_video_start(struct hdmi_wp_data *wp)
-{
-	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31);
-
-	return 0;
-}
-
-void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
-{
-	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);
-}
-
-void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
-		struct hdmi_video_format *video_fmt)
-{
-	u32 l = 0;
-
-	REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode,
-		10, 8);
-
-	l |= FLD_VAL(video_fmt->y_res, 31, 16);
-	l |= FLD_VAL(video_fmt->x_res, 15, 0);
-	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l);
-}
-
-void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings)
-{
-	u32 r;
-	bool vsync_pol, hsync_pol;
-	DSSDBG("Enter hdmi_wp_video_config_interface\n");
-
-	vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
-	hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
-
-	r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);
-	r = FLD_MOD(r, vsync_pol, 7, 7);
-	r = FLD_MOD(r, hsync_pol, 6, 6);
-	r = FLD_MOD(r, timings->interlace, 3, 3);
-	r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
-	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);
-}
-
-void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings)
-{
-	u32 timing_h = 0;
-	u32 timing_v = 0;
-
-	DSSDBG("Enter hdmi_wp_video_config_timing\n");
-
-	timing_h |= FLD_VAL(timings->hbp, 31, 20);
-	timing_h |= FLD_VAL(timings->hfp, 19, 8);
-	timing_h |= FLD_VAL(timings->hsw, 7, 0);
-	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);
-
-	timing_v |= FLD_VAL(timings->vbp, 31, 20);
-	timing_v |= FLD_VAL(timings->vfp, 19, 8);
-	timing_v |= FLD_VAL(timings->vsw, 7, 0);
-	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);
-}
-
-void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
-		struct omap_video_timings *timings, struct hdmi_config *param)
-{
-	DSSDBG("Enter hdmi_wp_video_init_format\n");
-
-	video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
-	video_fmt->y_res = param->timings.y_res;
-	video_fmt->x_res = param->timings.x_res;
-	if (param->timings.interlace)
-		video_fmt->y_res /= 2;
-
-	timings->hbp = param->timings.hbp;
-	timings->hfp = param->timings.hfp;
-	timings->hsw = param->timings.hsw;
-	timings->vbp = param->timings.vbp;
-	timings->vfp = param->timings.vfp;
-	timings->vsw = param->timings.vsw;
-	timings->vsync_level = param->timings.vsync_level;
-	timings->hsync_level = param->timings.hsync_level;
-	timings->interlace = param->timings.interlace;
-}
-
-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
-void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
-		struct hdmi_audio_format *aud_fmt)
-{
-	u32 r;
-
-	DSSDBG("Enter hdmi_wp_audio_config_format\n");
-
-	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
-	r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
-	r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
-	r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
-	r = FLD_MOD(r, aud_fmt->type, 4, 4);
-	r = FLD_MOD(r, aud_fmt->justification, 3, 3);
-	r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
-	r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
-	r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
-	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r);
-}
-
-void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
-		struct hdmi_audio_dma *aud_dma)
-{
-	u32 r;
-
-	DSSDBG("Enter hdmi_wp_audio_config_dma\n");
-
-	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2);
-	r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
-	r = FLD_MOD(r, aud_dma->block_size, 7, 0);
-	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r);
-
-	r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL);
-	r = FLD_MOD(r, aud_dma->mode, 9, 9);
-	r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
-	hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r);
-}
-
-int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable)
-{
-	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31);
-
-	return 0;
-}
-
-int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
-{
-	REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30);
-
-	return 0;
-}
-#endif
-
-#define WP_SIZE	0x200
-
-int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
-{
-	struct resource *res;
-	struct resource temp_res;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp");
-	if (!res) {
-		DSSDBG("can't get WP mem resource by name\n");
-		/*
-		 * if hwmod/DT doesn't have the memory resource information
-		 * split into HDMI sub blocks by name, we try again by getting
-		 * the platform's first resource. this code will be removed when
-		 * the driver can get the mem resources by name
-		 */
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!res) {
-			DSSERR("can't get WP mem resource\n");
-			return -EINVAL;
-		}
-
-		temp_res.start = res->start;
-		temp_res.end = temp_res.start + WP_SIZE - 1;
-		res = &temp_res;
-	}
-
-	wp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!wp->base) {
-		DSSERR("can't ioremap HDMI WP\n");
-		return -ENOMEM;
-	}
-
-	return 0;
-}
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c
deleted file mode 100644
index 37b59fe28dc8..000000000000
--- a/drivers/video/omap2/dss/manager-sysfs.c
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "MANAGER"
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/jiffies.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
-}
-
-static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
-{
-	struct omap_dss_device *dssdev = mgr->get_device(mgr);
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
-			dssdev->name : "<none>");
-}
-
-static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
-		const char *buf, size_t size)
-{
-	int r = 0;
-	size_t len = size;
-	struct omap_dss_device *dssdev = NULL;
-	struct omap_dss_device *old_dssdev;
-
-	int match(struct omap_dss_device *dssdev, void *data)
-	{
-		const char *str = data;
-		return sysfs_streq(dssdev->name, str);
-	}
-
-	if (buf[size-1] == '\n')
-		--len;
-
-	if (len > 0)
-		dssdev = omap_dss_find_device((void *)buf, match);
-
-	if (len > 0 && dssdev == NULL)
-		return -EINVAL;
-
-	if (dssdev) {
-		DSSDBG("display %s found\n", dssdev->name);
-
-		if (omapdss_device_is_connected(dssdev)) {
-			DSSERR("new display is already connected\n");
-			r = -EINVAL;
-			goto put_device;
-		}
-
-		if (omapdss_device_is_enabled(dssdev)) {
-			DSSERR("new display is not disabled\n");
-			r = -EINVAL;
-			goto put_device;
-		}
-	}
-
-	old_dssdev = mgr->get_device(mgr);
-	if (old_dssdev) {
-		if (omapdss_device_is_enabled(old_dssdev)) {
-			DSSERR("old display is not disabled\n");
-			r = -EINVAL;
-			goto put_device;
-		}
-
-		old_dssdev->driver->disconnect(old_dssdev);
-	}
-
-	if (dssdev) {
-		r = dssdev->driver->connect(dssdev);
-		if (r) {
-			DSSERR("failed to connect new device\n");
-			goto put_device;
-		}
-
-		old_dssdev = mgr->get_device(mgr);
-		if (old_dssdev != dssdev) {
-			DSSERR("failed to connect device to this manager\n");
-			dssdev->driver->disconnect(dssdev);
-			goto put_device;
-		}
-
-		r = mgr->apply(mgr);
-		if (r) {
-			DSSERR("failed to apply dispc config\n");
-			goto put_device;
-		}
-	}
-
-put_device:
-	if (dssdev)
-		omap_dss_put_device(dssdev);
-
-	return r ? r : size;
-}
-
-static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
-					  char *buf)
-{
-	struct omap_overlay_manager_info info;
-
-	mgr->get_manager_info(mgr, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
-}
-
-static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
-					   const char *buf, size_t size)
-{
-	struct omap_overlay_manager_info info;
-	u32 color;
-	int r;
-
-	r = kstrtouint(buf, 0, &color);
-	if (r)
-		return r;
-
-	mgr->get_manager_info(mgr, &info);
-
-	info.default_color = color;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static const char *trans_key_type_str[] = {
-	"gfx-destination",
-	"video-source",
-};
-
-static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
-					   char *buf)
-{
-	enum omap_dss_trans_key_type key_type;
-	struct omap_overlay_manager_info info;
-
-	mgr->get_manager_info(mgr, &info);
-
-	key_type = info.trans_key_type;
-	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
-}
-
-static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
-					    const char *buf, size_t size)
-{
-	enum omap_dss_trans_key_type key_type;
-	struct omap_overlay_manager_info info;
-	int r;
-
-	for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
-			key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
-		if (sysfs_streq(buf, trans_key_type_str[key_type]))
-			break;
-	}
-
-	if (key_type == ARRAY_SIZE(trans_key_type_str))
-		return -EINVAL;
-
-	mgr->get_manager_info(mgr, &info);
-
-	info.trans_key_type = key_type;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
-					    char *buf)
-{
-	struct omap_overlay_manager_info info;
-
-	mgr->get_manager_info(mgr, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
-}
-
-static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
-					     const char *buf, size_t size)
-{
-	struct omap_overlay_manager_info info;
-	u32 key_value;
-	int r;
-
-	r = kstrtouint(buf, 0, &key_value);
-	if (r)
-		return r;
-
-	mgr->get_manager_info(mgr, &info);
-
-	info.trans_key = key_value;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
-					      char *buf)
-{
-	struct omap_overlay_manager_info info;
-
-	mgr->get_manager_info(mgr, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
-}
-
-static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
-					       const char *buf, size_t size)
-{
-	struct omap_overlay_manager_info info;
-	bool enable;
-	int r;
-
-	r = strtobool(buf, &enable);
-	if (r)
-		return r;
-
-	mgr->get_manager_info(mgr, &info);
-
-	info.trans_enabled = enable;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t manager_alpha_blending_enabled_show(
-		struct omap_overlay_manager *mgr, char *buf)
-{
-	struct omap_overlay_manager_info info;
-
-	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
-		return -ENODEV;
-
-	mgr->get_manager_info(mgr, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-		info.partial_alpha_enabled);
-}
-
-static ssize_t manager_alpha_blending_enabled_store(
-		struct omap_overlay_manager *mgr,
-		const char *buf, size_t size)
-{
-	struct omap_overlay_manager_info info;
-	bool enable;
-	int r;
-
-	if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
-		return -ENODEV;
-
-	r = strtobool(buf, &enable);
-	if (r)
-		return r;
-
-	mgr->get_manager_info(mgr, &info);
-
-	info.partial_alpha_enabled = enable;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
-		char *buf)
-{
-	struct omap_overlay_manager_info info;
-
-	mgr->get_manager_info(mgr, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
-}
-
-static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
-		const char *buf, size_t size)
-{
-	struct omap_overlay_manager_info info;
-	int r;
-	bool enable;
-
-	if (!dss_has_feature(FEAT_CPR))
-		return -ENODEV;
-
-	r = strtobool(buf, &enable);
-	if (r)
-		return r;
-
-	mgr->get_manager_info(mgr, &info);
-
-	if (info.cpr_enable == enable)
-		return size;
-
-	info.cpr_enable = enable;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
-		char *buf)
-{
-	struct omap_overlay_manager_info info;
-
-	mgr->get_manager_info(mgr, &info);
-
-	return snprintf(buf, PAGE_SIZE,
-			"%d %d %d %d %d %d %d %d %d\n",
-			info.cpr_coefs.rr,
-			info.cpr_coefs.rg,
-			info.cpr_coefs.rb,
-			info.cpr_coefs.gr,
-			info.cpr_coefs.gg,
-			info.cpr_coefs.gb,
-			info.cpr_coefs.br,
-			info.cpr_coefs.bg,
-			info.cpr_coefs.bb);
-}
-
-static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
-		const char *buf, size_t size)
-{
-	struct omap_overlay_manager_info info;
-	struct omap_dss_cpr_coefs coefs;
-	int r, i;
-	s16 *arr;
-
-	if (!dss_has_feature(FEAT_CPR))
-		return -ENODEV;
-
-	if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
-				&coefs.rr, &coefs.rg, &coefs.rb,
-				&coefs.gr, &coefs.gg, &coefs.gb,
-				&coefs.br, &coefs.bg, &coefs.bb) != 9)
-		return -EINVAL;
-
-	arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
-		coefs.gr, coefs.gg, coefs.gb,
-		coefs.br, coefs.bg, coefs.bb };
-
-	for (i = 0; i < 9; ++i) {
-		if (arr[i] < -512 || arr[i] > 511)
-			return -EINVAL;
-	}
-
-	mgr->get_manager_info(mgr, &info);
-
-	info.cpr_coefs = coefs;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-	if (r)
-		return r;
-
-	return size;
-}
-
-struct manager_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct omap_overlay_manager *, char *);
-	ssize_t	(*store)(struct omap_overlay_manager *, const char *, size_t);
-};
-
-#define MANAGER_ATTR(_name, _mode, _show, _store) \
-	struct manager_attribute manager_attr_##_name = \
-	__ATTR(_name, _mode, _show, _store)
-
-static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
-static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
-		manager_display_show, manager_display_store);
-static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
-		manager_default_color_show, manager_default_color_store);
-static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
-		manager_trans_key_type_show, manager_trans_key_type_store);
-static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
-		manager_trans_key_value_show, manager_trans_key_value_store);
-static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
-		manager_trans_key_enabled_show,
-		manager_trans_key_enabled_store);
-static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
-		manager_alpha_blending_enabled_show,
-		manager_alpha_blending_enabled_store);
-static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
-		manager_cpr_enable_show,
-		manager_cpr_enable_store);
-static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
-		manager_cpr_coef_show,
-		manager_cpr_coef_store);
-
-
-static struct attribute *manager_sysfs_attrs[] = {
-	&manager_attr_name.attr,
-	&manager_attr_display.attr,
-	&manager_attr_default_color.attr,
-	&manager_attr_trans_key_type.attr,
-	&manager_attr_trans_key_value.attr,
-	&manager_attr_trans_key_enabled.attr,
-	&manager_attr_alpha_blending_enabled.attr,
-	&manager_attr_cpr_enable.attr,
-	&manager_attr_cpr_coef.attr,
-	NULL
-};
-
-static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
-		char *buf)
-{
-	struct omap_overlay_manager *manager;
-	struct manager_attribute *manager_attr;
-
-	manager = container_of(kobj, struct omap_overlay_manager, kobj);
-	manager_attr = container_of(attr, struct manager_attribute, attr);
-
-	if (!manager_attr->show)
-		return -ENOENT;
-
-	return manager_attr->show(manager, buf);
-}
-
-static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
-		const char *buf, size_t size)
-{
-	struct omap_overlay_manager *manager;
-	struct manager_attribute *manager_attr;
-
-	manager = container_of(kobj, struct omap_overlay_manager, kobj);
-	manager_attr = container_of(attr, struct manager_attribute, attr);
-
-	if (!manager_attr->store)
-		return -ENOENT;
-
-	return manager_attr->store(manager, buf, size);
-}
-
-static const struct sysfs_ops manager_sysfs_ops = {
-	.show = manager_attr_show,
-	.store = manager_attr_store,
-};
-
-static struct kobj_type manager_ktype = {
-	.sysfs_ops = &manager_sysfs_ops,
-	.default_attrs = manager_sysfs_attrs,
-};
-
-int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
-		struct platform_device *pdev)
-{
-	return kobject_init_and_add(&mgr->kobj, &manager_ktype,
-			&pdev->dev.kobj, "manager%d", mgr->id);
-}
-
-void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
-{
-	kobject_del(&mgr->kobj);
-	kobject_put(&mgr->kobj);
-
-	memset(&mgr->kobj, 0, sizeof(mgr->kobj));
-}
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
deleted file mode 100644
index 1aac9b4191a9..000000000000
--- a/drivers/video/omap2/dss/manager.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/manager.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "MANAGER"
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/jiffies.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-static int num_managers;
-static struct omap_overlay_manager *managers;
-
-int dss_init_overlay_managers(void)
-{
-	int i;
-
-	num_managers = dss_feat_get_num_mgrs();
-
-	managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers,
-			GFP_KERNEL);
-
-	BUG_ON(managers == NULL);
-
-	for (i = 0; i < num_managers; ++i) {
-		struct omap_overlay_manager *mgr = &managers[i];
-
-		switch (i) {
-		case 0:
-			mgr->name = "lcd";
-			mgr->id = OMAP_DSS_CHANNEL_LCD;
-			break;
-		case 1:
-			mgr->name = "tv";
-			mgr->id = OMAP_DSS_CHANNEL_DIGIT;
-			break;
-		case 2:
-			mgr->name = "lcd2";
-			mgr->id = OMAP_DSS_CHANNEL_LCD2;
-			break;
-		case 3:
-			mgr->name = "lcd3";
-			mgr->id = OMAP_DSS_CHANNEL_LCD3;
-			break;
-		}
-
-		mgr->caps = 0;
-		mgr->supported_displays =
-			dss_feat_get_supported_displays(mgr->id);
-		mgr->supported_outputs =
-			dss_feat_get_supported_outputs(mgr->id);
-
-		INIT_LIST_HEAD(&mgr->overlays);
-	}
-
-	return 0;
-}
-
-int dss_init_overlay_managers_sysfs(struct platform_device *pdev)
-{
-	int i, r;
-
-	for (i = 0; i < num_managers; ++i) {
-		struct omap_overlay_manager *mgr = &managers[i];
-
-		r = dss_manager_kobj_init(mgr, pdev);
-		if (r)
-			DSSERR("failed to create sysfs file\n");
-	}
-
-	return 0;
-}
-
-void dss_uninit_overlay_managers(void)
-{
-	kfree(managers);
-	managers = NULL;
-	num_managers = 0;
-}
-
-void dss_uninit_overlay_managers_sysfs(struct platform_device *pdev)
-{
-	int i;
-
-	for (i = 0; i < num_managers; ++i) {
-		struct omap_overlay_manager *mgr = &managers[i];
-
-		dss_manager_kobj_uninit(mgr);
-	}
-}
-
-int omap_dss_get_num_overlay_managers(void)
-{
-	return num_managers;
-}
-EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
-
-struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
-{
-	if (num >= num_managers)
-		return NULL;
-
-	return &managers[num];
-}
-EXPORT_SYMBOL(omap_dss_get_overlay_manager);
-
-int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
-		const struct omap_overlay_manager_info *info)
-{
-	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
-		/*
-		 * OMAP3 supports only graphics source transparency color key
-		 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
-		 * Alpha Mode.
-		 */
-		if (info->partial_alpha_enabled && info->trans_enabled
-			&& info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) {
-			DSSERR("check_manager: illegal transparency key\n");
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
-		struct omap_overlay_info **overlay_infos)
-{
-	struct omap_overlay *ovl1, *ovl2;
-	struct omap_overlay_info *info1, *info2;
-
-	list_for_each_entry(ovl1, &mgr->overlays, list) {
-		info1 = overlay_infos[ovl1->id];
-
-		if (info1 == NULL)
-			continue;
-
-		list_for_each_entry(ovl2, &mgr->overlays, list) {
-			if (ovl1 == ovl2)
-				continue;
-
-			info2 = overlay_infos[ovl2->id];
-
-			if (info2 == NULL)
-				continue;
-
-			if (info1->zorder == info2->zorder) {
-				DSSERR("overlays %d and %d have the same "
-						"zorder %d\n",
-					ovl1->id, ovl2->id, info1->zorder);
-				return -EINVAL;
-			}
-		}
-	}
-
-	return 0;
-}
-
-int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
-		const struct omap_video_timings *timings)
-{
-	if (!dispc_mgr_timings_ok(mgr->id, timings)) {
-		DSSERR("check_manager: invalid timings\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr,
-		const struct dss_lcd_mgr_config *config)
-{
-	struct dispc_clock_info cinfo = config->clock_info;
-	int dl = config->video_port_width;
-	bool stallmode = config->stallmode;
-	bool fifohandcheck = config->fifohandcheck;
-
-	if (cinfo.lck_div < 1 || cinfo.lck_div > 255)
-		return -EINVAL;
-
-	if (cinfo.pck_div < 1 || cinfo.pck_div > 255)
-		return -EINVAL;
-
-	if (dl != 12 && dl != 16 && dl != 18 && dl != 24)
-		return -EINVAL;
-
-	/* fifohandcheck should be used only with stallmode */
-	if (stallmode == false && fifohandcheck == true)
-		return -EINVAL;
-
-	/*
-	 * io pad mode can be only checked by using dssdev connected to the
-	 * manager. Ignore checking these for now, add checks when manager
-	 * is capable of holding information related to the connected interface
-	 */
-
-	return 0;
-}
-
-int dss_mgr_check(struct omap_overlay_manager *mgr,
-		struct omap_overlay_manager_info *info,
-		const struct omap_video_timings *mgr_timings,
-		const struct dss_lcd_mgr_config *lcd_config,
-		struct omap_overlay_info **overlay_infos)
-{
-	struct omap_overlay *ovl;
-	int r;
-
-	if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
-		r = dss_mgr_check_zorder(mgr, overlay_infos);
-		if (r)
-			return r;
-	}
-
-	r = dss_mgr_check_timings(mgr, mgr_timings);
-	if (r)
-		return r;
-
-	r = dss_mgr_check_lcd_config(mgr, lcd_config);
-	if (r)
-		return r;
-
-	list_for_each_entry(ovl, &mgr->overlays, list) {
-		struct omap_overlay_info *oi;
-		int r;
-
-		oi = overlay_infos[ovl->id];
-
-		if (oi == NULL)
-			continue;
-
-		r = dss_ovl_check(ovl, oi, mgr_timings);
-		if (r)
-			return r;
-	}
-
-	return 0;
-}
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
deleted file mode 100644
index 2ab3afa615e8..000000000000
--- a/drivers/video/omap2/dss/output.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments Ltd
- * Author: Archit Taneja <archit@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-
-static LIST_HEAD(output_list);
-static DEFINE_MUTEX(output_lock);
-
-int omapdss_output_set_device(struct omap_dss_device *out,
-		struct omap_dss_device *dssdev)
-{
-	int r;
-
-	mutex_lock(&output_lock);
-
-	if (out->dst) {
-		DSSERR("output already has device %s connected to it\n",
-			out->dst->name);
-		r = -EINVAL;
-		goto err;
-	}
-
-	if (out->output_type != dssdev->type) {
-		DSSERR("output type and display type don't match\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	out->dst = dssdev;
-	dssdev->src = out;
-
-	mutex_unlock(&output_lock);
-
-	return 0;
-err:
-	mutex_unlock(&output_lock);
-
-	return r;
-}
-EXPORT_SYMBOL(omapdss_output_set_device);
-
-int omapdss_output_unset_device(struct omap_dss_device *out)
-{
-	int r;
-
-	mutex_lock(&output_lock);
-
-	if (!out->dst) {
-		DSSERR("output doesn't have a device connected to it\n");
-		r = -EINVAL;
-		goto err;
-	}
-
-	if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
-		DSSERR("device %s is not disabled, cannot unset device\n",
-				out->dst->name);
-		r = -EINVAL;
-		goto err;
-	}
-
-	out->dst->src = NULL;
-	out->dst = NULL;
-
-	mutex_unlock(&output_lock);
-
-	return 0;
-err:
-	mutex_unlock(&output_lock);
-
-	return r;
-}
-EXPORT_SYMBOL(omapdss_output_unset_device);
-
-int omapdss_register_output(struct omap_dss_device *out)
-{
-	list_add_tail(&out->list, &output_list);
-	return 0;
-}
-EXPORT_SYMBOL(omapdss_register_output);
-
-void omapdss_unregister_output(struct omap_dss_device *out)
-{
-	list_del(&out->list);
-}
-EXPORT_SYMBOL(omapdss_unregister_output);
-
-struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
-{
-	struct omap_dss_device *out;
-
-	list_for_each_entry(out, &output_list, list) {
-		if (out->id == id)
-			return out;
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(omap_dss_get_output);
-
-struct omap_dss_device *omap_dss_find_output(const char *name)
-{
-	struct omap_dss_device *out;
-
-	list_for_each_entry(out, &output_list, list) {
-		if (strcmp(out->name, name) == 0)
-			return omap_dss_get_device(out);
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(omap_dss_find_output);
-
-struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node)
-{
-	struct omap_dss_device *out;
-
-	list_for_each_entry(out, &output_list, list) {
-		if (out->dev->of_node == node)
-			return omap_dss_get_device(out);
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(omap_dss_find_output_by_node);
-
-struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
-{
-	while (dssdev->src)
-		dssdev = dssdev->src;
-
-	if (dssdev->id != 0)
-		return omap_dss_get_device(dssdev);
-
-	return NULL;
-}
-EXPORT_SYMBOL(omapdss_find_output_from_display);
-
-struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_device *out;
-	struct omap_overlay_manager *mgr;
-
-	out = omapdss_find_output_from_display(dssdev);
-
-	if (out == NULL)
-		return NULL;
-
-	mgr = out->manager;
-
-	omap_dss_put_device(out);
-
-	return mgr;
-}
-EXPORT_SYMBOL(omapdss_find_mgr_from_display);
-
-static const struct dss_mgr_ops *dss_mgr_ops;
-
-int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
-{
-	if (dss_mgr_ops)
-		return -EBUSY;
-
-	dss_mgr_ops = mgr_ops;
-
-	return 0;
-}
-EXPORT_SYMBOL(dss_install_mgr_ops);
-
-void dss_uninstall_mgr_ops(void)
-{
-	dss_mgr_ops = NULL;
-}
-EXPORT_SYMBOL(dss_uninstall_mgr_ops);
-
-int dss_mgr_connect(struct omap_overlay_manager *mgr,
-		struct omap_dss_device *dst)
-{
-	return dss_mgr_ops->connect(mgr, dst);
-}
-EXPORT_SYMBOL(dss_mgr_connect);
-
-void dss_mgr_disconnect(struct omap_overlay_manager *mgr,
-		struct omap_dss_device *dst)
-{
-	dss_mgr_ops->disconnect(mgr, dst);
-}
-EXPORT_SYMBOL(dss_mgr_disconnect);
-
-void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-		const struct omap_video_timings *timings)
-{
-	dss_mgr_ops->set_timings(mgr, timings);
-}
-EXPORT_SYMBOL(dss_mgr_set_timings);
-
-void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
-		const struct dss_lcd_mgr_config *config)
-{
-	dss_mgr_ops->set_lcd_config(mgr, config);
-}
-EXPORT_SYMBOL(dss_mgr_set_lcd_config);
-
-int dss_mgr_enable(struct omap_overlay_manager *mgr)
-{
-	return dss_mgr_ops->enable(mgr);
-}
-EXPORT_SYMBOL(dss_mgr_enable);
-
-void dss_mgr_disable(struct omap_overlay_manager *mgr)
-{
-	dss_mgr_ops->disable(mgr);
-}
-EXPORT_SYMBOL(dss_mgr_disable);
-
-void dss_mgr_start_update(struct omap_overlay_manager *mgr)
-{
-	dss_mgr_ops->start_update(mgr);
-}
-EXPORT_SYMBOL(dss_mgr_start_update);
-
-int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
-		void (*handler)(void *), void *data)
-{
-	return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
-}
-EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
-
-void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
-		void (*handler)(void *), void *data)
-{
-	dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
-}
-EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c
deleted file mode 100644
index 4cc5ddebfb34..000000000000
--- a/drivers/video/omap2/dss/overlay-sysfs.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "OVERLAY"
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/sysfs.h>
-#include <linux/kobject.h>
-#include <linux/platform_device.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
-}
-
-static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			ovl->manager ? ovl->manager->name : "<none>");
-}
-
-static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
-		size_t size)
-{
-	int i, r;
-	struct omap_overlay_manager *mgr = NULL;
-	struct omap_overlay_manager *old_mgr;
-	int len = size;
-
-	if (buf[size-1] == '\n')
-		--len;
-
-	if (len > 0) {
-		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-			mgr = omap_dss_get_overlay_manager(i);
-
-			if (sysfs_streq(buf, mgr->name))
-				break;
-
-			mgr = NULL;
-		}
-	}
-
-	if (len > 0 && mgr == NULL)
-		return -EINVAL;
-
-	if (mgr)
-		DSSDBG("manager %s found\n", mgr->name);
-
-	if (mgr == ovl->manager)
-		return size;
-
-	old_mgr = ovl->manager;
-
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
-	/* detach old manager */
-	if (old_mgr) {
-		r = ovl->unset_manager(ovl);
-		if (r) {
-			DSSERR("detach failed\n");
-			goto err;
-		}
-
-		r = old_mgr->apply(old_mgr);
-		if (r)
-			goto err;
-	}
-
-	if (mgr) {
-		r = ovl->set_manager(ovl, mgr);
-		if (r) {
-			DSSERR("Failed to attach overlay\n");
-			goto err;
-		}
-
-		r = mgr->apply(mgr);
-		if (r)
-			goto err;
-	}
-
-	dispc_runtime_put();
-
-	return size;
-
-err:
-	dispc_runtime_put();
-	return r;
-}
-
-static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
-{
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-			info.width, info.height);
-}
-
-static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
-{
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
-}
-
-static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
-{
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-			info.pos_x, info.pos_y);
-}
-
-static ssize_t overlay_position_store(struct omap_overlay *ovl,
-		const char *buf, size_t size)
-{
-	int r;
-	char *last;
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	info.pos_x = simple_strtoul(buf, &last, 10);
-	++last;
-	if (last - buf >= size)
-		return -EINVAL;
-
-	info.pos_y = simple_strtoul(last, &last, 10);
-
-	r = ovl->set_overlay_info(ovl, &info);
-	if (r)
-		return r;
-
-	if (ovl->manager) {
-		r = ovl->manager->apply(ovl->manager);
-		if (r)
-			return r;
-	}
-
-	return size;
-}
-
-static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
-{
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-			info.out_width, info.out_height);
-}
-
-static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
-		const char *buf, size_t size)
-{
-	int r;
-	char *last;
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	info.out_width = simple_strtoul(buf, &last, 10);
-	++last;
-	if (last - buf >= size)
-		return -EINVAL;
-
-	info.out_height = simple_strtoul(last, &last, 10);
-
-	r = ovl->set_overlay_info(ovl, &info);
-	if (r)
-		return r;
-
-	if (ovl->manager) {
-		r = ovl->manager->apply(ovl->manager);
-		if (r)
-			return r;
-	}
-
-	return size;
-}
-
-static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
-}
-
-static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
-		size_t size)
-{
-	int r;
-	bool enable;
-
-	r = strtobool(buf, &enable);
-	if (r)
-		return r;
-
-	if (enable)
-		r = ovl->enable(ovl);
-	else
-		r = ovl->disable(ovl);
-
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
-{
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			info.global_alpha);
-}
-
-static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
-		const char *buf, size_t size)
-{
-	int r;
-	u8 alpha;
-	struct omap_overlay_info info;
-
-	if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
-		return -ENODEV;
-
-	r = kstrtou8(buf, 0, &alpha);
-	if (r)
-		return r;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	info.global_alpha = alpha;
-
-	r = ovl->set_overlay_info(ovl, &info);
-	if (r)
-		return r;
-
-	if (ovl->manager) {
-		r = ovl->manager->apply(ovl->manager);
-		if (r)
-			return r;
-	}
-
-	return size;
-}
-
-static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
-		char *buf)
-{
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			info.pre_mult_alpha);
-}
-
-static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
-		const char *buf, size_t size)
-{
-	int r;
-	u8 alpha;
-	struct omap_overlay_info info;
-
-	if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
-		return -ENODEV;
-
-	r = kstrtou8(buf, 0, &alpha);
-	if (r)
-		return r;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	info.pre_mult_alpha = alpha;
-
-	r = ovl->set_overlay_info(ovl, &info);
-	if (r)
-		return r;
-
-	if (ovl->manager) {
-		r = ovl->manager->apply(ovl->manager);
-		if (r)
-			return r;
-	}
-
-	return size;
-}
-
-static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
-{
-	struct omap_overlay_info info;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
-}
-
-static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
-		const char *buf, size_t size)
-{
-	int r;
-	u8 zorder;
-	struct omap_overlay_info info;
-
-	if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
-		return -ENODEV;
-
-	r = kstrtou8(buf, 0, &zorder);
-	if (r)
-		return r;
-
-	ovl->get_overlay_info(ovl, &info);
-
-	info.zorder = zorder;
-
-	r = ovl->set_overlay_info(ovl, &info);
-	if (r)
-		return r;
-
-	if (ovl->manager) {
-		r = ovl->manager->apply(ovl->manager);
-		if (r)
-			return r;
-	}
-
-	return size;
-}
-
-struct overlay_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct omap_overlay *, char *);
-	ssize_t	(*store)(struct omap_overlay *, const char *, size_t);
-};
-
-#define OVERLAY_ATTR(_name, _mode, _show, _store) \
-	struct overlay_attribute overlay_attr_##_name = \
-	__ATTR(_name, _mode, _show, _store)
-
-static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
-static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
-		overlay_manager_show, overlay_manager_store);
-static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
-static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
-static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
-		overlay_position_show, overlay_position_store);
-static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
-		overlay_output_size_show, overlay_output_size_store);
-static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
-		overlay_enabled_show, overlay_enabled_store);
-static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
-		overlay_global_alpha_show, overlay_global_alpha_store);
-static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
-		overlay_pre_mult_alpha_show,
-		overlay_pre_mult_alpha_store);
-static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
-		overlay_zorder_show, overlay_zorder_store);
-
-static struct attribute *overlay_sysfs_attrs[] = {
-	&overlay_attr_name.attr,
-	&overlay_attr_manager.attr,
-	&overlay_attr_input_size.attr,
-	&overlay_attr_screen_width.attr,
-	&overlay_attr_position.attr,
-	&overlay_attr_output_size.attr,
-	&overlay_attr_enabled.attr,
-	&overlay_attr_global_alpha.attr,
-	&overlay_attr_pre_mult_alpha.attr,
-	&overlay_attr_zorder.attr,
-	NULL
-};
-
-static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
-		char *buf)
-{
-	struct omap_overlay *overlay;
-	struct overlay_attribute *overlay_attr;
-
-	overlay = container_of(kobj, struct omap_overlay, kobj);
-	overlay_attr = container_of(attr, struct overlay_attribute, attr);
-
-	if (!overlay_attr->show)
-		return -ENOENT;
-
-	return overlay_attr->show(overlay, buf);
-}
-
-static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
-		const char *buf, size_t size)
-{
-	struct omap_overlay *overlay;
-	struct overlay_attribute *overlay_attr;
-
-	overlay = container_of(kobj, struct omap_overlay, kobj);
-	overlay_attr = container_of(attr, struct overlay_attribute, attr);
-
-	if (!overlay_attr->store)
-		return -ENOENT;
-
-	return overlay_attr->store(overlay, buf, size);
-}
-
-static const struct sysfs_ops overlay_sysfs_ops = {
-	.show = overlay_attr_show,
-	.store = overlay_attr_store,
-};
-
-static struct kobj_type overlay_ktype = {
-	.sysfs_ops = &overlay_sysfs_ops,
-	.default_attrs = overlay_sysfs_attrs,
-};
-
-int dss_overlay_kobj_init(struct omap_overlay *ovl,
-		struct platform_device *pdev)
-{
-	return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
-			&pdev->dev.kobj, "overlay%d", ovl->id);
-}
-
-void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
-{
-	kobject_del(&ovl->kobj);
-	kobject_put(&ovl->kobj);
-}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
deleted file mode 100644
index 2f7cee985cdd..000000000000
--- a/drivers/video/omap2/dss/overlay.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/overlay.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "OVERLAY"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/sysfs.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-static int num_overlays;
-static struct omap_overlay *overlays;
-
-int omap_dss_get_num_overlays(void)
-{
-	return num_overlays;
-}
-EXPORT_SYMBOL(omap_dss_get_num_overlays);
-
-struct omap_overlay *omap_dss_get_overlay(int num)
-{
-	if (num >= num_overlays)
-		return NULL;
-
-	return &overlays[num];
-}
-EXPORT_SYMBOL(omap_dss_get_overlay);
-
-void dss_init_overlays(struct platform_device *pdev)
-{
-	int i, r;
-
-	num_overlays = dss_feat_get_num_ovls();
-
-	overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays,
-			GFP_KERNEL);
-
-	BUG_ON(overlays == NULL);
-
-	for (i = 0; i < num_overlays; ++i) {
-		struct omap_overlay *ovl = &overlays[i];
-
-		switch (i) {
-		case 0:
-			ovl->name = "gfx";
-			ovl->id = OMAP_DSS_GFX;
-			break;
-		case 1:
-			ovl->name = "vid1";
-			ovl->id = OMAP_DSS_VIDEO1;
-			break;
-		case 2:
-			ovl->name = "vid2";
-			ovl->id = OMAP_DSS_VIDEO2;
-			break;
-		case 3:
-			ovl->name = "vid3";
-			ovl->id = OMAP_DSS_VIDEO3;
-			break;
-		}
-
-		ovl->caps = dss_feat_get_overlay_caps(ovl->id);
-		ovl->supported_modes =
-			dss_feat_get_supported_color_modes(ovl->id);
-
-		r = dss_overlay_kobj_init(ovl, pdev);
-		if (r)
-			DSSERR("failed to create sysfs file\n");
-	}
-}
-
-void dss_uninit_overlays(struct platform_device *pdev)
-{
-	int i;
-
-	for (i = 0; i < num_overlays; ++i) {
-		struct omap_overlay *ovl = &overlays[i];
-		dss_overlay_kobj_uninit(ovl);
-	}
-
-	kfree(overlays);
-	overlays = NULL;
-	num_overlays = 0;
-}
-
-int dss_ovl_simple_check(struct omap_overlay *ovl,
-		const struct omap_overlay_info *info)
-{
-	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
-		if (info->out_width != 0 && info->width != info->out_width) {
-			DSSERR("check_overlay: overlay %d doesn't support "
-					"scaling\n", ovl->id);
-			return -EINVAL;
-		}
-
-		if (info->out_height != 0 && info->height != info->out_height) {
-			DSSERR("check_overlay: overlay %d doesn't support "
-					"scaling\n", ovl->id);
-			return -EINVAL;
-		}
-	}
-
-	if ((ovl->supported_modes & info->color_mode) == 0) {
-		DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
-				ovl->id, info->color_mode);
-		return -EINVAL;
-	}
-
-	if (info->zorder >= omap_dss_get_num_overlays()) {
-		DSSERR("check_overlay: zorder %d too high\n", info->zorder);
-		return -EINVAL;
-	}
-
-	if (dss_feat_rotation_type_supported(info->rotation_type) == 0) {
-		DSSERR("check_overlay: rotation type %d not supported\n",
-				info->rotation_type);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
-		const struct omap_video_timings *mgr_timings)
-{
-	u16 outw, outh;
-	u16 dw, dh;
-
-	dw = mgr_timings->x_res;
-	dh = mgr_timings->y_res;
-
-	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
-		outw = info->width;
-		outh = info->height;
-	} else {
-		if (info->out_width == 0)
-			outw = info->width;
-		else
-			outw = info->out_width;
-
-		if (info->out_height == 0)
-			outh = info->height;
-		else
-			outh = info->out_height;
-	}
-
-	if (dw < info->pos_x + outw) {
-		DSSERR("overlay %d horizontally not inside the display area "
-				"(%d + %d >= %d)\n",
-				ovl->id, info->pos_x, outw, dw);
-		return -EINVAL;
-	}
-
-	if (dh < info->pos_y + outh) {
-		DSSERR("overlay %d vertically not inside the display area "
-				"(%d + %d >= %d)\n",
-				ovl->id, info->pos_y, outh, dh);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
- * Checks if replication logic should be used. Only use when overlay is in
- * RGB12U or RGB16 mode, and video port width interface is 18bpp or 24bpp
- */
-bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
-		enum omap_color_mode mode)
-{
-	if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
-		return false;
-
-	return config.video_port_width > 16;
-}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
deleted file mode 100644
index c8a81a2b879c..000000000000
--- a/drivers/video/omap2/dss/rfbi.c
+++ /dev/null
@@ -1,1058 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/rfbi.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "RFBI"
-
-#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/export.h>
-#include <linux/vmalloc.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/kfifo.h>
-#include <linux/ktime.h>
-#include <linux/hrtimer.h>
-#include <linux/seq_file.h>
-#include <linux/semaphore.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-
-#include <video/omapdss.h>
-#include "dss.h"
-
-struct rfbi_reg { u16 idx; };
-
-#define RFBI_REG(idx)		((const struct rfbi_reg) { idx })
-
-#define RFBI_REVISION		RFBI_REG(0x0000)
-#define RFBI_SYSCONFIG		RFBI_REG(0x0010)
-#define RFBI_SYSSTATUS		RFBI_REG(0x0014)
-#define RFBI_CONTROL		RFBI_REG(0x0040)
-#define RFBI_PIXEL_CNT		RFBI_REG(0x0044)
-#define RFBI_LINE_NUMBER	RFBI_REG(0x0048)
-#define RFBI_CMD		RFBI_REG(0x004c)
-#define RFBI_PARAM		RFBI_REG(0x0050)
-#define RFBI_DATA		RFBI_REG(0x0054)
-#define RFBI_READ		RFBI_REG(0x0058)
-#define RFBI_STATUS		RFBI_REG(0x005c)
-
-#define RFBI_CONFIG(n)		RFBI_REG(0x0060 + (n)*0x18)
-#define RFBI_ONOFF_TIME(n)	RFBI_REG(0x0064 + (n)*0x18)
-#define RFBI_CYCLE_TIME(n)	RFBI_REG(0x0068 + (n)*0x18)
-#define RFBI_DATA_CYCLE1(n)	RFBI_REG(0x006c + (n)*0x18)
-#define RFBI_DATA_CYCLE2(n)	RFBI_REG(0x0070 + (n)*0x18)
-#define RFBI_DATA_CYCLE3(n)	RFBI_REG(0x0074 + (n)*0x18)
-
-#define RFBI_VSYNC_WIDTH	RFBI_REG(0x0090)
-#define RFBI_HSYNC_WIDTH	RFBI_REG(0x0094)
-
-#define REG_FLD_MOD(idx, val, start, end) \
-	rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
-
-enum omap_rfbi_cycleformat {
-	OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
-	OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
-	OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
-	OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
-};
-
-enum omap_rfbi_datatype {
-	OMAP_DSS_RFBI_DATATYPE_12 = 0,
-	OMAP_DSS_RFBI_DATATYPE_16 = 1,
-	OMAP_DSS_RFBI_DATATYPE_18 = 2,
-	OMAP_DSS_RFBI_DATATYPE_24 = 3,
-};
-
-enum omap_rfbi_parallelmode {
-	OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
-	OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
-	OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
-	OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
-};
-
-static int rfbi_convert_timings(struct rfbi_timings *t);
-static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
-
-static struct {
-	struct platform_device *pdev;
-	void __iomem	*base;
-
-	unsigned long	l4_khz;
-
-	enum omap_rfbi_datatype datatype;
-	enum omap_rfbi_parallelmode parallelmode;
-
-	enum omap_rfbi_te_mode te_mode;
-	int te_enabled;
-
-	void (*framedone_callback)(void *data);
-	void *framedone_callback_data;
-
-	struct omap_dss_device *dssdev[2];
-
-	struct semaphore bus_lock;
-
-	struct omap_video_timings timings;
-	int pixel_size;
-	int data_lines;
-	struct rfbi_timings intf_timings;
-
-	struct omap_dss_device output;
-} rfbi;
-
-static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
-{
-	__raw_writel(val, rfbi.base + idx.idx);
-}
-
-static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
-{
-	return __raw_readl(rfbi.base + idx.idx);
-}
-
-static int rfbi_runtime_get(void)
-{
-	int r;
-
-	DSSDBG("rfbi_runtime_get\n");
-
-	r = pm_runtime_get_sync(&rfbi.pdev->dev);
-	WARN_ON(r < 0);
-	return r < 0 ? r : 0;
-}
-
-static void rfbi_runtime_put(void)
-{
-	int r;
-
-	DSSDBG("rfbi_runtime_put\n");
-
-	r = pm_runtime_put_sync(&rfbi.pdev->dev);
-	WARN_ON(r < 0 && r != -ENOSYS);
-}
-
-static void rfbi_bus_lock(void)
-{
-	down(&rfbi.bus_lock);
-}
-
-static void rfbi_bus_unlock(void)
-{
-	up(&rfbi.bus_lock);
-}
-
-static void rfbi_write_command(const void *buf, u32 len)
-{
-	switch (rfbi.parallelmode) {
-	case OMAP_DSS_RFBI_PARALLELMODE_8:
-	{
-		const u8 *b = buf;
-		for (; len; len--)
-			rfbi_write_reg(RFBI_CMD, *b++);
-		break;
-	}
-
-	case OMAP_DSS_RFBI_PARALLELMODE_16:
-	{
-		const u16 *w = buf;
-		BUG_ON(len & 1);
-		for (; len; len -= 2)
-			rfbi_write_reg(RFBI_CMD, *w++);
-		break;
-	}
-
-	case OMAP_DSS_RFBI_PARALLELMODE_9:
-	case OMAP_DSS_RFBI_PARALLELMODE_12:
-	default:
-		BUG();
-	}
-}
-
-static void rfbi_read_data(void *buf, u32 len)
-{
-	switch (rfbi.parallelmode) {
-	case OMAP_DSS_RFBI_PARALLELMODE_8:
-	{
-		u8 *b = buf;
-		for (; len; len--) {
-			rfbi_write_reg(RFBI_READ, 0);
-			*b++ = rfbi_read_reg(RFBI_READ);
-		}
-		break;
-	}
-
-	case OMAP_DSS_RFBI_PARALLELMODE_16:
-	{
-		u16 *w = buf;
-		BUG_ON(len & ~1);
-		for (; len; len -= 2) {
-			rfbi_write_reg(RFBI_READ, 0);
-			*w++ = rfbi_read_reg(RFBI_READ);
-		}
-		break;
-	}
-
-	case OMAP_DSS_RFBI_PARALLELMODE_9:
-	case OMAP_DSS_RFBI_PARALLELMODE_12:
-	default:
-		BUG();
-	}
-}
-
-static void rfbi_write_data(const void *buf, u32 len)
-{
-	switch (rfbi.parallelmode) {
-	case OMAP_DSS_RFBI_PARALLELMODE_8:
-	{
-		const u8 *b = buf;
-		for (; len; len--)
-			rfbi_write_reg(RFBI_PARAM, *b++);
-		break;
-	}
-
-	case OMAP_DSS_RFBI_PARALLELMODE_16:
-	{
-		const u16 *w = buf;
-		BUG_ON(len & 1);
-		for (; len; len -= 2)
-			rfbi_write_reg(RFBI_PARAM, *w++);
-		break;
-	}
-
-	case OMAP_DSS_RFBI_PARALLELMODE_9:
-	case OMAP_DSS_RFBI_PARALLELMODE_12:
-	default:
-		BUG();
-
-	}
-}
-
-static void rfbi_write_pixels(const void __iomem *buf, int scr_width,
-		u16 x, u16 y,
-		u16 w, u16 h)
-{
-	int start_offset = scr_width * y + x;
-	int horiz_offset = scr_width - w;
-	int i;
-
-	if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
-	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
-		const u16 __iomem *pd = buf;
-		pd += start_offset;
-
-		for (; h; --h) {
-			for (i = 0; i < w; ++i) {
-				const u8 __iomem *b = (const u8 __iomem *)pd;
-				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
-				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
-				++pd;
-			}
-			pd += horiz_offset;
-		}
-	} else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
-	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
-		const u32 __iomem *pd = buf;
-		pd += start_offset;
-
-		for (; h; --h) {
-			for (i = 0; i < w; ++i) {
-				const u8 __iomem *b = (const u8 __iomem *)pd;
-				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
-				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
-				rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
-				++pd;
-			}
-			pd += horiz_offset;
-		}
-	} else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
-	   rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
-		const u16 __iomem *pd = buf;
-		pd += start_offset;
-
-		for (; h; --h) {
-			for (i = 0; i < w; ++i) {
-				rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
-				++pd;
-			}
-			pd += horiz_offset;
-		}
-	} else {
-		BUG();
-	}
-}
-
-static int rfbi_transfer_area(struct omap_dss_device *dssdev,
-		void (*callback)(void *data), void *data)
-{
-	u32 l;
-	int r;
-	struct omap_overlay_manager *mgr = rfbi.output.manager;
-	u16 width = rfbi.timings.x_res;
-	u16 height = rfbi.timings.y_res;
-
-	/*BUG_ON(callback == 0);*/
-	BUG_ON(rfbi.framedone_callback != NULL);
-
-	DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
-
-	dss_mgr_set_timings(mgr, &rfbi.timings);
-
-	r = dss_mgr_enable(mgr);
-	if (r)
-		return r;
-
-	rfbi.framedone_callback = callback;
-	rfbi.framedone_callback_data = data;
-
-	rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
-
-	l = rfbi_read_reg(RFBI_CONTROL);
-	l = FLD_MOD(l, 1, 0, 0); /* enable */
-	if (!rfbi.te_enabled)
-		l = FLD_MOD(l, 1, 4, 4); /* ITE */
-
-	rfbi_write_reg(RFBI_CONTROL, l);
-
-	return 0;
-}
-
-static void framedone_callback(void *data)
-{
-	void (*callback)(void *data);
-
-	DSSDBG("FRAMEDONE\n");
-
-	REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
-
-	callback = rfbi.framedone_callback;
-	rfbi.framedone_callback = NULL;
-
-	if (callback != NULL)
-		callback(rfbi.framedone_callback_data);
-}
-
-#if 1 /* VERBOSE */
-static void rfbi_print_timings(void)
-{
-	u32 l;
-	u32 time;
-
-	l = rfbi_read_reg(RFBI_CONFIG(0));
-	time = 1000000000 / rfbi.l4_khz;
-	if (l & (1 << 4))
-		time *= 2;
-
-	DSSDBG("Tick time %u ps\n", time);
-	l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
-	DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
-		"REONTIME %d, REOFFTIME %d\n",
-		l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
-		(l >> 20) & 0x0f, (l >> 24) & 0x3f);
-
-	l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
-	DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
-		"ACCESSTIME %d\n",
-		(l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
-		(l >> 22) & 0x3f);
-}
-#else
-static void rfbi_print_timings(void) {}
-#endif
-
-
-
-
-static u32 extif_clk_period;
-
-static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
-{
-	int bus_tick = extif_clk_period * div;
-	return (ps + bus_tick - 1) / bus_tick * bus_tick;
-}
-
-static int calc_reg_timing(struct rfbi_timings *t, int div)
-{
-	t->clk_div = div;
-
-	t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
-
-	t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
-	t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
-	t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
-
-	t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
-	t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
-	t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
-
-	t->access_time = round_to_extif_ticks(t->access_time, div);
-	t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
-	t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
-
-	DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
-	       t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
-	DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
-	       t->we_on_time, t->we_off_time, t->re_cycle_time,
-	       t->we_cycle_time);
-	DSSDBG("[reg]rdaccess %d cspulse %d\n",
-	       t->access_time, t->cs_pulse_width);
-
-	return rfbi_convert_timings(t);
-}
-
-static int calc_extif_timings(struct rfbi_timings *t)
-{
-	u32 max_clk_div;
-	int div;
-
-	rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
-	for (div = 1; div <= max_clk_div; div++) {
-		if (calc_reg_timing(t, div) == 0)
-			break;
-	}
-
-	if (div <= max_clk_div)
-		return 0;
-
-	DSSERR("can't setup timings\n");
-	return -1;
-}
-
-
-static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
-{
-	int r;
-
-	if (!t->converted) {
-		r = calc_extif_timings(t);
-		if (r < 0)
-			DSSERR("Failed to calc timings\n");
-	}
-
-	BUG_ON(!t->converted);
-
-	rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
-	rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
-
-	/* TIMEGRANULARITY */
-	REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
-		    (t->tim[2] ? 1 : 0), 4, 4);
-
-	rfbi_print_timings();
-}
-
-static int ps_to_rfbi_ticks(int time, int div)
-{
-	unsigned long tick_ps;
-	int ret;
-
-	/* Calculate in picosecs to yield more exact results */
-	tick_ps = 1000000000 / (rfbi.l4_khz) * div;
-
-	ret = (time + tick_ps - 1) / tick_ps;
-
-	return ret;
-}
-
-static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
-{
-	*clk_period = 1000000000 / rfbi.l4_khz;
-	*max_clk_div = 2;
-}
-
-static int rfbi_convert_timings(struct rfbi_timings *t)
-{
-	u32 l;
-	int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
-	int actim, recyc, wecyc;
-	int div = t->clk_div;
-
-	if (div <= 0 || div > 2)
-		return -1;
-
-	/* Make sure that after conversion it still holds that:
-	 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
-	 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
-	 */
-	weon = ps_to_rfbi_ticks(t->we_on_time, div);
-	weoff = ps_to_rfbi_ticks(t->we_off_time, div);
-	if (weoff <= weon)
-		weoff = weon + 1;
-	if (weon > 0x0f)
-		return -1;
-	if (weoff > 0x3f)
-		return -1;
-
-	reon = ps_to_rfbi_ticks(t->re_on_time, div);
-	reoff = ps_to_rfbi_ticks(t->re_off_time, div);
-	if (reoff <= reon)
-		reoff = reon + 1;
-	if (reon > 0x0f)
-		return -1;
-	if (reoff > 0x3f)
-		return -1;
-
-	cson = ps_to_rfbi_ticks(t->cs_on_time, div);
-	csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
-	if (csoff <= cson)
-		csoff = cson + 1;
-	if (csoff < max(weoff, reoff))
-		csoff = max(weoff, reoff);
-	if (cson > 0x0f)
-		return -1;
-	if (csoff > 0x3f)
-		return -1;
-
-	l =  cson;
-	l |= csoff << 4;
-	l |= weon  << 10;
-	l |= weoff << 14;
-	l |= reon  << 20;
-	l |= reoff << 24;
-
-	t->tim[0] = l;
-
-	actim = ps_to_rfbi_ticks(t->access_time, div);
-	if (actim <= reon)
-		actim = reon + 1;
-	if (actim > 0x3f)
-		return -1;
-
-	wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
-	if (wecyc < weoff)
-		wecyc = weoff;
-	if (wecyc > 0x3f)
-		return -1;
-
-	recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
-	if (recyc < reoff)
-		recyc = reoff;
-	if (recyc > 0x3f)
-		return -1;
-
-	cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
-	if (cs_pulse > 0x3f)
-		return -1;
-
-	l =  wecyc;
-	l |= recyc    << 6;
-	l |= cs_pulse << 12;
-	l |= actim    << 22;
-
-	t->tim[1] = l;
-
-	t->tim[2] = div - 1;
-
-	t->converted = 1;
-
-	return 0;
-}
-
-/* xxx FIX module selection missing */
-static int rfbi_setup_te(enum omap_rfbi_te_mode mode,
-			     unsigned hs_pulse_time, unsigned vs_pulse_time,
-			     int hs_pol_inv, int vs_pol_inv, int extif_div)
-{
-	int hs, vs;
-	int min;
-	u32 l;
-
-	hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
-	vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
-	if (hs < 2)
-		return -EDOM;
-	if (mode == OMAP_DSS_RFBI_TE_MODE_2)
-		min = 2;
-	else /* OMAP_DSS_RFBI_TE_MODE_1 */
-		min = 4;
-	if (vs < min)
-		return -EDOM;
-	if (vs == hs)
-		return -EINVAL;
-	rfbi.te_mode = mode;
-	DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
-		mode, hs, vs, hs_pol_inv, vs_pol_inv);
-
-	rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
-	rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
-
-	l = rfbi_read_reg(RFBI_CONFIG(0));
-	if (hs_pol_inv)
-		l &= ~(1 << 21);
-	else
-		l |= 1 << 21;
-	if (vs_pol_inv)
-		l &= ~(1 << 20);
-	else
-		l |= 1 << 20;
-
-	return 0;
-}
-
-/* xxx FIX module selection missing */
-static int rfbi_enable_te(bool enable, unsigned line)
-{
-	u32 l;
-
-	DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
-	if (line > (1 << 11) - 1)
-		return -EINVAL;
-
-	l = rfbi_read_reg(RFBI_CONFIG(0));
-	l &= ~(0x3 << 2);
-	if (enable) {
-		rfbi.te_enabled = 1;
-		l |= rfbi.te_mode << 2;
-	} else
-		rfbi.te_enabled = 0;
-	rfbi_write_reg(RFBI_CONFIG(0), l);
-	rfbi_write_reg(RFBI_LINE_NUMBER, line);
-
-	return 0;
-}
-
-static int rfbi_configure_bus(int rfbi_module, int bpp, int lines)
-{
-	u32 l;
-	int cycle1 = 0, cycle2 = 0, cycle3 = 0;
-	enum omap_rfbi_cycleformat cycleformat;
-	enum omap_rfbi_datatype datatype;
-	enum omap_rfbi_parallelmode parallelmode;
-
-	switch (bpp) {
-	case 12:
-		datatype = OMAP_DSS_RFBI_DATATYPE_12;
-		break;
-	case 16:
-		datatype = OMAP_DSS_RFBI_DATATYPE_16;
-		break;
-	case 18:
-		datatype = OMAP_DSS_RFBI_DATATYPE_18;
-		break;
-	case 24:
-		datatype = OMAP_DSS_RFBI_DATATYPE_24;
-		break;
-	default:
-		BUG();
-		return 1;
-	}
-	rfbi.datatype = datatype;
-
-	switch (lines) {
-	case 8:
-		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
-		break;
-	case 9:
-		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
-		break;
-	case 12:
-		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
-		break;
-	case 16:
-		parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
-		break;
-	default:
-		BUG();
-		return 1;
-	}
-	rfbi.parallelmode = parallelmode;
-
-	if ((bpp % lines) == 0) {
-		switch (bpp / lines) {
-		case 1:
-			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
-			break;
-		case 2:
-			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
-			break;
-		case 3:
-			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
-			break;
-		default:
-			BUG();
-			return 1;
-		}
-	} else if ((2 * bpp % lines) == 0) {
-		if ((2 * bpp / lines) == 3)
-			cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
-		else {
-			BUG();
-			return 1;
-		}
-	} else {
-		BUG();
-		return 1;
-	}
-
-	switch (cycleformat) {
-	case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
-		cycle1 = lines;
-		break;
-
-	case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
-		cycle1 = lines;
-		cycle2 = lines;
-		break;
-
-	case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
-		cycle1 = lines;
-		cycle2 = lines;
-		cycle3 = lines;
-		break;
-
-	case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
-		cycle1 = lines;
-		cycle2 = (lines / 2) | ((lines / 2) << 16);
-		cycle3 = (lines << 16);
-		break;
-	}
-
-	REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
-
-	l = 0;
-	l |= FLD_VAL(parallelmode, 1, 0);
-	l |= FLD_VAL(0, 3, 2);		/* TRIGGERMODE: ITE */
-	l |= FLD_VAL(0, 4, 4);		/* TIMEGRANULARITY */
-	l |= FLD_VAL(datatype, 6, 5);
-	/* l |= FLD_VAL(2, 8, 7); */	/* L4FORMAT, 2pix/L4 */
-	l |= FLD_VAL(0, 8, 7);	/* L4FORMAT, 1pix/L4 */
-	l |= FLD_VAL(cycleformat, 10, 9);
-	l |= FLD_VAL(0, 12, 11);	/* UNUSEDBITS */
-	l |= FLD_VAL(0, 16, 16);	/* A0POLARITY */
-	l |= FLD_VAL(0, 17, 17);	/* REPOLARITY */
-	l |= FLD_VAL(0, 18, 18);	/* WEPOLARITY */
-	l |= FLD_VAL(0, 19, 19);	/* CSPOLARITY */
-	l |= FLD_VAL(1, 20, 20);	/* TE_VSYNC_POLARITY */
-	l |= FLD_VAL(1, 21, 21);	/* HSYNCPOLARITY */
-	rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
-
-	rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
-	rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
-	rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
-
-
-	l = rfbi_read_reg(RFBI_CONTROL);
-	l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
-	l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
-	rfbi_write_reg(RFBI_CONTROL, l);
-
-
-	DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
-	       bpp, lines, cycle1, cycle2, cycle3);
-
-	return 0;
-}
-
-static int rfbi_configure(struct omap_dss_device *dssdev)
-{
-	return rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
-			rfbi.data_lines);
-}
-
-static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
-		void *data)
-{
-	return rfbi_transfer_area(dssdev, callback, data);
-}
-
-static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
-{
-	rfbi.timings.x_res = w;
-	rfbi.timings.y_res = h;
-}
-
-static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
-{
-	rfbi.pixel_size = pixel_size;
-}
-
-static void rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
-{
-	rfbi.data_lines = data_lines;
-}
-
-static void rfbi_set_interface_timings(struct omap_dss_device *dssdev,
-		struct rfbi_timings *timings)
-{
-	rfbi.intf_timings = *timings;
-}
-
-static void rfbi_dump_regs(struct seq_file *s)
-{
-#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
-
-	if (rfbi_runtime_get())
-		return;
-
-	DUMPREG(RFBI_REVISION);
-	DUMPREG(RFBI_SYSCONFIG);
-	DUMPREG(RFBI_SYSSTATUS);
-	DUMPREG(RFBI_CONTROL);
-	DUMPREG(RFBI_PIXEL_CNT);
-	DUMPREG(RFBI_LINE_NUMBER);
-	DUMPREG(RFBI_CMD);
-	DUMPREG(RFBI_PARAM);
-	DUMPREG(RFBI_DATA);
-	DUMPREG(RFBI_READ);
-	DUMPREG(RFBI_STATUS);
-
-	DUMPREG(RFBI_CONFIG(0));
-	DUMPREG(RFBI_ONOFF_TIME(0));
-	DUMPREG(RFBI_CYCLE_TIME(0));
-	DUMPREG(RFBI_DATA_CYCLE1(0));
-	DUMPREG(RFBI_DATA_CYCLE2(0));
-	DUMPREG(RFBI_DATA_CYCLE3(0));
-
-	DUMPREG(RFBI_CONFIG(1));
-	DUMPREG(RFBI_ONOFF_TIME(1));
-	DUMPREG(RFBI_CYCLE_TIME(1));
-	DUMPREG(RFBI_DATA_CYCLE1(1));
-	DUMPREG(RFBI_DATA_CYCLE2(1));
-	DUMPREG(RFBI_DATA_CYCLE3(1));
-
-	DUMPREG(RFBI_VSYNC_WIDTH);
-	DUMPREG(RFBI_HSYNC_WIDTH);
-
-	rfbi_runtime_put();
-#undef DUMPREG
-}
-
-static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
-{
-	struct omap_overlay_manager *mgr = rfbi.output.manager;
-	struct dss_lcd_mgr_config mgr_config;
-
-	mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
-
-	mgr_config.stallmode = true;
-	/* Do we need fifohandcheck for RFBI? */
-	mgr_config.fifohandcheck = false;
-
-	mgr_config.video_port_width = rfbi.pixel_size;
-	mgr_config.lcden_sig_polarity = 0;
-
-	dss_mgr_set_lcd_config(mgr, &mgr_config);
-
-	/*
-	 * Set rfbi.timings with default values, the x_res and y_res fields
-	 * are expected to be already configured by the panel driver via
-	 * omapdss_rfbi_set_size()
-	 */
-	rfbi.timings.hsw = 1;
-	rfbi.timings.hfp = 1;
-	rfbi.timings.hbp = 1;
-	rfbi.timings.vsw = 1;
-	rfbi.timings.vfp = 0;
-	rfbi.timings.vbp = 0;
-
-	rfbi.timings.interlace = false;
-	rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
-
-	dss_mgr_set_timings(mgr, &rfbi.timings);
-}
-
-static int rfbi_display_enable(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_device *out = &rfbi.output;
-	int r;
-
-	if (out == NULL || out->manager == NULL) {
-		DSSERR("failed to enable display: no output/manager\n");
-		return -ENODEV;
-	}
-
-	r = rfbi_runtime_get();
-	if (r)
-		return r;
-
-	r = dss_mgr_register_framedone_handler(out->manager,
-			framedone_callback, NULL);
-	if (r) {
-		DSSERR("can't get FRAMEDONE irq\n");
-		goto err1;
-	}
-
-	rfbi_config_lcd_manager(dssdev);
-
-	rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size,
-			rfbi.data_lines);
-
-	rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
-
-	return 0;
-err1:
-	rfbi_runtime_put();
-	return r;
-}
-
-static void rfbi_display_disable(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_device *out = &rfbi.output;
-
-	dss_mgr_unregister_framedone_handler(out->manager,
-			framedone_callback, NULL);
-
-	rfbi_runtime_put();
-}
-
-static int rfbi_init_display(struct omap_dss_device *dssdev)
-{
-	rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
-	return 0;
-}
-
-static void rfbi_init_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &rfbi.output;
-
-	out->dev = &pdev->dev;
-	out->id = OMAP_DSS_OUTPUT_DBI;
-	out->output_type = OMAP_DISPLAY_TYPE_DBI;
-	out->name = "rfbi.0";
-	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
-	out->owner = THIS_MODULE;
-
-	omapdss_register_output(out);
-}
-
-static void __exit rfbi_uninit_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &rfbi.output;
-
-	omapdss_unregister_output(out);
-}
-
-/* RFBI HW IP initialisation */
-static int omap_rfbihw_probe(struct platform_device *pdev)
-{
-	u32 rev;
-	struct resource *rfbi_mem;
-	struct clk *clk;
-	int r;
-
-	rfbi.pdev = pdev;
-
-	sema_init(&rfbi.bus_lock, 1);
-
-	rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
-	if (!rfbi_mem) {
-		DSSERR("can't get IORESOURCE_MEM RFBI\n");
-		return -EINVAL;
-	}
-
-	rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start,
-				 resource_size(rfbi_mem));
-	if (!rfbi.base) {
-		DSSERR("can't ioremap RFBI\n");
-		return -ENOMEM;
-	}
-
-	clk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(clk)) {
-		DSSERR("can't get ick\n");
-		return PTR_ERR(clk);
-	}
-
-	rfbi.l4_khz = clk_get_rate(clk) / 1000;
-
-	clk_put(clk);
-
-	pm_runtime_enable(&pdev->dev);
-
-	r = rfbi_runtime_get();
-	if (r)
-		goto err_runtime_get;
-
-	msleep(10);
-
-	rev = rfbi_read_reg(RFBI_REVISION);
-	dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
-	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-	rfbi_runtime_put();
-
-	dss_debugfs_create_file("rfbi", rfbi_dump_regs);
-
-	rfbi_init_output(pdev);
-
-	return 0;
-
-err_runtime_get:
-	pm_runtime_disable(&pdev->dev);
-	return r;
-}
-
-static int __exit omap_rfbihw_remove(struct platform_device *pdev)
-{
-	rfbi_uninit_output(pdev);
-
-	pm_runtime_disable(&pdev->dev);
-
-	return 0;
-}
-
-static int rfbi_runtime_suspend(struct device *dev)
-{
-	dispc_runtime_put();
-
-	return 0;
-}
-
-static int rfbi_runtime_resume(struct device *dev)
-{
-	int r;
-
-	r = dispc_runtime_get();
-	if (r < 0)
-		return r;
-
-	return 0;
-}
-
-static const struct dev_pm_ops rfbi_pm_ops = {
-	.runtime_suspend = rfbi_runtime_suspend,
-	.runtime_resume = rfbi_runtime_resume,
-};
-
-static struct platform_driver omap_rfbihw_driver = {
-	.probe		= omap_rfbihw_probe,
-	.remove         = __exit_p(omap_rfbihw_remove),
-	.driver         = {
-		.name   = "omapdss_rfbi",
-		.owner  = THIS_MODULE,
-		.pm	= &rfbi_pm_ops,
-	},
-};
-
-int __init rfbi_init_platform_driver(void)
-{
-	return platform_driver_register(&omap_rfbihw_driver);
-}
-
-void __exit rfbi_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omap_rfbihw_driver);
-}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
deleted file mode 100644
index 911dcc9173a6..000000000000
--- a/drivers/video/omap2/dss/sdi.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/sdi.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "SDI"
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/regulator/consumer.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/of.h>
-
-#include <video/omapdss.h>
-#include "dss.h"
-
-static struct {
-	struct platform_device *pdev;
-
-	bool update_enabled;
-	struct regulator *vdds_sdi_reg;
-
-	struct dss_lcd_mgr_config mgr_config;
-	struct omap_video_timings timings;
-	int datapairs;
-
-	struct omap_dss_device output;
-
-	bool port_initialized;
-} sdi;
-
-struct sdi_clk_calc_ctx {
-	unsigned long pck_min, pck_max;
-
-	unsigned long fck;
-	struct dispc_clock_info dispc_cinfo;
-};
-
-static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
-		unsigned long pck, void *data)
-{
-	struct sdi_clk_calc_ctx *ctx = data;
-
-	ctx->dispc_cinfo.lck_div = lckd;
-	ctx->dispc_cinfo.pck_div = pckd;
-	ctx->dispc_cinfo.lck = lck;
-	ctx->dispc_cinfo.pck = pck;
-
-	return true;
-}
-
-static bool dpi_calc_dss_cb(unsigned long fck, void *data)
-{
-	struct sdi_clk_calc_ctx *ctx = data;
-
-	ctx->fck = fck;
-
-	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
-			dpi_calc_dispc_cb, ctx);
-}
-
-static int sdi_calc_clock_div(unsigned long pclk,
-		unsigned long *fck,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	int i;
-	struct sdi_clk_calc_ctx ctx;
-
-	/*
-	 * DSS fclk gives us very few possibilities, so finding a good pixel
-	 * clock may not be possible. We try multiple times to find the clock,
-	 * each time widening the pixel clock range we look for, up to
-	 * +/- 1MHz.
-	 */
-
-	for (i = 0; i < 10; ++i) {
-		bool ok;
-
-		memset(&ctx, 0, sizeof(ctx));
-		if (pclk > 1000 * i * i * i)
-			ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
-		else
-			ctx.pck_min = 0;
-		ctx.pck_max = pclk + 1000 * i * i * i;
-
-		ok = dss_div_calc(pclk, ctx.pck_min, dpi_calc_dss_cb, &ctx);
-		if (ok) {
-			*fck = ctx.fck;
-			*dispc_cinfo = ctx.dispc_cinfo;
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
-{
-	struct omap_overlay_manager *mgr = sdi.output.manager;
-
-	sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
-
-	sdi.mgr_config.stallmode = false;
-	sdi.mgr_config.fifohandcheck = false;
-
-	sdi.mgr_config.video_port_width = 24;
-	sdi.mgr_config.lcden_sig_polarity = 1;
-
-	dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
-}
-
-static int sdi_display_enable(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_device *out = &sdi.output;
-	struct omap_video_timings *t = &sdi.timings;
-	unsigned long fck;
-	struct dispc_clock_info dispc_cinfo;
-	unsigned long pck;
-	int r;
-
-	if (out == NULL || out->manager == NULL) {
-		DSSERR("failed to enable display: no output/manager\n");
-		return -ENODEV;
-	}
-
-	r = regulator_enable(sdi.vdds_sdi_reg);
-	if (r)
-		goto err_reg_enable;
-
-	r = dispc_runtime_get();
-	if (r)
-		goto err_get_dispc;
-
-	/* 15.5.9.1.2 */
-	t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-
-	r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo);
-	if (r)
-		goto err_calc_clock_div;
-
-	sdi.mgr_config.clock_info = dispc_cinfo;
-
-	pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
-
-	if (pck != t->pixelclock) {
-		DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
-			t->pixelclock, pck);
-
-		t->pixelclock = pck;
-	}
-
-
-	dss_mgr_set_timings(out->manager, t);
-
-	r = dss_set_fck_rate(fck);
-	if (r)
-		goto err_set_dss_clock_div;
-
-	sdi_config_lcd_manager(dssdev);
-
-	/*
-	 * LCLK and PCLK divisors are located in shadow registers, and we
-	 * normally write them to DISPC registers when enabling the output.
-	 * However, SDI uses pck-free as source clock for its PLL, and pck-free
-	 * is affected by the divisors. And as we need the PLL before enabling
-	 * the output, we need to write the divisors early.
-	 *
-	 * It seems just writing to the DISPC register is enough, and we don't
-	 * need to care about the shadow register mechanism for pck-free. The
-	 * exact reason for this is unknown.
-	 */
-	dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
-
-	dss_sdi_init(sdi.datapairs);
-	r = dss_sdi_enable();
-	if (r)
-		goto err_sdi_enable;
-	mdelay(2);
-
-	r = dss_mgr_enable(out->manager);
-	if (r)
-		goto err_mgr_enable;
-
-	return 0;
-
-err_mgr_enable:
-	dss_sdi_disable();
-err_sdi_enable:
-err_set_dss_clock_div:
-err_calc_clock_div:
-	dispc_runtime_put();
-err_get_dispc:
-	regulator_disable(sdi.vdds_sdi_reg);
-err_reg_enable:
-	return r;
-}
-
-static void sdi_display_disable(struct omap_dss_device *dssdev)
-{
-	struct omap_overlay_manager *mgr = sdi.output.manager;
-
-	dss_mgr_disable(mgr);
-
-	dss_sdi_disable();
-
-	dispc_runtime_put();
-
-	regulator_disable(sdi.vdds_sdi_reg);
-}
-
-static void sdi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	sdi.timings = *timings;
-}
-
-static void sdi_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	*timings = sdi.timings;
-}
-
-static int sdi_check_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings)
-{
-	struct omap_overlay_manager *mgr = sdi.output.manager;
-
-	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
-		return -EINVAL;
-
-	if (timings->pixelclock == 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-static void sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
-{
-	sdi.datapairs = datapairs;
-}
-
-static int sdi_init_regulator(void)
-{
-	struct regulator *vdds_sdi;
-
-	if (sdi.vdds_sdi_reg)
-		return 0;
-
-	vdds_sdi = devm_regulator_get(&sdi.pdev->dev, "vdds_sdi");
-	if (IS_ERR(vdds_sdi)) {
-		if (PTR_ERR(vdds_sdi) != -EPROBE_DEFER)
-			DSSERR("can't get VDDS_SDI regulator\n");
-		return PTR_ERR(vdds_sdi);
-	}
-
-	sdi.vdds_sdi_reg = vdds_sdi;
-
-	return 0;
-}
-
-static int sdi_connect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct omap_overlay_manager *mgr;
-	int r;
-
-	r = sdi_init_regulator();
-	if (r)
-		return r;
-
-	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
-	if (!mgr)
-		return -ENODEV;
-
-	r = dss_mgr_connect(mgr, dssdev);
-	if (r)
-		return r;
-
-	r = omapdss_output_set_device(dssdev, dst);
-	if (r) {
-		DSSERR("failed to connect output to new device: %s\n",
-				dst->name);
-		dss_mgr_disconnect(mgr, dssdev);
-		return r;
-	}
-
-	return 0;
-}
-
-static void sdi_disconnect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	WARN_ON(dst != dssdev->dst);
-
-	if (dst != dssdev->dst)
-		return;
-
-	omapdss_output_unset_device(dssdev);
-
-	if (dssdev->manager)
-		dss_mgr_disconnect(dssdev->manager, dssdev);
-}
-
-static const struct omapdss_sdi_ops sdi_ops = {
-	.connect = sdi_connect,
-	.disconnect = sdi_disconnect,
-
-	.enable = sdi_display_enable,
-	.disable = sdi_display_disable,
-
-	.check_timings = sdi_check_timings,
-	.set_timings = sdi_set_timings,
-	.get_timings = sdi_get_timings,
-
-	.set_datapairs = sdi_set_datapairs,
-};
-
-static void sdi_init_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &sdi.output;
-
-	out->dev = &pdev->dev;
-	out->id = OMAP_DSS_OUTPUT_SDI;
-	out->output_type = OMAP_DISPLAY_TYPE_SDI;
-	out->name = "sdi.0";
-	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
-	out->ops.sdi = &sdi_ops;
-	out->owner = THIS_MODULE;
-
-	omapdss_register_output(out);
-}
-
-static void __exit sdi_uninit_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &sdi.output;
-
-	omapdss_unregister_output(out);
-}
-
-static int omap_sdi_probe(struct platform_device *pdev)
-{
-	sdi.pdev = pdev;
-
-	sdi_init_output(pdev);
-
-	return 0;
-}
-
-static int __exit omap_sdi_remove(struct platform_device *pdev)
-{
-	sdi_uninit_output(pdev);
-
-	return 0;
-}
-
-static struct platform_driver omap_sdi_driver = {
-	.probe		= omap_sdi_probe,
-	.remove         = __exit_p(omap_sdi_remove),
-	.driver         = {
-		.name   = "omapdss_sdi",
-		.owner  = THIS_MODULE,
-	},
-};
-
-int __init sdi_init_platform_driver(void)
-{
-	return platform_driver_register(&omap_sdi_driver);
-}
-
-void __exit sdi_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omap_sdi_driver);
-}
-
-int __init sdi_init_port(struct platform_device *pdev, struct device_node *port)
-{
-	struct device_node *ep;
-	u32 datapairs;
-	int r;
-
-	ep = omapdss_of_get_next_endpoint(port, NULL);
-	if (!ep)
-		return 0;
-
-	r = of_property_read_u32(ep, "datapairs", &datapairs);
-	if (r) {
-		DSSERR("failed to parse datapairs\n");
-		goto err_datapairs;
-	}
-
-	sdi.datapairs = datapairs;
-
-	of_node_put(ep);
-
-	sdi.pdev = pdev;
-
-	sdi_init_output(pdev);
-
-	sdi.port_initialized = true;
-
-	return 0;
-
-err_datapairs:
-	of_node_put(ep);
-
-	return r;
-}
-
-void __exit sdi_uninit_port(void)
-{
-	if (!sdi.port_initialized)
-		return;
-
-	sdi_uninit_output(sdi.pdev);
-}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
deleted file mode 100644
index 21d81113962b..000000000000
--- a/drivers/video/omap2/dss/venc.c
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * linux/drivers/video/omap2/dss/venc.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * VENC settings from TI's DSS driver
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DSS_SUBSYS_NAME "VENC"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/seq_file.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/pm_runtime.h>
-#include <linux/of.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-#include "dss_features.h"
-
-/* Venc registers */
-#define VENC_REV_ID				0x00
-#define VENC_STATUS				0x04
-#define VENC_F_CONTROL				0x08
-#define VENC_VIDOUT_CTRL			0x10
-#define VENC_SYNC_CTRL				0x14
-#define VENC_LLEN				0x1C
-#define VENC_FLENS				0x20
-#define VENC_HFLTR_CTRL				0x24
-#define VENC_CC_CARR_WSS_CARR			0x28
-#define VENC_C_PHASE				0x2C
-#define VENC_GAIN_U				0x30
-#define VENC_GAIN_V				0x34
-#define VENC_GAIN_Y				0x38
-#define VENC_BLACK_LEVEL			0x3C
-#define VENC_BLANK_LEVEL			0x40
-#define VENC_X_COLOR				0x44
-#define VENC_M_CONTROL				0x48
-#define VENC_BSTAMP_WSS_DATA			0x4C
-#define VENC_S_CARR				0x50
-#define VENC_LINE21				0x54
-#define VENC_LN_SEL				0x58
-#define VENC_L21__WC_CTL			0x5C
-#define VENC_HTRIGGER_VTRIGGER			0x60
-#define VENC_SAVID__EAVID			0x64
-#define VENC_FLEN__FAL				0x68
-#define VENC_LAL__PHASE_RESET			0x6C
-#define VENC_HS_INT_START_STOP_X		0x70
-#define VENC_HS_EXT_START_STOP_X		0x74
-#define VENC_VS_INT_START_X			0x78
-#define VENC_VS_INT_STOP_X__VS_INT_START_Y	0x7C
-#define VENC_VS_INT_STOP_Y__VS_EXT_START_X	0x80
-#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y	0x84
-#define VENC_VS_EXT_STOP_Y			0x88
-#define VENC_AVID_START_STOP_X			0x90
-#define VENC_AVID_START_STOP_Y			0x94
-#define VENC_FID_INT_START_X__FID_INT_START_Y	0xA0
-#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X	0xA4
-#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y	0xA8
-#define VENC_TVDETGP_INT_START_STOP_X		0xB0
-#define VENC_TVDETGP_INT_START_STOP_Y		0xB4
-#define VENC_GEN_CTRL				0xB8
-#define VENC_OUTPUT_CONTROL			0xC4
-#define VENC_OUTPUT_TEST			0xC8
-#define VENC_DAC_B__DAC_C			0xC8
-
-struct venc_config {
-	u32 f_control;
-	u32 vidout_ctrl;
-	u32 sync_ctrl;
-	u32 llen;
-	u32 flens;
-	u32 hfltr_ctrl;
-	u32 cc_carr_wss_carr;
-	u32 c_phase;
-	u32 gain_u;
-	u32 gain_v;
-	u32 gain_y;
-	u32 black_level;
-	u32 blank_level;
-	u32 x_color;
-	u32 m_control;
-	u32 bstamp_wss_data;
-	u32 s_carr;
-	u32 line21;
-	u32 ln_sel;
-	u32 l21__wc_ctl;
-	u32 htrigger_vtrigger;
-	u32 savid__eavid;
-	u32 flen__fal;
-	u32 lal__phase_reset;
-	u32 hs_int_start_stop_x;
-	u32 hs_ext_start_stop_x;
-	u32 vs_int_start_x;
-	u32 vs_int_stop_x__vs_int_start_y;
-	u32 vs_int_stop_y__vs_ext_start_x;
-	u32 vs_ext_stop_x__vs_ext_start_y;
-	u32 vs_ext_stop_y;
-	u32 avid_start_stop_x;
-	u32 avid_start_stop_y;
-	u32 fid_int_start_x__fid_int_start_y;
-	u32 fid_int_offset_y__fid_ext_start_x;
-	u32 fid_ext_start_y__fid_ext_offset_y;
-	u32 tvdetgp_int_start_stop_x;
-	u32 tvdetgp_int_start_stop_y;
-	u32 gen_ctrl;
-};
-
-/* from TRM */
-static const struct venc_config venc_config_pal_trm = {
-	.f_control				= 0,
-	.vidout_ctrl				= 1,
-	.sync_ctrl				= 0x40,
-	.llen					= 0x35F, /* 863 */
-	.flens					= 0x270, /* 624 */
-	.hfltr_ctrl				= 0,
-	.cc_carr_wss_carr			= 0x2F7225ED,
-	.c_phase				= 0,
-	.gain_u					= 0x111,
-	.gain_v					= 0x181,
-	.gain_y					= 0x140,
-	.black_level				= 0x3B,
-	.blank_level				= 0x3B,
-	.x_color				= 0x7,
-	.m_control				= 0x2,
-	.bstamp_wss_data			= 0x3F,
-	.s_carr					= 0x2A098ACB,
-	.line21					= 0,
-	.ln_sel					= 0x01290015,
-	.l21__wc_ctl				= 0x0000F603,
-	.htrigger_vtrigger			= 0,
-
-	.savid__eavid				= 0x06A70108,
-	.flen__fal				= 0x00180270,
-	.lal__phase_reset			= 0x00040135,
-	.hs_int_start_stop_x			= 0x00880358,
-	.hs_ext_start_stop_x			= 0x000F035F,
-	.vs_int_start_x				= 0x01A70000,
-	.vs_int_stop_x__vs_int_start_y		= 0x000001A7,
-	.vs_int_stop_y__vs_ext_start_x		= 0x01AF0000,
-	.vs_ext_stop_x__vs_ext_start_y		= 0x000101AF,
-	.vs_ext_stop_y				= 0x00000025,
-	.avid_start_stop_x			= 0x03530083,
-	.avid_start_stop_y			= 0x026C002E,
-	.fid_int_start_x__fid_int_start_y	= 0x0001008A,
-	.fid_int_offset_y__fid_ext_start_x	= 0x002E0138,
-	.fid_ext_start_y__fid_ext_offset_y	= 0x01380001,
-
-	.tvdetgp_int_start_stop_x		= 0x00140001,
-	.tvdetgp_int_start_stop_y		= 0x00010001,
-	.gen_ctrl				= 0x00FF0000,
-};
-
-/* from TRM */
-static const struct venc_config venc_config_ntsc_trm = {
-	.f_control				= 0,
-	.vidout_ctrl				= 1,
-	.sync_ctrl				= 0x8040,
-	.llen					= 0x359,
-	.flens					= 0x20C,
-	.hfltr_ctrl				= 0,
-	.cc_carr_wss_carr			= 0x043F2631,
-	.c_phase				= 0,
-	.gain_u					= 0x102,
-	.gain_v					= 0x16C,
-	.gain_y					= 0x12F,
-	.black_level				= 0x43,
-	.blank_level				= 0x38,
-	.x_color				= 0x7,
-	.m_control				= 0x1,
-	.bstamp_wss_data			= 0x38,
-	.s_carr					= 0x21F07C1F,
-	.line21					= 0,
-	.ln_sel					= 0x01310011,
-	.l21__wc_ctl				= 0x0000F003,
-	.htrigger_vtrigger			= 0,
-
-	.savid__eavid				= 0x069300F4,
-	.flen__fal				= 0x0016020C,
-	.lal__phase_reset			= 0x00060107,
-	.hs_int_start_stop_x			= 0x008E0350,
-	.hs_ext_start_stop_x			= 0x000F0359,
-	.vs_int_start_x				= 0x01A00000,
-	.vs_int_stop_x__vs_int_start_y		= 0x020701A0,
-	.vs_int_stop_y__vs_ext_start_x		= 0x01AC0024,
-	.vs_ext_stop_x__vs_ext_start_y		= 0x020D01AC,
-	.vs_ext_stop_y				= 0x00000006,
-	.avid_start_stop_x			= 0x03480078,
-	.avid_start_stop_y			= 0x02060024,
-	.fid_int_start_x__fid_int_start_y	= 0x0001008A,
-	.fid_int_offset_y__fid_ext_start_x	= 0x01AC0106,
-	.fid_ext_start_y__fid_ext_offset_y	= 0x01060006,
-
-	.tvdetgp_int_start_stop_x		= 0x00140001,
-	.tvdetgp_int_start_stop_y		= 0x00010001,
-	.gen_ctrl				= 0x00F90000,
-};
-
-static const struct venc_config venc_config_pal_bdghi = {
-	.f_control				= 0,
-	.vidout_ctrl				= 0,
-	.sync_ctrl				= 0,
-	.hfltr_ctrl				= 0,
-	.x_color				= 0,
-	.line21					= 0,
-	.ln_sel					= 21,
-	.htrigger_vtrigger			= 0,
-	.tvdetgp_int_start_stop_x		= 0x00140001,
-	.tvdetgp_int_start_stop_y		= 0x00010001,
-	.gen_ctrl				= 0x00FB0000,
-
-	.llen					= 864-1,
-	.flens					= 625-1,
-	.cc_carr_wss_carr			= 0x2F7625ED,
-	.c_phase				= 0xDF,
-	.gain_u					= 0x111,
-	.gain_v					= 0x181,
-	.gain_y					= 0x140,
-	.black_level				= 0x3e,
-	.blank_level				= 0x3e,
-	.m_control				= 0<<2 | 1<<1,
-	.bstamp_wss_data			= 0x42,
-	.s_carr					= 0x2a098acb,
-	.l21__wc_ctl				= 0<<13 | 0x16<<8 | 0<<0,
-	.savid__eavid				= 0x06A70108,
-	.flen__fal				= 23<<16 | 624<<0,
-	.lal__phase_reset			= 2<<17 | 310<<0,
-	.hs_int_start_stop_x			= 0x00920358,
-	.hs_ext_start_stop_x			= 0x000F035F,
-	.vs_int_start_x				= 0x1a7<<16,
-	.vs_int_stop_x__vs_int_start_y		= 0x000601A7,
-	.vs_int_stop_y__vs_ext_start_x		= 0x01AF0036,
-	.vs_ext_stop_x__vs_ext_start_y		= 0x27101af,
-	.vs_ext_stop_y				= 0x05,
-	.avid_start_stop_x			= 0x03530082,
-	.avid_start_stop_y			= 0x0270002E,
-	.fid_int_start_x__fid_int_start_y	= 0x0005008A,
-	.fid_int_offset_y__fid_ext_start_x	= 0x002E0138,
-	.fid_ext_start_y__fid_ext_offset_y	= 0x01380005,
-};
-
-const struct omap_video_timings omap_dss_pal_timings = {
-	.x_res		= 720,
-	.y_res		= 574,
-	.pixelclock	= 13500000,
-	.hsw		= 64,
-	.hfp		= 12,
-	.hbp		= 68,
-	.vsw		= 5,
-	.vfp		= 5,
-	.vbp		= 41,
-
-	.interlace	= true,
-};
-EXPORT_SYMBOL(omap_dss_pal_timings);
-
-const struct omap_video_timings omap_dss_ntsc_timings = {
-	.x_res		= 720,
-	.y_res		= 482,
-	.pixelclock	= 13500000,
-	.hsw		= 64,
-	.hfp		= 16,
-	.hbp		= 58,
-	.vsw		= 6,
-	.vfp		= 6,
-	.vbp		= 31,
-
-	.interlace	= true,
-};
-EXPORT_SYMBOL(omap_dss_ntsc_timings);
-
-static struct {
-	struct platform_device *pdev;
-	void __iomem *base;
-	struct mutex venc_lock;
-	u32 wss_data;
-	struct regulator *vdda_dac_reg;
-
-	struct clk	*tv_dac_clk;
-
-	struct omap_video_timings timings;
-	enum omap_dss_venc_type type;
-	bool invert_polarity;
-
-	struct omap_dss_device output;
-} venc;
-
-static inline void venc_write_reg(int idx, u32 val)
-{
-	__raw_writel(val, venc.base + idx);
-}
-
-static inline u32 venc_read_reg(int idx)
-{
-	u32 l = __raw_readl(venc.base + idx);
-	return l;
-}
-
-static void venc_write_config(const struct venc_config *config)
-{
-	DSSDBG("write venc conf\n");
-
-	venc_write_reg(VENC_LLEN, config->llen);
-	venc_write_reg(VENC_FLENS, config->flens);
-	venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
-	venc_write_reg(VENC_C_PHASE, config->c_phase);
-	venc_write_reg(VENC_GAIN_U, config->gain_u);
-	venc_write_reg(VENC_GAIN_V, config->gain_v);
-	venc_write_reg(VENC_GAIN_Y, config->gain_y);
-	venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
-	venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
-	venc_write_reg(VENC_M_CONTROL, config->m_control);
-	venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
-			venc.wss_data);
-	venc_write_reg(VENC_S_CARR, config->s_carr);
-	venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
-	venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
-	venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
-	venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
-	venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
-	venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
-	venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
-	venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
-		       config->vs_int_stop_x__vs_int_start_y);
-	venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
-		       config->vs_int_stop_y__vs_ext_start_x);
-	venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
-		       config->vs_ext_stop_x__vs_ext_start_y);
-	venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
-	venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
-	venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
-	venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
-		       config->fid_int_start_x__fid_int_start_y);
-	venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
-		       config->fid_int_offset_y__fid_ext_start_x);
-	venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
-		       config->fid_ext_start_y__fid_ext_offset_y);
-
-	venc_write_reg(VENC_DAC_B__DAC_C,  venc_read_reg(VENC_DAC_B__DAC_C));
-	venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
-	venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
-	venc_write_reg(VENC_X_COLOR, config->x_color);
-	venc_write_reg(VENC_LINE21, config->line21);
-	venc_write_reg(VENC_LN_SEL, config->ln_sel);
-	venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
-	venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
-		       config->tvdetgp_int_start_stop_x);
-	venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
-		       config->tvdetgp_int_start_stop_y);
-	venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
-	venc_write_reg(VENC_F_CONTROL, config->f_control);
-	venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
-}
-
-static void venc_reset(void)
-{
-	int t = 1000;
-
-	venc_write_reg(VENC_F_CONTROL, 1<<8);
-	while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
-		if (--t == 0) {
-			DSSERR("Failed to reset venc\n");
-			return;
-		}
-	}
-
-#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
-	/* the magical sleep that makes things work */
-	/* XXX more info? What bug this circumvents? */
-	msleep(20);
-#endif
-}
-
-static int venc_runtime_get(void)
-{
-	int r;
-
-	DSSDBG("venc_runtime_get\n");
-
-	r = pm_runtime_get_sync(&venc.pdev->dev);
-	WARN_ON(r < 0);
-	return r < 0 ? r : 0;
-}
-
-static void venc_runtime_put(void)
-{
-	int r;
-
-	DSSDBG("venc_runtime_put\n");
-
-	r = pm_runtime_put_sync(&venc.pdev->dev);
-	WARN_ON(r < 0 && r != -ENOSYS);
-}
-
-static const struct venc_config *venc_timings_to_config(
-		struct omap_video_timings *timings)
-{
-	if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
-		return &venc_config_pal_trm;
-
-	if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
-		return &venc_config_ntsc_trm;
-
-	BUG();
-	return NULL;
-}
-
-static int venc_power_on(struct omap_dss_device *dssdev)
-{
-	struct omap_overlay_manager *mgr = venc.output.manager;
-	u32 l;
-	int r;
-
-	r = venc_runtime_get();
-	if (r)
-		goto err0;
-
-	venc_reset();
-	venc_write_config(venc_timings_to_config(&venc.timings));
-
-	dss_set_venc_output(venc.type);
-	dss_set_dac_pwrdn_bgz(1);
-
-	l = 0;
-
-	if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
-		l |= 1 << 1;
-	else /* S-Video */
-		l |= (1 << 0) | (1 << 2);
-
-	if (venc.invert_polarity == false)
-		l |= 1 << 3;
-
-	venc_write_reg(VENC_OUTPUT_CONTROL, l);
-
-	dss_mgr_set_timings(mgr, &venc.timings);
-
-	r = regulator_enable(venc.vdda_dac_reg);
-	if (r)
-		goto err1;
-
-	r = dss_mgr_enable(mgr);
-	if (r)
-		goto err2;
-
-	return 0;
-
-err2:
-	regulator_disable(venc.vdda_dac_reg);
-err1:
-	venc_write_reg(VENC_OUTPUT_CONTROL, 0);
-	dss_set_dac_pwrdn_bgz(0);
-
-	venc_runtime_put();
-err0:
-	return r;
-}
-
-static void venc_power_off(struct omap_dss_device *dssdev)
-{
-	struct omap_overlay_manager *mgr = venc.output.manager;
-
-	venc_write_reg(VENC_OUTPUT_CONTROL, 0);
-	dss_set_dac_pwrdn_bgz(0);
-
-	dss_mgr_disable(mgr);
-
-	regulator_disable(venc.vdda_dac_reg);
-
-	venc_runtime_put();
-}
-
-static int venc_display_enable(struct omap_dss_device *dssdev)
-{
-	struct omap_dss_device *out = &venc.output;
-	int r;
-
-	DSSDBG("venc_display_enable\n");
-
-	mutex_lock(&venc.venc_lock);
-
-	if (out == NULL || out->manager == NULL) {
-		DSSERR("Failed to enable display: no output/manager\n");
-		r = -ENODEV;
-		goto err0;
-	}
-
-	r = venc_power_on(dssdev);
-	if (r)
-		goto err0;
-
-	venc.wss_data = 0;
-
-	mutex_unlock(&venc.venc_lock);
-
-	return 0;
-err0:
-	mutex_unlock(&venc.venc_lock);
-	return r;
-}
-
-static void venc_display_disable(struct omap_dss_device *dssdev)
-{
-	DSSDBG("venc_display_disable\n");
-
-	mutex_lock(&venc.venc_lock);
-
-	venc_power_off(dssdev);
-
-	mutex_unlock(&venc.venc_lock);
-}
-
-static void venc_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	DSSDBG("venc_set_timings\n");
-
-	mutex_lock(&venc.venc_lock);
-
-	/* Reset WSS data when the TV standard changes. */
-	if (memcmp(&venc.timings, timings, sizeof(*timings)))
-		venc.wss_data = 0;
-
-	venc.timings = *timings;
-
-	dispc_set_tv_pclk(13500000);
-
-	mutex_unlock(&venc.venc_lock);
-}
-
-static int venc_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	DSSDBG("venc_check_timings\n");
-
-	if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
-		return 0;
-
-	if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
-		return 0;
-
-	return -EINVAL;
-}
-
-static void venc_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	mutex_lock(&venc.venc_lock);
-
-	*timings = venc.timings;
-
-	mutex_unlock(&venc.venc_lock);
-}
-
-static u32 venc_get_wss(struct omap_dss_device *dssdev)
-{
-	/* Invert due to VENC_L21_WC_CTL:INV=1 */
-	return (venc.wss_data >> 8) ^ 0xfffff;
-}
-
-static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
-{
-	const struct venc_config *config;
-	int r;
-
-	DSSDBG("venc_set_wss\n");
-
-	mutex_lock(&venc.venc_lock);
-
-	config = venc_timings_to_config(&venc.timings);
-
-	/* Invert due to VENC_L21_WC_CTL:INV=1 */
-	venc.wss_data = (wss ^ 0xfffff) << 8;
-
-	r = venc_runtime_get();
-	if (r)
-		goto err;
-
-	venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
-			venc.wss_data);
-
-	venc_runtime_put();
-
-err:
-	mutex_unlock(&venc.venc_lock);
-
-	return r;
-}
-
-static void venc_set_type(struct omap_dss_device *dssdev,
-		enum omap_dss_venc_type type)
-{
-	mutex_lock(&venc.venc_lock);
-
-	venc.type = type;
-
-	mutex_unlock(&venc.venc_lock);
-}
-
-static void venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
-		bool invert_polarity)
-{
-	mutex_lock(&venc.venc_lock);
-
-	venc.invert_polarity = invert_polarity;
-
-	mutex_unlock(&venc.venc_lock);
-}
-
-static int venc_init_regulator(void)
-{
-	struct regulator *vdda_dac;
-
-	if (venc.vdda_dac_reg != NULL)
-		return 0;
-
-	if (venc.pdev->dev.of_node)
-		vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda");
-	else
-		vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac");
-
-	if (IS_ERR(vdda_dac)) {
-		if (PTR_ERR(vdda_dac) != -EPROBE_DEFER)
-			DSSERR("can't get VDDA_DAC regulator\n");
-		return PTR_ERR(vdda_dac);
-	}
-
-	venc.vdda_dac_reg = vdda_dac;
-
-	return 0;
-}
-
-static void venc_dump_regs(struct seq_file *s)
-{
-#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
-
-	if (venc_runtime_get())
-		return;
-
-	DUMPREG(VENC_F_CONTROL);
-	DUMPREG(VENC_VIDOUT_CTRL);
-	DUMPREG(VENC_SYNC_CTRL);
-	DUMPREG(VENC_LLEN);
-	DUMPREG(VENC_FLENS);
-	DUMPREG(VENC_HFLTR_CTRL);
-	DUMPREG(VENC_CC_CARR_WSS_CARR);
-	DUMPREG(VENC_C_PHASE);
-	DUMPREG(VENC_GAIN_U);
-	DUMPREG(VENC_GAIN_V);
-	DUMPREG(VENC_GAIN_Y);
-	DUMPREG(VENC_BLACK_LEVEL);
-	DUMPREG(VENC_BLANK_LEVEL);
-	DUMPREG(VENC_X_COLOR);
-	DUMPREG(VENC_M_CONTROL);
-	DUMPREG(VENC_BSTAMP_WSS_DATA);
-	DUMPREG(VENC_S_CARR);
-	DUMPREG(VENC_LINE21);
-	DUMPREG(VENC_LN_SEL);
-	DUMPREG(VENC_L21__WC_CTL);
-	DUMPREG(VENC_HTRIGGER_VTRIGGER);
-	DUMPREG(VENC_SAVID__EAVID);
-	DUMPREG(VENC_FLEN__FAL);
-	DUMPREG(VENC_LAL__PHASE_RESET);
-	DUMPREG(VENC_HS_INT_START_STOP_X);
-	DUMPREG(VENC_HS_EXT_START_STOP_X);
-	DUMPREG(VENC_VS_INT_START_X);
-	DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
-	DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
-	DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
-	DUMPREG(VENC_VS_EXT_STOP_Y);
-	DUMPREG(VENC_AVID_START_STOP_X);
-	DUMPREG(VENC_AVID_START_STOP_Y);
-	DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
-	DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
-	DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
-	DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
-	DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
-	DUMPREG(VENC_GEN_CTRL);
-	DUMPREG(VENC_OUTPUT_CONTROL);
-	DUMPREG(VENC_OUTPUT_TEST);
-
-	venc_runtime_put();
-
-#undef DUMPREG
-}
-
-static int venc_get_clocks(struct platform_device *pdev)
-{
-	struct clk *clk;
-
-	if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
-		clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
-		if (IS_ERR(clk)) {
-			DSSERR("can't get tv_dac_clk\n");
-			return PTR_ERR(clk);
-		}
-	} else {
-		clk = NULL;
-	}
-
-	venc.tv_dac_clk = clk;
-
-	return 0;
-}
-
-static int venc_connect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	struct omap_overlay_manager *mgr;
-	int r;
-
-	r = venc_init_regulator();
-	if (r)
-		return r;
-
-	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
-	if (!mgr)
-		return -ENODEV;
-
-	r = dss_mgr_connect(mgr, dssdev);
-	if (r)
-		return r;
-
-	r = omapdss_output_set_device(dssdev, dst);
-	if (r) {
-		DSSERR("failed to connect output to new device: %s\n",
-				dst->name);
-		dss_mgr_disconnect(mgr, dssdev);
-		return r;
-	}
-
-	return 0;
-}
-
-static void venc_disconnect(struct omap_dss_device *dssdev,
-		struct omap_dss_device *dst)
-{
-	WARN_ON(dst != dssdev->dst);
-
-	if (dst != dssdev->dst)
-		return;
-
-	omapdss_output_unset_device(dssdev);
-
-	if (dssdev->manager)
-		dss_mgr_disconnect(dssdev->manager, dssdev);
-}
-
-static const struct omapdss_atv_ops venc_ops = {
-	.connect = venc_connect,
-	.disconnect = venc_disconnect,
-
-	.enable = venc_display_enable,
-	.disable = venc_display_disable,
-
-	.check_timings = venc_check_timings,
-	.set_timings = venc_set_timings,
-	.get_timings = venc_get_timings,
-
-	.set_type = venc_set_type,
-	.invert_vid_out_polarity = venc_invert_vid_out_polarity,
-
-	.set_wss = venc_set_wss,
-	.get_wss = venc_get_wss,
-};
-
-static void venc_init_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &venc.output;
-
-	out->dev = &pdev->dev;
-	out->id = OMAP_DSS_OUTPUT_VENC;
-	out->output_type = OMAP_DISPLAY_TYPE_VENC;
-	out->name = "venc.0";
-	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-	out->ops.atv = &venc_ops;
-	out->owner = THIS_MODULE;
-
-	omapdss_register_output(out);
-}
-
-static void __exit venc_uninit_output(struct platform_device *pdev)
-{
-	struct omap_dss_device *out = &venc.output;
-
-	omapdss_unregister_output(out);
-}
-
-static int venc_probe_of(struct platform_device *pdev)
-{
-	struct device_node *node = pdev->dev.of_node;
-	struct device_node *ep;
-	u32 channels;
-	int r;
-
-	ep = omapdss_of_get_first_endpoint(node);
-	if (!ep)
-		return 0;
-
-	venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity");
-
-	r = of_property_read_u32(ep, "ti,channels", &channels);
-	if (r) {
-		dev_err(&pdev->dev,
-			"failed to read property 'ti,channels': %d\n", r);
-		goto err;
-	}
-
-	switch (channels) {
-	case 1:
-		venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
-		break;
-	case 2:
-		venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
-		break;
-	default:
-		dev_err(&pdev->dev, "bad channel propert '%d'\n", channels);
-		r = -EINVAL;
-		goto err;
-	}
-
-	of_node_put(ep);
-
-	return 0;
-err:
-	of_node_put(ep);
-
-	return 0;
-}
-
-/* VENC HW IP initialisation */
-static int omap_venchw_probe(struct platform_device *pdev)
-{
-	u8 rev_id;
-	struct resource *venc_mem;
-	int r;
-
-	venc.pdev = pdev;
-
-	mutex_init(&venc.venc_lock);
-
-	venc.wss_data = 0;
-
-	venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
-	if (!venc_mem) {
-		DSSERR("can't get IORESOURCE_MEM VENC\n");
-		return -EINVAL;
-	}
-
-	venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
-				 resource_size(venc_mem));
-	if (!venc.base) {
-		DSSERR("can't ioremap VENC\n");
-		return -ENOMEM;
-	}
-
-	r = venc_get_clocks(pdev);
-	if (r)
-		return r;
-
-	pm_runtime_enable(&pdev->dev);
-
-	r = venc_runtime_get();
-	if (r)
-		goto err_runtime_get;
-
-	rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
-	dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
-
-	venc_runtime_put();
-
-	if (pdev->dev.of_node) {
-		r = venc_probe_of(pdev);
-		if (r) {
-			DSSERR("Invalid DT data\n");
-			goto err_probe_of;
-		}
-	}
-
-	dss_debugfs_create_file("venc", venc_dump_regs);
-
-	venc_init_output(pdev);
-
-	return 0;
-
-err_probe_of:
-err_runtime_get:
-	pm_runtime_disable(&pdev->dev);
-	return r;
-}
-
-static int __exit omap_venchw_remove(struct platform_device *pdev)
-{
-	venc_uninit_output(pdev);
-
-	pm_runtime_disable(&pdev->dev);
-
-	return 0;
-}
-
-static int venc_runtime_suspend(struct device *dev)
-{
-	if (venc.tv_dac_clk)
-		clk_disable_unprepare(venc.tv_dac_clk);
-
-	dispc_runtime_put();
-
-	return 0;
-}
-
-static int venc_runtime_resume(struct device *dev)
-{
-	int r;
-
-	r = dispc_runtime_get();
-	if (r < 0)
-		return r;
-
-	if (venc.tv_dac_clk)
-		clk_prepare_enable(venc.tv_dac_clk);
-
-	return 0;
-}
-
-static const struct dev_pm_ops venc_pm_ops = {
-	.runtime_suspend = venc_runtime_suspend,
-	.runtime_resume = venc_runtime_resume,
-};
-
-
-static const struct of_device_id venc_of_match[] = {
-	{ .compatible = "ti,omap2-venc", },
-	{ .compatible = "ti,omap3-venc", },
-	{ .compatible = "ti,omap4-venc", },
-	{},
-};
-
-static struct platform_driver omap_venchw_driver = {
-	.probe		= omap_venchw_probe,
-	.remove         = __exit_p(omap_venchw_remove),
-	.driver         = {
-		.name   = "omapdss_venc",
-		.owner  = THIS_MODULE,
-		.pm	= &venc_pm_ops,
-		.of_match_table = venc_of_match,
-	},
-};
-
-int __init venc_init_platform_driver(void)
-{
-	return platform_driver_register(&omap_venchw_driver);
-}
-
-void __exit venc_uninit_platform_driver(void)
-{
-	platform_driver_unregister(&omap_venchw_driver);
-}
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
deleted file mode 100644
index af68cd444d7e..000000000000
--- a/drivers/video/omap2/dss/venc_panel.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * VENC panel driver
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-
-#include <video/omapdss.h>
-
-#include "dss.h"
-
-static struct {
-	struct mutex lock;
-} venc_panel;
-
-static ssize_t display_output_type_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	const char *ret;
-
-	switch (dssdev->phy.venc.type) {
-	case OMAP_DSS_VENC_TYPE_COMPOSITE:
-		ret = "composite";
-		break;
-	case OMAP_DSS_VENC_TYPE_SVIDEO:
-		ret = "svideo";
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", ret);
-}
-
-static ssize_t display_output_type_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	enum omap_dss_venc_type new_type;
-
-	if (sysfs_streq("composite", buf))
-		new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
-	else if (sysfs_streq("svideo", buf))
-		new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
-	else
-		return -EINVAL;
-
-	mutex_lock(&venc_panel.lock);
-
-	if (dssdev->phy.venc.type != new_type) {
-		dssdev->phy.venc.type = new_type;
-		omapdss_venc_set_type(dssdev, new_type);
-		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-			omapdss_venc_display_disable(dssdev);
-			omapdss_venc_display_enable(dssdev);
-		}
-	}
-
-	mutex_unlock(&venc_panel.lock);
-
-	return size;
-}
-
-static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
-		display_output_type_show, display_output_type_store);
-
-static int venc_panel_probe(struct omap_dss_device *dssdev)
-{
-	/* set default timings to PAL */
-	const struct omap_video_timings default_timings = {
-		.x_res		= 720,
-		.y_res		= 574,
-		.pixelclock	= 13500000,
-		.hsw		= 64,
-		.hfp		= 12,
-		.hbp		= 68,
-		.vsw		= 5,
-		.vfp		= 5,
-		.vbp		= 41,
-
-		.vsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-		.hsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-
-		.interlace	= true,
-	};
-
-	mutex_init(&venc_panel.lock);
-
-	dssdev->panel.timings = default_timings;
-
-	return device_create_file(dssdev->dev, &dev_attr_output_type);
-}
-
-static void venc_panel_remove(struct omap_dss_device *dssdev)
-{
-	device_remove_file(dssdev->dev, &dev_attr_output_type);
-}
-
-static int venc_panel_enable(struct omap_dss_device *dssdev)
-{
-	int r;
-
-	dev_dbg(dssdev->dev, "venc_panel_enable\n");
-
-	mutex_lock(&venc_panel.lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
-	omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
-	omapdss_venc_invert_vid_out_polarity(dssdev,
-		dssdev->phy.venc.invert_polarity);
-
-	r = omapdss_venc_display_enable(dssdev);
-	if (r)
-		goto err;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&venc_panel.lock);
-
-	return 0;
-err:
-	mutex_unlock(&venc_panel.lock);
-
-	return r;
-}
-
-static void venc_panel_disable(struct omap_dss_device *dssdev)
-{
-	dev_dbg(dssdev->dev, "venc_panel_disable\n");
-
-	mutex_lock(&venc_panel.lock);
-
-	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
-		goto end;
-
-	omapdss_venc_display_disable(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-end:
-	mutex_unlock(&venc_panel.lock);
-}
-
-static void venc_panel_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	dev_dbg(dssdev->dev, "venc_panel_set_timings\n");
-
-	mutex_lock(&venc_panel.lock);
-
-	omapdss_venc_set_timings(dssdev, timings);
-	dssdev->panel.timings = *timings;
-
-	mutex_unlock(&venc_panel.lock);
-}
-
-static int venc_panel_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	dev_dbg(dssdev->dev, "venc_panel_check_timings\n");
-
-	return omapdss_venc_check_timings(dssdev, timings);
-}
-
-static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
-{
-	dev_dbg(dssdev->dev, "venc_panel_get_wss\n");
-
-	return omapdss_venc_get_wss(dssdev);
-}
-
-static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
-{
-	dev_dbg(dssdev->dev, "venc_panel_set_wss\n");
-
-	return omapdss_venc_set_wss(dssdev, wss);
-}
-
-static struct omap_dss_driver venc_driver = {
-	.probe		= venc_panel_probe,
-	.remove		= venc_panel_remove,
-
-	.enable		= venc_panel_enable,
-	.disable	= venc_panel_disable,
-
-	.get_resolution	= omapdss_default_get_resolution,
-	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
-
-	.set_timings	= venc_panel_set_timings,
-	.check_timings	= venc_panel_check_timings,
-
-	.get_wss	= venc_panel_get_wss,
-	.set_wss	= venc_panel_set_wss,
-
-	.driver         = {
-		.name   = "venc",
-		.owner  = THIS_MODULE,
-	},
-};
-
-int venc_panel_init(void)
-{
-	return omap_dss_register_driver(&venc_driver);
-}
-
-void venc_panel_exit(void)
-{
-	omap_dss_unregister_driver(&venc_driver);
-}
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
deleted file mode 100644
index 4cb12ce68855..000000000000
--- a/drivers/video/omap2/omapfb/Kconfig
+++ /dev/null
@@ -1,27 +0,0 @@
-menuconfig FB_OMAP2
-        tristate "OMAP2+ frame buffer support"
-        depends on FB && OMAP2_DSS && !DRM_OMAP
-
-	select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
-        select FB_CFB_FILLRECT
-        select FB_CFB_COPYAREA
-        select FB_CFB_IMAGEBLIT
-        help
-	  Frame buffer driver for OMAP2+ based boards.
-
-config FB_OMAP2_DEBUG_SUPPORT
-        bool "Debug support for OMAP2+ FB"
-	default y
-	depends on FB_OMAP2
-	help
-	  Support for debug output. You have to enable the actual printing
-	  with 'debug' module parameter.
-
-config FB_OMAP2_NUM_FBS
-	int "Number of framebuffers"
-	range 1 10
-	default 3
-	depends on FB_OMAP2
-	help
-	  Select the number of framebuffers created. OMAP2/3 has 3 overlays
-	  so normally this would be 3.
diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile
deleted file mode 100644
index 51c2e00d9bf8..000000000000
--- a/drivers/video/omap2/omapfb/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_FB_OMAP2) += omapfb.o
-omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
deleted file mode 100644
index 146b6f5428db..000000000000
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ /dev/null
@@ -1,922 +0,0 @@
-/*
- * linux/drivers/video/omap2/omapfb-ioctl.c
- *
- * Copyright (C) 2008 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/fb.h>
-#include <linux/device.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-#include <linux/mm.h>
-#include <linux/omapfb.h>
-#include <linux/vmalloc.h>
-#include <linux/export.h>
-#include <linux/sizes.h>
-
-#include <video/omapdss.h>
-#include <video/omapvrfb.h>
-
-#include "omapfb.h"
-
-static u8 get_mem_idx(struct omapfb_info *ofbi)
-{
-	if (ofbi->id == ofbi->region->id)
-		return 0;
-
-	return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
-}
-
-static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
-						 u8 mem_idx)
-{
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-
-	if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
-		mem_idx &= OMAPFB_MEM_IDX_MASK;
-	else
-		mem_idx = ofbi->id;
-
-	if (mem_idx >= fbdev->num_fbs)
-		return NULL;
-
-	return &fbdev->regions[mem_idx];
-}
-
-static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_overlay *ovl;
-	struct omap_overlay_info old_info;
-	struct omapfb2_mem_region *old_rg, *new_rg;
-	int r = 0;
-
-	DBG("omapfb_setup_plane\n");
-
-	if (ofbi->num_overlays == 0) {
-		r = -EINVAL;
-		goto out;
-	}
-
-	/* XXX uses only the first overlay */
-	ovl = ofbi->overlays[0];
-
-	old_rg = ofbi->region;
-	new_rg = get_mem_region(ofbi, pi->mem_idx);
-	if (!new_rg) {
-		r = -EINVAL;
-		goto out;
-	}
-
-	/* Take the locks in a specific order to keep lockdep happy */
-	if (old_rg->id < new_rg->id) {
-		omapfb_get_mem_region(old_rg);
-		omapfb_get_mem_region(new_rg);
-	} else if (new_rg->id < old_rg->id) {
-		omapfb_get_mem_region(new_rg);
-		omapfb_get_mem_region(old_rg);
-	} else
-		omapfb_get_mem_region(old_rg);
-
-	if (pi->enabled && !new_rg->size) {
-		/*
-		 * This plane's memory was freed, can't enable it
-		 * until it's reallocated.
-		 */
-		r = -EINVAL;
-		goto put_mem;
-	}
-
-	ovl->get_overlay_info(ovl, &old_info);
-
-	if (old_rg != new_rg) {
-		ofbi->region = new_rg;
-		set_fb_fix(fbi);
-	}
-
-	if (!pi->enabled) {
-		r = ovl->disable(ovl);
-		if (r)
-			goto undo;
-	}
-
-	if (pi->enabled) {
-		r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
-			pi->out_width, pi->out_height);
-		if (r)
-			goto undo;
-	} else {
-		struct omap_overlay_info info;
-
-		ovl->get_overlay_info(ovl, &info);
-
-		info.pos_x = pi->pos_x;
-		info.pos_y = pi->pos_y;
-		info.out_width = pi->out_width;
-		info.out_height = pi->out_height;
-
-		r = ovl->set_overlay_info(ovl, &info);
-		if (r)
-			goto undo;
-	}
-
-	if (ovl->manager)
-		ovl->manager->apply(ovl->manager);
-
-	if (pi->enabled) {
-		r = ovl->enable(ovl);
-		if (r)
-			goto undo;
-	}
-
-	/* Release the locks in a specific order to keep lockdep happy */
-	if (old_rg->id > new_rg->id) {
-		omapfb_put_mem_region(old_rg);
-		omapfb_put_mem_region(new_rg);
-	} else if (new_rg->id > old_rg->id) {
-		omapfb_put_mem_region(new_rg);
-		omapfb_put_mem_region(old_rg);
-	} else
-		omapfb_put_mem_region(old_rg);
-
-	return 0;
-
- undo:
-	if (old_rg != new_rg) {
-		ofbi->region = old_rg;
-		set_fb_fix(fbi);
-	}
-
-	ovl->set_overlay_info(ovl, &old_info);
- put_mem:
-	/* Release the locks in a specific order to keep lockdep happy */
-	if (old_rg->id > new_rg->id) {
-		omapfb_put_mem_region(old_rg);
-		omapfb_put_mem_region(new_rg);
-	} else if (new_rg->id > old_rg->id) {
-		omapfb_put_mem_region(new_rg);
-		omapfb_put_mem_region(old_rg);
-	} else
-		omapfb_put_mem_region(old_rg);
- out:
-	dev_err(fbdev->dev, "setup_plane failed\n");
-
-	return r;
-}
-
-static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-
-	if (ofbi->num_overlays == 0) {
-		memset(pi, 0, sizeof(*pi));
-	} else {
-		struct omap_overlay *ovl;
-		struct omap_overlay_info ovli;
-
-		ovl = ofbi->overlays[0];
-		ovl->get_overlay_info(ovl, &ovli);
-
-		pi->pos_x = ovli.pos_x;
-		pi->pos_y = ovli.pos_y;
-		pi->enabled = ovl->is_enabled(ovl);
-		pi->channel_out = 0; /* xxx */
-		pi->mirror = 0;
-		pi->mem_idx = get_mem_idx(ofbi);
-		pi->out_width = ovli.out_width;
-		pi->out_height = ovli.out_height;
-	}
-
-	return 0;
-}
-
-static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_dss_device *display = fb2display(fbi);
-	struct omapfb2_mem_region *rg;
-	int r = 0, i;
-	size_t size;
-
-	if (mi->type != OMAPFB_MEMTYPE_SDRAM)
-		return -EINVAL;
-
-	size = PAGE_ALIGN(mi->size);
-
-	if (display && display->driver->sync)
-		display->driver->sync(display);
-
-	rg = ofbi->region;
-
-	down_write_nested(&rg->lock, rg->id);
-	atomic_inc(&rg->lock_count);
-
-	if (rg->size == size && rg->type == mi->type)
-		goto out;
-
-	if (atomic_read(&rg->map_count)) {
-		r = -EBUSY;
-		goto out;
-	}
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
-		int j;
-
-		if (ofbi2->region != rg)
-			continue;
-
-		for (j = 0; j < ofbi2->num_overlays; j++) {
-			struct omap_overlay *ovl;
-			ovl = ofbi2->overlays[j];
-			if (ovl->is_enabled(ovl)) {
-				r = -EBUSY;
-				goto out;
-			}
-		}
-	}
-
-	r = omapfb_realloc_fbmem(fbi, size, mi->type);
-	if (r) {
-		dev_err(fbdev->dev, "realloc fbmem failed\n");
-		goto out;
-	}
-
- out:
-	atomic_dec(&rg->lock_count);
-	up_write(&rg->lock);
-
-	return r;
-}
-
-static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_mem_region *rg;
-
-	rg = omapfb_get_mem_region(ofbi->region);
-	memset(mi, 0, sizeof(*mi));
-
-	mi->size = rg->size;
-	mi->type = rg->type;
-
-	omapfb_put_mem_region(rg);
-
-	return 0;
-}
-
-static int omapfb_update_window(struct fb_info *fbi,
-		u32 x, u32 y, u32 w, u32 h)
-{
-	struct omap_dss_device *display = fb2display(fbi);
-	u16 dw, dh;
-
-	if (!display)
-		return 0;
-
-	if (w == 0 || h == 0)
-		return 0;
-
-	display->driver->get_resolution(display, &dw, &dh);
-
-	if (x + w > dw || y + h > dh)
-		return -EINVAL;
-
-	return display->driver->update(display, x, y, w, h);
-}
-
-int omapfb_set_update_mode(struct fb_info *fbi,
-				   enum omapfb_update_mode mode)
-{
-	struct omap_dss_device *display = fb2display(fbi);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omapfb_display_data *d;
-	int r;
-
-	if (!display)
-		return -EINVAL;
-
-	if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
-		return -EINVAL;
-
-	omapfb_lock(fbdev);
-
-	d = get_display_data(fbdev, display);
-
-	if (d->update_mode == mode) {
-		omapfb_unlock(fbdev);
-		return 0;
-	}
-
-	r = 0;
-
-	if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-		if (mode == OMAPFB_AUTO_UPDATE)
-			omapfb_start_auto_update(fbdev, display);
-		else /* MANUAL_UPDATE */
-			omapfb_stop_auto_update(fbdev, display);
-
-		d->update_mode = mode;
-	} else { /* AUTO_UPDATE */
-		if (mode == OMAPFB_MANUAL_UPDATE)
-			r = -EINVAL;
-	}
-
-	omapfb_unlock(fbdev);
-
-	return r;
-}
-
-int omapfb_get_update_mode(struct fb_info *fbi,
-		enum omapfb_update_mode *mode)
-{
-	struct omap_dss_device *display = fb2display(fbi);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omapfb_display_data *d;
-
-	if (!display)
-		return -EINVAL;
-
-	omapfb_lock(fbdev);
-
-	d = get_display_data(fbdev, display);
-
-	*mode = d->update_mode;
-
-	omapfb_unlock(fbdev);
-
-	return 0;
-}
-
-/* XXX this color key handling is a hack... */
-static struct omapfb_color_key omapfb_color_keys[2];
-
-static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
-		struct omapfb_color_key *ck)
-{
-	struct omap_overlay_manager_info info;
-	enum omap_dss_trans_key_type kt;
-	int r;
-
-	mgr->get_manager_info(mgr, &info);
-
-	if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
-		info.trans_enabled = false;
-		omapfb_color_keys[mgr->id] = *ck;
-
-		r = mgr->set_manager_info(mgr, &info);
-		if (r)
-			return r;
-
-		r = mgr->apply(mgr);
-
-		return r;
-	}
-
-	switch (ck->key_type) {
-	case OMAPFB_COLOR_KEY_GFX_DST:
-		kt = OMAP_DSS_COLOR_KEY_GFX_DST;
-		break;
-	case OMAPFB_COLOR_KEY_VID_SRC:
-		kt = OMAP_DSS_COLOR_KEY_VID_SRC;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	info.default_color = ck->background;
-	info.trans_key = ck->trans_key;
-	info.trans_key_type = kt;
-	info.trans_enabled = true;
-
-	omapfb_color_keys[mgr->id] = *ck;
-
-	r = mgr->set_manager_info(mgr, &info);
-	if (r)
-		return r;
-
-	r = mgr->apply(mgr);
-
-	return r;
-}
-
-static int omapfb_set_color_key(struct fb_info *fbi,
-		struct omapfb_color_key *ck)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	int r;
-	int i;
-	struct omap_overlay_manager *mgr = NULL;
-
-	omapfb_lock(fbdev);
-
-	for (i = 0; i < ofbi->num_overlays; i++) {
-		if (ofbi->overlays[i]->manager) {
-			mgr = ofbi->overlays[i]->manager;
-			break;
-		}
-	}
-
-	if (!mgr) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	r = _omapfb_set_color_key(mgr, ck);
-err:
-	omapfb_unlock(fbdev);
-
-	return r;
-}
-
-static int omapfb_get_color_key(struct fb_info *fbi,
-		struct omapfb_color_key *ck)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_overlay_manager *mgr = NULL;
-	int r = 0;
-	int i;
-
-	omapfb_lock(fbdev);
-
-	for (i = 0; i < ofbi->num_overlays; i++) {
-		if (ofbi->overlays[i]->manager) {
-			mgr = ofbi->overlays[i]->manager;
-			break;
-		}
-	}
-
-	if (!mgr) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	*ck = omapfb_color_keys[mgr->id];
-err:
-	omapfb_unlock(fbdev);
-
-	return r;
-}
-
-static int omapfb_memory_read(struct fb_info *fbi,
-		struct omapfb_memory_read *mr)
-{
-	struct omap_dss_device *display = fb2display(fbi);
-	void *buf;
-	int r;
-
-	if (!display || !display->driver->memory_read)
-		return -ENOENT;
-
-	if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
-		return -EFAULT;
-
-	if (mr->w * mr->h * 3 > mr->buffer_size)
-		return -EINVAL;
-
-	buf = vmalloc(mr->buffer_size);
-	if (!buf) {
-		DBG("vmalloc failed\n");
-		return -ENOMEM;
-	}
-
-	r = display->driver->memory_read(display, buf, mr->buffer_size,
-			mr->x, mr->y, mr->w, mr->h);
-
-	if (r > 0) {
-		if (copy_to_user(mr->buffer, buf, mr->buffer_size))
-			r = -EFAULT;
-	}
-
-	vfree(buf);
-
-	return r;
-}
-
-static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
-			     struct omapfb_ovl_colormode *mode)
-{
-	int ovl_idx = mode->overlay_idx;
-	int mode_idx = mode->mode_idx;
-	struct omap_overlay *ovl;
-	enum omap_color_mode supported_modes;
-	struct fb_var_screeninfo var;
-	int i;
-
-	if (ovl_idx >= fbdev->num_overlays)
-		return -ENODEV;
-	ovl = fbdev->overlays[ovl_idx];
-	supported_modes = ovl->supported_modes;
-
-	mode_idx = mode->mode_idx;
-
-	for (i = 0; i < sizeof(supported_modes) * 8; i++) {
-		if (!(supported_modes & (1 << i)))
-			continue;
-		/*
-		 * It's possible that the FB doesn't support a mode
-		 * that is supported by the overlay, so call the
-		 * following here.
-		 */
-		if (dss_mode_to_fb_mode(1 << i, &var) < 0)
-			continue;
-
-		mode_idx--;
-		if (mode_idx < 0)
-			break;
-	}
-
-	if (i == sizeof(supported_modes) * 8)
-		return -ENOENT;
-
-	mode->bits_per_pixel = var.bits_per_pixel;
-	mode->nonstd = var.nonstd;
-	mode->red = var.red;
-	mode->green = var.green;
-	mode->blue = var.blue;
-	mode->transp = var.transp;
-
-	return 0;
-}
-
-static int omapfb_wait_for_go(struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	int r = 0;
-	int i;
-
-	for (i = 0; i < ofbi->num_overlays; ++i) {
-		struct omap_overlay *ovl = ofbi->overlays[i];
-		r = ovl->wait_for_go(ovl);
-		if (r)
-			break;
-	}
-
-	return r;
-}
-
-int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_dss_device *display = fb2display(fbi);
-	struct omap_overlay_manager *mgr;
-
-	union {
-		struct omapfb_update_window_old	uwnd_o;
-		struct omapfb_update_window	uwnd;
-		struct omapfb_plane_info	plane_info;
-		struct omapfb_caps		caps;
-		struct omapfb_mem_info          mem_info;
-		struct omapfb_color_key		color_key;
-		struct omapfb_ovl_colormode	ovl_colormode;
-		enum omapfb_update_mode		update_mode;
-		int test_num;
-		struct omapfb_memory_read	memory_read;
-		struct omapfb_vram_info		vram_info;
-		struct omapfb_tearsync_info	tearsync_info;
-		struct omapfb_display_info	display_info;
-		u32				crt;
-	} p;
-
-	int r = 0;
-
-	switch (cmd) {
-	case OMAPFB_SYNC_GFX:
-		DBG("ioctl SYNC_GFX\n");
-		if (!display || !display->driver->sync) {
-			/* DSS1 never returns an error here, so we neither */
-			/*r = -EINVAL;*/
-			break;
-		}
-
-		r = display->driver->sync(display);
-		break;
-
-	case OMAPFB_UPDATE_WINDOW_OLD:
-		DBG("ioctl UPDATE_WINDOW_OLD\n");
-		if (!display || !display->driver->update) {
-			r = -EINVAL;
-			break;
-		}
-
-		if (copy_from_user(&p.uwnd_o,
-					(void __user *)arg,
-					sizeof(p.uwnd_o))) {
-			r = -EFAULT;
-			break;
-		}
-
-		r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
-				p.uwnd_o.width, p.uwnd_o.height);
-		break;
-
-	case OMAPFB_UPDATE_WINDOW:
-		DBG("ioctl UPDATE_WINDOW\n");
-		if (!display || !display->driver->update) {
-			r = -EINVAL;
-			break;
-		}
-
-		if (copy_from_user(&p.uwnd, (void __user *)arg,
-					sizeof(p.uwnd))) {
-			r = -EFAULT;
-			break;
-		}
-
-		r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
-				p.uwnd.width, p.uwnd.height);
-		break;
-
-	case OMAPFB_SETUP_PLANE:
-		DBG("ioctl SETUP_PLANE\n");
-		if (copy_from_user(&p.plane_info, (void __user *)arg,
-					sizeof(p.plane_info)))
-			r = -EFAULT;
-		else
-			r = omapfb_setup_plane(fbi, &p.plane_info);
-		break;
-
-	case OMAPFB_QUERY_PLANE:
-		DBG("ioctl QUERY_PLANE\n");
-		r = omapfb_query_plane(fbi, &p.plane_info);
-		if (r < 0)
-			break;
-		if (copy_to_user((void __user *)arg, &p.plane_info,
-					sizeof(p.plane_info)))
-			r = -EFAULT;
-		break;
-
-	case OMAPFB_SETUP_MEM:
-		DBG("ioctl SETUP_MEM\n");
-		if (copy_from_user(&p.mem_info, (void __user *)arg,
-					sizeof(p.mem_info)))
-			r = -EFAULT;
-		else
-			r = omapfb_setup_mem(fbi, &p.mem_info);
-		break;
-
-	case OMAPFB_QUERY_MEM:
-		DBG("ioctl QUERY_MEM\n");
-		r = omapfb_query_mem(fbi, &p.mem_info);
-		if (r < 0)
-			break;
-		if (copy_to_user((void __user *)arg, &p.mem_info,
-					sizeof(p.mem_info)))
-			r = -EFAULT;
-		break;
-
-	case OMAPFB_GET_CAPS:
-		DBG("ioctl GET_CAPS\n");
-		if (!display) {
-			r = -EINVAL;
-			break;
-		}
-
-		memset(&p.caps, 0, sizeof(p.caps));
-		if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
-			p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE;
-		if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM)
-			p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC;
-
-		if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
-			r = -EFAULT;
-		break;
-
-	case OMAPFB_GET_OVERLAY_COLORMODE:
-		DBG("ioctl GET_OVERLAY_COLORMODE\n");
-		if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
-				   sizeof(p.ovl_colormode))) {
-			r = -EFAULT;
-			break;
-		}
-		r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
-		if (r < 0)
-			break;
-		if (copy_to_user((void __user *)arg, &p.ovl_colormode,
-				 sizeof(p.ovl_colormode)))
-			r = -EFAULT;
-		break;
-
-	case OMAPFB_SET_UPDATE_MODE:
-		DBG("ioctl SET_UPDATE_MODE\n");
-		if (get_user(p.update_mode, (int __user *)arg))
-			r = -EFAULT;
-		else
-			r = omapfb_set_update_mode(fbi, p.update_mode);
-		break;
-
-	case OMAPFB_GET_UPDATE_MODE:
-		DBG("ioctl GET_UPDATE_MODE\n");
-		r = omapfb_get_update_mode(fbi, &p.update_mode);
-		if (r)
-			break;
-		if (put_user(p.update_mode,
-					(enum omapfb_update_mode __user *)arg))
-			r = -EFAULT;
-		break;
-
-	case OMAPFB_SET_COLOR_KEY:
-		DBG("ioctl SET_COLOR_KEY\n");
-		if (copy_from_user(&p.color_key, (void __user *)arg,
-				   sizeof(p.color_key)))
-			r = -EFAULT;
-		else
-			r = omapfb_set_color_key(fbi, &p.color_key);
-		break;
-
-	case OMAPFB_GET_COLOR_KEY:
-		DBG("ioctl GET_COLOR_KEY\n");
-		r = omapfb_get_color_key(fbi, &p.color_key);
-		if (r)
-			break;
-		if (copy_to_user((void __user *)arg, &p.color_key,
-				 sizeof(p.color_key)))
-			r = -EFAULT;
-		break;
-
-	case FBIO_WAITFORVSYNC:
-		if (get_user(p.crt, (__u32 __user *)arg)) {
-			r = -EFAULT;
-			break;
-		}
-		if (p.crt != 0) {
-			r = -ENODEV;
-			break;
-		}
-		/* FALLTHROUGH */
-
-	case OMAPFB_WAITFORVSYNC:
-		DBG("ioctl WAITFORVSYNC\n");
-
-		if (!display) {
-			r = -EINVAL;
-			break;
-		}
-
-		mgr = omapdss_find_mgr_from_display(display);
-		if (!mgr) {
-			r = -EINVAL;
-			break;
-		}
-
-		r = mgr->wait_for_vsync(mgr);
-		break;
-
-	case OMAPFB_WAITFORGO:
-		DBG("ioctl WAITFORGO\n");
-		if (!display) {
-			r = -EINVAL;
-			break;
-		}
-
-		r = omapfb_wait_for_go(fbi);
-		break;
-
-	/* LCD and CTRL tests do the same thing for backward
-	 * compatibility */
-	case OMAPFB_LCD_TEST:
-		DBG("ioctl LCD_TEST\n");
-		if (get_user(p.test_num, (int __user *)arg)) {
-			r = -EFAULT;
-			break;
-		}
-		if (!display || !display->driver->run_test) {
-			r = -EINVAL;
-			break;
-		}
-
-		r = display->driver->run_test(display, p.test_num);
-
-		break;
-
-	case OMAPFB_CTRL_TEST:
-		DBG("ioctl CTRL_TEST\n");
-		if (get_user(p.test_num, (int __user *)arg)) {
-			r = -EFAULT;
-			break;
-		}
-		if (!display || !display->driver->run_test) {
-			r = -EINVAL;
-			break;
-		}
-
-		r = display->driver->run_test(display, p.test_num);
-
-		break;
-
-	case OMAPFB_MEMORY_READ:
-		DBG("ioctl MEMORY_READ\n");
-
-		if (copy_from_user(&p.memory_read, (void __user *)arg,
-					sizeof(p.memory_read))) {
-			r = -EFAULT;
-			break;
-		}
-
-		r = omapfb_memory_read(fbi, &p.memory_read);
-
-		break;
-
-	case OMAPFB_GET_VRAM_INFO: {
-		DBG("ioctl GET_VRAM_INFO\n");
-
-		/*
-		 * We don't have the ability to get this vram info anymore.
-		 * Fill in something that should keep the applications working.
-		 */
-		p.vram_info.total = SZ_1M * 64;
-		p.vram_info.free = SZ_1M * 64;
-		p.vram_info.largest_free_block = SZ_1M * 64;
-
-		if (copy_to_user((void __user *)arg, &p.vram_info,
-					sizeof(p.vram_info)))
-			r = -EFAULT;
-		break;
-	}
-
-	case OMAPFB_SET_TEARSYNC: {
-		DBG("ioctl SET_TEARSYNC\n");
-
-		if (copy_from_user(&p.tearsync_info, (void __user *)arg,
-					sizeof(p.tearsync_info))) {
-			r = -EFAULT;
-			break;
-		}
-
-		if (!display || !display->driver->enable_te) {
-			r = -ENODEV;
-			break;
-		}
-
-		r = display->driver->enable_te(display,
-				!!p.tearsync_info.enabled);
-
-		break;
-	}
-
-	case OMAPFB_GET_DISPLAY_INFO: {
-		u16 xres, yres;
-
-		DBG("ioctl GET_DISPLAY_INFO\n");
-
-		if (display == NULL) {
-			r = -ENODEV;
-			break;
-		}
-
-		display->driver->get_resolution(display, &xres, &yres);
-
-		p.display_info.xres = xres;
-		p.display_info.yres = yres;
-
-		if (display->driver->get_dimensions) {
-			u32 w, h;
-			display->driver->get_dimensions(display, &w, &h);
-			p.display_info.width = w;
-			p.display_info.height = h;
-		} else {
-			p.display_info.width = 0;
-			p.display_info.height = 0;
-		}
-
-		if (copy_to_user((void __user *)arg, &p.display_info,
-					sizeof(p.display_info)))
-			r = -EFAULT;
-		break;
-	}
-
-	default:
-		dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
-		r = -EINVAL;
-	}
-
-	if (r < 0)
-		DBG("ioctl failed: %d\n", r);
-
-	return r;
-}
-
-
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
deleted file mode 100644
index ec2d132c782d..000000000000
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ /dev/null
@@ -1,2656 +0,0 @@
-/*
- * linux/drivers/video/omap2/omapfb-main.c
- *
- * Copyright (C) 2008 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/omapfb.h>
-
-#include <video/omapdss.h>
-#include <video/omapvrfb.h>
-
-#include "omapfb.h"
-
-#define MODULE_NAME     "omapfb"
-
-#define OMAPFB_PLANE_XRES_MIN		8
-#define OMAPFB_PLANE_YRES_MIN		8
-
-static char *def_mode;
-static char *def_vram;
-static bool def_vrfb;
-static int def_rotate;
-static bool def_mirror;
-static bool auto_update;
-static unsigned int auto_update_freq;
-module_param(auto_update, bool, 0);
-module_param(auto_update_freq, uint, 0644);
-
-#ifdef DEBUG
-bool omapfb_debug;
-module_param_named(debug, omapfb_debug, bool, 0644);
-static bool omapfb_test_pattern;
-module_param_named(test, omapfb_test_pattern, bool, 0644);
-#endif
-
-static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
-static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
-		struct omap_dss_device *dssdev);
-
-#ifdef DEBUG
-static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
-{
-	struct fb_var_screeninfo *var = &fbi->var;
-	struct fb_fix_screeninfo *fix = &fbi->fix;
-	void __iomem *addr = fbi->screen_base;
-	const unsigned bytespp = var->bits_per_pixel >> 3;
-	const unsigned line_len = fix->line_length / bytespp;
-
-	int r = (color >> 16) & 0xff;
-	int g = (color >> 8) & 0xff;
-	int b = (color >> 0) & 0xff;
-
-	if (var->bits_per_pixel == 16) {
-		u16 __iomem *p = (u16 __iomem *)addr;
-		p += y * line_len + x;
-
-		r = r * 32 / 256;
-		g = g * 64 / 256;
-		b = b * 32 / 256;
-
-		__raw_writew((r << 11) | (g << 5) | (b << 0), p);
-	} else if (var->bits_per_pixel == 24) {
-		u8 __iomem *p = (u8 __iomem *)addr;
-		p += (y * line_len + x) * 3;
-
-		__raw_writeb(b, p + 0);
-		__raw_writeb(g, p + 1);
-		__raw_writeb(r, p + 2);
-	} else if (var->bits_per_pixel == 32) {
-		u32 __iomem *p = (u32 __iomem *)addr;
-		p += y * line_len + x;
-		__raw_writel(color, p);
-	}
-}
-
-static void fill_fb(struct fb_info *fbi)
-{
-	struct fb_var_screeninfo *var = &fbi->var;
-	const short w = var->xres_virtual;
-	const short h = var->yres_virtual;
-	void __iomem *addr = fbi->screen_base;
-	int y, x;
-
-	if (!addr)
-		return;
-
-	DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
-
-	for (y = 0; y < h; y++) {
-		for (x = 0; x < w; x++) {
-			if (x < 20 && y < 20)
-				draw_pixel(fbi, x, y, 0xffffff);
-			else if (x < 20 && (y > 20 && y < h - 20))
-				draw_pixel(fbi, x, y, 0xff);
-			else if (y < 20 && (x > 20 && x < w - 20))
-				draw_pixel(fbi, x, y, 0xff00);
-			else if (x > w - 20 && (y > 20 && y < h - 20))
-				draw_pixel(fbi, x, y, 0xff0000);
-			else if (y > h - 20 && (x > 20 && x < w - 20))
-				draw_pixel(fbi, x, y, 0xffff00);
-			else if (x == 20 || x == w - 20 ||
-					y == 20 || y == h - 20)
-				draw_pixel(fbi, x, y, 0xffffff);
-			else if (x == y || w - x == h - y)
-				draw_pixel(fbi, x, y, 0xff00ff);
-			else if (w - x == y || x == h - y)
-				draw_pixel(fbi, x, y, 0x00ffff);
-			else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
-				int t = x * 3 / w;
-				unsigned r = 0, g = 0, b = 0;
-				unsigned c;
-				if (var->bits_per_pixel == 16) {
-					if (t == 0)
-						b = (y % 32) * 256 / 32;
-					else if (t == 1)
-						g = (y % 64) * 256 / 64;
-					else if (t == 2)
-						r = (y % 32) * 256 / 32;
-				} else {
-					if (t == 0)
-						b = (y % 256);
-					else if (t == 1)
-						g = (y % 256);
-					else if (t == 2)
-						r = (y % 256);
-				}
-				c = (r << 16) | (g << 8) | (b << 0);
-				draw_pixel(fbi, x, y, c);
-			} else {
-				draw_pixel(fbi, x, y, 0);
-			}
-		}
-	}
-}
-#endif
-
-static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
-{
-	const struct vrfb *vrfb = &ofbi->region->vrfb;
-	unsigned offset;
-
-	switch (rot) {
-	case FB_ROTATE_UR:
-		offset = 0;
-		break;
-	case FB_ROTATE_CW:
-		offset = vrfb->yoffset;
-		break;
-	case FB_ROTATE_UD:
-		offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
-		break;
-	case FB_ROTATE_CCW:
-		offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
-		break;
-	default:
-		BUG();
-		return 0;
-	}
-
-	offset *= vrfb->bytespp;
-
-	return offset;
-}
-
-static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
-{
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-		return ofbi->region->vrfb.paddr[rot]
-			+ omapfb_get_vrfb_offset(ofbi, rot);
-	} else {
-		return ofbi->region->paddr;
-	}
-}
-
-static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
-{
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		return ofbi->region->vrfb.paddr[0];
-	else
-		return ofbi->region->paddr;
-}
-
-static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
-{
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		return ofbi->region->vrfb.vaddr[0];
-	else
-		return ofbi->region->vaddr;
-}
-
-static struct omapfb_colormode omapfb_colormodes[] = {
-	{
-		.dssmode = OMAP_DSS_COLOR_UYVY,
-		.bits_per_pixel = 16,
-		.nonstd = OMAPFB_COLOR_YUV422,
-	}, {
-		.dssmode = OMAP_DSS_COLOR_YUV2,
-		.bits_per_pixel = 16,
-		.nonstd = OMAPFB_COLOR_YUY422,
-	}, {
-		.dssmode = OMAP_DSS_COLOR_ARGB16,
-		.bits_per_pixel = 16,
-		.red	= { .length = 4, .offset = 8, .msb_right = 0 },
-		.green	= { .length = 4, .offset = 4, .msb_right = 0 },
-		.blue	= { .length = 4, .offset = 0, .msb_right = 0 },
-		.transp	= { .length = 4, .offset = 12, .msb_right = 0 },
-	}, {
-		.dssmode = OMAP_DSS_COLOR_RGB16,
-		.bits_per_pixel = 16,
-		.red	= { .length = 5, .offset = 11, .msb_right = 0 },
-		.green	= { .length = 6, .offset = 5, .msb_right = 0 },
-		.blue	= { .length = 5, .offset = 0, .msb_right = 0 },
-		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
-	}, {
-		.dssmode = OMAP_DSS_COLOR_RGB24P,
-		.bits_per_pixel = 24,
-		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
-		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
-		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
-		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
-	}, {
-		.dssmode = OMAP_DSS_COLOR_RGB24U,
-		.bits_per_pixel = 32,
-		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
-		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
-		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
-		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
-	}, {
-		.dssmode = OMAP_DSS_COLOR_ARGB32,
-		.bits_per_pixel = 32,
-		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
-		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
-		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
-		.transp	= { .length = 8, .offset = 24, .msb_right = 0 },
-	}, {
-		.dssmode = OMAP_DSS_COLOR_RGBA32,
-		.bits_per_pixel = 32,
-		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
-		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
-		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
-		.transp	= { .length = 8, .offset = 0, .msb_right = 0 },
-	}, {
-		.dssmode = OMAP_DSS_COLOR_RGBX32,
-		.bits_per_pixel = 32,
-		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
-		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
-		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
-		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
-	},
-};
-
-static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
-		struct omapfb_colormode *color)
-{
-	bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
-	{
-		return f1->length == f2->length &&
-			f1->offset == f2->offset &&
-			f1->msb_right == f2->msb_right;
-	}
-
-	if (var->bits_per_pixel == 0 ||
-			var->red.length == 0 ||
-			var->blue.length == 0 ||
-			var->green.length == 0)
-		return 0;
-
-	return var->bits_per_pixel == color->bits_per_pixel &&
-		cmp_component(&var->red, &color->red) &&
-		cmp_component(&var->green, &color->green) &&
-		cmp_component(&var->blue, &color->blue) &&
-		cmp_component(&var->transp, &color->transp);
-}
-
-static void assign_colormode_to_var(struct fb_var_screeninfo *var,
-		struct omapfb_colormode *color)
-{
-	var->bits_per_pixel = color->bits_per_pixel;
-	var->nonstd = color->nonstd;
-	var->red = color->red;
-	var->green = color->green;
-	var->blue = color->blue;
-	var->transp = color->transp;
-}
-
-static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
-		enum omap_color_mode *mode)
-{
-	enum omap_color_mode dssmode;
-	int i;
-
-	/* first match with nonstd field */
-	if (var->nonstd) {
-		for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
-			struct omapfb_colormode *m = &omapfb_colormodes[i];
-			if (var->nonstd == m->nonstd) {
-				assign_colormode_to_var(var, m);
-				*mode = m->dssmode;
-				return 0;
-			}
-		}
-
-		return -EINVAL;
-	}
-
-	/* then try exact match of bpp and colors */
-	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
-		struct omapfb_colormode *m = &omapfb_colormodes[i];
-		if (cmp_var_to_colormode(var, m)) {
-			assign_colormode_to_var(var, m);
-			*mode = m->dssmode;
-			return 0;
-		}
-	}
-
-	/* match with bpp if user has not filled color fields
-	 * properly */
-	switch (var->bits_per_pixel) {
-	case 1:
-		dssmode = OMAP_DSS_COLOR_CLUT1;
-		break;
-	case 2:
-		dssmode = OMAP_DSS_COLOR_CLUT2;
-		break;
-	case 4:
-		dssmode = OMAP_DSS_COLOR_CLUT4;
-		break;
-	case 8:
-		dssmode = OMAP_DSS_COLOR_CLUT8;
-		break;
-	case 12:
-		dssmode = OMAP_DSS_COLOR_RGB12U;
-		break;
-	case 16:
-		dssmode = OMAP_DSS_COLOR_RGB16;
-		break;
-	case 24:
-		dssmode = OMAP_DSS_COLOR_RGB24P;
-		break;
-	case 32:
-		dssmode = OMAP_DSS_COLOR_RGB24U;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
-		struct omapfb_colormode *m = &omapfb_colormodes[i];
-		if (dssmode == m->dssmode) {
-			assign_colormode_to_var(var, m);
-			*mode = m->dssmode;
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-static int check_fb_res_bounds(struct fb_var_screeninfo *var)
-{
-	int xres_min = OMAPFB_PLANE_XRES_MIN;
-	int xres_max = 2048;
-	int yres_min = OMAPFB_PLANE_YRES_MIN;
-	int yres_max = 2048;
-
-	/* XXX: some applications seem to set virtual res to 0. */
-	if (var->xres_virtual == 0)
-		var->xres_virtual = var->xres;
-
-	if (var->yres_virtual == 0)
-		var->yres_virtual = var->yres;
-
-	if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
-		return -EINVAL;
-
-	if (var->xres < xres_min)
-		var->xres = xres_min;
-	if (var->yres < yres_min)
-		var->yres = yres_min;
-	if (var->xres > xres_max)
-		var->xres = xres_max;
-	if (var->yres > yres_max)
-		var->yres = yres_max;
-
-	if (var->xres > var->xres_virtual)
-		var->xres = var->xres_virtual;
-	if (var->yres > var->yres_virtual)
-		var->yres = var->yres_virtual;
-
-	return 0;
-}
-
-static void shrink_height(unsigned long max_frame_size,
-		struct fb_var_screeninfo *var)
-{
-	DBG("can't fit FB into memory, reducing y\n");
-	var->yres_virtual = max_frame_size /
-		(var->xres_virtual * var->bits_per_pixel >> 3);
-
-	if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
-		var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
-
-	if (var->yres > var->yres_virtual)
-		var->yres = var->yres_virtual;
-}
-
-static void shrink_width(unsigned long max_frame_size,
-		struct fb_var_screeninfo *var)
-{
-	DBG("can't fit FB into memory, reducing x\n");
-	var->xres_virtual = max_frame_size / var->yres_virtual /
-		(var->bits_per_pixel >> 3);
-
-	if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
-		var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
-
-	if (var->xres > var->xres_virtual)
-		var->xres = var->xres_virtual;
-}
-
-static int check_vrfb_fb_size(unsigned long region_size,
-		const struct fb_var_screeninfo *var)
-{
-	unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
-		var->yres_virtual, var->bits_per_pixel >> 3);
-
-	return min_phys_size > region_size ? -EINVAL : 0;
-}
-
-static int check_fb_size(const struct omapfb_info *ofbi,
-		struct fb_var_screeninfo *var)
-{
-	unsigned long max_frame_size = ofbi->region->size;
-	int bytespp = var->bits_per_pixel >> 3;
-	unsigned long line_size = var->xres_virtual * bytespp;
-
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-		/* One needs to check for both VRFB and OMAPFB limitations. */
-		if (check_vrfb_fb_size(max_frame_size, var))
-			shrink_height(omap_vrfb_max_height(
-				max_frame_size, var->xres_virtual, bytespp) *
-				line_size, var);
-
-		if (check_vrfb_fb_size(max_frame_size, var)) {
-			DBG("cannot fit FB to memory\n");
-			return -EINVAL;
-		}
-
-		return 0;
-	}
-
-	DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
-
-	if (line_size * var->yres_virtual > max_frame_size)
-		shrink_height(max_frame_size, var);
-
-	if (line_size * var->yres_virtual > max_frame_size) {
-		shrink_width(max_frame_size, var);
-		line_size = var->xres_virtual * bytespp;
-	}
-
-	if (line_size * var->yres_virtual > max_frame_size) {
-		DBG("cannot fit FB to memory\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
- * Consider if VRFB assisted rotation is in use and if the virtual space for
- * the zero degree view needs to be mapped. The need for mapping also acts as
- * the trigger for setting up the hardware on the context in question. This
- * ensures that one does not attempt to access the virtual view before the
- * hardware is serving the address translations.
- */
-static int setup_vrfb_rotation(struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_mem_region *rg = ofbi->region;
-	struct vrfb *vrfb = &rg->vrfb;
-	struct fb_var_screeninfo *var = &fbi->var;
-	struct fb_fix_screeninfo *fix = &fbi->fix;
-	unsigned bytespp;
-	bool yuv_mode;
-	enum omap_color_mode mode;
-	int r;
-	bool reconf;
-
-	if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
-		return 0;
-
-	DBG("setup_vrfb_rotation\n");
-
-	r = fb_mode_to_dss_mode(var, &mode);
-	if (r)
-		return r;
-
-	bytespp = var->bits_per_pixel >> 3;
-
-	yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
-
-	/* We need to reconfigure VRFB if the resolution changes, if yuv mode
-	 * is enabled/disabled, or if bytes per pixel changes */
-
-	/* XXX we shouldn't allow this when framebuffer is mmapped */
-
-	reconf = false;
-
-	if (yuv_mode != vrfb->yuv_mode)
-		reconf = true;
-	else if (bytespp != vrfb->bytespp)
-		reconf = true;
-	else if (vrfb->xres != var->xres_virtual ||
-			vrfb->yres != var->yres_virtual)
-		reconf = true;
-
-	if (vrfb->vaddr[0] && reconf) {
-		fbi->screen_base = NULL;
-		fix->smem_start = 0;
-		fix->smem_len = 0;
-		iounmap(vrfb->vaddr[0]);
-		vrfb->vaddr[0] = NULL;
-		DBG("setup_vrfb_rotation: reset fb\n");
-	}
-
-	if (vrfb->vaddr[0])
-		return 0;
-
-	omap_vrfb_setup(&rg->vrfb, rg->paddr,
-			var->xres_virtual,
-			var->yres_virtual,
-			bytespp, yuv_mode);
-
-	/* Now one can ioremap the 0 angle view */
-	r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
-	if (r)
-		return r;
-
-	/* used by open/write in fbmem.c */
-	fbi->screen_base = ofbi->region->vrfb.vaddr[0];
-
-	fix->smem_start = ofbi->region->vrfb.paddr[0];
-
-	switch (var->nonstd) {
-	case OMAPFB_COLOR_YUV422:
-	case OMAPFB_COLOR_YUY422:
-		fix->line_length =
-			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
-		break;
-	default:
-		fix->line_length =
-			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
-		break;
-	}
-
-	fix->smem_len = var->yres_virtual * fix->line_length;
-
-	return 0;
-}
-
-int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
-			struct fb_var_screeninfo *var)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
-		struct omapfb_colormode *mode = &omapfb_colormodes[i];
-		if (dssmode == mode->dssmode) {
-			assign_colormode_to_var(var, mode);
-			return 0;
-		}
-	}
-	return -ENOENT;
-}
-
-void set_fb_fix(struct fb_info *fbi)
-{
-	struct fb_fix_screeninfo *fix = &fbi->fix;
-	struct fb_var_screeninfo *var = &fbi->var;
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_mem_region *rg = ofbi->region;
-
-	DBG("set_fb_fix\n");
-
-	/* used by open/write in fbmem.c */
-	fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
-
-	/* used by mmap in fbmem.c */
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-		switch (var->nonstd) {
-		case OMAPFB_COLOR_YUV422:
-		case OMAPFB_COLOR_YUY422:
-			fix->line_length =
-				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
-			break;
-		default:
-			fix->line_length =
-				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
-			break;
-		}
-
-		fix->smem_len = var->yres_virtual * fix->line_length;
-	} else {
-		fix->line_length =
-			(var->xres_virtual * var->bits_per_pixel) >> 3;
-		fix->smem_len = rg->size;
-	}
-
-	fix->smem_start = omapfb_get_region_paddr(ofbi);
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-
-	if (var->nonstd)
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else {
-		switch (var->bits_per_pixel) {
-		case 32:
-		case 24:
-		case 16:
-		case 12:
-			fix->visual = FB_VISUAL_TRUECOLOR;
-			/* 12bpp is stored in 16 bits */
-			break;
-		case 1:
-		case 2:
-		case 4:
-		case 8:
-			fix->visual = FB_VISUAL_PSEUDOCOLOR;
-			break;
-		}
-	}
-
-	fix->accel = FB_ACCEL_NONE;
-
-	fix->xpanstep = 1;
-	fix->ypanstep = 1;
-}
-
-/* check new var and possibly modify it to be ok */
-int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omap_dss_device *display = fb2display(fbi);
-	enum omap_color_mode mode = 0;
-	int i;
-	int r;
-
-	DBG("check_fb_var %d\n", ofbi->id);
-
-	WARN_ON(!atomic_read(&ofbi->region->lock_count));
-
-	r = fb_mode_to_dss_mode(var, &mode);
-	if (r) {
-		DBG("cannot convert var to omap dss mode\n");
-		return r;
-	}
-
-	for (i = 0; i < ofbi->num_overlays; ++i) {
-		if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
-			DBG("invalid mode\n");
-			return -EINVAL;
-		}
-	}
-
-	if (var->rotate > 3)
-		return -EINVAL;
-
-	if (check_fb_res_bounds(var))
-		return -EINVAL;
-
-	/* When no memory is allocated ignore the size check */
-	if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
-		return -EINVAL;
-
-	if (var->xres + var->xoffset > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yres + var->yoffset > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
-			var->xres, var->yres,
-			var->xres_virtual, var->yres_virtual);
-
-	if (display && display->driver->get_dimensions) {
-		u32 w, h;
-		display->driver->get_dimensions(display, &w, &h);
-		var->width = DIV_ROUND_CLOSEST(w, 1000);
-		var->height = DIV_ROUND_CLOSEST(h, 1000);
-	} else {
-		var->height = -1;
-		var->width = -1;
-	}
-
-	var->grayscale          = 0;
-
-	if (display && display->driver->get_timings) {
-		struct omap_video_timings timings;
-		display->driver->get_timings(display, &timings);
-
-		/* pixclock in ps, the rest in pixclock */
-		var->pixclock = timings.pixelclock != 0 ?
-			KHZ2PICOS(timings.pixelclock / 1000) :
-			0;
-		var->left_margin = timings.hbp;
-		var->right_margin = timings.hfp;
-		var->upper_margin = timings.vbp;
-		var->lower_margin = timings.vfp;
-		var->hsync_len = timings.hsw;
-		var->vsync_len = timings.vsw;
-		var->sync |= timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
-				FB_SYNC_HOR_HIGH_ACT : 0;
-		var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
-				FB_SYNC_VERT_HIGH_ACT : 0;
-		var->vmode = timings.interlace ?
-				FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
-	} else {
-		var->pixclock = 0;
-		var->left_margin = 0;
-		var->right_margin = 0;
-		var->upper_margin = 0;
-		var->lower_margin = 0;
-		var->hsync_len = 0;
-		var->vsync_len = 0;
-		var->sync = 0;
-		var->vmode = FB_VMODE_NONINTERLACED;
-	}
-
-	return 0;
-}
-
-/*
- * ---------------------------------------------------------------------------
- * fbdev framework callbacks
- * ---------------------------------------------------------------------------
- */
-static int omapfb_open(struct fb_info *fbi, int user)
-{
-	return 0;
-}
-
-static int omapfb_release(struct fb_info *fbi, int user)
-{
-	return 0;
-}
-
-static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
-		const struct fb_fix_screeninfo *fix, int rotation)
-{
-	unsigned offset;
-
-	offset = var->yoffset * fix->line_length +
-		var->xoffset * (var->bits_per_pixel >> 3);
-
-	return offset;
-}
-
-static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
-		const struct fb_fix_screeninfo *fix, int rotation)
-{
-	unsigned offset;
-
-	if (rotation == FB_ROTATE_UD)
-		offset = (var->yres_virtual - var->yres) *
-			fix->line_length;
-	else if (rotation == FB_ROTATE_CW)
-		offset = (var->yres_virtual - var->yres) *
-			(var->bits_per_pixel >> 3);
-	else
-		offset = 0;
-
-	if (rotation == FB_ROTATE_UR)
-		offset += var->yoffset * fix->line_length +
-			var->xoffset * (var->bits_per_pixel >> 3);
-	else if (rotation == FB_ROTATE_UD)
-		offset -= var->yoffset * fix->line_length +
-			var->xoffset * (var->bits_per_pixel >> 3);
-	else if (rotation == FB_ROTATE_CW)
-		offset -= var->xoffset * fix->line_length +
-			var->yoffset * (var->bits_per_pixel >> 3);
-	else if (rotation == FB_ROTATE_CCW)
-		offset += var->xoffset * fix->line_length +
-			var->yoffset * (var->bits_per_pixel >> 3);
-
-	return offset;
-}
-
-static void omapfb_calc_addr(const struct omapfb_info *ofbi,
-			     const struct fb_var_screeninfo *var,
-			     const struct fb_fix_screeninfo *fix,
-			     int rotation, u32 *paddr)
-{
-	u32 data_start_p;
-	int offset;
-
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
-	else
-		data_start_p = omapfb_get_region_paddr(ofbi);
-
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		offset = calc_rotation_offset_vrfb(var, fix, rotation);
-	else
-		offset = calc_rotation_offset_dma(var, fix, rotation);
-
-	data_start_p += offset;
-
-	if (offset)
-		DBG("offset %d, %d = %d\n",
-		    var->xoffset, var->yoffset, offset);
-
-	DBG("paddr %x\n", data_start_p);
-
-	*paddr = data_start_p;
-}
-
-/* setup overlay according to the fb */
-int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
-		u16 posx, u16 posy, u16 outw, u16 outh)
-{
-	int r = 0;
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct fb_var_screeninfo *var = &fbi->var;
-	struct fb_fix_screeninfo *fix = &fbi->fix;
-	enum omap_color_mode mode = 0;
-	u32 data_start_p = 0;
-	struct omap_overlay_info info;
-	int xres, yres;
-	int screen_width;
-	int mirror;
-	int rotation = var->rotate;
-	int i;
-
-	WARN_ON(!atomic_read(&ofbi->region->lock_count));
-
-	for (i = 0; i < ofbi->num_overlays; i++) {
-		if (ovl != ofbi->overlays[i])
-			continue;
-
-		rotation = (rotation + ofbi->rotation[i]) % 4;
-		break;
-	}
-
-	DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
-			posx, posy, outw, outh);
-
-	if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
-		xres = var->yres;
-		yres = var->xres;
-	} else {
-		xres = var->xres;
-		yres = var->yres;
-	}
-
-	if (ofbi->region->size)
-		omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
-
-	r = fb_mode_to_dss_mode(var, &mode);
-	if (r) {
-		DBG("fb_mode_to_dss_mode failed");
-		goto err;
-	}
-
-	switch (var->nonstd) {
-	case OMAPFB_COLOR_YUV422:
-	case OMAPFB_COLOR_YUY422:
-		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-			screen_width = fix->line_length
-				/ (var->bits_per_pixel >> 2);
-			break;
-		}
-	default:
-		screen_width = fix->line_length / (var->bits_per_pixel >> 3);
-		break;
-	}
-
-	ovl->get_overlay_info(ovl, &info);
-
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		mirror = 0;
-	else
-		mirror = ofbi->mirror;
-
-	info.paddr = data_start_p;
-	info.screen_width = screen_width;
-	info.width = xres;
-	info.height = yres;
-	info.color_mode = mode;
-	info.rotation_type = ofbi->rotation_type;
-	info.rotation = rotation;
-	info.mirror = mirror;
-
-	info.pos_x = posx;
-	info.pos_y = posy;
-	info.out_width = outw;
-	info.out_height = outh;
-
-	r = ovl->set_overlay_info(ovl, &info);
-	if (r) {
-		DBG("ovl->setup_overlay_info failed\n");
-		goto err;
-	}
-
-	return 0;
-
-err:
-	DBG("setup_overlay failed\n");
-	return r;
-}
-
-/* apply var to the overlay */
-int omapfb_apply_changes(struct fb_info *fbi, int init)
-{
-	int r = 0;
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct fb_var_screeninfo *var = &fbi->var;
-	struct omap_overlay *ovl;
-	u16 posx, posy;
-	u16 outw, outh;
-	int i;
-
-#ifdef DEBUG
-	if (omapfb_test_pattern)
-		fill_fb(fbi);
-#endif
-
-	WARN_ON(!atomic_read(&ofbi->region->lock_count));
-
-	for (i = 0; i < ofbi->num_overlays; i++) {
-		ovl = ofbi->overlays[i];
-
-		DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
-
-		if (ofbi->region->size == 0) {
-			/* the fb is not available. disable the overlay */
-			omapfb_overlay_enable(ovl, 0);
-			if (!init && ovl->manager)
-				ovl->manager->apply(ovl->manager);
-			continue;
-		}
-
-		if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
-			int rotation = (var->rotate + ofbi->rotation[i]) % 4;
-			if (rotation == FB_ROTATE_CW ||
-					rotation == FB_ROTATE_CCW) {
-				outw = var->yres;
-				outh = var->xres;
-			} else {
-				outw = var->xres;
-				outh = var->yres;
-			}
-		} else {
-			struct omap_overlay_info info;
-			ovl->get_overlay_info(ovl, &info);
-			outw = info.out_width;
-			outh = info.out_height;
-		}
-
-		if (init) {
-			posx = 0;
-			posy = 0;
-		} else {
-			struct omap_overlay_info info;
-			ovl->get_overlay_info(ovl, &info);
-			posx = info.pos_x;
-			posy = info.pos_y;
-		}
-
-		r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
-		if (r)
-			goto err;
-
-		if (!init && ovl->manager)
-			ovl->manager->apply(ovl->manager);
-	}
-	return 0;
-err:
-	DBG("apply_changes failed\n");
-	return r;
-}
-
-/* checks var and eventually tweaks it to something supported,
- * DO NOT MODIFY PAR */
-static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	int r;
-
-	DBG("check_var(%d)\n", FB2OFB(fbi)->id);
-
-	omapfb_get_mem_region(ofbi->region);
-
-	r = check_fb_var(fbi, var);
-
-	omapfb_put_mem_region(ofbi->region);
-
-	return r;
-}
-
-/* set the video mode according to info->var */
-static int omapfb_set_par(struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	int r;
-
-	DBG("set_par(%d)\n", FB2OFB(fbi)->id);
-
-	omapfb_get_mem_region(ofbi->region);
-
-	set_fb_fix(fbi);
-
-	r = setup_vrfb_rotation(fbi);
-	if (r)
-		goto out;
-
-	r = omapfb_apply_changes(fbi, 0);
-
- out:
-	omapfb_put_mem_region(ofbi->region);
-
-	return r;
-}
-
-static int omapfb_pan_display(struct fb_var_screeninfo *var,
-		struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct fb_var_screeninfo new_var;
-	int r;
-
-	DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
-
-	if (var->xoffset == fbi->var.xoffset &&
-	    var->yoffset == fbi->var.yoffset)
-		return 0;
-
-	new_var = fbi->var;
-	new_var.xoffset = var->xoffset;
-	new_var.yoffset = var->yoffset;
-
-	fbi->var = new_var;
-
-	omapfb_get_mem_region(ofbi->region);
-
-	r = omapfb_apply_changes(fbi, 0);
-
-	omapfb_put_mem_region(ofbi->region);
-
-	return r;
-}
-
-static void mmap_user_open(struct vm_area_struct *vma)
-{
-	struct omapfb2_mem_region *rg = vma->vm_private_data;
-
-	omapfb_get_mem_region(rg);
-	atomic_inc(&rg->map_count);
-	omapfb_put_mem_region(rg);
-}
-
-static void mmap_user_close(struct vm_area_struct *vma)
-{
-	struct omapfb2_mem_region *rg = vma->vm_private_data;
-
-	omapfb_get_mem_region(rg);
-	atomic_dec(&rg->map_count);
-	omapfb_put_mem_region(rg);
-}
-
-static struct vm_operations_struct mmap_user_ops = {
-	.open = mmap_user_open,
-	.close = mmap_user_close,
-};
-
-static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct fb_fix_screeninfo *fix = &fbi->fix;
-	struct omapfb2_mem_region *rg;
-	unsigned long start;
-	u32 len;
-	int r;
-
-	rg = omapfb_get_mem_region(ofbi->region);
-
-	start = omapfb_get_region_paddr(ofbi);
-	len = fix->smem_len;
-
-	DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
-			vma->vm_pgoff << PAGE_SHIFT);
-
-	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-	vma->vm_ops = &mmap_user_ops;
-	vma->vm_private_data = rg;
-
-	r = vm_iomap_memory(vma, start, len);
-	if (r)
-		goto error;
-
-	/* vm_ops.open won't be called for mmap itself. */
-	atomic_inc(&rg->map_count);
-
-	omapfb_put_mem_region(rg);
-
-	return 0;
-
-error:
-	omapfb_put_mem_region(ofbi->region);
-
-	return r;
-}
-
-/* Store a single color palette entry into a pseudo palette or the hardware
- * palette if one is available. For now we support only 16bpp and thus store
- * the entry only to the pseudo palette.
- */
-static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
-		u_int blue, u_int transp, int update_hw_pal)
-{
-	/*struct omapfb_info *ofbi = FB2OFB(fbi);*/
-	/*struct omapfb2_device *fbdev = ofbi->fbdev;*/
-	struct fb_var_screeninfo *var = &fbi->var;
-	int r = 0;
-
-	enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
-
-	/*switch (plane->color_mode) {*/
-	switch (mode) {
-	case OMAPFB_COLOR_YUV422:
-	case OMAPFB_COLOR_YUV420:
-	case OMAPFB_COLOR_YUY422:
-		r = -EINVAL;
-		break;
-	case OMAPFB_COLOR_CLUT_8BPP:
-	case OMAPFB_COLOR_CLUT_4BPP:
-	case OMAPFB_COLOR_CLUT_2BPP:
-	case OMAPFB_COLOR_CLUT_1BPP:
-		/*
-		   if (fbdev->ctrl->setcolreg)
-		   r = fbdev->ctrl->setcolreg(regno, red, green, blue,
-		   transp, update_hw_pal);
-		   */
-		/* Fallthrough */
-		r = -EINVAL;
-		break;
-	case OMAPFB_COLOR_RGB565:
-	case OMAPFB_COLOR_RGB444:
-	case OMAPFB_COLOR_RGB24P:
-	case OMAPFB_COLOR_RGB24U:
-		if (r != 0)
-			break;
-
-		if (regno < 16) {
-			u32 pal;
-			pal = ((red >> (16 - var->red.length)) <<
-					var->red.offset) |
-				((green >> (16 - var->green.length)) <<
-				 var->green.offset) |
-				(blue >> (16 - var->blue.length));
-			((u32 *)(fbi->pseudo_palette))[regno] = pal;
-		}
-		break;
-	default:
-		BUG();
-	}
-	return r;
-}
-
-static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		u_int transp, struct fb_info *info)
-{
-	DBG("setcolreg\n");
-
-	return _setcolreg(info, regno, red, green, blue, transp, 1);
-}
-
-static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
-	int count, index, r;
-	u16 *red, *green, *blue, *transp;
-	u16 trans = 0xffff;
-
-	DBG("setcmap\n");
-
-	red     = cmap->red;
-	green   = cmap->green;
-	blue    = cmap->blue;
-	transp  = cmap->transp;
-	index   = cmap->start;
-
-	for (count = 0; count < cmap->len; count++) {
-		if (transp)
-			trans = *transp++;
-		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
-				count == cmap->len - 1);
-		if (r != 0)
-			return r;
-	}
-
-	return 0;
-}
-
-static int omapfb_blank(int blank, struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_dss_device *display = fb2display(fbi);
-	struct omapfb_display_data *d;
-	int r = 0;
-
-	if (!display)
-		return -EINVAL;
-
-	omapfb_lock(fbdev);
-
-	d = get_display_data(fbdev, display);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-		if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
-			goto exit;
-
-		r = display->driver->enable(display);
-
-		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
-				d->update_mode == OMAPFB_AUTO_UPDATE &&
-				!d->auto_update_work_enabled)
-			omapfb_start_auto_update(fbdev, display);
-
-		break;
-
-	case FB_BLANK_NORMAL:
-		/* FB_BLANK_NORMAL could be implemented.
-		 * Needs DSS additions. */
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_POWERDOWN:
-		if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
-			goto exit;
-
-		if (d->auto_update_work_enabled)
-			omapfb_stop_auto_update(fbdev, display);
-
-		display->driver->disable(display);
-
-		break;
-
-	default:
-		r = -EINVAL;
-	}
-
-exit:
-	omapfb_unlock(fbdev);
-
-	return r;
-}
-
-#if 0
-/* XXX fb_read and fb_write are needed for VRFB */
-ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
-		size_t count, loff_t *ppos)
-{
-	DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
-	/* XXX needed for VRFB */
-	return count;
-}
-#endif
-
-static struct fb_ops omapfb_ops = {
-	.owner          = THIS_MODULE,
-	.fb_open        = omapfb_open,
-	.fb_release     = omapfb_release,
-	.fb_fillrect    = cfb_fillrect,
-	.fb_copyarea    = cfb_copyarea,
-	.fb_imageblit   = cfb_imageblit,
-	.fb_blank       = omapfb_blank,
-	.fb_ioctl       = omapfb_ioctl,
-	.fb_check_var   = omapfb_check_var,
-	.fb_set_par     = omapfb_set_par,
-	.fb_pan_display = omapfb_pan_display,
-	.fb_mmap	= omapfb_mmap,
-	.fb_setcolreg	= omapfb_setcolreg,
-	.fb_setcmap	= omapfb_setcmap,
-	/*.fb_write	= omapfb_write,*/
-};
-
-static void omapfb_free_fbmem(struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omapfb2_mem_region *rg;
-
-	rg = ofbi->region;
-
-	if (rg->token == NULL)
-		return;
-
-	WARN_ON(atomic_read(&rg->map_count));
-
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-		/* unmap the 0 angle rotation */
-		if (rg->vrfb.vaddr[0]) {
-			iounmap(rg->vrfb.vaddr[0]);
-			rg->vrfb.vaddr[0] = NULL;
-		}
-
-		omap_vrfb_release_ctx(&rg->vrfb);
-	}
-
-	dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
-			&rg->attrs);
-
-	rg->token = NULL;
-	rg->vaddr = NULL;
-	rg->paddr = 0;
-	rg->alloc = 0;
-	rg->size = 0;
-}
-
-static void clear_fb_info(struct fb_info *fbi)
-{
-	memset(&fbi->var, 0, sizeof(fbi->var));
-	memset(&fbi->fix, 0, sizeof(fbi->fix));
-	strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
-}
-
-static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
-{
-	int i;
-
-	DBG("free all fbmem\n");
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct fb_info *fbi = fbdev->fbs[i];
-		omapfb_free_fbmem(fbi);
-		clear_fb_info(fbi);
-	}
-
-	return 0;
-}
-
-static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
-		unsigned long paddr)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omapfb2_mem_region *rg;
-	void *token;
-	DEFINE_DMA_ATTRS(attrs);
-	dma_addr_t dma_handle;
-	int r;
-
-	rg = ofbi->region;
-
-	rg->paddr = 0;
-	rg->vaddr = NULL;
-	memset(&rg->vrfb, 0, sizeof rg->vrfb);
-	rg->size = 0;
-	rg->type = 0;
-	rg->alloc = false;
-	rg->map = false;
-
-	size = PAGE_ALIGN(size);
-
-	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
-
-	DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
-
-	token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
-			GFP_KERNEL, &attrs);
-
-	if (token == NULL) {
-		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
-		return -ENOMEM;
-	}
-
-	DBG("allocated VRAM paddr %lx, vaddr %p\n",
-			(unsigned long)dma_handle, token);
-
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-		r = omap_vrfb_request_ctx(&rg->vrfb);
-		if (r) {
-			dma_free_attrs(fbdev->dev, size, token, dma_handle,
-					&attrs);
-			dev_err(fbdev->dev, "vrfb create ctx failed\n");
-			return r;
-		}
-	}
-
-	rg->attrs = attrs;
-	rg->token = token;
-	rg->dma_handle = dma_handle;
-
-	rg->paddr = (unsigned long)dma_handle;
-	rg->vaddr = (void __iomem *)token;
-	rg->size = size;
-	rg->alloc = 1;
-
-	return 0;
-}
-
-/* allocate fbmem using display resolution as reference */
-static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
-		unsigned long paddr)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_dss_device *display;
-	int bytespp;
-
-	display =  fb2display(fbi);
-
-	if (!display)
-		return 0;
-
-	switch (omapfb_get_recommended_bpp(fbdev, display)) {
-	case 16:
-		bytespp = 2;
-		break;
-	case 24:
-		bytespp = 4;
-		break;
-	default:
-		bytespp = 4;
-		break;
-	}
-
-	if (!size) {
-		u16 w, h;
-
-		display->driver->get_resolution(display, &w, &h);
-
-		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-			size = max(omap_vrfb_min_phys_size(w, h, bytespp),
-					omap_vrfb_min_phys_size(h, w, bytespp));
-
-			DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
-					w * h * bytespp, size);
-		} else {
-			size = w * h * bytespp;
-		}
-	}
-
-	if (!size)
-		return 0;
-
-	return omapfb_alloc_fbmem(fbi, size, paddr);
-}
-
-static int omapfb_parse_vram_param(const char *param, int max_entries,
-		unsigned long *sizes, unsigned long *paddrs)
-{
-	int fbnum;
-	unsigned long size;
-	unsigned long paddr = 0;
-	char *p, *start;
-
-	start = (char *)param;
-
-	while (1) {
-		p = start;
-
-		fbnum = simple_strtoul(p, &p, 10);
-
-		if (p == start)
-			return -EINVAL;
-
-		if (*p != ':')
-			return -EINVAL;
-
-		if (fbnum >= max_entries)
-			return -EINVAL;
-
-		size = memparse(p + 1, &p);
-
-		if (!size)
-			return -EINVAL;
-
-		paddr = 0;
-
-		if (*p == '@') {
-			paddr = simple_strtoul(p + 1, &p, 16);
-
-			if (!paddr)
-				return -EINVAL;
-
-		}
-
-		WARN_ONCE(paddr,
-			"reserving memory at predefined address not supported\n");
-
-		paddrs[fbnum] = paddr;
-		sizes[fbnum] = size;
-
-		if (*p == 0)
-			break;
-
-		if (*p != ',')
-			return -EINVAL;
-
-		++p;
-
-		start = p;
-	}
-
-	return 0;
-}
-
-static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
-{
-	int i, r;
-	unsigned long vram_sizes[10];
-	unsigned long vram_paddrs[10];
-
-	memset(&vram_sizes, 0, sizeof(vram_sizes));
-	memset(&vram_paddrs, 0, sizeof(vram_paddrs));
-
-	if (def_vram &&	omapfb_parse_vram_param(def_vram, 10,
-				vram_sizes, vram_paddrs)) {
-		dev_err(fbdev->dev, "failed to parse vram parameter\n");
-
-		memset(&vram_sizes, 0, sizeof(vram_sizes));
-		memset(&vram_paddrs, 0, sizeof(vram_paddrs));
-	}
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		/* allocate memory automatically only for fb0, or if
-		 * excplicitly defined with vram or plat data option */
-		if (i == 0 || vram_sizes[i] != 0) {
-			r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
-					vram_sizes[i], vram_paddrs[i]);
-
-			if (r)
-				return r;
-		}
-	}
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
-		struct omapfb2_mem_region *rg;
-		rg = ofbi->region;
-
-		DBG("region%d phys %08x virt %p size=%lu\n",
-				i,
-				rg->paddr,
-				rg->vaddr,
-				rg->size);
-	}
-
-	return 0;
-}
-
-static void omapfb_clear_fb(struct fb_info *fbi)
-{
-	const struct fb_fillrect rect = {
-		.dx = 0,
-		.dy = 0,
-		.width = fbi->var.xres_virtual,
-		.height = fbi->var.yres_virtual,
-		.color = 0,
-		.rop = ROP_COPY,
-	};
-
-	cfb_fillrect(fbi, &rect);
-}
-
-int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omapfb2_mem_region *rg = ofbi->region;
-	unsigned long old_size = rg->size;
-	unsigned long old_paddr = rg->paddr;
-	int old_type = rg->type;
-	int r;
-
-	if (type != OMAPFB_MEMTYPE_SDRAM)
-		return -EINVAL;
-
-	size = PAGE_ALIGN(size);
-
-	if (old_size == size && old_type == type)
-		return 0;
-
-	omapfb_free_fbmem(fbi);
-
-	if (size == 0) {
-		clear_fb_info(fbi);
-		return 0;
-	}
-
-	r = omapfb_alloc_fbmem(fbi, size, 0);
-
-	if (r) {
-		if (old_size)
-			omapfb_alloc_fbmem(fbi, old_size, old_paddr);
-
-		if (rg->size == 0)
-			clear_fb_info(fbi);
-
-		return r;
-	}
-
-	if (old_size == size)
-		return 0;
-
-	if (old_size == 0) {
-		DBG("initializing fb %d\n", ofbi->id);
-		r = omapfb_fb_init(fbdev, fbi);
-		if (r) {
-			DBG("omapfb_fb_init failed\n");
-			goto err;
-		}
-		r = omapfb_apply_changes(fbi, 1);
-		if (r) {
-			DBG("omapfb_apply_changes failed\n");
-			goto err;
-		}
-	} else {
-		struct fb_var_screeninfo new_var;
-		memcpy(&new_var, &fbi->var, sizeof(new_var));
-		r = check_fb_var(fbi, &new_var);
-		if (r)
-			goto err;
-		memcpy(&fbi->var, &new_var, sizeof(fbi->var));
-		set_fb_fix(fbi);
-		r = setup_vrfb_rotation(fbi);
-		if (r)
-			goto err;
-	}
-
-	omapfb_clear_fb(fbi);
-
-	return 0;
-err:
-	omapfb_free_fbmem(fbi);
-	clear_fb_info(fbi);
-	return r;
-}
-
-static void omapfb_auto_update_work(struct work_struct *work)
-{
-	struct omap_dss_device *dssdev;
-	struct omap_dss_driver *dssdrv;
-	struct omapfb_display_data *d;
-	u16 w, h;
-	unsigned int freq;
-	struct omapfb2_device *fbdev;
-
-	d = container_of(work, struct omapfb_display_data,
-			auto_update_work.work);
-
-	dssdev = d->dssdev;
-	dssdrv = dssdev->driver;
-	fbdev = d->fbdev;
-
-	if (!dssdrv || !dssdrv->update)
-		return;
-
-	if (dssdrv->sync)
-		dssdrv->sync(dssdev);
-
-	dssdrv->get_resolution(dssdev, &w, &h);
-	dssdrv->update(dssdev, 0, 0, w, h);
-
-	freq = auto_update_freq;
-	if (freq == 0)
-		freq = 20;
-	queue_delayed_work(fbdev->auto_update_wq,
-			&d->auto_update_work, HZ / freq);
-}
-
-void omapfb_start_auto_update(struct omapfb2_device *fbdev,
-		struct omap_dss_device *display)
-{
-	struct omapfb_display_data *d;
-
-	if (fbdev->auto_update_wq == NULL) {
-		struct workqueue_struct *wq;
-
-		wq = create_singlethread_workqueue("omapfb_auto_update");
-
-		if (wq == NULL) {
-			dev_err(fbdev->dev, "Failed to create workqueue for "
-					"auto-update\n");
-			return;
-		}
-
-		fbdev->auto_update_wq = wq;
-	}
-
-	d = get_display_data(fbdev, display);
-
-	INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
-
-	d->auto_update_work_enabled = true;
-
-	omapfb_auto_update_work(&d->auto_update_work.work);
-}
-
-void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
-		struct omap_dss_device *display)
-{
-	struct omapfb_display_data *d;
-
-	d = get_display_data(fbdev, display);
-
-	cancel_delayed_work_sync(&d->auto_update_work);
-
-	d->auto_update_work_enabled = false;
-}
-
-/* initialize fb_info, var, fix to something sane based on the display */
-static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
-{
-	struct fb_var_screeninfo *var = &fbi->var;
-	struct omap_dss_device *display = fb2display(fbi);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	int r = 0;
-
-	fbi->fbops = &omapfb_ops;
-	fbi->flags = FBINFO_FLAG_DEFAULT;
-	fbi->pseudo_palette = fbdev->pseudo_palette;
-
-	if (ofbi->region->size == 0) {
-		clear_fb_info(fbi);
-		return 0;
-	}
-
-	var->nonstd = 0;
-	var->bits_per_pixel = 0;
-
-	var->rotate = def_rotate;
-
-	if (display) {
-		u16 w, h;
-		int rotation = (var->rotate + ofbi->rotation[0]) % 4;
-
-		display->driver->get_resolution(display, &w, &h);
-
-		if (rotation == FB_ROTATE_CW ||
-				rotation == FB_ROTATE_CCW) {
-			var->xres = h;
-			var->yres = w;
-		} else {
-			var->xres = w;
-			var->yres = h;
-		}
-
-		var->xres_virtual = var->xres;
-		var->yres_virtual = var->yres;
-
-		if (!var->bits_per_pixel) {
-			switch (omapfb_get_recommended_bpp(fbdev, display)) {
-			case 16:
-				var->bits_per_pixel = 16;
-				break;
-			case 24:
-				var->bits_per_pixel = 32;
-				break;
-			default:
-				dev_err(fbdev->dev, "illegal display "
-						"bpp\n");
-				return -EINVAL;
-			}
-		}
-	} else {
-		/* if there's no display, let's just guess some basic values */
-		var->xres = 320;
-		var->yres = 240;
-		var->xres_virtual = var->xres;
-		var->yres_virtual = var->yres;
-		if (!var->bits_per_pixel)
-			var->bits_per_pixel = 16;
-	}
-
-	r = check_fb_var(fbi, var);
-	if (r)
-		goto err;
-
-	set_fb_fix(fbi);
-	r = setup_vrfb_rotation(fbi);
-	if (r)
-		goto err;
-
-	r = fb_alloc_cmap(&fbi->cmap, 256, 0);
-	if (r)
-		dev_err(fbdev->dev, "unable to allocate color map memory\n");
-
-err:
-	return r;
-}
-
-static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
-{
-	fb_dealloc_cmap(&fbi->cmap);
-}
-
-
-static void omapfb_free_resources(struct omapfb2_device *fbdev)
-{
-	int i;
-
-	DBG("free_resources\n");
-
-	if (fbdev == NULL)
-		return;
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
-		int j;
-
-		for (j = 0; j < ofbi->num_overlays; j++) {
-			struct omap_overlay *ovl = ofbi->overlays[j];
-			ovl->disable(ovl);
-		}
-	}
-
-	for (i = 0; i < fbdev->num_fbs; i++)
-		unregister_framebuffer(fbdev->fbs[i]);
-
-	/* free the reserved fbmem */
-	omapfb_free_all_fbmem(fbdev);
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		fbinfo_cleanup(fbdev, fbdev->fbs[i]);
-		framebuffer_release(fbdev->fbs[i]);
-	}
-
-	for (i = 0; i < fbdev->num_displays; i++) {
-		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
-
-		if (fbdev->displays[i].auto_update_work_enabled)
-			omapfb_stop_auto_update(fbdev, dssdev);
-
-		if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
-			dssdev->driver->disable(dssdev);
-
-		dssdev->driver->disconnect(dssdev);
-
-		omap_dss_put_device(dssdev);
-	}
-
-	if (fbdev->auto_update_wq != NULL) {
-		flush_workqueue(fbdev->auto_update_wq);
-		destroy_workqueue(fbdev->auto_update_wq);
-		fbdev->auto_update_wq = NULL;
-	}
-
-	dev_set_drvdata(fbdev->dev, NULL);
-}
-
-static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
-{
-	int r, i;
-
-	fbdev->num_fbs = 0;
-
-	DBG("create %d framebuffers\n",	CONFIG_FB_OMAP2_NUM_FBS);
-
-	/* allocate fb_infos */
-	for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
-		struct fb_info *fbi;
-		struct omapfb_info *ofbi;
-
-		fbi = framebuffer_alloc(sizeof(struct omapfb_info),
-				fbdev->dev);
-
-		if (fbi == NULL) {
-			dev_err(fbdev->dev,
-				"unable to allocate memory for plane info\n");
-			return -ENOMEM;
-		}
-
-		clear_fb_info(fbi);
-
-		fbdev->fbs[i] = fbi;
-
-		ofbi = FB2OFB(fbi);
-		ofbi->fbdev = fbdev;
-		ofbi->id = i;
-
-		ofbi->region = &fbdev->regions[i];
-		ofbi->region->id = i;
-		init_rwsem(&ofbi->region->lock);
-
-		/* assign these early, so that fb alloc can use them */
-		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
-			OMAP_DSS_ROT_DMA;
-		ofbi->mirror = def_mirror;
-
-		fbdev->num_fbs++;
-	}
-
-	DBG("fb_infos allocated\n");
-
-	/* assign overlays for the fbs */
-	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
-		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
-
-		ofbi->overlays[0] = fbdev->overlays[i];
-		ofbi->num_overlays = 1;
-	}
-
-	/* allocate fb memories */
-	r = omapfb_allocate_all_fbs(fbdev);
-	if (r) {
-		dev_err(fbdev->dev, "failed to allocate fbmem\n");
-		return r;
-	}
-
-	DBG("fbmems allocated\n");
-
-	/* setup fb_infos */
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct fb_info *fbi = fbdev->fbs[i];
-		struct omapfb_info *ofbi = FB2OFB(fbi);
-
-		omapfb_get_mem_region(ofbi->region);
-		r = omapfb_fb_init(fbdev, fbi);
-		omapfb_put_mem_region(ofbi->region);
-
-		if (r) {
-			dev_err(fbdev->dev, "failed to setup fb_info\n");
-			return r;
-		}
-	}
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct fb_info *fbi = fbdev->fbs[i];
-		struct omapfb_info *ofbi = FB2OFB(fbi);
-
-		if (ofbi->region->size == 0)
-			continue;
-
-		omapfb_clear_fb(fbi);
-	}
-
-	DBG("fb_infos initialized\n");
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		r = register_framebuffer(fbdev->fbs[i]);
-		if (r != 0) {
-			dev_err(fbdev->dev,
-				"registering framebuffer %d failed\n", i);
-			return r;
-		}
-	}
-
-	DBG("framebuffers registered\n");
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct fb_info *fbi = fbdev->fbs[i];
-		struct omapfb_info *ofbi = FB2OFB(fbi);
-
-		omapfb_get_mem_region(ofbi->region);
-		r = omapfb_apply_changes(fbi, 1);
-		omapfb_put_mem_region(ofbi->region);
-
-		if (r) {
-			dev_err(fbdev->dev, "failed to change mode\n");
-			return r;
-		}
-	}
-
-	/* Enable fb0 */
-	if (fbdev->num_fbs > 0) {
-		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
-
-		if (ofbi->num_overlays > 0) {
-			struct omap_overlay *ovl = ofbi->overlays[0];
-
-			ovl->manager->apply(ovl->manager);
-
-			r = omapfb_overlay_enable(ovl, 1);
-
-			if (r) {
-				dev_err(fbdev->dev,
-						"failed to enable overlay\n");
-				return r;
-			}
-		}
-	}
-
-	DBG("create_framebuffers done\n");
-
-	return 0;
-}
-
-static int omapfb_mode_to_timings(const char *mode_str,
-		struct omap_dss_device *display,
-		struct omap_video_timings *timings, u8 *bpp)
-{
-	struct fb_info *fbi;
-	struct fb_var_screeninfo *var;
-	struct fb_ops *fbops;
-	int r;
-
-#ifdef CONFIG_OMAP2_DSS_VENC
-	if (strcmp(mode_str, "pal") == 0) {
-		*timings = omap_dss_pal_timings;
-		*bpp = 24;
-		return 0;
-	} else if (strcmp(mode_str, "ntsc") == 0) {
-		*timings = omap_dss_ntsc_timings;
-		*bpp = 24;
-		return 0;
-	}
-#endif
-
-	/* this is quite a hack, but I wanted to use the modedb and for
-	 * that we need fb_info and var, so we create dummy ones */
-
-	*bpp = 0;
-	fbi = NULL;
-	var = NULL;
-	fbops = NULL;
-
-	fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
-	if (fbi == NULL) {
-		r = -ENOMEM;
-		goto err;
-	}
-
-	var = kzalloc(sizeof(*var), GFP_KERNEL);
-	if (var == NULL) {
-		r = -ENOMEM;
-		goto err;
-	}
-
-	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
-	if (fbops == NULL) {
-		r = -ENOMEM;
-		goto err;
-	}
-
-	fbi->fbops = fbops;
-
-	r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
-	if (r == 0) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	if (display->driver->get_timings) {
-		display->driver->get_timings(display, timings);
-	} else {
-		timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-		timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-		timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
-	}
-
-	timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000;
-	timings->hbp = var->left_margin;
-	timings->hfp = var->right_margin;
-	timings->vbp = var->upper_margin;
-	timings->vfp = var->lower_margin;
-	timings->hsw = var->hsync_len;
-	timings->vsw = var->vsync_len;
-	timings->x_res = var->xres;
-	timings->y_res = var->yres;
-	timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
-				OMAPDSS_SIG_ACTIVE_HIGH :
-				OMAPDSS_SIG_ACTIVE_LOW;
-	timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
-				OMAPDSS_SIG_ACTIVE_HIGH :
-				OMAPDSS_SIG_ACTIVE_LOW;
-	timings->interlace = var->vmode & FB_VMODE_INTERLACED;
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		*bpp = 16;
-		break;
-	case 24:
-	case 32:
-	default:
-		*bpp = 24;
-		break;
-	}
-
-	r = 0;
-
-err:
-	kfree(fbi);
-	kfree(var);
-	kfree(fbops);
-
-	return r;
-}
-
-static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
-		struct omap_dss_device *display, char *mode_str)
-{
-	int r;
-	u8 bpp;
-	struct omap_video_timings timings, temp_timings;
-	struct omapfb_display_data *d;
-
-	r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
-	if (r)
-		return r;
-
-	d = get_display_data(fbdev, display);
-	d->bpp_override = bpp;
-
-	if (display->driver->check_timings) {
-		r = display->driver->check_timings(display, &timings);
-		if (r)
-			return r;
-	} else {
-		/* If check_timings is not present compare xres and yres */
-		if (display->driver->get_timings) {
-			display->driver->get_timings(display, &temp_timings);
-
-			if (temp_timings.x_res != timings.x_res ||
-				temp_timings.y_res != timings.y_res)
-				return -EINVAL;
-		}
-	}
-
-	if (display->driver->set_timings)
-			display->driver->set_timings(display, &timings);
-
-	return 0;
-}
-
-static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
-		struct omap_dss_device *dssdev)
-{
-	struct omapfb_display_data *d;
-
-	BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
-
-	d = get_display_data(fbdev, dssdev);
-
-	if (d->bpp_override != 0)
-		return d->bpp_override;
-
-	return dssdev->driver->get_recommended_bpp(dssdev);
-}
-
-static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
-{
-	char *str, *options, *this_opt;
-	int r = 0;
-
-	str = kstrdup(def_mode, GFP_KERNEL);
-	if (!str)
-		return -ENOMEM;
-	options = str;
-
-	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
-		char *p, *display_str, *mode_str;
-		struct omap_dss_device *display;
-		int i;
-
-		p = strchr(this_opt, ':');
-		if (!p) {
-			r = -EINVAL;
-			break;
-		}
-
-		*p = 0;
-		display_str = this_opt;
-		mode_str = p + 1;
-
-		display = NULL;
-		for (i = 0; i < fbdev->num_displays; ++i) {
-			if (strcmp(fbdev->displays[i].dssdev->name,
-						display_str) == 0) {
-				display = fbdev->displays[i].dssdev;
-				break;
-			}
-		}
-
-		if (!display) {
-			r = -EINVAL;
-			break;
-		}
-
-		r = omapfb_set_def_mode(fbdev, display, mode_str);
-		if (r)
-			break;
-	}
-
-	kfree(str);
-
-	return r;
-}
-
-static void fb_videomode_to_omap_timings(struct fb_videomode *m,
-		struct omap_dss_device *display,
-		struct omap_video_timings *t)
-{
-	if (display->driver->get_timings) {
-		display->driver->get_timings(display, t);
-	} else {
-		t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-		t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-		t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
-	}
-
-	t->x_res = m->xres;
-	t->y_res = m->yres;
-	t->pixelclock = PICOS2KHZ(m->pixclock) * 1000;
-	t->hsw = m->hsync_len;
-	t->hfp = m->right_margin;
-	t->hbp = m->left_margin;
-	t->vsw = m->vsync_len;
-	t->vfp = m->lower_margin;
-	t->vbp = m->upper_margin;
-	t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
-				OMAPDSS_SIG_ACTIVE_HIGH :
-				OMAPDSS_SIG_ACTIVE_LOW;
-	t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
-				OMAPDSS_SIG_ACTIVE_HIGH :
-				OMAPDSS_SIG_ACTIVE_LOW;
-	t->interlace = m->vmode & FB_VMODE_INTERLACED;
-}
-
-static int omapfb_find_best_mode(struct omap_dss_device *display,
-		struct omap_video_timings *timings)
-{
-	struct fb_monspecs *specs;
-	u8 *edid;
-	int r, i, best_idx, len;
-
-	if (!display->driver->read_edid)
-		return -ENODEV;
-
-	len = 0x80 * 2;
-	edid = kmalloc(len, GFP_KERNEL);
-	if (edid == NULL)
-		return -ENOMEM;
-
-	r = display->driver->read_edid(display, edid, len);
-	if (r < 0)
-		goto err1;
-
-	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
-	if (specs == NULL) {
-		r = -ENOMEM;
-		goto err1;
-	}
-
-	fb_edid_to_monspecs(edid, specs);
-
-	best_idx = -1;
-
-	for (i = 0; i < specs->modedb_len; ++i) {
-		struct fb_videomode *m;
-		struct omap_video_timings t;
-
-		m = &specs->modedb[i];
-
-		if (m->pixclock == 0)
-			continue;
-
-		/* skip repeated pixel modes */
-		if (m->xres == 2880 || m->xres == 1440)
-			continue;
-
-		if (m->vmode & FB_VMODE_INTERLACED ||
-				m->vmode & FB_VMODE_DOUBLE)
-			continue;
-
-		fb_videomode_to_omap_timings(m, display, &t);
-
-		r = display->driver->check_timings(display, &t);
-		if (r == 0) {
-			best_idx = i;
-			break;
-		}
-	}
-
-	if (best_idx == -1) {
-		r = -ENOENT;
-		goto err2;
-	}
-
-	fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
-		timings);
-
-	r = 0;
-
-err2:
-	fb_destroy_modedb(specs->modedb);
-	kfree(specs);
-err1:
-	kfree(edid);
-
-	return r;
-}
-
-static int omapfb_init_display(struct omapfb2_device *fbdev,
-		struct omap_dss_device *dssdev)
-{
-	struct omap_dss_driver *dssdrv = dssdev->driver;
-	struct omapfb_display_data *d;
-	int r;
-
-	r = dssdrv->enable(dssdev);
-	if (r) {
-		dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
-				dssdev->name);
-		return r;
-	}
-
-	d = get_display_data(fbdev, dssdev);
-
-	d->fbdev = fbdev;
-
-	if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-		u16 w, h;
-
-		if (auto_update) {
-			omapfb_start_auto_update(fbdev, dssdev);
-			d->update_mode = OMAPFB_AUTO_UPDATE;
-		} else {
-			d->update_mode = OMAPFB_MANUAL_UPDATE;
-		}
-
-		if (dssdrv->enable_te) {
-			r = dssdrv->enable_te(dssdev, 1);
-			if (r) {
-				dev_err(fbdev->dev, "Failed to set TE\n");
-				return r;
-			}
-		}
-
-		dssdrv->get_resolution(dssdev, &w, &h);
-		r = dssdrv->update(dssdev, 0, 0, w, h);
-		if (r) {
-			dev_err(fbdev->dev,
-					"Failed to update display\n");
-			return r;
-		}
-	} else {
-		d->update_mode = OMAPFB_AUTO_UPDATE;
-	}
-
-	return 0;
-}
-
-static int omapfb_init_connections(struct omapfb2_device *fbdev,
-		struct omap_dss_device *def_dssdev)
-{
-	int i, r;
-	struct omap_overlay_manager *mgr;
-
-	r = def_dssdev->driver->connect(def_dssdev);
-	if (r) {
-		dev_err(fbdev->dev, "failed to connect default display\n");
-		return r;
-	}
-
-	for (i = 0; i < fbdev->num_displays; ++i) {
-		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
-
-		if (dssdev == def_dssdev)
-			continue;
-
-		/*
-		 * We don't care if the connect succeeds or not. We just want to
-		 * connect as many displays as possible.
-		 */
-		dssdev->driver->connect(dssdev);
-	}
-
-	mgr = omapdss_find_mgr_from_display(def_dssdev);
-
-	if (!mgr) {
-		dev_err(fbdev->dev, "no ovl manager for the default display\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < fbdev->num_overlays; i++) {
-		struct omap_overlay *ovl = fbdev->overlays[i];
-
-		if (ovl->manager)
-			ovl->unset_manager(ovl);
-
-		r = ovl->set_manager(ovl, mgr);
-		if (r)
-			dev_warn(fbdev->dev,
-					"failed to connect overlay %s to manager %s\n",
-					ovl->name, mgr->name);
-	}
-
-	return 0;
-}
-
-static struct omap_dss_device *
-omapfb_find_default_display(struct omapfb2_device *fbdev)
-{
-	const char *def_name;
-	int i;
-
-	/*
-	 * Search with the display name from the user or the board file,
-	 * comparing to display names and aliases
-	 */
-
-	def_name = omapdss_get_default_display_name();
-
-	if (def_name) {
-		for (i = 0; i < fbdev->num_displays; ++i) {
-			struct omap_dss_device *dssdev;
-
-			dssdev = fbdev->displays[i].dssdev;
-
-			if (dssdev->name && strcmp(def_name, dssdev->name) == 0)
-				return dssdev;
-
-			if (strcmp(def_name, dssdev->alias) == 0)
-				return dssdev;
-		}
-
-		/* def_name given but not found */
-		return NULL;
-	}
-
-	/* then look for DT alias display0 */
-	for (i = 0; i < fbdev->num_displays; ++i) {
-		struct omap_dss_device *dssdev;
-		int id;
-
-		dssdev = fbdev->displays[i].dssdev;
-
-		if (dssdev->dev->of_node == NULL)
-			continue;
-
-		id = of_alias_get_id(dssdev->dev->of_node, "display");
-		if (id == 0)
-			return dssdev;
-	}
-
-	/* return the first display we have in the list */
-	return fbdev->displays[0].dssdev;
-}
-
-static int omapfb_probe(struct platform_device *pdev)
-{
-	struct omapfb2_device *fbdev = NULL;
-	int r = 0;
-	int i;
-	struct omap_dss_device *def_display;
-	struct omap_dss_device *dssdev;
-
-	DBG("omapfb_probe\n");
-
-	if (omapdss_is_initialized() == false)
-		return -EPROBE_DEFER;
-
-	if (pdev->num_resources != 0) {
-		dev_err(&pdev->dev, "probed for an unknown device\n");
-		r = -ENODEV;
-		goto err0;
-	}
-
-	fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
-			GFP_KERNEL);
-	if (fbdev == NULL) {
-		r = -ENOMEM;
-		goto err0;
-	}
-
-	if (def_vrfb && !omap_vrfb_supported()) {
-		def_vrfb = 0;
-		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
-				"ignoring the module parameter vrfb=y\n");
-	}
-
-	r = omapdss_compat_init();
-	if (r)
-		goto err0;
-
-	mutex_init(&fbdev->mtx);
-
-	fbdev->dev = &pdev->dev;
-	platform_set_drvdata(pdev, fbdev);
-
-	fbdev->num_displays = 0;
-	dssdev = NULL;
-	for_each_dss_dev(dssdev) {
-		struct omapfb_display_data *d;
-
-		omap_dss_get_device(dssdev);
-
-		if (!dssdev->driver) {
-			dev_warn(&pdev->dev, "no driver for display: %s\n",
-				dssdev->name);
-			omap_dss_put_device(dssdev);
-			continue;
-		}
-
-		d = &fbdev->displays[fbdev->num_displays++];
-		d->dssdev = dssdev;
-		if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
-			d->update_mode = OMAPFB_MANUAL_UPDATE;
-		else
-			d->update_mode = OMAPFB_AUTO_UPDATE;
-	}
-
-	if (fbdev->num_displays == 0) {
-		dev_err(&pdev->dev, "no displays\n");
-		r = -EPROBE_DEFER;
-		goto cleanup;
-	}
-
-	fbdev->num_overlays = omap_dss_get_num_overlays();
-	for (i = 0; i < fbdev->num_overlays; i++)
-		fbdev->overlays[i] = omap_dss_get_overlay(i);
-
-	fbdev->num_managers = omap_dss_get_num_overlay_managers();
-	for (i = 0; i < fbdev->num_managers; i++)
-		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
-
-	def_display = omapfb_find_default_display(fbdev);
-	if (def_display == NULL) {
-		dev_err(fbdev->dev, "failed to find default display\n");
-		r = -EPROBE_DEFER;
-		goto cleanup;
-	}
-
-	r = omapfb_init_connections(fbdev, def_display);
-	if (r) {
-		dev_err(fbdev->dev, "failed to init overlay connections\n");
-		goto cleanup;
-	}
-
-	if (def_mode && strlen(def_mode) > 0) {
-		if (omapfb_parse_def_modes(fbdev))
-			dev_warn(&pdev->dev, "cannot parse default modes\n");
-	} else if (def_display && def_display->driver->set_timings &&
-			def_display->driver->check_timings) {
-		struct omap_video_timings t;
-
-		r = omapfb_find_best_mode(def_display, &t);
-
-		if (r == 0)
-			def_display->driver->set_timings(def_display, &t);
-	}
-
-	r = omapfb_create_framebuffers(fbdev);
-	if (r)
-		goto cleanup;
-
-	for (i = 0; i < fbdev->num_managers; i++) {
-		struct omap_overlay_manager *mgr;
-		mgr = fbdev->managers[i];
-		r = mgr->apply(mgr);
-		if (r)
-			dev_warn(fbdev->dev, "failed to apply dispc config\n");
-	}
-
-	DBG("mgr->apply'ed\n");
-
-	if (def_display) {
-		r = omapfb_init_display(fbdev, def_display);
-		if (r) {
-			dev_err(fbdev->dev,
-					"failed to initialize default "
-					"display\n");
-			goto cleanup;
-		}
-	}
-
-	DBG("create sysfs for fbs\n");
-	r = omapfb_create_sysfs(fbdev);
-	if (r) {
-		dev_err(fbdev->dev, "failed to create sysfs entries\n");
-		goto cleanup;
-	}
-
-	if (def_display) {
-		u16 w, h;
-
-		def_display->driver->get_resolution(def_display, &w, &h);
-
-		dev_info(fbdev->dev, "using display '%s' mode %dx%d\n",
-			def_display->name, w, h);
-	}
-
-	return 0;
-
-cleanup:
-	omapfb_free_resources(fbdev);
-	omapdss_compat_uninit();
-err0:
-	dev_err(&pdev->dev, "failed to setup omapfb\n");
-	return r;
-}
-
-static int __exit omapfb_remove(struct platform_device *pdev)
-{
-	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
-
-	/* FIXME: wait till completion of pending events */
-
-	omapfb_remove_sysfs(fbdev);
-
-	omapfb_free_resources(fbdev);
-
-	omapdss_compat_uninit();
-
-	return 0;
-}
-
-static struct platform_driver omapfb_driver = {
-	.probe		= omapfb_probe,
-	.remove         = __exit_p(omapfb_remove),
-	.driver         = {
-		.name   = "omapfb",
-		.owner  = THIS_MODULE,
-	},
-};
-
-module_param_named(mode, def_mode, charp, 0);
-module_param_named(vram, def_vram, charp, 0);
-module_param_named(rotate, def_rotate, int, 0);
-module_param_named(vrfb, def_vrfb, bool, 0);
-module_param_named(mirror, def_mirror, bool, 0);
-
-module_platform_driver(omapfb_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
-MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
deleted file mode 100644
index 18fa9e1d0033..000000000000
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * linux/drivers/video/omap2/omapfb-sysfs.c
- *
- * Copyright (C) 2008 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/fb.h>
-#include <linux/sysfs.h>
-#include <linux/device.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/omapfb.h>
-
-#include <video/omapdss.h>
-#include <video/omapvrfb.h>
-
-#include "omapfb.h"
-
-static ssize_t show_rotate_type(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
-}
-
-static ssize_t store_rotate_type(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_mem_region *rg;
-	int rot_type;
-	int r;
-
-	r = kstrtoint(buf, 0, &rot_type);
-	if (r)
-		return r;
-
-	if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
-		return -EINVAL;
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-
-	r = 0;
-	if (rot_type == ofbi->rotation_type)
-		goto out;
-
-	rg = omapfb_get_mem_region(ofbi->region);
-
-	if (rg->size) {
-		r = -EBUSY;
-		goto put_region;
-	}
-
-	ofbi->rotation_type = rot_type;
-
-	/*
-	 * Since the VRAM for this FB is not allocated at the moment we don't
-	 * need to do any further parameter checking at this point.
-	 */
-put_region:
-	omapfb_put_mem_region(rg);
-out:
-	unlock_fb_info(fbi);
-
-	return r ? r : count;
-}
-
-
-static ssize_t show_mirror(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
-}
-
-static ssize_t store_mirror(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	bool mirror;
-	int r;
-	struct fb_var_screeninfo new_var;
-
-	r = strtobool(buf, &mirror);
-	if (r)
-		return r;
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-
-	ofbi->mirror = mirror;
-
-	omapfb_get_mem_region(ofbi->region);
-
-	memcpy(&new_var, &fbi->var, sizeof(new_var));
-	r = check_fb_var(fbi, &new_var);
-	if (r)
-		goto out;
-	memcpy(&fbi->var, &new_var, sizeof(fbi->var));
-
-	set_fb_fix(fbi);
-
-	r = omapfb_apply_changes(fbi, 0);
-	if (r)
-		goto out;
-
-	r = count;
-out:
-	omapfb_put_mem_region(ofbi->region);
-
-	unlock_fb_info(fbi);
-
-	return r;
-}
-
-static ssize_t show_overlays(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	ssize_t l = 0;
-	int t;
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-	omapfb_lock(fbdev);
-
-	for (t = 0; t < ofbi->num_overlays; t++) {
-		struct omap_overlay *ovl = ofbi->overlays[t];
-		int ovlnum;
-
-		for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
-			if (ovl == fbdev->overlays[ovlnum])
-				break;
-
-		l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
-				t == 0 ? "" : ",", ovlnum);
-	}
-
-	l += snprintf(buf + l, PAGE_SIZE - l, "\n");
-
-	omapfb_unlock(fbdev);
-	unlock_fb_info(fbi);
-
-	return l;
-}
-
-static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
-		struct omap_overlay *ovl)
-{
-	int i, t;
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
-
-		for (t = 0; t < ofbi->num_overlays; t++) {
-			if (ofbi->overlays[t] == ovl)
-				return ofbi;
-		}
-	}
-
-	return NULL;
-}
-
-static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
-	struct omap_overlay *ovl;
-	int num_ovls, r, i;
-	int len;
-	bool added = false;
-
-	num_ovls = 0;
-
-	len = strlen(buf);
-	if (buf[len - 1] == '\n')
-		len = len - 1;
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-	omapfb_lock(fbdev);
-
-	if (len > 0) {
-		char *p = (char *)buf;
-		int ovlnum;
-
-		while (p < buf + len) {
-			int found;
-			if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
-				r = -EINVAL;
-				goto out;
-			}
-
-			ovlnum = simple_strtoul(p, &p, 0);
-			if (ovlnum > fbdev->num_overlays) {
-				r = -EINVAL;
-				goto out;
-			}
-
-			found = 0;
-			for (i = 0; i < num_ovls; ++i) {
-				if (ovls[i] == fbdev->overlays[ovlnum]) {
-					found = 1;
-					break;
-				}
-			}
-
-			if (!found)
-				ovls[num_ovls++] = fbdev->overlays[ovlnum];
-
-			p++;
-		}
-	}
-
-	for (i = 0; i < num_ovls; ++i) {
-		struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
-		if (ofbi2 && ofbi2 != ofbi) {
-			dev_err(fbdev->dev, "overlay already in use\n");
-			r = -EINVAL;
-			goto out;
-		}
-	}
-
-	/* detach unused overlays */
-	for (i = 0; i < ofbi->num_overlays; ++i) {
-		int t, found;
-
-		ovl = ofbi->overlays[i];
-
-		found = 0;
-
-		for (t = 0; t < num_ovls; ++t) {
-			if (ovl == ovls[t]) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (found)
-			continue;
-
-		DBG("detaching %d\n", ofbi->overlays[i]->id);
-
-		omapfb_get_mem_region(ofbi->region);
-
-		omapfb_overlay_enable(ovl, 0);
-
-		if (ovl->manager)
-			ovl->manager->apply(ovl->manager);
-
-		omapfb_put_mem_region(ofbi->region);
-
-		for (t = i + 1; t < ofbi->num_overlays; t++) {
-			ofbi->rotation[t-1] = ofbi->rotation[t];
-			ofbi->overlays[t-1] = ofbi->overlays[t];
-		}
-
-		ofbi->num_overlays--;
-		i--;
-	}
-
-	for (i = 0; i < num_ovls; ++i) {
-		int t, found;
-
-		ovl = ovls[i];
-
-		found = 0;
-
-		for (t = 0; t < ofbi->num_overlays; ++t) {
-			if (ovl == ofbi->overlays[t]) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (found)
-			continue;
-		ofbi->rotation[ofbi->num_overlays] = 0;
-		ofbi->overlays[ofbi->num_overlays++] = ovl;
-
-		added = true;
-	}
-
-	if (added) {
-		omapfb_get_mem_region(ofbi->region);
-
-		r = omapfb_apply_changes(fbi, 0);
-
-		omapfb_put_mem_region(ofbi->region);
-
-		if (r)
-			goto out;
-	}
-
-	r = count;
-out:
-	omapfb_unlock(fbdev);
-	unlock_fb_info(fbi);
-
-	return r;
-}
-
-static ssize_t show_overlays_rotate(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	ssize_t l = 0;
-	int t;
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-
-	for (t = 0; t < ofbi->num_overlays; t++) {
-		l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
-				t == 0 ? "" : ",", ofbi->rotation[t]);
-	}
-
-	l += snprintf(buf + l, PAGE_SIZE - l, "\n");
-
-	unlock_fb_info(fbi);
-
-	return l;
-}
-
-static ssize_t store_overlays_rotate(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	int num_ovls = 0, r, i;
-	int len;
-	bool changed = false;
-	u8 rotation[OMAPFB_MAX_OVL_PER_FB];
-
-	len = strlen(buf);
-	if (buf[len - 1] == '\n')
-		len = len - 1;
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-
-	if (len > 0) {
-		char *p = (char *)buf;
-
-		while (p < buf + len) {
-			int rot;
-
-			if (num_ovls == ofbi->num_overlays) {
-				r = -EINVAL;
-				goto out;
-			}
-
-			rot = simple_strtoul(p, &p, 0);
-			if (rot < 0 || rot > 3) {
-				r = -EINVAL;
-				goto out;
-			}
-
-			if (ofbi->rotation[num_ovls] != rot)
-				changed = true;
-
-			rotation[num_ovls++] = rot;
-
-			p++;
-		}
-	}
-
-	if (num_ovls != ofbi->num_overlays) {
-		r = -EINVAL;
-		goto out;
-	}
-
-	if (changed) {
-		for (i = 0; i < num_ovls; ++i)
-			ofbi->rotation[i] = rotation[i];
-
-		omapfb_get_mem_region(ofbi->region);
-
-		r = omapfb_apply_changes(fbi, 0);
-
-		omapfb_put_mem_region(ofbi->region);
-
-		if (r)
-			goto out;
-
-		/* FIXME error handling? */
-	}
-
-	r = count;
-out:
-	unlock_fb_info(fbi);
-
-	return r;
-}
-
-static ssize_t show_size(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-
-	return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
-}
-
-static ssize_t store_size(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_dss_device *display = fb2display(fbi);
-	struct omapfb2_mem_region *rg;
-	unsigned long size;
-	int r;
-	int i;
-
-	r = kstrtoul(buf, 0, &size);
-	if (r)
-		return r;
-
-	size = PAGE_ALIGN(size);
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-
-	if (display && display->driver->sync)
-		display->driver->sync(display);
-
-	rg = ofbi->region;
-
-	down_write_nested(&rg->lock, rg->id);
-	atomic_inc(&rg->lock_count);
-
-	if (atomic_read(&rg->map_count)) {
-		r = -EBUSY;
-		goto out;
-	}
-
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
-		int j;
-
-		if (ofbi2->region != rg)
-			continue;
-
-		for (j = 0; j < ofbi2->num_overlays; j++) {
-			struct omap_overlay *ovl;
-			ovl = ofbi2->overlays[j];
-			if (ovl->is_enabled(ovl)) {
-				r = -EBUSY;
-				goto out;
-			}
-		}
-	}
-
-	if (size != ofbi->region->size) {
-		r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
-		if (r) {
-			dev_err(dev, "realloc fbmem failed\n");
-			goto out;
-		}
-	}
-
-	r = count;
-out:
-	atomic_dec(&rg->lock_count);
-	up_write(&rg->lock);
-
-	unlock_fb_info(fbi);
-
-	return r;
-}
-
-static ssize_t show_phys(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-
-	return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
-}
-
-static ssize_t show_virt(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-
-	return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
-}
-
-static ssize_t show_upd_mode(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	enum omapfb_update_mode mode;
-	int r;
-
-	r = omapfb_get_update_mode(fbi, &mode);
-
-	if (r)
-		return r;
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
-}
-
-static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct fb_info *fbi = dev_get_drvdata(dev);
-	unsigned mode;
-	int r;
-
-	r = kstrtouint(buf, 0, &mode);
-	if (r)
-		return r;
-
-	r = omapfb_set_update_mode(fbi, mode);
-	if (r)
-		return r;
-
-	return count;
-}
-
-static struct device_attribute omapfb_attrs[] = {
-	__ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
-			store_rotate_type),
-	__ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
-	__ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
-	__ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
-	__ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
-			store_overlays_rotate),
-	__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
-	__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
-	__ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
-};
-
-int omapfb_create_sysfs(struct omapfb2_device *fbdev)
-{
-	int i;
-	int r;
-
-	DBG("create sysfs for fbs\n");
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		int t;
-		for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
-			r = device_create_file(fbdev->fbs[i]->dev,
-					&omapfb_attrs[t]);
-
-			if (r) {
-				dev_err(fbdev->dev, "failed to create sysfs "
-						"file\n");
-				return r;
-			}
-		}
-	}
-
-	return 0;
-}
-
-void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
-{
-	int i, t;
-
-	DBG("remove sysfs for fbs\n");
-	for (i = 0; i < fbdev->num_fbs; i++) {
-		for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
-			device_remove_file(fbdev->fbs[i]->dev,
-					&omapfb_attrs[t]);
-	}
-}
-
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
deleted file mode 100644
index 623cd872a367..000000000000
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * linux/drivers/video/omap2/omapfb.h
- *
- * Copyright (C) 2008 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * Some code and ideas taken from drivers/video/omap/ driver
- * by Imre Deak.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
-#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
-
-#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
-#define DEBUG
-#endif
-
-#include <linux/rwsem.h>
-#include <linux/dma-attrs.h>
-#include <linux/dma-mapping.h>
-
-#include <video/omapdss.h>
-
-#ifdef DEBUG
-extern bool omapfb_debug;
-#define DBG(format, ...) \
-	do { \
-		if (omapfb_debug) \
-			printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__); \
-	} while (0)
-#else
-#define DBG(format, ...)
-#endif
-
-#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
-
-/* max number of overlays to which a framebuffer data can be direct */
-#define OMAPFB_MAX_OVL_PER_FB 3
-
-struct omapfb2_mem_region {
-	int             id;
-	struct dma_attrs attrs;
-	void		*token;
-	dma_addr_t	dma_handle;
-	u32		paddr;
-	void __iomem	*vaddr;
-	struct vrfb	vrfb;
-	unsigned long	size;
-	u8		type;		/* OMAPFB_PLANE_MEM_* */
-	bool		alloc;		/* allocated by the driver */
-	bool		map;		/* kernel mapped by the driver */
-	atomic_t	map_count;
-	struct rw_semaphore lock;
-	atomic_t	lock_count;
-};
-
-/* appended to fb_info */
-struct omapfb_info {
-	int id;
-	struct omapfb2_mem_region *region;
-	int num_overlays;
-	struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
-	struct omapfb2_device *fbdev;
-	enum omap_dss_rotation_type rotation_type;
-	u8 rotation[OMAPFB_MAX_OVL_PER_FB];
-	bool mirror;
-};
-
-struct omapfb_display_data {
-	struct omapfb2_device *fbdev;
-	struct omap_dss_device *dssdev;
-	u8 bpp_override;
-	enum omapfb_update_mode update_mode;
-	bool auto_update_work_enabled;
-	struct delayed_work auto_update_work;
-};
-
-struct omapfb2_device {
-	struct device *dev;
-	struct mutex  mtx;
-
-	u32 pseudo_palette[17];
-
-	int state;
-
-	unsigned num_fbs;
-	struct fb_info *fbs[10];
-	struct omapfb2_mem_region regions[10];
-
-	unsigned num_displays;
-	struct omapfb_display_data displays[10];
-	unsigned num_overlays;
-	struct omap_overlay *overlays[10];
-	unsigned num_managers;
-	struct omap_overlay_manager *managers[10];
-
-	struct workqueue_struct *auto_update_wq;
-};
-
-struct omapfb_colormode {
-	enum omap_color_mode dssmode;
-	u32 bits_per_pixel;
-	u32 nonstd;
-	struct fb_bitfield red;
-	struct fb_bitfield green;
-	struct fb_bitfield blue;
-	struct fb_bitfield transp;
-};
-
-void set_fb_fix(struct fb_info *fbi);
-int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
-int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
-int omapfb_apply_changes(struct fb_info *fbi, int init);
-
-int omapfb_create_sysfs(struct omapfb2_device *fbdev);
-void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
-
-int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
-
-int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
-			struct fb_var_screeninfo *var);
-
-int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
-		u16 posx, u16 posy, u16 outw, u16 outh);
-
-void omapfb_start_auto_update(struct omapfb2_device *fbdev,
-		struct omap_dss_device *display);
-void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
-		struct omap_dss_device *display);
-int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
-int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
-
-/* find the display connected to this fb, if any */
-static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omap_overlay *ovl;
-
-	/* XXX: returns the display connected to first attached overlay */
-
-	if (ofbi->num_overlays == 0)
-		return NULL;
-
-	ovl = ofbi->overlays[0];
-
-	return ovl->get_device(ovl);
-}
-
-static inline struct omapfb_display_data *get_display_data(
-		struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
-{
-	int i;
-
-	for (i = 0; i < fbdev->num_displays; ++i)
-		if (fbdev->displays[i].dssdev == dssdev)
-			return &fbdev->displays[i];
-
-	/* This should never happen */
-	BUG();
-	return NULL;
-}
-
-static inline void omapfb_lock(struct omapfb2_device *fbdev)
-{
-	mutex_lock(&fbdev->mtx);
-}
-
-static inline void omapfb_unlock(struct omapfb2_device *fbdev)
-{
-	mutex_unlock(&fbdev->mtx);
-}
-
-static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
-		int enable)
-{
-	if (enable)
-		return ovl->enable(ovl);
-	else
-		return ovl->disable(ovl);
-}
-
-static inline struct omapfb2_mem_region *
-omapfb_get_mem_region(struct omapfb2_mem_region *rg)
-{
-	down_read_nested(&rg->lock, rg->id);
-	atomic_inc(&rg->lock_count);
-	return rg;
-}
-
-static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
-{
-	atomic_dec(&rg->lock_count);
-	up_read(&rg->lock);
-}
-
-#endif
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
deleted file mode 100644
index f346b02eee1d..000000000000
--- a/drivers/video/omap2/vrfb.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * VRFB Rotation Engine
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*#define DEBUG*/
-
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-
-#include <video/omapvrfb.h>
-
-#ifdef DEBUG
-#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-#define SMS_ROT_CONTROL(context)	(0x0 + 0x10 * context)
-#define SMS_ROT_SIZE(context)		(0x4 + 0x10 * context)
-#define SMS_ROT_PHYSICAL_BA(context)	(0x8 + 0x10 * context)
-#define SMS_ROT_VIRT_BASE(rot)		(0x1000000 * (rot))
-
-#define OMAP_VRFB_SIZE			(2048 * 2048 * 4)
-
-#define VRFB_PAGE_WIDTH_EXP	5 /* Assuming SDRAM pagesize= 1024 */
-#define VRFB_PAGE_HEIGHT_EXP	5 /* 1024 = 2^5 * 2^5 */
-#define VRFB_PAGE_WIDTH		(1 << VRFB_PAGE_WIDTH_EXP)
-#define VRFB_PAGE_HEIGHT	(1 << VRFB_PAGE_HEIGHT_EXP)
-#define SMS_IMAGEHEIGHT_OFFSET	16
-#define SMS_IMAGEWIDTH_OFFSET	0
-#define SMS_PH_OFFSET		8
-#define SMS_PW_OFFSET		4
-#define SMS_PS_OFFSET		0
-
-/* bitmap of reserved contexts */
-static unsigned long ctx_map;
-
-struct vrfb_ctx {
-	u32 base;
-	u32 physical_ba;
-	u32 control;
-	u32 size;
-};
-
-static DEFINE_MUTEX(ctx_lock);
-
-/*
- * Access to this happens from client drivers or the PM core after wake-up.
- * For the first case we require locking at the driver level, for the second
- * we don't need locking, since no drivers will run until after the wake-up
- * has finished.
- */
-
-static void __iomem *vrfb_base;
-
-static int num_ctxs;
-static struct vrfb_ctx *ctxs;
-
-static bool vrfb_loaded;
-
-static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
-{
-	__raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
-}
-
-static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
-{
-	__raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
-}
-
-static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
-{
-	__raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
-}
-
-static inline void restore_hw_context(int ctx)
-{
-	omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
-	omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
-	omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
-}
-
-static u32 get_image_width_roundup(u16 width, u8 bytespp)
-{
-	unsigned long stride = width * bytespp;
-	unsigned long ceil_pages_per_stride = (stride / VRFB_PAGE_WIDTH) +
-		(stride % VRFB_PAGE_WIDTH != 0);
-
-	return ceil_pages_per_stride * VRFB_PAGE_WIDTH / bytespp;
-}
-
-/*
- * This the extra space needed in the VRFB physical area for VRFB to safely wrap
- * any memory accesses to the invisible part of the virtual view to the physical
- * area.
- */
-static inline u32 get_extra_physical_size(u16 image_width_roundup, u8 bytespp)
-{
-	return (OMAP_VRFB_LINE_LEN - image_width_roundup) * VRFB_PAGE_HEIGHT *
-		bytespp;
-}
-
-void omap_vrfb_restore_context(void)
-{
-	int i;
-	unsigned long map = ctx_map;
-
-	for (i = ffs(map); i; i = ffs(map)) {
-		/* i=1..32 */
-		i--;
-		map &= ~(1 << i);
-		restore_hw_context(i);
-	}
-}
-
-void omap_vrfb_adjust_size(u16 *width, u16 *height,
-		u8 bytespp)
-{
-	*width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
-	*height = ALIGN(*height, VRFB_PAGE_HEIGHT);
-}
-EXPORT_SYMBOL(omap_vrfb_adjust_size);
-
-u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
-{
-	unsigned long image_width_roundup = get_image_width_roundup(width,
-		bytespp);
-
-	if (image_width_roundup > OMAP_VRFB_LINE_LEN)
-		return 0;
-
-	return (width * height * bytespp) + get_extra_physical_size(
-		image_width_roundup, bytespp);
-}
-EXPORT_SYMBOL(omap_vrfb_min_phys_size);
-
-u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
-{
-	unsigned long image_width_roundup = get_image_width_roundup(width,
-		bytespp);
-	unsigned long height;
-	unsigned long extra;
-
-	if (image_width_roundup > OMAP_VRFB_LINE_LEN)
-		return 0;
-
-	extra = get_extra_physical_size(image_width_roundup, bytespp);
-
-	if (phys_size < extra)
-		return 0;
-
-	height = (phys_size - extra) / (width * bytespp);
-
-	/* Virtual views provided by VRFB are limited to 2048x2048. */
-	return min_t(unsigned long, height, 2048);
-}
-EXPORT_SYMBOL(omap_vrfb_max_height);
-
-void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
-		u16 width, u16 height,
-		unsigned bytespp, bool yuv_mode)
-{
-	unsigned pixel_size_exp;
-	u16 vrfb_width;
-	u16 vrfb_height;
-	u8 ctx = vrfb->context;
-	u32 size;
-	u32 control;
-
-	DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d, %d)\n", ctx, paddr,
-			width, height, bytespp, yuv_mode);
-
-	/* For YUV2 and UYVY modes VRFB needs to handle pixels a bit
-	 * differently. See TRM. */
-	if (yuv_mode) {
-		bytespp *= 2;
-		width /= 2;
-	}
-
-	if (bytespp == 4)
-		pixel_size_exp = 2;
-	else if (bytespp == 2)
-		pixel_size_exp = 1;
-	else {
-		BUG();
-		return;
-	}
-
-	vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
-	vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
-
-	DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
-
-	size  = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
-	size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
-
-	control  = pixel_size_exp << SMS_PS_OFFSET;
-	control |= VRFB_PAGE_WIDTH_EXP  << SMS_PW_OFFSET;
-	control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
-
-	ctxs[ctx].physical_ba = paddr;
-	ctxs[ctx].size = size;
-	ctxs[ctx].control = control;
-
-	omap2_sms_write_rot_physical_ba(paddr, ctx);
-	omap2_sms_write_rot_size(size, ctx);
-	omap2_sms_write_rot_control(control, ctx);
-
-	DBG("vrfb offset pixels %d, %d\n",
-			vrfb_width - width, vrfb_height - height);
-
-	vrfb->xres = width;
-	vrfb->yres = height;
-	vrfb->xoffset = vrfb_width - width;
-	vrfb->yoffset = vrfb_height - height;
-	vrfb->bytespp = bytespp;
-	vrfb->yuv_mode = yuv_mode;
-}
-EXPORT_SYMBOL(omap_vrfb_setup);
-
-int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
-{
-	unsigned long size = height * OMAP_VRFB_LINE_LEN * vrfb->bytespp;
-
-	vrfb->vaddr[rot] = ioremap_wc(vrfb->paddr[rot], size);
-
-	if (!vrfb->vaddr[rot]) {
-		printk(KERN_ERR "vrfb: ioremap failed\n");
-		return -ENOMEM;
-	}
-
-	DBG("ioremapped vrfb area %d of size %lu into %p\n", rot, size,
-		vrfb->vaddr[rot]);
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_vrfb_map_angle);
-
-void omap_vrfb_release_ctx(struct vrfb *vrfb)
-{
-	int rot;
-	int ctx = vrfb->context;
-
-	if (ctx == 0xff)
-		return;
-
-	DBG("release ctx %d\n", ctx);
-
-	mutex_lock(&ctx_lock);
-
-	BUG_ON(!(ctx_map & (1 << ctx)));
-
-	clear_bit(ctx, &ctx_map);
-
-	for (rot = 0; rot < 4; ++rot) {
-		if (vrfb->paddr[rot]) {
-			release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
-			vrfb->paddr[rot] = 0;
-		}
-	}
-
-	vrfb->context = 0xff;
-
-	mutex_unlock(&ctx_lock);
-}
-EXPORT_SYMBOL(omap_vrfb_release_ctx);
-
-int omap_vrfb_request_ctx(struct vrfb *vrfb)
-{
-	int rot;
-	u32 paddr;
-	u8 ctx;
-	int r;
-
-	DBG("request ctx\n");
-
-	mutex_lock(&ctx_lock);
-
-	for (ctx = 0; ctx < num_ctxs; ++ctx)
-		if ((ctx_map & (1 << ctx)) == 0)
-			break;
-
-	if (ctx == num_ctxs) {
-		pr_err("vrfb: no free contexts\n");
-		r = -EBUSY;
-		goto out;
-	}
-
-	DBG("found free ctx %d\n", ctx);
-
-	set_bit(ctx, &ctx_map);
-
-	memset(vrfb, 0, sizeof(*vrfb));
-
-	vrfb->context = ctx;
-
-	for (rot = 0; rot < 4; ++rot) {
-		paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
-		if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
-			pr_err("vrfb: failed to reserve VRFB "
-					"area for ctx %d, rotation %d\n",
-					ctx, rot * 90);
-			omap_vrfb_release_ctx(vrfb);
-			r = -ENOMEM;
-			goto out;
-		}
-
-		vrfb->paddr[rot] = paddr;
-
-		DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
-	}
-
-	r = 0;
-out:
-	mutex_unlock(&ctx_lock);
-	return r;
-}
-EXPORT_SYMBOL(omap_vrfb_request_ctx);
-
-bool omap_vrfb_supported(void)
-{
-	return vrfb_loaded;
-}
-EXPORT_SYMBOL(omap_vrfb_supported);
-
-static int __init vrfb_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int i;
-
-	/* first resource is the register res, the rest are vrfb contexts */
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	vrfb_base = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(vrfb_base))
-		return PTR_ERR(vrfb_base);
-
-	num_ctxs = pdev->num_resources - 1;
-
-	ctxs = devm_kzalloc(&pdev->dev,
-			sizeof(struct vrfb_ctx) * num_ctxs,
-			GFP_KERNEL);
-
-	if (!ctxs)
-		return -ENOMEM;
-
-	for (i = 0; i < num_ctxs; ++i) {
-		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
-		if (!mem) {
-			dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
-					i);
-			return -EINVAL;
-		}
-
-		ctxs[i].base = mem->start;
-	}
-
-	vrfb_loaded = true;
-
-	return 0;
-}
-
-static void __exit vrfb_remove(struct platform_device *pdev)
-{
-	vrfb_loaded = false;
-}
-
-static struct platform_driver vrfb_driver = {
-	.driver.name	= "omapvrfb",
-	.remove		= __exit_p(vrfb_remove),
-};
-
-module_platform_driver_probe(vrfb_driver, vrfb_probe);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("OMAP VRFB");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
deleted file mode 100644
index 367cea8f43f3..000000000000
--- a/drivers/video/p9100.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/* p9100.c: P9100 frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			   unsigned, struct fb_info *);
-static int p9100_blank(int, struct fb_info *);
-
-static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
-static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops p9100_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= p9100_setcolreg,
-	.fb_blank		= p9100_blank,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_mmap		= p9100_mmap,
-	.fb_ioctl		= p9100_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-/* P9100 control registers */
-#define P9100_SYSCTL_OFF	0x0UL
-#define P9100_VIDEOCTL_OFF	0x100UL
-#define P9100_VRAMCTL_OFF 	0x180UL
-#define P9100_RAMDAC_OFF 	0x200UL
-#define P9100_VIDEOCOPROC_OFF 	0x400UL
-
-/* P9100 command registers */
-#define P9100_CMD_OFF 0x0UL
-
-/* P9100 framebuffer memory */
-#define P9100_FB_OFF 0x0UL
-
-/* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
-#define SYS_CONFIG_PIXELSIZE_SHIFT 26 
-
-#define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
-
-struct p9100_regs {
-	/* Registers for the system control */
-	u32 sys_base;
-	u32 sys_config;
-	u32 sys_intr;
-	u32 sys_int_ena;
-	u32 sys_alt_rd;
-	u32 sys_alt_wr;
-	u32 sys_xxx[58];
-
-	/* Registers for the video control */
-	u32 vid_base;
-	u32 vid_hcnt;
-	u32 vid_htotal;
-	u32 vid_hsync_rise;
-	u32 vid_hblank_rise;
-	u32 vid_hblank_fall;
-	u32 vid_hcnt_preload;
-	u32 vid_vcnt;
-	u32 vid_vlen;
-	u32 vid_vsync_rise;
-	u32 vid_vblank_rise;
-	u32 vid_vblank_fall;
-	u32 vid_vcnt_preload;
-	u32 vid_screenpaint_addr;
-	u32 vid_screenpaint_timectl1;
-	u32 vid_screenpaint_qsfcnt;
-	u32 vid_screenpaint_timectl2;
-	u32 vid_xxx[15];
-
-	/* Registers for the video control */
-	u32 vram_base;
-	u32 vram_memcfg;
-	u32 vram_refresh_pd;
-	u32 vram_refresh_cnt;
-	u32 vram_raslo_max;
-	u32 vram_raslo_cur;
-	u32 pwrup_cfg;
-	u32 vram_xxx[25];
-
-	/* Registers for IBM RGB528 Palette */
-	u32 ramdac_cmap_wridx; 
-	u32 ramdac_palette_data;
-	u32 ramdac_pixel_mask;
-	u32 ramdac_palette_rdaddr;
-	u32 ramdac_idx_lo;
-	u32 ramdac_idx_hi;
-	u32 ramdac_idx_data;
-	u32 ramdac_idx_ctl;
-	u32 ramdac_xxx[1784];
-};
-
-struct p9100_cmd_parameng {
-	u32 parameng_status;
-	u32 parameng_bltcmd;
-	u32 parameng_quadcmd;
-};
-
-struct p9100_par {
-	spinlock_t		lock;
-	struct p9100_regs	__iomem *regs;
-
-	u32			flags;
-#define P9100_FLAG_BLANKED	0x00000001
-
-	unsigned long		which_io;
-};
-
-/**
- *      p9100_setcolreg - Optional function. Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *      @green: The green value which can be up to 16 bits wide
- *      @blue:  The blue value which can be up to 16 bits wide.
- *      @transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- */
-static int p9100_setcolreg(unsigned regno,
-			   unsigned red, unsigned green, unsigned blue,
-			   unsigned transp, struct fb_info *info)
-{
-	struct p9100_par *par = (struct p9100_par *) info->par;
-	struct p9100_regs __iomem *regs = par->regs;
-	unsigned long flags;
-
-	if (regno >= 256)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	sbus_writel((regno << 16), &regs->ramdac_cmap_wridx);
-	sbus_writel((red << 16), &regs->ramdac_palette_data);
-	sbus_writel((green << 16), &regs->ramdac_palette_data);
-	sbus_writel((blue << 16), &regs->ramdac_palette_data);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-/**
- *      p9100_blank - Optional function.  Blanks the display.
- *      @blank_mode: the blank mode we want.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-p9100_blank(int blank, struct fb_info *info)
-{
-	struct p9100_par *par = (struct p9100_par *) info->par;
-	struct p9100_regs __iomem *regs = par->regs;
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		val = sbus_readl(&regs->vid_screenpaint_timectl1);
-		val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
-		sbus_writel(val, &regs->vid_screenpaint_timectl1);
-		par->flags &= ~P9100_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		val = sbus_readl(&regs->vid_screenpaint_timectl1);
-		val &= ~SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
-		sbus_writel(val, &regs->vid_screenpaint_timectl1);
-		par->flags |= P9100_FLAG_BLANKED;
-		break;
-	}
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static struct sbus_mmap_map p9100_mmap_map[] = {
-	{ CG3_MMAP_OFFSET,	0,		SBUS_MMAP_FBSIZE(1) },
-	{ 0,			0,		0		    }
-};
-
-static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct p9100_par *par = (struct p9100_par *)info->par;
-
-	return sbusfb_mmap_helper(p9100_mmap_map,
-				  info->fix.smem_start, info->fix.smem_len,
-				  par->which_io, vma);
-}
-
-static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
-		       unsigned long arg)
-{
-	/* Make it look like a cg3. */
-	return sbusfb_ioctl_helper(cmd, arg, info,
-				   FBTYPE_SUN3COLOR, 8, info->fix.smem_len);
-}
-
-/*
- *  Initialisation
- */
-
-static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
-{
-	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = linebytes;
-
-	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
-}
-
-static int p9100_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct p9100_par *par;
-	int linebytes, err;
-
-	info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-
-	/* This is the framebuffer and the only resource apps can mmap.  */
-	info->fix.smem_start = op->resource[2].start;
-	par->which_io = op->resource[2].flags & IORESOURCE_BITS;
-
-	sbusfb_fill_var(&info->var, dp, 8);
-	info->var.red.length = 8;
-	info->var.green.length = 8;
-	info->var.blue.length = 8;
-
-	linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
-	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
-
-	par->regs = of_ioremap(&op->resource[0], 0,
-			       sizeof(struct p9100_regs), "p9100 regs");
-	if (!par->regs)
-		goto out_release_fb;
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &p9100_ops;
-	info->screen_base = of_ioremap(&op->resource[2], 0,
-				       info->fix.smem_len, "p9100 ram");
-	if (!info->screen_base)
-		goto out_unmap_regs;
-
-	p9100_blank(FB_BLANK_UNBLANK, info);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0))
-		goto out_unmap_screen;
-
-	p9100_init_fix(info, linebytes, dp);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_dealloc_cmap;
-
-	fb_set_cmap(&info->cmap, info);
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: p9100 at %lx:%lx\n",
-	       dp->full_name,
-	       par->which_io, info->fix.smem_start);
-
-	return 0;
-
-out_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-out_unmap_screen:
-	of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
-
-out_unmap_regs:
-	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
-
-out_release_fb:
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int p9100_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct p9100_par *par = info->par;
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
-	of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id p9100_match[] = {
-	{
-		.name = "p9100",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, p9100_match);
-
-static struct platform_driver p9100_driver = {
-	.driver = {
-		.name = "p9100",
-		.owner = THIS_MODULE,
-		.of_match_table = p9100_match,
-	},
-	.probe		= p9100_probe,
-	.remove		= p9100_remove,
-};
-
-static int __init p9100_init(void)
-{
-	if (fb_get_options("p9100fb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&p9100_driver);
-}
-
-static void __exit p9100_exit(void)
-{
-	platform_driver_unregister(&p9100_driver);
-}
-
-module_init(p9100_init);
-module_exit(p9100_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
deleted file mode 100644
index 4c9299576827..000000000000
--- a/drivers/video/platinumfb.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- *  platinumfb.c -- frame buffer device for the PowerMac 'platinum' display
- *
- *  Copyright (C) 1998 Franz Sirl
- *
- *  Frame buffer structure from:
- *    drivers/video/controlfb.c -- frame buffer device for
- *    Apple 'control' display chip.
- *    Copyright (C) 1998 Dan Jacobowitz
- *
- *  Hardware information from:
- *    platinum.c: Console support for PowerMac "platinum" display adaptor.
- *    Copyright (C) 1996 Paul Mackerras and Mark Abene
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/nvram.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pgtable.h>
-
-#include "macmodes.h"
-#include "platinumfb.h"
-
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
-
-struct fb_info_platinum {
-	struct fb_info			*info;
-
-	int				vmode, cmode;
-	int				xres, yres;
-	int				vxres, vyres;
-	int				xoffset, yoffset;
-
-	struct {
-		__u8 red, green, blue;
-	}				palette[256];
-	u32				pseudo_palette[16];
-	
-	volatile struct cmap_regs	__iomem *cmap_regs;
-	unsigned long			cmap_regs_phys;
-	
-	volatile struct platinum_regs	__iomem *platinum_regs;
-	unsigned long			platinum_regs_phys;
-	
-	__u8				__iomem *frame_buffer;
-	volatile __u8			__iomem *base_frame_buffer;
-	unsigned long			frame_buffer_phys;
-	
-	unsigned long			total_vram;
-	int				clktype;
-	int				dactype;
-
-	struct resource			rsrc_fb, rsrc_reg;
-};
-
-/*
- * Frame buffer device API
- */
-
-static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-	u_int transp, struct fb_info *info);
-static int platinumfb_blank(int blank_mode, struct fb_info *info);
-static int platinumfb_set_par (struct fb_info *info);
-static int platinumfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
-
-/*
- * internal functions
- */
-
-static inline int platinum_vram_reqd(int video_mode, int color_mode);
-static int read_platinum_sense(struct fb_info_platinum *pinfo);
-static void set_platinum_clock(struct fb_info_platinum *pinfo);
-static void platinum_set_hardware(struct fb_info_platinum *pinfo);
-static int platinum_var_to_par(struct fb_var_screeninfo *var,
-			       struct fb_info_platinum *pinfo,
-			       int check_only);
-
-/*
- * Interface used by the world
- */
-
-static struct fb_ops platinumfb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_check_var	= platinumfb_check_var,
-	.fb_set_par	= platinumfb_set_par,
-	.fb_setcolreg	= platinumfb_setcolreg,
-	.fb_blank	= platinumfb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-/*
- * Checks a var structure
- */
-static int platinumfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	return platinum_var_to_par(var, info->par, 1);
-}
-
-/*
- * Applies current var to display
- */
-static int platinumfb_set_par (struct fb_info *info)
-{
-	struct fb_info_platinum *pinfo = info->par;
-	struct platinum_regvals *init;
-	int err, offset = 0x20;
-
-	if((err = platinum_var_to_par(&info->var, pinfo, 0))) {
-		printk (KERN_ERR "platinumfb_set_par: error calling"
-				 " platinum_var_to_par: %d.\n", err);
-		return err;
-	}
-
-	platinum_set_hardware(pinfo);
-
-	init = platinum_reg_init[pinfo->vmode-1];
-	
- 	if ((pinfo->vmode == VMODE_832_624_75) && (pinfo->cmode > CMODE_8))
-  		offset = 0x10;
-
-	info->screen_base = pinfo->frame_buffer + init->fb_offset + offset;
-	mutex_lock(&info->mm_lock);
-	info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
-	mutex_unlock(&info->mm_lock);
-	info->fix.visual = (pinfo->cmode == CMODE_8) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
- 	info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode)
-		+ offset;
-	printk("line_length: %x\n", info->fix.line_length);
-	return 0;
-}
-
-static int platinumfb_blank(int blank,  struct fb_info *fb)
-{
-/*
- *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
- *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
- *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
- *  to e.g. a video mode which doesn't support it. Implements VESA suspend
- *  and powerdown modes on hardware that supports disabling hsync/vsync:
- *    blank_mode == 2: suspend vsync
- *    blank_mode == 3: suspend hsync
- *    blank_mode == 4: powerdown
- */
-/* [danj] I think there's something fishy about those constants... */
-/*
-	struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
-	int	ctrl;
-
-	ctrl = ld_le32(&info->platinum_regs->ctrl.r) | 0x33;
-	if (blank)
-		--blank_mode;
-	if (blank & VESA_VSYNC_SUSPEND)
-		ctrl &= ~3;
-	if (blank & VESA_HSYNC_SUSPEND)
-		ctrl &= ~0x30;
-	out_le32(&info->platinum_regs->ctrl.r, ctrl);
-*/
-/* TODO: Figure out how the heck to powerdown this thing! */
-	return 0;
-}
-
-static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			      u_int transp, struct fb_info *info)
-{
-	struct fb_info_platinum *pinfo = info->par;
-	volatile struct cmap_regs __iomem *cmap_regs = pinfo->cmap_regs;
-
-	if (regno > 255)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	pinfo->palette[regno].red = red;
-	pinfo->palette[regno].green = green;
-	pinfo->palette[regno].blue = blue;
-
-	out_8(&cmap_regs->addr, regno);		/* tell clut what addr to fill	*/
-	out_8(&cmap_regs->lut, red);		/* send one color channel at	*/
-	out_8(&cmap_regs->lut, green);		/* a time...			*/
-	out_8(&cmap_regs->lut, blue);
-
-	if (regno < 16) {
-		int i;
-		u32 *pal = info->pseudo_palette;
-		switch (pinfo->cmode) {
-		case CMODE_16:
-			pal[regno] = (regno << 10) | (regno << 5) | regno;
-			break;
-		case CMODE_32:
-			i = (regno << 8) | regno;
-			pal[regno] = (i << 16) | i;
-			break;
-		}
-	}
-	
-	return 0;
-}
-
-static inline int platinum_vram_reqd(int video_mode, int color_mode)
-{
-	int baseval = vmode_attrs[video_mode-1].hres * (1<<color_mode);
-
-	if ((video_mode == VMODE_832_624_75) && (color_mode > CMODE_8))
-		baseval += 0x10;
-	else
-		baseval += 0x20;
-
-	return vmode_attrs[video_mode-1].vres * baseval + 0x1000;
-}
-
-#define STORE_D2(a, d) { \
-	out_8(&cmap_regs->addr, (a+32)); \
-	out_8(&cmap_regs->d2, (d)); \
-}
-
-static void set_platinum_clock(struct fb_info_platinum *pinfo)
-{
-	volatile struct cmap_regs __iomem *cmap_regs = pinfo->cmap_regs;
-	struct platinum_regvals	*init;
-
-	init = platinum_reg_init[pinfo->vmode-1];
-
-	STORE_D2(6, 0xc6);
-	out_8(&cmap_regs->addr,3+32);
-
-	if (in_8(&cmap_regs->d2) == 2) {
-		STORE_D2(7, init->clock_params[pinfo->clktype][0]);
-		STORE_D2(8, init->clock_params[pinfo->clktype][1]);
-		STORE_D2(3, 3);
-	} else {
-		STORE_D2(4, init->clock_params[pinfo->clktype][0]);
-		STORE_D2(5, init->clock_params[pinfo->clktype][1]);
-		STORE_D2(3, 2);
-	}
-
-	__delay(5000);
-	STORE_D2(9, 0xa6);
-}
-
-
-/* Now how about actually saying, Make it so! */
-/* Some things in here probably don't need to be done each time. */
-static void platinum_set_hardware(struct fb_info_platinum *pinfo)
-{
-	volatile struct platinum_regs	__iomem *platinum_regs = pinfo->platinum_regs;
-	volatile struct cmap_regs	__iomem *cmap_regs = pinfo->cmap_regs;
-	struct platinum_regvals		*init;
-	int				i;
-	int				vmode, cmode;
-	
-	vmode = pinfo->vmode;
-	cmode = pinfo->cmode;
-
-	init = platinum_reg_init[vmode - 1];
-
-	/* Initialize display timing registers */
-	out_be32(&platinum_regs->reg[24].r, 7);	/* turn display off */
-
-	for (i = 0; i < 26; ++i)
-		out_be32(&platinum_regs->reg[i+32].r, init->regs[i]);
-
-	out_be32(&platinum_regs->reg[26+32].r, (pinfo->total_vram == 0x100000 ?
-						init->offset[cmode] + 4 - cmode :
-						init->offset[cmode]));
-	out_be32(&platinum_regs->reg[16].r, (unsigned) pinfo->frame_buffer_phys+init->fb_offset+0x10);
-	out_be32(&platinum_regs->reg[18].r, init->pitch[cmode]);
-	out_be32(&platinum_regs->reg[19].r, (pinfo->total_vram == 0x100000 ?
-					     init->mode[cmode+1] :
-					     init->mode[cmode]));
-	out_be32(&platinum_regs->reg[20].r, (pinfo->total_vram == 0x100000 ? 0x11 : 0x1011));
-	out_be32(&platinum_regs->reg[21].r, 0x100);
-	out_be32(&platinum_regs->reg[22].r, 1);
-	out_be32(&platinum_regs->reg[23].r, 1);
-	out_be32(&platinum_regs->reg[26].r, 0xc00);
-	out_be32(&platinum_regs->reg[27].r, 0x235);
-	/* out_be32(&platinum_regs->reg[27].r, 0x2aa); */
-
-	STORE_D2(0, (pinfo->total_vram == 0x100000 ?
-		     init->dacula_ctrl[cmode] & 0xf :
-		     init->dacula_ctrl[cmode]));
-	STORE_D2(1, 4);
-	STORE_D2(2, 0);
-
-	set_platinum_clock(pinfo);
-
-	out_be32(&platinum_regs->reg[24].r, 0);	/* turn display on */
-}
-
-/*
- * Set misc info vars for this driver
- */
-static void platinum_init_info(struct fb_info *info,
-			       struct fb_info_platinum *pinfo)
-{
-	/* Fill fb_info */
-	info->fbops = &platinumfb_ops;
-	info->pseudo_palette = pinfo->pseudo_palette;
-        info->flags = FBINFO_DEFAULT;
-	info->screen_base = pinfo->frame_buffer + 0x20;
-
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	/* Fill fix common fields */
-	strcpy(info->fix.id, "platinum");
-	info->fix.mmio_start = pinfo->platinum_regs_phys;
-	info->fix.mmio_len = 0x1000;
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.smem_start = pinfo->frame_buffer_phys + 0x20; /* will be updated later */
-	info->fix.smem_len = pinfo->total_vram - 0x20;
-        info->fix.ywrapstep = 0;
-	info->fix.xpanstep = 0;
-	info->fix.ypanstep = 0;
-        info->fix.type_aux = 0;
-        info->fix.accel = FB_ACCEL_NONE;
-}
-
-
-static int platinum_init_fb(struct fb_info *info)
-{
-	struct fb_info_platinum *pinfo = info->par;
-	struct fb_var_screeninfo var;
-	int sense, rc;
-
-	sense = read_platinum_sense(pinfo);
-	printk(KERN_INFO "platinumfb: Monitor sense value = 0x%x, ", sense);
-	if (default_vmode == VMODE_NVRAM) {
-#ifdef CONFIG_NVRAM
-		default_vmode = nvram_read_byte(NV_VMODE);
-		if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
-		    !platinum_reg_init[default_vmode-1])
-#endif
-			default_vmode = VMODE_CHOOSE;
-	}
-	if (default_vmode == VMODE_CHOOSE) {
-		default_vmode = mac_map_monitor_sense(sense);
-	}
-	if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-		default_vmode = VMODE_640_480_60;
-#ifdef CONFIG_NVRAM
-	if (default_cmode == CMODE_NVRAM)
-		default_cmode = nvram_read_byte(NV_CMODE);
-#endif
-	if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
-		default_cmode = CMODE_8;
-	/*
-	 * Reduce the pixel size if we don't have enough VRAM.
-	 */
-	while(default_cmode > CMODE_8 &&
-	      platinum_vram_reqd(default_vmode, default_cmode) > pinfo->total_vram)
-		default_cmode--;
-
-	printk("platinumfb:  Using video mode %d and color mode %d.\n", default_vmode, default_cmode);
-
-	/* Setup default var */
-	if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) {
-		/* This shouldn't happen! */
-		printk("mac_vmode_to_var(%d, %d,) failed\n", default_vmode, default_cmode);
-try_again:
-		default_vmode = VMODE_640_480_60;
-		default_cmode = CMODE_8;
-		if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) {
-			printk(KERN_ERR "platinumfb: mac_vmode_to_var() failed\n");
-			return -ENXIO;
-		}
-	}
-
-	/* Initialize info structure */
-	platinum_init_info(info, pinfo);
-
-	/* Apply default var */
-	info->var = var;
-	var.activate = FB_ACTIVATE_NOW;
-	rc = fb_set_var(info, &var);
-	if (rc && (default_vmode != VMODE_640_480_60 || default_cmode != CMODE_8))
-		goto try_again;
-
-	/* Register with fbdev layer */
-	rc = register_framebuffer(info);
-	if (rc < 0)
-		return rc;
-
-	fb_info(info, "Apple Platinum frame buffer device\n");
-
-	return 0;
-}
-
-/*
- * Get the monitor sense value.
- * Note that this can be called before calibrate_delay,
- * so we can't use udelay.
- */
-static int read_platinum_sense(struct fb_info_platinum *info)
-{
-	volatile struct platinum_regs __iomem *platinum_regs = info->platinum_regs;
-	int sense;
-
-	out_be32(&platinum_regs->reg[23].r, 7);	/* turn off drivers */
-	__delay(2000);
-	sense = (~in_be32(&platinum_regs->reg[23].r) & 7) << 8;
-
-	/* drive each sense line low in turn and collect the other 2 */
-	out_be32(&platinum_regs->reg[23].r, 3);	/* drive A low */
-	__delay(2000);
-	sense |= (~in_be32(&platinum_regs->reg[23].r) & 3) << 4;
-	out_be32(&platinum_regs->reg[23].r, 5);	/* drive B low */
-	__delay(2000);
-	sense |= (~in_be32(&platinum_regs->reg[23].r) & 4) << 1;
-	sense |= (~in_be32(&platinum_regs->reg[23].r) & 1) << 2;
-	out_be32(&platinum_regs->reg[23].r, 6);	/* drive C low */
-	__delay(2000);
-	sense |= (~in_be32(&platinum_regs->reg[23].r) & 6) >> 1;
-
-	out_be32(&platinum_regs->reg[23].r, 7);	/* turn off drivers */
-
-	return sense;
-}
-
-/*
- * This routine takes a user-supplied var, and picks the best vmode/cmode from it.
- * It also updates the var structure to the actual mode data obtained
- */
-static int platinum_var_to_par(struct fb_var_screeninfo *var, 
-			       struct fb_info_platinum *pinfo,
-			       int check_only)
-{
-	int vmode, cmode;
-
-	if (mac_var_to_vmode(var, &vmode, &cmode) != 0) {
-		printk(KERN_ERR "platinum_var_to_par: mac_var_to_vmode unsuccessful.\n");
-		printk(KERN_ERR "platinum_var_to_par: var->xres = %d\n", var->xres);
-		printk(KERN_ERR "platinum_var_to_par: var->yres = %d\n", var->yres);
-		printk(KERN_ERR "platinum_var_to_par: var->xres_virtual = %d\n", var->xres_virtual);
-		printk(KERN_ERR "platinum_var_to_par: var->yres_virtual = %d\n", var->yres_virtual);
-		printk(KERN_ERR "platinum_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel);
-		printk(KERN_ERR "platinum_var_to_par: var->pixclock = %d\n", var->pixclock);
-		printk(KERN_ERR "platinum_var_to_par: var->vmode = %d\n", var->vmode);
-		return -EINVAL;
-	}
-
-	if (!platinum_reg_init[vmode-1]) {
-		printk(KERN_ERR "platinum_var_to_par, vmode %d not valid.\n", vmode);
-		return -EINVAL;
-	}
-
-	if (platinum_vram_reqd(vmode, cmode) > pinfo->total_vram) {
-		printk(KERN_ERR "platinum_var_to_par, not enough ram for vmode %d, cmode %d.\n", vmode, cmode);
-		return -EINVAL;
-	}
-
-	if (mac_vmode_to_var(vmode, cmode, var))
-		return -EINVAL;
-
-	if (check_only)
-		return 0;
-
-	pinfo->vmode = vmode;
-	pinfo->cmode = cmode;
-	pinfo->xres = vmode_attrs[vmode-1].hres;
-	pinfo->yres = vmode_attrs[vmode-1].vres;
-	pinfo->xoffset = 0;
-	pinfo->yoffset = 0;
-	pinfo->vxres = pinfo->xres;
-	pinfo->vyres = pinfo->yres;
-	
-	return 0;
-}
-
-
-/* 
- * Parse user specified options (`video=platinumfb:')
- */
-static int __init platinumfb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "vmode:", 6)) {
-	    		int vmode = simple_strtoul(this_opt+6, NULL, 0);
-			if (vmode > 0 && vmode <= VMODE_MAX)
-				default_vmode = vmode;
-		} else if (!strncmp(this_opt, "cmode:", 6)) {
-			int depth = simple_strtoul(this_opt+6, NULL, 0);
-			switch (depth) {
-			 case 0:
-			 case 8:
-			    default_cmode = CMODE_8;
-			    break;
-			 case 15:
-			 case 16:
-			    default_cmode = CMODE_16;
-			    break;
-			 case 24:
-			 case 32:
-			    default_cmode = CMODE_32;
-			    break;
-			}
-		}
-	}
-	return 0;
-}
-
-#ifdef __powerpc__
-#define invalidate_cache(addr) \
-	asm volatile("eieio; dcbf 0,%1" \
-	: "=m" (*(addr)) : "r" (addr) : "memory");
-#else
-#define invalidate_cache(addr)
-#endif
-
-static int platinumfb_probe(struct platform_device* odev)
-{
-	struct device_node	*dp = odev->dev.of_node;
-	struct fb_info		*info;
-	struct fb_info_platinum	*pinfo;
-	volatile __u8		*fbuffer;
-	int			bank0, bank1, bank2, bank3, rc;
-
-	dev_info(&odev->dev, "Found Apple Platinum video hardware\n");
-
-	info = framebuffer_alloc(sizeof(*pinfo), &odev->dev);
-	if (info == NULL) {
-		dev_err(&odev->dev, "Failed to allocate fbdev !\n");
-		return -ENOMEM;
-	}
-	pinfo = info->par;
-
-	if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) ||
-	    of_address_to_resource(dp, 1, &pinfo->rsrc_fb)) {
-		dev_err(&odev->dev, "Can't get resources\n");
-		framebuffer_release(info);
-		return -ENXIO;
-	}
-	dev_dbg(&odev->dev, " registers  : 0x%llx...0x%llx\n",
-		(unsigned long long)pinfo->rsrc_reg.start,
-		(unsigned long long)pinfo->rsrc_reg.end);
-	dev_dbg(&odev->dev, " framebuffer: 0x%llx...0x%llx\n",
-		(unsigned long long)pinfo->rsrc_fb.start,
-		(unsigned long long)pinfo->rsrc_fb.end);
-
-	/* Do not try to request register space, they overlap with the
-	 * northbridge and that can fail. Only request framebuffer
-	 */
-	if (!request_mem_region(pinfo->rsrc_fb.start,
-				resource_size(&pinfo->rsrc_fb),
-				"platinumfb framebuffer")) {
-		printk(KERN_ERR "platinumfb: Can't request framebuffer !\n");
-		framebuffer_release(info);
-		return -ENXIO;
-	}
-
-	/* frame buffer - map only 4MB */
-	pinfo->frame_buffer_phys = pinfo->rsrc_fb.start;
-	pinfo->frame_buffer = __ioremap(pinfo->rsrc_fb.start, 0x400000,
-					_PAGE_WRITETHRU);
-	pinfo->base_frame_buffer = pinfo->frame_buffer;
-
-	/* registers */
-	pinfo->platinum_regs_phys = pinfo->rsrc_reg.start;
-	pinfo->platinum_regs = ioremap(pinfo->rsrc_reg.start, 0x1000);
-
-	pinfo->cmap_regs_phys = 0xf301b000;	/* XXX not in prom? */
-	request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap");
-	pinfo->cmap_regs = ioremap(pinfo->cmap_regs_phys, 0x1000);
-
-	/* Grok total video ram */
-	out_be32(&pinfo->platinum_regs->reg[16].r, (unsigned)pinfo->frame_buffer_phys);
-	out_be32(&pinfo->platinum_regs->reg[20].r, 0x1011);	/* select max vram */
-	out_be32(&pinfo->platinum_regs->reg[24].r, 0);	/* switch in vram */
-
-	fbuffer = pinfo->base_frame_buffer;
-	fbuffer[0x100000] = 0x34;
-	fbuffer[0x100008] = 0x0;
-	invalidate_cache(&fbuffer[0x100000]);
-	fbuffer[0x200000] = 0x56;
-	fbuffer[0x200008] = 0x0;
-	invalidate_cache(&fbuffer[0x200000]);
-	fbuffer[0x300000] = 0x78;
-	fbuffer[0x300008] = 0x0;
-	invalidate_cache(&fbuffer[0x300000]);
-	bank0 = 1; /* builtin 1MB vram, always there */
-	bank1 = fbuffer[0x100000] == 0x34;
-	bank2 = fbuffer[0x200000] == 0x56;
-	bank3 = fbuffer[0x300000] == 0x78;
-	pinfo->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
-	printk(KERN_INFO "platinumfb: Total VRAM = %dMB (%d%d%d%d)\n",
-	       (unsigned int) (pinfo->total_vram / 1024 / 1024),
-	       bank3, bank2, bank1, bank0);
-
-	/*
-	 * Try to determine whether we have an old or a new DACula.
-	 */
-	out_8(&pinfo->cmap_regs->addr, 0x40);
-	pinfo->dactype = in_8(&pinfo->cmap_regs->d2);
-	switch (pinfo->dactype) {
-	case 0x3c:
-		pinfo->clktype = 1;
-		printk(KERN_INFO "platinumfb: DACula type 0x3c\n");
-		break;
-	case 0x84:
-		pinfo->clktype = 0;
-		printk(KERN_INFO "platinumfb: DACula type 0x84\n");
-		break;
-	default:
-		pinfo->clktype = 0;
-		printk(KERN_INFO "platinumfb: Unknown DACula type: %x\n", pinfo->dactype);
-		break;
-	}
-	dev_set_drvdata(&odev->dev, info);
-	
-	rc = platinum_init_fb(info);
-	if (rc != 0) {
-		iounmap(pinfo->frame_buffer);
-		iounmap(pinfo->platinum_regs);
-		iounmap(pinfo->cmap_regs);
-		framebuffer_release(info);
-	}
-
-	return rc;
-}
-
-static int platinumfb_remove(struct platform_device* odev)
-{
-	struct fb_info		*info = dev_get_drvdata(&odev->dev);
-	struct fb_info_platinum	*pinfo = info->par;
-	
-        unregister_framebuffer (info);
-	
-	/* Unmap frame buffer and registers */
-	iounmap(pinfo->frame_buffer);
-	iounmap(pinfo->platinum_regs);
-	iounmap(pinfo->cmap_regs);
-
-	release_mem_region(pinfo->rsrc_fb.start,
-			   resource_size(&pinfo->rsrc_fb));
-
-	release_mem_region(pinfo->cmap_regs_phys, 0x1000);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static struct of_device_id platinumfb_match[] = 
-{
-	{
-	.name 		= "platinum",
-	},
-	{},
-};
-
-static struct platform_driver platinum_driver = 
-{
-	.driver = {
-		.name = "platinumfb",
-		.owner = THIS_MODULE,
-		.of_match_table = platinumfb_match,
-	},
-	.probe		= platinumfb_probe,
-	.remove		= platinumfb_remove,
-};
-
-static int __init platinumfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("platinumfb", &option))
-		return -ENODEV;
-	platinumfb_setup(option);
-#endif
-	platform_driver_register(&platinum_driver);
-
-	return 0;
-}
-
-static void __exit platinumfb_exit(void)
-{
-	platform_driver_unregister(&platinum_driver);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("framebuffer driver for Apple Platinum video");
-module_init(platinumfb_init);
-
-#ifdef MODULE
-module_exit(platinumfb_exit);
-#endif
diff --git a/drivers/video/platinumfb.h b/drivers/video/platinumfb.h
deleted file mode 100644
index f6bd77cafd17..000000000000
--- a/drivers/video/platinumfb.h
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * linux/drivers/video/platinumfb-hw.c -- Frame buffer device for the
- * Platinum on-board video in PowerMac 7200s (and some clones based
- * on the same motherboard.)
- *
- *  Created 09 Feb 1998 by Jon Howell <jonh@cs.dartmouth.edu>
- *
- * Copyright (C) 1998 Jon Howell
- *
- *  based on drivers/macintosh/platinum.c: Console support
- * 	for PowerMac "platinum" display adaptor.
- *  Copyright (C) 1996 Paul Mackerras and Mark Abene.
- *
- *  based on skeletonfb.c:
- *  Created 28 Dec 1997 by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/*
- * Structure of the registers for the DACula colormap device.
- */
-struct cmap_regs {
-	unsigned char addr;
-	char pad1[15];
-	unsigned char d1;
-	char pad2[15];
-	unsigned char d2;
-	char pad3[15];
-	unsigned char lut;
-	char pad4[15];
-};
-
-/*
- * Structure of the registers for the "platinum" display adaptor".
- */
-struct preg {			/* padded register */
-	unsigned r;			/* notice this is 32 bits. */
-	char pad[12];
-};
-
-struct platinum_regs {
-	struct preg reg[128];
-};
-
-/*
- * Register initialization tables for the platinum display.
- *
- * It seems that there are two different types of platinum display
- * out there.  Older ones use the values in clocksel[1], for which
- * the formula for the clock frequency seems to be
- *	F = 14.3MHz * c0 / (c1 & 0x1f) / (1 << (c1 >> 5))
- * Newer ones use the values in clocksel[0], for which the formula
- * seems to be
- *	F = 15MHz * c0 / ((c1 & 0x1f) + 2) / (1 << (c1 >> 5))
- */
-struct platinum_regvals {
-	int	fb_offset;
-	int	pitch[3];
-	unsigned regs[26];
-	unsigned char offset[3];
-	unsigned char mode[3];
-	unsigned char dacula_ctrl[3];
-	unsigned char clock_params[2][2];
-};
-
-#define DIV2	0x20
-#define DIV4	0x40
-#define DIV8	0x60
-#define DIV16	0x80
-
-/* 1280x1024, 75Hz (20) */
-static struct platinum_regvals platinum_reg_init_20 = {
-	0x5c00,
-	{ 1312, 2592, 2592 },
-	{ 0xffc, 4, 0, 0, 0, 0, 0x428, 0,
-	  0, 0xb3, 0xd3, 0x12, 0x1a5, 0x23, 0x28, 0x2d,
-	  0x5e, 0x19e, 0x1a4, 0x854, 0x852, 4, 9, 0x50,
-	  0x850, 0x851 }, { 0x58, 0x5d, 0x5d },
-	{ 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 },
-	{{ 45, 3 }, { 66, 7 }}
-};
-
-/* 1280x960, 75Hz (19) */
-static struct platinum_regvals platinum_reg_init_19 = {
-	0x5c00,
-	{ 1312, 2592, 2592 },
-	{ 0xffc, 4, 0, 0, 0, 0, 0x428, 0,
-	  0, 0xb2, 0xd2, 0x12, 0x1a3, 0x23, 0x28, 0x2d,
-	  0x5c, 0x19c, 0x1a2, 0x7d0, 0x7ce, 4, 9, 0x4c,
-	  0x7cc, 0x7cd }, { 0x56, 0x5b, 0x5b },
-	{ 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 },
-	{{ 42, 3 }, { 44, 5 }}
-};
-
-/* 1152x870, 75Hz (18) */
-static struct platinum_regvals platinum_reg_init_18 = {
-	0x11b0,
-	{ 1184, 2336, 4640 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x38f, 0,
-	  0, 0x294, 0x16c, 0x20, 0x2d7, 0x3f, 0x49, 0x53,
-	  0x82, 0x2c2, 0x2d6, 0x726, 0x724, 4, 9, 0x52,
-	  0x71e, 0x722 }, { 0x74, 0x7c, 0x81 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 26, 0 + DIV2 }, { 42, 6 }}
-};
-
-/* 1024x768, 75Hz (17) */
-static struct platinum_regvals platinum_reg_init_17 = {
-	0x10b0,
-	{ 1056, 2080, 4128 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x254, 0x14b, 0x18, 0x295, 0x2f, 0x32, 0x3b,
-	  0x80, 0x280, 0x296, 0x648, 0x646, 4, 9, 0x40,
-	  0x640, 0x644 }, { 0x72, 0x7a, 0x7f },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 54, 3 + DIV2 }, { 67, 12 }}
-};
-
-/* 1024x768, 75Hz (16) */
-static struct platinum_regvals platinum_reg_init_16 = {
-	0x10b0,
-	{ 1056, 2080, 4128 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x250, 0x147, 0x17, 0x28f, 0x2f, 0x35, 0x47,
-	  0x82, 0x282, 0x28e, 0x640, 0x63e, 4, 9, 0x3c,
-	  0x63c, 0x63d }, { 0x74, 0x7c, 0x81 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 20, 0 + DIV2 }, { 11, 2 }}
-};
-
-/* 1024x768, 70Hz (15) */
-static struct platinum_regvals platinum_reg_init_15 = {
-	0x10b0,
-	{ 1056, 2080, 4128 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x254, 0x14b, 0x22, 0x297, 0x43, 0x49, 0x5b,
-	  0x86, 0x286, 0x296, 0x64c, 0x64a, 0xa, 0xf, 0x44,
-	  0x644, 0x646 }, { 0x78, 0x80, 0x85 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 19, 0 + DIV2 }, { 110, 21 }}
-};
-
-/* 1024x768, 60Hz (14) */
-static struct platinum_regvals platinum_reg_init_14 = {
-	0x10b0,
-	{ 1056, 2080, 4128 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x25a, 0x14f, 0x22, 0x29f, 0x43, 0x49, 0x5b,
-	  0x8e, 0x28e, 0x29e, 0x64c, 0x64a, 0xa, 0xf, 0x44,
-	  0x644, 0x646 }, { 0x80, 0x88, 0x8d },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 71, 6 + DIV2 }, { 118, 13 + DIV2 }}
-};
-
-/* 832x624, 75Hz (13) */
-static struct platinum_regvals platinum_reg_init_13 = {
-	0x70,
-	{ 864, 1680, 3344 },	/* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB,
-				 * and we use 3344 instead of 3360 to fit in 2Mb
-				 */
-	{ 0xff0, 4, 0, 0, 0, 0, 0x299, 0,
-	  0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37,
-	  0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52,
-	  0x532, 0x533 }, { 0x7c, 0x84, 0x89 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }}
-};
-
-/* 800x600, 75Hz (12) */
-static struct platinum_regvals platinum_reg_init_12 = {
-	0x1010,
-	{ 832, 1632, 3232 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x1ce, 0x108, 0x14, 0x20f, 0x27, 0x30, 0x39,
-	  0x72, 0x202, 0x20e, 0x4e2, 0x4e0, 4, 9, 0x2e,
-	  0x4de, 0x4df }, { 0x64, 0x6c, 0x71 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 122, 7 + DIV4 }, { 62, 9 + DIV2 }}
-};
-
-/* 800x600, 72Hz (11) */
-static struct platinum_regvals platinum_reg_init_11 = {
-	0x1010,
-	{ 832, 1632, 3232 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x1ca, 0x104, 0x1e, 0x207, 0x3b, 0x44, 0x4d,
-	  0x56, 0x1e6, 0x206, 0x534, 0x532, 0xa, 0xe, 0x38,
-	  0x4e8, 0x4ec }, { 0x48, 0x50, 0x55 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 26, 0 + DIV4 }, { 42, 6 + DIV2 }}
-};
-
-/* 800x600, 60Hz (10) */
-static struct platinum_regvals platinum_reg_init_10 = {
-	0x1010,
-	{ 832, 1632, 3232 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d,
-	  0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34,
-	  0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 54, 3 + DIV4 }, { 95, 1 + DIV8 }}
-};
-
-/* 800x600, 56Hz (9) --unsupported? copy of mode 10 for now... */
-static struct platinum_regvals platinum_reg_init_9 = {
-	0x1010,
-	{ 832, 1632, 3232 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d,
-	  0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34,
-	  0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 54, 3 + DIV4 }, { 88, 1 + DIV8 }}
-};
-
-/* 768x576, 50Hz Interlaced-PAL (8) */
-static struct platinum_regvals platinum_reg_init_8 = {
-	0x1010,
-	{ 800, 1568, 3104 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36,
-	  0x47, 0x1c7, 0x1d6, 0x271, 0x270, 4, 9, 0x27,
-	  0x267, 0x26b }, { 0x39, 0x41, 0x46 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }}
-};
-
-/* 640x870, 75Hz Portrait (7) */
-static struct platinum_regvals platinum_reg_init_7 = {
-	0xb10,
-	{ 672, 1312, 2592 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x176, 0xd0, 0x14, 0x19f, 0x27, 0x2d, 0x3f,
-	  0x4a, 0x18a, 0x19e, 0x72c, 0x72a, 4, 9, 0x58,
-	  0x724, 0x72a }, { 0x3c, 0x44, 0x49 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }}
-};
-
-/* 640x480, 67Hz (6) */
-static struct platinum_regvals platinum_reg_init_6 = {
-	0x1010,
-	{ 672, 1312, 2592 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x209, 0,
-	  0, 0x18e, 0xd8, 0x10, 0x1af, 0x1f, 0x25, 0x37,
-	  0x4a, 0x18a, 0x1ae, 0x41a, 0x418, 4, 9, 0x52,
-	  0x412, 0x416 }, { 0x3c, 0x44, 0x49 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 99, 4 + DIV8 }, { 42, 5 + DIV4 }}
-};
-
-/* 640x480, 60Hz (5) */
-static struct platinum_regvals platinum_reg_init_5 = {
-	0x1010,
-	{ 672, 1312, 2592 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x15e, 0xc8, 0x18, 0x18f, 0x2f, 0x35, 0x3e,
-	  0x42, 0x182, 0x18e, 0x41a, 0x418, 2, 7, 0x44,
-	  0x404, 0x408 }, { 0x34, 0x3c, 0x41 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 26, 0 + DIV8 }, { 14, 2 + DIV4 }}
-};
-
-/* 640x480, 60Hz Interlaced-NTSC (4) */
-static struct platinum_regvals platinum_reg_init_4 = {
-	0x1010,
-	{ 672, 1312, 2592 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30,
-	  0x37, 0x177, 0x184, 0x20d, 0x20c, 5, 0xb, 0x23,
-	  0x203, 0x206 }, { 0x29, 0x31, 0x36 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }}
-};
-
-/* 640x480, 50Hz Interlaced-PAL (3) */
-static struct platinum_regvals platinum_reg_init_3 = {
-	0x1010,
-	{ 672, 1312, 2592 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36,
-	  0x67, 0x1a7, 0x1d6, 0x271, 0x270, 4, 9, 0x57,
-	  0x237, 0x26b }, { 0x59, 0x61, 0x66 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }}
-};
-
-/* 512x384, 60Hz (2) */
-static struct platinum_regvals platinum_reg_init_2 = {
-	0x1010,
-	{ 544, 1056, 2080 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0x25c, 0x140, 0x10, 0x27f, 0x1f, 0x2b, 0x4f,
-	  0x68, 0x268, 0x27e, 0x32e, 0x32c, 4, 9, 0x2a,
-	  0x32a, 0x32b }, { 0x5a, 0x62, 0x67 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 33, 2 + DIV8 }, { 79, 9 + DIV8 }}
-};
-
-/* 512x384, 60Hz Interlaced-NTSC (1) */
-static struct platinum_regvals platinum_reg_init_1 = {
-	0x1010,
-	{ 544, 1056, 2080 },
-	{ 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
-	  0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30,
-	  0x57, 0x157, 0x184, 0x20d, 0x20c, 5, 0xb, 0x53,
-	  0x1d3, 0x206 }, { 0x49, 0x51, 0x56 },
-	{ 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
-	{{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }}
-};
-
-static struct platinum_regvals *platinum_reg_init[VMODE_MAX] = {
-	&platinum_reg_init_1,
-	&platinum_reg_init_2,
-	&platinum_reg_init_3,
-	&platinum_reg_init_4,
-	&platinum_reg_init_5,
-	&platinum_reg_init_6,
-	&platinum_reg_init_7,
-	&platinum_reg_init_8,
-	&platinum_reg_init_9,
-	&platinum_reg_init_10,
-	&platinum_reg_init_11,
-	&platinum_reg_init_12,
-	&platinum_reg_init_13,
-	&platinum_reg_init_14,
-	&platinum_reg_init_15,
-	&platinum_reg_init_16,
-	&platinum_reg_init_17,
-	&platinum_reg_init_18,
-	&platinum_reg_init_19,
-	&platinum_reg_init_20
-};
-
-struct vmode_attr {
-	int hres;
-	int vres;
-	int vfreq;
-	int interlaced;
-};
-
-struct vmode_attr vmode_attrs[VMODE_MAX] = {
-	{512, 384, 60, 1},
-	{512, 384, 60},
-	{640, 480, 50, 1},
-	{640, 480, 60, 1},
-	{640, 480, 60},
-	{640, 480, 67},
-	{640, 870, 75},
-	{768, 576, 50, 1},
-	{800, 600, 56},
-	{800, 600, 60},
-	{800, 600, 72},
-	{800, 600, 75},
-	{832, 624, 75},
-	{1024, 768, 60},
-	{1024, 768, 72},
-	{1024, 768, 75},
-	{1024, 768, 75},
-	{1152, 870, 75},
-	{1280, 960, 75},
-	{1280, 1024, 75}
-};
-
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
deleted file mode 100644
index 3b85b647bc10..000000000000
--- a/drivers/video/pm2fb.c
+++ /dev/null
@@ -1,1858 +0,0 @@
-/*
- * Permedia2 framebuffer driver.
- *
- * 2.5/2.6 driver:
- * Copyright (c) 2003 Jim Hague (jim.hague@acm.org)
- *
- * based on 2.4 driver:
- * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com)
- *
- * and additional input from James Simmon's port of Hannu Mallat's tdfx
- * driver.
- *
- * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. I
- * have no access to other pm2fb implementations. Sparc (and thus
- * hopefully other big-endian) devices now work, thanks to a lot of
- * testing work by Ron Murray. I have no access to CVision hardware,
- * and therefore for now I am omitting the CVision code.
- *
- * Multiple boards support has been on the TODO list for ages.
- * Don't expect this to change.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/permedia2.h>
-#include <video/cvisionppc.h>
-
-#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
-#error	"The endianness of the target host has not been defined."
-#endif
-
-#if !defined(CONFIG_PCI)
-#error "Only generic PCI cards supported."
-#endif
-
-#undef PM2FB_MASTER_DEBUG
-#ifdef PM2FB_MASTER_DEBUG
-#define DPRINTK(a, b...)	\
-	printk(KERN_DEBUG "pm2fb: %s: " a, __func__ , ## b)
-#else
-#define DPRINTK(a, b...)
-#endif
-
-#define PM2_PIXMAP_SIZE	(1600 * 4)
-
-/*
- * Driver data
- */
-static int hwcursor = 1;
-static char *mode_option;
-
-/*
- * The XFree GLINT driver will (I think to implement hardware cursor
- * support on TVP4010 and similar where there is no RAMDAC - see
- * comment in set_video) always request +ve sync regardless of what
- * the mode requires. This screws me because I have a Sun
- * fixed-frequency monitor which absolutely has to have -ve sync. So
- * these flags allow the user to specify that requests for +ve sync
- * should be silently turned in -ve sync.
- */
-static bool lowhsync;
-static bool lowvsync;
-static bool noaccel;
-/* mtrr option */
-#ifdef CONFIG_MTRR
-static bool nomtrr;
-#endif
-
-/*
- * The hardware state of the graphics card that isn't part of the
- * screeninfo.
- */
-struct pm2fb_par
-{
-	pm2type_t	type;		/* Board type */
-	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
-	u32		memclock;	/* memclock */
-	u32		video;		/* video flags before blanking */
-	u32		mem_config;	/* MemConfig reg at probe */
-	u32		mem_control;	/* MemControl reg at probe */
-	u32		boot_address;	/* BootAddress reg at probe */
-	u32		palette[16];
-	int		mtrr_handle;
-};
-
-/*
- * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
- * if we don't use modedb.
- */
-static struct fb_fix_screeninfo pm2fb_fix = {
-	.id =		"",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	0,
-	.accel =	FB_ACCEL_3DLABS_PERMEDIA2,
-};
-
-/*
- * Default video mode. In case the modedb doesn't work.
- */
-static struct fb_var_screeninfo pm2fb_var = {
-	/* "640x480, 8 bpp @ 60 Hz */
-	.xres =			640,
-	.yres =			480,
-	.xres_virtual =		640,
-	.yres_virtual =		480,
-	.bits_per_pixel =	8,
-	.red =			{0, 8, 0},
-	.blue =			{0, 8, 0},
-	.green =		{0, 8, 0},
-	.activate =		FB_ACTIVATE_NOW,
-	.height =		-1,
-	.width =		-1,
-	.accel_flags =		0,
-	.pixclock =		39721,
-	.left_margin =		40,
-	.right_margin =		24,
-	.upper_margin =		32,
-	.lower_margin =		11,
-	.hsync_len =		96,
-	.vsync_len =		2,
-	.vmode =		FB_VMODE_NONINTERLACED
-};
-
-/*
- * Utility functions
- */
-
-static inline u32 pm2_RD(struct pm2fb_par *p, s32 off)
-{
-	return fb_readl(p->v_regs + off);
-}
-
-static inline void pm2_WR(struct pm2fb_par *p, s32 off, u32 v)
-{
-	fb_writel(v, p->v_regs + off);
-}
-
-static inline u32 pm2_RDAC_RD(struct pm2fb_par *p, s32 idx)
-{
-	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
-	mb();
-	return pm2_RD(p, PM2R_RD_INDEXED_DATA);
-}
-
-static inline u32 pm2v_RDAC_RD(struct pm2fb_par *p, s32 idx)
-{
-	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
-	mb();
-	return pm2_RD(p,  PM2VR_RD_INDEXED_DATA);
-}
-
-static inline void pm2_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
-{
-	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
-	wmb();
-	pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
-	wmb();
-}
-
-static inline void pm2v_RDAC_WR(struct pm2fb_par *p, s32 idx, u32 v)
-{
-	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
-	wmb();
-	pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
-	wmb();
-}
-
-#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
-#define WAIT_FIFO(p, a)
-#else
-static inline void WAIT_FIFO(struct pm2fb_par *p, u32 a)
-{
-	while (pm2_RD(p, PM2R_IN_FIFO_SPACE) < a)
-		cpu_relax();
-}
-#endif
-
-/*
- * partial products for the supported horizontal resolutions.
- */
-#define PACKPP(p0, p1, p2)	(((p2) << 6) | ((p1) << 3) | (p0))
-static const struct {
-	u16 width;
-	u16 pp;
-} pp_table[] = {
-	{ 32,	PACKPP(1, 0, 0) }, { 64,	PACKPP(1, 1, 0) },
-	{ 96,	PACKPP(1, 1, 1) }, { 128,	PACKPP(2, 1, 1) },
-	{ 160,	PACKPP(2, 2, 1) }, { 192,	PACKPP(2, 2, 2) },
-	{ 224,	PACKPP(3, 2, 1) }, { 256,	PACKPP(3, 2, 2) },
-	{ 288,	PACKPP(3, 3, 1) }, { 320,	PACKPP(3, 3, 2) },
-	{ 384,	PACKPP(3, 3, 3) }, { 416,	PACKPP(4, 3, 1) },
-	{ 448,	PACKPP(4, 3, 2) }, { 512,	PACKPP(4, 3, 3) },
-	{ 544,	PACKPP(4, 4, 1) }, { 576,	PACKPP(4, 4, 2) },
-	{ 640,	PACKPP(4, 4, 3) }, { 768,	PACKPP(4, 4, 4) },
-	{ 800,	PACKPP(5, 4, 1) }, { 832,	PACKPP(5, 4, 2) },
-	{ 896,	PACKPP(5, 4, 3) }, { 1024,	PACKPP(5, 4, 4) },
-	{ 1056,	PACKPP(5, 5, 1) }, { 1088,	PACKPP(5, 5, 2) },
-	{ 1152,	PACKPP(5, 5, 3) }, { 1280,	PACKPP(5, 5, 4) },
-	{ 1536,	PACKPP(5, 5, 5) }, { 1568,	PACKPP(6, 5, 1) },
-	{ 1600,	PACKPP(6, 5, 2) }, { 1664,	PACKPP(6, 5, 3) },
-	{ 1792,	PACKPP(6, 5, 4) }, { 2048,	PACKPP(6, 5, 5) },
-	{ 0,	0 } };
-
-static u32 partprod(u32 xres)
-{
-	int i;
-
-	for (i = 0; pp_table[i].width && pp_table[i].width != xres; i++)
-		;
-	if (pp_table[i].width == 0)
-		DPRINTK("invalid width %u\n", xres);
-	return pp_table[i].pp;
-}
-
-static u32 to3264(u32 timing, int bpp, int is64)
-{
-	switch (bpp) {
-	case 24:
-		timing *= 3;
-	case 8:
-		timing >>= 1;
-	case 16:
-		timing >>= 1;
-	case 32:
-		break;
-	}
-	if (is64)
-		timing >>= 1;
-	return timing;
-}
-
-static void pm2_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
-		    unsigned char *pp)
-{
-	unsigned char m;
-	unsigned char n;
-	unsigned char p;
-	u32 f;
-	s32 curr;
-	s32 delta = 100000;
-
-	*mm = *nn = *pp = 0;
-	for (n = 2; n < 15; n++) {
-		for (m = 2; m; m++) {
-			f = PM2_REFERENCE_CLOCK * m / n;
-			if (f >= 150000 && f <= 300000) {
-				for (p = 0; p < 5; p++, f >>= 1) {
-					curr = (clk > f) ? clk - f : f - clk;
-					if (curr < delta) {
-						delta = curr;
-						*mm = m;
-						*nn = n;
-						*pp = p;
-					}
-				}
-			}
-		}
-	}
-}
-
-static void pm2v_mnp(u32 clk, unsigned char *mm, unsigned char *nn,
-		     unsigned char *pp)
-{
-	unsigned char m;
-	unsigned char n;
-	unsigned char p;
-	u32 f;
-	s32 delta = 1000;
-
-	*mm = *nn = *pp = 0;
-	for (m = 1; m < 128; m++) {
-		for (n = 2 * m + 1; n; n++) {
-			for (p = 0; p < 2; p++) {
-				f = (PM2_REFERENCE_CLOCK >> (p + 1)) * n / m;
-				if (clk > f - delta && clk < f + delta) {
-					delta = (clk > f) ? clk - f : f - clk;
-					*mm = m;
-					*nn = n;
-					*pp = p;
-				}
-			}
-		}
-	}
-}
-
-static void clear_palette(struct pm2fb_par *p)
-{
-	int i = 256;
-
-	WAIT_FIFO(p, 1);
-	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
-	wmb();
-	while (i--) {
-		WAIT_FIFO(p, 3);
-		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
-		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
-		pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
-	}
-}
-
-static void reset_card(struct pm2fb_par *p)
-{
-	if (p->type == PM2_TYPE_PERMEDIA2V)
-		pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
-	pm2_WR(p, PM2R_RESET_STATUS, 0);
-	mb();
-	while (pm2_RD(p, PM2R_RESET_STATUS) & PM2F_BEING_RESET)
-		cpu_relax();
-	mb();
-#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
-	DPRINTK("FIFO disconnect enabled\n");
-	pm2_WR(p, PM2R_FIFO_DISCON, 1);
-	mb();
-#endif
-
-	/* Restore stashed memory config information from probe */
-	WAIT_FIFO(p, 3);
-	pm2_WR(p, PM2R_MEM_CONTROL, p->mem_control);
-	pm2_WR(p, PM2R_BOOT_ADDRESS, p->boot_address);
-	wmb();
-	pm2_WR(p, PM2R_MEM_CONFIG, p->mem_config);
-}
-
-static void reset_config(struct pm2fb_par *p)
-{
-	WAIT_FIFO(p, 53);
-	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG) &
-			~(PM2F_VGA_ENABLE | PM2F_VGA_FIXED));
-	pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
-	pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
-	pm2_WR(p, PM2R_FIFO_CONTROL, 0);
-	pm2_WR(p, PM2R_APERTURE_ONE, 0);
-	pm2_WR(p, PM2R_APERTURE_TWO, 0);
-	pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
-	pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
-	pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
-	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
-	pm2_WR(p, PM2R_LB_READ_MODE, 0);
-	pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
-	pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
-	pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
-	pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
-	pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
-	pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
-	pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L));
-	pm2_WR(p, PM2R_FB_READ_PIXEL, 0);
-	pm2_WR(p, PM2R_DITHER_MODE, 0);
-	pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0);
-	pm2_WR(p, PM2R_DEPTH_MODE, 0);
-	pm2_WR(p, PM2R_STENCIL_MODE, 0);
-	pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0);
-	pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0);
-	pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0);
-	pm2_WR(p, PM2R_YUV_MODE, 0);
-	pm2_WR(p, PM2R_COLOR_DDA_MODE, 0);
-	pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0);
-	pm2_WR(p, PM2R_FOG_MODE, 0);
-	pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0);
-	pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
-	pm2_WR(p, PM2R_STATISTICS_MODE, 0);
-	pm2_WR(p, PM2R_SCISSOR_MODE, 0);
-	pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
-	pm2_WR(p, PM2R_RD_PIXEL_MASK, 0xff);
-	switch (p->type) {
-	case PM2_TYPE_PERMEDIA2:
-		pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
-		pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
-		pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
-		pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
-		pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
-		pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
-		pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
-		pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
-		break;
-	case PM2_TYPE_PERMEDIA2V:
-		pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */
-		break;
-	}
-}
-
-static void set_aperture(struct pm2fb_par *p, u32 depth)
-{
-	/*
-	 * The hardware is little-endian. When used in big-endian
-	 * hosts, the on-chip aperture settings are used where
-	 * possible to translate from host to card byte order.
-	 */
-	WAIT_FIFO(p, 2);
-#ifdef __LITTLE_ENDIAN
-	pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
-#else
-	switch (depth) {
-	case 24:	/* RGB->BGR */
-		/*
-		 * We can't use the aperture to translate host to
-		 * card byte order here, so we switch to BGR mode
-		 * in pm2fb_set_par().
-		 */
-	case 8:		/* B->B */
-		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_STANDARD);
-		break;
-	case 16:	/* HL->LH */
-		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_HALFWORDSWAP);
-		break;
-	case 32:	/* RGBA->ABGR */
-		pm2_WR(p, PM2R_APERTURE_ONE, PM2F_APERTURE_BYTESWAP);
-		break;
-	}
-#endif
-
-	/* We don't use aperture two, so this may be superflous */
-	pm2_WR(p, PM2R_APERTURE_TWO, PM2F_APERTURE_STANDARD);
-}
-
-static void set_color(struct pm2fb_par *p, unsigned char regno,
-		      unsigned char r, unsigned char g, unsigned char b)
-{
-	WAIT_FIFO(p, 4);
-	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
-	wmb();
-	pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
-	wmb();
-	pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
-	wmb();
-	pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
-}
-
-static void set_memclock(struct pm2fb_par *par, u32 clk)
-{
-	int i;
-	unsigned char m, n, p;
-
-	switch (par->type) {
-	case PM2_TYPE_PERMEDIA2V:
-		pm2v_mnp(clk/2, &m, &n, &p);
-		WAIT_FIFO(par, 12);
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
-		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
-		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
-		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n);
-		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
-		pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
-		rmb();
-		for (i = 256; i; i--)
-			if (pm2v_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2)
-				break;
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
-		break;
-	case PM2_TYPE_PERMEDIA2:
-		pm2_mnp(clk, &m, &n, &p);
-		WAIT_FIFO(par, 10);
-		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
-		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
-		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
-		pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
-		pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
-		rmb();
-		for (i = 256; i; i--)
-			if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
-				break;
-		break;
-	}
-}
-
-static void set_pixclock(struct pm2fb_par *par, u32 clk)
-{
-	int i;
-	unsigned char m, n, p;
-
-	switch (par->type) {
-	case PM2_TYPE_PERMEDIA2:
-		pm2_mnp(clk, &m, &n, &p);
-		WAIT_FIFO(par, 10);
-		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
-		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
-		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
-		pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
-		pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
-		rmb();
-		for (i = 256; i; i--)
-			if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED)
-				break;
-		break;
-	case PM2_TYPE_PERMEDIA2V:
-		pm2v_mnp(clk/2, &m, &n, &p);
-		WAIT_FIFO(par, 8);
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8);
-		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_PRESCALE, m);
-		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_FEEDBACK, n);
-		pm2v_RDAC_WR(par, PM2VI_RD_CLK0_POSTSCALE, p);
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
-		break;
-	}
-}
-
-static void set_video(struct pm2fb_par *p, u32 video)
-{
-	u32 tmp;
-	u32 vsync = video;
-
-	DPRINTK("video = 0x%x\n", video);
-
-	/*
-	 * The hardware cursor needs +vsync to recognise vert retrace.
-	 * We may not be using the hardware cursor, but the X Glint
-	 * driver may well. So always set +hsync/+vsync and then set
-	 * the RAMDAC to invert the sync if necessary.
-	 */
-	vsync &= ~(PM2F_HSYNC_MASK | PM2F_VSYNC_MASK);
-	vsync |= PM2F_HSYNC_ACT_HIGH | PM2F_VSYNC_ACT_HIGH;
-
-	WAIT_FIFO(p, 3);
-	pm2_WR(p, PM2R_VIDEO_CONTROL, vsync);
-
-	switch (p->type) {
-	case PM2_TYPE_PERMEDIA2:
-		tmp = PM2F_RD_PALETTE_WIDTH_8;
-		if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
-			tmp |= 4; /* invert hsync */
-		if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
-			tmp |= 8; /* invert vsync */
-		pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, tmp);
-		break;
-	case PM2_TYPE_PERMEDIA2V:
-		tmp = 0;
-		if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
-			tmp |= 1; /* invert hsync */
-		if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
-			tmp |= 4; /* invert vsync */
-		pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp);
-		break;
-	}
-}
-
-/*
- *	pm2fb_check_var - Optional function. Validates a var passed in.
- *	@var: frame buffer variable screen structure
- *	@info: frame buffer structure that represents a single frame buffer
- *
- *	Checks to see if the hardware supports the state requested by
- *	var passed in.
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	u32 lpitch;
-
-	if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
-	    var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
-		DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (var->xres != var->xres_virtual) {
-		DPRINTK("virtual x resolution != "
-			"physical x resolution not supported\n");
-		return -EINVAL;
-	}
-
-	if (var->yres > var->yres_virtual) {
-		DPRINTK("virtual y resolution < "
-			"physical y resolution not possible\n");
-		return -EINVAL;
-	}
-
-	/* permedia cannot blit over 2048 */
-	if (var->yres_virtual > 2047) {
-		var->yres_virtual = 2047;
-	}
-
-	if (var->xoffset) {
-		DPRINTK("xoffset not supported\n");
-		return -EINVAL;
-	}
-
-	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-		DPRINTK("interlace not supported\n");
-		return -EINVAL;
-	}
-
-	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
-	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
-
-	if (var->xres < 320 || var->xres > 1600) {
-		DPRINTK("width not supported: %u\n", var->xres);
-		return -EINVAL;
-	}
-
-	if (var->yres < 200 || var->yres > 1200) {
-		DPRINTK("height not supported: %u\n", var->yres);
-		return -EINVAL;
-	}
-
-	if (lpitch * var->yres_virtual > info->fix.smem_len) {
-		DPRINTK("no memory for screen (%ux%ux%u)\n",
-			var->xres, var->yres_virtual, var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
-		DPRINTK("pixclock too high (%ldKHz)\n",
-			PICOS2KHZ(var->pixclock));
-		return -EINVAL;
-	}
-
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	case 16:
-		var->red.offset   = 11;
-		var->red.length   = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset  = 0;
-		var->blue.length  = 5;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset	  = 16;
-		var->green.offset = 8;
-		var->blue.offset  = 0;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	case 24:
-#ifdef __BIG_ENDIAN
-		var->red.offset   = 0;
-		var->blue.offset  = 16;
-#else
-		var->red.offset   = 16;
-		var->blue.offset  = 0;
-#endif
-		var->green.offset = 8;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	}
-	var->height = -1;
-	var->width = -1;
-
-	var->accel_flags = 0;	/* Can't mmap if this is on */
-
-	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	return 0;
-}
-
-/**
- *	pm2fb_set_par - Alters the hardware state.
- *	@info: frame buffer structure that represents a single frame buffer
- *
- *	Using the fb_var_screeninfo in fb_info we set the resolution of the
- *	this particular framebuffer.
- */
-static int pm2fb_set_par(struct fb_info *info)
-{
-	struct pm2fb_par *par = info->par;
-	u32 pixclock;
-	u32 width = (info->var.xres_virtual + 7) & ~7;
-	u32 height = info->var.yres_virtual;
-	u32 depth = (info->var.bits_per_pixel + 7) & ~7;
-	u32 hsstart, hsend, hbend, htotal;
-	u32 vsstart, vsend, vbend, vtotal;
-	u32 stride;
-	u32 base;
-	u32 video = 0;
-	u32 clrmode = PM2F_RD_COLOR_MODE_RGB | PM2F_RD_GUI_ACTIVE;
-	u32 txtmap = 0;
-	u32 pixsize = 0;
-	u32 clrformat = 0;
-	u32 misc = 1; /* 8-bit DAC */
-	u32 xres = (info->var.xres + 31) & ~31;
-	int data64;
-
-	reset_card(par);
-	reset_config(par);
-	clear_palette(par);
-	if (par->memclock)
-		set_memclock(par, par->memclock);
-
-	depth = (depth > 32) ? 32 : depth;
-	data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V;
-
-	pixclock = PICOS2KHZ(info->var.pixclock);
-	if (pixclock > PM2_MAX_PIXCLOCK) {
-		DPRINTK("pixclock too high (%uKHz)\n", pixclock);
-		return -EINVAL;
-	}
-
-	hsstart = to3264(info->var.right_margin, depth, data64);
-	hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
-	hbend = hsend + to3264(info->var.left_margin, depth, data64);
-	htotal = to3264(xres, depth, data64) + hbend - 1;
-	vsstart = (info->var.lower_margin)
-		? info->var.lower_margin - 1
-		: 0;	/* FIXME! */
-	vsend = info->var.lower_margin + info->var.vsync_len - 1;
-	vbend = info->var.lower_margin + info->var.vsync_len +
-		info->var.upper_margin;
-	vtotal = info->var.yres + vbend - 1;
-	stride = to3264(width, depth, 1);
-	base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
-	if (data64)
-		video |= PM2F_DATA_64_ENABLE;
-
-	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
-		if (lowhsync) {
-			DPRINTK("ignoring +hsync, using -hsync.\n");
-			video |= PM2F_HSYNC_ACT_LOW;
-		} else
-			video |= PM2F_HSYNC_ACT_HIGH;
-	} else
-		video |= PM2F_HSYNC_ACT_LOW;
-
-	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) {
-		if (lowvsync) {
-			DPRINTK("ignoring +vsync, using -vsync.\n");
-			video |= PM2F_VSYNC_ACT_LOW;
-		} else
-			video |= PM2F_VSYNC_ACT_HIGH;
-	} else
-		video |= PM2F_VSYNC_ACT_LOW;
-
-	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-		DPRINTK("interlaced not supported\n");
-		return -EINVAL;
-	}
-	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
-		video |= PM2F_LINE_DOUBLE;
-	if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
-		video |= PM2F_VIDEO_ENABLE;
-	par->video = video;
-
-	info->fix.visual =
-		(depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = info->var.xres * depth / 8;
-	info->cmap.len = 256;
-
-	/*
-	 * Settings calculated. Now write them out.
-	 */
-	if (par->type == PM2_TYPE_PERMEDIA2V) {
-		WAIT_FIFO(par, 1);
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
-	}
-
-	set_aperture(par, depth);
-
-	mb();
-	WAIT_FIFO(par, 19);
-	switch (depth) {
-	case 8:
-		pm2_WR(par, PM2R_FB_READ_PIXEL, 0);
-		clrformat = 0x2e;
-		break;
-	case 16:
-		pm2_WR(par, PM2R_FB_READ_PIXEL, 1);
-		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB565;
-		txtmap = PM2F_TEXTEL_SIZE_16;
-		pixsize = 1;
-		clrformat = 0x70;
-		misc |= 8;
-		break;
-	case 32:
-		pm2_WR(par, PM2R_FB_READ_PIXEL, 2);
-		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGBA8888;
-		txtmap = PM2F_TEXTEL_SIZE_32;
-		pixsize = 2;
-		clrformat = 0x20;
-		misc |= 8;
-		break;
-	case 24:
-		pm2_WR(par, PM2R_FB_READ_PIXEL, 4);
-		clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB888;
-		txtmap = PM2F_TEXTEL_SIZE_24;
-		pixsize = 4;
-		clrformat = 0x20;
-		misc |= 8;
-		break;
-	}
-	pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
-	pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
-	pm2_WR(par, PM2R_LB_READ_MODE, partprod(xres));
-	pm2_WR(par, PM2R_TEXTURE_MAP_FORMAT, txtmap | partprod(xres));
-	pm2_WR(par, PM2R_H_TOTAL, htotal);
-	pm2_WR(par, PM2R_HS_START, hsstart);
-	pm2_WR(par, PM2R_HS_END, hsend);
-	pm2_WR(par, PM2R_HG_END, hbend);
-	pm2_WR(par, PM2R_HB_END, hbend);
-	pm2_WR(par, PM2R_V_TOTAL, vtotal);
-	pm2_WR(par, PM2R_VS_START, vsstart);
-	pm2_WR(par, PM2R_VS_END, vsend);
-	pm2_WR(par, PM2R_VB_END, vbend);
-	pm2_WR(par, PM2R_SCREEN_STRIDE, stride);
-	wmb();
-	pm2_WR(par, PM2R_WINDOW_ORIGIN, 0);
-	pm2_WR(par, PM2R_SCREEN_SIZE, (height << 16) | width);
-	pm2_WR(par, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
-	wmb();
-	pm2_WR(par, PM2R_SCREEN_BASE, base);
-	wmb();
-	set_video(par, video);
-	WAIT_FIFO(par, 10);
-	switch (par->type) {
-	case PM2_TYPE_PERMEDIA2:
-		pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE, clrmode);
-		pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
-				(depth == 8) ? 0 : PM2F_COLOR_KEY_TEST_OFF);
-		break;
-	case PM2_TYPE_PERMEDIA2V:
-		pm2v_RDAC_WR(par, PM2VI_RD_DAC_CONTROL, 0);
-		pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize);
-		pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat);
-		pm2v_RDAC_WR(par, PM2VI_RD_MISC_CONTROL, misc);
-		pm2v_RDAC_WR(par, PM2VI_RD_OVERLAY_KEY, 0);
-		break;
-	}
-	set_pixclock(par, pixclock);
-	DPRINTK("Setting graphics mode at %dx%d depth %d\n",
-		info->var.xres, info->var.yres, info->var.bits_per_pixel);
-	return 0;
-}
-
-/**
- *	pm2fb_setcolreg - Sets a color register.
- *	@regno: boolean, 0 copy local, 1 get_user() function
- *	@red: frame buffer colormap structure
- *	@green: The green value which can be up to 16 bits wide
- *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.
- *	@info: frame buffer info structure
- *
- *	Set a single color register. The values supplied have a 16 bit
- *	magnitude which needs to be scaled in this function for the hardware.
- *	Pretty much a direct lift from tdfxfb.c.
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct pm2fb_par *par = info->par;
-
-	if (regno >= info->cmap.len)  /* no. of hw registers */
-		return -EINVAL;
-	/*
-	 * Program hardware... do anything you want with transp
-	 */
-
-	/* grayscale works only partially under directcolor */
-	/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-	if (info->var.grayscale)
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-
-	/* Directcolor:
-	 *   var->{color}.offset contains start of bitfield
-	 *   var->{color}.length contains length of bitfield
-	 *   {hardwarespecific} contains width of DAC
-	 *   cmap[X] is programmed to
-	 *   (X << red.offset) | (X << green.offset) | (X << blue.offset)
-	 *   RAMDAC[X] is programmed to (red, green, blue)
-	 *
-	 * Pseudocolor:
-	 *    uses offset = 0 && length = DAC register width.
-	 *    var->{color}.offset is 0
-	 *    var->{color}.length contains width of DAC
-	 *    cmap is not used
-	 *    DAC[X] is programmed to (red, green, blue)
-	 * Truecolor:
-	 *    does not use RAMDAC (usually has 3 of them).
-	 *    var->{color}.offset contains start of bitfield
-	 *    var->{color}.length contains length of bitfield
-	 *    cmap is programmed to
-	 *    (red << red.offset) | (green << green.offset) |
-	 *    (blue << blue.offset) | (transp << transp.offset)
-	 *    RAMDAC does not exist
-	 */
-#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF -(val)) >> 16)
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		red = CNVT_TOHW(red, info->var.red.length);
-		green = CNVT_TOHW(green, info->var.green.length);
-		blue = CNVT_TOHW(blue, info->var.blue.length);
-		transp = CNVT_TOHW(transp, info->var.transp.length);
-		break;
-	case FB_VISUAL_DIRECTCOLOR:
-		/* example here assumes 8 bit DAC. Might be different
-		 * for your hardware */
-		red = CNVT_TOHW(red, 8);
-		green = CNVT_TOHW(green, 8);
-		blue = CNVT_TOHW(blue, 8);
-		/* hey, there is bug in transp handling... */
-		transp = CNVT_TOHW(transp, 8);
-		break;
-	}
-#undef CNVT_TOHW
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 v;
-
-		if (regno >= 16)
-			return -EINVAL;
-
-		v = (red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset) |
-			(transp << info->var.transp.offset);
-
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			break;
-		case 16:
-		case 24:
-		case 32:
-			par->palette[regno] = v;
-			break;
-		}
-		return 0;
-	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
-		set_color(par, regno, red, green, blue);
-
-	return 0;
-}
-
-/**
- *	pm2fb_pan_display - Pans the display.
- *	@var: frame buffer variable screen structure
- *	@info: frame buffer structure that represents a single frame buffer
- *
- *	Pan (or wrap, depending on the `vmode' field) the display using the
- *	`xoffset' and `yoffset' fields of the `var' structure.
- *	If the values don't fit, return -EINVAL.
- *
- *	Returns negative errno on error, or zero on success.
- *
- */
-static int pm2fb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct pm2fb_par *p = info->par;
-	u32 base;
-	u32 depth = (info->var.bits_per_pixel + 7) & ~7;
-	u32 xres = (info->var.xres + 31) & ~31;
-
-	depth = (depth > 32) ? 32 : depth;
-	base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
-	WAIT_FIFO(p, 1);
-	pm2_WR(p, PM2R_SCREEN_BASE, base);
-	return 0;
-}
-
-/**
- *	pm2fb_blank - Blanks the display.
- *	@blank_mode: the blank mode we want.
- *	@info: frame buffer structure that represents a single frame buffer
- *
- *	Blank the screen if blank_mode != 0, else unblank. Return 0 if
- *	blanking succeeded, != 0 if un-/blanking failed due to e.g. a
- *	video mode which doesn't support it. Implements VESA suspend
- *	and powerdown modes on hardware that supports disabling hsync/vsync:
- *	blank_mode == 2: suspend vsync
- *	blank_mode == 3: suspend hsync
- *	blank_mode == 4: powerdown
- *
- *	Returns negative errno on error, or zero on success.
- *
- */
-static int pm2fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct pm2fb_par *par = info->par;
-	u32 video = par->video;
-
-	DPRINTK("blank_mode %d\n", blank_mode);
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		/* Screen: On */
-		video |= PM2F_VIDEO_ENABLE;
-		break;
-	case FB_BLANK_NORMAL:
-		/* Screen: Off */
-		video &= ~PM2F_VIDEO_ENABLE;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		/* VSync: Off */
-		video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW);
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		/* HSync: Off */
-		video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
-		break;
-	case FB_BLANK_POWERDOWN:
-		/* HSync: Off, VSync: Off */
-		video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK | PM2F_BLANK_LOW);
-		break;
-	}
-	set_video(par, video);
-	return 0;
-}
-
-static int pm2fb_sync(struct fb_info *info)
-{
-	struct pm2fb_par *par = info->par;
-
-	WAIT_FIFO(par, 1);
-	pm2_WR(par, PM2R_SYNC, 0);
-	mb();
-	do {
-		while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0)
-			cpu_relax();
-	} while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
-
-	return 0;
-}
-
-static void pm2fb_fillrect(struct fb_info *info,
-				const struct fb_fillrect *region)
-{
-	struct pm2fb_par *par = info->par;
-	struct fb_fillrect modded;
-	int vxres, vyres;
-	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
-		((u32 *)info->pseudo_palette)[region->color] : region->color;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
-		region->rop != ROP_COPY ) {
-		cfb_fillrect(info, region);
-		return;
-	}
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	memcpy(&modded, region, sizeof(struct fb_fillrect));
-
-	if (!modded.width || !modded.height ||
-	    modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.dx + modded.width  > vxres)
-		modded.width  = vxres - modded.dx;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	if (info->var.bits_per_pixel == 8)
-		color |= color << 8;
-	if (info->var.bits_per_pixel <= 16)
-		color |= color << 16;
-
-	WAIT_FIFO(par, 3);
-	pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE);
-	pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
-	pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
-	if (info->var.bits_per_pixel != 24) {
-		WAIT_FIFO(par, 2);
-		pm2_WR(par, PM2R_FB_BLOCK_COLOR, color);
-		wmb();
-		pm2_WR(par, PM2R_RENDER,
-				PM2F_RENDER_RECTANGLE | PM2F_RENDER_FASTFILL);
-	} else {
-		WAIT_FIFO(par, 4);
-		pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
-		pm2_WR(par, PM2R_CONSTANT_COLOR, color);
-		wmb();
-		pm2_WR(par, PM2R_RENDER,
-				PM2F_RENDER_RECTANGLE |
-				PM2F_INCREASE_X | PM2F_INCREASE_Y );
-		pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
-	}
-}
-
-static void pm2fb_copyarea(struct fb_info *info,
-				const struct fb_copyarea *area)
-{
-	struct pm2fb_par *par = info->par;
-	struct fb_copyarea modded;
-	u32 vxres, vyres;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	memcpy(&modded, area, sizeof(struct fb_copyarea));
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	if (!modded.width || !modded.height ||
-	    modded.sx >= vxres || modded.sy >= vyres ||
-	    modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.sx + modded.width > vxres)
-		modded.width = vxres - modded.sx;
-	if (modded.dx + modded.width > vxres)
-		modded.width = vxres - modded.dx;
-	if (modded.sy + modded.height > vyres)
-		modded.height = vyres - modded.sy;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	WAIT_FIFO(par, 5);
-	pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
-		PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
-	pm2_WR(par, PM2R_FB_SOURCE_DELTA,
-			((modded.sy - modded.dy) & 0xfff) << 16 |
-			((modded.sx - modded.dx) & 0xfff));
-	pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (modded.dy << 16) | modded.dx);
-	pm2_WR(par, PM2R_RECTANGLE_SIZE, (modded.height << 16) | modded.width);
-	wmb();
-	pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
-				(modded.dx < modded.sx ? PM2F_INCREASE_X : 0) |
-				(modded.dy < modded.sy ? PM2F_INCREASE_Y : 0));
-}
-
-static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct pm2fb_par *par = info->par;
-	u32 height = image->height;
-	u32 fgx, bgx;
-	const u32 *src = (const u32 *)image->data;
-	u32 xres = (info->var.xres + 31) & ~31;
-	int raster_mode = 1; /* invert bits */
-
-#ifdef __LITTLE_ENDIAN
-	raster_mode |= 3 << 7; /* reverse byte order */
-#endif
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-	switch (info->fix.visual) {
-	case FB_VISUAL_PSEUDOCOLOR:
-		fgx = image->fg_color;
-		bgx = image->bg_color;
-		break;
-	case FB_VISUAL_TRUECOLOR:
-	default:
-		fgx = par->palette[image->fg_color];
-		bgx = par->palette[image->bg_color];
-		break;
-	}
-	if (info->var.bits_per_pixel == 8) {
-		fgx |= fgx << 8;
-		bgx |= bgx << 8;
-	}
-	if (info->var.bits_per_pixel <= 16) {
-		fgx |= fgx << 16;
-		bgx |= bgx << 16;
-	}
-
-	WAIT_FIFO(par, 13);
-	pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres));
-	pm2_WR(par, PM2R_SCISSOR_MIN_XY,
-			((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
-	pm2_WR(par, PM2R_SCISSOR_MAX_XY,
-			(((image->dy + image->height) & 0x0fff) << 16) |
-			((image->dx + image->width) & 0x0fff));
-	pm2_WR(par, PM2R_SCISSOR_MODE, 1);
-	/* GXcopy & UNIT_ENABLE */
-	pm2_WR(par, PM2R_LOGICAL_OP_MODE, (0x3 << 1) | 1);
-	pm2_WR(par, PM2R_RECTANGLE_ORIGIN,
-			((image->dy & 0xfff) << 16) | (image->dx & 0x0fff));
-	pm2_WR(par, PM2R_RECTANGLE_SIZE,
-			((image->height & 0x0fff) << 16) |
-			((image->width) & 0x0fff));
-	if (info->var.bits_per_pixel == 24) {
-		pm2_WR(par, PM2R_COLOR_DDA_MODE, 1);
-		/* clear area */
-		pm2_WR(par, PM2R_CONSTANT_COLOR, bgx);
-		pm2_WR(par, PM2R_RENDER,
-			PM2F_RENDER_RECTANGLE |
-			PM2F_INCREASE_X | PM2F_INCREASE_Y);
-		/* BitMapPackEachScanline */
-		pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9));
-		pm2_WR(par, PM2R_CONSTANT_COLOR, fgx);
-		pm2_WR(par, PM2R_RENDER,
-			PM2F_RENDER_RECTANGLE |
-			PM2F_INCREASE_X | PM2F_INCREASE_Y |
-			PM2F_RENDER_SYNC_ON_BIT_MASK);
-	} else {
-		pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
-		/* clear area */
-		pm2_WR(par, PM2R_FB_BLOCK_COLOR, bgx);
-		pm2_WR(par, PM2R_RENDER,
-			PM2F_RENDER_RECTANGLE |
-			PM2F_RENDER_FASTFILL |
-			PM2F_INCREASE_X | PM2F_INCREASE_Y);
-		pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode);
-		pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx);
-		pm2_WR(par, PM2R_RENDER,
-			PM2F_RENDER_RECTANGLE |
-			PM2F_INCREASE_X | PM2F_INCREASE_Y |
-			PM2F_RENDER_FASTFILL |
-			PM2F_RENDER_SYNC_ON_BIT_MASK);
-	}
-
-	while (height--) {
-		int width = ((image->width + 7) >> 3)
-				+ info->pixmap.scan_align - 1;
-		width >>= 2;
-		WAIT_FIFO(par, width);
-		while (width--) {
-			pm2_WR(par, PM2R_BIT_MASK_PATTERN, *src);
-			src++;
-		}
-	}
-	WAIT_FIFO(par, 3);
-	pm2_WR(par, PM2R_RASTERIZER_MODE, 0);
-	pm2_WR(par, PM2R_COLOR_DDA_MODE, 0);
-	pm2_WR(par, PM2R_SCISSOR_MODE, 0);
-}
-
-/*
- *	Hardware cursor support.
- */
-static const u8 cursor_bits_lookup[16] = {
-	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
-	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
-};
-
-static int pm2vfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct pm2fb_par *par = info->par;
-	u8 mode = PM2F_CURSORMODE_TYPE_X;
-	int x = cursor->image.dx - info->var.xoffset;
-	int y = cursor->image.dy - info->var.yoffset;
-
-	if (cursor->enable)
-		mode |= PM2F_CURSORMODE_CURSOR_ENABLE;
-
-	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_MODE, mode);
-
-	if (!cursor->enable)
-		x = 2047;	/* push it outside display */
-	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_LOW, x & 0xff);
-	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0xf);
-	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_LOW, y & 0xff);
-	pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HIGH, (y >> 8) & 0xf);
-
-	/*
-	 * If the cursor is not be changed this means either we want the
-	 * current cursor state (if enable is set) or we want to query what
-	 * we can do with the cursor (if enable is not set)
-	 */
-	if (!cursor->set)
-		return 0;
-
-	if (cursor->set & FB_CUR_SETHOT) {
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_X_HOT,
-			     cursor->hot.x & 0x3f);
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_Y_HOT,
-			     cursor->hot.y & 0x3f);
-	}
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		u32 fg_idx = cursor->image.fg_color;
-		u32 bg_idx = cursor->image.bg_color;
-		struct fb_cmap cmap = info->cmap;
-
-		/* the X11 driver says one should use these color registers */
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8);
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 0,
-			     cmap.red[bg_idx] >> 8 );
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 1,
-			     cmap.green[bg_idx] >> 8 );
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 2,
-			     cmap.blue[bg_idx] >> 8 );
-
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 3,
-			     cmap.red[fg_idx] >> 8 );
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 4,
-			     cmap.green[fg_idx] >> 8 );
-		pm2v_RDAC_WR(par, PM2VI_RD_CURSOR_PALETTE + 5,
-			     cmap.blue[fg_idx] >> 8 );
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
-	}
-
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
-		u8 *bitmap = (u8 *)cursor->image.data;
-		u8 *mask = (u8 *)cursor->mask;
-		int i;
-		int pos = PM2VI_RD_CURSOR_PATTERN;
-
-		for (i = 0; i < cursor->image.height; i++) {
-			int j = (cursor->image.width + 7) >> 3;
-			int k = 8 - j;
-
-			pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
-
-			for (; j > 0; j--) {
-				u8 data = *bitmap ^ *mask;
-
-				if (cursor->rop == ROP_COPY)
-					data = *mask & *bitmap;
-				/* Upper 4 bits of bitmap data */
-				pm2v_RDAC_WR(par, pos++,
-					cursor_bits_lookup[data >> 4] |
-					(cursor_bits_lookup[*mask >> 4] << 1));
-				/* Lower 4 bits of bitmap */
-				pm2v_RDAC_WR(par, pos++,
-					cursor_bits_lookup[data & 0xf] |
-					(cursor_bits_lookup[*mask & 0xf] << 1));
-				bitmap++;
-				mask++;
-			}
-			for (; k > 0; k--) {
-				pm2v_RDAC_WR(par, pos++, 0);
-				pm2v_RDAC_WR(par, pos++, 0);
-			}
-		}
-
-		while (pos < (1024 + PM2VI_RD_CURSOR_PATTERN)) {
-			pm2_WR(par, PM2VR_RD_INDEX_HIGH, pos >> 8);
-			pm2v_RDAC_WR(par, pos++, 0);
-		}
-
-		pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
-	}
-	return 0;
-}
-
-static int pm2fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct pm2fb_par *par = info->par;
-	u8 mode;
-
-	if (!hwcursor)
-		return -EINVAL;	/* just to force soft_cursor() call */
-
-	/* Too large of a cursor or wrong bpp :-( */
-	if (cursor->image.width > 64 ||
-	    cursor->image.height > 64 ||
-	    cursor->image.depth > 1)
-		return -EINVAL;
-
-	if (par->type == PM2_TYPE_PERMEDIA2V)
-		return pm2vfb_cursor(info, cursor);
-
-	mode = 0x40;
-	if (cursor->enable)
-		 mode = 0x43;
-
-	pm2_RDAC_WR(par, PM2I_RD_CURSOR_CONTROL, mode);
-
-	/*
-	 * If the cursor is not be changed this means either we want the
-	 * current cursor state (if enable is set) or we want to query what
-	 * we can do with the cursor (if enable is not set)
-	 */
-	if (!cursor->set)
-		return 0;
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		int x = cursor->image.dx - info->var.xoffset + 63;
-		int y = cursor->image.dy - info->var.yoffset + 63;
-
-		WAIT_FIFO(par, 4);
-		pm2_WR(par, PM2R_RD_CURSOR_X_LSB, x & 0xff);
-		pm2_WR(par, PM2R_RD_CURSOR_X_MSB, (x >> 8) & 0x7);
-		pm2_WR(par, PM2R_RD_CURSOR_Y_LSB, y & 0xff);
-		pm2_WR(par, PM2R_RD_CURSOR_Y_MSB, (y >> 8) & 0x7);
-	}
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		u32 fg_idx = cursor->image.fg_color;
-		u32 bg_idx = cursor->image.bg_color;
-
-		WAIT_FIFO(par, 7);
-		pm2_WR(par, PM2R_RD_CURSOR_COLOR_ADDRESS, 1);
-		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
-			info->cmap.red[bg_idx] >> 8);
-		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
-			info->cmap.green[bg_idx] >> 8);
-		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
-			info->cmap.blue[bg_idx] >> 8);
-
-		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
-			info->cmap.red[fg_idx] >> 8);
-		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
-			info->cmap.green[fg_idx] >> 8);
-		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,
-			info->cmap.blue[fg_idx] >> 8);
-	}
-
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
-		u8 *bitmap = (u8 *)cursor->image.data;
-		u8 *mask = (u8 *)cursor->mask;
-		int i;
-
-		WAIT_FIFO(par, 1);
-		pm2_WR(par, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
-
-		for (i = 0; i < cursor->image.height; i++) {
-			int j = (cursor->image.width + 7) >> 3;
-			int k = 8 - j;
-
-			WAIT_FIFO(par, 8);
-			for (; j > 0; j--) {
-				u8 data = *bitmap ^ *mask;
-
-				if (cursor->rop == ROP_COPY)
-					data = *mask & *bitmap;
-				/* bitmap data */
-				pm2_WR(par, PM2R_RD_CURSOR_DATA, data);
-				bitmap++;
-				mask++;
-			}
-			for (; k > 0; k--)
-				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
-		}
-		for (; i < 64; i++) {
-			int j = 8;
-			WAIT_FIFO(par, 8);
-			while (j-- > 0)
-				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
-		}
-
-		mask = (u8 *)cursor->mask;
-		for (i = 0; i < cursor->image.height; i++) {
-			int j = (cursor->image.width + 7) >> 3;
-			int k = 8 - j;
-
-			WAIT_FIFO(par, 8);
-			for (; j > 0; j--) {
-				/* mask */
-				pm2_WR(par, PM2R_RD_CURSOR_DATA, *mask);
-				mask++;
-			}
-			for (; k > 0; k--)
-				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
-		}
-		for (; i < 64; i++) {
-			int j = 8;
-			WAIT_FIFO(par, 8);
-			while (j-- > 0)
-				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);
-		}
-	}
-	return 0;
-}
-
-/* ------------ Hardware Independent Functions ------------ */
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops pm2fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= pm2fb_check_var,
-	.fb_set_par	= pm2fb_set_par,
-	.fb_setcolreg	= pm2fb_setcolreg,
-	.fb_blank	= pm2fb_blank,
-	.fb_pan_display	= pm2fb_pan_display,
-	.fb_fillrect	= pm2fb_fillrect,
-	.fb_copyarea	= pm2fb_copyarea,
-	.fb_imageblit	= pm2fb_imageblit,
-	.fb_sync	= pm2fb_sync,
-	.fb_cursor	= pm2fb_cursor,
-};
-
-/*
- * PCI stuff
- */
-
-
-/**
- * Device initialisation
- *
- * Initialise and allocate resource for PCI device.
- *
- * @param	pdev	PCI device.
- * @param	id	PCI device ID.
- */
-static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct pm2fb_par *default_par;
-	struct fb_info *info;
-	int err;
-	int retval = -ENXIO;
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
-		return err;
-	}
-
-	info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-	default_par = info->par;
-
-	switch (pdev->device) {
-	case  PCI_DEVICE_ID_TI_TVP4020:
-		strcpy(pm2fb_fix.id, "TVP4020");
-		default_par->type = PM2_TYPE_PERMEDIA2;
-		break;
-	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2:
-		strcpy(pm2fb_fix.id, "Permedia2");
-		default_par->type = PM2_TYPE_PERMEDIA2;
-		break;
-	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2V:
-		strcpy(pm2fb_fix.id, "Permedia2v");
-		default_par->type = PM2_TYPE_PERMEDIA2V;
-		break;
-	}
-
-	pm2fb_fix.mmio_start = pci_resource_start(pdev, 0);
-	pm2fb_fix.mmio_len = PM2_REGS_SIZE;
-
-#if defined(__BIG_ENDIAN)
-	/*
-	 * PM2 has a 64k register file, mapped twice in 128k. Lower
-	 * map is little-endian, upper map is big-endian.
-	 */
-	pm2fb_fix.mmio_start += PM2_REGS_SIZE;
-	DPRINTK("Adjusting register base for big-endian.\n");
-#endif
-	DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
-
-	/* Registers - request region and map it. */
-	if (!request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
-				"pm2fb regbase")) {
-		printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");
-		goto err_exit_neither;
-	}
-	default_par->v_regs =
-		ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
-	if (!default_par->v_regs) {
-		printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",
-		       pm2fb_fix.id);
-		release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
-		goto err_exit_neither;
-	}
-
-	/* Stash away memory register info for use when we reset the board */
-	default_par->mem_control = pm2_RD(default_par, PM2R_MEM_CONTROL);
-	default_par->boot_address = pm2_RD(default_par, PM2R_BOOT_ADDRESS);
-	default_par->mem_config = pm2_RD(default_par, PM2R_MEM_CONFIG);
-	DPRINTK("MemControl 0x%x BootAddress 0x%x MemConfig 0x%x\n",
-		default_par->mem_control, default_par->boot_address,
-		default_par->mem_config);
-
-	if (default_par->mem_control == 0 &&
-		default_par->boot_address == 0x31 &&
-		default_par->mem_config == 0x259fffff) {
-		default_par->memclock = CVPPC_MEMCLOCK;
-		default_par->mem_control = 0;
-		default_par->boot_address = 0x20;
-		default_par->mem_config = 0xe6002021;
-		if (pdev->subsystem_vendor == 0x1048 &&
-			pdev->subsystem_device == 0x0a31) {
-			DPRINTK("subsystem_vendor: %04x, "
-				"subsystem_device: %04x\n",
-				pdev->subsystem_vendor, pdev->subsystem_device);
-			DPRINTK("We have not been initialized by VGA BIOS and "
-				"are running on an Elsa Winner 2000 Office\n");
-			DPRINTK("Initializing card timings manually...\n");
-			default_par->memclock = 100000;
-		}
-		if (pdev->subsystem_vendor == 0x3d3d &&
-			pdev->subsystem_device == 0x0100) {
-			DPRINTK("subsystem_vendor: %04x, "
-				"subsystem_device: %04x\n",
-				pdev->subsystem_vendor, pdev->subsystem_device);
-			DPRINTK("We have not been initialized by VGA BIOS and "
-				"are running on an 3dlabs reference board\n");
-			DPRINTK("Initializing card timings manually...\n");
-			default_par->memclock = 74894;
-		}
-	}
-
-	/* Now work out how big lfb is going to be. */
-	switch (default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
-	case PM2F_MEM_BANKS_1:
-		pm2fb_fix.smem_len = 0x200000;
-		break;
-	case PM2F_MEM_BANKS_2:
-		pm2fb_fix.smem_len = 0x400000;
-		break;
-	case PM2F_MEM_BANKS_3:
-		pm2fb_fix.smem_len = 0x600000;
-		break;
-	case PM2F_MEM_BANKS_4:
-		pm2fb_fix.smem_len = 0x800000;
-		break;
-	}
-	pm2fb_fix.smem_start = pci_resource_start(pdev, 1);
-
-	/* Linear frame buffer - request region and map it. */
-	if (!request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,
-				"pm2fb smem")) {
-		printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");
-		goto err_exit_mmio;
-	}
-	info->screen_base =
-		ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
-	if (!info->screen_base) {
-		printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");
-		release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
-		goto err_exit_mmio;
-	}
-
-#ifdef CONFIG_MTRR
-	default_par->mtrr_handle = -1;
-	if (!nomtrr)
-		default_par->mtrr_handle =
-			mtrr_add(pm2fb_fix.smem_start,
-				 pm2fb_fix.smem_len,
-				 MTRR_TYPE_WRCOMB, 1);
-#endif
-
-	info->fbops		= &pm2fb_ops;
-	info->fix		= pm2fb_fix;
-	info->pseudo_palette	= default_par->palette;
-	info->flags		= FBINFO_DEFAULT |
-				  FBINFO_HWACCEL_YPAN |
-				  FBINFO_HWACCEL_COPYAREA |
-				  FBINFO_HWACCEL_IMAGEBLIT |
-				  FBINFO_HWACCEL_FILLRECT;
-
-	info->pixmap.addr = kmalloc(PM2_PIXMAP_SIZE, GFP_KERNEL);
-	if (!info->pixmap.addr) {
-		retval = -ENOMEM;
-		goto err_exit_pixmap;
-	}
-	info->pixmap.size = PM2_PIXMAP_SIZE;
-	info->pixmap.buf_align = 4;
-	info->pixmap.scan_align = 4;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-	if (noaccel) {
-		printk(KERN_DEBUG "disabling acceleration\n");
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-		info->pixmap.scan_align = 1;
-	}
-
-	if (!mode_option)
-		mode_option = "640x480@60";
-
-	err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
-	if (!err || err == 4)
-		info->var = pm2fb_var;
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0)
-		goto err_exit_both;
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err_exit_all;
-
-	fb_info(info, "%s frame buffer device, memory = %dK\n",
-		info->fix.id, pm2fb_fix.smem_len / 1024);
-
-	/*
-	 * Our driver data
-	 */
-	pci_set_drvdata(pdev, info);
-
-	return 0;
-
- err_exit_all:
-	fb_dealloc_cmap(&info->cmap);
- err_exit_both:
-	kfree(info->pixmap.addr);
- err_exit_pixmap:
-	iounmap(info->screen_base);
-	release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
- err_exit_mmio:
-	iounmap(default_par->v_regs);
-	release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);
- err_exit_neither:
-	framebuffer_release(info);
-	return retval;
-}
-
-/**
- * Device removal.
- *
- * Release all device resources.
- *
- * @param	pdev	PCI device to clean up.
- */
-static void pm2fb_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct fb_fix_screeninfo *fix = &info->fix;
-	struct pm2fb_par *par = info->par;
-
-	unregister_framebuffer(info);
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr_handle >= 0)
-		mtrr_del(par->mtrr_handle, info->fix.smem_start,
-			 info->fix.smem_len);
-#endif /* CONFIG_MTRR */
-	iounmap(info->screen_base);
-	release_mem_region(fix->smem_start, fix->smem_len);
-	iounmap(par->v_regs);
-	release_mem_region(fix->mmio_start, fix->mmio_len);
-
-	fb_dealloc_cmap(&info->cmap);
-	kfree(info->pixmap.addr);
-	framebuffer_release(info);
-}
-
-static struct pci_device_id pm2fb_id_table[] = {
-	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0, }
-};
-
-static struct pci_driver pm2fb_driver = {
-	.name		= "pm2fb",
-	.id_table	= pm2fb_id_table,
-	.probe		= pm2fb_probe,
-	.remove		= pm2fb_remove,
-};
-
-MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
-
-
-#ifndef MODULE
-/**
- * Parse user specified options.
- *
- * This is, comma-separated options following `video=pm2fb:'.
- */
-static int __init pm2fb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "lowhsync"))
-			lowhsync = 1;
-		else if (!strcmp(this_opt, "lowvsync"))
-			lowvsync = 1;
-		else if (!strncmp(this_opt, "hwcursor=", 9))
-			hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
-#ifdef CONFIG_MTRR
-		else if (!strncmp(this_opt, "nomtrr", 6))
-			nomtrr = 1;
-#endif
-		else if (!strncmp(this_opt, "noaccel", 7))
-			noaccel = 1;
-		else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-#endif
-
-
-static int __init pm2fb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("pm2fb", &option))
-		return -ENODEV;
-	pm2fb_setup(option);
-#endif
-
-	return pci_register_driver(&pm2fb_driver);
-}
-
-module_init(pm2fb_init);
-
-#ifdef MODULE
-/*
- *  Cleanup
- */
-
-static void __exit pm2fb_exit(void)
-{
-	pci_unregister_driver(&pm2fb_driver);
-}
-#endif
-
-#ifdef MODULE
-module_exit(pm2fb_exit);
-
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
-module_param_named(mode, mode_option, charp, 0);
-MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8@60' (deprecated)");
-module_param(lowhsync, bool, 0);
-MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");
-module_param(lowvsync, bool, 0);
-MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");
-module_param(noaccel, bool, 0);
-MODULE_PARM_DESC(noaccel, "Disable acceleration");
-module_param(hwcursor, int, 0644);
-MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
-			"(1=enable, 0=disable, default=1)");
-#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, 0);
-MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
-#endif
-
-MODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");
-MODULE_DESCRIPTION("Permedia2 framebuffer device driver");
-MODULE_LICENSE("GPL");
-#endif
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
deleted file mode 100644
index 4bf3273d0433..000000000000
--- a/drivers/video/pm3fb.c
+++ /dev/null
@@ -1,1586 +0,0 @@
-/*
- *  linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device
- *
- *  Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>.
- *
- *  Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl>
- *	based on pm2fb.c
- *
- *  Based on code written by:
- *	   Sven Luther, <luther@dpt-info.u-strasbg.fr>
- *	   Alan Hourihane, <alanh@fairlite.demon.co.uk>
- *	   Russell King, <rmk@arm.linux.org.uk>
- *  Based on linux/drivers/video/skeletonfb.c:
- *	Copyright (C) 1997 Geert Uytterhoeven
- *  Based on linux/driver/video/pm2fb.c:
- *	Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- *	Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/pm3fb.h>
-
-#if !defined(CONFIG_PCI)
-#error "Only generic PCI cards supported."
-#endif
-
-#undef PM3FB_MASTER_DEBUG
-#ifdef PM3FB_MASTER_DEBUG
-#define DPRINTK(a, b...)	\
-	printk(KERN_DEBUG "pm3fb: %s: " a, __func__ , ## b)
-#else
-#define DPRINTK(a, b...)
-#endif
-
-#define PM3_PIXMAP_SIZE	(2048 * 4)
-
-/*
- * Driver data
- */
-static int hwcursor = 1;
-static char *mode_option;
-static bool noaccel;
-
-/* mtrr option */
-#ifdef CONFIG_MTRR
-static bool nomtrr;
-#endif
-
-/*
- * This structure defines the hardware state of the graphics card. Normally
- * you place this in a header file in linux/include/video. This file usually
- * also includes register information. That allows other driver subsystems
- * and userland applications the ability to use the same header file to
- * avoid duplicate work and easy porting of software.
- */
-struct pm3_par {
-	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
-	u32		video;		/* video flags before blanking */
-	u32		base;		/* screen base in 128 bits unit */
-	u32		palette[16];
-	int		mtrr_handle;
-};
-
-/*
- * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
- * if we don't use modedb. If we do use modedb see pm3fb_init how to use it
- * to get a fb_var_screeninfo. Otherwise define a default var as well.
- */
-static struct fb_fix_screeninfo pm3fb_fix = {
-	.id =		"Permedia3",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	0,
-	.accel =	FB_ACCEL_3DLABS_PERMEDIA3,
-};
-
-/*
- * Utility functions
- */
-
-static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off)
-{
-	return fb_readl(par->v_regs + off);
-}
-
-static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
-{
-	fb_writel(v, par->v_regs + off);
-}
-
-static inline void PM3_WAIT(struct pm3_par *par, u32 n)
-{
-	while (PM3_READ_REG(par, PM3InFIFOSpace) < n)
-		cpu_relax();
-}
-
-static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
-{
-	PM3_WAIT(par, 3);
-	PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff);
-	PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff);
-	wmb();
-	PM3_WRITE_REG(par, PM3RD_IndexedData, v);
-	wmb();
-}
-
-static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
-			unsigned char r, unsigned char g, unsigned char b)
-{
-	PM3_WAIT(par, 4);
-	PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
-	wmb();
-	PM3_WRITE_REG(par, PM3RD_PaletteData, r);
-	wmb();
-	PM3_WRITE_REG(par, PM3RD_PaletteData, g);
-	wmb();
-	PM3_WRITE_REG(par, PM3RD_PaletteData, b);
-	wmb();
-}
-
-static void pm3fb_clear_colormap(struct pm3_par *par,
-			unsigned char r, unsigned char g, unsigned char b)
-{
-	int i;
-
-	for (i = 0; i < 256 ; i++)
-		pm3fb_set_color(par, i, r, g, b);
-
-}
-
-/* Calculating various clock parameters */
-static void pm3fb_calculate_clock(unsigned long reqclock,
-				unsigned char *prescale,
-				unsigned char *feedback,
-				unsigned char *postscale)
-{
-	int f, pre, post;
-	unsigned long freq;
-	long freqerr = 1000;
-	long currerr;
-
-	for (f = 1; f < 256; f++) {
-		for (pre = 1; pre < 256; pre++) {
-			for (post = 0; post < 5; post++) {
-				freq = ((2*PM3_REF_CLOCK * f) >> post) / pre;
-				currerr = (reqclock > freq)
-					? reqclock - freq
-					: freq - reqclock;
-				if (currerr < freqerr) {
-					freqerr = currerr;
-					*feedback = f;
-					*prescale = pre;
-					*postscale = post;
-				}
-			}
-		}
-	}
-}
-
-static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
-{
-	if (var->bits_per_pixel == 16)
-		return var->red.length + var->green.length
-			+ var->blue.length;
-
-	return var->bits_per_pixel;
-}
-
-static inline int pm3fb_shift_bpp(unsigned bpp, int v)
-{
-	switch (bpp) {
-	case 8:
-		return (v >> 4);
-	case 16:
-		return (v >> 3);
-	case 32:
-		return (v >> 2);
-	}
-	DPRINTK("Unsupported depth %u\n", bpp);
-	return 0;
-}
-
-/* acceleration */
-static int pm3fb_sync(struct fb_info *info)
-{
-	struct pm3_par *par = info->par;
-
-	PM3_WAIT(par, 2);
-	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
-	PM3_WRITE_REG(par, PM3Sync, 0);
-	mb();
-	do {
-		while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0)
-			cpu_relax();
-	} while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
-
-	return 0;
-}
-
-static void pm3fb_init_engine(struct fb_info *info)
-{
-	struct pm3_par *par = info->par;
-	const u32 width = (info->var.xres_virtual + 7) & ~7;
-
-	PM3_WAIT(par, 50);
-	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
-	PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
-	PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
-	PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
-	PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
-	PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
-	PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
-	PM3_WRITE_REG(par, PM3GIDMode, 0x0);
-	PM3_WRITE_REG(par, PM3DepthMode, 0x0);
-	PM3_WRITE_REG(par, PM3StencilMode, 0x0);
-	PM3_WRITE_REG(par, PM3StencilData, 0x0);
-	PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
-	PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
-	PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
-	PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
-	PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
-	PM3_WRITE_REG(par, PM3LUTMode, 0x0);
-	PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
-	PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
-	PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
-	PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
-	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
-	PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
-	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
-	PM3_WRITE_REG(par, PM3FogMode, 0x0);
-	PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
-	PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
-	PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
-	PM3_WRITE_REG(par, PM3YUVMode, 0x0);
-	PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
-	PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
-	PM3_WRITE_REG(par, PM3DitherMode, 0x0);
-	PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
-	PM3_WRITE_REG(par, PM3RouterMode, 0x0);
-	PM3_WRITE_REG(par, PM3Window, 0x0);
-
-	PM3_WRITE_REG(par, PM3Config2D, 0x0);
-
-	PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);
-
-	PM3_WRITE_REG(par, PM3XBias, 0x0);
-	PM3_WRITE_REG(par, PM3YBias, 0x0);
-	PM3_WRITE_REG(par, PM3DeltaControl, 0x0);
-
-	PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);
-
-	PM3_WRITE_REG(par, PM3FBDestReadEnables,
-			   PM3FBDestReadEnables_E(0xff) |
-			   PM3FBDestReadEnables_R(0xff) |
-			   PM3FBDestReadEnables_ReferenceAlpha(0xff));
-	PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
-	PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
-	PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
-			   PM3FBDestReadBufferWidth_Width(width));
-
-	PM3_WRITE_REG(par, PM3FBDestReadMode,
-			   PM3FBDestReadMode_ReadEnable |
-			   PM3FBDestReadMode_Enable0);
-	PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
-	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
-	PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
-			   PM3FBSourceReadBufferWidth_Width(width));
-	PM3_WRITE_REG(par, PM3FBSourceReadMode,
-			   PM3FBSourceReadMode_Blocking |
-			   PM3FBSourceReadMode_ReadEnable);
-
-	PM3_WAIT(par, 2);
-	{
-		/* invert bits in bitmask */
-		unsigned long rm = 1 | (3 << 7);
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			PM3_WRITE_REG(par, PM3PixelSize,
-					   PM3PixelSize_GLOBAL_8BIT);
-#ifdef __BIG_ENDIAN
-			rm |= 3 << 15;
-#endif
-			break;
-		case 16:
-			PM3_WRITE_REG(par, PM3PixelSize,
-					   PM3PixelSize_GLOBAL_16BIT);
-#ifdef __BIG_ENDIAN
-			rm |= 2 << 15;
-#endif
-			break;
-		case 32:
-			PM3_WRITE_REG(par, PM3PixelSize,
-					   PM3PixelSize_GLOBAL_32BIT);
-			break;
-		default:
-			DPRINTK(1, "Unsupported depth %d\n",
-				info->var.bits_per_pixel);
-			break;
-		}
-		PM3_WRITE_REG(par, PM3RasterizerMode, rm);
-	}
-
-	PM3_WAIT(par, 20);
-	PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
-	PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
-	PM3_WRITE_REG(par, PM3FBWriteMode,
-			   PM3FBWriteMode_WriteEnable |
-			   PM3FBWriteMode_OpaqueSpan |
-			   PM3FBWriteMode_Enable0);
-	PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
-	PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
-	PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
-			   PM3FBWriteBufferWidth_Width(width));
-
-	PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
-	{
-		/* size in lines of FB */
-		unsigned long sofb = info->screen_size /
-			info->fix.line_length;
-		if (sofb > 4095)
-			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
-		else
-			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);
-
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			PM3_WRITE_REG(par, PM3DitherMode,
-					   (1 << 10) | (2 << 3));
-			break;
-		case 16:
-			PM3_WRITE_REG(par, PM3DitherMode,
-					   (1 << 10) | (1 << 3));
-			break;
-		case 32:
-			PM3_WRITE_REG(par, PM3DitherMode,
-					   (1 << 10) | (0 << 3));
-			break;
-		default:
-			DPRINTK(1, "Unsupported depth %d\n",
-				info->current_par->depth);
-			break;
-		}
-	}
-
-	PM3_WRITE_REG(par, PM3dXDom, 0x0);
-	PM3_WRITE_REG(par, PM3dXSub, 0x0);
-	PM3_WRITE_REG(par, PM3dY, 1 << 16);
-	PM3_WRITE_REG(par, PM3StartXDom, 0x0);
-	PM3_WRITE_REG(par, PM3StartXSub, 0x0);
-	PM3_WRITE_REG(par, PM3StartY, 0x0);
-	PM3_WRITE_REG(par, PM3Count, 0x0);
-
-/* Disable LocalBuffer. better safe than sorry */
-	PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0);
-	PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0);
-	PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0);
-	PM3_WRITE_REG(par, PM3LBWriteMode, 0x0);
-
-	pm3fb_sync(info);
-}
-
-static void pm3fb_fillrect(struct fb_info *info,
-				const struct fb_fillrect *region)
-{
-	struct pm3_par *par = info->par;
-	struct fb_fillrect modded;
-	int vxres, vyres;
-	int rop;
-	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
-		((u32 *)info->pseudo_palette)[region->color] : region->color;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(info, region);
-		return;
-	}
-	if (region->rop == ROP_COPY )
-		rop = PM3Config2D_ForegroundROP(0x3); /* GXcopy */
-	else
-		rop = PM3Config2D_ForegroundROP(0x6) | /* GXxor */
-			PM3Config2D_FBDestReadEnable;
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	memcpy(&modded, region, sizeof(struct fb_fillrect));
-
-	if (!modded.width || !modded.height ||
-	    modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.dx + modded.width  > vxres)
-		modded.width  = vxres - modded.dx;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	if (info->var.bits_per_pixel == 8)
-		color |= color << 8;
-	if (info->var.bits_per_pixel <= 16)
-		color |= color << 16;
-
-	PM3_WAIT(par, 4);
-	/* ROP Ox3 is GXcopy */
-	PM3_WRITE_REG(par, PM3Config2D,
-			PM3Config2D_UseConstantSource |
-			PM3Config2D_ForegroundROPEnable |
-			rop |
-			PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(par, PM3ForegroundColor, color);
-
-	PM3_WRITE_REG(par, PM3RectanglePosition,
-			PM3RectanglePosition_XOffset(modded.dx) |
-			PM3RectanglePosition_YOffset(modded.dy));
-
-	PM3_WRITE_REG(par, PM3Render2D,
-		      PM3Render2D_XPositive |
-		      PM3Render2D_YPositive |
-		      PM3Render2D_Operation_Normal |
-		      PM3Render2D_SpanOperation |
-		      PM3Render2D_Width(modded.width) |
-		      PM3Render2D_Height(modded.height));
-}
-
-static void pm3fb_copyarea(struct fb_info *info,
-				const struct fb_copyarea *area)
-{
-	struct pm3_par *par = info->par;
-	struct fb_copyarea modded;
-	u32 vxres, vyres;
-	int x_align, o_x, o_y;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	memcpy(&modded, area, sizeof(struct fb_copyarea));
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	if (!modded.width || !modded.height ||
-	    modded.sx >= vxres || modded.sy >= vyres ||
-	    modded.dx >= vxres || modded.dy >= vyres)
-		return;
-
-	if (modded.sx + modded.width > vxres)
-		modded.width = vxres - modded.sx;
-	if (modded.dx + modded.width > vxres)
-		modded.width = vxres - modded.dx;
-	if (modded.sy + modded.height > vyres)
-		modded.height = vyres - modded.sy;
-	if (modded.dy + modded.height > vyres)
-		modded.height = vyres - modded.dy;
-
-	o_x = modded.sx - modded.dx;	/*(sx > dx ) ? (sx - dx) : (dx - sx); */
-	o_y = modded.sy - modded.dy;	/*(sy > dy ) ? (sy - dy) : (dy - sy); */
-
-	x_align = (modded.sx & 0x1f);
-
-	PM3_WAIT(par, 6);
-
-	PM3_WRITE_REG(par, PM3Config2D,
-			PM3Config2D_UserScissorEnable |
-			PM3Config2D_ForegroundROPEnable |
-			PM3Config2D_Blocking |
-			PM3Config2D_ForegroundROP(0x3) | /* Ox3 is GXcopy */
-			PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(par, PM3ScissorMinXY,
-			((modded.dy & 0x0fff) << 16) | (modded.dx & 0x0fff));
-	PM3_WRITE_REG(par, PM3ScissorMaxXY,
-			(((modded.dy + modded.height) & 0x0fff) << 16) |
-			((modded.dx + modded.width) & 0x0fff));
-
-	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset,
-			PM3FBSourceReadBufferOffset_XOffset(o_x) |
-			PM3FBSourceReadBufferOffset_YOffset(o_y));
-
-	PM3_WRITE_REG(par, PM3RectanglePosition,
-			PM3RectanglePosition_XOffset(modded.dx - x_align) |
-			PM3RectanglePosition_YOffset(modded.dy));
-
-	PM3_WRITE_REG(par, PM3Render2D,
-			((modded.sx > modded.dx) ? PM3Render2D_XPositive : 0) |
-			((modded.sy > modded.dy) ? PM3Render2D_YPositive : 0) |
-			PM3Render2D_Operation_Normal |
-			PM3Render2D_SpanOperation |
-			PM3Render2D_FBSourceReadEnable |
-			PM3Render2D_Width(modded.width + x_align) |
-			PM3Render2D_Height(modded.height));
-}
-
-static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct pm3_par *par = info->par;
-	u32 height = image->height;
-	u32 fgx, bgx;
-	const u32 *src = (const u32 *)image->data;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_imageblit(info, image);
-		return;
-	}
-	switch (info->fix.visual) {
-	case FB_VISUAL_PSEUDOCOLOR:
-		fgx = image->fg_color;
-		bgx = image->bg_color;
-		break;
-	case FB_VISUAL_TRUECOLOR:
-	default:
-		fgx = par->palette[image->fg_color];
-		bgx = par->palette[image->bg_color];
-		break;
-	}
-	if (image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	if (info->var.bits_per_pixel == 8) {
-		fgx |= fgx << 8;
-		bgx |= bgx << 8;
-	}
-	if (info->var.bits_per_pixel <= 16) {
-		fgx |= fgx << 16;
-		bgx |= bgx << 16;
-	}
-
-	PM3_WAIT(par, 7);
-
-	PM3_WRITE_REG(par, PM3ForegroundColor, fgx);
-	PM3_WRITE_REG(par, PM3BackgroundColor, bgx);
-
-	/* ROP Ox3 is GXcopy */
-	PM3_WRITE_REG(par, PM3Config2D,
-			PM3Config2D_UserScissorEnable |
-			PM3Config2D_UseConstantSource |
-			PM3Config2D_ForegroundROPEnable |
-			PM3Config2D_ForegroundROP(0x3) |
-			PM3Config2D_OpaqueSpan |
-			PM3Config2D_FBWriteEnable);
-	PM3_WRITE_REG(par, PM3ScissorMinXY,
-			((image->dy & 0x0fff) << 16) | (image->dx & 0x0fff));
-	PM3_WRITE_REG(par, PM3ScissorMaxXY,
-			(((image->dy + image->height) & 0x0fff) << 16) |
-			((image->dx + image->width) & 0x0fff));
-	PM3_WRITE_REG(par, PM3RectanglePosition,
-			PM3RectanglePosition_XOffset(image->dx) |
-			PM3RectanglePosition_YOffset(image->dy));
-	PM3_WRITE_REG(par, PM3Render2D,
-			PM3Render2D_XPositive |
-			PM3Render2D_YPositive |
-			PM3Render2D_Operation_SyncOnBitMask |
-			PM3Render2D_SpanOperation |
-			PM3Render2D_Width(image->width) |
-			PM3Render2D_Height(image->height));
-
-
-	while (height--) {
-		int width = ((image->width + 7) >> 3)
-				+ info->pixmap.scan_align - 1;
-		width >>= 2;
-
-		while (width >= PM3_FIFO_SIZE) {
-			int i = PM3_FIFO_SIZE - 1;
-
-			PM3_WAIT(par, PM3_FIFO_SIZE);
-			while (i--) {
-				PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
-				src++;
-			}
-			width -= PM3_FIFO_SIZE - 1;
-		}
-
-		PM3_WAIT(par, width + 1);
-		while (width--) {
-			PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
-			src++;
-		}
-	}
-}
-/* end of acceleration functions */
-
-/*
- *	Hardware Cursor support.
- */
-static const u8 cursor_bits_lookup[16] = {
-	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
-	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
-};
-
-static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct pm3_par *par = info->par;
-	u8 mode;
-
-	if (!hwcursor)
-		return -EINVAL;	/* just to force soft_cursor() call */
-
-	/* Too large of a cursor or wrong bpp :-( */
-	if (cursor->image.width > 64 ||
-	    cursor->image.height > 64 ||
-	    cursor->image.depth > 1)
-		return -EINVAL;
-
-	mode = PM3RD_CursorMode_TYPE_X;
-	if (cursor->enable)
-		 mode |= PM3RD_CursorMode_CURSOR_ENABLE;
-
-	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode);
-
-	/*
-	 * If the cursor is not be changed this means either we want the
-	 * current cursor state (if enable is set) or we want to query what
-	 * we can do with the cursor (if enable is not set)
-	 */
-	if (!cursor->set)
-		return 0;
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		int x = cursor->image.dx - info->var.xoffset;
-		int y = cursor->image.dy - info->var.yoffset;
-
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff);
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf);
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff);
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf);
-	}
-
-	if (cursor->set & FB_CUR_SETHOT) {
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX,
-				  cursor->hot.x & 0x3f);
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY,
-				  cursor->hot.y & 0x3f);
-	}
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		u32 fg_idx = cursor->image.fg_color;
-		u32 bg_idx = cursor->image.bg_color;
-		struct fb_cmap cmap = info->cmap;
-
-		/* the X11 driver says one should use these color registers */
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39),
-				  cmap.red[fg_idx] >> 8 );
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40),
-				  cmap.green[fg_idx] >> 8 );
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41),
-				  cmap.blue[fg_idx] >> 8 );
-
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42),
-				  cmap.red[bg_idx] >> 8 );
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43),
-				  cmap.green[bg_idx] >> 8 );
-		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44),
-				  cmap.blue[bg_idx] >> 8 );
-	}
-
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
-		u8 *bitmap = (u8 *)cursor->image.data;
-		u8 *mask = (u8 *)cursor->mask;
-		int i;
-		int pos = PM3RD_CursorPattern(0);
-
-		for (i = 0; i < cursor->image.height; i++) {
-			int j = (cursor->image.width + 7) >> 3;
-			int k = 8 - j;
-
-			for (; j > 0; j--) {
-				u8 data = *bitmap ^ *mask;
-
-				if (cursor->rop == ROP_COPY)
-					data = *mask & *bitmap;
-				/* Upper 4 bits of bitmap data */
-				PM3_WRITE_DAC_REG(par, pos++,
-					cursor_bits_lookup[data >> 4] |
-					(cursor_bits_lookup[*mask >> 4] << 1));
-				/* Lower 4 bits of bitmap */
-				PM3_WRITE_DAC_REG(par, pos++,
-					cursor_bits_lookup[data & 0xf] |
-					(cursor_bits_lookup[*mask & 0xf] << 1));
-				bitmap++;
-				mask++;
-			}
-			for (; k > 0; k--) {
-				PM3_WRITE_DAC_REG(par, pos++, 0);
-				PM3_WRITE_DAC_REG(par, pos++, 0);
-			}
-		}
-		while (pos < PM3RD_CursorPattern(1024))
-			PM3_WRITE_DAC_REG(par, pos++, 0);
-	}
-	return 0;
-}
-
-/* write the mode to registers */
-static void pm3fb_write_mode(struct fb_info *info)
-{
-	struct pm3_par *par = info->par;
-	char tempsync = 0x00;
-	char tempmisc = 0x00;
-	const u32 hsstart = info->var.right_margin;
-	const u32 hsend = hsstart + info->var.hsync_len;
-	const u32 hbend = hsend + info->var.left_margin;
-	const u32 xres = (info->var.xres + 31) & ~31;
-	const u32 htotal = xres + hbend;
-	const u32 vsstart = info->var.lower_margin;
-	const u32 vsend = vsstart + info->var.vsync_len;
-	const u32 vbend = vsend + info->var.upper_margin;
-	const u32 vtotal = info->var.yres + vbend;
-	const u32 width = (info->var.xres_virtual + 7) & ~7;
-	const unsigned bpp = info->var.bits_per_pixel;
-
-	PM3_WAIT(par, 20);
-	PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
-	PM3_WRITE_REG(par, PM3Aperture0, 0x00000000);
-	PM3_WRITE_REG(par, PM3Aperture1, 0x00000000);
-	PM3_WRITE_REG(par, PM3FIFODis, 0x00000007);
-
-	PM3_WRITE_REG(par, PM3HTotal,
-			   pm3fb_shift_bpp(bpp, htotal - 1));
-	PM3_WRITE_REG(par, PM3HsEnd,
-			   pm3fb_shift_bpp(bpp, hsend));
-	PM3_WRITE_REG(par, PM3HsStart,
-			   pm3fb_shift_bpp(bpp, hsstart));
-	PM3_WRITE_REG(par, PM3HbEnd,
-			   pm3fb_shift_bpp(bpp, hbend));
-	PM3_WRITE_REG(par, PM3HgEnd,
-			   pm3fb_shift_bpp(bpp, hbend));
-	PM3_WRITE_REG(par, PM3ScreenStride,
-			   pm3fb_shift_bpp(bpp, width));
-	PM3_WRITE_REG(par, PM3VTotal, vtotal - 1);
-	PM3_WRITE_REG(par, PM3VsEnd, vsend - 1);
-	PM3_WRITE_REG(par, PM3VsStart, vsstart - 1);
-	PM3_WRITE_REG(par, PM3VbEnd, vbend);
-
-	switch (bpp) {
-	case 8:
-		PM3_WRITE_REG(par, PM3ByAperture1Mode,
-				   PM3ByApertureMode_PIXELSIZE_8BIT);
-		PM3_WRITE_REG(par, PM3ByAperture2Mode,
-				   PM3ByApertureMode_PIXELSIZE_8BIT);
-		break;
-
-	case 16:
-#ifndef __BIG_ENDIAN
-		PM3_WRITE_REG(par, PM3ByAperture1Mode,
-				   PM3ByApertureMode_PIXELSIZE_16BIT);
-		PM3_WRITE_REG(par, PM3ByAperture2Mode,
-				   PM3ByApertureMode_PIXELSIZE_16BIT);
-#else
-		PM3_WRITE_REG(par, PM3ByAperture1Mode,
-				   PM3ByApertureMode_PIXELSIZE_16BIT |
-				   PM3ByApertureMode_BYTESWAP_BADC);
-		PM3_WRITE_REG(par, PM3ByAperture2Mode,
-				   PM3ByApertureMode_PIXELSIZE_16BIT |
-				   PM3ByApertureMode_BYTESWAP_BADC);
-#endif /* ! __BIG_ENDIAN */
-		break;
-
-	case 32:
-#ifndef __BIG_ENDIAN
-		PM3_WRITE_REG(par, PM3ByAperture1Mode,
-				   PM3ByApertureMode_PIXELSIZE_32BIT);
-		PM3_WRITE_REG(par, PM3ByAperture2Mode,
-				   PM3ByApertureMode_PIXELSIZE_32BIT);
-#else
-		PM3_WRITE_REG(par, PM3ByAperture1Mode,
-				   PM3ByApertureMode_PIXELSIZE_32BIT |
-				   PM3ByApertureMode_BYTESWAP_DCBA);
-		PM3_WRITE_REG(par, PM3ByAperture2Mode,
-				   PM3ByApertureMode_PIXELSIZE_32BIT |
-				   PM3ByApertureMode_BYTESWAP_DCBA);
-#endif /* ! __BIG_ENDIAN */
-		break;
-
-	default:
-		DPRINTK("Unsupported depth %d\n", bpp);
-		break;
-	}
-
-	/*
-	 * Oxygen VX1 - it appears that setting PM3VideoControl and
-	 * then PM3RD_SyncControl to the same SYNC settings undoes
-	 * any net change - they seem to xor together.  Only set the
-	 * sync options in PM3RD_SyncControl.  --rmk
-	 */
-	{
-		unsigned int video = par->video;
-
-		video &= ~(PM3VideoControl_HSYNC_MASK |
-			   PM3VideoControl_VSYNC_MASK);
-		video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
-			 PM3VideoControl_VSYNC_ACTIVE_HIGH;
-		PM3_WRITE_REG(par, PM3VideoControl, video);
-	}
-	PM3_WRITE_REG(par, PM3VClkCtl,
-			   (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
-	PM3_WRITE_REG(par, PM3ScreenBase, par->base);
-	PM3_WRITE_REG(par, PM3ChipConfig,
-			   (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
-
-	wmb();
-	{
-		unsigned char uninitialized_var(m);	/* ClkPreScale */
-		unsigned char uninitialized_var(n);	/* ClkFeedBackScale */
-		unsigned char uninitialized_var(p);	/* ClkPostScale */
-		unsigned long pixclock = PICOS2KHZ(info->var.pixclock);
-
-		(void)pm3fb_calculate_clock(pixclock, &m, &n, &p);
-
-		DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n",
-			pixclock, (int) m, (int) n, (int) p);
-
-		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m);
-		PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n);
-		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p);
-	}
-	/*
-	   PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00);
-	 */
-	/*
-	   PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00);
-	 */
-	if ((par->video & PM3VideoControl_HSYNC_MASK) ==
-	    PM3VideoControl_HSYNC_ACTIVE_HIGH)
-		tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
-	if ((par->video & PM3VideoControl_VSYNC_MASK) ==
-	    PM3VideoControl_VSYNC_ACTIVE_HIGH)
-		tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
-
-	PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync);
-	DPRINTK("PM3RD_SyncControl: %d\n", tempsync);
-
-	PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
-
-	switch (pm3fb_depth(&info->var)) {
-	case 8:
-		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
-				  PM3RD_PixelSize_8_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
-				  PM3RD_ColorFormat_CI8_COLOR |
-				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
-		tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-		break;
-	case 12:
-		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
-				  PM3RD_PixelSize_16_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
-				  PM3RD_ColorFormat_4444_COLOR |
-				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
-				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-		break;
-	case 15:
-		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
-				  PM3RD_PixelSize_16_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
-				  PM3RD_ColorFormat_5551_FRONT_COLOR |
-				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
-				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-		break;
-	case 16:
-		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
-				  PM3RD_PixelSize_16_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
-				  PM3RD_ColorFormat_565_FRONT_COLOR |
-				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
-				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-		break;
-	case 32:
-		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
-				  PM3RD_PixelSize_32_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
-				  PM3RD_ColorFormat_8888_COLOR |
-				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
-		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-		break;
-	}
-	PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc);
-}
-
-/*
- * hardware independent functions
- */
-static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	u32 lpitch;
-	unsigned bpp = var->red.length + var->green.length
-			+ var->blue.length + var->transp.length;
-
-	if (bpp != var->bits_per_pixel) {
-		/* set predefined mode for bits_per_pixel settings */
-
-		switch (var->bits_per_pixel) {
-		case 8:
-			var->red.length = 8;
-			var->green.length = 8;
-			var->blue.length = 8;
-			var->red.offset = 0;
-			var->green.offset = 0;
-			var->blue.offset = 0;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-			break;
-		case 16:
-			var->red.length = 5;
-			var->blue.length = 5;
-			var->green.length = 6;
-			var->transp.length = 0;
-			break;
-		case 32:
-			var->red.length = 8;
-			var->green.length = 8;
-			var->blue.length = 8;
-			var->transp.length = 8;
-			break;
-		default:
-			DPRINTK("depth not supported: %u\n",
-				var->bits_per_pixel);
-			return -EINVAL;
-		}
-	}
-	/* it is assumed BGRA order */
-	if (var->bits_per_pixel > 8 ) {
-		var->blue.offset = 0;
-		var->green.offset = var->blue.length;
-		var->red.offset = var->green.offset + var->green.length;
-		var->transp.offset = var->red.offset + var->red.length;
-	}
-	var->height = -1;
-	var->width = -1;
-
-	if (var->xres != var->xres_virtual) {
-		DPRINTK("virtual x resolution != "
-			"physical x resolution not supported\n");
-		return -EINVAL;
-	}
-
-	if (var->yres > var->yres_virtual) {
-		DPRINTK("virtual y resolution < "
-			"physical y resolution not possible\n");
-		return -EINVAL;
-	}
-
-	if (var->xoffset) {
-		DPRINTK("xoffset not supported\n");
-		return -EINVAL;
-	}
-
-	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-		DPRINTK("interlace not supported\n");
-		return -EINVAL;
-	}
-
-	var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */
-	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
-
-	if (var->xres < 200 || var->xres > 2048) {
-		DPRINTK("width not supported: %u\n", var->xres);
-		return -EINVAL;
-	}
-
-	if (var->yres < 200 || var->yres > 4095) {
-		DPRINTK("height not supported: %u\n", var->yres);
-		return -EINVAL;
-	}
-
-	if (lpitch * var->yres_virtual > info->fix.smem_len) {
-		DPRINTK("no memory for screen (%ux%ux%u)\n",
-			var->xres, var->yres_virtual, var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) {
-		DPRINTK("pixclock too high (%ldKHz)\n",
-			PICOS2KHZ(var->pixclock));
-		return -EINVAL;
-	}
-
-	var->accel_flags = 0;	/* Can't mmap if this is on */
-
-	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	return 0;
-}
-
-static int pm3fb_set_par(struct fb_info *info)
-{
-	struct pm3_par *par = info->par;
-	const u32 xres = (info->var.xres + 31) & ~31;
-	const unsigned bpp = info->var.bits_per_pixel;
-
-	par->base = pm3fb_shift_bpp(bpp, (info->var.yoffset * xres)
-					+ info->var.xoffset);
-	par->video = 0;
-
-	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;
-	else
-		par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW;
-
-	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;
-	else
-		par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW;
-
-	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
-		par->video |= PM3VideoControl_LINE_DOUBLE_ON;
-
-	if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
-		par->video |= PM3VideoControl_ENABLE;
-	else
-		DPRINTK("PM3Video disabled\n");
-
-	switch (bpp) {
-	case 8:
-		par->video |= PM3VideoControl_PIXELSIZE_8BIT;
-		break;
-	case 16:
-		par->video |= PM3VideoControl_PIXELSIZE_16BIT;
-		break;
-	case 32:
-		par->video |= PM3VideoControl_PIXELSIZE_32BIT;
-		break;
-	default:
-		DPRINTK("Unsupported depth\n");
-		break;
-	}
-
-	info->fix.visual =
-		(bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = ((info->var.xres_virtual + 7)  >> 3) * bpp;
-
-/*	pm3fb_clear_memory(info, 0);*/
-	pm3fb_clear_colormap(par, 0, 0, 0);
-	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, 0);
-	pm3fb_init_engine(info);
-	pm3fb_write_mode(info);
-	return 0;
-}
-
-static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct pm3_par *par = info->par;
-
-	if (regno >= 256)  /* no. of hw registers */
-	   return -EINVAL;
-
-	/* grayscale works only partially under directcolor */
-	/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-	if (info->var.grayscale)
-	   red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-
-	/* Directcolor:
-	 *   var->{color}.offset contains start of bitfield
-	 *   var->{color}.length contains length of bitfield
-	 *   {hardwarespecific} contains width of DAC
-	 *   pseudo_palette[X] is programmed to (X << red.offset) |
-	 *					(X << green.offset) |
-	 *					(X << blue.offset)
-	 *   RAMDAC[X] is programmed to (red, green, blue)
-	 *   color depth = SUM(var->{color}.length)
-	 *
-	 * Pseudocolor:
-	 *	var->{color}.offset is 0
-	 *	var->{color}.length contains width of DAC or the number
-	 *			of unique colors available (color depth)
-	 *	pseudo_palette is not used
-	 *	RAMDAC[X] is programmed to (red, green, blue)
-	 *	color depth = var->{color}.length
-	 */
-
-	/*
-	 * This is the point where the color is converted to something that
-	 * is acceptable by the hardware.
-	 */
-#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
-	red = CNVT_TOHW(red, info->var.red.length);
-	green = CNVT_TOHW(green, info->var.green.length);
-	blue = CNVT_TOHW(blue, info->var.blue.length);
-	transp = CNVT_TOHW(transp, info->var.transp.length);
-#undef CNVT_TOHW
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-	info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		u32 v;
-
-		if (regno >= 16)
-			return -EINVAL;
-
-		v = (red << info->var.red.offset) |
-			(green << info->var.green.offset) |
-			(blue << info->var.blue.offset) |
-			(transp << info->var.transp.offset);
-
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			break;
-		case 16:
-		case 32:
-			((u32 *)(info->pseudo_palette))[regno] = v;
-			break;
-		}
-		return 0;
-	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
-		pm3fb_set_color(par, regno, red, green, blue);
-
-	return 0;
-}
-
-static int pm3fb_pan_display(struct fb_var_screeninfo *var,
-				 struct fb_info *info)
-{
-	struct pm3_par *par = info->par;
-	const u32 xres = (info->var.xres + 31) & ~31;
-
-	par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
-					(var->yoffset * xres)
-					+ var->xoffset);
-	PM3_WAIT(par, 1);
-	PM3_WRITE_REG(par, PM3ScreenBase, par->base);
-	return 0;
-}
-
-static int pm3fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct pm3_par *par = info->par;
-	u32 video = par->video;
-
-	/*
-	 * Oxygen VX1 - it appears that setting PM3VideoControl and
-	 * then PM3RD_SyncControl to the same SYNC settings undoes
-	 * any net change - they seem to xor together.  Only set the
-	 * sync options in PM3RD_SyncControl.  --rmk
-	 */
-	video &= ~(PM3VideoControl_HSYNC_MASK |
-		   PM3VideoControl_VSYNC_MASK);
-	video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
-		 PM3VideoControl_VSYNC_ACTIVE_HIGH;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		video |= PM3VideoControl_ENABLE;
-		break;
-	case FB_BLANK_NORMAL:
-		video &= ~PM3VideoControl_ENABLE;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		video &= ~(PM3VideoControl_HSYNC_MASK |
-			  PM3VideoControl_BLANK_ACTIVE_LOW);
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		video &= ~(PM3VideoControl_VSYNC_MASK |
-			  PM3VideoControl_BLANK_ACTIVE_LOW);
-		break;
-	case FB_BLANK_POWERDOWN:
-		video &= ~(PM3VideoControl_HSYNC_MASK |
-			  PM3VideoControl_VSYNC_MASK |
-			  PM3VideoControl_BLANK_ACTIVE_LOW);
-		break;
-	default:
-		DPRINTK("Unsupported blanking %d\n", blank_mode);
-		return 1;
-	}
-
-	PM3_WAIT(par, 1);
-	PM3_WRITE_REG(par, PM3VideoControl, video);
-	return 0;
-}
-
-	/*
-	 *  Frame buffer operations
-	 */
-
-static struct fb_ops pm3fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= pm3fb_check_var,
-	.fb_set_par	= pm3fb_set_par,
-	.fb_setcolreg	= pm3fb_setcolreg,
-	.fb_pan_display	= pm3fb_pan_display,
-	.fb_fillrect	= pm3fb_fillrect,
-	.fb_copyarea	= pm3fb_copyarea,
-	.fb_imageblit	= pm3fb_imageblit,
-	.fb_blank	= pm3fb_blank,
-	.fb_sync	= pm3fb_sync,
-	.fb_cursor	= pm3fb_cursor,
-};
-
-/* ------------------------------------------------------------------------- */
-
-	/*
-	 *  Initialization
-	 */
-
-/* mmio register are already mapped when this function is called */
-/* the pm3fb_fix.smem_start is also set */
-static unsigned long pm3fb_size_memory(struct pm3_par *par)
-{
-	unsigned long	memsize = 0;
-	unsigned long	tempBypass, i, temp1, temp2;
-	unsigned char	__iomem *screen_mem;
-
-	pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */
-	/* Linear frame buffer - request region and map it. */
-	if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
-				 "pm3fb smem")) {
-		printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
-		return 0;
-	}
-	screen_mem =
-		ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
-	if (!screen_mem) {
-		printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
-		release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
-		return 0;
-	}
-
-	/* TODO: card-specific stuff, *before* accessing *any* FB memory */
-	/* For Appian Jeronimo 2000 board second head */
-
-	tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask);
-
-	DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
-
-	PM3_WAIT(par, 1);
-	PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
-
-	/* pm3 split up memory, replicates, and do a lot of
-	 * nasty stuff IMHO ;-)
-	 */
-	for (i = 0; i < 32; i++) {
-		fb_writel(i * 0x00345678,
-			  (screen_mem + (i * 1048576)));
-		mb();
-		temp1 = fb_readl((screen_mem + (i * 1048576)));
-
-		/* Let's check for wrapover, write will fail at 16MB boundary */
-		if (temp1 == (i * 0x00345678))
-			memsize = i;
-		else
-			break;
-	}
-
-	DPRINTK("First detect pass already got %ld MB\n", memsize + 1);
-
-	if (memsize + 1 == i) {
-		for (i = 0; i < 32; i++) {
-			/* Clear first 32MB ; 0 is 0, no need to byteswap */
-			writel(0x0000000, (screen_mem + (i * 1048576)));
-		}
-		wmb();
-
-		for (i = 32; i < 64; i++) {
-			fb_writel(i * 0x00345678,
-				  (screen_mem + (i * 1048576)));
-			mb();
-			temp1 =
-			    fb_readl((screen_mem + (i * 1048576)));
-			temp2 =
-			    fb_readl((screen_mem + ((i - 32) * 1048576)));
-			/* different value, different RAM... */
-			if ((temp1 == (i * 0x00345678)) && (temp2 == 0))
-				memsize = i;
-			else
-				break;
-		}
-	}
-	DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
-
-	PM3_WAIT(par, 1);
-	PM3_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
-
-	iounmap(screen_mem);
-	release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
-	memsize = 1048576 * (memsize + 1);
-
-	DPRINTK("Returning 0x%08lx bytes\n", memsize);
-
-	return memsize;
-}
-
-static int pm3fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	struct fb_info *info;
-	struct pm3_par *par;
-	struct device *device = &dev->dev; /* for pci drivers */
-	int err;
-	int retval = -ENXIO;
-
-	err = pci_enable_device(dev);
-	if (err) {
-		printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err);
-		return err;
-	}
-	/*
-	 * Dynamically allocate info and par
-	 */
-	info = framebuffer_alloc(sizeof(struct pm3_par), device);
-
-	if (!info)
-		return -ENOMEM;
-	par = info->par;
-
-	/*
-	 * Here we set the screen_base to the virtual memory address
-	 * for the framebuffer.
-	 */
-	pm3fb_fix.mmio_start = pci_resource_start(dev, 0);
-	pm3fb_fix.mmio_len = PM3_REGS_SIZE;
-#if defined(__BIG_ENDIAN)
-	pm3fb_fix.mmio_start += PM3_REGS_SIZE;
-	DPRINTK("Adjusting register base for big-endian.\n");
-#endif
-
-	/* Registers - request region and map it. */
-	if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len,
-				 "pm3fb regbase")) {
-		printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n");
-		goto err_exit_neither;
-	}
-	par->v_regs =
-		ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
-	if (!par->v_regs) {
-		printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n",
-			pm3fb_fix.id);
-		release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
-		goto err_exit_neither;
-	}
-
-	/* Linear frame buffer - request region and map it. */
-	pm3fb_fix.smem_start = pci_resource_start(dev, 1);
-	pm3fb_fix.smem_len = pm3fb_size_memory(par);
-	if (!pm3fb_fix.smem_len) {
-		printk(KERN_WARNING "pm3fb: Can't find memory on board.\n");
-		goto err_exit_mmio;
-	}
-	if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
-				 "pm3fb smem")) {
-		printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
-		goto err_exit_mmio;
-	}
-	info->screen_base =
-		ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
-	if (!info->screen_base) {
-		printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
-		release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
-		goto err_exit_mmio;
-	}
-	info->screen_size = pm3fb_fix.smem_len;
-
-#ifdef CONFIG_MTRR
-	if (!nomtrr)
-		par->mtrr_handle = mtrr_add(pm3fb_fix.smem_start,
-						pm3fb_fix.smem_len,
-						MTRR_TYPE_WRCOMB, 1);
-#endif
-	info->fbops = &pm3fb_ops;
-
-	par->video = PM3_READ_REG(par, PM3VideoControl);
-
-	info->fix = pm3fb_fix;
-	info->pseudo_palette = par->palette;
-	info->flags = FBINFO_DEFAULT |
-			FBINFO_HWACCEL_XPAN |
-			FBINFO_HWACCEL_YPAN |
-			FBINFO_HWACCEL_COPYAREA |
-			FBINFO_HWACCEL_IMAGEBLIT |
-			FBINFO_HWACCEL_FILLRECT;
-
-	if (noaccel) {
-		printk(KERN_DEBUG "disabling acceleration\n");
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-	}
-	info->pixmap.addr = kmalloc(PM3_PIXMAP_SIZE, GFP_KERNEL);
-	if (!info->pixmap.addr) {
-		retval = -ENOMEM;
-		goto err_exit_pixmap;
-	}
-	info->pixmap.size = PM3_PIXMAP_SIZE;
-	info->pixmap.buf_align = 4;
-	info->pixmap.scan_align = 4;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-	/*
-	 * This should give a reasonable default video mode. The following is
-	 * done when we can set a video mode.
-	 */
-	if (!mode_option)
-		mode_option = "640x480@60";
-
-	retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
-
-	if (!retval || retval == 4) {
-		retval = -EINVAL;
-		goto err_exit_both;
-	}
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		retval = -ENOMEM;
-		goto err_exit_both;
-	}
-
-	/*
-	 * For drivers that can...
-	 */
-	pm3fb_check_var(&info->var, info);
-
-	if (register_framebuffer(info) < 0) {
-		retval = -EINVAL;
-		goto err_exit_all;
-	}
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	pci_set_drvdata(dev, info);
-	return 0;
-
- err_exit_all:
-	fb_dealloc_cmap(&info->cmap);
- err_exit_both:
-	kfree(info->pixmap.addr);
- err_exit_pixmap:
-	iounmap(info->screen_base);
-	release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
- err_exit_mmio:
-	iounmap(par->v_regs);
-	release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
- err_exit_neither:
-	framebuffer_release(info);
-	return retval;
-}
-
-	/*
-	 *  Cleanup
-	 */
-static void pm3fb_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-
-	if (info) {
-		struct fb_fix_screeninfo *fix = &info->fix;
-		struct pm3_par *par = info->par;
-
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr_handle >= 0)
-		mtrr_del(par->mtrr_handle, info->fix.smem_start,
-			 info->fix.smem_len);
-#endif /* CONFIG_MTRR */
-		iounmap(info->screen_base);
-		release_mem_region(fix->smem_start, fix->smem_len);
-		iounmap(par->v_regs);
-		release_mem_region(fix->mmio_start, fix->mmio_len);
-
-		kfree(info->pixmap.addr);
-		framebuffer_release(info);
-	}
-}
-
-static struct pci_device_id pm3fb_id_table[] = {
-	{ PCI_VENDOR_ID_3DLABS, 0x0a,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0, }
-};
-
-/* For PCI drivers */
-static struct pci_driver pm3fb_driver = {
-	.name =		"pm3fb",
-	.id_table =	pm3fb_id_table,
-	.probe =	pm3fb_probe,
-	.remove =	pm3fb_remove,
-};
-
-MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
-
-#ifndef MODULE
-	/*
-	 *  Setup
-	 */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-static int __init pm3fb_setup(char *options)
-{
-	char *this_opt;
-
-	/* Parse user specified options (`video=pm3fb:') */
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		else if (!strncmp(this_opt, "noaccel", 7))
-			noaccel = 1;
-		else if (!strncmp(this_opt, "hwcursor=", 9))
-			hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
-#ifdef CONFIG_MTRR
-		else if (!strncmp(this_opt, "nomtrr", 6))
-			nomtrr = 1;
-#endif
-		else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-#endif /* MODULE */
-
-static int __init pm3fb_init(void)
-{
-	/*
-	 *  For kernel boot options (in 'video=pm3fb:<options>' format)
-	 */
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("pm3fb", &option))
-		return -ENODEV;
-	pm3fb_setup(option);
-#endif
-
-	return pci_register_driver(&pm3fb_driver);
-}
-
-#ifdef MODULE
-static void __exit pm3fb_exit(void)
-{
-	pci_unregister_driver(&pm3fb_driver);
-}
-
-module_exit(pm3fb_exit);
-#endif
-module_init(pm3fb_init);
-
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
-module_param(noaccel, bool, 0);
-MODULE_PARM_DESC(noaccel, "Disable acceleration");
-module_param(hwcursor, int, 0644);
-MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
-			"(1=enable, 0=disable, default=1)");
-#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, 0);
-MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
-#endif
-
-MODULE_DESCRIPTION("Permedia3 framebuffer device driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
deleted file mode 100644
index 838424817de2..000000000000
--- a/drivers/video/pmag-aa-fb.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- *	linux/drivers/video/pmag-aa-fb.c
- *	Copyright 2002 Karsten Merker <merker@debian.org>
- *
- *	PMAG-AA TurboChannel framebuffer card support ... derived from
- *	pmag-ba-fb.c, which is Copyright (C) 1999, 2000, 2001 by
- *	Michael Engel <engel@unix-ag.org>, Karsten Merker <merker@debian.org>
- *	and Harald Koerfgen <hkoerfg@web.de>, which itself is derived from
- *	"HP300 Topcat framebuffer support (derived from macfb of all things)
- *	Phil Blundell <philb@gnu.org> 1998"
- *
- *	This file is subject to the terms and conditions of the GNU General
- *	Public License.  See the file COPYING in the main directory of this
- *	archive for more details.
- *
- *	2002-09-28  Karsten Merker <merker@linuxtag.org>
- *		Version 0.01: First try to get a PMAG-AA running.
- *
- *	2003-02-24  Thiemo Seufer  <seufer@csv.ica.uni-stuttgart.de>
- *		Version 0.02: Major code cleanup.
- *
- *	2003-09-21  Thiemo Seufer  <seufer@csv.ica.uni-stuttgart.de>
- *		Hardware cursor support.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-
-#include <asm/bootinfo.h>
-#include <asm/dec/machtype.h>
-#include <asm/dec/tc.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-
-#include "bt455.h"
-#include "bt431.h"
-
-/* Version information */
-#define DRIVER_VERSION "0.02"
-#define DRIVER_AUTHOR "Karsten Merker <merker@linuxtag.org>"
-#define DRIVER_DESCRIPTION "PMAG-AA Framebuffer Driver"
-
-/* Prototypes */
-static int aafb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-
-/*
- * Bt455 RAM DAC register base offset (rel. to TC slot base address).
- */
-#define PMAG_AA_BT455_OFFSET		0x100000
-
-/*
- * Bt431 cursor generator offset (rel. to TC slot base address).
- */
-#define PMAG_AA_BT431_OFFSET		0x180000
-
-/*
- * Begin of PMAG-AA framebuffer memory relative to TC slot address,
- * resolution is 1280x1024x1 (8 bits deep, but only LSB is used).
- */
-#define PMAG_AA_ONBOARD_FBMEM_OFFSET	0x200000
-
-struct aafb_cursor {
-	struct timer_list timer;
-	int enable;
-	int on;
-	int vbl_cnt;
-	int blink_rate;
-	u16 x, y, width, height;
-};
-
-#define CURSOR_TIMER_FREQ	(HZ / 50)
-#define CURSOR_BLINK_RATE	(20)
-#define CURSOR_DRAW_DELAY	(2)
-
-struct aafb_info {
-	struct fb_info info;
-	struct display disp;
-	struct aafb_cursor cursor;
-	struct bt455_regs *bt455;
-	struct bt431_regs *bt431;
-	unsigned long fb_start;
-	unsigned long fb_size;
-	unsigned long fb_line_length;
-};
-
-/*
- * Max 3 TURBOchannel slots -> max 3 PMAG-AA.
- */
-static struct aafb_info my_fb_info[3];
-
-static struct aafb_par {
-} current_par;
-
-static int currcon = -1;
-
-static void aafb_set_cursor(struct aafb_info *info, int on)
-{
-	struct aafb_cursor *c = &info->cursor;
-
-	if (on) {
-		bt431_position_cursor(info->bt431, c->x, c->y);
-		bt431_enable_cursor(info->bt431);
-	} else
-		bt431_erase_cursor(info->bt431);
-}
-
-static void aafbcon_cursor(struct display *disp, int mode, int x, int y)
-{
-	struct aafb_info *info = (struct aafb_info *)disp->fb_info;
-	struct aafb_cursor *c = &info->cursor;
-
-	x *= fontwidth(disp);
-	y *= fontheight(disp);
-
-	if (c->x == x && c->y == y && (mode == CM_ERASE) == !c->enable)
-		return;
-
-	c->enable = 0;
-	if (c->on)
-		aafb_set_cursor(info, 0);
-	c->x = x - disp->var.xoffset;
-	c->y = y - disp->var.yoffset;
-
-	switch (mode) {
-		case CM_ERASE:
-			c->on = 0;
-			break;
-		case CM_DRAW:
-		case CM_MOVE:
-			if (c->on)
-				aafb_set_cursor(info, c->on);
-			else
-				c->vbl_cnt = CURSOR_DRAW_DELAY;
-			c->enable = 1;
-			break;
-	}
-}
-
-static int aafbcon_set_font(struct display *disp, int width, int height)
-{
-	struct aafb_info *info = (struct aafb_info *)disp->fb_info;
-	struct aafb_cursor *c = &info->cursor;
-	u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info);
-
-	if (width > 64 || height > 64 || width < 0 || height < 0)
-		return -EINVAL;
-
-	c->height = height;
-	c->width = width;
-
-	bt431_set_font(info->bt431, fgc, width, height);
-
-	return 1;
-}
-
-static void aafb_cursor_timer_handler(unsigned long data)
-{
-	struct aafb_info *info = (struct aafb_info *)data;
-	struct aafb_cursor *c = &info->cursor;
-
-	if (!c->enable)
-		goto out;
-
-	if (c->vbl_cnt && --c->vbl_cnt == 0) {
-		c->on ^= 1;
-		aafb_set_cursor(info, c->on);
-		c->vbl_cnt = c->blink_rate;
-	}
-
-out:
-	c->timer.expires = jiffies + CURSOR_TIMER_FREQ;
-	add_timer(&c->timer);
-}
-
-static void __init aafb_cursor_init(struct aafb_info *info)
-{
-	struct aafb_cursor *c = &info->cursor;
-
-	c->enable = 1;
-	c->on = 1;
-	c->x = c->y = 0;
-	c->width = c->height = 0;
-	c->vbl_cnt = CURSOR_DRAW_DELAY;
-	c->blink_rate = CURSOR_BLINK_RATE;
-
-	init_timer(&c->timer);
-	c->timer.data = (unsigned long)info;
-	c->timer.function = aafb_cursor_timer_handler;
-	mod_timer(&c->timer, jiffies + CURSOR_TIMER_FREQ);
-}
-
-static void __exit aafb_cursor_exit(struct aafb_info *info)
-{
-	struct aafb_cursor *c = &info->cursor;
-
-	del_timer_sync(&c->timer);
-}
-
-static struct display_switch aafb_switch8 = {
-	.setup = fbcon_cfb8_setup,
-	.bmove = fbcon_cfb8_bmove,
-	.clear = fbcon_cfb8_clear,
-	.putc = fbcon_cfb8_putc,
-	.putcs = fbcon_cfb8_putcs,
-	.revc = fbcon_cfb8_revc,
-	.cursor = aafbcon_cursor,
-	.set_font = aafbcon_set_font,
-	.clear_margins = fbcon_cfb8_clear_margins,
-	.fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-
-static void aafb_get_par(struct aafb_par *par)
-{
-	*par = current_par;
-}
-
-static int aafb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			struct fb_info *info)
-{
-	struct aafb_info *ip = (struct aafb_info *)info;
-
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, "PMAG-AA");
-	fix->smem_start = ip->fb_start;
-	fix->smem_len = ip->fb_size;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->ypanstep = 1;
-	fix->ywrapstep = 1;
-	fix->visual = FB_VISUAL_MONO10;
-	fix->line_length = 1280;
-	fix->accel = FB_ACCEL_NONE;
-
-	return 0;
-}
-
-static void aafb_set_disp(struct display *disp, int con,
-			  struct aafb_info *info)
-{
-	struct fb_fix_screeninfo fix;
-
-	disp->fb_info = &info->info;
-	aafb_set_var(&disp->var, con, &info->info);
-	if (disp->conp && disp->conp->vc_sw && disp->conp->vc_sw->con_cursor)
-		disp->conp->vc_sw->con_cursor(disp->conp, CM_ERASE);
-	disp->dispsw = &aafb_switch8;
-	disp->dispsw_data = 0;
-
-	aafb_get_fix(&fix, con, &info->info);
-	disp->screen_base = (u8 *) fix.smem_start;
-	disp->visual = fix.visual;
-	disp->type = fix.type;
-	disp->type_aux = fix.type_aux;
-	disp->ypanstep = fix.ypanstep;
-	disp->ywrapstep = fix.ywrapstep;
-	disp->line_length = fix.line_length;
-	disp->next_line = 2048;
-	disp->can_soft_blank = 1;
-	disp->inverse = 0;
-	disp->scrollmode = SCROLL_YREDRAW;
-
-	aafbcon_set_font(disp, fontwidth(disp), fontheight(disp));
-}
-
-static int aafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	static u16 color[2] = {0x0000, 0x000f};
-	static struct fb_cmap aafb_cmap = {0, 2, color, color, color, NULL};
-
-	fb_copy_cmap(&aafb_cmap, cmap, kspc ? 0 : 2);
-	return 0;
-}
-
-static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	u16 color[2] = {0x0000, 0x000f};
-
-	if (cmap->start == 0
-	    && cmap->len == 2
-	    && memcmp(cmap->red, color, sizeof(color)) == 0
-	    && memcmp(cmap->green, color, sizeof(color)) == 0
-	    && memcmp(cmap->blue, color, sizeof(color)) == 0
-	    && cmap->transp == NULL)
-		return 0;
-	else
-		return -EINVAL;
-}
-
-static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg)
-{
-	/* TODO: Not yet implemented */
-	return -ENOIOCTLCMD;
-}
-
-static int aafb_switch(int con, struct fb_info *info)
-{
-	struct aafb_info *ip = (struct aafb_info *)info;
-	struct display *old = (currcon < 0) ? &ip->disp : (fb_display + currcon);
-	struct display *new = (con < 0) ? &ip->disp : (fb_display + con);
-
-	if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor)
-		old->conp->vc_sw->con_cursor(old->conp, CM_ERASE);
-
-	/* Set the current console. */
-	currcon = con;
-	aafb_set_disp(new, con, ip);
-
-	return 0;
-}
-
-static void aafb_encode_var(struct fb_var_screeninfo *var,
-			    struct aafb_par *par)
-{
-	var->xres = 1280;
-	var->yres = 1024;
-	var->xres_virtual = 2048;
-	var->yres_virtual = 1024;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->bits_per_pixel = 8;
-	var->grayscale = 1;
-	var->red.offset = 0;
-	var->red.length = 0;
-	var->red.msb_right = 0;
-	var->green.offset = 0;
-	var->green.length = 1;
-	var->green.msb_right = 0;
-	var->blue.offset = 0;
-	var->blue.length = 0;
-	var->blue.msb_right = 0;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-	var->nonstd = 0;
-	var->activate &= ~FB_ACTIVATE_MASK & FB_ACTIVATE_NOW;
-	var->accel_flags = 0;
-	var->sync = FB_SYNC_ON_GREEN;
-	var->vmode &= ~FB_VMODE_MASK & FB_VMODE_NONINTERLACED;
-}
-
-static int aafb_get_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
-{
-	if (con < 0) {
-		struct aafb_par par;
-
-		memset(var, 0, sizeof(struct fb_var_screeninfo));
-		aafb_get_par(&par);
-		aafb_encode_var(var, &par);
-	} else
-		*var = info->var;
-
-	return 0;
-}
-
-static int aafb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
-{
-	struct aafb_par par;
-
-	aafb_get_par(&par);
-	aafb_encode_var(var, &par);
-	info->var = *var;
-
-	return 0;
-}
-
-static int aafb_update_var(int con, struct fb_info *info)
-{
-	struct aafb_info *ip = (struct aafb_info *)info;
-	struct display *disp = (con < 0) ? &ip->disp : (fb_display + con);
-
-	if (con == currcon)
-		aafbcon_cursor(disp, CM_ERASE, ip->cursor.x, ip->cursor.y);
-
-	return 0;
-}
-
-/* 0 unblanks, any other blanks. */
-
-static void aafb_blank(int blank, struct fb_info *info)
-{
-	struct aafb_info *ip = (struct aafb_info *)info;
-	u8 val = blank ? 0x00 : 0x0f;
-
-	bt455_write_cmap_entry(ip->bt455, 1, val, val, val);
-	aafbcon_cursor(&ip->disp, CM_ERASE, ip->cursor.x, ip->cursor.y);
-}
-
-static struct fb_ops aafb_ops = {
-	.owner = THIS_MODULE,
-	.fb_get_fix = aafb_get_fix,
-	.fb_get_var = aafb_get_var,
-	.fb_set_var = aafb_set_var,
-	.fb_get_cmap = aafb_get_cmap,
-	.fb_set_cmap = aafb_set_cmap,
-	.fb_ioctl = aafb_ioctl
-};
-
-static int __init init_one(int slot)
-{
-	unsigned long base_addr = CKSEG1ADDR(get_tc_base_addr(slot));
-	struct aafb_info *ip = &my_fb_info[slot];
-
-	memset(ip, 0, sizeof(struct aafb_info));
-
-	/*
-	 * Framebuffer display memory base address and friends.
-	 */
-	ip->bt455 = (struct bt455_regs *) (base_addr + PMAG_AA_BT455_OFFSET);
-	ip->bt431 = (struct bt431_regs *) (base_addr + PMAG_AA_BT431_OFFSET);
-	ip->fb_start = base_addr + PMAG_AA_ONBOARD_FBMEM_OFFSET;
-	ip->fb_size = 2048 * 1024; /* fb_fix_screeninfo.smem_length
-				      seems to be physical */
-	ip->fb_line_length = 2048;
-
-	/*
-	 * Let there be consoles..
-	 */
-	strcpy(ip->info.modename, "PMAG-AA");
-	ip->info.node = -1;
-	ip->info.flags = FBINFO_FLAG_DEFAULT;
-	ip->info.fbops = &aafb_ops;
-	ip->info.disp = &ip->disp;
-	ip->info.changevar = NULL;
-	ip->info.switch_con = &aafb_switch;
-	ip->info.updatevar = &aafb_update_var;
-	ip->info.blank = &aafb_blank;
-
-	aafb_set_disp(&ip->disp, currcon, ip);
-
-	/*
-	 * Configure the RAM DACs.
-	 */
-	bt455_erase_cursor(ip->bt455);
-
-	/* Init colormap. */
-	bt455_write_cmap_entry(ip->bt455, 0, 0x00, 0x00, 0x00);
-	bt455_write_cmap_entry(ip->bt455, 1, 0x0f, 0x0f, 0x0f);
-
-	/* Init hardware cursor. */
-	bt431_init_cursor(ip->bt431);
-	aafb_cursor_init(ip);
-
-	/* Clear the screen. */
-	memset ((void *)ip->fb_start, 0, ip->fb_size);
-
-	if (register_framebuffer(&ip->info) < 0)
-		return -EINVAL;
-
-	printk(KERN_INFO "fb%d: %s frame buffer in TC slot %d\n",
-	       GET_FB_IDX(ip->info.node), ip->info.modename, slot);
-
-	return 0;
-}
-
-static int __exit exit_one(int slot)
-{
-	struct aafb_info *ip = &my_fb_info[slot];
-
-	if (unregister_framebuffer(&ip->info) < 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-/*
- * Initialise the framebuffer.
- */
-int __init pmagaafb_init(void)
-{
-	int sid;
-	int found = 0;
-
-	while ((sid = search_tc_card("PMAG-AA")) >= 0) {
-		found = 1;
-		claim_tc_card(sid);
-		init_one(sid);
-	}
-
-	return found ? 0 : -ENXIO;
-}
-
-static void __exit pmagaafb_exit(void)
-{
-	int sid;
-
-	while ((sid = search_tc_card("PMAG-AA")) >= 0) {
-		exit_one(sid);
-		release_tc_card(sid);
-	}
-}
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
-MODULE_LICENSE("GPL");
-#ifdef MODULE
-module_init(pmagaafb_init);
-module_exit(pmagaafb_exit);
-#endif
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
deleted file mode 100644
index 914a52ba8477..000000000000
--- a/drivers/video/pmag-ba-fb.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- *	linux/drivers/video/pmag-ba-fb.c
- *
- *	PMAG-BA TURBOchannel Color Frame Buffer (CFB) card support,
- *	derived from:
- *	"HP300 Topcat framebuffer support (derived from macfb of all things)
- *	Phil Blundell <philb@gnu.org> 1998", the original code can be
- *	found in the file hpfb.c in the same directory.
- *
- *	Based on digital document:
- * 	"PMAG-BA TURBOchannel Color Frame Buffer
- *	 Functional Specification", Revision 1.2, August 27, 1990
- *
- *	DECstation related code Copyright (C) 1999, 2000, 2001 by
- *	Michael Engel <engel@unix-ag.org>,
- *	Karsten Merker <merker@linuxtag.org> and
- *	Harald Koerfgen.
- *	Copyright (c) 2005, 2006  Maciej W. Rozycki
- *	Copyright (c) 2005  James Simmons
- *
- *	This file is subject to the terms and conditions of the GNU General
- *	Public License.  See the file COPYING in the main directory of this
- *	archive for more details.
- */
-
-#include <linux/compiler.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/tc.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-
-#include <video/pmag-ba-fb.h>
-
-
-struct pmagbafb_par {
-	volatile void __iomem *mmio;
-	volatile u32 __iomem *dac;
-};
-
-
-static struct fb_var_screeninfo pmagbafb_defined = {
-	.xres		= 1024,
-	.yres		= 864,
-	.xres_virtual	= 1024,
-	.yres_virtual	= 864,
-	.bits_per_pixel	= 8,
-	.red.length	= 8,
-	.green.length	= 8,
-	.blue.length	= 8,
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= FB_ACCEL_NONE,
-	.pixclock	= 14452,
-	.left_margin	= 116,
-	.right_margin	= 12,
-	.upper_margin	= 34,
-	.lower_margin	= 12,
-	.hsync_len	= 128,
-	.vsync_len	= 3,
-	.sync		= FB_SYNC_ON_GREEN,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo pmagbafb_fix = {
-	.id		= "PMAG-BA",
-	.smem_len	= (1024 * 1024),
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_PSEUDOCOLOR,
-	.line_length	= 1024,
-	.mmio_len	= PMAG_BA_SIZE - PMAG_BA_BT459,
-};
-
-
-static inline void dac_write(struct pmagbafb_par *par, unsigned int reg, u8 v)
-{
-	writeb(v, par->dac + reg / 4);
-}
-
-static inline u8 dac_read(struct pmagbafb_par *par, unsigned int reg)
-{
-	return readb(par->dac + reg / 4);
-}
-
-
-/*
- * Set the palette.
- */
-static int pmagbafb_setcolreg(unsigned int regno, unsigned int red,
-			      unsigned int green, unsigned int blue,
-			      unsigned int transp, struct fb_info *info)
-{
-	struct pmagbafb_par *par = info->par;
-
-	if (regno >= info->cmap.len)
-		return 1;
-
-	red   >>= 8;	/* The cmap fields are 16 bits    */
-	green >>= 8;	/* wide, but the hardware colormap */
-	blue  >>= 8;	/* registers are only 8 bits wide */
-
-	mb();
-	dac_write(par, BT459_ADDR_LO, regno);
-	dac_write(par, BT459_ADDR_HI, 0x00);
-	wmb();
-	dac_write(par, BT459_CMAP, red);
-	wmb();
-	dac_write(par, BT459_CMAP, green);
-	wmb();
-	dac_write(par, BT459_CMAP, blue);
-
-	return 0;
-}
-
-static struct fb_ops pmagbafb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= pmagbafb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-
-/*
- * Turn the hardware cursor off.
- */
-static void __init pmagbafb_erase_cursor(struct fb_info *info)
-{
-	struct pmagbafb_par *par = info->par;
-
-	mb();
-	dac_write(par, BT459_ADDR_LO, 0x00);
-	dac_write(par, BT459_ADDR_HI, 0x03);
-	wmb();
-	dac_write(par, BT459_DATA, 0x00);
-}
-
-
-static int pmagbafb_probe(struct device *dev)
-{
-	struct tc_dev *tdev = to_tc_dev(dev);
-	resource_size_t start, len;
-	struct fb_info *info;
-	struct pmagbafb_par *par;
-	int err;
-
-	info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev);
-	if (!info) {
-		printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev));
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	dev_set_drvdata(dev, info);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		printk(KERN_ERR "%s: Cannot allocate color map\n",
-		       dev_name(dev));
-		err = -ENOMEM;
-		goto err_alloc;
-	}
-
-	info->fbops = &pmagbafb_ops;
-	info->fix = pmagbafb_fix;
-	info->var = pmagbafb_defined;
-	info->flags = FBINFO_DEFAULT;
-
-	/* Request the I/O MEM resource.  */
-	start = tdev->resource.start;
-	len = tdev->resource.end - start + 1;
-	if (!request_mem_region(start, len, dev_name(dev))) {
-		printk(KERN_ERR "%s: Cannot reserve FB region\n",
-		       dev_name(dev));
-		err = -EBUSY;
-		goto err_cmap;
-	}
-
-	/* MMIO mapping setup.  */
-	info->fix.mmio_start = start;
-	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
-	if (!par->mmio) {
-		printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
-		err = -ENOMEM;
-		goto err_resource;
-	}
-	par->dac = par->mmio + PMAG_BA_BT459;
-
-	/* Frame buffer mapping setup.  */
-	info->fix.smem_start = start + PMAG_BA_FBMEM;
-	info->screen_base = ioremap_nocache(info->fix.smem_start,
-					    info->fix.smem_len);
-	if (!info->screen_base) {
-		printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
-		err = -ENOMEM;
-		goto err_mmio_map;
-	}
-	info->screen_size = info->fix.smem_len;
-
-	pmagbafb_erase_cursor(info);
-
-	err = register_framebuffer(info);
-	if (err < 0) {
-		printk(KERN_ERR "%s: Cannot register framebuffer\n",
-		       dev_name(dev));
-		goto err_smem_map;
-	}
-
-	get_device(dev);
-
-	fb_info(info, "%s frame buffer device at %s\n",
-		info->fix.id, dev_name(dev));
-
-	return 0;
-
-
-err_smem_map:
-	iounmap(info->screen_base);
-
-err_mmio_map:
-	iounmap(par->mmio);
-
-err_resource:
-	release_mem_region(start, len);
-
-err_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-err_alloc:
-	framebuffer_release(info);
-	return err;
-}
-
-static int __exit pmagbafb_remove(struct device *dev)
-{
-	struct tc_dev *tdev = to_tc_dev(dev);
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct pmagbafb_par *par = info->par;
-	resource_size_t start, len;
-
-	put_device(dev);
-	unregister_framebuffer(info);
-	iounmap(info->screen_base);
-	iounmap(par->mmio);
-	start = tdev->resource.start;
-	len = tdev->resource.end - start + 1;
-	release_mem_region(start, len);
-	fb_dealloc_cmap(&info->cmap);
-	framebuffer_release(info);
-	return 0;
-}
-
-
-/*
- * Initialize the framebuffer.
- */
-static const struct tc_device_id pmagbafb_tc_table[] = {
-	{ "DEC     ", "PMAG-BA " },
-	{ }
-};
-MODULE_DEVICE_TABLE(tc, pmagbafb_tc_table);
-
-static struct tc_driver pmagbafb_driver = {
-	.id_table	= pmagbafb_tc_table,
-	.driver		= {
-		.name	= "pmagbafb",
-		.bus	= &tc_bus_type,
-		.probe	= pmagbafb_probe,
-		.remove	= __exit_p(pmagbafb_remove),
-	},
-};
-
-static int __init pmagbafb_init(void)
-{
-#ifndef MODULE
-	if (fb_get_options("pmagbafb", NULL))
-		return -ENXIO;
-#endif
-	return tc_register_driver(&pmagbafb_driver);
-}
-
-static void __exit pmagbafb_exit(void)
-{
-	tc_unregister_driver(&pmagbafb_driver);
-}
-
-
-module_init(pmagbafb_init);
-module_exit(pmagbafb_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
deleted file mode 100644
index 0822b6f8dddc..000000000000
--- a/drivers/video/pmagb-b-fb.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- *	linux/drivers/video/pmagb-b-fb.c
- *
- *	PMAGB-B TURBOchannel Smart Frame Buffer (SFB) card support,
- *	derived from:
- *	"HP300 Topcat framebuffer support (derived from macfb of all things)
- *	Phil Blundell <philb@gnu.org> 1998", the original code can be
- *	found in the file hpfb.c in the same directory.
- *
- *	DECstation related code Copyright (C) 1999, 2000, 2001 by
- *	Michael Engel <engel@unix-ag.org>,
- *	Karsten Merker <merker@linuxtag.org> and
- *	Harald Koerfgen.
- *	Copyright (c) 2005, 2006  Maciej W. Rozycki
- *
- *	This file is subject to the terms and conditions of the GNU General
- *	Public License.  See the file COPYING in the main directory of this
- *	archive for more details.
- */
-
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/tc.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-
-#include <video/pmagb-b-fb.h>
-
-
-struct pmagbbfb_par {
-	volatile void __iomem *mmio;
-	volatile void __iomem *smem;
-	volatile u32 __iomem *sfb;
-	volatile u32 __iomem *dac;
-	unsigned int osc0;
-	unsigned int osc1;
-	int slot;
-};
-
-
-static struct fb_var_screeninfo pmagbbfb_defined = {
-	.bits_per_pixel	= 8,
-	.red.length	= 8,
-	.green.length	= 8,
-	.blue.length	= 8,
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.accel_flags	= FB_ACCEL_NONE,
-	.sync		= FB_SYNC_ON_GREEN,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo pmagbbfb_fix = {
-	.id		= "PMAGB-BA",
-	.smem_len	= (2048 * 1024),
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_PSEUDOCOLOR,
-	.mmio_len	= PMAGB_B_FBMEM,
-};
-
-
-static inline void sfb_write(struct pmagbbfb_par *par, unsigned int reg, u32 v)
-{
-	writel(v, par->sfb + reg / 4);
-}
-
-static inline u32 sfb_read(struct pmagbbfb_par *par, unsigned int reg)
-{
-	return readl(par->sfb + reg / 4);
-}
-
-static inline void dac_write(struct pmagbbfb_par *par, unsigned int reg, u8 v)
-{
-	writeb(v, par->dac + reg / 4);
-}
-
-static inline u8 dac_read(struct pmagbbfb_par *par, unsigned int reg)
-{
-	return readb(par->dac + reg / 4);
-}
-
-static inline void gp0_write(struct pmagbbfb_par *par, u32 v)
-{
-	writel(v, par->mmio + PMAGB_B_GP0);
-}
-
-
-/*
- * Set the palette.
- */
-static int pmagbbfb_setcolreg(unsigned int regno, unsigned int red,
-			      unsigned int green, unsigned int blue,
-			      unsigned int transp, struct fb_info *info)
-{
-	struct pmagbbfb_par *par = info->par;
-
-	if (regno >= info->cmap.len)
-		return 1;
-
-	red   >>= 8;	/* The cmap fields are 16 bits    */
-	green >>= 8;	/* wide, but the hardware colormap */
-	blue  >>= 8;	/* registers are only 8 bits wide */
-
-	mb();
-	dac_write(par, BT459_ADDR_LO, regno);
-	dac_write(par, BT459_ADDR_HI, 0x00);
-	wmb();
-	dac_write(par, BT459_CMAP, red);
-	wmb();
-	dac_write(par, BT459_CMAP, green);
-	wmb();
-	dac_write(par, BT459_CMAP, blue);
-
-	return 0;
-}
-
-static struct fb_ops pmagbbfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= pmagbbfb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-
-/*
- * Turn the hardware cursor off.
- */
-static void __init pmagbbfb_erase_cursor(struct fb_info *info)
-{
-	struct pmagbbfb_par *par = info->par;
-
-	mb();
-	dac_write(par, BT459_ADDR_LO, 0x00);
-	dac_write(par, BT459_ADDR_HI, 0x03);
-	wmb();
-	dac_write(par, BT459_DATA, 0x00);
-}
-
-/*
- * Set up screen parameters.
- */
-static void pmagbbfb_screen_setup(struct fb_info *info)
-{
-	struct pmagbbfb_par *par = info->par;
-
-	info->var.xres = ((sfb_read(par, SFB_REG_VID_HOR) >>
-			   SFB_VID_HOR_PIX_SHIFT) & SFB_VID_HOR_PIX_MASK) * 4;
-	info->var.xres_virtual = info->var.xres;
-	info->var.yres = (sfb_read(par, SFB_REG_VID_VER) >>
-			  SFB_VID_VER_SL_SHIFT) & SFB_VID_VER_SL_MASK;
-	info->var.yres_virtual = info->var.yres;
-	info->var.left_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
-				  SFB_VID_HOR_BP_SHIFT) &
-				 SFB_VID_HOR_BP_MASK) * 4;
-	info->var.right_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
-				   SFB_VID_HOR_FP_SHIFT) &
-				  SFB_VID_HOR_FP_MASK) * 4;
-	info->var.upper_margin = (sfb_read(par, SFB_REG_VID_VER) >>
-				  SFB_VID_VER_BP_SHIFT) & SFB_VID_VER_BP_MASK;
-	info->var.lower_margin = (sfb_read(par, SFB_REG_VID_VER) >>
-				  SFB_VID_VER_FP_SHIFT) & SFB_VID_VER_FP_MASK;
-	info->var.hsync_len = ((sfb_read(par, SFB_REG_VID_HOR) >>
-				SFB_VID_HOR_SYN_SHIFT) &
-			       SFB_VID_HOR_SYN_MASK) * 4;
-	info->var.vsync_len = (sfb_read(par, SFB_REG_VID_VER) >>
-			       SFB_VID_VER_SYN_SHIFT) & SFB_VID_VER_SYN_MASK;
-
-	info->fix.line_length = info->var.xres;
-};
-
-/*
- * Determine oscillator configuration.
- */
-static void pmagbbfb_osc_setup(struct fb_info *info)
-{
-	static unsigned int pmagbbfb_freqs[] = {
-		130808, 119843, 104000, 92980, 74370, 72800,
-		69197, 66000, 65000, 50350, 36000, 32000, 25175
-	};
-	struct pmagbbfb_par *par = info->par;
-	struct tc_bus *tbus = to_tc_dev(info->device)->bus;
-	u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8;
-	u32 freq0, freq1, freqtc = tc_get_speed(tbus) / 250;
-	int i, j;
-
-	gp0_write(par, 0);				/* select Osc0 */
-	for (j = 0; j < 16; j++) {
-		mb();
-		sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
-		mb();
-		for (i = 0; i < 100; i++) {	/* nominally max. 20.5us */
-			if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
-				break;
-			udelay(1);
-		}
-		count0 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
-	}
-
-	gp0_write(par, 1);				/* select Osc1 */
-	for (j = 0; j < 16; j++) {
-		mb();
-		sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
-
-		for (i = 0; i < 100; i++) {	/* nominally max. 20.5us */
-			if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
-				break;
-			udelay(1);
-		}
-		count1 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
-	}
-
-	freq0 = (freqtc * count0 + counttc / 2) / counttc;
-	par->osc0 = freq0;
-	if (freq0 >= pmagbbfb_freqs[0] - (pmagbbfb_freqs[0] + 32) / 64 &&
-	    freq0 <= pmagbbfb_freqs[0] + (pmagbbfb_freqs[0] + 32) / 64)
-		par->osc0 = pmagbbfb_freqs[0];
-
-	freq1 = (par->osc0 * count1 + count0 / 2) / count0;
-	par->osc1 = freq1;
-	for (i = 0; i < ARRAY_SIZE(pmagbbfb_freqs); i++)
-		if (freq1 >= pmagbbfb_freqs[i] -
-			     (pmagbbfb_freqs[i] + 128) / 256 &&
-		    freq1 <= pmagbbfb_freqs[i] +
-			     (pmagbbfb_freqs[i] + 128) / 256) {
-			par->osc1 = pmagbbfb_freqs[i];
-			break;
-		}
-
-	if (par->osc0 - par->osc1 <= (par->osc0 + par->osc1 + 256) / 512 ||
-	    par->osc1 - par->osc0 <= (par->osc0 + par->osc1 + 256) / 512)
-		par->osc1 = 0;
-
-	gp0_write(par, par->osc1 != 0);			/* reselect OscX */
-
-	info->var.pixclock = par->osc1 ?
-			     (1000000000 + par->osc1 / 2) / par->osc1 :
-			     (1000000000 + par->osc0 / 2) / par->osc0;
-};
-
-
-static int pmagbbfb_probe(struct device *dev)
-{
-	struct tc_dev *tdev = to_tc_dev(dev);
-	resource_size_t start, len;
-	struct fb_info *info;
-	struct pmagbbfb_par *par;
-	char freq0[12], freq1[12];
-	u32 vid_base;
-	int err;
-
-	info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev);
-	if (!info) {
-		printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev));
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	dev_set_drvdata(dev, info);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		printk(KERN_ERR "%s: Cannot allocate color map\n",
-		       dev_name(dev));
-		err = -ENOMEM;
-		goto err_alloc;
-	}
-
-	info->fbops = &pmagbbfb_ops;
-	info->fix = pmagbbfb_fix;
-	info->var = pmagbbfb_defined;
-	info->flags = FBINFO_DEFAULT;
-
-	/* Request the I/O MEM resource.  */
-	start = tdev->resource.start;
-	len = tdev->resource.end - start + 1;
-	if (!request_mem_region(start, len, dev_name(dev))) {
-		printk(KERN_ERR "%s: Cannot reserve FB region\n",
-		       dev_name(dev));
-		err = -EBUSY;
-		goto err_cmap;
-	}
-
-	/* MMIO mapping setup.  */
-	info->fix.mmio_start = start;
-	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
-	if (!par->mmio) {
-		printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
-		err = -ENOMEM;
-		goto err_resource;
-	}
-	par->sfb = par->mmio + PMAGB_B_SFB;
-	par->dac = par->mmio + PMAGB_B_BT459;
-
-	/* Frame buffer mapping setup.  */
-	info->fix.smem_start = start + PMAGB_B_FBMEM;
-	par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
-	if (!par->smem) {
-		printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
-		err = -ENOMEM;
-		goto err_mmio_map;
-	}
-	vid_base = sfb_read(par, SFB_REG_VID_BASE);
-	info->screen_base = (void __iomem *)par->smem + vid_base * 0x1000;
-	info->screen_size = info->fix.smem_len - 2 * vid_base * 0x1000;
-
-	pmagbbfb_erase_cursor(info);
-	pmagbbfb_screen_setup(info);
-	pmagbbfb_osc_setup(info);
-
-	err = register_framebuffer(info);
-	if (err < 0) {
-		printk(KERN_ERR "%s: Cannot register framebuffer\n",
-		       dev_name(dev));
-		goto err_smem_map;
-	}
-
-	get_device(dev);
-
-	snprintf(freq0, sizeof(freq0), "%u.%03uMHz",
-		 par->osc0 / 1000, par->osc0 % 1000);
-	snprintf(freq1, sizeof(freq1), "%u.%03uMHz",
-		 par->osc1 / 1000, par->osc1 % 1000);
-
-	fb_info(info, "%s frame buffer device at %s\n",
-		info->fix.id, dev_name(dev));
-	fb_info(info, "Osc0: %s, Osc1: %s, Osc%u selected\n",
-		freq0, par->osc1 ? freq1 : "disabled", par->osc1 != 0);
-
-	return 0;
-
-
-err_smem_map:
-	iounmap(par->smem);
-
-err_mmio_map:
-	iounmap(par->mmio);
-
-err_resource:
-	release_mem_region(start, len);
-
-err_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-err_alloc:
-	framebuffer_release(info);
-	return err;
-}
-
-static int __exit pmagbbfb_remove(struct device *dev)
-{
-	struct tc_dev *tdev = to_tc_dev(dev);
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct pmagbbfb_par *par = info->par;
-	resource_size_t start, len;
-
-	put_device(dev);
-	unregister_framebuffer(info);
-	iounmap(par->smem);
-	iounmap(par->mmio);
-	start = tdev->resource.start;
-	len = tdev->resource.end - start + 1;
-	release_mem_region(start, len);
-	fb_dealloc_cmap(&info->cmap);
-	framebuffer_release(info);
-	return 0;
-}
-
-
-/*
- * Initialize the framebuffer.
- */
-static const struct tc_device_id pmagbbfb_tc_table[] = {
-	{ "DEC     ", "PMAGB-BA" },
-	{ }
-};
-MODULE_DEVICE_TABLE(tc, pmagbbfb_tc_table);
-
-static struct tc_driver pmagbbfb_driver = {
-	.id_table	= pmagbbfb_tc_table,
-	.driver		= {
-		.name	= "pmagbbfb",
-		.bus	= &tc_bus_type,
-		.probe	= pmagbbfb_probe,
-		.remove	= __exit_p(pmagbbfb_remove),
-	},
-};
-
-static int __init pmagbbfb_init(void)
-{
-#ifndef MODULE
-	if (fb_get_options("pmagbbfb", NULL))
-		return -ENXIO;
-#endif
-	return tc_register_driver(&pmagbbfb_driver);
-}
-
-static void __exit pmagbbfb_exit(void)
-{
-	tc_unregister_driver(&pmagbbfb_driver);
-}
-
-
-module_init(pmagbbfb_init);
-module_exit(pmagbbfb_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
deleted file mode 100644
index b269abd932aa..000000000000
--- a/drivers/video/ps3fb.c
+++ /dev/null
@@ -1,1307 +0,0 @@
-/*
- *  linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
- *
- *	Copyright (C) 2006 Sony Computer Entertainment Inc.
- *	Copyright 2006, 2007 Sony Corporation
- *
- *  This file is based on :
- *
- *  linux/drivers/video/vfb.c -- Virtual frame buffer device
- *
- *	Copyright (C) 2002 James Simmons
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/console.h>
-#include <linux/ioctl.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/uaccess.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-
-#include <asm/cell-regs.h>
-#include <asm/lv1call.h>
-#include <asm/ps3av.h>
-#include <asm/ps3fb.h>
-#include <asm/ps3.h>
-#include <asm/ps3gpu.h>
-
-
-#define DEVICE_NAME		"ps3fb"
-
-#define GPU_CMD_BUF_SIZE			(2 * 1024 * 1024)
-#define GPU_FB_START				(64 * 1024)
-#define GPU_IOIF				(0x0d000000UL)
-#define GPU_ALIGN_UP(x)				_ALIGN_UP((x), 64)
-#define GPU_MAX_LINE_LENGTH			(65536 - 64)
-
-#define GPU_INTR_STATUS_VSYNC_0			0	/* vsync on head A */
-#define GPU_INTR_STATUS_VSYNC_1			1	/* vsync on head B */
-#define GPU_INTR_STATUS_FLIP_0			3	/* flip head A */
-#define GPU_INTR_STATUS_FLIP_1			4	/* flip head B */
-#define GPU_INTR_STATUS_QUEUE_0			5	/* queue head A */
-#define GPU_INTR_STATUS_QUEUE_1			6	/* queue head B */
-
-#define GPU_DRIVER_INFO_VERSION			0x211
-
-/* gpu internals */
-struct display_head {
-	u64 be_time_stamp;
-	u32 status;
-	u32 offset;
-	u32 res1;
-	u32 res2;
-	u32 field;
-	u32 reserved1;
-
-	u64 res3;
-	u32 raster;
-
-	u64 vblank_count;
-	u32 field_vsync;
-	u32 reserved2;
-};
-
-struct gpu_irq {
-	u32 irq_outlet;
-	u32 status;
-	u32 mask;
-	u32 video_cause;
-	u32 graph_cause;
-	u32 user_cause;
-
-	u32 res1;
-	u64 res2;
-
-	u32 reserved[4];
-};
-
-struct gpu_driver_info {
-	u32 version_driver;
-	u32 version_gpu;
-	u32 memory_size;
-	u32 hardware_channel;
-
-	u32 nvcore_frequency;
-	u32 memory_frequency;
-
-	u32 reserved[1063];
-	struct display_head display_head[8];
-	struct gpu_irq irq;
-};
-
-struct ps3fb_priv {
-	unsigned int irq_no;
-
-	u64 context_handle, memory_handle;
-	struct gpu_driver_info *dinfo;
-
-	u64 vblank_count;	/* frame count */
-	wait_queue_head_t wait_vsync;
-
-	atomic_t ext_flip;	/* on/off flip with vsync */
-	atomic_t f_count;	/* fb_open count */
-	int is_blanked;
-	int is_kicked;
-	struct task_struct *task;
-};
-static struct ps3fb_priv ps3fb;
-
-struct ps3fb_par {
-	u32 pseudo_palette[16];
-	int mode_id, new_mode_id;
-	unsigned int num_frames;	/* num of frame buffers */
-	unsigned int width;
-	unsigned int height;
-	unsigned int ddr_line_length;
-	unsigned int ddr_frame_size;
-	unsigned int xdr_frame_size;
-	unsigned int full_offset;	/* start of fullscreen DDR fb */
-	unsigned int fb_offset;		/* start of actual DDR fb */
-	unsigned int pan_offset;
-};
-
-
-#define FIRST_NATIVE_MODE_INDEX	10
-
-static const struct fb_videomode ps3fb_modedb[] = {
-    /* 60 Hz broadcast modes (modes "1" to "5") */
-    {
-        /* 480i */
-        "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
-        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    },    {
-        /* 480p */
-        "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
-        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },    {
-        /* 720p */
-        "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },    {
-        /* 1080i */
-        "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    },    {
-        /* 1080p */
-        "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },
-
-    /* 50 Hz broadcast modes (modes "6" to "10") */
-    {
-        /* 576i */
-        "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    },    {
-        /* 576p */
-        "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },    {
-        /* 720p */
-        "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },    {
-        /* 1080i */
-        "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    },    {
-        /* 1080p */
-        "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
-        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },
-
-    [FIRST_NATIVE_MODE_INDEX] =
-    /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
-    {
-	/* 480if */
-	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
-	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    }, {
-	/* 480pf */
-	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
-	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    }, {
-	/* 720pf */
-	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1080if */
-	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    }, {
-	/* 1080pf */
-	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },
-
-    /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */
-    {
-	/* 576if */
-	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    }, {
-	/* 576pf */
-	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    }, {
-	/* 720pf */
-	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    }, {
-	/* 1080if */
-	"1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
-    }, {
-	/* 1080pf */
-	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
-	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
-    },
-
-    /* VESA modes (modes "11" to "13") */
-    {
-	/* WXGA */
-	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
-	0, FB_VMODE_NONINTERLACED,
-	FB_MODE_IS_VESA
-    }, {
-	/* SXGA */
-	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
-	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
-	FB_MODE_IS_VESA
-    }, {
-	/* WUXGA */
-	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
-	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
-	FB_MODE_IS_VESA
-    }
-};
-
-
-#define HEAD_A
-#define HEAD_B
-
-#define BPP		4			/* number of bytes per pixel */
-
-
-static int ps3fb_mode;
-module_param(ps3fb_mode, int, 0);
-
-static char *mode_option;
-
-static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
-			  const struct fb_var_screeninfo *var)
-{
-	long xres, yres, left_margin, right_margin, upper_margin, lower_margin;
-	long dx, dy;
-
-	/* maximum values */
-	if (var->xres > vmode->xres || var->yres > vmode->yres ||
-	    var->pixclock > vmode->pixclock ||
-	    var->hsync_len > vmode->hsync_len ||
-	    var->vsync_len > vmode->vsync_len)
-		return -1;
-
-	/* progressive/interlaced must match */
-	if ((var->vmode & FB_VMODE_MASK) != vmode->vmode)
-		return -1;
-
-	/* minimum resolution */
-	xres = max(var->xres, 1U);
-	yres = max(var->yres, 1U);
-
-	/* minimum margins */
-	left_margin = max(var->left_margin, vmode->left_margin);
-	right_margin = max(var->right_margin, vmode->right_margin);
-	upper_margin = max(var->upper_margin, vmode->upper_margin);
-	lower_margin = max(var->lower_margin, vmode->lower_margin);
-
-	/* resolution + margins may not exceed native parameters */
-	dx = ((long)vmode->left_margin + (long)vmode->xres +
-	      (long)vmode->right_margin) -
-	     (left_margin + xres + right_margin);
-	if (dx < 0)
-		return -1;
-
-	dy = ((long)vmode->upper_margin + (long)vmode->yres +
-	      (long)vmode->lower_margin) -
-	     (upper_margin + yres + lower_margin);
-	if (dy < 0)
-		return -1;
-
-	/* exact match */
-	if (!dx && !dy)
-		return 0;
-
-	/* resolution difference */
-	return (vmode->xres - xres) * (vmode->yres - yres);
-}
-
-static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id)
-{
-	return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1];
-}
-
-static const struct fb_videomode *ps3fb_vmode(int id)
-{
-	u32 mode = id & PS3AV_MODE_MASK;
-
-	if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA)
-		return NULL;
-
-	if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) {
-		/* Non-fullscreen broadcast mode */
-		return &ps3fb_modedb[mode - 1];
-	}
-
-	return ps3fb_native_vmode(mode);
-}
-
-static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var,
-				    u32 *ddr_line_length, u32 *xdr_line_length)
-{
-	unsigned int id, best_id;
-	int diff, best_diff;
-	const struct fb_videomode *vmode;
-	long gap;
-
-	best_id = 0;
-	best_diff = INT_MAX;
-	pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__,
-		 var->left_margin, var->xres, var->right_margin,
-		 var->upper_margin, var->yres, var->lower_margin);
-	for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) {
-		vmode = ps3fb_native_vmode(id);
-		diff = ps3fb_cmp_mode(vmode, var);
-		pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n",
-			 __func__, id, vmode->left_margin, vmode->xres,
-			 vmode->right_margin, vmode->upper_margin,
-			 vmode->yres, vmode->lower_margin, diff);
-		if (diff < 0)
-			continue;
-		if (diff < best_diff) {
-			best_id = id;
-			if (!diff)
-				break;
-			best_diff = diff;
-		}
-	}
-
-	if (!best_id) {
-		pr_debug("%s: no suitable mode found\n", __func__);
-		return 0;
-	}
-
-	id = best_id;
-	vmode = ps3fb_native_vmode(id);
-
-	*ddr_line_length = vmode->xres * BPP;
-
-	/* minimum resolution */
-	if (!var->xres)
-		var->xres = 1;
-	if (!var->yres)
-		var->yres = 1;
-
-	/* minimum virtual resolution */
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	/* minimum margins */
-	if (var->left_margin < vmode->left_margin)
-		var->left_margin = vmode->left_margin;
-	if (var->right_margin < vmode->right_margin)
-		var->right_margin = vmode->right_margin;
-	if (var->upper_margin < vmode->upper_margin)
-		var->upper_margin = vmode->upper_margin;
-	if (var->lower_margin < vmode->lower_margin)
-		var->lower_margin = vmode->lower_margin;
-
-	/* extra margins */
-	gap = ((long)vmode->left_margin + (long)vmode->xres +
-	       (long)vmode->right_margin) -
-	      ((long)var->left_margin + (long)var->xres +
-	       (long)var->right_margin);
-	if (gap > 0) {
-		var->left_margin += gap/2;
-		var->right_margin += (gap+1)/2;
-		pr_debug("%s: rounded up H to %u [%u] %u\n", __func__,
-			 var->left_margin, var->xres, var->right_margin);
-	}
-
-	gap = ((long)vmode->upper_margin + (long)vmode->yres +
-	       (long)vmode->lower_margin) -
-	      ((long)var->upper_margin + (long)var->yres +
-	       (long)var->lower_margin);
-	if (gap > 0) {
-		var->upper_margin += gap/2;
-		var->lower_margin += (gap+1)/2;
-		pr_debug("%s: rounded up V to %u [%u] %u\n", __func__,
-			 var->upper_margin, var->yres, var->lower_margin);
-	}
-
-	/* fixed fields */
-	var->pixclock = vmode->pixclock;
-	var->hsync_len = vmode->hsync_len;
-	var->vsync_len = vmode->vsync_len;
-	var->sync = vmode->sync;
-
-	if (ps3_compare_firmware_version(1, 9, 0) >= 0) {
-		*xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP);
-		if (*xdr_line_length > GPU_MAX_LINE_LENGTH)
-			*xdr_line_length = GPU_MAX_LINE_LENGTH;
-	} else
-		*xdr_line_length = *ddr_line_length;
-
-	if (vmode->sync & FB_SYNC_BROADCAST) {
-		/* Full broadcast modes have the full mode bit set */
-		if (vmode->xres == var->xres && vmode->yres == var->yres)
-			id |= PS3AV_MODE_FULL;
-	}
-
-	pr_debug("%s: mode %u\n", __func__, id);
-	return id;
-}
-
-static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
-			     u64 dst_offset, u64 src_offset, u32 width,
-			     u32 height, u32 dst_line_length,
-			     u32 src_line_length)
-{
-	int status;
-	u64 line_length;
-
-	line_length = dst_line_length;
-	if (src_line_length != dst_line_length)
-		line_length |= (u64)src_line_length << 32;
-
-	src_offset += GPU_FB_START;
-
-	mutex_lock(&ps3_gpu_mutex);
-	status = lv1_gpu_fb_blit(ps3fb.context_handle, dst_offset,
-				 GPU_IOIF + src_offset,
-				 L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
-				 (width << 16) | height,
-				 line_length);
-	mutex_unlock(&ps3_gpu_mutex);
-
-	if (status)
-		dev_err(dev, "%s: lv1_gpu_fb_blit failed: %d\n", __func__,
-			status);
-#ifdef HEAD_A
-	status = lv1_gpu_display_flip(ps3fb.context_handle, 0, frame_offset);
-	if (status)
-		dev_err(dev, "%s: lv1_gpu_display_flip failed: %d\n", __func__,
-			status);
-#endif
-#ifdef HEAD_B
-	status = lv1_gpu_display_flip(ps3fb.context_handle, 1, frame_offset);
-	if (status)
-		dev_err(dev, "%s: lv1_gpu_display_flip failed: %d\n", __func__,
-			status);
-#endif
-}
-
-static int ps3fb_sync(struct fb_info *info, u32 frame)
-{
-	struct ps3fb_par *par = info->par;
-	int error = 0;
-	u64 ddr_base, xdr_base;
-
-	if (frame > par->num_frames - 1) {
-		dev_dbg(info->device, "%s: invalid frame number (%u)\n",
-			__func__, frame);
-		error = -EINVAL;
-		goto out;
-	}
-
-	xdr_base = frame * par->xdr_frame_size;
-	ddr_base = frame * par->ddr_frame_size;
-
-	ps3fb_sync_image(info->device, ddr_base + par->full_offset,
-			 ddr_base + par->fb_offset, xdr_base + par->pan_offset,
-			 par->width, par->height, par->ddr_line_length,
-			 info->fix.line_length);
-
-out:
-	return error;
-}
-
-static int ps3fb_open(struct fb_info *info, int user)
-{
-	atomic_inc(&ps3fb.f_count);
-	return 0;
-}
-
-static int ps3fb_release(struct fb_info *info, int user)
-{
-	if (atomic_dec_and_test(&ps3fb.f_count)) {
-		if (atomic_read(&ps3fb.ext_flip)) {
-			atomic_set(&ps3fb.ext_flip, 0);
-			if (console_trylock()) {
-				ps3fb_sync(info, 0);	/* single buffer */
-				console_unlock();
-			}
-		}
-	}
-	return 0;
-}
-
-    /*
-     *  Setting the video mode has been split into two parts.
-     *  First part, xxxfb_check_var, must not write anything
-     *  to hardware, it should only verify and adjust var.
-     *  This means it doesn't alter par but it does use hardware
-     *  data from it to check this var.
-     */
-
-static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	u32 xdr_line_length, ddr_line_length;
-	int mode;
-
-	mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length);
-	if (!mode)
-		return -EINVAL;
-
-	/* Virtual screen */
-	if (var->xres_virtual > xdr_line_length / BPP) {
-		dev_dbg(info->device,
-			"Horizontal virtual screen size too large\n");
-		return -EINVAL;
-	}
-
-	if (var->xoffset + var->xres > var->xres_virtual ||
-	    var->yoffset + var->yres > var->yres_virtual) {
-		dev_dbg(info->device, "panning out-of-range\n");
-		return -EINVAL;
-	}
-
-	/* We support ARGB8888 only */
-	if (var->bits_per_pixel > 32 || var->grayscale ||
-	    var->red.offset > 16 || var->green.offset > 8 ||
-	    var->blue.offset > 0 || var->transp.offset > 24 ||
-	    var->red.length > 8 || var->green.length > 8 ||
-	    var->blue.length > 8 || var->transp.length > 8 ||
-	    var->red.msb_right || var->green.msb_right ||
-	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
-		dev_dbg(info->device, "We support ARGB8888 only\n");
-		return -EINVAL;
-	}
-
-	var->bits_per_pixel = 32;
-	var->red.offset = 16;
-	var->green.offset = 8;
-	var->blue.offset = 0;
-	var->transp.offset = 24;
-	var->red.length = 8;
-	var->green.length = 8;
-	var->blue.length = 8;
-	var->transp.length = 8;
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	/* Rotation is not supported */
-	if (var->rotate) {
-		dev_dbg(info->device, "Rotation is not supported\n");
-		return -EINVAL;
-	}
-
-	/* Memory limit */
-	if (var->yres_virtual * xdr_line_length > info->fix.smem_len) {
-		dev_dbg(info->device, "Not enough memory\n");
-		return -ENOMEM;
-	}
-
-	var->height = -1;
-	var->width = -1;
-
-	return 0;
-}
-
-    /*
-     * This routine actually sets the video mode.
-     */
-
-static int ps3fb_set_par(struct fb_info *info)
-{
-	struct ps3fb_par *par = info->par;
-	unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines;
-	unsigned int ddr_xoff, ddr_yoff, offset;
-	const struct fb_videomode *vmode;
-	u64 dst;
-
-	mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length);
-	if (!mode)
-		return -EINVAL;
-
-	vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK);
-
-	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
-	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
-	info->fix.line_length = xdr_line_length;
-
-	par->ddr_line_length = ddr_line_length;
-	par->ddr_frame_size = vmode->yres * ddr_line_length;
-	par->xdr_frame_size = info->var.yres_virtual * xdr_line_length;
-
-	par->num_frames = info->fix.smem_len /
-			  max(par->ddr_frame_size, par->xdr_frame_size);
-
-	/* Keep the special bits we cannot set using fb_var_screeninfo */
-	par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
-
-	par->width = info->var.xres;
-	par->height = info->var.yres;
-
-	/* Start of the virtual frame buffer (relative to fullscreen) */
-	ddr_xoff = info->var.left_margin - vmode->left_margin;
-	ddr_yoff = info->var.upper_margin - vmode->upper_margin;
-	offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP;
-
-	par->fb_offset = GPU_ALIGN_UP(offset);
-	par->full_offset = par->fb_offset - offset;
-	par->pan_offset = info->var.yoffset * xdr_line_length +
-			  info->var.xoffset * BPP;
-
-	if (par->new_mode_id != par->mode_id) {
-		if (ps3av_set_video_mode(par->new_mode_id)) {
-			par->new_mode_id = par->mode_id;
-			return -EINVAL;
-		}
-		par->mode_id = par->new_mode_id;
-	}
-
-	/* Clear XDR frame buffer memory */
-	memset((void __force *)info->screen_base, 0, info->fix.smem_len);
-
-	/* Clear DDR frame buffer memory */
-	lines = vmode->yres * par->num_frames;
-	if (par->full_offset)
-		lines++;
-	maxlines = info->fix.smem_len / ddr_line_length;
-	for (dst = 0; lines; dst += maxlines * ddr_line_length) {
-		unsigned int l = min(lines, maxlines);
-		ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l,
-				 ddr_line_length, ddr_line_length);
-		lines -= l;
-	}
-
-	return 0;
-}
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
-			   unsigned int green, unsigned int blue,
-			   unsigned int transp, struct fb_info *info)
-{
-	if (regno >= 16)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	transp >>= 8;
-
-	((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 |
-					       green << 8 | blue;
-	return 0;
-}
-
-static int ps3fb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct ps3fb_par *par = info->par;
-
-	par->pan_offset = var->yoffset * info->fix.line_length +
-			  var->xoffset * BPP;
-	return 0;
-}
-
-    /*
-     *  As we have a virtual frame buffer, we need our own mmap function
-     */
-
-static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	int r;
-
-	r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
-
-	dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
-		info->fix.smem_start + (vma->vm_pgoff << PAGE_SHIFT),
-		vma->vm_start);
-
-	return r;
-}
-
-    /*
-     * Blank the display
-     */
-
-static int ps3fb_blank(int blank, struct fb_info *info)
-{
-	int retval;
-
-	dev_dbg(info->device, "%s: blank:%d\n", __func__, blank);
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		retval = ps3av_video_mute(1);	/* mute on */
-		if (!retval)
-			ps3fb.is_blanked = 1;
-		break;
-
-	default:		/* unblank */
-		retval = ps3av_video_mute(0);	/* mute off */
-		if (!retval)
-			ps3fb.is_blanked = 0;
-		break;
-	}
-	return retval;
-}
-
-static int ps3fb_get_vblank(struct fb_vblank *vblank)
-{
-	memset(vblank, 0, sizeof(*vblank));
-	vblank->flags = FB_VBLANK_HAVE_VSYNC;
-	return 0;
-}
-
-static int ps3fb_wait_for_vsync(u32 crtc)
-{
-	int ret;
-	u64 count;
-
-	count = ps3fb.vblank_count;
-	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
-					       count != ps3fb.vblank_count,
-					       HZ / 10);
-	if (!ret)
-		return -ETIMEDOUT;
-
-	return 0;
-}
-
-
-    /*
-     * ioctl
-     */
-
-static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
-		       unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	u32 val;
-	int retval = -EFAULT;
-
-	switch (cmd) {
-	case FBIOGET_VBLANK:
-		{
-			struct fb_vblank vblank;
-			dev_dbg(info->device, "FBIOGET_VBLANK:\n");
-			retval = ps3fb_get_vblank(&vblank);
-			if (retval)
-				break;
-
-			if (copy_to_user(argp, &vblank, sizeof(vblank)))
-				retval = -EFAULT;
-			break;
-		}
-
-	case FBIO_WAITFORVSYNC:
-		{
-			u32 crt;
-			dev_dbg(info->device, "FBIO_WAITFORVSYNC:\n");
-			if (get_user(crt, (u32 __user *) arg))
-				break;
-
-			retval = ps3fb_wait_for_vsync(crt);
-			break;
-		}
-
-	case PS3FB_IOCTL_SETMODE:
-		{
-			struct ps3fb_par *par = info->par;
-			const struct fb_videomode *vmode;
-			struct fb_var_screeninfo var;
-
-			if (copy_from_user(&val, argp, sizeof(val)))
-				break;
-
-			if (!(val & PS3AV_MODE_MASK)) {
-				u32 id = ps3av_get_auto_mode();
-				if (id > 0)
-					val = (val & ~PS3AV_MODE_MASK) | id;
-			}
-			dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val);
-			retval = -EINVAL;
-			vmode = ps3fb_vmode(val);
-			if (vmode) {
-				var = info->var;
-				fb_videomode_to_var(&var, vmode);
-				console_lock();
-				info->flags |= FBINFO_MISC_USEREVENT;
-				/* Force, in case only special bits changed */
-				var.activate |= FB_ACTIVATE_FORCE;
-				par->new_mode_id = val;
-				retval = fb_set_var(info, &var);
-				info->flags &= ~FBINFO_MISC_USEREVENT;
-				console_unlock();
-			}
-			break;
-		}
-
-	case PS3FB_IOCTL_GETMODE:
-		val = ps3av_get_mode();
-		dev_dbg(info->device, "PS3FB_IOCTL_GETMODE:%x\n", val);
-		if (!copy_to_user(argp, &val, sizeof(val)))
-			retval = 0;
-		break;
-
-	case PS3FB_IOCTL_SCREENINFO:
-		{
-			struct ps3fb_par *par = info->par;
-			struct ps3fb_ioctl_res res;
-			dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n");
-			res.xres = info->fix.line_length / BPP;
-			res.yres = info->var.yres_virtual;
-			res.xoff = (res.xres - info->var.xres) / 2;
-			res.yoff = (res.yres - info->var.yres) / 2;
-			res.num_frames = par->num_frames;
-			if (!copy_to_user(argp, &res, sizeof(res)))
-				retval = 0;
-			break;
-		}
-
-	case PS3FB_IOCTL_ON:
-		dev_dbg(info->device, "PS3FB_IOCTL_ON:\n");
-		atomic_inc(&ps3fb.ext_flip);
-		retval = 0;
-		break;
-
-	case PS3FB_IOCTL_OFF:
-		dev_dbg(info->device, "PS3FB_IOCTL_OFF:\n");
-		atomic_dec_if_positive(&ps3fb.ext_flip);
-		retval = 0;
-		break;
-
-	case PS3FB_IOCTL_FSEL:
-		if (copy_from_user(&val, argp, sizeof(val)))
-			break;
-
-		dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val);
-		console_lock();
-		retval = ps3fb_sync(info, val);
-		console_unlock();
-		break;
-
-	default:
-		retval = -ENOIOCTLCMD;
-		break;
-	}
-	return retval;
-}
-
-static int ps3fbd(void *arg)
-{
-	struct fb_info *info = arg;
-
-	set_freezable();
-	while (!kthread_should_stop()) {
-		try_to_freeze();
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (ps3fb.is_kicked) {
-			ps3fb.is_kicked = 0;
-			console_lock();
-			ps3fb_sync(info, 0);	/* single buffer */
-			console_unlock();
-		}
-		schedule();
-	}
-	return 0;
-}
-
-static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
-{
-	struct device *dev = ptr;
-	u64 v1;
-	int status;
-	struct display_head *head = &ps3fb.dinfo->display_head[1];
-
-	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
-	if (status) {
-		dev_err(dev, "%s: lv1_gpu_context_intr failed: %d\n", __func__,
-			status);
-		return IRQ_NONE;
-	}
-
-	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
-		/* VSYNC */
-		ps3fb.vblank_count = head->vblank_count;
-		if (ps3fb.task && !ps3fb.is_blanked &&
-		    !atomic_read(&ps3fb.ext_flip)) {
-			ps3fb.is_kicked = 1;
-			wake_up_process(ps3fb.task);
-		}
-		wake_up_interruptible(&ps3fb.wait_vsync);
-	}
-
-	return IRQ_HANDLED;
-}
-
-
-static struct fb_ops ps3fb_ops = {
-	.fb_open	= ps3fb_open,
-	.fb_release	= ps3fb_release,
-	.fb_read        = fb_sys_read,
-	.fb_write       = fb_sys_write,
-	.fb_check_var	= ps3fb_check_var,
-	.fb_set_par	= ps3fb_set_par,
-	.fb_setcolreg	= ps3fb_setcolreg,
-	.fb_pan_display	= ps3fb_pan_display,
-	.fb_fillrect	= sys_fillrect,
-	.fb_copyarea	= sys_copyarea,
-	.fb_imageblit	= sys_imageblit,
-	.fb_mmap	= ps3fb_mmap,
-	.fb_blank	= ps3fb_blank,
-	.fb_ioctl	= ps3fb_ioctl,
-	.fb_compat_ioctl = ps3fb_ioctl
-};
-
-static struct fb_fix_screeninfo ps3fb_fix = {
-	.id =		DEVICE_NAME,
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static int ps3fb_probe(struct ps3_system_bus_device *dev)
-{
-	struct fb_info *info;
-	struct ps3fb_par *par;
-	int retval;
-	u64 ddr_lpar = 0;
-	u64 lpar_dma_control = 0;
-	u64 lpar_driver_info = 0;
-	u64 lpar_reports = 0;
-	u64 lpar_reports_size = 0;
-	u64 xdr_lpar;
-	struct gpu_driver_info *dinfo;
-	void *fb_start;
-	int status;
-	struct task_struct *task;
-	unsigned long max_ps3fb_size;
-
-	if (ps3fb_videomemory.size < GPU_CMD_BUF_SIZE) {
-		dev_err(&dev->core, "%s: Not enough video memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	retval = ps3_open_hv_device(dev);
-	if (retval) {
-		dev_err(&dev->core, "%s: ps3_open_hv_device failed\n",
-			__func__);
-		goto err;
-	}
-
-	if (!ps3fb_mode)
-		ps3fb_mode = ps3av_get_mode();
-	dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode);
-
-	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
-	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
-	init_waitqueue_head(&ps3fb.wait_vsync);
-
-#ifdef HEAD_A
-	status = lv1_gpu_display_sync(0x0, 0, L1GPU_DISPLAY_SYNC_VSYNC);
-	if (status) {
-		dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d\n",
-			__func__, status);
-		retval = -ENODEV;
-		goto err_close_device;
-	}
-#endif
-#ifdef HEAD_B
-	status = lv1_gpu_display_sync(0x0, 1, L1GPU_DISPLAY_SYNC_VSYNC);
-	if (status) {
-		dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d\n",
-			__func__, status);
-		retval = -ENODEV;
-		goto err_close_device;
-	}
-#endif
-
-	max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF;
-	if (ps3fb_videomemory.size > max_ps3fb_size) {
-		dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n",
-			 max_ps3fb_size);
-		ps3fb_videomemory.size = max_ps3fb_size;
-	}
-
-	/* get gpu context handle */
-	status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0,
-					 &ps3fb.memory_handle, &ddr_lpar);
-	if (status) {
-		dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
-			__func__, status);
-		retval = -ENOMEM;
-		goto err_close_device;
-	}
-	dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
-
-	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
-					  &ps3fb.context_handle,
-					  &lpar_dma_control, &lpar_driver_info,
-					  &lpar_reports, &lpar_reports_size);
-	if (status) {
-		dev_err(&dev->core,
-			"%s: lv1_gpu_context_allocate failed: %d\n", __func__,
-			status);
-		retval = -ENOMEM;
-		goto err_gpu_memory_free;
-	}
-
-	/* vsync interrupt */
-	dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
-	if (!dinfo) {
-		dev_err(&dev->core, "%s: ioremap failed\n", __func__);
-		retval = -ENOMEM;
-		goto err_gpu_context_free;
-	}
-
-	ps3fb.dinfo = dinfo;
-	dev_dbg(&dev->core, "version_driver:%x\n", dinfo->version_driver);
-	dev_dbg(&dev->core, "irq outlet:%x\n", dinfo->irq.irq_outlet);
-	dev_dbg(&dev->core, "version_gpu: %x memory_size: %x ch: %x "
-		"core_freq: %d mem_freq:%d\n", dinfo->version_gpu,
-		dinfo->memory_size, dinfo->hardware_channel,
-		dinfo->nvcore_frequency/1000000,
-		dinfo->memory_frequency/1000000);
-
-	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
-		dev_err(&dev->core, "%s: version_driver err:%x\n", __func__,
-			dinfo->version_driver);
-		retval = -EINVAL;
-		goto err_iounmap_dinfo;
-	}
-
-	retval = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
-				    &ps3fb.irq_no);
-	if (retval) {
-		dev_err(&dev->core, "%s: ps3_alloc_irq failed %d\n", __func__,
-			retval);
-		goto err_iounmap_dinfo;
-	}
-
-	retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
-			     0, DEVICE_NAME, &dev->core);
-	if (retval) {
-		dev_err(&dev->core, "%s: request_irq failed %d\n", __func__,
-			retval);
-		goto err_destroy_plug;
-	}
-
-	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
-			  (1 << GPU_INTR_STATUS_FLIP_1);
-
-	/* Clear memory to prevent kernel info leakage into userspace */
-	memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size);
-
-	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
-
-	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
-				       xdr_lpar, ps3fb_videomemory.size,
-				       CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
-				       CBE_IOPTE_M);
-	if (status) {
-		dev_err(&dev->core, "%s: lv1_gpu_context_iomap failed: %d\n",
-			__func__, status);
-		retval =  -ENXIO;
-		goto err_free_irq;
-	}
-
-	dev_dbg(&dev->core, "video:%p ioif:%lx lpar:%llx size:%lx\n",
-		ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
-		ps3fb_videomemory.size);
-
-	status = lv1_gpu_fb_setup(ps3fb.context_handle, xdr_lpar,
-				  GPU_CMD_BUF_SIZE, GPU_IOIF);
-	if (status) {
-		dev_err(&dev->core, "%s: lv1_gpu_fb_setup failed: %d\n",
-			__func__, status);
-		retval = -ENXIO;
-		goto err_context_unmap;
-	}
-
-	info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
-	if (!info) {
-		retval = -ENOMEM;
-		goto err_context_fb_close;
-	}
-
-	par = info->par;
-	par->mode_id = ~ps3fb_mode;	/* != ps3fb_mode, to trigger change */
-	par->new_mode_id = ps3fb_mode;
-	par->num_frames = 1;
-
-	info->fbops = &ps3fb_ops;
-	info->fix = ps3fb_fix;
-
-	/*
-	 * The GPU command buffer is at the start of video memory
-	 * As we don't use the full command buffer, we can put the actual
-	 * frame buffer at offset GPU_FB_START and save some precious XDR
-	 * memory
-	 */
-	fb_start = ps3fb_videomemory.address + GPU_FB_START;
-	info->screen_base = (char __force __iomem *)fb_start;
-	info->fix.smem_start = __pa(fb_start);
-	info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START;
-
-	info->pseudo_palette = par->pseudo_palette;
-	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
-		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0)
-		goto err_framebuffer_release;
-
-	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
-			  ARRAY_SIZE(ps3fb_modedb),
-			  ps3fb_vmode(par->new_mode_id), 32)) {
-		retval = -EINVAL;
-		goto err_fb_dealloc;
-	}
-
-	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),
-				 &info->modelist);
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err_fb_dealloc;
-
-	ps3_system_bus_set_drvdata(dev, info);
-
-	dev_info(info->device, "%s %s, using %u KiB of video memory\n",
-		 dev_driver_string(info->dev), dev_name(info->dev),
-		 info->fix.smem_len >> 10);
-
-	task = kthread_run(ps3fbd, info, DEVICE_NAME);
-	if (IS_ERR(task)) {
-		retval = PTR_ERR(task);
-		goto err_unregister_framebuffer;
-	}
-
-	ps3fb.task = task;
-
-	return 0;
-
-err_unregister_framebuffer:
-	unregister_framebuffer(info);
-err_fb_dealloc:
-	fb_dealloc_cmap(&info->cmap);
-err_framebuffer_release:
-	framebuffer_release(info);
-err_context_fb_close:
-	lv1_gpu_fb_close(ps3fb.context_handle);
-err_context_unmap:
-	lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
-			      ps3fb_videomemory.size, CBE_IOPTE_M);
-err_free_irq:
-	free_irq(ps3fb.irq_no, &dev->core);
-err_destroy_plug:
-	ps3_irq_plug_destroy(ps3fb.irq_no);
-err_iounmap_dinfo:
-	iounmap((u8 __force __iomem *)ps3fb.dinfo);
-err_gpu_context_free:
-	lv1_gpu_context_free(ps3fb.context_handle);
-err_gpu_memory_free:
-	lv1_gpu_memory_free(ps3fb.memory_handle);
-err_close_device:
-	ps3_close_hv_device(dev);
-err:
-	return retval;
-}
-
-static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
-{
-	struct fb_info *info = ps3_system_bus_get_drvdata(dev);
-	u64 xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
-
-	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
-
-	atomic_inc(&ps3fb.ext_flip);	/* flip off */
-	ps3fb.dinfo->irq.mask = 0;
-
-	if (ps3fb.task) {
-		struct task_struct *task = ps3fb.task;
-		ps3fb.task = NULL;
-		kthread_stop(task);
-	}
-	if (ps3fb.irq_no) {
-		free_irq(ps3fb.irq_no, &dev->core);
-		ps3_irq_plug_destroy(ps3fb.irq_no);
-	}
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-		ps3_system_bus_set_drvdata(dev, NULL);
-	}
-	iounmap((u8 __force __iomem *)ps3fb.dinfo);
-	lv1_gpu_fb_close(ps3fb.context_handle);
-	lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
-			      ps3fb_videomemory.size, CBE_IOPTE_M);
-	lv1_gpu_context_free(ps3fb.context_handle);
-	lv1_gpu_memory_free(ps3fb.memory_handle);
-	ps3_close_hv_device(dev);
-	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
-
-	return 0;
-}
-
-static struct ps3_system_bus_driver ps3fb_driver = {
-	.match_id	= PS3_MATCH_ID_GPU,
-	.match_sub_id	= PS3_MATCH_SUB_ID_GPU_FB,
-	.core.name	= DEVICE_NAME,
-	.core.owner	= THIS_MODULE,
-	.probe		= ps3fb_probe,
-	.remove		= ps3fb_shutdown,
-	.shutdown	= ps3fb_shutdown,
-};
-
-static int __init ps3fb_setup(void)
-{
-	char *options;
-
-#ifdef MODULE
-	return 0;
-#endif
-
-	if (fb_get_options(DEVICE_NAME, &options))
-		return -ENXIO;
-
-	if (!options || !*options)
-		return 0;
-
-	while (1) {
-		char *this_opt = strsep(&options, ",");
-
-		if (!this_opt)
-			break;
-		if (!*this_opt)
-			continue;
-		if (!strncmp(this_opt, "mode:", 5))
-			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
-		else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-
-static int __init ps3fb_init(void)
-{
-	if (!ps3fb_videomemory.address ||  ps3fb_setup())
-		return -ENXIO;
-
-	return ps3_system_bus_driver_register(&ps3fb_driver);
-}
-
-static void __exit ps3fb_exit(void)
-{
-	pr_debug(" -> %s:%d\n", __func__, __LINE__);
-	ps3_system_bus_driver_unregister(&ps3fb_driver);
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
-}
-
-module_init(ps3fb_init);
-module_exit(ps3fb_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
-MODULE_AUTHOR("Sony Computer Entertainment Inc.");
-MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_FB);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
deleted file mode 100644
index 167cffff3d4e..000000000000
--- a/drivers/video/pvr2fb.c
+++ /dev/null
@@ -1,1142 +0,0 @@
-/*
- * drivers/video/pvr2fb.c
- *
- * Frame buffer and fbcon support for the NEC PowerVR2 found within the Sega
- * Dreamcast.
- *
- * Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org>
- * Copyright (c) 2001 - 2008  Paul Mundt <lethal@linux-sh.org>
- *
- * This driver is mostly based on the excellent amifb and vfb sources.  It uses
- * an odd scheme for converting hardware values to/from framebuffer values,
- * here are some hacked-up formulas:
- *
- *  The Dreamcast has screen offsets from each side of its four borders and
- *  the start offsets of the display window.  I used these values to calculate
- *  'pseudo' values (think of them as placeholders) for the fb video mode, so
- *  that when it came time to convert these values back into their hardware
- *  values, I could just add mode- specific offsets to get the correct mode
- *  settings:
- *
- *      left_margin = diwstart_h - borderstart_h;
- *      right_margin = borderstop_h - (diwstart_h + xres);
- *      upper_margin = diwstart_v - borderstart_v;
- *      lower_margin = borderstop_v - (diwstart_h + yres);
- *
- *      hsync_len = borderstart_h + (hsync_total - borderstop_h);
- *      vsync_len = borderstart_v + (vsync_total - borderstop_v);
- *
- *  Then, when it's time to convert back to hardware settings, the only
- *  constants are the borderstart_* offsets, all other values are derived from
- *  the fb video mode:
- *
- *      // PAL
- *      borderstart_h = 116;
- *      borderstart_v = 44;
- *      ...
- *      borderstop_h = borderstart_h + hsync_total - hsync_len;
- *      ...
- *      diwstart_v = borderstart_v - upper_margin;
- *
- *  However, in the current implementation, the borderstart values haven't had
- *  the benefit of being fully researched, so some modes may be broken.
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#ifdef CONFIG_SH_DREAMCAST
-#include <asm/machvec.h>
-#include <mach-dreamcast/mach/sysasic.h>
-#endif
-
-#ifdef CONFIG_PVR2_DMA
-#include <linux/pagemap.h>
-#include <mach/dma.h>
-#include <asm/dma.h>
-#endif
-
-#ifdef CONFIG_SH_STORE_QUEUES
-#include <linux/uaccess.h>
-#include <cpu/sq.h>
-#endif
-
-#ifndef PCI_DEVICE_ID_NEC_NEON250
-#  define PCI_DEVICE_ID_NEC_NEON250	0x0067
-#endif
-
-/* 2D video registers */
-#define DISP_BASE	par->mmio_base
-#define DISP_BRDRCOLR (DISP_BASE + 0x40)
-#define DISP_DIWMODE (DISP_BASE + 0x44)
-#define DISP_DIWADDRL (DISP_BASE + 0x50)
-#define DISP_DIWADDRS (DISP_BASE + 0x54)
-#define DISP_DIWSIZE (DISP_BASE + 0x5c)
-#define DISP_SYNCCONF (DISP_BASE + 0xd0)
-#define DISP_BRDRHORZ (DISP_BASE + 0xd4)
-#define DISP_SYNCSIZE (DISP_BASE + 0xd8)
-#define DISP_BRDRVERT (DISP_BASE + 0xdc)
-#define DISP_DIWCONF (DISP_BASE + 0xe8)
-#define DISP_DIWHSTRT (DISP_BASE + 0xec)
-#define DISP_DIWVSTRT (DISP_BASE + 0xf0)
-#define DISP_PIXDEPTH (DISP_BASE + 0x108)
-
-/* Pixel clocks, one for TV output, doubled for VGA output */
-#define TV_CLK 74239
-#define VGA_CLK 37119
-
-/* This is for 60Hz - the VTOTAL is doubled for interlaced modes */
-#define PAL_HTOTAL 863
-#define PAL_VTOTAL 312
-#define NTSC_HTOTAL 857
-#define NTSC_VTOTAL 262
-
-/* Supported cable types */
-enum { CT_VGA, CT_NONE, CT_RGB, CT_COMPOSITE };
-
-/* Supported video output types */
-enum { VO_PAL, VO_NTSC, VO_VGA };
-
-/* Supported palette types */
-enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 };
-
-struct pvr2_params { unsigned int val; char *name; };
-static struct pvr2_params cables[] = {
-	{ CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
-};
-
-static struct pvr2_params outputs[] = {
-	{ VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
-};
-
-/*
- * This describes the current video mode
- */
-
-static struct pvr2fb_par {
-	unsigned int hsync_total;	/* Clocks/line */
-	unsigned int vsync_total;	/* Lines/field */
-	unsigned int borderstart_h;
-	unsigned int borderstop_h;
-	unsigned int borderstart_v;
-	unsigned int borderstop_v;
-	unsigned int diwstart_h;	/* Horizontal offset of the display field */
-	unsigned int diwstart_v;	/* Vertical offset of the display field, for
-				   interlaced modes, this is the long field */
-	unsigned long disp_start;	/* Address of image within VRAM */
-	unsigned char is_interlaced;	/* Is the display interlaced? */
-	unsigned char is_doublescan;	/* Are scanlines output twice? (doublescan) */
-	unsigned char is_lowres;	/* Is horizontal pixel-doubling enabled? */
-
-	unsigned long mmio_base;	/* MMIO base */
-	u32 palette[16];
-} *currentpar;
-
-static struct fb_info *fb_info;
-
-static struct fb_fix_screeninfo pvr2_fix = {
-	.id =		"NEC PowerVR2",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.ypanstep =	1,
-	.ywrapstep =	1,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo pvr2_var = {
-	.xres =		640,
-	.yres =		480,
-	.xres_virtual =	640,
-	.yres_virtual = 480,
-	.bits_per_pixel	=16,
-	.red =		{ 11, 5, 0 },
-	.green =	{  5, 6, 0 },
-	.blue =		{  0, 5, 0 },
-	.activate =	FB_ACTIVATE_NOW,
-	.height =	-1,
-	.width =	-1,
-	.vmode =	FB_VMODE_NONINTERLACED,
-};
-
-static int cable_type = CT_VGA;
-static int video_output = VO_VGA;
-
-static int nopan = 0;
-static int nowrap = 1;
-
-/*
- * We do all updating, blanking, etc. during the vertical retrace period
- */
-static unsigned int do_vmode_full = 0;	/* Change the video mode */
-static unsigned int do_vmode_pan = 0;	/* Update the video mode */
-static short do_blank = 0;		/* (Un)Blank the screen */
-
-static unsigned int is_blanked = 0;		/* Is the screen blanked? */
-
-#ifdef CONFIG_SH_STORE_QUEUES
-static unsigned long pvr2fb_map;
-#endif
-
-#ifdef CONFIG_PVR2_DMA
-static unsigned int shdma = PVR2_CASCADE_CHAN;
-static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
-#endif
-
-static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue,
-                            unsigned int transp, struct fb_info *info);
-static int pvr2fb_blank(int blank, struct fb_info *info);
-static unsigned long get_line_length(int xres_virtual, int bpp);
-static void set_color_bitfields(struct fb_var_screeninfo *var);
-static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
-static int pvr2fb_set_par(struct fb_info *info);
-static void pvr2_update_display(struct fb_info *info);
-static void pvr2_init_display(struct fb_info *info);
-static void pvr2_do_blank(void);
-static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id);
-static int pvr2_init_cable(void);
-static int pvr2_get_param(const struct pvr2_params *p, const char *s,
-                            int val, int size);
-#ifdef CONFIG_PVR2_DMA
-static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
-			    size_t count, loff_t *ppos);
-#endif
-
-static struct fb_ops pvr2fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= pvr2fb_setcolreg,
-	.fb_blank	= pvr2fb_blank,
-	.fb_check_var	= pvr2fb_check_var,
-	.fb_set_par	= pvr2fb_set_par,
-#ifdef CONFIG_PVR2_DMA
-	.fb_write	= pvr2fb_write,
-#endif
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static struct fb_videomode pvr2_modedb[] = {
-    /*
-     * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with
-     * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
-     * NTSC, so it shouldn't be a problem (I hope).
-     */
-
-    {
-	/* 640x480 @ 60Hz interlaced (NTSC) */
-	"ntsc_640x480i", 60, 640, 480, TV_CLK, 38, 33, 0, 18, 146, 26,
-	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-    }, {
-	/* 640x240 @ 60Hz (NTSC) */
-	/* XXX: Broken! Don't use... */
-	"ntsc_640x240", 60, 640, 240, TV_CLK, 38, 33, 0, 0, 146, 22,
-	FB_SYNC_BROADCAST, FB_VMODE_YWRAP
-    }, {
-	/* 640x480 @ 60hz (VGA) */
-	"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,
-	0, FB_VMODE_YWRAP
-    },
-};
-
-#define NUM_TOTAL_MODES  ARRAY_SIZE(pvr2_modedb)
-
-#define DEFMODE_NTSC	0
-#define DEFMODE_PAL	0
-#define DEFMODE_VGA	2
-
-static int defmode = DEFMODE_NTSC;
-static char *mode_option = NULL;
-
-static inline void pvr2fb_set_pal_type(unsigned int type)
-{
-	struct pvr2fb_par *par = (struct pvr2fb_par *)fb_info->par;
-
-	fb_writel(type, par->mmio_base + 0x108);
-}
-
-static inline void pvr2fb_set_pal_entry(struct pvr2fb_par *par,
-					unsigned int regno,
-					unsigned int val)
-{
-	fb_writel(val, par->mmio_base + 0x1000 + (4 * regno));
-}
-
-static int pvr2fb_blank(int blank, struct fb_info *info)
-{
-	do_blank = blank ? blank : -1;
-	return 0;
-}
-
-static inline unsigned long get_line_length(int xres_virtual, int bpp)
-{
-	return (unsigned long)((((xres_virtual*bpp)+31)&~31) >> 3);
-}
-
-static void set_color_bitfields(struct fb_var_screeninfo *var)
-{
-	switch (var->bits_per_pixel) {
-	    case 16:        /* RGB 565 */
-		pvr2fb_set_pal_type(PAL_RGB565);
-		var->red.offset = 11;    var->red.length = 5;
-		var->green.offset = 5;   var->green.length = 6;
-		var->blue.offset = 0;    var->blue.length = 5;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	    case 24:        /* RGB 888 */
-		var->red.offset = 16;    var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 0;    var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	    case 32:        /* ARGB 8888 */
-		pvr2fb_set_pal_type(PAL_ARGB8888);
-		var->red.offset = 16;    var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 0;    var->blue.length = 8;
-		var->transp.offset = 24; var->transp.length = 8;
-		break;
-	}
-}
-
-static int pvr2fb_setcolreg(unsigned int regno, unsigned int red,
-			    unsigned int green, unsigned int blue,
-                            unsigned int transp, struct fb_info *info)
-{
-	struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
-	unsigned int tmp;
-
-	if (regno > info->cmap.len)
-		return 1;
-
-	/*
-	 * We only support the hardware palette for 16 and 32bpp. It's also
-	 * expected that the palette format has been set by the time we get
-	 * here, so we don't waste time setting it again.
-	 */
-	switch (info->var.bits_per_pixel) {
-	    case 16: /* RGB 565 */
-		tmp =  (red   & 0xf800)       |
-		      ((green & 0xfc00) >> 5) |
-		      ((blue  & 0xf800) >> 11);
-
-		pvr2fb_set_pal_entry(par, regno, tmp);
-		break;
-	    case 24: /* RGB 888 */
-		red >>= 8; green >>= 8; blue >>= 8;
-		tmp = (red << 16) | (green << 8) | blue;
-		break;
-	    case 32: /* ARGB 8888 */
-		red >>= 8; green >>= 8; blue >>= 8;
-		tmp = (transp << 24) | (red << 16) | (green << 8) | blue;
-
-		pvr2fb_set_pal_entry(par, regno, tmp);
-		break;
-	    default:
-		pr_debug("Invalid bit depth %d?!?\n", info->var.bits_per_pixel);
-		return 1;
-	}
-
-	if (regno < 16)
-		((u32*)(info->pseudo_palette))[regno] = tmp;
-
-	return 0;
-}
-
-static int pvr2fb_set_par(struct fb_info *info)
-{
-	struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	unsigned long line_length;
-	unsigned int vtotal;
-
-	/*
-	 * XXX: It's possible that a user could use a VGA box, change the cable
-	 * type in hardware (i.e. switch from VGA<->composite), then change
-	 * modes (i.e. switching to another VT).  If that happens we should
-	 * automagically change the output format to cope, but currently I
-	 * don't have a VGA box to make sure this works properly.
-	 */
-	cable_type = pvr2_init_cable();
-	if (cable_type == CT_VGA && video_output != VO_VGA)
-		video_output = VO_VGA;
-
-	var->vmode &= FB_VMODE_MASK;
-	if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
-		par->is_interlaced = 1;
-	/*
-	 * XXX: Need to be more creative with this (i.e. allow doublecan for
-	 * PAL/NTSC output).
-	 */
-	if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA)
-		par->is_doublescan = 1;
-
-	par->hsync_total = var->left_margin + var->xres + var->right_margin +
-	                   var->hsync_len;
-	par->vsync_total = var->upper_margin + var->yres + var->lower_margin +
-	                   var->vsync_len;
-
-	if (var->sync & FB_SYNC_BROADCAST) {
-		vtotal = par->vsync_total;
-		if (par->is_interlaced)
-			vtotal /= 2;
-		if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) {
-			/* XXX: Check for start values here... */
-			/* XXX: Check hardware for PAL-compatibility */
-			par->borderstart_h = 116;
-			par->borderstart_v = 44;
-		} else {
-			/* NTSC video output */
-			par->borderstart_h = 126;
-			par->borderstart_v = 18;
-		}
-	} else {
-		/* VGA mode */
-		/* XXX: What else needs to be checked? */
-		/*
-		 * XXX: We have a little freedom in VGA modes, what ranges
-		 * should be here (i.e. hsync/vsync totals, etc.)?
-		 */
-		par->borderstart_h = 126;
-		par->borderstart_v = 40;
-	}
-
-	/* Calculate the remainding offsets */
-	par->diwstart_h = par->borderstart_h + var->left_margin;
-	par->diwstart_v = par->borderstart_v + var->upper_margin;
-	par->borderstop_h = par->diwstart_h + var->xres +
-			    var->right_margin;
-	par->borderstop_v = par->diwstart_v + var->yres +
-			    var->lower_margin;
-
-	if (!par->is_interlaced)
-		par->borderstop_v /= 2;
-	if (info->var.xres < 640)
-		par->is_lowres = 1;
-
-	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-	par->disp_start = info->fix.smem_start + (line_length * var->yoffset) * line_length;
-	info->fix.line_length = line_length;
-	return 0;
-}
-
-static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
-	unsigned int vtotal, hsync_total;
-	unsigned long line_length;
-
-	if (var->pixclock != TV_CLK && var->pixclock != VGA_CLK) {
-		pr_debug("Invalid pixclock value %d\n", var->pixclock);
-		return -EINVAL;
-	}
-
-	if (var->xres < 320)
-		var->xres = 320;
-	if (var->yres < 240)
-		var->yres = 240;
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel <= 24)
-		var->bits_per_pixel = 24;
-	else if (var->bits_per_pixel <= 32)
-		var->bits_per_pixel = 32;
-
-	set_color_bitfields(var);
-
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->xoffset || var->yoffset < 0 ||
-		    var->yoffset >= var->yres_virtual) {
-			var->xoffset = var->yoffset = 0;
-		} else {
-			if (var->xoffset > var->xres_virtual - var->xres ||
-			    var->yoffset > var->yres_virtual - var->yres ||
-			    var->xoffset < 0 || var->yoffset < 0)
-				var->xoffset = var->yoffset = 0;
-		}
-	} else {
-		var->xoffset = var->yoffset = 0;
-	}
-
-	/*
-	 * XXX: Need to be more creative with this (i.e. allow doublecan for
-	 * PAL/NTSC output).
-	 */
-	if (var->yres < 480 && video_output == VO_VGA)
-		var->vmode |= FB_VMODE_DOUBLE;
-
-	if (video_output != VO_VGA) {
-		var->sync |= FB_SYNC_BROADCAST;
-		var->vmode |= FB_VMODE_INTERLACED;
-	} else {
-		var->sync &= ~FB_SYNC_BROADCAST;
-		var->vmode &= ~FB_VMODE_INTERLACED;
-		var->vmode |= FB_VMODE_NONINTERLACED;
-	}
-
-	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_TEST) {
-		var->right_margin = par->borderstop_h -
-				   (par->diwstart_h + var->xres);
-		var->left_margin  = par->diwstart_h - par->borderstart_h;
-		var->hsync_len    = par->borderstart_h +
-		                   (par->hsync_total - par->borderstop_h);
-
-		var->upper_margin = par->diwstart_v - par->borderstart_v;
-		var->lower_margin = par->borderstop_v -
-				   (par->diwstart_v + var->yres);
-		var->vsync_len    = par->borderstop_v +
-				   (par->vsync_total - par->borderstop_v);
-	}
-
-	hsync_total = var->left_margin + var->xres + var->right_margin +
-		      var->hsync_len;
-	vtotal = var->upper_margin + var->yres + var->lower_margin +
-		 var->vsync_len;
-
-	if (var->sync & FB_SYNC_BROADCAST) {
-		if (var->vmode & FB_VMODE_INTERLACED)
-			vtotal /= 2;
-		if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) {
-			/* PAL video output */
-			/* XXX: Should be using a range here ... ? */
-			if (hsync_total != PAL_HTOTAL) {
-				pr_debug("invalid hsync total for PAL\n");
-				return -EINVAL;
-			}
-		} else {
-			/* NTSC video output */
-			if (hsync_total != NTSC_HTOTAL) {
-				pr_debug("invalid hsync total for NTSC\n");
-				return -EINVAL;
-			}
-		}
-	}
-
-	/* Check memory sizes */
-	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-	if (line_length * var->yres_virtual > info->fix.smem_len)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static void pvr2_update_display(struct fb_info *info)
-{
-	struct pvr2fb_par *par = (struct pvr2fb_par *) info->par;
-	struct fb_var_screeninfo *var = &info->var;
-
-	/* Update the start address of the display image */
-	fb_writel(par->disp_start, DISP_DIWADDRL);
-	fb_writel(par->disp_start +
-		  get_line_length(var->xoffset+var->xres, var->bits_per_pixel),
-	          DISP_DIWADDRS);
-}
-
-/*
- * Initialize the video mode.  Currently, the 16bpp and 24bpp modes aren't
- * very stable.  It's probably due to the fact that a lot of the 2D video
- * registers are still undocumented.
- */
-
-static void pvr2_init_display(struct fb_info *info)
-{
-	struct pvr2fb_par *par = (struct pvr2fb_par *) info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	unsigned int diw_height, diw_width, diw_modulo = 1;
-	unsigned int bytesperpixel = var->bits_per_pixel >> 3;
-
-	/* hsync and vsync totals */
-	fb_writel((par->vsync_total << 16) | par->hsync_total, DISP_SYNCSIZE);
-
-	/* column height, modulo, row width */
-	/* since we're "panning" within vram, we need to offset things based
-	 * on the offset from the virtual x start to our real gfx. */
-	if (video_output != VO_VGA && par->is_interlaced)
-		diw_modulo += info->fix.line_length / 4;
-	diw_height = (par->is_interlaced ? var->yres / 2 : var->yres);
-	diw_width = get_line_length(var->xres, var->bits_per_pixel) / 4;
-	fb_writel((diw_modulo << 20) | (--diw_height << 10) | --diw_width,
-	          DISP_DIWSIZE);
-
-	/* display address, long and short fields */
-	fb_writel(par->disp_start, DISP_DIWADDRL);
-	fb_writel(par->disp_start +
-	          get_line_length(var->xoffset+var->xres, var->bits_per_pixel),
-	          DISP_DIWADDRS);
-
-	/* border horizontal, border vertical, border color */
-	fb_writel((par->borderstart_h << 16) | par->borderstop_h, DISP_BRDRHORZ);
-	fb_writel((par->borderstart_v << 16) | par->borderstop_v, DISP_BRDRVERT);
-	fb_writel(0, DISP_BRDRCOLR);
-
-	/* display window start position */
-	fb_writel(par->diwstart_h, DISP_DIWHSTRT);
-	fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT);
-
-	/* misc. settings */
-	fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF);
-
-	/* clock doubler (for VGA), scan doubler, display enable */
-	fb_writel(((video_output == VO_VGA) << 23) |
-	          (par->is_doublescan << 1) | 1, DISP_DIWMODE);
-
-	/* bits per pixel */
-	fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
-	fb_writel(bytesperpixel << 2, DISP_PIXDEPTH);
-
-	/* video enable, color sync, interlace,
-	 * hsync and vsync polarity (currently unused) */
-	fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
-}
-
-/* Simulate blanking by making the border cover the entire screen */
-
-#define BLANK_BIT (1<<3)
-
-static void pvr2_do_blank(void)
-{
-	struct pvr2fb_par *par = currentpar;
-	unsigned long diwconf;
-
-	diwconf = fb_readl(DISP_DIWCONF);
-	if (do_blank > 0)
-		fb_writel(diwconf | BLANK_BIT, DISP_DIWCONF);
-	else
-		fb_writel(diwconf & ~BLANK_BIT, DISP_DIWCONF);
-
-	is_blanked = do_blank > 0 ? do_blank : 0;
-}
-
-static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id)
-{
-	struct fb_info *info = dev_id;
-
-	if (do_vmode_pan || do_vmode_full)
-		pvr2_update_display(info);
-	if (do_vmode_full)
-		pvr2_init_display(info);
-	if (do_vmode_pan)
-		do_vmode_pan = 0;
-	if (do_vmode_full)
-		do_vmode_full = 0;
-	if (do_blank) {
-		pvr2_do_blank();
-		do_blank = 0;
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * Determine the cable type and initialize the cable output format.  Don't do
- * anything if the cable type has been overidden (via "cable:XX").
- */
-
-#define PCTRA 0xff80002c
-#define PDTRA 0xff800030
-#define VOUTC 0xa0702c00
-
-static int pvr2_init_cable(void)
-{
-	if (cable_type < 0) {
-		fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
-	                  PCTRA);
-		cable_type = (fb_readw(PDTRA) >> 8) & 3;
-	}
-
-	/* Now select the output format (either composite or other) */
-	/* XXX: Save the previous val first, as this reg is also AICA
-	  related */
-	if (cable_type == CT_COMPOSITE)
-		fb_writel(3 << 8, VOUTC);
-	else if (cable_type == CT_RGB)
-		fb_writel(1 << 9, VOUTC);
-	else
-		fb_writel(0, VOUTC);
-
-	return cable_type;
-}
-
-#ifdef CONFIG_PVR2_DMA
-static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
-			    size_t count, loff_t *ppos)
-{
-	unsigned long dst, start, end, len;
-	unsigned int nr_pages;
-	struct page **pages;
-	int ret, i;
-
-	nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
-	pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
-	if (!pages)
-		return -ENOMEM;
-
-	down_read(&current->mm->mmap_sem);
-	ret = get_user_pages(current, current->mm, (unsigned long)buf,
-			     nr_pages, WRITE, 0, pages, NULL);
-	up_read(&current->mm->mmap_sem);
-
-	if (ret < nr_pages) {
-		nr_pages = ret;
-		ret = -EINVAL;
-		goto out_unmap;
-	}
-
-	dma_configure_channel(shdma, 0x12c1);
-
-	dst   = (unsigned long)fb_info->screen_base + *ppos;
-	start = (unsigned long)page_address(pages[0]);
-	end   = (unsigned long)page_address(pages[nr_pages]);
-	len   = nr_pages << PAGE_SHIFT;
-
-	/* Half-assed contig check */
-	if (start + len == end) {
-		/* As we do this in one shot, it's either all or nothing.. */
-		if ((*ppos + len) > fb_info->fix.smem_len) {
-			ret = -ENOSPC;
-			goto out_unmap;
-		}
-
-		dma_write(shdma, start, 0, len);
-		dma_write(pvr2dma, 0, dst, len);
-		dma_wait_for_completion(pvr2dma);
-
-		goto out;
-	}
-
-	/* Not contiguous, writeout per-page instead.. */
-	for (i = 0; i < nr_pages; i++, dst += PAGE_SIZE) {
-		if ((*ppos + (i << PAGE_SHIFT)) > fb_info->fix.smem_len) {
-			ret = -ENOSPC;
-			goto out_unmap;
-		}
-
-		dma_write_page(shdma, (unsigned long)page_address(pages[i]), 0);
-		dma_write_page(pvr2dma, 0, dst);
-		dma_wait_for_completion(pvr2dma);
-	}
-
-out:
-	*ppos += count;
-	ret = count;
-
-out_unmap:
-	for (i = 0; i < nr_pages; i++)
-		page_cache_release(pages[i]);
-
-	kfree(pages);
-
-	return ret;
-}
-#endif /* CONFIG_PVR2_DMA */
-
-/**
- * pvr2fb_common_init
- *
- * Common init code for the PVR2 chips.
- *
- * This mostly takes care of the common aspects of the fb setup and
- * registration. It's expected that the board-specific init code has
- * already setup pvr2_fix with something meaningful at this point.
- *
- * Device info reporting is also done here, as well as picking a sane
- * default from the modedb. For board-specific modelines, simply define
- * a per-board modedb.
- *
- * Also worth noting is that the cable and video output types are likely
- * always going to be VGA for the PCI-based PVR2 boards, but we leave this
- * in for flexibility anyways. Who knows, maybe someone has tv-out on a
- * PCI-based version of these things ;-)
- */
-static int pvr2fb_common_init(void)
-{
-	struct pvr2fb_par *par = currentpar;
-	unsigned long modememused, rev;
-
-	fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start,
-					       pvr2_fix.smem_len);
-
-	if (!fb_info->screen_base) {
-		printk(KERN_ERR "pvr2fb: Failed to remap smem space\n");
-		goto out_err;
-	}
-
-	par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start,
-							pvr2_fix.mmio_len);
-	if (!par->mmio_base) {
-		printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n");
-		goto out_err;
-	}
-
-	fb_memset(fb_info->screen_base, 0, pvr2_fix.smem_len);
-
-	pvr2_fix.ypanstep	= nopan  ? 0 : 1;
-	pvr2_fix.ywrapstep	= nowrap ? 0 : 1;
-
-	fb_info->fbops		= &pvr2fb_ops;
-	fb_info->fix		= pvr2_fix;
-	fb_info->par		= currentpar;
-	fb_info->pseudo_palette	= currentpar->palette;
-	fb_info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-
-	if (video_output == VO_VGA)
-		defmode = DEFMODE_VGA;
-
-	if (!mode_option)
-		mode_option = "640x480@60";
-
-	if (!fb_find_mode(&fb_info->var, fb_info, mode_option, pvr2_modedb,
-	                  NUM_TOTAL_MODES, &pvr2_modedb[defmode], 16))
-		fb_info->var = pvr2_var;
-
-	fb_alloc_cmap(&fb_info->cmap, 256, 0);
-
-	if (register_framebuffer(fb_info) < 0)
-		goto out_err;
-	/*Must write PIXDEPTH to register before anything is displayed - so force init */
-	pvr2_init_display(fb_info);
-
-	modememused = get_line_length(fb_info->var.xres_virtual,
-				      fb_info->var.bits_per_pixel);
-	modememused *= fb_info->var.yres_virtual;
-
-	rev = fb_readl(par->mmio_base + 0x04);
-
-	fb_info(fb_info, "%s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n",
-		fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f,
-		modememused >> 10,
-		(unsigned long)(fb_info->fix.smem_len >> 10));
-	fb_info(fb_info, "Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
-		fb_info->var.xres, fb_info->var.yres,
-		fb_info->var.bits_per_pixel,
-		get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
-		(char *)pvr2_get_param(cables, NULL, cable_type, 3),
-		(char *)pvr2_get_param(outputs, NULL, video_output, 3));
-
-#ifdef CONFIG_SH_STORE_QUEUES
-	fb_notice(fb_info, "registering with SQ API\n");
-
-	pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
-			      fb_info->fix.id, PAGE_SHARED);
-
-	fb_notice(fb_info, "Mapped video memory to SQ addr 0x%lx\n",
-		  pvr2fb_map);
-#endif
-
-	return 0;
-
-out_err:
-	if (fb_info->screen_base)
-		iounmap(fb_info->screen_base);
-	if (par->mmio_base)
-		iounmap((void *)par->mmio_base);
-
-	return -ENXIO;
-}
-
-#ifdef CONFIG_SH_DREAMCAST
-static int __init pvr2fb_dc_init(void)
-{
-	if (!mach_is_dreamcast())
-		return -ENXIO;
-
-	/* Make a guess at the monitor based on the attached cable */
-	if (pvr2_init_cable() == CT_VGA) {
-		fb_info->monspecs.hfmin = 30000;
-		fb_info->monspecs.hfmax = 70000;
-		fb_info->monspecs.vfmin = 60;
-		fb_info->monspecs.vfmax = 60;
-	} else {
-		/* Not VGA, using a TV (taken from acornfb) */
-		fb_info->monspecs.hfmin = 15469;
-		fb_info->monspecs.hfmax = 15781;
-		fb_info->monspecs.vfmin = 49;
-		fb_info->monspecs.vfmax = 51;
-	}
-
-	/*
-	 * XXX: This needs to pull default video output via BIOS or other means
-	 */
-	if (video_output < 0) {
-		if (cable_type == CT_VGA) {
-			video_output = VO_VGA;
-		} else {
-			video_output = VO_NTSC;
-		}
-	}
-
-	/*
-	 * Nothing exciting about the DC PVR2 .. only a measly 8MiB.
-	 */
-	pvr2_fix.smem_start	= 0xa5000000;	/* RAM starts here */
-	pvr2_fix.smem_len	= 8 << 20;
-
-	pvr2_fix.mmio_start	= 0xa05f8000;	/* registers start here */
-	pvr2_fix.mmio_len	= 0x2000;
-
-	if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, IRQF_SHARED,
-	                "pvr2 VBL handler", fb_info)) {
-		return -EBUSY;
-	}
-
-#ifdef CONFIG_PVR2_DMA
-	if (request_dma(pvr2dma, "pvr2") != 0) {
-		free_irq(HW_EVENT_VSYNC, fb_info);
-		return -EBUSY;
-	}
-#endif
-
-	return pvr2fb_common_init();
-}
-
-static void __exit pvr2fb_dc_exit(void)
-{
-	if (fb_info->screen_base) {
-		iounmap(fb_info->screen_base);
-		fb_info->screen_base = NULL;
-	}
-	if (currentpar->mmio_base) {
-		iounmap((void *)currentpar->mmio_base);
-		currentpar->mmio_base = 0;
-	}
-
-	free_irq(HW_EVENT_VSYNC, fb_info);
-#ifdef CONFIG_PVR2_DMA
-	free_dma(pvr2dma);
-#endif
-}
-#endif /* CONFIG_SH_DREAMCAST */
-
-#ifdef CONFIG_PCI
-static int pvr2fb_pci_probe(struct pci_dev *pdev,
-			    const struct pci_device_id *ent)
-{
-	int ret;
-
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		printk(KERN_ERR "pvr2fb: PCI enable failed\n");
-		return ret;
-	}
-
-	ret = pci_request_regions(pdev, "pvr2fb");
-	if (ret) {
-		printk(KERN_ERR "pvr2fb: PCI request regions failed\n");
-		return ret;
-	}
-
-	/*
-	 * Slightly more exciting than the DC PVR2 .. 16MiB!
-	 */
-	pvr2_fix.smem_start	= pci_resource_start(pdev, 0);
-	pvr2_fix.smem_len	= pci_resource_len(pdev, 0);
-
-	pvr2_fix.mmio_start	= pci_resource_start(pdev, 1);
-	pvr2_fix.mmio_len	= pci_resource_len(pdev, 1);
-
-	fb_info->device		= &pdev->dev;
-
-	return pvr2fb_common_init();
-}
-
-static void pvr2fb_pci_remove(struct pci_dev *pdev)
-{
-	if (fb_info->screen_base) {
-		iounmap(fb_info->screen_base);
-		fb_info->screen_base = NULL;
-	}
-	if (currentpar->mmio_base) {
-		iounmap((void *)currentpar->mmio_base);
-		currentpar->mmio_base = 0;
-	}
-
-	pci_release_regions(pdev);
-}
-
-static struct pci_device_id pvr2fb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NEON250,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, pvr2fb_pci_tbl);
-
-static struct pci_driver pvr2fb_pci_driver = {
-	.name		= "pvr2fb",
-	.id_table	= pvr2fb_pci_tbl,
-	.probe		= pvr2fb_pci_probe,
-	.remove		= pvr2fb_pci_remove,
-};
-
-static int __init pvr2fb_pci_init(void)
-{
-	return pci_register_driver(&pvr2fb_pci_driver);
-}
-
-static void __exit pvr2fb_pci_exit(void)
-{
-	pci_unregister_driver(&pvr2fb_pci_driver);
-}
-#endif /* CONFIG_PCI */
-
-static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val,
-			  int size)
-{
-	int i;
-
-	for (i = 0 ; i < size ; i++ ) {
-		if (s != NULL) {
-			if (!strnicmp(p[i].name, s, strlen(s)))
-				return p[i].val;
-		} else {
-			if (p[i].val == val)
-				return (int)p[i].name;
-		}
-	}
-	return -1;
-}
-
-/*
- * Parse command arguments.  Supported arguments are:
- *    inverse                             Use inverse color maps
- *    cable:composite|rgb|vga             Override the video cable type
- *    output:NTSC|PAL|VGA                 Override the video output format
- *
- *    <xres>x<yres>[-<bpp>][@<refresh>]   or,
- *    <name>[-<bpp>][@<refresh>]          Startup using this video mode
- */
-
-#ifndef MODULE
-static int __init pvr2fb_setup(char *options)
-{
-	char *this_opt;
-	char cable_arg[80];
-	char output_arg[80];
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ","))) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "cable:", 6)) {
-			strcpy(cable_arg, this_opt + 6);
-		} else if (!strncmp(this_opt, "output:", 7)) {
-			strcpy(output_arg, this_opt + 7);
-		} else if (!strncmp(this_opt, "nopan", 5)) {
-			nopan = 1;
-		} else if (!strncmp(this_opt, "nowrap", 6)) {
-			nowrap = 1;
-		} else {
-			mode_option = this_opt;
-		}
-	}
-
-	if (*cable_arg)
-		cable_type = pvr2_get_param(cables, cable_arg, 0, 3);
-	if (*output_arg)
-		video_output = pvr2_get_param(outputs, output_arg, 0, 3);
-
-	return 0;
-}
-#endif
-
-static struct pvr2_board {
-	int (*init)(void);
-	void (*exit)(void);
-	char name[16];
-} board_driver[] __refdata = {
-#ifdef CONFIG_SH_DREAMCAST
-	{ pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" },
-#endif
-#ifdef CONFIG_PCI
-	{ pvr2fb_pci_init, pvr2fb_pci_exit, "PCI PVR2" },
-#endif
-	{ 0, },
-};
-
-static int __init pvr2fb_init(void)
-{
-	int i, ret = -ENODEV;
-	int size;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("pvr2fb", &option))
-		return -ENODEV;
-	pvr2fb_setup(option);
-#endif
-	size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
-
-	fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL);
-
-	if (!fb_info) {
-		printk(KERN_ERR "Failed to allocate memory for fb_info\n");
-		return -ENOMEM;
-	}
-
-
-	currentpar = fb_info->par;
-
-	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
-		struct pvr2_board *pvr_board = board_driver + i;
-
-		if (!pvr_board->init)
-			continue;
-
-		ret = pvr_board->init();
-
-		if (ret != 0) {
-			printk(KERN_ERR "pvr2fb: Failed init of %s device\n",
-				pvr_board->name);
-			framebuffer_release(fb_info);
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static void __exit pvr2fb_exit(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
-		struct pvr2_board *pvr_board = board_driver + i;
-
-		if (pvr_board->exit)
-			pvr_board->exit();
-	}
-
-#ifdef CONFIG_SH_STORE_QUEUES
-	sq_unmap(pvr2fb_map);
-#endif
-
-	unregister_framebuffer(fb_info);
-	framebuffer_release(fb_info);
-}
-
-module_init(pvr2fb_init);
-module_exit(pvr2fb_exit);
-
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
-MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
deleted file mode 100644
index c95b9e46d48f..000000000000
--- a/drivers/video/pxa168fb.c
+++ /dev/null
@@ -1,837 +0,0 @@
-/*
- * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller
- *
- *  Copyright (C) 2008 Marvell International Ltd.
- *  All rights reserved.
- *
- *  2009-02-16  adapted from original version for PXA168/910
- *              Jun Nie <njun@marvell.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/uaccess.h>
-#include <video/pxa168fb.h>
-
-#include "pxa168fb.h"
-
-#define DEFAULT_REFRESH		60	/* Hz */
-
-static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
-{
-	/*
-	 * Pseudocolor mode?
-	 */
-	if (var->bits_per_pixel == 8)
-		return PIX_FMT_PSEUDOCOLOR;
-
-	/*
-	 * Check for 565/1555.
-	 */
-	if (var->bits_per_pixel == 16 && var->red.length <= 5 &&
-	    var->green.length <= 6 && var->blue.length <= 5) {
-		if (var->transp.length == 0) {
-			if (var->red.offset >= var->blue.offset)
-				return PIX_FMT_RGB565;
-			else
-				return PIX_FMT_BGR565;
-		}
-
-		if (var->transp.length == 1 && var->green.length <= 5) {
-			if (var->red.offset >= var->blue.offset)
-				return PIX_FMT_RGB1555;
-			else
-				return PIX_FMT_BGR1555;
-		}
-
-		/* fall through */
-	}
-
-	/*
-	 * Check for 888/A888.
-	 */
-	if (var->bits_per_pixel <= 32 && var->red.length <= 8 &&
-	    var->green.length <= 8 && var->blue.length <= 8) {
-		if (var->bits_per_pixel == 24 && var->transp.length == 0) {
-			if (var->red.offset >= var->blue.offset)
-				return PIX_FMT_RGB888PACK;
-			else
-				return PIX_FMT_BGR888PACK;
-		}
-
-		if (var->bits_per_pixel == 32 && var->transp.length == 8) {
-			if (var->red.offset >= var->blue.offset)
-				return PIX_FMT_RGBA888;
-			else
-				return PIX_FMT_BGRA888;
-		} else {
-			if (var->red.offset >= var->blue.offset)
-				return PIX_FMT_RGB888UNPACK;
-			else
-				return PIX_FMT_BGR888UNPACK;
-		}
-
-		/* fall through */
-	}
-
-	return -EINVAL;
-}
-
-static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt)
-{
-	switch (pix_fmt) {
-	case PIX_FMT_RGB565:
-		var->bits_per_pixel = 16;
-		var->red.offset = 11;    var->red.length = 5;
-		var->green.offset = 5;   var->green.length = 6;
-		var->blue.offset = 0;    var->blue.length = 5;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIX_FMT_BGR565:
-		var->bits_per_pixel = 16;
-		var->red.offset = 0;     var->red.length = 5;
-		var->green.offset = 5;   var->green.length = 6;
-		var->blue.offset = 11;   var->blue.length = 5;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIX_FMT_RGB1555:
-		var->bits_per_pixel = 16;
-		var->red.offset = 10;    var->red.length = 5;
-		var->green.offset = 5;   var->green.length = 5;
-		var->blue.offset = 0;    var->blue.length = 5;
-		var->transp.offset = 15; var->transp.length = 1;
-		break;
-	case PIX_FMT_BGR1555:
-		var->bits_per_pixel = 16;
-		var->red.offset = 0;     var->red.length = 5;
-		var->green.offset = 5;   var->green.length = 5;
-		var->blue.offset = 10;   var->blue.length = 5;
-		var->transp.offset = 15; var->transp.length = 1;
-		break;
-	case PIX_FMT_RGB888PACK:
-		var->bits_per_pixel = 24;
-		var->red.offset = 16;    var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 0;    var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIX_FMT_BGR888PACK:
-		var->bits_per_pixel = 24;
-		var->red.offset = 0;     var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 16;   var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	case PIX_FMT_RGBA888:
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;    var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 0;    var->blue.length = 8;
-		var->transp.offset = 24; var->transp.length = 8;
-		break;
-	case PIX_FMT_BGRA888:
-		var->bits_per_pixel = 32;
-		var->red.offset = 0;     var->red.length = 8;
-		var->green.offset = 8;   var->green.length = 8;
-		var->blue.offset = 16;   var->blue.length = 8;
-		var->transp.offset = 24; var->transp.length = 8;
-		break;
-	case PIX_FMT_PSEUDOCOLOR:
-		var->bits_per_pixel = 8;
-		var->red.offset = 0;     var->red.length = 8;
-		var->green.offset = 0;   var->green.length = 8;
-		var->blue.offset = 0;    var->blue.length = 8;
-		var->transp.offset = 0;  var->transp.length = 0;
-		break;
-	}
-}
-
-static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var,
-		     struct fb_videomode *mode, int pix_fmt, int ystretch)
-{
-	struct fb_info *info = fbi->info;
-
-	set_pix_fmt(var, pix_fmt);
-
-	var->xres = mode->xres;
-	var->yres = mode->yres;
-	var->xres_virtual = max(var->xres, var->xres_virtual);
-	if (ystretch)
-		var->yres_virtual = info->fix.smem_len /
-			(var->xres_virtual * (var->bits_per_pixel >> 3));
-	else
-		var->yres_virtual = max(var->yres, var->yres_virtual);
-	var->grayscale = 0;
-	var->accel_flags = FB_ACCEL_NONE;
-	var->pixclock = mode->pixclock;
-	var->left_margin = mode->left_margin;
-	var->right_margin = mode->right_margin;
-	var->upper_margin = mode->upper_margin;
-	var->lower_margin = mode->lower_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
-	var->sync = mode->sync;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	var->rotate = FB_ROTATE_UR;
-}
-
-static int pxa168fb_check_var(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct pxa168fb_info *fbi = info->par;
-	int pix_fmt;
-
-	/*
-	 * Determine which pixel format we're going to use.
-	 */
-	pix_fmt = determine_best_pix_fmt(var);
-	if (pix_fmt < 0)
-		return pix_fmt;
-	set_pix_fmt(var, pix_fmt);
-	fbi->pix_fmt = pix_fmt;
-
-	/*
-	 * Basic geometry sanity checks.
-	 */
-	if (var->xoffset + var->xres > var->xres_virtual)
-		return -EINVAL;
-	if (var->yoffset + var->yres > var->yres_virtual)
-		return -EINVAL;
-	if (var->xres + var->right_margin +
-	    var->hsync_len + var->left_margin > 2048)
-		return -EINVAL;
-	if (var->yres + var->lower_margin +
-	    var->vsync_len + var->upper_margin > 2048)
-		return -EINVAL;
-
-	/*
-	 * Check size of framebuffer.
-	 */
-	if (var->xres_virtual * var->yres_virtual *
-	    (var->bits_per_pixel >> 3) > info->fix.smem_len)
-		return -EINVAL;
-
-	return 0;
-}
-
-/*
- * The hardware clock divider has an integer and a fractional
- * stage:
- *
- *	clk2 = clk_in / integer_divider
- *	clk_out = clk2 * (1 - (fractional_divider >> 12))
- *
- * Calculate integer and fractional divider for given clk_in
- * and clk_out.
- */
-static void set_clock_divider(struct pxa168fb_info *fbi,
-			      const struct fb_videomode *m)
-{
-	int divider_int;
-	int needed_pixclk;
-	u64 div_result;
-	u32 x = 0;
-
-	/*
-	 * Notice: The field pixclock is used by linux fb
-	 * is in pixel second. E.g. struct fb_videomode &
-	 * struct fb_var_screeninfo
-	 */
-
-	/*
-	 * Check input values.
-	 */
-	if (!m || !m->pixclock || !m->refresh) {
-		dev_err(fbi->dev, "Input refresh or pixclock is wrong.\n");
-		return;
-	}
-
-	/*
-	 * Using PLL/AXI clock.
-	 */
-	x = 0x80000000;
-
-	/*
-	 * Calc divider according to refresh rate.
-	 */
-	div_result = 1000000000000ll;
-	do_div(div_result, m->pixclock);
-	needed_pixclk = (u32)div_result;
-
-	divider_int = clk_get_rate(fbi->clk) / needed_pixclk;
-
-	/* check whether divisor is too small. */
-	if (divider_int < 2) {
-		dev_warn(fbi->dev, "Warning: clock source is too slow."
-				"Try smaller resolution\n");
-		divider_int = 2;
-	}
-
-	/*
-	 * Set setting to reg.
-	 */
-	x |= divider_int;
-	writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV);
-}
-
-static void set_dma_control0(struct pxa168fb_info *fbi)
-{
-	u32 x;
-
-	/*
-	 * Set bit to enable graphics DMA.
-	 */
-	x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
-	x &= ~CFG_GRA_ENA_MASK;
-	x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0);
-
-	/*
-	 * If we are in a pseudo-color mode, we need to enable
-	 * palette lookup.
-	 */
-	if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
-		x |= 0x10000000;
-
-	/*
-	 * Configure hardware pixel format.
-	 */
-	x &= ~(0xF << 16);
-	x |= (fbi->pix_fmt >> 1) << 16;
-
-	/*
-	 * Check red and blue pixel swap.
-	 * 1. source data swap
-	 * 2. panel output data swap
-	 */
-	x &= ~(1 << 12);
-	x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12;
-
-	writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0);
-}
-
-static void set_dma_control1(struct pxa168fb_info *fbi, int sync)
-{
-	u32 x;
-
-	/*
-	 * Configure default bits: vsync triggers DMA, gated clock
-	 * enable, power save enable, configure alpha registers to
-	 * display 100% graphics, and set pixel command.
-	 */
-	x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1);
-	x |= 0x2032ff81;
-
-	/*
-	 * We trigger DMA on the falling edge of vsync if vsync is
-	 * active low, or on the rising edge if vsync is active high.
-	 */
-	if (!(sync & FB_SYNC_VERT_HIGH_ACT))
-		x |= 0x08000000;
-
-	writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1);
-}
-
-static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset)
-{
-	struct pxa168fb_info *fbi = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	int pixel_offset;
-	unsigned long addr;
-
-	pixel_offset = (yoffset * var->xres_virtual) + xoffset;
-
-	addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3));
-	writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0);
-}
-
-static void set_dumb_panel_control(struct fb_info *info)
-{
-	struct pxa168fb_info *fbi = info->par;
-	struct pxa168fb_mach_info *mi = dev_get_platdata(fbi->dev);
-	u32 x;
-
-	/*
-	 * Preserve enable flag.
-	 */
-	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001;
-
-	x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28;
-	x |= mi->gpio_output_data << 20;
-	x |= mi->gpio_output_mask << 12;
-	x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0;
-	x |= mi->invert_composite_blank ? 0x00000040 : 0;
-	x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0;
-	x |= mi->invert_pix_val_ena ? 0x00000010 : 0;
-	x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008;
-	x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004;
-	x |= mi->invert_pixclock ? 0x00000002 : 0;
-
-	writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL);
-}
-
-static void set_dumb_screen_dimensions(struct fb_info *info)
-{
-	struct pxa168fb_info *fbi = info->par;
-	struct fb_var_screeninfo *v = &info->var;
-	int x;
-	int y;
-
-	x = v->xres + v->right_margin + v->hsync_len + v->left_margin;
-	y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin;
-
-	writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL);
-}
-
-static int pxa168fb_set_par(struct fb_info *info)
-{
-	struct pxa168fb_info *fbi = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	struct fb_videomode mode;
-	u32 x;
-	struct pxa168fb_mach_info *mi;
-
-	mi = dev_get_platdata(fbi->dev);
-
-	/*
-	 * Set additional mode info.
-	 */
-	if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
-	info->fix.ypanstep = var->yres;
-
-	/*
-	 * Disable panel output while we setup the display.
-	 */
-	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
-	writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
-
-	/*
-	 * Configure global panel parameters.
-	 */
-	writel((var->yres << 16) | var->xres,
-		fbi->reg_base + LCD_SPU_V_H_ACTIVE);
-
-	/*
-	 * convet var to video mode
-	 */
-	fb_var_to_videomode(&mode, &info->var);
-
-	/* Calculate clock divisor. */
-	set_clock_divider(fbi, &mode);
-
-	/* Configure dma ctrl regs. */
-	set_dma_control0(fbi);
-	set_dma_control1(fbi, info->var.sync);
-
-	/*
-	 * Configure graphics DMA parameters.
-	 */
-	x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH);
-	x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3);
-	writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH);
-	writel((var->yres << 16) | var->xres,
-		fbi->reg_base + LCD_SPU_GRA_HPXL_VLN);
-	writel((var->yres << 16) | var->xres,
-		fbi->reg_base + LCD_SPU_GZM_HPXL_VLN);
-
-	/*
-	 * Configure dumb panel ctrl regs & timings.
-	 */
-	set_dumb_panel_control(info);
-	set_dumb_screen_dimensions(info);
-
-	writel((var->left_margin << 16) | var->right_margin,
-			fbi->reg_base + LCD_SPU_H_PORCH);
-	writel((var->upper_margin << 16) | var->lower_margin,
-			fbi->reg_base + LCD_SPU_V_PORCH);
-
-	/*
-	 * Re-enable panel output.
-	 */
-	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
-	writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
-
-	return 0;
-}
-
-static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
-{
-	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
-}
-
-static u32 to_rgb(u16 red, u16 green, u16 blue)
-{
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	return (red << 16) | (green << 8) | blue;
-}
-
-static int
-pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
-		 unsigned int blue, unsigned int trans, struct fb_info *info)
-{
-	struct pxa168fb_info *fbi = info->par;
-	u32 val;
-
-	if (info->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-					7471 * blue) >> 16;
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) {
-		val =  chan_to_field(red,   &info->var.red);
-		val |= chan_to_field(green, &info->var.green);
-		val |= chan_to_field(blue , &info->var.blue);
-		fbi->pseudo_palette[regno] = val;
-	}
-
-	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
-		val = to_rgb(red, green, blue);
-		writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT);
-		writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL);
-	}
-
-	return 0;
-}
-
-static int pxa168fb_blank(int blank, struct fb_info *info)
-{
-	struct pxa168fb_info *fbi = info->par;
-
-	fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1;
-	set_dumb_panel_control(info);
-
-	return 0;
-}
-
-static int pxa168fb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	set_graphics_start(info, var->xoffset, var->yoffset);
-
-	return 0;
-}
-
-static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id)
-{
-	struct pxa168fb_info *fbi = dev_id;
-	u32 isr = readl(fbi->reg_base + SPU_IRQ_ISR);
-
-	if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) {
-
-		writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK),
-			fbi->reg_base + SPU_IRQ_ISR);
-
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
-}
-
-static struct fb_ops pxa168fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= pxa168fb_check_var,
-	.fb_set_par	= pxa168fb_set_par,
-	.fb_setcolreg	= pxa168fb_setcolreg,
-	.fb_blank	= pxa168fb_blank,
-	.fb_pan_display	= pxa168fb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int pxa168fb_init_mode(struct fb_info *info,
-			      struct pxa168fb_mach_info *mi)
-{
-	struct pxa168fb_info *fbi = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	int ret = 0;
-	u32 total_w, total_h, refresh;
-	u64 div_result;
-	const struct fb_videomode *m;
-
-	/*
-	 * Set default value
-	 */
-	refresh = DEFAULT_REFRESH;
-
-	/* try to find best video mode. */
-	m = fb_find_best_mode(&info->var, &info->modelist);
-	if (m)
-		fb_videomode_to_var(&info->var, m);
-
-	/* Init settings. */
-	var->xres_virtual = var->xres;
-	var->yres_virtual = info->fix.smem_len /
-		(var->xres_virtual * (var->bits_per_pixel >> 3));
-	dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n",
-				var->xres, var->yres);
-
-	/* correct pixclock. */
-	total_w = var->xres + var->left_margin + var->right_margin +
-		  var->hsync_len;
-	total_h = var->yres + var->upper_margin + var->lower_margin +
-		  var->vsync_len;
-
-	div_result = 1000000000000ll;
-	do_div(div_result, total_w * total_h * refresh);
-	var->pixclock = (u32)div_result;
-
-	return ret;
-}
-
-static int pxa168fb_probe(struct platform_device *pdev)
-{
-	struct pxa168fb_mach_info *mi;
-	struct fb_info *info = 0;
-	struct pxa168fb_info *fbi = 0;
-	struct resource *res;
-	struct clk *clk;
-	int irq, ret;
-
-	mi = dev_get_platdata(&pdev->dev);
-	if (mi == NULL) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
-
-	clk = clk_get(&pdev->dev, "LCDCLK");
-	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "unable to get LCDCLK");
-		return PTR_ERR(clk);
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no IO memory defined\n");
-		ret = -ENOENT;
-		goto failed_put_clk;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no IRQ defined\n");
-		ret = -ENOENT;
-		goto failed_put_clk;
-	}
-
-	info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev);
-	if (info == NULL) {
-		ret = -ENOMEM;
-		goto failed_put_clk;
-	}
-
-	/* Initialize private data */
-	fbi = info->par;
-	fbi->info = info;
-	fbi->clk = clk;
-	fbi->dev = info->dev = &pdev->dev;
-	fbi->panel_rbswap = mi->panel_rbswap;
-	fbi->is_blanked = 0;
-	fbi->active = mi->active;
-
-	/*
-	 * Initialise static fb parameters.
-	 */
-	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
-		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
-	info->node = -1;
-	strlcpy(info->fix.id, mi->id, 16);
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux = 0;
-	info->fix.xpanstep = 0;
-	info->fix.ypanstep = 0;
-	info->fix.ywrapstep = 0;
-	info->fix.mmio_start = res->start;
-	info->fix.mmio_len = resource_size(res);
-	info->fix.accel = FB_ACCEL_NONE;
-	info->fbops = &pxa168fb_ops;
-	info->pseudo_palette = fbi->pseudo_palette;
-
-	/*
-	 * Map LCD controller registers.
-	 */
-	fbi->reg_base = devm_ioremap_nocache(&pdev->dev, res->start,
-					     resource_size(res));
-	if (fbi->reg_base == NULL) {
-		ret = -ENOMEM;
-		goto failed_free_info;
-	}
-
-	/*
-	 * Allocate framebuffer memory.
-	 */
-	info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE);
-
-	info->screen_base = dma_alloc_writecombine(fbi->dev, info->fix.smem_len,
-						&fbi->fb_start_dma, GFP_KERNEL);
-	if (info->screen_base == NULL) {
-		ret = -ENOMEM;
-		goto failed_free_info;
-	}
-
-	info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
-	set_graphics_start(info, 0, 0);
-
-	/*
-	 * Set video mode according to platform data.
-	 */
-	set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1);
-
-	fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist);
-
-	/*
-	 * init video mode data.
-	 */
-	pxa168fb_init_mode(info, mi);
-
-	/*
-	 * Fill in sane defaults.
-	 */
-	ret = pxa168fb_check_var(&info->var, info);
-	if (ret)
-		goto failed_free_fbmem;
-
-	/*
-	 * enable controller clock
-	 */
-	clk_enable(fbi->clk);
-
-	pxa168fb_set_par(info);
-
-	/*
-	 * Configure default register values.
-	 */
-	writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR);
-	writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL);
-	writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1);
-	writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN);
-	writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
-	writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
-		fbi->reg_base + LCD_SPU_SRAM_PARA1);
-
-	/*
-	 * Allocate color map.
-	 */
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		ret = -ENOMEM;
-		goto failed_free_clk;
-	}
-
-	/*
-	 * Register irq handler.
-	 */
-	ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
-			       IRQF_SHARED, info->fix.id, fbi);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "unable to request IRQ\n");
-		ret = -ENXIO;
-		goto failed_free_cmap;
-	}
-
-	/*
-	 * Enable GFX interrupt
-	 */
-	writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA);
-
-	/*
-	 * Register framebuffer.
-	 */
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
-		ret = -ENXIO;
-		goto failed_free_cmap;
-	}
-
-	platform_set_drvdata(pdev, fbi);
-	return 0;
-
-failed_free_cmap:
-	fb_dealloc_cmap(&info->cmap);
-failed_free_clk:
-	clk_disable(fbi->clk);
-failed_free_fbmem:
-	dma_free_coherent(fbi->dev, info->fix.smem_len,
-			info->screen_base, fbi->fb_start_dma);
-failed_free_info:
-	kfree(info);
-failed_put_clk:
-	clk_put(clk);
-
-	dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret);
-	return ret;
-}
-
-static int pxa168fb_remove(struct platform_device *pdev)
-{
-	struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
-	struct fb_info *info;
-	int irq;
-	unsigned int data;
-
-	if (!fbi)
-		return 0;
-
-	/* disable DMA transfer */
-	data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
-	data &= ~CFG_GRA_ENA_MASK;
-	writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
-
-	info = fbi->info;
-
-	unregister_framebuffer(info);
-
-	writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
-
-	if (info->cmap.len)
-		fb_dealloc_cmap(&info->cmap);
-
-	irq = platform_get_irq(pdev, 0);
-
-	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
-				info->screen_base, info->fix.smem_start);
-
-	clk_disable(fbi->clk);
-	clk_put(fbi->clk);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static struct platform_driver pxa168fb_driver = {
-	.driver		= {
-		.name	= "pxa168-fb",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= pxa168fb_probe,
-	.remove		= pxa168fb_remove,
-};
-
-module_platform_driver(pxa168fb_driver);
-
-MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
-	      "Green Wan <gwan@marvell.com>");
-MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
deleted file mode 100644
index eee09279c524..000000000000
--- a/drivers/video/pxa168fb.h
+++ /dev/null
@@ -1,558 +0,0 @@
-#ifndef __PXA168FB_H__
-#define __PXA168FB_H__
-
-/* ------------< LCD register >------------ */
-/* Video Frame 0&1 start address registers */
-#define	LCD_SPU_DMA_START_ADDR_Y0		0x00C0
-#define	LCD_SPU_DMA_START_ADDR_U0		0x00C4
-#define	LCD_SPU_DMA_START_ADDR_V0		0x00C8
-#define LCD_CFG_DMA_START_ADDR_0		0x00CC /* Cmd address */
-#define	LCD_SPU_DMA_START_ADDR_Y1		0x00D0
-#define	LCD_SPU_DMA_START_ADDR_U1		0x00D4
-#define	LCD_SPU_DMA_START_ADDR_V1		0x00D8
-#define LCD_CFG_DMA_START_ADDR_1		0x00DC /* Cmd address */
-
-/* YC & UV Pitch */
-#define LCD_SPU_DMA_PITCH_YC			0x00E0
-#define     SPU_DMA_PITCH_C(c)			((c) << 16)
-#define     SPU_DMA_PITCH_Y(y)			(y)
-#define LCD_SPU_DMA_PITCH_UV			0x00E4
-#define     SPU_DMA_PITCH_V(v)			((v) << 16)
-#define     SPU_DMA_PITCH_U(u)			(u)
-
-/* Video Starting Point on Screen Register */
-#define LCD_SPUT_DMA_OVSA_HPXL_VLN		0x00E8
-#define     CFG_DMA_OVSA_VLN(y)			((y) << 16) /* 0~0xfff */
-#define     CFG_DMA_OVSA_HPXL(x)		(x)     /* 0~0xfff */
-
-/* Video Size Register */
-#define LCD_SPU_DMA_HPXL_VLN			0x00EC
-#define     CFG_DMA_VLN(y)			((y) << 16)
-#define     CFG_DMA_HPXL(x)			(x)
-
-/* Video Size After zooming Register */
-#define LCD_SPU_DZM_HPXL_VLN			0x00F0
-#define     CFG_DZM_VLN(y)			((y) << 16)
-#define     CFG_DZM_HPXL(x)			(x)
-
-/* Graphic Frame 0&1 Starting Address Register */
-#define LCD_CFG_GRA_START_ADDR0			0x00F4
-#define LCD_CFG_GRA_START_ADDR1			0x00F8
-
-/* Graphic Frame Pitch */
-#define LCD_CFG_GRA_PITCH			0x00FC
-
-/* Graphic Starting Point on Screen Register */
-#define LCD_SPU_GRA_OVSA_HPXL_VLN		0x0100
-#define     CFG_GRA_OVSA_VLN(y)			((y) << 16)
-#define     CFG_GRA_OVSA_HPXL(x)		(x)
-
-/* Graphic Size Register */
-#define LCD_SPU_GRA_HPXL_VLN			0x0104
-#define     CFG_GRA_VLN(y)			((y) << 16)
-#define     CFG_GRA_HPXL(x)			(x)
-
-/* Graphic Size after Zooming Register */
-#define LCD_SPU_GZM_HPXL_VLN			0x0108
-#define     CFG_GZM_VLN(y)			((y) << 16)
-#define     CFG_GZM_HPXL(x)			(x)
-
-/* HW Cursor Starting Point on Screen Register */
-#define LCD_SPU_HWC_OVSA_HPXL_VLN		0x010C
-#define     CFG_HWC_OVSA_VLN(y)			((y) << 16)
-#define     CFG_HWC_OVSA_HPXL(x)		(x)
-
-/* HW Cursor Size */
-#define LCD_SPU_HWC_HPXL_VLN			0x0110
-#define     CFG_HWC_VLN(y)			((y) << 16)
-#define     CFG_HWC_HPXL(x)			(x)
-
-/* Total Screen Size Register */
-#define LCD_SPUT_V_H_TOTAL			0x0114
-#define     CFG_V_TOTAL(y)			((y) << 16)
-#define     CFG_H_TOTAL(x)			(x)
-
-/* Total Screen Active Size Register */
-#define LCD_SPU_V_H_ACTIVE			0x0118
-#define     CFG_V_ACTIVE(y)			((y) << 16)
-#define     CFG_H_ACTIVE(x)			(x)
-
-/* Screen H&V Porch Register */
-#define LCD_SPU_H_PORCH				0x011C
-#define     CFG_H_BACK_PORCH(b)			((b) << 16)
-#define     CFG_H_FRONT_PORCH(f)		(f)
-#define LCD_SPU_V_PORCH				0x0120
-#define     CFG_V_BACK_PORCH(b)			((b) << 16)
-#define     CFG_V_FRONT_PORCH(f)		(f)
-
-/* Screen Blank Color Register */
-#define LCD_SPU_BLANKCOLOR			0x0124
-#define     CFG_BLANKCOLOR_MASK			0x00FFFFFF
-#define     CFG_BLANKCOLOR_R_MASK		0x000000FF
-#define     CFG_BLANKCOLOR_G_MASK		0x0000FF00
-#define     CFG_BLANKCOLOR_B_MASK		0x00FF0000
-
-/* HW Cursor Color 1&2 Register */
-#define LCD_SPU_ALPHA_COLOR1			0x0128
-#define     CFG_HWC_COLOR1			0x00FFFFFF
-#define     CFG_HWC_COLOR1_R(red)		((red) << 16)
-#define     CFG_HWC_COLOR1_G(green)		((green) << 8)
-#define     CFG_HWC_COLOR1_B(blue)		(blue)
-#define     CFG_HWC_COLOR1_R_MASK		0x000000FF
-#define     CFG_HWC_COLOR1_G_MASK		0x0000FF00
-#define     CFG_HWC_COLOR1_B_MASK		0x00FF0000
-#define LCD_SPU_ALPHA_COLOR2			0x012C
-#define     CFG_HWC_COLOR2			0x00FFFFFF
-#define     CFG_HWC_COLOR2_R_MASK		0x000000FF
-#define     CFG_HWC_COLOR2_G_MASK		0x0000FF00
-#define     CFG_HWC_COLOR2_B_MASK		0x00FF0000
-
-/* Video YUV Color Key Control */
-#define LCD_SPU_COLORKEY_Y			0x0130
-#define     CFG_CKEY_Y2(y2)			((y2) << 24)
-#define     CFG_CKEY_Y2_MASK			0xFF000000
-#define     CFG_CKEY_Y1(y1)			((y1) << 16)
-#define     CFG_CKEY_Y1_MASK			0x00FF0000
-#define     CFG_CKEY_Y(y)			((y) << 8)
-#define     CFG_CKEY_Y_MASK			0x0000FF00
-#define     CFG_ALPHA_Y(y)			(y)
-#define     CFG_ALPHA_Y_MASK			0x000000FF
-#define LCD_SPU_COLORKEY_U			0x0134
-#define     CFG_CKEY_U2(u2)			((u2) << 24)
-#define     CFG_CKEY_U2_MASK			0xFF000000
-#define     CFG_CKEY_U1(u1)			((u1) << 16)
-#define     CFG_CKEY_U1_MASK			0x00FF0000
-#define     CFG_CKEY_U(u)			((u) << 8)
-#define     CFG_CKEY_U_MASK			0x0000FF00
-#define     CFG_ALPHA_U(u)			(u)
-#define     CFG_ALPHA_U_MASK			0x000000FF
-#define LCD_SPU_COLORKEY_V			0x0138
-#define     CFG_CKEY_V2(v2)			((v2) << 24)
-#define     CFG_CKEY_V2_MASK			0xFF000000
-#define     CFG_CKEY_V1(v1)			((v1) << 16)
-#define     CFG_CKEY_V1_MASK			0x00FF0000
-#define     CFG_CKEY_V(v)			((v) << 8)
-#define     CFG_CKEY_V_MASK			0x0000FF00
-#define     CFG_ALPHA_V(v)			(v)
-#define     CFG_ALPHA_V_MASK			0x000000FF
-
-/* SPI Read Data Register */
-#define LCD_SPU_SPI_RXDATA			0x0140
-
-/* Smart Panel Read Data Register */
-#define LCD_SPU_ISA_RSDATA			0x0144
-#define     ISA_RXDATA_16BIT_1_DATA_MASK	0x000000FF
-#define     ISA_RXDATA_16BIT_2_DATA_MASK	0x0000FF00
-#define     ISA_RXDATA_16BIT_3_DATA_MASK	0x00FF0000
-#define     ISA_RXDATA_16BIT_4_DATA_MASK	0xFF000000
-#define     ISA_RXDATA_32BIT_1_DATA_MASK	0x00FFFFFF
-
-/* HWC SRAM Read Data Register */
-#define LCD_SPU_HWC_RDDAT			0x0158
-
-/* Gamma Table SRAM Read Data Register */
-#define LCD_SPU_GAMMA_RDDAT			0x015c
-#define     CFG_GAMMA_RDDAT_MASK		0x000000FF
-
-/* Palette Table SRAM Read Data Register */
-#define LCD_SPU_PALETTE_RDDAT			0x0160
-#define     CFG_PALETTE_RDDAT_MASK		0x00FFFFFF
-
-/* I/O Pads Input Read Only Register */
-#define LCD_SPU_IOPAD_IN			0x0178
-#define     CFG_IOPAD_IN_MASK			0x0FFFFFFF
-
-/* Reserved Read Only Registers */
-#define LCD_CFG_RDREG5F				0x017C
-#define     IRE_FRAME_CNT_MASK			0x000000C0
-#define     IPE_FRAME_CNT_MASK			0x00000030
-#define     GRA_FRAME_CNT_MASK			0x0000000C  /* Graphic */
-#define     DMA_FRAME_CNT_MASK			0x00000003  /* Video */
-
-/* SPI Control Register. */
-#define LCD_SPU_SPI_CTRL			0x0180
-#define     CFG_SCLKCNT(div)			((div) << 24)  /* 0xFF~0x2 */
-#define     CFG_SCLKCNT_MASK			0xFF000000
-#define     CFG_RXBITS(rx)			((rx) << 16)   /* 0x1F~0x1 */
-#define     CFG_RXBITS_MASK			0x00FF0000
-#define     CFG_TXBITS(tx)			((tx) << 8)    /* 0x1F~0x1 */
-#define     CFG_TXBITS_MASK			0x0000FF00
-#define     CFG_CLKINV(clk)			((clk) << 7)
-#define     CFG_CLKINV_MASK			0x00000080
-#define     CFG_KEEPXFER(transfer)		((transfer) << 6)
-#define     CFG_KEEPXFER_MASK			0x00000040
-#define     CFG_RXBITSTO0(rx)			((rx) << 5)
-#define     CFG_RXBITSTO0_MASK			0x00000020
-#define     CFG_TXBITSTO0(tx)			((tx) << 4)
-#define     CFG_TXBITSTO0_MASK			0x00000010
-#define     CFG_SPI_ENA(spi)			((spi) << 3)
-#define     CFG_SPI_ENA_MASK			0x00000008
-#define     CFG_SPI_SEL(spi)			((spi) << 2)
-#define     CFG_SPI_SEL_MASK			0x00000004
-#define     CFG_SPI_3W4WB(wire)			((wire) << 1)
-#define     CFG_SPI_3W4WB_MASK			0x00000002
-#define     CFG_SPI_START(start)		(start)
-#define     CFG_SPI_START_MASK			0x00000001
-
-/* SPI Tx Data Register */
-#define LCD_SPU_SPI_TXDATA			0x0184
-
-/*
-   1. Smart Pannel 8-bit Bus Control Register.
-   2. AHB Slave Path Data Port Register
-*/
-#define LCD_SPU_SMPN_CTRL			0x0188
-
-/* DMA Control 0 Register */
-#define LCD_SPU_DMA_CTRL0			0x0190
-#define     CFG_NOBLENDING(nb)			((nb) << 31)
-#define     CFG_NOBLENDING_MASK			0x80000000
-#define     CFG_GAMMA_ENA(gn)			((gn) << 30)
-#define     CFG_GAMMA_ENA_MASK			0x40000000
-#define     CFG_CBSH_ENA(cn)			((cn) << 29)
-#define     CFG_CBSH_ENA_MASK			0x20000000
-#define     CFG_PALETTE_ENA(pn)			((pn) << 28)
-#define     CFG_PALETTE_ENA_MASK		0x10000000
-#define     CFG_ARBFAST_ENA(an)			((an) << 27)
-#define     CFG_ARBFAST_ENA_MASK		0x08000000
-#define     CFG_HWC_1BITMOD(mode)		((mode) << 26)
-#define     CFG_HWC_1BITMOD_MASK		0x04000000
-#define     CFG_HWC_1BITENA(mn)			((mn) << 25)
-#define     CFG_HWC_1BITENA_MASK		0x02000000
-#define     CFG_HWC_ENA(cn)		        ((cn) << 24)
-#define     CFG_HWC_ENA_MASK			0x01000000
-#define     CFG_DMAFORMAT(dmaformat)		((dmaformat) << 20)
-#define     CFG_DMAFORMAT_MASK			0x00F00000
-#define     CFG_GRAFORMAT(graformat)		((graformat) << 16)
-#define     CFG_GRAFORMAT_MASK			0x000F0000
-/* for graphic part */
-#define     CFG_GRA_FTOGGLE(toggle)		((toggle) << 15)
-#define     CFG_GRA_FTOGGLE_MASK		0x00008000
-#define     CFG_GRA_HSMOOTH(smooth)		((smooth) << 14)
-#define     CFG_GRA_HSMOOTH_MASK		0x00004000
-#define     CFG_GRA_TSTMODE(test)		((test) << 13)
-#define     CFG_GRA_TSTMODE_MASK		0x00002000
-#define     CFG_GRA_SWAPRB(swap)		((swap) << 12)
-#define     CFG_GRA_SWAPRB_MASK			0x00001000
-#define     CFG_GRA_SWAPUV(swap)		((swap) << 11)
-#define     CFG_GRA_SWAPUV_MASK			0x00000800
-#define     CFG_GRA_SWAPYU(swap)		((swap) << 10)
-#define     CFG_GRA_SWAPYU_MASK			0x00000400
-#define     CFG_YUV2RGB_GRA(cvrt)		((cvrt) << 9)
-#define     CFG_YUV2RGB_GRA_MASK		0x00000200
-#define     CFG_GRA_ENA(gra)			((gra) << 8)
-#define     CFG_GRA_ENA_MASK			0x00000100
-/* for video part */
-#define     CFG_DMA_FTOGGLE(toggle)		((toggle) << 7)
-#define     CFG_DMA_FTOGGLE_MASK		0x00000080
-#define     CFG_DMA_HSMOOTH(smooth)		((smooth) << 6)
-#define     CFG_DMA_HSMOOTH_MASK		0x00000040
-#define     CFG_DMA_TSTMODE(test)		((test) << 5)
-#define     CFG_DMA_TSTMODE_MASK		0x00000020
-#define     CFG_DMA_SWAPRB(swap)		((swap) << 4)
-#define     CFG_DMA_SWAPRB_MASK			0x00000010
-#define     CFG_DMA_SWAPUV(swap)		((swap) << 3)
-#define     CFG_DMA_SWAPUV_MASK			0x00000008
-#define     CFG_DMA_SWAPYU(swap)		((swap) << 2)
-#define     CFG_DMA_SWAPYU_MASK			0x00000004
-#define     CFG_DMA_SWAP_MASK			0x0000001C
-#define     CFG_YUV2RGB_DMA(cvrt)		((cvrt) << 1)
-#define     CFG_YUV2RGB_DMA_MASK		0x00000002
-#define     CFG_DMA_ENA(video)			(video)
-#define     CFG_DMA_ENA_MASK			0x00000001
-
-/* DMA Control 1 Register */
-#define LCD_SPU_DMA_CTRL1			0x0194
-#define     CFG_FRAME_TRIG(trig)		((trig) << 31)
-#define     CFG_FRAME_TRIG_MASK			0x80000000
-#define     CFG_VSYNC_TRIG(trig)		((trig) << 28)
-#define     CFG_VSYNC_TRIG_MASK			0x70000000
-#define     CFG_VSYNC_INV(inv)			((inv) << 27)
-#define     CFG_VSYNC_INV_MASK			0x08000000
-#define     CFG_COLOR_KEY_MODE(cmode)		((cmode) << 24)
-#define     CFG_COLOR_KEY_MASK			0x07000000
-#define     CFG_CARRY(carry)			((carry) << 23)
-#define     CFG_CARRY_MASK			0x00800000
-#define     CFG_LNBUF_ENA(lnbuf)		((lnbuf) << 22)
-#define     CFG_LNBUF_ENA_MASK			0x00400000
-#define     CFG_GATED_ENA(gated)		((gated) << 21)
-#define     CFG_GATED_ENA_MASK			0x00200000
-#define     CFG_PWRDN_ENA(power)		((power) << 20)
-#define     CFG_PWRDN_ENA_MASK			0x00100000
-#define     CFG_DSCALE(dscale)			((dscale) << 18)
-#define     CFG_DSCALE_MASK			0x000C0000
-#define     CFG_ALPHA_MODE(amode)		((amode) << 16)
-#define     CFG_ALPHA_MODE_MASK			0x00030000
-#define     CFG_ALPHA(alpha)			((alpha) << 8)
-#define     CFG_ALPHA_MASK			0x0000FF00
-#define     CFG_PXLCMD(pxlcmd)			(pxlcmd)
-#define     CFG_PXLCMD_MASK			0x000000FF
-
-/* SRAM Control Register */
-#define LCD_SPU_SRAM_CTRL			0x0198
-#define     CFG_SRAM_INIT_WR_RD(mode)		((mode) << 14)
-#define     CFG_SRAM_INIT_WR_RD_MASK		0x0000C000
-#define     CFG_SRAM_ADDR_LCDID(id)		((id) << 8)
-#define     CFG_SRAM_ADDR_LCDID_MASK		0x00000F00
-#define     CFG_SRAM_ADDR(addr)			(addr)
-#define     CFG_SRAM_ADDR_MASK			0x000000FF
-
-/* SRAM Write Data Register */
-#define LCD_SPU_SRAM_WRDAT			0x019C
-
-/* SRAM RTC/WTC Control Register */
-#define LCD_SPU_SRAM_PARA0			0x01A0
-
-/* SRAM Power Down Control Register */
-#define LCD_SPU_SRAM_PARA1			0x01A4
-#define     CFG_CSB_256x32(hwc)			((hwc) << 15)	/* HWC */
-#define     CFG_CSB_256x32_MASK			0x00008000
-#define     CFG_CSB_256x24(palette)		((palette) << 14)	/* Palette */
-#define     CFG_CSB_256x24_MASK			0x00004000
-#define     CFG_CSB_256x8(gamma)		((gamma) << 13)	/* Gamma */
-#define     CFG_CSB_256x8_MASK			0x00002000
-#define     CFG_PDWN256x32(pdwn)		((pdwn) << 7)	/* HWC */
-#define     CFG_PDWN256x32_MASK			0x00000080
-#define     CFG_PDWN256x24(pdwn)		((pdwn) << 6)	/* Palette */
-#define     CFG_PDWN256x24_MASK			0x00000040
-#define     CFG_PDWN256x8(pdwn)			((pdwn) << 5)	/* Gamma */
-#define     CFG_PDWN256x8_MASK			0x00000020
-#define     CFG_PDWN32x32(pdwn)			((pdwn) << 3)
-#define     CFG_PDWN32x32_MASK			0x00000008
-#define     CFG_PDWN16x66(pdwn)			((pdwn) << 2)
-#define     CFG_PDWN16x66_MASK			0x00000004
-#define     CFG_PDWN32x66(pdwn)			((pdwn) << 1)
-#define     CFG_PDWN32x66_MASK			0x00000002
-#define     CFG_PDWN64x66(pdwn)			(pdwn)
-#define     CFG_PDWN64x66_MASK			0x00000001
-
-/* Smart or Dumb Panel Clock Divider */
-#define LCD_CFG_SCLK_DIV			0x01A8
-#define     SCLK_SOURCE_SELECT(src)		((src) << 31)
-#define     SCLK_SOURCE_SELECT_MASK		0x80000000
-#define     CLK_FRACDIV(frac)			((frac) << 16)
-#define     CLK_FRACDIV_MASK			0x0FFF0000
-#define     CLK_INT_DIV(div)			(div)
-#define     CLK_INT_DIV_MASK			0x0000FFFF
-
-/* Video Contrast Register */
-#define LCD_SPU_CONTRAST			0x01AC
-#define     CFG_BRIGHTNESS(bright)		((bright) << 16)
-#define     CFG_BRIGHTNESS_MASK			0xFFFF0000
-#define     CFG_CONTRAST(contrast)		(contrast)
-#define     CFG_CONTRAST_MASK			0x0000FFFF
-
-/* Video Saturation Register */
-#define LCD_SPU_SATURATION			0x01B0
-#define     CFG_C_MULTS(mult)			((mult) << 16)
-#define     CFG_C_MULTS_MASK			0xFFFF0000
-#define     CFG_SATURATION(sat)			(sat)
-#define     CFG_SATURATION_MASK			0x0000FFFF
-
-/* Video Hue Adjust Register */
-#define LCD_SPU_CBSH_HUE			0x01B4
-#define     CFG_SIN0(sin0)			((sin0) << 16)
-#define     CFG_SIN0_MASK			0xFFFF0000
-#define     CFG_COS0(con0)			(con0)
-#define     CFG_COS0_MASK			0x0000FFFF
-
-/* Dump LCD Panel Control Register */
-#define LCD_SPU_DUMB_CTRL			0x01B8
-#define     CFG_DUMBMODE(mode)			((mode) << 28)
-#define     CFG_DUMBMODE_MASK			0xF0000000
-#define     CFG_LCDGPIO_O(data)			((data) << 20)
-#define     CFG_LCDGPIO_O_MASK			0x0FF00000
-#define     CFG_LCDGPIO_ENA(gpio)		((gpio) << 12)
-#define     CFG_LCDGPIO_ENA_MASK		0x000FF000
-#define     CFG_BIAS_OUT(bias)			((bias) << 8)
-#define     CFG_BIAS_OUT_MASK			0x00000100
-#define     CFG_REVERSE_RGB(rRGB)		((rRGB) << 7)
-#define     CFG_REVERSE_RGB_MASK		0x00000080
-#define     CFG_INV_COMPBLANK(blank)		((blank) << 6)
-#define     CFG_INV_COMPBLANK_MASK		0x00000040
-#define     CFG_INV_COMPSYNC(sync)		((sync) << 5)
-#define     CFG_INV_COMPSYNC_MASK		0x00000020
-#define     CFG_INV_HENA(hena)			((hena) << 4)
-#define     CFG_INV_HENA_MASK			0x00000010
-#define     CFG_INV_VSYNC(vsync)		((vsync) << 3)
-#define     CFG_INV_VSYNC_MASK			0x00000008
-#define     CFG_INV_HSYNC(hsync)		((hsync) << 2)
-#define     CFG_INV_HSYNC_MASK			0x00000004
-#define     CFG_INV_PCLK(pclk)			((pclk) << 1)
-#define     CFG_INV_PCLK_MASK			0x00000002
-#define     CFG_DUMB_ENA(dumb)			(dumb)
-#define     CFG_DUMB_ENA_MASK			0x00000001
-
-/* LCD I/O Pads Control Register */
-#define SPU_IOPAD_CONTROL			0x01BC
-#define     CFG_GRA_VM_ENA(vm)			((vm) << 15)        /* gfx */
-#define     CFG_GRA_VM_ENA_MASK			0x00008000
-#define     CFG_DMA_VM_ENA(vm)			((vm) << 13)	/* video */
-#define     CFG_DMA_VM_ENA_MASK			0x00002000
-#define     CFG_CMD_VM_ENA(vm)			((vm) << 13)
-#define     CFG_CMD_VM_ENA_MASK			0x00000800
-#define     CFG_CSC(csc)			((csc) << 8)	/* csc */
-#define     CFG_CSC_MASK			0x00000300
-#define     CFG_AXICTRL(axi)			((axi) << 4)
-#define     CFG_AXICTRL_MASK			0x000000F0
-#define     CFG_IOPADMODE(iopad)		(iopad)
-#define     CFG_IOPADMODE_MASK			0x0000000F
-
-/* LCD Interrupt Control Register */
-#define SPU_IRQ_ENA				0x01C0
-#define     DMA_FRAME_IRQ0_ENA(irq)		((irq) << 31)
-#define     DMA_FRAME_IRQ0_ENA_MASK		0x80000000
-#define     DMA_FRAME_IRQ1_ENA(irq)		((irq) << 30)
-#define     DMA_FRAME_IRQ1_ENA_MASK		0x40000000
-#define     DMA_FF_UNDERFLOW_ENA(ff)		((ff) << 29)
-#define     DMA_FF_UNDERFLOW_ENA_MASK		0x20000000
-#define     GRA_FRAME_IRQ0_ENA(irq)		((irq) << 27)
-#define     GRA_FRAME_IRQ0_ENA_MASK		0x08000000
-#define     GRA_FRAME_IRQ1_ENA(irq)		((irq) << 26)
-#define     GRA_FRAME_IRQ1_ENA_MASK		0x04000000
-#define     GRA_FF_UNDERFLOW_ENA(ff)		((ff) << 25)
-#define     GRA_FF_UNDERFLOW_ENA_MASK		0x02000000
-#define     VSYNC_IRQ_ENA(vsync_irq)		((vsync_irq) << 23)
-#define     VSYNC_IRQ_ENA_MASK			0x00800000
-#define     DUMB_FRAMEDONE_ENA(fdone)		((fdone) << 22)
-#define     DUMB_FRAMEDONE_ENA_MASK		0x00400000
-#define     TWC_FRAMEDONE_ENA(fdone)		((fdone) << 21)
-#define     TWC_FRAMEDONE_ENA_MASK		0x00200000
-#define     HWC_FRAMEDONE_ENA(fdone)		((fdone) << 20)
-#define     HWC_FRAMEDONE_ENA_MASK		0x00100000
-#define     SLV_IRQ_ENA(irq)			((irq) << 19)
-#define     SLV_IRQ_ENA_MASK			0x00080000
-#define     SPI_IRQ_ENA(irq)			((irq) << 18)
-#define     SPI_IRQ_ENA_MASK			0x00040000
-#define     PWRDN_IRQ_ENA(irq)			((irq) << 17)
-#define     PWRDN_IRQ_ENA_MASK			0x00020000
-#define     ERR_IRQ_ENA(irq)			((irq) << 16)
-#define     ERR_IRQ_ENA_MASK			0x00010000
-#define     CLEAN_SPU_IRQ_ISR(irq)		(irq)
-#define     CLEAN_SPU_IRQ_ISR_MASK		0x0000FFFF
-
-/* LCD Interrupt Status Register */
-#define SPU_IRQ_ISR				0x01C4
-#define     DMA_FRAME_IRQ0(irq)			((irq) << 31)
-#define     DMA_FRAME_IRQ0_MASK			0x80000000
-#define     DMA_FRAME_IRQ1(irq)			((irq) << 30)
-#define     DMA_FRAME_IRQ1_MASK			0x40000000
-#define     DMA_FF_UNDERFLOW(ff)		((ff) << 29)
-#define     DMA_FF_UNDERFLOW_MASK		0x20000000
-#define     GRA_FRAME_IRQ0(irq)			((irq) << 27)
-#define     GRA_FRAME_IRQ0_MASK			0x08000000
-#define     GRA_FRAME_IRQ1(irq)			((irq) << 26)
-#define     GRA_FRAME_IRQ1_MASK			0x04000000
-#define     GRA_FF_UNDERFLOW(ff)		((ff) << 25)
-#define     GRA_FF_UNDERFLOW_MASK		0x02000000
-#define     VSYNC_IRQ(vsync_irq)		((vsync_irq) << 23)
-#define     VSYNC_IRQ_MASK			0x00800000
-#define     DUMB_FRAMEDONE(fdone)		((fdone) << 22)
-#define     DUMB_FRAMEDONE_MASK			0x00400000
-#define     TWC_FRAMEDONE(fdone)		((fdone) << 21)
-#define     TWC_FRAMEDONE_MASK			0x00200000
-#define     HWC_FRAMEDONE(fdone)		((fdone) << 20)
-#define     HWC_FRAMEDONE_MASK			0x00100000
-#define     SLV_IRQ(irq)			((irq) << 19)
-#define     SLV_IRQ_MASK			0x00080000
-#define     SPI_IRQ(irq)			((irq) << 18)
-#define     SPI_IRQ_MASK			0x00040000
-#define     PWRDN_IRQ(irq)			((irq) << 17)
-#define     PWRDN_IRQ_MASK			0x00020000
-#define     ERR_IRQ(irq)			((irq) << 16)
-#define     ERR_IRQ_MASK			0x00010000
-/* read-only */
-#define     DMA_FRAME_IRQ0_LEVEL_MASK		0x00008000
-#define     DMA_FRAME_IRQ1_LEVEL_MASK		0x00004000
-#define     DMA_FRAME_CNT_ISR_MASK		0x00003000
-#define     GRA_FRAME_IRQ0_LEVEL_MASK		0x00000800
-#define     GRA_FRAME_IRQ1_LEVEL_MASK		0x00000400
-#define     GRA_FRAME_CNT_ISR_MASK		0x00000300
-#define     VSYNC_IRQ_LEVEL_MASK		0x00000080
-#define     DUMB_FRAMEDONE_LEVEL_MASK		0x00000040
-#define     TWC_FRAMEDONE_LEVEL_MASK		0x00000020
-#define     HWC_FRAMEDONE_LEVEL_MASK		0x00000010
-#define     SLV_FF_EMPTY_MASK			0x00000008
-#define     DMA_FF_ALLEMPTY_MASK		0x00000004
-#define     GRA_FF_ALLEMPTY_MASK		0x00000002
-#define     PWRDN_IRQ_LEVEL_MASK		0x00000001
-
-
-/*
- * defined Video Memory Color format for DMA control 0 register
- * DMA0 bit[23:20]
- */
-#define VMODE_RGB565		0x0
-#define VMODE_RGB1555		0x1
-#define VMODE_RGB888PACKED	0x2
-#define VMODE_RGB888UNPACKED	0x3
-#define VMODE_RGBA888		0x4
-#define VMODE_YUV422PACKED	0x5
-#define VMODE_YUV422PLANAR	0x6
-#define VMODE_YUV420PLANAR	0x7
-#define VMODE_SMPNCMD		0x8
-#define VMODE_PALETTE4BIT	0x9
-#define VMODE_PALETTE8BIT	0xa
-#define VMODE_RESERVED		0xb
-
-/*
- * defined Graphic Memory Color format for DMA control 0 register
- * DMA0 bit[19:16]
- */
-#define GMODE_RGB565		0x0
-#define GMODE_RGB1555		0x1
-#define GMODE_RGB888PACKED	0x2
-#define GMODE_RGB888UNPACKED	0x3
-#define GMODE_RGBA888		0x4
-#define GMODE_YUV422PACKED	0x5
-#define GMODE_YUV422PLANAR	0x6
-#define GMODE_YUV420PLANAR	0x7
-#define GMODE_SMPNCMD		0x8
-#define GMODE_PALETTE4BIT	0x9
-#define GMODE_PALETTE8BIT	0xa
-#define GMODE_RESERVED		0xb
-
-/*
- * define for DMA control 1 register
- */
-#define DMA1_FRAME_TRIG		31 /* bit location */
-#define DMA1_VSYNC_MODE		28
-#define DMA1_VSYNC_INV		27
-#define DMA1_CKEY		24
-#define DMA1_CARRY		23
-#define DMA1_LNBUF_ENA		22
-#define DMA1_GATED_ENA		21
-#define DMA1_PWRDN_ENA		20
-#define DMA1_DSCALE		18
-#define DMA1_ALPHA_MODE		16
-#define DMA1_ALPHA		08
-#define DMA1_PXLCMD		00
-
-/*
- * defined for Configure Dumb Mode
- * DUMB LCD Panel bit[31:28]
- */
-#define DUMB16_RGB565_0		0x0
-#define DUMB16_RGB565_1		0x1
-#define DUMB18_RGB666_0		0x2
-#define DUMB18_RGB666_1		0x3
-#define DUMB12_RGB444_0		0x4
-#define DUMB12_RGB444_1		0x5
-#define DUMB24_RGB888_0		0x6
-#define DUMB_BLANK		0x7
-
-/*
- * defined for Configure I/O Pin Allocation Mode
- * LCD LCD I/O Pads control register bit[3:0]
- */
-#define IOPAD_DUMB24		0x0
-#define IOPAD_DUMB18SPI		0x1
-#define IOPAD_DUMB18GPIO	0x2
-#define IOPAD_DUMB16SPI		0x3
-#define IOPAD_DUMB16GPIO	0x4
-#define IOPAD_DUMB12		0x5
-#define IOPAD_SMART18SPI	0x6
-#define IOPAD_SMART16SPI	0x7
-#define IOPAD_SMART8BOTH	0x8
-
-#endif /* __PXA168FB_H__ */
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
deleted file mode 100644
index 417f9a27eb7d..000000000000
--- a/drivers/video/pxa3xx-gcu.c
+++ /dev/null
@@ -1,724 +0,0 @@
-/*
- *  pxa3xx-gcu.c - Linux kernel module for PXA3xx graphics controllers
- *
- *  This driver needs a DirectFB counterpart in user space, communication
- *  is handled via mmap()ed memory areas and an ioctl.
- *
- *  Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- *  Copyright (c) 2009 Janine Kropp <nin@directfb.org>
- *  Copyright (c) 2009 Denis Oliver Kropp <dok@directfb.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * WARNING: This controller is attached to System Bus 2 of the PXA which
- * needs its arbiter to be enabled explicitly (CKENB & 1<<9).
- * There is currently no way to do this from Linux, so you need to teach
- * your bootloader for now.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/miscdevice.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/uaccess.h>
-#include <linux/ioctl.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-
-#include "pxa3xx-gcu.h"
-
-#define DRV_NAME	"pxa3xx-gcu"
-#define MISCDEV_MINOR	197
-
-#define REG_GCCR	0x00
-#define GCCR_SYNC_CLR	(1 << 9)
-#define GCCR_BP_RST	(1 << 8)
-#define GCCR_ABORT	(1 << 6)
-#define GCCR_STOP	(1 << 4)
-
-#define REG_GCISCR	0x04
-#define REG_GCIECR	0x08
-#define REG_GCRBBR	0x20
-#define REG_GCRBLR	0x24
-#define REG_GCRBHR	0x28
-#define REG_GCRBTR	0x2C
-#define REG_GCRBEXHR	0x30
-
-#define IE_EOB		(1 << 0)
-#define IE_EEOB		(1 << 5)
-#define IE_ALL		0xff
-
-#define SHARED_SIZE	PAGE_ALIGN(sizeof(struct pxa3xx_gcu_shared))
-
-/* #define PXA3XX_GCU_DEBUG */
-/* #define PXA3XX_GCU_DEBUG_TIMER */
-
-#ifdef PXA3XX_GCU_DEBUG
-#define QDUMP(msg)					\
-	do {						\
-		QPRINT(priv, KERN_DEBUG, msg);		\
-	} while (0)
-#else
-#define QDUMP(msg)	do {} while (0)
-#endif
-
-#define QERROR(msg)					\
-	do {						\
-		QPRINT(priv, KERN_ERR, msg);		\
-	} while (0)
-
-struct pxa3xx_gcu_batch {
-	struct pxa3xx_gcu_batch *next;
-	u32			*ptr;
-	dma_addr_t		 phys;
-	unsigned long		 length;
-};
-
-struct pxa3xx_gcu_priv {
-	void __iomem		 *mmio_base;
-	struct clk		 *clk;
-	struct pxa3xx_gcu_shared *shared;
-	dma_addr_t		  shared_phys;
-	struct resource		 *resource_mem;
-	struct miscdevice	  misc_dev;
-	wait_queue_head_t	  wait_idle;
-	wait_queue_head_t	  wait_free;
-	spinlock_t		  spinlock;
-	struct timeval 		  base_time;
-
-	struct pxa3xx_gcu_batch *free;
-	struct pxa3xx_gcu_batch *ready;
-	struct pxa3xx_gcu_batch *ready_last;
-	struct pxa3xx_gcu_batch *running;
-};
-
-static inline unsigned long
-gc_readl(struct pxa3xx_gcu_priv *priv, unsigned int off)
-{
-	return __raw_readl(priv->mmio_base + off);
-}
-
-static inline void
-gc_writel(struct pxa3xx_gcu_priv *priv, unsigned int off, unsigned long val)
-{
-	__raw_writel(val, priv->mmio_base + off);
-}
-
-#define QPRINT(priv, level, msg)					\
-	do {								\
-		struct timeval tv;					\
-		struct pxa3xx_gcu_shared *shared = priv->shared;	\
-		u32 base = gc_readl(priv, REG_GCRBBR);			\
-									\
-		do_gettimeofday(&tv);					\
-									\
-		printk(level "%ld.%03ld.%03ld - %-17s: %-21s (%s, "	\
-			"STATUS "					\
-			"0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, "	\
-			"T %5ld)\n",					\
-			tv.tv_sec - priv->base_time.tv_sec,		\
-			tv.tv_usec / 1000, tv.tv_usec % 1000,		\
-			__func__, msg,					\
-			shared->hw_running ? "running" : "   idle",	\
-			gc_readl(priv, REG_GCISCR),			\
-			gc_readl(priv, REG_GCRBBR),			\
-			gc_readl(priv, REG_GCRBLR),			\
-			(gc_readl(priv, REG_GCRBEXHR) - base) / 4,	\
-			(gc_readl(priv, REG_GCRBHR) - base) / 4,	\
-			(gc_readl(priv, REG_GCRBTR) - base) / 4);	\
-	} while (0)
-
-static void
-pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
-{
-	QDUMP("RESET");
-
-	/* disable interrupts */
-	gc_writel(priv, REG_GCIECR, 0);
-
-	/* reset hardware */
-	gc_writel(priv, REG_GCCR, GCCR_ABORT);
-	gc_writel(priv, REG_GCCR, 0);
-
-	memset(priv->shared, 0, SHARED_SIZE);
-	priv->shared->buffer_phys = priv->shared_phys;
-	priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
-
-	do_gettimeofday(&priv->base_time);
-
-	/* set up the ring buffer pointers */
-	gc_writel(priv, REG_GCRBLR, 0);
-	gc_writel(priv, REG_GCRBBR, priv->shared_phys);
-	gc_writel(priv, REG_GCRBTR, priv->shared_phys);
-
-	/* enable all IRQs except EOB */
-	gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
-}
-
-static void
-dump_whole_state(struct pxa3xx_gcu_priv *priv)
-{
-	struct pxa3xx_gcu_shared *sh = priv->shared;
-	u32 base = gc_readl(priv, REG_GCRBBR);
-
-	QDUMP("DUMP");
-
-	printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
-		"%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
-		sh->hw_running ? "running" : "idle   ",
-		gc_readl(priv, REG_GCISCR),
-		gc_readl(priv, REG_GCRBBR),
-		gc_readl(priv, REG_GCRBLR),
-		(gc_readl(priv, REG_GCRBEXHR) - base) / 4,
-		(gc_readl(priv, REG_GCRBHR) - base) / 4,
-		(gc_readl(priv, REG_GCRBTR) - base) / 4);
-}
-
-static void
-flush_running(struct pxa3xx_gcu_priv *priv)
-{
-	struct pxa3xx_gcu_batch *running = priv->running;
-	struct pxa3xx_gcu_batch *next;
-
-	while (running) {
-		next = running->next;
-		running->next = priv->free;
-		priv->free = running;
-		running = next;
-	}
-
-	priv->running = NULL;
-}
-
-static void
-run_ready(struct pxa3xx_gcu_priv *priv)
-{
-	unsigned int num = 0;
-	struct pxa3xx_gcu_shared *shared = priv->shared;
-	struct pxa3xx_gcu_batch	*ready = priv->ready;
-
-	QDUMP("Start");
-
-	BUG_ON(!ready);
-
-	shared->buffer[num++] = 0x05000000;
-
-	while (ready) {
-		shared->buffer[num++] = 0x00000001;
-		shared->buffer[num++] = ready->phys;
-		ready = ready->next;
-	}
-
-	shared->buffer[num++] = 0x05000000;
-	priv->running = priv->ready;
-	priv->ready = priv->ready_last = NULL;
-	gc_writel(priv, REG_GCRBLR, 0);
-	shared->hw_running = 1;
-
-	/* ring base address */
-	gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
-
-	/* ring tail address */
-	gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
-
-	/* ring length */
-	gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
-}
-
-static irqreturn_t
-pxa3xx_gcu_handle_irq(int irq, void *ctx)
-{
-	struct pxa3xx_gcu_priv *priv = ctx;
-	struct pxa3xx_gcu_shared *shared = priv->shared;
-	u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
-
-	QDUMP("-Interrupt");
-
-	if (!status)
-		return IRQ_NONE;
-
-	spin_lock(&priv->spinlock);
-	shared->num_interrupts++;
-
-	if (status & IE_EEOB) {
-		QDUMP(" [EEOB]");
-
-		flush_running(priv);
-		wake_up_all(&priv->wait_free);
-
-		if (priv->ready) {
-			run_ready(priv);
-		} else {
-			/* There is no more data prepared by the userspace.
-			 * Set hw_running = 0 and wait for the next userspace
-			 * kick-off */
-			shared->num_idle++;
-			shared->hw_running = 0;
-
-			QDUMP(" '-> Idle.");
-
-			/* set ring buffer length to zero */
-			gc_writel(priv, REG_GCRBLR, 0);
-
-			wake_up_all(&priv->wait_idle);
-		}
-
-		shared->num_done++;
-	} else {
-		QERROR(" [???]");
-		dump_whole_state(priv);
-	}
-
-	/* Clear the interrupt */
-	gc_writel(priv, REG_GCISCR, status);
-	spin_unlock(&priv->spinlock);
-
-	return IRQ_HANDLED;
-}
-
-static int
-pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
-{
-	int ret = 0;
-
-	QDUMP("Waiting for idle...");
-
-	/* Does not need to be atomic. There's a lock in user space,
-	 * but anyhow, this is just for statistics. */
-	priv->shared->num_wait_idle++;
-
-	while (priv->shared->hw_running) {
-		int num = priv->shared->num_interrupts;
-		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
-
-		ret = wait_event_interruptible_timeout(priv->wait_idle,
-					!priv->shared->hw_running, HZ*4);
-
-		if (ret != 0)
-			break;
-
-		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
-		    priv->shared->num_interrupts == num) {
-			QERROR("TIMEOUT");
-			ret = -ETIMEDOUT;
-			break;
-		}
-	}
-
-	QDUMP("done");
-
-	return ret;
-}
-
-static int
-pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
-{
-	int ret = 0;
-
-	QDUMP("Waiting for free...");
-
-	/* Does not need to be atomic. There's a lock in user space,
-	 * but anyhow, this is just for statistics. */
-	priv->shared->num_wait_free++;
-
-	while (!priv->free) {
-		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
-
-		ret = wait_event_interruptible_timeout(priv->wait_free,
-						       priv->free, HZ*4);
-
-		if (ret < 0)
-			break;
-
-		if (ret > 0)
-			continue;
-
-		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
-			QERROR("TIMEOUT");
-			ret = -ETIMEDOUT;
-			break;
-		}
-	}
-
-	QDUMP("done");
-
-	return ret;
-}
-
-/* Misc device layer */
-
-static inline struct pxa3xx_gcu_priv *to_pxa3xx_gcu_priv(struct file *file)
-{
-	struct miscdevice *dev = file->private_data;
-	return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
-}
-
-/*
- * provide an empty .open callback, so the core sets file->private_data
- * for us.
- */
-static int pxa3xx_gcu_open(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static ssize_t
-pxa3xx_gcu_write(struct file *file, const char *buff,
-		 size_t count, loff_t *offp)
-{
-	int ret;
-	unsigned long flags;
-	struct pxa3xx_gcu_batch	*buffer;
-	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
-
-	int words = count / 4;
-
-	/* Does not need to be atomic. There's a lock in user space,
-	 * but anyhow, this is just for statistics. */
-	priv->shared->num_writes++;
-	priv->shared->num_words += words;
-
-	/* Last word reserved for batch buffer end command */
-	if (words >= PXA3XX_GCU_BATCH_WORDS)
-		return -E2BIG;
-
-	/* Wait for a free buffer */
-	if (!priv->free) {
-		ret = pxa3xx_gcu_wait_free(priv);
-		if (ret < 0)
-			return ret;
-	}
-
-	/*
-	 * Get buffer from free list
-	 */
-	spin_lock_irqsave(&priv->spinlock, flags);
-	buffer = priv->free;
-	priv->free = buffer->next;
-	spin_unlock_irqrestore(&priv->spinlock, flags);
-
-
-	/* Copy data from user into buffer */
-	ret = copy_from_user(buffer->ptr, buff, words * 4);
-	if (ret) {
-		spin_lock_irqsave(&priv->spinlock, flags);
-		buffer->next = priv->free;
-		priv->free = buffer;
-		spin_unlock_irqrestore(&priv->spinlock, flags);
-		return -EFAULT;
-	}
-
-	buffer->length = words;
-
-	/* Append batch buffer end command */
-	buffer->ptr[words] = 0x01000000;
-
-	/*
-	 * Add buffer to ready list
-	 */
-	spin_lock_irqsave(&priv->spinlock, flags);
-
-	buffer->next = NULL;
-
-	if (priv->ready) {
-		BUG_ON(priv->ready_last == NULL);
-
-		priv->ready_last->next = buffer;
-	} else
-		priv->ready = buffer;
-
-	priv->ready_last = buffer;
-
-	if (!priv->shared->hw_running)
-		run_ready(priv);
-
-	spin_unlock_irqrestore(&priv->spinlock, flags);
-
-	return words * 4;
-}
-
-
-static long
-pxa3xx_gcu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	unsigned long flags;
-	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
-
-	switch (cmd) {
-	case PXA3XX_GCU_IOCTL_RESET:
-		spin_lock_irqsave(&priv->spinlock, flags);
-		pxa3xx_gcu_reset(priv);
-		spin_unlock_irqrestore(&priv->spinlock, flags);
-		return 0;
-
-	case PXA3XX_GCU_IOCTL_WAIT_IDLE:
-		return pxa3xx_gcu_wait_idle(priv);
-	}
-
-	return -ENOSYS;
-}
-
-static int
-pxa3xx_gcu_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	unsigned int size = vma->vm_end - vma->vm_start;
-	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
-
-	switch (vma->vm_pgoff) {
-	case 0:
-		/* hand out the shared data area */
-		if (size != SHARED_SIZE)
-			return -EINVAL;
-
-		return dma_mmap_coherent(NULL, vma,
-			priv->shared, priv->shared_phys, size);
-
-	case SHARED_SIZE >> PAGE_SHIFT:
-		/* hand out the MMIO base for direct register access
-		 * from userspace */
-		if (size != resource_size(priv->resource_mem))
-			return -EINVAL;
-
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-		return io_remap_pfn_range(vma, vma->vm_start,
-				priv->resource_mem->start >> PAGE_SHIFT,
-				size, vma->vm_page_prot);
-	}
-
-	return -EINVAL;
-}
-
-
-#ifdef PXA3XX_GCU_DEBUG_TIMER
-static struct timer_list pxa3xx_gcu_debug_timer;
-
-static void pxa3xx_gcu_debug_timedout(unsigned long ptr)
-{
-	struct pxa3xx_gcu_priv *priv = (struct pxa3xx_gcu_priv *) ptr;
-
-	QERROR("Timer DUMP");
-
-	/* init the timer structure */
-	init_timer(&pxa3xx_gcu_debug_timer);
-	pxa3xx_gcu_debug_timer.function = pxa3xx_gcu_debug_timedout;
-	pxa3xx_gcu_debug_timer.data = ptr;
-	pxa3xx_gcu_debug_timer.expires = jiffies + 5*HZ; /* one second */
-
-	add_timer(&pxa3xx_gcu_debug_timer);
-}
-
-static void pxa3xx_gcu_init_debug_timer(void)
-{
-	pxa3xx_gcu_debug_timedout((unsigned long) &pxa3xx_gcu_debug_timer);
-}
-#else
-static inline void pxa3xx_gcu_init_debug_timer(void) {}
-#endif
-
-static int
-pxa3xx_gcu_add_buffer(struct device *dev,
-		      struct pxa3xx_gcu_priv *priv)
-{
-	struct pxa3xx_gcu_batch *buffer;
-
-	buffer = kzalloc(sizeof(struct pxa3xx_gcu_batch), GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	buffer->ptr = dma_alloc_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
-					 &buffer->phys, GFP_KERNEL);
-	if (!buffer->ptr) {
-		kfree(buffer);
-		return -ENOMEM;
-	}
-
-	buffer->next = priv->free;
-	priv->free = buffer;
-
-	return 0;
-}
-
-static void
-pxa3xx_gcu_free_buffers(struct device *dev,
-			struct pxa3xx_gcu_priv *priv)
-{
-	struct pxa3xx_gcu_batch *next, *buffer = priv->free;
-
-	while (buffer) {
-		next = buffer->next;
-
-		dma_free_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
-				  buffer->ptr, buffer->phys);
-
-		kfree(buffer);
-		buffer = next;
-	}
-
-	priv->free = NULL;
-}
-
-static const struct file_operations pxa3xx_gcu_miscdev_fops = {
-	.owner =		THIS_MODULE,
-	.open =			pxa3xx_gcu_open,
-	.write =		pxa3xx_gcu_write,
-	.unlocked_ioctl =	pxa3xx_gcu_ioctl,
-	.mmap =			pxa3xx_gcu_mmap,
-};
-
-static int pxa3xx_gcu_probe(struct platform_device *pdev)
-{
-	int i, ret, irq;
-	struct resource *r;
-	struct pxa3xx_gcu_priv *priv;
-	struct device *dev = &pdev->dev;
-
-	priv = devm_kzalloc(dev, sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	init_waitqueue_head(&priv->wait_idle);
-	init_waitqueue_head(&priv->wait_free);
-	spin_lock_init(&priv->spinlock);
-
-	/* we allocate the misc device structure as part of our own allocation,
-	 * so we can get a pointer to our priv structure later on with
-	 * container_of(). This isn't really necessary as we have a fixed minor
-	 * number anyway, but this is to avoid statics. */
-
-	priv->misc_dev.minor	= MISCDEV_MINOR,
-	priv->misc_dev.name	= DRV_NAME,
-	priv->misc_dev.fops	= &pxa3xx_gcu_miscdev_fops;
-
-	/* handle IO resources */
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	priv->mmio_base = devm_request_and_ioremap(dev, r);
-	if (IS_ERR(priv->mmio_base)) {
-		dev_err(dev, "failed to map I/O memory\n");
-		return PTR_ERR(priv->mmio_base);
-	}
-
-	/* enable the clock */
-	priv->clk = devm_clk_get(dev, NULL);
-	if (IS_ERR(priv->clk)) {
-		dev_err(dev, "failed to get clock\n");
-		return PTR_ERR(priv->clk);
-	}
-
-	/* request the IRQ */
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(dev, "no IRQ defined\n");
-		return -ENODEV;
-	}
-
-	ret = devm_request_irq(dev, irq, pxa3xx_gcu_handle_irq,
-			       0, DRV_NAME, priv);
-	if (ret < 0) {
-		dev_err(dev, "request_irq failed\n");
-		return ret;
-	}
-
-	/* allocate dma memory */
-	priv->shared = dma_alloc_coherent(dev, SHARED_SIZE,
-					  &priv->shared_phys, GFP_KERNEL);
-	if (!priv->shared) {
-		dev_err(dev, "failed to allocate DMA memory\n");
-		return -ENOMEM;
-	}
-
-	/* register misc device */
-	ret = misc_register(&priv->misc_dev);
-	if (ret < 0) {
-		dev_err(dev, "misc_register() for minor %d failed\n",
-			MISCDEV_MINOR);
-		goto err_free_dma;
-	}
-
-	ret = clk_enable(priv->clk);
-	if (ret < 0) {
-		dev_err(dev, "failed to enable clock\n");
-		goto err_misc_deregister;
-	}
-
-	for (i = 0; i < 8; i++) {
-		ret = pxa3xx_gcu_add_buffer(dev, priv);
-		if (ret) {
-			dev_err(dev, "failed to allocate DMA memory\n");
-			goto err_disable_clk;
-		}
-	}
-
-	platform_set_drvdata(pdev, priv);
-	priv->resource_mem = r;
-	pxa3xx_gcu_reset(priv);
-	pxa3xx_gcu_init_debug_timer();
-
-	dev_info(dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
-			(void *) r->start, (void *) priv->shared_phys,
-			SHARED_SIZE, irq);
-	return 0;
-
-err_free_dma:
-	dma_free_coherent(dev, SHARED_SIZE,
-			priv->shared, priv->shared_phys);
-
-err_misc_deregister:
-	misc_deregister(&priv->misc_dev);
-
-err_disable_clk:
-	clk_disable(priv->clk);
-
-	return ret;
-}
-
-static int pxa3xx_gcu_remove(struct platform_device *pdev)
-{
-	struct pxa3xx_gcu_priv *priv = platform_get_drvdata(pdev);
-	struct device *dev = &pdev->dev;
-
-	pxa3xx_gcu_wait_idle(priv);
-	misc_deregister(&priv->misc_dev);
-	dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys);
-	pxa3xx_gcu_free_buffers(dev, priv);
-
-	return 0;
-}
-
-static struct platform_driver pxa3xx_gcu_driver = {
-	.probe	  = pxa3xx_gcu_probe,
-	.remove	 = pxa3xx_gcu_remove,
-	.driver	 = {
-		.owner  = THIS_MODULE,
-		.name   = DRV_NAME,
-	},
-};
-
-module_platform_driver(pxa3xx_gcu_driver);
-
-MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(MISCDEV_MINOR);
-MODULE_AUTHOR("Janine Kropp <nin@directfb.org>, "
-		"Denis Oliver Kropp <dok@directfb.org>, "
-		"Daniel Mack <daniel@caiaq.de>");
diff --git a/drivers/video/pxa3xx-gcu.h b/drivers/video/pxa3xx-gcu.h
deleted file mode 100644
index 0428ed03dc49..000000000000
--- a/drivers/video/pxa3xx-gcu.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef __PXA3XX_GCU_H__
-#define __PXA3XX_GCU_H__
-
-#include <linux/types.h>
-
-/* Number of 32bit words in display list (ring buffer). */
-#define PXA3XX_GCU_BUFFER_WORDS  ((256 * 1024 - 256) / 4)
-
-/* To be increased when breaking the ABI */
-#define PXA3XX_GCU_SHARED_MAGIC  0x30000001
-
-#define PXA3XX_GCU_BATCH_WORDS   8192
-
-struct pxa3xx_gcu_shared {
-	u32            buffer[PXA3XX_GCU_BUFFER_WORDS];
-
-	bool           hw_running;
-
-	unsigned long  buffer_phys;
-
-	unsigned int   num_words;
-	unsigned int   num_writes;
-	unsigned int   num_done;
-	unsigned int   num_interrupts;
-	unsigned int   num_wait_idle;
-	unsigned int   num_wait_free;
-	unsigned int   num_idle;
-
-	u32            magic;
-};
-
-/* Initialization and synchronization.
- * Hardware is started upon write(). */
-#define PXA3XX_GCU_IOCTL_RESET		_IO('G', 0)
-#define PXA3XX_GCU_IOCTL_WAIT_IDLE	_IO('G', 2)
-
-#endif /* __PXA3XX_GCU_H__ */
-
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
deleted file mode 100644
index 1ecd9cec2921..000000000000
--- a/drivers/video/pxafb.c
+++ /dev/null
@@ -1,2332 +0,0 @@
-/*
- *  linux/drivers/video/pxafb.c
- *
- *  Copyright (C) 1999 Eric A. Thomas.
- *  Copyright (C) 2004 Jean-Frederic Clere.
- *  Copyright (C) 2004 Ian Campbell.
- *  Copyright (C) 2004 Jeff Lackey.
- *   Based on sa1100fb.c Copyright (C) 1999 Eric A. Thomas
- *  which in turn is
- *   Based on acornfb.c Copyright (C) Russell King.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- *	        Intel PXA250/210 LCD Controller Frame Buffer Driver
- *
- * Please direct your questions and comments on this driver to the following
- * email address:
- *
- *	linux-arm-kernel@lists.arm.linux.org.uk
- *
- * Add support for overlay1 and overlay2 based on pxafb_overlay.c:
- *
- *   Copyright (C) 2004, Intel Corporation
- *
- *     2003/08/27: <yu.tang@intel.com>
- *     2004/03/10: <stanley.cai@intel.com>
- *     2004/10/28: <yan.yin@intel.com>
- *
- *   Copyright (C) 2006-2008 Marvell International Ltd.
- *   All Rights Reserved
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/cpufreq.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/console.h>
-
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-#include <mach/bitfield.h>
-#include <linux/platform_data/video-pxafb.h>
-
-/*
- * Complain if VAR is out of range.
- */
-#define DEBUG_VAR 1
-
-#include "pxafb.h"
-
-/* Bits which should not be set in machine configuration structures */
-#define LCCR0_INVALID_CONFIG_MASK	(LCCR0_OUM | LCCR0_BM | LCCR0_QDM |\
-					 LCCR0_DIS | LCCR0_EFM | LCCR0_IUM |\
-					 LCCR0_SFM | LCCR0_LDM | LCCR0_ENB)
-
-#define LCCR3_INVALID_CONFIG_MASK	(LCCR3_HSP | LCCR3_VSP |\
-					 LCCR3_PCD | LCCR3_BPP(0xf))
-
-static int pxafb_activate_var(struct fb_var_screeninfo *var,
-				struct pxafb_info *);
-static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
-static void setup_base_frame(struct pxafb_info *fbi,
-                             struct fb_var_screeninfo *var, int branch);
-static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
-			   unsigned long offset, size_t size);
-
-static unsigned long video_mem_size = 0;
-
-static inline unsigned long
-lcd_readl(struct pxafb_info *fbi, unsigned int off)
-{
-	return __raw_readl(fbi->mmio_base + off);
-}
-
-static inline void
-lcd_writel(struct pxafb_info *fbi, unsigned int off, unsigned long val)
-{
-	__raw_writel(val, fbi->mmio_base + off);
-}
-
-static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	/*
-	 * We need to handle two requests being made at the same time.
-	 * There are two important cases:
-	 *  1. When we are changing VT (C_REENABLE) while unblanking
-	 *     (C_ENABLE) We must perform the unblanking, which will
-	 *     do our REENABLE for us.
-	 *  2. When we are blanking, but immediately unblank before
-	 *     we have blanked.  We do the "REENABLE" thing here as
-	 *     well, just to be sure.
-	 */
-	if (fbi->task_state == C_ENABLE && state == C_REENABLE)
-		state = (u_int) -1;
-	if (fbi->task_state == C_DISABLE && state == C_ENABLE)
-		state = C_REENABLE;
-
-	if (state != (u_int)-1) {
-		fbi->task_state = state;
-		schedule_work(&fbi->task);
-	}
-	local_irq_restore(flags);
-}
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int
-pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
-		       u_int trans, struct fb_info *info)
-{
-	struct pxafb_info *fbi = (struct pxafb_info *)info;
-	u_int val;
-
-	if (regno >= fbi->palette_size)
-		return 1;
-
-	if (fbi->fb.var.grayscale) {
-		fbi->palette_cpu[regno] = ((blue >> 8) & 0x00ff);
-		return 0;
-	}
-
-	switch (fbi->lccr4 & LCCR4_PAL_FOR_MASK) {
-	case LCCR4_PAL_FOR_0:
-		val  = ((red   >>  0) & 0xf800);
-		val |= ((green >>  5) & 0x07e0);
-		val |= ((blue  >> 11) & 0x001f);
-		fbi->palette_cpu[regno] = val;
-		break;
-	case LCCR4_PAL_FOR_1:
-		val  = ((red   << 8) & 0x00f80000);
-		val |= ((green >> 0) & 0x0000fc00);
-		val |= ((blue  >> 8) & 0x000000f8);
-		((u32 *)(fbi->palette_cpu))[regno] = val;
-		break;
-	case LCCR4_PAL_FOR_2:
-		val  = ((red   << 8) & 0x00fc0000);
-		val |= ((green >> 0) & 0x0000fc00);
-		val |= ((blue  >> 8) & 0x000000fc);
-		((u32 *)(fbi->palette_cpu))[regno] = val;
-		break;
-	case LCCR4_PAL_FOR_3:
-		val  = ((red   << 8) & 0x00ff0000);
-		val |= ((green >> 0) & 0x0000ff00);
-		val |= ((blue  >> 8) & 0x000000ff);
-		((u32 *)(fbi->palette_cpu))[regno] = val;
-		break;
-	}
-
-	return 0;
-}
-
-static int
-pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		   u_int trans, struct fb_info *info)
-{
-	struct pxafb_info *fbi = (struct pxafb_info *)info;
-	unsigned int val;
-	int ret = 1;
-
-	/*
-	 * If inverse mode was selected, invert all the colours
-	 * rather than the register number.  The register number
-	 * is what you poke into the framebuffer to produce the
-	 * colour you requested.
-	 */
-	if (fbi->cmap_inverse) {
-		red   = 0xffff - red;
-		green = 0xffff - green;
-		blue  = 0xffff - blue;
-	}
-
-	/*
-	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no matter what visual we are using.
-	 */
-	if (fbi->fb.var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-					7471 * blue) >> 16;
-
-	switch (fbi->fb.fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 16-bit True Colour.  We encode the RGB value
-		 * according to the RGB bitfield information.
-		 */
-		if (regno < 16) {
-			u32 *pal = fbi->fb.pseudo_palette;
-
-			val  = chan_to_field(red, &fbi->fb.var.red);
-			val |= chan_to_field(green, &fbi->fb.var.green);
-			val |= chan_to_field(blue, &fbi->fb.var.blue);
-
-			pal[regno] = val;
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_STATIC_PSEUDOCOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);
-		break;
-	}
-
-	return ret;
-}
-
-/* calculate pixel depth, transparency bit included, >=16bpp formats _only_ */
-static inline int var_to_depth(struct fb_var_screeninfo *var)
-{
-	return var->red.length + var->green.length +
-		var->blue.length + var->transp.length;
-}
-
-/* calculate 4-bit BPP value for LCCR3 and OVLxC1 */
-static int pxafb_var_to_bpp(struct fb_var_screeninfo *var)
-{
-	int bpp = -EINVAL;
-
-	switch (var->bits_per_pixel) {
-	case 1:  bpp = 0; break;
-	case 2:  bpp = 1; break;
-	case 4:  bpp = 2; break;
-	case 8:  bpp = 3; break;
-	case 16: bpp = 4; break;
-	case 24:
-		switch (var_to_depth(var)) {
-		case 18: bpp = 6; break; /* 18-bits/pixel packed */
-		case 19: bpp = 8; break; /* 19-bits/pixel packed */
-		case 24: bpp = 9; break;
-		}
-		break;
-	case 32:
-		switch (var_to_depth(var)) {
-		case 18: bpp = 5; break; /* 18-bits/pixel unpacked */
-		case 19: bpp = 7; break; /* 19-bits/pixel unpacked */
-		case 25: bpp = 10; break;
-		}
-		break;
-	}
-	return bpp;
-}
-
-/*
- *  pxafb_var_to_lccr3():
- *    Convert a bits per pixel value to the correct bit pattern for LCCR3
- *
- *  NOTE: for PXA27x with overlays support, the LCCR3_PDFOR_x bits have an
- *  implication of the acutal use of transparency bit,  which we handle it
- *  here separatedly. See PXA27x Developer's Manual, Section <<7.4.6 Pixel
- *  Formats>> for the valid combination of PDFOR, PAL_FOR for various BPP.
- *
- *  Transparency for palette pixel formats is not supported at the moment.
- */
-static uint32_t pxafb_var_to_lccr3(struct fb_var_screeninfo *var)
-{
-	int bpp = pxafb_var_to_bpp(var);
-	uint32_t lccr3;
-
-	if (bpp < 0)
-		return 0;
-
-	lccr3 = LCCR3_BPP(bpp);
-
-	switch (var_to_depth(var)) {
-	case 16: lccr3 |= var->transp.length ? LCCR3_PDFOR_3 : 0; break;
-	case 18: lccr3 |= LCCR3_PDFOR_3; break;
-	case 24: lccr3 |= var->transp.length ? LCCR3_PDFOR_2 : LCCR3_PDFOR_3;
-		 break;
-	case 19:
-	case 25: lccr3 |= LCCR3_PDFOR_0; break;
-	}
-	return lccr3;
-}
-
-#define SET_PIXFMT(v, r, g, b, t)				\
-({								\
-	(v)->transp.offset = (t) ? (r) + (g) + (b) : 0;		\
-	(v)->transp.length = (t) ? (t) : 0;			\
-	(v)->blue.length   = (b); (v)->blue.offset = 0;		\
-	(v)->green.length  = (g); (v)->green.offset = (b);	\
-	(v)->red.length    = (r); (v)->red.offset = (b) + (g);	\
-})
-
-/* set the RGBT bitfields of fb_var_screeninf according to
- * var->bits_per_pixel and given depth
- */
-static void pxafb_set_pixfmt(struct fb_var_screeninfo *var, int depth)
-{
-	if (depth == 0)
-		depth = var->bits_per_pixel;
-
-	if (var->bits_per_pixel < 16) {
-		/* indexed pixel formats */
-		var->red.offset    = 0; var->red.length    = 8;
-		var->green.offset  = 0; var->green.length  = 8;
-		var->blue.offset   = 0; var->blue.length   = 8;
-		var->transp.offset = 0; var->transp.length = 8;
-	}
-
-	switch (depth) {
-	case 16: var->transp.length ?
-		 SET_PIXFMT(var, 5, 5, 5, 1) :		/* RGBT555 */
-		 SET_PIXFMT(var, 5, 6, 5, 0); break;	/* RGB565 */
-	case 18: SET_PIXFMT(var, 6, 6, 6, 0); break;	/* RGB666 */
-	case 19: SET_PIXFMT(var, 6, 6, 6, 1); break;	/* RGBT666 */
-	case 24: var->transp.length ?
-		 SET_PIXFMT(var, 8, 8, 7, 1) :		/* RGBT887 */
-		 SET_PIXFMT(var, 8, 8, 8, 0); break;	/* RGB888 */
-	case 25: SET_PIXFMT(var, 8, 8, 8, 1); break;	/* RGBT888 */
-	}
-}
-
-#ifdef CONFIG_CPU_FREQ
-/*
- *  pxafb_display_dma_period()
- *    Calculate the minimum period (in picoseconds) between two DMA
- *    requests for the LCD controller.  If we hit this, it means we're
- *    doing nothing but LCD DMA.
- */
-static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
-{
-	/*
-	 * Period = pixclock * bits_per_byte * bytes_per_transfer
-	 *              / memory_bits_per_pixel;
-	 */
-	return var->pixclock * 8 * 16 / var->bits_per_pixel;
-}
-#endif
-
-/*
- * Select the smallest mode that allows the desired resolution to be
- * displayed. If desired parameters can be rounded up.
- */
-static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach,
-					     struct fb_var_screeninfo *var)
-{
-	struct pxafb_mode_info *mode = NULL;
-	struct pxafb_mode_info *modelist = mach->modes;
-	unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
-	unsigned int i;
-
-	for (i = 0; i < mach->num_modes; i++) {
-		if (modelist[i].xres >= var->xres &&
-		    modelist[i].yres >= var->yres &&
-		    modelist[i].xres < best_x &&
-		    modelist[i].yres < best_y &&
-		    modelist[i].bpp >= var->bits_per_pixel) {
-			best_x = modelist[i].xres;
-			best_y = modelist[i].yres;
-			mode = &modelist[i];
-		}
-	}
-
-	return mode;
-}
-
-static void pxafb_setmode(struct fb_var_screeninfo *var,
-			  struct pxafb_mode_info *mode)
-{
-	var->xres		= mode->xres;
-	var->yres		= mode->yres;
-	var->bits_per_pixel	= mode->bpp;
-	var->pixclock		= mode->pixclock;
-	var->hsync_len		= mode->hsync_len;
-	var->left_margin	= mode->left_margin;
-	var->right_margin	= mode->right_margin;
-	var->vsync_len		= mode->vsync_len;
-	var->upper_margin	= mode->upper_margin;
-	var->lower_margin	= mode->lower_margin;
-	var->sync		= mode->sync;
-	var->grayscale		= mode->cmap_greyscale;
-	var->transp.length	= mode->transparency;
-
-	/* set the initial RGBA bitfields */
-	pxafb_set_pixfmt(var, mode->depth);
-}
-
-static int pxafb_adjust_timing(struct pxafb_info *fbi,
-			       struct fb_var_screeninfo *var)
-{
-	int line_length;
-
-	var->xres = max_t(int, var->xres, MIN_XRES);
-	var->yres = max_t(int, var->yres, MIN_YRES);
-
-	if (!(fbi->lccr0 & LCCR0_LCDT)) {
-		clamp_val(var->hsync_len, 1, 64);
-		clamp_val(var->vsync_len, 1, 64);
-		clamp_val(var->left_margin,  1, 255);
-		clamp_val(var->right_margin, 1, 255);
-		clamp_val(var->upper_margin, 1, 255);
-		clamp_val(var->lower_margin, 1, 255);
-	}
-
-	/* make sure each line is aligned on word boundary */
-	line_length = var->xres * var->bits_per_pixel / 8;
-	line_length = ALIGN(line_length, 4);
-	var->xres = line_length * 8 / var->bits_per_pixel;
-
-	/* we don't support xpan, force xres_virtual to be equal to xres */
-	var->xres_virtual = var->xres;
-
-	if (var->accel_flags & FB_ACCELF_TEXT)
-		var->yres_virtual = fbi->fb.fix.smem_len / line_length;
-	else
-		var->yres_virtual = max(var->yres_virtual, var->yres);
-
-	/* check for limits */
-	if (var->xres > MAX_XRES || var->yres > MAX_YRES)
-		return -EINVAL;
-
-	if (var->yres > var->yres_virtual)
-		return -EINVAL;
-
-	return 0;
-}
-
-/*
- *  pxafb_check_var():
- *    Get the video params out of 'var'. If a value doesn't fit, round it up,
- *    if it's too big, return -EINVAL.
- *
- *    Round up in the following order: bits_per_pixel, xres,
- *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
- *    bitfields, horizontal timing, vertical timing.
- */
-static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct pxafb_info *fbi = (struct pxafb_info *)info;
-	struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
-	int err;
-
-	if (inf->fixed_modes) {
-		struct pxafb_mode_info *mode;
-
-		mode = pxafb_getmode(inf, var);
-		if (!mode)
-			return -EINVAL;
-		pxafb_setmode(var, mode);
-	}
-
-	/* do a test conversion to BPP fields to check the color formats */
-	err = pxafb_var_to_bpp(var);
-	if (err < 0)
-		return err;
-
-	pxafb_set_pixfmt(var, var_to_depth(var));
-
-	err = pxafb_adjust_timing(fbi, var);
-	if (err)
-		return err;
-
-#ifdef CONFIG_CPU_FREQ
-	pr_debug("pxafb: dma period = %d ps\n",
-		 pxafb_display_dma_period(var));
-#endif
-
-	return 0;
-}
-
-/*
- * pxafb_set_par():
- *	Set the user defined part of the display for the specified console
- */
-static int pxafb_set_par(struct fb_info *info)
-{
-	struct pxafb_info *fbi = (struct pxafb_info *)info;
-	struct fb_var_screeninfo *var = &info->var;
-
-	if (var->bits_per_pixel >= 16)
-		fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-	else if (!fbi->cmap_static)
-		fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else {
-		/*
-		 * Some people have weird ideas about wanting static
-		 * pseudocolor maps.  I suspect their user space
-		 * applications are broken.
-		 */
-		fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-	}
-
-	fbi->fb.fix.line_length = var->xres_virtual *
-				  var->bits_per_pixel / 8;
-	if (var->bits_per_pixel >= 16)
-		fbi->palette_size = 0;
-	else
-		fbi->palette_size = var->bits_per_pixel == 1 ?
-					4 : 1 << var->bits_per_pixel;
-
-	fbi->palette_cpu = (u16 *)&fbi->dma_buff->palette[0];
-
-	if (fbi->fb.var.bits_per_pixel >= 16)
-		fb_dealloc_cmap(&fbi->fb.cmap);
-	else
-		fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
-
-	pxafb_activate_var(var, fbi);
-
-	return 0;
-}
-
-static int pxafb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct pxafb_info *fbi = (struct pxafb_info *)info;
-	struct fb_var_screeninfo newvar;
-	int dma = DMA_MAX + DMA_BASE;
-
-	if (fbi->state != C_ENABLE)
-		return 0;
-
-	/* Only take .xoffset, .yoffset and .vmode & FB_VMODE_YWRAP from what
-	 * was passed in and copy the rest from the old screeninfo.
-	 */
-	memcpy(&newvar, &fbi->fb.var, sizeof(newvar));
-	newvar.xoffset = var->xoffset;
-	newvar.yoffset = var->yoffset;
-	newvar.vmode &= ~FB_VMODE_YWRAP;
-	newvar.vmode |= var->vmode & FB_VMODE_YWRAP;
-
-	setup_base_frame(fbi, &newvar, 1);
-
-	if (fbi->lccr0 & LCCR0_SDS)
-		lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1);
-
-	lcd_writel(fbi, FBR0, fbi->fdadr[dma] | 0x1);
-	return 0;
-}
-
-/*
- * pxafb_blank():
- *	Blank the display by setting all palette values to zero.  Note, the
- * 	16 bpp mode does not really use the palette, so this will not
- *      blank the display in all modes.
- */
-static int pxafb_blank(int blank, struct fb_info *info)
-{
-	struct pxafb_info *fbi = (struct pxafb_info *)info;
-	int i;
-
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
-		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-			for (i = 0; i < fbi->palette_size; i++)
-				pxafb_setpalettereg(i, 0, 0, 0, 0, info);
-
-		pxafb_schedule_work(fbi, C_DISABLE);
-		/* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
-		break;
-
-	case FB_BLANK_UNBLANK:
-		/* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
-		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
-		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-			fb_set_cmap(&fbi->fb.cmap, info);
-		pxafb_schedule_work(fbi, C_ENABLE);
-	}
-	return 0;
-}
-
-static struct fb_ops pxafb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= pxafb_check_var,
-	.fb_set_par	= pxafb_set_par,
-	.fb_pan_display	= pxafb_pan_display,
-	.fb_setcolreg	= pxafb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_blank	= pxafb_blank,
-};
-
-#ifdef CONFIG_FB_PXA_OVERLAY
-static void overlay1fb_setup(struct pxafb_layer *ofb)
-{
-	int size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
-	unsigned long start = ofb->video_mem_phys;
-	setup_frame_dma(ofb->fbi, DMA_OV1, PAL_NONE, start, size);
-}
-
-/* Depending on the enable status of overlay1/2, the DMA should be
- * updated from FDADRx (when disabled) or FBRx (when enabled).
- */
-static void overlay1fb_enable(struct pxafb_layer *ofb)
-{
-	int enabled = lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN;
-	uint32_t fdadr1 = ofb->fbi->fdadr[DMA_OV1] | (enabled ? 0x1 : 0);
-
-	lcd_writel(ofb->fbi, enabled ? FBR1 : FDADR1, fdadr1);
-	lcd_writel(ofb->fbi, OVL1C2, ofb->control[1]);
-	lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] | OVLxC1_OEN);
-}
-
-static void overlay1fb_disable(struct pxafb_layer *ofb)
-{
-	uint32_t lccr5;
-
-	if (!(lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN))
-		return;
-
-	lccr5 = lcd_readl(ofb->fbi, LCCR5);
-
-	lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
-
-	lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(1));
-	lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(1));
-	lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3);
-
-	if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
-		pr_warning("%s: timeout disabling overlay1\n", __func__);
-
-	lcd_writel(ofb->fbi, LCCR5, lccr5);
-}
-
-static void overlay2fb_setup(struct pxafb_layer *ofb)
-{
-	int size, div = 1, pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
-	unsigned long start[3] = { ofb->video_mem_phys, 0, 0 };
-
-	if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED) {
-		size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
-		setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size);
-	} else {
-		size = ofb->fb.var.xres_virtual * ofb->fb.var.yres_virtual;
-		switch (pfor) {
-		case OVERLAY_FORMAT_YUV444_PLANAR: div = 1; break;
-		case OVERLAY_FORMAT_YUV422_PLANAR: div = 2; break;
-		case OVERLAY_FORMAT_YUV420_PLANAR: div = 4; break;
-		}
-		start[1] = start[0] + size;
-		start[2] = start[1] + size / div;
-		setup_frame_dma(ofb->fbi, DMA_OV2_Y,  -1, start[0], size);
-		setup_frame_dma(ofb->fbi, DMA_OV2_Cb, -1, start[1], size / div);
-		setup_frame_dma(ofb->fbi, DMA_OV2_Cr, -1, start[2], size / div);
-	}
-}
-
-static void overlay2fb_enable(struct pxafb_layer *ofb)
-{
-	int pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
-	int enabled = lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN;
-	uint32_t fdadr2 = ofb->fbi->fdadr[DMA_OV2_Y]  | (enabled ? 0x1 : 0);
-	uint32_t fdadr3 = ofb->fbi->fdadr[DMA_OV2_Cb] | (enabled ? 0x1 : 0);
-	uint32_t fdadr4 = ofb->fbi->fdadr[DMA_OV2_Cr] | (enabled ? 0x1 : 0);
-
-	if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED)
-		lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
-	else {
-		lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
-		lcd_writel(ofb->fbi, enabled ? FBR3 : FDADR3, fdadr3);
-		lcd_writel(ofb->fbi, enabled ? FBR4 : FDADR4, fdadr4);
-	}
-	lcd_writel(ofb->fbi, OVL2C2, ofb->control[1]);
-	lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] | OVLxC1_OEN);
-}
-
-static void overlay2fb_disable(struct pxafb_layer *ofb)
-{
-	uint32_t lccr5;
-
-	if (!(lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN))
-		return;
-
-	lccr5 = lcd_readl(ofb->fbi, LCCR5);
-
-	lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);
-
-	lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(2));
-	lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(2));
-	lcd_writel(ofb->fbi, FBR2, ofb->fbi->fdadr[DMA_OV2_Y]  | 0x3);
-	lcd_writel(ofb->fbi, FBR3, ofb->fbi->fdadr[DMA_OV2_Cb] | 0x3);
-	lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3);
-
-	if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
-		pr_warning("%s: timeout disabling overlay2\n", __func__);
-}
-
-static struct pxafb_layer_ops ofb_ops[] = {
-	[0] = {
-		.enable		= overlay1fb_enable,
-		.disable	= overlay1fb_disable,
-		.setup		= overlay1fb_setup,
-	},
-	[1] = {
-		.enable		= overlay2fb_enable,
-		.disable	= overlay2fb_disable,
-		.setup		= overlay2fb_setup,
-	},
-};
-
-static int overlayfb_open(struct fb_info *info, int user)
-{
-	struct pxafb_layer *ofb = (struct pxafb_layer *)info;
-
-	/* no support for framebuffer console on overlay */
-	if (user == 0)
-		return -ENODEV;
-
-	if (ofb->usage++ == 0) {
-		/* unblank the base framebuffer */
-		console_lock();
-		fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
-		console_unlock();
-	}
-
-	return 0;
-}
-
-static int overlayfb_release(struct fb_info *info, int user)
-{
-	struct pxafb_layer *ofb = (struct pxafb_layer*) info;
-
-	if (ofb->usage == 1) {
-		ofb->ops->disable(ofb);
-		ofb->fb.var.height	= -1;
-		ofb->fb.var.width	= -1;
-		ofb->fb.var.xres = ofb->fb.var.xres_virtual = 0;
-		ofb->fb.var.yres = ofb->fb.var.yres_virtual = 0;
-
-		ofb->usage--;
-	}
-	return 0;
-}
-
-static int overlayfb_check_var(struct fb_var_screeninfo *var,
-			       struct fb_info *info)
-{
-	struct pxafb_layer *ofb = (struct pxafb_layer *)info;
-	struct fb_var_screeninfo *base_var = &ofb->fbi->fb.var;
-	int xpos, ypos, pfor, bpp;
-
-	xpos = NONSTD_TO_XPOS(var->nonstd);
-	ypos = NONSTD_TO_YPOS(var->nonstd);
-	pfor = NONSTD_TO_PFOR(var->nonstd);
-
-	bpp = pxafb_var_to_bpp(var);
-	if (bpp < 0)
-		return -EINVAL;
-
-	/* no support for YUV format on overlay1 */
-	if (ofb->id == OVERLAY1 && pfor != 0)
-		return -EINVAL;
-
-	/* for YUV packed formats, bpp = 'minimum bpp of YUV components' */
-	switch (pfor) {
-	case OVERLAY_FORMAT_RGB:
-		bpp = pxafb_var_to_bpp(var);
-		if (bpp < 0)
-			return -EINVAL;
-
-		pxafb_set_pixfmt(var, var_to_depth(var));
-		break;
-	case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
-	case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 8; break;
-	case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 4; break;
-	case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 2; break;
-	default:
-		return -EINVAL;
-	}
-
-	/* each line must start at a 32-bit word boundary */
-	if ((xpos * bpp) % 32)
-		return -EINVAL;
-
-	/* xres must align on 32-bit word boundary */
-	var->xres = roundup(var->xres * bpp, 32) / bpp;
-
-	if ((xpos + var->xres > base_var->xres) ||
-	    (ypos + var->yres > base_var->yres))
-		return -EINVAL;
-
-	var->xres_virtual = var->xres;
-	var->yres_virtual = max(var->yres, var->yres_virtual);
-	return 0;
-}
-
-static int overlayfb_check_video_memory(struct pxafb_layer *ofb)
-{
-	struct fb_var_screeninfo *var = &ofb->fb.var;
-	int pfor = NONSTD_TO_PFOR(var->nonstd);
-	int size, bpp = 0;
-
-	switch (pfor) {
-	case OVERLAY_FORMAT_RGB: bpp = var->bits_per_pixel; break;
-	case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
-	case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 24; break;
-	case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 16; break;
-	case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 12; break;
-	}
-
-	ofb->fb.fix.line_length = var->xres_virtual * bpp / 8;
-
-	size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual);
-
-	if (ofb->video_mem) {
-		if (ofb->video_mem_size >= size)
-			return 0;
-	}
-	return -EINVAL;
-}
-
-static int overlayfb_set_par(struct fb_info *info)
-{
-	struct pxafb_layer *ofb = (struct pxafb_layer *)info;
-	struct fb_var_screeninfo *var = &info->var;
-	int xpos, ypos, pfor, bpp, ret;
-
-	ret = overlayfb_check_video_memory(ofb);
-	if (ret)
-		return ret;
-
-	bpp  = pxafb_var_to_bpp(var);
-	xpos = NONSTD_TO_XPOS(var->nonstd);
-	ypos = NONSTD_TO_YPOS(var->nonstd);
-	pfor = NONSTD_TO_PFOR(var->nonstd);
-
-	ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) |
-			  OVLxC1_BPP(bpp);
-	ofb->control[1] = OVLxC2_XPOS(xpos) | OVLxC2_YPOS(ypos);
-
-	if (ofb->id == OVERLAY2)
-		ofb->control[1] |= OVL2C2_PFOR(pfor);
-
-	ofb->ops->setup(ofb);
-	ofb->ops->enable(ofb);
-	return 0;
-}
-
-static struct fb_ops overlay_fb_ops = {
-	.owner			= THIS_MODULE,
-	.fb_open		= overlayfb_open,
-	.fb_release		= overlayfb_release,
-	.fb_check_var 		= overlayfb_check_var,
-	.fb_set_par		= overlayfb_set_par,
-};
-
-static void init_pxafb_overlay(struct pxafb_info *fbi, struct pxafb_layer *ofb,
-			       int id)
-{
-	sprintf(ofb->fb.fix.id, "overlay%d", id + 1);
-
-	ofb->fb.fix.type		= FB_TYPE_PACKED_PIXELS;
-	ofb->fb.fix.xpanstep		= 0;
-	ofb->fb.fix.ypanstep		= 1;
-
-	ofb->fb.var.activate		= FB_ACTIVATE_NOW;
-	ofb->fb.var.height		= -1;
-	ofb->fb.var.width		= -1;
-	ofb->fb.var.vmode		= FB_VMODE_NONINTERLACED;
-
-	ofb->fb.fbops			= &overlay_fb_ops;
-	ofb->fb.flags			= FBINFO_FLAG_DEFAULT;
-	ofb->fb.node			= -1;
-	ofb->fb.pseudo_palette		= NULL;
-
-	ofb->id = id;
-	ofb->ops = &ofb_ops[id];
-	ofb->usage = 0;
-	ofb->fbi = fbi;
-	init_completion(&ofb->branch_done);
-}
-
-static inline int pxafb_overlay_supported(void)
-{
-	if (cpu_is_pxa27x() || cpu_is_pxa3xx())
-		return 1;
-
-	return 0;
-}
-
-static int pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
-					  struct pxafb_layer *ofb)
-{
-	/* We assume that user will use at most video_mem_size for overlay fb,
-	 * anyway, it's useless to use 16bpp main plane and 24bpp overlay
-	 */
-	ofb->video_mem = alloc_pages_exact(PAGE_ALIGN(pxafb->video_mem_size),
-		GFP_KERNEL | __GFP_ZERO);
-	if (ofb->video_mem == NULL)
-		return -ENOMEM;
-
-	ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
-	ofb->video_mem_size = PAGE_ALIGN(pxafb->video_mem_size);
-
-	mutex_lock(&ofb->fb.mm_lock);
-	ofb->fb.fix.smem_start	= ofb->video_mem_phys;
-	ofb->fb.fix.smem_len	= pxafb->video_mem_size;
-	mutex_unlock(&ofb->fb.mm_lock);
-
-	ofb->fb.screen_base	= ofb->video_mem;
-
-	return 0;
-}
-
-static void pxafb_overlay_init(struct pxafb_info *fbi)
-{
-	int i, ret;
-
-	if (!pxafb_overlay_supported())
-		return;
-
-	for (i = 0; i < 2; i++) {
-		struct pxafb_layer *ofb = &fbi->overlay[i];
-		init_pxafb_overlay(fbi, ofb, i);
-		ret = register_framebuffer(&ofb->fb);
-		if (ret) {
-			dev_err(fbi->dev, "failed to register overlay %d\n", i);
-			continue;
-		}
-		ret = pxafb_overlay_map_video_memory(fbi, ofb);
-		if (ret) {
-			dev_err(fbi->dev,
-				"failed to map video memory for overlay %d\n",
-				i);
-			unregister_framebuffer(&ofb->fb);
-			continue;
-		}
-		ofb->registered = 1;
-	}
-
-	/* mask all IU/BS/EOF/SOF interrupts */
-	lcd_writel(fbi, LCCR5, ~0);
-
-	pr_info("PXA Overlay driver loaded successfully!\n");
-}
-
-static void pxafb_overlay_exit(struct pxafb_info *fbi)
-{
-	int i;
-
-	if (!pxafb_overlay_supported())
-		return;
-
-	for (i = 0; i < 2; i++) {
-		struct pxafb_layer *ofb = &fbi->overlay[i];
-		if (ofb->registered) {
-			if (ofb->video_mem)
-				free_pages_exact(ofb->video_mem,
-					ofb->video_mem_size);
-			unregister_framebuffer(&ofb->fb);
-		}
-	}
-}
-#else
-static inline void pxafb_overlay_init(struct pxafb_info *fbi) {}
-static inline void pxafb_overlay_exit(struct pxafb_info *fbi) {}
-#endif /* CONFIG_FB_PXA_OVERLAY */
-
-/*
- * Calculate the PCD value from the clock rate (in picoseconds).
- * We take account of the PPCR clock setting.
- * From PXA Developer's Manual:
- *
- *   PixelClock =      LCLK
- *                -------------
- *                2 ( PCD + 1 )
- *
- *   PCD =      LCLK
- *         ------------- - 1
- *         2(PixelClock)
- *
- * Where:
- *   LCLK = LCD/Memory Clock
- *   PCD = LCCR3[7:0]
- *
- * PixelClock here is in Hz while the pixclock argument given is the
- * period in picoseconds. Hence PixelClock = 1 / ( pixclock * 10^-12 )
- *
- * The function get_lclk_frequency_10khz returns LCLK in units of
- * 10khz. Calling the result of this function lclk gives us the
- * following
- *
- *    PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 )
- *          -------------------------------------- - 1
- *                          2
- *
- * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
- */
-static inline unsigned int get_pcd(struct pxafb_info *fbi,
-				   unsigned int pixclock)
-{
-	unsigned long long pcd;
-
-	/* FIXME: Need to take into account Double Pixel Clock mode
-	 * (DPC) bit? or perhaps set it based on the various clock
-	 * speeds */
-	pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000);
-	pcd *= pixclock;
-	do_div(pcd, 100000000 * 2);
-	/* no need for this, since we should subtract 1 anyway. they cancel */
-	/* pcd += 1; */ /* make up for integer math truncations */
-	return (unsigned int)pcd;
-}
-
-/*
- * Some touchscreens need hsync information from the video driver to
- * function correctly. We export it here.  Note that 'hsync_time' and
- * the value returned from pxafb_get_hsync_time() is the *reciprocal*
- * of the hsync period in seconds.
- */
-static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
-{
-	unsigned long htime;
-
-	if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
-		fbi->hsync_time = 0;
-		return;
-	}
-
-	htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len);
-
-	fbi->hsync_time = htime;
-}
-
-unsigned long pxafb_get_hsync_time(struct device *dev)
-{
-	struct pxafb_info *fbi = dev_get_drvdata(dev);
-
-	/* If display is blanked/suspended, hsync isn't active */
-	if (!fbi || (fbi->state != C_ENABLE))
-		return 0;
-
-	return fbi->hsync_time;
-}
-EXPORT_SYMBOL(pxafb_get_hsync_time);
-
-static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
-			   unsigned long start, size_t size)
-{
-	struct pxafb_dma_descriptor *dma_desc, *pal_desc;
-	unsigned int dma_desc_off, pal_desc_off;
-
-	if (dma < 0 || dma >= DMA_MAX * 2)
-		return -EINVAL;
-
-	dma_desc = &fbi->dma_buff->dma_desc[dma];
-	dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]);
-
-	dma_desc->fsadr = start;
-	dma_desc->fidr  = 0;
-	dma_desc->ldcmd = size;
-
-	if (pal < 0 || pal >= PAL_MAX * 2) {
-		dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
-		fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
-	} else {
-		pal_desc = &fbi->dma_buff->pal_desc[pal];
-		pal_desc_off = offsetof(struct pxafb_dma_buff, pal_desc[pal]);
-
-		pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE;
-		pal_desc->fidr  = 0;
-
-		if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
-			pal_desc->ldcmd = fbi->palette_size * sizeof(u16);
-		else
-			pal_desc->ldcmd = fbi->palette_size * sizeof(u32);
-
-		pal_desc->ldcmd |= LDCMD_PAL;
-
-		/* flip back and forth between palette and frame buffer */
-		pal_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
-		dma_desc->fdadr = fbi->dma_buff_phys + pal_desc_off;
-		fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
-	}
-
-	return 0;
-}
-
-static void setup_base_frame(struct pxafb_info *fbi,
-                             struct fb_var_screeninfo *var,
-                             int branch)
-{
-	struct fb_fix_screeninfo *fix = &fbi->fb.fix;
-	int nbytes, dma, pal, bpp = var->bits_per_pixel;
-	unsigned long offset;
-
-	dma = DMA_BASE + (branch ? DMA_MAX : 0);
-	pal = (bpp >= 16) ? PAL_NONE : PAL_BASE + (branch ? PAL_MAX : 0);
-
-	nbytes = fix->line_length * var->yres;
-	offset = fix->line_length * var->yoffset + fbi->video_mem_phys;
-
-	if (fbi->lccr0 & LCCR0_SDS) {
-		nbytes = nbytes / 2;
-		setup_frame_dma(fbi, dma + 1, PAL_NONE, offset + nbytes, nbytes);
-	}
-
-	setup_frame_dma(fbi, dma, pal, offset, nbytes);
-}
-
-#ifdef CONFIG_FB_PXA_SMARTPANEL
-static int setup_smart_dma(struct pxafb_info *fbi)
-{
-	struct pxafb_dma_descriptor *dma_desc;
-	unsigned long dma_desc_off, cmd_buff_off;
-
-	dma_desc = &fbi->dma_buff->dma_desc[DMA_CMD];
-	dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[DMA_CMD]);
-	cmd_buff_off = offsetof(struct pxafb_dma_buff, cmd_buff);
-
-	dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
-	dma_desc->fsadr = fbi->dma_buff_phys + cmd_buff_off;
-	dma_desc->fidr  = 0;
-	dma_desc->ldcmd = fbi->n_smart_cmds * sizeof(uint16_t);
-
-	fbi->fdadr[DMA_CMD] = dma_desc->fdadr;
-	return 0;
-}
-
-int pxafb_smart_flush(struct fb_info *info)
-{
-	struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
-	uint32_t prsr;
-	int ret = 0;
-
-	/* disable controller until all registers are set up */
-	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
-
-	/* 1. make it an even number of commands to align on 32-bit boundary
-	 * 2. add the interrupt command to the end of the chain so we can
-	 *    keep track of the end of the transfer
-	 */
-
-	while (fbi->n_smart_cmds & 1)
-		fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_NOOP;
-
-	fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_INTERRUPT;
-	fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_WAIT_FOR_VSYNC;
-	setup_smart_dma(fbi);
-
-	/* continue to execute next command */
-	prsr = lcd_readl(fbi, PRSR) | PRSR_ST_OK | PRSR_CON_NT;
-	lcd_writel(fbi, PRSR, prsr);
-
-	/* stop the processor in case it executed "wait for sync" cmd */
-	lcd_writel(fbi, CMDCR, 0x0001);
-
-	/* don't send interrupts for fifo underruns on channel 6 */
-	lcd_writel(fbi, LCCR5, LCCR5_IUM(6));
-
-	lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
-	lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
-	lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
-	lcd_writel(fbi, LCCR4, fbi->reg_lccr4);
-	lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
-	lcd_writel(fbi, FDADR6, fbi->fdadr[6]);
-
-	/* begin sending */
-	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
-
-	if (wait_for_completion_timeout(&fbi->command_done, HZ/2) == 0) {
-		pr_warning("%s: timeout waiting for command done\n",
-				__func__);
-		ret = -ETIMEDOUT;
-	}
-
-	/* quick disable */
-	prsr = lcd_readl(fbi, PRSR) & ~(PRSR_ST_OK | PRSR_CON_NT);
-	lcd_writel(fbi, PRSR, prsr);
-	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
-	lcd_writel(fbi, FDADR6, 0);
-	fbi->n_smart_cmds = 0;
-	return ret;
-}
-
-int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
-{
-	int i;
-	struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
-
-	for (i = 0; i < n_cmds; i++, cmds++) {
-		/* if it is a software delay, flush and delay */
-		if ((*cmds & 0xff00) == SMART_CMD_DELAY) {
-			pxafb_smart_flush(info);
-			mdelay(*cmds & 0xff);
-			continue;
-		}
-
-		/* leave 2 commands for INTERRUPT and WAIT_FOR_SYNC */
-		if (fbi->n_smart_cmds == CMD_BUFF_SIZE - 8)
-			pxafb_smart_flush(info);
-
-		fbi->smart_cmds[fbi->n_smart_cmds++] = *cmds;
-	}
-
-	return 0;
-}
-
-static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk)
-{
-	unsigned int t = (time_ns * (lcd_clk / 1000000) / 1000);
-	return (t == 0) ? 1 : t;
-}
-
-static void setup_smart_timing(struct pxafb_info *fbi,
-				struct fb_var_screeninfo *var)
-{
-	struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
-	struct pxafb_mode_info *mode = &inf->modes[0];
-	unsigned long lclk = clk_get_rate(fbi->clk);
-	unsigned t1, t2, t3, t4;
-
-	t1 = max(mode->a0csrd_set_hld, mode->a0cswr_set_hld);
-	t2 = max(mode->rd_pulse_width, mode->wr_pulse_width);
-	t3 = mode->op_hold_time;
-	t4 = mode->cmd_inh_time;
-
-	fbi->reg_lccr1 =
-		LCCR1_DisWdth(var->xres) |
-		LCCR1_BegLnDel(__smart_timing(t1, lclk)) |
-		LCCR1_EndLnDel(__smart_timing(t2, lclk)) |
-		LCCR1_HorSnchWdth(__smart_timing(t3, lclk));
-
-	fbi->reg_lccr2 = LCCR2_DisHght(var->yres);
-	fbi->reg_lccr3 = fbi->lccr3 | LCCR3_PixClkDiv(__smart_timing(t4, lclk));
-	fbi->reg_lccr3 |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HSP : 0;
-	fbi->reg_lccr3 |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VSP : 0;
-
-	/* FIXME: make this configurable */
-	fbi->reg_cmdcr = 1;
-}
-
-static int pxafb_smart_thread(void *arg)
-{
-	struct pxafb_info *fbi = arg;
-	struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
-
-	if (!inf->smart_update) {
-		pr_err("%s: not properly initialized, thread terminated\n",
-				__func__);
-		return -EINVAL;
-	}
-	inf = dev_get_platdata(fbi->dev);
-
-	pr_debug("%s(): task starting\n", __func__);
-
-	set_freezable();
-	while (!kthread_should_stop()) {
-
-		if (try_to_freeze())
-			continue;
-
-		mutex_lock(&fbi->ctrlr_lock);
-
-		if (fbi->state == C_ENABLE) {
-			inf->smart_update(&fbi->fb);
-			complete(&fbi->refresh_done);
-		}
-
-		mutex_unlock(&fbi->ctrlr_lock);
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(30 * HZ / 1000);
-	}
-
-	pr_debug("%s(): task ending\n", __func__);
-	return 0;
-}
-
-static int pxafb_smart_init(struct pxafb_info *fbi)
-{
-	if (!(fbi->lccr0 & LCCR0_LCDT))
-		return 0;
-
-	fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
-	fbi->n_smart_cmds = 0;
-
-	init_completion(&fbi->command_done);
-	init_completion(&fbi->refresh_done);
-
-	fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
-					"lcd_refresh");
-	if (IS_ERR(fbi->smart_thread)) {
-		pr_err("%s: unable to create kernel thread\n", __func__);
-		return PTR_ERR(fbi->smart_thread);
-	}
-
-	return 0;
-}
-#else
-static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; }
-#endif /* CONFIG_FB_PXA_SMARTPANEL */
-
-static void setup_parallel_timing(struct pxafb_info *fbi,
-				  struct fb_var_screeninfo *var)
-{
-	unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
-
-	fbi->reg_lccr1 =
-		LCCR1_DisWdth(var->xres) +
-		LCCR1_HorSnchWdth(var->hsync_len) +
-		LCCR1_BegLnDel(var->left_margin) +
-		LCCR1_EndLnDel(var->right_margin);
-
-	/*
-	 * If we have a dual scan LCD, we need to halve
-	 * the YRES parameter.
-	 */
-	lines_per_panel = var->yres;
-	if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual)
-		lines_per_panel /= 2;
-
-	fbi->reg_lccr2 =
-		LCCR2_DisHght(lines_per_panel) +
-		LCCR2_VrtSnchWdth(var->vsync_len) +
-		LCCR2_BegFrmDel(var->upper_margin) +
-		LCCR2_EndFrmDel(var->lower_margin);
-
-	fbi->reg_lccr3 = fbi->lccr3 |
-		(var->sync & FB_SYNC_HOR_HIGH_ACT ?
-		 LCCR3_HorSnchH : LCCR3_HorSnchL) |
-		(var->sync & FB_SYNC_VERT_HIGH_ACT ?
-		 LCCR3_VrtSnchH : LCCR3_VrtSnchL);
-
-	if (pcd) {
-		fbi->reg_lccr3 |= LCCR3_PixClkDiv(pcd);
-		set_hsync_time(fbi, pcd);
-	}
-}
-
-/*
- * pxafb_activate_var():
- *	Configures LCD Controller based on entries in var parameter.
- *	Settings are only written to the controller if changes were made.
- */
-static int pxafb_activate_var(struct fb_var_screeninfo *var,
-			      struct pxafb_info *fbi)
-{
-	u_long flags;
-
-	/* Update shadow copy atomically */
-	local_irq_save(flags);
-
-#ifdef CONFIG_FB_PXA_SMARTPANEL
-	if (fbi->lccr0 & LCCR0_LCDT)
-		setup_smart_timing(fbi, var);
-	else
-#endif
-		setup_parallel_timing(fbi, var);
-
-	setup_base_frame(fbi, var, 0);
-
-	fbi->reg_lccr0 = fbi->lccr0 |
-		(LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
-		 LCCR0_QDM | LCCR0_BM  | LCCR0_OUM);
-
-	fbi->reg_lccr3 |= pxafb_var_to_lccr3(var);
-
-	fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK;
-	fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
-	local_irq_restore(flags);
-
-	/*
-	 * Only update the registers if the controller is enabled
-	 * and something has changed.
-	 */
-	if ((lcd_readl(fbi, LCCR0) != fbi->reg_lccr0) ||
-	    (lcd_readl(fbi, LCCR1) != fbi->reg_lccr1) ||
-	    (lcd_readl(fbi, LCCR2) != fbi->reg_lccr2) ||
-	    (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
-	    (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) ||
-	    (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
-	    ((fbi->lccr0 & LCCR0_SDS) &&
-	    (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])))
-		pxafb_schedule_work(fbi, C_REENABLE);
-
-	return 0;
-}
-
-/*
- * NOTE!  The following functions are purely helpers for set_ctrlr_state.
- * Do not call them directly; set_ctrlr_state does the correct serialisation
- * to ensure that things happen in the right way 100% of time time.
- *	-- rmk
- */
-static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
-{
-	pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
-
-	if (fbi->backlight_power)
-		fbi->backlight_power(on);
-}
-
-static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
-{
-	pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
-
-	if (fbi->lcd_power)
-		fbi->lcd_power(on, &fbi->fb.var);
-}
-
-static void pxafb_enable_controller(struct pxafb_info *fbi)
-{
-	pr_debug("pxafb: Enabling LCD controller\n");
-	pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr[0]);
-	pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr[1]);
-	pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
-	pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
-	pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
-	pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
-
-	/* enable LCD controller clock */
-	clk_prepare_enable(fbi->clk);
-
-	if (fbi->lccr0 & LCCR0_LCDT)
-		return;
-
-	/* Sequence from 11.7.10 */
-	lcd_writel(fbi, LCCR4, fbi->reg_lccr4);
-	lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
-	lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
-	lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
-	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
-
-	lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
-	if (fbi->lccr0 & LCCR0_SDS)
-		lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
-	lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
-}
-
-static void pxafb_disable_controller(struct pxafb_info *fbi)
-{
-	uint32_t lccr0;
-
-#ifdef CONFIG_FB_PXA_SMARTPANEL
-	if (fbi->lccr0 & LCCR0_LCDT) {
-		wait_for_completion_timeout(&fbi->refresh_done,
-				200 * HZ / 1000);
-		return;
-	}
-#endif
-
-	/* Clear LCD Status Register */
-	lcd_writel(fbi, LCSR, 0xffffffff);
-
-	lccr0 = lcd_readl(fbi, LCCR0) & ~LCCR0_LDM;
-	lcd_writel(fbi, LCCR0, lccr0);
-	lcd_writel(fbi, LCCR0, lccr0 | LCCR0_DIS);
-
-	wait_for_completion_timeout(&fbi->disable_done, 200 * HZ / 1000);
-
-	/* disable LCD controller clock */
-	clk_disable_unprepare(fbi->clk);
-}
-
-/*
- *  pxafb_handle_irq: Handle 'LCD DONE' interrupts.
- */
-static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
-{
-	struct pxafb_info *fbi = dev_id;
-	unsigned int lccr0, lcsr;
-
-	lcsr = lcd_readl(fbi, LCSR);
-	if (lcsr & LCSR_LDD) {
-		lccr0 = lcd_readl(fbi, LCCR0);
-		lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM);
-		complete(&fbi->disable_done);
-	}
-
-#ifdef CONFIG_FB_PXA_SMARTPANEL
-	if (lcsr & LCSR_CMD_INT)
-		complete(&fbi->command_done);
-#endif
-	lcd_writel(fbi, LCSR, lcsr);
-
-#ifdef CONFIG_FB_PXA_OVERLAY
-	{
-		unsigned int lcsr1 = lcd_readl(fbi, LCSR1);
-		if (lcsr1 & LCSR1_BS(1))
-			complete(&fbi->overlay[0].branch_done);
-
-		if (lcsr1 & LCSR1_BS(2))
-			complete(&fbi->overlay[1].branch_done);
-
-		lcd_writel(fbi, LCSR1, lcsr1);
-	}
-#endif
-	return IRQ_HANDLED;
-}
-
-/*
- * This function must be called from task context only, since it will
- * sleep when disabling the LCD controller, or if we get two contending
- * processes trying to alter state.
- */
-static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
-{
-	u_int old_state;
-
-	mutex_lock(&fbi->ctrlr_lock);
-
-	old_state = fbi->state;
-
-	/*
-	 * Hack around fbcon initialisation.
-	 */
-	if (old_state == C_STARTUP && state == C_REENABLE)
-		state = C_ENABLE;
-
-	switch (state) {
-	case C_DISABLE_CLKCHANGE:
-		/*
-		 * Disable controller for clock change.  If the
-		 * controller is already disabled, then do nothing.
-		 */
-		if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
-			fbi->state = state;
-			/* TODO __pxafb_lcd_power(fbi, 0); */
-			pxafb_disable_controller(fbi);
-		}
-		break;
-
-	case C_DISABLE_PM:
-	case C_DISABLE:
-		/*
-		 * Disable controller
-		 */
-		if (old_state != C_DISABLE) {
-			fbi->state = state;
-			__pxafb_backlight_power(fbi, 0);
-			__pxafb_lcd_power(fbi, 0);
-			if (old_state != C_DISABLE_CLKCHANGE)
-				pxafb_disable_controller(fbi);
-		}
-		break;
-
-	case C_ENABLE_CLKCHANGE:
-		/*
-		 * Enable the controller after clock change.  Only
-		 * do this if we were disabled for the clock change.
-		 */
-		if (old_state == C_DISABLE_CLKCHANGE) {
-			fbi->state = C_ENABLE;
-			pxafb_enable_controller(fbi);
-			/* TODO __pxafb_lcd_power(fbi, 1); */
-		}
-		break;
-
-	case C_REENABLE:
-		/*
-		 * Re-enable the controller only if it was already
-		 * enabled.  This is so we reprogram the control
-		 * registers.
-		 */
-		if (old_state == C_ENABLE) {
-			__pxafb_lcd_power(fbi, 0);
-			pxafb_disable_controller(fbi);
-			pxafb_enable_controller(fbi);
-			__pxafb_lcd_power(fbi, 1);
-		}
-		break;
-
-	case C_ENABLE_PM:
-		/*
-		 * Re-enable the controller after PM.  This is not
-		 * perfect - think about the case where we were doing
-		 * a clock change, and we suspended half-way through.
-		 */
-		if (old_state != C_DISABLE_PM)
-			break;
-		/* fall through */
-
-	case C_ENABLE:
-		/*
-		 * Power up the LCD screen, enable controller, and
-		 * turn on the backlight.
-		 */
-		if (old_state != C_ENABLE) {
-			fbi->state = C_ENABLE;
-			pxafb_enable_controller(fbi);
-			__pxafb_lcd_power(fbi, 1);
-			__pxafb_backlight_power(fbi, 1);
-		}
-		break;
-	}
-	mutex_unlock(&fbi->ctrlr_lock);
-}
-
-/*
- * Our LCD controller task (which is called when we blank or unblank)
- * via keventd.
- */
-static void pxafb_task(struct work_struct *work)
-{
-	struct pxafb_info *fbi =
-		container_of(work, struct pxafb_info, task);
-	u_int state = xchg(&fbi->task_state, -1);
-
-	set_ctrlr_state(fbi, state);
-}
-
-#ifdef CONFIG_CPU_FREQ
-/*
- * CPU clock speed change handler.  We need to adjust the LCD timing
- * parameters when the CPU clock is adjusted by the power management
- * subsystem.
- *
- * TODO: Determine why f->new != 10*get_lclk_frequency_10khz()
- */
-static int
-pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
-{
-	struct pxafb_info *fbi = TO_INF(nb, freq_transition);
-	/* TODO struct cpufreq_freqs *f = data; */
-	u_int pcd;
-
-	switch (val) {
-	case CPUFREQ_PRECHANGE:
-#ifdef CONFIG_FB_PXA_OVERLAY
-		if (!(fbi->overlay[0].usage || fbi->overlay[1].usage))
-#endif
-			set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
-		break;
-
-	case CPUFREQ_POSTCHANGE:
-		pcd = get_pcd(fbi, fbi->fb.var.pixclock);
-		set_hsync_time(fbi, pcd);
-		fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) |
-				  LCCR3_PixClkDiv(pcd);
-		set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
-		break;
-	}
-	return 0;
-}
-
-static int
-pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data)
-{
-	struct pxafb_info *fbi = TO_INF(nb, freq_policy);
-	struct fb_var_screeninfo *var = &fbi->fb.var;
-	struct cpufreq_policy *policy = data;
-
-	switch (val) {
-	case CPUFREQ_ADJUST:
-	case CPUFREQ_INCOMPATIBLE:
-		pr_debug("min dma period: %d ps, "
-			"new clock %d kHz\n", pxafb_display_dma_period(var),
-			policy->max);
-		/* TODO: fill in min/max values */
-		break;
-	}
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PM
-/*
- * Power management hooks.  Note that we won't be called from IRQ context,
- * unlike the blank functions above, so we may sleep.
- */
-static int pxafb_suspend(struct device *dev)
-{
-	struct pxafb_info *fbi = dev_get_drvdata(dev);
-
-	set_ctrlr_state(fbi, C_DISABLE_PM);
-	return 0;
-}
-
-static int pxafb_resume(struct device *dev)
-{
-	struct pxafb_info *fbi = dev_get_drvdata(dev);
-
-	set_ctrlr_state(fbi, C_ENABLE_PM);
-	return 0;
-}
-
-static const struct dev_pm_ops pxafb_pm_ops = {
-	.suspend	= pxafb_suspend,
-	.resume		= pxafb_resume,
-};
-#endif
-
-static int pxafb_init_video_memory(struct pxafb_info *fbi)
-{
-	int size = PAGE_ALIGN(fbi->video_mem_size);
-
-	fbi->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
-	if (fbi->video_mem == NULL)
-		return -ENOMEM;
-
-	fbi->video_mem_phys = virt_to_phys(fbi->video_mem);
-	fbi->video_mem_size = size;
-
-	fbi->fb.fix.smem_start	= fbi->video_mem_phys;
-	fbi->fb.fix.smem_len	= fbi->video_mem_size;
-	fbi->fb.screen_base	= fbi->video_mem;
-
-	return fbi->video_mem ? 0 : -ENOMEM;
-}
-
-static void pxafb_decode_mach_info(struct pxafb_info *fbi,
-				   struct pxafb_mach_info *inf)
-{
-	unsigned int lcd_conn = inf->lcd_conn;
-	struct pxafb_mode_info *m;
-	int i;
-
-	fbi->cmap_inverse	= inf->cmap_inverse;
-	fbi->cmap_static	= inf->cmap_static;
-	fbi->lccr4 		= inf->lccr4;
-
-	switch (lcd_conn & LCD_TYPE_MASK) {
-	case LCD_TYPE_MONO_STN:
-		fbi->lccr0 = LCCR0_CMS;
-		break;
-	case LCD_TYPE_MONO_DSTN:
-		fbi->lccr0 = LCCR0_CMS | LCCR0_SDS;
-		break;
-	case LCD_TYPE_COLOR_STN:
-		fbi->lccr0 = 0;
-		break;
-	case LCD_TYPE_COLOR_DSTN:
-		fbi->lccr0 = LCCR0_SDS;
-		break;
-	case LCD_TYPE_COLOR_TFT:
-		fbi->lccr0 = LCCR0_PAS;
-		break;
-	case LCD_TYPE_SMART_PANEL:
-		fbi->lccr0 = LCCR0_LCDT | LCCR0_PAS;
-		break;
-	default:
-		/* fall back to backward compatibility way */
-		fbi->lccr0 = inf->lccr0;
-		fbi->lccr3 = inf->lccr3;
-		goto decode_mode;
-	}
-
-	if (lcd_conn == LCD_MONO_STN_8BPP)
-		fbi->lccr0 |= LCCR0_DPD;
-
-	fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;
-
-	fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
-	fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
-	fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL)  ? LCCR3_PCP : 0;
-
-decode_mode:
-	pxafb_setmode(&fbi->fb.var, &inf->modes[0]);
-
-	/* decide video memory size as follows:
-	 * 1. default to mode of maximum resolution
-	 * 2. allow platform to override
-	 * 3. allow module parameter to override
-	 */
-	for (i = 0, m = &inf->modes[0]; i < inf->num_modes; i++, m++)
-		fbi->video_mem_size = max_t(size_t, fbi->video_mem_size,
-				m->xres * m->yres * m->bpp / 8);
-
-	if (inf->video_mem_size > fbi->video_mem_size)
-		fbi->video_mem_size = inf->video_mem_size;
-
-	if (video_mem_size > fbi->video_mem_size)
-		fbi->video_mem_size = video_mem_size;
-}
-
-static struct pxafb_info *pxafb_init_fbinfo(struct device *dev)
-{
-	struct pxafb_info *fbi;
-	void *addr;
-	struct pxafb_mach_info *inf = dev_get_platdata(dev);
-
-	/* Alloc the pxafb_info and pseudo_palette in one step */
-	fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
-	if (!fbi)
-		return NULL;
-
-	memset(fbi, 0, sizeof(struct pxafb_info));
-	fbi->dev = dev;
-
-	fbi->clk = clk_get(dev, NULL);
-	if (IS_ERR(fbi->clk)) {
-		kfree(fbi);
-		return NULL;
-	}
-
-	strcpy(fbi->fb.fix.id, PXA_NAME);
-
-	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
-	fbi->fb.fix.type_aux	= 0;
-	fbi->fb.fix.xpanstep	= 0;
-	fbi->fb.fix.ypanstep	= 1;
-	fbi->fb.fix.ywrapstep	= 0;
-	fbi->fb.fix.accel	= FB_ACCEL_NONE;
-
-	fbi->fb.var.nonstd	= 0;
-	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
-	fbi->fb.var.height	= -1;
-	fbi->fb.var.width	= -1;
-	fbi->fb.var.accel_flags	= FB_ACCELF_TEXT;
-	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
-
-	fbi->fb.fbops		= &pxafb_ops;
-	fbi->fb.flags		= FBINFO_DEFAULT;
-	fbi->fb.node		= -1;
-
-	addr = fbi;
-	addr = addr + sizeof(struct pxafb_info);
-	fbi->fb.pseudo_palette	= addr;
-
-	fbi->state		= C_STARTUP;
-	fbi->task_state		= (u_char)-1;
-
-	pxafb_decode_mach_info(fbi, inf);
-
-#ifdef CONFIG_FB_PXA_OVERLAY
-	/* place overlay(s) on top of base */
-	if (pxafb_overlay_supported())
-		fbi->lccr0 |= LCCR0_OUC;
-#endif
-
-	init_waitqueue_head(&fbi->ctrlr_wait);
-	INIT_WORK(&fbi->task, pxafb_task);
-	mutex_init(&fbi->ctrlr_lock);
-	init_completion(&fbi->disable_done);
-
-	return fbi;
-}
-
-#ifdef CONFIG_FB_PXA_PARAMETERS
-static int parse_opt_mode(struct device *dev, const char *this_opt)
-{
-	struct pxafb_mach_info *inf = dev_get_platdata(dev);
-
-	const char *name = this_opt+5;
-	unsigned int namelen = strlen(name);
-	int res_specified = 0, bpp_specified = 0;
-	unsigned int xres = 0, yres = 0, bpp = 0;
-	int yres_specified = 0;
-	int i;
-	for (i = namelen-1; i >= 0; i--) {
-		switch (name[i]) {
-		case '-':
-			namelen = i;
-			if (!bpp_specified && !yres_specified) {
-				bpp = simple_strtoul(&name[i+1], NULL, 0);
-				bpp_specified = 1;
-			} else
-				goto done;
-			break;
-		case 'x':
-			if (!yres_specified) {
-				yres = simple_strtoul(&name[i+1], NULL, 0);
-				yres_specified = 1;
-			} else
-				goto done;
-			break;
-		case '0' ... '9':
-			break;
-		default:
-			goto done;
-		}
-	}
-	if (i < 0 && yres_specified) {
-		xres = simple_strtoul(name, NULL, 0);
-		res_specified = 1;
-	}
-done:
-	if (res_specified) {
-		dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
-		inf->modes[0].xres = xres; inf->modes[0].yres = yres;
-	}
-	if (bpp_specified)
-		switch (bpp) {
-		case 1:
-		case 2:
-		case 4:
-		case 8:
-		case 16:
-			inf->modes[0].bpp = bpp;
-			dev_info(dev, "overriding bit depth: %d\n", bpp);
-			break;
-		default:
-			dev_err(dev, "Depth %d is not valid\n", bpp);
-			return -EINVAL;
-		}
-	return 0;
-}
-
-static int parse_opt(struct device *dev, char *this_opt)
-{
-	struct pxafb_mach_info *inf = dev_get_platdata(dev);
-	struct pxafb_mode_info *mode = &inf->modes[0];
-	char s[64];
-
-	s[0] = '\0';
-
-	if (!strncmp(this_opt, "vmem:", 5)) {
-		video_mem_size = memparse(this_opt + 5, NULL);
-	} else if (!strncmp(this_opt, "mode:", 5)) {
-		return parse_opt_mode(dev, this_opt);
-	} else if (!strncmp(this_opt, "pixclock:", 9)) {
-		mode->pixclock = simple_strtoul(this_opt+9, NULL, 0);
-		sprintf(s, "pixclock: %ld\n", mode->pixclock);
-	} else if (!strncmp(this_opt, "left:", 5)) {
-		mode->left_margin = simple_strtoul(this_opt+5, NULL, 0);
-		sprintf(s, "left: %u\n", mode->left_margin);
-	} else if (!strncmp(this_opt, "right:", 6)) {
-		mode->right_margin = simple_strtoul(this_opt+6, NULL, 0);
-		sprintf(s, "right: %u\n", mode->right_margin);
-	} else if (!strncmp(this_opt, "upper:", 6)) {
-		mode->upper_margin = simple_strtoul(this_opt+6, NULL, 0);
-		sprintf(s, "upper: %u\n", mode->upper_margin);
-	} else if (!strncmp(this_opt, "lower:", 6)) {
-		mode->lower_margin = simple_strtoul(this_opt+6, NULL, 0);
-		sprintf(s, "lower: %u\n", mode->lower_margin);
-	} else if (!strncmp(this_opt, "hsynclen:", 9)) {
-		mode->hsync_len = simple_strtoul(this_opt+9, NULL, 0);
-		sprintf(s, "hsynclen: %u\n", mode->hsync_len);
-	} else if (!strncmp(this_opt, "vsynclen:", 9)) {
-		mode->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
-		sprintf(s, "vsynclen: %u\n", mode->vsync_len);
-	} else if (!strncmp(this_opt, "hsync:", 6)) {
-		if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
-			sprintf(s, "hsync: Active Low\n");
-			mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;
-		} else {
-			sprintf(s, "hsync: Active High\n");
-			mode->sync |= FB_SYNC_HOR_HIGH_ACT;
-		}
-	} else if (!strncmp(this_opt, "vsync:", 6)) {
-		if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
-			sprintf(s, "vsync: Active Low\n");
-			mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;
-		} else {
-			sprintf(s, "vsync: Active High\n");
-			mode->sync |= FB_SYNC_VERT_HIGH_ACT;
-		}
-	} else if (!strncmp(this_opt, "dpc:", 4)) {
-		if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
-			sprintf(s, "double pixel clock: false\n");
-			inf->lccr3 &= ~LCCR3_DPC;
-		} else {
-			sprintf(s, "double pixel clock: true\n");
-			inf->lccr3 |= LCCR3_DPC;
-		}
-	} else if (!strncmp(this_opt, "outputen:", 9)) {
-		if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
-			sprintf(s, "output enable: active low\n");
-			inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
-		} else {
-			sprintf(s, "output enable: active high\n");
-			inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
-		}
-	} else if (!strncmp(this_opt, "pixclockpol:", 12)) {
-		if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
-			sprintf(s, "pixel clock polarity: falling edge\n");
-			inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
-		} else {
-			sprintf(s, "pixel clock polarity: rising edge\n");
-			inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
-		}
-	} else if (!strncmp(this_opt, "color", 5)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
-	} else if (!strncmp(this_opt, "mono", 4)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
-	} else if (!strncmp(this_opt, "active", 6)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
-	} else if (!strncmp(this_opt, "passive", 7)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
-	} else if (!strncmp(this_opt, "single", 6)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
-	} else if (!strncmp(this_opt, "dual", 4)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
-	} else if (!strncmp(this_opt, "4pix", 4)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
-	} else if (!strncmp(this_opt, "8pix", 4)) {
-		inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
-	} else {
-		dev_err(dev, "unknown option: %s\n", this_opt);
-		return -EINVAL;
-	}
-
-	if (s[0] != '\0')
-		dev_info(dev, "override %s", s);
-
-	return 0;
-}
-
-static int pxafb_parse_options(struct device *dev, char *options)
-{
-	char *this_opt;
-	int ret;
-
-	if (!options || !*options)
-		return 0;
-
-	dev_dbg(dev, "options are \"%s\"\n", options ? options : "null");
-
-	/* could be made table driven or similar?... */
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		ret = parse_opt(dev, this_opt);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
-static char g_options[256] = "";
-
-#ifndef MODULE
-static int __init pxafb_setup_options(void)
-{
-	char *options = NULL;
-
-	if (fb_get_options("pxafb", &options))
-		return -ENODEV;
-
-	if (options)
-		strlcpy(g_options, options, sizeof(g_options));
-
-	return 0;
-}
-#else
-#define pxafb_setup_options()		(0)
-
-module_param_string(options, g_options, sizeof(g_options), 0);
-MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
-#endif
-
-#else
-#define pxafb_parse_options(...)	(0)
-#define pxafb_setup_options()		(0)
-#endif
-
-#ifdef DEBUG_VAR
-/* Check for various illegal bit-combinations. Currently only
- * a warning is given. */
-static void pxafb_check_options(struct device *dev, struct pxafb_mach_info *inf)
-{
-	if (inf->lcd_conn)
-		return;
-
-	if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
-		dev_warn(dev, "machine LCCR0 setting contains "
-				"illegal bits: %08x\n",
-			inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
-	if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
-		dev_warn(dev, "machine LCCR3 setting contains "
-				"illegal bits: %08x\n",
-			inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
-	if (inf->lccr0 & LCCR0_DPD &&
-	    ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
-	     (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
-	     (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
-		dev_warn(dev, "Double Pixel Data (DPD) mode is "
-				"only valid in passive mono"
-				" single panel mode\n");
-	if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
-	    (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
-		dev_warn(dev, "Dual panel only valid in passive mode\n");
-	if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
-	     (inf->modes->upper_margin || inf->modes->lower_margin))
-		dev_warn(dev, "Upper and lower margins must be 0 in "
-				"passive mode\n");
-}
-#else
-#define pxafb_check_options(...)	do {} while (0)
-#endif
-
-static int pxafb_probe(struct platform_device *dev)
-{
-	struct pxafb_info *fbi;
-	struct pxafb_mach_info *inf;
-	struct resource *r;
-	int irq, ret;
-
-	dev_dbg(&dev->dev, "pxafb_probe\n");
-
-	inf = dev_get_platdata(&dev->dev);
-	ret = -ENOMEM;
-	fbi = NULL;
-	if (!inf)
-		goto failed;
-
-	ret = pxafb_parse_options(&dev->dev, g_options);
-	if (ret < 0)
-		goto failed;
-
-	pxafb_check_options(&dev->dev, inf);
-
-	dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
-			inf->modes->xres,
-			inf->modes->yres,
-			inf->modes->bpp);
-	if (inf->modes->xres == 0 ||
-	    inf->modes->yres == 0 ||
-	    inf->modes->bpp == 0) {
-		dev_err(&dev->dev, "Invalid resolution or bit depth\n");
-		ret = -EINVAL;
-		goto failed;
-	}
-
-	fbi = pxafb_init_fbinfo(&dev->dev);
-	if (!fbi) {
-		/* only reason for pxafb_init_fbinfo to fail is kmalloc */
-		dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
-		ret = -ENOMEM;
-		goto failed;
-	}
-
-	if (cpu_is_pxa3xx() && inf->acceleration_enabled)
-		fbi->fb.fix.accel = FB_ACCEL_PXA3XX;
-
-	fbi->backlight_power = inf->pxafb_backlight_power;
-	fbi->lcd_power = inf->pxafb_lcd_power;
-
-	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		dev_err(&dev->dev, "no I/O memory resource defined\n");
-		ret = -ENODEV;
-		goto failed_fbi;
-	}
-
-	r = request_mem_region(r->start, resource_size(r), dev->name);
-	if (r == NULL) {
-		dev_err(&dev->dev, "failed to request I/O memory\n");
-		ret = -EBUSY;
-		goto failed_fbi;
-	}
-
-	fbi->mmio_base = ioremap(r->start, resource_size(r));
-	if (fbi->mmio_base == NULL) {
-		dev_err(&dev->dev, "failed to map I/O memory\n");
-		ret = -EBUSY;
-		goto failed_free_res;
-	}
-
-	fbi->dma_buff_size = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
-	fbi->dma_buff = dma_alloc_coherent(fbi->dev, fbi->dma_buff_size,
-				&fbi->dma_buff_phys, GFP_KERNEL);
-	if (fbi->dma_buff == NULL) {
-		dev_err(&dev->dev, "failed to allocate memory for DMA\n");
-		ret = -ENOMEM;
-		goto failed_free_io;
-	}
-
-	ret = pxafb_init_video_memory(fbi);
-	if (ret) {
-		dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
-		ret = -ENOMEM;
-		goto failed_free_dma;
-	}
-
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0) {
-		dev_err(&dev->dev, "no IRQ defined\n");
-		ret = -ENODEV;
-		goto failed_free_mem;
-	}
-
-	ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi);
-	if (ret) {
-		dev_err(&dev->dev, "request_irq failed: %d\n", ret);
-		ret = -EBUSY;
-		goto failed_free_mem;
-	}
-
-	ret = pxafb_smart_init(fbi);
-	if (ret) {
-		dev_err(&dev->dev, "failed to initialize smartpanel\n");
-		goto failed_free_irq;
-	}
-
-	/*
-	 * This makes sure that our colour bitfield
-	 * descriptors are correctly initialised.
-	 */
-	ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);
-	if (ret) {
-		dev_err(&dev->dev, "failed to get suitable mode\n");
-		goto failed_free_irq;
-	}
-
-	ret = pxafb_set_par(&fbi->fb);
-	if (ret) {
-		dev_err(&dev->dev, "Failed to set parameters\n");
-		goto failed_free_irq;
-	}
-
-	platform_set_drvdata(dev, fbi);
-
-	ret = register_framebuffer(&fbi->fb);
-	if (ret < 0) {
-		dev_err(&dev->dev,
-			"Failed to register framebuffer device: %d\n", ret);
-		goto failed_free_cmap;
-	}
-
-	pxafb_overlay_init(fbi);
-
-#ifdef CONFIG_CPU_FREQ
-	fbi->freq_transition.notifier_call = pxafb_freq_transition;
-	fbi->freq_policy.notifier_call = pxafb_freq_policy;
-	cpufreq_register_notifier(&fbi->freq_transition,
-				CPUFREQ_TRANSITION_NOTIFIER);
-	cpufreq_register_notifier(&fbi->freq_policy,
-				CPUFREQ_POLICY_NOTIFIER);
-#endif
-
-	/*
-	 * Ok, now enable the LCD controller
-	 */
-	set_ctrlr_state(fbi, C_ENABLE);
-
-	return 0;
-
-failed_free_cmap:
-	if (fbi->fb.cmap.len)
-		fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_irq:
-	free_irq(irq, fbi);
-failed_free_mem:
-	free_pages_exact(fbi->video_mem, fbi->video_mem_size);
-failed_free_dma:
-	dma_free_coherent(&dev->dev, fbi->dma_buff_size,
-			fbi->dma_buff, fbi->dma_buff_phys);
-failed_free_io:
-	iounmap(fbi->mmio_base);
-failed_free_res:
-	release_mem_region(r->start, resource_size(r));
-failed_fbi:
-	clk_put(fbi->clk);
-	kfree(fbi);
-failed:
-	return ret;
-}
-
-static int pxafb_remove(struct platform_device *dev)
-{
-	struct pxafb_info *fbi = platform_get_drvdata(dev);
-	struct resource *r;
-	int irq;
-	struct fb_info *info;
-
-	if (!fbi)
-		return 0;
-
-	info = &fbi->fb;
-
-	pxafb_overlay_exit(fbi);
-	unregister_framebuffer(info);
-
-	pxafb_disable_controller(fbi);
-
-	if (fbi->fb.cmap.len)
-		fb_dealloc_cmap(&fbi->fb.cmap);
-
-	irq = platform_get_irq(dev, 0);
-	free_irq(irq, fbi);
-
-	free_pages_exact(fbi->video_mem, fbi->video_mem_size);
-
-	dma_free_writecombine(&dev->dev, fbi->dma_buff_size,
-			fbi->dma_buff, fbi->dma_buff_phys);
-
-	iounmap(fbi->mmio_base);
-
-	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, resource_size(r));
-
-	clk_put(fbi->clk);
-	kfree(fbi);
-
-	return 0;
-}
-
-static struct platform_driver pxafb_driver = {
-	.probe		= pxafb_probe,
-	.remove 	= pxafb_remove,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "pxa2xx-fb",
-#ifdef CONFIG_PM
-		.pm	= &pxafb_pm_ops,
-#endif
-	},
-};
-
-static int __init pxafb_init(void)
-{
-	if (pxafb_setup_options())
-		return -EINVAL;
-
-	return platform_driver_register(&pxafb_driver);
-}
-
-static void __exit pxafb_exit(void)
-{
-	platform_driver_unregister(&pxafb_driver);
-}
-
-module_init(pxafb_init);
-module_exit(pxafb_exit);
-
-MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
deleted file mode 100644
index 26ba9fa3f737..000000000000
--- a/drivers/video/pxafb.h
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef __PXAFB_H__
-#define __PXAFB_H__
-
-/*
- * linux/drivers/video/pxafb.h
- *    -- Intel PXA250/210 LCD Controller Frame Buffer Device
- *
- *  Copyright (C) 1999 Eric A. Thomas.
- *  Copyright (C) 2004 Jean-Frederic Clere.
- *  Copyright (C) 2004 Ian Campbell.
- *  Copyright (C) 2004 Jeff Lackey.
- *   Based on sa1100fb.c Copyright (C) 1999 Eric A. Thomas
- *  which in turn is
- *   Based on acornfb.c Copyright (C) Russell King.
- *
- *  2001-08-03: Cliff Brake <cbrake@acclent.com>
- *	 - ported SA1100 code to PXA
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/* PXA LCD DMA descriptor */
-struct pxafb_dma_descriptor {
-	unsigned int fdadr;
-	unsigned int fsadr;
-	unsigned int fidr;
-	unsigned int ldcmd;
-};
-
-enum {
-	PAL_NONE	= -1,
-	PAL_BASE	= 0,
-	PAL_OV1		= 1,
-	PAL_OV2		= 2,
-	PAL_MAX,
-};
-
-enum {
-	DMA_BASE	= 0,
-	DMA_UPPER	= 0,
-	DMA_LOWER	= 1,
-	DMA_OV1		= 1,
-	DMA_OV2_Y	= 2,
-	DMA_OV2_Cb	= 3,
-	DMA_OV2_Cr	= 4,
-	DMA_CURSOR	= 5,
-	DMA_CMD		= 6,
-	DMA_MAX,
-};
-
-/* maximum palette size - 256 entries, each 4 bytes long */
-#define PALETTE_SIZE	(256 * 4)
-#define CMD_BUFF_SIZE	(1024 * 50)
-
-/* NOTE: the palette and frame dma descriptors are doubled to allow
- * the 2nd set for branch settings (FBRx)
- */
-struct pxafb_dma_buff {
-	unsigned char palette[PAL_MAX * PALETTE_SIZE];
-	uint16_t cmd_buff[CMD_BUFF_SIZE];
-	struct pxafb_dma_descriptor pal_desc[PAL_MAX * 2];
-	struct pxafb_dma_descriptor dma_desc[DMA_MAX * 2];
-};
-
-enum {
-	OVERLAY1,
-	OVERLAY2,
-};
-
-enum {
-	OVERLAY_FORMAT_RGB = 0,
-	OVERLAY_FORMAT_YUV444_PACKED,
-	OVERLAY_FORMAT_YUV444_PLANAR,
-	OVERLAY_FORMAT_YUV422_PLANAR,
-	OVERLAY_FORMAT_YUV420_PLANAR,
-};
-
-#define NONSTD_TO_XPOS(x)	(((x) >> 0)  & 0x3ff)
-#define NONSTD_TO_YPOS(x)	(((x) >> 10) & 0x3ff)
-#define NONSTD_TO_PFOR(x)	(((x) >> 20) & 0x7)
-
-struct pxafb_layer;
-
-struct pxafb_layer_ops {
-	void (*enable)(struct pxafb_layer *);
-	void (*disable)(struct pxafb_layer *);
-	void (*setup)(struct pxafb_layer *);
-};
-
-struct pxafb_layer {
-	struct fb_info		fb;
-	int			id;
-	int			registered;
-	uint32_t		usage;
-	uint32_t		control[2];
-
-	struct pxafb_layer_ops	*ops;
-
-	void __iomem		*video_mem;
-	unsigned long		video_mem_phys;
-	size_t			video_mem_size;
-	struct completion	branch_done;
-
-	struct pxafb_info	*fbi;
-};
-
-struct pxafb_info {
-	struct fb_info		fb;
-	struct device		*dev;
-	struct clk		*clk;
-
-	void __iomem		*mmio_base;
-
-	struct pxafb_dma_buff	*dma_buff;
-	size_t			dma_buff_size;
-	dma_addr_t		dma_buff_phys;
-	dma_addr_t		fdadr[DMA_MAX * 2];
-
-	void __iomem		*video_mem;	/* virtual address of frame buffer */
-	unsigned long		video_mem_phys;	/* physical address of frame buffer */
-	size_t			video_mem_size;	/* size of the frame buffer */
-	u16 *			palette_cpu;	/* virtual address of palette memory */
-	u_int			palette_size;
-
-	u_int			lccr0;
-	u_int			lccr3;
-	u_int			lccr4;
-	u_int			cmap_inverse:1,
-				cmap_static:1,
-				unused:30;
-
-	u_int			reg_lccr0;
-	u_int			reg_lccr1;
-	u_int			reg_lccr2;
-	u_int			reg_lccr3;
-	u_int			reg_lccr4;
-	u_int			reg_cmdcr;
-
-	unsigned long	hsync_time;
-
-	volatile u_char		state;
-	volatile u_char		task_state;
-	struct mutex		ctrlr_lock;
-	wait_queue_head_t	ctrlr_wait;
-	struct work_struct	task;
-
-	struct completion	disable_done;
-
-#ifdef CONFIG_FB_PXA_SMARTPANEL
-	uint16_t		*smart_cmds;
-	size_t			n_smart_cmds;
-	struct completion	command_done;
-	struct completion	refresh_done;
-	struct task_struct	*smart_thread;
-#endif
-
-#ifdef CONFIG_FB_PXA_OVERLAY
-	struct pxafb_layer	overlay[2];
-#endif
-
-#ifdef CONFIG_CPU_FREQ
-	struct notifier_block	freq_transition;
-	struct notifier_block	freq_policy;
-#endif
-
-	void (*lcd_power)(int, struct fb_var_screeninfo *);
-	void (*backlight_power)(int);
-};
-
-#define TO_INF(ptr,member) container_of(ptr,struct pxafb_info,member)
-
-/*
- * These are the actions for set_ctrlr_state
- */
-#define C_DISABLE		(0)
-#define C_ENABLE		(1)
-#define C_DISABLE_CLKCHANGE	(2)
-#define C_ENABLE_CLKCHANGE	(3)
-#define C_REENABLE		(4)
-#define C_DISABLE_PM		(5)
-#define C_ENABLE_PM		(6)
-#define C_STARTUP		(7)
-
-#define PXA_NAME	"PXA"
-
-/*
- * Minimum X and Y resolutions
- */
-#define MIN_XRES	64
-#define MIN_YRES	64
-
-/* maximum X and Y resolutions - note these are limits from the register
- * bits length instead of the real ones
- */
-#define MAX_XRES	1024
-#define MAX_YRES	1024
-
-#endif /* __PXAFB_H__ */
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
deleted file mode 100644
index 7487f76f6275..000000000000
--- a/drivers/video/q40fb.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * linux/drivers/video/q40fb.c -- Q40 frame buffer device
- *
- * Copyright (C) 2001
- *
- *      Richard Zidlicky <rz@linux-m68k.org>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <asm/uaccess.h>
-#include <asm/setup.h>
-#include <asm/q40_master.h>
-#include <linux/fb.h>
-#include <linux/module.h>
-#include <asm/pgtable.h>
-
-#define Q40_PHYS_SCREEN_ADDR 0xFE800000
-
-static struct fb_fix_screeninfo q40fb_fix = {
-	.id		= "Q40",
-	.smem_len	= 1024*1024,
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_TRUECOLOR,
-	.line_length	= 1024*2,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo q40fb_var = {
-	.xres		= 1024,
-	.yres		= 512,
-	.xres_virtual	= 1024,
-	.yres_virtual	= 512,
-	.bits_per_pixel	= 16,
-    	.red		= {6, 5, 0},
-	.green		= {11, 5, 0},
-	.blue		= {0, 6, 0},
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= 230,
-	.width		= 300,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-    /*
-     *  Set a single color register. The values supplied have a 16 bit
-     *  magnitude.
-     *  Return != 0 for invalid regno.
-     */
-
-    if (regno > 255)
-	    return 1;
-    red>>=11;
-    green>>=11;
-    blue>>=10;
-
-    if (regno < 16) {
-	((u32 *)info->pseudo_palette)[regno] = ((red & 31) <<6) |
-					       ((green & 31) << 11) |
-					       (blue & 63);
-    }
-    return 0;
-}
-
-static struct fb_ops q40fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= q40fb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int q40fb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-
-	if (!MACH_IS_Q40)
-		return -ENXIO;
-
-	/* mapped in q40/config.c */
-	q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR;
-
-	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	info->var = q40fb_var;
-	info->fix = q40fb_fix;
-	info->fbops = &q40fb_ops;
-	info->flags = FBINFO_DEFAULT;  /* not as module for now */
-	info->pseudo_palette = info->par;
-	info->par = NULL;
-	info->screen_base = (char *) q40fb_fix.smem_start;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		framebuffer_release(info);
-		return -ENOMEM;
-	}
-
-	master_outb(3, DISPLAY_CONTROL_REG);
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "Unable to register Q40 frame buffer\n");
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-		return -EINVAL;
-	}
-
-	fb_info(info, "Q40 frame buffer alive and kicking !\n");
-	return 0;
-}
-
-static struct platform_driver q40fb_driver = {
-	.probe	= q40fb_probe,
-	.driver	= {
-		.name	= "q40fb",
-	},
-};
-
-static struct platform_device q40fb_device = {
-	.name	= "q40fb",
-};
-
-int __init q40fb_init(void)
-{
-	int ret = 0;
-
-	if (fb_get_options("q40fb", NULL))
-		return -ENODEV;
-
-	ret = platform_driver_register(&q40fb_driver);
-
-	if (!ret) {
-		ret = platform_device_register(&q40fb_device);
-		if (ret)
-			platform_driver_unregister(&q40fb_driver);
-	}
-	return ret;
-}
-
-module_init(q40fb_init);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/Makefile b/drivers/video/riva/Makefile
deleted file mode 100644
index 8898c9915b02..000000000000
--- a/drivers/video/riva/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the Riva framebuffer driver
-#
-
-obj-$(CONFIG_FB_RIVA)     += rivafb.o
-
-rivafb-objs               := fbdev.o riva_hw.o nv_driver.o
-
-ifdef CONFIG_FB_RIVA_I2C
-	rivafb-objs       += rivafb-i2c.o
-endif
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
deleted file mode 100644
index 8a8d7f060784..000000000000
--- a/drivers/video/riva/fbdev.c
+++ /dev/null
@@ -1,2230 +0,0 @@
-/*
- * linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
- *
- * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
- *
- * Copyright 1999-2000 Jeff Garzik
- *
- * Contributors:
- *
- *	Ani Joshi:  Lots of debugging and cleanup work, really helped
- *	get the driver going
- *
- *	Ferenc Bakonyi:  Bug fixes, cleanup, modularization
- *
- *	Jindrich Makovicka:  Accel code help, hw cursor, mtrr
- *
- *	Paul Richards:  Bug fixes, updates
- *
- * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
- * Includes riva_hw.c from nVidia, see copyright below.
- * KGI code provided the basis for state storage, init, and mode switching.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- * Known bugs and issues:
- *	restoring text mode fails
- *	doublescan modes are broken
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/backlight.h>
-#include <linux/bitrev.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-#ifdef CONFIG_PPC_OF
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/machdep.h>
-#include <asm/backlight.h>
-#endif
-
-#include "rivafb.h"
-#include "nvreg.h"
-
-/* version number of this driver */
-#define RIVAFB_VERSION "0.9.5b"
-
-/* ------------------------------------------------------------------------- *
- *
- * various helpful macros and constants
- *
- * ------------------------------------------------------------------------- */
-#ifdef CONFIG_FB_RIVA_DEBUG
-#define NVTRACE          printk
-#else
-#define NVTRACE          if(0) printk
-#endif
-
-#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __func__)
-#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __func__)
-
-#ifdef CONFIG_FB_RIVA_DEBUG
-#define assert(expr) \
-	if(!(expr)) { \
-	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-	#expr,__FILE__,__func__,__LINE__); \
-	BUG(); \
-	}
-#else
-#define assert(expr)
-#endif
-
-#define PFX "rivafb: "
-
-/* macro that allows you to set overflow bits */
-#define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
-#define SetBit(n)		(1<<(n))
-#define Set8Bits(value)		((value)&0xff)
-
-/* HW cursor parameters */
-#define MAX_CURS		32
-
-/* ------------------------------------------------------------------------- *
- *
- * prototypes
- *
- * ------------------------------------------------------------------------- */
-
-static int rivafb_blank(int blank, struct fb_info *info);
-
-/* ------------------------------------------------------------------------- *
- *
- * card identification
- *
- * ------------------------------------------------------------------------- */
-
-static struct pci_device_id rivafb_pci_tbl[] = {
-	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	// NF2/IGP version, GeForce 4 MX, NV18
-	{ PCI_VENDOR_ID_NVIDIA, 0x01f0,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0, } /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
-
-/* ------------------------------------------------------------------------- *
- *
- * global variables
- *
- * ------------------------------------------------------------------------- */
-
-/* command line data, set in rivafb_setup() */
-static int flatpanel = -1; /* Autodetect later */
-static int forceCRTC = -1;
-static bool noaccel  = 0;
-#ifdef CONFIG_MTRR
-static bool nomtrr = 0;
-#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight = 1;
-#else
-static int backlight = 0;
-#endif
-
-static char *mode_option = NULL;
-static bool strictmode       = 0;
-
-static struct fb_fix_screeninfo rivafb_fix = {
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.xpanstep	= 1,
-	.ypanstep	= 1,
-};
-
-static struct fb_var_screeninfo rivafb_default_var = {
-	.xres		= 640,
-	.yres		= 480,
-	.xres_virtual	= 640,
-	.yres_virtual	= 480,
-	.bits_per_pixel	= 8,
-	.red		= {0, 8, 0},
-	.green		= {0, 8, 0},
-	.blue		= {0, 8, 0},
-	.transp		= {0, 0, 0},
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.pixclock	= 39721,
-	.left_margin	= 40,
-	.right_margin	= 24,
-	.upper_margin	= 32,
-	.lower_margin	= 11,
-	.hsync_len	= 96,
-	.vsync_len	= 2,
-	.vmode		= FB_VMODE_NONINTERLACED
-};
-
-/* from GGI */
-static const struct riva_regs reg_template = {
-	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* ATTR */
-	 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	 0x41, 0x01, 0x0F, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* CRT  */
-	 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3,	/* 0x10 */
-	 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x20 */
-	 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x30 */
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00,							/* 0x40 */
-	 },
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,	/* GRA  */
-	 0xFF},
-	{0x03, 0x01, 0x0F, 0x00, 0x0E},				/* SEQ  */
-	0xEB							/* MISC */
-};
-
-/*
- * Backlight control
- */
-#ifdef CONFIG_FB_RIVA_BACKLIGHT
-/* We do not have any information about which values are allowed, thus
- * we used safe values.
- */
-#define MIN_LEVEL 0x158
-#define MAX_LEVEL 0x534
-#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
-
-static int riva_bl_get_level_brightness(struct riva_par *par,
-		int level)
-{
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int nlevel;
-
-	/* Get and convert the value */
-	/* No locking on bl_curve since accessing a single value */
-	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
-
-	if (nlevel < 0)
-		nlevel = 0;
-	else if (nlevel < MIN_LEVEL)
-		nlevel = MIN_LEVEL;
-	else if (nlevel > MAX_LEVEL)
-		nlevel = MAX_LEVEL;
-
-	return nlevel;
-}
-
-static int riva_bl_update_status(struct backlight_device *bd)
-{
-	struct riva_par *par = bl_get_data(bd);
-	U032 tmp_pcrt, tmp_pmc;
-	int level;
-
-	if (bd->props.power != FB_BLANK_UNBLANK ||
-	    bd->props.fb_blank != FB_BLANK_UNBLANK)
-		level = 0;
-	else
-		level = bd->props.brightness;
-
-	tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF;
-	tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC;
-	if(level > 0) {
-		tmp_pcrt |= 0x1;
-		tmp_pmc |= (1 << 31); /* backlight bit */
-		tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
-	}
-	NV_WR32(par->riva.PCRTC0, 0x081C, tmp_pcrt);
-	NV_WR32(par->riva.PMC, 0x10F0, tmp_pmc);
-
-	return 0;
-}
-
-static int riva_bl_get_brightness(struct backlight_device *bd)
-{
-	return bd->props.brightness;
-}
-
-static const struct backlight_ops riva_bl_ops = {
-	.get_brightness = riva_bl_get_brightness,
-	.update_status	= riva_bl_update_status,
-};
-
-static void riva_bl_init(struct riva_par *par)
-{
-	struct backlight_properties props;
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	struct backlight_device *bd;
-	char name[12];
-
-	if (!par->FlatPanel)
-		return;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (!machine_is(powermac) ||
-	    !pmac_has_backlight_type("mnca"))
-		return;
-#endif
-
-	snprintf(name, sizeof(name), "rivabl%d", info->node);
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
-	bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
-				       &props);
-	if (IS_ERR(bd)) {
-		info->bl_dev = NULL;
-		printk(KERN_WARNING "riva: Backlight registration failed\n");
-		goto error;
-	}
-
-	info->bl_dev = bd;
-	fb_bl_default_curve(info, 0,
-		MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,
-		FB_BACKLIGHT_MAX);
-
-	bd->props.brightness = bd->props.max_brightness;
-	bd->props.power = FB_BLANK_UNBLANK;
-	backlight_update_status(bd);
-
-	printk("riva: Backlight initialized (%s)\n", name);
-
-	return;
-
-error:
-	return;
-}
-
-static void riva_bl_exit(struct fb_info *info)
-{
-	struct backlight_device *bd = info->bl_dev;
-
-	backlight_device_unregister(bd);
-	printk("riva: Backlight unloaded\n");
-}
-#else
-static inline void riva_bl_init(struct riva_par *par) {}
-static inline void riva_bl_exit(struct fb_info *info) {}
-#endif /* CONFIG_FB_RIVA_BACKLIGHT */
-
-/* ------------------------------------------------------------------------- *
- *
- * MMIO access macros
- *
- * ------------------------------------------------------------------------- */
-
-static inline void CRTCout(struct riva_par *par, unsigned char index,
-			   unsigned char val)
-{
-	VGA_WR08(par->riva.PCIO, 0x3d4, index);
-	VGA_WR08(par->riva.PCIO, 0x3d5, val);
-}
-
-static inline unsigned char CRTCin(struct riva_par *par,
-				   unsigned char index)
-{
-	VGA_WR08(par->riva.PCIO, 0x3d4, index);
-	return (VGA_RD08(par->riva.PCIO, 0x3d5));
-}
-
-static inline void GRAout(struct riva_par *par, unsigned char index,
-			  unsigned char val)
-{
-	VGA_WR08(par->riva.PVIO, 0x3ce, index);
-	VGA_WR08(par->riva.PVIO, 0x3cf, val);
-}
-
-static inline unsigned char GRAin(struct riva_par *par,
-				  unsigned char index)
-{
-	VGA_WR08(par->riva.PVIO, 0x3ce, index);
-	return (VGA_RD08(par->riva.PVIO, 0x3cf));
-}
-
-static inline void SEQout(struct riva_par *par, unsigned char index,
-			  unsigned char val)
-{
-	VGA_WR08(par->riva.PVIO, 0x3c4, index);
-	VGA_WR08(par->riva.PVIO, 0x3c5, val);
-}
-
-static inline unsigned char SEQin(struct riva_par *par,
-				  unsigned char index)
-{
-	VGA_WR08(par->riva.PVIO, 0x3c4, index);
-	return (VGA_RD08(par->riva.PVIO, 0x3c5));
-}
-
-static inline void ATTRout(struct riva_par *par, unsigned char index,
-			   unsigned char val)
-{
-	VGA_WR08(par->riva.PCIO, 0x3c0, index);
-	VGA_WR08(par->riva.PCIO, 0x3c0, val);
-}
-
-static inline unsigned char ATTRin(struct riva_par *par,
-				   unsigned char index)
-{
-	VGA_WR08(par->riva.PCIO, 0x3c0, index);
-	return (VGA_RD08(par->riva.PCIO, 0x3c1));
-}
-
-static inline void MISCout(struct riva_par *par, unsigned char val)
-{
-	VGA_WR08(par->riva.PVIO, 0x3c2, val);
-}
-
-static inline unsigned char MISCin(struct riva_par *par)
-{
-	return (VGA_RD08(par->riva.PVIO, 0x3cc));
-}
-
-static inline void reverse_order(u32 *l)
-{
-	u8 *a = (u8 *)l;
-	a[0] = bitrev8(a[0]);
-	a[1] = bitrev8(a[1]);
-	a[2] = bitrev8(a[2]);
-	a[3] = bitrev8(a[3]);
-}
-
-/* ------------------------------------------------------------------------- *
- *
- * cursor stuff
- *
- * ------------------------------------------------------------------------- */
-
-/**
- * rivafb_load_cursor_image - load cursor image to hardware
- * @data: address to monochrome bitmap (1 = foreground color, 0 = background)
- * @par:  pointer to private data
- * @w:    width of cursor image in pixels
- * @h:    height of cursor image in scanlines
- * @bg:   background color (ARGB1555) - alpha bit determines opacity
- * @fg:   foreground color (ARGB1555)
- *
- * DESCRIPTiON:
- * Loads cursor image based on a monochrome source and mask bitmap.  The
- * image bits determines the color of the pixel, 0 for background, 1 for
- * foreground.  Only the affected region (as determined by @w and @h 
- * parameters) will be updated.
- *
- * CALLED FROM:
- * rivafb_cursor()
- */
-static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
-				     u16 bg, u16 fg, u32 w, u32 h)
-{
-	int i, j, k = 0;
-	u32 b, tmp;
-	u32 *data = (u32 *)data8;
-	bg = le16_to_cpu(bg);
-	fg = le16_to_cpu(fg);
-
-	w = (w + 1) & ~1;
-
-	for (i = 0; i < h; i++) {
-		b = *data++;
-		reverse_order(&b);
-		
-		for (j = 0; j < w/2; j++) {
-			tmp = 0;
-#if defined (__BIG_ENDIAN)
-			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
-			b <<= 1;
-			tmp |= (b & (1 << 31)) ? fg : bg;
-			b <<= 1;
-#else
-			tmp = (b & 1) ? fg : bg;
-			b >>= 1;
-			tmp |= (b & 1) ? fg << 16 : bg << 16;
-			b >>= 1;
-#endif
-			writel(tmp, &par->riva.CURSOR[k++]);
-		}
-		k += (MAX_CURS - w)/2;
-	}
-}
-
-/* ------------------------------------------------------------------------- *
- *
- * general utility functions
- *
- * ------------------------------------------------------------------------- */
-
-/**
- * riva_wclut - set CLUT entry
- * @chip: pointer to RIVA_HW_INST object
- * @regnum: register number
- * @red: red component
- * @green: green component
- * @blue: blue component
- *
- * DESCRIPTION:
- * Sets color register @regnum.
- *
- * CALLED FROM:
- * rivafb_setcolreg()
- */
-static void riva_wclut(RIVA_HW_INST *chip,
-		       unsigned char regnum, unsigned char red,
-		       unsigned char green, unsigned char blue)
-{
-	VGA_WR08(chip->PDIO, 0x3c8, regnum);
-	VGA_WR08(chip->PDIO, 0x3c9, red);
-	VGA_WR08(chip->PDIO, 0x3c9, green);
-	VGA_WR08(chip->PDIO, 0x3c9, blue);
-}
-
-/**
- * riva_rclut - read fromCLUT register
- * @chip: pointer to RIVA_HW_INST object
- * @regnum: register number
- * @red: red component
- * @green: green component
- * @blue: blue component
- *
- * DESCRIPTION:
- * Reads red, green, and blue from color register @regnum.
- *
- * CALLED FROM:
- * rivafb_setcolreg()
- */
-static void riva_rclut(RIVA_HW_INST *chip,
-		       unsigned char regnum, unsigned char *red,
-		       unsigned char *green, unsigned char *blue)
-{
-	
-	VGA_WR08(chip->PDIO, 0x3c7, regnum);
-	*red = VGA_RD08(chip->PDIO, 0x3c9);
-	*green = VGA_RD08(chip->PDIO, 0x3c9);
-	*blue = VGA_RD08(chip->PDIO, 0x3c9);
-}
-
-/**
- * riva_save_state - saves current chip state
- * @par: pointer to riva_par object containing info for current riva board
- * @regs: pointer to riva_regs object
- *
- * DESCRIPTION:
- * Saves current chip state to @regs.
- *
- * CALLED FROM:
- * rivafb_probe()
- */
-/* from GGI */
-static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
-{
-	int i;
-
-	NVTRACE_ENTER();
-	par->riva.LockUnlock(&par->riva, 0);
-
-	par->riva.UnloadStateExt(&par->riva, &regs->ext);
-
-	regs->misc_output = MISCin(par);
-
-	for (i = 0; i < NUM_CRT_REGS; i++)
-		regs->crtc[i] = CRTCin(par, i);
-
-	for (i = 0; i < NUM_ATC_REGS; i++)
-		regs->attr[i] = ATTRin(par, i);
-
-	for (i = 0; i < NUM_GRC_REGS; i++)
-		regs->gra[i] = GRAin(par, i);
-
-	for (i = 0; i < NUM_SEQ_REGS; i++)
-		regs->seq[i] = SEQin(par, i);
-	NVTRACE_LEAVE();
-}
-
-/**
- * riva_load_state - loads current chip state
- * @par: pointer to riva_par object containing info for current riva board
- * @regs: pointer to riva_regs object
- *
- * DESCRIPTION:
- * Loads chip state from @regs.
- *
- * CALLED FROM:
- * riva_load_video_mode()
- * rivafb_probe()
- * rivafb_remove()
- */
-/* from GGI */
-static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
-{
-	RIVA_HW_STATE *state = &regs->ext;
-	int i;
-
-	NVTRACE_ENTER();
-	CRTCout(par, 0x11, 0x00);
-
-	par->riva.LockUnlock(&par->riva, 0);
-
-	par->riva.LoadStateExt(&par->riva, state);
-
-	MISCout(par, regs->misc_output);
-
-	for (i = 0; i < NUM_CRT_REGS; i++) {
-		switch (i) {
-		case 0x19:
-		case 0x20 ... 0x40:
-			break;
-		default:
-			CRTCout(par, i, regs->crtc[i]);
-		}
-	}
-
-	for (i = 0; i < NUM_ATC_REGS; i++)
-		ATTRout(par, i, regs->attr[i]);
-
-	for (i = 0; i < NUM_GRC_REGS; i++)
-		GRAout(par, i, regs->gra[i]);
-
-	for (i = 0; i < NUM_SEQ_REGS; i++)
-		SEQout(par, i, regs->seq[i]);
-	NVTRACE_LEAVE();
-}
-
-/**
- * riva_load_video_mode - calculate timings
- * @info: pointer to fb_info object containing info for current riva board
- *
- * DESCRIPTION:
- * Calculate some timings and then send em off to riva_load_state().
- *
- * CALLED FROM:
- * rivafb_set_par()
- */
-static int riva_load_video_mode(struct fb_info *info)
-{
-	int bpp, width, hDisplaySize, hDisplay, hStart,
-	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
-	int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
-	int rc;
-	struct riva_par *par = info->par;
-	struct riva_regs newmode;
-	
-	NVTRACE_ENTER();
-	/* time to calculate */
-	rivafb_blank(FB_BLANK_NORMAL, info);
-
-	bpp = info->var.bits_per_pixel;
-	if (bpp == 16 && info->var.green.length == 5)
-		bpp = 15;
-	width = info->var.xres_virtual;
-	hDisplaySize = info->var.xres;
-	hDisplay = (hDisplaySize / 8) - 1;
-	hStart = (hDisplaySize + info->var.right_margin) / 8 - 1;
-	hEnd = (hDisplaySize + info->var.right_margin +
-		info->var.hsync_len) / 8 - 1;
-	hTotal = (hDisplaySize + info->var.right_margin +
-		  info->var.hsync_len + info->var.left_margin) / 8 - 5;
-	hBlankStart = hDisplay;
-	hBlankEnd = hTotal + 4;
-
-	height = info->var.yres_virtual;
-	vDisplay = info->var.yres - 1;
-	vStart = info->var.yres + info->var.lower_margin - 1;
-	vEnd = info->var.yres + info->var.lower_margin +
-	       info->var.vsync_len - 1;
-	vTotal = info->var.yres + info->var.lower_margin +
-		 info->var.vsync_len + info->var.upper_margin + 2;
-	vBlankStart = vDisplay;
-	vBlankEnd = vTotal + 1;
-	dotClock = 1000000000 / info->var.pixclock;
-
-	memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
-
-	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
-		vTotal |= 1;
-
-	if (par->FlatPanel) {
-		vStart = vTotal - 3;
-		vEnd = vTotal - 2;
-		vBlankStart = vStart;
-		hStart = hTotal - 3;
-		hEnd = hTotal - 2;
-		hBlankEnd = hTotal + 4;
-	}
-
-	newmode.crtc[0x0] = Set8Bits (hTotal); 
-	newmode.crtc[0x1] = Set8Bits (hDisplay);
-	newmode.crtc[0x2] = Set8Bits (hBlankStart);
-	newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7);
-	newmode.crtc[0x4] = Set8Bits (hStart);
-	newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7)
-		| SetBitField (hEnd, 4: 0, 4:0);
-	newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
-	newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
-		| SetBitField (vDisplay, 8: 8, 1:1)
-		| SetBitField (vStart, 8: 8, 2:2)
-		| SetBitField (vBlankStart, 8: 8, 3:3)
-		| SetBit (4)
-		| SetBitField (vTotal, 9: 9, 5:5)
-		| SetBitField (vDisplay, 9: 9, 6:6)
-		| SetBitField (vStart, 9: 9, 7:7);
-	newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5)
-		| SetBit (6);
-	newmode.crtc[0x10] = Set8Bits (vStart);
-	newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
-		| SetBit (5);
-	newmode.crtc[0x12] = Set8Bits (vDisplay);
-	newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8);
-	newmode.crtc[0x15] = Set8Bits (vBlankStart);
-	newmode.crtc[0x16] = Set8Bits (vBlankEnd);
-
-	newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4)
-		| SetBitField(vBlankStart,10:10,3:3)
-		| SetBitField(vStart,10:10,2:2)
-		| SetBitField(vDisplay,10:10,1:1)
-		| SetBitField(vTotal,10:10,0:0);
-	newmode.ext.horiz  = SetBitField(hTotal,8:8,0:0) 
-		| SetBitField(hDisplay,8:8,1:1)
-		| SetBitField(hBlankStart,8:8,2:2)
-		| SetBitField(hStart,8:8,3:3);
-	newmode.ext.extra  = SetBitField(vTotal,11:11,0:0)
-		| SetBitField(vDisplay,11:11,2:2)
-		| SetBitField(vStart,11:11,4:4)
-		| SetBitField(vBlankStart,11:11,6:6); 
-
-	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-		int tmp = (hTotal >> 1) & ~1;
-		newmode.ext.interlace = Set8Bits(tmp);
-		newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4);
-	} else 
-		newmode.ext.interlace = 0xff; /* interlace off */
-
-	if (par->riva.Architecture >= NV_ARCH_10)
-		par->riva.CURSOR = (U032 __iomem *)(info->screen_base + par->riva.CursorStart);
-
-	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		newmode.misc_output &= ~0x40;
-	else
-		newmode.misc_output |= 0x40;
-	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		newmode.misc_output &= ~0x80;
-	else
-		newmode.misc_output |= 0x80;	
-
-	rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width,
-			  hDisplaySize, height, dotClock);
-	if (rc)
-		goto out;
-
-	newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) &
-		0xfff000ff;
-	if (par->FlatPanel == 1) {
-		newmode.ext.pixel |= (1 << 7);
-		newmode.ext.scale |= (1 << 8);
-	}
-	if (par->SecondCRTC) {
-		newmode.ext.head  = NV_RD32(par->riva.PCRTC0, 0x00000860) &
-			~0x00001000;
-		newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) |
-			0x00001000;
-		newmode.ext.crtcOwner = 3;
-		newmode.ext.pllsel |= 0x20000800;
-		newmode.ext.vpll2 = newmode.ext.vpll;
-	} else if (par->riva.twoHeads) {
-		newmode.ext.head  =  NV_RD32(par->riva.PCRTC0, 0x00000860) |
-			0x00001000;
-		newmode.ext.head2 =  NV_RD32(par->riva.PCRTC0, 0x00002860) &
-			~0x00001000;
-		newmode.ext.crtcOwner = 0;
-		newmode.ext.vpll2 = NV_RD32(par->riva.PRAMDAC0, 0x00000520);
-	}
-	if (par->FlatPanel == 1) {
-		newmode.ext.pixel |= (1 << 7);
-		newmode.ext.scale |= (1 << 8);
-	}
-	newmode.ext.cursorConfig = 0x02000100;
-	par->current_state = newmode;
-	riva_load_state(par, &par->current_state);
-	par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
-
-out:
-	rivafb_blank(FB_BLANK_UNBLANK, info);
-	NVTRACE_LEAVE();
-
-	return rc;
-}
-
-static void riva_update_var(struct fb_var_screeninfo *var,
-			    const struct fb_videomode *modedb)
-{
-	NVTRACE_ENTER();
-	var->xres = var->xres_virtual = modedb->xres;
-	var->yres = modedb->yres;
-        if (var->yres_virtual < var->yres)
-	    var->yres_virtual = var->yres;
-        var->xoffset = var->yoffset = 0;
-        var->pixclock = modedb->pixclock;
-        var->left_margin = modedb->left_margin;
-        var->right_margin = modedb->right_margin;
-        var->upper_margin = modedb->upper_margin;
-        var->lower_margin = modedb->lower_margin;
-        var->hsync_len = modedb->hsync_len;
-        var->vsync_len = modedb->vsync_len;
-        var->sync = modedb->sync;
-        var->vmode = modedb->vmode;
-	NVTRACE_LEAVE();
-}
-
-/**
- * rivafb_do_maximize - 
- * @info: pointer to fb_info object containing info for current riva board
- * @var:
- * @nom:
- * @den:
- *
- * DESCRIPTION:
- * .
- *
- * RETURNS:
- * -EINVAL on failure, 0 on success
- * 
- *
- * CALLED FROM:
- * rivafb_check_var()
- */
-static int rivafb_do_maximize(struct fb_info *info,
-			      struct fb_var_screeninfo *var,
-			      int nom, int den)
-{
-	static struct {
-		int xres, yres;
-	} modes[] = {
-		{1600, 1280},
-		{1280, 1024},
-		{1024, 768},
-		{800, 600},
-		{640, 480},
-		{-1, -1}
-	};
-	int i;
-
-	NVTRACE_ENTER();
-	/* use highest possible virtual resolution */
-	if (var->xres_virtual == -1 && var->yres_virtual == -1) {
-		printk(KERN_WARNING PFX
-		       "using maximum available virtual resolution\n");
-		for (i = 0; modes[i].xres != -1; i++) {
-			if (modes[i].xres * nom / den * modes[i].yres <
-			    info->fix.smem_len)
-				break;
-		}
-		if (modes[i].xres == -1) {
-			printk(KERN_ERR PFX
-			       "could not find a virtual resolution that fits into video memory!!\n");
-			NVTRACE("EXIT - EINVAL error\n");
-			return -EINVAL;
-		}
-		var->xres_virtual = modes[i].xres;
-		var->yres_virtual = modes[i].yres;
-
-		printk(KERN_INFO PFX
-		       "virtual resolution set to maximum of %dx%d\n",
-		       var->xres_virtual, var->yres_virtual);
-	} else if (var->xres_virtual == -1) {
-		var->xres_virtual = (info->fix.smem_len * den /
-			(nom * var->yres_virtual)) & ~15;
-		printk(KERN_WARNING PFX
-		       "setting virtual X resolution to %d\n", var->xres_virtual);
-	} else if (var->yres_virtual == -1) {
-		var->xres_virtual = (var->xres_virtual + 15) & ~15;
-		var->yres_virtual = info->fix.smem_len * den /
-			(nom * var->xres_virtual);
-		printk(KERN_WARNING PFX
-		       "setting virtual Y resolution to %d\n", var->yres_virtual);
-	} else {
-		var->xres_virtual = (var->xres_virtual + 15) & ~15;
-		if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) {
-			printk(KERN_ERR PFX
-			       "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
-			       var->xres, var->yres, var->bits_per_pixel);
-			NVTRACE("EXIT - EINVAL error\n");
-			return -EINVAL;
-		}
-	}
-	
-	if (var->xres_virtual * nom / den >= 8192) {
-		printk(KERN_WARNING PFX
-		       "virtual X resolution (%d) is too high, lowering to %d\n",
-		       var->xres_virtual, 8192 * den / nom - 16);
-		var->xres_virtual = 8192 * den / nom - 16;
-	}
-	
-	if (var->xres_virtual < var->xres) {
-		printk(KERN_ERR PFX
-		       "virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
-		return -EINVAL;
-	}
-
-	if (var->yres_virtual < var->yres) {
-		printk(KERN_ERR PFX
-		       "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
-		return -EINVAL;
-	}
-	if (var->yres_virtual > 0x7fff/nom)
-		var->yres_virtual = 0x7fff/nom;
-	if (var->xres_virtual > 0x7fff/nom)
-		var->xres_virtual = 0x7fff/nom;
-	NVTRACE_LEAVE();
-	return 0;
-}
-
-static void
-riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1)
-{
-	RIVA_FIFO_FREE(par->riva, Patt, 4);
-	NV_WR32(&par->riva.Patt->Color0, 0, clr0);
-	NV_WR32(&par->riva.Patt->Color1, 0, clr1);
-	NV_WR32(par->riva.Patt->Monochrome, 0, pat0);
-	NV_WR32(par->riva.Patt->Monochrome, 4, pat1);
-}
-
-/* acceleration routines */
-static inline void wait_for_idle(struct riva_par *par)
-{
-	while (par->riva.Busy(&par->riva));
-}
-
-/*
- * Set ROP.  Translate X rop into ROP3.  Internal routine.
- */
-static void
-riva_set_rop_solid(struct riva_par *par, int rop)
-{
-	riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-        RIVA_FIFO_FREE(par->riva, Rop, 1);
-        NV_WR32(&par->riva.Rop->Rop3, 0, rop);
-
-}
-
-static void riva_setup_accel(struct fb_info *info)
-{
-	struct riva_par *par = info->par;
-
-	RIVA_FIFO_FREE(par->riva, Clip, 2);
-	NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0);
-	NV_WR32(&par->riva.Clip->WidthHeight, 0,
-		(info->var.xres_virtual & 0xffff) |
-		(info->var.yres_virtual << 16));
-	riva_set_rop_solid(par, 0xcc);
-	wait_for_idle(par);
-}
-
-/**
- * riva_get_cmap_len - query current color map length
- * @var: standard kernel fb changeable data
- *
- * DESCRIPTION:
- * Get current color map length.
- *
- * RETURNS:
- * Length of color map
- *
- * CALLED FROM:
- * rivafb_setcolreg()
- */
-static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
-{
-	int rc = 256;		/* reasonable default */
-
-	switch (var->green.length) {
-	case 8:
-		rc = 256;	/* 256 entries (2^8), 8 bpp and RGB8888 */
-		break;
-	case 5:
-		rc = 32;	/* 32 entries (2^5), 16 bpp, RGB555 */
-		break;
-	case 6:
-		rc = 64;	/* 64 entries (2^6), 16 bpp, RGB565 */
-		break;		
-	default:
-		/* should not occur */
-		break;
-	}
-	return rc;
-}
-
-/* ------------------------------------------------------------------------- *
- *
- * framebuffer operations
- *
- * ------------------------------------------------------------------------- */
-
-static int rivafb_open(struct fb_info *info, int user)
-{
-	struct riva_par *par = info->par;
-
-	NVTRACE_ENTER();
-	mutex_lock(&par->open_lock);
-	if (!par->ref_count) {
-#ifdef CONFIG_X86
-		memset(&par->state, 0, sizeof(struct vgastate));
-		par->state.flags = VGA_SAVE_MODE  | VGA_SAVE_FONTS;
-		/* save the DAC for Riva128 */
-		if (par->riva.Architecture == NV_ARCH_03)
-			par->state.flags |= VGA_SAVE_CMAP;
-		save_vga(&par->state);
-#endif
-		/* vgaHWunlock() + riva unlock (0x7F) */
-		CRTCout(par, 0x11, 0xFF);
-		par->riva.LockUnlock(&par->riva, 0);
-	
-		riva_save_state(par, &par->initial_state);
-	}
-	par->ref_count++;
-	mutex_unlock(&par->open_lock);
-	NVTRACE_LEAVE();
-	return 0;
-}
-
-static int rivafb_release(struct fb_info *info, int user)
-{
-	struct riva_par *par = info->par;
-
-	NVTRACE_ENTER();
-	mutex_lock(&par->open_lock);
-	if (!par->ref_count) {
-		mutex_unlock(&par->open_lock);
-		return -EINVAL;
-	}
-	if (par->ref_count == 1) {
-		par->riva.LockUnlock(&par->riva, 0);
-		par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
-		riva_load_state(par, &par->initial_state);
-#ifdef CONFIG_X86
-		restore_vga(&par->state);
-#endif
-		par->riva.LockUnlock(&par->riva, 1);
-	}
-	par->ref_count--;
-	mutex_unlock(&par->open_lock);
-	NVTRACE_LEAVE();
-	return 0;
-}
-
-static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	const struct fb_videomode *mode;
-	struct riva_par *par = info->par;
-	int nom, den;		/* translating from pixels->bytes */
-	int mode_valid = 0;
-	
-	NVTRACE_ENTER();
-	switch (var->bits_per_pixel) {
-	case 1 ... 8:
-		var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 8;
-		var->bits_per_pixel = 8;
-		nom = den = 1;
-		break;
-	case 9 ... 15:
-		var->green.length = 5;
-		/* fall through */
-	case 16:
-		var->bits_per_pixel = 16;
-		/* The Riva128 supports RGB555 only */
-		if (par->riva.Architecture == NV_ARCH_03)
-			var->green.length = 5;
-		if (var->green.length == 5) {
-			/* 0rrrrrgg gggbbbbb */
-			var->red.offset = 10;
-			var->green.offset = 5;
-			var->blue.offset = 0;
-			var->red.length = 5;
-			var->green.length = 5;
-			var->blue.length = 5;
-		} else {
-			/* rrrrrggg gggbbbbb */
-			var->red.offset = 11;
-			var->green.offset = 5;
-			var->blue.offset = 0;
-			var->red.length = 5;
-			var->green.length = 6;
-			var->blue.length = 5;
-		}
-		nom = 2;
-		den = 1;
-		break;
-	case 17 ... 32:
-		var->red.length = var->green.length = var->blue.length = 8;
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		nom = 4;
-		den = 1;
-		break;
-	default:
-		printk(KERN_ERR PFX
-		       "mode %dx%dx%d rejected...color depth not supported.\n",
-		       var->xres, var->yres, var->bits_per_pixel);
-		NVTRACE("EXIT, returning -EINVAL\n");
-		return -EINVAL;
-	}
-
-	if (!strictmode) {
-		if (!info->monspecs.vfmax || !info->monspecs.hfmax ||
-		    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
-			mode_valid = 1;
-	}
-
-	/* calculate modeline if supported by monitor */
-	if (!mode_valid && info->monspecs.gtf) {
-		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
-			mode_valid = 1;
-	}
-
-	if (!mode_valid) {
-		mode = fb_find_best_mode(var, &info->modelist);
-		if (mode) {
-			riva_update_var(var, mode);
-			mode_valid = 1;
-		}
-	}
-
-	if (!mode_valid && info->monspecs.modedb_len)
-		return -EINVAL;
-
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual <= var->yres)
-		var->yres_virtual = -1;
-	if (rivafb_do_maximize(info, var, nom, den) < 0)
-		return -EINVAL;
-
-	/* truncate xoffset and yoffset to maximum if too high */
-	if (var->xoffset > var->xres_virtual - var->xres)
-		var->xoffset = var->xres_virtual - var->xres - 1;
-
-	if (var->yoffset > var->yres_virtual - var->yres)
-		var->yoffset = var->yres_virtual - var->yres - 1;
-
-	var->red.msb_right = 
-	    var->green.msb_right =
-	    var->blue.msb_right =
-	    var->transp.offset = var->transp.length = var->transp.msb_right = 0;
-	NVTRACE_LEAVE();
-	return 0;
-}
-
-static int rivafb_set_par(struct fb_info *info)
-{
-	struct riva_par *par = info->par;
-	int rc = 0;
-
-	NVTRACE_ENTER();
-	/* vgaHWunlock() + riva unlock (0x7F) */
-	CRTCout(par, 0x11, 0xFF);
-	par->riva.LockUnlock(&par->riva, 0);
-	rc = riva_load_video_mode(info);
-	if (rc)
-		goto out;
-	if(!(info->flags & FBINFO_HWACCEL_DISABLED))
-		riva_setup_accel(info);
-	
-	par->cursor_reset = 1;
-	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
-	info->fix.visual = (info->var.bits_per_pixel == 8) ?
-				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED)
-		info->pixmap.scan_align = 1;
-	else
-		info->pixmap.scan_align = 4;
-
-out:
-	NVTRACE_LEAVE();
-	return rc;
-}
-
-/**
- * rivafb_pan_display
- * @var: standard kernel fb changeable data
- * @con: TODO
- * @info: pointer to fb_info object containing info for current riva board
- *
- * DESCRIPTION:
- * Pan (or wrap, depending on the `vmode' field) the display using the
- * `xoffset' and `yoffset' fields of the `var' structure.
- * If the values don't fit, return -EINVAL.
- *
- * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- */
-static int rivafb_pan_display(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct riva_par *par = info->par;
-	unsigned int base;
-
-	NVTRACE_ENTER();
-	base = var->yoffset * info->fix.line_length + var->xoffset;
-	par->riva.SetStartAddress(&par->riva, base);
-	NVTRACE_LEAVE();
-	return 0;
-}
-
-static int rivafb_blank(int blank, struct fb_info *info)
-{
-	struct riva_par *par= info->par;
-	unsigned char tmp, vesa;
-
-	tmp = SEQin(par, 0x01) & ~0x20;	/* screen on/off */
-	vesa = CRTCin(par, 0x1a) & ~0xc0;	/* sync on/off */
-
-	NVTRACE_ENTER();
-
-	if (blank)
-		tmp |= 0x20;
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		vesa |= 0x80;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		vesa |= 0x40;
-		break;
-	case FB_BLANK_POWERDOWN:
-		vesa |= 0xc0;
-		break;
-	}
-
-	SEQout(par, 0x01, tmp);
-	CRTCout(par, 0x1a, vesa);
-
-	NVTRACE_LEAVE();
-
-	return 0;
-}
-
-/**
- * rivafb_setcolreg
- * @regno: register index
- * @red: red component
- * @green: green component
- * @blue: blue component
- * @transp: transparency
- * @info: pointer to fb_info object containing info for current riva board
- *
- * DESCRIPTION:
- * Set a single color register. The values supplied have a 16 bit
- * magnitude.
- *
- * RETURNS:
- * Return != 0 for invalid regno.
- *
- * CALLED FROM:
- * fbcmap.c:fb_set_cmap()
- */
-static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			  unsigned blue, unsigned transp,
-			  struct fb_info *info)
-{
-	struct riva_par *par = info->par;
-	RIVA_HW_INST *chip = &par->riva;
-	int i;
-
-	if (regno >= riva_get_cmap_len(&info->var))
-			return -EINVAL;
-
-	if (info->var.grayscale) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue =
-		    (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		((u32 *) info->pseudo_palette)[regno] =
-			(regno << info->var.red.offset) |
-			(regno << info->var.green.offset) |
-			(regno << info->var.blue.offset);
-		/*
-		 * The Riva128 2D engine requires color information in
-		 * TrueColor format even if framebuffer is in DirectColor
-		 */
-		if (par->riva.Architecture == NV_ARCH_03) {
-			switch (info->var.bits_per_pixel) {
-			case 16:
-				par->palette[regno] = ((red & 0xf800) >> 1) |
-					((green & 0xf800) >> 6) |
-					((blue & 0xf800) >> 11);
-				break;
-			case 32:
-				par->palette[regno] = ((red & 0xff00) << 8) |
-					((green & 0xff00)) |
-					((blue & 0xff00) >> 8);
-				break;
-			}
-		}
-	}
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		/* "transparent" stuff is completely ignored. */
-		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
-		break;
-	case 16:
-		if (info->var.green.length == 5) {
-			for (i = 0; i < 8; i++) {
-				riva_wclut(chip, regno*8+i, red >> 8,
-					   green >> 8, blue >> 8);
-			}
-		} else {
-			u8 r, g, b;
-
-			if (regno < 32) {
-				for (i = 0; i < 8; i++) {
-					riva_wclut(chip, regno*8+i,
-						   red >> 8, green >> 8,
-						   blue >> 8);
-				}
-			}
-			riva_rclut(chip, regno*4, &r, &g, &b);
-			for (i = 0; i < 4; i++)
-				riva_wclut(chip, regno*4+i, r,
-					   green >> 8, b);
-		}
-		break;
-	case 32:
-		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
-		break;
-	default:
-		/* do nothing */
-		break;
-	}
-	return 0;
-}
-
-/**
- * rivafb_fillrect - hardware accelerated color fill function
- * @info: pointer to fb_info structure
- * @rect: pointer to fb_fillrect structure
- *
- * DESCRIPTION:
- * This function fills up a region of framebuffer memory with a solid
- * color with a choice of two different ROP's, copy or invert.
- *
- * CALLED FROM:
- * framebuffer hook
- */
-static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct riva_par *par = info->par;
-	u_int color, rop = 0;
-
-	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	if (info->var.bits_per_pixel == 8)
-		color = rect->color;
-	else {
-		if (par->riva.Architecture != NV_ARCH_03)
-			color = ((u32 *)info->pseudo_palette)[rect->color];
-		else
-			color = par->palette[rect->color];
-	}
-
-	switch (rect->rop) {
-	case ROP_XOR:
-		rop = 0x66;
-		break;
-	case ROP_COPY:
-	default:
-		rop = 0xCC;
-		break;
-	}
-
-	riva_set_rop_solid(par, rop);
-
-	RIVA_FIFO_FREE(par->riva, Bitmap, 1);
-	NV_WR32(&par->riva.Bitmap->Color1A, 0, color);
-
-	RIVA_FIFO_FREE(par->riva, Bitmap, 2);
-	NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].TopLeft, 0,
-		(rect->dx << 16) | rect->dy);
-	mb();
-	NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].WidthHeight, 0,
-		(rect->width << 16) | rect->height);
-	mb();
-	riva_set_rop_solid(par, 0xcc);
-
-}
-
-/**
- * rivafb_copyarea - hardware accelerated blit function
- * @info: pointer to fb_info structure
- * @region: pointer to fb_copyarea structure
- *
- * DESCRIPTION:
- * This copies an area of pixels from one location to another
- *
- * CALLED FROM:
- * framebuffer hook
- */
-static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
-	struct riva_par *par = info->par;
-
-	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
-		cfb_copyarea(info, region);
-		return;
-	}
-
-	RIVA_FIFO_FREE(par->riva, Blt, 3);
-	NV_WR32(&par->riva.Blt->TopLeftSrc, 0,
-		(region->sy << 16) | region->sx);
-	NV_WR32(&par->riva.Blt->TopLeftDst, 0,
-		(region->dy << 16) | region->dx);
-	mb();
-	NV_WR32(&par->riva.Blt->WidthHeight, 0,
-		(region->height << 16) | region->width);
-	mb();
-}
-
-static inline void convert_bgcolor_16(u32 *col)
-{
-	*col = ((*col & 0x0000F800) << 8)
-		| ((*col & 0x00007E0) << 5)
-		| ((*col & 0x0000001F) << 3)
-		|	   0xFF000000;
-	mb();
-}
-
-/**
- * rivafb_imageblit: hardware accelerated color expand function
- * @info: pointer to fb_info structure
- * @image: pointer to fb_image structure
- *
- * DESCRIPTION:
- * If the source is a monochrome bitmap, the function fills up a a region
- * of framebuffer memory with pixels whose color is determined by the bit
- * setting of the bitmap, 1 - foreground, 0 - background.
- *
- * If the source is not a monochrome bitmap, color expansion is not done.
- * In this case, it is channeled to a software function.
- *
- * CALLED FROM:
- * framebuffer hook
- */
-static void rivafb_imageblit(struct fb_info *info, 
-			     const struct fb_image *image)
-{
-	struct riva_par *par = info->par;
-	u32 fgx = 0, bgx = 0, width, tmp;
-	u8 *cdat = (u8 *) image->data;
-	volatile u32 __iomem *d;
-	int i, size;
-
-	if ((info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		fgx = image->fg_color;
-		bgx = image->bg_color;
-		break;
-	case 16:
-	case 32:
-		if (par->riva.Architecture != NV_ARCH_03) {
-			fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
-			bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
-		} else {
-			fgx = par->palette[image->fg_color];
-			bgx = par->palette[image->bg_color];
-		}
-		if (info->var.green.length == 6)
-			convert_bgcolor_16(&bgx);	
-		break;
-	}
-
-	RIVA_FIFO_FREE(par->riva, Bitmap, 7);
-	NV_WR32(&par->riva.Bitmap->ClipE.TopLeft, 0,
-		(image->dy << 16) | (image->dx & 0xFFFF));
-	NV_WR32(&par->riva.Bitmap->ClipE.BottomRight, 0,
-		(((image->dy + image->height) << 16) |
-		 ((image->dx + image->width) & 0xffff)));
-	NV_WR32(&par->riva.Bitmap->Color0E, 0, bgx);
-	NV_WR32(&par->riva.Bitmap->Color1E, 0, fgx);
-	NV_WR32(&par->riva.Bitmap->WidthHeightInE, 0,
-		(image->height << 16) | ((image->width + 31) & ~31));
-	NV_WR32(&par->riva.Bitmap->WidthHeightOutE, 0,
-		(image->height << 16) | ((image->width + 31) & ~31));
-	NV_WR32(&par->riva.Bitmap->PointE, 0,
-		(image->dy << 16) | (image->dx & 0xFFFF));
-
-	d = &par->riva.Bitmap->MonochromeData01E;
-
-	width = (image->width + 31)/32;
-	size = width * image->height;
-	while (size >= 16) {
-		RIVA_FIFO_FREE(par->riva, Bitmap, 16);
-		for (i = 0; i < 16; i++) {
-			tmp = *((u32 *)cdat);
-			cdat = (u8 *)((u32 *)cdat + 1);
-			reverse_order(&tmp);
-			NV_WR32(d, i*4, tmp);
-		}
-		size -= 16;
-	}
-	if (size) {
-		RIVA_FIFO_FREE(par->riva, Bitmap, size);
-		for (i = 0; i < size; i++) {
-			tmp = *((u32 *) cdat);
-			cdat = (u8 *)((u32 *)cdat + 1);
-			reverse_order(&tmp);
-			NV_WR32(d, i*4, tmp);
-		}
-	}
-}
-
-/**
- * rivafb_cursor - hardware cursor function
- * @info: pointer to info structure
- * @cursor: pointer to fbcursor structure
- *
- * DESCRIPTION:
- * A cursor function that supports displaying a cursor image via hardware.
- * Within the kernel, copy and invert rops are supported.  If exported
- * to user space, only the copy rop will be supported.
- *
- * CALLED FROM
- * framebuffer hook
- */
-static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct riva_par *par = info->par;
-	u8 data[MAX_CURS * MAX_CURS/8];
-	int i, set = cursor->set;
-	u16 fg, bg;
-
-	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
-		return -ENXIO;
-
-	par->riva.ShowHideCursor(&par->riva, 0);
-
-	if (par->cursor_reset) {
-		set = FB_CUR_SETALL;
-		par->cursor_reset = 0;
-	}
-
-	if (set & FB_CUR_SETSIZE)
-		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
-
-	if (set & FB_CUR_SETPOS) {
-		u32 xx, yy, temp;
-
-		yy = cursor->image.dy - info->var.yoffset;
-		xx = cursor->image.dx - info->var.xoffset;
-		temp = xx & 0xFFFF;
-		temp |= yy << 16;
-
-		NV_WR32(par->riva.PRAMDAC, 0x0000300, temp);
-	}
-
-
-	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
-		u32 bg_idx = cursor->image.bg_color;
-		u32 fg_idx = cursor->image.fg_color;
-		u32 s_pitch = (cursor->image.width+7) >> 3;
-		u32 d_pitch = MAX_CURS/8;
-		u8 *dat = (u8 *) cursor->image.data;
-		u8 *msk = (u8 *) cursor->mask;
-		u8 *src;
-		
-		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
-
-		if (src) {
-			switch (cursor->rop) {
-			case ROP_XOR:
-				for (i = 0; i < s_pitch * cursor->image.height; i++)
-					src[i] = dat[i] ^ msk[i];
-				break;
-			case ROP_COPY:
-			default:
-				for (i = 0; i < s_pitch * cursor->image.height; i++)
-					src[i] = dat[i] & msk[i];
-				break;
-			}
-
-			fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
-						cursor->image.height);
-
-			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
-				((info->cmap.green[bg_idx] & 0xf8) << 2) |
-				((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
-				1 << 15;
-
-			fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
-				((info->cmap.green[fg_idx] & 0xf8) << 2) |
-				((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
-				1 << 15;
-
-			par->riva.LockUnlock(&par->riva, 0);
-
-			rivafb_load_cursor_image(par, data, bg, fg,
-						 cursor->image.width,
-						 cursor->image.height);
-			kfree(src);
-		}
-	}
-
-	if (cursor->enable)
-		par->riva.ShowHideCursor(&par->riva, 1);
-
-	return 0;
-}
-
-static int rivafb_sync(struct fb_info *info)
-{
-	struct riva_par *par = info->par;
-
-	wait_for_idle(par);
-	return 0;
-}
-
-/* ------------------------------------------------------------------------- *
- *
- * initialization helper functions
- *
- * ------------------------------------------------------------------------- */
-
-/* kernel interface */
-static struct fb_ops riva_fb_ops = {
-	.owner 		= THIS_MODULE,
-	.fb_open	= rivafb_open,
-	.fb_release	= rivafb_release,
-	.fb_check_var 	= rivafb_check_var,
-	.fb_set_par 	= rivafb_set_par,
-	.fb_setcolreg 	= rivafb_setcolreg,
-	.fb_pan_display	= rivafb_pan_display,
-	.fb_blank 	= rivafb_blank,
-	.fb_fillrect 	= rivafb_fillrect,
-	.fb_copyarea 	= rivafb_copyarea,
-	.fb_imageblit 	= rivafb_imageblit,
-	.fb_cursor	= rivafb_cursor,	
-	.fb_sync 	= rivafb_sync,
-};
-
-static int riva_set_fbinfo(struct fb_info *info)
-{
-	unsigned int cmap_len;
-	struct riva_par *par = info->par;
-
-	NVTRACE_ENTER();
-	info->flags = FBINFO_DEFAULT
-		    | FBINFO_HWACCEL_XPAN
-		    | FBINFO_HWACCEL_YPAN
-		    | FBINFO_HWACCEL_COPYAREA
-		    | FBINFO_HWACCEL_FILLRECT
-	            | FBINFO_HWACCEL_IMAGEBLIT;
-
-	/* Accel seems to not work properly on NV30 yet...*/
-	if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
-	    	printk(KERN_DEBUG PFX "disabling acceleration\n");
-  		info->flags |= FBINFO_HWACCEL_DISABLED;
-	}
-
-	info->var = rivafb_default_var;
-	info->fix.visual = (info->var.bits_per_pixel == 8) ?
-				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
-	info->pseudo_palette = par->pseudo_palette;
-
-	cmap_len = riva_get_cmap_len(&info->var);
-	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
-
-	info->pixmap.size = 8 * 1024;
-	info->pixmap.buf_align = 4;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-	info->var.yres_virtual = -1;
-	NVTRACE_LEAVE();
-	return (rivafb_check_var(&info->var, info));
-}
-
-#ifdef CONFIG_PPC_OF
-static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
-{
-	struct riva_par *par = info->par;
-	struct device_node *dp;
-	const unsigned char *pedid = NULL;
-	const unsigned char *disptype = NULL;
-	static char *propnames[] = {
-		"DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
-	int i;
-
-	NVTRACE_ENTER();
-	dp = pci_device_to_OF_node(pd);
-	for (; dp != NULL; dp = dp->child) {
-		disptype = of_get_property(dp, "display-type", NULL);
-		if (disptype == NULL)
-			continue;
-		if (strncmp(disptype, "LCD", 3) != 0)
-			continue;
-		for (i = 0; propnames[i] != NULL; ++i) {
-			pedid = of_get_property(dp, propnames[i], NULL);
-			if (pedid != NULL) {
-				par->EDID = (unsigned char *)pedid;
-				NVTRACE("LCD found.\n");
-				return 1;
-			}
-		}
-	}
-	NVTRACE_LEAVE();
-	return 0;
-}
-#endif /* CONFIG_PPC_OF */
-
-#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
-static int riva_get_EDID_i2c(struct fb_info *info)
-{
-	struct riva_par *par = info->par;
-	struct fb_var_screeninfo var;
-	int i;
-
-	NVTRACE_ENTER();
-	riva_create_i2c_busses(par);
-	for (i = 0; i < 3; i++) {
-		if (!par->chan[i].par)
-			continue;
-		riva_probe_i2c_connector(par, i, &par->EDID);
-		if (par->EDID && !fb_parse_edid(par->EDID, &var)) {
-			printk(PFX "Found EDID Block from BUS %i\n", i);
-			break;
-		}
-	}
-
-	NVTRACE_LEAVE();
-	return (par->EDID) ? 1 : 0;
-}
-#endif /* CONFIG_FB_RIVA_I2C */
-
-static void riva_update_default_var(struct fb_var_screeninfo *var,
-				    struct fb_info *info)
-{
-	struct fb_monspecs *specs = &info->monspecs;
-	struct fb_videomode modedb;
-
-	NVTRACE_ENTER();
-	/* respect mode options */
-	if (mode_option) {
-		fb_find_mode(var, info, mode_option,
-			     specs->modedb, specs->modedb_len,
-			     NULL, 8);
-	} else if (specs->modedb != NULL) {
-		/* get first mode in database as fallback */
-		modedb = specs->modedb[0];
-		/* get preferred timing */
-		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
-			int i;
-
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-					modedb = specs->modedb[i];
-					break;
-				}
-			}
-		}
-		var->bits_per_pixel = 8;
-		riva_update_var(var, &modedb);
-	}
-	NVTRACE_LEAVE();
-}
-
-
-static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
-{
-	NVTRACE_ENTER();
-#ifdef CONFIG_PPC_OF
-	if (!riva_get_EDID_OF(info, pdev))
-		printk(PFX "could not retrieve EDID from OF\n");
-#elif defined(CONFIG_FB_RIVA_I2C)
-	if (!riva_get_EDID_i2c(info))
-		printk(PFX "could not retrieve EDID from DDC/I2C\n");
-#endif
-	NVTRACE_LEAVE();
-}
-
-
-static void riva_get_edidinfo(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &rivafb_default_var;
-	struct riva_par *par = info->par;
-
-	fb_edid_to_monspecs(par->EDID, &info->monspecs);
-	fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
-				 &info->modelist);
-	riva_update_default_var(var, info);
-
-	/* if user specified flatpanel, we respect that */
-	if (info->monspecs.input & FB_DISP_DDI)
-		par->FlatPanel = 1;
-}
-
-/* ------------------------------------------------------------------------- *
- *
- * PCI bus
- *
- * ------------------------------------------------------------------------- */
-
-static u32 riva_get_arch(struct pci_dev *pd)
-{
-    	u32 arch = 0;
-
-	switch (pd->device & 0x0ff0) {
-		case 0x0100:   /* GeForce 256 */
-		case 0x0110:   /* GeForce2 MX */
-		case 0x0150:   /* GeForce2 */
-		case 0x0170:   /* GeForce4 MX */
-		case 0x0180:   /* GeForce4 MX (8x AGP) */
-		case 0x01A0:   /* nForce */
-		case 0x01F0:   /* nForce2 */
-		     arch =  NV_ARCH_10;
-		     break;
-		case 0x0200:   /* GeForce3 */
-		case 0x0250:   /* GeForce4 Ti */
-		case 0x0280:   /* GeForce4 Ti (8x AGP) */
-		     arch =  NV_ARCH_20;
-		     break;
-		case 0x0300:   /* GeForceFX 5800 */
-		case 0x0310:   /* GeForceFX 5600 */
-		case 0x0320:   /* GeForceFX 5200 */
-		case 0x0330:   /* GeForceFX 5900 */
-		case 0x0340:   /* GeForceFX 5700 */
-		     arch =  NV_ARCH_30;
-		     break;
-		case 0x0020:   /* TNT, TNT2 */
-		     arch =  NV_ARCH_04;
-		     break;
-		case 0x0010:   /* Riva128 */
-		     arch =  NV_ARCH_03;
-		     break;
-		default:   /* unknown architecture */
-		     break;
-	}
-	return arch;
-}
-
-static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
-{
-	struct riva_par *default_par;
-	struct fb_info *info;
-	int ret;
-
-	NVTRACE_ENTER();
-	assert(pd != NULL);
-
-	info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev);
-	if (!info) {
-		printk (KERN_ERR PFX "could not allocate memory\n");
-		ret = -ENOMEM;
-		goto err_ret;
-	}
-	default_par = info->par;
-	default_par->pdev = pd;
-
-	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
-	if (info->pixmap.addr == NULL) {
-	    	ret = -ENOMEM;
-		goto err_framebuffer_release;
-	}
-
-	ret = pci_enable_device(pd);
-	if (ret < 0) {
-		printk(KERN_ERR PFX "cannot enable PCI device\n");
-		goto err_free_pixmap;
-	}
-
-	ret = pci_request_regions(pd, "rivafb");
-	if (ret < 0) {
-		printk(KERN_ERR PFX "cannot request PCI regions\n");
-		goto err_disable_device;
-	}
-
-	mutex_init(&default_par->open_lock);
-	default_par->riva.Architecture = riva_get_arch(pd);
-
-	default_par->Chipset = (pd->vendor << 16) | pd->device;
-	printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
-	
-	if(default_par->riva.Architecture == 0) {
-		printk(KERN_ERR PFX "unknown NV_ARCH\n");
-		ret=-ENODEV;
-		goto err_release_region;
-	}
-	if(default_par->riva.Architecture == NV_ARCH_10 ||
-	   default_par->riva.Architecture == NV_ARCH_20 ||
-	   default_par->riva.Architecture == NV_ARCH_30) {
-		sprintf(rivafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
-	} else {
-		sprintf(rivafb_fix.id, "NV%x", default_par->riva.Architecture);
-	}
-
-	default_par->FlatPanel = flatpanel;
-	if (flatpanel == 1)
-		printk(KERN_INFO PFX "flatpanel support enabled\n");
-	default_par->forceCRTC = forceCRTC;
-	
-	rivafb_fix.mmio_len = pci_resource_len(pd, 0);
-	rivafb_fix.smem_len = pci_resource_len(pd, 1);
-
-	{
-		/* enable IO and mem if not already done */
-		unsigned short cmd;
-
-		pci_read_config_word(pd, PCI_COMMAND, &cmd);
-		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-		pci_write_config_word(pd, PCI_COMMAND, cmd);
-	}
-	
-	rivafb_fix.mmio_start = pci_resource_start(pd, 0);
-	rivafb_fix.smem_start = pci_resource_start(pd, 1);
-
-	default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
-					 rivafb_fix.mmio_len);
-	if (!default_par->ctrl_base) {
-		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
-		ret = -EIO;
-		goto err_release_region;
-	}
-
-	switch (default_par->riva.Architecture) {
-	case NV_ARCH_03:
-		/* Riva128's PRAMIN is in the "framebuffer" space
-		 * Since these cards were never made with more than 8 megabytes
-		 * we can safely allocate this separately.
-		 */
-		default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
-		if (!default_par->riva.PRAMIN) {
-			printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
-			ret = -EIO;
-			goto err_iounmap_ctrl_base;
-		}
-		break;
-	case NV_ARCH_04:
-	case NV_ARCH_10:
-	case NV_ARCH_20:
-	case NV_ARCH_30:
-		default_par->riva.PCRTC0 =
-			(u32 __iomem *)(default_par->ctrl_base + 0x00600000);
-		default_par->riva.PRAMIN =
-			(u32 __iomem *)(default_par->ctrl_base + 0x00710000);
-		break;
-	}
-	riva_common_setup(default_par);
-
-	if (default_par->riva.Architecture == NV_ARCH_03) {
-		default_par->riva.PCRTC = default_par->riva.PCRTC0
-		                        = default_par->riva.PGRAPH;
-	}
-
-	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
-	default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
-	info->screen_base = ioremap(rivafb_fix.smem_start,
-				    rivafb_fix.smem_len);
-	if (!info->screen_base) {
-		printk(KERN_ERR PFX "cannot ioremap FB base\n");
-		ret = -EIO;
-		goto err_iounmap_pramin;
-	}
-
-#ifdef CONFIG_MTRR
-	if (!nomtrr) {
-		default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
-					   	  rivafb_fix.smem_len,
-					    	  MTRR_TYPE_WRCOMB, 1);
-		if (default_par->mtrr.vram < 0) {
-			printk(KERN_ERR PFX "unable to setup MTRR\n");
-		} else {
-			default_par->mtrr.vram_valid = 1;
-			/* let there be speed */
-			printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
-		}
-	}
-#endif /* CONFIG_MTRR */
-
-	info->fbops = &riva_fb_ops;
-	info->fix = rivafb_fix;
-	riva_get_EDID(info, pd);
-	riva_get_edidinfo(info);
-
-	ret=riva_set_fbinfo(info);
-	if (ret < 0) {
-		printk(KERN_ERR PFX "error setting initial video mode\n");
-		goto err_iounmap_screen_base;
-	}
-
-	fb_destroy_modedb(info->monspecs.modedb);
-	info->monspecs.modedb = NULL;
-
-	pci_set_drvdata(pd, info);
-
-	if (backlight)
-		riva_bl_init(info->par);
-
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		printk(KERN_ERR PFX
-			"error registering riva framebuffer\n");
-		goto err_iounmap_screen_base;
-	}
-
-	printk(KERN_INFO PFX
-		"PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
-		info->fix.id,
-		RIVAFB_VERSION,
-		info->fix.smem_len / (1024 * 1024),
-		info->fix.smem_start);
-
-	NVTRACE_LEAVE();
-	return 0;
-
-err_iounmap_screen_base:
-#ifdef CONFIG_FB_RIVA_I2C
-	riva_delete_i2c_busses(info->par);
-#endif
-	iounmap(info->screen_base);
-err_iounmap_pramin:
-	if (default_par->riva.Architecture == NV_ARCH_03) 
-		iounmap(default_par->riva.PRAMIN);
-err_iounmap_ctrl_base:
-	iounmap(default_par->ctrl_base);
-err_release_region:
-	pci_release_regions(pd);
-err_disable_device:
-err_free_pixmap:
-	kfree(info->pixmap.addr);
-err_framebuffer_release:
-	framebuffer_release(info);
-err_ret:
-	return ret;
-}
-
-static void rivafb_remove(struct pci_dev *pd)
-{
-	struct fb_info *info = pci_get_drvdata(pd);
-	struct riva_par *par = info->par;
-	
-	NVTRACE_ENTER();
-
-#ifdef CONFIG_FB_RIVA_I2C
-	riva_delete_i2c_busses(par);
-	kfree(par->EDID);
-#endif
-
-	unregister_framebuffer(info);
-
-	riva_bl_exit(info);
-
-#ifdef CONFIG_MTRR
-	if (par->mtrr.vram_valid)
-		mtrr_del(par->mtrr.vram, info->fix.smem_start,
-			 info->fix.smem_len);
-#endif /* CONFIG_MTRR */
-
-	iounmap(par->ctrl_base);
-	iounmap(info->screen_base);
-	if (par->riva.Architecture == NV_ARCH_03)
-		iounmap(par->riva.PRAMIN);
-	pci_release_regions(pd);
-	kfree(info->pixmap.addr);
-	framebuffer_release(info);
-	NVTRACE_LEAVE();
-}
-
-/* ------------------------------------------------------------------------- *
- *
- * initialization
- *
- * ------------------------------------------------------------------------- */
-
-#ifndef MODULE
-static int rivafb_setup(char *options)
-{
-	char *this_opt;
-
-	NVTRACE_ENTER();
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "forceCRTC", 9)) {
-			char *p;
-			
-			p = this_opt + 9;
-			if (!*p || !*(++p)) continue; 
-			forceCRTC = *p - '0';
-			if (forceCRTC < 0 || forceCRTC > 1) 
-				forceCRTC = -1;
-		} else if (!strncmp(this_opt, "flatpanel", 9)) {
-			flatpanel = 1;
-		} else if (!strncmp(this_opt, "backlight:", 10)) {
-			backlight = simple_strtoul(this_opt+10, NULL, 0);
-#ifdef CONFIG_MTRR
-		} else if (!strncmp(this_opt, "nomtrr", 6)) {
-			nomtrr = 1;
-#endif
-		} else if (!strncmp(this_opt, "strictmode", 10)) {
-			strictmode = 1;
-		} else if (!strncmp(this_opt, "noaccel", 7)) {
-			noaccel = 1;
-		} else
-			mode_option = this_opt;
-	}
-	NVTRACE_LEAVE();
-	return 0;
-}
-#endif /* !MODULE */
-
-static struct pci_driver rivafb_driver = {
-	.name		= "rivafb",
-	.id_table	= rivafb_pci_tbl,
-	.probe		= rivafb_probe,
-	.remove		= rivafb_remove,
-};
-
-
-
-/* ------------------------------------------------------------------------- *
- *
- * modularization
- *
- * ------------------------------------------------------------------------- */
-
-static int rivafb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("rivafb", &option))
-		return -ENODEV;
-	rivafb_setup(option);
-#endif
-	return pci_register_driver(&rivafb_driver);
-}
-
-
-module_init(rivafb_init);
-
-static void __exit rivafb_exit(void)
-{
-	pci_unregister_driver(&rivafb_driver);
-}
-
-module_exit(rivafb_exit);
-
-module_param(noaccel, bool, 0);
-MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
-module_param(flatpanel, int, 0);
-MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");
-module_param(forceCRTC, int, 0);
-MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");
-#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, 0);
-MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
-#endif
-module_param(strictmode, bool, 0);
-MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
-
-MODULE_AUTHOR("Ani Joshi, maintainer");
-MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/nv_driver.c b/drivers/video/riva/nv_driver.c
deleted file mode 100644
index f3694cf17e58..000000000000
--- a/drivers/video/riva/nv_driver.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */
-/*
- * Copyright 1996-1997  David J. McKay
- *
- * 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,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * DAVID J. MCKAY 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.
- */
-
-/*
- * GPL licensing note -- nVidia is allowing a liberal interpretation of
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived
- * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
- */
-
-/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
-   <jpaana@s2.org> */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.18 2002/08/0
-5 20:47:06 mvojkovi Exp $ */
-
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include "nv_type.h"
-#include "rivafb.h"
-#include "nvreg.h"
-
-#define PFX "rivafb: "
-
-static inline unsigned char MISCin(struct riva_par *par)
-{
-	return (VGA_RD08(par->riva.PVIO, 0x3cc));
-}
-
-static Bool 
-riva_is_connected(struct riva_par *par, Bool second)
-{
-	volatile U032 __iomem *PRAMDAC = par->riva.PRAMDAC0;
-	U032 reg52C, reg608;
-	Bool present;
-
-	if(second) PRAMDAC += 0x800;
-
-	reg52C = NV_RD32(PRAMDAC, 0x052C);
-	reg608 = NV_RD32(PRAMDAC, 0x0608);
-
-	NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
-
-	NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
-	mdelay(1); 
-	NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
-
-	NV_WR32(par->riva.PRAMDAC0, 0x0610, 0x94050140);
-	NV_WR32(par->riva.PRAMDAC0, 0x0608, 0x00001000);
-
-	mdelay(1);
-
-	present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? TRUE : FALSE;
-
-	NV_WR32(par->riva.PRAMDAC0, 0x0608,
-		NV_RD32(par->riva.PRAMDAC0, 0x0608) & 0x0000EFFF);
-
-	NV_WR32(PRAMDAC, 0x052C, reg52C);
-	NV_WR32(PRAMDAC, 0x0608, reg608);
-
-	return present;
-}
-
-static void
-riva_override_CRTC(struct riva_par *par)
-{
-	printk(KERN_INFO PFX
-		"Detected CRTC controller %i being used\n",
-		par->SecondCRTC ? 1 : 0);
-
-	if(par->forceCRTC != -1) {
-		printk(KERN_INFO PFX
-			"Forcing usage of CRTC %i\n", par->forceCRTC);
-		par->SecondCRTC = par->forceCRTC;
-	}
-}
-
-static void
-riva_is_second(struct riva_par *par)
-{
-	if (par->FlatPanel == 1) {
-		switch(par->Chipset & 0xffff) {
-		case 0x0174:
-		case 0x0175:
-		case 0x0176:
-		case 0x0177:
-		case 0x0179:
-		case 0x017C:
-		case 0x017D:
-		case 0x0186:
-		case 0x0187:
-		/* this might not be a good default for the chips below */
-		case 0x0286:
-		case 0x028C:
-		case 0x0316:
-		case 0x0317:
-		case 0x031A:
-		case 0x031B:
-		case 0x031C:
-		case 0x031D:
-		case 0x031E:
-		case 0x031F:
-		case 0x0324:
-		case 0x0325:
-		case 0x0328:
-		case 0x0329:
-		case 0x032C:
-		case 0x032D:
-			par->SecondCRTC = TRUE;
-			break;
-		default:
-			par->SecondCRTC = FALSE;
-			break;
-		}
-	} else {
-		if(riva_is_connected(par, 0)) {
-
-			if (NV_RD32(par->riva.PRAMDAC0, 0x0000052C) & 0x100)
-				par->SecondCRTC = TRUE;
-			else
-				par->SecondCRTC = FALSE;
-		} else 
-		if (riva_is_connected(par, 1)) {
-			if(NV_RD32(par->riva.PRAMDAC0, 0x0000252C) & 0x100)
-				par->SecondCRTC = TRUE;
-			else
-				par->SecondCRTC = FALSE;
-		} else /* default */
-			par->SecondCRTC = FALSE;
-	}
-	riva_override_CRTC(par);
-}
-
-unsigned long riva_get_memlen(struct riva_par *par)
-{
-	RIVA_HW_INST *chip = &par->riva;
-	unsigned long memlen = 0;
-	unsigned int chipset = par->Chipset;
-	struct pci_dev* dev;
-	u32 amt;
-
-	switch (chip->Architecture) {
-	case NV_ARCH_03:
-		if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) {
-			if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
-			    && ((NV_RD32(chip->PMC, 0x00000000)&0x0F)>=0x02)) {
-				/*
-				 * SDRAM 128 ZX.
-				 */
-				switch (NV_RD32(chip->PFB,0x00000000) & 0x03) {
-				case 2:
-					memlen = 1024 * 4;
-					break;
-				case 1:
-					memlen = 1024 * 2;
-					break;
-				default:
-					memlen = 1024 * 8;
-					break;
-				}
-			} else {
-				memlen = 1024 * 8;
-			}            
-		} else 	{
-			/*
-			 * SGRAM 128.
-			 */
-			switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) {
-			case 0:
-				memlen = 1024 * 8;
-				break;
-			case 2:
-				memlen = 1024 * 4;
-				break;
-			default:
-				memlen = 1024 * 2;
-				break;
-			}
-		}        
-		break;
-	case NV_ARCH_04:
-		if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100) {
-			memlen = ((NV_RD32(chip->PFB, 0x00000000)>>12)&0x0F) *
-				1024 * 2 + 1024 * 2;
-		} else {
-			switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) {
-			case 0:
-				memlen = 1024 * 32;
-				break;
-			case 1:
-				memlen = 1024 * 4;
-				break;
-			case 2:
-				memlen = 1024 * 8;
-				break;
-			case 3:
-			default:
-				memlen = 1024 * 16;
-				break;
-			}
-		}
-		break;
-	case NV_ARCH_10:
-	case NV_ARCH_20:
-	case NV_ARCH_30:
-		if(chipset == NV_CHIP_IGEFORCE2) {
-
-			dev = pci_get_bus_and_slot(0, 1);
-			pci_read_config_dword(dev, 0x7C, &amt);
-			pci_dev_put(dev);
-			memlen = (((amt >> 6) & 31) + 1) * 1024;
-		} else if (chipset == NV_CHIP_0x01F0) {
-			dev = pci_get_bus_and_slot(0, 1);
-			pci_read_config_dword(dev, 0x84, &amt);
-			pci_dev_put(dev);
-			memlen = (((amt >> 4) & 127) + 1) * 1024;
-		} else {
-			switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) &
-				0x000000FF){
-			case 0x02:
-				memlen = 1024 * 2;
-				break;
-			case 0x04:
-				memlen = 1024 * 4;
-				break;
-			case 0x08:
-				memlen = 1024 * 8;
-				break;
-			case 0x10:
-				memlen = 1024 * 16;
-				break;
-			case 0x20:
-				memlen = 1024 * 32;
-				break;
-			case 0x40:
-				memlen = 1024 * 64;
-				break;
-			case 0x80:
-				memlen = 1024 * 128;
-				break;
-			default:
-				memlen = 1024 * 16;
-				break;
-			}
-		}
-		break;
-	}
-	return memlen;
-}
-
-unsigned long riva_get_maxdclk(struct riva_par *par)
-{
-	RIVA_HW_INST *chip = &par->riva;
-	unsigned long dclk = 0;
-
-	switch (chip->Architecture) {
-	case NV_ARCH_03:
-		if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) {
-			if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
-			    && ((NV_RD32(chip->PMC,0x00000000)&0x0F) >= 0x02)) {
-				/*
-				 * SDRAM 128 ZX.
-				 */
-				dclk = 800000;
-			} else {
-				dclk = 1000000;
-			}            
-		} else {
-			/*
-			 * SGRAM 128.
-			 */
-			dclk = 1000000;
-		} 
-		break;
-	case NV_ARCH_04:
-	case NV_ARCH_10:
-	case NV_ARCH_20:
-	case NV_ARCH_30:
-		switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003) {
-		case 3:
-			dclk = 800000;
-			break;
-		default:
-			dclk = 1000000;
-			break;
-		}
-		break;
-	}
-	return dclk;
-}
-
-void
-riva_common_setup(struct riva_par *par)
-{
-	par->riva.EnableIRQ = 0;
-	par->riva.PRAMDAC0 =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00680000);
-	par->riva.PFB =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00100000);
-	par->riva.PFIFO =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00002000);
-	par->riva.PGRAPH =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00400000);
-	par->riva.PEXTDEV =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00101000);
-	par->riva.PTIMER =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00009000);
-	par->riva.PMC =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00000000);
-	par->riva.FIFO =
-		(volatile U032 __iomem *)(par->ctrl_base + 0x00800000);
-	par->riva.PCIO0 = par->ctrl_base + 0x00601000;
-	par->riva.PDIO0 = par->ctrl_base + 0x00681000;
-	par->riva.PVIO = par->ctrl_base + 0x000C0000;
-
-	par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0;
-	
-	if (par->FlatPanel == -1) {
-		switch (par->Chipset & 0xffff) {
-		case 0x0112:   /* known laptop chips */
-		case 0x0174:
-		case 0x0175:
-		case 0x0176:
-		case 0x0177:
-		case 0x0179:
-		case 0x017C:
-		case 0x017D:
-		case 0x0186:
-		case 0x0187:
-		case 0x0286:
-		case 0x028C:
-		case 0x0316:
-		case 0x0317:
-		case 0x031A:
-		case 0x031B:
-		case 0x031C:
-		case 0x031D:
-		case 0x031E:
-		case 0x031F:
-		case 0x0324:
-		case 0x0325:
-		case 0x0328:
-		case 0x0329:
-		case 0x032C:
-		case 0x032D:
-			printk(KERN_INFO PFX 
-				"On a laptop.  Assuming Digital Flat Panel\n");
-			par->FlatPanel = 1;
-			break;
-		default:
-			break;
-		}
-	}
-	
-	switch (par->Chipset & 0x0ff0) {
-	case 0x0110:
-		if (par->Chipset == NV_CHIP_GEFORCE2_GO)
-			par->SecondCRTC = TRUE; 
-#if defined(__powerpc__)
-		if (par->FlatPanel == 1)
-			par->SecondCRTC = TRUE;
-#endif
-		riva_override_CRTC(par);
-		break;
-	case 0x0170:
-	case 0x0180:
-	case 0x01F0:
-	case 0x0250:
-	case 0x0280:
-	case 0x0300:
-	case 0x0310:
-	case 0x0320:
-	case 0x0330:
-	case 0x0340:
-		riva_is_second(par);
-		break;
-	default:
-		break;
-	}
-
-	if (par->SecondCRTC) {
-		par->riva.PCIO = par->riva.PCIO0 + 0x2000;
-		par->riva.PCRTC = par->riva.PCRTC0 + 0x800;
-		par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800;
-		par->riva.PDIO = par->riva.PDIO0 + 0x2000;
-	} else {
-		par->riva.PCIO = par->riva.PCIO0;
-		par->riva.PCRTC = par->riva.PCRTC0;
-		par->riva.PRAMDAC = par->riva.PRAMDAC0;
-		par->riva.PDIO = par->riva.PDIO0;
-	}
-
-	if (par->FlatPanel == -1) {
-		/* Fix me, need x86 DDC code */
-		par->FlatPanel = 0;
-	}
-	par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE;
-
-	RivaGetConfig(&par->riva, par->Chipset);
-}
-
diff --git a/drivers/video/riva/nv_type.h b/drivers/video/riva/nv_type.h
deleted file mode 100644
index a69480c9a67c..000000000000
--- a/drivers/video/riva/nv_type.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_type.h,v 1.35 2002/08/05 20:47:06 mvojkovi Exp $ */
-
-#ifndef __NV_STRUCT_H__
-#define __NV_STRUCT_H__
-
-#define NV_CHIP_RIVA_128            ((PCI_VENDOR_ID_NVIDIA_SGS << 16)| PCI_DEVICE_ID_NVIDIA_RIVA128)
-#define NV_CHIP_TNT                 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT)
-#define NV_CHIP_TNT2                ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT2)
-#define NV_CHIP_UTNT2               ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UTNT2)
-#define NV_CHIP_VTNT2               ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_VTNT2)
-#define NV_CHIP_UVTNT2              ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UVTNT2)
-#define NV_CHIP_ITNT2               ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_ITNT2)
-#define NV_CHIP_GEFORCE_256         ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_256)
-#define NV_CHIP_GEFORCE_DDR         ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR)
-#define NV_CHIP_QUADRO              ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_QUADRO)
-#define NV_CHIP_GEFORCE2_MX         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX)
-#define NV_CHIP_GEFORCE2_MX_100     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX_100)
-#define NV_CHIP_QUADRO2_MXR         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR)
-#define NV_CHIP_GEFORCE2_GO         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO)
-#define NV_CHIP_GEFORCE2_GTS        ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS)
-#define NV_CHIP_GEFORCE2_TI         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_TI)
-#define NV_CHIP_GEFORCE2_ULTRA      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA)
-#define NV_CHIP_QUADRO2_PRO         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO)
-#define NV_CHIP_GEFORCE4_MX_460     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460)
-#define NV_CHIP_GEFORCE4_MX_440     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440)
-#define NV_CHIP_GEFORCE4_MX_420     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420)
-#define NV_CHIP_GEFORCE4_440_GO     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO)
-#define NV_CHIP_GEFORCE4_420_GO     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO)
-#define NV_CHIP_GEFORCE4_420_GO_M32 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32)
-#define NV_CHIP_QUADRO4_500XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL)
-#define NV_CHIP_GEFORCE4_440_GO_M64 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64)
-#define NV_CHIP_QUADRO4_200         ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_200)
-#define NV_CHIP_QUADRO4_550XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL)
-#define NV_CHIP_QUADRO4_500_GOGL    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL)
-#define NV_CHIP_0x0180              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0180)
-#define NV_CHIP_0x0181              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0181)
-#define NV_CHIP_0x0182              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0182)
-#define NV_CHIP_0x0188              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0188)
-#define NV_CHIP_0x018A              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018A)
-#define NV_CHIP_0x018B              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018B)
-#define NV_CHIP_IGEFORCE2           ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_IGEFORCE2)
-#define NV_CHIP_0x01F0              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x01F0)
-#define NV_CHIP_GEFORCE3            ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3)
-#define NV_CHIP_GEFORCE3_TI_200     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_200)
-#define NV_CHIP_GEFORCE3_TI_500     ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_500)
-#define NV_CHIP_QUADRO_DCC          ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO_DCC)
-#define NV_CHIP_GEFORCE4_TI_4600    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600)
-#define NV_CHIP_GEFORCE4_TI_4400    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400)
-#define NV_CHIP_GEFORCE4_TI_4200    ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200)
-#define NV_CHIP_QUADRO4_900XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL)
-#define NV_CHIP_QUADRO4_750XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL)
-#define NV_CHIP_QUADRO4_700XGL      ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL)
-#define NV_CHIP_0x0280              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0280)
-#define NV_CHIP_0x0281              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0281)
-#define NV_CHIP_0x0288              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0288)
-#define NV_CHIP_0x0289              ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0289)
-
-#endif /* __NV_STRUCT_H__ */
diff --git a/drivers/video/riva/nvreg.h b/drivers/video/riva/nvreg.h
deleted file mode 100644
index abfc167ae8d8..000000000000
--- a/drivers/video/riva/nvreg.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */
-/*
- * Copyright 1996-1997  David J. McKay
- *
- * 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,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * DAVID J. MCKAY 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.
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/nvreg.h,v 3.2.2.1 1998/01/18 10:35:36 hohndel Exp $ */
-
-#ifndef __NVREG_H_
-#define __NVREG_H_
-
-/* Little macro to construct bitmask for contiguous ranges of bits */
-#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1)  << (b))
-#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
-
-/* Macro to set specific bitfields (mask has to be a macro x:y) ! */
-#define SetBF(mask,value) ((value) << (0?mask))
-#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
-
-#define MaskAndSetBF(var,mask,value) (var)=(((var)&(~MASKEXPAND(mask)) \
-                                             | SetBF(mask,value)))
-
-#define DEVICE_BASE(device) (0?NV##_##device)
-#define DEVICE_SIZE(device) ((1?NV##_##device) - DEVICE_BASE(device)+1)
-
-/* This is where we will have to have conditional compilation */
-#define DEVICE_ACCESS(device,reg) \
-  nvCONTROL[(NV_##device##_##reg)/4]
-
-#define DEVICE_WRITE(device,reg,value) DEVICE_ACCESS(device,reg)=(value)
-#define DEVICE_READ(device,reg)        DEVICE_ACCESS(device,reg)
-#define DEVICE_PRINT(device,reg) \
-  ErrorF("NV_"#device"_"#reg"=#%08lx\n",DEVICE_ACCESS(device,reg))
-#define DEVICE_DEF(device,mask,value) \
-  SetBF(NV_##device##_##mask,NV_##device##_##mask##_##value)
-#define DEVICE_VALUE(device,mask,value) SetBF(NV_##device##_##mask,value)
-#define DEVICE_MASK(device,mask) MASKEXPAND(NV_##device##_##mask)
-
-#define PDAC_Write(reg,value)           DEVICE_WRITE(PDAC,reg,value)
-#define PDAC_Read(reg)                  DEVICE_READ(PDAC,reg)
-#define PDAC_Print(reg)                 DEVICE_PRINT(PDAC,reg)
-#define PDAC_Def(mask,value)            DEVICE_DEF(PDAC,mask,value)
-#define PDAC_Val(mask,value)            DEVICE_VALUE(PDAC,mask,value)
-#define PDAC_Mask(mask)                 DEVICE_MASK(PDAC,mask)
-
-#define PFB_Write(reg,value)            DEVICE_WRITE(PFB,reg,value)
-#define PFB_Read(reg)                   DEVICE_READ(PFB,reg)
-#define PFB_Print(reg)                  DEVICE_PRINT(PFB,reg)
-#define PFB_Def(mask,value)             DEVICE_DEF(PFB,mask,value)
-#define PFB_Val(mask,value)             DEVICE_VALUE(PFB,mask,value)
-#define PFB_Mask(mask)                  DEVICE_MASK(PFB,mask)
-
-#define PRM_Write(reg,value)            DEVICE_WRITE(PRM,reg,value)
-#define PRM_Read(reg)                   DEVICE_READ(PRM,reg)
-#define PRM_Print(reg)                  DEVICE_PRINT(PRM,reg)
-#define PRM_Def(mask,value)             DEVICE_DEF(PRM,mask,value)
-#define PRM_Val(mask,value)             DEVICE_VALUE(PRM,mask,value)
-#define PRM_Mask(mask)                  DEVICE_MASK(PRM,mask)
-
-#define PGRAPH_Write(reg,value)         DEVICE_WRITE(PGRAPH,reg,value)
-#define PGRAPH_Read(reg)                DEVICE_READ(PGRAPH,reg)
-#define PGRAPH_Print(reg)               DEVICE_PRINT(PGRAPH,reg)
-#define PGRAPH_Def(mask,value)          DEVICE_DEF(PGRAPH,mask,value)
-#define PGRAPH_Val(mask,value)          DEVICE_VALUE(PGRAPH,mask,value)
-#define PGRAPH_Mask(mask)               DEVICE_MASK(PGRAPH,mask)
-
-#define PDMA_Write(reg,value)           DEVICE_WRITE(PDMA,reg,value)
-#define PDMA_Read(reg)                  DEVICE_READ(PDMA,reg)
-#define PDMA_Print(reg)                 DEVICE_PRINT(PDMA,reg)
-#define PDMA_Def(mask,value)            DEVICE_DEF(PDMA,mask,value)
-#define PDMA_Val(mask,value)            DEVICE_VALUE(PDMA,mask,value)
-#define PDMA_Mask(mask)                 DEVICE_MASK(PDMA,mask)
-
-#define PTIMER_Write(reg,value)         DEVICE_WRITE(PTIMER,reg,value)
-#define PTIMER_Read(reg)                DEVICE_READ(PTIMER,reg)
-#define PTIMER_Print(reg)               DEVICE_PRINT(PTIMER,reg)
-#define PTIMER_Def(mask,value)          DEVICE_DEF(PTIMER,mask,value)
-#define PTIMER_Val(mask,value)          DEVICE_VALUE(PTIEMR,mask,value)
-#define PTIMER_Mask(mask)               DEVICE_MASK(PTIMER,mask)
-
-#define PEXTDEV_Write(reg,value)         DEVICE_WRITE(PEXTDEV,reg,value)
-#define PEXTDEV_Read(reg)                DEVICE_READ(PEXTDEV,reg)
-#define PEXTDEV_Print(reg)               DEVICE_PRINT(PEXTDEV,reg)
-#define PEXTDEV_Def(mask,value)          DEVICE_DEF(PEXTDEV,mask,value)
-#define PEXTDEV_Val(mask,value)          DEVICE_VALUE(PEXTDEV,mask,value)
-#define PEXTDEV_Mask(mask)               DEVICE_MASK(PEXTDEV,mask)
-
-#define PFIFO_Write(reg,value)          DEVICE_WRITE(PFIFO,reg,value)
-#define PFIFO_Read(reg)                 DEVICE_READ(PFIFO,reg)
-#define PFIFO_Print(reg)                DEVICE_PRINT(PFIFO,reg)
-#define PFIFO_Def(mask,value)           DEVICE_DEF(PFIFO,mask,value)
-#define PFIFO_Val(mask,value)           DEVICE_VALUE(PFIFO,mask,value)
-#define PFIFO_Mask(mask)                DEVICE_MASK(PFIFO,mask)
-
-#define PRAM_Write(reg,value)           DEVICE_WRITE(PRAM,reg,value)
-#define PRAM_Read(reg)                  DEVICE_READ(PRAM,reg)
-#define PRAM_Print(reg)                 DEVICE_PRINT(PRAM,reg)
-#define PRAM_Def(mask,value)            DEVICE_DEF(PRAM,mask,value)
-#define PRAM_Val(mask,value)            DEVICE_VALUE(PRAM,mask,value)
-#define PRAM_Mask(mask)                 DEVICE_MASK(PRAM,mask)
-
-#define PRAMFC_Write(reg,value)         DEVICE_WRITE(PRAMFC,reg,value)
-#define PRAMFC_Read(reg)                DEVICE_READ(PRAMFC,reg)
-#define PRAMFC_Print(reg)               DEVICE_PRINT(PRAMFC,reg)
-#define PRAMFC_Def(mask,value)          DEVICE_DEF(PRAMFC,mask,value)
-#define PRAMFC_Val(mask,value)          DEVICE_VALUE(PRAMFC,mask,value)
-#define PRAMFC_Mask(mask)               DEVICE_MASK(PRAMFC,mask)
-
-#define PMC_Write(reg,value)            DEVICE_WRITE(PMC,reg,value)
-#define PMC_Read(reg)                   DEVICE_READ(PMC,reg)
-#define PMC_Print(reg)                  DEVICE_PRINT(PMC,reg)
-#define PMC_Def(mask,value)             DEVICE_DEF(PMC,mask,value)
-#define PMC_Val(mask,value)             DEVICE_VALUE(PMC,mask,value)
-#define PMC_Mask(mask)                  DEVICE_MASK(PMC,mask)
-
-#define PMC_Write(reg,value)            DEVICE_WRITE(PMC,reg,value)
-#define PMC_Read(reg)                   DEVICE_READ(PMC,reg)
-#define PMC_Print(reg)                  DEVICE_PRINT(PMC,reg)
-#define PMC_Def(mask,value)             DEVICE_DEF(PMC,mask,value)
-#define PMC_Val(mask,value)             DEVICE_VALUE(PMC,mask,value)
-#define PMC_Mask(mask)                  DEVICE_MASK(PMC,mask)
-
-
-#define PBUS_Write(reg,value)         DEVICE_WRITE(PBUS,reg,value)
-#define PBUS_Read(reg)                DEVICE_READ(PBUS,reg)
-#define PBUS_Print(reg)               DEVICE_PRINT(PBUS,reg)
-#define PBUS_Def(mask,value)          DEVICE_DEF(PBUS,mask,value)
-#define PBUS_Val(mask,value)          DEVICE_VALUE(PBUS,mask,value)
-#define PBUS_Mask(mask)               DEVICE_MASK(PBUS,mask)
-
-
-#define PRAMDAC_Write(reg,value)         DEVICE_WRITE(PRAMDAC,reg,value)
-#define PRAMDAC_Read(reg)                DEVICE_READ(PRAMDAC,reg)
-#define PRAMDAC_Print(reg)               DEVICE_PRINT(PRAMDAC,reg)
-#define PRAMDAC_Def(mask,value)          DEVICE_DEF(PRAMDAC,mask,value)
-#define PRAMDAC_Val(mask,value)          DEVICE_VALUE(PRAMDAC,mask,value)
-#define PRAMDAC_Mask(mask)               DEVICE_MASK(PRAMDAC,mask)
-
-
-#define PDAC_ReadExt(reg) \
-  ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\
-  (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\
-  (PDAC_Read(INDEX_DATA)))
-
-#define PDAC_WriteExt(reg,value)\
-  ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\
-  (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\
-  (PDAC_Write(INDEX_DATA,(value))))
-
-#define CRTC_Write(index,value) outb((index), 0x3d4); outb(value, 0x3d5)
-#define CRTC_Read(index) (outb(index, 0x3d4),inb(0x3d5))
-
-#define PCRTC_Write(index,value) CRTC_Write(NV_PCRTC_##index,value)
-#define PCRTC_Read(index) CRTC_Read(NV_PCRTC_##index)
-
-#define PCRTC_Def(mask,value)          DEVICE_DEF(PCRTC,mask,value)
-#define PCRTC_Val(mask,value)          DEVICE_VALUE(PCRTC,mask,value)
-#define PCRTC_Mask(mask)               DEVICE_MASK(PCRTC,mask)
-
-#define SR_Write(index,value) outb(0x3c4,(index));outb(0x3c5,value)
-#define SR_Read(index) (outb(0x3c4,index),inb(0x3c5))
-
-extern volatile unsigned  *nvCONTROL;
-
-typedef enum {NV1,NV3,NV4,NumNVChips} NVChipType;
-
-NVChipType GetChipType(void);
-
-#endif
-
-
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
deleted file mode 100644
index 78fdbf5178d7..000000000000
--- a/drivers/video/riva/riva_hw.c
+++ /dev/null
@@ -1,2268 +0,0 @@
- /***************************************************************************\
-|*                                                                           *|
-|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL licensing note -- nVidia is allowing a liberal interpretation of
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived
- * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.33 2002/08/05 20:47:06 mvojkovi Exp $ */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include "riva_hw.h"
-#include "riva_tbl.h"
-#include "nv_type.h"
-
-/*
- * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
- * operate identically (except TNT has more memory and better 3D quality.
- */
-static int nv3Busy
-(
-    RIVA_HW_INST *chip
-)
-{
-    return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
-	    NV_RD32(&chip->PGRAPH[0x000006B0/4], 0) & 0x01);
-}
-static int nv4Busy
-(
-    RIVA_HW_INST *chip
-)
-{
-    return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
-	    NV_RD32(&chip->PGRAPH[0x00000700/4], 0) & 0x01);
-}
-static int nv10Busy
-(
-    RIVA_HW_INST *chip
-)
-{
-    return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
-	    NV_RD32(&chip->PGRAPH[0x00000700/4], 0) & 0x01);
-}
-
-static void vgaLockUnlock
-(
-    RIVA_HW_INST *chip,
-    int           Lock
-)
-{
-    U008 cr11;
-    VGA_WR08(chip->PCIO, 0x3D4, 0x11);
-    cr11 = VGA_RD08(chip->PCIO, 0x3D5);
-    if(Lock) cr11 |= 0x80;
-    else cr11 &= ~0x80;
-    VGA_WR08(chip->PCIO, 0x3D5, cr11);
-}
-static void nv3LockUnlock
-(
-    RIVA_HW_INST *chip,
-    int           Lock
-)
-{
-    VGA_WR08(chip->PVIO, 0x3C4, 0x06);
-    VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57);
-    vgaLockUnlock(chip, Lock);
-}
-static void nv4LockUnlock
-(
-    RIVA_HW_INST *chip,
-    int           Lock
-)
-{
-    VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
-    VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
-    vgaLockUnlock(chip, Lock);
-}
-
-static int ShowHideCursor
-(
-    RIVA_HW_INST *chip,
-    int           ShowHide
-)
-{
-    int cursor;
-    cursor                      =  chip->CurrentState->cursor1;
-    chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
-                                  (ShowHide & 0x01);
-    VGA_WR08(chip->PCIO, 0x3D4, 0x31);
-    VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
-    return (cursor & 0x01);
-}
-
-/****************************************************************************\
-*                                                                            *
-* The video arbitration routines calculate some "magic" numbers.  Fixes      *
-* the snow seen when accessing the framebuffer without it.                   *
-* It just works (I hope).                                                    *
-*                                                                            *
-\****************************************************************************/
-
-#define DEFAULT_GR_LWM 100
-#define DEFAULT_VID_LWM 100
-#define DEFAULT_GR_BURST_SIZE 256
-#define DEFAULT_VID_BURST_SIZE 128
-#define VIDEO		0
-#define GRAPHICS	1
-#define MPORT		2
-#define ENGINE		3
-#define GFIFO_SIZE	320
-#define GFIFO_SIZE_128	256
-#define MFIFO_SIZE	120
-#define VFIFO_SIZE	256
-
-typedef struct {
-  int gdrain_rate;
-  int vdrain_rate;
-  int mdrain_rate;
-  int gburst_size;
-  int vburst_size;
-  char vid_en;
-  char gr_en;
-  int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm;
-  int by_gfacc;
-  char vid_only_once;
-  char gr_only_once;
-  char first_vacc;
-  char first_gacc;
-  char first_macc;
-  int vocc;
-  int gocc;
-  int mocc;
-  char cur;
-  char engine_en;
-  char converged;
-  int priority;
-} nv3_arb_info;
-typedef struct {
-  int graphics_lwm;
-  int video_lwm;
-  int graphics_burst_size;
-  int video_burst_size;
-  int graphics_hi_priority;
-  int media_hi_priority;
-  int rtl_values;
-  int valid;
-} nv3_fifo_info;
-typedef struct {
-  char pix_bpp;
-  char enable_video;
-  char gr_during_vid;
-  char enable_mp;
-  int memory_width;
-  int video_scale;
-  int pclk_khz;
-  int mclk_khz;
-  int mem_page_miss;
-  int mem_latency;
-  char mem_aligned;
-} nv3_sim_state;
-typedef struct {
-  int graphics_lwm;
-  int video_lwm;
-  int graphics_burst_size;
-  int video_burst_size;
-  int valid;
-} nv4_fifo_info;
-typedef struct {
-  int pclk_khz;
-  int mclk_khz;
-  int nvclk_khz;
-  char mem_page_miss;
-  char mem_latency;
-  int memory_width;
-  char enable_video;
-  char gr_during_vid;
-  char pix_bpp;
-  char mem_aligned;
-  char enable_mp;
-} nv4_sim_state;
-typedef struct {
-  int graphics_lwm;
-  int video_lwm;
-  int graphics_burst_size;
-  int video_burst_size;
-  int valid;
-} nv10_fifo_info;
-typedef struct {
-  int pclk_khz;
-  int mclk_khz;
-  int nvclk_khz;
-  char mem_page_miss;
-  char mem_latency;
-  u32 memory_type;
-  int memory_width;
-  char enable_video;
-  char gr_during_vid;
-  char pix_bpp;
-  char mem_aligned;
-  char enable_mp;
-} nv10_sim_state;
-static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
-{
-    int iter = 0;
-    int tmp;
-    int vfsize, mfsize, gfsize;
-    int mburst_size = 32;
-    int mmisses, gmisses, vmisses;
-    int misses;
-    int vlwm, glwm, mlwm;
-    int last, next, cur;
-    int max_gfsize ;
-    long ns;
-
-    vlwm = 0;
-    glwm = 0;
-    mlwm = 0;
-    vfsize = 0;
-    gfsize = 0;
-    cur = ainfo->cur;
-    mmisses = 2;
-    gmisses = 2;
-    vmisses = 2;
-    if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128;
-    else  max_gfsize = GFIFO_SIZE;
-    max_gfsize = GFIFO_SIZE;
-    while (1)
-    {
-        if (ainfo->vid_en)
-        {
-            if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc;
-            if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ;
-            ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
-            vfsize = ns * ainfo->vdrain_rate / 1000000;
-            vfsize =  ainfo->wcvlwm - ainfo->vburst_size + vfsize;
-        }
-        if (state->enable_mp)
-        {
-            if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc;
-        }
-        if (ainfo->gr_en)
-        {
-            if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
-            if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
-            ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
-            gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
-            gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
-        }
-        mfsize = 0;
-        if (!state->gr_during_vid && ainfo->vid_en)
-            if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once)
-                next = VIDEO;
-            else if (ainfo->mocc < 0)
-                next = MPORT;
-            else if (ainfo->gocc< ainfo->by_gfacc)
-                next = GRAPHICS;
-            else return (0);
-        else switch (ainfo->priority)
-            {
-                case VIDEO:
-                    if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
-                        next = VIDEO;
-                    else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
-                        next = GRAPHICS;
-                    else if (ainfo->mocc<0)
-                        next = MPORT;
-                    else    return (0);
-                    break;
-                case GRAPHICS:
-                    if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
-                        next = GRAPHICS;
-                    else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
-                        next = VIDEO;
-                    else if (ainfo->mocc<0)
-                        next = MPORT;
-                    else    return (0);
-                    break;
-                default:
-                    if (ainfo->mocc<0)
-                        next = MPORT;
-                    else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
-                        next = GRAPHICS;
-                    else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
-                        next = VIDEO;
-                    else    return (0);
-                    break;
-            }
-        last = cur;
-        cur = next;
-        iter++;
-        switch (cur)
-        {
-            case VIDEO:
-                if (last==cur)    misses = 0;
-                else if (ainfo->first_vacc)   misses = vmisses;
-                else    misses = 1;
-                ainfo->first_vacc = 0;
-                if (last!=cur)
-                {
-                    ns =  1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; 
-                    vlwm = ns * ainfo->vdrain_rate/ 1000000;
-                    vlwm = ainfo->vocc - vlwm;
-                }
-                ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz;
-                ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000;
-                ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000;
-                ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000;
-                break;
-            case GRAPHICS:
-                if (last==cur)    misses = 0;
-                else if (ainfo->first_gacc)   misses = gmisses;
-                else    misses = 1;
-                ainfo->first_gacc = 0;
-                if (last!=cur)
-                {
-                    ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ;
-                    glwm = ns * ainfo->gdrain_rate/1000000;
-                    glwm = ainfo->gocc - glwm;
-                }
-                ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
-                ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
-                ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000;
-                ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000;
-                break;
-            default:
-                if (last==cur)    misses = 0;
-                else if (ainfo->first_macc)   misses = mmisses;
-                else    misses = 1;
-                ainfo->first_macc = 0;
-                ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz;
-                ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
-                ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000;
-                ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000;
-                break;
-        }
-        if (iter>100)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
-        tmp = ns * ainfo->gdrain_rate/1000000;
-        if (abs(ainfo->gburst_size) + ((abs(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
-        tmp = ns * ainfo->vdrain_rate/1000000;
-        if (abs(ainfo->vburst_size) + (abs(ainfo->wcvlwm + 32) & ~0xf)  - tmp> VFIFO_SIZE)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        if (abs(ainfo->gocc) > max_gfsize)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        if (abs(ainfo->vocc) > VFIFO_SIZE)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        if (abs(ainfo->mocc) > MFIFO_SIZE)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        if (abs(vfsize) > VFIFO_SIZE)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        if (abs(gfsize) > max_gfsize)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-        if (abs(mfsize) > MFIFO_SIZE)
-        {
-            ainfo->converged = 0;
-            return (1);
-        }
-    }
-}
-static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state,  nv3_arb_info *ainfo) 
-{
-    long ens, vns, mns, gns;
-    int mmisses, gmisses, vmisses, eburst_size, mburst_size;
-    int refresh_cycle;
-
-    refresh_cycle = 0;
-    refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5;
-    mmisses = 2;
-    if (state->mem_aligned) gmisses = 2;
-    else    gmisses = 3;
-    vmisses = 2;
-    eburst_size = state->memory_width * 1;
-    mburst_size = 32;
-    gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
-    ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
-    ainfo->wcmocc = 0;
-    ainfo->wcgocc = 0;
-    ainfo->wcvocc = 0;
-    ainfo->wcvlwm = 0;
-    ainfo->wcglwm = 0;
-    ainfo->engine_en = 1;
-    ainfo->converged = 1;
-    if (ainfo->engine_en)
-    {
-        ens =  1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz;
-        ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0;
-        ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0;
-        ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0;
-        ainfo->cur = ENGINE;
-        ainfo->first_vacc = 1;
-        ainfo->first_gacc = 1;
-        ainfo->first_macc = 1;
-        nv3_iterate(res_info, state,ainfo);
-    }
-    if (state->enable_mp)
-    {
-        mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
-        ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000;
-        ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000;
-        ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000;
-        ainfo->cur = MPORT;
-        ainfo->first_vacc = 1;
-        ainfo->first_gacc = 1;
-        ainfo->first_macc = 0;
-        nv3_iterate(res_info, state,ainfo);
-    }
-    if (ainfo->gr_en)
-    {
-        ainfo->first_vacc = 1;
-        ainfo->first_gacc = 0;
-        ainfo->first_macc = 1;
-        gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
-        ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000;
-        ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0;
-        ainfo->mocc = state->enable_mp ?  0-gns*ainfo->mdrain_rate/1000000: 0;
-        ainfo->cur = GRAPHICS;
-        nv3_iterate(res_info, state,ainfo);
-    }
-    if (ainfo->vid_en)
-    {
-        ainfo->first_vacc = 0;
-        ainfo->first_gacc = 1;
-        ainfo->first_macc = 1;
-        vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
-        ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000;
-        ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0;
-        ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ;
-        ainfo->cur = VIDEO;
-        nv3_iterate(res_info, state, ainfo);
-    }
-    if (ainfo->converged)
-    {
-        res_info->graphics_lwm = (int)abs(ainfo->wcglwm) + 16;
-        res_info->video_lwm = (int)abs(ainfo->wcvlwm) + 32;
-        res_info->graphics_burst_size = ainfo->gburst_size;
-        res_info->video_burst_size = ainfo->vburst_size;
-        res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS);
-        res_info->media_hi_priority = (ainfo->priority == MPORT);
-        if (res_info->video_lwm > 160)
-        {
-            res_info->graphics_lwm = 256;
-            res_info->video_lwm = 128;
-            res_info->graphics_burst_size = 64;
-            res_info->video_burst_size = 64;
-            res_info->graphics_hi_priority = 0;
-            res_info->media_hi_priority = 0;
-            ainfo->converged = 0;
-            return (0);
-        }
-        if (res_info->video_lwm > 128)
-        {
-            res_info->video_lwm = 128;
-        }
-        return (1);
-    }
-    else
-    {
-        res_info->graphics_lwm = 256;
-        res_info->video_lwm = 128;
-        res_info->graphics_burst_size = 64;
-        res_info->video_burst_size = 64;
-        res_info->graphics_hi_priority = 0;
-        res_info->media_hi_priority = 0;
-        return (0);
-    }
-}
-static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
-{
-    int done, g,v, p;
-    
-    done = 0;
-    for (p=0; p < 2; p++)
-    {
-        for (g=128 ; g > 32; g= g>> 1)
-        {
-            for (v=128; v >=32; v = v>> 1)
-            {
-                ainfo->priority = p;
-                ainfo->gburst_size = g;     
-                ainfo->vburst_size = v;
-                done = nv3_arb(res_info, state,ainfo);
-                if (done && (g==128))
-                    if ((res_info->graphics_lwm + g) > 256)
-                        done = 0;
-                if (done)
-                    goto Done;
-            }
-        }
-    }
-
- Done:
-    return done;
-}
-static void nv3CalcArbitration 
-(
-    nv3_fifo_info * res_info,
-    nv3_sim_state * state
-)
-{
-    nv3_fifo_info save_info;
-    nv3_arb_info ainfo;
-    char   res_gr, res_vid;
-
-    ainfo.gr_en = 1;
-    ainfo.vid_en = state->enable_video;
-    ainfo.vid_only_once = 0;
-    ainfo.gr_only_once = 0;
-    ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
-    ainfo.vdrain_rate = (int) state->pclk_khz * 2;
-    if (state->video_scale != 0)
-        ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
-    ainfo.mdrain_rate = 33000;
-    res_info->rtl_values = 0;
-    if (!state->gr_during_vid && state->enable_video)
-    {
-        ainfo.gr_only_once = 1;
-        ainfo.gr_en = 1;
-        ainfo.gdrain_rate = 0;
-        res_vid = nv3_get_param(res_info, state,  &ainfo);
-        res_vid = ainfo.converged;
-        save_info.video_lwm = res_info->video_lwm;
-        save_info.video_burst_size = res_info->video_burst_size;
-        ainfo.vid_en = 1;
-        ainfo.vid_only_once = 1;
-        ainfo.gr_en = 1;
-        ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
-        ainfo.vdrain_rate = 0;
-        res_gr = nv3_get_param(res_info, state,  &ainfo);
-        res_gr = ainfo.converged;
-        res_info->video_lwm = save_info.video_lwm;
-        res_info->video_burst_size = save_info.video_burst_size;
-        res_info->valid = res_gr & res_vid;
-    }
-    else
-    {
-        if (!ainfo.gr_en) ainfo.gdrain_rate = 0;
-        if (!ainfo.vid_en) ainfo.vdrain_rate = 0;
-        res_gr = nv3_get_param(res_info, state,  &ainfo);
-        res_info->valid = ainfo.converged;
-    }
-}
-static void nv3UpdateArbitrationSettings
-(
-    unsigned      VClk, 
-    unsigned      pixelDepth, 
-    unsigned     *burst,
-    unsigned     *lwm,
-    RIVA_HW_INST *chip
-)
-{
-    nv3_fifo_info fifo_data;
-    nv3_sim_state sim_data;
-    unsigned int M, N, P, pll, MClk;
-    
-    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
-    M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
-    MClk = (N * chip->CrystalFreqKHz / M) >> P;
-    sim_data.pix_bpp        = (char)pixelDepth;
-    sim_data.enable_video   = 0;
-    sim_data.enable_mp      = 0;
-    sim_data.video_scale    = 1;
-    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
-	128 : 64;
-    sim_data.memory_width   = 128;
-
-    sim_data.mem_latency    = 9;
-    sim_data.mem_aligned    = 1;
-    sim_data.mem_page_miss  = 11;
-    sim_data.gr_during_vid  = 0;
-    sim_data.pclk_khz       = VClk;
-    sim_data.mclk_khz       = MClk;
-    nv3CalcArbitration(&fifo_data, &sim_data);
-    if (fifo_data.valid)
-    {
-        int  b = fifo_data.graphics_burst_size >> 4;
-        *burst = 0;
-        while (b >>= 1)
-	    (*burst)++;
-        *lwm   = fifo_data.graphics_lwm >> 3;
-    }
-    else
-    {
-        *lwm   = 0x24;
-        *burst = 0x2;
-    }
-}
-static void nv4CalcArbitration 
-(
-    nv4_fifo_info *fifo,
-    nv4_sim_state *arb
-)
-{
-    int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
-    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
-    int found, mclk_extra, mclk_loop, cbs, m1, p1;
-    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
-    int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
-    int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
-    int craw, vraw;
-
-    fifo->valid = 1;
-    pclk_freq = arb->pclk_khz;
-    mclk_freq = arb->mclk_khz;
-    nvclk_freq = arb->nvclk_khz;
-    pagemiss = arb->mem_page_miss;
-    cas = arb->mem_latency;
-    width = arb->memory_width >> 6;
-    video_enable = arb->enable_video;
-    color_key_enable = arb->gr_during_vid;
-    bpp = arb->pix_bpp;
-    align = arb->mem_aligned;
-    mp_enable = arb->enable_mp;
-    clwm = 0;
-    vlwm = 0;
-    cbs = 128;
-    pclks = 2;
-    nvclks = 2;
-    nvclks += 2;
-    nvclks += 1;
-    mclks = 5;
-    mclks += 3;
-    mclks += 1;
-    mclks += cas;
-    mclks += 1;
-    mclks += 1;
-    mclks += 1;
-    mclks += 1;
-    mclk_extra = 3;
-    nvclks += 2;
-    nvclks += 1;
-    nvclks += 1;
-    nvclks += 1;
-    if (mp_enable)
-        mclks+=4;
-    nvclks += 0;
-    pclks += 0;
-    found = 0;
-    vbs = 0;
-    while (found != 1)
-    {
-        fifo->valid = 1;
-        found = 1;
-        mclk_loop = mclks+mclk_extra;
-        us_m = mclk_loop *1000*1000 / mclk_freq;
-        us_n = nvclks*1000*1000 / nvclk_freq;
-        us_p = nvclks*1000*1000 / pclk_freq;
-        if (video_enable)
-        {
-            video_drain_rate = pclk_freq * 2;
-            crtc_drain_rate = pclk_freq * bpp/8;
-            vpagemiss = 2;
-            vpagemiss += 1;
-            crtpagemiss = 2;
-            vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
-            if (nvclk_freq * 2 > mclk_freq * width)
-                video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
-            else
-                video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
-            us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
-            vlwm = us_video * video_drain_rate/(1000*1000);
-            vlwm++;
-            vbs = 128;
-            if (vlwm > 128) vbs = 64;
-            if (vlwm > (256-64)) vbs = 32;
-            if (nvclk_freq * 2 > mclk_freq * width)
-                video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
-            else
-                video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
-            cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
-            us_crt =
-            us_video
-            +video_fill_us
-            +cpm_us
-            +us_m + us_n +us_p
-            ;
-            clwm = us_crt * crtc_drain_rate/(1000*1000);
-            clwm++;
-        }
-        else
-        {
-            crtc_drain_rate = pclk_freq * bpp/8;
-            crtpagemiss = 2;
-            crtpagemiss += 1;
-            cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
-            us_crt =  cpm_us + us_m + us_n + us_p ;
-            clwm = us_crt * crtc_drain_rate/(1000*1000);
-            clwm++;
-        }
-        m1 = clwm + cbs - 512;
-        p1 = m1 * pclk_freq / mclk_freq;
-        p1 = p1 * bpp / 8;
-        if ((p1 < m1) && (m1 > 0))
-        {
-            fifo->valid = 0;
-            found = 0;
-            if (mclk_extra ==0)   found = 1;
-            mclk_extra--;
-        }
-        else if (video_enable)
-        {
-            if ((clwm > 511) || (vlwm > 255))
-            {
-                fifo->valid = 0;
-                found = 0;
-                if (mclk_extra ==0)   found = 1;
-                mclk_extra--;
-            }
-        }
-        else
-        {
-            if (clwm > 519)
-            {
-                fifo->valid = 0;
-                found = 0;
-                if (mclk_extra ==0)   found = 1;
-                mclk_extra--;
-            }
-        }
-        craw = clwm;
-        vraw = vlwm;
-        if (clwm < 384) clwm = 384;
-        if (vlwm < 128) vlwm = 128;
-        data = (int)(clwm);
-        fifo->graphics_lwm = data;
-        fifo->graphics_burst_size = 128;
-        data = (int)((vlwm+15));
-        fifo->video_lwm = data;
-        fifo->video_burst_size = vbs;
-    }
-}
-static void nv4UpdateArbitrationSettings
-(
-    unsigned      VClk, 
-    unsigned      pixelDepth, 
-    unsigned     *burst,
-    unsigned     *lwm,
-    RIVA_HW_INST *chip
-)
-{
-    nv4_fifo_info fifo_data;
-    nv4_sim_state sim_data;
-    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
-
-    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
-    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
-    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
-    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
-    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
-    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
-    cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
-    sim_data.pix_bpp        = (char)pixelDepth;
-    sim_data.enable_video   = 0;
-    sim_data.enable_mp      = 0;
-    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
-	128 : 64;
-    sim_data.mem_latency    = (char)cfg1 & 0x0F;
-    sim_data.mem_aligned    = 1;
-    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
-    sim_data.gr_during_vid  = 0;
-    sim_data.pclk_khz       = VClk;
-    sim_data.mclk_khz       = MClk;
-    sim_data.nvclk_khz      = NVClk;
-    nv4CalcArbitration(&fifo_data, &sim_data);
-    if (fifo_data.valid)
-    {
-        int  b = fifo_data.graphics_burst_size >> 4;
-        *burst = 0;
-        while (b >>= 1)
-	    (*burst)++;
-        *lwm   = fifo_data.graphics_lwm >> 3;
-    }
-}
-static void nv10CalcArbitration 
-(
-    nv10_fifo_info *fifo,
-    nv10_sim_state *arb
-)
-{
-    int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
-    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
-    int nvclk_fill, us_extra;
-    int found, mclk_extra, mclk_loop, cbs, m1;
-    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
-    int us_m, us_m_min, us_n, us_p, video_drain_rate, crtc_drain_rate;
-    int vus_m, vus_n, vus_p;
-    int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm;
-    int clwm_rnd_down;
-    int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2;
-    int pclks_2_top_fifo, min_mclk_extra;
-    int us_min_mclk_extra;
-
-    fifo->valid = 1;
-    pclk_freq = arb->pclk_khz; /* freq in KHz */
-    mclk_freq = arb->mclk_khz;
-    nvclk_freq = arb->nvclk_khz;
-    pagemiss = arb->mem_page_miss;
-    cas = arb->mem_latency;
-    width = arb->memory_width/64;
-    video_enable = arb->enable_video;
-    color_key_enable = arb->gr_during_vid;
-    bpp = arb->pix_bpp;
-    align = arb->mem_aligned;
-    mp_enable = arb->enable_mp;
-    clwm = 0;
-    vlwm = 1024;
-
-    cbs = 512;
-    vbs = 512;
-
-    pclks = 4; /* lwm detect. */
-
-    nvclks = 3; /* lwm -> sync. */
-    nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
-
-    mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
-
-    mclks += 1;   /* arb_hp_req */
-    mclks += 5;   /* ap_hp_req   tiling pipeline */
-
-    mclks += 2;    /* tc_req     latency fifo */
-    mclks += 2;    /* fb_cas_n_  memory request to fbio block */
-    mclks += 7;    /* sm_d_rdv   data returned from fbio block */
-
-    /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
-    if (arb->memory_type == 0)
-      if (arb->memory_width == 64) /* 64 bit bus */
-        mclks += 4;
-      else
-        mclks += 2;
-    else
-      if (arb->memory_width == 64) /* 64 bit bus */
-        mclks += 2;
-      else
-        mclks += 1;
-
-    if ((!video_enable) && (arb->memory_width == 128))
-    {  
-      mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
-      min_mclk_extra = 17;
-    }
-    else
-    {
-      mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
-      /* mclk_extra = 4; */ /* Margin of error */
-      min_mclk_extra = 18;
-    }
-
-    nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
-    nvclks += 1; /* fbi_d_rdv_n */
-    nvclks += 1; /* Fbi_d_rdata */
-    nvclks += 1; /* crtfifo load */
-
-    if(mp_enable)
-      mclks+=4; /* Mp can get in with a burst of 8. */
-    /* Extra clocks determined by heuristics */
-
-    nvclks += 0;
-    pclks += 0;
-    found = 0;
-    while(found != 1) {
-      fifo->valid = 1;
-      found = 1;
-      mclk_loop = mclks+mclk_extra;
-      us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
-      us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
-      us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
-      us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
-      us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
-      us_pipe = us_m + us_n + us_p;
-      us_pipe_min = us_m_min + us_n + us_p;
-      us_extra = 0;
-
-      vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
-      vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */
-      vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */
-      vus_pipe = vus_m + vus_n + vus_p;
-
-      if(video_enable) {
-        video_drain_rate = pclk_freq * 4; /* MB/s */
-        crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
-
-        vpagemiss = 1; /* self generating page miss */
-        vpagemiss += 1; /* One higher priority before */
-
-        crtpagemiss = 2; /* self generating page miss */
-        if(mp_enable)
-            crtpagemiss += 1; /* if MA0 conflict */
-
-        vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
-
-        us_video = vpm_us + vus_m; /* Video has separate read return path */
-
-        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
-        us_crt =
-          us_video  /* Wait for video */
-          +cpm_us /* CRT Page miss */
-          +us_m + us_n +us_p /* other latency */
-          ;
-
-        clwm = us_crt * crtc_drain_rate/(1000*1000);
-        clwm++; /* fixed point <= float_point - 1.  Fixes that */
-      } else {
-        crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
-
-        crtpagemiss = 1; /* self generating page miss */
-        crtpagemiss += 1; /* MA0 page miss */
-        if(mp_enable)
-            crtpagemiss += 1; /* if MA0 conflict */
-        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
-        us_crt =  cpm_us + us_m + us_n + us_p ;
-        clwm = us_crt * crtc_drain_rate/(1000*1000);
-        clwm++; /* fixed point <= float_point - 1.  Fixes that */
-
-  /*
-          //
-          // Another concern, only for high pclks so don't do this
-          // with video:
-          // What happens if the latency to fetch the cbs is so large that
-          // fifo empties.  In that case we need to have an alternate clwm value
-          // based off the total burst fetch
-          //
-          us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
-          us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq;
-          clwm_mt = us_crt * crtc_drain_rate/(1000*1000);
-          clwm_mt ++;
-          if(clwm_mt > clwm)
-              clwm = clwm_mt;
-  */
-          /* Finally, a heuristic check when width == 64 bits */
-          if(width == 1){
-              nvclk_fill = nvclk_freq * 8;
-              if(crtc_drain_rate * 100 >= nvclk_fill * 102)
-                      clwm = 0xfff; /*Large number to fail */
-
-              else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
-                  clwm = 1024;
-                  cbs = 512;
-                  us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
-              }
-          }
-      }
-
-
-      /*
-        Overfill check:
-
-        */
-
-      clwm_rnd_down = ((int)clwm/8)*8;
-      if (clwm_rnd_down < clwm)
-          clwm += 8;
-
-      m1 = clwm + cbs -  1024; /* Amount of overfill */
-      m2us = us_pipe_min + us_min_mclk_extra;
-      pclks_2_top_fifo = (1024-clwm)/(8*width);
-
-      /* pclk cycles to drain */
-      p1clk = m2us * pclk_freq/(1000*1000); 
-      p2 = p1clk * bpp / 8; /* bytes drained. */
-
-      if((p2 < m1) && (m1 > 0)) {
-          fifo->valid = 0;
-          found = 0;
-          if(min_mclk_extra == 0)   {
-            if(cbs <= 32) {
-              found = 1; /* Can't adjust anymore! */
-            } else {
-              cbs = cbs/2;  /* reduce the burst size */
-            }
-          } else {
-            min_mclk_extra--;
-          }
-      } else {
-        if (clwm > 1023){ /* Have some margin */
-          fifo->valid = 0;
-          found = 0;
-          if(min_mclk_extra == 0)   
-              found = 1; /* Can't adjust anymore! */
-          else 
-              min_mclk_extra--;
-        }
-      }
-      craw = clwm;
-
-      if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
-      data = (int)(clwm);
-      /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
-      fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
-
-      /*  printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */
-      fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
-    }
-}
-static void nv10UpdateArbitrationSettings
-(
-    unsigned      VClk, 
-    unsigned      pixelDepth, 
-    unsigned     *burst,
-    unsigned     *lwm,
-    RIVA_HW_INST *chip
-)
-{
-    nv10_fifo_info fifo_data;
-    nv10_sim_state sim_data;
-    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
-
-    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
-    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
-    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
-    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
-    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
-    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
-    cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
-    sim_data.pix_bpp        = (char)pixelDepth;
-    sim_data.enable_video   = 0;
-    sim_data.enable_mp      = 0;
-    sim_data.memory_type    = (NV_RD32(&chip->PFB[0x00000200/4], 0) & 0x01) ?
-	1 : 0;
-    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
-	128 : 64;
-    sim_data.mem_latency    = (char)cfg1 & 0x0F;
-    sim_data.mem_aligned    = 1;
-    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
-    sim_data.gr_during_vid  = 0;
-    sim_data.pclk_khz       = VClk;
-    sim_data.mclk_khz       = MClk;
-    sim_data.nvclk_khz      = NVClk;
-    nv10CalcArbitration(&fifo_data, &sim_data);
-    if (fifo_data.valid)
-    {
-        int  b = fifo_data.graphics_burst_size >> 4;
-        *burst = 0;
-        while (b >>= 1)
-	    (*burst)++;
-        *lwm   = fifo_data.graphics_lwm >> 3;
-    }
-}
-
-static void nForceUpdateArbitrationSettings
-(
-    unsigned      VClk,
-    unsigned      pixelDepth,
-    unsigned     *burst,
-    unsigned     *lwm,
-    RIVA_HW_INST *chip
-)
-{
-    nv10_fifo_info fifo_data;
-    nv10_sim_state sim_data;
-    unsigned int M, N, P, pll, MClk, NVClk;
-    unsigned int uMClkPostDiv;
-    struct pci_dev *dev;
-
-    dev = pci_get_bus_and_slot(0, 3);
-    pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
-    pci_dev_put(dev);
-    uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
-
-    if(!uMClkPostDiv) uMClkPostDiv = 4;
-    MClk = 400000 / uMClkPostDiv;
-
-    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
-    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
-    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
-    sim_data.pix_bpp        = (char)pixelDepth;
-    sim_data.enable_video   = 0;
-    sim_data.enable_mp      = 0;
-
-    dev = pci_get_bus_and_slot(0, 1);
-    pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
-    pci_dev_put(dev);
-    sim_data.memory_type    = (sim_data.memory_type >> 12) & 1;
-
-    sim_data.memory_width   = 64;
-    sim_data.mem_latency    = 3;
-    sim_data.mem_aligned    = 1;
-    sim_data.mem_page_miss  = 10;
-    sim_data.gr_during_vid  = 0;
-    sim_data.pclk_khz       = VClk;
-    sim_data.mclk_khz       = MClk;
-    sim_data.nvclk_khz      = NVClk;
-    nv10CalcArbitration(&fifo_data, &sim_data);
-    if (fifo_data.valid)
-    {
-        int  b = fifo_data.graphics_burst_size >> 4;
-        *burst = 0;
-        while (b >>= 1)
-	    (*burst)++;
-        *lwm   = fifo_data.graphics_lwm >> 3;
-    }
-}
-
-/****************************************************************************\
-*                                                                            *
-*                          RIVA Mode State Routines                          *
-*                                                                            *
-\****************************************************************************/
-
-/*
- * Calculate the Video Clock parameters for the PLL.
- */
-static int CalcVClock
-(
-    int           clockIn,
-    int          *clockOut,
-    int          *mOut,
-    int          *nOut,
-    int          *pOut,
-    RIVA_HW_INST *chip
-)
-{
-    unsigned lowM, highM, highP;
-    unsigned DeltaNew, DeltaOld;
-    unsigned VClk, Freq;
-    unsigned M, N, P;
-    
-    DeltaOld = 0xFFFFFFFF;
-
-    VClk     = (unsigned)clockIn;
-    
-    if (chip->CrystalFreqKHz == 13500)
-    {
-        lowM  = 7;
-        highM = 13 - (chip->Architecture == NV_ARCH_03);
-    }
-    else
-    {
-        lowM  = 8;
-        highM = 14 - (chip->Architecture == NV_ARCH_03);
-    }                      
-
-    highP = 4 - (chip->Architecture == NV_ARCH_03);
-    for (P = 0; P <= highP; P ++)
-    {
-        Freq = VClk << P;
-        if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz))
-        {
-            for (M = lowM; M <= highM; M++)
-            {
-                N    = (VClk << P) * M / chip->CrystalFreqKHz;
-                if(N <= 255) {
-                Freq = (chip->CrystalFreqKHz * N / M) >> P;
-                if (Freq > VClk)
-                    DeltaNew = Freq - VClk;
-                else
-                    DeltaNew = VClk - Freq;
-                if (DeltaNew < DeltaOld)
-                {
-                    *mOut     = M;
-                    *nOut     = N;
-                    *pOut     = P;
-                    *clockOut = Freq;
-                    DeltaOld  = DeltaNew;
-                }
-            }
-        }
-    }
-    }
-
-    /* non-zero: M/N/P/clock values assigned.  zero: error (not set) */
-    return (DeltaOld != 0xFFFFFFFF);
-}
-/*
- * Calculate extended mode parameters (SVGA) and save in a 
- * mode state structure.
- */
-int CalcStateExt
-(
-    RIVA_HW_INST  *chip,
-    RIVA_HW_STATE *state,
-    int            bpp,
-    int            width,
-    int            hDisplaySize,
-    int            height,
-    int            dotClock
-)
-{
-    int pixelDepth;
-    int uninitialized_var(VClk),uninitialized_var(m),
-        uninitialized_var(n),	uninitialized_var(p);
-
-    /*
-     * Save mode parameters.
-     */
-    state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
-    state->width  = width;
-    state->height = height;
-    /*
-     * Extended RIVA registers.
-     */
-    pixelDepth = (bpp + 1)/8;
-    if (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip))
-    	return -EINVAL;
-
-    switch (chip->Architecture)
-    {
-        case NV_ARCH_03:
-            nv3UpdateArbitrationSettings(VClk, 
-                                         pixelDepth * 8, 
-                                        &(state->arbitration0),
-                                        &(state->arbitration1),
-                                         chip);
-            state->cursor0  = 0x00;
-            state->cursor1  = 0x78;
-            state->cursor2  = 0x00000000;
-            state->pllsel   = 0x10010100;
-            state->config   = ((width + 31)/32)
-                            | (((pixelDepth > 2) ? 3 : pixelDepth) << 8)
-                            | 0x1000;
-            state->general  = 0x00100100;
-            state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02;
-            break;
-        case NV_ARCH_04:
-            nv4UpdateArbitrationSettings(VClk, 
-                                         pixelDepth * 8, 
-                                        &(state->arbitration0),
-                                        &(state->arbitration1),
-                                         chip);
-            state->cursor0  = 0x00;
-            state->cursor1  = 0xFC;
-            state->cursor2  = 0x00000000;
-            state->pllsel   = 0x10000700;
-            state->config   = 0x00001114;
-            state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
-            state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
-            break;
-        case NV_ARCH_10:
-        case NV_ARCH_20:
-        case NV_ARCH_30:
-            if((chip->Chipset == NV_CHIP_IGEFORCE2) ||
-               (chip->Chipset == NV_CHIP_0x01F0))
-            {
-                nForceUpdateArbitrationSettings(VClk,
-                                          pixelDepth * 8,
-                                         &(state->arbitration0),
-                                         &(state->arbitration1),
-                                          chip);
-            } else {
-                nv10UpdateArbitrationSettings(VClk, 
-                                          pixelDepth * 8, 
-                                         &(state->arbitration0),
-                                         &(state->arbitration1),
-                                          chip);
-            }
-            state->cursor0  = 0x80 | (chip->CursorStart >> 17);
-            state->cursor1  = (chip->CursorStart >> 11) << 2;
-            state->cursor2  = chip->CursorStart >> 24;
-            state->pllsel   = 0x10000700;
-            state->config   = NV_RD32(&chip->PFB[0x00000200/4], 0);
-            state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
-            state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
-            break;
-    }
-
-     /* Paul Richards: below if block borks things in kernel for some reason */
-     /* Tony: Below is needed to set hardware in DirectColor */
-    if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
-	    state->general |= 0x00000030;
-
-    state->vpll     = (p << 16) | (n << 8) | m;
-    state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
-    state->pixel    = pixelDepth > 2   ? 3    : pixelDepth;
-    state->offset0  =
-    state->offset1  =
-    state->offset2  =
-    state->offset3  = 0;
-    state->pitch0   =
-    state->pitch1   =
-    state->pitch2   =
-    state->pitch3   = pixelDepth * width;
-
-    return 0;
-}
-/*
- * Load fixed function state and pre-calculated/stored state.
- */
-#if 0
-#define LOAD_FIXED_STATE(tbl,dev)                                       \
-    for (i = 0; i < sizeof(tbl##Table##dev)/8; i++)                 \
-        chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1]
-#define LOAD_FIXED_STATE_8BPP(tbl,dev)                                  \
-    for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++)            \
-        chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1]
-#define LOAD_FIXED_STATE_15BPP(tbl,dev)                                 \
-    for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++)           \
-        chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1]
-#define LOAD_FIXED_STATE_16BPP(tbl,dev)                                 \
-    for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++)           \
-        chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1]
-#define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
-    for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
-        chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
-#endif
-
-#define LOAD_FIXED_STATE(tbl,dev)                                       \
-    for (i = 0; i < sizeof(tbl##Table##dev)/8; i++)                 \
-        NV_WR32(&chip->dev[tbl##Table##dev[i][0]], 0, tbl##Table##dev[i][1])
-#define LOAD_FIXED_STATE_8BPP(tbl,dev)                                  \
-    for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++)            \
-        NV_WR32(&chip->dev[tbl##Table##dev##_8BPP[i][0]], 0, tbl##Table##dev##_8BPP[i][1])
-#define LOAD_FIXED_STATE_15BPP(tbl,dev)                                 \
-    for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++)           \
-        NV_WR32(&chip->dev[tbl##Table##dev##_15BPP[i][0]], 0, tbl##Table##dev##_15BPP[i][1])
-#define LOAD_FIXED_STATE_16BPP(tbl,dev)                                 \
-    for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++)           \
-        NV_WR32(&chip->dev[tbl##Table##dev##_16BPP[i][0]], 0, tbl##Table##dev##_16BPP[i][1])
-#define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
-    for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
-        NV_WR32(&chip->dev[tbl##Table##dev##_32BPP[i][0]], 0, tbl##Table##dev##_32BPP[i][1])
-
-static void UpdateFifoState
-(
-    RIVA_HW_INST  *chip
-)
-{
-    int i;
-
-    switch (chip->Architecture)
-    {
-        case NV_ARCH_04:
-            LOAD_FIXED_STATE(nv4,FIFO);
-            chip->Tri03 = NULL;
-            chip->Tri05 = (RivaTexturedTriangle05 __iomem *)&(chip->FIFO[0x0000E000/4]);
-            break;
-        case NV_ARCH_10:
-        case NV_ARCH_20:
-        case NV_ARCH_30:
-            /*
-             * Initialize state for the RivaTriangle3D05 routines.
-             */
-            LOAD_FIXED_STATE(nv10tri05,PGRAPH);
-            LOAD_FIXED_STATE(nv10,FIFO);
-            chip->Tri03 = NULL;
-            chip->Tri05 = (RivaTexturedTriangle05 __iomem *)&(chip->FIFO[0x0000E000/4]);
-            break;
-    }
-}
-static void LoadStateExt
-(
-    RIVA_HW_INST  *chip,
-    RIVA_HW_STATE *state
-)
-{
-    int i;
-
-    /*
-     * Load HW fixed function state.
-     */
-    LOAD_FIXED_STATE(Riva,PMC);
-    LOAD_FIXED_STATE(Riva,PTIMER);
-    switch (chip->Architecture)
-    {
-        case NV_ARCH_03:
-            /*
-             * Make sure frame buffer config gets set before loading PRAMIN.
-             */
-            NV_WR32(chip->PFB, 0x00000200, state->config);
-            LOAD_FIXED_STATE(nv3,PFIFO);
-            LOAD_FIXED_STATE(nv3,PRAMIN);
-            LOAD_FIXED_STATE(nv3,PGRAPH);
-            switch (state->bpp)
-            {
-                case 15:
-                case 16:
-                    LOAD_FIXED_STATE_15BPP(nv3,PRAMIN);
-                    LOAD_FIXED_STATE_15BPP(nv3,PGRAPH);
-                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
-                    break;
-                case 24:
-                case 32:
-                    LOAD_FIXED_STATE_32BPP(nv3,PRAMIN);
-                    LOAD_FIXED_STATE_32BPP(nv3,PGRAPH);
-                    chip->Tri03 = NULL;
-                    break;
-                case 8:
-                default:
-                    LOAD_FIXED_STATE_8BPP(nv3,PRAMIN);
-                    LOAD_FIXED_STATE_8BPP(nv3,PGRAPH);
-                    chip->Tri03 = NULL;
-                    break;
-            }
-            for (i = 0x00000; i < 0x00800; i++)
-                NV_WR32(&chip->PRAMIN[0x00000502 + i], 0, (i << 12) | 0x03);
-            NV_WR32(chip->PGRAPH, 0x00000630, state->offset0);
-            NV_WR32(chip->PGRAPH, 0x00000634, state->offset1);
-            NV_WR32(chip->PGRAPH, 0x00000638, state->offset2);
-            NV_WR32(chip->PGRAPH, 0x0000063C, state->offset3);
-            NV_WR32(chip->PGRAPH, 0x00000650, state->pitch0);
-            NV_WR32(chip->PGRAPH, 0x00000654, state->pitch1);
-            NV_WR32(chip->PGRAPH, 0x00000658, state->pitch2);
-            NV_WR32(chip->PGRAPH, 0x0000065C, state->pitch3);
-            break;
-        case NV_ARCH_04:
-            /*
-             * Make sure frame buffer config gets set before loading PRAMIN.
-             */
-            NV_WR32(chip->PFB, 0x00000200, state->config);
-            LOAD_FIXED_STATE(nv4,PFIFO);
-            LOAD_FIXED_STATE(nv4,PRAMIN);
-            LOAD_FIXED_STATE(nv4,PGRAPH);
-            switch (state->bpp)
-            {
-                case 15:
-                    LOAD_FIXED_STATE_15BPP(nv4,PRAMIN);
-                    LOAD_FIXED_STATE_15BPP(nv4,PGRAPH);
-                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
-                    break;
-                case 16:
-                    LOAD_FIXED_STATE_16BPP(nv4,PRAMIN);
-                    LOAD_FIXED_STATE_16BPP(nv4,PGRAPH);
-                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
-                    break;
-                case 24:
-                case 32:
-                    LOAD_FIXED_STATE_32BPP(nv4,PRAMIN);
-                    LOAD_FIXED_STATE_32BPP(nv4,PGRAPH);
-                    chip->Tri03 = NULL;
-                    break;
-                case 8:
-                default:
-                    LOAD_FIXED_STATE_8BPP(nv4,PRAMIN);
-                    LOAD_FIXED_STATE_8BPP(nv4,PGRAPH);
-                    chip->Tri03 = NULL;
-                    break;
-            }
-            NV_WR32(chip->PGRAPH, 0x00000640, state->offset0);
-            NV_WR32(chip->PGRAPH, 0x00000644, state->offset1);
-            NV_WR32(chip->PGRAPH, 0x00000648, state->offset2);
-            NV_WR32(chip->PGRAPH, 0x0000064C, state->offset3);
-            NV_WR32(chip->PGRAPH, 0x00000670, state->pitch0);
-            NV_WR32(chip->PGRAPH, 0x00000674, state->pitch1);
-            NV_WR32(chip->PGRAPH, 0x00000678, state->pitch2);
-            NV_WR32(chip->PGRAPH, 0x0000067C, state->pitch3);
-            break;
-        case NV_ARCH_10:
-        case NV_ARCH_20:
-        case NV_ARCH_30:
-            if(chip->twoHeads) {
-               VGA_WR08(chip->PCIO, 0x03D4, 0x44);
-               VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner);
-               chip->LockUnlock(chip, 0);
-            }
-
-            LOAD_FIXED_STATE(nv10,PFIFO);
-            LOAD_FIXED_STATE(nv10,PRAMIN);
-            LOAD_FIXED_STATE(nv10,PGRAPH);
-            switch (state->bpp)
-            {
-                case 15:
-                    LOAD_FIXED_STATE_15BPP(nv10,PRAMIN);
-                    LOAD_FIXED_STATE_15BPP(nv10,PGRAPH);
-                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
-                    break;
-                case 16:
-                    LOAD_FIXED_STATE_16BPP(nv10,PRAMIN);
-                    LOAD_FIXED_STATE_16BPP(nv10,PGRAPH);
-                    chip->Tri03 = (RivaTexturedTriangle03  __iomem *)&(chip->FIFO[0x0000E000/4]);
-                    break;
-                case 24:
-                case 32:
-                    LOAD_FIXED_STATE_32BPP(nv10,PRAMIN);
-                    LOAD_FIXED_STATE_32BPP(nv10,PGRAPH);
-                    chip->Tri03 = NULL;
-                    break;
-                case 8:
-                default:
-                    LOAD_FIXED_STATE_8BPP(nv10,PRAMIN);
-                    LOAD_FIXED_STATE_8BPP(nv10,PGRAPH);
-                    chip->Tri03 = NULL;
-                    break;
-            }
-
-            if(chip->Architecture == NV_ARCH_10) {
-                NV_WR32(chip->PGRAPH, 0x00000640, state->offset0);
-                NV_WR32(chip->PGRAPH, 0x00000644, state->offset1);
-                NV_WR32(chip->PGRAPH, 0x00000648, state->offset2);
-                NV_WR32(chip->PGRAPH, 0x0000064C, state->offset3);
-                NV_WR32(chip->PGRAPH, 0x00000670, state->pitch0);
-                NV_WR32(chip->PGRAPH, 0x00000674, state->pitch1);
-                NV_WR32(chip->PGRAPH, 0x00000678, state->pitch2);
-                NV_WR32(chip->PGRAPH, 0x0000067C, state->pitch3);
-                NV_WR32(chip->PGRAPH, 0x00000680, state->pitch3);
-        } else {
-        NV_WR32(chip->PGRAPH, 0x00000820, state->offset0);
-        NV_WR32(chip->PGRAPH, 0x00000824, state->offset1);
-        NV_WR32(chip->PGRAPH, 0x00000828, state->offset2);
-        NV_WR32(chip->PGRAPH, 0x0000082C, state->offset3);
-        NV_WR32(chip->PGRAPH, 0x00000850, state->pitch0);
-        NV_WR32(chip->PGRAPH, 0x00000854, state->pitch1);
-        NV_WR32(chip->PGRAPH, 0x00000858, state->pitch2);
-        NV_WR32(chip->PGRAPH, 0x0000085C, state->pitch3);
-        NV_WR32(chip->PGRAPH, 0x00000860, state->pitch3);
-        NV_WR32(chip->PGRAPH, 0x00000864, state->pitch3);
-        NV_WR32(chip->PGRAPH, 0x000009A4, NV_RD32(chip->PFB, 0x00000200));
-        NV_WR32(chip->PGRAPH, 0x000009A8, NV_RD32(chip->PFB, 0x00000204));
-        }
-            if(chip->twoHeads) {
-               NV_WR32(chip->PCRTC0, 0x00000860, state->head);
-               NV_WR32(chip->PCRTC0, 0x00002860, state->head2);
-            }
-            NV_WR32(chip->PRAMDAC, 0x00000404, NV_RD32(chip->PRAMDAC, 0x00000404) | (1 << 25));
-
-            NV_WR32(chip->PMC, 0x00008704, 1);
-            NV_WR32(chip->PMC, 0x00008140, 0);
-            NV_WR32(chip->PMC, 0x00008920, 0);
-            NV_WR32(chip->PMC, 0x00008924, 0);
-            NV_WR32(chip->PMC, 0x00008908, 0x01ffffff);
-            NV_WR32(chip->PMC, 0x0000890C, 0x01ffffff);
-            NV_WR32(chip->PMC, 0x00001588, 0);
-
-            NV_WR32(chip->PFB, 0x00000240, 0);
-            NV_WR32(chip->PFB, 0x00000250, 0);
-            NV_WR32(chip->PFB, 0x00000260, 0);
-            NV_WR32(chip->PFB, 0x00000270, 0);
-            NV_WR32(chip->PFB, 0x00000280, 0);
-            NV_WR32(chip->PFB, 0x00000290, 0);
-            NV_WR32(chip->PFB, 0x000002A0, 0);
-            NV_WR32(chip->PFB, 0x000002B0, 0);
-
-            NV_WR32(chip->PGRAPH, 0x00000B00, NV_RD32(chip->PFB, 0x00000240));
-            NV_WR32(chip->PGRAPH, 0x00000B04, NV_RD32(chip->PFB, 0x00000244));
-            NV_WR32(chip->PGRAPH, 0x00000B08, NV_RD32(chip->PFB, 0x00000248));
-            NV_WR32(chip->PGRAPH, 0x00000B0C, NV_RD32(chip->PFB, 0x0000024C));
-            NV_WR32(chip->PGRAPH, 0x00000B10, NV_RD32(chip->PFB, 0x00000250));
-            NV_WR32(chip->PGRAPH, 0x00000B14, NV_RD32(chip->PFB, 0x00000254));
-            NV_WR32(chip->PGRAPH, 0x00000B18, NV_RD32(chip->PFB, 0x00000258));
-            NV_WR32(chip->PGRAPH, 0x00000B1C, NV_RD32(chip->PFB, 0x0000025C));
-            NV_WR32(chip->PGRAPH, 0x00000B20, NV_RD32(chip->PFB, 0x00000260));
-            NV_WR32(chip->PGRAPH, 0x00000B24, NV_RD32(chip->PFB, 0x00000264));
-            NV_WR32(chip->PGRAPH, 0x00000B28, NV_RD32(chip->PFB, 0x00000268));
-            NV_WR32(chip->PGRAPH, 0x00000B2C, NV_RD32(chip->PFB, 0x0000026C));
-            NV_WR32(chip->PGRAPH, 0x00000B30, NV_RD32(chip->PFB, 0x00000270));
-            NV_WR32(chip->PGRAPH, 0x00000B34, NV_RD32(chip->PFB, 0x00000274));
-            NV_WR32(chip->PGRAPH, 0x00000B38, NV_RD32(chip->PFB, 0x00000278));
-            NV_WR32(chip->PGRAPH, 0x00000B3C, NV_RD32(chip->PFB, 0x0000027C));
-            NV_WR32(chip->PGRAPH, 0x00000B40, NV_RD32(chip->PFB, 0x00000280));
-            NV_WR32(chip->PGRAPH, 0x00000B44, NV_RD32(chip->PFB, 0x00000284));
-            NV_WR32(chip->PGRAPH, 0x00000B48, NV_RD32(chip->PFB, 0x00000288));
-            NV_WR32(chip->PGRAPH, 0x00000B4C, NV_RD32(chip->PFB, 0x0000028C));
-            NV_WR32(chip->PGRAPH, 0x00000B50, NV_RD32(chip->PFB, 0x00000290));
-            NV_WR32(chip->PGRAPH, 0x00000B54, NV_RD32(chip->PFB, 0x00000294));
-            NV_WR32(chip->PGRAPH, 0x00000B58, NV_RD32(chip->PFB, 0x00000298));
-            NV_WR32(chip->PGRAPH, 0x00000B5C, NV_RD32(chip->PFB, 0x0000029C));
-            NV_WR32(chip->PGRAPH, 0x00000B60, NV_RD32(chip->PFB, 0x000002A0));
-            NV_WR32(chip->PGRAPH, 0x00000B64, NV_RD32(chip->PFB, 0x000002A4));
-            NV_WR32(chip->PGRAPH, 0x00000B68, NV_RD32(chip->PFB, 0x000002A8));
-            NV_WR32(chip->PGRAPH, 0x00000B6C, NV_RD32(chip->PFB, 0x000002AC));
-            NV_WR32(chip->PGRAPH, 0x00000B70, NV_RD32(chip->PFB, 0x000002B0));
-            NV_WR32(chip->PGRAPH, 0x00000B74, NV_RD32(chip->PFB, 0x000002B4));
-            NV_WR32(chip->PGRAPH, 0x00000B78, NV_RD32(chip->PFB, 0x000002B8));
-            NV_WR32(chip->PGRAPH, 0x00000B7C, NV_RD32(chip->PFB, 0x000002BC));
-            NV_WR32(chip->PGRAPH, 0x00000F40, 0x10000000);
-            NV_WR32(chip->PGRAPH, 0x00000F44, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
-            NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000008);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000200);
-            for (i = 0; i < (3*16); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
-            NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000800);
-            for (i = 0; i < (16*16); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F40, 0x30000000);
-            NV_WR32(chip->PGRAPH, 0x00000F44, 0x00000004);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006400);
-            for (i = 0; i < (59*4); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006800);
-            for (i = 0; i < (47*4); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006C00);
-            for (i = 0; i < (3*4); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007000);
-            for (i = 0; i < (19*4); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007400);
-            for (i = 0; i < (12*4); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007800);
-            for (i = 0; i < (12*4); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00004400);
-            for (i = 0; i < (8*4); i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000000);
-            for (i = 0; i < 16; i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-            NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
-            for (i = 0; i < 4; i++)
-                NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
-
-            NV_WR32(chip->PCRTC, 0x00000810, state->cursorConfig);
-
-            if(chip->flatPanel) {
-               if((chip->Chipset & 0x0ff0) == 0x0110) {
-                   NV_WR32(chip->PRAMDAC, 0x0528, state->dither);
-               } else 
-               if((chip->Chipset & 0x0ff0) >= 0x0170) {
-                   NV_WR32(chip->PRAMDAC, 0x083C, state->dither);
-               }
-            
-               VGA_WR08(chip->PCIO, 0x03D4, 0x53);
-               VGA_WR08(chip->PCIO, 0x03D5, 0);
-               VGA_WR08(chip->PCIO, 0x03D4, 0x54);
-               VGA_WR08(chip->PCIO, 0x03D5, 0);
-               VGA_WR08(chip->PCIO, 0x03D4, 0x21);
-               VGA_WR08(chip->PCIO, 0x03D5, 0xfa);
-            }
-
-            VGA_WR08(chip->PCIO, 0x03D4, 0x41);
-            VGA_WR08(chip->PCIO, 0x03D5, state->extra);
-    }
-    LOAD_FIXED_STATE(Riva,FIFO);
-    UpdateFifoState(chip);
-    /*
-     * Load HW mode state.
-     */
-    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
-    VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
-    VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
-    VGA_WR08(chip->PCIO, 0x03D5, state->screen);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
-    VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
-    VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
-    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
-    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
-    VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
-    VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
-    VGA_WR08(chip->PCIO, 0x03D5, state->cursor2);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x39);
-    VGA_WR08(chip->PCIO, 0x03D5, state->interlace);
-
-    if(!chip->flatPanel) {
-       NV_WR32(chip->PRAMDAC0, 0x00000508, state->vpll);
-       NV_WR32(chip->PRAMDAC0, 0x0000050C, state->pllsel);
-       if(chip->twoHeads)
-          NV_WR32(chip->PRAMDAC0, 0x00000520, state->vpll2);
-    }  else {
-       NV_WR32(chip->PRAMDAC, 0x00000848 , state->scale);
-    }  
-    NV_WR32(chip->PRAMDAC, 0x00000600 , state->general);
-
-    /*
-     * Turn off VBlank enable and reset.
-     */
-    NV_WR32(chip->PCRTC, 0x00000140, 0);
-    NV_WR32(chip->PCRTC, 0x00000100, chip->VBlankBit);
-    /*
-     * Set interrupt enable.
-     */    
-    NV_WR32(chip->PMC, 0x00000140, chip->EnableIRQ & 0x01);
-    /*
-     * Set current state pointer.
-     */
-    chip->CurrentState = state;
-    /*
-     * Reset FIFO free and empty counts.
-     */
-    chip->FifoFreeCount  = 0;
-    /* Free count from first subchannel */
-    chip->FifoEmptyCount = NV_RD32(&chip->Rop->FifoFree, 0);
-}
-static void UnloadStateExt
-(
-    RIVA_HW_INST  *chip,
-    RIVA_HW_STATE *state
-)
-{
-    /*
-     * Save current HW state.
-     */
-    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
-    state->repaint0     = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
-    state->repaint1     = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
-    state->screen       = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
-    state->pixel        = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
-    state->horiz        = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
-    state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
-    state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
-    state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
-    state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
-    state->cursor2      = VGA_RD08(chip->PCIO, 0x03D5);
-    VGA_WR08(chip->PCIO, 0x03D4, 0x39);
-    state->interlace    = VGA_RD08(chip->PCIO, 0x03D5);
-    state->vpll         = NV_RD32(chip->PRAMDAC0, 0x00000508);
-    state->vpll2        = NV_RD32(chip->PRAMDAC0, 0x00000520);
-    state->pllsel       = NV_RD32(chip->PRAMDAC0, 0x0000050C);
-    state->general      = NV_RD32(chip->PRAMDAC, 0x00000600);
-    state->scale        = NV_RD32(chip->PRAMDAC, 0x00000848);
-    state->config       = NV_RD32(chip->PFB, 0x00000200);
-    switch (chip->Architecture)
-    {
-        case NV_ARCH_03:
-            state->offset0  = NV_RD32(chip->PGRAPH, 0x00000630);
-            state->offset1  = NV_RD32(chip->PGRAPH, 0x00000634);
-            state->offset2  = NV_RD32(chip->PGRAPH, 0x00000638);
-            state->offset3  = NV_RD32(chip->PGRAPH, 0x0000063C);
-            state->pitch0   = NV_RD32(chip->PGRAPH, 0x00000650);
-            state->pitch1   = NV_RD32(chip->PGRAPH, 0x00000654);
-            state->pitch2   = NV_RD32(chip->PGRAPH, 0x00000658);
-            state->pitch3   = NV_RD32(chip->PGRAPH, 0x0000065C);
-            break;
-        case NV_ARCH_04:
-            state->offset0  = NV_RD32(chip->PGRAPH, 0x00000640);
-            state->offset1  = NV_RD32(chip->PGRAPH, 0x00000644);
-            state->offset2  = NV_RD32(chip->PGRAPH, 0x00000648);
-            state->offset3  = NV_RD32(chip->PGRAPH, 0x0000064C);
-            state->pitch0   = NV_RD32(chip->PGRAPH, 0x00000670);
-            state->pitch1   = NV_RD32(chip->PGRAPH, 0x00000674);
-            state->pitch2   = NV_RD32(chip->PGRAPH, 0x00000678);
-            state->pitch3   = NV_RD32(chip->PGRAPH, 0x0000067C);
-            break;
-        case NV_ARCH_10:
-        case NV_ARCH_20:
-        case NV_ARCH_30:
-            state->offset0  = NV_RD32(chip->PGRAPH, 0x00000640);
-            state->offset1  = NV_RD32(chip->PGRAPH, 0x00000644);
-            state->offset2  = NV_RD32(chip->PGRAPH, 0x00000648);
-            state->offset3  = NV_RD32(chip->PGRAPH, 0x0000064C);
-            state->pitch0   = NV_RD32(chip->PGRAPH, 0x00000670);
-            state->pitch1   = NV_RD32(chip->PGRAPH, 0x00000674);
-            state->pitch2   = NV_RD32(chip->PGRAPH, 0x00000678);
-            state->pitch3   = NV_RD32(chip->PGRAPH, 0x0000067C);
-            if(chip->twoHeads) {
-               state->head     = NV_RD32(chip->PCRTC0, 0x00000860);
-               state->head2    = NV_RD32(chip->PCRTC0, 0x00002860);
-               VGA_WR08(chip->PCIO, 0x03D4, 0x44);
-               state->crtcOwner = VGA_RD08(chip->PCIO, 0x03D5);
-            }
-            VGA_WR08(chip->PCIO, 0x03D4, 0x41);
-            state->extra = VGA_RD08(chip->PCIO, 0x03D5);
-            state->cursorConfig = NV_RD32(chip->PCRTC, 0x00000810);
-
-            if((chip->Chipset & 0x0ff0) == 0x0110) {
-                state->dither = NV_RD32(chip->PRAMDAC, 0x0528);
-            } else 
-            if((chip->Chipset & 0x0ff0) >= 0x0170) {
-                state->dither = NV_RD32(chip->PRAMDAC, 0x083C);
-            }
-            break;
-    }
-}
-static void SetStartAddress
-(
-    RIVA_HW_INST *chip,
-    unsigned      start
-)
-{
-    NV_WR32(chip->PCRTC, 0x800, start);
-}
-
-static void SetStartAddress3
-(
-    RIVA_HW_INST *chip,
-    unsigned      start
-)
-{
-    int offset = start >> 2;
-    int pan    = (start & 3) << 1;
-    unsigned char tmp;
-
-    /*
-     * Unlock extended registers.
-     */
-    chip->LockUnlock(chip, 0);
-    /*
-     * Set start address.
-     */
-    VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
-    offset >>= 8;
-    VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
-    offset >>= 8;
-    VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
-    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
-    VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
-    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
-    /*
-     * 4 pixel pan register.
-     */
-    offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
-    VGA_WR08(chip->PCIO, 0x3C0, 0x13);
-    VGA_WR08(chip->PCIO, 0x3C0, pan);
-}
-static void nv3SetSurfaces2D
-(
-    RIVA_HW_INST *chip,
-    unsigned     surf0,
-    unsigned     surf1
-)
-{
-    RivaSurface __iomem *Surface =
-	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
-
-    RIVA_FIFO_FREE(*chip,Tri03,5);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
-    NV_WR32(&Surface->Offset, 0, surf0);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
-    NV_WR32(&Surface->Offset, 0, surf1);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000013);
-}
-static void nv4SetSurfaces2D
-(
-    RIVA_HW_INST *chip,
-    unsigned     surf0,
-    unsigned     surf1
-)
-{
-    RivaSurface __iomem *Surface =
-	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
-
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
-    NV_WR32(&Surface->Offset, 0, surf0);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
-    NV_WR32(&Surface->Offset, 0, surf1);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
-}
-static void nv10SetSurfaces2D
-(
-    RIVA_HW_INST *chip,
-    unsigned     surf0,
-    unsigned     surf1
-)
-{
-    RivaSurface __iomem *Surface =
-	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
-
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
-    NV_WR32(&Surface->Offset, 0, surf0);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
-    NV_WR32(&Surface->Offset, 0, surf1);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
-}
-static void nv3SetSurfaces3D
-(
-    RIVA_HW_INST *chip,
-    unsigned     surf0,
-    unsigned     surf1
-)
-{
-    RivaSurface __iomem *Surface =
-	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
-
-    RIVA_FIFO_FREE(*chip,Tri03,5);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000005);
-    NV_WR32(&Surface->Offset, 0, surf0);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000006);
-    NV_WR32(&Surface->Offset, 0, surf1);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000013);
-}
-static void nv4SetSurfaces3D
-(
-    RIVA_HW_INST *chip,
-    unsigned     surf0,
-    unsigned     surf1
-)
-{
-    RivaSurface __iomem *Surface =
-	(RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
-
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000005);
-    NV_WR32(&Surface->Offset, 0, surf0);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000006);
-    NV_WR32(&Surface->Offset, 0, surf1);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
-}
-static void nv10SetSurfaces3D
-(
-    RIVA_HW_INST *chip,
-    unsigned     surf0,
-    unsigned     surf1
-)
-{
-    RivaSurface3D __iomem *Surfaces3D =
-	(RivaSurface3D __iomem *)&(chip->FIFO[0x0000E000/4]);
-
-    RIVA_FIFO_FREE(*chip,Tri03,4);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000007);
-    NV_WR32(&Surfaces3D->RenderBufferOffset, 0, surf0);
-    NV_WR32(&Surfaces3D->ZBufferOffset, 0, surf1);
-    NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
-}
-
-/****************************************************************************\
-*                                                                            *
-*                      Probe RIVA Chip Configuration                         *
-*                                                                            *
-\****************************************************************************/
-
-static void nv3GetConfig
-(
-    RIVA_HW_INST *chip
-)
-{
-    /*
-     * Fill in chip configuration.
-     */
-    if (NV_RD32(&chip->PFB[0x00000000/4], 0) & 0x00000020)
-    {
-        if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
-         && ((NV_RD32(chip->PMC, 0x00000000) & 0x0F) >= 0x02))
-        {        
-            /*
-             * SDRAM 128 ZX.
-             */
-            chip->RamBandwidthKBytesPerSec = 800000;
-            switch (NV_RD32(chip->PFB, 0x00000000) & 0x03)
-            {
-                case 2:
-                    chip->RamAmountKBytes = 1024 * 4;
-                    break;
-                case 1:
-                    chip->RamAmountKBytes = 1024 * 2;
-                    break;
-                default:
-                    chip->RamAmountKBytes = 1024 * 8;
-                    break;
-            }
-        }            
-        else            
-        {
-            chip->RamBandwidthKBytesPerSec = 1000000;
-            chip->RamAmountKBytes          = 1024 * 8;
-        }            
-    }
-    else
-    {
-        /*
-         * SGRAM 128.
-         */
-        chip->RamBandwidthKBytesPerSec = 1000000;
-        switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003)
-        {
-            case 0:
-                chip->RamAmountKBytes = 1024 * 8;
-                break;
-            case 2:
-                chip->RamAmountKBytes = 1024 * 4;
-                break;
-            default:
-                chip->RamAmountKBytes = 1024 * 2;
-                break;
-        }
-    }        
-    chip->CrystalFreqKHz   = (NV_RD32(chip->PEXTDEV, 0x00000000) & 0x00000040) ? 14318 : 13500;
-    chip->CURSOR           = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
-    chip->VBlankBit        = 0x00000100;
-    chip->MaxVClockFreqKHz = 256000;
-    /*
-     * Set chip functions.
-     */
-    chip->Busy            = nv3Busy;
-    chip->ShowHideCursor  = ShowHideCursor;
-    chip->LoadStateExt    = LoadStateExt;
-    chip->UnloadStateExt  = UnloadStateExt;
-    chip->SetStartAddress = SetStartAddress3;
-    chip->SetSurfaces2D   = nv3SetSurfaces2D;
-    chip->SetSurfaces3D   = nv3SetSurfaces3D;
-    chip->LockUnlock      = nv3LockUnlock;
-}
-static void nv4GetConfig
-(
-    RIVA_HW_INST *chip
-)
-{
-    /*
-     * Fill in chip configuration.
-     */
-    if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100)
-    {
-        chip->RamAmountKBytes = ((NV_RD32(chip->PFB, 0x00000000) >> 12) & 0x0F) * 1024 * 2
-                              + 1024 * 2;
-    }
-    else
-    {
-        switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003)
-        {
-            case 0:
-                chip->RamAmountKBytes = 1024 * 32;
-                break;
-            case 1:
-                chip->RamAmountKBytes = 1024 * 4;
-                break;
-            case 2:
-                chip->RamAmountKBytes = 1024 * 8;
-                break;
-            case 3:
-            default:
-                chip->RamAmountKBytes = 1024 * 16;
-                break;
-        }
-    }
-    switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003)
-    {
-        case 3:
-            chip->RamBandwidthKBytesPerSec = 800000;
-            break;
-        default:
-            chip->RamBandwidthKBytesPerSec = 1000000;
-            break;
-    }
-    chip->CrystalFreqKHz   = (NV_RD32(chip->PEXTDEV, 0x00000000) & 0x00000040) ? 14318 : 13500;
-    chip->CURSOR           = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
-    chip->VBlankBit        = 0x00000001;
-    chip->MaxVClockFreqKHz = 350000;
-    /*
-     * Set chip functions.
-     */
-    chip->Busy            = nv4Busy;
-    chip->ShowHideCursor  = ShowHideCursor;
-    chip->LoadStateExt    = LoadStateExt;
-    chip->UnloadStateExt  = UnloadStateExt;
-    chip->SetStartAddress = SetStartAddress;
-    chip->SetSurfaces2D   = nv4SetSurfaces2D;
-    chip->SetSurfaces3D   = nv4SetSurfaces3D;
-    chip->LockUnlock      = nv4LockUnlock;
-}
-static void nv10GetConfig
-(
-    RIVA_HW_INST *chip,
-    unsigned int chipset
-)
-{
-    struct pci_dev* dev;
-    u32 amt;
-
-#ifdef __BIG_ENDIAN
-    /* turn on big endian register access */
-    if(!(NV_RD32(chip->PMC, 0x00000004) & 0x01000001))
-    	NV_WR32(chip->PMC, 0x00000004, 0x01000001);
-#endif
-
-    /*
-     * Fill in chip configuration.
-     */
-    if(chipset == NV_CHIP_IGEFORCE2) {
-        dev = pci_get_bus_and_slot(0, 1);
-        pci_read_config_dword(dev, 0x7C, &amt);
-        pci_dev_put(dev);
-        chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
-    } else if(chipset == NV_CHIP_0x01F0) {
-        dev = pci_get_bus_and_slot(0, 1);
-        pci_read_config_dword(dev, 0x84, &amt);
-        pci_dev_put(dev);
-        chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
-    } else {
-        switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & 0x000000FF)
-        {
-            case 0x02:
-                chip->RamAmountKBytes = 1024 * 2;
-                break;
-            case 0x04:
-                chip->RamAmountKBytes = 1024 * 4;
-                break;
-            case 0x08:
-                chip->RamAmountKBytes = 1024 * 8;
-                break;
-            case 0x10:
-                chip->RamAmountKBytes = 1024 * 16;
-                break;
-            case 0x20:
-                chip->RamAmountKBytes = 1024 * 32;
-                break;
-            case 0x40:
-                chip->RamAmountKBytes = 1024 * 64;
-                break;
-            case 0x80:
-                chip->RamAmountKBytes = 1024 * 128;
-                break;
-            default:
-                chip->RamAmountKBytes = 1024 * 16;
-                break;
-        }
-    }
-    switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003)
-    {
-        case 3:
-            chip->RamBandwidthKBytesPerSec = 800000;
-            break;
-        default:
-            chip->RamBandwidthKBytesPerSec = 1000000;
-            break;
-    }
-    chip->CrystalFreqKHz = (NV_RD32(chip->PEXTDEV, 0x0000) & (1 << 6)) ?
-	14318 : 13500;
-
-    switch (chipset & 0x0ff0) {
-    case 0x0170:
-    case 0x0180:
-    case 0x01F0:
-    case 0x0250:
-    case 0x0280:
-    case 0x0300:
-    case 0x0310:
-    case 0x0320:
-    case 0x0330:
-    case 0x0340:
-       if(NV_RD32(chip->PEXTDEV, 0x0000) & (1 << 22))
-           chip->CrystalFreqKHz = 27000;
-       break;
-    default:
-       break;
-    }
-
-    chip->CursorStart      = (chip->RamAmountKBytes - 128) * 1024;
-    chip->CURSOR           = NULL;  /* can't set this here */
-    chip->VBlankBit        = 0x00000001;
-    chip->MaxVClockFreqKHz = 350000;
-    /*
-     * Set chip functions.
-     */
-    chip->Busy            = nv10Busy;
-    chip->ShowHideCursor  = ShowHideCursor;
-    chip->LoadStateExt    = LoadStateExt;
-    chip->UnloadStateExt  = UnloadStateExt;
-    chip->SetStartAddress = SetStartAddress;
-    chip->SetSurfaces2D   = nv10SetSurfaces2D;
-    chip->SetSurfaces3D   = nv10SetSurfaces3D;
-    chip->LockUnlock      = nv4LockUnlock;
-
-    switch(chipset & 0x0ff0) {
-    case 0x0110:
-    case 0x0170:
-    case 0x0180:
-    case 0x01F0:
-    case 0x0250:
-    case 0x0280:
-    case 0x0300:
-    case 0x0310:
-    case 0x0320:
-    case 0x0330:
-    case 0x0340:
-        chip->twoHeads = TRUE;
-        break;
-    default:
-        chip->twoHeads = FALSE;
-        break;
-    }
-}
-int RivaGetConfig
-(
-    RIVA_HW_INST *chip,
-    unsigned int chipset
-)
-{
-    /*
-     * Save this so future SW know whats it's dealing with.
-     */
-    chip->Version = RIVA_SW_VERSION;
-    /*
-     * Chip specific configuration.
-     */
-    switch (chip->Architecture)
-    {
-        case NV_ARCH_03:
-            nv3GetConfig(chip);
-            break;
-        case NV_ARCH_04:
-            nv4GetConfig(chip);
-            break;
-        case NV_ARCH_10:
-        case NV_ARCH_20:
-        case NV_ARCH_30:
-            nv10GetConfig(chip, chipset);
-            break;
-        default:
-            return (-1);
-    }
-    chip->Chipset = chipset;
-    /*
-     * Fill in FIFO pointers.
-     */
-    chip->Rop    = (RivaRop __iomem         *)&(chip->FIFO[0x00000000/4]);
-    chip->Clip   = (RivaClip __iomem        *)&(chip->FIFO[0x00002000/4]);
-    chip->Patt   = (RivaPattern __iomem     *)&(chip->FIFO[0x00004000/4]);
-    chip->Pixmap = (RivaPixmap __iomem      *)&(chip->FIFO[0x00006000/4]);
-    chip->Blt    = (RivaScreenBlt __iomem   *)&(chip->FIFO[0x00008000/4]);
-    chip->Bitmap = (RivaBitmap __iomem      *)&(chip->FIFO[0x0000A000/4]);
-    chip->Line   = (RivaLine __iomem        *)&(chip->FIFO[0x0000C000/4]);
-    chip->Tri03  = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
-    return (0);
-}
-
diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
deleted file mode 100644
index c2769f73e0b2..000000000000
--- a/drivers/video/riva/riva_hw.h
+++ /dev/null
@@ -1,563 +0,0 @@
-/***************************************************************************\
-|*                                                                           *|
-|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
-\***************************************************************************/
-
-/*
- * GPL licensing note -- nVidia is allowing a liberal interpretation of
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived
- * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.21 2002/10/14 18:22:46 mvojkovi Exp $ */
-#ifndef __RIVA_HW_H__
-#define __RIVA_HW_H__
-#define RIVA_SW_VERSION 0x00010003
-
-#ifndef Bool
-typedef int Bool;
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-/*
- * Typedefs to force certain sized values.
- */
-typedef unsigned char  U008;
-typedef unsigned short U016;
-typedef unsigned int   U032;
-
-/*
- * HW access macros.
- */
-#include <asm/io.h>
-
-#define NV_WR08(p,i,d)  (__raw_writeb((d), (void __iomem *)(p) + (i)))
-#define NV_RD08(p,i)    (__raw_readb((void __iomem *)(p) + (i)))
-#define NV_WR16(p,i,d)  (__raw_writew((d), (void __iomem *)(p) + (i)))
-#define NV_RD16(p,i)    (__raw_readw((void __iomem *)(p) + (i)))
-#define NV_WR32(p,i,d)  (__raw_writel((d), (void __iomem *)(p) + (i)))
-#define NV_RD32(p,i)    (__raw_readl((void __iomem *)(p) + (i)))
-
-#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
-#define VGA_RD08(p,i)   (readb((void __iomem *)(p) + (i)))
-
-/*
- * Define different architectures.
- */
-#define NV_ARCH_03  0x03
-#define NV_ARCH_04  0x04
-#define NV_ARCH_10  0x10
-#define NV_ARCH_20  0x20
-#define NV_ARCH_30  0x30
-#define NV_ARCH_40  0x40
-
-/***************************************************************************\
-*                                                                           *
-*                             FIFO registers.                               *
-*                                                                           *
-\***************************************************************************/
-
-/*
- * Raster OPeration. Windows style ROP3.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BB];
-    U032 Rop3;
-} RivaRop;
-/*
- * 8X8 Monochrome pattern.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BD];
-    U032 Shape;
-    U032 reserved03[0x001];
-    U032 Color0;
-    U032 Color1;
-    U032 Monochrome[2];
-} RivaPattern;
-/*
- * Scissor clip rectangle.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BB];
-    U032 TopLeft;
-    U032 WidthHeight;
-} RivaClip;
-/*
- * 2D filled rectangle.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop[1];
-#endif
-    U032 reserved01[0x0BC];
-    U032 Color;
-    U032 reserved03[0x03E];
-    U032 TopLeft;
-    U032 WidthHeight;
-} RivaRectangle;
-/*
- * 2D screen-screen BLT.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BB];
-    U032 TopLeftSrc;
-    U032 TopLeftDst;
-    U032 WidthHeight;
-} RivaScreenBlt;
-/*
- * 2D pixel BLT.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop[1];
-#endif
-    U032 reserved01[0x0BC];
-    U032 TopLeft;
-    U032 WidthHeight;
-    U032 WidthHeightIn;
-    U032 reserved02[0x03C];
-    U032 Pixels;
-} RivaPixmap;
-/*
- * Filled rectangle combined with monochrome expand.  Useful for glyphs.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BB];
-    U032 reserved03[(0x040)-1];
-    U032 Color1A;
-    struct
-    {
-        U032 TopLeft;
-        U032 WidthHeight;
-    } UnclippedRectangle[64];
-    U032 reserved04[(0x080)-3];
-    struct
-    {
-        U032 TopLeft;
-        U032 BottomRight;
-    } ClipB;
-    U032 Color1B;
-    struct
-    {
-        U032 TopLeft;
-        U032 BottomRight;
-    } ClippedRectangle[64];
-    U032 reserved05[(0x080)-5];
-    struct
-    {
-        U032 TopLeft;
-        U032 BottomRight;
-    } ClipC;
-    U032 Color1C;
-    U032 WidthHeightC;
-    U032 PointC;
-    U032 MonochromeData1C;
-    U032 reserved06[(0x080)+121];
-    struct
-    {
-        U032 TopLeft;
-        U032 BottomRight;
-    } ClipD;
-    U032 Color1D;
-    U032 WidthHeightInD;
-    U032 WidthHeightOutD;
-    U032 PointD;
-    U032 MonochromeData1D;
-    U032 reserved07[(0x080)+120];
-    struct
-    {
-        U032 TopLeft;
-        U032 BottomRight;
-    } ClipE;
-    U032 Color0E;
-    U032 Color1E;
-    U032 WidthHeightInE;
-    U032 WidthHeightOutE;
-    U032 PointE;
-    U032 MonochromeData01E;
-} RivaBitmap;
-/*
- * 3D textured, Z buffered triangle.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BC];
-    U032 TextureOffset;
-    U032 TextureFormat;
-    U032 TextureFilter;
-    U032 FogColor;
-/* This is a problem on LynxOS */
-#ifdef Control
-#undef Control
-#endif
-    U032 Control;
-    U032 AlphaTest;
-    U032 reserved02[0x339];
-    U032 FogAndIndex;
-    U032 Color;
-    float ScreenX;
-    float ScreenY;
-    float ScreenZ;
-    float EyeM;
-    float TextureS;
-    float TextureT;
-} RivaTexturedTriangle03;
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BB];
-    U032 ColorKey;
-    U032 TextureOffset;
-    U032 TextureFormat;
-    U032 TextureFilter;
-    U032 Blend;
-/* This is a problem on LynxOS */
-#ifdef Control
-#undef Control
-#endif
-    U032 Control;
-    U032 FogColor;
-    U032 reserved02[0x39];
-    struct
-    {
-        float ScreenX;
-        float ScreenY;
-        float ScreenZ;
-        float EyeM;
-        U032 Color;
-        U032 Specular;
-        float TextureS;
-        float TextureT;
-    } Vertex[16];
-    U032 DrawTriangle3D;
-} RivaTexturedTriangle05;
-/*
- * 2D line.
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop[1];
-#endif
-    U032 reserved01[0x0BC];
-    U032 Color;             /* source color               0304-0307*/
-    U032 Reserved02[0x03e];
-    struct {                /* start aliased methods in array   0400-    */
-        U032 point0;        /* y_x S16_S16 in pixels            0-   3*/
-        U032 point1;        /* y_x S16_S16 in pixels            4-   7*/
-    } Lin[16];              /* end of aliased methods in array      -047f*/
-    struct {                /* start aliased methods in array   0480-    */
-        U032 point0X;       /* in pixels, 0 at left                0-   3*/
-        U032 point0Y;       /* in pixels, 0 at top                 4-   7*/
-        U032 point1X;       /* in pixels, 0 at left                8-   b*/
-        U032 point1Y;       /* in pixels, 0 at top                 c-   f*/
-    } Lin32[8];             /* end of aliased methods in array      -04ff*/
-    U032 PolyLin[32];       /* y_x S16_S16 in pixels         0500-057f*/
-    struct {                /* start aliased methods in array   0580-    */
-        U032 x;             /* in pixels, 0 at left                0-   3*/
-        U032 y;             /* in pixels, 0 at top                 4-   7*/
-    } PolyLin32[16];        /* end of aliased methods in array      -05ff*/
-    struct {                /* start aliased methods in array   0600-    */
-        U032 color;         /* source color                     0-   3*/
-        U032 point;         /* y_x S16_S16 in pixels            4-   7*/
-    } ColorPolyLin[16];     /* end of aliased methods in array      -067f*/
-} RivaLine;
-/*
- * 2D/3D surfaces
- */
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BE];
-    U032 Offset;
-} RivaSurface;
-typedef volatile struct
-{
-    U032 reserved00[4];
-#ifdef __BIG_ENDIAN
-    U032 FifoFree;
-#else
-    U016 FifoFree;
-    U016 Nop;
-#endif
-    U032 reserved01[0x0BD];
-    U032 Pitch;
-    U032 RenderBufferOffset;
-    U032 ZBufferOffset;
-} RivaSurface3D;
-    
-/***************************************************************************\
-*                                                                           *
-*                        Virtualized RIVA H/W interface.                    *
-*                                                                           *
-\***************************************************************************/
-
-#define FP_ENABLE  1
-#define FP_DITHER  2
-
-struct _riva_hw_inst;
-struct _riva_hw_state;
-/*
- * Virtialized chip interface. Makes RIVA 128 and TNT look alike.
- */
-typedef struct _riva_hw_inst
-{
-    /*
-     * Chip specific settings.
-     */
-    U032 Architecture;
-    U032 Version;
-    U032 Chipset;
-    U032 CrystalFreqKHz;
-    U032 RamAmountKBytes;
-    U032 MaxVClockFreqKHz;
-    U032 RamBandwidthKBytesPerSec;
-    U032 EnableIRQ;
-    U032 IO;
-    U032 VBlankBit;
-    U032 FifoFreeCount;
-    U032 FifoEmptyCount;
-    U032 CursorStart;
-    U032 flatPanel;
-    Bool twoHeads;
-    /*
-     * Non-FIFO registers.
-     */
-    volatile U032 __iomem *PCRTC0;
-    volatile U032 __iomem *PCRTC;
-    volatile U032 __iomem *PRAMDAC0;
-    volatile U032 __iomem *PFB;
-    volatile U032 __iomem *PFIFO;
-    volatile U032 __iomem *PGRAPH;
-    volatile U032 __iomem *PEXTDEV;
-    volatile U032 __iomem *PTIMER;
-    volatile U032 __iomem *PMC;
-    volatile U032 __iomem *PRAMIN;
-    volatile U032 __iomem *FIFO;
-    volatile U032 __iomem *CURSOR;
-    volatile U008 __iomem *PCIO0;
-    volatile U008 __iomem *PCIO;
-    volatile U008 __iomem *PVIO;
-    volatile U008 __iomem *PDIO0;
-    volatile U008 __iomem *PDIO;
-    volatile U032 __iomem *PRAMDAC;
-    /*
-     * Common chip functions.
-     */
-    int  (*Busy)(struct _riva_hw_inst *);
-    void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
-    void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
-    void (*SetStartAddress)(struct _riva_hw_inst *,U032);
-    void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032);
-    void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032);
-    int  (*ShowHideCursor)(struct _riva_hw_inst *,int);
-    void (*LockUnlock)(struct _riva_hw_inst *, int);
-    /*
-     * Current extended mode settings.
-     */
-    struct _riva_hw_state *CurrentState;
-    /*
-     * FIFO registers.
-     */
-    RivaRop                 __iomem *Rop;
-    RivaPattern             __iomem *Patt;
-    RivaClip                __iomem *Clip;
-    RivaPixmap              __iomem *Pixmap;
-    RivaScreenBlt           __iomem *Blt;
-    RivaBitmap              __iomem *Bitmap;
-    RivaLine                __iomem *Line;
-    RivaTexturedTriangle03  __iomem *Tri03;
-    RivaTexturedTriangle05  __iomem *Tri05;
-} RIVA_HW_INST;
-/*
- * Extended mode state information.
- */
-typedef struct _riva_hw_state
-{
-    U032 bpp;
-    U032 width;
-    U032 height;
-    U032 interlace;
-    U032 repaint0;
-    U032 repaint1;
-    U032 screen;
-    U032 scale;
-    U032 dither;
-    U032 extra;
-    U032 pixel;
-    U032 horiz;
-    U032 arbitration0;
-    U032 arbitration1;
-    U032 vpll;
-    U032 vpll2;
-    U032 pllsel;
-    U032 general;
-    U032 crtcOwner;
-    U032 head; 
-    U032 head2; 
-    U032 config;
-    U032 cursorConfig;	
-    U032 cursor0;
-    U032 cursor1;
-    U032 cursor2;
-    U032 offset0;
-    U032 offset1;
-    U032 offset2;
-    U032 offset3;
-    U032 pitch0;
-    U032 pitch1;
-    U032 pitch2;
-    U032 pitch3;
-} RIVA_HW_STATE;
-
-/*
- * function prototypes
- */
-
-extern int CalcStateExt
-(
-    RIVA_HW_INST  *chip,
-    RIVA_HW_STATE *state,
-    int            bpp,
-    int            width,
-    int            hDisplaySize,
-    int            height,
-    int            dotClock
-);
-
-/*
- * External routines.
- */
-int RivaGetConfig(RIVA_HW_INST *, unsigned int);
-/*
- * FIFO Free Count. Should attempt to yield processor if RIVA is busy.
- */
-
-#define RIVA_FIFO_FREE(hwinst,hwptr,cnt)                            \
-{                                                                   \
-    while ((hwinst).FifoFreeCount < (cnt)) {                        \
-	mb();mb();						    \
-        (hwinst).FifoFreeCount = NV_RD32(&(hwinst).hwptr->FifoFree, 0) >> 2;     \
-    }								    \
-    (hwinst).FifoFreeCount -= (cnt);                                \
-}
-#endif /* __RIVA_HW_H__ */
-
diff --git a/drivers/video/riva/riva_tbl.h b/drivers/video/riva/riva_tbl.h
deleted file mode 100644
index 7ee7d72932d4..000000000000
--- a/drivers/video/riva/riva_tbl.h
+++ /dev/null
@@ -1,1008 +0,0 @@
- /***************************************************************************\
-|*                                                                           *|
-|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
-|*     international laws.  Users and possessors of this source code are     *|
-|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
-|*     use this code in individual and commercial software.                  *|
-|*                                                                           *|
-|*     Any use of this source code must include,  in the user documenta-     *|
-|*     tion and  internal comments to the code,  notices to the end user     *|
-|*     as follows:                                                           *|
-|*                                                                           *|
-|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
-|*                                                                           *|
-|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
-|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
-|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
-|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
-|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
-|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
-|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
-|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
-|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
-|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
-|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
-|*                                                                           *|
-|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
-|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
-|*     consisting  of "commercial  computer  software"  and  "commercial     *|
-|*     computer  software  documentation,"  as such  terms  are  used in     *|
-|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
-|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
-|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
-|*     all U.S. Government End Users  acquire the source code  with only     *|
-|*     those rights set forth herein.                                        *|
-|*                                                                           *|
- \***************************************************************************/
-
-/*
- * GPL licensing note -- nVidia is allowing a liberal interpretation of
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived
- * from this source.  -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.9 2002/01/30 01:35:03 mvojkovi Exp $ */
-
-
-/*
- * RIVA Fixed Functionality Init Tables.
- */
-static unsigned RivaTablePMC[][2] =
-{
-    {0x00000050, 0x00000000},
-    {0x00000080, 0xFFFF00FF},
-    {0x00000080, 0xFFFFFFFF}
-};
-static unsigned RivaTablePTIMER[][2] =
-{
-    {0x00000080, 0x00000008},
-    {0x00000084, 0x00000003},
-    {0x00000050, 0x00000000},
-    {0x00000040, 0xFFFFFFFF}
-};
-static unsigned RivaTableFIFO[][2] =
-{
-    {0x00000000, 0x80000000},
-    {0x00000800, 0x80000001},
-    {0x00001000, 0x80000002},
-    {0x00001800, 0x80000010},
-    {0x00002000, 0x80000011},
-    {0x00002800, 0x80000012},
-    {0x00003000, 0x80000016},
-    {0x00003800, 0x80000013}
-};
-static unsigned nv3TablePFIFO[][2] =
-{
-    {0x00000140, 0x00000000},
-    {0x00000480, 0x00000000},
-    {0x00000490, 0x00000000},
-    {0x00000494, 0x00000000},
-    {0x00000481, 0x00000000},
-    {0x00000084, 0x00000000},
-    {0x00000086, 0x00002000},
-    {0x00000085, 0x00002200},
-    {0x00000484, 0x00000000},
-    {0x0000049C, 0x00000000},
-    {0x00000104, 0x00000000},
-    {0x00000108, 0x00000000},
-    {0x00000100, 0x00000000},
-    {0x000004A0, 0x00000000},
-    {0x000004A4, 0x00000000},
-    {0x000004A8, 0x00000000},
-    {0x000004AC, 0x00000000},
-    {0x000004B0, 0x00000000},
-    {0x000004B4, 0x00000000},
-    {0x000004B8, 0x00000000},
-    {0x000004BC, 0x00000000},
-    {0x00000050, 0x00000000},
-    {0x00000040, 0xFFFFFFFF},
-    {0x00000480, 0x00000001},
-    {0x00000490, 0x00000001},
-    {0x00000140, 0x00000001}
-};
-static unsigned nv3TablePGRAPH[][2] =
-{
-    {0x00000020, 0x1230001F},
-    {0x00000021, 0x10113000},
-    {0x00000022, 0x1131F101},
-    {0x00000023, 0x0100F531},
-    {0x00000060, 0x00000000},
-    {0x00000065, 0x00000000},
-    {0x00000068, 0x00000000},
-    {0x00000069, 0x00000000},
-    {0x0000006A, 0x00000000},
-    {0x0000006B, 0x00000000},
-    {0x0000006C, 0x00000000},
-    {0x0000006D, 0x00000000},
-    {0x0000006E, 0x00000000},
-    {0x0000006F, 0x00000000},
-    {0x000001A8, 0x00000000},
-    {0x00000440, 0xFFFFFFFF},
-    {0x00000480, 0x00000001},
-    {0x000001A0, 0x00000000},
-    {0x000001A2, 0x00000000},
-    {0x0000018A, 0xFFFFFFFF},
-    {0x00000190, 0x00000000},
-    {0x00000142, 0x00000000},
-    {0x00000154, 0x00000000},
-    {0x00000155, 0xFFFFFFFF},
-    {0x00000156, 0x00000000},
-    {0x00000157, 0xFFFFFFFF},
-    {0x00000064, 0x10010002},
-    {0x00000050, 0x00000000},
-    {0x00000051, 0x00000000},
-    {0x00000040, 0xFFFFFFFF},
-    {0x00000041, 0xFFFFFFFF},
-    {0x00000440, 0xFFFFFFFF},
-    {0x000001A9, 0x00000001}
-};
-static unsigned nv3TablePGRAPH_8BPP[][2] =
-{
-    {0x000001AA, 0x00001111}
-};
-static unsigned nv3TablePGRAPH_15BPP[][2] =
-{
-    {0x000001AA, 0x00002222}
-};
-static unsigned nv3TablePGRAPH_32BPP[][2] =
-{
-    {0x000001AA, 0x00003333}
-};
-static unsigned nv3TablePRAMIN[][2] =
-{
-    {0x00000500, 0x00010000},
-    {0x00000501, 0x007FFFFF},
-    {0x00000200, 0x80000000},
-    {0x00000201, 0x00C20341},
-    {0x00000204, 0x80000001},
-    {0x00000205, 0x00C50342},
-    {0x00000208, 0x80000002},
-    {0x00000209, 0x00C60343},
-    {0x0000020C, 0x80000003},
-    {0x0000020D, 0x00DC0348},
-    {0x00000210, 0x80000004},
-    {0x00000211, 0x00DC0349},
-    {0x00000214, 0x80000005},
-    {0x00000215, 0x00DC034A},
-    {0x00000218, 0x80000006},
-    {0x00000219, 0x00DC034B},
-    {0x00000240, 0x80000010},
-    {0x00000241, 0x00D10344},
-    {0x00000244, 0x80000011},
-    {0x00000245, 0x00D00345},
-    {0x00000248, 0x80000012},
-    {0x00000249, 0x00CC0346},
-    {0x0000024C, 0x80000013},
-    {0x0000024D, 0x00D70347},
-    {0x00000258, 0x80000016},
-    {0x00000259, 0x00CA034C},
-    {0x00000D05, 0x00000000},
-    {0x00000D06, 0x00000000},
-    {0x00000D07, 0x00000000},
-    {0x00000D09, 0x00000000},
-    {0x00000D0A, 0x00000000},
-    {0x00000D0B, 0x00000000},
-    {0x00000D0D, 0x00000000},
-    {0x00000D0E, 0x00000000},
-    {0x00000D0F, 0x00000000},
-    {0x00000D11, 0x00000000},
-    {0x00000D12, 0x00000000},
-    {0x00000D13, 0x00000000},
-    {0x00000D15, 0x00000000},
-    {0x00000D16, 0x00000000},
-    {0x00000D17, 0x00000000},
-    {0x00000D19, 0x00000000},
-    {0x00000D1A, 0x00000000},
-    {0x00000D1B, 0x00000000},
-    {0x00000D1D, 0x00000140},
-    {0x00000D1E, 0x00000000},
-    {0x00000D1F, 0x00000000},
-    {0x00000D20, 0x10100200},
-    {0x00000D21, 0x00000000},
-    {0x00000D22, 0x00000000},
-    {0x00000D23, 0x00000000},
-    {0x00000D24, 0x10210200},
-    {0x00000D25, 0x00000000},
-    {0x00000D26, 0x00000000},
-    {0x00000D27, 0x00000000},
-    {0x00000D28, 0x10420200},
-    {0x00000D29, 0x00000000},
-    {0x00000D2A, 0x00000000},
-    {0x00000D2B, 0x00000000},
-    {0x00000D2C, 0x10830200},
-    {0x00000D2D, 0x00000000},
-    {0x00000D2E, 0x00000000},
-    {0x00000D2F, 0x00000000},
-    {0x00000D31, 0x00000000},
-    {0x00000D32, 0x00000000},
-    {0x00000D33, 0x00000000}
-};
-static unsigned nv3TablePRAMIN_8BPP[][2] =
-{
-    /*           0xXXXXX3XX For  MSB mono format */
-    /*           0xXXXXX2XX For  LSB mono format */
-    {0x00000D04, 0x10110203},
-    {0x00000D08, 0x10110203},
-    {0x00000D0C, 0x1011020B},
-    {0x00000D10, 0x10118203},
-    {0x00000D14, 0x10110203},
-    {0x00000D18, 0x10110203},
-    {0x00000D1C, 0x10419208},
-    {0x00000D30, 0x10118203}
-};
-static unsigned nv3TablePRAMIN_15BPP[][2] =
-{
-    /*           0xXXXXX2XX For  MSB mono format */
-    /*           0xXXXXX3XX For  LSB mono format */
-    {0x00000D04, 0x10110200},
-    {0x00000D08, 0x10110200},
-    {0x00000D0C, 0x10110208},
-    {0x00000D10, 0x10118200},
-    {0x00000D14, 0x10110200},
-    {0x00000D18, 0x10110200},
-    {0x00000D1C, 0x10419208},
-    {0x00000D30, 0x10118200}
-};
-static unsigned nv3TablePRAMIN_32BPP[][2] =
-{
-    /*           0xXXXXX3XX For  MSB mono format */
-    /*           0xXXXXX2XX For  LSB mono format */
-    {0x00000D04, 0x10110201},
-    {0x00000D08, 0x10110201},
-    {0x00000D0C, 0x10110209},
-    {0x00000D10, 0x10118201},
-    {0x00000D14, 0x10110201},
-    {0x00000D18, 0x10110201},
-    {0x00000D1C, 0x10419208},
-    {0x00000D30, 0x10118201}
-};
-static unsigned nv4TableFIFO[][2] =
-{
-    {0x00003800, 0x80000014}
-};
-static unsigned nv4TablePFIFO[][2] =
-{
-    {0x00000140, 0x00000000},
-    {0x00000480, 0x00000000},
-    {0x00000494, 0x00000000},
-    {0x00000481, 0x00000000},
-    {0x0000048B, 0x00000000},
-    {0x00000400, 0x00000000},
-    {0x00000414, 0x00000000},
-    {0x00000084, 0x03000100},  
-    {0x00000085, 0x00000110},
-    {0x00000086, 0x00000112},  
-    {0x00000143, 0x0000FFFF},
-    {0x00000496, 0x0000FFFF},
-    {0x00000050, 0x00000000},
-    {0x00000040, 0xFFFFFFFF},
-    {0x00000415, 0x00000001},
-    {0x00000480, 0x00000001},
-    {0x00000494, 0x00000001},
-    {0x00000495, 0x00000001},
-    {0x00000140, 0x00000001}
-};
-static unsigned nv4TablePGRAPH[][2] =
-{
-    {0x00000020, 0x1231C001},
-    {0x00000021, 0x72111101},
-    {0x00000022, 0x11D5F071},
-    {0x00000023, 0x10D4FF31},
-    {0x00000060, 0x00000000},
-    {0x00000068, 0x00000000},
-    {0x00000070, 0x00000000},
-    {0x00000078, 0x00000000},
-    {0x00000061, 0x00000000},
-    {0x00000069, 0x00000000},
-    {0x00000071, 0x00000000},
-    {0x00000079, 0x00000000},
-    {0x00000062, 0x00000000},
-    {0x0000006A, 0x00000000},
-    {0x00000072, 0x00000000},
-    {0x0000007A, 0x00000000},
-    {0x00000063, 0x00000000},
-    {0x0000006B, 0x00000000},
-    {0x00000073, 0x00000000},
-    {0x0000007B, 0x00000000},
-    {0x00000064, 0x00000000},
-    {0x0000006C, 0x00000000},
-    {0x00000074, 0x00000000},
-    {0x0000007C, 0x00000000},
-    {0x00000065, 0x00000000},
-    {0x0000006D, 0x00000000},
-    {0x00000075, 0x00000000},
-    {0x0000007D, 0x00000000},
-    {0x00000066, 0x00000000},
-    {0x0000006E, 0x00000000},
-    {0x00000076, 0x00000000},
-    {0x0000007E, 0x00000000},
-    {0x00000067, 0x00000000},
-    {0x0000006F, 0x00000000},
-    {0x00000077, 0x00000000},
-    {0x0000007F, 0x00000000},
-    {0x00000058, 0x00000000},
-    {0x00000059, 0x00000000},
-    {0x0000005A, 0x00000000},
-    {0x0000005B, 0x00000000},
-    {0x00000196, 0x00000000},
-    {0x000001A1, 0x01FFFFFF},
-    {0x00000197, 0x00000000},
-    {0x000001A2, 0x01FFFFFF},
-    {0x00000198, 0x00000000},
-    {0x000001A3, 0x01FFFFFF},
-    {0x00000199, 0x00000000},
-    {0x000001A4, 0x01FFFFFF},
-    {0x00000050, 0x00000000},
-    {0x00000040, 0xFFFFFFFF},
-    {0x0000005C, 0x10010100},
-    {0x000001C4, 0xFFFFFFFF},
-    {0x000001C8, 0x00000001},
-    {0x00000204, 0x00000000},
-    {0x000001C3, 0x00000001}
-};
-static unsigned nv4TablePGRAPH_8BPP[][2] =
-{
-    {0x000001C9, 0x00111111},
-    {0x00000186, 0x00001010},
-    {0x0000020C, 0x03020202}
-};
-static unsigned nv4TablePGRAPH_15BPP[][2] =
-{
-    {0x000001C9, 0x00226222},
-    {0x00000186, 0x00002071},
-    {0x0000020C, 0x09080808}
-};
-static unsigned nv4TablePGRAPH_16BPP[][2] =
-{
-    {0x000001C9, 0x00556555},
-    {0x00000186, 0x000050C2},
-    {0x0000020C, 0x0C0B0B0B}
-};
-static unsigned nv4TablePGRAPH_32BPP[][2] =
-{
-    {0x000001C9, 0x0077D777},
-    {0x00000186, 0x000070E5},
-    {0x0000020C, 0x0E0D0D0D}
-};
-static unsigned nv4TablePRAMIN[][2] =
-{
-    {0x00000000, 0x80000010},
-    {0x00000001, 0x80011145},
-    {0x00000002, 0x80000011},
-    {0x00000003, 0x80011146},
-    {0x00000004, 0x80000012},
-    {0x00000005, 0x80011147},
-    {0x00000006, 0x80000013},
-    {0x00000007, 0x80011148},
-    {0x00000008, 0x80000014},
-    {0x00000009, 0x80011149},
-    {0x0000000A, 0x80000015},
-    {0x0000000B, 0x8001114A},
-    {0x0000000C, 0x80000016},
-    {0x0000000D, 0x8001114F},
-    {0x00000020, 0x80000000},
-    {0x00000021, 0x80011142},
-    {0x00000022, 0x80000001},
-    {0x00000023, 0x80011143},
-    {0x00000024, 0x80000002},
-    {0x00000025, 0x80011144}, 
-    {0x00000026, 0x80000003},
-    {0x00000027, 0x8001114B},
-    {0x00000028, 0x80000004},
-    {0x00000029, 0x8001114C},
-    {0x0000002A, 0x80000005},
-    {0x0000002B, 0x8001114D},
-    {0x0000002C, 0x80000006},
-    {0x0000002D, 0x8001114E},
-    {0x00000500, 0x00003000},
-    {0x00000501, 0x01FFFFFF},
-    {0x00000502, 0x00000002},
-    {0x00000503, 0x00000002},
-    {0x00000508, 0x01008043},
-    {0x0000050A, 0x00000000},
-    {0x0000050B, 0x00000000},
-    {0x0000050C, 0x01008019},
-    {0x0000050E, 0x00000000},
-    {0x0000050F, 0x00000000},
-#if 1
-    {0x00000510, 0x01008018},
-#else
-    {0x00000510, 0x01008044},
-#endif
-    {0x00000512, 0x00000000},
-    {0x00000513, 0x00000000},
-    {0x00000514, 0x01008021},
-    {0x00000516, 0x00000000},
-    {0x00000517, 0x00000000},
-    {0x00000518, 0x0100805F},
-    {0x0000051A, 0x00000000},
-    {0x0000051B, 0x00000000},
-#if 1
-    {0x0000051C, 0x0100804B},
-#else
-    {0x0000051C, 0x0100804A},
-#endif
-    {0x0000051E, 0x00000000},
-    {0x0000051F, 0x00000000},
-    {0x00000520, 0x0100A048},
-    {0x00000521, 0x00000D01},
-    {0x00000522, 0x11401140},
-    {0x00000523, 0x00000000},
-    {0x00000524, 0x0300A054},
-    {0x00000525, 0x00000D01},
-    {0x00000526, 0x11401140},
-    {0x00000527, 0x00000000},
-    {0x00000528, 0x0300A055},
-    {0x00000529, 0x00000D01},
-    {0x0000052A, 0x11401140},
-    {0x0000052B, 0x00000000},
-    {0x0000052C, 0x00000058},
-    {0x0000052E, 0x11401140},
-    {0x0000052F, 0x00000000},
-    {0x00000530, 0x00000059},
-    {0x00000532, 0x11401140},
-    {0x00000533, 0x00000000},
-    {0x00000534, 0x0000005A},
-    {0x00000536, 0x11401140},
-    {0x00000537, 0x00000000},
-    {0x00000538, 0x0000005B},
-    {0x0000053A, 0x11401140},
-    {0x0000053B, 0x00000000},
-    {0x0000053C, 0x0300A01C},
-    {0x0000053E, 0x11401140},
-    {0x0000053F, 0x00000000}
-};
-static unsigned nv4TablePRAMIN_8BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000302},
-    {0x0000050D, 0x00000302},
-    {0x00000511, 0x00000202},
-    {0x00000515, 0x00000302},
-    {0x00000519, 0x00000302},
-    {0x0000051D, 0x00000302},
-    {0x0000052D, 0x00000302},
-    {0x0000052E, 0x00000302},
-    {0x00000535, 0x00000000},
-    {0x00000539, 0x00000000},
-    {0x0000053D, 0x00000302}
-};
-static unsigned nv4TablePRAMIN_15BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000902},
-    {0x0000050D, 0x00000902},
-    {0x00000511, 0x00000802},
-    {0x00000515, 0x00000902},
-    {0x00000519, 0x00000902},
-    {0x0000051D, 0x00000902},
-    {0x0000052D, 0x00000902},
-    {0x0000052E, 0x00000902},
-    {0x00000535, 0x00000702},
-    {0x00000539, 0x00000702},
-    {0x0000053D, 0x00000902}
-};
-static unsigned nv4TablePRAMIN_16BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000C02},
-    {0x0000050D, 0x00000C02},
-    {0x00000511, 0x00000B02},
-    {0x00000515, 0x00000C02},
-    {0x00000519, 0x00000C02},
-    {0x0000051D, 0x00000C02},
-    {0x0000052D, 0x00000C02},
-    {0x0000052E, 0x00000C02},
-    {0x00000535, 0x00000702},
-    {0x00000539, 0x00000702},
-    {0x0000053D, 0x00000C02}
-};
-static unsigned nv4TablePRAMIN_32BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000E02},
-    {0x0000050D, 0x00000E02},
-    {0x00000511, 0x00000D02},
-    {0x00000515, 0x00000E02},
-    {0x00000519, 0x00000E02},
-    {0x0000051D, 0x00000E02},
-    {0x0000052D, 0x00000E02},
-    {0x0000052E, 0x00000E02},
-    {0x00000535, 0x00000E02},
-    {0x00000539, 0x00000E02},
-    {0x0000053D, 0x00000E02}
-};
-static unsigned nv10TableFIFO[][2] =
-{
-    {0x00003800, 0x80000014}
-};
-static unsigned nv10TablePFIFO[][2] =
-{
-    {0x00000140, 0x00000000},
-    {0x00000480, 0x00000000},
-    {0x00000494, 0x00000000},
-    {0x00000481, 0x00000000},
-    {0x0000048B, 0x00000000},
-    {0x00000400, 0x00000000},
-    {0x00000414, 0x00000000},
-    {0x00000084, 0x03000100},
-    {0x00000085, 0x00000110},
-    {0x00000086, 0x00000112},
-    {0x00000143, 0x0000FFFF},
-    {0x00000496, 0x0000FFFF},
-    {0x00000050, 0x00000000},
-    {0x00000040, 0xFFFFFFFF},
-    {0x00000415, 0x00000001},
-    {0x00000480, 0x00000001},
-    {0x00000494, 0x00000001},
-    {0x00000495, 0x00000001},
-    {0x00000140, 0x00000001}
-};
-static unsigned nv10TablePGRAPH[][2] =
-{
-    {0x00000020, 0x0003FFFF},
-    {0x00000021, 0x00118701},
-    {0x00000022, 0x24F82AD9},
-    {0x00000023, 0x55DE0030},
-    {0x00000020, 0x00000000},
-    {0x00000024, 0x00000000},
-    {0x00000058, 0x00000000},
-    {0x00000060, 0x00000000},
-    {0x00000068, 0x00000000},
-    {0x00000070, 0x00000000},
-    {0x00000078, 0x00000000},
-    {0x00000059, 0x00000000},
-    {0x00000061, 0x00000000},
-    {0x00000069, 0x00000000},
-    {0x00000071, 0x00000000},
-    {0x00000079, 0x00000000},
-    {0x0000005A, 0x00000000},
-    {0x00000062, 0x00000000},
-    {0x0000006A, 0x00000000},
-    {0x00000072, 0x00000000},
-    {0x0000007A, 0x00000000},
-    {0x0000005B, 0x00000000},
-    {0x00000063, 0x00000000},
-    {0x0000006B, 0x00000000},
-    {0x00000073, 0x00000000},
-    {0x0000007B, 0x00000000},
-    {0x0000005C, 0x00000000},
-    {0x00000064, 0x00000000},
-    {0x0000006C, 0x00000000},
-    {0x00000074, 0x00000000},
-    {0x0000007C, 0x00000000},
-    {0x0000005D, 0x00000000},
-    {0x00000065, 0x00000000},
-    {0x0000006D, 0x00000000},
-    {0x00000075, 0x00000000},
-    {0x0000007D, 0x00000000},
-    {0x0000005E, 0x00000000},
-    {0x00000066, 0x00000000},
-    {0x0000006E, 0x00000000},
-    {0x00000076, 0x00000000},
-    {0x0000007E, 0x00000000},
-    {0x0000005F, 0x00000000},
-    {0x00000067, 0x00000000},
-    {0x0000006F, 0x00000000},
-    {0x00000077, 0x00000000},
-    {0x0000007F, 0x00000000},
-    {0x00000053, 0x00000000},
-    {0x00000054, 0x00000000},
-    {0x00000055, 0x00000000},
-    {0x00000056, 0x00000000},
-    {0x00000057, 0x00000000},
-    {0x00000196, 0x00000000},
-    {0x000001A1, 0x01FFFFFF},
-    {0x00000197, 0x00000000},
-    {0x000001A2, 0x01FFFFFF},
-    {0x00000198, 0x00000000},
-    {0x000001A3, 0x01FFFFFF},
-    {0x00000199, 0x00000000},
-    {0x000001A4, 0x01FFFFFF},
-    {0x0000019A, 0x00000000},
-    {0x000001A5, 0x01FFFFFF},
-    {0x0000019B, 0x00000000},
-    {0x000001A6, 0x01FFFFFF},
-    {0x00000050, 0x01111111},
-    {0x00000040, 0xFFFFFFFF},
-    {0x00000051, 0x10010100},
-    {0x000001C5, 0xFFFFFFFF},
-    {0x000001C8, 0x00000001},
-    {0x00000204, 0x00000000},
-    {0x000001C4, 0x00000001}
-};
-static unsigned nv10TablePGRAPH_8BPP[][2] =
-{
-    {0x000001C9, 0x00111111},
-    {0x00000186, 0x00001010},
-    {0x0000020C, 0x03020202}
-};
-static unsigned nv10TablePGRAPH_15BPP[][2] =
-{
-    {0x000001C9, 0x00226222},
-    {0x00000186, 0x00002071},
-    {0x0000020C, 0x09080808}
-};
-static unsigned nv10TablePGRAPH_16BPP[][2] =
-{
-    {0x000001C9, 0x00556555},
-    {0x00000186, 0x000050C2},
-    {0x0000020C, 0x000B0B0C}
-};
-static unsigned nv10TablePGRAPH_32BPP[][2] =
-{
-    {0x000001C9, 0x0077D777},
-    {0x00000186, 0x000070E5},
-    {0x0000020C, 0x0E0D0D0D}
-};
-static unsigned nv10tri05TablePGRAPH[][2] =
-{
-    {(0x00000E00/4), 0x00000000},
-    {(0x00000E04/4), 0x00000000},
-    {(0x00000E08/4), 0x00000000},
-    {(0x00000E0C/4), 0x00000000},
-    {(0x00000E10/4), 0x00001000},
-    {(0x00000E14/4), 0x00001000},
-    {(0x00000E18/4), 0x4003ff80},
-    {(0x00000E1C/4), 0x00000000},
-    {(0x00000E20/4), 0x00000000},
-    {(0x00000E24/4), 0x00000000},
-    {(0x00000E28/4), 0x00000000},
-    {(0x00000E2C/4), 0x00000000},
-    {(0x00000E30/4), 0x00080008},
-    {(0x00000E34/4), 0x00080008},
-    {(0x00000E38/4), 0x00000000},
-    {(0x00000E3C/4), 0x00000000},
-    {(0x00000E40/4), 0x00000000},
-    {(0x00000E44/4), 0x00000000},
-    {(0x00000E48/4), 0x00000000},
-    {(0x00000E4C/4), 0x00000000},
-    {(0x00000E50/4), 0x00000000},
-    {(0x00000E54/4), 0x00000000},
-    {(0x00000E58/4), 0x00000000},
-    {(0x00000E5C/4), 0x00000000},
-    {(0x00000E60/4), 0x00000000},
-    {(0x00000E64/4), 0x10000000},
-    {(0x00000E68/4), 0x00000000},
-    {(0x00000E6C/4), 0x00000000},
-    {(0x00000E70/4), 0x00000000},
-    {(0x00000E74/4), 0x00000000},
-    {(0x00000E78/4), 0x00000000},
-    {(0x00000E7C/4), 0x00000000},
-    {(0x00000E80/4), 0x00000000},
-    {(0x00000E84/4), 0x00000000},
-    {(0x00000E88/4), 0x08000000},
-    {(0x00000E8C/4), 0x00000000},
-    {(0x00000E90/4), 0x00000000},
-    {(0x00000E94/4), 0x00000000},
-    {(0x00000E98/4), 0x00000000},
-    {(0x00000E9C/4), 0x4B7FFFFF},
-    {(0x00000EA0/4), 0x00000000},
-    {(0x00000EA4/4), 0x00000000},
-    {(0x00000EA8/4), 0x00000000},
-    {(0x00000F00/4), 0x07FF0800},
-    {(0x00000F04/4), 0x07FF0800},
-    {(0x00000F08/4), 0x07FF0800},
-    {(0x00000F0C/4), 0x07FF0800},
-    {(0x00000F10/4), 0x07FF0800},
-    {(0x00000F14/4), 0x07FF0800},
-    {(0x00000F18/4), 0x07FF0800},
-    {(0x00000F1C/4), 0x07FF0800},
-    {(0x00000F20/4), 0x07FF0800},
-    {(0x00000F24/4), 0x07FF0800},
-    {(0x00000F28/4), 0x07FF0800},
-    {(0x00000F2C/4), 0x07FF0800},
-    {(0x00000F30/4), 0x07FF0800},
-    {(0x00000F34/4), 0x07FF0800},
-    {(0x00000F38/4), 0x07FF0800},
-    {(0x00000F3C/4), 0x07FF0800},
-    {(0x00000F40/4), 0x10000000},
-    {(0x00000F44/4), 0x00000000},
-    {(0x00000F50/4), 0x00006740},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F50/4), 0x00006750},
-    {(0x00000F54/4), 0x40000000},
-    {(0x00000F54/4), 0x40000000},
-    {(0x00000F54/4), 0x40000000},
-    {(0x00000F54/4), 0x40000000},
-    {(0x00000F50/4), 0x00006760},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x00006770},
-    {(0x00000F54/4), 0xC5000000},
-    {(0x00000F54/4), 0xC5000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x00006780},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x000067A0},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F50/4), 0x00006AB0},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F50/4), 0x00006AC0},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x00006C10},
-    {(0x00000F54/4), 0xBF800000},
-    {(0x00000F50/4), 0x00007030},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x00007040},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x00007050},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x00007060},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x00007070},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x00007080},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x00007090},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x000070A0},
-    {(0x00000F54/4), 0x7149F2CA},
-    {(0x00000F50/4), 0x00006A80},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F50/4), 0x00006AA0},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x00000040},
-    {(0x00000F54/4), 0x00000005},
-    {(0x00000F50/4), 0x00006400},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x4B7FFFFF},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x00006410},
-    {(0x00000F54/4), 0xC5000000},
-    {(0x00000F54/4), 0xC5000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x00006420},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x00006430},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x000064C0},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F54/4), 0x477FFFFF},
-    {(0x00000F54/4), 0x3F800000},
-    {(0x00000F50/4), 0x000064D0},
-    {(0x00000F54/4), 0xC5000000},
-    {(0x00000F54/4), 0xC5000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x000064E0},
-    {(0x00000F54/4), 0xC4FFF000},
-    {(0x00000F54/4), 0xC4FFF000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F50/4), 0x000064F0},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F54/4), 0x00000000},
-    {(0x00000F40/4), 0x30000000},
-    {(0x00000F44/4), 0x00000004},
-    {(0x00000F48/4), 0x10000000},
-    {(0x00000F4C/4), 0x00000000}
-};
-static unsigned nv10TablePRAMIN[][2] =
-{
-    {0x00000000, 0x80000010},
-    {0x00000001, 0x80011145},
-    {0x00000002, 0x80000011},
-    {0x00000003, 0x80011146},
-    {0x00000004, 0x80000012},
-    {0x00000005, 0x80011147},
-    {0x00000006, 0x80000013},
-    {0x00000007, 0x80011148},
-    {0x00000008, 0x80000014},
-    {0x00000009, 0x80011149},
-    {0x0000000A, 0x80000015},
-    {0x0000000B, 0x8001114A},
-    {0x0000000C, 0x80000016},
-    {0x0000000D, 0x80011150},
-    {0x00000020, 0x80000000},
-    {0x00000021, 0x80011142},
-    {0x00000022, 0x80000001},
-    {0x00000023, 0x80011143},
-    {0x00000024, 0x80000002},
-    {0x00000025, 0x80011144},
-    {0x00000026, 0x80000003},
-    {0x00000027, 0x8001114B},
-    {0x00000028, 0x80000004},
-    {0x00000029, 0x8001114C},
-    {0x0000002A, 0x80000005},
-    {0x0000002B, 0x8001114D},
-    {0x0000002C, 0x80000006},
-    {0x0000002D, 0x8001114E},
-    {0x0000002E, 0x80000007},
-    {0x0000002F, 0x8001114F},
-    {0x00000500, 0x00003000},
-    {0x00000501, 0x01FFFFFF},
-    {0x00000502, 0x00000002},
-    {0x00000503, 0x00000002},
-#ifdef __BIG_ENDIAN
-    {0x00000508, 0x01088043}, 
-#else
-    {0x00000508, 0x01008043},
-#endif
-    {0x0000050A, 0x00000000},
-    {0x0000050B, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x0000050C, 0x01088019},
-#else
-    {0x0000050C, 0x01008019},
-#endif
-    {0x0000050E, 0x00000000},
-    {0x0000050F, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x00000510, 0x01088018},
-#else
-    {0x00000510, 0x01008018},
-#endif
-    {0x00000512, 0x00000000},
-    {0x00000513, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x00000514, 0x01088021},
-#else
-    {0x00000514, 0x01008021},
-#endif
-    {0x00000516, 0x00000000},
-    {0x00000517, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x00000518, 0x0108805F},
-#else
-    {0x00000518, 0x0100805F},
-#endif
-    {0x0000051A, 0x00000000},
-    {0x0000051B, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x0000051C, 0x0108804B},
-#else
-    {0x0000051C, 0x0100804B},
-#endif
-    {0x0000051E, 0x00000000},
-    {0x0000051F, 0x00000000},
-    {0x00000520, 0x0100A048},
-    {0x00000521, 0x00000D01},
-    {0x00000522, 0x11401140},
-    {0x00000523, 0x00000000},
-    {0x00000524, 0x0300A094},
-    {0x00000525, 0x00000D01},
-    {0x00000526, 0x11401140},
-    {0x00000527, 0x00000000},
-    {0x00000528, 0x0300A095},
-    {0x00000529, 0x00000D01},
-    {0x0000052A, 0x11401140},
-    {0x0000052B, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x0000052C, 0x00080058},
-#else
-    {0x0000052C, 0x00000058},
-#endif
-    {0x0000052E, 0x11401140},
-    {0x0000052F, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x00000530, 0x00080059},
-#else
-    {0x00000530, 0x00000059},
-#endif
-    {0x00000532, 0x11401140},
-    {0x00000533, 0x00000000},
-    {0x00000534, 0x0000005A},
-    {0x00000536, 0x11401140},
-    {0x00000537, 0x00000000},
-    {0x00000538, 0x0000005B},
-    {0x0000053A, 0x11401140},
-    {0x0000053B, 0x00000000},
-    {0x0000053C, 0x00000093},
-    {0x0000053E, 0x11401140},
-    {0x0000053F, 0x00000000},
-#ifdef __BIG_ENDIAN
-    {0x00000540, 0x0308A01C},
-#else
-    {0x00000540, 0x0300A01C},
-#endif
-    {0x00000542, 0x11401140},
-    {0x00000543, 0x00000000}
-};
-static unsigned nv10TablePRAMIN_8BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000302},
-    {0x0000050D, 0x00000302},
-    {0x00000511, 0x00000202},
-    {0x00000515, 0x00000302},
-    {0x00000519, 0x00000302},
-    {0x0000051D, 0x00000302},
-    {0x0000052D, 0x00000302},
-    {0x0000052E, 0x00000302},
-    {0x00000535, 0x00000000},
-    {0x00000539, 0x00000000},
-    {0x0000053D, 0x00000000},
-    {0x00000541, 0x00000302}
-};
-static unsigned nv10TablePRAMIN_15BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000902},
-    {0x0000050D, 0x00000902},
-    {0x00000511, 0x00000802},
-    {0x00000515, 0x00000902},
-    {0x00000519, 0x00000902},
-    {0x0000051D, 0x00000902},
-    {0x0000052D, 0x00000902},
-    {0x0000052E, 0x00000902},
-    {0x00000535, 0x00000902},
-    {0x00000539, 0x00000902}, 
-    {0x0000053D, 0x00000902},
-    {0x00000541, 0x00000902}
-};
-static unsigned nv10TablePRAMIN_16BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000C02},
-    {0x0000050D, 0x00000C02},
-    {0x00000511, 0x00000B02},
-    {0x00000515, 0x00000C02},
-    {0x00000519, 0x00000C02},
-    {0x0000051D, 0x00000C02},
-    {0x0000052D, 0x00000C02},
-    {0x0000052E, 0x00000C02},
-    {0x00000535, 0x00000C02},
-    {0x00000539, 0x00000C02},
-    {0x0000053D, 0x00000C02},
-    {0x00000541, 0x00000C02}
-};
-static unsigned nv10TablePRAMIN_32BPP[][2] =
-{
-    /*           0xXXXXXX01 For  MSB mono format */
-    /*           0xXXXXXX02 For  LSB mono format */
-    {0x00000509, 0x00000E02},
-    {0x0000050D, 0x00000E02},
-    {0x00000511, 0x00000D02},
-    {0x00000515, 0x00000E02},
-    {0x00000519, 0x00000E02},
-    {0x0000051D, 0x00000E02},
-    {0x0000052D, 0x00000E02},
-    {0x0000052E, 0x00000E02},
-    {0x00000535, 0x00000E02},
-    {0x00000539, 0x00000E02},
-    {0x0000053D, 0x00000E02},
-    {0x00000541, 0x00000E02}
-};
-
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
deleted file mode 100644
index 6a183375ced1..000000000000
--- a/drivers/video/riva/rivafb-i2c.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * linux/drivers/video/riva/fbdev-i2c.c - nVidia i2c
- *
- * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
- *
- * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
- *
- * Based on radeonfb-i2c.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/fb.h>
-#include <linux/jiffies.h>
-
-#include <asm/io.h>
-
-#include "rivafb.h"
-#include "../edid.h"
-
-static void riva_gpio_setscl(void* data, int state)
-{
-	struct riva_i2c_chan 	*chan = data;
-	struct riva_par 	*par = chan->par;
-	u32			val;
-
-	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
-	val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
-
-	if (state)
-		val |= 0x20;
-	else
-		val &= ~0x20;
-
-	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
-	VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
-}
-
-static void riva_gpio_setsda(void* data, int state)
-{
-	struct riva_i2c_chan 	*chan = data;
-	struct riva_par 	*par = chan->par;
-	u32			val;
-
-	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
-	val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
-
-	if (state)
-		val |= 0x10;
-	else
-		val &= ~0x10;
-
-	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
-	VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
-}
-
-static int riva_gpio_getscl(void* data)
-{
-	struct riva_i2c_chan 	*chan = data;
-	struct riva_par 	*par = chan->par;
-	u32			val = 0;
-
-	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
-	if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04)
-		val = 1;
-
-	return val;
-}
-
-static int riva_gpio_getsda(void* data)
-{
-	struct riva_i2c_chan 	*chan = data;
-	struct riva_par 	*par = chan->par;
-	u32			val = 0;
-
-	VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
-	if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x08)
-		val = 1;
-
-	return val;
-}
-
-static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name,
-			      unsigned int i2c_class)
-{
-	int rc;
-
-	strcpy(chan->adapter.name, name);
-	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.class		= i2c_class;
-	chan->adapter.algo_data		= &chan->algo;
-	chan->adapter.dev.parent	= &chan->par->pdev->dev;
-	chan->algo.setsda		= riva_gpio_setsda;
-	chan->algo.setscl		= riva_gpio_setscl;
-	chan->algo.getsda		= riva_gpio_getsda;
-	chan->algo.getscl		= riva_gpio_getscl;
-	chan->algo.udelay		= 40;
-	chan->algo.timeout		= msecs_to_jiffies(2);
-	chan->algo.data 		= chan;
-
-	i2c_set_adapdata(&chan->adapter, chan);
-
-	/* Raise SCL and SDA */
-	riva_gpio_setsda(chan, 1);
-	riva_gpio_setscl(chan, 1);
-	udelay(20);
-
-	rc = i2c_bit_add_bus(&chan->adapter);
-	if (rc == 0)
-		dev_dbg(&chan->par->pdev->dev, "I2C bus %s registered.\n", name);
-	else {
-		dev_warn(&chan->par->pdev->dev,
-			 "Failed to register I2C bus %s.\n", name);
-		chan->par = NULL;
-	}
-
-	return rc;
-}
-
-void riva_create_i2c_busses(struct riva_par *par)
-{
-	par->chan[0].par	= par;
-	par->chan[1].par	= par;
-	par->chan[2].par        = par;
-
-	par->chan[0].ddc_base = 0x36;
-	par->chan[1].ddc_base = 0x3e;
-	par->chan[2].ddc_base = 0x50;
-	riva_setup_i2c_bus(&par->chan[0], "BUS1", I2C_CLASS_HWMON);
-	riva_setup_i2c_bus(&par->chan[1], "BUS2", 0);
-	riva_setup_i2c_bus(&par->chan[2], "BUS3", 0);
-}
-
-void riva_delete_i2c_busses(struct riva_par *par)
-{
-	int i;
-
-	for (i = 0; i < 3; i++) {
-		if (!par->chan[i].par)
-			continue;
-		i2c_del_adapter(&par->chan[i].adapter);
-		par->chan[i].par = NULL;
-	}
-}
-
-int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
-{
-	u8 *edid = NULL;
-
-	if (par->chan[conn].par)
-		edid = fb_ddc_read(&par->chan[conn].adapter);
-
-	if (out_edid)
-		*out_edid = edid;
-	if (!edid)
-		return 1;
-
-	return 0;
-}
-
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
deleted file mode 100644
index d9f107b704c6..000000000000
--- a/drivers/video/riva/rivafb.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef __RIVAFB_H
-#define __RIVAFB_H
-
-#include <linux/fb.h>
-#include <video/vga.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include "riva_hw.h"
-
-/* GGI compatibility macros */
-#define NUM_SEQ_REGS		0x05
-#define NUM_CRT_REGS		0x41
-#define NUM_GRC_REGS		0x09
-#define NUM_ATC_REGS		0x15
-
-/* I2C */
-#define DDC_SCL_READ_MASK       (1 << 2)
-#define DDC_SCL_WRITE_MASK      (1 << 5)
-#define DDC_SDA_READ_MASK       (1 << 3)
-#define DDC_SDA_WRITE_MASK      (1 << 4)
-
-/* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
- * From KGI originally. */
-struct riva_regs {
-	u8 attr[NUM_ATC_REGS];
-	u8 crtc[NUM_CRT_REGS];
-	u8 gra[NUM_GRC_REGS];
-	u8 seq[NUM_SEQ_REGS];
-	u8 misc_output;
-	RIVA_HW_STATE ext;
-};
-
-struct riva_par;
-
-struct riva_i2c_chan {
-	struct riva_par *par;
-	unsigned long   ddc_base;
-	struct i2c_adapter adapter;
-	struct i2c_algo_bit_data algo;
-};
-
-struct riva_par {
-	RIVA_HW_INST riva;	/* interface to riva_hw.c */
-	u32 pseudo_palette[16]; /* default palette */
-	u32 palette[16];        /* for Riva128 */
-	u8 __iomem *ctrl_base;	/* virtual control register base addr */
-	unsigned dclk_max;	/* max DCLK */
-
-	struct riva_regs initial_state;	/* initial startup video mode */
-	struct riva_regs current_state;
-#ifdef CONFIG_X86
-	struct vgastate state;
-#endif
-	struct mutex open_lock;
-	unsigned int ref_count;
-	unsigned char *EDID;
-	unsigned int Chipset;
-	int forceCRTC;
-	Bool SecondCRTC;
-	int FlatPanel;
-	struct pci_dev *pdev;
-	int cursor_reset;
-#ifdef CONFIG_MTRR
-	struct { int vram; int vram_valid; } mtrr;
-#endif
-	struct riva_i2c_chan chan[3];
-};
-
-void riva_common_setup(struct riva_par *);
-unsigned long riva_get_memlen(struct riva_par *);
-unsigned long riva_get_maxdclk(struct riva_par *);
-void riva_delete_i2c_busses(struct riva_par *par);
-void riva_create_i2c_busses(struct riva_par *par);
-int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid);
-
-#endif /* __RIVAFB_H */
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
deleted file mode 100644
index 83433cb0dfba..000000000000
--- a/drivers/video/s1d13xxxfb.c
+++ /dev/null
@@ -1,1040 +0,0 @@
-/* drivers/video/s1d13xxxfb.c
- *
- * (c) 2004 Simtec Electronics
- * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
- * (c) 2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
- *
- * Driver for Epson S1D13xxx series framebuffer chips
- *
- * Adapted from
- *  linux/drivers/video/skeletonfb.c
- *  linux/drivers/video/epson1355fb.c
- *  linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson)
- *
- * TODO: - handle dual screen display (CRT and LCD at the same time).
- *	 - check_var(), mode change, etc.
- *	 - probably not SMP safe :)
- *       - support all bitblt operations on all cards
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/fb.h>
-#include <linux/spinlock_types.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-
-#include <video/s1d13xxxfb.h>
-
-#define PFX	"s1d13xxxfb: "
-#define BLIT	"s1d13xxxfb_bitblt: "
-
-/*
- * set this to enable debugging on general functions
- */
-#if 0
-#define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)
-#else
-#define dbg(fmt, args...) do { } while (0)
-#endif
-
-/*
- * set this to enable debugging on 2D acceleration
- */
-#if 0
-#define dbg_blit(fmt, args...) do { printk(KERN_INFO BLIT fmt, ## args); } while (0)
-#else
-#define dbg_blit(fmt, args...) do { } while (0)
-#endif
-
-/*
- * we make sure only one bitblt operation is running
- */
-static DEFINE_SPINLOCK(s1d13xxxfb_bitblt_lock);
-
-/*
- * list of card production ids
- */
-static const int s1d13xxxfb_prod_ids[] = {
-	S1D13505_PROD_ID,
-	S1D13506_PROD_ID,
-	S1D13806_PROD_ID,
-};
-
-/*
- * List of card strings
- */
-static const char *s1d13xxxfb_prod_names[] = {
-	"S1D13505",
-	"S1D13506",
-	"S1D13806",
-};
-
-/*
- * here we define the default struct fb_fix_screeninfo
- */
-static struct fb_fix_screeninfo s1d13xxxfb_fix = {
-	.id		= S1D_FBID,
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep	= 0,
-	.ypanstep	= 1,
-	.ywrapstep	= 0,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static inline u8
-s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
-{
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
-	regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
-#endif
-	return readb(par->regs + regno);
-}
-
-static inline void
-s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
-{
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
-	regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
-#endif
-	writeb(value, par->regs + regno);
-}
-
-static inline void
-s1d13xxxfb_runinit(struct s1d13xxxfb_par *par,
-			const struct s1d13xxxfb_regval *initregs,
-			const unsigned int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++) {
-        	if ((initregs[i].addr == S1DREG_DELAYOFF) ||
-				(initregs[i].addr == S1DREG_DELAYON))
-			mdelay((int)initregs[i].value);
-        	else {
-			s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);
-		}
-        }
-
-	/* make sure the hardware can cope with us */
-	mdelay(1);
-}
-
-static inline void
-lcd_enable(struct s1d13xxxfb_par *par, int enable)
-{
-	u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
-
-	if (enable)
-		mode |= 0x01;
-	else
-		mode &= ~0x01;
-
-	s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
-}
-
-static inline void
-crt_enable(struct s1d13xxxfb_par *par, int enable)
-{
-	u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
-
-	if (enable)
-		mode |= 0x02;
-	else
-		mode &= ~0x02;
-
-	s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
-}
-
-
-/*************************************************************
- framebuffer control functions
- *************************************************************/
-static inline void
-s1d13xxxfb_setup_pseudocolour(struct fb_info *info)
-{
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->var.red.length = 4;
-	info->var.green.length = 4;
-	info->var.blue.length = 4;
-}
-
-static inline void
-s1d13xxxfb_setup_truecolour(struct fb_info *info)
-{
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-	info->var.bits_per_pixel = 16;
-
-	info->var.red.length = 5;
-	info->var.red.offset = 11;
-
-	info->var.green.length = 6;
-	info->var.green.offset = 5;
-
-	info->var.blue.length = 5;
-	info->var.blue.offset = 0;
-}
-
-/**
- *      s1d13xxxfb_set_par - Alters the hardware state.
- *      @info: frame buffer structure
- *
- *	Using the fb_var_screeninfo in fb_info we set the depth of the
- *	framebuffer. This function alters the par AND the
- *	fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
- *	fb_info since we are using that data. This means we depend on the
- *	data in var inside fb_info to be supported by the hardware.
- *	xxxfb_check_var is always called before xxxfb_set_par to ensure this.
- *
- *	XXX TODO: write proper s1d13xxxfb_check_var(), without which that
- *	function is quite useless.
- */
-static int
-s1d13xxxfb_set_par(struct fb_info *info)
-{
-	struct s1d13xxxfb_par *s1dfb = info->par;
-	unsigned int val;
-
-	dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);
-
-	if ((s1dfb->display & 0x01))	/* LCD */
-		val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE);   /* read colour control */
-	else	/* CRT */
-		val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE);   /* read colour control */
-
-	val &= ~0x07;
-
-	switch (info->var.bits_per_pixel) {
-		case 4:
-			dbg("pseudo colour 4\n");
-			s1d13xxxfb_setup_pseudocolour(info);
-			val |= 2;
-			break;
-		case 8:
-			dbg("pseudo colour 8\n");
-			s1d13xxxfb_setup_pseudocolour(info);
-			val |= 3;
-			break;
-		case 16:
-			dbg("true colour\n");
-			s1d13xxxfb_setup_truecolour(info);
-			val |= 5;
-			break;
-
-		default:
-			dbg("bpp not supported!\n");
-			return -EINVAL;
-	}
-
-	dbg("writing %02x to display mode register\n", val);
-
-	if ((s1dfb->display & 0x01))	/* LCD */
-		s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);
-	else	/* CRT */
-		s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);
-
-	info->fix.line_length  = info->var.xres * info->var.bits_per_pixel;
-	info->fix.line_length /= 8;
-
-	dbg("setting line_length to %d\n", info->fix.line_length);
-
-	dbg("done setup\n");
-
-	return 0;
-}
-
-/**
- *	s1d13xxxfb_setcolreg - sets a color register.
- *	@regno: Which register in the CLUT we are programming
- *	@red: The red value which can be up to 16 bits wide
- *	@green: The green value which can be up to 16 bits wide
- *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.
- *	@info: frame buffer info structure
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int
-s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			u_int transp, struct fb_info *info)
-{
-	struct s1d13xxxfb_par *s1dfb = info->par;
-	unsigned int pseudo_val;
-
-	if (regno >= S1D_PALETTE_SIZE)
-		return -EINVAL;
-
-	dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",
-		    regno, red, green, blue, transp);
-
-	if (info->var.grayscale)
-		red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;
-
-	switch (info->fix.visual) {
-		case FB_VISUAL_TRUECOLOR:
-			if (regno >= 16)
-				return -EINVAL;
-
-			/* deal with creating pseudo-palette entries */
-
-			pseudo_val  = (red   >> 11) << info->var.red.offset;
-			pseudo_val |= (green >> 10) << info->var.green.offset;
-			pseudo_val |= (blue  >> 11) << info->var.blue.offset;
-
-			dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
-				    regno, pseudo_val);
-
-#if defined(CONFIG_PLAT_MAPPI)
-			((u32 *)info->pseudo_palette)[regno] = cpu_to_le16(pseudo_val);
-#else
-			((u32 *)info->pseudo_palette)[regno] = pseudo_val;
-#endif
-
-			break;
-		case FB_VISUAL_PSEUDOCOLOR:
-			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);
-			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);
-			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);
-			s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);
-
-			break;
-		default:
-			return -ENOSYS;
-	}
-
-	dbg("s1d13xxxfb_setcolreg: done\n");
-
-	return 0;
-}
-
-/**
- *      s1d13xxxfb_blank - blanks the display.
- *      @blank_mode: the blank mode we want.
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
- *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
- *      video mode which doesn't support it. Implements VESA suspend
- *      and powerdown modes on hardware that supports disabling hsync/vsync:
- *      blank_mode == 2: suspend vsync
- *      blank_mode == 3: suspend hsync
- *      blank_mode == 4: powerdown
- *
- *      Returns negative errno on error, or zero on success.
- */
-static int
-s1d13xxxfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct s1d13xxxfb_par *par = info->par;
-
-	dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);
-
-	switch (blank_mode) {
-		case FB_BLANK_UNBLANK:
-		case FB_BLANK_NORMAL:
-			if ((par->display & 0x01) != 0)
-				lcd_enable(par, 1);
-			if ((par->display & 0x02) != 0)
-				crt_enable(par, 1);
-			break;
-		case FB_BLANK_VSYNC_SUSPEND:
-		case FB_BLANK_HSYNC_SUSPEND:
-			break;
-		case FB_BLANK_POWERDOWN:
-			lcd_enable(par, 0);
-			crt_enable(par, 0);
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	/* let fbcon do a soft blank for us */
-	return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
-}
-
-/**
- *	s1d13xxxfb_pan_display - Pans the display.
- *	@var: frame buffer variable screen structure
- *	@info: frame buffer structure that represents a single frame buffer
- *
- *	Pan (or wrap, depending on the `vmode' field) the display using the
- *	`yoffset' field of the `var' structure (`xoffset'  not yet supported).
- *	If the values don't fit, return -EINVAL.
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int
-s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct s1d13xxxfb_par *par = info->par;
-	u32 start;
-
-	if (var->xoffset != 0)	/* not yet ... */
-		return -EINVAL;
-
-	if (var->yoffset + info->var.yres > info->var.yres_virtual)
-		return -EINVAL;
-
-	start = (info->fix.line_length >> 1) * var->yoffset;
-
-	if ((par->display & 0x01)) {
-		/* LCD */
-		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));
-		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));
-		s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));
-	} else {
-		/* CRT */
-		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));
-		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));
-		s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));
-	}
-
-	return 0;
-}
-
-/************************************************************
- functions to handle bitblt acceleration
- ************************************************************/
-
-/**
- *	bltbit_wait_bitclear - waits for change in register value
- *	@info : frambuffer structure
- *	@bit  : value currently in register
- *	@timeout : ...
- *
- *	waits until value changes FROM bit
- *
- */
-static u8
-bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout)
-{
-	while (s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit) {
-		udelay(10);
-		if (!--timeout) {
-			dbg_blit("wait_bitclear timeout\n");
-			break;
-		}
-	}
-
-	return timeout;
-}
-
-/*
- *	s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
- *	@info : framebuffer structure
- *	@area : fb_copyarea structure
- *
- *	supports (atleast) S1D13506
- *
- */
-static void
-s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	u32 dst, src;
-	u32 stride;
-	u16 reverse = 0;
-	u16 sx = area->sx, sy = area->sy;
-	u16 dx = area->dx, dy = area->dy;
-	u16 width = area->width, height = area->height;
-	u16 bpp;
-
-	spin_lock(&s1d13xxxfb_bitblt_lock);
-
-	/* bytes per xres line */
-	bpp = (info->var.bits_per_pixel >> 3);
-	stride = bpp * info->var.xres;
-
-	/* reverse, calculate the last pixel in rectangle */
-	if ((dy > sy) || ((dy == sy) && (dx >= sx))) {
-		dst = (((dy + height - 1) * stride) + (bpp * (dx + width - 1)));
-		src = (((sy + height - 1) * stride) + (bpp * (sx + width - 1)));
-		reverse = 1;
-	/* not reverse, calculate the first pixel in rectangle */
-	} else { /* (y * xres) + (bpp * x) */
-		dst = (dy * stride) + (bpp * dx);
-		src = (sy * stride) + (bpp * sx);
-	}
-
-	/* set source address */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff));
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff);
-
-	/* set destination address */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff));
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff);
-
-	/* program height and width */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, (width & 0xff) - 1);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (width >> 8));
-
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, (height & 0xff) - 1);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (height >> 8));
-
-	/* negative direction ROP */
-	if (reverse == 1) {
-		dbg_blit("(copyarea) negative rop\n");
-		s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x03);
-	} else /* positive direction ROP */ {
-		s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x02);
-		dbg_blit("(copyarea) positive rop\n");
-	}
-
-	/* set for rectangel mode and not linear */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
-
-	/* setup the bpp 1 = 16bpp, 0 = 8bpp*/
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (bpp >> 1));
-
-	/* set words per xres */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (stride >> 1) & 0xff);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (stride >> 9));
-
-	dbg_blit("(copyarea) dx=%d, dy=%d\n", dx, dy);
-	dbg_blit("(copyarea) sx=%d, sy=%d\n", sx, sy);
-	dbg_blit("(copyarea) width=%d, height=%d\n", width - 1, height - 1);
-	dbg_blit("(copyarea) stride=%d\n", stride);
-	dbg_blit("(copyarea) bpp=%d=0x0%d, mem_offset1=%d, mem_offset2=%d\n", bpp, (bpp >> 1),
-		(stride >> 1) & 0xff, stride >> 9);
-
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CC_EXP, 0x0c);
-
-	/* initialize the engine */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
-
-	/* wait to complete */
-	bltbit_wait_bitclear(info, 0x80, 8000);
-
-	spin_unlock(&s1d13xxxfb_bitblt_lock);
-}
-
-/**
- *
- *	s1d13xxxfb_bitblt_solidfill - accelerated solidfill function
- *	@info : framebuffer structure
- *	@rect : fb_fillrect structure
- *
- *	supports (atleast 13506)
- *
- **/
-static void
-s1d13xxxfb_bitblt_solidfill(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	u32 screen_stride, dest;
-	u32 fg;
-	u16 bpp = (info->var.bits_per_pixel >> 3);
-
-	/* grab spinlock */
-	spin_lock(&s1d13xxxfb_bitblt_lock);
-
-	/* bytes per x width */
-	screen_stride = (bpp * info->var.xres);
-
-	/* bytes to starting point */
-	dest = ((rect->dy * screen_stride) + (bpp * rect->dx));
-
-	dbg_blit("(solidfill) dx=%d, dy=%d, stride=%d, dest=%d\n"
-		 "(solidfill) : rect_width=%d, rect_height=%d\n",
-				rect->dx, rect->dy, screen_stride, dest,
-				rect->width - 1, rect->height - 1);
-
-	dbg_blit("(solidfill) : xres=%d, yres=%d, bpp=%d\n",
-				info->var.xres, info->var.yres,
-				info->var.bits_per_pixel);
-	dbg_blit("(solidfill) : rop=%d\n", rect->rop);
-
-	/* We split the destination into the three registers */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dest & 0x00ff));
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, ((dest >> 8) & 0x00ff));
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, ((dest >> 16) & 0x00ff));
-
-	/* give information regarding rectangel width */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, ((rect->width) & 0x00ff) - 1);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (rect->width >> 8));
-
-	/* give information regarding rectangel height */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, ((rect->height) & 0x00ff) - 1);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (rect->height >> 8));
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-		info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		fg = ((u32 *)info->pseudo_palette)[rect->color];
-		dbg_blit("(solidfill) truecolor/directcolor\n");
-		dbg_blit("(solidfill) pseudo_palette[%d] = %d\n", rect->color, fg);
-	} else {
-		fg = rect->color;
-		dbg_blit("(solidfill) color = %d\n", rect->color);
-	}
-
-	/* set foreground color */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC0, (fg & 0xff));
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC1, (fg >> 8) & 0xff);
-
-	/* set rectangual region of memory (rectangle and not linear) */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
-
-	/* set operation mode SOLID_FILL */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, BBLT_SOLID_FILL);
-
-	/* set bits per pixel (1 = 16bpp, 0 = 8bpp) */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (info->var.bits_per_pixel >> 4));
-
-	/* set the memory offset for the bblt in word sizes */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (screen_stride >> 1) & 0x00ff);
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (screen_stride >> 9));
-
-	/* and away we go.... */
-	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
-
-	/* wait until its done */
-	bltbit_wait_bitclear(info, 0x80, 8000);
-
-	/* let others play */
-	spin_unlock(&s1d13xxxfb_bitblt_lock);
-}
-
-/* framebuffer information structures */
-static struct fb_ops s1d13xxxfb_fbops = {
-	.owner		= THIS_MODULE,
-	.fb_set_par	= s1d13xxxfb_set_par,
-	.fb_setcolreg	= s1d13xxxfb_setcolreg,
-	.fb_blank	= s1d13xxxfb_blank,
-
-	.fb_pan_display	= s1d13xxxfb_pan_display,
-
-	/* gets replaced at chip detection time */
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int s1d13xxxfb_width_tab[2][4] = {
-	{4, 8, 16, -1},
-	{9, 12, 18, -1},
-};
-
-/**
- *	s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to
- *	hardware setup.
- *	@info: frame buffer structure
- *
- *	We setup the framebuffer structures according to the current
- *	hardware setup. On some machines, the BIOS will have filled
- *	the chip registers with such info, on others, these values will
- *	have been written in some init procedure. In any case, the
- *	software values needs to match the hardware ones. This is what
- *	this function ensures.
- *
- *	Note: some of the hardcoded values here might need some love to
- *	work on various chips, and might need to no longer be hardcoded.
- */
-static void s1d13xxxfb_fetch_hw_state(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-	struct fb_fix_screeninfo *fix = &info->fix;
-	struct s1d13xxxfb_par *par = info->par;
-	u8 panel, display;
-	u16 offset;
-	u32 xres, yres;
-	u32 xres_virtual, yres_virtual;
-	int bpp, lcd_bpp;
-	int is_color, is_dual, is_tft;
-	int lcd_enabled, crt_enabled;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-
-	/* general info */
-	par->display = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
-	crt_enabled = (par->display & 0x02) != 0;
-	lcd_enabled = (par->display & 0x01) != 0;
-
-	if (lcd_enabled && crt_enabled)
-		printk(KERN_WARNING PFX "Warning: LCD and CRT detected, using LCD\n");
-
-	if (lcd_enabled)
-		display = s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_MODE);
-	else	/* CRT */
-		display = s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_MODE);
-
-	bpp = display & 0x07;
-
-	switch (bpp) {
-		case 2:	/* 4 bpp */
-		case 3:	/* 8 bpp */
-			var->bits_per_pixel = 8;
-			var->red.offset = var->green.offset = var->blue.offset = 0;
-			var->red.length = var->green.length = var->blue.length = 8;
-			break;
-		case 5:	/* 16 bpp */
-			s1d13xxxfb_setup_truecolour(info);
-			break;
-		default:
-			dbg("bpp: %i\n", bpp);
-	}
-	fb_alloc_cmap(&info->cmap, 256, 0);
-
-	/* LCD info */
-	panel = s1d13xxxfb_readreg(par, S1DREG_PANEL_TYPE);
-	is_color = (panel & 0x04) != 0;
-	is_dual = (panel & 0x02) != 0;
-	is_tft = (panel & 0x01) != 0;
-	lcd_bpp = s1d13xxxfb_width_tab[is_tft][(panel >> 4) & 3];
-
-	if (lcd_enabled) {
-		xres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_HWIDTH) + 1) * 8;
-		yres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT0) +
-			((s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT1) & 0x03) << 8) + 1);
-
-		offset = (s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF0) +
-			((s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF1) & 0x7) << 8));
-	} else { /* crt */
-		xres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_HWIDTH) + 1) * 8;
-		yres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT0) +
-			((s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT1) & 0x03) << 8) + 1);
-
-		offset = (s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF0) +
-			((s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF1) & 0x7) << 8));
-	}
-	xres_virtual = offset * 16 / var->bits_per_pixel;
-	yres_virtual = fix->smem_len / (offset * 2);
-
-	var->xres		= xres;
-	var->yres		= yres;
-	var->xres_virtual	= xres_virtual;
-	var->yres_virtual	= yres_virtual;
-	var->xoffset		= var->yoffset = 0;
-
-	fix->line_length	= offset * 2;
-
-	var->grayscale		= !is_color;
-
-	var->activate		= FB_ACTIVATE_NOW;
-
-	dbg(PFX "bpp=%d, lcd_bpp=%d, "
-		"crt_enabled=%d, lcd_enabled=%d\n",
-		var->bits_per_pixel, lcd_bpp, crt_enabled, lcd_enabled);
-	dbg(PFX "xres=%d, yres=%d, vxres=%d, vyres=%d "
-		"is_color=%d, is_dual=%d, is_tft=%d\n",
-		xres, yres, xres_virtual, yres_virtual, is_color, is_dual, is_tft);
-}
-
-
-static int
-s1d13xxxfb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct s1d13xxxfb_par *par = NULL;
-
-	if (info) {
-		par = info->par;
-		if (par && par->regs) {
-			/* disable output & enable powersave */
-			s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, 0x00);
-			s1d13xxxfb_writereg(par, S1DREG_PS_CNF, 0x11);
-			iounmap(par->regs);
-		}
-
-		fb_dealloc_cmap(&info->cmap);
-
-		if (info->screen_base)
-			iounmap(info->screen_base);
-
-		framebuffer_release(info);
-	}
-
-	release_mem_region(pdev->resource[0].start,
-			pdev->resource[0].end - pdev->resource[0].start +1);
-	release_mem_region(pdev->resource[1].start,
-			pdev->resource[1].end - pdev->resource[1].start +1);
-	return 0;
-}
-
-static int s1d13xxxfb_probe(struct platform_device *pdev)
-{
-	struct s1d13xxxfb_par *default_par;
-	struct fb_info *info;
-	struct s1d13xxxfb_pdata *pdata = NULL;
-	int ret = 0;
-	int i;
-	u8 revision, prod_id;
-
-	dbg("probe called: device is %p\n", pdev);
-
-	printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
-
-	/* enable platform-dependent hardware glue, if any */
-	if (dev_get_platdata(&pdev->dev))
-		pdata = dev_get_platdata(&pdev->dev);
-
-	if (pdata && pdata->platform_init_video)
-		pdata->platform_init_video();
-
-	if (pdev->num_resources != 2) {
-		dev_err(&pdev->dev, "invalid num_resources: %i\n",
-		       pdev->num_resources);
-		ret = -ENODEV;
-		goto bail;
-	}
-
-	/* resource[0] is VRAM, resource[1] is registers */
-	if (pdev->resource[0].flags != IORESOURCE_MEM
-			|| pdev->resource[1].flags != IORESOURCE_MEM) {
-		dev_err(&pdev->dev, "invalid resource type\n");
-		ret = -ENODEV;
-		goto bail;
-	}
-
-	if (!request_mem_region(pdev->resource[0].start,
-		pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) {
-		dev_dbg(&pdev->dev, "request_mem_region failed\n");
-		ret = -EBUSY;
-		goto bail;
-	}
-
-	if (!request_mem_region(pdev->resource[1].start,
-		pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) {
-		dev_dbg(&pdev->dev, "request_mem_region failed\n");
-		ret = -EBUSY;
-		goto bail;
-	}
-
-	info = framebuffer_alloc(sizeof(struct s1d13xxxfb_par) + sizeof(u32) * 256, &pdev->dev);
-	if (!info) {
-		ret = -ENOMEM;
-		goto bail;
-	}
-
-	platform_set_drvdata(pdev, info);
-	default_par = info->par;
-	default_par->regs = ioremap_nocache(pdev->resource[1].start,
-			pdev->resource[1].end - pdev->resource[1].start +1);
-	if (!default_par->regs) {
-		printk(KERN_ERR PFX "unable to map registers\n");
-		ret = -ENOMEM;
-		goto bail;
-	}
-	info->pseudo_palette = default_par->pseudo_palette;
-
-	info->screen_base = ioremap_nocache(pdev->resource[0].start,
-			pdev->resource[0].end - pdev->resource[0].start +1);
-
-	if (!info->screen_base) {
-		printk(KERN_ERR PFX "unable to map framebuffer\n");
-		ret = -ENOMEM;
-		goto bail;
-	}
-
-	/* production id is top 6 bits */
-	prod_id = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
-	/* revision id is lower 2 bits */
-	revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) & 0x3;
-	ret = -ENODEV;
-
-	for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_prod_ids); i++) {
-		if (prod_id == s1d13xxxfb_prod_ids[i]) {
-			/* looks like we got it in our list */
-			default_par->prod_id = prod_id;
-			default_par->revision = revision;
-			ret = 0;
-			break;
-		}
-	}
-
-	if (!ret) {
-		printk(KERN_INFO PFX "chip production id %i = %s\n",
-			prod_id, s1d13xxxfb_prod_names[i]);
-		printk(KERN_INFO PFX "chip revision %i\n", revision);
-	} else {
-		printk(KERN_INFO PFX
-			"unknown chip production id %i, revision %i\n",
-			prod_id, revision);
-		printk(KERN_INFO PFX "please contact maintainer\n");
-		goto bail;
-	}
-
-	info->fix = s1d13xxxfb_fix;
-	info->fix.mmio_start = pdev->resource[1].start;
-	info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start + 1;
-	info->fix.smem_start = pdev->resource[0].start;
-	info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-
-	printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n",
-	       default_par->regs, info->fix.smem_len / 1024, info->screen_base);
-
-	info->par = default_par;
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	info->fbops = &s1d13xxxfb_fbops;
-
-	switch(prod_id) {
-	case S1D13506_PROD_ID:	/* activate acceleration */
-		s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill;
-		s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea;
-		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
-			FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
-		break;
-	default:
-		break;
-	}
-
-	/* perform "manual" chip initialization, if needed */
-	if (pdata && pdata->initregs)
-		s1d13xxxfb_runinit(info->par, pdata->initregs, pdata->initregssize);
-
-	s1d13xxxfb_fetch_hw_state(info);
-
-	if (register_framebuffer(info) < 0) {
-		ret = -EINVAL;
-		goto bail;
-	}
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	return 0;
-
-bail:
-	s1d13xxxfb_remove(pdev);
-	return ret;
-
-}
-
-#ifdef CONFIG_PM
-static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct s1d13xxxfb_par *s1dfb = info->par;
-	struct s1d13xxxfb_pdata *pdata = NULL;
-
-	/* disable display */
-	lcd_enable(s1dfb, 0);
-	crt_enable(s1dfb, 0);
-
-	if (dev_get_platdata(&dev->dev))
-		pdata = dev_get_platdata(&dev->dev);
-
-#if 0
-	if (!s1dfb->disp_save)
-		s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
-
-	if (!s1dfb->disp_save) {
-		printk(KERN_ERR PFX "no memory to save screen");
-		return -ENOMEM;
-	}
-
-	memcpy_fromio(s1dfb->disp_save, info->screen_base, info->fix.smem_len);
-#else
-	s1dfb->disp_save = NULL;
-#endif
-
-	if (!s1dfb->regs_save)
-		s1dfb->regs_save = kmalloc(info->fix.mmio_len, GFP_KERNEL);
-
-	if (!s1dfb->regs_save) {
-		printk(KERN_ERR PFX "no memory to save registers");
-		return -ENOMEM;
-	}
-
-	/* backup all registers */
-	memcpy_fromio(s1dfb->regs_save, s1dfb->regs, info->fix.mmio_len);
-
-	/* now activate power save mode */
-	s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x11);
-
-	if (pdata && pdata->platform_suspend_video)
-		return pdata->platform_suspend_video();
-	else
-		return 0;
-}
-
-static int s1d13xxxfb_resume(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct s1d13xxxfb_par *s1dfb = info->par;
-	struct s1d13xxxfb_pdata *pdata = NULL;
-
-	/* awaken the chip */
-	s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
-
-	/* do not let go until SDRAM "wakes up" */
-	while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
-		udelay(10);
-
-	if (dev_get_platdata(&dev->dev))
-		pdata = dev_get_platdata(&dev->dev);
-
-	if (s1dfb->regs_save) {
-		/* will write RO regs, *should* get away with it :) */
-		memcpy_toio(s1dfb->regs, s1dfb->regs_save, info->fix.mmio_len);
-		kfree(s1dfb->regs_save);
-	}
-
-	if (s1dfb->disp_save) {
-		memcpy_toio(info->screen_base, s1dfb->disp_save,
-				info->fix.smem_len);
-		kfree(s1dfb->disp_save);	/* XXX kmalloc()'d when? */
-	}
-
-	if ((s1dfb->display & 0x01) != 0)
-		lcd_enable(s1dfb, 1);
-	if ((s1dfb->display & 0x02) != 0)
-		crt_enable(s1dfb, 1);
-
-	if (pdata && pdata->platform_resume_video)
-		return pdata->platform_resume_video();
-	else
-		return 0;
-}
-#endif /* CONFIG_PM */
-
-static struct platform_driver s1d13xxxfb_driver = {
-	.probe		= s1d13xxxfb_probe,
-	.remove		= s1d13xxxfb_remove,
-#ifdef CONFIG_PM
-	.suspend	= s1d13xxxfb_suspend,
-	.resume		= s1d13xxxfb_resume,
-#endif
-	.driver		= {
-		.name	= S1D_DEVICENAME,
-	},
-};
-
-
-static int __init
-s1d13xxxfb_init(void)
-{
-
-#ifndef MODULE
-	if (fb_get_options("s1d13xxxfb", NULL))
-		return -ENODEV;
-#endif
-
-	return platform_driver_register(&s1d13xxxfb_driver);
-}
-
-
-static void __exit
-s1d13xxxfb_exit(void)
-{
-	platform_driver_unregister(&s1d13xxxfb_driver);
-}
-
-module_init(s1d13xxxfb_init);
-module_exit(s1d13xxxfb_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Framebuffer driver for S1D13xxx devices");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Thibaut VARENE <varenet@parisc-linux.org>");
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
deleted file mode 100644
index 62acae2694a9..000000000000
--- a/drivers/video/s3c-fb.c
+++ /dev/null
@@ -1,2049 +0,0 @@
-/* linux/drivers/video/s3c-fb.c
- *
- * Copyright 2008 Openmoko Inc.
- * Copyright 2008-2010 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Samsung SoC Framebuffer driver
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software FoundatIon.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/fb.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/interrupt.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_data/video_s3c.h>
-
-#include <video/samsung_fimd.h>
-
-/* This driver will export a number of framebuffer interfaces depending
- * on the configuration passed in via the platform data. Each fb instance
- * maps to a hardware window. Currently there is no support for runtime
- * setting of the alpha-blending functions that each window has, so only
- * window 0 is actually useful.
- *
- * Window 0 is treated specially, it is used for the basis of the LCD
- * output timings and as the control for the output power-down state.
-*/
-
-/* note, the previous use of <mach/regs-fb.h> to get platform specific data
- * has been replaced by using the platform device name to pick the correct
- * configuration data for the system.
-*/
-
-#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
-#undef writel
-#define writel(v, r) do { \
-	pr_debug("%s: %08x => %p\n", __func__, (unsigned int)v, r); \
-	__raw_writel(v, r); \
-} while (0)
-#endif /* FB_S3C_DEBUG_REGWRITE */
-
-/* irq_flags bits */
-#define S3C_FB_VSYNC_IRQ_EN	0
-
-#define VSYNC_TIMEOUT_MSEC 50
-
-struct s3c_fb;
-
-#define VALID_BPP(x) (1 << ((x) - 1))
-
-#define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride))
-#define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00)
-#define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04)
-#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
-#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
-
-/**
- * struct s3c_fb_variant - fb variant information
- * @is_2443: Set if S3C2443/S3C2416 style hardware.
- * @nr_windows: The number of windows.
- * @vidtcon: The base for the VIDTCONx registers
- * @wincon: The base for the WINxCON registers.
- * @winmap: The base for the WINxMAP registers.
- * @keycon: The abse for the WxKEYCON registers.
- * @buf_start: Offset of buffer start registers.
- * @buf_size: Offset of buffer size registers.
- * @buf_end: Offset of buffer end registers.
- * @osd: The base for the OSD registers.
- * @palette: Address of palette memory, or 0 if none.
- * @has_prtcon: Set if has PRTCON register.
- * @has_shadowcon: Set if has SHADOWCON register.
- * @has_blendcon: Set if has BLENDCON register.
- * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
- * @has_fixvclk: Set if VIDCON1 register has FIXVCLK bits.
- */
-struct s3c_fb_variant {
-	unsigned int	is_2443:1;
-	unsigned short	nr_windows;
-	unsigned int	vidtcon;
-	unsigned short	wincon;
-	unsigned short	winmap;
-	unsigned short	keycon;
-	unsigned short	buf_start;
-	unsigned short	buf_end;
-	unsigned short	buf_size;
-	unsigned short	osd;
-	unsigned short	osd_stride;
-	unsigned short	palette[S3C_FB_MAX_WIN];
-
-	unsigned int	has_prtcon:1;
-	unsigned int	has_shadowcon:1;
-	unsigned int	has_blendcon:1;
-	unsigned int	has_clksel:1;
-	unsigned int	has_fixvclk:1;
-};
-
-/**
- * struct s3c_fb_win_variant
- * @has_osd_c: Set if has OSD C register.
- * @has_osd_d: Set if has OSD D register.
- * @has_osd_alpha: Set if can change alpha transparency for a window.
- * @palette_sz: Size of palette in entries.
- * @palette_16bpp: Set if palette is 16bits wide.
- * @osd_size_off: If != 0, supports setting up OSD for a window; the appropriate
- *                register is located at the given offset from OSD_BASE.
- * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel.
- *
- * valid_bpp bit x is set if (x+1)BPP is supported.
- */
-struct s3c_fb_win_variant {
-	unsigned int	has_osd_c:1;
-	unsigned int	has_osd_d:1;
-	unsigned int	has_osd_alpha:1;
-	unsigned int	palette_16bpp:1;
-	unsigned short	osd_size_off;
-	unsigned short	palette_sz;
-	u32		valid_bpp;
-};
-
-/**
- * struct s3c_fb_driverdata - per-device type driver data for init time.
- * @variant: The variant information for this driver.
- * @win: The window information for each window.
- */
-struct s3c_fb_driverdata {
-	struct s3c_fb_variant	variant;
-	struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN];
-};
-
-/**
- * struct s3c_fb_palette - palette information
- * @r: Red bitfield.
- * @g: Green bitfield.
- * @b: Blue bitfield.
- * @a: Alpha bitfield.
- */
-struct s3c_fb_palette {
-	struct fb_bitfield	r;
-	struct fb_bitfield	g;
-	struct fb_bitfield	b;
-	struct fb_bitfield	a;
-};
-
-/**
- * struct s3c_fb_win - per window private data for each framebuffer.
- * @windata: The platform data supplied for the window configuration.
- * @parent: The hardware that this window is part of.
- * @fbinfo: Pointer pack to the framebuffer info for this window.
- * @varint: The variant information for this window.
- * @palette_buffer: Buffer/cache to hold palette entries.
- * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
- * @index: The window number of this window.
- * @palette: The bitfields for changing r/g/b into a hardware palette entry.
- */
-struct s3c_fb_win {
-	struct s3c_fb_pd_win	*windata;
-	struct s3c_fb		*parent;
-	struct fb_info		*fbinfo;
-	struct s3c_fb_palette	 palette;
-	struct s3c_fb_win_variant variant;
-
-	u32			*palette_buffer;
-	u32			 pseudo_palette[16];
-	unsigned int		 index;
-};
-
-/**
- * struct s3c_fb_vsync - vsync information
- * @wait:	a queue for processes waiting for vsync
- * @count:	vsync interrupt count
- */
-struct s3c_fb_vsync {
-	wait_queue_head_t	wait;
-	unsigned int		count;
-};
-
-/**
- * struct s3c_fb - overall hardware state of the hardware
- * @slock: The spinlock protection for this data structure.
- * @dev: The device that we bound to, for printing, etc.
- * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
- * @lcd_clk: The clk (sclk) feeding pixclk.
- * @regs: The mapped hardware registers.
- * @variant: Variant information for this hardware.
- * @enabled: A bitmask of enabled hardware windows.
- * @output_on: Flag if the physical output is enabled.
- * @pdata: The platform configuration data passed with the device.
- * @windows: The hardware windows that have been claimed.
- * @irq_no: IRQ line number
- * @irq_flags: irq flags
- * @vsync_info: VSYNC-related information (count, queues...)
- */
-struct s3c_fb {
-	spinlock_t		slock;
-	struct device		*dev;
-	struct clk		*bus_clk;
-	struct clk		*lcd_clk;
-	void __iomem		*regs;
-	struct s3c_fb_variant	 variant;
-
-	unsigned char		 enabled;
-	bool			 output_on;
-
-	struct s3c_fb_platdata	*pdata;
-	struct s3c_fb_win	*windows[S3C_FB_MAX_WIN];
-
-	int			 irq_no;
-	unsigned long		 irq_flags;
-	struct s3c_fb_vsync	 vsync_info;
-};
-
-/**
- * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
- * @win: The device window.
- * @bpp: The bit depth.
- */
-static bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp)
-{
-	return win->variant.valid_bpp & VALID_BPP(bpp);
-}
-
-/**
- * s3c_fb_check_var() - framebuffer layer request to verify a given mode.
- * @var: The screen information to verify.
- * @info: The framebuffer device.
- *
- * Framebuffer layer call to verify the given information and allow us to
- * update various information depending on the hardware capabilities.
- */
-static int s3c_fb_check_var(struct fb_var_screeninfo *var,
-			    struct fb_info *info)
-{
-	struct s3c_fb_win *win = info->par;
-	struct s3c_fb *sfb = win->parent;
-
-	dev_dbg(sfb->dev, "checking parameters\n");
-
-	var->xres_virtual = max(var->xres_virtual, var->xres);
-	var->yres_virtual = max(var->yres_virtual, var->yres);
-
-	if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
-		dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
-			win->index, var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	/* always ensure these are zero, for drop through cases below */
-	var->transp.offset = 0;
-	var->transp.length = 0;
-
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-		if (sfb->variant.palette[win->index] != 0) {
-			/* non palletised, A:1,R:2,G:3,B:2 mode */
-			var->red.offset		= 5;
-			var->green.offset	= 2;
-			var->blue.offset	= 0;
-			var->red.length		= 2;
-			var->green.length	= 3;
-			var->blue.length	= 2;
-			var->transp.offset	= 7;
-			var->transp.length	= 1;
-		} else {
-			var->red.offset	= 0;
-			var->red.length	= var->bits_per_pixel;
-			var->green	= var->red;
-			var->blue	= var->red;
-		}
-		break;
-
-	case 19:
-		/* 666 with one bit alpha/transparency */
-		var->transp.offset	= 18;
-		var->transp.length	= 1;
-		/* drop through */
-	case 18:
-		var->bits_per_pixel	= 32;
-
-		/* 666 format */
-		var->red.offset		= 12;
-		var->green.offset	= 6;
-		var->blue.offset	= 0;
-		var->red.length		= 6;
-		var->green.length	= 6;
-		var->blue.length	= 6;
-		break;
-
-	case 16:
-		/* 16 bpp, 565 format */
-		var->red.offset		= 11;
-		var->green.offset	= 5;
-		var->blue.offset	= 0;
-		var->red.length		= 5;
-		var->green.length	= 6;
-		var->blue.length	= 5;
-		break;
-
-	case 32:
-	case 28:
-	case 25:
-		var->transp.length	= var->bits_per_pixel - 24;
-		var->transp.offset	= 24;
-		/* drop through */
-	case 24:
-		/* our 24bpp is unpacked, so 32bpp */
-		var->bits_per_pixel	= 32;
-		var->red.offset		= 16;
-		var->red.length		= 8;
-		var->green.offset	= 8;
-		var->green.length	= 8;
-		var->blue.offset	= 0;
-		var->blue.length	= 8;
-		break;
-
-	default:
-		dev_err(sfb->dev, "invalid bpp\n");
-		return -EINVAL;
-	}
-
-	dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
-	return 0;
-}
-
-/**
- * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
- * @sfb: The hardware state.
- * @pixclock: The pixel clock wanted, in picoseconds.
- *
- * Given the specified pixel clock, work out the necessary divider to get
- * close to the output frequency.
- */
-static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
-{
-	unsigned long clk;
-	unsigned long long tmp;
-	unsigned int result;
-
-	if (sfb->variant.has_clksel)
-		clk = clk_get_rate(sfb->bus_clk);
-	else
-		clk = clk_get_rate(sfb->lcd_clk);
-
-	tmp = (unsigned long long)clk;
-	tmp *= pixclk;
-
-	do_div(tmp, 1000000000UL);
-	result = (unsigned int)tmp / 1000;
-
-	dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
-		pixclk, clk, result, result ? clk / result : clk);
-
-	return result;
-}
-
-/**
- * s3c_fb_align_word() - align pixel count to word boundary
- * @bpp: The number of bits per pixel
- * @pix: The value to be aligned.
- *
- * Align the given pixel count so that it will start on an 32bit word
- * boundary.
- */
-static int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
-{
-	int pix_per_word;
-
-	if (bpp > 16)
-		return pix;
-
-	pix_per_word = (8 * 32) / bpp;
-	return ALIGN(pix, pix_per_word);
-}
-
-/**
- * vidosd_set_size() - set OSD size for a window
- *
- * @win: the window to set OSD size for
- * @size: OSD size register value
- */
-static void vidosd_set_size(struct s3c_fb_win *win, u32 size)
-{
-	struct s3c_fb *sfb = win->parent;
-
-	/* OSD can be set up if osd_size_off != 0 for this window */
-	if (win->variant.osd_size_off)
-		writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant)
-				+ win->variant.osd_size_off);
-}
-
-/**
- * vidosd_set_alpha() - set alpha transparency for a window
- *
- * @win: the window to set OSD size for
- * @alpha: alpha register value
- */
-static void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha)
-{
-	struct s3c_fb *sfb = win->parent;
-
-	if (win->variant.has_osd_alpha)
-		writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant));
-}
-
-/**
- * shadow_protect_win() - disable updating values from shadow registers at vsync
- *
- * @win: window to protect registers for
- * @protect: 1 to protect (disable updates)
- */
-static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
-{
-	struct s3c_fb *sfb = win->parent;
-	u32 reg;
-
-	if (protect) {
-		if (sfb->variant.has_prtcon) {
-			writel(PRTCON_PROTECT, sfb->regs + PRTCON);
-		} else if (sfb->variant.has_shadowcon) {
-			reg = readl(sfb->regs + SHADOWCON);
-			writel(reg | SHADOWCON_WINx_PROTECT(win->index),
-				sfb->regs + SHADOWCON);
-		}
-	} else {
-		if (sfb->variant.has_prtcon) {
-			writel(0, sfb->regs + PRTCON);
-		} else if (sfb->variant.has_shadowcon) {
-			reg = readl(sfb->regs + SHADOWCON);
-			writel(reg & ~SHADOWCON_WINx_PROTECT(win->index),
-				sfb->regs + SHADOWCON);
-		}
-	}
-}
-
-/**
- * s3c_fb_enable() - Set the state of the main LCD output
- * @sfb: The main framebuffer state.
- * @enable: The state to set.
- */
-static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
-{
-	u32 vidcon0 = readl(sfb->regs + VIDCON0);
-
-	if (enable && !sfb->output_on)
-		pm_runtime_get_sync(sfb->dev);
-
-	if (enable) {
-		vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
-	} else {
-		/* see the note in the framebuffer datasheet about
-		 * why you cannot take both of these bits down at the
-		 * same time. */
-
-		if (vidcon0 & VIDCON0_ENVID) {
-			vidcon0 |= VIDCON0_ENVID;
-			vidcon0 &= ~VIDCON0_ENVID_F;
-		}
-	}
-
-	writel(vidcon0, sfb->regs + VIDCON0);
-
-	if (!enable && sfb->output_on)
-		pm_runtime_put_sync(sfb->dev);
-
-	sfb->output_on = enable;
-}
-
-/**
- * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
- * @info: The framebuffer to change.
- *
- * Framebuffer layer request to set a new mode for the specified framebuffer
- */
-static int s3c_fb_set_par(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-	struct s3c_fb_win *win = info->par;
-	struct s3c_fb *sfb = win->parent;
-	void __iomem *regs = sfb->regs;
-	void __iomem *buf = regs;
-	int win_no = win->index;
-	u32 alpha = 0;
-	u32 data;
-	u32 pagewidth;
-
-	dev_dbg(sfb->dev, "setting framebuffer parameters\n");
-
-	pm_runtime_get_sync(sfb->dev);
-
-	shadow_protect_win(win, 1);
-
-	switch (var->bits_per_pixel) {
-	case 32:
-	case 24:
-	case 16:
-	case 12:
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	case 8:
-		if (win->variant.palette_sz >= 256)
-			info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		else
-			info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	case 1:
-		info->fix.visual = FB_VISUAL_MONO01;
-		break;
-	default:
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	}
-
-	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
-
-	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
-	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
-
-	/* disable the window whilst we update it */
-	writel(0, regs + WINCON(win_no));
-
-	if (!sfb->output_on)
-		s3c_fb_enable(sfb, 1);
-
-	/* write the buffer address */
-
-	/* start and end registers stride is 8 */
-	buf = regs + win_no * 8;
-
-	writel(info->fix.smem_start, buf + sfb->variant.buf_start);
-
-	data = info->fix.smem_start + info->fix.line_length * var->yres;
-	writel(data, buf + sfb->variant.buf_end);
-
-	pagewidth = (var->xres * var->bits_per_pixel) >> 3;
-	data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
-	       VIDW_BUF_SIZE_PAGEWIDTH(pagewidth) |
-	       VIDW_BUF_SIZE_OFFSET_E(info->fix.line_length - pagewidth) |
-	       VIDW_BUF_SIZE_PAGEWIDTH_E(pagewidth);
-	writel(data, regs + sfb->variant.buf_size + (win_no * 4));
-
-	/* write 'OSD' registers to control position of framebuffer */
-
-	data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0) |
-	       VIDOSDxA_TOPLEFT_X_E(0) | VIDOSDxA_TOPLEFT_Y_E(0);
-	writel(data, regs + VIDOSD_A(win_no, sfb->variant));
-
-	data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
-						     var->xres - 1)) |
-	       VIDOSDxB_BOTRIGHT_Y(var->yres - 1) |
-	       VIDOSDxB_BOTRIGHT_X_E(s3c_fb_align_word(var->bits_per_pixel,
-						     var->xres - 1)) |
-	       VIDOSDxB_BOTRIGHT_Y_E(var->yres - 1);
-
-	writel(data, regs + VIDOSD_B(win_no, sfb->variant));
-
-	data = var->xres * var->yres;
-
-	alpha = VIDISD14C_ALPHA1_R(0xf) |
-		VIDISD14C_ALPHA1_G(0xf) |
-		VIDISD14C_ALPHA1_B(0xf);
-
-	vidosd_set_alpha(win, alpha);
-	vidosd_set_size(win, data);
-
-	/* Enable DMA channel for this window */
-	if (sfb->variant.has_shadowcon) {
-		data = readl(sfb->regs + SHADOWCON);
-		data |= SHADOWCON_CHx_ENABLE(win_no);
-		writel(data, sfb->regs + SHADOWCON);
-	}
-
-	data = WINCONx_ENWIN;
-	sfb->enabled |= (1 << win->index);
-
-	/* note, since we have to round up the bits-per-pixel, we end up
-	 * relying on the bitfield information for r/g/b/a to work out
-	 * exactly which mode of operation is intended. */
-
-	switch (var->bits_per_pixel) {
-	case 1:
-		data |= WINCON0_BPPMODE_1BPP;
-		data |= WINCONx_BITSWP;
-		data |= WINCONx_BURSTLEN_4WORD;
-		break;
-	case 2:
-		data |= WINCON0_BPPMODE_2BPP;
-		data |= WINCONx_BITSWP;
-		data |= WINCONx_BURSTLEN_8WORD;
-		break;
-	case 4:
-		data |= WINCON0_BPPMODE_4BPP;
-		data |= WINCONx_BITSWP;
-		data |= WINCONx_BURSTLEN_8WORD;
-		break;
-	case 8:
-		if (var->transp.length != 0)
-			data |= WINCON1_BPPMODE_8BPP_1232;
-		else
-			data |= WINCON0_BPPMODE_8BPP_PALETTE;
-		data |= WINCONx_BURSTLEN_8WORD;
-		data |= WINCONx_BYTSWP;
-		break;
-	case 16:
-		if (var->transp.length != 0)
-			data |= WINCON1_BPPMODE_16BPP_A1555;
-		else
-			data |= WINCON0_BPPMODE_16BPP_565;
-		data |= WINCONx_HAWSWP;
-		data |= WINCONx_BURSTLEN_16WORD;
-		break;
-	case 24:
-	case 32:
-		if (var->red.length == 6) {
-			if (var->transp.length != 0)
-				data |= WINCON1_BPPMODE_19BPP_A1666;
-			else
-				data |= WINCON1_BPPMODE_18BPP_666;
-		} else if (var->transp.length == 1)
-			data |= WINCON1_BPPMODE_25BPP_A1888
-				| WINCON1_BLD_PIX;
-		else if ((var->transp.length == 4) ||
-			(var->transp.length == 8))
-			data |= WINCON1_BPPMODE_28BPP_A4888
-				| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
-		else
-			data |= WINCON0_BPPMODE_24BPP_888;
-
-		data |= WINCONx_WSWP;
-		data |= WINCONx_BURSTLEN_16WORD;
-		break;
-	}
-
-	/* Enable the colour keying for the window below this one */
-	if (win_no > 0) {
-		u32 keycon0_data = 0, keycon1_data = 0;
-		void __iomem *keycon = regs + sfb->variant.keycon;
-
-		keycon0_data = ~(WxKEYCON0_KEYBL_EN |
-				WxKEYCON0_KEYEN_F |
-				WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
-
-		keycon1_data = WxKEYCON1_COLVAL(0xffffff);
-
-		keycon += (win_no - 1) * 8;
-
-		writel(keycon0_data, keycon + WKEYCON0);
-		writel(keycon1_data, keycon + WKEYCON1);
-	}
-
-	writel(data, regs + sfb->variant.wincon + (win_no * 4));
-	writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
-
-	/* Set alpha value width */
-	if (sfb->variant.has_blendcon) {
-		data = readl(sfb->regs + BLENDCON);
-		data &= ~BLENDCON_NEW_MASK;
-		if (var->transp.length > 4)
-			data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
-		else
-			data |= BLENDCON_NEW_4BIT_ALPHA_VALUE;
-		writel(data, sfb->regs + BLENDCON);
-	}
-
-	shadow_protect_win(win, 0);
-
-	pm_runtime_put_sync(sfb->dev);
-
-	return 0;
-}
-
-/**
- * s3c_fb_update_palette() - set or schedule a palette update.
- * @sfb: The hardware information.
- * @win: The window being updated.
- * @reg: The palette index being changed.
- * @value: The computed palette value.
- *
- * Change the value of a palette register, either by directly writing to
- * the palette (this requires the palette RAM to be disconnected from the
- * hardware whilst this is in progress) or schedule the update for later.
- *
- * At the moment, since we have no VSYNC interrupt support, we simply set
- * the palette entry directly.
- */
-static void s3c_fb_update_palette(struct s3c_fb *sfb,
-				  struct s3c_fb_win *win,
-				  unsigned int reg,
-				  u32 value)
-{
-	void __iomem *palreg;
-	u32 palcon;
-
-	palreg = sfb->regs + sfb->variant.palette[win->index];
-
-	dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
-		__func__, win->index, reg, palreg, value);
-
-	win->palette_buffer[reg] = value;
-
-	palcon = readl(sfb->regs + WPALCON);
-	writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
-
-	if (win->variant.palette_16bpp)
-		writew(value, palreg + (reg * 2));
-	else
-		writel(value, palreg + (reg * 4));
-
-	writel(palcon, sfb->regs + WPALCON);
-}
-
-static inline unsigned int chan_to_field(unsigned int chan,
-					 struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-/**
- * s3c_fb_setcolreg() - framebuffer layer request to change palette.
- * @regno: The palette index to change.
- * @red: The red field for the palette data.
- * @green: The green field for the palette data.
- * @blue: The blue field for the palette data.
- * @trans: The transparency (alpha) field for the palette data.
- * @info: The framebuffer being changed.
- */
-static int s3c_fb_setcolreg(unsigned regno,
-			    unsigned red, unsigned green, unsigned blue,
-			    unsigned transp, struct fb_info *info)
-{
-	struct s3c_fb_win *win = info->par;
-	struct s3c_fb *sfb = win->parent;
-	unsigned int val;
-
-	dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
-		__func__, win->index, regno, red, green, blue);
-
-	pm_runtime_get_sync(sfb->dev);
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/* true-colour, use pseudo-palette */
-
-		if (regno < 16) {
-			u32 *pal = info->pseudo_palette;
-
-			val  = chan_to_field(red,   &info->var.red);
-			val |= chan_to_field(green, &info->var.green);
-			val |= chan_to_field(blue,  &info->var.blue);
-
-			pal[regno] = val;
-		}
-		break;
-
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno < win->variant.palette_sz) {
-			val  = chan_to_field(red, &win->palette.r);
-			val |= chan_to_field(green, &win->palette.g);
-			val |= chan_to_field(blue, &win->palette.b);
-
-			s3c_fb_update_palette(sfb, win, regno, val);
-		}
-
-		break;
-
-	default:
-		pm_runtime_put_sync(sfb->dev);
-		return 1;	/* unknown type */
-	}
-
-	pm_runtime_put_sync(sfb->dev);
-	return 0;
-}
-
-/**
- * s3c_fb_blank() - blank or unblank the given window
- * @blank_mode: The blank state from FB_BLANK_*
- * @info: The framebuffer to blank.
- *
- * Framebuffer layer request to change the power state.
- */
-static int s3c_fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct s3c_fb_win *win = info->par;
-	struct s3c_fb *sfb = win->parent;
-	unsigned int index = win->index;
-	u32 wincon;
-	u32 output_on = sfb->output_on;
-
-	dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
-
-	pm_runtime_get_sync(sfb->dev);
-
-	wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
-
-	switch (blank_mode) {
-	case FB_BLANK_POWERDOWN:
-		wincon &= ~WINCONx_ENWIN;
-		sfb->enabled &= ~(1 << index);
-		/* fall through to FB_BLANK_NORMAL */
-
-	case FB_BLANK_NORMAL:
-		/* disable the DMA and display 0x0 (black) */
-		shadow_protect_win(win, 1);
-		writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
-		       sfb->regs + sfb->variant.winmap + (index * 4));
-		shadow_protect_win(win, 0);
-		break;
-
-	case FB_BLANK_UNBLANK:
-		shadow_protect_win(win, 1);
-		writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
-		shadow_protect_win(win, 0);
-		wincon |= WINCONx_ENWIN;
-		sfb->enabled |= (1 << index);
-		break;
-
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	default:
-		pm_runtime_put_sync(sfb->dev);
-		return 1;
-	}
-
-	shadow_protect_win(win, 1);
-	writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
-
-	/* Check the enabled state to see if we need to be running the
-	 * main LCD interface, as if there are no active windows then
-	 * it is highly likely that we also do not need to output
-	 * anything.
-	 */
-	s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
-	shadow_protect_win(win, 0);
-
-	pm_runtime_put_sync(sfb->dev);
-
-	return output_on == sfb->output_on;
-}
-
-/**
- * s3c_fb_pan_display() - Pan the display.
- *
- * Note that the offsets can be written to the device at any time, as their
- * values are latched at each vsync automatically. This also means that only
- * the last call to this function will have any effect on next vsync, but
- * there is no need to sleep waiting for it to prevent tearing.
- *
- * @var: The screen information to verify.
- * @info: The framebuffer device.
- */
-static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct s3c_fb_win *win	= info->par;
-	struct s3c_fb *sfb	= win->parent;
-	void __iomem *buf	= sfb->regs + win->index * 8;
-	unsigned int start_boff, end_boff;
-
-	pm_runtime_get_sync(sfb->dev);
-
-	/* Offset in bytes to the start of the displayed area */
-	start_boff = var->yoffset * info->fix.line_length;
-	/* X offset depends on the current bpp */
-	if (info->var.bits_per_pixel >= 8) {
-		start_boff += var->xoffset * (info->var.bits_per_pixel >> 3);
-	} else {
-		switch (info->var.bits_per_pixel) {
-		case 4:
-			start_boff += var->xoffset >> 1;
-			break;
-		case 2:
-			start_boff += var->xoffset >> 2;
-			break;
-		case 1:
-			start_boff += var->xoffset >> 3;
-			break;
-		default:
-			dev_err(sfb->dev, "invalid bpp\n");
-			pm_runtime_put_sync(sfb->dev);
-			return -EINVAL;
-		}
-	}
-	/* Offset in bytes to the end of the displayed area */
-	end_boff = start_boff + info->var.yres * info->fix.line_length;
-
-	/* Temporarily turn off per-vsync update from shadow registers until
-	 * both start and end addresses are updated to prevent corruption */
-	shadow_protect_win(win, 1);
-
-	writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start);
-	writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end);
-
-	shadow_protect_win(win, 0);
-
-	pm_runtime_put_sync(sfb->dev);
-	return 0;
-}
-
-/**
- * s3c_fb_enable_irq() - enable framebuffer interrupts
- * @sfb: main hardware state
- */
-static void s3c_fb_enable_irq(struct s3c_fb *sfb)
-{
-	void __iomem *regs = sfb->regs;
-	u32 irq_ctrl_reg;
-
-	if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
-		/* IRQ disabled, enable it */
-		irq_ctrl_reg = readl(regs + VIDINTCON0);
-
-		irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
-		irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
-
-		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
-		irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
-		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
-		irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
-
-		writel(irq_ctrl_reg, regs + VIDINTCON0);
-	}
-}
-
-/**
- * s3c_fb_disable_irq() - disable framebuffer interrupts
- * @sfb: main hardware state
- */
-static void s3c_fb_disable_irq(struct s3c_fb *sfb)
-{
-	void __iomem *regs = sfb->regs;
-	u32 irq_ctrl_reg;
-
-	if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
-		/* IRQ enabled, disable it */
-		irq_ctrl_reg = readl(regs + VIDINTCON0);
-
-		irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
-		irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
-
-		writel(irq_ctrl_reg, regs + VIDINTCON0);
-	}
-}
-
-static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
-{
-	struct s3c_fb *sfb = dev_id;
-	void __iomem  *regs = sfb->regs;
-	u32 irq_sts_reg;
-
-	spin_lock(&sfb->slock);
-
-	irq_sts_reg = readl(regs + VIDINTCON1);
-
-	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
-
-		/* VSYNC interrupt, accept it */
-		writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
-
-		sfb->vsync_info.count++;
-		wake_up_interruptible(&sfb->vsync_info.wait);
-	}
-
-	/* We only support waiting for VSYNC for now, so it's safe
-	 * to always disable irqs here.
-	 */
-	s3c_fb_disable_irq(sfb);
-
-	spin_unlock(&sfb->slock);
-	return IRQ_HANDLED;
-}
-
-/**
- * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
- * @sfb: main hardware state
- * @crtc: head index.
- */
-static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
-{
-	unsigned long count;
-	int ret;
-
-	if (crtc != 0)
-		return -ENODEV;
-
-	pm_runtime_get_sync(sfb->dev);
-
-	count = sfb->vsync_info.count;
-	s3c_fb_enable_irq(sfb);
-	ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
-				       count != sfb->vsync_info.count,
-				       msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
-
-	pm_runtime_put_sync(sfb->dev);
-
-	if (ret == 0)
-		return -ETIMEDOUT;
-
-	return 0;
-}
-
-static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
-			unsigned long arg)
-{
-	struct s3c_fb_win *win = info->par;
-	struct s3c_fb *sfb = win->parent;
-	int ret;
-	u32 crtc;
-
-	switch (cmd) {
-	case FBIO_WAITFORVSYNC:
-		if (get_user(crtc, (u32 __user *)arg)) {
-			ret = -EFAULT;
-			break;
-		}
-
-		ret = s3c_fb_wait_for_vsync(sfb, crtc);
-		break;
-	default:
-		ret = -ENOTTY;
-	}
-
-	return ret;
-}
-
-static struct fb_ops s3c_fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= s3c_fb_check_var,
-	.fb_set_par	= s3c_fb_set_par,
-	.fb_blank	= s3c_fb_blank,
-	.fb_setcolreg	= s3c_fb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_pan_display	= s3c_fb_pan_display,
-	.fb_ioctl	= s3c_fb_ioctl,
-};
-
-/**
- * s3c_fb_missing_pixclock() - calculates pixel clock
- * @mode: The video mode to change.
- *
- * Calculate the pixel clock when none has been given through platform data.
- */
-static void s3c_fb_missing_pixclock(struct fb_videomode *mode)
-{
-	u64 pixclk = 1000000000000ULL;
-	u32 div;
-
-	div  = mode->left_margin + mode->hsync_len + mode->right_margin +
-	       mode->xres;
-	div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
-	       mode->yres;
-	div *= mode->refresh ? : 60;
-
-	do_div(pixclk, div);
-
-	mode->pixclock = pixclk;
-}
-
-/**
- * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
- * @sfb: The base resources for the hardware.
- * @win: The window to initialise memory for.
- *
- * Allocate memory for the given framebuffer.
- */
-static int s3c_fb_alloc_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
-{
-	struct s3c_fb_pd_win *windata = win->windata;
-	unsigned int real_size, virt_size, size;
-	struct fb_info *fbi = win->fbinfo;
-	dma_addr_t map_dma;
-
-	dev_dbg(sfb->dev, "allocating memory for display\n");
-
-	real_size = windata->xres * windata->yres;
-	virt_size = windata->virtual_x * windata->virtual_y;
-
-	dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
-		real_size, windata->xres, windata->yres,
-		virt_size, windata->virtual_x, windata->virtual_y);
-
-	size = (real_size > virt_size) ? real_size : virt_size;
-	size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
-	size /= 8;
-
-	fbi->fix.smem_len = size;
-	size = PAGE_ALIGN(size);
-
-	dev_dbg(sfb->dev, "want %u bytes for window\n", size);
-
-	fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,
-						  &map_dma, GFP_KERNEL);
-	if (!fbi->screen_base)
-		return -ENOMEM;
-
-	dev_dbg(sfb->dev, "mapped %x to %p\n",
-		(unsigned int)map_dma, fbi->screen_base);
-
-	memset(fbi->screen_base, 0x0, size);
-	fbi->fix.smem_start = map_dma;
-
-	return 0;
-}
-
-/**
- * s3c_fb_free_memory() - free the display memory for the given window
- * @sfb: The base resources for the hardware.
- * @win: The window to free the display memory for.
- *
- * Free the display memory allocated by s3c_fb_alloc_memory().
- */
-static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
-{
-	struct fb_info *fbi = win->fbinfo;
-
-	if (fbi->screen_base)
-		dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
-			      fbi->screen_base, fbi->fix.smem_start);
-}
-
-/**
- * s3c_fb_release_win() - release resources for a framebuffer window.
- * @win: The window to cleanup the resources for.
- *
- * Release the resources that where claimed for the hardware window,
- * such as the framebuffer instance and any memory claimed for it.
- */
-static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
-{
-	u32 data;
-
-	if (win->fbinfo) {
-		if (sfb->variant.has_shadowcon) {
-			data = readl(sfb->regs + SHADOWCON);
-			data &= ~SHADOWCON_CHx_ENABLE(win->index);
-			data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
-			writel(data, sfb->regs + SHADOWCON);
-		}
-		unregister_framebuffer(win->fbinfo);
-		if (win->fbinfo->cmap.len)
-			fb_dealloc_cmap(&win->fbinfo->cmap);
-		s3c_fb_free_memory(sfb, win);
-		framebuffer_release(win->fbinfo);
-	}
-}
-
-/**
- * s3c_fb_probe_win() - register an hardware window
- * @sfb: The base resources for the hardware
- * @variant: The variant information for this window.
- * @res: Pointer to where to place the resultant window.
- *
- * Allocate and do the basic initialisation for one of the hardware's graphics
- * windows.
- */
-static int s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
-			    struct s3c_fb_win_variant *variant,
-			    struct s3c_fb_win **res)
-{
-	struct fb_var_screeninfo *var;
-	struct fb_videomode initmode;
-	struct s3c_fb_pd_win *windata;
-	struct s3c_fb_win *win;
-	struct fb_info *fbinfo;
-	int palette_size;
-	int ret;
-
-	dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
-
-	init_waitqueue_head(&sfb->vsync_info.wait);
-
-	palette_size = variant->palette_sz * 4;
-
-	fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
-				   palette_size * sizeof(u32), sfb->dev);
-	if (!fbinfo) {
-		dev_err(sfb->dev, "failed to allocate framebuffer\n");
-		return -ENOENT;
-	}
-
-	windata = sfb->pdata->win[win_no];
-	initmode = *sfb->pdata->vtiming;
-
-	WARN_ON(windata->max_bpp == 0);
-	WARN_ON(windata->xres == 0);
-	WARN_ON(windata->yres == 0);
-
-	win = fbinfo->par;
-	*res = win;
-	var = &fbinfo->var;
-	win->variant = *variant;
-	win->fbinfo = fbinfo;
-	win->parent = sfb;
-	win->windata = windata;
-	win->index = win_no;
-	win->palette_buffer = (u32 *)(win + 1);
-
-	ret = s3c_fb_alloc_memory(sfb, win);
-	if (ret) {
-		dev_err(sfb->dev, "failed to allocate display memory\n");
-		return ret;
-	}
-
-	/* setup the r/b/g positions for the window's palette */
-	if (win->variant.palette_16bpp) {
-		/* Set RGB 5:6:5 as default */
-		win->palette.r.offset = 11;
-		win->palette.r.length = 5;
-		win->palette.g.offset = 5;
-		win->palette.g.length = 6;
-		win->palette.b.offset = 0;
-		win->palette.b.length = 5;
-
-	} else {
-		/* Set 8bpp or 8bpp and 1bit alpha */
-		win->palette.r.offset = 16;
-		win->palette.r.length = 8;
-		win->palette.g.offset = 8;
-		win->palette.g.length = 8;
-		win->palette.b.offset = 0;
-		win->palette.b.length = 8;
-	}
-
-	/* setup the initial video mode from the window */
-	initmode.xres = windata->xres;
-	initmode.yres = windata->yres;
-	fb_videomode_to_var(&fbinfo->var, &initmode);
-
-	fbinfo->fix.type	= FB_TYPE_PACKED_PIXELS;
-	fbinfo->fix.accel	= FB_ACCEL_NONE;
-	fbinfo->var.activate	= FB_ACTIVATE_NOW;
-	fbinfo->var.vmode	= FB_VMODE_NONINTERLACED;
-	fbinfo->var.bits_per_pixel = windata->default_bpp;
-	fbinfo->fbops		= &s3c_fb_ops;
-	fbinfo->flags		= FBINFO_FLAG_DEFAULT;
-	fbinfo->pseudo_palette  = &win->pseudo_palette;
-
-	/* prepare to actually start the framebuffer */
-
-	ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
-	if (ret < 0) {
-		dev_err(sfb->dev, "check_var failed on initial video params\n");
-		return ret;
-	}
-
-	/* create initial colour map */
-
-	ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
-	if (ret == 0)
-		fb_set_cmap(&fbinfo->cmap, fbinfo);
-	else
-		dev_err(sfb->dev, "failed to allocate fb cmap\n");
-
-	s3c_fb_set_par(fbinfo);
-
-	dev_dbg(sfb->dev, "about to register framebuffer\n");
-
-	/* run the check_var and set_par on our configuration. */
-
-	ret = register_framebuffer(fbinfo);
-	if (ret < 0) {
-		dev_err(sfb->dev, "failed to register framebuffer\n");
-		return ret;
-	}
-
-	dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
-
-	return 0;
-}
-
-/**
- * s3c_fb_set_rgb_timing() - set video timing for rgb interface.
- * @sfb: The base resources for the hardware.
- *
- * Set horizontal and vertical lcd rgb interface timing.
- */
-static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb)
-{
-	struct fb_videomode *vmode = sfb->pdata->vtiming;
-	void __iomem *regs = sfb->regs;
-	int clkdiv;
-	u32 data;
-
-	if (!vmode->pixclock)
-		s3c_fb_missing_pixclock(vmode);
-
-	clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock);
-
-	data = sfb->pdata->vidcon0;
-	data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
-
-	if (clkdiv > 1)
-		data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
-	else
-		data &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
-
-	if (sfb->variant.is_2443)
-		data |= (1 << 5);
-	writel(data, regs + VIDCON0);
-
-	data = VIDTCON0_VBPD(vmode->upper_margin - 1) |
-	       VIDTCON0_VFPD(vmode->lower_margin - 1) |
-	       VIDTCON0_VSPW(vmode->vsync_len - 1);
-	writel(data, regs + sfb->variant.vidtcon);
-
-	data = VIDTCON1_HBPD(vmode->left_margin - 1) |
-	       VIDTCON1_HFPD(vmode->right_margin - 1) |
-	       VIDTCON1_HSPW(vmode->hsync_len - 1);
-	writel(data, regs + sfb->variant.vidtcon + 4);
-
-	data = VIDTCON2_LINEVAL(vmode->yres - 1) |
-	       VIDTCON2_HOZVAL(vmode->xres - 1) |
-	       VIDTCON2_LINEVAL_E(vmode->yres - 1) |
-	       VIDTCON2_HOZVAL_E(vmode->xres - 1);
-	writel(data, regs + sfb->variant.vidtcon + 8);
-}
-
-/**
- * s3c_fb_clear_win() - clear hardware window registers.
- * @sfb: The base resources for the hardware.
- * @win: The window to process.
- *
- * Reset the specific window registers to a known state.
- */
-static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
-{
-	void __iomem *regs = sfb->regs;
-	u32 reg;
-
-	writel(0, regs + sfb->variant.wincon + (win * 4));
-	writel(0, regs + VIDOSD_A(win, sfb->variant));
-	writel(0, regs + VIDOSD_B(win, sfb->variant));
-	writel(0, regs + VIDOSD_C(win, sfb->variant));
-
-	if (sfb->variant.has_shadowcon) {
-		reg = readl(sfb->regs + SHADOWCON);
-		reg &= ~(SHADOWCON_WINx_PROTECT(win) |
-			SHADOWCON_CHx_ENABLE(win) |
-			SHADOWCON_CHx_LOCAL_ENABLE(win));
-		writel(reg, sfb->regs + SHADOWCON);
-	}
-}
-
-static int s3c_fb_probe(struct platform_device *pdev)
-{
-	const struct platform_device_id *platid;
-	struct s3c_fb_driverdata *fbdrv;
-	struct device *dev = &pdev->dev;
-	struct s3c_fb_platdata *pd;
-	struct s3c_fb *sfb;
-	struct resource *res;
-	int win;
-	int ret = 0;
-	u32 reg;
-
-	platid = platform_get_device_id(pdev);
-	fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
-
-	if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
-		dev_err(dev, "too many windows, cannot attach\n");
-		return -EINVAL;
-	}
-
-	pd = dev_get_platdata(&pdev->dev);
-	if (!pd) {
-		dev_err(dev, "no platform data specified\n");
-		return -EINVAL;
-	}
-
-	sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
-	if (!sfb) {
-		dev_err(dev, "no memory for framebuffers\n");
-		return -ENOMEM;
-	}
-
-	dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
-
-	sfb->dev = dev;
-	sfb->pdata = pd;
-	sfb->variant = fbdrv->variant;
-
-	spin_lock_init(&sfb->slock);
-
-	sfb->bus_clk = devm_clk_get(dev, "lcd");
-	if (IS_ERR(sfb->bus_clk)) {
-		dev_err(dev, "failed to get bus clock\n");
-		return PTR_ERR(sfb->bus_clk);
-	}
-
-	clk_prepare_enable(sfb->bus_clk);
-
-	if (!sfb->variant.has_clksel) {
-		sfb->lcd_clk = devm_clk_get(dev, "sclk_fimd");
-		if (IS_ERR(sfb->lcd_clk)) {
-			dev_err(dev, "failed to get lcd clock\n");
-			ret = PTR_ERR(sfb->lcd_clk);
-			goto err_bus_clk;
-		}
-
-		clk_prepare_enable(sfb->lcd_clk);
-	}
-
-	pm_runtime_enable(sfb->dev);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	sfb->regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(sfb->regs)) {
-		ret = PTR_ERR(sfb->regs);
-		goto err_lcd_clk;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(dev, "failed to acquire irq resource\n");
-		ret = -ENOENT;
-		goto err_lcd_clk;
-	}
-	sfb->irq_no = res->start;
-	ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,
-			  0, "s3c_fb", sfb);
-	if (ret) {
-		dev_err(dev, "irq request failed\n");
-		goto err_lcd_clk;
-	}
-
-	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
-
-	platform_set_drvdata(pdev, sfb);
-	pm_runtime_get_sync(sfb->dev);
-
-	/* setup gpio and output polarity controls */
-
-	pd->setup_gpio();
-
-	writel(pd->vidcon1, sfb->regs + VIDCON1);
-
-	/* set video clock running at under-run */
-	if (sfb->variant.has_fixvclk) {
-		reg = readl(sfb->regs + VIDCON1);
-		reg &= ~VIDCON1_VCLK_MASK;
-		reg |= VIDCON1_VCLK_RUN;
-		writel(reg, sfb->regs + VIDCON1);
-	}
-
-	/* zero all windows before we do anything */
-
-	for (win = 0; win < fbdrv->variant.nr_windows; win++)
-		s3c_fb_clear_win(sfb, win);
-
-	/* initialise colour key controls */
-	for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) {
-		void __iomem *regs = sfb->regs + sfb->variant.keycon;
-
-		regs += (win * 8);
-		writel(0xffffff, regs + WKEYCON0);
-		writel(0xffffff, regs + WKEYCON1);
-	}
-
-	s3c_fb_set_rgb_timing(sfb);
-
-	/* we have the register setup, start allocating framebuffers */
-
-	for (win = 0; win < fbdrv->variant.nr_windows; win++) {
-		if (!pd->win[win])
-			continue;
-
-		ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
-				       &sfb->windows[win]);
-		if (ret < 0) {
-			dev_err(dev, "failed to create window %d\n", win);
-			for (; win >= 0; win--)
-				s3c_fb_release_win(sfb, sfb->windows[win]);
-			goto err_pm_runtime;
-		}
-	}
-
-	platform_set_drvdata(pdev, sfb);
-	pm_runtime_put_sync(sfb->dev);
-
-	return 0;
-
-err_pm_runtime:
-	pm_runtime_put_sync(sfb->dev);
-
-err_lcd_clk:
-	pm_runtime_disable(sfb->dev);
-
-	if (!sfb->variant.has_clksel)
-		clk_disable_unprepare(sfb->lcd_clk);
-
-err_bus_clk:
-	clk_disable_unprepare(sfb->bus_clk);
-
-	return ret;
-}
-
-/**
- * s3c_fb_remove() - Cleanup on module finalisation
- * @pdev: The platform device we are bound to.
- *
- * Shutdown and then release all the resources that the driver allocated
- * on initialisation.
- */
-static int s3c_fb_remove(struct platform_device *pdev)
-{
-	struct s3c_fb *sfb = platform_get_drvdata(pdev);
-	int win;
-
-	pm_runtime_get_sync(sfb->dev);
-
-	for (win = 0; win < S3C_FB_MAX_WIN; win++)
-		if (sfb->windows[win])
-			s3c_fb_release_win(sfb, sfb->windows[win]);
-
-	if (!sfb->variant.has_clksel)
-		clk_disable_unprepare(sfb->lcd_clk);
-
-	clk_disable_unprepare(sfb->bus_clk);
-
-	pm_runtime_put_sync(sfb->dev);
-	pm_runtime_disable(sfb->dev);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int s3c_fb_suspend(struct device *dev)
-{
-	struct s3c_fb *sfb = dev_get_drvdata(dev);
-	struct s3c_fb_win *win;
-	int win_no;
-
-	pm_runtime_get_sync(sfb->dev);
-
-	for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
-		win = sfb->windows[win_no];
-		if (!win)
-			continue;
-
-		/* use the blank function to push into power-down */
-		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
-	}
-
-	if (!sfb->variant.has_clksel)
-		clk_disable_unprepare(sfb->lcd_clk);
-
-	clk_disable_unprepare(sfb->bus_clk);
-
-	pm_runtime_put_sync(sfb->dev);
-
-	return 0;
-}
-
-static int s3c_fb_resume(struct device *dev)
-{
-	struct s3c_fb *sfb = dev_get_drvdata(dev);
-	struct s3c_fb_platdata *pd = sfb->pdata;
-	struct s3c_fb_win *win;
-	int win_no;
-	u32 reg;
-
-	pm_runtime_get_sync(sfb->dev);
-
-	clk_prepare_enable(sfb->bus_clk);
-
-	if (!sfb->variant.has_clksel)
-		clk_prepare_enable(sfb->lcd_clk);
-
-	/* setup gpio and output polarity controls */
-	pd->setup_gpio();
-	writel(pd->vidcon1, sfb->regs + VIDCON1);
-
-	/* set video clock running at under-run */
-	if (sfb->variant.has_fixvclk) {
-		reg = readl(sfb->regs + VIDCON1);
-		reg &= ~VIDCON1_VCLK_MASK;
-		reg |= VIDCON1_VCLK_RUN;
-		writel(reg, sfb->regs + VIDCON1);
-	}
-
-	/* zero all windows before we do anything */
-	for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
-		s3c_fb_clear_win(sfb, win_no);
-
-	for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
-		void __iomem *regs = sfb->regs + sfb->variant.keycon;
-		win = sfb->windows[win_no];
-		if (!win)
-			continue;
-
-		shadow_protect_win(win, 1);
-		regs += (win_no * 8);
-		writel(0xffffff, regs + WKEYCON0);
-		writel(0xffffff, regs + WKEYCON1);
-		shadow_protect_win(win, 0);
-	}
-
-	s3c_fb_set_rgb_timing(sfb);
-
-	/* restore framebuffers */
-	for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
-		win = sfb->windows[win_no];
-		if (!win)
-			continue;
-
-		dev_dbg(dev, "resuming window %d\n", win_no);
-		s3c_fb_set_par(win->fbinfo);
-	}
-
-	pm_runtime_put_sync(sfb->dev);
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int s3c_fb_runtime_suspend(struct device *dev)
-{
-	struct s3c_fb *sfb = dev_get_drvdata(dev);
-
-	if (!sfb->variant.has_clksel)
-		clk_disable_unprepare(sfb->lcd_clk);
-
-	clk_disable_unprepare(sfb->bus_clk);
-
-	return 0;
-}
-
-static int s3c_fb_runtime_resume(struct device *dev)
-{
-	struct s3c_fb *sfb = dev_get_drvdata(dev);
-	struct s3c_fb_platdata *pd = sfb->pdata;
-
-	clk_prepare_enable(sfb->bus_clk);
-
-	if (!sfb->variant.has_clksel)
-		clk_prepare_enable(sfb->lcd_clk);
-
-	/* setup gpio and output polarity controls */
-	pd->setup_gpio();
-	writel(pd->vidcon1, sfb->regs + VIDCON1);
-
-	return 0;
-}
-#endif
-
-#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
-#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
-
-static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
-	[0] = {
-		.has_osd_c	= 1,
-		.osd_size_off	= 0x8,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(24)),
-	},
-	[1] = {
-		.has_osd_c	= 1,
-		.has_osd_d	= 1,
-		.osd_size_off	= 0xc,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(28)),
-	},
-	[2] = {
-		.has_osd_c	= 1,
-		.has_osd_d	= 1,
-		.osd_size_off	= 0xc,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 16,
-		.palette_16bpp	= 1,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(28)),
-	},
-	[3] = {
-		.has_osd_c	= 1,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 16,
-		.palette_16bpp	= 1,
-		.valid_bpp	= (VALID_BPP124  | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(28)),
-	},
-	[4] = {
-		.has_osd_c	= 1,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 4,
-		.palette_16bpp	= 1,
-		.valid_bpp	= (VALID_BPP(1) | VALID_BPP(2) |
-				   VALID_BPP(16) | VALID_BPP(18) |
-				   VALID_BPP(19) | VALID_BPP(24) |
-				   VALID_BPP(25) | VALID_BPP(28)),
-	},
-};
-
-static struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {
-	[0] = {
-		.has_osd_c	= 1,
-		.osd_size_off	= 0x8,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
-				   VALID_BPP(15) | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(32)),
-	},
-	[1] = {
-		.has_osd_c	= 1,
-		.has_osd_d	= 1,
-		.osd_size_off	= 0xc,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
-				   VALID_BPP(15) | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(32)),
-	},
-	[2] = {
-		.has_osd_c	= 1,
-		.has_osd_d	= 1,
-		.osd_size_off	= 0xc,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
-				   VALID_BPP(15) | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(32)),
-	},
-	[3] = {
-		.has_osd_c	= 1,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
-				   VALID_BPP(15) | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(32)),
-	},
-	[4] = {
-		.has_osd_c	= 1,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
-				   VALID_BPP(15) | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(32)),
-	},
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_64xx = {
-	.variant = {
-		.nr_windows	= 5,
-		.vidtcon	= VIDTCON0,
-		.wincon		= WINCON(0),
-		.winmap		= WINxMAP(0),
-		.keycon		= WKEYCON,
-		.osd		= VIDOSD_BASE,
-		.osd_stride	= 16,
-		.buf_start	= VIDW_BUF_START(0),
-		.buf_size	= VIDW_BUF_SIZE(0),
-		.buf_end	= VIDW_BUF_END(0),
-
-		.palette = {
-			[0] = 0x400,
-			[1] = 0x800,
-			[2] = 0x300,
-			[3] = 0x320,
-			[4] = 0x340,
-		},
-
-		.has_prtcon	= 1,
-		.has_clksel	= 1,
-	},
-	.win[0]	= &s3c_fb_data_64xx_wins[0],
-	.win[1]	= &s3c_fb_data_64xx_wins[1],
-	.win[2]	= &s3c_fb_data_64xx_wins[2],
-	.win[3]	= &s3c_fb_data_64xx_wins[3],
-	.win[4]	= &s3c_fb_data_64xx_wins[4],
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
-	.variant = {
-		.nr_windows	= 5,
-		.vidtcon	= VIDTCON0,
-		.wincon		= WINCON(0),
-		.winmap		= WINxMAP(0),
-		.keycon		= WKEYCON,
-		.osd		= VIDOSD_BASE,
-		.osd_stride	= 16,
-		.buf_start	= VIDW_BUF_START(0),
-		.buf_size	= VIDW_BUF_SIZE(0),
-		.buf_end	= VIDW_BUF_END(0),
-
-		.palette = {
-			[0] = 0x2400,
-			[1] = 0x2800,
-			[2] = 0x2c00,
-			[3] = 0x3000,
-			[4] = 0x3400,
-		},
-
-		.has_prtcon	= 1,
-		.has_blendcon	= 1,
-		.has_clksel	= 1,
-	},
-	.win[0]	= &s3c_fb_data_s5p_wins[0],
-	.win[1]	= &s3c_fb_data_s5p_wins[1],
-	.win[2]	= &s3c_fb_data_s5p_wins[2],
-	.win[3]	= &s3c_fb_data_s5p_wins[3],
-	.win[4]	= &s3c_fb_data_s5p_wins[4],
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
-	.variant = {
-		.nr_windows	= 5,
-		.vidtcon	= VIDTCON0,
-		.wincon		= WINCON(0),
-		.winmap		= WINxMAP(0),
-		.keycon		= WKEYCON,
-		.osd		= VIDOSD_BASE,
-		.osd_stride	= 16,
-		.buf_start	= VIDW_BUF_START(0),
-		.buf_size	= VIDW_BUF_SIZE(0),
-		.buf_end	= VIDW_BUF_END(0),
-
-		.palette = {
-			[0] = 0x2400,
-			[1] = 0x2800,
-			[2] = 0x2c00,
-			[3] = 0x3000,
-			[4] = 0x3400,
-		},
-
-		.has_shadowcon	= 1,
-		.has_blendcon	= 1,
-		.has_clksel	= 1,
-		.has_fixvclk	= 1,
-	},
-	.win[0]	= &s3c_fb_data_s5p_wins[0],
-	.win[1]	= &s3c_fb_data_s5p_wins[1],
-	.win[2]	= &s3c_fb_data_s5p_wins[2],
-	.win[3]	= &s3c_fb_data_s5p_wins[3],
-	.win[4]	= &s3c_fb_data_s5p_wins[4],
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
-	.variant = {
-		.nr_windows	= 5,
-		.vidtcon	= VIDTCON0,
-		.wincon		= WINCON(0),
-		.winmap		= WINxMAP(0),
-		.keycon		= WKEYCON,
-		.osd		= VIDOSD_BASE,
-		.osd_stride	= 16,
-		.buf_start	= VIDW_BUF_START(0),
-		.buf_size	= VIDW_BUF_SIZE(0),
-		.buf_end	= VIDW_BUF_END(0),
-
-		.palette = {
-			[0] = 0x2400,
-			[1] = 0x2800,
-			[2] = 0x2c00,
-			[3] = 0x3000,
-			[4] = 0x3400,
-		},
-
-		.has_shadowcon	= 1,
-		.has_blendcon	= 1,
-		.has_fixvclk	= 1,
-	},
-	.win[0]	= &s3c_fb_data_s5p_wins[0],
-	.win[1]	= &s3c_fb_data_s5p_wins[1],
-	.win[2]	= &s3c_fb_data_s5p_wins[2],
-	.win[3]	= &s3c_fb_data_s5p_wins[3],
-	.win[4]	= &s3c_fb_data_s5p_wins[4],
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
-	.variant = {
-		.nr_windows	= 5,
-		.vidtcon	= FIMD_V8_VIDTCON0,
-		.wincon		= WINCON(0),
-		.winmap		= WINxMAP(0),
-		.keycon		= WKEYCON,
-		.osd		= VIDOSD_BASE,
-		.osd_stride	= 16,
-		.buf_start	= VIDW_BUF_START(0),
-		.buf_size	= VIDW_BUF_SIZE(0),
-		.buf_end	= VIDW_BUF_END(0),
-
-		.palette = {
-			[0] = 0x2400,
-			[1] = 0x2800,
-			[2] = 0x2c00,
-			[3] = 0x3000,
-			[4] = 0x3400,
-		},
-		.has_shadowcon	= 1,
-		.has_blendcon	= 1,
-		.has_fixvclk	= 1,
-	},
-	.win[0]	= &s3c_fb_data_s5p_wins[0],
-	.win[1]	= &s3c_fb_data_s5p_wins[1],
-	.win[2]	= &s3c_fb_data_s5p_wins[2],
-	.win[3]	= &s3c_fb_data_s5p_wins[3],
-	.win[4]	= &s3c_fb_data_s5p_wins[4],
-};
-
-/* S3C2443/S3C2416 style hardware */
-static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
-	.variant = {
-		.nr_windows	= 2,
-		.is_2443	= 1,
-
-		.vidtcon	= 0x08,
-		.wincon		= 0x14,
-		.winmap		= 0xd0,
-		.keycon		= 0xb0,
-		.osd		= 0x28,
-		.osd_stride	= 12,
-		.buf_start	= 0x64,
-		.buf_size	= 0x94,
-		.buf_end	= 0x7c,
-
-		.palette = {
-			[0] = 0x400,
-			[1] = 0x800,
-		},
-		.has_clksel	= 1,
-	},
-	.win[0] = &(struct s3c_fb_win_variant) {
-		.palette_sz	= 256,
-		.valid_bpp	= VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
-	},
-	.win[1] = &(struct s3c_fb_win_variant) {
-		.has_osd_c	= 1,
-		.has_osd_alpha	= 1,
-		.palette_sz	= 256,
-		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
-				   VALID_BPP(18) | VALID_BPP(19) |
-				   VALID_BPP(24) | VALID_BPP(25) |
-				   VALID_BPP(28)),
-	},
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
-	.variant = {
-		.nr_windows	= 3,
-		.vidtcon	= VIDTCON0,
-		.wincon		= WINCON(0),
-		.winmap		= WINxMAP(0),
-		.keycon		= WKEYCON,
-		.osd		= VIDOSD_BASE,
-		.osd_stride	= 16,
-		.buf_start	= VIDW_BUF_START(0),
-		.buf_size	= VIDW_BUF_SIZE(0),
-		.buf_end	= VIDW_BUF_END(0),
-
-		.palette = {
-			[0] = 0x2400,
-			[1] = 0x2800,
-			[2] = 0x2c00,
-		},
-
-		.has_blendcon	= 1,
-		.has_fixvclk	= 1,
-	},
-	.win[0] = &s3c_fb_data_s5p_wins[0],
-	.win[1] = &s3c_fb_data_s5p_wins[1],
-	.win[2] = &s3c_fb_data_s5p_wins[2],
-};
-
-static struct platform_device_id s3c_fb_driver_ids[] = {
-	{
-		.name		= "s3c-fb",
-		.driver_data	= (unsigned long)&s3c_fb_data_64xx,
-	}, {
-		.name		= "s5pc100-fb",
-		.driver_data	= (unsigned long)&s3c_fb_data_s5pc100,
-	}, {
-		.name		= "s5pv210-fb",
-		.driver_data	= (unsigned long)&s3c_fb_data_s5pv210,
-	}, {
-		.name		= "exynos4-fb",
-		.driver_data	= (unsigned long)&s3c_fb_data_exynos4,
-	}, {
-		.name		= "exynos5-fb",
-		.driver_data	= (unsigned long)&s3c_fb_data_exynos5,
-	}, {
-		.name		= "s3c2443-fb",
-		.driver_data	= (unsigned long)&s3c_fb_data_s3c2443,
-	}, {
-		.name		= "s5p64x0-fb",
-		.driver_data	= (unsigned long)&s3c_fb_data_s5p64x0,
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
-
-static const struct dev_pm_ops s3cfb_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
-	SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
-			   NULL)
-};
-
-static struct platform_driver s3c_fb_driver = {
-	.probe		= s3c_fb_probe,
-	.remove		= s3c_fb_remove,
-	.id_table	= s3c_fb_driver_ids,
-	.driver		= {
-		.name	= "s3c-fb",
-		.owner	= THIS_MODULE,
-		.pm	= &s3cfb_pm_ops,
-	},
-};
-
-module_platform_driver(s3c_fb_driver);
-
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s3c-fb");
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
deleted file mode 100644
index 81af5a63e9e1..000000000000
--- a/drivers/video/s3c2410fb.c
+++ /dev/null
@@ -1,1146 +0,0 @@
-/* linux/drivers/video/s3c2410fb.c
- *	Copyright (c) 2004,2005 Arnaud Patard
- *	Copyright (c) 2004-2008 Ben Dooks
- *
- * S3C2410 LCD Framebuffer Driver
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Driver based on skeletonfb.c, sa1100fb.c and others.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/io.h>
-
-#include <asm/div64.h>
-
-#include <asm/mach/map.h>
-#include <mach/regs-lcd.h>
-#include <mach/regs-gpio.h>
-#include <mach/fb.h>
-
-#ifdef CONFIG_PM
-#include <linux/pm.h>
-#endif
-
-#include "s3c2410fb.h"
-
-/* Debugging stuff */
-#ifdef CONFIG_FB_S3C2410_DEBUG
-static int debug	= 1;
-#else
-static int debug;
-#endif
-
-#define dprintk(msg...) \
-do { \
-	if (debug) \
-		pr_debug(msg); \
-} while (0)
-
-/* useful functions */
-
-static int is_s3c2412(struct s3c2410fb_info *fbi)
-{
-	return (fbi->drv_type == DRV_S3C2412);
-}
-
-/* s3c2410fb_set_lcdaddr
- *
- * initialise lcd controller address pointers
- */
-static void s3c2410fb_set_lcdaddr(struct fb_info *info)
-{
-	unsigned long saddr1, saddr2, saddr3;
-	struct s3c2410fb_info *fbi = info->par;
-	void __iomem *regs = fbi->io;
-
-	saddr1  = info->fix.smem_start >> 1;
-	saddr2  = info->fix.smem_start;
-	saddr2 += info->fix.line_length * info->var.yres;
-	saddr2 >>= 1;
-
-	saddr3 = S3C2410_OFFSIZE(0) |
-		 S3C2410_PAGEWIDTH((info->fix.line_length / 2) & 0x3ff);
-
-	dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
-	dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
-	dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
-
-	writel(saddr1, regs + S3C2410_LCDSADDR1);
-	writel(saddr2, regs + S3C2410_LCDSADDR2);
-	writel(saddr3, regs + S3C2410_LCDSADDR3);
-}
-
-/* s3c2410fb_calc_pixclk()
- *
- * calculate divisor for clk->pixclk
- */
-static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
-					  unsigned long pixclk)
-{
-	unsigned long clk = fbi->clk_rate;
-	unsigned long long div;
-
-	/* pixclk is in picoseconds, our clock is in Hz
-	 *
-	 * Hz -> picoseconds is / 10^-12
-	 */
-
-	div = (unsigned long long)clk * pixclk;
-	div >>= 12;			/* div / 2^12 */
-	do_div(div, 625 * 625UL * 625); /* div / 5^12 */
-
-	dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);
-	return div;
-}
-
-/*
- *	s3c2410fb_check_var():
- *	Get the video params out of 'var'. If a value doesn't fit, round it up,
- *	if it's too big, return -EINVAL.
- *
- */
-static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
-			       struct fb_info *info)
-{
-	struct s3c2410fb_info *fbi = info->par;
-	struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
-	struct s3c2410fb_display *display = NULL;
-	struct s3c2410fb_display *default_display = mach_info->displays +
-						    mach_info->default_display;
-	int type = default_display->type;
-	unsigned i;
-
-	dprintk("check_var(var=%p, info=%p)\n", var, info);
-
-	/* validate x/y resolution */
-	/* choose default mode if possible */
-	if (var->yres == default_display->yres &&
-	    var->xres == default_display->xres &&
-	    var->bits_per_pixel == default_display->bpp)
-		display = default_display;
-	else
-		for (i = 0; i < mach_info->num_displays; i++)
-			if (type == mach_info->displays[i].type &&
-			    var->yres == mach_info->displays[i].yres &&
-			    var->xres == mach_info->displays[i].xres &&
-			    var->bits_per_pixel == mach_info->displays[i].bpp) {
-				display = mach_info->displays + i;
-				break;
-			}
-
-	if (!display) {
-		dprintk("wrong resolution or depth %dx%d at %d bpp\n",
-			var->xres, var->yres, var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	/* it is always the size as the display */
-	var->xres_virtual = display->xres;
-	var->yres_virtual = display->yres;
-	var->height = display->height;
-	var->width = display->width;
-
-	/* copy lcd settings */
-	var->pixclock = display->pixclock;
-	var->left_margin = display->left_margin;
-	var->right_margin = display->right_margin;
-	var->upper_margin = display->upper_margin;
-	var->lower_margin = display->lower_margin;
-	var->vsync_len = display->vsync_len;
-	var->hsync_len = display->hsync_len;
-
-	fbi->regs.lcdcon5 = display->lcdcon5;
-	/* set display type */
-	fbi->regs.lcdcon1 = display->type;
-
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	/* set r/g/b positions */
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 2:
-	case 4:
-		var->red.offset	= 0;
-		var->red.length	= var->bits_per_pixel;
-		var->green	= var->red;
-		var->blue	= var->red;
-		break;
-	case 8:
-		if (display->type != S3C2410_LCDCON1_TFT) {
-			/* 8 bpp 332 */
-			var->red.length		= 3;
-			var->red.offset		= 5;
-			var->green.length	= 3;
-			var->green.offset	= 2;
-			var->blue.length	= 2;
-			var->blue.offset	= 0;
-		} else {
-			var->red.offset		= 0;
-			var->red.length		= 8;
-			var->green		= var->red;
-			var->blue		= var->red;
-		}
-		break;
-	case 12:
-		/* 12 bpp 444 */
-		var->red.length		= 4;
-		var->red.offset		= 8;
-		var->green.length	= 4;
-		var->green.offset	= 4;
-		var->blue.length	= 4;
-		var->blue.offset	= 0;
-		break;
-
-	default:
-	case 16:
-		if (display->lcdcon5 & S3C2410_LCDCON5_FRM565) {
-			/* 16 bpp, 565 format */
-			var->red.offset		= 11;
-			var->green.offset	= 5;
-			var->blue.offset	= 0;
-			var->red.length		= 5;
-			var->green.length	= 6;
-			var->blue.length	= 5;
-		} else {
-			/* 16 bpp, 5551 format */
-			var->red.offset		= 11;
-			var->green.offset	= 6;
-			var->blue.offset	= 1;
-			var->red.length		= 5;
-			var->green.length	= 5;
-			var->blue.length	= 5;
-		}
-		break;
-	case 32:
-		/* 24 bpp 888 and 8 dummy */
-		var->red.length		= 8;
-		var->red.offset		= 16;
-		var->green.length	= 8;
-		var->green.offset	= 8;
-		var->blue.length	= 8;
-		var->blue.offset	= 0;
-		break;
-	}
-	return 0;
-}
-
-/* s3c2410fb_calculate_stn_lcd_regs
- *
- * calculate register values from var settings
- */
-static void s3c2410fb_calculate_stn_lcd_regs(const struct fb_info *info,
-					     struct s3c2410fb_hw *regs)
-{
-	const struct s3c2410fb_info *fbi = info->par;
-	const struct fb_var_screeninfo *var = &info->var;
-	int type = regs->lcdcon1 & ~S3C2410_LCDCON1_TFT;
-	int hs = var->xres >> 2;
-	unsigned wdly = (var->left_margin >> 4) - 1;
-	unsigned wlh = (var->hsync_len >> 4) - 1;
-
-	if (type != S3C2410_LCDCON1_STN4)
-		hs >>= 1;
-
-	switch (var->bits_per_pixel) {
-	case 1:
-		regs->lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
-		break;
-	case 2:
-		regs->lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
-		break;
-	case 4:
-		regs->lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
-		break;
-	case 8:
-		regs->lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
-		hs *= 3;
-		break;
-	case 12:
-		regs->lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
-		hs *= 3;
-		break;
-
-	default:
-		/* invalid pixel depth */
-		dev_err(fbi->dev, "invalid bpp %d\n",
-			var->bits_per_pixel);
-	}
-	/* update X/Y info */
-	dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
-		var->left_margin, var->right_margin, var->hsync_len);
-
-	regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1);
-
-	if (wdly > 3)
-		wdly = 3;
-
-	if (wlh > 3)
-		wlh = 3;
-
-	regs->lcdcon3 =	S3C2410_LCDCON3_WDLY(wdly) |
-			S3C2410_LCDCON3_LINEBLANK(var->right_margin / 8) |
-			S3C2410_LCDCON3_HOZVAL(hs - 1);
-
-	regs->lcdcon4 = S3C2410_LCDCON4_WLH(wlh);
-}
-
-/* s3c2410fb_calculate_tft_lcd_regs
- *
- * calculate register values from var settings
- */
-static void s3c2410fb_calculate_tft_lcd_regs(const struct fb_info *info,
-					     struct s3c2410fb_hw *regs)
-{
-	const struct s3c2410fb_info *fbi = info->par;
-	const struct fb_var_screeninfo *var = &info->var;
-
-	switch (var->bits_per_pixel) {
-	case 1:
-		regs->lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
-		break;
-	case 2:
-		regs->lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
-		break;
-	case 4:
-		regs->lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
-		break;
-	case 8:
-		regs->lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
-		regs->lcdcon5 |= S3C2410_LCDCON5_BSWP |
-				 S3C2410_LCDCON5_FRM565;
-		regs->lcdcon5 &= ~S3C2410_LCDCON5_HWSWP;
-		break;
-	case 16:
-		regs->lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
-		regs->lcdcon5 &= ~S3C2410_LCDCON5_BSWP;
-		regs->lcdcon5 |= S3C2410_LCDCON5_HWSWP;
-		break;
-	case 32:
-		regs->lcdcon1 |= S3C2410_LCDCON1_TFT24BPP;
-		regs->lcdcon5 &= ~(S3C2410_LCDCON5_BSWP |
-				   S3C2410_LCDCON5_HWSWP |
-				   S3C2410_LCDCON5_BPP24BL);
-		break;
-	default:
-		/* invalid pixel depth */
-		dev_err(fbi->dev, "invalid bpp %d\n",
-			var->bits_per_pixel);
-	}
-	/* update X/Y info */
-	dprintk("setting vert: up=%d, low=%d, sync=%d\n",
-		var->upper_margin, var->lower_margin, var->vsync_len);
-
-	dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
-		var->left_margin, var->right_margin, var->hsync_len);
-
-	regs->lcdcon2 = S3C2410_LCDCON2_LINEVAL(var->yres - 1) |
-			S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
-			S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
-			S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
-
-	regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
-			S3C2410_LCDCON3_HFPD(var->left_margin - 1) |
-			S3C2410_LCDCON3_HOZVAL(var->xres - 1);
-
-	regs->lcdcon4 = S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
-}
-
-/* s3c2410fb_activate_var
- *
- * activate (set) the controller from the given framebuffer
- * information
- */
-static void s3c2410fb_activate_var(struct fb_info *info)
-{
-	struct s3c2410fb_info *fbi = info->par;
-	void __iomem *regs = fbi->io;
-	int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT;
-	struct fb_var_screeninfo *var = &info->var;
-	int clkdiv;
-
-	clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2);
-
-	dprintk("%s: var->xres  = %d\n", __func__, var->xres);
-	dprintk("%s: var->yres  = %d\n", __func__, var->yres);
-	dprintk("%s: var->bpp   = %d\n", __func__, var->bits_per_pixel);
-
-	if (type == S3C2410_LCDCON1_TFT) {
-		s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);
-		--clkdiv;
-		if (clkdiv < 0)
-			clkdiv = 0;
-	} else {
-		s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);
-		if (clkdiv < 2)
-			clkdiv = 2;
-	}
-
-	fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);
-
-	/* write new registers */
-
-	dprintk("new register set:\n");
-	dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);
-	dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);
-	dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);
-	dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
-	dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
-
-	writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,
-		regs + S3C2410_LCDCON1);
-	writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);
-	writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);
-	writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);
-	writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);
-
-	/* set lcd address pointers */
-	s3c2410fb_set_lcdaddr(info);
-
-	fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,
-	writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);
-}
-
-/*
- *      s3c2410fb_set_par - Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- *
- */
-static int s3c2410fb_set_par(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-
-	switch (var->bits_per_pixel) {
-	case 32:
-	case 16:
-	case 12:
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	case 1:
-		info->fix.visual = FB_VISUAL_MONO01;
-		break;
-	default:
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	}
-
-	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
-
-	/* activate this new configuration */
-
-	s3c2410fb_activate_var(info);
-	return 0;
-}
-
-static void schedule_palette_update(struct s3c2410fb_info *fbi,
-				    unsigned int regno, unsigned int val)
-{
-	unsigned long flags;
-	unsigned long irqen;
-	void __iomem *irq_base = fbi->irq_base;
-
-	local_irq_save(flags);
-
-	fbi->palette_buffer[regno] = val;
-
-	if (!fbi->palette_ready) {
-		fbi->palette_ready = 1;
-
-		/* enable IRQ */
-		irqen = readl(irq_base + S3C24XX_LCDINTMSK);
-		irqen &= ~S3C2410_LCDINT_FRSYNC;
-		writel(irqen, irq_base + S3C24XX_LCDINTMSK);
-	}
-
-	local_irq_restore(flags);
-}
-
-/* from pxafb.c */
-static inline unsigned int chan_to_field(unsigned int chan,
-					 struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int s3c2410fb_setcolreg(unsigned regno,
-			       unsigned red, unsigned green, unsigned blue,
-			       unsigned transp, struct fb_info *info)
-{
-	struct s3c2410fb_info *fbi = info->par;
-	void __iomem *regs = fbi->io;
-	unsigned int val;
-
-	/* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n",
-		   regno, red, green, blue); */
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/* true-colour, use pseudo-palette */
-
-		if (regno < 16) {
-			u32 *pal = info->pseudo_palette;
-
-			val  = chan_to_field(red,   &info->var.red);
-			val |= chan_to_field(green, &info->var.green);
-			val |= chan_to_field(blue,  &info->var.blue);
-
-			pal[regno] = val;
-		}
-		break;
-
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno < 256) {
-			/* currently assume RGB 5-6-5 mode */
-
-			val  = (red   >>  0) & 0xf800;
-			val |= (green >>  5) & 0x07e0;
-			val |= (blue  >> 11) & 0x001f;
-
-			writel(val, regs + S3C2410_TFTPAL(regno));
-			schedule_palette_update(fbi, regno, val);
-		}
-
-		break;
-
-	default:
-		return 1;	/* unknown type */
-	}
-
-	return 0;
-}
-
-/* s3c2410fb_lcd_enable
- *
- * shutdown the lcd controller
- */
-static void s3c2410fb_lcd_enable(struct s3c2410fb_info *fbi, int enable)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	if (enable)
-		fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
-	else
-		fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
-
-	writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1);
-
-	local_irq_restore(flags);
-}
-
-
-/*
- *      s3c2410fb_blank
- *	@blank_mode: the blank mode we want.
- *	@info: frame buffer structure that represents a single frame buffer
- *
- *	Blank the screen if blank_mode != 0, else unblank. Return 0 if
- *	blanking succeeded, != 0 if un-/blanking failed due to e.g. a
- *	video mode which doesn't support it. Implements VESA suspend
- *	and powerdown modes on hardware that supports disabling hsync/vsync:
- *
- *	Returns negative errno on error, or zero on success.
- *
- */
-static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct s3c2410fb_info *fbi = info->par;
-	void __iomem *tpal_reg = fbi->io;
-
-	dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
-
-	tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
-
-	if (blank_mode == FB_BLANK_POWERDOWN)
-		s3c2410fb_lcd_enable(fbi, 0);
-	else
-		s3c2410fb_lcd_enable(fbi, 1);
-
-	if (blank_mode == FB_BLANK_UNBLANK)
-		writel(0x0, tpal_reg);
-	else {
-		dprintk("setting TPAL to output 0x000000\n");
-		writel(S3C2410_TPAL_EN, tpal_reg);
-	}
-
-	return 0;
-}
-
-static int s3c2410fb_debug_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");
-}
-
-static int s3c2410fb_debug_store(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t len)
-{
-	if (len < 1)
-		return -EINVAL;
-
-	if (strnicmp(buf, "on", 2) == 0 ||
-	    strnicmp(buf, "1", 1) == 0) {
-		debug = 1;
-		dev_dbg(dev, "s3c2410fb: Debug On");
-	} else if (strnicmp(buf, "off", 3) == 0 ||
-		   strnicmp(buf, "0", 1) == 0) {
-		debug = 0;
-		dev_dbg(dev, "s3c2410fb: Debug Off");
-	} else {
-		return -EINVAL;
-	}
-
-	return len;
-}
-
-static DEVICE_ATTR(debug, 0666, s3c2410fb_debug_show, s3c2410fb_debug_store);
-
-static struct fb_ops s3c2410fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= s3c2410fb_check_var,
-	.fb_set_par	= s3c2410fb_set_par,
-	.fb_blank	= s3c2410fb_blank,
-	.fb_setcolreg	= s3c2410fb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-/*
- * s3c2410fb_map_video_memory():
- *	Allocates the DRAM memory for the frame buffer.  This buffer is
- *	remapped into a non-cached, non-buffered, memory region to
- *	allow palette and pixel writes to occur without flushing the
- *	cache.  Once this area is remapped, all virtual memory
- *	access to the video memory should occur at the new region.
- */
-static int s3c2410fb_map_video_memory(struct fb_info *info)
-{
-	struct s3c2410fb_info *fbi = info->par;
-	dma_addr_t map_dma;
-	unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
-
-	dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
-
-	info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
-						   &map_dma, GFP_KERNEL);
-
-	if (info->screen_base) {
-		/* prevent initial garbage on screen */
-		dprintk("map_video_memory: clear %p:%08x\n",
-			info->screen_base, map_size);
-		memset(info->screen_base, 0x00, map_size);
-
-		info->fix.smem_start = map_dma;
-
-		dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\n",
-			info->fix.smem_start, info->screen_base, map_size);
-	}
-
-	return info->screen_base ? 0 : -ENOMEM;
-}
-
-static inline void s3c2410fb_unmap_video_memory(struct fb_info *info)
-{
-	struct s3c2410fb_info *fbi = info->par;
-
-	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
-			      info->screen_base, info->fix.smem_start);
-}
-
-static inline void modify_gpio(void __iomem *reg,
-			       unsigned long set, unsigned long mask)
-{
-	unsigned long tmp;
-
-	tmp = readl(reg) & ~mask;
-	writel(tmp | set, reg);
-}
-
-/*
- * s3c2410fb_init_registers - Initialise all LCD-related registers
- */
-static int s3c2410fb_init_registers(struct fb_info *info)
-{
-	struct s3c2410fb_info *fbi = info->par;
-	struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
-	unsigned long flags;
-	void __iomem *regs = fbi->io;
-	void __iomem *tpal;
-	void __iomem *lpcsel;
-
-	if (is_s3c2412(fbi)) {
-		tpal = regs + S3C2412_TPAL;
-		lpcsel = regs + S3C2412_TCONSEL;
-	} else {
-		tpal = regs + S3C2410_TPAL;
-		lpcsel = regs + S3C2410_LPCSEL;
-	}
-
-	/* Initialise LCD with values from haret */
-
-	local_irq_save(flags);
-
-	/* modify the gpio(s) with interrupts set (bjd) */
-
-	modify_gpio(S3C2410_GPCUP,  mach_info->gpcup,  mach_info->gpcup_mask);
-	modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
-	modify_gpio(S3C2410_GPDUP,  mach_info->gpdup,  mach_info->gpdup_mask);
-	modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
-
-	local_irq_restore(flags);
-
-	dprintk("LPCSEL    = 0x%08lx\n", mach_info->lpcsel);
-	writel(mach_info->lpcsel, lpcsel);
-
-	dprintk("replacing TPAL %08x\n", readl(tpal));
-
-	/* ensure temporary palette disabled */
-	writel(0x00, tpal);
-
-	return 0;
-}
-
-static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
-{
-	unsigned int i;
-	void __iomem *regs = fbi->io;
-
-	fbi->palette_ready = 0;
-
-	for (i = 0; i < 256; i++) {
-		unsigned long ent = fbi->palette_buffer[i];
-		if (ent == PALETTE_BUFF_CLEAR)
-			continue;
-
-		writel(ent, regs + S3C2410_TFTPAL(i));
-
-		/* it seems the only way to know exactly
-		 * if the palette wrote ok, is to check
-		 * to see if the value verifies ok
-		 */
-
-		if (readw(regs + S3C2410_TFTPAL(i)) == ent)
-			fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR;
-		else
-			fbi->palette_ready = 1;   /* retry */
-	}
-}
-
-static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
-{
-	struct s3c2410fb_info *fbi = dev_id;
-	void __iomem *irq_base = fbi->irq_base;
-	unsigned long lcdirq = readl(irq_base + S3C24XX_LCDINTPND);
-
-	if (lcdirq & S3C2410_LCDINT_FRSYNC) {
-		if (fbi->palette_ready)
-			s3c2410fb_write_palette(fbi);
-
-		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND);
-		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND);
-	}
-
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_CPU_FREQ
-
-static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
-					unsigned long val, void *data)
-{
-	struct s3c2410fb_info *info;
-	struct fb_info *fbinfo;
-	long delta_f;
-
-	info = container_of(nb, struct s3c2410fb_info, freq_transition);
-	fbinfo = platform_get_drvdata(to_platform_device(info->dev));
-
-	/* work out change, <0 for speed-up */
-	delta_f = info->clk_rate - clk_get_rate(info->clk);
-
-	if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
-	    (val == CPUFREQ_PRECHANGE && delta_f < 0)) {
-		info->clk_rate = clk_get_rate(info->clk);
-		s3c2410fb_activate_var(fbinfo);
-	}
-
-	return 0;
-}
-
-static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info)
-{
-	info->freq_transition.notifier_call = s3c2410fb_cpufreq_transition;
-
-	return cpufreq_register_notifier(&info->freq_transition,
-					 CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
-{
-	cpufreq_unregister_notifier(&info->freq_transition,
-				    CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-#else
-static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info)
-{
-	return 0;
-}
-
-static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
-{
-}
-#endif
-
-
-static const char driver_name[] = "s3c2410fb";
-
-static int s3c24xxfb_probe(struct platform_device *pdev,
-			   enum s3c_drv_type drv_type)
-{
-	struct s3c2410fb_info *info;
-	struct s3c2410fb_display *display;
-	struct fb_info *fbinfo;
-	struct s3c2410fb_mach_info *mach_info;
-	struct resource *res;
-	int ret;
-	int irq;
-	int i;
-	int size;
-	u32 lcdcon1;
-
-	mach_info = dev_get_platdata(&pdev->dev);
-	if (mach_info == NULL) {
-		dev_err(&pdev->dev,
-			"no platform data for lcd, cannot attach\n");
-		return -EINVAL;
-	}
-
-	if (mach_info->default_display >= mach_info->num_displays) {
-		dev_err(&pdev->dev, "default is %d but only %d displays\n",
-			mach_info->default_display, mach_info->num_displays);
-		return -EINVAL;
-	}
-
-	display = mach_info->displays + mach_info->default_display;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no irq for device\n");
-		return -ENOENT;
-	}
-
-	fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);
-	if (!fbinfo)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, fbinfo);
-
-	info = fbinfo->par;
-	info->dev = &pdev->dev;
-	info->drv_type = drv_type;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "failed to get memory registers\n");
-		ret = -ENXIO;
-		goto dealloc_fb;
-	}
-
-	size = resource_size(res);
-	info->mem = request_mem_region(res->start, size, pdev->name);
-	if (info->mem == NULL) {
-		dev_err(&pdev->dev, "failed to get memory region\n");
-		ret = -ENOENT;
-		goto dealloc_fb;
-	}
-
-	info->io = ioremap(res->start, size);
-	if (info->io == NULL) {
-		dev_err(&pdev->dev, "ioremap() of registers failed\n");
-		ret = -ENXIO;
-		goto release_mem;
-	}
-
-	if (drv_type == DRV_S3C2412)
-		info->irq_base = info->io + S3C2412_LCDINTBASE;
-	else
-		info->irq_base = info->io + S3C2410_LCDINTBASE;
-
-	dprintk("devinit\n");
-
-	strcpy(fbinfo->fix.id, driver_name);
-
-	/* Stop the video */
-	lcdcon1 = readl(info->io + S3C2410_LCDCON1);
-	writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
-
-	fbinfo->fix.type	    = FB_TYPE_PACKED_PIXELS;
-	fbinfo->fix.type_aux	    = 0;
-	fbinfo->fix.xpanstep	    = 0;
-	fbinfo->fix.ypanstep	    = 0;
-	fbinfo->fix.ywrapstep	    = 0;
-	fbinfo->fix.accel	    = FB_ACCEL_NONE;
-
-	fbinfo->var.nonstd	    = 0;
-	fbinfo->var.activate	    = FB_ACTIVATE_NOW;
-	fbinfo->var.accel_flags     = 0;
-	fbinfo->var.vmode	    = FB_VMODE_NONINTERLACED;
-
-	fbinfo->fbops		    = &s3c2410fb_ops;
-	fbinfo->flags		    = FBINFO_FLAG_DEFAULT;
-	fbinfo->pseudo_palette      = &info->pseudo_pal;
-
-	for (i = 0; i < 256; i++)
-		info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
-
-	ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info);
-	if (ret) {
-		dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
-		ret = -EBUSY;
-		goto release_regs;
-	}
-
-	info->clk = clk_get(NULL, "lcd");
-	if (IS_ERR(info->clk)) {
-		dev_err(&pdev->dev, "failed to get lcd clock source\n");
-		ret = PTR_ERR(info->clk);
-		goto release_irq;
-	}
-
-	clk_enable(info->clk);
-	dprintk("got and enabled clock\n");
-
-	usleep_range(1000, 1100);
-
-	info->clk_rate = clk_get_rate(info->clk);
-
-	/* find maximum required memory size for display */
-	for (i = 0; i < mach_info->num_displays; i++) {
-		unsigned long smem_len = mach_info->displays[i].xres;
-
-		smem_len *= mach_info->displays[i].yres;
-		smem_len *= mach_info->displays[i].bpp;
-		smem_len >>= 3;
-		if (fbinfo->fix.smem_len < smem_len)
-			fbinfo->fix.smem_len = smem_len;
-	}
-
-	/* Initialize video memory */
-	ret = s3c2410fb_map_video_memory(fbinfo);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
-		ret = -ENOMEM;
-		goto release_clock;
-	}
-
-	dprintk("got video memory\n");
-
-	fbinfo->var.xres = display->xres;
-	fbinfo->var.yres = display->yres;
-	fbinfo->var.bits_per_pixel = display->bpp;
-
-	s3c2410fb_init_registers(fbinfo);
-
-	s3c2410fb_check_var(&fbinfo->var, fbinfo);
-
-	ret = s3c2410fb_cpufreq_register(info);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to register cpufreq\n");
-		goto free_video_memory;
-	}
-
-	ret = register_framebuffer(fbinfo);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n",
-			ret);
-		goto free_cpufreq;
-	}
-
-	/* create device files */
-	ret = device_create_file(&pdev->dev, &dev_attr_debug);
-	if (ret)
-		dev_err(&pdev->dev, "failed to add debug attribute\n");
-
-	dev_info(&pdev->dev, "fb%d: %s frame buffer device\n",
-		fbinfo->node, fbinfo->fix.id);
-
-	return 0;
-
- free_cpufreq:
-	s3c2410fb_cpufreq_deregister(info);
-free_video_memory:
-	s3c2410fb_unmap_video_memory(fbinfo);
-release_clock:
-	clk_disable(info->clk);
-	clk_put(info->clk);
-release_irq:
-	free_irq(irq, info);
-release_regs:
-	iounmap(info->io);
-release_mem:
-	release_mem_region(res->start, size);
-dealloc_fb:
-	framebuffer_release(fbinfo);
-	return ret;
-}
-
-static int s3c2410fb_probe(struct platform_device *pdev)
-{
-	return s3c24xxfb_probe(pdev, DRV_S3C2410);
-}
-
-static int s3c2412fb_probe(struct platform_device *pdev)
-{
-	return s3c24xxfb_probe(pdev, DRV_S3C2412);
-}
-
-
-/*
- *  Cleanup
- */
-static int s3c2410fb_remove(struct platform_device *pdev)
-{
-	struct fb_info *fbinfo = platform_get_drvdata(pdev);
-	struct s3c2410fb_info *info = fbinfo->par;
-	int irq;
-
-	unregister_framebuffer(fbinfo);
-	s3c2410fb_cpufreq_deregister(info);
-
-	s3c2410fb_lcd_enable(info, 0);
-	usleep_range(1000, 1100);
-
-	s3c2410fb_unmap_video_memory(fbinfo);
-
-	if (info->clk) {
-		clk_disable(info->clk);
-		clk_put(info->clk);
-		info->clk = NULL;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	free_irq(irq, info);
-
-	iounmap(info->io);
-
-	release_mem_region(info->mem->start, resource_size(info->mem));
-
-	framebuffer_release(fbinfo);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-/* suspend and resume support for the lcd controller */
-static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
-	struct s3c2410fb_info *info = fbinfo->par;
-
-	s3c2410fb_lcd_enable(info, 0);
-
-	/* sleep before disabling the clock, we need to ensure
-	 * the LCD DMA engine is not going to get back on the bus
-	 * before the clock goes off again (bjd) */
-
-	usleep_range(1000, 1100);
-	clk_disable(info->clk);
-
-	return 0;
-}
-
-static int s3c2410fb_resume(struct platform_device *dev)
-{
-	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
-	struct s3c2410fb_info *info = fbinfo->par;
-
-	clk_enable(info->clk);
-	usleep_range(1000, 1100);
-
-	s3c2410fb_init_registers(fbinfo);
-
-	/* re-activate our display after resume */
-	s3c2410fb_activate_var(fbinfo);
-	s3c2410fb_blank(FB_BLANK_UNBLANK, fbinfo);
-
-	return 0;
-}
-
-#else
-#define s3c2410fb_suspend NULL
-#define s3c2410fb_resume  NULL
-#endif
-
-static struct platform_driver s3c2410fb_driver = {
-	.probe		= s3c2410fb_probe,
-	.remove		= s3c2410fb_remove,
-	.suspend	= s3c2410fb_suspend,
-	.resume		= s3c2410fb_resume,
-	.driver		= {
-		.name	= "s3c2410-lcd",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver s3c2412fb_driver = {
-	.probe		= s3c2412fb_probe,
-	.remove		= s3c2410fb_remove,
-	.suspend	= s3c2410fb_suspend,
-	.resume		= s3c2410fb_resume,
-	.driver		= {
-		.name	= "s3c2412-lcd",
-		.owner	= THIS_MODULE,
-	},
-};
-
-int __init s3c2410fb_init(void)
-{
-	int ret = platform_driver_register(&s3c2410fb_driver);
-
-	if (ret == 0)
-		ret = platform_driver_register(&s3c2412fb_driver);
-
-	return ret;
-}
-
-static void __exit s3c2410fb_cleanup(void)
-{
-	platform_driver_unregister(&s3c2410fb_driver);
-	platform_driver_unregister(&s3c2412fb_driver);
-}
-
-module_init(s3c2410fb_init);
-module_exit(s3c2410fb_cleanup);
-
-MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
-MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
-MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s3c2410-lcd");
-MODULE_ALIAS("platform:s3c2412-lcd");
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
deleted file mode 100644
index 47a17bd23011..000000000000
--- a/drivers/video/s3c2410fb.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/drivers/video/s3c2410fb.h
- *	Copyright (c) 2004 Arnaud Patard
- *
- *  S3C2410 LCD Framebuffer Driver
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
-*/
-
-#ifndef __S3C2410FB_H
-#define __S3C2410FB_H
-
-enum s3c_drv_type {
-	DRV_S3C2410,
-	DRV_S3C2412,
-};
-
-struct s3c2410fb_info {
-	struct device		*dev;
-	struct clk		*clk;
-
-	struct resource		*mem;
-	void __iomem		*io;
-	void __iomem		*irq_base;
-
-	enum s3c_drv_type	drv_type;
-	struct s3c2410fb_hw	regs;
-
-	unsigned long		clk_rate;
-	unsigned int		palette_ready;
-
-#ifdef CONFIG_CPU_FREQ
-	struct notifier_block	freq_transition;
-#endif
-
-	/* keep these registers in case we need to re-write palette */
-	u32			palette_buffer[256];
-	u32			pseudo_pal[16];
-};
-
-#define PALETTE_BUFF_CLEAR (0x80000000)	/* entry is clear/invalid */
-
-int s3c2410fb_init(void);
-
-#endif
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
deleted file mode 100644
index 9a3f8f1c6aab..000000000000
--- a/drivers/video/s3fb.c
+++ /dev/null
@@ -1,1597 +0,0 @@
-/*
- * linux/drivers/video/s3fb.c -- Frame buffer device driver for S3 Trio/Virge
- *
- * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Code is based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
- * which is based on the code of neofb.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/svga.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
-#include <video/vga.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-struct s3fb_info {
-	int chip, rev, mclk_freq;
-	int mtrr_reg;
-	struct vgastate state;
-	struct mutex open_lock;
-	unsigned int ref_count;
-	u32 pseudo_palette[16];
-#ifdef CONFIG_FB_S3_DDC
-	u8 __iomem *mmio;
-	bool ddc_registered;
-	struct i2c_adapter ddc_adapter;
-	struct i2c_algo_bit_data ddc_algo;
-#endif
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-static const struct svga_fb_format s3fb_formats[] = {
-	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 16},
-	{ 4,  {0, 4, 0},  {0, 4, 0},  {0, 4, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
-	{ 4,  {0, 4, 0},  {0, 4, 0},  {0, 4, 0}, {0, 0, 0}, 1,
-		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
-	{ 8,  {0, 8, 0},  {0, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 4, 8},
-	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
-	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
-	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
-	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
-	SVGA_FORMAT_END
-};
-
-
-static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
-	35000, 240000, 14318};
-static const struct svga_pll s3_trio3d_pll = {3, 129, 3, 31, 0, 4,
-	230000, 460000, 14318};
-
-static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
-
-static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
-			"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
-			"S3 Plato/PX", "S3 Aurora64V+", "S3 Virge",
-			"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
-			"S3 Virge/GX2", "S3 Virge/GX2+", "",
-			"S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X",
-			"S3 Trio3D", "S3 Virge/MX"};
-
-#define CHIP_UNKNOWN		0x00
-#define CHIP_732_TRIO32		0x01
-#define CHIP_764_TRIO64		0x02
-#define CHIP_765_TRIO64VP	0x03
-#define CHIP_767_TRIO64UVP	0x04
-#define CHIP_775_TRIO64V2_DX	0x05
-#define CHIP_785_TRIO64V2_GX	0x06
-#define CHIP_551_PLATO_PX	0x07
-#define CHIP_M65_AURORA64VP	0x08
-#define CHIP_325_VIRGE		0x09
-#define CHIP_988_VIRGE_VX	0x0A
-#define CHIP_375_VIRGE_DX	0x0B
-#define CHIP_385_VIRGE_GX	0x0C
-#define CHIP_357_VIRGE_GX2	0x0D
-#define CHIP_359_VIRGE_GX2P	0x0E
-#define CHIP_360_TRIO3D_1X	0x10
-#define CHIP_362_TRIO3D_2X	0x11
-#define CHIP_368_TRIO3D_2X	0x12
-#define CHIP_365_TRIO3D		0x13
-#define CHIP_260_VIRGE_MX	0x14
-
-#define CHIP_XXX_TRIO		0x80
-#define CHIP_XXX_TRIO64V2_DXGX	0x81
-#define CHIP_XXX_VIRGE_DXGX	0x82
-#define CHIP_36X_TRIO3D_1X_2X	0x83
-
-#define CHIP_UNDECIDED_FLAG	0x80
-#define CHIP_MASK		0xFF
-
-#define MMIO_OFFSET		0x1000000
-#define MMIO_SIZE		0x10000
-
-/* CRT timing register sets */
-
-static const struct vga_regset s3_h_total_regs[]        = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END};
-static const struct vga_regset s3_h_display_regs[]      = {{0x01, 0, 7}, {0x5D, 1, 1}, VGA_REGSET_END};
-static const struct vga_regset s3_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x5D, 2, 2}, VGA_REGSET_END};
-static const struct vga_regset s3_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7}, VGA_REGSET_END};
-static const struct vga_regset s3_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x5D, 4, 4}, VGA_REGSET_END};
-static const struct vga_regset s3_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
-
-static const struct vga_regset s3_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x5E, 0, 0}, VGA_REGSET_END};
-static const struct vga_regset s3_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x5E, 1, 1}, VGA_REGSET_END};
-static const struct vga_regset s3_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x5E, 2, 2}, VGA_REGSET_END};
-static const struct vga_regset s3_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
-static const struct vga_regset s3_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x5E, 4, 4}, VGA_REGSET_END};
-static const struct vga_regset s3_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
-
-static const struct vga_regset s3_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END};
-static const struct vga_regset s3_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x69, 0, 4}, VGA_REGSET_END};
-static const struct vga_regset s3_offset_regs[]         = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */
-
-static const struct vga_regset s3_dtpc_regs[]		= {{0x3B, 0, 7}, {0x5D, 6, 6}, VGA_REGSET_END};
-
-static const struct svga_timing_regs s3_timing_regs     = {
-	s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs,
-	s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs,
-	s3_v_total_regs, s3_v_display_regs, s3_v_blank_start_regs,
-	s3_v_blank_end_regs, s3_v_sync_start_regs, s3_v_sync_end_regs,
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Module parameters */
-
-
-static char *mode_option;
-
-#ifdef CONFIG_MTRR
-static int mtrr = 1;
-#endif
-
-static int fasttext = 1;
-
-
-MODULE_AUTHOR("(c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("fbdev driver for S3 Trio/Virge");
-
-module_param(mode_option, charp, 0444);
-MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
-module_param_named(mode, mode_option, charp, 0444);
-MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
-
-#ifdef CONFIG_MTRR
-module_param(mtrr, int, 0444);
-MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
-#endif
-
-module_param(fasttext, int, 0644);
-MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, default=1)");
-
-
-/* ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_FB_S3_DDC
-
-#define DDC_REG		0xaa		/* Trio 3D/1X/2X */
-#define DDC_MMIO_REG	0xff20		/* all other chips */
-#define DDC_SCL_OUT	(1 << 0)
-#define DDC_SDA_OUT	(1 << 1)
-#define DDC_SCL_IN	(1 << 2)
-#define DDC_SDA_IN	(1 << 3)
-#define DDC_DRIVE_EN	(1 << 4)
-
-static bool s3fb_ddc_needs_mmio(int chip)
-{
-	return !(chip == CHIP_360_TRIO3D_1X  ||
-		 chip == CHIP_362_TRIO3D_2X  ||
-		 chip == CHIP_368_TRIO3D_2X);
-}
-
-static u8 s3fb_ddc_read(struct s3fb_info *par)
-{
-	if (s3fb_ddc_needs_mmio(par->chip))
-		return readb(par->mmio + DDC_MMIO_REG);
-	else
-		return vga_rcrt(par->state.vgabase, DDC_REG);
-}
-
-static void s3fb_ddc_write(struct s3fb_info *par, u8 val)
-{
-	if (s3fb_ddc_needs_mmio(par->chip))
-		writeb(val, par->mmio + DDC_MMIO_REG);
-	else
-		vga_wcrt(par->state.vgabase, DDC_REG, val);
-}
-
-static void s3fb_ddc_setscl(void *data, int val)
-{
-	struct s3fb_info *par = data;
-	unsigned char reg;
-
-	reg = s3fb_ddc_read(par) | DDC_DRIVE_EN;
-	if (val)
-		reg |= DDC_SCL_OUT;
-	else
-		reg &= ~DDC_SCL_OUT;
-	s3fb_ddc_write(par, reg);
-}
-
-static void s3fb_ddc_setsda(void *data, int val)
-{
-	struct s3fb_info *par = data;
-	unsigned char reg;
-
-	reg = s3fb_ddc_read(par) | DDC_DRIVE_EN;
-	if (val)
-		reg |= DDC_SDA_OUT;
-	else
-		reg &= ~DDC_SDA_OUT;
-	s3fb_ddc_write(par, reg);
-}
-
-static int s3fb_ddc_getscl(void *data)
-{
-	struct s3fb_info *par = data;
-
-	return !!(s3fb_ddc_read(par) & DDC_SCL_IN);
-}
-
-static int s3fb_ddc_getsda(void *data)
-{
-	struct s3fb_info *par = data;
-
-	return !!(s3fb_ddc_read(par) & DDC_SDA_IN);
-}
-
-static int s3fb_setup_ddc_bus(struct fb_info *info)
-{
-	struct s3fb_info *par = info->par;
-
-	strlcpy(par->ddc_adapter.name, info->fix.id,
-		sizeof(par->ddc_adapter.name));
-	par->ddc_adapter.owner		= THIS_MODULE;
-	par->ddc_adapter.class		= I2C_CLASS_DDC;
-	par->ddc_adapter.algo_data	= &par->ddc_algo;
-	par->ddc_adapter.dev.parent	= info->device;
-	par->ddc_algo.setsda		= s3fb_ddc_setsda;
-	par->ddc_algo.setscl		= s3fb_ddc_setscl;
-	par->ddc_algo.getsda		= s3fb_ddc_getsda;
-	par->ddc_algo.getscl		= s3fb_ddc_getscl;
-	par->ddc_algo.udelay		= 10;
-	par->ddc_algo.timeout		= 20;
-	par->ddc_algo.data		= par;
-
-	i2c_set_adapdata(&par->ddc_adapter, par);
-
-	/*
-	 * some Virge cards have external MUX to switch chip I2C bus between
-	 * DDC and extension pins - switch it do DDC
-	 */
-/*	vga_wseq(par->state.vgabase, 0x08, 0x06); - not needed, already unlocked */
-	if (par->chip == CHIP_357_VIRGE_GX2 ||
-	    par->chip == CHIP_359_VIRGE_GX2P ||
-	    par->chip == CHIP_260_VIRGE_MX)
-		svga_wseq_mask(par->state.vgabase, 0x0d, 0x01, 0x03);
-	else
-		svga_wseq_mask(par->state.vgabase, 0x0d, 0x00, 0x03);
-	/* some Virge need this or the DDC is ignored */
-	svga_wcrt_mask(par->state.vgabase, 0x5c, 0x03, 0x03);
-
-	return i2c_bit_add_bus(&par->ddc_adapter);
-}
-#endif /* CONFIG_FB_S3_DDC */
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Set font in S3 fast text mode */
-
-static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
-{
-	const u8 *font = map->data;
-	u8 __iomem *fb = (u8 __iomem *) info->screen_base;
-	int i, c;
-
-	if ((map->width != 8) || (map->height != 16) ||
-	    (map->depth != 1) || (map->length != 256)) {
-		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
-		       map->width, map->height, map->depth, map->length);
-		return;
-	}
-
-	fb += 2;
-	for (i = 0; i < map->height; i++) {
-		for (c = 0; c < map->length; c++) {
-			fb_writeb(font[c * map->height + i], fb + c * 4);
-		}
-		fb += 1024;
-	}
-}
-
-static void s3fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
-{
-	struct s3fb_info *par = info->par;
-
-	svga_tilecursor(par->state.vgabase, info, cursor);
-}
-
-static struct fb_tile_ops s3fb_tile_ops = {
-	.fb_settile	= svga_settile,
-	.fb_tilecopy	= svga_tilecopy,
-	.fb_tilefill    = svga_tilefill,
-	.fb_tileblit    = svga_tileblit,
-	.fb_tilecursor  = s3fb_tilecursor,
-	.fb_get_tilemax = svga_get_tilemax,
-};
-
-static struct fb_tile_ops s3fb_fast_tile_ops = {
-	.fb_settile	= s3fb_settile_fast,
-	.fb_tilecopy	= svga_tilecopy,
-	.fb_tilefill    = svga_tilefill,
-	.fb_tileblit    = svga_tileblit,
-	.fb_tilecursor  = s3fb_tilecursor,
-	.fb_get_tilemax = svga_get_tilemax,
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-/* image data is MSB-first, fb structure is MSB-first too */
-static inline u32 expand_color(u32 c)
-{
-	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
-}
-
-/* s3fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
-static void s3fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	u32 fg = expand_color(image->fg_color);
-	u32 bg = expand_color(image->bg_color);
-	const u8 *src1, *src;
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	u32 val;
-	int x, y;
-
-	src1 = image->data;
-	dst1 = info->screen_base + (image->dy * info->fix.line_length)
-		 + ((image->dx / 8) * 4);
-
-	for (y = 0; y < image->height; y++) {
-		src = src1;
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < image->width; x += 8) {
-			val = *(src++) * 0x01010101;
-			val = (val & fg) | (~val & bg);
-			fb_writel(val, dst++);
-		}
-		src1 += image->width / 8;
-		dst1 += info->fix.line_length;
-	}
-
-}
-
-/* s3fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
-static void s3fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	u32 fg = expand_color(rect->color);
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	int x, y;
-
-	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
-		 + ((rect->dx / 8) * 4);
-
-	for (y = 0; y < rect->height; y++) {
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < rect->width; x += 8) {
-			fb_writel(fg, dst++);
-		}
-		dst1 += info->fix.line_length;
-	}
-}
-
-
-/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
-static inline u32 expand_pixel(u32 c)
-{
-	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
-		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
-}
-
-/* s3fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
-static void s3fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	u32 fg = image->fg_color * 0x11111111;
-	u32 bg = image->bg_color * 0x11111111;
-	const u8 *src1, *src;
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	u32 val;
-	int x, y;
-
-	src1 = image->data;
-	dst1 = info->screen_base + (image->dy * info->fix.line_length)
-		 + ((image->dx / 8) * 4);
-
-	for (y = 0; y < image->height; y++) {
-		src = src1;
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < image->width; x += 8) {
-			val = expand_pixel(*(src++));
-			val = (val & fg) | (~val & bg);
-			fb_writel(val, dst++);
-		}
-		src1 += image->width / 8;
-		dst1 += info->fix.line_length;
-	}
-}
-
-static void s3fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
-	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
-		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
-			s3fb_iplan_imageblit(info, image);
-		else
-			s3fb_cfb4_imageblit(info, image);
-	} else
-		cfb_imageblit(info, image);
-}
-
-static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	if ((info->var.bits_per_pixel == 4)
-	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
-	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
-		s3fb_iplan_fillrect(info, rect);
-	 else
-		cfb_fillrect(info, rect);
-}
-
-
-
-/* ------------------------------------------------------------------------- */
-
-
-static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
-{
-	struct s3fb_info *par = info->par;
-	u16 m, n, r;
-	u8 regval;
-	int rv;
-
-	rv = svga_compute_pll((par->chip == CHIP_365_TRIO3D) ? &s3_trio3d_pll : &s3_pll,
-			      1000000000 / pixclock, &m, &n, &r, info->node);
-	if (rv < 0) {
-		fb_err(info, "cannot set requested pixclock, keeping old value\n");
-		return;
-	}
-
-	/* Set VGA misc register  */
-	regval = vga_r(par->state.vgabase, VGA_MIS_R);
-	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
-
-	/* Set S3 clock registers */
-	if (par->chip == CHIP_357_VIRGE_GX2 ||
-	    par->chip == CHIP_359_VIRGE_GX2P ||
-	    par->chip == CHIP_360_TRIO3D_1X ||
-	    par->chip == CHIP_362_TRIO3D_2X ||
-	    par->chip == CHIP_368_TRIO3D_2X ||
-	    par->chip == CHIP_260_VIRGE_MX) {
-		vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6));	/* n and two bits of r */
-		vga_wseq(par->state.vgabase, 0x29, r >> 2); /* remaining highest bit of r */
-	} else
-		vga_wseq(par->state.vgabase, 0x12, (n - 2) | (r << 5));
-	vga_wseq(par->state.vgabase, 0x13, m - 2);
-
-	udelay(1000);
-
-	/* Activate clock - write 0, 1, 0 to seq/15 bit 5 */
-	regval = vga_rseq (par->state.vgabase, 0x15); /* | 0x80; */
-	vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5));
-	vga_wseq(par->state.vgabase, 0x15, regval |  (1<<5));
-	vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5));
-}
-
-
-/* Open framebuffer */
-
-static int s3fb_open(struct fb_info *info, int user)
-{
-	struct s3fb_info *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	if (par->ref_count == 0) {
-		void __iomem *vgabase = par->state.vgabase;
-
-		memset(&(par->state), 0, sizeof(struct vgastate));
-		par->state.vgabase = vgabase;
-		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
-		par->state.num_crtc = 0x70;
-		par->state.num_seq = 0x20;
-		save_vga(&(par->state));
-	}
-
-	par->ref_count++;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-/* Close framebuffer */
-
-static int s3fb_release(struct fb_info *info, int user)
-{
-	struct s3fb_info *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	if (par->ref_count == 0) {
-		mutex_unlock(&(par->open_lock));
-		return -EINVAL;
-	}
-
-	if (par->ref_count == 1)
-		restore_vga(&(par->state));
-
-	par->ref_count--;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-/* Validate passed in var */
-
-static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct s3fb_info *par = info->par;
-	int rv, mem, step;
-	u16 m, n, r;
-
-	/* Find appropriate format */
-	rv = svga_match_format (s3fb_formats, var, NULL);
-
-	/* 32bpp mode is not supported on VIRGE VX,
-	   24bpp is not supported on others */
-	if ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6))
-		rv = -EINVAL;
-
-	if (rv < 0) {
-		fb_err(info, "unsupported mode requested\n");
-		return rv;
-	}
-
-	/* Do not allow to have real resoulution larger than virtual */
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-
-	/* Round up xres_virtual to have proper alignment of lines */
-	step = s3fb_formats[rv].xresstep - 1;
-	var->xres_virtual = (var->xres_virtual+step) & ~step;
-
-	/* Check whether have enough memory */
-	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
-	if (mem > info->screen_size) {
-		fb_err(info, "not enough framebuffer memory (%d kB requested , %u kB available)\n",
-		       mem >> 10, (unsigned int) (info->screen_size >> 10));
-		return -EINVAL;
-	}
-
-	rv = svga_check_timings (&s3_timing_regs, var, info->node);
-	if (rv < 0) {
-		fb_err(info, "invalid timings requested\n");
-		return rv;
-	}
-
-	rv = svga_compute_pll(&s3_pll, PICOS2KHZ(var->pixclock), &m, &n, &r,
-				info->node);
-	if (rv < 0) {
-		fb_err(info, "invalid pixclock value requested\n");
-		return rv;
-	}
-
-	return 0;
-}
-
-/* Set video mode from par */
-
-static int s3fb_set_par(struct fb_info *info)
-{
-	struct s3fb_info *par = info->par;
-	u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes;
-	u32 bpp = info->var.bits_per_pixel;
-	u32 htotal, hsstart;
-
-	if (bpp != 0) {
-		info->fix.ypanstep = 1;
-		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
-
-		info->flags &= ~FBINFO_MISC_TILEBLITTING;
-		info->tileops = NULL;
-
-		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
-		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
-		info->pixmap.blit_y = ~(u32)0;
-
-		offset_value = (info->var.xres_virtual * bpp) / 64;
-		screen_size = info->var.yres_virtual * info->fix.line_length;
-	} else {
-		info->fix.ypanstep = 16;
-		info->fix.line_length = 0;
-
-		info->flags |= FBINFO_MISC_TILEBLITTING;
-		info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
-
-		/* supports 8x16 tiles only */
-		info->pixmap.blit_x = 1 << (8 - 1);
-		info->pixmap.blit_y = 1 << (16 - 1);
-
-		offset_value = info->var.xres_virtual / 16;
-		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
-	}
-
-	info->var.xoffset = 0;
-	info->var.yoffset = 0;
-	info->var.activate = FB_ACTIVATE_NOW;
-
-	/* Unlock registers */
-	vga_wcrt(par->state.vgabase, 0x38, 0x48);
-	vga_wcrt(par->state.vgabase, 0x39, 0xA5);
-	vga_wseq(par->state.vgabase, 0x08, 0x06);
-	svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
-
-	/* Blank screen and turn off sync */
-	svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-	svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
-
-	/* Set default values */
-	svga_set_default_gfx_regs(par->state.vgabase);
-	svga_set_default_atc_regs(par->state.vgabase);
-	svga_set_default_seq_regs(par->state.vgabase);
-	svga_set_default_crt_regs(par->state.vgabase);
-	svga_wcrt_multi(par->state.vgabase, s3_line_compare_regs, 0xFFFFFFFF);
-	svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, 0);
-
-	/* S3 specific initialization */
-	svga_wcrt_mask(par->state.vgabase, 0x58, 0x10, 0x10); /* enable linear framebuffer */
-	svga_wcrt_mask(par->state.vgabase, 0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */
-
-/*	svga_wcrt_mask(par->state.vgabase, 0x33, 0x08, 0x08); */ /* DDR ?	*/
-/*	svga_wcrt_mask(par->state.vgabase, 0x43, 0x01, 0x01); */ /* DDR ?	*/
-	svga_wcrt_mask(par->state.vgabase, 0x33, 0x00, 0x08); /* no DDR ?	*/
-	svga_wcrt_mask(par->state.vgabase, 0x43, 0x00, 0x01); /* no DDR ?	*/
-
-	svga_wcrt_mask(par->state.vgabase, 0x5D, 0x00, 0x28); /* Clear strange HSlen bits */
-
-/*	svga_wcrt_mask(par->state.vgabase, 0x58, 0x03, 0x03); */
-
-/*	svga_wcrt_mask(par->state.vgabase, 0x53, 0x12, 0x13); */ /* enable MMIO */
-/*	svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08); */ /* enable write buffer */
-
-
-	/* Set the offset register */
-	fb_dbg(info, "offset register       : %d\n", offset_value);
-	svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value);
-
-	if (par->chip != CHIP_357_VIRGE_GX2 &&
-	    par->chip != CHIP_359_VIRGE_GX2P &&
-	    par->chip != CHIP_360_TRIO3D_1X &&
-	    par->chip != CHIP_362_TRIO3D_2X &&
-	    par->chip != CHIP_368_TRIO3D_2X &&
-	    par->chip != CHIP_260_VIRGE_MX) {
-		vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */
-		vga_wcrt(par->state.vgabase, 0x60, 0xff); /* N parameter */
-		vga_wcrt(par->state.vgabase, 0x61, 0xff); /* L parameter */
-		vga_wcrt(par->state.vgabase, 0x62, 0xff); /* L parameter */
-	}
-
-	vga_wcrt(par->state.vgabase, 0x3A, 0x35);
-	svga_wattr(par->state.vgabase, 0x33, 0x00);
-
-	if (info->var.vmode & FB_VMODE_DOUBLE)
-		svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
-	else
-		svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
-
-	if (info->var.vmode & FB_VMODE_INTERLACED)
-		svga_wcrt_mask(par->state.vgabase, 0x42, 0x20, 0x20);
-	else
-		svga_wcrt_mask(par->state.vgabase, 0x42, 0x00, 0x20);
-
-	/* Disable hardware graphics cursor */
-	svga_wcrt_mask(par->state.vgabase, 0x45, 0x00, 0x01);
-	/* Disable Streams engine */
-	svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0x0C);
-
-	mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));
-
-	/* S3 virge DX hack */
-	if (par->chip == CHIP_375_VIRGE_DX) {
-		vga_wcrt(par->state.vgabase, 0x86, 0x80);
-		vga_wcrt(par->state.vgabase, 0x90, 0x00);
-	}
-
-	/* S3 virge VX hack */
-	if (par->chip == CHIP_988_VIRGE_VX) {
-		vga_wcrt(par->state.vgabase, 0x50, 0x00);
-		vga_wcrt(par->state.vgabase, 0x67, 0x50);
-		msleep(10); /* screen remains blank sometimes without this */
-		vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
-		vga_wcrt(par->state.vgabase, 0x66, 0x90);
-	}
-
-	if (par->chip == CHIP_357_VIRGE_GX2 ||
-	    par->chip == CHIP_359_VIRGE_GX2P ||
-	    par->chip == CHIP_360_TRIO3D_1X ||
-	    par->chip == CHIP_362_TRIO3D_2X ||
-	    par->chip == CHIP_368_TRIO3D_2X ||
-	    par->chip == CHIP_365_TRIO3D    ||
-	    par->chip == CHIP_375_VIRGE_DX  ||
-	    par->chip == CHIP_385_VIRGE_GX  ||
-	    par->chip == CHIP_260_VIRGE_MX) {
-		dbytes = info->var.xres * ((bpp+7)/8);
-		vga_wcrt(par->state.vgabase, 0x91, (dbytes + 7) / 8);
-		vga_wcrt(par->state.vgabase, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80);
-
-		vga_wcrt(par->state.vgabase, 0x66, 0x81);
-	}
-
-	if (par->chip == CHIP_357_VIRGE_GX2  ||
-	    par->chip == CHIP_359_VIRGE_GX2P ||
-	    par->chip == CHIP_360_TRIO3D_1X ||
-	    par->chip == CHIP_362_TRIO3D_2X ||
-	    par->chip == CHIP_368_TRIO3D_2X ||
-	    par->chip == CHIP_260_VIRGE_MX)
-		vga_wcrt(par->state.vgabase, 0x34, 0x00);
-	else	/* enable Data Transfer Position Control (DTPC) */
-		vga_wcrt(par->state.vgabase, 0x34, 0x10);
-
-	svga_wcrt_mask(par->state.vgabase, 0x31, 0x00, 0x40);
-	multiplex = 0;
-	hmul = 1;
-
-	/* Set mode-specific register values */
-	switch (mode) {
-	case 0:
-		fb_dbg(info, "text mode\n");
-		svga_set_textmode_vga_regs(par->state.vgabase);
-
-		/* Set additional registers like in 8-bit mode */
-		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
-		svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
-
-		/* Disable enhanced mode */
-		svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
-
-		if (fasttext) {
-			fb_dbg(info, "high speed text mode set\n");
-			svga_wcrt_mask(par->state.vgabase, 0x31, 0x40, 0x40);
-		}
-		break;
-	case 1:
-		fb_dbg(info, "4 bit pseudocolor\n");
-		vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
-
-		/* Set additional registers like in 8-bit mode */
-		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
-		svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
-
-		/* disable enhanced mode */
-		svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
-		break;
-	case 2:
-		fb_dbg(info, "4 bit pseudocolor, planar\n");
-
-		/* Set additional registers like in 8-bit mode */
-		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
-		svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
-
-		/* disable enhanced mode */
-		svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
-		break;
-	case 3:
-		fb_dbg(info, "8 bit pseudocolor\n");
-		svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
-		if (info->var.pixclock > 20000 ||
-		    par->chip == CHIP_357_VIRGE_GX2 ||
-		    par->chip == CHIP_359_VIRGE_GX2P ||
-		    par->chip == CHIP_360_TRIO3D_1X ||
-		    par->chip == CHIP_362_TRIO3D_2X ||
-		    par->chip == CHIP_368_TRIO3D_2X ||
-		    par->chip == CHIP_260_VIRGE_MX)
-			svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
-		else {
-			svga_wcrt_mask(par->state.vgabase, 0x67, 0x10, 0xF0);
-			multiplex = 1;
-		}
-		break;
-	case 4:
-		fb_dbg(info, "5/5/5 truecolor\n");
-		if (par->chip == CHIP_988_VIRGE_VX) {
-			if (info->var.pixclock > 20000)
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0);
-			else
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
-		} else if (par->chip == CHIP_365_TRIO3D) {
-			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
-			if (info->var.pixclock > 8695) {
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
-				hmul = 2;
-			} else {
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0);
-				multiplex = 1;
-			}
-		} else {
-			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
-			svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
-			if (par->chip != CHIP_357_VIRGE_GX2 &&
-			    par->chip != CHIP_359_VIRGE_GX2P &&
-			    par->chip != CHIP_360_TRIO3D_1X &&
-			    par->chip != CHIP_362_TRIO3D_2X &&
-			    par->chip != CHIP_368_TRIO3D_2X &&
-			    par->chip != CHIP_260_VIRGE_MX)
-				hmul = 2;
-		}
-		break;
-	case 5:
-		fb_dbg(info, "5/6/5 truecolor\n");
-		if (par->chip == CHIP_988_VIRGE_VX) {
-			if (info->var.pixclock > 20000)
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0);
-			else
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
-		} else if (par->chip == CHIP_365_TRIO3D) {
-			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
-			if (info->var.pixclock > 8695) {
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
-				hmul = 2;
-			} else {
-				svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0);
-				multiplex = 1;
-			}
-		} else {
-			svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
-			svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
-			if (par->chip != CHIP_357_VIRGE_GX2 &&
-			    par->chip != CHIP_359_VIRGE_GX2P &&
-			    par->chip != CHIP_360_TRIO3D_1X &&
-			    par->chip != CHIP_362_TRIO3D_2X &&
-			    par->chip != CHIP_368_TRIO3D_2X &&
-			    par->chip != CHIP_260_VIRGE_MX)
-				hmul = 2;
-		}
-		break;
-	case 6:
-		/* VIRGE VX case */
-		fb_dbg(info, "8/8/8 truecolor\n");
-		svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
-		break;
-	case 7:
-		fb_dbg(info, "8/8/8/8 truecolor\n");
-		svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30);
-		svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
-		break;
-	default:
-		fb_err(info, "unsupported mode - bug\n");
-		return -EINVAL;
-	}
-
-	if (par->chip != CHIP_988_VIRGE_VX) {
-		svga_wseq_mask(par->state.vgabase, 0x15, multiplex ? 0x10 : 0x00, 0x10);
-		svga_wseq_mask(par->state.vgabase, 0x18, multiplex ? 0x80 : 0x00, 0x80);
-	}
-
-	s3_set_pixclock(info, info->var.pixclock);
-	svga_set_timings(par->state.vgabase, &s3_timing_regs, &(info->var), hmul, 1,
-			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
-			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
-			 hmul, info->node);
-
-	/* Set interlaced mode start/end register */
-	htotal = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
-	htotal = ((htotal * hmul) / 8) - 5;
-	vga_wcrt(par->state.vgabase, 0x3C, (htotal + 1) / 2);
-
-	/* Set Data Transfer Position */
-	hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8;
-	/* + 2 is needed for Virge/VX, does no harm on other cards */
-	value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1);
-	svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value);
-
-	memset_io(info->screen_base, 0x00, screen_size);
-	/* Device and screen back on */
-	svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
-	svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
-
-	return 0;
-}
-
-/* Set a colour register */
-
-static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-				u_int transp, struct fb_info *fb)
-{
-	switch (fb->var.bits_per_pixel) {
-	case 0:
-	case 4:
-		if (regno >= 16)
-			return -EINVAL;
-
-		if ((fb->var.bits_per_pixel == 4) &&
-		    (fb->var.nonstd == 0)) {
-			outb(0xF0, VGA_PEL_MSK);
-			outb(regno*16, VGA_PEL_IW);
-		} else {
-			outb(0x0F, VGA_PEL_MSK);
-			outb(regno, VGA_PEL_IW);
-		}
-		outb(red >> 10, VGA_PEL_D);
-		outb(green >> 10, VGA_PEL_D);
-		outb(blue >> 10, VGA_PEL_D);
-		break;
-	case 8:
-		if (regno >= 256)
-			return -EINVAL;
-
-		outb(0xFF, VGA_PEL_MSK);
-		outb(regno, VGA_PEL_IW);
-		outb(red >> 10, VGA_PEL_D);
-		outb(green >> 10, VGA_PEL_D);
-		outb(blue >> 10, VGA_PEL_D);
-		break;
-	case 16:
-		if (regno >= 16)
-			return 0;
-
-		if (fb->var.green.length == 5)
-			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
-				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
-		else if (fb->var.green.length == 6)
-			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
-				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-		else return -EINVAL;
-		break;
-	case 24:
-	case 32:
-		if (regno >= 16)
-			return 0;
-
-		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
-			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
-/* Set the display blanking state */
-
-static int s3fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct s3fb_info *par = info->par;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		fb_dbg(info, "unblank\n");
-		svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
-		break;
-	case FB_BLANK_NORMAL:
-		fb_dbg(info, "blank\n");
-		svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		fb_dbg(info, "hsync\n");
-		svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		fb_dbg(info, "vsync\n");
-		svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	case FB_BLANK_POWERDOWN:
-		fb_dbg(info, "sync down\n");
-		svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	}
-
-	return 0;
-}
-
-
-/* Pan the display */
-
-static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct s3fb_info *par = info->par;
-	unsigned int offset;
-
-	/* Calculate the offset */
-	if (info->var.bits_per_pixel == 0) {
-		offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
-		       + (var->xoffset / 2);
-		offset = offset >> 2;
-	} else {
-		offset = (var->yoffset * info->fix.line_length) +
-			 (var->xoffset * info->var.bits_per_pixel / 8);
-		offset = offset >> 2;
-	}
-
-	/* Set the offset */
-	svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, offset);
-
-	return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* Frame buffer operations */
-
-static struct fb_ops s3fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= s3fb_open,
-	.fb_release	= s3fb_release,
-	.fb_check_var	= s3fb_check_var,
-	.fb_set_par	= s3fb_set_par,
-	.fb_setcolreg	= s3fb_setcolreg,
-	.fb_blank	= s3fb_blank,
-	.fb_pan_display	= s3fb_pan_display,
-	.fb_fillrect	= s3fb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= s3fb_imageblit,
-	.fb_get_caps    = svga_get_caps,
-};
-
-/* ------------------------------------------------------------------------- */
-
-static int s3_identification(struct s3fb_info *par)
-{
-	int chip = par->chip;
-
-	if (chip == CHIP_XXX_TRIO) {
-		u8 cr30 = vga_rcrt(par->state.vgabase, 0x30);
-		u8 cr2e = vga_rcrt(par->state.vgabase, 0x2e);
-		u8 cr2f = vga_rcrt(par->state.vgabase, 0x2f);
-
-		if ((cr30 == 0xE0) || (cr30 == 0xE1)) {
-			if (cr2e == 0x10)
-				return CHIP_732_TRIO32;
-			if (cr2e == 0x11) {
-				if (! (cr2f & 0x40))
-					return CHIP_764_TRIO64;
-				else
-					return CHIP_765_TRIO64VP;
-			}
-		}
-	}
-
-	if (chip == CHIP_XXX_TRIO64V2_DXGX) {
-		u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f);
-
-		if (! (cr6f & 0x01))
-			return CHIP_775_TRIO64V2_DX;
-		else
-			return CHIP_785_TRIO64V2_GX;
-	}
-
-	if (chip == CHIP_XXX_VIRGE_DXGX) {
-		u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f);
-
-		if (! (cr6f & 0x01))
-			return CHIP_375_VIRGE_DX;
-		else
-			return CHIP_385_VIRGE_GX;
-	}
-
-	if (chip == CHIP_36X_TRIO3D_1X_2X) {
-		switch (vga_rcrt(par->state.vgabase, 0x2f)) {
-		case 0x00:
-			return CHIP_360_TRIO3D_1X;
-		case 0x01:
-			return CHIP_362_TRIO3D_2X;
-		case 0x02:
-			return CHIP_368_TRIO3D_2X;
-		}
-	}
-
-	return CHIP_UNKNOWN;
-}
-
-
-/* PCI probe */
-
-static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct pci_bus_region bus_reg;
-	struct resource vga_res;
-	struct fb_info *info;
-	struct s3fb_info *par;
-	int rc;
-	u8 regval, cr38, cr39;
-	bool found = false;
-
-	/* Ignore secondary VGA device because there is no VGA arbitration */
-	if (! svga_primary_device(dev)) {
-		dev_info(&(dev->dev), "ignoring secondary device\n");
-		return -ENODEV;
-	}
-
-	/* Allocate and fill driver data structure */
-	info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev));
-	if (!info) {
-		dev_err(&(dev->dev), "cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	mutex_init(&par->open_lock);
-
-	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
-	info->fbops = &s3fb_ops;
-
-	/* Prepare PCI device */
-	rc = pci_enable_device(dev);
-	if (rc < 0) {
-		dev_err(info->device, "cannot enable PCI device\n");
-		goto err_enable_device;
-	}
-
-	rc = pci_request_regions(dev, "s3fb");
-	if (rc < 0) {
-		dev_err(info->device, "cannot reserve framebuffer region\n");
-		goto err_request_regions;
-	}
-
-
-	info->fix.smem_start = pci_resource_start(dev, 0);
-	info->fix.smem_len = pci_resource_len(dev, 0);
-
-	/* Map physical IO memory address into kernel space */
-	info->screen_base = pci_iomap(dev, 0, 0);
-	if (! info->screen_base) {
-		rc = -ENOMEM;
-		dev_err(info->device, "iomap for framebuffer failed\n");
-		goto err_iomap;
-	}
-
-	bus_reg.start = 0;
-	bus_reg.end = 64 * 1024;
-
-	vga_res.flags = IORESOURCE_IO;
-
-	pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
-
-	par->state.vgabase = (void __iomem *) vga_res.start;
-
-	/* Unlock regs */
-	cr38 = vga_rcrt(par->state.vgabase, 0x38);
-	cr39 = vga_rcrt(par->state.vgabase, 0x39);
-	vga_wseq(par->state.vgabase, 0x08, 0x06);
-	vga_wcrt(par->state.vgabase, 0x38, 0x48);
-	vga_wcrt(par->state.vgabase, 0x39, 0xA5);
-
-	/* Identify chip type */
-	par->chip = id->driver_data & CHIP_MASK;
-	par->rev = vga_rcrt(par->state.vgabase, 0x2f);
-	if (par->chip & CHIP_UNDECIDED_FLAG)
-		par->chip = s3_identification(par);
-
-	/* Find how many physical memory there is on card */
-	/* 0x36 register is accessible even if other registers are locked */
-	regval = vga_rcrt(par->state.vgabase, 0x36);
-	if (par->chip == CHIP_360_TRIO3D_1X ||
-	    par->chip == CHIP_362_TRIO3D_2X ||
-	    par->chip == CHIP_368_TRIO3D_2X ||
-	    par->chip == CHIP_365_TRIO3D) {
-		switch ((regval & 0xE0) >> 5) {
-		case 0: /* 8MB -- only 4MB usable for display */
-		case 1: /* 4MB with 32-bit bus */
-		case 2:	/* 4MB */
-			info->screen_size = 4 << 20;
-			break;
-		case 4: /* 2MB on 365 Trio3D */
-		case 6: /* 2MB */
-			info->screen_size = 2 << 20;
-			break;
-		}
-	} else if (par->chip == CHIP_357_VIRGE_GX2 ||
-		   par->chip == CHIP_359_VIRGE_GX2P ||
-		   par->chip == CHIP_260_VIRGE_MX) {
-		switch ((regval & 0xC0) >> 6) {
-		case 1: /* 4MB */
-			info->screen_size = 4 << 20;
-			break;
-		case 3: /* 2MB */
-			info->screen_size = 2 << 20;
-			break;
-		}
-	} else if (par->chip == CHIP_988_VIRGE_VX) {
-		switch ((regval & 0x60) >> 5) {
-		case 0: /* 2MB */
-			info->screen_size = 2 << 20;
-			break;
-		case 1: /* 4MB */
-			info->screen_size = 4 << 20;
-			break;
-		case 2: /* 6MB */
-			info->screen_size = 6 << 20;
-			break;
-		case 3: /* 8MB */
-			info->screen_size = 8 << 20;
-			break;
-		}
-		/* off-screen memory */
-		regval = vga_rcrt(par->state.vgabase, 0x37);
-		switch ((regval & 0x60) >> 5) {
-		case 1: /* 4MB */
-			info->screen_size -= 4 << 20;
-			break;
-		case 2: /* 2MB */
-			info->screen_size -= 2 << 20;
-			break;
-		}
-	} else
-		info->screen_size = s3_memsizes[regval >> 5] << 10;
-	info->fix.smem_len = info->screen_size;
-
-	/* Find MCLK frequency */
-	regval = vga_rseq(par->state.vgabase, 0x10);
-	par->mclk_freq = ((vga_rseq(par->state.vgabase, 0x11) + 2) * 14318) / ((regval & 0x1F)  + 2);
-	par->mclk_freq = par->mclk_freq >> (regval >> 5);
-
-	/* Restore locks */
-	vga_wcrt(par->state.vgabase, 0x38, cr38);
-	vga_wcrt(par->state.vgabase, 0x39, cr39);
-
-	strcpy(info->fix.id, s3_names [par->chip]);
-	info->fix.mmio_start = 0;
-	info->fix.mmio_len = 0;
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	info->fix.ypanstep = 0;
-	info->fix.accel = FB_ACCEL_NONE;
-	info->pseudo_palette = (void*) (par->pseudo_palette);
-	info->var.bits_per_pixel = 8;
-
-#ifdef CONFIG_FB_S3_DDC
-	/* Enable MMIO if needed */
-	if (s3fb_ddc_needs_mmio(par->chip)) {
-		par->mmio = ioremap(info->fix.smem_start + MMIO_OFFSET, MMIO_SIZE);
-		if (par->mmio)
-			svga_wcrt_mask(par->state.vgabase, 0x53, 0x08, 0x08);	/* enable MMIO */
-		else
-			dev_err(info->device, "unable to map MMIO at 0x%lx, disabling DDC",
-				info->fix.smem_start + MMIO_OFFSET);
-	}
-	if (!s3fb_ddc_needs_mmio(par->chip) || par->mmio)
-		if (s3fb_setup_ddc_bus(info) == 0) {
-			u8 *edid = fb_ddc_read(&par->ddc_adapter);
-			par->ddc_registered = true;
-			if (edid) {
-				fb_edid_to_monspecs(edid, &info->monspecs);
-				kfree(edid);
-				if (!info->monspecs.modedb)
-					dev_err(info->device, "error getting mode database\n");
-				else {
-					const struct fb_videomode *m;
-
-					fb_videomode_to_modelist(info->monspecs.modedb,
-								 info->monspecs.modedb_len,
-								 &info->modelist);
-					m = fb_find_best_display(&info->monspecs, &info->modelist);
-					if (m) {
-						fb_videomode_to_var(&info->var, m);
-						/* fill all other info->var's fields */
-						if (s3fb_check_var(&info->var, info) == 0)
-							found = true;
-					}
-				}
-			}
-		}
-#endif
-	if (!mode_option && !found)
-		mode_option = "640x480-8@60";
-
-	/* Prepare startup mode */
-	if (mode_option) {
-		rc = fb_find_mode(&info->var, info, mode_option,
-				   info->monspecs.modedb, info->monspecs.modedb_len,
-				   NULL, info->var.bits_per_pixel);
-		if (!rc || rc == 4) {
-			rc = -EINVAL;
-			dev_err(info->device, "mode %s not found\n", mode_option);
-			fb_destroy_modedb(info->monspecs.modedb);
-			info->monspecs.modedb = NULL;
-			goto err_find_mode;
-		}
-	}
-
-	fb_destroy_modedb(info->monspecs.modedb);
-	info->monspecs.modedb = NULL;
-
-	/* maximize virtual vertical size for fast scrolling */
-	info->var.yres_virtual = info->fix.smem_len * 8 /
-			(info->var.bits_per_pixel * info->var.xres_virtual);
-	if (info->var.yres_virtual < info->var.yres) {
-		dev_err(info->device, "virtual vertical size smaller than real\n");
-		rc = -EINVAL;
-		goto err_find_mode;
-	}
-
-	rc = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (rc < 0) {
-		dev_err(info->device, "cannot allocate colormap\n");
-		goto err_alloc_cmap;
-	}
-
-	rc = register_framebuffer(info);
-	if (rc < 0) {
-		dev_err(info->device, "cannot register framebuffer\n");
-		goto err_reg_fb;
-	}
-
-	fb_info(info, "%s on %s, %d MB RAM, %d MHz MCLK\n",
-		info->fix.id, pci_name(dev),
-		info->fix.smem_len >> 20, (par->mclk_freq + 500) / 1000);
-
-	if (par->chip == CHIP_UNKNOWN)
-		fb_info(info, "unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n",
-			vga_rcrt(par->state.vgabase, 0x2d),
-			vga_rcrt(par->state.vgabase, 0x2e),
-			vga_rcrt(par->state.vgabase, 0x2f),
-			vga_rcrt(par->state.vgabase, 0x30));
-
-	/* Record a reference to the driver data */
-	pci_set_drvdata(dev, info);
-
-#ifdef CONFIG_MTRR
-	if (mtrr) {
-		par->mtrr_reg = -1;
-		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-	}
-#endif
-
-	return 0;
-
-	/* Error handling */
-err_reg_fb:
-	fb_dealloc_cmap(&info->cmap);
-err_alloc_cmap:
-err_find_mode:
-#ifdef CONFIG_FB_S3_DDC
-	if (par->ddc_registered)
-		i2c_del_adapter(&par->ddc_adapter);
-	if (par->mmio)
-		iounmap(par->mmio);
-#endif
-	pci_iounmap(dev, info->screen_base);
-err_iomap:
-	pci_release_regions(dev);
-err_request_regions:
-/*	pci_disable_device(dev); */
-err_enable_device:
-	framebuffer_release(info);
-	return rc;
-}
-
-
-/* PCI remove */
-
-static void s3_pci_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct s3fb_info __maybe_unused *par = info->par;
-
-	if (info) {
-
-#ifdef CONFIG_MTRR
-		if (par->mtrr_reg >= 0) {
-			mtrr_del(par->mtrr_reg, 0, 0);
-			par->mtrr_reg = -1;
-		}
-#endif
-
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-
-#ifdef CONFIG_FB_S3_DDC
-		if (par->ddc_registered)
-			i2c_del_adapter(&par->ddc_adapter);
-		if (par->mmio)
-			iounmap(par->mmio);
-#endif
-
-		pci_iounmap(dev, info->screen_base);
-		pci_release_regions(dev);
-/*		pci_disable_device(dev); */
-
-		framebuffer_release(info);
-	}
-}
-
-/* PCI suspend */
-
-static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct s3fb_info *par = info->par;
-
-	dev_info(info->device, "suspend\n");
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
-		mutex_unlock(&(par->open_lock));
-		console_unlock();
-		return 0;
-	}
-
-	fb_set_suspend(info, 1);
-
-	pci_save_state(dev);
-	pci_disable_device(dev);
-	pci_set_power_state(dev, pci_choose_state(dev, state));
-
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-
-	return 0;
-}
-
-
-/* PCI resume */
-
-static int s3_pci_resume(struct pci_dev* dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct s3fb_info *par = info->par;
-	int err;
-
-	dev_info(info->device, "resume\n");
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	if (par->ref_count == 0) {
-		mutex_unlock(&(par->open_lock));
-		console_unlock();
-		return 0;
-	}
-
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
-	err = pci_enable_device(dev);
-	if (err) {
-		mutex_unlock(&(par->open_lock));
-		console_unlock();
-		dev_err(info->device, "error %d enabling device for resume\n", err);
-		return err;
-	}
-	pci_set_master(dev);
-
-	s3fb_set_par(info);
-	fb_set_suspend(info, 0);
-
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-
-	return 0;
-}
-
-
-/* List of boards that we are trying to support */
-
-static struct pci_device_id s3_devices[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8810), .driver_data = CHIP_XXX_TRIO},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8811), .driver_data = CHIP_XXX_TRIO},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8812), .driver_data = CHIP_M65_AURORA64VP},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8814), .driver_data = CHIP_767_TRIO64UVP},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8901), .driver_data = CHIP_XXX_TRIO64V2_DXGX},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8902), .driver_data = CHIP_551_PLATO_PX},
-
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D},
-	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8C01), .driver_data = CHIP_260_VIRGE_MX},
-
-	{0, 0, 0, 0, 0, 0, 0}
-};
-
-
-MODULE_DEVICE_TABLE(pci, s3_devices);
-
-static struct pci_driver s3fb_pci_driver = {
-	.name		= "s3fb",
-	.id_table	= s3_devices,
-	.probe		= s3_pci_probe,
-	.remove		= s3_pci_remove,
-	.suspend	= s3_pci_suspend,
-	.resume		= s3_pci_resume,
-};
-
-/* Parse user specified options */
-
-#ifndef MODULE
-static int  __init s3fb_setup(char *options)
-{
-	char *opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((opt = strsep(&options, ",")) != NULL) {
-
-		if (!*opt)
-			continue;
-#ifdef CONFIG_MTRR
-		else if (!strncmp(opt, "mtrr:", 5))
-			mtrr = simple_strtoul(opt + 5, NULL, 0);
-#endif
-		else if (!strncmp(opt, "fasttext:", 9))
-			fasttext = simple_strtoul(opt + 9, NULL, 0);
-		else
-			mode_option = opt;
-	}
-
-	return 0;
-}
-#endif
-
-/* Cleanup */
-
-static void __exit s3fb_cleanup(void)
-{
-	pr_debug("s3fb: cleaning up\n");
-	pci_unregister_driver(&s3fb_pci_driver);
-}
-
-/* Driver Initialisation */
-
-static int __init s3fb_init(void)
-{
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("s3fb", &option))
-		return -ENODEV;
-	s3fb_setup(option);
-#endif
-
-	pr_debug("s3fb: initializing\n");
-	return pci_register_driver(&s3fb_pci_driver);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* Modularization */
-
-module_init(s3fb_init);
-module_exit(s3fb_cleanup);
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
deleted file mode 100644
index 580c444ec301..000000000000
--- a/drivers/video/sa1100fb.c
+++ /dev/null
@@ -1,1340 +0,0 @@
-/*
- *  linux/drivers/video/sa1100fb.c
- *
- *  Copyright (C) 1999 Eric A. Thomas
- *   Based on acornfb.c Copyright (C) Russell King.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- *	        StrongARM 1100 LCD Controller Frame Buffer Driver
- *
- * Please direct your questions and comments on this driver to the following
- * email address:
- *
- *	linux-arm-kernel@lists.arm.linux.org.uk
- *
- * Clean patches should be sent to the ARM Linux Patch System.  Please see the
- * following web page for more information:
- *
- *	http://www.arm.linux.org.uk/developer/patches/info.shtml
- *
- * Thank you.
- *
- * Known problems:
- *	- With the Neponset plugged into an Assabet, LCD powerdown
- *	  doesn't work (LCD stays powered up).  Therefore we shouldn't
- *	  blank the screen.
- *	- We don't limit the CPU clock rate nor the mode selection
- *	  according to the available SDRAM bandwidth.
- *
- * Other notes:
- *	- Linear grayscale palettes and the kernel.
- *	  Such code does not belong in the kernel.  The kernel frame buffer
- *	  drivers do not expect a linear colourmap, but a colourmap based on
- *	  the VT100 standard mapping.
- *
- *	  If your _userspace_ requires a linear colourmap, then the setup of
- *	  such a colourmap belongs _in userspace_, not in the kernel.  Code
- *	  to set the colourmap correctly from user space has been sent to
- *	  David Neuer.  It's around 8 lines of C code, plus another 4 to
- *	  detect if we are using grayscale.
- *
- *	- The following must never be specified in a panel definition:
- *	     LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
- *
- *	- The following should be specified:
- *	     either LCCR0_Color or LCCR0_Mono
- *	     either LCCR0_Sngl or LCCR0_Dual
- *	     either LCCR0_Act or LCCR0_Pas
- *	     either LCCR3_OutEnH or LCCD3_OutEnL
- *	     either LCCR3_PixRsEdg or LCCR3_PixFlEdg
- *	     either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
- *
- * Code Status:
- * 1999/04/01:
- *	- Driver appears to be working for Brutus 320x200x8bpp mode.  Other
- *	  resolutions are working, but only the 8bpp mode is supported.
- *	  Changes need to be made to the palette encode and decode routines
- *	  to support 4 and 16 bpp modes.  
- *	  Driver is not designed to be a module.  The FrameBuffer is statically
- *	  allocated since dynamic allocation of a 300k buffer cannot be 
- *	  guaranteed. 
- *
- * 1999/06/17:
- *	- FrameBuffer memory is now allocated at run-time when the
- *	  driver is initialized.    
- *
- * 2000/04/10: Nicolas Pitre <nico@fluxnic.net>
- *	- Big cleanup for dynamic selection of machine type at run time.
- *
- * 2000/07/19: Jamey Hicks <jamey@crl.dec.com>
- *	- Support for Bitsy aka Compaq iPAQ H3600 added.
- *
- * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com>
- *	       Jeff Sutherland <jsutherland@accelent.com>
- *	- Resolved an issue caused by a change made to the Assabet's PLD 
- *	  earlier this year which broke the framebuffer driver for newer 
- *	  Phase 4 Assabets.  Some other parameters were changed to optimize
- *	  for the Sharp display.
- *
- * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp>
- *	- XP860 support added
- *
- * 2000/08/19: Mark Huang <mhuang@livetoy.com>
- *	- Allows standard options to be passed on the kernel command line
- *	  for most common passive displays.
- *
- * 2000/08/29:
- *	- s/save_flags_cli/local_irq_save/
- *	- remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller
- *
- * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
- *	- Updated LART stuff. Fixed some minor bugs.
- *
- * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw>
- *	- Pangolin support added
- *
- * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de>
- *	- Huw Webpanel support added
- *
- * 2000/11/23: Eric Peng <ericpeng@coventive.com>
- *	- Freebird add
- *
- * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> 
- *	       Cliff Brake <cbrake@accelent.com>
- *	- Added PM callback
- *
- * 2001/05/26: <rmk@arm.linux.org.uk>
- *	- Fix 16bpp so that (a) we use the right colours rather than some
- *	  totally random colour depending on what was in page 0, and (b)
- *	  we don't de-reference a NULL pointer.
- *	- remove duplicated implementation of consistent_alloc()
- *	- convert dma address types to dma_addr_t
- *	- remove unused 'montype' stuff
- *	- remove redundant zero inits of init_var after the initial
- *	  memset.
- *	- remove allow_modeset (acornfb idea does not belong here)
- *
- * 2001/05/28: <rmk@arm.linux.org.uk>
- *	- massive cleanup - move machine dependent data into structures
- *	- I've left various #warnings in - if you see one, and know
- *	  the hardware concerned, please get in contact with me.
- *
- * 2001/05/31: <rmk@arm.linux.org.uk>
- *	- Fix LCCR1 HSW value, fix all machine type specifications to
- *	  keep values in line.  (Please check your machine type specs)
- *
- * 2001/06/10: <rmk@arm.linux.org.uk>
- *	- Fiddle with the LCD controller from task context only; mainly
- *	  so that we can run with interrupts on, and sleep.
- *	- Convert #warnings into #errors.  No pain, no gain. ;)
- *
- * 2001/06/14: <rmk@arm.linux.org.uk>
- *	- Make the palette BPS value for 12bpp come out correctly.
- *	- Take notice of "greyscale" on any colour depth.
- *	- Make truecolor visuals use the RGB channel encoding information.
- *
- * 2001/07/02: <rmk@arm.linux.org.uk>
- *	- Fix colourmap problems.
- *
- * 2001/07/13: <abraham@2d3d.co.za>
- *	- Added support for the ICP LCD-Kit01 on LART. This LCD is
- *	  manufactured by Prime View, model no V16C6448AB
- *
- * 2001/07/23: <rmk@arm.linux.org.uk>
- *	- Hand merge version from handhelds.org CVS tree.  See patch
- *	  notes for 595/1 for more information.
- *	- Drop 12bpp (it's 16bpp with different colour register mappings).
- *	- This hardware can not do direct colour.  Therefore we don't
- *	  support it.
- *
- * 2001/07/27: <rmk@arm.linux.org.uk>
- *	- Halve YRES on dual scan LCDs.
- *
- * 2001/08/22: <rmk@arm.linux.org.uk>
- *	- Add b/w iPAQ pixclock value.
- *
- * 2001/10/12: <rmk@arm.linux.org.uk>
- *	- Add patch 681/1 and clean up stork definitions.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/cpufreq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <video/sa1100fb.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <mach/shannon.h>
-
-/*
- * Complain if VAR is out of range.
- */
-#define DEBUG_VAR 1
-
-#include "sa1100fb.h"
-
-static const struct sa1100fb_rgb rgb_4 = {
-	.red	= { .offset = 0,  .length = 4, },
-	.green	= { .offset = 0,  .length = 4, },
-	.blue	= { .offset = 0,  .length = 4, },
-	.transp	= { .offset = 0,  .length = 0, },
-};
-
-static const struct sa1100fb_rgb rgb_8 = {
-	.red	= { .offset = 0,  .length = 8, },
-	.green	= { .offset = 0,  .length = 8, },
-	.blue	= { .offset = 0,  .length = 8, },
-	.transp	= { .offset = 0,  .length = 0, },
-};
-
-static const struct sa1100fb_rgb def_rgb_16 = {
-	.red	= { .offset = 11, .length = 5, },
-	.green	= { .offset = 5,  .length = 6, },
-	.blue	= { .offset = 0,  .length = 5, },
-	.transp	= { .offset = 0,  .length = 0, },
-};
-
-
-
-static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
-static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
-
-static inline void sa1100fb_schedule_work(struct sa1100fb_info *fbi, u_int state)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	/*
-	 * We need to handle two requests being made at the same time.
-	 * There are two important cases:
-	 *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
-	 *     We must perform the unblanking, which will do our REENABLE for us.
-	 *  2. When we are blanking, but immediately unblank before we have
-	 *     blanked.  We do the "REENABLE" thing here as well, just to be sure.
-	 */
-	if (fbi->task_state == C_ENABLE && state == C_REENABLE)
-		state = (u_int) -1;
-	if (fbi->task_state == C_DISABLE && state == C_ENABLE)
-		state = C_REENABLE;
-
-	if (state != (u_int)-1) {
-		fbi->task_state = state;
-		schedule_work(&fbi->task);
-	}
-	local_irq_restore(flags);
-}
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-/*
- * Convert bits-per-pixel to a hardware palette PBS value.
- */
-static inline u_int palette_pbs(struct fb_var_screeninfo *var)
-{
-	int ret = 0;
-	switch (var->bits_per_pixel) {
-	case 4:  ret = 0 << 12;	break;
-	case 8:  ret = 1 << 12; break;
-	case 16: ret = 2 << 12; break;
-	}
-	return ret;
-}
-
-static int
-sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
-		       u_int trans, struct fb_info *info)
-{
-	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-	u_int val, ret = 1;
-
-	if (regno < fbi->palette_size) {
-		val = ((red >> 4) & 0xf00);
-		val |= ((green >> 8) & 0x0f0);
-		val |= ((blue >> 12) & 0x00f);
-
-		if (regno == 0)
-			val |= palette_pbs(&fbi->fb.var);
-
-		fbi->palette_cpu[regno] = val;
-		ret = 0;
-	}
-	return ret;
-}
-
-static int
-sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-		   u_int trans, struct fb_info *info)
-{
-	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-	unsigned int val;
-	int ret = 1;
-
-	/*
-	 * If inverse mode was selected, invert all the colours
-	 * rather than the register number.  The register number
-	 * is what you poke into the framebuffer to produce the
-	 * colour you requested.
-	 */
-	if (fbi->inf->cmap_inverse) {
-		red   = 0xffff - red;
-		green = 0xffff - green;
-		blue  = 0xffff - blue;
-	}
-
-	/*
-	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no mater what visual we are using.
-	 */
-	if (fbi->fb.var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green +
-					7471 * blue) >> 16;
-
-	switch (fbi->fb.fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/*
-		 * 12 or 16-bit True Colour.  We encode the RGB value
-		 * according to the RGB bitfield information.
-		 */
-		if (regno < 16) {
-			u32 *pal = fbi->fb.pseudo_palette;
-
-			val  = chan_to_field(red, &fbi->fb.var.red);
-			val |= chan_to_field(green, &fbi->fb.var.green);
-			val |= chan_to_field(blue, &fbi->fb.var.blue);
-
-			pal[regno] = val;
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_STATIC_PSEUDOCOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		ret = sa1100fb_setpalettereg(regno, red, green, blue, trans, info);
-		break;
-	}
-
-	return ret;
-}
-
-#ifdef CONFIG_CPU_FREQ
-/*
- *  sa1100fb_display_dma_period()
- *    Calculate the minimum period (in picoseconds) between two DMA
- *    requests for the LCD controller.  If we hit this, it means we're
- *    doing nothing but LCD DMA.
- */
-static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
-{
-	/*
-	 * Period = pixclock * bits_per_byte * bytes_per_transfer
-	 *		/ memory_bits_per_pixel;
-	 */
-	return var->pixclock * 8 * 16 / var->bits_per_pixel;
-}
-#endif
-
-/*
- *  sa1100fb_check_var():
- *    Round up in the following order: bits_per_pixel, xres,
- *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
- *    bitfields, horizontal timing, vertical timing.
- */
-static int
-sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-	int rgbidx;
-
-	if (var->xres < MIN_XRES)
-		var->xres = MIN_XRES;
-	if (var->yres < MIN_YRES)
-		var->yres = MIN_YRES;
-	if (var->xres > fbi->inf->xres)
-		var->xres = fbi->inf->xres;
-	if (var->yres > fbi->inf->yres)
-		var->yres = fbi->inf->yres;
-	var->xres_virtual = max(var->xres_virtual, var->xres);
-	var->yres_virtual = max(var->yres_virtual, var->yres);
-
-	dev_dbg(fbi->dev, "var->bits_per_pixel=%d\n", var->bits_per_pixel);
-	switch (var->bits_per_pixel) {
-	case 4:
-		rgbidx = RGB_4;
-		break;
-	case 8:
-		rgbidx = RGB_8;
-		break;
-	case 16:
-		rgbidx = RGB_16;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * Copy the RGB parameters for this display
-	 * from the machine specific parameters.
-	 */
-	var->red    = fbi->rgb[rgbidx]->red;
-	var->green  = fbi->rgb[rgbidx]->green;
-	var->blue   = fbi->rgb[rgbidx]->blue;
-	var->transp = fbi->rgb[rgbidx]->transp;
-
-	dev_dbg(fbi->dev, "RGBT length = %d:%d:%d:%d\n",
-		var->red.length, var->green.length, var->blue.length,
-		var->transp.length);
-
-	dev_dbg(fbi->dev, "RGBT offset = %d:%d:%d:%d\n",
-		var->red.offset, var->green.offset, var->blue.offset,
-		var->transp.offset);
-
-#ifdef CONFIG_CPU_FREQ
-	dev_dbg(fbi->dev, "dma period = %d ps, clock = %d kHz\n",
-		sa1100fb_display_dma_period(var),
-		cpufreq_get(smp_processor_id()));
-#endif
-
-	return 0;
-}
-
-static void sa1100fb_set_visual(struct sa1100fb_info *fbi, u32 visual)
-{
-	if (fbi->inf->set_visual)
-		fbi->inf->set_visual(visual);
-}
-
-/*
- * sa1100fb_set_par():
- *	Set the user defined part of the display for the specified console
- */
-static int sa1100fb_set_par(struct fb_info *info)
-{
-	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-	struct fb_var_screeninfo *var = &info->var;
-	unsigned long palette_mem_size;
-
-	dev_dbg(fbi->dev, "set_par\n");
-
-	if (var->bits_per_pixel == 16)
-		fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-	else if (!fbi->inf->cmap_static)
-		fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	else {
-		/*
-		 * Some people have weird ideas about wanting static
-		 * pseudocolor maps.  I suspect their user space
-		 * applications are broken.
-		 */
-		fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-	}
-
-	fbi->fb.fix.line_length = var->xres_virtual *
-				  var->bits_per_pixel / 8;
-	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
-
-	palette_mem_size = fbi->palette_size * sizeof(u16);
-
-	dev_dbg(fbi->dev, "palette_mem_size = 0x%08lx\n", palette_mem_size);
-
-	fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
-	fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
-
-	/*
-	 * Set (any) board control register to handle new color depth
-	 */
-	sa1100fb_set_visual(fbi, fbi->fb.fix.visual);
-	sa1100fb_activate_var(var, fbi);
-
-	return 0;
-}
-
-#if 0
-static int
-sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-		  struct fb_info *info)
-{
-	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-
-	/*
-	 * Make sure the user isn't doing something stupid.
-	 */
-	if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->inf->cmap_static))
-		return -EINVAL;
-
-	return gen_set_cmap(cmap, kspc, con, info);
-}
-#endif
-
-/*
- * Formal definition of the VESA spec:
- *  On
- *  	This refers to the state of the display when it is in full operation
- *  Stand-By
- *  	This defines an optional operating state of minimal power reduction with
- *  	the shortest recovery time
- *  Suspend
- *  	This refers to a level of power management in which substantial power
- *  	reduction is achieved by the display.  The display can have a longer 
- *  	recovery time from this state than from the Stand-by state
- *  Off
- *  	This indicates that the display is consuming the lowest level of power
- *  	and is non-operational. Recovery from this state may optionally require
- *  	the user to manually power on the monitor
- *
- *  Now, the fbdev driver adds an additional state, (blank), where they
- *  turn off the video (maybe by colormap tricks), but don't mess with the
- *  video itself: think of it semantically between on and Stand-By.
- *
- *  So here's what we should do in our fbdev blank routine:
- *
- *  	VESA_NO_BLANKING (mode 0)	Video on,  front/back light on
- *  	VESA_VSYNC_SUSPEND (mode 1)  	Video on,  front/back light off
- *  	VESA_HSYNC_SUSPEND (mode 2)  	Video on,  front/back light off
- *  	VESA_POWERDOWN (mode 3)		Video off, front/back light off
- *
- *  This will match the matrox implementation.
- */
-/*
- * sa1100fb_blank():
- *	Blank the display by setting all palette values to zero.  Note, the 
- * 	12 and 16 bpp modes don't really use the palette, so this will not
- *      blank the display in all modes.  
- */
-static int sa1100fb_blank(int blank, struct fb_info *info)
-{
-	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-	int i;
-
-	dev_dbg(fbi->dev, "sa1100fb_blank: blank=%d\n", blank);
-
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
-		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-			for (i = 0; i < fbi->palette_size; i++)
-				sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
-		sa1100fb_schedule_work(fbi, C_DISABLE);
-		break;
-
-	case FB_BLANK_UNBLANK:
-		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
-		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-			fb_set_cmap(&fbi->fb.cmap, info);
-		sa1100fb_schedule_work(fbi, C_ENABLE);
-	}
-	return 0;
-}
-
-static int sa1100fb_mmap(struct fb_info *info,
-			 struct vm_area_struct *vma)
-{
-	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
-	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
-
-	if (off < info->fix.smem_len) {
-		vma->vm_pgoff += 1; /* skip over the palette */
-		return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu,
-					     fbi->map_dma, fbi->map_size);
-	}
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	return vm_iomap_memory(vma, info->fix.mmio_start, info->fix.mmio_len);
-}
-
-static struct fb_ops sa1100fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= sa1100fb_check_var,
-	.fb_set_par	= sa1100fb_set_par,
-//	.fb_set_cmap	= sa1100fb_set_cmap,
-	.fb_setcolreg	= sa1100fb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_blank	= sa1100fb_blank,
-	.fb_mmap	= sa1100fb_mmap,
-};
-
-/*
- * Calculate the PCD value from the clock rate (in picoseconds).
- * We take account of the PPCR clock setting.
- */
-static inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock)
-{
-	unsigned int pcd = cpuclock / 100;
-
-	pcd *= pixclock;
-	pcd /= 10000000;
-
-	return pcd + 1;	/* make up for integer math truncations */
-}
-
-/*
- * sa1100fb_activate_var():
- *	Configures LCD Controller based on entries in var parameter.  Settings are      
- *	only written to the controller if changes were made.  
- */
-static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
-{
-	struct sa1100fb_lcd_reg new_regs;
-	u_int half_screen_size, yres, pcd;
-	u_long flags;
-
-	dev_dbg(fbi->dev, "Configuring SA1100 LCD\n");
-
-	dev_dbg(fbi->dev, "var: xres=%d hslen=%d lm=%d rm=%d\n",
-		var->xres, var->hsync_len,
-		var->left_margin, var->right_margin);
-	dev_dbg(fbi->dev, "var: yres=%d vslen=%d um=%d bm=%d\n",
-		var->yres, var->vsync_len,
-		var->upper_margin, var->lower_margin);
-
-#if DEBUG_VAR
-	if (var->xres < 16        || var->xres > 1024)
-		dev_err(fbi->dev, "%s: invalid xres %d\n",
-			fbi->fb.fix.id, var->xres);
-	if (var->hsync_len < 1    || var->hsync_len > 64)
-		dev_err(fbi->dev, "%s: invalid hsync_len %d\n",
-			fbi->fb.fix.id, var->hsync_len);
-	if (var->left_margin < 1  || var->left_margin > 255)
-		dev_err(fbi->dev, "%s: invalid left_margin %d\n",
-			fbi->fb.fix.id, var->left_margin);
-	if (var->right_margin < 1 || var->right_margin > 255)
-		dev_err(fbi->dev, "%s: invalid right_margin %d\n",
-			fbi->fb.fix.id, var->right_margin);
-	if (var->yres < 1         || var->yres > 1024)
-		dev_err(fbi->dev, "%s: invalid yres %d\n",
-			fbi->fb.fix.id, var->yres);
-	if (var->vsync_len < 1    || var->vsync_len > 64)
-		dev_err(fbi->dev, "%s: invalid vsync_len %d\n",
-			fbi->fb.fix.id, var->vsync_len);
-	if (var->upper_margin < 0 || var->upper_margin > 255)
-		dev_err(fbi->dev, "%s: invalid upper_margin %d\n",
-			fbi->fb.fix.id, var->upper_margin);
-	if (var->lower_margin < 0 || var->lower_margin > 255)
-		dev_err(fbi->dev, "%s: invalid lower_margin %d\n",
-			fbi->fb.fix.id, var->lower_margin);
-#endif
-
-	new_regs.lccr0 = fbi->inf->lccr0 |
-		LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
-		LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
-
-	new_regs.lccr1 =
-		LCCR1_DisWdth(var->xres) +
-		LCCR1_HorSnchWdth(var->hsync_len) +
-		LCCR1_BegLnDel(var->left_margin) +
-		LCCR1_EndLnDel(var->right_margin);
-
-	/*
-	 * If we have a dual scan LCD, then we need to halve
-	 * the YRES parameter.
-	 */
-	yres = var->yres;
-	if (fbi->inf->lccr0 & LCCR0_Dual)
-		yres /= 2;
-
-	new_regs.lccr2 =
-		LCCR2_DisHght(yres) +
-		LCCR2_VrtSnchWdth(var->vsync_len) +
-		LCCR2_BegFrmDel(var->upper_margin) +
-		LCCR2_EndFrmDel(var->lower_margin);
-
-	pcd = get_pcd(var->pixclock, cpufreq_get(0));
-	new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->inf->lccr3 |
-		(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
-		(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
-
-	dev_dbg(fbi->dev, "nlccr0 = 0x%08lx\n", new_regs.lccr0);
-	dev_dbg(fbi->dev, "nlccr1 = 0x%08lx\n", new_regs.lccr1);
-	dev_dbg(fbi->dev, "nlccr2 = 0x%08lx\n", new_regs.lccr2);
-	dev_dbg(fbi->dev, "nlccr3 = 0x%08lx\n", new_regs.lccr3);
-
-	half_screen_size = var->bits_per_pixel;
-	half_screen_size = half_screen_size * var->xres * var->yres / 16;
-
-	/* Update shadow copy atomically */
-	local_irq_save(flags);
-	fbi->dbar1 = fbi->palette_dma;
-	fbi->dbar2 = fbi->screen_dma + half_screen_size;
-
-	fbi->reg_lccr0 = new_regs.lccr0;
-	fbi->reg_lccr1 = new_regs.lccr1;
-	fbi->reg_lccr2 = new_regs.lccr2;
-	fbi->reg_lccr3 = new_regs.lccr3;
-	local_irq_restore(flags);
-
-	/*
-	 * Only update the registers if the controller is enabled
-	 * and something has changed.
-	 */
-	if (readl_relaxed(fbi->base + LCCR0) != fbi->reg_lccr0 ||
-	    readl_relaxed(fbi->base + LCCR1) != fbi->reg_lccr1 ||
-	    readl_relaxed(fbi->base + LCCR2) != fbi->reg_lccr2 ||
-	    readl_relaxed(fbi->base + LCCR3) != fbi->reg_lccr3 ||
-	    readl_relaxed(fbi->base + DBAR1) != fbi->dbar1 ||
-	    readl_relaxed(fbi->base + DBAR2) != fbi->dbar2)
-		sa1100fb_schedule_work(fbi, C_REENABLE);
-
-	return 0;
-}
-
-/*
- * NOTE!  The following functions are purely helpers for set_ctrlr_state.
- * Do not call them directly; set_ctrlr_state does the correct serialisation
- * to ensure that things happen in the right way 100% of time time.
- *	-- rmk
- */
-static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on)
-{
-	dev_dbg(fbi->dev, "backlight o%s\n", on ? "n" : "ff");
-
-	if (fbi->inf->backlight_power)
-		fbi->inf->backlight_power(on);
-}
-
-static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on)
-{
-	dev_dbg(fbi->dev, "LCD power o%s\n", on ? "n" : "ff");
-
-	if (fbi->inf->lcd_power)
-		fbi->inf->lcd_power(on);
-}
-
-static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
-{
-	u_int mask = 0;
-
-	/*
-	 * Enable GPIO<9:2> for LCD use if:
-	 *  1. Active display, or
-	 *  2. Color Dual Passive display
-	 *
-	 * see table 11.8 on page 11-27 in the SA1100 manual
-	 *   -- Erik.
-	 *
-	 * SA1110 spec update nr. 25 says we can and should
-	 * clear LDD15 to 12 for 4 or 8bpp modes with active
-	 * panels.  
-	 */
-	if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
-	    (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
-		mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
-
-		if (fbi->fb.var.bits_per_pixel > 8 ||
-		    (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual)
-			mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12;
-
-	}
-
-	if (mask) {
-		unsigned long flags;
-
-		/*
-		 * SA-1100 requires the GPIO direction register set
-		 * appropriately for the alternate function.  Hence
-		 * we set it here via bitmask rather than excessive
-		 * fiddling via the GPIO subsystem - and even then
-		 * we'll still have to deal with GAFR.
-		 */
-		local_irq_save(flags);
-		GPDR |= mask;
-		GAFR |= mask;
-		local_irq_restore(flags);
-	}
-}
-
-static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
-{
-	dev_dbg(fbi->dev, "Enabling LCD controller\n");
-
-	/*
-	 * Make sure the mode bits are present in the first palette entry
-	 */
-	fbi->palette_cpu[0] &= 0xcfff;
-	fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
-
-	/* Sequence from 11.7.10 */
-	writel_relaxed(fbi->reg_lccr3, fbi->base + LCCR3);
-	writel_relaxed(fbi->reg_lccr2, fbi->base + LCCR2);
-	writel_relaxed(fbi->reg_lccr1, fbi->base + LCCR1);
-	writel_relaxed(fbi->reg_lccr0 & ~LCCR0_LEN, fbi->base + LCCR0);
-	writel_relaxed(fbi->dbar1, fbi->base + DBAR1);
-	writel_relaxed(fbi->dbar2, fbi->base + DBAR2);
-	writel_relaxed(fbi->reg_lccr0 | LCCR0_LEN, fbi->base + LCCR0);
-
-	if (machine_is_shannon())
-		gpio_set_value(SHANNON_GPIO_DISP_EN, 1);
-
-	dev_dbg(fbi->dev, "DBAR1: 0x%08x\n", readl_relaxed(fbi->base + DBAR1));
-	dev_dbg(fbi->dev, "DBAR2: 0x%08x\n", readl_relaxed(fbi->base + DBAR2));
-	dev_dbg(fbi->dev, "LCCR0: 0x%08x\n", readl_relaxed(fbi->base + LCCR0));
-	dev_dbg(fbi->dev, "LCCR1: 0x%08x\n", readl_relaxed(fbi->base + LCCR1));
-	dev_dbg(fbi->dev, "LCCR2: 0x%08x\n", readl_relaxed(fbi->base + LCCR2));
-	dev_dbg(fbi->dev, "LCCR3: 0x%08x\n", readl_relaxed(fbi->base + LCCR3));
-}
-
-static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	u32 lccr0;
-
-	dev_dbg(fbi->dev, "Disabling LCD controller\n");
-
-	if (machine_is_shannon())
-		gpio_set_value(SHANNON_GPIO_DISP_EN, 0);
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&fbi->ctrlr_wait, &wait);
-
-	/* Clear LCD Status Register */
-	writel_relaxed(~0, fbi->base + LCSR);
-
-	lccr0 = readl_relaxed(fbi->base + LCCR0);
-	lccr0 &= ~LCCR0_LDM;	/* Enable LCD Disable Done Interrupt */
-	writel_relaxed(lccr0, fbi->base + LCCR0);
-	lccr0 &= ~LCCR0_LEN;	/* Disable LCD Controller */
-	writel_relaxed(lccr0, fbi->base + LCCR0);
-
-	schedule_timeout(20 * HZ / 1000);
-	remove_wait_queue(&fbi->ctrlr_wait, &wait);
-}
-
-/*
- *  sa1100fb_handle_irq: Handle 'LCD DONE' interrupts.
- */
-static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
-{
-	struct sa1100fb_info *fbi = dev_id;
-	unsigned int lcsr = readl_relaxed(fbi->base + LCSR);
-
-	if (lcsr & LCSR_LDD) {
-		u32 lccr0 = readl_relaxed(fbi->base + LCCR0) | LCCR0_LDM;
-		writel_relaxed(lccr0, fbi->base + LCCR0);
-		wake_up(&fbi->ctrlr_wait);
-	}
-
-	writel_relaxed(lcsr, fbi->base + LCSR);
-	return IRQ_HANDLED;
-}
-
-/*
- * This function must be called from task context only, since it will
- * sleep when disabling the LCD controller, or if we get two contending
- * processes trying to alter state.
- */
-static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
-{
-	u_int old_state;
-
-	mutex_lock(&fbi->ctrlr_lock);
-
-	old_state = fbi->state;
-
-	/*
-	 * Hack around fbcon initialisation.
-	 */
-	if (old_state == C_STARTUP && state == C_REENABLE)
-		state = C_ENABLE;
-
-	switch (state) {
-	case C_DISABLE_CLKCHANGE:
-		/*
-		 * Disable controller for clock change.  If the
-		 * controller is already disabled, then do nothing.
-		 */
-		if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
-			fbi->state = state;
-			sa1100fb_disable_controller(fbi);
-		}
-		break;
-
-	case C_DISABLE_PM:
-	case C_DISABLE:
-		/*
-		 * Disable controller
-		 */
-		if (old_state != C_DISABLE) {
-			fbi->state = state;
-
-			__sa1100fb_backlight_power(fbi, 0);
-			if (old_state != C_DISABLE_CLKCHANGE)
-				sa1100fb_disable_controller(fbi);
-			__sa1100fb_lcd_power(fbi, 0);
-		}
-		break;
-
-	case C_ENABLE_CLKCHANGE:
-		/*
-		 * Enable the controller after clock change.  Only
-		 * do this if we were disabled for the clock change.
-		 */
-		if (old_state == C_DISABLE_CLKCHANGE) {
-			fbi->state = C_ENABLE;
-			sa1100fb_enable_controller(fbi);
-		}
-		break;
-
-	case C_REENABLE:
-		/*
-		 * Re-enable the controller only if it was already
-		 * enabled.  This is so we reprogram the control
-		 * registers.
-		 */
-		if (old_state == C_ENABLE) {
-			sa1100fb_disable_controller(fbi);
-			sa1100fb_setup_gpio(fbi);
-			sa1100fb_enable_controller(fbi);
-		}
-		break;
-
-	case C_ENABLE_PM:
-		/*
-		 * Re-enable the controller after PM.  This is not
-		 * perfect - think about the case where we were doing
-		 * a clock change, and we suspended half-way through.
-		 */
-		if (old_state != C_DISABLE_PM)
-			break;
-		/* fall through */
-
-	case C_ENABLE:
-		/*
-		 * Power up the LCD screen, enable controller, and
-		 * turn on the backlight.
-		 */
-		if (old_state != C_ENABLE) {
-			fbi->state = C_ENABLE;
-			sa1100fb_setup_gpio(fbi);
-			__sa1100fb_lcd_power(fbi, 1);
-			sa1100fb_enable_controller(fbi);
-			__sa1100fb_backlight_power(fbi, 1);
-		}
-		break;
-	}
-	mutex_unlock(&fbi->ctrlr_lock);
-}
-
-/*
- * Our LCD controller task (which is called when we blank or unblank)
- * via keventd.
- */
-static void sa1100fb_task(struct work_struct *w)
-{
-	struct sa1100fb_info *fbi = container_of(w, struct sa1100fb_info, task);
-	u_int state = xchg(&fbi->task_state, -1);
-
-	set_ctrlr_state(fbi, state);
-}
-
-#ifdef CONFIG_CPU_FREQ
-/*
- * Calculate the minimum DMA period over all displays that we own.
- * This, together with the SDRAM bandwidth defines the slowest CPU
- * frequency that can be selected.
- */
-static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
-{
-#if 0
-	unsigned int min_period = (unsigned int)-1;
-	int i;
-
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
-		struct display *disp = &fb_display[i];
-		unsigned int period;
-
-		/*
-		 * Do we own this display?
-		 */
-		if (disp->fb_info != &fbi->fb)
-			continue;
-
-		/*
-		 * Ok, calculate its DMA period
-		 */
-		period = sa1100fb_display_dma_period(&disp->var);
-		if (period < min_period)
-			min_period = period;
-	}
-
-	return min_period;
-#else
-	/*
-	 * FIXME: we need to verify _all_ consoles.
-	 */
-	return sa1100fb_display_dma_period(&fbi->fb.var);
-#endif
-}
-
-/*
- * CPU clock speed change handler.  We need to adjust the LCD timing
- * parameters when the CPU clock is adjusted by the power management
- * subsystem.
- */
-static int
-sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val,
-			 void *data)
-{
-	struct sa1100fb_info *fbi = TO_INF(nb, freq_transition);
-	struct cpufreq_freqs *f = data;
-	u_int pcd;
-
-	switch (val) {
-	case CPUFREQ_PRECHANGE:
-		set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
-		break;
-
-	case CPUFREQ_POSTCHANGE:
-		pcd = get_pcd(fbi->fb.var.pixclock, f->new);
-		fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
-		set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
-		break;
-	}
-	return 0;
-}
-
-static int
-sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
-		     void *data)
-{
-	struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
-	struct cpufreq_policy *policy = data;
-
-	switch (val) {
-	case CPUFREQ_ADJUST:
-	case CPUFREQ_INCOMPATIBLE:
-		dev_dbg(fbi->dev, "min dma period: %d ps, "
-			"new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
-			policy->max);
-		/* todo: fill in min/max values */
-		break;
-	case CPUFREQ_NOTIFY:
-		do {} while(0);
-		/* todo: panic if min/max values aren't fulfilled 
-		 * [can't really happen unless there's a bug in the
-		 * CPU policy verififcation process *
-		 */
-		break;
-	}
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PM
-/*
- * Power management hooks.  Note that we won't be called from IRQ context,
- * unlike the blank functions above, so we may sleep.
- */
-static int sa1100fb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct sa1100fb_info *fbi = platform_get_drvdata(dev);
-
-	set_ctrlr_state(fbi, C_DISABLE_PM);
-	return 0;
-}
-
-static int sa1100fb_resume(struct platform_device *dev)
-{
-	struct sa1100fb_info *fbi = platform_get_drvdata(dev);
-
-	set_ctrlr_state(fbi, C_ENABLE_PM);
-	return 0;
-}
-#else
-#define sa1100fb_suspend	NULL
-#define sa1100fb_resume		NULL
-#endif
-
-/*
- * sa1100fb_map_video_memory():
- *      Allocates the DRAM memory for the frame buffer.  This buffer is  
- *	remapped into a non-cached, non-buffered, memory region to  
- *      allow palette and pixel writes to occur without flushing the 
- *      cache.  Once this area is remapped, all virtual memory
- *      access to the video memory should occur at the new region.
- */
-static int sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
-{
-	/*
-	 * We reserve one page for the palette, plus the size
-	 * of the framebuffer.
-	 */
-	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
-	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
-					      &fbi->map_dma, GFP_KERNEL);
-
-	if (fbi->map_cpu) {
-		fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
-		fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
-		/*
-		 * FIXME: this is actually the wrong thing to place in
-		 * smem_start.  But fbdev suffers from the problem that
-		 * it needs an API which doesn't exist (in this case,
-		 * dma_writecombine_mmap)
-		 */
-		fbi->fb.fix.smem_start = fbi->screen_dma;
-	}
-
-	return fbi->map_cpu ? 0 : -ENOMEM;
-}
-
-/* Fake monspecs to fill in fbinfo structure */
-static struct fb_monspecs monspecs = {
-	.hfmin	= 30000,
-	.hfmax	= 70000,
-	.vfmin	= 50,
-	.vfmax	= 65,
-};
-
-
-static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev)
-{
-	struct sa1100fb_mach_info *inf = dev_get_platdata(dev);
-	struct sa1100fb_info *fbi;
-	unsigned i;
-
-	fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
-		      GFP_KERNEL);
-	if (!fbi)
-		return NULL;
-
-	memset(fbi, 0, sizeof(struct sa1100fb_info));
-	fbi->dev = dev;
-
-	strcpy(fbi->fb.fix.id, SA1100_NAME);
-
-	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
-	fbi->fb.fix.type_aux	= 0;
-	fbi->fb.fix.xpanstep	= 0;
-	fbi->fb.fix.ypanstep	= 0;
-	fbi->fb.fix.ywrapstep	= 0;
-	fbi->fb.fix.accel	= FB_ACCEL_NONE;
-
-	fbi->fb.var.nonstd	= 0;
-	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
-	fbi->fb.var.height	= -1;
-	fbi->fb.var.width	= -1;
-	fbi->fb.var.accel_flags	= 0;
-	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
-
-	fbi->fb.fbops		= &sa1100fb_ops;
-	fbi->fb.flags		= FBINFO_DEFAULT;
-	fbi->fb.monspecs	= monspecs;
-	fbi->fb.pseudo_palette	= (fbi + 1);
-
-	fbi->rgb[RGB_4]		= &rgb_4;
-	fbi->rgb[RGB_8]		= &rgb_8;
-	fbi->rgb[RGB_16]	= &def_rgb_16;
-
-	/*
-	 * People just don't seem to get this.  We don't support
-	 * anything but correct entries now, so panic if someone
-	 * does something stupid.
-	 */
-	if (inf->lccr3 & (LCCR3_VrtSnchL|LCCR3_HorSnchL|0xff) ||
-	    inf->pixclock == 0)
-		panic("sa1100fb error: invalid LCCR3 fields set or zero "
-			"pixclock.");
-
-	fbi->fb.var.xres		= inf->xres;
-	fbi->fb.var.xres_virtual	= inf->xres;
-	fbi->fb.var.yres		= inf->yres;
-	fbi->fb.var.yres_virtual	= inf->yres;
-	fbi->fb.var.bits_per_pixel	= inf->bpp;
-	fbi->fb.var.pixclock		= inf->pixclock;
-	fbi->fb.var.hsync_len		= inf->hsync_len;
-	fbi->fb.var.left_margin		= inf->left_margin;
-	fbi->fb.var.right_margin	= inf->right_margin;
-	fbi->fb.var.vsync_len		= inf->vsync_len;
-	fbi->fb.var.upper_margin	= inf->upper_margin;
-	fbi->fb.var.lower_margin	= inf->lower_margin;
-	fbi->fb.var.sync		= inf->sync;
-	fbi->fb.var.grayscale		= inf->cmap_greyscale;
-	fbi->state			= C_STARTUP;
-	fbi->task_state			= (u_char)-1;
-	fbi->fb.fix.smem_len		= inf->xres * inf->yres *
-					  inf->bpp / 8;
-	fbi->inf			= inf;
-
-	/* Copy the RGB bitfield overrides */
-	for (i = 0; i < NR_RGB; i++)
-		if (inf->rgb[i])
-			fbi->rgb[i] = inf->rgb[i];
-
-	init_waitqueue_head(&fbi->ctrlr_wait);
-	INIT_WORK(&fbi->task, sa1100fb_task);
-	mutex_init(&fbi->ctrlr_lock);
-
-	return fbi;
-}
-
-static int sa1100fb_probe(struct platform_device *pdev)
-{
-	struct sa1100fb_info *fbi;
-	struct resource *res;
-	int ret, irq;
-
-	if (!dev_get_platdata(&pdev->dev)) {
-		dev_err(&pdev->dev, "no platform LCD data\n");
-		return -EINVAL;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0 || !res)
-		return -EINVAL;
-
-	if (!request_mem_region(res->start, resource_size(res), "LCD"))
-		return -EBUSY;
-
-	fbi = sa1100fb_init_fbinfo(&pdev->dev);
-	ret = -ENOMEM;
-	if (!fbi)
-		goto failed;
-
-	fbi->base = ioremap(res->start, resource_size(res));
-	if (!fbi->base)
-		goto failed;
-
-	/* Initialize video memory */
-	ret = sa1100fb_map_video_memory(fbi);
-	if (ret)
-		goto failed;
-
-	ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
-	if (ret) {
-		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
-		goto failed;
-	}
-
-	if (machine_is_shannon()) {
-		ret = gpio_request_one(SHANNON_GPIO_DISP_EN,
-			GPIOF_OUT_INIT_LOW, "display enable");
-		if (ret)
-			goto err_free_irq;
-	}
-
-	/*
-	 * This makes sure that our colour bitfield
-	 * descriptors are correctly initialised.
-	 */
-	sa1100fb_check_var(&fbi->fb.var, &fbi->fb);
-
-	platform_set_drvdata(pdev, fbi);
-
-	ret = register_framebuffer(&fbi->fb);
-	if (ret < 0)
-		goto err_reg_fb;
-
-#ifdef CONFIG_CPU_FREQ
-	fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
-	fbi->freq_policy.notifier_call = sa1100fb_freq_policy;
-	cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
-	cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
-#endif
-
-	/* This driver cannot be unloaded at the moment */
-	return 0;
-
- err_reg_fb:
-	if (machine_is_shannon())
-		gpio_free(SHANNON_GPIO_DISP_EN);
- err_free_irq:
-	free_irq(irq, fbi);
- failed:
-	if (fbi)
-		iounmap(fbi->base);
-	kfree(fbi);
-	release_mem_region(res->start, resource_size(res));
-	return ret;
-}
-
-static struct platform_driver sa1100fb_driver = {
-	.probe		= sa1100fb_probe,
-	.suspend	= sa1100fb_suspend,
-	.resume		= sa1100fb_resume,
-	.driver		= {
-		.name	= "sa11x0-fb",
-		.owner	= THIS_MODULE,
-	},
-};
-
-int __init sa1100fb_init(void)
-{
-	if (fb_get_options("sa1100fb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&sa1100fb_driver);
-}
-
-int __init sa1100fb_setup(char *options)
-{
-#if 0
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-
-		if (!strncmp(this_opt, "bpp:", 4))
-			current_par.max_bpp =
-			    simple_strtoul(this_opt + 4, NULL, 0);
-
-		if (!strncmp(this_opt, "lccr0:", 6))
-			lcd_shadow.lccr0 =
-			    simple_strtoul(this_opt + 6, NULL, 0);
-		if (!strncmp(this_opt, "lccr1:", 6)) {
-			lcd_shadow.lccr1 =
-			    simple_strtoul(this_opt + 6, NULL, 0);
-			current_par.max_xres =
-			    (lcd_shadow.lccr1 & 0x3ff) + 16;
-		}
-		if (!strncmp(this_opt, "lccr2:", 6)) {
-			lcd_shadow.lccr2 =
-			    simple_strtoul(this_opt + 6, NULL, 0);
-			current_par.max_yres =
-			    (lcd_shadow.
-			     lccr0 & LCCR0_SDS) ? ((lcd_shadow.
-						    lccr2 & 0x3ff) +
-						   1) *
-			    2 : ((lcd_shadow.lccr2 & 0x3ff) + 1);
-		}
-		if (!strncmp(this_opt, "lccr3:", 6))
-			lcd_shadow.lccr3 =
-			    simple_strtoul(this_opt + 6, NULL, 0);
-	}
-#endif
-	return 0;
-}
-
-module_init(sa1100fb_init);
-MODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
deleted file mode 100644
index fc5d4292fad6..000000000000
--- a/drivers/video/sa1100fb.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * linux/drivers/video/sa1100fb.h
- *    -- StrongARM 1100 LCD Controller Frame Buffer Device
- *
- *  Copyright (C) 1999 Eric A. Thomas
- *   Based on acornfb.c Copyright (C) Russell King.
- *  
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#define LCCR0           0x0000          /* LCD Control Reg. 0 */
-#define LCSR            0x0004          /* LCD Status Reg. */
-#define DBAR1           0x0010          /* LCD DMA Base Address Reg. channel 1 */
-#define DCAR1           0x0014          /* LCD DMA Current Address Reg. channel 1 */
-#define DBAR2           0x0018          /* LCD DMA Base Address Reg.  channel 2 */
-#define DCAR2           0x001C          /* LCD DMA Current Address Reg. channel 2 */
-#define LCCR1           0x0020          /* LCD Control Reg. 1 */
-#define LCCR2           0x0024          /* LCD Control Reg. 2 */
-#define LCCR3           0x0028          /* LCD Control Reg. 3 */
-
-/* Shadows for LCD controller registers */
-struct sa1100fb_lcd_reg {
-	unsigned long lccr0;
-	unsigned long lccr1;
-	unsigned long lccr2;
-	unsigned long lccr3;
-};
-
-struct sa1100fb_info {
-	struct fb_info		fb;
-	struct device		*dev;
-	const struct sa1100fb_rgb *rgb[NR_RGB];
-	void __iomem		*base;
-
-	/*
-	 * These are the addresses we mapped
-	 * the framebuffer memory region to.
-	 */
-	dma_addr_t		map_dma;
-	u_char *		map_cpu;
-	u_int			map_size;
-
-	u_char *		screen_cpu;
-	dma_addr_t		screen_dma;
-	u16 *			palette_cpu;
-	dma_addr_t		palette_dma;
-	u_int			palette_size;
-
-	dma_addr_t		dbar1;
-	dma_addr_t		dbar2;
-
-	u_int			reg_lccr0;
-	u_int			reg_lccr1;
-	u_int			reg_lccr2;
-	u_int			reg_lccr3;
-
-	volatile u_char		state;
-	volatile u_char		task_state;
-	struct mutex		ctrlr_lock;
-	wait_queue_head_t	ctrlr_wait;
-	struct work_struct	task;
-
-#ifdef CONFIG_CPU_FREQ
-	struct notifier_block	freq_transition;
-	struct notifier_block	freq_policy;
-#endif
-
-	const struct sa1100fb_mach_info *inf;
-};
-
-#define TO_INF(ptr,member)	container_of(ptr,struct sa1100fb_info,member)
-
-#define SA1100_PALETTE_MODE_VAL(bpp)    (((bpp) & 0x018) << 9)
-
-/*
- * These are the actions for set_ctrlr_state
- */
-#define C_DISABLE		(0)
-#define C_ENABLE		(1)
-#define C_DISABLE_CLKCHANGE	(2)
-#define C_ENABLE_CLKCHANGE	(3)
-#define C_REENABLE		(4)
-#define C_DISABLE_PM		(5)
-#define C_ENABLE_PM		(6)
-#define C_STARTUP		(7)
-
-#define SA1100_NAME	"SA1100"
-
-/*
- * Minimum X and Y resolutions
- */
-#define MIN_XRES	64
-#define MIN_YRES	64
-
diff --git a/drivers/video/savage/Makefile b/drivers/video/savage/Makefile
deleted file mode 100644
index e09770fff8ea..000000000000
--- a/drivers/video/savage/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the S3 Savage framebuffer driver
-#
-
-obj-$(CONFIG_FB_SAVAGE)			+= savagefb.o
-
-savagefb-y				+= savagefb_driver.o
-savagefb-$(CONFIG_FB_SAVAGE_I2C)	+= savagefb-i2c.o
-savagefb-$(CONFIG_FB_SAVAGE_ACCEL)	+= savagefb_accel.o
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
deleted file mode 100644
index 80fa87e2ae2f..000000000000
--- a/drivers/video/savage/savagefb-i2c.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * linux/drivers/video/savage/savagefb-i2c.c - S3 Savage DDC2
- *
- * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
- *
- * Based partly on rivafb-i2c.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <linux/pci.h>
-#include <linux/fb.h>
-
-#include <asm/io.h>
-#include "savagefb.h"
-
-#define SAVAGE_DDC 	0x50
-
-#define VGA_CR_IX	0x3d4
-#define VGA_CR_DATA	0x3d5
-
-#define CR_SERIAL1	0xa0	/* I2C serial communications interface */
-#define MM_SERIAL1	0xff20
-#define CR_SERIAL2	0xb1	/* DDC2 monitor communications interface */
-
-/* based on vt8365 documentation */
-#define PROSAVAGE_I2C_ENAB	0x10
-#define PROSAVAGE_I2C_SCL_OUT	0x01
-#define PROSAVAGE_I2C_SDA_OUT	0x02
-#define PROSAVAGE_I2C_SCL_IN	0x04
-#define PROSAVAGE_I2C_SDA_IN	0x08
-
-#define SAVAGE4_I2C_ENAB	0x00000020
-#define SAVAGE4_I2C_SCL_OUT	0x00000001
-#define SAVAGE4_I2C_SDA_OUT	0x00000002
-#define SAVAGE4_I2C_SCL_IN	0x00000008
-#define SAVAGE4_I2C_SDA_IN	0x00000010
-
-static void savage4_gpio_setscl(void *data, int val)
-{
-	struct savagefb_i2c_chan *chan = data;
-	unsigned int r;
-
-	r = readl(chan->ioaddr + chan->reg);
-	if(val)
-		r |= SAVAGE4_I2C_SCL_OUT;
-	else
-		r &= ~SAVAGE4_I2C_SCL_OUT;
-	writel(r, chan->ioaddr + chan->reg);
-	readl(chan->ioaddr + chan->reg);	/* flush posted write */
-}
-
-static void savage4_gpio_setsda(void *data, int val)
-{
-	struct savagefb_i2c_chan *chan = data;
-
-	unsigned int r;
-	r = readl(chan->ioaddr + chan->reg);
-	if(val)
-		r |= SAVAGE4_I2C_SDA_OUT;
-	else
-		r &= ~SAVAGE4_I2C_SDA_OUT;
-	writel(r, chan->ioaddr + chan->reg);
-	readl(chan->ioaddr + chan->reg);	/* flush posted write */
-}
-
-static int savage4_gpio_getscl(void *data)
-{
-	struct savagefb_i2c_chan *chan = data;
-
-	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));
-}
-
-static int savage4_gpio_getsda(void *data)
-{
-	struct savagefb_i2c_chan *chan = data;
-
-	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));
-}
-
-static void prosavage_gpio_setscl(void* data, int val)
-{
-	struct savagefb_i2c_chan *chan = data;
-	u32			  r;
-
-	r = VGArCR(chan->reg, chan->par);
-	r |= PROSAVAGE_I2C_ENAB;
-	if (val) {
-		r |= PROSAVAGE_I2C_SCL_OUT;
-	} else {
-		r &= ~PROSAVAGE_I2C_SCL_OUT;
-	}
-
-	VGAwCR(chan->reg, r, chan->par);
-}
-
-static void prosavage_gpio_setsda(void* data, int val)
-{
-	struct savagefb_i2c_chan *chan = data;
-	unsigned int r;
-
-	r = VGArCR(chan->reg, chan->par);
-	r |= PROSAVAGE_I2C_ENAB;
-	if (val) {
-		r |= PROSAVAGE_I2C_SDA_OUT;
-	} else {
-		r &= ~PROSAVAGE_I2C_SDA_OUT;
-	}
-
-	VGAwCR(chan->reg, r, chan->par);
-}
-
-static int prosavage_gpio_getscl(void* data)
-{
-	struct savagefb_i2c_chan *chan = data;
-
-	return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SCL_IN) ? 1 : 0;
-}
-
-static int prosavage_gpio_getsda(void* data)
-{
-	struct savagefb_i2c_chan *chan = data;
-
-	return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SDA_IN) ? 1 : 0;
-}
-
-static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
-				const char *name)
-{
-	int rc = 0;
-
-	if (chan->par) {
-		strcpy(chan->adapter.name, name);
-		chan->adapter.owner		= THIS_MODULE;
-		chan->adapter.algo_data		= &chan->algo;
-		chan->adapter.dev.parent	= &chan->par->pcidev->dev;
-		chan->algo.udelay		= 10;
-		chan->algo.timeout		= 20;
-		chan->algo.data 		= chan;
-
-		i2c_set_adapdata(&chan->adapter, chan);
-
-		/* Raise SCL and SDA */
-		chan->algo.setsda(chan, 1);
-		chan->algo.setscl(chan, 1);
-		udelay(20);
-
-		rc = i2c_bit_add_bus(&chan->adapter);
-
-		if (rc == 0)
-			dev_dbg(&chan->par->pcidev->dev,
-				"I2C bus %s registered.\n", name);
-		else
-			dev_warn(&chan->par->pcidev->dev,
-				 "Failed to register I2C bus %s.\n", name);
-	}
-
-	return rc;
-}
-
-void savagefb_create_i2c_busses(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-	par->chan.par	= par;
-
-	switch (par->chip) {
-	case S3_PROSAVAGE:
-	case S3_PROSAVAGEDDR:
-	case S3_TWISTER:
-		par->chan.reg         = CR_SERIAL2;
-		par->chan.ioaddr      = par->mmio.vbase;
-		par->chan.algo.setsda = prosavage_gpio_setsda;
-		par->chan.algo.setscl = prosavage_gpio_setscl;
-		par->chan.algo.getsda = prosavage_gpio_getsda;
-		par->chan.algo.getscl = prosavage_gpio_getscl;
-		break;
-	case S3_SAVAGE4:
-		par->chan.reg = CR_SERIAL1;
-		if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))
-			par->chan.reg = CR_SERIAL2;
-		par->chan.ioaddr      = par->mmio.vbase;
-		par->chan.algo.setsda = prosavage_gpio_setsda;
-		par->chan.algo.setscl = prosavage_gpio_setscl;
-		par->chan.algo.getsda = prosavage_gpio_getsda;
-		par->chan.algo.getscl = prosavage_gpio_getscl;
-		break;
-	case S3_SAVAGE2000:
-		par->chan.reg         = MM_SERIAL1;
-		par->chan.ioaddr      = par->mmio.vbase;
-		par->chan.algo.setsda = savage4_gpio_setsda;
-		par->chan.algo.setscl = savage4_gpio_setscl;
-		par->chan.algo.getsda = savage4_gpio_getsda;
-		par->chan.algo.getscl = savage4_gpio_getscl;
-		break;
-	default:
-		par->chan.par = NULL;
-	}
-
-	savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");
-}
-
-void savagefb_delete_i2c_busses(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-
-	if (par->chan.par)
-		i2c_del_adapter(&par->chan.adapter);
-
-	par->chan.par = NULL;
-}
-
-int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
-{
-	struct savagefb_par *par = info->par;
-	u8 *edid;
-
-	if (par->chan.par)
-		edid = fb_ddc_read(&par->chan.adapter);
-	else
-		edid = NULL;
-
-	if (!edid) {
-		/* try to get from firmware */
-		const u8 *e = fb_firmware_edid(info->device);
-
-		if (e)
-			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
-	}
-
-	*out_edid = edid;
-
-	return (edid) ? 0 : 1;
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
deleted file mode 100644
index dcaab9012ca2..000000000000
--- a/drivers/video/savage/savagefb.h
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * linux/drivers/video/savagefb.h -- S3 Savage Framebuffer Driver
- *
- * Copyright (c) 2001  Denis Oliver Kropp <dok@convergence.de>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- */
-
-
-#ifndef __SAVAGEFB_H__
-#define __SAVAGEFB_H__
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/mutex.h>
-#include <video/vga.h>
-#include "../edid.h"
-
-#ifdef SAVAGEFB_DEBUG
-# define DBG(x)		printk (KERN_DEBUG "savagefb: %s\n", (x));
-#else
-# define DBG(x)
-# define SavagePrintRegs(...)
-#endif
-
-
-#define PCI_CHIP_SAVAGE4      0x8a22
-#define PCI_CHIP_SAVAGE3D     0x8a20
-#define PCI_CHIP_SAVAGE3D_MV  0x8a21
-#define PCI_CHIP_SAVAGE2000   0x9102
-#define PCI_CHIP_SAVAGE_MX_MV 0x8c10
-#define PCI_CHIP_SAVAGE_MX    0x8c11
-#define PCI_CHIP_SAVAGE_IX_MV 0x8c12
-#define PCI_CHIP_SAVAGE_IX    0x8c13
-#define PCI_CHIP_PROSAVAGE_PM 0x8a25
-#define PCI_CHIP_PROSAVAGE_KM 0x8a26
-#define PCI_CHIP_S3TWISTER_P  0x8d01
-#define PCI_CHIP_S3TWISTER_K  0x8d02
-#define PCI_CHIP_PROSAVAGE_DDR          0x8d03
-#define PCI_CHIP_PROSAVAGE_DDRK         0x8d04
-#define PCI_CHIP_SUPSAV_MX128		0x8c22
-#define PCI_CHIP_SUPSAV_MX64		0x8c24
-#define PCI_CHIP_SUPSAV_MX64C		0x8c26
-#define PCI_CHIP_SUPSAV_IX128SDR	0x8c2a
-#define PCI_CHIP_SUPSAV_IX128DDR	0x8c2b
-#define PCI_CHIP_SUPSAV_IX64SDR		0x8c2c
-#define PCI_CHIP_SUPSAV_IX64DDR		0x8c2d
-#define PCI_CHIP_SUPSAV_IXCSDR		0x8c2e
-#define PCI_CHIP_SUPSAV_IXCDDR		0x8c2f
-
-
-#define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
-
-#define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
-
-#define S3_SAVAGE4_SERIES(chip)   ((chip>=S3_SAVAGE4) && (chip<=S3_PROSAVAGEDDR))
-
-#define S3_SAVAGE_MOBILE_SERIES(chip)  ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
-
-#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip==S3_PROSAVAGEDDR))
-
-/* Chip tags.  These are used to group the adapters into
- * related families.
- */
-
-typedef enum {
-  S3_UNKNOWN = 0,
-  S3_SAVAGE3D,
-  S3_SAVAGE_MX,
-  S3_SAVAGE4,
-  S3_PROSAVAGE,
-  S3_TWISTER,
-  S3_PROSAVAGEDDR,
-  S3_SUPERSAVAGE,
-  S3_SAVAGE2000,
-  S3_LAST
-} savage_chipset;
-
-#define BIOS_BSIZE		     1024
-#define BIOS_BASE		     0xc0000
-
-#define SAVAGE_NEWMMIO_REGBASE_S3    0x1000000  /* 16MB */
-#define SAVAGE_NEWMMIO_REGBASE_S4    0x0000000
-#define SAVAGE_NEWMMIO_REGSIZE	     0x0080000  /* 512kb */
-#define SAVAGE_NEWMMIO_VGABASE	     0x8000
-
-#define BASE_FREQ		     14318
-#define HALF_BASE_FREQ               7159
-
-#define FIFO_CONTROL_REG	     0x8200
-#define MIU_CONTROL_REG		     0x8204
-#define STREAMS_TIMEOUT_REG	     0x8208
-#define MISC_TIMEOUT_REG	     0x820c
-
-#define MONO_PAT_0                   0xa4e8
-#define MONO_PAT_1                   0xa4ec
-
-#define MAXFIFO                      0x7f00
-
-#define BCI_CMD_NOP                  0x40000000
-#define BCI_CMD_SETREG               0x96000000
-#define BCI_CMD_RECT                 0x48000000
-#define BCI_CMD_RECT_XP              0x01000000
-#define BCI_CMD_RECT_YP              0x02000000
-#define BCI_CMD_SEND_COLOR           0x00008000
-#define BCI_CMD_DEST_GBD             0x00000000
-#define BCI_CMD_SRC_GBD              0x00000020
-#define BCI_CMD_SRC_SOLID            0x00000000
-#define BCI_CMD_SRC_MONO             0x00000060
-#define BCI_CMD_CLIP_NEW             0x00006000
-#define BCI_CMD_CLIP_LR              0x00004000
-
-#define BCI_CLIP_LR(l, r)            ((((r) << 16) | (l)) & 0x0FFF0FFF)
-#define BCI_CLIP_TL(t, l)            ((((t) << 16) | (l)) & 0x0FFF0FFF)
-#define BCI_CLIP_BR(b, r)            ((((b) << 16) | (r)) & 0x0FFF0FFF)
-#define BCI_W_H(w, h)                (((h) << 16) | ((w) & 0xFFF))
-#define BCI_X_Y(x, y)                (((y) << 16) | ((x) & 0xFFF))
-
-#define BCI_GBD1                     0xE0
-#define BCI_GBD2                     0xE1
-
-#define BCI_BUFFER_OFFSET            0x10000
-#define BCI_SIZE                     0x4000
-
-#define BCI_SEND(dw)                 writel(dw, par->bci_base + par->bci_ptr++)
-
-#define BCI_CMD_GET_ROP(cmd)         (((cmd) >> 16) & 0xFF)
-#define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
-#define BCI_CMD_SEND_COLOR           0x00008000
-
-#define DISP_CRT     1
-#define DISP_LCD     2
-#define DISP_DFP     3
-
-struct xtimings {
-	unsigned int Clock;
-	unsigned int HDisplay;
-	unsigned int HSyncStart;
-	unsigned int HSyncEnd;
-	unsigned int HTotal;
-	unsigned int HAdjusted;
-	unsigned int VDisplay;
-	unsigned int VSyncStart;
-	unsigned int VSyncEnd;
-	unsigned int VTotal;
-	unsigned int sync;
-	int	       dblscan;
-	int	       interlaced;
-};
-
-struct savage_reg {
-	unsigned char MiscOutReg;     /* Misc */
-	unsigned char CRTC[25];       /* Crtc Controller */
-	unsigned char Sequencer[5];   /* Video Sequencer */
-	unsigned char Graphics[9];    /* Video Graphics */
-	unsigned char Attribute[21];  /* Video Attribute */
-
-	unsigned int mode, refresh;
-	unsigned char SR08, SR0E, SR0F;
-	unsigned char SR10, SR11, SR12, SR13, SR15, SR18, SR29, SR30;
-	unsigned char SR54[8];
-	unsigned char Clock;
-	unsigned char CR31, CR32, CR33, CR34, CR36, CR3A, CR3B, CR3C;
-	unsigned char CR40, CR41, CR42, CR43, CR45;
-	unsigned char CR50, CR51, CR53, CR55, CR58, CR5B, CR5D, CR5E;
-	unsigned char CR60, CR63, CR65, CR66, CR67, CR68, CR69, CR6D, CR6F;
-	unsigned char CR86, CR88;
-	unsigned char CR90, CR91, CRB0;
-	unsigned int  STREAMS[22];	/* yuck, streams regs */
-	unsigned int  MMPR0, MMPR1, MMPR2, MMPR3;
-};
-/* --------------------------------------------------------------------- */
-
-#define NR_PALETTE	256
-
-
-struct savagefb_par;
-
-struct savagefb_i2c_chan {
-	struct savagefb_par *par;
-	struct i2c_adapter adapter;
-	struct i2c_algo_bit_data algo;
-	volatile u8 __iomem *ioaddr;
-	u32   reg;
-};
-
-struct savagefb_par {
-	struct pci_dev *pcidev;
-	savage_chipset  chip;
-	struct savagefb_i2c_chan chan;
-	struct savage_reg state;
-	struct savage_reg save;
-	struct savage_reg initial;
-	struct vgastate vgastate;
-	struct mutex open_lock;
-	unsigned char   *edid;
-	u32 pseudo_palette[16];
-	u32 open_count;
-	int paletteEnabled;
-	int pm_state;
-	int display_type;
-	int dvi;
-	int crtonly;
-	int dacSpeedBpp;
-	int maxClock;
-	int minClock;
-	int numClocks;
-	int clock[4];
-	int MCLK, REFCLK, LCDclk;
-	struct {
-		void   __iomem *vbase;
-		u32    pbase;
-		u32    len;
-#ifdef CONFIG_MTRR
-		int    mtrr;
-#endif
-	} video;
-
-	struct {
-		void  __iomem *vbase;
-		u32           pbase;
-		u32           len;
-	} mmio;
-
-	volatile u32  __iomem *bci_base;
-	unsigned int  bci_ptr;
-	u32           cob_offset;
-	u32           cob_size;
-	int           cob_index;
-
-	void (*SavageWaitIdle) (struct savagefb_par *par);
-	void (*SavageWaitFifo) (struct savagefb_par *par, int space);
-
-	int HorizScaleFactor;
-
-	/* Panels size */
-	int SavagePanelWidth;
-	int SavagePanelHeight;
-
-	struct {
-		u16 red, green, blue, transp;
-	} palette[NR_PALETTE];
-
-	int depth;
-	int vwidth;
-};
-
-#define BCI_BD_BW_DISABLE            0x10000000
-#define BCI_BD_SET_BPP(bd, bpp)      ((bd) |= (((bpp) & 0xFF) << 16))
-#define BCI_BD_SET_STRIDE(bd, st)    ((bd) |= ((st) & 0xFFFF))
-
-
-/* IO functions */
-static inline u8 savage_in8(u32 addr, struct savagefb_par *par)
-{
-	return readb(par->mmio.vbase + addr);
-}
-
-static inline u16 savage_in16(u32 addr, struct savagefb_par *par)
-{
-	return readw(par->mmio.vbase + addr);
-}
-
-static inline u32 savage_in32(u32 addr, struct savagefb_par *par)
-{
-	return readl(par->mmio.vbase + addr);
-}
-
-static inline void savage_out8(u32 addr, u8 val, struct savagefb_par *par)
-{
-	writeb(val, par->mmio.vbase + addr);
-}
-
-static inline void savage_out16(u32 addr, u16 val, struct savagefb_par *par)
-{
-	writew(val, par->mmio.vbase + addr);
-}
-
-static inline void savage_out32(u32 addr, u32 val, struct savagefb_par *par)
-{
-	writel(val, par->mmio.vbase + addr);
-}
-
-static inline u8 vga_in8(int addr, struct savagefb_par *par)
-{
-	return savage_in8(0x8000 + addr, par);
-}
-
-static inline u16 vga_in16(int addr, struct savagefb_par *par)
-{
-	return savage_in16(0x8000 + addr, par);
-}
-
-static inline u8 vga_in32(int addr, struct savagefb_par *par)
-{
-	return savage_in32(0x8000 + addr, par);
-}
-
-static inline void vga_out8(int addr, u8 val, struct savagefb_par *par)
-{
-	savage_out8(0x8000 + addr, val, par);
-}
-
-static inline void vga_out16(int addr, u16 val, struct savagefb_par *par)
-{
-	savage_out16(0x8000 + addr, val, par);
-}
-
-static inline void vga_out32(int addr, u32 val, struct savagefb_par *par)
-{
-	savage_out32(0x8000 + addr, val, par);
-}
-
-static inline u8 VGArCR (u8 index, struct savagefb_par *par)
-{
-	vga_out8(0x3d4, index,  par);
-	return vga_in8(0x3d5, par);
-}
-
-static inline u8 VGArGR (u8 index, struct savagefb_par *par)
-{
-	vga_out8(0x3ce, index, par);
-	return vga_in8(0x3cf, par);
-}
-
-static inline u8 VGArSEQ (u8 index, struct savagefb_par *par)
-{
-	vga_out8(0x3c4, index, par);
-	return vga_in8(0x3c5, par);
-}
-
-static inline void VGAwCR(u8 index, u8 val, struct savagefb_par *par)
-{
-	vga_out8(0x3d4, index, par);
-	vga_out8(0x3d5, val, par);
-}
-
-static inline void VGAwGR(u8 index, u8 val, struct savagefb_par *par)
-{
-	vga_out8(0x3ce, index, par);
-	vga_out8(0x3cf, val, par);
-}
-
-static inline void VGAwSEQ(u8 index, u8 val, struct savagefb_par *par)
-{
-	vga_out8(0x3c4, index, par);
-	vga_out8 (0x3c5, val, par);
-}
-
-static inline void VGAenablePalette(struct savagefb_par *par)
-{
-	u8 tmp;
-
-	tmp = vga_in8(0x3da, par);
-	vga_out8(0x3c0, 0x00, par);
-	par->paletteEnabled = 1;
-}
-
-static inline void VGAdisablePalette(struct savagefb_par *par)
-{
-	u8 tmp;
-
-	tmp = vga_in8(0x3da, par);
-	vga_out8(0x3c0, 0x20, par);
-	par->paletteEnabled = 0;
-}
-
-static inline void VGAwATTR(u8 index, u8 value, struct savagefb_par *par)
-{
-	u8 tmp;
-
-	if (par->paletteEnabled)
-		index &= ~0x20;
-	else
-		index |= 0x20;
-
-	tmp = vga_in8(0x3da, par);
-	vga_out8(0x3c0, index, par);
-	vga_out8 (0x3c0, value, par);
-}
-
-static inline void VGAwMISC(u8 value, struct savagefb_par *par)
-{
-	vga_out8(0x3c2, value, par);
-}
-
-#ifndef CONFIG_FB_SAVAGE_ACCEL
-#define savagefb_set_clip(x)
-#endif
-
-static inline void VerticalRetraceWait(struct savagefb_par *par)
-{
-	vga_out8(0x3d4, 0x17, par);
-	if (vga_in8(0x3d5, par) & 0x80) {
-		while ((vga_in8(0x3da, par) & 0x08) == 0x08);
-		while ((vga_in8(0x3da, par) & 0x08) == 0x00);
-	}
-}
-
-extern int savagefb_probe_i2c_connector(struct fb_info *info,
-					u8 **out_edid);
-extern void savagefb_create_i2c_busses(struct fb_info *info);
-extern void savagefb_delete_i2c_busses(struct fb_info *info);
-extern int  savagefb_sync(struct fb_info *info);
-extern void savagefb_copyarea(struct fb_info *info,
-			      const struct fb_copyarea *region);
-extern void savagefb_fillrect(struct fb_info *info,
-			      const struct fb_fillrect *rect);
-extern void savagefb_imageblit(struct fb_info *info,
-			       const struct fb_image *image);
-
-
-#endif /* __SAVAGEFB_H__ */
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
deleted file mode 100644
index bfefa6234cf0..000000000000
--- a/drivers/video/savage/savagefb_accel.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*-*- linux-c -*-
- *  linux/drivers/video/savage/savage_accel.c -- Hardware Acceleration
- *
- *      Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <linux/module.h>
-
-#include "savagefb.h"
-
-static u32 savagefb_rop[] = {
-	0xCC, /* ROP_COPY */
-	0x5A  /* ROP_XOR  */
-};
-
-int savagefb_sync(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-
-	par->SavageWaitIdle(par);
-	return 0;
-}
-
-void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
-	struct savagefb_par *par = info->par;
-	int sx = region->sx, dx = region->dx;
-	int sy = region->sy, dy = region->dy;
-	int cmd;
-
-	if (!region->width || !region->height)
-		return;
-	par->bci_ptr = 0;
-	cmd = BCI_CMD_RECT | BCI_CMD_DEST_GBD | BCI_CMD_SRC_GBD;
-	BCI_CMD_SET_ROP(cmd, savagefb_rop[0]);
-
-	if (dx <= sx) {
-		cmd |= BCI_CMD_RECT_XP;
-	} else {
-		sx += region->width - 1;
-		dx += region->width - 1;
-	}
-
-	if (dy <= sy) {
-		cmd |= BCI_CMD_RECT_YP;
-	} else {
-		sy += region->height - 1;
-		dy += region->height - 1;
-	}
-
-	par->SavageWaitFifo(par,4);
-	BCI_SEND(cmd);
-	BCI_SEND(BCI_X_Y(sx, sy));
-	BCI_SEND(BCI_X_Y(dx, dy));
-	BCI_SEND(BCI_W_H(region->width, region->height));
-}
-
-void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct savagefb_par *par = info->par;
-	int cmd, color;
-
-	if (!rect->width || !rect->height)
-		return;
-
-	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
-		color = rect->color;
-	else
-		color = ((u32 *)info->pseudo_palette)[rect->color];
-
-	cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
-	      BCI_CMD_DEST_GBD | BCI_CMD_SRC_SOLID |
-	      BCI_CMD_SEND_COLOR;
-
-	par->bci_ptr = 0;
-	BCI_CMD_SET_ROP(cmd, savagefb_rop[rect->rop]);
-
-	par->SavageWaitFifo(par,4);
-	BCI_SEND(cmd);
-	BCI_SEND(color);
-	BCI_SEND( BCI_X_Y(rect->dx, rect->dy) );
-	BCI_SEND( BCI_W_H(rect->width, rect->height) );
-}
-
-void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct savagefb_par *par = info->par;
-	int fg, bg, size, i, width;
-	int cmd;
-	u32 *src = (u32 *) image->data;
-
-	if (!image->width || !image->height)
-		return;
-
-	if (image->depth != 1) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
-		fg = image->fg_color;
-		bg = image->bg_color;
-	} else {
-		fg = ((u32 *)info->pseudo_palette)[image->fg_color];
-		bg = ((u32 *)info->pseudo_palette)[image->bg_color];
-	}
-
-	cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
-	      BCI_CMD_CLIP_LR | BCI_CMD_DEST_GBD | BCI_CMD_SRC_MONO |
-	      BCI_CMD_SEND_COLOR;
-
-	par->bci_ptr = 0;
-	BCI_CMD_SET_ROP(cmd, savagefb_rop[0]);
-
-	width = (image->width + 31) & ~31;
-	size = (width * image->height)/8;
-	size >>= 2;
-
-	par->SavageWaitFifo(par, size + 5);
-	BCI_SEND(cmd);
-	BCI_SEND(BCI_CLIP_LR(image->dx, image->dx + image->width - 1));
-	BCI_SEND(fg);
-	BCI_SEND(bg);
-	BCI_SEND(BCI_X_Y(image->dx, image->dy));
-	BCI_SEND(BCI_W_H(width, image->height));
-	for (i = 0; i < size; i++)
-		BCI_SEND(src[i]);
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
deleted file mode 100644
index 4dbf45f3b21a..000000000000
--- a/drivers/video/savage/savagefb_driver.c
+++ /dev/null
@@ -1,2571 +0,0 @@
-/*
- * linux/drivers/video/savagefb.c -- S3 Savage Framebuffer Driver
- *
- * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
- *                          Sven Neumann <neo@directfb.org>
- *
- *
- * Card specific code is based on XFree86's savage driver.
- * Framebuffer framework code is based on code of cyber2000fb and tdfxfb.
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * 0.4.0 (neo)
- *  - hardware accelerated clear and move
- *
- * 0.3.2 (dok)
- *  - wait for vertical retrace before writing to cr67
- *    at the beginning of savagefb_set_par
- *  - use synchronization registers cr23 and cr26
- *
- * 0.3.1 (dok)
- *  - reset 3D engine
- *  - don't return alpha bits for 32bit format
- *
- * 0.3.0 (dok)
- *  - added WaitIdle functions for all Savage types
- *  - do WaitIdle before mode switching
- *  - code cleanup
- *
- * 0.2.0 (dok)
- *  - first working version
- *
- *
- * TODO
- * - clock validations in decode_var
- *
- * BUGS
- * - white margin on bootup
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include "savagefb.h"
-
-
-#define SAVAGEFB_VERSION "0.4.0_2.6"
-
-/* --------------------------------------------------------------------- */
-
-
-static char *mode_option = NULL;
-
-#ifdef MODULE
-
-MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");
-
-#endif
-
-
-/* --------------------------------------------------------------------- */
-
-static void vgaHWSeqReset(struct savagefb_par *par, int start)
-{
-	if (start)
-		VGAwSEQ(0x00, 0x01, par);	/* Synchronous Reset */
-	else
-		VGAwSEQ(0x00, 0x03, par);	/* End Reset */
-}
-
-static void vgaHWProtect(struct savagefb_par *par, int on)
-{
-	unsigned char tmp;
-
-	if (on) {
-		/*
-		 * Turn off screen and disable sequencer.
-		 */
-		tmp = VGArSEQ(0x01, par);
-
-		vgaHWSeqReset(par, 1);	        /* start synchronous reset */
-		VGAwSEQ(0x01, tmp | 0x20, par);/* disable the display */
-
-		VGAenablePalette(par);
-	} else {
-		/*
-		 * Reenable sequencer, then turn on screen.
-		 */
-
-		tmp = VGArSEQ(0x01, par);
-
-		VGAwSEQ(0x01, tmp & ~0x20, par);/* reenable display */
-		vgaHWSeqReset(par, 0);	        /* clear synchronous reset */
-
-		VGAdisablePalette(par);
-	}
-}
-
-static void vgaHWRestore(struct savagefb_par  *par, struct savage_reg *reg)
-{
-	int i;
-
-	VGAwMISC(reg->MiscOutReg, par);
-
-	for (i = 1; i < 5; i++)
-		VGAwSEQ(i, reg->Sequencer[i], par);
-
-	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
-	   CRTC[17] */
-	VGAwCR(17, reg->CRTC[17] & ~0x80, par);
-
-	for (i = 0; i < 25; i++)
-		VGAwCR(i, reg->CRTC[i], par);
-
-	for (i = 0; i < 9; i++)
-		VGAwGR(i, reg->Graphics[i], par);
-
-	VGAenablePalette(par);
-
-	for (i = 0; i < 21; i++)
-		VGAwATTR(i, reg->Attribute[i], par);
-
-	VGAdisablePalette(par);
-}
-
-static void vgaHWInit(struct fb_var_screeninfo *var,
-		      struct savagefb_par            *par,
-		      struct xtimings                *timings,
-		      struct savage_reg              *reg)
-{
-	reg->MiscOutReg = 0x23;
-
-	if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
-		reg->MiscOutReg |= 0x40;
-
-	if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
-		reg->MiscOutReg |= 0x80;
-
-	/*
-	 * Time Sequencer
-	 */
-	reg->Sequencer[0x00] = 0x00;
-	reg->Sequencer[0x01] = 0x01;
-	reg->Sequencer[0x02] = 0x0F;
-	reg->Sequencer[0x03] = 0x00;          /* Font select */
-	reg->Sequencer[0x04] = 0x0E;          /* Misc */
-
-	/*
-	 * CRTC Controller
-	 */
-	reg->CRTC[0x00] = (timings->HTotal >> 3) - 5;
-	reg->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
-	reg->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
-	reg->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
-	reg->CRTC[0x04] = (timings->HSyncStart >> 3);
-	reg->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
-		(((timings->HSyncEnd >> 3)) & 0x1f);
-	reg->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
-	reg->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
-		(((timings->VDisplay - 1) & 0x100) >> 7) |
-		((timings->VSyncStart & 0x100) >> 6) |
-		(((timings->VSyncStart - 1) & 0x100) >> 5) |
-		0x10 |
-		(((timings->VTotal - 2) & 0x200) >> 4) |
-		(((timings->VDisplay - 1) & 0x200) >> 3) |
-		((timings->VSyncStart & 0x200) >> 2);
-	reg->CRTC[0x08] = 0x00;
-	reg->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
-
-	if (timings->dblscan)
-		reg->CRTC[0x09] |= 0x80;
-
-	reg->CRTC[0x0a] = 0x00;
-	reg->CRTC[0x0b] = 0x00;
-	reg->CRTC[0x0c] = 0x00;
-	reg->CRTC[0x0d] = 0x00;
-	reg->CRTC[0x0e] = 0x00;
-	reg->CRTC[0x0f] = 0x00;
-	reg->CRTC[0x10] = timings->VSyncStart & 0xff;
-	reg->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
-	reg->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
-	reg->CRTC[0x13] = var->xres_virtual >> 4;
-	reg->CRTC[0x14] = 0x00;
-	reg->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
-	reg->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
-	reg->CRTC[0x17] = 0xc3;
-	reg->CRTC[0x18] = 0xff;
-
-	/*
-	 * are these unnecessary?
-	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
-	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
-	 */
-
-	/*
-	 * Graphics Display Controller
-	 */
-	reg->Graphics[0x00] = 0x00;
-	reg->Graphics[0x01] = 0x00;
-	reg->Graphics[0x02] = 0x00;
-	reg->Graphics[0x03] = 0x00;
-	reg->Graphics[0x04] = 0x00;
-	reg->Graphics[0x05] = 0x40;
-	reg->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
-	reg->Graphics[0x07] = 0x0F;
-	reg->Graphics[0x08] = 0xFF;
-
-
-	reg->Attribute[0x00]  = 0x00; /* standard colormap translation */
-	reg->Attribute[0x01]  = 0x01;
-	reg->Attribute[0x02]  = 0x02;
-	reg->Attribute[0x03]  = 0x03;
-	reg->Attribute[0x04]  = 0x04;
-	reg->Attribute[0x05]  = 0x05;
-	reg->Attribute[0x06]  = 0x06;
-	reg->Attribute[0x07]  = 0x07;
-	reg->Attribute[0x08]  = 0x08;
-	reg->Attribute[0x09]  = 0x09;
-	reg->Attribute[0x0a] = 0x0A;
-	reg->Attribute[0x0b] = 0x0B;
-	reg->Attribute[0x0c] = 0x0C;
-	reg->Attribute[0x0d] = 0x0D;
-	reg->Attribute[0x0e] = 0x0E;
-	reg->Attribute[0x0f] = 0x0F;
-	reg->Attribute[0x10] = 0x41;
-	reg->Attribute[0x11] = 0xFF;
-	reg->Attribute[0x12] = 0x0F;
-	reg->Attribute[0x13] = 0x00;
-	reg->Attribute[0x14] = 0x00;
-}
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/*
- * Hardware Acceleration for SavageFB
- */
-
-/* Wait for fifo space */
-static void
-savage3D_waitfifo(struct savagefb_par *par, int space)
-{
-	int slots = MAXFIFO - space;
-
-	while ((savage_in32(0x48C00, par) & 0x0000ffff) > slots);
-}
-
-static void
-savage4_waitfifo(struct savagefb_par *par, int space)
-{
-	int slots = MAXFIFO - space;
-
-	while ((savage_in32(0x48C60, par) & 0x001fffff) > slots);
-}
-
-static void
-savage2000_waitfifo(struct savagefb_par *par, int space)
-{
-	int slots = MAXFIFO - space;
-
-	while ((savage_in32(0x48C60, par) & 0x0000ffff) > slots);
-}
-
-/* Wait for idle accelerator */
-static void
-savage3D_waitidle(struct savagefb_par *par)
-{
-	while ((savage_in32(0x48C00, par) & 0x0008ffff) != 0x80000);
-}
-
-static void
-savage4_waitidle(struct savagefb_par *par)
-{
-	while ((savage_in32(0x48C60, par) & 0x00a00000) != 0x00a00000);
-}
-
-static void
-savage2000_waitidle(struct savagefb_par *par)
-{
-	while ((savage_in32(0x48C60, par) & 0x009fffff));
-}
-
-#ifdef CONFIG_FB_SAVAGE_ACCEL
-static void
-SavageSetup2DEngine(struct savagefb_par  *par)
-{
-	unsigned long GlobalBitmapDescriptor;
-
-	GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;
-	BCI_BD_SET_BPP(GlobalBitmapDescriptor, par->depth);
-	BCI_BD_SET_STRIDE(GlobalBitmapDescriptor, par->vwidth);
-
-	switch(par->chip) {
-	case S3_SAVAGE3D:
-	case S3_SAVAGE_MX:
-		/* Disable BCI */
-		savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
-		/* Setup BCI command overflow buffer */
-		savage_out32(0x48C14,
-			     (par->cob_offset >> 11) | (par->cob_index << 29),
-			     par);
-		/* Program shadow status update. */
-		savage_out32(0x48C10, 0x78207220, par);
-		savage_out32(0x48C0C, 0, par);
-		/* Enable BCI and command overflow buffer */
-		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par);
-		break;
-	case S3_SAVAGE4:
-	case S3_TWISTER:
-	case S3_PROSAVAGE:
-	case S3_PROSAVAGEDDR:
-	case S3_SUPERSAVAGE:
-		/* Disable BCI */
-		savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
-		/* Program shadow status update */
-		savage_out32(0x48C10, 0x00700040, par);
-		savage_out32(0x48C0C, 0, par);
-		/* Enable BCI without the COB */
-		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x08, par);
-		break;
-	case S3_SAVAGE2000:
-		/* Disable BCI */
-		savage_out32(0x48C18, 0, par);
-		/* Setup BCI command overflow buffer */
-		savage_out32(0x48C18,
-			     (par->cob_offset >> 7) | (par->cob_index),
-			     par);
-		/* Disable shadow status update */
-		savage_out32(0x48A30, 0, par);
-		/* Enable BCI and command overflow buffer */
-		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x00280000,
-			     par);
-		break;
-	    default:
-		break;
-	}
-	/* Turn on 16-bit register access. */
-	vga_out8(0x3d4, 0x31, par);
-	vga_out8(0x3d5, 0x0c, par);
-
-	/* Set stride to use GBD. */
-	vga_out8(0x3d4, 0x50, par);
-	vga_out8(0x3d5, vga_in8(0x3d5, par) | 0xC1, par);
-
-	/* Enable 2D engine. */
-	vga_out8(0x3d4, 0x40, par);
-	vga_out8(0x3d5, 0x01, par);
-
-	savage_out32(MONO_PAT_0, ~0, par);
-	savage_out32(MONO_PAT_1, ~0, par);
-
-	/* Setup plane masks */
-	savage_out32(0x8128, ~0, par); /* enable all write planes */
-	savage_out32(0x812C, ~0, par); /* enable all read planes */
-	savage_out16(0x8134, 0x27, par);
-	savage_out16(0x8136, 0x07, par);
-
-	/* Now set the GBD */
-	par->bci_ptr = 0;
-	par->SavageWaitFifo(par, 4);
-
-	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD1);
-	BCI_SEND(0);
-	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2);
-	BCI_SEND(GlobalBitmapDescriptor);
-
-	/*
-	 * I don't know why, sending this twice fixes the initial black screen,
-	 * prevents X from crashing at least in Toshiba laptops with SavageIX.
-	 * --Tony
-	 */
-	par->bci_ptr = 0;
-	par->SavageWaitFifo(par, 4);
-
-	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD1);
-	BCI_SEND(0);
-	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2);
-	BCI_SEND(GlobalBitmapDescriptor);
-}
-
-static void savagefb_set_clip(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-	int cmd;
-
-	cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
-	par->bci_ptr = 0;
-	par->SavageWaitFifo(par,3);
-	BCI_SEND(cmd);
-	BCI_SEND(BCI_CLIP_TL(0, 0));
-	BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
-}
-#else
-static void SavageSetup2DEngine(struct savagefb_par  *par) {}
-
-#endif
-
-static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
-			    int min_n2, int max_n2, long freq_min,
-			    long freq_max, unsigned int *mdiv,
-			    unsigned int *ndiv, unsigned int *r)
-{
-	long diff, best_diff;
-	unsigned int m;
-	unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
-
-	if (freq < freq_min / (1 << max_n2)) {
-		printk(KERN_ERR "invalid frequency %ld Khz\n", freq);
-		freq = freq_min / (1 << max_n2);
-	}
-	if (freq > freq_max / (1 << min_n2)) {
-		printk(KERN_ERR "invalid frequency %ld Khz\n", freq);
-		freq = freq_max / (1 << min_n2);
-	}
-
-	/* work out suitable timings */
-	best_diff = freq;
-
-	for (n2=min_n2; n2<=max_n2; n2++) {
-		for (n1=min_n1+2; n1<=max_n1+2; n1++) {
-			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
-				BASE_FREQ;
-			if (m < min_m+2 || m > 127+2)
-				continue;
-			if ((m * BASE_FREQ >= freq_min * n1) &&
-			    (m * BASE_FREQ <= freq_max * n1)) {
-				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
-				if (diff < 0)
-					diff = -diff;
-				if (diff < best_diff) {
-					best_diff = diff;
-					best_m = m;
-					best_n1 = n1;
-					best_n2 = n2;
-				}
-			}
-		}
-	}
-
-	*ndiv = best_n1 - 2;
-	*r = best_n2;
-	*mdiv = best_m - 2;
-}
-
-static int common_calc_clock(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)
-{
-	long diff, best_diff;
-	unsigned int m;
-	unsigned char n1, n2;
-	unsigned char best_n1 = 16+2, best_n2 = 2, best_m = 125+2;
-
-	best_diff = freq;
-
-	for (n2 = min_n2; n2 <= max_n2; n2++) {
-		for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {
-			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
-				BASE_FREQ;
-			if (m < min_m + 2 || m > 127+2)
-				continue;
-			if ((m * BASE_FREQ >= freq_min * n1) &&
-			    (m * BASE_FREQ <= freq_max * n1)) {
-				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
-				if (diff < 0)
-					diff = -diff;
-				if (diff < best_diff) {
-					best_diff = diff;
-					best_m = m;
-					best_n1 = n1;
-					best_n2 = n2;
-				}
-			}
-		}
-	}
-
-	if (max_n1 == 63)
-		*ndiv = (best_n1 - 2) | (best_n2 << 6);
-	else
-		*ndiv = (best_n1 - 2) | (best_n2 << 5);
-
-	*mdiv = best_m - 2;
-
-	return 0;
-}
-
-#ifdef SAVAGEFB_DEBUG
-/* This function is used to debug, it prints out the contents of s3 regs */
-
-static void SavagePrintRegs(struct savagefb_par *par)
-{
-	unsigned char i;
-	int vgaCRIndex = 0x3d4;
-	int vgaCRReg = 0x3d5;
-
-	printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "
-	       "xF");
-
-	for (i = 0; i < 0x70; i++) {
-		if (!(i % 16))
-			printk(KERN_DEBUG "\nSR%xx ", i >> 4);
-		vga_out8(0x3c4, i, par);
-		printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par));
-	}
-
-	printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
-	       "xD xE xF");
-
-	for (i = 0; i < 0xB7; i++) {
-		if (!(i % 16))
-			printk(KERN_DEBUG "\nCR%xx ", i >> 4);
-		vga_out8(vgaCRIndex, i, par);
-		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par));
-	}
-
-	printk(KERN_DEBUG "\n\n");
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-static void savage_get_default_par(struct savagefb_par *par, struct savage_reg *reg)
-{
-	unsigned char cr3a, cr53, cr66;
-
-	vga_out16(0x3d4, 0x4838, par);
-	vga_out16(0x3d4, 0xa039, par);
-	vga_out16(0x3c4, 0x0608, par);
-
-	vga_out8(0x3d4, 0x66, par);
-	cr66 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr66 | 0x80, par);
-	vga_out8(0x3d4, 0x3a, par);
-	cr3a = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr3a | 0x80, par);
-	vga_out8(0x3d4, 0x53, par);
-	cr53 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr53 & 0x7f, par);
-
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66, par);
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, cr3a, par);
-
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66, par);
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, cr3a, par);
-
-	/* unlock extended seq regs */
-	vga_out8(0x3c4, 0x08, par);
-	reg->SR08 = vga_in8(0x3c5, par);
-	vga_out8(0x3c5, 0x06, par);
-
-	/* now save all the extended regs we need */
-	vga_out8(0x3d4, 0x31, par);
-	reg->CR31 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x32, par);
-	reg->CR32 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x34, par);
-	reg->CR34 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x36, par);
-	reg->CR36 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x3a, par);
-	reg->CR3A = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x40, par);
-	reg->CR40 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x42, par);
-	reg->CR42 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x45, par);
-	reg->CR45 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x50, par);
-	reg->CR50 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x51, par);
-	reg->CR51 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x53, par);
-	reg->CR53 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x58, par);
-	reg->CR58 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x60, par);
-	reg->CR60 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x66, par);
-	reg->CR66 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x67, par);
-	reg->CR67 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x68, par);
-	reg->CR68 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x69, par);
-	reg->CR69 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x6f, par);
-	reg->CR6F = vga_in8(0x3d5, par);
-
-	vga_out8(0x3d4, 0x33, par);
-	reg->CR33 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x86, par);
-	reg->CR86 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x88, par);
-	reg->CR88 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x90, par);
-	reg->CR90 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x91, par);
-	reg->CR91 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0xb0, par);
-	reg->CRB0 = vga_in8(0x3d5, par) | 0x80;
-
-	/* extended mode timing regs */
-	vga_out8(0x3d4, 0x3b, par);
-	reg->CR3B = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x3c, par);
-	reg->CR3C = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x43, par);
-	reg->CR43 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x5d, par);
-	reg->CR5D = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x5e, par);
-	reg->CR5E = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x65, par);
-	reg->CR65 = vga_in8(0x3d5, par);
-
-	/* save seq extended regs for DCLK PLL programming */
-	vga_out8(0x3c4, 0x0e, par);
-	reg->SR0E = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x0f, par);
-	reg->SR0F = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x10, par);
-	reg->SR10 = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x11, par);
-	reg->SR11 = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x12, par);
-	reg->SR12 = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x13, par);
-	reg->SR13 = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x29, par);
-	reg->SR29 = vga_in8(0x3c5, par);
-
-	vga_out8(0x3c4, 0x15, par);
-	reg->SR15 = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x30, par);
-	reg->SR30 = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x18, par);
-	reg->SR18 = vga_in8(0x3c5, par);
-
-	/* Save flat panel expansion registers. */
-	if (par->chip == S3_SAVAGE_MX) {
-		int i;
-
-		for (i = 0; i < 8; i++) {
-			vga_out8(0x3c4, 0x54+i, par);
-			reg->SR54[i] = vga_in8(0x3c5, par);
-		}
-	}
-
-	vga_out8(0x3d4, 0x66, par);
-	cr66 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr66 | 0x80, par);
-	vga_out8(0x3d4, 0x3a, par);
-	cr3a = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr3a | 0x80, par);
-
-	/* now save MIU regs */
-	if (par->chip != S3_SAVAGE_MX) {
-		reg->MMPR0 = savage_in32(FIFO_CONTROL_REG, par);
-		reg->MMPR1 = savage_in32(MIU_CONTROL_REG, par);
-		reg->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par);
-		reg->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par);
-	}
-
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, cr3a, par);
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66, par);
-}
-
-static void savage_set_default_par(struct savagefb_par *par,
-				struct savage_reg *reg)
-{
-	unsigned char cr3a, cr53, cr66;
-
-	vga_out16(0x3d4, 0x4838, par);
-	vga_out16(0x3d4, 0xa039, par);
-	vga_out16(0x3c4, 0x0608, par);
-
-	vga_out8(0x3d4, 0x66, par);
-	cr66 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr66 | 0x80, par);
-	vga_out8(0x3d4, 0x3a, par);
-	cr3a = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr3a | 0x80, par);
-	vga_out8(0x3d4, 0x53, par);
-	cr53 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr53 & 0x7f, par);
-
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66, par);
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, cr3a, par);
-
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66, par);
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, cr3a, par);
-
-	/* unlock extended seq regs */
-	vga_out8(0x3c4, 0x08, par);
-	vga_out8(0x3c5, reg->SR08, par);
-	vga_out8(0x3c5, 0x06, par);
-
-	/* now restore all the extended regs we need */
-	vga_out8(0x3d4, 0x31, par);
-	vga_out8(0x3d5, reg->CR31, par);
-	vga_out8(0x3d4, 0x32, par);
-	vga_out8(0x3d5, reg->CR32, par);
-	vga_out8(0x3d4, 0x34, par);
-	vga_out8(0x3d5, reg->CR34, par);
-	vga_out8(0x3d4, 0x36, par);
-	vga_out8(0x3d5,reg->CR36, par);
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, reg->CR3A, par);
-	vga_out8(0x3d4, 0x40, par);
-	vga_out8(0x3d5, reg->CR40, par);
-	vga_out8(0x3d4, 0x42, par);
-	vga_out8(0x3d5, reg->CR42, par);
-	vga_out8(0x3d4, 0x45, par);
-	vga_out8(0x3d5, reg->CR45, par);
-	vga_out8(0x3d4, 0x50, par);
-	vga_out8(0x3d5, reg->CR50, par);
-	vga_out8(0x3d4, 0x51, par);
-	vga_out8(0x3d5, reg->CR51, par);
-	vga_out8(0x3d4, 0x53, par);
-	vga_out8(0x3d5, reg->CR53, par);
-	vga_out8(0x3d4, 0x58, par);
-	vga_out8(0x3d5, reg->CR58, par);
-	vga_out8(0x3d4, 0x60, par);
-	vga_out8(0x3d5, reg->CR60, par);
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, reg->CR66, par);
-	vga_out8(0x3d4, 0x67, par);
-	vga_out8(0x3d5, reg->CR67, par);
-	vga_out8(0x3d4, 0x68, par);
-	vga_out8(0x3d5, reg->CR68, par);
-	vga_out8(0x3d4, 0x69, par);
-	vga_out8(0x3d5, reg->CR69, par);
-	vga_out8(0x3d4, 0x6f, par);
-	vga_out8(0x3d5, reg->CR6F, par);
-
-	vga_out8(0x3d4, 0x33, par);
-	vga_out8(0x3d5, reg->CR33, par);
-	vga_out8(0x3d4, 0x86, par);
-	vga_out8(0x3d5, reg->CR86, par);
-	vga_out8(0x3d4, 0x88, par);
-	vga_out8(0x3d5, reg->CR88, par);
-	vga_out8(0x3d4, 0x90, par);
-	vga_out8(0x3d5, reg->CR90, par);
-	vga_out8(0x3d4, 0x91, par);
-	vga_out8(0x3d5, reg->CR91, par);
-	vga_out8(0x3d4, 0xb0, par);
-	vga_out8(0x3d5, reg->CRB0, par);
-
-	/* extended mode timing regs */
-	vga_out8(0x3d4, 0x3b, par);
-	vga_out8(0x3d5, reg->CR3B, par);
-	vga_out8(0x3d4, 0x3c, par);
-	vga_out8(0x3d5, reg->CR3C, par);
-	vga_out8(0x3d4, 0x43, par);
-	vga_out8(0x3d5, reg->CR43, par);
-	vga_out8(0x3d4, 0x5d, par);
-	vga_out8(0x3d5, reg->CR5D, par);
-	vga_out8(0x3d4, 0x5e, par);
-	vga_out8(0x3d5, reg->CR5E, par);
-	vga_out8(0x3d4, 0x65, par);
-	vga_out8(0x3d5, reg->CR65, par);
-
-	/* save seq extended regs for DCLK PLL programming */
-	vga_out8(0x3c4, 0x0e, par);
-	vga_out8(0x3c5, reg->SR0E, par);
-	vga_out8(0x3c4, 0x0f, par);
-	vga_out8(0x3c5, reg->SR0F, par);
-	vga_out8(0x3c4, 0x10, par);
-	vga_out8(0x3c5, reg->SR10, par);
-	vga_out8(0x3c4, 0x11, par);
-	vga_out8(0x3c5, reg->SR11, par);
-	vga_out8(0x3c4, 0x12, par);
-	vga_out8(0x3c5, reg->SR12, par);
-	vga_out8(0x3c4, 0x13, par);
-	vga_out8(0x3c5, reg->SR13, par);
-	vga_out8(0x3c4, 0x29, par);
-	vga_out8(0x3c5, reg->SR29, par);
-
-	vga_out8(0x3c4, 0x15, par);
-	vga_out8(0x3c5, reg->SR15, par);
-	vga_out8(0x3c4, 0x30, par);
-	vga_out8(0x3c5, reg->SR30, par);
-	vga_out8(0x3c4, 0x18, par);
-	vga_out8(0x3c5, reg->SR18, par);
-
-	/* Save flat panel expansion registers. */
-	if (par->chip == S3_SAVAGE_MX) {
-		int i;
-
-		for (i = 0; i < 8; i++) {
-			vga_out8(0x3c4, 0x54+i, par);
-			vga_out8(0x3c5, reg->SR54[i], par);
-		}
-	}
-
-	vga_out8(0x3d4, 0x66, par);
-	cr66 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr66 | 0x80, par);
-	vga_out8(0x3d4, 0x3a, par);
-	cr3a = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr3a | 0x80, par);
-
-	/* now save MIU regs */
-	if (par->chip != S3_SAVAGE_MX) {
-		savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par);
-		savage_out32(MIU_CONTROL_REG, reg->MMPR1, par);
-		savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par);
-		savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par);
-	}
-
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, cr3a, par);
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66, par);
-}
-
-static void savage_update_var(struct fb_var_screeninfo *var,
-			      const struct fb_videomode *modedb)
-{
-	var->xres = var->xres_virtual = modedb->xres;
-	var->yres = modedb->yres;
-        if (var->yres_virtual < var->yres)
-	    var->yres_virtual = var->yres;
-        var->xoffset = var->yoffset = 0;
-        var->pixclock = modedb->pixclock;
-        var->left_margin = modedb->left_margin;
-        var->right_margin = modedb->right_margin;
-        var->upper_margin = modedb->upper_margin;
-        var->lower_margin = modedb->lower_margin;
-        var->hsync_len = modedb->hsync_len;
-        var->vsync_len = modedb->vsync_len;
-        var->sync = modedb->sync;
-        var->vmode = modedb->vmode;
-}
-
-static int savagefb_check_var(struct fb_var_screeninfo   *var,
-			      struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-	int memlen, vramlen, mode_valid = 0;
-
-	DBG("savagefb_check_var");
-
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.offset = var->green.offset =
-			var->blue.offset = 0;
-		var->red.length = var->green.length =
-			var->blue.length = var->bits_per_pixel;
-		break;
-	case 16:
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
-	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
-		mode_valid = 1;
-
-	/* calculate modeline if supported by monitor */
-	if (!mode_valid && info->monspecs.gtf) {
-		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
-			mode_valid = 1;
-	}
-
-	if (!mode_valid) {
-		const struct fb_videomode *mode;
-
-		mode = fb_find_best_mode(var, &info->modelist);
-		if (mode) {
-			savage_update_var(var, mode);
-			mode_valid = 1;
-		}
-	}
-
-	if (!mode_valid && info->monspecs.modedb_len)
-		return -EINVAL;
-
-	/* Is the mode larger than the LCD panel? */
-	if (par->SavagePanelWidth &&
-	    (var->xres > par->SavagePanelWidth ||
-	     var->yres > par->SavagePanelHeight)) {
-		printk(KERN_INFO "Mode (%dx%d) larger than the LCD panel "
-		       "(%dx%d)\n", var->xres,  var->yres,
-		       par->SavagePanelWidth,
-		       par->SavagePanelHeight);
-		return -1;
-	}
-
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	vramlen = info->fix.smem_len;
-
-	memlen = var->xres_virtual * var->bits_per_pixel *
-		var->yres_virtual / 8;
-	if (memlen > vramlen) {
-		var->yres_virtual = vramlen * 8 /
-			(var->xres_virtual * var->bits_per_pixel);
-		memlen = var->xres_virtual * var->bits_per_pixel *
-			var->yres_virtual / 8;
-	}
-
-	/* we must round yres/xres down, we already rounded y/xres_virtual up
-	   if it was possible. We should return -EINVAL, but I disagree */
-	if (var->yres_virtual < var->yres)
-		var->yres = var->yres_virtual;
-	if (var->xres_virtual < var->xres)
-		var->xres = var->xres_virtual;
-	if (var->xoffset + var->xres > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yoffset + var->yres > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	return 0;
-}
-
-
-static int savagefb_decode_var(struct fb_var_screeninfo   *var,
-			       struct savagefb_par        *par,
-			       struct savage_reg          *reg)
-{
-	struct xtimings timings;
-	int width, dclk, i, j; /*, refresh; */
-	unsigned int m, n, r;
-	unsigned char tmp = 0;
-	unsigned int pixclock = var->pixclock;
-
-	DBG("savagefb_decode_var");
-
-	memset(&timings, 0, sizeof(timings));
-
-	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
-	timings.Clock = 1000000000 / pixclock;
-	if (timings.Clock < 1) timings.Clock = 1;
-	timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
-	timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
-	timings.HDisplay = var->xres;
-	timings.HSyncStart = timings.HDisplay + var->right_margin;
-	timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
-	timings.HTotal = timings.HSyncEnd + var->left_margin;
-	timings.VDisplay = var->yres;
-	timings.VSyncStart = timings.VDisplay + var->lower_margin;
-	timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
-	timings.VTotal = timings.VSyncEnd + var->upper_margin;
-	timings.sync = var->sync;
-
-
-	par->depth  = var->bits_per_pixel;
-	par->vwidth = var->xres_virtual;
-
-	if (var->bits_per_pixel == 16  &&  par->chip == S3_SAVAGE3D) {
-		timings.HDisplay *= 2;
-		timings.HSyncStart *= 2;
-		timings.HSyncEnd *= 2;
-		timings.HTotal *= 2;
-	}
-
-	/*
-	 * This will allocate the datastructure and initialize all of the
-	 * generic VGA registers.
-	 */
-	vgaHWInit(var, par, &timings, reg);
-
-	/* We need to set CR67 whether or not we use the BIOS. */
-
-	dclk = timings.Clock;
-	reg->CR67 = 0x00;
-
-	switch(var->bits_per_pixel) {
-	case 8:
-		if ((par->chip == S3_SAVAGE2000) && (dclk >= 230000))
-			reg->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
-		else
-			reg->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
-		break;
-	case 15:
-		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))
-			reg->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
-		else
-			reg->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
-		break;
-	case 16:
-		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-		   ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))
-			reg->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
-		else
-			reg->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
-		break;
-	case 24:
-		reg->CR67 = 0x70;
-		break;
-	case 32:
-		reg->CR67 = 0xd0;
-		break;
-	}
-
-	/*
-	 * Either BIOS use is disabled, or we failed to find a suitable
-	 * match.  Fall back to traditional register-crunching.
-	 */
-
-	vga_out8(0x3d4, 0x3a, par);
-	tmp = vga_in8(0x3d5, par);
-	if (1 /*FIXME:psav->pci_burst*/)
-		reg->CR3A = (tmp & 0x7f) | 0x15;
-	else
-		reg->CR3A = tmp | 0x95;
-
-	reg->CR53 = 0x00;
-	reg->CR31 = 0x8c;
-	reg->CR66 = 0x89;
-
-	vga_out8(0x3d4, 0x58, par);
-	reg->CR58 = vga_in8(0x3d5, par) & 0x80;
-	reg->CR58 |= 0x13;
-
-	reg->SR15 = 0x03 | 0x80;
-	reg->SR18 = 0x00;
-	reg->CR43 = reg->CR45 = reg->CR65 = 0x00;
-
-	vga_out8(0x3d4, 0x40, par);
-	reg->CR40 = vga_in8(0x3d5, par) & ~0x01;
-
-	reg->MMPR0 = 0x010400;
-	reg->MMPR1 = 0x00;
-	reg->MMPR2 = 0x0808;
-	reg->MMPR3 = 0x08080810;
-
-	SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
-	/* m = 107; n = 4; r = 2; */
-
-	if (par->MCLK <= 0) {
-		reg->SR10 = 255;
-		reg->SR11 = 255;
-	} else {
-		common_calc_clock(par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
-				   &reg->SR11, &reg->SR10);
-		/*      reg->SR10 = 80; // MCLK == 286000 */
-		/*      reg->SR11 = 125; */
-	}
-
-	reg->SR12 = (r << 6) | (n & 0x3f);
-	reg->SR13 = m & 0xff;
-	reg->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
-
-	if (var->bits_per_pixel < 24)
-		reg->MMPR0 -= 0x8000;
-	else
-		reg->MMPR0 -= 0x4000;
-
-	if (timings.interlaced)
-		reg->CR42 = 0x20;
-	else
-		reg->CR42 = 0x00;
-
-	reg->CR34 = 0x10; /* display fifo */
-
-	i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |
-		((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |
-		((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) |
-		((timings.HSyncStart & 0x800) >> 7);
-
-	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64)
-		i |= 0x08;
-	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)
-		i |= 0x20;
-
-	j = (reg->CRTC[0] + ((i & 0x01) << 8) +
-	     reg->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
-
-	if (j - (reg->CRTC[4] + ((i & 0x10) << 4)) < 4) {
-		if (reg->CRTC[4] + ((i & 0x10) << 4) + 4 <=
-		    reg->CRTC[0] + ((i & 0x01) << 8))
-			j = reg->CRTC[4] + ((i & 0x10) << 4) + 4;
-		else
-			j = reg->CRTC[0] + ((i & 0x01) << 8) + 1;
-	}
-
-	reg->CR3B = j & 0xff;
-	i |= (j & 0x100) >> 2;
-	reg->CR3C = (reg->CRTC[0] + ((i & 0x01) << 8)) / 2;
-	reg->CR5D = i;
-	reg->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
-		(((timings.VDisplay - 1) & 0x400) >> 9) |
-		(((timings.VSyncStart) & 0x400) >> 8) |
-		(((timings.VSyncStart) & 0x400) >> 6) | 0x40;
-	width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;
-	reg->CR91 = reg->CRTC[19] = 0xff & width;
-	reg->CR51 = (0x300 & width) >> 4;
-	reg->CR90 = 0x80 | (width >> 8);
-	reg->MiscOutReg |= 0x0c;
-
-	/* Set frame buffer description. */
-
-	if (var->bits_per_pixel <= 8)
-		reg->CR50 = 0;
-	else if (var->bits_per_pixel <= 16)
-		reg->CR50 = 0x10;
-	else
-		reg->CR50 = 0x30;
-
-	if (var->xres_virtual <= 640)
-		reg->CR50 |= 0x40;
-	else if (var->xres_virtual == 800)
-		reg->CR50 |= 0x80;
-	else if (var->xres_virtual == 1024)
-		reg->CR50 |= 0x00;
-	else if (var->xres_virtual == 1152)
-		reg->CR50 |= 0x01;
-	else if (var->xres_virtual == 1280)
-		reg->CR50 |= 0xc0;
-	else if (var->xres_virtual == 1600)
-		reg->CR50 |= 0x81;
-	else
-		reg->CR50 |= 0xc1;	/* Use GBD */
-
-	if (par->chip == S3_SAVAGE2000)
-		reg->CR33 = 0x08;
-	else
-		reg->CR33 = 0x20;
-
-	reg->CRTC[0x17] = 0xeb;
-
-	reg->CR67 |= 1;
-
-	vga_out8(0x3d4, 0x36, par);
-	reg->CR36 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x68, par);
-	reg->CR68 = vga_in8(0x3d5, par);
-	reg->CR69 = 0;
-	vga_out8(0x3d4, 0x6f, par);
-	reg->CR6F = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x86, par);
-	reg->CR86 = vga_in8(0x3d5, par);
-	vga_out8(0x3d4, 0x88, par);
-	reg->CR88 = vga_in8(0x3d5, par) | 0x08;
-	vga_out8(0x3d4, 0xb0, par);
-	reg->CRB0 = vga_in8(0x3d5, par) | 0x80;
-
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-static int savagefb_setcolreg(unsigned        regno,
-			      unsigned        red,
-			      unsigned        green,
-			      unsigned        blue,
-			      unsigned        transp,
-			      struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-
-	if (regno >= NR_PALETTE)
-		return -EINVAL;
-
-	par->palette[regno].red    = red;
-	par->palette[regno].green  = green;
-	par->palette[regno].blue   = blue;
-	par->palette[regno].transp = transp;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		vga_out8(0x3c8, regno, par);
-
-		vga_out8(0x3c9, red   >> 10, par);
-		vga_out8(0x3c9, green >> 10, par);
-		vga_out8(0x3c9, blue  >> 10, par);
-		break;
-
-	case 16:
-		if (regno < 16)
-			((u32 *)info->pseudo_palette)[regno] =
-				((red   & 0xf800)      ) |
-				((green & 0xfc00) >>  5) |
-				((blue  & 0xf800) >> 11);
-		break;
-
-	case 24:
-		if (regno < 16)
-			((u32 *)info->pseudo_palette)[regno] =
-				((red    & 0xff00) <<  8) |
-				((green  & 0xff00)      ) |
-				((blue   & 0xff00) >>  8);
-		break;
-	case 32:
-		if (regno < 16)
-			((u32 *)info->pseudo_palette)[regno] =
-				((transp & 0xff00) << 16) |
-				((red    & 0xff00) <<  8) |
-				((green  & 0xff00)      ) |
-				((blue   & 0xff00) >>  8);
-		break;
-
-	default:
-		return 1;
-	}
-
-	return 0;
-}
-
-static void savagefb_set_par_int(struct savagefb_par  *par, struct savage_reg *reg)
-{
-	unsigned char tmp, cr3a, cr66, cr67;
-
-	DBG("savagefb_set_par_int");
-
-	par->SavageWaitIdle(par);
-
-	vga_out8(0x3c2, 0x23, par);
-
-	vga_out16(0x3d4, 0x4838, par);
-	vga_out16(0x3d4, 0xa539, par);
-	vga_out16(0x3c4, 0x0608, par);
-
-	vgaHWProtect(par, 1);
-
-	/*
-	 * Some Savage/MX and /IX systems go nuts when trying to exit the
-	 * server after WindowMaker has displayed a gradient background.  I
-	 * haven't been able to find what causes it, but a non-destructive
-	 * switch to mode 3 here seems to eliminate the issue.
-	 */
-
-	VerticalRetraceWait(par);
-	vga_out8(0x3d4, 0x67, par);
-	cr67 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */
-
-	vga_out8(0x3d4, 0x23, par);
-	vga_out8(0x3d5, 0x00, par);
-	vga_out8(0x3d4, 0x26, par);
-	vga_out8(0x3d5, 0x00, par);
-
-	/* restore extended regs */
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, reg->CR66, par);
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, reg->CR3A, par);
-	vga_out8(0x3d4, 0x31, par);
-	vga_out8(0x3d5, reg->CR31, par);
-	vga_out8(0x3d4, 0x32, par);
-	vga_out8(0x3d5, reg->CR32, par);
-	vga_out8(0x3d4, 0x58, par);
-	vga_out8(0x3d5, reg->CR58, par);
-	vga_out8(0x3d4, 0x53, par);
-	vga_out8(0x3d5, reg->CR53 & 0x7f, par);
-
-	vga_out16(0x3c4, 0x0608, par);
-
-	/* Restore DCLK registers. */
-
-	vga_out8(0x3c4, 0x0e, par);
-	vga_out8(0x3c5, reg->SR0E, par);
-	vga_out8(0x3c4, 0x0f, par);
-	vga_out8(0x3c5, reg->SR0F, par);
-	vga_out8(0x3c4, 0x29, par);
-	vga_out8(0x3c5, reg->SR29, par);
-	vga_out8(0x3c4, 0x15, par);
-	vga_out8(0x3c5, reg->SR15, par);
-
-	/* Restore flat panel expansion registers. */
-	if (par->chip == S3_SAVAGE_MX) {
-		int i;
-
-		for (i = 0; i < 8; i++) {
-			vga_out8(0x3c4, 0x54+i, par);
-			vga_out8(0x3c5, reg->SR54[i], par);
-		}
-	}
-
-	vgaHWRestore (par, reg);
-
-	/* extended mode timing registers */
-	vga_out8(0x3d4, 0x53, par);
-	vga_out8(0x3d5, reg->CR53, par);
-	vga_out8(0x3d4, 0x5d, par);
-	vga_out8(0x3d5, reg->CR5D, par);
-	vga_out8(0x3d4, 0x5e, par);
-	vga_out8(0x3d5, reg->CR5E, par);
-	vga_out8(0x3d4, 0x3b, par);
-	vga_out8(0x3d5, reg->CR3B, par);
-	vga_out8(0x3d4, 0x3c, par);
-	vga_out8(0x3d5, reg->CR3C, par);
-	vga_out8(0x3d4, 0x43, par);
-	vga_out8(0x3d5, reg->CR43, par);
-	vga_out8(0x3d4, 0x65, par);
-	vga_out8(0x3d5, reg->CR65, par);
-
-	/* restore the desired video mode with cr67 */
-	vga_out8(0x3d4, 0x67, par);
-	/* following part not present in X11 driver */
-	cr67 = vga_in8(0x3d5, par) & 0xf;
-	vga_out8(0x3d5, 0x50 | cr67, par);
-	mdelay(10);
-	vga_out8(0x3d4, 0x67, par);
-	/* end of part */
-	vga_out8(0x3d5, reg->CR67 & ~0x0c, par);
-
-	/* other mode timing and extended regs */
-	vga_out8(0x3d4, 0x34, par);
-	vga_out8(0x3d5, reg->CR34, par);
-	vga_out8(0x3d4, 0x40, par);
-	vga_out8(0x3d5, reg->CR40, par);
-	vga_out8(0x3d4, 0x42, par);
-	vga_out8(0x3d5, reg->CR42, par);
-	vga_out8(0x3d4, 0x45, par);
-	vga_out8(0x3d5, reg->CR45, par);
-	vga_out8(0x3d4, 0x50, par);
-	vga_out8(0x3d5, reg->CR50, par);
-	vga_out8(0x3d4, 0x51, par);
-	vga_out8(0x3d5, reg->CR51, par);
-
-	/* memory timings */
-	vga_out8(0x3d4, 0x36, par);
-	vga_out8(0x3d5, reg->CR36, par);
-	vga_out8(0x3d4, 0x60, par);
-	vga_out8(0x3d5, reg->CR60, par);
-	vga_out8(0x3d4, 0x68, par);
-	vga_out8(0x3d5, reg->CR68, par);
-	vga_out8(0x3d4, 0x69, par);
-	vga_out8(0x3d5, reg->CR69, par);
-	vga_out8(0x3d4, 0x6f, par);
-	vga_out8(0x3d5, reg->CR6F, par);
-
-	vga_out8(0x3d4, 0x33, par);
-	vga_out8(0x3d5, reg->CR33, par);
-	vga_out8(0x3d4, 0x86, par);
-	vga_out8(0x3d5, reg->CR86, par);
-	vga_out8(0x3d4, 0x88, par);
-	vga_out8(0x3d5, reg->CR88, par);
-	vga_out8(0x3d4, 0x90, par);
-	vga_out8(0x3d5, reg->CR90, par);
-	vga_out8(0x3d4, 0x91, par);
-	vga_out8(0x3d5, reg->CR91, par);
-
-	if (par->chip == S3_SAVAGE4) {
-		vga_out8(0x3d4, 0xb0, par);
-		vga_out8(0x3d5, reg->CRB0, par);
-	}
-
-	vga_out8(0x3d4, 0x32, par);
-	vga_out8(0x3d5, reg->CR32, par);
-
-	/* unlock extended seq regs */
-	vga_out8(0x3c4, 0x08, par);
-	vga_out8(0x3c5, 0x06, par);
-
-	/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
-	 * that we should leave the default SR10 and SR11 values there.
-	 */
-	if (reg->SR10 != 255) {
-		vga_out8(0x3c4, 0x10, par);
-		vga_out8(0x3c5, reg->SR10, par);
-		vga_out8(0x3c4, 0x11, par);
-		vga_out8(0x3c5, reg->SR11, par);
-	}
-
-	/* restore extended seq regs for dclk */
-	vga_out8(0x3c4, 0x0e, par);
-	vga_out8(0x3c5, reg->SR0E, par);
-	vga_out8(0x3c4, 0x0f, par);
-	vga_out8(0x3c5, reg->SR0F, par);
-	vga_out8(0x3c4, 0x12, par);
-	vga_out8(0x3c5, reg->SR12, par);
-	vga_out8(0x3c4, 0x13, par);
-	vga_out8(0x3c5, reg->SR13, par);
-	vga_out8(0x3c4, 0x29, par);
-	vga_out8(0x3c5, reg->SR29, par);
-	vga_out8(0x3c4, 0x18, par);
-	vga_out8(0x3c5, reg->SR18, par);
-
-	/* load new m, n pll values for dclk & mclk */
-	vga_out8(0x3c4, 0x15, par);
-	tmp = vga_in8(0x3c5, par) & ~0x21;
-
-	vga_out8(0x3c5, tmp | 0x03, par);
-	vga_out8(0x3c5, tmp | 0x23, par);
-	vga_out8(0x3c5, tmp | 0x03, par);
-	vga_out8(0x3c5, reg->SR15, par);
-	udelay(100);
-
-	vga_out8(0x3c4, 0x30, par);
-	vga_out8(0x3c5, reg->SR30, par);
-	vga_out8(0x3c4, 0x08, par);
-	vga_out8(0x3c5, reg->SR08, par);
-
-	/* now write out cr67 in full, possibly starting STREAMS */
-	VerticalRetraceWait(par);
-	vga_out8(0x3d4, 0x67, par);
-	vga_out8(0x3d5, reg->CR67, par);
-
-	vga_out8(0x3d4, 0x66, par);
-	cr66 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr66 | 0x80, par);
-	vga_out8(0x3d4, 0x3a, par);
-	cr3a = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr3a | 0x80, par);
-
-	if (par->chip != S3_SAVAGE_MX) {
-		VerticalRetraceWait(par);
-		savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par);
-		par->SavageWaitIdle(par);
-		savage_out32(MIU_CONTROL_REG, reg->MMPR1, par);
-		par->SavageWaitIdle(par);
-		savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par);
-		par->SavageWaitIdle(par);
-		savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par);
-	}
-
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66, par);
-	vga_out8(0x3d4, 0x3a, par);
-	vga_out8(0x3d5, cr3a, par);
-
-	SavageSetup2DEngine(par);
-	vgaHWProtect(par, 0);
-}
-
-static void savagefb_update_start(struct savagefb_par *par, int base)
-{
-	/* program the start address registers */
-	vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
-	vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
-	vga_out8(0x3d4, 0x69, par);
-	vga_out8(0x3d5, (base & 0x7f0000) >> 16, par);
-}
-
-
-static void savagefb_set_fix(struct fb_info *info)
-{
-	info->fix.line_length = info->var.xres_virtual *
-		info->var.bits_per_pixel / 8;
-
-	if (info->var.bits_per_pixel == 8) {
-		info->fix.visual      = FB_VISUAL_PSEUDOCOLOR;
-		info->fix.xpanstep    = 4;
-	} else {
-		info->fix.visual      = FB_VISUAL_TRUECOLOR;
-		info->fix.xpanstep    = 2;
-	}
-
-}
-
-static int savagefb_set_par(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	int err;
-
-	DBG("savagefb_set_par");
-	err = savagefb_decode_var(var, par, &par->state);
-	if (err)
-		return err;
-
-	if (par->dacSpeedBpp <= 0) {
-		if (var->bits_per_pixel > 24)
-			par->dacSpeedBpp = par->clock[3];
-		else if (var->bits_per_pixel >= 24)
-			par->dacSpeedBpp = par->clock[2];
-		else if ((var->bits_per_pixel > 8) && (var->bits_per_pixel < 24))
-			par->dacSpeedBpp = par->clock[1];
-		else if (var->bits_per_pixel <= 8)
-			par->dacSpeedBpp = par->clock[0];
-	}
-
-	/* Set ramdac limits */
-	par->maxClock = par->dacSpeedBpp;
-	par->minClock = 10000;
-
-	savagefb_set_par_int(par, &par->state);
-	fb_set_cmap(&info->cmap, info);
-	savagefb_set_fix(info);
-	savagefb_set_clip(info);
-
-	SavagePrintRegs(par);
-	return 0;
-}
-
-/*
- *    Pan or Wrap the Display
- */
-static int savagefb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info           *info)
-{
-	struct savagefb_par *par = info->par;
-	int base;
-
-	base = (var->yoffset * info->fix.line_length
-	     + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2;
-
-	savagefb_update_start(par, base);
-	return 0;
-}
-
-static int savagefb_blank(int blank, struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-	u8 sr8 = 0, srd = 0;
-
-	if (par->display_type == DISP_CRT) {
-		vga_out8(0x3c4, 0x08, par);
-		sr8 = vga_in8(0x3c5, par);
-		sr8 |= 0x06;
-		vga_out8(0x3c5, sr8, par);
-		vga_out8(0x3c4, 0x0d, par);
-		srd = vga_in8(0x3c5, par);
-		srd &= 0x50;
-
-		switch (blank) {
-		case FB_BLANK_UNBLANK:
-		case FB_BLANK_NORMAL:
-			break;
-		case FB_BLANK_VSYNC_SUSPEND:
-			srd |= 0x10;
-			break;
-		case FB_BLANK_HSYNC_SUSPEND:
-			srd |= 0x40;
-			break;
-		case FB_BLANK_POWERDOWN:
-			srd |= 0x50;
-			break;
-		}
-
-		vga_out8(0x3c4, 0x0d, par);
-		vga_out8(0x3c5, srd, par);
-	}
-
-	if (par->display_type == DISP_LCD ||
-	    par->display_type == DISP_DFP) {
-		switch(blank) {
-		case FB_BLANK_UNBLANK:
-		case FB_BLANK_NORMAL:
-			vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
-			vga_out8(0x3c5, vga_in8(0x3c5, par) | 0x10, par);
-			break;
-		case FB_BLANK_VSYNC_SUSPEND:
-		case FB_BLANK_HSYNC_SUSPEND:
-		case FB_BLANK_POWERDOWN:
-			vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
-			vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x10, par);
-			break;
-		}
-	}
-
-	return (blank == FB_BLANK_NORMAL) ? 1 : 0;
-}
-
-static int savagefb_open(struct fb_info *info, int user)
-{
-	struct savagefb_par *par = info->par;
-
-	mutex_lock(&par->open_lock);
-
-	if (!par->open_count) {
-		memset(&par->vgastate, 0, sizeof(par->vgastate));
-		par->vgastate.flags = VGA_SAVE_CMAP | VGA_SAVE_FONTS |
-			VGA_SAVE_MODE;
-		par->vgastate.vgabase = par->mmio.vbase + 0x8000;
-		save_vga(&par->vgastate);
-		savage_get_default_par(par, &par->initial);
-	}
-
-	par->open_count++;
-	mutex_unlock(&par->open_lock);
-	return 0;
-}
-
-static int savagefb_release(struct fb_info *info, int user)
-{
-	struct savagefb_par *par = info->par;
-
-	mutex_lock(&par->open_lock);
-
-	if (par->open_count == 1) {
-		savage_set_default_par(par, &par->initial);
-		restore_vga(&par->vgastate);
-	}
-
-	par->open_count--;
-	mutex_unlock(&par->open_lock);
-	return 0;
-}
-
-static struct fb_ops savagefb_ops = {
-	.owner          = THIS_MODULE,
-	.fb_open        = savagefb_open,
-	.fb_release     = savagefb_release,
-	.fb_check_var   = savagefb_check_var,
-	.fb_set_par     = savagefb_set_par,
-	.fb_setcolreg   = savagefb_setcolreg,
-	.fb_pan_display = savagefb_pan_display,
-	.fb_blank       = savagefb_blank,
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-	.fb_fillrect    = savagefb_fillrect,
-	.fb_copyarea    = savagefb_copyarea,
-	.fb_imageblit   = savagefb_imageblit,
-	.fb_sync        = savagefb_sync,
-#else
-	.fb_fillrect    = cfb_fillrect,
-	.fb_copyarea    = cfb_copyarea,
-	.fb_imageblit   = cfb_imageblit,
-#endif
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo savagefb_var800x600x8 = {
-	.accel_flags =	FB_ACCELF_TEXT,
-	.xres =		800,
-	.yres =		600,
-	.xres_virtual =  800,
-	.yres_virtual =  600,
-	.bits_per_pixel = 8,
-	.pixclock =	25000,
-	.left_margin =	88,
-	.right_margin =	40,
-	.upper_margin =	23,
-	.lower_margin =	1,
-	.hsync_len =	128,
-	.vsync_len =	4,
-	.sync =		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode =	FB_VMODE_NONINTERLACED
-};
-
-static void savage_enable_mmio(struct savagefb_par *par)
-{
-	unsigned char val;
-
-	DBG("savage_enable_mmio\n");
-
-	val = vga_in8(0x3c3, par);
-	vga_out8(0x3c3, val | 0x01, par);
-	val = vga_in8(0x3cc, par);
-	vga_out8(0x3c2, val | 0x01, par);
-
-	if (par->chip >= S3_SAVAGE4) {
-		vga_out8(0x3d4, 0x40, par);
-		val = vga_in8(0x3d5, par);
-		vga_out8(0x3d5, val | 1, par);
-	}
-}
-
-
-static void savage_disable_mmio(struct savagefb_par *par)
-{
-	unsigned char val;
-
-	DBG("savage_disable_mmio\n");
-
-	if (par->chip >= S3_SAVAGE4) {
-		vga_out8(0x3d4, 0x40, par);
-		val = vga_in8(0x3d5, par);
-		vga_out8(0x3d5, val | 1, par);
-	}
-}
-
-
-static int savage_map_mmio(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-	DBG("savage_map_mmio");
-
-	if (S3_SAVAGE3D_SERIES(par->chip))
-		par->mmio.pbase = pci_resource_start(par->pcidev, 0) +
-			SAVAGE_NEWMMIO_REGBASE_S3;
-	else
-		par->mmio.pbase = pci_resource_start(par->pcidev, 0) +
-			SAVAGE_NEWMMIO_REGBASE_S4;
-
-	par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
-
-	par->mmio.vbase = ioremap(par->mmio.pbase, par->mmio.len);
-	if (!par->mmio.vbase) {
-		printk("savagefb: unable to map memory mapped IO\n");
-		return -ENOMEM;
-	} else
-		printk(KERN_INFO "savagefb: mapped io at %p\n",
-			par->mmio.vbase);
-
-	info->fix.mmio_start = par->mmio.pbase;
-	info->fix.mmio_len   = par->mmio.len;
-
-	par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
-	par->bci_ptr  = 0;
-
-	savage_enable_mmio(par);
-
-	return 0;
-}
-
-static void savage_unmap_mmio(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-	DBG("savage_unmap_mmio");
-
-	savage_disable_mmio(par);
-
-	if (par->mmio.vbase) {
-		iounmap(par->mmio.vbase);
-		par->mmio.vbase = NULL;
-	}
-}
-
-static int savage_map_video(struct fb_info *info, int video_len)
-{
-	struct savagefb_par *par = info->par;
-	int resource;
-
-	DBG("savage_map_video");
-
-	if (S3_SAVAGE3D_SERIES(par->chip))
-		resource = 0;
-	else
-		resource = 1;
-
-	par->video.pbase = pci_resource_start(par->pcidev, resource);
-	par->video.len   = video_len;
-	par->video.vbase = ioremap(par->video.pbase, par->video.len);
-
-	if (!par->video.vbase) {
-		printk("savagefb: unable to map screen memory\n");
-		return -ENOMEM;
-	} else
-		printk(KERN_INFO "savagefb: mapped framebuffer at %p, "
-		       "pbase == %x\n", par->video.vbase, par->video.pbase);
-
-	info->fix.smem_start = par->video.pbase;
-	info->fix.smem_len   = par->video.len - par->cob_size;
-	info->screen_base    = par->video.vbase;
-
-#ifdef CONFIG_MTRR
-	par->video.mtrr = mtrr_add(par->video.pbase, video_len,
-				   MTRR_TYPE_WRCOMB, 1);
-#endif
-
-	/* Clear framebuffer, it's all white in memory after boot */
-	memset_io(par->video.vbase, 0, par->video.len);
-
-	return 0;
-}
-
-static void savage_unmap_video(struct fb_info *info)
-{
-	struct savagefb_par *par = info->par;
-
-	DBG("savage_unmap_video");
-
-	if (par->video.vbase) {
-#ifdef CONFIG_MTRR
-		mtrr_del(par->video.mtrr, par->video.pbase, par->video.len);
-#endif
-
-		iounmap(par->video.vbase);
-		par->video.vbase = NULL;
-		info->screen_base = NULL;
-	}
-}
-
-static int savage_init_hw(struct savagefb_par *par)
-{
-	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
-
-	static unsigned char RamSavage3D[] = { 8, 4, 4, 2 };
-	static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
-	static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
-	static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
-	int videoRam, videoRambytes, dvi;
-
-	DBG("savage_init_hw");
-
-	/* unprotect CRTC[0-7] */
-	vga_out8(0x3d4, 0x11, par);
-	tmp = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, tmp & 0x7f, par);
-
-	/* unlock extended regs */
-	vga_out16(0x3d4, 0x4838, par);
-	vga_out16(0x3d4, 0xa039, par);
-	vga_out16(0x3c4, 0x0608, par);
-
-	vga_out8(0x3d4, 0x40, par);
-	tmp = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, tmp & ~0x01, par);
-
-	/* unlock sys regs */
-	vga_out8(0x3d4, 0x38, par);
-	vga_out8(0x3d5, 0x48, par);
-
-	/* Unlock system registers. */
-	vga_out16(0x3d4, 0x4838, par);
-
-	/* Next go on to detect amount of installed ram */
-
-	vga_out8(0x3d4, 0x36, par);            /* for register CR36 (CONFG_REG1), */
-	config1 = vga_in8(0x3d5, par);    /* get amount of vram installed */
-
-	/* Compute the amount of video memory and offscreen memory. */
-
-	switch  (par->chip) {
-	case S3_SAVAGE3D:
-		videoRam = RamSavage3D[(config1 & 0xC0) >> 6 ] * 1024;
-		break;
-
-	case S3_SAVAGE4:
-		/*
-		 * The Savage4 has one ugly special case to consider.  On
-		 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
-		 * when it really means 8MB.  Why do it the same when you
-		 * can do it different...
-		 */
-		vga_out8(0x3d4, 0x68, par);	/* memory control 1 */
-		if ((vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6))
-			RamSavage4[1] = 8;
-
-		/*FALLTHROUGH*/
-
-	case S3_SAVAGE2000:
-		videoRam = RamSavage4[(config1 & 0xE0) >> 5] * 1024;
-		break;
-
-	case S3_SAVAGE_MX:
-	case S3_SUPERSAVAGE:
-		videoRam = RamSavageMX[(config1 & 0x0E) >> 1] * 1024;
-		break;
-
-	case S3_PROSAVAGE:
-	case S3_PROSAVAGEDDR:
-	case S3_TWISTER:
-		videoRam = RamSavageNB[(config1 & 0xE0) >> 5] * 1024;
-		break;
-
-	default:
-		/* How did we get here? */
-		videoRam = 0;
-		break;
-	}
-
-	videoRambytes = videoRam * 1024;
-
-	printk(KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
-
-	/* reset graphics engine to avoid memory corruption */
-	vga_out8(0x3d4, 0x66, par);
-	cr66 = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr66 | 0x02, par);
-	mdelay(10);
-
-	vga_out8(0x3d4, 0x66, par);
-	vga_out8(0x3d5, cr66 & ~0x02, par);	/* clear reset flag */
-	mdelay(10);
-
-
-	/*
-	 * reset memory interface, 3D engine, AGP master, PCI master,
-	 * master engine unit, motion compensation/LPB
-	 */
-	vga_out8(0x3d4, 0x3f, par);
-	cr3f = vga_in8(0x3d5, par);
-	vga_out8(0x3d5, cr3f | 0x08, par);
-	mdelay(10);
-
-	vga_out8(0x3d4, 0x3f, par);
-	vga_out8(0x3d5, cr3f & ~0x08, par);	/* clear reset flags */
-	mdelay(10);
-
-	/* Savage ramdac speeds */
-	par->numClocks = 4;
-	par->clock[0] = 250000;
-	par->clock[1] = 250000;
-	par->clock[2] = 220000;
-	par->clock[3] = 220000;
-
-	/* detect current mclk */
-	vga_out8(0x3c4, 0x08, par);
-	sr8 = vga_in8(0x3c5, par);
-	vga_out8(0x3c5, 0x06, par);
-	vga_out8(0x3c4, 0x10, par);
-	n = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x11, par);
-	m = vga_in8(0x3c5, par);
-	vga_out8(0x3c4, 0x08, par);
-	vga_out8(0x3c5, sr8, par);
-	m &= 0x7f;
-	n1 = n & 0x1f;
-	n2 = (n >> 5) & 0x03;
-	par->MCLK = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
-	printk(KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
-		par->MCLK);
-
-	/* check for DVI/flat panel */
-	dvi = 0;
-
-	if (par->chip == S3_SAVAGE4) {
-		unsigned char sr30 = 0x00;
-
-		vga_out8(0x3c4, 0x30, par);
-		/* clear bit 1 */
-		vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x02, par);
-		sr30 = vga_in8(0x3c5, par);
-		if (sr30 & 0x02 /*0x04 */) {
-			dvi = 1;
-			printk("savagefb: Digital Flat Panel Detected\n");
-		}
-	}
-
-	if ((S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-	     S3_MOBILE_TWISTER_SERIES(par->chip)) && !par->crtonly)
-		par->display_type = DISP_LCD;
-	else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
-		par->display_type = DISP_DFP;
-	else
-		par->display_type = DISP_CRT;
-
-	/* Check LCD panel parrmation */
-
-	if (par->display_type == DISP_LCD) {
-		unsigned char cr6b = VGArCR(0x6b, par);
-
-		int panelX = (VGArSEQ(0x61, par) +
-			      ((VGArSEQ(0x66, par) & 0x02) << 7) + 1) * 8;
-		int panelY = (VGArSEQ(0x69, par) +
-			      ((VGArSEQ(0x6e, par) & 0x70) << 4) + 1);
-
-		char * sTechnology = "Unknown";
-
-		/* OK, I admit it.  I don't know how to limit the max dot clock
-		 * for LCD panels of various sizes.  I thought I copied the
-		 * formula from the BIOS, but many users have parrmed me of
-		 * my folly.
-		 *
-		 * Instead, I'll abandon any attempt to automatically limit the
-		 * clock, and add an LCDClock option to XF86Config.  Some day,
-		 * I should come back to this.
-		 */
-
-		enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */
-			ActiveCRT = 0x01,
-			ActiveLCD = 0x02,
-			ActiveTV = 0x04,
-			ActiveCRT2 = 0x20,
-			ActiveDUO = 0x80
-		};
-
-		if ((VGArSEQ(0x39, par) & 0x03) == 0) {
-			sTechnology = "TFT";
-		} else if ((VGArSEQ(0x30, par) & 0x01) == 0) {
-			sTechnology = "DSTN";
-		} else 	{
-			sTechnology = "STN";
-		}
-
-		printk(KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
-		       panelX, panelY, sTechnology,
-		       cr6b & ActiveLCD ? "and active" : "but not active");
-
-		if (cr6b & ActiveLCD) 	{
-			/*
-			 * If the LCD is active and panel expansion is enabled,
-			 * we probably want to kill the HW cursor.
-			 */
-
-			printk(KERN_INFO "savagefb: Limiting video mode to "
-				"%dx%d\n", panelX, panelY);
-
-			par->SavagePanelWidth = panelX;
-			par->SavagePanelHeight = panelY;
-
-		} else
-			par->display_type = DISP_CRT;
-	}
-
-	savage_get_default_par(par, &par->state);
-	par->save = par->state;
-
-	if (S3_SAVAGE4_SERIES(par->chip)) {
-		/*
-		 * The Savage4 and ProSavage have COB coherency bugs which
-		 * render the buffer useless.  We disable it.
-		 */
-		par->cob_index = 2;
-		par->cob_size = 0x8000 << par->cob_index;
-		par->cob_offset = videoRambytes;
-	} else {
-		/* We use 128kB for the COB on all chips. */
-
-		par->cob_index  = 7;
-		par->cob_size   = 0x400 << par->cob_index;
-		par->cob_offset = videoRambytes - par->cob_size;
-	}
-
-	return videoRambytes;
-}
-
-static int savage_init_fb_info(struct fb_info *info, struct pci_dev *dev,
-			       const struct pci_device_id *id)
-{
-	struct savagefb_par *par = info->par;
-	int err = 0;
-
-	par->pcidev  = dev;
-
-	info->fix.type	   = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux	   = 0;
-	info->fix.ypanstep	   = 1;
-	info->fix.ywrapstep   = 0;
-	info->fix.accel       = id->driver_data;
-
-	switch (info->fix.accel) {
-	case FB_ACCEL_SUPERSAVAGE:
-		par->chip = S3_SUPERSAVAGE;
-		snprintf(info->fix.id, 16, "SuperSavage");
-		break;
-	case FB_ACCEL_SAVAGE4:
-		par->chip = S3_SAVAGE4;
-		snprintf(info->fix.id, 16, "Savage4");
-		break;
-	case FB_ACCEL_SAVAGE3D:
-		par->chip = S3_SAVAGE3D;
-		snprintf(info->fix.id, 16, "Savage3D");
-		break;
-	case FB_ACCEL_SAVAGE3D_MV:
-		par->chip = S3_SAVAGE3D;
-		snprintf(info->fix.id, 16, "Savage3D-MV");
-		break;
-	case FB_ACCEL_SAVAGE2000:
-		par->chip = S3_SAVAGE2000;
-		snprintf(info->fix.id, 16, "Savage2000");
-		break;
-	case FB_ACCEL_SAVAGE_MX_MV:
-		par->chip = S3_SAVAGE_MX;
-		snprintf(info->fix.id, 16, "Savage/MX-MV");
-		break;
-	case FB_ACCEL_SAVAGE_MX:
-		par->chip = S3_SAVAGE_MX;
-		snprintf(info->fix.id, 16, "Savage/MX");
-		break;
-	case FB_ACCEL_SAVAGE_IX_MV:
-		par->chip = S3_SAVAGE_MX;
-		snprintf(info->fix.id, 16, "Savage/IX-MV");
-		break;
-	case FB_ACCEL_SAVAGE_IX:
-		par->chip = S3_SAVAGE_MX;
-		snprintf(info->fix.id, 16, "Savage/IX");
-		break;
-	case FB_ACCEL_PROSAVAGE_PM:
-		par->chip = S3_PROSAVAGE;
-		snprintf(info->fix.id, 16, "ProSavagePM");
-		break;
-	case FB_ACCEL_PROSAVAGE_KM:
-		par->chip = S3_PROSAVAGE;
-		snprintf(info->fix.id, 16, "ProSavageKM");
-		break;
-	case FB_ACCEL_S3TWISTER_P:
-		par->chip = S3_TWISTER;
-		snprintf(info->fix.id, 16, "TwisterP");
-		break;
-	case FB_ACCEL_S3TWISTER_K:
-		par->chip = S3_TWISTER;
-		snprintf(info->fix.id, 16, "TwisterK");
-		break;
-	case FB_ACCEL_PROSAVAGE_DDR:
-		par->chip = S3_PROSAVAGEDDR;
-		snprintf(info->fix.id, 16, "ProSavageDDR");
-		break;
-	case FB_ACCEL_PROSAVAGE_DDRK:
-		par->chip = S3_PROSAVAGEDDR;
-		snprintf(info->fix.id, 16, "ProSavage8");
-		break;
-	}
-
-	if (S3_SAVAGE3D_SERIES(par->chip)) {
-		par->SavageWaitIdle = savage3D_waitidle;
-		par->SavageWaitFifo = savage3D_waitfifo;
-	} else if (S3_SAVAGE4_SERIES(par->chip) ||
-		   S3_SUPERSAVAGE == par->chip) {
-		par->SavageWaitIdle = savage4_waitidle;
-		par->SavageWaitFifo = savage4_waitfifo;
-	} else {
-		par->SavageWaitIdle = savage2000_waitidle;
-		par->SavageWaitFifo = savage2000_waitfifo;
-	}
-
-	info->var.nonstd      = 0;
-	info->var.activate    = FB_ACTIVATE_NOW;
-	info->var.width       = -1;
-	info->var.height      = -1;
-	info->var.accel_flags = 0;
-
-	info->fbops          = &savagefb_ops;
-	info->flags          = FBINFO_DEFAULT |
-		               FBINFO_HWACCEL_YPAN |
-		               FBINFO_HWACCEL_XPAN;
-
-	info->pseudo_palette = par->pseudo_palette;
-
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-	/* FIFO size + padding for commands */
-	info->pixmap.addr = kcalloc(8, 1024, GFP_KERNEL);
-
-	err = -ENOMEM;
-	if (info->pixmap.addr) {
-		info->pixmap.size = 8*1024;
-		info->pixmap.scan_align = 4;
-		info->pixmap.buf_align = 4;
-		info->pixmap.access_align = 32;
-
-		err = fb_alloc_cmap(&info->cmap, NR_PALETTE, 0);
-		if (!err)
-		info->flags |= FBINFO_HWACCEL_COPYAREA |
-	                       FBINFO_HWACCEL_FILLRECT |
-		               FBINFO_HWACCEL_IMAGEBLIT;
-	}
-#endif
-	return err;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct fb_info *info;
-	struct savagefb_par *par;
-	u_int h_sync, v_sync;
-	int err, lpitch;
-	int video_len;
-
-	DBG("savagefb_probe");
-
-	info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
-	if (!info)
-		return -ENOMEM;
-	par = info->par;
-	mutex_init(&par->open_lock);
-	err = pci_enable_device(dev);
-	if (err)
-		goto failed_enable;
-
-	if ((err = pci_request_regions(dev, "savagefb"))) {
-		printk(KERN_ERR "cannot request PCI regions\n");
-		goto failed_enable;
-	}
-
-	err = -ENOMEM;
-
-	if ((err = savage_init_fb_info(info, dev, id)))
-		goto failed_init;
-
-	err = savage_map_mmio(info);
-	if (err)
-		goto failed_mmio;
-
-	video_len = savage_init_hw(par);
-	/* FIXME: can't be negative */
-	if (video_len < 0) {
-		err = video_len;
-		goto failed_mmio;
-	}
-
-	err = savage_map_video(info, video_len);
-	if (err)
-		goto failed_video;
-
-	INIT_LIST_HEAD(&info->modelist);
-#if defined(CONFIG_FB_SAVAGE_I2C)
-	savagefb_create_i2c_busses(info);
-	savagefb_probe_i2c_connector(info, &par->edid);
-	fb_edid_to_monspecs(par->edid, &info->monspecs);
-	kfree(par->edid);
-	fb_videomode_to_modelist(info->monspecs.modedb,
-				 info->monspecs.modedb_len,
-				 &info->modelist);
-#endif
-	info->var = savagefb_var800x600x8;
-	/* if a panel was detected, default to a CVT mode instead */
-	if (par->SavagePanelWidth) {
-		struct fb_videomode cvt_mode;
-
-		memset(&cvt_mode, 0, sizeof(cvt_mode));
-		cvt_mode.xres = par->SavagePanelWidth;
-		cvt_mode.yres = par->SavagePanelHeight;
-		cvt_mode.refresh = 60;
-		/* FIXME: if we know there is only the panel
-		 * we can enable reduced blanking as well */
-		if (fb_find_mode_cvt(&cvt_mode, 0, 0))
-			printk(KERN_WARNING "No CVT mode found for panel\n");
-		else if (fb_find_mode(&info->var, info, NULL, NULL, 0,
-				      &cvt_mode, 0) != 3)
-			info->var = savagefb_var800x600x8;
-	}
-
-	if (mode_option) {
-		fb_find_mode(&info->var, info, mode_option,
-			     info->monspecs.modedb, info->monspecs.modedb_len,
-			     NULL, 8);
-	} else if (info->monspecs.modedb != NULL) {
-		const struct fb_videomode *mode;
-
-		mode = fb_find_best_display(&info->monspecs, &info->modelist);
-		savage_update_var(&info->var, mode);
-	}
-
-	/* maximize virtual vertical length */
-	lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
-	info->var.yres_virtual = info->fix.smem_len/lpitch;
-
-	if (info->var.yres_virtual < info->var.yres) {
-		err = -ENOMEM;
-		goto failed;
-	}
-
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-	/*
-	 * The clipping coordinates are masked with 0xFFF, so limit our
-	 * virtual resolutions to these sizes.
-	 */
-	if (info->var.yres_virtual > 0x1000)
-		info->var.yres_virtual = 0x1000;
-
-	if (info->var.xres_virtual > 0x1000)
-		info->var.xres_virtual = 0x1000;
-#endif
-	savagefb_check_var(&info->var, info);
-	savagefb_set_fix(info);
-
-	/*
-	 * Calculate the hsync and vsync frequencies.  Note that
-	 * we split the 1e12 constant up so that we can preserve
-	 * the precision and fit the results into 32-bit registers.
-	 *  (1953125000 * 512 = 1e12)
-	 */
-	h_sync = 1953125000 / info->var.pixclock;
-	h_sync = h_sync * 512 / (info->var.xres + info->var.left_margin +
-				 info->var.right_margin +
-				 info->var.hsync_len);
-	v_sync = h_sync / (info->var.yres + info->var.upper_margin +
-			   info->var.lower_margin + info->var.vsync_len);
-
-	printk(KERN_INFO "savagefb v" SAVAGEFB_VERSION ": "
-	       "%dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
-	       info->fix.smem_len >> 10,
-	       info->var.xres, info->var.yres,
-	       h_sync / 1000, h_sync % 1000, v_sync);
-
-
-	fb_destroy_modedb(info->monspecs.modedb);
-	info->monspecs.modedb = NULL;
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto failed;
-
-	printk(KERN_INFO "fb: S3 %s frame buffer device\n",
-	       info->fix.id);
-
-	/*
-	 * Our driver data
-	 */
-	pci_set_drvdata(dev, info);
-
-	return 0;
-
- failed:
-#ifdef CONFIG_FB_SAVAGE_I2C
-	savagefb_delete_i2c_busses(info);
-#endif
-	fb_alloc_cmap(&info->cmap, 0, 0);
-	savage_unmap_video(info);
- failed_video:
-	savage_unmap_mmio(info);
- failed_mmio:
-	kfree(info->pixmap.addr);
- failed_init:
-	pci_release_regions(dev);
- failed_enable:
-	framebuffer_release(info);
-
-	return err;
-}
-
-static void savagefb_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-
-	DBG("savagefb_remove");
-
-	if (info) {
-		/*
-		 * If unregister_framebuffer fails, then
-		 * we will be leaving hooks that could cause
-		 * oopsen laying around.
-		 */
-		if (unregister_framebuffer(info))
-			printk(KERN_WARNING "savagefb: danger danger! "
-			       "Oopsen imminent!\n");
-
-#ifdef CONFIG_FB_SAVAGE_I2C
-		savagefb_delete_i2c_busses(info);
-#endif
-		fb_alloc_cmap(&info->cmap, 0, 0);
-		savage_unmap_video(info);
-		savage_unmap_mmio(info);
-		kfree(info->pixmap.addr);
-		pci_release_regions(dev);
-		framebuffer_release(info);
-	}
-}
-
-static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct savagefb_par *par = info->par;
-
-	DBG("savagefb_suspend");
-
-	if (mesg.event == PM_EVENT_PRETHAW)
-		mesg.event = PM_EVENT_FREEZE;
-	par->pm_state = mesg.event;
-	dev->dev.power.power_state = mesg;
-
-	/*
-	 * For PM_EVENT_FREEZE, do not power down so the console
-	 * can remain active.
-	 */
-	if (mesg.event == PM_EVENT_FREEZE)
-		return 0;
-
-	console_lock();
-	fb_set_suspend(info, 1);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-	savagefb_blank(FB_BLANK_POWERDOWN, info);
-	savage_set_default_par(par, &par->save);
-	savage_disable_mmio(par);
-	pci_save_state(dev);
-	pci_disable_device(dev);
-	pci_set_power_state(dev, pci_choose_state(dev, mesg));
-	console_unlock();
-
-	return 0;
-}
-
-static int savagefb_resume(struct pci_dev* dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct savagefb_par *par = info->par;
-	int cur_state = par->pm_state;
-
-	DBG("savage_resume");
-
-	par->pm_state = PM_EVENT_ON;
-
-	/*
-	 * The adapter was not powered down coming back from a
-	 * PM_EVENT_FREEZE.
-	 */
-	if (cur_state == PM_EVENT_FREEZE) {
-		pci_set_power_state(dev, PCI_D0);
-		return 0;
-	}
-
-	console_lock();
-
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
-
-	if (pci_enable_device(dev))
-		DBG("err");
-
-	pci_set_master(dev);
-	savage_enable_mmio(par);
-	savage_init_hw(par);
-	savagefb_set_par(info);
-	fb_set_suspend(info, 0);
-	savagefb_blank(FB_BLANK_UNBLANK, info);
-	console_unlock();
-
-	return 0;
-}
-
-
-static struct pci_device_id savagefb_devices[] = {
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64C,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128SDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128DDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64SDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64DDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCSDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCDDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE4},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D_MV,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D_MV},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE2000},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX_MV,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX_MV},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX_MV,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX_MV},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_PM,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_PM},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_KM,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_KM},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_P,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_P},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_K,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_K},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDR},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDRK,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDRK},
-
-	{0, 0, 0, 0, 0, 0, 0}
-};
-
-MODULE_DEVICE_TABLE(pci, savagefb_devices);
-
-static struct pci_driver savagefb_driver = {
-	.name =     "savagefb",
-	.id_table = savagefb_devices,
-	.probe =    savagefb_probe,
-	.suspend =  savagefb_suspend,
-	.resume =   savagefb_resume,
-	.remove =   savagefb_remove,
-};
-
-/* **************************** exit-time only **************************** */
-
-static void __exit savage_done(void)
-{
-	DBG("savage_done");
-	pci_unregister_driver(&savagefb_driver);
-}
-
-
-/* ************************* init in-kernel code ************************** */
-
-static int __init savagefb_setup(char *options)
-{
-#ifndef MODULE
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		mode_option = this_opt;
-	}
-#endif /* !MODULE */
-	return 0;
-}
-
-static int __init savagefb_init(void)
-{
-	char *option;
-
-	DBG("savagefb_init");
-
-	if (fb_get_options("savagefb", &option))
-		return -ENODEV;
-
-	savagefb_setup(option);
-	return pci_register_driver(&savagefb_driver);
-
-}
-
-module_init(savagefb_init);
-module_exit(savage_done);
-
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Specify initial video mode");
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
deleted file mode 100644
index a350209ffbd3..000000000000
--- a/drivers/video/sbuslib.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/* sbuslib.c: Helper library for SBUS framebuffer drivers.
- *
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
- */
-
-#include <linux/compat.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <linux/of_device.h>
-
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp,
-		     int bpp)
-{
-	memset(var, 0, sizeof(*var));
-
-	var->xres = of_getintprop_default(dp, "width", 1152);
-	var->yres = of_getintprop_default(dp, "height", 900);
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-	var->bits_per_pixel = bpp;
-}
-
-EXPORT_SYMBOL(sbusfb_fill_var);
-
-static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize)
-{
-	if (size == SBUS_MMAP_EMPTY) return 0;
-	if (size >= 0) return size;
-	return fbsize * (-size);
-}
-
-int sbusfb_mmap_helper(struct sbus_mmap_map *map,
-		       unsigned long physbase,
-		       unsigned long fbsize,
-		       unsigned long iospace,
-		       struct vm_area_struct *vma)
-{
-	unsigned int size, page, r, map_size;
-	unsigned long map_offset = 0;
-	unsigned long off;
-	int i;
-                                        
-	if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE)))
-		return -EINVAL;
-
-	size = vma->vm_end - vma->vm_start;
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	/* Each page, see which map applies */
-	for (page = 0; page < size; ){
-		map_size = 0;
-		for (i = 0; map[i].size; i++)
-			if (map[i].voff == off+page) {
-				map_size = sbusfb_mmapsize(map[i].size, fbsize);
-#ifdef __sparc_v9__
-#define POFF_MASK	(PAGE_MASK|0x1UL)
-#else
-#define POFF_MASK	(PAGE_MASK)
-#endif				
-				map_offset = (physbase + map[i].poff) & POFF_MASK;
-				break;
-			}
-		if (!map_size) {
-			page += PAGE_SIZE;
-			continue;
-		}
-		if (page + map_size > size)
-			map_size = size - page;
-		r = io_remap_pfn_range(vma,
-					vma->vm_start + page,
-					MK_IOSPACE_PFN(iospace,
-						map_offset >> PAGE_SHIFT),
-					map_size,
-					vma->vm_page_prot);
-		if (r)
-			return -EAGAIN;
-		page += map_size;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(sbusfb_mmap_helper);
-
-int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
-			struct fb_info *info,
-			int type, int fb_depth, unsigned long fb_size)
-{
-	switch(cmd) {
-	case FBIOGTYPE: {
-		struct fbtype __user *f = (struct fbtype __user *) arg;
-
-		if (put_user(type, &f->fb_type) ||
-		    __put_user(info->var.yres, &f->fb_height) ||
-		    __put_user(info->var.xres, &f->fb_width) ||
-		    __put_user(fb_depth, &f->fb_depth) ||
-		    __put_user(0, &f->fb_cmsize) ||
-		    __put_user(fb_size, &f->fb_cmsize))
-			return -EFAULT;
-		return 0;
-	}
-	case FBIOPUTCMAP_SPARC: {
-		struct fbcmap __user *c = (struct fbcmap __user *) arg;
-		struct fb_cmap cmap;
-		u16 red, green, blue;
-		u8 red8, green8, blue8;
-		unsigned char __user *ured;
-		unsigned char __user *ugreen;
-		unsigned char __user *ublue;
-		int index, count, i;
-
-		if (get_user(index, &c->index) ||
-		    __get_user(count, &c->count) ||
-		    __get_user(ured, &c->red) ||
-		    __get_user(ugreen, &c->green) ||
-		    __get_user(ublue, &c->blue))
-			return -EFAULT;
-
-		cmap.len = 1;
-		cmap.red = &red;
-		cmap.green = &green;
-		cmap.blue = &blue;
-		cmap.transp = NULL;
-		for (i = 0; i < count; i++) {
-			int err;
-
-			if (get_user(red8, &ured[i]) ||
-			    get_user(green8, &ugreen[i]) ||
-			    get_user(blue8, &ublue[i]))
-				return -EFAULT;
-
-			red = red8 << 8;
-			green = green8 << 8;
-			blue = blue8 << 8;
-
-			cmap.start = index + i;
-			err = fb_set_cmap(&cmap, info);
-			if (err)
-				return err;
-		}
-		return 0;
-	}
-	case FBIOGETCMAP_SPARC: {
-		struct fbcmap __user *c = (struct fbcmap __user *) arg;
-		unsigned char __user *ured;
-		unsigned char __user *ugreen;
-		unsigned char __user *ublue;
-		struct fb_cmap *cmap = &info->cmap;
-		int index, count, i;
-		u8 red, green, blue;
-
-		if (get_user(index, &c->index) ||
-		    __get_user(count, &c->count) ||
-		    __get_user(ured, &c->red) ||
-		    __get_user(ugreen, &c->green) ||
-		    __get_user(ublue, &c->blue))
-			return -EFAULT;
-
-		if (index + count > cmap->len)
-			return -EINVAL;
-
-		for (i = 0; i < count; i++) {
-			red = cmap->red[index + i] >> 8;
-			green = cmap->green[index + i] >> 8;
-			blue = cmap->blue[index + i] >> 8;
-			if (put_user(red, &ured[i]) ||
-			    put_user(green, &ugreen[i]) ||
-			    put_user(blue, &ublue[i]))
-				return -EFAULT;
-		}
-		return 0;
-	}
-	default:
-		return -EINVAL;
-	}
-}
-EXPORT_SYMBOL(sbusfb_ioctl_helper);
-
-#ifdef CONFIG_COMPAT
-static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	struct fbcmap32 __user *argp = (void __user *)arg;
-	struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p));
-	u32 addr;
-	int ret;
-
-	ret = copy_in_user(p, argp, 2 * sizeof(int));
-	ret |= get_user(addr, &argp->red);
-	ret |= put_user(compat_ptr(addr), &p->red);
-	ret |= get_user(addr, &argp->green);
-	ret |= put_user(compat_ptr(addr), &p->green);
-	ret |= get_user(addr, &argp->blue);
-	ret |= put_user(compat_ptr(addr), &p->blue);
-	if (ret)
-		return -EFAULT;
-	return info->fbops->fb_ioctl(info,
-			(cmd == FBIOPUTCMAP32) ?
-			FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC,
-			(unsigned long)p);
-}
-
-static int fbiogscursor(struct fb_info *info, unsigned long arg)
-{
-	struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
-	struct fbcursor32 __user *argp =  (void __user *)arg;
-	compat_uptr_t addr;
-	int ret;
-
-	ret = copy_in_user(p, argp,
-			      2 * sizeof (short) + 2 * sizeof(struct fbcurpos));
-	ret |= copy_in_user(&p->size, &argp->size, sizeof(struct fbcurpos));
-	ret |= copy_in_user(&p->cmap, &argp->cmap, 2 * sizeof(int));
-	ret |= get_user(addr, &argp->cmap.red);
-	ret |= put_user(compat_ptr(addr), &p->cmap.red);
-	ret |= get_user(addr, &argp->cmap.green);
-	ret |= put_user(compat_ptr(addr), &p->cmap.green);
-	ret |= get_user(addr, &argp->cmap.blue);
-	ret |= put_user(compat_ptr(addr), &p->cmap.blue);
-	ret |= get_user(addr, &argp->mask);
-	ret |= put_user(compat_ptr(addr), &p->mask);
-	ret |= get_user(addr, &argp->image);
-	ret |= put_user(compat_ptr(addr), &p->image);
-	if (ret)
-		return -EFAULT;
-	return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p);
-}
-
-int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case FBIOGTYPE:
-	case FBIOSATTR:
-	case FBIOGATTR:
-	case FBIOSVIDEO:
-	case FBIOGVIDEO:
-	case FBIOGCURSOR32:	/* This is not implemented yet.
-				   Later it should be converted... */
-	case FBIOSCURPOS:
-	case FBIOGCURPOS:
-	case FBIOGCURMAX:
-		return info->fbops->fb_ioctl(info, cmd, arg);
-	case FBIOPUTCMAP32:
-		return fbiogetputcmap(info, cmd, arg);
-	case FBIOGETCMAP32:
-		return fbiogetputcmap(info, cmd, arg);
-	case FBIOSCURSOR32:
-		return fbiogscursor(info, arg);
-	default:
-		return -ENOIOCTLCMD;
-	}
-}
-EXPORT_SYMBOL(sbusfb_compat_ioctl);
-#endif
diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h
deleted file mode 100644
index 7ba3250236bd..000000000000
--- a/drivers/video/sbuslib.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* sbuslib.h: SBUS fb helper library interfaces */
-#ifndef _SBUSLIB_H
-#define _SBUSLIB_H
-
-struct sbus_mmap_map {
-	unsigned long voff;
-	unsigned long poff;
-	unsigned long size;
-};
-
-#define SBUS_MMAP_FBSIZE(n) (-n)
-#define SBUS_MMAP_EMPTY	0x80000000
-
-extern void sbusfb_fill_var(struct fb_var_screeninfo *var,
-			    struct device_node *dp, int bpp);
-struct vm_area_struct;
-extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
-			      unsigned long physbase, unsigned long fbsize,
-			      unsigned long iospace,
-			      struct vm_area_struct *vma);
-int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
-			struct fb_info *info,
-			int type, int fb_depth, unsigned long fb_size);
-int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd,
-			unsigned long arg);
-
-#endif /* _SBUSLIB_H */
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
deleted file mode 100644
index 1265b25f9f99..000000000000
--- a/drivers/video/sh7760fb.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * SH7760/SH7763 LCDC Framebuffer driver.
- *
- * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
- *             Manuel Lauss <mano@roarinelk.homelinux.net>
- * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
- *
- *  This file is subject to the terms and conditions of the GNU General
- *  Public License.  See the file COPYING in the main directory of this
- *  archive for more details.
- *
- * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt!
- *
- * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de>
- *     for his original source and testing!
- *
- * sh7760_setcolreg get from drivers/video/sh_mobile_lcdcfb.c
- */
-
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/fb.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <asm/sh7760fb.h>
-
-struct sh7760fb_par {
-	void __iomem *base;
-	int irq;
-
-	struct sh7760fb_platdata *pd;	/* display information */
-
-	dma_addr_t fbdma;	/* physical address */
-
-	int rot;		/* rotation enabled? */
-
-	u32 pseudo_palette[16];
-
-	struct platform_device *dev;
-	struct resource *ioarea;
-	struct completion vsync;	/* vsync irq event */
-};
-
-static irqreturn_t sh7760fb_irq(int irq, void *data)
-{
-	struct completion *c = data;
-
-	complete(c);
-
-	return IRQ_HANDLED;
-}
-
-/* wait_for_lps - wait until power supply has reached a certain state. */
-static int wait_for_lps(struct sh7760fb_par *par, int val)
-{
-	int i = 100;
-	while (--i && ((ioread16(par->base + LDPMMR) & 3) != val))
-		msleep(1);
-
-	if (i <= 0)
-		return -ETIMEDOUT;
-
-	return 0;
-}
-
-/* en/disable the LCDC */
-static int sh7760fb_blank(int blank, struct fb_info *info)
-{
-	struct sh7760fb_par *par = info->par;
-	struct sh7760fb_platdata *pd = par->pd;
-	unsigned short cntr = ioread16(par->base + LDCNTR);
-	unsigned short intr = ioread16(par->base + LDINTR);
-	int lps;
-
-	if (blank == FB_BLANK_UNBLANK) {
-		intr |= VINT_START;
-		cntr = LDCNTR_DON2 | LDCNTR_DON;
-		lps = 3;
-	} else {
-		intr &= ~VINT_START;
-		cntr = LDCNTR_DON2;
-		lps = 0;
-	}
-
-	if (pd->blank)
-		pd->blank(blank);
-
-	iowrite16(intr, par->base + LDINTR);
-	iowrite16(cntr, par->base + LDCNTR);
-
-	return wait_for_lps(par, lps);
-}
-
-static int sh7760_setcolreg (u_int regno,
-	u_int red, u_int green, u_int blue,
-	u_int transp, struct fb_info *info)
-{
-	u32 *palette = info->pseudo_palette;
-
-	if (regno >= 16)
-		return -EINVAL;
-
-	/* only FB_VISUAL_TRUECOLOR supported */
-
-	red >>= 16 - info->var.red.length;
-	green >>= 16 - info->var.green.length;
-	blue >>= 16 - info->var.blue.length;
-	transp >>= 16 - info->var.transp.length;
-
-	palette[regno] = (red << info->var.red.offset) |
-		(green << info->var.green.offset) |
-		(blue << info->var.blue.offset) |
-		(transp << info->var.transp.offset);
-
-	return 0;
-}
-
-static int sh7760fb_get_color_info(struct device *dev,
-				   u16 lddfr, int *bpp, int *gray)
-{
-	int lbpp, lgray;
-
-	lgray = lbpp = 0;
-
-	switch (lddfr & LDDFR_COLOR_MASK) {
-	case LDDFR_1BPP_MONO:
-		lgray = 1;
-		lbpp = 1;
-		break;
-	case LDDFR_2BPP_MONO:
-		lgray = 1;
-		lbpp = 2;
-		break;
-	case LDDFR_4BPP_MONO:
-		lgray = 1;
-	case LDDFR_4BPP:
-		lbpp = 4;
-		break;
-	case LDDFR_6BPP_MONO:
-		lgray = 1;
-	case LDDFR_8BPP:
-		lbpp = 8;
-		break;
-	case LDDFR_16BPP_RGB555:
-	case LDDFR_16BPP_RGB565:
-		lbpp = 16;
-		lgray = 0;
-		break;
-	default:
-		dev_dbg(dev, "unsupported LDDFR bit depth.\n");
-		return -EINVAL;
-	}
-
-	if (bpp)
-		*bpp = lbpp;
-	if (gray)
-		*gray = lgray;
-
-	return 0;
-}
-
-static int sh7760fb_check_var(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct fb_fix_screeninfo *fix = &info->fix;
-	struct sh7760fb_par *par = info->par;
-	int ret, bpp;
-
-	/* get color info from register value */
-	ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
-	if (ret)
-		return ret;
-
-	var->bits_per_pixel = bpp;
-
-	if ((var->grayscale) && (var->bits_per_pixel == 1))
-		fix->visual = FB_VISUAL_MONO10;
-	else if (var->bits_per_pixel >= 15)
-		fix->visual = FB_VISUAL_TRUECOLOR;
-	else
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-
-	/* TODO: add some more validation here */
-	return 0;
-}
-
-/*
- * sh7760fb_set_par - set videomode.
- *
- * NOTE: The rotation, grayscale and DSTN codepaths are
- *     totally untested!
- */
-static int sh7760fb_set_par(struct fb_info *info)
-{
-	struct sh7760fb_par *par = info->par;
-	struct fb_videomode *vm = par->pd->def_mode;
-	unsigned long sbase, dstn_off, ldsarl, stride;
-	unsigned short hsynp, hsynw, htcn, hdcn;
-	unsigned short vsynp, vsynw, vtln, vdln;
-	unsigned short lddfr, ldmtr;
-	int ret, bpp, gray;
-
-	par->rot = par->pd->rotate;
-
-	/* rotate only works with xres <= 320 */
-	if (par->rot && (vm->xres > 320)) {
-		dev_dbg(info->dev, "rotation disabled due to display size\n");
-		par->rot = 0;
-	}
-
-	/* calculate LCDC reg vals from display parameters */
-	hsynp = vm->right_margin + vm->xres;
-	hsynw = vm->hsync_len;
-	htcn = vm->left_margin + hsynp + hsynw;
-	hdcn = vm->xres;
-	vsynp = vm->lower_margin + vm->yres;
-	vsynw = vm->vsync_len;
-	vtln = vm->upper_margin + vsynp + vsynw;
-	vdln = vm->yres;
-
-	/* get color info from register value */
-	ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, &gray);
-	if (ret)
-		return ret;
-
-	dev_dbg(info->dev, "%dx%d %dbpp %s (orientation %s)\n", hdcn,
-		vdln, bpp, gray ? "grayscale" : "color",
-		par->rot ? "rotated" : "normal");
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-	lddfr = par->pd->lddfr | (1 << 8);
-#else
-	lddfr = par->pd->lddfr & ~(1 << 8);
-#endif
-
-	ldmtr = par->pd->ldmtr;
-
-	if (!(vm->sync & FB_SYNC_HOR_HIGH_ACT))
-		ldmtr |= LDMTR_CL1POL;
-	if (!(vm->sync & FB_SYNC_VERT_HIGH_ACT))
-		ldmtr |= LDMTR_FLMPOL;
-
-	/* shut down LCDC before changing display parameters */
-	sh7760fb_blank(FB_BLANK_POWERDOWN, info);
-
-	iowrite16(par->pd->ldickr, par->base + LDICKR);	/* pixclock */
-	iowrite16(ldmtr, par->base + LDMTR);	/* polarities */
-	iowrite16(lddfr, par->base + LDDFR);	/* color/depth */
-	iowrite16((par->rot ? 1 << 13 : 0), par->base + LDSMR);	/* rotate */
-	iowrite16(par->pd->ldpmmr, par->base + LDPMMR);	/* Power Management */
-	iowrite16(par->pd->ldpspr, par->base + LDPSPR);	/* Power Supply Ctrl */
-
-	/* display resolution */
-	iowrite16(((htcn >> 3) - 1) | (((hdcn >> 3) - 1) << 8),
-		  par->base + LDHCNR);
-	iowrite16(vdln - 1, par->base + LDVDLNR);
-	iowrite16(vtln - 1, par->base + LDVTLNR);
-	/* h/v sync signals */
-	iowrite16((vsynp - 1) | ((vsynw - 1) << 12), par->base + LDVSYNR);
-	iowrite16(((hsynp >> 3) - 1) | (((hsynw >> 3) - 1) << 12),
-		  par->base + LDHSYNR);
-	/* AC modulation sig */
-	iowrite16(par->pd->ldaclnr, par->base + LDACLNR);
-
-	stride = (par->rot) ? vtln : hdcn;
-	if (!gray)
-		stride *= (bpp + 7) >> 3;
-	else {
-		if (bpp == 1)
-			stride >>= 3;
-		else if (bpp == 2)
-			stride >>= 2;
-		else if (bpp == 4)
-			stride >>= 1;
-		/* 6 bpp == 8 bpp */
-	}
-
-	/* if rotated, stride must be power of 2 */
-	if (par->rot) {
-		unsigned long bit = 1 << 31;
-		while (bit) {
-			if (stride & bit)
-				break;
-			bit >>= 1;
-		}
-		if (stride & ~bit)
-			stride = bit << 1;	/* not P-o-2, round up */
-	}
-	iowrite16(stride, par->base + LDLAOR);
-
-	/* set display mem start address */
-	sbase = (unsigned long)par->fbdma;
-	if (par->rot)
-		sbase += (hdcn - 1) * stride;
-
-	iowrite32(sbase, par->base + LDSARU);
-
-	/*
-	 * for DSTN need to set address for lower half.
-	 * I (mlau) don't know which address to set it to,
-	 * so I guessed at (stride * yres/2).
-	 */
-	if (((ldmtr & 0x003f) >= LDMTR_DSTN_MONO_8) &&
-	    ((ldmtr & 0x003f) <= LDMTR_DSTN_COLOR_16)) {
-
-		dev_dbg(info->dev, " ***** DSTN untested! *****\n");
-
-		dstn_off = stride;
-		if (par->rot)
-			dstn_off *= hdcn >> 1;
-		else
-			dstn_off *= vdln >> 1;
-
-		ldsarl = sbase + dstn_off;
-	} else
-		ldsarl = 0;
-
-	iowrite32(ldsarl, par->base + LDSARL);	/* mem for lower half of DSTN */
-
-	info->fix.line_length = stride;
-
-	sh7760fb_check_var(&info->var, info);
-
-	sh7760fb_blank(FB_BLANK_UNBLANK, info);	/* panel on! */
-
-	dev_dbg(info->dev, "hdcn  : %6d htcn  : %6d\n", hdcn, htcn);
-	dev_dbg(info->dev, "hsynw : %6d hsynp : %6d\n", hsynw, hsynp);
-	dev_dbg(info->dev, "vdln  : %6d vtln  : %6d\n", vdln, vtln);
-	dev_dbg(info->dev, "vsynw : %6d vsynp : %6d\n", vsynw, vsynp);
-	dev_dbg(info->dev, "clksrc: %6d clkdiv: %6d\n",
-		(par->pd->ldickr >> 12) & 3, par->pd->ldickr & 0x1f);
-	dev_dbg(info->dev, "ldpmmr: 0x%04x ldpspr: 0x%04x\n", par->pd->ldpmmr,
-		par->pd->ldpspr);
-	dev_dbg(info->dev, "ldmtr : 0x%04x lddfr : 0x%04x\n", ldmtr, lddfr);
-	dev_dbg(info->dev, "ldlaor: %ld\n", stride);
-	dev_dbg(info->dev, "ldsaru: 0x%08lx ldsarl: 0x%08lx\n", sbase, ldsarl);
-
-	return 0;
-}
-
-static struct fb_ops sh7760fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_blank = sh7760fb_blank,
-	.fb_check_var = sh7760fb_check_var,
-	.fb_setcolreg = sh7760_setcolreg,
-	.fb_set_par = sh7760fb_set_par,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-};
-
-static void sh7760fb_free_mem(struct fb_info *info)
-{
-	struct sh7760fb_par *par = info->par;
-
-	if (!info->screen_base)
-		return;
-
-	dma_free_coherent(info->dev, info->screen_size,
-			  info->screen_base, par->fbdma);
-
-	par->fbdma = 0;
-	info->screen_base = NULL;
-	info->screen_size = 0;
-}
-
-/* allocate the framebuffer memory. This memory must be in Area3,
- * (dictated by the DMA engine) and contiguous, at a 512 byte boundary.
- */
-static int sh7760fb_alloc_mem(struct fb_info *info)
-{
-	struct sh7760fb_par *par = info->par;
-	void *fbmem;
-	unsigned long vram;
-	int ret, bpp;
-
-	if (info->screen_base)
-		return 0;
-
-	/* get color info from register value */
-	ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
-	if (ret) {
-		printk(KERN_ERR "colinfo\n");
-		return ret;
-	}
-
-	/* min VRAM: xres_min = 16, yres_min = 1, bpp = 1: 2byte -> 1 page
-	   max VRAM: xres_max = 1024, yres_max = 1024, bpp = 16: 2MB */
-
-	vram = info->var.xres * info->var.yres;
-	if (info->var.grayscale) {
-		if (bpp == 1)
-			vram >>= 3;
-		else if (bpp == 2)
-			vram >>= 2;
-		else if (bpp == 4)
-			vram >>= 1;
-	} else if (bpp > 8)
-		vram *= 2;
-	if ((vram < 1) || (vram > 1024 * 2048)) {
-		dev_dbg(info->dev, "too much VRAM required. Check settings\n");
-		return -ENODEV;
-	}
-
-	if (vram < PAGE_SIZE)
-		vram = PAGE_SIZE;
-
-	fbmem = dma_alloc_coherent(info->dev, vram, &par->fbdma, GFP_KERNEL);
-
-	if (!fbmem)
-		return -ENOMEM;
-
-	if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) {
-		sh7760fb_free_mem(info);
-		dev_err(info->dev, "kernel gave me memory at 0x%08lx, which is"
-			"unusable for the LCDC\n", (unsigned long)par->fbdma);
-		return -ENOMEM;
-	}
-
-	info->screen_base = fbmem;
-	info->screen_size = vram;
-	info->fix.smem_start = (unsigned long)info->screen_base;
-	info->fix.smem_len = info->screen_size;
-
-	return 0;
-}
-
-static int sh7760fb_probe(struct platform_device *pdev)
-{
-	struct fb_info *info;
-	struct resource *res;
-	struct sh7760fb_par *par;
-	int ret;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (unlikely(res == NULL)) {
-		dev_err(&pdev->dev, "invalid resource\n");
-		return -EINVAL;
-	}
-
-	info = framebuffer_alloc(sizeof(struct sh7760fb_par), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	par = info->par;
-	par->dev = pdev;
-
-	par->pd = pdev->dev.platform_data;
-	if (!par->pd) {
-		dev_dbg(info->dev, "no display setup data!\n");
-		ret = -ENODEV;
-		goto out_fb;
-	}
-
-	par->ioarea = request_mem_region(res->start,
-					 resource_size(res), pdev->name);
-	if (!par->ioarea) {
-		dev_err(&pdev->dev, "mmio area busy\n");
-		ret = -EBUSY;
-		goto out_fb;
-	}
-
-	par->base = ioremap_nocache(res->start, resource_size(res));
-	if (!par->base) {
-		dev_err(&pdev->dev, "cannot remap\n");
-		ret = -ENODEV;
-		goto out_res;
-	}
-
-	iowrite16(0, par->base + LDINTR);	/* disable vsync irq */
-	par->irq = platform_get_irq(pdev, 0);
-	if (par->irq >= 0) {
-		ret = request_irq(par->irq, sh7760fb_irq, 0,
-				  "sh7760-lcdc", &par->vsync);
-		if (ret) {
-			dev_err(&pdev->dev, "cannot grab IRQ\n");
-			par->irq = -ENXIO;
-		} else
-			disable_irq_nosync(par->irq);
-	}
-
-	fb_videomode_to_var(&info->var, par->pd->def_mode);
-
-	ret = sh7760fb_alloc_mem(info);
-	if (ret) {
-		dev_dbg(info->dev, "framebuffer memory allocation failed!\n");
-		goto out_unmap;
-	}
-
-	info->pseudo_palette = par->pseudo_palette;
-
-	/* fixup color register bitpositions. These are fixed by hardware */
-	info->var.red.offset = 11;
-	info->var.red.length = 5;
-	info->var.red.msb_right = 0;
-
-	info->var.green.offset = 5;
-	info->var.green.length = 6;
-	info->var.green.msb_right = 0;
-
-	info->var.blue.offset = 0;
-	info->var.blue.length = 5;
-	info->var.blue.msb_right = 0;
-
-	info->var.transp.offset = 0;
-	info->var.transp.length = 0;
-	info->var.transp.msb_right = 0;
-
-	strcpy(info->fix.id, "sh7760-lcdc");
-
-	/* set the DON2 bit now, before cmap allocation, as it will randomize
-	 * palette memory.
-	 */
-	iowrite16(LDCNTR_DON2, par->base + LDCNTR);
-	info->fbops = &sh7760fb_ops;
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret) {
-		dev_dbg(info->dev, "Unable to allocate cmap memory\n");
-		goto out_mem;
-	}
-
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		dev_dbg(info->dev, "cannot register fb!\n");
-		goto out_cmap;
-	}
-	platform_set_drvdata(pdev, info);
-
-	printk(KERN_INFO "%s: memory at phys 0x%08lx-0x%08lx, size %ld KiB\n",
-	       pdev->name,
-	       (unsigned long)par->fbdma,
-	       (unsigned long)(par->fbdma + info->screen_size - 1),
-	       info->screen_size >> 10);
-
-	return 0;
-
-out_cmap:
-	sh7760fb_blank(FB_BLANK_POWERDOWN, info);
-	fb_dealloc_cmap(&info->cmap);
-out_mem:
-	sh7760fb_free_mem(info);
-out_unmap:
-	if (par->irq >= 0)
-		free_irq(par->irq, &par->vsync);
-	iounmap(par->base);
-out_res:
-	release_mem_region(res->start, resource_size(res));
-out_fb:
-	framebuffer_release(info);
-	return ret;
-}
-
-static int sh7760fb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct sh7760fb_par *par = info->par;
-
-	sh7760fb_blank(FB_BLANK_POWERDOWN, info);
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-	sh7760fb_free_mem(info);
-	if (par->irq >= 0)
-		free_irq(par->irq, &par->vsync);
-	iounmap(par->base);
-	release_mem_region(par->ioarea->start, resource_size(par->ioarea));
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static struct platform_driver sh7760_lcdc_driver = {
-	.driver = {
-		   .name = "sh7760-lcdc",
-		   .owner = THIS_MODULE,
-		   },
-	.probe = sh7760fb_probe,
-	.remove = sh7760fb_remove,
-};
-
-module_platform_driver(sh7760_lcdc_driver);
-
-MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
-MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
deleted file mode 100644
index 8f6e8ff620d4..000000000000
--- a/drivers/video/sh_mipi_dsi.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Renesas SH-mobile MIPI DSI support
- *
- * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- */
-
-#include <linux/bitmap.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/module.h>
-
-#include <video/mipi_display.h>
-#include <video/sh_mipi_dsi.h>
-#include <video/sh_mobile_lcdc.h>
-
-#include "sh_mobile_lcdcfb.h"
-
-#define SYSCTRL		0x0000
-#define SYSCONF		0x0004
-#define TIMSET		0x0008
-#define RESREQSET0	0x0018
-#define RESREQSET1	0x001c
-#define HSTTOVSET	0x0020
-#define LPRTOVSET	0x0024
-#define TATOVSET	0x0028
-#define PRTOVSET	0x002c
-#define DSICTRL		0x0030
-#define DSIINTE		0x0060
-#define PHYCTRL		0x0070
-
-/* relative to linkbase */
-#define DTCTR		0x0000
-#define VMCTR1		0x0020
-#define VMCTR2		0x0024
-#define VMLEN1		0x0028
-#define VMLEN2		0x002c
-#define CMTSRTREQ	0x0070
-#define CMTSRTCTR	0x00d0
-
-/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
-#define MAX_SH_MIPI_DSI 2
-
-struct sh_mipi {
-	struct sh_mobile_lcdc_entity entity;
-
-	void __iomem	*base;
-	void __iomem	*linkbase;
-	struct clk	*dsit_clk;
-	struct platform_device *pdev;
-};
-
-#define to_sh_mipi(e)	container_of(e, struct sh_mipi, entity)
-
-static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
-
-/* Protect the above array */
-static DEFINE_MUTEX(array_lock);
-
-static struct sh_mipi *sh_mipi_by_handle(int handle)
-{
-	if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0)
-		return NULL;
-
-	return mipi_dsi[handle];
-}
-
-static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
-			      u8 cmd, u8 param)
-{
-	u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8);
-	int cnt = 100;
-
-	/* transmit a short packet to LCD panel */
-	iowrite32(1 | data, mipi->linkbase + CMTSRTCTR);
-	iowrite32(1, mipi->linkbase + CMTSRTREQ);
-
-	while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt)
-		udelay(1);
-
-	return cnt ? 0 : -ETIMEDOUT;
-}
-
-#define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
-				-EINVAL : (c) - 1)
-
-static int sh_mipi_dcs(int handle, u8 cmd)
-{
-	struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
-	if (!mipi)
-		return -ENODEV;
-	return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
-}
-
-static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
-{
-	struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
-	if (!mipi)
-		return -ENODEV;
-	return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd,
-				  param);
-}
-
-static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
-{
-	/*
-	 * enable LCDC data tx, transition to LPS after completion of each HS
-	 * packet
-	 */
-	iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR);
-}
-
-static void sh_mipi_shutdown(struct platform_device *pdev)
-{
-	struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
-
-	sh_mipi_dsi_enable(mipi, false);
-}
-
-static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode)
-{
-	void __iomem *base = mipi->base;
-	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
-	u32 pctype, datatype, pixfmt, linelength, vmctr2;
-	u32 tmp, top, bottom, delay, div;
-	int bpp;
-
-	/*
-	 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
-	 * the default videomode. If this ever becomes a problem, We'll have to
-	 * move this to mipi_display_on() above and use info->var.xres
-	 */
-	switch (pdata->data_format) {
-	case MIPI_RGB888:
-		pctype = 0;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
-		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = mode->xres * 3;
-		break;
-	case MIPI_RGB565:
-		pctype = 1;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
-		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = mode->xres * 2;
-		break;
-	case MIPI_RGB666_LP:
-		pctype = 2;
-		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
-		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = mode->xres * 3;
-		break;
-	case MIPI_RGB666:
-		pctype = 3;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
-		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
-		linelength = (mode->xres * 18 + 7) / 8;
-		break;
-	case MIPI_BGR888:
-		pctype = 8;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
-		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = mode->xres * 3;
-		break;
-	case MIPI_BGR565:
-		pctype = 9;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
-		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = mode->xres * 2;
-		break;
-	case MIPI_BGR666_LP:
-		pctype = 0xa;
-		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
-		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = mode->xres * 3;
-		break;
-	case MIPI_BGR666:
-		pctype = 0xb;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
-		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
-		linelength = (mode->xres * 18 + 7) / 8;
-		break;
-	case MIPI_YUYV:
-		pctype = 4;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
-		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = mode->xres * 2;
-		break;
-	case MIPI_UYVY:
-		pctype = 5;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
-		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = mode->xres * 2;
-		break;
-	case MIPI_YUV420_L:
-		pctype = 6;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
-		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
-		linelength = (mode->xres * 12 + 7) / 8;
-		break;
-	case MIPI_YUV420:
-		pctype = 7;
-		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
-		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
-		/* Length of U/V line */
-		linelength = (mode->xres + 1) / 2;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (!pdata->lane)
-		return -EINVAL;
-
-	/* reset DSI link */
-	iowrite32(0x00000001, base + SYSCTRL);
-	/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
-	udelay(50);
-	iowrite32(0x00000000, base + SYSCTRL);
-
-	/* setup DSI link */
-
-	/*
-	 * T_wakeup = 0x7000
-	 * T_hs-trail = 3
-	 * T_hs-prepare = 3
-	 * T_clk-trail = 3
-	 * T_clk-prepare = 2
-	 */
-	iowrite32(0x70003332, base + TIMSET);
-	/* no responses requested */
-	iowrite32(0x00000000, base + RESREQSET0);
-	/* request response to packets of type 0x28 */
-	iowrite32(0x00000100, base + RESREQSET1);
-	/* High-speed transmission timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + HSTTOVSET);
-	/* LP reception timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + LPRTOVSET);
-	/* Turn-around timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + TATOVSET);
-	/* Peripheral reset timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + PRTOVSET);
-	/* Interrupts not used, disable all */
-	iowrite32(0, base + DSIINTE);
-	/* DSI-Tx bias on */
-	iowrite32(0x00000001, base + PHYCTRL);
-	udelay(200);
-	/* Deassert resets, power on */
-	iowrite32(0x03070001 | pdata->phyctrl, base + PHYCTRL);
-
-	/*
-	 * Default = ULPS enable |
-	 *	Contention detection enabled |
-	 *	EoT packet transmission enable |
-	 *	CRC check enable |
-	 *	ECC check enable
-	 */
-	bitmap_fill((unsigned long *)&tmp, pdata->lane);
-	tmp |= 0x00003700;
-	iowrite32(tmp, base + SYSCONF);
-
-	/* setup l-bridge */
-
-	/*
-	 * Enable transmission of all packets,
-	 * transmit LPS after each HS packet completion
-	 */
-	iowrite32(0x00000006, mipi->linkbase + DTCTR);
-	/* VSYNC width = 2 (<< 17) */
-	iowrite32((mode->vsync_len << pdata->vsynw_offset) |
-		  (pdata->clksrc << 16) | (pctype << 12) | datatype,
-		  mipi->linkbase + VMCTR1);
-
-	/*
-	 * Non-burst mode with sync pulses: VSE and HSE are output,
-	 * HSA period allowed, no commands in LP
-	 */
-	vmctr2 = 0;
-	if (pdata->flags & SH_MIPI_DSI_VSEE)
-		vmctr2 |= 1 << 23;
-	if (pdata->flags & SH_MIPI_DSI_HSEE)
-		vmctr2 |= 1 << 22;
-	if (pdata->flags & SH_MIPI_DSI_HSAE)
-		vmctr2 |= 1 << 21;
-	if (pdata->flags & SH_MIPI_DSI_BL2E)
-		vmctr2 |= 1 << 17;
-	if (pdata->flags & SH_MIPI_DSI_HSABM)
-		vmctr2 |= 1 << 5;
-	if (pdata->flags & SH_MIPI_DSI_HBPBM)
-		vmctr2 |= 1 << 4;
-	if (pdata->flags & SH_MIPI_DSI_HFPBM)
-		vmctr2 |= 1 << 3;
-	iowrite32(vmctr2, mipi->linkbase + VMCTR2);
-
-	/*
-	 * VMLEN1 = RGBLEN | HSALEN
-	 *
-	 * see
-	 *  Video mode - Blanking Packet setting
-	 */
-	top = linelength << 16; /* RGBLEN */
-	bottom = 0x00000001;
-	if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
-		bottom = (pdata->lane * mode->hsync_len) - 10;
-	iowrite32(top | bottom , mipi->linkbase + VMLEN1);
-
-	/*
-	 * VMLEN2 = HBPLEN | HFPLEN
-	 *
-	 * see
-	 *  Video mode - Blanking Packet setting
-	 */
-	top	= 0x00010000;
-	bottom	= 0x00000001;
-	delay	= 0;
-
-	div = 1;	/* HSbyteCLK is calculation base
-			 * HS4divCLK = HSbyteCLK/2
-			 * HS6divCLK is not supported for now */
-	if (pdata->flags & SH_MIPI_DSI_HS4divCLK)
-		div = 2;
-
-	if (pdata->flags & SH_MIPI_DSI_HFPBM) {	/* HBPLEN */
-		top = mode->hsync_len + mode->left_margin;
-		top = ((pdata->lane * top / div) - 10) << 16;
-	}
-	if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
-		bottom = mode->right_margin;
-		bottom = (pdata->lane * bottom / div) - 12;
-	}
-
-	bpp = linelength / mode->xres; /* byte / pixel */
-	if ((pdata->lane / div) > bpp) {
-		tmp = mode->xres / bpp; /* output cycle */
-		tmp = mode->xres - tmp; /* (input - output) cycle */
-		delay = (pdata->lane * tmp);
-	}
-
-	iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2);
-
-	msleep(5);
-
-	/* setup LCD panel */
-
-	/* cf. drivers/video/omap/lcd_mipid.c */
-	sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE);
-	msleep(120);
-	/*
-	 * [7] - Page Address Mode
-	 * [6] - Column Address Mode
-	 * [5] - Page / Column Address Mode
-	 * [4] - Display Device Line Refresh Order
-	 * [3] - RGB/BGR Order
-	 * [2] - Display Data Latch Data Order
-	 * [1] - Flip Horizontal
-	 * [0] - Flip Vertical
-	 */
-	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
-	/* cf. set_data_lines() */
-	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT,
-			  pixfmt << 4);
-	sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON);
-
-	/* Enable timeout counters */
-	iowrite32(0x00000f00, base + DSICTRL);
-
-	return 0;
-}
-
-static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
-{
-	struct sh_mipi *mipi = to_sh_mipi(entity);
-	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
-	int ret;
-
-	pm_runtime_get_sync(&mipi->pdev->dev);
-
-	ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1);
-	if (ret < 0)
-		goto mipi_display_on_fail1;
-
-	ret = sh_mipi_setup(mipi, &entity->def_mode);
-	if (ret < 0)
-		goto mipi_display_on_fail2;
-
-	sh_mipi_dsi_enable(mipi, true);
-
-	return SH_MOBILE_LCDC_DISPLAY_CONNECTED;
-
-mipi_display_on_fail1:
-	pm_runtime_put_sync(&mipi->pdev->dev);
-mipi_display_on_fail2:
-	pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
-
-	return ret;
-}
-
-static void mipi_display_off(struct sh_mobile_lcdc_entity *entity)
-{
-	struct sh_mipi *mipi = to_sh_mipi(entity);
-	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
-
-	sh_mipi_dsi_enable(mipi, false);
-
-	pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
-
-	pm_runtime_put_sync(&mipi->pdev->dev);
-}
-
-static const struct sh_mobile_lcdc_entity_ops mipi_ops = {
-	.display_on = mipi_display_on,
-	.display_off = mipi_display_off,
-};
-
-static int __init sh_mipi_probe(struct platform_device *pdev)
-{
-	struct sh_mipi *mipi;
-	struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	unsigned long rate, f_current;
-	int idx = pdev->id, ret;
-
-	if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
-		return -ENODEV;
-
-	if (!pdata->set_dot_clock)
-		return -EINVAL;
-
-	mutex_lock(&array_lock);
-	if (idx < 0)
-		for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
-			;
-
-	if (idx == ARRAY_SIZE(mipi_dsi)) {
-		ret = -EBUSY;
-		goto efindslot;
-	}
-
-	mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
-	if (!mipi) {
-		ret = -ENOMEM;
-		goto ealloc;
-	}
-
-	mipi->entity.owner = THIS_MODULE;
-	mipi->entity.ops = &mipi_ops;
-
-	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "MIPI register region already claimed\n");
-		ret = -EBUSY;
-		goto ereqreg;
-	}
-
-	mipi->base = ioremap(res->start, resource_size(res));
-	if (!mipi->base) {
-		ret = -ENOMEM;
-		goto emap;
-	}
-
-	if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) {
-		dev_err(&pdev->dev, "MIPI register region 2 already claimed\n");
-		ret = -EBUSY;
-		goto ereqreg2;
-	}
-
-	mipi->linkbase = ioremap(res2->start, resource_size(res2));
-	if (!mipi->linkbase) {
-		ret = -ENOMEM;
-		goto emap2;
-	}
-
-	mipi->pdev = pdev;
-
-	mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
-	if (IS_ERR(mipi->dsit_clk)) {
-		ret = PTR_ERR(mipi->dsit_clk);
-		goto eclktget;
-	}
-
-	f_current = clk_get_rate(mipi->dsit_clk);
-	/* 80MHz required by the datasheet */
-	rate = clk_round_rate(mipi->dsit_clk, 80000000);
-	if (rate > 0 && rate != f_current)
-		ret = clk_set_rate(mipi->dsit_clk, rate);
-	else
-		ret = rate;
-	if (ret < 0)
-		goto esettrate;
-
-	dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
-
-	ret = clk_enable(mipi->dsit_clk);
-	if (ret < 0)
-		goto eclkton;
-
-	mipi_dsi[idx] = mipi;
-
-	pm_runtime_enable(&pdev->dev);
-	pm_runtime_resume(&pdev->dev);
-
-	mutex_unlock(&array_lock);
-	platform_set_drvdata(pdev, &mipi->entity);
-
-	return 0;
-
-eclkton:
-esettrate:
-	clk_put(mipi->dsit_clk);
-eclktget:
-	iounmap(mipi->linkbase);
-emap2:
-	release_mem_region(res2->start, resource_size(res2));
-ereqreg2:
-	iounmap(mipi->base);
-emap:
-	release_mem_region(res->start, resource_size(res));
-ereqreg:
-	kfree(mipi);
-ealloc:
-efindslot:
-	mutex_unlock(&array_lock);
-
-	return ret;
-}
-
-static int sh_mipi_remove(struct platform_device *pdev)
-{
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
-	int i, ret;
-
-	mutex_lock(&array_lock);
-
-	for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++)
-		;
-
-	if (i == ARRAY_SIZE(mipi_dsi)) {
-		ret = -EINVAL;
-	} else {
-		ret = 0;
-		mipi_dsi[i] = NULL;
-	}
-
-	mutex_unlock(&array_lock);
-
-	if (ret < 0)
-		return ret;
-
-	pm_runtime_disable(&pdev->dev);
-	clk_disable(mipi->dsit_clk);
-	clk_put(mipi->dsit_clk);
-
-	iounmap(mipi->linkbase);
-	if (res2)
-		release_mem_region(res2->start, resource_size(res2));
-	iounmap(mipi->base);
-	if (res)
-		release_mem_region(res->start, resource_size(res));
-	kfree(mipi);
-
-	return 0;
-}
-
-static struct platform_driver sh_mipi_driver = {
-	.remove		= sh_mipi_remove,
-	.shutdown	= sh_mipi_shutdown,
-	.driver = {
-		.name	= "sh-mipi-dsi",
-	},
-};
-
-module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe);
-
-MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
-MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
deleted file mode 100644
index 9a33ee0413fb..000000000000
--- a/drivers/video/sh_mobile_hdmi.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/*
- * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
- * for SLISHDMI13T and SLIPHDMIT IP cores
- *
- * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/initval.h>
-
-#include <video/sh_mobile_hdmi.h>
-#include <video/sh_mobile_lcdc.h>
-
-#include "sh_mobile_lcdcfb.h"
-
-/* HDMI Core Control Register (HTOP0) */
-#define HDMI_SYSTEM_CTRL			0x00 /* System control */
-#define HDMI_L_R_DATA_SWAP_CTRL_RPKT		0x01 /* L/R data swap control,
-							bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
-#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8	0x02 /* bits 15..8 of 20-bit N for Audio Clock Regeneration packet */
-#define HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0	0x03 /* bits 7..0 of 20-bit N for Audio Clock Regeneration packet */
-#define HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS		0x04 /* SPDIF audio sampling frequency,
-							bits 19..16 of Internal CTS */
-#define HDMI_INTERNAL_CTS_15_8			0x05 /* bits 15..8 of Internal CTS */
-#define HDMI_INTERNAL_CTS_7_0			0x06 /* bits 7..0 of Internal CTS */
-#define HDMI_EXTERNAL_CTS_19_16			0x07 /* External CTS */
-#define HDMI_EXTERNAL_CTS_15_8			0x08 /* External CTS */
-#define HDMI_EXTERNAL_CTS_7_0			0x09 /* External CTS */
-#define HDMI_AUDIO_SETTING_1			0x0A /* Audio setting.1 */
-#define HDMI_AUDIO_SETTING_2			0x0B /* Audio setting.2 */
-#define HDMI_I2S_AUDIO_SET			0x0C /* I2S audio setting */
-#define HDMI_DSD_AUDIO_SET			0x0D /* DSD audio setting */
-#define HDMI_DEBUG_MONITOR_1			0x0E /* Debug monitor.1 */
-#define HDMI_DEBUG_MONITOR_2			0x0F /* Debug monitor.2 */
-#define HDMI_I2S_INPUT_PIN_SWAP			0x10 /* I2S input pin swap */
-#define HDMI_AUDIO_STATUS_BITS_SETTING_1	0x11 /* Audio status bits setting.1 */
-#define HDMI_AUDIO_STATUS_BITS_SETTING_2	0x12 /* Audio status bits setting.2 */
-#define HDMI_CATEGORY_CODE			0x13 /* Category code */
-#define HDMI_SOURCE_NUM_AUDIO_WORD_LEN		0x14 /* Source number/Audio word length */
-#define HDMI_AUDIO_VIDEO_SETTING_1		0x15 /* Audio/Video setting.1 */
-#define HDMI_VIDEO_SETTING_1			0x16 /* Video setting.1 */
-#define HDMI_DEEP_COLOR_MODES			0x17 /* Deep Color Modes */
-
-/* 12 16- and 10-bit Color space conversion parameters: 0x18..0x2f */
-#define HDMI_COLOR_SPACE_CONVERSION_PARAMETERS	0x18
-
-#define HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS	0x30 /* External video parameter settings */
-#define HDMI_EXTERNAL_H_TOTAL_7_0		0x31 /* External horizontal total (LSB) */
-#define HDMI_EXTERNAL_H_TOTAL_11_8		0x32 /* External horizontal total (MSB) */
-#define HDMI_EXTERNAL_H_BLANK_7_0		0x33 /* External horizontal blank (LSB) */
-#define HDMI_EXTERNAL_H_BLANK_9_8		0x34 /* External horizontal blank (MSB) */
-#define HDMI_EXTERNAL_H_DELAY_7_0		0x35 /* External horizontal delay (LSB) */
-#define HDMI_EXTERNAL_H_DELAY_9_8		0x36 /* External horizontal delay (MSB) */
-#define HDMI_EXTERNAL_H_DURATION_7_0		0x37 /* External horizontal duration (LSB) */
-#define HDMI_EXTERNAL_H_DURATION_9_8		0x38 /* External horizontal duration (MSB) */
-#define HDMI_EXTERNAL_V_TOTAL_7_0		0x39 /* External vertical total (LSB) */
-#define HDMI_EXTERNAL_V_TOTAL_9_8		0x3A /* External vertical total (MSB) */
-#define HDMI_AUDIO_VIDEO_SETTING_2		0x3B /* Audio/Video setting.2 */
-#define HDMI_EXTERNAL_V_BLANK			0x3D /* External vertical blank */
-#define HDMI_EXTERNAL_V_DELAY			0x3E /* External vertical delay */
-#define HDMI_EXTERNAL_V_DURATION		0x3F /* External vertical duration */
-#define HDMI_CTRL_PKT_MANUAL_SEND_CONTROL	0x40 /* Control packet manual send control */
-#define HDMI_CTRL_PKT_AUTO_SEND			0x41 /* Control packet auto send with VSYNC control */
-#define HDMI_AUTO_CHECKSUM_OPTION		0x42 /* Auto checksum option */
-#define HDMI_VIDEO_SETTING_2			0x45 /* Video setting.2 */
-#define HDMI_OUTPUT_OPTION			0x46 /* Output option */
-#define HDMI_SLIPHDMIT_PARAM_OPTION		0x51 /* SLIPHDMIT parameter option */
-#define HDMI_HSYNC_PMENT_AT_EMB_7_0		0x52 /* HSYNC placement at embedded sync (LSB) */
-#define HDMI_HSYNC_PMENT_AT_EMB_15_8		0x53 /* HSYNC placement at embedded sync (MSB) */
-#define HDMI_VSYNC_PMENT_AT_EMB_7_0		0x54 /* VSYNC placement at embedded sync (LSB) */
-#define HDMI_VSYNC_PMENT_AT_EMB_14_8		0x55 /* VSYNC placement at embedded sync (MSB) */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_1		0x56 /* SLIPHDMIT parameter settings.1 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_2		0x57 /* SLIPHDMIT parameter settings.2 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_3		0x58 /* SLIPHDMIT parameter settings.3 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_5		0x59 /* SLIPHDMIT parameter settings.5 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_6		0x5A /* SLIPHDMIT parameter settings.6 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_7		0x5B /* SLIPHDMIT parameter settings.7 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_8		0x5C /* SLIPHDMIT parameter settings.8 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_9		0x5D /* SLIPHDMIT parameter settings.9 */
-#define HDMI_SLIPHDMIT_PARAM_SETTINGS_10	0x5E /* SLIPHDMIT parameter settings.10 */
-#define HDMI_CTRL_PKT_BUF_INDEX			0x5F /* Control packet buffer index */
-#define HDMI_CTRL_PKT_BUF_ACCESS_HB0		0x60 /* Control packet data buffer access window - HB0 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_HB1		0x61 /* Control packet data buffer access window - HB1 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_HB2		0x62 /* Control packet data buffer access window - HB2 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB0		0x63 /* Control packet data buffer access window - PB0 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB1		0x64 /* Control packet data buffer access window - PB1 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB2		0x65 /* Control packet data buffer access window - PB2 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB3		0x66 /* Control packet data buffer access window - PB3 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB4		0x67 /* Control packet data buffer access window - PB4 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB5		0x68 /* Control packet data buffer access window - PB5 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB6		0x69 /* Control packet data buffer access window - PB6 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB7		0x6A /* Control packet data buffer access window - PB7 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB8		0x6B /* Control packet data buffer access window - PB8 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB9		0x6C /* Control packet data buffer access window - PB9 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB10		0x6D /* Control packet data buffer access window - PB10 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB11		0x6E /* Control packet data buffer access window - PB11 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB12		0x6F /* Control packet data buffer access window - PB12 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB13		0x70 /* Control packet data buffer access window - PB13 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB14		0x71 /* Control packet data buffer access window - PB14 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB15		0x72 /* Control packet data buffer access window - PB15 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB16		0x73 /* Control packet data buffer access window - PB16 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB17		0x74 /* Control packet data buffer access window - PB17 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB18		0x75 /* Control packet data buffer access window - PB18 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB19		0x76 /* Control packet data buffer access window - PB19 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB20		0x77 /* Control packet data buffer access window - PB20 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB21		0x78 /* Control packet data buffer access window - PB21 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB22		0x79 /* Control packet data buffer access window - PB22 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB23		0x7A /* Control packet data buffer access window - PB23 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB24		0x7B /* Control packet data buffer access window - PB24 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB25		0x7C /* Control packet data buffer access window - PB25 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB26		0x7D /* Control packet data buffer access window - PB26 */
-#define HDMI_CTRL_PKT_BUF_ACCESS_PB27		0x7E /* Control packet data buffer access window - PB27 */
-#define HDMI_EDID_KSV_FIFO_ACCESS_WINDOW	0x80 /* EDID/KSV FIFO access window */
-#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_7_0	0x81 /* DDC bus access frequency control (LSB) */
-#define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_15_8	0x82 /* DDC bus access frequency control (MSB) */
-#define HDMI_INTERRUPT_MASK_1			0x92 /* Interrupt mask.1 */
-#define HDMI_INTERRUPT_MASK_2			0x93 /* Interrupt mask.2 */
-#define HDMI_INTERRUPT_STATUS_1			0x94 /* Interrupt status.1 */
-#define HDMI_INTERRUPT_STATUS_2			0x95 /* Interrupt status.2 */
-#define HDMI_INTERRUPT_MASK_3			0x96 /* Interrupt mask.3 */
-#define HDMI_INTERRUPT_MASK_4			0x97 /* Interrupt mask.4 */
-#define HDMI_INTERRUPT_STATUS_3			0x98 /* Interrupt status.3 */
-#define HDMI_INTERRUPT_STATUS_4			0x99 /* Interrupt status.4 */
-#define HDMI_SOFTWARE_HDCP_CONTROL_1		0x9A /* Software HDCP control.1 */
-#define HDMI_FRAME_COUNTER			0x9C /* Frame counter */
-#define HDMI_FRAME_COUNTER_FOR_RI_CHECK		0x9D /* Frame counter for Ri check */
-#define HDMI_HDCP_CONTROL			0xAF /* HDCP control */
-#define HDMI_RI_FRAME_COUNT_REGISTER		0xB2 /* Ri frame count register */
-#define HDMI_DDC_BUS_CONTROL			0xB7 /* DDC bus control */
-#define HDMI_HDCP_STATUS			0xB8 /* HDCP status */
-#define HDMI_SHA0				0xB9 /* sha0 */
-#define HDMI_SHA1				0xBA /* sha1 */
-#define HDMI_SHA2				0xBB /* sha2 */
-#define HDMI_SHA3				0xBC /* sha3 */
-#define HDMI_SHA4				0xBD /* sha4 */
-#define HDMI_BCAPS_READ				0xBE /* BCAPS read / debug */
-#define HDMI_AKSV_BKSV_7_0_MONITOR		0xBF /* AKSV/BKSV[7:0] monitor */
-#define HDMI_AKSV_BKSV_15_8_MONITOR		0xC0 /* AKSV/BKSV[15:8] monitor */
-#define HDMI_AKSV_BKSV_23_16_MONITOR		0xC1 /* AKSV/BKSV[23:16] monitor */
-#define HDMI_AKSV_BKSV_31_24_MONITOR		0xC2 /* AKSV/BKSV[31:24] monitor */
-#define HDMI_AKSV_BKSV_39_32_MONITOR		0xC3 /* AKSV/BKSV[39:32] monitor */
-#define HDMI_EDID_SEGMENT_POINTER		0xC4 /* EDID segment pointer */
-#define HDMI_EDID_WORD_ADDRESS			0xC5 /* EDID word address */
-#define HDMI_EDID_DATA_FIFO_ADDRESS		0xC6 /* EDID data FIFO address */
-#define HDMI_NUM_OF_HDMI_DEVICES		0xC7 /* Number of HDMI devices */
-#define HDMI_HDCP_ERROR_CODE			0xC8 /* HDCP error code */
-#define HDMI_100MS_TIMER_SET			0xC9 /* 100ms timer setting */
-#define HDMI_5SEC_TIMER_SET			0xCA /* 5sec timer setting */
-#define HDMI_RI_READ_COUNT			0xCB /* Ri read count */
-#define HDMI_AN_SEED				0xCC /* An seed */
-#define HDMI_MAX_NUM_OF_RCIVRS_ALLOWED		0xCD /* Maximum number of receivers allowed */
-#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_1	0xCE /* HDCP memory access control.1 */
-#define HDMI_HDCP_MEMORY_ACCESS_CONTROL_2	0xCF /* HDCP memory access control.2 */
-#define HDMI_HDCP_CONTROL_2			0xD0 /* HDCP Control 2 */
-#define HDMI_HDCP_KEY_MEMORY_CONTROL		0xD2 /* HDCP Key Memory Control */
-#define HDMI_COLOR_SPACE_CONV_CONFIG_1		0xD3 /* Color space conversion configuration.1 */
-#define HDMI_VIDEO_SETTING_3			0xD4 /* Video setting.3 */
-#define HDMI_RI_7_0				0xD5 /* Ri[7:0] */
-#define HDMI_RI_15_8				0xD6 /* Ri[15:8] */
-#define HDMI_PJ					0xD7 /* Pj */
-#define HDMI_SHA_RD				0xD8 /* sha_rd */
-#define HDMI_RI_7_0_SAVED			0xD9 /* Ri[7:0] saved */
-#define HDMI_RI_15_8_SAVED			0xDA /* Ri[15:8] saved */
-#define HDMI_PJ_SAVED				0xDB /* Pj saved */
-#define HDMI_NUM_OF_DEVICES			0xDC /* Number of devices */
-#define HDMI_HOT_PLUG_MSENS_STATUS		0xDF /* Hot plug/MSENS status */
-#define HDMI_BCAPS_WRITE			0xE0 /* bcaps */
-#define HDMI_BSTAT_7_0				0xE1 /* bstat[7:0] */
-#define HDMI_BSTAT_15_8				0xE2 /* bstat[15:8] */
-#define HDMI_BKSV_7_0				0xE3 /* bksv[7:0] */
-#define HDMI_BKSV_15_8				0xE4 /* bksv[15:8] */
-#define HDMI_BKSV_23_16				0xE5 /* bksv[23:16] */
-#define HDMI_BKSV_31_24				0xE6 /* bksv[31:24] */
-#define HDMI_BKSV_39_32				0xE7 /* bksv[39:32] */
-#define HDMI_AN_7_0				0xE8 /* An[7:0] */
-#define HDMI_AN_15_8				0xE9 /* An [15:8] */
-#define HDMI_AN_23_16				0xEA /* An [23:16] */
-#define HDMI_AN_31_24				0xEB /* An [31:24] */
-#define HDMI_AN_39_32				0xEC /* An [39:32] */
-#define HDMI_AN_47_40				0xED /* An [47:40] */
-#define HDMI_AN_55_48				0xEE /* An [55:48] */
-#define HDMI_AN_63_56				0xEF /* An [63:56] */
-#define HDMI_PRODUCT_ID				0xF0 /* Product ID */
-#define HDMI_REVISION_ID			0xF1 /* Revision ID */
-#define HDMI_TEST_MODE				0xFE /* Test mode */
-
-/* HDMI Control Register (HTOP1) */
-#define HDMI_HTOP1_TEST_MODE			0x0000 /* Test mode */
-#define HDMI_HTOP1_VIDEO_INPUT			0x0008 /* VideoInput */
-#define HDMI_HTOP1_CORE_RSTN			0x000C /* CoreResetn */
-#define HDMI_HTOP1_PLLBW			0x0018 /* PLLBW */
-#define HDMI_HTOP1_CLK_TO_PHY			0x001C /* Clk to Phy */
-#define HDMI_HTOP1_VIDEO_INPUT2			0x0020 /* VideoInput2 */
-#define HDMI_HTOP1_TISEMP0_1			0x0024 /* tisemp0-1 */
-#define HDMI_HTOP1_TISEMP2_C			0x0028 /* tisemp2-c */
-#define HDMI_HTOP1_TISIDRV			0x002C /* tisidrv */
-#define HDMI_HTOP1_TISEN			0x0034 /* tisen */
-#define HDMI_HTOP1_TISDREN			0x0038 /* tisdren  */
-#define HDMI_HTOP1_CISRANGE			0x003C /* cisrange  */
-#define HDMI_HTOP1_ENABLE_SELECTOR		0x0040 /* Enable Selector */
-#define HDMI_HTOP1_MACRO_RESET			0x0044 /* Macro reset */
-#define HDMI_HTOP1_PLL_CALIBRATION		0x0048 /* PLL calibration */
-#define HDMI_HTOP1_RE_CALIBRATION		0x004C /* Re-calibration */
-#define HDMI_HTOP1_CURRENT			0x0050 /* Current */
-#define HDMI_HTOP1_PLL_LOCK_DETECT		0x0054 /* PLL lock detect */
-#define HDMI_HTOP1_PHY_TEST_MODE		0x0058 /* PHY Test Mode */
-#define HDMI_HTOP1_CLK_SET			0x0080 /* Clock Set */
-#define HDMI_HTOP1_DDC_FAIL_SAFE		0x0084 /* DDC fail safe */
-#define HDMI_HTOP1_PRBS				0x0088 /* PRBS */
-#define HDMI_HTOP1_EDID_AINC_CONTROL		0x008C /* EDID ainc Control */
-#define HDMI_HTOP1_HTOP_DCL_MODE		0x00FC /* Deep Coloer Mode */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0		0x0100 /* Deep Color:FRC COEF0 */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1		0x0104 /* Deep Color:FRC COEF1 */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2		0x0108 /* Deep Color:FRC COEF2 */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3		0x010C /* Deep Color:FRC COEF3 */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C		0x0110 /* Deep Color:FRC COEF0C */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C		0x0114 /* Deep Color:FRC COEF1C */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C		0x0118 /* Deep Color:FRC COEF2C */
-#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C		0x011C /* Deep Color:FRC COEF3C */
-#define HDMI_HTOP1_HTOP_DCL_FRC_MODE		0x0120 /* Deep Color:FRC Mode */
-#define HDMI_HTOP1_HTOP_DCL_RECT_START1		0x0124 /* Deep Color:Rect Start1 */
-#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1		0x0128 /* Deep Color:Rect Size1 */
-#define HDMI_HTOP1_HTOP_DCL_RECT_START2		0x012C /* Deep Color:Rect Start2 */
-#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2		0x0130 /* Deep Color:Rect Size2 */
-#define HDMI_HTOP1_HTOP_DCL_RECT_START3		0x0134 /* Deep Color:Rect Start3 */
-#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3		0x0138 /* Deep Color:Rect Size3 */
-#define HDMI_HTOP1_HTOP_DCL_RECT_START4		0x013C /* Deep Color:Rect Start4 */
-#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4		0x0140 /* Deep Color:Rect Size4 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1	0x0144 /* Deep Color:Fil Para Y1_1 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2	0x0148 /* Deep Color:Fil Para Y1_2 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1	0x014C /* Deep Color:Fil Para CB1_1 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2	0x0150 /* Deep Color:Fil Para CB1_2 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1	0x0154 /* Deep Color:Fil Para CR1_1 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2	0x0158 /* Deep Color:Fil Para CR1_2 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1	0x015C /* Deep Color:Fil Para Y2_1 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2	0x0160 /* Deep Color:Fil Para Y2_2 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1	0x0164 /* Deep Color:Fil Para CB2_1 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2	0x0168 /* Deep Color:Fil Para CB2_2 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1	0x016C /* Deep Color:Fil Para CR2_1 */
-#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2	0x0170 /* Deep Color:Fil Para CR2_2 */
-#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1		0x0174 /* Deep Color:Cor Para Y1 */
-#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1	0x0178 /* Deep Color:Cor Para CB1 */
-#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1	0x017C /* Deep Color:Cor Para CR1 */
-#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2		0x0180 /* Deep Color:Cor Para Y2 */
-#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2	0x0184 /* Deep Color:Cor Para CB2 */
-#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2	0x0188 /* Deep Color:Cor Para CR2 */
-#define HDMI_HTOP1_EDID_DATA_READ		0x0200 /* EDID Data Read 128Byte:0x03FC */
-
-enum hotplug_state {
-	HDMI_HOTPLUG_DISCONNECTED,
-	HDMI_HOTPLUG_CONNECTED,
-	HDMI_HOTPLUG_EDID_DONE,
-};
-
-struct sh_hdmi {
-	struct sh_mobile_lcdc_entity entity;
-
-	void __iomem *base;
-	void __iomem *htop1;
-	enum hotplug_state hp_state;	/* hot-plug status */
-	u8 preprogrammed_vic;		/* use a pre-programmed VIC or
-					   the external mode */
-	u8 edid_block_addr;
-	u8 edid_segment_nr;
-	u8 edid_blocks;
-	struct clk *hdmi_clk;
-	struct device *dev;
-	struct delayed_work edid_work;
-	struct fb_videomode mode;
-	struct fb_monspecs monspec;
-
-	/* register access functions */
-	void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg);
-	u8 (*read)(struct sh_hdmi *hdmi, u8 reg);
-};
-
-#define entity_to_sh_hdmi(e)	container_of(e, struct sh_hdmi, entity)
-
-static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg)
-{
-	iowrite8(data, hdmi->base + reg);
-}
-
-static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg)
-{
-	return ioread8(hdmi->base + reg);
-}
-
-static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg)
-{
-	iowrite32((u32)data, hdmi->base + (reg * 4));
-	udelay(100);
-}
-
-static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg)
-{
-	return (u8)ioread32(hdmi->base + (reg * 4));
-}
-
-static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
-{
-	hdmi->write(hdmi, data, reg);
-}
-
-static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
-{
-	return hdmi->read(hdmi, reg);
-}
-
-static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
-{
-	u8 val = hdmi_read(hdmi, reg);
-
-	val &= ~mask;
-	val |= (data & mask);
-
-	hdmi_write(hdmi, val, reg);
-}
-
-static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg)
-{
-	iowrite32(data, hdmi->htop1 + reg);
-	udelay(100);
-}
-
-static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg)
-{
-	return ioread32(hdmi->htop1 + reg);
-}
-
-/*
- *	HDMI sound
- */
-static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec,
-				     unsigned int reg)
-{
-	struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
-
-	return hdmi_read(hdmi, reg);
-}
-
-static int sh_hdmi_snd_write(struct snd_soc_codec *codec,
-			     unsigned int reg,
-			     unsigned int value)
-{
-	struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
-
-	hdmi_write(hdmi, value, reg);
-	return 0;
-}
-
-static struct snd_soc_dai_driver sh_hdmi_dai = {
-	.name = "sh_mobile_hdmi-hifi",
-	.playback = {
-		.stream_name = "Playback",
-		.channels_min = 2,
-		.channels_max = 8,
-		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100  |
-			 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200  |
-			 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
-			 SNDRV_PCM_RATE_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
-	},
-};
-
-static int sh_hdmi_snd_probe(struct snd_soc_codec *codec)
-{
-	dev_info(codec->dev, "SH Mobile HDMI Audio Codec");
-
-	return 0;
-}
-
-static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
-	.probe		= sh_hdmi_snd_probe,
-	.read		= sh_hdmi_snd_read,
-	.write		= sh_hdmi_snd_write,
-};
-
-/*
- *	HDMI video
- */
-
-/* External video parameter settings */
-static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
-{
-	struct fb_videomode *mode = &hdmi->mode;
-	u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
-	u8 sync = 0;
-
-	htotal = mode->xres + mode->right_margin + mode->left_margin
-	       + mode->hsync_len;
-	hdelay = mode->hsync_len + mode->left_margin;
-	hblank = mode->right_margin + hdelay;
-
-	/*
-	 * Vertical timing looks a bit different in Figure 18,
-	 * but let's try the same first by setting offset = 0
-	 */
-	vtotal = mode->yres + mode->upper_margin + mode->lower_margin
-	       + mode->vsync_len;
-	vdelay = mode->vsync_len + mode->upper_margin;
-	vblank = mode->lower_margin + vdelay;
-	voffset = min(mode->upper_margin / 2, 6U);
-
-	/*
-	 * [3]: VSYNC polarity: Positive
-	 * [2]: HSYNC polarity: Positive
-	 * [1]: Interlace/Progressive: Progressive
-	 * [0]: External video settings enable: used.
-	 */
-	if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
-		sync |= 4;
-	if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
-		sync |= 8;
-
-	dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
-		htotal, hblank, hdelay, mode->hsync_len,
-		vtotal, vblank, vdelay, mode->vsync_len, sync);
-
-	hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
-
-	hdmi_write(hdmi, htotal, HDMI_EXTERNAL_H_TOTAL_7_0);
-	hdmi_write(hdmi, htotal >> 8, HDMI_EXTERNAL_H_TOTAL_11_8);
-
-	hdmi_write(hdmi, hblank, HDMI_EXTERNAL_H_BLANK_7_0);
-	hdmi_write(hdmi, hblank >> 8, HDMI_EXTERNAL_H_BLANK_9_8);
-
-	hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0);
-	hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8);
-
-	hdmi_write(hdmi, mode->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0);
-	hdmi_write(hdmi, mode->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8);
-
-	hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0);
-	hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8);
-
-	hdmi_write(hdmi, vblank, HDMI_EXTERNAL_V_BLANK);
-
-	hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY);
-
-	hdmi_write(hdmi, mode->vsync_len, HDMI_EXTERNAL_V_DURATION);
-
-	/* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
-	if (!hdmi->preprogrammed_vic)
-		hdmi_write(hdmi, sync | 1 | (voffset << 4),
-			   HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
-}
-
-/**
- * sh_hdmi_video_config()
- */
-static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
-{
-	/*
-	 * [7:4]: Audio sampling frequency: 48kHz
-	 * [3:1]: Input video format: RGB and YCbCr 4:4:4 (Y on Green)
-	 * [0]: Internal/External DE select: internal
-	 */
-	hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
-
-	/*
-	 * [7:6]: Video output format: RGB 4:4:4
-	 * [5:4]: Input video data width: 8 bit
-	 * [3:1]: EAV/SAV location: channel 1
-	 * [0]: Video input color space: RGB
-	 */
-	hdmi_write(hdmi, 0x34, HDMI_VIDEO_SETTING_1);
-
-	/*
-	 * [7:6]: Together with bit [6] of HDMI_AUDIO_VIDEO_SETTING_2, which is
-	 * left at 0 by default, this configures 24bpp and sets the Color Depth
-	 * (CD) field in the General Control Packet
-	 */
-	hdmi_write(hdmi, 0x20, HDMI_DEEP_COLOR_MODES);
-}
-
-/**
- * sh_hdmi_audio_config()
- */
-static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
-{
-	u8 data;
-	struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev);
-
-	/*
-	 * [7:4] L/R data swap control
-	 * [3:0] appropriate N[19:16]
-	 */
-	hdmi_write(hdmi, 0x00, HDMI_L_R_DATA_SWAP_CTRL_RPKT);
-	/* appropriate N[15:8] */
-	hdmi_write(hdmi, 0x18, HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8);
-	/* appropriate N[7:0] */
-	hdmi_write(hdmi, 0x00, HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0);
-
-	/* [7:4] 48 kHz	SPDIF not used */
-	hdmi_write(hdmi, 0x20, HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS);
-
-	/*
-	 * [6:5] set required down sampling rate if required
-	 * [4:3] set required audio source
-	 */
-	switch (pdata->flags & HDMI_SND_SRC_MASK) {
-	default:
-		/* fall through */
-	case HDMI_SND_SRC_I2S:
-		data = 0x0 << 3;
-		break;
-	case HDMI_SND_SRC_SPDIF:
-		data = 0x1 << 3;
-		break;
-	case HDMI_SND_SRC_DSD:
-		data = 0x2 << 3;
-		break;
-	case HDMI_SND_SRC_HBR:
-		data = 0x3 << 3;
-		break;
-	}
-	hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1);
-
-	/* [3:0] set sending channel number for channel status */
-	hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
-
-	/*
-	 * [5:2] set valid I2S source input pin
-	 * [1:0] set input I2S source mode
-	 */
-	hdmi_write(hdmi, 0x04, HDMI_I2S_AUDIO_SET);
-
-	/* [7:4] set valid DSD source input pin */
-	hdmi_write(hdmi, 0x00, HDMI_DSD_AUDIO_SET);
-
-	/* [7:0] set appropriate I2S input pin swap settings if required */
-	hdmi_write(hdmi, 0x00, HDMI_I2S_INPUT_PIN_SWAP);
-
-	/*
-	 * [7] set validity bit for channel status
-	 * [3:0] set original sample frequency for channel status
-	 */
-	hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_1);
-
-	/*
-	 * [7] set value for channel status
-	 * [6] set value for channel status
-	 * [5] set copyright bit for channel status
-	 * [4:2] set additional information for channel status
-	 * [1:0] set clock accuracy for channel status
-	 */
-	hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_2);
-
-	/* [7:0] set category code for channel status */
-	hdmi_write(hdmi, 0x00, HDMI_CATEGORY_CODE);
-
-	/*
-	 * [7:4] set source number for channel status
-	 * [3:0] set word length for channel status
-	 */
-	hdmi_write(hdmi, 0x00, HDMI_SOURCE_NUM_AUDIO_WORD_LEN);
-
-	/* [7:4] set sample frequency for channel status */
-	hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1);
-}
-
-/**
- * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode
- */
-static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
-{
-	if (hdmi->mode.pixclock < 10000) {
-		/* for 1080p8bit 148MHz */
-		hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
-		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
-		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
-		hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
-		hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
-		hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
-		hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
-		hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
-		hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
-	} else if (hdmi->mode.pixclock < 30000) {
-		/* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
-		/*
-		 * [1:0]	Speed_A
-		 * [3:2]	Speed_B
-		 * [4]		PLLA_Bypass
-		 * [6]		DRV_TEST_EN
-		 * [7]		DRV_TEST_IN
-		 */
-		hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
-		/* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */
-		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
-		/*
-		 * [2:0]	BGR_I_OFFSET
-		 * [6:4]	BGR_V_OFFSET
-		 */
-		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
-		/* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
-		hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
-		/*
-		 * PLLA_CONFIG[15:8]: regulator voltage[0], CP current,
-		 * LPF capacitance, LPF resistance[1]
-		 */
-		hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
-		/* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */
-		hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
-		/*
-		 * PLLB_CONFIG[15:8]: regulator voltage[0], CP current,
-		 * LPF capacitance, LPF resistance[1]
-		 */
-		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
-		/* DRV_CONFIG, PE_CONFIG */
-		hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
-		/*
-		 * [2:0]	AMON_SEL (4 == LPF voltage)
-		 * [4]		PLLA_CONFIG[16]
-		 * [5]		PLLB_CONFIG[16]
-		 */
-		hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
-	} else {
-		/* for 480p8bit 27MHz */
-		hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
-		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
-		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
-		hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
-		hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
-		hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
-		hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
-		hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
-		hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
-	}
-}
-
-/**
- * sh_hdmi_avi_infoframe_setup() - Auxiliary Video Information InfoFrame CONTROL PACKET
- */
-static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
-{
-	u8 vic;
-
-	/* AVI InfoFrame */
-	hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
-
-	/* Packet Type = 0x82 */
-	hdmi_write(hdmi, 0x82, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
-
-	/* Version = 0x02 */
-	hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
-
-	/* Length = 13 (0x0D) */
-	hdmi_write(hdmi, 0x0D, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
-
-	/* N. A. Checksum */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
-
-	/*
-	 * Y = RGB
-	 * A0 = No Data
-	 * B = Bar Data not valid
-	 * S = No Data
-	 */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
-
-	/*
-	 * [7:6] C = Colorimetry: no data
-	 * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio
-	 * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio
-	 */
-	hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
-
-	/*
-	 * ITC = No Data
-	 * EC = xvYCC601
-	 * Q = Default (depends on video format)
-	 * SC = No Known non_uniform Scaling
-	 */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
-
-	/*
-	 * VIC should be ignored if external config is used, so, we could just use 0,
-	 * but play safe and use a valid value in any case just in case
-	 */
-	if (hdmi->preprogrammed_vic)
-		vic = hdmi->preprogrammed_vic;
-	else
-		vic = 4;
-	hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
-
-	/* PR = No Repetition */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
-
-	/* Line Number of End of Top Bar (lower 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
-
-	/* Line Number of End of Top Bar (upper 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
-
-	/* Line Number of Start of Bottom Bar (lower 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
-
-	/* Line Number of Start of Bottom Bar (upper 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
-
-	/* Pixel Number of End of Left Bar (lower 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
-
-	/* Pixel Number of End of Left Bar (upper 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB11);
-
-	/* Pixel Number of Start of Right Bar (lower 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB12);
-
-	/* Pixel Number of Start of Right Bar (upper 8 bits) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB13);
-}
-
-/**
- * sh_hdmi_audio_infoframe_setup() - Audio InfoFrame of CONTROL PACKET
- */
-static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
-{
-	/* Audio InfoFrame */
-	hdmi_write(hdmi, 0x08, HDMI_CTRL_PKT_BUF_INDEX);
-
-	/* Packet Type = 0x84 */
-	hdmi_write(hdmi, 0x84, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
-
-	/* Version Number = 0x01 */
-	hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
-
-	/* 0 Length = 10 (0x0A) */
-	hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
-
-	/* n. a. Checksum */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0);
-
-	/* Audio Channel Count = Refer to Stream Header */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
-
-	/* Refer to Stream Header */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
-
-	/* Format depends on coding type (i.e. CT0...CT3) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
-
-	/* Speaker Channel Allocation = Front Right + Front Left */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
-
-	/* Level Shift Value = 0 dB, Down - mix is permitted or no information */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
-
-	/* Reserved (0) */
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6);
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7);
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8);
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9);
-	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10);
-}
-
-/**
- * sh_hdmi_configure() - Initialise HDMI for output
- */
-static void sh_hdmi_configure(struct sh_hdmi *hdmi)
-{
-	/* Configure video format */
-	sh_hdmi_video_config(hdmi);
-
-	/* Configure audio format */
-	sh_hdmi_audio_config(hdmi);
-
-	/* Configure PHY */
-	sh_hdmi_phy_config(hdmi);
-
-	/* Auxiliary Video Information (AVI) InfoFrame */
-	sh_hdmi_avi_infoframe_setup(hdmi);
-
-	/* Audio InfoFrame */
-	sh_hdmi_audio_infoframe_setup(hdmi);
-
-	/*
-	 * Control packet auto send with VSYNC control: auto send
-	 * General control, Gamut metadata, ISRC, and ACP packets
-	 */
-	hdmi_write(hdmi, 0x8E, HDMI_CTRL_PKT_AUTO_SEND);
-
-	/* FIXME */
-	msleep(10);
-
-	/* PS mode b->d, reset PLLA and PLLB */
-	hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL);
-
-	udelay(10);
-
-	hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL);
-}
-
-static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
-		const struct fb_videomode *mode,
-		unsigned long *hdmi_rate, unsigned long *parent_rate)
-{
-	unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
-	struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev);
-
-	*hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
-	if ((long)*hdmi_rate < 0)
-		*hdmi_rate = clk_get_rate(hdmi->hdmi_clk);
-
-	rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX;
-	if (rate_error && pdata->clk_optimize_parent)
-		rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate);
-	else if (clk_get_parent(hdmi->hdmi_clk))
-		*parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk));
-
-	dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
-		mode->left_margin, mode->xres,
-		mode->right_margin, mode->hsync_len,
-		mode->upper_margin, mode->yres,
-		mode->lower_margin, mode->vsync_len);
-
-	dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target,
-		rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
-		mode->refresh, *parent_rate);
-
-	return rate_error;
-}
-
-static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
-			     unsigned long *parent_rate)
-{
-	struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
-	const struct fb_videomode *mode, *found = NULL;
-	unsigned int f_width = 0, f_height = 0, f_refresh = 0;
-	unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
-	bool scanning = false, preferred_bad = false;
-	bool use_edid_mode = false;
-	u8 edid[128];
-	char *forced;
-	int i;
-
-	/* Read EDID */
-	dev_dbg(hdmi->dev, "Read back EDID code:");
-	for (i = 0; i < 128; i++) {
-		edid[i] = (hdmi->htop1) ?
-			(u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) :
-			hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
-#ifdef DEBUG
-		if ((i % 16) == 0) {
-			printk(KERN_CONT "\n");
-			printk(KERN_DEBUG "%02X | %02X", i, edid[i]);
-		} else {
-			printk(KERN_CONT " %02X", edid[i]);
-		}
-#endif
-	}
-#ifdef DEBUG
-	printk(KERN_CONT "\n");
-#endif
-
-	if (!hdmi->edid_blocks) {
-		fb_edid_to_monspecs(edid, &hdmi->monspec);
-		hdmi->edid_blocks = edid[126] + 1;
-
-		dev_dbg(hdmi->dev, "%d main modes, %d extension blocks\n",
-			hdmi->monspec.modedb_len, hdmi->edid_blocks - 1);
-	} else {
-		dev_dbg(hdmi->dev, "Extension %u detected, DTD start %u\n",
-			edid[0], edid[2]);
-		fb_edid_add_monspecs(edid, &hdmi->monspec);
-	}
-
-	if (hdmi->edid_blocks > hdmi->edid_segment_nr * 2 +
-	    (hdmi->edid_block_addr >> 7) + 1) {
-		/* More blocks to read */
-		if (hdmi->edid_block_addr) {
-			hdmi->edid_block_addr = 0;
-			hdmi->edid_segment_nr++;
-		} else {
-			hdmi->edid_block_addr = 0x80;
-		}
-		/* Set EDID word address  */
-		hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
-		/* Enable EDID interrupt */
-		hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
-		/* Set EDID segment pointer - starts reading EDID */
-		hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
-		return -EAGAIN;
-	}
-
-	/* All E-EDID blocks ready */
-	dev_dbg(hdmi->dev, "%d main and extended modes\n", hdmi->monspec.modedb_len);
-
-	fb_get_options("sh_mobile_lcdc", &forced);
-	if (forced && *forced) {
-		/* Only primitive parsing so far */
-		i = sscanf(forced, "%ux%u@%u",
-			   &f_width, &f_height, &f_refresh);
-		if (i < 2) {
-			f_width = 0;
-			f_height = 0;
-		} else {
-			/* The user wants us to use the EDID data */
-			scanning = true;
-		}
-		dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
-			f_width, f_height, f_refresh);
-	}
-
-	/* Walk monitor modes to find the best or the exact match */
-	for (i = 0, mode = hdmi->monspec.modedb;
-	     i < hdmi->monspec.modedb_len && scanning;
-	     i++, mode++) {
-		unsigned long rate_error;
-
-		if (!f_width && !f_height) {
-			/*
-			 * A parameter string "video=sh_mobile_lcdc:0x0" means
-			 * use the preferred EDID mode. If it is rejected by
-			 * .fb_check_var(), keep looking, until an acceptable
-			 * one is found.
-			 */
-			if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad)
-				scanning = false;
-			else
-				continue;
-		} else if (f_width != mode->xres || f_height != mode->yres) {
-			/* No interest in unmatching modes */
-			continue;
-		}
-
-		rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
-
-		if (scanning) {
-			if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
-				/*
-				 * Exact match if either the refresh rate
-				 * matches or it hasn't been specified and we've
-				 * found a mode, for which we can configure the
-				 * clock precisely
-				 */
-				scanning = false;
-			else if (found && found_rate_error <= rate_error)
-				/*
-				 * We otherwise search for the closest matching
-				 * clock rate - either if no refresh rate has
-				 * been specified or we cannot find an exactly
-				 * matching one
-				 */
-				continue;
-		}
-
-		/* Check if supported: sufficient fb memory, supported clock-rate */
-		if (ch && ch->notify &&
-		    ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_MODE, mode,
-			       NULL)) {
-			scanning = true;
-			preferred_bad = true;
-			continue;
-		}
-
-		found = mode;
-		found_rate_error = rate_error;
-		use_edid_mode = true;
-	}
-
-	/*
-	 * TODO 1: if no default mode is present, postpone running the config
-	 * until after the LCDC channel is initialized.
-	 * TODO 2: consider registering the HDMI platform device from the LCDC
-	 * driver.
-	 */
-	if (!found && hdmi->entity.def_mode.xres != 0) {
-		found = &hdmi->entity.def_mode;
-		found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate,
-						      parent_rate);
-	}
-
-	/* No cookie today */
-	if (!found)
-		return -ENXIO;
-
-	if (found->xres == 640 && found->yres == 480 && found->refresh == 60)
-		hdmi->preprogrammed_vic = 1;
-	else if (found->xres == 720 && found->yres == 480 && found->refresh == 60)
-		hdmi->preprogrammed_vic = 2;
-	else if (found->xres == 720 && found->yres == 576 && found->refresh == 50)
-		hdmi->preprogrammed_vic = 17;
-	else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60)
-		hdmi->preprogrammed_vic = 4;
-	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24)
-		hdmi->preprogrammed_vic = 32;
-	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50)
-		hdmi->preprogrammed_vic = 31;
-	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60)
-		hdmi->preprogrammed_vic = 16;
-	else
-		hdmi->preprogrammed_vic = 0;
-
-	dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), "
-		"clock error %luHz\n", use_edid_mode ? "EDID" : "default",
-		hdmi->preprogrammed_vic ? "VIC" : "external", found->xres,
-		found->yres, found->refresh, PICOS2KHZ(found->pixclock) * 1000,
-		found_rate_error);
-
-	hdmi->mode = *found;
-	sh_hdmi_external_video_param(hdmi);
-
-	return 0;
-}
-
-static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
-{
-	struct sh_hdmi *hdmi = dev_id;
-	u8 status1, status2, mask1, mask2;
-
-	/* mode_b and PLLA and PLLB reset */
-	hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL);
-
-	/* How long shall reset be held? */
-	udelay(10);
-
-	/* mode_b and PLLA and PLLB reset release */
-	hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL);
-
-	status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
-	status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
-
-	mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1);
-	mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2);
-
-	/* Correct would be to ack only set bits, but the datasheet requires 0xff */
-	hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1);
-	hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
-
-	if (printk_ratelimit())
-		dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
-			irq, status1, mask1, status2, mask2);
-
-	if (!((status1 & mask1) | (status2 & mask2))) {
-		return IRQ_NONE;
-	} else if (status1 & 0xc0) {
-		u8 msens;
-
-		/* Datasheet specifies 10ms... */
-		udelay(500);
-
-		msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
-		dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens);
-		/* Check, if hot plug & MSENS pin status are both high */
-		if ((msens & 0xC0) == 0xC0) {
-			/* Display plug in */
-			hdmi->edid_segment_nr = 0;
-			hdmi->edid_block_addr = 0;
-			hdmi->edid_blocks = 0;
-			hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
-
-			/* Set EDID word address  */
-			hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
-			/* Enable EDID interrupt */
-			hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
-			/* Set EDID segment pointer - starts reading EDID */
-			hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
-		} else if (!(status1 & 0x80)) {
-			/* Display unplug, beware multiple interrupts */
-			if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) {
-				hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
-				schedule_delayed_work(&hdmi->edid_work, 0);
-			}
-			/* display_off will switch back to mode_a */
-		}
-	} else if (status1 & 2) {
-		/* EDID error interrupt: retry */
-		/* Set EDID word address  */
-		hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
-		/* Set EDID segment pointer */
-		hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
-	} else if (status1 & 4) {
-		/* Disable EDID interrupt */
-		hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
-		schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity)
-{
-	struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
-
-	dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, hdmi,
-		hdmi->hp_state);
-
-	/*
-	 * hp_state can be set to
-	 * HDMI_HOTPLUG_DISCONNECTED:	on monitor unplug
-	 * HDMI_HOTPLUG_CONNECTED:	on monitor plug-in
-	 * HDMI_HOTPLUG_EDID_DONE:	on EDID read completion
-	 */
-	if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
-		/* PS mode d->e. All functions are active */
-		hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL);
-		dev_dbg(hdmi->dev, "HDMI running\n");
-	}
-
-	return hdmi->hp_state == HDMI_HOTPLUG_DISCONNECTED
-		? SH_MOBILE_LCDC_DISPLAY_DISCONNECTED
-		: SH_MOBILE_LCDC_DISPLAY_CONNECTED;
-}
-
-static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
-{
-	struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
-
-	dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi);
-	/* PS mode e->a */
-	hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL);
-}
-
-static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
-	.display_on = sh_hdmi_display_on,
-	.display_off = sh_hdmi_display_off,
-};
-
-/**
- * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
- * @hdmi:		driver context
- * @hdmi_rate:		HDMI clock frequency in Hz
- * @parent_rate:	if != 0 - set parent clock rate for optimal precision
- * return:		configured positive rate if successful
- *			0 if couldn't set the rate, but managed to enable the
- *			clock, negative error, if couldn't enable the clock
- */
-static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
-				  unsigned long parent_rate)
-{
-	int ret;
-
-	if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) {
-		ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate);
-		if (ret < 0) {
-			dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret);
-			hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate);
-		} else {
-			dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate);
-		}
-	}
-
-	ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate);
-	if (ret < 0) {
-		dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret);
-		hdmi_rate = 0;
-	} else {
-		dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate);
-	}
-
-	return hdmi_rate;
-}
-
-/* Hotplug interrupt occurred, read EDID */
-static void sh_hdmi_edid_work_fn(struct work_struct *work)
-{
-	struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
-	struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
-	int ret;
-
-	dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi,
-		hdmi->hp_state);
-
-	if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
-		unsigned long parent_rate = 0, hdmi_rate;
-
-		ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
-		if (ret < 0)
-			goto out;
-
-		hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
-
-		/* Reconfigure the clock */
-		ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
-		if (ret < 0)
-			goto out;
-
-		msleep(10);
-		sh_hdmi_configure(hdmi);
-		/* Switched to another (d) power-save mode */
-		msleep(10);
-
-		if (ch && ch->notify)
-			ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
-				   &hdmi->mode, &hdmi->monspec);
-	} else {
-		hdmi->monspec.modedb_len = 0;
-		fb_destroy_modedb(hdmi->monspec.modedb);
-		hdmi->monspec.modedb = NULL;
-
-		if (ch && ch->notify)
-			ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
-				   NULL, NULL);
-
-		ret = 0;
-	}
-
-out:
-	if (ret < 0 && ret != -EAGAIN)
-		hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
-
-	dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
-}
-
-static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi)
-{
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE);
-	hdmi_htop1_write(hdmi, 0x0000000b, 0x0010);
-	hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE);
-	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1);
-	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2);
-	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1);
-	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2);
-	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1);
-	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2);
-	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1);
-	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2);
-	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1);
-	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2);
-	hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1);
-	hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2);
-	hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE);
-	hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW);
-	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
-	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
-	hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
-	hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
-	hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE);
-	msleep(100);
-	hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR);
-	msleep(100);
-	hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
-	hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
-	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
-	hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY);
-	hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2);
-	hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET);
-}
-
-static int __init sh_hdmi_probe(struct platform_device *pdev)
-{
-	struct sh_mobile_hdmi_info *pdata = dev_get_platdata(&pdev->dev);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	struct resource *htop1_res;
-	int irq = platform_get_irq(pdev, 0), ret;
-	struct sh_hdmi *hdmi;
-	long rate;
-
-	if (!res || !pdata || irq < 0)
-		return -ENODEV;
-
-	htop1_res = NULL;
-	if (pdata->flags & HDMI_HAS_HTOP1) {
-		htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (!htop1_res) {
-			dev_err(&pdev->dev, "htop1 needs register base\n");
-			return -EINVAL;
-		}
-	}
-
-	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
-	if (!hdmi) {
-		dev_err(&pdev->dev, "Cannot allocate device data\n");
-		return -ENOMEM;
-	}
-
-	hdmi->dev = &pdev->dev;
-	hdmi->entity.owner = THIS_MODULE;
-	hdmi->entity.ops = &sh_hdmi_ops;
-
-	hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(hdmi->hdmi_clk)) {
-		ret = PTR_ERR(hdmi->hdmi_clk);
-		dev_err(&pdev->dev, "Unable to get clock: %d\n", ret);
-		return ret;
-	}
-
-	/* select register access functions */
-	if (pdata->flags & HDMI_32BIT_REG) {
-		hdmi->write	= __hdmi_write32;
-		hdmi->read	= __hdmi_read32;
-	} else {
-		hdmi->write	= __hdmi_write8;
-		hdmi->read	= __hdmi_read8;
-	}
-
-	/* An arbitrary relaxed pixclock just to get things started: from standard 480p */
-	rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
-	if (rate > 0)
-		rate = sh_hdmi_clk_configure(hdmi, rate, 0);
-
-	if (rate < 0) {
-		ret = rate;
-		goto erate;
-	}
-
-	ret = clk_prepare_enable(hdmi->hdmi_clk);
-	if (ret < 0) {
-		dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
-		goto erate;
-	}
-
-	dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
-
-	if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
-		dev_err(&pdev->dev, "HDMI register region already claimed\n");
-		ret = -EBUSY;
-		goto ereqreg;
-	}
-
-	hdmi->base = ioremap(res->start, resource_size(res));
-	if (!hdmi->base) {
-		dev_err(&pdev->dev, "HDMI register region already claimed\n");
-		ret = -ENOMEM;
-		goto emap;
-	}
-
-	platform_set_drvdata(pdev, &hdmi->entity);
-
-	INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
-
-	pm_runtime_enable(&pdev->dev);
-	pm_runtime_get_sync(&pdev->dev);
-
-	/* init interrupt polarity */
-	if (pdata->flags & HDMI_OUTPUT_PUSH_PULL)
-		hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL);
-
-	if (pdata->flags & HDMI_OUTPUT_POLARITY_HI)
-		hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL);
-
-	/* enable htop1 register if needed */
-	if (htop1_res) {
-		hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res));
-		if (!hdmi->htop1) {
-			dev_err(&pdev->dev, "control register region already claimed\n");
-			ret = -ENOMEM;
-			goto emap_htop1;
-		}
-		sh_hdmi_htop1_init(hdmi);
-	}
-
-	/* Product and revision IDs are 0 in sh-mobile version */
-	dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
-		 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
-
-	ret = request_irq(irq, sh_hdmi_hotplug, 0,
-			  dev_name(&pdev->dev), hdmi);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to request irq: %d\n", ret);
-		goto ereqirq;
-	}
-
-	ret = snd_soc_register_codec(&pdev->dev,
-			&soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "codec registration failed\n");
-		goto ecodec;
-	}
-
-	return 0;
-
-ecodec:
-	free_irq(irq, hdmi);
-ereqirq:
-	if (hdmi->htop1)
-		iounmap(hdmi->htop1);
-emap_htop1:
-	pm_runtime_put(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
-	iounmap(hdmi->base);
-emap:
-	release_mem_region(res->start, resource_size(res));
-ereqreg:
-	clk_disable_unprepare(hdmi->hdmi_clk);
-erate:
-	clk_put(hdmi->hdmi_clk);
-
-	return ret;
-}
-
-static int __exit sh_hdmi_remove(struct platform_device *pdev)
-{
-	struct sh_hdmi *hdmi = entity_to_sh_hdmi(platform_get_drvdata(pdev));
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	int irq = platform_get_irq(pdev, 0);
-
-	snd_soc_unregister_codec(&pdev->dev);
-
-	/* No new work will be scheduled, wait for running ISR */
-	free_irq(irq, hdmi);
-	/* Wait for already scheduled work */
-	cancel_delayed_work_sync(&hdmi->edid_work);
-	pm_runtime_put(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
-	clk_disable_unprepare(hdmi->hdmi_clk);
-	clk_put(hdmi->hdmi_clk);
-	if (hdmi->htop1)
-		iounmap(hdmi->htop1);
-	iounmap(hdmi->base);
-	release_mem_region(res->start, resource_size(res));
-
-	return 0;
-}
-
-static struct platform_driver sh_hdmi_driver = {
-	.remove		= __exit_p(sh_hdmi_remove),
-	.driver = {
-		.name	= "sh-mobile-hdmi",
-	},
-};
-
-module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe);
-
-MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
-MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
deleted file mode 100644
index 2bcc84ac18c7..000000000000
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ /dev/null
@@ -1,2863 +0,0 @@
-/*
- * SuperH Mobile LCDC Framebuffer
- *
- * Copyright (c) 2008 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/atomic.h>
-#include <linux/backlight.h>
-#include <linux/clk.h>
-#include <linux/console.h>
-#include <linux/ctype.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioctl.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <linux/vmalloc.h>
-
-#include <video/sh_mobile_lcdc.h>
-#include <video/sh_mobile_meram.h>
-
-#include "sh_mobile_lcdcfb.h"
-
-/* ----------------------------------------------------------------------------
- * Overlay register definitions
- */
-
-#define LDBCR			0xb00
-#define LDBCR_UPC(n)		(1 << ((n) + 16))
-#define LDBCR_UPF(n)		(1 << ((n) + 8))
-#define LDBCR_UPD(n)		(1 << ((n) + 0))
-#define LDBnBSIFR(n)		(0xb20 + (n) * 0x20 + 0x00)
-#define LDBBSIFR_EN		(1 << 31)
-#define LDBBSIFR_VS		(1 << 29)
-#define LDBBSIFR_BRSEL		(1 << 28)
-#define LDBBSIFR_MX		(1 << 27)
-#define LDBBSIFR_MY		(1 << 26)
-#define LDBBSIFR_CV3		(3 << 24)
-#define LDBBSIFR_CV2		(2 << 24)
-#define LDBBSIFR_CV1		(1 << 24)
-#define LDBBSIFR_CV0		(0 << 24)
-#define LDBBSIFR_CV_MASK	(3 << 24)
-#define LDBBSIFR_LAY_MASK	(0xff << 16)
-#define LDBBSIFR_LAY_SHIFT	16
-#define LDBBSIFR_ROP3_MASK	(0xff << 16)
-#define LDBBSIFR_ROP3_SHIFT	16
-#define LDBBSIFR_AL_PL8		(3 << 14)
-#define LDBBSIFR_AL_PL1		(2 << 14)
-#define LDBBSIFR_AL_PK		(1 << 14)
-#define LDBBSIFR_AL_1		(0 << 14)
-#define LDBBSIFR_AL_MASK	(3 << 14)
-#define LDBBSIFR_SWPL		(1 << 10)
-#define LDBBSIFR_SWPW		(1 << 9)
-#define LDBBSIFR_SWPB		(1 << 8)
-#define LDBBSIFR_RY		(1 << 7)
-#define LDBBSIFR_CHRR_420	(2 << 0)
-#define LDBBSIFR_CHRR_422	(1 << 0)
-#define LDBBSIFR_CHRR_444	(0 << 0)
-#define LDBBSIFR_RPKF_ARGB32	(0x00 << 0)
-#define LDBBSIFR_RPKF_RGB16	(0x03 << 0)
-#define LDBBSIFR_RPKF_RGB24	(0x0b << 0)
-#define LDBBSIFR_RPKF_MASK	(0x1f << 0)
-#define LDBnBSSZR(n)		(0xb20 + (n) * 0x20 + 0x04)
-#define LDBBSSZR_BVSS_MASK	(0xfff << 16)
-#define LDBBSSZR_BVSS_SHIFT	16
-#define LDBBSSZR_BHSS_MASK	(0xfff << 0)
-#define LDBBSSZR_BHSS_SHIFT	0
-#define LDBnBLOCR(n)		(0xb20 + (n) * 0x20 + 0x08)
-#define LDBBLOCR_CVLC_MASK	(0xfff << 16)
-#define LDBBLOCR_CVLC_SHIFT	16
-#define LDBBLOCR_CHLC_MASK	(0xfff << 0)
-#define LDBBLOCR_CHLC_SHIFT	0
-#define LDBnBSMWR(n)		(0xb20 + (n) * 0x20 + 0x0c)
-#define LDBBSMWR_BSMWA_MASK	(0xffff << 16)
-#define LDBBSMWR_BSMWA_SHIFT	16
-#define LDBBSMWR_BSMW_MASK	(0xffff << 0)
-#define LDBBSMWR_BSMW_SHIFT	0
-#define LDBnBSAYR(n)		(0xb20 + (n) * 0x20 + 0x10)
-#define LDBBSAYR_FG1A_MASK	(0xff << 24)
-#define LDBBSAYR_FG1A_SHIFT	24
-#define LDBBSAYR_FG1R_MASK	(0xff << 16)
-#define LDBBSAYR_FG1R_SHIFT	16
-#define LDBBSAYR_FG1G_MASK	(0xff << 8)
-#define LDBBSAYR_FG1G_SHIFT	8
-#define LDBBSAYR_FG1B_MASK	(0xff << 0)
-#define LDBBSAYR_FG1B_SHIFT	0
-#define LDBnBSACR(n)		(0xb20 + (n) * 0x20 + 0x14)
-#define LDBBSACR_FG2A_MASK	(0xff << 24)
-#define LDBBSACR_FG2A_SHIFT	24
-#define LDBBSACR_FG2R_MASK	(0xff << 16)
-#define LDBBSACR_FG2R_SHIFT	16
-#define LDBBSACR_FG2G_MASK	(0xff << 8)
-#define LDBBSACR_FG2G_SHIFT	8
-#define LDBBSACR_FG2B_MASK	(0xff << 0)
-#define LDBBSACR_FG2B_SHIFT	0
-#define LDBnBSAAR(n)		(0xb20 + (n) * 0x20 + 0x18)
-#define LDBBSAAR_AP_MASK	(0xff << 24)
-#define LDBBSAAR_AP_SHIFT	24
-#define LDBBSAAR_R_MASK		(0xff << 16)
-#define LDBBSAAR_R_SHIFT	16
-#define LDBBSAAR_GY_MASK	(0xff << 8)
-#define LDBBSAAR_GY_SHIFT	8
-#define LDBBSAAR_B_MASK		(0xff << 0)
-#define LDBBSAAR_B_SHIFT	0
-#define LDBnBPPCR(n)		(0xb20 + (n) * 0x20 + 0x1c)
-#define LDBBPPCR_AP_MASK	(0xff << 24)
-#define LDBBPPCR_AP_SHIFT	24
-#define LDBBPPCR_R_MASK		(0xff << 16)
-#define LDBBPPCR_R_SHIFT	16
-#define LDBBPPCR_GY_MASK	(0xff << 8)
-#define LDBBPPCR_GY_SHIFT	8
-#define LDBBPPCR_B_MASK		(0xff << 0)
-#define LDBBPPCR_B_SHIFT	0
-#define LDBnBBGCL(n)		(0xb10 + (n) * 0x04)
-#define LDBBBGCL_BGA_MASK	(0xff << 24)
-#define LDBBBGCL_BGA_SHIFT	24
-#define LDBBBGCL_BGR_MASK	(0xff << 16)
-#define LDBBBGCL_BGR_SHIFT	16
-#define LDBBBGCL_BGG_MASK	(0xff << 8)
-#define LDBBBGCL_BGG_SHIFT	8
-#define LDBBBGCL_BGB_MASK	(0xff << 0)
-#define LDBBBGCL_BGB_SHIFT	0
-
-#define SIDE_B_OFFSET 0x1000
-#define MIRROR_OFFSET 0x2000
-
-#define MAX_XRES 1920
-#define MAX_YRES 1080
-
-enum sh_mobile_lcdc_overlay_mode {
-	LCDC_OVERLAY_BLEND,
-	LCDC_OVERLAY_ROP3,
-};
-
-/*
- * struct sh_mobile_lcdc_overlay - LCDC display overlay
- *
- * @channel: LCDC channel this overlay belongs to
- * @cfg: Overlay configuration
- * @info: Frame buffer device
- * @index: Overlay index (0-3)
- * @base: Overlay registers base address
- * @enabled: True if the overlay is enabled
- * @mode: Overlay blending mode (alpha blend or ROP3)
- * @alpha: Global alpha blending value (0-255, for alpha blending mode)
- * @rop3: Raster operation (for ROP3 mode)
- * @fb_mem: Frame buffer virtual memory address
- * @fb_size: Frame buffer size in bytes
- * @dma_handle: Frame buffer DMA address
- * @base_addr_y: Overlay base address (RGB or luma component)
- * @base_addr_c: Overlay base address (chroma component)
- * @pan_y_offset: Panning linear offset in bytes (luma component)
- * @format: Current pixelf format
- * @xres: Horizontal visible resolution
- * @xres_virtual: Horizontal total resolution
- * @yres: Vertical visible resolution
- * @yres_virtual: Vertical total resolution
- * @pitch: Overlay line pitch
- * @pos_x: Horizontal overlay position
- * @pos_y: Vertical overlay position
- */
-struct sh_mobile_lcdc_overlay {
-	struct sh_mobile_lcdc_chan *channel;
-
-	const struct sh_mobile_lcdc_overlay_cfg *cfg;
-	struct fb_info *info;
-
-	unsigned int index;
-	unsigned long base;
-
-	bool enabled;
-	enum sh_mobile_lcdc_overlay_mode mode;
-	unsigned int alpha;
-	unsigned int rop3;
-
-	void *fb_mem;
-	unsigned long fb_size;
-
-	dma_addr_t dma_handle;
-	unsigned long base_addr_y;
-	unsigned long base_addr_c;
-	unsigned long pan_y_offset;
-
-	const struct sh_mobile_lcdc_format_info *format;
-	unsigned int xres;
-	unsigned int xres_virtual;
-	unsigned int yres;
-	unsigned int yres_virtual;
-	unsigned int pitch;
-	int pos_x;
-	int pos_y;
-};
-
-struct sh_mobile_lcdc_priv {
-	void __iomem *base;
-	int irq;
-	atomic_t hw_usecnt;
-	struct device *dev;
-	struct clk *dot_clk;
-	unsigned long lddckr;
-
-	struct sh_mobile_lcdc_chan ch[2];
-	struct sh_mobile_lcdc_overlay overlays[4];
-
-	struct notifier_block notifier;
-	int started;
-	int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
-	struct sh_mobile_meram_info *meram_dev;
-};
-
-/* -----------------------------------------------------------------------------
- * Registers access
- */
-
-static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
-	[LDDCKPAT1R] = 0x400,
-	[LDDCKPAT2R] = 0x404,
-	[LDMT1R] = 0x418,
-	[LDMT2R] = 0x41c,
-	[LDMT3R] = 0x420,
-	[LDDFR] = 0x424,
-	[LDSM1R] = 0x428,
-	[LDSM2R] = 0x42c,
-	[LDSA1R] = 0x430,
-	[LDSA2R] = 0x434,
-	[LDMLSR] = 0x438,
-	[LDHCNR] = 0x448,
-	[LDHSYNR] = 0x44c,
-	[LDVLNR] = 0x450,
-	[LDVSYNR] = 0x454,
-	[LDPMR] = 0x460,
-	[LDHAJR] = 0x4a0,
-};
-
-static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
-	[LDDCKPAT1R] = 0x408,
-	[LDDCKPAT2R] = 0x40c,
-	[LDMT1R] = 0x600,
-	[LDMT2R] = 0x604,
-	[LDMT3R] = 0x608,
-	[LDDFR] = 0x60c,
-	[LDSM1R] = 0x610,
-	[LDSM2R] = 0x614,
-	[LDSA1R] = 0x618,
-	[LDMLSR] = 0x620,
-	[LDHCNR] = 0x624,
-	[LDHSYNR] = 0x628,
-	[LDVLNR] = 0x62c,
-	[LDVSYNR] = 0x630,
-	[LDPMR] = 0x63c,
-};
-
-static bool banked(int reg_nr)
-{
-	switch (reg_nr) {
-	case LDMT1R:
-	case LDMT2R:
-	case LDMT3R:
-	case LDDFR:
-	case LDSM1R:
-	case LDSA1R:
-	case LDSA2R:
-	case LDMLSR:
-	case LDHCNR:
-	case LDHSYNR:
-	case LDVLNR:
-	case LDVSYNR:
-		return true;
-	}
-	return false;
-}
-
-static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
-{
-	return chan->cfg->chan == LCDC_CHAN_SUBLCD;
-}
-
-static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
-			    int reg_nr, unsigned long data)
-{
-	iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
-	if (banked(reg_nr))
-		iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
-			  SIDE_B_OFFSET);
-}
-
-static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan,
-			    int reg_nr, unsigned long data)
-{
-	iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
-		  MIRROR_OFFSET);
-}
-
-static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
-				    int reg_nr)
-{
-	return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
-}
-
-static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl,
-			       int reg, unsigned long data)
-{
-	iowrite32(data, ovl->channel->lcdc->base + reg);
-	iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET);
-}
-
-static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
-		       unsigned long reg_offs, unsigned long data)
-{
-	iowrite32(data, priv->base + reg_offs);
-}
-
-static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
-			       unsigned long reg_offs)
-{
-	return ioread32(priv->base + reg_offs);
-}
-
-static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
-			  unsigned long reg_offs,
-			  unsigned long mask, unsigned long until)
-{
-	while ((lcdc_read(priv, reg_offs) & mask) != until)
-		cpu_relax();
-}
-
-/* -----------------------------------------------------------------------------
- * Clock management
- */
-
-static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
-{
-	if (atomic_inc_and_test(&priv->hw_usecnt)) {
-		if (priv->dot_clk)
-			clk_prepare_enable(priv->dot_clk);
-		pm_runtime_get_sync(priv->dev);
-		if (priv->meram_dev && priv->meram_dev->pdev)
-			pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
-	}
-}
-
-static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
-{
-	if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
-		if (priv->meram_dev && priv->meram_dev->pdev)
-			pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
-		pm_runtime_put(priv->dev);
-		if (priv->dot_clk)
-			clk_disable_unprepare(priv->dot_clk);
-	}
-}
-
-static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
-				       int clock_source)
-{
-	struct clk *clk;
-	char *str;
-
-	switch (clock_source) {
-	case LCDC_CLK_BUS:
-		str = "bus_clk";
-		priv->lddckr = LDDCKR_ICKSEL_BUS;
-		break;
-	case LCDC_CLK_PERIPHERAL:
-		str = "peripheral_clk";
-		priv->lddckr = LDDCKR_ICKSEL_MIPI;
-		break;
-	case LCDC_CLK_EXTERNAL:
-		str = NULL;
-		priv->lddckr = LDDCKR_ICKSEL_HDMI;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (str == NULL)
-		return 0;
-
-	clk = clk_get(priv->dev, str);
-	if (IS_ERR(clk)) {
-		dev_err(priv->dev, "cannot get dot clock %s\n", str);
-		return PTR_ERR(clk);
-	}
-
-	priv->dot_clk = clk;
-	return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Display, panel and deferred I/O
- */
-
-static void lcdc_sys_write_index(void *handle, unsigned long data)
-{
-	struct sh_mobile_lcdc_chan *ch = handle;
-
-	lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
-	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
-	lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
-		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
-	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
-}
-
-static void lcdc_sys_write_data(void *handle, unsigned long data)
-{
-	struct sh_mobile_lcdc_chan *ch = handle;
-
-	lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
-	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
-	lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
-		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
-	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
-}
-
-static unsigned long lcdc_sys_read_data(void *handle)
-{
-	struct sh_mobile_lcdc_chan *ch = handle;
-
-	lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
-	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
-	lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
-		   (lcdc_chan_is_sublcd(ch) ? 2 : 0));
-	udelay(1);
-	lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
-
-	return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
-}
-
-static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
-	lcdc_sys_write_index,
-	lcdc_sys_write_data,
-	lcdc_sys_read_data,
-};
-
-static int sh_mobile_lcdc_sginit(struct fb_info *info,
-				  struct list_head *pagelist)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
-	struct page *page;
-	int nr_pages = 0;
-
-	sg_init_table(ch->sglist, nr_pages_max);
-
-	list_for_each_entry(page, pagelist, lru)
-		sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
-
-	return nr_pages;
-}
-
-static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
-				       struct list_head *pagelist)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
-
-	/* enable clocks before accessing hardware */
-	sh_mobile_lcdc_clk_on(ch->lcdc);
-
-	/*
-	 * It's possible to get here without anything on the pagelist via
-	 * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
-	 * invocation. In the former case, the acceleration routines are
-	 * stepped in to when using the framebuffer console causing the
-	 * workqueue to be scheduled without any dirty pages on the list.
-	 *
-	 * Despite this, a panel update is still needed given that the
-	 * acceleration routines have their own methods for writing in
-	 * that still need to be updated.
-	 *
-	 * The fsync() and empty pagelist case could be optimized for,
-	 * but we don't bother, as any application exhibiting such
-	 * behaviour is fundamentally broken anyways.
-	 */
-	if (!list_empty(pagelist)) {
-		unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
-
-		/* trigger panel update */
-		dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
-		if (panel->start_transfer)
-			panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
-		lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
-		dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages,
-			     DMA_TO_DEVICE);
-	} else {
-		if (panel->start_transfer)
-			panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
-		lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
-	}
-}
-
-static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
-{
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-
-	if (fbdefio)
-		schedule_delayed_work(&info->deferred_work, fbdefio->delay);
-}
-
-static void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch)
-{
-	const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
-
-	if (ch->tx_dev) {
-		int ret;
-
-		ret = ch->tx_dev->ops->display_on(ch->tx_dev);
-		if (ret < 0)
-			return;
-
-		if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED)
-			ch->info->state = FBINFO_STATE_SUSPENDED;
-	}
-
-	/* HDMI must be enabled before LCDC configuration */
-	if (panel->display_on)
-		panel->display_on();
-}
-
-static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
-{
-	const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
-
-	if (panel->display_off)
-		panel->display_off();
-
-	if (ch->tx_dev)
-		ch->tx_dev->ops->display_off(ch->tx_dev);
-}
-
-static bool
-sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
-				const struct fb_videomode *new_mode)
-{
-	dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
-		ch->display.mode.xres, ch->display.mode.yres,
-		new_mode->xres, new_mode->yres);
-
-	/* It can be a different monitor with an equal video-mode */
-	if (fb_mode_is_equal(&ch->display.mode, new_mode))
-		return false;
-
-	dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
-		ch->display.mode.yres, new_mode->yres);
-	ch->display.mode = *new_mode;
-
-	return true;
-}
-
-static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
-				    struct fb_info *info);
-
-static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
-					 enum sh_mobile_lcdc_entity_event event,
-					 const struct fb_videomode *mode,
-					 const struct fb_monspecs *monspec)
-{
-	struct fb_info *info = ch->info;
-	struct fb_var_screeninfo var;
-	int ret = 0;
-
-	switch (event) {
-	case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
-		/* HDMI plug in */
-		console_lock();
-		if (lock_fb_info(info)) {
-
-
-			ch->display.width = monspec->max_x * 10;
-			ch->display.height = monspec->max_y * 10;
-
-			if (!sh_mobile_lcdc_must_reconfigure(ch, mode) &&
-			    info->state == FBINFO_STATE_RUNNING) {
-				/* First activation with the default monitor.
-				 * Just turn on, if we run a resume here, the
-				 * logo disappears.
-				 */
-				info->var.width = ch->display.width;
-				info->var.height = ch->display.height;
-				sh_mobile_lcdc_display_on(ch);
-			} else {
-				/* New monitor or have to wake up */
-				fb_set_suspend(info, 0);
-			}
-
-
-			unlock_fb_info(info);
-		}
-		console_unlock();
-		break;
-
-	case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
-		/* HDMI disconnect */
-		console_lock();
-		if (lock_fb_info(info)) {
-			fb_set_suspend(info, 1);
-			unlock_fb_info(info);
-		}
-		console_unlock();
-		break;
-
-	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
-		/* Validate a proposed new mode */
-		fb_videomode_to_var(&var, mode);
-		var.bits_per_pixel = info->var.bits_per_pixel;
-		var.grayscale = info->var.grayscale;
-		ret = sh_mobile_lcdc_check_var(&var, info);
-		break;
-	}
-
-	return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * Format helpers
- */
-
-struct sh_mobile_lcdc_format_info {
-	u32 fourcc;
-	unsigned int bpp;
-	bool yuv;
-	u32 lddfr;
-};
-
-static const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = {
-	{
-		.fourcc = V4L2_PIX_FMT_RGB565,
-		.bpp = 16,
-		.yuv = false,
-		.lddfr = LDDFR_PKF_RGB16,
-	}, {
-		.fourcc = V4L2_PIX_FMT_BGR24,
-		.bpp = 24,
-		.yuv = false,
-		.lddfr = LDDFR_PKF_RGB24,
-	}, {
-		.fourcc = V4L2_PIX_FMT_BGR32,
-		.bpp = 32,
-		.yuv = false,
-		.lddfr = LDDFR_PKF_ARGB32,
-	}, {
-		.fourcc = V4L2_PIX_FMT_NV12,
-		.bpp = 12,
-		.yuv = true,
-		.lddfr = LDDFR_CC | LDDFR_YF_420,
-	}, {
-		.fourcc = V4L2_PIX_FMT_NV21,
-		.bpp = 12,
-		.yuv = true,
-		.lddfr = LDDFR_CC | LDDFR_YF_420,
-	}, {
-		.fourcc = V4L2_PIX_FMT_NV16,
-		.bpp = 16,
-		.yuv = true,
-		.lddfr = LDDFR_CC | LDDFR_YF_422,
-	}, {
-		.fourcc = V4L2_PIX_FMT_NV61,
-		.bpp = 16,
-		.yuv = true,
-		.lddfr = LDDFR_CC | LDDFR_YF_422,
-	}, {
-		.fourcc = V4L2_PIX_FMT_NV24,
-		.bpp = 24,
-		.yuv = true,
-		.lddfr = LDDFR_CC | LDDFR_YF_444,
-	}, {
-		.fourcc = V4L2_PIX_FMT_NV42,
-		.bpp = 24,
-		.yuv = true,
-		.lddfr = LDDFR_CC | LDDFR_YF_444,
-	},
-};
-
-static const struct sh_mobile_lcdc_format_info *
-sh_mobile_format_info(u32 fourcc)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) {
-		if (sh_mobile_format_infos[i].fourcc == fourcc)
-			return &sh_mobile_format_infos[i];
-	}
-
-	return NULL;
-}
-
-static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
-{
-	if (var->grayscale > 1)
-		return var->grayscale;
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		return V4L2_PIX_FMT_RGB565;
-	case 24:
-		return V4L2_PIX_FMT_BGR24;
-	case 32:
-		return V4L2_PIX_FMT_BGR32;
-	default:
-		return 0;
-	}
-}
-
-static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
-{
-	return var->grayscale > 1;
-}
-
-/* -----------------------------------------------------------------------------
- * Start, stop and IRQ
- */
-
-static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
-{
-	struct sh_mobile_lcdc_priv *priv = data;
-	struct sh_mobile_lcdc_chan *ch;
-	unsigned long ldintr;
-	int is_sub;
-	int k;
-
-	/* Acknowledge interrupts and disable further VSYNC End IRQs. */
-	ldintr = lcdc_read(priv, _LDINTR);
-	lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
-
-	/* figure out if this interrupt is for main or sub lcd */
-	is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
-
-	/* wake up channel and disable clocks */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		ch = &priv->ch[k];
-
-		if (!ch->enabled)
-			continue;
-
-		/* Frame End */
-		if (ldintr & LDINTR_FS) {
-			if (is_sub == lcdc_chan_is_sublcd(ch)) {
-				ch->frame_end = 1;
-				wake_up(&ch->frame_end_wait);
-
-				sh_mobile_lcdc_clk_off(priv);
-			}
-		}
-
-		/* VSYNC End */
-		if (ldintr & LDINTR_VES)
-			complete(&ch->vsync_completion);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
-{
-	unsigned long ldintr;
-	int ret;
-
-	/* Enable VSync End interrupt and be careful not to acknowledge any
-	 * pending interrupt.
-	 */
-	ldintr = lcdc_read(ch->lcdc, _LDINTR);
-	ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
-	lcdc_write(ch->lcdc, _LDINTR, ldintr);
-
-	ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
-							msecs_to_jiffies(100));
-	if (!ret)
-		return -ETIMEDOUT;
-
-	return 0;
-}
-
-static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
-				      int start)
-{
-	unsigned long tmp = lcdc_read(priv, _LDCNT2R);
-	int k;
-
-	/* start or stop the lcdc */
-	if (start)
-		lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
-	else
-		lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
-
-	/* wait until power is applied/stopped on all channels */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
-		if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
-			while (1) {
-				tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
-				    & LDPMR_LPS;
-				if (start && tmp == LDPMR_LPS)
-					break;
-				if (!start && tmp == 0)
-					break;
-				cpu_relax();
-			}
-
-	if (!start)
-		lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
-}
-
-static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
-{
-	const struct fb_var_screeninfo *var = &ch->info->var;
-	const struct fb_videomode *mode = &ch->display.mode;
-	unsigned long h_total, hsync_pos, display_h_total;
-	u32 tmp;
-
-	tmp = ch->ldmt1r_value;
-	tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
-	tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
-	tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
-	tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
-	tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
-	tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
-	tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
-	lcdc_write_chan(ch, LDMT1R, tmp);
-
-	/* setup SYS bus */
-	lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r);
-	lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r);
-
-	/* horizontal configuration */
-	h_total = mode->xres + mode->hsync_len + mode->left_margin
-		+ mode->right_margin;
-	tmp = h_total / 8; /* HTCN */
-	tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
-	lcdc_write_chan(ch, LDHCNR, tmp);
-
-	hsync_pos = mode->xres + mode->right_margin;
-	tmp = hsync_pos / 8; /* HSYNP */
-	tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */
-	lcdc_write_chan(ch, LDHSYNR, tmp);
-
-	/* vertical configuration */
-	tmp = mode->yres + mode->vsync_len + mode->upper_margin
-	    + mode->lower_margin; /* VTLN */
-	tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
-	lcdc_write_chan(ch, LDVLNR, tmp);
-
-	tmp = mode->yres + mode->lower_margin; /* VSYNP */
-	tmp |= mode->vsync_len << 16; /* VSYNW */
-	lcdc_write_chan(ch, LDVSYNR, tmp);
-
-	/* Adjust horizontal synchronisation for HDMI */
-	display_h_total = mode->xres + mode->hsync_len + mode->left_margin
-			+ mode->right_margin;
-	tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
-	    | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
-	lcdc_write_chan(ch, LDHAJR, tmp);
-	lcdc_write_chan_mirror(ch, LDHAJR, tmp);
-}
-
-static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
-{
-	u32 format = 0;
-
-	if (!ovl->enabled) {
-		lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
-		lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0);
-		lcdc_write(ovl->channel->lcdc, LDBCR,
-			   LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
-		return;
-	}
-
-	ovl->base_addr_y = ovl->dma_handle;
-	ovl->base_addr_c = ovl->dma_handle
-			 + ovl->xres_virtual * ovl->yres_virtual;
-
-	switch (ovl->mode) {
-	case LCDC_OVERLAY_BLEND:
-		format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT);
-		break;
-
-	case LCDC_OVERLAY_ROP3:
-		format = LDBBSIFR_EN | LDBBSIFR_BRSEL
-		       | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT);
-		break;
-	}
-
-	switch (ovl->format->fourcc) {
-	case V4L2_PIX_FMT_RGB565:
-	case V4L2_PIX_FMT_NV21:
-	case V4L2_PIX_FMT_NV61:
-	case V4L2_PIX_FMT_NV42:
-		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
-		break;
-	case V4L2_PIX_FMT_BGR24:
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_NV16:
-	case V4L2_PIX_FMT_NV24:
-		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
-		break;
-	case V4L2_PIX_FMT_BGR32:
-	default:
-		format |= LDBBSIFR_SWPL;
-		break;
-	}
-
-	switch (ovl->format->fourcc) {
-	case V4L2_PIX_FMT_RGB565:
-		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
-		break;
-	case V4L2_PIX_FMT_BGR24:
-		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
-		break;
-	case V4L2_PIX_FMT_BGR32:
-		format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
-		break;
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_NV21:
-		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
-		break;
-	case V4L2_PIX_FMT_NV16:
-	case V4L2_PIX_FMT_NV61:
-		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
-		break;
-	case V4L2_PIX_FMT_NV24:
-	case V4L2_PIX_FMT_NV42:
-		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
-		break;
-	}
-
-	lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
-
-	lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format);
-
-	lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index),
-		(ovl->yres << LDBBSSZR_BVSS_SHIFT) |
-		(ovl->xres << LDBBSSZR_BHSS_SHIFT));
-	lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index),
-		(ovl->pos_y << LDBBLOCR_CVLC_SHIFT) |
-		(ovl->pos_x << LDBBLOCR_CHLC_SHIFT));
-	lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index),
-		ovl->pitch << LDBBSMWR_BSMW_SHIFT);
-
-	lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
-	lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
-
-	lcdc_write(ovl->channel->lcdc, LDBCR,
-		   LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
-}
-
-/*
- * __sh_mobile_lcdc_start - Configure and start the LCDC
- * @priv: LCDC device
- *
- * Configure all enabled channels and start the LCDC device. All external
- * devices (clocks, MERAM, panels, ...) are not touched by this function.
- */
-static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
-{
-	struct sh_mobile_lcdc_chan *ch;
-	unsigned long tmp;
-	int k, m;
-
-	/* Enable LCDC channels. Read data from external memory, avoid using the
-	 * BEU for now.
-	 */
-	lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
-
-	/* Stop the LCDC first and disable all interrupts. */
-	sh_mobile_lcdc_start_stop(priv, 0);
-	lcdc_write(priv, _LDINTR, 0);
-
-	/* Configure power supply, dot clocks and start them. */
-	tmp = priv->lddckr;
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		ch = &priv->ch[k];
-		if (!ch->enabled)
-			continue;
-
-		/* Power supply */
-		lcdc_write_chan(ch, LDPMR, 0);
-
-		m = ch->cfg->clock_divider;
-		if (!m)
-			continue;
-
-		/* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
-		 * denominator.
-		 */
-		lcdc_write_chan(ch, LDDCKPAT1R, 0);
-		lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
-
-		if (m == 1)
-			m = LDDCKR_MOSEL;
-		tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
-	}
-
-	lcdc_write(priv, _LDDCKR, tmp);
-	lcdc_write(priv, _LDDCKSTPR, 0);
-	lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
-
-	/* Setup geometry, format, frame buffer memory and operation mode. */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		ch = &priv->ch[k];
-		if (!ch->enabled)
-			continue;
-
-		sh_mobile_lcdc_geometry(ch);
-
-		tmp = ch->format->lddfr;
-
-		if (ch->format->yuv) {
-			switch (ch->colorspace) {
-			case V4L2_COLORSPACE_REC709:
-				tmp |= LDDFR_CF1;
-				break;
-			case V4L2_COLORSPACE_JPEG:
-				tmp |= LDDFR_CF0;
-				break;
-			}
-		}
-
-		lcdc_write_chan(ch, LDDFR, tmp);
-		lcdc_write_chan(ch, LDMLSR, ch->line_size);
-		lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
-		if (ch->format->yuv)
-			lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
-
-		/* When using deferred I/O mode, configure the LCDC for one-shot
-		 * operation and enable the frame end interrupt. Otherwise use
-		 * continuous read mode.
-		 */
-		if (ch->ldmt1r_value & LDMT1R_IFM &&
-		    ch->cfg->sys_bus_cfg.deferred_io_msec) {
-			lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
-			lcdc_write(priv, _LDINTR, LDINTR_FE);
-		} else {
-			lcdc_write_chan(ch, LDSM1R, 0);
-		}
-	}
-
-	/* Word and long word swap. */
-	switch (priv->ch[0].format->fourcc) {
-	case V4L2_PIX_FMT_RGB565:
-	case V4L2_PIX_FMT_NV21:
-	case V4L2_PIX_FMT_NV61:
-	case V4L2_PIX_FMT_NV42:
-		tmp = LDDDSR_LS | LDDDSR_WS;
-		break;
-	case V4L2_PIX_FMT_BGR24:
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_NV16:
-	case V4L2_PIX_FMT_NV24:
-		tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
-		break;
-	case V4L2_PIX_FMT_BGR32:
-	default:
-		tmp = LDDDSR_LS;
-		break;
-	}
-	lcdc_write(priv, _LDDDSR, tmp);
-
-	/* Enable the display output. */
-	lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
-	sh_mobile_lcdc_start_stop(priv, 1);
-	priv->started = 1;
-}
-
-static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
-{
-	struct sh_mobile_meram_info *mdev = priv->meram_dev;
-	struct sh_mobile_lcdc_chan *ch;
-	unsigned long tmp;
-	int ret;
-	int k;
-
-	/* enable clocks before accessing the hardware */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		if (priv->ch[k].enabled)
-			sh_mobile_lcdc_clk_on(priv);
-	}
-
-	/* reset */
-	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
-	lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
-
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		const struct sh_mobile_lcdc_panel_cfg *panel;
-
-		ch = &priv->ch[k];
-		if (!ch->enabled)
-			continue;
-
-		panel = &ch->cfg->panel_cfg;
-		if (panel->setup_sys) {
-			ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops);
-			if (ret)
-				return ret;
-		}
-	}
-
-	/* Compute frame buffer base address and pitch for each channel. */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		int pixelformat;
-		void *cache;
-
-		ch = &priv->ch[k];
-		if (!ch->enabled)
-			continue;
-
-		ch->base_addr_y = ch->dma_handle;
-		ch->base_addr_c = ch->dma_handle
-				+ ch->xres_virtual * ch->yres_virtual;
-		ch->line_size = ch->pitch;
-
-		/* Enable MERAM if possible. */
-		if (mdev == NULL || ch->cfg->meram_cfg == NULL)
-			continue;
-
-		/* Free the allocated MERAM cache. */
-		if (ch->cache) {
-			sh_mobile_meram_cache_free(mdev, ch->cache);
-			ch->cache = NULL;
-		}
-
-		switch (ch->format->fourcc) {
-		case V4L2_PIX_FMT_NV12:
-		case V4L2_PIX_FMT_NV21:
-		case V4L2_PIX_FMT_NV16:
-		case V4L2_PIX_FMT_NV61:
-			pixelformat = SH_MOBILE_MERAM_PF_NV;
-			break;
-		case V4L2_PIX_FMT_NV24:
-		case V4L2_PIX_FMT_NV42:
-			pixelformat = SH_MOBILE_MERAM_PF_NV24;
-			break;
-		case V4L2_PIX_FMT_RGB565:
-		case V4L2_PIX_FMT_BGR24:
-		case V4L2_PIX_FMT_BGR32:
-		default:
-			pixelformat = SH_MOBILE_MERAM_PF_RGB;
-			break;
-		}
-
-		cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
-					ch->pitch, ch->yres, pixelformat,
-					&ch->line_size);
-		if (!IS_ERR(cache)) {
-			sh_mobile_meram_cache_update(mdev, cache,
-					ch->base_addr_y, ch->base_addr_c,
-					&ch->base_addr_y, &ch->base_addr_c);
-			ch->cache = cache;
-		}
-	}
-
-	for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) {
-		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k];
-		sh_mobile_lcdc_overlay_setup(ovl);
-	}
-
-	/* Start the LCDC. */
-	__sh_mobile_lcdc_start(priv);
-
-	/* Setup deferred I/O, tell the board code to enable the panels, and
-	 * turn backlight on.
-	 */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		ch = &priv->ch[k];
-		if (!ch->enabled)
-			continue;
-
-		tmp = ch->cfg->sys_bus_cfg.deferred_io_msec;
-		if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
-			ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
-			ch->defio.delay = msecs_to_jiffies(tmp);
-			ch->info->fbdefio = &ch->defio;
-			fb_deferred_io_init(ch->info);
-		}
-
-		sh_mobile_lcdc_display_on(ch);
-
-		if (ch->bl) {
-			ch->bl->props.power = FB_BLANK_UNBLANK;
-			backlight_update_status(ch->bl);
-		}
-	}
-
-	return 0;
-}
-
-static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
-{
-	struct sh_mobile_lcdc_chan *ch;
-	int k;
-
-	/* clean up deferred io and ask board code to disable panel */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-		ch = &priv->ch[k];
-		if (!ch->enabled)
-			continue;
-
-		/* deferred io mode:
-		 * flush frame, and wait for frame end interrupt
-		 * clean up deferred io and enable clock
-		 */
-		if (ch->info && ch->info->fbdefio) {
-			ch->frame_end = 0;
-			schedule_delayed_work(&ch->info->deferred_work, 0);
-			wait_event(ch->frame_end_wait, ch->frame_end);
-			fb_deferred_io_cleanup(ch->info);
-			ch->info->fbdefio = NULL;
-			sh_mobile_lcdc_clk_on(priv);
-		}
-
-		if (ch->bl) {
-			ch->bl->props.power = FB_BLANK_POWERDOWN;
-			backlight_update_status(ch->bl);
-		}
-
-		sh_mobile_lcdc_display_off(ch);
-
-		/* Free the MERAM cache. */
-		if (ch->cache) {
-			sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
-			ch->cache = NULL;
-		}
-
-	}
-
-	/* stop the lcdc */
-	if (priv->started) {
-		sh_mobile_lcdc_start_stop(priv, 0);
-		priv->started = 0;
-	}
-
-	/* stop clocks */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
-		if (priv->ch[k].enabled)
-			sh_mobile_lcdc_clk_off(priv);
-}
-
-static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
-				      struct fb_info *info)
-{
-	if (var->xres > MAX_XRES || var->yres > MAX_YRES)
-		return -EINVAL;
-
-	/* Make sure the virtual resolution is at least as big as the visible
-	 * resolution.
-	 */
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
-	if (sh_mobile_format_is_fourcc(var)) {
-		const struct sh_mobile_lcdc_format_info *format;
-
-		format = sh_mobile_format_info(var->grayscale);
-		if (format == NULL)
-			return -EINVAL;
-		var->bits_per_pixel = format->bpp;
-
-		/* Default to RGB and JPEG color-spaces for RGB and YUV formats
-		 * respectively.
-		 */
-		if (!format->yuv)
-			var->colorspace = V4L2_COLORSPACE_SRGB;
-		else if (var->colorspace != V4L2_COLORSPACE_REC709)
-			var->colorspace = V4L2_COLORSPACE_JPEG;
-	} else {
-		if (var->bits_per_pixel <= 16) {		/* RGB 565 */
-			var->bits_per_pixel = 16;
-			var->red.offset = 11;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 6;
-			var->blue.offset = 0;
-			var->blue.length = 5;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-		} else if (var->bits_per_pixel <= 24) {		/* RGB 888 */
-			var->bits_per_pixel = 24;
-			var->red.offset = 16;
-			var->red.length = 8;
-			var->green.offset = 8;
-			var->green.length = 8;
-			var->blue.offset = 0;
-			var->blue.length = 8;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-		} else if (var->bits_per_pixel <= 32) {		/* RGBA 888 */
-			var->bits_per_pixel = 32;
-			var->red.offset = 16;
-			var->red.length = 8;
-			var->green.offset = 8;
-			var->green.length = 8;
-			var->blue.offset = 0;
-			var->blue.length = 8;
-			var->transp.offset = 24;
-			var->transp.length = 8;
-		} else
-			return -EINVAL;
-
-		var->red.msb_right = 0;
-		var->green.msb_right = 0;
-		var->blue.msb_right = 0;
-		var->transp.msb_right = 0;
-	}
-
-	/* Make sure we don't exceed our allocated memory. */
-	if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
-	    info->fix.smem_len)
-		return -EINVAL;
-
-	return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Frame buffer operations - Overlays
- */
-
-static ssize_t
-overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha);
-}
-
-static ssize_t
-overlay_alpha_store(struct device *dev, struct device_attribute *attr,
-		    const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-	unsigned int alpha;
-	char *endp;
-
-	alpha = simple_strtoul(buf, &endp, 10);
-	if (isspace(*endp))
-		endp++;
-
-	if (endp - buf != count)
-		return -EINVAL;
-
-	if (alpha > 255)
-		return -EINVAL;
-
-	if (ovl->alpha != alpha) {
-		ovl->alpha = alpha;
-
-		if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled)
-			sh_mobile_lcdc_overlay_setup(ovl);
-	}
-
-	return count;
-}
-
-static ssize_t
-overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode);
-}
-
-static ssize_t
-overlay_mode_store(struct device *dev, struct device_attribute *attr,
-		   const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-	unsigned int mode;
-	char *endp;
-
-	mode = simple_strtoul(buf, &endp, 10);
-	if (isspace(*endp))
-		endp++;
-
-	if (endp - buf != count)
-		return -EINVAL;
-
-	if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3)
-		return -EINVAL;
-
-	if (ovl->mode != mode) {
-		ovl->mode = mode;
-
-		if (ovl->enabled)
-			sh_mobile_lcdc_overlay_setup(ovl);
-	}
-
-	return count;
-}
-
-static ssize_t
-overlay_position_show(struct device *dev, struct device_attribute *attr,
-		      char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y);
-}
-
-static ssize_t
-overlay_position_store(struct device *dev, struct device_attribute *attr,
-		       const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-	char *endp;
-	int pos_x;
-	int pos_y;
-
-	pos_x = simple_strtol(buf, &endp, 10);
-	if (*endp != ',')
-		return -EINVAL;
-
-	pos_y = simple_strtol(endp + 1, &endp, 10);
-	if (isspace(*endp))
-		endp++;
-
-	if (endp - buf != count)
-		return -EINVAL;
-
-	if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) {
-		ovl->pos_x = pos_x;
-		ovl->pos_y = pos_y;
-
-		if (ovl->enabled)
-			sh_mobile_lcdc_overlay_setup(ovl);
-	}
-
-	return count;
-}
-
-static ssize_t
-overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3);
-}
-
-static ssize_t
-overlay_rop3_store(struct device *dev, struct device_attribute *attr,
-		    const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-	unsigned int rop3;
-	char *endp;
-
-	rop3 = !!simple_strtoul(buf, &endp, 10);
-	if (isspace(*endp))
-		endp++;
-
-	if (endp - buf != count)
-		return -EINVAL;
-
-	if (rop3 > 255)
-		return -EINVAL;
-
-	if (ovl->rop3 != rop3) {
-		ovl->rop3 = rop3;
-
-		if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled)
-			sh_mobile_lcdc_overlay_setup(ovl);
-	}
-
-	return count;
-}
-
-static const struct device_attribute overlay_sysfs_attrs[] = {
-	__ATTR(ovl_alpha, S_IRUGO|S_IWUSR,
-	       overlay_alpha_show, overlay_alpha_store),
-	__ATTR(ovl_mode, S_IRUGO|S_IWUSR,
-	       overlay_mode_show, overlay_mode_store),
-	__ATTR(ovl_position, S_IRUGO|S_IWUSR,
-	       overlay_position_show, overlay_position_store),
-	__ATTR(ovl_rop3, S_IRUGO|S_IWUSR,
-	       overlay_rop3_show, overlay_rop3_store),
-};
-
-static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix  = {
-	.id =		"SH Mobile LCDC",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.accel =	FB_ACCEL_NONE,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	0,
-	.capabilities =	FB_CAP_FOURCC,
-};
-
-static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
-				    struct fb_info *info)
-{
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-	unsigned long base_addr_y;
-	unsigned long base_addr_c;
-	unsigned long y_offset;
-	unsigned long c_offset;
-
-	if (!ovl->format->yuv) {
-		y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset)
-			 * ovl->format->bpp / 8;
-		c_offset = 0;
-	} else {
-		unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1;
-		unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1;
-
-		y_offset = var->yoffset * ovl->xres_virtual + var->xoffset;
-		c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub
-			 + var->xoffset * 2 / xsub;
-	}
-
-	/* If the Y offset hasn't changed, the C offset hasn't either. There's
-	 * nothing to do in that case.
-	 */
-	if (y_offset == ovl->pan_y_offset)
-		return 0;
-
-	/* Set the source address for the next refresh */
-	base_addr_y = ovl->dma_handle + y_offset;
-	base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual
-		    + c_offset;
-
-	ovl->base_addr_y = base_addr_y;
-	ovl->base_addr_c = base_addr_c;
-	ovl->pan_y_offset = y_offset;
-
-	lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
-
-	lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
-	lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
-
-	lcdc_write(ovl->channel->lcdc, LDBCR,
-		   LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
-
-	return 0;
-}
-
-static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd,
-				      unsigned long arg)
-{
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	switch (cmd) {
-	case FBIO_WAITFORVSYNC:
-		return sh_mobile_lcdc_wait_for_vsync(ovl->channel);
-
-	default:
-		return -ENOIOCTLCMD;
-	}
-}
-
-static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var,
-					  struct fb_info *info)
-{
-	return __sh_mobile_lcdc_check_var(var, info);
-}
-
-static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
-{
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	ovl->format =
-		sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
-
-	ovl->xres = info->var.xres;
-	ovl->xres_virtual = info->var.xres_virtual;
-	ovl->yres = info->var.yres;
-	ovl->yres_virtual = info->var.yres_virtual;
-
-	if (ovl->format->yuv)
-		ovl->pitch = info->var.xres_virtual;
-	else
-		ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8;
-
-	sh_mobile_lcdc_overlay_setup(ovl);
-
-	info->fix.line_length = ovl->pitch;
-
-	if (sh_mobile_format_is_fourcc(&info->var)) {
-		info->fix.type = FB_TYPE_FOURCC;
-		info->fix.visual = FB_VISUAL_FOURCC;
-	} else {
-		info->fix.type = FB_TYPE_PACKED_PIXELS;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	}
-
-	return 0;
-}
-
-/* Overlay blanking. Disable the overlay when blanked. */
-static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
-{
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	ovl->enabled = !blank;
-	sh_mobile_lcdc_overlay_setup(ovl);
-
-	/* Prevent the backlight from receiving a blanking event by returning
-	 * a non-zero value.
-	 */
-	return 1;
-}
-
-static int
-sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct sh_mobile_lcdc_overlay *ovl = info->par;
-
-	return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
-				 ovl->dma_handle, ovl->fb_size);
-}
-
-static struct fb_ops sh_mobile_lcdc_overlay_ops = {
-	.owner          = THIS_MODULE,
-	.fb_read        = fb_sys_read,
-	.fb_write       = fb_sys_write,
-	.fb_fillrect	= sys_fillrect,
-	.fb_copyarea	= sys_copyarea,
-	.fb_imageblit	= sys_imageblit,
-	.fb_blank	= sh_mobile_lcdc_overlay_blank,
-	.fb_pan_display = sh_mobile_lcdc_overlay_pan,
-	.fb_ioctl       = sh_mobile_lcdc_overlay_ioctl,
-	.fb_check_var	= sh_mobile_lcdc_overlay_check_var,
-	.fb_set_par	= sh_mobile_lcdc_overlay_set_par,
-	.fb_mmap	= sh_mobile_lcdc_overlay_mmap,
-};
-
-static void
-sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl)
-{
-	struct fb_info *info = ovl->info;
-
-	if (info == NULL || info->dev == NULL)
-		return;
-
-	unregister_framebuffer(ovl->info);
-}
-
-static int
-sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl)
-{
-	struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc;
-	struct fb_info *info = ovl->info;
-	unsigned int i;
-	int ret;
-
-	if (info == NULL)
-		return 0;
-
-	ret = register_framebuffer(info);
-	if (ret < 0)
-		return ret;
-
-	dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n",
-		 dev_name(lcdc->dev), ovl->index, info->var.xres,
-		 info->var.yres, info->var.bits_per_pixel);
-
-	for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) {
-		ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static void
-sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl)
-{
-	struct fb_info *info = ovl->info;
-
-	if (info == NULL || info->device == NULL)
-		return;
-
-	framebuffer_release(info);
-}
-
-static int
-sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
-{
-	struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc;
-	struct fb_var_screeninfo *var;
-	struct fb_info *info;
-
-	/* Allocate and initialize the frame buffer device. */
-	info = framebuffer_alloc(0, priv->dev);
-	if (info == NULL) {
-		dev_err(priv->dev, "unable to allocate fb_info\n");
-		return -ENOMEM;
-	}
-
-	ovl->info = info;
-
-	info->flags = FBINFO_FLAG_DEFAULT;
-	info->fbops = &sh_mobile_lcdc_overlay_ops;
-	info->device = priv->dev;
-	info->screen_base = ovl->fb_mem;
-	info->par = ovl;
-
-	/* Initialize fixed screen information. Restrict pan to 2 lines steps
-	 * for NV12 and NV21.
-	 */
-	info->fix = sh_mobile_lcdc_overlay_fix;
-	snprintf(info->fix.id, sizeof(info->fix.id),
-		 "SH Mobile LCDC Overlay %u", ovl->index);
-	info->fix.smem_start = ovl->dma_handle;
-	info->fix.smem_len = ovl->fb_size;
-	info->fix.line_length = ovl->pitch;
-
-	if (ovl->format->yuv)
-		info->fix.visual = FB_VISUAL_FOURCC;
-	else
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	switch (ovl->format->fourcc) {
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_NV21:
-		info->fix.ypanstep = 2;
-	case V4L2_PIX_FMT_NV16:
-	case V4L2_PIX_FMT_NV61:
-		info->fix.xpanstep = 2;
-	}
-
-	/* Initialize variable screen information. */
-	var = &info->var;
-	memset(var, 0, sizeof(*var));
-	var->xres = ovl->xres;
-	var->yres = ovl->yres;
-	var->xres_virtual = ovl->xres_virtual;
-	var->yres_virtual = ovl->yres_virtual;
-	var->activate = FB_ACTIVATE_NOW;
-
-	/* Use the legacy API by default for RGB formats, and the FOURCC API
-	 * for YUV formats.
-	 */
-	if (!ovl->format->yuv)
-		var->bits_per_pixel = ovl->format->bpp;
-	else
-		var->grayscale = ovl->format->fourcc;
-
-	return sh_mobile_lcdc_overlay_check_var(var, info);
-}
-
-/* -----------------------------------------------------------------------------
- * Frame buffer operations - main frame buffer
- */
-
-static int sh_mobile_lcdc_setcolreg(u_int regno,
-				    u_int red, u_int green, u_int blue,
-				    u_int transp, struct fb_info *info)
-{
-	u32 *palette = info->pseudo_palette;
-
-	if (regno >= PALETTE_NR)
-		return -EINVAL;
-
-	/* only FB_VISUAL_TRUECOLOR supported */
-
-	red >>= 16 - info->var.red.length;
-	green >>= 16 - info->var.green.length;
-	blue >>= 16 - info->var.blue.length;
-	transp >>= 16 - info->var.transp.length;
-
-	palette[regno] = (red << info->var.red.offset) |
-	  (green << info->var.green.offset) |
-	  (blue << info->var.blue.offset) |
-	  (transp << info->var.transp.offset);
-
-	return 0;
-}
-
-static const struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
-	.id =		"SH Mobile LCDC",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.accel =	FB_ACCEL_NONE,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	0,
-	.capabilities =	FB_CAP_FOURCC,
-};
-
-static void sh_mobile_lcdc_fillrect(struct fb_info *info,
-				    const struct fb_fillrect *rect)
-{
-	sys_fillrect(info, rect);
-	sh_mobile_lcdc_deferred_io_touch(info);
-}
-
-static void sh_mobile_lcdc_copyarea(struct fb_info *info,
-				    const struct fb_copyarea *area)
-{
-	sys_copyarea(info, area);
-	sh_mobile_lcdc_deferred_io_touch(info);
-}
-
-static void sh_mobile_lcdc_imageblit(struct fb_info *info,
-				     const struct fb_image *image)
-{
-	sys_imageblit(info, image);
-	sh_mobile_lcdc_deferred_io_touch(info);
-}
-
-static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
-	unsigned long ldrcntr;
-	unsigned long base_addr_y, base_addr_c;
-	unsigned long y_offset;
-	unsigned long c_offset;
-
-	if (!ch->format->yuv) {
-		y_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
-			 * ch->format->bpp / 8;
-		c_offset = 0;
-	} else {
-		unsigned int xsub = ch->format->bpp < 24 ? 2 : 1;
-		unsigned int ysub = ch->format->bpp < 16 ? 2 : 1;
-
-		y_offset = var->yoffset * ch->xres_virtual + var->xoffset;
-		c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub
-			 + var->xoffset * 2 / xsub;
-	}
-
-	/* If the Y offset hasn't changed, the C offset hasn't either. There's
-	 * nothing to do in that case.
-	 */
-	if (y_offset == ch->pan_y_offset)
-		return 0;
-
-	/* Set the source address for the next refresh */
-	base_addr_y = ch->dma_handle + y_offset;
-	base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
-		    + c_offset;
-
-	if (ch->cache)
-		sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
-					     base_addr_y, base_addr_c,
-					     &base_addr_y, &base_addr_c);
-
-	ch->base_addr_y = base_addr_y;
-	ch->base_addr_c = base_addr_c;
-	ch->pan_y_offset = y_offset;
-
-	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
-	if (ch->format->yuv)
-		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
-
-	ldrcntr = lcdc_read(priv, _LDRCNTR);
-	if (lcdc_chan_is_sublcd(ch))
-		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
-	else
-		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
-
-
-	sh_mobile_lcdc_deferred_io_touch(info);
-
-	return 0;
-}
-
-static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd,
-				unsigned long arg)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	int retval;
-
-	switch (cmd) {
-	case FBIO_WAITFORVSYNC:
-		retval = sh_mobile_lcdc_wait_for_vsync(ch);
-		break;
-
-	default:
-		retval = -ENOIOCTLCMD;
-		break;
-	}
-	return retval;
-}
-
-static void sh_mobile_fb_reconfig(struct fb_info *info)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	struct fb_var_screeninfo var;
-	struct fb_videomode mode;
-	struct fb_event event;
-	int evnt = FB_EVENT_MODE_CHANGE_ALL;
-
-	if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
-		/* More framebuffer users are active */
-		return;
-
-	fb_var_to_videomode(&mode, &info->var);
-
-	if (fb_mode_is_equal(&ch->display.mode, &mode))
-		return;
-
-	/* Display has been re-plugged, framebuffer is free now, reconfigure */
-	var = info->var;
-	fb_videomode_to_var(&var, &ch->display.mode);
-	var.width = ch->display.width;
-	var.height = ch->display.height;
-	var.activate = FB_ACTIVATE_NOW;
-
-	if (fb_set_var(info, &var) < 0)
-		/* Couldn't reconfigure, hopefully, can continue as before */
-		return;
-
-	/*
-	 * fb_set_var() calls the notifier change internally, only if
-	 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
-	 * user event, we have to call the chain ourselves.
-	 */
-	event.info = info;
-	event.data = &ch->display.mode;
-	fb_notifier_call_chain(evnt, &event);
-}
-
-/*
- * Locking: both .fb_release() and .fb_open() are called with info->lock held if
- * user == 1, or with console sem held, if user == 0.
- */
-static int sh_mobile_lcdc_release(struct fb_info *info, int user)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-
-	mutex_lock(&ch->open_lock);
-	dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
-
-	ch->use_count--;
-
-	/* Nothing to reconfigure, when called from fbcon */
-	if (user) {
-		console_lock();
-		sh_mobile_fb_reconfig(info);
-		console_unlock();
-	}
-
-	mutex_unlock(&ch->open_lock);
-
-	return 0;
-}
-
-static int sh_mobile_lcdc_open(struct fb_info *info, int user)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-
-	mutex_lock(&ch->open_lock);
-	ch->use_count++;
-
-	dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
-	mutex_unlock(&ch->open_lock);
-
-	return 0;
-}
-
-static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
-				    struct fb_info *info)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	struct sh_mobile_lcdc_priv *p = ch->lcdc;
-	unsigned int best_dist = (unsigned int)-1;
-	unsigned int best_xres = 0;
-	unsigned int best_yres = 0;
-	unsigned int i;
-	int ret;
-
-	/* If board code provides us with a list of available modes, make sure
-	 * we use one of them. Find the mode closest to the requested one. The
-	 * distance between two modes is defined as the size of the
-	 * non-overlapping parts of the two rectangles.
-	 */
-	for (i = 0; i < ch->cfg->num_modes; ++i) {
-		const struct fb_videomode *mode = &ch->cfg->lcd_modes[i];
-		unsigned int dist;
-
-		/* We can only round up. */
-		if (var->xres > mode->xres || var->yres > mode->yres)
-			continue;
-
-		dist = var->xres * var->yres + mode->xres * mode->yres
-		     - 2 * min(var->xres, mode->xres)
-			 * min(var->yres, mode->yres);
-
-		if (dist < best_dist) {
-			best_xres = mode->xres;
-			best_yres = mode->yres;
-			best_dist = dist;
-		}
-	}
-
-	/* If no available mode can be used, return an error. */
-	if (ch->cfg->num_modes != 0) {
-		if (best_dist == (unsigned int)-1)
-			return -EINVAL;
-
-		var->xres = best_xres;
-		var->yres = best_yres;
-	}
-
-	ret = __sh_mobile_lcdc_check_var(var, info);
-	if (ret < 0)
-		return ret;
-
-	/* only accept the forced_fourcc for dual channel configurations */
-	if (p->forced_fourcc &&
-	    p->forced_fourcc != sh_mobile_format_fourcc(var))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int sh_mobile_lcdc_set_par(struct fb_info *info)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	int ret;
-
-	sh_mobile_lcdc_stop(ch->lcdc);
-
-	ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
-	ch->colorspace = info->var.colorspace;
-
-	ch->xres = info->var.xres;
-	ch->xres_virtual = info->var.xres_virtual;
-	ch->yres = info->var.yres;
-	ch->yres_virtual = info->var.yres_virtual;
-
-	if (ch->format->yuv)
-		ch->pitch = info->var.xres_virtual;
-	else
-		ch->pitch = info->var.xres_virtual * ch->format->bpp / 8;
-
-	ret = sh_mobile_lcdc_start(ch->lcdc);
-	if (ret < 0)
-		dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
-
-	info->fix.line_length = ch->pitch;
-
-	if (sh_mobile_format_is_fourcc(&info->var)) {
-		info->fix.type = FB_TYPE_FOURCC;
-		info->fix.visual = FB_VISUAL_FOURCC;
-	} else {
-		info->fix.type = FB_TYPE_PACKED_PIXELS;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	}
-
-	return ret;
-}
-
-/*
- * Screen blanking. Behavior is as follows:
- * FB_BLANK_UNBLANK: screen unblanked, clocks enabled
- * FB_BLANK_NORMAL: screen blanked, clocks enabled
- * FB_BLANK_VSYNC,
- * FB_BLANK_HSYNC,
- * FB_BLANK_POWEROFF: screen blanked, clocks disabled
- */
-static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-	struct sh_mobile_lcdc_priv *p = ch->lcdc;
-
-	/* blank the screen? */
-	if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
-		struct fb_fillrect rect = {
-			.width = ch->xres,
-			.height = ch->yres,
-		};
-		sh_mobile_lcdc_fillrect(info, &rect);
-	}
-	/* turn clocks on? */
-	if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) {
-		sh_mobile_lcdc_clk_on(p);
-	}
-	/* turn clocks off? */
-	if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) {
-		/* make sure the screen is updated with the black fill before
-		 * switching the clocks off. one vsync is not enough since
-		 * blanking may occur in the middle of a refresh. deferred io
-		 * mode will reenable the clocks and update the screen in time,
-		 * so it does not need this. */
-		if (!info->fbdefio) {
-			sh_mobile_lcdc_wait_for_vsync(ch);
-			sh_mobile_lcdc_wait_for_vsync(ch);
-		}
-		sh_mobile_lcdc_clk_off(p);
-	}
-
-	ch->blank_status = blank;
-	return 0;
-}
-
-static int
-sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct sh_mobile_lcdc_chan *ch = info->par;
-
-	return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
-				 ch->dma_handle, ch->fb_size);
-}
-
-static struct fb_ops sh_mobile_lcdc_ops = {
-	.owner          = THIS_MODULE,
-	.fb_setcolreg	= sh_mobile_lcdc_setcolreg,
-	.fb_read        = fb_sys_read,
-	.fb_write       = fb_sys_write,
-	.fb_fillrect	= sh_mobile_lcdc_fillrect,
-	.fb_copyarea	= sh_mobile_lcdc_copyarea,
-	.fb_imageblit	= sh_mobile_lcdc_imageblit,
-	.fb_blank	= sh_mobile_lcdc_blank,
-	.fb_pan_display = sh_mobile_lcdc_pan,
-	.fb_ioctl       = sh_mobile_lcdc_ioctl,
-	.fb_open	= sh_mobile_lcdc_open,
-	.fb_release	= sh_mobile_lcdc_release,
-	.fb_check_var	= sh_mobile_lcdc_check_var,
-	.fb_set_par	= sh_mobile_lcdc_set_par,
-	.fb_mmap	= sh_mobile_lcdc_mmap,
-};
-
-static void
-sh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch)
-{
-	if (ch->info && ch->info->dev)
-		unregister_framebuffer(ch->info);
-}
-
-static int
-sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
-{
-	struct fb_info *info = ch->info;
-	int ret;
-
-	if (info->fbdefio) {
-		ch->sglist = vmalloc(sizeof(struct scatterlist) *
-				     ch->fb_size >> PAGE_SHIFT);
-		if (!ch->sglist) {
-			dev_err(ch->lcdc->dev, "cannot allocate sglist\n");
-			return -ENOMEM;
-		}
-	}
-
-	info->bl_dev = ch->bl;
-
-	ret = register_framebuffer(info);
-	if (ret < 0)
-		return ret;
-
-	dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n",
-		 dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ?
-		 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
-		 info->var.bits_per_pixel);
-
-	/* deferred io mode: disable clock to save power */
-	if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
-		sh_mobile_lcdc_clk_off(ch->lcdc);
-
-	return ret;
-}
-
-static void
-sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
-{
-	struct fb_info *info = ch->info;
-
-	if (!info || !info->device)
-		return;
-
-	if (ch->sglist)
-		vfree(ch->sglist);
-
-	fb_dealloc_cmap(&info->cmap);
-	framebuffer_release(info);
-}
-
-static int
-sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
-			       const struct fb_videomode *modes,
-			       unsigned int num_modes)
-{
-	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
-	struct fb_var_screeninfo *var;
-	struct fb_info *info;
-	int ret;
-
-	/* Allocate and initialize the frame buffer device. Create the modes
-	 * list and allocate the color map.
-	 */
-	info = framebuffer_alloc(0, priv->dev);
-	if (info == NULL) {
-		dev_err(priv->dev, "unable to allocate fb_info\n");
-		return -ENOMEM;
-	}
-
-	ch->info = info;
-
-	info->flags = FBINFO_FLAG_DEFAULT;
-	info->fbops = &sh_mobile_lcdc_ops;
-	info->device = priv->dev;
-	info->screen_base = ch->fb_mem;
-	info->pseudo_palette = &ch->pseudo_palette;
-	info->par = ch;
-
-	fb_videomode_to_modelist(modes, num_modes, &info->modelist);
-
-	ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
-	if (ret < 0) {
-		dev_err(priv->dev, "unable to allocate cmap\n");
-		return ret;
-	}
-
-	/* Initialize fixed screen information. Restrict pan to 2 lines steps
-	 * for NV12 and NV21.
-	 */
-	info->fix = sh_mobile_lcdc_fix;
-	info->fix.smem_start = ch->dma_handle;
-	info->fix.smem_len = ch->fb_size;
-	info->fix.line_length = ch->pitch;
-
-	if (ch->format->yuv)
-		info->fix.visual = FB_VISUAL_FOURCC;
-	else
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-	switch (ch->format->fourcc) {
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_NV21:
-		info->fix.ypanstep = 2;
-	case V4L2_PIX_FMT_NV16:
-	case V4L2_PIX_FMT_NV61:
-		info->fix.xpanstep = 2;
-	}
-
-	/* Initialize variable screen information using the first mode as
-	 * default.
-	 */
-	var = &info->var;
-	fb_videomode_to_var(var, modes);
-	var->width = ch->display.width;
-	var->height = ch->display.height;
-	var->xres_virtual = ch->xres_virtual;
-	var->yres_virtual = ch->yres_virtual;
-	var->activate = FB_ACTIVATE_NOW;
-
-	/* Use the legacy API by default for RGB formats, and the FOURCC API
-	 * for YUV formats.
-	 */
-	if (!ch->format->yuv)
-		var->bits_per_pixel = ch->format->bpp;
-	else
-		var->grayscale = ch->format->fourcc;
-
-	ret = sh_mobile_lcdc_check_var(var, info);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Backlight
- */
-
-static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
-{
-	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
-	int brightness = bdev->props.brightness;
-
-	if (bdev->props.power != FB_BLANK_UNBLANK ||
-	    bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
-		brightness = 0;
-
-	ch->bl_brightness = brightness;
-	return ch->cfg->bl_info.set_brightness(brightness);
-}
-
-static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
-{
-	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
-
-	return ch->bl_brightness;
-}
-
-static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
-				   struct fb_info *info)
-{
-	return (info->bl_dev == bdev);
-}
-
-static struct backlight_ops sh_mobile_lcdc_bl_ops = {
-	.options	= BL_CORE_SUSPENDRESUME,
-	.update_status	= sh_mobile_lcdc_update_bl,
-	.get_brightness	= sh_mobile_lcdc_get_brightness,
-	.check_fb	= sh_mobile_lcdc_check_fb,
-};
-
-static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
-					       struct sh_mobile_lcdc_chan *ch)
-{
-	struct backlight_device *bl;
-
-	bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch,
-				       &sh_mobile_lcdc_bl_ops, NULL);
-	if (IS_ERR(bl)) {
-		dev_err(parent, "unable to register backlight device: %ld\n",
-			PTR_ERR(bl));
-		return NULL;
-	}
-
-	bl->props.max_brightness = ch->cfg->bl_info.max_brightness;
-	bl->props.brightness = bl->props.max_brightness;
-	backlight_update_status(bl);
-
-	return bl;
-}
-
-static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
-{
-	backlight_device_unregister(bdev);
-}
-
-/* -----------------------------------------------------------------------------
- * Power management
- */
-
-static int sh_mobile_lcdc_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-
-	sh_mobile_lcdc_stop(platform_get_drvdata(pdev));
-	return 0;
-}
-
-static int sh_mobile_lcdc_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-
-	return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
-}
-
-static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
-
-	/* turn off LCDC hardware */
-	lcdc_write(priv, _LDCNT1R, 0);
-
-	return 0;
-}
-
-static int sh_mobile_lcdc_runtime_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
-
-	__sh_mobile_lcdc_start(priv);
-
-	return 0;
-}
-
-static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
-	.suspend = sh_mobile_lcdc_suspend,
-	.resume = sh_mobile_lcdc_resume,
-	.runtime_suspend = sh_mobile_lcdc_runtime_suspend,
-	.runtime_resume = sh_mobile_lcdc_runtime_resume,
-};
-
-/* -----------------------------------------------------------------------------
- * Framebuffer notifier
- */
-
-/* locking: called with info->lock held */
-static int sh_mobile_lcdc_notify(struct notifier_block *nb,
-				 unsigned long action, void *data)
-{
-	struct fb_event *event = data;
-	struct fb_info *info = event->info;
-	struct sh_mobile_lcdc_chan *ch = info->par;
-
-	if (&ch->lcdc->notifier != nb)
-		return NOTIFY_DONE;
-
-	dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
-		__func__, action, event->data);
-
-	switch(action) {
-	case FB_EVENT_SUSPEND:
-		sh_mobile_lcdc_display_off(ch);
-		sh_mobile_lcdc_stop(ch->lcdc);
-		break;
-	case FB_EVENT_RESUME:
-		mutex_lock(&ch->open_lock);
-		sh_mobile_fb_reconfig(info);
-		mutex_unlock(&ch->open_lock);
-
-		sh_mobile_lcdc_display_on(ch);
-		sh_mobile_lcdc_start(ch->lcdc);
-	}
-
-	return NOTIFY_OK;
-}
-
-/* -----------------------------------------------------------------------------
- * Probe/remove and driver init/exit
- */
-
-static const struct fb_videomode default_720p = {
-	.name = "HDMI 720p",
-	.xres = 1280,
-	.yres = 720,
-
-	.left_margin = 220,
-	.right_margin = 110,
-	.hsync_len = 40,
-
-	.upper_margin = 20,
-	.lower_margin = 5,
-	.vsync_len = 5,
-
-	.pixclock = 13468,
-	.refresh = 60,
-	.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
-};
-
-static int sh_mobile_lcdc_remove(struct platform_device *pdev)
-{
-	struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
-	unsigned int i;
-
-	fb_unregister_client(&priv->notifier);
-
-	for (i = 0; i < ARRAY_SIZE(priv->overlays); i++)
-		sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]);
-	for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
-		sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
-
-	sh_mobile_lcdc_stop(priv);
-
-	for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) {
-		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
-
-		sh_mobile_lcdc_overlay_fb_cleanup(ovl);
-
-		if (ovl->fb_mem)
-			dma_free_coherent(&pdev->dev, ovl->fb_size,
-					  ovl->fb_mem, ovl->dma_handle);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
-		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
-
-		if (ch->tx_dev) {
-			ch->tx_dev->lcdc = NULL;
-			module_put(ch->cfg->tx_dev->dev.driver->owner);
-		}
-
-		sh_mobile_lcdc_channel_fb_cleanup(ch);
-
-		if (ch->fb_mem)
-			dma_free_coherent(&pdev->dev, ch->fb_size,
-					  ch->fb_mem, ch->dma_handle);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
-		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
-
-		if (ch->bl)
-			sh_mobile_lcdc_bl_remove(ch->bl);
-		mutex_destroy(&ch->open_lock);
-	}
-
-	if (priv->dot_clk) {
-		pm_runtime_disable(&pdev->dev);
-		clk_put(priv->dot_clk);
-	}
-
-	if (priv->base)
-		iounmap(priv->base);
-
-	if (priv->irq)
-		free_irq(priv->irq, priv);
-	kfree(priv);
-	return 0;
-}
-
-static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
-{
-	int interface_type = ch->cfg->interface_type;
-
-	switch (interface_type) {
-	case RGB8:
-	case RGB9:
-	case RGB12A:
-	case RGB12B:
-	case RGB16:
-	case RGB18:
-	case RGB24:
-	case SYS8A:
-	case SYS8B:
-	case SYS8C:
-	case SYS8D:
-	case SYS9:
-	case SYS12:
-	case SYS16A:
-	case SYS16B:
-	case SYS16C:
-	case SYS18:
-	case SYS24:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* SUBLCD only supports SYS interface */
-	if (lcdc_chan_is_sublcd(ch)) {
-		if (!(interface_type & LDMT1R_IFM))
-			return -EINVAL;
-
-		interface_type &= ~LDMT1R_IFM;
-	}
-
-	ch->ldmt1r_value = interface_type;
-	return 0;
-}
-
-static int
-sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
-{
-	const struct sh_mobile_lcdc_format_info *format;
-	struct device *dev = ovl->channel->lcdc->dev;
-	int ret;
-
-	if (ovl->cfg->fourcc == 0)
-		return 0;
-
-	/* Validate the format. */
-	format = sh_mobile_format_info(ovl->cfg->fourcc);
-	if (format == NULL) {
-		dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
-		return -EINVAL;
-	}
-
-	ovl->enabled = false;
-	ovl->mode = LCDC_OVERLAY_BLEND;
-	ovl->alpha = 255;
-	ovl->rop3 = 0;
-	ovl->pos_x = 0;
-	ovl->pos_y = 0;
-
-	/* The default Y virtual resolution is twice the panel size to allow for
-	 * double-buffering.
-	 */
-	ovl->format = format;
-	ovl->xres = ovl->cfg->max_xres;
-	ovl->xres_virtual = ovl->xres;
-	ovl->yres = ovl->cfg->max_yres;
-	ovl->yres_virtual = ovl->yres * 2;
-
-	if (!format->yuv)
-		ovl->pitch = ovl->xres_virtual * format->bpp / 8;
-	else
-		ovl->pitch = ovl->xres_virtual;
-
-	/* Allocate frame buffer memory. */
-	ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
-		       * format->bpp / 8 * 2;
-	ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
-					 GFP_KERNEL);
-	if (!ovl->fb_mem) {
-		dev_err(dev, "unable to allocate buffer\n");
-		return -ENOMEM;
-	}
-
-	ret = sh_mobile_lcdc_overlay_fb_init(ovl);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int
-sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
-{
-	const struct sh_mobile_lcdc_format_info *format;
-	const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
-	struct device *dev = ch->lcdc->dev;
-	const struct fb_videomode *max_mode;
-	const struct fb_videomode *mode;
-	unsigned int num_modes;
-	unsigned int max_size;
-	unsigned int i;
-
-	mutex_init(&ch->open_lock);
-	ch->notify = sh_mobile_lcdc_display_notify;
-
-	/* Validate the format. */
-	format = sh_mobile_format_info(cfg->fourcc);
-	if (format == NULL) {
-		dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
-		return -EINVAL;
-	}
-
-	/* Iterate through the modes to validate them and find the highest
-	 * resolution.
-	 */
-	max_mode = NULL;
-	max_size = 0;
-
-	for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) {
-		unsigned int size = mode->yres * mode->xres;
-
-		/* NV12/NV21 buffers must have even number of lines */
-		if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
-		     cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
-			dev_err(dev, "yres must be multiple of 2 for "
-				"YCbCr420 mode.\n");
-			return -EINVAL;
-		}
-
-		if (size > max_size) {
-			max_mode = mode;
-			max_size = size;
-		}
-	}
-
-	if (!max_size)
-		max_size = MAX_XRES * MAX_YRES;
-	else
-		dev_dbg(dev, "Found largest videomode %ux%u\n",
-			max_mode->xres, max_mode->yres);
-
-	if (cfg->lcd_modes == NULL) {
-		mode = &default_720p;
-		num_modes = 1;
-	} else {
-		mode = cfg->lcd_modes;
-		num_modes = cfg->num_modes;
-	}
-
-	/* Use the first mode as default. The default Y virtual resolution is
-	 * twice the panel size to allow for double-buffering.
-	 */
-	ch->format = format;
-	ch->xres = mode->xres;
-	ch->xres_virtual = mode->xres;
-	ch->yres = mode->yres;
-	ch->yres_virtual = mode->yres * 2;
-
-	if (!format->yuv) {
-		ch->colorspace = V4L2_COLORSPACE_SRGB;
-		ch->pitch = ch->xres_virtual * format->bpp / 8;
-	} else {
-		ch->colorspace = V4L2_COLORSPACE_REC709;
-		ch->pitch = ch->xres_virtual;
-	}
-
-	ch->display.width = cfg->panel_cfg.width;
-	ch->display.height = cfg->panel_cfg.height;
-	ch->display.mode = *mode;
-
-	/* Allocate frame buffer memory. */
-	ch->fb_size = max_size * format->bpp / 8 * 2;
-	ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
-					GFP_KERNEL);
-	if (ch->fb_mem == NULL) {
-		dev_err(dev, "unable to allocate buffer\n");
-		return -ENOMEM;
-	}
-
-	/* Initialize the transmitter device if present. */
-	if (cfg->tx_dev) {
-		if (!cfg->tx_dev->dev.driver ||
-		    !try_module_get(cfg->tx_dev->dev.driver->owner)) {
-			dev_warn(dev, "unable to get transmitter device\n");
-			return -EINVAL;
-		}
-		ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
-		ch->tx_dev->lcdc = ch;
-		ch->tx_dev->def_mode = *mode;
-	}
-
-	return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes);
-}
-
-static int sh_mobile_lcdc_probe(struct platform_device *pdev)
-{
-	struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
-	struct sh_mobile_lcdc_priv *priv;
-	struct resource *res;
-	int num_channels;
-	int error;
-	int i;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	i = platform_get_irq(pdev, 0);
-	if (!res || i < 0) {
-		dev_err(&pdev->dev, "cannot get platform resources\n");
-		return -ENOENT;
-	}
-
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&pdev->dev, "cannot allocate device data\n");
-		return -ENOMEM;
-	}
-
-	priv->dev = &pdev->dev;
-	priv->meram_dev = pdata->meram_dev;
-	platform_set_drvdata(pdev, priv);
-
-	error = request_irq(i, sh_mobile_lcdc_irq, 0,
-			    dev_name(&pdev->dev), priv);
-	if (error) {
-		dev_err(&pdev->dev, "unable to request irq\n");
-		goto err1;
-	}
-
-	priv->irq = i;
-	atomic_set(&priv->hw_usecnt, -1);
-
-	for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) {
-		struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
-
-		ch->lcdc = priv;
-		ch->cfg = &pdata->ch[i];
-
-		error = sh_mobile_lcdc_check_interface(ch);
-		if (error) {
-			dev_err(&pdev->dev, "unsupported interface type\n");
-			goto err1;
-		}
-		init_waitqueue_head(&ch->frame_end_wait);
-		init_completion(&ch->vsync_completion);
-
-		/* probe the backlight is there is one defined */
-		if (ch->cfg->bl_info.max_brightness)
-			ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
-
-		switch (pdata->ch[i].chan) {
-		case LCDC_CHAN_MAINLCD:
-			ch->enabled = LDCNT2R_ME;
-			ch->reg_offs = lcdc_offs_mainlcd;
-			num_channels++;
-			break;
-		case LCDC_CHAN_SUBLCD:
-			ch->enabled = LDCNT2R_SE;
-			ch->reg_offs = lcdc_offs_sublcd;
-			num_channels++;
-			break;
-		}
-	}
-
-	if (!num_channels) {
-		dev_err(&pdev->dev, "no channels defined\n");
-		error = -EINVAL;
-		goto err1;
-	}
-
-	/* for dual channel LCDC (MAIN + SUB) force shared format setting */
-	if (num_channels == 2)
-		priv->forced_fourcc = pdata->ch[0].fourcc;
-
-	priv->base = ioremap_nocache(res->start, resource_size(res));
-	if (!priv->base)
-		goto err1;
-
-	error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source);
-	if (error) {
-		dev_err(&pdev->dev, "unable to setup clocks\n");
-		goto err1;
-	}
-
-	/* Enable runtime PM. */
-	pm_runtime_enable(&pdev->dev);
-
-	for (i = 0; i < num_channels; i++) {
-		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
-
-		error = sh_mobile_lcdc_channel_init(ch);
-		if (error)
-			goto err1;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
-		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
-
-		ovl->cfg = &pdata->overlays[i];
-		ovl->channel = &priv->ch[0];
-
-		error = sh_mobile_lcdc_overlay_init(ovl);
-		if (error)
-			goto err1;
-	}
-
-	error = sh_mobile_lcdc_start(priv);
-	if (error) {
-		dev_err(&pdev->dev, "unable to start hardware\n");
-		goto err1;
-	}
-
-	for (i = 0; i < num_channels; i++) {
-		struct sh_mobile_lcdc_chan *ch = priv->ch + i;
-
-		error = sh_mobile_lcdc_channel_fb_register(ch);
-		if (error)
-			goto err1;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
-		struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
-
-		error = sh_mobile_lcdc_overlay_fb_register(ovl);
-		if (error)
-			goto err1;
-	}
-
-	/* Failure ignored */
-	priv->notifier.notifier_call = sh_mobile_lcdc_notify;
-	fb_register_client(&priv->notifier);
-
-	return 0;
-err1:
-	sh_mobile_lcdc_remove(pdev);
-
-	return error;
-}
-
-static struct platform_driver sh_mobile_lcdc_driver = {
-	.driver		= {
-		.name		= "sh_mobile_lcdc_fb",
-		.owner		= THIS_MODULE,
-		.pm		= &sh_mobile_lcdc_dev_pm_ops,
-	},
-	.probe		= sh_mobile_lcdc_probe,
-	.remove		= sh_mobile_lcdc_remove,
-};
-
-module_platform_driver(sh_mobile_lcdc_driver);
-
-MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
-MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
deleted file mode 100644
index f839adef1d90..000000000000
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#ifndef SH_MOBILE_LCDCFB_H
-#define SH_MOBILE_LCDCFB_H
-
-#include <linux/completion.h>
-#include <linux/fb.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-
-/* per-channel registers */
-enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
-       LDSM2R, LDSA1R, LDSA2R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
-       LDHAJR,
-       NR_CH_REGS };
-
-#define PALETTE_NR 16
-
-struct backlight_device;
-struct fb_info;
-struct module;
-struct sh_mobile_lcdc_chan;
-struct sh_mobile_lcdc_entity;
-struct sh_mobile_lcdc_format_info;
-struct sh_mobile_lcdc_priv;
-
-#define SH_MOBILE_LCDC_DISPLAY_DISCONNECTED	0
-#define SH_MOBILE_LCDC_DISPLAY_CONNECTED	1
-
-struct sh_mobile_lcdc_entity_ops {
-	/* Display */
-	int (*display_on)(struct sh_mobile_lcdc_entity *entity);
-	void (*display_off)(struct sh_mobile_lcdc_entity *entity);
-};
-
-enum sh_mobile_lcdc_entity_event {
-	SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
-	SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
-	SH_MOBILE_LCDC_EVENT_DISPLAY_MODE,
-};
-
-struct sh_mobile_lcdc_entity {
-	struct module *owner;
-	const struct sh_mobile_lcdc_entity_ops *ops;
-	struct sh_mobile_lcdc_chan *lcdc;
-	struct fb_videomode def_mode;
-};
-
-/*
- * struct sh_mobile_lcdc_chan - LCDC display channel
- *
- * @pan_y_offset: Panning linear offset in bytes (luma component)
- * @base_addr_y: Frame buffer viewport base address (luma component)
- * @base_addr_c: Frame buffer viewport base address (chroma component)
- * @pitch: Frame buffer line pitch
- */
-struct sh_mobile_lcdc_chan {
-	struct sh_mobile_lcdc_priv *lcdc;
-	struct sh_mobile_lcdc_entity *tx_dev;
-	const struct sh_mobile_lcdc_chan_cfg *cfg;
-
-	unsigned long *reg_offs;
-	unsigned long ldmt1r_value;
-	unsigned long enabled; /* ME and SE in LDCNT2R */
-	void *cache;
-
-	struct mutex open_lock;		/* protects the use counter */
-	int use_count;
-
-	void *fb_mem;
-	unsigned long fb_size;
-
-	dma_addr_t dma_handle;
-	unsigned long pan_y_offset;
-
-	unsigned long frame_end;
-	wait_queue_head_t frame_end_wait;
-	struct completion vsync_completion;
-
-	const struct sh_mobile_lcdc_format_info *format;
-	u32 colorspace;
-	unsigned int xres;
-	unsigned int xres_virtual;
-	unsigned int yres;
-	unsigned int yres_virtual;
-	unsigned int pitch;
-
-	unsigned long base_addr_y;
-	unsigned long base_addr_c;
-	unsigned int line_size;
-
-	int (*notify)(struct sh_mobile_lcdc_chan *ch,
-		      enum sh_mobile_lcdc_entity_event event,
-		      const struct fb_videomode *mode,
-		      const struct fb_monspecs *monspec);
-
-	/* Backlight */
-	struct backlight_device *bl;
-	unsigned int bl_brightness;
-
-	/* FB */
-	struct fb_info *info;
-	u32 pseudo_palette[PALETTE_NR];
-	struct {
-		unsigned int width;
-		unsigned int height;
-		struct fb_videomode mode;
-	} display;
-	struct fb_deferred_io defio;
-	struct scatterlist *sglist;
-	int blank_status;
-};
-
-#endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
deleted file mode 100644
index a297de5cc859..000000000000
--- a/drivers/video/sh_mobile_meram.c
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * SuperH Mobile MERAM Driver for SuperH Mobile LCDC Driver
- *
- * Copyright (c) 2011	Damian Hobson-Garcia <dhobsong@igel.co.jp>
- *                      Takanari Hayama <taki@igel.co.jp>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/genalloc.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-
-#include <video/sh_mobile_meram.h>
-
-/* -----------------------------------------------------------------------------
- * MERAM registers
- */
-
-#define MEVCR1			0x4
-#define MEVCR1_RST		(1 << 31)
-#define MEVCR1_WD		(1 << 30)
-#define MEVCR1_AMD1		(1 << 29)
-#define MEVCR1_AMD0		(1 << 28)
-#define MEQSEL1			0x40
-#define MEQSEL2			0x44
-
-#define MExxCTL			0x400
-#define MExxCTL_BV		(1 << 31)
-#define MExxCTL_BSZ_SHIFT	28
-#define MExxCTL_MSAR_MASK	(0x7ff << MExxCTL_MSAR_SHIFT)
-#define MExxCTL_MSAR_SHIFT	16
-#define MExxCTL_NXT_MASK	(0x1f << MExxCTL_NXT_SHIFT)
-#define MExxCTL_NXT_SHIFT	11
-#define MExxCTL_WD1		(1 << 10)
-#define MExxCTL_WD0		(1 << 9)
-#define MExxCTL_WS		(1 << 8)
-#define MExxCTL_CB		(1 << 7)
-#define MExxCTL_WBF		(1 << 6)
-#define MExxCTL_WF		(1 << 5)
-#define MExxCTL_RF		(1 << 4)
-#define MExxCTL_CM		(1 << 3)
-#define MExxCTL_MD_READ		(1 << 0)
-#define MExxCTL_MD_WRITE	(2 << 0)
-#define MExxCTL_MD_ICB_WB	(3 << 0)
-#define MExxCTL_MD_ICB		(4 << 0)
-#define MExxCTL_MD_FB		(7 << 0)
-#define MExxCTL_MD_MASK		(7 << 0)
-#define MExxBSIZE		0x404
-#define MExxBSIZE_RCNT_SHIFT	28
-#define MExxBSIZE_YSZM1_SHIFT	16
-#define MExxBSIZE_XSZM1_SHIFT	0
-#define MExxMNCF		0x408
-#define MExxMNCF_KWBNM_SHIFT	28
-#define MExxMNCF_KRBNM_SHIFT	24
-#define MExxMNCF_BNM_SHIFT	16
-#define MExxMNCF_XBV		(1 << 15)
-#define MExxMNCF_CPL_YCBCR444	(1 << 12)
-#define MExxMNCF_CPL_YCBCR420	(2 << 12)
-#define MExxMNCF_CPL_YCBCR422	(3 << 12)
-#define MExxMNCF_CPL_MSK	(3 << 12)
-#define MExxMNCF_BL		(1 << 2)
-#define MExxMNCF_LNM_SHIFT	0
-#define MExxSARA		0x410
-#define MExxSARB		0x414
-#define MExxSBSIZE		0x418
-#define MExxSBSIZE_HDV		(1 << 31)
-#define MExxSBSIZE_HSZ16	(0 << 28)
-#define MExxSBSIZE_HSZ32	(1 << 28)
-#define MExxSBSIZE_HSZ64	(2 << 28)
-#define MExxSBSIZE_HSZ128	(3 << 28)
-#define MExxSBSIZE_SBSIZZ_SHIFT	0
-
-#define MERAM_MExxCTL_VAL(next, addr)	\
-	((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
-	 (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
-#define	MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
-	(((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
-	 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
-	 ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
-
-static const unsigned long common_regs[] = {
-	MEVCR1,
-	MEQSEL1,
-	MEQSEL2,
-};
-#define MERAM_REGS_SIZE ARRAY_SIZE(common_regs)
-
-static const unsigned long icb_regs[] = {
-	MExxCTL,
-	MExxBSIZE,
-	MExxMNCF,
-	MExxSARA,
-	MExxSARB,
-	MExxSBSIZE,
-};
-#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
-
-/*
- * sh_mobile_meram_icb - MERAM ICB information
- * @regs: Registers cache
- * @index: ICB index
- * @offset: MERAM block offset
- * @size: MERAM block size in KiB
- * @cache_unit: Bytes to cache per ICB
- * @pixelformat: Video pixel format of the data stored in the ICB
- * @current_reg: Which of Start Address Register A (0) or B (1) is in use
- */
-struct sh_mobile_meram_icb {
-	unsigned long regs[ICB_REGS_SIZE];
-	unsigned int index;
-	unsigned long offset;
-	unsigned int size;
-
-	unsigned int cache_unit;
-	unsigned int pixelformat;
-	unsigned int current_reg;
-};
-
-#define MERAM_ICB_NUM			32
-
-struct sh_mobile_meram_fb_plane {
-	struct sh_mobile_meram_icb *marker;
-	struct sh_mobile_meram_icb *cache;
-};
-
-struct sh_mobile_meram_fb_cache {
-	unsigned int nplanes;
-	struct sh_mobile_meram_fb_plane planes[2];
-};
-
-/*
- * sh_mobile_meram_priv - MERAM device
- * @base: Registers base address
- * @meram: MERAM physical address
- * @regs: Registers cache
- * @lock: Protects used_icb and icbs
- * @used_icb: Bitmask of used ICBs
- * @icbs: ICBs
- * @pool: Allocation pool to manage the MERAM
- */
-struct sh_mobile_meram_priv {
-	void __iomem *base;
-	unsigned long meram;
-	unsigned long regs[MERAM_REGS_SIZE];
-
-	struct mutex lock;
-	unsigned long used_icb;
-	struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM];
-
-	struct gen_pool *pool;
-};
-
-/* settings */
-#define MERAM_GRANULARITY		1024
-#define MERAM_SEC_LINE			15
-#define MERAM_LINE_WIDTH		2048
-
-/* -----------------------------------------------------------------------------
- * Registers access
- */
-
-#define MERAM_ICB_OFFSET(base, idx, off)	((base) + (off) + (idx) * 0x20)
-
-static inline void meram_write_icb(void __iomem *base, unsigned int idx,
-				   unsigned int off, unsigned long val)
-{
-	iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
-}
-
-static inline unsigned long meram_read_icb(void __iomem *base, unsigned int idx,
-					   unsigned int off)
-{
-	return ioread32(MERAM_ICB_OFFSET(base, idx, off));
-}
-
-static inline void meram_write_reg(void __iomem *base, unsigned int off,
-				   unsigned long val)
-{
-	iowrite32(val, base + off);
-}
-
-static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
-{
-	return ioread32(base + off);
-}
-
-/* -----------------------------------------------------------------------------
- * MERAM allocation and free
- */
-
-static unsigned long meram_alloc(struct sh_mobile_meram_priv *priv, size_t size)
-{
-	return gen_pool_alloc(priv->pool, size);
-}
-
-static void meram_free(struct sh_mobile_meram_priv *priv, unsigned long mem,
-		       size_t size)
-{
-	gen_pool_free(priv->pool, mem, size);
-}
-
-/* -----------------------------------------------------------------------------
- * LCDC cache planes allocation, init, cleanup and free
- */
-
-/* Allocate ICBs and MERAM for a plane. */
-static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
-			     struct sh_mobile_meram_fb_plane *plane,
-			     size_t size)
-{
-	unsigned long mem;
-	unsigned long idx;
-
-	idx = find_first_zero_bit(&priv->used_icb, 28);
-	if (idx == 28)
-		return -ENOMEM;
-	plane->cache = &priv->icbs[idx];
-
-	idx = find_next_zero_bit(&priv->used_icb, 32, 28);
-	if (idx == 32)
-		return -ENOMEM;
-	plane->marker = &priv->icbs[idx];
-
-	mem = meram_alloc(priv, size * 1024);
-	if (mem == 0)
-		return -ENOMEM;
-
-	__set_bit(plane->marker->index, &priv->used_icb);
-	__set_bit(plane->cache->index, &priv->used_icb);
-
-	plane->marker->offset = mem - priv->meram;
-	plane->marker->size = size;
-
-	return 0;
-}
-
-/* Free ICBs and MERAM for a plane. */
-static void meram_plane_free(struct sh_mobile_meram_priv *priv,
-			     struct sh_mobile_meram_fb_plane *plane)
-{
-	meram_free(priv, priv->meram + plane->marker->offset,
-		   plane->marker->size * 1024);
-
-	__clear_bit(plane->marker->index, &priv->used_icb);
-	__clear_bit(plane->cache->index, &priv->used_icb);
-}
-
-/* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */
-static int is_nvcolor(int cspace)
-{
-	if (cspace == SH_MOBILE_MERAM_PF_NV ||
-	    cspace == SH_MOBILE_MERAM_PF_NV24)
-		return 1;
-	return 0;
-}
-
-/* Set the next address to fetch. */
-static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
-				struct sh_mobile_meram_fb_cache *cache,
-				unsigned long base_addr_y,
-				unsigned long base_addr_c)
-{
-	struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
-	unsigned long target;
-
-	icb->current_reg ^= 1;
-	target = icb->current_reg ? MExxSARB : MExxSARA;
-
-	/* set the next address to fetch */
-	meram_write_icb(priv->base, cache->planes[0].cache->index, target,
-			base_addr_y);
-	meram_write_icb(priv->base, cache->planes[0].marker->index, target,
-			base_addr_y + cache->planes[0].marker->cache_unit);
-
-	if (cache->nplanes == 2) {
-		meram_write_icb(priv->base, cache->planes[1].cache->index,
-				target, base_addr_c);
-		meram_write_icb(priv->base, cache->planes[1].marker->index,
-				target, base_addr_c +
-				cache->planes[1].marker->cache_unit);
-	}
-}
-
-/* Get the next ICB address. */
-static void
-meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
-			struct sh_mobile_meram_fb_cache *cache,
-			unsigned long *icb_addr_y, unsigned long *icb_addr_c)
-{
-	struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
-	unsigned long icb_offset;
-
-	if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
-		icb_offset = 0x80000000 | (icb->current_reg << 29);
-	else
-		icb_offset = 0xc0000000 | (icb->current_reg << 23);
-
-	*icb_addr_y = icb_offset | (cache->planes[0].marker->index << 24);
-	if (cache->nplanes == 2)
-		*icb_addr_c = icb_offset
-			    | (cache->planes[1].marker->index << 24);
-}
-
-#define MERAM_CALC_BYTECOUNT(x, y) \
-	(((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
-
-/* Initialize MERAM. */
-static int meram_plane_init(struct sh_mobile_meram_priv *priv,
-			    struct sh_mobile_meram_fb_plane *plane,
-			    unsigned int xres, unsigned int yres,
-			    unsigned int *out_pitch)
-{
-	struct sh_mobile_meram_icb *marker = plane->marker;
-	unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
-	unsigned long bnm;
-	unsigned int lcdc_pitch;
-	unsigned int xpitch;
-	unsigned int line_cnt;
-	unsigned int save_lines;
-
-	/* adjust pitch to 1024, 2048, 4096 or 8192 */
-	lcdc_pitch = (xres - 1) | 1023;
-	lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1);
-	lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2);
-	lcdc_pitch += 1;
-
-	/* derive settings */
-	if (lcdc_pitch == 8192 && yres >= 1024) {
-		lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
-		line_cnt = total_byte_count >> 11;
-		*out_pitch = xres;
-		save_lines = plane->marker->size / 16 / MERAM_SEC_LINE;
-		save_lines *= MERAM_SEC_LINE;
-	} else {
-		xpitch = xres;
-		line_cnt = yres;
-		*out_pitch = lcdc_pitch;
-		save_lines = plane->marker->size / (lcdc_pitch >> 10) / 2;
-		save_lines &= 0xff;
-	}
-	bnm = (save_lines - 1) << 16;
-
-	/* TODO: we better to check if we have enough MERAM buffer size */
-
-	/* set up ICB */
-	meram_write_icb(priv->base, plane->cache->index,  MExxBSIZE,
-			MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
-	meram_write_icb(priv->base, plane->marker->index, MExxBSIZE,
-			MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
-
-	meram_write_icb(priv->base, plane->cache->index,  MExxMNCF, bnm);
-	meram_write_icb(priv->base, plane->marker->index, MExxMNCF, bnm);
-
-	meram_write_icb(priv->base, plane->cache->index,  MExxSBSIZE, xpitch);
-	meram_write_icb(priv->base, plane->marker->index, MExxSBSIZE, xpitch);
-
-	/* save a cache unit size */
-	plane->cache->cache_unit = xres * save_lines;
-	plane->marker->cache_unit = xres * save_lines;
-
-	/*
-	 * Set MERAM for framebuffer
-	 *
-	 * we also chain the cache_icb and the marker_icb.
-	 * we also split the allocated MERAM buffer between two ICBs.
-	 */
-	meram_write_icb(priv->base, plane->cache->index, MExxCTL,
-			MERAM_MExxCTL_VAL(plane->marker->index, marker->offset)
-			| MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
-			MExxCTL_MD_FB);
-	meram_write_icb(priv->base, plane->marker->index, MExxCTL,
-			MERAM_MExxCTL_VAL(plane->cache->index, marker->offset +
-					  plane->marker->size / 2) |
-			MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
-			MExxCTL_MD_FB);
-
-	return 0;
-}
-
-static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
-				struct sh_mobile_meram_fb_plane *plane)
-{
-	/* disable ICB */
-	meram_write_icb(priv->base, plane->cache->index,  MExxCTL,
-			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
-	meram_write_icb(priv->base, plane->marker->index, MExxCTL,
-			MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
-
-	plane->cache->cache_unit = 0;
-	plane->marker->cache_unit = 0;
-}
-
-/* -----------------------------------------------------------------------------
- * MERAM operations
- */
-
-unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *pdata,
-				    size_t size)
-{
-	struct sh_mobile_meram_priv *priv = pdata->priv;
-
-	return meram_alloc(priv, size);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_alloc);
-
-void sh_mobile_meram_free(struct sh_mobile_meram_info *pdata, unsigned long mem,
-			  size_t size)
-{
-	struct sh_mobile_meram_priv *priv = pdata->priv;
-
-	meram_free(priv, mem, size);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_free);
-
-/* Allocate memory for the ICBs and mark them as used. */
-static struct sh_mobile_meram_fb_cache *
-meram_cache_alloc(struct sh_mobile_meram_priv *priv,
-		  const struct sh_mobile_meram_cfg *cfg,
-		  int pixelformat)
-{
-	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
-	struct sh_mobile_meram_fb_cache *cache;
-	int ret;
-
-	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
-	if (cache == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	cache->nplanes = nplanes;
-
-	ret = meram_plane_alloc(priv, &cache->planes[0],
-				cfg->icb[0].meram_size);
-	if (ret < 0)
-		goto error;
-
-	cache->planes[0].marker->current_reg = 1;
-	cache->planes[0].marker->pixelformat = pixelformat;
-
-	if (cache->nplanes == 1)
-		return cache;
-
-	ret = meram_plane_alloc(priv, &cache->planes[1],
-				cfg->icb[1].meram_size);
-	if (ret < 0) {
-		meram_plane_free(priv, &cache->planes[0]);
-		goto error;
-	}
-
-	return cache;
-
-error:
-	kfree(cache);
-	return ERR_PTR(-ENOMEM);
-}
-
-void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *pdata,
-				  const struct sh_mobile_meram_cfg *cfg,
-				  unsigned int xres, unsigned int yres,
-				  unsigned int pixelformat, unsigned int *pitch)
-{
-	struct sh_mobile_meram_fb_cache *cache;
-	struct sh_mobile_meram_priv *priv = pdata->priv;
-	struct platform_device *pdev = pdata->pdev;
-	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
-	unsigned int out_pitch;
-
-	if (priv == NULL)
-		return ERR_PTR(-ENODEV);
-
-	if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
-	    pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
-	    pixelformat != SH_MOBILE_MERAM_PF_RGB)
-		return ERR_PTR(-EINVAL);
-
-	dev_dbg(&pdev->dev, "registering %dx%d (%s)", xres, yres,
-		!pixelformat ? "yuv" : "rgb");
-
-	/* we can't handle wider than 8192px */
-	if (xres > 8192) {
-		dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (cfg->icb[0].meram_size == 0)
-		return ERR_PTR(-EINVAL);
-
-	if (nplanes == 2 && cfg->icb[1].meram_size == 0)
-		return ERR_PTR(-EINVAL);
-
-	mutex_lock(&priv->lock);
-
-	/* We now register the ICBs and allocate the MERAM regions. */
-	cache = meram_cache_alloc(priv, cfg, pixelformat);
-	if (IS_ERR(cache)) {
-		dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
-			PTR_ERR(cache));
-		goto err;
-	}
-
-	/* initialize MERAM */
-	meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
-	*pitch = out_pitch;
-	if (pixelformat == SH_MOBILE_MERAM_PF_NV)
-		meram_plane_init(priv, &cache->planes[1],
-				 xres, (yres + 1) / 2, &out_pitch);
-	else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
-		meram_plane_init(priv, &cache->planes[1],
-				 2 * xres, (yres + 1) / 2, &out_pitch);
-
-err:
-	mutex_unlock(&priv->lock);
-	return cache;
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_alloc);
-
-void
-sh_mobile_meram_cache_free(struct sh_mobile_meram_info *pdata, void *data)
-{
-	struct sh_mobile_meram_fb_cache *cache = data;
-	struct sh_mobile_meram_priv *priv = pdata->priv;
-
-	mutex_lock(&priv->lock);
-
-	/* Cleanup and free. */
-	meram_plane_cleanup(priv, &cache->planes[0]);
-	meram_plane_free(priv, &cache->planes[0]);
-
-	if (cache->nplanes == 2) {
-		meram_plane_cleanup(priv, &cache->planes[1]);
-		meram_plane_free(priv, &cache->planes[1]);
-	}
-
-	kfree(cache);
-
-	mutex_unlock(&priv->lock);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_free);
-
-void
-sh_mobile_meram_cache_update(struct sh_mobile_meram_info *pdata, void *data,
-			     unsigned long base_addr_y,
-			     unsigned long base_addr_c,
-			     unsigned long *icb_addr_y,
-			     unsigned long *icb_addr_c)
-{
-	struct sh_mobile_meram_fb_cache *cache = data;
-	struct sh_mobile_meram_priv *priv = pdata->priv;
-
-	mutex_lock(&priv->lock);
-
-	meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
-	meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
-
-	mutex_unlock(&priv->lock);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
-
-/* -----------------------------------------------------------------------------
- * Power management
- */
-
-#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
-static int sh_mobile_meram_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
-	unsigned int i, j;
-
-	for (i = 0; i < MERAM_REGS_SIZE; i++)
-		priv->regs[i] = meram_read_reg(priv->base, common_regs[i]);
-
-	for (i = 0; i < 32; i++) {
-		if (!test_bit(i, &priv->used_icb))
-			continue;
-		for (j = 0; j < ICB_REGS_SIZE; j++) {
-			priv->icbs[i].regs[j] =
-				meram_read_icb(priv->base, i, icb_regs[j]);
-			/* Reset ICB on resume */
-			if (icb_regs[j] == MExxCTL)
-				priv->icbs[i].regs[j] |=
-					MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
-		}
-	}
-	return 0;
-}
-
-static int sh_mobile_meram_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
-	unsigned int i, j;
-
-	for (i = 0; i < 32; i++) {
-		if (!test_bit(i, &priv->used_icb))
-			continue;
-		for (j = 0; j < ICB_REGS_SIZE; j++)
-			meram_write_icb(priv->base, i, icb_regs[j],
-					priv->icbs[i].regs[j]);
-	}
-
-	for (i = 0; i < MERAM_REGS_SIZE; i++)
-		meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
-	return 0;
-}
-#endif /* CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME */
-
-static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
-			    sh_mobile_meram_suspend,
-			    sh_mobile_meram_resume, NULL);
-
-/* -----------------------------------------------------------------------------
- * Probe/remove and driver init/exit
- */
-
-static int sh_mobile_meram_probe(struct platform_device *pdev)
-{
-	struct sh_mobile_meram_priv *priv;
-	struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
-	struct resource *regs;
-	struct resource *meram;
-	unsigned int i;
-	int error;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
-
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (regs == NULL || meram == NULL) {
-		dev_err(&pdev->dev, "cannot get platform resources\n");
-		return -ENOENT;
-	}
-
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&pdev->dev, "cannot allocate device data\n");
-		return -ENOMEM;
-	}
-
-	/* Initialize private data. */
-	mutex_init(&priv->lock);
-	priv->used_icb = pdata->reserved_icbs;
-
-	for (i = 0; i < MERAM_ICB_NUM; ++i)
-		priv->icbs[i].index = i;
-
-	pdata->priv = priv;
-	pdata->pdev = pdev;
-
-	/* Request memory regions and remap the registers. */
-	if (!request_mem_region(regs->start, resource_size(regs), pdev->name)) {
-		dev_err(&pdev->dev, "MERAM registers region already claimed\n");
-		error = -EBUSY;
-		goto err_req_regs;
-	}
-
-	if (!request_mem_region(meram->start, resource_size(meram),
-				pdev->name)) {
-		dev_err(&pdev->dev, "MERAM memory region already claimed\n");
-		error = -EBUSY;
-		goto err_req_meram;
-	}
-
-	priv->base = ioremap_nocache(regs->start, resource_size(regs));
-	if (!priv->base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		error = -EFAULT;
-		goto err_ioremap;
-	}
-
-	priv->meram = meram->start;
-
-	/* Create and initialize the MERAM memory pool. */
-	priv->pool = gen_pool_create(ilog2(MERAM_GRANULARITY), -1);
-	if (priv->pool == NULL) {
-		error = -ENOMEM;
-		goto err_genpool;
-	}
-
-	error = gen_pool_add(priv->pool, meram->start, resource_size(meram),
-			     -1);
-	if (error < 0)
-		goto err_genpool;
-
-	/* initialize ICB addressing mode */
-	if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
-		meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
-
-	platform_set_drvdata(pdev, priv);
-	pm_runtime_enable(&pdev->dev);
-
-	dev_info(&pdev->dev, "sh_mobile_meram initialized.");
-
-	return 0;
-
-err_genpool:
-	if (priv->pool)
-		gen_pool_destroy(priv->pool);
-	iounmap(priv->base);
-err_ioremap:
-	release_mem_region(meram->start, resource_size(meram));
-err_req_meram:
-	release_mem_region(regs->start, resource_size(regs));
-err_req_regs:
-	mutex_destroy(&priv->lock);
-	kfree(priv);
-
-	return error;
-}
-
-
-static int sh_mobile_meram_remove(struct platform_device *pdev)
-{
-	struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
-	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	struct resource *meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
-	pm_runtime_disable(&pdev->dev);
-
-	gen_pool_destroy(priv->pool);
-
-	iounmap(priv->base);
-	release_mem_region(meram->start, resource_size(meram));
-	release_mem_region(regs->start, resource_size(regs));
-
-	mutex_destroy(&priv->lock);
-
-	kfree(priv);
-
-	return 0;
-}
-
-static struct platform_driver sh_mobile_meram_driver = {
-	.driver	= {
-		.name		= "sh_mobile_meram",
-		.owner		= THIS_MODULE,
-		.pm		= &sh_mobile_meram_dev_pm_ops,
-	},
-	.probe		= sh_mobile_meram_probe,
-	.remove		= sh_mobile_meram_remove,
-};
-
-module_platform_driver(sh_mobile_meram_driver);
-
-MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
-MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c
deleted file mode 100644
index 210f3a02121a..000000000000
--- a/drivers/video/simplefb.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Simplest possible simple frame-buffer driver, as a platform device
- *
- * Copyright (c) 2013, Stephen Warren
- *
- * Based on q40fb.c, which was:
- * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org>
- *
- * Also based on offb.c, which was:
- * Copyright (C) 1997 Geert Uytterhoeven
- * Copyright (C) 1996 Paul Mackerras
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_data/simplefb.h>
-#include <linux/platform_device.h>
-
-static struct fb_fix_screeninfo simplefb_fix = {
-	.id		= "simple",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_TRUECOLOR,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo simplefb_var = {
-	.height		= -1,
-	.width		= -1,
-	.activate	= FB_ACTIVATE_NOW,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			      u_int transp, struct fb_info *info)
-{
-	u32 *pal = info->pseudo_palette;
-	u32 cr = red >> (16 - info->var.red.length);
-	u32 cg = green >> (16 - info->var.green.length);
-	u32 cb = blue >> (16 - info->var.blue.length);
-	u32 value;
-
-	if (regno >= 16)
-		return -EINVAL;
-
-	value = (cr << info->var.red.offset) |
-		(cg << info->var.green.offset) |
-		(cb << info->var.blue.offset);
-	if (info->var.transp.length > 0) {
-		u32 mask = (1 << info->var.transp.length) - 1;
-		mask <<= info->var.transp.offset;
-		value |= mask;
-	}
-	pal[regno] = value;
-
-	return 0;
-}
-
-static void simplefb_destroy(struct fb_info *info)
-{
-	if (info->screen_base)
-		iounmap(info->screen_base);
-}
-
-static struct fb_ops simplefb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_destroy	= simplefb_destroy,
-	.fb_setcolreg	= simplefb_setcolreg,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static struct simplefb_format simplefb_formats[] = SIMPLEFB_FORMATS;
-
-struct simplefb_params {
-	u32 width;
-	u32 height;
-	u32 stride;
-	struct simplefb_format *format;
-};
-
-static int simplefb_parse_dt(struct platform_device *pdev,
-			   struct simplefb_params *params)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-	const char *format;
-	int i;
-
-	ret = of_property_read_u32(np, "width", &params->width);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't parse width property\n");
-		return ret;
-	}
-
-	ret = of_property_read_u32(np, "height", &params->height);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't parse height property\n");
-		return ret;
-	}
-
-	ret = of_property_read_u32(np, "stride", &params->stride);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't parse stride property\n");
-		return ret;
-	}
-
-	ret = of_property_read_string(np, "format", &format);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't parse format property\n");
-		return ret;
-	}
-	params->format = NULL;
-	for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
-		if (strcmp(format, simplefb_formats[i].name))
-			continue;
-		params->format = &simplefb_formats[i];
-		break;
-	}
-	if (!params->format) {
-		dev_err(&pdev->dev, "Invalid format value\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int simplefb_parse_pd(struct platform_device *pdev,
-			     struct simplefb_params *params)
-{
-	struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
-	int i;
-
-	params->width = pd->width;
-	params->height = pd->height;
-	params->stride = pd->stride;
-
-	params->format = NULL;
-	for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
-		if (strcmp(pd->format, simplefb_formats[i].name))
-			continue;
-
-		params->format = &simplefb_formats[i];
-		break;
-	}
-
-	if (!params->format) {
-		dev_err(&pdev->dev, "Invalid format value\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int simplefb_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct simplefb_params params;
-	struct fb_info *info;
-	struct resource *mem;
-
-	if (fb_get_options("simplefb", NULL))
-		return -ENODEV;
-
-	ret = -ENODEV;
-	if (dev_get_platdata(&pdev->dev))
-		ret = simplefb_parse_pd(pdev, &params);
-	else if (pdev->dev.of_node)
-		ret = simplefb_parse_dt(pdev, &params);
-
-	if (ret)
-		return ret;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "No memory resource\n");
-		return -EINVAL;
-	}
-
-	info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-	platform_set_drvdata(pdev, info);
-
-	info->fix = simplefb_fix;
-	info->fix.smem_start = mem->start;
-	info->fix.smem_len = resource_size(mem);
-	info->fix.line_length = params.stride;
-
-	info->var = simplefb_var;
-	info->var.xres = params.width;
-	info->var.yres = params.height;
-	info->var.xres_virtual = params.width;
-	info->var.yres_virtual = params.height;
-	info->var.bits_per_pixel = params.format->bits_per_pixel;
-	info->var.red = params.format->red;
-	info->var.green = params.format->green;
-	info->var.blue = params.format->blue;
-	info->var.transp = params.format->transp;
-
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures) {
-		framebuffer_release(info);
-		return -ENOMEM;
-	}
-	info->apertures->ranges[0].base = info->fix.smem_start;
-	info->apertures->ranges[0].size = info->fix.smem_len;
-
-	info->fbops = &simplefb_ops;
-	info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE;
-	info->screen_base = ioremap_wc(info->fix.smem_start,
-				       info->fix.smem_len);
-	if (!info->screen_base) {
-		framebuffer_release(info);
-		return -ENODEV;
-	}
-	info->pseudo_palette = (void *)(info + 1);
-
-	dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n",
-			     info->fix.smem_start, info->fix.smem_len,
-			     info->screen_base);
-	dev_info(&pdev->dev, "format=%s, mode=%dx%dx%d, linelength=%d\n",
-			     params.format->name,
-			     info->var.xres, info->var.yres,
-			     info->var.bits_per_pixel, info->fix.line_length);
-
-	ret = register_framebuffer(info);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
-		iounmap(info->screen_base);
-		framebuffer_release(info);
-		return ret;
-	}
-
-	dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
-
-	return 0;
-}
-
-static int simplefb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-
-	unregister_framebuffer(info);
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id simplefb_of_match[] = {
-	{ .compatible = "simple-framebuffer", },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, simplefb_of_match);
-
-static struct platform_driver simplefb_driver = {
-	.driver = {
-		.name = "simple-framebuffer",
-		.owner = THIS_MODULE,
-		.of_match_table = simplefb_of_match,
-	},
-	.probe = simplefb_probe,
-	.remove = simplefb_remove,
-};
-module_platform_driver(simplefb_driver);
-
-MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
-MODULE_DESCRIPTION("Simple framebuffer driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sis/300vtbl.h b/drivers/video/sis/300vtbl.h
deleted file mode 100644
index e4b4a2626da4..000000000000
--- a/drivers/video/sis/300vtbl.h
+++ /dev/null
@@ -1,1072 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * Register settings for SiS 300 series
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-static const struct SiS_Ext SiS300_EModeIDTable[] =
-{
-	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x? */
-	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
-	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x8 */
-	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},
-	{0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x8 */
-	{0x32,0x6a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x8 */
-	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x16 */
-	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x16 */
-	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x32 */
-	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x32 */
-	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x? */
-	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x8 */
-	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},  /* 1280x1024x8 */
-	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
-	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
-	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x15 */
-	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x16 */
-	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
-	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
-	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x15 */
-	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x16 */
-	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
-	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
-	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
-	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
-	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x8  */
-	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x8  */
-	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x8  */
-	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x16 */
-	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x16 */
-	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x16 */
-	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x8  */
-	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x32 */
-	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x16 */
-	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x32 */
-	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
-	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x32 */
-	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
-	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
-	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
-	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
-	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
-	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
-	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x8 */
-	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x16 */
-	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x8 */
-	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x8 */
-	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x16 */
-	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x16 */
-	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x32 */
-	{0x77,0x4a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x32 */
-	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x32 */
-	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x8 */
-	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x16 */
-	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x8 */
-	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x16 */
-	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x32 */
-	{0x20,0x4a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},  /* 1024x600 */
-	{0x21,0x4a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
-	{0x22,0x4a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
-	{0x23,0x4a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},  /* 1152x768 */
-	{0x24,0x4a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
-	{0x25,0x4a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
-	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},  /* 1152x864 */
-	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
-	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
-	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x39,-1},  /* 848x480 */
-	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x39,-1},
-	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x39,-1},
-	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3b,-1},  /* 856x480 */
-	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3b,-1},
-	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3b,-1},
-	{0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1},  /* 1360x768 */
-	{0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1},
-	{0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1},
-	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x32 */
-	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x32 */
-	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x32 */
-	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1},  /* 1280x768   */
-	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1},
-	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1},
-	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3f,-1},  /* 768x576x8 */
-	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3f,-1},  /* 768x576x16 */
-	{0x61,0x6a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3f,-1},  /* 768x576x32 */
-	{0x67,0x6e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1},  /* 1360x1024x8 (BARCO) */
-	{0x6f,0x6e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1},  /* 1360x1024x16 (BARCO) */
-	{0x72,0x6eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1},  /* 1360x1024x32 (BARCO) */
-	{0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
-};
-
-static const struct SiS_Ext2 SiS300_RefIndex[] =
-{
-	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 00 */
-	{0x0467,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 01 */
-	{0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 02 - CRT1CRTC was 0x4f */
-	{0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 03 */
-	{0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 04 */
-	{0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 05 */
-	{0x0047,0x11,0x0e,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 06 - CRT1CRTC was 0x51 */
-	{0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 07 */
-	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 08 */
-	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 09 */
-	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0a */
-	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0b */
-	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0c */
-	{0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0d */
-	{0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0e */
-	{0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0f */
-	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0, 0x4a, 0x49}, /* 10 */
-	{0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0, 0x00, 0x00}, /* 11 */
-	{0x006f,0x32,0x4a,0x06,0x14,0x32, 720, 576, 0, 0x00, 0x00}, /* 12 */ /* 4a was 03 */
-	{0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 13 */
-	{0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 14 */
-	{0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 15 - CRT1CRTC was 0x97 */
-	{0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 16 */
-	{0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 17 - CRT1CRTC was 0x59 */
-	{0x0047,0x1a,0x12,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 18 */
-	{0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 19 - CRT1CRTC was 0x5b */
-	{0x0387,0x1c,0x0d,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1a - CRT1CRTC was 0x5c */
-	{0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1b */
-	{0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1c */
-	{0x0007,0x1f,0x18,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1d */
-	{0x0007,0x20,0x19,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1e - CRT1CRTC was 0x60 */
-	{0x0007,0x21,0x1a,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1f */
-	{0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 20 */
-	{0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 21 - CRT1CRTC was 0x63 */
-	{0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 22 */
-	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0, 0x4b, 0x4b}, /* 23 */
-	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0, 0x00, 0x00}, /* 24 */
-	{0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0, 0x00, 0x00}, /* 25 */
-	{0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0, 0x00, 0x00}, /* 26 */  /* was c077 */
-	{0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0, 0x00, 0x00}, /* 27 */
-	{0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0, 0x00, 0x00}, /* 28 */
-	{0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 29 - 1280x960-60 */
-	{0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 2a - 1280x960-85 */
-	{0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0, 0x00, 0x00}, /* 2b */
-	{0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0, 0x00, 0x00}, /* 2c */	/* VCLK 0x09 */
-	{0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2d */
-	{0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2e */
-	{0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2f */
-	{0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 30 */
-	{0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 31 */
-	{0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 32 */
-	{0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 33 */
-	{0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 34 */
-	{0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 35 */
-	{0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 36 1152x864-60Hz  */
-	{0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 37 1152x864-75Hz */
-	{0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 38 1152x864-85Hz */
-	{0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 39 848x480-38Hzi */
-	{0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 3a 848x480-60Hz  */
-	{0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3b 856x480-38Hzi */
-	{0xc067,0x42,0x28,0x0c,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3c 856x480-60Hz  */
-	{0x0067,0x43,0x3e,0x0d,0x1b,0x48,1360, 768, 0, 0x00, 0x00}, /* 3d 1360x768-60Hz */
-	{0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0, 0x00, 0x00}, /* 3e 1280x768-60Hz */
-	{0x006f,0x47,0x4c,0x06,0x15,0x5f, 768, 576, 0, 0x00, 0x00}, /* 3f 768x576 */
-	{0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0, 0x00, 0x00}, /* 40 1360x1024-59Hz (BARCO1366 only) */
-	{0xffff,   0,   0,   0,   0,   0,   0,   0, 0, 0x00, 0x00}
-};
-
-static const struct SiS_VBMode SiS300_VBModeIDTable[] =
-{
-	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
-	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
-	{0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x02},
-	{0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x00},
-	{0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x01},
-	{0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x02},
-	{0x05,0x00,0x00,0x01,0x04,0x00,0x00,0x00},
-	{0x06,0x00,0x00,0x01,0x05,0x00,0x02,0x00},
-	{0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x01},
-	{0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x02},
-	{0x0d,0x00,0x00,0x01,0x04,0x00,0x00,0x00},
-	{0x0e,0x00,0x00,0x01,0x05,0x00,0x02,0x00},
-	{0x0f,0x00,0x00,0x01,0x05,0x00,0x02,0x01},
-	{0x10,0x00,0x00,0x01,0x05,0x00,0x02,0x01},
-	{0x11,0x00,0x00,0x01,0x05,0x00,0x02,0x03},
-	{0x12,0x00,0x00,0x01,0x05,0x00,0x02,0x03},
-	{0x13,0x00,0x00,0x01,0x04,0x00,0x04,0x00},
-	{0x6a,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
-	{0x2e,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
-	{0x2f,0x00,0x00,0x01,0x05,0x00,0x06,0x06},
-	{0x30,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
-	{0x31,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x32,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x33,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x34,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x35,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x36,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x37,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
-	{0x38,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
-	{0x3a,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
-	{0x40,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
-	{0x41,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
-	{0x43,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
-	{0x44,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
-	{0x46,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
-	{0x47,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
-	{0x49,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
-	{0x4a,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
-	{0x4c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
-	{0x4d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
-	{0x4f,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
-	{0x50,0x00,0x00,0x01,0x04,0x00,0x05,0x07},
-	{0x51,0x00,0x00,0x01,0x07,0x00,0x07,0x09},
-	{0x52,0x00,0x00,0x01,0x00,0x00,0x09,0x0b},
-	{0x53,0x00,0x00,0x01,0x04,0x00,0x05,0x07},
-	{0x54,0x00,0x00,0x01,0x07,0x00,0x07,0x09},
-	{0x56,0x00,0x00,0x01,0x04,0x00,0x05,0x07},
-	{0x57,0x00,0x00,0x01,0x07,0x00,0x07,0x09},
-	{0x58,0x00,0x00,0x01,0x00,0x00,0x09,0x0b},
-	{0x59,0x00,0x00,0x01,0x04,0x00,0x05,0x05},
-	{0x5c,0x00,0x00,0x01,0x00,0x00,0x09,0x0b},
-	{0x5d,0x00,0x00,0x01,0x05,0x00,0x06,0x06},
-	{0x5e,0x00,0x00,0x01,0x05,0x00,0x06,0x06},
-	{0x5f,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x60,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x61,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
-	{0x62,0x00,0x00,0x01,0x05,0x00,0x06,0x08},
-	{0x63,0x00,0x00,0x01,0x07,0x00,0x08,0x0a},
-	{0x64,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c},
-	{0x65,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
-	{0x6c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
-	{0x6d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
-	{0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
-};
-
-static const struct SiS_CRT1Table SiS300_CRT1Table[] =
-{
- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,    /* 0x00 - 320x200 */
-  0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,     /* HRE [4],[15] is invalid - but correcting it does not work */
-  0x00}},
- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,    /* 0x01 */
-  0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,     /* HRE [4],[15] is invalid - but correcting it does not work */
-  0x00}},
- {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,    /* 0x02 */
-  0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
-  0x01}},
- {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
-  0x01}},
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-  0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
-  0x00}},
- {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* 0x05 - corrected 640x480-60 */
-  0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
-  0x00}},
- {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,    /* 0x06 - corrected 640x480-72 */
-  0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
-  0x00}},
- {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
-  0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
-  0x00}},
- {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
-  0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
-  0x00}},
- {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e,    /* 0x09 - corrected 640x480-100 */
-  0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
-  0x00}},
- {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e,    /* 0x0a - corrected 640x480-120 */
-  0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
-  0x00}},
- {{0x63,0x4f,0x4f,0x87,0x56,0x9d,0xfb,0x1f,
-  0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x01,
-  0x00}},
- {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
-  0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,    /* Corrected VDE, VBE */
-  0x00}},
- {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
-  0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
-  0x01}},
- {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-  0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
-  0x01}},
- {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
-  0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
-  0x01}},
- {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
-  0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
-  0x01}},
- {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
-  0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
-  0x01}},
- {{0x8c,0x63,0x63,0x87,0x72,0x16,0x7e,0xf0,
-  0x59,0x8d,0x57,0x57,0x7f,0x00,0x00,0x06,
-  0x01}},
- {{0x7e,0x63,0x63,0x82,0x6c,0x14,0x75,0xe0,
-  0x58,0x0b,0x57,0x57,0x76,0x20,0x00,0x06,
-  0x01}},
- {{0x7e,0x63,0x63,0x82,0x6c,0x14,0x75,0xe0,   /* 0x14 */
-  0x58,0x0b,0x57,0x57,0x76,0x20,0x00,0x06,
-  0x01}},
- {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
-  0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
-  0x00}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-  0x01}},
- {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
-  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-  0x01}},
- {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
-  0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
-  0x01}},
- {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
-  0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
-  0x01}},
- {{0x9f,0x7f,0x7f,0x83,0x83,0x93,0x1e,0xf5,  /* 0x1a */
-  0x00,0x84,0xff,0xff,0x1f,0x10,0x00,0x02,
-  0x01}},
- {{0xa2,0x7f,0x7f,0x86,0x84,0x94,0x37,0xf5,
-  0x0b,0x82,0xff,0xff,0x38,0x10,0x00,0x02,
-  0x01}},
- {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
-  0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
-  0x00}},
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
-  0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
-  0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,  /* 0x1e */
-  0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
-  0x01}},
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
-  0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
-  0x01}},
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-  0x00}},
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-  0x00}},
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-  0x00}},
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-  0x00}},
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,  /* 36: 1600x1200x85Hz */
-  0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-  0x00}},
- {{0x3f,0xef,0xef,0x83,0xfd,0x1a,0xda,0x1f,  /* 37: 1920x1440x60Hz */
-  0xa0,0x84,0x9f,0x9f,0xdb,0x1f,0x01,0x01,
-  0x00}},
- {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
-  0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
-  0x00}},
- {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,  /* 0x27: 1280x960-60 - correct */
-  0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
-  0x01}},
- {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,  /* 0x28 */
-  0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
-  0x01}},
- {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
-  0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
-  0x01}},
- {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
-  0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
-  0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
-  0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
-  0x01}},
- {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
-  0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
-  0x01}},
- {{0xa7,0x7f,0x7f,0x88,0x89,0x15,0x26,0xf1,
-  0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
-  0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
-  0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-  0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
-  0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-  0x01}},
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
-  0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
-  0x01}},
- {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
-  0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
-  0x00}},
- {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,  /* 0x32: 720x576, corrected to 60Hz */
-  0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
-  0x41}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,  /* 0x33 - 1024x600 */
-  0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
-  0x01}},
- {{0xa3,0x8f,0x8f,0x97,0x96,0x97,0x24,0xf5,  /* 0x34 - 1152x768 - corrected */
-  0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-  0x01}},
- {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,  /* 0x35 */
-   0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
-   0x01}}, /* 0x35 */
- {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
-   0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
-   0x01}}, /* 0x36 */
- {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
-   0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
-   0x01}}, /* 0x37 */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
-   0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
-   0x01}}, /* 0x38 */
- {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
-   0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
-   0x01}}, /* 0x39 */
- {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,  /* 95 was 15 - illegal HBE! */
-   0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
-   0x01}}, /* 0x3a */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
-   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-   0x01}}, /* 0x3b */
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
-   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-   0x01}}, /* 0x3c */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
-   0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
-   0x01}}, /* 0x3d */
- {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,  /* 1152x864-75 */
-   0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
-   0x01}},  /* 0x3e */
- {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,  /* 848x480-38i */
-   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
-   0x00}}, /* 0x3f */
- {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,  /* 848x480-60  */
-   0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
-   0x00}}, /* 0x40 */
- {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,  /* 856x480-38i */
-   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
-   0x00}}, /* 0x41 */
- {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,  /* 856x480-60  */
-   0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
-   0x00}}, /* 0x42 */
- {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,  /* 1360x768-60 */
-   0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
-   0x01}}, /* 0x43 */
- {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,  /* 1152x864-84 */
-   0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
-   0x01}}, /* 0x44 */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,  /* 1280x960-85 */
-   0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
-   0x01}}, /* 0x45 */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,  /* 1280x768-60 */
-   0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
-   0x01}}, /* 0x46 */
- {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,  /* 768x576, corrected to 60Hz */
-   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
-   0x41}}, /* 0x47 */
- {{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52,  /* 1360x1024 (Barco iQ Pro R300) */
-   0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03,
-   0x00}}, /* 0x48 */
- {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,  /* 1152x864-60 */
-   0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
-   0x41}}, /* 0x49 */
- {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
-   0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
-   0x40}}, /* 0x4a */
- {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
-   0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
-   0x00}}  /* 0x4b */
-};
-
-static const struct SiS_MCLKData SiS300_MCLKData_630[] =
-{
-	{ 0x5a,0x64,0x80, 66},
-	{ 0xb3,0x45,0x80, 83},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x22,0x80,133},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x61,0x80,100}
-};
-
-static const struct SiS_MCLKData SiS300_MCLKData_300[] =
-{
-	{ 0x68,0x43,0x80,125},
-	{ 0x68,0x43,0x80,125},
-	{ 0x68,0x43,0x80,125},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x61,0x80,100},
-	{ 0x37,0x61,0x80,100}
-};
-
-static struct SiS_VCLKData SiS300_VCLKData[] =
-{
-	{ 0x1b,0xe1, 25}, /* 0x00 */
-	{ 0x4e,0xe4, 28}, /* 0x01 */
-	{ 0x57,0xe4, 32}, /* 0x02 */
-	{ 0xc3,0xc8, 36}, /* 0x03 */
-	{ 0x42,0xc3, 40}, /* 0x04 */
-	{ 0x5d,0xc4, 45}, /* 0x05 */
-	{ 0x52,0x65, 50}, /* 0x06 */
-	{ 0x53,0x65, 50}, /* 0x07 */
-	{ 0x6d,0x66, 56}, /* 0x08 */
-	{ 0x5a,0x64, 65}, /* 0x09 */
-	{ 0x46,0x44, 68}, /* 0x0a */
-	{ 0x3e,0x43, 75}, /* 0x0b */
-	{ 0x6d,0x46, 76}, /* 0x0c */  /* 800x600 | LVDS_2(CH), MITAC(CH);  - 730, A901(301B): 0xb1,0x46, 76 */
-	{ 0x41,0x43, 79}, /* 0x0d */
-	{ 0x31,0x42, 79}, /* 0x0e */
-	{ 0x46,0x25, 85}, /* 0x0f */
-	{ 0x78,0x29, 87}, /* 0x10 */
-	{ 0x62,0x44, 95}, /* 0x11 */
-	{ 0x2b,0x22,105}, /* 0x12 */
-	{ 0x49,0x24,106}, /* 0x13 */
-	{ 0xc3,0x28,108}, /* 0x14 */
-	{ 0x3c,0x23,109}, /* 0x15 */
-	{ 0xf7,0x2c,132}, /* 0x16 */
-	{ 0xd4,0x28,136}, /* 0x17 */
-	{ 0x41,0x05,158}, /* 0x18 */
-	{ 0x43,0x05,162}, /* 0x19 */
-	{ 0xe1,0x0f,175}, /* 0x1a */
-	{ 0xfc,0x12,189}, /* 0x1b */
-	{ 0xde,0x26,194}, /* 0x1c */
-	{ 0x54,0x05,203}, /* 0x1d */
-	{ 0x3f,0x03,230}, /* 0x1e */
-	{ 0x30,0x02,234}, /* 0x1f */
-	{ 0x24,0x01,266}, /* 0x20 */
-	{ 0x52,0x2a, 54}, /* 0x21 */  /* 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x22 */  /* 301 TV */
-	{ 0x62,0x24, 70}, /* 0x23 */  /* 301 TV */
-	{ 0x62,0x64, 70}, /* 0x24 */  /* 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x25 */  /* 301 TV */
-	{ 0x20,0x26, 33}, /* 0x26 */  /* 301 TV */
-	{ 0x31,0xc2, 39}, /* 0x27 */
-	{ 0xbf,0xc8, 35}, /* 0x28 */  /* 856x480 */
-	{ 0x60,0x36, 30}, /* 0x29 */  /* CH/UNTSC TEXT | LVDS_2(CH) - 730, A901(301B), Mitac(CH): 0xe0, 0xb6, 30 */
-	{ 0x40,0x4a, 28}, /* 0x2a */  /* CH-TV */
-	{ 0x9f,0x46, 44}, /* 0x2b */  /* CH-TV */
-	{ 0x97,0x2c, 26}, /* 0x2c */  /* CH-TV */
-	{ 0x44,0xe4, 25}, /* 0x2d */  /* CH-TV */
-	{ 0x7e,0x32, 47}, /* 0x2e */  /* CH-TV */
-	{ 0x8a,0x24, 31}, /* 0x2f */  /* CH/PAL TEXT | LVDS_2(CH), Mitac(CH) -  730, A901(301B): 0x57, 0xe4, 31 */
-	{ 0x97,0x2c, 26}, /* 0x30 */  /* CH-TV */
-	{ 0xce,0x3c, 39}, /* 0x31 */  /* CH-TV */
-	{ 0x52,0x4a, 36}, /* 0x32 */  /* CH/PAL 800x600 5/6 */
-	{ 0x34,0x61, 95}, /* 0x33 */
-	{ 0x78,0x27,108}, /* 0x34 */  /* Replacement for index 0x14 for 630 (?) */
-	{ 0x70,0x28, 90}, /* 0x35 */  /* 1152x864@60 */
-	{ 0x45,0x6b, 21}, /* 0x36 */  /* Chrontel SuperOverscan */
-	{ 0x52,0xe2, 49}, /* 0x37 */  /* 16:9 modes  */
-	{ 0x2b,0x61, 78}, /* 0x38 */  /* 16:9 modes  */
-	{ 0x70,0x44,108}, /* 0x39 */  /* 16:9 modes  */
-	{ 0x54,0x42,135}, /* 0x3a */  /* 16:9 modes  */
-	{ 0x41,0x22,157}, /* 0x3b */  /* 16:9 modes  */
-	{ 0x52,0x07,149}, /* 0x3c */  /* 1280x960-85 */
-	{ 0x62,0xc6, 34}, /* 0x3d */  /* 848x480-60  */
-	{ 0x30,0x23, 88}, /* 0x3e */  /* 1360x768-60 */
-        { 0x70,0x29, 81}, /* 0x3f */  /* 1280x768-60 */
-	{ 0x72,0x2a, 76}, /* 0x40 */  /* test for SiS730 --- LIMIT for table (&0x3f) */
-	{ 0x15,0x21, 79}, /* 0x41 */  /* test for SiS730 */
-	{ 0xa1,0x42,108}, /* 0x42 */  /* 1280x960 LCD */
-	{ 0x37,0x61,100}, /* 0x43 */  /* 1280x960 LCD */
-	{ 0xe3,0x9a,106}, /* 0x44 */  /* 1360x1024 - special for Barco iQ R300 */
-	{ 0xe2,0x46,135}, /* 0x45 */  /* 1280x1024-75, better clock for VGA2 */
-	{ 0x70,0x29, 81}, /* 0x46 */  /* unused */
-	{    0,   0,  0}, /* 0x47 custom (will be filled out) */
-	{ 0xce,0x25,189}, /* 0x48 */  /* Replacement for index 0x1b for 730 (and 540?) */
-	{ 0x15,0xe1, 20}, /* 0x49 */  /* 640x400@60 (fake, not actually used) */
-	{ 0x5f,0xc6, 33}, /* 0x4a */  /* 720x576@60 */
-	{ 0x37,0x5a, 10}, /* 0x4b */  /* 320x200@60 (fake, not actually used) */
-	{ 0x2b,0xc2, 35}  /* 0x4c */  /* 768@576@60 */
-};
-
-static const unsigned char SiS300_SR15[4 * 8] =
-{
-	0x01,0x09,0xa3,0x00,
-	0x43,0x43,0x43,0x00,
-	0x1e,0x1e,0x1e,0x00,
-	0x2a,0x2a,0x2a,0x00,
-	0x06,0x06,0x06,0x00,
-	0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00
-};
-
-static const struct SiS_PanelDelayTbl SiS300_PanelDelayTbl[] =
-{
-	{{0x05,0xaa}},
-	{{0x05,0x14}},
-	{{0x05,0x36}},
-	{{0x05,0x14}},
-	{{0x05,0x14}},
-	{{0x05,0x14}},
-	{{0x05,0x90}},
-	{{0x05,0x90}},
-	{{0x05,0x14}},
-	{{0x05,0x14}},
-	{{0x05,0x14}},
-	{{0x05,0x14}},
-	{{0x20,0x80}},
-	{{0x05,0x14}},
-	{{0x05,0x40}},
-	{{0x05,0x60}}
-};
-
-/**************************************************************/
-/* SIS VIDEO BRIDGE ----------------------------------------- */
-/**************************************************************/
-
-static const struct SiS_LCDData SiS300_St2LCD1024x768Data[] =
-{
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const struct SiS_LCDData SiS300_ExtLCD1024x768Data[] =
-{
-	{   12,   5, 896, 512,1344, 806},
-	{   12,   5, 896, 510,1344, 806},
-	{   32,  15,1008, 505,1344, 806},
-	{   32,  15,1008, 514,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const struct SiS_LCDData SiS300_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const struct SiS_LCDData SiS300_ExtLCD1280x1024Data[] =
-{
-	{  211,  60,1024, 501,1688,1066},
-	{  211,  60,1024, 508,1688,1066},
-	{  211,  60,1024, 501,1688,1066},
-	{  211,  60,1024, 508,1688,1066},
-	{  211,  60,1024, 500,1688,1066},
-	{  211,  75,1024, 625,1688,1066},
-	{  211, 120,1280, 798,1688,1066},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_1[] =
-{ /* VESA Timing */
-	{{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
-	{{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
-	{{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
-	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
-	{{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
-	{{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
-	{{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
-};
-
-static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_2[] =
-{  /* Non-VESA */
-	{{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
-};
-
-static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_3[] =
-{
-	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-/**************************************************************/
-/* LVDS/Chrontel -------------------------------------------- */
-/**************************************************************/
-
-/* Custom data for Barco iQ R series */
-static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_1[]=
-{
-	{ 832, 438,1331, 806},
-	{ 832, 388,1331, 806},
-	{ 832, 438,1331, 806},
-	{ 832, 388,1331, 806},
-	{ 832, 518,1331, 806},
-	{1050, 638,1344, 806},
-	{1344, 806,1344, 806},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066}   /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ R series */
-static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_2[]=
-{
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066}   /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ G series */
-static const struct SiS_LVDSData SiS300_LVDSBARCO1024Data_1[]=
-{
-	{ 832, 438,1331, 806},
-	{ 832, 409,1331, 806},
-	{ 832, 438,1331, 806},
-	{ 832, 409,1331, 806},
-	{ 832, 518,1331, 806},   /* 640x480 */
-	{1050, 638,1344, 806},   /* 800x600 */
-	{1344, 806,1344, 806},   /* 1024x768 */
-};
-
-/* Custom data for 848x480 and 856x480 parallel LVDS panels */
-static const struct SiS_LVDSData SiS300_LVDS848x480Data_1[]=
-{
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{1088, 525,1088, 525},  /* 640x480 TODO */
-	{1088, 525,1088, 525},  /* 800x600 TODO */
-	{1088, 525,1088, 525},  /* 1024x768 TODO */
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{1088, 525,1088, 525},  /* 848x480 */
-	{1088, 525,1088, 525},  /* 856x480 */
-	{1088, 525,1088, 525}   /* 1360x768 TODO */
-};
-
-/* Custom data for 848x480 parallel panel */
-static const struct SiS_LVDSData SiS300_LVDS848x480Data_2[]=
-{
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{1088, 525,1088, 525},  /*  640x480 */
-	{1088, 525,1088, 525},  /*  800x600 */
-	{1088, 525,1088, 525},  /* 1024x768 */
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{   0,   0,   0,   0},
-	{1088, 525,1088, 525},  /* 848x480 */
-	{1088, 525,1088, 525},  /* 856x480 */
-	{1088, 525,1088, 525}	/* 1360x768 TODO */
-};
-
-static const struct SiS_LVDSData SiS300_CHTVUPALData[] =
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 750, 840, 750},
-	{ 936, 836, 936, 836}
-};
-
-static const struct SiS_LVDSData SiS300_CHTVOPALData[] =
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 625, 840, 625},
-	{ 960, 750, 960, 750}
-};
-
-static const struct SiS_LVDSData SiS300_CHTVSOPALData[] =
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 500, 840, 500},
-	{ 944, 625, 944, 625}
-};
-
-/* Custom des data for Barco iQ R200/300/400 (BIOS 2.00.07) */
-static const struct SiS_LVDSDes SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
-{
-	{1330, 798},  /* 320x200 */
-	{1330, 794},
-	{1330, 798},
-	{1330, 794},
-	{1330,   0},  /* 640x480 / 320x240  */
-	{1343,   0},  /* 800x600 / 400x300  */
-	{   0, 805},  /* 1024x768 / 512x384 */
-	{1688,1066},  /* 1280x1024          */
-	{   0,   0}   /* 1360x1024          */
-};
-
-static const struct SiS_LVDSDes SiS300_PanelType04_2a[] =
-{
-	{1152, 622},
-	{1152, 597},
-	{1152, 622},
-	{1152, 597},
-	{1152, 662},
-	{1232, 722},
-	{   0, 805},
-	{1688,1066},
-	{   0,   0}
-};
-
-/* Custom des data for Barco iQ G200/300/400 (BIOS 2.00.07) */
-static const struct SiS_LVDSDes SiS300_PanelType04_1b[] =	/* 1024x768 */
-{
-	{1330, 798},  /* 320x200 */
-	{1330, 794},
-	{1330, 798},
-	{1330, 794},
-	{1330,   0},  /* 640x480 / 320x240  */
-	{1343,   0},  /* 800x600 / 400x300  */
-	{   0, 805}   /* 1024x768 / 512x384 */
-};
-
-static const struct SiS_LVDSDes SiS300_PanelType04_2b[] =
-{
-	{1152, 622},
-	{1152, 597},
-	{1152, 622},
-	{1152, 597},
-	{1152, 662},
-	{1232, 722},
-	{   0, 805}
-};
-
-/* CRT1 CRTC for slave modes */
-
-static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UNTSC[] =
-{
-	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-	  0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-	  0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-	  0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-	  0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
-	  0x00 }},
-	{{0x5d,0x4f,0x81,0x53,0x9c,0x56,0xba,
-	  0x18,0x84,0xdf,0x57,0x00,0x00,0x01,
-	  0x00 }},
-	{{0x80,0x63,0x84,0x6c,0x17,0xec,0xf0,
-	  0x90,0x8c,0x57,0xed,0x20,0x00,0x06,
-	  0x01 }}
-};
-
-static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1ONTSC[] =
-{
-	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
-	  0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
-	  0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
-	  0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
-	  0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
-	  0x00 }},
-	{{0x5d,0x4f,0x81,0x56,0x9c,0x0b,0x3e,
-	  0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,
-	  0x00 }},
-	{{0x7d,0x63,0x81,0x6a,0x16,0xba,0xf0,
-	  0x7f,0x86,0x57,0xbb,0x00,0x00,0x06,
-	  0x01 }}
-};
-
-static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UPAL[] =
-{
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x55,0x80,0xec,0xba,
-	  0x50,0x84,0xdf,0xed,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x70,0x63,0x94,0x68,0x8d,0x42,0xf1,
-	  0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05,
-	  0x01 }}
-};
-
-static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1OPAL[] =
-{
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba,
-	  0x20,0x83,0xdf,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0,
-	  0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
-	  0x01 }}
-};
-
-static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1SOPAL[] =
-{
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
-	  0x00 }},
-	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-	  0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba,  /* TODO */
-	  0x20,0x83,0xdf,0x70,0x00,0x00,0x05,
-	  0x00 }},
-	{{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0,  /* TODO */
-	  0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
-	  0x01 }}
-};
-
-static const struct SiS_CHTVRegData SiS300_CHTVReg_UNTSC[] =
-{
-	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x6a,0x6a,0x00,0x2d,0xfa,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 17: 640x480 NTSC 7/8  */
-	{{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 24: 800x600 NTSC 7/10 */
-};
-
-static const struct SiS_CHTVRegData SiS300_CHTVReg_ONTSC[] =
-{
-	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x69,0x6a,0x00,0x1e,0xfd,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 16: 640x480 NTSC 1/1 */
-	{{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 23: 800x600 NTSC 3/4 */
-};
-
-static const struct SiS_CHTVRegData SiS300_CHTVReg_UPAL[] =
-{
-	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x63,0x94,0x01,0x50,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 15: 640x480 PAL 5/6 */
-	{{0x84,0x64,0x01,0x4e,0x2f,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 21: 800x600 PAL 3/4 */
-
-};
-
-static const struct SiS_CHTVRegData SiS300_CHTVReg_OPAL[] =
-{
-	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
-	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x61,0x94,0x01,0x36,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 14: 640x480 PAL 1/1 */
-	{{0x83,0x76,0x01,0x40,0x31,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 20: 800x600 PAL 5/6 */
-
-};
-
-static const struct SiS_CHTVRegData SiS300_CHTVReg_SOPAL[] =
-{
-	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
-	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
-	{{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 13: 640x480 PAL 5/4 */
-	{{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 19: 800x600 PAL 1/1 */
-};
-
-static const unsigned char SiS300_CHTVVCLKUNTSC[]  = { 0x29,0x29,0x29,0x29,0x2a,0x2e };
-
-static const unsigned char SiS300_CHTVVCLKONTSC[]  = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
-
-static const unsigned char SiS300_CHTVVCLKSONTSC[] = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
-
-static const unsigned char SiS300_CHTVVCLKUPAL[]   = { 0x2f,0x2f,0x2f,0x2f,0x2f,0x31 };
-
-static const unsigned char SiS300_CHTVVCLKOPAL[]   = { 0x2f,0x2f,0x2f,0x2f,0x30,0x32 };
-
-static const unsigned char SiS300_CHTVVCLKSOPAL[]  = { 0x2f,0x2f,0x2f,0x2f,0x36,0x29 };
-
-
diff --git a/drivers/video/sis/310vtbl.h b/drivers/video/sis/310vtbl.h
deleted file mode 100644
index 54fcbbf4ef63..000000000000
--- a/drivers/video/sis/310vtbl.h
+++ /dev/null
@@ -1,1339 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * Register settings for SiS 315/330/340 series
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-static const struct SiS_Ext SiS310_EModeIDTable[] =
-{
-	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
-	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
-	{0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
-	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
-	{0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
-	{0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
-	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
-	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
-	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
-	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
-	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x? */
-	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
-	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x8 */
-	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x8 */
-	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x16 */
-	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x15 */
-	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x16 */
-	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2},
-	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
-	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3},
-	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
-	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13, 4},
-	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
-	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8},
-	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
-	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8  */
-	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8  */
-	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8  */
-	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
-	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
-	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
-	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8  */
-	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8  fstn */
-	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
-	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x32 */
-	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0},
-	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
-	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
-	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
-	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
-	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x32 */
-	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x32 */
-	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x8 */
-	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x16 */
-	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x32 */
-	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x8 */
-	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x16 */
-	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x32 */
-	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x8 */
-	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x8 */
-	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x16 */
-	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x16 */
-	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x32 */
-	{0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x32 */
-	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x32 */
-	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x8 */
-	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x16 */
-	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x8 */
-	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x16 */
-	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x32 */
-	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
-	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
-	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
-	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x8 */
-	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x16 */
-	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x32*/
-	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1}, /* 1152x864 */
-	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
-	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
-	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1}, /* 848x480 */
-	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1},
-	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1},
-	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1}, /* 856x480 */
-	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1},
-	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1},
-	{0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1}, /* 1360x768 */
-	{0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
-	{0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
-	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
-	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
-	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
-	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1}, /* 768x576 */
-	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1},
-	{0x61,0x6a3f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1},
-	{0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7}, /* 1280x800 */
-	{0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
-	{0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
-	{0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9}, /* 1680x1050 */
-	{0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
-	{0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
-	{0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1}, /* 1920x1080(i) */
-	{0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
-	{0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
-	{0x1d,0x6a1b,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1}, /* 960x540 */
-	{0x1e,0x6a3d,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1},
-	{0x1f,0x6a7f,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1},
-	{0x20,0x6a1b,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1}, /* 960x600 */
-	{0x21,0x6a3d,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1},
-	{0x22,0x6a7f,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1},
-	{0x1a,0x0e3b,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8}, /* 1280x854 */
-	{0x1b,0x0e7d,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
-	{0x1c,0x0eff,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
-	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
-};
-
-static const struct SiS_Ext2 SiS310_RefIndex[] =
-{
-	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x0 */
-	{0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1 */
-	{0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2 */
-	{0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3 */
-	{0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4 */
-	{0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x5 */
-	{0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x6 */
-	{0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x7 */
-	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x8 */
-	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x9 */
-	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xa */
-	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xb */
-	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xc */
-	{0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xd */
-	{0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xe */
-	{0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xf */
-	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e, 0x00, 0x00, 0x00, 0x00}, /* 0x10 */
-	{0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x11 */
-	{0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x12 (6f was 03) */
-	{0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x13 */
-	{0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x14 */
-	{0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x15 */
-	{0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x16 */
-	{0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x17 */
-	{0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x18 */
-	{0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x19 */
-	{0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1a */
-	{0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1b */
-	{0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1c */
-	{0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1d */
-	{0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1e */
-	{0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1f */
-	{0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x20 */
-	{0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x21 */
-	{0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x22 */
-	{0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x23 */
-	{0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x24 */
-	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30, 0x56, 0x4e, 0x00, 0x00, 0x00, 0x00}, /* 0x25 */
-	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x26 */
-	{0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x27 */
-	{0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x28 */
-	{0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x29 */
-	{0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2a */
-	{0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2b */
-	{0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2c */
-	{0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2d */
-	{0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2e */
-	{0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2f */
-	{0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x30 */
-	{0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x31 */
-	{0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x32 */
-	{0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x33 */
-	{0x2077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x32, 0x40, 0x5e, 0x73}, /* 0x34 */
-	{0x2047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x33, 0x07, 0xff, 0xff}, /* 0x35 */
-	{0x2047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x34, 0x0a, 0xff, 0xff}, /* 0x36 */
-	{0x2077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x35, 0x0b, 0x5f, 0x74}, /* 0x37 */
-	{0x2047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x36, 0x11, 0xff, 0xff}, /* 0x38 */
-	{0x2047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x37, 0x16, 0xff, 0xff}, /* 0x39 */
-	{0x3137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x38, 0x19, 0x60, 0x75}, /* 0x3a */
-	{0x3107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x39, 0x1e, 0xff, 0xff}, /* 0x3b */
-	{0x3307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x3a, 0x20, 0xff, 0xff}, /* 0x3c */
-	{0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3d */
-	{0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3e */
-	{0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3f */    /* FSTN 320x240 */
-	{0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x58, 0x19, 0x42, 0x5b}, /* 0x40 */    /* 0x5b was 0x12 */
-	{0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x59, 0x1e, 0xff, 0xff}, /* 0x41 */
-	{0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x5a, 0x20, 0xff, 0xff}, /* 0x42 */
-	{0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x43 */
-	{0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x44 1400x1050-75Hz */
-	{0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x45 1152x864-60Hz  */
-	{0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x46 1152x864-75Hz  */
-	{0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x47 1152x864-85Hz  */
-	{0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x48 848x480-38Hzi  */
-	{0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x49 848x480-60Hz   */
-	{0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4a 856x480-38Hzi  */
-	{0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4b 856x480-60Hz   */
-	{0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4c 1360x768-60Hz  */
-	{0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4d 768x576-56Hz   */
-	{0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5b, 0x19, 0x4f, 0x5c}, /* 0x4e 1280x800-60Hz  */
-	{0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5c, 0x1e, 0xff, 0xff}, /* 0x4f 1280x800-75Hz  */
-	{0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5d, 0x20, 0xff, 0xff}, /* 0x50 1280x800-85Hz  */
-	{0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x51 1680x1050-60Hz */
-	{0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x52 1920x1080 60Hzi */
-	{0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x53 960x540 60Hz */
-	{0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x54 960x600 60Hz */
-	{0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x62, 0x19, 0x61, 0x76}, /* 0x55 1280x854-60Hz  */
-	{0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x63, 0x1e, 0xff, 0xff}, /* 0x56 1280x854-75Hz  */
-	{0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x64, 0x20, 0xff, 0xff}, /* 0x57 1280x854-85Hz  */
-	{0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct SiS_CRT1Table SiS310_CRT1Table[] =
-{
- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},  /* 0x0 */
- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
-   0x00}},  /* 0x1 */
- {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
-   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
-   0x01}},  /* 0x2 */
- {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
-   0x01}},  /* 0x3 */
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},  /* 0x4 */
- {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* corrected 640x480-60 */
-   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
-   0x00}},  /* 0x5 */
- {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,    /* corrected 640x480-72 */
-   0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
-   0x00}},  /* 0x6 */
- {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
-   0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
-   0x00}},  /* 0x7 */
- {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
-   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
-   0x00}},  /* 0x8 */
- {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
-   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* Corrected VBE */
-   0x61}},  /* 0x9 */
- {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
-   0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
-   0x61}},  /* 0xa */
- {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
-   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* Corrected VBE */
-   0x61}},  /* 0xb */
- {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
-   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* Corrected VDE, VBE */
-   0x00}},  /* 0xc */
- {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
-   0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
-   0x01}},  /* 0xd */
- {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
-   0x01}},  /* 0xe */
- {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
-   0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
-   0x01}},  /* 0xf */
- {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
-   0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
-   0x01}},  /* 0x10 */
- {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
-   0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
-   0x01}},  /* 0x11 */
- {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
-   0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
-   0x61}},  /* 0x12 */
- {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
-   0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
-   0x61}},  /* 0x13 */
- {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
-   0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
-   0x61}},  /* 0x14 */
- {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
-   0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
-   0x00}},  /* 0x15 */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}},  /* 0x16 */
- {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}},  /* 0x17 */
- {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
-   0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
-   0x01}},  /* 0x18 */
- {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
-   0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
-   0x01}},  /* 0x19 */
- {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
-   0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
-   0x62}},  /* 0x1a */
- {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
-   0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
-   0x62}},  /* 0x1b */
- {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
-   0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
-   0x00}},  /* 0x1c */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
-   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
-   0x01}},  /* 0x1d */
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
-   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
-   0x01}},  /* 0x1e */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
-   0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
-   0x01}},  /* 0x1f */
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}},  /* 0x20 */
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}},  /* 0x21 */
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}},  /* 0x22 */
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}},  /* 0x23 */
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}},  /* 0x24 */
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}},  /* 0x25 */
- {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
-   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}},  /* 0x26 */
- {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
-   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}},  /* 0x27 */
- {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
-   0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
-   0x63}},  /* 0x28 */
- {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
-   0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
-   0x63}},  /* 0x29 */
- {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
-   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}},  /* 0x2a */
- {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
-   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}},  /* 0x2b */
- {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
-   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}},  /* 0x2c */
- {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
-   0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
-   0x44}},  /* 0x2d */
- {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
-   0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
-   0x44}},  /* 0x2e */
- {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
-   0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
-   0x44}},  /* 0x2f */
- {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
-   0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
-   0x44}},  /* 0x30 */
- {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
-   0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
-   0x00}},  /* 0x31 */
- {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
-   0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
-   0x01}},  /* 0x32 */
- {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
-   0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
-   0x01}},  /* 0x33 */
- {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
-   0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
-   0x01}},  /* 0x34 */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
-   0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
-   0x01}},  /* 0x35 */
- {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
-   0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
-   0x01}},  /* 0x36 */
- {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* 95 was 15 - illegal HBE! */
-   0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
-   0x01}},  /* 0x37 */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
-   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-   0x01}},  /* 0x38 */
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
-   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-   0x01}},  /* 0x39 */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
-   0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
-   0x01}},  /* 0x3a */
- {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,	/* 1280x960-60 - corrected */
-   0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
-   0x01}},  /* 0x3b */
- {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
-   0x00}},  /* 0x3c */
- {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,	/* 720x576, corrected to 60Hz */
-   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
-   0x41}},  /* 0x3d */
- {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
-   0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
-   0x00}},  /* 0x3e */
- {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
-   0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
-   0x00}},  /* 0x3f */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
-   0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
-   0x01}},  /* 0x40 */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}},  /* 0x41 */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
-   0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
-   0x01}},  /* 0x42 */
- {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
-   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
-   0x00}},  /* 0x43 */
- {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */
-   0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
-   0x01}},  /* 0x44 */
- {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */
-   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
-   0x00}},  /* 0x45 */
- {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */
-   0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
-   0x00}},  /* 0x46 */
- {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */
-   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
-   0x00}},  /* 0x47 */
- {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */
-   0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
-   0x00}},  /* 0x48 */
- {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */
-   0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
-   0x01}},  /* 0x49 */
- {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84  */
-   0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
-   0x01}},  /* 0x4a */
- {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* 1400x1050-75  */
-   0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
-   0x00}},  /* 0x4b */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
-   0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
-   0x01}},  /* 0x4c */
- {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, /* 768x576, corrected to 60Hz */
-   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
-   0x41}},  /* 0x4d */
- {{0x5f,0x27,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* FSTN 320x240 (working) */
-   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
-   0x00}},  /* 0x4e */
- {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
-   0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
-   0x21}},  /* 0x4f */
- {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, /* 1680x1050-60 */
-   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
-   0x20}},  /* 0x50 */
- {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0, /* 1920x1080-60i */
-   0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
-   0x61}},  /* 0x51 */
- {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0, /* 960x540-60 */
-   0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
-   0x41}},  /* 0x52 */
- {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0, /* 960x600-60 */
-   0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
-   0x01}},  /* 0x53 */
- {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */
-   0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
-   0x41}},  /* 0x54 */
- {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
-   0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
-   0x40}},  /* 0x55 */
- {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
-   0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
-   0x00}},  /* 0x56 */
- {{0xd7,0xc7,0xc7,0x9b,0xd1,0x15,0xd1,0x10, /* 1600x1200 for LCDA */
-   0xb2,0x86,0xaf,0xb0,0xd2,0x2f,0x00,0x03,
-   0x00}},  /* 0x57 */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 60 Hz */
-   0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
-   0x01}},  /* 0x58 */
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 75 Hz */
-   0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
-   0x01}},  /* 0x59 */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xdc, /* 1280x768 (1280x1024) 85 Hz */
-   0x95,0x89,0xff,0x94,0x2f,0x21,0x00,0x07,
-   0x01}},  /* 0x5a */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x800 (1280x1024) 60 Hz */
-   0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
-   0x01}},  /* 0x5b */
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x800 (1280x1024) 75 Hz */
-   0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
-   0x01}},  /* 0x5c */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x800 (1280x1024) 85 Hz */
-   0xa5,0x89,0x1f,0xa4,0x2f,0x01,0x00,0x07,
-   0x01}},  /* 0x5d */
- {{0x7f,0x63,0x63,0x83,0x6d,0x1d,0x0b,0x3e, /* 800x480 (wide) 60 Hz */
-   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x06,
-   0x00}},  /* 0x5e */
- {{0xa0,0x7f,0x7f,0x84,0x85,0x97,0x52,0xf0, /* 1024x576 (wide) 60 Hz */
-   0x41,0x85,0x3f,0x40,0x53,0x00,0x00,0x02,
-   0x01}},  /* 0x5f */
- {{0xc9,0x9f,0x9f,0x8d,0xb0,0x15,0xec,0xf0, /* 1280x720 (wide) 60 Hz */
-   0xd4,0x89,0xcf,0xd3,0xed,0x20,0x00,0x07,
-   0x01}},  /* 0x60 */
- {{0xcb,0x9f,0x9f,0x8f,0xa5,0x13,0x5b,0xff, /* 1280x854-60 wide */
-   0x56,0x89,0x55,0x55,0x5c,0x30,0x00,0x07,
-   0x01}},  /* 0x61 */
- {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x854 (1280x1024) 60 Hz */
-   0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
-   0x41}},  /* 0x62 */
- {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x854 (1280x1024) 75 Hz */
-   0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
-   0x41}},  /* 0x63 */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x854 (1280x1024) 85 Hz */
-   0xc0,0x84,0x55,0xbf,0x2f,0x01,0x00,0x07,
-   0x41}}   /* 0x64 */
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_0_315[] =
-{
-	{ 0x3b,0x22,0x01,143},
-	{ 0x5c,0x23,0x01,166},
-	{ 0x5c,0x23,0x01,166},
-	{ 0x5c,0x23,0x01,166},
-	{ 0x5c,0x23,0x01,166},
-	{ 0x5c,0x23,0x01,166},
-	{ 0x5c,0x23,0x01,166},
-	{ 0x5c,0x23,0x01,166}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_0_650[] =
-{
-	{ 0x5a,0x64,0x82, 66},
-	{ 0xb3,0x45,0x82, 83},
-	{ 0x37,0x61,0x82,100},
-	{ 0x37,0x22,0x82,133},
-	{ 0x37,0x61,0x82,100},
-	{ 0x37,0x22,0x82,133},
-	{ 0x37,0x22,0x82,133},
-	{ 0x37,0x22,0x82,133}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_0_330[] =
-{
-	{ 0x5c,0x23,0x01,166},
-	{ 0x5c,0x23,0x01,166},
-	{ 0x7c,0x08,0x01,200},
-	{ 0x79,0x06,0x01,250},
-	{ 0x7c,0x08,0x01,200},
-	{ 0x7c,0x08,0x01,200},
-	{ 0x7c,0x08,0x01,200},
-	{ 0x79,0x06,0x01,250}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_0_660[] =
-{
-	{ 0x5c,0x23,0x82,166},
-	{ 0x5c,0x23,0x82,166},
-	{ 0x37,0x21,0x82,200},
-	{ 0x37,0x22,0x82,133},
-	{ 0x29,0x21,0x82,150},
-	{ 0x5c,0x23,0x82,166},
-	{ 0x65,0x23,0x82,183},
-	{ 0x37,0x21,0x82,200}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_0_760[] =
-{
-	{ 0x37,0x22,0x82,133},
-	{ 0x5c,0x23,0x82,166},
-	{ 0x65,0x23,0x82,183},
-	{ 0x7c,0x08,0x82,200},
-	{ 0x29,0x21,0x82,150},
-	{ 0x5c,0x23,0x82,166},
-	{ 0x65,0x23,0x82,183},
-	{ 0x37,0x21,0x82,200}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_0_761[] =
-{
-	{ 0x37,0x22,0x82,133},  /* Preliminary */
-	{ 0x5c,0x23,0x82,166},
-	{ 0x65,0x23,0x82,183},
-	{ 0x7c,0x08,0x82,200},
-	{ 0x29,0x21,0x82,150},
-	{ 0x5c,0x23,0x82,166},
-	{ 0x65,0x23,0x82,183},
-	{ 0x37,0x21,0x82,200}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_0_340[] =
-{
-	{ 0x79,0x06,0x01,250},
-	{ 0x7c,0x08,0x01,200},
-	{ 0x7c,0x08,0x80,200},
-	{ 0x79,0x06,0x80,250},
-	{ 0x29,0x01,0x81,300},
-	{ 0x29,0x01,0x81,300},
-	{ 0x29,0x01,0x81,300},
-	{ 0x29,0x01,0x81,300}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_1[] = /* ECLK */
-{
-	{ 0x29,0x21,0x82,150},
-	{ 0x5c,0x23,0x82,166},
-	{ 0x65,0x23,0x82,183},
-	{ 0x37,0x21,0x82,200},
-	{ 0x37,0x22,0x82,133},
-	{ 0x37,0x22,0x82,133},
-	{ 0x37,0x22,0x82,133},
-	{ 0x37,0x22,0x82,133}
-};
-
-static const struct SiS_MCLKData SiS310_MCLKData_1_340[] =
-{
-	{ 0x7c,0x08,0x01,200},
-	{ 0x7c,0x08,0x01,200},
-	{ 0x7c,0x08,0x80,200},
-	{ 0x79,0x06,0x80,250},
-	{ 0x29,0x01,0x81,300},
-	{ 0x29,0x01,0x81,300},
-	{ 0x29,0x01,0x81,300},
-	{ 0x29,0x01,0x81,300}
-};
-
-static struct SiS_VCLKData SiS310_VCLKData[] =
-{
-	{ 0x1b,0xe1, 25}, /* 0x00 */
-	{ 0x4e,0xe4, 28}, /* 0x01 */
-	{ 0x57,0xe4, 31}, /* 0x02 */
-	{ 0xc3,0xc8, 36}, /* 0x03 */
-	{ 0x42,0xe2, 40}, /* 0x04 */
-	{ 0xfe,0xcd, 43}, /* 0x05 */
-	{ 0x5d,0xc4, 44}, /* 0x06 */
-	{ 0x52,0xe2, 49}, /* 0x07 */
-	{ 0x53,0xe2, 50}, /* 0x08 */
-	{ 0x74,0x67, 52}, /* 0x09 */
-	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x5a,0x64, 65}, /* 0x0b */  /* was 6c c3 - WRONG */
-	{ 0x46,0x44, 67}, /* 0x0c */
-	{ 0xb1,0x46, 68}, /* 0x0d */
-	{ 0xd3,0x4a, 72}, /* 0x0e */
-	{ 0x29,0x61, 75}, /* 0x0f */
-	{ 0x6e,0x46, 76}, /* 0x10 */
-	{ 0x2b,0x61, 78}, /* 0x11 */
-	{ 0x31,0x42, 79}, /* 0x12 */
-	{ 0xab,0x44, 83}, /* 0x13 */
-	{ 0x46,0x25, 84}, /* 0x14 */
-	{ 0x78,0x29, 86}, /* 0x15 */
-	{ 0x62,0x44, 94}, /* 0x16 */
-	{ 0x2b,0x41,104}, /* 0x17 */
-	{ 0x3a,0x23,105}, /* 0x18 */
-	{ 0x70,0x44,108}, /* 0x19 */
-	{ 0x3c,0x23,109}, /* 0x1a */
-	{ 0x5e,0x43,113}, /* 0x1b */
-	{ 0xbc,0x44,116}, /* 0x1c */
-	{ 0xe0,0x46,132}, /* 0x1d */
-	{ 0x54,0x42,135}, /* 0x1e */
-	{ 0xea,0x2a,139}, /* 0x1f */
-	{ 0x41,0x22,157}, /* 0x20 */
-	{ 0x70,0x24,162}, /* 0x21 */
-	{ 0x30,0x21,175}, /* 0x22 */
-	{ 0x4e,0x22,189}, /* 0x23 */
-	{ 0xde,0x26,194}, /* 0x24 */
-	{ 0x62,0x06,202}, /* 0x25 */
-	{ 0x3f,0x03,229}, /* 0x26 */
-	{ 0xb8,0x06,234}, /* 0x27 */
-	{ 0x34,0x02,253}, /* 0x28 */
-	{ 0x58,0x04,255}, /* 0x29 */
-	{ 0x24,0x01,265}, /* 0x2a */
-	{ 0x9b,0x02,267}, /* 0x2b */
-	{ 0x70,0x05,270}, /* 0x2c */
-	{ 0x25,0x01,272}, /* 0x2d */
-	{ 0x9c,0x02,277}, /* 0x2e */
-	{ 0x27,0x01,286}, /* 0x2f */
-	{ 0x3c,0x02,291}, /* 0x30 */
-	{ 0xef,0x0a,292}, /* 0x31 */
-	{ 0xf6,0x0a,310}, /* 0x32 */
-	{ 0x95,0x01,315}, /* 0x33 */
-	{ 0xf0,0x09,324}, /* 0x34 */
-	{ 0xfe,0x0a,331}, /* 0x35 */
-	{ 0xf3,0x09,332}, /* 0x36 */
-	{ 0xea,0x08,340}, /* 0x37 */
-	{ 0xe8,0x07,376}, /* 0x38 */
-	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
-	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x60,0x36, 30}, /* 0x41 Chrontel */
-	{ 0x40,0x4a, 28}, /* 0x42 Chrontel */
-	{ 0x9f,0x46, 44}, /* 0x43 Chrontel */
-	{ 0x97,0x2c, 26}, /* 0x44 */
-	{ 0x44,0xe4, 25}, /* 0x45 Chrontel */
-	{ 0x7e,0x32, 47}, /* 0x46 Chrontel */
-	{ 0x8a,0x24, 31}, /* 0x47 Chrontel */
-	{ 0x97,0x2c, 26}, /* 0x48 Chrontel */
-	{ 0xce,0x3c, 39}, /* 0x49 */
-	{ 0x52,0x4a, 36}, /* 0x4a Chrontel */
-	{ 0x34,0x61, 95}, /* 0x4b */
-	{ 0x78,0x27,108}, /* 0x4c - was 102 */
-	{ 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
-	{ 0x41,0x4e, 21}, /* 0x4e */
-	{ 0xa1,0x4a, 29}, /* 0x4f Chrontel */
-	{ 0x19,0x42, 42}, /* 0x50 */
-	{ 0x54,0x46, 58}, /* 0x51 Chrontel */
-	{ 0x25,0x42, 61}, /* 0x52 */
-	{ 0x44,0x44, 66}, /* 0x53 Chrontel */
-	{ 0x3a,0x62, 70}, /* 0x54 Chrontel */
-	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
-	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
-	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
-	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
-	{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
-	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
-	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
-	{ 0x45,0x25, 83}, /* 0x5c 1280x800  */
-	{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
-	{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
-	{ 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
-	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
-	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
-	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
-	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
-	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
-	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
-	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
-	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
-	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
-	{ 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
-	{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
-	{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
-	{ 0x45,0x25, 83}, /* 0x6c 1280x800 */
-	{ 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
-	{ 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
-	{ 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
-	{ 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
-	{ 0x2b,0xc2, 35}, /* 0x71 768x576@60 */
-	{ 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
-	{ 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
-	{ 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
-	{ 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
-	{ 0x75,0x13, 84}  /* 0x76 1280x854 60Hz (wide) */
-};
-
-static struct SiS_VBVCLKData SiS310_VBVCLKData[] =
-{
-	{ 0x1b,0xe1, 25}, /* 0x00 */
-	{ 0x4e,0xe4, 28}, /* 0x01 */
-	{ 0x57,0xe4, 31}, /* 0x02 */
-	{ 0xc3,0xc8, 36}, /* 0x03 */
-	{ 0x42,0x47, 40}, /* 0x04 */
-	{ 0xfe,0xcd, 43}, /* 0x05 */
-	{ 0x5d,0xc4, 44}, /* 0x06 */
-	{ 0x52,0x47, 49}, /* 0x07 */
-	{ 0x53,0x47, 50}, /* 0x08 */
-	{ 0x74,0x67, 52}, /* 0x09 */
-	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301: 35,62  */
-	{ 0x46,0x44, 67}, /* 0x0c */
-	{ 0xb1,0x46, 68}, /* 0x0d */
-	{ 0xd3,0x4a, 72}, /* 0x0e */
-	{ 0x29,0x61, 75}, /* 0x0f */
-	{ 0x6d,0x46, 75}, /* 0x10 */
-	{ 0x41,0x43, 78}, /* 0x11 */
-	{ 0x31,0x42, 79}, /* 0x12 */
-	{ 0xab,0x44, 83}, /* 0x13 */
-	{ 0x46,0x25, 84}, /* 0x14 */
-	{ 0x78,0x29, 86}, /* 0x15 */
-	{ 0x62,0x44, 94}, /* 0x16 */
-	{ 0x2b,0x22,104}, /* 0x17 */
-	{ 0x49,0x24,105}, /* 0x18 */
-	{ 0xf8,0x2f,108}, /* 0x19 */  /* 1400x1050 LCD */
-	{ 0x3c,0x23,109}, /* 0x1a */
-	{ 0x5e,0x43,113}, /* 0x1b */
-	{ 0xbc,0x44,116}, /* 0x1c */
-	{ 0xe0,0x46,132}, /* 0x1d */
-	{ 0xe2,0x46,135}, /* 0x1e */  /* 1280x1024-75, better clock for VGA2 */
-	{ 0xe5,0x46,139}, /* 0x1f */  /* 1024x768-120, better clock for VGA2 */
-	{ 0x15,0x01,157}, /* 0x20 */  /* 1280x1024-85, better clock for VGA2 */
-	{ 0x70,0x09,162}, /* 0x21 */  /* 1600x1200-60, better clock for VGA2 */
-	{ 0x30,0x21,175}, /* 0x22 */
-	{ 0x4e,0x22,189}, /* 0x23 */
-	{ 0xde,0x26,194}, /* 0x24 */
-	{ 0x70,0x07,202}, /* 0x25 */
-	{ 0x3f,0x03,229}, /* 0x26 */
-	{ 0xb8,0x06,234}, /* 0x27 */
-	{ 0x34,0x02,253}, /* 0x28 */
-	{ 0x58,0x04,255}, /* 0x29 */
-	{ 0x24,0x01,265}, /* 0x2a */
-	{ 0x9b,0x02,267}, /* 0x2b */
-	{ 0x70,0x05,270}, /* 0x2c */
-	{ 0x25,0x01,272}, /* 0x2d */
-	{ 0x9c,0x02,277}, /* 0x2e */
-	{ 0x27,0x01,286}, /* 0x2f */
-	{ 0x3c,0x02,291}, /* 0x30 */
-	{ 0xef,0x0a,292}, /* 0x31 */
-	{ 0xf6,0x0a,310}, /* 0x32 */
-	{ 0x95,0x01,315}, /* 0x33 */
-	{ 0xf0,0x09,324}, /* 0x34 */
-	{ 0xfe,0x0a,331}, /* 0x35 */
-	{ 0xf3,0x09,332}, /* 0x36 */
-	{ 0xea,0x08,340}, /* 0x37 */
-	{ 0xe8,0x07,376}, /* 0x38 */
-	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a 301 TV - start */
-	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
-	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x2e,0x48, 25}, /* 0x41 Replacement for LCD on 315 for index 0 */
-	{ 0x24,0x46, 25}, /* 0x42 Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
-	{ 0x26,0x64, 28}, /* 0x43 Replacement for LCD on 315 for index 1 */
-	{ 0x37,0x64, 40}, /* 0x44 Replacement for LCD on 315 for index 4 */
-	{ 0xa1,0x42,108}, /* 0x45 1280x960 LCD */
-	{ 0x37,0x61,100}, /* 0x46 1280x960 LCD */
-	{ 0x78,0x27,108}, /* 0x47 */
-	{ 0x97,0x2c, 26}, /* 0x48 UNUSED */
-	{ 0xce,0x3c, 39}, /* 0x49 UNUSED */
-	{ 0x52,0x4a, 36}, /* 0x4a UNUSED */
-	{ 0x34,0x61, 95}, /* 0x4b UNUSED */
-	{ 0x78,0x27,108}, /* 0x4c UNUSED */
-	{ 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
-	{ 0x41,0x4e, 21}, /* 0x4e */
-	{ 0xa1,0x4a, 29}, /* 0x4f UNUSED */
-	{ 0x19,0x42, 42}, /* 0x50 UNUSED */
-	{ 0x54,0x46, 58}, /* 0x51 UNUSED */
-	{ 0x25,0x42, 61}, /* 0x52 UNUSED */
-	{ 0x44,0x44, 66}, /* 0x53 UNUSED */
-	{ 0x3a,0x62, 70}, /* 0x54 UNUSED */
-	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
-	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP, UNUSED */
-	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60  */
-	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
-	{ 0x52,0x07,149}, /* 0x59 1280x960-85  */
-	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
-	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
-	{ 0xce,0x1e, 73}, /* 0x5c 1280x800_2 LCD (SiS LVDS) - (CRT1: 45 25 83) */
-	{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
-	{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
-	{ 0x52,0x27, 75}, /* 0x5f 1280x720 (TMDS + HDTV) (correct) */
-	{ 0xc8,0x48, 77}, /* 0x60 1280x768_2 (SiS LVDS) */
-	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 (SiS LVDS) - temp */
-	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
-	{ 0x9c,0x62, 69}, /* 0x63 1280x720 (SiS LVDS) */
-	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
-	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
-	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
-	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
-	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
-	{ 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced (UNUSED) */
-	{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
-	{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
-	{ 0x9c,0x62, 69}, /* 0x6c 1280x800 (SiS TMDS) (special) */
-	{ 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
-	{ 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
-	{ 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
-	{ 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
-	{ 0x2b,0xc2, 35}, /* 0x71 768@576@60 */
-	{ 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
-	{ 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
-	{ 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
-	{ 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
-	{ 0x75,0x13, 84}  /* 0x76 1280x854 60Hz (SiS LVDS) LCD */
-};
-
-static const unsigned char SiS310_SR15[4 * 8] =
-{
-	0x00,0x04,0x60,0x60,
-	0x0f,0x0f,0x0f,0x0f,
-	0xba,0xba,0xba,0xba,
-	0xa9,0xa9,0xac,0xac,
-	0xa0,0xa0,0xa0,0xa8,
-	0x00,0x00,0x02,0x02,
-	0x30,0x30,0x40,0x40,
-	0x00,0xa5,0xfb,0xf6
-};
-
-static const struct SiS_PanelDelayTbl SiS310_PanelDelayTbl[] =
-{
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}},
-	{{0x10,0x40}}
-};
-
-static const struct SiS_PanelDelayTbl SiS310_PanelDelayTblLVDS[] =
-{
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}},
-	{{0x28,0xc8}}
-};
-
-/**************************************************************/
-/* SIS VIDEO BRIDGE ----------------------------------------- */
-/**************************************************************/
-
-static const struct SiS_LCDData SiS310_St2LCD1024x768Data[] =
-{
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const struct SiS_LCDData SiS310_ExtLCD1024x768Data[] =
-{
-	{   42,  25,1536, 419,1344, 806},
-	{   48,  25,1536, 369,1344, 806},
-	{   42,  25,1536, 419,1344, 806},
-	{   48,  25,1536, 369,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const struct SiS_LCDData SiS310_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const struct SiS_LCDData SiS310_ExtLCD1280x1024Data[] =
-{
-	{  211,  60,1024, 501,1688,1066},
-	{  211,  60,1024, 508,1688,1066},
-	{  211,  60,1024, 501,1688,1066},
-	{  211,  60,1024, 508,1688,1066},
-	{  211,  60,1024, 500,1688,1066},
-	{  211,  75,1024, 625,1688,1066},
-	{  211, 120,1280, 798,1688,1066},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const struct SiS_Part2PortTbl SiS310_CRT2Part2_1024x768_1[] =
-{
-	{{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
-	{{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
-};
-
-/**************************************************************/
-/* LVDS, CHRONTEL ------------------------------------------- */
-/**************************************************************/
-
-static const struct SiS_LVDSData SiS310_CHTVUPALData[] =
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 625, 840, 625},
-	{ 960, 750, 960, 750},
-	{1400,1000,1400,1000}
-};
-
-static const struct SiS_LVDSData SiS310_CHTVOPALData[] =
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 625, 840, 625},
-	{ 944, 625, 944, 625},
-	{1400, 875,1400, 875}
-};
-
-static const struct SiS_LVDSData SiS310_CHTVUPALMData[] =
-{
-	{ 840, 600, 840, 600},
-	{ 840, 600, 840, 600},
-	{ 840, 600, 840, 600},
-	{ 840, 600, 840, 600},
-	{ 784, 600, 784, 600},
-	{1064, 750,1064, 750},
-	{1160, 945,1160, 945}
-};
-
-static const struct SiS_LVDSData SiS310_CHTVOPALMData[] =
-{
-	{ 840, 525, 840, 525},
-	{ 840, 525, 840, 525},
-	{ 840, 525, 840, 525},
-	{ 840, 525, 840, 525},
-	{ 784, 525, 784, 525},
-	{1040, 700,1040, 700},
-	{1160, 840,1160, 840}
-};
-
-static const struct SiS_LVDSData SiS310_CHTVUPALNData[] =
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 625, 840, 625},
-	{ 960, 750, 960, 750},
-	{1400,1000,1400,1000}
-};
-
-static const struct SiS_LVDSData SiS310_CHTVOPALNData[] =
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 625, 840, 625},
-	{ 944, 625, 944, 625},
-	{1400, 875,1400, 875}
-};
-
-static const struct SiS_LVDSData SiS310_CHTVSOPALData[] =   /* (super overscan - no effect on 7019) */
-{
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{1008, 625,1008, 625},
-	{ 840, 625, 840, 625},
-	{ 944, 625, 944, 625},
-        {1400, 875,1400, 875}
-};
-
-/* CRT1 CRTC for Chrontel TV slave modes */
-
-static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UNTSC[] =
-{
- {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-   0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
-   0x00 }},
- {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-   0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
-   0x00 }},
- {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-   0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
-   0x00 }},
- {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
-   0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,
-   0x00 }},
- {{0x5d,0x4f,0x81,0x56,0x99,0x56,0xba,
-   0x0a,0x84,0xdf,0x57,0x00,0x00,0x01,
-   0x00 }},
- {{0x80,0x63,0x84,0x6d,0x0f,0xec,0xf0,
-   0x7a,0x8f,0x57,0xed,0x20,0x00,0x06,
-   0x01 }},
- {{0x8c,0x7f,0x90,0x86,0x09,0xaf,0xf5,
-   0x36,0x88,0xff,0xb0,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1ONTSC[] =
-{
- {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
-   0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
-   0x00 }},
- {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
-   0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
-   0x00 }},
- {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
-   0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
-   0x00 }},
- {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
-   0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,
-   0x00 }},
- {{0x5d,0x4f,0x81,0x58,0x9d,0x0b,0x3e,
-   0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,
-   0x00 }},
- {{0x7d,0x63,0x81,0x68,0x0e,0xba,0xf0,
-   0x78,0x8a,0x57,0xbb,0x20,0x00,0x06,
-   0x01 }},
- {{0x8c,0x7f,0x90,0x82,0x06,0x46,0xf5,
-   0x15,0x88,0xff,0x47,0x70,0x00,0x02,
-   0x01 }}
-};
-
-static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UPAL[] =
-{
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
-   0x00 }},
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-   0x00 }},
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
-   0x00 }},
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-   0x00 }},
- {{0x64,0x4f,0x88,0x5a,0x9f,0x6f,0xba,
-   0x15,0x83,0xdf,0x70,0x00,0x00,0x01,
-   0x00 }},
- {{0x73,0x63,0x97,0x69,0x8b,0xec,0xf0,
-   0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
-   0x01 }},
- {{0xaa,0x7f,0x8e,0x8e,0x96,0xe6,0xf5,
-   0x50,0x88,0xff,0xe7,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1OPAL[] =
-{
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
-   0x00 }},
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-   0x00 }},
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
-   0x00 }},
- {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
-   0xde,0x81,0x5d,0x70,0x00,0x00,0x05,
-   0x00 }},
- {{0x64,0x4f,0x88,0x58,0x9d,0x6f,0xba,
-   0x15,0x83,0xdf,0x70,0x00,0x00,0x01,
-   0x00 }},
- {{0x71,0x63,0x95,0x69,0x8c,0x6f,0xf0,
-   0x5a,0x8b,0x57,0x70,0x20,0x00,0x05,
-   0x01 }},
- {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5,
-   0x28,0x88,0xff,0x6a,0x10,0x00,0x02,
-   0x01 }}
-};
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_UNTSC[] =
-{
- {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x6a,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x7e,0x80,0x98,0x00}},
- {{0xcf,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x88,0x30,0x7f,0x00}},
- {{0xee,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xd3,0xf2,0x36,0x00}}
-}; /* WRONG: 0x02: should be 0xfx, because if CIVEnable is clear, this should be set;
-             0x07: Blacklevel: NTSC/PAL-M: Should be 131 (0x83), and not 0x50/0x5a
-	                       PAL/PAL-N:  110 (0x6e)
-			       NTSC-J:     102 (0x66)
-	     0x0c-0x0f: CIV is not default as in datasheet
-      MISSING: 0x21: Should set D1 to ZERO (for NTSC, PAL-M) or ONE (PAL, NTSC-J)
-      Most of this is wrong in all NTSC and PAL register arrays. But I won't correct
-      it as long as it works. For NTSC-J, the blacklevel is corrected in init301.c;
-      for PAL-M and PAL-N all above is corrected.
-    */
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_ONTSC[] =
-{
- {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x69,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x43,0x04,0x00}},
- {{0xce,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1c,0x00,0x82,0x97,0x00}},
- {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
-};
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_UPAL[] =
-{
- {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}},
- {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x1f,0x84,0x3d,0x28,0x00}},
- {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
-};
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_OPAL[] =
-{
- {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}},
- {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00}},
- {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
-};
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALM[] =
-{
- {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x72,0x77,0xfb,0x6e,0x84,0x2e,0x02,0x83,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}},
- {{0xd7,0x77,0xf7,0xc8,0x84,0x3b,0x02,0x83,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}},
- {{0xf6,0x77,0xfb,0x66,0x87,0x32,0x01,0x83,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}}
-#if 0 /* Correct blacklevel and CFRB */
- {{0x72,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}},
- {{0xd7,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}},
- {{0xf6,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}}
-#endif
-};
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALM[] =
-{
- {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
- {{0x71,0x77,0xfb,0x6e,0x84,0x1e,0x00,0x83,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}},
- {{0xd6,0x77,0xf7,0xb6,0x83,0x2c,0x02,0x83,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}},
- {{0xf5,0x77,0xfb,0x66,0x8c,0x21,0x02,0x83,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}}
-#if 0 /* Correct blacklevel and CFRB */
- {{0x71,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}},
- {{0xd6,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}},
- {{0xf5,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}}
-#endif
-};
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALN[] =
-{
- {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}
-#if 0 /* Correct blacklevel, CIV and CFRB */
- {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}},
- {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x19,0x78,0xef,0x35,0x00}},
- {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x1a,0x33,0x3f,0x2f,0x00}}
-#endif
-};
-
-static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALN[] =
-{
- {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
- {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}
-#if 0 /* Correct blacklevel, CIV and CFRB */
- {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}},
- {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x1f,0x15,0xc0,0x1e,0x00}},
- {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x1d,0xf1,0x6c,0xcb,0x00}}
-#endif
-};
-
-static const unsigned char SiS310_CHTVVCLKUNTSC[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
-static const unsigned char SiS310_CHTVVCLKONTSC[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
-
-static const unsigned char SiS310_CHTVVCLKUPAL[]  = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
-static const unsigned char SiS310_CHTVVCLKOPAL[]  = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
-
-static const unsigned char SiS310_CHTVVCLKUPALM[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
-static const unsigned char SiS310_CHTVVCLKOPALM[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
-
-static const unsigned char SiS310_CHTVVCLKUPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
-static const unsigned char SiS310_CHTVVCLKOPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
-
-
diff --git a/drivers/video/sis/Makefile b/drivers/video/sis/Makefile
deleted file mode 100644
index f7c0046e5b1d..000000000000
--- a/drivers/video/sis/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the SiS framebuffer device driver
-#
-
-obj-$(CONFIG_FB_SIS) += sisfb.o
-
-sisfb-objs := sis_main.o sis_accel.o init.o init301.o initextlfb.o
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
deleted file mode 100644
index bd40f5ecd901..000000000000
--- a/drivers/video/sis/init.c
+++ /dev/null
@@ -1,3655 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * Mode initializing code (CRT1 section) for
- * for SiS 300/305/540/630/730,
- *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
- *     XGI Volari V3XT/V5/V8, Z7
- * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
- * Used by permission.
- */
-
-#include "init.h"
-
-#ifdef CONFIG_FB_SIS_300
-#include "300vtbl.h"
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-#include "310vtbl.h"
-#endif
-
-#if defined(ALLOC_PRAGMA)
-#pragma alloc_text(PAGE,SiSSetMode)
-#endif
-
-/*********************************************/
-/*         POINTER INITIALIZATION            */
-/*********************************************/
-
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-static void
-InitCommonPointer(struct SiS_Private *SiS_Pr)
-{
-   SiS_Pr->SiS_SModeIDTable  = SiS_SModeIDTable;
-   SiS_Pr->SiS_StResInfo     = SiS_StResInfo;
-   SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;
-   SiS_Pr->SiS_StandTable    = SiS_StandTable;
-
-   SiS_Pr->SiS_NTSCTiming     = SiS_NTSCTiming;
-   SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
-   SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
-   SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;
-
-   SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
-   SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
-   SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
-#if 0
-   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
-   SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
-#endif
-
-   SiS_Pr->SiS_StPALData   = SiS_StPALData;
-   SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;
-   SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;
-   SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
-   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData;
-   SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
-   SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
-   SiS_Pr->SiS_St525iData  = SiS_StNTSCData;
-   SiS_Pr->SiS_St525pData  = SiS_St525pData;
-   SiS_Pr->SiS_St750pData  = SiS_St750pData;
-   SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData;
-   SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData;
-   SiS_Pr->SiS_Ext750pData = SiS_Ext750pData;
-
-   SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
-   SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
-
-   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
-   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
-   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
-   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
-   SiS_Pr->SiS_LCD1280x800_2Data    = SiS_LCD1280x800_2Data;
-   SiS_Pr->SiS_LCD1280x854Data      = SiS_LCD1280x854Data;
-   SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
-   SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
-   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
-   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
-   SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
-   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
-   SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
-
-   SiS_Pr->SiS_LVDS320x240Data_1   = SiS_LVDS320x240Data_1;
-   SiS_Pr->SiS_LVDS320x240Data_2   = SiS_LVDS320x240Data_2;
-   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
-   SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;
-   SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;
-   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;
-
-   SiS_Pr->SiS_LVDSCRT1320x240_1     = SiS_LVDSCRT1320x240_1;
-   SiS_Pr->SiS_LVDSCRT1320x240_2     = SiS_LVDSCRT1320x240_2;
-   SiS_Pr->SiS_LVDSCRT1320x240_2_H   = SiS_LVDSCRT1320x240_2_H;
-   SiS_Pr->SiS_LVDSCRT1320x240_3     = SiS_LVDSCRT1320x240_3;
-   SiS_Pr->SiS_LVDSCRT1320x240_3_H   = SiS_LVDSCRT1320x240_3_H;
-   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
-   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
-#if 0
-   SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
-#endif
-
-   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
-   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
-
-   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
-   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_300
-static void
-InitTo300Pointer(struct SiS_Private *SiS_Pr)
-{
-   InitCommonPointer(SiS_Pr);
-
-   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
-   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
-   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
-   if(SiS_Pr->ChipType == SIS_300) {
-      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
-   } else {
-      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
-   }
-   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
-   SiS_Pr->SiS_VBVCLKData    = (struct SiS_VBVCLKData *)SiS300_VCLKData;
-
-   SiS_Pr->SiS_SR15  = SiS300_SR15;
-
-   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
-
-   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
-
-   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
-
-   SiS_Pr->SiS_LVDS848x480Data_1   = SiS300_LVDS848x480Data_1;
-   SiS_Pr->SiS_LVDS848x480Data_2   = SiS300_LVDS848x480Data_2;
-   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
-   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
-   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
-
-   SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
-   SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
-   SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
-   SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
-
-   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
-   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
-   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
-   SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
-   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
-   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS300_CHTVVCLKOPAL;
-   SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static void
-InitTo310Pointer(struct SiS_Private *SiS_Pr)
-{
-   InitCommonPointer(SiS_Pr);
-
-   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
-   SiS_Pr->SiS_RefIndex      = SiS310_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
-   if(SiS_Pr->ChipType >= SIS_340) {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 + XGI */
-   } else if(SiS_Pr->ChipType >= SIS_761) {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761;  /* 761 - preliminary */
-   } else if(SiS_Pr->ChipType >= SIS_760) {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
-   } else if(SiS_Pr->ChipType >= SIS_661) {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
-   } else if(SiS_Pr->ChipType == SIS_330) {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
-   } else if(SiS_Pr->ChipType > SIS_315PRO) {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
-   } else {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
-   }
-   if(SiS_Pr->ChipType >= SIS_340) {
-      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
-   } else {
-      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
-   }
-   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
-   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
-
-   SiS_Pr->SiS_SR15  = SiS310_SR15;
-
-   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
-
-   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
-
-   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
-   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
-   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
-   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
-   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
-
-   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS310_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS310_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
-
-   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
-   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
-   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
-   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
-   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
-
-   SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
-   SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
-   SiS_Pr->SiS_CHTVVCLKUPAL  = SiS310_CHTVVCLKUPAL;
-   SiS_Pr->SiS_CHTVVCLKOPAL  = SiS310_CHTVVCLKOPAL;
-   SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
-   SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
-   SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
-   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
-   SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
-}
-#endif
-
-bool
-SiSInitPtr(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-      InitTo300Pointer(SiS_Pr);
-#else
-      return false;
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      InitTo310Pointer(SiS_Pr);
-#else
-      return false;
-#endif
-   }
-   return true;
-}
-
-/*********************************************/
-/*            HELPER: Get ModeID             */
-/*********************************************/
-
-static
-unsigned short
-SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-		int Depth, bool FSTN, int LCDwidth, int LCDheight)
-{
-   unsigned short ModeIndex = 0;
-
-   switch(HDisplay)
-   {
-	case 320:
-		if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
-		else if(VDisplay == 240) {
-			if((VBFlags & CRT2_LCD) && (FSTN))
-				ModeIndex = ModeIndex_320x240_FSTN[Depth];
-			else
-				ModeIndex = ModeIndex_320x240[Depth];
-		}
-		break;
-	case 400:
-		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
-			if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
-		}
-		break;
-	case 512:
-		if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
-			if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
-		}
-		break;
-	case 640:
-		if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
-		else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
-		break;
-	case 720:
-		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
-		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
-		break;
-	case 768:
-		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-		break;
-	case 800:
-		if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
-		else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
-		break;
-	case 848:
-		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-		break;
-	case 856:
-		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
-		break;
-	case 960:
-		if(VGAEngine == SIS_315_VGA) {
-			if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
-			else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
-		}
-		break;
-	case 1024:
-		if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];
-		else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-		else if(VGAEngine == SIS_300_VGA) {
-			if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
-		}
-		break;
-	case 1152:
-		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
-		if(VGAEngine == SIS_300_VGA) {
-			if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
-		}
-		break;
-	case 1280:
-		switch(VDisplay) {
-			case 720:
-				ModeIndex = ModeIndex_1280x720[Depth];
-				break;
-			case 768:
-				if(VGAEngine == SIS_300_VGA) {
-					ModeIndex = ModeIndex_300_1280x768[Depth];
-				} else {
-					ModeIndex = ModeIndex_310_1280x768[Depth];
-				}
-				break;
-			case 800:
-				if(VGAEngine == SIS_315_VGA) {
-					ModeIndex = ModeIndex_1280x800[Depth];
-				}
-				break;
-			case 854:
-				if(VGAEngine == SIS_315_VGA) {
-					ModeIndex = ModeIndex_1280x854[Depth];
-				}
-				break;
-			case 960:
-				ModeIndex = ModeIndex_1280x960[Depth];
-				break;
-			case 1024:
-				ModeIndex = ModeIndex_1280x1024[Depth];
-				break;
-		}
-		break;
-	case 1360:
-		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
-		if(VGAEngine == SIS_300_VGA) {
-			if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
-		}
-		break;
-	case 1400:
-		if(VGAEngine == SIS_315_VGA) {
-			if(VDisplay == 1050) {
-				ModeIndex = ModeIndex_1400x1050[Depth];
-			}
-		}
-		break;
-	case 1600:
-		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
-		break;
-	case 1680:
-		if(VGAEngine == SIS_315_VGA) {
-			if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
-		}
-		break;
-	case 1920:
-		if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
-		else if(VGAEngine == SIS_315_VGA) {
-			if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
-		}
-		break;
-	case 2048:
-		if(VDisplay == 1536) {
-			if(VGAEngine == SIS_300_VGA) {
-				ModeIndex = ModeIndex_300_2048x1536[Depth];
-			} else {
-				ModeIndex = ModeIndex_310_2048x1536[Depth];
-			}
-		}
-		break;
-   }
-
-   return ModeIndex;
-}
-
-unsigned short
-SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-		int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
-		unsigned int VBFlags2)
-{
-   unsigned short ModeIndex = 0;
-
-   if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
-
-      switch(HDisplay)
-      {
-	case 320:
-	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
-		if(VDisplay == 200) {
-		   if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
-		} else if(VDisplay == 240) {
-		   if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
-		   else if(VGAEngine == SIS_315_VGA) {
-		      ModeIndex = ModeIndex_320x240_FSTN[Depth];
-		   }
-		}
-	     }
-	     break;
-	case 400:
-	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
-		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
-		   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
-		}
-	     }
-	     break;
-	case 512:
-	     if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
-		if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
-		   if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
-		      if(VDisplay == 384) {
-		         ModeIndex = ModeIndex_512x384[Depth];
-		      }
-		   }
-		}
-	     }
-	     break;
-	case 640:
-	     if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
-	     else if(VDisplay == 400) {
-		if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
-		   ModeIndex = ModeIndex_640x400[Depth];
-	     }
-	     break;
-	case 800:
-	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
-	     break;
-	case 848:
-	     if(CustomT == CUT_PANEL848) {
-	        if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-	     }
-	     break;
-	case 856:
-	     if(CustomT == CUT_PANEL856) {
-	        if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
-	     }
-	     break;
-	case 1024:
-	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-	     else if(VGAEngine == SIS_300_VGA) {
-		if((VDisplay == 600) && (LCDheight == 600)) {
-		   ModeIndex = ModeIndex_1024x600[Depth];
-		}
-	     }
-	     break;
-	case 1152:
-	     if(VGAEngine == SIS_300_VGA) {
-		if((VDisplay == 768) && (LCDheight == 768)) {
-		   ModeIndex = ModeIndex_1152x768[Depth];
-		}
-	     }
-	     break;
-        case 1280:
-	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
-	     else if(VGAEngine == SIS_315_VGA) {
-		if((VDisplay == 768) && (LCDheight == 768)) {
-		   ModeIndex = ModeIndex_310_1280x768[Depth];
-		}
-	     }
-	     break;
-	case 1360:
-	     if(VGAEngine == SIS_300_VGA) {
-		if(CustomT == CUT_BARCO1366) {
-		   if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
-		}
-	     }
-	     if(CustomT == CUT_PANEL848) {
-		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
-	     }
-	     break;
-	case 1400:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
-	     }
-	     break;
-	case 1600:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
-	     }
-	     break;
-      }
-
-   } else if(VBFlags2 & VB2_SISBRIDGE) {
-
-      switch(HDisplay)
-      {
-	case 320:
-	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
-	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
-	     break;
-	case 400:
-	     if(LCDwidth >= 800 && LCDheight >= 600) {
-		if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
-	     }
-	     break;
-	case 512:
-	     if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
-		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
-	     }
-	     break;
-	case 640:
-	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
-	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
-	     break;
-	case 720:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
-		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
-	     }
-	     break;
-	case 768:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-	     }
-	     break;
-	case 800:
-	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
-	     }
-	     break;
-	case 848:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-	     }
-	     break;
-	case 856:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
-	     }
-	     break;
-	case 960:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
-		else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
-	     }
-	     break;
-	case 1024:
-	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
-	     }
-	     break;
-	case 1152:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
-	     }
-	     break;
-	case 1280:
-	     switch(VDisplay) {
-	     case 720:
-		ModeIndex = ModeIndex_1280x720[Depth];
-		break;
-	     case 768:
-		if(VGAEngine == SIS_300_VGA) {
-		   ModeIndex = ModeIndex_300_1280x768[Depth];
-		} else {
-		   ModeIndex = ModeIndex_310_1280x768[Depth];
-		}
-		break;
-	     case 800:
-		if(VGAEngine == SIS_315_VGA) {
-		   ModeIndex = ModeIndex_1280x800[Depth];
-		}
-		break;
-	     case 854:
-		if(VGAEngine == SIS_315_VGA) {
-		   ModeIndex = ModeIndex_1280x854[Depth];
-		}
-		break;
-	     case 960:
-		ModeIndex = ModeIndex_1280x960[Depth];
-		break;
-	     case 1024:
-		ModeIndex = ModeIndex_1280x1024[Depth];
-		break;
-	     }
-	     break;
-	case 1360:
-	     if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */
-		if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
-	     }
-	     break;
-	case 1400:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
-		   if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
-		}
-	     }
-	     break;
-	case 1600:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
-		   if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
-		}
-	     }
-	     break;
-#ifndef VB_FORBID_CRT2LCD_OVER_1600
-	case 1680:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
-		   if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
-		}
-	     }
-	     break;
-	case 1920:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
-		   if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
-		}
-	     }
-	     break;
-	case 2048:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
-		   if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
-		}
-	     }
-	     break;
-#endif
-      }
-   }
-
-   return ModeIndex;
-}
-
-unsigned short
-SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
-			unsigned int VBFlags2)
-{
-   unsigned short ModeIndex = 0;
-
-   if(VBFlags2 & VB2_CHRONTEL) {
-
-      switch(HDisplay)
-      {
-	case 512:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
-	     }
-	     break;
-	case 640:
-	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
-	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
-	     break;
-	case 800:
-	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
-	     break;
-	case 1024:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-	     }
-	     break;
-      }
-
-   } else if(VBFlags2 & VB2_SISTVBRIDGE) {
-
-      switch(HDisplay)
-      {
-	case 320:
-	     if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
-	     else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
-	     break;
-	case 400:
-	     if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
-	     break;
-	case 512:
-	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
-		 (VBFlags & TV_HIVISION) 					      ||
-		 ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
-		if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
-	     }
-	     break;
-	case 640:
-	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
-	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
-	     break;
-	case 720:
-	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
-		if(VDisplay == 480) {
-		   ModeIndex = ModeIndex_720x480[Depth];
-		} else if(VDisplay == 576) {
-		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
-		       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
-		      ModeIndex = ModeIndex_720x576[Depth];
-		}
-	     }
-             break;
-	case 768:
-	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
-		if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
-		    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
-		   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-		}
-             }
-	     break;
-	case 800:
-	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
-	     else if(VDisplay == 480) {
-		if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
-		   ModeIndex = ModeIndex_800x480[Depth];
-		}
-	     }
-	     break;
-	case 960:
-	     if(VGAEngine == SIS_315_VGA) {
-		if(VDisplay == 600) {
-		   if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
-		      ModeIndex = ModeIndex_960x600[Depth];
-		   }
-		}
-	     }
-	     break;
-	case 1024:
-	     if(VDisplay == 768) {
-		if(VBFlags2 & VB2_30xBLV) {
-		   ModeIndex = ModeIndex_1024x768[Depth];
-		}
-	     } else if(VDisplay == 576) {
-		if( (VBFlags & TV_HIVISION) ||
-		    ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
-		    ((VBFlags2 & VB2_30xBLV) &&
-		     ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
-		   ModeIndex = ModeIndex_1024x576[Depth];
-		}
-	     }
-	     break;
-	case 1280:
-	     if(VDisplay == 720) {
-		if((VBFlags & TV_HIVISION) ||
-		   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
-		   ModeIndex = ModeIndex_1280x720[Depth];
-		}
-	     } else if(VDisplay == 1024) {
-		if((VBFlags & TV_HIVISION) ||
-		   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
-		   ModeIndex = ModeIndex_1280x1024[Depth];
-		}
-	     }
-	     break;
-      }
-   }
-   return ModeIndex;
-}
-
-unsigned short
-SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
-			unsigned int VBFlags2)
-{
-   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
-
-   if(HDisplay >= 1920) return 0;
-
-   switch(HDisplay)
-   {
-	case 1600:
-		if(VDisplay == 1200) {
-			if(VGAEngine != SIS_315_VGA) return 0;
-			if(!(VBFlags2 & VB2_30xB)) return 0;
-		}
-		break;
-	case 1680:
-		if(VDisplay == 1050) {
-			if(VGAEngine != SIS_315_VGA) return 0;
-			if(!(VBFlags2 & VB2_30xB)) return 0;
-		}
-		break;
-   }
-
-   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
-}
-
-
-/*********************************************/
-/*          HELPER: SetReg, GetReg           */
-/*********************************************/
-
-void
-SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
-{
-	outb(index, port);
-	outb(data, port + 1);
-}
-
-void
-SiS_SetRegByte(SISIOADDRESS port, u8 data)
-{
-	outb(data, port);
-}
-
-void
-SiS_SetRegShort(SISIOADDRESS port, u16 data)
-{
-	outw(data, port);
-}
-
-void
-SiS_SetRegLong(SISIOADDRESS port, u32 data)
-{
-	outl(data, port);
-}
-
-u8
-SiS_GetReg(SISIOADDRESS port, u8 index)
-{
-	outb(index, port);
-	return inb(port + 1);
-}
-
-u8
-SiS_GetRegByte(SISIOADDRESS port)
-{
-	return inb(port);
-}
-
-u16
-SiS_GetRegShort(SISIOADDRESS port)
-{
-	return inw(port);
-}
-
-u32
-SiS_GetRegLong(SISIOADDRESS port)
-{
-	return inl(port);
-}
-
-void
-SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
-{
-   u8 temp;
-
-   temp = SiS_GetReg(Port, Index);
-   temp = (temp & (DataAND)) | DataOR;
-   SiS_SetReg(Port, Index, temp);
-}
-
-void
-SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
-{
-   u8 temp;
-
-   temp = SiS_GetReg(Port, Index);
-   temp &= DataAND;
-   SiS_SetReg(Port, Index, temp);
-}
-
-void
-SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
-{
-   u8 temp;
-
-   temp = SiS_GetReg(Port, Index);
-   temp |= DataOR;
-   SiS_SetReg(Port, Index, temp);
-}
-
-/*********************************************/
-/*      HELPER: DisplayOn, DisplayOff        */
-/*********************************************/
-
-void
-SiS_DisplayOn(struct SiS_Private *SiS_Pr)
-{
-   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
-}
-
-void
-SiS_DisplayOff(struct SiS_Private *SiS_Pr)
-{
-   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
-}
-
-
-/*********************************************/
-/*        HELPER: Init Port Addresses        */
-/*********************************************/
-
-void
-SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
-{
-   SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
-   SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
-   SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
-   SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
-   SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
-   SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
-   SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
-   SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
-   SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
-   SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
-   SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
-   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
-   SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
-   SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
-   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
-   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
-   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
-   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
-   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
-   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;
-   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;
-   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;
-}
-
-/*********************************************/
-/*             HELPER: GetSysFlags           */
-/*********************************************/
-
-static void
-SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
-{
-   unsigned char cr5f, temp1, temp2;
-
-   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
-   /* (SR11 is used for DDC and in enable/disablebridge) */
-   SiS_Pr->SiS_SensibleSR11 = false;
-   SiS_Pr->SiS_MyCR63 = 0x63;
-   if(SiS_Pr->ChipType >= SIS_330) {
-      SiS_Pr->SiS_MyCR63 = 0x53;
-      if(SiS_Pr->ChipType >= SIS_661) {
-         SiS_Pr->SiS_SensibleSR11 = true;
-      }
-   }
-
-   /* You should use the macros, not these flags directly */
-
-   SiS_Pr->SiS_SysFlags = 0;
-   if(SiS_Pr->ChipType == SIS_650) {
-      cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
-      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
-      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
-      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
-      temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
-      if((!temp1) || (temp2)) {
-	 switch(cr5f) {
-	    case 0x80:
-	    case 0x90:
-	    case 0xc0:
-	       SiS_Pr->SiS_SysFlags |= SF_IsM650;
-	       break;
-	    case 0xa0:
-	    case 0xb0:
-	    case 0xe0:
-	       SiS_Pr->SiS_SysFlags |= SF_Is651;
-	       break;
-	 }
-      } else {
-	 switch(cr5f) {
-	    case 0x90:
-	       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
-	       switch(temp1) {
-		  case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
-		  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
-		  default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
-	       }
-	       break;
-	    case 0xb0:
-	       SiS_Pr->SiS_SysFlags |= SF_Is652;
-	       break;
-	    default:
-	       SiS_Pr->SiS_SysFlags |= SF_IsM650;
-	       break;
-	 }
-      }
-   }
-
-   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
-         SiS_Pr->SiS_SysFlags |= SF_760LFB;
-      }
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
-         SiS_Pr->SiS_SysFlags |= SF_760UMA;
-      }
-   }
-}
-
-/*********************************************/
-/*         HELPER: Init PCI & Engines        */
-/*********************************************/
-
-static void
-SiSInitPCIetc(struct SiS_Private *SiS_Pr)
-{
-   switch(SiS_Pr->ChipType) {
-#ifdef CONFIG_FB_SIS_300
-   case SIS_300:
-   case SIS_540:
-   case SIS_630:
-   case SIS_730:
-      /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
-       *     - RELOCATED VGA IO ENABLED (0x20)
-       *     - MMIO ENABLED (0x01)
-       * Leave other bits untouched.
-       */
-      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
-      /*  - Enable 2D (0x40)
-       *  - Enable 3D (0x02)
-       *  - Enable 3D Vertex command fetch (0x10) ?
-       *  - Enable 3D command parser (0x08) ?
-       */
-      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
-      break;
-#endif
-#ifdef CONFIG_FB_SIS_315
-   case SIS_315H:
-   case SIS_315:
-   case SIS_315PRO:
-   case SIS_650:
-   case SIS_740:
-   case SIS_330:
-   case SIS_661:
-   case SIS_741:
-   case SIS_660:
-   case SIS_760:
-   case SIS_761:
-   case SIS_340:
-   case XGI_40:
-      /* See above */
-      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
-      /*  - Enable 3D G/L transformation engine (0x80)
-       *  - Enable 2D (0x40)
-       *  - Enable 3D vertex command fetch (0x10)
-       *  - Enable 3D command parser (0x08)
-       *  - Enable 3D (0x02)
-       */
-      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
-      break;
-   case XGI_20:
-   case SIS_550:
-      /* See above */
-      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
-      /* No 3D engine ! */
-      /*  - Enable 2D (0x40)
-       *  - disable 3D
-       */
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
-      break;
-#endif
-   default:
-      break;
-   }
-}
-
-/*********************************************/
-/*             HELPER: SetLVDSetc            */
-/*********************************************/
-
-static
-void
-SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
-{
-   unsigned short temp;
-
-   SiS_Pr->SiS_IF_DEF_LVDS = 0;
-   SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
-   SiS_Pr->SiS_IF_DEF_CH70xx = 0;
-   SiS_Pr->SiS_IF_DEF_CONEX = 0;
-
-   SiS_Pr->SiS_ChrontelInit = 0;
-
-   if(SiS_Pr->ChipType == XGI_20) return;
-
-   /* Check for SiS30x first */
-   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-   if((temp == 1) || (temp == 2)) return;
-
-   switch(SiS_Pr->ChipType) {
-#ifdef CONFIG_FB_SIS_300
-   case SIS_540:
-   case SIS_630:
-   case SIS_730:
-	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
-	if((temp >= 2) && (temp <= 5))	SiS_Pr->SiS_IF_DEF_LVDS = 1;
-	if(temp == 3)			SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
-	if((temp == 4) || (temp == 5)) {
-		/* Save power status (and error check) - UNUSED */
-		SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
-		SiS_Pr->SiS_IF_DEF_CH70xx = 1;
-	}
-	break;
-#endif
-#ifdef CONFIG_FB_SIS_315
-   case SIS_550:
-   case SIS_650:
-   case SIS_740:
-   case SIS_330:
-	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
-	if((temp >= 2) && (temp <= 3))	SiS_Pr->SiS_IF_DEF_LVDS = 1;
-	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
-	break;
-   case SIS_661:
-   case SIS_741:
-   case SIS_660:
-   case SIS_760:
-   case SIS_761:
-   case SIS_340:
-   case XGI_20:
-   case XGI_40:
-	temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
-	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
-	if(temp == 3)			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
-	if(temp == 4)			SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
-	break;
-#endif
-   default:
-	break;
-   }
-}
-
-/*********************************************/
-/*          HELPER: Enable DSTN/FSTN         */
-/*********************************************/
-
-void
-SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
-{
-   SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
-}
-
-void
-SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
-{
-   SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
-}
-
-/*********************************************/
-/*            HELPER: Get modeflag           */
-/*********************************************/
-
-unsigned short
-SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex)
-{
-   if(SiS_Pr->UseCustomMode) {
-      return SiS_Pr->CModeFlag;
-   } else if(ModeNo <= 0x13) {
-      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-   } else {
-      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-   }
-}
-
-/*********************************************/
-/*        HELPER: Determine ROM usage        */
-/*********************************************/
-
-bool
-SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
-   unsigned short romversoffs, romvmaj = 1, romvmin = 0;
-
-   if(SiS_Pr->ChipType >= XGI_20) {
-      /* XGI ROMs don't qualify */
-      return false;
-   } else if(SiS_Pr->ChipType >= SIS_761) {
-      /* I very much assume 761, 340 and newer will use new layout */
-      return true;
-   } else if(SiS_Pr->ChipType >= SIS_661) {
-      if((ROMAddr[0x1a] == 'N') &&
-	 (ROMAddr[0x1b] == 'e') &&
-	 (ROMAddr[0x1c] == 'w') &&
-	 (ROMAddr[0x1d] == 'V')) {
-	 return true;
-      }
-      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
-      if(romversoffs) {
-	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
-	    romvmaj = ROMAddr[romversoffs] - '0';
-	    romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
-	 }
-      }
-      if((romvmaj != 0) || (romvmin >= 92)) {
-	 return true;
-      }
-   } else if(IS_SIS650740) {
-      if((ROMAddr[0x1a] == 'N') &&
-	 (ROMAddr[0x1b] == 'e') &&
-	 (ROMAddr[0x1c] == 'w') &&
-	 (ROMAddr[0x1d] == 'V')) {
-	 return true;
-      }
-   }
-   return false;
-}
-
-static void
-SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
-   unsigned short romptr = 0;
-
-   SiS_Pr->SiS_UseROM = false;
-   SiS_Pr->SiS_ROMNew = false;
-   SiS_Pr->SiS_PWDOffset = 0;
-
-   if(SiS_Pr->ChipType >= XGI_20) return;
-
-   if((ROMAddr) && (SiS_Pr->UseROM)) {
-      if(SiS_Pr->ChipType == SIS_300) {
-	 /* 300: We check if the code starts below 0x220 by
-	  * checking the jmp instruction at the beginning
-	  * of the BIOS image.
-	  */
-	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
-	    SiS_Pr->SiS_UseROM = true;
-      } else if(SiS_Pr->ChipType < SIS_315H) {
-	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
-	  * the others do as well
-	  */
-	 SiS_Pr->SiS_UseROM = true;
-      } else {
-	 /* 315/330 series stick to the standard(s) */
-	 SiS_Pr->SiS_UseROM = true;
-	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
-	    SiS_Pr->SiS_EMIOffset = 14;
-	    SiS_Pr->SiS_PWDOffset = 17;
-	    SiS_Pr->SiS661LCD2TableSize = 36;
-	    /* Find out about LCD data table entry size */
-	    if((romptr = SISGETROMW(0x0102))) {
-	       if(ROMAddr[romptr + (32 * 16)] == 0xff)
-		  SiS_Pr->SiS661LCD2TableSize = 32;
-	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
-		  SiS_Pr->SiS661LCD2TableSize = 34;
-	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)	   /* 0.94, 2.05.00+ */
-		  SiS_Pr->SiS661LCD2TableSize = 36;
-	       else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */
-		 	(ROMAddr[0x6F] & 0x01) ) {		   /* 2.03.00 - <2.05.00 */
-		  SiS_Pr->SiS661LCD2TableSize = 38;		   /* UMC data layout abandoned at 2.05.00 */
-		  SiS_Pr->SiS_EMIOffset = 16;
-		  SiS_Pr->SiS_PWDOffset = 19;
-	       }
-	    }
-	 }
-      }
-   }
-}
-
-/*********************************************/
-/*        HELPER: SET SEGMENT REGISTERS      */
-/*********************************************/
-
-static void
-SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
-{
-   unsigned short temp;
-
-   value &= 0x00ff;
-   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
-   temp |= (value >> 4);
-   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
-   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;
-   temp |= (value & 0x0f);
-   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
-}
-
-static void
-SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
-{
-   unsigned short temp;
-
-   value &= 0x00ff;
-   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
-   temp |= (value & 0xf0);
-   SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
-   temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;
-   temp |= (value << 4);
-   SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
-}
-
-static void
-SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
-{
-   SiS_SetSegRegLower(SiS_Pr, value);
-   SiS_SetSegRegUpper(SiS_Pr, value);
-}
-
-static void
-SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
-{
-   SiS_SetSegmentReg(SiS_Pr, 0);
-}
-
-static void
-SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
-{
-   unsigned short temp = value >> 8;
-
-   temp &= 0x07;
-   temp |= (temp << 4);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);
-   SiS_SetSegmentReg(SiS_Pr, value);
-}
-
-static void
-SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
-{
-   SiS_SetSegmentRegOver(SiS_Pr, 0);
-}
-
-static void
-SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
-{
-   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
-      SiS_ResetSegmentReg(SiS_Pr);
-      SiS_ResetSegmentRegOver(SiS_Pr);
-   }
-}
-
-/*********************************************/
-/*             HELPER: GetVBType             */
-/*********************************************/
-
-static
-void
-SiS_GetVBType(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag = 0, rev = 0, nolcd = 0;
-   unsigned short p4_0f, p4_25, p4_27;
-
-   SiS_Pr->SiS_VBType = 0;
-
-   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
-      return;
-
-   if(SiS_Pr->ChipType == XGI_20)
-      return;
-
-   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-
-   if(flag > 3)
-      return;
-
-   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
-
-   if(flag >= 2) {
-      SiS_Pr->SiS_VBType = VB_SIS302B;
-   } else if(flag == 1) {
-      if(rev >= 0xC0) {
-	 SiS_Pr->SiS_VBType = VB_SIS301C;
-      } else if(rev >= 0xB0) {
-	 SiS_Pr->SiS_VBType = VB_SIS301B;
-	 /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
-	 nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
-	 if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
-      } else {
-	 SiS_Pr->SiS_VBType = VB_SIS301;
-      }
-   }
-   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
-      if(rev >= 0xE0) {
-	 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
-	 if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
-	 else 	 	  SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
-      } else if(rev >= 0xD0) {
-	 SiS_Pr->SiS_VBType = VB_SIS301LV;
-      }
-   }
-   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
-      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
-      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
-      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
-      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
-      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
-      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
-      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
-         SiS_Pr->SiS_VBType |= VB_UMC;
-      }
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
-   }
-}
-
-/*********************************************/
-/*           HELPER: Check RAM size          */
-/*********************************************/
-
-static bool
-SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex)
-{
-   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
-   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
-
-   if(!AdapterMemSize) return true;
-
-   if(AdapterMemSize < memorysize) return false;
-   return true;
-}
-
-/*********************************************/
-/*           HELPER: Get DRAM type           */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_315
-static unsigned char
-SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
-{
-   unsigned char data;
-
-   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
-      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
-   } else {
-      if(SiS_Pr->ChipType >= XGI_20) {
-         /* Do I need this? SR17 seems to be zero anyway... */
-	 data = 0;
-      } else if(SiS_Pr->ChipType >= SIS_340) {
-	 /* TODO */
-	 data = 0;
-      } if(SiS_Pr->ChipType >= SIS_661) {
-	 if(SiS_Pr->SiS_ROMNew) {
-	    data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
-	 } else {
-	    data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
-	 }
-      } else if(IS_SIS550650740) {
-	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
-      } else {	/* 315, 330 */
-	 data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
-	 if(SiS_Pr->ChipType == SIS_330) {
-	    if(data > 1) {
-	       switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
-	       case 0x00: data = 1; break;
-	       case 0x10: data = 3; break;
-	       case 0x20: data = 3; break;
-	       case 0x30: data = 2; break;
-	       }
-	    } else {
-	       data = 0;
-	    }
-	 }
-      }
-   }
-
-   return data;
-}
-
-static unsigned short
-SiS_GetMCLK(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short index;
-
-   index = SiS_Get310DRAMType(SiS_Pr);
-   if(SiS_Pr->ChipType >= SIS_661) {
-      if(SiS_Pr->SiS_ROMNew) {
-	 return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
-      }
-      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
-   } else if(index >= 4) {
-      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
-   } else {
-      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
-   }
-}
-#endif
-
-/*********************************************/
-/*           HELPER: ClearBuffer             */
-/*********************************************/
-
-static void
-SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
-   unsigned int   memsize = SiS_Pr->VideoMemorySize;
-   unsigned short SISIOMEMTYPE *pBuffer;
-   int i;
-
-   if(!memaddr || !memsize) return;
-
-   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
-      if(ModeNo > 0x13) {
-	 memset_io(memaddr, 0, memsize);
-      } else {
-	 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
-	 for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
-      }
-   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
-      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
-      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
-   } else {
-      memset_io(memaddr, 0, 0x8000);
-   }
-}
-
-/*********************************************/
-/*           HELPER: SearchModeID            */
-/*********************************************/
-
-bool
-SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
-		unsigned short *ModeIdIndex)
-{
-   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
-
-   if((*ModeNo) <= 0x13) {
-
-      if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
-
-      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
-	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
-	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
-      }
-
-      if((*ModeNo) == 0x07) {
-	  if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
-	  /* else 350 lines */
-      }
-      if((*ModeNo) <= 0x03) {
-	 if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
-	 if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
-	 /* else 350 lines  */
-      }
-      /* else 200 lines  */
-
-   } else {
-
-      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
-	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
-	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
-      }
-
-   }
-   return true;
-}
-
-/*********************************************/
-/*            HELPER: GetModePtr             */
-/*********************************************/
-
-unsigned short
-SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned short index;
-
-   if(ModeNo <= 0x13) {
-      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
-   } else {
-      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
-      else index = 0x0F;
-   }
-   return index;
-}
-
-/*********************************************/
-/*         HELPERS: Get some indices         */
-/*********************************************/
-
-unsigned short
-SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
-{
-   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
-      if(UseWide == 1) {
-         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
-      } else {
-         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
-      }
-   } else {
-      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
-   }
-}
-
-unsigned short
-SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
-{
-   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
-      if(UseWide == 1) {
-         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
-      } else {
-         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
-      }
-   } else {
-      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
-   }
-}
-
-/*********************************************/
-/*           HELPER: LowModeTests            */
-/*********************************************/
-
-static bool
-SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-   unsigned short temp, temp1, temp2;
-
-   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
-      return true;
-   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
-   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
-   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
-   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
-   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
-   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
-   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
-   if((SiS_Pr->ChipType >= SIS_315H) ||
-      (SiS_Pr->ChipType == SIS_300)) {
-      if(temp2 == 0x55) return false;
-      else return true;
-   } else {
-      if(temp2 != 0x55) return true;
-      else {
-	 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-	 return false;
-      }
-   }
-}
-
-static void
-SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
-      SiS_Pr->SiS_SetFlag |= LowModeTests;
-   }
-}
-
-/*********************************************/
-/*        HELPER: OPEN/CLOSE CRT1 CRTC       */
-/*********************************************/
-
-static void
-SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
-{
-   if(IS_SIS650) {
-      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-   } else if(IS_SIS661741660760) {
-      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
-      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-      if(!SiS_Pr->SiS_ROMNew) {
-	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-      }
-   }
-}
-
-static void
-SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
-{
-#if 0 /* This locks some CRTC registers. We don't want that. */
-   unsigned short temp1 = 0, temp2 = 0;
-
-   if(IS_SIS661741660760) {
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-         temp1 = 0xa0; temp2 = 0x08;
-      }
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
-   }
-#endif
-}
-
-static void
-SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
-{
-   /* Enable CRT1 gating */
-   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
-#if 0
-   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
-      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
-         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
-         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
-      }
-   }
-#endif
-}
-
-/*********************************************/
-/*           HELPER: GetColorDepth           */
-/*********************************************/
-
-unsigned short
-SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex)
-{
-   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
-   unsigned short modeflag;
-   short index;
-
-   /* Do NOT check UseCustomMode, will skrew up FIFO */
-   if(ModeNo == 0xfe) {
-      modeflag = SiS_Pr->CModeFlag;
-   } else if(ModeNo <= 0x13) {
-      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-   } else {
-      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-   }
-
-   index = (modeflag & ModeTypeMask) - ModeEGA;
-   if(index < 0) index = 0;
-   return ColorDepth[index];
-}
-
-/*********************************************/
-/*             HELPER: GetOffset             */
-/*********************************************/
-
-unsigned short
-SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex, unsigned short RRTI)
-{
-   unsigned short xres, temp, colordepth, infoflag;
-
-   if(SiS_Pr->UseCustomMode) {
-      infoflag = SiS_Pr->CInfoFlag;
-      xres = SiS_Pr->CHDisplay;
-   } else {
-      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
-      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
-   }
-
-   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
-
-   temp = xres / 16;
-   if(infoflag & InterlaceMode) temp <<= 1;
-   temp *= colordepth;
-   if(xres % 16) temp += (colordepth >> 1);
-
-   return temp;
-}
-
-/*********************************************/
-/*                   SEQ                     */
-/*********************************************/
-
-static void
-SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
-{
-   unsigned char SRdata;
-   int i;
-
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
-
-   /* or "display off"  */
-   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
-
-   /* determine whether to force x8 dotclock */
-   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
-
-      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
-         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;
-      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
-
-   }
-
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
-
-   for(i = 2; i <= 4; i++) {
-      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
-      SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
-   }
-}
-
-/*********************************************/
-/*                  MISC                     */
-/*********************************************/
-
-static void
-SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
-{
-   unsigned char Miscdata;
-
-   Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
-
-   if(SiS_Pr->ChipType < SIS_661) {
-      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	   Miscdata |= 0x0C;
-	 }
-      }
-   }
-
-   SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);
-}
-
-/*********************************************/
-/*                  CRTC                     */
-/*********************************************/
-
-static void
-SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
-{
-   unsigned char  CRTCdata;
-   unsigned short i;
-
-   /* Unlock CRTC */
-   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-
-   for(i = 0; i <= 0x18; i++) {
-      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
-      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
-   }
-
-   if(SiS_Pr->ChipType >= SIS_661) {
-      SiS_OpenCRTC(SiS_Pr);
-      for(i = 0x13; i <= 0x14; i++) {
-	 CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
-	 SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
-      }
-   } else if( ( (SiS_Pr->ChipType == SIS_630) ||
-	        (SiS_Pr->ChipType == SIS_730) )  &&
-	      (SiS_Pr->ChipRevision >= 0x30) ) {
-      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
-	    SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
-	 }
-      }
-   }
-}
-
-/*********************************************/
-/*                   ATT                     */
-/*********************************************/
-
-static void
-SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
-{
-   unsigned char  ARdata;
-   unsigned short i;
-
-   for(i = 0; i <= 0x13; i++) {
-      ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
-
-      if(i == 0x13) {
-	 /* Pixel shift. If screen on LCD or TV is shifted left or right,
-	  * this might be the cause.
-	  */
-	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
-	 }
-	 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	    if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-		  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
-	       }
-	    }
-	 }
-	 if(SiS_Pr->ChipType >= SIS_661) {
-	    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
-	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
-	    }
-	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	    if(SiS_Pr->ChipType >= SIS_315H) {
-	       if(IS_SIS550650740660) {
-		  /* 315, 330 don't do this */
-		  if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
-		     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
-		  } else {
-		     ARdata = 0;
-		  }
-	       }
-	    } else {
-	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
-	    }
-	 }
-      }
-      SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */
-      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);	/* set index  */
-      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata);	/* set data   */
-   }
-
-   SiS_GetRegByte(SiS_Pr->SiS_P3da);		/* reset 3da  */
-   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);	/* set index  */
-   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);	/* set data   */
-
-   SiS_GetRegByte(SiS_Pr->SiS_P3da);
-   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);	/* Enable Attribute  */
-   SiS_GetRegByte(SiS_Pr->SiS_P3da);
-}
-
-/*********************************************/
-/*                   GRC                     */
-/*********************************************/
-
-static void
-SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
-{
-   unsigned char  GRdata;
-   unsigned short i;
-
-   for(i = 0; i <= 0x08; i++) {
-      GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
-      SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);
-   }
-
-   if(SiS_Pr->SiS_ModeType > ModeVGA) {
-      /* 256 color disable */
-      SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);
-   }
-}
-
-/*********************************************/
-/*          CLEAR EXTENDED REGISTERS         */
-/*********************************************/
-
-static void
-SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-   unsigned short i;
-
-   for(i = 0x0A; i <= 0x0E; i++) {
-      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
-   }
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
-      if(ModeNo <= 0x13) {
-	 if(ModeNo == 0x06 || ModeNo >= 0x0e) {
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
-	 }
-      }
-   }
-}
-
-/*********************************************/
-/*                 RESET VCLK                */
-/*********************************************/
-
-static void
-SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if(SiS_Pr->ChipType < SIS_661) {
-	 if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
-      }
-   } else {
-      if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
-	 (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
-	 return;
-      }
-   }
-
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
-}
-
-/*********************************************/
-/*                  SYNC                     */
-/*********************************************/
-
-static void
-SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
-{
-   unsigned short sync;
-
-   if(SiS_Pr->UseCustomMode) {
-      sync = SiS_Pr->CInfoFlag >> 8;
-   } else {
-      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
-   }
-
-   sync &= 0xC0;
-   sync |= 0x2f;
-   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
-}
-
-/*********************************************/
-/*                  CRTC/2                   */
-/*********************************************/
-
-static void
-SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex, unsigned short RRTI)
-{
-   unsigned short temp, i, j, modeflag;
-   unsigned char  *crt1data = NULL;
-
-   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-
-   if(SiS_Pr->UseCustomMode) {
-
-      crt1data = &SiS_Pr->CCRT1CRTC[0];
-
-   } else {
-
-      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
-
-      /* Alternate for 1600x1200 LCDA */
-      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
-
-      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
-
-   }
-
-   /* unlock cr0-7 */
-   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-
-   for(i = 0, j = 0; i <= 7; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
-   }
-   for(j = 0x10; i <= 10; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
-   }
-   for(j = 0x15; i <= 12; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
-   }
-   for(j = 0x0A; i <= 15; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
-   }
-
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
-
-   temp = (crt1data[16] & 0x01) << 5;
-   if(modeflag & DoubleScanMode) temp |= 0x80;
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
-
-   if(SiS_Pr->SiS_ModeType > ModeVGA) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
-   }
-
-#ifdef CONFIG_FB_SIS_315
-   if(SiS_Pr->ChipType == XGI_20) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
-      if(!(temp = crt1data[5] & 0x1f)) {
-         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
-      }
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
-      temp = (crt1data[16] >> 5) + 3;
-      if(temp > 7) temp -= 7;
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
-   }
-#endif
-}
-
-/*********************************************/
-/*               OFFSET & PITCH              */
-/*********************************************/
-/*  (partly overruled by SetPitch() in XF86) */
-/*********************************************/
-
-static void
-SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex, unsigned short RRTI)
-{
-   unsigned short temp, DisplayUnit, infoflag;
-
-   if(SiS_Pr->UseCustomMode) {
-      infoflag = SiS_Pr->CInfoFlag;
-   } else {
-      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
-   }
-
-   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
-
-   temp = (DisplayUnit >> 8) & 0x0f;
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
-
-   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
-
-   if(infoflag & InterlaceMode) DisplayUnit >>= 1;
-
-   DisplayUnit <<= 5;
-   temp = (DisplayUnit >> 8) + 1;
-   if(DisplayUnit & 0xff) temp++;
-   if(SiS_Pr->ChipType == XGI_20) {
-      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
-   }
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
-}
-
-/*********************************************/
-/*                  VCLK                     */
-/*********************************************/
-
-static void
-SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex, unsigned short RRTI)
-{
-   unsigned short index = 0, clka, clkb;
-
-   if(SiS_Pr->UseCustomMode) {
-      clka = SiS_Pr->CSR2B;
-      clkb = SiS_Pr->CSR2C;
-   } else {
-      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
-      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
-	 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-	 /* Alternate for 1600x1200 LCDA */
-	 if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
-	 clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
-	 clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
-      } else {
-	 clka = SiS_Pr->SiS_VCLKData[index].SR2B;
-	 clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
-      }
-   }
-
-   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
-
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-#ifdef CONFIG_FB_SIS_315
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
-      if(SiS_Pr->ChipType == XGI_20) {
-         unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-	 if(mf & HalfDCLK) {
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
-	    clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
-	    clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
-	 }
-      }
-#endif
-   } else {
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
-   }
-}
-
-/*********************************************/
-/*                  FIFO                     */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_300
-void
-SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
-		unsigned short *idx2)
-{
-   unsigned short temp1, temp2;
-   static const unsigned char ThTiming[8] = {
-		1, 2, 2, 3, 0, 1, 1, 2
-   };
-
-   temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
-   (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
-   (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
-   (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
-   (*idx1) <<= 1;
-}
-
-static unsigned short
-SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
-{
-   static const unsigned char ThLowA[8 * 3] = {
-		61, 3,52, 5,68, 7,100,11,
-		43, 3,42, 5,54, 7, 78,11,
-		34, 3,37, 5,47, 7, 67,11
-   };
-
-   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
-}
-
-unsigned short
-SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
-{
-   static const unsigned char ThLowB[8 * 3] = {
-		81, 4,72, 6,88, 8,120,12,
-		55, 4,54, 6,66, 8, 90,12,
-		42, 4,45, 6,55, 8, 75,12
-   };
-
-   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
-}
-
-static unsigned short
-SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
-		unsigned short colordepth, unsigned short key)
-{
-   unsigned short idx1, idx2;
-   unsigned int   longtemp = VCLK * colordepth;
-
-   SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
-
-   if(key == 0) {
-      longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
-   } else {
-      longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
-   }
-   idx1 = longtemp % (MCLK * 16);
-   longtemp /= (MCLK * 16);
-   if(idx1) longtemp++;
-   return (unsigned short)longtemp;
-}
-
-static unsigned short
-SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
-		unsigned short colordepth, unsigned short MCLK)
-{
-   unsigned short temp1, temp2;
-
-   temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
-   temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
-   if(temp1 < 4) temp1 = 4;
-   temp1 -= 4;
-   if(temp2 < temp1) temp2 = temp1;
-   return temp2;
-}
-
-static void
-SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short RefreshRateTableIndex)
-{
-   unsigned short ThresholdLow = 0;
-   unsigned short temp, index, VCLK, MCLK, colorth;
-   static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
-
-   if(ModeNo > 0x13) {
-
-      /* Get VCLK  */
-      if(SiS_Pr->UseCustomMode) {
-	 VCLK = SiS_Pr->CSRClock;
-      } else {
-	 index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
-	 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
-      }
-
-      /* Get half colordepth */
-      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
-
-      /* Get MCLK  */
-      index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
-      MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
-
-      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
-
-      do {
-	 ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
-	 if(ThresholdLow < 0x13) break;
-	 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
-	 ThresholdLow = 0x13;
-	 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
-	 if(!temp) break;
-	 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
-      } while(0);
-
-   } else ThresholdLow = 2;
-
-   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
-   temp = (ThresholdLow << 4) | 0x0f;
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
-
-   temp = (ThresholdLow & 0x10) << 1;
-   if(ModeNo > 0x13) temp |= 0x40;
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
-
-   /* What is this? */
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
-
-   /* Write CRT/CPU threshold high */
-   temp = ThresholdLow + 3;
-   if(temp > 0x0f) temp = 0x0f;
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
-}
-
-unsigned short
-SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
-{
-   static const unsigned char LatencyFactor[] = {
-		97, 88, 86, 79, 77,  0,       /* 64  bit    BQ=2   */
-		 0, 87, 85, 78, 76, 54,       /* 64  bit    BQ=1   */
-		97, 88, 86, 79, 77,  0,       /* 128 bit    BQ=2   */
-		 0, 79, 77, 70, 68, 48,       /* 128 bit    BQ=1   */
-		80, 72, 69, 63, 61,  0,       /* 64  bit    BQ=2   */
-		 0, 70, 68, 61, 59, 37,       /* 64  bit    BQ=1   */
-		86, 77, 75, 68, 66,  0,       /* 128 bit    BQ=2   */
-		 0, 68, 66, 59, 57, 37        /* 128 bit    BQ=1   */
-   };
-   static const unsigned char LatencyFactor730[] = {
-		 69, 63, 61,
-		 86, 79, 77,
-		103, 96, 94,
-		120,113,111,
-		137,130,128
-   };
-
-   if(SiS_Pr->ChipType == SIS_730) {
-      return (unsigned short)LatencyFactor730[index];
-   } else {
-      return (unsigned short)LatencyFactor[index];
-   }
-}
-
-static unsigned short
-SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
-{
-   unsigned short index;
-
-   if(SiS_Pr->ChipType == SIS_730) {
-      index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
-   } else {
-      index = (key & 0xe0) >> 5;
-      if(key & 0x10)    index +=  6;
-      if(!(key & 0x01)) index += 24;
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
-   }
-   return SiS_GetLatencyFactor630(SiS_Pr, index);
-}
-
-static void
-SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-                    unsigned short RefreshRateTableIndex)
-{
-   unsigned short  ThresholdLow = 0;
-   unsigned short  i, data, VCLK, MCLK16, colorth = 0;
-   unsigned int    templ, datal;
-   const unsigned char *queuedata = NULL;
-   static const unsigned char FQBQData[21] = {
-		0x01,0x21,0x41,0x61,0x81,
-		0x31,0x51,0x71,0x91,0xb1,
-		0x00,0x20,0x40,0x60,0x80,
-		0x30,0x50,0x70,0x90,0xb0,
-		0xff
-   };
-   static const unsigned char FQBQData730[16] = {
-		0x34,0x74,0xb4,
-		0x23,0x63,0xa3,
-		0x12,0x52,0x92,
-		0x01,0x41,0x81,
-		0x00,0x40,0x80,
-		0xff
-   };
-   static const unsigned short colortharray[6] = {
-		1, 1, 2, 2, 3, 4
-   };
-
-   i = 0;
-
-   if(ModeNo > 0x13) {
-
-      /* Get VCLK  */
-      if(SiS_Pr->UseCustomMode) {
-	 VCLK = SiS_Pr->CSRClock;
-      } else {
-	 data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
-	 VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
-      }
-
-      /* Get MCLK * 16 */
-      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
-      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
-
-      /* Get half colordepth */
-      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
-
-      if(SiS_Pr->ChipType == SIS_730) {
-	 queuedata = &FQBQData730[0];
-      } else {
-	 queuedata = &FQBQData[0];
-      }
-
-      do {
-	 templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
-
-	 datal = templ % MCLK16;
-	 templ = (templ / MCLK16) + 1;
-	 if(datal) templ++;
-
-	 if(templ > 0x13) {
-	    if(queuedata[i + 1] == 0xFF) {
-	       ThresholdLow = 0x13;
-	       break;
-	    }
-	    i++;
-	 } else {
-	    ThresholdLow = templ;
-	    break;
-	 }
-      } while(queuedata[i] != 0xFF);
-
-   } else {
-
-      if(SiS_Pr->ChipType != SIS_730) i = 9;
-      ThresholdLow = 0x02;
-
-   }
-
-   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
-   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
-
-   data = (ThresholdLow & 0x10) << 1;
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
-
-   /* What is this? */
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
-
-   /* Write CRT/CPU threshold high (gap = 3) */
-   data = ThresholdLow + 3;
-   if(data > 0x0f) data = 0x0f;
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
-
-  /* Write foreground and background queue */
-   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
-
-   if(SiS_Pr->ChipType == SIS_730) {
-
-      templ &= 0xfffff9ff;
-      templ |= ((queuedata[i] & 0xc0) << 3);
-
-   } else {
-
-      templ &= 0xf0ffffff;
-      if( (ModeNo <= 0x13) &&
-          (SiS_Pr->ChipType == SIS_630) &&
-	  (SiS_Pr->ChipRevision >= 0x30) ) {
-	 templ |= 0x0b000000;
-      } else {
-         templ |= ((queuedata[i] & 0xf0) << 20);
-      }
-
-   }
-
-   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
-   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
-
-   /* GUI grant timer (PCI config 0xA3) */
-   if(SiS_Pr->ChipType == SIS_730) {
-
-      templ &= 0x00ffffff;
-      datal = queuedata[i] << 8;
-      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
-
-   } else {
-
-      templ &= 0xf0ffffff;
-      templ |= ((queuedata[i] & 0x0f) << 24);
-
-   }
-
-   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
-}
-#endif /* CONFIG_FB_SIS_300 */
-
-#ifdef CONFIG_FB_SIS_315
-static void
-SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned short modeflag;
-
-   /* disable auto-threshold */
-   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
-
-   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-   if(ModeNo > 0x13) {
-      if(SiS_Pr->ChipType >= XGI_20) {
-	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-      } else if(SiS_Pr->ChipType >= SIS_661) {
-	 if(!(modeflag & HalfDCLK)) {
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-	 }
-      } else {
-	 if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-	 }
-      }
-   }
-}
-#endif
-
-/*********************************************/
-/*              MODE REGISTERS               */
-/*********************************************/
-
-static void
-SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
-{
-   unsigned short data = 0, VCLK = 0, index = 0;
-
-   if(ModeNo > 0x13) {
-      if(SiS_Pr->UseCustomMode) {
-         VCLK = SiS_Pr->CSRClock;
-      } else {
-         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
-      }
-   }
-
-   if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-      if(VCLK > 150) data |= 0x80;
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
-
-      data = 0x00;
-      if(VCLK >= 150) data |= 0x08;
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
-#endif
-   } else if(SiS_Pr->ChipType < XGI_20) {
-#ifdef CONFIG_FB_SIS_315
-      if(VCLK >= 166) data |= 0x0c;
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
-
-      if(VCLK >= 166) {
-         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
-      }
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      if(VCLK >= 200) data |= 0x0c;
-      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
-      if(SiS_Pr->ChipType != XGI_20) {
-         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
-	 if(VCLK < 200) data |= 0x10;
-	 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
-      }
-#endif
-   }
-
-   /* DAC speed */
-   if(SiS_Pr->ChipType >= SIS_661) {
-
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
-
-   } else {
-
-      data = 0x03;
-      if(VCLK >= 260)      data = 0x00;
-      else if(VCLK >= 160) data = 0x01;
-      else if(VCLK >= 135) data = 0x02;
-
-      if(SiS_Pr->ChipType == SIS_540) {
-         /* Was == 203 or < 234 which made no sense */
-         if (VCLK < 234) data = 0x02;
-      }
-
-      if(SiS_Pr->ChipType < SIS_315H) {
-         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
-      } else {
-         if(SiS_Pr->ChipType > SIS_315PRO) {
-            if(ModeNo > 0x13) data &= 0xfc;
-         }
-         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
-      }
-
-   }
-}
-
-static void
-SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex, unsigned short RRTI)
-{
-   unsigned short data, infoflag = 0, modeflag, resindex;
-#ifdef CONFIG_FB_SIS_315
-   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
-   unsigned short data2, data3;
-#endif
-
-   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-
-   if(SiS_Pr->UseCustomMode) {
-      infoflag = SiS_Pr->CInfoFlag;
-   } else {
-      resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
-      if(ModeNo > 0x13) {
-	 infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
-      }
-   }
-
-   /* Disable DPMS */
-   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
-
-   data = 0;
-   if(ModeNo > 0x13) {
-      if(SiS_Pr->SiS_ModeType > ModeEGA) {
-         data |= 0x02;
-         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
-      }
-      if(infoflag & InterlaceMode) data |= 0x20;
-   }
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
-
-   if(SiS_Pr->ChipType != SIS_300) {
-      data = 0;
-      if(infoflag & InterlaceMode) {
-	 /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
-	 int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
-		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
-	 int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
-		    ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
-	 data = hrs - (hto >> 1) + 3;
-      }
-      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
-   }
-
-   if(modeflag & HalfDCLK) {
-      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
-   }
-
-   data = 0;
-   if(modeflag & LineCompareOff) data = 0x08;
-   if(SiS_Pr->ChipType == SIS_300) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
-   } else {
-      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
-      if(SiS_Pr->SiS_ModeType == ModeEGA) {
-	 if(ModeNo > 0x13) {
-	    data |= 0x40;
-	 }
-      }
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
-   }
-
-#ifdef CONFIG_FB_SIS_315
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
-   }
-
-   if(SiS_Pr->ChipType == SIS_315PRO) {
-
-      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
-      if(SiS_Pr->SiS_ModeType == ModeText) {
-	 data &= 0xc7;
-      } else {
-	 data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
-	 if(infoflag & InterlaceMode) data2 >>= 1;
-	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
-	 if(data3) data2 /= data3;
-	 if(data2 >= 0x50) {
-	    data &= 0x0f;
-	    data |= 0x50;
-	 }
-      }
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-
-   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
-
-      data = SiS_Get310DRAMType(SiS_Pr);
-      if(SiS_Pr->ChipType == SIS_330) {
-	 data = SiS_Pr->SiS_SR15[(2 * 4) + data];
-      } else {
-	 if(SiS_Pr->SiS_ROMNew)	     data = ROMAddr[0xf6];
-	 else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
-	 else			     data = 0xba;
-      }
-      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
-	 data &= 0xc7;
-      } else {
-	 if(SiS_Pr->UseCustomMode) {
-	    data2 = SiS_Pr->CSRClock;
-	 } else {
-	    data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
-	    data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
-	 }
-
-	 data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
-	 if(data3) data2 *= data3;
-
-	 data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
-
-	 if(SiS_Pr->ChipType == SIS_330) {
-	    if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
-	       if     (data2 >= 0x19c) data = 0xba;
-	       else if(data2 >= 0x140) data = 0x7a;
-	       else if(data2 >= 0x101) data = 0x3a;
-	       else if(data2 >= 0xf5)  data = 0x32;
-	       else if(data2 >= 0xe2)  data = 0x2a;
-	       else if(data2 >= 0xc4)  data = 0x22;
-	       else if(data2 >= 0xac)  data = 0x1a;
-	       else if(data2 >= 0x9e)  data = 0x12;
-	       else if(data2 >= 0x8e)  data = 0x0a;
-	       else                    data = 0x02;
-	    } else {
-	       if(data2 >= 0x127)      data = 0xba;
-	       else                    data = 0x7a;
-	    }
-	 } else {  /* 76x+LFB */
-	    if     (data2 >= 0x190) data = 0xba;
-	    else if(data2 >= 0xff)  data = 0x7a;
-	    else if(data2 >= 0xd3)  data = 0x3a;
-	    else if(data2 >= 0xa9)  data = 0x1a;
-	    else if(data2 >= 0x93)  data = 0x0a;
-	    else                    data = 0x02;
-	 }
-      }
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-
-   }
-      /* XGI: Nothing. */
-      /* TODO: Check SiS340 */
-#endif
-
-   data = 0x60;
-   if(SiS_Pr->SiS_ModeType != ModeText) {
-      data ^= 0x60;
-      if(SiS_Pr->SiS_ModeType != ModeEGA) {
-         data ^= 0xA0;
-      }
-   }
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
-
-   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
-
-#ifdef CONFIG_FB_SIS_315
-   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
-       (SiS_Pr->ChipType == XGI_40)) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
-      } else {
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
-      }
-   } else if(SiS_Pr->ChipType == XGI_20) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
-      } else {
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
-      }
-      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
-   }
-#endif
-}
-
-#ifdef CONFIG_FB_SIS_315
-static void
-SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
-{
-#if 0
-   /* TODO: Find out about IOAddress2 */
-   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
-   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
-   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
-   int i;
-
-   if((SiS_Pr->ChipRevision != 0) ||
-      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
-      return;
-
-   for(i = 0; i <= 4; i++) {					/* SR00 - SR04 */
-      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
-   }
-   for(i = 0; i <= 8; i++) {					/* GR00 - GR08 */
-      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
-   }
-   SiS_SetReg(P2_3c4,0x05,0x86);
-   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));	/* SR06 */
-   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));	/* SR21 */
-   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));	/* MISC */
-   SiS_SetReg(P2_3c4,0x05,0x00);
-#endif
-}
-#endif
-
-/*********************************************/
-/*                 LOAD DAC                  */
-/*********************************************/
-
-static void
-SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
-             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
-{
-   unsigned short d1, d2, d3;
-
-   switch(dl) {
-   case  0: d1 = dh; d2 = ah; d3 = al; break;
-   case  1: d1 = ah; d2 = al; d3 = dh; break;
-   default: d1 = al; d2 = dh; d3 = ah;
-   }
-   SiS_SetRegByte(DACData, (d1 << shiftflag));
-   SiS_SetRegByte(DACData, (d2 << shiftflag));
-   SiS_SetRegByte(DACData, (d3 << shiftflag));
-}
-
-void
-SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned short data, data2, time, i, j, k, m, n, o;
-   unsigned short si, di, bx, sf;
-   SISIOADDRESS DACAddr, DACData;
-   const unsigned char *table = NULL;
-
-   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
-
-   j = time = 64;
-   if(data == 0x00)      table = SiS_MDA_DAC;
-   else if(data == 0x08) table = SiS_CGA_DAC;
-   else if(data == 0x10) table = SiS_EGA_DAC;
-   else if(data == 0x18) {
-      j = 16;
-      time = 256;
-      table = SiS_VGA_DAC;
-   }
-
-   if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */
-         (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||
-       (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */
-       (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */
-      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
-      DACAddr = SiS_Pr->SiS_P3c8;
-      DACData = SiS_Pr->SiS_P3c9;
-      sf = 0;
-   } else {
-      DACAddr = SiS_Pr->SiS_Part5Port;
-      DACData = SiS_Pr->SiS_Part5Port + 1;
-      sf = 2;
-   }
-
-   SiS_SetRegByte(DACAddr,0x00);
-
-   for(i = 0; i < j; i++) {
-      data = table[i];
-      for(k = 0; k < 3; k++) {
-	data2 = 0;
-	if(data & 0x01) data2 += 0x2A;
-	if(data & 0x02) data2 += 0x15;
-	SiS_SetRegByte(DACData, (data2 << sf));
-	data >>= 2;
-      }
-   }
-
-   if(time == 256) {
-      for(i = 16; i < 32; i++) {
-	 data = table[i] << sf;
-	 for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
-      }
-      si = 32;
-      for(m = 0; m < 9; m++) {
-	 di = si;
-	 bx = si + 4;
-	 for(n = 0; n < 3; n++) {
-	    for(o = 0; o < 5; o++) {
-	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
-	       si++;
-	    }
-	    si -= 2;
-	    for(o = 0; o < 3; o++) {
-	       SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
-	       si--;
-	    }
-	 }            /* for n < 3 */
-	 si += 5;
-      }               /* for m < 9 */
-   }
-}
-
-/*********************************************/
-/*         SET CRT1 REGISTER GROUP           */
-/*********************************************/
-
-static void
-SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned short StandTableIndex, RefreshRateTableIndex;
-
-   SiS_Pr->SiS_CRT1Mode = ModeNo;
-
-   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
-
-   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
-         SiS_DisableBridge(SiS_Pr);
-      }
-   }
-
-   SiS_ResetSegmentRegisters(SiS_Pr);
-
-   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
-   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
-   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
-   SiS_SetATTRegs(SiS_Pr, StandTableIndex);
-   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
-   SiS_ClearExt1Regs(SiS_Pr, ModeNo);
-   SiS_ResetCRT1VCLK(SiS_Pr);
-
-   SiS_Pr->SiS_SelectCRT2Rate = 0;
-   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
-
-   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
-      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-      }
-   }
-
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-   }
-
-   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
-
-   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
-   }
-
-   if(RefreshRateTableIndex != 0xFFFF) {
-      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
-      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-   }
-
-   switch(SiS_Pr->ChipType) {
-#ifdef CONFIG_FB_SIS_300
-   case SIS_300:
-      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
-      break;
-   case SIS_540:
-   case SIS_630:
-   case SIS_730:
-      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
-      break;
-#endif
-   default:
-#ifdef CONFIG_FB_SIS_315
-      if(SiS_Pr->ChipType == XGI_20) {
-         unsigned char sr2b = 0, sr2c = 0;
-         switch(ModeNo) {
-	 case 0x00:
-	 case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
-	 case 0x04:
-	 case 0x05:
-	 case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
-	 }
-	 if(sr2b) {
-            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
-	    SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
-	 }
-      }
-      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
-#endif
-      break;
-   }
-
-   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-
-#ifdef CONFIG_FB_SIS_315
-   if(SiS_Pr->ChipType == XGI_40) {
-      SiS_SetupDualChip(SiS_Pr);
-   }
-#endif
-
-   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
-
-   if(SiS_Pr->SiS_flag_clearbuffer) {
-      SiS_ClearBuffer(SiS_Pr, ModeNo);
-   }
-
-   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
-      SiS_WaitRetrace1(SiS_Pr);
-      SiS_DisplayOn(SiS_Pr);
-   }
-}
-
-/*********************************************/
-/*       HELPER: VIDEO BRIDGE PROG CLK       */
-/*********************************************/
-
-static void
-SiS_InitVB(struct SiS_Private *SiS_Pr)
-{
-   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
-
-   SiS_Pr->Init_P4_0E = 0;
-   if(SiS_Pr->SiS_ROMNew) {
-      SiS_Pr->Init_P4_0E = ROMAddr[0x82];
-   } else if(SiS_Pr->ChipType >= XGI_40) {
-      if(SiS_Pr->SiS_XGIROM) {
-         SiS_Pr->Init_P4_0E = ROMAddr[0x80];
-      }
-   }
-}
-
-static void
-SiS_ResetVB(struct SiS_Private *SiS_Pr)
-{
-#ifdef CONFIG_FB_SIS_315
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short temp;
-
-   /* VB programming clock */
-   if(SiS_Pr->SiS_UseROM) {
-      if(SiS_Pr->ChipType < SIS_330) {
-	 temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
-	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
-	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
-	 temp = ROMAddr[0x7e] | 0x40;
-	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
-	 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-      }
-   } else if(SiS_Pr->ChipType >= XGI_40) {
-      temp = 0x40;
-      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
-      /* Can we do this on any chipset? */
-      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-   }
-#endif
-}
-
-/*********************************************/
-/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */
-/*********************************************/
-
-static void
-SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
-{
-   /* SiS65x and XGI set up some sort of "lock mode" for text
-    * which locks CRT2 in some way to CRT1 timing. Disable
-    * this here.
-    */
-#ifdef CONFIG_FB_SIS_315
-   if((IS_SIS651) || (IS_SISM650) ||
-      SiS_Pr->ChipType == SIS_340 ||
-      SiS_Pr->ChipType == XGI_40) {
-      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
-      SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
-      SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
-      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
-      SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
-   }
-   /* !!! This does not support modes < 0x13 !!! */
-#endif
-}
-
-/*********************************************/
-/*     HELPER: SET AGP TIMING FOR SiS760     */
-/*********************************************/
-
-static void
-SiS_Handle760(struct SiS_Private *SiS_Pr)
-{
-#ifdef CONFIG_FB_SIS_315
-   unsigned int somebase;
-   unsigned char temp1, temp2, temp3;
-
-   if( (SiS_Pr->ChipType != SIS_760)                         ||
-       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
-       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||
-       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
-      return;
-
-   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
-   somebase &= 0xffff;
-
-   if(somebase == 0) return;
-
-   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
-
-   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
-      temp1 = 0x21;
-      temp2 = 0x03;
-      temp3 |= 0x08;
-   } else {
-      temp1 = 0x25;
-      temp2 = 0x0b;
-   }
-
-   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
-   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
-
-   SiS_SetRegByte((somebase + 0x85), temp3);
-#endif
-}
-
-/*********************************************/
-/*                 SiSSetMode()              */
-/*********************************************/
-
-bool
-SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
-   unsigned short RealModeNo, ModeIdIndex;
-   unsigned char  backupreg = 0;
-   unsigned short KeepLockReg;
-
-   SiS_Pr->UseCustomMode = false;
-   SiS_Pr->CRT1UsesCustomMode = false;
-
-   SiS_Pr->SiS_flag_clearbuffer = 0;
-
-   if(SiS_Pr->UseCustomMode) {
-      ModeNo = 0xfe;
-   } else {
-      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
-      ModeNo &= 0x7f;
-   }
-
-   /* Don't use FSTN mode for CRT1 */
-   RealModeNo = ModeNo;
-   if(ModeNo == 0x5b) ModeNo = 0x56;
-
-   SiSInitPtr(SiS_Pr);
-   SiSRegInit(SiS_Pr, BaseAddr);
-   SiS_GetSysFlags(SiS_Pr);
-
-   SiS_Pr->SiS_VGAINFO = 0x11;
-
-   KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
-
-   SiSInitPCIetc(SiS_Pr);
-   SiSSetLVDSetc(SiS_Pr);
-   SiSDetermineROMUsage(SiS_Pr);
-
-   SiS_UnLockCRT2(SiS_Pr);
-
-   if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
-   } else {
-      ModeIdIndex = 0;
-   }
-
-   SiS_GetVBType(SiS_Pr);
-
-   /* Init/restore some VB registers */
-   SiS_InitVB(SiS_Pr);
-   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      if(SiS_Pr->ChipType >= SIS_315H) {
-         SiS_ResetVB(SiS_Pr);
-	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      } else {
-         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-      }
-   }
-
-   /* Get VB information (connectors, connected devices) */
-   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
-   SiS_SetYPbPr(SiS_Pr);
-   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
-   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
-   SiS_SetLowModeTest(SiS_Pr, ModeNo);
-
-   /* Check memory size (kernel framebuffer driver only) */
-   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
-      return false;
-   }
-
-   SiS_OpenCRTC(SiS_Pr);
-
-   if(SiS_Pr->UseCustomMode) {
-      SiS_Pr->CRT1UsesCustomMode = true;
-      SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
-      SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
-   } else {
-      SiS_Pr->CRT1UsesCustomMode = false;
-   }
-
-   /* Set mode on CRT1 */
-   if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
-       (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
-      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
-   }
-
-   /* Set mode on CRT2 */
-   if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
-      if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
-	  (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
-	  (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
-	  (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
-	 SiS_SetCRT2Group(SiS_Pr, RealModeNo);
-      }
-   }
-
-   SiS_HandleCRT1(SiS_Pr);
-
-   SiS_StrangeStuff(SiS_Pr);
-
-   SiS_DisplayOn(SiS_Pr);
-   SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
-
-#ifdef CONFIG_FB_SIS_315
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	 if(!(SiS_IsDualEdge(SiS_Pr))) {
-	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
-	 }
-      }
-   }
-#endif
-
-   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      if(SiS_Pr->ChipType >= SIS_315H) {
-#ifdef CONFIG_FB_SIS_315
-	 if(!SiS_Pr->SiS_ROMNew) {
-	    if(SiS_IsVAMode(SiS_Pr)) {
-	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-	    } else {
-	       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
-	    }
-	 }
-
-	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
-
-	 if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
-	    if((ModeNo == 0x03) || (ModeNo == 0x10)) {
-	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
-	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
-	    }
-	 }
-
-	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
-	 }
-#endif
-      } else if((SiS_Pr->ChipType == SIS_630) ||
-	        (SiS_Pr->ChipType == SIS_730)) {
-	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
-      }
-   }
-
-   SiS_CloseCRTC(SiS_Pr);
-
-   SiS_Handle760(SiS_Pr);
-
-   /* We never lock registers in XF86 */
-   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
-
-   return true;
-}
-
-#ifndef GETBITSTR
-#define GENBITSMASK(mask)   	GENMASK(1?mask,0?mask)
-#define GETBITS(var,mask)   	(((var) & GENBITSMASK(mask)) >> (0?mask))
-#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
-#endif
-
-void
-SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
-{
-   int x = 1; /* Fix sync */
-
-   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;		/* CR0 */
-   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;			/* CR1 */
-   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;			/* CR2 */
-   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;	/* CR3 */
-   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;			/* CR4 */
-   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |	/* CR5 */
-			    (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
-
-   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal       - 2) & 0xFF;			/* CR6 */
-   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal     - 2) & 0x100) >> 8)		/* CR7 */
-			  | (((SiS_Pr->CVDisplay   - 1) & 0x100) >> 7)
-			  | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
-			  | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
-			  | 0x10
-			  | (((SiS_Pr->CVTotal     - 2) & 0x200) >> 4)
-			  | (((SiS_Pr->CVDisplay   - 1) & 0x200) >> 3)
-			  | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
-
-   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* CR9 */
-
-   if(depth != 8) {
-      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;		/* SRE */
-      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
-   }
-
-   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart  - x) & 0xFF;			/* CR10 */
-   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd   - x) & 0x0F) | 0x80;		/* CR11 */
-   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;			/* CR12 */
-   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;			/* CR15 */
-   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;			/* CR16 */
-
-   SiS_Pr->CCRT1CRTC[13] =							/* SRA */
-			GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
-			GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
-			GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
-			GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
-			GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
-			GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
-
-   SiS_Pr->CCRT1CRTC[14] =							/* SRB */
-			GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
-			GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
-			GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
-			GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
-
-
-   SiS_Pr->CCRT1CRTC[15] =							/* SRC */
-			GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
-			GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
-}
-
-void
-SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex)
-{
-   unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
-   unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
-   int i, j;
-
-   /* 1:1 data: use data set by setcrt1crtc() */
-   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
-
-   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-
-   if(modeflag & HalfDCLK) VGAHDE >>= 1;
-
-   SiS_Pr->CHDisplay = VGAHDE;
-   SiS_Pr->CHBlankStart = VGAHDE;
-
-   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
-   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
-
-   if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-      tempbx = SiS_Pr->SiS_VGAHT;
-      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-         tempbx = SiS_Pr->PanelHT;
-      }
-      if(modeflag & HalfDCLK) tempbx >>= 1;
-      remaining = tempbx % 8;
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      /* OK for LCDA, LVDS */
-      tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
-      tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
-      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-         tempax = SiS_Pr->PanelXRes;
-      }
-      tempbx += tempax;
-      if(modeflag & HalfDCLK) tempbx -= VGAHDE;
-#endif
-   }
-   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
-
-   if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-      if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
-	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
-	 SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
-	 if(modeflag & HalfDCLK) {
-	    SiS_Pr->CHSyncStart >>= 1;
-	    SiS_Pr->CHSyncEnd >>= 1;
-	 }
-      } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	 tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
-	 tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
-	 if(modeflag & HalfDCLK) {
-	    tempax >>= 1;
-	    tempbx >>= 1;
-	 }
-	 SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
-	 tempax = SiS_Pr->PanelHRE + 7;
-	 if(modeflag & HalfDCLK) tempax >>= 1;
-	 SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
-      } else {
-	 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
-	 if(modeflag & HalfDCLK) {
-	    SiS_Pr->CHSyncStart >>= 1;
-	    tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
-	    SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
-	 } else {
-	    SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
-	    SiS_Pr->CHSyncStart += 8;
-	 }
-      }
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      tempax = VGAHDE;
-      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	 tempbx = SiS_Pr->PanelXRes;
-	 if(modeflag & HalfDCLK) tempbx >>= 1;
-	 tempax += ((tempbx - tempax) >> 1);
-      }
-      tempax += SiS_Pr->PanelHRS;
-      SiS_Pr->CHSyncStart = tempax;
-      tempax += SiS_Pr->PanelHRE;
-      SiS_Pr->CHSyncEnd = tempax;
-#endif
-   }
-
-   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
-   tempax = SiS_Pr->SiS_VGAVDE;
-   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-      tempax = SiS_Pr->PanelYRes;
-   } else if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-      /* Stupid hack for 640x400/320x200 */
-      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	 if((tempax + tempbx) == 438) tempbx += 16;
-      } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
-		(SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
-	 tempax = 0;
-	 tempbx = SiS_Pr->SiS_VGAVT;
-      }
-#endif
-   }
-   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
-
-   tempax = SiS_Pr->SiS_VGAVDE;
-   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
-   }
-   tempax += SiS_Pr->PanelVRS;
-   SiS_Pr->CVSyncStart = tempax;
-   tempax += SiS_Pr->PanelVRE;
-   SiS_Pr->CVSyncEnd = tempax;
-   if(SiS_Pr->ChipType < SIS_315H) {
-      SiS_Pr->CVSyncStart--;
-      SiS_Pr->CVSyncEnd--;
-   }
-
-   SiS_CalcCRRegisters(SiS_Pr, 8);
-   SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
-   SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
-   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
-
-   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-
-   for(i = 0, j = 0; i <= 7; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
-   }
-   for(j = 0x10; i <= 10; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
-   }
-   for(j = 0x15; i <= 12; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
-   }
-   for(j = 0x0A; i <= 15; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
-   }
-
-   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
-
-   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
-   if(modeflag & DoubleScanMode) tempax |= 0x80;
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
-
-}
-
-void
-SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
-			int xres, int yres,
-			struct fb_var_screeninfo *var, bool writeres
-)
-{
-   unsigned short HRE, HBE, HRS, HBS, HDE, HT;
-   unsigned short VRE, VBE, VRS, VBS, VDE, VT;
-   unsigned char  sr_data, cr_data, cr_data2;
-   int            A, B, C, D, E, F, temp;
-
-   sr_data = crdata[14];
-
-   /* Horizontal total */
-   HT =  crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
-   A = HT + 5;
-
-   /* Horizontal display enable end */
-   HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
-   E = HDE + 1;
-
-   /* Horizontal retrace (=sync) start */
-   HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
-   F = HRS - E - 3;
-
-   /* Horizontal blank start */
-   HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
-
-   sr_data = crdata[15];
-   cr_data = crdata[5];
-
-   /* Horizontal blank end */
-   HBE = (crdata[3] & 0x1f) |
-         ((unsigned short)(cr_data & 0x80) >> 2) |
-         ((unsigned short)(sr_data & 0x03) << 6);
-
-   /* Horizontal retrace (=sync) end */
-   HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
-
-   temp = HBE - ((E - 1) & 255);
-   B = (temp > 0) ? temp : (temp + 256);
-
-   temp = HRE - ((E + F + 3) & 63);
-   C = (temp > 0) ? temp : (temp + 64);
-
-   D = B - F - C;
-
-   if(writeres) var->xres = xres = E * 8;
-   var->left_margin = D * 8;
-   var->right_margin = F * 8;
-   var->hsync_len = C * 8;
-
-   /* Vertical */
-   sr_data = crdata[13];
-   cr_data = crdata[7];
-
-   /* Vertical total */
-   VT  = crdata[6] |
-	 ((unsigned short)(cr_data & 0x01) << 8) |
-	 ((unsigned short)(cr_data & 0x20) << 4) |
-	 ((unsigned short)(sr_data & 0x01) << 10);
-   A = VT + 2;
-
-   /* Vertical display enable end */
-   VDE = crdata[10] |
-	 ((unsigned short)(cr_data & 0x02) << 7) |
-	 ((unsigned short)(cr_data & 0x40) << 3) |
-	 ((unsigned short)(sr_data & 0x02) << 9);
-   E = VDE + 1;
-
-   /* Vertical retrace (=sync) start */
-   VRS = crdata[8] |
-	 ((unsigned short)(cr_data & 0x04) << 6) |
-	 ((unsigned short)(cr_data & 0x80) << 2) |
-	 ((unsigned short)(sr_data & 0x08) << 7);
-   F = VRS + 1 - E;
-
-   cr_data2 = (crdata[16] & 0x01) << 5;
-
-   /* Vertical blank start */
-   VBS = crdata[11] |
-	 ((unsigned short)(cr_data  & 0x08) << 5) |
-	 ((unsigned short)(cr_data2 & 0x20) << 4) |
-	 ((unsigned short)(sr_data  & 0x04) << 8);
-
-   /* Vertical blank end */
-   VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
-   temp = VBE - ((E - 1) & 511);
-   B = (temp > 0) ? temp : (temp + 512);
-
-   /* Vertical retrace (=sync) end */
-   VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
-   temp = VRE - ((E + F - 1) & 31);
-   C = (temp > 0) ? temp : (temp + 32);
-
-   D = B - F - C;
-
-   if(writeres) var->yres = yres = E;
-   var->upper_margin = D;
-   var->lower_margin = F;
-   var->vsync_len = C;
-
-   if((xres == 320) && ((yres == 200) || (yres == 240))) {
-	/* Terrible hack, but correct CRTC data for
-	 * these modes only produces a black screen...
-	 * (HRE is 0, leading into a too large C and
-	 * a negative D. The CRT controller does not
-	 * seem to like correcting HRE to 50)
-	 */
-      var->left_margin = (400 - 376);
-      var->right_margin = (328 - 320);
-      var->hsync_len = (376 - 328);
-
-   }
-
-}
-
-
-
-
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
deleted file mode 100644
index 85d6738b6c64..000000000000
--- a/drivers/video/sis/init.h
+++ /dev/null
@@ -1,1541 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * Data and prototypes for init.c
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-#ifndef _INIT_H_
-#define _INIT_H_
-
-#include "initdef.h"
-
-#include "vgatypes.h"
-#include "vstruct.h"
-#ifdef SIS_CP
-#undef SIS_CP
-#endif
-#include <linux/types.h>
-#include <asm/io.h>
-#include <linux/fb.h>
-#include "sis.h"
-#include <video/sisfb.h>
-
-/* Mode numbers */
-static const unsigned short ModeIndex_320x200[]      = {0x59, 0x41, 0x00, 0x4f};
-static const unsigned short ModeIndex_320x240[]      = {0x50, 0x56, 0x00, 0x53};
-static const unsigned short ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00};  /* FSTN */
-static const unsigned short ModeIndex_400x300[]      = {0x51, 0x57, 0x00, 0x54};
-static const unsigned short ModeIndex_512x384[]      = {0x52, 0x58, 0x00, 0x5c};
-static const unsigned short ModeIndex_640x400[]      = {0x2f, 0x5d, 0x00, 0x5e};
-static const unsigned short ModeIndex_640x480[]      = {0x2e, 0x44, 0x00, 0x62};
-static const unsigned short ModeIndex_720x480[]      = {0x31, 0x33, 0x00, 0x35};
-static const unsigned short ModeIndex_720x576[]      = {0x32, 0x34, 0x00, 0x36};
-static const unsigned short ModeIndex_768x576[]      = {0x5f, 0x60, 0x00, 0x61};
-static const unsigned short ModeIndex_800x480[]      = {0x70, 0x7a, 0x00, 0x76};
-static const unsigned short ModeIndex_800x600[]      = {0x30, 0x47, 0x00, 0x63};
-static const unsigned short ModeIndex_848x480[]      = {0x39, 0x3b, 0x00, 0x3e};
-static const unsigned short ModeIndex_856x480[]      = {0x3f, 0x42, 0x00, 0x45};
-static const unsigned short ModeIndex_960x540[]      = {0x1d, 0x1e, 0x00, 0x1f};  /* 315 series only */
-static const unsigned short ModeIndex_960x600[]      = {0x20, 0x21, 0x00, 0x22};  /* 315 series only */
-static const unsigned short ModeIndex_1024x768[]     = {0x38, 0x4a, 0x00, 0x64};
-static const unsigned short ModeIndex_1024x576[]     = {0x71, 0x74, 0x00, 0x77};
-static const unsigned short ModeIndex_1024x600[]     = {0x20, 0x21, 0x00, 0x22};  /* 300 series only */
-static const unsigned short ModeIndex_1280x1024[]    = {0x3a, 0x4d, 0x00, 0x65};
-static const unsigned short ModeIndex_1280x960[]     = {0x7c, 0x7d, 0x00, 0x7e};
-static const unsigned short ModeIndex_1152x768[]     = {0x23, 0x24, 0x00, 0x25};  /* 300 series only */
-static const unsigned short ModeIndex_1152x864[]     = {0x29, 0x2a, 0x00, 0x2b};
-static const unsigned short ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
-static const unsigned short ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
-static const unsigned short ModeIndex_1280x720[]     = {0x79, 0x75, 0x00, 0x78};
-static const unsigned short ModeIndex_1280x800[]     = {0x14, 0x15, 0x00, 0x16};
-static const unsigned short ModeIndex_1280x854[]     = {0x1a, 0x1b, 0x00, 0x1c};
-static const unsigned short ModeIndex_1360x768[]     = {0x48, 0x4b, 0x00, 0x4e};
-static const unsigned short ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72};  /* 300 series, BARCO only */
-static const unsigned short ModeIndex_1400x1050[]    = {0x26, 0x27, 0x00, 0x28};  /* 315 series only */
-static const unsigned short ModeIndex_1680x1050[]    = {0x17, 0x18, 0x00, 0x19};  /* 315 series only */
-static const unsigned short ModeIndex_1600x1200[]    = {0x3c, 0x3d, 0x00, 0x66};
-static const unsigned short ModeIndex_1920x1080[]    = {0x2c, 0x2d, 0x00, 0x73};  /* 315 series only */
-static const unsigned short ModeIndex_1920x1440[]    = {0x68, 0x69, 0x00, 0x6b};
-static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
-static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
-
-static const unsigned char SiS_MDA_DAC[] =
-{
-	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
-        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
-        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
-        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
-        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
-        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
-};
-
-static const unsigned char SiS_CGA_DAC[] =
-{
-        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
-        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
-        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
-        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
-        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
-        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
-        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
-        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
-};
-
-static const unsigned char SiS_EGA_DAC[] =
-{
-        0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
-        0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
-        0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
-        0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
-        0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
-        0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
-        0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
-        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
-};
-
-static const unsigned char SiS_VGA_DAC[] =
-{
-	0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
-	0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
-	0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
-	0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
-	0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
-	0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
-	0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
-	0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
-	0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
-	0x0B,0x0C,0x0D,0x0F,0x10
-};
-
-static const struct SiS_St SiS_SModeIDTable[] =
-{
-	{0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00,0x40},
-	{0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00,0x40},
-	{0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01,0x40},
-	{0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02,0x40},
-	{0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02,0x40},
-	{0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
-	{0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04,0x40},
-	{0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05,0x40},
-	{0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03,0x40},
-	{0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03,0x40},
-	{0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04,0x40},
-	{0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05,0x40},
-	{0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05,0x40},
-	{0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05,0x40},
-	{0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05,0x40},
-	{0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05,0x40},
-	{0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04,0x40},
-	{0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05,0x40},
-	{0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05,0x40},
-	{0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
-};
-
-static const struct SiS_StResInfo_S SiS_StResInfo[]=
-{
-	{ 640,400},
-	{ 640,350},
-	{ 720,400},
-	{ 720,350},
-	{ 640,480}
-};
-
-static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
-{
-	{  320, 200, 8, 8},   /* 0x00 */
-	{  320, 240, 8, 8},   /* 0x01 */
-	{  320, 400, 8, 8},   /* 0x02 */
-	{  400, 300, 8, 8},   /* 0x03 */
-	{  512, 384, 8, 8},   /* 0x04 */
-	{  640, 400, 8,16},   /* 0x05 */
-	{  640, 480, 8,16},   /* 0x06 */
-	{  800, 600, 8,16},   /* 0x07 */
-	{ 1024, 768, 8,16},   /* 0x08 */
-	{ 1280,1024, 8,16},   /* 0x09 */
-	{ 1600,1200, 8,16},   /* 0x0a */
-	{ 1920,1440, 8,16},   /* 0x0b */
-	{ 2048,1536, 8,16},   /* 0x0c */
-	{  720, 480, 8,16},   /* 0x0d */
-	{  720, 576, 8,16},   /* 0x0e */
-	{ 1280, 960, 8,16},   /* 0x0f */
-	{  800, 480, 8,16},   /* 0x10 */
-	{ 1024, 576, 8,16},   /* 0x11 */
-	{ 1280, 720, 8,16},   /* 0x12 */
-	{  856, 480, 8,16},   /* 0x13 */
-	{ 1280, 768, 8,16},   /* 0x14 */
-	{ 1400,1050, 8,16},   /* 0x15 */
-	{ 1152, 864, 8,16},   /* 0x16 */
-	{  848, 480, 8,16},   /* 0x17 */
-	{ 1360, 768, 8,16},   /* 0x18 */
-	{ 1024, 600, 8,16},   /* 0x19 */
-	{ 1152, 768, 8,16},   /* 0x1a */
-	{  768, 576, 8,16},   /* 0x1b */
-	{ 1360,1024, 8,16},   /* 0x1c */
-	{ 1680,1050, 8,16},   /* 0x1d */
-	{ 1280, 800, 8,16},   /* 0x1e */
-	{ 1920,1080, 8,16},   /* 0x1f */
-	{  960, 540, 8,16},   /* 0x20 */
-	{  960, 600, 8,16},   /* 0x21 */
-	{ 1280, 854, 8,16}    /* 0x22 */
-};
-
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-static const struct SiS_StandTable_S SiS_StandTable[]=
-{
-/* 0x00: MD_0_200 */
- {
-  0x28,0x18,0x08,0x0800,
-  {0x09,0x03,0x00,0x02},
-  0x63,
-  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x01: MD_1_200 */
- {
-  0x28,0x18,0x08,0x0800,
-  {0x09,0x03,0x00,0x02},
-  0x63,
-  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x02: MD_2_200 */
- {
-  0x50,0x18,0x08,0x1000,
-  {0x01,0x03,0x00,0x02},
-  0x63,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x03: MD_3_200 - mode 0x03 - 0 */
- {
-  0x50,0x18,0x08,0x1000,
-  {0x01,0x03,0x00,0x02},
-  0x63,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x04: MD_4 */
- {
-  0x28,0x18,0x08,0x4000,
-  {0x09,0x03,0x00,0x02},
-  0x63,
-  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,   /* 0x2c is 2b for 300 */
-   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
-   0xff},
-  {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x01,0x00,0x03,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
-   0xff}
- },
-/* 0x05: MD_5 */
- {
-  0x28,0x18,0x08,0x4000,
-  {0x09,0x03,0x00,0x02},
-  0x63,
-  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,   /* 0x2c is 2b for 300 */
-   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
-   0xff},
-  {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x01,0x00,0x03,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
-   0xff}
- },
-/* 0x06: MD_6 */
- {
-  0x50,0x18,0x08,0x4000,
-  {0x01,0x01,0x00,0x06},
-  0x63,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,   /* 55,81 is 54,80 for 300 */
-   0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
-   0xff},
-  {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
-   0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
-   0x01,0x00,0x01,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
-   0xff}
- },
-/* 0x07: MD_7 */
- {
-  0x50,0x18,0x0e,0x1000,
-  {0x00,0x03,0x00,0x03},
-  0xa6,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
-   0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
-   0xff},
-  {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
-   0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-   0x0e,0x00,0x0f,0x08},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
-   0xff}
- },
-/* 0x08: MDA_DAC */
- {
-  0x00,0x00,0x00,0x0000,
-  {0x00,0x00,0x00,0x15},
-  0x15,
-  {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
-   0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
-   0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
-   0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
-   0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
-   0x15,0x15,0x15,0x15},
-  {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
-   0x3f}
- },
-/* 0x09: CGA_DAC */
- {
-  0x00,0x10,0x04,0x0114,
-  {0x11,0x09,0x15,0x00},
-  0x10,
-  {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
-   0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
-   0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
-   0x04},
-  {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
-   0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
-   0x3e,0x2b,0x3b,0x2f},
-  {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
-   0x3f}
- },
-/* 0x0a: EGA_DAC */
- {
-  0x00,0x10,0x04,0x0114,
-  {0x11,0x05,0x15,0x20},
-  0x30,
-  {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
-   0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
-   0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
-   0x06},
-  {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
-   0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
-   0x1e,0x0b,0x1b,0x0f},
-  {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
-   0x3f}
- },
-/* 0x0b: VGA_DAC */
- {
-  0x00,0x10,0x04,0x0114,
-  {0x11,0x09,0x15,0x2a},
-  0x3a,
-  {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
-   0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
-   0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
-   0x1f},
-  {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
-   0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
-   0x1c,0x0e,0x11,0x15},
-  {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
-   0x04}
- },
-/* 0x0c */
- {
-  0x08,0x0c,0x10,0x0a08,
-  {0x0c,0x0e,0x10,0x0b},
-  0x0c,
-  {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
-   0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
-   0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
-   0x06},
-  {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
-   0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
-   0x00,0x00,0x00,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x00}
- },
-/* 0x0d: MD_D */
- {
-  0x28,0x18,0x08,0x2000,
-  {0x09,0x0f,0x00,0x06},
-  0x63,
-  {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,     /* 2c is 2b for 300 */
-   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x01,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
-   0xff}
- },
-/* 0x0e: MD_E */
- {
-  0x50,0x18,0x08,0x4000,
-  {0x01,0x0f,0x00,0x06},
-  0x63,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,     /* 55,81 is 54,80 for 300 */
-   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
-   0x01,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
-   0xff}
- },
-/* 0x0f: ExtVGATable - modes > 0x13 */
- {
-  0x00,0x00,0x00,0x0000,
-  {0x01,0x0f,0x00,0x0e},
-  0x23,
-  {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
-   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-   0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
-   0x01,0x00,0x00,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
-   0xff}
- },
-/* 0x10: ROM_SAVEPTR - totally different for 300 */
- {
-  0x9f,0x3b,0x00,0x00c0,
-  {0x00,0x00,0x00,0x00},
-  0x00,
-  {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f,
-   0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0,
-   0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x00,0x00,0x00,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x00}
- },
-/* 0x11: MD_F */
- {
-  0x50,0x18,0x0e,0x8000,
-  {0x01,0x0f,0x00,0x06},
-  0xa2,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,    /* 55,81 is 54,80 on 300 */
-   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,    /* 82,84 is 83,85 on 300 */
-   0xff},
-  {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
-   0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
-   0x0b,0x00,0x05,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
-   0xff}
- },
-/* 0x12: MD_10 */
- {
-  0x50,0x18,0x0e,0x8000,
-  {0x01,0x0f,0x00,0x06},
-  0xa3,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,    /* 55,81 is 54,80 on 300 */
-   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,    /* 82,84 is 83,85 on 300 */
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x01,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
-   0xff}
- },
-/* 0x13: MD_0_350 */
- {
-  0x28,0x18,0x0e,0x0800,
-  {0x09,0x03,0x00,0x02},
-  0xa3,
-  {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,    /* b1 is a0 on 300 */
-   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
-   0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x14: MD_1_350 */
- {
-  0x28,0x18,0x0e,0x0800,
-  {0x09,0x03,0x00,0x02},
-  0xa3,
-  {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
-   0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x15: MD_2_350 */
- {
-  0x50,0x18,0x0e,0x1000,
-  {0x01,0x03,0x00,0x02},
-  0xa3,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
-   0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x16: MD_3_350 - mode 0x03 - 1 */
- {
-  0x50,0x18,0x0e,0x1000,
-  {0x01,0x03,0x00,0x02},
-  0xa3,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
-   0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x08,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x17: MD_0_1_400 */
- {
-  0x28,0x18,0x10,0x0800,
-  {0x08,0x03,0x00,0x02},
-  0x67,
-  {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,    /* b1 is a0 on 300 */
-   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x0c,0x00,0x0f,0x08},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x18: MD_2_3_400 - mode 0x03 - 2 */
- {
-  0x50,0x18,0x10,0x1000,
-  {0x00,0x03,0x00,0x02},
-  0x67,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x0c,0x00,0x0f,0x08},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
-   0xff}
- },
-/* 0x19: MD_7_400 */
- {
-  0x50,0x18,0x10,0x1000,
-  {0x00,0x03,0x00,0x02},
-  0x66,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
-   0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
-   0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-   0x0e,0x00,0x0f,0x08},
-  {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
-   0xff}
- },
-/* 0x1a: MD_11 */
- {
-  0x50,0x1d,0x10,0xa000,
-  {0x01,0x0f,0x00,0x06},
-  0xe3,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,    /* 55,81 is 54,80 on 300 */
-   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-   0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3,    /* e9,8b is ea,8c on 300 */
-   0xff},
-  {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
-   0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
-   0x01,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
-   0xff}
- },
-/* 0x1b: ExtEGATable - Modes <= 0x02 */
- {
-  0x50,0x1d,0x10,0xa000,
-  {0x01,0x0f,0x00,0x06},
-  0xe3,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,    /* 55,81 is 54,80 on 300 */
-   0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
-   0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,    /* e9,8b is ea,8c on 300 */
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
-   0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
-   0x01,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
-   0xff}
- },
-/* 0x1c: MD_13 */
- {
-  0x28,0x18,0x08,0x2000,
-  {0x01,0x0f,0x00,0x0e},
-  0x63,
-  {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,    /* 55,81 is 54,80 on 300 */
-   0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
-   0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
-   0xff},
-  {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
-   0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
-   0x41,0x00,0x0f,0x00},
-  {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
-   0xff}
- }
-};
-#endif
-
-/**************************************************************/
-/* SIS VIDEO BRIDGE ----------------------------------------- */
-/**************************************************************/
-
-static const unsigned char SiS_SoftSetting  = 0x30;   /* RAM setting */
-
-static const unsigned char SiS_OutputSelect = 0x40;
-
-static const unsigned char SiS_NTSCTiming[] = {
-	0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
-	0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
-	0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
-	0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
-	0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
-	0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
-	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
-	0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
-};
-
-static const unsigned char SiS_PALTiming[] = {
-	0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
-	0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
-	0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
-	0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17,
-	0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02,
-	0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
-	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
-	0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
-};
-
-static const unsigned char SiS_HiTVExtTiming[] = {
-	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
-	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
-	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
-	0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
-	0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
-	0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
-	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
-	0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
-};
-
-static const unsigned char SiS_HiTVSt1Timing[] = {
-	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
-	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
-	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
-	0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
-	0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10,
-	0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40,
-	0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86,
-	0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
-};
-
-static const unsigned char SiS_HiTVSt2Timing[] = {
-	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
-	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
-	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
-	0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
-	0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
-	0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
-	0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
-	0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
-};
-
-#if 0
-static const unsigned char SiS_HiTVTextTiming[] = {
-	0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
-	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
-	0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
-	0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
-	0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
-	0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40,
-        0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96,
-	0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00
-};
-#endif
-
-static const unsigned char SiS_HiTVGroup3Data[] = {
-	0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
-	0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
-	0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
-	0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
-	0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
-	0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9,
-	0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75,
-	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
-};
-
-static const unsigned char SiS_HiTVGroup3Simu[] = {
-	0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
-	0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
-	0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
-	0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
-	0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
-	0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4,
-	0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
-	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
-};
-
-#if 0
-static const unsigned char SiS_HiTVGroup3Text[] = {
-	0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
-	0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
-	0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
-	0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
-	0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
-	0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca,
-	0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
-	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
-};
-#endif
-
-static const struct SiS_TVData SiS_StPALData[] =
-{
- {    1,   1, 864, 525,1270, 400, 100, 0, 760,    0,0xf4,0xff,0x1c,0x22},
- {    1,   1, 864, 525,1270, 350, 100, 0, 760,    0,0xf4,0xff,0x1c,0x22},
- {    1,   1, 864, 525,1270, 400,   0, 0, 720,    0,0xf1,0x04,0x1f,0x18},
- {    1,   1, 864, 525,1270, 350,   0, 0, 720,    0,0xf4,0x0b,0x1c,0x0a},
- {    1,   1, 864, 525,1270, 480,  50, 0, 760,    0,0xf4,0xff,0x1c,0x22},
- {    1,   1, 864, 525,1270, 600,  50, 0,   0,0x300,0xf4,0xff,0x1c,0x22}
-};
-
-static const struct SiS_TVData SiS_ExtPALData[] =
-{
- {   27,  10, 848, 448,1270, 530,  50, 0,  50,    0,0xf4,0xff,0x1c,0x22},  /* 640x400, 320x200 */
- {  108,  35, 848, 398,1270, 530,  50, 0,  50,    0,0xf4,0xff,0x1c,0x22},
- {   12,   5, 954, 448,1270, 530,  50, 0,  50,    0,0xf1,0x04,0x1f,0x18},
- {    9,   4, 960, 463,1644, 438,  50, 0,  50,    0,0xf4,0x0b,0x1c,0x0a},
- {    9,   4, 848, 528,1270, 530,   0, 0,  50,    0,0xf5,0xfb,0x1b,0x2a},  /* 640x480, 320x240 */
- {   36,  25,1060, 648,1270, 530, 438, 0, 438,    0,0xeb,0x05,0x25,0x16},  /* 800x600, 400x300 */
- {    3,   2,1080, 619,1270, 540, 438, 0, 438,    0,0xf3,0x00,0x1d,0x20},  /* 720x576 */
- {    1,   1,1170, 821,1270, 520, 686, 0, 686,    0,0xF3,0x00,0x1D,0x20},  /* 1024x768 */
- {    1,   1,1170, 821,1270, 520, 686, 0, 686,    0,0xF3,0x00,0x1D,0x20},  /* 1024x768 (for NTSC equ) */
- {    9,   4, 848, 528,1270, 530,   0, 0,  50,    0,0xf5,0xfb,0x1b,0x2a}   /* 720x480 */
-};
-
-static const struct SiS_TVData SiS_StNTSCData[] =
-{
- {    1,   1, 858, 525,1270, 400,  50, 0, 760,    0,0xf1,0x04,0x1f,0x18},
- {    1,   1, 858, 525,1270, 350,  50, 0, 640,    0,0xf1,0x04,0x1f,0x18},
- {    1,   1, 858, 525,1270, 400,   0, 0, 720,    0,0xf1,0x04,0x1f,0x18},
- {    1,   1, 858, 525,1270, 350,   0, 0, 720,    0,0xf4,0x0b,0x1c,0x0a},
- {    1,   1, 858, 525,1270, 480,   0, 0, 760,    0,0xf1,0x04,0x1f,0x18}
-};
-
-static const struct SiS_TVData SiS_ExtNTSCData[] =
-{
- {  143,  65, 858, 443,1270, 440, 171, 0, 171,    0,0xf1,0x04,0x1f,0x18},    /* 640x400, 320x200 */
- {   88,  35, 858, 393,1270, 440, 171, 0, 171,    0,0xf1,0x04,0x1f,0x18},
- {  143,  70, 924, 443,1270, 440,  92, 0,  92,    0,0xf1,0x04,0x1f,0x18},
- {  143,  70, 924, 393,1270, 440,  92, 0,  92,    0,0xf4,0x0b,0x1c,0x0a},
- {  143,  76, 836, 523,1270, 440, 224, 0,   0,    0,0xf1,0x05,0x1f,0x16},    /* 640x480, 320x240 */
- {  143, 120,1056, 643,1270, 440,   0, 1,   0,    0,0xf4,0x10,0x1c,0x00},    /* 800x600, 400x300  */
- {  143,  76, 836, 523,1270, 440,   0, 1,   0,    0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
- {    1,   1,1100, 811,1412, 440,   0, 1,   0,    0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
-#if 0  /* flimmert und ist unten abgeschnitten (NTSCHT, NTSC clock) */
- {   65,  64,1056, 791,1270, 480, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
-#endif
-#if 0
- {    1,   1,1100, 811,1412, 440,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
-#endif
-#if 0
- {    1,   1,1120, 821,1516, 420,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
-#endif
-#if 0
- {    1,   1, 938, 821,1516, 420,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
-#endif
-#if 0 /* zoom hin, unten abgeschnitten (NTSC2HT, NTSC1024 clock) */
- {    1,   1,1072, 791,1270, 480, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
-#endif
-#if 1 /* zu weit links (squeezed) (NTSC2HT, NTSC1024 clock) */
- {    1,   1,1100, 846,1270, 440, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
-#endif
-#if 0 /* zu weit links, rechts abgeschnitten (NTSC2HT, NTSC1024 clock) */
- {    1,   1,1100, 846,1412, 440, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
-#endif
-};
-
-static const struct SiS_TVData SiS_StHiTVData[] =  /* Slave + TVSimu */
-{
- {    1,   1, 0x37c,0x233,0x2b2,0x320,    0, 0, 0, 0, 0, 0, 0, 0},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
- {    1,   1, 0x37c,0x233,0x2b2,0x320,    0, 0, 0, 0, 0, 0, 0, 0},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
- {    1,   1, 0x37c,0x233,0x2b2,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
- {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x150, 1, 0, 0, 0, 0, 0, 0}
-};
-
-static const struct SiS_TVData SiS_St2HiTVData[] = /* Slave */
-{
- {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc, 	  0, 0, 0, 0, 0, 0, 0, 0},
- {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
- {    5,   2, 0x348,0x233,0x670,0x3c0,0x08d, 1, 0, 0, 0, 0, 0, 0},
- {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x17c, 1, 0, 0, 0, 0, 0, 0}
-};
-
-static const struct SiS_TVData SiS_ExtHiTVData[] =
-{ /* all ok */
- {    6,   1, 0x348,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
- {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
- {    6,   1, 0x348,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
- {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
- {    5,   1, 0x348,0x233,0x670,0x3c0,0x166, 1, 0, 0, 0, 0, 0, 0},  /* 640x480   */
- {   16,   5, 0x41a,0x2ab,0x670,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0},  /* 800x600   */
- {   25,  12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 1024x768  */
- {    5,   4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0},  /* 1280x1024 */
- {    4,   1, 0x41a,0x233,0x60c,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0},  /* 800x480   */
- {    5,   2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 1024x576  */
- {    8,   5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0},  /* 1280x720  */
- {    8,   3, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 960x600  */
-};
-
-static const struct SiS_TVData SiS_St525pData[] =
-{
- {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x1e0,    0, 0, 0x2f8, 0, 0, 0, 0, 0}
-};
-
-static const struct SiS_TVData SiS_St750pData[] =
-{
- {    1,   1, 0x672,0x2ee,0x500,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
- {    1,   1, 0x672,0x2ee,0x500,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
- {    1,   1, 0x672,0x2ee,0x500,0x190,    0, 0, 0x2d0, 0, 0, 0, 0, 0},
- {    1,   1, 0x672,0x2ee,0x500,0x15e,    0, 0, 0x2d0, 0, 0, 0, 0, 0},
- {    1,   1, 0x672,0x2ee,0x500,0x1e0,    0, 0, 0x2f8, 0, 0, 0, 0, 0}
-};
-
-static const struct SiS_TVData SiS_Ext750pData[] =
-{ /* all ok */
- {    3,  1,  935, 470, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},  /* 320x200/640x400 */
- {   24,  7,  935, 420, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
- {    3,  1,  935, 470, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
- {   24,  7,  935, 420, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
- {    2,  1, 1100, 590, 1130, 640,  50, 0, 0, 0, 0, 0, 0, 0},  /* 640x480 */
- {    3,  2, 1210, 690, 1130, 660,  50, 0, 0, 0, 0, 0, 0, 0},  /* 800x600 OK */
- {    2,  1, 1100, 562, 1130, 640,   0, 1, 0, 0, 0, 0, 0, 0},  /* 720x480 OK */
- {    1,  1, 1375, 878, 1130, 640, 638, 0, 0, 0, 0, 0, 0, 0},  /* 1024x768 OK */
- {    5,  3, 1100, 675, 1130, 640,   0, 1, 0, 0, 0, 0, 0, 0},  /* 720/768x576 OK */
- {   25, 24, 1496, 755, 1120, 680,  50, 0, 0, 0, 0, 0, 0, 0}   /* 1280x720 OK */
-};
-
-static const struct SiS_LCDData SiS_LCD1280x720Data[] =  /* 2.03.00 */
-{
-	{  44,   15,  864,  430, 1408,  806 }, /* 640x400 */
-	{ 128,   35,  792,  385, 1408,  806 },
-	{  44,   15,  864,  430, 1408,  806 },
-	{ 128,   35,  792,  385, 1408,  806 },
-	{  22,    9,  864,  516, 1408,  806 }, /* 640x480 */
-	{   8,    5, 1056,  655, 1408,  806 }, /* 800x600 */
-	{   0,    0,    0,    0,    0,    0 }, /* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 }, /* 1280x1024 */
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   1,    1, 1408,  806, 1408,  806 }  /* 1280x720 */
-};
-
-/* About 1280x768: For TMDS, Panel_1280x768 will only be set if
- * the panel is a Fujitsu 7911 (VL-17WDX8) (with clock 81, 1688x802)
- * Other TMDS panels of this resolution will be treated as custom.
- * For LVDS, we know another type (_2).
- * (Note: 1280x768_3 is now special for SiS301/NetVista
- */
-
-static const struct SiS_LCDData SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
-{
-	{  64,   21,  858,  434, 1408,  806 }, /* 640x400 */
-	{  32,    9,  858,  372, 1408,  806 },
-	{  64,   21,  858,  434, 1408,  806 },
-	{  32,    9,  858,  372, 1408,  806 },
-	{ 143,   68, 1024,  527, 1408,  806 }, /* 640x480 */
-	{  64,   51, 1364,  663, 1408,  806 }, /* 800x600 */
-	{  88,   81, 1296,  806, 1408,  806 }, /* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 },
-	{   1,    1, 1408,  806, 1408,  806 }, /* 1280x768 */
-	{   0,    0,    0,    0,    0,    0 },
-	{  16,   15, 1600,  750, 1600,  806 }  /* 1280x720 - from Ext */
-};
-
-static const struct SiS_LCDData SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
-{
-	{  16,    5,  960,  410, 1600,  806 }, /* 640x400 */
-	{  64,   21, 1152,  364, 1600,  806 },
-	{  16,    5,  960,  410, 1600,  806 },
-	{  64,   21, 1152,  364, 1600,  806 },
-	{  32,   13, 1040,  493, 1600,  806 }, /* 640x480 */
-	{  16,    9, 1152,  618, 1600,  806 }, /* 800x600 */
-	{  25,   21, 1344,  796, 1600,  806 }, /* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 },
-	{   1,    1, 1600,  806, 1600,  806 }, /* 1280x768 */
-	{   0,    0,    0,    0,    0,    0 },
-	{  16,   15, 1600,  750, 1600,  806 }  /* 1280x720 */
-};
-
-#if 0  /* Not used; _3 now reserved for NetVista (SiS301) */
-static const struct SiS_LCDData SiS_LCD1280x768_3Data[] =
-{
-	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
-	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
-	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
-	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
-	{  32,   15, 1056,  513, 1408,  806 }, /* ,664 */	/* 640x480 */
-	{ 176,  125, 1280,  640, 1408,  806 }, /* ,768 */	/* 800x600 */
-	{  64,   61, 1342,  806, 1408,  806 },			/* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 },
-	{   1,    1, 1408,  806, 1408,  806 },			/* 1280x768 */
-	{   0,    0,    0,    0,    0,    0 },
-	{  16,   15, 1600,  750, 1600,  806 }  /* 1280x720  from above */
-};
-#endif
-
-static const struct SiS_LCDData SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
-{
-	{ 128,   51, 1122,  412, 1408,  816 },  /* 640x400 */
-	{ 128,   49, 1232,  361, 1408,  816 },
-	{ 128,   51, 1122,  412, 1408,  816 },
-	{ 128,   49, 1232,  361, 1408,  816 },
-	{   8,    3,  880,  491, 1408,  816 },  /* 640x480 */
-	{  11,    6, 1024,  612, 1408,  816 },  /* 800x600 */
-	{  22,   21, 1400,  784, 1408,  816 },  /* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 },  /* 1280x1024 */
-	{   1,    1, 1408,  816, 1408,  816 },  /* 1280x800 */
-	{   0,    0,    0,    0,    0,    0 },  /* 1280x768 (patch index) */
-	{   0,    0,    0,    0,    0,    0 }   /* 1280x720 */
-};
-
-static const struct SiS_LCDData SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
-{
-	{  97,   42, 1344,  409, 1552,  812 }, /* 640x400 */
-	{  97,   35, 1280,  358, 1552,  812 },
-	{  97,   42, 1344,  409, 1552,  812 },
-	{  97,   35, 1280,  358, 1552,  812 },
-	{  97,   39, 1040,  488, 1552,  812 }, /* 640x480 */
-	{ 194,  105, 1120,  608, 1552,  812 }, /* 800x600 */
-	{  97,   84, 1400,  780, 1552,  812 }, /* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 }, /* 1280x1024 */
-	{   1,    1, 1552,  812, 1552,  812 }, /* 1280x800 */
-	{  97,   96, 1600,  780, 1552,  812 }, /* 1280x768 - patch index */
-	{  97,   90, 1600,  730, 1552,  812 }  /* 1280x720 */
-};
-
-#if 0
-static const struct SiS_LCDData SiS_LCD1280x800_3Data[] = /* 2.02.05a (LVDS); m250 */
-{
-	{ 128,   51, 1122,  412, 1408,  816 }, /* 640x400 */
-	{ 128,   49, 1232,  361, 1408,  816 },
-	{ 128,   51, 1122,  412, 1408,  816 },
-	{ 128,   49, 1232,  361, 1408,  816 },
-	{   8,    3,  880,  491, 1408,  816 }, /* 640x480 */
-	{  11,    6, 1024,  612, 1408,  816 }, /* 800x600 */
-	{  22,   21, 1400,  784, 1408,  816 }, /* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 }, /* 1280x1024 */
-	{   1,    1, 1408,  816, 1408,  816 }, /* 1280x800 */
-	{   0,    0,    0,    0,    0,    0 }, /* 1280x768 - patch index */
-	{   0,    0,    0,    0,    0,    0 }  /* 1280x720 */
-};
-#endif
-
-static const struct SiS_LCDData SiS_LCD1280x854Data[] = /* 2.21.00CS (LVDS) */
-{
-	{  56,   15,  936,  410, 1664,  861 },  /* 640x400 */
-	{  64,   25, 1586,  355, 1664,  861 },
-	{  56,   15,  936,  410, 1664,  861 },
-	{  64,   25, 1586,  355, 1664,  861 },
-	{  91,   45, 1464,  485, 1664,  861 },  /* 640x480 */
-	{ 182,   75,  976,  605, 1664,  861 },  /* 800x600 */
-	{  91,   66, 1342,  774, 1664,  861 },  /* 1024x768 */
-	{   0,    0,    0,    0,    0,    0 },  /* 1280x1024 */
-	{  26,   25, 1708,  807, 1664,  861 },  /* 1280x800 */
-	{  13,   12, 1708,  774, 1664,  861 },  /* 1280x768 - patch index */
-	{  52,   45, 1708,  725, 1664,  861 },  /* 1280x720 */
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   1,    1, 1664,  861, 1664,  861 }   /* 1280x854 */
-};
-
-static const struct SiS_LCDData SiS_LCD1280x960Data[] =
-{
-	{    9,   2,  800,  500, 1800, 1000 },
-	{    9,   2,  800,  500, 1800, 1000 },
-	{    4,   1,  900,  500, 1800, 1000 },
-	{    4,   1,  900,  500, 1800, 1000 },
-	{    9,   2,  800,  500, 1800, 1000 },
-	{   30,  11, 1056,  625, 1800, 1000 },
-	{    5,   3, 1350,  800, 1800, 1000 },
-	{    1,   1, 1576, 1050, 1576, 1050 },
-	{    1,   1, 1800, 1000, 1800, 1000 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 }
-};
-
-static const struct SiS_LCDData SiS_StLCD1400x1050Data[] =
-{
-	{ 211,  100, 2100,  408, 1688, 1066 },
-	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,  100, 2100,  408, 1688, 1066 },
-	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,   48,  840,  488, 1688, 1066 },
-	{ 211,   72, 1008,  609, 1688, 1066 },
-	{ 211,  128, 1400,  776, 1688, 1066 },
-	{ 211,  205, 1680, 1041, 1688, 1066 },
-	{   1,    1, 1688, 1066, 1688, 1066 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 }
-};
-
-static const struct SiS_LCDData SiS_ExtLCD1400x1050Data[] =
-{
-/*	{ 211,   60, 1260,  410, 1688, 1066 },    640x400 (6330) */
-	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 (6325) WORKS */
-	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,  100, 2100,  408, 1688, 1066 },
-	{ 211,   64, 1536,  358, 1688, 1066 },
-/*	{ 211,   80, 1400,  490, 1688, 1066 },    640x480 (6330) */
-	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 (6325) WORKS */
-/*	{ 211,  117, 1638,  613, 1688, 1066 },    800x600 (6330) */
-	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 (6325) WORKS */
-	{ 211,  128, 1400,  776, 1688, 1066 }, /* 1024x768 */
-	{ 211,  205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
-	{   1,    1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
-	{   0,    0,    0,    0,    0,    0 }, /* kludge */
-	{ 211,  120, 1400,  730, 1688, 1066 }, /* 1280x720 */
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 },
-	{   0,    0,    0,    0,    0,    0 }
-};
-
-static const struct SiS_LCDData SiS_LCD1680x1050Data[] =
-{
-	{  95,   24, 1260,  410, 1900, 1066 }, /*  0 640x400 */
-	{  10,    3, 1710,  362, 1900, 1066 },
-	{  95,   24, 1260,  410, 1900, 1066 },
-	{  10,    3, 1710,  362, 1900, 1066 },
-	{  95,   32, 1400,  490, 1900, 1066 }, /*  4 640x480 */
-	{  95,   42, 1470,  610, 1900, 1066 }, /*  5 800x600 */
-	{  95,   64, 1750,  784, 1900, 1066 }, /*  6 1024x768 */
-	{  95,   94, 1900, 1055, 1900, 1066 }, /*  7 1280x1024 */
-	{  41,   31, 1900,  806, 1900, 1066 }, /*  8 1280x768 */
-	{  95,   69, 1800,  817, 1900, 1066 }, /*  9 1280x800 patch index */
-	{  13,    9, 1900,  739, 1900, 1066 }, /* 10 1280x720 */
-	{  95,   94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch index */
-	{   1,    1, 1900, 1066, 1900, 1066 }, /* 12 1680x1050 */
-	{   0,    0,    0,    0,    0,    0 }
-};
-
-static const struct SiS_LCDData SiS_StLCD1600x1200Data[] =
-{
-	{27,  4, 800, 500, 2160, 1250 },
-	{27,  4, 800, 500, 2160, 1250 },
-	{ 6,  1, 900, 500, 2160, 1250 },
-	{ 6,  1, 900, 500, 2160, 1250 },
-	{27,  1, 800, 500, 2160, 1250 },
-	{ 4,  1,1080, 625, 2160, 1250 },
-	{ 5,  2,1350, 800, 2160, 1250 },
-	{135,88,1600,1100, 2160, 1250 },
-	{72, 49,1680,1092, 2160, 1250 },
-	{ 1,  1,2160,1250, 2160, 1250 },
-	{ 0,  0,   0,   0,    0,    0 },
-	{ 0,  0,   0,   0,    0,    0 },
-	{ 0,  0,   0,   0,    0,    0 },
-	{ 0,  0,   0,   0,    0,    0 }
-};
-
-static const struct SiS_LCDData SiS_ExtLCD1600x1200Data[] =
-{
-	{72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) WORKS */
-/*	{27, 4, 800, 500, 2160, 1250 },    640x400 (6235) */
-	{27, 4, 800, 500, 2160, 1250 },
-	{ 6, 1, 900, 500, 2160, 1250 },
-	{ 6, 1, 900, 500, 2160, 1250 },
-	{45, 8, 960, 505, 2160, 1250 }, /* 640x480 (6330) WORKS */
-/*	{27, 1, 800, 500, 2160, 1250 },    640x480 (6325) */
-	{ 4, 1,1080, 625, 2160, 1250 },
-	{ 5, 2,1350, 800, 2160, 1250 },
-	{27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
-	{72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
-	{ 1, 1,2160,1250, 2160, 1250 },
-	{ 0, 0,   0,   0,    0,    0 },
-	{ 0, 0,   0,   0,    0,    0 },
-	{ 0, 0,   0,   0,    0,    0 },
-	{ 0, 0,   0,   0,    0,    0 }
-};
-
-static const struct SiS_LCDData SiS_NoScaleData[] =
-{
-	{ 1, 1, 800, 449, 800, 449 },  /* 0x00: 320x200, 640x400 */
-	{ 1, 1, 800, 449, 800, 449 },
-	{ 1, 1, 900, 449, 900, 449 },
-	{ 1, 1, 900, 449, 900, 449 },
-	{ 1, 1, 800, 525, 800, 525 },  /* 0x04: 320x240, 640x480  */
-	{ 1, 1,1056, 628,1056, 628 },  /* 0x05: 400x300, 800x600  */
-	{ 1, 1,1344, 806,1344, 806 },  /* 0x06: 512x384, 1024x768 */
-	{ 1, 1,1688,1066,1688,1066 },  /* 0x07: 1280x1024 */
-        { 1, 1,1688, 802,1688, 802 },  /* 0x08: 1280x768: Fujitsu, TMDS only */
-        { 1, 1,2160,1250,2160,1250 },  /* 0x09: 1600x1200 */
-	{ 1, 1,1800,1000,1800,1000 },  /* 0x0a: 1280x960  */
-	{ 1, 1,1688,1066,1688,1066 },  /* 0x0b: 1400x1050 */
-	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS, projector)  */
-	{ 1, 1,1552, 812,1552, 812 },  /* 0x0d: 1280x800_2 (LVDS) (was: 1408,816/ 1656,841) */
-	{ 1, 1,1900,1066,1900,1066 },  /* 0x0e: 1680x1050 (LVDS) */
-	{ 1, 1,1660, 806,1660, 806 },  /* 0x0f: 1280x768_2 (LVDS) */
-	{ 1, 1,1664, 798,1664, 798 },  /* 0x10: 1280x768_3 (NetVista SiS 301) - TODO */
-	{ 1, 1,1688, 802,1688, 802 },  /* 0x11: 1280x768   (TMDS Fujitsu) */
-	{ 1, 1,1408, 806,1408, 806 },  /* 0x12: 1280x720 (LVDS) */
-	{ 1, 1, 896, 497, 896, 497 },  /* 0x13: 720x480 */
-	{ 1, 1, 912, 597, 912, 597 },  /* 0x14: 720x576 */
-	{ 1, 1, 912, 597, 912, 597 },  /* 0x15: 768x576 */
-	{ 1, 1,1056, 497,1056, 497 },  /* 0x16: 848x480 */
-	{ 1, 1,1064, 497,1064, 497 },  /* 0x17: 856x480 */
-	{ 1, 1,1056, 497,1056, 497 },  /* 0x18: 800x480 */
-	{ 1, 1,1328, 739,1328, 739 },  /* 0x19: 1024x576 */
-	{ 1, 1,1680, 892,1680, 892 },  /* 0x1a: 1152x864 */
-	{ 1, 1,1808, 808,1808, 808 },  /* 0x1b: 1360x768 */
-	{ 1, 1,1104, 563,1104, 563 },  /* 0x1c: 960x540 */
-	{ 1, 1,1120, 618,1120, 618 },  /* 0x1d: 960x600 */
-	{ 1, 1,1408, 816,1408, 816 },  /* 0x1f: 1280x800 (TMDS special) */
-	{ 1, 1,1760,1235,1760,1235 },  /* 0x20: 1600x1200 for LCDA */
-	{ 1, 1,2048,1320,2048,1320 },  /* 0x21: 1600x1200 for non-SiS LVDS */
-	{ 1, 1,1664, 861,1664, 861 }   /* 0x22: 1280x854 */
-};
-
-/**************************************************************/
-/* LVDS ----------------------------------------------------- */
-/**************************************************************/
-
-/* FSTN/DSTN 320x240, 2 variants */
-static const struct SiS_LVDSData SiS_LVDS320x240Data_1[]=
-{
-	{ 848, 433, 400, 525},
-	{ 848, 389, 400, 525},
-	{ 848, 433, 400, 525},
-	{ 848, 389, 400, 525},
-	{ 848, 518, 400, 525},
-	{1056, 628, 400, 525},
-	{ 400, 525, 400, 525}  /* xSTN */
-};
-
-static const struct SiS_LVDSData SiS_LVDS320x240Data_2[]=
-{
-	{ 800, 445, 800, 525},
-	{ 800, 395, 800, 525},
-	{ 800, 445, 800, 525},
-	{ 800, 395, 800, 525},
-	{ 800, 525, 800, 525},
-	{1056, 628,1056, 628},
-	{ 480, 525, 480, 525} /* xSTN */
-};
-
-static const struct SiS_LVDSData SiS_LVDS640x480Data_1[]=
-{
-	{ 800, 445, 800, 525},   /* 800, 449, 800, 449 */
-	{ 800, 395, 800, 525},
-	{ 800, 445, 800, 525},
-	{ 800, 395, 800, 525},
-	{ 800, 525, 800, 525}
-};
-
-static const struct SiS_LVDSData SiS_LVDS800x600Data_1[]=
-{
-	{ 848, 433,1060, 629},
-	{ 848, 389,1060, 629},
-	{ 848, 433,1060, 629},
-	{ 848, 389,1060, 629},
-	{ 848, 518,1060, 629},
-	{1056, 628,1056, 628}
-};
-
-static const struct SiS_LVDSData SiS_LVDS1024x600Data_1[] =
-{
-	{ 840, 604,1344, 800},
-	{ 840, 560,1344, 800},
-	{ 840, 604,1344, 800},
-	{ 840, 560,1344, 800},
-	{ 840, 689,1344, 800},
-	{1050, 800,1344, 800},
-	{1344, 800,1344, 800}
-};
-
-static const struct SiS_LVDSData SiS_LVDS1024x768Data_1[]=
-{
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 518,1344, 806},   /* 640x480 */
-	{1050, 638,1344, 806},   /* 800x600 */
-	{1344, 806,1344, 806},   /* 1024x768 */
-};
-
-static const struct SiS_LVDSData SiS_CHTVUNTSCData[]=
-{
-	{ 840, 600, 840, 600},
-	{ 840, 600, 840, 600},
-	{ 840, 600, 840, 600},
-	{ 840, 600, 840, 600},
-	{ 784, 600, 784, 600},
-	{1064, 750,1064, 750},
-        {1160, 945,1160, 945}
-};
-
-static const struct SiS_LVDSData SiS_CHTVONTSCData[]=
-{
-	{ 840, 525, 840, 525},
-	{ 840, 525, 840, 525},
-	{ 840, 525, 840, 525},
-	{ 840, 525, 840, 525},
-	{ 784, 525, 784, 525},
-	{1040, 700,1040, 700},
-        {1160, 840,1160, 840}
-};
-
-/* CRT1 CRTC data for slave modes */
-
-static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_1[] =
-{
- {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
-   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-   0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00 }},
- {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-   0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00 }},
- {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
-   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
-   0x00 }},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01 }},
- {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00 }}
-};
-
-static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
-#if 0
- {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}
-#endif
- {{0x5f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xe8,0x0c,0x00,0x00,0x05,
-   0x00}},
-};
-
-static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2_H[] =
-{
- {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
-   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-   0x00}},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00}},
- {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-   0x00}},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00}},
- {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
-   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}
-};
-
-static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}
-};
-
-static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3_H[] =
-{
- {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
-   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-   0x00}},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00}},
- {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-   0x00}},
- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00}},
- {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
-   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}
-};
-
-static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}}
-};
-
-static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
-{
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}
-};
-
-bool		SiSInitPtr(struct SiS_Private *SiS_Pr);
-unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, bool FSTN,
-				unsigned short CustomT, int LCDwith, int LCDheight,
-				unsigned int VBFlags2);
-unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, unsigned int VBFlags2);
-unsigned short	SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, unsigned int VBFlags2);
-
-void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
-void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
-void		SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-void		SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
-void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
-unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
-
-bool		SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
-				unsigned short *ModeIdIndex);
-unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-unsigned short  SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
-unsigned short  SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
-unsigned short	SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-unsigned short	SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
-				unsigned short ModeIdIndex, unsigned short RRTI);
-#ifdef CONFIG_FB_SIS_300
-void		SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
-				unsigned short *idx2);
-unsigned short	SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
-unsigned short	SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
-#endif
-void		SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
-bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
-void		SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
-void		SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-void		SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
-				int yres, struct fb_var_screeninfo *var, bool writeres);
-
-/* From init301.c: */
-extern void		SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex, int chkcrt2mode);
-extern void		SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-extern void		SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
-extern void		SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-extern void		SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
-extern void		SiS_DisableBridge(struct SiS_Private *);
-extern bool		SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
-extern unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-extern void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
-extern unsigned short	SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-extern unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
-extern unsigned short	SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex, unsigned short RRTI);
-extern bool		SiS_IsVAMode(struct SiS_Private *);
-extern bool		SiS_IsDualEdge(struct SiS_Private *);
-
-#ifdef CONFIG_FB_SIS_300
-extern unsigned int	sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-extern void		sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
-				unsigned int val);
-#endif
-#ifdef CONFIG_FB_SIS_315
-extern void		sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
-				unsigned char val);
-extern unsigned int	sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
-#endif
-
-#endif
-
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
deleted file mode 100644
index a89e3cafd5ad..000000000000
--- a/drivers/video/sis/init301.c
+++ /dev/null
@@ -1,11071 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * Mode initializing code (CRT2 section)
- * for SiS 300/305/540/630/730,
- *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
- *     XGI V3XT/V5/V8, Z7
- * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
- * Used by permission.
- *
- */
-
-#if 1
-#define SET_EMI		/* 302LV/ELV: Set EMI values */
-#endif
-
-#if 1
-#define SET_PWD		/* 301/302LV: Set PWD */
-#endif
-
-#define COMPAL_HACK	/* Needed for Compal 1400x1050 (EMI) */
-#define COMPAQ_HACK	/* Needed for Inventec/Compaq 1280x1024 (EMI) */
-#define ASUS_HACK	/* Needed for Asus A2H 1024x768 (EMI) */
-
-#include "init301.h"
-
-#ifdef CONFIG_FB_SIS_300
-#include "oem300.h"
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-#include "oem310.h"
-#endif
-
-#define SiS_I2CDELAY      1000
-#define SiS_I2CDELAYSHORT  150
-
-static unsigned short	SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
-static void		SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-
-/*********************************************/
-/*         HELPER: Lock/Unlock CRT2          */
-/*********************************************/
-
-void
-SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType == XGI_20)
-      return;
-   else if(SiS_Pr->ChipType >= SIS_315H)
-      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
-   else
-      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
-}
-
-static
-void
-SiS_LockCRT2(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType == XGI_20)
-      return;
-   else if(SiS_Pr->ChipType >= SIS_315H)
-      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
-   else
-      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
-}
-
-/*********************************************/
-/*            HELPER: Write SR11             */
-/*********************************************/
-
-static void
-SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
-{
-   if(SiS_Pr->ChipType >= SIS_661) {
-      DataAND &= 0x0f;
-      DataOR  &= 0x0f;
-   }
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
-}
-
-/*********************************************/
-/*    HELPER: Get Pointer to LCD structure   */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_315
-static unsigned char *
-GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned char  *myptr = NULL;
-   unsigned short romindex = 0, reg = 0, idx = 0;
-
-   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
-    * due to the variaty of panels the BIOS doesn't know about.
-    * Exception: If the BIOS has better knowledge (such as in case
-    * of machines with a 301C and a panel that does not support DDC)
-    * use the BIOS data as well.
-    */
-
-   if((SiS_Pr->SiS_ROMNew) &&
-      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
-
-      if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
-      else                           reg = 0x7d;
-
-      idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
-
-      if(idx < (8*26)) {
-         myptr = (unsigned char *)&SiS_LCDStruct661[idx];
-      }
-      romindex = SISGETROMW(0x100);
-      if(romindex) {
-         romindex += idx;
-         myptr = &ROMAddr[romindex];
-      }
-   }
-   return myptr;
-}
-
-static unsigned short
-GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short romptr = 0;
-
-   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
-    * due to the variaty of panels the BIOS doesn't know about.
-    * Exception: If the BIOS has better knowledge (such as in case
-    * of machines with a 301C and a panel that does not support DDC)
-    * use the BIOS data as well.
-    */
-
-   if((SiS_Pr->SiS_ROMNew) &&
-      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
-      romptr = SISGETROMW(0x102);
-      romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
-   }
-
-   return romptr;
-}
-#endif
-
-/*********************************************/
-/*           Adjust Rate for CRT2            */
-/*********************************************/
-
-static bool
-SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RRTI, unsigned short *i)
-{
-   unsigned short checkmask=0, modeid, infoflag;
-
-   modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-
-	 checkmask |= SupportRAMDAC2;
-	 if(SiS_Pr->ChipType >= SIS_315H) {
-	    checkmask |= SupportRAMDAC2_135;
-	    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	       checkmask |= SupportRAMDAC2_162;
-	       if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
-		  checkmask |= SupportRAMDAC2_202;
-	       }
-	    }
-	 }
-
-      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-
-	 checkmask |= SupportLCD;
-	 if(SiS_Pr->ChipType >= SIS_315H) {
-	    if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	       if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-	          if(modeid == 0x2e) checkmask |= Support64048060Hz;
-	       }
-	    }
-	 }
-
-      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-
-	 checkmask |= SupportHiVision;
-
-      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
-
-	 checkmask |= SupportTV;
-	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	    checkmask |= SupportTV1024;
-	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
-	          checkmask |= SupportYPbPr750p;
-	       }
-	    }
-	 }
-
-      }
-
-   } else {	/* LVDS */
-
-      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	    checkmask |= SupportCHTV;
-	 }
-      }
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	 checkmask |= SupportLCD;
-      }
-
-   }
-
-   /* Look backwards in table for matching CRT2 mode */
-   for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
-      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-      if(infoflag & checkmask) return true;
-      if((*i) == 0) break;
-   }
-
-   /* Look through the whole mode-section of the table from the beginning
-    * for a matching CRT2 mode if no mode was found yet.
-    */
-   for((*i) = 0; ; (*i)++) {
-      if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
-      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-      if(infoflag & checkmask) return true;
-   }
-   return false;
-}
-
-/*********************************************/
-/*              Get rate index               */
-/*********************************************/
-
-unsigned short
-SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned short RRTI,i,backup_i;
-   unsigned short modeflag,index,temp,backupindex;
-   static const unsigned short LCDRefreshIndex[] = {
-		0x00, 0x00, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01,
-		0x01, 0x01, 0x01, 0x01,
-		0x00, 0x00, 0x00, 0x00
-   };
-
-   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
-   if(ModeNo == 0xfe) return 0;
-
-   if(ModeNo <= 0x13) {
-      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-   } else {
-      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-   }
-
-   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	 if(modeflag & HalfDCLK) return 0;
-      }
-   }
-
-   if(ModeNo < 0x14) return 0xFFFF;
-
-   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
-   backupindex = index;
-
-   if(index > 0) index--;
-
-   if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
-      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	    if(SiS_Pr->SiS_VBType & VB_NoLCD)		 index = 0;
-	    else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
-	 }
-	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-	    if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
-	       temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
-	       if(index > temp) index = temp;
-	    }
-	 }
-      } else {
-	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
-	 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
-	 }
-      }
-   }
-
-   RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-   ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
-	 if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
-	     (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
-	    if(backupindex <= 1) RRTI++;
-	 }
-      }
-   }
-
-   i = 0;
-   do {
-      if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
-      temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
-      temp &= ModeTypeMask;
-      if(temp < SiS_Pr->SiS_ModeType) break;
-      i++;
-      index--;
-   } while(index != 0xFFFF);
-
-   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	 temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
-	 if(temp & InterlaceMode) i++;
-      }
-   }
-
-   i--;
-
-   if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
-      backup_i = i;
-      if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
-	 i = backup_i;
-      }
-   }
-
-   return (RRTI + i);
-}
-
-/*********************************************/
-/*            STORE CRT2 INFO in CR34        */
-/*********************************************/
-
-static void
-SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-   unsigned short temp1, temp2;
-
-   /* Store CRT1 ModeNo in CR34 */
-   SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
-   temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
-   temp2 = ~(SetInSlaveMode >> 8);
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
-}
-
-/*********************************************/
-/*    HELPER: GET SOME DATA FROM BIOS ROM    */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_300
-static bool
-SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short temp,temp1;
-
-   if(SiS_Pr->SiS_UseROM) {
-      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
-	 temp1 = SISGETROMW(0x23b);
-	 if(temp1 & temp) return true;
-      }
-   }
-   return false;
-}
-
-static bool
-SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short temp,temp1;
-
-   if(SiS_Pr->SiS_UseROM) {
-      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
-	 temp1 = SISGETROMW(0x23d);
-	 if(temp1 & temp) return true;
-      }
-   }
-   return false;
-}
-#endif
-
-/*********************************************/
-/*          HELPER: DELAY FUNCTIONS          */
-/*********************************************/
-
-void
-SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
-{
-   while (delaytime-- > 0)
-      SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
-}
-
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-static void
-SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
-{
-   SiS_DDC2Delay(SiS_Pr, delay * 36);
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static void
-SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
-{
-   while(delay--) {
-      SiS_GenericDelay(SiS_Pr, 6623);
-   }
-}
-#endif
-
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-static void
-SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
-{
-   while(delay--) {
-      SiS_GenericDelay(SiS_Pr, 66);
-   }
-}
-#endif
-
-static void
-SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
-{
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short PanelID, DelayIndex, Delay=0;
-#endif
-
-   if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300
-
-      PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
-      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	 if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
-	 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
-      }
-      DelayIndex = PanelID >> 4;
-      if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
-	 Delay = 3;
-      } else {
-	 if(DelayTime >= 2) DelayTime -= 2;
-	 if(!(DelayTime & 0x01)) {
-	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
-	 } else {
-	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
-	 }
-	 if(SiS_Pr->SiS_UseROM) {
-	    if(ROMAddr[0x220] & 0x40) {
-	       if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
-	       else 	    	       Delay = (unsigned short)ROMAddr[0x226];
-	    }
-	 }
-      }
-      SiS_ShortDelay(SiS_Pr, Delay);
-
-#endif  /* CONFIG_FB_SIS_300 */
-
-   } else {
-
-#ifdef CONFIG_FB_SIS_315
-
-      if((SiS_Pr->ChipType >= SIS_661)    ||
-	 (SiS_Pr->ChipType <= SIS_315PRO) ||
-	 (SiS_Pr->ChipType == SIS_330)    ||
-	 (SiS_Pr->SiS_ROMNew)) {
-
-	 if(!(DelayTime & 0x01)) {
-	    SiS_DDC2Delay(SiS_Pr, 0x1000);
-	 } else {
-	    SiS_DDC2Delay(SiS_Pr, 0x4000);
-	 }
-
-      } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
-	 (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {			/* 315 series, LVDS; Special */
-
-	 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	    PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
-	    if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
-	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
-	    }
-	    if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	       DelayIndex = PanelID & 0x0f;
-	    } else {
-	       DelayIndex = PanelID >> 4;
-	    }
-	    if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
-	       Delay = 3;
-	    } else {
-	       if(DelayTime >= 2) DelayTime -= 2;
-	       if(!(DelayTime & 0x01)) {
-		  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
-		} else {
-		  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
-	       }
-	       if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-		  if(ROMAddr[0x13c] & 0x40) {
-		     if(!(DelayTime & 0x01)) {
-			Delay = (unsigned short)ROMAddr[0x17e];
-		     } else {
-			Delay = (unsigned short)ROMAddr[0x17f];
-		     }
-		  }
-	       }
-	    }
-	    SiS_ShortDelay(SiS_Pr, Delay);
-	 }
-
-      } else if(SiS_Pr->SiS_VBType & VB_SISVB) {			/* 315 series, all bridges */
-
-	 DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
-	 if(!(DelayTime & 0x01)) {
-	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
-	 } else {
-	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
-	 }
-	 Delay <<= 8;
-	 SiS_DDC2Delay(SiS_Pr, Delay);
-
-      }
-
-#endif /* CONFIG_FB_SIS_315 */
-
-   }
-}
-
-#ifdef CONFIG_FB_SIS_315
-static void
-SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
-{
-   int i;
-   for(i = 0; i < DelayLoop; i++) {
-      SiS_PanelDelay(SiS_Pr, DelayTime);
-   }
-}
-#endif
-
-/*********************************************/
-/*    HELPER: WAIT-FOR-RETRACE FUNCTIONS     */
-/*********************************************/
-
-void
-SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
-{
-   unsigned short watchdog;
-
-   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
-   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
-
-   watchdog = 65535;
-   while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
-   watchdog = 65535;
-   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
-}
-
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-static void
-SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
-{
-   unsigned short watchdog;
-
-   watchdog = 65535;
-   while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
-   watchdog = 65535;
-   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
-}
-#endif
-
-static void
-SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
-      }
-      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
-	 SiS_WaitRetrace1(SiS_Pr);
-      } else {
-	 SiS_WaitRetrace2(SiS_Pr, 0x25);
-      }
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
-	 SiS_WaitRetrace1(SiS_Pr);
-      } else {
-	 SiS_WaitRetrace2(SiS_Pr, 0x30);
-      }
-#endif
-   }
-}
-
-static void
-SiS_VBWait(struct SiS_Private *SiS_Pr)
-{
-   unsigned short tempal,temp,i,j;
-
-   temp = 0;
-   for(i = 0; i < 3; i++) {
-     for(j = 0; j < 100; j++) {
-        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
-        if(temp & 0x01) {
-	   if((tempal & 0x08))  continue;
-	   else break;
-        } else {
-	   if(!(tempal & 0x08)) continue;
-	   else break;
-        }
-     }
-     temp ^= 0x01;
-   }
-}
-
-static void
-SiS_VBLongWait(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-      SiS_VBWait(SiS_Pr);
-   } else {
-      SiS_WaitRetrace1(SiS_Pr);
-   }
-}
-
-/*********************************************/
-/*               HELPER: MISC                */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_300
-static bool
-SiS_Is301B(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
-   return false;
-}
-#endif
-
-static bool
-SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType == SIS_730) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
-   }
-   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
-   return false;
-}
-
-bool
-SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
-{
-#ifdef CONFIG_FB_SIS_315
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
-	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
-      }
-   }
-#endif
-   return false;
-}
-
-bool
-SiS_IsVAMode(struct SiS_Private *SiS_Pr)
-{
-#ifdef CONFIG_FB_SIS_315
-   unsigned short flag;
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
-   }
-#endif
-   return false;
-}
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_IsVAMode(SiS_Pr))  return true;
-   if(SiS_CRT2IsLCD(SiS_Pr)) return true;
-   return false;
-}
-#endif
-
-static bool
-SiS_IsDualLink(struct SiS_Private *SiS_Pr)
-{
-#ifdef CONFIG_FB_SIS_315
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if((SiS_CRT2IsLCD(SiS_Pr)) ||
-         (SiS_IsVAMode(SiS_Pr))) {
-	 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
-      }
-   }
-#endif
-   return false;
-}
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_TVEnabled(struct SiS_Private *SiS_Pr)
-{
-   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
-   if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
-      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
-   }
-   return false;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
-   return false;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
-{
-   if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
-   }
-   return false;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag;
-
-   if(SiS_Pr->ChipType == SIS_650) {
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
-      /* Check for revision != A0 only */
-      if((flag == 0xe0) || (flag == 0xc0) ||
-         (flag == 0xb0) || (flag == 0x90)) return false;
-   } else if(SiS_Pr->ChipType >= SIS_661) return false;
-   return true;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      /* YPrPb = 0x08 */
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
-   }
-   return false;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_IsChScart(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      /* Scart = 0x04 */
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
-   }
-   return false;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag;
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToTV)        return true;
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if(flag & EnableCHYPbPr)      return true;  /* = YPrPb = 0x08 */
-      if(flag & EnableCHScart)      return true;  /* = Scart = 0x04 - TW */
-   } else {
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToTV)        return true;
-   }
-   return false;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static bool
-SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag;
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToLCD) return true;
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if(flag & SetToLCDA)    return true;
-   } else {
-      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToLCD) return true;
-   }
-   return false;
-}
-#endif
-
-static bool
-SiS_HaveBridge(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag;
-
-   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-      return true;
-   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-      if((flag == 1) || (flag == 2)) return true;
-   }
-   return false;
-}
-
-static bool
-SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag;
-
-   if(SiS_HaveBridge(SiS_Pr)) {
-      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-      if(SiS_Pr->ChipType < SIS_315H) {
-	flag &= 0xa0;
-	if((flag == 0x80) || (flag == 0x20)) return true;
-      } else {
-	flag &= 0x50;
-	if((flag == 0x40) || (flag == 0x10)) return true;
-      }
-   }
-   return false;
-}
-
-static bool
-SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag1;
-
-   flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
-   if(flag1 & (SetInSlaveMode >> 8)) return true;
-   return false;
-}
-
-/*********************************************/
-/*       GET VIDEO BRIDGE CONFIG INFO        */
-/*********************************************/
-
-/* Setup general purpose IO for Chrontel communication */
-#ifdef CONFIG_FB_SIS_300
-void
-SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
-{
-   unsigned int   acpibase;
-   unsigned short temp;
-
-   if(!(SiS_Pr->SiS_ChSW)) return;
-
-   acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
-   acpibase &= 0xFFFF;
-   if(!acpibase) return;
-   temp = SiS_GetRegShort((acpibase + 0x3c));	/* ACPI register 0x3c: GP Event 1 I/O mode select */
-   temp &= 0xFEFF;
-   SiS_SetRegShort((acpibase + 0x3c), temp);
-   temp = SiS_GetRegShort((acpibase + 0x3c));
-   temp = SiS_GetRegShort((acpibase + 0x3a));	/* ACPI register 0x3a: GP Pin Level (low/high) */
-   temp &= 0xFEFF;
-   if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
-   SiS_SetRegShort((acpibase + 0x3a), temp);
-   temp = SiS_GetRegShort((acpibase + 0x3a));
-}
-#endif
-
-void
-SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex, int checkcrt2mode)
-{
-   unsigned short tempax, tempbx, temp;
-   unsigned short modeflag, resinfo = 0;
-
-   SiS_Pr->SiS_SetFlag = 0;
-
-   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-
-   SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
-
-   if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
-      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-   }
-
-   tempbx = 0;
-
-   if(SiS_HaveBridge(SiS_Pr)) {
-
-	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	tempbx |= temp;
-	tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
-	tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
-	tempbx |= tempax;
-
-#ifdef CONFIG_FB_SIS_315
-	if(SiS_Pr->ChipType >= SIS_315H) {
-	   if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
-	      if(ModeNo == 0x03) {
-		 /* Mode 0x03 is never in driver mode */
-		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
-	      }
-	      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
-		 /* Reset LCDA setting if not driver mode */
-		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
-	      }
-	      if(IS_SIS650) {
-		 if(SiS_Pr->SiS_UseLCDA) {
-		    if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
-		       if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
-			  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
-		       }
-		    }
-		 }
-	      }
-	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-	      if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
-		 tempbx |= SetCRT2ToLCDA;
-	      }
-	   }
-
-	   if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
-	      tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
-	      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
-		 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
-		 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
-		 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
-		    tempbx |= SetCRT2ToYPbPr525750;
-		 }
-	      }
-	   }
-
-	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-	      if(temp & SetToLCDA) {
-		 tempbx |= SetCRT2ToLCDA;
-	      }
-	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-		 if(temp & EnableCHYPbPr) {
-		    tempbx |= SetCRT2ToCHYPbPr;
-		 }
-	      }
-	   }
-	}
-
-#endif  /* CONFIG_FB_SIS_315 */
-
-        if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
-	   tempbx &= ~(SetCRT2ToRAMDAC);
-	}
-
-	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	   temp = SetCRT2ToSVIDEO   |
-		  SetCRT2ToAVIDEO   |
-		  SetCRT2ToSCART    |
-		  SetCRT2ToLCDA     |
-		  SetCRT2ToLCD      |
-		  SetCRT2ToRAMDAC   |
-		  SetCRT2ToHiVision |
-		  SetCRT2ToYPbPr525750;
-	} else {
-	   if(SiS_Pr->ChipType >= SIS_315H) {
-	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-		 temp = SetCRT2ToAVIDEO |
-		        SetCRT2ToSVIDEO |
-		        SetCRT2ToSCART  |
-		        SetCRT2ToLCDA   |
-		        SetCRT2ToLCD    |
-		        SetCRT2ToCHYPbPr;
-	      } else {
-		 temp = SetCRT2ToLCDA   |
-		        SetCRT2ToLCD;
-	      }
-	   } else {
-	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-		 temp = SetCRT2ToTV | SetCRT2ToLCD;
-	      } else {
-		 temp = SetCRT2ToLCD;
-	      }
-	   }
-	}
-
-	if(!(tempbx & temp)) {
-	   tempax = DisableCRT2Display;
-	   tempbx = 0;
-	}
-
-	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-	   unsigned short clearmask = ( DriverMode |
-				DisableCRT2Display |
-				LoadDACFlag 	   |
-				SetNotSimuMode 	   |
-				SetInSlaveMode 	   |
-				SetPALTV 	   |
-				SwitchCRT2	   |
-				SetSimuScanMode );
-
-	   if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
-	   if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
-	   if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
-	   if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
-	   if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
-	   if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
-
-	} else {
-
-	   if(SiS_Pr->ChipType >= SIS_315H) {
-	      if(tempbx & SetCRT2ToLCDA) {
-		 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
-	      }
-	   }
-	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	      if(tempbx & SetCRT2ToTV) {
-		 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
-	      }
-	   }
-	   if(tempbx & SetCRT2ToLCD) {
-	      tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
-	   }
-	   if(SiS_Pr->ChipType >= SIS_315H) {
-	      if(tempbx & SetCRT2ToLCDA) {
-	         tempbx |= SetCRT2ToLCD;
-	      }
-	   }
-
-	}
-
-	if(tempax & DisableCRT2Display) {
-	   if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
-	      tempbx = SetSimuScanMode | DisableCRT2Display;
-	   }
-	}
-
-	if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
-
-	/* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
-	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
-	       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
-	      modeflag &= (~CRT2Mode);
-	   }
-	}
-
-	if(!(tempbx & SetSimuScanMode)) {
-	   if(tempbx & SwitchCRT2) {
-	      if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
-		 if(resinfo != SIS_RI_1600x1200) {
-		    tempbx |= SetSimuScanMode;
-		 }
-              }
-	   } else {
-	      if(SiS_BridgeIsEnabled(SiS_Pr)) {
-		 if(!(tempbx & DriverMode)) {
-		    if(SiS_BridgeInSlavemode(SiS_Pr)) {
-		       tempbx |= SetSimuScanMode;
-		    }
-		 }
-	      }
-	   }
-	}
-
-	if(!(tempbx & DisableCRT2Display)) {
-	   if(tempbx & DriverMode) {
-	      if(tempbx & SetSimuScanMode) {
-		 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
-		    if(resinfo != SIS_RI_1600x1200) {
-		       tempbx |= SetInSlaveMode;
-		    }
-		 }
-	      }
-	   } else {
-	      tempbx |= SetInSlaveMode;
-	   }
-	}
-
-   }
-
-   SiS_Pr->SiS_VBInfo = tempbx;
-
-#ifdef CONFIG_FB_SIS_300
-   if(SiS_Pr->ChipType == SIS_630) {
-      SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
-   }
-#endif
-
-#if 0
-   printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
-      SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
-#endif
-}
-
-/*********************************************/
-/*           DETERMINE YPbPr MODE            */
-/*********************************************/
-
-void
-SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
-{
-
-   unsigned char temp;
-
-   /* Note: This variable is only used on 30xLV systems.
-    * CR38 has a different meaning on LVDS/CH7019 systems.
-    * On 661 and later, these bits moved to CR35.
-    *
-    * On 301, 301B, only HiVision 1080i is supported.
-    * On 30xLV, 301C, only YPbPr 1080i is supported.
-    */
-
-   SiS_Pr->SiS_YPbPr = 0;
-   if(SiS_Pr->ChipType >= SIS_661) return;
-
-   if(SiS_Pr->SiS_VBType) {
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	 SiS_Pr->SiS_YPbPr = YPbPrHiVision;
-      }
-   }
-
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
-	 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-	 if(temp & 0x08) {
-	    switch((temp >> 4)) {
-	    case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
-	    case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
-	    case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
-	    case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
-	    }
-	 }
-      }
-   }
-
-}
-
-/*********************************************/
-/*           DETERMINE TVMode flag           */
-/*********************************************/
-
-void
-SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short temp, temp1, resinfo = 0, romindex = 0;
-   unsigned char  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
-
-   SiS_Pr->SiS_TVMode = 0;
-
-   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
-   if(SiS_Pr->UseCustomMode) return;
-
-   if(ModeNo > 0x13) {
-      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-   }
-
-   if(SiS_Pr->ChipType < SIS_661) {
-
-      if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
-
-      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	 temp = 0;
-	 if((SiS_Pr->ChipType == SIS_630) ||
-	    (SiS_Pr->ChipType == SIS_730)) {
-	    temp = 0x35;
-	    romindex = 0xfe;
-	 } else if(SiS_Pr->ChipType >= SIS_315H) {
-	    temp = 0x38;
-	    if(SiS_Pr->ChipType < XGI_20) {
-	       romindex = 0xf3;
-	       if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
-	    }
-	 }
-	 if(temp) {
-	    if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
-	       OutputSelect = ROMAddr[romindex];
-	       if(!(OutputSelect & EnablePALMN)) {
-		  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
-	       }
-	    }
-	    temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
-	    if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	       if(temp1 & EnablePALM) {		/* 0x40 */
-		  SiS_Pr->SiS_TVMode |= TVSetPALM;
-		  SiS_Pr->SiS_TVMode &= ~TVSetPAL;
-	       } else if(temp1 & EnablePALN) {	/* 0x80 */
-		  SiS_Pr->SiS_TVMode |= TVSetPALN;
-	       }
-	    } else {
-	       if(temp1 & EnableNTSCJ) {	/* 0x40 */
-		  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
-	       }
-	    }
-	 }
-	 /* Translate HiVision/YPbPr to our new flags */
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
-	    else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
-	    else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
-	    else				        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
-	    if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
-	       SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
-	       SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
-	    } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
-	       SiS_Pr->SiS_TVMode |= TVSetPAL;
-	    }
-	 }
-      } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	 if(SiS_Pr->SiS_CHOverScan) {
-	    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-	       if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
-		  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-	       }
-	    } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
-	       if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
-		  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-	       }
-	    }
-	    if(SiS_Pr->SiS_CHSOverScan) {
-	       SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-	    }
-	 }
-	 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-	    if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	       if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
-	       else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
-	    } else {
-	       if(temp & EnableNTSCJ) {
-		  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
-	       }
-	    }
-	 }
-      }
-
-   } else {  /* 661 and later */
-
-      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-      if(temp1 & 0x01) {
-	 SiS_Pr->SiS_TVMode |= TVSetPAL;
-	 if(temp1 & 0x08) {
-	    SiS_Pr->SiS_TVMode |= TVSetPALN;
-	 } else if(temp1 & 0x04) {
-	    if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	       SiS_Pr->SiS_TVMode &= ~TVSetPAL;
-	    }
-	    SiS_Pr->SiS_TVMode |= TVSetPALM;
-	 }
-      } else {
-	 if(temp1 & 0x02) {
-	    SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
-	 }
-      }
-      if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	 if(SiS_Pr->SiS_CHOverScan) {
-	    if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
-	       SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-	    }
-	 }
-      }
-      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	    temp1 &= 0xe0;
-	    if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
-	    else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
-	    else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
-	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
-	 }
-	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
-	    if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
-	       SiS_Pr->SiS_TVMode |= TVAspect169;
-	    } else {
-	       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
-	       if(temp1 & 0x02) {
-		  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
-		     SiS_Pr->SiS_TVMode |= TVAspect169;
-		  } else {
-		     SiS_Pr->SiS_TVMode |= TVAspect43LB;
-		  }
-	       } else {
-		  SiS_Pr->SiS_TVMode |= TVAspect43;
-	       }
-	    }
-	 }
-      }
-   }
-
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	 SiS_Pr->SiS_TVMode |= TVSetPAL;
-	 SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
-      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
-	    SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
-	 }
-      }
-
-      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-	    SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
-	 }
-      }
-
-      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	 if(resinfo == SIS_RI_1024x768) {
-	    if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-	       SiS_Pr->SiS_TVMode |= TVSet525p1024;
-	    } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
-	       SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
-	    }
-	 }
-      }
-
-      SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
-      if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
-	 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-	 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
-      } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
-	 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
-      } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
-	 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-	    SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
-	 }
-      }
-
-   }
-
-   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
-}
-
-/*********************************************/
-/*               GET LCD INFO                */
-/*********************************************/
-
-static unsigned short
-SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
-{
-   unsigned short temp = SiS_Pr->SiS_LCDResInfo;
-   /* Translate my LCDResInfo to BIOS value */
-   switch(temp) {
-   case Panel_1280x768_2: temp = Panel_1280x768;    break;
-   case Panel_1280x800_2: temp = Panel_1280x800;    break;
-   case Panel_1280x854:   temp = Panel661_1280x854; break;
-   }
-   return temp;
-}
-
-static void
-SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
-{
-#ifdef CONFIG_FB_SIS_315
-   unsigned char  *ROMAddr;
-   unsigned short temp;
-
-   if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
-      if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
-	 SiS_Pr->SiS_NeedRomModeData = true;
-	 SiS_Pr->PanelHT  = temp;
-      }
-      if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
-	 SiS_Pr->SiS_NeedRomModeData = true;
-	 SiS_Pr->PanelVT  = temp;
-      }
-      SiS_Pr->PanelHRS = SISGETROMW(10);
-      SiS_Pr->PanelHRE = SISGETROMW(12);
-      SiS_Pr->PanelVRS = SISGETROMW(14);
-      SiS_Pr->PanelVRE = SISGETROMW(16);
-      SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
-      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
-	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
-      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
-	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
-      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
-	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
-
-   }
-#endif
-}
-
-static void
-SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
-			const unsigned char *nonscalingmodes)
-{
-   int i = 0;
-   while(nonscalingmodes[i] != 0xff) {
-      if(nonscalingmodes[i++] == resinfo) {
-	 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
-	    (SiS_Pr->UsePanelScaler == -1)) {
-	    SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	 }
-	 break;
-      }
-   }
-}
-
-void
-SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
-  bool panelcanscale = false;
-#ifdef CONFIG_FB_SIS_300
-  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
-  static const unsigned char SiS300SeriesLCDRes[] =
-          { 0,  1,  2,  3,  7,  4,  5,  8,
-	    0,  0, 10,  0,  0,  0,  0, 15 };
-#endif
-#ifdef CONFIG_FB_SIS_315
-  unsigned char   *myptr = NULL;
-#endif
-
-  SiS_Pr->SiS_LCDResInfo  = 0;
-  SiS_Pr->SiS_LCDTypeInfo = 0;
-  SiS_Pr->SiS_LCDInfo     = 0;
-  SiS_Pr->PanelHRS        = 999; /* HSync start */
-  SiS_Pr->PanelHRE        = 999; /* HSync end */
-  SiS_Pr->PanelVRS        = 999; /* VSync start */
-  SiS_Pr->PanelVRE        = 999; /* VSync end */
-  SiS_Pr->SiS_NeedRomModeData = false;
-
-  /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
-  SiS_Pr->Alternate1600x1200 = false;
-
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
-
-  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-
-  if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
-     modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
-  }
-
-  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
-
-  /* For broken BIOSes: Assume 1024x768 */
-  if(temp == 0) temp = 0x02;
-
-  if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
-     SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
-  } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
-     SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
-  } else {
-     SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
-  }
-  temp &= 0x0f;
-#ifdef CONFIG_FB_SIS_300
-  if(SiS_Pr->ChipType < SIS_315H) {
-     /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
-     if(SiS_Pr->SiS_VBType & VB_SIS301) {
-        if(temp < 0x0f) temp &= 0x07;
-     }
-     /* Translate 300 series LCDRes to 315 series for unified usage */
-     temp = SiS300SeriesLCDRes[temp];
-  }
-#endif
-
-  /* Translate to our internal types */
-#ifdef CONFIG_FB_SIS_315
-  if(SiS_Pr->ChipType == SIS_550) {
-     if     (temp == Panel310_1152x768)  temp = Panel_320x240_2; /* Verified working */
-     else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
-     else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
-  } else if(SiS_Pr->ChipType >= SIS_661) {
-     if(temp == Panel661_1280x854)       temp = Panel_1280x854;
-  }
-#endif
-
-  if(SiS_Pr->SiS_VBType & VB_SISLVDS) {		/* SiS LVDS */
-     if(temp == Panel310_1280x768) {
-        temp = Panel_1280x768_2;
-     }
-     if(SiS_Pr->SiS_ROMNew) {
-	if(temp == Panel661_1280x800) {
-	   temp = Panel_1280x800_2;
-	}
-     }
-  }
-
-  SiS_Pr->SiS_LCDResInfo = temp;
-
-#ifdef CONFIG_FB_SIS_300
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-	SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
-     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
-	SiS_Pr->SiS_LCDResInfo = Panel_848x480;
-     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
-	SiS_Pr->SiS_LCDResInfo = Panel_856x480;
-     }
-  }
-#endif
-
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
-  }
-
-  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-  SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
-  /* Need temp below! */
-
-  /* These must/can't scale no matter what */
-  switch(SiS_Pr->SiS_LCDResInfo) {
-  case Panel_320x240_1:
-  case Panel_320x240_2:
-  case Panel_320x240_3:
-  case Panel_1280x960:
-      SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-      break;
-  case Panel_640x480:
-      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-  }
-
-  panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
-
-  if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-
-  /* Dual link, Pass 1:1 BIOS default, etc. */
-#ifdef CONFIG_FB_SIS_315
-  if(SiS_Pr->ChipType >= SIS_661) {
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
-     }
-     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
-	if(SiS_Pr->SiS_ROMNew) {
-	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	} else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
-	   if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
-     }
-  } else if(SiS_Pr->ChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
-     }
-     if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
-	SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
-	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-	if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
-	if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
-	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
-     } else if(!(SiS_Pr->SiS_ROMNew)) {
-	if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
-	   if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
-	      (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
-	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	   }
-	   if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
-	      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
-	      (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
-	      (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
-	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	   }
-	}
-     }
-  }
-#endif
-
-  /* Pass 1:1 */
-  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-     /* Always center screen on LVDS (if scaling is disabled) */
-     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	/* Always center screen on SiS LVDS (if scaling is disabled) */
-	SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-     } else {
-	/* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
-	if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
-	if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-     }
-  }
-
-  SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
-  SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
-
-  switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_320x240_1:
-     case Panel_320x240_2:
-     case Panel_320x240_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
-			    SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
-			    break;
-     case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
-						      SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
-			    break;
-     case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
-     			    SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
-			    SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
-			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
-			    SiS_Pr->PanelVCLKIdx300 = VCLK40;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK40;
-			    break;
-     case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
-			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
-			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
-			    SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
-			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
-			    break;
-     case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
-			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
-			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
-			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
-			    if(SiS_Pr->ChipType < SIS_315H) {
-			       SiS_Pr->PanelHRS = 23;
-						      SiS_Pr->PanelVRE  =    5;
-			    }
-			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
-			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
-			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
-			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
-			    if(SiS_Pr->ChipType < SIS_315H) {
-			       SiS_Pr->PanelHRS = 23;
-						      SiS_Pr->PanelVRE  =    5;
-			    }
-			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
-			    break;
-     case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
-			    break;
-     case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
-			    SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
-			    SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
-			    SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
-			    /* Data above for TMDS (projector); get from BIOS for LVDS */
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
-			    if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-			       SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
-			       SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
-			       SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
-			    } else {
-			       SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
-			       SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
-			       SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
-			       SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
-			       SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
-			    }
-			    break;
-     case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
-			    SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
-			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
-			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
-			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
-			    SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
-			    SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
-			    SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
-			    SiS_Pr->PanelHRS   =  48; SiS_Pr->PanelHRE  =  112;
-			    SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1280x854:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  854;
-			    SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  861;
-			    SiS_Pr->PanelHRS   =  16; SiS_Pr->PanelHRE  =  112;
-			    SiS_Pr->PanelVRS   =   1; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
-			    SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
-			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
-			    if(resinfo == SIS_RI_1280x1024) {
-			       SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
-			       SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
-			    }
-			    break;
-     case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
-			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
-			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
-			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
-			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
-			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
-			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
-			    SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
-			    SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
-			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
-			    if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
-			       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-				  SiS_Pr->PanelHT  = 1760; SiS_Pr->PanelVT  = 1235;
-				  SiS_Pr->PanelHRS =   48; SiS_Pr->PanelHRE =   32;
-				  SiS_Pr->PanelVRS =    2; SiS_Pr->PanelVRE =    4;
-				  SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
-				  SiS_Pr->Alternate1600x1200 = true;
-			       }
-			    } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
-			       SiS_Pr->PanelHT  = 2048; SiS_Pr->PanelVT  = 1320;
-			       SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
-			       SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
-			    }
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
-			    SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
-			    SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
-			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
-			    SiS_GetLCDInfoBIOS(SiS_Pr);
-			    break;
-     case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
-			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
-			    break;
-     case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
-			    SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
-			    break;
-     case Panel_856x480:    SiS_Pr->PanelXRes =  856; SiS_Pr->PanelYRes =  480;
-			    SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
-			    break;
-     case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
-			    SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
-			    SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
-			    SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
-			    if(SiS_Pr->CP_PreferredIndex != -1) {
-			       SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
-			       SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
-			       SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
-			       SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
-			       SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
-			       if(SiS_Pr->CP_PrefClock) {
-				  int idx;
-				  SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
-				  SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
-				  if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
-				  else				   idx = VCLK_CUSTOM_315;
-				  SiS_Pr->SiS_VCLKData[idx].CLOCK =
-				     SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
-				  SiS_Pr->SiS_VCLKData[idx].SR2B =
-				     SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
-				  SiS_Pr->SiS_VCLKData[idx].SR2C =
-				     SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
-			       }
-			    }
-			    break;
-     default:		    SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
-			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
-			    break;
-  }
-
-  /* Special cases */
-  if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
-      (SiS_Pr->SiS_IF_DEF_DSTN)              ||
-      (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
-     SiS_Pr->PanelHRS = 999;
-     SiS_Pr->PanelHRE = 999;
-  }
-
-  if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
-     SiS_Pr->PanelVRS = 999;
-     SiS_Pr->PanelVRE = 999;
-  }
-
-  /* DontExpand overrule */
-  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-
-     if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
-	/* No scaling for this mode on any panel (LCD=CRT2)*/
-	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-     }
-
-     switch(SiS_Pr->SiS_LCDResInfo) {
-
-     case Panel_Custom:
-     case Panel_1152x864:
-     case Panel_1280x768:	/* TMDS only */
-	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	break;
-
-     case Panel_800x600: {
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	break;
-     }
-     case Panel_1024x768: {
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	break;
-     }
-     case Panel_1280x720: {
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	if(SiS_Pr->PanelHT == 1650) {
-	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	}
-	break;
-     }
-     case Panel_1280x768_2: {  /* LVDS only */
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   SIS_RI_1152x768,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	switch(resinfo) {
-	case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
-				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-			       }
-			       break;
-	}
-	break;
-     }
-     case Panel_1280x800: {  	/* SiS TMDS special (Averatec 6200 series) */
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	break;
-     }
-     case Panel_1280x800_2:  { 	/* SiS LVDS */
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   SIS_RI_1152x768,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	switch(resinfo) {
-	case SIS_RI_1280x720:
-	case SIS_RI_1280x768:  if(SiS_Pr->UsePanelScaler == -1) {
-				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-			       }
-			       break;
-	}
-	break;
-     }
-     case Panel_1280x854: {  	/* SiS LVDS */
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   SIS_RI_1152x768,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	switch(resinfo) {
-	case SIS_RI_1280x720:
-	case SIS_RI_1280x768:
-	case SIS_RI_1280x800:  if(SiS_Pr->UsePanelScaler == -1) {
-				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-			       }
-			       break;
-	}
-	break;
-     }
-     case Panel_1280x960: {
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
-	   SIS_RI_1280x854,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	break;
-     }
-     case Panel_1280x1024: {
-	static const unsigned char nonscalingmodes[] = {
-	   SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	   SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	   SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
-	   SIS_RI_1280x854,SIS_RI_1280x960,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	break;
-     }
-     case Panel_1400x1050: {
-	static const unsigned char nonscalingmodes[] = {
-	     SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	     SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	     SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
-	     SIS_RI_1280x960,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	switch(resinfo) {
-	case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
-				  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-			       }
-			       break;
-	case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-			       break;
-	}
-	break;
-     }
-     case Panel_1600x1200: {
-	static const unsigned char nonscalingmodes[] = {
-	     SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	     SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	     SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
-	     SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	break;
-     }
-     case Panel_1680x1050: {
-	static const unsigned char nonscalingmodes[] = {
-	     SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
-	     SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-	     SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
-	     SIS_RI_1360x1024,0xff
-	};
-	SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-	break;
-     }
-     }
-  }
-
-#ifdef CONFIG_FB_SIS_300
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
-	SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
-     }
-  }
-
-  if(SiS_Pr->ChipType < SIS_315H) {
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	if(SiS_Pr->SiS_UseROM) {
-	   if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-	      if(!(ROMAddr[0x235] & 0x02)) {
-		 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
-	      }
-	   }
-	}
-     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
-	   SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
-	}
-     }
-  }
-#endif
-
-  /* Special cases */
-
-  if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
-     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-  }
-
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
-     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
-  }
-
-  switch(SiS_Pr->SiS_LCDResInfo) {
-  case Panel_640x480:
-     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
-     break;
-  case Panel_1280x800:
-     /* Don't pass 1:1 by default (TMDS special) */
-     if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-     break;
-  case Panel_1280x960:
-     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-     break;
-  case Panel_Custom:
-     if((!SiS_Pr->CP_PrefClock) ||
-        (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
-        SiS_Pr->SiS_LCDInfo |= LCDPass11;
-     }
-     break;
-  }
-
-  if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
-     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
-  }
-
-  /* (In)validate LCDPass11 flag */
-  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-  }
-
-  /* LVDS DDA */
-  if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
-
-     if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-	if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-	   if(ModeNo == 0x12) {
-	      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-		 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-	      }
-	   } else if(ModeNo > 0x13) {
-	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
-		 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-		    if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
-		       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-		    }
-		 }
-	      }
-	   }
-	}
-     }
-
-     if(modeflag & HalfDCLK) {
-	if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
-	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-	} else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-	} else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
-	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-	} else if(ModeNo > 0x13) {
-	   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	      if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-	   } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
-	      if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-	   }
-	}
-     }
-
-  }
-
-  /* VESA timing */
-  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-     if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
-	SiS_Pr->SiS_SetFlag |= LCDVESATiming;
-     }
-  } else {
-     SiS_Pr->SiS_SetFlag |= LCDVESATiming;
-  }
-
-#if 0
-  printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
-	SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
-#endif
-}
-
-/*********************************************/
-/*                 GET VCLK                  */
-/*********************************************/
-
-unsigned short
-SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex)
-{
-  unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
-  unsigned short modeflag, resinfo, tempbx;
-  const unsigned char *CHTVVCLKPtr = NULL;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-     CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-     VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
-     VCLKIndexGENCRT = VCLKIndexGEN;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-     VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-     VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
-		(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
-  }
-
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
-
-     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
-
-	CRT2Index >>= 6;
-	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      	/*  LCD */
-
-	   if(SiS_Pr->ChipType < SIS_315H) {
-	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
-	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-		 VCLKIndex = VCLKIndexGEN;
-	      }
-	   } else {
-	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
-	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-		 switch(resinfo) {
-		 /* Correct those whose IndexGEN doesn't match VBVCLK array */
-		 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
-		 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
-		 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
-		 case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
-		 case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
-		 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
-		 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
-		 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
-		 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
-		 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
-		 default:              VCLKIndex = VCLKIndexGEN;
-		 }
-
-		 if(ModeNo <= 0x13) {
-		    if(SiS_Pr->ChipType <= SIS_315PRO) {
-		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
-		    } else {
-		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
-		    }
-		 }
-		 if(SiS_Pr->ChipType <= SIS_315PRO) {
-		    if(VCLKIndex == 0) VCLKIndex = 0x41;
-		    if(VCLKIndex == 1) VCLKIndex = 0x43;
-		    if(VCLKIndex == 4) VCLKIndex = 0x44;
-		 }
-	      }
-	   }
-
-	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 	/*  TV */
-
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	      if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) 	   VCLKIndex = HiTVVCLKDIV2;
-	      else                                  	   VCLKIndex = HiTVVCLK;
-	      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     VCLKIndex = HiTVSimuVCLK;
-	   } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  VCLKIndex = YPbPr750pVCLK;
-	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)    VCLKIndex = TVVCLKDIV2;
-	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)      VCLKIndex = TVVCLKDIV2;
-	   else						   VCLKIndex = TVVCLK;
-
-	   if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
-	   else				   VCLKIndex += TVCLKBASE_315;
-
-	} else {							/* VGA2 */
-
-	   VCLKIndex = VCLKIndexGENCRT;
-	   if(SiS_Pr->ChipType < SIS_315H) {
-	      if(ModeNo > 0x13) {
-		 if( (SiS_Pr->ChipType == SIS_630) &&
-		     (SiS_Pr->ChipRevision >= 0x30)) {
-		    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
-		 }
-		 /* Better VGA2 clock for 1280x1024@75 */
-		 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
-	      }
-	   }
-	}
-
-     } else {   /* If not programming CRT2 */
-
-	VCLKIndex = VCLKIndexGENCRT;
-	if(SiS_Pr->ChipType < SIS_315H) {
-	   if(ModeNo > 0x13) {
-	      if( (SiS_Pr->ChipType != SIS_630) &&
-		  (SiS_Pr->ChipType != SIS_300) ) {
-		 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
-	      }
-	   }
-	}
-     }
-
-  } else {       /*   LVDS  */
-
-     VCLKIndex = CRT2Index;
-
-     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
-
-	if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
-
-	   VCLKIndex &= 0x1f;
-	   tempbx = 0;
-	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	      tempbx += 2;
-	      if(SiS_Pr->SiS_ModeType > ModeVGA) {
-		 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
-	      }
-	      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-		 tempbx = 4;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-		 tempbx = 6;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      }
-	   }
-	   switch(tempbx) {
-	     case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
-	     case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
-	     case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
-	     case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
-	     case  4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM;  break;
-	     case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
-	     case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
-	     case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
-	     case  8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL;  break;
-	     default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
-	   }
-	   VCLKIndex = CHTVVCLKPtr[VCLKIndex];
-
-	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-
-	   if(SiS_Pr->ChipType < SIS_315H) {
-	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
-	   } else {
-	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
-	   }
-
-#ifdef CONFIG_FB_SIS_300
-	   /* Special Timing: Barco iQ Pro R series */
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
-
-	   /* Special Timing: 848x480 and 856x480 parallel lvds panels */
-	   if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
-	      if(SiS_Pr->ChipType < SIS_315H) {
-		 VCLKIndex = VCLK34_300;
-		 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
-	      } else {
-		 VCLKIndex = VCLK34_315;
-		 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
-	      }
-	   }
-#endif
-
-	} else {
-
-	   VCLKIndex = VCLKIndexGENCRT;
-	   if(SiS_Pr->ChipType < SIS_315H) {
-	      if(ModeNo > 0x13) {
-		 if( (SiS_Pr->ChipType == SIS_630) &&
-		     (SiS_Pr->ChipRevision >= 0x30) ) {
-		    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
-		 }
-	      }
-	   }
-	}
-
-     } else {  /* if not programming CRT2 */
-
-	VCLKIndex = VCLKIndexGENCRT;
-	if(SiS_Pr->ChipType < SIS_315H) {
-	   if(ModeNo > 0x13) {
-	      if( (SiS_Pr->ChipType != SIS_630) &&
-		  (SiS_Pr->ChipType != SIS_300) ) {
-		 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
-	      }
-#if 0
-	      if(SiS_Pr->ChipType == SIS_730) {
-		 if(VCLKIndex == 0x0b) VCLKIndex = 0x40;   /* 1024x768-70 */
-		 if(VCLKIndex == 0x0d) VCLKIndex = 0x41;   /* 1024x768-75 */
-	      }
-#endif
-	   }
-        }
-
-     }
-
-  }
-
-  return VCLKIndex;
-}
-
-/*********************************************/
-/*        SET CRT2 MODE TYPE REGISTERS       */
-/*********************************************/
-
-static void
-SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned short i, j, modeflag, tempah=0;
-  short tempcl;
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-  unsigned short tempbl;
-#endif
-#ifdef CONFIG_FB_SIS_315
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short tempah2, tempbl2;
-#endif
-
-  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
-
-  } else {
-
-     for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
-     if(SiS_Pr->ChipType >= SIS_315H) {
-        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
-     }
-
-     tempcl = SiS_Pr->SiS_ModeType;
-
-     if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300    /* ---- 300 series ---- */
-
-	/* For 301BDH: (with LCD via LVDS) */
-	if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-	   tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
-	   tempbl &= 0xef;
-	   tempbl |= 0x02;
-	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-	      tempbl |= 0x10;
-	      tempbl &= 0xfd;
-	   }
-	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
-	}
-
-	if(ModeNo > 0x13) {
-	   tempcl -= ModeVGA;
-	   if(tempcl >= 0) {
-	      tempah = ((0x10 >> tempcl) | 0x80);
-	   }
-	} else tempah = 0x80;
-
-	if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
-
-#endif  /* CONFIG_FB_SIS_300 */
-
-     } else {
-
-#ifdef CONFIG_FB_SIS_315    /* ------- 315/330 series ------ */
-
-	if(ModeNo > 0x13) {
-	   tempcl -= ModeVGA;
-	   if(tempcl >= 0) {
-	      tempah = (0x08 >> tempcl);
-	      if (tempah == 0) tempah = 1;
-	      tempah |= 0x40;
-	   }
-	} else tempah = 0x40;
-
-	if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
-
-#endif  /* CONFIG_FB_SIS_315 */
-
-     }
-
-     if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
-
-     if(SiS_Pr->ChipType < SIS_315H) {
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
-     } else {
-#ifdef CONFIG_FB_SIS_315
-	if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
-	} else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	   if(IS_SIS740) {
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
-	   } else {
-	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
-	   }
-	}
-#endif
-     }
-
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-	tempah = 0x01;
-	if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-	   tempah |= 0x02;
-	}
-	if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-	   tempah ^= 0x05;
-	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-	      tempah ^= 0x01;
-	   }
-	}
-
-	if(SiS_Pr->ChipType < SIS_315H) {
-
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
-
-	   tempah = (tempah << 5) & 0xFF;
-	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
-	   tempah = (tempah >> 5) & 0xFF;
-
-	} else {
-
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0x08;
-	   else if(!(SiS_IsDualEdge(SiS_Pr)))           tempah |= 0x08;
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
-	   tempah &= ~0x08;
-
-	}
-
-	if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
-	   tempah |= 0x10;
-	}
-
-	tempah |= 0x80;
-	if(SiS_Pr->SiS_VBType & VB_SIS301) {
-	   if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
-	}
-
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	   if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
-	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-		 tempah |= 0x20;
-	      }
-	   }
-	}
-
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
-
-	tempah = 0x80;
-	if(SiS_Pr->SiS_VBType & VB_SIS301) {
-	   if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
-	}
-
-	if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
-
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	   if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
-	      tempah |= 0x40;
-	   }
-	}
-
-	SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
-
-     } else {  /* LVDS */
-
-	if(SiS_Pr->ChipType >= SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_315
-	   /* LVDS can only be slave in 8bpp modes */
-	   tempah = 0x80;
-	   if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
-	      if(SiS_Pr->SiS_VBInfo & DriverMode) {
-	         tempah |= 0x02;
-	      }
-	   }
-
-	   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  tempah |= 0x02;
-
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)        tempah ^= 0x01;
-
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
-
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
-#endif
-
-	} else {
-
-#ifdef CONFIG_FB_SIS_300
-	   tempah = 0;
-	   if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
-	      tempah |= 0x02;
-	   }
-	   tempah <<= 5;
-
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
-
-	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
-#endif
-
-	}
-
-     }
-
-  }  /* LCDA */
-
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-     if(SiS_Pr->ChipType >= SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_315
-	/* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
-
-	/* The following is nearly unpreditable and varies from machine
-	 * to machine. Especially the 301DH seems to be a real trouble
-	 * maker. Some BIOSes simply set the registers (like in the
-	 * NoLCD-if-statements here), some set them according to the
-	 * LCDA stuff. It is very likely that some machines are not
-	 * treated correctly in the following, very case-orientated
-	 * code. What do I do then...?
-	 */
-
-	/* 740 variants match for 30xB, 301B-DH, 30xLV */
-
-	if(!(IS_SIS740)) {
-	   tempah = 0x04;						   /* For all bridges */
-	   tempbl = 0xfb;
-	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-	      tempah = 0x00;
-	      if(SiS_IsDualEdge(SiS_Pr)) {
-	         tempbl = 0xff;
-	      }
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
-	}
-
-	/* The following two are responsible for eventually wrong colors
-	 * in TV output. The DH (VB_NoLCD) conditions are unknown; the
-	 * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
-	 * in a 650 box (Jake). What is the criteria?
-	 * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
-	 * treatment like the 651+301B-DH(b0) case. Seems more to be the
-	 * chipset than the bridge revision.
-	 */
-
-	if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
-	   tempah = 0x30;
-	   tempbl = 0xc0;
-	   if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
-	      ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
-	      tempah = 0x00;
-	      tempbl = 0x00;
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
-	} else if(SiS_Pr->SiS_VBType & VB_SIS301) {
-	   /* Fixes "TV-blue-bug" on 315+301 */
-	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);	/* For 301   */
-	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
-	} else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);	/* For 30xLV */
-	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
-	} else if(SiS_Pr->SiS_VBType & VB_NoLCD) {		/* For 301B-DH */
-	   tempah = 0x30; tempah2 = 0xc0;
-	   tempbl = 0xcf; tempbl2 = 0x3f;
-	   if(SiS_Pr->SiS_TVBlue == 0) {
-	         tempah = tempah2 = 0x00;
-	   } else if(SiS_Pr->SiS_TVBlue == -1) {
-	      /* Set on 651/M650, clear on 315/650 */
-	      if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
-	         tempah = tempah2 = 0x00;
-	      }
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
-	} else {
-	   tempah = 0x30; tempah2 = 0xc0;		       /* For 30xB, 301C */
-	   tempbl = 0xcf; tempbl2 = 0x3f;
-	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-	      tempah = tempah2 = 0x00;
-	      if(SiS_IsDualEdge(SiS_Pr)) {
-		 tempbl = tempbl2 = 0xff;
-	      }
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
-	}
-
-	if(IS_SIS740) {
-	   tempah = 0x80;
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
-	} else {
-	   tempah = 0x00;
-	   tempbl = 0x7f;
-	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-	      tempbl = 0xff;
-	      if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
-	}
-
-#endif /* CONFIG_FB_SIS_315 */
-
-     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-
-#ifdef CONFIG_FB_SIS_300
-	SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
-
-	if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
-	   ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
-	    (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
-	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
-	} else {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
-	}
-#endif
-
-     }
-
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
-	if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
-        }
-     }
-
-  } else {  /* LVDS */
-
-#ifdef CONFIG_FB_SIS_315
-     if(SiS_Pr->ChipType >= SIS_315H) {
-
-	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-
-	   tempah = 0x04;
-	   tempbl = 0xfb;
-	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-	      tempah = 0x00;
-	      if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
-
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
-	   }
-
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
-
-	} else if(SiS_Pr->ChipType == SIS_550) {
-
-	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
-
-	}
-
-     }
-#endif
-
-  }
-
-}
-
-/*********************************************/
-/*            GET RESOLUTION DATA            */
-/*********************************************/
-
-unsigned short
-SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   if(ModeNo <= 0x13)
-      return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
-   else
-      return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
-}
-
-static void
-SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned short xres, yres, modeflag=0, resindex;
-
-   if(SiS_Pr->UseCustomMode) {
-      xres = SiS_Pr->CHDisplay;
-      if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
-      SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
-      /* DoubleScanMode-check done in CheckCalcCustomMode()! */
-      SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
-      return;
-   }
-
-   resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
-
-   if(ModeNo <= 0x13) {
-      xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
-      yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
-   } else {
-      xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
-      yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
-      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-   }
-
-   if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
-
-      if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
-	 if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-	    if(yres == 350) yres = 400;
-	 }
-	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
-	    if(ModeNo == 0x12) yres = 400;
-	 }
-      }
-
-      if(modeflag & HalfDCLK)       xres <<= 1;
-      if(modeflag & DoubleScanMode) yres <<= 1;
-
-   }
-
-   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	 switch(SiS_Pr->SiS_LCDResInfo) {
-	   case Panel_1024x768:
-	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-		 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-		    if(yres == 350) yres = 357;
-		    if(yres == 400) yres = 420;
-		    if(yres == 480) yres = 525;
-		 }
-	      }
-	      break;
-	   case Panel_1280x1024:
-	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-		 /* BIOS bug - does this regardless of scaling */
-		 if(yres == 400) yres = 405;
-	      }
-	      if(yres == 350) yres = 360;
-	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-		 if(yres == 360) yres = 375;
-	      }
-	      break;
-	   case Panel_1600x1200:
-	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-		 if(yres == 1024) yres = 1056;
-	      }
-	      break;
-	 }
-      }
-
-   } else {
-
-      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-	    if(xres == 720) xres = 640;
-	 }
-      } else if(xres == 720) xres = 640;
-
-      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-	 yres = 400;
-	 if(SiS_Pr->ChipType >= SIS_315H) {
-	    if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-	 } else {
-	    if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-	 }
-	 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
-      }
-
-   }
-   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
-   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
-}
-
-/*********************************************/
-/*           GET CRT2 TIMING DATA            */
-/*********************************************/
-
-static void
-SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-	       unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
-	       unsigned short *ResIndex)
-{
-  unsigned short tempbx=0, tempal=0, resinfo=0;
-
-  if(ModeNo <= 0x13) {
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
-
-  if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
-
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
-
-	tempbx = SiS_Pr->SiS_LCDResInfo;
-	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
-
-	/* patch index */
-	if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
-	   if     (resinfo == SIS_RI_1280x800)  tempal =  9;
-	   else if(resinfo == SIS_RI_1400x1050) tempal = 11;
-	} else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
-		  (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
-		  (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
-	   if     (resinfo == SIS_RI_1280x768)  tempal =  9;
-	}
-
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	   /* Pass 1:1 only (center-screen handled outside) */
-	   /* This is never called for the panel's native resolution */
-	   /* since Pass1:1 will not be set in this case */
-	   tempbx = 100;
-	   if(ModeNo >= 0x13) {
-	      tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
-	   }
-	}
-
-#ifdef CONFIG_FB_SIS_315
-	if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-		 tempbx = 200;
-		 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
-	      }
-	   }
-	}
-#endif
-
-     } else {						  	/* TV */
-
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	   /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
-	   tempbx = 2;
-	   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	      tempbx = 13;
-	      if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
-	   }
-	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	   if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)	tempbx = 7;
-	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)	tempbx = 6;
-	   else						tempbx = 5;
-	   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)	tempbx += 5;
-	} else {
-	   if(SiS_Pr->SiS_TVMode & TVSetPAL)		tempbx = 3;
-	   else						tempbx = 4;
-	   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)	tempbx += 5;
-	}
-
-     }
-
-     tempal &= 0x3F;
-
-     if(ModeNo > 0x13) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
-	   switch(resinfo) {
-	   case SIS_RI_720x480:
-	      tempal = 6;
-	      if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN))	tempal = 9;
-	      break;
-	   case SIS_RI_720x576:
-	   case SIS_RI_768x576:
-	   case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
-	      tempal = 6;
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-		 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)	tempal = 8;
-	      }
-	      break;
-	   case SIS_RI_800x480:
-	      tempal = 4;
-	      break;
-	   case SIS_RI_512x384:
-	   case SIS_RI_1024x768:
-	      tempal = 7;
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-		 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)	tempal = 8;
-	      }
-	      break;
-	   case SIS_RI_1280x720:
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-		 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)	tempal = 9;
-	      }
-	      break;
-	   }
-	}
-     }
-
-     *CRT2Index = tempbx;
-     *ResIndex = tempal;
-
-  } else {   /* LVDS, 301B-DH (if running on LCD) */
-
-     tempbx = 0;
-     if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-
-	tempbx = 90;
-	if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	   tempbx = 92;
-	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
-	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
-	   }
-	   if(SiS_Pr->SiS_TVMode & TVSetPALM)      tempbx = 94;
-	   else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
-	}
-	if(tempbx != 99) {
-	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-	}
-
-     } else {
-
-	switch(SiS_Pr->SiS_LCDResInfo) {
-	case Panel_640x480:   tempbx = 12; break;
-	case Panel_320x240_1: tempbx = 10; break;
-	case Panel_320x240_2:
-	case Panel_320x240_3: tempbx = 14; break;
-	case Panel_800x600:   tempbx = 16; break;
-	case Panel_1024x600:  tempbx = 18; break;
-	case Panel_1152x768:
-	case Panel_1024x768:  tempbx = 20; break;
-	case Panel_1280x768:  tempbx = 22; break;
-	case Panel_1280x1024: tempbx = 24; break;
-	case Panel_1400x1050: tempbx = 26; break;
-	case Panel_1600x1200: tempbx = 28; break;
-#ifdef CONFIG_FB_SIS_300
-	case Panel_Barco1366: tempbx = 80; break;
-#endif
-	}
-
-	switch(SiS_Pr->SiS_LCDResInfo) {
-	case Panel_320x240_1:
-	case Panel_320x240_2:
-	case Panel_320x240_3:
-	case Panel_640x480:
-	   break;
-	default:
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-	}
-
-	if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
-
-#ifdef CONFIG_FB_SIS_300
-	if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	   tempbx = 82;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-	} else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
-	   tempbx = 84;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-	}
-#endif
-
-     }
-
-     (*CRT2Index) = tempbx;
-     (*ResIndex) = tempal & 0x1F;
-  }
-}
-
-static void
-SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex)
-{
-  unsigned short tempax=0, tempbx=0, index, dotclock;
-  unsigned short temp1=0, modeflag=0, tempcx=0;
-
-  SiS_Pr->SiS_RVBHCMAX  = 1;
-  SiS_Pr->SiS_RVBHCFACT = 1;
-
-  if(ModeNo <= 0x13) {
-
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
-
-     tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
-     tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
-     temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
-
-     dotclock = (modeflag & Charx8Dot) ? 8 : 9;
-
-  } else {
-
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
-
-     tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
-     tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
-     tempax &= 0x03FF;
-     tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
-     tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
-     tempcx &= 0x0100;
-     tempcx <<= 2;
-     tempbx |= tempcx;
-     temp1  = SiS_Pr->SiS_CRT1Table[index].CR[7];
-
-     dotclock = 8;
-
-  }
-
-  if(temp1 & 0x01) tempbx |= 0x0100;
-  if(temp1 & 0x20) tempbx |= 0x0200;
-
-  tempax += 5;
-  tempax *= dotclock;
-  if(modeflag & HalfDCLK) tempax <<= 1;
-
-  tempbx++;
-
-  SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
-  SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
-}
-
-static void
-SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
-{
-   unsigned short ResIndex;
-
-   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-	 if(SiS_Pr->UseCustomMode) {
-	    ResIndex = SiS_Pr->CHTotal;
-	    if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
-	    SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
-	    SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
-	 } else {
-	    if(ModeNo < 0x13) {
-	       ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-	    } else {
-	       ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
-	    }
-	    if(ResIndex == 0x09) {
-	       if(SiS_Pr->Alternate1600x1200)        ResIndex = 0x20; /* 1600x1200 LCDA */
-	       else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
-	    }
-	    SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
-	    SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
-	    SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
-	    SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
-	 }
-      } else {
-	 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
-	 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
-      }
-   } else {
-      /* This handles custom modes and custom panels */
-      SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-      SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-      SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
-      SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
-      SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
-      SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
-   }
-}
-
-static void
-SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-                    unsigned short RefreshRateTableIndex)
-{
-   unsigned short CRT2Index, ResIndex, backup;
-   const struct SiS_LVDSData *LVDSData = NULL;
-
-   SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-      SiS_Pr->SiS_RVBHCMAX  = 1;
-      SiS_Pr->SiS_RVBHCFACT = 1;
-      SiS_Pr->SiS_NewFlickerMode = 0;
-      SiS_Pr->SiS_RVBHRS = 50;
-      SiS_Pr->SiS_RY1COE = 0;
-      SiS_Pr->SiS_RY2COE = 0;
-      SiS_Pr->SiS_RY3COE = 0;
-      SiS_Pr->SiS_RY4COE = 0;
-      SiS_Pr->SiS_RVBHRS2 = 0;
-   }
-
-   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-
-#ifdef CONFIG_FB_SIS_315
-      SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
-#endif
-
-   } else {
-
-      /* 301BDH needs LVDS Data */
-      backup = SiS_Pr->SiS_IF_DEF_LVDS;
-      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-	 SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      }
-
-      SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                     		            &CRT2Index, &ResIndex);
-
-      SiS_Pr->SiS_IF_DEF_LVDS = backup;
-
-      switch(CRT2Index) {
-	 case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1;    break;
-	 case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2;    break;
-	 case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
-	 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
-	 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
-	 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-#ifdef CONFIG_FB_SIS_300
-	 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
-	 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
-	 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
-	 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
-	 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
-#endif
-	 case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
-	 case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
-	 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
-	 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
-	 case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
-	 case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
-	 case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
-	 case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
-	 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;
-      }
-
-      if(LVDSData) {
-	 SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
-	 SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
-	 SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
-	 SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
-      } else {
-	 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      }
-
-      if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
-	  (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
-	  (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
-	 if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
-	     (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
-	    SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-            SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-#ifdef CONFIG_FB_SIS_300
-	    if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-	       if(ResIndex < 0x08) {
-		  SiS_Pr->SiS_HDE = 1280;
-		  SiS_Pr->SiS_VDE = 1024;
-	       }
-	    }
-#endif
-         }
-      }
-   }
-}
-
-static void
-SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex)
-{
-  unsigned char  *ROMAddr = NULL;
-  unsigned short tempax, tempbx, modeflag, romptr=0;
-  unsigned short resinfo, CRT2Index, ResIndex;
-  const struct SiS_LCDData *LCDPtr = NULL;
-  const struct SiS_TVData  *TVPtr  = NULL;
-#ifdef CONFIG_FB_SIS_315
-  short resinfo661;
-#endif
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-     resinfo = 0;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-#ifdef CONFIG_FB_SIS_315
-     resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
-     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
-	 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
-	 (resinfo661 >= 0)                     &&
-	 (SiS_Pr->SiS_NeedRomModeData) ) {
-	if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
-	   if((romptr = (SISGETROMW(21)))) {
-	      romptr += (resinfo661 * 10);
-	      ROMAddr = SiS_Pr->VirtualRomBase;
-	   }
-	}
-     }
-#endif
-  }
-
-  SiS_Pr->SiS_NewFlickerMode = 0;
-  SiS_Pr->SiS_RVBHRS = 50;
-  SiS_Pr->SiS_RY1COE = 0;
-  SiS_Pr->SiS_RY2COE = 0;
-  SiS_Pr->SiS_RY3COE = 0;
-  SiS_Pr->SiS_RY4COE = 0;
-  SiS_Pr->SiS_RVBHRS2 = 0;
-
-  SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-
-     if(SiS_Pr->UseCustomMode) {
-
-	SiS_Pr->SiS_RVBHCMAX  = 1;
-	SiS_Pr->SiS_RVBHCFACT = 1;
-	SiS_Pr->SiS_HDE       = SiS_Pr->SiS_VGAHDE;
-	SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
-
-	tempax = SiS_Pr->CHTotal;
-	if(modeflag & HalfDCLK) tempax <<= 1;
-	SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
-	SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
-
-     } else {
-
-	SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-
-     }
-
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-
-     SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-		    &CRT2Index,&ResIndex);
-
-     switch(CRT2Index) {
-	case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
-	case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
-	case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
-	case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
-	case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
-	case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
-	case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
-	case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
-	case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
-	case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
-	case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
-	case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
-	case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
-	default: TVPtr = SiS_Pr->SiS_StPALData;     break;
-     }
-
-     SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
-     SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
-     SiS_Pr->SiS_VGAHT     = (TVPtr+ResIndex)->VGAHT;
-     SiS_Pr->SiS_VGAVT     = (TVPtr+ResIndex)->VGAVT;
-     SiS_Pr->SiS_HDE       = (TVPtr+ResIndex)->TVHDE;
-     SiS_Pr->SiS_VDE       = (TVPtr+ResIndex)->TVVDE;
-     SiS_Pr->SiS_RVBHRS2   = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
-     if(modeflag & HalfDCLK) {
-	SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
-	if(SiS_Pr->SiS_RVBHRS2) {
-	   SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
-	   tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
-	   if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
-	   else                                   SiS_Pr->SiS_RVBHRS2 += tempax;
-	}
-     } else {
-	SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
-     }
-     SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
-
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-
-	if((resinfo == SIS_RI_960x600)   ||
-	   (resinfo == SIS_RI_1024x768)  ||
-	   (resinfo == SIS_RI_1280x1024) ||
-	   (resinfo == SIS_RI_1280x720)) {
-	   SiS_Pr->SiS_NewFlickerMode = 0x40;
-	}
-
-	if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
-
-	SiS_Pr->SiS_HT = ExtHiTVHT;
-	SiS_Pr->SiS_VT = ExtHiTVVT;
-	if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-	      SiS_Pr->SiS_HT = StHiTVHT;
-	      SiS_Pr->SiS_VT = StHiTVVT;
-	   }
-	}
-
-     } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-
-	if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
-	   SiS_Pr->SiS_HT = 1650;
-	   SiS_Pr->SiS_VT = 750;
-	} else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-	   SiS_Pr->SiS_HT = NTSCHT;
-	   if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
-	   SiS_Pr->SiS_VT = NTSCVT;
-	} else {
-	   SiS_Pr->SiS_HT = NTSCHT;
-	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
-	   SiS_Pr->SiS_VT = NTSCVT;
-	}
-
-     } else {
-
-	SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
-	SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
-	SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
-	SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
-
-	if(modeflag & HalfDCLK) {
-	   SiS_Pr->SiS_RY1COE = 0x00;
-	   SiS_Pr->SiS_RY2COE = 0xf4;
-	   SiS_Pr->SiS_RY3COE = 0x10;
-	   SiS_Pr->SiS_RY4COE = 0x38;
-	}
-
-	if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	   SiS_Pr->SiS_HT = NTSCHT;
-	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
-	   SiS_Pr->SiS_VT = NTSCVT;
-	} else {
-	   SiS_Pr->SiS_HT = PALHT;
-	   SiS_Pr->SiS_VT = PALVT;
-	}
-
-     }
-
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-
-     SiS_Pr->SiS_RVBHCMAX  = 1;
-     SiS_Pr->SiS_RVBHCFACT = 1;
-
-     if(SiS_Pr->UseCustomMode) {
-
-	SiS_Pr->SiS_HDE   = SiS_Pr->SiS_VGAHDE;
-	SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
-
-	tempax = SiS_Pr->CHTotal;
-	if(modeflag & HalfDCLK) tempax <<= 1;
-	SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
-	SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
-
-     } else {
-
-	bool gotit = false;
-
-	if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-
-	   SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
-	   SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
-	   SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
-	   SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
-	   gotit = true;
-
-	} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
-
-#ifdef CONFIG_FB_SIS_315
-	   SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
-	   SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
-	   SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
-	   SiS_Pr->SiS_VGAVT     = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
-	   SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
-	   SiS_Pr->SiS_VT        = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
-	   SiS_Pr->SiS_RVBHRS2   = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
-	   if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
-	      SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
-	      tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
-	      if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
-	      else                         SiS_Pr->SiS_RVBHRS2 += tempax;
-	   }
-	   if(SiS_Pr->SiS_VGAHT) gotit = true;
-	   else {
-	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
-	      SiS_Pr->SiS_RVBHCMAX  = 1;
-	      SiS_Pr->SiS_RVBHCFACT = 1;
-	      SiS_Pr->SiS_VGAHT   = SiS_Pr->PanelHT;
-	      SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
-	      SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
-	      SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
-	      SiS_Pr->SiS_RVBHRS2 = 0;
-	      gotit = true;
-	   }
-#endif
-
-	}
-
-	if(!gotit) {
-
-	   SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-			  &CRT2Index,&ResIndex);
-
-	   switch(CRT2Index) {
-	      case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
-	      case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
-	      case Panel_1280x720      :
-	      case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
-	      case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
-	      case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
-	      case Panel_1280x800      :
-	      case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
-	      case Panel_1280x800_2    :
-	      case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data;    break;
-	      case Panel_1280x854      :
-	      case Panel_1280x854  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data;      break;
-	      case Panel_1280x960      :
-	      case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
-	      case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
-	      case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
-	      case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
-	      case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
-	      case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
-	      case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
-	      case Panel_1680x1050     :
-	      case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
-	      case 100		       : LCDPtr = SiS_Pr->SiS_NoScaleData;	    break;
-#ifdef CONFIG_FB_SIS_315
-	      case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
-	      case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
-#endif
-	      default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
-	   }
-
-	   SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
-	   SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
-	   SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
-	   SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
-	   SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
-	   SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
-
-        }
-
-	tempax = SiS_Pr->PanelXRes;
-	tempbx = SiS_Pr->PanelYRes;
-
-	switch(SiS_Pr->SiS_LCDResInfo) {
-	case Panel_1024x768:
-	   if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-	      if(SiS_Pr->ChipType < SIS_315H) {
-		 if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
-		 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-	      }
-	   } else {
-	      if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
-	      else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
-	      else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
-	      else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
-	      else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
-	      else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-	   }
-	   break;
-	case Panel_1280x960:
-	   if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
-	   else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
-	   else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
-	   break;
-	case Panel_1280x1024:
-	   if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
-	   else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
-	   else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
-	   break;
-	case Panel_1600x1200:
-	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-	      if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
-	      else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
-	   }
-	   break;
-	}
-
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	   tempax = SiS_Pr->SiS_VGAHDE;
-	   tempbx = SiS_Pr->SiS_VGAVDE;
-	}
-
-	SiS_Pr->SiS_HDE = tempax;
-	SiS_Pr->SiS_VDE = tempbx;
-     }
-  }
-}
-
-static void
-SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-                unsigned short RefreshRateTableIndex)
-{
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-         SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      } else {
-	 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-	    /* Need LVDS Data for LCD on 301B-DH */
-	    SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	 } else {
-	    SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	 }
-      }
-
-   } else {
-
-      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-
-   }
-}
-
-/*********************************************/
-/*         GET LVDS DES (SKEW) DATA          */
-/*********************************************/
-
-static const struct SiS_LVDSDes *
-SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
-{
-   const struct SiS_LVDSDes *PanelDesPtr = NULL;
-
-#ifdef CONFIG_FB_SIS_300
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-
-      if(SiS_Pr->ChipType < SIS_315H) {
-	 if(SiS_Pr->SiS_LCDTypeInfo == 4) {
-	    if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-	       PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
-	       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-		  PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
-	       }
-            } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	       PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
-	       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-		  PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
-	       }
-	    }
-	 }
-      }
-   }
-#endif
-   return PanelDesPtr;
-}
-
-static void
-SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-                   unsigned short RefreshRateTableIndex)
-{
-  unsigned short modeflag, ResIndex;
-  const struct SiS_LVDSDes *PanelDesPtr = NULL;
-
-  SiS_Pr->SiS_LCDHDES = 0;
-  SiS_Pr->SiS_LCDVDES = 0;
-
-  /* Some special cases */
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-
-     /* Trumpion */
-     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
-	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
-	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	   }
-	}
-	return;
-     }
-
-     /* 640x480 on LVDS */
-     if(SiS_Pr->ChipType < SIS_315H) {
-	if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
-	   SiS_Pr->SiS_LCDHDES = 8;
-	   if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
-	   else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
-	   else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
-	   return;
-	}
-     }
-
-  } /* LCD */
-
-  if( (SiS_Pr->UseCustomMode) 		         ||
-      (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL856)      ||
-      (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
-     return;
-  }
-
-  if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else               ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-
-#ifdef CONFIG_FB_SIS_315
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	/* non-pass 1:1 only, see above */
-	if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
-	   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
-	}
-	if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
-	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
-	}
-     }
-     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
-	switch(SiS_Pr->SiS_CustomT) {
-	case CUT_UNIWILL1024:
-	case CUT_UNIWILL10242:
-	case CUT_CLEVO1400:
-	   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	   }
-	   break;
-	}
-	switch(SiS_Pr->SiS_LCDResInfo) {
-	case Panel_1280x1024:
-	   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
-	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	   }
-	   break;
-	case Panel_1280x800:	/* Verified for Averatec 6240 */
-	case Panel_1280x800_2:	/* Verified for Asus A4L */
-	case Panel_1280x854:    /* Not verified yet FIXME */
-	   SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	   break;
-	}
-     }
-#endif
-
-  } else {
-
-     if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-
-	if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
-	   if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
-	}
-
-     } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
-
-	SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
-	SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
-
-     } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-
-	if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
-	   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
-	}
-	if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
-	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
-	} else {
-	   if(SiS_Pr->ChipType < SIS_315H) {
-	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	   } else {
-	      switch(SiS_Pr->SiS_LCDResInfo) {
-	      case Panel_800x600:
-	      case Panel_1024x768:
-	      case Panel_1280x1024:
-		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
-		 break;
-	      case Panel_1400x1050:
-		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-		 break;
-	      }
-	   }
-	}
-
-     } else {
-
-        if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-	   switch(SiS_Pr->SiS_LCDResInfo) {
-	   case Panel_800x600:
-	      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
-		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	      } else {
-		 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
-		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
-		 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
-		 else                          SiS_Pr->SiS_LCDVDES -= 4;
-	      }
-	      break;
-	   case Panel_1024x768:
-	      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
-		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	      } else {
-		 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
-		 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
-		 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
-	      }
-	      break;
-	   case Panel_1024x600:
-	   default:
-	      if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
-		  (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
-		 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	      } else {
-		 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
-	      }
-	      break;
-	   }
-
-	   switch(SiS_Pr->SiS_LCDTypeInfo) {
-	   case 1:
-	      SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
-	      break;
-	   case 3: /* 640x480 only? */
-	      SiS_Pr->SiS_LCDHDES = 8;
-	      if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
-	      else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
-	      else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
-	      break;
-	   }
-#endif
-        } else {
-#ifdef CONFIG_FB_SIS_315
-	   switch(SiS_Pr->SiS_LCDResInfo) {
-	   case Panel_1024x768:
-	   case Panel_1280x1024:
-	      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
-	         SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
-	      }
-	      break;
-	   case Panel_320x240_1:
-	   case Panel_320x240_2:
-	   case Panel_320x240_3:
-	      SiS_Pr->SiS_LCDVDES = 524;
-	      break;
-	   }
-#endif
-	}
-     }
-
-     if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-	if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-	   if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
-	} else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-	   if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
-	      if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
-	         if(SiS_Pr->ChipType < SIS_315H) {
-	            if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
-	         } else {
-#ifdef CONFIG_FB_SIS_315
-		    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
-		    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
-		    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
-		    if(!(modeflag & HalfDCLK)) {
-		       SiS_Pr->SiS_LCDHDES = 320;
-		       if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
-		       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
-        	    }
-#endif
-		 }
-	      }
-	   }
-	}
-     }
-  }
-}
-
-/*********************************************/
-/*           DISABLE VIDEO BRIDGE            */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_315
-static int
-SiS_HandlePWD(struct SiS_Private *SiS_Pr)
-{
-   int ret = 0;
-#ifdef SET_PWD
-   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
-   unsigned char  drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
-   unsigned short temp;
-
-   if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
-       (romptr)				&&
-       (SiS_Pr->SiS_PWDOffset) ) {
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
-      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
-      temp = 0x00;
-      if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
-         temp = 0x80;
-	 ret = 1;
-      }
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
-   }
-#endif
-   return ret;
-}
-#endif
-
-/* NEVER use any variables (VBInfo), this will be called
- * from outside the context of modeswitch!
- * MUST call getVBType before calling this
- */
-void
-SiS_DisableBridge(struct SiS_Private *SiS_Pr)
-{
-#ifdef CONFIG_FB_SIS_315
-  unsigned short tempah, pushax=0, modenum;
-#endif
-  unsigned short temp=0;
-
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {		/* ===== For 30xB/C/LV ===== */
-
-	if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300	   /* 300 series */
-
-	   if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
-	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-		 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-	      } else {
-		 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
-	      }
-	      SiS_PanelDelay(SiS_Pr, 3);
-	   }
-	   if(SiS_Is301B(SiS_Pr)) {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
-	      SiS_ShortDelay(SiS_Pr,1);
-	   }
-	   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	   SiS_DisplayOff(SiS_Pr);
-	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	   SiS_UnLockCRT2(SiS_Pr);
-	   if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
-	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
-	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
-	   }
-	   if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
-	       (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
-	      SiS_PanelDelay(SiS_Pr, 2);
-	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-	      } else {
-		 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
-	      }
-	   }
-
-#endif  /* CONFIG_FB_SIS_300 */
-
-        } else {
-
-#ifdef CONFIG_FB_SIS_315	   /* 315 series */
-
-	   int didpwd = 0;
-	   bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	                  (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
-
-	   modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
-
-	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-
-#ifdef SET_EMI
-	      if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-		 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		 }
-	      }
-#endif
-
-	      didpwd = SiS_HandlePWD(SiS_Pr);
-
-	      if( (modenum <= 0x13)           ||
-		  (SiS_IsVAMode(SiS_Pr))      ||
-		  (!(SiS_IsDualEdge(SiS_Pr))) ) {
-		 if(!didpwd) {
-		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
-		    if(custom1) SiS_PanelDelay(SiS_Pr, 3);
-		 } else {
-		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
-		 }
-	      }
-
-	      if(!custom1) {
-		 SiS_DDC2Delay(SiS_Pr,0xff00);
-		 SiS_DDC2Delay(SiS_Pr,0xe000);
-		 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-		 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
-		 if(IS_SIS740) {
-		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-		 }
-	         SiS_PanelDelay(SiS_Pr, 3);
-	      }
-
-	   }
-
-	   if(!(SiS_IsNotM650orLater(SiS_Pr))) {
-	      /* if(SiS_Pr->ChipType < SIS_340) {*/
-		 tempah = 0xef;
-		 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
-		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	      /*}*/
-	   }
-
-	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
-	   }
-
-	   tempah = 0x3f;
-	   if(SiS_IsDualEdge(SiS_Pr)) {
-	      tempah = 0x7f;
-	      if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
-	   }
-	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-
-	   if((SiS_IsVAMode(SiS_Pr)) ||
-	      ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
-
-	      SiS_DisplayOff(SiS_Pr);
-	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-		 SiS_PanelDelay(SiS_Pr, 2);
-	      }
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
-
-	   }
-
-	   if((!(SiS_IsVAMode(SiS_Pr))) ||
-	      ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
-
-	      if(!(SiS_IsDualEdge(SiS_Pr))) {
-		 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
-		 SiS_DisplayOff(SiS_Pr);
-	      }
-	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-
-	      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-		 SiS_PanelDelay(SiS_Pr, 2);
-	      }
-
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-
-	   }
-
-	   if(SiS_IsNotM650orLater(SiS_Pr)) {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-	   }
-
-	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-
-	      if( (!(SiS_IsVAMode(SiS_Pr)))  &&
-		  (!(SiS_CRT2IsLCD(SiS_Pr))) &&
-		  (!(SiS_IsDualEdge(SiS_Pr))) ) {
-
-		 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
-		 if(!didpwd) {
-		    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-		 }
-		 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
-	      }
-
-	      if(!custom1) {
-		 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
-		 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-		    if(SiS_IsVAorLCD(SiS_Pr)) {
-		       SiS_PanelDelayLoop(SiS_Pr, 3, 20);
-		    }
-		 }
-	      }
-
-	   }
-
-#endif /* CONFIG_FB_SIS_315 */
-
-	}
-
-     } else {     /* ============ For 301 ================ */
-
-        if(SiS_Pr->ChipType < SIS_315H) {
-#ifdef CONFIG_FB_SIS_300
-	   if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
-	      SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
-	      SiS_PanelDelay(SiS_Pr, 3);
-	   }
-#endif
-	}
-
-	SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
-	SiS_DisplayOff(SiS_Pr);
-
-	if(SiS_Pr->ChipType >= SIS_315H) {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	}
-
-	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
-
-	if(SiS_Pr->ChipType >= SIS_315H) {
-	    temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-	} else {
-#ifdef CONFIG_FB_SIS_300
-	    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
-	    if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
-		(!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
-		SiS_PanelDelay(SiS_Pr, 2);
-		SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
-	    }
-#endif
-	}
-
-      }
-
-  } else {     /* ============ For LVDS =============*/
-
-    if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300	/* 300 series */
-
-	if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-	   SiS_SetCH700x(SiS_Pr,0x0E,0x09);
-	}
-
-	if(SiS_Pr->ChipType == SIS_730) {
-	   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
-	      SiS_WaitVBRetrace(SiS_Pr);
-	   }
-	   if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
-	      SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
-	      SiS_PanelDelay(SiS_Pr, 3);
-	   }
-	} else {
-	   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
-	      if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-		 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
-		    SiS_WaitVBRetrace(SiS_Pr);
-		    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
-		       SiS_DisplayOff(SiS_Pr);
-		    }
-		    SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
-		    SiS_PanelDelay(SiS_Pr, 3);
-		 }
-	      }
-	   }
-	}
-
-	SiS_DisplayOff(SiS_Pr);
-
-	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-
-	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	SiS_UnLockCRT2(SiS_Pr);
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
-
-	if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
-	    (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
-	   SiS_PanelDelay(SiS_Pr, 2);
-	   SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
-	}
-
-#endif  /* CONFIG_FB_SIS_300 */
-
-    } else {
-
-#ifdef CONFIG_FB_SIS_315	/* 315 series */
-
-	if(!(SiS_IsNotM650orLater(SiS_Pr))) {
-	   /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
-	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
-	   /* } */
-	}
-
-	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-
-	   if(SiS_Pr->ChipType == SIS_740) {
-	      temp = SiS_GetCH701x(SiS_Pr,0x61);
-	      if(temp < 1) {
-		 SiS_SetCH701x(SiS_Pr,0x76,0xac);
-		 SiS_SetCH701x(SiS_Pr,0x66,0x00);
-	      }
-
-	      if( (!(SiS_IsDualEdge(SiS_Pr))) ||
-		  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
-		 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
-	      }
-	   }
-
-	   if( (!(SiS_IsDualEdge(SiS_Pr))) ||
-	       (SiS_IsVAMode(SiS_Pr)) ) {
-	      SiS_Chrontel701xBLOff(SiS_Pr);
-	      SiS_Chrontel701xOff(SiS_Pr);
-	   }
-
-	   if(SiS_Pr->ChipType != SIS_740) {
-	      if( (!(SiS_IsDualEdge(SiS_Pr))) ||
-		  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
-		 SiS_SetCH701x(SiS_Pr,0x49,0x01);
-	      }
-	   }
-
-	}
-
-	if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	   SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
-	   SiS_PanelDelay(SiS_Pr, 3);
-	}
-
-	if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-	    (!(SiS_IsDualEdge(SiS_Pr))) ||
-	    (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
-	   SiS_DisplayOff(SiS_Pr);
-	}
-
-	if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-	    (!(SiS_IsDualEdge(SiS_Pr))) ||
-	    (!(SiS_IsVAMode(SiS_Pr))) ) {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	}
-
-	if(SiS_Pr->ChipType == SIS_740) {
-	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-	}
-
-	SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-
-	if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-	    (!(SiS_IsDualEdge(SiS_Pr))) ||
-	    (!(SiS_IsVAMode(SiS_Pr))) ) {
-	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	}
-
-	if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	   if(SiS_CRT2IsLCD(SiS_Pr)) {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
-	      if(SiS_Pr->ChipType == SIS_550) {
-		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
-		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
-	      }
-	   }
-	} else {
-	   if(SiS_Pr->ChipType == SIS_740) {
-	      if(SiS_IsLCDOrLCDA(SiS_Pr)) {
-		 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
-	      }
-	   } else if(SiS_IsVAMode(SiS_Pr)) {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
-	   }
-	}
-
-	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	   if(SiS_IsDualEdge(SiS_Pr)) {
-	      /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
-	   } else {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
-	   }
-	}
-
-	SiS_UnLockCRT2(SiS_Pr);
-
-	if(SiS_Pr->ChipType == SIS_550) {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
-	} else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-		   (!(SiS_IsDualEdge(SiS_Pr))) ||
-		   (!(SiS_IsVAMode(SiS_Pr))) ) {
-	   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
-	}
-
-        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	   if(SiS_CRT2IsLCD(SiS_Pr)) {
-	      if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
-		 SiS_PanelDelay(SiS_Pr, 2);
-		 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
-	      }
-	   }
-        }
-
-#endif  /* CONFIG_FB_SIS_315 */
-
-    }  /* 315 series */
-
-  }  /* LVDS */
-
-}
-
-/*********************************************/
-/*            ENABLE VIDEO BRIDGE            */
-/*********************************************/
-
-/* NEVER use any variables (VBInfo), this will be called
- * from outside the context of a mode switch!
- * MUST call getVBType before calling this
- */
-static
-void
-SiS_EnableBridge(struct SiS_Private *SiS_Pr)
-{
-  unsigned short temp=0, tempah;
-#ifdef CONFIG_FB_SIS_315
-  unsigned short temp1, pushax=0;
-  bool delaylong = false;
-#endif
-
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {		/* ====== For 301B et al  ====== */
-
-      if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300     /* 300 series */
-
-	 if(SiS_CRT2IsLCD(SiS_Pr)) {
-	    if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-	       SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
-	    }
-	    if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
-	       if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
-		  SiS_PanelDelay(SiS_Pr, 0);
-	       }
-	    }
-	 }
-
-	 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
-	    (SiS_CRT2IsLCD(SiS_Pr))) {
-
-	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   		/* Enable CRT2 */
-	    SiS_DisplayOn(SiS_Pr);
-	    SiS_UnLockCRT2(SiS_Pr);
-	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
-	    } else {
-	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
-	    }
-	    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-		  if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
-		     SiS_PanelDelay(SiS_Pr, 1);
-		  }
-		  SiS_WaitVBRetrace(SiS_Pr);
-		  SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
-	       }
-	    }
-
-	 } else {
-
-	    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
-	       tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	       if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
-	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
-	    SiS_DisplayOn(SiS_Pr);
-	    if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	       if(SiS_CRT2IsLCD(SiS_Pr)) {
-		  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-		     if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
-		        SiS_PanelDelay(SiS_Pr, 1);
-		     }
-		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-		  }
-	       }
-	    }
-
-	 }
-
-
-#endif /* CONFIG_FB_SIS_300 */
-
-      } else {
-
-#ifdef CONFIG_FB_SIS_315    /* 315 series */
-
-#ifdef SET_EMI
-	 unsigned char   r30=0, r31=0, r32=0, r33=0, cr36=0;
-	 int didpwd = 0;
-	 /* unsigned short  emidelay=0; */
-#endif
-
-	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
-#ifdef SET_EMI
-	    if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-	    }
-#endif
-	 }
-
-	 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
-	    /*if(SiS_Pr->ChipType < SIS_340) { */
-	       tempah = 0x10;
-	       if(SiS_LCDAEnabled(SiS_Pr)) {
-		  if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
-		  else			    tempah = 0x08;
-	       }
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	    /*}*/
-	 }
-
-	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-
-	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-	    SiS_DisplayOff(SiS_Pr);
-	    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
-	    if(IS_SIS740) {
-	       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-	    }
-
-	    didpwd = SiS_HandlePWD(SiS_Pr);
-
-	    if(SiS_IsVAorLCD(SiS_Pr)) {
-	       if(!didpwd) {
-		  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
-		     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
-		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-		     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
-		     if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-		        SiS_GenericDelay(SiS_Pr, 17664);
-		     }
-		  }
-	       } else {
-		  SiS_PanelDelayLoop(SiS_Pr, 3, 2);
-		  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-		     SiS_GenericDelay(SiS_Pr, 17664);
-		  }
-	       }
-	    }
-
-	    if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
-	       SiS_PanelDelayLoop(SiS_Pr, 3, 10);
-	       delaylong = true;
-	    }
-
-	 }
-
-	 if(!(SiS_IsVAMode(SiS_Pr))) {
-
-	    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
-	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
-	       tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	       if(!(tempah & SetCRT2ToRAMDAC)) {
-		  if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
-	       }
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-
-	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
-
-	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-
-	    if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	       SiS_PanelDelay(SiS_Pr, 2);
-	    }
-
-	 } else {
-
-	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
-
-	 }
-
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
-	 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-
-	 if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
-	    if( (SiS_LCDAEnabled(SiS_Pr)) ||
-	        (SiS_CRT2IsLCD(SiS_Pr)) ) {
-	       /* Enable "LVDS PLL power on" (even on 301C) */
-	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
-	       /* Enable "LVDS Driver Power on" (even on 301C) */
-	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
-	    }
-	 }
-
-	 tempah = 0xc0;
-	 if(SiS_IsDualEdge(SiS_Pr)) {
-	    tempah = 0x80;
-	    if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
-	 }
-	 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-
-	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-
-	    SiS_PanelDelay(SiS_Pr, 2);
-
-	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
-	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-
-	    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-#ifdef SET_EMI
-	       if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-		  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		  SiS_GenericDelay(SiS_Pr, 2048);
-	       }
-#endif
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
-
-	       if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-#ifdef SET_EMI
-		  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
-
-		  if(SiS_Pr->SiS_ROMNew) {
-		     unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-		     unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
-		     if(romptr) {
-			SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
-			SiS_Pr->EMI_30 = 0;
-			SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
-			SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
-			SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
-			if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
-			/* emidelay = SISGETROMW((romptr + 0x22)); */
-			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
-		     }
-		  }
-
-		  /*                                              (P4_30|0x40)  */
-		  /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
-		  /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
-		  /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
-		  /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
-		  /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
-		  /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
-		  /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
-		  /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
-		  /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
-
-		  if(SiS_Pr->HaveEMI) {
-		     r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
-		     r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
-		  } else {
-		     r30 = 0;
-		  }
-
-		  /* EMI_30 is read at driver start; however, the BIOS sets this
-		   * (if it is used) only if the LCD is in use. In case we caught
-		   * the machine while on TV output, this bit is not set and we
-		   * don't know if it should be set - hence our detection is wrong.
-		   * Work-around this here:
-		   */
-
-		  if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
-		     switch((cr36 & 0x0f)) {
-		     case 2:
-			r30 |= 0x40;
-			if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
-			if(!SiS_Pr->HaveEMI) {
-			   r31 = 0x05; r32 = 0x60; r33 = 0x33;
-			   if((cr36 & 0xf0) == 0x30) {
-			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;
-			   }
-			}
-			break;
-		     case 3:  /* 1280x1024 */
-			if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
-			if(!SiS_Pr->HaveEMI) {
-			   r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
-			   if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-			      r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
-			   }
-			}
-			break;
-		     case 9:  /* 1400x1050 */
-			r30 |= 0x40;
-			if(!SiS_Pr->HaveEMI) {
-			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
-			   if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
-			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
-			   }
-			}
-			break;
-		     case 11: /* 1600x1200 - unknown */
-			r30 |= 0x40;
-			if(!SiS_Pr->HaveEMI) {
-			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
-			}
-		     }
-                  }
-
-		  /* BIOS values don't work so well sometimes */
-		  if(!SiS_Pr->OverruleEMI) {
-#ifdef COMPAL_HACK
-		     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
-			if((cr36 & 0x0f) == 0x09) {
-			   r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
-			}
- 		     }
-#endif
-#ifdef COMPAQ_HACK
-		     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-			if((cr36 & 0x0f) == 0x03) {
-			   r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
-			}
-		     }
-#endif
-#ifdef ASUS_HACK
-		     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-			if((cr36 & 0x0f) == 0x02) {
-			   /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
-			   /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
-			   /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
-			   /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
-			}
-		     }
-#endif
-		  }
-
-		  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
-		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
-		     SiS_GenericDelay(SiS_Pr, 2048);
-		  }
-		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
-		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
-		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
-#endif	/* SET_EMI */
-
-		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-
-#ifdef SET_EMI
-		  if( (SiS_LCDAEnabled(SiS_Pr)) ||
-		      (SiS_CRT2IsLCD(SiS_Pr)) ) {
-		     if(r30 & 0x40) {
-			/*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
-			SiS_PanelDelayLoop(SiS_Pr, 3, 5);
-			if(delaylong) {
-			   SiS_PanelDelayLoop(SiS_Pr, 3, 5);
-			   delaylong = false;
-			}
-			SiS_WaitVBRetrace(SiS_Pr);
-			SiS_WaitVBRetrace(SiS_Pr);
-			if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-			   SiS_GenericDelay(SiS_Pr, 1280);
-			}
-			SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
-			/*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
-		     }
-		  }
-#endif
-	       }
-	    }
-
-	    if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
-	       if(SiS_IsVAorLCD(SiS_Pr)) {
-		  SiS_PanelDelayLoop(SiS_Pr, 3, 10);
-		  if(delaylong) {
-		     SiS_PanelDelayLoop(SiS_Pr, 3, 10);
-		  }
-		  SiS_WaitVBRetrace(SiS_Pr);
-		  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-		     SiS_GenericDelay(SiS_Pr, 2048);
-		     SiS_WaitVBRetrace(SiS_Pr);
-		  }
-		  if(!didpwd) {
-		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-		  } else {
-		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
-		  }
-	       }
-	    }
-
-	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
-	    SiS_DisplayOn(SiS_Pr);
-	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
-
-	 }
-
-	 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
-	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-	 }
-
-#endif /* CONFIG_FB_SIS_315 */
-
-      }
-
-    } else {	/* ============  For 301 ================ */
-
-       if(SiS_Pr->ChipType < SIS_315H) {
-	  if(SiS_CRT2IsLCD(SiS_Pr)) {
-	     SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
-	     SiS_PanelDelay(SiS_Pr, 0);
-	  }
-       }
-
-       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
-       if(SiS_BridgeInSlavemode(SiS_Pr)) {
-	  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	  if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
-       }
-       SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-
-       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                  /* enable CRT2 */
-
-       if(SiS_Pr->ChipType >= SIS_315H) {
-	  temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-	  if(!(temp & 0x80)) {
-	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
-	  }
-       }
-
-       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);     /* enable VB processor */
-
-       SiS_VBLongWait(SiS_Pr);
-       SiS_DisplayOn(SiS_Pr);
-       if(SiS_Pr->ChipType >= SIS_315H) {
-	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-       }
-       SiS_VBLongWait(SiS_Pr);
-
-       if(SiS_Pr->ChipType < SIS_315H) {
-	  if(SiS_CRT2IsLCD(SiS_Pr)) {
-	     SiS_PanelDelay(SiS_Pr, 1);
-	     SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
-	  }
-       }
-
-    }
-
-  } else {   /* =================== For LVDS ================== */
-
-    if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300    /* 300 series */
-
-       if(SiS_CRT2IsLCD(SiS_Pr)) {
-	  if(SiS_Pr->ChipType == SIS_730) {
-	     SiS_PanelDelay(SiS_Pr, 1);
-	     SiS_PanelDelay(SiS_Pr, 1);
-	     SiS_PanelDelay(SiS_Pr, 1);
-	  }
-	  SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
-	  if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
-	     SiS_PanelDelay(SiS_Pr, 0);
-	  }
-       }
-
-       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-       SiS_DisplayOn(SiS_Pr);
-       SiS_UnLockCRT2(SiS_Pr);
-       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-       if(SiS_BridgeInSlavemode(SiS_Pr)) {
-	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
-       } else {
-	  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
-       }
-
-       if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-	  if(!(SiS_CRT2IsLCD(SiS_Pr))) {
-	     SiS_WaitVBRetrace(SiS_Pr);
-	     SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
-	  }
-       }
-
-       if(SiS_CRT2IsLCD(SiS_Pr)) {
-	  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-	     if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-		if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
-		   SiS_PanelDelay(SiS_Pr, 1);
-		   SiS_PanelDelay(SiS_Pr, 1);
-		}
-		SiS_WaitVBRetrace(SiS_Pr);
-		SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
-	     }
-	  }
-       }
-
-#endif  /* CONFIG_FB_SIS_300 */
-
-    } else {
-
-#ifdef CONFIG_FB_SIS_315    /* 315 series */
-
-       if(!(SiS_IsNotM650orLater(SiS_Pr))) {
-	  /*if(SiS_Pr->ChipType < SIS_340) {*/  /* XGI needs this */
-	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
-	  /*}*/
-       }
-
-       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	  if(SiS_CRT2IsLCD(SiS_Pr)) {
-	     SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
-	     SiS_PanelDelay(SiS_Pr, 0);
-	  }
-       }
-
-       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-       SiS_UnLockCRT2(SiS_Pr);
-
-       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
-
-       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	  temp = SiS_GetCH701x(SiS_Pr,0x66);
-	  temp &= 0x20;
-	  SiS_Chrontel701xBLOff(SiS_Pr);
-       }
-
-       if(SiS_Pr->ChipType != SIS_550) {
-	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-       }
-
-       if(SiS_Pr->ChipType == SIS_740) {
-	  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	     if(SiS_IsLCDOrLCDA(SiS_Pr)) {
-		SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
-	     }
-	  }
-       }
-
-       temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-       if(!(temp1 & 0x80)) {
-	  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
-       }
-
-       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	  if(temp) {
-	     SiS_Chrontel701xBLOn(SiS_Pr);
-	  }
-       }
-
-       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	  if(SiS_CRT2IsLCD(SiS_Pr)) {
-	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
-	     if(SiS_Pr->ChipType == SIS_550) {
-		SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
-		SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
-	     }
-	  }
-       } else if(SiS_IsVAMode(SiS_Pr)) {
-	  if(SiS_Pr->ChipType != SIS_740) {
-	     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
-	  }
-       }
-
-       if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
-	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-       }
-
-       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	  if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
-	     SiS_Chrontel701xOn(SiS_Pr);
-	  }
-	  if( (SiS_IsVAMode(SiS_Pr)) ||
-	      (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
-	     SiS_ChrontelDoSomething1(SiS_Pr);
-	  }
-       }
-
-       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-	  if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
-	     if( (SiS_IsVAMode(SiS_Pr)) ||
-		 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
-		SiS_Chrontel701xBLOn(SiS_Pr);
-		SiS_ChrontelInitTVVSync(SiS_Pr);
-	     }
-	  }
-       } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	  if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
-	     if(SiS_CRT2IsLCD(SiS_Pr)) {
-		SiS_PanelDelay(SiS_Pr, 1);
-		SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
-	     }
-	  }
-       }
-
-#endif  /* CONFIG_FB_SIS_315 */
-
-    } /* 310 series */
-
-  }  /* LVDS */
-
-}
-
-/*********************************************/
-/*         SET PART 1 REGISTER GROUP         */
-/*********************************************/
-
-/* Set CRT2 OFFSET / PITCH */
-static void
-SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RRTI)
-{
-   unsigned short offset;
-   unsigned char  temp;
-
-   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
-
-   offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
-
-   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
-   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
-
-   temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
-   if(offset & 0x07) temp++;
-   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
-}
-
-/* Set CRT2 sync and PanelLink mode */
-static void
-SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
-{
-   unsigned short tempah=0, tempbl, infoflag;
-
-   tempbl = 0xC0;
-
-   if(SiS_Pr->UseCustomMode) {
-      infoflag = SiS_Pr->CInfoFlag;
-   } else {
-      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-   }
-
-   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* LVDS */
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	 tempah = 0;
-      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
-	 tempah = SiS_Pr->SiS_LCDInfo;
-      } else tempah = infoflag >> 8;
-      tempah &= 0xC0;
-      tempah |= 0x20;
-      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-	    (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-	    tempah |= 0xf0;
-	 }
-	 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
-	     (SiS_Pr->SiS_IF_DEF_DSTN) ||
-	     (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
-	     (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
-	     (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
-	    tempah |= 0x30;
-	 }
-	 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
-	     (SiS_Pr->SiS_IF_DEF_DSTN) ) {
-	    tempah &= ~0xc0;
-	 }
-      }
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	 if(SiS_Pr->ChipType >= SIS_315H) {
-	    tempah >>= 3;
-	    tempah &= 0x18;
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
-	    /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
-	 } else {
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
-	 }
-      } else {
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-      }
-
-   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300  /* ---- 300 series --- */
-
-	 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {			/* 630 - 301B(-DH) */
-
-	    tempah = infoflag >> 8;
-	    tempbl = 0;
-	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	       if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-		  tempah = SiS_Pr->SiS_LCDInfo;
-		  tempbl = (tempah >> 6) & 0x03;
-	       }
-	    }
-	    tempah &= 0xC0;
-	    tempah |= 0x20;
-	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-	    tempah |= 0xc0;
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-	    if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-	       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
-	    }
-
-	 } else {							/* 630 - 301 */
-
-	    tempah = ((infoflag >> 8) & 0xc0) | 0x20;
-	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-
-	 }
-
-#endif /* CONFIG_FB_SIS_300 */
-
-      } else {
-
-#ifdef CONFIG_FB_SIS_315  /* ------- 315 series ------ */
-
-	 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {	  		/* 315 - LVDS */
-
-	    tempbl = 0;
-	    if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-	       (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
-	       tempah = infoflag >> 8;
-	       if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-		 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-	       }
-	    } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
-		      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
-	       tempah = infoflag >> 8;
-	       tempbl = 0x03;
-	    } else {
-	       tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-	       tempbl = (tempah >> 6) & 0x03;
-	       tempbl |= 0x08;
-	       if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
-	    }
-	    tempah &= 0xC0;
-	    tempah |= 0x20;
-	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-	    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
-	       }
-	    }
-
-	 } else {							/* 315 - TMDS */
-
-	    tempah = tempbl = infoflag >> 8;
-	    if(!SiS_Pr->UseCustomMode) {
-	       tempbl = 0;
-	       if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-		  if(ModeNo <= 0x13) {
-		     tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
-		  }
-	       }
-	       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-		  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-		    if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-		       tempah = SiS_Pr->SiS_LCDInfo;
-		       tempbl = (tempah >> 6) & 0x03;
-		    }
-		  }
-	       }
-	    }
-	    tempah &= 0xC0;
-	    tempah |= 0x20;
-	    if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-	    if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-	       /* Imitate BIOS bug */
-	       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
-	    }
-	    if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-	       tempah >>= 3;
-	       tempah &= 0x18;
-	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
-	    } else {
-	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-	       if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-		  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
-		  }
-	       }
-	    }
-
-         }
-#endif  /* CONFIG_FB_SIS_315 */
-      }
-   }
-}
-
-/* Set CRT2 FIFO on 300/540/630/730 */
-#ifdef CONFIG_FB_SIS_300
-static void
-SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
-{
-  unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
-  unsigned short temp, index, modeidindex, refreshratetableindex;
-  unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
-  unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
-  unsigned int   data, pci50, pciA0;
-  static const unsigned char colortharray[] = {
-  	1, 1, 2, 2, 3, 4
-  };
-
-  SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
-
-  if(!SiS_Pr->CRT1UsesCustomMode) {
-
-     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
-     SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
-     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
-     SiS_Pr->SiS_SelectCRT2Rate = 0;
-     refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
-
-     if(CRT1ModeNo >= 0x13) {
-        /* Get VCLK */
-	index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
-	VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
-
-	/* Get colordepth */
-	colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
-	if(!colorth) colorth++;
-     }
-
-  } else {
-
-     CRT1ModeNo = 0xfe;
-
-     /* Get VCLK */
-     VCLK = SiS_Pr->CSRClock_CRT1;
-
-     /* Get color depth */
-     colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
-
-  }
-
-  if(CRT1ModeNo >= 0x13) {
-     /* Get MCLK */
-     if(SiS_Pr->ChipType == SIS_300) {
-        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
-     } else {
-        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
-     }
-     index &= 0x07;
-     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
-
-     temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
-     if(!temp) temp++;
-     temp <<= 2;
-
-     data2 = temp - ((colorth * VCLK) / MCLK);
-
-     temp = (28 * 16) % data2;
-     data2 = (28 * 16) / data2;
-     if(temp) data2++;
-
-     if(SiS_Pr->ChipType == SIS_300) {
-
-	SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
-	data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
-
-     } else {
-
-	pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
-	pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
-
-        if(SiS_Pr->ChipType == SIS_730) {
-
-	   index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
-	   index += (unsigned short)(((pci50 >> 9)) & 0x03);
-
-	   /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
-	   index = 0;  /* -- do it like the BIOS anyway... */
-
-	} else {
-
-	   pci50 >>= 24;
-	   pciA0 >>= 24;
-
-	   index = (pci50 >> 1) & 0x07;
-
-	   if(pci50 & 0x01)    index += 6;
-	   if(!(pciA0 & 0x01)) index += 24;
-
-	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
-
-	}
-
-	data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
-	if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
-
-     }
-
-     data += data2;						/* CRT1 Request Period */
-
-     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
-
-     if(!SiS_Pr->UseCustomMode) {
-
-	CRT2ModeNo = ModeNo;
-	SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
-
-	refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
-
-	/* Get VCLK  */
-	index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
-	VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
-
-	if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-	   if(SiS_Pr->SiS_UseROM) {
-	      if(ROMAddr[0x220] & 0x01) {
-		 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
-	      }
-           }
-        }
-
-     } else {
-
-	/* Get VCLK */
-	CRT2ModeNo = 0xfe;
-	VCLK = SiS_Pr->CSRClock;
-
-     }
-
-     /* Get colordepth */
-     colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
-     if(!colorth) colorth++;
-
-     data = data * VCLK * colorth;
-     temp = data % (MCLK << 4);
-     data = data / (MCLK << 4);
-     if(temp) data++;
-
-     if(data < 6) data = 6;
-     else if(data > 0x14) data = 0x14;
-
-     if(SiS_Pr->ChipType == SIS_300) {
-        temp = 0x16;
-	if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
-	   temp = 0x13;
-     } else {
-        temp = 0x16;
-	if(( (SiS_Pr->ChipType == SIS_630) ||
-	     (SiS_Pr->ChipType == SIS_730) )  &&
-	   (SiS_Pr->ChipRevision >= 0x30))
-	   temp = 0x1b;
-     }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
-
-     if((SiS_Pr->ChipType == SIS_630) &&
-	(SiS_Pr->ChipRevision >= 0x30)) {
-	if(data > 0x13) data = 0x13;
-     }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
-
-  } else {  /* If mode <= 0x13, we just restore everything */
-
-     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
-
-  }
-}
-#endif
-
-/* Set CRT2 FIFO on 315/330 series */
-#ifdef CONFIG_FB_SIS_315
-static void
-SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
-{
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
-  if( (SiS_Pr->ChipType == SIS_760)      &&
-      (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
-      (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
-      (SiS_Pr->SiS_VGAHDE >= 1280)	  &&
-      (SiS_Pr->SiS_VGAVDE >= 1024) ) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
-  } else {
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
-  }
-
-}
-#endif
-
-static unsigned short
-SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
-{
-  unsigned int tempax,tempbx;
-
-  tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
-  tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
-  tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
-  return (unsigned short)tempax;
-}
-
-/* Set Part 1 / SiS bridge slave mode */
-static void
-SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
-                  unsigned short RefreshRateTableIndex)
-{
-  unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
-  static const unsigned short CRTranslation[] = {
-       /* CR0   CR1   CR2   CR3   CR4   CR5   CR6   CR7   */
-	  0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
-       /* CR8   CR9   SR0A  SR0B  SR0C  SR0D  SR0E  CR0F  */
-	  0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
-       /* CR10  CR11  CR12  CR13  CR14  CR15  CR16  CR17  */
-	  0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
-  };
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-     xres = SiS_Pr->CHDisplay;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
-  }
-
-  /* The following is only done if bridge is in slave mode: */
-
-  if(SiS_Pr->ChipType >= SIS_315H) {
-     if(xres >= 1600) {  /* BIOS: == 1600 */
-        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
-     }
-  }
-
-  SiS_Pr->CHTotal = 8224;  /* Max HT, 0x2020, results in 0x3ff in registers */
-
-  SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
-
-  SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     SiS_Pr->CHBlankStart += 16;
-  }
-
-  SiS_Pr->CHBlankEnd = 32;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
-  }
-
-  temp = SiS_Pr->SiS_VGAHT - 96;
-  if(!(modeflag & HalfDCLK)) temp -= 32;
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
-     temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
-     temp -= 3;
-     temp <<= 3;
-  } else {
-     if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
-  }
-  SiS_Pr->CHSyncStart = temp;
-
-  SiS_Pr->CHSyncEnd = 0xffe8; 	/* results in 0x2000 in registers */
-
-  SiS_Pr->CVTotal = 2049;  	/* Max VT, 0x0801, results in 0x7ff in registers */
-
-  VGAVDE = SiS_Pr->SiS_VGAVDE;
-  if     (VGAVDE ==  357) VGAVDE =  350;
-  else if(VGAVDE ==  360) VGAVDE =  350;
-  else if(VGAVDE ==  375) VGAVDE =  350;
-  else if(VGAVDE ==  405) VGAVDE =  400;
-  else if(VGAVDE ==  420) VGAVDE =  400;
-  else if(VGAVDE ==  525) VGAVDE =  480;
-  else if(VGAVDE == 1056) VGAVDE = 1024;
-  SiS_Pr->CVDisplay = VGAVDE;
-
-  SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
-
-  SiS_Pr->CVBlankEnd = 1;
-  if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
-
-  temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
-  SiS_Pr->CVSyncStart = VGAVDE + temp;
-
-  temp >>= 3;
-  SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
-
-  SiS_CalcCRRegisters(SiS_Pr, 0);
-  SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
-
-  for(i = 0; i <= 7; i++) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
-  }
-  for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
-  }
-  for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
-  }
-  for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
-  }
-
-  temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
-
-  temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
-  if(modeflag & DoubleScanMode) temp |= 0x80;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
-
-  temp = 0;
-  temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
-  if(modeflag & HalfDCLK) temp |= 0x08;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);              	/* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
-
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);              	/* CR14: (text mode: underline location) */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);              	/* CR17: n/a */
-
-  temp = 0;
-  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-     temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                	/* SR0E, dither[7] */
-
-  temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);			/* ? */
-}
-
-/* Setup panel link
- * This is used for LVDS, LCDA and Chrontel TV output
- * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
- */
-static void
-SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex)
-{
-  unsigned short modeflag, resinfo = 0;
-  unsigned short push2, tempax, tempbx, tempcx, temp;
-  unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
-  bool islvds = false, issis  = false, chkdclkfirst = false;
-#ifdef CONFIG_FB_SIS_300
-  unsigned short crt2crtc = 0;
-#endif
-#ifdef CONFIG_FB_SIS_315
-  unsigned short pushcx;
-#endif
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-#ifdef CONFIG_FB_SIS_300
-     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-#endif
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-#ifdef CONFIG_FB_SIS_300
-     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-#endif
-  }
-
-  /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
-  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-     islvds = true;
-  }
-
-  /* is really sis if sis bridge, but not 301B-DH */
-  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-     issis = true;
-  }
-
-  if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        chkdclkfirst = true;
-     }
-  }
-
-#ifdef CONFIG_FB_SIS_315
-  if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-     if(IS_SIS330) {
-        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
-     } else if(IS_SIS740) {
-        if(islvds) {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
-        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
-        }
-     } else {
-        if(islvds) {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
-        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
-	   if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
-	      if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
-	         (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
-	         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
-	      }
-	   }
-        }
-     }
-  }
-#endif
-
-  /* Horizontal */
-
-  tempax = SiS_Pr->SiS_LCDHDES;
-  if(islvds) {
-     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-	if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
-	   if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
-	      (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
-	      tempax -= 8;
-	   }
-	}
-     }
-  }
-
-  temp = (tempax & 0x0007);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);			/* BPLHDESKEW[2:0]   */
-  temp = (tempax >> 3) & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);			/* BPLHDESKEW[10:3]  */
-
-  tempbx = SiS_Pr->SiS_HDE;
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        tempbx = SiS_Pr->PanelXRes;
-     }
-     if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
-        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
-        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
-        tempbx >>= 1;
-     }
-  }
-
-  tempax += tempbx;
-  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
-
-  temp = tempax;
-  if(temp & 0x07) temp += 8;
-  temp >>= 3;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);			/* BPLHDEE  */
-
-  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
-
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
-     }
-  }
-
-  tempcx += tempax;
-  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
-
-  temp = (tempcx >> 3) & 0x00FF;
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
-	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   switch(ModeNo) {
-	   case 0x04:
-	   case 0x05:
-	   case 0x0d: temp = 0x56; break;
-	   case 0x10: temp = 0x60; break;
-	   case 0x13: temp = 0x5f; break;
-	   case 0x40:
-	   case 0x41:
-	   case 0x4f:
-	   case 0x43:
-	   case 0x44:
-	   case 0x62:
-	   case 0x56:
-	   case 0x53:
-	   case 0x5d:
-	   case 0x5e: temp = 0x54; break;
-	   }
-	}
-     }
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);			/* BPLHRS */
-
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     temp += 2;
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-	temp += 8;
-	if(SiS_Pr->PanelHRE != 999) {
-	   temp = tempcx + SiS_Pr->PanelHRE;
-	   if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
-	   temp >>= 3;
-	}
-     }
-  } else {
-     temp += 10;
-  }
-
-  temp &= 0x1F;
-  temp |= ((tempcx & 0x07) << 5);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);			/* BPLHRE */
-
-  /* Vertical */
-
-  tempax = SiS_Pr->SiS_VGAVDE;
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-	tempax = SiS_Pr->PanelYRes;
-     }
-  }
-
-  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-
-  push2 = tempbx;
-
-  tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
-  if(SiS_Pr->ChipType < SIS_315H) {
-     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-	if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-	   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
-	}
-     }
-  }
-  if(islvds) tempcx >>= 1;
-  else       tempcx >>= 2;
-
-  if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
-      (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) 		    &&
-      (SiS_Pr->PanelVRS != 999) ) {
-     tempcx = SiS_Pr->PanelVRS;
-     tempbx += tempcx;
-     if(issis) tempbx++;
-  } else {
-     tempbx += tempcx;
-     if(SiS_Pr->ChipType < SIS_315H) tempbx++;
-     else if(issis)                   tempbx++;
-  }
-
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-
-  temp = tempbx & 0x00FF;
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	if(ModeNo == 0x10) temp = 0xa9;
-     }
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);			/* BPLVRS */
-
-  tempcx >>= 3;
-  tempcx++;
-
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
-     }
-  }
-
-  tempcx += tempbx;
-  temp = tempcx & 0x000F;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);	/* BPLVRE  */
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-     if(SiS_Pr->SiS_HDE != 640) {
-        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
-     }
-  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
-  tempbx = 0x87;
-  if((SiS_Pr->ChipType >= SIS_315H) ||
-     (SiS_Pr->ChipRevision >= 0x30)) {
-     tempbx = 0x07;
-     if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-	if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
-     }
-     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
-     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
-	} else {
-	   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
-	}
-     }
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
-
-  tempbx = push2;						/* BPLVDEE */
-
-  tempcx = SiS_Pr->SiS_LCDVDES;					/* BPLVDES */
-
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_640x480:
-	tempbx = SiS_Pr->SiS_VGAVDE - 1;
-	tempcx = SiS_Pr->SiS_VGAVDE;
-	break;
-     case Panel_800x600:
-	if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-	   if(resinfo == SIS_RI_800x600) tempcx++;
-	}
-	break;
-     case Panel_1024x600:
-	if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-	   if(resinfo == SIS_RI_1024x600) tempcx++;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	      if(resinfo == SIS_RI_800x600) tempcx++;
-	   }
-	}
-	break;
-     case Panel_1024x768:
-	if(SiS_Pr->ChipType < SIS_315H) {
-	   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-	      if(resinfo == SIS_RI_1024x768) tempcx++;
-	   }
-	}
-	break;
-     }
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp |= ((tempcx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
-
-  /* Vertical scaling */
-
-  if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300      /* 300 series */
-     tempeax = SiS_Pr->SiS_VGAVDE << 6;
-     temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
-     tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
-     if(temp) tempeax++;
-
-     if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
-
-     temp = (unsigned short)(tempeax & 0x00FF);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      	/* BPLVCFACT */
-     tempvcfact = temp;
-#endif /* CONFIG_FB_SIS_300 */
-
-  } else {
-
-#ifdef CONFIG_FB_SIS_315  /* 315 series */
-     tempeax = SiS_Pr->SiS_VGAVDE << 18;
-     tempebx = SiS_Pr->SiS_VDE;
-     temp = (tempeax % tempebx);
-     tempeax = tempeax / tempebx;
-     if(temp) tempeax++;
-     tempvcfact = tempeax;
-
-     temp = (unsigned short)(tempeax & 0x00FF);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
-     temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
-     temp = (unsigned short)((tempeax & 0x00030000) >> 16);
-     if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
-
-     if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
-        temp = (unsigned short)(tempeax & 0x00FF);
-        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
-        temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
-        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
-        temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
-        temp = 0;
-        if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
-     }
-#endif
-
-  }
-
-  /* Horizontal scaling */
-
-  tempeax = SiS_Pr->SiS_VGAHDE;		/* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
-  if(chkdclkfirst) {
-     if(modeflag & HalfDCLK) tempeax >>= 1;
-  }
-  tempebx = tempeax << 16;
-  if(SiS_Pr->SiS_HDE == tempeax) {
-     tempecx = 0xFFFF;
-  } else {
-     tempecx = tempebx / SiS_Pr->SiS_HDE;
-     if(SiS_Pr->ChipType >= SIS_315H) {
-        if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
-     }
-  }
-
-  if(SiS_Pr->ChipType >= SIS_315H) {
-     tempeax = (tempebx / tempecx) - 1;
-  } else {
-     tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
-  }
-  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
-  temp = (unsigned short)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
-
-  if(SiS_Pr->ChipType >= SIS_315H) {
-     tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-     tempbx = (unsigned short)(tempeax & 0xFFFF);
-  } else {
-     tempeax = SiS_Pr->SiS_VGAVDE << 6;
-     tempbx = tempvcfact & 0x3f;
-     if(tempbx == 0) tempbx = 64;
-     tempeax /= tempbx;
-     tempbx = (unsigned short)(tempeax & 0xFFFF);
-  }
-  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
-     else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempecx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
-
-  tempecx >>= 16;						/* BPLHCFACT  */
-  if(!chkdclkfirst) {
-     if(modeflag & HalfDCLK) tempecx >>= 1;
-  }
-  temp = (unsigned short)((tempecx & 0xFF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
-  temp = (unsigned short)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
-
-#ifdef CONFIG_FB_SIS_315
-  if(SiS_Pr->ChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
-           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
-	}
-     } else {
-        if(islvds) {
-           if(SiS_Pr->ChipType == SIS_740) {
-              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
-           } else {
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
-           }
-        }
-     }
-  }
-#endif
-
-#ifdef CONFIG_FB_SIS_300
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
-     unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
-     unsigned char *trumpdata;
-     int   i, j = crt2crtc;
-     unsigned char TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
-     unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
-     unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
-
-     if(SiS_Pr->SiS_UseROM) {
-	trumpdata = &ROMAddr[0x8001 + (j * 80)];
-     } else {
-	if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
-	trumpdata = &SiS300_TrumpionData[j][0];
-     }
-
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
-     for(i=0; i<5; i++) {
-	SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
-     }
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	if(ModeNo == 0x13) {
-	   for(i=0; i<4; i++) {
-	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
-	   }
-	} else if(ModeNo == 0x10) {
-	   for(i=0; i<4; i++) {
-	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
-	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
-	   }
-	}
-     }
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
-  }
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
-     tempax = SiS_Pr->SiS_HDE;					/* Blps = lcdhdee(lcdhdes+HDE) + 64 */
-     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
-     tempax += 64;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
-     temp = (tempax >> 8) << 3;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
-     tempax += 32;						/* Blpe = lBlps+32 */
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);		/* Bflml = 0 */
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
-
-     tempax = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
-     tempax >>= 1;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
-     temp = (tempax >> 8) << 3;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
-
-     tempeax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
-     tempeax <<= 2;			 			/* BDxFIFOSTOP = (HDE*4)/128 */
-     temp = tempeax & 0x7f;
-     tempeax >>= 7;
-     if(temp) tempeax++;
-     temp = tempeax & 0x3f;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);		/* BDxWadrst0 */
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
-
-     tempax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
-     tempax >>= 4;						/* BDxWadroff = HDE*4/8/8 */
-     pushcx = tempax;
-     temp = tempax & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
-     temp = ((tempax & 0xFF00) >> 8) << 3;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
-
-     tempax = SiS_Pr->SiS_VDE;				 	/* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
-     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
-     tempeax = tempax * pushcx;
-     temp = tempeax & 0xFF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
-     temp = (tempeax & 0xFF00) >> 8;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
-     temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
-     temp = ((tempeax & 0x01000000) >> 24) << 7;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
-
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
-
-     if(SiS_Pr->SiS_IF_DEF_FSTN) {
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
-     }
-  }
-#endif  /* CONFIG_FB_SIS_315 */
-}
-
-/* Set Part 1 */
-static void
-SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex)
-{
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-  unsigned char   *ROMAddr = SiS_Pr->VirtualRomBase;
-#endif
-  unsigned short  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
-  unsigned short  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
-#ifdef CONFIG_FB_SIS_315
-  unsigned short  tempbl=0;
-#endif
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-     return;
-  }
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
-
-  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-
-  if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
-         (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
-         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
-
-     if(SiS_Pr->ChipType < SIS_315H ) {
-#ifdef CONFIG_FB_SIS_300
-	SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
-#endif
-     } else {
-#ifdef CONFIG_FB_SIS_315
-	SiS_SetCRT2FIFO_310(SiS_Pr);
-#endif
-     }
-
-     /* 1. Horizontal setup */
-
-     if(SiS_Pr->ChipType < SIS_315H ) {
-
-#ifdef CONFIG_FB_SIS_300   /* ------------- 300 series --------------*/
-
-	temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   		  /* BTVGA2HT 0x08,0x09 */
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
-
-	temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
-
-	temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
-
-	pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
-	tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
-	tempbx = pushbx + tempcx;
-	tempcx <<= 1;
-	tempcx += tempbx;
-
-	bridgeadd = 12;
-
-#endif /* CONFIG_FB_SIS_300 */
-
-     } else {
-
-#ifdef CONFIG_FB_SIS_315  /* ------------------- 315/330 series --------------- */
-
-	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HT 0x08,0x09 */
-	if(modeflag & HalfDCLK) {
-	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	      tempcx >>= 1;
-	   } else {
-	      tempax = SiS_Pr->SiS_VGAHDE >> 1;
-	      tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	         tempcx = SiS_Pr->SiS_HT - tempax;
-	      }
-	   }
-	}
-	tempcx--;
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
-	temp = (tempcx >> 4) & 0xF0;
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
-
-	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HDEE 0x0A,0x0C */
-	tempbx = SiS_Pr->SiS_VGAHDE;
-	tempcx -= tempbx;
-	tempcx >>= 2;
-	if(modeflag & HalfDCLK) {
-	   tempbx >>= 1;
-	   tempcx >>= 1;
-	}
-	tempbx += 16;
-
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
-
-	pushbx = tempbx;
-	tempcx >>= 1;
-	tempbx += tempcx;
-	tempcx += tempbx;
-
-	bridgeadd = 16;
-
-	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	   if(SiS_Pr->ChipType >= SIS_661) {
-	      if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
-		 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
-		 if(resinfo == SIS_RI_1280x1024) {
-		    tempcx = (tempcx & 0xff00) | 0x30;
-		 } else if(resinfo == SIS_RI_1600x1200) {
-		    tempcx = (tempcx & 0xff00) | 0xff;
-		 }
-	      }
-	   }
-        }
-
-#endif  /* CONFIG_FB_SIS_315 */
-
-     }  /* 315/330 series */
-
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-	if(SiS_Pr->UseCustomMode) {
-	   tempbx = SiS_Pr->CHSyncStart + bridgeadd;
-	   tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
-	   tempax = SiS_Pr->SiS_VGAHT;
-	   if(modeflag & HalfDCLK) tempax >>= 1;
-	   tempax--;
-	   if(tempcx > tempax) tempcx = tempax;
-	}
-
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	   unsigned char cr4, cr14, cr5, cr15;
-	   if(SiS_Pr->UseCustomMode) {
-	      cr4  = SiS_Pr->CCRT1CRTC[4];
-	      cr14 = SiS_Pr->CCRT1CRTC[14];
-	      cr5  = SiS_Pr->CCRT1CRTC[5];
-	      cr15 = SiS_Pr->CCRT1CRTC[15];
-	   } else {
-	      cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-	      cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-	      cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-	      cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-	   }
-	   tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		    /* (VGAHRS-3)*8 */
-	   tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
-	   tempcx &= 0x00FF;
-	   tempcx |= (tempbx & 0xFF00);
-	   tempbx += bridgeadd;
-	   tempcx += bridgeadd;
-	   tempax = SiS_Pr->SiS_VGAHT;
-	   if(modeflag & HalfDCLK) tempax >>= 1;
-	   tempax--;
-	   if(tempcx > tempax) tempcx = tempax;
-	}
-
-	if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
-	   tempbx = 1040;
-	   tempcx = 1044;   /* HWCursor bug! */
-	}
-
-     }
-
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);            	  /* CRT2 Horizontal Retrace Start */
-
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
-
-     temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);		  /* Overflow */
-
-     /* 2. Vertical setup */
-
-     tempcx = SiS_Pr->SiS_VGAVT - 1;
-     temp = tempcx & 0x00FF;
-
-     if(SiS_Pr->ChipType < SIS_661) {
-        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	   if(SiS_Pr->ChipType < SIS_315H) {
-	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
-	            temp--;
-	         }
-	      }
-	   } else {
-	      temp--;
-	   }
-	} else if(SiS_Pr->ChipType >= SIS_315H) {
-	   temp--;
-	}
-     }
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
-
-     tempbx = SiS_Pr->SiS_VGAVDE - 1;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
-
-     temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
-
-     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
-	tempbx++;
-	tempax = tempbx;
-	tempcx++;
-	tempcx -= tempax;
-	tempcx >>= 2;
-	tempbx += tempcx;
-	if(tempcx < 4) tempcx = 4;
-	tempcx >>= 2;
-	tempcx += tempbx;
-	tempcx++;
-     } else {
-	tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
-	tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
-     }
-
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	if(SiS_Pr->UseCustomMode) {
-	   tempbx = SiS_Pr->CVSyncStart;
-	   tempcx = SiS_Pr->CVSyncEnd;
-	}
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	   unsigned char cr8, cr7, cr13;
-	   if(SiS_Pr->UseCustomMode) {
-	      cr8    = SiS_Pr->CCRT1CRTC[8];
-	      cr7    = SiS_Pr->CCRT1CRTC[7];
-	      cr13   = SiS_Pr->CCRT1CRTC[13];
-	      tempcx = SiS_Pr->CCRT1CRTC[9];
-	   } else {
-	      cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
-	      cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
-	      cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
-	      tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
-	   }
-	   tempbx = cr8;
-	   if(cr7  & 0x04) tempbx |= 0x0100;
-	   if(cr7  & 0x80) tempbx |= 0x0200;
-	   if(cr13 & 0x08) tempbx |= 0x0400;
-	}
-     }
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
-
-     temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
-
-     /* 3. Panel delay compensation */
-
-     if(SiS_Pr->ChipType < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300  /* ---------- 300 series -------------- */
-
-	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	   temp = 0x20;
-	   if(SiS_Pr->ChipType == SIS_300) {
-	      temp = 0x10;
-	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
-	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
-	   }
-	   if(SiS_Pr->SiS_VBType & VB_SIS301) {
-	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
-	   }
-	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
-	   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 	    temp = 0x08;
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	    temp = 0x2c;
-	      else 					    temp = 0x20;
-	   }
-	   if(SiS_Pr->SiS_UseROM) {
-	      if(ROMAddr[0x220] & 0x80) {
-		 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
-		    temp = ROMAddr[0x221];
-		 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
-		    temp = ROMAddr[0x222];
-		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
-		    temp = ROMAddr[0x223];
-		 else
-		    temp = ROMAddr[0x224];
-	      }
-	   }
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	      if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC;
-	   }
-
-	} else {
-	   temp = 0x20;
-	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-	      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
-	   }
-	   if(SiS_Pr->SiS_UseROM) {
-	      if(ROMAddr[0x220] & 0x80) {
-	         temp = ROMAddr[0x220];
-	      }
-	   }
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	      if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
-	   }
-	}
-
-	temp &= 0x3c;
-
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
-
-#endif  /* CONFIG_FB_SIS_300 */
-
-     } else {
-
-#ifdef CONFIG_FB_SIS_315   /* --------------- 315/330 series ---------------*/
-
-	if(SiS_Pr->ChipType < SIS_661) {
-
-	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-
-	      if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
-	      else 		              temp = 0x00;
-
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
-	      tempbl = 0xF0;
-	      if(SiS_Pr->ChipType == SIS_650) {
-		 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-		    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
-		 }
-	      }
-
-	      if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
-		 temp = 0x08;
-		 tempbl = 0;
-		 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-		    if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
-		 }
-	      }
-
-	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);	    /* Panel Link Delay Compensation */
-	   }
-
-	} /* < 661 */
-
-	tempax = 0;
-	if(modeflag & DoubleScanMode) tempax |= 0x80;
-	if(modeflag & HalfDCLK)       tempax |= 0x40;
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
-
-#endif  /* CONFIG_FB_SIS_315 */
-
-     }
-
-  }  /* Slavemode */
-
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-	/* For 301BDH with LCD, we set up the Panel Link */
-	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-     } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-     }
-  } else {
-     if(SiS_Pr->ChipType < SIS_315H) {
-	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-     } else {
-	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	   if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
-	   }
-	} else {
-	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
-	}
-     }
-  }
-}
-
-/*********************************************/
-/*         SET PART 2 REGISTER GROUP         */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_315
-static unsigned char *
-SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
-{
-   const unsigned char *tableptr = NULL;
-   unsigned short      a, b, p = 0;
-
-   a = SiS_Pr->SiS_VGAHDE;
-   b = SiS_Pr->SiS_HDE;
-   if(tabletype) {
-      a = SiS_Pr->SiS_VGAVDE;
-      b = SiS_Pr->SiS_VDE;
-   }
-
-   if(a < b) {
-      tableptr = SiS_Part2CLVX_1;
-   } else if(a == b) {
-      tableptr = SiS_Part2CLVX_2;
-   } else {
-      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	 tableptr = SiS_Part2CLVX_4;
-      } else {
-	 tableptr = SiS_Part2CLVX_3;
-      }
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	tableptr = SiS_Part2CLVX_3;
-	 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) 	tableptr = SiS_Part2CLVX_3;
-	 else 				         	tableptr = SiS_Part2CLVX_5;
-      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	 tableptr = SiS_Part2CLVX_6;
-      }
-      do {
-	 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
-	 p += 0x42;
-      } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
-      if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
-   }
-   p += 2;
-   return ((unsigned char *)&tableptr[p]);
-}
-
-static void
-SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-	      	    unsigned short RefreshRateTableIndex)
-{
-   unsigned char *tableptr;
-   unsigned char temp;
-   int i, j;
-
-   if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
-
-   tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
-   for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
-   }
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-      tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
-      for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
-         SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
-      }
-   }
-   temp = 0x10;
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
-   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
-}
-
-static bool
-SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
-		    unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
-		    unsigned short *ResIndex)
-{
-
-  if(SiS_Pr->ChipType < SIS_315H) return false;
-
-  if(ModeNo <= 0x13)
-     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  (*ResIndex) &= 0x3f;
-  (*CRT2Index) = 0;
-
-  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        (*CRT2Index) = 200;
-     }
-  }
-
-  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
-     }
-  }
-  return (((*CRT2Index) != 0));
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_300
-static void
-SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
-{
-   unsigned short tempcx;
-   static const unsigned char atable[] = {
-       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
-       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
-   };
-
-   if(!SiS_Pr->UseCustomMode) {
-      if( ( ( (SiS_Pr->ChipType == SIS_630) ||
-	      (SiS_Pr->ChipType == SIS_730) ) &&
-	    (SiS_Pr->ChipRevision > 2) )  &&
-	  (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
-	  (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
-	  (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-	 if(ModeNo == 0x13) {
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
-	 } else if((crt2crtc & 0x3F) == 4) {
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
-	 }
-      }
-
-      if(SiS_Pr->ChipType < SIS_315H) {
-	 if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
-	    crt2crtc &= 0x1f;
-	    tempcx = 0;
-	    if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-		  tempcx += 7;
-	       }
-	    }
-	    tempcx += crt2crtc;
-	    if(crt2crtc >= 4) {
-	       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
-	    }
-
-	    if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-		  if(crt2crtc == 4) {
-		     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
-		  }
-	       }
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
-	 }
-      }
-   }
-}
-
-/* For ECS A907. Highly preliminary. */
-static void
-SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
-		    unsigned short ModeNo)
-{
-  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
-  unsigned short crt2crtc, resindex;
-  int i, j;
-
-  if(SiS_Pr->ChipType != SIS_300) return;
-  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
-  if(SiS_Pr->UseCustomMode) return;
-
-  if(ModeNo <= 0x13) {
-     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
-
-  resindex = crt2crtc & 0x3F;
-  if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
-  else                                    CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
-
-  /* The BIOS code (1.16.51,56) is obviously a fragment! */
-  if(ModeNo > 0x13) {
-     CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
-     resindex = 4;
-  }
-
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
-  for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
-  }
-  for(j = 0x1c; j <= 0x1d; i++, j++ ) {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
-  }
-  for(j = 0x1f; j <= 0x21; i++, j++ ) {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
-}
-#endif
-
-static void
-SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
-  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
-
-  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-     if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-        const unsigned char specialtv[] = {
-		0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
-		0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
-		0x58,0xe4,0x73,0xda,0x13
-	};
-	int i, j;
-	for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
-	}
-	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
-	if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
-	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
-	   } else {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
-	   }
-	}
-     }
-  } else {
-     if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
-        (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
-     } else {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
-     }
-  }
-}
-
-static void
-SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-  unsigned short temp;
-
-  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-     if(SiS_Pr->SiS_VGAVDE == 525) {
-	temp = 0xc3;
-	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	   temp++;
-	   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
-	}
-	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
-     } else if(SiS_Pr->SiS_VGAVDE == 420) {
-	temp = 0x4d;
-	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	   temp++;
-	   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
-	}
-	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-     }
-  }
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
-	if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
-	   /* Not always for LV, see SetGrp2 */
-	}
-	temp = 1;
-	if(ModeNo <= 0x13) temp = 3;
-	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
-     }
-#if 0
-     /* 651+301C, for 1280x768 - do I really need that? */
-     if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
-        if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
-	   if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
-	      ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
-	      SiS_SetReg(SiS_Part2Port,0x01,0x2b);
-	      SiS_SetReg(SiS_Part2Port,0x02,0x13);
-	      SiS_SetReg(SiS_Part2Port,0x04,0xe5);
-	      SiS_SetReg(SiS_Part2Port,0x05,0x08);
-	      SiS_SetReg(SiS_Part2Port,0x06,0xe2);
-	      SiS_SetReg(SiS_Part2Port,0x1c,0x21);
-	      SiS_SetReg(SiS_Part2Port,0x1d,0x45);
-	      SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
-	      SiS_SetReg(SiS_Part2Port,0x20,0x00);
-	      SiS_SetReg(SiS_Part2Port,0x21,0xa9);
-	      SiS_SetReg(SiS_Part2Port,0x23,0x0b);
-	      SiS_SetReg(SiS_Part2Port,0x25,0x04);
-	   }
-	}
-     }
-#endif
-  }
-}
-
-static void
-SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex)
-{
-  unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
-  unsigned short push2, modeflag, crt2crtc, bridgeoffset;
-  unsigned int   longtemp, PhaseIndex;
-  bool           newtvphase;
-  const unsigned char *TimingPoint;
-#ifdef CONFIG_FB_SIS_315
-  unsigned short resindex, CRT2Index;
-  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
-#endif
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-     crt2crtc = 0;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
-
-  temp = 0;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
-
-  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) 	      temp |= 0x10;
-
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
-
-  PhaseIndex  = 0x01; /* SiS_PALPhase */
-  TimingPoint = SiS_Pr->SiS_PALTiming;
-
-  newtvphase = false;
-  if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
-      ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-	(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-     newtvphase = true;
-  }
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-
-     TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
-     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
-        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-	   TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
-        }
-     }
-
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-
-     i = 0;
-     if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      i = 2;
-     else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
-
-     TimingPoint = &SiS_YPbPrTable[i][0];
-
-     PhaseIndex = 0x00; /* SiS_NTSCPhase */
-
-  } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-
-     if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
-
-  } else {
-
-     TimingPoint = SiS_Pr->SiS_NTSCTiming;
-     PhaseIndex  = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00;	/* SiS_PALPhase : SiS_NTSCPhase */
-     if(newtvphase) PhaseIndex += 8;					/* SiS_PALPhase2 : SiS_NTSCPhase2 */
-
-  }
-
-  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
-     PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03;	/* SiS_PALMPhase : SiS_PALNPhase */
-     if(newtvphase) PhaseIndex += 8;					/* SiS_PALMPhase2 : SiS_PALNPhase2 */
-  }
-
-  if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-     if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-        PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
-     } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-        PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
-     } else {
-        PhaseIndex = 0x10; /* SiS_SpecialPhase */
-     }
-  }
-
-  for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
-  }
-
-  for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
-  }
-  for(i = 0x39; i <= 0x45; i++, j++) {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
-  }
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(SiS_Pr->SiS_ModeType != ModeText) {
-        SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
-     }
-  }
-
-  SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
-
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)	tempax = 950;
-  else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  tempax = 680;
-  else if(SiS_Pr->SiS_TVMode & TVSetPAL)	tempax = 520;
-  else						tempax = 440; /* NTSC, YPbPr 525 */
-
-  if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
-      ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
-        ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
-
-     tempax -= SiS_Pr->SiS_VDE;
-     tempax >>= 1;
-     if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
-        tempax >>= 1;
-     }
-     tempax &= 0x00ff;
-
-     temp = tempax + (unsigned short)TimingPoint[0];
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
-
-     temp = tempax + (unsigned short)TimingPoint[1];
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
-
-     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
-        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
-        } else {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
-        }
-     }
-
-  }
-
-  tempcx = SiS_Pr->SiS_HT;
-  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
-  tempcx--;
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
-
-  tempcx = SiS_Pr->SiS_HT >> 1;
-  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
-  tempcx += 7;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
-
-  tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
-  tempbx += tempcx;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
-
-  tempbx += 8;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     tempbx -= 4;
-     tempcx = tempbx;
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
-
-  j += 2;
-  tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
-
-  tempcx += 8;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
-
-  tempcx = SiS_Pr->SiS_HT >> 1;
-  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
-  j += 2;
-  tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
-
-  tempcx -= 11;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-     tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
-
-  tempbx = SiS_Pr->SiS_VDE;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
-     if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
-     if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
-  } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
-             (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
-     tempbx >>= 1;
-     if(SiS_Pr->ChipType >= SIS_315H) {
-        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-	   if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
-	} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	   if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	      if(crt2crtc == 4) tempbx++;
-	   }
-	}
-     }
-     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	   if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
-	}
-	if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	   if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
-        }
-     }
-  }
-  tempbx -= 2;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
-
-  temp = (tempcx >> 8) & 0x0F;
-  temp |= ((tempbx >> 2) & 0xC0);
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
-     temp |= 0x10;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
-
-  if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
-  }
-
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-     tempbx = SiS_Pr->SiS_VDE;
-     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
-         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
-        tempbx >>= 1;
-     }
-     tempbx -= 3;
-     temp = ((tempbx >> 3) & 0x60) | 0x18;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
-
-     if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
-     }
-  }
-
-  tempbx = 0;
-  if(!(modeflag & HalfDCLK)) {
-     if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
-        tempax = 0;
-        tempbx |= 0x20;
-     }
-  }
-
-  tempch = tempcl = 0x01;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(SiS_Pr->SiS_VGAHDE >= 960) {
-        if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
-	   tempcl = 0x20;
-	   if(SiS_Pr->SiS_VGAHDE >= 1280) {
-              tempch = 20;
-              tempbx &= ~0x20;
-           } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
-              tempch = 25;
-           } else {
-	      tempch = 25; /* OK */
-	   }
-        }
-     }
-  }
-
-  if(!(tempbx & 0x20)) {
-     if(modeflag & HalfDCLK) tempcl <<= 1;
-     longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
-     tempax = longtemp / SiS_Pr->SiS_HDE;
-     if(longtemp % SiS_Pr->SiS_HDE) tempax++;
-     tempbx |= ((tempax >> 8) & 0x1F);
-     tempcx = tempax >> 13;
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
-
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-
-     tempcx &= 0x07;
-     if(tempbx & 0x20) tempcx = 0;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
-
-     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-        tempbx = 0x0382;
-        tempcx = 0x007e;
-     } else {
-        tempbx = 0x0369;
-        tempcx = 0x0061;
-     }
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
-     temp = (tempcx & 0x0300) >> 6;
-     temp |= ((tempbx >> 8) & 0x03);
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-        temp |= 0x10;
-	if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)      temp |= 0x20;
-	else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
-     }
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
-
-     temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
-
-     SiS_SetTVSpecial(SiS_Pr, ModeNo);
-
-     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
-        temp = 0;
-        if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
-     }
-
-  }
-
-  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-     if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
-        temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
-     }
-     SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
-  }
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
-     }
-  }
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
-
-  /* From here: Part2 LCD setup */
-
-  tempbx = SiS_Pr->SiS_HDE;
-  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
-  tempbx--;			         	/* RHACTE = HDE - 1 */
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
-
-  temp = 0x01;
-  if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-     if(SiS_Pr->SiS_ModeType == ModeEGA) {
-        if(SiS_Pr->SiS_VGAHDE >= 1024) {
-           temp = 0x02;
-           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-              temp = 0x01;
-	   }
-        }
-     }
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
-
-  tempbx = SiS_Pr->SiS_VDE - 1;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
-
-  tempcx = SiS_Pr->SiS_VT - 1;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
-  temp = (tempcx >> 3) & 0xE0;
-  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-     /* Enable dithering; only do this for 32bpp mode */
-     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
-        temp |= 0x10;
-     }
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
-
-  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
-  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
-
-  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
-  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
-
-#ifdef CONFIG_FB_SIS_315
-  if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          			&CRT2Index, &resindex)) {
-      switch(CRT2Index) {
-        case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
-	default:
-        case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
-      }
-
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
-      for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
-      }
-      for(j = 0x1c; j <= 0x1d; i++, j++ ) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
-      }
-      for(j = 0x1f; j <= 0x21; i++, j++ ) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
-      }
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
-
-      SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
-
-  } else {
-#endif
-
-    /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
-    /*             Clevo dual-link 1024x768 */
-    /* 		   Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
-    /*		   Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
-
-    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-       if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
-          tempbx = SiS_Pr->SiS_VDE - 1;
-          tempcx = SiS_Pr->SiS_VT - 1;
-       } else {
-          tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
-	  tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
-       }
-    } else {
-       tempbx = SiS_Pr->PanelYRes;
-       tempcx = SiS_Pr->SiS_VT;
-       tempax = 1;
-       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
-          tempax = SiS_Pr->PanelYRes;
-	  /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
-          if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
-             tempax = tempcx = 0;
-          } else {
-             tempax -= SiS_Pr->SiS_VDE;
-          }
-          tempax >>= 1;
-       }
-       tempcx -= tempax; /* lcdvdes */
-       tempbx -= tempax; /* lcdvdee */
-    }
-
-    /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
-
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);	/* lcdvdes  */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);	/* lcdvdee  */
-
-    temp = (tempbx >> 5) & 0x38;
-    temp |= ((tempcx >> 8) & 0x07);
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
-
-    tempax = SiS_Pr->SiS_VDE;
-    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-       tempax = SiS_Pr->PanelYRes;
-    }
-    tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
-    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
-	  tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
-       }
-    }
-
-    tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
-    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
-          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
-             tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
-	     if(tempax % 4) { tempax >>= 2; tempax++; }
-	     else           { tempax >>= 2;           }
-             tempbx -= (tempax - 1);
-	  } else {
-	     tempbx -= 10;
-	     if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
-	  }
-       }
-    }
-    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-       tempbx++;
-       if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
-          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-	     tempbx = 770;
-	     tempcx = 3;
-	  }
-       }
-    }
-
-    /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
-
-    if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CVSyncStart;
-    }
-
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);	    /* lcdvrs */
-
-    temp = (tempbx >> 4) & 0xF0;
-    tempbx += (tempcx + 1);
-    temp |= (tempbx & 0x0F);
-
-    if(SiS_Pr->UseCustomMode) {
-       temp &= 0xf0;
-       temp |= (SiS_Pr->CVSyncEnd & 0x0f);
-    }
-
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
-
-#ifdef CONFIG_FB_SIS_300
-    SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
-#endif
-
-    bridgeoffset = 7;
-    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)	bridgeoffset += 2;
-    if(SiS_Pr->SiS_VBType & VB_SIS30xCLV)	bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
-    if(SiS_IsDualLink(SiS_Pr))			bridgeoffset++;
-    else if(SiS_Pr->SiS_VBType & VB_SIS302LV)	bridgeoffset++;    /* OK for Asus A4L 1280x800 */
-    /* Higher bridgeoffset shifts to the LEFT */
-
-    temp = 0;
-    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
-	  temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
-	  if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
-       }
-    }
-    temp += bridgeoffset;
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	     /* lcdhdes */
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
-
-    tempcx = SiS_Pr->SiS_HT;
-    tempax = tempbx = SiS_Pr->SiS_HDE;
-    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
-          tempax = SiS_Pr->PanelXRes;
-          tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
-       }
-    }
-    if(SiS_IsDualLink(SiS_Pr)) {
-       tempcx >>= 1;
-       tempbx >>= 1;
-       tempax >>= 1;
-    }
-
-    tempbx += bridgeoffset;
-
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);	    /* lcdhdee */
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
-
-    tempcx = (tempcx - tempax) >> 2;
-
-    tempbx += tempcx;
-    push2 = tempbx;
-
-    if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-             if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
-	  }
-       }
-    }
-
-    if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncStart;
-       if(modeflag & HalfDCLK) tempbx <<= 1;
-       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
-       tempbx += bridgeoffset;
-    }
-
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);	    /* lcdhrs */
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
-
-    tempbx = push2;
-
-    tempcx <<= 1;
-    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
-    }
-    tempbx += tempcx;
-
-    if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncEnd;
-       if(modeflag & HalfDCLK) tempbx <<= 1;
-       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
-       tempbx += bridgeoffset;
-    }
-
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);	    /* lcdhre */
-
-    SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
-
-#ifdef CONFIG_FB_SIS_300
-    SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
-#endif
-#ifdef CONFIG_FB_SIS_315
-  } /* CRT2-LCD from table */
-#endif
-}
-
-/*********************************************/
-/*         SET PART 3 REGISTER GROUP         */
-/*********************************************/
-
-static void
-SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned short i;
-  const unsigned char *tempdi;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
-
-#ifndef SIS_CP
-  SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
-#else
-  SIS_CP_INIT301_CP
-#endif
-
-  if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
-     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
-  } else {
-     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
-     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
-  }
-
-  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
-     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
-     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
-  }
-
-  tempdi = NULL;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     tempdi = SiS_Pr->SiS_HiTVGroup3Data;
-     if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-        tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
-     }
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-     if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
-        tempdi = SiS_HiTVGroup3_1;
-        if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
-     }
-  }
-  if(tempdi) {
-     for(i=0; i<=0x3E; i++) {
-        SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
-     }
-     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
-	if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-	   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
-	}
-     }
-  }
-
-#ifdef SIS_CP
-  SIS_CP_INIT301_CP2
-#endif
-}
-
-/*********************************************/
-/*         SET PART 4 REGISTER GROUP         */
-/*********************************************/
-
-#ifdef CONFIG_FB_SIS_315
-#if 0
-static void
-SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
-{
-   unsigned short temp, temp1, temp2;
-
-   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
-   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
-   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
-   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
-   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
-   temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
-   temp = (unsigned short)((int)(temp) + shift);
-   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
-   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
-   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
-   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
-   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
-   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
-}
-#endif
-
-static void
-SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-   unsigned short temp, temp1, resinfo = 0;
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-
-   if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
-   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
-
-   if(SiS_Pr->ChipType >= XGI_20) return;
-
-   if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
-      if(!(ROMAddr[0x61] & 0x04)) return;
-   }
-
-   if(ModeNo > 0x13) {
-      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-   }
-
-   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
-   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
-   if(!(temp & 0x01)) {
-      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
-      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
-      if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
-         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
-      }
-      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
-      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
-      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
-      else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
-      else					   temp = 0x0402;
-      if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
-         temp1 = 0;
-	 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
-	 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
-	 if(ModeNo > 0x13) {
-            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
-         }
-      } else {
-         temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
-	 if(temp1 == 0x01) temp |= 0x01;
-	 if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
-	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
-	 if(ModeNo > 0x13) {
-            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
-         }
-      }
-
-#if 0
-      if(SiS_Pr->ChipType >= SIS_661) { 		/* ? */
-         if(SiS_Pr->SiS_TVMode & TVAspect43) {
-            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
-	       if(resinfo == SIS_RI_1024x768) {
-	          SiS_ShiftXPos(SiS_Pr, 97);
-	       } else {
-	          SiS_ShiftXPos(SiS_Pr, 111);
-	       }
-	    } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
-	       SiS_ShiftXPos(SiS_Pr, 136);
-	    }
-         }
-      }
-#endif
-
-   }
-
-}
-#endif
-
-static void
-SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-                 unsigned short RefreshRateTableIndex)
-{
-  unsigned short vclkindex, temp, reg1, reg2;
-
-  if(SiS_Pr->UseCustomMode) {
-     reg1 = SiS_Pr->CSR2B;
-     reg2 = SiS_Pr->CSR2C;
-  } else {
-     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-     reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
-     reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
-  }
-
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-     if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
-        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
- 	SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
-	SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
-     } else {
-        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
-        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
-     }
-  } else {
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
-  temp = 0x08;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
-  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
-}
-
-static void
-SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
-{
-  if(SiS_Pr->ChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
-	if((SiS_CRT2IsLCD(SiS_Pr)) ||
-	   (SiS_IsVAMode(SiS_Pr))) {
-	   if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
-	      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
-	   } else {
-	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
-	   }
-	}
-     }
-  }
-  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
-     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-  }
-}
-
-static void
-SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex)
-{
-  unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
-  unsigned int   tempebx, tempeax, templong;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-     resinfo = 0;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
-
-  if(SiS_Pr->ChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
-	}
-     }
-  }
-
-  if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
-     }
-  }
-
-  if(SiS_Pr->ChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	SiS_SetDualLinkEtc(SiS_Pr);
-	return;
-     }
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
-
-  tempbx = SiS_Pr->SiS_RVBHCMAX;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
-
-  temp = (tempbx >> 1) & 0x80;
-
-  tempcx = SiS_Pr->SiS_VGAHT - 1;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
-
-  temp |= ((tempcx >> 5) & 0x78);
-
-  tempcx = SiS_Pr->SiS_VGAVT - 1;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
-
-  temp |= ((tempcx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
-
-  tempbx = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK)    tempbx >>= 1;
-  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     temp = 0;
-     if(tempbx > 800)        temp = 0x60;
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     temp = 0;
-     if(tempbx > 1024)       temp = 0xC0;
-     else if(tempbx >= 960)  temp = 0xA0;
-  } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
-     temp = 0;
-     if(tempbx >= 1280)      temp = 0x40;
-     else if(tempbx >= 1024) temp = 0x20;
-  } else {
-     temp = 0x80;
-     if(tempbx >= 1024)      temp = 0xA0;
-  }
-
-  temp |= SiS_Pr->Init_P4_0E;
-
-  if(SiS_Pr->SiS_VBType & VB_SIS301) {
-     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
-        temp &= 0xf0;
-        temp |= 0x0A;
-     }
-  }
-
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
-
-  tempeax = SiS_Pr->SiS_VGAVDE;
-  tempebx = SiS_Pr->SiS_VDE;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     if(!(temp & 0xE0)) tempebx >>=1;
-  }
-
-  tempcx = SiS_Pr->SiS_RVBHRS;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
-  tempcx >>= 8;
-  tempcx |= 0x40;
-
-  if(tempeax <= tempebx) {
-     tempcx ^= 0x40;
-  } else {
-     tempeax -= tempebx;
-  }
-
-  tempeax *= (256 * 1024);
-  templong = tempeax % tempebx;
-  tempeax /= tempebx;
-  if(templong) tempeax++;
-
-  temp = (unsigned short)(tempeax & 0x000000FF);
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
-  temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
-  temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
-  temp |= (tempcx & 0x4F);
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
-
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
-
-     /* Calc Linebuffer max address and set/clear decimode */
-     tempbx = 0;
-     if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
-     tempax = SiS_Pr->SiS_VGAHDE;
-     if(modeflag & HalfDCLK)    tempax >>= 1;
-     if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
-     if(tempax > 800) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	   tempax -= 800;
-	} else {
-	   tempbx = 0x08;
-	   if(tempax == 960)	   tempax *= 25; /* Correct */
-           else if(tempax == 1024) tempax *= 25;
-           else			   tempax *= 20;
-	   temp = tempax % 32;
-	   tempax /= 32;
-	   if(temp) tempax++;
-	   tempax++;
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	      if(resinfo == SIS_RI_1024x768 ||
-	         resinfo == SIS_RI_1024x576 ||
-		 resinfo == SIS_RI_1280x1024 ||
-		 resinfo == SIS_RI_1280x720) {
-	         /* Otherwise white line or garbage at right edge */
-	         tempax = (tempax & 0xff00) | 0x20;
-	      }
-	   }
-	}
-     }
-     tempax--;
-     temp = ((tempax >> 4) & 0x30) | tempbx;
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
-
-     temp = 0x0036; tempbx = 0xD0;
-     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
-	temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
-     }
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
-	   temp |= 0x01;
-	   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	      if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-  	         temp &= ~0x01;
-	      }
-	   }
-	}
-     }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
-
-     tempbx = SiS_Pr->SiS_HT >> 1;
-     if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
-     tempbx -= 2;
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
-     temp = (tempbx >> 5) & 0x38;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
-
-     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
-	   /* LCD-too-dark-error-source, see FinalizeLCD() */
-	}
-     }
-
-     SiS_SetDualLinkEtc(SiS_Pr);
-
-  }  /* 301B */
-
-  SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-}
-
-/*********************************************/
-/*         SET PART 5 REGISTER GROUP         */
-/*********************************************/
-
-static void
-SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
-
-  if(SiS_Pr->SiS_ModeType == ModeVGA) {
-     if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-        SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
-     }
-  }
-}
-
-/*********************************************/
-/*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
-/*********************************************/
-
-static bool
-SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		   unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
-		   unsigned short *DisplayType)
- {
-  unsigned short modeflag = 0;
-  bool checkhd = true;
-
-  /* Pass 1:1 not supported here */
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
-
-  (*ResIndex) &= 0x3F;
-
-  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-
-     (*DisplayType) = 80;
-     if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
-      	(*DisplayType) = 82;
-	if(SiS_Pr->SiS_ModeType > ModeVGA) {
-	   if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
-	}
-     }
-     if((*DisplayType) != 84) {
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
-     }
-
-  } else {
-
-     (*DisplayType = 0);
-     switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_320x240_1: (*DisplayType) = 50;
-			   checkhd = false;
-			   break;
-     case Panel_320x240_2: (*DisplayType) = 14;
-			   break;
-     case Panel_320x240_3: (*DisplayType) = 18;
-			   break;
-     case Panel_640x480:   (*DisplayType) = 10;
-			   break;
-     case Panel_1024x600:  (*DisplayType) = 26;
-			   break;
-     default: return true;
-     }
-
-     if(checkhd) {
-        if(modeflag & HalfDCLK) (*DisplayType)++;
-     }
-
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
-     }
-
-  }
-
-  return true;
-}
-
-static void
-SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-                unsigned short RefreshRateTableIndex)
-{
-  unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
-  const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
-  static const unsigned short CRIdx[] = {
-	0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
-	0x07, 0x10, 0x11, 0x15, 0x16
-  };
-
-  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-     (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
-     return;
-
-  if(SiS_Pr->SiS_IF_DEF_LVDS) {
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
-     }
-  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
-  } else return;
-
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
-
-  if(SiS_Pr->ChipType < SIS_315H) {
-     if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
-  }
-
-  if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          &ResIndex, &DisplayType))) {
-     return;
-  }
-
-  switch(DisplayType) {
-    case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1;           break; /* xSTN */
-    case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2;           break; /* xSTN */
-    case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H;         break; /* xSTN */
-    case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3;           break; /* xSTN */
-    case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H;         break; /* xSTN */
-    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
-    case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
-#if 0 /* Works better with calculated numbers */
-    case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
-    case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
-    case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
-    case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
-#endif
-    case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
-    case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
-    case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
-    case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
-    case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
-  }
-
-  if(LVDSCRT1Ptr) {
-
-     SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-
-     for(i = 0; i <= 10; i++) {
-        tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
-        SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
-     }
-
-     for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
-        tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
-        SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
-     }
-
-     tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
-
-     if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
-     tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
-     if(modeflag & DoubleScanMode) tempah |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
-
-  } else {
-
-     SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
-
-  }
-}
-
-/*********************************************/
-/*              SET CRT2 ECLK                */
-/*********************************************/
-
-static void
-SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-           unsigned short RefreshRateTableIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short clkbase, vclkindex = 0;
-  unsigned char  sr2b, sr2c;
-
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
-     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
-	RefreshRateTableIndex--;
-     }
-     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
-                                    RefreshRateTableIndex);
-     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-  } else {
-     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
-                                    RefreshRateTableIndex);
-  }
-
-  sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
-  sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
-
-  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-     if(SiS_Pr->SiS_UseROM) {
-	if(ROMAddr[0x220] & 0x01) {
-	   sr2b = ROMAddr[0x227];
-	   sr2c = ROMAddr[0x228];
-	}
-     }
-  }
-
-  clkbase = 0x02B;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-	clkbase += 3;
-     }
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
-}
-
-/*********************************************/
-/*           SET UP CHRONTEL CHIPS           */
-/*********************************************/
-
-static void
-SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-               unsigned short RefreshRateTableIndex)
-{
-   unsigned short TVType, resindex;
-   const struct SiS_CHTVRegData *CHTVRegData = NULL;
-
-   if(ModeNo <= 0x13)
-      resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-   else
-      resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-   resindex &= 0x3F;
-
-   TVType = 0;
-   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
-   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-      TVType += 2;
-      if(SiS_Pr->SiS_ModeType > ModeVGA) {
-	 if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
-      }
-      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-	 TVType = 4;
-	 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
-      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-	 TVType = 6;
-	 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
-      }
-   }
-
-   switch(TVType) {
-      case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
-      case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
-      case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
-      case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
-      case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
-      case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
-      case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
-      case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
-      case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
-      default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
-   }
-
-
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-
-#ifdef CONFIG_FB_SIS_300
-
-      /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
-
-      /* We don't support modes >800x600 */
-      if (resindex > 5) return;
-
-      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	 SiS_SetCH700x(SiS_Pr,0x04,0x43);  /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
-	 SiS_SetCH700x(SiS_Pr,0x09,0x69);  /* Black level for PAL (105)*/
-      } else {
-	 SiS_SetCH700x(SiS_Pr,0x04,0x03);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
-	 SiS_SetCH700x(SiS_Pr,0x09,0x71);   /* Black level for NTSC (113)*/
-      }
-
-      SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]);	/* Mode register */
-      SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]);	/* Start active video register */
-      SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]);	/* Position overflow register */
-      SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]);	/* Horiz Position register */
-      SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]);	/* Vertical Position register */
-
-      /* Set minimum flicker filter for Luma channel (SR1-0=00),
-                minimum text enhancement (S3-2=10),
-   	        maximum flicker filter for Chroma channel (S5-4=10)
-	        =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
-       */
-      SiS_SetCH700x(SiS_Pr,0x01,0x28);
-
-      /* Set video bandwidth
-            High bandwidth Luma composite video filter(S0=1)
-            low bandwidth Luma S-video filter (S2-1=00)
-	    disable peak filter in S-video channel (S3=0)
-	    high bandwidth Chroma Filter (S5-4=11)
-	    =00110001=0x31
-      */
-      SiS_SetCH700x(SiS_Pr,0x03,0xb1);       /* old: 3103 */
-
-      /* Register 0x3D does not exist in non-macrovision register map
-            (Maybe this is a macrovision register?)
-       */
-#ifndef SIS_CP
-      SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
-#endif
-
-      /* Register 0x10 only contains 1 writable bit (S0) for sensing,
-             all other bits a read-only. Macrovision?
-       */
-      SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
-
-      /* Register 0x11 only contains 3 writable bits (S0-S2) for
-             contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
-       */
-      SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
-
-      /* Clear DSEN
-       */
-      SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
-
-      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {		/* ---- NTSC ---- */
-         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
-            if(resindex == 0x04) {   			/* 640x480 overscan: Mode 16 */
-      	       SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);	/* ACIV on, no need to set FSCI */
-            } else if(resindex == 0x05) {    		/* 800x600 overscan: Mode 23 */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);	/* 0x18-0x1f: FSCI 469,762,048 */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF);	/* Loop filter on for mode 23 */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);	/* ACIV off, need to set FSCI */
-            }
-         } else {
-            if(resindex == 0x04) {     			/* ----- 640x480 underscan; Mode 17 */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
-            } else if(resindex == 0x05) {   		/* ----- 800x600 underscan: Mode 24 */
-#if 0
-               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);	/* (FSCI was 0x1f1c71c7 - this is for mode 22) */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0);	/* FSCI for mode 24 is 428,554,851 */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0);       /* 198b3a63 */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
-               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off for mode 24 */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);	* ACIV off, need to set FSCI */
-#endif         /* All alternatives wrong (datasheet wrong?), don't use FSCI */
-	       SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	 /* loop filter off */
-               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
-            }
-         }
-      } else {						/* ---- PAL ---- */
-         /* We don't play around with FSCI in PAL mode */
-         if(resindex == 0x04) {
-            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
-            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);	/* ACIV on */
-         } else {
-            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);	/* loop filter off */
-            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);	/* ACIV on */
-         }
-      }
-
-#endif  /* 300 */
-
-   } else {
-
-      /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
-
-#ifdef CONFIG_FB_SIS_315
-
-      unsigned short temp;
-
-      /* We don't support modes >1024x768 */
-      if (resindex > 6) return;
-
-      temp = CHTVRegData[resindex].Reg[0];
-      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
-      SiS_SetCH701x(SiS_Pr,0x00,temp);
-
-      SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
-      SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
-      SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
-      SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
-      SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
-      SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
-
-      temp = CHTVRegData[resindex].Reg[7];
-      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
-      SiS_SetCH701x(SiS_Pr,0x07,temp);
-
-      SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
-      SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
-      SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
-      SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
-      SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
-      SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
-      SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
-      SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
-
-      temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
-      /* D1 should be set for PAL, PAL-N and NTSC-J,
-         but I won't do that for PAL unless somebody
-	 tells me to do so. Since the BIOS uses
-	 non-default CIV values and blacklevels,
-	 this might be compensated anyway.
-       */
-      if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
-      SiS_SetCH701x(SiS_Pr,0x21,temp);
-
-#endif	/* 315 */
-
-   }
-
-#ifdef SIS_CP
-   SIS_CP_INIT301_CP3
-#endif
-
-}
-
-#ifdef CONFIG_FB_SIS_315  /* ----------- 315 series only ---------- */
-
-void
-SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
-{
-   unsigned short temp;
-
-   /* Enable Chrontel 7019 LCD panel backlight */
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-      if(SiS_Pr->ChipType == SIS_740) {
-	 SiS_SetCH701x(SiS_Pr,0x66,0x65);
-      } else {
-	 temp = SiS_GetCH701x(SiS_Pr,0x66);
-	 temp |= 0x20;
-	 SiS_SetCH701x(SiS_Pr,0x66,temp);
-      }
-   }
-}
-
-void
-SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
-{
-   unsigned short temp;
-
-   /* Disable Chrontel 7019 LCD panel backlight */
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-      temp = SiS_GetCH701x(SiS_Pr,0x66);
-      temp &= 0xDF;
-      SiS_SetCH701x(SiS_Pr,0x66,temp);
-   }
-}
-
-static void
-SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
-{
-  static const unsigned char regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
-  static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
-  static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
-  static const unsigned char asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
-  static const unsigned char asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
-  static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
-  static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
-  const unsigned char *tableptr = NULL;
-  int i;
-
-  /* Set up Power up/down timing */
-
-  if(SiS_Pr->ChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
-	else    			          tableptr = table1024_740;
-     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
-	       (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
-	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
-        else					  tableptr = table1400_740;
-     } else return;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	tableptr = table1024_650;
-     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
-	       (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
-	tableptr = table1400_650;
-     } else return;
-  }
-
-  for(i=0; i<5; i++) {
-     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
-  }
-}
-
-static void
-SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
-{
-  const unsigned char *tableptr = NULL;
-  unsigned short tempbh;
-  int i;
-  static const unsigned char regtable[] = {
-		0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
-		0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
-  };
-  static const unsigned char table1024_740[] = {
-		0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
-		0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
-  };
-  static const unsigned char table1280_740[] = {
-		0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
-		0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
-  };
-  static const unsigned char table1400_740[] = {
-		0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
-		0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
-  };
-  static const unsigned char table1600_740[] = {
-		0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
-		0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
-  };
-  static const unsigned char table1024_650[] = {
-		0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
-		0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
-  };
-  static const unsigned char table1280_650[] = {
-		0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
-		0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
-  };
-  static const unsigned char table1400_650[] = {
-		0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
-		0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
-  };
-  static const unsigned char table1600_650[] = {
-		0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
-		0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
-  };
-
-  if(SiS_Pr->ChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
-     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
-     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
-     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
-     else return;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
-     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
-     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
-     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
-     else return;
-  }
-
-  tempbh = SiS_GetCH701x(SiS_Pr,0x74);
-  if((tempbh == 0xf6) || (tempbh == 0xc7)) {
-     tempbh = SiS_GetCH701x(SiS_Pr,0x73);
-     if(tempbh == 0xc8) {
-        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
-     } else if(tempbh == 0xdb) {
-        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
-	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
-     } else if(tempbh == 0xde) {
-        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
-     }
-  }
-
-  if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
-  else     			  tempbh = 0x0c;
-
-  for(i = 0; i < tempbh; i++) {
-     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
-  }
-  SiS_ChrontelPowerSequencing(SiS_Pr);
-  tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
-  tempbh |= 0xc0;
-  SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
-
-  if(SiS_Pr->ChipType == SIS_740) {
-     tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
-     tempbh &= 0xfb;
-     SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
-     tempbh = SiS_GetCH701x(SiS_Pr,0x64);
-     tempbh |= 0x40;
-     SiS_SetCH701x(SiS_Pr,0x64,tempbh);
-     tempbh = SiS_GetCH701x(SiS_Pr,0x03);
-     tempbh &= 0x3f;
-     SiS_SetCH701x(SiS_Pr,0x03,tempbh);
-  }
-}
-
-static void
-SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
-{
-  unsigned char temp, temp1;
-
-  temp1 = SiS_GetCH701x(SiS_Pr,0x49);
-  SiS_SetCH701x(SiS_Pr,0x49,0x3e);
-  temp = SiS_GetCH701x(SiS_Pr,0x47);
-  temp &= 0x7f;	/* Use external VSYNC */
-  SiS_SetCH701x(SiS_Pr,0x47,temp);
-  SiS_LongDelay(SiS_Pr, 3);
-  temp = SiS_GetCH701x(SiS_Pr,0x47);
-  temp |= 0x80;	/* Use internal VSYNC */
-  SiS_SetCH701x(SiS_Pr,0x47,temp);
-  SiS_SetCH701x(SiS_Pr,0x49,temp1);
-}
-
-static void
-SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
-{
-  unsigned short temp;
-
-  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-     if(SiS_Pr->ChipType == SIS_740) {
-        temp = SiS_GetCH701x(SiS_Pr,0x1c);
-        temp |= 0x04;	/* Invert XCLK phase */
-        SiS_SetCH701x(SiS_Pr,0x1c,temp);
-     }
-     if(SiS_IsYPbPr(SiS_Pr)) {
-        temp = SiS_GetCH701x(SiS_Pr,0x01);
-	temp &= 0x3f;
-	temp |= 0x80;	/* Enable YPrPb (HDTV) */
-	SiS_SetCH701x(SiS_Pr,0x01,temp);
-     }
-     if(SiS_IsChScart(SiS_Pr)) {
-        temp = SiS_GetCH701x(SiS_Pr,0x01);
-	temp &= 0x3f;
-	temp |= 0xc0;	/* Enable SCART + CVBS */
-	SiS_SetCH701x(SiS_Pr,0x01,temp);
-     }
-     if(SiS_Pr->ChipType == SIS_740) {
-        SiS_ChrontelResetVSync(SiS_Pr);
-        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
-     } else {
-        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
-        temp = SiS_GetCH701x(SiS_Pr,0x49);
-        if(SiS_IsYPbPr(SiS_Pr)) {
-           temp = SiS_GetCH701x(SiS_Pr,0x73);
-	   temp |= 0x60;
-	   SiS_SetCH701x(SiS_Pr,0x73,temp);
-        }
-        temp = SiS_GetCH701x(SiS_Pr,0x47);
-        temp &= 0x7f;
-        SiS_SetCH701x(SiS_Pr,0x47,temp);
-        SiS_LongDelay(SiS_Pr, 2);
-        temp = SiS_GetCH701x(SiS_Pr,0x47);
-        temp |= 0x80;
-        SiS_SetCH701x(SiS_Pr,0x47,temp);
-     }
-  }
-}
-
-static void
-SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
-{
-  unsigned short temp;
-
-  /* Complete power down of LVDS */
-  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-     if(SiS_Pr->ChipType == SIS_740) {
-        SiS_LongDelay(SiS_Pr, 1);
-	SiS_GenericDelay(SiS_Pr, 5887);
-	SiS_SetCH701x(SiS_Pr,0x76,0xac);
-	SiS_SetCH701x(SiS_Pr,0x66,0x00);
-     } else {
-        SiS_LongDelay(SiS_Pr, 2);
-	temp = SiS_GetCH701x(SiS_Pr,0x76);
-	temp &= 0xfc;
-	SiS_SetCH701x(SiS_Pr,0x76,temp);
-	SiS_SetCH701x(SiS_Pr,0x66,0x00);
-     }
-  }
-}
-
-static void
-SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
-{
-     unsigned short temp;
-
-     if(SiS_Pr->ChipType == SIS_740) {
-
-        temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
-        temp &= 0x01;
-        if(!temp) {
-
-           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
-	      temp = SiS_GetCH701x(SiS_Pr,0x49);
-	      SiS_SetCH701x(SiS_Pr,0x49,0x3e);
-	   }
-
-	   /* Reset Chrontel 7019 datapath */
-           SiS_SetCH701x(SiS_Pr,0x48,0x10);
-           SiS_LongDelay(SiS_Pr, 1);
-           SiS_SetCH701x(SiS_Pr,0x48,0x18);
-
-	   if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
-	      SiS_ChrontelResetVSync(SiS_Pr);
-	      SiS_SetCH701x(SiS_Pr,0x49,temp);
-	   }
-
-        } else {
-
-	   /* Clear/set/clear GPIO */
-           temp = SiS_GetCH701x(SiS_Pr,0x5c);
-	   temp &= 0xef;
-	   SiS_SetCH701x(SiS_Pr,0x5c,temp);
-	   temp = SiS_GetCH701x(SiS_Pr,0x5c);
-	   temp |= 0x10;
-	   SiS_SetCH701x(SiS_Pr,0x5c,temp);
-	   temp = SiS_GetCH701x(SiS_Pr,0x5c);
-	   temp &= 0xef;
-	   SiS_SetCH701x(SiS_Pr,0x5c,temp);
-	   temp = SiS_GetCH701x(SiS_Pr,0x61);
-	   if(!temp) {
-	      SiS_SetCH701xForLCD(SiS_Pr);
-	   }
-        }
-
-     } else { /* 650 */
-        /* Reset Chrontel 7019 datapath */
-        SiS_SetCH701x(SiS_Pr,0x48,0x10);
-        SiS_LongDelay(SiS_Pr, 1);
-        SiS_SetCH701x(SiS_Pr,0x48,0x18);
-     }
-}
-
-static void
-SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
-{
-     unsigned short temp;
-
-     if(SiS_Pr->ChipType == SIS_740) {
-
-        if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
-           SiS_ChrontelResetVSync(SiS_Pr);
-        }
-
-     } else {
-
-        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* Power up LVDS block */
-        temp = SiS_GetCH701x(SiS_Pr,0x49);
-        temp &= 1;
-        if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
-	   temp = SiS_GetCH701x(SiS_Pr,0x47);
-	   temp &= 0x70;
-	   SiS_SetCH701x(SiS_Pr,0x47,temp);  /* enable VSYNC */
-	   SiS_LongDelay(SiS_Pr, 3);
-	   temp = SiS_GetCH701x(SiS_Pr,0x47);
-	   temp |= 0x80;
-	   SiS_SetCH701x(SiS_Pr,0x47,temp);  /* disable VSYNC */
-        }
-
-     }
-}
-
-static void
-SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-     unsigned short temp,temp1;
-
-     if(SiS_Pr->ChipType == SIS_740) {
-
-        temp = SiS_GetCH701x(SiS_Pr,0x61);
-        if(temp < 1) {
-           temp++;
-	   SiS_SetCH701x(SiS_Pr,0x61,temp);
-        }
-        SiS_SetCH701x(SiS_Pr,0x66,0x45);  /* Panel power on */
-        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on */
-        SiS_LongDelay(SiS_Pr, 1);
-        SiS_GenericDelay(SiS_Pr, 5887);
-
-     } else {  /* 650 */
-
-        temp1 = 0;
-        temp = SiS_GetCH701x(SiS_Pr,0x61);
-        if(temp < 2) {
-           temp++;
-	   SiS_SetCH701x(SiS_Pr,0x61,temp);
-	   temp1 = 1;
-        }
-        SiS_SetCH701x(SiS_Pr,0x76,0xac);
-        temp = SiS_GetCH701x(SiS_Pr,0x66);
-        temp |= 0x5f;
-        SiS_SetCH701x(SiS_Pr,0x66,temp);
-        if(ModeNo > 0x13) {
-           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
-	      SiS_GenericDelay(SiS_Pr, 1023);
-	   } else {
-	      SiS_GenericDelay(SiS_Pr, 767);
-	   }
-        } else {
-           if(!temp1)
-	      SiS_GenericDelay(SiS_Pr, 767);
-        }
-        temp = SiS_GetCH701x(SiS_Pr,0x76);
-        temp |= 0x03;
-        SiS_SetCH701x(SiS_Pr,0x76,temp);
-        temp = SiS_GetCH701x(SiS_Pr,0x66);
-        temp &= 0x7f;
-        SiS_SetCH701x(SiS_Pr,0x66,temp);
-        SiS_LongDelay(SiS_Pr, 1);
-
-     }
-}
-
-static void
-SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
-{
-     unsigned short temp;
-
-     SiS_LongDelay(SiS_Pr, 1);
-
-     do {
-       temp = SiS_GetCH701x(SiS_Pr,0x66);
-       temp &= 0x04;  /* PLL stable? -> bail out */
-       if(temp == 0x04) break;
-
-       if(SiS_Pr->ChipType == SIS_740) {
-          /* Power down LVDS output, PLL normal operation */
-          SiS_SetCH701x(SiS_Pr,0x76,0xac);
-       }
-
-       SiS_SetCH701xForLCD(SiS_Pr);
-
-       temp = SiS_GetCH701x(SiS_Pr,0x76);
-       temp &= 0xfb;  /* Reset PLL */
-       SiS_SetCH701x(SiS_Pr,0x76,temp);
-       SiS_LongDelay(SiS_Pr, 2);
-       temp = SiS_GetCH701x(SiS_Pr,0x76);
-       temp |= 0x04;  /* PLL normal operation */
-       SiS_SetCH701x(SiS_Pr,0x76,temp);
-       if(SiS_Pr->ChipType == SIS_740) {
-          SiS_SetCH701x(SiS_Pr,0x78,0xe0);	/* PLL loop filter */
-       } else {
-          SiS_SetCH701x(SiS_Pr,0x78,0x60);
-       }
-       SiS_LongDelay(SiS_Pr, 2);
-    } while(0);
-
-    SiS_SetCH701x(SiS_Pr,0x77,0x00);  /* MV? */
-}
-
-static void
-SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
-{
-     unsigned short temp;
-
-     temp = SiS_GetCH701x(SiS_Pr,0x03);
-     temp |= 0x80;	/* Set datapath 1 to TV   */
-     temp &= 0xbf;	/* Set datapath 2 to LVDS */
-     SiS_SetCH701x(SiS_Pr,0x03,temp);
-
-     if(SiS_Pr->ChipType == SIS_740) {
-
-        temp = SiS_GetCH701x(SiS_Pr,0x1c);
-        temp &= 0xfb;	/* Normal XCLK phase */
-        SiS_SetCH701x(SiS_Pr,0x1c,temp);
-
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
-
-        temp = SiS_GetCH701x(SiS_Pr,0x64);
-        temp |= 0x40;	/* ? Bit not defined */
-        SiS_SetCH701x(SiS_Pr,0x64,temp);
-
-        temp = SiS_GetCH701x(SiS_Pr,0x03);
-        temp &= 0x3f;	/* D1 input to both LVDS and TV */
-        SiS_SetCH701x(SiS_Pr,0x03,temp);
-
-	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
-	   SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
-	   SiS_LongDelay(SiS_Pr, 1);
-	   SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
-	   SiS_ChrontelResetDB(SiS_Pr);
-	   SiS_ChrontelDoSomething2(SiS_Pr);
-	   SiS_ChrontelDoSomething3(SiS_Pr, 0);
-	} else {
-           temp = SiS_GetCH701x(SiS_Pr,0x66);
-           if(temp != 0x45) {
-              SiS_ChrontelResetDB(SiS_Pr);
-              SiS_ChrontelDoSomething2(SiS_Pr);
-              SiS_ChrontelDoSomething3(SiS_Pr, 0);
-           }
-	}
-
-     } else { /* 650 */
-
-        SiS_ChrontelResetDB(SiS_Pr);
-        SiS_ChrontelDoSomething2(SiS_Pr);
-        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
-        SiS_ChrontelDoSomething3(SiS_Pr,temp);
-        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on, LVDS normal operation */
-
-     }
-
-}
-#endif  /* 315 series  */
-
-/*********************************************/
-/*      MAIN: SET CRT2 REGISTER GROUP        */
-/*********************************************/
-
-bool
-SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-#ifdef CONFIG_FB_SIS_300
-   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
-#endif
-   unsigned short ModeIdIndex, RefreshRateTableIndex;
-
-   SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-
-   if(!SiS_Pr->UseCustomMode) {
-      SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
-   } else {
-      ModeIdIndex = 0;
-   }
-
-   /* Used for shifting CR33 */
-   SiS_Pr->SiS_SelectCRT2Rate = 4;
-
-   SiS_UnLockCRT2(SiS_Pr);
-
-   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
-
-   SiS_SaveCRT2Info(SiS_Pr,ModeNo);
-
-   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_DisableBridge(SiS_Pr);
-      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
-         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
-      }
-      SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
-   }
-
-   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-      SiS_LockCRT2(SiS_Pr);
-      SiS_DisplayOn(SiS_Pr);
-      return true;
-   }
-
-   SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-
-   /* Set up Panel Link for LVDS and LCDA */
-   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
-   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
-       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
-       ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
-      SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-   }
-
-   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-   }
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-
-	 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-#ifdef CONFIG_FB_SIS_315
-	 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-#endif
-	 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
-	 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-#ifdef CONFIG_FB_SIS_315
-	 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
-#endif
-	 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
-
-	 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
-
-	 /* For 301BDH (Panel link initialization): */
-	 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-
-	    if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
-	       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-		  SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	       }
-            }
-	    SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	 }
-      }
-
-   } else {
-
-      SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
-
-      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
-
-      SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
-
-      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-	 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-	       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-#ifdef CONFIG_FB_SIS_315
-		  SiS_SetCH701xForLCD(SiS_Pr);
-#endif
-	       }
-	    }
-	    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	       SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
-	    }
-	 }
-      }
-
-   }
-
-#ifdef CONFIG_FB_SIS_300
-   if(SiS_Pr->ChipType < SIS_315H) {
-      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-	 if(SiS_Pr->SiS_UseOEM) {
-	    if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
-	       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-		  SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	       }
-	    } else {
-	       SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	    }
-	 }
-	 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	    if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-	       (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-	       SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
-	    }
-	    SiS_DisplayOn(SiS_Pr);
-         }
-      }
-   }
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-   if(SiS_Pr->ChipType >= SIS_315H) {
-      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-	 if(SiS_Pr->ChipType < SIS_661) {
-	    SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
-	    SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	 } else {
-	    SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-	 }
-	 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
-      }
-   }
-#endif
-
-   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_EnableBridge(SiS_Pr);
-   }
-
-   SiS_DisplayOn(SiS_Pr);
-
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	 /* Disable LCD panel when using TV */
-	 SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
-      } else {
-	 /* Disable TV when using LCD */
-	 SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
-      }
-   }
-
-   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_LockCRT2(SiS_Pr);
-   }
-
-   return true;
-}
-
-
-/*********************************************/
-/*     ENABLE/DISABLE LCD BACKLIGHT (SIS)    */
-/*********************************************/
-
-void
-SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
-{
-  /* Switch on LCD backlight on SiS30xLV */
-  SiS_DDC2Delay(SiS_Pr,0xff00);
-  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
-     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-     SiS_WaitVBRetrace(SiS_Pr);
-  }
-  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
-     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-  }
-}
-
-void
-SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
-{
-  /* Switch off LCD backlight on SiS30xLV */
-  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-  SiS_DDC2Delay(SiS_Pr,0xff00);
-}
-
-/*********************************************/
-/*          DDC RELATED FUNCTIONS            */
-/*********************************************/
-
-static void
-SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
-{
-  SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
-  SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
-  if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
-     SiS_Pr->SiS_DDC_NData &= 0x0f;
-     SiS_Pr->SiS_DDC_NClk  &= 0x0f;
-  }
-}
-
-#ifdef CONFIG_FB_SIS_300
-static unsigned char *
-SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
-{
-  int i, j, num;
-  unsigned short tempah,temp;
-  unsigned char *mydataptr;
-
-  for(i=0; i<20; i++) {				/* Do 20 attempts to write */
-     mydataptr = dataptr;
-     num = *mydataptr++;
-     if(!num) return mydataptr;
-     if(i) {
-        SiS_SetStop(SiS_Pr);
-	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
-     }
-     if(SiS_SetStart(SiS_Pr)) continue;		/* Set start condition */
-     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write DAB (S0=0=write) */
-     if(temp) continue;				/*    (ERROR: no ack) */
-     tempah = *mydataptr++;
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write register number */
-     if(temp) continue;				/*    (ERROR: no ack) */
-     for(j=0; j<num; j++) {
-        tempah = *mydataptr++;
-        temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
-	if(temp) break;
-     }
-     if(temp) continue;
-     if(SiS_SetStop(SiS_Pr)) continue;
-     return mydataptr;
-  }
-  return NULL;
-}
-
-static bool
-SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
-{
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
-  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x02;			/* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x01;			/* Bitmask in IndexReg for Clk */
-  SiS_SetupDDCN(SiS_Pr);
-
-  SiS_SetSwitchDDC2(SiS_Pr);
-
-  while(*dataptr) {
-     dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
-     if(!dataptr) return false;
-  }
-  return true;
-}
-#endif
-
-/* The Chrontel 700x is connected to the 630/730 via
- * the 630/730's DDC/I2C port.
- *
- * On 630(S)T chipset, the index changed from 0x11 to
- * 0x0a, possibly for working around the DDC problems
- */
-
-static bool
-SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
-{
-  unsigned short temp, i;
-
-  for(i=0; i<20; i++) {				/* Do 20 attempts to write */
-     if(i) {
-	SiS_SetStop(SiS_Pr);
-	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
-     }
-     if(SiS_SetStart(SiS_Pr)) continue;					/* Set start condition */
-     temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr);	/* Write DAB (S0=0=write) */
-     if(temp) continue;							/*    (ERROR: no ack) */
-     temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor));			/* Write RAB (700x: set bit 7, see datasheet) */
-     if(temp) continue;							/*    (ERROR: no ack) */
-     temp = SiS_WriteDDC2Data(SiS_Pr, val);				/* Write data */
-     if(temp) continue;							/*    (ERROR: no ack) */
-     if(SiS_SetStop(SiS_Pr)) continue;					/* Set stop condition */
-     SiS_Pr->SiS_ChrontelInit = 1;
-     return true;
-  }
-  return false;
-}
-
-/* Write to Chrontel 700x */
-void
-SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
-{
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;  		/* DAB (Device Address Byte) */
-
-  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
-
-  if(!(SiS_Pr->SiS_ChrontelInit)) {
-     SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
-     SiS_Pr->SiS_DDC_Data  = 0x02;		/* Bitmask in IndexReg for Data */
-     SiS_Pr->SiS_DDC_Clk   = 0x01;		/* Bitmask in IndexReg for Clk */
-     SiS_SetupDDCN(SiS_Pr);
-  }
-
-  if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
-      (!(SiS_Pr->SiS_ChrontelInit)) ) {
-     SiS_Pr->SiS_DDC_Index = 0x0a;
-     SiS_Pr->SiS_DDC_Data  = 0x80;
-     SiS_Pr->SiS_DDC_Clk   = 0x40;
-     SiS_SetupDDCN(SiS_Pr);
-
-     SiS_SetChReg(SiS_Pr, reg, val, 0x80);
-  }
-}
-
-/* Write to Chrontel 701x */
-/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
-void
-SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
-{
-  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x08;			/* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x04;			/* Bitmask in IndexReg for Clk */
-  SiS_SetupDDCN(SiS_Pr);
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB (Device Address Byte) */
-  SiS_SetChReg(SiS_Pr, reg, val, 0);
-}
-
-static
-void
-SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
-{
-  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-     SiS_SetCH700x(SiS_Pr, reg, val);
-  else
-     SiS_SetCH701x(SiS_Pr, reg, val);
-}
-
-static unsigned short
-SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
-{
-  unsigned short tempah, temp, i;
-
-  for(i=0; i<20; i++) {				/* Do 20 attempts to read */
-     if(i) {
-	SiS_SetStop(SiS_Pr);
-	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
-     }
-     if(SiS_SetStart(SiS_Pr)) continue;					/* Set start condition */
-     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr);	/* Write DAB (S0=0=write) */
-     if(temp) continue;							/*        (ERROR: no ack) */
-     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor);	/* Write RAB (700x: | 0x80) */
-     if(temp) continue;							/*        (ERROR: no ack) */
-     if (SiS_SetStart(SiS_Pr)) continue;				/* Re-start */
-     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
-     if(temp) continue;							/*        (ERROR: no ack) */
-     tempah = SiS_ReadDDC2Data(SiS_Pr);					/* Read byte */
-     if(SiS_SetStop(SiS_Pr)) continue;					/* Stop condition */
-     SiS_Pr->SiS_ChrontelInit = 1;
-     return tempah;
-  }
-  return 0xFFFF;
-}
-
-/* Read from Chrontel 700x */
-/* Parameter is [Register no (S7-S0)] */
-unsigned short
-SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
-{
-  unsigned short result;
-
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
-
-  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
-
-  if(!(SiS_Pr->SiS_ChrontelInit)) {
-     SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
-     SiS_Pr->SiS_DDC_Data  = 0x02;		/* Bitmask in IndexReg for Data */
-     SiS_Pr->SiS_DDC_Clk   = 0x01;		/* Bitmask in IndexReg for Clk */
-     SiS_SetupDDCN(SiS_Pr);
-  }
-
-  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
-
-  if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
-      (!SiS_Pr->SiS_ChrontelInit) ) {
-
-     SiS_Pr->SiS_DDC_Index = 0x0a;
-     SiS_Pr->SiS_DDC_Data  = 0x80;
-     SiS_Pr->SiS_DDC_Clk   = 0x40;
-     SiS_SetupDDCN(SiS_Pr);
-
-     result = SiS_GetChReg(SiS_Pr,0x80);
-  }
-  return result;
-}
-
-/* Read from Chrontel 701x */
-/* Parameter is [Register no (S7-S0)] */
-unsigned short
-SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
-{
-  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x08;			/* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x04;			/* Bitmask in IndexReg for Clk */
-  SiS_SetupDDCN(SiS_Pr);
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
-
-  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
-
-  return SiS_GetChReg(SiS_Pr,0);
-}
-
-/* Read from Chrontel 70xx */
-/* Parameter is [Register no (S7-S0)] */
-static
-unsigned short
-SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
-{
-  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-     return SiS_GetCH700x(SiS_Pr, tempbx);
-  else
-     return SiS_GetCH701x(SiS_Pr, tempbx);
-}
-
-void
-SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
-		unsigned char myor, unsigned short myand)
-{
-  unsigned short tempbl;
-
-  tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
-  SiS_SetCH70xx(SiS_Pr, reg, tempbl);
-}
-
-/* Our own DDC functions */
-static
-unsigned short
-SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
-                unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
-		unsigned int VBFlags2)
-{
-     unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
-     unsigned char flag, cr32;
-     unsigned short        temp = 0, myadaptnum = adaptnum;
-
-     if(adaptnum != 0) {
-	if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
-	if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
-     }
-
-     /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
-
-     SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
-
-     SiS_Pr->SiS_DDC_SecAddr = 0;
-     SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
-     SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
-     SiS_Pr->SiS_DDC_Index = 0x11;
-     flag = 0xff;
-
-     cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
-
-#if 0
-     if(VBFlags2 & VB2_SISBRIDGE) {
-	if(myadaptnum == 0) {
-	   if(!(cr32 & 0x20)) {
-	      myadaptnum = 2;
-	      if(!(cr32 & 0x10)) {
-	         myadaptnum = 1;
-		 if(!(cr32 & 0x08)) {
-		    myadaptnum = 0;
-		 }
-	      }
-	   }
-        }
-     }
-#endif
-
-     if(VGAEngine == SIS_300_VGA) {		/* 300 series */
-
-        if(myadaptnum != 0) {
-	   flag = 0;
-	   if(VBFlags2 & VB2_SISBRIDGE) {
-	      SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
-              SiS_Pr->SiS_DDC_Index = 0x0f;
-	   }
-        }
-
-	if(!(VBFlags2 & VB2_301)) {
-	   if((cr32 & 0x80) && (checkcr32)) {
-              if(myadaptnum >= 1) {
-	         if(!(cr32 & 0x08)) {
-		     myadaptnum = 1;
-		     if(!(cr32 & 0x10)) return 0xFFFF;
-                 }
-	      }
-	   }
-	}
-
-	temp = 4 - (myadaptnum * 2);
-	if(flag) temp = 0;
-
-     } else {						/* 315/330 series */
-
-	/* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
-
-	if(VBFlags2 & VB2_SISBRIDGE) {
-	   if(myadaptnum == 2) {
-	      myadaptnum = 1;
-	   }
-	}
-
-        if(myadaptnum == 1) {
-	   flag = 0;
-	   if(VBFlags2 & VB2_SISBRIDGE) {
-	      SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
-              SiS_Pr->SiS_DDC_Index = 0x0f;
-	   }
-        }
-
-        if((cr32 & 0x80) && (checkcr32)) {
-           if(myadaptnum >= 1) {
-	      if(!(cr32 & 0x08)) {
-	         myadaptnum = 1;
-		 if(!(cr32 & 0x10)) return 0xFFFF;
-	      }
-	   }
-        }
-
-        temp = myadaptnum;
-        if(myadaptnum == 1) {
-           temp = 0;
-	   if(VBFlags2 & VB2_LVDS) flag = 0xff;
-        }
-
-	if(flag) temp = 0;
-    }
-
-    SiS_Pr->SiS_DDC_Data = 0x02 << temp;
-    SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
-
-    SiS_SetupDDCN(SiS_Pr);
-
-    return 0;
-}
-
-static unsigned short
-SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
-   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
-      return 0xFFFF;
-   }
-   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
-      return 0xFFFF;
-   }
-   return 0;
-}
-
-static unsigned short
-SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
-   if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
-      return 0xFFFF;
-   }
-   return 0;
-}
-
-static unsigned short
-SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
-{
-   if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
-   if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
-   return 0;
-}
-
-static void
-SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
-{
-   SiS_SetSCLKLow(SiS_Pr);
-   if(yesno) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		      SiS_Pr->SiS_DDC_Index,
-		      SiS_Pr->SiS_DDC_NData,
-		      SiS_Pr->SiS_DDC_Data);
-   } else {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		      SiS_Pr->SiS_DDC_Index,
-		      SiS_Pr->SiS_DDC_NData,
-		      0);
-   }
-   SiS_SetSCLKHigh(SiS_Pr);
-}
-
-static unsigned short
-SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
-{
-    unsigned char mask, value;
-    unsigned short  temp, ret=0;
-    bool failed = false;
-
-    SiS_SetSwitchDDC2(SiS_Pr);
-    if(SiS_PrepareDDC(SiS_Pr)) {
-         SiS_SetStop(SiS_Pr);
-         return 0xFFFF;
-    }
-    mask = 0xf0;
-    value = 0x20;
-    if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
-       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
-       SiS_SendACK(SiS_Pr, 0);
-       if(temp == 0) {
-           mask = 0xff;
-	   value = 0xff;
-       } else {
-           failed = true;
-	   ret = 0xFFFF;
-       }
-    }
-    if(!failed) {
-       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
-       SiS_SendACK(SiS_Pr, 1);
-       temp &= mask;
-       if(temp == value) ret = 0;
-       else {
-          ret = 0xFFFF;
-          if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
-             if(temp == 0x30) ret = 0;
-          }
-       }
-    }
-    SiS_SetStop(SiS_Pr);
-    return ret;
-}
-
-static
-unsigned short
-SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
-{
-   unsigned short flag;
-
-   flag = 0x180;
-   SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
-   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
-   SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
-   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
-   SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
-   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
-   if(!(flag & 0x1a)) flag = 0;
-   return flag;
-}
-
-static
-unsigned short
-SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
-{
-   unsigned short flag, length, i;
-   unsigned char chksum,gotcha;
-
-   if(DDCdatatype > 4) return 0xFFFF;
-
-   flag = 0;
-   SiS_SetSwitchDDC2(SiS_Pr);
-   if(!(SiS_PrepareDDC(SiS_Pr))) {
-      length = 127;
-      if(DDCdatatype != 1) length = 255;
-      chksum = 0;
-      gotcha = 0;
-      for(i=0; i<length; i++) {
-	 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
-	 chksum += buffer[i];
-	 gotcha |= buffer[i];
-	 SiS_SendACK(SiS_Pr, 0);
-      }
-      buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
-      chksum += buffer[i];
-      SiS_SendACK(SiS_Pr, 1);
-      if(gotcha) flag = (unsigned short)chksum;
-      else flag = 0xFFFF;
-   } else {
-      flag = 0xFFFF;
-   }
-   SiS_SetStop(SiS_Pr);
-   return flag;
-}
-
-/* Our private DDC functions
-
-   It complies somewhat with the corresponding VESA function
-   in arguments and return values.
-
-   Since this is probably called before the mode is changed,
-   we use our pre-detected pSiS-values instead of SiS_Pr as
-   regards chipset and video bridge type.
-
-   Arguments:
-       adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
-                 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
-		 LCDA is CRT1, but DDC is read from CRT2 port.
-       DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
-       buffer: ptr to 256 data bytes which will be filled with read data.
-
-   Returns 0xFFFF if error, otherwise
-       if DDCdatatype > 0:  Returns 0 if reading OK (included a correct checksum)
-       if DDCdatatype = 0:  Returns supported DDC modes
-
- */
-unsigned short
-SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
-              unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
-	      unsigned int VBFlags2)
-{
-   unsigned char  sr1f, cr17=1;
-   unsigned short result;
-
-   if(adaptnum > 2)
-      return 0xFFFF;
-
-   if(DDCdatatype > 4)
-      return 0xFFFF;
-
-   if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
-      return 0xFFFF;
-
-   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
-      return 0xFFFF;
-
-   sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
-   if(VGAEngine == SIS_300_VGA) {
-      cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
-      if(!cr17) {
-         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
-         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
-         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
-      }
-   }
-   if((sr1f) || (!cr17)) {
-      SiS_WaitRetrace1(SiS_Pr);
-      SiS_WaitRetrace1(SiS_Pr);
-      SiS_WaitRetrace1(SiS_Pr);
-      SiS_WaitRetrace1(SiS_Pr);
-   }
-
-   if(DDCdatatype == 0) {
-      result = SiS_ProbeDDC(SiS_Pr);
-   } else {
-      result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
-      if((!result) && (DDCdatatype == 1)) {
-         if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
-	    (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
-	    (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
-	    (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
-	    (buffer[0x12] == 1)) {
-	    if(!SiS_Pr->DDCPortMixup) {
-	       if(adaptnum == 1) {
-	          if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
-	       } else {
-	          if(buffer[0x14] & 0x80)    result = 0xFFFE;
-	       }
-	    }
-	 }
-      }
-   }
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
-   if(VGAEngine == SIS_300_VGA) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
-   }
-   return result;
-}
-
-/* Generic I2C functions for Chrontel & DDC --------- */
-
-static void
-SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
-{
-  SiS_SetSCLKHigh(SiS_Pr);
-  SiS_WaitRetrace1(SiS_Pr);
-
-  SiS_SetSCLKLow(SiS_Pr);
-  SiS_WaitRetrace1(SiS_Pr);
-}
-
-unsigned short
-SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
-{
-   SiS_WaitRetrace1(SiS_Pr);
-   return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
-}
-
-/* Set I2C start condition */
-/* This is done by a SD high-to-low transition while SC is high */
-static unsigned short
-SiS_SetStart(struct SiS_Private *SiS_Pr)
-{
-  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			/* (SC->low)  */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		  SiS_Pr->SiS_DDC_Index,
-		  SiS_Pr->SiS_DDC_NData,
-		  SiS_Pr->SiS_DDC_Data);        		/* SD->high */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* SC->high */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		  SiS_Pr->SiS_DDC_Index,
-		  SiS_Pr->SiS_DDC_NData,
-		  0x00);					/* SD->low = start condition */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* (SC->low) */
-  return 0;
-}
-
-/* Set I2C stop condition */
-/* This is done by a SD low-to-high transition while SC is high */
-static unsigned short
-SiS_SetStop(struct SiS_Private *SiS_Pr)
-{
-  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			/* (SC->low) */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		  SiS_Pr->SiS_DDC_Index,
-		  SiS_Pr->SiS_DDC_NData,
-		  0x00);					/* SD->low   */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* SC->high  */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		  SiS_Pr->SiS_DDC_Index,
-		  SiS_Pr->SiS_DDC_NData,
-		  SiS_Pr->SiS_DDC_Data);			/* SD->high = stop condition */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			/* (SC->high) */
-  return 0;
-}
-
-/* Write 8 bits of data */
-static unsigned short
-SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
-{
-  unsigned short i,flag,temp;
-
-  flag = 0x80;
-  for(i = 0; i < 8; i++) {
-    SiS_SetSCLKLow(SiS_Pr);					/* SC->low */
-    if(tempax & flag) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		      SiS_Pr->SiS_DDC_Index,
-		      SiS_Pr->SiS_DDC_NData,
-		      SiS_Pr->SiS_DDC_Data);			/* Write bit (1) to SD */
-    } else {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		      SiS_Pr->SiS_DDC_Index,
-		      SiS_Pr->SiS_DDC_NData,
-		      0x00);					/* Write bit (0) to SD */
-    }
-    SiS_SetSCLKHigh(SiS_Pr);					/* SC->high */
-    flag >>= 1;
-  }
-  temp = SiS_CheckACK(SiS_Pr);					/* Check acknowledge */
-  return temp;
-}
-
-static unsigned short
-SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
-{
-  unsigned short i, temp, getdata;
-
-  getdata = 0;
-  for(i = 0; i < 8; i++) {
-    getdata <<= 1;
-    SiS_SetSCLKLow(SiS_Pr);
-    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		    SiS_Pr->SiS_DDC_Index,
-		    SiS_Pr->SiS_DDC_NData,
-		    SiS_Pr->SiS_DDC_Data);
-    SiS_SetSCLKHigh(SiS_Pr);
-    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
-    if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
-  }
-  return getdata;
-}
-
-static unsigned short
-SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
-{
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		  SiS_Pr->SiS_DDC_Index,
-		  SiS_Pr->SiS_DDC_NClk,
-		  0x00);					/* SetSCLKLow()  */
-  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
-  return 0;
-}
-
-static unsigned short
-SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
-{
-  unsigned short temp, watchdog=1000;
-
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		  SiS_Pr->SiS_DDC_Index,
-		  SiS_Pr->SiS_DDC_NClk,
-		  SiS_Pr->SiS_DDC_Clk);  			/* SetSCLKHigh()  */
-  do {
-    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
-  } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
-  if (!watchdog) {
-  	return 0xFFFF;
-  }
-  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
-  return 0;
-}
-
-/* Check I2C acknowledge */
-/* Returns 0 if ack ok, non-0 if ack not ok */
-static unsigned short
-SiS_CheckACK(struct SiS_Private *SiS_Pr)
-{
-  unsigned short tempah;
-
-  SiS_SetSCLKLow(SiS_Pr);				           /* (SC->low) */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-		  SiS_Pr->SiS_DDC_Index,
-		  SiS_Pr->SiS_DDC_NData,
-		  SiS_Pr->SiS_DDC_Data);			   /* (SD->high) */
-  SiS_SetSCLKHigh(SiS_Pr);				           /* SC->high = clock impulse for ack */
-  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
-  SiS_SetSCLKLow(SiS_Pr);				           /* SC->low = end of clock impulse */
-  if(tempah & SiS_Pr->SiS_DDC_Data) return 1;			   /* Ack OK if bit = 0 */
-  return 0;
-}
-
-/* End of I2C functions ----------------------- */
-
-
-/* =============== SiS 315/330 O.E.M. ================= */
-
-#ifdef CONFIG_FB_SIS_315
-
-static unsigned short
-GetRAMDACromptr(struct SiS_Private *SiS_Pr)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short romptr;
-
-  if(SiS_Pr->ChipType < SIS_330) {
-     romptr = SISGETROMW(0x128);
-     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
-        romptr = SISGETROMW(0x12a);
-  } else {
-     romptr = SISGETROMW(0x1a8);
-     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
-        romptr = SISGETROMW(0x1aa);
-  }
-  return romptr;
-}
-
-static unsigned short
-GetLCDromptr(struct SiS_Private *SiS_Pr)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short romptr;
-
-  if(SiS_Pr->ChipType < SIS_330) {
-     romptr = SISGETROMW(0x120);
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
-        romptr = SISGETROMW(0x122);
-  } else {
-     romptr = SISGETROMW(0x1a0);
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
-        romptr = SISGETROMW(0x1a2);
-  }
-  return romptr;
-}
-
-static unsigned short
-GetTVromptr(struct SiS_Private *SiS_Pr)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short romptr;
-
-  if(SiS_Pr->ChipType < SIS_330) {
-     romptr = SISGETROMW(0x114);
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
-        romptr = SISGETROMW(0x11a);
-  } else {
-     romptr = SISGETROMW(0x194);
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
-        romptr = SISGETROMW(0x19a);
-  }
-  return romptr;
-}
-
-static unsigned short
-GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
-{
-  unsigned short index;
-
-  if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
-     if(!(SiS_IsNotM650orLater(SiS_Pr))) {
-        if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
-	   index >>= 4;
-	   index *= 3;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
-           else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
-           return index;
-	}
-     }
-  }
-
-  index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
-  if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
-  if(SiS_Pr->SiS_VBType & VB_SIS301C) {  /* 1.15.20 and later (not VB specific) */
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
-  }
-  index--;
-  index *= 3;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
-  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
-  return index;
-}
-
-static unsigned short
-GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
-{
-  unsigned short index;
-
-  index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
-  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
-  return index;
-}
-
-static unsigned short
-GetTVPtrIndex(struct SiS_Private *SiS_Pr)
-{
-  unsigned short index;
-
-  index = 0;
-  if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
-
-  index <<= 1;
-
-  if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
-     (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-     index++;
-  }
-
-  return index;
-}
-
-static unsigned int
-GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
-{
-   unsigned short index = 0, temp = 0;
-
-   if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
-   if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
-   if(SiS_Pr->SiS_TVMode & TVSetPALN)  index = 3;
-   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
-   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-      index = 4;
-      if(SiS_Pr->SiS_TVMode & TVSetPALM)  index++;
-      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
-   }
-
-   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-         (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-	 index += addme;
-	 temp++;
-      }
-      temp += 0x0100;
-   }
-   return (unsigned int)(index | (temp << 16));
-}
-
-static unsigned int
-GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
-{
-   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
-}
-
-#if 0
-static unsigned int
-GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
-{
-   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
-}
-#endif
-
-static int
-GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
-{
-   int index = 0;
-
-   if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
-   if(SiS_Pr->SiS_ROMNew) {
-      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
-      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
-      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
-      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
-   } else {
-      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
-      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
-      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
-      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
-   }
-
-   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
-
-   return index;
-}
-
-static void
-SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short delay=0,index,myindex,temp,romptr=0;
-  bool dochiptest = true;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
-  } else {
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
-  }
-
-  /* Find delay (from ROM, internal tables, PCI subsystem) */
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {			/* ------------ VGA */
-
-     if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-        romptr = GetRAMDACromptr(SiS_Pr);
-     }
-     if(romptr) delay = ROMAddr[romptr];
-     else {
-        delay = 0x04;
-        if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
-	   if(IS_SIS650) {
-	      delay = 0x0a;
-	   } else if(IS_SIS740) {
-	      delay = 0x00;
-	   } else if(SiS_Pr->ChipType < SIS_330) {
-	      delay = 0x0c;
-	   } else {
-	      delay = 0x0c;
-	   }
-	} else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-           delay = 0x00;
-	}
-     }
-
-  } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ----------	LCD/LCDA */
-
-     bool gotitfrompci = false;
-
-     /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
-
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	if(SiS_Pr->PDC != -1) {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
-	   return;
-	}
-     } else {
-	if(SiS_Pr->PDCA != -1) {
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
-	   return;
-	}
-     }
-
-     /* Custom Panel? */
-
-     if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	   delay = 0x00;
-	   if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
-	      delay = 0x20;
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
-	} else {
-	   delay = 0x0c;
-	   if(SiS_Pr->SiS_VBType & VB_SIS301C) {
-	      delay = 0x03;
-	      if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
-	         delay = 0x00;
-	      }
-	   } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	      if(IS_SIS740) delay = 0x01;
-	      else          delay = 0x03;
-	   }
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
-	}
-        return;
-     }
-
-     /* This is a piece of typical SiS crap: They code the OEM LCD
-      * delay into the code, at no defined place in the BIOS.
-      * We now have to start doing a PCI subsystem check here.
-      */
-
-     switch(SiS_Pr->SiS_CustomT) {
-     case CUT_COMPAQ1280:
-     case CUT_COMPAQ12802:
-	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-	   gotitfrompci = true;
-	   dochiptest = false;
-	   delay = 0x03;
-	}
-	break;
-     case CUT_CLEVO1400:
-     case CUT_CLEVO14002:
-	gotitfrompci = true;
-	dochiptest = false;
-	delay = 0x02;
-	break;
-     case CUT_CLEVO1024:
-     case CUT_CLEVO10242:
-        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   gotitfrompci = true;
-	   dochiptest = false;
-	   delay = 0x33;
-	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
-	   delay &= 0x0f;
-	}
-	break;
-     }
-
-     /* Could we find it through the PCI ID? If no, use ROM or table */
-
-     if(!gotitfrompci) {
-
-        index = GetLCDPtrIndexBIOS(SiS_Pr);
-        myindex = GetLCDPtrIndex(SiS_Pr);
-
-        if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
-
-           if(SiS_IsNotM650orLater(SiS_Pr)) {
-
-              if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-	         /* Always use the second pointer on 650; some BIOSes */
-                 /* still carry old 301 data at the first location    */
-	         /* romptr = SISGETROMW(0x120);                       */
-	         /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
-	         romptr = SISGETROMW(0x122);
-	         if(!romptr) return;
-	         delay = ROMAddr[(romptr + index)];
-	      } else {
-                 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
-	      }
-
-          } else {
-
-             delay = SiS310_LCDDelayCompensation_651301LV[myindex];
-	     if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
-	        delay = SiS310_LCDDelayCompensation_651302LV[myindex];
-
-          }
-
-        } else if(SiS_Pr->SiS_UseROM 			      &&
-		  (!(SiS_Pr->SiS_ROMNew))		      &&
-	          (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
-		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
-		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)  &&
-		  (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)  &&
-		  ((romptr = GetLCDromptr(SiS_Pr)))) {
-
-	   /* Data for 1280x1024 wrong in 301B BIOS */
-	   /* Data for 1600x1200 wrong in 301C BIOS */
-	   delay = ROMAddr[(romptr + index)];
-
-        } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-
-	   if(IS_SIS740) delay = 0x03;
-	   else          delay = 0x00;
-
-	} else {
-
-           delay = SiS310_LCDDelayCompensation_301[myindex];
-	   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-	      if(IS_SIS740) delay = 0x01;
-	      else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
-	      else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
-	   } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
-	      if(IS_SIS740) delay = 0x01;  /* ? */
-	      else          delay = 0x03;
-	      if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
-	   } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
-	      if(IS_SIS740) delay = 0x01;
-	      else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
-	   }
-
-        }
-
-     }  /* got it from PCI */
-
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
-	dochiptest = false;
-     }
-
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {			/* ------------ TV */
-
-     index = GetTVPtrIndex(SiS_Pr);
-
-     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
-
-        if(SiS_IsNotM650orLater(SiS_Pr)) {
-
-           if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-	      /* Always use the second pointer on 650; some BIOSes */
-              /* still carry old 301 data at the first location    */
-              /* romptr = SISGETROMW(0x114);			   */
-	      /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
-	      romptr = SISGETROMW(0x11a);
-	      if(!romptr) return;
-	      delay = ROMAddr[romptr + index];
-
-	   } else {
-
-	      delay = SiS310_TVDelayCompensation_301B[index];
-
-	   }
-
-        } else {
-
-           switch(SiS_Pr->SiS_CustomT) {
-	   case CUT_COMPAQ1280:
-	   case CUT_COMPAQ12802:
-	   case CUT_CLEVO1400:
-	   case CUT_CLEVO14002:
-	      delay = 0x02;
-	      dochiptest = false;
-	      break;
-	   case CUT_CLEVO1024:
-	   case CUT_CLEVO10242:
-	      delay = 0x03;
-	      dochiptest = false;
-   	      break;
-	   default:
-              delay = SiS310_TVDelayCompensation_651301LV[index];
-	      if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
-	         delay = SiS310_TVDelayCompensation_651302LV[index];
-	      }
-	   }
-        }
-
-     } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-
-        romptr = GetTVromptr(SiS_Pr);
-	if(!romptr) return;
-	delay = ROMAddr[romptr + index];
-
-     } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-
-        delay = SiS310_TVDelayCompensation_LVDS[index];
-
-     } else {
-
-	delay = SiS310_TVDelayCompensation_301[index];
-        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-	   if(IS_SIS740) {
-	      delay = SiS310_TVDelayCompensation_740301B[index];
-	      /* LV: use 301 data? BIOS bug? */
-	   } else {
-              delay = SiS310_TVDelayCompensation_301B[index];
-	      if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
-	   }
-	}
-
-     }
-
-     if(SiS_LCDAEnabled(SiS_Pr)) {
-	delay &= 0x0f;
-	dochiptest = false;
-     }
-
-  } else return;
-
-  /* Write delay */
-
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
-
-        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
-        if(temp == 8) {		/* 1400x1050 BIOS (COMPAL) */
-	   delay &= 0x0f;
-	   delay |= 0xb0;
-        } else if(temp == 6) {
-           delay &= 0x0f;
-	   delay |= 0xc0;
-        } else if(temp > 7) {	/* 1280x1024 BIOS (which one?) */
-	   delay = 0x35;
-        }
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
-
-     } else {
-
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
-
-     }
-
-  } else {  /* LVDS */
-
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
-     } else {
-        if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
-           delay <<= 4;
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
-        } else {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
-        }
-     }
-
-  }
-
-}
-
-static void
-SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp,temp1,romptr=0;
-
-  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
-
-  if(ModeNo<=0x13)
-     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
-  else
-     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
-
-  temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;  	  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
-  temp1 = temp;
-
-  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
-     if(SiS_Pr->ChipType >= SIS_661) {
-        temp1 = GetOEMTVPtr661(SiS_Pr);
-        temp1 >>= 1;
-        romptr = SISGETROMW(0x260);
-        if(SiS_Pr->ChipType >= SIS_760) {
-	   romptr = SISGETROMW(0x360);
-	}
-     } else if(SiS_Pr->ChipType >= SIS_330) {
-        romptr = SISGETROMW(0x192);
-     } else {
-        romptr = SISGETROMW(0x112);
-     }
-  }
-
-  if(romptr) {
-     temp1 <<= 1;
-     temp = ROMAddr[romptr + temp1 + index];
-  } else {
-     temp = SiS310_TVAntiFlick1[temp][index];
-  }
-  temp <<= 4;
-
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp);  /* index 0A D[6:4] */
-}
-
-static void
-SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp,temp1,romptr=0;
-
-  temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; 	/* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
-
-  if(ModeNo <= 0x13)
-     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
-  else
-     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
-
-  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
-     if(SiS_Pr->ChipType >= SIS_661) {
-        romptr = SISGETROMW(0x26c);
-        if(SiS_Pr->ChipType >= SIS_760) {
-	   romptr = SISGETROMW(0x36c);
-	}
-	temp1 = GetOEMTVPtr661(SiS_Pr);
-        temp1 >>= 1;
-     } else if(SiS_Pr->ChipType >= SIS_330) {
-        romptr = SISGETROMW(0x1a4);
-     } else {
-        romptr = SISGETROMW(0x124);
-     }
-  }
-
-  if(romptr) {
-     temp1 <<= 1;
-     temp = ROMAddr[romptr + temp1 + index];
-  } else {
-     temp = SiS310_TVEdge1[temp][index];
-  }
-  temp <<= 5;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp);  /* index 0A D[7:5] */
-}
-
-static void
-SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
-{
-  unsigned short index, temp, i, j;
-
-  if(ModeNo <= 0x13) {
-     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
-  } else {
-     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
-  }
-
-  temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
-
-  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)	     temp = 1;  /* NTSC-J uses PAL */
-  else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
-  else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
-
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-     for(i=0x35, j=0; i<=0x38; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
-     }
-     for(i=0x48; i<=0x4A; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
-     }
-  } else {
-     for(i=0x35, j=0; i<=0x38; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
-     }
-  }
-}
-
-static void
-SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp,i,j,resinfo,romptr=0;
-  unsigned int  lindex;
-
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
-
-  /* NTSC-J data not in BIOS, and already set in SetGroup2 */
-  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
-
-  if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
-     lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
-     lindex <<= 2;
-     for(j=0, i=0x31; i<=0x34; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
-     }
-     return;
-  }
-
-  /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
-  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
-
-  if(ModeNo<=0x13) {
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  } else {
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
-
-  temp = GetTVPtrIndex(SiS_Pr);
-  /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
-   * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
-   */
-  if(SiS_Pr->SiS_UseROM) {
-     romptr = SISGETROMW(0x116);
-     if(SiS_Pr->ChipType >= SIS_330) {
-        romptr = SISGETROMW(0x196);
-     }
-     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-        romptr = SISGETROMW(0x11c);
-	if(SiS_Pr->ChipType >= SIS_330) {
-	   romptr = SISGETROMW(0x19c);
-	}
-	if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
-	   romptr = SISGETROMW(0x116);
-	   if(SiS_Pr->ChipType >= SIS_330) {
-              romptr = SISGETROMW(0x196);
-           }
-	}
-     }
-  }
-  if(romptr) {
-     romptr += (temp << 2);
-     for(j=0, i=0x31; i<=0x34; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
-     }
-  } else {
-     index = temp % 2;
-     temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
-     for(j=0, i=0x31; i<=0x34; i++, j++) {
-        if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
-        else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
-        else
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
-     }
-  }
-
-  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
-     if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
-        if((resinfo == SIS_RI_640x480) ||
-	   (resinfo == SIS_RI_800x600)) {
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
-	} else if(resinfo == SIS_RI_1024x768) {
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
-	}
-     }
-  }
-}
-
-static void
-SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-                unsigned short ModeIdIndex, unsigned short RTI)
-{
-   unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-
-   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
-      return;
-
-   /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
-   /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
-
-   if(SiS_Pr->SiS_ROMNew) {
-      if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) 			||
-         ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
-	  (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-         index = 25;
-         if(SiS_Pr->UseCustomMode) {
-	    index = SiS_Pr->CSRClock;
-         } else if(ModeNo > 0x13) {
-            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
-            index = SiS_Pr->SiS_VCLKData[index].CLOCK;
-         }
-	 if(index < 25) index = 25;
-         index = ((index / 25) - 1) << 1;
-         if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
-	    index++;
-	 }
-	 romptr = SISGETROMW(0x104);
-         delay = ROMAddr[romptr + index];
-         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
-            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
-            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
-         } else {
-            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
-         }
-         return;
-      }
-   }
-
-   /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
-
-   if(SiS_Pr->UseCustomMode) delay = 0x04;
-   else if(ModeNo <= 0x13)   delay = 0x04;
-   else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
-   delay |= (delay << 8);
-
-   if(SiS_Pr->ChipType >= XGI_20) {
-
-      delay = 0x0606;
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-
-	 delay = 0x0404;
-         if(SiS_Pr->SiS_XGIROM) {
-	     index = GetTVPtrIndex(SiS_Pr);
-	     if((romptr = SISGETROMW(0x35e))) {
-	        delay = (ROMAddr[romptr + index] & 0x0f) << 1;
-		delay |= (delay << 8);
-	     }
-	 }
-
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
-	       delay -= 0x0404;
-	    }
-	 }
-      }
-
-   } else if(SiS_Pr->ChipType >= SIS_340) {
-
-      delay = 0x0606;
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-         delay = 0x0404;
-      }
-      /* TODO (eventually) */
-
-   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-
-      /* 3. TV */
-
-      index = GetOEMTVPtr661(SiS_Pr);
-      if(SiS_Pr->SiS_ROMNew) {
-         romptr = SISGETROMW(0x106);
-	 if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
-         delay = ROMAddr[romptr + index];
-      } else {
-         delay = 0x04;
-	 if(index > 3) delay = 0;
-      }
-
-   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-
-      /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
-
-      if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
-          ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
-
-	 lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
-
-	 /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
-	 delay = ROMAddr[romptr + lcdpdcindex + 1];	/* LCD  */
-	 delay |= (ROMAddr[romptr + lcdpdcindex] << 8);	/* LCDA */
-
-      } else {
-
-         /* TMDS: Set our own, since BIOS has no idea */
-	 /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
-         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-	    switch(SiS_Pr->SiS_LCDResInfo) {
-	    case Panel_1024x768:  delay = 0x0008; break;
-	    case Panel_1280x720:  delay = 0x0004; break;
-	    case Panel_1280x768:
-	    case Panel_1280x768_2:delay = 0x0004; break;
-	    case Panel_1280x800:
-	    case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
-	    case Panel_1280x854:  delay = 0x0004; break; /* FIXME */
-	    case Panel_1280x1024: delay = 0x1e04; break;
-	    case Panel_1400x1050: delay = 0x0004; break;
-	    case Panel_1600x1200: delay = 0x0400; break;
-	    case Panel_1680x1050: delay = 0x0e04; break;
-	    default:
-               if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
-	          delay = 0x0008;
-	       } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
-	          delay = 0x1e04;
-               } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
-	          delay = 0x0004;
-	       } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
-	          delay = 0x0400;
-               } else
-	          delay = 0x0e04;
-	       break;
-	    }
-         }
-
-	 /* Override by detected or user-set values */
-	 /* (but only if, for some reason, we can't read value from BIOS) */
-         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
-            delay = SiS_Pr->PDC & 0x1f;
-         }
-         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
-            delay = (SiS_Pr->PDCA & 0x1f) << 8;
-         }
-
-      }
-
-   }
-
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      delay >>= 8;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
-   } else {
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
-   }
-}
-
-static void
-SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
-{
-   unsigned short infoflag;
-   unsigned char  temp;
-
-   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-
-      if(ModeNo <= 0x13) {
-         infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
-      } else if(SiS_Pr->UseCustomMode) {
-         infoflag = SiS_Pr->CInfoFlag;
-      } else {
-         infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
-      }
-
-      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-         infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
-      }
-
-      infoflag &= 0xc0;
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-         temp = (infoflag >> 6) | 0x0c;
-         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-	    temp ^= 0x04;
-	    if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
-	 }
-         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
-      } else {
-         temp = 0x30;
-         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
-         temp |= infoflag;
-         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
-         temp = 0;
-         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-	    if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
-	 }
-         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
-      }
-
-   }
-}
-
-static void
-SetPanelParms661(struct SiS_Private *SiS_Pr)
-{
-   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-   unsigned short romptr, temp1, temp2;
-
-   if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
-      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
-   }
-
-   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-      if(SiS_Pr->LVDSHL != -1) {
-         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
-      }
-   }
-
-   if(SiS_Pr->SiS_ROMNew) {
-
-      if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
-         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-            temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
-	    temp2 = 0xfc;
-	    if(SiS_Pr->LVDSHL != -1) {
-	      temp1 &= 0xfc;
-	      temp2 = 0xf3;
-	    }
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
-         }
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-            temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
-            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
-	 }
-      }
-
-   }
-}
-
-static void
-SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
-{
-   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
-      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
-      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
-         SetPanelParms661(SiS_Pr);
-      }
-   } else {
-      SetDelayComp(SiS_Pr,ModeNo);
-   }
-
-   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-      SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
-      SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
-      SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
-      if(SiS_Pr->SiS_VBType & VB_SIS301) {
-         SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
-      }
-   }
-}
-
-static void
-SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-			unsigned short ModeIdIndex, unsigned short RRTI)
-{
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
-
-      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
-         SetPanelParms661(SiS_Pr);
-      }
-
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-         SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
-         SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
-         SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
-         if(SiS_Pr->SiS_VBType & VB_SIS301) {
-            SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
-         }
-      }
-   }
-}
-
-/* FinalizeLCD
- * This finalizes some CRT2 registers for the very panel used.
- * If we have a backup if these registers, we use it; otherwise
- * we set the register according to most BIOSes. However, this
- * function looks quite different in every BIOS, so you better
- * pray that we have a backup...
- */
-static void
-SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
-  unsigned short resinfo,modeflag;
-
-  if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
-  if(SiS_Pr->SiS_ROMNew) return;
-
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(SiS_Pr->LVDSHL != -1) {
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
-     }
-  }
-
-  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
-  if(SiS_Pr->UseCustomMode) return;
-
-  switch(SiS_Pr->SiS_CustomT) {
-  case CUT_COMPAQ1280:
-  case CUT_COMPAQ12802:
-  case CUT_CLEVO1400:
-  case CUT_CLEVO14002:
-     return;
-  }
-
-  if(ModeNo <= 0x13) {
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-     modeflag =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     modeflag =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
-
-  if(IS_SIS650) {
-     if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
-        if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
-	} else {
-           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
-	}
-     }
-  }
-
-  if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-        /* Maybe all panels? */
-        if(SiS_Pr->LVDSHL == -1) {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
-	}
-	return;
-     }
-  }
-
-  if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
-     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   if(SiS_Pr->LVDSHL == -1) {
-	      /* Maybe all panels? */
-              SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
-	   }
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
-	      if(tempch == 3) {
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
-	      }
-	   }
-	   return;
-	}
-     }
-  }
-
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	if(SiS_Pr->SiS_VBType & VB_SISEMI) {
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
-	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-	}
-     } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-        if(SiS_Pr->LVDSHL == -1) {
-           /* Maybe ACER only? */
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
-	}
-     }
-     tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
-	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
-	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   if(tempch == 0x03) {
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
-	   }
-	   if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
-	   } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {	/* 1.10.8w */
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
-	      if(ModeNo <= 0x13) {
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
-		 if((resinfo == 0) || (resinfo == 2)) return;
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
-		 if((resinfo == 1) || (resinfo == 3)) return;
-	      }
-	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
-	      if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);  /* 1.10.7u */
-#if 0
-	         tempbx = 806;  /* 0x326 */			 /* other older BIOSes */
-		 tempbx--;
-		 temp = tempbx & 0xff;
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
-		 temp = (tempbx >> 8) & 0x03;
-		 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
-#endif
-	      }
-	   } else if(ModeNo <= 0x13) {
-	      if(ModeNo <= 1) {
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
-	      }
-	      if(!(modeflag & HalfDCLK)) {
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
-		 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
-		 if(ModeNo == 0x12) {
-		    switch(tempch) {
-		       case 0:
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
-			  break;
-		       case 2:
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
-			  break;
-		       case 3:
-			  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
-			  break;
-		    }
-		 }
-	      }
-	   }
-	}
-     } else {
-        tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
-	tempcl &= 0x0f;
-	tempbh &= 0x70;
-	tempbh >>= 4;
-	tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
-	tempbx = (tempbh << 8) | tempbl;
-	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
-	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-	      	 tempbx = 770;
-	      } else {
-	         if(tempbx > 770) tempbx = 770;
-		 if(SiS_Pr->SiS_VGAVDE < 600) {
-		    tempax = 768 - SiS_Pr->SiS_VGAVDE;
-		    tempax >>= 4;  				 /* 1.10.7w; 1.10.6s: 3;  */
-		    if(SiS_Pr->SiS_VGAVDE <= 480)  tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
-		    tempbx -= tempax;
-		 }
-	      }
-	   } else return;
-	}
-	temp = tempbx & 0xff;
-	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
-	temp = ((tempbx & 0xff00) >> 4) | tempcl;
-	SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
-     }
-  }
-}
-
-#endif
-
-/*  =================  SiS 300 O.E.M. ================== */
-
-#ifdef CONFIG_FB_SIS_300
-
-static void
-SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
-		unsigned short RefTabIndex)
-{
-  unsigned short crt2crtc=0, modeflag, myindex=0;
-  unsigned char  temp;
-  int i;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
-  }
-
-  crt2crtc &= 0x3f;
-
-  if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
-  }
-
-  if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-     if(modeflag & HalfDCLK) myindex = 1;
-
-     if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-        for(i=0; i<7; i++) {
-           if(barco_p1[myindex][crt2crtc][i][0]) {
-	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
-	                      barco_p1[myindex][crt2crtc][i][0],
-	   	   	      barco_p1[myindex][crt2crtc][i][2],
-			      barco_p1[myindex][crt2crtc][i][1]);
-	   }
-        }
-     }
-     temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-     if(temp & 0x80) {
-        temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
-        temp++;
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
-     }
-  }
-}
-
-static unsigned short
-GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short tempbx=0,romptr=0;
-  static const unsigned char customtable300[] = {
-	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
-	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
-  };
-  static const unsigned char customtable630[] = {
-	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
-	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
-  };
-
-  if(SiS_Pr->ChipType == SIS_300) {
-
-    tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
-    if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
-    tempbx -= 2;
-    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
-    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
-    }
-    if(SiS_Pr->SiS_UseROM) {
-       if(ROMAddr[0x235] & 0x80) {
-          tempbx = SiS_Pr->SiS_LCDTypeInfo;
-          if(Flag) {
-	     romptr = SISGETROMW(0x255);
-	     if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	     else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
-             if(tempbx == 0xFF) return 0xFFFF;
-          }
-	  tempbx <<= 1;
-	  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
-       }
-    }
-
-  } else {
-
-    if(Flag) {
-       if(SiS_Pr->SiS_UseROM) {
-          romptr = SISGETROMW(0x255);
-	  if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	  else 	     tempbx = 0xff;
-       } else {
-          tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
-       }
-       if(tempbx == 0xFF) return 0xFFFF;
-       tempbx <<= 2;
-       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
-       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-       return tempbx;
-    }
-    tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
-    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
-    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-
-  }
-
-  return tempbx;
-}
-
-static void
-SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp,romptr=0;
-
-  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
-
-  if(SiS_Pr->SiS_UseROM) {
-     if(!(ROMAddr[0x237] & 0x01)) return;
-     if(!(ROMAddr[0x237] & 0x02)) return;
-     romptr = SISGETROMW(0x24b);
-  }
-
-  /* The Panel Compensation Delay should be set according to tables
-   * here. Unfortunately, various BIOS versions don't care about
-   * a uniform way using eg. ROM byte 0x220, but use different
-   * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
-   * Thus we don't set this if the user selected a custom pdc or if
-   * we otherwise detected a valid pdc.
-   */
-  if(SiS_Pr->PDC != -1) return;
-
-  temp = GetOEMLCDPtr(SiS_Pr, 0);
-
-  if(SiS_Pr->UseCustomMode)
-     index = 0;
-  else
-     index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
-
-  if(SiS_Pr->ChipType != SIS_300) {
-     if(romptr) {
-	romptr += (temp * 2);
-	romptr = SISGETROMW(romptr);
-	romptr += index;
-	temp = ROMAddr[romptr];
-     } else {
-	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-    	   temp = SiS300_OEMLCDDelay2[temp][index];
-	} else {
-           temp = SiS300_OEMLCDDelay3[temp][index];
-        }
-     }
-  } else {
-     if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
-	if(romptr) {
-	   romptr += (temp * 2);
-	   romptr = SISGETROMW(romptr);
-	   romptr += index;
-	   temp = ROMAddr[romptr];
-	} else {
-	   temp = SiS300_OEMLCDDelay5[temp][index];
-	}
-     } else {
-        if(SiS_Pr->SiS_UseROM) {
-	   romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
-	   if(romptr) {
-	      romptr += (temp * 2);
-	      romptr = SISGETROMW(romptr);
-	      romptr += index;
-	      temp = ROMAddr[romptr];
-	   } else {
-	      temp = SiS300_OEMLCDDelay4[temp][index];
-	   }
-	} else {
-	   temp = SiS300_OEMLCDDelay4[temp][index];
-	}
-     }
-  }
-  temp &= 0x3c;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
-}
-
-static void
-SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-#if 0  /* Unfinished; Data table missing */
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp;
-
-  if((SiS_Pr->SiS_UseROM) {
-     if(!(ROMAddr[0x237] & 0x01)) return;
-     if(!(ROMAddr[0x237] & 0x04)) return;
-     /* No rom pointer in BIOS header! */
-  }
-
-  temp = GetOEMLCDPtr(SiS_Pr, 1);
-  if(temp == 0xFFFF) return;
-
-  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
-  for(i=0x14, j=0; i<=0x17; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
-  }
-  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
-
-  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
-  SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
-  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
-  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
-  for(i=0x1b, j=3; i<=0x1d; i++, j++) {
-      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
-  }
-#endif
-}
-
-static unsigned short
-GetOEMTVPtr(struct SiS_Private *SiS_Pr)
-{
-  unsigned short index;
-
-  index = 0;
-  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)  index += 2;
-     else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
-     else if(SiS_Pr->SiS_TVMode & TVSetPAL)   index += 1;
-  } else {
-     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
-     if(SiS_Pr->SiS_TVMode & TVSetPAL)        index += 1;
-  }
-  return index;
-}
-
-static void
-SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp,romptr=0;
-
-  if(SiS_Pr->SiS_UseROM) {
-     if(!(ROMAddr[0x238] & 0x01)) return;
-     if(!(ROMAddr[0x238] & 0x02)) return;
-     romptr = SISGETROMW(0x241);
-  }
-
-  temp = GetOEMTVPtr(SiS_Pr);
-
-  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
-
-  if(romptr) {
-     romptr += (temp * 2);
-     romptr = SISGETROMW(romptr);
-     romptr += index;
-     temp = ROMAddr[romptr];
-  } else {
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        temp = SiS300_OEMTVDelay301[temp][index];
-     } else {
-        temp = SiS300_OEMTVDelayLVDS[temp][index];
-     }
-  }
-  temp &= 0x3c;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
-}
-
-static void
-SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp,romptr=0;
-
-  if(SiS_Pr->SiS_UseROM) {
-     if(!(ROMAddr[0x238] & 0x01)) return;
-     if(!(ROMAddr[0x238] & 0x04)) return;
-     romptr = SISGETROMW(0x243);
-  }
-
-  temp = GetOEMTVPtr(SiS_Pr);
-
-  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
-
-  if(romptr) {
-     romptr += (temp * 2);
-     romptr = SISGETROMW(romptr);
-     romptr += index;
-     temp = ROMAddr[romptr];
-  } else {
-     temp = SiS300_OEMTVFlicker[temp][index];
-  }
-  temp &= 0x70;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
-}
-
-static void
-SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,i,j,temp,romptr=0;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
-
-  if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
-
-  if(SiS_Pr->SiS_UseROM) {
-     if(!(ROMAddr[0x238] & 0x01)) return;
-     if(!(ROMAddr[0x238] & 0x08)) return;
-     romptr = SISGETROMW(0x245);
-  }
-
-  temp = GetOEMTVPtr(SiS_Pr);
-
-  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
-
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-     for(i=0x31, j=0; i<=0x34; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
-     }
-  } else {
-     if(romptr) {
-        romptr += (temp * 2);
-	romptr = SISGETROMW(romptr);
-	romptr += (index * 4);
-        for(i=0x31, j=0; i<=0x34; i++, j++) {
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
-	}
-     } else {
-        for(i=0x31, j=0; i<=0x34; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
-	}
-     }
-  }
-}
-
-static void
-SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
-{
-  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
-  unsigned short index,temp,i,j,romptr=0;
-
-  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
-
-  if(SiS_Pr->SiS_UseROM) {
-     if(!(ROMAddr[0x238] & 0x01)) return;
-     if(!(ROMAddr[0x238] & 0x10)) return;
-     romptr = SISGETROMW(0x247);
-  }
-
-  temp = GetOEMTVPtr(SiS_Pr);
-
-  if(SiS_Pr->SiS_TVMode & TVSetPALM)      temp = 8;
-  else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
-  /* NTSCJ uses NTSC filters */
-
-  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
-
-  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
-      for(i=0x35, j=0; i<=0x38; i++, j++) {
-       	SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
-      }
-      for(i=0x48; i<=0x4A; i++, j++) {
-     	SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
-      }
-  } else {
-      if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
-         romptr += (temp * 2);
-	 romptr = SISGETROMW(romptr);
-	 romptr += (index * 4);
-	 for(i=0x35, j=0; i<=0x38; i++, j++) {
-       	    SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
-         }
-      } else {
-         for(i=0x35, j=0; i<=0x38; i++, j++) {
-       	    SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
-         }
-      }
-  }
-}
-
-static unsigned short
-SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
-{
-   unsigned short ModeIdIndex;
-   unsigned char  VGAINFO = SiS_Pr->SiS_VGAINFO;
-
-   if(*ModeNo <= 5) *ModeNo |= 1;
-
-   for(ModeIdIndex=0; ; ModeIdIndex++) {
-      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
-      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)    return 0;
-   }
-
-   if(*ModeNo != 0x07) {
-      if(*ModeNo > 0x03) return ModeIdIndex;
-      if(VGAINFO & 0x80) return ModeIdIndex;
-      ModeIdIndex++;
-   }
-
-   if(VGAINFO & 0x10) ModeIdIndex++;   /* 400 lines */
-	                               /* else 350 lines */
-   return ModeIdIndex;
-}
-
-static void
-SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-		  unsigned short RefTableIndex)
-{
-  unsigned short OEMModeIdIndex = 0;
-
-  if(!SiS_Pr->UseCustomMode) {
-     OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
-     if(!(OEMModeIdIndex)) return;
-  }
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
-     }
-  }
-  if(SiS_Pr->UseCustomMode) return;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
-    	SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
-       	SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
-     }
-  }
-}
-#endif
-
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
deleted file mode 100644
index 2112d6d7feda..000000000000
--- a/drivers/video/sis/init301.h
+++ /dev/null
@@ -1,456 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * Data and prototypes for init301.c
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-#ifndef  _INIT301_H_
-#define  _INIT301_H_
-
-#include "initdef.h"
-
-#include "vgatypes.h"
-#include "vstruct.h"
-#ifdef SIS_CP
-#undef SIS_CP
-#endif
-#include <linux/types.h>
-#include <asm/io.h>
-#include <linux/fb.h>
-#include "sis.h"
-#include <video/sisfb.h>
-
-static const unsigned char SiS_YPbPrTable[3][64] = {
-  {
-    0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
-    0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
-    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
-    0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
-    0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
-    0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
-    0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
-  },
-  {
-    0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
-    0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
-    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
-    0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
-    0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
-    0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
-  },
-  {
-#if 0 /* OK, but sticks to left edge */
-    0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
-    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
-    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
-    0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
-    0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
-    0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
-#endif
-#if 1 /* Perfect */
-    0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
-    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
-    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
-    0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
-    0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
-    0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
-#endif
-  }
-};
-
-static const unsigned char SiS_TVPhase[] =
-{
-	0x21,0xED,0xBA,0x08,	/* 0x00 SiS_NTSCPhase */
-	0x2A,0x05,0xE3,0x00,	/* 0x01 SiS_PALPhase */
-	0x21,0xE4,0x2E,0x9B,	/* 0x02 SiS_PALMPhase */
-	0x21,0xF4,0x3E,0xBA,	/* 0x03 SiS_PALNPhase */
-	0x1E,0x8B,0xA2,0xA7,
-	0x1E,0x83,0x0A,0xE0,	/* 0x05 SiS_SpecialPhaseM */
-	0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x21,0xF0,0x7B,0xD6,	/* 0x08 SiS_NTSCPhase2 */
-	0x2A,0x09,0x86,0xE9,	/* 0x09 SiS_PALPhase2 */
-	0x21,0xE6,0xEF,0xA4,	/* 0x0a SiS_PALMPhase2 */
-	0x21,0xF6,0x94,0x46,	/* 0x0b SiS_PALNPhase2 */
-	0x1E,0x8B,0xA2,0xA7,
-	0x1E,0x83,0x0A,0xE0,	/* 0x0d SiS_SpecialPhaseM */
-	0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00,
-	0x1e,0x8c,0x5c,0x7a,	/* 0x10 SiS_SpecialPhase */
-	0x25,0xd4,0xfd,0x5e	/* 0x11 SiS_SpecialPhaseJ */
-};
-
-static const unsigned char SiS_HiTVGroup3_1[] = {
-    0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
-    0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
-    0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
-    0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10,
-    0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80,
-    0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0,
-    0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e,
-    0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
-};
-
-static const unsigned char SiS_HiTVGroup3_2[] = {
-    0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
-    0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
-    0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
-    0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10,
-    0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80,
-    0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94,
-    0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64,
-    0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
-};
-
-/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
-
-static const unsigned char SiS_Part2CLVX_1[] = {
-    0x00,0x00,
-    0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
-    0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
-    0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
-};
-
-static const unsigned char SiS_Part2CLVX_2[] = {
-    0x00,0x00,
-    0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
-    0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
-    0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
-};
-
-static const unsigned char SiS_Part2CLVX_3[] = {  /* NTSC, 525i, 525p */
-    0xE0,0x01,
-    0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
-    0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
-    0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E,
-    0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00,0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02,
-    0x58,0x02,
-    0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D,0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E,
-    0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F,0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F,
-    0x00,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01,0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03,
-    0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04,0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06,
-    0x00,0x03,
-    0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00,0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01,
-    0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02,0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03,
-    0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05,0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06,
-    0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07,0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08,
-    0xFF,0xFF
-};
-
-static const unsigned char SiS_Part2CLVX_4[] = {   /* PAL */
-    0x58,0x02,
-    0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
-    0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
-    0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
-    0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
-    0x00,0x03,
-    0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E,0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F,
-    0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00,0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01,
-    0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02,0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04,
-    0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05,0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07,
-    0x40,0x02,
-    0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
-    0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
-    0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
-    0xFF,0xFF
-};
-
-static const unsigned char SiS_Part2CLVX_5[] = {   /* 750p */
-    0x00,0x03,
-    0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
-    0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
-    0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
-    0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
-    0xFF,0xFF
-};
-
-static const unsigned char SiS_Part2CLVX_6[] = {   /* 1080i */
-    0x00,0x04,
-    0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
-    0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
-    0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
-    0xFF,0xFF,
-};
-
-#ifdef CONFIG_FB_SIS_315
-/* 661 et al LCD data structure (2.03.00) */
-static const unsigned char SiS_LCDStruct661[] = {
-    /* 1024x768 */
-/*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
-    0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
-    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
-    /*  | vss     |    vse  |clck|  clock  |CRT2DataP|CRT2DataP|idx     */
-    /*					      VESA    non-VESA  noscale */
-    /* 1280x1024 */
-    0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
-    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
-    /* 1400x1050 */
-    0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
-    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
-    /* 1600x1200 */
-    0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
-    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0A,
-    /* 1280x768 (_2) */
-    0x0A,0xE0,0x00,0x05,0x00,0x03,0x7C,0x06,0x26,0x03,0x30,0x00,0x70,
-    0x00,0x03,0x00,0x06,0x00,0x4D,0xC8,0x48,0x00,0x00,0x00,0x00,0x06,
-    /* 1280x720 */
-    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x20,
-    0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
-    /* 1280x800 (_2) */
-    0x0C,0xE0,0x00,0x05,0x20,0x03,0x10,0x06,0x2C,0x03,0x30,0x00,0x70,
-    0x00,0x04,0x00,0x03,0x00,0x49,0xCE,0x1E,0x00,0x00,0x00,0x00,0x09,
-    /* 1680x1050 */
-    0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
-    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
-    /* 1280x800_3 */
-    0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
-    0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
-    /* 800x600 */
-    0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
-    0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
-    /* 1280x854 */
-    0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
-    0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
-};
-#endif
-
-#ifdef CONFIG_FB_SIS_300
-static unsigned char SiS300_TrumpionData[14][80] = {
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
-    0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
-    0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
-    0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
-    0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
-    0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
-    0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
-    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
-    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
-    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
-    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
-    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
-    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
-    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
-    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
-    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
-    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
-    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
-    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
-    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
-    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
-    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
-    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
-  /* variant 2 */
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
-    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
-    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
-    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
-    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
-    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
-    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
-    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
-    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
-    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
-    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
-    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
-    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
-    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
-    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
-    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
-    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
-    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
-    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
-    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
-  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
-    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
-    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
-    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
-    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
-};
-#endif
-
-void		SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
-void		SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
-unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
-void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
-bool		SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
-bool		SiS_IsVAMode(struct SiS_Private *SiS_Pr);
-void		SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-			unsigned short ModeIdIndex, int checkcrt2mode);
-void		SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
-void    	SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-			unsigned short ModeIdIndex);
-void		SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-		unsigned short ModeIdIndex);
-unsigned short	SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-			unsigned short RefreshRateTableIndex);
-unsigned short	SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
-void		SiS_DisableBridge(struct SiS_Private *SiS_Pr);
-bool		SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
-void		SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
-void		SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
-
-void		SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
-void		SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-unsigned short	SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
-void		SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
-			unsigned char orval,unsigned short andval);
-#ifdef CONFIG_FB_SIS_315
-static void	SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
-static void	SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
-static void	SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
-static void	SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
-void		SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
-void		SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
-#endif /* 315 */
-
-#ifdef CONFIG_FB_SIS_300
-static  bool	SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
-void		SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
-#endif
-
-void		SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
-unsigned short	SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
-unsigned short	SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
-			unsigned short adaptnum, unsigned short DDCdatatype,
-			unsigned char *buffer, unsigned int VBFlags2);
-
-static unsigned short	SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
-				int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
-				bool checkcr32, unsigned int VBFlags2);
-static unsigned short	SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
-				unsigned char *buffer);
-static void		SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_SetStart(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_SetStop(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
-static unsigned short	SiS_CheckACK(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
-static unsigned short	SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
-static void		SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
-static unsigned short	SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
-
-#ifdef CONFIG_FB_SIS_300
-static void		SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
-				unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
-static void		SetOEMLCDData2(struct SiS_Private *SiS_Pr,
-				unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
-#endif
-#ifdef CONFIG_FB_SIS_315
-static void		SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
-				unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
-static void		SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
-				unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
-static void		SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
-#endif
-
-extern void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
-extern void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
-extern bool		SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
-extern unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-extern unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
-extern unsigned short	SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
-extern unsigned short	SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
-				unsigned short RefreshRateTableIndex);
-extern void		SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-extern void		SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
-				unsigned short ModeIdIndex);
-extern void		SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
-extern unsigned short	SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
-extern unsigned short	SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
-#ifdef CONFIG_FB_SIS_300
-extern void		SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
-				unsigned short *tempcl);
-extern unsigned short	SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
-extern unsigned short	SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
-extern unsigned int	sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-extern unsigned int	sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-#endif
-
-#endif
diff --git a/drivers/video/sis/initdef.h b/drivers/video/sis/initdef.h
deleted file mode 100644
index 264b55a5947b..000000000000
--- a/drivers/video/sis/initdef.h
+++ /dev/null
@@ -1,708 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * Global definitions for init.c and init301.c
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-#ifndef _INITDEF_
-#define _INITDEF_
-
-#define IS_SIS330		(SiS_Pr->ChipType == SIS_330)
-#define IS_SIS550		(SiS_Pr->ChipType == SIS_550)
-#define IS_SIS650		(SiS_Pr->ChipType == SIS_650)  /* All versions, incl 651, M65x */
-#define IS_SIS740		(SiS_Pr->ChipType == SIS_740)
-#define IS_SIS651	        (SiS_Pr->SiS_SysFlags & (SF_Is651 | SF_Is652))
-#define IS_SISM650	        (SiS_Pr->SiS_SysFlags & (SF_IsM650 | SF_IsM652 | SF_IsM653))
-#define IS_SIS65x               (IS_SIS651 || IS_SISM650)       /* Only special versions of 65x */
-#define IS_SIS661		(SiS_Pr->ChipType == SIS_661)
-#define IS_SIS741		(SiS_Pr->ChipType == SIS_741)
-#define IS_SIS660		(SiS_Pr->ChipType == SIS_660)
-#define IS_SIS760		(SiS_Pr->ChipType == SIS_760)
-#define IS_SIS761		(SiS_Pr->ChipType == SIS_761)
-#define IS_SIS661741660760	(IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760 || IS_SIS761)
-#define IS_SIS650740            ((SiS_Pr->ChipType >= SIS_650) && (SiS_Pr->ChipType < SIS_330))
-#define IS_SIS550650740         (IS_SIS550 || IS_SIS650740)
-#define IS_SIS650740660         (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
-#define IS_SIS550650740660      (IS_SIS550 || IS_SIS650740660)
-
-#define SISGETROMW(x)		(ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
-
-/* SiS_VBType */
-#define VB_SIS301		0x0001
-#define VB_SIS301B		0x0002
-#define VB_SIS302B		0x0004
-#define VB_SIS301LV		0x0008
-#define VB_SIS302LV		0x0010
-#define VB_SIS302ELV		0x0020
-#define VB_SIS301C		0x0040
-#define VB_SIS307T		0x0080
-#define VB_SIS307LV		0x0100
-#define VB_UMC			0x4000
-#define VB_NoLCD        	0x8000
-#define VB_SIS30xB		(VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
-#define VB_SIS30xC		(VB_SIS301C | VB_SIS307T)
-#define VB_SISTMDS		(VB_SIS301 | VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
-#define VB_SISLVDS		(VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SIS30xBLV		(VB_SIS30xB | VB_SISLVDS)
-#define VB_SIS30xCLV		(VB_SIS30xC | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SISVB		(VB_SIS301 | VB_SIS30xBLV)
-#define VB_SISLCDA		(VB_SIS302B | VB_SIS301C  | VB_SIS307T  | VB_SISLVDS)
-#define VB_SISTMDSLCDA		(VB_SIS301C | VB_SIS307T)
-#define VB_SISPART4SCALER	(VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SISHIVISION		(VB_SIS301 | VB_SIS301B | VB_SIS302B)
-#define VB_SISYPBPR		(VB_SIS301C | VB_SIS307T  | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SISTAP4SCALER	(VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SISPART4OVERFLOW	(VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SISPWD		(VB_SIS301C | VB_SIS307T | VB_SISLVDS)
-#define VB_SISEMI		(VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SISPOWER		(VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
-#define VB_SISDUALLINK		(VB_SIS302LV | VB_SIS302ELV | VB_SIS307T | VB_SIS307LV)
-#define VB_SISVGA2		VB_SISTMDS
-#define VB_SISRAMDAC202		(VB_SIS301C | VB_SIS307T)
-
-/* VBInfo */
-#define SetSimuScanMode         0x0001   /* CR 30 */
-#define SwitchCRT2              0x0002
-#define SetCRT2ToAVIDEO         0x0004
-#define SetCRT2ToSVIDEO         0x0008
-#define SetCRT2ToSCART          0x0010
-#define SetCRT2ToLCD            0x0020
-#define SetCRT2ToRAMDAC         0x0040
-#define SetCRT2ToHiVision       0x0080   		/* for SiS bridge */
-#define SetCRT2ToCHYPbPr       	SetCRT2ToHiVision	/* for Chrontel   */
-#define SetNTSCTV               0x0000   /* CR 31 */
-#define SetPALTV                0x0100   		/* Deprecated here, now in TVMode */
-#define SetInSlaveMode          0x0200
-#define SetNotSimuMode          0x0400
-#define SetNotSimuTVMode        SetNotSimuMode
-#define SetDispDevSwitch        0x0800
-#define SetCRT2ToYPbPr525750    0x0800
-#define LoadDACFlag             0x1000
-#define DisableCRT2Display      0x2000
-#define DriverMode              0x4000
-#define HotKeySwitch            0x8000
-#define SetCRT2ToLCDA           0x8000
-
-/* v-- Needs change in sis_vga.c if changed (GPIO) --v */
-#define SetCRT2ToTV             (SetCRT2ToYPbPr525750|SetCRT2ToHiVision|SetCRT2ToSCART|SetCRT2ToSVIDEO|SetCRT2ToAVIDEO)
-#define SetCRT2ToTVNoYPbPrHiVision (SetCRT2ToSCART | SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)
-#define SetCRT2ToTVNoHiVision  	(SetCRT2ToYPbPr525750 | SetCRT2ToSCART | SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)
-
-/* SiS_ModeType */
-#define ModeText                0x00
-#define ModeCGA                 0x01
-#define ModeEGA                 0x02
-#define ModeVGA                 0x03
-#define Mode15Bpp               0x04
-#define Mode16Bpp               0x05
-#define Mode24Bpp               0x06
-#define Mode32Bpp               0x07
-
-#define ModeTypeMask            0x07
-#define IsTextMode              0x07
-
-#define DACInfoFlag             0x0018
-#define MemoryInfoFlag          0x01E0
-#define MemorySizeShift         5
-
-/* modeflag */
-#define Charx8Dot               0x0200
-#define LineCompareOff          0x0400
-#define CRT2Mode                0x0800
-#define HalfDCLK                0x1000
-#define NoSupportSimuTV         0x2000
-#define NoSupportLCDScale	0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
-#define DoubleScanMode          0x8000
-
-/* Infoflag */
-#define SupportTV               0x0008
-#define SupportTV1024           0x0800
-#define SupportCHTV 		0x0800
-#define Support64048060Hz       0x0800  /* Special for 640x480 LCD */
-#define SupportHiVision         0x0010
-#define SupportYPbPr750p        0x1000
-#define SupportLCD              0x0020
-#define SupportRAMDAC2          0x0040	/* All           (<= 100Mhz) */
-#define SupportRAMDAC2_135      0x0100  /* All except DH (<= 135Mhz) */
-#define SupportRAMDAC2_162      0x0200  /* B, C          (<= 162Mhz) */
-#define SupportRAMDAC2_202      0x0400  /* C             (<= 202Mhz) */
-#define InterlaceMode           0x0080
-#define SyncPP                  0x0000
-#define HaveWideTiming		0x2000	/* Have specific wide- and non-wide timing */
-#define SyncPN                  0x4000
-#define SyncNP                  0x8000
-#define SyncNN                  0xc000
-
-/* SetFlag */
-#define ProgrammingCRT2         0x0001
-#define LowModeTests		0x0002
-/* #define TVSimuMode           0x0002 - deprecated */
-/* #define RPLLDIV2XO           0x0004 - deprecated */
-#define LCDVESATiming           0x0008
-#define EnableLVDSDDA           0x0010
-#define SetDispDevSwitchFlag    0x0020
-#define CheckWinDos             0x0040
-#define SetDOSMode              0x0080
-
-/* TVMode flag */
-#define TVSetPAL		0x0001
-#define TVSetNTSCJ		0x0002
-#define TVSetPALM		0x0004
-#define TVSetPALN		0x0008
-#define TVSetCHOverScan		0x0010
-#define TVSetYPbPr525i		0x0020 /* new 0x10 */
-#define TVSetYPbPr525p		0x0040 /* new 0x20 */
-#define TVSetYPbPr750p		0x0080 /* new 0x40 */
-#define TVSetHiVision		0x0100 /* new 0x80; = 1080i, software-wise identical */
-#define TVSetTVSimuMode		0x0200 /* new 0x200, prev. 0x800 */
-#define TVRPLLDIV2XO		0x0400 /* prev 0x1000 */
-#define TVSetNTSC1024		0x0800 /* new 0x100, prev. 0x2000 */
-#define TVSet525p1024		0x1000 /* TW */
-#define TVAspect43		0x2000
-#define TVAspect169		0x4000
-#define TVAspect43LB		0x8000
-
-/* YPbPr flag (>=315, <661; converted to TVMode) */
-#define YPbPr525p               0x0001
-#define YPbPr750p               0x0002
-#define YPbPr525i               0x0004
-#define YPbPrHiVision           0x0008
-#define YPbPrModeMask           (YPbPr750p | YPbPr525p | YPbPr525i | YPbPrHiVision)
-
-/* SysFlags (to identify special versions) */
-#define SF_Is651                0x0001
-#define SF_IsM650               0x0002
-#define SF_Is652		0x0004
-#define SF_IsM652		0x0008
-#define SF_IsM653		0x0010
-#define SF_IsM661		0x0020
-#define SF_IsM741		0x0040
-#define SF_IsM760		0x0080
-#define SF_760UMA		0x4000  /* 76x: We have UMA */
-#define SF_760LFB		0x8000  /* 76x: We have LFB */
-
-/* CR32 (Newer 630, and 315 series)
-
-   [0]   VB connected with CVBS
-   [1]   VB connected with SVHS
-   [2]   VB connected with SCART
-   [3]   VB connected with LCD
-   [4]   VB connected with CRT2 (secondary VGA)
-   [5]   CRT1 monitor is connected
-   [6]   VB connected with Hi-Vision TV
-   [7]   <= 330: VB connected with DVI combo connector
-         >= 661: VB connected to YPbPr
-*/
-
-/* CR35 (300 series only) */
-#define TVOverScan              0x10
-#define TVOverScanShift         4
-
-/* CR35 (661 series only)
-   [0]    1 = PAL, 0 = NTSC
-   [1]    1 = NTSC-J (if D0 = 0)
-   [2]    1 = PALM (if D0 = 1)
-   [3]    1 = PALN (if D0 = 1)
-   [4]    1 = Overscan (Chrontel only)
-   [7:5]  (only if D2 in CR38 is set)
-	  000  525i
-	  001  525p
-	  010  750p
-	  011  1080i (or HiVision on 301, 301B)
-*/
-
-/* CR37
-   [0]   Set 24/18 bit (0/1) RGB to LVDS/TMDS transmitter (set by BIOS)
-   [3:1] External chip
-         300 series:
-	    001   SiS301 (never seen)
-	    010   LVDS
-	    011   LVDS + Tumpion Zurac
-	    100   LVDS + Chrontel 7005
-	    110   Chrontel 7005
-	  315/330 series
-	    001   SiS30x (never seen)
-	    010   LVDS
-	    011   LVDS + Chrontel 7019
-	  660 series [2:1] only:
-	     reserved (chip type now in CR38)
-	  All other combinations reserved
-   [3]    661 only: Pass 1:1 data
-   [4]    LVDS: 0: Panel Link expands / 1: Panel Link does not expand
-          30x:  0: Bridge scales      / 1: Bridge does not scale = Panel scales (if possible)
-   [5]    LCD polarity select
-          0: VESA DMT Standard
-	  1: EDID 2.x defined
-   [6]    LCD horizontal polarity select
-          0: High active
-	  1: Low active
-   [7]    LCD vertical polarity select
-          0: High active
-	  1: Low active
-*/
-
-/* CR37: LCDInfo */
-#define LCDRGB18Bit           0x0001
-#define LCDNonExpanding       0x0010
-#define LCDSync               0x0020
-#define LCDPass11             0x0100   /* 0: center screen, 1: Pass 1:1 data */
-#define LCDDualLink	      0x0200
-
-#define DontExpandLCD	      LCDNonExpanding
-#define LCDNonExpandingShift       4
-#define DontExpandLCDShift    LCDNonExpandingShift
-#define LCDSyncBit            0x00e0
-#define LCDSyncShift               6
-
-/* CR38 (315 series) */
-#define EnableDualEdge 		0x01
-#define SetToLCDA		0x02   /* LCD channel A (301C/302B/30x(E)LV and 650+LVDS only) */
-#define EnableCHScart           0x04   /* Scart on Ch7019 (unofficial definition - TW) */
-#define EnableCHYPbPr           0x08   /* YPbPr on Ch7019 (480i HDTV); only on 650/Ch7019 systems */
-#define EnableSiSYPbPr          0x08   /* Enable YPbPr mode (30xLV/301C only) */
-#define EnableYPbPr525i         0x00   /* Enable 525i YPbPr mode (30xLV/301C only) (mask 0x30) */
-#define EnableYPbPr525p         0x10   /* Enable 525p YPbPr mode (30xLV/301C only) (mask 0x30) */
-#define EnableYPbPr750p         0x20   /* Enable 750p YPbPr mode (30xLV/301C only) (mask 0x30) */
-#define EnableYPbPr1080i        0x30   /* Enable 1080i YPbPr mode (30xLV/301C only) (mask 0x30) */
-#define EnablePALM              0x40   /* 1 = Set PALM */
-#define EnablePALN              0x80   /* 1 = Set PALN */
-#define EnableNTSCJ             EnablePALM  /* Not BIOS */
-
-/* CR38 (661 and later)
-  D[7:5]  000 No VB
-          001 301 series VB
-	  010 LVDS
-	  011 Chrontel 7019
-	  100 Conexant
-  D2      Enable YPbPr output (see CR35)
-  D[1:0]  LCDA (like before)
-*/
-
-#define EnablePALMN             0x40   /* Romflag: 1 = Allow PALM/PALN */
-
-/* CR39 (650 only) */
-#define LCDPass1_1		0x01   /* 0: center screen, 1: pass 1:1 data output  */
-#define Enable302LV_DualLink    0x04   /* 302LV only; enable dual link */
-
-/* CR39 (661 and later)
-   D[7]   LVDS (SiS or third party)
-   D[1:0] YPbPr Aspect Ratio
-          00 4:3 letterbox
-	  01 4:3
-	  10 16:9
-	  11 4:3
-*/
-
-/* CR3B (651+301C)
-   D[1:0] YPbPr Aspect Ratio
-          ?
-*/
-
-/* CR79 (315/330 series only; not 661 and later)
-   [3-0] Notify driver
-         0001 Mode Switch event (set by BIOS)
-	 0010 Epansion On/Off event
-	 0011 TV UnderScan/OverScan event
-	 0100 Set Brightness event
-	 0101 Set Contrast event
-	 0110 Set Mute event
-	 0111 Set Volume Up/Down event
-   [4]   Enable Backlight Control by BIOS/driver
-         (set by driver; set means that the BIOS should
-	 not touch the backlight registers because eg.
-	 the driver already switched off the backlight)
-   [5]   PAL/NTSC (set by BIOS)
-   [6]   Expansion On/Off (set by BIOS; copied to CR32[4])
-   [7]   TV UnderScan/OverScan (set by BIOS)
-*/
-
-/* CR7C - 661 and later
-   [7]   DualEdge enabled (or: to be enabled)
-   [6]   CRT2 = TV/LCD/VGA enabled (or: to be enabled)
-   [5]   Init done (set at end of SiS_Init)
-   {4]   LVDS LCD capabilities
-   [3]   LVDS LCD capabilities
-   [2]   LVDS LCD capabilities (PWD)
-   [1]   LVDS LCD capabilities (PWD)
-   [0]   LVDS=1, TMDS=0 (SiS or third party)
-*/
-
-/* CR7E - 661 and later
-   VBType:
-   [7] LVDS (third party)
-   [3] 301C
-   [2] 302LV
-   [1] 301LV
-   [0] 301B
-*/
-
-/* LCDResInfo */
-#define Panel300_800x600        0x01	/* CR36 */
-#define Panel300_1024x768       0x02
-#define Panel300_1280x1024      0x03
-#define Panel300_1280x960       0x04
-#define Panel300_640x480        0x05
-#define Panel300_1024x600       0x06
-#define Panel300_1152x768       0x07
-#define Panel300_1280x768       0x0a
-#define Panel300_Custom		0x0f
-#define Panel300_Barco1366      0x10
-
-#define Panel310_800x600        0x01
-#define Panel310_1024x768       0x02
-#define Panel310_1280x1024      0x03
-#define Panel310_640x480        0x04
-#define Panel310_1024x600       0x05
-#define Panel310_1152x864       0x06
-#define Panel310_1280x960       0x07
-#define Panel310_1152x768       0x08	/* LVDS only */
-#define Panel310_1400x1050      0x09
-#define Panel310_1280x768       0x0a
-#define Panel310_1600x1200      0x0b
-#define Panel310_320x240_2      0x0c    /* xSTN */
-#define Panel310_320x240_3      0x0d    /* xSTN */
-#define Panel310_320x240_1      0x0e    /* xSTN - This is fake, can be any */
-#define Panel310_Custom		0x0f
-
-#define Panel661_800x600        0x01
-#define Panel661_1024x768       0x02
-#define Panel661_1280x1024      0x03
-#define Panel661_640x480        0x04
-#define Panel661_1024x600       0x05
-#define Panel661_1152x864       0x06
-#define Panel661_1280x960       0x07
-#define Panel661_1280x854       0x08
-#define Panel661_1400x1050      0x09
-#define Panel661_1280x768       0x0a
-#define Panel661_1600x1200      0x0b
-#define Panel661_1280x800       0x0c
-#define Panel661_1680x1050      0x0d
-#define Panel661_1280x720       0x0e
-#define Panel661_Custom		0x0f
-
-#define Panel_800x600           0x01	/* Unified values */
-#define Panel_1024x768          0x02    /* MUST match BIOS values from 0-e */
-#define Panel_1280x1024         0x03
-#define Panel_640x480           0x04
-#define Panel_1024x600          0x05
-#define Panel_1152x864          0x06
-#define Panel_1280x960          0x07
-#define Panel_1152x768          0x08	/* LVDS only */
-#define Panel_1400x1050         0x09
-#define Panel_1280x768          0x0a    /* 30xB/C and LVDS only (BIOS: all) */
-#define Panel_1600x1200         0x0b
-#define Panel_1280x800		0x0c    /* 661etc (TMDS) */
-#define Panel_1680x1050         0x0d    /* 661etc  */
-#define Panel_1280x720		0x0e    /* 661etc  */
-#define Panel_Custom		0x0f	/* MUST BE 0x0f (for DVI DDC detection) */
-#define Panel_320x240_1         0x10    /* SiS 550 xSTN */
-#define Panel_Barco1366         0x11
-#define Panel_848x480		0x12
-#define Panel_320x240_2		0x13    /* SiS 550 xSTN */
-#define Panel_320x240_3		0x14    /* SiS 550 xSTN */
-#define Panel_1280x768_2        0x15	/* 30xLV */
-#define Panel_1280x768_3        0x16    /* (unused) */
-#define Panel_1280x800_2	0x17    /* 30xLV */
-#define Panel_856x480		0x18
-#define Panel_1280x854		0x19	/* 661etc */
-
-/* Index in ModeResInfo table */
-#define SIS_RI_320x200    0
-#define SIS_RI_320x240    1
-#define SIS_RI_320x400    2
-#define SIS_RI_400x300    3
-#define SIS_RI_512x384    4
-#define SIS_RI_640x400    5
-#define SIS_RI_640x480    6
-#define SIS_RI_800x600    7
-#define SIS_RI_1024x768   8
-#define SIS_RI_1280x1024  9
-#define SIS_RI_1600x1200 10
-#define SIS_RI_1920x1440 11
-#define SIS_RI_2048x1536 12
-#define SIS_RI_720x480   13
-#define SIS_RI_720x576   14
-#define SIS_RI_1280x960  15
-#define SIS_RI_800x480   16
-#define SIS_RI_1024x576  17
-#define SIS_RI_1280x720  18
-#define SIS_RI_856x480   19
-#define SIS_RI_1280x768  20
-#define SIS_RI_1400x1050 21
-#define SIS_RI_1152x864  22  /* Up to here SiS conforming */
-#define SIS_RI_848x480   23
-#define SIS_RI_1360x768  24
-#define SIS_RI_1024x600  25
-#define SIS_RI_1152x768  26
-#define SIS_RI_768x576   27
-#define SIS_RI_1360x1024 28
-#define SIS_RI_1680x1050 29
-#define SIS_RI_1280x800  30
-#define SIS_RI_1920x1080 31
-#define SIS_RI_960x540   32
-#define SIS_RI_960x600   33
-#define SIS_RI_1280x854  34
-
-/* CR5F */
-#define IsM650                  0x80
-
-/* Timing data */
-#define NTSCHT                  1716
-#define NTSC2HT                 1920
-#define NTSCVT                  525
-#define PALHT                   1728
-#define PALVT                   625
-#define StHiTVHT                892
-#define StHiTVVT                1126
-#define StHiTextTVHT            1000
-#define StHiTextTVVT            1126
-#define ExtHiTVHT               2100
-#define ExtHiTVVT               1125
-
-/* Indices in (VB)VCLKData tables */
-
-#define VCLK28                  0x00   /* Index in VCLKData table (300 and 315) */
-#define VCLK40                  0x04   /* Index in VCLKData table (300 and 315) */
-#define VCLK65_300              0x09   /* Index in VCLKData table (300) */
-#define VCLK108_2_300           0x14   /* Index in VCLKData table (300) */
-#define VCLK81_300		0x3f   /* Index in VCLKData table (300) */
-#define VCLK108_3_300           0x42   /* Index in VCLKData table (300) */
-#define VCLK100_300             0x43   /* Index in VCLKData table (300) */
-#define VCLK34_300              0x3d   /* Index in VCLKData table (300) */
-#define VCLK_CUSTOM_300		0x47
-
-#define VCLK65_315              0x0b   /* Indices in (VB)VCLKData table (315) */
-#define VCLK108_2_315           0x19
-#define VCLK81_315		0x5b
-#define VCLK162_315             0x5e
-#define VCLK108_3_315           0x45
-#define VCLK100_315             0x46
-#define VCLK34_315              0x55
-#define VCLK68_315		0x0d
-#define VCLK_1280x800_315_2	0x5c
-#define VCLK121_315		0x5d
-#define VCLK130_315		0x72
-#define VCLK_1280x720		0x5f
-#define VCLK_1280x768_2		0x60
-#define VCLK_1280x768_3		0x61   /* (unused?) */
-#define VCLK_CUSTOM_315		0x62
-#define VCLK_1280x720_2		0x63
-#define VCLK_720x480		0x67
-#define VCLK_720x576		0x68
-#define VCLK_768x576		0x68
-#define VCLK_848x480		0x65
-#define VCLK_856x480		0x66
-#define VCLK_800x480		0x65
-#define VCLK_1024x576		0x51
-#define VCLK_1152x864		0x64
-#define VCLK_1360x768		0x58
-#define VCLK_1280x800_315	0x6c
-#define VCLK_1280x854		0x76
-
-#define TVCLKBASE_300		0x21   /* Indices on TV clocks in VCLKData table (300) */
-#define TVCLKBASE_315	        0x3a   /* Indices on TV clocks in (VB)VCLKData table (315) */
-#define TVVCLKDIV2              0x00   /* Index relative to TVCLKBASE */
-#define TVVCLK                  0x01   /* Index relative to TVCLKBASE */
-#define HiTVVCLKDIV2            0x02   /* Index relative to TVCLKBASE */
-#define HiTVVCLK                0x03   /* Index relative to TVCLKBASE */
-#define HiTVSimuVCLK            0x04   /* Index relative to TVCLKBASE */
-#define HiTVTextVCLK            0x05   /* Index relative to TVCLKBASE */
-#define YPbPr750pVCLK		0x25   /* Index relative to TVCLKBASE; was 0x0f NOT relative */
-
-/* ------------------------------ */
-
-#define SetSCARTOutput          0x01
-
-#define HotPlugFunction         0x08
-
-#define StStructSize            0x06
-
-#define SIS_VIDEO_CAPTURE       0x00 - 0x30
-#define SIS_VIDEO_PLAYBACK      0x02 - 0x30
-#define SIS_CRT2_PORT_04        0x04 - 0x30
-#define SIS_CRT2_PORT_10        0x10 - 0x30
-#define SIS_CRT2_PORT_12        0x12 - 0x30
-#define SIS_CRT2_PORT_14        0x14 - 0x30
-
-#define ADR_CRT2PtrData         0x20E
-#define offset_Zurac            0x210   /* TW: Trumpion Zurac data pointer */
-#define ADR_LVDSDesPtrData      0x212
-#define ADR_LVDSCRT1DataPtr     0x214
-#define ADR_CHTVVCLKPtr         0x216
-#define ADR_CHTVRegDataPtr      0x218
-
-#define LCDDataLen              8
-#define HiTVDataLen             12
-#define TVDataLen               16
-
-#define LVDSDataLen             6
-#define LVDSDesDataLen          3
-#define ActiveNonExpanding      0x40
-#define ActiveNonExpandingShift 6
-#define ActivePAL               0x20
-#define ActivePALShift          5
-#define ModeSwitchStatus        0x0F
-#define SoftTVType              0x40
-#define SoftSettingAddr         0x52
-#define ModeSettingAddr         0x53
-
-#define _PanelType00             0x00
-#define _PanelType01             0x08
-#define _PanelType02             0x10
-#define _PanelType03             0x18
-#define _PanelType04             0x20
-#define _PanelType05             0x28
-#define _PanelType06             0x30
-#define _PanelType07             0x38
-#define _PanelType08             0x40
-#define _PanelType09             0x48
-#define _PanelType0A             0x50
-#define _PanelType0B             0x58
-#define _PanelType0C             0x60
-#define _PanelType0D             0x68
-#define _PanelType0E             0x70
-#define _PanelType0F             0x78
-
-#define PRIMARY_VGA       	0     /* 1: SiS is primary vga 0:SiS is secondary vga */
-
-#define BIOSIDCodeAddr          0x235  /* Offsets to ptrs in BIOS image */
-#define OEMUtilIDCodeAddr       0x237
-#define VBModeIDTableAddr       0x239
-#define OEMTVPtrAddr            0x241
-#define PhaseTableAddr          0x243
-#define NTSCFilterTableAddr     0x245
-#define PALFilterTableAddr      0x247
-#define OEMLCDPtr_1Addr         0x249
-#define OEMLCDPtr_2Addr         0x24B
-#define LCDHPosTable_1Addr      0x24D
-#define LCDHPosTable_2Addr      0x24F
-#define LCDVPosTable_1Addr      0x251
-#define LCDVPosTable_2Addr      0x253
-#define OEMLCDPIDTableAddr      0x255
-
-#define VBModeStructSize        5
-#define PhaseTableSize          4
-#define FilterTableSize         4
-#define LCDHPosTableSize        7
-#define LCDVPosTableSize        5
-#define OEMLVDSPIDTableSize     4
-#define LVDSHPosTableSize       4
-#define LVDSVPosTableSize       6
-
-#define VB_ModeID               0
-#define VB_TVTableIndex         1
-#define VB_LCDTableIndex        2
-#define VB_LCDHIndex            3
-#define VB_LCDVIndex            4
-
-#define OEMLCDEnable            0x0001
-#define OEMLCDDelayEnable       0x0002
-#define OEMLCDPOSEnable         0x0004
-#define OEMTVEnable             0x0100
-#define OEMTVDelayEnable        0x0200
-#define OEMTVFlickerEnable      0x0400
-#define OEMTVPhaseEnable        0x0800
-#define OEMTVFilterEnable       0x1000
-
-#define OEMLCDPanelIDSupport    0x0080
-
-/*
-  =============================================================
-   		  for 315 series (old data layout)
-  =============================================================
-*/
-#define SoftDRAMType        0x80
-#define SoftSetting_OFFSET  0x52
-#define SR07_OFFSET  0x7C
-#define SR15_OFFSET  0x7D
-#define SR16_OFFSET  0x81
-#define SR17_OFFSET  0x85
-#define SR19_OFFSET  0x8D
-#define SR1F_OFFSET  0x99
-#define SR21_OFFSET  0x9A
-#define SR22_OFFSET  0x9B
-#define SR23_OFFSET  0x9C
-#define SR24_OFFSET  0x9D
-#define SR25_OFFSET  0x9E
-#define SR31_OFFSET  0x9F
-#define SR32_OFFSET  0xA0
-#define SR33_OFFSET  0xA1
-
-#define CR40_OFFSET  0xA2
-#define SR25_1_OFFSET  0xF6
-#define CR49_OFFSET  0xF7
-
-#define VB310Data_1_2_Offset  0xB6
-#define VB310Data_4_D_Offset  0xB7
-#define VB310Data_4_E_Offset  0xB8
-#define VB310Data_4_10_Offset 0xBB
-
-#define RGBSenseDataOffset    0xBD
-#define YCSenseDataOffset     0xBF
-#define VideoSenseDataOffset  0xC1
-#define OutputSelectOffset    0xF3
-
-#define ECLK_MCLK_DISTANCE  0x14
-#define VBIOSTablePointerStart    0x100
-#define StandTablePtrOffset       VBIOSTablePointerStart+0x02
-#define EModeIDTablePtrOffset     VBIOSTablePointerStart+0x04
-#define CRT1TablePtrOffset        VBIOSTablePointerStart+0x06
-#define ScreenOffsetPtrOffset     VBIOSTablePointerStart+0x08
-#define VCLKDataPtrOffset         VBIOSTablePointerStart+0x0A
-#define MCLKDataPtrOffset         VBIOSTablePointerStart+0x0E
-#define CRT2PtrDataPtrOffset      VBIOSTablePointerStart+0x10
-#define TVAntiFlickPtrOffset      VBIOSTablePointerStart+0x12
-#define TVDelayPtr1Offset         VBIOSTablePointerStart+0x14
-#define TVPhaseIncrPtr1Offset     VBIOSTablePointerStart+0x16
-#define TVYFilterPtr1Offset       VBIOSTablePointerStart+0x18
-#define LCDDelayPtr1Offset        VBIOSTablePointerStart+0x20
-#define TVEdgePtr1Offset          VBIOSTablePointerStart+0x24
-#define CRT2Delay1Offset          VBIOSTablePointerStart+0x28
-
-#endif
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
deleted file mode 100644
index 3ab18f5a3759..000000000000
--- a/drivers/video/sis/initextlfb.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * SiS 300/540/630[S]/730[S]
- * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX]
- * XGI V3XT/V5/V8, Z7
- * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
- *
- * Linux kernel specific extensions to init.c/init301.c
- *
- * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Author:	Thomas Winischhofer <thomas@winischhofer.net>
- */
-
-#include "initdef.h"
-#include "vgatypes.h"
-#include "vstruct.h"
-
-#include <linux/types.h>
-#include <linux/fb.h>
-
-int		sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
-			unsigned char modeno, unsigned char rateindex);
-int		sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
-			unsigned char rateindex, struct fb_var_screeninfo *var);
-bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
-			int *htotal, int *vtotal, unsigned char rateindex);
-
-extern bool	SiSInitPtr(struct SiS_Private *SiS_Pr);
-extern bool	SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
-			unsigned short *ModeIdIndex);
-extern void	SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
-			int xres, int yres, struct fb_var_screeninfo *var, bool writeres);
-
-int
-sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
-			unsigned char rateindex)
-{
-    unsigned short ModeNo = modeno;
-    unsigned short ModeIdIndex = 0, ClockIndex = 0;
-    unsigned short RRTI = 0;
-    int Clock;
-
-    if(!SiSInitPtr(SiS_Pr)) return 65000;
-
-    if(rateindex > 0) rateindex--;
-
-#ifdef CONFIG_FB_SIS_315
-    switch(ModeNo) {
-    case 0x5a: ModeNo = 0x50; break;
-    case 0x5b: ModeNo = 0x56;
-    }
-#endif
-
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {
-       printk(KERN_ERR "Could not find mode %x\n", ModeNo);
-       return 65000;
-    }
-
-    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-
-    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
-       if(SiS_Pr->SiS_UseWide == 1) {
-	  /* Wide screen: Ignore rateindex */
-	  ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_WIDE;
-       } else {
-	  RRTI += rateindex;
-	  ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_NORM;
-       }
-    } else {
-       RRTI += rateindex;
-       ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK;
-    }
-
-    Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
-
-    return Clock;
-}
-
-int
-sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
-			unsigned char rateindex, struct fb_var_screeninfo *var)
-{
-    unsigned short ModeNo = modeno;
-    unsigned short ModeIdIndex = 0, index = 0, RRTI = 0;
-    int            j;
-
-    if(!SiSInitPtr(SiS_Pr)) return 0;
-
-    if(rateindex > 0) rateindex--;
-
-#ifdef CONFIG_FB_SIS_315
-    switch(ModeNo) {
-       case 0x5a: ModeNo = 0x50; break;
-       case 0x5b: ModeNo = 0x56;
-    }
-#endif
-
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
-
-    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
-       if(SiS_Pr->SiS_UseWide == 1) {
-	  /* Wide screen: Ignore rateindex */
-	  index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
-       } else {
-	  RRTI += rateindex;
-	  index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
-       }
-    } else {
-       RRTI += rateindex;
-       index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
-    }
-
-    SiS_Generic_ConvertCRData(SiS_Pr,
-			(unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
-			SiS_Pr->SiS_RefIndex[RRTI].XRes,
-			SiS_Pr->SiS_RefIndex[RRTI].YRes,
-			var, false);
-
-    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
-       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
-    else
-       var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
-    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x4000)
-       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
-    else
-       var->sync |= FB_SYNC_HOR_HIGH_ACT;
-
-    var->vmode = FB_VMODE_NONINTERLACED;
-    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x0080)
-       var->vmode = FB_VMODE_INTERLACED;
-    else {
-       j = 0;
-       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
-	  if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
-	                  SiS_Pr->SiS_RefIndex[RRTI].ModeID) {
-	      if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
-	      	  var->vmode = FB_VMODE_DOUBLE;
-	      }
-	      break;
-	  }
-	  j++;
-       }
-    }
-
-    if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-#if 0  /* Do this? */
-       var->upper_margin <<= 1;
-       var->lower_margin <<= 1;
-       var->vsync_len <<= 1;
-#endif
-    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-       var->upper_margin >>= 1;
-       var->lower_margin >>= 1;
-       var->vsync_len >>= 1;
-    }
-
-    return 1;
-}
-
-bool
-sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
-			int *vtotal, unsigned char rateindex)
-{
-    unsigned short ModeNo = modeno;
-    unsigned short ModeIdIndex = 0, CRT1Index = 0;
-    unsigned short RRTI = 0;
-    unsigned char  sr_data, cr_data, cr_data2;
-
-    if(!SiSInitPtr(SiS_Pr)) return false;
-
-    if(rateindex > 0) rateindex--;
-
-#ifdef CONFIG_FB_SIS_315
-    switch(ModeNo) {
-       case 0x5a: ModeNo = 0x50; break;
-       case 0x5b: ModeNo = 0x56;
-    }
-#endif
-
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
-
-    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
-       if(SiS_Pr->SiS_UseWide == 1) {
-	  /* Wide screen: Ignore rateindex */
-	  CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
-       } else {
-	  RRTI += rateindex;
-	  CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
-       }
-    } else {
-       RRTI += rateindex;
-       CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
-    }
-
-    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
-    *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
-
-    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
-    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
-    cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
-    *vtotal = ((cr_data & 0xFF) |
-	       ((unsigned short)(cr_data2 & 0x01) <<  8) |
-	       ((unsigned short)(cr_data2 & 0x20) <<  4) |
-	       ((unsigned short)(sr_data  & 0x01) << 10)) + 2;
-
-    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
-       *vtotal *= 2;
-
-    return true;
-}
-
-
-
diff --git a/drivers/video/sis/oem300.h b/drivers/video/sis/oem300.h
deleted file mode 100644
index b73f26840143..000000000000
--- a/drivers/video/sis/oem300.h
+++ /dev/null
@@ -1,840 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * OEM Data for 300 series
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-static const unsigned char SiS300_OEMTVDelay301[8][4] =
-{
-	{0x08,0x08,0x08,0x08},
-	{0x08,0x08,0x08,0x08},
-	{0x08,0x08,0x08,0x08},
-	{0x2c,0x2c,0x2c,0x2c},
-	{0x08,0x08,0x08,0x08},
-	{0x08,0x08,0x08,0x08},
-	{0x08,0x08,0x08,0x08},
-	{0x20,0x20,0x20,0x20}
-};
-
-static const unsigned char SiS300_OEMTVDelayLVDS[8][4] =
-{
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20}
-};
-
-static const unsigned char SiS300_OEMTVFlicker[8][4] =
-{
-	{0x00,0x00,0x00,0x00},
-	{0x00,0x00,0x00,0x00},
-	{0x00,0x00,0x00,0x00},
-	{0x00,0x00,0x00,0x00},
-	{0x00,0x00,0x00,0x00},
-	{0x00,0x00,0x00,0x00},
-	{0x00,0x00,0x00,0x00},
-	{0x00,0x00,0x00,0x00}
-};
-
-static const unsigned char SiS300_OEMLCDDelay2[64][4] =		 /* for 301/301b/302b/301LV/302LV */
-{
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20}
-};
-
-static const unsigned char SiS300_OEMLCDDelay4[12][4] =
-{
-	{0x2c,0x2c,0x2c,0x2c},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x2c,0x2c,0x2c,0x2c},
-	{0x2c,0x2c,0x2c,0x2c},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x24,0x24,0x24,0x24},
-	{0x24,0x24,0x24,0x24},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x24,0x24,0x24,0x24}
-};
-
-static const unsigned char SiS300_OEMLCDDelay5[32][4] =
-{
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-};
-
-static const unsigned char SiS300_OEMLCDDelay3[64][4] =		/* For LVDS */
-{
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20},
-	{0x20,0x20,0x20,0x20}
-};
-
-static const unsigned char SiS300_Phase1[8][5][4] =
-{
-    {
-	{0x21,0xed,0x00,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08}
-    },
-    {
-        {0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-        {0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-        {0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-        {0x21,0xed,0x00,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08}
-    },
-    {
-        {0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-        {0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-        {0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    }
-};
-
-static const unsigned char SiS300_Phase2[8][5][4] =
-{
-    {
-	{0x21,0xed,0x00,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08}
-    },
-    {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-	{0x21,0xed,0x00,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08},
-	{0x21,0xed,0x8a,0x08}
-    },
-    {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    },
-    {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-    }
-};
-
-static const unsigned char SiS300_Filter1[10][16][4] =
-{
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x10,0x18},
-	{0xf7,0x06,0x19,0x14},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x15,0x25,0xf6},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x10,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xfc,0xfb,0x14,0x2a},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x10,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xfc,0xfb,0x14,0x2a},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x10,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xfc,0xfb,0x14,0x2a},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x10,0x18},
-	{0xf7,0x06,0x19,0x14},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x15,0x25,0xf6},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x10,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xfc,0xfb,0x14,0x2a},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x10,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xfc,0xfb,0x14,0x2a},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x10,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xfc,0xfb,0x14,0x2a},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf1,0xf7,0x1f,0x32}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x10,0x18},
-	{0xf7,0x06,0x19,0x14},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x15,0x25,0xf6},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18}
-    },
-    {
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x10,0x18},
-	{0xf7,0x06,0x19,0x14},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x15,0x25,0xf6},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18}
-    },
-};
-
-static const unsigned char SiS300_Filter2[10][9][7] =
-{
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    },
-    {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-    }
-};
-
-/* Custom data for Barco iQ Pro R300 */
-static const unsigned char barco_p1[2][9][7][3] =
-{
-  {
-     {
-	{ 0x16, 0xcf, 0x00 },
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x19, 0x00 }
-     },
-     {
-	{ 0x16, 0xcf, 0x00 },
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x1e, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x16, 0x00 }
-     },
-     {
-	{ 0x16, 0xcf, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x19, 0x00 },
-	{    0,    0,    0 }
-     },
-     {
-	{    0,    0,    0 }
-     },
-     {
-	{ 0x16, 0xcf, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x1e, 0x00 },
-	{    0,    0,    0 }
-     },
-     {
-	{ 0x16, 0xd1, 0x00 },
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x11, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x26, 0x00 }
-     },
-     {
-	{ 0x16, 0xd1, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x30, 0x00 },
-	{    0,    0,    0 }
-     },
-     {
-	{ 0x16, 0x00, 0x00 },
-	{ 0x17, 0xa0, 0x00 },
-	{ 0x1a, 0xa0, 0x00 },
-	{ 0x1b, 0x2a, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{    0,    0,    0 }
-     },
-     {
-	{ 0x16, 0x00, 0x00 },
-	{ 0x17, 0xaa, 0x00 },
-	{ 0x1a, 0xa0, 0x00 },
-	{ 0x1b, 0x2a, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{    0,    0,    0 }
-     }
-  },
-  {
-     {
-	{ 0x16, 0xcf, 0x00 },
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x19, 0x00 }
-     },
-     {
-	{    0,    0,    0 }
-     },
-     {
-	{ 0x16, 0xcf, 0x00 },
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x19, 0x00 },
-     },
-     {
-	{    0,    0,    0 }
-     },
-     {
-	{ 0x16, 0xcf, 0x00 },
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe7, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x1e, 0x00 }
-     },
-     {
-	{ 0x16, 0xd1, 0x00 },
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe6, 0x00 },
-	{ 0x1b, 0x11, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x26, 0x00 }
-     },
-     {
-	{ 0x18, 0x00, 0x00 },
-	{ 0x1a, 0xe0, 0x00 },
-	{ 0x1b, 0x26, 0x00 },
-	{ 0x1c, 0xff, 0x00 },
-	{ 0x1d, 0x1c, 0x00 },
-	{ 0x1e, 0x30, 0x00 },
-	{    0,    0,    0 }
-     },
-     {
-	{    0,    0,    0 }
-     },
-     {
-	{    0,    0,    0 }
-     }
-  }
-};
-
-
-
-
-
-
diff --git a/drivers/video/sis/oem310.h b/drivers/video/sis/oem310.h
deleted file mode 100644
index 8fce56e4482c..000000000000
--- a/drivers/video/sis/oem310.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * OEM Data for 315/330/340 series
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-static const unsigned char SiS310_LCDDelayCompensation_301[] =	    		/* 301 */
-{
-	0x00,0x00,0x00,    /*   800x600 */
-	0x0b,0x0b,0x0b,    /*  1024x768 */
-	0x08,0x08,0x08,    /* 1280x1024 */
-	0x00,0x00,0x00,    /*   640x480 (unknown) */
-	0x00,0x00,0x00,    /*  1024x600 (unknown) */
-	0x00,0x00,0x00,    /*  1152x864 (unknown) */
-	0x08,0x08,0x08,    /*  1280x960 (guessed) */
-	0x00,0x00,0x00,    /*  1152x768 (unknown) */
-	0x08,0x08,0x08,    /* 1400x1050 */
-	0x08,0x08,0x08,    /*  1280x768  (guessed) */
-	0x00,0x00,0x00,    /* 1600x1200 */
-	0x00,0x00,0x00,    /*   320x480 (unknown) */
-	0x00,0x00,0x00,
-	0x00,0x00,0x00,
-	0x00,0x00,0x00
-};
-
-/* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */
-static const unsigned char SiS310_LCDDelayCompensation_650301LV[] =	   	/* 650 + 30xLV */
-{
-	0x01,0x01,0x01,    /*   800x600 */
-	0x01,0x01,0x01,    /*  1024x768 */
-	0x01,0x01,0x01,    /* 1280x1024 */
-	0x01,0x01,0x01,    /*   640x480 (unknown) */
-	0x01,0x01,0x01,    /*  1024x600 (unknown) */
-	0x01,0x01,0x01,    /*  1152x864 (unknown) */
-	0x01,0x01,0x01,    /*  1280x960 (guessed) */
-	0x01,0x01,0x01,    /*  1152x768 (unknown) */
-	0x01,0x01,0x01,    /* 1400x1050 */
-	0x01,0x01,0x01,    /*  1280x768  (guessed) */
-	0x01,0x01,0x01,    /* 1600x1200 */
-	0x02,0x02,0x02,
-	0x02,0x02,0x02,
-	0x02,0x02,0x02,
-	0x02,0x02,0x02
-};
-
-static const unsigned char SiS310_LCDDelayCompensation_651301LV[] =	  	/* M650/651 301LV */
-{
-	0x33,0x33,0x33,    /*   800x600 (guessed) - new: PanelType, not PanelRes ! */
-	0x33,0x33,0x33,    /*  1024x768 */
-	0x33,0x33,0x33,    /* 1280x1024 */
-	0x33,0x33,0x33,    /*   640x480 (unknown) */
-	0x33,0x33,0x33,    /*  1024x600 (unknown) */
-	0x33,0x33,0x33,    /*  1152x864 (unknown) */
-	0x33,0x33,0x33,    /*  1280x960 (guessed) */
-	0x33,0x33,0x33,    /*  1152x768 (unknown) */
-	0x33,0x33,0x33,    /* 1400x1050 */
-	0x33,0x33,0x33,    /*  1280x768  (guessed) */
-	0x33,0x33,0x33,    /* 1600x1200 */
-	0x33,0x33,0x33,
-	0x33,0x33,0x33,
-	0x33,0x33,0x33,
-	0x33,0x33,0x33
-};
-
-static const unsigned char SiS310_LCDDelayCompensation_651302LV[] =	   	/* M650/651 302LV */
-{
-	0x33,0x33,0x33,    /*   800x600 (guessed) */
-	0x33,0x33,0x33,    /*  1024x768 */
-	0x33,0x33,0x33,    /* 1280x1024 */
-	0x33,0x33,0x33,    /*   640x480 (unknown) */
-	0x33,0x33,0x33,    /*  1024x600 (unknown) */
-	0x33,0x33,0x33,    /*  1152x864 (unknown) */
-	0x33,0x33,0x33,    /*  1280x960 (guessed) */
-	0x33,0x33,0x33,    /*  1152x768 (unknown) */
-	0x33,0x33,0x33,    /* 1400x1050 */
-	0x33,0x33,0x33,    /*  1280x768  (guessed) */
-	0x33,0x33,0x33,    /* 1600x1200 */
-	0x33,0x33,0x33,
-	0x33,0x33,0x33,
-	0x33,0x33,0x33,
-	0x33,0x33,0x33
-};
-
-static const unsigned char SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB */
-{
-	0x01,0x01,0x01,    /*   800x600 */
-	0x0C,0x0C,0x0C,    /*  1024x768 */
-	0x0C,0x0C,0x0C,    /* 1280x1024 */
-	0x08,0x08,0x08,    /*   640x480 */
-	0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
-	0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
-	0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
-	0x02,0x02,0x02,
-	0x02,0x02,0x02,
-	0x02,0x02,0x02,
-	0x02,0x02,0x02
-};
-
-static const unsigned char SiS310_LCDDelayCompensation_3xx301LV[] =	   	/* 315+30xLV */
-{
-	0x01,0x01,0x01,    /*   800x600 */
-	0x04,0x04,0x04,    /*  1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
-	0x0C,0x0C,0x0C,    /* 1280x1024 */
-	0x08,0x08,0x08,    /*   640x480 */
-	0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
-	0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
-	0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
-	0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
-	0x02,0x02,0x02,
-	0x02,0x02,0x02,
-	0x02,0x02,0x02,
-	0x02,0x02,0x02
-};
-
-static const unsigned char SiS310_TVDelayCompensation_301[] = 		/* 301 */
-{
-	0x02,0x02,    /* NTSC Enhanced, Standard */
-	0x02,0x02,    /* PAL */
-	0x08,0x0b     /* HiVision */
-};
-
-static const unsigned char SiS310_TVDelayCompensation_301B[] =		/* 30xB, 30xLV */
-{
-	0x03,0x03,
-	0x03,0x03,
-	0x03,0x03
-};
-
-static const unsigned char SiS310_TVDelayCompensation_740301B[] =	/* 740 + 30xB (30xLV?) */
-{
-	0x05,0x05,
-	0x05,0x05,
-	0x05,0x05
-};
-
-static const unsigned char SiS310_TVDelayCompensation_651301LV[] =	/* M650, 651, 301LV */
-{
-	0x33,0x33,
-	0x33,0x33,
-	0x33,0x33
-};
-
-static const unsigned char SiS310_TVDelayCompensation_651302LV[] =	/* M650, 651, 302LV */
-{
-	0x33,0x33,
-	0x33,0x33,
-	0x33,0x33
-};
-
-static const unsigned char SiS_TVDelay661_301[] =			/* 661, 301 */
-{
-	0x44,0x44,
-	0x44,0x44,
-	0x00,0x00,
-	0x44,0x44,
-	0x44,0x44,
-	0x44,0x44
-};
-
-static const unsigned char SiS_TVDelay661_301B[] =			/* 661, 301B et al */
-{
-	0x44,0x44,
-	0x44,0x44,
-	0x00,0x00,
-	0x44,0x44,
-	0x44,0x44,
-	0x44,0x44
-};
-
-static const unsigned char SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
-{
-	0x0a,0x0a,
-	0x0a,0x0a,
-	0x0a,0x0a
-};
-
-static const unsigned char SiS310_TVAntiFlick1[6][2] =
-{
-	{0x4,0x0},
-	{0x4,0x8},
-	{0x0,0x0},
-	{0x0,0x0},
-	{0x0,0x0},
-	{0x0,0x0}
-};
-
-static const unsigned char SiS310_TVEdge1[6][2] =
-{
-	{0x0,0x4},
-	{0x0,0x4},
-	{0x0,0x0},
-	{0x0,0x0},
-	{0x0,0x0},
-	{0x0,0x0}
-};
-
-static const unsigned char SiS310_TVYFilter1[5][8][4] =
-{
-   {
-	{0x00,0xf4,0x10,0x38},	/* NTSC */
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xf1,0x04,0x1f,0x18},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xee,0x0c,0x22,0x08},
-	{0xeb,0x15,0x25,0xf6}
-   },
-   {
-	{0x00,0xf4,0x10,0x38},	/* PAL */
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0x00,0xf4,0x10,0x38},
-	{0xf1,0xf7,0x1f,0x32},
-	{0xf3,0x00,0x1d,0x20},
-	{0xfc,0xfb,0x14,0x2a}
-   },
-   {
-	{0x00,0x00,0x00,0x00},	/* HiVision */
-	{0x00,0xf4,0x10,0x38},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xf7,0x06,0x19,0x14},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xee,0x0c,0x22,0x08}
-   },
-   {
-	{0x00,0xf4,0x10,0x38},	/* PAL-M */
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x10,0x18},
-	{0xf7,0x06,0x19,0x14},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x15,0x25,0xf6}
-   },
-   {
-	{0x00,0xf4,0x10,0x38},	/* PAL-N */
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x10,0x18},
-	{0xf7,0x06,0x19,0x14},
-	{0x00,0xf4,0x10,0x38},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x04,0x25,0x18},
-	{0xeb,0x15,0x25,0xf6}
-   }
-};
-
-static const unsigned char SiS310_TVYFilter2[5][9][7] =
-{
-   {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},	/* NTSC */
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-   },
-   {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* PAL */
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-   },
-   {
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},	/* HiVision */
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
-	{0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}
-   },
-   {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, 	/* PAL-M */
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-   },
-   {
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},	/* PAL-N */
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
-	{0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
-	{0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
-	{0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
-   }
-};
-
-static const unsigned char SiS310_TVPhaseIncr1[3][2][4] =
-{
-   {
-	{0x21,0xed,0xba,0x08},
-	{0x21,0xed,0xba,0x08}
-   },
-   {
-	{0x2a,0x05,0xe3,0x00},
-	{0x2a,0x05,0xe3,0x00}
-   },
-   {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-   }
-};
-
-static const unsigned char SiS310_TVPhaseIncr2[3][2][4] =
-{
-   {
-	{0x21,0xf0,0x7b,0xd6},
-	{0x21,0xf0,0x7b,0xd6}
-   },
-   {
-	{0x2a,0x0a,0x41,0xe9},
-	{0x2a,0x0a,0x41,0xe9}
-   },
-   {
-	{0x2a,0x05,0xd3,0x00},
-	{0x2a,0x05,0xd3,0x00}
-   }
-};
-
-/**************************************************************/
-/* CUSTOM TIMING DATA --------------------------------------- */
-/**************************************************************/
-
-/* Inventec / Compaq Presario 3045US, 3017 */
-
-static const struct SiS_LCDData SiS310_ExtCompaq1280x1024Data[] =
-{
-	{  211,  60,1024, 501,1688,1066},
-	{  211,  60,1024, 508,1688,1066},
-	{  211,  60,1024, 501,1688,1066},
-	{  211,  60,1024, 508,1688,1066},
-	{   32,  15,1696, 501,1696,1066},
-	{  212,  75,1024, 621,1696,1066},
-	{    4,   3,1696, 810,1696,1066},
-	{    1,   1,1696,1066,1696,1066}
-};
-
-/* Asus A2xxxH _2 */
-
-static const struct SiS_Part2PortTbl SiS310_CRT2Part2_Asus1024x768_3[] =
-{
-	{{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
-	{{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
-	{{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
-	{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
-	{{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
-};
-
-
-
-
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
deleted file mode 100644
index 1987f1b7212f..000000000000
--- a/drivers/video/sis/sis.h
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * SiS 300/540/630[S]/730[S],
- * SiS 315[E|PRO]/550/[M]65x/[M]661[F|M]X/740/[M]741[GX]/330/[M]76x[GX],
- * XGI V3XT/V5/V8, Z7
- * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
- *
- * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef _SIS_H_
-#define _SIS_H_
-
-#include <video/sisfb.h>
-
-#include "vgatypes.h"
-#include "vstruct.h"
-
-#define VER_MAJOR		1
-#define VER_MINOR		8
-#define VER_LEVEL		9
-
-#include <linux/spinlock.h>
-
-#ifdef CONFIG_COMPAT
-#define SIS_NEW_CONFIG_COMPAT
-#endif	/* CONFIG_COMPAT */
-
-#undef SISFBDEBUG
-
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-#define TWDEBUG(x) printk(KERN_INFO x "\n");
-#else
-#define DPRINTK(fmt, args...)
-#define TWDEBUG(x)
-#endif
-
-#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
-
-/* To be included in pci_ids.h */
-#ifndef PCI_DEVICE_ID_SI_650_VGA
-#define PCI_DEVICE_ID_SI_650_VGA	0x6325
-#endif
-#ifndef PCI_DEVICE_ID_SI_650
-#define PCI_DEVICE_ID_SI_650		0x0650
-#endif
-#ifndef PCI_DEVICE_ID_SI_651
-#define PCI_DEVICE_ID_SI_651		0x0651
-#endif
-#ifndef PCI_DEVICE_ID_SI_740
-#define PCI_DEVICE_ID_SI_740		0x0740
-#endif
-#ifndef PCI_DEVICE_ID_SI_330
-#define PCI_DEVICE_ID_SI_330		0x0330
-#endif
-#ifndef PCI_DEVICE_ID_SI_660_VGA
-#define PCI_DEVICE_ID_SI_660_VGA	0x6330
-#endif
-#ifndef PCI_DEVICE_ID_SI_661
-#define PCI_DEVICE_ID_SI_661		0x0661
-#endif
-#ifndef PCI_DEVICE_ID_SI_741
-#define PCI_DEVICE_ID_SI_741		0x0741
-#endif
-#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660		0x0660
-#endif
-#ifndef PCI_DEVICE_ID_SI_760
-#define PCI_DEVICE_ID_SI_760		0x0760
-#endif
-#ifndef PCI_DEVICE_ID_SI_761
-#define PCI_DEVICE_ID_SI_761		0x0761
-#endif
-
-#ifndef PCI_VENDOR_ID_XGI
-#define PCI_VENDOR_ID_XGI		0x18ca
-#endif
-
-#ifndef PCI_DEVICE_ID_XGI_20
-#define PCI_DEVICE_ID_XGI_20		0x0020
-#endif
-
-#ifndef PCI_DEVICE_ID_XGI_40
-#define PCI_DEVICE_ID_XGI_40		0x0040
-#endif
-
-/* To be included in fb.h */
-#ifndef FB_ACCEL_SIS_GLAMOUR_2
-#define FB_ACCEL_SIS_GLAMOUR_2	40	/* SiS 315, 65x, 740, 661, 741  */
-#endif
-#ifndef FB_ACCEL_SIS_XABRE
-#define FB_ACCEL_SIS_XABRE	41	/* SiS 330 ("Xabre"), 76x 	*/
-#endif
-#ifndef FB_ACCEL_XGI_VOLARI_V
-#define FB_ACCEL_XGI_VOLARI_V	47	/* XGI Volari Vx (V3XT, V5, V8)	*/
-#endif
-#ifndef FB_ACCEL_XGI_VOLARI_Z
-#define FB_ACCEL_XGI_VOLARI_Z	48	/* XGI Volari Z7		*/
-#endif
-
-/* ivideo->caps */
-#define HW_CURSOR_CAP		0x80
-#define TURBO_QUEUE_CAP		0x40
-#define AGP_CMD_QUEUE_CAP	0x20
-#define VM_CMD_QUEUE_CAP	0x10
-#define MMIO_CMD_QUEUE_CAP	0x08
-
-/* For 300 series */
-#define TURBO_QUEUE_AREA_SIZE	(512 * 1024)	/* 512K */
-#define HW_CURSOR_AREA_SIZE_300	4096		/* 4K */
-
-/* For 315/Xabre series */
-#define COMMAND_QUEUE_AREA_SIZE	(512 * 1024)	/* 512K */
-#define COMMAND_QUEUE_AREA_SIZE_Z7 (128 * 1024)	/* 128k for XGI Z7 */
-#define HW_CURSOR_AREA_SIZE_315	16384		/* 16K */
-#define COMMAND_QUEUE_THRESHOLD	0x1F
-
-#define SIS_OH_ALLOC_SIZE	4000
-#define SENTINEL		0x7fffffff
-
-#define SEQ_ADR			0x14
-#define SEQ_DATA		0x15
-#define DAC_ADR			0x18
-#define DAC_DATA		0x19
-#define CRTC_ADR		0x24
-#define CRTC_DATA		0x25
-#define DAC2_ADR		(0x16-0x30)
-#define DAC2_DATA		(0x17-0x30)
-#define VB_PART1_ADR		(0x04-0x30)
-#define VB_PART1_DATA		(0x05-0x30)
-#define VB_PART2_ADR		(0x10-0x30)
-#define VB_PART2_DATA		(0x11-0x30)
-#define VB_PART3_ADR		(0x12-0x30)
-#define VB_PART3_DATA		(0x13-0x30)
-#define VB_PART4_ADR		(0x14-0x30)
-#define VB_PART4_DATA		(0x15-0x30)
-
-#define SISSR			ivideo->SiS_Pr.SiS_P3c4
-#define SISCR			ivideo->SiS_Pr.SiS_P3d4
-#define SISDACA			ivideo->SiS_Pr.SiS_P3c8
-#define SISDACD			ivideo->SiS_Pr.SiS_P3c9
-#define SISPART1		ivideo->SiS_Pr.SiS_Part1Port
-#define SISPART2		ivideo->SiS_Pr.SiS_Part2Port
-#define SISPART3		ivideo->SiS_Pr.SiS_Part3Port
-#define SISPART4		ivideo->SiS_Pr.SiS_Part4Port
-#define SISPART5		ivideo->SiS_Pr.SiS_Part5Port
-#define SISDAC2A		SISPART5
-#define SISDAC2D		(SISPART5 + 1)
-#define SISMISCR		(ivideo->SiS_Pr.RelIO + 0x1c)
-#define SISMISCW		ivideo->SiS_Pr.SiS_P3c2
-#define SISINPSTAT		(ivideo->SiS_Pr.RelIO + 0x2a)
-#define SISPEL			ivideo->SiS_Pr.SiS_P3c6
-#define SISVGAENABLE		(ivideo->SiS_Pr.RelIO + 0x13)
-#define SISVID			(ivideo->SiS_Pr.RelIO + 0x02 - 0x30)
-#define SISCAP			(ivideo->SiS_Pr.RelIO + 0x00 - 0x30)
-
-#define IND_SIS_PASSWORD		0x05  /* SRs */
-#define IND_SIS_COLOR_MODE		0x06
-#define IND_SIS_RAMDAC_CONTROL		0x07
-#define IND_SIS_DRAM_SIZE		0x14
-#define IND_SIS_MODULE_ENABLE		0x1E
-#define IND_SIS_PCI_ADDRESS_SET		0x20
-#define IND_SIS_TURBOQUEUE_ADR		0x26
-#define IND_SIS_TURBOQUEUE_SET		0x27
-#define IND_SIS_POWER_ON_TRAP		0x38
-#define IND_SIS_POWER_ON_TRAP2		0x39
-#define IND_SIS_CMDQUEUE_SET		0x26
-#define IND_SIS_CMDQUEUE_THRESHOLD	0x27
-
-#define IND_SIS_AGP_IO_PAD	0x48
-
-#define SIS_CRT2_WENABLE_300	0x24  /* Part1 */
-#define SIS_CRT2_WENABLE_315	0x2F
-
-#define SIS_PASSWORD		0x86  /* SR05 */
-
-#define SIS_INTERLACED_MODE	0x20  /* SR06 */
-#define SIS_8BPP_COLOR_MODE	0x0
-#define SIS_15BPP_COLOR_MODE	0x1
-#define SIS_16BPP_COLOR_MODE	0x2
-#define SIS_32BPP_COLOR_MODE	0x4
-
-#define SIS_ENABLE_2D		0x40  /* SR1E */
-
-#define SIS_MEM_MAP_IO_ENABLE	0x01  /* SR20 */
-#define SIS_PCI_ADDR_ENABLE	0x80
-
-#define SIS_AGP_CMDQUEUE_ENABLE		0x80  /* 315/330/340 series SR26 */
-#define SIS_VRAM_CMDQUEUE_ENABLE	0x40
-#define SIS_MMIO_CMD_ENABLE		0x20
-#define SIS_CMD_QUEUE_SIZE_512k		0x00
-#define SIS_CMD_QUEUE_SIZE_1M		0x04
-#define SIS_CMD_QUEUE_SIZE_2M		0x08
-#define SIS_CMD_QUEUE_SIZE_4M		0x0C
-#define SIS_CMD_QUEUE_RESET		0x01
-#define SIS_CMD_AUTO_CORR		0x02
-
-#define SIS_CMD_QUEUE_SIZE_Z7_64k	0x00 /* XGI Z7 */
-#define SIS_CMD_QUEUE_SIZE_Z7_128k	0x04
-
-#define SIS_SIMULTANEOUS_VIEW_ENABLE	0x01  /* CR30 */
-#define SIS_MODE_SELECT_CRT2		0x02
-#define SIS_VB_OUTPUT_COMPOSITE		0x04
-#define SIS_VB_OUTPUT_SVIDEO		0x08
-#define SIS_VB_OUTPUT_SCART		0x10
-#define SIS_VB_OUTPUT_LCD		0x20
-#define SIS_VB_OUTPUT_CRT2		0x40
-#define SIS_VB_OUTPUT_HIVISION		0x80
-
-#define SIS_VB_OUTPUT_DISABLE	0x20  /* CR31 */
-#define SIS_DRIVER_MODE		0x40
-
-#define SIS_VB_COMPOSITE	0x01  /* CR32 */
-#define SIS_VB_SVIDEO		0x02
-#define SIS_VB_SCART		0x04
-#define SIS_VB_LCD		0x08
-#define SIS_VB_CRT2		0x10
-#define SIS_CRT1		0x20
-#define SIS_VB_HIVISION		0x40
-#define SIS_VB_YPBPR		0x80
-#define SIS_VB_TV		(SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
-				SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
-
-#define SIS_EXTERNAL_CHIP_MASK			0x0E  /* CR37 (< SiS 660) */
-#define SIS_EXTERNAL_CHIP_SIS301		0x01  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS			0x02
-#define SIS_EXTERNAL_CHIP_TRUMPION		0x03
-#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL		0x04
-#define SIS_EXTERNAL_CHIP_CHRONTEL		0x05
-#define SIS310_EXTERNAL_CHIP_LVDS		0x02
-#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL	0x03
-
-#define SIS_AGP_2X		0x20  /* CR48 */
-
-/* vbflags, private entries (others in sisfb.h) */
-#define VB_CONEXANT		0x00000800	/* 661 series only */
-#define VB_TRUMPION		VB_CONEXANT	/* 300 series only */
-#define VB_302ELV		0x00004000
-#define VB_301			0x00100000	/* Video bridge type */
-#define VB_301B			0x00200000
-#define VB_302B			0x00400000
-#define VB_30xBDH		0x00800000	/* 30xB DH version (w/o LCD support) */
-#define VB_LVDS			0x01000000
-#define VB_CHRONTEL		0x02000000
-#define VB_301LV		0x04000000
-#define VB_302LV		0x08000000
-#define VB_301C			0x10000000
-
-#define VB_SISBRIDGE		(VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
-#define VB_VIDEOBRIDGE		(VB_SISBRIDGE | VB_LVDS | VB_CHRONTEL | VB_CONEXANT)
-
-/* vbflags2 (static stuff only!) */
-#define VB2_SISUMC		0x00000001
-#define VB2_301			0x00000002	/* Video bridge type */
-#define VB2_301B		0x00000004
-#define VB2_301C		0x00000008
-#define VB2_307T		0x00000010
-#define VB2_302B		0x00000800
-#define VB2_301LV		0x00001000
-#define VB2_302LV		0x00002000
-#define VB2_302ELV		0x00004000
-#define VB2_307LV		0x00008000
-#define VB2_30xBDH		0x08000000      /* 30xB DH version (w/o LCD support) */
-#define VB2_CONEXANT		0x10000000
-#define VB2_TRUMPION		0x20000000
-#define VB2_LVDS		0x40000000
-#define VB2_CHRONTEL		0x80000000
-
-#define VB2_SISLVDSBRIDGE	(VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
-#define VB2_SISTMDSBRIDGE	(VB2_301   | VB2_301B  | VB2_301C   | VB2_302B | VB2_307T)
-#define VB2_SISBRIDGE		(VB2_SISLVDSBRIDGE | VB2_SISTMDSBRIDGE)
-
-#define VB2_SISTMDSLCDABRIDGE	(VB2_301C | VB2_307T)
-#define VB2_SISLCDABRIDGE	(VB2_SISTMDSLCDABRIDGE | VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
-
-#define VB2_SISHIVISIONBRIDGE	(VB2_301  | VB2_301B | VB2_302B)
-#define VB2_SISYPBPRBRIDGE	(VB2_301C | VB2_307T | VB2_SISLVDSBRIDGE)
-#define VB2_SISYPBPRARBRIDGE	(VB2_301C | VB2_307T | VB2_307LV)
-#define VB2_SISTAP4SCALER	(VB2_301C | VB2_307T | VB2_302ELV | VB2_307LV)
-#define VB2_SISTVBRIDGE		(VB2_SISHIVISIONBRIDGE | VB2_SISYPBPRBRIDGE)
-
-#define VB2_SISVGA2BRIDGE	(VB2_301 | VB2_301B | VB2_301C | VB2_302B | VB2_307T)
-
-#define VB2_VIDEOBRIDGE		(VB2_SISBRIDGE | VB2_LVDS | VB2_CHRONTEL | VB2_CONEXANT)
-
-#define VB2_30xB		(VB2_301B  | VB2_301C   | VB2_302B  | VB2_307T)
-#define VB2_30xBLV		(VB2_30xB  | VB2_SISLVDSBRIDGE)
-#define VB2_30xC		(VB2_301C  | VB2_307T)
-#define VB2_30xCLV		(VB2_301C  | VB2_307T   | VB2_302ELV| VB2_307LV)
-#define VB2_SISEMIBRIDGE	(VB2_302LV | VB2_302ELV | VB2_307LV)
-#define VB2_LCD162MHZBRIDGE	(VB2_301C  | VB2_307T)
-#define VB2_LCDOVER1280BRIDGE	(VB2_301C  | VB2_307T   | VB2_302LV | VB2_302ELV | VB2_307LV)
-#define VB2_LCDOVER1600BRIDGE	(VB2_307T  | VB2_307LV)
-#define VB2_RAMDAC202MHZBRIDGE	(VB2_301C  | VB2_307T)
-
-/* I/O port access functions */
-
-void SiS_SetReg(SISIOADDRESS, u8, u8);
-void SiS_SetRegByte(SISIOADDRESS, u8);
-void SiS_SetRegShort(SISIOADDRESS, u16);
-void SiS_SetRegLong(SISIOADDRESS, u32);
-void SiS_SetRegANDOR(SISIOADDRESS, u8, u8, u8);
-void SiS_SetRegAND(SISIOADDRESS, u8, u8);
-void SiS_SetRegOR(SISIOADDRESS, u8, u8);
-u8 SiS_GetReg(SISIOADDRESS, u8);
-u8 SiS_GetRegByte(SISIOADDRESS);
-u16 SiS_GetRegShort(SISIOADDRESS);
-u32 SiS_GetRegLong(SISIOADDRESS);
-
-/* MMIO access macros */
-#define MMIO_IN8(base, offset)  readb((base+offset))
-#define MMIO_IN16(base, offset) readw((base+offset))
-#define MMIO_IN32(base, offset) readl((base+offset))
-
-#define MMIO_OUT8(base, offset, val)  writeb(((u8)(val)), (base+offset))
-#define MMIO_OUT16(base, offset, val) writew(((u16)(val)), (base+offset))
-#define MMIO_OUT32(base, offset, val) writel(((u32)(val)), (base+offset))
-
-/* Queue control MMIO registers */
-#define Q_BASE_ADDR		0x85C0  /* Base address of software queue */
-#define Q_WRITE_PTR		0x85C4  /* Current write pointer */
-#define Q_READ_PTR		0x85C8  /* Current read pointer */
-#define Q_STATUS		0x85CC  /* queue status */
-
-#define MMIO_QUEUE_PHYBASE      Q_BASE_ADDR
-#define MMIO_QUEUE_WRITEPORT    Q_WRITE_PTR
-#define MMIO_QUEUE_READPORT     Q_READ_PTR
-
-#ifndef FB_BLANK_UNBLANK
-#define FB_BLANK_UNBLANK	0
-#endif
-#ifndef FB_BLANK_NORMAL
-#define FB_BLANK_NORMAL		1
-#endif
-#ifndef FB_BLANK_VSYNC_SUSPEND
-#define FB_BLANK_VSYNC_SUSPEND	2
-#endif
-#ifndef FB_BLANK_HSYNC_SUSPEND
-#define FB_BLANK_HSYNC_SUSPEND	3
-#endif
-#ifndef FB_BLANK_POWERDOWN
-#define FB_BLANK_POWERDOWN	4
-#endif
-
-enum _SIS_LCD_TYPE {
-    LCD_INVALID = 0,
-    LCD_800x600,
-    LCD_1024x768,
-    LCD_1280x1024,
-    LCD_1280x960,
-    LCD_640x480,
-    LCD_1600x1200,
-    LCD_1920x1440,
-    LCD_2048x1536,
-    LCD_320x240,	/* FSTN */
-    LCD_1400x1050,
-    LCD_1152x864,
-    LCD_1152x768,
-    LCD_1280x768,
-    LCD_1024x600,
-    LCD_320x240_2,	/* DSTN */
-    LCD_320x240_3,	/* DSTN */
-    LCD_848x480,
-    LCD_1280x800,
-    LCD_1680x1050,
-    LCD_1280x720,
-    LCD_1280x854,
-    LCD_CUSTOM,
-    LCD_UNKNOWN
-};
-
-enum _SIS_CMDTYPE {
-    MMIO_CMD = 0,
-    AGP_CMD_QUEUE,
-    VM_CMD_QUEUE,
-};
-
-struct SIS_OH {
-	struct SIS_OH *poh_next;
-	struct SIS_OH *poh_prev;
-	u32            offset;
-	u32            size;
-};
-
-struct SIS_OHALLOC {
-	struct SIS_OHALLOC *poha_next;
-	struct SIS_OH aoh[1];
-};
-
-struct SIS_HEAP {
-	struct SIS_OH	oh_free;
-	struct SIS_OH	oh_used;
-	struct SIS_OH	*poh_freelist;
-	struct SIS_OHALLOC *poha_chain;
-	u32		max_freesize;
-	struct sis_video_info *vinfo;
-};
-
-/* Our "par" */
-struct sis_video_info {
-	int		cardnumber;
-	struct fb_info  *memyselfandi;
-
-	struct SiS_Private SiS_Pr;
-
-	struct sisfb_info sisfbinfo;	/* For ioctl SISFB_GET_INFO */
-
-	struct fb_var_screeninfo default_var;
-
-	struct fb_fix_screeninfo sisfb_fix;
-	u32		pseudo_palette[16];
-
-	struct sisfb_monitor {
-		u16 hmin;
-		u16 hmax;
-		u16 vmin;
-		u16 vmax;
-		u32 dclockmax;
-		u8  feature;
-		bool datavalid;
-	}		sisfb_thismonitor;
-
-	unsigned short	chip_id;	/* PCI ID of chip */
-	unsigned short	chip_vendor;	/* PCI ID of vendor */
-	char		myid[40];
-
-	struct pci_dev  *nbridge;
-	struct pci_dev  *lpcdev;
-
-	int		mni;	/* Mode number index */
-
-	unsigned long	video_size;
-	unsigned long	video_base;
-	unsigned long	mmio_size;
-	unsigned long	mmio_base;
-	unsigned long	vga_base;
-
-	unsigned long	video_offset;
-
-	unsigned long	UMAsize, LFBsize;
-
-	void __iomem	*video_vbase;
-	void __iomem	*mmio_vbase;
-
-	unsigned char	*bios_abase;
-
-	int		mtrr;
-
-	u32		sisfb_mem;
-
-	u32		sisfb_parm_mem;
-	int		sisfb_accel;
-	int		sisfb_ypan;
-	int		sisfb_max;
-	int		sisfb_userom;
-	int		sisfb_useoem;
-	int		sisfb_mode_idx;
-	int		sisfb_parm_rate;
-	int		sisfb_crt1off;
-	int		sisfb_forcecrt1;
-	int		sisfb_crt2type;
-	int		sisfb_crt2flags;
-	int		sisfb_dstn;
-	int		sisfb_fstn;
-	int		sisfb_tvplug;
-	int		sisfb_tvstd;
-	int		sisfb_nocrt2rate;
-
-	u32		heapstart;		/* offset  */
-	void __iomem	*sisfb_heap_start;	/* address */
-	void __iomem	*sisfb_heap_end;	/* address */
-	u32		sisfb_heap_size;
-	int		havenoheap;
-
-	struct SIS_HEAP	sisfb_heap;		/* This card's vram heap */
-
-	int		video_bpp;
-	int		video_cmap_len;
-	int		video_width;
-	int		video_height;
-	unsigned int	refresh_rate;
-
-	unsigned int	chip;
-	unsigned int	chip_real_id;
-	u8		revision_id;
-	int		sisvga_enabled;		/* PCI device was enabled */
-
-	int		video_linelength;	/* real pitch */
-	int		scrnpitchCRT1;		/* pitch regarding interlace */
-
-	u16		DstColor;		/* For 2d acceleration */
-	u32		SiS310_AccelDepth;
-	u32		CommandReg;
-	int		cmdqueuelength;		/* Current (for accel) */
-	u32		cmdQueueSize;		/* Total size in KB */
-
-	spinlock_t	lockaccel;		/* Do not use outside of kernel! */
-
-	unsigned int	pcibus;
-	unsigned int	pcislot;
-	unsigned int	pcifunc;
-
-	int		accel;
-	int		engineok;
-
-	u16		subsysvendor;
-	u16		subsysdevice;
-
-	u32		vbflags;		/* Replacing deprecated stuff from above */
-	u32		currentvbflags;
-	u32		vbflags2;
-
-	int		lcdxres, lcdyres;
-	int		lcddefmodeidx, tvdefmodeidx, defmodeidx;
-	u32		CRT2LCDType;		/* defined in "SIS_LCD_TYPE" */
-	u32		curFSTN, curDSTN;
-
-	int		current_bpp;
-	int		current_width;
-	int		current_height;
-	int		current_htotal;
-	int		current_vtotal;
-	int		current_linelength;
-	__u32		current_pixclock;
-	int		current_refresh_rate;
-
-	unsigned int	current_base;
-
-	u8		mode_no;
-	u8		rate_idx;
-	int		modechanged;
-	unsigned char	modeprechange;
-
-	u8		sisfb_lastrates[128];
-
-	int		newrom;
-	int		haveXGIROM;
-	int		registered;
-	int		warncount;
-
-	int		sisvga_engine;
-	int		hwcursor_size;
-	int		CRT2_write_enable;
-	u8		caps;
-
-	u8		detectedpdc;
-	u8		detectedpdca;
-	u8		detectedlcda;
-
-	void __iomem	*hwcursor_vbase;
-
-	int		chronteltype;
-	int		tvxpos, tvypos;
-	u8		p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
-	int		tvx, tvy;
-
-	u8		sisfblocked;
-
-	struct sisfb_info sisfb_infoblock;
-
-	struct sisfb_cmd sisfb_command;
-
-	u32		sisfb_id;
-
-	u8		sisfb_can_post;
-	u8		sisfb_card_posted;
-	u8		sisfb_was_boot_device;
-
-	struct sis_video_info *next;
-};
-
-#endif
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
deleted file mode 100644
index ceb434c95c0d..000000000000
--- a/drivers/video/sis/sis_accel.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * SiS 300/540/630[S]/730[S],
- * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
- * XGI V3XT/V5/V8, Z7
- * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
- *
- * 2D acceleration part
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Based on the XFree86/X.org driver which is
- *     Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
- *			(see http://www.winischhofer.net/
- *			for more information and updates)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <asm/io.h>
-
-#include "sis.h"
-#include "sis_accel.h"
-
-static const u8 sisALUConv[] =
-{
-    0x00,       /* dest = 0;            0,      GXclear,        0 */
-    0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
-    0x44,       /* dest = src & ~dest;  SDna,   GXandReverse,   0x2 */
-    0xCC,       /* dest = src;          S,      GXcopy,         0x3 */
-    0x22,       /* dest &= ~src;        DSna,   GXandInverted,  0x4 */
-    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
-    0x66,       /* dest = ^src;         DSx,    GXxor,          0x6 */
-    0xEE,       /* dest |= src;         DSo,    GXor,           0x7 */
-    0x11,       /* dest = ~src & ~dest; DSon,   GXnor,          0x8 */
-    0x99,       /* dest ^= ~src ;       DSxn,   GXequiv,        0x9 */
-    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
-    0xDD,       /* dest = src|~dest ;   SDno,   GXorReverse,    0xB */
-    0x33,       /* dest = ~src;         Sn,     GXcopyInverted, 0xC */
-    0xBB,       /* dest |= ~src;        DSno,   GXorInverted,   0xD */
-    0x77,       /* dest = ~src|~dest;   DSan,   GXnand,         0xE */
-    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
-};
-/* same ROP but with Pattern as Source */
-static const u8 sisPatALUConv[] =
-{
-    0x00,       /* dest = 0;            0,      GXclear,        0 */
-    0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
-    0x50,       /* dest = src & ~dest;  PDna,   GXandReverse,   0x2 */
-    0xF0,       /* dest = src;          P,      GXcopy,         0x3 */
-    0x0A,       /* dest &= ~src;        DPna,   GXandInverted,  0x4 */
-    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
-    0x5A,       /* dest = ^src;         DPx,    GXxor,          0x6 */
-    0xFA,       /* dest |= src;         DPo,    GXor,           0x7 */
-    0x05,       /* dest = ~src & ~dest; DPon,   GXnor,          0x8 */
-    0xA5,       /* dest ^= ~src ;       DPxn,   GXequiv,        0x9 */
-    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
-    0xF5,       /* dest = src|~dest ;   PDno,   GXorReverse,    0xB */
-    0x0F,       /* dest = ~src;         Pn,     GXcopyInverted, 0xC */
-    0xAF,       /* dest |= ~src;        DPno,   GXorInverted,   0xD */
-    0x5F,       /* dest = ~src|~dest;   DPan,   GXnand,         0xE */
-    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
-};
-
-static const int myrops[] = {
-   	3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
-};
-
-/* 300 series ----------------------------------------------------- */
-#ifdef CONFIG_FB_SIS_300
-static void
-SiS300Sync(struct sis_video_info *ivideo)
-{
-	SiS300Idle
-}
-
-static void
-SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir,
-                                 int rop, int trans_color)
-{
-	SiS300SetupDSTColorDepth(ivideo->DstColor);
-	SiS300SetupSRCPitch(ivideo->video_linelength)
-	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
-
-	if(trans_color != -1) {
-		SiS300SetupROP(0x0A)
-		SiS300SetupSRCTrans(trans_color)
-		SiS300SetupCMDFlag(TRANSPARENT_BITBLT)
-	} else {
-	        SiS300SetupROP(sisALUConv[rop])
-	}
-	if(xdir > 0) {
-		SiS300SetupCMDFlag(X_INC)
-	}
-	if(ydir > 0) {
-		SiS300SetupCMDFlag(Y_INC)
-	}
-}
-
-static void
-SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x,
-				   int src_y, int dst_x, int dst_y, int width, int height)
-{
-	u32 srcbase = 0, dstbase = 0;
-
-	if(src_y >= 2048) {
-		srcbase = ivideo->video_linelength * src_y;
-		src_y = 0;
-	}
-	if(dst_y >= 2048) {
-		dstbase = ivideo->video_linelength * dst_y;
-		dst_y = 0;
-	}
-
-	SiS300SetupSRCBase(srcbase);
-	SiS300SetupDSTBase(dstbase);
-
-	if(!(ivideo->CommandReg & X_INC))  {
-		src_x += width-1;
-		dst_x += width-1;
-	}
-	if(!(ivideo->CommandReg & Y_INC))  {
-		src_y += height-1;
-		dst_y += height-1;
-	}
-	SiS300SetupRect(width, height)
-	SiS300SetupSRCXY(src_x, src_y)
-	SiS300SetupDSTXY(dst_x, dst_y)
-	SiS300DoCMD
-}
-
-static void
-SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
-{
-	SiS300SetupPATFG(color)
-	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
-	SiS300SetupDSTColorDepth(ivideo->DstColor);
-	SiS300SetupROP(sisPatALUConv[rop])
-	SiS300SetupCMDFlag(PATFG)
-}
-
-static void
-SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
-{
-	u32 dstbase = 0;
-
-	if(y >= 2048) {
-		dstbase = ivideo->video_linelength * y;
-		y = 0;
-	}
-	SiS300SetupDSTBase(dstbase)
-	SiS300SetupDSTXY(x,y)
-	SiS300SetupRect(w,h)
-	SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT)
-	SiS300DoCMD
-}
-#endif
-
-/* 315/330/340 series ---------------------------------------------- */
-
-#ifdef CONFIG_FB_SIS_315
-static void
-SiS310Sync(struct sis_video_info *ivideo)
-{
-	SiS310Idle
-}
-
-static void
-SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color)
-{
-	SiS310SetupDSTColorDepth(ivideo->DstColor);
-	SiS310SetupSRCPitch(ivideo->video_linelength)
-	SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
-	if(trans_color != -1) {
-		SiS310SetupROP(0x0A)
-		SiS310SetupSRCTrans(trans_color)
-		SiS310SetupCMDFlag(TRANSPARENT_BITBLT)
-	} else {
-	        SiS310SetupROP(sisALUConv[rop])
-		/* Set command - not needed, both 0 */
-		/* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
-	}
-	SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
-	/* The chip is smart enough to know the direction */
-}
-
-static void
-SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y,
-			 int dst_x, int dst_y, int width, int height)
-{
-	u32 srcbase = 0, dstbase = 0;
-	int mymin = min(src_y, dst_y);
-	int mymax = max(src_y, dst_y);
-
-	/* Although the chip knows the direction to use
-	 * if the source and destination areas overlap,
-	 * that logic fails if we fiddle with the bitmap
-	 * addresses. Therefore, we check if the source
-	 * and destination blitting areas overlap and
-	 * adapt the bitmap addresses synchronously
-	 * if the coordinates exceed the valid range.
-	 * The the areas do not overlap, we do our
-	 * normal check.
-	 */
-	if((mymax - mymin) < height) {
-		if((src_y >= 2048) || (dst_y >= 2048)) {
-			srcbase = ivideo->video_linelength * mymin;
-			dstbase = ivideo->video_linelength * mymin;
-			src_y -= mymin;
-			dst_y -= mymin;
-		}
-	} else {
-		if(src_y >= 2048) {
-			srcbase = ivideo->video_linelength * src_y;
-			src_y = 0;
-		}
-		if(dst_y >= 2048) {
-			dstbase = ivideo->video_linelength * dst_y;
-			dst_y = 0;
-		}
-	}
-
-	srcbase += ivideo->video_offset;
-	dstbase += ivideo->video_offset;
-
-	SiS310SetupSRCBase(srcbase);
-	SiS310SetupDSTBase(dstbase);
-	SiS310SetupRect(width, height)
-	SiS310SetupSRCXY(src_x, src_y)
-	SiS310SetupDSTXY(dst_x, dst_y)
-	SiS310DoCMD
-}
-
-static void
-SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
-{
-	SiS310SetupPATFG(color)
-	SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
-	SiS310SetupDSTColorDepth(ivideo->DstColor);
-	SiS310SetupROP(sisPatALUConv[rop])
-	SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
-}
-
-static void
-SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
-{
-	u32 dstbase = 0;
-
-	if(y >= 2048) {
-		dstbase = ivideo->video_linelength * y;
-		y = 0;
-	}
-	dstbase += ivideo->video_offset;
-	SiS310SetupDSTBase(dstbase)
-	SiS310SetupDSTXY(x,y)
-	SiS310SetupRect(w,h)
-	SiS310SetupCMDFlag(BITBLT)
-	SiS310DoCMD
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-/* The exported routines */
-
-int sisfb_initaccel(struct sis_video_info *ivideo)
-{
-#ifdef SISFB_USE_SPINLOCKS
-	spin_lock_init(&ivideo->lockaccel);
-#endif
-	return 0;
-}
-
-void sisfb_syncaccel(struct sis_video_info *ivideo)
-{
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-		SiS300Sync(ivideo);
-#endif
-	} else {
-#ifdef CONFIG_FB_SIS_315
-		SiS310Sync(ivideo);
-#endif
-	}
-}
-
-int fbcon_sis_sync(struct fb_info *info)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-	CRITFLAGS
-
-	if((!ivideo->accel) || (!ivideo->engineok))
-		return 0;
-
-	CRITBEGIN
-	sisfb_syncaccel(ivideo);
-	CRITEND
-
-	return 0;
-}
-
-void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-	u32 col = 0;
-	u32 vxres = info->var.xres_virtual;
-	u32 vyres = info->var.yres_virtual;
-	int width, height;
-	CRITFLAGS
-
-	if(info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if((!ivideo->accel) || (!ivideo->engineok)) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres)
-		return;
-
-	/* Clipping */
-	width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
-	height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
-
-	switch(info->var.bits_per_pixel) {
-	case 8:  col = rect->color;
-		 break;
-	case 16:
-	case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
-		 break;
-	}
-
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-		CRITBEGIN
-		SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
-		SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
-		CRITEND
-#endif
-	} else {
-#ifdef CONFIG_FB_SIS_315
-		CRITBEGIN
-		SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
-		SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
-		CRITEND
-#endif
-	}
-
-	sisfb_syncaccel(ivideo);
-}
-
-void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-	u32 vxres = info->var.xres_virtual;
-	u32 vyres = info->var.yres_virtual;
-	int width = area->width;
-	int height = area->height;
-	CRITFLAGS
-
-	if(info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if((!ivideo->accel) || (!ivideo->engineok)) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	if(!width || !height ||
-	   area->sx >= vxres || area->sy >= vyres ||
-	   area->dx >= vxres || area->dy >= vyres)
-		return;
-
-	/* Clipping */
-	if((area->sx + width) > vxres) width = vxres - area->sx;
-	if((area->dx + width) > vxres) width = vxres - area->dx;
-	if((area->sy + height) > vyres) height = vyres - area->sy;
-	if((area->dy + height) > vyres) height = vyres - area->dy;
-
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-		int xdir, ydir;
-
-		if(area->sx < area->dx) xdir = 0;
-		else                    xdir = 1;
-		if(area->sy < area->dy) ydir = 0;
-		else                    ydir = 1;
-
-		CRITBEGIN
-		SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
-		SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
-					area->dx, area->dy, width, height);
-		CRITEND
-#endif
-	} else {
-#ifdef CONFIG_FB_SIS_315
-		CRITBEGIN
-		SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
-		SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
-					area->dx, area->dy, width, height);
-		CRITEND
-#endif
-	}
-
-	sisfb_syncaccel(ivideo);
-}
diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/sis/sis_accel.h
deleted file mode 100644
index 30e03cdf6b85..000000000000
--- a/drivers/video/sis/sis_accel.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * SiS 300/540/630[S]/730[S],
- * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
- * XGI V3XT/V5/V8, Z7
- * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
- *
- * 2D acceleration part
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Based on the X driver's sis300_accel.h which is
- *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
- * and sis310_accel.h which is
- *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
- *
- * Author:   Thomas Winischhofer <thomas@winischhofer.net>:
- *			(see http://www.winischhofer.net/
- *			for more information and updates)
- */
-
-#ifndef _SISFB_ACCEL_H
-#define _SISFB_ACCEL_H
-
-/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */
-#undef SISFB_USE_SPINLOCKS
-
-#ifdef SISFB_USE_SPINLOCKS
-#include <linux/spinlock.h>
-#define CRITBEGIN  spin_lock_irqsave(&ivideo->lockaccel, critflags);
-#define CRITEND	   spin_unlock_irqrestore(&ivideo->lockaccel, critflags);
-#define CRITFLAGS  unsigned long critflags;
-#else
-#define CRITBEGIN
-#define CRITEND
-#define CRITFLAGS
-#endif
-
-/* Definitions for the SIS engine communication. */
-
-#define PATREGSIZE      384  /* Pattern register size. 384 bytes @ 0x8300 */
-#define BR(x)   (0x8200 | (x) << 2)
-#define PBR(x)  (0x8300 | (x) << 2)
-
-/* SiS300 engine commands */
-#define BITBLT                  0x00000000  /* Blit */
-#define COLOREXP                0x00000001  /* Color expand */
-#define ENCOLOREXP              0x00000002  /* Enhanced color expand */
-#define MULTIPLE_SCANLINE       0x00000003  /* ? */
-#define LINE                    0x00000004  /* Draw line */
-#define TRAPAZOID_FILL          0x00000005  /* Fill trapezoid */
-#define TRANSPARENT_BITBLT      0x00000006  /* Transparent Blit */
-
-/* Additional engine commands for 315 */
-#define ALPHA_BLEND		0x00000007  /* Alpha blend ? */
-#define A3D_FUNCTION		0x00000008  /* 3D command ? */
-#define	CLEAR_Z_BUFFER		0x00000009  /* ? */
-#define GRADIENT_FILL		0x0000000A  /* Gradient fill */
-
-/* source select */
-#define SRCVIDEO                0x00000000  /* source is video RAM */
-#define SRCSYSTEM               0x00000010  /* source is system memory */
-#define SRCCPUBLITBUF           SRCSYSTEM   /* source is CPU-driven BitBuffer (for color expand) */
-#define SRCAGP                  0x00000020  /* source is AGP memory (?) */
-
-/* Pattern flags */
-#define PATFG                   0x00000000  /* foreground color */
-#define PATPATREG               0x00000040  /* pattern in pattern buffer (0x8300) */
-#define PATMONO                 0x00000080  /* mono pattern */
-
-/* blitting direction (300 series only) */
-#define X_INC                   0x00010000
-#define X_DEC                   0x00000000
-#define Y_INC                   0x00020000
-#define Y_DEC                   0x00000000
-
-/* Clipping flags */
-#define NOCLIP                  0x00000000
-#define NOMERGECLIP             0x04000000
-#define CLIPENABLE              0x00040000
-#define CLIPWITHOUTMERGE        0x04040000
-
-/* Transparency */
-#define OPAQUE                  0x00000000
-#define TRANSPARENT             0x00100000
-
-/* ? */
-#define DSTAGP                  0x02000000
-#define DSTVIDEO                0x02000000
-
-/* Subfunctions for Color/Enhanced Color Expansion (315 only) */
-#define COLOR_TO_MONO		0x00100000
-#define AA_TEXT			0x00200000
-
-/* Some general registers for 315 series */
-#define SRC_ADDR		0x8200
-#define SRC_PITCH		0x8204
-#define AGP_BASE		0x8206 /* color-depth dependent value */
-#define SRC_Y			0x8208
-#define SRC_X			0x820A
-#define DST_Y			0x820C
-#define DST_X			0x820E
-#define DST_ADDR		0x8210
-#define DST_PITCH		0x8214
-#define DST_HEIGHT		0x8216
-#define RECT_WIDTH		0x8218
-#define RECT_HEIGHT		0x821A
-#define PAT_FGCOLOR		0x821C
-#define PAT_BGCOLOR		0x8220
-#define SRC_FGCOLOR		0x8224
-#define SRC_BGCOLOR		0x8228
-#define MONO_MASK		0x822C
-#define LEFT_CLIP		0x8234
-#define TOP_CLIP		0x8236
-#define RIGHT_CLIP		0x8238
-#define BOTTOM_CLIP		0x823A
-#define COMMAND_READY		0x823C
-#define FIRE_TRIGGER      	0x8240
-
-#define PATTERN_REG		0x8300  /* 384 bytes pattern buffer */
-
-/* Transparent bitblit registers */
-#define TRANS_DST_KEY_HIGH	PAT_FGCOLOR
-#define TRANS_DST_KEY_LOW	PAT_BGCOLOR
-#define TRANS_SRC_KEY_HIGH	SRC_FGCOLOR
-#define TRANS_SRC_KEY_LOW	SRC_BGCOLOR
-
-/* Store queue length in par */
-#define CmdQueLen ivideo->cmdqueuelength
-
-/* ------------- SiS 300 series -------------- */
-
-/* BR(16) (0x8240):
-
-   bit 31 2D engine: 1 is idle,
-   bit 30 3D engine: 1 is idle,
-   bit 29 Command queue: 1 is empty
-   bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
-   bits 15:0:  Current command queue length
-
-*/
-
-#define SiS300Idle \
-  { \
-  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  	CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \
-  }
-/* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
-
-#define SiS300SetupSRCBase(base) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\
-	CmdQueLen--;
-
-#define SiS300SetupSRCPitch(pitch) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\
-	CmdQueLen--;
-
-#define SiS300SetupSRCXY(x,y) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\
-	CmdQueLen--;
-
-#define SiS300SetupDSTBase(base) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\
-	CmdQueLen--;
-
-#define SiS300SetupDSTXY(x,y) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\
-	CmdQueLen--;
-
-#define SiS300SetupDSTRect(x,y) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\
-	CmdQueLen--;
-
-#define SiS300SetupDSTColorDepth(bpp) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\
-	CmdQueLen--;
-
-#define SiS300SetupRect(w,h) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\
-	CmdQueLen--;
-
-#define SiS300SetupPATFG(color) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\
-	CmdQueLen--;
-
-#define SiS300SetupPATBG(color) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\
-	CmdQueLen--;
-
-#define SiS300SetupSRCFG(color) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\
-	CmdQueLen--;
-
-#define SiS300SetupSRCBG(color) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\
-	CmdQueLen--;
-
-/* 0x8224 src colorkey high */
-/* 0x8228 src colorkey low */
-/* 0x821c dest colorkey high */
-/* 0x8220 dest colorkey low */
-#define SiS300SetupSRCTrans(color) \
-	if(CmdQueLen <= 1) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\
-	MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\
-	CmdQueLen -= 2;
-
-#define SiS300SetupDSTTrans(color) \
-	if(CmdQueLen <= 1) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \
-	MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \
-	CmdQueLen -= 2;
-
-#define SiS300SetupMONOPAT(p0,p1) \
-	if(CmdQueLen <= 1) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\
-	CmdQueLen -= 2;
-
-#define SiS300SetupClipLT(left,top) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
-	CmdQueLen--;
-
-#define SiS300SetupClipRB(right,bottom) \
-	if(CmdQueLen <= 0) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
-	CmdQueLen--;
-
-/* General */
-#define SiS300SetupROP(rop) \
-	ivideo->CommandReg = (rop) << 8;
-
-#define SiS300SetupCMDFlag(flags) \
-	ivideo->CommandReg |= (flags);
-
-#define SiS300DoCMD \
-	if(CmdQueLen <= 1) SiS300Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \
-	MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\
-	CmdQueLen -= 2;
-
-/* -------------- SiS 315/330 series --------------- */
-
-/* Q_STATUS:
-   bit 31 = 1: All engines idle and all queues empty
-   bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty
-   bit 29 = 1: 2D engine is idle
-   bit 28 = 1: 3D engine is idle
-   bit 27 = 1: HW command queue empty
-   bit 26 = 1: 2D queue empty
-   bit 25 = 1: 3D queue empty
-   bit 24 = 1: SW command queue empty
-   bits 23:16: 2D counter 3
-   bits 15:8:  2D counter 2
-   bits 7:0:   2D counter 1
-*/
-
-#define SiS310Idle \
-  { \
-  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  	CmdQueLen = 0; \
-  }
-
-#define SiS310SetupSRCBase(base) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\
-	CmdQueLen--;
-
-#define SiS310SetupSRCPitch(pitch) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\
-	CmdQueLen--;
-
-#define SiS310SetupSRCXY(x,y) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\
-	CmdQueLen--;
-
-#define SiS310SetupDSTBase(base) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\
-	CmdQueLen--;
-
-#define SiS310SetupDSTXY(x,y) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\
-	CmdQueLen--;
-
-#define SiS310SetupDSTRect(x,y) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
-	CmdQueLen--;
-
-#define SiS310SetupDSTColorDepth(bpp) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\
-	CmdQueLen--;
-
-#define SiS310SetupRect(w,h) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
-	CmdQueLen--;
-
-#define SiS310SetupPATFG(color) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\
-	CmdQueLen--;
-
-#define SiS310SetupPATBG(color) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\
-	CmdQueLen--;
-
-#define SiS310SetupSRCFG(color) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\
-	CmdQueLen--;
-
-#define SiS310SetupSRCBG(color) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\
-	CmdQueLen--;
-
-#define SiS310SetupSRCTrans(color) \
-	if(CmdQueLen <= 1) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
-	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\
-	CmdQueLen -= 2;
-
-#define SiS310SetupDSTTrans(color) \
-	if(CmdQueLen <= 1) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \
-	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \
-	CmdQueLen -= 2;
-
-#define SiS310SetupMONOPAT(p0,p1) \
-	if(CmdQueLen <= 1) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\
-	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\
-	CmdQueLen -= 2;
-
-#define SiS310SetupClipLT(left,top) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
-	CmdQueLen--;
-
-#define SiS310SetupClipRB(right,bottom) \
-	if(CmdQueLen <= 0) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
-	CmdQueLen--;
-
-#define SiS310SetupROP(rop) \
-	ivideo->CommandReg = (rop) << 8;
-
-#define SiS310SetupCMDFlag(flags) \
-	ivideo->CommandReg |= (flags);
-
-#define SiS310DoCMD \
-	if(CmdQueLen <= 1) SiS310Idle;\
-	MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \
-	MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \
-	CmdQueLen -= 2;
-
-int  sisfb_initaccel(struct sis_video_info *ivideo);
-void sisfb_syncaccel(struct sis_video_info *ivideo);
-
-int  fbcon_sis_sync(struct fb_info *info);
-void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-
-#endif
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
deleted file mode 100644
index 22ad028bf123..000000000000
--- a/drivers/video/sis/sis_main.c
+++ /dev/null
@@ -1,6844 +0,0 @@
-/*
- * SiS 300/540/630[S]/730[S],
- * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
- * XGI V3XT/V5/V8, Z7
- * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
- *
- * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Author:	Thomas Winischhofer <thomas@winischhofer.net>
- *
- * Author of (practically wiped) code base:
- *		SiS (www.sis.com)
- *		Copyright (C) 1999 Silicon Integrated Systems, Inc.
- *
- * See http://www.winischhofer.net/ for more information and updates
- *
- * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
- * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/screen_info.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/selection.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/capability.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/uaccess.h>
-#include <asm/io.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include "sis.h"
-#include "sis_main.h"
-
-#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
-#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
-#warning sisfb will not work!
-#endif
-
-static void sisfb_handle_command(struct sis_video_info *ivideo,
-				 struct sisfb_cmd *sisfb_command);
-
-/* ------------------ Internal helper routines ----------------- */
-
-static void __init
-sisfb_setdefaultparms(void)
-{
-	sisfb_off		= 0;
-	sisfb_parm_mem		= 0;
-	sisfb_accel		= -1;
-	sisfb_ypan		= -1;
-	sisfb_max		= -1;
-	sisfb_userom		= -1;
-	sisfb_useoem		= -1;
-	sisfb_mode_idx		= -1;
-	sisfb_parm_rate		= -1;
-	sisfb_crt1off		= 0;
-	sisfb_forcecrt1		= -1;
-	sisfb_crt2type		= -1;
-	sisfb_crt2flags		= 0;
-	sisfb_pdc		= 0xff;
-	sisfb_pdca		= 0xff;
-	sisfb_scalelcd		= -1;
-	sisfb_specialtiming 	= CUT_NONE;
-	sisfb_lvdshl		= -1;
-	sisfb_dstn		= 0;
-	sisfb_fstn		= 0;
-	sisfb_tvplug		= -1;
-	sisfb_tvstd		= -1;
-	sisfb_tvxposoffset	= 0;
-	sisfb_tvyposoffset	= 0;
-	sisfb_nocrt2rate	= 0;
-#if !defined(__i386__) && !defined(__x86_64__)
-	sisfb_resetcard		= 0;
-	sisfb_videoram		= 0;
-#endif
-}
-
-/* ------------- Parameter parsing -------------- */
-
-static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
-{
-	int i = 0, j = 0;
-
-	/* We don't know the hardware specs yet and there is no ivideo */
-
-	if(vesamode == 0) {
-		if(!quiet)
-			printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
-
-		sisfb_mode_idx = DEFAULT_MODE;
-
-		return;
-	}
-
-	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
-
-	while(sisbios_mode[i++].mode_no[0] != 0) {
-		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
-		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
-			if(sisfb_fstn) {
-				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
-				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
-				   sisbios_mode[i-1].mode_no[1] == 0x53)
-					continue;
-			} else {
-				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
-				   sisbios_mode[i-1].mode_no[1] == 0x5b)
-					continue;
-			}
-			sisfb_mode_idx = i - 1;
-			j = 1;
-			break;
-		}
-	}
-	if((!j) && !quiet)
-		printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
-}
-
-static void sisfb_search_mode(char *name, bool quiet)
-{
-	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
-	int i = 0;
-	char strbuf[16], strbuf1[20];
-	char *nameptr = name;
-
-	/* We don't know the hardware specs yet and there is no ivideo */
-
-	if(name == NULL) {
-		if(!quiet)
-			printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
-
-		sisfb_mode_idx = DEFAULT_MODE;
-		return;
-	}
-
-	if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
-		if(!quiet)
-			printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
-
-		sisfb_mode_idx = DEFAULT_MODE;
-		return;
-	}
-
-	if(strlen(name) <= 19) {
-		strcpy(strbuf1, name);
-		for(i = 0; i < strlen(strbuf1); i++) {
-			if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
-		}
-
-		/* This does some fuzzy mode naming detection */
-		if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
-			if((rate <= 32) || (depth > 32)) {
-				j = rate; rate = depth; depth = j;
-			}
-			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-			nameptr = strbuf;
-			sisfb_parm_rate = rate;
-		} else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
-			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-			nameptr = strbuf;
-		} else {
-			xres = 0;
-			if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
-				sprintf(strbuf, "%ux%ux8", xres, yres);
-				nameptr = strbuf;
-			} else {
-				sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
-				return;
-			}
-		}
-	}
-
-	i = 0; j = 0;
-	while(sisbios_mode[i].mode_no[0] != 0) {
-		if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
-			if(sisfb_fstn) {
-				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
-				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
-				   sisbios_mode[i-1].mode_no[1] == 0x53)
-					continue;
-			} else {
-				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
-				   sisbios_mode[i-1].mode_no[1] == 0x5b)
-					continue;
-			}
-			sisfb_mode_idx = i - 1;
-			j = 1;
-			break;
-		}
-	}
-
-	if((!j) && !quiet)
-		printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
-}
-
-#ifndef MODULE
-static void sisfb_get_vga_mode_from_kernel(void)
-{
-#ifdef CONFIG_X86
-	char mymode[32];
-	int  mydepth = screen_info.lfb_depth;
-
-	if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
-
-	if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
-	    (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
-	    (mydepth >= 8) && (mydepth <= 32) ) {
-
-		if(mydepth == 24) mydepth = 32;
-
-		sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
-					screen_info.lfb_height,
-					mydepth);
-
-		printk(KERN_DEBUG
-			"sisfb: Using vga mode %s pre-set by kernel as default\n",
-			mymode);
-
-		sisfb_search_mode(mymode, true);
-	}
-#endif
-	return;
-}
-#endif
-
-static void __init
-sisfb_search_crt2type(const char *name)
-{
-	int i = 0;
-
-	/* We don't know the hardware specs yet and there is no ivideo */
-
-	if(name == NULL) return;
-
-	while(sis_crt2type[i].type_no != -1) {
-		if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
-			sisfb_crt2type = sis_crt2type[i].type_no;
-			sisfb_tvplug = sis_crt2type[i].tvplug_no;
-			sisfb_crt2flags = sis_crt2type[i].flags;
-			break;
-		}
-		i++;
-	}
-
-	sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
-	sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
-
-	if(sisfb_crt2type < 0)
-		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
-}
-
-static void __init
-sisfb_search_tvstd(const char *name)
-{
-	int i = 0;
-
-	/* We don't know the hardware specs yet and there is no ivideo */
-
-	if(name == NULL)
-		return;
-
-	while(sis_tvtype[i].type_no != -1) {
-		if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
-			sisfb_tvstd = sis_tvtype[i].type_no;
-			break;
-		}
-		i++;
-	}
-}
-
-static void __init
-sisfb_search_specialtiming(const char *name)
-{
-	int i = 0;
-	bool found = false;
-
-	/* We don't know the hardware specs yet and there is no ivideo */
-
-	if(name == NULL)
-		return;
-
-	if(!strnicmp(name, "none", 4)) {
-		sisfb_specialtiming = CUT_FORCENONE;
-		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
-	} else {
-		while(mycustomttable[i].chipID != 0) {
-			if(!strnicmp(name,mycustomttable[i].optionName,
-			   strlen(mycustomttable[i].optionName))) {
-				sisfb_specialtiming = mycustomttable[i].SpecialID;
-				found = true;
-				printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
-					mycustomttable[i].vendorName,
-					mycustomttable[i].cardName,
-					mycustomttable[i].optionName);
-				break;
-			}
-			i++;
-		}
-		if(!found) {
-			printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
-			printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
-			i = 0;
-			while(mycustomttable[i].chipID != 0) {
-				printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
-					mycustomttable[i].optionName,
-					mycustomttable[i].vendorName,
-					mycustomttable[i].cardName);
-				i++;
-			}
-		}
-	}
-}
-
-/* ----------- Various detection routines ----------- */
-
-static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
-{
-	unsigned char *biosver = NULL;
-	unsigned char *biosdate = NULL;
-	bool footprint;
-	u32 chksum = 0;
-	int i, j;
-
-	if(ivideo->SiS_Pr.UseROM) {
-		biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
-		biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
-		for(i = 0; i < 32768; i++)
-			chksum += ivideo->SiS_Pr.VirtualRomBase[i];
-	}
-
-	i = 0;
-	do {
-		if( (mycustomttable[i].chipID == ivideo->chip)			&&
-		    ((!strlen(mycustomttable[i].biosversion)) ||
-		     (ivideo->SiS_Pr.UseROM &&
-		      (!strncmp(mycustomttable[i].biosversion, biosver,
-				strlen(mycustomttable[i].biosversion)))))	&&
-		    ((!strlen(mycustomttable[i].biosdate)) ||
-		     (ivideo->SiS_Pr.UseROM &&
-		      (!strncmp(mycustomttable[i].biosdate, biosdate,
-				strlen(mycustomttable[i].biosdate)))))		&&
-		    ((!mycustomttable[i].bioschksum) ||
-		     (ivideo->SiS_Pr.UseROM &&
-		      (mycustomttable[i].bioschksum == chksum)))		&&
-		    (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
-		    (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
-			footprint = true;
-			for(j = 0; j < 5; j++) {
-				if(mycustomttable[i].biosFootprintAddr[j]) {
-					if(ivideo->SiS_Pr.UseROM) {
-						if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
-							mycustomttable[i].biosFootprintData[j]) {
-							footprint = false;
-						}
-					} else
-						footprint = false;
-				}
-			}
-			if(footprint) {
-				ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
-				printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
-					mycustomttable[i].vendorName,
-				mycustomttable[i].cardName);
-				printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
-					mycustomttable[i].optionName);
-				break;
-			}
-		}
-		i++;
-	} while(mycustomttable[i].chipID);
-}
-
-static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
-{
-	int i, j, xres, yres, refresh, index;
-	u32 emodes;
-
-	if(buffer[0] != 0x00 || buffer[1] != 0xff ||
-	   buffer[2] != 0xff || buffer[3] != 0xff ||
-	   buffer[4] != 0xff || buffer[5] != 0xff ||
-	   buffer[6] != 0xff || buffer[7] != 0x00) {
-		printk(KERN_DEBUG "sisfb: Bad EDID header\n");
-		return false;
-	}
-
-	if(buffer[0x12] != 0x01) {
-		printk(KERN_INFO "sisfb: EDID version %d not supported\n",
-			buffer[0x12]);
-		return false;
-	}
-
-	monitor->feature = buffer[0x18];
-
-	if(!(buffer[0x14] & 0x80)) {
-		if(!(buffer[0x14] & 0x08)) {
-			printk(KERN_INFO
-				"sisfb: WARNING: Monitor does not support separate syncs\n");
-		}
-	}
-
-	if(buffer[0x13] >= 0x01) {
-	   /* EDID V1 rev 1 and 2: Search for monitor descriptor
-	    * to extract ranges
-	    */
-	    j = 0x36;
-	    for(i=0; i<4; i++) {
-	       if(buffer[j]     == 0x00 && buffer[j + 1] == 0x00 &&
-		  buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
-		  buffer[j + 4] == 0x00) {
-		  monitor->hmin = buffer[j + 7];
-		  monitor->hmax = buffer[j + 8];
-		  monitor->vmin = buffer[j + 5];
-		  monitor->vmax = buffer[j + 6];
-		  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
-		  monitor->datavalid = true;
-		  break;
-	       }
-	       j += 18;
-	    }
-	}
-
-	if(!monitor->datavalid) {
-	   /* Otherwise: Get a range from the list of supported
-	    * Estabished Timings. This is not entirely accurate,
-	    * because fixed frequency monitors are not supported
-	    * that way.
-	    */
-	   monitor->hmin = 65535; monitor->hmax = 0;
-	   monitor->vmin = 65535; monitor->vmax = 0;
-	   monitor->dclockmax = 0;
-	   emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
-	   for(i = 0; i < 13; i++) {
-	      if(emodes & sisfb_ddcsmodes[i].mask) {
-		 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
-		 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
-		 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
-		 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
-		 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
-	      }
-	   }
-	   index = 0x26;
-	   for(i = 0; i < 8; i++) {
-	      xres = (buffer[index] + 31) * 8;
-	      switch(buffer[index + 1] & 0xc0) {
-		 case 0xc0: yres = (xres * 9) / 16; break;
-		 case 0x80: yres = (xres * 4) /  5; break;
-		 case 0x40: yres = (xres * 3) /  4; break;
-		 default:   yres = xres;	    break;
-	      }
-	      refresh = (buffer[index + 1] & 0x3f) + 60;
-	      if((xres >= 640) && (yres >= 480)) {
-		 for(j = 0; j < 8; j++) {
-		    if((xres == sisfb_ddcfmodes[j].x) &&
-		       (yres == sisfb_ddcfmodes[j].y) &&
-		       (refresh == sisfb_ddcfmodes[j].v)) {
-		      if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
-		      if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
-		      if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
-		      if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
-		      if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
-		    }
-		 }
-	      }
-	      index += 2;
-	   }
-	   if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
-	      monitor->datavalid = true;
-	   }
-	}
-
-	return monitor->datavalid;
-}
-
-static void sisfb_handle_ddc(struct sis_video_info *ivideo,
-			     struct sisfb_monitor *monitor, int crtno)
-{
-	unsigned short temp, i, realcrtno = crtno;
-	unsigned char  buffer[256];
-
-	monitor->datavalid = false;
-
-	if(crtno) {
-	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
-	   else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
-	   else return;
-	}
-
-	if((ivideo->sisfb_crt1off) && (!crtno))
-		return;
-
-	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
-				realcrtno, 0, &buffer[0], ivideo->vbflags2);
-	if((!temp) || (temp == 0xffff)) {
-	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
-	   return;
-	} else {
-	   printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
-	   printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
-		crtno + 1,
-		(temp & 0x1a) ? "" : "[none of the supported]",
-		(temp & 0x02) ? "2 " : "",
-		(temp & 0x08) ? "D&P" : "",
-		(temp & 0x10) ? "FPDI-2" : "");
-	   if(temp & 0x02) {
-	      i = 3;  /* Number of retrys */
-	      do {
-		 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
-				     realcrtno, 1, &buffer[0], ivideo->vbflags2);
-	      } while((temp) && i--);
-	      if(!temp) {
-		 if(sisfb_interpret_edid(monitor, &buffer[0])) {
-		    printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
-			monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
-			monitor->dclockmax / 1000);
-		 } else {
-		    printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
-		 }
-	      } else {
-		 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
-	      }
-	   } else {
-	      printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
-	   }
-	}
-}
-
-/* -------------- Mode validation --------------- */
-
-static bool
-sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
-		int mode_idx, int rate_idx, int rate)
-{
-	int htotal, vtotal;
-	unsigned int dclock, hsync;
-
-	if(!monitor->datavalid)
-		return true;
-
-	if(mode_idx < 0)
-		return false;
-
-	/* Skip for 320x200, 320x240, 640x400 */
-	switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
-	case 0x59:
-	case 0x41:
-	case 0x4f:
-	case 0x50:
-	case 0x56:
-	case 0x53:
-	case 0x2f:
-	case 0x5d:
-	case 0x5e:
-		return true;
-#ifdef CONFIG_FB_SIS_315
-	case 0x5a:
-	case 0x5b:
-		if(ivideo->sisvga_engine == SIS_315_VGA) return true;
-#endif
-	}
-
-	if(rate < (monitor->vmin - 1))
-		return false;
-	if(rate > (monitor->vmax + 1))
-		return false;
-
-	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
-				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
-				  &htotal, &vtotal, rate_idx)) {
-		dclock = (htotal * vtotal * rate) / 1000;
-		if(dclock > (monitor->dclockmax + 1000))
-			return false;
-		hsync = dclock / htotal;
-		if(hsync < (monitor->hmin - 1))
-			return false;
-		if(hsync > (monitor->hmax + 1))
-			return false;
-        } else {
-		return false;
-	}
-	return true;
-}
-
-static int
-sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
-{
-	u16 xres=0, yres, myres;
-
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		if(!(sisbios_mode[myindex].chipset & MD_SIS300))
-			return -1 ;
-	}
-#endif
-#ifdef CONFIG_FB_SIS_315
-	if(ivideo->sisvga_engine == SIS_315_VGA) {
-		if(!(sisbios_mode[myindex].chipset & MD_SIS315))
-			return -1;
-	}
-#endif
-
-	myres = sisbios_mode[myindex].yres;
-
-	switch(vbflags & VB_DISPTYPE_DISP2) {
-
-	case CRT2_LCD:
-		xres = ivideo->lcdxres; yres = ivideo->lcdyres;
-
-		if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
-		   (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
-			if(sisbios_mode[myindex].xres > xres)
-				return -1;
-			if(myres > yres)
-				return -1;
-		}
-
-		if(ivideo->sisfb_fstn) {
-			if(sisbios_mode[myindex].xres == 320) {
-				if(myres == 240) {
-					switch(sisbios_mode[myindex].mode_no[1]) {
-						case 0x50: myindex = MODE_FSTN_8;  break;
-						case 0x56: myindex = MODE_FSTN_16; break;
-						case 0x53: return -1;
-					}
-				}
-			}
-		}
-
-		if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-			 	sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
-			 	ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
-			return -1;
-		}
-		break;
-
-	case CRT2_TV:
-		if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
-			return -1;
-		}
-		break;
-
-	case CRT2_VGA:
-		if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
-			return -1;
-		}
-		break;
-	}
-
-	return myindex;
-}
-
-static u8
-sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
-{
-	int i = 0;
-	u16 xres = sisbios_mode[mode_idx].xres;
-	u16 yres = sisbios_mode[mode_idx].yres;
-
-	ivideo->rate_idx = 0;
-	while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
-		if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
-			if(sisfb_vrate[i].refresh == rate) {
-				ivideo->rate_idx = sisfb_vrate[i].idx;
-				break;
-			} else if(sisfb_vrate[i].refresh > rate) {
-				if((sisfb_vrate[i].refresh - rate) <= 3) {
-					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
-						rate, sisfb_vrate[i].refresh);
-					ivideo->rate_idx = sisfb_vrate[i].idx;
-					ivideo->refresh_rate = sisfb_vrate[i].refresh;
-				} else if((sisfb_vrate[i].idx != 1) &&
-						((rate - sisfb_vrate[i-1].refresh) <= 2)) {
-					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
-						rate, sisfb_vrate[i-1].refresh);
-					ivideo->rate_idx = sisfb_vrate[i-1].idx;
-					ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
-				}
-				break;
-			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
-				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
-						rate, sisfb_vrate[i].refresh);
-				ivideo->rate_idx = sisfb_vrate[i].idx;
-				break;
-			}
-		}
-		i++;
-	}
-	if(ivideo->rate_idx > 0) {
-		return ivideo->rate_idx;
-	} else {
-		printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
-				rate, xres, yres);
-		return 0;
-	}
-}
-
-static bool
-sisfb_bridgeisslave(struct sis_video_info *ivideo)
-{
-	unsigned char P1_00;
-
-	if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
-		return false;
-
-	P1_00 = SiS_GetReg(SISPART1, 0x00);
-	if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
-	    ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
-		return true;
-	} else {
-		return false;
-	}
-}
-
-static bool
-sisfballowretracecrt1(struct sis_video_info *ivideo)
-{
-	u8 temp;
-
-	temp = SiS_GetReg(SISCR, 0x17);
-	if(!(temp & 0x80))
-		return false;
-
-	temp = SiS_GetReg(SISSR, 0x1f);
-	if(temp & 0xc0)
-		return false;
-
-	return true;
-}
-
-static bool
-sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
-{
-	if(!sisfballowretracecrt1(ivideo))
-		return false;
-
-	if (SiS_GetRegByte(SISINPSTAT) & 0x08)
-		return true;
-	else
-		return false;
-}
-
-static void
-sisfbwaitretracecrt1(struct sis_video_info *ivideo)
-{
-	int watchdog;
-
-	if(!sisfballowretracecrt1(ivideo))
-		return;
-
-	watchdog = 65536;
-	while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
-	watchdog = 65536;
-	while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
-}
-
-static bool
-sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
-{
-	unsigned char temp, reg;
-
-	switch(ivideo->sisvga_engine) {
-	case SIS_300_VGA: reg = 0x25; break;
-	case SIS_315_VGA: reg = 0x30; break;
-	default:	  return false;
-	}
-
-	temp = SiS_GetReg(SISPART1, reg);
-	if(temp & 0x02)
-		return true;
-	else
-		return false;
-}
-
-static bool
-sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
-{
-	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-		if(!sisfb_bridgeisslave(ivideo)) {
-			return sisfbcheckvretracecrt2(ivideo);
-		}
-	}
-	return sisfbcheckvretracecrt1(ivideo);
-}
-
-static u32
-sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
-{
-	u8 idx, reg1, reg2, reg3, reg4;
-	u32 ret = 0;
-
-	(*vcount) = (*hcount) = 0;
-
-	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
-
-		ret |= (FB_VBLANK_HAVE_VSYNC  |
-			FB_VBLANK_HAVE_HBLANK |
-			FB_VBLANK_HAVE_VBLANK |
-			FB_VBLANK_HAVE_VCOUNT |
-			FB_VBLANK_HAVE_HCOUNT);
-		switch(ivideo->sisvga_engine) {
-			case SIS_300_VGA: idx = 0x25; break;
-			default:
-			case SIS_315_VGA: idx = 0x30; break;
-		}
-		reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
-		reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
-		reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
-		reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
-		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
-		if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
-		if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
-		(*vcount) = reg3 | ((reg4 & 0x70) << 4);
-		(*hcount) = reg2 | ((reg4 & 0x0f) << 8);
-
-	} else if(sisfballowretracecrt1(ivideo)) {
-
-		ret |= (FB_VBLANK_HAVE_VSYNC  |
-			FB_VBLANK_HAVE_VBLANK |
-			FB_VBLANK_HAVE_VCOUNT |
-			FB_VBLANK_HAVE_HCOUNT);
-		reg1 = SiS_GetRegByte(SISINPSTAT);
-		if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
-		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
-		reg1 = SiS_GetReg(SISCR, 0x20);
-		reg1 = SiS_GetReg(SISCR, 0x1b);
-		reg2 = SiS_GetReg(SISCR, 0x1c);
-		reg3 = SiS_GetReg(SISCR, 0x1d);
-		(*vcount) = reg2 | ((reg3 & 0x07) << 8);
-		(*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
-	}
-
-	return ret;
-}
-
-static int
-sisfb_myblank(struct sis_video_info *ivideo, int blank)
-{
-	u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
-	bool backlight = true;
-
-	switch(blank) {
-		case FB_BLANK_UNBLANK:	/* on */
-			sr01  = 0x00;
-			sr11  = 0x00;
-			sr1f  = 0x00;
-			cr63  = 0x00;
-			p2_0  = 0x20;
-			p1_13 = 0x00;
-			backlight = true;
-			break;
-		case FB_BLANK_NORMAL:	/* blank */
-			sr01  = 0x20;
-			sr11  = 0x00;
-			sr1f  = 0x00;
-			cr63  = 0x00;
-			p2_0  = 0x20;
-			p1_13 = 0x00;
-			backlight = true;
-			break;
-		case FB_BLANK_VSYNC_SUSPEND:	/* no vsync */
-			sr01  = 0x20;
-			sr11  = 0x08;
-			sr1f  = 0x80;
-			cr63  = 0x40;
-			p2_0  = 0x40;
-			p1_13 = 0x80;
-			backlight = false;
-			break;
-		case FB_BLANK_HSYNC_SUSPEND:	/* no hsync */
-			sr01  = 0x20;
-			sr11  = 0x08;
-			sr1f  = 0x40;
-			cr63  = 0x40;
-			p2_0  = 0x80;
-			p1_13 = 0x40;
-			backlight = false;
-			break;
-		case FB_BLANK_POWERDOWN:	/* off */
-			sr01  = 0x20;
-			sr11  = 0x08;
-			sr1f  = 0xc0;
-			cr63  = 0x40;
-			p2_0  = 0xc0;
-			p1_13 = 0xc0;
-			backlight = false;
-			break;
-		default:
-			return 1;
-	}
-
-	if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
-
-		if( (!ivideo->sisfb_thismonitor.datavalid) ||
-		    ((ivideo->sisfb_thismonitor.datavalid) &&
-		     (ivideo->sisfb_thismonitor.feature & 0xe0))) {
-
-			if(ivideo->sisvga_engine == SIS_315_VGA) {
-				SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
-			}
-
-			if(!(sisfb_bridgeisslave(ivideo))) {
-				SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
-				SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
-			}
-		}
-
-	}
-
-	if(ivideo->currentvbflags & CRT2_LCD) {
-
-		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
-			if(backlight) {
-				SiS_SiS30xBLOn(&ivideo->SiS_Pr);
-			} else {
-				SiS_SiS30xBLOff(&ivideo->SiS_Pr);
-			}
-		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
-#ifdef CONFIG_FB_SIS_315
-			if(ivideo->vbflags2 & VB2_CHRONTEL) {
-				if(backlight) {
-					SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
-				} else {
-					SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
-				}
-			}
-#endif
-		}
-
-		if(((ivideo->sisvga_engine == SIS_300_VGA) &&
-		    (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
-		   ((ivideo->sisvga_engine == SIS_315_VGA) &&
-		    ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
-			SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
-		}
-
-		if(ivideo->sisvga_engine == SIS_300_VGA) {
-			if((ivideo->vbflags2 & VB2_30xB) &&
-			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
-				SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
-			}
-		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
-			if((ivideo->vbflags2 & VB2_30xB) &&
-			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
-				SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
-			}
-		}
-
-	} else if(ivideo->currentvbflags & CRT2_VGA) {
-
-		if(ivideo->vbflags2 & VB2_30xB) {
-			SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
-		}
-
-	}
-
-	return 0;
-}
-
-/* ------------- Callbacks from init.c/init301.c  -------------- */
-
-#ifdef CONFIG_FB_SIS_300
-unsigned int
-sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
-{
-   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
-   u32 val = 0;
-
-   pci_read_config_dword(ivideo->nbridge, reg, &val);
-   return (unsigned int)val;
-}
-
-void
-sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
-{
-   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
-
-   pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
-}
-
-unsigned int
-sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
-{
-   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
-   u32 val = 0;
-
-   if(!ivideo->lpcdev) return 0;
-
-   pci_read_config_dword(ivideo->lpcdev, reg, &val);
-   return (unsigned int)val;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-void
-sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
-{
-   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
-
-   pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
-}
-
-unsigned int
-sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
-{
-   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
-   u16 val = 0;
-
-   if(!ivideo->lpcdev) return 0;
-
-   pci_read_config_word(ivideo->lpcdev, reg, &val);
-   return (unsigned int)val;
-}
-#endif
-
-/* ----------- FBDev related routines for all series ----------- */
-
-static int
-sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
-{
-	return (var->bits_per_pixel == 8) ? 256 : 16;
-}
-
-static void
-sisfb_set_vparms(struct sis_video_info *ivideo)
-{
-	switch(ivideo->video_bpp) {
-	case 8:
-		ivideo->DstColor = 0x0000;
-		ivideo->SiS310_AccelDepth = 0x00000000;
-		ivideo->video_cmap_len = 256;
-		break;
-	case 16:
-		ivideo->DstColor = 0x8000;
-		ivideo->SiS310_AccelDepth = 0x00010000;
-		ivideo->video_cmap_len = 16;
-		break;
-	case 32:
-		ivideo->DstColor = 0xC000;
-		ivideo->SiS310_AccelDepth = 0x00020000;
-		ivideo->video_cmap_len = 16;
-		break;
-	default:
-		ivideo->video_cmap_len = 16;
-		printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
-		ivideo->accel = 0;
-	}
-}
-
-static int
-sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
-{
-	int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
-
-	if(maxyres > 32767) maxyres = 32767;
-
-	return maxyres;
-}
-
-static void
-sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
-{
-	ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
-	ivideo->scrnpitchCRT1 = ivideo->video_linelength;
-	if(!(ivideo->currentvbflags & CRT1_LCDA)) {
-		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-			ivideo->scrnpitchCRT1 <<= 1;
-		}
-	}
-}
-
-static void
-sisfb_set_pitch(struct sis_video_info *ivideo)
-{
-	bool isslavemode = false;
-	unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
-	unsigned short HDisplay2 = ivideo->video_linelength >> 3;
-
-	if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
-
-	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
-	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
-		SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
-		SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
-	}
-
-	/* We must not set the pitch for CRT2 if bridge is in slave mode */
-	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
-		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
-		SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
-		SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
-	}
-}
-
-static void
-sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
-{
-	ivideo->video_cmap_len = sisfb_get_cmap_len(var);
-
-	switch(var->bits_per_pixel) {
-	case 8:
-		var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 8;
-		break;
-	case 16:
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 32:
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	}
-}
-
-static int
-sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
-{
-	unsigned short modeno = ivideo->mode_no;
-
-	/* >=2.6.12's fbcon clears the screen anyway */
-	modeno |= 0x80;
-
-	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
-	sisfb_pre_setmode(ivideo);
-
-	if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
-		printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
-		return -EINVAL;
-	}
-
-	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
-	sisfb_post_setmode(ivideo);
-
-	return 0;
-}
-
-
-static int
-sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-	unsigned int htotal = 0, vtotal = 0;
-	unsigned int drate = 0, hrate = 0;
-	int found_mode = 0, ret;
-	int old_mode;
-	u32 pixclock;
-
-	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
-
-	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
-
-	pixclock = var->pixclock;
-
-	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
-		vtotal += var->yres;
-		vtotal <<= 1;
-	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		vtotal += var->yres;
-		vtotal <<= 2;
-	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-		vtotal += var->yres;
-		vtotal <<= 1;
-	} else 	vtotal += var->yres;
-
-	if(!(htotal) || !(vtotal)) {
-		DPRINTK("sisfb: Invalid 'var' information\n");
-		return -EINVAL;
-	}
-
-	if(pixclock && htotal && vtotal) {
-		drate = 1000000000 / pixclock;
-		hrate = (drate * 1000) / htotal;
-		ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else {
-		ivideo->refresh_rate = 60;
-	}
-
-	old_mode = ivideo->sisfb_mode_idx;
-	ivideo->sisfb_mode_idx = 0;
-
-	while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
-	       (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
-		if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
-		    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
-		    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
-			ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
-			found_mode = 1;
-			break;
-		}
-		ivideo->sisfb_mode_idx++;
-	}
-
-	if(found_mode) {
-		ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
-				ivideo->sisfb_mode_idx, ivideo->currentvbflags);
-	} else {
-		ivideo->sisfb_mode_idx = -1;
-	}
-
-       	if(ivideo->sisfb_mode_idx < 0) {
-		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
-		       var->yres, var->bits_per_pixel);
-		ivideo->sisfb_mode_idx = old_mode;
-		return -EINVAL;
-	}
-
-	ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
-
-	if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
-		ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
-		ivideo->refresh_rate = 60;
-	}
-
-	if(isactive) {
-		/* If acceleration to be used? Need to know
-		 * before pre/post_set_mode()
-		 */
-		ivideo->accel = 0;
-#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
-#ifdef STUPID_ACCELF_TEXT_SHIT
-		if(var->accel_flags & FB_ACCELF_TEXT) {
-			info->flags &= ~FBINFO_HWACCEL_DISABLED;
-		} else {
-			info->flags |= FBINFO_HWACCEL_DISABLED;
-		}
-#endif
-		if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
-#else
-		if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
-#endif
-
-		if((ret = sisfb_set_mode(ivideo, 1))) {
-			return ret;
-		}
-
-		ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
-		ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
-		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
-
-		sisfb_calc_pitch(ivideo, var);
-		sisfb_set_pitch(ivideo);
-
-		sisfb_set_vparms(ivideo);
-
-		ivideo->current_width = ivideo->video_width;
-		ivideo->current_height = ivideo->video_height;
-		ivideo->current_bpp = ivideo->video_bpp;
-		ivideo->current_htotal = htotal;
-		ivideo->current_vtotal = vtotal;
-		ivideo->current_linelength = ivideo->video_linelength;
-		ivideo->current_pixclock = var->pixclock;
-		ivideo->current_refresh_rate = ivideo->refresh_rate;
-		ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
-	}
-
-	return 0;
-}
-
-static void
-sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
-{
-	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
-	SiS_SetReg(SISCR, 0x0D, base & 0xFF);
-	SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
-	SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
-	if(ivideo->sisvga_engine == SIS_315_VGA) {
-		SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
-	}
-}
-
-static void
-sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
-{
-	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
-		SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
-		SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
-		SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
-		if(ivideo->sisvga_engine == SIS_315_VGA) {
-			SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
-		}
-	}
-}
-
-static int
-sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
-	      struct fb_var_screeninfo *var)
-{
-	ivideo->current_base = var->yoffset * info->var.xres_virtual
-			     + var->xoffset;
-
-	/* calculate base bpp dep. */
-	switch (info->var.bits_per_pixel) {
-	case 32:
-		break;
-	case 16:
-		ivideo->current_base >>= 1;
-		break;
-	case 8:
-	default:
-		ivideo->current_base >>= 2;
-		break;
-	}
-
-	ivideo->current_base += (ivideo->video_offset >> 2);
-
-	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
-	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
-
-	return 0;
-}
-
-static int
-sisfb_open(struct fb_info *info, int user)
-{
-	return 0;
-}
-
-static int
-sisfb_release(struct fb_info *info, int user)
-{
-	return 0;
-}
-
-static int
-sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-		unsigned transp, struct fb_info *info)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-	if(regno >= sisfb_get_cmap_len(&info->var))
-		return 1;
-
-	switch(info->var.bits_per_pixel) {
-	case 8:
-		SiS_SetRegByte(SISDACA, regno);
-		SiS_SetRegByte(SISDACD, (red >> 10));
-		SiS_SetRegByte(SISDACD, (green >> 10));
-		SiS_SetRegByte(SISDACD, (blue >> 10));
-		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-			SiS_SetRegByte(SISDAC2A, regno);
-			SiS_SetRegByte(SISDAC2D, (red >> 8));
-			SiS_SetRegByte(SISDAC2D, (green >> 8));
-			SiS_SetRegByte(SISDAC2D, (blue >> 8));
-		}
-		break;
-	case 16:
-		if (regno >= 16)
-			break;
-
-		((u32 *)(info->pseudo_palette))[regno] =
-				(red & 0xf800)          |
-				((green & 0xfc00) >> 5) |
-				((blue & 0xf800) >> 11);
-		break;
-	case 32:
-		if (regno >= 16)
-			break;
-
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-		((u32 *)(info->pseudo_palette))[regno] =
-				(red << 16) | (green << 8) | (blue);
-		break;
-	}
-	return 0;
-}
-
-static int
-sisfb_set_par(struct fb_info *info)
-{
-	int err;
-
-	if((err = sisfb_do_set_var(&info->var, 1, info)))
-		return err;
-
-	sisfb_get_fix(&info->fix, -1, info);
-
-	return 0;
-}
-
-static int
-sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
-	unsigned int drate = 0, hrate = 0, maxyres;
-	int found_mode = 0;
-	int refresh_rate, search_idx, tidx;
-	bool recalc_clock = false;
-	u32 pixclock;
-
-	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
-
-	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
-
-	pixclock = var->pixclock;
-
-	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
-		vtotal += var->yres;
-		vtotal <<= 1;
-	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		vtotal += var->yres;
-		vtotal <<= 2;
-	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-		vtotal += var->yres;
-		vtotal <<= 1;
-	} else
-		vtotal += var->yres;
-
-	if(!(htotal) || !(vtotal)) {
-		SISFAIL("sisfb: no valid timing data");
-	}
-
-	search_idx = 0;
-	while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
-	       (sisbios_mode[search_idx].xres <= var->xres) ) {
-		if( (sisbios_mode[search_idx].xres == var->xres) &&
-		    (sisbios_mode[search_idx].yres == var->yres) &&
-		    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
-			if((tidx = sisfb_validate_mode(ivideo, search_idx,
-						ivideo->currentvbflags)) > 0) {
-				found_mode = 1;
-				search_idx = tidx;
-				break;
-			}
-		}
-		search_idx++;
-	}
-
-	if(!found_mode) {
-		search_idx = 0;
-		while(sisbios_mode[search_idx].mode_no[0] != 0) {
-		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
-		       (var->yres <= sisbios_mode[search_idx].yres) &&
-		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
-			if((tidx = sisfb_validate_mode(ivideo,search_idx,
-						ivideo->currentvbflags)) > 0) {
-				found_mode = 1;
-				search_idx = tidx;
-				break;
-			}
-		   }
-		   search_idx++;
-		}
-		if(found_mode) {
-			printk(KERN_DEBUG
-				"sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
-				var->xres, var->yres, var->bits_per_pixel,
-				sisbios_mode[search_idx].xres,
-				sisbios_mode[search_idx].yres,
-				var->bits_per_pixel);
-			var->xres = sisbios_mode[search_idx].xres;
-			var->yres = sisbios_mode[search_idx].yres;
-		} else {
-			printk(KERN_ERR
-				"sisfb: Failed to find supported mode near %dx%dx%d\n",
-				var->xres, var->yres, var->bits_per_pixel);
-			return -EINVAL;
-		}
-	}
-
-	if( ((ivideo->vbflags2 & VB2_LVDS) ||
-	     ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
-	    (var->bits_per_pixel == 8) ) {
-		/* Slave modes on LVDS and 301B-DH */
-		refresh_rate = 60;
-		recalc_clock = true;
-	} else if( (ivideo->current_htotal == htotal) &&
-		   (ivideo->current_vtotal == vtotal) &&
-		   (ivideo->current_pixclock == pixclock) ) {
-		/* x=x & y=y & c=c -> assume depth change */
-		drate = 1000000000 / pixclock;
-		hrate = (drate * 1000) / htotal;
-		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else if( ( (ivideo->current_htotal != htotal) ||
-		     (ivideo->current_vtotal != vtotal) ) &&
-		   (ivideo->current_pixclock == var->pixclock) ) {
-		/* x!=x | y!=y & c=c -> invalid pixclock */
-		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
-			refresh_rate =
-				ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
-		} else if(ivideo->sisfb_parm_rate != -1) {
-			/* Sic, sisfb_parm_rate - want to know originally desired rate here */
-			refresh_rate = ivideo->sisfb_parm_rate;
-		} else {
-			refresh_rate = 60;
-		}
-		recalc_clock = true;
-	} else if((pixclock) && (htotal) && (vtotal)) {
-		drate = 1000000000 / pixclock;
-		hrate = (drate * 1000) / htotal;
-		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else if(ivideo->current_refresh_rate) {
-		refresh_rate = ivideo->current_refresh_rate;
-		recalc_clock = true;
-	} else {
-		refresh_rate = 60;
-		recalc_clock = true;
-	}
-
-	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
-
-	/* Eventually recalculate timing and clock */
-	if(recalc_clock) {
-		if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
-		var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
-						sisbios_mode[search_idx].mode_no[ivideo->mni],
-						myrateindex));
-		sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
-					sisbios_mode[search_idx].mode_no[ivideo->mni],
-					myrateindex, var);
-		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-			var->pixclock <<= 1;
-		}
-	}
-
-	if(ivideo->sisfb_thismonitor.datavalid) {
-		if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
-				myrateindex, refresh_rate)) {
-			printk(KERN_INFO
-				"sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
-		}
-	}
-
-	/* Adapt RGB settings */
-	sisfb_bpp_to_var(ivideo, var);
-
-	/* Sanity check for offsets */
-	if(var->xoffset < 0) var->xoffset = 0;
-	if(var->yoffset < 0) var->yoffset = 0;
-
-	if(var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-
-	if(ivideo->sisfb_ypan) {
-		maxyres = sisfb_calc_maxyres(ivideo, var);
-		if(ivideo->sisfb_max) {
-			var->yres_virtual = maxyres;
-		} else {
-			if(var->yres_virtual > maxyres) {
-				var->yres_virtual = maxyres;
-			}
-		}
-		if(var->yres_virtual <= var->yres) {
-			var->yres_virtual = var->yres;
-		}
-	} else {
-		if(var->yres != var->yres_virtual) {
-			var->yres_virtual = var->yres;
-		}
-		var->xoffset = 0;
-		var->yoffset = 0;
-	}
-
-	/* Truncate offsets to maximum if too high */
-	if(var->xoffset > var->xres_virtual - var->xres) {
-		var->xoffset = var->xres_virtual - var->xres - 1;
-	}
-
-	if(var->yoffset > var->yres_virtual - var->yres) {
-		var->yoffset = var->yres_virtual - var->yres - 1;
-	}
-
-	/* Set everything else to 0 */
-	var->red.msb_right =
-		var->green.msb_right =
-		var->blue.msb_right =
-		var->transp.offset =
-		var->transp.length =
-		var->transp.msb_right = 0;
-
-	return 0;
-}
-
-static int
-sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-	int err;
-
-	if (var->vmode & FB_VMODE_YWRAP)
-		return -EINVAL;
-
-	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-	    var->yoffset + info->var.yres > info->var.yres_virtual)
-		return -EINVAL;
-
-	err = sisfb_pan_var(ivideo, info, var);
-	if (err < 0)
-		return err;
-
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-
-	return 0;
-}
-
-static int
-sisfb_blank(int blank, struct fb_info *info)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-	return sisfb_myblank(ivideo, blank);
-}
-
-/* ----------- FBDev related routines for all series ---------- */
-
-static int	sisfb_ioctl(struct fb_info *info, unsigned int cmd,
-			    unsigned long arg)
-{
-	struct sis_video_info	*ivideo = (struct sis_video_info *)info->par;
-	struct sis_memreq	sismemreq;
-	struct fb_vblank	sisvbblank;
-	u32			gpu32 = 0;
-#ifndef __user
-#define __user
-#endif
-	u32 __user 		*argp = (u32 __user *)arg;
-
-	switch(cmd) {
-	   case FBIO_ALLOC:
-		if(!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-
-		if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
-			return -EFAULT;
-
-		sis_malloc(&sismemreq);
-
-		if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
-			sis_free((u32)sismemreq.offset);
-			return -EFAULT;
-		}
-		break;
-
-	   case FBIO_FREE:
-		if(!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-
-		if(get_user(gpu32, argp))
-			return -EFAULT;
-
-		sis_free(gpu32);
-		break;
-
-	   case FBIOGET_VBLANK:
-
-		memset(&sisvbblank, 0, sizeof(struct fb_vblank));
-
-		sisvbblank.count = 0;
-		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
-
-		if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
-			return -EFAULT;
-
-		break;
-
-	   case SISFB_GET_INFO_SIZE:
-		return put_user(sizeof(struct sisfb_info), argp);
-
-	   case SISFB_GET_INFO_OLD:
-		if(ivideo->warncount++ < 10)
-			printk(KERN_INFO
-				"sisfb: Deprecated ioctl call received - update your application!\n");
-	   case SISFB_GET_INFO:  /* For communication with X driver */
-		ivideo->sisfb_infoblock.sisfb_id         = SISFB_ID;
-		ivideo->sisfb_infoblock.sisfb_version    = VER_MAJOR;
-		ivideo->sisfb_infoblock.sisfb_revision   = VER_MINOR;
-		ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
-		ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
-		ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
-		ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
-		ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
-		if(ivideo->modechanged) {
-			ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
-		} else {
-			ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
-		}
-		ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
-		ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
-		ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
-		ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
-		ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
-		ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
-		ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
-		ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
-		ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
-		ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
-		ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
-		ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
-		ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
-		ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
-		ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
-		ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
-		ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
-		ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
-		ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
-		ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
-		ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
-		ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
-		ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
-		ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
-		ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
-		ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
-		ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
-		ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
-
-		if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
-						sizeof(ivideo->sisfb_infoblock)))
-			return -EFAULT;
-
-	        break;
-
-	   case SISFB_GET_VBRSTATUS_OLD:
-		if(ivideo->warncount++ < 10)
-			printk(KERN_INFO
-				"sisfb: Deprecated ioctl call received - update your application!\n");
-	   case SISFB_GET_VBRSTATUS:
-		if(sisfb_CheckVBRetrace(ivideo))
-			return put_user((u32)1, argp);
-		else
-			return put_user((u32)0, argp);
-
-	   case SISFB_GET_AUTOMAXIMIZE_OLD:
-		if(ivideo->warncount++ < 10)
-			printk(KERN_INFO
-				"sisfb: Deprecated ioctl call received - update your application!\n");
-	   case SISFB_GET_AUTOMAXIMIZE:
-		if(ivideo->sisfb_max)
-			return put_user((u32)1, argp);
-		else
-			return put_user((u32)0, argp);
-
-	   case SISFB_SET_AUTOMAXIMIZE_OLD:
-		if(ivideo->warncount++ < 10)
-			printk(KERN_INFO
-				"sisfb: Deprecated ioctl call received - update your application!\n");
-	   case SISFB_SET_AUTOMAXIMIZE:
-		if(get_user(gpu32, argp))
-			return -EFAULT;
-
-		ivideo->sisfb_max = (gpu32) ? 1 : 0;
-		break;
-
-	   case SISFB_SET_TVPOSOFFSET:
-		if(get_user(gpu32, argp))
-			return -EFAULT;
-
-		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
-		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
-		break;
-
-	   case SISFB_GET_TVPOSOFFSET:
-		return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
-							argp);
-
-	   case SISFB_COMMAND:
-		if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
-							sizeof(struct sisfb_cmd)))
-			return -EFAULT;
-
-		sisfb_handle_command(ivideo, &ivideo->sisfb_command);
-
-		if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
-							sizeof(struct sisfb_cmd)))
-			return -EFAULT;
-
-		break;
-
-	   case SISFB_SET_LOCK:
-		if(get_user(gpu32, argp))
-			return -EFAULT;
-
-		ivideo->sisfblocked = (gpu32) ? 1 : 0;
-		break;
-
-	   default:
-#ifdef SIS_NEW_CONFIG_COMPAT
-		return -ENOIOCTLCMD;
-#else
-		return -EINVAL;
-#endif
-	}
-	return 0;
-}
-
-static int
-sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-{
-	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-
-	strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
-
-	mutex_lock(&info->mm_lock);
-	fix->smem_start  = ivideo->video_base + ivideo->video_offset;
-	fix->smem_len    = ivideo->sisfb_mem;
-	mutex_unlock(&info->mm_lock);
-	fix->type        = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux    = 0;
-	fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	fix->xpanstep    = 1;
-	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;
-	fix->ywrapstep   = 0;
-	fix->line_length = ivideo->video_linelength;
-	fix->mmio_start  = ivideo->mmio_base;
-	fix->mmio_len    = ivideo->mmio_size;
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		fix->accel = FB_ACCEL_SIS_GLAMOUR;
-	} else if((ivideo->chip == SIS_330) ||
-		  (ivideo->chip == SIS_760) ||
-		  (ivideo->chip == SIS_761)) {
-		fix->accel = FB_ACCEL_SIS_XABRE;
-	} else if(ivideo->chip == XGI_20) {
-		fix->accel = FB_ACCEL_XGI_VOLARI_Z;
-	} else if(ivideo->chip >= XGI_40) {
-		fix->accel = FB_ACCEL_XGI_VOLARI_V;
-	} else {
-		fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
-	}
-
-	return 0;
-}
-
-/* ----------------  fb_ops structures ----------------- */
-
-static struct fb_ops sisfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= sisfb_open,
-	.fb_release	= sisfb_release,
-	.fb_check_var	= sisfb_check_var,
-	.fb_set_par	= sisfb_set_par,
-	.fb_setcolreg	= sisfb_setcolreg,
-	.fb_pan_display	= sisfb_pan_display,
-	.fb_blank	= sisfb_blank,
-	.fb_fillrect	= fbcon_sis_fillrect,
-	.fb_copyarea	= fbcon_sis_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_sync	= fbcon_sis_sync,
-#ifdef SIS_NEW_CONFIG_COMPAT
-	.fb_compat_ioctl= sisfb_ioctl,
-#endif
-	.fb_ioctl	= sisfb_ioctl
-};
-
-/* ---------------- Chip generation dependent routines ---------------- */
-
-static struct pci_dev *sisfb_get_northbridge(int basechipid)
-{
-	struct pci_dev *pdev = NULL;
-	int nbridgenum, nbridgeidx, i;
-	static const unsigned short nbridgeids[] = {
-		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */
-		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */
-		PCI_DEVICE_ID_SI_730,
-		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
-		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
-		PCI_DEVICE_ID_SI_651,
-		PCI_DEVICE_ID_SI_740,
-		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760/761 VGA */
-		PCI_DEVICE_ID_SI_741,
-		PCI_DEVICE_ID_SI_660,
-		PCI_DEVICE_ID_SI_760,
-		PCI_DEVICE_ID_SI_761
-	};
-
-	switch(basechipid) {
-#ifdef CONFIG_FB_SIS_300
-	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;
-	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;
-#endif
-#ifdef CONFIG_FB_SIS_315
-	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
-	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;
-	case SIS_660:	nbridgeidx = 7; nbridgenum = 5; break;
-#endif
-	default:	return NULL;
-	}
-	for(i = 0; i < nbridgenum; i++) {
-		if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
-				nbridgeids[nbridgeidx+i], NULL)))
-			break;
-	}
-	return pdev;
-}
-
-static int sisfb_get_dram_size(struct sis_video_info *ivideo)
-{
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-	u8 reg;
-#endif
-
-	ivideo->video_size = 0;
-	ivideo->UMAsize = ivideo->LFBsize = 0;
-
-	switch(ivideo->chip) {
-#ifdef CONFIG_FB_SIS_300
-	case SIS_300:
-		reg = SiS_GetReg(SISSR, 0x14);
-		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
-		break;
-	case SIS_540:
-	case SIS_630:
-	case SIS_730:
-		if(!ivideo->nbridge)
-			return -1;
-		pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
-		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
-		break;
-#endif
-#ifdef CONFIG_FB_SIS_315
-	case SIS_315H:
-	case SIS_315PRO:
-	case SIS_315:
-		reg = SiS_GetReg(SISSR, 0x14);
-		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-		switch((reg >> 2) & 0x03) {
-		case 0x01:
-		case 0x03:
-			ivideo->video_size <<= 1;
-			break;
-		case 0x02:
-			ivideo->video_size += (ivideo->video_size/2);
-		}
-		break;
-	case SIS_330:
-		reg = SiS_GetReg(SISSR, 0x14);
-		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-		if(reg & 0x0c) ivideo->video_size <<= 1;
-		break;
-	case SIS_550:
-	case SIS_650:
-	case SIS_740:
-		reg = SiS_GetReg(SISSR, 0x14);
-		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
-		break;
-	case SIS_661:
-	case SIS_741:
-		reg = SiS_GetReg(SISCR, 0x79);
-		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-		break;
-	case SIS_660:
-	case SIS_760:
-	case SIS_761:
-		reg = SiS_GetReg(SISCR, 0x79);
-		reg = (reg & 0xf0) >> 4;
-		if(reg)	{
-			ivideo->video_size = (1 << reg) << 20;
-			ivideo->UMAsize = ivideo->video_size;
-		}
-		reg = SiS_GetReg(SISCR, 0x78);
-		reg &= 0x30;
-		if(reg) {
-			if(reg == 0x10) {
-				ivideo->LFBsize = (32 << 20);
-			} else {
-				ivideo->LFBsize = (64 << 20);
-			}
-			ivideo->video_size += ivideo->LFBsize;
-		}
-		break;
-	case SIS_340:
-	case XGI_20:
-	case XGI_40:
-		reg = SiS_GetReg(SISSR, 0x14);
-		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-		if(ivideo->chip != XGI_20) {
-			reg = (reg & 0x0c) >> 2;
-			if(ivideo->revision_id == 2) {
-				if(reg & 0x01) reg = 0x02;
-				else	       reg = 0x00;
-			}
-			if(reg == 0x02)		ivideo->video_size <<= 1;
-			else if(reg == 0x03)	ivideo->video_size <<= 2;
-		}
-		break;
-#endif
-	default:
-		return -1;
-	}
-	return 0;
-}
-
-/* -------------- video bridge device detection --------------- */
-
-static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
-{
-	u8 cr32, temp;
-
-	/* No CRT2 on XGI Z7 */
-	if(ivideo->chip == XGI_20) {
-		ivideo->sisfb_crt1off = 0;
-		return;
-	}
-
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		temp = SiS_GetReg(SISSR, 0x17);
-		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
-			/* PAL/NTSC is stored on SR16 on such machines */
-			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-				temp = SiS_GetReg(SISSR, 0x16);
-				if(temp & 0x20)
-					ivideo->vbflags |= TV_PAL;
-				else
-					ivideo->vbflags |= TV_NTSC;
-			}
-		}
-	}
-#endif
-
-	cr32 = SiS_GetReg(SISCR, 0x32);
-
-	if(cr32 & SIS_CRT1) {
-		ivideo->sisfb_crt1off = 0;
-	} else {
-		ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
-	}
-
-	ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
-
-	if(cr32 & SIS_VB_TV)   ivideo->vbflags |= CRT2_TV;
-	if(cr32 & SIS_VB_LCD)  ivideo->vbflags |= CRT2_LCD;
-	if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
-
-	/* Check given parms for hardware compatibility.
-	 * (Cannot do this in the search_xx routines since we don't
-	 * know what hardware we are running on then)
-	 */
-
-	if(ivideo->chip != SIS_550) {
-	   ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
-	}
-
-	if(ivideo->sisfb_tvplug != -1) {
-	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
-	       (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
-	      if(ivideo->sisfb_tvplug & TV_YPBPR) {
-		 ivideo->sisfb_tvplug = -1;
-		 printk(KERN_ERR "sisfb: YPbPr not supported\n");
-	      }
-	   }
-	}
-	if(ivideo->sisfb_tvplug != -1) {
-	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
-	       (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
-	      if(ivideo->sisfb_tvplug & TV_HIVISION) {
-		 ivideo->sisfb_tvplug = -1;
-		 printk(KERN_ERR "sisfb: HiVision not supported\n");
-	      }
-	   }
-	}
-	if(ivideo->sisfb_tvstd != -1) {
-	   if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
-	       (!((ivideo->sisvga_engine == SIS_315_VGA) &&
-			(ivideo->vbflags2 & VB2_CHRONTEL))) ) {
-	      if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
-		 ivideo->sisfb_tvstd = -1;
-		 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
-	      }
-	   }
-	}
-
-	/* Detect/set TV plug & type */
-	if(ivideo->sisfb_tvplug != -1) {
-		ivideo->vbflags |= ivideo->sisfb_tvplug;
-	} else {
-		if(cr32 & SIS_VB_YPBPR)     	 ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
-		else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
-		else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
-		else {
-			if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
-			if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
-		}
-	}
-
-	if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
-	    if(ivideo->sisfb_tvstd != -1) {
-	       ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
-	       ivideo->vbflags |= ivideo->sisfb_tvstd;
-	    }
-	    if(ivideo->vbflags & TV_SCART) {
-	       ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
-	       ivideo->vbflags |= TV_PAL;
-	    }
-	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
-		if(ivideo->sisvga_engine == SIS_300_VGA) {
-			temp = SiS_GetReg(SISSR, 0x38);
-			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
-			else		ivideo->vbflags |= TV_NTSC;
-		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
-			temp = SiS_GetReg(SISSR, 0x38);
-			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
-			else		ivideo->vbflags |= TV_NTSC;
-		} else {
-			temp = SiS_GetReg(SISCR, 0x79);
-			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
-			else		ivideo->vbflags |= TV_NTSC;
-		}
-	    }
-	}
-
-	/* Copy forceCRT1 option to CRT1off if option is given */
-	if(ivideo->sisfb_forcecrt1 != -1) {
-	   ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
-	}
-}
-
-/* ------------------ Sensing routines ------------------ */
-
-static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
-{
-    unsigned short old;
-    int count = 48;
-
-    old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
-    do {
-	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
-    } while(count--);
-    return (count != -1);
-}
-
-static void sisfb_sense_crt1(struct sis_video_info *ivideo)
-{
-    bool mustwait = false;
-    u8  sr1F, cr17;
-#ifdef CONFIG_FB_SIS_315
-    u8  cr63=0;
-#endif
-    u16 temp = 0xffff;
-    int i;
-
-    sr1F = SiS_GetReg(SISSR, 0x1F);
-    SiS_SetRegOR(SISSR, 0x1F, 0x04);
-    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
-    if(sr1F & 0xc0) mustwait = true;
-
-#ifdef CONFIG_FB_SIS_315
-    if(ivideo->sisvga_engine == SIS_315_VGA) {
-       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
-       cr63 &= 0x40;
-       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
-    }
-#endif
-
-    cr17 = SiS_GetReg(SISCR, 0x17);
-    cr17 &= 0x80;
-    if(!cr17) {
-       SiS_SetRegOR(SISCR, 0x17, 0x80);
-       mustwait = true;
-       SiS_SetReg(SISSR, 0x00, 0x01);
-       SiS_SetReg(SISSR, 0x00, 0x03);
-    }
-
-    if(mustwait) {
-       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
-    }
-
-#ifdef CONFIG_FB_SIS_315
-    if(ivideo->chip >= SIS_330) {
-       SiS_SetRegAND(SISCR, 0x32, ~0x20);
-       if(ivideo->chip >= SIS_340) {
-	   SiS_SetReg(SISCR, 0x57, 0x4a);
-       } else {
-	   SiS_SetReg(SISCR, 0x57, 0x5f);
-       }
-	SiS_SetRegOR(SISCR, 0x53, 0x02);
-	while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
-	while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
-	if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
-	SiS_SetRegAND(SISCR, 0x53, 0xfd);
-	SiS_SetRegAND(SISCR, 0x57, 0x00);
-    }
-#endif
-
-    if(temp == 0xffff) {
-       i = 3;
-       do {
-	  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
-		ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
-       } while(((temp == 0) || (temp == 0xffff)) && i--);
-
-       if((temp == 0) || (temp == 0xffff)) {
-          if(sisfb_test_DDC1(ivideo)) temp = 1;
-       }
-    }
-
-    if((temp) && (temp != 0xffff)) {
-       SiS_SetRegOR(SISCR, 0x32, 0x20);
-    }
-
-#ifdef CONFIG_FB_SIS_315
-    if(ivideo->sisvga_engine == SIS_315_VGA) {
-	SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
-    }
-#endif
-
-    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
-
-    SiS_SetReg(SISSR, 0x1F, sr1F);
-}
-
-/* Determine and detect attached devices on SiS30x */
-static void SiS_SenseLCD(struct sis_video_info *ivideo)
-{
-	unsigned char buffer[256];
-	unsigned short temp, realcrtno, i;
-	u8 reg, cr37 = 0, paneltype = 0;
-	u16 xres, yres;
-
-	ivideo->SiS_Pr.PanelSelfDetected = false;
-
-	/* LCD detection only for TMDS bridges */
-	if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
-		return;
-	if(ivideo->vbflags2 & VB2_30xBDH)
-		return;
-
-	/* If LCD already set up by BIOS, skip it */
-	reg = SiS_GetReg(SISCR, 0x32);
-	if(reg & 0x08)
-		return;
-
-	realcrtno = 1;
-	if(ivideo->SiS_Pr.DDCPortMixup)
-		realcrtno = 0;
-
-	/* Check DDC capabilities */
-	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
-				realcrtno, 0, &buffer[0], ivideo->vbflags2);
-
-	if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
-		return;
-
-	/* Read DDC data */
-	i = 3;  /* Number of retrys */
-	do {
-		temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
-				ivideo->sisvga_engine, realcrtno, 1,
-				&buffer[0], ivideo->vbflags2);
-	} while((temp) && i--);
-
-	if(temp)
-		return;
-
-	/* No digital device */
-	if(!(buffer[0x14] & 0x80))
-		return;
-
-	/* First detailed timing preferred timing? */
-	if(!(buffer[0x18] & 0x02))
-		return;
-
-	xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
-	yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
-
-	switch(xres) {
-		case 1024:
-			if(yres == 768)
-				paneltype = 0x02;
-			break;
-		case 1280:
-			if(yres == 1024)
-				paneltype = 0x03;
-			break;
-		case 1600:
-			if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
-				paneltype = 0x0b;
-			break;
-	}
-
-	if(!paneltype)
-		return;
-
-	if(buffer[0x23])
-		cr37 |= 0x10;
-
-	if((buffer[0x47] & 0x18) == 0x18)
-		cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
-	else
-		cr37 |= 0xc0;
-
-	SiS_SetReg(SISCR, 0x36, paneltype);
-	cr37 &= 0xf1;
-	SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
-	SiS_SetRegOR(SISCR, 0x32, 0x08);
-
-	ivideo->SiS_Pr.PanelSelfDetected = true;
-}
-
-static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
-{
-    int temp, mytest, result, i, j;
-
-    for(j = 0; j < 10; j++) {
-       result = 0;
-       for(i = 0; i < 3; i++) {
-          mytest = test;
-	   SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
-          temp = (type >> 8) | (mytest & 0x00ff);
-	  SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
-          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
-          mytest >>= 8;
-          mytest &= 0x7f;
-	   temp = SiS_GetReg(SISPART4, 0x03);
-          temp ^= 0x0e;
-          temp &= mytest;
-          if(temp == mytest) result++;
-#if 1
-	  SiS_SetReg(SISPART4, 0x11, 0x00);
-	  SiS_SetRegAND(SISPART4, 0x10, 0xe0);
-	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
-#endif
-       }
-       if((result == 0) || (result >= 2)) break;
-    }
-    return result;
-}
-
-static void SiS_Sense30x(struct sis_video_info *ivideo)
-{
-    u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
-    u16 svhs=0, svhs_c=0;
-    u16 cvbs=0, cvbs_c=0;
-    u16 vga2=0, vga2_c=0;
-    int myflag, result;
-    char stdstr[] = "sisfb: Detected";
-    char tvstr[]  = "TV connected to";
-
-    if(ivideo->vbflags2 & VB2_301) {
-       svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
-       myflag = SiS_GetReg(SISPART4, 0x01);
-       if(myflag & 0x04) {
-	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
-       }
-    } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
-       svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
-    } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
-       svhs = 0x0200; cvbs = 0x0100;
-    } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
-       svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
-    } else
-       return;
-
-    vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
-    if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
-       svhs_c = 0x0408; cvbs_c = 0x0808;
-    }
-
-    biosflag = 2;
-    if(ivideo->haveXGIROM) {
-       biosflag = ivideo->bios_abase[0x58] & 0x03;
-    } else if(ivideo->newrom) {
-       if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
-    } else if(ivideo->sisvga_engine == SIS_300_VGA) {
-       if(ivideo->bios_abase) {
-          biosflag = ivideo->bios_abase[0xfe] & 0x03;
-       }
-    }
-
-    if(ivideo->chip == SIS_300) {
-       myflag = SiS_GetReg(SISSR, 0x3b);
-       if(!(myflag & 0x01)) vga2 = vga2_c = 0;
-    }
-
-    if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
-       vga2 = vga2_c = 0;
-    }
-
-    backupSR_1e = SiS_GetReg(SISSR, 0x1e);
-    SiS_SetRegOR(SISSR, 0x1e, 0x20);
-
-    backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
-    if(ivideo->vbflags2 & VB2_30xC) {
-	SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
-    } else {
-       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
-    }
-    SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
-
-    backupP2_00 = SiS_GetReg(SISPART2, 0x00);
-    SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
-
-    backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
-    if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
-	SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
-    }
-
-    if(!(ivideo->vbflags2 & VB2_30xCLV)) {
-       SISDoSense(ivideo, 0, 0);
-    }
-
-    SiS_SetRegAND(SISCR, 0x32, ~0x14);
-
-    if(vga2_c || vga2) {
-       if(SISDoSense(ivideo, vga2, vga2_c)) {
-          if(biosflag & 0x01) {
-	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
-	     SiS_SetRegOR(SISCR, 0x32, 0x04);
-	  } else {
-	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
-	     SiS_SetRegOR(SISCR, 0x32, 0x10);
-	  }
-       }
-    }
-
-    SiS_SetRegAND(SISCR, 0x32, 0x3f);
-
-    if(ivideo->vbflags2 & VB2_30xCLV) {
-       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
-    }
-
-    if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
-       SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
-       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
-       if((result = SISDoSense(ivideo, svhs, 0x0604))) {
-          if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
-	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
-	     SiS_SetRegOR(SISCR, 0x32, 0x80);
-	  }
-       }
-       SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
-    }
-
-    SiS_SetRegAND(SISCR, 0x32, ~0x03);
-
-    if(!(ivideo->vbflags & TV_YPBPR)) {
-       if((result = SISDoSense(ivideo, svhs, svhs_c))) {
-          printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
-	   SiS_SetRegOR(SISCR, 0x32, 0x02);
-       }
-       if((biosflag & 0x02) || (!result)) {
-          if(SISDoSense(ivideo, cvbs, cvbs_c)) {
-	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
-	     SiS_SetRegOR(SISCR, 0x32, 0x01);
-          }
-       }
-    }
-
-    SISDoSense(ivideo, 0, 0);
-
-    SiS_SetReg(SISPART2, 0x00, backupP2_00);
-    SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
-    SiS_SetReg(SISSR, 0x1e, backupSR_1e);
-
-    if(ivideo->vbflags2 & VB2_30xCLV) {
-	biosflag = SiS_GetReg(SISPART2, 0x00);
-       if(biosflag & 0x20) {
-          for(myflag = 2; myflag > 0; myflag--) {
-	     biosflag ^= 0x20;
-	     SiS_SetReg(SISPART2, 0x00, biosflag);
-	  }
-       }
-    }
-
-    SiS_SetReg(SISPART2, 0x00, backupP2_00);
-}
-
-/* Determine and detect attached TV's on Chrontel */
-static void SiS_SenseCh(struct sis_video_info *ivideo)
-{
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-    u8 temp1, temp2;
-    char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
-#endif
-#ifdef CONFIG_FB_SIS_300
-    unsigned char test[3];
-    int i;
-#endif
-
-    if(ivideo->chip < SIS_315H) {
-
-#ifdef CONFIG_FB_SIS_300
-       ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
-       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
-       SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
-       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
-       /* See Chrontel TB31 for explanation */
-       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
-       if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
-	  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
-	  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
-       }
-       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
-       if(temp2 != temp1) temp1 = temp2;
-
-       if((temp1 >= 0x22) && (temp1 <= 0x50)) {
-	   /* Read power status */
-	   temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
-	   if((temp1 & 0x03) != 0x03) {
-		/* Power all outputs */
-		SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
-		SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
-	   }
-	   /* Sense connected TV devices */
-	   for(i = 0; i < 3; i++) {
-	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
-	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
-	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
-	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
-	       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
-	       if(!(temp1 & 0x08))       test[i] = 0x02;
-	       else if(!(temp1 & 0x02))  test[i] = 0x01;
-	       else                      test[i] = 0;
-	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
-	   }
-
-	   if(test[0] == test[1])      temp1 = test[0];
-	   else if(test[0] == test[2]) temp1 = test[0];
-	   else if(test[1] == test[2]) temp1 = test[1];
-	   else {
-		printk(KERN_INFO
-			"sisfb: TV detection unreliable - test results varied\n");
-		temp1 = test[2];
-	   }
-	   if(temp1 == 0x02) {
-		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
-		ivideo->vbflags |= TV_SVIDEO;
-		SiS_SetRegOR(SISCR, 0x32, 0x02);
-		SiS_SetRegAND(SISCR, 0x32, ~0x05);
-	   } else if (temp1 == 0x01) {
-		printk(KERN_INFO "%s CVBS output\n", stdstr);
-		ivideo->vbflags |= TV_AVIDEO;
-		SiS_SetRegOR(SISCR, 0x32, 0x01);
-		SiS_SetRegAND(SISCR, 0x32, ~0x06);
-	   } else {
-		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
-		SiS_SetRegAND(SISCR, 0x32, ~0x07);
-	   }
-       } else if(temp1 == 0) {
-	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
-	  SiS_SetRegAND(SISCR, 0x32, ~0x07);
-       }
-       /* Set general purpose IO for Chrontel communication */
-       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
-#endif
-
-    } else {
-
-#ifdef CONFIG_FB_SIS_315
-	ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
-	temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
-	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
-	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
-	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
-	temp2 |= 0x01;
-	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
-	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
-	temp2 ^= 0x01;
-	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
-	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
-	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
-	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
-	temp1 = 0;
-	if(temp2 & 0x02) temp1 |= 0x01;
-	if(temp2 & 0x10) temp1 |= 0x01;
-	if(temp2 & 0x04) temp1 |= 0x02;
-	if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
-	switch(temp1) {
-	case 0x01:
-	     printk(KERN_INFO "%s CVBS output\n", stdstr);
-	     ivideo->vbflags |= TV_AVIDEO;
-	     SiS_SetRegOR(SISCR, 0x32, 0x01);
-	     SiS_SetRegAND(SISCR, 0x32, ~0x06);
-	     break;
-	case 0x02:
-	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
-	     ivideo->vbflags |= TV_SVIDEO;
-	     SiS_SetRegOR(SISCR, 0x32, 0x02);
-	     SiS_SetRegAND(SISCR, 0x32, ~0x05);
-	     break;
-	case 0x04:
-	     printk(KERN_INFO "%s SCART output\n", stdstr);
-	     SiS_SetRegOR(SISCR, 0x32, 0x04);
-	     SiS_SetRegAND(SISCR, 0x32, ~0x03);
-	     break;
-	default:
-	     SiS_SetRegAND(SISCR, 0x32, ~0x07);
-	}
-#endif
-    }
-}
-
-static void sisfb_get_VB_type(struct sis_video_info *ivideo)
-{
-	char stdstr[]    = "sisfb: Detected";
-	char bridgestr[] = "video bridge";
-	u8 vb_chipid;
-	u8 reg;
-
-	/* No CRT2 on XGI Z7 */
-	if(ivideo->chip == XGI_20)
-		return;
-
-	vb_chipid = SiS_GetReg(SISPART4, 0x00);
-	switch(vb_chipid) {
-	case 0x01:
-		reg = SiS_GetReg(SISPART4, 0x01);
-		if(reg < 0xb0) {
-			ivideo->vbflags |= VB_301;	/* Deprecated */
-			ivideo->vbflags2 |= VB2_301;
-			printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
-		} else if(reg < 0xc0) {
-			ivideo->vbflags |= VB_301B;	/* Deprecated */
-			ivideo->vbflags2 |= VB2_301B;
-			reg = SiS_GetReg(SISPART4, 0x23);
-			if(!(reg & 0x02)) {
-			   ivideo->vbflags |= VB_30xBDH;	/* Deprecated */
-			   ivideo->vbflags2 |= VB2_30xBDH;
-			   printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
-			} else {
-			   printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
-			}
-		} else if(reg < 0xd0) {
-			ivideo->vbflags |= VB_301C;	/* Deprecated */
-			ivideo->vbflags2 |= VB2_301C;
-			printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
-		} else if(reg < 0xe0) {
-			ivideo->vbflags |= VB_301LV;	/* Deprecated */
-			ivideo->vbflags2 |= VB2_301LV;
-			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
-		} else if(reg <= 0xe1) {
-			reg = SiS_GetReg(SISPART4, 0x39);
-			if(reg == 0xff) {
-			   ivideo->vbflags |= VB_302LV;	/* Deprecated */
-			   ivideo->vbflags2 |= VB2_302LV;
-			   printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
-			} else {
-			   ivideo->vbflags |= VB_301C;	/* Deprecated */
-			   ivideo->vbflags2 |= VB2_301C;
-			   printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
-#if 0
-			   ivideo->vbflags |= VB_302ELV;	/* Deprecated */
-			   ivideo->vbflags2 |= VB2_302ELV;
-			   printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
-#endif
-			}
-		}
-		break;
-	case 0x02:
-		ivideo->vbflags |= VB_302B;	/* Deprecated */
-		ivideo->vbflags2 |= VB2_302B;
-		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
-		break;
-	}
-
-	if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
-		reg = SiS_GetReg(SISCR, 0x37);
-		reg &= SIS_EXTERNAL_CHIP_MASK;
-		reg >>= 1;
-		if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-			switch(reg) {
-			   case SIS_EXTERNAL_CHIP_LVDS:
-				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
-				ivideo->vbflags2 |= VB2_LVDS;
-				break;
-			   case SIS_EXTERNAL_CHIP_TRUMPION:
-				ivideo->vbflags |= (VB_LVDS | VB_TRUMPION);	/* Deprecated */
-				ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
-				break;
-			   case SIS_EXTERNAL_CHIP_CHRONTEL:
-				ivideo->vbflags |= VB_CHRONTEL;	/* Deprecated */
-				ivideo->vbflags2 |= VB2_CHRONTEL;
-				break;
-			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
-				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
-				break;
-			}
-			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
-#endif
-		} else if(ivideo->chip < SIS_661) {
-#ifdef CONFIG_FB_SIS_315
-			switch (reg) {
-			   case SIS310_EXTERNAL_CHIP_LVDS:
-				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
-				ivideo->vbflags2 |= VB2_LVDS;
-				break;
-			   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
-				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
-				break;
-			}
-			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
-#endif
-		} else if(ivideo->chip >= SIS_661) {
-#ifdef CONFIG_FB_SIS_315
-			reg = SiS_GetReg(SISCR, 0x38);
-			reg >>= 5;
-			switch(reg) {
-			   case 0x02:
-				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
-				ivideo->vbflags2 |= VB2_LVDS;
-				break;
-			   case 0x03:
-				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
-				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
-				break;
-			   case 0x04:
-				ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);	/* Deprecated */
-				ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
-				break;
-			}
-			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
-#endif
-		}
-		if(ivideo->vbflags2 & VB2_LVDS) {
-		   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
-		}
-		if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
-		   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
-		}
-		if(ivideo->vbflags2 & VB2_CHRONTEL) {
-		   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
-		}
-		if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
-		   printk(KERN_INFO "%s Conexant external device\n", stdstr);
-		}
-	}
-
-	if(ivideo->vbflags2 & VB2_SISBRIDGE) {
-		SiS_SenseLCD(ivideo);
-		SiS_Sense30x(ivideo);
-	} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
-		SiS_SenseCh(ivideo);
-	}
-}
-
-/* ---------- Engine initialization routines ------------ */
-
-static void
-sisfb_engine_init(struct sis_video_info *ivideo)
-{
-
-	/* Initialize command queue (we use MMIO only) */
-
-	/* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
-
-	ivideo->caps &= ~(TURBO_QUEUE_CAP    |
-			  MMIO_CMD_QUEUE_CAP |
-			  VM_CMD_QUEUE_CAP   |
-			  AGP_CMD_QUEUE_CAP);
-
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		u32 tqueue_pos;
-		u8 tq_state;
-
-		tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
-
-		tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
-		tq_state |= 0xf0;
-		tq_state &= 0xfc;
-		tq_state |= (u8)(tqueue_pos >> 8);
-		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-
-		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
-
-		ivideo->caps |= TURBO_QUEUE_CAP;
-	}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-	if(ivideo->sisvga_engine == SIS_315_VGA) {
-		u32 tempq = 0, templ;
-		u8  temp;
-
-		if(ivideo->chip == XGI_20) {
-			switch(ivideo->cmdQueueSize) {
-			case (64 * 1024):
-				temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
-				break;
-			case (128 * 1024):
-			default:
-				temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
-			}
-		} else {
-			switch(ivideo->cmdQueueSize) {
-			case (4 * 1024 * 1024):
-				temp = SIS_CMD_QUEUE_SIZE_4M;
-				break;
-			case (2 * 1024 * 1024):
-				temp = SIS_CMD_QUEUE_SIZE_2M;
-				break;
-			case (1 * 1024 * 1024):
-				temp = SIS_CMD_QUEUE_SIZE_1M;
-				break;
-			default:
-			case (512 * 1024):
-				temp = SIS_CMD_QUEUE_SIZE_512k;
-			}
-		}
-
-		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-		if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
-			/* Must disable dual pipe on XGI_40. Can't do
-			 * this in MMIO mode, because it requires
-			 * setting/clearing a bit in the MMIO fire trigger
-			 * register.
-			 */
-			if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
-
-				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
-
-				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
-
-				tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
-				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
-
-				tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
-				MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
-
-				writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
-				writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
-				writel(0x168F0000, ivideo->video_vbase + tempq + 8);
-				writel(0x168F0000, ivideo->video_vbase + tempq + 12);
-
-				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
-
-				sisfb_syncaccel(ivideo);
-
-				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-			}
-		}
-
-		tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
-		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
-
-		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
-		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
-
-		tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
-		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
-
-		ivideo->caps |= MMIO_CMD_QUEUE_CAP;
-	}
-#endif
-
-	ivideo->engineok = 1;
-}
-
-static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
-{
-	u8 reg;
-	int i;
-
-	reg = SiS_GetReg(SISCR, 0x36);
-	reg &= 0x0f;
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		ivideo->CRT2LCDType = sis300paneltype[reg];
-	} else if(ivideo->chip >= SIS_661) {
-		ivideo->CRT2LCDType = sis661paneltype[reg];
-	} else {
-		ivideo->CRT2LCDType = sis310paneltype[reg];
-		if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
-			if((ivideo->CRT2LCDType != LCD_320x240_2) &&
-			   (ivideo->CRT2LCDType != LCD_320x240_3)) {
-				ivideo->CRT2LCDType = LCD_320x240;
-			}
-		}
-	}
-
-	if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
-		/* For broken BIOSes: Assume 1024x768, RGB18 */
-		ivideo->CRT2LCDType = LCD_1024x768;
-		SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
-		SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
-		printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
-	}
-
-	for(i = 0; i < SIS_LCD_NUMBER; i++) {
-		if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
-			ivideo->lcdxres = sis_lcd_data[i].xres;
-			ivideo->lcdyres = sis_lcd_data[i].yres;
-			ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
-			break;
-		}
-	}
-
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
-		ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
-		ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
-	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
-		ivideo->lcdxres =  848; ivideo->lcdyres =  480;
-		ivideo->lcddefmodeidx = DEFAULT_MODE_848;
-	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
-		ivideo->lcdxres =  856; ivideo->lcdyres =  480;
-		ivideo->lcddefmodeidx = DEFAULT_MODE_856;
-	}
-#endif
-
-	printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
-			ivideo->lcdxres, ivideo->lcdyres);
-}
-
-static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
-{
-#ifdef CONFIG_FB_SIS_300
-	/* Save the current PanelDelayCompensation if the LCD is currently used */
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
-			int tmp;
-			tmp = SiS_GetReg(SISCR, 0x30);
-			if(tmp & 0x20) {
-				/* Currently on LCD? If yes, read current pdc */
-				ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
-				ivideo->detectedpdc &= 0x3c;
-				if(ivideo->SiS_Pr.PDC == -1) {
-					/* Let option override detection */
-					ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
-				}
-				printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
-					ivideo->detectedpdc);
-			}
-			if((ivideo->SiS_Pr.PDC != -1) &&
-			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
-				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
-					ivideo->SiS_Pr.PDC);
-			}
-		}
-	}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-	if(ivideo->sisvga_engine == SIS_315_VGA) {
-
-		/* Try to find about LCDA */
-		if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
-			int tmp;
-			tmp = SiS_GetReg(SISPART1, 0x13);
-			if(tmp & 0x04) {
-				ivideo->SiS_Pr.SiS_UseLCDA = true;
-				ivideo->detectedlcda = 0x03;
-			}
-		}
-
-		/* Save PDC */
-		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
-			int tmp;
-			tmp = SiS_GetReg(SISCR, 0x30);
-			if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
-				/* Currently on LCD? If yes, read current pdc */
-				u8 pdc;
-				pdc = SiS_GetReg(SISPART1, 0x2D);
-				ivideo->detectedpdc  = (pdc & 0x0f) << 1;
-				ivideo->detectedpdca = (pdc & 0xf0) >> 3;
-				pdc = SiS_GetReg(SISPART1, 0x35);
-				ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
-				pdc = SiS_GetReg(SISPART1, 0x20);
-				ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
-				if(ivideo->newrom) {
-					/* New ROM invalidates other PDC resp. */
-					if(ivideo->detectedlcda != 0xff) {
-						ivideo->detectedpdc = 0xff;
-					} else {
-						ivideo->detectedpdca = 0xff;
-					}
-				}
-				if(ivideo->SiS_Pr.PDC == -1) {
-					if(ivideo->detectedpdc != 0xff) {
-						ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
-					}
-				}
-				if(ivideo->SiS_Pr.PDCA == -1) {
-					if(ivideo->detectedpdca != 0xff) {
-						ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
-					}
-				}
-				if(ivideo->detectedpdc != 0xff) {
-					printk(KERN_INFO
-						"sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
-						ivideo->detectedpdc);
-				}
-				if(ivideo->detectedpdca != 0xff) {
-					printk(KERN_INFO
-						"sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
-						ivideo->detectedpdca);
-				}
-			}
-
-			/* Save EMI */
-			if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
-				ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
-				ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
-				ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
-				ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
-				ivideo->SiS_Pr.HaveEMI = true;
-				if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
-					ivideo->SiS_Pr.HaveEMILCD = true;
-				}
-			}
-		}
-
-		/* Let user override detected PDCs (all bridges) */
-		if(ivideo->vbflags2 & VB2_30xBLV) {
-			if((ivideo->SiS_Pr.PDC != -1) &&
-			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
-				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
-					ivideo->SiS_Pr.PDC);
-			}
-			if((ivideo->SiS_Pr.PDCA != -1) &&
-			   (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
-				printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
-				 ivideo->SiS_Pr.PDCA);
-			}
-		}
-
-	}
-#endif
-}
-
-/* -------------------- Memory manager routines ---------------------- */
-
-static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
-{
-	u32 ret = ivideo->sisfb_parm_mem * 1024;
-	u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
-	u32 def;
-
-	/* Calculate heap start = end of memory for console
-	 *
-	 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
-	 * C = console, D = heap, H = HWCursor, Q = cmd-queue
-	 *
-	 * On 76x in UMA+LFB mode, the layout is as follows:
-	 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
-	 * where the heap is the entire UMA area, eventually
-	 * into the LFB area if the given mem parameter is
-	 * higher than the size of the UMA memory.
-	 *
-	 * Basically given by "mem" parameter
-	 *
-	 * maximum = videosize - cmd_queue - hwcursor
-	 *           (results in a heap of size 0)
-	 * default = SiS 300: depends on videosize
-	 *           SiS 315/330/340/XGI: 32k below max
-	 */
-
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		if(ivideo->video_size > 0x1000000) {
-			def = 0xc00000;
-		} else if(ivideo->video_size > 0x800000) {
-			def = 0x800000;
-		} else {
-			def = 0x400000;
-		}
-	} else if(ivideo->UMAsize && ivideo->LFBsize) {
-		ret = def = 0;
-	} else {
-		def = maxoffs - 0x8000;
-	}
-
-	/* Use default for secondary card for now (FIXME) */
-	if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
-		ret = def;
-
-	return ret;
-}
-
-static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
-{
-	u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
-	u32 ret = 0;
-
-	if(ivideo->UMAsize && ivideo->LFBsize) {
-		if( (!ivideo->sisfb_parm_mem)			||
-		    ((ivideo->sisfb_parm_mem * 1024) > max)	||
-		    ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
-			ret = ivideo->UMAsize;
-			max -= ivideo->UMAsize;
-		} else {
-			ret = max - (ivideo->sisfb_parm_mem * 1024);
-			max = ivideo->sisfb_parm_mem * 1024;
-		}
-		ivideo->video_offset = ret;
-		ivideo->sisfb_mem = max;
-	} else {
-		ret = max - ivideo->heapstart;
-		ivideo->sisfb_mem = ivideo->heapstart;
-	}
-
-	return ret;
-}
-
-static int sisfb_heap_init(struct sis_video_info *ivideo)
-{
-	struct SIS_OH *poh;
-
-	ivideo->video_offset = 0;
-	if(ivideo->sisfb_parm_mem) {
-		if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
-		    (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
-			ivideo->sisfb_parm_mem = 0;
-		}
-	}
-
-	ivideo->heapstart = sisfb_getheapstart(ivideo);
-	ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
-
-	ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
-	ivideo->sisfb_heap_end   = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
-
-	printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
-		(int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
-
-	ivideo->sisfb_heap.vinfo = ivideo;
-
-	ivideo->sisfb_heap.poha_chain = NULL;
-	ivideo->sisfb_heap.poh_freelist = NULL;
-
-	poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
-	if(poh == NULL)
-		return 1;
-
-	poh->poh_next = &ivideo->sisfb_heap.oh_free;
-	poh->poh_prev = &ivideo->sisfb_heap.oh_free;
-	poh->size = ivideo->sisfb_heap_size;
-	poh->offset = ivideo->heapstart;
-
-	ivideo->sisfb_heap.oh_free.poh_next = poh;
-	ivideo->sisfb_heap.oh_free.poh_prev = poh;
-	ivideo->sisfb_heap.oh_free.size = 0;
-	ivideo->sisfb_heap.max_freesize = poh->size;
-
-	ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
-	ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
-	ivideo->sisfb_heap.oh_used.size = SENTINEL;
-
-	if(ivideo->cardnumber == 0) {
-		/* For the first card, make this heap the "global" one
-		 * for old DRM (which could handle only one card)
-		 */
-		sisfb_heap = &ivideo->sisfb_heap;
-	}
-
-	return 0;
-}
-
-static struct SIS_OH *
-sisfb_poh_new_node(struct SIS_HEAP *memheap)
-{
-	struct SIS_OHALLOC	*poha;
-	struct SIS_OH		*poh;
-	unsigned long		cOhs;
-	int			i;
-
-	if(memheap->poh_freelist == NULL) {
-		poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
-		if(!poha)
-			return NULL;
-
-		poha->poha_next = memheap->poha_chain;
-		memheap->poha_chain = poha;
-
-		cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
-
-		poh = &poha->aoh[0];
-		for(i = cOhs - 1; i != 0; i--) {
-			poh->poh_next = poh + 1;
-			poh = poh + 1;
-		}
-
-		poh->poh_next = NULL;
-		memheap->poh_freelist = &poha->aoh[0];
-	}
-
-	poh = memheap->poh_freelist;
-	memheap->poh_freelist = poh->poh_next;
-
-	return poh;
-}
-
-static struct SIS_OH *
-sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
-{
-	struct SIS_OH	*pohThis;
-	struct SIS_OH	*pohRoot;
-	int		bAllocated = 0;
-
-	if(size > memheap->max_freesize) {
-		DPRINTK("sisfb: Can't allocate %dk video memory\n",
-			(unsigned int) size / 1024);
-		return NULL;
-	}
-
-	pohThis = memheap->oh_free.poh_next;
-
-	while(pohThis != &memheap->oh_free) {
-		if(size <= pohThis->size) {
-			bAllocated = 1;
-			break;
-		}
-		pohThis = pohThis->poh_next;
-	}
-
-	if(!bAllocated) {
-		DPRINTK("sisfb: Can't allocate %dk video memory\n",
-			(unsigned int) size / 1024);
-		return NULL;
-	}
-
-	if(size == pohThis->size) {
-		pohRoot = pohThis;
-		sisfb_delete_node(pohThis);
-	} else {
-		pohRoot = sisfb_poh_new_node(memheap);
-		if(pohRoot == NULL)
-			return NULL;
-
-		pohRoot->offset = pohThis->offset;
-		pohRoot->size = size;
-
-		pohThis->offset += size;
-		pohThis->size -= size;
-	}
-
-	memheap->max_freesize -= size;
-
-	pohThis = &memheap->oh_used;
-	sisfb_insert_node(pohThis, pohRoot);
-
-	return pohRoot;
-}
-
-static void
-sisfb_delete_node(struct SIS_OH *poh)
-{
-	poh->poh_prev->poh_next = poh->poh_next;
-	poh->poh_next->poh_prev = poh->poh_prev;
-}
-
-static void
-sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
-{
-	struct SIS_OH *pohTemp = pohList->poh_next;
-
-	pohList->poh_next = poh;
-	pohTemp->poh_prev = poh;
-
-	poh->poh_prev = pohList;
-	poh->poh_next = pohTemp;
-}
-
-static struct SIS_OH *
-sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
-{
-	struct SIS_OH *pohThis;
-	struct SIS_OH *poh_freed;
-	struct SIS_OH *poh_prev;
-	struct SIS_OH *poh_next;
-	u32    ulUpper;
-	u32    ulLower;
-	int    foundNode = 0;
-
-	poh_freed = memheap->oh_used.poh_next;
-
-	while(poh_freed != &memheap->oh_used) {
-		if(poh_freed->offset == base) {
-			foundNode = 1;
-			break;
-		}
-
-		poh_freed = poh_freed->poh_next;
-	}
-
-	if(!foundNode)
-		return NULL;
-
-	memheap->max_freesize += poh_freed->size;
-
-	poh_prev = poh_next = NULL;
-	ulUpper = poh_freed->offset + poh_freed->size;
-	ulLower = poh_freed->offset;
-
-	pohThis = memheap->oh_free.poh_next;
-
-	while(pohThis != &memheap->oh_free) {
-		if(pohThis->offset == ulUpper) {
-			poh_next = pohThis;
-		} else if((pohThis->offset + pohThis->size) == ulLower) {
-			poh_prev = pohThis;
-		}
-		pohThis = pohThis->poh_next;
-	}
-
-	sisfb_delete_node(poh_freed);
-
-	if(poh_prev && poh_next) {
-		poh_prev->size += (poh_freed->size + poh_next->size);
-		sisfb_delete_node(poh_next);
-		sisfb_free_node(memheap, poh_freed);
-		sisfb_free_node(memheap, poh_next);
-		return poh_prev;
-	}
-
-	if(poh_prev) {
-		poh_prev->size += poh_freed->size;
-		sisfb_free_node(memheap, poh_freed);
-		return poh_prev;
-	}
-
-	if(poh_next) {
-		poh_next->size += poh_freed->size;
-		poh_next->offset = poh_freed->offset;
-		sisfb_free_node(memheap, poh_freed);
-		return poh_next;
-	}
-
-	sisfb_insert_node(&memheap->oh_free, poh_freed);
-
-	return poh_freed;
-}
-
-static void
-sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
-{
-	if(poh == NULL)
-		return;
-
-	poh->poh_next = memheap->poh_freelist;
-	memheap->poh_freelist = poh;
-}
-
-static void
-sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
-{
-	struct SIS_OH *poh = NULL;
-
-	if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
-		poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
-
-	if(poh == NULL) {
-		req->offset = req->size = 0;
-		DPRINTK("sisfb: Video RAM allocation failed\n");
-	} else {
-		req->offset = poh->offset;
-		req->size = poh->size;
-		DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
-			(poh->offset + ivideo->video_vbase));
-	}
-}
-
-void
-sis_malloc(struct sis_memreq *req)
-{
-	struct sis_video_info *ivideo = sisfb_heap->vinfo;
-
-	if(&ivideo->sisfb_heap == sisfb_heap)
-		sis_int_malloc(ivideo, req);
-	else
-		req->offset = req->size = 0;
-}
-
-void
-sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
-{
-	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-
-	sis_int_malloc(ivideo, req);
-}
-
-/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
-
-static void
-sis_int_free(struct sis_video_info *ivideo, u32 base)
-{
-	struct SIS_OH *poh;
-
-	if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
-		return;
-
-	poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
-
-	if(poh == NULL) {
-		DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
-			(unsigned int) base);
-	}
-}
-
-void
-sis_free(u32 base)
-{
-	struct sis_video_info *ivideo = sisfb_heap->vinfo;
-
-	sis_int_free(ivideo, base);
-}
-
-void
-sis_free_new(struct pci_dev *pdev, u32 base)
-{
-	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-
-	sis_int_free(ivideo, base);
-}
-
-/* --------------------- SetMode routines ------------------------- */
-
-static void
-sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
-{
-	u8 cr30, cr31;
-
-	/* Check if MMIO and engines are enabled,
-	 * and sync in case they are. Can't use
-	 * ivideo->accel here, as this might have
-	 * been changed before this is called.
-	 */
-	cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
-	cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
-	/* MMIO and 2D/3D engine enabled? */
-	if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
-#ifdef CONFIG_FB_SIS_300
-		if(ivideo->sisvga_engine == SIS_300_VGA) {
-			/* Don't care about TurboQueue. It's
-			 * enough to know that the engines
-			 * are enabled
-			 */
-			sisfb_syncaccel(ivideo);
-		}
-#endif
-#ifdef CONFIG_FB_SIS_315
-		if(ivideo->sisvga_engine == SIS_315_VGA) {
-			/* Check that any queue mode is
-			 * enabled, and that the queue
-			 * is not in the state of "reset"
-			 */
-			cr30 = SiS_GetReg(SISSR, 0x26);
-			if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
-				sisfb_syncaccel(ivideo);
-			}
-		}
-#endif
-	}
-}
-
-static void
-sisfb_pre_setmode(struct sis_video_info *ivideo)
-{
-	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
-	int tvregnum = 0;
-
-	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
-
-	SiS_SetReg(SISSR, 0x05, 0x86);
-
-	cr31 = SiS_GetReg(SISCR, 0x31);
-	cr31 &= ~0x60;
-	cr31 |= 0x04;
-
-	cr33 = ivideo->rate_idx & 0x0F;
-
-#ifdef CONFIG_FB_SIS_315
-	if(ivideo->sisvga_engine == SIS_315_VGA) {
-	   if(ivideo->chip >= SIS_661) {
-	      cr38 = SiS_GetReg(SISCR, 0x38);
-	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
-	   } else {
-	      tvregnum = 0x38;
-	      cr38 = SiS_GetReg(SISCR, tvregnum);
-	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
-	   }
-	}
-#endif
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-	   tvregnum = 0x35;
-	   cr38 = SiS_GetReg(SISCR, tvregnum);
-	}
-#endif
-
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
-	ivideo->curFSTN = ivideo->curDSTN = 0;
-
-	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-
-	   case CRT2_TV:
-	      cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
-	      if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
-#ifdef CONFIG_FB_SIS_315
-		 if(ivideo->chip >= SIS_661) {
-		    cr38 |= 0x04;
-		    if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
-		    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
-		    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
-		    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
-		    cr35 &= ~0x01;
-		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
-		 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
-		    cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		    cr38 |= 0x08;
-		    if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
-		    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
-		    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
-		    cr31 &= ~0x01;
-		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
-		 }
-#endif
-	      } else if((ivideo->vbflags & TV_HIVISION) &&
-				(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
-		 if(ivideo->chip >= SIS_661) {
-		    cr38 |= 0x04;
-		    cr35 |= 0x60;
-		 } else {
-		    cr30 |= 0x80;
-		 }
-		 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
-		 cr31 |= 0x01;
-		 cr35 |= 0x01;
-		 ivideo->currentvbflags |= TV_HIVISION;
-	      } else if(ivideo->vbflags & TV_SCART) {
-		 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		 cr31 |= 0x01;
-		 cr35 |= 0x01;
-		 ivideo->currentvbflags |= TV_SCART;
-	      } else {
-		 if(ivideo->vbflags & TV_SVIDEO) {
-		    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		    ivideo->currentvbflags |= TV_SVIDEO;
-		 }
-		 if(ivideo->vbflags & TV_AVIDEO) {
-		    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		    ivideo->currentvbflags |= TV_AVIDEO;
-		 }
-	      }
-	      cr31 |= SIS_DRIVER_MODE;
-
-	      if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
-		 if(ivideo->vbflags & TV_PAL) {
-		    cr31 |= 0x01; cr35 |= 0x01;
-		    ivideo->currentvbflags |= TV_PAL;
-		    if(ivideo->vbflags & TV_PALM) {
-		       cr38 |= 0x40; cr35 |= 0x04;
-		       ivideo->currentvbflags |= TV_PALM;
-		    } else if(ivideo->vbflags & TV_PALN) {
-		       cr38 |= 0x80; cr35 |= 0x08;
-		       ivideo->currentvbflags |= TV_PALN;
-		    }
-		 } else {
-		    cr31 &= ~0x01; cr35 &= ~0x01;
-		    ivideo->currentvbflags |= TV_NTSC;
-		    if(ivideo->vbflags & TV_NTSCJ) {
-		       cr38 |= 0x40; cr35 |= 0x02;
-		       ivideo->currentvbflags |= TV_NTSCJ;
-		    }
-		 }
-	      }
-	      break;
-
-	   case CRT2_LCD:
-	      cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
-	      cr31 |= SIS_DRIVER_MODE;
-	      SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
-	      SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
-	      ivideo->curFSTN = ivideo->sisfb_fstn;
-	      ivideo->curDSTN = ivideo->sisfb_dstn;
-	      break;
-
-	   case CRT2_VGA:
-	      cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
-	      cr31 |= SIS_DRIVER_MODE;
-	      if(ivideo->sisfb_nocrt2rate) {
-		 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
-	      } else {
-		 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
-	      }
-	      break;
-
-	   default:	/* disable CRT2 */
-	      cr30 = 0x00;
-	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
-	}
-
-	SiS_SetReg(SISCR, 0x30, cr30);
-	SiS_SetReg(SISCR, 0x33, cr33);
-
-	if(ivideo->chip >= SIS_661) {
-#ifdef CONFIG_FB_SIS_315
-	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
-	   SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
-	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
-	   SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
-#endif
-	} else if(ivideo->chip != SIS_300) {
-	   SiS_SetReg(SISCR, tvregnum, cr38);
-	}
-	SiS_SetReg(SISCR, 0x31, cr31);
-
-	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
-
-	sisfb_check_engine_and_sync(ivideo);
-}
-
-/* Fix SR11 for 661 and later */
-#ifdef CONFIG_FB_SIS_315
-static void
-sisfb_fixup_SR11(struct sis_video_info *ivideo)
-{
-	u8  tmpreg;
-
-	if(ivideo->chip >= SIS_661) {
-		tmpreg = SiS_GetReg(SISSR, 0x11);
-		if(tmpreg & 0x20) {
-			tmpreg = SiS_GetReg(SISSR, 0x3e);
-			tmpreg = (tmpreg + 1) & 0xff;
-			SiS_SetReg(SISSR, 0x3e, tmpreg);
-			tmpreg = SiS_GetReg(SISSR, 0x11);
-		}
-		if(tmpreg & 0xf0) {
-			SiS_SetRegAND(SISSR, 0x11, 0x0f);
-		}
-	}
-}
-#endif
-
-static void
-sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
-{
-	if(val > 32) val = 32;
-	if(val < -32) val = -32;
-	ivideo->tvxpos = val;
-
-	if(ivideo->sisfblocked) return;
-	if(!ivideo->modechanged) return;
-
-	if(ivideo->currentvbflags & CRT2_TV) {
-
-		if(ivideo->vbflags2 & VB2_CHRONTEL) {
-
-			int x = ivideo->tvx;
-
-			switch(ivideo->chronteltype) {
-			case 1:
-				x += val;
-				if(x < 0) x = 0;
-				SiS_SetReg(SISSR, 0x05, 0x86);
-				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
-				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
-				break;
-			case 2:
-				/* Not supported by hardware */
-				break;
-			}
-
-		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
-
-			u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
-			unsigned short temp;
-
-			p2_1f = ivideo->p2_1f;
-			p2_20 = ivideo->p2_20;
-			p2_2b = ivideo->p2_2b;
-			p2_42 = ivideo->p2_42;
-			p2_43 = ivideo->p2_43;
-
-			temp = p2_1f | ((p2_20 & 0xf0) << 4);
-			temp += (val * 2);
-			p2_1f = temp & 0xff;
-			p2_20 = (temp & 0xf00) >> 4;
-			p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
-			temp = p2_43 | ((p2_42 & 0xf0) << 4);
-			temp += (val * 2);
-			p2_43 = temp & 0xff;
-			p2_42 = (temp & 0xf00) >> 4;
-			SiS_SetReg(SISPART2, 0x1f, p2_1f);
-			SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
-			SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
-			SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
-			SiS_SetReg(SISPART2, 0x43, p2_43);
-		}
-	}
-}
-
-static void
-sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
-{
-	if(val > 32) val = 32;
-	if(val < -32) val = -32;
-	ivideo->tvypos = val;
-
-	if(ivideo->sisfblocked) return;
-	if(!ivideo->modechanged) return;
-
-	if(ivideo->currentvbflags & CRT2_TV) {
-
-		if(ivideo->vbflags2 & VB2_CHRONTEL) {
-
-			int y = ivideo->tvy;
-
-			switch(ivideo->chronteltype) {
-			case 1:
-				y -= val;
-				if(y < 0) y = 0;
-				SiS_SetReg(SISSR, 0x05, 0x86);
-				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
-				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
-				break;
-			case 2:
-				/* Not supported by hardware */
-				break;
-			}
-
-		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
-
-			char p2_01, p2_02;
-			val /= 2;
-			p2_01 = ivideo->p2_01;
-			p2_02 = ivideo->p2_02;
-
-			p2_01 += val;
-			p2_02 += val;
-			if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
-				while((p2_01 <= 0) || (p2_02 <= 0)) {
-					p2_01 += 2;
-					p2_02 += 2;
-				}
-			}
-			SiS_SetReg(SISPART2, 0x01, p2_01);
-			SiS_SetReg(SISPART2, 0x02, p2_02);
-		}
-	}
-}
-
-static void
-sisfb_post_setmode(struct sis_video_info *ivideo)
-{
-	bool crt1isoff = false;
-	bool doit = true;
-#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
-	u8 reg;
-#endif
-#ifdef CONFIG_FB_SIS_315
-	u8 reg1;
-#endif
-
-	SiS_SetReg(SISSR, 0x05, 0x86);
-
-#ifdef CONFIG_FB_SIS_315
-	sisfb_fixup_SR11(ivideo);
-#endif
-
-	/* Now we actually HAVE changed the display mode */
-	ivideo->modechanged = 1;
-
-	/* We can't switch off CRT1 if bridge is in slave mode */
-	if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
-		if(sisfb_bridgeisslave(ivideo)) doit = false;
-	} else
-		ivideo->sisfb_crt1off = 0;
-
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		if((ivideo->sisfb_crt1off) && (doit)) {
-			crt1isoff = true;
-			reg = 0x00;
-		} else {
-			crt1isoff = false;
-			reg = 0x80;
-		}
-		SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
-	}
-#endif
-#ifdef CONFIG_FB_SIS_315
-	if(ivideo->sisvga_engine == SIS_315_VGA) {
-		if((ivideo->sisfb_crt1off) && (doit)) {
-			crt1isoff = true;
-			reg  = 0x40;
-			reg1 = 0xc0;
-		} else {
-			crt1isoff = false;
-			reg  = 0x00;
-			reg1 = 0x00;
-		}
-		SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
-		SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
-	}
-#endif
-
-	if(crt1isoff) {
-		ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
-		ivideo->currentvbflags |= VB_SINGLE_MODE;
-	} else {
-		ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
-		if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
-			ivideo->currentvbflags |= VB_MIRROR_MODE;
-		} else {
-			ivideo->currentvbflags |= VB_SINGLE_MODE;
-		}
-	}
-
-	SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
-
-	if(ivideo->currentvbflags & CRT2_TV) {
-		if(ivideo->vbflags2 & VB2_SISBRIDGE) {
-			ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
-			ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
-			ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
-			ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
-			ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
-			ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
-			ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
-		} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
-			if(ivideo->chronteltype == 1) {
-				ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
-				ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
-				ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
-				ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
-			}
-		}
-	}
-
-	if(ivideo->tvxpos) {
-		sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
-	}
-	if(ivideo->tvypos) {
-		sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
-	}
-
-	/* Eventually sync engines */
-	sisfb_check_engine_and_sync(ivideo);
-
-	/* (Re-)Initialize chip engines */
-	if(ivideo->accel) {
-		sisfb_engine_init(ivideo);
-	} else {
-		ivideo->engineok = 0;
-	}
-}
-
-static int
-sisfb_reset_mode(struct sis_video_info *ivideo)
-{
-	if(sisfb_set_mode(ivideo, 0))
-		return 1;
-
-	sisfb_set_pitch(ivideo);
-	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
-	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
-
-	return 0;
-}
-
-static void
-sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
-{
-	int mycrt1off;
-
-	switch(sisfb_command->sisfb_cmd) {
-	case SISFB_CMD_GETVBFLAGS:
-		if(!ivideo->modechanged) {
-			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
-		} else {
-			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
-			sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
-			sisfb_command->sisfb_result[2] = ivideo->vbflags2;
-		}
-		break;
-	case SISFB_CMD_SWITCHCRT1:
-		/* arg[0]: 0 = off, 1 = on, 99 = query */
-		if(!ivideo->modechanged) {
-			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
-		} else if(sisfb_command->sisfb_arg[0] == 99) {
-			/* Query */
-			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
-			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
-		} else if(ivideo->sisfblocked) {
-			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
-		} else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
-					(sisfb_command->sisfb_arg[0] == 0)) {
-			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
-		} else {
-			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
-			mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
-			if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
-			    ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
-				ivideo->sisfb_crt1off = mycrt1off;
-				if(sisfb_reset_mode(ivideo)) {
-					sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
-				}
-			}
-			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
-		}
-		break;
-	/* more to come */
-	default:
-		sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
-		printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
-			sisfb_command->sisfb_cmd);
-	}
-}
-
-#ifndef MODULE
-static int __init sisfb_setup(char *options)
-{
-	char *this_opt;
-
-	sisfb_setdefaultparms();
-
-	if(!options || !(*options))
-		return 0;
-
-	while((this_opt = strsep(&options, ",")) != NULL) {
-
-		if(!(*this_opt)) continue;
-
-		if(!strnicmp(this_opt, "off", 3)) {
-			sisfb_off = 1;
-		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
-			/* Need to check crt2 type first for fstn/dstn */
-			sisfb_search_crt2type(this_opt + 14);
-		} else if(!strnicmp(this_opt, "tvmode:",7)) {
-			sisfb_search_tvstd(this_opt + 7);
-		} else if(!strnicmp(this_opt, "tvstandard:",11)) {
-			sisfb_search_tvstd(this_opt + 11);
-		} else if(!strnicmp(this_opt, "mode:", 5)) {
-			sisfb_search_mode(this_opt + 5, false);
-		} else if(!strnicmp(this_opt, "vesa:", 5)) {
-			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
-		} else if(!strnicmp(this_opt, "rate:", 5)) {
-			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
-		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
-			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-		} else if(!strnicmp(this_opt, "mem:",4)) {
-			sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if(!strnicmp(this_opt, "pdc:", 4)) {
-			sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if(!strnicmp(this_opt, "pdc1:", 5)) {
-			sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
-		} else if(!strnicmp(this_opt, "noaccel", 7)) {
-			sisfb_accel = 0;
-		} else if(!strnicmp(this_opt, "accel", 5)) {
-			sisfb_accel = -1;
-		} else if(!strnicmp(this_opt, "noypan", 6)) {
-			sisfb_ypan = 0;
-		} else if(!strnicmp(this_opt, "ypan", 4)) {
-			sisfb_ypan = -1;
-		} else if(!strnicmp(this_opt, "nomax", 5)) {
-			sisfb_max = 0;
-		} else if(!strnicmp(this_opt, "max", 3)) {
-			sisfb_max = -1;
-		} else if(!strnicmp(this_opt, "userom:", 7)) {
-			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if(!strnicmp(this_opt, "useoem:", 7)) {
-			sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
-			sisfb_nocrt2rate = 1;
-		} else if(!strnicmp(this_opt, "scalelcd:", 9)) {
-			unsigned long temp = 2;
-			temp = simple_strtoul(this_opt + 9, NULL, 0);
-			if((temp == 0) || (temp == 1)) {
-			   sisfb_scalelcd = temp ^ 1;
-			}
-		} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
-			int temp = 0;
-			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
-			if((temp >= -32) && (temp <= 32)) {
-			   sisfb_tvxposoffset = temp;
-			}
-		} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
-			int temp = 0;
-			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
-			if((temp >= -32) && (temp <= 32)) {
-			   sisfb_tvyposoffset = temp;
-			}
-		} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
-			sisfb_search_specialtiming(this_opt + 14);
-		} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
-			int temp = 4;
-			temp = simple_strtoul(this_opt + 7, NULL, 0);
-			if((temp >= 0) && (temp <= 3)) {
-			   sisfb_lvdshl = temp;
-			}
-		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
-			sisfb_search_mode(this_opt, true);
-#if !defined(__i386__) && !defined(__x86_64__)
-		} else if(!strnicmp(this_opt, "resetcard", 9)) {
-			sisfb_resetcard = 1;
-	        } else if(!strnicmp(this_opt, "videoram:", 9)) {
-			sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
-#endif
-		} else {
-			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
-		}
-
-	}
-
-	return 0;
-}
-#endif
-
-static int sisfb_check_rom(void __iomem *rom_base,
-			   struct sis_video_info *ivideo)
-{
-	void __iomem *rom;
-	int romptr;
-
-	if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
-		return 0;
-
-	romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
-	if(romptr > (0x10000 - 8))
-		return 0;
-
-	rom = rom_base + romptr;
-
-	if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
-	   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
-		return 0;
-
-	if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
-		return 0;
-
-	if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
-		return 0;
-
-	return 1;
-}
-
-static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
-{
-	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-	void __iomem *rom_base;
-	unsigned char *myrombase = NULL;
-	size_t romsize;
-
-	/* First, try the official pci ROM functions (except
-	 * on integrated chipsets which have no ROM).
-	 */
-
-	if(!ivideo->nbridge) {
-
-		if((rom_base = pci_map_rom(pdev, &romsize))) {
-
-			if(sisfb_check_rom(rom_base, ivideo)) {
-
-				if((myrombase = vmalloc(65536))) {
-					memcpy_fromio(myrombase, rom_base,
-							(romsize > 65536) ? 65536 : romsize);
-				}
-			}
-			pci_unmap_rom(pdev, rom_base);
-		}
-	}
-
-	if(myrombase) return myrombase;
-
-	/* Otherwise do it the conventional way. */
-
-#if defined(__i386__) || defined(__x86_64__)
-	{
-		u32 temp;
-
-		for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
-
-			rom_base = ioremap(temp, 65536);
-			if (!rom_base)
-				continue;
-
-			if (!sisfb_check_rom(rom_base, ivideo)) {
-				iounmap(rom_base);
-				continue;
-			}
-
-			if ((myrombase = vmalloc(65536)))
-				memcpy_fromio(myrombase, rom_base, 65536);
-
-			iounmap(rom_base);
-			break;
-
-		}
-
-	}
-#endif
-
-	return myrombase;
-}
-
-static void sisfb_post_map_vram(struct sis_video_info *ivideo,
-				unsigned int *mapsize, unsigned int min)
-{
-	if (*mapsize < (min << 20))
-		return;
-
-	ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
-
-	if(!ivideo->video_vbase) {
-		printk(KERN_ERR
-			"sisfb: Unable to map maximum video RAM for size detection\n");
-		(*mapsize) >>= 1;
-		while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
-			(*mapsize) >>= 1;
-			if((*mapsize) < (min << 20))
-				break;
-		}
-		if(ivideo->video_vbase) {
-			printk(KERN_ERR
-				"sisfb: Video RAM size detection limited to %dMB\n",
-				(int)((*mapsize) >> 20));
-		}
-	}
-}
-
-#ifdef CONFIG_FB_SIS_300
-static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
-{
-	void __iomem *FBAddress = ivideo->video_vbase;
-	unsigned short temp;
-	unsigned char reg;
-	int i, j;
-
-	SiS_SetRegAND(SISSR, 0x15, 0xFB);
-	SiS_SetRegOR(SISSR, 0x15, 0x04);
-	SiS_SetReg(SISSR, 0x13, 0x00);
-	SiS_SetReg(SISSR, 0x14, 0xBF);
-
-	for(i = 0; i < 2; i++) {
-		temp = 0x1234;
-		for(j = 0; j < 4; j++) {
-			writew(temp, FBAddress);
-			if(readw(FBAddress) == temp)
-				break;
-			SiS_SetRegOR(SISSR, 0x3c, 0x01);
-			reg = SiS_GetReg(SISSR, 0x05);
-			reg = SiS_GetReg(SISSR, 0x05);
-			SiS_SetRegAND(SISSR, 0x3c, 0xfe);
-			reg = SiS_GetReg(SISSR, 0x05);
-			reg = SiS_GetReg(SISSR, 0x05);
-			temp++;
-		}
-	}
-
-	writel(0x01234567L, FBAddress);
-	writel(0x456789ABL, (FBAddress + 4));
-	writel(0x89ABCDEFL, (FBAddress + 8));
-	writel(0xCDEF0123L, (FBAddress + 12));
-
-	reg = SiS_GetReg(SISSR, 0x3b);
-	if(reg & 0x01) {
-		if(readl((FBAddress + 12)) == 0xCDEF0123L)
-			return 4;	/* Channel A 128bit */
-	}
-
-	if(readl((FBAddress + 4)) == 0x456789ABL)
-		return 2;		/* Channel B 64bit */
-
-	return 1;			/* 32bit */
-}
-
-static const unsigned short SiS_DRAMType[17][5] = {
-	{0x0C,0x0A,0x02,0x40,0x39},
-	{0x0D,0x0A,0x01,0x40,0x48},
-	{0x0C,0x09,0x02,0x20,0x35},
-	{0x0D,0x09,0x01,0x20,0x44},
-	{0x0C,0x08,0x02,0x10,0x31},
-	{0x0D,0x08,0x01,0x10,0x40},
-	{0x0C,0x0A,0x01,0x20,0x34},
-	{0x0C,0x09,0x01,0x08,0x32},
-	{0x0B,0x08,0x02,0x08,0x21},
-	{0x0C,0x08,0x01,0x08,0x30},
-	{0x0A,0x08,0x02,0x04,0x11},
-	{0x0B,0x0A,0x01,0x10,0x28},
-	{0x09,0x08,0x02,0x02,0x01},
-	{0x0B,0x09,0x01,0x08,0x24},
-	{0x0B,0x08,0x01,0x04,0x20},
-	{0x0A,0x08,0x01,0x02,0x10},
-	{0x09,0x08,0x01,0x01,0x00}
-};
-
-static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
-				 int buswidth, int PseudoRankCapacity,
-				 int PseudoAdrPinCount, unsigned int mapsize)
-{
-	void __iomem *FBAddr = ivideo->video_vbase;
-	unsigned short sr14;
-	unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
-	unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
-
-	 for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
-
-		RankCapacity = buswidth * SiS_DRAMType[k][3];
-
-		if(RankCapacity != PseudoRankCapacity)
-			continue;
-
-		if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
-			continue;
-
-		BankNumHigh = RankCapacity * 16 * iteration - 1;
-		if(iteration == 3) {             /* Rank No */
-			BankNumMid  = RankCapacity * 16 - 1;
-		} else {
-			BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
-		}
-
-		PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
-		PhysicalAdrHigh = BankNumHigh;
-		PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
-		PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
-
-		SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
-		SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
-		sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
-		if(buswidth == 4)      sr14 |= 0x80;
-		else if(buswidth == 2) sr14 |= 0x40;
-		SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
-		SiS_SetReg(SISSR, 0x14, sr14);
-
-		BankNumHigh <<= 16;
-		BankNumMid <<= 16;
-
-		if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
-		   (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
-		   (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
-		   (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
-			continue;
-
-		/* Write data */
-		writew(((unsigned short)PhysicalAdrHigh),
-				(FBAddr + BankNumHigh + PhysicalAdrHigh));
-		writew(((unsigned short)BankNumMid),
-				(FBAddr + BankNumMid  + PhysicalAdrHigh));
-		writew(((unsigned short)PhysicalAdrHalfPage),
-				(FBAddr + BankNumHigh + PhysicalAdrHalfPage));
-		writew(((unsigned short)PhysicalAdrOtherPage),
-				(FBAddr + BankNumHigh + PhysicalAdrOtherPage));
-
-		/* Read data */
-		if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
-			return 1;
-	}
-
-	return 0;
-}
-
-static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
-{
-	struct	sis_video_info *ivideo = pci_get_drvdata(pdev);
-	int	i, j, buswidth;
-	int	PseudoRankCapacity, PseudoAdrPinCount;
-
-	buswidth = sisfb_post_300_buswidth(ivideo);
-
-	for(i = 6; i >= 0; i--) {
-		PseudoRankCapacity = 1 << i;
-		for(j = 4; j >= 1; j--) {
-			PseudoAdrPinCount = 15 - j;
-			if((PseudoRankCapacity * j) <= 64) {
-				if(sisfb_post_300_rwtest(ivideo,
-						j,
-						buswidth,
-						PseudoRankCapacity,
-						PseudoAdrPinCount,
-						mapsize))
-					return;
-			}
-		}
-	}
-}
-
-static void sisfb_post_sis300(struct pci_dev *pdev)
-{
-	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-	unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
-	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
-	u16 index, rindex, memtype = 0;
-	unsigned int mapsize;
-
-	if(!ivideo->SiS_Pr.UseROM)
-		bios = NULL;
-
-	SiS_SetReg(SISSR, 0x05, 0x86);
-
-	if(bios) {
-		if(bios[0x52] & 0x80) {
-			memtype = bios[0x52];
-		} else {
-			memtype = SiS_GetReg(SISSR, 0x3a);
-		}
-		memtype &= 0x07;
-	}
-
-	v3 = 0x80; v6 = 0x80;
-	if(ivideo->revision_id <= 0x13) {
-		v1 = 0x44; v2 = 0x42;
-		v4 = 0x44; v5 = 0x42;
-	} else {
-		v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
-		v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
-		if(bios) {
-			index = memtype * 5;
-			rindex = index + 0x54;
-			v1 = bios[rindex++];
-			v2 = bios[rindex++];
-			v3 = bios[rindex++];
-			rindex = index + 0x7c;
-			v4 = bios[rindex++];
-			v5 = bios[rindex++];
-			v6 = bios[rindex++];
-		}
-	}
-	SiS_SetReg(SISSR, 0x28, v1);
-	SiS_SetReg(SISSR, 0x29, v2);
-	SiS_SetReg(SISSR, 0x2a, v3);
-	SiS_SetReg(SISSR, 0x2e, v4);
-	SiS_SetReg(SISSR, 0x2f, v5);
-	SiS_SetReg(SISSR, 0x30, v6);
-
-	v1 = 0x10;
-	if(bios)
-		v1 = bios[0xa4];
-	SiS_SetReg(SISSR, 0x07, v1);       /* DAC speed */
-
-	SiS_SetReg(SISSR, 0x11, 0x0f);     /* DDC, power save */
-
-	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
-	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
-	if(bios) {
-		memtype += 0xa5;
-		v1 = bios[memtype];
-		v2 = bios[memtype + 8];
-		v3 = bios[memtype + 16];
-		v4 = bios[memtype + 24];
-		v5 = bios[memtype + 32];
-		v6 = bios[memtype + 40];
-		v7 = bios[memtype + 48];
-		v8 = bios[memtype + 56];
-	}
-	if(ivideo->revision_id >= 0x80)
-		v3 &= 0xfd;
-	SiS_SetReg(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
-	SiS_SetReg(SISSR, 0x16, v2);
-	SiS_SetReg(SISSR, 0x17, v3);
-	SiS_SetReg(SISSR, 0x18, v4);
-	SiS_SetReg(SISSR, 0x19, v5);
-	SiS_SetReg(SISSR, 0x1a, v6);
-	SiS_SetReg(SISSR, 0x1b, v7);
-	SiS_SetReg(SISSR, 0x1c, v8);	   /* ---- */
-	SiS_SetRegAND(SISSR, 0x15, 0xfb);
-	SiS_SetRegOR(SISSR, 0x15, 0x04);
-	if(bios) {
-		if(bios[0x53] & 0x02) {
-			SiS_SetRegOR(SISSR, 0x19, 0x20);
-		}
-	}
-	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
-	if(ivideo->revision_id >= 0x80)
-		v1 |= 0x01;
-	SiS_SetReg(SISSR, 0x1f, v1);
-	SiS_SetReg(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
-	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
-	if(bios) {
-		v1 = bios[0xe8];
-		v2 = bios[0xe9];
-		v3 = bios[0xea];
-	}
-	SiS_SetReg(SISSR, 0x23, v1);
-	SiS_SetReg(SISSR, 0x24, v2);
-	SiS_SetReg(SISSR, 0x25, v3);
-	SiS_SetReg(SISSR, 0x21, 0x84);
-	SiS_SetReg(SISSR, 0x22, 0x00);
-	SiS_SetReg(SISCR, 0x37, 0x00);
-	SiS_SetRegOR(SISPART1, 0x24, 0x01);   /* unlock crt2 */
-	SiS_SetReg(SISPART1, 0x00, 0x00);
-	v1 = 0x40; v2 = 0x11;
-	if(bios) {
-		v1 = bios[0xec];
-		v2 = bios[0xeb];
-	}
-	SiS_SetReg(SISPART1, 0x02, v1);
-
-	if(ivideo->revision_id >= 0x80)
-		v2 &= ~0x01;
-
-	reg = SiS_GetReg(SISPART4, 0x00);
-	if((reg == 1) || (reg == 2)) {
-		SiS_SetReg(SISCR, 0x37, 0x02);
-		SiS_SetReg(SISPART2, 0x00, 0x1c);
-		v4 = 0x00; v5 = 0x00; v6 = 0x10;
-		if(ivideo->SiS_Pr.UseROM) {
-			v4 = bios[0xf5];
-			v5 = bios[0xf6];
-			v6 = bios[0xf7];
-		}
-		SiS_SetReg(SISPART4, 0x0d, v4);
-		SiS_SetReg(SISPART4, 0x0e, v5);
-		SiS_SetReg(SISPART4, 0x10, v6);
-		SiS_SetReg(SISPART4, 0x0f, 0x3f);
-		reg = SiS_GetReg(SISPART4, 0x01);
-		if(reg >= 0xb0) {
-			reg = SiS_GetReg(SISPART4, 0x23);
-			reg &= 0x20;
-			reg <<= 1;
-			SiS_SetReg(SISPART4, 0x23, reg);
-		}
-	} else {
-		v2 &= ~0x10;
-	}
-	SiS_SetReg(SISSR, 0x32, v2);
-
-	SiS_SetRegAND(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
-
-	reg = SiS_GetReg(SISSR, 0x16);
-	reg &= 0xc3;
-	SiS_SetReg(SISCR, 0x35, reg);
-	SiS_SetReg(SISCR, 0x83, 0x00);
-#if !defined(__i386__) && !defined(__x86_64__)
-	if(sisfb_videoram) {
-		SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
-		reg = ((sisfb_videoram >> 10) - 1) | 0x40;
-		SiS_SetReg(SISSR, 0x14, reg);
-	} else {
-#endif
-		/* Need to map max FB size for finding out about RAM size */
-		mapsize = ivideo->video_size;
-		sisfb_post_map_vram(ivideo, &mapsize, 4);
-
-		if(ivideo->video_vbase) {
-			sisfb_post_300_ramsize(pdev, mapsize);
-			iounmap(ivideo->video_vbase);
-		} else {
-			printk(KERN_DEBUG
-				"sisfb: Failed to map memory for size detection, assuming 8MB\n");
-			SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
-			SiS_SetReg(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
-		}
-#if !defined(__i386__) && !defined(__x86_64__)
-	}
-#endif
-	if(bios) {
-		v1 = bios[0xe6];
-		v2 = bios[0xe7];
-	} else {
-		reg = SiS_GetReg(SISSR, 0x3a);
-		if((reg & 0x30) == 0x30) {
-			v1 = 0x04; /* PCI */
-			v2 = 0x92;
-		} else {
-			v1 = 0x14; /* AGP */
-			v2 = 0xb2;
-		}
-	}
-	SiS_SetReg(SISSR, 0x21, v1);
-	SiS_SetReg(SISSR, 0x22, v2);
-
-	/* Sense CRT1 */
-	sisfb_sense_crt1(ivideo);
-
-	/* Set default mode, don't clear screen */
-	ivideo->SiS_Pr.SiS_UseOEM = false;
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
-	ivideo->curFSTN = ivideo->curDSTN = 0;
-	ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
-	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
-
-	SiS_SetReg(SISSR, 0x05, 0x86);
-
-	/* Display off */
-	SiS_SetRegOR(SISSR, 0x01, 0x20);
-
-	/* Save mode number in CR34 */
-	SiS_SetReg(SISCR, 0x34, 0x2e);
-
-	/* Let everyone know what the current mode is */
-	ivideo->modeprechange = 0x2e;
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-#if 0
-static void sisfb_post_sis315330(struct pci_dev *pdev)
-{
-	/* TODO */
-}
-#endif
-
-static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
-{
-	return ivideo->chip_real_id == XGI_21;
-}
-
-static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
-{
-	unsigned int i;
-	u8 reg;
-
-	for(i = 0; i <= (delay * 10 * 36); i++) {
-		reg = SiS_GetReg(SISSR, 0x05);
-		reg++;
-	}
-}
-
-static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
-				  struct pci_dev *mypdev,
-				  unsigned short pcivendor)
-{
-	struct pci_dev *pdev = NULL;
-	unsigned short temp;
-	int ret = 0;
-
-	while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
-		temp = pdev->vendor;
-		if(temp == pcivendor) {
-			ret = 1;
-			pci_dev_put(pdev);
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
-				 unsigned int enda, unsigned int mapsize)
-{
-	unsigned int pos;
-	int i;
-
-	writel(0, ivideo->video_vbase);
-
-	for(i = starta; i <= enda; i++) {
-		pos = 1 << i;
-		if(pos < mapsize)
-			writel(pos, ivideo->video_vbase + pos);
-	}
-
-	sisfb_post_xgi_delay(ivideo, 150);
-
-	if(readl(ivideo->video_vbase) != 0)
-		return 0;
-
-	for(i = starta; i <= enda; i++) {
-		pos = 1 << i;
-		if(pos < mapsize) {
-			if(readl(ivideo->video_vbase + pos) != pos)
-				return 0;
-		} else
-			return 0;
-	}
-
-	return 1;
-}
-
-static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
-{
-	unsigned int buswidth, ranksize, channelab, mapsize;
-	int i, j, k, l, status;
-	u8 reg, sr14;
-	static const u8 dramsr13[12 * 5] = {
-		0x02, 0x0e, 0x0b, 0x80, 0x5d,
-		0x02, 0x0e, 0x0a, 0x40, 0x59,
-		0x02, 0x0d, 0x0b, 0x40, 0x4d,
-		0x02, 0x0e, 0x09, 0x20, 0x55,
-		0x02, 0x0d, 0x0a, 0x20, 0x49,
-		0x02, 0x0c, 0x0b, 0x20, 0x3d,
-		0x02, 0x0e, 0x08, 0x10, 0x51,
-		0x02, 0x0d, 0x09, 0x10, 0x45,
-		0x02, 0x0c, 0x0a, 0x10, 0x39,
-		0x02, 0x0d, 0x08, 0x08, 0x41,
-		0x02, 0x0c, 0x09, 0x08, 0x35,
-		0x02, 0x0c, 0x08, 0x04, 0x31
-	};
-	static const u8 dramsr13_4[4 * 5] = {
-		0x02, 0x0d, 0x09, 0x40, 0x45,
-		0x02, 0x0c, 0x09, 0x20, 0x35,
-		0x02, 0x0c, 0x08, 0x10, 0x31,
-		0x02, 0x0b, 0x08, 0x08, 0x21
-	};
-
-	/* Enable linear mode, disable 0xa0000 address decoding */
-	/* We disable a0000 address decoding, because
-	 * - if running on x86, if the card is disabled, it means
-	 *   that another card is in the system. We don't want
-	 *   to interphere with that primary card's textmode.
-	 * - if running on non-x86, there usually is no VGA window
-	 *   at a0000.
-	 */
-	SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
-
-	/* Need to map max FB size for finding out about RAM size */
-	mapsize = ivideo->video_size;
-	sisfb_post_map_vram(ivideo, &mapsize, 32);
-
-	if(!ivideo->video_vbase) {
-		printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
-		SiS_SetReg(SISSR, 0x13, 0x35);
-		SiS_SetReg(SISSR, 0x14, 0x41);
-		/* TODO */
-		return -ENOMEM;
-	}
-
-	/* Non-interleaving */
-	SiS_SetReg(SISSR, 0x15, 0x00);
-	/* No tiling */
-	SiS_SetReg(SISSR, 0x1c, 0x00);
-
-	if(ivideo->chip == XGI_20) {
-
-		channelab = 1;
-		reg = SiS_GetReg(SISCR, 0x97);
-		if(!(reg & 0x01)) {	/* Single 32/16 */
-			buswidth = 32;
-			SiS_SetReg(SISSR, 0x13, 0xb1);
-			SiS_SetReg(SISSR, 0x14, 0x52);
-			sisfb_post_xgi_delay(ivideo, 1);
-			sr14 = 0x02;
-			if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
-				goto bail_out;
-
-			SiS_SetReg(SISSR, 0x13, 0x31);
-			SiS_SetReg(SISSR, 0x14, 0x42);
-			sisfb_post_xgi_delay(ivideo, 1);
-			if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
-				goto bail_out;
-
-			buswidth = 16;
-			SiS_SetReg(SISSR, 0x13, 0xb1);
-			SiS_SetReg(SISSR, 0x14, 0x41);
-			sisfb_post_xgi_delay(ivideo, 1);
-			sr14 = 0x01;
-			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
-				goto bail_out;
-			else
-				SiS_SetReg(SISSR, 0x13, 0x31);
-		} else {		/* Dual 16/8 */
-			buswidth = 16;
-			SiS_SetReg(SISSR, 0x13, 0xb1);
-			SiS_SetReg(SISSR, 0x14, 0x41);
-			sisfb_post_xgi_delay(ivideo, 1);
-			sr14 = 0x01;
-			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
-				goto bail_out;
-
-			SiS_SetReg(SISSR, 0x13, 0x31);
-			SiS_SetReg(SISSR, 0x14, 0x31);
-			sisfb_post_xgi_delay(ivideo, 1);
-			if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
-				goto bail_out;
-
-			buswidth = 8;
-			SiS_SetReg(SISSR, 0x13, 0xb1);
-			SiS_SetReg(SISSR, 0x14, 0x30);
-			sisfb_post_xgi_delay(ivideo, 1);
-			sr14 = 0x00;
-			if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
-				goto bail_out;
-			else
-				SiS_SetReg(SISSR, 0x13, 0x31);
-		}
-
-	} else {	/* XGI_40 */
-
-		reg = SiS_GetReg(SISCR, 0x97);
-		if(!(reg & 0x10)) {
-			reg = SiS_GetReg(SISSR, 0x39);
-			reg >>= 1;
-		}
-
-		if(reg & 0x01) {	/* DDRII */
-			buswidth = 32;
-			if(ivideo->revision_id == 2) {
-				channelab = 2;
-				SiS_SetReg(SISSR, 0x13, 0xa1);
-				SiS_SetReg(SISSR, 0x14, 0x44);
-				sr14 = 0x04;
-				sisfb_post_xgi_delay(ivideo, 1);
-				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
-					goto bail_out;
-
-				SiS_SetReg(SISSR, 0x13, 0x21);
-				SiS_SetReg(SISSR, 0x14, 0x34);
-				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
-					goto bail_out;
-
-				channelab = 1;
-				SiS_SetReg(SISSR, 0x13, 0xa1);
-				SiS_SetReg(SISSR, 0x14, 0x40);
-				sr14 = 0x00;
-				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
-					goto bail_out;
-
-				SiS_SetReg(SISSR, 0x13, 0x21);
-				SiS_SetReg(SISSR, 0x14, 0x30);
-			} else {
-				channelab = 3;
-				SiS_SetReg(SISSR, 0x13, 0xa1);
-				SiS_SetReg(SISSR, 0x14, 0x4c);
-				sr14 = 0x0c;
-				sisfb_post_xgi_delay(ivideo, 1);
-				if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
-					goto bail_out;
-
-				channelab = 2;
-				SiS_SetReg(SISSR, 0x14, 0x48);
-				sisfb_post_xgi_delay(ivideo, 1);
-				sr14 = 0x08;
-				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
-					goto bail_out;
-
-				SiS_SetReg(SISSR, 0x13, 0x21);
-				SiS_SetReg(SISSR, 0x14, 0x3c);
-				sr14 = 0x0c;
-
-				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
-					channelab = 3;
-				} else {
-					channelab = 2;
-					SiS_SetReg(SISSR, 0x14, 0x38);
-					sr14 = 0x08;
-				}
-			}
-			sisfb_post_xgi_delay(ivideo, 1);
-
-		} else {	/* DDR */
-
-			buswidth = 64;
-			if(ivideo->revision_id == 2) {
-				channelab = 1;
-				SiS_SetReg(SISSR, 0x13, 0xa1);
-				SiS_SetReg(SISSR, 0x14, 0x52);
-				sisfb_post_xgi_delay(ivideo, 1);
-				sr14 = 0x02;
-				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
-					goto bail_out;
-
-				SiS_SetReg(SISSR, 0x13, 0x21);
-				SiS_SetReg(SISSR, 0x14, 0x42);
-			} else {
-				channelab = 2;
-				SiS_SetReg(SISSR, 0x13, 0xa1);
-				SiS_SetReg(SISSR, 0x14, 0x5a);
-				sisfb_post_xgi_delay(ivideo, 1);
-				sr14 = 0x0a;
-				if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
-					goto bail_out;
-
-				SiS_SetReg(SISSR, 0x13, 0x21);
-				SiS_SetReg(SISSR, 0x14, 0x4a);
-			}
-			sisfb_post_xgi_delay(ivideo, 1);
-
-		}
-	}
-
-bail_out:
-	SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
-	sisfb_post_xgi_delay(ivideo, 1);
-
-	j = (ivideo->chip == XGI_20) ? 5 : 9;
-	k = (ivideo->chip == XGI_20) ? 12 : 4;
-	status = -EIO;
-
-	for(i = 0; i < k; i++) {
-
-		reg = (ivideo->chip == XGI_20) ?
-				dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
-		SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
-		sisfb_post_xgi_delay(ivideo, 50);
-
-		ranksize = (ivideo->chip == XGI_20) ?
-				dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
-
-		reg = SiS_GetReg(SISSR, 0x13);
-		if(reg & 0x80) ranksize <<= 1;
-
-		if(ivideo->chip == XGI_20) {
-			if(buswidth == 16)      ranksize <<= 1;
-			else if(buswidth == 32) ranksize <<= 2;
-		} else {
-			if(buswidth == 64)      ranksize <<= 1;
-		}
-
-		reg = 0;
-		l = channelab;
-		if(l == 3) l = 4;
-		if((ranksize * l) <= 256) {
-			while((ranksize >>= 1)) reg += 0x10;
-		}
-
-		if(!reg) continue;
-
-		SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
-		sisfb_post_xgi_delay(ivideo, 1);
-
-		if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
-			status = 0;
-			break;
-		}
-	}
-
-	iounmap(ivideo->video_vbase);
-
-	return status;
-}
-
-static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
-{
-	u8 v1, v2, v3;
-	int index;
-	static const u8 cs90[8 * 3] = {
-		0x16, 0x01, 0x01,
-		0x3e, 0x03, 0x01,
-		0x7c, 0x08, 0x01,
-		0x79, 0x06, 0x01,
-		0x29, 0x01, 0x81,
-		0x5c, 0x23, 0x01,
-		0x5c, 0x23, 0x01,
-		0x5c, 0x23, 0x01
-	};
-	static const u8 csb8[8 * 3] = {
-		0x5c, 0x23, 0x01,
-		0x29, 0x01, 0x01,
-		0x7c, 0x08, 0x01,
-		0x79, 0x06, 0x01,
-		0x29, 0x01, 0x81,
-		0x5c, 0x23, 0x01,
-		0x5c, 0x23, 0x01,
-		0x5c, 0x23, 0x01
-	};
-
-	regb = 0;  /* ! */
-
-	index = regb * 3;
-	v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
-	if(ivideo->haveXGIROM) {
-		v1 = ivideo->bios_abase[0x90 + index];
-		v2 = ivideo->bios_abase[0x90 + index + 1];
-		v3 = ivideo->bios_abase[0x90 + index + 2];
-	}
-	SiS_SetReg(SISSR, 0x28, v1);
-	SiS_SetReg(SISSR, 0x29, v2);
-	SiS_SetReg(SISSR, 0x2a, v3);
-	sisfb_post_xgi_delay(ivideo, 0x43);
-	sisfb_post_xgi_delay(ivideo, 0x43);
-	sisfb_post_xgi_delay(ivideo, 0x43);
-	index = regb * 3;
-	v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
-	if(ivideo->haveXGIROM) {
-		v1 = ivideo->bios_abase[0xb8 + index];
-		v2 = ivideo->bios_abase[0xb8 + index + 1];
-		v3 = ivideo->bios_abase[0xb8 + index + 2];
-	}
-	SiS_SetReg(SISSR, 0x2e, v1);
-	SiS_SetReg(SISSR, 0x2f, v2);
-	SiS_SetReg(SISSR, 0x30, v3);
-	sisfb_post_xgi_delay(ivideo, 0x43);
-	sisfb_post_xgi_delay(ivideo, 0x43);
-	sisfb_post_xgi_delay(ivideo, 0x43);
-}
-
-static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
-					    u8 regb)
-{
-	unsigned char *bios = ivideo->bios_abase;
-	u8 v1;
-
-	SiS_SetReg(SISSR, 0x28, 0x64);
-	SiS_SetReg(SISSR, 0x29, 0x63);
-	sisfb_post_xgi_delay(ivideo, 15);
-	SiS_SetReg(SISSR, 0x18, 0x00);
-	SiS_SetReg(SISSR, 0x19, 0x20);
-	SiS_SetReg(SISSR, 0x16, 0x00);
-	SiS_SetReg(SISSR, 0x16, 0x80);
-	SiS_SetReg(SISSR, 0x18, 0xc5);
-	SiS_SetReg(SISSR, 0x19, 0x23);
-	SiS_SetReg(SISSR, 0x16, 0x00);
-	SiS_SetReg(SISSR, 0x16, 0x80);
-	sisfb_post_xgi_delay(ivideo, 1);
-	SiS_SetReg(SISCR, 0x97, 0x11);
-	sisfb_post_xgi_setclocks(ivideo, regb);
-	sisfb_post_xgi_delay(ivideo, 0x46);
-	SiS_SetReg(SISSR, 0x18, 0xc5);
-	SiS_SetReg(SISSR, 0x19, 0x23);
-	SiS_SetReg(SISSR, 0x16, 0x00);
-	SiS_SetReg(SISSR, 0x16, 0x80);
-	sisfb_post_xgi_delay(ivideo, 1);
-	SiS_SetReg(SISSR, 0x1b, 0x04);
-	sisfb_post_xgi_delay(ivideo, 1);
-	SiS_SetReg(SISSR, 0x1b, 0x00);
-	sisfb_post_xgi_delay(ivideo, 1);
-	v1 = 0x31;
-	if (ivideo->haveXGIROM) {
-		v1 = bios[0xf0];
-	}
-	SiS_SetReg(SISSR, 0x18, v1);
-	SiS_SetReg(SISSR, 0x19, 0x06);
-	SiS_SetReg(SISSR, 0x16, 0x04);
-	SiS_SetReg(SISSR, 0x16, 0x84);
-	sisfb_post_xgi_delay(ivideo, 1);
-}
-
-static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
-{
-	sisfb_post_xgi_setclocks(ivideo, 1);
-
-	SiS_SetReg(SISCR, 0x97, 0x11);
-	sisfb_post_xgi_delay(ivideo, 0x46);
-
-	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS2 */
-	SiS_SetReg(SISSR, 0x19, 0x80);
-	SiS_SetReg(SISSR, 0x16, 0x05);
-	SiS_SetReg(SISSR, 0x16, 0x85);
-
-	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS3 */
-	SiS_SetReg(SISSR, 0x19, 0xc0);
-	SiS_SetReg(SISSR, 0x16, 0x05);
-	SiS_SetReg(SISSR, 0x16, 0x85);
-
-	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS1 */
-	SiS_SetReg(SISSR, 0x19, 0x40);
-	SiS_SetReg(SISSR, 0x16, 0x05);
-	SiS_SetReg(SISSR, 0x16, 0x85);
-
-	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
-	SiS_SetReg(SISSR, 0x19, 0x02);
-	SiS_SetReg(SISSR, 0x16, 0x05);
-	SiS_SetReg(SISSR, 0x16, 0x85);
-	sisfb_post_xgi_delay(ivideo, 1);
-
-	SiS_SetReg(SISSR, 0x1b, 0x04);
-	sisfb_post_xgi_delay(ivideo, 1);
-
-	SiS_SetReg(SISSR, 0x1b, 0x00);
-	sisfb_post_xgi_delay(ivideo, 1);
-
-	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
-	SiS_SetReg(SISSR, 0x19, 0x00);
-	SiS_SetReg(SISSR, 0x16, 0x05);
-	SiS_SetReg(SISSR, 0x16, 0x85);
-	sisfb_post_xgi_delay(ivideo, 1);
-}
-
-static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
-{
-	unsigned char *bios = ivideo->bios_abase;
-	static const u8 cs158[8] = {
-		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs160[8] = {
-		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs168[8] = {
-		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	u8 reg;
-	u8 v1;
-	u8 v2;
-	u8 v3;
-
-	SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
-	SiS_SetReg(SISCR, 0x82, 0x77);
-	SiS_SetReg(SISCR, 0x86, 0x00);
-	reg = SiS_GetReg(SISCR, 0x86);
-	SiS_SetReg(SISCR, 0x86, 0x88);
-	reg = SiS_GetReg(SISCR, 0x86);
-	v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
-	if (ivideo->haveXGIROM) {
-		v1 = bios[regb + 0x168];
-		v2 = bios[regb + 0x160];
-		v3 = bios[regb + 0x158];
-	}
-	SiS_SetReg(SISCR, 0x86, v1);
-	SiS_SetReg(SISCR, 0x82, 0x77);
-	SiS_SetReg(SISCR, 0x85, 0x00);
-	reg = SiS_GetReg(SISCR, 0x85);
-	SiS_SetReg(SISCR, 0x85, 0x88);
-	reg = SiS_GetReg(SISCR, 0x85);
-	SiS_SetReg(SISCR, 0x85, v2);
-	SiS_SetReg(SISCR, 0x82, v3);
-	SiS_SetReg(SISCR, 0x98, 0x01);
-	SiS_SetReg(SISCR, 0x9a, 0x02);
-	if (sisfb_xgi_is21(ivideo))
-		sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
-	else
-		sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
-}
-
-static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
-{
-	unsigned char *bios = ivideo->bios_abase;
-	u8 ramtype;
-	u8 reg;
-	u8 v1;
-
-	ramtype = 0x00; v1 = 0x10;
-	if (ivideo->haveXGIROM) {
-		ramtype = bios[0x62];
-		v1 = bios[0x1d2];
-	}
-	if (!(ramtype & 0x80)) {
-		if (sisfb_xgi_is21(ivideo)) {
-			SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
-			SiS_SetRegOR(SISCR, 0x4a, 0x80);  /* GPIOH EN */
-			reg = SiS_GetReg(SISCR, 0x48);
-			SiS_SetRegOR(SISCR, 0xb4, 0x02);
-			ramtype = reg & 0x01;		  /* GPIOH */
-		} else if (ivideo->chip == XGI_20) {
-			SiS_SetReg(SISCR, 0x97, v1);
-			reg = SiS_GetReg(SISCR, 0x97);
-			if (reg & 0x10) {
-				ramtype = (reg & 0x01) << 1;
-			}
-		} else {
-			reg = SiS_GetReg(SISSR, 0x39);
-			ramtype = reg & 0x02;
-			if (!(ramtype)) {
-				reg = SiS_GetReg(SISSR, 0x3a);
-				ramtype = (reg >> 1) & 0x01;
-			}
-		}
-	}
-	ramtype &= 0x07;
-
-	return ramtype;
-}
-
-static int sisfb_post_xgi(struct pci_dev *pdev)
-{
-	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-	unsigned char *bios = ivideo->bios_abase;
-	struct pci_dev *mypdev = NULL;
-	const u8 *ptr, *ptr2;
-	u8 v1, v2, v3, v4, v5, reg, ramtype;
-	u32 rega, regb, regd;
-	int i, j, k, index;
-	static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
-	static const u8 cs76[2] = { 0xa3, 0xfb };
-	static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
-	static const u8 cs158[8] = {
-		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs160[8] = {
-		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs168[8] = {
-		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs128[3 * 8] = {
-		0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs148[2 * 8] = {
-		0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs31a[8 * 4] = {
-		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs33a[8 * 4] = {
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs45a[8 * 2] = {
-		0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs170[7 * 8] = {
-		0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs1a8[3 * 8] = {
-		0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	static const u8 cs100[2 * 8] = {
-		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-
-	/* VGA enable */
-	reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
-	SiS_SetRegByte(SISVGAENABLE, reg);
-
-	/* Misc */
-	reg = SiS_GetRegByte(SISMISCR) | 0x01;
-	SiS_SetRegByte(SISMISCW, reg);
-
-	/* Unlock SR */
-	SiS_SetReg(SISSR, 0x05, 0x86);
-	reg = SiS_GetReg(SISSR, 0x05);
-	if(reg != 0xa1)
-		return 0;
-
-	/* Clear some regs */
-	for(i = 0; i < 0x22; i++) {
-		if(0x06 + i == 0x20) continue;
-		SiS_SetReg(SISSR, 0x06 + i, 0x00);
-	}
-	for(i = 0; i < 0x0b; i++) {
-		SiS_SetReg(SISSR, 0x31 + i, 0x00);
-	}
-	for(i = 0; i < 0x10; i++) {
-		SiS_SetReg(SISCR, 0x30 + i, 0x00);
-	}
-
-	ptr = cs78;
-	if(ivideo->haveXGIROM) {
-		ptr = (const u8 *)&bios[0x78];
-	}
-	for(i = 0; i < 3; i++) {
-		SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
-	}
-
-	ptr = cs76;
-	if(ivideo->haveXGIROM) {
-		ptr = (const u8 *)&bios[0x76];
-	}
-	for(i = 0; i < 2; i++) {
-		SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
-	}
-
-	v1 = 0x18; v2 = 0x00;
-	if(ivideo->haveXGIROM) {
-		v1 = bios[0x74];
-		v2 = bios[0x75];
-	}
-	SiS_SetReg(SISSR, 0x07, v1);
-	SiS_SetReg(SISSR, 0x11, 0x0f);
-	SiS_SetReg(SISSR, 0x1f, v2);
-	/* PCI linear mode, RelIO enabled, A0000 decoding disabled */
-	SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
-	SiS_SetReg(SISSR, 0x27, 0x74);
-
-	ptr = cs7b;
-	if(ivideo->haveXGIROM) {
-		ptr = (const u8 *)&bios[0x7b];
-	}
-	for(i = 0; i < 3; i++) {
-		SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
-	}
-
-	if(ivideo->chip == XGI_40) {
-		if(ivideo->revision_id == 2) {
-			SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
-		}
-		SiS_SetReg(SISCR, 0x7d, 0xfe);
-		SiS_SetReg(SISCR, 0x7e, 0x0f);
-	}
-	if(ivideo->revision_id == 0) {	/* 40 *and* 20? */
-		SiS_SetRegAND(SISCR, 0x58, 0xd7);
-		reg = SiS_GetReg(SISCR, 0xcb);
-		if(reg & 0x20) {
-			SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
-		}
-	}
-
-	reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
-	SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
-
-	if(ivideo->chip == XGI_20) {
-		SiS_SetReg(SISSR, 0x36, 0x70);
-	} else {
-		SiS_SetReg(SISVID, 0x00, 0x86);
-		SiS_SetReg(SISVID, 0x32, 0x00);
-		SiS_SetReg(SISVID, 0x30, 0x00);
-		SiS_SetReg(SISVID, 0x32, 0x01);
-		SiS_SetReg(SISVID, 0x30, 0x00);
-		SiS_SetRegAND(SISVID, 0x2f, 0xdf);
-		SiS_SetRegAND(SISCAP, 0x00, 0x3f);
-
-		SiS_SetReg(SISPART1, 0x2f, 0x01);
-		SiS_SetReg(SISPART1, 0x00, 0x00);
-		SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
-		SiS_SetReg(SISPART1, 0x2e, 0x08);
-		SiS_SetRegAND(SISPART1, 0x35, 0x7f);
-		SiS_SetRegAND(SISPART1, 0x50, 0xfe);
-
-		reg = SiS_GetReg(SISPART4, 0x00);
-		if(reg == 1 || reg == 2) {
-			SiS_SetReg(SISPART2, 0x00, 0x1c);
-			SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
-			SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
-			SiS_SetReg(SISPART4, 0x10, bios[0x81]);
-			SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
-
-			reg = SiS_GetReg(SISPART4, 0x01);
-			if((reg & 0xf0) >= 0xb0) {
-				reg = SiS_GetReg(SISPART4, 0x23);
-				if(reg & 0x20) reg |= 0x40;
-				SiS_SetReg(SISPART4, 0x23, reg);
-				reg = (reg & 0x20) ? 0x02 : 0x00;
-				SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
-			}
-		}
-
-		v1 = bios[0x77];
-
-		reg = SiS_GetReg(SISSR, 0x3b);
-		if(reg & 0x02) {
-			reg = SiS_GetReg(SISSR, 0x3a);
-			v2 = (reg & 0x30) >> 3;
-			if(!(v2 & 0x04)) v2 ^= 0x02;
-			reg = SiS_GetReg(SISSR, 0x39);
-			if(reg & 0x80) v2 |= 0x80;
-			v2 |= 0x01;
-
-			if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
-				pci_dev_put(mypdev);
-				if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
-					v2 &= 0xf9;
-				v2 |= 0x08;
-				v1 &= 0xfe;
-			} else {
-				mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
-				if(!mypdev)
-					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
-				if(!mypdev)
-					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
-				if(mypdev) {
-					pci_read_config_dword(mypdev, 0x94, &regd);
-					regd &= 0xfffffeff;
-					pci_write_config_dword(mypdev, 0x94, regd);
-					v1 &= 0xfe;
-					pci_dev_put(mypdev);
-				} else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
-					v1 &= 0xfe;
-				} else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
-					  sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
-					  sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
-					  sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
-					if((v2 & 0x06) == 4)
-						v2 ^= 0x06;
-					v2 |= 0x08;
-				}
-			}
-			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
-		}
-		SiS_SetReg(SISSR, 0x22, v1);
-
-		if(ivideo->revision_id == 2) {
-			v1 = SiS_GetReg(SISSR, 0x3b);
-			v2 = SiS_GetReg(SISSR, 0x3a);
-			regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
-			if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
-				SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
-
-			if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
-				/* TODO: set CR5f &0xf1 | 0x01 for version 6570
-				 * of nforce 2 ROM
-				 */
-				if(0)
-					SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
-				pci_dev_put(mypdev);
-			}
-		}
-
-		v1 = 0x30;
-		reg = SiS_GetReg(SISSR, 0x3b);
-		v2 = SiS_GetReg(SISCR, 0x5f);
-		if((!(reg & 0x02)) && (v2 & 0x0e))
-			v1 |= 0x08;
-		SiS_SetReg(SISSR, 0x27, v1);
-
-		if(bios[0x64] & 0x01) {
-			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
-		}
-
-		v1 = bios[0x4f7];
-		pci_read_config_dword(pdev, 0x50, &regd);
-		regd = (regd >> 20) & 0x0f;
-		if(regd == 1) {
-			v1 &= 0xfc;
-			SiS_SetRegOR(SISCR, 0x5f, 0x08);
-		}
-		SiS_SetReg(SISCR, 0x48, v1);
-
-		SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
-		SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
-		SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
-		SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
-		SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
-		SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
-		SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
-		SiS_SetReg(SISCR, 0x74, 0xd0);
-		SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
-		SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
-		SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
-		v1 = bios[0x501];
-		if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
-			v1 = 0xf0;
-			pci_dev_put(mypdev);
-		}
-		SiS_SetReg(SISCR, 0x77, v1);
-	}
-
-	/* RAM type:
-	 *
-	 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
-	 *
-	 * The code seems to written so that regb should equal ramtype,
-	 * however, so far it has been hardcoded to 0. Enable other values only
-	 * on XGI Z9, as it passes the POST, and add a warning for others.
-	 */
-	ramtype = sisfb_post_xgi_ramtype(ivideo);
-	if (!sisfb_xgi_is21(ivideo) && ramtype) {
-		dev_warn(&pdev->dev,
-			 "RAM type something else than expected: %d\n",
-			 ramtype);
-		regb = 0;
-	} else {
-		regb = ramtype;
-	}
-
-	v1 = 0xff;
-	if(ivideo->haveXGIROM) {
-		v1 = bios[0x140 + regb];
-	}
-	SiS_SetReg(SISCR, 0x6d, v1);
-
-	ptr = cs128;
-	if(ivideo->haveXGIROM) {
-		ptr = (const u8 *)&bios[0x128];
-	}
-	for(i = 0, j = 0; i < 3; i++, j += 8) {
-		SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
-	}
-
-	ptr  = cs31a;
-	ptr2 = cs33a;
-	if(ivideo->haveXGIROM) {
-		index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
-		ptr  = (const u8 *)&bios[index];
-		ptr2 = (const u8 *)&bios[index + 0x20];
-	}
-	for(i = 0; i < 2; i++) {
-		if(i == 0) {
-			regd = le32_to_cpu(((u32 *)ptr)[regb]);
-			rega = 0x6b;
-		} else {
-			regd = le32_to_cpu(((u32 *)ptr2)[regb]);
-			rega = 0x6e;
-		}
-		reg = 0x00;
-		for(j = 0; j < 16; j++) {
-			reg &= 0xf3;
-			if(regd & 0x01) reg |= 0x04;
-			if(regd & 0x02) reg |= 0x08;
-			regd >>= 2;
-			SiS_SetReg(SISCR, rega, reg);
-			reg = SiS_GetReg(SISCR, rega);
-			reg = SiS_GetReg(SISCR, rega);
-			reg += 0x10;
-		}
-	}
-
-	SiS_SetRegAND(SISCR, 0x6e, 0xfc);
-
-	ptr  = NULL;
-	if(ivideo->haveXGIROM) {
-		index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
-		ptr  = (const u8 *)&bios[index];
-	}
-	for(i = 0; i < 4; i++) {
-		SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
-		reg = 0x00;
-		for(j = 0; j < 2; j++) {
-			regd = 0;
-			if(ptr) {
-				regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
-				ptr += 4;
-			}
-			/* reg = 0x00; */
-			for(k = 0; k < 16; k++) {
-				reg &= 0xfc;
-				if(regd & 0x01) reg |= 0x01;
-				if(regd & 0x02) reg |= 0x02;
-				regd >>= 2;
-				SiS_SetReg(SISCR, 0x6f, reg);
-				reg = SiS_GetReg(SISCR, 0x6f);
-				reg = SiS_GetReg(SISCR, 0x6f);
-				reg += 0x08;
-			}
-		}
-	}
-
-	ptr  = cs148;
-	if(ivideo->haveXGIROM) {
-		ptr  = (const u8 *)&bios[0x148];
-	}
-	for(i = 0, j = 0; i < 2; i++, j += 8) {
-		SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
-	}
-
-	SiS_SetRegAND(SISCR, 0x89, 0x8f);
-
-	ptr  = cs45a;
-	if(ivideo->haveXGIROM) {
-		index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
-		ptr  = (const u8 *)&bios[index];
-	}
-	regd = le16_to_cpu(((const u16 *)ptr)[regb]);
-	reg = 0x80;
-	for(i = 0; i < 5; i++) {
-		reg &= 0xfc;
-		if(regd & 0x01) reg |= 0x01;
-		if(regd & 0x02) reg |= 0x02;
-		regd >>= 2;
-		SiS_SetReg(SISCR, 0x89, reg);
-		reg = SiS_GetReg(SISCR, 0x89);
-		reg = SiS_GetReg(SISCR, 0x89);
-		reg += 0x10;
-	}
-
-	v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
-	if(ivideo->haveXGIROM) {
-		v1 = bios[0x118 + regb];
-		v2 = bios[0xf8 + regb];
-		v3 = bios[0x120 + regb];
-		v4 = bios[0x1ca];
-	}
-	SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
-	SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
-	SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
-	SiS_SetReg(SISCR, 0x41, v2);
-
-	ptr  = cs170;
-	if(ivideo->haveXGIROM) {
-		ptr  = (const u8 *)&bios[0x170];
-	}
-	for(i = 0, j = 0; i < 7; i++, j += 8) {
-		SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
-	}
-
-	SiS_SetReg(SISCR, 0x59, v3);
-
-	ptr  = cs1a8;
-	if(ivideo->haveXGIROM) {
-		ptr  = (const u8 *)&bios[0x1a8];
-	}
-	for(i = 0, j = 0; i < 3; i++, j += 8) {
-		SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
-	}
-
-	ptr  = cs100;
-	if(ivideo->haveXGIROM) {
-		ptr  = (const u8 *)&bios[0x100];
-	}
-	for(i = 0, j = 0; i < 2; i++, j += 8) {
-		SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
-	}
-
-	SiS_SetReg(SISCR, 0xcf, v4);
-
-	SiS_SetReg(SISCR, 0x83, 0x09);
-	SiS_SetReg(SISCR, 0x87, 0x00);
-
-	if(ivideo->chip == XGI_40) {
-		if( (ivideo->revision_id == 1) ||
-		    (ivideo->revision_id == 2) ) {
-			SiS_SetReg(SISCR, 0x8c, 0x87);
-		}
-	}
-
-	if (regb == 1)
-		SiS_SetReg(SISSR, 0x17, 0x80);		/* DDR2 */
-	else
-		SiS_SetReg(SISSR, 0x17, 0x00);		/* DDR1 */
-	SiS_SetReg(SISSR, 0x1a, 0x87);
-
-	if(ivideo->chip == XGI_20) {
-		SiS_SetReg(SISSR, 0x15, 0x00);
-		SiS_SetReg(SISSR, 0x1c, 0x00);
-	}
-
-	switch(ramtype) {
-	case 0:
-		sisfb_post_xgi_setclocks(ivideo, regb);
-		if((ivideo->chip == XGI_20) ||
-		   (ivideo->revision_id == 1)   ||
-		   (ivideo->revision_id == 2)) {
-			v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
-			if(ivideo->haveXGIROM) {
-				v1 = bios[regb + 0x158];
-				v2 = bios[regb + 0x160];
-				v3 = bios[regb + 0x168];
-			}
-			SiS_SetReg(SISCR, 0x82, v1);
-			SiS_SetReg(SISCR, 0x85, v2);
-			SiS_SetReg(SISCR, 0x86, v3);
-		} else {
-			SiS_SetReg(SISCR, 0x82, 0x88);
-			SiS_SetReg(SISCR, 0x86, 0x00);
-			reg = SiS_GetReg(SISCR, 0x86);
-			SiS_SetReg(SISCR, 0x86, 0x88);
-			reg = SiS_GetReg(SISCR, 0x86);
-			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
-			SiS_SetReg(SISCR, 0x82, 0x77);
-			SiS_SetReg(SISCR, 0x85, 0x00);
-			reg = SiS_GetReg(SISCR, 0x85);
-			SiS_SetReg(SISCR, 0x85, 0x88);
-			reg = SiS_GetReg(SISCR, 0x85);
-			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
-			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
-		}
-		if(ivideo->chip == XGI_40) {
-			SiS_SetReg(SISCR, 0x97, 0x00);
-		}
-		SiS_SetReg(SISCR, 0x98, 0x01);
-		SiS_SetReg(SISCR, 0x9a, 0x02);
-
-		SiS_SetReg(SISSR, 0x18, 0x01);
-		if((ivideo->chip == XGI_20) ||
-		   (ivideo->revision_id == 2)) {
-			SiS_SetReg(SISSR, 0x19, 0x40);
-		} else {
-			SiS_SetReg(SISSR, 0x19, 0x20);
-		}
-		SiS_SetReg(SISSR, 0x16, 0x00);
-		SiS_SetReg(SISSR, 0x16, 0x80);
-		if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
-			sisfb_post_xgi_delay(ivideo, 0x43);
-			sisfb_post_xgi_delay(ivideo, 0x43);
-			sisfb_post_xgi_delay(ivideo, 0x43);
-			SiS_SetReg(SISSR, 0x18, 0x00);
-			if((ivideo->chip == XGI_20) ||
-			   (ivideo->revision_id == 2)) {
-				SiS_SetReg(SISSR, 0x19, 0x40);
-			} else {
-				SiS_SetReg(SISSR, 0x19, 0x20);
-			}
-		} else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
-			/* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
-		}
-		SiS_SetReg(SISSR, 0x16, 0x00);
-		SiS_SetReg(SISSR, 0x16, 0x80);
-		sisfb_post_xgi_delay(ivideo, 4);
-		v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
-		if(ivideo->haveXGIROM) {
-			v1 = bios[0xf0];
-			index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
-			v2 = bios[index];
-			v3 = bios[index + 1];
-			v4 = bios[index + 2];
-			v5 = bios[index + 3];
-		}
-		SiS_SetReg(SISSR, 0x18, v1);
-		SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
-		SiS_SetReg(SISSR, 0x16, v2);
-		SiS_SetReg(SISSR, 0x16, v3);
-		sisfb_post_xgi_delay(ivideo, 0x43);
-		SiS_SetReg(SISSR, 0x1b, 0x03);
-		sisfb_post_xgi_delay(ivideo, 0x22);
-		SiS_SetReg(SISSR, 0x18, v1);
-		SiS_SetReg(SISSR, 0x19, 0x00);
-		SiS_SetReg(SISSR, 0x16, v4);
-		SiS_SetReg(SISSR, 0x16, v5);
-		SiS_SetReg(SISSR, 0x1b, 0x00);
-		break;
-	case 1:
-		sisfb_post_xgi_ddr2(ivideo, regb);
-		break;
-	default:
-		sisfb_post_xgi_setclocks(ivideo, regb);
-		if((ivideo->chip == XGI_40) &&
-		   ((ivideo->revision_id == 1) ||
-		    (ivideo->revision_id == 2))) {
-			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
-			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
-			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
-		} else {
-			SiS_SetReg(SISCR, 0x82, 0x88);
-			SiS_SetReg(SISCR, 0x86, 0x00);
-			reg = SiS_GetReg(SISCR, 0x86);
-			SiS_SetReg(SISCR, 0x86, 0x88);
-			SiS_SetReg(SISCR, 0x82, 0x77);
-			SiS_SetReg(SISCR, 0x85, 0x00);
-			reg = SiS_GetReg(SISCR, 0x85);
-			SiS_SetReg(SISCR, 0x85, 0x88);
-			reg = SiS_GetReg(SISCR, 0x85);
-			v1 = cs160[regb]; v2 = cs158[regb];
-			if(ivideo->haveXGIROM) {
-				v1 = bios[regb + 0x160];
-				v2 = bios[regb + 0x158];
-			}
-			SiS_SetReg(SISCR, 0x85, v1);
-			SiS_SetReg(SISCR, 0x82, v2);
-		}
-		if(ivideo->chip == XGI_40) {
-			SiS_SetReg(SISCR, 0x97, 0x11);
-		}
-		if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
-			SiS_SetReg(SISCR, 0x98, 0x01);
-		} else {
-			SiS_SetReg(SISCR, 0x98, 0x03);
-		}
-		SiS_SetReg(SISCR, 0x9a, 0x02);
-
-		if(ivideo->chip == XGI_40) {
-			SiS_SetReg(SISSR, 0x18, 0x01);
-		} else {
-			SiS_SetReg(SISSR, 0x18, 0x00);
-		}
-		SiS_SetReg(SISSR, 0x19, 0x40);
-		SiS_SetReg(SISSR, 0x16, 0x00);
-		SiS_SetReg(SISSR, 0x16, 0x80);
-		if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
-			sisfb_post_xgi_delay(ivideo, 0x43);
-			sisfb_post_xgi_delay(ivideo, 0x43);
-			sisfb_post_xgi_delay(ivideo, 0x43);
-			SiS_SetReg(SISSR, 0x18, 0x00);
-			SiS_SetReg(SISSR, 0x19, 0x40);
-			SiS_SetReg(SISSR, 0x16, 0x00);
-			SiS_SetReg(SISSR, 0x16, 0x80);
-		}
-		sisfb_post_xgi_delay(ivideo, 4);
-		v1 = 0x31;
-		if(ivideo->haveXGIROM) {
-			v1 = bios[0xf0];
-		}
-		SiS_SetReg(SISSR, 0x18, v1);
-		SiS_SetReg(SISSR, 0x19, 0x01);
-		if(ivideo->chip == XGI_40) {
-			SiS_SetReg(SISSR, 0x16, bios[0x53e]);
-			SiS_SetReg(SISSR, 0x16, bios[0x53f]);
-		} else {
-			SiS_SetReg(SISSR, 0x16, 0x05);
-			SiS_SetReg(SISSR, 0x16, 0x85);
-		}
-		sisfb_post_xgi_delay(ivideo, 0x43);
-		if(ivideo->chip == XGI_40) {
-			SiS_SetReg(SISSR, 0x1b, 0x01);
-		} else {
-			SiS_SetReg(SISSR, 0x1b, 0x03);
-		}
-		sisfb_post_xgi_delay(ivideo, 0x22);
-		SiS_SetReg(SISSR, 0x18, v1);
-		SiS_SetReg(SISSR, 0x19, 0x00);
-		if(ivideo->chip == XGI_40) {
-			SiS_SetReg(SISSR, 0x16, bios[0x540]);
-			SiS_SetReg(SISSR, 0x16, bios[0x541]);
-		} else {
-			SiS_SetReg(SISSR, 0x16, 0x05);
-			SiS_SetReg(SISSR, 0x16, 0x85);
-		}
-		SiS_SetReg(SISSR, 0x1b, 0x00);
-	}
-
-	regb = 0;	/* ! */
-	v1 = 0x03;
-	if(ivideo->haveXGIROM) {
-		v1 = bios[0x110 + regb];
-	}
-	SiS_SetReg(SISSR, 0x1b, v1);
-
-	/* RAM size */
-	v1 = 0x00; v2 = 0x00;
-	if(ivideo->haveXGIROM) {
-		v1 = bios[0x62];
-		v2 = bios[0x63];
-	}
-	regb = 0;	/* ! */
-	regd = 1 << regb;
-	if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
-
-		SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
-		SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
-
-	} else {
-		int err;
-
-		/* Set default mode, don't clear screen */
-		ivideo->SiS_Pr.SiS_UseOEM = false;
-		SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
-		SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
-		ivideo->curFSTN = ivideo->curDSTN = 0;
-		ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
-		SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
-
-		SiS_SetReg(SISSR, 0x05, 0x86);
-
-		/* Disable read-cache */
-		SiS_SetRegAND(SISSR, 0x21, 0xdf);
-		err = sisfb_post_xgi_ramsize(ivideo);
-		/* Enable read-cache */
-		SiS_SetRegOR(SISSR, 0x21, 0x20);
-
-		if (err) {
-			dev_err(&pdev->dev,
-				"%s: RAM size detection failed: %d\n",
-				__func__, err);
-			return 0;
-		}
-	}
-
-#if 0
-	printk(KERN_DEBUG "-----------------\n");
-	for(i = 0; i < 0xff; i++) {
-		reg = SiS_GetReg(SISCR, i);
-		printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
-	}
-	for(i = 0; i < 0x40; i++) {
-		reg = SiS_GetReg(SISSR, i);
-		printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
-	}
-	printk(KERN_DEBUG "-----------------\n");
-#endif
-
-	/* Sense CRT1 */
-	if(ivideo->chip == XGI_20) {
-		SiS_SetRegOR(SISCR, 0x32, 0x20);
-	} else {
-		reg = SiS_GetReg(SISPART4, 0x00);
-		if((reg == 1) || (reg == 2)) {
-			sisfb_sense_crt1(ivideo);
-		} else {
-			SiS_SetRegOR(SISCR, 0x32, 0x20);
-		}
-	}
-
-	/* Set default mode, don't clear screen */
-	ivideo->SiS_Pr.SiS_UseOEM = false;
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
-	ivideo->curFSTN = ivideo->curDSTN = 0;
-	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
-
-	SiS_SetReg(SISSR, 0x05, 0x86);
-
-	/* Display off */
-	SiS_SetRegOR(SISSR, 0x01, 0x20);
-
-	/* Save mode number in CR34 */
-	SiS_SetReg(SISCR, 0x34, 0x2e);
-
-	/* Let everyone know what the current mode is */
-	ivideo->modeprechange = 0x2e;
-
-	if(ivideo->chip == XGI_40) {
-		reg = SiS_GetReg(SISCR, 0xca);
-		v1 = SiS_GetReg(SISCR, 0xcc);
-		if((reg & 0x10) && (!(v1 & 0x04))) {
-			printk(KERN_ERR
-				"sisfb: Please connect power to the card.\n");
-			return 0;
-		}
-	}
-
-	return 1;
-}
-#endif
-
-static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	struct sisfb_chip_info	*chipinfo = &sisfb_chip_info[ent->driver_data];
-	struct sis_video_info	*ivideo = NULL;
-	struct fb_info		*sis_fb_info = NULL;
-	u16 reg16;
-	u8  reg;
-	int i, ret;
-
-	if(sisfb_off)
-		return -ENXIO;
-
-	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
-	if(!sis_fb_info)
-		return -ENOMEM;
-
-	ivideo = (struct sis_video_info *)sis_fb_info->par;
-	ivideo->memyselfandi = sis_fb_info;
-
-	ivideo->sisfb_id = SISFB_ID;
-
-	if(card_list == NULL) {
-		ivideo->cardnumber = 0;
-	} else {
-		struct sis_video_info *countvideo = card_list;
-		ivideo->cardnumber = 1;
-		while((countvideo = countvideo->next) != NULL)
-			ivideo->cardnumber++;
-	}
-
-	strncpy(ivideo->myid, chipinfo->chip_name, 30);
-
-	ivideo->warncount = 0;
-	ivideo->chip_id = pdev->device;
-	ivideo->chip_vendor = pdev->vendor;
-	ivideo->revision_id = pdev->revision;
-	ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
-	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
-	ivideo->sisvga_enabled = reg16 & 0x01;
-	ivideo->pcibus = pdev->bus->number;
-	ivideo->pcislot = PCI_SLOT(pdev->devfn);
-	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
-	ivideo->subsysvendor = pdev->subsystem_vendor;
-	ivideo->subsysdevice = pdev->subsystem_device;
-
-#ifndef MODULE
-	if(sisfb_mode_idx == -1) {
-		sisfb_get_vga_mode_from_kernel();
-	}
-#endif
-
-	ivideo->chip = chipinfo->chip;
-	ivideo->chip_real_id = chipinfo->chip;
-	ivideo->sisvga_engine = chipinfo->vgaengine;
-	ivideo->hwcursor_size = chipinfo->hwcursor_size;
-	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
-	ivideo->mni = chipinfo->mni;
-
-	ivideo->detectedpdc  = 0xff;
-	ivideo->detectedpdca = 0xff;
-	ivideo->detectedlcda = 0xff;
-
-	ivideo->sisfb_thismonitor.datavalid = false;
-
-	ivideo->current_base = 0;
-
-	ivideo->engineok = 0;
-
-	ivideo->sisfb_was_boot_device = 0;
-
-	if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
-		if(ivideo->sisvga_enabled)
-			ivideo->sisfb_was_boot_device = 1;
-		else {
-			printk(KERN_DEBUG "sisfb: PCI device is disabled, "
-				"but marked as boot video device ???\n");
-			printk(KERN_DEBUG "sisfb: I will not accept this "
-				"as the primary VGA device\n");
-		}
-	}
-
-	ivideo->sisfb_parm_mem = sisfb_parm_mem;
-	ivideo->sisfb_accel = sisfb_accel;
-	ivideo->sisfb_ypan = sisfb_ypan;
-	ivideo->sisfb_max = sisfb_max;
-	ivideo->sisfb_userom = sisfb_userom;
-	ivideo->sisfb_useoem = sisfb_useoem;
-	ivideo->sisfb_mode_idx = sisfb_mode_idx;
-	ivideo->sisfb_parm_rate = sisfb_parm_rate;
-	ivideo->sisfb_crt1off = sisfb_crt1off;
-	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
-	ivideo->sisfb_crt2type = sisfb_crt2type;
-	ivideo->sisfb_crt2flags = sisfb_crt2flags;
-	/* pdc(a), scalelcd, special timing, lvdshl handled below */
-	ivideo->sisfb_dstn = sisfb_dstn;
-	ivideo->sisfb_fstn = sisfb_fstn;
-	ivideo->sisfb_tvplug = sisfb_tvplug;
-	ivideo->sisfb_tvstd = sisfb_tvstd;
-	ivideo->tvxpos = sisfb_tvxposoffset;
-	ivideo->tvypos = sisfb_tvyposoffset;
-	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
-	ivideo->refresh_rate = 0;
-	if(ivideo->sisfb_parm_rate != -1) {
-		ivideo->refresh_rate = ivideo->sisfb_parm_rate;
-	}
-
-	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
-	ivideo->SiS_Pr.CenterScreen = -1;
-	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
-	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
-
-	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
-	ivideo->SiS_Pr.SiS_CHOverScan = -1;
-	ivideo->SiS_Pr.SiS_ChSW = false;
-	ivideo->SiS_Pr.SiS_UseLCDA = false;
-	ivideo->SiS_Pr.HaveEMI = false;
-	ivideo->SiS_Pr.HaveEMILCD = false;
-	ivideo->SiS_Pr.OverruleEMI = false;
-	ivideo->SiS_Pr.SiS_SensibleSR11 = false;
-	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
-	ivideo->SiS_Pr.PDC  = -1;
-	ivideo->SiS_Pr.PDCA = -1;
-	ivideo->SiS_Pr.DDCPortMixup = false;
-#ifdef CONFIG_FB_SIS_315
-	if(ivideo->chip >= SIS_330) {
-		ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
-		if(ivideo->chip >= SIS_661) {
-			ivideo->SiS_Pr.SiS_SensibleSR11 = true;
-		}
-	}
-#endif
-
-	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
-
-	pci_set_drvdata(pdev, ivideo);
-
-	/* Patch special cases */
-	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
-		switch(ivideo->nbridge->device) {
-#ifdef CONFIG_FB_SIS_300
-		case PCI_DEVICE_ID_SI_730:
-			ivideo->chip = SIS_730;
-			strcpy(ivideo->myid, "SiS 730");
-			break;
-#endif
-#ifdef CONFIG_FB_SIS_315
-		case PCI_DEVICE_ID_SI_651:
-			/* ivideo->chip is ok */
-			strcpy(ivideo->myid, "SiS 651");
-			break;
-		case PCI_DEVICE_ID_SI_740:
-			ivideo->chip = SIS_740;
-			strcpy(ivideo->myid, "SiS 740");
-			break;
-		case PCI_DEVICE_ID_SI_661:
-			ivideo->chip = SIS_661;
-			strcpy(ivideo->myid, "SiS 661");
-			break;
-		case PCI_DEVICE_ID_SI_741:
-			ivideo->chip = SIS_741;
-			strcpy(ivideo->myid, "SiS 741");
-			break;
-		case PCI_DEVICE_ID_SI_760:
-			ivideo->chip = SIS_760;
-			strcpy(ivideo->myid, "SiS 760");
-			break;
-		case PCI_DEVICE_ID_SI_761:
-			ivideo->chip = SIS_761;
-			strcpy(ivideo->myid, "SiS 761");
-			break;
-#endif
-		default:
-			break;
-		}
-	}
-
-	ivideo->SiS_Pr.ChipType = ivideo->chip;
-
-	ivideo->SiS_Pr.ivideo = (void *)ivideo;
-
-#ifdef CONFIG_FB_SIS_315
-	if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
-	   (ivideo->SiS_Pr.ChipType == SIS_315)) {
-		ivideo->SiS_Pr.ChipType = SIS_315H;
-	}
-#endif
-
-	if(!ivideo->sisvga_enabled) {
-		if(pci_enable_device(pdev)) {
-			if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
-			framebuffer_release(sis_fb_info);
-			return -EIO;
-		}
-	}
-
-	ivideo->video_base = pci_resource_start(pdev, 0);
-	ivideo->video_size = pci_resource_len(pdev, 0);
-	ivideo->mmio_base  = pci_resource_start(pdev, 1);
-	ivideo->mmio_size  = pci_resource_len(pdev, 1);
-	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
-	ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
-
-	SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
-
-#ifdef CONFIG_FB_SIS_300
-	/* Find PCI systems for Chrontel/GPIO communication setup */
-	if(ivideo->chip == SIS_630) {
-		i = 0;
-        	do {
-			if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
-			   mychswtable[i].subsysCard   == ivideo->subsysdevice) {
-				ivideo->SiS_Pr.SiS_ChSW = true;
-				printk(KERN_DEBUG "sisfb: Identified [%s %s] "
-					"requiring Chrontel/GPIO setup\n",
-					mychswtable[i].vendorName,
-					mychswtable[i].cardName);
-				ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
-				break;
-			}
-			i++;
-		} while(mychswtable[i].subsysVendor != 0);
-	}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-	if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
-		ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
-	}
-#endif
-
-	SiS_SetReg(SISSR, 0x05, 0x86);
-
-	if( (!ivideo->sisvga_enabled)
-#if !defined(__i386__) && !defined(__x86_64__)
-			      || (sisfb_resetcard)
-#endif
-						   ) {
-		for(i = 0x30; i <= 0x3f; i++) {
-			SiS_SetReg(SISCR, i, 0x00);
-		}
-	}
-
-	/* Find out about current video mode */
-	ivideo->modeprechange = 0x03;
-	reg = SiS_GetReg(SISCR, 0x34);
-	if(reg & 0x7f) {
-		ivideo->modeprechange = reg & 0x7f;
-	} else if(ivideo->sisvga_enabled) {
-#if defined(__i386__) || defined(__x86_64__)
-		unsigned char __iomem *tt = ioremap(0x400, 0x100);
-		if(tt) {
-			ivideo->modeprechange = readb(tt + 0x49);
-			iounmap(tt);
-		}
-#endif
-	}
-
-	/* Search and copy ROM image */
-	ivideo->bios_abase = NULL;
-	ivideo->SiS_Pr.VirtualRomBase = NULL;
-	ivideo->SiS_Pr.UseROM = false;
-	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
-	if(ivideo->sisfb_userom) {
-		ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
-		ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
-		ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
-		printk(KERN_INFO "sisfb: Video ROM %sfound\n",
-			ivideo->SiS_Pr.UseROM ? "" : "not ");
-		if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
-		   ivideo->SiS_Pr.UseROM = false;
-		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
-		   if( (ivideo->revision_id == 2) &&
-		       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
-			ivideo->SiS_Pr.DDCPortMixup = true;
-		   }
-		}
-	} else {
-		printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
-	}
-
-	/* Find systems for special custom timing */
-	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
-		sisfb_detect_custom_timing(ivideo);
-	}
-
-#ifdef CONFIG_FB_SIS_315
-	if (ivideo->chip == XGI_20) {
-		/* Check if our Z7 chip is actually Z9 */
-		SiS_SetRegOR(SISCR, 0x4a, 0x40);	/* GPIOG EN */
-		reg = SiS_GetReg(SISCR, 0x48);
-		if (reg & 0x02) {			/* GPIOG */
-			ivideo->chip_real_id = XGI_21;
-			dev_info(&pdev->dev, "Z9 detected\n");
-		}
-	}
-#endif
-
-	/* POST card in case this has not been done by the BIOS */
-	if( (!ivideo->sisvga_enabled)
-#if !defined(__i386__) && !defined(__x86_64__)
-			     || (sisfb_resetcard)
-#endif
-						 ) {
-#ifdef CONFIG_FB_SIS_300
-		if(ivideo->sisvga_engine == SIS_300_VGA) {
-			if(ivideo->chip == SIS_300) {
-				sisfb_post_sis300(pdev);
-				ivideo->sisfb_can_post = 1;
-			}
-		}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-		if(ivideo->sisvga_engine == SIS_315_VGA) {
-			int result = 1;
-		/*	if((ivideo->chip == SIS_315H)   ||
-			   (ivideo->chip == SIS_315)    ||
-			   (ivideo->chip == SIS_315PRO) ||
-			   (ivideo->chip == SIS_330)) {
-				sisfb_post_sis315330(pdev);
-			} else */ if(ivideo->chip == XGI_20) {
-				result = sisfb_post_xgi(pdev);
-				ivideo->sisfb_can_post = 1;
-			} else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
-				result = sisfb_post_xgi(pdev);
-				ivideo->sisfb_can_post = 1;
-			} else {
-				printk(KERN_INFO "sisfb: Card is not "
-					"POSTed and sisfb can't do this either.\n");
-			}
-			if(!result) {
-				printk(KERN_ERR "sisfb: Failed to POST card\n");
-				ret = -ENODEV;
-				goto error_3;
-			}
-		}
-#endif
-	}
-
-	ivideo->sisfb_card_posted = 1;
-
-	/* Find out about RAM size */
-	if(sisfb_get_dram_size(ivideo)) {
-		printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
-		ret = -ENODEV;
-		goto error_3;
-	}
-
-
-	/* Enable PCI addressing and MMIO */
-	if((ivideo->sisfb_mode_idx < 0) ||
-	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
-		/* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
-		SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
-		/* Enable 2D accelerator engine */
-		SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
-	}
-
-	if(sisfb_pdc != 0xff) {
-		if(ivideo->sisvga_engine == SIS_300_VGA)
-			sisfb_pdc &= 0x3c;
-		else
-			sisfb_pdc &= 0x1f;
-		ivideo->SiS_Pr.PDC = sisfb_pdc;
-	}
-#ifdef CONFIG_FB_SIS_315
-	if(ivideo->sisvga_engine == SIS_315_VGA) {
-		if(sisfb_pdca != 0xff)
-			ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
-	}
-#endif
-
-	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
-		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
-				(int)(ivideo->video_size >> 20));
-		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
-		ret = -ENODEV;
-		goto error_3;
-	}
-
-	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
-		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
-		ret = -ENODEV;
-		goto error_2;
-	}
-
-	ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
-	ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
-	if(!ivideo->video_vbase) {
-		printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
-		ret = -ENODEV;
-		goto error_1;
-	}
-
-	ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
-	if(!ivideo->mmio_vbase) {
-		printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
-		ret = -ENODEV;
-error_0:	iounmap(ivideo->video_vbase);
-error_1:	release_mem_region(ivideo->video_base, ivideo->video_size);
-error_2:	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
-error_3:	vfree(ivideo->bios_abase);
-		if(ivideo->lpcdev)
-			pci_dev_put(ivideo->lpcdev);
-		if(ivideo->nbridge)
-			pci_dev_put(ivideo->nbridge);
-		if(!ivideo->sisvga_enabled)
-			pci_disable_device(pdev);
-		framebuffer_release(sis_fb_info);
-		return ret;
-	}
-
-	printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
-		ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
-
-	if(ivideo->video_offset) {
-		printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
-			ivideo->video_offset / 1024);
-	}
-
-	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
-		ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
-
-
-	/* Determine the size of the command queue */
-	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
-	} else {
-		if(ivideo->chip == XGI_20) {
-			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
-		} else {
-			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
-		}
-	}
-
-	/* Engines are no longer initialized here; this is
-	 * now done after the first mode-switch (if the
-	 * submitted var has its acceleration flags set).
-	 */
-
-	/* Calculate the base of the (unused) hw cursor */
-	ivideo->hwcursor_vbase = ivideo->video_vbase
-				 + ivideo->video_size
-				 - ivideo->cmdQueueSize
-				 - ivideo->hwcursor_size;
-	ivideo->caps |= HW_CURSOR_CAP;
-
-	/* Initialize offscreen memory manager */
-	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
-		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
-	}
-
-	/* Used for clearing the screen only, therefore respect our mem limit */
-	ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
-	ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
-
-	ivideo->mtrr = -1;
-
-	ivideo->vbflags = 0;
-	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
-	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
-	ivideo->defmodeidx    = DEFAULT_MODE;
-
-	ivideo->newrom = 0;
-	if(ivideo->chip < XGI_20) {
-		if(ivideo->bios_abase) {
-			ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
-		}
-	}
-
-	if((ivideo->sisfb_mode_idx < 0) ||
-	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
-
-		sisfb_sense_crt1(ivideo);
-
-		sisfb_get_VB_type(ivideo);
-
-		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
-			sisfb_detect_VB_connect(ivideo);
-		}
-
-		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
-
-		/* Decide on which CRT2 device to use */
-		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
-			if(ivideo->sisfb_crt2type != -1) {
-				if((ivideo->sisfb_crt2type == CRT2_LCD) &&
-				   (ivideo->vbflags & CRT2_LCD)) {
-					ivideo->currentvbflags |= CRT2_LCD;
-				} else if(ivideo->sisfb_crt2type != CRT2_LCD) {
-					ivideo->currentvbflags |= ivideo->sisfb_crt2type;
-				}
-			} else {
-				/* Chrontel 700x TV detection often unreliable, therefore
-				 * use a different default order on such machines
-				 */
-				if((ivideo->sisvga_engine == SIS_300_VGA) &&
-				   (ivideo->vbflags2 & VB2_CHRONTEL)) {
-					if(ivideo->vbflags & CRT2_LCD)
-						ivideo->currentvbflags |= CRT2_LCD;
-					else if(ivideo->vbflags & CRT2_TV)
-						ivideo->currentvbflags |= CRT2_TV;
-					else if(ivideo->vbflags & CRT2_VGA)
-						ivideo->currentvbflags |= CRT2_VGA;
-				} else {
-					if(ivideo->vbflags & CRT2_TV)
-						ivideo->currentvbflags |= CRT2_TV;
-					else if(ivideo->vbflags & CRT2_LCD)
-						ivideo->currentvbflags |= CRT2_LCD;
-					else if(ivideo->vbflags & CRT2_VGA)
-						ivideo->currentvbflags |= CRT2_VGA;
-				}
-			}
-		}
-
-		if(ivideo->vbflags & CRT2_LCD) {
-			sisfb_detect_lcd_type(ivideo);
-		}
-
-		sisfb_save_pdc_emi(ivideo);
-
-		if(!ivideo->sisfb_crt1off) {
-			sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
-		} else {
-			if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
-			   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
-				sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
-			}
-		}
-
-		if(ivideo->sisfb_mode_idx >= 0) {
-			int bu = ivideo->sisfb_mode_idx;
-			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
-					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
-			if(bu != ivideo->sisfb_mode_idx) {
-				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
-					sisbios_mode[bu].xres,
-					sisbios_mode[bu].yres,
-					sisbios_mode[bu].bpp);
-			}
-		}
-
-		if(ivideo->sisfb_mode_idx < 0) {
-			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-			   case CRT2_LCD:
-				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
-				break;
-			   case CRT2_TV:
-				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
-				break;
-			   default:
-				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
-				break;
-			}
-		}
-
-		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
-
-		if(ivideo->refresh_rate != 0) {
-			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
-						ivideo->sisfb_mode_idx);
-		}
-
-		if(ivideo->rate_idx == 0) {
-			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
-			ivideo->refresh_rate = 60;
-		}
-
-		if(ivideo->sisfb_thismonitor.datavalid) {
-			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
-						ivideo->sisfb_mode_idx,
-						ivideo->rate_idx,
-						ivideo->refresh_rate)) {
-				printk(KERN_INFO "sisfb: WARNING: Refresh rate "
-							"exceeds monitor specs!\n");
-			}
-		}
-
-		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
-		ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
-		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
-
-		sisfb_set_vparms(ivideo);
-
-		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
-			ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
-			ivideo->refresh_rate);
-
-		/* Set up the default var according to chosen default display mode */
-		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
-		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
-		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
-
-		sisfb_bpp_to_var(ivideo, &ivideo->default_var);
-
-		ivideo->default_var.pixclock = (u32) (1000000000 /
-			sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
-
-		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
-						ivideo->rate_idx, &ivideo->default_var)) {
-			if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-				ivideo->default_var.pixclock <<= 1;
-			}
-		}
-
-		if(ivideo->sisfb_ypan) {
-			/* Maximize regardless of sisfb_max at startup */
-			ivideo->default_var.yres_virtual =
-				sisfb_calc_maxyres(ivideo, &ivideo->default_var);
-			if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
-				ivideo->default_var.yres_virtual = ivideo->default_var.yres;
-			}
-		}
-
-		sisfb_calc_pitch(ivideo, &ivideo->default_var);
-
-		ivideo->accel = 0;
-		if(ivideo->sisfb_accel) {
-			ivideo->accel = -1;
-#ifdef STUPID_ACCELF_TEXT_SHIT
-			ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
-#endif
-		}
-		sisfb_initaccel(ivideo);
-
-#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
-		sis_fb_info->flags = FBINFO_DEFAULT 		|
-				     FBINFO_HWACCEL_YPAN 	|
-				     FBINFO_HWACCEL_XPAN 	|
-				     FBINFO_HWACCEL_COPYAREA 	|
-				     FBINFO_HWACCEL_FILLRECT 	|
-				     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
-#else
-		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
-#endif
-		sis_fb_info->var = ivideo->default_var;
-		sis_fb_info->fix = ivideo->sisfb_fix;
-		sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
-		sis_fb_info->fbops = &sisfb_ops;
-		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
-
-		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
-
-		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
-
-#ifdef CONFIG_MTRR
-		ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
-					MTRR_TYPE_WRCOMB, 1);
-		if(ivideo->mtrr < 0) {
-			printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
-		}
-#endif
-
-		if(register_framebuffer(sis_fb_info) < 0) {
-			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
-			ret = -EINVAL;
-			iounmap(ivideo->mmio_vbase);
-			goto error_0;
-		}
-
-		ivideo->registered = 1;
-
-		/* Enlist us */
-		ivideo->next = card_list;
-		card_list = ivideo;
-
-		printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
-			ivideo->sisfb_accel ? "enabled" : "disabled",
-			ivideo->sisfb_ypan  ?
-				(ivideo->sisfb_max ? "enabled (auto-max)" :
-						"enabled (no auto-max)") :
-									"disabled");
-
-
-		fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
-			ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
-
-		printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
-
-	}	/* if mode = "none" */
-
-	return 0;
-}
-
-/*****************************************************/
-/*                PCI DEVICE HANDLING                */
-/*****************************************************/
-
-static void sisfb_remove(struct pci_dev *pdev)
-{
-	struct sis_video_info	*ivideo = pci_get_drvdata(pdev);
-	struct fb_info		*sis_fb_info = ivideo->memyselfandi;
-	int			registered = ivideo->registered;
-	int			modechanged = ivideo->modechanged;
-
-	/* Unmap */
-	iounmap(ivideo->mmio_vbase);
-	iounmap(ivideo->video_vbase);
-
-	/* Release mem regions */
-	release_mem_region(ivideo->video_base, ivideo->video_size);
-	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
-
-	vfree(ivideo->bios_abase);
-
-	if(ivideo->lpcdev)
-		pci_dev_put(ivideo->lpcdev);
-
-	if(ivideo->nbridge)
-		pci_dev_put(ivideo->nbridge);
-
-#ifdef CONFIG_MTRR
-	/* Release MTRR region */
-	if(ivideo->mtrr >= 0)
-		mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
-#endif
-
-	/* If device was disabled when starting, disable
-	 * it when quitting.
-	 */
-	if(!ivideo->sisvga_enabled)
-		pci_disable_device(pdev);
-
-	/* Unregister the framebuffer */
-	if(ivideo->registered) {
-		unregister_framebuffer(sis_fb_info);
-		framebuffer_release(sis_fb_info);
-	}
-
-	/* OK, our ivideo is gone for good from here. */
-
-	/* TODO: Restore the initial mode
-	 * This sounds easy but is as good as impossible
-	 * on many machines with SiS chip and video bridge
-	 * since text modes are always set up differently
-	 * from machine to machine. Depends on the type
-	 * of integration between chipset and bridge.
-	 */
-	if(registered && modechanged)
-		printk(KERN_INFO
-			"sisfb: Restoring of text mode not supported yet\n");
-};
-
-static struct pci_driver sisfb_driver = {
-	.name		= "sisfb",
-	.id_table 	= sisfb_pci_table,
-	.probe		= sisfb_probe,
-	.remove 	= sisfb_remove,
-};
-
-static int __init sisfb_init(void)
-{
-#ifndef MODULE
-	char *options = NULL;
-
-	if(fb_get_options("sisfb", &options))
-		return -ENODEV;
-
-	sisfb_setup(options);
-#endif
-	return pci_register_driver(&sisfb_driver);
-}
-
-#ifndef MODULE
-module_init(sisfb_init);
-#endif
-
-/*****************************************************/
-/*                      MODULE                       */
-/*****************************************************/
-
-#ifdef MODULE
-
-static char		*mode = NULL;
-static int		vesa = -1;
-static unsigned int	rate = 0;
-static unsigned int	crt1off = 1;
-static unsigned int	mem = 0;
-static char		*forcecrt2type = NULL;
-static int		forcecrt1 = -1;
-static int		pdc = -1;
-static int		pdc1 = -1;
-static int		noaccel = -1;
-static int		noypan  = -1;
-static int		nomax = -1;
-static int		userom = -1;
-static int		useoem = -1;
-static char		*tvstandard = NULL;
-static int		nocrt2rate = 0;
-static int		scalelcd = -1;
-static char		*specialtiming = NULL;
-static int		lvdshl = -1;
-static int		tvxposoffset = 0, tvyposoffset = 0;
-#if !defined(__i386__) && !defined(__x86_64__)
-static int		resetcard = 0;
-static int		videoram = 0;
-#endif
-
-static int __init sisfb_init_module(void)
-{
-	sisfb_setdefaultparms();
-
-	if(rate)
-		sisfb_parm_rate = rate;
-
-	if((scalelcd == 0) || (scalelcd == 1))
-		sisfb_scalelcd = scalelcd ^ 1;
-
-	/* Need to check crt2 type first for fstn/dstn */
-
-	if(forcecrt2type)
-		sisfb_search_crt2type(forcecrt2type);
-
-	if(tvstandard)
-		sisfb_search_tvstd(tvstandard);
-
-	if(mode)
-		sisfb_search_mode(mode, false);
-	else if(vesa != -1)
-		sisfb_search_vesamode(vesa, false);
-
-	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
-
-	sisfb_forcecrt1 = forcecrt1;
-	if(forcecrt1 == 1)
-		sisfb_crt1off = 0;
-	else if(forcecrt1 == 0)
-		sisfb_crt1off = 1;
-
-	if(noaccel == 1)
-		sisfb_accel = 0;
-	else if(noaccel == 0)
-		sisfb_accel = 1;
-
-	if(noypan == 1)
-		sisfb_ypan = 0;
-	else if(noypan == 0)
-		sisfb_ypan = 1;
-
-	if(nomax == 1)
-		sisfb_max = 0;
-	else if(nomax == 0)
-		sisfb_max = 1;
-
-	if(mem)
-		sisfb_parm_mem = mem;
-
-	if(userom != -1)
-		sisfb_userom = userom;
-
-	if(useoem != -1)
-		sisfb_useoem = useoem;
-
-        if(pdc != -1)
-		sisfb_pdc  = (pdc  & 0x7f);
-
-	if(pdc1 != -1)
-		sisfb_pdca = (pdc1 & 0x1f);
-
-	sisfb_nocrt2rate = nocrt2rate;
-
-	if(specialtiming)
-		sisfb_search_specialtiming(specialtiming);
-
-	if((lvdshl >= 0) && (lvdshl <= 3))
-		sisfb_lvdshl = lvdshl;
-
-	sisfb_tvxposoffset = tvxposoffset;
-	sisfb_tvyposoffset = tvyposoffset;
-
-#if !defined(__i386__) && !defined(__x86_64__)
-	sisfb_resetcard = (resetcard) ? 1 : 0;
-	if(videoram)
-		sisfb_videoram = videoram;
-#endif
-
-	return sisfb_init();
-}
-
-static void __exit sisfb_remove_module(void)
-{
-	pci_unregister_driver(&sisfb_driver);
-	printk(KERN_DEBUG "sisfb: Module unloaded\n");
-}
-
-module_init(sisfb_init_module);
-module_exit(sisfb_remove_module);
-
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
-
-module_param(mem, int, 0);
-module_param(noaccel, int, 0);
-module_param(noypan, int, 0);
-module_param(nomax, int, 0);
-module_param(userom, int, 0);
-module_param(useoem, int, 0);
-module_param(mode, charp, 0);
-module_param(vesa, int, 0);
-module_param(rate, int, 0);
-module_param(forcecrt1, int, 0);
-module_param(forcecrt2type, charp, 0);
-module_param(scalelcd, int, 0);
-module_param(pdc, int, 0);
-module_param(pdc1, int, 0);
-module_param(specialtiming, charp, 0);
-module_param(lvdshl, int, 0);
-module_param(tvstandard, charp, 0);
-module_param(tvxposoffset, int, 0);
-module_param(tvyposoffset, int, 0);
-module_param(nocrt2rate, int, 0);
-#if !defined(__i386__) && !defined(__x86_64__)
-module_param(resetcard, int, 0);
-module_param(videoram, int, 0);
-#endif
-
-MODULE_PARM_DESC(mem,
-	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
-	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
-	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
-	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
-	  "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
-	  "The value is to be specified without 'KB'.\n");
-
-MODULE_PARM_DESC(noaccel,
-	"\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
-	  "(default: 0)\n");
-
-MODULE_PARM_DESC(noypan,
-	"\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
-	  "will be performed by redrawing the screen. (default: 0)\n");
-
-MODULE_PARM_DESC(nomax,
-	"\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
-	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
-	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
-	  "enable the user to positively specify a virtual Y size of the screen using\n"
-	  "fbset. (default: 0)\n");
-
-MODULE_PARM_DESC(mode,
-	"\nSelects the desired default display mode in the format XxYxDepth,\n"
-	 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
-	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
-	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
-
-MODULE_PARM_DESC(vesa,
-	"\nSelects the desired default display mode by VESA defined mode number, eg.\n"
-	 "0x117 (default: 0x0103)\n");
-
-MODULE_PARM_DESC(rate,
-	"\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
-	  "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
-	  "will be ignored (default: 60)\n");
-
-MODULE_PARM_DESC(forcecrt1,
-	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
-	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
-	  "0=CRT1 OFF) (default: [autodetected])\n");
-
-MODULE_PARM_DESC(forcecrt2type,
-	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
-	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
-	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
-	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
-	  "be used instead of TV to override the TV detection. Furthermore, on systems\n"
-	  "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
-	  "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
-	  "depends on the very hardware in use. (default: [autodetected])\n");
-
-MODULE_PARM_DESC(scalelcd,
-	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
-	  "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
-	  "show black bars around the image, TMDS panels will probably do the scaling\n"
-	  "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
-
-MODULE_PARM_DESC(pdc,
-	"\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
-	  "should detect this correctly in most cases; however, sometimes this is not\n"
-	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
-	  "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
-	  "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
-	  "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
-
-#ifdef CONFIG_FB_SIS_315
-MODULE_PARM_DESC(pdc1,
-	"\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
-	  "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
-	  "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
-	  "implemented yet.\n");
-#endif
-
-MODULE_PARM_DESC(specialtiming,
-	"\nPlease refer to documentation for more information on this option.\n");
-
-MODULE_PARM_DESC(lvdshl,
-	"\nPlease refer to documentation for more information on this option.\n");
-
-MODULE_PARM_DESC(tvstandard,
-	"\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
-	  "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
-
-MODULE_PARM_DESC(tvxposoffset,
-	"\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
-	  "Default: 0\n");
-
-MODULE_PARM_DESC(tvyposoffset,
-	"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
-	  "Default: 0\n");
-
-MODULE_PARM_DESC(nocrt2rate,
-	"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
-	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
-
-#if !defined(__i386__) && !defined(__x86_64__)
-#ifdef CONFIG_FB_SIS_300
-MODULE_PARM_DESC(resetcard,
-	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
-	  "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
-	  "currently). Default: 0\n");
-
-MODULE_PARM_DESC(videoram,
-	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
-	  "some non-x86 architectures where the memory auto detection fails. Only\n"
-	  "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
-#endif
-#endif
-
-#endif 	   /*  /MODULE  */
-
-/* _GPL only for new symbols. */
-EXPORT_SYMBOL(sis_malloc);
-EXPORT_SYMBOL(sis_free);
-EXPORT_SYMBOL_GPL(sis_malloc_new);
-EXPORT_SYMBOL_GPL(sis_free_new);
-
-
-
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
deleted file mode 100644
index 32e23c209430..000000000000
--- a/drivers/video/sis/sis_main.h
+++ /dev/null
@@ -1,781 +0,0 @@
-/*
- * SiS 300/305/540/630(S)/730(S),
- * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
- * XGI V3XT/V5/V8, Z7
- * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
- *
- * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef _SISFB_MAIN
-#define _SISFB_MAIN
-
-#include "vstruct.h"
-#include "sis.h"
-
-/* Fbcon stuff */
-static struct fb_var_screeninfo my_default_var = {
-	.xres            = 0,
-	.yres            = 0,
-	.xres_virtual    = 0,
-	.yres_virtual    = 0,
-	.xoffset         = 0,
-	.yoffset         = 0,
-	.bits_per_pixel  = 0,
-	.grayscale       = 0,
-	.red             = {0, 8, 0},
-	.green           = {0, 8, 0},
-	.blue            = {0, 8, 0},
-	.transp          = {0, 0, 0},
-	.nonstd          = 0,
-	.activate        = FB_ACTIVATE_NOW,
-	.height          = -1,
-	.width           = -1,
-	.accel_flags     = 0,
-	.pixclock        = 0,
-	.left_margin     = 0,
-	.right_margin    = 0,
-	.upper_margin    = 0,
-	.lower_margin    = 0,
-	.hsync_len       = 0,
-	.vsync_len       = 0,
-	.sync            = 0,
-	.vmode           = FB_VMODE_NONINTERLACED,
-};
-
-#define MODE_INDEX_NONE           0  /* index for mode=none */
-
-/* Boot-time parameters */
-static int sisfb_off = 0;
-static int sisfb_parm_mem = 0;
-static int sisfb_accel = -1;
-static int sisfb_ypan = -1;
-static int sisfb_max = -1;
-static int sisfb_userom = 1;
-static int sisfb_useoem = -1;
-static int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
-static int sisfb_parm_rate = -1;
-static int sisfb_crt1off = 0;
-static int sisfb_forcecrt1 = -1;
-static int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
-static int sisfb_crt2flags = 0;
-static int sisfb_pdc = 0xff;
-static int sisfb_pdca = 0xff;
-static int sisfb_scalelcd = -1;
-static int sisfb_specialtiming = CUT_NONE;
-static int sisfb_lvdshl = -1;
-static int sisfb_dstn = 0;
-static int sisfb_fstn = 0;
-static int sisfb_tvplug = -1;		/* Tv plug type (for overriding autodetection) */
-static int sisfb_tvstd  = -1;
-static int sisfb_tvxposoffset = 0;
-static int sisfb_tvyposoffset = 0;
-static int sisfb_nocrt2rate = 0;
-#if !defined(__i386__) && !defined(__x86_64__)
-static int sisfb_resetcard = 0;
-static int sisfb_videoram = 0;
-#endif
-
-/* List of supported chips */
-static struct sisfb_chip_info {
-	int		chip;
-	int		vgaengine;
-	int		mni;
-	int		hwcursor_size;
-	int		CRT2_write_enable;
-	const char	*chip_name;
-} sisfb_chip_info[] = {
-	{ SIS_300,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
-	{ SIS_540,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
-	{ SIS_630,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
-	{ SIS_315H,   SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
-	{ SIS_315,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
-	{ SIS_315PRO, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
-	{ SIS_550,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
-	{ SIS_650,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
-	{ SIS_330,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
-	{ SIS_660,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
-	{ XGI_20,     SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI Z7" },
-	{ XGI_40,     SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI V3XT/V5/V8" },
-};
-
-static struct pci_device_id sisfb_pci_table[] = {
-#ifdef CONFIG_FB_SIS_300
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
-#endif
-#ifdef CONFIG_FB_SIS_315
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
-	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
-	{ PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_20,     PCI_ANY_ID, PCI_ANY_ID, 0, 0,10},
-	{ PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_40,     PCI_ANY_ID, PCI_ANY_ID, 0, 0,11},
-#endif
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
-
-static struct sis_video_info *card_list = NULL;
-
-/* The memory heap is now handled card-wise, by using
-   sis_malloc_new/sis_free_new. However, the DRM does
-   not do this yet. Until it does, we keep a "global"
-   heap which is actually the first card's one.
- */
-static struct SIS_HEAP	*sisfb_heap;
-
-#define MD_SIS300 1
-#define MD_SIS315 2
-
-/* Mode table */
-static const struct _sisbios_mode {
-	char name[15];
-	u8  mode_no[2];
-	u16 vesa_mode_no_1;  /* "SiS defined" VESA mode number */
-	u16 vesa_mode_no_2;  /* Real VESA mode numbers */
-	u16 xres;
-	u16 yres;
-	u16 bpp;
-	u16 rate_idx;
-	u16 cols;
-	u16 rows;
-	u8  chipset;
-} sisbios_mode[] = {
-/*0*/	{"none",         {0xff,0xff}, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_SIS300|MD_SIS315},
-	{"320x200x8",    {0x59,0x59}, 0x0138, 0x0000,  320,  200,  8, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x200x16",   {0x41,0x41}, 0x010e, 0x0000,  320,  200, 16, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x200x24",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},  /* That's for people who mix up color- and fb depth */
-	{"320x200x32",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x240x8",    {0x50,0x50}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x16",   {0x56,0x56}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x24",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x32",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
-#define MODE_FSTN_8	9
-#define MODE_FSTN_16	10
-	{"320x240x8",    {0x5a,0x5a}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15,           MD_SIS315},  /* FSTN */
-/*10*/	{"320x240x16",   {0x5b,0x5b}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15,           MD_SIS315},  /* FSTN */
-	{"400x300x8",    {0x51,0x51}, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x16",   {0x57,0x57}, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x24",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x32",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"512x384x8",    {0x52,0x52}, 0x0000, 0x0000,  512,  384,  8, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x16",   {0x58,0x58}, 0x0000, 0x0000,  512,  384, 16, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x24",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x32",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"640x400x8",    {0x2f,0x2f}, 0x0000, 0x0000,  640,  400,  8, 1,  80, 25, MD_SIS300|MD_SIS315},
-/*20*/	{"640x400x16",   {0x5d,0x5d}, 0x0000, 0x0000,  640,  400, 16, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x24",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x32",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x480x8",    {0x2e,0x2e}, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x16",   {0x44,0x44}, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x24",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x32",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"720x480x8",    {0x31,0x31}, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x16",   {0x33,0x33}, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x24",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-/*30*/	{"720x480x32",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x576x8",    {0x32,0x32}, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x16",   {0x34,0x34}, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x24",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x32",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"768x576x8",    {0x5f,0x5f}, 0x0000, 0x0000,  768,  576,  8, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x16",   {0x60,0x60}, 0x0000, 0x0000,  768,  576, 16, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x24",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x32",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"800x480x8",    {0x70,0x70}, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_SIS300|MD_SIS315},
-/*40*/	{"800x480x16",   {0x7a,0x7a}, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x24",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x32",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
-#define DEFAULT_MODE		43 /* index for 800x600x8 */
-#define DEFAULT_LCDMODE		43 /* index for 800x600x8 */
-#define DEFAULT_TVMODE		43 /* index for 800x600x8 */
-	{"800x600x8",    {0x30,0x30}, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x16",   {0x47,0x47}, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x24",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x32",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"848x480x8",    {0x39,0x39}, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
-#define DEFAULT_MODE_848	48
-	{"848x480x16",   {0x3b,0x3b}, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"848x480x24",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
-/*50*/	{"848x480x32",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"856x480x8",    {0x3f,0x3f}, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
-#define DEFAULT_MODE_856	52
-	{"856x480x16",   {0x42,0x42}, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x24",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x32",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"960x540x8",    {0x1d,0x1d}, 0x0000, 0x0000,  960,  540,  8, 1, 120, 33,           MD_SIS315},
-	{"960x540x16",   {0x1e,0x1e}, 0x0000, 0x0000,  960,  540, 16, 1, 120, 33,           MD_SIS315},
-	{"960x540x24",   {0x1f,0x1f}, 0x0000, 0x0000,  960,  540, 32, 1, 120, 33,           MD_SIS315},
-	{"960x540x32",   {0x1f,0x1f}, 0x0000, 0x0000,  960,  540, 32, 1, 120, 33,           MD_SIS315},
-	{"960x600x8",    {0x20,0x20}, 0x0000, 0x0000,  960,  600,  8, 1, 120, 37,           MD_SIS315},
-/*60*/	{"960x600x16",   {0x21,0x21}, 0x0000, 0x0000,  960,  600, 16, 1, 120, 37,           MD_SIS315},
-	{"960x600x24",   {0x22,0x22}, 0x0000, 0x0000,  960,  600, 32, 1, 120, 37,           MD_SIS315},
-	{"960x600x32",   {0x22,0x22}, 0x0000, 0x0000,  960,  600, 32, 1, 120, 37,           MD_SIS315},
-	{"1024x576x8",   {0x71,0x71}, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x16",  {0x74,0x74}, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x24",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x32",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x600x8",   {0x20,0x20}, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_SIS300          },
-	{"1024x600x16",  {0x21,0x21}, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_SIS300          },
-	{"1024x600x24",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
-/*70*/	{"1024x600x32",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
-	{"1024x768x8",   {0x38,0x38}, 0x0105, 0x0105, 1024,  768,  8, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x16",  {0x4a,0x4a}, 0x0117, 0x0117, 1024,  768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x24",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x32",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1152x768x8",   {0x23,0x23}, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_SIS300          },
-	{"1152x768x16",  {0x24,0x24}, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_SIS300          },
-	{"1152x768x24",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
-	{"1152x768x32",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
-	{"1152x864x8",   {0x29,0x29}, 0x0000, 0x0000, 1152,  864,  8, 1, 144, 54, MD_SIS300|MD_SIS315},
-/*80*/	{"1152x864x16",  {0x2a,0x2a}, 0x0000, 0x0000, 1152,  864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x24",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x32",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1280x720x8",   {0x79,0x79}, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x16",  {0x75,0x75}, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x24",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x32",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x768x8",   {0x55,0x23}, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x16",  {0x5a,0x24}, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x24",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-/*90*/	{"1280x768x32",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x800x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
-	{"1280x800x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
-	{"1280x800x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
-	{"1280x800x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
-	{"1280x854x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  854,  8, 1, 160, 53,           MD_SIS315},
-	{"1280x854x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  854, 16, 1, 160, 53,           MD_SIS315},
-	{"1280x854x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  854, 32, 1, 160, 53,           MD_SIS315},
-	{"1280x854x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  854, 32, 1, 160, 53,           MD_SIS315},
-	{"1280x960x8",   {0x7c,0x7c}, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
-/*100*/	{"1280x960x16",  {0x7d,0x7d}, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x24",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x32",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x1024x8",  {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1360x768x8",   {0x48,0x48}, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x16",  {0x4b,0x4b}, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x24",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
-/*110*/	{"1360x768x32",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x1024x8",  {0x67,0x67}, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
-#define DEFAULT_MODE_1360	112
-	{"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
-	{"1400x1050x8",  {0x26,0x26}, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
-	{"1600x1200x8",  {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
-/*120*/	{"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1680x1050x8",  {0x17,0x17}, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
-	{"1920x1080x8",  {0x2c,0x2c}, 0x0000, 0x0000, 1920, 1080,  8, 1, 240, 67,           MD_SIS315},
-	{"1920x1080x16", {0x2d,0x2d}, 0x0000, 0x0000, 1920, 1080, 16, 1, 240, 67,           MD_SIS315},
-	{"1920x1080x24", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
-/*130*/	{"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
-	{"1920x1440x8",  {0x68,0x68}, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"2048x1536x8",  {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x32", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
-	{"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
-};
-
-#define SIS_LCD_NUMBER 18
-static struct _sis_lcd_data {
-	u32 lcdtype;
-	u16 xres;
-	u16 yres;
-	u8  default_mode_idx;
-} sis_lcd_data[] = {
-	{ LCD_640x480,    640,  480,  23 },
-	{ LCD_800x600,    800,  600,  43 },
-	{ LCD_1024x600,  1024,  600,  67 },
-	{ LCD_1024x768,  1024,  768,  71 },
-	{ LCD_1152x768,  1152,  768,  75 },
-	{ LCD_1152x864,  1152,  864,  79 },
-	{ LCD_1280x720,  1280,  720,  83 },
-	{ LCD_1280x768,  1280,  768,  87 },
-	{ LCD_1280x800,  1280,  800,  91 },
-	{ LCD_1280x854,  1280,  854,  95 },
-	{ LCD_1280x960,  1280,  960,  99 },
-	{ LCD_1280x1024, 1280, 1024, 103 },
-	{ LCD_1400x1050, 1400, 1050, 115 },
-	{ LCD_1680x1050, 1680, 1050, 123 },
-	{ LCD_1600x1200, 1600, 1200, 119 },
-	{ LCD_320x240_2,  320,  240,   9 },
-	{ LCD_320x240_3,  320,  240,   9 },
-	{ LCD_320x240,    320,  240,   9 },
-};
-
-/* CR36 evaluation */
-static unsigned short sis300paneltype[] = {
-	LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
-	LCD_1280x960,  LCD_640x480,   LCD_1024x600,  LCD_1152x768,
-	LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
-	LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN
-};
-
-static unsigned short sis310paneltype[] = {
-	LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
-	LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
-	LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
-	LCD_320x240_2, LCD_320x240_3, LCD_UNKNOWN,   LCD_UNKNOWN
-};
-
-static unsigned short sis661paneltype[] = {
-	LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
-	LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
-	LCD_1280x854,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
-	LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_UNKNOWN
-};
-
-#define FL_550_DSTN 0x01
-#define FL_550_FSTN 0x02
-#define FL_300      0x04
-#define FL_315      0x08
-
-static struct _sis_crt2type {
-	char name[32];
-	u32 type_no;
-	u32 tvplug_no;
-	u16 flags;
-} sis_crt2type[] __initdata = {
-	{"NONE", 	     0, 	-1,                     FL_300|FL_315},
-	{"LCD",  	     CRT2_LCD, 	-1,                     FL_300|FL_315},
-	{"TV",   	     CRT2_TV, 	-1,                     FL_300|FL_315},
-	{"VGA",  	     CRT2_VGA, 	-1,                     FL_300|FL_315},
-	{"SVIDEO", 	     CRT2_TV, 	TV_SVIDEO,              FL_300|FL_315},
-	{"COMPOSITE", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
-	{"CVBS", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
-	{"SVIDEO+COMPOSITE", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
-	{"COMPOSITE+SVIDEO", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
-	{"SVIDEO+CVBS",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
-	{"CVBS+SVIDEO",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
-	{"SCART", 	     CRT2_TV, 	TV_SCART,               FL_300|FL_315},
-	{"HIVISION",	     CRT2_TV,   TV_HIVISION,            FL_315},
-	{"YPBPR480I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525I,  FL_315},
-	{"YPBPR480P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525P,  FL_315},
-	{"YPBPR720P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR750P,  FL_315},
-	{"YPBPR1080I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR1080I, FL_315},
-	{"DSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_DSTN},
-	{"FSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_FSTN},
-	{"\0",  	     -1, 	-1,                     0}
-};
-
-/* TV standard */
-static struct _sis_tvtype {
-	char name[6];
-	u32 type_no;
-} sis_tvtype[] __initdata = {
-	{"PAL",  	TV_PAL},
-	{"NTSC", 	TV_NTSC},
-	{"PALM",  	TV_PAL|TV_PALM},
-	{"PALN",  	TV_PAL|TV_PALN},
-	{"NTSCJ",  	TV_NTSC|TV_NTSCJ},
-	{"\0",   	-1}
-};
-
-static const struct _sis_vrate {
-	u16 idx;
-	u16 xres;
-	u16 yres;
-	u16 refresh;
-	bool SiS730valid32bpp;
-} sisfb_vrate[] = {
-	{1,  320,  200,  70,  true},
-	{1,  320,  240,  60,  true},
-	{1,  400,  300,  60,  true},
-	{1,  512,  384,  60,  true},
-	{1,  640,  400,  72,  true},
-	{1,  640,  480,  60,  true}, {2,  640,  480,  72,  true}, {3,  640,  480,  75,  true},
-	{4,  640,  480,  85,  true}, {5,  640,  480, 100,  true}, {6,  640,  480, 120,  true},
-	{7,  640,  480, 160,  true}, {8,  640,  480, 200,  true},
-	{1,  720,  480,  60,  true},
-	{1,  720,  576,  58,  true},
-	{1,  768,  576,  58,  true},
-	{1,  800,  480,  60,  true}, {2,  800,  480,  75,  true}, {3,  800,  480,  85,  true},
-	{1,  800,  600,  56,  true}, {2,  800,  600,  60,  true}, {3,  800,  600,  72,  true},
-	{4,  800,  600,  75,  true}, {5,  800,  600,  85,  true}, {6,  800,  600, 105,  true},
-	{7,  800,  600, 120,  true}, {8,  800,  600, 160,  true},
-	{1,  848,  480,  39,  true}, {2,  848,  480,  60,  true},
-	{1,  856,  480,  39,  true}, {2,  856,  480,  60,  true},
-	{1,  960,  540,  60,  true},
-	{1,  960,  600,  60,  true},
-	{1, 1024,  576,  60,  true}, {2, 1024,  576,  75,  true}, {3, 1024,  576,  85,  true},
-	{1, 1024,  600,  60,  true},
-	{1, 1024,  768,  43,  true}, {2, 1024,  768,  60,  true}, {3, 1024,  768,  70, false},
-	{4, 1024,  768,  75, false}, {5, 1024,  768,  85,  true}, {6, 1024,  768, 100,  true},
-	{7, 1024,  768, 120,  true},
-	{1, 1152,  768,  60,  true},
-	{1, 1152,  864,  60,  true}, {2, 1152,  864,  75,  true}, {3, 1152,  864,  84,  true},
-	{1, 1280,  720,  60,  true}, {2, 1280,  720,  75,  true}, {3, 1280,  720,  85,  true},
-	{1, 1280,  768,  60,  true},
-	{1, 1280,  800,  60,  true},
-	{1, 1280,  854,  60,  true},
-	{1, 1280,  960,  60,  true}, {2, 1280,  960,  85,  true},
-	{1, 1280, 1024,  43,  true}, {2, 1280, 1024,  60,  true}, {3, 1280, 1024,  75,  true},
-	{4, 1280, 1024,  85,  true},
-	{1, 1360,  768,  60,  true},
-	{1, 1360, 1024,  59,  true},
-	{1, 1400, 1050,  60,  true}, {2, 1400, 1050,  75,  true},
-	{1, 1600, 1200,  60,  true}, {2, 1600, 1200,  65,  true}, {3, 1600, 1200,  70,  true},
-	{4, 1600, 1200,  75,  true}, {5, 1600, 1200,  85,  true}, {6, 1600, 1200, 100,  true},
-	{7, 1600, 1200, 120,  true},
-	{1, 1680, 1050,  60,  true},
-	{1, 1920, 1080,  30,  true},
-	{1, 1920, 1440,  60,  true}, {2, 1920, 1440,  65,  true}, {3, 1920, 1440,  70,  true},
-	{4, 1920, 1440,  75,  true}, {5, 1920, 1440,  85,  true}, {6, 1920, 1440, 100,  true},
-	{1, 2048, 1536,  60,  true}, {2, 2048, 1536,  65,  true}, {3, 2048, 1536,  70,  true},
-	{4, 2048, 1536,  75,  true}, {5, 2048, 1536,  85,  true},
-	{0,    0,    0,   0, false}
-};
-
-static struct _sisfbddcsmodes {
-	u32 mask;
-	u16 h;
-	u16 v;
-	u32 d;
-} sisfb_ddcsmodes[] = {
-	{ 0x10000, 67, 75, 108000},
-	{ 0x08000, 48, 72,  50000},
-	{ 0x04000, 46, 75,  49500},
-	{ 0x01000, 35, 43,  44900},
-	{ 0x00800, 48, 60,  65000},
-	{ 0x00400, 56, 70,  75000},
-	{ 0x00200, 60, 75,  78800},
-	{ 0x00100, 80, 75, 135000},
-	{ 0x00020, 31, 60,  25200},
-	{ 0x00008, 38, 72,  31500},
-	{ 0x00004, 37, 75,  31500},
-	{ 0x00002, 35, 56,  36000},
-	{ 0x00001, 38, 60,  40000}
-};
-
-static struct _sisfbddcfmodes {
-	u16 x;
-	u16 y;
-	u16 v;
-	u16 h;
-	u32 d;
-} sisfb_ddcfmodes[] = {
-	{ 1280, 1024, 85, 92, 157500},
-	{ 1600, 1200, 60, 75, 162000},
-	{ 1600, 1200, 65, 82, 175500},
-	{ 1600, 1200, 70, 88, 189000},
-	{ 1600, 1200, 75, 94, 202500},
-	{ 1600, 1200, 85, 107,229500},
-	{ 1920, 1440, 60, 90, 234000},
-	{ 1920, 1440, 75, 113,297000}
-};
-
-#ifdef CONFIG_FB_SIS_300
-static struct _chswtable {
-	u16  subsysVendor;
-	u16  subsysCard;
-	char *vendorName;
-	char *cardName;
-} mychswtable[] = {
-	{ 0x1631, 0x1002, "Mitachi", "0x1002" },
-	{ 0x1071, 0x7521, "Mitac"  , "7521P"  },
-	{ 0,      0,      ""       , ""       }
-};
-#endif
-
-static struct _customttable {
-	u16   chipID;
-	char  *biosversion;
-	char  *biosdate;
-	u32   bioschksum;
-	u16   biosFootprintAddr[5];
-	u8    biosFootprintData[5];
-	u16   pcisubsysvendor;
-	u16   pcisubsyscard;
-	char  *vendorName;
-	char  *cardName;
-	u32   SpecialID;
-	char  *optionName;
-} mycustomttable[] = {
-	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
-	  0x3240A8,
-	  { 0x220, 0x227, 0x228, 0x229, 0x0ee },
-	  {  0x01,  0xe3,  0x9a,  0x6a,  0xef },
-	  0x1039, 0x6300,
-	  "Barco", "iQ R200L/300/400", CUT_BARCO1366, "BARCO_1366"
-	},
-	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
-	  0x323FBD,
-	  { 0x220, 0x227, 0x228, 0x229, 0x0ee },
-	  {  0x00,  0x5a,  0x64,  0x41,  0xef },
-	  0x1039, 0x6300,
-	  "Barco", "iQ G200L/300/400/500", CUT_BARCO1024, "BARCO_1024"
-	},
-	{ SIS_650, "", "",
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x0e11, 0x083c,
-	  "Inventec (Compaq)", "3017cl/3045US", CUT_COMPAQ12802, "COMPAQ_1280"
-	},
-	{ SIS_650, "", "",
-	  0,
-	  { 0x00c, 0, 0, 0, 0 },
-	  { 'e'  , 0, 0, 0, 0 },
-	  0x1558, 0x0287,
-	  "Clevo", "L285/L287 (Version 1)", CUT_CLEVO1024, "CLEVO_L28X_1"
-	},
-	{ SIS_650, "", "",
-	  0,
-	  { 0x00c, 0, 0, 0, 0 },
-	  { 'y'  , 0, 0, 0, 0 },
-	  0x1558, 0x0287,
-	  "Clevo", "L285/L287 (Version 2)", CUT_CLEVO10242, "CLEVO_L28X_2"
-	},
-	{ SIS_650, "", "",
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1558, 0x0400,  /* possibly 401 and 402 as well; not panelsize specific (?) */
-	  "Clevo", "D400S/D410S/D400H/D410H", CUT_CLEVO1400, "CLEVO_D4X0"
-	},
-	{ SIS_650, "", "",
-	  0,	/* Shift LCD in LCD-via-CRT1 mode */
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1558, 0x2263,
-	  "Clevo", "D22ES/D27ES", CUT_UNIWILL1024, "CLEVO_D2X0ES"
-	},
-	{ SIS_650, "", "",
-	  0,	/* Shift LCD in LCD-via-CRT1 mode */
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1734, 0x101f,
-	  "Uniwill", "N243S9", CUT_UNIWILL1024, "UNIWILL_N243S9"
-	},
-	{ SIS_650, "", "",
-	  0,	/* Shift LCD in LCD-via-CRT1 mode */
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1584, 0x5103,
-	  "Uniwill", "N35BS1", CUT_UNIWILL10242, "UNIWILL_N35BS1"
-	},
-	{ SIS_650, "1.09.2c", "",  /* Other versions, too? */
-	  0,	/* Shift LCD in LCD-via-CRT1 mode */
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1019, 0x0f05,
-	  "ECS", "A928", CUT_UNIWILL1024, "ECS_A928"
-	},
-	{ SIS_740, "1.11.27a", "",
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1043, 0x1612,
-	  "Asus", "L3000D/L3500D", CUT_ASUSL3000D, "ASUS_L3X00"
-	},
-	{ SIS_650, "1.10.9k", "",
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1025, 0x0028,
-	  "Acer", "Aspire 1700", CUT_ACER1280, "ACER_ASPIRE1700"
-	},
-	{ SIS_650, "1.10.7w", "",
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x14c0, 0x0012,
-	  "Compal", "??? (V1)", CUT_COMPAL1400_1, "COMPAL_1400_1"
-	},
-	{ SIS_650, "1.10.7x", "",
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x14c0, 0x0012,
-	  "Compal", "??? (V2)", CUT_COMPAL1400_2, "COMPAL_1400_2"
-	},
-	{ SIS_650, "1.10.8o", "",
-	  0,	/* For EMI (unknown) */
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1043, 0x1612,
-	  "Asus", "A2H (V1)", CUT_ASUSA2H_1, "ASUS_A2H_1"
-	},
-	{ SIS_650, "1.10.8q", "",
-	  0,	/* For EMI */
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0x1043, 0x1612,
-	  "Asus", "A2H (V2)", CUT_ASUSA2H_2, "ASUS_A2H_2"
-	},
-	{ 4321, "", "",			/* never autodetected */
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0, 0,
-	  "Generic", "LVDS/Parallel 848x480", CUT_PANEL848, "PANEL848x480"
-	},
-	{ 4322, "", "",			/* never autodetected */
-	  0,
-	  { 0, 0, 0, 0, 0 },
-	  { 0, 0, 0, 0, 0 },
-	  0, 0,
-	  "Generic", "LVDS/Parallel 856x480", CUT_PANEL856, "PANEL856x480"
-	},
-	{ 0, "", "",
-	  0,
-	  { 0, 0, 0, 0 },
-	  { 0, 0, 0, 0 },
-	  0, 0,
-	  "", "", CUT_NONE, ""
-	}
-};
-
-/* ---------------------- Prototypes ------------------------- */
-
-/* Interface used by the world */
-#ifndef MODULE
-static int sisfb_setup(char *options);
-#endif
-
-/* Interface to the low level console driver */
-static int sisfb_init(void);
-
-/* fbdev routines */
-static int	sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-				struct fb_info *info);
-
-static int	sisfb_ioctl(struct fb_info *info, unsigned int cmd,
-			    unsigned long arg);
-static int	sisfb_set_par(struct fb_info *info);
-static int	sisfb_blank(int blank,
-				struct fb_info *info);
-extern void	fbcon_sis_fillrect(struct fb_info *info,
-				const struct fb_fillrect *rect);
-extern void	fbcon_sis_copyarea(struct fb_info *info,
-				const struct fb_copyarea *area);
-extern int	fbcon_sis_sync(struct fb_info *info);
-
-/* Internal 2D accelerator functions */
-extern int	sisfb_initaccel(struct sis_video_info *ivideo);
-extern void	sisfb_syncaccel(struct sis_video_info *ivideo);
-
-/* Internal general routines */
-static void	sisfb_search_mode(char *name, bool quiet);
-static int	sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
-static u8	sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
-				int index);
-static int	sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-				unsigned blue, unsigned transp,
-				struct fb_info *fb_info);
-static int	sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
-				struct fb_info *info);
-static void	sisfb_pre_setmode(struct sis_video_info *ivideo);
-static void	sisfb_post_setmode(struct sis_video_info *ivideo);
-static bool	sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
-static bool	sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
-static bool	sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
-static bool	sisfb_bridgeisslave(struct sis_video_info *ivideo);
-static void	sisfb_detect_VB_connect(struct sis_video_info *ivideo);
-static void	sisfb_get_VB_type(struct sis_video_info *ivideo);
-static void	sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
-static void	sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
-#ifdef CONFIG_FB_SIS_300
-unsigned int	sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-void		sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val);
-unsigned int	sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-#endif
-#ifdef CONFIG_FB_SIS_315
-void		sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val);
-unsigned int	sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
-#endif
-
-/* SiS-specific exported functions */
-void			sis_malloc(struct sis_memreq *req);
-void			sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
-void			sis_free(u32 base);
-void			sis_free_new(struct pci_dev *pdev, u32 base);
-
-/* Internal heap routines */
-static int		sisfb_heap_init(struct sis_video_info *ivideo);
-static struct SIS_OH *	sisfb_poh_new_node(struct SIS_HEAP *memheap);
-static struct SIS_OH *	sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
-static void		sisfb_delete_node(struct SIS_OH *poh);
-static void		sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
-static struct SIS_OH *	sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
-static void		sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
-
-/* Routines from init.c/init301.c */
-extern unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, bool FSTN, unsigned short CustomT,
-				int LCDwith, int LCDheight, unsigned int VBFlags2);
-extern unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, unsigned int VBFlags2);
-extern unsigned short	SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, unsigned int VBFlags2);
-extern void		SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-extern bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
-extern void		SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
-extern void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
-
-extern bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
-
-extern bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
-				int *htotal, int *vtotal, unsigned char rateindex);
-extern int		sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
-				unsigned char modeno, unsigned char rateindex);
-extern int		sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
-				unsigned char rateindex, struct fb_var_screeninfo *var);
-
-/* Chrontel TV, DDC and DPMS functions */
-extern unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg);
-extern void		SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-extern unsigned short	SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg);
-extern void		SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-extern void		SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
-				unsigned char myor, unsigned char myand);
-extern void		SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
-extern void		SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
-extern unsigned short	SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
-				unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
-				unsigned int VBFlags2);
-extern unsigned short	SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
-#ifdef CONFIG_FB_SIS_315
-extern void		SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
-extern void		SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
-#endif
-extern void		SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
-extern void		SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
-#endif
-
-
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
deleted file mode 100644
index e3f9976cfef0..000000000000
--- a/drivers/video/sis/vgatypes.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * General type definitions for universal mode switching modules
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-#ifndef _VGATYPES_H_
-#define _VGATYPES_H_
-
-#define SISIOMEMTYPE
-
-typedef unsigned long SISIOADDRESS;
-#include <linux/types.h>  /* Need __iomem */
-#undef SISIOMEMTYPE
-#define SISIOMEMTYPE __iomem
-
-typedef enum _SIS_CHIP_TYPE {
-    SIS_VGALegacy = 0,
-    SIS_530,
-    SIS_OLD,
-    SIS_300,
-    SIS_630,
-    SIS_730,
-    SIS_540,
-    SIS_315H,   /* SiS 310 */
-    SIS_315,
-    SIS_315PRO, /* SiS 325 */
-    SIS_550,
-    SIS_650,
-    SIS_740,
-    SIS_330,
-    SIS_661,
-    SIS_741,
-    SIS_670,
-    SIS_660 = 35,
-    SIS_760,
-    SIS_761,
-    SIS_762,
-    SIS_770,
-    SIS_340 = 55,
-    SIS_341,
-    SIS_342,
-    XGI_20  = 75,
-    XGI_21,
-    XGI_40,
-    MAX_SIS_CHIP
-} SIS_CHIP_TYPE;
-
-
-#endif
-
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
deleted file mode 100644
index ea94d214dcff..000000000000
--- a/drivers/video/sis/vstruct.h
+++ /dev/null
@@ -1,551 +0,0 @@
-/* $XFree86$ */
-/* $XdotOrg$ */
-/*
- * General structure definitions for universal mode switching modules
- *
- * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
- *
- * If distributed as part of the Linux kernel, the following license terms
- * apply:
- *
- * * This program is free software; you can redistribute it and/or modify
- * * it under the terms of the GNU General Public License as published by
- * * the Free Software Foundation; either version 2 of the named License,
- * * or any later version.
- * *
- * * This program is distributed in the hope that it will be useful,
- * * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * * GNU General Public License for more details.
- * *
- * * You should have received a copy of the GNU General Public License
- * * along with this program; if not, write to the Free Software
- * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Otherwise, the following license terms apply:
- *
- * * Redistribution and use in source and binary forms, with or without
- * * modification, are permitted provided that the following conditions
- * * are met:
- * * 1) Redistributions of source code must retain the above copyright
- * *    notice, this list of conditions and the following disclaimer.
- * * 2) Redistributions in binary form must reproduce the above copyright
- * *    notice, this list of conditions and the following disclaimer in the
- * *    documentation and/or other materials provided with the distribution.
- * * 3) The name of the author may not be used to endorse or promote products
- * *    derived from this software without specific prior written permission.
- * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
- *
- */
-
-#ifndef _VSTRUCT_H_
-#define _VSTRUCT_H_
-
-struct SiS_PanelDelayTbl {
- 	unsigned char timer[2];
-};
-
-struct SiS_LCDData {
-	unsigned short RVBHCMAX;
-	unsigned short RVBHCFACT;
-	unsigned short VGAHT;
-	unsigned short VGAVT;
-	unsigned short LCDHT;
-	unsigned short LCDVT;
-};
-
-struct SiS_TVData {
-	unsigned short RVBHCMAX;
-	unsigned short RVBHCFACT;
-	unsigned short VGAHT;
-	unsigned short VGAVT;
-	unsigned short TVHDE;
-	unsigned short TVVDE;
-	unsigned short RVBHRS;
-	unsigned char  FlickerMode;
-	unsigned short HALFRVBHRS;
-	unsigned short RVBHRS2;
-	unsigned char  RY1COE;
-	unsigned char  RY2COE;
-	unsigned char  RY3COE;
-	unsigned char  RY4COE;
-};
-
-struct SiS_LVDSData {
-	unsigned short VGAHT;
-	unsigned short VGAVT;
-	unsigned short LCDHT;
-	unsigned short LCDVT;
-};
-
-struct SiS_LVDSDes {
-	unsigned short LCDHDES;
-	unsigned short LCDVDES;
-};
-
-struct SiS_LVDSCRT1Data {
-	unsigned char  CR[15];
-};
-
-struct SiS_CHTVRegData {
-	unsigned char  Reg[16];
-};
-
-struct SiS_St {
-	unsigned char  St_ModeID;
-	unsigned short St_ModeFlag;
-	unsigned char  St_StTableIndex;
-	unsigned char  St_CRT2CRTC;
-	unsigned char  St_ResInfo;
-	unsigned char  VB_StTVFlickerIndex;
-	unsigned char  VB_StTVEdgeIndex;
-	unsigned char  VB_StTVYFilterIndex;
-	unsigned char  St_PDC;
-};
-
-struct SiS_VBMode {
-	unsigned char  ModeID;
-	unsigned char  VB_TVDelayIndex;
-	unsigned char  VB_TVFlickerIndex;
-	unsigned char  VB_TVPhaseIndex;
-	unsigned char  VB_TVYFilterIndex;
-	unsigned char  VB_LCDDelayIndex;
-	unsigned char  _VB_LCDHIndex;
-	unsigned char  _VB_LCDVIndex;
-};
-
-struct SiS_StandTable_S {
-	unsigned char  CRT_COLS;
-	unsigned char  ROWS;
-	unsigned char  CHAR_HEIGHT;
-	unsigned short CRT_LEN;
-	unsigned char  SR[4];
-	unsigned char  MISC;
-	unsigned char  CRTC[0x19];
-	unsigned char  ATTR[0x14];
-	unsigned char  GRC[9];
-};
-
-struct SiS_Ext {
-	unsigned char  Ext_ModeID;
-	unsigned short Ext_ModeFlag;
-	unsigned short Ext_VESAID;
-	unsigned char  Ext_RESINFO;
-	unsigned char  VB_ExtTVFlickerIndex;
-	unsigned char  VB_ExtTVEdgeIndex;
-	unsigned char  VB_ExtTVYFilterIndex;
-	unsigned char  VB_ExtTVYFilterIndexROM661;
-	unsigned char  REFindex;
-	char           ROMMODEIDX661;
-};
-
-struct SiS_Ext2 {
-	unsigned short Ext_InfoFlag;
-	unsigned char  Ext_CRT1CRTC;
-	unsigned char  Ext_CRTVCLK;
-	unsigned char  Ext_CRT2CRTC;
-	unsigned char  Ext_CRT2CRTC_NS;
-	unsigned char  ModeID;
-	unsigned short XRes;
-	unsigned short YRes;
-	unsigned char  Ext_PDC;
-	unsigned char  Ext_FakeCRT2CRTC;
-	unsigned char  Ext_FakeCRT2Clk;
-	unsigned char  Ext_CRT1CRTC_NORM;
-	unsigned char  Ext_CRTVCLK_NORM;
-	unsigned char  Ext_CRT1CRTC_WIDE;
-	unsigned char  Ext_CRTVCLK_WIDE;
-};
-
-struct SiS_Part2PortTbl {
- 	unsigned char  CR[12];
-};
-
-struct SiS_CRT1Table {
-	unsigned char  CR[17];
-};
-
-struct SiS_MCLKData {
-	unsigned char  SR28,SR29,SR2A;
-	unsigned short CLOCK;
-};
-
-struct SiS_VCLKData {
-	unsigned char  SR2B,SR2C;
-	unsigned short CLOCK;
-};
-
-struct SiS_VBVCLKData {
-	unsigned char  Part4_A,Part4_B;
-	unsigned short CLOCK;
-};
-
-struct SiS_StResInfo_S {
-	unsigned short HTotal;
-	unsigned short VTotal;
-};
-
-struct SiS_ModeResInfo_S {
-	unsigned short HTotal;
-	unsigned short VTotal;
-	unsigned char  XChar;
-	unsigned char  YChar;
-};
-
-/* Defines for SiS_CustomT */
-/* Never change these for sisfb compatibility */
-#define CUT_NONE		 0
-#define CUT_FORCENONE		 1
-#define CUT_BARCO1366		 2
-#define CUT_BARCO1024		 3
-#define CUT_COMPAQ1280		 4
-#define CUT_COMPAQ12802		 5
-#define CUT_PANEL848		 6
-#define CUT_CLEVO1024		 7
-#define CUT_CLEVO10242		 8
-#define CUT_CLEVO1400		 9
-#define CUT_CLEVO14002		10
-#define CUT_UNIWILL1024		11
-#define CUT_ASUSL3000D		12
-#define CUT_UNIWILL10242	13
-#define CUT_ACER1280		14
-#define CUT_COMPAL1400_1	15
-#define CUT_COMPAL1400_2	16
-#define CUT_ASUSA2H_1		17
-#define CUT_ASUSA2H_2		18
-#define CUT_UNKNOWNLCD		19
-#define CUT_AOP8060		20
-#define CUT_PANEL856		21
-
-struct SiS_Private
-{
-	unsigned char			ChipType;
-	unsigned char			ChipRevision;
-	void				*ivideo;
-	unsigned char 			*VirtualRomBase;
-	bool				UseROM;
-	unsigned char SISIOMEMTYPE	*VideoMemoryAddress;
-	unsigned int			VideoMemorySize;
-	SISIOADDRESS			IOAddress;
-	SISIOADDRESS			IOAddress2;  /* For dual chip XGI volari */
-
-	SISIOADDRESS			RelIO;
-	SISIOADDRESS			SiS_P3c4;
-	SISIOADDRESS			SiS_P3d4;
-	SISIOADDRESS			SiS_P3c0;
-	SISIOADDRESS			SiS_P3ce;
-	SISIOADDRESS			SiS_P3c2;
-	SISIOADDRESS			SiS_P3ca;
-	SISIOADDRESS			SiS_P3c6;
-	SISIOADDRESS			SiS_P3c7;
-	SISIOADDRESS			SiS_P3c8;
-	SISIOADDRESS			SiS_P3c9;
-	SISIOADDRESS			SiS_P3cb;
-	SISIOADDRESS			SiS_P3cc;
-	SISIOADDRESS			SiS_P3cd;
-	SISIOADDRESS			SiS_P3da;
-	SISIOADDRESS			SiS_Part1Port;
-	SISIOADDRESS			SiS_Part2Port;
-	SISIOADDRESS			SiS_Part3Port;
-	SISIOADDRESS			SiS_Part4Port;
-	SISIOADDRESS			SiS_Part5Port;
-	SISIOADDRESS			SiS_VidCapt;
-	SISIOADDRESS			SiS_VidPlay;
-	unsigned short			SiS_IF_DEF_LVDS;
-	unsigned short			SiS_IF_DEF_CH70xx;
-	unsigned short			SiS_IF_DEF_CONEX;
-	unsigned short			SiS_IF_DEF_TRUMPION;
-	unsigned short			SiS_IF_DEF_DSTN;
-	unsigned short			SiS_IF_DEF_FSTN;
-	unsigned short			SiS_SysFlags;
-	unsigned char			SiS_VGAINFO;
-	bool				SiS_UseROM;
-	bool				SiS_ROMNew;
-	bool				SiS_XGIROM;
-	bool				SiS_NeedRomModeData;
-	bool				PanelSelfDetected;
-	bool				DDCPortMixup;
-	int				SiS_CHOverScan;
-	bool				SiS_CHSOverScan;
-	bool				SiS_ChSW;
-	bool				SiS_UseLCDA;
-	int				SiS_UseOEM;
-	unsigned int			SiS_CustomT;
-	int				SiS_UseWide, SiS_UseWideCRT2;
-	int				SiS_TVBlue;
-	unsigned short			SiS_Backup70xx;
-	bool				HaveEMI;
-	bool				HaveEMILCD;
-	bool				OverruleEMI;
-	unsigned char			EMI_30,EMI_31,EMI_32,EMI_33;
-	unsigned short			SiS_EMIOffset;
-	unsigned short			SiS_PWDOffset;
-	short				PDC, PDCA;
-	unsigned char			SiS_MyCR63;
-	unsigned short			SiS_CRT1Mode;
-	unsigned short			SiS_flag_clearbuffer;
-	int				SiS_RAMType;
-	unsigned char			SiS_ChannelAB;
-	unsigned char			SiS_DataBusWidth;
-	unsigned short			SiS_ModeType;
-	unsigned short			SiS_VBInfo;
-	unsigned short			SiS_TVMode;
-	unsigned short			SiS_LCDResInfo;
-	unsigned short			SiS_LCDTypeInfo;
-	unsigned short			SiS_LCDInfo;
-	unsigned short			SiS_LCDInfo661;
-	unsigned short			SiS_VBType;
-	unsigned short			SiS_VBExtInfo;
-	unsigned short			SiS_YPbPr;
-	unsigned short			SiS_SelectCRT2Rate;
-	unsigned short			SiS_SetFlag;
-	unsigned short			SiS_RVBHCFACT;
-	unsigned short			SiS_RVBHCMAX;
-	unsigned short			SiS_RVBHRS;
-	unsigned short			SiS_RVBHRS2;
-	unsigned short			SiS_VGAVT;
-	unsigned short			SiS_VGAHT;
-	unsigned short			SiS_VT;
-	unsigned short			SiS_HT;
-	unsigned short			SiS_VGAVDE;
-	unsigned short			SiS_VGAHDE;
-	unsigned short			SiS_VDE;
-	unsigned short			SiS_HDE;
-	unsigned short			SiS_NewFlickerMode;
-	unsigned short			SiS_RY1COE;
-	unsigned short			SiS_RY2COE;
-	unsigned short			SiS_RY3COE;
-	unsigned short			SiS_RY4COE;
-	unsigned short			SiS_LCDHDES;
-	unsigned short			SiS_LCDVDES;
-	SISIOADDRESS			SiS_DDC_Port;
-	unsigned short			SiS_DDC_Index;
-	unsigned short			SiS_DDC_Data;
-	unsigned short			SiS_DDC_NData;
-	unsigned short			SiS_DDC_Clk;
-	unsigned short			SiS_DDC_NClk;
-	unsigned short			SiS_DDC_DeviceAddr;
-	unsigned short			SiS_DDC_ReadAddr;
-	unsigned short			SiS_DDC_SecAddr;
-	unsigned short			SiS_ChrontelInit;
-	bool				SiS_SensibleSR11;
-	unsigned short			SiS661LCD2TableSize;
-
-	unsigned short			SiS_PanelMinLVDS;
-	unsigned short			SiS_PanelMin301;
-
-	const struct SiS_St		*SiS_SModeIDTable;
-	const struct SiS_StandTable_S	*SiS_StandTable;
-	const struct SiS_Ext		*SiS_EModeIDTable;
-	const struct SiS_Ext2		*SiS_RefIndex;
-	const struct SiS_VBMode		*SiS_VBModeIDTable;
-	const struct SiS_CRT1Table	*SiS_CRT1Table;
-	const struct SiS_MCLKData	*SiS_MCLKData_0;
-	const struct SiS_MCLKData	*SiS_MCLKData_1;
-	struct SiS_VCLKData		*SiS_VCLKData;
-	struct SiS_VBVCLKData		*SiS_VBVCLKData;
-	const struct SiS_StResInfo_S	*SiS_StResInfo;
-	const struct SiS_ModeResInfo_S	*SiS_ModeResInfo;
-
-	const unsigned char		*pSiS_OutputSelect;
-	const unsigned char		*pSiS_SoftSetting;
-
-	const unsigned char		*SiS_SR15;
-
-	const struct SiS_PanelDelayTbl	*SiS_PanelDelayTbl;
-	const struct SiS_PanelDelayTbl	*SiS_PanelDelayTblLVDS;
-
-	/* SiS bridge */
-
-	const struct SiS_LCDData	*SiS_ExtLCD1024x768Data;
-	const struct SiS_LCDData	*SiS_St2LCD1024x768Data;
-	const struct SiS_LCDData	*SiS_LCD1280x720Data;
-	const struct SiS_LCDData	*SiS_StLCD1280x768_2Data;
-	const struct SiS_LCDData	*SiS_ExtLCD1280x768_2Data;
-	const struct SiS_LCDData	*SiS_LCD1280x800Data;
-	const struct SiS_LCDData	*SiS_LCD1280x800_2Data;
-	const struct SiS_LCDData	*SiS_LCD1280x854Data;
-	const struct SiS_LCDData	*SiS_LCD1280x960Data;
-	const struct SiS_LCDData	*SiS_ExtLCD1280x1024Data;
-	const struct SiS_LCDData	*SiS_St2LCD1280x1024Data;
-	const struct SiS_LCDData	*SiS_StLCD1400x1050Data;
-	const struct SiS_LCDData	*SiS_ExtLCD1400x1050Data;
-	const struct SiS_LCDData	*SiS_StLCD1600x1200Data;
-	const struct SiS_LCDData	*SiS_ExtLCD1600x1200Data;
-	const struct SiS_LCDData	*SiS_LCD1680x1050Data;
-	const struct SiS_LCDData	*SiS_NoScaleData;
-	const struct SiS_TVData		*SiS_StPALData;
-	const struct SiS_TVData		*SiS_ExtPALData;
-	const struct SiS_TVData		*SiS_StNTSCData;
-	const struct SiS_TVData		*SiS_ExtNTSCData;
-	const struct SiS_TVData		*SiS_St1HiTVData;
-	const struct SiS_TVData		*SiS_St2HiTVData;
-	const struct SiS_TVData		*SiS_ExtHiTVData;
-	const struct SiS_TVData		*SiS_St525iData;
-	const struct SiS_TVData		*SiS_St525pData;
-	const struct SiS_TVData		*SiS_St750pData;
-	const struct SiS_TVData		*SiS_Ext525iData;
-	const struct SiS_TVData		*SiS_Ext525pData;
-	const struct SiS_TVData		*SiS_Ext750pData;
-	const unsigned char		*SiS_NTSCTiming;
-	const unsigned char		*SiS_PALTiming;
-	const unsigned char		*SiS_HiTVExtTiming;
-	const unsigned char		*SiS_HiTVSt1Timing;
-	const unsigned char		*SiS_HiTVSt2Timing;
-	const unsigned char		*SiS_HiTVGroup3Data;
-	const unsigned char		*SiS_HiTVGroup3Simu;
-#if 0
-	const unsigned char		*SiS_HiTVTextTiming;
-	const unsigned char		*SiS_HiTVGroup3Text;
-#endif
-
-	const struct SiS_Part2PortTbl	*SiS_CRT2Part2_1024x768_1;
-	const struct SiS_Part2PortTbl	*SiS_CRT2Part2_1024x768_2;
-	const struct SiS_Part2PortTbl	*SiS_CRT2Part2_1024x768_3;
-
-	/* LVDS, Chrontel */
-
-	const struct SiS_LVDSData	*SiS_LVDS320x240Data_1;
-	const struct SiS_LVDSData	*SiS_LVDS320x240Data_2;
-	const struct SiS_LVDSData	*SiS_LVDS640x480Data_1;
-	const struct SiS_LVDSData	*SiS_LVDS800x600Data_1;
-	const struct SiS_LVDSData	*SiS_LVDS1024x600Data_1;
-	const struct SiS_LVDSData	*SiS_LVDS1024x768Data_1;
-	const struct SiS_LVDSData	*SiS_LVDSBARCO1366Data_1;
-	const struct SiS_LVDSData	*SiS_LVDSBARCO1366Data_2;
-	const struct SiS_LVDSData	*SiS_LVDSBARCO1024Data_1;
-	const struct SiS_LVDSData	*SiS_LVDS848x480Data_1;
-	const struct SiS_LVDSData	*SiS_LVDS848x480Data_2;
-	const struct SiS_LVDSData	*SiS_CHTVUNTSCData;
-	const struct SiS_LVDSData	*SiS_CHTVONTSCData;
-	const struct SiS_LVDSData	*SiS_CHTVUPALData;
-	const struct SiS_LVDSData	*SiS_CHTVOPALData;
-	const struct SiS_LVDSData	*SiS_CHTVUPALMData;
-	const struct SiS_LVDSData	*SiS_CHTVOPALMData;
-	const struct SiS_LVDSData	*SiS_CHTVUPALNData;
-	const struct SiS_LVDSData	*SiS_CHTVOPALNData;
-	const struct SiS_LVDSData	*SiS_CHTVSOPALData;
-
-	const struct SiS_LVDSDes	*SiS_PanelType04_1a;
-	const struct SiS_LVDSDes	*SiS_PanelType04_2a;
-	const struct SiS_LVDSDes	*SiS_PanelType04_1b;
-	const struct SiS_LVDSDes	*SiS_PanelType04_2b;
-
-	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_1;
-	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_2;
-	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_2_H;
-	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_3;
-	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1320x240_3_H;
-	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1640x480_1;
-	const struct SiS_LVDSCRT1Data	*SiS_LVDSCRT1640x480_1_H;
-	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1UNTSC;
-	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1ONTSC;
-	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1UPAL;
-	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1OPAL;
-	const struct SiS_LVDSCRT1Data	*SiS_CHTVCRT1SOPAL;
-
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_UNTSC;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_ONTSC;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_UPAL;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_OPAL;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_UPALM;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_OPALM;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_UPALN;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_OPALN;
-	const struct SiS_CHTVRegData	*SiS_CHTVReg_SOPAL;
-
-	const unsigned char		*SiS_CHTVVCLKUNTSC;
-	const unsigned char		*SiS_CHTVVCLKONTSC;
-	const unsigned char		*SiS_CHTVVCLKUPAL;
-	const unsigned char		*SiS_CHTVVCLKOPAL;
-	const unsigned char		*SiS_CHTVVCLKUPALM;
-	const unsigned char		*SiS_CHTVVCLKOPALM;
-	const unsigned char		*SiS_CHTVVCLKUPALN;
-	const unsigned char		*SiS_CHTVVCLKOPALN;
-	const unsigned char		*SiS_CHTVVCLKSOPAL;
-
-	unsigned short			PanelXRes, PanelHT;
-	unsigned short			PanelYRes, PanelVT;
-	unsigned short			PanelHRS,  PanelHRE;
-	unsigned short			PanelVRS,  PanelVRE;
-	unsigned short			PanelVCLKIdx300;
-	unsigned short			PanelVCLKIdx315;
-	bool				Alternate1600x1200;
-
-	bool				UseCustomMode;
-	bool				CRT1UsesCustomMode;
-	unsigned short			CHDisplay;
-	unsigned short			CHSyncStart;
-	unsigned short			CHSyncEnd;
-	unsigned short			CHTotal;
-	unsigned short			CHBlankStart;
-	unsigned short			CHBlankEnd;
-	unsigned short			CVDisplay;
-	unsigned short			CVSyncStart;
-	unsigned short			CVSyncEnd;
-	unsigned short			CVTotal;
-	unsigned short			CVBlankStart;
-	unsigned short			CVBlankEnd;
-	unsigned int			CDClock;
-	unsigned int			CFlags;
-	unsigned char			CCRT1CRTC[17];
-	unsigned char			CSR2B;
-	unsigned char			CSR2C;
-	unsigned short			CSRClock;
-	unsigned short			CSRClock_CRT1;
-	unsigned short			CModeFlag;
-	unsigned short			CModeFlag_CRT1;
-	unsigned short			CInfoFlag;
-
-	int				LVDSHL;
-
-	bool				Backup;
-	unsigned char			Backup_Mode;
-	unsigned char			Backup_14;
-	unsigned char			Backup_15;
-	unsigned char			Backup_16;
-	unsigned char			Backup_17;
-	unsigned char			Backup_18;
-	unsigned char			Backup_19;
-	unsigned char			Backup_1a;
-	unsigned char			Backup_1b;
-	unsigned char			Backup_1c;
-	unsigned char			Backup_1d;
-
-	unsigned char			Init_P4_0E;
-
-	int				UsePanelScaler;
-	int				CenterScreen;
-
-	unsigned short			CP_Vendor, CP_Product;
-	bool				CP_HaveCustomData;
-	int				CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
-	int				CP_MaxX, CP_MaxY, CP_MaxClock;
-	unsigned char			CP_PrefSR2B, CP_PrefSR2C;
-	unsigned short			CP_PrefClock;
-	bool				CP_Supports64048075;
-	int				CP_HDisplay[7], CP_VDisplay[7];	/* For Custom LCD panel dimensions */
-	int				CP_HTotal[7], CP_VTotal[7];
-	int				CP_HSyncStart[7], CP_VSyncStart[7];
-	int				CP_HSyncEnd[7], CP_VSyncEnd[7];
-	int				CP_HBlankStart[7], CP_VBlankStart[7];
-	int				CP_HBlankEnd[7], CP_VBlankEnd[7];
-	int				CP_Clock[7];
-	bool				CP_DataValid[7];
-	bool				CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
-};
-
-#endif
-
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
deleted file mode 100644
index fefde7c6add7..000000000000
--- a/drivers/video/skeletonfb.c
+++ /dev/null
@@ -1,1037 +0,0 @@
-/*
- * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
- *
- *  Modified to new api Jan 2001 by James Simmons (jsimmons@transvirtual.com)
- *
- *  Created 28 Dec 1997 by Geert Uytterhoeven
- *
- *
- *  I have started rewriting this driver as a example of the upcoming new API
- *  The primary goal is to remove the console code from fbdev and place it
- *  into fbcon.c. This reduces the code and makes writing a new fbdev driver
- *  easy since the author doesn't need to worry about console internals. It
- *  also allows the ability to run fbdev without a console/tty system on top 
- *  of it. 
- *
- *  First the roles of struct fb_info and struct display have changed. Struct
- *  display will go away. The way the new framebuffer console code will
- *  work is that it will act to translate data about the tty/console in 
- *  struct vc_data to data in a device independent way in struct fb_info. Then
- *  various functions in struct fb_ops will be called to store the device 
- *  dependent state in the par field in struct fb_info and to change the 
- *  hardware to that state. This allows a very clean separation of the fbdev
- *  layer from the console layer. It also allows one to use fbdev on its own
- *  which is a bounus for embedded devices. The reason this approach works is  
- *  for each framebuffer device when used as a tty/console device is allocated
- *  a set of virtual terminals to it. Only one virtual terminal can be active 
- *  per framebuffer device. We already have all the data we need in struct 
- *  vc_data so why store a bunch of colormaps and other fbdev specific data
- *  per virtual terminal. 
- *
- *  As you can see doing this makes the con parameter pretty much useless
- *  for struct fb_ops functions, as it should be. Also having struct  
- *  fb_var_screeninfo and other data in fb_info pretty much eliminates the 
- *  need for get_fix and get_var. Once all drivers use the fix, var, and cmap
- *  fbcon can be written around these fields. This will also eliminate the
- *  need to regenerate struct fb_var_screeninfo, struct fb_fix_screeninfo
- *  struct fb_cmap every time get_var, get_fix, get_cmap functions are called
- *  as many drivers do now. 
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-    /*
-     *  This is just simple sample code.
-     *
-     *  No warranty that it actually compiles.
-     *  Even less warranty that it actually works :-)
-     */
-
-/*
- * Driver data
- */
-static char *mode_option;
-
-/*
- *  If your driver supports multiple boards, you should make the  
- *  below data types arrays, or allocate them dynamically (using kmalloc()). 
- */ 
-
-/* 
- * This structure defines the hardware state of the graphics card. Normally
- * you place this in a header file in linux/include/video. This file usually
- * also includes register information. That allows other driver subsystems
- * and userland applications the ability to use the same header file to 
- * avoid duplicate work and easy porting of software. 
- */
-struct xxx_par;
-
-/*
- * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
- * if we don't use modedb. If we do use modedb see xxxfb_init how to use it
- * to get a fb_var_screeninfo. Otherwise define a default var as well. 
- */
-static struct fb_fix_screeninfo xxxfb_fix = {
-	.id =		"FB's name", 
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	1, 
-	.accel =	FB_ACCEL_NONE,
-};
-
-    /*
-     * 	Modern graphical hardware not only supports pipelines but some 
-     *  also support multiple monitors where each display can have its  
-     *  its own unique data. In this case each display could be  
-     *  represented by a separate framebuffer device thus a separate 
-     *  struct fb_info. Now the struct xxx_par represents the graphics
-     *  hardware state thus only one exist per card. In this case the 
-     *  struct xxx_par for each graphics card would be shared between 
-     *  every struct fb_info that represents a framebuffer on that card. 
-     *  This allows when one display changes it video resolution (info->var) 
-     *  the other displays know instantly. Each display can always be
-     *  aware of the entire hardware state that affects it because they share
-     *  the same xxx_par struct. The other side of the coin is multiple
-     *  graphics cards that pass data around until it is finally displayed
-     *  on one monitor. Such examples are the voodoo 1 cards and high end
-     *  NUMA graphics servers. For this case we have a bunch of pars, each
-     *  one that represents a graphics state, that belong to one struct 
-     *  fb_info. Their you would want to have *par point to a array of device
-     *  states and have each struct fb_ops function deal with all those 
-     *  states. I hope this covers every possible hardware design. If not
-     *  feel free to send your ideas at jsimmons@users.sf.net 
-     */
-
-    /*
-     *  If your driver supports multiple boards or it supports multiple 
-     *  framebuffers, you should make these arrays, or allocate them 
-     *  dynamically using framebuffer_alloc() and free them with
-     *  framebuffer_release().
-     */ 
-static struct fb_info info;
-
-    /* 
-     * Each one represents the state of the hardware. Most hardware have
-     * just one hardware state. These here represent the default state(s). 
-     */
-static struct xxx_par __initdata current_par;
-
-int xxxfb_init(void);
-
-/**
- *	xxxfb_open - Optional function. Called when the framebuffer is
- *		     first accessed.
- *	@info: frame buffer structure that represents a single frame buffer
- *	@user: tell us if the userland (value=1) or the console is accessing
- *	       the framebuffer. 
- *
- *	This function is the first function called in the framebuffer api.
- *	Usually you don't need to provide this function. The case where it 
- *	is used is to change from a text mode hardware state to a graphics
- * 	mode state. 
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int xxxfb_open(struct fb_info *info, int user)
-{
-    return 0;
-}
-
-/**
- *	xxxfb_release - Optional function. Called when the framebuffer 
- *			device is closed. 
- *	@info: frame buffer structure that represents a single frame buffer
- *	@user: tell us if the userland (value=1) or the console is accessing
- *	       the framebuffer. 
- *	
- *	Thus function is called when we close /dev/fb or the framebuffer 
- *	console system is released. Usually you don't need this function.
- *	The case where it is usually used is to go from a graphics state
- *	to a text mode state.
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int xxxfb_release(struct fb_info *info, int user)
-{
-    return 0;
-}
-
-/**
- *      xxxfb_check_var - Optional function. Validates a var passed in. 
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer 
- *
- *	Checks to see if the hardware supports the state requested by
- *	var passed in. This function does not alter the hardware state!!! 
- *	This means the data stored in struct fb_info and struct xxx_par do 
- *      not change. This includes the var inside of struct fb_info. 
- *	Do NOT change these. This function can be called on its own if we
- *	intent to only test a mode and not actually set it. The stuff in 
- *	modedb.c is a example of this. If the var passed in is slightly 
- *	off by what the hardware can support then we alter the var PASSED in
- *	to what we can do.
- *
- *      For values that are off, this function must round them _up_ to the
- *      next value that is supported by the hardware.  If the value is
- *      greater than the highest value supported by the hardware, then this
- *      function must return -EINVAL.
- *
- *      Exception to the above rule:  Some drivers have a fixed mode, ie,
- *      the hardware is already set at boot up, and cannot be changed.  In
- *      this case, it is more acceptable that this function just return
- *      a copy of the currently working var (info->var). Better is to not
- *      implement this function, as the upper layer will do the copying
- *      of the current var for you.
- *
- *      Note:  This is the only function where the contents of var can be
- *      freely adjusted after the driver has been registered. If you find
- *      that you have code outside of this function that alters the content
- *      of var, then you are doing something wrong.  Note also that the
- *      contents of info->var must be left untouched at all times after
- *      driver registration.
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-    /* ... */
-    return 0;	   	
-}
-
-/**
- *      xxxfb_set_par - Optional function. Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *	Using the fb_var_screeninfo in fb_info we set the resolution of the
- *	this particular framebuffer. This function alters the par AND the
- *	fb_fix_screeninfo stored in fb_info. It doesn't not alter var in 
- *	fb_info since we are using that data. This means we depend on the
- *	data in var inside fb_info to be supported by the hardware. 
- *
- *      This function is also used to recover/restore the hardware to a
- *      known working state.
- *
- *	xxxfb_check_var is always called before xxxfb_set_par to ensure that
- *      the contents of var is always valid.
- *
- *	Again if you can't change the resolution you don't need this function.
- *
- *      However, even if your hardware does not support mode changing,
- *      a set_par might be needed to at least initialize the hardware to
- *      a known working state, especially if it came back from another
- *      process that also modifies the same hardware, such as X.
- *
- *      If this is the case, a combination such as the following should work:
- *
- *      static int xxxfb_check_var(struct fb_var_screeninfo *var,
- *                                struct fb_info *info)
- *      {
- *              *var = info->var;
- *              return 0;
- *      }
- *
- *      static int xxxfb_set_par(struct fb_info *info)
- *      {
- *              init your hardware here
- *      }
- *
- *	Returns negative errno on error, or zero on success.
- */
-static int xxxfb_set_par(struct fb_info *info)
-{
-    struct xxx_par *par = info->par;
-    /* ... */
-    return 0;	
-}
-
-/**
- *  	xxxfb_setcolreg - Optional function. Sets a color register.
- *      @regno: Which register in the CLUT we are programming 
- *      @red: The red value which can be up to 16 bits wide 
- *	@green: The green value which can be up to 16 bits wide 
- *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported, the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- * 
- *  	Set a single color register. The values supplied have a 16 bit
- *  	magnitude which needs to be scaled in this function for the hardware. 
- *	Things to take into consideration are how many color registers, if
- *	any, are supported with the current color visual. With truecolor mode
- *	no color palettes are supported. Here a pseudo palette is created
- *	which we store the value in pseudo_palette in struct fb_info. For
- *	pseudocolor mode we have a limited color palette. To deal with this
- *	we can program what color is displayed for a particular pixel value.
- *	DirectColor is similar in that we can program each color field. If
- *	we have a static colormap we don't need to implement this function. 
- * 
- *	Returns negative errno on error, or zero on success.
- */
-static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-    if (regno >= 256)  /* no. of hw registers */
-       return -EINVAL;
-    /*
-     * Program hardware... do anything you want with transp
-     */
-
-    /* grayscale works only partially under directcolor */
-    if (info->var.grayscale) {
-       /* grayscale = 0.30*R + 0.59*G + 0.11*B */
-       red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-    }
-
-    /* Directcolor:
-     *   var->{color}.offset contains start of bitfield
-     *   var->{color}.length contains length of bitfield
-     *   {hardwarespecific} contains width of DAC
-     *   pseudo_palette[X] is programmed to (X << red.offset) |
-     *                                      (X << green.offset) |
-     *                                      (X << blue.offset)
-     *   RAMDAC[X] is programmed to (red, green, blue)
-     *   color depth = SUM(var->{color}.length)
-     *
-     * Pseudocolor:
-     *    var->{color}.offset is 0 unless the palette index takes less than
-     *                        bits_per_pixel bits and is stored in the upper
-     *                        bits of the pixel value
-     *    var->{color}.length is set so that 1 << length is the number of
-     *                        available palette entries
-     *    pseudo_palette is not used
-     *    RAMDAC[X] is programmed to (red, green, blue)
-     *    color depth = var->{color}.length
-     *
-     * Static pseudocolor:
-     *    same as Pseudocolor, but the RAMDAC is not programmed (read-only)
-     *
-     * Mono01/Mono10:
-     *    Has only 2 values, black on white or white on black (fg on bg),
-     *    var->{color}.offset is 0
-     *    white = (1 << var->{color}.length) - 1, black = 0
-     *    pseudo_palette is not used
-     *    RAMDAC does not exist
-     *    color depth is always 2
-     *
-     * Truecolor:
-     *    does not use RAMDAC (usually has 3 of them).
-     *    var->{color}.offset contains start of bitfield
-     *    var->{color}.length contains length of bitfield
-     *    pseudo_palette is programmed to (red << red.offset) |
-     *                                    (green << green.offset) |
-     *                                    (blue << blue.offset) |
-     *                                    (transp << transp.offset)
-     *    RAMDAC does not exist
-     *    color depth = SUM(var->{color}.length})
-     *
-     *  The color depth is used by fbcon for choosing the logo and also
-     *  for color palette transformation if color depth < 4
-     *
-     *  As can be seen from the above, the field bits_per_pixel is _NOT_
-     *  a criteria for describing the color visual.
-     *
-     *  A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor,
-     *  and higher than that, true/directcolor.  This is incorrect, one needs
-     *  to look at the fix->visual.
-     *
-     *  Another common mistake is using bits_per_pixel to calculate the color
-     *  depth.  The bits_per_pixel field does not directly translate to color
-     *  depth. You have to compute for the color depth (using the color
-     *  bitfields) and fix->visual as seen above.
-     */
-
-    /*
-     * This is the point where the color is converted to something that
-     * is acceptable by the hardware.
-     */
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
-    red = CNVT_TOHW(red, info->var.red.length);
-    green = CNVT_TOHW(green, info->var.green.length);
-    blue = CNVT_TOHW(blue, info->var.blue.length);
-    transp = CNVT_TOHW(transp, info->var.transp.length);
-#undef CNVT_TOHW
-    /*
-     * This is the point where the function feeds the color to the hardware
-     * palette after converting the colors to something acceptable by
-     * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and
-     * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette.
-     * If you have code that writes to the hardware CLUT, and it's not
-     * any of the above visuals, then you are doing something wrong.
-     */
-    if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
-	info->fix.visual == FB_VISUAL_TRUECOLOR)
-	    write_{red|green|blue|transp}_to_clut();
-
-    /* This is the point were you need to fill up the contents of
-     * info->pseudo_palette. This structure is used _only_ by fbcon, thus
-     * it only contains 16 entries to match the number of colors supported
-     * by the console. The pseudo_palette is used only if the visual is
-     * in directcolor or truecolor mode.  With other visuals, the
-     * pseudo_palette is not used. (This might change in the future.)
-     *
-     * The contents of the pseudo_palette is in raw pixel format.  Ie, each
-     * entry can be written directly to the framebuffer without any conversion.
-     * The pseudo_palette is (void *).  However, if using the generic
-     * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette
-     * must be casted to (u32 *) _regardless_ of the bits per pixel. If the
-     * driver is using its own drawing functions, then it can use whatever
-     * size it wants.
-     */
-    if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-	info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-	    u32 v;
-
-	    if (regno >= 16)
-		    return -EINVAL;
-
-	    v = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset) |
-		    (transp << info->var.transp.offset);
-
-	    ((u32*)(info->pseudo_palette))[regno] = v;
-    }
-
-    /* ... */
-    return 0;
-}
-
-/**
- *      xxxfb_pan_display - NOT a required function. Pans the display.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *	Pan (or wrap, depending on the `vmode' field) the display using the
- *  	`xoffset' and `yoffset' fields of the `var' structure.
- *  	If the values don't fit, return -EINVAL.
- *
- *      Returns negative errno on error, or zero on success.
- */
-static int xxxfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-    /*
-     * If your hardware does not support panning, _do_ _not_ implement this
-     * function. Creating a dummy function will just confuse user apps.
-     */
-
-    /*
-     * Note that even if this function is fully functional, a setting of
-     * 0 in both xpanstep and ypanstep means that this function will never
-     * get called.
-     */
-
-    /* ... */
-    return 0;
-}
-
-/**
- *      xxxfb_blank - NOT a required function. Blanks the display.
- *      @blank_mode: the blank mode we want. 
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *      Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
- *      Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
- *      e.g. a video mode which doesn't support it.
- *
- *      Implements VESA suspend and powerdown modes on hardware that supports
- *      disabling hsync/vsync:
- *
- *      FB_BLANK_NORMAL = display is blanked, syncs are on.
- *      FB_BLANK_HSYNC_SUSPEND = hsync off
- *      FB_BLANK_VSYNC_SUSPEND = vsync off
- *      FB_BLANK_POWERDOWN =  hsync and vsync off
- *
- *      If implementing this function, at least support FB_BLANK_UNBLANK.
- *      Return !0 for any modes that are unimplemented.
- *
- */
-static int xxxfb_blank(int blank_mode, struct fb_info *info)
-{
-    /* ... */
-    return 0;
-}
-
-/* ------------ Accelerated Functions --------------------- */
-
-/*
- * We provide our own functions if we have hardware acceleration
- * or non packed pixel format layouts. If we have no hardware 
- * acceleration, we can use a generic unaccelerated function. If using
- * a pack pixel format just use the functions in cfb_*.c. Each file 
- * has one of the three different accel functions we support.
- */
-
-/**
- *      xxxfb_fillrect - REQUIRED function. Can use generic routines if 
- *		 	 non acclerated hardware and packed pixel based.
- *			 Draws a rectangle on the screen.		
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *	@region: The structure representing the rectangular region we 
- *		 wish to draw to.
- *
- *	This drawing operation places/removes a retangle on the screen 
- *	depending on the rastering operation with the value of color which
- *	is in the current color depth format.
- */
-void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
-{
-/*	Meaning of struct fb_fillrect
- *
- *	@dx: The x and y corrdinates of the upper left hand corner of the 
- *	@dy: area we want to draw to. 
- *	@width: How wide the rectangle is we want to draw.
- *	@height: How tall the rectangle is we want to draw.
- *	@color:	The color to fill in the rectangle with. 
- *	@rop: The raster operation. We can draw the rectangle with a COPY
- *	      of XOR which provides erasing effect. 
- */
-}
-
-/**
- *      xxxfb_copyarea - REQUIRED function. Can use generic routines if
- *                       non acclerated hardware and packed pixel based.
- *                       Copies one area of the screen to another area.
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *      @area: Structure providing the data to copy the framebuffer contents
- *	       from one region to another.
- *
- *      This drawing operation copies a rectangular area from one area of the
- *	screen to another area.
- */
-void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) 
-{
-/*
- *      @dx: The x and y coordinates of the upper left hand corner of the
- *	@dy: destination area on the screen.
- *      @width: How wide the rectangle is we want to copy.
- *      @height: How tall the rectangle is we want to copy.
- *      @sx: The x and y coordinates of the upper left hand corner of the
- *      @sy: source area on the screen.
- */
-}
-
-
-/**
- *      xxxfb_imageblit - REQUIRED function. Can use generic routines if
- *                        non acclerated hardware and packed pixel based.
- *                        Copies a image from system memory to the screen. 
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *	@image:	structure defining the image.
- *
- *      This drawing operation draws a image on the screen. It can be a 
- *	mono image (needed for font handling) or a color image (needed for
- *	tux). 
- */
-void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) 
-{
-/*
- *      @dx: The x and y coordinates of the upper left hand corner of the
- *	@dy: destination area to place the image on the screen.
- *      @width: How wide the image is we want to copy.
- *      @height: How tall the image is we want to copy.
- *      @fg_color: For mono bitmap images this is color data for     
- *      @bg_color: the foreground and background of the image to
- *		   write directly to the frmaebuffer.
- *	@depth:	How many bits represent a single pixel for this image.
- *	@data: The actual data used to construct the image on the display.
- *	@cmap: The colormap used for color images.   
- */
-
-/*
- * The generic function, cfb_imageblit, expects that the bitmap scanlines are
- * padded to the next byte.  Most hardware accelerators may require padding to
- * the next u16 or the next u32.  If that is the case, the driver can specify
- * this by setting info->pixmap.scan_align = 2 or 4.  See a more
- * comprehensive description of the pixmap below.
- */
-}
-
-/**
- *	xxxfb_cursor - 	OPTIONAL. If your hardware lacks support
- *			for a cursor, leave this field NULL.
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *	@cursor: structure defining the cursor to draw.
- *
- *      This operation is used to set or alter the properities of the
- *	cursor.
- *
- *	Returns negative errno on error, or zero on success.
- */
-int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-/*
- *      @set: 	Which fields we are altering in struct fb_cursor 
- *	@enable: Disable or enable the cursor 
- *      @rop: 	The bit operation we want to do. 
- *      @mask:  This is the cursor mask bitmap. 
- *      @dest:  A image of the area we are going to display the cursor.
- *		Used internally by the driver.	 
- *      @hot:	The hot spot. 
- *	@image:	The actual data for the cursor image.
- *
- *      NOTES ON FLAGS (cursor->set):
- *
- *      FB_CUR_SETIMAGE - the cursor image has changed (cursor->image.data)
- *      FB_CUR_SETPOS   - the cursor position has changed (cursor->image.dx|dy)
- *      FB_CUR_SETHOT   - the cursor hot spot has changed (cursor->hot.dx|dy)
- *      FB_CUR_SETCMAP  - the cursor colors has changed (cursor->fg_color|bg_color)
- *      FB_CUR_SETSHAPE - the cursor bitmask has changed (cursor->mask)
- *      FB_CUR_SETSIZE  - the cursor size has changed (cursor->width|height)
- *      FB_CUR_SETALL   - everything has changed
- *
- *      NOTES ON ROPs (cursor->rop, Raster Operation)
- *
- *      ROP_XOR         - cursor->image.data XOR cursor->mask
- *      ROP_COPY        - curosr->image.data AND cursor->mask
- *
- *      OTHER NOTES:
- *
- *      - fbcon only supports a 2-color cursor (cursor->image.depth = 1)
- *      - The fb_cursor structure, @cursor, _will_ always contain valid
- *        fields, whether any particular bitfields in cursor->set is set
- *        or not.
- */
-}
-
-/**
- *	xxxfb_rotate -  NOT a required function. If your hardware
- *			supports rotation the whole screen then 
- *			you would provide a hook for this. 
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *	@angle: The angle we rotate the screen.   
- *
- *      This operation is used to set or alter the properities of the
- *	cursor.
- */
-void xxxfb_rotate(struct fb_info *info, int angle)
-{
-/* Will be deprecated */
-}
-
-/**
- *	xxxfb_sync - NOT a required function. Normally the accel engine 
- *		     for a graphics card take a specific amount of time.
- *		     Often we have to wait for the accelerator to finish
- *		     its operation before we can write to the framebuffer
- *		     so we can have consistent display output. 
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *      If the driver has implemented its own hardware-based drawing function,
- *      implementing this function is highly recommended.
- */
-int xxxfb_sync(struct fb_info *info)
-{
-	return 0;
-}
-
-    /*
-     *  Frame buffer operations
-     */
-
-static struct fb_ops xxxfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= xxxfb_open,
-	.fb_read	= xxxfb_read,
-	.fb_write	= xxxfb_write,
-	.fb_release	= xxxfb_release,
-	.fb_check_var	= xxxfb_check_var,
-	.fb_set_par	= xxxfb_set_par,
-	.fb_setcolreg	= xxxfb_setcolreg,
-	.fb_blank	= xxxfb_blank,
-	.fb_pan_display	= xxxfb_pan_display,
-	.fb_fillrect	= xxxfb_fillrect, 	/* Needed !!! */
-	.fb_copyarea	= xxxfb_copyarea,	/* Needed !!! */
-	.fb_imageblit	= xxxfb_imageblit,	/* Needed !!! */
-	.fb_cursor	= xxxfb_cursor,		/* Optional !!! */
-	.fb_rotate	= xxxfb_rotate,
-	.fb_sync	= xxxfb_sync,
-	.fb_ioctl	= xxxfb_ioctl,
-	.fb_mmap	= xxxfb_mmap,
-};
-
-/* ------------------------------------------------------------------------- */
-
-    /*
-     *  Initialization
-     */
-
-/* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
-static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
-{
-    struct fb_info *info;
-    struct xxx_par *par;
-    struct device *device = &dev->dev; /* or &pdev->dev */
-    int cmap_len, retval;	
-   
-    /*
-     * Dynamically allocate info and par
-     */
-    info = framebuffer_alloc(sizeof(struct xxx_par), device);
-
-    if (!info) {
-	    /* goto error path */
-    }
-
-    par = info->par;
-
-    /* 
-     * Here we set the screen_base to the virtual memory address
-     * for the framebuffer. Usually we obtain the resource address
-     * from the bus layer and then translate it to virtual memory
-     * space via ioremap. Consult ioport.h. 
-     */
-    info->screen_base = framebuffer_virtual_memory;
-    info->fbops = &xxxfb_ops;
-    info->fix = xxxfb_fix;
-    info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
-					    * 16-member array
-					    */
-    /*
-     * Set up flags to indicate what sort of acceleration your
-     * driver can provide (pan/wrap/copyarea/etc.) and whether it
-     * is a module -- see FBINFO_* in include/linux/fb.h
-     *
-     * If your hardware can support any of the hardware accelerated functions
-     * fbcon performance will improve if info->flags is set properly.
-     *
-     * FBINFO_HWACCEL_COPYAREA - hardware moves
-     * FBINFO_HWACCEL_FILLRECT - hardware fills
-     * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion
-     * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis
-     * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis
-     * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled
-     * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion
-     * FBINFO_MISC_TILEBLITTING - hardware can do tile blits
-     *
-     * NOTE: These are for fbcon use only.
-     */
-    info->flags = FBINFO_DEFAULT;
-
-/********************* This stage is optional ******************************/
-     /*
-     * The struct pixmap is a scratch pad for the drawing functions. This
-     * is where the monochrome bitmap is constructed by the higher layers
-     * and then passed to the accelerator.  For drivers that uses
-     * cfb_imageblit, you can skip this part.  For those that have a more
-     * rigorous requirement, this stage is needed
-     */
-
-    /* PIXMAP_SIZE should be small enough to optimize drawing, but not
-     * large enough that memory is wasted.  A safe size is
-     * (max_xres * max_font_height/8). max_xres is driver dependent,
-     * max_font_height is 32.
-     */
-    info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL);
-    if (!info->pixmap.addr) {
-	    /* goto error */
-    }
-
-    info->pixmap.size = PIXMAP_SIZE;
-
-    /*
-     * FB_PIXMAP_SYSTEM - memory is in system ram
-     * FB_PIXMAP_IO     - memory is iomapped
-     * FB_PIXMAP_SYNC   - if set, will call fb_sync() per access to pixmap,
-     *                    usually if FB_PIXMAP_IO is set.
-     *
-     * Currently, FB_PIXMAP_IO is unimplemented.
-     */
-    info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-    /*
-     * scan_align is the number of padding for each scanline.  It is in bytes.
-     * Thus for accelerators that need padding to the next u32, put 4 here.
-     */
-    info->pixmap.scan_align = 4;
-
-    /*
-     * buf_align is the amount to be padded for the buffer. For example,
-     * the i810fb needs a scan_align of 2 but expects it to be fed with
-     * dwords, so a buf_align = 4 is required.
-     */
-    info->pixmap.buf_align = 4;
-
-    /* access_align is how many bits can be accessed from the framebuffer
-     * ie. some epson cards allow 16-bit access only.  Most drivers will
-     * be safe with u32 here.
-     *
-     * NOTE: This field is currently unused.
-     */
-    info->pixmap.access_align = 32;
-/***************************** End optional stage ***************************/
-
-    /*
-     * This should give a reasonable default video mode. The following is
-     * done when we can set a video mode. 
-     */
-    if (!mode_option)
-	mode_option = "640x480@60";	 	
-
-    retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
-  
-    if (!retval || retval == 4)
-	return -EINVAL;			
-
-    /* This has to be done! */
-    if (fb_alloc_cmap(&info->cmap, cmap_len, 0))
-	return -ENOMEM;
-	
-    /* 
-     * The following is done in the case of having hardware with a static 
-     * mode. If we are setting the mode ourselves we don't call this. 
-     */	
-    info->var = xxxfb_var;
-
-    /*
-     * For drivers that can...
-     */
-    xxxfb_check_var(&info->var, info);
-
-    /*
-     * Does a call to fb_set_par() before register_framebuffer needed?  This
-     * will depend on you and the hardware.  If you are sure that your driver
-     * is the only device in the system, a call to fb_set_par() is safe.
-     *
-     * Hardware in x86 systems has a VGA core.  Calling set_par() at this
-     * point will corrupt the VGA console, so it might be safer to skip a
-     * call to set_par here and just allow fbcon to do it for you.
-     */
-    /* xxxfb_set_par(info); */
-
-    if (register_framebuffer(info) < 0) {
-	fb_dealloc_cmap(&info->cmap);
-	return -EINVAL;
-    }
-    fb_info(info, "%s frame buffer device\n", info->fix.id);
-    pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */
-    return 0;
-}
-
-    /*
-     *  Cleanup
-     */
-/* static void xxxfb_remove(struct platform_device *pdev) */
-static void xxxfb_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	/* or platform_get_drvdata(pdev); */
-
-	if (info) {
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		/* ... */
-		framebuffer_release(info);
-	}
-}
-
-#ifdef CONFIG_PCI
-#ifdef CONFIG_PM
-/**
- *	xxxfb_suspend - Optional but recommended function. Suspend the device.
- *	@dev: PCI device
- *	@msg: the suspend event code.
- *
- *      See Documentation/power/devices.txt for more information
- */
-static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct xxxfb_par *par = info->par;
-
-	/* suspend here */
-	return 0;
-}
-
-/**
- *	xxxfb_resume - Optional but recommended function. Resume the device.
- *	@dev: PCI device
- *
- *      See Documentation/power/devices.txt for more information
- */
-static int xxxfb_resume(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct xxxfb_par *par = info->par;
-
-	/* resume here */
-	return 0;
-}
-#else
-#define xxxfb_suspend NULL
-#define xxxfb_resume NULL
-#endif /* CONFIG_PM */
-
-static struct pci_device_id xxxfb_id_table[] = {
-	{ PCI_VENDOR_ID_XXX, PCI_DEVICE_ID_XXX,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
-	  PCI_CLASS_MASK, 0 },
-	{ 0, }
-};
-
-/* For PCI drivers */
-static struct pci_driver xxxfb_driver = {
-	.name =		"xxxfb",
-	.id_table =	xxxfb_id_table,
-	.probe =	xxxfb_probe,
-	.remove =	xxxfb_remove,
-	.suspend =      xxxfb_suspend, /* optional but recommended */
-	.resume =       xxxfb_resume,  /* optional but recommended */
-};
-
-MODULE_DEVICE_TABLE(pci, xxxfb_id_table);
-
-int __init xxxfb_init(void)
-{
-	/*
-	 *  For kernel boot options (in 'video=xxxfb:<options>' format)
-	 */
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("xxxfb", &option))
-		return -ENODEV;
-	xxxfb_setup(option);
-#endif
-
-	return pci_register_driver(&xxxfb_driver);
-}
-
-static void __exit xxxfb_exit(void)
-{
-	pci_unregister_driver(&xxxfb_driver);
-}
-#else /* non PCI, platform drivers */
-#include <linux/platform_device.h>
-/* for platform devices */
-
-#ifdef CONFIG_PM
-/**
- *	xxxfb_suspend - Optional but recommended function. Suspend the device.
- *	@dev: platform device
- *	@msg: the suspend event code.
- *
- *      See Documentation/power/devices.txt for more information
- */
-static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct xxxfb_par *par = info->par;
-
-	/* suspend here */
-	return 0;
-}
-
-/**
- *	xxxfb_resume - Optional but recommended function. Resume the device.
- *	@dev: platform device
- *
- *      See Documentation/power/devices.txt for more information
- */
-static int xxxfb_resume(struct platform_dev *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct xxxfb_par *par = info->par;
-
-	/* resume here */
-	return 0;
-}
-#else
-#define xxxfb_suspend NULL
-#define xxxfb_resume NULL
-#endif /* CONFIG_PM */
-
-static struct platform_device_driver xxxfb_driver = {
-	.probe = xxxfb_probe,
-	.remove = xxxfb_remove,
-	.suspend = xxxfb_suspend, /* optional but recommended */
-	.resume = xxxfb_resume,   /* optional but recommended */
-	.driver = {
-		.name = "xxxfb",
-	},
-};
-
-static struct platform_device *xxxfb_device;
-
-#ifndef MODULE
-    /*
-     *  Setup
-     */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-int __init xxxfb_setup(char *options)
-{
-    /* Parse user specified options (`video=xxxfb:') */
-}
-#endif /* MODULE */
-
-static int __init xxxfb_init(void)
-{
-	int ret;
-	/*
-	 *  For kernel boot options (in 'video=xxxfb:<options>' format)
-	 */
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("xxxfb", &option))
-		return -ENODEV;
-	xxxfb_setup(option);
-#endif
-	ret = platform_driver_register(&xxxfb_driver);
-
-	if (!ret) {
-		xxxfb_device = platform_device_register_simple("xxxfb", 0,
-								NULL, 0);
-
-		if (IS_ERR(xxxfb_device)) {
-			platform_driver_unregister(&xxxfb_driver);
-			ret = PTR_ERR(xxxfb_device);
-		}
-	}
-
-	return ret;
-}
-
-static void __exit xxxfb_exit(void)
-{
-	platform_device_unregister(xxxfb_device);
-	platform_driver_unregister(&xxxfb_driver);
-}
-#endif /* CONFIG_PCI */
-
-/* ------------------------------------------------------------------------- */
-
-
-    /*
-     *  Modularization
-     */
-
-module_init(xxxfb_init);
-module_exit(xxxfb_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
deleted file mode 100644
index 1501979099dc..000000000000
--- a/drivers/video/sm501fb.c
+++ /dev/null
@@ -1,2240 +0,0 @@
-/* linux/drivers/video/sm501fb.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Vincent Sanders <vince@simtec.co.uk>
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Framebuffer driver for the Silicon Motion SM501
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/wait.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/console.h>
-#include <linux/io.h>
-
-#include <asm/uaccess.h>
-#include <asm/div64.h>
-
-#ifdef CONFIG_PM
-#include <linux/pm.h>
-#endif
-
-#include <linux/sm501.h>
-#include <linux/sm501-regs.h>
-
-#include "edid.h"
-
-static char *fb_mode = "640x480-16@60";
-static unsigned long default_bpp = 16;
-
-static struct fb_videomode sm501_default_mode = {
-	.refresh	= 60,
-	.xres		= 640,
-	.yres		= 480,
-	.pixclock	= 20833,
-	.left_margin	= 142,
-	.right_margin	= 13,
-	.upper_margin	= 21,
-	.lower_margin	= 1,
-	.hsync_len	= 69,
-	.vsync_len	= 3,
-	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode		= FB_VMODE_NONINTERLACED
-};
-
-#define NR_PALETTE	256
-
-enum sm501_controller {
-	HEAD_CRT	= 0,
-	HEAD_PANEL	= 1,
-};
-
-/* SM501 memory address.
- *
- * This structure is used to track memory usage within the SM501 framebuffer
- * allocation. The sm_addr field is stored as an offset as it is often used
- * against both the physical and mapped addresses.
- */
-struct sm501_mem {
-	unsigned long	 size;
-	unsigned long	 sm_addr;	/* offset from base of sm501 fb. */
-	void __iomem	*k_addr;
-};
-
-/* private data that is shared between all frambuffers* */
-struct sm501fb_info {
-	struct device		*dev;
-	struct fb_info		*fb[2];		/* fb info for both heads */
-	struct resource		*fbmem_res;	/* framebuffer resource */
-	struct resource		*regs_res;	/* registers resource */
-	struct resource		*regs2d_res;	/* 2d registers resource */
-	struct sm501_platdata_fb *pdata;	/* our platform data */
-
-	unsigned long		 pm_crt_ctrl;	/* pm: crt ctrl save */
-
-	int			 irq;
-	int			 swap_endian;	/* set to swap rgb=>bgr */
-	void __iomem		*regs;		/* remapped registers */
-	void __iomem		*regs2d;	/* 2d remapped registers */
-	void __iomem		*fbmem;		/* remapped framebuffer */
-	size_t			 fbmem_len;	/* length of remapped region */
-	u8 *edid_data;
-};
-
-/* per-framebuffer private data */
-struct sm501fb_par {
-	u32			 pseudo_palette[16];
-
-	enum sm501_controller	 head;
-	struct sm501_mem	 cursor;
-	struct sm501_mem	 screen;
-	struct fb_ops		 ops;
-
-	void			*store_fb;
-	void			*store_cursor;
-	void __iomem		*cursor_regs;
-	struct sm501fb_info	*info;
-};
-
-/* Helper functions */
-
-static inline int h_total(struct fb_var_screeninfo *var)
-{
-	return var->xres + var->left_margin +
-		var->right_margin + var->hsync_len;
-}
-
-static inline int v_total(struct fb_var_screeninfo *var)
-{
-	return var->yres + var->upper_margin +
-		var->lower_margin + var->vsync_len;
-}
-
-/* sm501fb_sync_regs()
- *
- * This call is mainly for PCI bus systems where we need to
- * ensure that any writes to the bus are completed before the
- * next phase, or after completing a function.
-*/
-
-static inline void sm501fb_sync_regs(struct sm501fb_info *info)
-{
-	smc501_readl(info->regs);
-}
-
-/* sm501_alloc_mem
- *
- * This is an attempt to lay out memory for the two framebuffers and
- * everything else
- *
- * |fbmem_res->start					       fbmem_res->end|
- * |									     |
- * |fb[0].fix.smem_start    |	      |fb[1].fix.smem_start    |     2K	     |
- * |-> fb[0].fix.smem_len <-| spare   |-> fb[1].fix.smem_len <-|-> cursors <-|
- *
- * The "spare" space is for the 2d engine data
- * the fixed is space for the cursors (2x1Kbyte)
- *
- * we need to allocate memory for the 2D acceleration engine
- * command list and the data for the engine to deal with.
- *
- * - all allocations must be 128bit aligned
- * - cursors are 64x64x2 bits (1Kbyte)
- *
- */
-
-#define SM501_MEMF_CURSOR		(1)
-#define SM501_MEMF_PANEL		(2)
-#define SM501_MEMF_CRT			(4)
-#define SM501_MEMF_ACCEL		(8)
-
-static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
-			   unsigned int why, size_t size, u32 smem_len)
-{
-	struct sm501fb_par *par;
-	struct fb_info *fbi;
-	unsigned int ptr;
-	unsigned int end;
-
-	switch (why) {
-	case SM501_MEMF_CURSOR:
-		ptr = inf->fbmem_len - size;
-		inf->fbmem_len = ptr;	/* adjust available memory. */
-		break;
-
-	case SM501_MEMF_PANEL:
-		if (size > inf->fbmem_len)
-			return -ENOMEM;
-
-		ptr = inf->fbmem_len - size;
-		fbi = inf->fb[HEAD_CRT];
-
-		/* round down, some programs such as directfb do not draw
-		 * 0,0 correctly unless the start is aligned to a page start.
-		 */
-
-		if (ptr > 0)
-			ptr &= ~(PAGE_SIZE - 1);
-
-		if (fbi && ptr < smem_len)
-			return -ENOMEM;
-
-		break;
-
-	case SM501_MEMF_CRT:
-		ptr = 0;
-
-		/* check to see if we have panel memory allocated
-		 * which would put an limit on available memory. */
-
-		fbi = inf->fb[HEAD_PANEL];
-		if (fbi) {
-			par = fbi->par;
-			end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len;
-		} else
-			end = inf->fbmem_len;
-
-		if ((ptr + size) > end)
-			return -ENOMEM;
-
-		break;
-
-	case SM501_MEMF_ACCEL:
-		fbi = inf->fb[HEAD_CRT];
-		ptr = fbi ? smem_len : 0;
-
-		fbi = inf->fb[HEAD_PANEL];
-		if (fbi) {
-			par = fbi->par;
-			end = par->screen.sm_addr;
-		} else
-			end = inf->fbmem_len;
-
-		if ((ptr + size) > end)
-			return -ENOMEM;
-
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	mem->size    = size;
-	mem->sm_addr = ptr;
-	mem->k_addr  = inf->fbmem + ptr;
-
-	dev_dbg(inf->dev, "%s: result %08lx, %p - %u, %zd\n",
-		__func__, mem->sm_addr, mem->k_addr, why, size);
-
-	return 0;
-}
-
-/* sm501fb_ps_to_hz
- *
- * Converts a period in picoseconds to Hz.
- *
- * Note, we try to keep this in Hz to minimise rounding with
- * the limited PLL settings on the SM501.
-*/
-
-static unsigned long sm501fb_ps_to_hz(unsigned long psvalue)
-{
-	unsigned long long numerator=1000000000000ULL;
-
-	/* 10^12 / picosecond period gives frequency in Hz */
-	do_div(numerator, psvalue);
-	return (unsigned long)numerator;
-}
-
-/* sm501fb_hz_to_ps is identical to the opposite transform */
-
-#define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x)
-
-/* sm501fb_setup_gamma
- *
- * Programs a linear 1.0 gamma ramp in case the gamma
- * correction is enabled without programming anything else.
-*/
-
-static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
-				unsigned long palette)
-{
-	unsigned long value = 0;
-	int offset;
-
-	/* set gamma values */
-	for (offset = 0; offset < 256 * 4; offset += 4) {
-		smc501_writel(value, fbi->regs + palette + offset);
-		value += 0x010101; 	/* Advance RGB by 1,1,1.*/
-	}
-}
-
-/* sm501fb_check_var
- *
- * check common variables for both panel and crt
-*/
-
-static int sm501fb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *sm  = par->info;
-	unsigned long tmp;
-
-	/* check we can fit these values into the registers */
-
-	if (var->hsync_len > 255 || var->vsync_len > 63)
-		return -EINVAL;
-
-	/* hdisplay end and hsync start */
-	if ((var->xres + var->right_margin) > 4096)
-		return -EINVAL;
-
-	/* vdisplay end and vsync start */
-	if ((var->yres + var->lower_margin) > 2048)
-		return -EINVAL;
-
-	/* hard limits of device */
-
-	if (h_total(var) > 4096 || v_total(var) > 2048)
-		return -EINVAL;
-
-	/* check our line length is going to be 128 bit aligned */
-
-	tmp = (var->xres * var->bits_per_pixel) / 8;
-	if ((tmp & 15) != 0)
-		return -EINVAL;
-
-	/* check the virtual size */
-
-	if (var->xres_virtual > 4096 || var->yres_virtual > 2048)
-		return -EINVAL;
-
-	/* can cope with 8,16 or 32bpp */
-
-	if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel == 24)
-		var->bits_per_pixel = 32;
-
-	/* set r/g/b positions and validate bpp */
-	switch(var->bits_per_pixel) {
-	case 8:
-		var->red.length		= var->bits_per_pixel;
-		var->red.offset		= 0;
-		var->green.length	= var->bits_per_pixel;
-		var->green.offset	= 0;
-		var->blue.length	= var->bits_per_pixel;
-		var->blue.offset	= 0;
-		var->transp.length	= 0;
-		var->transp.offset	= 0;
-
-		break;
-
-	case 16:
-		if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
-			var->blue.offset	= 11;
-			var->green.offset	= 5;
-			var->red.offset		= 0;
-		} else {
-			var->red.offset		= 11;
-			var->green.offset	= 5;
-			var->blue.offset	= 0;
-		}
-		var->transp.offset	= 0;
-
-		var->red.length		= 5;
-		var->green.length	= 6;
-		var->blue.length	= 5;
-		var->transp.length	= 0;
-		break;
-
-	case 32:
-		if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) {
-			var->transp.offset	= 0;
-			var->red.offset		= 8;
-			var->green.offset	= 16;
-			var->blue.offset	= 24;
-		} else {
-			var->transp.offset	= 24;
-			var->red.offset		= 16;
-			var->green.offset	= 8;
-			var->blue.offset	= 0;
-		}
-
-		var->red.length		= 8;
-		var->green.length	= 8;
-		var->blue.length	= 8;
-		var->transp.length	= 0;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
- * sm501fb_check_var_crt():
- *
- * check the parameters for the CRT head, and either bring them
- * back into range, or return -EINVAL.
-*/
-
-static int sm501fb_check_var_crt(struct fb_var_screeninfo *var,
-				 struct fb_info *info)
-{
-	return sm501fb_check_var(var, info);
-}
-
-/* sm501fb_check_var_pnl():
- *
- * check the parameters for the CRT head, and either bring them
- * back into range, or return -EINVAL.
-*/
-
-static int sm501fb_check_var_pnl(struct fb_var_screeninfo *var,
-				 struct fb_info *info)
-{
-	return sm501fb_check_var(var, info);
-}
-
-/* sm501fb_set_par_common
- *
- * set common registers for framebuffers
-*/
-
-static int sm501fb_set_par_common(struct fb_info *info,
-				  struct fb_var_screeninfo *var)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	unsigned long pixclock;      /* pixelclock in Hz */
-	unsigned long sm501pixclock; /* pixelclock the 501 can achieve in Hz */
-	unsigned int mem_type;
-	unsigned int clock_type;
-	unsigned int head_addr;
-	unsigned int smem_len;
-
-	dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n",
-		__func__, var->xres, var->yres, var->bits_per_pixel,
-		var->xres_virtual, var->yres_virtual);
-
-	switch (par->head) {
-	case HEAD_CRT:
-		mem_type = SM501_MEMF_CRT;
-		clock_type = SM501_CLOCK_V2XCLK;
-		head_addr = SM501_DC_CRT_FB_ADDR;
-		break;
-
-	case HEAD_PANEL:
-		mem_type = SM501_MEMF_PANEL;
-		clock_type = SM501_CLOCK_P2XCLK;
-		head_addr = SM501_DC_PANEL_FB_ADDR;
-		break;
-
-	default:
-		mem_type = 0;		/* stop compiler warnings */
-		head_addr = 0;
-		clock_type = 0;
-	}
-
-	switch (var->bits_per_pixel) {
-	case 8:
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-
-	case 16:
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-
-	case 32:
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		break;
-	}
-
-	/* allocate fb memory within 501 */
-	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8;
-	smem_len = info->fix.line_length * var->yres_virtual;
-
-	dev_dbg(fbi->dev, "%s: line length = %u\n", __func__,
-		info->fix.line_length);
-
-	if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) {
-		dev_err(fbi->dev, "no memory available\n");
-		return -ENOMEM;
-	}
-
-	mutex_lock(&info->mm_lock);
-	info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr;
-	info->fix.smem_len   = smem_len;
-	mutex_unlock(&info->mm_lock);
-
-	info->screen_base = fbi->fbmem + par->screen.sm_addr;
-	info->screen_size = info->fix.smem_len;
-
-	/* set start of framebuffer to the screen */
-
-	smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP,
-			fbi->regs + head_addr);
-
-	/* program CRT clock  */
-
-	pixclock = sm501fb_ps_to_hz(var->pixclock);
-
-	sm501pixclock = sm501_set_clock(fbi->dev->parent, clock_type,
-					pixclock);
-
-	/* update fb layer with actual clock used */
-	var->pixclock = sm501fb_hz_to_ps(sm501pixclock);
-
-	dev_dbg(fbi->dev, "%s: pixclock(ps) = %u, pixclock(Hz)  = %lu, "
-	       "sm501pixclock = %lu,  error = %ld%%\n",
-	       __func__, var->pixclock, pixclock, sm501pixclock,
-	       ((pixclock - sm501pixclock)*100)/pixclock);
-
-	return 0;
-}
-
-/* sm501fb_set_par_geometry
- *
- * set the geometry registers for specified framebuffer.
-*/
-
-static void sm501fb_set_par_geometry(struct fb_info *info,
-				     struct fb_var_screeninfo *var)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	void __iomem *base = fbi->regs;
-	unsigned long reg;
-
-	if (par->head == HEAD_CRT)
-		base += SM501_DC_CRT_H_TOT;
-	else
-		base += SM501_DC_PANEL_H_TOT;
-
-	/* set framebuffer width and display width */
-
-	reg = info->fix.line_length;
-	reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
-
-	smc501_writel(reg, fbi->regs + (par->head == HEAD_CRT ?
-		    SM501_DC_CRT_FB_OFFSET :  SM501_DC_PANEL_FB_OFFSET));
-
-	/* program horizontal total */
-
-	reg  = (h_total(var) - 1) << 16;
-	reg |= (var->xres - 1);
-
-	smc501_writel(reg, base + SM501_OFF_DC_H_TOT);
-
-	/* program horizontal sync */
-
-	reg  = var->hsync_len << 16;
-	reg |= var->xres + var->right_margin - 1;
-
-	smc501_writel(reg, base + SM501_OFF_DC_H_SYNC);
-
-	/* program vertical total */
-
-	reg  = (v_total(var) - 1) << 16;
-	reg |= (var->yres - 1);
-
-	smc501_writel(reg, base + SM501_OFF_DC_V_TOT);
-
-	/* program vertical sync */
-	reg  = var->vsync_len << 16;
-	reg |= var->yres + var->lower_margin - 1;
-
-	smc501_writel(reg, base + SM501_OFF_DC_V_SYNC);
-}
-
-/* sm501fb_pan_crt
- *
- * pan the CRT display output within an virtual framebuffer
-*/
-
-static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	unsigned int bytes_pixel = info->var.bits_per_pixel / 8;
-	unsigned long reg;
-	unsigned long xoffs;
-
-	xoffs = var->xoffset * bytes_pixel;
-
-	reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
-
-	reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
-	reg |= ((xoffs & 15) / bytes_pixel) << 4;
-	smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
-
-	reg = (par->screen.sm_addr + xoffs +
-	       var->yoffset * info->fix.line_length);
-	smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
-
-	sm501fb_sync_regs(fbi);
-	return 0;
-}
-
-/* sm501fb_pan_pnl
- *
- * pan the panel display output within an virtual framebuffer
-*/
-
-static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	unsigned long reg;
-
-	reg = var->xoffset | (info->var.xres_virtual << 16);
-	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
-
-	reg = var->yoffset | (info->var.yres_virtual << 16);
-	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
-
-	sm501fb_sync_regs(fbi);
-	return 0;
-}
-
-/* sm501fb_set_par_crt
- *
- * Set the CRT video mode from the fb_info structure
-*/
-
-static int sm501fb_set_par_crt(struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	struct fb_var_screeninfo *var = &info->var;
-	unsigned long control;       /* control register */
-	int ret;
-
-	/* activate new configuration */
-
-	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
-
-	/* enable CRT DAC - note 0 is on!*/
-	sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
-
-	control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
-
-	control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
-		    SM501_DC_CRT_CONTROL_GAMMA |
-		    SM501_DC_CRT_CONTROL_BLANK |
-		    SM501_DC_CRT_CONTROL_SEL |
-		    SM501_DC_CRT_CONTROL_CP |
-		    SM501_DC_CRT_CONTROL_TVP);
-
-	/* set the sync polarities before we check data source  */
-
-	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
-		control |= SM501_DC_CRT_CONTROL_HSP;
-
-	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
-		control |= SM501_DC_CRT_CONTROL_VSP;
-
-	if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
-		/* the head is displaying panel data... */
-
-		sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0,
-				info->fix.smem_len);
-		goto out_update;
-	}
-
-	ret = sm501fb_set_par_common(info, var);
-	if (ret) {
-		dev_err(fbi->dev, "failed to set common parameters\n");
-		return ret;
-	}
-
-	sm501fb_pan_crt(var, info);
-	sm501fb_set_par_geometry(info, var);
-
-	control |= SM501_FIFO_3;	/* fill if >3 free slots */
-
-	switch(var->bits_per_pixel) {
-	case 8:
-		control |= SM501_DC_CRT_CONTROL_8BPP;
-		break;
-
-	case 16:
-		control |= SM501_DC_CRT_CONTROL_16BPP;
-		sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE);
-		break;
-
-	case 32:
-		control |= SM501_DC_CRT_CONTROL_32BPP;
-		sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE);
-		break;
-
-	default:
-		BUG();
-	}
-
-	control |= SM501_DC_CRT_CONTROL_SEL;	/* CRT displays CRT data */
-	control |= SM501_DC_CRT_CONTROL_TE;	/* enable CRT timing */
-	control |= SM501_DC_CRT_CONTROL_ENABLE;	/* enable CRT plane */
-
- out_update:
-	dev_dbg(fbi->dev, "new control is %08lx\n", control);
-
-	smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
-	sm501fb_sync_regs(fbi);
-
-	return 0;
-}
-
-static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
-{
-	unsigned long control;
-	void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
-	struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
-
-	control = smc501_readl(ctrl_reg);
-
-	if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
-		/* enable panel power */
-
-		control |= SM501_DC_PANEL_CONTROL_VDD;	/* FPVDDEN */
-		smc501_writel(control, ctrl_reg);
-		sm501fb_sync_regs(fbi);
-		mdelay(10);
-
-		control |= SM501_DC_PANEL_CONTROL_DATA;	/* DATA */
-		smc501_writel(control, ctrl_reg);
-		sm501fb_sync_regs(fbi);
-		mdelay(10);
-
-		/* VBIASEN */
-
-		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
-			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
-				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
-			else
-				control |= SM501_DC_PANEL_CONTROL_BIAS;
-
-			smc501_writel(control, ctrl_reg);
-			sm501fb_sync_regs(fbi);
-			mdelay(10);
-		}
-
-		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
-			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
-				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
-			else
-				control |= SM501_DC_PANEL_CONTROL_FPEN;
-
-			smc501_writel(control, ctrl_reg);
-			sm501fb_sync_regs(fbi);
-			mdelay(10);
-		}
-	} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
-		/* disable panel power */
-		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
-			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
-				control |= SM501_DC_PANEL_CONTROL_FPEN;
-			else
-				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
-
-			smc501_writel(control, ctrl_reg);
-			sm501fb_sync_regs(fbi);
-			mdelay(10);
-		}
-
-		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
-			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
-				control |= SM501_DC_PANEL_CONTROL_BIAS;
-			else
-				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
-
-			smc501_writel(control, ctrl_reg);
-			sm501fb_sync_regs(fbi);
-			mdelay(10);
-		}
-
-		control &= ~SM501_DC_PANEL_CONTROL_DATA;
-		smc501_writel(control, ctrl_reg);
-		sm501fb_sync_regs(fbi);
-		mdelay(10);
-
-		control &= ~SM501_DC_PANEL_CONTROL_VDD;
-		smc501_writel(control, ctrl_reg);
-		sm501fb_sync_regs(fbi);
-		mdelay(10);
-	}
-
-	sm501fb_sync_regs(fbi);
-}
-
-/* sm501fb_set_par_pnl
- *
- * Set the panel video mode from the fb_info structure
-*/
-
-static int sm501fb_set_par_pnl(struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	struct fb_var_screeninfo *var = &info->var;
-	unsigned long control;
-	unsigned long reg;
-	int ret;
-
-	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);
-
-	/* activate this new configuration */
-
-	ret = sm501fb_set_par_common(info, var);
-	if (ret)
-		return ret;
-
-	sm501fb_pan_pnl(var, info);
-	sm501fb_set_par_geometry(info, var);
-
-	/* update control register */
-
-	control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL);
-	control &= (SM501_DC_PANEL_CONTROL_GAMMA |
-		    SM501_DC_PANEL_CONTROL_VDD  |
-		    SM501_DC_PANEL_CONTROL_DATA |
-		    SM501_DC_PANEL_CONTROL_BIAS |
-		    SM501_DC_PANEL_CONTROL_FPEN |
-		    SM501_DC_PANEL_CONTROL_CP |
-		    SM501_DC_PANEL_CONTROL_CK |
-		    SM501_DC_PANEL_CONTROL_HP |
-		    SM501_DC_PANEL_CONTROL_VP |
-		    SM501_DC_PANEL_CONTROL_HPD |
-		    SM501_DC_PANEL_CONTROL_VPD);
-
-	control |= SM501_FIFO_3;	/* fill if >3 free slots */
-
-	switch(var->bits_per_pixel) {
-	case 8:
-		control |= SM501_DC_PANEL_CONTROL_8BPP;
-		break;
-
-	case 16:
-		control |= SM501_DC_PANEL_CONTROL_16BPP;
-		sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE);
-		break;
-
-	case 32:
-		control |= SM501_DC_PANEL_CONTROL_32BPP;
-		sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE);
-		break;
-
-	default:
-		BUG();
-	}
-
-	smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
-
-	/* panel plane top left and bottom right location */
-
-	smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
-
-	reg  = var->xres - 1;
-	reg |= (var->yres - 1) << 16;
-
-	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
-
-	/* program panel control register */
-
-	control |= SM501_DC_PANEL_CONTROL_TE;	/* enable PANEL timing */
-	control |= SM501_DC_PANEL_CONTROL_EN;	/* enable PANEL gfx plane */
-
-	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
-		control |= SM501_DC_PANEL_CONTROL_HSP;
-
-	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
-		control |= SM501_DC_PANEL_CONTROL_VSP;
-
-	smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
-	sm501fb_sync_regs(fbi);
-
-	/* ensure the panel interface is not tristated at this point */
-
-	sm501_modify_reg(fbi->dev->parent, SM501_SYSTEM_CONTROL,
-			 0, SM501_SYSCTRL_PANEL_TRISTATE);
-
-	/* power the panel up */
-	sm501fb_panel_power(fbi, 1);
-	return 0;
-}
-
-
-/* chan_to_field
- *
- * convert a colour value into a field position
- *
- * from pxafb.c
-*/
-
-static inline unsigned int chan_to_field(unsigned int chan,
-					 struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-/* sm501fb_setcolreg
- *
- * set the colour mapping for modes that support palettised data
-*/
-
-static int sm501fb_setcolreg(unsigned regno,
-			     unsigned red, unsigned green, unsigned blue,
-			     unsigned transp, struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	void __iomem *base = fbi->regs;
-	unsigned int val;
-
-	if (par->head == HEAD_CRT)
-		base += SM501_DC_CRT_PALETTE;
-	else
-		base += SM501_DC_PANEL_PALETTE;
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		/* true-colour, use pseuo-palette */
-
-		if (regno < 16) {
-			u32 *pal = par->pseudo_palette;
-
-			val  = chan_to_field(red,   &info->var.red);
-			val |= chan_to_field(green, &info->var.green);
-			val |= chan_to_field(blue,  &info->var.blue);
-
-			pal[regno] = val;
-		}
-		break;
-
-	case FB_VISUAL_PSEUDOCOLOR:
-		if (regno < 256) {
-			val = (red >> 8) << 16;
-			val |= (green >> 8) << 8;
-			val |= blue >> 8;
-
-			smc501_writel(val, base + (regno * 4));
-		}
-
-		break;
-
-	default:
-		return 1;   /* unknown type */
-	}
-
-	return 0;
-}
-
-/* sm501fb_blank_pnl
- *
- * Blank or un-blank the panel interface
-*/
-
-static int sm501fb_blank_pnl(int blank_mode, struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-
-	dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
-
-	switch (blank_mode) {
-	case FB_BLANK_POWERDOWN:
-		sm501fb_panel_power(fbi, 0);
-		break;
-
-	case FB_BLANK_UNBLANK:
-		sm501fb_panel_power(fbi, 1);
-		break;
-
-	case FB_BLANK_NORMAL:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	default:
-		return 1;
-	}
-
-	return 0;
-}
-
-/* sm501fb_blank_crt
- *
- * Blank or un-blank the crt interface
-*/
-
-static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	unsigned long ctrl;
-
-	dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
-
-	ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
-
-	switch (blank_mode) {
-	case FB_BLANK_POWERDOWN:
-		ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
-		sm501_misc_control(fbi->dev->parent, SM501_MISC_DAC_POWER, 0);
-
-	case FB_BLANK_NORMAL:
-		ctrl |= SM501_DC_CRT_CONTROL_BLANK;
-		break;
-
-	case FB_BLANK_UNBLANK:
-		ctrl &= ~SM501_DC_CRT_CONTROL_BLANK;
-		ctrl |=  SM501_DC_CRT_CONTROL_ENABLE;
-		sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
-		break;
-
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	default:
-		return 1;
-
-	}
-
-	smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
-	sm501fb_sync_regs(fbi);
-
-	return 0;
-}
-
-/* sm501fb_cursor
- *
- * set or change the hardware cursor parameters
-*/
-
-static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	void __iomem *base = fbi->regs;
-	unsigned long hwc_addr;
-	unsigned long fg, bg;
-
-	dev_dbg(fbi->dev, "%s(%p,%p)\n", __func__, info, cursor);
-
-	if (par->head == HEAD_CRT)
-		base += SM501_DC_CRT_HWC_BASE;
-	else
-		base += SM501_DC_PANEL_HWC_BASE;
-
-	/* check not being asked to exceed capabilities */
-
-	if (cursor->image.width > 64)
-		return -EINVAL;
-
-	if (cursor->image.height > 64)
-		return -EINVAL;
-
-	if (cursor->image.depth > 1)
-		return -EINVAL;
-
-	hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR);
-
-	if (cursor->enable)
-		smc501_writel(hwc_addr | SM501_HWC_EN,
-				base + SM501_OFF_HWC_ADDR);
-	else
-		smc501_writel(hwc_addr & ~SM501_HWC_EN,
-				base + SM501_OFF_HWC_ADDR);
-
-	/* set data */
-	if (cursor->set & FB_CUR_SETPOS) {
-		unsigned int x = cursor->image.dx;
-		unsigned int y = cursor->image.dy;
-
-		if (x >= 2048 || y >= 2048 )
-			return -EINVAL;
-
-		dev_dbg(fbi->dev, "set position %d,%d\n", x, y);
-
-		//y += cursor->image.height;
-
-		smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
-	}
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		unsigned int bg_col = cursor->image.bg_color;
-		unsigned int fg_col = cursor->image.fg_color;
-
-		dev_dbg(fbi->dev, "%s: update cmap (%08x,%08x)\n",
-			__func__, bg_col, fg_col);
-
-		bg = ((info->cmap.red[bg_col] & 0xF8) << 8) |
-			((info->cmap.green[bg_col] & 0xFC) << 3) |
-			((info->cmap.blue[bg_col] & 0xF8) >> 3);
-
-		fg = ((info->cmap.red[fg_col] & 0xF8) << 8) |
-			((info->cmap.green[fg_col] & 0xFC) << 3) |
-			((info->cmap.blue[fg_col] & 0xF8) >> 3);
-
-		dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
-
-		smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
-		smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3);
-	}
-
-	if (cursor->set & FB_CUR_SETSIZE ||
-	    cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
-		/* SM501 cursor is a two bpp 64x64 bitmap this routine
-		 * clears it to transparent then combines the cursor
-		 * shape plane with the colour plane to set the
-		 * cursor */
-		int x, y;
-		const unsigned char *pcol = cursor->image.data;
-		const unsigned char *pmsk = cursor->mask;
-		void __iomem   *dst = par->cursor.k_addr;
-		unsigned char  dcol = 0;
-		unsigned char  dmsk = 0;
-		unsigned int   op;
-
-		dev_dbg(fbi->dev, "%s: setting shape (%d,%d)\n",
-			__func__, cursor->image.width, cursor->image.height);
-
-		for (op = 0; op < (64*64*2)/8; op+=4)
-			smc501_writel(0x0, dst + op);
-
-		for (y = 0; y < cursor->image.height; y++) {
-			for (x = 0; x < cursor->image.width; x++) {
-				if ((x % 8) == 0) {
-					dcol = *pcol++;
-					dmsk = *pmsk++;
-				} else {
-					dcol >>= 1;
-					dmsk >>= 1;
-				}
-
-				if (dmsk & 1) {
-					op = (dcol & 1) ? 1 : 3;
-					op <<= ((x % 4) * 2);
-
-					op |= readb(dst + (x / 4));
-					writeb(op, dst + (x / 4));
-				}
-			}
-			dst += (64*2)/8;
-		}
-	}
-
-	sm501fb_sync_regs(fbi);	/* ensure cursor data flushed */
-	return 0;
-}
-
-/* sm501fb_crtsrc_show
- *
- * device attribute code to show where the crt output is sourced from
-*/
-
-static ssize_t sm501fb_crtsrc_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct sm501fb_info *info = dev_get_drvdata(dev);
-	unsigned long ctrl;
-
-	ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
-	ctrl &= SM501_DC_CRT_CONTROL_SEL;
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
-}
-
-/* sm501fb_crtsrc_show
- *
- * device attribute code to set where the crt output is sourced from
-*/
-
-static ssize_t sm501fb_crtsrc_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t len)
-{
-	struct sm501fb_info *info = dev_get_drvdata(dev);
-	enum sm501_controller head;
-	unsigned long ctrl;
-
-	if (len < 1)
-		return -EINVAL;
-
-	if (strnicmp(buf, "crt", 3) == 0)
-		head = HEAD_CRT;
-	else if (strnicmp(buf, "panel", 5) == 0)
-		head = HEAD_PANEL;
-	else
-		return -EINVAL;
-
-	dev_info(dev, "setting crt source to head %d\n", head);
-
-	ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
-
-	if (head == HEAD_CRT) {
-		ctrl |= SM501_DC_CRT_CONTROL_SEL;
-		ctrl |= SM501_DC_CRT_CONTROL_ENABLE;
-		ctrl |= SM501_DC_CRT_CONTROL_TE;
-	} else {
-		ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
-		ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE;
-		ctrl &= ~SM501_DC_CRT_CONTROL_TE;
-	}
-
-	smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
-	sm501fb_sync_regs(info);
-
-	return len;
-}
-
-/* Prepare the device_attr for registration with sysfs later */
-static DEVICE_ATTR(crt_src, 0666, sm501fb_crtsrc_show, sm501fb_crtsrc_store);
-
-/* sm501fb_show_regs
- *
- * show the primary sm501 registers
-*/
-static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
-			     unsigned int start, unsigned int len)
-{
-	void __iomem *mem = info->regs;
-	char *buf = ptr;
-	unsigned int reg;
-
-	for (reg = start; reg < (len + start); reg += 4)
-		ptr += sprintf(ptr, "%08x = %08x\n", reg,
-				smc501_readl(mem + reg));
-
-	return ptr - buf;
-}
-
-/* sm501fb_debug_show_crt
- *
- * show the crt control and cursor registers
-*/
-
-static ssize_t sm501fb_debug_show_crt(struct device *dev,
-				  struct device_attribute *attr, char *buf)
-{
-	struct sm501fb_info *info = dev_get_drvdata(dev);
-	char *ptr = buf;
-
-	ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_CONTROL, 0x40);
-	ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_HWC_BASE, 0x10);
-
-	return ptr - buf;
-}
-
-static DEVICE_ATTR(fbregs_crt, 0444, sm501fb_debug_show_crt, NULL);
-
-/* sm501fb_debug_show_pnl
- *
- * show the panel control and cursor registers
-*/
-
-static ssize_t sm501fb_debug_show_pnl(struct device *dev,
-				  struct device_attribute *attr, char *buf)
-{
-	struct sm501fb_info *info = dev_get_drvdata(dev);
-	char *ptr = buf;
-
-	ptr += sm501fb_show_regs(info, ptr, 0x0, 0x40);
-	ptr += sm501fb_show_regs(info, ptr, SM501_DC_PANEL_HWC_BASE, 0x10);
-
-	return ptr - buf;
-}
-
-static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL);
-
-/* acceleration operations */
-static int sm501fb_sync(struct fb_info *info)
-{
-	int count = 1000000;
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-
-	/* wait for the 2d engine to be ready */
-	while ((count > 0) &&
-	       (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) &
-		SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
-		count--;
-
-	if (count <= 0) {
-		dev_err(info->dev, "Timeout waiting for 2d engine sync\n");
-		return 1;
-	}
-	return 0;
-}
-
-static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	int width = area->width;
-	int height = area->height;
-	int sx = area->sx;
-	int sy = area->sy;
-	int dx = area->dx;
-	int dy = area->dy;
-	unsigned long rtl = 0;
-
-	/* source clip */
-	if ((sx >= info->var.xres_virtual) ||
-	    (sy >= info->var.yres_virtual))
-		/* source Area not within virtual screen, skipping */
-		return;
-	if ((sx + width) >= info->var.xres_virtual)
-		width = info->var.xres_virtual - sx - 1;
-	if ((sy + height) >= info->var.yres_virtual)
-		height = info->var.yres_virtual - sy - 1;
-
-	/* dest clip */
-	if ((dx >= info->var.xres_virtual) ||
-	    (dy >= info->var.yres_virtual))
-		/* Destination Area not within virtual screen, skipping */
-		return;
-	if ((dx + width) >= info->var.xres_virtual)
-		width = info->var.xres_virtual - dx - 1;
-	if ((dy + height) >= info->var.yres_virtual)
-		height = info->var.yres_virtual - dy - 1;
-
-	if ((sx < dx) || (sy < dy)) {
-		rtl = 1 << 27;
-		sx += width - 1;
-		dx += width - 1;
-		sy += height - 1;
-		dy += height - 1;
-	}
-
-	if (sm501fb_sync(info))
-		return;
-
-	/* set the base addresses */
-	smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
-	smc501_writel(par->screen.sm_addr,
-			fbi->regs2d + SM501_2D_DESTINATION_BASE);
-
-	/* set the window width */
-	smc501_writel((info->var.xres << 16) | info->var.xres,
-	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
-
-	/* set window stride */
-	smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
-	       fbi->regs2d + SM501_2D_PITCH);
-
-	/* set data format */
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
-		break;
-	case 16:
-		smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
-		break;
-	case 32:
-		smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
-		break;
-	}
-
-	/* 2d compare mask */
-	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
-
-	/* 2d mask */
-	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
-
-	/* source and destination x y */
-	smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
-	smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
-
-	/* w/h */
-	smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
-
-	/* do area move */
-	smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
-}
-
-static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct sm501fb_par  *par = info->par;
-	struct sm501fb_info *fbi = par->info;
-	int width = rect->width, height = rect->height;
-
-	if ((rect->dx >= info->var.xres_virtual) ||
-	    (rect->dy >= info->var.yres_virtual))
-		/* Rectangle not within virtual screen, skipping */
-		return;
-	if ((rect->dx + width) >= info->var.xres_virtual)
-		width = info->var.xres_virtual - rect->dx - 1;
-	if ((rect->dy + height) >= info->var.yres_virtual)
-		height = info->var.yres_virtual - rect->dy - 1;
-
-	if (sm501fb_sync(info))
-		return;
-
-	/* set the base addresses */
-	smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
-	smc501_writel(par->screen.sm_addr,
-			fbi->regs2d + SM501_2D_DESTINATION_BASE);
-
-	/* set the window width */
-	smc501_writel((info->var.xres << 16) | info->var.xres,
-	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
-
-	/* set window stride */
-	smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
-	       fbi->regs2d + SM501_2D_PITCH);
-
-	/* set data format */
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
-		break;
-	case 16:
-		smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
-		break;
-	case 32:
-		smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
-		break;
-	}
-
-	/* 2d compare mask */
-	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
-
-	/* 2d mask */
-	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
-
-	/* colour */
-	smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
-
-	/* x y */
-	smc501_writel((rect->dx << 16) | rect->dy,
-			fbi->regs2d + SM501_2D_DESTINATION);
-
-	/* w/h */
-	smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
-
-	/* do rectangle fill */
-	smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
-}
-
-
-static struct fb_ops sm501fb_ops_crt = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= sm501fb_check_var_crt,
-	.fb_set_par	= sm501fb_set_par_crt,
-	.fb_blank	= sm501fb_blank_crt,
-	.fb_setcolreg	= sm501fb_setcolreg,
-	.fb_pan_display	= sm501fb_pan_crt,
-	.fb_cursor	= sm501fb_cursor,
-	.fb_fillrect	= sm501fb_fillrect,
-	.fb_copyarea	= sm501fb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_sync	= sm501fb_sync,
-};
-
-static struct fb_ops sm501fb_ops_pnl = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= sm501fb_check_var_pnl,
-	.fb_set_par	= sm501fb_set_par_pnl,
-	.fb_pan_display	= sm501fb_pan_pnl,
-	.fb_blank	= sm501fb_blank_pnl,
-	.fb_setcolreg	= sm501fb_setcolreg,
-	.fb_cursor	= sm501fb_cursor,
-	.fb_fillrect	= sm501fb_fillrect,
-	.fb_copyarea	= sm501fb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_sync	= sm501fb_sync,
-};
-
-/* sm501_init_cursor
- *
- * initialise hw cursor parameters
-*/
-
-static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
-{
-	struct sm501fb_par *par;
-	struct sm501fb_info *info;
-	int ret;
-
-	if (fbi == NULL)
-		return 0;
-
-	par = fbi->par;
-	info = par->info;
-
-	par->cursor_regs = info->regs + reg_base;
-
-	ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024,
-			      fbi->fix.smem_len);
-	if (ret < 0)
-		return ret;
-
-	/* initialise the colour registers */
-
-	smc501_writel(par->cursor.sm_addr,
-			par->cursor_regs + SM501_OFF_HWC_ADDR);
-
-	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
-	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
-	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
-	sm501fb_sync_regs(info);
-
-	return 0;
-}
-
-/* sm501fb_info_start
- *
- * fills the par structure claiming resources and remapping etc.
-*/
-
-static int sm501fb_start(struct sm501fb_info *info,
-			 struct platform_device *pdev)
-{
-	struct resource	*res;
-	struct device *dev = &pdev->dev;
-	int k;
-	int ret;
-
-	info->irq = ret = platform_get_irq(pdev, 0);
-	if (ret < 0) {
-		/* we currently do not use the IRQ */
-		dev_warn(dev, "no irq for device\n");
-	}
-
-	/* allocate, reserve and remap resources for display
-	 * controller registers */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(dev, "no resource definition for registers\n");
-		ret = -ENOENT;
-		goto err_release;
-	}
-
-	info->regs_res = request_mem_region(res->start,
-					    resource_size(res),
-					    pdev->name);
-
-	if (info->regs_res == NULL) {
-		dev_err(dev, "cannot claim registers\n");
-		ret = -ENXIO;
-		goto err_release;
-	}
-
-	info->regs = ioremap(res->start, resource_size(res));
-	if (info->regs == NULL) {
-		dev_err(dev, "cannot remap registers\n");
-		ret = -ENXIO;
-		goto err_regs_res;
-	}
-
-	/* allocate, reserve and remap resources for 2d
-	 * controller registers */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (res == NULL) {
-		dev_err(dev, "no resource definition for 2d registers\n");
-		ret = -ENOENT;
-		goto err_regs_map;
-	}
-
-	info->regs2d_res = request_mem_region(res->start,
-					      resource_size(res),
-					      pdev->name);
-
-	if (info->regs2d_res == NULL) {
-		dev_err(dev, "cannot claim registers\n");
-		ret = -ENXIO;
-		goto err_regs_map;
-	}
-
-	info->regs2d = ioremap(res->start, resource_size(res));
-	if (info->regs2d == NULL) {
-		dev_err(dev, "cannot remap registers\n");
-		ret = -ENXIO;
-		goto err_regs2d_res;
-	}
-
-	/* allocate, reserve resources for framebuffer */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	if (res == NULL) {
-		dev_err(dev, "no memory resource defined\n");
-		ret = -ENXIO;
-		goto err_regs2d_map;
-	}
-
-	info->fbmem_res = request_mem_region(res->start,
-					     resource_size(res),
-					     pdev->name);
-	if (info->fbmem_res == NULL) {
-		dev_err(dev, "cannot claim framebuffer\n");
-		ret = -ENXIO;
-		goto err_regs2d_map;
-	}
-
-	info->fbmem = ioremap(res->start, resource_size(res));
-	if (info->fbmem == NULL) {
-		dev_err(dev, "cannot remap framebuffer\n");
-		goto err_mem_res;
-	}
-
-	info->fbmem_len = resource_size(res);
-
-	/* clear framebuffer memory - avoids garbage data on unused fb */
-	memset(info->fbmem, 0, info->fbmem_len);
-
-	/* clear palette ram - undefined at power on */
-	for (k = 0; k < (256 * 3); k++)
-		smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
-
-	/* enable display controller */
-	sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
-
-	/* enable 2d controller */
-	sm501_unit_power(dev->parent, SM501_GATE_2D_ENGINE, 1);
-
-	/* setup cursors */
-	sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR);
-	sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR);
-
-	return 0; /* everything is setup */
-
- err_mem_res:
-	release_mem_region(info->fbmem_res->start,
-			   resource_size(info->fbmem_res));
-
- err_regs2d_map:
-	iounmap(info->regs2d);
-
- err_regs2d_res:
-	release_mem_region(info->regs2d_res->start,
-			   resource_size(info->regs2d_res));
-
- err_regs_map:
-	iounmap(info->regs);
-
- err_regs_res:
-	release_mem_region(info->regs_res->start,
-			   resource_size(info->regs_res));
-
- err_release:
-	return ret;
-}
-
-static void sm501fb_stop(struct sm501fb_info *info)
-{
-	/* disable display controller */
-	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
-
-	iounmap(info->fbmem);
-	release_mem_region(info->fbmem_res->start,
-			   resource_size(info->fbmem_res));
-
-	iounmap(info->regs2d);
-	release_mem_region(info->regs2d_res->start,
-			   resource_size(info->regs2d_res));
-
-	iounmap(info->regs);
-	release_mem_region(info->regs_res->start,
-			   resource_size(info->regs_res));
-}
-
-static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head,
-			   const char *fbname)
-{
-	struct sm501_platdata_fbsub *pd;
-	struct sm501fb_par *par = fb->par;
-	struct sm501fb_info *info = par->info;
-	unsigned long ctrl;
-	unsigned int enable;
-	int ret;
-
-	switch (head) {
-	case HEAD_CRT:
-		pd = info->pdata->fb_crt;
-		ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
-		enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
-
-		/* ensure we set the correct source register */
-		if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
-			ctrl |= SM501_DC_CRT_CONTROL_SEL;
-			smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
-		}
-
-		break;
-
-	case HEAD_PANEL:
-		pd = info->pdata->fb_pnl;
-		ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL);
-		enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
-		break;
-
-	default:
-		pd = NULL;		/* stop compiler warnings */
-		ctrl = 0;
-		enable = 0;
-		BUG();
-	}
-
-	dev_info(info->dev, "fb %s %sabled at start\n",
-		 fbname, enable ? "en" : "dis");
-
-	/* check to see if our routing allows this */
-
-	if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) {
-		ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
-		smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
-		enable = 0;
-	}
-
-	strlcpy(fb->fix.id, fbname, sizeof(fb->fix.id));
-
-	memcpy(&par->ops,
-	       (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
-	       sizeof(struct fb_ops));
-
-	/* update ops dependent on what we've been passed */
-
-	if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0)
-		par->ops.fb_cursor = NULL;
-
-	fb->fbops = &par->ops;
-	fb->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST |
-		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
-		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
-
-#if defined(CONFIG_OF)
-#ifdef __BIG_ENDIAN
-	if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
-		fb->flags |= FBINFO_FOREIGN_ENDIAN;
-#else
-	if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
-		fb->flags |= FBINFO_FOREIGN_ENDIAN;
-#endif
-#endif
-	/* fixed data */
-
-	fb->fix.type		= FB_TYPE_PACKED_PIXELS;
-	fb->fix.type_aux	= 0;
-	fb->fix.xpanstep	= 1;
-	fb->fix.ypanstep	= 1;
-	fb->fix.ywrapstep	= 0;
-	fb->fix.accel		= FB_ACCEL_NONE;
-
-	/* screenmode */
-
-	fb->var.nonstd		= 0;
-	fb->var.activate	= FB_ACTIVATE_NOW;
-	fb->var.accel_flags	= 0;
-	fb->var.vmode		= FB_VMODE_NONINTERLACED;
-	fb->var.bits_per_pixel  = 16;
-
-	if (info->edid_data) {
-			/* Now build modedb from EDID */
-			fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
-			fb_videomode_to_modelist(fb->monspecs.modedb,
-						 fb->monspecs.modedb_len,
-						 &fb->modelist);
-	}
-
-	if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
-		/* TODO read the mode from the current display */
-	} else {
-		if (pd->def_mode) {
-			dev_info(info->dev, "using supplied mode\n");
-			fb_videomode_to_var(&fb->var, pd->def_mode);
-
-			fb->var.bits_per_pixel = pd->def_bpp ? pd->def_bpp : 8;
-			fb->var.xres_virtual = fb->var.xres;
-			fb->var.yres_virtual = fb->var.yres;
-		} else {
-			if (info->edid_data) {
-				ret = fb_find_mode(&fb->var, fb, fb_mode,
-					fb->monspecs.modedb,
-					fb->monspecs.modedb_len,
-					&sm501_default_mode, default_bpp);
-				/* edid_data is no longer needed, free it */
-				kfree(info->edid_data);
-			} else {
-				ret = fb_find_mode(&fb->var, fb,
-					   NULL, NULL, 0, NULL, 8);
-			}
-
-			switch (ret) {
-			case 1:
-				dev_info(info->dev, "using mode specified in "
-						"@mode\n");
-				break;
-			case 2:
-				dev_info(info->dev, "using mode specified in "
-					"@mode with ignored refresh rate\n");
-				break;
-			case 3:
-				dev_info(info->dev, "using mode default "
-					"mode\n");
-				break;
-			case 4:
-				dev_info(info->dev, "using mode from list\n");
-				break;
-			default:
-				dev_info(info->dev, "ret = %d\n", ret);
-				dev_info(info->dev, "failed to find mode\n");
-				return -EINVAL;
-			}
-		}
-	}
-
-	/* initialise and set the palette */
-	if (fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0)) {
-		dev_err(info->dev, "failed to allocate cmap memory\n");
-		return -ENOMEM;
-	}
-	fb_set_cmap(&fb->cmap, fb);
-
-	ret = (fb->fbops->fb_check_var)(&fb->var, fb);
-	if (ret)
-		dev_err(info->dev, "check_var() failed on initial setup?\n");
-
-	return 0;
-}
-
-/* default platform data if none is supplied (ie, PCI device) */
-
-static struct sm501_platdata_fbsub sm501fb_pdata_crt = {
-	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
-			   SM501FB_FLAG_USE_HWCURSOR |
-			   SM501FB_FLAG_USE_HWACCEL |
-			   SM501FB_FLAG_DISABLE_AT_EXIT),
-
-};
-
-static struct sm501_platdata_fbsub sm501fb_pdata_pnl = {
-	.flags		= (SM501FB_FLAG_USE_INIT_MODE |
-			   SM501FB_FLAG_USE_HWCURSOR |
-			   SM501FB_FLAG_USE_HWACCEL |
-			   SM501FB_FLAG_DISABLE_AT_EXIT),
-};
-
-static struct sm501_platdata_fb sm501fb_def_pdata = {
-	.fb_route		= SM501_FB_OWN,
-	.fb_crt			= &sm501fb_pdata_crt,
-	.fb_pnl			= &sm501fb_pdata_pnl,
-};
-
-static char driver_name_crt[] = "sm501fb-crt";
-static char driver_name_pnl[] = "sm501fb-panel";
-
-static int sm501fb_probe_one(struct sm501fb_info *info,
-			     enum sm501_controller head)
-{
-	unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
-	struct sm501_platdata_fbsub *pd;
-	struct sm501fb_par *par;
-	struct fb_info *fbi;
-
-	pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
-
-	/* Do not initialise if we've not been given any platform data */
-	if (pd == NULL) {
-		dev_info(info->dev, "no data for fb %s (disabled)\n", name);
-		return 0;
-	}
-
-	fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
-	if (fbi == NULL) {
-		dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
-		return -ENOMEM;
-	}
-
-	par = fbi->par;
-	par->info = info;
-	par->head = head;
-	fbi->pseudo_palette = &par->pseudo_palette;
-
-	info->fb[head] = fbi;
-
-	return 0;
-}
-
-/* Free up anything allocated by sm501fb_init_fb */
-
-static void sm501_free_init_fb(struct sm501fb_info *info,
-				enum sm501_controller head)
-{
-	struct fb_info *fbi = info->fb[head];
-
-	fb_dealloc_cmap(&fbi->cmap);
-}
-
-static int sm501fb_start_one(struct sm501fb_info *info,
-			     enum sm501_controller head, const char *drvname)
-{
-	struct fb_info *fbi = info->fb[head];
-	int ret;
-
-	if (!fbi)
-		return 0;
-
-	mutex_init(&info->fb[head]->mm_lock);
-
-	ret = sm501fb_init_fb(info->fb[head], head, drvname);
-	if (ret) {
-		dev_err(info->dev, "cannot initialise fb %s\n", drvname);
-		return ret;
-	}
-
-	ret = register_framebuffer(info->fb[head]);
-	if (ret) {
-		dev_err(info->dev, "failed to register fb %s\n", drvname);
-		sm501_free_init_fb(info, head);
-		return ret;
-	}
-
-	dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
-
-	return 0;
-}
-
-static int sm501fb_probe(struct platform_device *pdev)
-{
-	struct sm501fb_info *info;
-	struct device *dev = &pdev->dev;
-	int ret;
-
-	/* allocate our framebuffers */
-
-	info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
-	if (!info) {
-		dev_err(dev, "failed to allocate state\n");
-		return -ENOMEM;
-	}
-
-	info->dev = dev = &pdev->dev;
-	platform_set_drvdata(pdev, info);
-
-	if (dev->parent->platform_data) {
-		struct sm501_platdata *pd = dev->parent->platform_data;
-		info->pdata = pd->fb;
-	}
-
-	if (info->pdata == NULL) {
-		int found = 0;
-#if defined(CONFIG_OF)
-		struct device_node *np = pdev->dev.parent->of_node;
-		const u8 *prop;
-		const char *cp;
-		int len;
-
-		info->pdata = &sm501fb_def_pdata;
-		if (np) {
-			/* Get EDID */
-			cp = of_get_property(np, "mode", &len);
-			if (cp)
-				strcpy(fb_mode, cp);
-			prop = of_get_property(np, "edid", &len);
-			if (prop && len == EDID_LENGTH) {
-				info->edid_data = kmemdup(prop, EDID_LENGTH,
-							  GFP_KERNEL);
-				if (info->edid_data)
-					found = 1;
-			}
-		}
-#endif
-		if (!found) {
-			dev_info(dev, "using default configuration data\n");
-			info->pdata = &sm501fb_def_pdata;
-		}
-	}
-
-	/* probe for the presence of each panel */
-
-	ret = sm501fb_probe_one(info, HEAD_CRT);
-	if (ret < 0) {
-		dev_err(dev, "failed to probe CRT\n");
-		goto err_alloc;
-	}
-
-	ret = sm501fb_probe_one(info, HEAD_PANEL);
-	if (ret < 0) {
-		dev_err(dev, "failed to probe PANEL\n");
-		goto err_probed_crt;
-	}
-
-	if (info->fb[HEAD_PANEL] == NULL &&
-	    info->fb[HEAD_CRT] == NULL) {
-		dev_err(dev, "no framebuffers found\n");
-		goto err_alloc;
-	}
-
-	/* get the resources for both of the framebuffers */
-
-	ret = sm501fb_start(info, pdev);
-	if (ret) {
-		dev_err(dev, "cannot initialise SM501\n");
-		goto err_probed_panel;
-	}
-
-	ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
-	if (ret) {
-		dev_err(dev, "failed to start CRT\n");
-		goto err_started;
-	}
-
-	ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
-	if (ret) {
-		dev_err(dev, "failed to start Panel\n");
-		goto err_started_crt;
-	}
-
-	/* create device files */
-
-	ret = device_create_file(dev, &dev_attr_crt_src);
-	if (ret)
-		goto err_started_panel;
-
-	ret = device_create_file(dev, &dev_attr_fbregs_pnl);
-	if (ret)
-		goto err_attached_crtsrc_file;
-
-	ret = device_create_file(dev, &dev_attr_fbregs_crt);
-	if (ret)
-		goto err_attached_pnlregs_file;
-
-	/* we registered, return ok */
-	return 0;
-
-err_attached_pnlregs_file:
-	device_remove_file(dev, &dev_attr_fbregs_pnl);
-
-err_attached_crtsrc_file:
-	device_remove_file(dev, &dev_attr_crt_src);
-
-err_started_panel:
-	unregister_framebuffer(info->fb[HEAD_PANEL]);
-	sm501_free_init_fb(info, HEAD_PANEL);
-
-err_started_crt:
-	unregister_framebuffer(info->fb[HEAD_CRT]);
-	sm501_free_init_fb(info, HEAD_CRT);
-
-err_started:
-	sm501fb_stop(info);
-
-err_probed_panel:
-	framebuffer_release(info->fb[HEAD_PANEL]);
-
-err_probed_crt:
-	framebuffer_release(info->fb[HEAD_CRT]);
-
-err_alloc:
-	kfree(info);
-
-	return ret;
-}
-
-
-/*
- *  Cleanup
- */
-static int sm501fb_remove(struct platform_device *pdev)
-{
-	struct sm501fb_info *info = platform_get_drvdata(pdev);
-	struct fb_info	   *fbinfo_crt = info->fb[0];
-	struct fb_info	   *fbinfo_pnl = info->fb[1];
-
-	device_remove_file(&pdev->dev, &dev_attr_fbregs_crt);
-	device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
-	device_remove_file(&pdev->dev, &dev_attr_crt_src);
-
-	sm501_free_init_fb(info, HEAD_CRT);
-	sm501_free_init_fb(info, HEAD_PANEL);
-
-	unregister_framebuffer(fbinfo_crt);
-	unregister_framebuffer(fbinfo_pnl);
-
-	sm501fb_stop(info);
-	kfree(info);
-
-	framebuffer_release(fbinfo_pnl);
-	framebuffer_release(fbinfo_crt);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int sm501fb_suspend_fb(struct sm501fb_info *info,
-			      enum sm501_controller head)
-{
-	struct fb_info *fbi = info->fb[head];
-	struct sm501fb_par *par = fbi->par;
-
-	if (par->screen.size == 0)
-		return 0;
-
-	/* blank the relevant interface to ensure unit power minimised */
-	(par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
-
-	/* tell console/fb driver we are suspending */
-
-	console_lock();
-	fb_set_suspend(fbi, 1);
-	console_unlock();
-
-	/* backup copies in case chip is powered down over suspend */
-
-	par->store_fb = vmalloc(par->screen.size);
-	if (par->store_fb == NULL) {
-		dev_err(info->dev, "no memory to store screen\n");
-		return -ENOMEM;
-	}
-
-	par->store_cursor = vmalloc(par->cursor.size);
-	if (par->store_cursor == NULL) {
-		dev_err(info->dev, "no memory to store cursor\n");
-		goto err_nocursor;
-	}
-
-	dev_dbg(info->dev, "suspending screen to %p\n", par->store_fb);
-	dev_dbg(info->dev, "suspending cursor to %p\n", par->store_cursor);
-
-	memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size);
-	memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size);
-
-	return 0;
-
- err_nocursor:
-	vfree(par->store_fb);
-	par->store_fb = NULL;
-
-	return -ENOMEM;
-}
-
-static void sm501fb_resume_fb(struct sm501fb_info *info,
-			      enum sm501_controller head)
-{
-	struct fb_info *fbi = info->fb[head];
-	struct sm501fb_par *par = fbi->par;
-
-	if (par->screen.size == 0)
-		return;
-
-	/* re-activate the configuration */
-
-	(par->ops.fb_set_par)(fbi);
-
-	/* restore the data */
-
-	dev_dbg(info->dev, "restoring screen from %p\n", par->store_fb);
-	dev_dbg(info->dev, "restoring cursor from %p\n", par->store_cursor);
-
-	if (par->store_fb)
-		memcpy_toio(par->screen.k_addr, par->store_fb,
-			    par->screen.size);
-
-	if (par->store_cursor)
-		memcpy_toio(par->cursor.k_addr, par->store_cursor,
-			    par->cursor.size);
-
-	console_lock();
-	fb_set_suspend(fbi, 0);
-	console_unlock();
-
-	vfree(par->store_fb);
-	vfree(par->store_cursor);
-}
-
-
-/* suspend and resume support */
-
-static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct sm501fb_info *info = platform_get_drvdata(pdev);
-
-	/* store crt control to resume with */
-	info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
-
-	sm501fb_suspend_fb(info, HEAD_CRT);
-	sm501fb_suspend_fb(info, HEAD_PANEL);
-
-	/* turn off the clocks, in case the device is not powered down */
-	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
-
-	return 0;
-}
-
-#define SM501_CRT_CTRL_SAVE (SM501_DC_CRT_CONTROL_TVP |        \
-			     SM501_DC_CRT_CONTROL_SEL)
-
-
-static int sm501fb_resume(struct platform_device *pdev)
-{
-	struct sm501fb_info *info = platform_get_drvdata(pdev);
-	unsigned long crt_ctrl;
-
-	sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1);
-
-	/* restore the items we want to be saved for crt control */
-
-	crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
-	crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
-	crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
-	smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
-
-	sm501fb_resume_fb(info, HEAD_CRT);
-	sm501fb_resume_fb(info, HEAD_PANEL);
-
-	return 0;
-}
-
-#else
-#define sm501fb_suspend NULL
-#define sm501fb_resume  NULL
-#endif
-
-static struct platform_driver sm501fb_driver = {
-	.probe		= sm501fb_probe,
-	.remove		= sm501fb_remove,
-	.suspend	= sm501fb_suspend,
-	.resume		= sm501fb_resume,
-	.driver		= {
-		.name	= "sm501-fb",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(sm501fb_driver);
-
-module_param_named(mode, fb_mode, charp, 0);
-MODULE_PARM_DESC(mode,
-	"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-module_param_named(bpp, default_bpp, ulong, 0);
-MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
-MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
-MODULE_DESCRIPTION("SM501 Framebuffer driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
deleted file mode 100644
index d513ed6a49f2..000000000000
--- a/drivers/video/smscufx.c
+++ /dev/null
@@ -1,1980 +0,0 @@
-/*
- * smscufx.c -- Framebuffer driver for SMSC UFX USB controller
- *
- * Copyright (C) 2011 Steve Glendinning <steve.glendinning@shawell.net>
- * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
- * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
- * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License v2. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Based on udlfb, with work from Florian Echtler, Henrik Bjerregaard Pedersen,
- * and others.
- *
- * Works well with Bernie Thompson's X DAMAGE patch to xf86-video-fbdev
- * available from http://git.plugable.com
- *
- * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
- * usb-skeleton by GregKH.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/uaccess.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "edid.h"
-
-#define check_warn(status, fmt, args...) \
-	({ if (status < 0) pr_warn(fmt, ##args); })
-
-#define check_warn_return(status, fmt, args...) \
-	({ if (status < 0) { pr_warn(fmt, ##args); return status; } })
-
-#define check_warn_goto_error(status, fmt, args...) \
-	({ if (status < 0) { pr_warn(fmt, ##args); goto error; } })
-
-#define all_bits_set(x, bits) (((x) & (bits)) == (bits))
-
-#define USB_VENDOR_REQUEST_WRITE_REGISTER	0xA0
-#define USB_VENDOR_REQUEST_READ_REGISTER	0xA1
-
-/*
- * TODO: Propose standard fb.h ioctl for reporting damage,
- * using _IOWR() and one of the existing area structs from fb.h
- * Consider these ioctls deprecated, but they're still used by the
- * DisplayLink X server as yet - need both to be modified in tandem
- * when new ioctl(s) are ready.
- */
-#define UFX_IOCTL_RETURN_EDID	(0xAD)
-#define UFX_IOCTL_REPORT_DAMAGE	(0xAA)
-
-/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
-#define BULK_SIZE		(512)
-#define MAX_TRANSFER		(PAGE_SIZE*16 - BULK_SIZE)
-#define WRITES_IN_FLIGHT	(4)
-
-#define GET_URB_TIMEOUT		(HZ)
-#define FREE_URB_TIMEOUT	(HZ*2)
-
-#define BPP			2
-
-#define UFX_DEFIO_WRITE_DELAY	5 /* fb_deferred_io.delay in jiffies */
-#define UFX_DEFIO_WRITE_DISABLE	(HZ*60) /* "disable" with long delay */
-
-struct dloarea {
-	int x, y;
-	int w, h;
-};
-
-struct urb_node {
-	struct list_head entry;
-	struct ufx_data *dev;
-	struct delayed_work release_urb_work;
-	struct urb *urb;
-};
-
-struct urb_list {
-	struct list_head list;
-	spinlock_t lock;
-	struct semaphore limit_sem;
-	int available;
-	int count;
-	size_t size;
-};
-
-struct ufx_data {
-	struct usb_device *udev;
-	struct device *gdev; /* &udev->dev */
-	struct fb_info *info;
-	struct urb_list urbs;
-	struct kref kref;
-	int fb_count;
-	bool virtualized; /* true when physical usb device not present */
-	struct delayed_work free_framebuffer_work;
-	atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
-	atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
-	u8 *edid; /* null until we read edid from hw or get from sysfs */
-	size_t edid_size;
-	u32 pseudo_palette[256];
-};
-
-static struct fb_fix_screeninfo ufx_fix = {
-	.id =           "smscufx",
-	.type =         FB_TYPE_PACKED_PIXELS,
-	.visual =       FB_VISUAL_TRUECOLOR,
-	.xpanstep =     0,
-	.ypanstep =     0,
-	.ywrapstep =    0,
-	.accel =        FB_ACCEL_NONE,
-};
-
-static const u32 smscufx_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
-	FBINFO_VIRTFB |	FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
-	FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
-
-static struct usb_device_id id_table[] = {
-	{USB_DEVICE(0x0424, 0x9d00),},
-	{USB_DEVICE(0x0424, 0x9d01),},
-	{},
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-/* module options */
-static bool console;   /* Optionally allow fbcon to consume first framebuffer */
-static bool fb_defio = true;  /* Optionally enable fb_defio mmap support */
-
-/* ufx keeps a list of urbs for efficient bulk transfers */
-static void ufx_urb_completion(struct urb *urb);
-static struct urb *ufx_get_urb(struct ufx_data *dev);
-static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len);
-static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size);
-static void ufx_free_urb_list(struct ufx_data *dev);
-
-/* reads a control register */
-static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data)
-{
-	u32 *buf = kmalloc(4, GFP_KERNEL);
-	int ret;
-
-	BUG_ON(!dev);
-
-	if (!buf)
-		return -ENOMEM;
-
-	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-		USB_VENDOR_REQUEST_READ_REGISTER,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
-
-	le32_to_cpus(buf);
-	*data = *buf;
-	kfree(buf);
-
-	if (unlikely(ret < 0))
-		pr_warn("Failed to read register index 0x%08x\n", index);
-
-	return ret;
-}
-
-/* writes a control register */
-static int ufx_reg_write(struct ufx_data *dev, u32 index, u32 data)
-{
-	u32 *buf = kmalloc(4, GFP_KERNEL);
-	int ret;
-
-	BUG_ON(!dev);
-
-	if (!buf)
-		return -ENOMEM;
-
-	*buf = data;
-	cpu_to_le32s(buf);
-
-	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		USB_VENDOR_REQUEST_WRITE_REGISTER,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
-
-	kfree(buf);
-
-	if (unlikely(ret < 0))
-		pr_warn("Failed to write register index 0x%08x with value "
-			"0x%08x\n", index, data);
-
-	return ret;
-}
-
-static int ufx_reg_clear_and_set_bits(struct ufx_data *dev, u32 index,
-	u32 bits_to_clear, u32 bits_to_set)
-{
-	u32 data;
-	int status = ufx_reg_read(dev, index, &data);
-	check_warn_return(status, "ufx_reg_clear_and_set_bits error reading "
-		"0x%x", index);
-
-	data &= (~bits_to_clear);
-	data |= bits_to_set;
-
-	status = ufx_reg_write(dev, index, data);
-	check_warn_return(status, "ufx_reg_clear_and_set_bits error writing "
-		"0x%x", index);
-
-	return 0;
-}
-
-static int ufx_reg_set_bits(struct ufx_data *dev, u32 index, u32 bits)
-{
-	return ufx_reg_clear_and_set_bits(dev, index, 0, bits);
-}
-
-static int ufx_reg_clear_bits(struct ufx_data *dev, u32 index, u32 bits)
-{
-	return ufx_reg_clear_and_set_bits(dev, index, bits, 0);
-}
-
-static int ufx_lite_reset(struct ufx_data *dev)
-{
-	int status;
-	u32 value;
-
-	status = ufx_reg_write(dev, 0x3008, 0x00000001);
-	check_warn_return(status, "ufx_lite_reset error writing 0x3008");
-
-	status = ufx_reg_read(dev, 0x3008, &value);
-	check_warn_return(status, "ufx_lite_reset error reading 0x3008");
-
-	return (value == 0) ? 0 : -EIO;
-}
-
-/* If display is unblanked, then blank it */
-static int ufx_blank(struct ufx_data *dev, bool wait)
-{
-	u32 dc_ctrl, dc_sts;
-	int i;
-
-	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
-	check_warn_return(status, "ufx_blank error reading 0x2004");
-
-	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
-	check_warn_return(status, "ufx_blank error reading 0x2000");
-
-	/* return success if display is already blanked */
-	if ((dc_sts & 0x00000100) || (dc_ctrl & 0x00000100))
-		return 0;
-
-	/* request the DC to blank the display */
-	dc_ctrl |= 0x00000100;
-	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
-	check_warn_return(status, "ufx_blank error writing 0x2000");
-
-	/* return success immediately if we don't have to wait */
-	if (!wait)
-		return 0;
-
-	for (i = 0; i < 250; i++) {
-		status = ufx_reg_read(dev, 0x2004, &dc_sts);
-		check_warn_return(status, "ufx_blank error reading 0x2004");
-
-		if (dc_sts & 0x00000100)
-			return 0;
-	}
-
-	/* timed out waiting for display to blank */
-	return -EIO;
-}
-
-/* If display is blanked, then unblank it */
-static int ufx_unblank(struct ufx_data *dev, bool wait)
-{
-	u32 dc_ctrl, dc_sts;
-	int i;
-
-	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
-	check_warn_return(status, "ufx_unblank error reading 0x2004");
-
-	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
-	check_warn_return(status, "ufx_unblank error reading 0x2000");
-
-	/* return success if display is already unblanked */
-	if (((dc_sts & 0x00000100) == 0) || ((dc_ctrl & 0x00000100) == 0))
-		return 0;
-
-	/* request the DC to unblank the display */
-	dc_ctrl &= ~0x00000100;
-	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
-	check_warn_return(status, "ufx_unblank error writing 0x2000");
-
-	/* return success immediately if we don't have to wait */
-	if (!wait)
-		return 0;
-
-	for (i = 0; i < 250; i++) {
-		status = ufx_reg_read(dev, 0x2004, &dc_sts);
-		check_warn_return(status, "ufx_unblank error reading 0x2004");
-
-		if ((dc_sts & 0x00000100) == 0)
-			return 0;
-	}
-
-	/* timed out waiting for display to unblank */
-	return -EIO;
-}
-
-/* If display is enabled, then disable it */
-static int ufx_disable(struct ufx_data *dev, bool wait)
-{
-	u32 dc_ctrl, dc_sts;
-	int i;
-
-	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
-	check_warn_return(status, "ufx_disable error reading 0x2004");
-
-	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
-	check_warn_return(status, "ufx_disable error reading 0x2000");
-
-	/* return success if display is already disabled */
-	if (((dc_sts & 0x00000001) == 0) || ((dc_ctrl & 0x00000001) == 0))
-		return 0;
-
-	/* request the DC to disable the display */
-	dc_ctrl &= ~(0x00000001);
-	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
-	check_warn_return(status, "ufx_disable error writing 0x2000");
-
-	/* return success immediately if we don't have to wait */
-	if (!wait)
-		return 0;
-
-	for (i = 0; i < 250; i++) {
-		status = ufx_reg_read(dev, 0x2004, &dc_sts);
-		check_warn_return(status, "ufx_disable error reading 0x2004");
-
-		if ((dc_sts & 0x00000001) == 0)
-			return 0;
-	}
-
-	/* timed out waiting for display to disable */
-	return -EIO;
-}
-
-/* If display is disabled, then enable it */
-static int ufx_enable(struct ufx_data *dev, bool wait)
-{
-	u32 dc_ctrl, dc_sts;
-	int i;
-
-	int status = ufx_reg_read(dev, 0x2004, &dc_sts);
-	check_warn_return(status, "ufx_enable error reading 0x2004");
-
-	status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
-	check_warn_return(status, "ufx_enable error reading 0x2000");
-
-	/* return success if display is already enabled */
-	if ((dc_sts & 0x00000001) || (dc_ctrl & 0x00000001))
-		return 0;
-
-	/* request the DC to enable the display */
-	dc_ctrl |= 0x00000001;
-	status = ufx_reg_write(dev, 0x2000, dc_ctrl);
-	check_warn_return(status, "ufx_enable error writing 0x2000");
-
-	/* return success immediately if we don't have to wait */
-	if (!wait)
-		return 0;
-
-	for (i = 0; i < 250; i++) {
-		status = ufx_reg_read(dev, 0x2004, &dc_sts);
-		check_warn_return(status, "ufx_enable error reading 0x2004");
-
-		if (dc_sts & 0x00000001)
-			return 0;
-	}
-
-	/* timed out waiting for display to enable */
-	return -EIO;
-}
-
-static int ufx_config_sys_clk(struct ufx_data *dev)
-{
-	int status = ufx_reg_write(dev, 0x700C, 0x8000000F);
-	check_warn_return(status, "error writing 0x700C");
-
-	status = ufx_reg_write(dev, 0x7014, 0x0010024F);
-	check_warn_return(status, "error writing 0x7014");
-
-	status = ufx_reg_write(dev, 0x7010, 0x00000000);
-	check_warn_return(status, "error writing 0x7010");
-
-	status = ufx_reg_clear_bits(dev, 0x700C, 0x0000000A);
-	check_warn_return(status, "error clearing PLL1 bypass in 0x700C");
-	msleep(1);
-
-	status = ufx_reg_clear_bits(dev, 0x700C, 0x80000000);
-	check_warn_return(status, "error clearing output gate in 0x700C");
-
-	return 0;
-}
-
-static int ufx_config_ddr2(struct ufx_data *dev)
-{
-	int status, i = 0;
-	u32 tmp;
-
-	status = ufx_reg_write(dev, 0x0004, 0x001F0F77);
-	check_warn_return(status, "error writing 0x0004");
-
-	status = ufx_reg_write(dev, 0x0008, 0xFFF00000);
-	check_warn_return(status, "error writing 0x0008");
-
-	status = ufx_reg_write(dev, 0x000C, 0x0FFF2222);
-	check_warn_return(status, "error writing 0x000C");
-
-	status = ufx_reg_write(dev, 0x0010, 0x00030814);
-	check_warn_return(status, "error writing 0x0010");
-
-	status = ufx_reg_write(dev, 0x0014, 0x00500019);
-	check_warn_return(status, "error writing 0x0014");
-
-	status = ufx_reg_write(dev, 0x0018, 0x020D0F15);
-	check_warn_return(status, "error writing 0x0018");
-
-	status = ufx_reg_write(dev, 0x001C, 0x02532305);
-	check_warn_return(status, "error writing 0x001C");
-
-	status = ufx_reg_write(dev, 0x0020, 0x0B030905);
-	check_warn_return(status, "error writing 0x0020");
-
-	status = ufx_reg_write(dev, 0x0024, 0x00000827);
-	check_warn_return(status, "error writing 0x0024");
-
-	status = ufx_reg_write(dev, 0x0028, 0x00000000);
-	check_warn_return(status, "error writing 0x0028");
-
-	status = ufx_reg_write(dev, 0x002C, 0x00000042);
-	check_warn_return(status, "error writing 0x002C");
-
-	status = ufx_reg_write(dev, 0x0030, 0x09520000);
-	check_warn_return(status, "error writing 0x0030");
-
-	status = ufx_reg_write(dev, 0x0034, 0x02223314);
-	check_warn_return(status, "error writing 0x0034");
-
-	status = ufx_reg_write(dev, 0x0038, 0x00430043);
-	check_warn_return(status, "error writing 0x0038");
-
-	status = ufx_reg_write(dev, 0x003C, 0xF00F000F);
-	check_warn_return(status, "error writing 0x003C");
-
-	status = ufx_reg_write(dev, 0x0040, 0xF380F00F);
-	check_warn_return(status, "error writing 0x0040");
-
-	status = ufx_reg_write(dev, 0x0044, 0xF00F0496);
-	check_warn_return(status, "error writing 0x0044");
-
-	status = ufx_reg_write(dev, 0x0048, 0x03080406);
-	check_warn_return(status, "error writing 0x0048");
-
-	status = ufx_reg_write(dev, 0x004C, 0x00001000);
-	check_warn_return(status, "error writing 0x004C");
-
-	status = ufx_reg_write(dev, 0x005C, 0x00000007);
-	check_warn_return(status, "error writing 0x005C");
-
-	status = ufx_reg_write(dev, 0x0100, 0x54F00012);
-	check_warn_return(status, "error writing 0x0100");
-
-	status = ufx_reg_write(dev, 0x0104, 0x00004012);
-	check_warn_return(status, "error writing 0x0104");
-
-	status = ufx_reg_write(dev, 0x0118, 0x40404040);
-	check_warn_return(status, "error writing 0x0118");
-
-	status = ufx_reg_write(dev, 0x0000, 0x00000001);
-	check_warn_return(status, "error writing 0x0000");
-
-	while (i++ < 500) {
-		status = ufx_reg_read(dev, 0x0000, &tmp);
-		check_warn_return(status, "error reading 0x0000");
-
-		if (all_bits_set(tmp, 0xC0000000))
-			return 0;
-	}
-
-	pr_err("DDR2 initialisation timed out, reg 0x0000=0x%08x", tmp);
-	return -ETIMEDOUT;
-}
-
-struct pll_values {
-	u32 div_r0;
-	u32 div_f0;
-	u32 div_q0;
-	u32 range0;
-	u32 div_r1;
-	u32 div_f1;
-	u32 div_q1;
-	u32 range1;
-};
-
-static u32 ufx_calc_range(u32 ref_freq)
-{
-	if (ref_freq >= 88000000)
-		return 7;
-
-	if (ref_freq >= 54000000)
-		return 6;
-
-	if (ref_freq >= 34000000)
-		return 5;
-
-	if (ref_freq >= 21000000)
-		return 4;
-
-	if (ref_freq >= 13000000)
-		return 3;
-
-	if (ref_freq >= 8000000)
-		return 2;
-
-	return 1;
-}
-
-/* calculates PLL divider settings for a desired target frequency */
-static void ufx_calc_pll_values(const u32 clk_pixel_pll, struct pll_values *asic_pll)
-{
-	const u32 ref_clk = 25000000;
-	u32 div_r0, div_f0, div_q0, div_r1, div_f1, div_q1;
-	u32 min_error = clk_pixel_pll;
-
-	for (div_r0 = 1; div_r0 <= 32; div_r0++) {
-		u32 ref_freq0 = ref_clk / div_r0;
-		if (ref_freq0 < 5000000)
-			break;
-
-		if (ref_freq0 > 200000000)
-			continue;
-
-		for (div_f0 = 1; div_f0 <= 256; div_f0++) {
-			u32 vco_freq0 = ref_freq0 * div_f0;
-
-			if (vco_freq0 < 350000000)
-				continue;
-
-			if (vco_freq0 > 700000000)
-				break;
-
-			for (div_q0 = 0; div_q0 < 7; div_q0++) {
-				u32 pllout_freq0 = vco_freq0 / (1 << div_q0);
-
-				if (pllout_freq0 < 5000000)
-					break;
-
-				if (pllout_freq0 > 200000000)
-					continue;
-
-				for (div_r1 = 1; div_r1 <= 32; div_r1++) {
-					u32 ref_freq1 = pllout_freq0 / div_r1;
-
-					if (ref_freq1 < 5000000)
-						break;
-
-					for (div_f1 = 1; div_f1 <= 256; div_f1++) {
-						u32 vco_freq1 = ref_freq1 * div_f1;
-
-						if (vco_freq1 < 350000000)
-							continue;
-
-						if (vco_freq1 > 700000000)
-							break;
-
-						for (div_q1 = 0; div_q1 < 7; div_q1++) {
-							u32 pllout_freq1 = vco_freq1 / (1 << div_q1);
-							int error = abs(pllout_freq1 - clk_pixel_pll);
-
-							if (pllout_freq1 < 5000000)
-								break;
-
-							if (pllout_freq1 > 700000000)
-								continue;
-
-							if (error < min_error) {
-								min_error = error;
-
-								/* final returned value is equal to calculated value - 1
-								 * because a value of 0 = divide by 1 */
-								asic_pll->div_r0 = div_r0 - 1;
-								asic_pll->div_f0 = div_f0 - 1;
-								asic_pll->div_q0 = div_q0;
-								asic_pll->div_r1 = div_r1 - 1;
-								asic_pll->div_f1 = div_f1 - 1;
-								asic_pll->div_q1 = div_q1;
-
-								asic_pll->range0 = ufx_calc_range(ref_freq0);
-								asic_pll->range1 = ufx_calc_range(ref_freq1);
-
-								if (min_error == 0)
-									return;
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-}
-
-/* sets analog bit PLL configuration values */
-static int ufx_config_pix_clk(struct ufx_data *dev, u32 pixclock)
-{
-	struct pll_values asic_pll = {0};
-	u32 value, clk_pixel, clk_pixel_pll;
-	int status;
-
-	/* convert pixclock (in ps) to frequency (in Hz) */
-	clk_pixel = PICOS2KHZ(pixclock) * 1000;
-	pr_debug("pixclock %d ps = clk_pixel %d Hz", pixclock, clk_pixel);
-
-	/* clk_pixel = 1/2 clk_pixel_pll */
-	clk_pixel_pll = clk_pixel * 2;
-
-	ufx_calc_pll_values(clk_pixel_pll, &asic_pll);
-
-	/* Keep BYPASS and RESET signals asserted until configured */
-	status = ufx_reg_write(dev, 0x7000, 0x8000000F);
-	check_warn_return(status, "error writing 0x7000");
-
-	value = (asic_pll.div_f1 | (asic_pll.div_r1 << 8) |
-		(asic_pll.div_q1 << 16) | (asic_pll.range1 << 20));
-	status = ufx_reg_write(dev, 0x7008, value);
-	check_warn_return(status, "error writing 0x7008");
-
-	value = (asic_pll.div_f0 | (asic_pll.div_r0 << 8) |
-		(asic_pll.div_q0 << 16) | (asic_pll.range0 << 20));
-	status = ufx_reg_write(dev, 0x7004, value);
-	check_warn_return(status, "error writing 0x7004");
-
-	status = ufx_reg_clear_bits(dev, 0x7000, 0x00000005);
-	check_warn_return(status,
-		"error clearing PLL0 bypass bits in 0x7000");
-	msleep(1);
-
-	status = ufx_reg_clear_bits(dev, 0x7000, 0x0000000A);
-	check_warn_return(status,
-		"error clearing PLL1 bypass bits in 0x7000");
-	msleep(1);
-
-	status = ufx_reg_clear_bits(dev, 0x7000, 0x80000000);
-	check_warn_return(status, "error clearing gate bits in 0x7000");
-
-	return 0;
-}
-
-static int ufx_set_vid_mode(struct ufx_data *dev, struct fb_var_screeninfo *var)
-{
-	u32 temp;
-	u16 h_total, h_active, h_blank_start, h_blank_end, h_sync_start, h_sync_end;
-	u16 v_total, v_active, v_blank_start, v_blank_end, v_sync_start, v_sync_end;
-
-	int status = ufx_reg_write(dev, 0x8028, 0);
-	check_warn_return(status, "ufx_set_vid_mode error disabling RGB pad");
-
-	status = ufx_reg_write(dev, 0x8024, 0);
-	check_warn_return(status, "ufx_set_vid_mode error disabling VDAC");
-
-	/* shut everything down before changing timing */
-	status = ufx_blank(dev, true);
-	check_warn_return(status, "ufx_set_vid_mode error blanking display");
-
-	status = ufx_disable(dev, true);
-	check_warn_return(status, "ufx_set_vid_mode error disabling display");
-
-	status = ufx_config_pix_clk(dev, var->pixclock);
-	check_warn_return(status, "ufx_set_vid_mode error configuring pixclock");
-
-	status = ufx_reg_write(dev, 0x2000, 0x00000104);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2000");
-
-	/* set horizontal timings */
-	h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
-	h_active = var->xres;
-	h_blank_start = var->xres + var->right_margin;
-	h_blank_end = var->xres + var->right_margin + var->hsync_len;
-	h_sync_start = var->xres + var->right_margin;
-	h_sync_end = var->xres + var->right_margin + var->hsync_len;
-
-	temp = ((h_total - 1) << 16) | (h_active - 1);
-	status = ufx_reg_write(dev, 0x2008, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2008");
-
-	temp = ((h_blank_start - 1) << 16) | (h_blank_end - 1);
-	status = ufx_reg_write(dev, 0x200C, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x200C");
-
-	temp = ((h_sync_start - 1) << 16) | (h_sync_end - 1);
-	status = ufx_reg_write(dev, 0x2010, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2010");
-
-	/* set vertical timings */
-	v_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
-	v_active = var->yres;
-	v_blank_start = var->yres + var->lower_margin;
-	v_blank_end = var->yres + var->lower_margin + var->vsync_len;
-	v_sync_start = var->yres + var->lower_margin;
-	v_sync_end = var->yres + var->lower_margin + var->vsync_len;
-
-	temp = ((v_total - 1) << 16) | (v_active - 1);
-	status = ufx_reg_write(dev, 0x2014, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2014");
-
-	temp = ((v_blank_start - 1) << 16) | (v_blank_end - 1);
-	status = ufx_reg_write(dev, 0x2018, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2018");
-
-	temp = ((v_sync_start - 1) << 16) | (v_sync_end - 1);
-	status = ufx_reg_write(dev, 0x201C, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x201C");
-
-	status = ufx_reg_write(dev, 0x2020, 0x00000000);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2020");
-
-	status = ufx_reg_write(dev, 0x2024, 0x00000000);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2024");
-
-	/* Set the frame length register (#pix * 2 bytes/pixel) */
-	temp = var->xres * var->yres * 2;
-	temp = (temp + 7) & (~0x7);
-	status = ufx_reg_write(dev, 0x2028, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2028");
-
-	/* enable desired output interface & disable others */
-	status = ufx_reg_write(dev, 0x2040, 0);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
-
-	status = ufx_reg_write(dev, 0x2044, 0);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2044");
-
-	status = ufx_reg_write(dev, 0x2048, 0);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2048");
-
-	/* set the sync polarities & enable bit */
-	temp = 0x00000001;
-	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-		temp |= 0x00000010;
-
-	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-		temp |= 0x00000008;
-
-	status = ufx_reg_write(dev, 0x2040, temp);
-	check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
-
-	/* start everything back up */
-	status = ufx_enable(dev, true);
-	check_warn_return(status, "ufx_set_vid_mode error enabling display");
-
-	/* Unblank the display */
-	status = ufx_unblank(dev, true);
-	check_warn_return(status, "ufx_set_vid_mode error unblanking display");
-
-	/* enable RGB pad */
-	status = ufx_reg_write(dev, 0x8028, 0x00000003);
-	check_warn_return(status, "ufx_set_vid_mode error enabling RGB pad");
-
-	/* enable VDAC */
-	status = ufx_reg_write(dev, 0x8024, 0x00000007);
-	check_warn_return(status, "ufx_set_vid_mode error enabling VDAC");
-
-	return 0;
-}
-
-static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	unsigned long start = vma->vm_start;
-	unsigned long size = vma->vm_end - vma->vm_start;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	unsigned long page, pos;
-
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-	if (size > info->fix.smem_len)
-		return -EINVAL;
-	if (offset > info->fix.smem_len - size)
-		return -EINVAL;
-
-	pos = (unsigned long)info->fix.smem_start + offset;
-
-	pr_debug("mmap() framebuffer addr:%lu size:%lu\n",
-		  pos, size);
-
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-}
-
-static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y,
-	int width, int height)
-{
-	size_t packed_line_len = ALIGN((width * 2), 4);
-	size_t packed_rect_len = packed_line_len * height;
-	int line;
-
-	BUG_ON(!dev);
-	BUG_ON(!dev->info);
-
-	/* command word */
-	*((u32 *)&cmd[0]) = cpu_to_le32(0x01);
-
-	/* length word */
-	*((u32 *)&cmd[2]) = cpu_to_le32(packed_rect_len + 16);
-
-	cmd[4] = cpu_to_le16(x);
-	cmd[5] = cpu_to_le16(y);
-	cmd[6] = cpu_to_le16(width);
-	cmd[7] = cpu_to_le16(height);
-
-	/* frame base address */
-	*((u32 *)&cmd[8]) = cpu_to_le32(0);
-
-	/* color mode and horizontal resolution */
-	cmd[10] = cpu_to_le16(0x4000 | dev->info->var.xres);
-
-	/* vertical resolution */
-	cmd[11] = cpu_to_le16(dev->info->var.yres);
-
-	/* packed data */
-	for (line = 0; line < height; line++) {
-		const int line_offset = dev->info->fix.line_length * (y + line);
-		const int byte_offset = line_offset + (x * BPP);
-		memcpy(&cmd[(24 + (packed_line_len * line)) / 2],
-			(char *)dev->info->fix.smem_start + byte_offset, width * BPP);
-	}
-}
-
-static int ufx_handle_damage(struct ufx_data *dev, int x, int y,
-	int width, int height)
-{
-	size_t packed_line_len = ALIGN((width * 2), 4);
-	int len, status, urb_lines, start_line = 0;
-
-	if ((width <= 0) || (height <= 0) ||
-	    (x + width > dev->info->var.xres) ||
-	    (y + height > dev->info->var.yres))
-		return -EINVAL;
-
-	if (!atomic_read(&dev->usb_active))
-		return 0;
-
-	while (start_line < height) {
-		struct urb *urb = ufx_get_urb(dev);
-		if (!urb) {
-			pr_warn("ufx_handle_damage unable to get urb");
-			return 0;
-		}
-
-		/* assume we have enough space to transfer at least one line */
-		BUG_ON(urb->transfer_buffer_length < (24 + (width * 2)));
-
-		/* calculate the maximum number of lines we could fit in */
-		urb_lines = (urb->transfer_buffer_length - 24) / packed_line_len;
-
-		/* but we might not need this many */
-		urb_lines = min(urb_lines, (height - start_line));
-
-		memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
-
-		ufx_raw_rect(dev, urb->transfer_buffer, x, (y + start_line), width, urb_lines);
-		len = 24 + (packed_line_len * urb_lines);
-
-		status = ufx_submit_urb(dev, urb, len);
-		check_warn_return(status, "Error submitting URB");
-
-		start_line += urb_lines;
-	}
-
-	return 0;
-}
-
-/* Path triggered by usermode clients who write to filesystem
- * e.g. cat filename > /dev/fb1
- * Not used by X Windows or text-mode console. But useful for testing.
- * Slow because of extra copy and we must assume all pixels dirty. */
-static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf,
-			  size_t count, loff_t *ppos)
-{
-	ssize_t result;
-	struct ufx_data *dev = info->par;
-	u32 offset = (u32) *ppos;
-
-	result = fb_sys_write(info, buf, count, ppos);
-
-	if (result > 0) {
-		int start = max((int)(offset / info->fix.line_length), 0);
-		int lines = min((u32)((result / info->fix.line_length) + 1),
-				(u32)info->var.yres);
-
-		ufx_handle_damage(dev, 0, start, info->var.xres, lines);
-	}
-
-	return result;
-}
-
-static void ufx_ops_copyarea(struct fb_info *info,
-				const struct fb_copyarea *area)
-{
-
-	struct ufx_data *dev = info->par;
-
-	sys_copyarea(info, area);
-
-	ufx_handle_damage(dev, area->dx, area->dy,
-			area->width, area->height);
-}
-
-static void ufx_ops_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	struct ufx_data *dev = info->par;
-
-	sys_imageblit(info, image);
-
-	ufx_handle_damage(dev, image->dx, image->dy,
-			image->width, image->height);
-}
-
-static void ufx_ops_fillrect(struct fb_info *info,
-			  const struct fb_fillrect *rect)
-{
-	struct ufx_data *dev = info->par;
-
-	sys_fillrect(info, rect);
-
-	ufx_handle_damage(dev, rect->dx, rect->dy, rect->width,
-			      rect->height);
-}
-
-/* NOTE: fb_defio.c is holding info->fbdefio.mutex
- *   Touching ANY framebuffer memory that triggers a page fault
- *   in fb_defio will cause a deadlock, when it also tries to
- *   grab the same mutex. */
-static void ufx_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct ufx_data *dev = info->par;
-
-	if (!fb_defio)
-		return;
-
-	if (!atomic_read(&dev->usb_active))
-		return;
-
-	/* walk the written page list and render each to device */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-		/* create a rectangle of full screen width that encloses the
-		 * entire dirty framebuffer page */
-		const int x = 0;
-		const int width = dev->info->var.xres;
-		const int y = (cur->index << PAGE_SHIFT) / (width * 2);
-		int height = (PAGE_SIZE / (width * 2)) + 1;
-		height = min(height, (int)(dev->info->var.yres - y));
-
-		BUG_ON(y >= dev->info->var.yres);
-		BUG_ON((y + height) > dev->info->var.yres);
-
-		ufx_handle_damage(dev, x, y, width, height);
-	}
-}
-
-static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd,
-			 unsigned long arg)
-{
-	struct ufx_data *dev = info->par;
-	struct dloarea *area = NULL;
-
-	if (!atomic_read(&dev->usb_active))
-		return 0;
-
-	/* TODO: Update X server to get this from sysfs instead */
-	if (cmd == UFX_IOCTL_RETURN_EDID) {
-		u8 __user *edid = (u8 __user *)arg;
-		if (copy_to_user(edid, dev->edid, dev->edid_size))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
-	if (cmd == UFX_IOCTL_REPORT_DAMAGE) {
-		/* If we have a damage-aware client, turn fb_defio "off"
-		 * To avoid perf imact of unnecessary page fault handling.
-		 * Done by resetting the delay for this fb_info to a very
-		 * long period. Pages will become writable and stay that way.
-		 * Reset to normal value when all clients have closed this fb.
-		 */
-		if (info->fbdefio)
-			info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE;
-
-		area = (struct dloarea *)arg;
-
-		if (area->x < 0)
-			area->x = 0;
-
-		if (area->x > info->var.xres)
-			area->x = info->var.xres;
-
-		if (area->y < 0)
-			area->y = 0;
-
-		if (area->y > info->var.yres)
-			area->y = info->var.yres;
-
-		ufx_handle_damage(dev, area->x, area->y, area->w, area->h);
-	}
-
-	return 0;
-}
-
-/* taken from vesafb */
-static int
-ufx_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
-	       unsigned blue, unsigned transp, struct fb_info *info)
-{
-	int err = 0;
-
-	if (regno >= info->cmap.len)
-		return 1;
-
-	if (regno < 16) {
-		if (info->var.red.offset == 10) {
-			/* 1:5:5:5 */
-			((u32 *) (info->pseudo_palette))[regno] =
-			    ((red & 0xf800) >> 1) |
-			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
-		} else {
-			/* 0:5:6:5 */
-			((u32 *) (info->pseudo_palette))[regno] =
-			    ((red & 0xf800)) |
-			    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
-		}
-	}
-
-	return err;
-}
-
-/* It's common for several clients to have framebuffer open simultaneously.
- * e.g. both fbcon and X. Makes things interesting.
- * Assumes caller is holding info->lock (for open and release at least) */
-static int ufx_ops_open(struct fb_info *info, int user)
-{
-	struct ufx_data *dev = info->par;
-
-	/* fbcon aggressively connects to first framebuffer it finds,
-	 * preventing other clients (X) from working properly. Usually
-	 * not what the user wants. Fail by default with option to enable. */
-	if (user == 0 && !console)
-		return -EBUSY;
-
-	/* If the USB device is gone, we don't accept new opens */
-	if (dev->virtualized)
-		return -ENODEV;
-
-	dev->fb_count++;
-
-	kref_get(&dev->kref);
-
-	if (fb_defio && (info->fbdefio == NULL)) {
-		/* enable defio at last moment if not disabled by client */
-
-		struct fb_deferred_io *fbdefio;
-
-		fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
-
-		if (fbdefio) {
-			fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
-			fbdefio->deferred_io = ufx_dpy_deferred_io;
-		}
-
-		info->fbdefio = fbdefio;
-		fb_deferred_io_init(info);
-	}
-
-	pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d",
-		info->node, user, info, dev->fb_count);
-
-	return 0;
-}
-
-/*
- * Called when all client interfaces to start transactions have been disabled,
- * and all references to our device instance (ufx_data) are released.
- * Every transaction must have a reference, so we know are fully spun down
- */
-static void ufx_free(struct kref *kref)
-{
-	struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
-
-	/* this function will wait for all in-flight urbs to complete */
-	if (dev->urbs.count > 0)
-		ufx_free_urb_list(dev);
-
-	pr_debug("freeing ufx_data %p", dev);
-
-	kfree(dev);
-}
-
-static void ufx_release_urb_work(struct work_struct *work)
-{
-	struct urb_node *unode = container_of(work, struct urb_node,
-					      release_urb_work.work);
-
-	up(&unode->dev->urbs.limit_sem);
-}
-
-static void ufx_free_framebuffer_work(struct work_struct *work)
-{
-	struct ufx_data *dev = container_of(work, struct ufx_data,
-					    free_framebuffer_work.work);
-	struct fb_info *info = dev->info;
-	int node = info->node;
-
-	unregister_framebuffer(info);
-
-	if (info->cmap.len != 0)
-		fb_dealloc_cmap(&info->cmap);
-	if (info->monspecs.modedb)
-		fb_destroy_modedb(info->monspecs.modedb);
-	if (info->screen_base)
-		vfree(info->screen_base);
-
-	fb_destroy_modelist(&info->modelist);
-
-	dev->info = NULL;
-
-	/* Assume info structure is freed after this point */
-	framebuffer_release(info);
-
-	pr_debug("fb_info for /dev/fb%d has been freed", node);
-
-	/* ref taken in probe() as part of registering framebfufer */
-	kref_put(&dev->kref, ufx_free);
-}
-
-/*
- * Assumes caller is holding info->lock mutex (for open and release at least)
- */
-static int ufx_ops_release(struct fb_info *info, int user)
-{
-	struct ufx_data *dev = info->par;
-
-	dev->fb_count--;
-
-	/* We can't free fb_info here - fbmem will touch it when we return */
-	if (dev->virtualized && (dev->fb_count == 0))
-		schedule_delayed_work(&dev->free_framebuffer_work, HZ);
-
-	if ((dev->fb_count == 0) && (info->fbdefio)) {
-		fb_deferred_io_cleanup(info);
-		kfree(info->fbdefio);
-		info->fbdefio = NULL;
-		info->fbops->fb_mmap = ufx_ops_mmap;
-	}
-
-	pr_debug("released /dev/fb%d user=%d count=%d",
-		  info->node, user, dev->fb_count);
-
-	kref_put(&dev->kref, ufx_free);
-
-	return 0;
-}
-
-/* Check whether a video mode is supported by the chip
- * We start from monitor's modes, so don't need to filter that here */
-static int ufx_is_valid_mode(struct fb_videomode *mode,
-		struct fb_info *info)
-{
-	if ((mode->xres * mode->yres) > (2048 * 1152)) {
-		pr_debug("%dx%d too many pixels",
-		       mode->xres, mode->yres);
-		return 0;
-	}
-
-	if (mode->pixclock < 5000) {
-		pr_debug("%dx%d %dps pixel clock too fast",
-		       mode->xres, mode->yres, mode->pixclock);
-		return 0;
-	}
-
-	pr_debug("%dx%d (pixclk %dps %dMHz) valid mode", mode->xres, mode->yres,
-		mode->pixclock, (1000000 / mode->pixclock));
-	return 1;
-}
-
-static void ufx_var_color_format(struct fb_var_screeninfo *var)
-{
-	const struct fb_bitfield red = { 11, 5, 0 };
-	const struct fb_bitfield green = { 5, 6, 0 };
-	const struct fb_bitfield blue = { 0, 5, 0 };
-
-	var->bits_per_pixel = 16;
-	var->red = red;
-	var->green = green;
-	var->blue = blue;
-}
-
-static int ufx_ops_check_var(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	struct fb_videomode mode;
-
-	/* TODO: support dynamically changing framebuffer size */
-	if ((var->xres * var->yres * 2) > info->fix.smem_len)
-		return -EINVAL;
-
-	/* set device-specific elements of var unrelated to mode */
-	ufx_var_color_format(var);
-
-	fb_var_to_videomode(&mode, var);
-
-	if (!ufx_is_valid_mode(&mode, info))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int ufx_ops_set_par(struct fb_info *info)
-{
-	struct ufx_data *dev = info->par;
-	int result;
-	u16 *pix_framebuffer;
-	int i;
-
-	pr_debug("set_par mode %dx%d", info->var.xres, info->var.yres);
-	result = ufx_set_vid_mode(dev, &info->var);
-
-	if ((result == 0) && (dev->fb_count == 0)) {
-		/* paint greenscreen */
-		pix_framebuffer = (u16 *) info->screen_base;
-		for (i = 0; i < info->fix.smem_len / 2; i++)
-			pix_framebuffer[i] = 0x37e6;
-
-		ufx_handle_damage(dev, 0, 0, info->var.xres, info->var.yres);
-	}
-
-	/* re-enable defio if previously disabled by damage tracking */
-	if (info->fbdefio)
-		info->fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
-
-	return result;
-}
-
-/* In order to come back from full DPMS off, we need to set the mode again */
-static int ufx_ops_blank(int blank_mode, struct fb_info *info)
-{
-	struct ufx_data *dev = info->par;
-	ufx_set_vid_mode(dev, &info->var);
-	return 0;
-}
-
-static struct fb_ops ufx_ops = {
-	.owner = THIS_MODULE,
-	.fb_read = fb_sys_read,
-	.fb_write = ufx_ops_write,
-	.fb_setcolreg = ufx_ops_setcolreg,
-	.fb_fillrect = ufx_ops_fillrect,
-	.fb_copyarea = ufx_ops_copyarea,
-	.fb_imageblit = ufx_ops_imageblit,
-	.fb_mmap = ufx_ops_mmap,
-	.fb_ioctl = ufx_ops_ioctl,
-	.fb_open = ufx_ops_open,
-	.fb_release = ufx_ops_release,
-	.fb_blank = ufx_ops_blank,
-	.fb_check_var = ufx_ops_check_var,
-	.fb_set_par = ufx_ops_set_par,
-};
-
-/* Assumes &info->lock held by caller
- * Assumes no active clients have framebuffer open */
-static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
-{
-	int retval = -ENOMEM;
-	int old_len = info->fix.smem_len;
-	int new_len;
-	unsigned char *old_fb = info->screen_base;
-	unsigned char *new_fb;
-
-	pr_debug("Reallocating framebuffer. Addresses will change!");
-
-	new_len = info->fix.line_length * info->var.yres;
-
-	if (PAGE_ALIGN(new_len) > old_len) {
-		/*
-		 * Alloc system memory for virtual framebuffer
-		 */
-		new_fb = vmalloc(new_len);
-		if (!new_fb) {
-			pr_err("Virtual framebuffer alloc failed");
-			goto error;
-		}
-
-		if (info->screen_base) {
-			memcpy(new_fb, old_fb, old_len);
-			vfree(info->screen_base);
-		}
-
-		info->screen_base = new_fb;
-		info->fix.smem_len = PAGE_ALIGN(new_len);
-		info->fix.smem_start = (unsigned long) new_fb;
-		info->flags = smscufx_info_flags;
-	}
-
-	retval = 0;
-
-error:
-	return retval;
-}
-
-/* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master,
- * restart enabled, but no start byte, enable controller */
-static int ufx_i2c_init(struct ufx_data *dev)
-{
-	u32 tmp;
-
-	/* disable the controller before it can be reprogrammed */
-	int status = ufx_reg_write(dev, 0x106C, 0x00);
-	check_warn_return(status, "failed to disable I2C");
-
-	/* Setup the clock count registers
-	 * (12+1) = 13 clks @ 2.5 MHz = 5.2 uS */
-	status = ufx_reg_write(dev, 0x1018, 12);
-	check_warn_return(status, "error writing 0x1018");
-
-	/* (6+8) = 14 clks @ 2.5 MHz = 5.6 uS */
-	status = ufx_reg_write(dev, 0x1014, 6);
-	check_warn_return(status, "error writing 0x1014");
-
-	status = ufx_reg_read(dev, 0x1000, &tmp);
-	check_warn_return(status, "error reading 0x1000");
-
-	/* set speed to std mode */
-	tmp &= ~(0x06);
-	tmp |= 0x02;
-
-	/* 7-bit (not 10-bit) addressing */
-	tmp &= ~(0x10);
-
-	/* enable restart conditions and master mode */
-	tmp |= 0x21;
-
-	status = ufx_reg_write(dev, 0x1000, tmp);
-	check_warn_return(status, "error writing 0x1000");
-
-	/* Set normal tx using target address 0 */
-	status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0xC00, 0x000);
-	check_warn_return(status, "error setting TX mode bits in 0x1004");
-
-	/* Enable the controller */
-	status = ufx_reg_write(dev, 0x106C, 0x01);
-	check_warn_return(status, "failed to enable I2C");
-
-	return 0;
-}
-
-/* sets the I2C port mux and target address */
-static int ufx_i2c_configure(struct ufx_data *dev)
-{
-	int status = ufx_reg_write(dev, 0x106C, 0x00);
-	check_warn_return(status, "failed to disable I2C");
-
-	status = ufx_reg_write(dev, 0x3010, 0x00000000);
-	check_warn_return(status, "failed to write 0x3010");
-
-	/* A0h is std for any EDID, right shifted by one */
-	status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0x3FF,	(0xA0 >> 1));
-	check_warn_return(status, "failed to set TAR bits in 0x1004");
-
-	status = ufx_reg_write(dev, 0x106C, 0x01);
-	check_warn_return(status, "failed to enable I2C");
-
-	return 0;
-}
-
-/* wait for BUSY to clear, with a timeout of 50ms with 10ms sleeps. if no
- * monitor is connected, there is no error except for timeout */
-static int ufx_i2c_wait_busy(struct ufx_data *dev)
-{
-	u32 tmp;
-	int i, status;
-
-	for (i = 0; i < 15; i++) {
-		status = ufx_reg_read(dev, 0x1100, &tmp);
-		check_warn_return(status, "0x1100 read failed");
-
-		/* if BUSY is clear, check for error */
-		if ((tmp & 0x80000000) == 0) {
-			if (tmp & 0x20000000) {
-				pr_warn("I2C read failed, 0x1100=0x%08x", tmp);
-				return -EIO;
-			}
-
-			return 0;
-		}
-
-		/* perform the first 10 retries without delay */
-		if (i >= 10)
-			msleep(10);
-	}
-
-	pr_warn("I2C access timed out, resetting I2C hardware");
-	status =  ufx_reg_write(dev, 0x1100, 0x40000000);
-	check_warn_return(status, "0x1100 write failed");
-
-	return -ETIMEDOUT;
-}
-
-/* reads a 128-byte EDID block from the currently selected port and TAR */
-static int ufx_read_edid(struct ufx_data *dev, u8 *edid, int edid_len)
-{
-	int i, j, status;
-	u32 *edid_u32 = (u32 *)edid;
-
-	BUG_ON(edid_len != EDID_LENGTH);
-
-	status = ufx_i2c_configure(dev);
-	if (status < 0) {
-		pr_err("ufx_i2c_configure failed");
-		return status;
-	}
-
-	memset(edid, 0xff, EDID_LENGTH);
-
-	/* Read the 128-byte EDID as 2 bursts of 64 bytes */
-	for (i = 0; i < 2; i++) {
-		u32 temp = 0x28070000 | (63 << 20) | (((u32)(i * 64)) << 8);
-		status = ufx_reg_write(dev, 0x1100, temp);
-		check_warn_return(status, "Failed to write 0x1100");
-
-		temp |= 0x80000000;
-		status = ufx_reg_write(dev, 0x1100, temp);
-		check_warn_return(status, "Failed to write 0x1100");
-
-		status = ufx_i2c_wait_busy(dev);
-		check_warn_return(status, "Timeout waiting for I2C BUSY to clear");
-
-		for (j = 0; j < 16; j++) {
-			u32 data_reg_addr = 0x1110 + (j * 4);
-			status = ufx_reg_read(dev, data_reg_addr, edid_u32++);
-			check_warn_return(status, "Error reading i2c data");
-		}
-	}
-
-	/* all FF's in the first 16 bytes indicates nothing is connected */
-	for (i = 0; i < 16; i++) {
-		if (edid[i] != 0xFF) {
-			pr_debug("edid data read successfully");
-			return EDID_LENGTH;
-		}
-	}
-
-	pr_warn("edid data contains all 0xff");
-	return -ETIMEDOUT;
-}
-
-/* 1) use sw default
- * 2) Parse into various fb_info structs
- * 3) Allocate virtual framebuffer memory to back highest res mode
- *
- * Parses EDID into three places used by various parts of fbdev:
- * fb_var_screeninfo contains the timing of the monitor's preferred mode
- * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
- * fb_info.modelist is a linked list of all monitor & VESA modes which work
- *
- * If EDID is not readable/valid, then modelist is all VESA modes,
- * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
- * Returns 0 if successful */
-static int ufx_setup_modes(struct ufx_data *dev, struct fb_info *info,
-	char *default_edid, size_t default_edid_size)
-{
-	const struct fb_videomode *default_vmode = NULL;
-	u8 *edid;
-	int i, result = 0, tries = 3;
-
-	if (info->dev) /* only use mutex if info has been registered */
-		mutex_lock(&info->lock);
-
-	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-	if (!edid) {
-		result = -ENOMEM;
-		goto error;
-	}
-
-	fb_destroy_modelist(&info->modelist);
-	memset(&info->monspecs, 0, sizeof(info->monspecs));
-
-	/* Try to (re)read EDID from hardware first
-	 * EDID data may return, but not parse as valid
-	 * Try again a few times, in case of e.g. analog cable noise */
-	while (tries--) {
-		i = ufx_read_edid(dev, edid, EDID_LENGTH);
-
-		if (i >= EDID_LENGTH)
-			fb_edid_to_monspecs(edid, &info->monspecs);
-
-		if (info->monspecs.modedb_len > 0) {
-			dev->edid = edid;
-			dev->edid_size = i;
-			break;
-		}
-	}
-
-	/* If that fails, use a previously returned EDID if available */
-	if (info->monspecs.modedb_len == 0) {
-		pr_err("Unable to get valid EDID from device/display\n");
-
-		if (dev->edid) {
-			fb_edid_to_monspecs(dev->edid, &info->monspecs);
-			if (info->monspecs.modedb_len > 0)
-				pr_err("Using previously queried EDID\n");
-		}
-	}
-
-	/* If that fails, use the default EDID we were handed */
-	if (info->monspecs.modedb_len == 0) {
-		if (default_edid_size >= EDID_LENGTH) {
-			fb_edid_to_monspecs(default_edid, &info->monspecs);
-			if (info->monspecs.modedb_len > 0) {
-				memcpy(edid, default_edid, default_edid_size);
-				dev->edid = edid;
-				dev->edid_size = default_edid_size;
-				pr_err("Using default/backup EDID\n");
-			}
-		}
-	}
-
-	/* If we've got modes, let's pick a best default mode */
-	if (info->monspecs.modedb_len > 0) {
-
-		for (i = 0; i < info->monspecs.modedb_len; i++) {
-			if (ufx_is_valid_mode(&info->monspecs.modedb[i], info))
-				fb_add_videomode(&info->monspecs.modedb[i],
-					&info->modelist);
-			else /* if we've removed top/best mode */
-				info->monspecs.misc &= ~FB_MISC_1ST_DETAIL;
-		}
-
-		default_vmode = fb_find_best_display(&info->monspecs,
-						     &info->modelist);
-	}
-
-	/* If everything else has failed, fall back to safe default mode */
-	if (default_vmode == NULL) {
-
-		struct fb_videomode fb_vmode = {0};
-
-		/* Add the standard VESA modes to our modelist
-		 * Since we don't have EDID, there may be modes that
-		 * overspec monitor and/or are incorrect aspect ratio, etc.
-		 * But at least the user has a chance to choose
-		 */
-		for (i = 0; i < VESA_MODEDB_SIZE; i++) {
-			if (ufx_is_valid_mode((struct fb_videomode *)
-						&vesa_modes[i], info))
-				fb_add_videomode(&vesa_modes[i],
-						 &info->modelist);
-		}
-
-		/* default to resolution safe for projectors
-		 * (since they are most common case without EDID)
-		 */
-		fb_vmode.xres = 800;
-		fb_vmode.yres = 600;
-		fb_vmode.refresh = 60;
-		default_vmode = fb_find_nearest_mode(&fb_vmode,
-						     &info->modelist);
-	}
-
-	/* If we have good mode and no active clients */
-	if ((default_vmode != NULL) && (dev->fb_count == 0)) {
-
-		fb_videomode_to_var(&info->var, default_vmode);
-		ufx_var_color_format(&info->var);
-
-		/* with mode size info, we can now alloc our framebuffer */
-		memcpy(&info->fix, &ufx_fix, sizeof(ufx_fix));
-		info->fix.line_length = info->var.xres *
-			(info->var.bits_per_pixel / 8);
-
-		result = ufx_realloc_framebuffer(dev, info);
-
-	} else
-		result = -EINVAL;
-
-error:
-	if (edid && (dev->edid != edid))
-		kfree(edid);
-
-	if (info->dev)
-		mutex_unlock(&info->lock);
-
-	return result;
-}
-
-static int ufx_usb_probe(struct usb_interface *interface,
-			const struct usb_device_id *id)
-{
-	struct usb_device *usbdev;
-	struct ufx_data *dev;
-	struct fb_info *info = NULL;
-	int retval = -ENOMEM;
-	u32 id_rev, fpga_rev;
-
-	/* usb initialization */
-	usbdev = interface_to_usbdev(interface);
-	BUG_ON(!usbdev);
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL) {
-		dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n");
-		goto error;
-	}
-
-	/* we need to wait for both usb and fbdev to spin down on disconnect */
-	kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
-	kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
-
-	dev->udev = usbdev;
-	dev->gdev = &usbdev->dev; /* our generic struct device * */
-	usb_set_intfdata(interface, dev);
-
-	dev_dbg(dev->gdev, "%s %s - serial #%s\n",
-		usbdev->manufacturer, usbdev->product, usbdev->serial);
-	dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n",
-		usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-		usbdev->descriptor.bcdDevice, dev);
-	dev_dbg(dev->gdev, "console enable=%d\n", console);
-	dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio);
-
-	if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
-		retval = -ENOMEM;
-		dev_err(dev->gdev, "ufx_alloc_urb_list failed\n");
-		goto error;
-	}
-
-	/* We don't register a new USB class. Our client interface is fbdev */
-
-	/* allocates framebuffer driver structure, not framebuffer memory */
-	info = framebuffer_alloc(0, &usbdev->dev);
-	if (!info) {
-		retval = -ENOMEM;
-		dev_err(dev->gdev, "framebuffer_alloc failed\n");
-		goto error;
-	}
-
-	dev->info = info;
-	info->par = dev;
-	info->pseudo_palette = dev->pseudo_palette;
-	info->fbops = &ufx_ops;
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0) {
-		dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval);
-		goto error;
-	}
-
-	INIT_DELAYED_WORK(&dev->free_framebuffer_work,
-			  ufx_free_framebuffer_work);
-
-	INIT_LIST_HEAD(&info->modelist);
-
-	retval = ufx_reg_read(dev, 0x3000, &id_rev);
-	check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
-	dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev);
-
-	retval = ufx_reg_read(dev, 0x3004, &fpga_rev);
-	check_warn_goto_error(retval, "error %d reading 0x3004 register from device", retval);
-	dev_dbg(dev->gdev, "FPGA_REV register value 0x%08x", fpga_rev);
-
-	dev_dbg(dev->gdev, "resetting device");
-	retval = ufx_lite_reset(dev);
-	check_warn_goto_error(retval, "error %d resetting device", retval);
-
-	dev_dbg(dev->gdev, "configuring system clock");
-	retval = ufx_config_sys_clk(dev);
-	check_warn_goto_error(retval, "error %d configuring system clock", retval);
-
-	dev_dbg(dev->gdev, "configuring DDR2 controller");
-	retval = ufx_config_ddr2(dev);
-	check_warn_goto_error(retval, "error %d initialising DDR2 controller", retval);
-
-	dev_dbg(dev->gdev, "configuring I2C controller");
-	retval = ufx_i2c_init(dev);
-	check_warn_goto_error(retval, "error %d initialising I2C controller", retval);
-
-	dev_dbg(dev->gdev, "selecting display mode");
-	retval = ufx_setup_modes(dev, info, NULL, 0);
-	check_warn_goto_error(retval, "unable to find common mode for display and adapter");
-
-	retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001);
-	check_warn_goto_error(retval, "error %d enabling graphics engine", retval);
-
-	/* ready to begin using device */
-	atomic_set(&dev->usb_active, 1);
-
-	dev_dbg(dev->gdev, "checking var");
-	retval = ufx_ops_check_var(&info->var, info);
-	check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval);
-
-	dev_dbg(dev->gdev, "setting par");
-	retval = ufx_ops_set_par(info);
-	check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval);
-
-	dev_dbg(dev->gdev, "registering framebuffer");
-	retval = register_framebuffer(info);
-	check_warn_goto_error(retval, "error %d register_framebuffer", retval);
-
-	dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution."
-		" Using %dK framebuffer memory\n", info->node,
-		info->var.xres, info->var.yres, info->fix.smem_len >> 10);
-
-	return 0;
-
-error:
-	if (dev) {
-		if (info) {
-			if (info->cmap.len != 0)
-				fb_dealloc_cmap(&info->cmap);
-			if (info->monspecs.modedb)
-				fb_destroy_modedb(info->monspecs.modedb);
-			if (info->screen_base)
-				vfree(info->screen_base);
-
-			fb_destroy_modelist(&info->modelist);
-
-			framebuffer_release(info);
-		}
-
-		kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
-		kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
-
-		/* dev has been deallocated. Do not dereference */
-	}
-
-	return retval;
-}
-
-static void ufx_usb_disconnect(struct usb_interface *interface)
-{
-	struct ufx_data *dev;
-	struct fb_info *info;
-
-	dev = usb_get_intfdata(interface);
-	info = dev->info;
-
-	pr_debug("USB disconnect starting\n");
-
-	/* we virtualize until all fb clients release. Then we free */
-	dev->virtualized = true;
-
-	/* When non-active we'll update virtual framebuffer, but no new urbs */
-	atomic_set(&dev->usb_active, 0);
-
-	usb_set_intfdata(interface, NULL);
-
-	/* if clients still have us open, will be freed on last close */
-	if (dev->fb_count == 0)
-		schedule_delayed_work(&dev->free_framebuffer_work, 0);
-
-	/* release reference taken by kref_init in probe() */
-	kref_put(&dev->kref, ufx_free);
-
-	/* consider ufx_data freed */
-}
-
-static struct usb_driver ufx_driver = {
-	.name = "smscufx",
-	.probe = ufx_usb_probe,
-	.disconnect = ufx_usb_disconnect,
-	.id_table = id_table,
-};
-
-module_usb_driver(ufx_driver);
-
-static void ufx_urb_completion(struct urb *urb)
-{
-	struct urb_node *unode = urb->context;
-	struct ufx_data *dev = unode->dev;
-	unsigned long flags;
-
-	/* sync/async unlink faults aren't errors */
-	if (urb->status) {
-		if (!(urb->status == -ENOENT ||
-		    urb->status == -ECONNRESET ||
-		    urb->status == -ESHUTDOWN)) {
-			pr_err("%s - nonzero write bulk status received: %d\n",
-				__func__, urb->status);
-			atomic_set(&dev->lost_pixels, 1);
-		}
-	}
-
-	urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
-
-	spin_lock_irqsave(&dev->urbs.lock, flags);
-	list_add_tail(&unode->entry, &dev->urbs.list);
-	dev->urbs.available++;
-	spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-	/* When using fb_defio, we deadlock if up() is called
-	 * while another is waiting. So queue to another process */
-	if (fb_defio)
-		schedule_delayed_work(&unode->release_urb_work, 0);
-	else
-		up(&dev->urbs.limit_sem);
-}
-
-static void ufx_free_urb_list(struct ufx_data *dev)
-{
-	int count = dev->urbs.count;
-	struct list_head *node;
-	struct urb_node *unode;
-	struct urb *urb;
-	int ret;
-	unsigned long flags;
-
-	pr_debug("Waiting for completes and freeing all render urbs\n");
-
-	/* keep waiting and freeing, until we've got 'em all */
-	while (count--) {
-		/* Getting interrupted means a leak, but ok at shutdown*/
-		ret = down_interruptible(&dev->urbs.limit_sem);
-		if (ret)
-			break;
-
-		spin_lock_irqsave(&dev->urbs.lock, flags);
-
-		node = dev->urbs.list.next; /* have reserved one with sem */
-		list_del_init(node);
-
-		spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-		unode = list_entry(node, struct urb_node, entry);
-		urb = unode->urb;
-
-		/* Free each separately allocated piece */
-		usb_free_coherent(urb->dev, dev->urbs.size,
-				  urb->transfer_buffer, urb->transfer_dma);
-		usb_free_urb(urb);
-		kfree(node);
-	}
-}
-
-static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size)
-{
-	int i = 0;
-	struct urb *urb;
-	struct urb_node *unode;
-	char *buf;
-
-	spin_lock_init(&dev->urbs.lock);
-
-	dev->urbs.size = size;
-	INIT_LIST_HEAD(&dev->urbs.list);
-
-	while (i < count) {
-		unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
-		if (!unode)
-			break;
-		unode->dev = dev;
-
-		INIT_DELAYED_WORK(&unode->release_urb_work,
-			  ufx_release_urb_work);
-
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb) {
-			kfree(unode);
-			break;
-		}
-		unode->urb = urb;
-
-		buf = usb_alloc_coherent(dev->udev, size, GFP_KERNEL,
-					 &urb->transfer_dma);
-		if (!buf) {
-			kfree(unode);
-			usb_free_urb(urb);
-			break;
-		}
-
-		/* urb->transfer_buffer_length set to actual before submit */
-		usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
-			buf, size, ufx_urb_completion, unode);
-		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-		list_add_tail(&unode->entry, &dev->urbs.list);
-
-		i++;
-	}
-
-	sema_init(&dev->urbs.limit_sem, i);
-	dev->urbs.count = i;
-	dev->urbs.available = i;
-
-	pr_debug("allocated %d %d byte urbs\n", i, (int) size);
-
-	return i;
-}
-
-static struct urb *ufx_get_urb(struct ufx_data *dev)
-{
-	int ret = 0;
-	struct list_head *entry;
-	struct urb_node *unode;
-	struct urb *urb = NULL;
-	unsigned long flags;
-
-	/* Wait for an in-flight buffer to complete and get re-queued */
-	ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
-	if (ret) {
-		atomic_set(&dev->lost_pixels, 1);
-		pr_warn("wait for urb interrupted: %x available: %d\n",
-		       ret, dev->urbs.available);
-		goto error;
-	}
-
-	spin_lock_irqsave(&dev->urbs.lock, flags);
-
-	BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
-	entry = dev->urbs.list.next;
-	list_del_init(entry);
-	dev->urbs.available--;
-
-	spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-	unode = list_entry(entry, struct urb_node, entry);
-	urb = unode->urb;
-
-error:
-	return urb;
-}
-
-static int ufx_submit_urb(struct ufx_data *dev, struct urb *urb, size_t len)
-{
-	int ret;
-
-	BUG_ON(len > dev->urbs.size);
-
-	urb->transfer_buffer_length = len; /* set to actual payload len */
-	ret = usb_submit_urb(urb, GFP_KERNEL);
-	if (ret) {
-		ufx_urb_completion(urb); /* because no one else will */
-		atomic_set(&dev->lost_pixels, 1);
-		pr_err("usb_submit_urb error %x\n", ret);
-	}
-	return ret;
-}
-
-module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(console, "Allow fbcon to be used on this display");
-
-module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support");
-
-MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>");
-MODULE_DESCRIPTION("SMSC UFX kernel framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
deleted file mode 100644
index f4daa59f0a80..000000000000
--- a/drivers/video/ssd1307fb.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Driver for the Solomon SSD1307 OLED controller
- *
- * Copyright 2012 Free Electrons
- *
- * Licensed under the GPLv2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/uaccess.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/pwm.h>
-#include <linux/delay.h>
-
-#define SSD1307FB_DATA			0x40
-#define SSD1307FB_COMMAND		0x80
-
-#define SSD1307FB_SET_ADDRESS_MODE	0x20
-#define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL	(0x00)
-#define SSD1307FB_SET_ADDRESS_MODE_VERTICAL	(0x01)
-#define SSD1307FB_SET_ADDRESS_MODE_PAGE		(0x02)
-#define SSD1307FB_SET_COL_RANGE		0x21
-#define SSD1307FB_SET_PAGE_RANGE	0x22
-#define SSD1307FB_CONTRAST		0x81
-#define	SSD1307FB_CHARGE_PUMP		0x8d
-#define SSD1307FB_SEG_REMAP_ON		0xa1
-#define SSD1307FB_DISPLAY_OFF		0xae
-#define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
-#define SSD1307FB_DISPLAY_ON		0xaf
-#define SSD1307FB_START_PAGE_ADDRESS	0xb0
-#define SSD1307FB_SET_DISPLAY_OFFSET	0xd3
-#define	SSD1307FB_SET_CLOCK_FREQ	0xd5
-#define	SSD1307FB_SET_PRECHARGE_PERIOD	0xd9
-#define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
-#define	SSD1307FB_SET_VCOMH		0xdb
-
-struct ssd1307fb_par;
-
-struct ssd1307fb_ops {
-	int (*init)(struct ssd1307fb_par *);
-	int (*remove)(struct ssd1307fb_par *);
-};
-
-struct ssd1307fb_par {
-	struct i2c_client *client;
-	u32 height;
-	struct fb_info *info;
-	struct ssd1307fb_ops *ops;
-	u32 page_offset;
-	struct pwm_device *pwm;
-	u32 pwm_period;
-	int reset;
-	u32 width;
-};
-
-struct ssd1307fb_array {
-	u8	type;
-	u8	data[0];
-};
-
-static struct fb_fix_screeninfo ssd1307fb_fix = {
-	.id		= "Solomon SSD1307",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.visual		= FB_VISUAL_MONO10,
-	.xpanstep	= 0,
-	.ypanstep	= 0,
-	.ywrapstep	= 0,
-	.accel		= FB_ACCEL_NONE,
-};
-
-static struct fb_var_screeninfo ssd1307fb_var = {
-	.bits_per_pixel	= 1,
-};
-
-static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
-{
-	struct ssd1307fb_array *array;
-
-	array = kzalloc(sizeof(struct ssd1307fb_array) + len, GFP_KERNEL);
-	if (!array)
-		return NULL;
-
-	array->type = type;
-
-	return array;
-}
-
-static int ssd1307fb_write_array(struct i2c_client *client,
-				 struct ssd1307fb_array *array, u32 len)
-{
-	int ret;
-
-	len += sizeof(struct ssd1307fb_array);
-
-	ret = i2c_master_send(client, (u8 *)array, len);
-	if (ret != len) {
-		dev_err(&client->dev, "Couldn't send I2C command.\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
-{
-	struct ssd1307fb_array *array;
-	int ret;
-
-	array = ssd1307fb_alloc_array(1, SSD1307FB_COMMAND);
-	if (!array)
-		return -ENOMEM;
-
-	array->data[0] = cmd;
-
-	ret = ssd1307fb_write_array(client, array, 1);
-	kfree(array);
-
-	return ret;
-}
-
-static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
-{
-	struct ssd1307fb_array *array;
-	int ret;
-
-	array = ssd1307fb_alloc_array(1, SSD1307FB_DATA);
-	if (!array)
-		return -ENOMEM;
-
-	array->data[0] = data;
-
-	ret = ssd1307fb_write_array(client, array, 1);
-	kfree(array);
-
-	return ret;
-}
-
-static void ssd1307fb_update_display(struct ssd1307fb_par *par)
-{
-	struct ssd1307fb_array *array;
-	u8 *vmem = par->info->screen_base;
-	int i, j, k;
-
-	array = ssd1307fb_alloc_array(par->width * par->height / 8,
-				      SSD1307FB_DATA);
-	if (!array)
-		return;
-
-	/*
-	 * The screen is divided in pages, each having a height of 8
-	 * pixels, and the width of the screen. When sending a byte of
-	 * data to the controller, it gives the 8 bits for the current
-	 * column. I.e, the first byte are the 8 bits of the first
-	 * column, then the 8 bits for the second column, etc.
-	 *
-	 *
-	 * Representation of the screen, assuming it is 5 bits
-	 * wide. Each letter-number combination is a bit that controls
-	 * one pixel.
-	 *
-	 * A0 A1 A2 A3 A4
-	 * B0 B1 B2 B3 B4
-	 * C0 C1 C2 C3 C4
-	 * D0 D1 D2 D3 D4
-	 * E0 E1 E2 E3 E4
-	 * F0 F1 F2 F3 F4
-	 * G0 G1 G2 G3 G4
-	 * H0 H1 H2 H3 H4
-	 *
-	 * If you want to update this screen, you need to send 5 bytes:
-	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
-	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
-	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
-	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
-	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
-	 */
-
-	for (i = 0; i < (par->height / 8); i++) {
-		for (j = 0; j < par->width; j++) {
-			u32 array_idx = i * par->width + j;
-			array->data[array_idx] = 0;
-			for (k = 0; k < 8; k++) {
-				u32 page_length = par->width * i;
-				u32 index = page_length + (par->width * k + j) / 8;
-				u8 byte = *(vmem + index);
-				u8 bit = byte & (1 << (j % 8));
-				bit = bit >> (j % 8);
-				array->data[array_idx] |= bit << k;
-			}
-		}
-	}
-
-	ssd1307fb_write_array(par->client, array, par->width * par->height / 8);
-	kfree(array);
-}
-
-
-static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
-		size_t count, loff_t *ppos)
-{
-	struct ssd1307fb_par *par = info->par;
-	unsigned long total_size;
-	unsigned long p = *ppos;
-	u8 __iomem *dst;
-
-	total_size = info->fix.smem_len;
-
-	if (p > total_size)
-		return -EINVAL;
-
-	if (count + p > total_size)
-		count = total_size - p;
-
-	if (!count)
-		return -EINVAL;
-
-	dst = (void __force *) (info->screen_base + p);
-
-	if (copy_from_user(dst, buf, count))
-		return -EFAULT;
-
-	ssd1307fb_update_display(par);
-
-	*ppos += count;
-
-	return count;
-}
-
-static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct ssd1307fb_par *par = info->par;
-	sys_fillrect(info, rect);
-	ssd1307fb_update_display(par);
-}
-
-static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct ssd1307fb_par *par = info->par;
-	sys_copyarea(info, area);
-	ssd1307fb_update_display(par);
-}
-
-static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct ssd1307fb_par *par = info->par;
-	sys_imageblit(info, image);
-	ssd1307fb_update_display(par);
-}
-
-static struct fb_ops ssd1307fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_read	= fb_sys_read,
-	.fb_write	= ssd1307fb_write,
-	.fb_fillrect	= ssd1307fb_fillrect,
-	.fb_copyarea	= ssd1307fb_copyarea,
-	.fb_imageblit	= ssd1307fb_imageblit,
-};
-
-static void ssd1307fb_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	ssd1307fb_update_display(info->par);
-}
-
-static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
-	.deferred_io	= ssd1307fb_deferred_io,
-};
-
-static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
-{
-	int ret;
-
-	par->pwm = pwm_get(&par->client->dev, NULL);
-	if (IS_ERR(par->pwm)) {
-		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
-		return PTR_ERR(par->pwm);
-	}
-
-	par->pwm_period = pwm_get_period(par->pwm);
-	/* Enable the PWM */
-	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
-	pwm_enable(par->pwm);
-
-	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
-		par->pwm->pwm, par->pwm_period);
-
-	/* Map column 127 of the OLED to segment 0 */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
-{
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
-	return 0;
-}
-
-static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
-	.init	= ssd1307fb_ssd1307_init,
-	.remove	= ssd1307fb_ssd1307_remove,
-};
-
-static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
-{
-	int ret;
-
-	/* Set initial contrast */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x7f);
-	if (ret < 0)
-		return ret;
-
-	/* Set COM direction */
-	ret = ssd1307fb_write_cmd(par->client, 0xc8);
-	if (ret < 0)
-		return ret;
-
-	/* Set segment re-map */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Set multiplex ratio value */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO);
-	ret = ret & ssd1307fb_write_cmd(par->client, par->height - 1);
-	if (ret < 0)
-		return ret;
-
-	/* set display offset value */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET);
-	ret = ssd1307fb_write_cmd(par->client, 0x20);
-	if (ret < 0)
-		return ret;
-
-	/* Set clock frequency */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0xf0);
-	if (ret < 0)
-		return ret;
-
-	/* Set precharge period in number of ticks from the internal clock */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
-	if (ret < 0)
-		return ret;
-
-	/* Set COM pins configuration */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
-	if (ret < 0)
-		return ret;
-
-	/* Set VCOMH */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x49);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the DC-DC Charge Pump */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x14);
-	if (ret < 0)
-		return ret;
-
-	/* Switch to horizontal addressing mode */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
-	ret = ret & ssd1307fb_write_cmd(par->client,
-					SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
-	if (ret < 0)
-		return ret;
-
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
-	ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1);
-	if (ret < 0)
-		return ret;
-
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
-	ret = ret & ssd1307fb_write_cmd(par->client,
-					par->page_offset + (par->height / 8) - 1);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
-	.init	= ssd1307fb_ssd1306_init,
-};
-
-static const struct of_device_id ssd1307fb_of_match[] = {
-	{
-		.compatible = "solomon,ssd1306fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1306_ops,
-	},
-	{
-		.compatible = "solomon,ssd1307fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1307_ops,
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
-
-static int ssd1307fb_probe(struct i2c_client *client,
-			   const struct i2c_device_id *id)
-{
-	struct fb_info *info;
-	struct device_node *node = client->dev.of_node;
-	u32 vmem_size;
-	struct ssd1307fb_par *par;
-	u8 *vmem;
-	int ret;
-
-	if (!node) {
-		dev_err(&client->dev, "No device tree data found!\n");
-		return -EINVAL;
-	}
-
-	info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
-	if (!info) {
-		dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	par->info = info;
-	par->client = client;
-
-	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
-							   &client->dev)->data;
-
-	par->reset = of_get_named_gpio(client->dev.of_node,
-					 "reset-gpios", 0);
-	if (!gpio_is_valid(par->reset)) {
-		ret = -EINVAL;
-		goto fb_alloc_error;
-	}
-
-	if (of_property_read_u32(node, "solomon,width", &par->width))
-		par->width = 96;
-
-	if (of_property_read_u32(node, "solomon,height", &par->height))
-		par->width = 16;
-
-	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
-		par->page_offset = 1;
-
-	vmem_size = par->width * par->height / 8;
-
-	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
-	if (!vmem) {
-		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
-		ret = -ENOMEM;
-		goto fb_alloc_error;
-	}
-
-	info->fbops = &ssd1307fb_ops;
-	info->fix = ssd1307fb_fix;
-	info->fix.line_length = par->width / 8;
-	info->fbdefio = &ssd1307fb_defio;
-
-	info->var = ssd1307fb_var;
-	info->var.xres = par->width;
-	info->var.xres_virtual = par->width;
-	info->var.yres = par->height;
-	info->var.yres_virtual = par->height;
-
-	info->var.red.length = 1;
-	info->var.red.offset = 0;
-	info->var.green.length = 1;
-	info->var.green.offset = 0;
-	info->var.blue.length = 1;
-	info->var.blue.offset = 0;
-
-	info->screen_base = (u8 __force __iomem *)vmem;
-	info->fix.smem_start = (unsigned long)vmem;
-	info->fix.smem_len = vmem_size;
-
-	fb_deferred_io_init(info);
-
-	ret = devm_gpio_request_one(&client->dev, par->reset,
-				    GPIOF_OUT_INIT_HIGH,
-				    "oled-reset");
-	if (ret) {
-		dev_err(&client->dev,
-			"failed to request gpio %d: %d\n",
-			par->reset, ret);
-		goto reset_oled_error;
-	}
-
-	i2c_set_clientdata(client, info);
-
-	/* Reset the screen */
-	gpio_set_value(par->reset, 0);
-	udelay(4);
-	gpio_set_value(par->reset, 1);
-	udelay(4);
-
-	if (par->ops->init) {
-		ret = par->ops->init(par);
-		if (ret)
-			goto reset_oled_error;
-	}
-
-	ret = register_framebuffer(info);
-	if (ret) {
-		dev_err(&client->dev, "Couldn't register the framebuffer\n");
-		goto panel_init_error;
-	}
-
-	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
-
-	return 0;
-
-panel_init_error:
-	if (par->ops->remove)
-		par->ops->remove(par);
-reset_oled_error:
-	fb_deferred_io_cleanup(info);
-fb_alloc_error:
-	framebuffer_release(info);
-	return ret;
-}
-
-static int ssd1307fb_remove(struct i2c_client *client)
-{
-	struct fb_info *info = i2c_get_clientdata(client);
-	struct ssd1307fb_par *par = info->par;
-
-	unregister_framebuffer(info);
-	if (par->ops->remove)
-		par->ops->remove(par);
-	fb_deferred_io_cleanup(info);
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct i2c_device_id ssd1307fb_i2c_id[] = {
-	{ "ssd1306fb", 0 },
-	{ "ssd1307fb", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
-
-static struct i2c_driver ssd1307fb_driver = {
-	.probe = ssd1307fb_probe,
-	.remove = ssd1307fb_remove,
-	.id_table = ssd1307fb_i2c_id,
-	.driver = {
-		.name = "ssd1307fb",
-		.of_match_table = ssd1307fb_of_match,
-		.owner = THIS_MODULE,
-	},
-};
-
-module_i2c_driver(ssd1307fb_driver);
-
-MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controller");
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
deleted file mode 100644
index f0cb279ef333..000000000000
--- a/drivers/video/sstfb.c
+++ /dev/null
@@ -1,1532 +0,0 @@
-/*
- * linux/drivers/video/sstfb.c -- voodoo graphics frame buffer
- *
- *     Copyright (c) 2000-2002 Ghozlane Toumi <gtoumi@laposte.net>
- *
- *     Created 15 Jan 2000 by Ghozlane Toumi
- *
- * Contributions (and many thanks) :
- *
- * 03/2001 James Simmons   <jsimmons@infradead.org>
- * 04/2001 Paul Mundt      <lethal@chaoticdreams.org>
- * 05/2001 Urs Ganse       <ursg@uni.de>
- *	(initial work on voodoo2 port, interlace)
- * 09/2002 Helge Deller    <deller@gmx.de>
- *	(enable driver on big-endian machines (hppa), ioctl fixes)
- * 12/2002 Helge Deller    <deller@gmx.de>
- *	(port driver to new frambuffer infrastructure)
- * 01/2003 Helge Deller    <deller@gmx.de>
- *	(initial work on fb hardware acceleration for voodoo2)
- * 08/2006 Alan Cox 	   <alan@redhat.com>
- *	Remove never finished and bogus 24/32bit support
- *	Clean up macro abuse
- *	Minor tidying for format.
- * 12/2006 Helge Deller    <deller@gmx.de>
- *	add /sys/class/graphics/fbX/vgapass sysfs-interface
- *	add module option "mode_option" to set initial screen mode
- *	use fbdev default videomode database
- *	remove debug functions from ioctl
- */
-
-/*
- * The voodoo1 has the following memory mapped address space:
- * 0x000000 - 0x3fffff : registers              (4MB)
- * 0x400000 - 0x7fffff : linear frame buffer    (4MB)
- * 0x800000 - 0xffffff : texture memory         (8MB)
- */
-
-/*
- * misc notes, TODOs, toASKs, and deep thoughts
-
--TODO: at one time or another test that the mode is acceptable by the monitor
--ASK: Can I choose different ordering for the color bitfields (rgba argb ...)
-      which one should i use ? is there any preferred one ? It seems ARGB is
-      the one ...
--TODO: in  set_var check the validity of timings (hsync vsync)...
--TODO: check and recheck the use of sst_wait_idle : we don't flush the fifo via
-       a nop command. so it's ok as long as the commands we pass don't go
-       through the fifo. warning: issuing a nop command seems to need pci_fifo
--FIXME: in case of failure in the init sequence, be sure we return to a safe
-        state.
-- FIXME: Use accelerator for 2D scroll
--FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)
- */
-
-/*
- * debug info
- * SST_DEBUG : enable debugging
- * SST_DEBUG_REG : debug registers
- *   0 :  no debug
- *   1 : dac calls, [un]set_bits, FbiInit
- *   2 : insane debug level (log every register read/write)
- * SST_DEBUG_FUNC : functions
- *   0 : no debug
- *   1 : function call / debug ioctl
- *   2 : variables
- *   3 : flood . you don't want to do that. trust me.
- * SST_DEBUG_VAR : debug display/var structs
- *   0 : no debug
- *   1 : dumps display, fb_var
- *
- * sstfb specific ioctls:
- *   		toggle vga (0x46db) : toggle vga_pass_through
- */
-
-#undef SST_DEBUG
-
-
-/*
- * Includes
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <video/sstfb.h>
-
-
-/* initialized by setup */
-
-static bool vgapass;		/* enable VGA passthrough cable */
-static int mem;			/* mem size in MB, 0 = autodetect */
-static bool clipping = 1;	/* use clipping (slower, safer) */
-static int gfxclk;		/* force FBI freq in Mhz . Dangerous */
-static bool slowpci;		/* slow PCI settings */
-
-/*
-  Possible default video modes: 800x600@60, 640x480@75, 1024x768@76, 640x480@60
-*/
-#define DEFAULT_VIDEO_MODE "640x480@60"
-
-static char *mode_option = DEFAULT_VIDEO_MODE;
-
-enum {
-	ID_VOODOO1 = 0,
-	ID_VOODOO2 = 1,
-};
-
-#define IS_VOODOO2(par) ((par)->type == ID_VOODOO2)
-
-static struct sst_spec voodoo_spec[] = {
- { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
- { .name = "Voodoo2",	      .default_gfx_clock = 75000, .max_gfxclk = 85 },
-};
-
-
-/*
- * debug functions
- */
-
-#if (SST_DEBUG_REG > 0)
-static void sst_dbg_print_read_reg(u32 reg, u32 val) {
-	const char *regname;
-	switch (reg) {
-	case FBIINIT0:	regname = "FbiInit0"; break;
-	case FBIINIT1:	regname = "FbiInit1"; break;
-	case FBIINIT2:	regname = "FbiInit2"; break;
-	case FBIINIT3:	regname = "FbiInit3"; break;
-	case FBIINIT4:	regname = "FbiInit4"; break;
-	case FBIINIT5:	regname = "FbiInit5"; break;
-	case FBIINIT6:	regname = "FbiInit6"; break;
-	default:	regname = NULL;       break;
-	}
-	if (regname == NULL)
-		r_ddprintk("sst_read(%#x): %#x\n", reg, val);
-	else
-		r_dprintk(" sst_read(%s): %#x\n", regname, val);
-}
-
-static void sst_dbg_print_write_reg(u32 reg, u32 val) {
-	const char *regname;
-	switch (reg) {
-	case FBIINIT0:	regname = "FbiInit0"; break;
-	case FBIINIT1:	regname = "FbiInit1"; break;
-	case FBIINIT2:	regname = "FbiInit2"; break;
-	case FBIINIT3:	regname = "FbiInit3"; break;
-	case FBIINIT4:	regname = "FbiInit4"; break;
-	case FBIINIT5:	regname = "FbiInit5"; break;
-	case FBIINIT6:	regname = "FbiInit6"; break;
-	default:	regname = NULL;       break;
-	}
-	if (regname == NULL)
-		r_ddprintk("sst_write(%#x, %#x)\n", reg, val);
-	else
-		r_dprintk(" sst_write(%s, %#x)\n", regname, val);
-}
-#else /*  (SST_DEBUG_REG > 0) */
-#  define sst_dbg_print_read_reg(reg, val)	do {} while(0)
-#  define sst_dbg_print_write_reg(reg, val)	do {} while(0)
-#endif /*  (SST_DEBUG_REG > 0) */
-
-/*
- * hardware access functions
- */
-
-/* register access */
-#define sst_read(reg)		__sst_read(par->mmio_vbase, reg)
-#define sst_write(reg,val)	__sst_write(par->mmio_vbase, reg, val)
-#define sst_set_bits(reg,val)	__sst_set_bits(par->mmio_vbase, reg, val)
-#define sst_unset_bits(reg,val)	__sst_unset_bits(par->mmio_vbase, reg, val)
-#define sst_dac_read(reg)	__sst_dac_read(par->mmio_vbase, reg)
-#define sst_dac_write(reg,val)	__sst_dac_write(par->mmio_vbase, reg, val)
-#define dac_i_read(reg)		__dac_i_read(par->mmio_vbase, reg)
-#define dac_i_write(reg,val)	__dac_i_write(par->mmio_vbase, reg, val)
-
-static inline u32 __sst_read(u8 __iomem *vbase, u32 reg)
-{
-	u32 ret = readl(vbase + reg);
-	sst_dbg_print_read_reg(reg, ret);
-	return ret;
-}
-
-static inline void __sst_write(u8 __iomem *vbase, u32 reg, u32 val)
-{
-	sst_dbg_print_write_reg(reg, val);
-	writel(val, vbase + reg);
-}
-
-static inline void __sst_set_bits(u8 __iomem *vbase, u32 reg, u32 val)
-{
-	r_dprintk("sst_set_bits(%#x, %#x)\n", reg, val);
-	__sst_write(vbase, reg, __sst_read(vbase, reg) | val);
-}
-
-static inline void __sst_unset_bits(u8 __iomem *vbase, u32 reg, u32 val)
-{
-	r_dprintk("sst_unset_bits(%#x, %#x)\n", reg, val);
-	__sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);
-}
-
-/*
- * wait for the fbi chip. ASK: what happens if the fbi is stuck ?
- *
- * the FBI is supposed to be ready if we receive 5 time
- * in a row a "idle" answer to our requests
- */
-
-#define sst_wait_idle() __sst_wait_idle(par->mmio_vbase)
-
-static int __sst_wait_idle(u8 __iomem *vbase)
-{
-	int count = 0;
-
-	/* if (doFBINOP) __sst_write(vbase, NOPCMD, 0); */
-
-	while(1) {
-		if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
-			f_dddprintk("status: busy\n");
-/* FIXME basically, this is a busy wait. maybe not that good. oh well;
- * this is a small loop after all.
- * Or maybe we should use mdelay() or udelay() here instead ? */
-			count = 0;
-		} else {
-			count++;
-			f_dddprintk("status: idle(%d)\n", count);
-		}
-		if (count >= 5) return 1;
-/* XXX  do something to avoid hanging the machine if the voodoo is out */
-	}
-}
-
-
-/* dac access */
-/* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */
-static u8 __sst_dac_read(u8 __iomem *vbase, u8 reg)
-{
-	u8 ret;
-
-	reg &= 0x07;
-	__sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
-	__sst_wait_idle(vbase);
-	/* udelay(10); */
-	ret = __sst_read(vbase, DAC_READ) & 0xff;
-	r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
-
-	return ret;
-}
-
-static void __sst_dac_write(u8 __iomem *vbase, u8 reg, u8 val)
-{
-	r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);
-	reg &= 0x07;
-	__sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);
-	__sst_wait_idle(vbase);
-}
-
-/* indexed access to ti/att dacs */
-static u32 __dac_i_read(u8 __iomem *vbase, u8 reg)
-{
-	u32 ret;
-
-	__sst_dac_write(vbase, DACREG_ADDR_I, reg);
-	ret = __sst_dac_read(vbase, DACREG_DATA_I);
-	r_dprintk("sst_dac_read_i(%#x): %#x\n", reg, ret);
-	return ret;
-}
-static void __dac_i_write(u8 __iomem *vbase, u8 reg,u8 val)
-{
-	r_dprintk("sst_dac_write_i(%#x, %#x)\n", reg, val);
-	__sst_dac_write(vbase, DACREG_ADDR_I, reg);
-	__sst_dac_write(vbase, DACREG_DATA_I, val);
-}
-
-/* compute the m,n,p  , returns the real freq
- * (ics datasheet :  N <-> N1 , P <-> N2)
- *
- * Fout= Fref * (M+2)/( 2^P * (N+2))
- *  we try to get close to the asked freq
- *  with P as high, and M as low as possible
- * range:
- * ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63
- * ics    : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31
- * we'll use the lowest limitation, should be precise enouth
- */
-static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
-{
-	int m, m2, n, p, best_err, fout;
-	int best_n = -1;
-	int best_m = -1;
-
-	best_err = freq;
-	p = 3;
-	/* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
-	while (((1 << p) * freq > VCO_MAX) && (p >= 0))
-		p--;
-	if (p == -1)
-		return -EINVAL;
-	for (n = 1; n < 32; n++) {
-		/* calc 2 * m so we can round it later*/
-		m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
-
-		m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
-		if (m >= 128)
-			break;
-		fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
-		if ((abs(fout - freq) < best_err) && (m > 0)) {
-			best_n = n;
-			best_m = m;
-			best_err = abs(fout - freq);
-			/* we get the lowest m , allowing 0.5% error in freq*/
-			if (200*best_err < freq) break;
-		}
-	}
-	if (best_n == -1)  /* unlikely, but who knows ? */
-		return -EINVAL;
-	t->p = p;
-	t->n = best_n;
-	t->m = best_m;
-	*freq_out = (DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
-	f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
-		  t->m, t->n, t->p, *freq_out);
-	return 0;
-}
-
-/*
- * clear lfb screen
- */
-static void sstfb_clear_screen(struct fb_info *info)
-{
-	/* clear screen */
-	fb_memset(info->screen_base, 0, info->fix.smem_len);
-}
-
-
-/**
- *      sstfb_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- *
- *	Limit to the abilities of a single chip as SLI is not supported
- *	by this driver.
- */
-
-static int sstfb_check_var(struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-	struct sstfb_par *par = info->par;
-	int hSyncOff   = var->xres + var->right_margin + var->left_margin;
-	int vSyncOff   = var->yres + var->lower_margin + var->upper_margin;
-	int vBackPorch = var->left_margin, yDim = var->yres;
-	int vSyncOn    = var->vsync_len;
-	int tiles_in_X, real_length;
-	unsigned int freq;
-
-	if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) {
-		printk(KERN_ERR "sstfb: Pixclock at %ld KHZ out of range\n",
-				PICOS2KHZ(var->pixclock));
-		return -EINVAL;
-	}
-	var->pixclock = KHZ2PICOS(freq);
-	
-	if (var->vmode & FB_VMODE_INTERLACED)
-		vBackPorch += (vBackPorch % 2);
-	if (var->vmode & FB_VMODE_DOUBLE) {
-		vBackPorch <<= 1;
-		yDim <<=1;
-		vSyncOn <<=1;
-		vSyncOff <<=1;
-	}
-
-	switch (var->bits_per_pixel) {
-	case 0 ... 16 :
-		var->bits_per_pixel = 16;
-		break;
-	default :
-		printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel);
-		return -EINVAL;
-	}
-	
-	/* validity tests */
-	if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1  ||
-	    hSyncOff <= 1  || var->left_margin <= 2  || vSyncOn <= 0 ||
-	    vSyncOff <= 0 || vBackPorch <= 0) {
-		return -EINVAL;
-	}
-
-	if (IS_VOODOO2(par)) {
-		/* Voodoo 2 limits */
-		tiles_in_X = (var->xres + 63 ) / 64 * 2;		
-
-		if (var->xres  > POW2(11) || yDim >= POW2(11)) {
-			printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
-			         var->xres, var->yres);
-			return -EINVAL;
-		}
-
-		if (var->hsync_len > POW2(9) || hSyncOff > POW2(11) ||
-		    var->left_margin - 2 >= POW2(9) || vSyncOn >= POW2(13) ||
-		    vSyncOff >= POW2(13) || vBackPorch >= POW2(9) ||
-		    tiles_in_X >= POW2(6) || tiles_in_X <= 0) {
-			printk(KERN_ERR "sstfb: Unsupported timings\n");
-			return -EINVAL;
-		}
-	} else {
-		/* Voodoo limits */
-		tiles_in_X = (var->xres + 63 ) / 64;
-
-		if (var->vmode) {
-			printk(KERN_ERR "sstfb: Interlace/doublescan not supported %#x\n",
-				var->vmode);
-			return -EINVAL;
-		}
-		if (var->xres > POW2(10) || var->yres >= POW2(10)) {
-			printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
-			         var->xres, var->yres);
-			return -EINVAL;
-		}
-		if (var->hsync_len > POW2(8) || hSyncOff - 1 > POW2(10) ||
-		    var->left_margin - 2 >= POW2(8) || vSyncOn >= POW2(12) ||
-		    vSyncOff >= POW2(12) || vBackPorch >= POW2(8) ||
-		    tiles_in_X >= POW2(4) || tiles_in_X <= 0) {
-			printk(KERN_ERR "sstfb: Unsupported timings\n");
-			return -EINVAL;
-		}
-	}
-
-	/* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem */
-	/* FIXME: i don't like this... looks wrong */
-	real_length = tiles_in_X  * (IS_VOODOO2(par) ? 32 : 64 )
-	              * ((var->bits_per_pixel == 16) ? 2 : 4);
-
-	if (real_length * yDim > info->fix.smem_len) {
-		printk(KERN_ERR "sstfb: Not enough video memory\n");
-		return -ENOMEM;
-	}
-
-	var->sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
-	var->vmode &= (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->height  = -1;
-	var->width   = -1;
-
-	/*
-	 * correct the color bit fields
-	 */
-	/* var->{red|green|blue}.msb_right = 0; */
-
-	switch (var->bits_per_pixel) {
-	case 16:	/* RGB 565  LfbMode 0 */
-		var->red.length    = 5;
-		var->green.length  = 6;
-		var->blue.length   = 5;
-		var->transp.length = 0;
-
-		var->red.offset    = 11;
-		var->green.offset  = 5;
-		var->blue.offset   = 0;
-		var->transp.offset = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/**
- *      sstfb_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int sstfb_set_par(struct fb_info *info)
-{
-	struct sstfb_par *par = info->par;
-	u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
-	struct pci_dev *sst_dev = par->dev;
-	unsigned int freq;
-	int ntiles;
-
-	par->hSyncOff	= info->var.xres + info->var.right_margin + info->var.left_margin;
-
-	par->yDim 	= info->var.yres;
-	par->vSyncOn 	= info->var.vsync_len;
-	par->vSyncOff	= info->var.yres + info->var.lower_margin + info->var.upper_margin;
-	par->vBackPorch = info->var.upper_margin;
-
-	/* We need par->pll */
-	sst_calc_pll(PICOS2KHZ(info->var.pixclock), &freq, &par->pll);
-
-	if (info->var.vmode & FB_VMODE_INTERLACED)
-		par->vBackPorch += (par->vBackPorch % 2);
-	if (info->var.vmode & FB_VMODE_DOUBLE) {
-		par->vBackPorch <<= 1;
-		par->yDim <<=1;
-		par->vSyncOn <<=1;
-		par->vSyncOff <<=1;
-	}
-
-	if (IS_VOODOO2(par)) {
-		/* voodoo2 has 32 pixel wide tiles , BUT strange things
-		   happen with odd number of tiles */
-		par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2;
-	} else {
-		/* voodoo1 has 64 pixels wide tiles. */
-		par->tiles_in_X = (info->var.xres + 63 ) / 64;
-	}
-
-	f_ddprintk("hsync_len hSyncOff vsync_len vSyncOff\n");
-	f_ddprintk("%-7d %-8d %-7d %-8d\n",
-	           info->var.hsync_len, par->hSyncOff,
-	           par->vSyncOn, par->vSyncOff);
-	f_ddprintk("left_margin upper_margin xres yres Freq\n");
-	f_ddprintk("%-10d %-10d %-4d %-4d %-8ld\n",
-	           info->var.left_margin, info->var.upper_margin,
-	           info->var.xres, info->var.yres, PICOS2KHZ(info->var.pixclock));
-
-	sst_write(NOPCMD, 0);
-	sst_wait_idle();
-	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
-	sst_set_bits(FBIINIT1, VIDEO_RESET);
-	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
-	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
-	sst_wait_idle();
-
-	/*sst_unset_bits (FBIINIT0, FBI_RESET); / reenable FBI ? */
-
-	sst_write(BACKPORCH, par->vBackPorch << 16 | (info->var.left_margin - 2));
-	sst_write(VIDEODIMENSIONS, par->yDim << 16 | (info->var.xres - 1));
-	sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1));
-	sst_write(VSYNC,       par->vSyncOff << 16 | par->vSyncOn);
-
-	fbiinit2 = sst_read(FBIINIT2);
-	fbiinit3 = sst_read(FBIINIT3);
-
-	/* everything is reset. we enable fbiinit2/3 remap : dac access ok */
-	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
-	                       PCI_EN_INIT_WR | PCI_REMAP_DAC );
-
-	par->dac_sw.set_vidmod(info, info->var.bits_per_pixel);
-
-	/* set video clock */
-	par->dac_sw.set_pll(info, &par->pll, VID_CLOCK);
-
-	/* disable fbiinit2/3 remap */
-	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
-	                       PCI_EN_INIT_WR);
-
-	/* restore fbiinit2/3 */
-	sst_write(FBIINIT2,fbiinit2);
-	sst_write(FBIINIT3,fbiinit3);
-
-	fbiinit1 = (sst_read(FBIINIT1) & VIDEO_MASK)
-	            | EN_DATA_OE
-	            | EN_BLANK_OE
-	            | EN_HVSYNC_OE
-	            | EN_DCLK_OE
-		 /* | (15 << TILES_IN_X_SHIFT) */
-	            | SEL_INPUT_VCLK_2X
-		 /* | (2 << VCLK_2X_SEL_DEL_SHIFT)
-	            | (2 << VCLK_DEL_SHIFT) */;
-/* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28)
- in (near) future set them accordingly to revision + resolution (cf glide)
- first understand what it stands for :)
- FIXME: there are some artefacts... check for the vclk_in_delay
- lets try with 6ns delay in both vclk_out & in...
- doh... they're still there :\
-*/
-
-	ntiles = par->tiles_in_X;
-	if (IS_VOODOO2(par)) {
-		fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
-		            | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT;
-/* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
-   and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just
-   write our value. BTW due to the dac unable to read odd number of tiles, this
-   field is always null ... */
-		fbiinit6 = (ntiles & 0x1) << TILES_IN_X_LSB_SHIFT;
-	}
-	else
-		fbiinit1 |= ntiles << TILES_IN_X_SHIFT;
-
-	switch (info->var.bits_per_pixel) {
-	case 16:
-		fbiinit1 |=  SEL_SOURCE_VCLK_2X_SEL;
-		break;
-	default:
-		return -EINVAL;
-	}
-	sst_write(FBIINIT1, fbiinit1);
-	if (IS_VOODOO2(par)) {
-		sst_write(FBIINIT6, fbiinit6);
-		fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
-		if (info->var.vmode & FB_VMODE_INTERLACED)
-			fbiinit5 |= INTERLACE;
-		if (info->var.vmode & FB_VMODE_DOUBLE)
-			fbiinit5 |= VDOUBLESCAN;
-		if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-			fbiinit5 |= HSYNC_HIGH;
-		if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-			fbiinit5 |= VSYNC_HIGH;
-		sst_write(FBIINIT5, fbiinit5);
-	}
-	sst_wait_idle();
-	sst_unset_bits(FBIINIT1, VIDEO_RESET);
-	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
-	sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);
-	/* disables fbiinit writes */
-	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
-
-	/* set lfbmode : set mode + front buffer for reads/writes
-	   + disable pipeline */
-	switch (info->var.bits_per_pixel) {
-	case 16:
-		lfbmode = LFB_565;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-#if defined(__BIG_ENDIAN)
-	/* Enable byte-swizzle functionality in hardware.
-	 * With this enabled, all our read- and write-accesses to
-	 * the voodoo framebuffer can be done in native format, and
-	 * the hardware will automatically convert it to little-endian.
-	 * - tested on HP-PARISC, Helge Deller <deller@gmx.de> */
-	lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
-		     LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
-#endif
-	
-	if (clipping) {
-		sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
-	/*
-	 * Set "clipping" dimensions. If clipping is disabled and
-	 * writes to offscreen areas of the framebuffer are performed,
-	 * the "behaviour is undefined" (_very_ undefined) - Urs
-	 */
-	/* btw, it requires enabling pixel pipeline in LFBMODE .
-	   off screen read/writes will just wrap and read/print pixels
-	   on screen. Ugly but not that dangerous */
-		f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
-		            info->var.xres - 1, par->yDim - 1);
-
-		sst_write(CLIP_LEFT_RIGHT, info->var.xres);
-		sst_write(CLIP_LOWY_HIGHY, par->yDim);
-		sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
-	} else {
-		/* no clipping : direct access, no pipeline */
-		sst_write(LFBMODE, lfbmode);
-	}
-	return 0;
-}
-
-/**
- *      sstfb_setcolreg - Optional function. Sets a color register.
- *      @regno: hardware colormap register
- *      @red: frame buffer colormap structure
- *      @green: The green value which can be up to 16 bits wide
- *      @blue:  The blue value which can be up to 16 bits wide.
- *      @transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- */
-static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                           u_int transp, struct fb_info *info)
-{
-	struct sstfb_par *par = info->par;
-	u32 col;
-
-	f_dddprintk("sstfb_setcolreg\n");
-	f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
-	            regno, red, green, blue, transp);
-	if (regno > 15)
-		return 0;
-
-	red    >>= (16 - info->var.red.length);
-	green  >>= (16 - info->var.green.length);
-	blue   >>= (16 - info->var.blue.length);
-	transp >>= (16 - info->var.transp.length);
-	col = (red << info->var.red.offset)
-	    | (green << info->var.green.offset)
-	    | (blue  << info->var.blue.offset)
-	    | (transp << info->var.transp.offset);
-	
-	par->palette[regno] = col;
-
-	return 0;
-}
-
-static void sstfb_setvgapass( struct fb_info *info, int enable )
-{
-	struct sstfb_par *par = info->par;
-	struct pci_dev *sst_dev = par->dev;
-	u32 fbiinit0, tmp;
-
-	enable = enable ? 1:0;
-	if (par->vgapass == enable)
-		return;
-	par->vgapass = enable;
-
-	pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
-	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
-			       tmp | PCI_EN_INIT_WR );
-	fbiinit0 = sst_read (FBIINIT0);
-	if (par->vgapass) {
-		sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);
-		fb_info(info, "Enabling VGA pass-through\n");
-	} else {
-		sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);
-		fb_info(info, "Disabling VGA pass-through\n");
-	}
-	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
-}
-
-static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,
-			const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(device);
-	char ** last = NULL;
-	int val;
-
-	val = simple_strtoul(buf, last, 0);
-	sstfb_setvgapass(info, val);
-
-	return count;
-}
-
-static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,
-			char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(device);
-	struct sstfb_par *par = info->par;
-	return snprintf(buf, PAGE_SIZE, "%d\n", par->vgapass);
-}
-
-static struct device_attribute device_attrs[] = {
-	__ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)
-	};
-
-static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,
-			unsigned long arg)
-{
-	struct sstfb_par *par;
-	u32 val;
-
-	switch (cmd) {
-	/* set/get VGA pass_through mode */
-	case SSTFB_SET_VGAPASS:
-		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
-			return -EFAULT;
-		sstfb_setvgapass(info, val);
-		return 0;
-	case SSTFB_GET_VGAPASS:
-		par = info->par;
-		val = par->vgapass;
-		if (copy_to_user((void __user *)arg, &val, sizeof(val)))
-			return -EFAULT;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-
-/*
- * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) - Voodoo2 only
- */
-#if 0
-static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct sstfb_par *par = info->par;
-	u32 stride = info->fix.line_length;
-   
-	if (!IS_VOODOO2(par))
-		return;
-
-	sst_write(BLTSRCBASEADDR, 0);
-	sst_write(BLTDSTBASEADDR, 0);
-	sst_write(BLTROP, BLTROP_COPY);
-	sst_write(BLTXYSTRIDES, stride | (stride << 16));
-	sst_write(BLTSRCXY, area->sx | (area->sy << 16));
-	sst_write(BLTDSTXY, area->dx | (area->dy << 16));
-	sst_write(BLTSIZE, area->width | (area->height << 16));
-	sst_write(BLTCOMMAND, BLT_SCR2SCR_BITBLT | LAUNCH_BITBLT |
-		(BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) );
-	sst_wait_idle();
-}
-#endif
-
-
-/*
- * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
- */
-#if 0
-static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
-{
-	struct sstfb_par *par = info->par;
-	u32 stride = info->fix.line_length;
-
-	if (!IS_VOODOO2(par))
-		return;
-   	
-	sst_write(BLTCLIPX, info->var.xres);
-	sst_write(BLTCLIPY, info->var.yres);
-	
-	sst_write(BLTDSTBASEADDR, 0);
-	sst_write(BLTCOLOR, rect->color);
-	sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);
-	sst_write(BLTXYSTRIDES, stride | (stride << 16));
-	sst_write(BLTDSTXY, rect->dx | (rect->dy << 16));
-	sst_write(BLTSIZE, rect->width | (rect->height << 16));
-	sst_write(BLTCOMMAND, BLT_RECFILL_BITBLT | LAUNCH_BITBLT
-		 | (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );
-	sst_wait_idle();
-}
-#endif
-
-
-
-/* 
- * get lfb size 
- */
-static int sst_get_memsize(struct fb_info *info, __u32 *memsize)
-{
-	u8 __iomem *fbbase_virt = info->screen_base;
-
-	/* force memsize */
-	if (mem >= 1  && mem <= 4) {
-		*memsize = (mem * 0x100000);
-		printk(KERN_INFO "supplied memsize: %#x\n", *memsize);
-		return 1;
-	}
-
-	writel(0xdeadbeef, fbbase_virt);
-	writel(0xdeadbeef, fbbase_virt+0x100000);
-	writel(0xdeadbeef, fbbase_virt+0x200000);
-	f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
-	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),
-	           readl(fbbase_virt + 0x200000));
-
-	writel(0xabcdef01, fbbase_virt);
-
-	f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
-	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),
-	           readl(fbbase_virt + 0x200000));
-
-	/* checks for 4mb lfb, then 2, then defaults to 1 */
-	if (readl(fbbase_virt + 0x200000) == 0xdeadbeef)
-		*memsize = 0x400000;
-	else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef)
-		*memsize = 0x200000;
-	else
-		*memsize = 0x100000;
-	f_ddprintk("detected memsize: %dMB\n", *memsize >> 20);
-	return 1;
-}
-
-
-/* 
- * DAC detection routines 
- */
-
-/* fbi should be idle, and fifo emty and mem disabled */
-/* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */
-
-static int sst_detect_att(struct fb_info *info)
-{
-	struct sstfb_par *par = info->par;
-	int i, mir, dir;
-
-	for (i = 0; i < 3; i++) {
-		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
-		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
-		sst_dac_read(DACREG_RMR);
-		sst_dac_read(DACREG_RMR);
-		sst_dac_read(DACREG_RMR);
-		/* the fifth time,  CR0 is read */
-		sst_dac_read(DACREG_RMR);
-		/* the 6th, manufacturer id register */
-		mir = sst_dac_read(DACREG_RMR);
-		/*the 7th, device ID register */
-		dir = sst_dac_read(DACREG_RMR);
-		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
-		if (mir == DACREG_MIR_ATT && dir == DACREG_DIR_ATT) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int sst_detect_ti(struct fb_info *info)
-{
-	struct sstfb_par *par = info->par;
-	int i, mir, dir;
-
-	for (i = 0; i<3; i++) {
-		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
-		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
-		sst_dac_read(DACREG_RMR);
-		sst_dac_read(DACREG_RMR);
-		sst_dac_read(DACREG_RMR);
-		/* the fifth time,  CR0 is read */
-		sst_dac_read(DACREG_RMR);
-		/* the 6th, manufacturer id register */
-		mir = sst_dac_read(DACREG_RMR);
-		/*the 7th, device ID register */
-		dir = sst_dac_read(DACREG_RMR);
-		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
-		if ((mir == DACREG_MIR_TI ) && (dir == DACREG_DIR_TI)) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * try to detect ICS5342  ramdac
- * we get the 1st byte (M value) of preset f1,f7 and fB
- * why those 3 ? mmmh... for now, i'll do it the glide way...
- * and ask questions later. anyway, it seems that all the freq registers are
- * really at their default state (cf specs) so i ask again, why those 3 regs ?
- * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for
- * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be
- * touched...
- * is it really safe ? how can i reset this ramdac ? geee...
- */
-static int sst_detect_ics(struct fb_info *info)
-{
-	struct sstfb_par *par = info->par;
-	int m_clk0_1, m_clk0_7, m_clk1_b;
-	int n_clk0_1, n_clk0_7, n_clk1_b;
-	int i;
-
-	for (i = 0; i<5; i++ ) {
-		sst_dac_write(DACREG_ICS_PLLRMA, 0x1);	/* f1 */
-		m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
-		n_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
-		sst_dac_write(DACREG_ICS_PLLRMA, 0x7);	/* f7 */
-		m_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
-		n_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
-		sst_dac_write(DACREG_ICS_PLLRMA, 0xb);	/* fB */
-		m_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
-		n_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
-		f_ddprintk("m_clk0_1: %#x, m_clk0_7: %#x, m_clk1_b: %#x\n",
-			m_clk0_1, m_clk0_7, m_clk1_b);
-		f_ddprintk("n_clk0_1: %#x, n_clk0_7: %#x, n_clk1_b: %#x\n",
-			n_clk0_1, n_clk0_7, n_clk1_b);
-		if ((   m_clk0_1 == DACREG_ICS_PLL_CLK0_1_INI)
-		    && (m_clk0_7 == DACREG_ICS_PLL_CLK0_7_INI)
-		    && (m_clk1_b == DACREG_ICS_PLL_CLK1_B_INI)) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-
-/*
- * gfx, video, pci fifo should be reset, dram refresh disabled
- * see detect_dac
- */
-
-static int sst_set_pll_att_ti(struct fb_info *info, 
-		const struct pll_timing *t, const int clock)
-{
-	struct sstfb_par *par = info->par;
-	u8 cr0, cc;
-
-	/* enable indexed mode */
-	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
-	sst_dac_read(DACREG_RMR);	/* 1 time:  RMR */
-	sst_dac_read(DACREG_RMR);	/* 2 RMR */
-	sst_dac_read(DACREG_RMR);	/* 3 //  */
-	sst_dac_read(DACREG_RMR);	/* 4 //  */
-	cr0 = sst_dac_read(DACREG_RMR);	/* 5 CR0 */
-
-	sst_dac_write(DACREG_WMA, 0);
-	sst_dac_read(DACREG_RMR);
-	sst_dac_read(DACREG_RMR);
-	sst_dac_read(DACREG_RMR);
-	sst_dac_read(DACREG_RMR);
-	sst_dac_write(DACREG_RMR, (cr0 & 0xf0)
-	              | DACREG_CR0_EN_INDEXED
-	              | DACREG_CR0_8BIT
-	              | DACREG_CR0_PWDOWN );
-	/* so, now we are in indexed mode . dunno if its common, but
-	   i find this way of doing things a little bit weird :p */
-
-	udelay(300);
-	cc = dac_i_read(DACREG_CC_I);
-	switch (clock) {
-	case VID_CLOCK:
-		dac_i_write(DACREG_AC0_I, t->m);
-		dac_i_write(DACREG_AC1_I, t->p << 6 | t->n);
-		dac_i_write(DACREG_CC_I,
-		            (cc & 0x0f) | DACREG_CC_CLKA | DACREG_CC_CLKA_C);
-		break;
-	case GFX_CLOCK:
-		dac_i_write(DACREG_BD0_I, t->m);
-		dac_i_write(DACREG_BD1_I, t->p << 6 | t->n);
-		dac_i_write(DACREG_CC_I,
-		            (cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D);
-		break;
-	default:
-		dprintk("%s: wrong clock code '%d'\n",
-		        __func__, clock);
-		return 0;
-		}
-	udelay(300);
-
-	/* power up the dac & return to "normal" non-indexed mode */
-	dac_i_write(DACREG_CR0_I,
-	            cr0 & ~DACREG_CR0_PWDOWN & ~DACREG_CR0_EN_INDEXED);
-	return 1;
-}
-
-static int sst_set_pll_ics(struct fb_info *info,
-		const struct pll_timing *t, const int clock)
-{
-	struct sstfb_par *par = info->par;
-	u8 pll_ctrl;
-
-	sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
-	pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);
-	switch(clock) {
-	case VID_CLOCK:
-		sst_dac_write(DACREG_ICS_PLLWMA, 0x0);	/* CLK0, f0 */
-		sst_dac_write(DACREG_ICS_PLLDATA, t->m);
-		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
-		/* selects freq f0 for clock 0 */
-		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
-		sst_dac_write(DACREG_ICS_PLLDATA,
-		              (pll_ctrl & 0xd8)
-		              | DACREG_ICS_CLK0
-		              | DACREG_ICS_CLK0_0);
-		break;
-	case GFX_CLOCK :
-		sst_dac_write(DACREG_ICS_PLLWMA, 0xa);	/* CLK1, fA */
-		sst_dac_write(DACREG_ICS_PLLDATA, t->m);
-		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
-		/* selects freq fA for clock 1 */
-		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
-		sst_dac_write(DACREG_ICS_PLLDATA,
-		              (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);
-		break;
-	default:
-		dprintk("%s: wrong clock code '%d'\n",
-		        __func__, clock);
-		return 0;
-		}
-	udelay(300);
-	return 1;
-}
-
-static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
-{
-	struct sstfb_par *par = info->par;
-	u8 cr0;
-
-	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
-	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
-	sst_dac_read(DACREG_RMR);
-	sst_dac_read(DACREG_RMR);
-	sst_dac_read(DACREG_RMR);
-	/* the fifth time,  CR0 is read */
-	cr0 = sst_dac_read(DACREG_RMR);
-
-	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
-	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
-	sst_dac_read(DACREG_RMR);
-	sst_dac_read(DACREG_RMR);
-	sst_dac_read(DACREG_RMR);
-	/* cr0 */
-	switch(bpp) {
-	case 16:
-		sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);
-		break;
-	default:
-		dprintk("%s: bad depth '%u'\n", __func__, bpp);
-		break;
-	}
-}
-
-static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
-{
-	struct sstfb_par *par = info->par;
-
-	switch(bpp) {
-	case 16:
-		sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
-		break;
-	default:
-		dprintk("%s: bad depth '%u'\n", __func__, bpp);
-		break;
-	}
-}
-
-/*
- * detect dac type
- * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
- * dram refresh disabled, FbiInit remaped.
- * TODO: mmh.. maybe i should put the "prerequisite" in the func ...
- */
-
-
-static struct dac_switch dacs[] = {
-	{	.name		= "TI TVP3409",
-		.detect		= sst_detect_ti,
-		.set_pll	= sst_set_pll_att_ti,
-		.set_vidmod	= sst_set_vidmod_att_ti },
-
-	{	.name		= "AT&T ATT20C409",
-		.detect		= sst_detect_att,
-		.set_pll	= sst_set_pll_att_ti,
-		.set_vidmod	= sst_set_vidmod_att_ti },
-	{	.name		= "ICS ICS5342",
-		.detect		= sst_detect_ics,
-		.set_pll	= sst_set_pll_ics,
-		.set_vidmod	= sst_set_vidmod_ics },
-};
-
-static int sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
-{
-	int i, ret = 0;
-
-	for (i = 0; i < ARRAY_SIZE(dacs); i++) {
-		ret = dacs[i].detect(info);
-		if (ret)
-			break;
-	}
-	if (!ret)
-		return 0;
-	f_dprintk("%s found %s\n", __func__, dacs[i].name);
-	par->dac_sw = dacs[i];
-	return 1;
-}
-
-/*
- * Internal Routines
- */
-static int sst_init(struct fb_info *info, struct sstfb_par *par)
-{
-	u32 fbiinit0, fbiinit1, fbiinit4;
-	struct pci_dev *dev = par->dev;
-	struct pll_timing gfx_timings;
-	struct sst_spec *spec;
-	int Fout;
-	int gfx_clock;
-
-	spec = &voodoo_spec[par->type];
-	f_ddprintk(" fbiinit0   fbiinit1   fbiinit2   fbiinit3   fbiinit4  "
-	           " fbiinit6\n");
-	f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n",
-	            sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),
-	            sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));
-	/* disable video clock */
-	pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0);
-
-	/* enable writing to init registers, disable pci fifo */
-	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
-	/* reset video */
-	sst_set_bits(FBIINIT1, VIDEO_RESET);
-	sst_wait_idle();
-	/* reset gfx + pci fifo */
-	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
-	sst_wait_idle();
-
-	/* unreset fifo */
-	/*sst_unset_bits(FBIINIT0, FIFO_RESET);
-	sst_wait_idle();*/
-	/* unreset FBI */
-	/*sst_unset_bits(FBIINIT0, FBI_RESET);
-	sst_wait_idle();*/
-
-	/* disable dram refresh */
-	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
-	sst_wait_idle();
-	/* remap fbinit2/3 to dac */
-	pci_write_config_dword(dev, PCI_INIT_ENABLE,
-				PCI_EN_INIT_WR | PCI_REMAP_DAC );
-	/* detect dac type */
-	if (!sst_detect_dactype(info, par)) {
-		printk(KERN_ERR "sstfb: unknown dac type.\n");
-		//FIXME watch it: we are not in a safe state, bad bad bad.
-		return 0;
-	}
-
-	/* set graphic clock */
-	gfx_clock = spec->default_gfx_clock;
-	if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
-		printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);
-		 gfx_clock = gfxclk *1000;
-	} else if (gfxclk) {
-		printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);
-	}
-
-	sst_calc_pll(gfx_clock, &Fout, &gfx_timings);
-	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
-
-	/* disable fbiinit remap */
-	pci_write_config_dword(dev, PCI_INIT_ENABLE,
-	                       PCI_EN_INIT_WR| PCI_EN_FIFO_WR );
-	/* defaults init registers */
-	/* FbiInit0: unreset gfx, unreset fifo */
-	fbiinit0 = FBIINIT0_DEFAULT;
-	fbiinit1 = FBIINIT1_DEFAULT;
-	fbiinit4 = FBIINIT4_DEFAULT;
-	par->vgapass = vgapass;
-	if (par->vgapass)
-		fbiinit0 &= ~DIS_VGA_PASSTHROUGH;
-	else
-		fbiinit0 |= DIS_VGA_PASSTHROUGH;
-	if (slowpci) {
-		fbiinit1 |= SLOW_PCI_WRITES;
-		fbiinit4 |= SLOW_PCI_READS;
-	} else {
-		fbiinit1 &= ~SLOW_PCI_WRITES;
-		fbiinit4 &= ~SLOW_PCI_READS;
-	}
-	sst_write(FBIINIT0, fbiinit0);
-	sst_wait_idle();
-	sst_write(FBIINIT1, fbiinit1);
-	sst_wait_idle();
-	sst_write(FBIINIT2, FBIINIT2_DEFAULT);
-	sst_wait_idle();
-	sst_write(FBIINIT3, FBIINIT3_DEFAULT);
-	sst_wait_idle();
-	sst_write(FBIINIT4, fbiinit4);
-	sst_wait_idle();
-	if (IS_VOODOO2(par)) {
-		sst_write(FBIINIT6, FBIINIT6_DEFAULT);
-		sst_wait_idle();
-	}
-
-	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
-	pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);
-	return 1;
-}
-
-static void sst_shutdown(struct fb_info *info)
-{
-	struct sstfb_par *par = info->par;
-	struct pci_dev *dev = par->dev;
-	struct pll_timing gfx_timings;
-	int Fout;
-
-	/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */
-	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
-	sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);
-	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
-	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
-	sst_wait_idle();
-	pci_write_config_dword(dev, PCI_INIT_ENABLE,
-	                       PCI_EN_INIT_WR | PCI_REMAP_DAC);
-	/* set 20Mhz gfx clock */
-	sst_calc_pll(20000, &Fout, &gfx_timings);
-	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
-	/* TODO maybe shutdown the dac, vrefresh and so on... */
-	pci_write_config_dword(dev, PCI_INIT_ENABLE,
-	                       PCI_EN_INIT_WR);
-	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);
-	pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
-	/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct
-	 * from start ? */
-	pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);
-
-}
-
-/*
- * Interface to the world
- */
-static int sstfb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt) continue;
-
-		f_ddprintk("option %s\n", this_opt);
-
-		if (!strcmp(this_opt, "vganopass"))
-			vgapass = 0;
-		else if (!strcmp(this_opt, "vgapass"))
-			vgapass = 1;
-		else if (!strcmp(this_opt, "clipping"))
-		        clipping = 1;
-		else if (!strcmp(this_opt, "noclipping"))
-		        clipping = 0;
-		else if (!strcmp(this_opt, "fastpci"))
-		        slowpci = 0;
-		else if (!strcmp(this_opt, "slowpci"))
-		        slowpci = 1;
-		else if (!strncmp(this_opt, "mem:",4))
-			mem = simple_strtoul (this_opt+4, NULL, 0);
-		else if (!strncmp(this_opt, "gfxclk:",7))
-			gfxclk = simple_strtoul (this_opt+7, NULL, 0);
-		else
-			mode_option = this_opt;
-	}
-	return 0;
-}
-
-
-static struct fb_ops sstfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= sstfb_check_var,
-	.fb_set_par	= sstfb_set_par,
-	.fb_setcolreg	= sstfb_setcolreg,
-	.fb_fillrect	= cfb_fillrect, /* sstfb_fillrect */
-	.fb_copyarea	= cfb_copyarea, /* sstfb_copyarea */
-	.fb_imageblit	= cfb_imageblit,
-	.fb_ioctl	= sstfb_ioctl,
-};
-
-static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct fb_info *info;
-	struct fb_fix_screeninfo *fix;
-	struct sstfb_par *par;
-	struct sst_spec *spec;
-	int err;
-
-	/* Enable device in PCI config. */
-	if ((err=pci_enable_device(pdev))) {
-		printk(KERN_ERR "cannot enable device\n");
-		return err;
-	}
-
-	/* Allocate the fb and par structures.  */
-	info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	pci_set_drvdata(pdev, info);
-	
-	par  = info->par;
-	fix  = &info->fix;
-	
-	par->type = id->driver_data;
-	spec = &voodoo_spec[par->type];
-	f_ddprintk("found device : %s\n", spec->name);
-
-	par->dev = pdev;
-	par->revision = pdev->revision;
-
-	fix->mmio_start = pci_resource_start(pdev,0);
-	fix->mmio_len	= 0x400000;
-	fix->smem_start = fix->mmio_start + 0x400000;
-
-	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) {
-		printk(KERN_ERR "sstfb: cannot reserve mmio memory\n");
-		goto fail_mmio_mem;
-	}
-
-	if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {
-		printk(KERN_ERR "sstfb: cannot reserve fb memory\n");
-		goto fail_fb_mem;
-	}
-
-	par->mmio_vbase = ioremap_nocache(fix->mmio_start,
-					fix->mmio_len);
-	if (!par->mmio_vbase) {
-		printk(KERN_ERR "sstfb: cannot remap register area %#lx\n",
-		        fix->mmio_start);
-		goto fail_mmio_remap;
-	}
-	info->screen_base = ioremap_nocache(fix->smem_start, 0x400000);
-	if (!info->screen_base) {
-		printk(KERN_ERR "sstfb: cannot remap framebuffer %#lx\n",
-		        fix->smem_start);
-		goto fail_fb_remap;
-	}
-
-	if (!sst_init(info, par)) {
-		printk(KERN_ERR "sstfb: Init failed\n");
-		goto fail;
-	}
-	sst_get_memsize(info, &fix->smem_len);
-	strlcpy(fix->id, spec->name, sizeof(fix->id));
-
-	printk(KERN_INFO "%s (revision %d) with %s dac\n",
-		fix->id, par->revision, par->dac_sw.name);
-	printk(KERN_INFO "framebuffer at %#lx, mapped to 0x%p, size %dMB\n",
-	        fix->smem_start, info->screen_base,
-	        fix->smem_len >> 20);
-
-	f_ddprintk("regbase_virt: %#lx\n", par->mmio_vbase);
-	f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
-	f_ddprintk("fbbase_virt: %p\n", info->screen_base);
-
-	info->flags	= FBINFO_DEFAULT;
-	info->fbops	= &sstfb_ops;
-	info->pseudo_palette = par->palette;
-
-	fix->type	= FB_TYPE_PACKED_PIXELS;
-	fix->visual	= FB_VISUAL_TRUECOLOR;
-	fix->accel	= FB_ACCEL_NONE;  /* FIXME */
-	/*
-	 * According to the specs, the linelength must be of 1024 *pixels*
-	 * and the 24bpp mode is in fact a 32 bpp mode (and both are in
-	 * fact dithered to 16bit).
-	 */
-	fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
-	
-	fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
-
-	if (sstfb_check_var(&info->var, info)) {
-		printk(KERN_ERR "sstfb: invalid video mode.\n");
-		goto fail;
-	}
-
-	if (sstfb_set_par(info)) {
-		printk(KERN_ERR "sstfb: can't set default video mode.\n");
-		goto fail;
-	}
-	
-	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
-		printk(KERN_ERR "sstfb: can't alloc cmap memory.\n");
-		goto fail;
-	}
-
-	/* register fb */
-	info->device = &pdev->dev;
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "sstfb: can't register framebuffer.\n");
-		goto fail_register;
-	}
-
-	sstfb_clear_screen(info);
-
-	if (device_create_file(info->dev, &device_attrs[0]))
-		printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");
-
-
-	fb_info(info, "%s frame buffer device at 0x%p\n",
-		fix->id, info->screen_base);
-
-	return 0;
-
-fail_register:
-	fb_dealloc_cmap(&info->cmap);
-fail:
-	iounmap(info->screen_base);
-fail_fb_remap:
-	iounmap(par->mmio_vbase);
-fail_mmio_remap:
-	release_mem_region(fix->smem_start, 0x400000);
-fail_fb_mem:
-	release_mem_region(fix->mmio_start, info->fix.mmio_len);
-fail_mmio_mem:
-	framebuffer_release(info);
-	return -ENXIO; 	/* no voodoo detected */
-}
-
-static void sstfb_remove(struct pci_dev *pdev)
-{
-	struct sstfb_par *par;
-	struct fb_info *info;
-
-	info = pci_get_drvdata(pdev);
-	par = info->par;
-	
-	device_remove_file(info->dev, &device_attrs[0]);
-	sst_shutdown(info);
-	iounmap(info->screen_base);
-	iounmap(par->mmio_vbase);
-	release_mem_region(info->fix.smem_start, 0x400000);
-	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-	fb_dealloc_cmap(&info->cmap);
-	unregister_framebuffer(info);
-	framebuffer_release(info);
-}
-
-
-static const struct pci_device_id sstfb_id_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),
-		.driver_data = ID_VOODOO1, },
-	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),
-		.driver_data = ID_VOODOO2, },
-	{ 0 },
-};
-
-static struct pci_driver sstfb_driver = {
-	.name		= "sstfb",
-	.id_table	= sstfb_id_tbl,
-	.probe		= sstfb_probe,
-	.remove		= sstfb_remove,
-};
-
-
-static int sstfb_init(void)
-{
-	char *option = NULL;
-
-	if (fb_get_options("sstfb", &option))
-		return -ENODEV;
-	sstfb_setup(option);
-
-	return pci_register_driver(&sstfb_driver);
-}
-
-static void sstfb_exit(void)
-{
-	pci_unregister_driver(&sstfb_driver);
-}
-
-
-module_init(sstfb_init);
-module_exit(sstfb_exit);
-
-MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
-MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
-MODULE_LICENSE("GPL");
-
-module_param(mem, int, 0);
-MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");
-module_param(vgapass, bool, 0);
-MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");
-module_param(clipping, bool, 0);
-MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");
-module_param(gfxclk, int, 0);
-MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
-module_param(slowpci, bool, 0);
-MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");
-
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h
deleted file mode 100644
index af1619536ac8..000000000000
--- a/drivers/video/sticore.h
+++ /dev/null
@@ -1,401 +0,0 @@
-#ifndef STICORE_H
-#define STICORE_H
-
-/* generic STI structures & functions */
-
-#if 0
-#define DPRINTK(x)	printk x
-#else
-#define DPRINTK(x) 
-#endif
-
-#define MAX_STI_ROMS 4		/* max no. of ROMs which this driver handles */
-
-#define STI_REGION_MAX 8	/* hardcoded STI constants */
-#define STI_DEV_NAME_LENGTH 32
-#define STI_MONITOR_MAX 256
-
-#define STI_FONT_HPROMAN8 1
-#define STI_FONT_KANA8 2
-
-#define ALT_CODE_TYPE_UNKNOWN 0x00	/* alt code type values */
-#define ALT_CODE_TYPE_PA_RISC_64 0x01
-
-/* The latency of the STI functions cannot really be reduced by setting
- * this to 0;  STI doesn't seem to be designed to allow calling a different
- * function (or the same function with different arguments) after a
- * function exited with 1 as return value.
- *
- * As all of the functions below could be called from interrupt context,
- * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
- * block.  Really bad latency there.
- *
- * Probably the best solution to all this is have the generic code manage
- * the screen buffer and a kernel thread to call STI occasionally.
- * 
- * Luckily, the frame buffer guys have the same problem so we can just wait
- * for them to fix it and steal their solution.   prumpf
- */
- 
-#include <asm/io.h>
-
-#define STI_WAIT 1
-
-#define STI_PTR(p)	( virt_to_phys(p) )
-#define PTR_STI(p)	( phys_to_virt((unsigned long)p) )
-
-#define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x)
-#define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y)
-
-/* sti_font_xy() use the native font ROM ! */
-#define sti_font_x(sti) (PTR_STI(sti->font)->width)
-#define sti_font_y(sti) (PTR_STI(sti->font)->height)
-
-#ifdef CONFIG_64BIT
-#define STI_LOWMEM	(GFP_KERNEL | GFP_DMA)
-#else
-#define STI_LOWMEM	(GFP_KERNEL)
-#endif
-
-
-/* STI function configuration structs */
-
-typedef union region {
-	struct { 
-		u32 offset	: 14;	/* offset in 4kbyte page */
-		u32 sys_only	: 1;	/* don't map to user space */
-		u32 cache	: 1;	/* map to data cache */
-		u32 btlb	: 1;	/* map to block tlb */
-		u32 last	: 1;	/* last region in list */
-		u32 length	: 14;	/* length in 4kbyte page */
-	} region_desc;
-
-	u32 region;			/* complete region value */
-} region_t;
-
-#define REGION_OFFSET_TO_PHYS( rt, hpa ) \
-	(((rt).region_desc.offset << 12) + (hpa))
-
-struct sti_glob_cfg_ext {
-	 u8 curr_mon;			/* current monitor configured */
-	 u8 friendly_boot;		/* in friendly boot mode */
-	s16 power;			/* power calculation (in Watts) */
-	s32 freq_ref;			/* frequency reference */
-	u32 sti_mem_addr;		/* pointer to global sti memory (size=sti_mem_request) */
-	u32 future_ptr; 		/* pointer to future data */
-};
-
-struct sti_glob_cfg {
-	s32 text_planes;		/* number of planes used for text */
-	s16 onscreen_x;			/* screen width in pixels */
-	s16 onscreen_y;			/* screen height in pixels */
-	s16 offscreen_x;		/* offset width in pixels */
-	s16 offscreen_y;		/* offset height in pixels */
-	s16 total_x;			/* frame buffer width in pixels */
-	s16 total_y;			/* frame buffer height in pixels */
-	u32 region_ptrs[STI_REGION_MAX]; /* region pointers */
-	s32 reent_lvl;			/* storage for reentry level value */
-	u32 save_addr;			/* where to save or restore reentrant state */
-	u32 ext_ptr;			/* pointer to extended glob_cfg data structure */
-};
-
-
-/* STI init function structs */
-
-struct sti_init_flags {
-	u32 wait : 1;		/* should routine idle wait or not */
-	u32 reset : 1;		/* hard reset the device? */
-	u32 text : 1;		/* turn on text display planes? */
-	u32 nontext : 1;	/* turn on non-text display planes? */
-	u32 clear : 1;		/* clear text display planes? */
-	u32 cmap_blk : 1;	/* non-text planes cmap black? */
-	u32 enable_be_timer : 1; /* enable bus error timer */
-	u32 enable_be_int : 1;	/* enable bus error timer interrupt */
-	u32 no_chg_tx : 1;	/* don't change text settings */
-	u32 no_chg_ntx : 1;	/* don't change non-text settings */
-	u32 no_chg_bet : 1;	/* don't change berr timer settings */
-	u32 no_chg_bei : 1;	/* don't change berr int settings */
-	u32 init_cmap_tx : 1;	/* initialize cmap for text planes */
-	u32 cmt_chg : 1;	/* change current monitor type */
-	u32 retain_ie : 1;	/* don't allow reset to clear int enables */
-	u32 caller_bootrom : 1;	/* set only by bootrom for each call */
-	u32 caller_kernel : 1;	/* set only by kernel for each call */
-	u32 caller_other : 1;	/* set only by non-[BR/K] caller */
-	u32 pad	: 14;		/* pad to word boundary */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-struct sti_init_inptr_ext {
-	u8  config_mon_type;	/* configure to monitor type */
-	u8  pad[1];		/* pad to word boundary */
-	u16 inflight_data;	/* inflight data possible on PCI */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-struct sti_init_inptr {
-	s32 text_planes;	/* number of planes to use for text */
-	u32 ext_ptr;		/* pointer to extended init_graph inptr data structure*/
-};
-
-
-struct sti_init_outptr {
-	s32 errno;		/* error number on failure */
-	s32 text_planes;	/* number of planes used for text */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-
-
-/* STI configuration function structs */
-
-struct sti_conf_flags {
-	u32 wait : 1;		/* should routine idle wait or not */
-	u32 pad : 31;		/* pad to word boundary */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-struct sti_conf_inptr {
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-struct sti_conf_outptr_ext {
-	u32 crt_config[3];	/* hardware specific X11/OGL information */	
-	u32 crt_hdw[3];
-	u32 future_ptr;
-};
-
-struct sti_conf_outptr {
-	s32 errno;		/* error number on failure */
-	s16 onscreen_x;		/* screen width in pixels */
-	s16 onscreen_y;		/* screen height in pixels */
-	s16 offscreen_x;	/* offscreen width in pixels */
-	s16 offscreen_y;	/* offscreen height in pixels */
-	s16 total_x;		/* frame buffer width in pixels */
-	s16 total_y;		/* frame buffer height in pixels */
-	s32 bits_per_pixel;	/* bits/pixel device has configured */
-	s32 bits_used;		/* bits which can be accessed */
-	s32 planes;		/* number of fb planes in system */
-	 u8 dev_name[STI_DEV_NAME_LENGTH]; /* null terminated product name */
-	u32 attributes;		/* flags denoting attributes */
-	u32 ext_ptr;		/* pointer to future data */
-};
-
-struct sti_rom {
-	 u8 type[4];
-	 u8 res004;
-	 u8 num_mons;
-	 u8 revno[2];
-	u32 graphics_id[2];
-
-	u32 font_start;
-	u32 statesize;
-	u32 last_addr;
-	u32 region_list;
-
-	u16 reentsize;
-	u16 maxtime;
-	u32 mon_tbl_addr;
-	u32 user_data_addr;
-	u32 sti_mem_req;
-
-	u32 user_data_size;
-	u16 power;
-	 u8 bus_support;
-	 u8 ext_bus_support;
-	 u8 alt_code_type;
-	 u8 ext_dd_struct[3];
-	u32 cfb_addr;
-
-	u32 init_graph;
-	u32 state_mgmt;
-	u32 font_unpmv;
-	u32 block_move;
-	u32 self_test;
-	u32 excep_hdlr;
-	u32 inq_conf;
-	u32 set_cm_entry;
-	u32 dma_ctrl;
-	 u8 res040[7 * 4];
-	
-	u32 init_graph_addr;
-	u32 state_mgmt_addr;
-	u32 font_unp_addr;
-	u32 block_move_addr;
-	u32 self_test_addr;
-	u32 excep_hdlr_addr;
-	u32 inq_conf_addr;
-	u32 set_cm_entry_addr;
-	u32 image_unpack_addr;
-	u32 pa_risx_addrs[7];
-};
-
-struct sti_rom_font {
-	u16 first_char;
-	u16 last_char;
-	 u8 width;
-	 u8 height;
-	 u8 font_type;		/* language type */
-	 u8 bytes_per_char;
-	u32 next_font;
-	 u8 underline_height;
-	 u8 underline_pos;
-	 u8 res008[2];
-};
-
-/* sticore internal font handling */
-
-struct sti_cooked_font {
-        struct sti_rom_font *raw;
-	struct sti_cooked_font *next_font;
-};
-
-struct sti_cooked_rom {
-        struct sti_rom *raw;
-	struct sti_cooked_font *font_start;
-};
-
-/* STI font printing function structs */
-
-struct sti_font_inptr {
-	u32 font_start_addr;	/* address of font start */
-	s16 index;		/* index into font table of character */
-	u8 fg_color;		/* foreground color of character */
-	u8 bg_color;		/* background color of character */
-	s16 dest_x;		/* X location of character upper left */
-	s16 dest_y;		/* Y location of character upper left */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-struct sti_font_flags {
-	u32 wait : 1;		/* should routine idle wait or not */
-	u32 non_text : 1;	/* font unpack/move in non_text planes =1, text =0 */
-	u32 pad : 30;		/* pad to word boundary */
-	u32 future_ptr; 	/* pointer to future data */
-};
-	
-struct sti_font_outptr {
-	s32 errno;		/* error number on failure */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-/* STI blockmove structs */
-
-struct sti_blkmv_flags {
-	u32 wait : 1;		/* should routine idle wait or not */
-	u32 color : 1;		/* change color during move? */
-	u32 clear : 1;		/* clear during move? */
-	u32 non_text : 1;	/* block move in non_text planes =1, text =0 */
-	u32 pad : 28;		/* pad to word boundary */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-struct sti_blkmv_inptr {
-	u8 fg_color;		/* foreground color after move */
-	u8 bg_color;		/* background color after move */
-	s16 src_x;		/* source upper left pixel x location */
-	s16 src_y;		/* source upper left pixel y location */
-	s16 dest_x;		/* dest upper left pixel x location */
-	s16 dest_y;		/* dest upper left pixel y location */
-	s16 width;		/* block width in pixels */
-	s16 height;		/* block height in pixels */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-struct sti_blkmv_outptr {
-	s32 errno;		/* error number on failure */
-	u32 future_ptr; 	/* pointer to future data */
-};
-
-
-/* sti_all_data is an internal struct which needs to be allocated in
- * low memory (< 4GB) if STI is used with 32bit STI on a 64bit kernel */
-
-struct sti_all_data {
-	struct sti_glob_cfg glob_cfg;
-	struct sti_glob_cfg_ext glob_cfg_ext;
-
-	struct sti_conf_inptr		inq_inptr;
-	struct sti_conf_outptr		inq_outptr; /* configuration */
-	struct sti_conf_outptr_ext	inq_outptr_ext;
-
-	struct sti_init_inptr_ext	init_inptr_ext;
-	struct sti_init_inptr		init_inptr;
-	struct sti_init_outptr		init_outptr;
-
-	struct sti_blkmv_inptr		blkmv_inptr;
-	struct sti_blkmv_outptr		blkmv_outptr;
-
-	struct sti_font_inptr		font_inptr;
-	struct sti_font_outptr		font_outptr;
-
-	/* leave as last entries */
-	unsigned long save_addr[1024 / sizeof(unsigned long)];
-	   /* min 256 bytes which is STI default, max sti->sti_mem_request */
-	unsigned long sti_mem_addr[256 / sizeof(unsigned long)];
-	/* do not add something below here ! */
-};
-
-/* internal generic STI struct */
-
-struct sti_struct {
-	spinlock_t lock;
-		
-	/* the following fields needs to be filled in by the word/byte routines */
-	int font_width;	
-	int font_height;
-	/* char **mon_strings; */
-	int sti_mem_request;
-	u32 graphics_id[2];
-
-	struct sti_cooked_rom *rom;
-
-	unsigned long font_unpmv;
-	unsigned long block_move;
-	unsigned long init_graph;
-	unsigned long inq_conf;
-
-	/* all following fields are initialized by the generic routines */
-	int text_planes;
-	region_t regions[STI_REGION_MAX];
-	unsigned long regions_phys[STI_REGION_MAX];
-
-	struct sti_glob_cfg *glob_cfg;	/* points into sti_all_data */
-
-	struct sti_cooked_font *font;	/* ptr to selected font (cooked) */
-
-	struct pci_dev *pd;
-
-	/* PCI data structures (pg. 17ff from sti.pdf) */
-	u8 rm_entry[16]; /* pci region mapper array == pci config space offset */
-
-	/* pointer to the fb_info where this STI device is used */
-	struct fb_info *info;
-
-	/* pointer to all internal data */
-	struct sti_all_data *sti_data;
-};
-
-
-/* sticore interface functions */
-
-struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
-
-
-/* sticore main function to call STI firmware */
-
-int sti_call(const struct sti_struct *sti, unsigned long func,
-		const void *flags, void *inptr, void *outptr,
-		struct sti_glob_cfg *glob_cfg);
-
-
-/* functions to call the STI ROM directly */
-
-void sti_putc(struct sti_struct *sti, int c, int y, int x);
-void sti_set(struct sti_struct *sti, int src_y, int src_x,
-	     int height, int width, u8 color);
-void sti_clear(struct sti_struct *sti, int src_y, int src_x,
-	       int height, int width, int c);
-void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
-	       int dst_y, int dst_x, int height, int width);
-
-#endif	/* STICORE_H */
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
deleted file mode 100644
index cfe8a2f905c5..000000000000
--- a/drivers/video/stifb.c
+++ /dev/null
@@ -1,1417 +0,0 @@
-/*
- * linux/drivers/video/stifb.c - 
- * Low level Frame buffer driver for HP workstations with 
- * STI (standard text interface) video firmware.
- *
- * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>
- * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
- * 
- * Based on:
- * - linux/drivers/video/artistfb.c -- Artist frame buffer driver
- *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *   - based on skeletonfb, which was
- *	Created 28 Dec 1997 by Geert Uytterhoeven
- * - HP Xhp cfb-based X11 window driver for XFree86
- *	(c)Copyright 1992 Hewlett-Packard Co.
- *
- * 
- *  The following graphics display devices (NGLE family) are supported by this driver:
- *
- *  HPA4070A	known as "HCRX", a 1280x1024 color device with 8 planes
- *  HPA4071A	known as "HCRX24", a 1280x1024 color device with 24 planes,
- *		optionally available with a hardware accelerator as HPA4071A_Z
- *  HPA1659A	known as "CRX", a 1280x1024 color device with 8 planes
- *  HPA1439A	known as "CRX24", a 1280x1024 color device with 24 planes,
- *		optionally available with a hardware accelerator.
- *  HPA1924A	known as "GRX", a 1280x1024 grayscale device with 8 planes
- *  HPA2269A	known as "Dual CRX", a 1280x1024 color device with 8 planes,
- *		implements support for two displays on a single graphics card.
- *  HP710C	internal graphics support optionally available on the HP9000s710 SPU,
- *		supports 1280x1024 color displays with 8 planes.
- *  HP710G	same as HP710C, 1280x1024 grayscale only
- *  HP710L	same as HP710C, 1024x768 color only
- *  HP712	internal graphics support on HP9000s712 SPU, supports 640x480, 
- *		1024x768 or 1280x1024 color displays on 8 planes (Artist)
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/* TODO:
- *	- 1bpp mode is completely untested
- *	- add support for h/w acceleration
- *	- add hardware cursor
- *	- automatically disable double buffering (e.g. on RDI precisionbook laptop)
- */
-
-
-/* on supported graphic devices you may:
- * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or
- * #undef  FALLBACK_TO_1BPP to reject support for unsupported cards */
-#undef FALLBACK_TO_1BPP
-
-#undef DEBUG_STIFB_REGS		/* debug sti register accesses */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-
-#include <asm/grfioctl.h>	/* for HP-UX compatibility */
-#include <asm/uaccess.h>
-
-#include "sticore.h"
-
-/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
-#define REGION_BASE(fb_info, index) \
-	F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
-
-#define NGLEDEVDEPROM_CRT_REGION 1
-
-#define NR_PALETTE 256
-
-typedef struct {
-	__s32	video_config_reg;
-	__s32	misc_video_start;
-	__s32	horiz_timing_fmt;
-	__s32	serr_timing_fmt;
-	__s32	vert_timing_fmt;
-	__s32	horiz_state;
-	__s32	vert_state;
-	__s32	vtg_state_elements;
-	__s32	pipeline_delay;
-	__s32	misc_video_end;
-} video_setup_t;
-
-typedef struct {                  
-	__s16	sizeof_ngle_data;
-	__s16	x_size_visible;	    /* visible screen dim in pixels  */
-	__s16	y_size_visible;
-	__s16	pad2[15];
-	__s16	cursor_pipeline_delay;
-	__s16	video_interleaves;
-	__s32	pad3[11];
-} ngle_rom_t;
-
-struct stifb_info {
-	struct fb_info info;
-	unsigned int id;
-	ngle_rom_t ngle_rom;
-	struct sti_struct *sti;
-	int deviceSpecificConfig;
-	u32 pseudo_palette[16];
-};
-
-static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
-
-/* ------------------- chipset specific functions -------------------------- */
-
-/* offsets to graphic-chip internal registers */
-
-#define REG_1		0x000118
-#define REG_2		0x000480
-#define REG_3		0x0004a0
-#define REG_4		0x000600
-#define REG_6		0x000800
-#define REG_8		0x000820
-#define REG_9		0x000a04
-#define REG_10		0x018000
-#define REG_11		0x018004
-#define REG_12		0x01800c
-#define REG_13		0x018018
-#define REG_14  	0x01801c
-#define REG_15		0x200000
-#define REG_15b0	0x200000
-#define REG_16b1	0x200005
-#define REG_16b3	0x200007
-#define REG_21		0x200218
-#define REG_22		0x0005a0
-#define REG_23		0x0005c0
-#define REG_26		0x200118
-#define REG_27		0x200308
-#define REG_32		0x21003c
-#define REG_33		0x210040
-#define REG_34		0x200008
-#define REG_35		0x018010
-#define REG_38		0x210020
-#define REG_39		0x210120
-#define REG_40		0x210130
-#define REG_42		0x210028
-#define REG_43		0x21002c
-#define REG_44		0x210030
-#define REG_45		0x210034
-
-#define READ_BYTE(fb,reg)		gsc_readb((fb)->info.fix.mmio_start + (reg))
-#define READ_WORD(fb,reg)		gsc_readl((fb)->info.fix.mmio_start + (reg))
-
-
-#ifndef DEBUG_STIFB_REGS
-# define  DEBUG_OFF()
-# define  DEBUG_ON()
-# define WRITE_BYTE(value,fb,reg)	gsc_writeb((value),(fb)->info.fix.mmio_start + (reg))
-# define WRITE_WORD(value,fb,reg)	gsc_writel((value),(fb)->info.fix.mmio_start + (reg))
-#else
-  static int debug_on = 1;
-# define  DEBUG_OFF() debug_on=0
-# define  DEBUG_ON()  debug_on=1
-# define WRITE_BYTE(value,fb,reg)	do { if (debug_on) \
-						printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \
-							__func__, reg, value, READ_BYTE(fb,reg)); 		  \
-					gsc_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
-# define WRITE_WORD(value,fb,reg)	do { if (debug_on) \
-						printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \
-							__func__, reg, value, READ_WORD(fb,reg)); 		  \
-					gsc_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
-#endif /* DEBUG_STIFB_REGS */
-
-
-#define ENABLE	1	/* for enabling/disabling screen */	
-#define DISABLE 0
-
-#define NGLE_LOCK(fb_info)	do { } while (0) 
-#define NGLE_UNLOCK(fb_info)	do { } while (0)
-
-static void
-SETUP_HW(struct stifb_info *fb)
-{
-	char stat;
-
-	do {
-		stat = READ_BYTE(fb, REG_15b0);
-		if (!stat)
-	    		stat = READ_BYTE(fb, REG_15b0);
-	} while (stat);
-}
-
-
-static void
-SETUP_FB(struct stifb_info *fb)
-{	
-	unsigned int reg10_value = 0;
-	
-	SETUP_HW(fb);
-	switch (fb->id)
-	{
-		case CRT_ID_VISUALIZE_EG:
-		case S9000_ID_ARTIST:
-		case S9000_ID_A1659A:
-			reg10_value = 0x13601000;
-			break;
-		case S9000_ID_A1439A:
-			if (fb->info.var.bits_per_pixel == 32)						
-				reg10_value = 0xBBA0A000;
-			else 
-				reg10_value = 0x13601000;
-			break;
-		case S9000_ID_HCRX:
-			if (fb->info.var.bits_per_pixel == 32)
-				reg10_value = 0xBBA0A000;
-			else					
-				reg10_value = 0x13602000;
-			break;
-		case S9000_ID_TIMBER:
-		case CRX24_OVERLAY_PLANES:
-			reg10_value = 0x13602000;
-			break;
-	}
-	if (reg10_value)
-		WRITE_WORD(reg10_value, fb, REG_10);
-	WRITE_WORD(0x83000300, fb, REG_14);
-	SETUP_HW(fb);
-	WRITE_BYTE(1, fb, REG_16b1);
-}
-
-static void
-START_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
-{
-	SETUP_HW(fb);
-	WRITE_WORD(0xBBE0F000, fb, REG_10);
-	WRITE_WORD(0x03000300, fb, REG_14);
-	WRITE_WORD(~0, fb, REG_13);
-}
-
-static void
-WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color) 
-{
-	SETUP_HW(fb);
-	WRITE_WORD(((0x100+index)<<2), fb, REG_3);
-	WRITE_WORD(color, fb, REG_4);
-}
-
-static void
-FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb) 
-{		
-	WRITE_WORD(0x400, fb, REG_2);
-	if (fb->info.var.bits_per_pixel == 32) {
-		WRITE_WORD(0x83000100, fb, REG_1);
-	} else {
-		if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG)
-			WRITE_WORD(0x80000100, fb, REG_26);
-		else							
-			WRITE_WORD(0x80000100, fb, REG_1);
-	}
-	SETUP_FB(fb);
-}
-
-static void
-SETUP_RAMDAC(struct stifb_info *fb) 
-{
-	SETUP_HW(fb);
-	WRITE_WORD(0x04000000, fb, 0x1020);
-	WRITE_WORD(0xff000000, fb, 0x1028);
-}
-
-static void 
-CRX24_SETUP_RAMDAC(struct stifb_info *fb) 
-{
-	SETUP_HW(fb);
-	WRITE_WORD(0x04000000, fb, 0x1000);
-	WRITE_WORD(0x02000000, fb, 0x1004);
-	WRITE_WORD(0xff000000, fb, 0x1008);
-	WRITE_WORD(0x05000000, fb, 0x1000);
-	WRITE_WORD(0x02000000, fb, 0x1004);
-	WRITE_WORD(0x03000000, fb, 0x1008);
-}
-
-#if 0
-static void 
-HCRX_SETUP_RAMDAC(struct stifb_info *fb)
-{
-	WRITE_WORD(0xffffffff, fb, REG_32);
-}
-#endif
-
-static void 
-CRX24_SET_OVLY_MASK(struct stifb_info *fb)
-{
-	SETUP_HW(fb);
-	WRITE_WORD(0x13a02000, fb, REG_11);
-	WRITE_WORD(0x03000300, fb, REG_14);
-	WRITE_WORD(0x000017f0, fb, REG_3);
-	WRITE_WORD(0xffffffff, fb, REG_13);
-	WRITE_WORD(0xffffffff, fb, REG_22);
-	WRITE_WORD(0x00000000, fb, REG_23);
-}
-
-static void
-ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
-{
-	unsigned int value = enable ? 0x43000000 : 0x03000000;
-        SETUP_HW(fb);
-        WRITE_WORD(0x06000000,	fb, 0x1030);
-        WRITE_WORD(value, 	fb, 0x1038);
-}
-
-static void 
-CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
-{
-	unsigned int value = enable ? 0x10000000 : 0x30000000;
-	SETUP_HW(fb);
-	WRITE_WORD(0x01000000,	fb, 0x1000);
-	WRITE_WORD(0x02000000,	fb, 0x1004);
-	WRITE_WORD(value,	fb, 0x1008);
-}
-
-static void
-ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) 
-{
-	u32 DregsMiscVideo = REG_21;
-	u32 DregsMiscCtl = REG_27;
-	
-	SETUP_HW(fb);
-	if (enable) {
-	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo);
-	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   | 0x00800000, fb, DregsMiscCtl);
-	} else {
-	  WRITE_WORD(READ_WORD(fb, DregsMiscVideo) & ~0x0A000000, fb, DregsMiscVideo);
-	  WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   & ~0x00800000, fb, DregsMiscCtl);
-	}
-}
-
-#define GET_ROMTABLE_INDEX(fb) \
-	(READ_BYTE(fb, REG_16b3) - 1)
-
-#define HYPER_CONFIG_PLANES_24 0x00000100
-	
-#define IS_24_DEVICE(fb) \
-	(fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24)
-
-#define IS_888_DEVICE(fb) \
-	(!(IS_24_DEVICE(fb)))
-
-#define GET_FIFO_SLOTS(fb, cnt, numslots)	\
-{	while (cnt < numslots) 			\
-		cnt = READ_WORD(fb, REG_34);	\
-	cnt -= numslots;			\
-}
-
-#define	    IndexedDcd	0	/* Pixel data is indexed (pseudo) color */
-#define	    Otc04	2	/* Pixels in each longword transfer (4) */
-#define	    Otc32	5	/* Pixels in each longword transfer (32) */
-#define	    Ots08	3	/* Each pixel is size (8)d transfer (1) */
-#define	    OtsIndirect	6	/* Each bit goes through FG/BG color(8) */
-#define	    AddrLong	5	/* FB address is Long aligned (pixel) */
-#define	    BINovly	0x2	/* 8 bit overlay */
-#define	    BINapp0I	0x0	/* Application Buffer 0, Indexed */
-#define	    BINapp1I	0x1	/* Application Buffer 1, Indexed */
-#define	    BINapp0F8	0xa	/* Application Buffer 0, Fractional 8-8-8 */
-#define	    BINattr	0xd	/* Attribute Bitmap */
-#define	    RopSrc 	0x3
-#define	    BitmapExtent08  3	/* Each write hits ( 8) bits in depth */
-#define	    BitmapExtent32  5	/* Each write hits (32) bits in depth */
-#define	    DataDynamic	    0	/* Data register reloaded by direct access */
-#define	    MaskDynamic	    1	/* Mask register reloaded by direct access */
-#define	    MaskOtc	    0	/* Mask contains Object Count valid bits */
-
-#define MaskAddrOffset(offset) (offset)
-#define StaticReg(en) (en)
-#define BGx(en) (en)
-#define FGx(en) (en)
-
-#define BAJustPoint(offset) (offset)
-#define BAIndexBase(base) (base)
-#define BA(F,C,S,A,J,B,I) \
-	(((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))
-
-#define IBOvals(R,M,X,S,D,L,B,F) \
-	(((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))
-
-#define NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, val) \
-	WRITE_WORD(val, fb, REG_14)
-
-#define NGLE_QUICK_SET_DST_BM_ACCESS(fb, val) \
-	WRITE_WORD(val, fb, REG_11)
-
-#define NGLE_QUICK_SET_CTL_PLN_REG(fb, val) \
-	WRITE_WORD(val, fb, REG_12)
-
-#define NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, plnmsk32) \
-	WRITE_WORD(plnmsk32, fb, REG_13)
-
-#define NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, fg32) \
-	WRITE_WORD(fg32, fb, REG_35)
-
-#define NGLE_SET_TRANSFERDATA(fb, val) \
-	WRITE_WORD(val, fb, REG_8)
-
-#define NGLE_SET_DSTXY(fb, val) \
-	WRITE_WORD(val, fb, REG_6)
-
-#define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) (		\
-	(u32) (fbaddrbase) +					\
-	    (	(unsigned int)  ( (y) << 13      ) |		\
-		(unsigned int)  ( (x) << 2       )	)	\
-	)
-
-#define NGLE_BINC_SET_DSTADDR(fb, addr) \
-	WRITE_WORD(addr, fb, REG_3)
-
-#define NGLE_BINC_SET_SRCADDR(fb, addr) \
-	WRITE_WORD(addr, fb, REG_2)
-
-#define NGLE_BINC_SET_DSTMASK(fb, mask) \
-	WRITE_WORD(mask, fb, REG_22)
-
-#define NGLE_BINC_WRITE32(fb, data32) \
-	WRITE_WORD(data32, fb, REG_23)
-
-#define START_COLORMAPLOAD(fb, cmapBltCtlData32) \
-	WRITE_WORD((cmapBltCtlData32), fb, REG_38)
-
-#define SET_LENXY_START_RECFILL(fb, lenxy) \
-	WRITE_WORD(lenxy, fb, REG_9)
-
-static void
-HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
-{
-	u32 DregsHypMiscVideo = REG_33;
-	unsigned int value;
-	SETUP_HW(fb);
-	value = READ_WORD(fb, DregsHypMiscVideo);
-	if (enable)
-		value |= 0x0A000000;
-	else
-		value &= ~0x0A000000;
-	WRITE_WORD(value, fb, DregsHypMiscVideo);
-}
-
-
-/* BufferNumbers used by SETUP_ATTR_ACCESS() */
-#define BUFF0_CMAP0	0x00001e02
-#define BUFF1_CMAP0	0x02001e02
-#define BUFF1_CMAP3	0x0c001e02
-#define ARTIST_CMAP0	0x00000102
-#define HYPER_CMAP8	0x00000100
-#define HYPER_CMAP24	0x00000800
-
-static void
-SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber)
-{
-	SETUP_HW(fb);
-	WRITE_WORD(0x2EA0D000, fb, REG_11);
-	WRITE_WORD(0x23000302, fb, REG_14);
-	WRITE_WORD(BufferNumber, fb, REG_12);
-	WRITE_WORD(0xffffffff, fb, REG_8);
-}
-
-static void
-SET_ATTR_SIZE(struct stifb_info *fb, int width, int height) 
-{
-	/* REG_6 seems to have special values when run on a 
-	   RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or
-	   INTERNAL_EG_X1024).  The values are:
-		0x2f0: internal (LCD) & external display enabled
-		0x2a0: external display only
-		0x000: zero on standard artist graphic cards
-	*/ 
-	WRITE_WORD(0x00000000, fb, REG_6);
-	WRITE_WORD((width<<16) | height, fb, REG_9);
-	WRITE_WORD(0x05000000, fb, REG_6);
-	WRITE_WORD(0x00040001, fb, REG_9);
-}
-
-static void
-FINISH_ATTR_ACCESS(struct stifb_info *fb) 
-{
-	SETUP_HW(fb);
-	WRITE_WORD(0x00000000, fb, REG_12);
-}
-
-static void
-elkSetupPlanes(struct stifb_info *fb)
-{
-	SETUP_RAMDAC(fb);
-	SETUP_FB(fb);
-}
-
-static void 
-ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)
-{
-	SETUP_ATTR_ACCESS(fb, BufferNumber);
-	SET_ATTR_SIZE(fb, fb->info.var.xres, fb->info.var.yres);
-	FINISH_ATTR_ACCESS(fb);
-	SETUP_FB(fb);
-}
-
-
-static void
-rattlerSetupPlanes(struct stifb_info *fb)
-{
-	int saved_id, y;
-
- 	/* Write RAMDAC pixel read mask register so all overlay
-	 * planes are display-enabled.  (CRX24 uses Bt462 pixel
-	 * read mask register for overlay planes, not image planes).
-	 */
-	CRX24_SETUP_RAMDAC(fb);
-    
-	/* change fb->id temporarily to fool SETUP_FB() */
-	saved_id = fb->id;
-	fb->id = CRX24_OVERLAY_PLANES;
-	SETUP_FB(fb);
-	fb->id = saved_id;
-
-	for (y = 0; y < fb->info.var.yres; ++y)
-		memset(fb->info.screen_base + y * fb->info.fix.line_length,
-			0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8);
-
-	CRX24_SET_OVLY_MASK(fb);
-	SETUP_FB(fb);
-}
-
-
-#define HYPER_CMAP_TYPE				0
-#define NGLE_CMAP_INDEXED0_TYPE			0
-#define NGLE_CMAP_OVERLAY_TYPE			3
-
-/* typedef of LUT (Colormap) BLT Control Register */
-typedef union	/* Note assumption that fields are packed left-to-right */
-{	u32 all;
-	struct
-	{
-		unsigned enable              :  1;
-		unsigned waitBlank           :  1;
-		unsigned reserved1           :  4;
-		unsigned lutOffset           : 10;   /* Within destination LUT */
-		unsigned lutType             :  2;   /* Cursor, image, overlay */
-		unsigned reserved2           :  4;
-		unsigned length              : 10;
-	} fields;
-} NgleLutBltCtl;
-
-
-#if 0
-static NgleLutBltCtl
-setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
-{
-	NgleLutBltCtl lutBltCtl;
-
-	/* set enable, zero reserved fields */
-	lutBltCtl.all           = 0x80000000;
-	lutBltCtl.fields.length = length;
-
-	switch (fb->id) 
-	{
-	case S9000_ID_A1439A:		/* CRX24 */
-		if (fb->var.bits_per_pixel == 8) {
-			lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE;
-			lutBltCtl.fields.lutOffset = 0;
-		} else {
-			lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
-			lutBltCtl.fields.lutOffset = 0 * 256;
-		}
-		break;
-		
-	case S9000_ID_ARTIST:
-		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
-		lutBltCtl.fields.lutOffset = 0 * 256;
-		break;
-		
-	default:
-		lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
-		lutBltCtl.fields.lutOffset = 0;
-		break;
-	}
-
-	/* Offset points to start of LUT.  Adjust for within LUT */
-	lutBltCtl.fields.lutOffset += offsetWithinLut;
-
-	return lutBltCtl;
-}
-#endif
-
-static NgleLutBltCtl
-setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length) 
-{
-	NgleLutBltCtl lutBltCtl;
-
-	/* set enable, zero reserved fields */
-	lutBltCtl.all = 0x80000000;
-
-	lutBltCtl.fields.length = length;
-	lutBltCtl.fields.lutType = HYPER_CMAP_TYPE;
-
-	/* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */
-	if (fb->info.var.bits_per_pixel == 8)
-		lutBltCtl.fields.lutOffset = 2 * 256;
-	else
-		lutBltCtl.fields.lutOffset = 0 * 256;
-
-	/* Offset points to start of LUT.  Adjust for within LUT */
-	lutBltCtl.fields.lutOffset += offsetWithinLut;
-
-	return lutBltCtl;
-}
-
-
-static void hyperUndoITE(struct stifb_info *fb)
-{
-	int nFreeFifoSlots = 0;
-	u32 fbAddr;
-
-	NGLE_LOCK(fb);
-
-	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
-	WRITE_WORD(0xffffffff, fb, REG_32);
-
-	/* Write overlay transparency mask so only entry 255 is transparent */
-
-	/* Hardware setup for full-depth write to "magic" location */
-	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
-	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
-		BA(IndexedDcd, Otc04, Ots08, AddrLong,
-		BAJustPoint(0), BINovly, BAIndexBase(0)));
-	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
-		IBOvals(RopSrc, MaskAddrOffset(0),
-		BitmapExtent08, StaticReg(0),
-		DataDynamic, MaskOtc, BGx(0), FGx(0)));
-
-	/* Now prepare to write to the "magic" location */
-	fbAddr = NGLE_LONG_FB_ADDRESS(0, 1532, 0);
-	NGLE_BINC_SET_DSTADDR(fb, fbAddr);
-	NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffff);
-	NGLE_BINC_SET_DSTMASK(fb, 0xffffffff);
-
-	/* Finally, write a zero to clear the mask */
-	NGLE_BINC_WRITE32(fb, 0);
-
-	NGLE_UNLOCK(fb);
-}
-
-static void 
-ngleDepth8_ClearImagePlanes(struct stifb_info *fb)
-{
-	/* FIXME! */
-}
-
-static void 
-ngleDepth24_ClearImagePlanes(struct stifb_info *fb)
-{
-	/* FIXME! */
-}
-
-static void
-ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg)
-{
-	int nFreeFifoSlots = 0;
-	u32 packed_dst;
-	u32 packed_len;
-
-	NGLE_LOCK(fb);
-
-	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4);
-	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
-				     BA(IndexedDcd, Otc32, OtsIndirect,
-					AddrLong, BAJustPoint(0),
-					BINattr, BAIndexBase(0)));
-	NGLE_QUICK_SET_CTL_PLN_REG(fb, ctlPlaneReg);
-	NGLE_SET_TRANSFERDATA(fb, 0xffffffff);
-
-	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
-				       IBOvals(RopSrc, MaskAddrOffset(0),
-					       BitmapExtent08, StaticReg(1),
-					       DataDynamic, MaskOtc,
-					       BGx(0), FGx(0)));
-	packed_dst = 0;
-	packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
-	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
-	NGLE_SET_DSTXY(fb, packed_dst);
-	SET_LENXY_START_RECFILL(fb, packed_len);
-
-	/*
-	 * In order to work around an ELK hardware problem (Buffy doesn't
-	 * always flush it's buffers when writing to the attribute
-	 * planes), at least 4 pixels must be written to the attribute
-	 * planes starting at (X == 1280) and (Y != to the last Y written
-	 * by BIF):
-	 */
-
-	if (fb->id == S9000_ID_A1659A) {   /* ELK_DEVICE_ID */
-		/* It's safe to use scanline zero: */
-		packed_dst = (1280 << 16);
-		GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
-		NGLE_SET_DSTXY(fb, packed_dst);
-		packed_len = (4 << 16) | 1;
-		SET_LENXY_START_RECFILL(fb, packed_len);
-	}   /* ELK Hardware Kludge */
-
-	/**** Finally, set the Control Plane Register back to zero: ****/
-	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
-	NGLE_QUICK_SET_CTL_PLN_REG(fb, 0);
-	
-	NGLE_UNLOCK(fb);
-}
-    
-static void
-ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data)
-{
-	int nFreeFifoSlots = 0;
-	u32 packed_dst;
-	u32 packed_len;
-    
-	NGLE_LOCK(fb);
-
-	/* Hardware setup */
-	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8);
-	NGLE_QUICK_SET_DST_BM_ACCESS(fb, 
-				     BA(IndexedDcd, Otc04, Ots08, AddrLong,
-					BAJustPoint(0), BINovly, BAIndexBase(0)));
-
-        NGLE_SET_TRANSFERDATA(fb, 0xffffffff);  /* Write foreground color */
-
-        NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data);
-        NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask);
-    
-        packed_dst = 0;
-        packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
-        NGLE_SET_DSTXY(fb, packed_dst);
-    
-        /* Write zeroes to overlay planes */		       
-	NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
-				       IBOvals(RopSrc, MaskAddrOffset(0),
-					       BitmapExtent08, StaticReg(0),
-					       DataDynamic, MaskOtc, BGx(0), FGx(0)));
-		       
-        SET_LENXY_START_RECFILL(fb, packed_len);
-
-	NGLE_UNLOCK(fb);
-}
-
-static void 
-hyperResetPlanes(struct stifb_info *fb, int enable)
-{
-	unsigned int controlPlaneReg;
-
-	NGLE_LOCK(fb);
-
-	if (IS_24_DEVICE(fb))
-		if (fb->info.var.bits_per_pixel == 32)
-			controlPlaneReg = 0x04000F00;
-		else
-			controlPlaneReg = 0x00000F00;   /* 0x00000800 should be enough, but lets clear all 4 bits */
-	else
-		controlPlaneReg = 0x00000F00; /* 0x00000100 should be enough, but lets clear all 4 bits */
-
-	switch (enable) {
-	case ENABLE:
-		/* clear screen */
-		if (IS_24_DEVICE(fb))
-			ngleDepth24_ClearImagePlanes(fb);
-		else
-			ngleDepth8_ClearImagePlanes(fb);
-
-		/* Paint attribute planes for default case.
-		 * On Hyperdrive, this means all windows using overlay cmap 0. */
-		ngleResetAttrPlanes(fb, controlPlaneReg);
-
-		/* clear overlay planes */
-	        ngleClearOverlayPlanes(fb, 0xff, 255);
-
-		/**************************************************
-		 ** Also need to counteract ITE settings 
-		 **************************************************/
-		hyperUndoITE(fb);
-		break;
-
-	case DISABLE:
-		/* clear screen */
-		if (IS_24_DEVICE(fb))
-			ngleDepth24_ClearImagePlanes(fb);
-		else
-			ngleDepth8_ClearImagePlanes(fb);
-		ngleResetAttrPlanes(fb, controlPlaneReg);
-		ngleClearOverlayPlanes(fb, 0xff, 0);
-		break;
-
-	case -1:	/* RESET */
-		hyperUndoITE(fb);
-		ngleResetAttrPlanes(fb, controlPlaneReg);
-		break;
-    	}
-	
-	NGLE_UNLOCK(fb);
-}
-
-/* Return pointer to in-memory structure holding ELK device-dependent ROM values. */
-
-static void 
-ngleGetDeviceRomData(struct stifb_info *fb)
-{
-#if 0
-XXX: FIXME: !!!
-	int	*pBytePerLongDevDepData;/* data byte == LSB */
-	int 	*pRomTable;
-	NgleDevRomData	*pPackedDevRomData;
-	int	sizePackedDevRomData = sizeof(*pPackedDevRomData);
-	char	*pCard8;
-	int	i;
-	char	*mapOrigin = NULL;
-    
-	int romTableIdx;
-
-	pPackedDevRomData = fb->ngle_rom;
-
-	SETUP_HW(fb);
-	if (fb->id == S9000_ID_ARTIST) {
-		pPackedDevRomData->cursor_pipeline_delay = 4;
-		pPackedDevRomData->video_interleaves     = 4;
-	} else {
-		/* Get pointer to unpacked byte/long data in ROM */
-		pBytePerLongDevDepData = fb->sti->regions[NGLEDEVDEPROM_CRT_REGION];
-
-		/* Tomcat supports several resolutions: 1280x1024, 1024x768, 640x480 */
-		if (fb->id == S9000_ID_TOMCAT)
-	{
-	    /*  jump to the correct ROM table  */
-	    GET_ROMTABLE_INDEX(romTableIdx);
-	    while  (romTableIdx > 0)
-	    {
-		pCard8 = (Card8 *) pPackedDevRomData;
-		pRomTable = pBytePerLongDevDepData;
-		/* Pack every fourth byte from ROM into structure */
-		for (i = 0; i < sizePackedDevRomData; i++)
-		{
-		    *pCard8++ = (Card8) (*pRomTable++);
-		}
-
-		pBytePerLongDevDepData = (Card32 *)
-			((Card8 *) pBytePerLongDevDepData +
-			       pPackedDevRomData->sizeof_ngle_data);
-
-		romTableIdx--;
-	    }
-	}
-
-	pCard8 = (Card8 *) pPackedDevRomData;
-
-	/* Pack every fourth byte from ROM into structure */
-	for (i = 0; i < sizePackedDevRomData; i++)
-	{
-	    *pCard8++ = (Card8) (*pBytePerLongDevDepData++);
-	}
-    }
-
-    SETUP_FB(fb);
-#endif
-}
-
-
-#define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES	4
-#define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE	8
-#define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE		10
-#define HYPERBOWL_MODE2_8_24					15
-
-/* HCRX specific boot-time initialization */
-static void __init
-SETUP_HCRX(struct stifb_info *fb)
-{
-	int	hyperbowl;
-        int	nFreeFifoSlots = 0;
-
-	if (fb->id != S9000_ID_HCRX)
-		return;
-
-	/* Initialize Hyperbowl registers */
-	GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
-	
-	if (IS_24_DEVICE(fb)) {
-		hyperbowl = (fb->info.var.bits_per_pixel == 32) ?
-			HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE :
-			HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE;
-
-		/* First write to Hyperbowl must happen twice (bug) */
-		WRITE_WORD(hyperbowl, fb, REG_40);
-		WRITE_WORD(hyperbowl, fb, REG_40);
-		
-		WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39);
-		
-		WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */
-		WRITE_WORD(0x404c4048, fb, REG_43);
-		WRITE_WORD(0x034c0348, fb, REG_44);
-		WRITE_WORD(0x444c4448, fb, REG_45);
-	} else {
-		hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES;
-
-		/* First write to Hyperbowl must happen twice (bug) */
-		WRITE_WORD(hyperbowl, fb, REG_40);
-		WRITE_WORD(hyperbowl, fb, REG_40);
-
-		WRITE_WORD(0x00000000, fb, REG_42);
-		WRITE_WORD(0x00000000, fb, REG_43);
-		WRITE_WORD(0x00000000, fb, REG_44);
-		WRITE_WORD(0x444c4048, fb, REG_45);
-	}
-}
-
-
-/* ------------------- driver specific functions --------------------------- */
-
-static int
-stifb_setcolreg(u_int regno, u_int red, u_int green,
-	      u_int blue, u_int transp, struct fb_info *info)
-{
-	struct stifb_info *fb = (struct stifb_info *) info;
-	u32 color;
-
-	if (regno >= NR_PALETTE)
-		return 1;
-
-	red   >>= 8;
-	green >>= 8;
-	blue  >>= 8;
-
-	DEBUG_OFF();
-
-	START_IMAGE_COLORMAP_ACCESS(fb);
-
-	if (unlikely(fb->info.var.grayscale)) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		color = ((red * 77) +
-			 (green * 151) +
-			 (blue * 28)) >> 8;
-	} else {
-		color = ((red << 16) |
-			 (green << 8) |
-			 (blue));
-	}
-
-	if (fb->info.fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		struct fb_var_screeninfo *var = &fb->info.var;
-		if (regno < 16)
-			((u32 *)fb->info.pseudo_palette)[regno] =
-				regno << var->red.offset |
-				regno << var->green.offset |
-				regno << var->blue.offset;
-	}
-
-	WRITE_IMAGE_COLOR(fb, regno, color);
-
-	if (fb->id == S9000_ID_HCRX) {
-		NgleLutBltCtl lutBltCtl;
-
-		lutBltCtl = setHyperLutBltCtl(fb,
-				0,	/* Offset w/i LUT */
-				256);	/* Load entire LUT */
-		NGLE_BINC_SET_SRCADDR(fb,
-				NGLE_LONG_FB_ADDRESS(0, 0x100, 0)); 
-				/* 0x100 is same as used in WRITE_IMAGE_COLOR() */
-		START_COLORMAPLOAD(fb, lutBltCtl.all);
-		SETUP_FB(fb);
-	} else {
-		/* cleanup colormap hardware */
-		FINISH_IMAGE_COLORMAP_ACCESS(fb);
-	}
-
-	DEBUG_ON();
-
-	return 0;
-}
-
-static int
-stifb_blank(int blank_mode, struct fb_info *info)
-{
-	struct stifb_info *fb = (struct stifb_info *) info;
-	int enable = (blank_mode == 0) ? ENABLE : DISABLE;
-
-	switch (fb->id) {
-	case S9000_ID_A1439A:
-		CRX24_ENABLE_DISABLE_DISPLAY(fb, enable);
-		break;
-	case CRT_ID_VISUALIZE_EG:
-	case S9000_ID_ARTIST:
-		ARTIST_ENABLE_DISABLE_DISPLAY(fb, enable);
-		break;
-	case S9000_ID_HCRX:
-		HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);
-		break;
-	case S9000_ID_A1659A:	/* fall through */
-	case S9000_ID_TIMBER:
-	case CRX24_OVERLAY_PLANES:
-	default:
-		ENABLE_DISABLE_DISPLAY(fb, enable);
-		break;
-	}
-	
-	SETUP_FB(fb);
-	return 0;
-}
-
-static void __init
-stifb_init_display(struct stifb_info *fb)
-{
-	int id = fb->id;
-
-	SETUP_FB(fb);
-
-	/* HCRX specific initialization */
-	SETUP_HCRX(fb);
-	
-	/*
-	if (id == S9000_ID_HCRX)
-		hyperInitSprite(fb);
-	else
-		ngleInitSprite(fb);
-	*/
-	
-	/* Initialize the image planes. */ 
-        switch (id) {
-	 case S9000_ID_HCRX:
-	    hyperResetPlanes(fb, ENABLE);
-	    break;
-	 case S9000_ID_A1439A:
-	    rattlerSetupPlanes(fb);
-	    break;
-	 case S9000_ID_A1659A:
-	 case S9000_ID_ARTIST:
-	 case CRT_ID_VISUALIZE_EG:
-	    elkSetupPlanes(fb);
-	    break;
-	}
-
-	/* Clear attribute planes on non HCRX devices. */
-        switch (id) {
-	 case S9000_ID_A1659A:
-	 case S9000_ID_A1439A:
-	    if (fb->info.var.bits_per_pixel == 32)
-		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
-	    else {
-		ngleSetupAttrPlanes(fb, BUFF1_CMAP0);
-	    }
-	    if (id == S9000_ID_A1439A)
-		ngleClearOverlayPlanes(fb, 0xff, 0);
-	    break;
-	 case S9000_ID_ARTIST:
-	 case CRT_ID_VISUALIZE_EG:
-	    if (fb->info.var.bits_per_pixel == 32)
-		ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
-	    else {
-		ngleSetupAttrPlanes(fb, ARTIST_CMAP0);
-	    }
-	    break;
-	}
-	stifb_blank(0, (struct fb_info *)fb);	/* 0=enable screen */
-
-	SETUP_FB(fb);
-}
-
-/* ------------ Interfaces to hardware functions ------------ */
-
-static struct fb_ops stifb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= stifb_setcolreg,
-	.fb_blank	= stifb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-
-/*
- *  Initialization
- */
-
-static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
-{
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	struct stifb_info *fb;
-	struct fb_info *info;
-	unsigned long sti_rom_address;
-	char *dev_name;
-	int bpp, xres, yres;
-
-	fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
-	if (!fb) {
-		printk(KERN_ERR "stifb: Could not allocate stifb structure\n");
-		return -ENODEV;
-	}
-	
-	info = &fb->info;
-
-	/* set struct to a known state */
-	fix = &info->fix;
-	var = &info->var;
-
-	fb->sti = sti;
-	dev_name = sti->sti_data->inq_outptr.dev_name;
-	/* store upper 32bits of the graphics id */
-	fb->id = fb->sti->graphics_id[0];
-
-	/* only supported cards are allowed */
-	switch (fb->id) {
-	case CRT_ID_VISUALIZE_EG:
-		/* Visualize cards can run either in "double buffer" or
- 		  "standard" mode. Depending on the mode, the card reports
-		  a different device name, e.g. "INTERNAL_EG_DX1024" in double
-		  buffer mode and "INTERNAL_EG_X1024" in standard mode.
-		  Since this driver only supports standard mode, we check
-		  if the device name contains the string "DX" and tell the
-		  user how to reconfigure the card. */
-		if (strstr(dev_name, "DX")) {
-		   printk(KERN_WARNING
-"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"
-"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",
-			dev_name);
-		   goto out_err0;
-		}
-		/* fall though */
-	case S9000_ID_ARTIST:
-	case S9000_ID_HCRX:
-	case S9000_ID_TIMBER:
-	case S9000_ID_A1659A:
-	case S9000_ID_A1439A:
-		break;
-	default:
-		printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",
-			dev_name, fb->id);
-		goto out_err0;
-	}
-	
-	/* default to 8 bpp on most graphic chips */
-	bpp = 8;
-	xres = sti_onscreen_x(fb->sti);
-	yres = sti_onscreen_y(fb->sti);
-
-	ngleGetDeviceRomData(fb);
-
-	/* get (virtual) io region base addr */
-	fix->mmio_start = REGION_BASE(fb,2);
-	fix->mmio_len   = 0x400000;
-
-       	/* Reject any device not in the NGLE family */
-	switch (fb->id) {
-	case S9000_ID_A1659A:	/* CRX/A1659A */
-		break;
-	case S9000_ID_ELM:	/* GRX, grayscale but else same as A1659A */
-		var->grayscale = 1;
-		fb->id = S9000_ID_A1659A;
-		break;
-	case S9000_ID_TIMBER:	/* HP9000/710 Any (may be a grayscale device) */
-		if (strstr(dev_name, "GRAYSCALE") || 
-		    strstr(dev_name, "Grayscale") ||
-		    strstr(dev_name, "grayscale"))
-			var->grayscale = 1;
-		break;
-	case S9000_ID_TOMCAT:	/* Dual CRX, behaves else like a CRX */
-		/* FIXME: TomCat supports two heads:
-		 * fb.iobase = REGION_BASE(fb_info,3);
-		 * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx);
-		 * for now we only support the left one ! */
-		xres = fb->ngle_rom.x_size_visible;
-		yres = fb->ngle_rom.y_size_visible;
-		fb->id = S9000_ID_A1659A;
-		break;
-	case S9000_ID_A1439A:	/* CRX24/A1439A */
-		bpp = 32;
-		break;
-	case S9000_ID_HCRX:	/* Hyperdrive/HCRX */
-		memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
-		if ((fb->sti->regions_phys[0] & 0xfc000000) ==
-		    (fb->sti->regions_phys[2] & 0xfc000000))
-			sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
-		else
-			sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
-
-		fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
-		if (IS_24_DEVICE(fb)) {
-			if (bpp_pref == 8 || bpp_pref == 32)
-				bpp = bpp_pref;
-			else
-				bpp = 32;
-		} else
-			bpp = 8;
-		READ_WORD(fb, REG_15);
-		SETUP_HW(fb);
-		break;
-	case CRT_ID_VISUALIZE_EG:
-	case S9000_ID_ARTIST:	/* Artist */
-		break;
-	default: 
-#ifdef FALLBACK_TO_1BPP
-	       	printk(KERN_WARNING 
-			"stifb: Unsupported graphics card (id=0x%08x) "
-				"- now trying 1bpp mode instead\n",
-			fb->id);
-		bpp = 1;	/* default to 1 bpp */
-		break;
-#else
-	       	printk(KERN_WARNING 
-			"stifb: Unsupported graphics card (id=0x%08x) "
-				"- skipping.\n",
-			fb->id);
-		goto out_err0;
-#endif
-	}
-
-
-	/* get framebuffer physical and virtual base addr & len (64bit ready) */
-	fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]);
-	fix->smem_len = fb->sti->regions[1].region_desc.length * 4096;
-
-	fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;
-	if (!fix->line_length)
-		fix->line_length = 2048; /* default */
-	
-	/* limit fbsize to max visible screen size */
-	if (fix->smem_len > yres*fix->line_length)
-		fix->smem_len = yres*fix->line_length;
-	
-	fix->accel = FB_ACCEL_NONE;
-
-	switch (bpp) {
-	    case 1:
-		fix->type = FB_TYPE_PLANES;	/* well, sort of */
-		fix->visual = FB_VISUAL_MONO10;
-		var->red.length = var->green.length = var->blue.length = 1;
-		break;
-	    case 8:
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-		var->red.length = var->green.length = var->blue.length = 8;
-		break;
-	    case 32:
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->visual = FB_VISUAL_DIRECTCOLOR;
-		var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
-		var->blue.offset = 0;
-		var->green.offset = 8;
-		var->red.offset = 16;
-		var->transp.offset = 24;
-		break;
-	    default:
-		break;
-	}
-	
-	var->xres = var->xres_virtual = xres;
-	var->yres = var->yres_virtual = yres;
-	var->bits_per_pixel = bpp;
-
-	strcpy(fix->id, "stifb");
-	info->fbops = &stifb_ops;
-	info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len);
-	info->screen_size = fix->smem_len;
-	info->flags = FBINFO_DEFAULT;
-	info->pseudo_palette = &fb->pseudo_palette;
-
-	/* This has to be done !!! */
-	if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0))
-		goto out_err1;
-	stifb_init_display(fb);
-
-	if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
-		printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",
-				fix->smem_start, fix->smem_start+fix->smem_len);
-		goto out_err2;
-	}
-		
-	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) {
-		printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n",
-				fix->mmio_start, fix->mmio_start+fix->mmio_len);
-		goto out_err3;
-	}
-
-	if (register_framebuffer(&fb->info) < 0)
-		goto out_err4;
-
-	sti->info = info; /* save for unregister_framebuffer() */
-
-	fb_info(&fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",
-		fix->id,
-		var->xres, 
-		var->yres,
-		var->bits_per_pixel,
-		dev_name,
-		fb->id, 
-		fix->mmio_start);
-
-	return 0;
-
-
-out_err4:
-	release_mem_region(fix->mmio_start, fix->mmio_len);
-out_err3:
-	release_mem_region(fix->smem_start, fix->smem_len);
-out_err2:
-	fb_dealloc_cmap(&info->cmap);
-out_err1:
-	iounmap(info->screen_base);
-out_err0:
-	kfree(fb);
-	return -ENXIO;
-}
-
-static int stifb_disabled __initdata;
-
-int __init
-stifb_setup(char *options);
-
-static int __init stifb_init(void)
-{
-	struct sti_struct *sti;
-	struct sti_struct *def_sti;
-	int i;
-	
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("stifb", &option))
-		return -ENODEV;
-	stifb_setup(option);
-#endif
-	if (stifb_disabled) {
-		printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
-		return -ENXIO;
-	}
-	
-	def_sti = sti_get_rom(0);
-	if (def_sti) {
-		for (i = 1; i <= MAX_STI_ROMS; i++) {
-			sti = sti_get_rom(i);
-			if (!sti)
-				break;
-			if (sti == def_sti) {
-				stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
-				break;
-			}
-		}
-	}
-
-	for (i = 1; i <= MAX_STI_ROMS; i++) {
-		sti = sti_get_rom(i);
-		if (!sti)
-			break;
-		if (sti == def_sti)
-			continue;
-		stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
-	}
-	return 0;
-}
-
-/*
- *  Cleanup
- */
-
-static void __exit
-stifb_cleanup(void)
-{
-	struct sti_struct *sti;
-	int i;
-	
-	for (i = 1; i <= MAX_STI_ROMS; i++) {
-		sti = sti_get_rom(i);
-		if (!sti)
-			break;
-		if (sti->info) {
-			struct fb_info *info = sti->info;
-			unregister_framebuffer(sti->info);
-			release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-		        release_mem_region(info->fix.smem_start, info->fix.smem_len);
-				if (info->screen_base)
-					iounmap(info->screen_base);
-		        fb_dealloc_cmap(&info->cmap);
-		        framebuffer_release(info);
-		}
-		sti->info = NULL;
-	}
-}
-
-int __init
-stifb_setup(char *options)
-{
-	int i;
-	
-	if (!options || !*options)
-		return 1;
-	
-	if (strncmp(options, "off", 3) == 0) {
-		stifb_disabled = 1;
-		options += 3;
-	}
-
-	if (strncmp(options, "bpp", 3) == 0) {
-		options += 3;
-		for (i = 0; i < MAX_STI_ROMS; i++) {
-			if (*options++ != ':')
-				break;
-			stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);
-		}
-	}
-	return 1;
-}
-
-__setup("stifb=", stifb_setup);
-
-module_init(stifb_init);
-module_exit(stifb_cleanup);
-
-MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
-MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
deleted file mode 100644
index 58241b47a96d..000000000000
--- a/drivers/video/sunxvr1000.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* sunxvr1000.c: Sun XVR-1000 driver for sparc64 systems
- *
- * Copyright (C) 2010 David S. Miller (davem@davemloft.net)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/of_device.h>
-
-struct gfb_info {
-	struct fb_info		*info;
-
-	char __iomem		*fb_base;
-	unsigned long		fb_base_phys;
-
-	struct device_node	*of_node;
-
-	unsigned int		width;
-	unsigned int		height;
-	unsigned int		depth;
-	unsigned int		fb_size;
-
-	u32			pseudo_palette[16];
-};
-
-static int gfb_get_props(struct gfb_info *gp)
-{
-	gp->width = of_getintprop_default(gp->of_node, "width", 0);
-	gp->height = of_getintprop_default(gp->of_node, "height", 0);
-	gp->depth = of_getintprop_default(gp->of_node, "depth", 32);
-
-	if (!gp->width || !gp->height) {
-		printk(KERN_ERR "gfb: Critical properties missing for %s\n",
-		       gp->of_node->full_name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int gfb_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	u32 value;
-
-	if (regno < 16) {
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-
-		value = (blue << 16) | (green << 8) | red;
-		((u32 *)info->pseudo_palette)[regno] = value;
-	}
-
-	return 0;
-}
-
-static struct fb_ops gfb_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= gfb_setcolreg,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-};
-
-static int gfb_set_fbinfo(struct gfb_info *gp)
-{
-	struct fb_info *info = gp->info;
-	struct fb_var_screeninfo *var = &info->var;
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &gfb_ops;
-	info->screen_base = gp->fb_base;
-	info->screen_size = gp->fb_size;
-
-	info->pseudo_palette = gp->pseudo_palette;
-
-	/* Fill fix common fields */
-	strlcpy(info->fix.id, "gfb", sizeof(info->fix.id));
-        info->fix.smem_start = gp->fb_base_phys;
-        info->fix.smem_len = gp->fb_size;
-        info->fix.type = FB_TYPE_PACKED_PIXELS;
-	if (gp->depth == 32 || gp->depth == 24)
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	else
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	var->xres = gp->width;
-	var->yres = gp->height;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-	var->bits_per_pixel = gp->depth;
-
-	var->red.offset = 0;
-	var->red.length = 8;
-	var->green.offset = 8;
-	var->green.length = 8;
-	var->blue.offset = 16;
-	var->blue.length = 8;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
-		printk(KERN_ERR "gfb: Cannot allocate color map.\n");
-		return -ENOMEM;
-	}
-
-        return 0;
-}
-
-static int gfb_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct gfb_info *gp;
-	int err;
-
-	info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev);
-	if (!info) {
-		printk(KERN_ERR "gfb: Cannot allocate fb_info\n");
-		err = -ENOMEM;
-		goto err_out;
-	}
-
-	gp = info->par;
-	gp->info = info;
-	gp->of_node = dp;
-
-	gp->fb_base_phys = op->resource[6].start;
-
-	err = gfb_get_props(gp);
-	if (err)
-		goto err_release_fb;
-
-	/* Framebuffer length is the same regardless of resolution. */
-	info->fix.line_length = 16384;
-	gp->fb_size = info->fix.line_length * gp->height;
-
-	gp->fb_base = of_ioremap(&op->resource[6], 0,
-				 gp->fb_size, "gfb fb");
-	if (!gp->fb_base) {
-		err = -ENOMEM;
-		goto err_release_fb;
-	}
-
-	err = gfb_set_fbinfo(gp);
-	if (err)
-		goto err_unmap_fb;
-
-	printk("gfb: Found device at %s\n", dp->full_name);
-
-	err = register_framebuffer(info);
-	if (err < 0) {
-		printk(KERN_ERR "gfb: Could not register framebuffer %s\n",
-		       dp->full_name);
-		goto err_unmap_fb;
-	}
-
-	dev_set_drvdata(&op->dev, info);
-
-	return 0;
-
-err_unmap_fb:
-	of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size);
-
-err_release_fb:
-        framebuffer_release(info);
-
-err_out:
-	return err;
-}
-
-static int gfb_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct gfb_info *gp = info->par;
-
-	unregister_framebuffer(info);
-
-	iounmap(gp->fb_base);
-
-	of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size);
-
-        framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id gfb_match[] = {
-	{
-		.name = "SUNW,gfb",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, ffb_match);
-
-static struct platform_driver gfb_driver = {
-	.probe		= gfb_probe,
-	.remove		= gfb_remove,
-	.driver = {
-		.name		= "gfb",
-		.owner		= THIS_MODULE,
-		.of_match_table	= gfb_match,
-	},
-};
-
-static int __init gfb_init(void)
-{
-	if (fb_get_options("gfb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&gfb_driver);
-}
-
-static void __exit gfb_exit(void)
-{
-	platform_driver_unregister(&gfb_driver);
-}
-
-module_init(gfb_init);
-module_exit(gfb_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for Sun XVR-1000 graphics");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c
deleted file mode 100644
index 843b6bab0483..000000000000
--- a/drivers/video/sunxvr2500.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* s3d.c: Sun 3DLABS XVR-2500 et al. driver for sparc64 systems
- *
- * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-
-struct s3d_info {
-	struct fb_info		*info;
-	struct pci_dev		*pdev;
-
-	char __iomem		*fb_base;
-	unsigned long		fb_base_phys;
-
-	struct device_node	*of_node;
-
-	unsigned int		width;
-	unsigned int		height;
-	unsigned int		depth;
-	unsigned int		fb_size;
-
-	u32			pseudo_palette[16];
-};
-
-static int s3d_get_props(struct s3d_info *sp)
-{
-	sp->width = of_getintprop_default(sp->of_node, "width", 0);
-	sp->height = of_getintprop_default(sp->of_node, "height", 0);
-	sp->depth = of_getintprop_default(sp->of_node, "depth", 8);
-
-	if (!sp->width || !sp->height) {
-		printk(KERN_ERR "s3d: Critical properties missing for %s\n",
-		       pci_name(sp->pdev));
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int s3d_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	u32 value;
-
-	if (regno < 16) {
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-
-		value = (blue << 24) | (green << 16) | (red << 8);
-		((u32 *)info->pseudo_palette)[regno] = value;
-	}
-
-	return 0;
-}
-
-static struct fb_ops s3d_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= s3d_setcolreg,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-};
-
-static int s3d_set_fbinfo(struct s3d_info *sp)
-{
-	struct fb_info *info = sp->info;
-	struct fb_var_screeninfo *var = &info->var;
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &s3d_ops;
-	info->screen_base = sp->fb_base;
-	info->screen_size = sp->fb_size;
-
-	info->pseudo_palette = sp->pseudo_palette;
-
-	/* Fill fix common fields */
-	strlcpy(info->fix.id, "s3d", sizeof(info->fix.id));
-        info->fix.smem_start = sp->fb_base_phys;
-        info->fix.smem_len = sp->fb_size;
-        info->fix.type = FB_TYPE_PACKED_PIXELS;
-	if (sp->depth == 32 || sp->depth == 24)
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	else
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	var->xres = sp->width;
-	var->yres = sp->height;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-	var->bits_per_pixel = sp->depth;
-
-	var->red.offset = 8;
-	var->red.length = 8;
-	var->green.offset = 16;
-	var->green.length = 8;
-	var->blue.offset = 24;
-	var->blue.length = 8;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
-		printk(KERN_ERR "s3d: Cannot allocate color map.\n");
-		return -ENOMEM;
-	}
-
-        return 0;
-}
-
-static int s3d_pci_register(struct pci_dev *pdev,
-			    const struct pci_device_id *ent)
-{
-	struct fb_info *info;
-	struct s3d_info *sp;
-	int err;
-
-	err = pci_enable_device(pdev);
-	if (err < 0) {
-		printk(KERN_ERR "s3d: Cannot enable PCI device %s\n",
-		       pci_name(pdev));
-		goto err_out;
-	}
-
-	info = framebuffer_alloc(sizeof(struct s3d_info), &pdev->dev);
-	if (!info) {
-		printk(KERN_ERR "s3d: Cannot allocate fb_info\n");
-		err = -ENOMEM;
-		goto err_disable;
-	}
-
-	sp = info->par;
-	sp->info = info;
-	sp->pdev = pdev;
-	sp->of_node = pci_device_to_OF_node(pdev);
-	if (!sp->of_node) {
-		printk(KERN_ERR "s3d: Cannot find OF node of %s\n",
-		       pci_name(pdev));
-		err = -ENODEV;
-		goto err_release_fb;
-	}
-
-	sp->fb_base_phys = pci_resource_start (pdev, 1);
-
-	err = pci_request_region(pdev, 1, "s3d framebuffer");
-	if (err < 0) {
-		printk("s3d: Cannot request region 1 for %s\n",
-		       pci_name(pdev));
-		goto err_release_fb;
-	}
-
-	err = s3d_get_props(sp);
-	if (err)
-		goto err_release_pci;
-
-	/* XXX 'linebytes' is often wrong, it is equal to the width
-	 * XXX with depth of 32 on my XVR-2500 which is clearly not
-	 * XXX right.  So we don't try to use it.
-	 */
-	switch (sp->depth) {
-	case 8:
-		info->fix.line_length = sp->width;
-		break;
-	case 16:
-		info->fix.line_length = sp->width * 2;
-		break;
-	case 24:
-		info->fix.line_length = sp->width * 3;
-		break;
-	case 32:
-		info->fix.line_length = sp->width * 4;
-		break;
-	}
-	sp->fb_size = info->fix.line_length * sp->height;
-
-	sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size);
-	if (!sp->fb_base) {
-		err = -ENOMEM;
-		goto err_release_pci;
-	}
-
-	err = s3d_set_fbinfo(sp);
-	if (err)
-		goto err_unmap_fb;
-
-	pci_set_drvdata(pdev, info);
-
-	printk("s3d: Found device at %s\n", pci_name(pdev));
-
-	err = register_framebuffer(info);
-	if (err < 0) {
-		printk(KERN_ERR "s3d: Could not register framebuffer %s\n",
-		       pci_name(pdev));
-		goto err_unmap_fb;
-	}
-
-	return 0;
-
-err_unmap_fb:
-	iounmap(sp->fb_base);
-
-err_release_pci:
-	pci_release_region(pdev, 1);
-
-err_release_fb:
-        framebuffer_release(info);
-
-err_disable:
-	pci_disable_device(pdev);
-
-err_out:
-	return err;
-}
-
-static void s3d_pci_unregister(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct s3d_info *sp = info->par;
-
-	unregister_framebuffer(info);
-
-	iounmap(sp->fb_base);
-
-	pci_release_region(pdev, 1);
-
-        framebuffer_release(info);
-
-	pci_disable_device(pdev);
-}
-
-static struct pci_device_id s3d_pci_table[] = {
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002c),	},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002d),	},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002e),	},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002f),	},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0030),	},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0031),	},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0032),	},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0033),	},
-	{ 0, }
-};
-
-static struct pci_driver s3d_driver = {
-	.name		= "s3d",
-	.id_table	= s3d_pci_table,
-	.probe		= s3d_pci_register,
-	.remove		= s3d_pci_unregister,
-};
-
-static int __init s3d_init(void)
-{
-	if (fb_get_options("s3d", NULL))
-		return -ENODEV;
-
-	return pci_register_driver(&s3d_driver);
-}
-
-static void __exit s3d_exit(void)
-{
-	pci_unregister_driver(&s3d_driver);
-}
-
-module_init(s3d_init);
-module_exit(s3d_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for Sun XVR-2500 graphics");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c
deleted file mode 100644
index 387350d004df..000000000000
--- a/drivers/video/sunxvr500.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/* sunxvr500.c: Sun 3DLABS XVR-500 Expert3D driver for sparc64 systems
- *
- * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-
-/* XXX This device has a 'dev-comm' property which apparently is
- * XXX a pointer into the openfirmware's address space which is
- * XXX a shared area the kernel driver can use to keep OBP
- * XXX informed about the current resolution setting.  The idea
- * XXX is that the kernel can change resolutions, and as long
- * XXX as the values in the 'dev-comm' area are accurate then
- * XXX OBP can still render text properly to the console.
- * XXX
- * XXX I'm still working out the layout of this and whether there
- * XXX are any signatures we need to look for etc.
- */
-struct e3d_info {
-	struct fb_info		*info;
-	struct pci_dev		*pdev;
-
-	spinlock_t		lock;
-
-	char __iomem		*fb_base;
-	unsigned long		fb_base_phys;
-
-	unsigned long		fb8_buf_diff;
-	unsigned long		regs_base_phys;
-
-	void __iomem		*ramdac;
-
-	struct device_node	*of_node;
-
-	unsigned int		width;
-	unsigned int		height;
-	unsigned int		depth;
-	unsigned int		fb_size;
-
-	u32			fb_base_reg;
-	u32			fb8_0_off;
-	u32			fb8_1_off;
-
-	u32			pseudo_palette[16];
-};
-
-static int e3d_get_props(struct e3d_info *ep)
-{
-	ep->width = of_getintprop_default(ep->of_node, "width", 0);
-	ep->height = of_getintprop_default(ep->of_node, "height", 0);
-	ep->depth = of_getintprop_default(ep->of_node, "depth", 8);
-
-	if (!ep->width || !ep->height) {
-		printk(KERN_ERR "e3d: Critical properties missing for %s\n",
-		       pci_name(ep->pdev));
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* My XVR-500 comes up, at 1280x768 and a FB base register value of
- * 0x04000000, the following video layout register values:
- *
- * RAMDAC_VID_WH	0x03ff04ff
- * RAMDAC_VID_CFG	0x1a0b0088
- * RAMDAC_VID_32FB_0	0x04000000
- * RAMDAC_VID_32FB_1	0x04800000
- * RAMDAC_VID_8FB_0	0x05000000
- * RAMDAC_VID_8FB_1	0x05200000
- * RAMDAC_VID_XXXFB	0x05400000
- * RAMDAC_VID_YYYFB	0x05c00000
- * RAMDAC_VID_ZZZFB	0x05e00000
- */
-/* Video layout registers */
-#define RAMDAC_VID_WH		0x00000070UL /* (height-1)<<16 | (width-1) */
-#define RAMDAC_VID_CFG		0x00000074UL /* 0x1a000088|(linesz_log2<<16) */
-#define RAMDAC_VID_32FB_0	0x00000078UL /* PCI base 32bpp FB buffer 0 */
-#define RAMDAC_VID_32FB_1	0x0000007cUL /* PCI base 32bpp FB buffer 1 */
-#define RAMDAC_VID_8FB_0	0x00000080UL /* PCI base 8bpp FB buffer 0 */
-#define RAMDAC_VID_8FB_1	0x00000084UL /* PCI base 8bpp FB buffer 1 */
-#define RAMDAC_VID_XXXFB	0x00000088UL /* PCI base of XXX FB */
-#define RAMDAC_VID_YYYFB	0x0000008cUL /* PCI base of YYY FB */
-#define RAMDAC_VID_ZZZFB	0x00000090UL /* PCI base of ZZZ FB */
-
-/* CLUT registers */
-#define RAMDAC_INDEX		0x000000bcUL
-#define RAMDAC_DATA		0x000000c0UL
-
-static void e3d_clut_write(struct e3d_info *ep, int index, u32 val)
-{
-	void __iomem *ramdac = ep->ramdac;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ep->lock, flags);
-
-	writel(index, ramdac + RAMDAC_INDEX);
-	writel(val, ramdac + RAMDAC_DATA);
-
-	spin_unlock_irqrestore(&ep->lock, flags);
-}
-
-static int e3d_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	struct e3d_info *ep = info->par;
-	u32 red_8, green_8, blue_8;
-	u32 red_10, green_10, blue_10;
-	u32 value;
-
-	if (regno >= 256)
-		return 1;
-
-	red_8 = red >> 8;
-	green_8 = green >> 8;
-	blue_8 = blue >> 8;
-
-	value = (blue_8 << 24) | (green_8 << 16) | (red_8 << 8);
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16)
-		((u32 *)info->pseudo_palette)[regno] = value;
-
-
-	red_10 = red >> 6;
-	green_10 = green >> 6;
-	blue_10 = blue >> 6;
-
-	value = (blue_10 << 20) | (green_10 << 10) | (red_10 << 0);
-	e3d_clut_write(ep, regno, value);
-
-	return 0;
-}
-
-/* XXX This is a bit of a hack.  I can't figure out exactly how the
- * XXX two 8bpp areas of the framebuffer work.  I imagine there is
- * XXX a WID attribute somewhere else in the framebuffer which tells
- * XXX the ramdac which of the two 8bpp framebuffer regions to take
- * XXX the pixel from.  So, for now, render into both regions to make
- * XXX sure the pixel shows up.
- */
-static void e3d_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct e3d_info *ep = info->par;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ep->lock, flags);
-	cfb_imageblit(info, image);
-	info->screen_base += ep->fb8_buf_diff;
-	cfb_imageblit(info, image);
-	info->screen_base -= ep->fb8_buf_diff;
-	spin_unlock_irqrestore(&ep->lock, flags);
-}
-
-static void e3d_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct e3d_info *ep = info->par;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ep->lock, flags);
-	cfb_fillrect(info, rect);
-	info->screen_base += ep->fb8_buf_diff;
-	cfb_fillrect(info, rect);
-	info->screen_base -= ep->fb8_buf_diff;
-	spin_unlock_irqrestore(&ep->lock, flags);
-}
-
-static void e3d_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct e3d_info *ep = info->par;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ep->lock, flags);
-	cfb_copyarea(info, area);
-	info->screen_base += ep->fb8_buf_diff;
-	cfb_copyarea(info, area);
-	info->screen_base -= ep->fb8_buf_diff;
-	spin_unlock_irqrestore(&ep->lock, flags);
-}
-
-static struct fb_ops e3d_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= e3d_setcolreg,
-	.fb_fillrect		= e3d_fillrect,
-	.fb_copyarea		= e3d_copyarea,
-	.fb_imageblit		= e3d_imageblit,
-};
-
-static int e3d_set_fbinfo(struct e3d_info *ep)
-{
-	struct fb_info *info = ep->info;
-	struct fb_var_screeninfo *var = &info->var;
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &e3d_ops;
-	info->screen_base = ep->fb_base;
-	info->screen_size = ep->fb_size;
-
-	info->pseudo_palette = ep->pseudo_palette;
-
-	/* Fill fix common fields */
-	strlcpy(info->fix.id, "e3d", sizeof(info->fix.id));
-        info->fix.smem_start = ep->fb_base_phys;
-        info->fix.smem_len = ep->fb_size;
-        info->fix.type = FB_TYPE_PACKED_PIXELS;
-	if (ep->depth == 32 || ep->depth == 24)
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-	else
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	var->xres = ep->width;
-	var->yres = ep->height;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-	var->bits_per_pixel = ep->depth;
-
-	var->red.offset = 8;
-	var->red.length = 8;
-	var->green.offset = 16;
-	var->green.length = 8;
-	var->blue.offset = 24;
-	var->blue.length = 8;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
-		printk(KERN_ERR "e3d: Cannot allocate color map.\n");
-		return -ENOMEM;
-	}
-
-        return 0;
-}
-
-static int e3d_pci_register(struct pci_dev *pdev,
-			    const struct pci_device_id *ent)
-{
-	struct device_node *of_node;
-	const char *device_type;
-	struct fb_info *info;
-	struct e3d_info *ep;
-	unsigned int line_length;
-	int err;
-
-	of_node = pci_device_to_OF_node(pdev);
-	if (!of_node) {
-		printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
-		       pci_name(pdev));
-		return -ENODEV;
-	}
-
-	device_type = of_get_property(of_node, "device_type", NULL);
-	if (!device_type) {
-		printk(KERN_INFO "e3d: Ignoring secondary output device "
-		       "at %s\n", pci_name(pdev));
-		return -ENODEV;
-	}
-
-	err = pci_enable_device(pdev);
-	if (err < 0) {
-		printk(KERN_ERR "e3d: Cannot enable PCI device %s\n",
-		       pci_name(pdev));
-		goto err_out;
-	}
-
-	info = framebuffer_alloc(sizeof(struct e3d_info), &pdev->dev);
-	if (!info) {
-		printk(KERN_ERR "e3d: Cannot allocate fb_info\n");
-		err = -ENOMEM;
-		goto err_disable;
-	}
-
-	ep = info->par;
-	ep->info = info;
-	ep->pdev = pdev;
-	spin_lock_init(&ep->lock);
-	ep->of_node = of_node;
-
-	/* Read the PCI base register of the frame buffer, which we
-	 * need in order to interpret the RAMDAC_VID_*FB* values in
-	 * the ramdac correctly.
-	 */
-	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
-			      &ep->fb_base_reg);
-	ep->fb_base_reg &= PCI_BASE_ADDRESS_MEM_MASK;
-
-	ep->regs_base_phys = pci_resource_start (pdev, 1);
-	err = pci_request_region(pdev, 1, "e3d regs");
-	if (err < 0) {
-		printk("e3d: Cannot request region 1 for %s\n",
-		       pci_name(pdev));
-		goto err_release_fb;
-	}
-	ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000);
-	if (!ep->ramdac) {
-		err = -ENOMEM;
-		goto err_release_pci1;
-	}
-
-	ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);
-	ep->fb8_0_off -= ep->fb_base_reg;
-
-	ep->fb8_1_off = readl(ep->ramdac + RAMDAC_VID_8FB_1);
-	ep->fb8_1_off -= ep->fb_base_reg;
-
-	ep->fb8_buf_diff = ep->fb8_1_off - ep->fb8_0_off;
-
-	ep->fb_base_phys = pci_resource_start (pdev, 0);
-	ep->fb_base_phys += ep->fb8_0_off;
-
-	err = pci_request_region(pdev, 0, "e3d framebuffer");
-	if (err < 0) {
-		printk("e3d: Cannot request region 0 for %s\n",
-		       pci_name(pdev));
-		goto err_unmap_ramdac;
-	}
-
-	err = e3d_get_props(ep);
-	if (err)
-		goto err_release_pci0;
-
-	line_length = (readl(ep->ramdac + RAMDAC_VID_CFG) >> 16) & 0xff;
-	line_length = 1 << line_length;
-
-	switch (ep->depth) {
-	case 8:
-		info->fix.line_length = line_length;
-		break;
-	case 16:
-		info->fix.line_length = line_length * 2;
-		break;
-	case 24:
-		info->fix.line_length = line_length * 3;
-		break;
-	case 32:
-		info->fix.line_length = line_length * 4;
-		break;
-	}
-	ep->fb_size = info->fix.line_length * ep->height;
-
-	ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size);
-	if (!ep->fb_base) {
-		err = -ENOMEM;
-		goto err_release_pci0;
-	}
-
-	err = e3d_set_fbinfo(ep);
-	if (err)
-		goto err_unmap_fb;
-
-	pci_set_drvdata(pdev, info);
-
-	printk("e3d: Found device at %s\n", pci_name(pdev));
-
-	err = register_framebuffer(info);
-	if (err < 0) {
-		printk(KERN_ERR "e3d: Could not register framebuffer %s\n",
-		       pci_name(pdev));
-		goto err_free_cmap;
-	}
-
-	return 0;
-
-err_free_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-err_unmap_fb:
-	iounmap(ep->fb_base);
-
-err_release_pci0:
-	pci_release_region(pdev, 0);
-
-err_unmap_ramdac:
-	iounmap(ep->ramdac);
-
-err_release_pci1:
-	pci_release_region(pdev, 1);
-
-err_release_fb:
-        framebuffer_release(info);
-
-err_disable:
-	pci_disable_device(pdev);
-
-err_out:
-	return err;
-}
-
-static void e3d_pci_unregister(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct e3d_info *ep = info->par;
-
-	unregister_framebuffer(info);
-
-	iounmap(ep->ramdac);
-	iounmap(ep->fb_base);
-
-	pci_release_region(pdev, 0);
-	pci_release_region(pdev, 1);
-
-	fb_dealloc_cmap(&info->cmap);
-        framebuffer_release(info);
-
-	pci_disable_device(pdev);
-}
-
-static struct pci_device_id e3d_pci_table[] = {
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a0),	},
-	{	PCI_DEVICE(0x1091, 0x7a0),			},
-	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a2),	},
-	{	.vendor = PCI_VENDOR_ID_3DLABS,
-		.device = PCI_ANY_ID,
-		.subvendor = PCI_VENDOR_ID_3DLABS,
-		.subdevice = 0x0108,
-	},
-	{	.vendor = PCI_VENDOR_ID_3DLABS,
-		.device = PCI_ANY_ID,
-		.subvendor = PCI_VENDOR_ID_3DLABS,
-		.subdevice = 0x0140,
-	},
-	{	.vendor = PCI_VENDOR_ID_3DLABS,
-		.device = PCI_ANY_ID,
-		.subvendor = PCI_VENDOR_ID_3DLABS,
-		.subdevice = 0x1024,
-	},
-	{ 0, }
-};
-
-static struct pci_driver e3d_driver = {
-	.name		= "e3d",
-	.id_table	= e3d_pci_table,
-	.probe		= e3d_pci_register,
-	.remove		= e3d_pci_unregister,
-};
-
-static int __init e3d_init(void)
-{
-	if (fb_get_options("e3d", NULL))
-		return -ENODEV;
-
-	return pci_register_driver(&e3d_driver);
-}
-
-static void __exit e3d_exit(void)
-{
-	pci_unregister_driver(&e3d_driver);
-}
-
-module_init(e3d_init);
-module_exit(e3d_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for Sun XVR-500 graphics");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c
deleted file mode 100644
index 9e01322fabe3..000000000000
--- a/drivers/video/svgalib.c
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Common utility functions for VGA-based graphics cards.
- *
- * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Some parts are based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <linux/svga.h>
-#include <asm/types.h>
-#include <asm/io.h>
-
-
-/* Write a CRT register value spread across multiple registers */
-void svga_wcrt_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value)
-{
-	u8 regval, bitval, bitnum;
-
-	while (regset->regnum != VGA_REGSET_END_VAL) {
-		regval = vga_rcrt(regbase, regset->regnum);
-		bitnum = regset->lowbit;
-		while (bitnum <= regset->highbit) {
-			bitval = 1 << bitnum;
-			regval = regval & ~bitval;
-			if (value & 1) regval = regval | bitval;
-			bitnum ++;
-			value = value >> 1;
-		}
-		vga_wcrt(regbase, regset->regnum, regval);
-		regset ++;
-	}
-}
-
-/* Write a sequencer register value spread across multiple registers */
-void svga_wseq_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value)
-{
-	u8 regval, bitval, bitnum;
-
-	while (regset->regnum != VGA_REGSET_END_VAL) {
-		regval = vga_rseq(regbase, regset->regnum);
-		bitnum = regset->lowbit;
-		while (bitnum <= regset->highbit) {
-			bitval = 1 << bitnum;
-			regval = regval & ~bitval;
-			if (value & 1) regval = regval | bitval;
-			bitnum ++;
-			value = value >> 1;
-		}
-		vga_wseq(regbase, regset->regnum, regval);
-		regset ++;
-	}
-}
-
-static unsigned int svga_regset_size(const struct vga_regset *regset)
-{
-	u8 count = 0;
-
-	while (regset->regnum != VGA_REGSET_END_VAL) {
-		count += regset->highbit - regset->lowbit + 1;
-		regset ++;
-	}
-	return 1 << count;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* Set graphics controller registers to sane values */
-void svga_set_default_gfx_regs(void __iomem *regbase)
-{
-	/* All standard GFX registers (GR00 - GR08) */
-	vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0x00);
-	vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0x00);
-	vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0x00);
-	vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0x00);
-	vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0x00);
-	vga_wgfx(regbase, VGA_GFX_MODE, 0x00);
-/*	vga_wgfx(regbase, VGA_GFX_MODE, 0x20); */
-/*	vga_wgfx(regbase, VGA_GFX_MODE, 0x40); */
-	vga_wgfx(regbase, VGA_GFX_MISC, 0x05);
-/*	vga_wgfx(regbase, VGA_GFX_MISC, 0x01); */
-	vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x0F);
-	vga_wgfx(regbase, VGA_GFX_BIT_MASK, 0xFF);
-}
-
-/* Set attribute controller registers to sane values */
-void svga_set_default_atc_regs(void __iomem *regbase)
-{
-	u8 count;
-
-	vga_r(regbase, 0x3DA);
-	vga_w(regbase, VGA_ATT_W, 0x00);
-
-	/* All standard ATC registers (AR00 - AR14) */
-	for (count = 0; count <= 0xF; count ++)
-		svga_wattr(regbase, count, count);
-
-	svga_wattr(regbase, VGA_ATC_MODE, 0x01);
-/*	svga_wattr(regbase, VGA_ATC_MODE, 0x41); */
-	svga_wattr(regbase, VGA_ATC_OVERSCAN, 0x00);
-	svga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 0x0F);
-	svga_wattr(regbase, VGA_ATC_PEL, 0x00);
-	svga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0x00);
-
-	vga_r(regbase, 0x3DA);
-	vga_w(regbase, VGA_ATT_W, 0x20);
-}
-
-/* Set sequencer registers to sane values */
-void svga_set_default_seq_regs(void __iomem *regbase)
-{
-	/* Standard sequencer registers (SR01 - SR04), SR00 is not set */
-	vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS);
-	vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES);
-	vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
-/*	vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */
-	vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE);
-}
-
-/* Set CRTC registers to sane values */
-void svga_set_default_crt_regs(void __iomem *regbase)
-{
-	/* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */
-	svga_wcrt_mask(regbase, 0x03, 0x80, 0x80);	/* Enable vertical retrace EVRA */
-	vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
-	svga_wcrt_mask(regbase, VGA_CRTC_MAX_SCAN, 0, 0x1F);
-	vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
-	vga_wcrt(regbase, VGA_CRTC_MODE, 0xE3);
-}
-
-void svga_set_textmode_vga_regs(void __iomem *regbase)
-{
-	/* svga_wseq_mask(regbase, 0x1, 0x00, 0x01); */   /* Switch 8/9 pixel per char */
-	vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM);
-	vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x03);
-
-	vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, 0x0f); /* 0x4f */
-	vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0x1f);
-	svga_wcrt_mask(regbase, VGA_CRTC_MODE, 0x23, 0x7f);
-
-	vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0x0d);
-	vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 0x0e);
-	vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0x00);
-	vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0x00);
-
-	vga_wgfx(regbase, VGA_GFX_MODE, 0x10); /* Odd/even memory mode */
-	vga_wgfx(regbase, VGA_GFX_MISC, 0x0E); /* Misc graphics register - text mode enable */
-	vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x00);
-
-	vga_r(regbase, 0x3DA);
-	vga_w(regbase, VGA_ATT_W, 0x00);
-
-	svga_wattr(regbase, 0x10, 0x0C);			/* Attribute Mode Control Register - text mode, blinking and line graphics */
-	svga_wattr(regbase, 0x13, 0x08);			/* Horizontal Pixel Panning Register  */
-
-	vga_r(regbase, 0x3DA);
-	vga_w(regbase, VGA_ATT_W, 0x20);
-}
-
-#if 0
-void svga_dump_var(struct fb_var_screeninfo *var, int node)
-{
-	pr_debug("fb%d: var.vmode         : 0x%X\n", node, var->vmode);
-	pr_debug("fb%d: var.xres          : %d\n", node, var->xres);
-	pr_debug("fb%d: var.yres          : %d\n", node, var->yres);
-	pr_debug("fb%d: var.bits_per_pixel: %d\n", node, var->bits_per_pixel);
-	pr_debug("fb%d: var.xres_virtual  : %d\n", node, var->xres_virtual);
-	pr_debug("fb%d: var.yres_virtual  : %d\n", node, var->yres_virtual);
-	pr_debug("fb%d: var.left_margin   : %d\n", node, var->left_margin);
-	pr_debug("fb%d: var.right_margin  : %d\n", node, var->right_margin);
-	pr_debug("fb%d: var.upper_margin  : %d\n", node, var->upper_margin);
-	pr_debug("fb%d: var.lower_margin  : %d\n", node, var->lower_margin);
-	pr_debug("fb%d: var.hsync_len     : %d\n", node, var->hsync_len);
-	pr_debug("fb%d: var.vsync_len     : %d\n", node, var->vsync_len);
-	pr_debug("fb%d: var.sync          : 0x%X\n", node, var->sync);
-	pr_debug("fb%d: var.pixclock      : %d\n\n", node, var->pixclock);
-}
-#endif  /*  0  */
-
-
-/* ------------------------------------------------------------------------- */
-
-
-void svga_settile(struct fb_info *info, struct fb_tilemap *map)
-{
-	const u8 *font = map->data;
-	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
-	int i, c;
-
-	if ((map->width != 8) || (map->height != 16) ||
-	    (map->depth != 1) || (map->length != 256)) {
-		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
-		       map->width, map->height, map->depth, map->length);
-		return;
-	}
-
-	fb += 2;
-	for (c = 0; c < map->length; c++) {
-		for (i = 0; i < map->height; i++) {
-			fb_writeb(font[i], fb + i * 4);
-//			fb[i * 4] = font[i];
-		}
-		fb += 128;
-		font += map->height;
-	}
-}
-
-/* Copy area in text (tileblit) mode */
-void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area)
-{
-	int dx, dy;
-	/*  colstride is halved in this function because u16 are used */
-	int colstride = 1 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
-	int rowstride = colstride * (info->var.xres_virtual / 8);
-	u16 __iomem *fb = (u16 __iomem *) info->screen_base;
-	u16 __iomem *src, *dst;
-
-	if ((area->sy > area->dy) ||
-	    ((area->sy == area->dy) && (area->sx > area->dx))) {
-		src = fb + area->sx * colstride + area->sy * rowstride;
-		dst = fb + area->dx * colstride + area->dy * rowstride;
-	    } else {
-		src = fb + (area->sx + area->width - 1) * colstride
-			 + (area->sy + area->height - 1) * rowstride;
-		dst = fb + (area->dx + area->width - 1) * colstride
-			 + (area->dy + area->height - 1) * rowstride;
-
-		colstride = -colstride;
-		rowstride = -rowstride;
-	    }
-
-	for (dy = 0; dy < area->height; dy++) {
-		u16 __iomem *src2 = src;
-		u16 __iomem *dst2 = dst;
-		for (dx = 0; dx < area->width; dx++) {
-			fb_writew(fb_readw(src2), dst2);
-//			*dst2 = *src2;
-			src2 += colstride;
-			dst2 += colstride;
-		}
-		src += rowstride;
-		dst += rowstride;
-	}
-}
-
-/* Fill area in text (tileblit) mode */
-void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect)
-{
-	int dx, dy;
-	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
-	int rowstride = colstride * (info->var.xres_virtual / 8);
-	int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg);
-	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
-	fb += rect->sx * colstride + rect->sy * rowstride;
-
-	for (dy = 0; dy < rect->height; dy++) {
-		u8 __iomem *fb2 = fb;
-		for (dx = 0; dx < rect->width; dx++) {
-			fb_writeb(rect->index, fb2);
-			fb_writeb(attr, fb2 + 1);
-			fb2 += colstride;
-		}
-		fb += rowstride;
-	}
-}
-
-/* Write text in text (tileblit) mode */
-void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit)
-{
-	int dx, dy, i;
-	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
-	int rowstride = colstride * (info->var.xres_virtual / 8);
-	int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg);
-	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
-	fb += blit->sx * colstride + blit->sy * rowstride;
-
-	i=0;
-	for (dy=0; dy < blit->height; dy ++) {
-		u8 __iomem *fb2 = fb;
-		for (dx = 0; dx < blit->width; dx ++) {
-			fb_writeb(blit->indices[i], fb2);
-			fb_writeb(attr, fb2 + 1);
-			fb2 += colstride;
-			i ++;
-			if (i == blit->length) return;
-		}
-		fb += rowstride;
-	}
-
-}
-
-/* Set cursor in text (tileblit) mode */
-void svga_tilecursor(void __iomem *regbase, struct fb_info *info, struct fb_tilecursor *cursor)
-{
-	u8 cs = 0x0d;
-	u8 ce = 0x0e;
-	u16 pos =  cursor->sx + (info->var.xoffset /  8)
-		+ (cursor->sy + (info->var.yoffset / 16))
-		   * (info->var.xres_virtual / 8);
-
-	if (! cursor -> mode)
-		return;
-
-	svga_wcrt_mask(regbase, 0x0A, 0x20, 0x20); /* disable cursor */
-
-	if (cursor -> shape == FB_TILE_CURSOR_NONE)
-		return;
-
-	switch (cursor -> shape) {
-	case FB_TILE_CURSOR_UNDERLINE:
-		cs = 0x0d;
-		break;
-	case FB_TILE_CURSOR_LOWER_THIRD:
-		cs = 0x09;
-		break;
-	case FB_TILE_CURSOR_LOWER_HALF:
-		cs = 0x07;
-		break;
-	case FB_TILE_CURSOR_TWO_THIRDS:
-		cs = 0x05;
-		break;
-	case FB_TILE_CURSOR_BLOCK:
-		cs = 0x01;
-		break;
-	}
-
-	/* set cursor position */
-	vga_wcrt(regbase, 0x0E, pos >> 8);
-	vga_wcrt(regbase, 0x0F, pos & 0xFF);
-
-	vga_wcrt(regbase, 0x0B, ce); /* set cursor end */
-	vga_wcrt(regbase, 0x0A, cs); /* set cursor start and enable it */
-}
-
-int svga_get_tilemax(struct fb_info *info)
-{
-	return 256;
-}
-
-/* Get capabilities of accelerator based on the mode */
-
-void svga_get_caps(struct fb_info *info, struct fb_blit_caps *caps,
-		   struct fb_var_screeninfo *var)
-{
-	if (var->bits_per_pixel == 0) {
-		/* can only support 256 8x16 bitmap */
-		caps->x = 1 << (8 - 1);
-		caps->y = 1 << (16 - 1);
-		caps->len = 256;
-	} else {
-		caps->x = (var->bits_per_pixel == 4) ? 1 << (8 - 1) : ~(u32)0;
-		caps->y = ~(u32)0;
-		caps->len = ~(u32)0;
-	}
-}
-EXPORT_SYMBOL(svga_get_caps);
-
-/* ------------------------------------------------------------------------- */
-
-
-/*
- *  Compute PLL settings (M, N, R)
- *  F_VCO = (F_BASE * M) / N
- *  F_OUT = F_VCO / (2^R)
- */
-
-static inline u32 abs_diff(u32 a, u32 b)
-{
-	return (a > b) ? (a - b) : (b - a);
-}
-
-int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node)
-{
-	u16 am, an, ar;
-	u32 f_vco, f_current, delta_current, delta_best;
-
-	pr_debug("fb%d: ideal frequency: %d kHz\n", node, (unsigned int) f_wanted);
-
-	ar = pll->r_max;
-	f_vco = f_wanted << ar;
-
-	/* overflow check */
-	if ((f_vco >> ar) != f_wanted)
-		return -EINVAL;
-
-	/* It is usually better to have greater VCO clock
-	   because of better frequency stability.
-	   So first try r_max, then r smaller. */
-	while ((ar > pll->r_min) && (f_vco > pll->f_vco_max)) {
-		ar--;
-		f_vco = f_vco >> 1;
-	}
-
-	/* VCO bounds check */
-	if ((f_vco < pll->f_vco_min) || (f_vco > pll->f_vco_max))
-		return -EINVAL;
-
-	delta_best = 0xFFFFFFFF;
-	*m = 0;
-	*n = 0;
-	*r = ar;
-
-	am = pll->m_min;
-	an = pll->n_min;
-
-	while ((am <= pll->m_max) && (an <= pll->n_max)) {
-		f_current = (pll->f_base * am) / an;
-		delta_current = abs_diff (f_current, f_vco);
-
-		if (delta_current < delta_best) {
-			delta_best = delta_current;
-			*m = am;
-			*n = an;
-		}
-
-		if (f_current <= f_vco) {
-			am ++;
-		} else {
-			an ++;
-		}
-	}
-
-	f_current = (pll->f_base * *m) / *n;
-	pr_debug("fb%d: found frequency: %d kHz (VCO %d kHz)\n", node, (int) (f_current >> ar), (int) f_current);
-	pr_debug("fb%d: m = %d n = %d r = %d\n", node, (unsigned int) *m, (unsigned int) *n, (unsigned int) *r);
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* Check CRT timing values */
-int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node)
-{
-	u32 value;
-
-	var->xres         = (var->xres+7)&~7;
-	var->left_margin  = (var->left_margin+7)&~7;
-	var->right_margin = (var->right_margin+7)&~7;
-	var->hsync_len    = (var->hsync_len+7)&~7;
-
-	/* Check horizontal total */
-	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
-	if (((value / 8) - 5) >= svga_regset_size (tm->h_total_regs))
-		return -EINVAL;
-
-	/* Check horizontal display and blank start */
-	value = var->xres;
-	if (((value / 8) - 1) >= svga_regset_size (tm->h_display_regs))
-		return -EINVAL;
-	if (((value / 8) - 1) >= svga_regset_size (tm->h_blank_start_regs))
-		return -EINVAL;
-
-	/* Check horizontal sync start */
-	value = var->xres + var->right_margin;
-	if (((value / 8) - 1) >= svga_regset_size (tm->h_sync_start_regs))
-		return -EINVAL;
-
-	/* Check horizontal blank end (or length) */
-	value = var->left_margin + var->right_margin + var->hsync_len;
-	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_blank_end_regs)))
-		return -EINVAL;
-
-	/* Check horizontal sync end (or length) */
-	value = var->hsync_len;
-	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_sync_end_regs)))
-		return -EINVAL;
-
-	/* Check vertical total */
-	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
-	if ((value - 1) >= svga_regset_size(tm->v_total_regs))
-		return -EINVAL;
-
-	/* Check vertical display and blank start */
-	value = var->yres;
-	if ((value - 1) >= svga_regset_size(tm->v_display_regs))
-		return -EINVAL;
-	if ((value - 1) >= svga_regset_size(tm->v_blank_start_regs))
-		return -EINVAL;
-
-	/* Check vertical sync start */
-	value = var->yres + var->lower_margin;
-	if ((value - 1) >= svga_regset_size(tm->v_sync_start_regs))
-		return -EINVAL;
-
-	/* Check vertical blank end (or length) */
-	value = var->upper_margin + var->lower_margin + var->vsync_len;
-	if ((value == 0) || (value >= svga_regset_size (tm->v_blank_end_regs)))
-		return -EINVAL;
-
-	/* Check vertical sync end  (or length) */
-	value = var->vsync_len;
-	if ((value == 0) || (value >= svga_regset_size (tm->v_sync_end_regs)))
-		return -EINVAL;
-
-	return 0;
-}
-
-/* Set CRT timing registers */
-void svga_set_timings(void __iomem *regbase, const struct svga_timing_regs *tm,
-		      struct fb_var_screeninfo *var,
-		      u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node)
-{
-	u8 regval;
-	u32 value;
-
-	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
-	value = (value * hmul) / hdiv;
-	pr_debug("fb%d: horizontal total      : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->h_total_regs, (value / 8) - 5);
-
-	value = var->xres;
-	value = (value * hmul) / hdiv;
-	pr_debug("fb%d: horizontal display    : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->h_display_regs, (value / 8) - 1);
-
-	value = var->xres;
-	value = (value * hmul) / hdiv;
-	pr_debug("fb%d: horizontal blank start: %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->h_blank_start_regs, (value / 8) - 1 + hborder);
-
-	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
-	value = (value * hmul) / hdiv;
-	pr_debug("fb%d: horizontal blank end  : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->h_blank_end_regs, (value / 8) - 1 - hborder);
-
-	value = var->xres + var->right_margin;
-	value = (value * hmul) / hdiv;
-	pr_debug("fb%d: horizontal sync start : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->h_sync_start_regs, (value / 8));
-
-	value = var->xres + var->right_margin + var->hsync_len;
-	value = (value * hmul) / hdiv;
-	pr_debug("fb%d: horizontal sync end   : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->h_sync_end_regs, (value / 8));
-
-	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
-	value = (value * vmul) / vdiv;
-	pr_debug("fb%d: vertical total        : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->v_total_regs, value - 2);
-
-	value = var->yres;
-	value = (value * vmul) / vdiv;
-	pr_debug("fb%d: vertical display      : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->v_display_regs, value - 1);
-
-	value = var->yres;
-	value = (value * vmul) / vdiv;
-	pr_debug("fb%d: vertical blank start  : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->v_blank_start_regs, value);
-
-	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
-	value = (value * vmul) / vdiv;
-	pr_debug("fb%d: vertical blank end    : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->v_blank_end_regs, value - 2);
-
-	value = var->yres + var->lower_margin;
-	value = (value * vmul) / vdiv;
-	pr_debug("fb%d: vertical sync start   : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->v_sync_start_regs, value);
-
-	value = var->yres + var->lower_margin + var->vsync_len;
-	value = (value * vmul) / vdiv;
-	pr_debug("fb%d: vertical sync end     : %d\n", node, value);
-	svga_wcrt_multi(regbase, tm->v_sync_end_regs, value);
-
-	/* Set horizontal and vertical sync pulse polarity in misc register */
-
-	regval = vga_r(regbase, VGA_MIS_R);
-	if (var->sync & FB_SYNC_HOR_HIGH_ACT) {
-		pr_debug("fb%d: positive horizontal sync\n", node);
-		regval = regval & ~0x80;
-	} else {
-		pr_debug("fb%d: negative horizontal sync\n", node);
-		regval = regval | 0x80;
-	}
-	if (var->sync & FB_SYNC_VERT_HIGH_ACT) {
-		pr_debug("fb%d: positive vertical sync\n", node);
-		regval = regval & ~0x40;
-	} else {
-		pr_debug("fb%d: negative vertical sync\n\n", node);
-		regval = regval | 0x40;
-	}
-	vga_w(regbase, VGA_MIS_W, regval);
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-static inline int match_format(const struct svga_fb_format *frm,
-			       struct fb_var_screeninfo *var)
-{
-	int i = 0;
-	int stored = -EINVAL;
-
-	while (frm->bits_per_pixel != SVGA_FORMAT_END_VAL)
-	{
-		if ((var->bits_per_pixel == frm->bits_per_pixel) &&
-		    (var->red.length     <= frm->red.length)     &&
-		    (var->green.length   <= frm->green.length)   &&
-		    (var->blue.length    <= frm->blue.length)    &&
-		    (var->transp.length  <= frm->transp.length)  &&
-		    (var->nonstd	 == frm->nonstd))
-			return i;
-		if (var->bits_per_pixel == frm->bits_per_pixel)
-			stored = i;
-		i++;
-		frm++;
-	}
-	return stored;
-}
-
-int svga_match_format(const struct svga_fb_format *frm,
-		      struct fb_var_screeninfo *var,
-		      struct fb_fix_screeninfo *fix)
-{
-	int i = match_format(frm, var);
-
-	if (i >= 0) {
-		var->bits_per_pixel = frm[i].bits_per_pixel;
-		var->red            = frm[i].red;
-		var->green          = frm[i].green;
-		var->blue           = frm[i].blue;
-		var->transp         = frm[i].transp;
-		var->nonstd         = frm[i].nonstd;
-		if (fix != NULL) {
-			fix->type      = frm[i].type;
-			fix->type_aux  = frm[i].type_aux;
-			fix->visual    = frm[i].visual;
-			fix->xpanstep  = frm[i].xpanstep;
-		}
-	}
-
-	return i;
-}
-
-
-EXPORT_SYMBOL(svga_wcrt_multi);
-EXPORT_SYMBOL(svga_wseq_multi);
-
-EXPORT_SYMBOL(svga_set_default_gfx_regs);
-EXPORT_SYMBOL(svga_set_default_atc_regs);
-EXPORT_SYMBOL(svga_set_default_seq_regs);
-EXPORT_SYMBOL(svga_set_default_crt_regs);
-EXPORT_SYMBOL(svga_set_textmode_vga_regs);
-
-EXPORT_SYMBOL(svga_settile);
-EXPORT_SYMBOL(svga_tilecopy);
-EXPORT_SYMBOL(svga_tilefill);
-EXPORT_SYMBOL(svga_tileblit);
-EXPORT_SYMBOL(svga_tilecursor);
-EXPORT_SYMBOL(svga_get_tilemax);
-
-EXPORT_SYMBOL(svga_compute_pll);
-EXPORT_SYMBOL(svga_check_timings);
-EXPORT_SYMBOL(svga_set_timings);
-EXPORT_SYMBOL(svga_match_format);
-
-MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>");
-MODULE_DESCRIPTION("Common utility functions for VGA-based graphics cards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/syscopyarea.c b/drivers/video/syscopyarea.c
deleted file mode 100644
index 844a32fd38ed..000000000000
--- a/drivers/video/syscopyarea.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- *  Generic Bit Block Transfer for frame buffers located in system RAM with
- *  packed pixels of any depth.
- *
- *  Based almost entirely from cfbcopyarea.c (which is based almost entirely
- *  on Geert Uytterhoeven's copyarea routine)
- *
- *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <asm/types.h>
-#include <asm/io.h>
-#include "fb_draw.h"
-
-    /*
-     *  Generic bitwise copy algorithm
-     */
-
-static void
-bitcpy(struct fb_info *p, unsigned long *dst, int dst_idx,
-		const unsigned long *src, int src_idx, int bits, unsigned n)
-{
-	unsigned long first, last;
-	int const shift = dst_idx-src_idx;
-	int left, right;
-
-	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
-	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
-
-	if (!shift) {
-		/* Same alignment for source and dest */
-		if (dst_idx+n <= bits) {
-			/* Single word */
-			if (last)
-				first &= last;
-			*dst = comp(*src, *dst, first);
-		} else {
-			/* Multiple destination words */
-			/* Leading bits */
- 			if (first != ~0UL) {
-				*dst = comp(*src, *dst, first);
-				dst++;
-				src++;
-				n -= bits - dst_idx;
-			}
-
-			/* Main chunk */
-			n /= bits;
-			while (n >= 8) {
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				*dst++ = *src++;
-				n -= 8;
-			}
-			while (n--)
-				*dst++ = *src++;
-
-			/* Trailing bits */
-			if (last)
-				*dst = comp(*src, *dst, last);
-		}
-	} else {
-		unsigned long d0, d1;
-		int m;
-
-		/* Different alignment for source and dest */
-		right = shift & (bits - 1);
-		left = -shift & (bits - 1);
-
-		if (dst_idx+n <= bits) {
-			/* Single destination word */
-			if (last)
-				first &= last;
-			if (shift > 0) {
-				/* Single source word */
-				*dst = comp(*src >> right, *dst, first);
-			} else if (src_idx+n <= bits) {
-				/* Single source word */
-				*dst = comp(*src << left, *dst, first);
-			} else {
-				/* 2 source words */
-				d0 = *src++;
-				d1 = *src;
-				*dst = comp(d0 << left | d1 >> right, *dst,
-					    first);
-			}
-		} else {
-			/* Multiple destination words */
-			/** We must always remember the last value read,
-			    because in case SRC and DST overlap bitwise (e.g.
-			    when moving just one pixel in 1bpp), we always
-			    collect one full long for DST and that might
-			    overlap with the current long from SRC. We store
-			    this value in 'd0'. */
-			d0 = *src++;
-			/* Leading bits */
-			if (shift > 0) {
-				/* Single source word */
-				*dst = comp(d0 >> right, *dst, first);
-				dst++;
-				n -= bits - dst_idx;
-			} else {
-				/* 2 source words */
-				d1 = *src++;
-				*dst = comp(d0 << left | *dst >> right, *dst, first);
-				d0 = d1;
-				dst++;
-				n -= bits - dst_idx;
-			}
-
-			/* Main chunk */
-			m = n % bits;
-			n /= bits;
-			while (n >= 4) {
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-				n -= 4;
-			}
-			while (n--) {
-				d1 = *src++;
-				*dst++ = d0 << left | d1 >> right;
-				d0 = d1;
-			}
-
-			/* Trailing bits */
-			if (last) {
-				if (m <= right) {
-					/* Single source word */
-					*dst = comp(d0 << left, *dst, last);
-				} else {
-					/* 2 source words */
- 					d1 = *src;
-					*dst = comp(d0 << left | d1 >> right,
-						    *dst, last);
-				}
-			}
-		}
-	}
-}
-
-    /*
-     *  Generic bitwise copy algorithm, operating backward
-     */
-
-static void
-bitcpy_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
-		const unsigned long *src, int src_idx, int bits, unsigned n)
-{
-	unsigned long first, last;
-	int shift;
-
-	dst += (n-1)/bits;
-	src += (n-1)/bits;
-	if ((n-1) % bits) {
-		dst_idx += (n-1) % bits;
-		dst += dst_idx >> (ffs(bits) - 1);
-		dst_idx &= bits - 1;
-		src_idx += (n-1) % bits;
-		src += src_idx >> (ffs(bits) - 1);
-		src_idx &= bits - 1;
-	}
-
-	shift = dst_idx-src_idx;
-
-	first = FB_SHIFT_LOW(p, ~0UL, bits - 1 - dst_idx);
-	last = ~(FB_SHIFT_LOW(p, ~0UL, bits - 1 - ((dst_idx-n) % bits)));
-
-	if (!shift) {
-		/* Same alignment for source and dest */
-		if ((unsigned long)dst_idx+1 >= n) {
-			/* Single word */
-			if (last)
-				first &= last;
-			*dst = comp(*src, *dst, first);
-		} else {
-			/* Multiple destination words */
-
-			/* Leading bits */
-			if (first != ~0UL) {
-				*dst = comp(*src, *dst, first);
-				dst--;
-				src--;
-				n -= dst_idx+1;
-			}
-
-			/* Main chunk */
-			n /= bits;
-			while (n >= 8) {
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				*dst-- = *src--;
-				n -= 8;
-			}
-			while (n--)
-				*dst-- = *src--;
-			/* Trailing bits */
-			if (last)
-				*dst = comp(*src, *dst, last);
-		}
-	} else {
-		/* Different alignment for source and dest */
-
-		int const left = -shift & (bits-1);
-		int const right = shift & (bits-1);
-
-		if ((unsigned long)dst_idx+1 >= n) {
-			/* Single destination word */
-			if (last)
-				first &= last;
-			if (shift < 0) {
-				/* Single source word */
-				*dst = comp(*src << left, *dst, first);
-			} else if (1+(unsigned long)src_idx >= n) {
-				/* Single source word */
-				*dst = comp(*src >> right, *dst, first);
-			} else {
-				/* 2 source words */
-				*dst = comp(*src >> right | *(src-1) << left,
-					    *dst, first);
-			}
-		} else {
-			/* Multiple destination words */
-			/** We must always remember the last value read,
-			    because in case SRC and DST overlap bitwise (e.g.
-			    when moving just one pixel in 1bpp), we always
-			    collect one full long for DST and that might
-			    overlap with the current long from SRC. We store
-			    this value in 'd0'. */
-			unsigned long d0, d1;
-			int m;
-
-			d0 = *src--;
-			/* Leading bits */
-			if (shift < 0) {
-				/* Single source word */
-				*dst = comp(d0 << left, *dst, first);
-			} else {
-				/* 2 source words */
-				d1 = *src--;
-				*dst = comp(d0 >> right | d1 << left, *dst,
-					    first);
-				d0 = d1;
-			}
-			dst--;
-			n -= dst_idx+1;
-
-			/* Main chunk */
-			m = n % bits;
-			n /= bits;
-			while (n >= 4) {
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-				n -= 4;
-			}
-			while (n--) {
-				d1 = *src--;
-				*dst-- = d0 >> right | d1 << left;
-				d0 = d1;
-			}
-
-			/* Trailing bits */
-			if (last) {
-				if (m <= left) {
-					/* Single source word */
-					*dst = comp(d0 >> right, *dst, last);
-				} else {
-					/* 2 source words */
-					d1 = *src;
-					*dst = comp(d0 >> right | d1 << left,
-						    *dst, last);
-				}
-			}
-		}
-	}
-}
-
-void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area)
-{
-	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
-	u32 height = area->height, width = area->width;
-	unsigned long const bits_per_line = p->fix.line_length*8u;
-	unsigned long *dst = NULL, *src = NULL;
-	int bits = BITS_PER_LONG, bytes = bits >> 3;
-	int dst_idx = 0, src_idx = 0, rev_copy = 0;
-
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	/* if the beginning of the target area might overlap with the end of
-	the source area, be have to copy the area reverse. */
-	if ((dy == sy && dx > sx) || (dy > sy)) {
-		dy += height;
-		sy += height;
-		rev_copy = 1;
-	}
-
-	/* split the base of the framebuffer into a long-aligned address and
-	   the index of the first bit */
-	dst = src = (unsigned long *)((unsigned long)p->screen_base &
-				      ~(bytes-1));
-	dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
-	/* add offset of source and target area */
-	dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
-	src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
-
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-
-	if (rev_copy) {
-		while (height--) {
-			dst_idx -= bits_per_line;
-			src_idx -= bits_per_line;
-			dst += dst_idx >> (ffs(bits) - 1);
-			dst_idx &= (bytes - 1);
-			src += src_idx >> (ffs(bits) - 1);
-			src_idx &= (bytes - 1);
-			bitcpy_rev(p, dst, dst_idx, src, src_idx, bits,
-				width*p->var.bits_per_pixel);
-		}
-	} else {
-		while (height--) {
-			dst += dst_idx >> (ffs(bits) - 1);
-			dst_idx &= (bytes - 1);
-			src += src_idx >> (ffs(bits) - 1);
-			src_idx &= (bytes - 1);
-			bitcpy(p, dst, dst_idx, src, src_idx, bits,
-				width*p->var.bits_per_pixel);
-			dst_idx += bits_per_line;
-			src_idx += bits_per_line;
-		}
-	}
-}
-
-EXPORT_SYMBOL(sys_copyarea);
-
-MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
-MODULE_DESCRIPTION("Generic copyarea (sys-to-sys)");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/sysfillrect.c b/drivers/video/sysfillrect.c
deleted file mode 100644
index 33ee3d34f9d2..000000000000
--- a/drivers/video/sysfillrect.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- *  Generic fillrect for frame buffers in system RAM with packed pixels of
- *  any depth.
- *
- *  Based almost entirely from cfbfillrect.c (which is based almost entirely
- *  on Geert Uytterhoeven's fillrect routine)
- *
- *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <asm/types.h>
-#include "fb_draw.h"
-
-    /*
-     *  Aligned pattern fill using 32/64-bit memory accesses
-     */
-
-static void
-bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx,
-		unsigned long pat, unsigned n, int bits)
-{
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
-	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
-
-	if (dst_idx+n <= bits) {
-		/* Single word */
-		if (last)
-			first &= last;
-		*dst = comp(pat, *dst, first);
-	} else {
-		/* Multiple destination words */
-
-		/* Leading bits */
- 		if (first!= ~0UL) {
-			*dst = comp(pat, *dst, first);
-			dst++;
-			n -= bits - dst_idx;
-		}
-
-		/* Main chunk */
-		n /= bits;
-		while (n >= 8) {
-			*dst++ = pat;
-			*dst++ = pat;
-			*dst++ = pat;
-			*dst++ = pat;
-			*dst++ = pat;
-			*dst++ = pat;
-			*dst++ = pat;
-			*dst++ = pat;
-			n -= 8;
-		}
-		while (n--)
-			*dst++ = pat;
-		/* Trailing bits */
-		if (last)
-			*dst = comp(pat, *dst, last);
-	}
-}
-
-
-    /*
-     *  Unaligned generic pattern fill using 32/64-bit memory accesses
-     *  The pattern must have been expanded to a full 32/64-bit value
-     *  Left/right are the appropriate shifts to convert to the pattern to be
-     *  used for the next 32/64-bit word
-     */
-
-static void
-bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx,
-		  unsigned long pat, int left, int right, unsigned n, int bits)
-{
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
-	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
-
-	if (dst_idx+n <= bits) {
-		/* Single word */
-		if (last)
-			first &= last;
-		*dst = comp(pat, *dst, first);
-	} else {
-		/* Multiple destination words */
-		/* Leading bits */
-		if (first) {
-			*dst = comp(pat, *dst, first);
-			dst++;
-			pat = pat << left | pat >> right;
-			n -= bits - dst_idx;
-		}
-
-		/* Main chunk */
-		n /= bits;
-		while (n >= 4) {
-			*dst++ = pat;
-			pat = pat << left | pat >> right;
-			*dst++ = pat;
-			pat = pat << left | pat >> right;
-			*dst++ = pat;
-			pat = pat << left | pat >> right;
-			*dst++ = pat;
-			pat = pat << left | pat >> right;
-			n -= 4;
-		}
-		while (n--) {
-			*dst++ = pat;
-			pat = pat << left | pat >> right;
-		}
-
-		/* Trailing bits */
-		if (last)
-			*dst = comp(pat, *dst, last);
-	}
-}
-
-    /*
-     *  Aligned pattern invert using 32/64-bit memory accesses
-     */
-static void
-bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
-		    unsigned long pat, unsigned n, int bits)
-{
-	unsigned long val = pat;
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
-	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
-
-	if (dst_idx+n <= bits) {
-		/* Single word */
-		if (last)
-			first &= last;
-		*dst = comp(*dst ^ val, *dst, first);
-	} else {
-		/* Multiple destination words */
-		/* Leading bits */
-		if (first!=0UL) {
-			*dst = comp(*dst ^ val, *dst, first);
-			dst++;
-			n -= bits - dst_idx;
-		}
-
-		/* Main chunk */
-		n /= bits;
-		while (n >= 8) {
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			*dst++ ^= val;
-			n -= 8;
-		}
-		while (n--)
-			*dst++ ^= val;
-		/* Trailing bits */
-		if (last)
-			*dst = comp(*dst ^ val, *dst, last);
-	}
-}
-
-
-    /*
-     *  Unaligned generic pattern invert using 32/64-bit memory accesses
-     *  The pattern must have been expanded to a full 32/64-bit value
-     *  Left/right are the appropriate shifts to convert to the pattern to be
-     *  used for the next 32/64-bit word
-     */
-
-static void
-bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
-		      unsigned long pat, int left, int right, unsigned n,
-		      int bits)
-{
-	unsigned long first, last;
-
-	if (!n)
-		return;
-
-	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
-	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
-
-	if (dst_idx+n <= bits) {
-		/* Single word */
-		if (last)
-			first &= last;
-		*dst = comp(*dst ^ pat, *dst, first);
-	} else {
-		/* Multiple destination words */
-
-		/* Leading bits */
-		if (first != 0UL) {
-			*dst = comp(*dst ^ pat, *dst, first);
-			dst++;
-			pat = pat << left | pat >> right;
-			n -= bits - dst_idx;
-		}
-
-		/* Main chunk */
-		n /= bits;
-		while (n >= 4) {
-			*dst++ ^= pat;
-			pat = pat << left | pat >> right;
-			*dst++ ^= pat;
-			pat = pat << left | pat >> right;
-			*dst++ ^= pat;
-			pat = pat << left | pat >> right;
-			*dst++ ^= pat;
-			pat = pat << left | pat >> right;
-			n -= 4;
-		}
-		while (n--) {
-			*dst ^= pat;
-			pat = pat << left | pat >> right;
-		}
-
-		/* Trailing bits */
-		if (last)
-			*dst = comp(*dst ^ pat, *dst, last);
-	}
-}
-
-void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
-{
-	unsigned long pat, pat2, fg;
-	unsigned long width = rect->width, height = rect->height;
-	int bits = BITS_PER_LONG, bytes = bits >> 3;
-	u32 bpp = p->var.bits_per_pixel;
-	unsigned long *dst;
-	int dst_idx, left;
-
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
-	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
-		fg = ((u32 *) (p->pseudo_palette))[rect->color];
-	else
-		fg = rect->color;
-
-	pat = pixel_to_pat( bpp, fg);
-
-	dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
-	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
-	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
-	/* FIXME For now we support 1-32 bpp only */
-	left = bits % bpp;
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-	if (!left) {
-		void (*fill_op32)(struct fb_info *p, unsigned long *dst,
-				  int dst_idx, unsigned long pat, unsigned n,
-				  int bits) = NULL;
-
-		switch (rect->rop) {
-		case ROP_XOR:
-			fill_op32 = bitfill_aligned_rev;
-			break;
-		case ROP_COPY:
-			fill_op32 = bitfill_aligned;
-			break;
-		default:
-			printk( KERN_ERR "cfb_fillrect(): unknown rop, "
-				"defaulting to ROP_COPY\n");
-			fill_op32 = bitfill_aligned;
-			break;
-		}
-		while (height--) {
-			dst += dst_idx >> (ffs(bits) - 1);
-			dst_idx &= (bits - 1);
-			fill_op32(p, dst, dst_idx, pat, width*bpp, bits);
-			dst_idx += p->fix.line_length*8;
-		}
-	} else {
-		int right, r;
-		void (*fill_op)(struct fb_info *p, unsigned long *dst,
-				int dst_idx, unsigned long pat, int left,
-				int right, unsigned n, int bits) = NULL;
-#ifdef __LITTLE_ENDIAN
-		right = left;
-		left = bpp - right;
-#else
-		right = bpp - left;
-#endif
-		switch (rect->rop) {
-		case ROP_XOR:
-			fill_op = bitfill_unaligned_rev;
-			break;
-		case ROP_COPY:
-			fill_op = bitfill_unaligned;
-			break;
-		default:
-			printk(KERN_ERR "sys_fillrect(): unknown rop, "
-				"defaulting to ROP_COPY\n");
-			fill_op = bitfill_unaligned;
-			break;
-		}
-		while (height--) {
-			dst += dst_idx / bits;
-			dst_idx &= (bits - 1);
-			r = dst_idx % bpp;
-			/* rotate pattern to the correct start position */
-			pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
-			fill_op(p, dst, dst_idx, pat2, left, right,
-				width*bpp, bits);
-			dst_idx += p->fix.line_length*8;
-		}
-	}
-}
-
-EXPORT_SYMBOL(sys_fillrect);
-
-MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
-MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/sysimgblt.c b/drivers/video/sysimgblt.c
deleted file mode 100644
index a4d05b1b17d7..000000000000
--- a/drivers/video/sysimgblt.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- *  Generic 1-bit or 8-bit source to 1-32 bit destination expansion
- *  for frame buffer located in system RAM with packed pixels of any depth.
- *
- *  Based almost entirely on cfbimgblt.c
- *
- *      Copyright (C)  April 2007 Antonino Daplas <adaplas@pol.net>
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <asm/types.h>
-
-#define DEBUG
-
-#ifdef DEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-static const u32 cfb_tab8_be[] = {
-    0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
-    0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
-    0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
-    0xffff0000,0xffff00ff,0xffffff00,0xffffffff
-};
-
-static const u32 cfb_tab8_le[] = {
-    0x00000000,0xff000000,0x00ff0000,0xffff0000,
-    0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
-    0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
-    0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
-};
-
-static const u32 cfb_tab16_be[] = {
-    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
-};
-
-static const u32 cfb_tab16_le[] = {
-    0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
-};
-
-static const u32 cfb_tab32[] = {
-	0x00000000, 0xffffffff
-};
-
-static void color_imageblit(const struct fb_image *image, struct fb_info *p,
-			    void *dst1, u32 start_index, u32 pitch_index)
-{
-	/* Draw the penguin */
-	u32 *dst, *dst2;
-	u32 color = 0, val, shift;
-	int i, n, bpp = p->var.bits_per_pixel;
-	u32 null_bits = 32 - bpp;
-	u32 *palette = (u32 *) p->pseudo_palette;
-	const u8 *src = image->data;
-
-	dst2 = dst1;
-	for (i = image->height; i--; ) {
-		n = image->width;
-		dst = dst1;
-		shift = 0;
-		val = 0;
-
-		if (start_index) {
-			u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
-							 start_index));
-			val = *dst & start_mask;
-			shift = start_index;
-		}
-		while (n--) {
-			if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
-			    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
-				color = palette[*src];
-			else
-				color = *src;
-			color <<= FB_LEFT_POS(p, bpp);
-			val |= FB_SHIFT_HIGH(p, color, shift);
-			if (shift >= null_bits) {
-				*dst++ = val;
-
-				val = (shift == null_bits) ? 0 :
-					FB_SHIFT_LOW(p, color, 32 - shift);
-			}
-			shift += bpp;
-			shift &= (32 - 1);
-			src++;
-		}
-		if (shift) {
-			u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
-
-			*dst &= end_mask;
-			*dst |= val;
-		}
-		dst1 += p->fix.line_length;
-		if (pitch_index) {
-			dst2 += p->fix.line_length;
-			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
-
-			start_index += pitch_index;
-			start_index &= 32 - 1;
-		}
-	}
-}
-
-static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
-				  void *dst1, u32 fgcolor, u32 bgcolor,
-				  u32 start_index, u32 pitch_index)
-{
-	u32 shift, color = 0, bpp = p->var.bits_per_pixel;
-	u32 *dst, *dst2;
-	u32 val, pitch = p->fix.line_length;
-	u32 null_bits = 32 - bpp;
-	u32 spitch = (image->width+7)/8;
-	const u8 *src = image->data, *s;
-	u32 i, j, l;
-
-	dst2 = dst1;
-	fgcolor <<= FB_LEFT_POS(p, bpp);
-	bgcolor <<= FB_LEFT_POS(p, bpp);
-
-	for (i = image->height; i--; ) {
-		shift = val = 0;
-		l = 8;
-		j = image->width;
-		dst = dst1;
-		s = src;
-
-		/* write leading bits */
-		if (start_index) {
-			u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
-							 start_index));
-			val = *dst & start_mask;
-			shift = start_index;
-		}
-
-		while (j--) {
-			l--;
-			color = (*s & (1 << l)) ? fgcolor : bgcolor;
-			val |= FB_SHIFT_HIGH(p, color, shift);
-
-			/* Did the bitshift spill bits to the next long? */
-			if (shift >= null_bits) {
-				*dst++ = val;
-				val = (shift == null_bits) ? 0 :
-					FB_SHIFT_LOW(p, color, 32 - shift);
-			}
-			shift += bpp;
-			shift &= (32 - 1);
-			if (!l) { l = 8; s++; }
-		}
-
-		/* write trailing bits */
- 		if (shift) {
-			u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
-
-			*dst &= end_mask;
-			*dst |= val;
-		}
-
-		dst1 += pitch;
-		src += spitch;
-		if (pitch_index) {
-			dst2 += pitch;
-			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
-			start_index += pitch_index;
-			start_index &= 32 - 1;
-		}
-
-	}
-}
-
-/*
- * fast_imageblit - optimized monochrome color expansion
- *
- * Only if:  bits_per_pixel == 8, 16, or 32
- *           image->width is divisible by pixel/dword (ppw);
- *           fix->line_legth is divisible by 4;
- *           beginning and end of a scanline is dword aligned
- */
-static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
-				  void *dst1, u32 fgcolor, u32 bgcolor)
-{
-	u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
-	u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
-	u32 bit_mask, end_mask, eorx, shift;
-	const char *s = image->data, *src;
-	u32 *dst;
-	const u32 *tab = NULL;
-	int i, j, k;
-
-	switch (bpp) {
-	case 8:
-		tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
-		break;
-	case 16:
-		tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
-		break;
-	case 32:
-	default:
-		tab = cfb_tab32;
-		break;
-	}
-
-	for (i = ppw-1; i--; ) {
-		fgx <<= bpp;
-		bgx <<= bpp;
-		fgx |= fgcolor;
-		bgx |= bgcolor;
-	}
-
-	bit_mask = (1 << ppw) - 1;
-	eorx = fgx ^ bgx;
-	k = image->width/ppw;
-
-	for (i = image->height; i--; ) {
-		dst = dst1;
-		shift = 8;
-		src = s;
-
-		for (j = k; j--; ) {
-			shift -= ppw;
-			end_mask = tab[(*src >> shift) & bit_mask];
-			*dst++ = (end_mask & eorx) ^ bgx;
-			if (!shift) {
-				shift = 8;
-				src++;
-			}
-		}
-		dst1 += p->fix.line_length;
-		s += spitch;
-	}
-}
-
-void sys_imageblit(struct fb_info *p, const struct fb_image *image)
-{
-	u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
-	u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
-	u32 width = image->width;
-	u32 dx = image->dx, dy = image->dy;
-	void *dst1;
-
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
-	start_index = bitstart & (32 - 1);
-	pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
-
-	bitstart /= 8;
-	bitstart &= ~(bpl - 1);
-	dst1 = (void __force *)p->screen_base + bitstart;
-
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-
-	if (image->depth == 1) {
-		if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
-		    p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-			fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
-			bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
-		} else {
-			fgcolor = image->fg_color;
-			bgcolor = image->bg_color;
-		}
-
-		if (32 % bpp == 0 && !start_index && !pitch_index &&
-		    ((width & (32/bpp-1)) == 0) &&
-		    bpp >= 8 && bpp <= 32)
-			fast_imageblit(image, p, dst1, fgcolor, bgcolor);
-		else
-			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
-					start_index, pitch_index);
-	} else
-		color_imageblit(image, p, dst1, start_index, pitch_index);
-}
-
-EXPORT_SYMBOL(sys_imageblit);
-
-MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
-MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
deleted file mode 100644
index 7fb2d696fac7..000000000000
--- a/drivers/video/tcx.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/* tcx.c: TCX frame buffer driver
- *
- * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- *
- * Driver layout based loosely on tgafb.c, see that file for credits.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/mm.h>
-#include <linux/of_device.h>
-
-#include <asm/io.h>
-#include <asm/fbio.h>
-
-#include "sbuslib.h"
-
-/*
- * Local functions.
- */
-
-static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			 unsigned, struct fb_info *);
-static int tcx_blank(int, struct fb_info *);
-
-static int tcx_mmap(struct fb_info *, struct vm_area_struct *);
-static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long);
-static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *);
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops tcx_ops = {
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= tcx_setcolreg,
-	.fb_blank		= tcx_blank,
-	.fb_pan_display		= tcx_pan_display,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-	.fb_mmap		= tcx_mmap,
-	.fb_ioctl		= tcx_ioctl,
-#ifdef CONFIG_COMPAT
-	.fb_compat_ioctl	= sbusfb_compat_ioctl,
-#endif
-};
-
-/* THC definitions */
-#define TCX_THC_MISC_REV_SHIFT       16
-#define TCX_THC_MISC_REV_MASK        15
-#define TCX_THC_MISC_VSYNC_DIS       (1 << 25)
-#define TCX_THC_MISC_HSYNC_DIS       (1 << 24)
-#define TCX_THC_MISC_RESET           (1 << 12)
-#define TCX_THC_MISC_VIDEO           (1 << 10)
-#define TCX_THC_MISC_SYNC            (1 << 9)
-#define TCX_THC_MISC_VSYNC           (1 << 8)
-#define TCX_THC_MISC_SYNC_ENAB       (1 << 7)
-#define TCX_THC_MISC_CURS_RES        (1 << 6)
-#define TCX_THC_MISC_INT_ENAB        (1 << 5)
-#define TCX_THC_MISC_INT             (1 << 4)
-#define TCX_THC_MISC_INIT            0x9f
-#define TCX_THC_REV_REV_SHIFT        20
-#define TCX_THC_REV_REV_MASK         15
-#define TCX_THC_REV_MINREV_SHIFT     28
-#define TCX_THC_REV_MINREV_MASK      15
-
-/* The contents are unknown */
-struct tcx_tec {
-	u32 tec_matrix;
-	u32 tec_clip;
-	u32 tec_vdc;
-};
-
-struct tcx_thc {
-	u32 thc_rev;
-	u32 thc_pad0[511];
-	u32 thc_hs;		/* hsync timing */
-	u32 thc_hsdvs;
-	u32 thc_hd;
-	u32 thc_vs;		/* vsync timing */
-	u32 thc_vd;
-	u32 thc_refresh;
-	u32 thc_misc;
-	u32 thc_pad1[56];
-	u32 thc_cursxy;	/* cursor x,y position (16 bits each) */
-	u32 thc_cursmask[32];	/* cursor mask bits */
-	u32 thc_cursbits[32];	/* what to show where mask enabled */
-};
-
-struct bt_regs {
-	u32 addr;
-	u32 color_map;
-	u32 control;
-	u32 cursor;
-};
-
-#define TCX_MMAP_ENTRIES 14
-
-struct tcx_par {
-	spinlock_t		lock;
-	struct bt_regs		__iomem *bt;
-	struct tcx_thc		__iomem *thc;
-	struct tcx_tec		__iomem *tec;
-	u32			__iomem *cplane;
-
-	u32			flags;
-#define TCX_FLAG_BLANKED	0x00000001
-
-	unsigned long		which_io;
-
-	struct sbus_mmap_map	mmap_map[TCX_MMAP_ENTRIES];
-	int			lowdepth;
-};
-
-/* Reset control plane so that WID is 8-bit plane. */
-static void __tcx_set_control_plane(struct fb_info *info)
-{
-	struct tcx_par *par = info->par;
-	u32 __iomem *p, *pend;
-
-	if (par->lowdepth)
-		return;
-
-	p = par->cplane;
-	if (p == NULL)
-		return;
-	for (pend = p + info->fix.smem_len; p < pend; p++) {
-		u32 tmp = sbus_readl(p);
-
-		tmp &= 0xffffff;
-		sbus_writel(tmp, p);
-	}
-}
-
-static void tcx_reset(struct fb_info *info)
-{
-	struct tcx_par *par = (struct tcx_par *) info->par;
-	unsigned long flags;
-
-	spin_lock_irqsave(&par->lock, flags);
-	__tcx_set_control_plane(info);
-	spin_unlock_irqrestore(&par->lock, flags);
-}
-
-static int tcx_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	tcx_reset(info);
-	return 0;
-}
-
-/**
- *      tcx_setcolreg - Optional function. Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *      @green: The green value which can be up to 16 bits wide
- *      @blue:  The blue value which can be up to 16 bits wide.
- *      @transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- */
-static int tcx_setcolreg(unsigned regno,
-			 unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *info)
-{
-	struct tcx_par *par = (struct tcx_par *) info->par;
-	struct bt_regs __iomem *bt = par->bt;
-	unsigned long flags;
-
-	if (regno >= 256)
-		return 1;
-
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	sbus_writel(regno << 24, &bt->addr);
-	sbus_writel(red << 24, &bt->color_map);
-	sbus_writel(green << 24, &bt->color_map);
-	sbus_writel(blue << 24, &bt->color_map);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-/**
- *      tcx_blank - Optional function.  Blanks the display.
- *      @blank_mode: the blank mode we want.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-tcx_blank(int blank, struct fb_info *info)
-{
-	struct tcx_par *par = (struct tcx_par *) info->par;
-	struct tcx_thc __iomem *thc = par->thc;
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&par->lock, flags);
-
-	val = sbus_readl(&thc->thc_misc);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		val &= ~(TCX_THC_MISC_VSYNC_DIS |
-			 TCX_THC_MISC_HSYNC_DIS);
-		val |= TCX_THC_MISC_VIDEO;
-		par->flags &= ~TCX_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-		val &= ~TCX_THC_MISC_VIDEO;
-		par->flags |= TCX_FLAG_BLANKED;
-		break;
-
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-		val |= TCX_THC_MISC_VSYNC_DIS;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-		val |= TCX_THC_MISC_HSYNC_DIS;
-		break;
-
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		break;
-	}
-
-	sbus_writel(val, &thc->thc_misc);
-
-	spin_unlock_irqrestore(&par->lock, flags);
-
-	return 0;
-}
-
-static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = {
-	{
-		.voff	= TCX_RAM8BIT,
-		.size	= SBUS_MMAP_FBSIZE(1)
-	},
-	{
-		.voff	= TCX_RAM24BIT,
-		.size	= SBUS_MMAP_FBSIZE(4)
-	},
-	{
-		.voff	= TCX_UNK3,
-		.size	= SBUS_MMAP_FBSIZE(8)
-	},
-	{
-		.voff	= TCX_UNK4,
-		.size	= SBUS_MMAP_FBSIZE(8)
-	},
-	{
-		.voff	= TCX_CONTROLPLANE,
-		.size	= SBUS_MMAP_FBSIZE(4)
-	},
-	{
-		.voff	= TCX_UNK6,
-		.size	= SBUS_MMAP_FBSIZE(8)
-	},
-	{
-		.voff	= TCX_UNK7,
-		.size	= SBUS_MMAP_FBSIZE(8)
-	},
-	{
-		.voff	= TCX_TEC,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= TCX_BTREGS,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= TCX_THC,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= TCX_DHC,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= TCX_ALT,
-		.size	= PAGE_SIZE
-	},
-	{
-		.voff	= TCX_UNK2,
-		.size	= 0x20000
-	},
-	{ .size = 0 }
-};
-
-static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct tcx_par *par = (struct tcx_par *)info->par;
-
-	return sbusfb_mmap_helper(par->mmap_map,
-				  info->fix.smem_start, info->fix.smem_len,
-				  par->which_io, vma);
-}
-
-static int tcx_ioctl(struct fb_info *info, unsigned int cmd,
-		     unsigned long arg)
-{
-	struct tcx_par *par = (struct tcx_par *) info->par;
-
-	return sbusfb_ioctl_helper(cmd, arg, info,
-				   FBTYPE_TCXCOLOR,
-				   (par->lowdepth ? 8 : 24),
-				   info->fix.smem_len);
-}
-
-/*
- *  Initialisation
- */
-
-static void
-tcx_init_fix(struct fb_info *info, int linebytes)
-{
-	struct tcx_par *par = (struct tcx_par *)info->par;
-	const char *tcx_name;
-
-	if (par->lowdepth)
-		tcx_name = "TCX8";
-	else
-		tcx_name = "TCX24";
-
-	strlcpy(info->fix.id, tcx_name, sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-
-	info->fix.line_length = linebytes;
-
-	info->fix.accel = FB_ACCEL_SUN_TCX;
-}
-
-static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
-			   struct tcx_par *par)
-{
-	if (par->tec)
-		of_iounmap(&op->resource[7],
-			   par->tec, sizeof(struct tcx_tec));
-	if (par->thc)
-		of_iounmap(&op->resource[9],
-			   par->thc, sizeof(struct tcx_thc));
-	if (par->bt)
-		of_iounmap(&op->resource[8],
-			   par->bt, sizeof(struct bt_regs));
-	if (par->cplane)
-		of_iounmap(&op->resource[4],
-			   par->cplane, info->fix.smem_len * sizeof(u32));
-	if (info->screen_base)
-		of_iounmap(&op->resource[0],
-			   info->screen_base, info->fix.smem_len);
-}
-
-static int tcx_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	struct fb_info *info;
-	struct tcx_par *par;
-	int linebytes, i, err;
-
-	info = framebuffer_alloc(sizeof(struct tcx_par), &op->dev);
-
-	err = -ENOMEM;
-	if (!info)
-		goto out_err;
-	par = info->par;
-
-	spin_lock_init(&par->lock);
-
-	par->lowdepth =
-		(of_find_property(dp, "tcx-8-bit", NULL) != NULL);
-
-	sbusfb_fill_var(&info->var, dp, 8);
-	info->var.red.length = 8;
-	info->var.green.length = 8;
-	info->var.blue.length = 8;
-
-	linebytes = of_getintprop_default(dp, "linebytes",
-					  info->var.xres);
-	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
-
-	par->tec = of_ioremap(&op->resource[7], 0,
-				  sizeof(struct tcx_tec), "tcx tec");
-	par->thc = of_ioremap(&op->resource[9], 0,
-				  sizeof(struct tcx_thc), "tcx thc");
-	par->bt = of_ioremap(&op->resource[8], 0,
-				 sizeof(struct bt_regs), "tcx dac");
-	info->screen_base = of_ioremap(&op->resource[0], 0,
-					   info->fix.smem_len, "tcx ram");
-	if (!par->tec || !par->thc ||
-	    !par->bt || !info->screen_base)
-		goto out_unmap_regs;
-
-	memcpy(&par->mmap_map, &__tcx_mmap_map, sizeof(par->mmap_map));
-	if (!par->lowdepth) {
-		par->cplane = of_ioremap(&op->resource[4], 0,
-					     info->fix.smem_len * sizeof(u32),
-					     "tcx cplane");
-		if (!par->cplane)
-			goto out_unmap_regs;
-	} else {
-		par->mmap_map[1].size = SBUS_MMAP_EMPTY;
-		par->mmap_map[4].size = SBUS_MMAP_EMPTY;
-		par->mmap_map[5].size = SBUS_MMAP_EMPTY;
-		par->mmap_map[6].size = SBUS_MMAP_EMPTY;
-	}
-
-	info->fix.smem_start = op->resource[0].start;
-	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
-
-	for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
-		int j;
-
-		switch (i) {
-		case 10:
-			j = 12;
-			break;
-
-		case 11: case 12:
-			j = i - 1;
-			break;
-
-		default:
-			j = i;
-			break;
-		}
-		par->mmap_map[i].poff = op->resource[j].start;
-	}
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &tcx_ops;
-
-	/* Initialize brooktree DAC. */
-	sbus_writel(0x04 << 24, &par->bt->addr);         /* color planes */
-	sbus_writel(0xff << 24, &par->bt->control);
-	sbus_writel(0x05 << 24, &par->bt->addr);
-	sbus_writel(0x00 << 24, &par->bt->control);
-	sbus_writel(0x06 << 24, &par->bt->addr);         /* overlay plane */
-	sbus_writel(0x73 << 24, &par->bt->control);
-	sbus_writel(0x07 << 24, &par->bt->addr);
-	sbus_writel(0x00 << 24, &par->bt->control);
-
-	tcx_reset(info);
-
-	tcx_blank(FB_BLANK_UNBLANK, info);
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0))
-		goto out_unmap_regs;
-
-	fb_set_cmap(&info->cmap, info);
-	tcx_init_fix(info, linebytes);
-
-	err = register_framebuffer(info);
-	if (err < 0)
-		goto out_dealloc_cmap;
-
-	dev_set_drvdata(&op->dev, info);
-
-	printk(KERN_INFO "%s: TCX at %lx:%lx, %s\n",
-	       dp->full_name,
-	       par->which_io,
-	       info->fix.smem_start,
-	       par->lowdepth ? "8-bit only" : "24-bit depth");
-
-	return 0;
-
-out_dealloc_cmap:
-	fb_dealloc_cmap(&info->cmap);
-
-out_unmap_regs:
-	tcx_unmap_regs(op, info, par);
-	framebuffer_release(info);
-
-out_err:
-	return err;
-}
-
-static int tcx_remove(struct platform_device *op)
-{
-	struct fb_info *info = dev_get_drvdata(&op->dev);
-	struct tcx_par *par = info->par;
-
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-
-	tcx_unmap_regs(op, info, par);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static const struct of_device_id tcx_match[] = {
-	{
-		.name = "SUNW,tcx",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, tcx_match);
-
-static struct platform_driver tcx_driver = {
-	.driver = {
-		.name = "tcx",
-		.owner = THIS_MODULE,
-		.of_match_table = tcx_match,
-	},
-	.probe		= tcx_probe,
-	.remove		= tcx_remove,
-};
-
-static int __init tcx_init(void)
-{
-	if (fb_get_options("tcxfb", NULL))
-		return -ENODEV;
-
-	return platform_driver_register(&tcx_driver);
-}
-
-static void __exit tcx_exit(void)
-{
-	platform_driver_unregister(&tcx_driver);
-}
-
-module_init(tcx_init);
-module_exit(tcx_exit);
-
-MODULE_DESCRIPTION("framebuffer driver for TCX chipsets");
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_VERSION("2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
deleted file mode 100644
index f761fe375f5b..000000000000
--- a/drivers/video/tdfxfb.c
+++ /dev/null
@@ -1,1686 +0,0 @@
-/*
- *
- * tdfxfb.c
- *
- * Author: Hannu Mallat <hmallat@cc.hut.fi>
- *
- * Copyright © 1999 Hannu Mallat
- * All rights reserved
- *
- * Created      : Thu Sep 23 18:17:43 1999, hmallat
- * Last modified: Tue Nov  2 21:19:47 1999, hmallat
- *
- * I2C part copied from the i2c-voodoo3.c driver by:
- * Frodo Looijaard <frodol@dds.nl>,
- * Philip Edelbrock <phil@netroedge.com>,
- * Ralph Metzler <rjkm@thp.uni-koeln.de>, and
- * Mark D. Studebaker <mdsxyz123@yahoo.com>
- *
- * Lots of the information here comes from the Daryll Strauss' Banshee
- * patches to the XF86 server, and the rest comes from the 3dfx
- * Banshee specification. I'm very much indebted to Daryll for his
- * work on the X server.
- *
- * Voodoo3 support was contributed Harold Oga. Lots of additions
- * (proper acceleration, 24 bpp, hardware cursor) and bug fixes by Attila
- * Kesmarki. Thanks guys!
- *
- * Voodoo1 and Voodoo2 support aren't relevant to this driver as they
- * behave very differently from the Voodoo3/4/5. For anyone wanting to
- * use frame buffer on the Voodoo1/2, see the sstfb driver (which is
- * located at http://www.sourceforge.net/projects/sstfb).
- *
- * While I _am_ grateful to 3Dfx for releasing the specs for Banshee,
- * I do wish the next version is a bit more complete. Without the XF86
- * patches I couldn't have gotten even this far... for instance, the
- * extensions to the VGA register set go completely unmentioned in the
- * spec! Also, lots of references are made to the 'SST core', but no
- * spec is publicly available, AFAIK.
- *
- * The structure of this driver comes pretty much from the Permedia
- * driver by Ilario Nardinocchi, which in turn is based on skeletonfb.
- *
- * TODO:
- * - multihead support (basically need to support an array of fb_infos)
- * - support other architectures (PPC, Alpha); does the fact that the VGA
- *   core can be accessed only thru I/O (not memory mapped) complicate
- *   things?
- *
- * Version history:
- *
- * 0.1.4 (released 2002-05-28)	ported over to new fbdev api by James Simmons
- *
- * 0.1.3 (released 1999-11-02)	added Attila's panning support, code
- *				reorg, hwcursor address page size alignment
- *				(for mmapping both frame buffer and regs),
- *				and my changes to get rid of hardcoded
- *				VGA i/o register locations (uses PCI
- *				configuration info now)
- * 0.1.2 (released 1999-10-19)	added Attila Kesmarki's bug fixes and
- *				improvements
- * 0.1.1 (released 1999-10-07)	added Voodoo3 support by Harold Oga.
- * 0.1.0 (released 1999-10-06)	initial version
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-#include <video/tdfx.h>
-
-#define DPRINTK(a, b...) pr_debug("fb: %s: " a, __func__ , ## b)
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#else
-/* duplicate asm/mtrr.h defines to work on archs without mtrr */
-#define MTRR_TYPE_WRCOMB     1
-
-static inline int mtrr_add(unsigned long base, unsigned long size,
-				unsigned int type, char increment)
-{
-    return -ENODEV;
-}
-static inline int mtrr_del(int reg, unsigned long base,
-				unsigned long size)
-{
-    return -ENODEV;
-}
-#endif
-
-#define BANSHEE_MAX_PIXCLOCK 270000
-#define VOODOO3_MAX_PIXCLOCK 300000
-#define VOODOO5_MAX_PIXCLOCK 350000
-
-static struct fb_fix_screeninfo tdfx_fix = {
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.ypanstep =	1,
-	.ywrapstep =	1,
-	.accel =	FB_ACCEL_3DFX_BANSHEE
-};
-
-static struct fb_var_screeninfo tdfx_var = {
-	/* "640x480, 8 bpp @ 60 Hz */
-	.xres =		640,
-	.yres =		480,
-	.xres_virtual =	640,
-	.yres_virtual =	1024,
-	.bits_per_pixel = 8,
-	.red =		{0, 8, 0},
-	.blue =		{0, 8, 0},
-	.green =	{0, 8, 0},
-	.activate =	FB_ACTIVATE_NOW,
-	.height =	-1,
-	.width =	-1,
-	.accel_flags =	FB_ACCELF_TEXT,
-	.pixclock =	39722,
-	.left_margin =	40,
-	.right_margin =	24,
-	.upper_margin =	32,
-	.lower_margin =	11,
-	.hsync_len =	96,
-	.vsync_len =	2,
-	.vmode =	FB_VMODE_NONINTERLACED
-};
-
-/*
- * PCI driver prototypes
- */
-static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void tdfxfb_remove(struct pci_dev *pdev);
-
-static struct pci_device_id tdfxfb_id_table[] = {
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
-	  0xff0000, 0 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
-	  0xff0000, 0 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
-	  0xff0000, 0 },
-	{ 0, }
-};
-
-static struct pci_driver tdfxfb_driver = {
-	.name		= "tdfxfb",
-	.id_table	= tdfxfb_id_table,
-	.probe		= tdfxfb_probe,
-	.remove		= tdfxfb_remove,
-};
-
-MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
-
-/*
- * Driver data
- */
-static int nopan;
-static int nowrap = 1;      /* not implemented (yet) */
-static int hwcursor = 1;
-static char *mode_option;
-/* mtrr option */
-static bool nomtrr;
-
-/* -------------------------------------------------------------------------
- *			Hardware-specific funcions
- * ------------------------------------------------------------------------- */
-
-static inline u8 vga_inb(struct tdfx_par *par, u32 reg)
-{
-	return inb(par->iobase + reg - 0x300);
-}
-
-static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val)
-{
-	outb(val, par->iobase + reg - 0x300);
-}
-
-static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val)
-{
-	vga_outb(par, GRA_I, idx);
-	wmb();
-	vga_outb(par, GRA_D, val);
-	wmb();
-}
-
-static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val)
-{
-	vga_outb(par, SEQ_I, idx);
-	wmb();
-	vga_outb(par, SEQ_D, val);
-	wmb();
-}
-
-static inline u8 seq_inb(struct tdfx_par *par, u32 idx)
-{
-	vga_outb(par, SEQ_I, idx);
-	mb();
-	return vga_inb(par, SEQ_D);
-}
-
-static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val)
-{
-	vga_outb(par, CRT_I, idx);
-	wmb();
-	vga_outb(par, CRT_D, val);
-	wmb();
-}
-
-static inline u8 crt_inb(struct tdfx_par *par, u32 idx)
-{
-	vga_outb(par, CRT_I, idx);
-	mb();
-	return vga_inb(par, CRT_D);
-}
-
-static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val)
-{
-	unsigned char tmp;
-
-	tmp = vga_inb(par, IS1_R);
-	vga_outb(par, ATT_IW, idx);
-	vga_outb(par, ATT_IW, val);
-}
-
-static inline void vga_disable_video(struct tdfx_par *par)
-{
-	unsigned char s;
-
-	s = seq_inb(par, 0x01) | 0x20;
-	seq_outb(par, 0x00, 0x01);
-	seq_outb(par, 0x01, s);
-	seq_outb(par, 0x00, 0x03);
-}
-
-static inline void vga_enable_video(struct tdfx_par *par)
-{
-	unsigned char s;
-
-	s = seq_inb(par, 0x01) & 0xdf;
-	seq_outb(par, 0x00, 0x01);
-	seq_outb(par, 0x01, s);
-	seq_outb(par, 0x00, 0x03);
-}
-
-static inline void vga_enable_palette(struct tdfx_par *par)
-{
-	vga_inb(par, IS1_R);
-	mb();
-	vga_outb(par, ATT_IW, 0x20);
-}
-
-static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg)
-{
-	return readl(par->regbase_virt + reg);
-}
-
-static inline void tdfx_outl(struct tdfx_par *par, unsigned int reg, u32 val)
-{
-	writel(val, par->regbase_virt + reg);
-}
-
-static inline void banshee_make_room(struct tdfx_par *par, int size)
-{
-	/* Note: The Voodoo3's onboard FIFO has 32 slots. This loop
-	 * won't quit if you ask for more. */
-	while ((tdfx_inl(par, STATUS) & 0x1f) < size - 1)
-		cpu_relax();
-}
-
-static int banshee_wait_idle(struct fb_info *info)
-{
-	struct tdfx_par *par = info->par;
-	int i = 0;
-
-	banshee_make_room(par, 1);
-	tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP);
-
-	do {
-		if ((tdfx_inl(par, STATUS) & STATUS_BUSY) == 0)
-			i++;
-	} while (i < 3);
-
-	return 0;
-}
-
-/*
- * Set the color of a palette entry in 8bpp mode
- */
-static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c)
-{
-	banshee_make_room(par, 2);
-	tdfx_outl(par, DACADDR, regno);
-	/* read after write makes it working */
-	tdfx_inl(par, DACADDR);
-	tdfx_outl(par, DACDATA, c);
-}
-
-static u32 do_calc_pll(int freq, int *freq_out)
-{
-	int m, n, k, best_m, best_n, best_k, best_error;
-	int fref = 14318;
-
-	best_error = freq;
-	best_n = best_m = best_k = 0;
-
-	for (k = 3; k >= 0; k--) {
-		for (m = 63; m >= 0; m--) {
-			/*
-			 * Estimate value of n that produces target frequency
-			 * with current m and k
-			 */
-			int n_estimated = ((freq * (m + 2) << k) / fref) - 2;
-
-			/* Search neighborhood of estimated n */
-			for (n = max(0, n_estimated);
-				n <= min(255, n_estimated + 1);
-				n++) {
-				/*
-				 * Calculate PLL freqency with current m, k and
-				 * estimated n
-				 */
-				int f = (fref * (n + 2) / (m + 2)) >> k;
-				int error = abs(f - freq);
-
-				/*
-				 * If this is the closest we've come to the
-				 * target frequency then remember n, m and k
-				 */
-				if (error < best_error) {
-					best_error = error;
-					best_n = n;
-					best_m = m;
-					best_k = k;
-				}
-			}
-		}
-	}
-
-	n = best_n;
-	m = best_m;
-	k = best_k;
-	*freq_out = (fref * (n + 2) / (m + 2)) >> k;
-
-	return (n << 8) | (m << 2) | k;
-}
-
-static void do_write_regs(struct fb_info *info, struct banshee_reg *reg)
-{
-	struct tdfx_par *par = info->par;
-	int i;
-
-	banshee_wait_idle(info);
-
-	tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01);
-
-	crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */
-
-	banshee_make_room(par, 3);
-	tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF);
-	tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001);
-#if 0
-	tdfx_outl(par, PLLCTRL1, reg->mempll);
-	tdfx_outl(par, PLLCTRL2, reg->gfxpll);
-#endif
-	tdfx_outl(par, PLLCTRL0, reg->vidpll);
-
-	vga_outb(par, MISC_W, reg->misc[0x00] | 0x01);
-
-	for (i = 0; i < 5; i++)
-		seq_outb(par, i, reg->seq[i]);
-
-	for (i = 0; i < 25; i++)
-		crt_outb(par, i, reg->crt[i]);
-
-	for (i = 0; i < 9; i++)
-		gra_outb(par, i, reg->gra[i]);
-
-	for (i = 0; i < 21; i++)
-		att_outb(par, i, reg->att[i]);
-
-	crt_outb(par, 0x1a, reg->ext[0]);
-	crt_outb(par, 0x1b, reg->ext[1]);
-
-	vga_enable_palette(par);
-	vga_enable_video(par);
-
-	banshee_make_room(par, 9);
-	tdfx_outl(par, VGAINIT0, reg->vgainit0);
-	tdfx_outl(par, DACMODE, reg->dacmode);
-	tdfx_outl(par, VIDDESKSTRIDE, reg->stride);
-	tdfx_outl(par, HWCURPATADDR, reg->curspataddr);
-
-	tdfx_outl(par, VIDSCREENSIZE, reg->screensize);
-	tdfx_outl(par, VIDDESKSTART, reg->startaddr);
-	tdfx_outl(par, VIDPROCCFG, reg->vidcfg);
-	tdfx_outl(par, VGAINIT1, reg->vgainit1);
-	tdfx_outl(par, MISCINIT0, reg->miscinit0);
-
-	banshee_make_room(par, 8);
-	tdfx_outl(par, SRCBASE, reg->startaddr);
-	tdfx_outl(par, DSTBASE, reg->startaddr);
-	tdfx_outl(par, COMMANDEXTRA_2D, 0);
-	tdfx_outl(par, CLIP0MIN, 0);
-	tdfx_outl(par, CLIP0MAX, 0x0fff0fff);
-	tdfx_outl(par, CLIP1MIN, 0);
-	tdfx_outl(par, CLIP1MAX, 0x0fff0fff);
-	tdfx_outl(par, SRCXY, 0);
-
-	banshee_wait_idle(info);
-}
-
-static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
-{
-	u32 draminit0 = tdfx_inl(par, DRAMINIT0);
-	u32 draminit1 = tdfx_inl(par, DRAMINIT1);
-	u32 miscinit1;
-	int num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4;
-	int chip_size; /* in MB */
-	int has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM;
-
-	if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
-		/* Banshee/Voodoo3 */
-		chip_size = 2;
-		if (has_sgram && !(draminit0 & DRAMINIT0_SGRAM_TYPE))
-			chip_size = 1;
-	} else {
-		/* Voodoo4/5 */
-		has_sgram = 0;
-		chip_size = draminit0 & DRAMINIT0_SGRAM_TYPE_MASK;
-		chip_size = 1 << (chip_size >> DRAMINIT0_SGRAM_TYPE_SHIFT);
-	}
-
-	/* disable block writes for SDRAM */
-	miscinit1 = tdfx_inl(par, MISCINIT1);
-	miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS;
-	miscinit1 |= MISCINIT1_CLUT_INV;
-
-	banshee_make_room(par, 1);
-	tdfx_outl(par, MISCINIT1, miscinit1);
-	return num_chips * chip_size * 1024l * 1024;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct tdfx_par *par = info->par;
-	u32 lpitch;
-
-	if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
-	    var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
-		DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	if (var->xres != var->xres_virtual)
-		var->xres_virtual = var->xres;
-
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-
-	if (var->xoffset) {
-		DPRINTK("xoffset not supported\n");
-		return -EINVAL;
-	}
-	var->yoffset = 0;
-
-	/*
-	 * Banshee doesn't support interlace, but Voodoo4/5 and probably
-	 * Voodoo3 do.
-	 * no direct information about device id now?
-	 *  use max_pixclock for this...
-	 */
-	if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) &&
-	    (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
-		DPRINTK("interlace not supported\n");
-		return -EINVAL;
-	}
-
-	if (info->monspecs.hfmax && info->monspecs.vfmax &&
-	    info->monspecs.dclkmax && fb_validate_mode(var, info) < 0) {
-		DPRINTK("mode outside monitor's specs\n");
-		return -EINVAL;
-	}
-
-	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
-	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
-
-	if (var->xres < 320 || var->xres > 2048) {
-		DPRINTK("width not supported: %u\n", var->xres);
-		return -EINVAL;
-	}
-
-	if (var->yres < 200 || var->yres > 2048) {
-		DPRINTK("height not supported: %u\n", var->yres);
-		return -EINVAL;
-	}
-
-	if (lpitch * var->yres_virtual > info->fix.smem_len) {
-		var->yres_virtual = info->fix.smem_len / lpitch;
-		if (var->yres_virtual < var->yres) {
-			DPRINTK("no memory for screen (%ux%ux%u)\n",
-				var->xres, var->yres_virtual,
-				var->bits_per_pixel);
-			return -EINVAL;
-		}
-	}
-
-	if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
-		DPRINTK("pixclock too high (%ldKHz)\n",
-			PICOS2KHZ(var->pixclock));
-		return -EINVAL;
-	}
-
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.length = 8;
-		var->red.offset = 0;
-		var->green = var->red;
-		var->blue = var->red;
-		break;
-	case 16:
-		var->red.offset   = 11;
-		var->red.length   = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset  = 0;
-		var->blue.length  = 5;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-	case 24:
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 8;
-		break;
-	}
-	var->width = -1;
-	var->height = -1;
-
-	var->accel_flags = FB_ACCELF_TEXT;
-
-	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
-		var->xres, var->yres, var->bits_per_pixel);
-	return 0;
-}
-
-static int tdfxfb_set_par(struct fb_info *info)
-{
-	struct tdfx_par *par = info->par;
-	u32 hdispend = info->var.xres;
-	u32 hsyncsta = hdispend + info->var.right_margin;
-	u32 hsyncend = hsyncsta + info->var.hsync_len;
-	u32 htotal   = hsyncend + info->var.left_margin;
-	u32 hd, hs, he, ht, hbs, hbe;
-	u32 vd, vs, ve, vt, vbs, vbe;
-	struct banshee_reg reg;
-	int fout, freq;
-	u32 wd;
-	u32 cpp = (info->var.bits_per_pixel + 7) >> 3;
-
-	memset(&reg, 0, sizeof(reg));
-
-	reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE |
-		     VIDCFG_CURS_X11 |
-		     ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) |
-		     (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);
-
-	/* PLL settings */
-	freq = PICOS2KHZ(info->var.pixclock);
-
-	reg.vidcfg &= ~VIDCFG_2X;
-
-	if (freq > par->max_pixclock / 2) {
-		freq = freq > par->max_pixclock ? par->max_pixclock : freq;
-		reg.dacmode |= DACMODE_2X;
-		reg.vidcfg  |= VIDCFG_2X;
-		hdispend >>= 1;
-		hsyncsta >>= 1;
-		hsyncend >>= 1;
-		htotal   >>= 1;
-	}
-
-	wd = (hdispend >> 3) - 1;
-	hd  = wd;
-	hs  = (hsyncsta >> 3) - 1;
-	he  = (hsyncend >> 3) - 1;
-	ht  = (htotal >> 3) - 1;
-	hbs = hd;
-	hbe = ht;
-
-	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		vd = (info->var.yres << 1) - 1;
-		vs  = vd + (info->var.lower_margin << 1);
-		ve  = vs + (info->var.vsync_len << 1);
-		vt = ve + (info->var.upper_margin << 1) - 1;
-		reg.screensize = info->var.xres | (info->var.yres << 13);
-		reg.vidcfg |= VIDCFG_HALF_MODE;
-		reg.crt[0x09] = 0x80;
-	} else {
-		vd = info->var.yres - 1;
-		vs  = vd + info->var.lower_margin;
-		ve  = vs + info->var.vsync_len;
-		vt = ve + info->var.upper_margin - 1;
-		reg.screensize = info->var.xres | (info->var.yres << 12);
-		reg.vidcfg &= ~VIDCFG_HALF_MODE;
-	}
-	vbs = vd;
-	vbe = vt;
-
-	/* this is all pretty standard VGA register stuffing */
-	reg.misc[0x00] = 0x0f |
-			(info->var.xres < 400 ? 0xa0 :
-			 info->var.xres < 480 ? 0x60 :
-			 info->var.xres < 768 ? 0xe0 : 0x20);
-
-	reg.gra[0x05] = 0x40;
-	reg.gra[0x06] = 0x05;
-	reg.gra[0x07] = 0x0f;
-	reg.gra[0x08] = 0xff;
-
-	reg.att[0x00] = 0x00;
-	reg.att[0x01] = 0x01;
-	reg.att[0x02] = 0x02;
-	reg.att[0x03] = 0x03;
-	reg.att[0x04] = 0x04;
-	reg.att[0x05] = 0x05;
-	reg.att[0x06] = 0x06;
-	reg.att[0x07] = 0x07;
-	reg.att[0x08] = 0x08;
-	reg.att[0x09] = 0x09;
-	reg.att[0x0a] = 0x0a;
-	reg.att[0x0b] = 0x0b;
-	reg.att[0x0c] = 0x0c;
-	reg.att[0x0d] = 0x0d;
-	reg.att[0x0e] = 0x0e;
-	reg.att[0x0f] = 0x0f;
-	reg.att[0x10] = 0x41;
-	reg.att[0x12] = 0x0f;
-
-	reg.seq[0x00] = 0x03;
-	reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */
-	reg.seq[0x02] = 0x0f;
-	reg.seq[0x03] = 0x00;
-	reg.seq[0x04] = 0x0e;
-
-	reg.crt[0x00] = ht - 4;
-	reg.crt[0x01] = hd;
-	reg.crt[0x02] = hbs;
-	reg.crt[0x03] = 0x80 | (hbe & 0x1f);
-	reg.crt[0x04] = hs;
-	reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
-	reg.crt[0x06] = vt;
-	reg.crt[0x07] = ((vs & 0x200) >> 2) |
-			((vd & 0x200) >> 3) |
-			((vt & 0x200) >> 4) | 0x10 |
-			((vbs & 0x100) >> 5) |
-			((vs & 0x100) >> 6) |
-			((vd & 0x100) >> 7) |
-			((vt & 0x100) >> 8);
-	reg.crt[0x09] |= 0x40 | ((vbs & 0x200) >> 4);
-	reg.crt[0x10] = vs;
-	reg.crt[0x11] = (ve & 0x0f) | 0x20;
-	reg.crt[0x12] = vd;
-	reg.crt[0x13] = wd;
-	reg.crt[0x15] = vbs;
-	reg.crt[0x16] = vbe + 1;
-	reg.crt[0x17] = 0xc3;
-	reg.crt[0x18] = 0xff;
-
-	/* Banshee's nonvga stuff */
-	reg.ext[0x00] = (((ht & 0x100) >> 8) |
-			((hd & 0x100) >> 6) |
-			((hbs & 0x100) >> 4) |
-			((hbe & 0x40) >> 1) |
-			((hs & 0x100) >> 2) |
-			((he & 0x20) << 2));
-	reg.ext[0x01] = (((vt & 0x400) >> 10) |
-			((vd & 0x400) >> 8) |
-			((vbs & 0x400) >> 6) |
-			((vbe & 0x400) >> 4));
-
-	reg.vgainit0 =	VGAINIT0_8BIT_DAC     |
-			VGAINIT0_EXT_ENABLE   |
-			VGAINIT0_WAKEUP_3C3   |
-			VGAINIT0_ALT_READBACK |
-			VGAINIT0_EXTSHIFTOUT;
-	reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff;
-
-	if (hwcursor)
-		reg.curspataddr = info->fix.smem_len;
-
-	reg.cursloc   = 0;
-
-	reg.cursc0    = 0;
-	reg.cursc1    = 0xffffff;
-
-	reg.stride    = info->var.xres * cpp;
-	reg.startaddr = info->var.yoffset * reg.stride
-			+ info->var.xoffset * cpp;
-
-	reg.vidpll = do_calc_pll(freq, &fout);
-#if 0
-	reg.mempll = do_calc_pll(..., &fout);
-	reg.gfxpll = do_calc_pll(..., &fout);
-#endif
-
-	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
-		reg.vidcfg |= VIDCFG_INTERLACE;
-	reg.miscinit0 = tdfx_inl(par, MISCINIT0);
-
-#if defined(__BIG_ENDIAN)
-	switch (info->var.bits_per_pixel) {
-	case 8:
-	case 24:
-		reg.miscinit0 &= ~(1 << 30);
-		reg.miscinit0 &= ~(1 << 31);
-		break;
-	case 16:
-		reg.miscinit0 |= (1 << 30);
-		reg.miscinit0 |= (1 << 31);
-		break;
-	case 32:
-		reg.miscinit0 |= (1 << 30);
-		reg.miscinit0 &= ~(1 << 31);
-		break;
-	}
-#endif
-	do_write_regs(info, &reg);
-
-	/* Now change fb_fix_screeninfo according to changes in par */
-	info->fix.line_length = reg.stride;
-	info->fix.visual = (info->var.bits_per_pixel == 8)
-				? FB_VISUAL_PSEUDOCOLOR
-				: FB_VISUAL_TRUECOLOR;
-	DPRINTK("Graphics mode is now set at %dx%d depth %d\n",
-		info->var.xres, info->var.yres, info->var.bits_per_pixel);
-	return 0;
-}
-
-/* A handy macro shamelessly pinched from matroxfb */
-#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
-
-static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			    unsigned blue, unsigned transp,
-			    struct fb_info *info)
-{
-	struct tdfx_par *par = info->par;
-	u32 rgbcol;
-
-	if (regno >= info->cmap.len || regno > 255)
-		return 1;
-
-	/* grayscale works only partially under directcolor */
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		blue = (red * 77 + green * 151 + blue * 28) >> 8;
-		green = blue;
-		red = blue;
-	}
-
-	switch (info->fix.visual) {
-	case FB_VISUAL_PSEUDOCOLOR:
-		rgbcol = (((u32)red   & 0xff00) << 8) |
-			 (((u32)green & 0xff00) << 0) |
-			 (((u32)blue  & 0xff00) >> 8);
-		do_setpalentry(par, regno, rgbcol);
-		break;
-	/* Truecolor has no hardware color palettes. */
-	case FB_VISUAL_TRUECOLOR:
-		if (regno < 16) {
-			rgbcol = (CNVT_TOHW(red, info->var.red.length) <<
-				  info->var.red.offset) |
-				(CNVT_TOHW(green, info->var.green.length) <<
-				 info->var.green.offset) |
-				(CNVT_TOHW(blue, info->var.blue.length) <<
-				 info->var.blue.offset) |
-				(CNVT_TOHW(transp, info->var.transp.length) <<
-				 info->var.transp.offset);
-			par->palette[regno] = rgbcol;
-		}
-
-		break;
-	default:
-		DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
-		break;
-	}
-
-	return 0;
-}
-
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-static int tdfxfb_blank(int blank, struct fb_info *info)
-{
-	struct tdfx_par *par = info->par;
-	int vgablank = 1;
-	u32 dacmode = tdfx_inl(par, DACMODE);
-
-	dacmode &= ~(BIT(1) | BIT(3));
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */
-		vgablank = 0;
-		break;
-	case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */
-		break;
-	case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */
-		dacmode |= BIT(3);
-		break;
-	case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */
-		dacmode |= BIT(1);
-		break;
-	case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */
-		dacmode |= BIT(1) | BIT(3);
-		break;
-	}
-
-	banshee_make_room(par, 1);
-	tdfx_outl(par, DACMODE, dacmode);
-	if (vgablank)
-		vga_disable_video(par);
-	else
-		vga_enable_video(par);
-	return 0;
-}
-
-/*
- * Set the starting position of the visible screen to var->yoffset
- */
-static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct tdfx_par *par = info->par;
-	u32 addr = var->yoffset * info->fix.line_length;
-
-	if (nopan || var->xoffset)
-		return -EINVAL;
-
-	banshee_make_room(par, 1);
-	tdfx_outl(par, VIDDESKSTART, addr);
-
-	return 0;
-}
-
-#ifdef CONFIG_FB_3DFX_ACCEL
-/*
- * FillRect 2D command (solidfill or invert (via ROP_XOR))
- */
-static void tdfxfb_fillrect(struct fb_info *info,
-			    const struct fb_fillrect *rect)
-{
-	struct tdfx_par *par = info->par;
-	u32 bpp = info->var.bits_per_pixel;
-	u32 stride = info->fix.line_length;
-	u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
-	int tdfx_rop;
-	u32 dx = rect->dx;
-	u32 dy = rect->dy;
-	u32 dstbase = 0;
-
-	if (rect->rop == ROP_COPY)
-		tdfx_rop = TDFX_ROP_COPY;
-	else
-		tdfx_rop = TDFX_ROP_XOR;
-
-	/* assume always rect->height < 4096 */
-	if (dy + rect->height > 4095) {
-		dstbase = stride * dy;
-		dy = 0;
-	}
-	/* assume always rect->width < 4096 */
-	if (dx + rect->width > 4095) {
-		dstbase += dx * bpp >> 3;
-		dx = 0;
-	}
-	banshee_make_room(par, 6);
-	tdfx_outl(par, DSTFORMAT, fmt);
-	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
-		tdfx_outl(par, COLORFORE, rect->color);
-	} else { /* FB_VISUAL_TRUECOLOR */
-		tdfx_outl(par, COLORFORE, par->palette[rect->color]);
-	}
-	tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
-	tdfx_outl(par, DSTBASE, dstbase);
-	tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
-	tdfx_outl(par, LAUNCH_2D, dx | (dy << 16));
-}
-
-/*
- * Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
- */
-static void tdfxfb_copyarea(struct fb_info *info,
-			    const struct fb_copyarea *area)
-{
-	struct tdfx_par *par = info->par;
-	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
-	u32 bpp = info->var.bits_per_pixel;
-	u32 stride = info->fix.line_length;
-	u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
-	u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
-	u32 dstbase = 0;
-	u32 srcbase = 0;
-
-	/* assume always area->height < 4096 */
-	if (sy + area->height > 4095) {
-		srcbase = stride * sy;
-		sy = 0;
-	}
-	/* assume always area->width < 4096 */
-	if (sx + area->width > 4095) {
-		srcbase += sx * bpp >> 3;
-		sx = 0;
-	}
-	/* assume always area->height < 4096 */
-	if (dy + area->height > 4095) {
-		dstbase = stride * dy;
-		dy = 0;
-	}
-	/* assume always area->width < 4096 */
-	if (dx + area->width > 4095) {
-		dstbase += dx * bpp >> 3;
-		dx = 0;
-	}
-
-	if (area->sx <= area->dx) {
-		/* -X */
-		blitcmd |= BIT(14);
-		sx += area->width - 1;
-		dx += area->width - 1;
-	}
-	if (area->sy <= area->dy) {
-		/* -Y */
-		blitcmd |= BIT(15);
-		sy += area->height - 1;
-		dy += area->height - 1;
-	}
-
-	banshee_make_room(par, 8);
-
-	tdfx_outl(par, SRCFORMAT, fmt);
-	tdfx_outl(par, DSTFORMAT, fmt);
-	tdfx_outl(par, COMMAND_2D, blitcmd);
-	tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
-	tdfx_outl(par, DSTXY, dx | (dy << 16));
-	tdfx_outl(par, SRCBASE, srcbase);
-	tdfx_outl(par, DSTBASE, dstbase);
-	tdfx_outl(par, LAUNCH_2D, sx | (sy << 16));
-}
-
-static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct tdfx_par *par = info->par;
-	int size = image->height * ((image->width * image->depth + 7) >> 3);
-	int fifo_free;
-	int i, stride = info->fix.line_length;
-	u32 bpp = info->var.bits_per_pixel;
-	u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
-	u8 *chardata = (u8 *) image->data;
-	u32 srcfmt;
-	u32 dx = image->dx;
-	u32 dy = image->dy;
-	u32 dstbase = 0;
-
-	if (image->depth != 1) {
-#ifdef BROKEN_CODE
-		banshee_make_room(par, 6 + ((size + 3) >> 2));
-		srcfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13) |
-			0x400000;
-#else
-		cfb_imageblit(info, image);
-#endif
-		return;
-	}
-	banshee_make_room(par, 9);
-	switch (info->fix.visual) {
-	case FB_VISUAL_PSEUDOCOLOR:
-		tdfx_outl(par, COLORFORE, image->fg_color);
-		tdfx_outl(par, COLORBACK, image->bg_color);
-		break;
-	case FB_VISUAL_TRUECOLOR:
-	default:
-		tdfx_outl(par, COLORFORE,
-			  par->palette[image->fg_color]);
-		tdfx_outl(par, COLORBACK,
-			  par->palette[image->bg_color]);
-	}
-#ifdef __BIG_ENDIAN
-	srcfmt = 0x400000 | BIT(20);
-#else
-	srcfmt = 0x400000;
-#endif
-	/* assume always image->height < 4096 */
-	if (dy + image->height > 4095) {
-		dstbase = stride * dy;
-		dy = 0;
-	}
-	/* assume always image->width < 4096 */
-	if (dx + image->width > 4095) {
-		dstbase += dx * bpp >> 3;
-		dx = 0;
-	}
-
-	tdfx_outl(par, DSTBASE, dstbase);
-	tdfx_outl(par, SRCXY, 0);
-	tdfx_outl(par, DSTXY, dx | (dy << 16));
-	tdfx_outl(par, COMMAND_2D,
-		  COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
-	tdfx_outl(par, SRCFORMAT, srcfmt);
-	tdfx_outl(par, DSTFORMAT, dstfmt);
-	tdfx_outl(par, DSTSIZE, image->width | (image->height << 16));
-
-	/* A count of how many free FIFO entries we've requested.
-	 * When this goes negative, we need to request more. */
-	fifo_free = 0;
-
-	/* Send four bytes at a time of data */
-	for (i = (size >> 2); i > 0; i--) {
-		if (--fifo_free < 0) {
-			fifo_free = 31;
-			banshee_make_room(par, fifo_free);
-		}
-		tdfx_outl(par, LAUNCH_2D, *(u32 *)chardata);
-		chardata += 4;
-	}
-
-	/* Send the leftovers now */
-	banshee_make_room(par, 3);
-	switch (size % 4) {
-	case 0:
-		break;
-	case 1:
-		tdfx_outl(par, LAUNCH_2D, *chardata);
-		break;
-	case 2:
-		tdfx_outl(par, LAUNCH_2D, *(u16 *)chardata);
-		break;
-	case 3:
-		tdfx_outl(par, LAUNCH_2D,
-			*(u16 *)chardata | (chardata[3] << 24));
-		break;
-	}
-}
-#endif /* CONFIG_FB_3DFX_ACCEL */
-
-static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct tdfx_par *par = info->par;
-	u32 vidcfg;
-
-	if (!hwcursor)
-		return -EINVAL;	/* just to force soft_cursor() call */
-
-	/* Too large of a cursor or wrong bpp :-( */
-	if (cursor->image.width > 64 ||
-	    cursor->image.height > 64 ||
-	    cursor->image.depth > 1)
-		return -EINVAL;
-
-	vidcfg = tdfx_inl(par, VIDPROCCFG);
-	if (cursor->enable)
-		tdfx_outl(par, VIDPROCCFG, vidcfg | VIDCFG_HWCURSOR_ENABLE);
-	else
-		tdfx_outl(par, VIDPROCCFG, vidcfg & ~VIDCFG_HWCURSOR_ENABLE);
-
-	/*
-	 * If the cursor is not be changed this means either we want the
-	 * current cursor state (if enable is set) or we want to query what
-	 * we can do with the cursor (if enable is not set)
-	 */
-	if (!cursor->set)
-		return 0;
-
-	/* fix cursor color - XFree86 forgets to restore it properly */
-	if (cursor->set & FB_CUR_SETCMAP) {
-		struct fb_cmap cmap = info->cmap;
-		u32 bg_idx = cursor->image.bg_color;
-		u32 fg_idx = cursor->image.fg_color;
-		unsigned long bg_color, fg_color;
-
-		fg_color = (((u32)cmap.red[fg_idx]   & 0xff00) << 8) |
-			   (((u32)cmap.green[fg_idx] & 0xff00) << 0) |
-			   (((u32)cmap.blue[fg_idx]  & 0xff00) >> 8);
-		bg_color = (((u32)cmap.red[bg_idx]   & 0xff00) << 8) |
-			   (((u32)cmap.green[bg_idx] & 0xff00) << 0) |
-			   (((u32)cmap.blue[bg_idx]  & 0xff00) >> 8);
-		banshee_make_room(par, 2);
-		tdfx_outl(par, HWCURC0, bg_color);
-		tdfx_outl(par, HWCURC1, fg_color);
-	}
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		int x = cursor->image.dx;
-		int y = cursor->image.dy - info->var.yoffset;
-
-		x += 63;
-		y += 63;
-		banshee_make_room(par, 1);
-		tdfx_outl(par, HWCURLOC, (y << 16) + x);
-	}
-	if (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
-		/*
-		 * Voodoo 3 and above cards use 2 monochrome cursor patterns.
-		 *    The reason is so the card can fetch 8 words at a time
-		 * and are stored on chip for use for the next 8 scanlines.
-		 * This reduces the number of times for access to draw the
-		 * cursor for each screen refresh.
-		 *    Each pattern is a bitmap of 64 bit wide and 64 bit high
-		 * (total of 8192 bits or 1024 bytes). The two patterns are
-		 * stored in such a way that pattern 0 always resides in the
-		 * lower half (least significant 64 bits) of a 128 bit word
-		 * and pattern 1 the upper half. If you examine the data of
-		 * the cursor image the graphics card uses then from the
-		 * beginning you see line one of pattern 0, line one of
-		 * pattern 1, line two of pattern 0, line two of pattern 1,
-		 * etc etc. The linear stride for the cursor is always 16 bytes
-		 * (128 bits) which is the maximum cursor width times two for
-		 * the two monochrome patterns.
-		 */
-		u8 __iomem *cursorbase = info->screen_base + info->fix.smem_len;
-		u8 *bitmap = (u8 *)cursor->image.data;
-		u8 *mask = (u8 *)cursor->mask;
-		int i;
-
-		fb_memset(cursorbase, 0, 1024);
-
-		for (i = 0; i < cursor->image.height; i++) {
-			int h = 0;
-			int j = (cursor->image.width + 7) >> 3;
-
-			for (; j > 0; j--) {
-				u8 data = *mask ^ *bitmap;
-				if (cursor->rop == ROP_COPY)
-					data = *mask & *bitmap;
-				/* Pattern 0. Copy the cursor mask to it */
-				fb_writeb(*mask, cursorbase + h);
-				mask++;
-				/* Pattern 1. Copy the cursor bitmap to it */
-				fb_writeb(data, cursorbase + h + 8);
-				bitmap++;
-				h++;
-			}
-			cursorbase += 16;
-		}
-	}
-	return 0;
-}
-
-static struct fb_ops tdfxfb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_check_var	= tdfxfb_check_var,
-	.fb_set_par	= tdfxfb_set_par,
-	.fb_setcolreg	= tdfxfb_setcolreg,
-	.fb_blank	= tdfxfb_blank,
-	.fb_pan_display	= tdfxfb_pan_display,
-	.fb_sync	= banshee_wait_idle,
-	.fb_cursor	= tdfxfb_cursor,
-#ifdef CONFIG_FB_3DFX_ACCEL
-	.fb_fillrect	= tdfxfb_fillrect,
-	.fb_copyarea	= tdfxfb_copyarea,
-	.fb_imageblit	= tdfxfb_imageblit,
-#else
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-#endif
-};
-
-#ifdef CONFIG_FB_3DFX_I2C
-/* The voo GPIO registers don't have individual masks for each bit
-   so we always have to read before writing. */
-
-static void tdfxfb_i2c_setscl(void *data, int val)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-	unsigned int r;
-
-	r = tdfx_inl(par, VIDSERPARPORT);
-	if (val)
-		r |= I2C_SCL_OUT;
-	else
-		r &= ~I2C_SCL_OUT;
-	tdfx_outl(par, VIDSERPARPORT, r);
-	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
-}
-
-static void tdfxfb_i2c_setsda(void *data, int val)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-	unsigned int r;
-
-	r = tdfx_inl(par, VIDSERPARPORT);
-	if (val)
-		r |= I2C_SDA_OUT;
-	else
-		r &= ~I2C_SDA_OUT;
-	tdfx_outl(par, VIDSERPARPORT, r);
-	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
-}
-
-/* The GPIO pins are open drain, so the pins always remain outputs.
-   We rely on the i2c-algo-bit routines to set the pins high before
-   reading the input from other chips. */
-
-static int tdfxfb_i2c_getscl(void *data)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-
-	return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SCL_IN));
-}
-
-static int tdfxfb_i2c_getsda(void *data)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-
-	return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SDA_IN));
-}
-
-static void tdfxfb_ddc_setscl(void *data, int val)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-	unsigned int r;
-
-	r = tdfx_inl(par, VIDSERPARPORT);
-	if (val)
-		r |= DDC_SCL_OUT;
-	else
-		r &= ~DDC_SCL_OUT;
-	tdfx_outl(par, VIDSERPARPORT, r);
-	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
-}
-
-static void tdfxfb_ddc_setsda(void *data, int val)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-	unsigned int r;
-
-	r = tdfx_inl(par, VIDSERPARPORT);
-	if (val)
-		r |= DDC_SDA_OUT;
-	else
-		r &= ~DDC_SDA_OUT;
-	tdfx_outl(par, VIDSERPARPORT, r);
-	tdfx_inl(par, VIDSERPARPORT);	/* flush posted write */
-}
-
-static int tdfxfb_ddc_getscl(void *data)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-
-	return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SCL_IN));
-}
-
-static int tdfxfb_ddc_getsda(void *data)
-{
-	struct tdfxfb_i2c_chan 	*chan = data;
-	struct tdfx_par 	*par = chan->par;
-
-	return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SDA_IN));
-}
-
-static int tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan, const char *name,
-				struct device *dev)
-{
-	int rc;
-
-	strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
-	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.class		= I2C_CLASS_DDC;
-	chan->adapter.algo_data		= &chan->algo;
-	chan->adapter.dev.parent	= dev;
-	chan->algo.setsda		= tdfxfb_ddc_setsda;
-	chan->algo.setscl		= tdfxfb_ddc_setscl;
-	chan->algo.getsda		= tdfxfb_ddc_getsda;
-	chan->algo.getscl		= tdfxfb_ddc_getscl;
-	chan->algo.udelay		= 10;
-	chan->algo.timeout		= msecs_to_jiffies(500);
-	chan->algo.data 		= chan;
-
-	i2c_set_adapdata(&chan->adapter, chan);
-
-	rc = i2c_bit_add_bus(&chan->adapter);
-	if (rc == 0)
-		DPRINTK("I2C bus %s registered.\n", name);
-	else
-		chan->par = NULL;
-
-	return rc;
-}
-
-static int tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan, const char *name,
-				struct device *dev)
-{
-	int rc;
-
-	strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
-	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.algo_data		= &chan->algo;
-	chan->adapter.dev.parent	= dev;
-	chan->algo.setsda		= tdfxfb_i2c_setsda;
-	chan->algo.setscl		= tdfxfb_i2c_setscl;
-	chan->algo.getsda		= tdfxfb_i2c_getsda;
-	chan->algo.getscl		= tdfxfb_i2c_getscl;
-	chan->algo.udelay		= 10;
-	chan->algo.timeout		= msecs_to_jiffies(500);
-	chan->algo.data 		= chan;
-
-	i2c_set_adapdata(&chan->adapter, chan);
-
-	rc = i2c_bit_add_bus(&chan->adapter);
-	if (rc == 0)
-		DPRINTK("I2C bus %s registered.\n", name);
-	else
-		chan->par = NULL;
-
-	return rc;
-}
-
-static void tdfxfb_create_i2c_busses(struct fb_info *info)
-{
-	struct tdfx_par *par = info->par;
-
-	tdfx_outl(par, VIDINFORMAT, 0x8160);
-	tdfx_outl(par, VIDSERPARPORT, 0xcffc0020);
-
-	par->chan[0].par = par;
-	par->chan[1].par = par;
-
-	tdfxfb_setup_ddc_bus(&par->chan[0], "Voodoo3-DDC", info->dev);
-	tdfxfb_setup_i2c_bus(&par->chan[1], "Voodoo3-I2C", info->dev);
-}
-
-static void tdfxfb_delete_i2c_busses(struct tdfx_par *par)
-{
-	if (par->chan[0].par)
-		i2c_del_adapter(&par->chan[0].adapter);
-	par->chan[0].par = NULL;
-
-	if (par->chan[1].par)
-		i2c_del_adapter(&par->chan[1].adapter);
-	par->chan[1].par = NULL;
-}
-
-static int tdfxfb_probe_i2c_connector(struct tdfx_par *par,
-				      struct fb_monspecs *specs)
-{
-	u8 *edid = NULL;
-
-	DPRINTK("Probe DDC Bus\n");
-	if (par->chan[0].par)
-		edid = fb_ddc_read(&par->chan[0].adapter);
-
-	if (edid) {
-		fb_edid_to_monspecs(edid, specs);
-		kfree(edid);
-		return 0;
-	}
-	return 1;
-}
-#endif /* CONFIG_FB_3DFX_I2C */
-
-/**
- *      tdfxfb_probe - Device Initializiation
- *
- *      @pdev:  PCI Device to initialize
- *      @id:    PCI Device ID
- *
- *      Initializes and allocates resources for PCI device @pdev.
- *
- */
-static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct tdfx_par *default_par;
-	struct fb_info *info;
-	int err, lpitch;
-	struct fb_monspecs *specs;
-	bool found;
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err);
-		return err;
-	}
-
-	info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev);
-
-	if (!info)
-		return -ENOMEM;
-
-	default_par = info->par;
-	info->fix = tdfx_fix;
-
-	/* Configure the default fb_fix_screeninfo first */
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_3DFX_BANSHEE:
-		strcpy(info->fix.id, "3Dfx Banshee");
-		default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
-		break;
-	case PCI_DEVICE_ID_3DFX_VOODOO3:
-		strcpy(info->fix.id, "3Dfx Voodoo3");
-		default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
-		break;
-	case PCI_DEVICE_ID_3DFX_VOODOO5:
-		strcpy(info->fix.id, "3Dfx Voodoo5");
-		default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
-		break;
-	}
-
-	info->fix.mmio_start = pci_resource_start(pdev, 0);
-	info->fix.mmio_len = pci_resource_len(pdev, 0);
-	if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len,
-				"tdfx regbase")) {
-		printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
-		goto out_err;
-	}
-
-	default_par->regbase_virt =
-		ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
-	if (!default_par->regbase_virt) {
-		printk(KERN_ERR "fb: Can't remap %s register area.\n",
-				info->fix.id);
-		goto out_err_regbase;
-	}
-
-	info->fix.smem_start = pci_resource_start(pdev, 1);
-	info->fix.smem_len = do_lfb_size(default_par, pdev->device);
-	if (!info->fix.smem_len) {
-		printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id);
-		goto out_err_regbase;
-	}
-
-	if (!request_mem_region(info->fix.smem_start,
-				pci_resource_len(pdev, 1), "tdfx smem")) {
-		printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
-		goto out_err_regbase;
-	}
-
-	info->screen_base = ioremap_nocache(info->fix.smem_start,
-					    info->fix.smem_len);
-	if (!info->screen_base) {
-		printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
-				info->fix.id);
-		goto out_err_screenbase;
-	}
-
-	default_par->iobase = pci_resource_start(pdev, 2);
-
-	if (!request_region(pci_resource_start(pdev, 2),
-			    pci_resource_len(pdev, 2), "tdfx iobase")) {
-		printk(KERN_ERR "tdfxfb: Can't reserve iobase\n");
-		goto out_err_screenbase;
-	}
-
-	printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id,
-			info->fix.smem_len >> 10);
-
-	default_par->mtrr_handle = -1;
-	if (!nomtrr)
-		default_par->mtrr_handle =
-			mtrr_add(info->fix.smem_start, info->fix.smem_len,
-				 MTRR_TYPE_WRCOMB, 1);
-
-	info->fix.ypanstep	= nopan ? 0 : 1;
-	info->fix.ywrapstep	= nowrap ? 0 : 1;
-
-	info->fbops		= &tdfxfb_ops;
-	info->pseudo_palette	= default_par->palette;
-	info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-#ifdef CONFIG_FB_3DFX_ACCEL
-	info->flags		|= FBINFO_HWACCEL_FILLRECT |
-				   FBINFO_HWACCEL_COPYAREA |
-				   FBINFO_HWACCEL_IMAGEBLIT |
-				   FBINFO_READS_FAST;
-#endif
-	/* reserve 8192 bits for cursor */
-	/* the 2.4 driver says PAGE_MASK boundary is not enough for Voodoo4 */
-	if (hwcursor)
-		info->fix.smem_len = (info->fix.smem_len - 1024) &
-					(PAGE_MASK << 1);
-	specs = &info->monspecs;
-	found = false;
-	info->var.bits_per_pixel = 8;
-#ifdef CONFIG_FB_3DFX_I2C
-	tdfxfb_create_i2c_busses(info);
-	err = tdfxfb_probe_i2c_connector(default_par, specs);
-
-	if (!err) {
-		if (specs->modedb == NULL)
-			DPRINTK("Unable to get Mode Database\n");
-		else {
-			const struct fb_videomode *m;
-
-			fb_videomode_to_modelist(specs->modedb,
-						 specs->modedb_len,
-						 &info->modelist);
-			m = fb_find_best_display(specs, &info->modelist);
-			if (m) {
-				fb_videomode_to_var(&info->var, m);
-				/* fill all other info->var's fields */
-				if (tdfxfb_check_var(&info->var, info) < 0)
-					info->var = tdfx_var;
-				else
-					found = true;
-			}
-		}
-	}
-#endif
-	if (!mode_option && !found)
-		mode_option = "640x480@60";
-
-	if (mode_option) {
-		err = fb_find_mode(&info->var, info, mode_option,
-				   specs->modedb, specs->modedb_len,
-				   NULL, info->var.bits_per_pixel);
-		if (!err || err == 4)
-			info->var = tdfx_var;
-	}
-
-	if (found) {
-		fb_destroy_modedb(specs->modedb);
-		specs->modedb = NULL;
-	}
-
-	/* maximize virtual vertical length */
-	lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
-	info->var.yres_virtual = info->fix.smem_len / lpitch;
-	if (info->var.yres_virtual < info->var.yres)
-		goto out_err_iobase;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		printk(KERN_ERR "tdfxfb: Can't allocate color map\n");
-		goto out_err_iobase;
-	}
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "tdfxfb: can't register framebuffer\n");
-		fb_dealloc_cmap(&info->cmap);
-		goto out_err_iobase;
-	}
-	/*
-	 * Our driver data
-	 */
-	pci_set_drvdata(pdev, info);
-	return 0;
-
-out_err_iobase:
-#ifdef CONFIG_FB_3DFX_I2C
-	tdfxfb_delete_i2c_busses(default_par);
-#endif
-	if (default_par->mtrr_handle >= 0)
-		mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
-			 info->fix.smem_len);
-	release_region(pci_resource_start(pdev, 2),
-		       pci_resource_len(pdev, 2));
-out_err_screenbase:
-	if (info->screen_base)
-		iounmap(info->screen_base);
-	release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1));
-out_err_regbase:
-	/*
-	 * Cleanup after anything that was remapped/allocated.
-	 */
-	if (default_par->regbase_virt)
-		iounmap(default_par->regbase_virt);
-	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
-out_err:
-	framebuffer_release(info);
-	return -ENXIO;
-}
-
-#ifndef MODULE
-static void __init tdfxfb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "nopan")) {
-			nopan = 1;
-		} else if (!strcmp(this_opt, "nowrap")) {
-			nowrap = 1;
-		} else if (!strncmp(this_opt, "hwcursor=", 9)) {
-			hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
-#ifdef CONFIG_MTRR
-		} else if (!strncmp(this_opt, "nomtrr", 6)) {
-			nomtrr = 1;
-#endif
-		} else {
-			mode_option = this_opt;
-		}
-	}
-}
-#endif
-
-/**
- *      tdfxfb_remove - Device removal
- *
- *      @pdev:  PCI Device to cleanup
- *
- *      Releases all resources allocated during the course of the driver's
- *      lifetime for the PCI device @pdev.
- *
- */
-static void tdfxfb_remove(struct pci_dev *pdev)
-{
-	struct fb_info *info = pci_get_drvdata(pdev);
-	struct tdfx_par *par = info->par;
-
-	unregister_framebuffer(info);
-#ifdef CONFIG_FB_3DFX_I2C
-	tdfxfb_delete_i2c_busses(par);
-#endif
-	if (par->mtrr_handle >= 0)
-		mtrr_del(par->mtrr_handle, info->fix.smem_start,
-			 info->fix.smem_len);
-	iounmap(par->regbase_virt);
-	iounmap(info->screen_base);
-
-	/* Clean up after reserved regions */
-	release_region(pci_resource_start(pdev, 2),
-		       pci_resource_len(pdev, 2));
-	release_mem_region(pci_resource_start(pdev, 1),
-			   pci_resource_len(pdev, 1));
-	release_mem_region(pci_resource_start(pdev, 0),
-			   pci_resource_len(pdev, 0));
-	fb_dealloc_cmap(&info->cmap);
-	framebuffer_release(info);
-}
-
-static int __init tdfxfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("tdfxfb", &option))
-		return -ENODEV;
-
-	tdfxfb_setup(option);
-#endif
-	return pci_register_driver(&tdfxfb_driver);
-}
-
-static void __exit tdfxfb_exit(void)
-{
-	pci_unregister_driver(&tdfxfb_driver);
-}
-
-MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
-MODULE_DESCRIPTION("3Dfx framebuffer device driver");
-MODULE_LICENSE("GPL");
-
-module_param(hwcursor, int, 0644);
-MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
-			"(1=enable, 0=disable, default=1)");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
-#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, 0);
-MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
-#endif
-
-module_init(tdfxfb_init);
-module_exit(tdfxfb_exit);
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
deleted file mode 100644
index 65ba9921506e..000000000000
--- a/drivers/video/tgafb.c
+++ /dev/null
@@ -1,1611 +0,0 @@
-/*
- *  linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
- *
- *	Copyright (C) 1995 Jay Estabrook
- *	Copyright (C) 1997 Geert Uytterhoeven
- *	Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
- *	Copyright (C) 2002 Richard Henderson
- *	Copyright (C) 2006, 2007  Maciej W. Rozycki
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/bitrev.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/selection.h>
-#include <linux/string.h>
-#include <linux/tc.h>
-
-#include <asm/io.h>
-
-#include <video/tgafb.h>
-
-#ifdef CONFIG_TC
-#define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type)
-#else
-#define TGA_BUS_TC(dev) 0
-#endif
-
-/*
- * Local functions.
- */
-
-static int tgafb_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int tgafb_set_par(struct fb_info *);
-static void tgafb_set_pll(struct tga_par *, int);
-static int tgafb_setcolreg(unsigned, unsigned, unsigned, unsigned,
-			   unsigned, struct fb_info *);
-static int tgafb_blank(int, struct fb_info *);
-static void tgafb_init_fix(struct fb_info *);
-
-static void tgafb_imageblit(struct fb_info *, const struct fb_image *);
-static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
-static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
-static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
-
-static int tgafb_register(struct device *dev);
-static void tgafb_unregister(struct device *dev);
-
-static const char *mode_option;
-static const char *mode_option_pci = "640x480@60";
-static const char *mode_option_tc = "1280x1024@72";
-
-
-static struct pci_driver tgafb_pci_driver;
-static struct tc_driver tgafb_tc_driver;
-
-/*
- *  Frame buffer operations
- */
-
-static struct fb_ops tgafb_ops = {
-	.owner			= THIS_MODULE,
-	.fb_check_var		= tgafb_check_var,
-	.fb_set_par		= tgafb_set_par,
-	.fb_setcolreg		= tgafb_setcolreg,
-	.fb_blank		= tgafb_blank,
-	.fb_pan_display		= tgafb_pan_display,
-	.fb_fillrect		= tgafb_fillrect,
-	.fb_copyarea		= tgafb_copyarea,
-	.fb_imageblit		= tgafb_imageblit,
-};
-
-
-#ifdef CONFIG_PCI
-/*
- *  PCI registration operations
- */
-static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
-static void tgafb_pci_unregister(struct pci_dev *);
-
-static struct pci_device_id const tgafb_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, tgafb_pci_table);
-
-static struct pci_driver tgafb_pci_driver = {
-	.name			= "tgafb",
-	.id_table		= tgafb_pci_table,
-	.probe			= tgafb_pci_register,
-	.remove			= tgafb_pci_unregister,
-};
-
-static int tgafb_pci_register(struct pci_dev *pdev,
-			      const struct pci_device_id *ent)
-{
-	return tgafb_register(&pdev->dev);
-}
-
-static void tgafb_pci_unregister(struct pci_dev *pdev)
-{
-	tgafb_unregister(&pdev->dev);
-}
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_TC
-/*
- *  TC registration operations
- */
-static int tgafb_tc_register(struct device *);
-static int tgafb_tc_unregister(struct device *);
-
-static struct tc_device_id const tgafb_tc_table[] = {
-	{ "DEC     ", "PMAGD-AA" },
-	{ "DEC     ", "PMAGD   " },
-	{ }
-};
-MODULE_DEVICE_TABLE(tc, tgafb_tc_table);
-
-static struct tc_driver tgafb_tc_driver = {
-	.id_table		= tgafb_tc_table,
-	.driver			= {
-		.name		= "tgafb",
-		.bus		= &tc_bus_type,
-		.probe		= tgafb_tc_register,
-		.remove		= tgafb_tc_unregister,
-	},
-};
-
-static int tgafb_tc_register(struct device *dev)
-{
-	int status = tgafb_register(dev);
-	if (!status)
-		get_device(dev);
-	return status;
-}
-
-static int tgafb_tc_unregister(struct device *dev)
-{
-	put_device(dev);
-	tgafb_unregister(dev);
-	return 0;
-}
-#endif /* CONFIG_TC */
-
-
-/**
- *      tgafb_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct tga_par *par = (struct tga_par *)info->par;
-
-	if (par->tga_type == TGA_TYPE_8PLANE) {
-		if (var->bits_per_pixel != 8)
-			return -EINVAL;
-	} else {
-		if (var->bits_per_pixel != 32)
-			return -EINVAL;
-	}
-	var->red.length = var->green.length = var->blue.length = 8;
-	if (var->bits_per_pixel == 32) {
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-	}
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->xres * var->yres * (var->bits_per_pixel >> 3) > info->fix.smem_len)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if (1000000000 / var->pixclock > TGA_PLL_MAX_FREQ)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	/* Some of the acceleration routines assume the line width is
-	   a multiple of 8 bytes.  */
-	if (var->xres * (par->tga_type == TGA_TYPE_8PLANE ? 1 : 4) % 8)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      tgafb_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-tgafb_set_par(struct fb_info *info)
-{
-	static unsigned int const deep_presets[4] = {
-		0x00004000,
-		0x0000440d,
-		0xffffffff,
-		0x0000441d
-	};
-	static unsigned int const rasterop_presets[4] = {
-		0x00000003,
-		0x00000303,
-		0xffffffff,
-		0x00000303
-	};
-	static unsigned int const mode_presets[4] = {
-		0x00000000,
-		0x00000300,
-		0xffffffff,
-		0x00000300
-	};
-	static unsigned int const base_addr_presets[4] = {
-		0x00000000,
-		0x00000001,
-		0xffffffff,
-		0x00000001
-	};
-
-	struct tga_par *par = (struct tga_par *) info->par;
-	int tga_bus_pci = dev_is_pci(par->dev);
-	int tga_bus_tc = TGA_BUS_TC(par->dev);
-	u32 htimings, vtimings, pll_freq;
-	u8 tga_type;
-	int i;
-
-	/* Encode video timings.  */
-	htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
-		    | (((info->var.xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB));
-	vtimings = (info->var.yres & TGA_VERT_ACTIVE);
-	htimings |= ((info->var.right_margin/4) << 9) & TGA_HORIZ_FP;
-	vtimings |= (info->var.lower_margin << 11) & TGA_VERT_FP;
-	htimings |= ((info->var.hsync_len/4) << 14) & TGA_HORIZ_SYNC;
-	vtimings |= (info->var.vsync_len << 16) & TGA_VERT_SYNC;
-	htimings |= ((info->var.left_margin/4) << 21) & TGA_HORIZ_BP;
-	vtimings |= (info->var.upper_margin << 22) & TGA_VERT_BP;
-
-	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
-		htimings |= TGA_HORIZ_POLARITY;
-	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
-		vtimings |= TGA_VERT_POLARITY;
-
-	par->htimings = htimings;
-	par->vtimings = vtimings;
-
-	par->sync_on_green = !!(info->var.sync & FB_SYNC_ON_GREEN);
-
-	/* Store other useful values in par.  */
-	par->xres = info->var.xres;
-	par->yres = info->var.yres;
-	par->pll_freq = pll_freq = 1000000000 / info->var.pixclock;
-	par->bits_per_pixel = info->var.bits_per_pixel;
-	info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
-
-	tga_type = par->tga_type;
-
-	/* First, disable video.  */
-	TGA_WRITE_REG(par, TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
-
-	/* Write the DEEP register.  */
-	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
-		continue;
-	mb();
-	TGA_WRITE_REG(par, deep_presets[tga_type] |
-			   (par->sync_on_green ? 0x0 : 0x00010000),
-		      TGA_DEEP_REG);
-	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
-		continue;
-	mb();
-
-	/* Write some more registers.  */
-	TGA_WRITE_REG(par, rasterop_presets[tga_type], TGA_RASTEROP_REG);
-	TGA_WRITE_REG(par, mode_presets[tga_type], TGA_MODE_REG);
-	TGA_WRITE_REG(par, base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
-
-	/* Calculate & write the PLL.  */
-	tgafb_set_pll(par, pll_freq);
-
-	/* Write some more registers.  */
-	TGA_WRITE_REG(par, 0xffffffff, TGA_PLANEMASK_REG);
-	TGA_WRITE_REG(par, 0xffffffff, TGA_PIXELMASK_REG);
-
-	/* Init video timing regs.  */
-	TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
-	TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
-
-	/* Initialise RAMDAC. */
-	if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
-
-		/* Init BT485 RAMDAC registers.  */
-		BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0),
-			    BT485_CMD_0);
-		BT485_WRITE(par, 0x01, BT485_ADDR_PAL_WRITE);
-		BT485_WRITE(par, 0x14, BT485_CMD_3); /* cursor 64x64 */
-		BT485_WRITE(par, 0x40, BT485_CMD_1);
-		BT485_WRITE(par, 0x20, BT485_CMD_2); /* cursor off, for now */
-		BT485_WRITE(par, 0xff, BT485_PIXEL_MASK);
-
-		/* Fill palette registers.  */
-		BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
-		TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
-
-		for (i = 0; i < 256 * 3; i += 4) {
-			TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
-				      TGA_RAMDAC_REG);
-		}
-
-	} else if (tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
-
-		/* Init BT459 RAMDAC registers.  */
-		BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_0, 0x40);
-		BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_1, 0x00);
-		BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_2,
-			    (par->sync_on_green ? 0xc0 : 0x40));
-
-		BT459_WRITE(par, BT459_REG_ACC, BT459_CUR_CMD_REG, 0x00);
-
-		/* Fill the palette.  */
-		BT459_LOAD_ADDR(par, 0x0000);
-		TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
-
-		for (i = 0; i < 256 * 3; i += 4) {
-			TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-		}
-
-	} else { /* 24-plane or 24plusZ */
-
-		/* Init BT463 RAMDAC registers.  */
-		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
-			    (par->sync_on_green ? 0xc0 : 0x40));
-
-		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
-
-		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
-		BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
-
-		/* Fill the palette.  */
-		BT463_LOAD_ADDR(par, 0x0000);
-		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
-
-#ifdef CONFIG_HW_CONSOLE
-		for (i = 0; i < 16; i++) {
-			int j = color_table[i];
-
-			TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
-		}
-		for (i = 0; i < 512 * 3; i += 4) {
-#else
-		for (i = 0; i < 528 * 3; i += 4) {
-#endif
-			TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-		}
-
-		/* Fill window type table after start of vertical retrace.  */
-		while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
-			continue;
-		TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
-		mb();
-		while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
-			continue;
-		TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
-
-		BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
-		TGA_WRITE_REG(par, BT463_REG_ACC << 2, TGA_RAMDAC_SETUP_REG);
-
-		for (i = 0; i < 16; i++) {
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x01, TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
-		}
-
-	}
-
-	/* Finally, enable video scan (and pray for the monitor... :-) */
-	TGA_WRITE_REG(par, TGA_VALID_VIDEO, TGA_VALID_REG);
-
-	return 0;
-}
-
-#define DIFFCHECK(X)							  \
-do {									  \
-	if (m <= 0x3f) {						  \
-		int delta = f - (TGA_PLL_BASE_FREQ * (X)) / (r << shift); \
-		if (delta < 0)						  \
-			delta = -delta;					  \
-		if (delta < min_diff)					  \
-			min_diff = delta, vm = m, va = a, vr = r;	  \
-	}								  \
-} while (0)
-
-static void
-tgafb_set_pll(struct tga_par *par, int f)
-{
-	int n, shift, base, min_diff, target;
-	int r,a,m,vm = 34, va = 1, vr = 30;
-
-	for (r = 0 ; r < 12 ; r++)
-		TGA_WRITE_REG(par, !r, TGA_CLOCK_REG);
-
-	if (f > TGA_PLL_MAX_FREQ)
-		f = TGA_PLL_MAX_FREQ;
-
-	if (f >= TGA_PLL_MAX_FREQ / 2)
-		shift = 0;
-	else if (f >= TGA_PLL_MAX_FREQ / 4)
-		shift = 1;
-	else
-		shift = 2;
-
-	TGA_WRITE_REG(par, shift & 1, TGA_CLOCK_REG);
-	TGA_WRITE_REG(par, shift >> 1, TGA_CLOCK_REG);
-
-	for (r = 0 ; r < 10 ; r++)
-		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-
-	if (f <= 120000) {
-		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-	}
-	else if (f <= 200000) {
-		TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
-		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-	}
-	else {
-		TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-		TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
-	}
-
-	TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
-	TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-	TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-	TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
-	TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-	TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
-
-	target = (f << shift) / TGA_PLL_BASE_FREQ;
-	min_diff = TGA_PLL_MAX_FREQ;
-
-	r = 7 / target;
-	if (!r) r = 1;
-
-	base = target * r;
-	while (base < 449) {
-		for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) {
-			m = ((n + 3) / 7) - 1;
-			a = 0;
-			DIFFCHECK((m + 1) * 7);
-			m++;
-			DIFFCHECK((m + 1) * 7);
-			m = (n / 6) - 1;
-			if ((a = n % 6))
-				DIFFCHECK(n);
-		}
-		r++;
-		base += target;
-	}
-
-	vr--;
-
-	for (r = 0; r < 8; r++)
-		TGA_WRITE_REG(par, (vm >> r) & 1, TGA_CLOCK_REG);
-	for (r = 0; r < 8 ; r++)
-		TGA_WRITE_REG(par, (va >> r) & 1, TGA_CLOCK_REG);
-	for (r = 0; r < 7 ; r++)
-		TGA_WRITE_REG(par, (vr >> r) & 1, TGA_CLOCK_REG);
-	TGA_WRITE_REG(par, ((vr >> 7) & 1)|2, TGA_CLOCK_REG);
-}
-
-
-/**
- *      tgafb_setcolreg - Optional function. Sets a color register.
- *      @regno: boolean, 0 copy local, 1 get_user() function
- *      @red: frame buffer colormap structure
- *      @green: The green value which can be up to 16 bits wide
- *      @blue:  The blue value which can be up to 16 bits wide.
- *      @transp: If supported the alpha value which can be up to 16 bits wide.
- *      @info: frame buffer info structure
- */
-static int
-tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-		unsigned transp, struct fb_info *info)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	int tga_bus_pci = dev_is_pci(par->dev);
-	int tga_bus_tc = TGA_BUS_TC(par->dev);
-
-	if (regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
-		BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE);
-		TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
-		TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-		TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-		TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-	} else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) {
-		BT459_LOAD_ADDR(par, regno);
-		TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
-		TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
-		TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
-		TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
-	} else {
-		if (regno < 16) {
-			u32 value = (regno << 16) | (regno << 8) | regno;
-			((u32 *)info->pseudo_palette)[regno] = value;
-		}
-		BT463_LOAD_ADDR(par, regno);
-		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
-		TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
-		TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
-		TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
-	}
-
-	return 0;
-}
-
-
-/**
- *      tgafb_blank - Optional function.  Blanks the display.
- *      @blank_mode: the blank mode we want.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-tgafb_blank(int blank, struct fb_info *info)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	u32 vhcr, vvcr, vvvr;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	vhcr = TGA_READ_REG(par, TGA_HORIZ_REG);
-	vvcr = TGA_READ_REG(par, TGA_VERT_REG);
-	vvvr = TGA_READ_REG(par, TGA_VALID_REG);
-	vvvr &= ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK: /* Unblanking */
-		if (par->vesa_blanked) {
-			TGA_WRITE_REG(par, vhcr & 0xbfffffff, TGA_HORIZ_REG);
-			TGA_WRITE_REG(par, vvcr & 0xbfffffff, TGA_VERT_REG);
-			par->vesa_blanked = 0;
-		}
-		TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
-		break;
-
-	case FB_BLANK_NORMAL: /* Normal blanking */
-		TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK,
-			      TGA_VALID_REG);
-		break;
-
-	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
-		TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
-		TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
-		par->vesa_blanked = 1;
-		break;
-
-	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
-		TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
-		TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
-		par->vesa_blanked = 1;
-		break;
-
-	case FB_BLANK_POWERDOWN: /* Poweroff */
-		TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
-		TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
-		TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
-		par->vesa_blanked = 1;
-		break;
-	}
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-
-/*
- *  Acceleration.
- */
-
-static void
-tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
-	unsigned long rincr, line_length, shift, pos, is8bpp;
-	unsigned long i, j;
-	const unsigned char *data;
-	void __iomem *regs_base;
-	void __iomem *fb_base;
-
-	is8bpp = info->var.bits_per_pixel == 8;
-
-	dx = image->dx;
-	dy = image->dy;
-	width = image->width;
-	height = image->height;
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-	line_length = info->fix.line_length;
-	rincr = (width + 7) / 8;
-
-	/* A shift below cannot cope with.  */
-	if (unlikely(width == 0))
-		return;
-	/* Crop the image to the screen.  */
-	if (dx > vxres || dy > vyres)
-		return;
-	if (dx + width > vxres)
-		width = vxres - dx;
-	if (dy + height > vyres)
-		height = vyres - dy;
-
-	regs_base = par->tga_regs_base;
-	fb_base = par->tga_fb_base;
-
-	/* Expand the color values to fill 32-bits.  */
-	/* ??? Would be nice to notice colour changes elsewhere, so
-	   that we can do this only when necessary.  */
-	fgcolor = image->fg_color;
-	bgcolor = image->bg_color;
-	if (is8bpp) {
-		fgcolor |= fgcolor << 8;
-		fgcolor |= fgcolor << 16;
-		bgcolor |= bgcolor << 8;
-		bgcolor |= bgcolor << 16;
-	} else {
-		if (fgcolor < 16)
-			fgcolor = ((u32 *)info->pseudo_palette)[fgcolor];
-		if (bgcolor < 16)
-			bgcolor = ((u32 *)info->pseudo_palette)[bgcolor];
-	}
-	__raw_writel(fgcolor, regs_base + TGA_FOREGROUND_REG);
-	__raw_writel(bgcolor, regs_base + TGA_BACKGROUND_REG);
-
-	/* Acquire proper alignment; set up the PIXELMASK register
-	   so that we only write the proper character cell.  */
-	pos = dy * line_length;
-	if (is8bpp) {
-		pos += dx;
-		shift = pos & 3;
-		pos &= -4;
-	} else {
-		pos += dx * 4;
-		shift = (pos & 7) >> 2;
-		pos &= -8;
-	}
-
-	data = (const unsigned char *) image->data;
-
-	/* Enable opaque stipple mode.  */
-	__raw_writel((is8bpp
-		      ? TGA_MODE_SBM_8BPP | TGA_MODE_OPAQUE_STIPPLE
-		      : TGA_MODE_SBM_24BPP | TGA_MODE_OPAQUE_STIPPLE),
-		     regs_base + TGA_MODE_REG);
-
-	if (width + shift <= 32) {
-		unsigned long bwidth;
-
-		/* Handle common case of imaging a single character, in
-		   a font less than or 32 pixels wide.  */
-
-		/* Avoid a shift by 32; width > 0 implied.  */
-		pixelmask = (2ul << (width - 1)) - 1;
-		pixelmask <<= shift;
-		__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
-		wmb();
-
-		bwidth = (width + 7) / 8;
-
-		for (i = 0; i < height; ++i) {
-			u32 mask = 0;
-
-			/* The image data is bit big endian; we need
-			   little endian.  */
-			for (j = 0; j < bwidth; ++j)
-				mask |= bitrev8(data[j]) << (j * 8);
-
-			__raw_writel(mask << shift, fb_base + pos);
-
-			pos += line_length;
-			data += rincr;
-		}
-		wmb();
-		__raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
-	} else if (shift == 0) {
-		unsigned long pos0 = pos;
-		const unsigned char *data0 = data;
-		unsigned long bincr = (is8bpp ? 8 : 8*4);
-		unsigned long bwidth;
-
-		/* Handle another common case in which accel_putcs
-		   generates a large bitmap, which happens to be aligned.
-		   Allow the tail to be misaligned.  This case is 
-		   interesting because we've not got to hold partial
-		   bytes across the words being written.  */
-
-		wmb();
-
-		bwidth = (width / 8) & -4;
-		for (i = 0; i < height; ++i) {
-			for (j = 0; j < bwidth; j += 4) {
-				u32 mask = 0;
-				mask |= bitrev8(data[j+0]) << (0 * 8);
-				mask |= bitrev8(data[j+1]) << (1 * 8);
-				mask |= bitrev8(data[j+2]) << (2 * 8);
-				mask |= bitrev8(data[j+3]) << (3 * 8);
-				__raw_writel(mask, fb_base + pos + j*bincr);
-			}
-			pos += line_length;
-			data += rincr;
-		}
-		wmb();
-
-		pixelmask = (1ul << (width & 31)) - 1;
-		if (pixelmask) {
-			__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
-			wmb();
-
-			pos = pos0 + bwidth*bincr;
-			data = data0 + bwidth;
-			bwidth = ((width & 31) + 7) / 8;
-
-			for (i = 0; i < height; ++i) {
-				u32 mask = 0;
-				for (j = 0; j < bwidth; ++j)
-					mask |= bitrev8(data[j]) << (j * 8);
-				__raw_writel(mask, fb_base + pos);
-				pos += line_length;
-				data += rincr;
-			}
-			wmb();
-			__raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
-		}
-	} else {
-		unsigned long pos0 = pos;
-		const unsigned char *data0 = data;
-		unsigned long bincr = (is8bpp ? 8 : 8*4);
-		unsigned long bwidth;
-
-		/* Finally, handle the generic case of misaligned start.
-		   Here we split the write into 16-bit spans.  This allows
-		   us to use only one pixel mask, instead of four as would
-		   be required by writing 24-bit spans.  */
-
-		pixelmask = 0xffff << shift;
-		__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
-		wmb();
-
-		bwidth = (width / 8) & -2;
-		for (i = 0; i < height; ++i) {
-			for (j = 0; j < bwidth; j += 2) {
-				u32 mask = 0;
-				mask |= bitrev8(data[j+0]) << (0 * 8);
-				mask |= bitrev8(data[j+1]) << (1 * 8);
-				mask <<= shift;
-				__raw_writel(mask, fb_base + pos + j*bincr);
-			}
-			pos += line_length;
-			data += rincr;
-		}
-		wmb();
-
-		pixelmask = ((1ul << (width & 15)) - 1) << shift;
-		if (pixelmask) {
-			__raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
-			wmb();
-
-			pos = pos0 + bwidth*bincr;
-			data = data0 + bwidth;
-			bwidth = (width & 15) > 8;
-
-			for (i = 0; i < height; ++i) {
-				u32 mask = bitrev8(data[0]);
-				if (bwidth)
-					mask |= bitrev8(data[1]) << 8;
-				mask <<= shift;
-				__raw_writel(mask, fb_base + pos);
-				pos += line_length;
-				data += rincr;
-			}
-			wmb();
-		}
-		__raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG);
-	}
-
-	/* Disable opaque stipple mode.  */
-	__raw_writel((is8bpp
-		      ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
-		      : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
-		     regs_base + TGA_MODE_REG);
-}
-
-static void
-tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	u32 color, dx, dy, width, height, vxres, vyres;
-	u32 *palette = ((u32 *)info->pseudo_palette);
-	unsigned long pos, line_length, i, j;
-	const unsigned char *data;
-	void __iomem *regs_base, *fb_base;
-
-	dx = image->dx;
-	dy = image->dy;
-	width = image->width;
-	height = image->height;
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-	line_length = info->fix.line_length;
-
-	/* Crop the image to the screen.  */
-	if (dx > vxres || dy > vyres)
-		return;
-	if (dx + width > vxres)
-		width = vxres - dx;
-	if (dy + height > vyres)
-		height = vyres - dy;
-
-	regs_base = par->tga_regs_base;
-	fb_base = par->tga_fb_base;
-
-	pos = dy * line_length + (dx * 4);
-	data = image->data;
-
-	/* Now copy the image, color_expanding via the palette. */
-	for (i = 0; i < height; i++) {
-		for (j = 0; j < width; j++) {
-			color = palette[*data++];
-			__raw_writel(color, fb_base + pos + j*4);
-		}
-		pos += line_length;
-	}
-}
-
-/**
- *      tgafb_imageblit - REQUIRED function. Can use generic routines if
- *                        non acclerated hardware and packed pixel based.
- *                        Copies a image from system memory to the screen.
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *      @image: structure defining the image.
- */
-static void
-tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	unsigned int is8bpp = info->var.bits_per_pixel == 8;
-
-	/* If a mono image, regardless of FB depth, go do it. */
-	if (image->depth == 1) {
-		tgafb_mono_imageblit(info, image);
-		return;
-	}
-
-	/* For copies that aren't pixel expansion, there's little we
-	   can do better than the generic code.  */
-	/* ??? There is a DMA write mode; I wonder if that could be
-	   made to pull the data from the image buffer...  */
-	if (image->depth == info->var.bits_per_pixel) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	/* If 24-plane FB and the image is 8-plane with CLUT, we can do it. */
-	if (!is8bpp && image->depth == 8) {
-		tgafb_clut_imageblit(info, image);
-		return;
-	}
-
-	/* Silently return... */
-}
-
-/**
- *      tgafb_fillrect - REQUIRED function. Can use generic routines if 
- *                       non acclerated hardware and packed pixel based.
- *                       Draws a rectangle on the screen.               
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *      @rect: structure defining the rectagle and operation.
- */
-static void
-tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	int is8bpp = info->var.bits_per_pixel == 8;
-	u32 dx, dy, width, height, vxres, vyres, color;
-	unsigned long pos, align, line_length, i, j;
-	void __iomem *regs_base;
-	void __iomem *fb_base;
-
-	dx = rect->dx;
-	dy = rect->dy;
-	width = rect->width;
-	height = rect->height;
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-	line_length = info->fix.line_length;
-	regs_base = par->tga_regs_base;
-	fb_base = par->tga_fb_base;
-
-	/* Crop the rectangle to the screen.  */
-	if (dx > vxres || dy > vyres || !width || !height)
-		return;
-	if (dx + width > vxres)
-		width = vxres - dx;
-	if (dy + height > vyres)
-		height = vyres - dy;
-
-	pos = dy * line_length + dx * (is8bpp ? 1 : 4);
-
-	/* ??? We could implement ROP_XOR with opaque fill mode
-	   and a RasterOp setting of GXxor, but as far as I can
-	   tell, this mode is not actually used in the kernel.
-	   Thus I am ignoring it for now.  */
-	if (rect->rop != ROP_COPY) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	/* Expand the color value to fill 8 pixels.  */
-	color = rect->color;
-	if (is8bpp) {
-		color |= color << 8;
-		color |= color << 16;
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
-	} else {
-		if (color < 16)
-			color = ((u32 *)info->pseudo_palette)[color];
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR0_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR1_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR2_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR3_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR4_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR5_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR6_REG);
-		__raw_writel(color, regs_base + TGA_BLOCK_COLOR7_REG);
-	}
-
-	/* The DATA register holds the fill mask for block fill mode.
-	   Since we're not stippling, this is all ones.  */
-	__raw_writel(0xffffffff, regs_base + TGA_DATA_REG);
-
-	/* Enable block fill mode.  */
-	__raw_writel((is8bpp
-		      ? TGA_MODE_SBM_8BPP | TGA_MODE_BLOCK_FILL
-		      : TGA_MODE_SBM_24BPP | TGA_MODE_BLOCK_FILL),
-		     regs_base + TGA_MODE_REG);
-	wmb();
-
-	/* We can fill 2k pixels per operation.  Notice blocks that fit
-	   the width of the screen so that we can take advantage of this
-	   and fill more than one line per write.  */
-	if (width == line_length)
-		width *= height, height = 1;
-
-	/* The write into the frame buffer must be aligned to 4 bytes,
-	   but we are allowed to encode the offset within the word in
-	   the data word written.  */
-	align = (pos & 3) << 16;
-	pos &= -4;
-
-	if (width <= 2048) {
-		u32 data;
-
-		data = (width - 1) | align;
-
-		for (i = 0; i < height; ++i) {
-			__raw_writel(data, fb_base + pos);
-			pos += line_length;
-		}
-	} else {
-		unsigned long Bpp = (is8bpp ? 1 : 4);
-		unsigned long nwidth = width & -2048;
-		u32 fdata, ldata;
-
-		fdata = (2048 - 1) | align;
-		ldata = ((width & 2047) - 1) | align;
-
-		for (i = 0; i < height; ++i) {
-			for (j = 0; j < nwidth; j += 2048)
-				__raw_writel(fdata, fb_base + pos + j*Bpp);
-			if (j < width)
-				__raw_writel(ldata, fb_base + pos + j*Bpp);
-			pos += line_length;
-		}
-	}
-	wmb();
-
-	/* Disable block fill mode.  */
-	__raw_writel((is8bpp
-		      ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE
-		      : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE),
-		     regs_base + TGA_MODE_REG);
-}
-
-/**
- *      tgafb_copyarea - REQUIRED function. Can use generic routines if
- *                       non acclerated hardware and packed pixel based.
- *                       Copies on area of the screen to another area.
- *
- *      @info: frame buffer structure that represents a single frame buffer
- *      @area: structure defining the source and destination.
- */
-
-/* Handle the special case of copying entire lines, e.g. during scrolling.
-   We can avoid a lot of needless computation in this case.  In the 8bpp
-   case we need to use the COPY64 registers instead of mask writes into 
-   the frame buffer to achieve maximum performance.  */
-
-static inline void
-copyarea_line_8bpp(struct fb_info *info, u32 dy, u32 sy,
-		   u32 height, u32 width)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	void __iomem *tga_regs = par->tga_regs_base;
-	unsigned long dpos, spos, i, n64;
-
-	/* Set up the MODE and PIXELSHIFT registers.  */
-	__raw_writel(TGA_MODE_SBM_8BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
-	__raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
-	wmb();
-
-	n64 = (height * width) / 64;
-
-	if (sy < dy) {
-		spos = (sy + height) * width;
-		dpos = (dy + height) * width;
-
-		for (i = 0; i < n64; ++i) {
-			spos -= 64;
-			dpos -= 64;
-			__raw_writel(spos, tga_regs+TGA_COPY64_SRC);
-			wmb();
-			__raw_writel(dpos, tga_regs+TGA_COPY64_DST);
-			wmb();
-		}
-	} else {
-		spos = sy * width;
-		dpos = dy * width;
-
-		for (i = 0; i < n64; ++i) {
-			__raw_writel(spos, tga_regs+TGA_COPY64_SRC);
-			wmb();
-			__raw_writel(dpos, tga_regs+TGA_COPY64_DST);
-			wmb();
-			spos += 64;
-			dpos += 64;
-		}
-	}
-
-	/* Reset the MODE register to normal.  */
-	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
-}
-
-static inline void
-copyarea_line_32bpp(struct fb_info *info, u32 dy, u32 sy,
-		    u32 height, u32 width)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	void __iomem *tga_regs = par->tga_regs_base;
-	void __iomem *tga_fb = par->tga_fb_base;
-	void __iomem *src;
-	void __iomem *dst;
-	unsigned long i, n16;
-
-	/* Set up the MODE and PIXELSHIFT registers.  */
-	__raw_writel(TGA_MODE_SBM_24BPP | TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
-	__raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
-	wmb();
-
-	n16 = (height * width) / 16;
-
-	if (sy < dy) {
-		src = tga_fb + (sy + height) * width * 4;
-		dst = tga_fb + (dy + height) * width * 4;
-
-		for (i = 0; i < n16; ++i) {
-			src -= 64;
-			dst -= 64;
-			__raw_writel(0xffff, src);
-			wmb();
-			__raw_writel(0xffff, dst);
-			wmb();
-		}
-	} else {
-		src = tga_fb + sy * width * 4;
-		dst = tga_fb + dy * width * 4;
-
-		for (i = 0; i < n16; ++i) {
-			__raw_writel(0xffff, src);
-			wmb();
-			__raw_writel(0xffff, dst);
-			wmb();
-			src += 64;
-			dst += 64;
-		}
-	}
-
-	/* Reset the MODE register to normal.  */
-	__raw_writel(TGA_MODE_SBM_24BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
-}
-
-/* The (almost) general case of backward copy in 8bpp mode.  */
-static inline void
-copyarea_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
-	      u32 height, u32 width, u32 line_length,
-	      const struct fb_copyarea *area)
-{
-	struct tga_par *par = (struct tga_par *) info->par;
-	unsigned i, yincr;
-	int depos, sepos, backward, last_step, step;
-	u32 mask_last;
-	unsigned n32;
-	void __iomem *tga_regs;
-	void __iomem *tga_fb;
-
-	/* Do acceleration only if we are aligned on 8 pixels */
-	if ((dx | sx | width) & 7) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	yincr = line_length;
-	if (dy > sy) {
-		dy += height - 1;
-		sy += height - 1;
-		yincr = -yincr;
-	}
-	backward = dy == sy && dx > sx && dx < sx + width;
-
-	/* Compute the offsets and alignments in the frame buffer.
-	   More than anything else, these control how we do copies.  */
-	depos = dy * line_length + dx;
-	sepos = sy * line_length + sx;
-	if (backward)
-		depos += width, sepos += width;
-
-	/* Next copy full words at a time.  */
-	n32 = width / 32;
-	last_step = width % 32;
-
-	/* Finally copy the unaligned head of the span.  */
-	mask_last = (1ul << last_step) - 1;
-
-	if (!backward) {
-		step = 32;
-		last_step = 32;
-	} else {
-		step = -32;
-		last_step = -last_step;
-		sepos -= 32;
-		depos -= 32;
-	}
-
-	tga_regs = par->tga_regs_base;
-	tga_fb = par->tga_fb_base;
-
-	/* Set up the MODE and PIXELSHIFT registers.  */
-	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
-	__raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);
-	wmb();
-
-	for (i = 0; i < height; ++i) {
-		unsigned long j;
-		void __iomem *sfb;
-		void __iomem *dfb;
-
-		sfb = tga_fb + sepos;
-		dfb = tga_fb + depos;
-
-		for (j = 0; j < n32; j++) {
-			if (j < 2 && j + 1 < n32 && !backward &&
-			    !(((unsigned long)sfb | (unsigned long)dfb) & 63)) {
-				do {
-					__raw_writel(sfb - tga_fb, tga_regs+TGA_COPY64_SRC);
-					wmb();
-					__raw_writel(dfb - tga_fb, tga_regs+TGA_COPY64_DST);
-					wmb();
-					sfb += 64;
-					dfb += 64;
-					j += 2;
-				} while (j + 1 < n32);
-				j--;
-				continue;
-			}
-			__raw_writel(0xffffffff, sfb);
-			wmb();
-			__raw_writel(0xffffffff, dfb);
-			wmb();
-			sfb += step;
-			dfb += step;
-		}
-
-		if (mask_last) {
-			sfb += last_step - step;
-			dfb += last_step - step;
-			__raw_writel(mask_last, sfb);
-			wmb();
-			__raw_writel(mask_last, dfb);
-			wmb();
-		}
-
-		sepos += yincr;
-		depos += yincr;
-	}
-
-	/* Reset the MODE register to normal.  */
-	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
-}
-
-static void
-tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 
-{
-	unsigned long dx, dy, width, height, sx, sy, vxres, vyres;
-	unsigned long line_length, bpp;
-
-	dx = area->dx;
-	dy = area->dy;
-	width = area->width;
-	height = area->height;
-	sx = area->sx;
-	sy = area->sy;
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-	line_length = info->fix.line_length;
-
-	/* The top left corners must be in the virtual screen.  */
-	if (dx > vxres || sx > vxres || dy > vyres || sy > vyres)
-		return;
-
-	/* Clip the destination.  */
-	if (dx + width > vxres)
-		width = vxres - dx;
-	if (dy + height > vyres)
-		height = vyres - dy;
-
-	/* The source must be completely inside the virtual screen.  */
-	if (sx + width > vxres || sy + height > vyres)
-		return;
-
-	bpp = info->var.bits_per_pixel;
-
-	/* Detect copies of the entire line.  */
-	if (!(line_length & 63) && width * (bpp >> 3) == line_length) {
-		if (bpp == 8)
-			copyarea_line_8bpp(info, dy, sy, height, width);
-		else
-			copyarea_line_32bpp(info, dy, sy, height, width);
-	}
-
-	/* ??? The documentation is unclear to me exactly how the pixelshift
-	   register works in 32bpp mode.  Since I don't have hardware to test,
-	   give up for now and fall back on the generic routines.  */
-	else if (bpp == 32)
-		cfb_copyarea(info, area);
-
-	else
-		copyarea_8bpp(info, dx, dy, sx, sy, height,
-			      width, line_length, area);
-}
-
-
-/*
- *  Initialisation
- */
-
-static void
-tgafb_init_fix(struct fb_info *info)
-{
-	struct tga_par *par = (struct tga_par *)info->par;
-	int tga_bus_pci = dev_is_pci(par->dev);
-	int tga_bus_tc = TGA_BUS_TC(par->dev);
-	u8 tga_type = par->tga_type;
-	const char *tga_type_name = NULL;
-	unsigned memory_size;
-
-	switch (tga_type) {
-	case TGA_TYPE_8PLANE:
-		if (tga_bus_pci)
-			tga_type_name = "Digital ZLXp-E1";
-		if (tga_bus_tc)
-			tga_type_name = "Digital ZLX-E1";
-		memory_size = 2097152;
-		break;
-	case TGA_TYPE_24PLANE:
-		if (tga_bus_pci)
-			tga_type_name = "Digital ZLXp-E2";
-		if (tga_bus_tc)
-			tga_type_name = "Digital ZLX-E2";
-		memory_size = 8388608;
-		break;
-	case TGA_TYPE_24PLUSZ:
-		if (tga_bus_pci)
-			tga_type_name = "Digital ZLXp-E3";
-		if (tga_bus_tc)
-			tga_type_name = "Digital ZLX-E3";
-		memory_size = 16777216;
-		break;
-	}
-	if (!tga_type_name) {
-		tga_type_name = "Unknown";
-		memory_size = 16777216;
-	}
-
-	strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
-
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux = 0;
-	info->fix.visual = (tga_type == TGA_TYPE_8PLANE
-			    ? FB_VISUAL_PSEUDOCOLOR
-			    : FB_VISUAL_DIRECTCOLOR);
-
-	info->fix.smem_start = (size_t) par->tga_fb_base;
-	info->fix.smem_len = memory_size;
-	info->fix.mmio_start = (size_t) par->tga_regs_base;
-	info->fix.mmio_len = 512;
-
-	info->fix.xpanstep = 0;
-	info->fix.ypanstep = 0;
-	info->fix.ywrapstep = 0;
-
-	info->fix.accel = FB_ACCEL_DEC_TGA;
-
-	/*
-	 * These are needed by fb_set_logo_truepalette(), so we
-	 * set them here for 24-plane cards.
-	 */
-	if (tga_type != TGA_TYPE_8PLANE) {
-		info->var.red.length = 8;
-		info->var.green.length = 8;
-		info->var.blue.length = 8;
-		info->var.red.offset = 16;
-		info->var.green.offset = 8;
-		info->var.blue.offset = 0;
-	}
-}
-
-static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	/* We just use this to catch switches out of graphics mode. */
-	tgafb_set_par(info); /* A bit of overkill for BASE_ADDR reset. */
-	return 0;
-}
-
-static int tgafb_register(struct device *dev)
-{
-	static const struct fb_videomode modedb_tc = {
-		/* 1280x1024 @ 72 Hz, 76.8 kHz hsync */
-		"1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3,
-		FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED
-	};
-
-	static unsigned int const fb_offset_presets[4] = {
-		TGA_8PLANE_FB_OFFSET,
-		TGA_24PLANE_FB_OFFSET,
-		0xffffffff,
-		TGA_24PLUSZ_FB_OFFSET
-	};
-
-	const struct fb_videomode *modedb_tga = NULL;
-	resource_size_t bar0_start = 0, bar0_len = 0;
-	const char *mode_option_tga = NULL;
-	int tga_bus_pci = dev_is_pci(dev);
-	int tga_bus_tc = TGA_BUS_TC(dev);
-	unsigned int modedbsize_tga = 0;
-	void __iomem *mem_base;
-	struct fb_info *info;
-	struct tga_par *par;
-	u8 tga_type;
-	int ret = 0;
-
-	/* Enable device in PCI config.  */
-	if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) {
-		printk(KERN_ERR "tgafb: Cannot enable PCI device\n");
-		return -ENODEV;
-	}
-
-	/* Allocate the fb and par structures.  */
-	info = framebuffer_alloc(sizeof(struct tga_par), dev);
-	if (!info) {
-		printk(KERN_ERR "tgafb: Cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	dev_set_drvdata(dev, info);
-
-	/* Request the mem regions.  */
-	ret = -ENODEV;
-	if (tga_bus_pci) {
-		bar0_start = pci_resource_start(to_pci_dev(dev), 0);
-		bar0_len = pci_resource_len(to_pci_dev(dev), 0);
-	}
-	if (tga_bus_tc) {
-		bar0_start = to_tc_dev(dev)->resource.start;
-		bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
-	}
-	if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {
-		printk(KERN_ERR "tgafb: cannot reserve FB region\n");
-		goto err0;
-	}
-
-	/* Map the framebuffer.  */
-	mem_base = ioremap_nocache(bar0_start, bar0_len);
-	if (!mem_base) {
-		printk(KERN_ERR "tgafb: Cannot map MMIO\n");
-		goto err1;
-	}
-
-	/* Grab info about the card.  */
-	tga_type = (readl(mem_base) >> 12) & 0x0f;
-	par->dev = dev;
-	par->tga_mem_base = mem_base;
-	par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
-	par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
-	par->tga_type = tga_type;
-	if (tga_bus_pci)
-		par->tga_chip_rev = (to_pci_dev(dev))->revision;
-	if (tga_bus_tc)
-		par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
-
-	/* Setup framebuffer.  */
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
-		      FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
-	info->fbops = &tgafb_ops;
-	info->screen_base = par->tga_fb_base;
-	info->pseudo_palette = par->palette;
-
-	/* This should give a reasonable default video mode.  */
-	if (tga_bus_pci) {
-		mode_option_tga = mode_option_pci;
-	}
-	if (tga_bus_tc) {
-		mode_option_tga = mode_option_tc;
-		modedb_tga = &modedb_tc;
-		modedbsize_tga = 1;
-	}
-
-	tgafb_init_fix(info);
-
-	ret = fb_find_mode(&info->var, info,
-			   mode_option ? mode_option : mode_option_tga,
-			   modedb_tga, modedbsize_tga, NULL,
-			   tga_type == TGA_TYPE_8PLANE ? 8 : 32);
-	if (ret == 0 || ret == 4) {
-		printk(KERN_ERR "tgafb: Could not find valid video mode\n");
-		ret = -EINVAL;
-		goto err1;
-	}
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
-		printk(KERN_ERR "tgafb: Could not allocate color map\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	tgafb_set_par(info);
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "tgafb: Could not register framebuffer\n");
-		ret = -EINVAL;
-		goto err2;
-	}
-
-	if (tga_bus_pci) {
-		pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
-			par->tga_chip_rev);
-		pr_info("tgafb: at PCI bus %d, device %d, function %d\n",
-			to_pci_dev(dev)->bus->number,
-			PCI_SLOT(to_pci_dev(dev)->devfn),
-			PCI_FUNC(to_pci_dev(dev)->devfn));
-	}
-	if (tga_bus_tc)
-		pr_info("tgafb: SFB+ detected, rev=0x%02x\n",
-			par->tga_chip_rev);
-	fb_info(info, "%s frame buffer device at 0x%lx\n",
-		info->fix.id, (long)bar0_start);
-
-	return 0;
-
- err2:
-	fb_dealloc_cmap(&info->cmap);
- err1:
-	if (mem_base)
-		iounmap(mem_base);
-	release_mem_region(bar0_start, bar0_len);
- err0:
-	framebuffer_release(info);
-	return ret;
-}
-
-static void tgafb_unregister(struct device *dev)
-{
-	resource_size_t bar0_start = 0, bar0_len = 0;
-	int tga_bus_pci = dev_is_pci(dev);
-	int tga_bus_tc = TGA_BUS_TC(dev);
-	struct fb_info *info = NULL;
-	struct tga_par *par;
-
-	info = dev_get_drvdata(dev);
-	if (!info)
-		return;
-
-	par = info->par;
-	unregister_framebuffer(info);
-	fb_dealloc_cmap(&info->cmap);
-	iounmap(par->tga_mem_base);
-	if (tga_bus_pci) {
-		bar0_start = pci_resource_start(to_pci_dev(dev), 0);
-		bar0_len = pci_resource_len(to_pci_dev(dev), 0);
-	}
-	if (tga_bus_tc) {
-		bar0_start = to_tc_dev(dev)->resource.start;
-		bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;
-	}
-	release_mem_region(bar0_start, bar0_len);
-	framebuffer_release(info);
-}
-
-static void tgafb_exit(void)
-{
-	tc_unregister_driver(&tgafb_tc_driver);
-	pci_unregister_driver(&tgafb_pci_driver);
-}
-
-#ifndef MODULE
-static int tgafb_setup(char *arg)
-{
-	char *this_opt;
-
-	if (arg && *arg) {
-		while ((this_opt = strsep(&arg, ","))) {
-			if (!*this_opt)
-				continue;
-			if (!strncmp(this_opt, "mode:", 5))
-				mode_option = this_opt+5;
-			else
-				printk(KERN_ERR
-				       "tgafb: unknown parameter %s\n",
-				       this_opt);
-		}
-	}
-
-	return 0;
-}
-#endif /* !MODULE */
-
-static int tgafb_init(void)
-{
-	int status;
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("tgafb", &option))
-		return -ENODEV;
-	tgafb_setup(option);
-#endif
-	status = pci_register_driver(&tgafb_pci_driver);
-	if (!status)
-		status = tc_register_driver(&tgafb_tc_driver);
-	return status;
-}
-
-/*
- *  Modularisation
- */
-
-module_init(tgafb_init);
-module_exit(tgafb_exit);
-
-MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
deleted file mode 100644
index 7fb4e321a431..000000000000
--- a/drivers/video/tmiofb.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
- * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller
- *
- * Copyright(C) 2005-2006 Chris Humbert
- * Copyright(C) 2005 Dirk Opfer
- * Copytight(C) 2007,2008 Dmitry Baryshkov
- *
- * Based on:
- *	drivers/video/w100fb.c
- *	code written by Sharp/Lineo for 2.4 kernels
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-/* Why should fb driver call console functions? because console_lock() */
-#include <linux/console.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/tmio.h>
-#include <linux/uaccess.h>
-
-/*
- * accelerator commands
- */
-#define TMIOFB_ACC_CSADR(x)	(0x00000000 | ((x) & 0x001ffffe))
-#define TMIOFB_ACC_CHPIX(x)	(0x01000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_CVPIX(x)	(0x02000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_PSADR(x)	(0x03000000 | ((x) & 0x00fffffe))
-#define TMIOFB_ACC_PHPIX(x)	(0x04000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_PVPIX(x)	(0x05000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_PHOFS(x)	(0x06000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_PVOFS(x)	(0x07000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_POADR(x)	(0x08000000 | ((x) & 0x00fffffe))
-#define TMIOFB_ACC_RSTR(x)	(0x09000000 | ((x) & 0x000000ff))
-#define TMIOFB_ACC_TCLOR(x)	(0x0A000000 | ((x) & 0x0000ffff))
-#define TMIOFB_ACC_FILL(x)	(0x0B000000 | ((x) & 0x0000ffff))
-#define TMIOFB_ACC_DSADR(x)	(0x0C000000 | ((x) & 0x00fffffe))
-#define TMIOFB_ACC_SSADR(x)	(0x0D000000 | ((x) & 0x00fffffe))
-#define TMIOFB_ACC_DHPIX(x)	(0x0E000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_DVPIX(x)	(0x0F000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_SHPIX(x)	(0x10000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_SVPIX(x)	(0x11000000 | ((x) & 0x000003ff))
-#define TMIOFB_ACC_LBINI(x)	(0x12000000 | ((x) & 0x0000ffff))
-#define TMIOFB_ACC_LBK2(x)	(0x13000000 | ((x) & 0x0000ffff))
-#define TMIOFB_ACC_SHBINI(x)	(0x14000000 | ((x) & 0x0000ffff))
-#define TMIOFB_ACC_SHBK2(x)	(0x15000000 | ((x) & 0x0000ffff))
-#define TMIOFB_ACC_SVBINI(x)	(0x16000000 | ((x) & 0x0000ffff))
-#define TMIOFB_ACC_SVBK2(x)	(0x17000000 | ((x) & 0x0000ffff))
-
-#define TMIOFB_ACC_CMGO		0x20000000
-#define TMIOFB_ACC_CMGO_CEND	0x00000001
-#define TMIOFB_ACC_CMGO_INT	0x00000002
-#define TMIOFB_ACC_CMGO_CMOD	0x00000010
-#define TMIOFB_ACC_CMGO_CDVRV	0x00000020
-#define TMIOFB_ACC_CMGO_CDHRV	0x00000040
-#define TMIOFB_ACC_CMGO_RUND	0x00008000
-#define TMIOFB_ACC_SCGO		0x21000000
-#define TMIOFB_ACC_SCGO_CEND	0x00000001
-#define TMIOFB_ACC_SCGO_INT	0x00000002
-#define TMIOFB_ACC_SCGO_ROP3	0x00000004
-#define TMIOFB_ACC_SCGO_TRNS	0x00000008
-#define TMIOFB_ACC_SCGO_DVRV	0x00000010
-#define TMIOFB_ACC_SCGO_DHRV	0x00000020
-#define TMIOFB_ACC_SCGO_SVRV	0x00000040
-#define TMIOFB_ACC_SCGO_SHRV	0x00000080
-#define TMIOFB_ACC_SCGO_DSTXY	0x00008000
-#define TMIOFB_ACC_SBGO		0x22000000
-#define TMIOFB_ACC_SBGO_CEND	0x00000001
-#define TMIOFB_ACC_SBGO_INT	0x00000002
-#define TMIOFB_ACC_SBGO_DVRV	0x00000010
-#define TMIOFB_ACC_SBGO_DHRV	0x00000020
-#define TMIOFB_ACC_SBGO_SVRV	0x00000040
-#define TMIOFB_ACC_SBGO_SHRV	0x00000080
-#define TMIOFB_ACC_SBGO_SBMD	0x00000100
-#define TMIOFB_ACC_FLGO		0x23000000
-#define TMIOFB_ACC_FLGO_CEND	0x00000001
-#define TMIOFB_ACC_FLGO_INT	0x00000002
-#define TMIOFB_ACC_FLGO_ROP3	0x00000004
-#define TMIOFB_ACC_LDGO		0x24000000
-#define TMIOFB_ACC_LDGO_CEND	0x00000001
-#define TMIOFB_ACC_LDGO_INT	0x00000002
-#define TMIOFB_ACC_LDGO_ROP3	0x00000004
-#define TMIOFB_ACC_LDGO_ENDPX	0x00000008
-#define TMIOFB_ACC_LDGO_LVRV	0x00000010
-#define TMIOFB_ACC_LDGO_LHRV	0x00000020
-#define TMIOFB_ACC_LDGO_LDMOD	0x00000040
-
-/* a FIFO is always allocated, even if acceleration is not used */
-#define TMIOFB_FIFO_SIZE	512
-
-/*
- * LCD Host Controller Configuration Register
- *
- * This iomem area supports only 16-bit IO.
- */
-#define CCR_CMD			0x04 /* Command				*/
-#define CCR_REVID		0x08 /* Revision ID			*/
-#define CCR_BASEL		0x10 /* LCD Control Reg Base Addr Low	*/
-#define CCR_BASEH		0x12 /* LCD Control Reg Base Addr High	*/
-#define CCR_UGCC		0x40 /* Unified Gated Clock Control	*/
-#define CCR_GCC			0x42 /* Gated Clock Control		*/
-#define CCR_USC			0x50 /* Unified Software Clear		*/
-#define CCR_VRAMRTC		0x60 /* VRAM Timing Control		*/
-				/* 0x61 VRAM Refresh Control		*/
-#define CCR_VRAMSAC		0x62 /* VRAM Access Control		*/
-				/* 0x63	VRAM Status			*/
-#define CCR_VRAMBC		0x64 /* VRAM Block Control		*/
-
-/*
- * LCD Control Register
- *
- * This iomem area supports only 16-bit IO.
- */
-#define LCR_UIS			0x000 /* Unified Interrupt Status	*/
-#define LCR_VHPN		0x008 /* VRAM Horizontal Pixel Number	*/
-#define LCR_CFSAL		0x00a /* Command FIFO Start Address Low	*/
-#define LCR_CFSAH		0x00c /* Command FIFO Start Address High */
-#define LCR_CFS			0x00e /* Command FIFO Size		*/
-#define LCR_CFWS		0x010 /* Command FIFO Writeable Size	*/
-#define LCR_BBIE		0x012 /* BitBLT Interrupt Enable	*/
-#define LCR_BBISC		0x014 /* BitBLT Interrupt Status and Clear */
-#define LCR_CCS			0x016 /* Command Count Status		*/
-#define LCR_BBES		0x018 /* BitBLT Execution Status	*/
-#define LCR_CMDL		0x01c /* Command Low			*/
-#define LCR_CMDH		0x01e /* Command High			*/
-#define LCR_CFC			0x022 /* Command FIFO Clear		*/
-#define LCR_CCIFC		0x024 /* CMOS Camera IF Control		*/
-#define LCR_HWT			0x026 /* Hardware Test			*/
-#define LCR_LCDCCRC		0x100 /* LCDC Clock and Reset Control	*/
-#define LCR_LCDCC		0x102 /* LCDC Control			*/
-#define LCR_LCDCOPC		0x104 /* LCDC Output Pin Control	*/
-#define LCR_LCDIS		0x108 /* LCD Interrupt Status		*/
-#define LCR_LCDIM		0x10a /* LCD Interrupt Mask		*/
-#define LCR_LCDIE		0x10c /* LCD Interrupt Enable		*/
-#define LCR_GDSAL		0x122 /* Graphics Display Start Address Low */
-#define LCR_GDSAH		0x124 /* Graphics Display Start Address High */
-#define LCR_VHPCL		0x12a /* VRAM Horizontal Pixel Count Low */
-#define LCR_VHPCH		0x12c /* VRAM Horizontal Pixel Count High */
-#define LCR_GM			0x12e /* Graphic Mode(VRAM access enable) */
-#define LCR_HT			0x140 /* Horizontal Total		*/
-#define LCR_HDS			0x142 /* Horizontal Display Start	*/
-#define LCR_HSS			0x144 /* H-Sync Start			*/
-#define LCR_HSE			0x146 /* H-Sync End			*/
-#define LCR_HNP			0x14c /* Horizontal Number of Pixels	*/
-#define LCR_VT			0x150 /* Vertical Total			*/
-#define LCR_VDS			0x152 /* Vertical Display Start		*/
-#define LCR_VSS			0x154 /* V-Sync Start			*/
-#define LCR_VSE			0x156 /* V-Sync End			*/
-#define LCR_CDLN		0x160 /* Current Display Line Number	*/
-#define LCR_ILN			0x162 /* Interrupt Line Number		*/
-#define LCR_SP			0x164 /* Sync Polarity			*/
-#define LCR_MISC		0x166 /* MISC(RGB565 mode)		*/
-#define LCR_VIHSS		0x16a /* Video Interface H-Sync Start	*/
-#define LCR_VIVS		0x16c /* Video Interface Vertical Start	*/
-#define LCR_VIVE		0x16e /* Video Interface Vertical End	*/
-#define LCR_VIVSS		0x170 /* Video Interface V-Sync Start	*/
-#define LCR_VCCIS		0x17e /* Video / CMOS Camera Interface Select */
-#define LCR_VIDWSAL		0x180 /* VI Data Write Start Address Low */
-#define LCR_VIDWSAH		0x182 /* VI Data Write Start Address High */
-#define LCR_VIDRSAL		0x184 /* VI Data Read Start Address Low	*/
-#define LCR_VIDRSAH		0x186 /* VI Data Read Start Address High */
-#define LCR_VIPDDST		0x188 /* VI Picture Data Display Start Timing */
-#define LCR_VIPDDET		0x186 /* VI Picture Data Display End Timing */
-#define LCR_VIE			0x18c /* Video Interface Enable		*/
-#define LCR_VCS			0x18e /* Video/Camera Select		*/
-#define LCR_VPHWC		0x194 /* Video Picture Horizontal Wait Count */
-#define LCR_VPHS		0x196 /* Video Picture Horizontal Size	*/
-#define LCR_VPVWC		0x198 /* Video Picture Vertical Wait Count */
-#define LCR_VPVS		0x19a /* Video Picture Vertical Size	*/
-#define LCR_PLHPIX		0x1a0 /* PLHPIX				*/
-#define LCR_XS			0x1a2 /* XStart				*/
-#define LCR_XCKHW		0x1a4 /* XCK High Width			*/
-#define LCR_STHS		0x1a8 /* STH Start			*/
-#define LCR_VT2			0x1aa /* Vertical Total			*/
-#define LCR_YCKSW		0x1ac /* YCK Start Wait			*/
-#define LCR_YSTS		0x1ae /* YST Start			*/
-#define LCR_PPOLS		0x1b0 /* #PPOL Start			*/
-#define LCR_PRECW		0x1b2 /* PREC Width			*/
-#define LCR_VCLKHW		0x1b4 /* VCLK High Width		*/
-#define LCR_OC			0x1b6 /* Output Control			*/
-
-static char *mode_option;
-
-struct tmiofb_par {
-	u32				pseudo_palette[16];
-
-#ifdef CONFIG_FB_TMIO_ACCELL
-	wait_queue_head_t		wait_acc;
-	bool				use_polling;
-#endif
-
-	void __iomem			*ccr;
-	void __iomem			*lcr;
-};
-
-/*--------------------------------------------------------------------------*/
-
-/*
- * reasons for an interrupt:
- *	uis	bbisc	lcdis
- *	0100	0001	accelerator command completed
- * 	2000	0001	vsync start
- * 	2000	0002	display start
- * 	2000	0004	line number match(0x1ff mask???)
- */
-static irqreturn_t tmiofb_irq(int irq, void *__info)
-{
-	struct fb_info *info = __info;
-	struct tmiofb_par *par = info->par;
-	unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
-
-
-	tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
-
-#ifdef CONFIG_FB_TMIO_ACCELL
-	/*
-	 * We were in polling mode and now we got correct irq.
-	 * Switch back to IRQ-based sync of command FIFO
-	 */
-	if (unlikely(par->use_polling && irq != -1)) {
-		printk(KERN_INFO "tmiofb: switching to waitq\n");
-		par->use_polling = false;
-	}
-
-	if (bbisc & 1)
-		wake_up(&par->wait_acc);
-#endif
-
-	return IRQ_HANDLED;
-}
-
-
-/*--------------------------------------------------------------------------*/
-
-
-/*
- * Turns off the LCD controller and LCD host controller.
- */
-static int tmiofb_hw_stop(struct platform_device *dev)
-{
-	struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct tmiofb_par *par = info->par;
-
-	tmio_iowrite16(0, par->ccr + CCR_UGCC);
-	tmio_iowrite16(0, par->lcr + LCR_GM);
-	data->lcd_set_power(dev, 0);
-	tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
-
-	return 0;
-}
-
-/*
- * Initializes the LCD host controller.
- */
-static int tmiofb_hw_init(struct platform_device *dev)
-{
-	const struct mfd_cell *cell = mfd_get_cell(dev);
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct tmiofb_par *par = info->par;
-	const struct resource *nlcr = &cell->resources[0];
-	const struct resource *vram = &cell->resources[2];
-	unsigned long base;
-
-	if (nlcr == NULL || vram == NULL)
-		return -EINVAL;
-
-	base = nlcr->start;
-
-	tmio_iowrite16(0x003a, par->ccr + CCR_UGCC);
-	tmio_iowrite16(0x003a, par->ccr + CCR_GCC);
-	tmio_iowrite16(0x3f00, par->ccr + CCR_USC);
-
-	msleep(2); /* wait for device to settle */
-
-	tmio_iowrite16(0x0000, par->ccr + CCR_USC);
-	tmio_iowrite16(base >> 16, par->ccr + CCR_BASEH);
-	tmio_iowrite16(base, par->ccr + CCR_BASEL);
-	tmio_iowrite16(0x0002, par->ccr + CCR_CMD); /* base address enable */
-	tmio_iowrite16(0x40a8, par->ccr + CCR_VRAMRTC); /* VRAMRC, VRAMTC */
-	tmio_iowrite16(0x0018, par->ccr + CCR_VRAMSAC); /* VRAMSTS, VRAMAC */
-	tmio_iowrite16(0x0002, par->ccr + CCR_VRAMBC);
-	msleep(2); /* wait for device to settle */
-	tmio_iowrite16(0x000b, par->ccr + CCR_VRAMBC);
-
-	base = vram->start + info->screen_size;
-	tmio_iowrite16(base >> 16, par->lcr + LCR_CFSAH);
-	tmio_iowrite16(base, par->lcr + LCR_CFSAL);
-	tmio_iowrite16(TMIOFB_FIFO_SIZE - 1, par->lcr + LCR_CFS);
-	tmio_iowrite16(1, par->lcr + LCR_CFC);
-	tmio_iowrite16(1, par->lcr + LCR_BBIE);
-	tmio_iowrite16(0, par->lcr + LCR_CFWS);
-
-	return 0;
-}
-
-/*
- * Sets the LCD controller's output resolution and pixel clock
- */
-static void tmiofb_hw_mode(struct platform_device *dev)
-{
-	struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct fb_videomode *mode = info->mode;
-	struct tmiofb_par *par = info->par;
-	unsigned int i;
-
-	tmio_iowrite16(0, par->lcr + LCR_GM);
-	data->lcd_set_power(dev, 0);
-	tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
-	data->lcd_mode(dev, mode);
-	data->lcd_set_power(dev, 1);
-
-	tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPN);
-	tmio_iowrite16(0, par->lcr + LCR_GDSAH);
-	tmio_iowrite16(0, par->lcr + LCR_GDSAL);
-	tmio_iowrite16(info->fix.line_length >> 16, par->lcr + LCR_VHPCH);
-	tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPCL);
-	tmio_iowrite16(i = 0, par->lcr + LCR_HSS);
-	tmio_iowrite16(i += mode->hsync_len, par->lcr + LCR_HSE);
-	tmio_iowrite16(i += mode->left_margin, par->lcr + LCR_HDS);
-	tmio_iowrite16(i += mode->xres + mode->right_margin, par->lcr + LCR_HT);
-	tmio_iowrite16(mode->xres, par->lcr + LCR_HNP);
-	tmio_iowrite16(i = 0, par->lcr + LCR_VSS);
-	tmio_iowrite16(i += mode->vsync_len, par->lcr + LCR_VSE);
-	tmio_iowrite16(i += mode->upper_margin, par->lcr + LCR_VDS);
-	tmio_iowrite16(i += mode->yres, par->lcr + LCR_ILN);
-	tmio_iowrite16(i += mode->lower_margin, par->lcr + LCR_VT);
-	tmio_iowrite16(3, par->lcr + LCR_MISC); /* RGB565 mode */
-	tmio_iowrite16(1, par->lcr + LCR_GM); /* VRAM enable */
-	tmio_iowrite16(0x4007, par->lcr + LCR_LCDCC);
-	tmio_iowrite16(3, par->lcr + LCR_SP);  /* sync polarity */
-
-	tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
-	msleep(5); /* wait for device to settle */
-	tmio_iowrite16(0x0014, par->lcr + LCR_LCDCCRC); /* STOP_CKP */
-	msleep(5); /* wait for device to settle */
-	tmio_iowrite16(0x0015, par->lcr + LCR_LCDCCRC); /* STOP_CKP|SOFT_RESET*/
-	tmio_iowrite16(0xfffa, par->lcr + LCR_VCS);
-}
-
-/*--------------------------------------------------------------------------*/
-
-#ifdef CONFIG_FB_TMIO_ACCELL
-static int __must_check
-tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
-{
-	struct tmiofb_par *par = info->par;
-	/*
-	 * This code can be called with interrupts disabled.
-	 * So instead of relaying on irq to trigger the event,
-	 * poll the state till the necessary command is executed.
-	 */
-	if (irqs_disabled() || par->use_polling) {
-		int i = 0;
-		while (tmio_ioread16(par->lcr + LCR_CCS) > ccs) {
-			udelay(1);
-			i++;
-			if (i > 10000) {
-				pr_err("tmiofb: timeout waiting for %d\n",
-						ccs);
-				return -ETIMEDOUT;
-			}
-			tmiofb_irq(-1, info);
-		}
-	} else {
-		if (!wait_event_interruptible_timeout(par->wait_acc,
-				tmio_ioread16(par->lcr + LCR_CCS) <= ccs,
-				1000)) {
-			pr_err("tmiofb: timeout waiting for %d\n", ccs);
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Writes an accelerator command to the accelerator's FIFO.
- */
-static int
-tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count)
-{
-	struct tmiofb_par *par = info->par;
-	int ret;
-
-	ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count);
-	if (ret)
-		return ret;
-
-	for (; count; count--, cmd++) {
-		tmio_iowrite16(*cmd >> 16, par->lcr + LCR_CMDH);
-		tmio_iowrite16(*cmd, par->lcr + LCR_CMDL);
-	}
-
-	return ret;
-}
-
-/*
- * Wait for the accelerator to finish its operations before writing
- * to the framebuffer for consistent display output.
- */
-static int tmiofb_sync(struct fb_info *fbi)
-{
-	struct tmiofb_par *par = fbi->par;
-
-	int ret;
-	int i = 0;
-
-	ret = tmiofb_acc_wait(fbi, 0);
-
-	while (tmio_ioread16(par->lcr + LCR_BBES) & 2) { /* blit active */
-		udelay(1);
-		i++ ;
-		if (i > 10000) {
-			printk(KERN_ERR "timeout waiting for blit to end!\n");
-			return -ETIMEDOUT;
-		}
-	}
-
-	return ret;
-}
-
-static void
-tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect)
-{
-	const u32 cmd[] = {
-		TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2),
-		TMIOFB_ACC_DHPIX(rect->width - 1),
-		TMIOFB_ACC_DVPIX(rect->height - 1),
-		TMIOFB_ACC_FILL(rect->color),
-		TMIOFB_ACC_FLGO,
-	};
-
-	if (fbi->state != FBINFO_STATE_RUNNING ||
-	    fbi->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(fbi, rect);
-		return;
-	}
-
-	tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
-}
-
-static void
-tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area)
-{
-	const u32 cmd[] = {
-		TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2),
-		TMIOFB_ACC_DHPIX(area->width - 1),
-		TMIOFB_ACC_DVPIX(area->height - 1),
-		TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2),
-		TMIOFB_ACC_SCGO,
-	};
-
-	if (fbi->state != FBINFO_STATE_RUNNING ||
-	    fbi->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(fbi, area);
-		return;
-	}
-
-	tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
-}
-#endif
-
-static void tmiofb_clearscreen(struct fb_info *info)
-{
-	const struct fb_fillrect rect = {
-		.dx	= 0,
-		.dy	= 0,
-		.width	= info->mode->xres,
-		.height	= info->mode->yres,
-		.color	= 0,
-		.rop	= ROP_COPY,
-	};
-
-	info->fbops->fb_fillrect(info, &rect);
-}
-
-static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank)
-{
-	struct tmiofb_par *par = fbi->par;
-	struct fb_videomode *mode = fbi->mode;
-	unsigned int vcount = tmio_ioread16(par->lcr + LCR_CDLN);
-	unsigned int vds = mode->vsync_len + mode->upper_margin;
-
-	vblank->vcount = vcount;
-	vblank->flags = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT
-						| FB_VBLANK_HAVE_VSYNC;
-
-	if (vcount < mode->vsync_len)
-		vblank->flags |= FB_VBLANK_VSYNCING;
-
-	if (vcount < vds || vcount > vds + mode->yres)
-		vblank->flags |= FB_VBLANK_VBLANKING;
-
-	return 0;
-}
-
-
-static int tmiofb_ioctl(struct fb_info *fbi,
-		unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case FBIOGET_VBLANK: {
-		struct fb_vblank vblank = {0};
-		void __user *argp = (void __user *) arg;
-
-		tmiofb_vblank(fbi, &vblank);
-		if (copy_to_user(argp, &vblank, sizeof vblank))
-			return -EFAULT;
-		return 0;
-	}
-
-#ifdef CONFIG_FB_TMIO_ACCELL
-	case FBIO_TMIO_ACC_SYNC:
-		tmiofb_sync(fbi);
-		return 0;
-
-	case FBIO_TMIO_ACC_WRITE: {
-		u32 __user *argp = (void __user *) arg;
-		u32 len;
-		u32 acc[16];
-
-		if (get_user(len, argp))
-			return -EFAULT;
-		if (len > ARRAY_SIZE(acc))
-			return -EINVAL;
-		if (copy_from_user(acc, argp + 1, sizeof(u32) * len))
-			return -EFAULT;
-
-		return tmiofb_acc_write(fbi, acc, len);
-	}
-#endif
-	}
-
-	return -ENOTTY;
-}
-
-/*--------------------------------------------------------------------------*/
-
-/* Select the smallest mode that allows the desired resolution to be
- * displayed.  If desired, the x and y parameters can be rounded up to
- * match the selected mode.
- */
-static struct fb_videomode *
-tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
-{
-	struct tmio_fb_data *data = dev_get_platdata(info->device);
-	struct fb_videomode *best = NULL;
-	int i;
-
-	for (i = 0; i < data->num_modes; i++) {
-		struct fb_videomode *mode = data->modes + i;
-
-		if (mode->xres >= var->xres && mode->yres >= var->yres
-				&& (!best || (mode->xres < best->xres
-					   && mode->yres < best->yres)))
-			best = mode;
-	}
-
-	return best;
-}
-
-static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-
-	struct fb_videomode *mode;
-	struct tmio_fb_data *data = dev_get_platdata(info->device);
-
-	mode = tmiofb_find_mode(info, var);
-	if (!mode || var->bits_per_pixel > 16)
-		return -EINVAL;
-
-	fb_videomode_to_var(var, mode);
-
-	var->xres_virtual = mode->xres;
-	var->yres_virtual = info->screen_size / (mode->xres * 2);
-
-	if (var->yres_virtual < var->yres)
-		return -EINVAL;
-
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->bits_per_pixel = 16;
-	var->grayscale = 0;
-	var->red.offset = 11;
-	var->red.length = 5;
-	var->green.offset = 5;
-	var->green.length = 6;
-	var->blue.offset = 0;
-	var->blue.length = 5;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->nonstd = 0;
-	var->height = data->height; /* mm */
-	var->width = data->width; /* mm */
-	var->rotate = 0;
-	return 0;
-}
-
-static int tmiofb_set_par(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &info->var;
-	struct fb_videomode *mode;
-
-	mode = tmiofb_find_mode(info, var);
-	if (!mode)
-		return -EINVAL;
-
-	info->mode = mode;
-	info->fix.line_length = info->mode->xres *
-			var->bits_per_pixel / 8;
-
-	tmiofb_hw_mode(to_platform_device(info->device));
-	tmiofb_clearscreen(info);
-	return 0;
-}
-
-static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct tmiofb_par *par = info->par;
-
-	if (regno < ARRAY_SIZE(par->pseudo_palette)) {
-		par->pseudo_palette[regno] =
-			((red & 0xf800)) |
-			((green & 0xfc00) >>  5) |
-			((blue & 0xf800) >> 11);
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int tmiofb_blank(int blank, struct fb_info *info)
-{
-	/*
-	 * everything is done in lcd/bl drivers.
-	 * this is purely to make sysfs happy and work.
-	 */
-	return 0;
-}
-
-static struct fb_ops tmiofb_ops = {
-	.owner		= THIS_MODULE,
-
-	.fb_ioctl	= tmiofb_ioctl,
-	.fb_check_var	= tmiofb_check_var,
-	.fb_set_par	= tmiofb_set_par,
-	.fb_setcolreg	= tmiofb_setcolreg,
-	.fb_blank	= tmiofb_blank,
-	.fb_imageblit	= cfb_imageblit,
-#ifdef CONFIG_FB_TMIO_ACCELL
-	.fb_sync	= tmiofb_sync,
-	.fb_fillrect	= tmiofb_fillrect,
-	.fb_copyarea	= tmiofb_copyarea,
-#else
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-#endif
-};
-
-/*--------------------------------------------------------------------------*/
-
-static int tmiofb_probe(struct platform_device *dev)
-{
-	const struct mfd_cell *cell = mfd_get_cell(dev);
-	struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
-	struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
-	struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
-	int irq = platform_get_irq(dev, 0);
-	struct fb_info *info;
-	struct tmiofb_par *par;
-	int retval;
-
-	/*
-	 * This is the only way ATM to disable the fb
-	 */
-	if (data == NULL) {
-		dev_err(&dev->dev, "NULL platform data!\n");
-		return -EINVAL;
-	}
-	if (ccr == NULL || lcr == NULL || vram == NULL || irq < 0) {
-		dev_err(&dev->dev, "missing resources\n");
-		return -EINVAL;
-	}
-
-	info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev);
-
-	if (!info)
-		return -ENOMEM;
-
-	par = info->par;
-
-#ifdef CONFIG_FB_TMIO_ACCELL
-	init_waitqueue_head(&par->wait_acc);
-
-	par->use_polling = true;
-
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA
-			| FBINFO_HWACCEL_FILLRECT;
-#else
-	info->flags = FBINFO_DEFAULT;
-#endif
-
-	info->fbops = &tmiofb_ops;
-
-	strcpy(info->fix.id, "tmio-fb");
-	info->fix.smem_start = vram->start;
-	info->fix.smem_len = resource_size(vram);
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-	info->fix.mmio_start = lcr->start;
-	info->fix.mmio_len = resource_size(lcr);
-	info->fix.accel = FB_ACCEL_NONE;
-	info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE);
-	info->pseudo_palette = par->pseudo_palette;
-
-	par->ccr = ioremap(ccr->start, resource_size(ccr));
-	if (!par->ccr) {
-		retval = -ENOMEM;
-		goto err_ioremap_ccr;
-	}
-
-	par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len);
-	if (!par->lcr) {
-		retval = -ENOMEM;
-		goto err_ioremap_lcr;
-	}
-
-	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-	if (!info->screen_base) {
-		retval = -ENOMEM;
-		goto err_ioremap_vram;
-	}
-
-	retval = request_irq(irq, &tmiofb_irq, 0,
-					dev_name(&dev->dev), info);
-
-	if (retval)
-		goto err_request_irq;
-
-	platform_set_drvdata(dev, info);
-
-	retval = fb_find_mode(&info->var, info, mode_option,
-			data->modes, data->num_modes,
-			data->modes, 16);
-	if (!retval) {
-		retval = -EINVAL;
-		goto err_find_mode;
-	}
-
-	if (cell->enable) {
-		retval = cell->enable(dev);
-		if (retval)
-			goto err_enable;
-	}
-
-	retval = tmiofb_hw_init(dev);
-	if (retval)
-		goto err_hw_init;
-
-	fb_videomode_to_modelist(data->modes, data->num_modes,
-				 &info->modelist);
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err_register_framebuffer;
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	return 0;
-
-err_register_framebuffer:
-/*err_set_par:*/
-	tmiofb_hw_stop(dev);
-err_hw_init:
-	if (cell->disable)
-		cell->disable(dev);
-err_enable:
-err_find_mode:
-	free_irq(irq, info);
-err_request_irq:
-	iounmap(info->screen_base);
-err_ioremap_vram:
-	iounmap(par->lcr);
-err_ioremap_lcr:
-	iounmap(par->ccr);
-err_ioremap_ccr:
-	framebuffer_release(info);
-	return retval;
-}
-
-static int tmiofb_remove(struct platform_device *dev)
-{
-	const struct mfd_cell *cell = mfd_get_cell(dev);
-	struct fb_info *info = platform_get_drvdata(dev);
-	int irq = platform_get_irq(dev, 0);
-	struct tmiofb_par *par;
-
-	if (info) {
-		par = info->par;
-		unregister_framebuffer(info);
-
-		tmiofb_hw_stop(dev);
-
-		if (cell->disable)
-			cell->disable(dev);
-
-		free_irq(irq, info);
-
-		iounmap(info->screen_base);
-		iounmap(par->lcr);
-		iounmap(par->ccr);
-
-		framebuffer_release(info);
-	}
-
-	return 0;
-}
-
-#ifdef DEBUG
-static void tmiofb_dump_regs(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct tmiofb_par *par = info->par;
-
-	printk(KERN_DEBUG "lhccr:\n");
-#define CCR_PR(n)	printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
-		tmio_ioread16(par->ccr + CCR_ ## n));
-	CCR_PR(CMD);
-	CCR_PR(REVID);
-	CCR_PR(BASEL);
-	CCR_PR(BASEH);
-	CCR_PR(UGCC);
-	CCR_PR(GCC);
-	CCR_PR(USC);
-	CCR_PR(VRAMRTC);
-	CCR_PR(VRAMSAC);
-	CCR_PR(VRAMBC);
-#undef CCR_PR
-
-	printk(KERN_DEBUG "lcr: \n");
-#define LCR_PR(n)	printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
-		tmio_ioread16(par->lcr + LCR_ ## n));
-	LCR_PR(UIS);
-	LCR_PR(VHPN);
-	LCR_PR(CFSAL);
-	LCR_PR(CFSAH);
-	LCR_PR(CFS);
-	LCR_PR(CFWS);
-	LCR_PR(BBIE);
-	LCR_PR(BBISC);
-	LCR_PR(CCS);
-	LCR_PR(BBES);
-	LCR_PR(CMDL);
-	LCR_PR(CMDH);
-	LCR_PR(CFC);
-	LCR_PR(CCIFC);
-	LCR_PR(HWT);
-	LCR_PR(LCDCCRC);
-	LCR_PR(LCDCC);
-	LCR_PR(LCDCOPC);
-	LCR_PR(LCDIS);
-	LCR_PR(LCDIM);
-	LCR_PR(LCDIE);
-	LCR_PR(GDSAL);
-	LCR_PR(GDSAH);
-	LCR_PR(VHPCL);
-	LCR_PR(VHPCH);
-	LCR_PR(GM);
-	LCR_PR(HT);
-	LCR_PR(HDS);
-	LCR_PR(HSS);
-	LCR_PR(HSE);
-	LCR_PR(HNP);
-	LCR_PR(VT);
-	LCR_PR(VDS);
-	LCR_PR(VSS);
-	LCR_PR(VSE);
-	LCR_PR(CDLN);
-	LCR_PR(ILN);
-	LCR_PR(SP);
-	LCR_PR(MISC);
-	LCR_PR(VIHSS);
-	LCR_PR(VIVS);
-	LCR_PR(VIVE);
-	LCR_PR(VIVSS);
-	LCR_PR(VCCIS);
-	LCR_PR(VIDWSAL);
-	LCR_PR(VIDWSAH);
-	LCR_PR(VIDRSAL);
-	LCR_PR(VIDRSAH);
-	LCR_PR(VIPDDST);
-	LCR_PR(VIPDDET);
-	LCR_PR(VIE);
-	LCR_PR(VCS);
-	LCR_PR(VPHWC);
-	LCR_PR(VPHS);
-	LCR_PR(VPVWC);
-	LCR_PR(VPVS);
-	LCR_PR(PLHPIX);
-	LCR_PR(XS);
-	LCR_PR(XCKHW);
-	LCR_PR(STHS);
-	LCR_PR(VT2);
-	LCR_PR(YCKSW);
-	LCR_PR(YSTS);
-	LCR_PR(PPOLS);
-	LCR_PR(PRECW);
-	LCR_PR(VCLKHW);
-	LCR_PR(OC);
-#undef LCR_PR
-}
-#endif
-
-#ifdef CONFIG_PM
-static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-#ifdef CONFIG_FB_TMIO_ACCELL
-	struct tmiofb_par *par = info->par;
-#endif
-	const struct mfd_cell *cell = mfd_get_cell(dev);
-	int retval = 0;
-
-	console_lock();
-
-	fb_set_suspend(info, 1);
-
-	if (info->fbops->fb_sync)
-		info->fbops->fb_sync(info);
-
-
-#ifdef CONFIG_FB_TMIO_ACCELL
-	/*
-	 * The fb should be usable even if interrupts are disabled (and they are
-	 * during suspend/resume). Switch temporary to forced polling.
-	 */
-	printk(KERN_INFO "tmiofb: switching to polling\n");
-	par->use_polling = true;
-#endif
-	tmiofb_hw_stop(dev);
-
-	if (cell->suspend)
-		retval = cell->suspend(dev);
-
-	console_unlock();
-
-	return retval;
-}
-
-static int tmiofb_resume(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	const struct mfd_cell *cell = mfd_get_cell(dev);
-	int retval = 0;
-
-	console_lock();
-
-	if (cell->resume) {
-		retval = cell->resume(dev);
-		if (retval)
-			goto out;
-	}
-
-	tmiofb_irq(-1, info);
-
-	tmiofb_hw_init(dev);
-
-	tmiofb_hw_mode(dev);
-
-	fb_set_suspend(info, 0);
-out:
-	console_unlock();
-	return retval;
-}
-#else
-#define tmiofb_suspend	NULL
-#define tmiofb_resume	NULL
-#endif
-
-static struct platform_driver tmiofb_driver = {
-	.driver.name	= "tmio-fb",
-	.driver.owner	= THIS_MODULE,
-	.probe		= tmiofb_probe,
-	.remove		= tmiofb_remove,
-	.suspend	= tmiofb_suspend,
-	.resume		= tmiofb_resume,
-};
-
-/*--------------------------------------------------------------------------*/
-
-#ifndef MODULE
-static void __init tmiofb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		/*
-		 * FIXME
-		 */
-	}
-}
-#endif
-
-static int __init tmiofb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("tmiofb", &option))
-		return -ENODEV;
-	tmiofb_setup(option);
-#endif
-	return platform_driver_register(&tmiofb_driver);
-}
-
-static void __exit tmiofb_cleanup(void)
-{
-	platform_driver_unregister(&tmiofb_driver);
-}
-
-module_init(tmiofb_init);
-module_exit(tmiofb_cleanup);
-
-MODULE_DESCRIPTION("TMIO framebuffer driver");
-MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
deleted file mode 100644
index 7ed9a227f5ea..000000000000
--- a/drivers/video/tridentfb.c
+++ /dev/null
@@ -1,1659 +0,0 @@
-/*
- * Frame buffer driver for Trident TGUI, Blade and Image series
- *
- * Copyright 2001, 2002 - Jani Monoses   <jani@iv.ro>
- * Copyright 2009 Krzysztof Helt <krzysztof.h1@wp.pl>
- *
- * CREDITS:(in order of appearance)
- *	skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video
- *	Special thanks ;) to Mattia Crivellini <tia@mclink.it>
- *	much inspired by the XFree86 4.x Trident driver sources
- *	by Alan Hourihane the FreeVGA project
- *	Francesco Salvestrini <salvestrini@users.sf.net> XP support,
- *	code, suggestions
- * TODO:
- *	timing value tweaking so it looks good on every monitor in every mode
- */
-
-#include <linux/module.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <linux/delay.h>
-#include <video/vga.h>
-#include <video/trident.h>
-
-struct tridentfb_par {
-	void __iomem *io_virt;	/* iospace virtual memory address */
-	u32 pseudo_pal[16];
-	int chip_id;
-	int flatpanel;
-	void (*init_accel) (struct tridentfb_par *, int, int);
-	void (*wait_engine) (struct tridentfb_par *);
-	void (*fill_rect)
-		(struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
-	void (*copy_rect)
-		(struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
-	void (*image_blit)
-		(struct tridentfb_par *par, const char*,
-		 u32, u32, u32, u32, u32, u32);
-	unsigned char eng_oper;	/* engine operation... */
-};
-
-static struct fb_fix_screeninfo tridentfb_fix = {
-	.id = "Trident",
-	.type = FB_TYPE_PACKED_PIXELS,
-	.ypanstep = 1,
-	.visual = FB_VISUAL_PSEUDOCOLOR,
-	.accel = FB_ACCEL_NONE,
-};
-
-/* defaults which are normally overriden by user values */
-
-/* video mode */
-static char *mode_option = "640x480-8@60";
-static int bpp = 8;
-
-static int noaccel;
-
-static int center;
-static int stretch;
-
-static int fp;
-static int crt;
-
-static int memsize;
-static int memdiff;
-static int nativex;
-
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
-module_param_named(mode, mode_option, charp, 0);
-MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8@60' (deprecated)");
-module_param(bpp, int, 0);
-module_param(center, int, 0);
-module_param(stretch, int, 0);
-module_param(noaccel, int, 0);
-module_param(memsize, int, 0);
-module_param(memdiff, int, 0);
-module_param(nativex, int, 0);
-module_param(fp, int, 0);
-MODULE_PARM_DESC(fp, "Define if flatpanel is connected");
-module_param(crt, int, 0);
-MODULE_PARM_DESC(crt, "Define if CRT is connected");
-
-static inline int is_oldclock(int id)
-{
-	return	(id == TGUI9440) ||
-		(id == TGUI9660) ||
-		(id == CYBER9320);
-}
-
-static inline int is_oldprotect(int id)
-{
-	return	is_oldclock(id) ||
-		(id == PROVIDIA9685) ||
-		(id == CYBER9382) ||
-		(id == CYBER9385);
-}
-
-static inline int is_blade(int id)
-{
-	return	(id == BLADE3D) ||
-		(id == CYBERBLADEE4) ||
-		(id == CYBERBLADEi7) ||
-		(id == CYBERBLADEi7D) ||
-		(id == CYBERBLADEi1) ||
-		(id == CYBERBLADEi1D) ||
-		(id == CYBERBLADEAi1) ||
-		(id == CYBERBLADEAi1D);
-}
-
-static inline int is_xp(int id)
-{
-	return	(id == CYBERBLADEXPAi1) ||
-		(id == CYBERBLADEXPm8) ||
-		(id == CYBERBLADEXPm16);
-}
-
-static inline int is3Dchip(int id)
-{
-	return	is_blade(id) || is_xp(id) ||
-		(id == CYBER9397) || (id == CYBER9397DVD) ||
-		(id == CYBER9520) || (id == CYBER9525DVD) ||
-		(id == IMAGE975) || (id == IMAGE985);
-}
-
-static inline int iscyber(int id)
-{
-	switch (id) {
-	case CYBER9388:
-	case CYBER9382:
-	case CYBER9385:
-	case CYBER9397:
-	case CYBER9397DVD:
-	case CYBER9520:
-	case CYBER9525DVD:
-	case CYBERBLADEE4:
-	case CYBERBLADEi7D:
-	case CYBERBLADEi1:
-	case CYBERBLADEi1D:
-	case CYBERBLADEAi1:
-	case CYBERBLADEAi1D:
-	case CYBERBLADEXPAi1:
-		return 1;
-
-	case CYBER9320:
-	case CYBERBLADEi7:	/* VIA MPV4 integrated version */
-	default:
-		/* case CYBERBLDAEXPm8:  Strange */
-		/* case CYBERBLDAEXPm16: Strange */
-		return 0;
-	}
-}
-
-static inline void t_outb(struct tridentfb_par *p, u8 val, u16 reg)
-{
-	fb_writeb(val, p->io_virt + reg);
-}
-
-static inline u8 t_inb(struct tridentfb_par *p, u16 reg)
-{
-	return fb_readb(p->io_virt + reg);
-}
-
-static inline void writemmr(struct tridentfb_par *par, u16 r, u32 v)
-{
-	fb_writel(v, par->io_virt + r);
-}
-
-static inline u32 readmmr(struct tridentfb_par *par, u16 r)
-{
-	return fb_readl(par->io_virt + r);
-}
-
-/*
- * Blade specific acceleration.
- */
-
-#define point(x, y) ((y) << 16 | (x))
-
-static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp)
-{
-	int v1 = (pitch >> 3) << 20;
-	int tmp = bpp == 24 ? 2 : (bpp >> 4);
-	int v2 = v1 | (tmp << 29);
-
-	writemmr(par, 0x21C0, v2);
-	writemmr(par, 0x21C4, v2);
-	writemmr(par, 0x21B8, v2);
-	writemmr(par, 0x21BC, v2);
-	writemmr(par, 0x21D0, v1);
-	writemmr(par, 0x21D4, v1);
-	writemmr(par, 0x21C8, v1);
-	writemmr(par, 0x21CC, v1);
-	writemmr(par, 0x216C, 0);
-}
-
-static void blade_wait_engine(struct tridentfb_par *par)
-{
-	while (readmmr(par, STATUS) & 0xFA800000)
-		cpu_relax();
-}
-
-static void blade_fill_rect(struct tridentfb_par *par,
-			    u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
-{
-	writemmr(par, COLOR, c);
-	writemmr(par, ROP, rop ? ROP_X : ROP_S);
-	writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
-
-	writemmr(par, DST1, point(x, y));
-	writemmr(par, DST2, point(x + w - 1, y + h - 1));
-}
-
-static void blade_image_blit(struct tridentfb_par *par, const char *data,
-			     u32 x, u32 y, u32 w, u32 h, u32 c, u32 b)
-{
-	unsigned size = ((w + 31) >> 5) * h;
-
-	writemmr(par, COLOR, c);
-	writemmr(par, BGCOLOR, b);
-	writemmr(par, CMD, 0xa0000000 | 3 << 19);
-
-	writemmr(par, DST1, point(x, y));
-	writemmr(par, DST2, point(x + w - 1, y + h - 1));
-
-	memcpy(par->io_virt + 0x10000, data, 4 * size);
-}
-
-static void blade_copy_rect(struct tridentfb_par *par,
-			    u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
-{
-	int direction = 2;
-	u32 s1 = point(x1, y1);
-	u32 s2 = point(x1 + w - 1, y1 + h - 1);
-	u32 d1 = point(x2, y2);
-	u32 d2 = point(x2 + w - 1, y2 + h - 1);
-
-	if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
-		direction = 0;
-
-	writemmr(par, ROP, ROP_S);
-	writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
-
-	writemmr(par, SRC1, direction ? s2 : s1);
-	writemmr(par, SRC2, direction ? s1 : s2);
-	writemmr(par, DST1, direction ? d2 : d1);
-	writemmr(par, DST2, direction ? d1 : d2);
-}
-
-/*
- * BladeXP specific acceleration functions
- */
-
-static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp)
-{
-	unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
-	int v1 = pitch << (bpp == 24 ? 20 : (18 + x));
-
-	switch (pitch << (bpp >> 3)) {
-	case 8192:
-	case 512:
-		x |= 0x00;
-		break;
-	case 1024:
-		x |= 0x04;
-		break;
-	case 2048:
-		x |= 0x08;
-		break;
-	case 4096:
-		x |= 0x0C;
-		break;
-	}
-
-	t_outb(par, x, 0x2125);
-
-	par->eng_oper = x | 0x40;
-
-	writemmr(par, 0x2154, v1);
-	writemmr(par, 0x2150, v1);
-	t_outb(par, 3, 0x2126);
-}
-
-static void xp_wait_engine(struct tridentfb_par *par)
-{
-	int count = 0;
-	int timeout = 0;
-
-	while (t_inb(par, STATUS) & 0x80) {
-		count++;
-		if (count == 10000000) {
-			/* Timeout */
-			count = 9990000;
-			timeout++;
-			if (timeout == 8) {
-				/* Reset engine */
-				t_outb(par, 0x00, STATUS);
-				return;
-			}
-		}
-		cpu_relax();
-	}
-}
-
-static void xp_fill_rect(struct tridentfb_par *par,
-			 u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
-{
-	writemmr(par, 0x2127, ROP_P);
-	writemmr(par, 0x2158, c);
-	writemmr(par, DRAWFL, 0x4000);
-	writemmr(par, OLDDIM, point(h, w));
-	writemmr(par, OLDDST, point(y, x));
-	t_outb(par, 0x01, OLDCMD);
-	t_outb(par, par->eng_oper, 0x2125);
-}
-
-static void xp_copy_rect(struct tridentfb_par *par,
-			 u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
-{
-	u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
-	int direction = 0x0004;
-
-	if ((x1 < x2) && (y1 == y2)) {
-		direction |= 0x0200;
-		x1_tmp = x1 + w - 1;
-		x2_tmp = x2 + w - 1;
-	} else {
-		x1_tmp = x1;
-		x2_tmp = x2;
-	}
-
-	if (y1 < y2) {
-		direction |= 0x0100;
-		y1_tmp = y1 + h - 1;
-		y2_tmp = y2 + h - 1;
-	} else {
-		y1_tmp = y1;
-		y2_tmp = y2;
-	}
-
-	writemmr(par, DRAWFL, direction);
-	t_outb(par, ROP_S, 0x2127);
-	writemmr(par, OLDSRC, point(y1_tmp, x1_tmp));
-	writemmr(par, OLDDST, point(y2_tmp, x2_tmp));
-	writemmr(par, OLDDIM, point(h, w));
-	t_outb(par, 0x01, OLDCMD);
-}
-
-/*
- * Image specific acceleration functions
- */
-static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp)
-{
-	int tmp = bpp == 24 ? 2: (bpp >> 4);
-
-	writemmr(par, 0x2120, 0xF0000000);
-	writemmr(par, 0x2120, 0x40000000 | tmp);
-	writemmr(par, 0x2120, 0x80000000);
-	writemmr(par, 0x2144, 0x00000000);
-	writemmr(par, 0x2148, 0x00000000);
-	writemmr(par, 0x2150, 0x00000000);
-	writemmr(par, 0x2154, 0x00000000);
-	writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch);
-	writemmr(par, 0x216C, 0x00000000);
-	writemmr(par, 0x2170, 0x00000000);
-	writemmr(par, 0x217C, 0x00000000);
-	writemmr(par, 0x2120, 0x10000000);
-	writemmr(par, 0x2130, (2047 << 16) | 2047);
-}
-
-static void image_wait_engine(struct tridentfb_par *par)
-{
-	while (readmmr(par, 0x2164) & 0xF0000000)
-		cpu_relax();
-}
-
-static void image_fill_rect(struct tridentfb_par *par,
-			    u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
-{
-	writemmr(par, 0x2120, 0x80000000);
-	writemmr(par, 0x2120, 0x90000000 | ROP_S);
-
-	writemmr(par, 0x2144, c);
-
-	writemmr(par, DST1, point(x, y));
-	writemmr(par, DST2, point(x + w - 1, y + h - 1));
-
-	writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
-}
-
-static void image_copy_rect(struct tridentfb_par *par,
-			    u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
-{
-	int direction = 0x4;
-	u32 s1 = point(x1, y1);
-	u32 s2 = point(x1 + w - 1, y1 + h - 1);
-	u32 d1 = point(x2, y2);
-	u32 d2 = point(x2 + w - 1, y2 + h - 1);
-
-	if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
-		direction = 0;
-
-	writemmr(par, 0x2120, 0x80000000);
-	writemmr(par, 0x2120, 0x90000000 | ROP_S);
-
-	writemmr(par, SRC1, direction ? s2 : s1);
-	writemmr(par, SRC2, direction ? s1 : s2);
-	writemmr(par, DST1, direction ? d2 : d1);
-	writemmr(par, DST2, direction ? d1 : d2);
-	writemmr(par, 0x2124,
-		 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
-}
-
-/*
- * TGUI 9440/96XX acceleration
- */
-
-static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp)
-{
-	unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
-
-	/* disable clipping */
-	writemmr(par, 0x2148, 0);
-	writemmr(par, 0x214C, point(4095, 2047));
-
-	switch ((pitch * bpp) / 8) {
-	case 8192:
-	case 512:
-		x |= 0x00;
-		break;
-	case 1024:
-		x |= 0x04;
-		break;
-	case 2048:
-		x |= 0x08;
-		break;
-	case 4096:
-		x |= 0x0C;
-		break;
-	}
-
-	fb_writew(x, par->io_virt + 0x2122);
-}
-
-static void tgui_fill_rect(struct tridentfb_par *par,
-			   u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
-{
-	t_outb(par, ROP_P, 0x2127);
-	writemmr(par, OLDCLR, c);
-	writemmr(par, DRAWFL, 0x4020);
-	writemmr(par, OLDDIM, point(w - 1, h - 1));
-	writemmr(par, OLDDST, point(x, y));
-	t_outb(par, 1, OLDCMD);
-}
-
-static void tgui_copy_rect(struct tridentfb_par *par,
-			   u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
-{
-	int flags = 0;
-	u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
-
-	if ((x1 < x2) && (y1 == y2)) {
-		flags |= 0x0200;
-		x1_tmp = x1 + w - 1;
-		x2_tmp = x2 + w - 1;
-	} else {
-		x1_tmp = x1;
-		x2_tmp = x2;
-	}
-
-	if (y1 < y2) {
-		flags |= 0x0100;
-		y1_tmp = y1 + h - 1;
-		y2_tmp = y2 + h - 1;
-	} else {
-		y1_tmp = y1;
-		y2_tmp = y2;
-	}
-
-	writemmr(par, DRAWFL, 0x4 | flags);
-	t_outb(par, ROP_S, 0x2127);
-	writemmr(par, OLDSRC, point(x1_tmp, y1_tmp));
-	writemmr(par, OLDDST, point(x2_tmp, y2_tmp));
-	writemmr(par, OLDDIM, point(w - 1, h - 1));
-	t_outb(par, 1, OLDCMD);
-}
-
-/*
- * Accel functions called by the upper layers
- */
-static void tridentfb_fillrect(struct fb_info *info,
-			       const struct fb_fillrect *fr)
-{
-	struct tridentfb_par *par = info->par;
-	int col;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(info, fr);
-		return;
-	}
-	if (info->var.bits_per_pixel == 8) {
-		col = fr->color;
-		col |= col << 8;
-		col |= col << 16;
-	} else
-		col = ((u32 *)(info->pseudo_palette))[fr->color];
-
-	par->wait_engine(par);
-	par->fill_rect(par, fr->dx, fr->dy, fr->width,
-		       fr->height, col, fr->rop);
-}
-
-static void tridentfb_imageblit(struct fb_info *info,
-				const struct fb_image *img)
-{
-	struct tridentfb_par *par = info->par;
-	int col, bgcol;
-
-	if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) {
-		cfb_imageblit(info, img);
-		return;
-	}
-	if (info->var.bits_per_pixel == 8) {
-		col = img->fg_color;
-		col |= col << 8;
-		col |= col << 16;
-		bgcol = img->bg_color;
-		bgcol |= bgcol << 8;
-		bgcol |= bgcol << 16;
-	} else {
-		col = ((u32 *)(info->pseudo_palette))[img->fg_color];
-		bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color];
-	}
-
-	par->wait_engine(par);
-	if (par->image_blit)
-		par->image_blit(par, img->data, img->dx, img->dy,
-				img->width, img->height, col, bgcol);
-	else
-		cfb_imageblit(info, img);
-}
-
-static void tridentfb_copyarea(struct fb_info *info,
-			       const struct fb_copyarea *ca)
-{
-	struct tridentfb_par *par = info->par;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, ca);
-		return;
-	}
-	par->wait_engine(par);
-	par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy,
-		       ca->width, ca->height);
-}
-
-static int tridentfb_sync(struct fb_info *info)
-{
-	struct tridentfb_par *par = info->par;
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
-		par->wait_engine(par);
-	return 0;
-}
-
-/*
- * Hardware access functions
- */
-
-static inline unsigned char read3X4(struct tridentfb_par *par, int reg)
-{
-	return vga_mm_rcrt(par->io_virt, reg);
-}
-
-static inline void write3X4(struct tridentfb_par *par, int reg,
-			    unsigned char val)
-{
-	vga_mm_wcrt(par->io_virt, reg, val);
-}
-
-static inline unsigned char read3CE(struct tridentfb_par *par,
-				    unsigned char reg)
-{
-	return vga_mm_rgfx(par->io_virt, reg);
-}
-
-static inline void writeAttr(struct tridentfb_par *par, int reg,
-			     unsigned char val)
-{
-	fb_readb(par->io_virt + VGA_IS1_RC);	/* flip-flop to index */
-	vga_mm_wattr(par->io_virt, reg, val);
-}
-
-static inline void write3CE(struct tridentfb_par *par, int reg,
-			    unsigned char val)
-{
-	vga_mm_wgfx(par->io_virt, reg, val);
-}
-
-static void enable_mmio(struct tridentfb_par *par)
-{
-	/* Goto New Mode */
-	vga_io_rseq(0x0B);
-
-	/* Unprotect registers */
-	vga_io_wseq(NewMode1, 0x80);
-	if (!is_oldprotect(par->chip_id))
-		vga_io_wseq(Protection, 0x92);
-
-	/* Enable MMIO */
-	outb(PCIReg, 0x3D4);
-	outb(inb(0x3D5) | 0x01, 0x3D5);
-}
-
-static void disable_mmio(struct tridentfb_par *par)
-{
-	/* Goto New Mode */
-	vga_mm_rseq(par->io_virt, 0x0B);
-
-	/* Unprotect registers */
-	vga_mm_wseq(par->io_virt, NewMode1, 0x80);
-	if (!is_oldprotect(par->chip_id))
-		vga_mm_wseq(par->io_virt, Protection, 0x92);
-
-	/* Disable MMIO */
-	t_outb(par, PCIReg, 0x3D4);
-	t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);
-}
-
-static inline void crtc_unlock(struct tridentfb_par *par)
-{
-	write3X4(par, VGA_CRTC_V_SYNC_END,
-		 read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F);
-}
-
-/*  Return flat panel's maximum x resolution */
-static int get_nativex(struct tridentfb_par *par)
-{
-	int x, y, tmp;
-
-	if (nativex)
-		return nativex;
-
-	tmp = (read3CE(par, VertStretch) >> 4) & 3;
-
-	switch (tmp) {
-	case 0:
-		x = 1280; y = 1024;
-		break;
-	case 2:
-		x = 1024; y = 768;
-		break;
-	case 3:
-		x = 800; y = 600;
-		break;
-	case 4:
-		x = 1400; y = 1050;
-		break;
-	case 1:
-	default:
-		x = 640;  y = 480;
-		break;
-	}
-
-	output("%dx%d flat panel found\n", x, y);
-	return x;
-}
-
-/* Set pitch */
-static inline void set_lwidth(struct tridentfb_par *par, int width)
-{
-	write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);
-	write3X4(par, AddColReg,
-		 (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
-}
-
-/* For resolutions smaller than FP resolution stretch */
-static void screen_stretch(struct tridentfb_par *par)
-{
-	if (par->chip_id != CYBERBLADEXPAi1)
-		write3CE(par, BiosReg, 0);
-	else
-		write3CE(par, BiosReg, 8);
-	write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1);
-	write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1);
-}
-
-/* For resolutions smaller than FP resolution center */
-static inline void screen_center(struct tridentfb_par *par)
-{
-	write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80);
-	write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80);
-}
-
-/* Address of first shown pixel in display memory */
-static void set_screen_start(struct tridentfb_par *par, int base)
-{
-	u8 tmp;
-	write3X4(par, VGA_CRTC_START_LO, base & 0xFF);
-	write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8);
-	tmp = read3X4(par, CRTCModuleTest) & 0xDF;
-	write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11));
-	tmp = read3X4(par, CRTHiOrd) & 0xF8;
-	write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17));
-}
-
-/* Set dotclock frequency */
-static void set_vclk(struct tridentfb_par *par, unsigned long freq)
-{
-	int m, n, k;
-	unsigned long fi, d, di;
-	unsigned char best_m = 0, best_n = 0, best_k = 0;
-	unsigned char hi, lo;
-	unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1;
-
-	d = 20000;
-	for (k = shift; k >= 0; k--)
-		for (m = 1; m < 32; m++) {
-			n = ((m + 2) << shift) - 8;
-			for (n = (n < 0 ? 0 : n); n < 122; n++) {
-				fi = ((14318l * (n + 8)) / (m + 2)) >> k;
-				di = abs(fi - freq);
-				if (di < d || (di == d && k == best_k)) {
-					d = di;
-					best_n = n;
-					best_m = m;
-					best_k = k;
-				}
-				if (fi > freq)
-					break;
-			}
-		}
-
-	if (is_oldclock(par->chip_id)) {
-		lo = best_n | (best_m << 7);
-		hi = (best_m >> 1) | (best_k << 4);
-	} else {
-		lo = best_n;
-		hi = best_m | (best_k << 6);
-	}
-
-	if (is3Dchip(par->chip_id)) {
-		vga_mm_wseq(par->io_virt, ClockHigh, hi);
-		vga_mm_wseq(par->io_virt, ClockLow, lo);
-	} else {
-		t_outb(par, lo, 0x43C8);
-		t_outb(par, hi, 0x43C9);
-	}
-	debug("VCLK = %X %X\n", hi, lo);
-}
-
-/* Set number of lines for flat panels*/
-static void set_number_of_lines(struct tridentfb_par *par, int lines)
-{
-	int tmp = read3CE(par, CyberEnhance) & 0x8F;
-	if (lines > 1024)
-		tmp |= 0x50;
-	else if (lines > 768)
-		tmp |= 0x30;
-	else if (lines > 600)
-		tmp |= 0x20;
-	else if (lines > 480)
-		tmp |= 0x10;
-	write3CE(par, CyberEnhance, tmp);
-}
-
-/*
- * If we see that FP is active we assume we have one.
- * Otherwise we have a CRT display. User can override.
- */
-static int is_flatpanel(struct tridentfb_par *par)
-{
-	if (fp)
-		return 1;
-	if (crt || !iscyber(par->chip_id))
-		return 0;
-	return (read3CE(par, FPConfig) & 0x10) ? 1 : 0;
-}
-
-/* Try detecting the video memory size */
-static unsigned int get_memsize(struct tridentfb_par *par)
-{
-	unsigned char tmp, tmp2;
-	unsigned int k;
-
-	/* If memory size provided by user */
-	if (memsize)
-		k = memsize * Kb;
-	else
-		switch (par->chip_id) {
-		case CYBER9525DVD:
-			k = 2560 * Kb;
-			break;
-		default:
-			tmp = read3X4(par, SPR) & 0x0F;
-			switch (tmp) {
-
-			case 0x01:
-				k = 512 * Kb;
-				break;
-			case 0x02:
-				k = 6 * Mb;	/* XP */
-				break;
-			case 0x03:
-				k = 1 * Mb;
-				break;
-			case 0x04:
-				k = 8 * Mb;
-				break;
-			case 0x06:
-				k = 10 * Mb;	/* XP */
-				break;
-			case 0x07:
-				k = 2 * Mb;
-				break;
-			case 0x08:
-				k = 12 * Mb;	/* XP */
-				break;
-			case 0x0A:
-				k = 14 * Mb;	/* XP */
-				break;
-			case 0x0C:
-				k = 16 * Mb;	/* XP */
-				break;
-			case 0x0E:		/* XP */
-
-				tmp2 = vga_mm_rseq(par->io_virt, 0xC1);
-				switch (tmp2) {
-				case 0x00:
-					k = 20 * Mb;
-					break;
-				case 0x01:
-					k = 24 * Mb;
-					break;
-				case 0x10:
-					k = 28 * Mb;
-					break;
-				case 0x11:
-					k = 32 * Mb;
-					break;
-				default:
-					k = 1 * Mb;
-					break;
-				}
-				break;
-
-			case 0x0F:
-				k = 4 * Mb;
-				break;
-			default:
-				k = 1 * Mb;
-				break;
-			}
-		}
-
-	k -= memdiff * Kb;
-	output("framebuffer size = %d Kb\n", k / Kb);
-	return k;
-}
-
-/* See if we can handle the video mode described in var */
-static int tridentfb_check_var(struct fb_var_screeninfo *var,
-			       struct fb_info *info)
-{
-	struct tridentfb_par *par = info->par;
-	int bpp = var->bits_per_pixel;
-	int line_length;
-	int ramdac = 230000; /* 230MHz for most 3D chips */
-	debug("enter\n");
-
-	/* check color depth */
-	if (bpp == 24)
-		bpp = var->bits_per_pixel = 32;
-	if (bpp != 8 && bpp != 16 && bpp != 32)
-		return -EINVAL;
-	if (par->chip_id == TGUI9440 && bpp == 32)
-		return -EINVAL;
-	/* check whether resolution fits on panel and in memory */
-	if (par->flatpanel && nativex && var->xres > nativex)
-		return -EINVAL;
-	/* various resolution checks */
-	var->xres = (var->xres + 7) & ~0x7;
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-	if (var->xres_virtual > 4095 || var->yres > 2048)
-		return -EINVAL;
-	/* prevent from position overflow for acceleration */
-	if (var->yres_virtual > 0xffff)
-		return -EINVAL;
-	line_length = var->xres_virtual * bpp / 8;
-
-	if (!is3Dchip(par->chip_id) &&
-	    !(info->flags & FBINFO_HWACCEL_DISABLED)) {
-		/* acceleration requires line length to be power of 2 */
-		if (line_length <= 512)
-			var->xres_virtual = 512 * 8 / bpp;
-		else if (line_length <= 1024)
-			var->xres_virtual = 1024 * 8 / bpp;
-		else if (line_length <= 2048)
-			var->xres_virtual = 2048 * 8 / bpp;
-		else if (line_length <= 4096)
-			var->xres_virtual = 4096 * 8 / bpp;
-		else if (line_length <= 8192)
-			var->xres_virtual = 8192 * 8 / bpp;
-		else
-			return -EINVAL;
-
-		line_length = var->xres_virtual * bpp / 8;
-	}
-
-	/* datasheet specifies how to set panning only up to 4 MB */
-	if (line_length * (var->yres_virtual - var->yres) > (4 << 20))
-		var->yres_virtual = ((4 << 20) / line_length) + var->yres;
-
-	if (line_length * var->yres_virtual > info->fix.smem_len)
-		return -EINVAL;
-
-	switch (bpp) {
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green = var->red;
-		var->blue = var->red;
-		break;
-	case 16:
-		var->red.offset = 11;
-		var->green.offset = 5;
-		var->blue.offset = 0;
-		var->red.length = 5;
-		var->green.length = 6;
-		var->blue.length = 5;
-		break;
-	case 32:
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (is_xp(par->chip_id))
-		ramdac = 350000;
-
-	switch (par->chip_id) {
-	case TGUI9440:
-		ramdac = (bpp >= 16) ? 45000 : 90000;
-		break;
-	case CYBER9320:
-	case TGUI9660:
-		ramdac = 135000;
-		break;
-	case PROVIDIA9685:
-	case CYBER9388:
-	case CYBER9382:
-	case CYBER9385:
-		ramdac = 170000;
-		break;
-	}
-
-	/* The clock is doubled for 32 bpp */
-	if (bpp == 32)
-		ramdac /= 2;
-
-	if (PICOS2KHZ(var->pixclock) > ramdac)
-		return -EINVAL;
-
-	debug("exit\n");
-
-	return 0;
-
-}
-
-/* Pan the display */
-static int tridentfb_pan_display(struct fb_var_screeninfo *var,
-				 struct fb_info *info)
-{
-	struct tridentfb_par *par = info->par;
-	unsigned int offset;
-
-	debug("enter\n");
-	offset = (var->xoffset + (var->yoffset * info->var.xres_virtual))
-		* info->var.bits_per_pixel / 32;
-	set_screen_start(par, offset);
-	debug("exit\n");
-	return 0;
-}
-
-static inline void shadowmode_on(struct tridentfb_par *par)
-{
-	write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81);
-}
-
-static inline void shadowmode_off(struct tridentfb_par *par)
-{
-	write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E);
-}
-
-/* Set the hardware to the requested video mode */
-static int tridentfb_set_par(struct fb_info *info)
-{
-	struct tridentfb_par *par = info->par;
-	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
-	u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
-	struct fb_var_screeninfo *var = &info->var;
-	int bpp = var->bits_per_pixel;
-	unsigned char tmp;
-	unsigned long vclk;
-
-	debug("enter\n");
-	hdispend = var->xres / 8 - 1;
-	hsyncstart = (var->xres + var->right_margin) / 8;
-	hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;
-	htotal = (var->xres + var->left_margin + var->right_margin +
-		  var->hsync_len) / 8 - 5;
-	hblankstart = hdispend + 1;
-	hblankend = htotal + 3;
-
-	vdispend = var->yres - 1;
-	vsyncstart = var->yres + var->lower_margin;
-	vsyncend = vsyncstart + var->vsync_len;
-	vtotal = var->upper_margin + vsyncend - 2;
-	vblankstart = vdispend + 1;
-	vblankend = vtotal;
-
-	if (info->var.vmode & FB_VMODE_INTERLACED) {
-		vtotal /= 2;
-		vdispend /= 2;
-		vsyncstart /= 2;
-		vsyncend /= 2;
-		vblankstart /= 2;
-		vblankend /= 2;
-	}
-
-	enable_mmio(par);
-	crtc_unlock(par);
-	write3CE(par, CyberControl, 8);
-	tmp = 0xEB;
-	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-		tmp &= ~0x40;
-	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-		tmp &= ~0x80;
-
-	if (par->flatpanel && var->xres < nativex) {
-		/*
-		 * on flat panels with native size larger
-		 * than requested resolution decide whether
-		 * we stretch or center
-		 */
-		t_outb(par, tmp | 0xC0, VGA_MIS_W);
-
-		shadowmode_on(par);
-
-		if (center)
-			screen_center(par);
-		else if (stretch)
-			screen_stretch(par);
-
-	} else {
-		t_outb(par, tmp, VGA_MIS_W);
-		write3CE(par, CyberControl, 8);
-	}
-
-	/* vertical timing values */
-	write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF);
-	write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF);
-	write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF);
-	write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F));
-	write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF);
-	write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF);
-
-	/* horizontal timing values */
-	write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF);
-	write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF);
-	write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF);
-	write3X4(par, VGA_CRTC_H_SYNC_END,
-		 (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
-	write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF);
-	write3X4(par, VGA_CRTC_H_BLANK_END, hblankend & 0x1F);
-
-	/* higher bits of vertical timing values */
-	tmp = 0x10;
-	if (vtotal & 0x100) tmp |= 0x01;
-	if (vdispend & 0x100) tmp |= 0x02;
-	if (vsyncstart & 0x100) tmp |= 0x04;
-	if (vblankstart & 0x100) tmp |= 0x08;
-
-	if (vtotal & 0x200) tmp |= 0x20;
-	if (vdispend & 0x200) tmp |= 0x40;
-	if (vsyncstart & 0x200) tmp |= 0x80;
-	write3X4(par, VGA_CRTC_OVERFLOW, tmp);
-
-	tmp = read3X4(par, CRTHiOrd) & 0x07;
-	tmp |= 0x08;	/* line compare bit 10 */
-	if (vtotal & 0x400) tmp |= 0x80;
-	if (vblankstart & 0x400) tmp |= 0x40;
-	if (vsyncstart & 0x400) tmp |= 0x20;
-	if (vdispend & 0x400) tmp |= 0x10;
-	write3X4(par, CRTHiOrd, tmp);
-
-	tmp = (htotal >> 8) & 0x01;
-	tmp |= (hdispend >> 7) & 0x02;
-	tmp |= (hsyncstart >> 5) & 0x08;
-	tmp |= (hblankstart >> 4) & 0x10;
-	write3X4(par, HorizOverflow, tmp);
-
-	tmp = 0x40;
-	if (vblankstart & 0x200) tmp |= 0x20;
-//FIXME	if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80;  /* double scan for 200 line modes */
-	write3X4(par, VGA_CRTC_MAX_SCAN, tmp);
-
-	write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF);
-	write3X4(par, VGA_CRTC_PRESET_ROW, 0);
-	write3X4(par, VGA_CRTC_MODE, 0xC3);
-
-	write3X4(par, LinearAddReg, 0x20);	/* enable linear addressing */
-
-	tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
-	/* enable access extended memory */
-	write3X4(par, CRTCModuleTest, tmp);
-	tmp = read3CE(par, MiscIntContReg) & ~0x4;
-	if (info->var.vmode & FB_VMODE_INTERLACED)
-		tmp |= 0x4;
-	write3CE(par, MiscIntContReg, tmp);
-
-	/* enable GE for text acceleration */
-	write3X4(par, GraphEngReg, 0x80);
-
-	switch (bpp) {
-	case 8:
-		tmp = 0x00;
-		break;
-	case 16:
-		tmp = 0x05;
-		break;
-	case 24:
-		tmp = 0x29;
-		break;
-	case 32:
-		tmp = 0x09;
-		break;
-	}
-
-	write3X4(par, PixelBusReg, tmp);
-
-	tmp = read3X4(par, DRAMControl);
-	if (!is_oldprotect(par->chip_id))
-		tmp |= 0x10;
-	if (iscyber(par->chip_id))
-		tmp |= 0x20;
-	write3X4(par, DRAMControl, tmp);	/* both IO, linear enable */
-
-	write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40);
-	if (!is_xp(par->chip_id))
-		write3X4(par, Performance, read3X4(par, Performance) | 0x10);
-	/* MMIO & PCI read and write burst enable */
-	if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975)
-		write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06);
-
-	vga_mm_wseq(par->io_virt, 0, 3);
-	vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */
-	/* enable 4 maps because needed in chain4 mode */
-	vga_mm_wseq(par->io_virt, 2, 0x0F);
-	vga_mm_wseq(par->io_virt, 3, 0);
-	vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */
-
-	/* convert from picoseconds to kHz */
-	vclk = PICOS2KHZ(info->var.pixclock);
-
-	/* divide clock by 2 if 32bpp chain4 mode display and CPU path */
-	tmp = read3CE(par, MiscExtFunc) & 0xF0;
-	if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) {
-		tmp |= 8;
-		vclk *= 2;
-	}
-	set_vclk(par, vclk);
-	write3CE(par, MiscExtFunc, tmp | 0x12);
-	write3CE(par, 0x5, 0x40);	/* no CGA compat, allow 256 col */
-	write3CE(par, 0x6, 0x05);	/* graphics mode */
-	write3CE(par, 0x7, 0x0F);	/* planes? */
-
-	/* graphics mode and support 256 color modes */
-	writeAttr(par, 0x10, 0x41);
-	writeAttr(par, 0x12, 0x0F);	/* planes */
-	writeAttr(par, 0x13, 0);	/* horizontal pel panning */
-
-	/* colors */
-	for (tmp = 0; tmp < 0x10; tmp++)
-		writeAttr(par, tmp, tmp);
-	fb_readb(par->io_virt + VGA_IS1_RC);	/* flip-flop to index */
-	t_outb(par, 0x20, VGA_ATT_W);		/* enable attr */
-
-	switch (bpp) {
-	case 8:
-		tmp = 0;
-		break;
-	case 16:
-		tmp = 0x30;
-		break;
-	case 24:
-	case 32:
-		tmp = 0xD0;
-		break;
-	}
-
-	t_inb(par, VGA_PEL_IW);
-	t_inb(par, VGA_PEL_MSK);
-	t_inb(par, VGA_PEL_MSK);
-	t_inb(par, VGA_PEL_MSK);
-	t_inb(par, VGA_PEL_MSK);
-	t_outb(par, tmp, VGA_PEL_MSK);
-	t_inb(par, VGA_PEL_IW);
-
-	if (par->flatpanel)
-		set_number_of_lines(par, info->var.yres);
-	info->fix.line_length = info->var.xres_virtual * bpp / 8;
-	set_lwidth(par, info->fix.line_length / 8);
-
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
-		par->init_accel(par, info->var.xres_virtual, bpp);
-
-	info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->cmap.len = (bpp == 8) ? 256 : 16;
-	debug("exit\n");
-	return 0;
-}
-
-/* Set one color register */
-static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			       unsigned blue, unsigned transp,
-			       struct fb_info *info)
-{
-	int bpp = info->var.bits_per_pixel;
-	struct tridentfb_par *par = info->par;
-
-	if (regno >= info->cmap.len)
-		return 1;
-
-	if (bpp == 8) {
-		t_outb(par, 0xFF, VGA_PEL_MSK);
-		t_outb(par, regno, VGA_PEL_IW);
-
-		t_outb(par, red >> 10, VGA_PEL_D);
-		t_outb(par, green >> 10, VGA_PEL_D);
-		t_outb(par, blue >> 10, VGA_PEL_D);
-
-	} else if (regno < 16) {
-		if (bpp == 16) {	/* RGB 565 */
-			u32 col;
-
-			col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
-				((blue & 0xF800) >> 11);
-			col |= col << 16;
-			((u32 *)(info->pseudo_palette))[regno] = col;
-		} else if (bpp == 32)		/* ARGB 8888 */
-			((u32 *)info->pseudo_palette)[regno] =
-				((transp & 0xFF00) << 16)	|
-				((red & 0xFF00) << 8)		|
-				((green & 0xFF00))		|
-				((blue & 0xFF00) >> 8);
-	}
-
-	return 0;
-}
-
-/* Try blanking the screen. For flat panels it does nothing */
-static int tridentfb_blank(int blank_mode, struct fb_info *info)
-{
-	unsigned char PMCont, DPMSCont;
-	struct tridentfb_par *par = info->par;
-
-	debug("enter\n");
-	if (par->flatpanel)
-		return 0;
-	t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */
-	PMCont = t_inb(par, 0x83C6) & 0xFC;
-	DPMSCont = read3CE(par, PowerStatus) & 0xFC;
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		/* Screen: On, HSync: On, VSync: On */
-	case FB_BLANK_NORMAL:
-		/* Screen: Off, HSync: On, VSync: On */
-		PMCont |= 0x03;
-		DPMSCont |= 0x00;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		/* Screen: Off, HSync: Off, VSync: On */
-		PMCont |= 0x02;
-		DPMSCont |= 0x01;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		/* Screen: Off, HSync: On, VSync: Off */
-		PMCont |= 0x02;
-		DPMSCont |= 0x02;
-		break;
-	case FB_BLANK_POWERDOWN:
-		/* Screen: Off, HSync: Off, VSync: Off */
-		PMCont |= 0x00;
-		DPMSCont |= 0x03;
-		break;
-	}
-
-	write3CE(par, PowerStatus, DPMSCont);
-	t_outb(par, 4, 0x83C8);
-	t_outb(par, PMCont, 0x83C6);
-
-	debug("exit\n");
-
-	/* let fbcon do a softblank for us */
-	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
-}
-
-static struct fb_ops tridentfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_setcolreg = tridentfb_setcolreg,
-	.fb_pan_display = tridentfb_pan_display,
-	.fb_blank = tridentfb_blank,
-	.fb_check_var = tridentfb_check_var,
-	.fb_set_par = tridentfb_set_par,
-	.fb_fillrect = tridentfb_fillrect,
-	.fb_copyarea = tridentfb_copyarea,
-	.fb_imageblit = tridentfb_imageblit,
-	.fb_sync = tridentfb_sync,
-};
-
-static int trident_pci_probe(struct pci_dev *dev,
-			     const struct pci_device_id *id)
-{
-	int err;
-	unsigned char revision;
-	struct fb_info *info;
-	struct tridentfb_par *default_par;
-	int chip3D;
-	int chip_id;
-
-	err = pci_enable_device(dev);
-	if (err)
-		return err;
-
-	info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev);
-	if (!info)
-		return -ENOMEM;
-	default_par = info->par;
-
-	chip_id = id->device;
-
-	/* If PCI id is 0x9660 then further detect chip type */
-
-	if (chip_id == TGUI9660) {
-		revision = vga_io_rseq(RevisionID);
-
-		switch (revision) {
-		case 0x21:
-			chip_id = PROVIDIA9685;
-			break;
-		case 0x22:
-		case 0x23:
-			chip_id = CYBER9397;
-			break;
-		case 0x2A:
-			chip_id = CYBER9397DVD;
-			break;
-		case 0x30:
-		case 0x33:
-		case 0x34:
-		case 0x35:
-		case 0x38:
-		case 0x3A:
-		case 0xB3:
-			chip_id = CYBER9385;
-			break;
-		case 0x40 ... 0x43:
-			chip_id = CYBER9382;
-			break;
-		case 0x4A:
-			chip_id = CYBER9388;
-			break;
-		default:
-			break;
-		}
-	}
-
-	chip3D = is3Dchip(chip_id);
-
-	if (is_xp(chip_id)) {
-		default_par->init_accel = xp_init_accel;
-		default_par->wait_engine = xp_wait_engine;
-		default_par->fill_rect = xp_fill_rect;
-		default_par->copy_rect = xp_copy_rect;
-		tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP;
-	} else if (is_blade(chip_id)) {
-		default_par->init_accel = blade_init_accel;
-		default_par->wait_engine = blade_wait_engine;
-		default_par->fill_rect = blade_fill_rect;
-		default_par->copy_rect = blade_copy_rect;
-		default_par->image_blit = blade_image_blit;
-		tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D;
-	} else if (chip3D) {			/* 3DImage family left */
-		default_par->init_accel = image_init_accel;
-		default_par->wait_engine = image_wait_engine;
-		default_par->fill_rect = image_fill_rect;
-		default_par->copy_rect = image_copy_rect;
-		tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE;
-	} else { 				/* TGUI 9440/96XX family */
-		default_par->init_accel = tgui_init_accel;
-		default_par->wait_engine = xp_wait_engine;
-		default_par->fill_rect = tgui_fill_rect;
-		default_par->copy_rect = tgui_copy_rect;
-		tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI;
-	}
-
-	default_par->chip_id = chip_id;
-
-	/* setup MMIO region */
-	tridentfb_fix.mmio_start = pci_resource_start(dev, 1);
-	tridentfb_fix.mmio_len = pci_resource_len(dev, 1);
-
-	if (!request_mem_region(tridentfb_fix.mmio_start,
-				tridentfb_fix.mmio_len, "tridentfb")) {
-		debug("request_region failed!\n");
-		framebuffer_release(info);
-		return -1;
-	}
-
-	default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start,
-					       tridentfb_fix.mmio_len);
-
-	if (!default_par->io_virt) {
-		debug("ioremap failed\n");
-		err = -1;
-		goto out_unmap1;
-	}
-
-	enable_mmio(default_par);
-
-	/* setup framebuffer memory */
-	tridentfb_fix.smem_start = pci_resource_start(dev, 0);
-	tridentfb_fix.smem_len = get_memsize(default_par);
-
-	if (!request_mem_region(tridentfb_fix.smem_start,
-				tridentfb_fix.smem_len, "tridentfb")) {
-		debug("request_mem_region failed!\n");
-		disable_mmio(info->par);
-		err = -1;
-		goto out_unmap1;
-	}
-
-	info->screen_base = ioremap_nocache(tridentfb_fix.smem_start,
-					    tridentfb_fix.smem_len);
-
-	if (!info->screen_base) {
-		debug("ioremap failed\n");
-		err = -1;
-		goto out_unmap2;
-	}
-
-	default_par->flatpanel = is_flatpanel(default_par);
-
-	if (default_par->flatpanel)
-		nativex = get_nativex(default_par);
-
-	info->fix = tridentfb_fix;
-	info->fbops = &tridentfb_ops;
-	info->pseudo_palette = default_par->pseudo_pal;
-
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	if (!noaccel && default_par->init_accel) {
-		info->flags &= ~FBINFO_HWACCEL_DISABLED;
-		info->flags |= FBINFO_HWACCEL_COPYAREA;
-		info->flags |= FBINFO_HWACCEL_FILLRECT;
-	} else
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-
-	if (is_blade(chip_id) && chip_id != BLADE3D)
-		info->flags |= FBINFO_READS_FAST;
-
-	info->pixmap.addr = kmalloc(4096, GFP_KERNEL);
-	if (!info->pixmap.addr) {
-		err = -ENOMEM;
-		goto out_unmap2;
-	}
-
-	info->pixmap.size = 4096;
-	info->pixmap.buf_align = 4;
-	info->pixmap.scan_align = 1;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-	if (default_par->image_blit) {
-		info->flags |= FBINFO_HWACCEL_IMAGEBLIT;
-		info->pixmap.scan_align = 4;
-	}
-
-	if (noaccel) {
-		printk(KERN_DEBUG "disabling acceleration\n");
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-		info->pixmap.scan_align = 1;
-	}
-
-	if (!fb_find_mode(&info->var, info,
-			  mode_option, NULL, 0, NULL, bpp)) {
-		err = -EINVAL;
-		goto out_unmap2;
-	}
-	err = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (err < 0)
-		goto out_unmap2;
-
-	info->var.activate |= FB_ACTIVATE_NOW;
-	info->device = &dev->dev;
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "tridentfb: could not register framebuffer\n");
-		fb_dealloc_cmap(&info->cmap);
-		err = -EINVAL;
-		goto out_unmap2;
-	}
-	output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
-	   info->node, info->fix.id, info->var.xres,
-	   info->var.yres, info->var.bits_per_pixel);
-
-	pci_set_drvdata(dev, info);
-	return 0;
-
-out_unmap2:
-	kfree(info->pixmap.addr);
-	if (info->screen_base)
-		iounmap(info->screen_base);
-	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
-	disable_mmio(info->par);
-out_unmap1:
-	if (default_par->io_virt)
-		iounmap(default_par->io_virt);
-	release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
-	framebuffer_release(info);
-	return err;
-}
-
-static void trident_pci_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct tridentfb_par *par = info->par;
-
-	unregister_framebuffer(info);
-	iounmap(par->io_virt);
-	iounmap(info->screen_base);
-	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
-	release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
-	kfree(info->pixmap.addr);
-	fb_dealloc_cmap(&info->cmap);
-	framebuffer_release(info);
-}
-
-/* List of boards that we are trying to support */
-static struct pci_device_id trident_devices[] = {
-	{PCI_VENDOR_ID_TRIDENT,	BLADE3D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi7D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBER9320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBER9388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBER9520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBER9525DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBER9397, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBER9397DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPm8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPm16, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, trident_devices);
-
-static struct pci_driver tridentfb_pci_driver = {
-	.name = "tridentfb",
-	.id_table = trident_devices,
-	.probe = trident_pci_probe,
-	.remove = trident_pci_remove,
-};
-
-/*
- * Parse user specified options (`video=trident:')
- * example:
- *	video=trident:800x600,bpp=16,noaccel
- */
-#ifndef MODULE
-static int __init tridentfb_setup(char *options)
-{
-	char *opt;
-	if (!options || !*options)
-		return 0;
-	while ((opt = strsep(&options, ",")) != NULL) {
-		if (!*opt)
-			continue;
-		if (!strncmp(opt, "noaccel", 7))
-			noaccel = 1;
-		else if (!strncmp(opt, "fp", 2))
-			fp = 1;
-		else if (!strncmp(opt, "crt", 3))
-			fp = 0;
-		else if (!strncmp(opt, "bpp=", 4))
-			bpp = simple_strtoul(opt + 4, NULL, 0);
-		else if (!strncmp(opt, "center", 6))
-			center = 1;
-		else if (!strncmp(opt, "stretch", 7))
-			stretch = 1;
-		else if (!strncmp(opt, "memsize=", 8))
-			memsize = simple_strtoul(opt + 8, NULL, 0);
-		else if (!strncmp(opt, "memdiff=", 8))
-			memdiff = simple_strtoul(opt + 8, NULL, 0);
-		else if (!strncmp(opt, "nativex=", 8))
-			nativex = simple_strtoul(opt + 8, NULL, 0);
-		else
-			mode_option = opt;
-	}
-	return 0;
-}
-#endif
-
-static int __init tridentfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("tridentfb", &option))
-		return -ENODEV;
-	tridentfb_setup(option);
-#endif
-	return pci_register_driver(&tridentfb_pci_driver);
-}
-
-static void __exit tridentfb_exit(void)
-{
-	pci_unregister_driver(&tridentfb_pci_driver);
-}
-
-module_init(tridentfb_init);
-module_exit(tridentfb_exit);
-
-MODULE_AUTHOR("Jani Monoses <jani@iv.ro>");
-MODULE_DESCRIPTION("Framebuffer driver for Trident cards");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("cyblafb");
-
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
deleted file mode 100644
index 77b890e4d296..000000000000
--- a/drivers/video/udlfb.c
+++ /dev/null
@@ -1,1985 +0,0 @@
-/*
- * udlfb.c -- Framebuffer driver for DisplayLink USB controller
- *
- * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
- * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
- * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License v2. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
- * usb-skeleton by GregKH.
- *
- * Device-specific portions based on information from Displaylink, with work
- * from Florian Echtler, Henrik Bjerregaard Pedersen, and others.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/uaccess.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/prefetch.h>
-#include <linux/delay.h>
-#include <video/udlfb.h>
-#include "edid.h"
-
-static struct fb_fix_screeninfo dlfb_fix = {
-	.id =           "udlfb",
-	.type =         FB_TYPE_PACKED_PIXELS,
-	.visual =       FB_VISUAL_TRUECOLOR,
-	.xpanstep =     0,
-	.ypanstep =     0,
-	.ywrapstep =    0,
-	.accel =        FB_ACCEL_NONE,
-};
-
-static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
-		FBINFO_VIRTFB |
-		FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
-		FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
-
-/*
- * There are many DisplayLink-based graphics products, all with unique PIDs.
- * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff)
- * We also require a match on SubClass (0x00) and Protocol (0x00),
- * which is compatible with all known USB 2.0 era graphics chips and firmware,
- * but allows DisplayLink to increment those for any future incompatible chips
- */
-static struct usb_device_id id_table[] = {
-	{.idVendor = 0x17e9,
-	 .bInterfaceClass = 0xff,
-	 .bInterfaceSubClass = 0x00,
-	 .bInterfaceProtocol = 0x00,
-	 .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
-		USB_DEVICE_ID_MATCH_INT_CLASS |
-		USB_DEVICE_ID_MATCH_INT_SUBCLASS |
-		USB_DEVICE_ID_MATCH_INT_PROTOCOL,
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-/* module options */
-static bool console = 1; /* Allow fbcon to open framebuffer */
-static bool fb_defio = 1;  /* Detect mmap writes using page faults */
-static bool shadow = 1; /* Optionally disable shadow framebuffer */
-static int pixel_limit; /* Optionally force a pixel resolution limit */
-
-/* dlfb keeps a list of urbs for efficient bulk transfers */
-static void dlfb_urb_completion(struct urb *urb);
-static struct urb *dlfb_get_urb(struct dlfb_data *dev);
-static int dlfb_submit_urb(struct dlfb_data *dev, struct urb * urb, size_t len);
-static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size);
-static void dlfb_free_urb_list(struct dlfb_data *dev);
-
-/*
- * All DisplayLink bulk operations start with 0xAF, followed by specific code
- * All operations are written to buffers which then later get sent to device
- */
-static char *dlfb_set_register(char *buf, u8 reg, u8 val)
-{
-	*buf++ = 0xAF;
-	*buf++ = 0x20;
-	*buf++ = reg;
-	*buf++ = val;
-	return buf;
-}
-
-static char *dlfb_vidreg_lock(char *buf)
-{
-	return dlfb_set_register(buf, 0xFF, 0x00);
-}
-
-static char *dlfb_vidreg_unlock(char *buf)
-{
-	return dlfb_set_register(buf, 0xFF, 0xFF);
-}
-
-/*
- * Map FB_BLANK_* to DisplayLink register
- * DLReg FB_BLANK_*
- * ----- -----------------------------
- *  0x00 FB_BLANK_UNBLANK (0)
- *  0x01 FB_BLANK (1)
- *  0x03 FB_BLANK_VSYNC_SUSPEND (2)
- *  0x05 FB_BLANK_HSYNC_SUSPEND (3)
- *  0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back
- */
-static char *dlfb_blanking(char *buf, int fb_blank)
-{
-	u8 reg;
-
-	switch (fb_blank) {
-	case FB_BLANK_POWERDOWN:
-		reg = 0x07;
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		reg = 0x05;
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		reg = 0x03;
-		break;
-	case FB_BLANK_NORMAL:
-		reg = 0x01;
-		break;
-	default:
-		reg = 0x00;
-	}
-
-	buf = dlfb_set_register(buf, 0x1F, reg);
-
-	return buf;
-}
-
-static char *dlfb_set_color_depth(char *buf, u8 selection)
-{
-	return dlfb_set_register(buf, 0x00, selection);
-}
-
-static char *dlfb_set_base16bpp(char *wrptr, u32 base)
-{
-	/* the base pointer is 16 bits wide, 0x20 is hi byte. */
-	wrptr = dlfb_set_register(wrptr, 0x20, base >> 16);
-	wrptr = dlfb_set_register(wrptr, 0x21, base >> 8);
-	return dlfb_set_register(wrptr, 0x22, base);
-}
-
-/*
- * DisplayLink HW has separate 16bpp and 8bpp framebuffers.
- * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
- */
-static char *dlfb_set_base8bpp(char *wrptr, u32 base)
-{
-	wrptr = dlfb_set_register(wrptr, 0x26, base >> 16);
-	wrptr = dlfb_set_register(wrptr, 0x27, base >> 8);
-	return dlfb_set_register(wrptr, 0x28, base);
-}
-
-static char *dlfb_set_register_16(char *wrptr, u8 reg, u16 value)
-{
-	wrptr = dlfb_set_register(wrptr, reg, value >> 8);
-	return dlfb_set_register(wrptr, reg+1, value);
-}
-
-/*
- * This is kind of weird because the controller takes some
- * register values in a different byte order than other registers.
- */
-static char *dlfb_set_register_16be(char *wrptr, u8 reg, u16 value)
-{
-	wrptr = dlfb_set_register(wrptr, reg, value);
-	return dlfb_set_register(wrptr, reg+1, value >> 8);
-}
-
-/*
- * LFSR is linear feedback shift register. The reason we have this is
- * because the display controller needs to minimize the clock depth of
- * various counters used in the display path. So this code reverses the
- * provided value into the lfsr16 value by counting backwards to get
- * the value that needs to be set in the hardware comparator to get the
- * same actual count. This makes sense once you read above a couple of
- * times and think about it from a hardware perspective.
- */
-static u16 dlfb_lfsr16(u16 actual_count)
-{
-	u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */
-
-	while (actual_count--) {
-		lv =	 ((lv << 1) |
-			(((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1))
-			& 0xFFFF;
-	}
-
-	return (u16) lv;
-}
-
-/*
- * This does LFSR conversion on the value that is to be written.
- * See LFSR explanation above for more detail.
- */
-static char *dlfb_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
-{
-	return dlfb_set_register_16(wrptr, reg, dlfb_lfsr16(value));
-}
-
-/*
- * This takes a standard fbdev screeninfo struct and all of its monitor mode
- * details and converts them into the DisplayLink equivalent register commands.
- */
-static char *dlfb_set_vid_cmds(char *wrptr, struct fb_var_screeninfo *var)
-{
-	u16 xds, yds;
-	u16 xde, yde;
-	u16 yec;
-
-	/* x display start */
-	xds = var->left_margin + var->hsync_len;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x01, xds);
-	/* x display end */
-	xde = xds + var->xres;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x03, xde);
-
-	/* y display start */
-	yds = var->upper_margin + var->vsync_len;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x05, yds);
-	/* y display end */
-	yde = yds + var->yres;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x07, yde);
-
-	/* x end count is active + blanking - 1 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x09,
-			xde + var->right_margin - 1);
-
-	/* libdlo hardcodes hsync start to 1 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0B, 1);
-
-	/* hsync end is width of sync pulse + 1 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0D, var->hsync_len + 1);
-
-	/* hpixels is active pixels */
-	wrptr = dlfb_set_register_16(wrptr, 0x0F, var->xres);
-
-	/* yendcount is vertical active + vertical blanking */
-	yec = var->yres + var->upper_margin + var->lower_margin +
-			var->vsync_len;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x11, yec);
-
-	/* libdlo hardcodes vsync start to 0 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x13, 0);
-
-	/* vsync end is width of vsync pulse */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x15, var->vsync_len);
-
-	/* vpixels is active pixels */
-	wrptr = dlfb_set_register_16(wrptr, 0x17, var->yres);
-
-	/* convert picoseconds to 5kHz multiple for pclk5k = x * 1E12/5k */
-	wrptr = dlfb_set_register_16be(wrptr, 0x1B,
-			200*1000*1000/var->pixclock);
-
-	return wrptr;
-}
-
-/*
- * This takes a standard fbdev screeninfo struct that was fetched or prepared
- * and then generates the appropriate command sequence that then drives the
- * display controller.
- */
-static int dlfb_set_video_mode(struct dlfb_data *dev,
-				struct fb_var_screeninfo *var)
-{
-	char *buf;
-	char *wrptr;
-	int retval = 0;
-	int writesize;
-	struct urb *urb;
-
-	if (!atomic_read(&dev->usb_active))
-		return -EPERM;
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return -ENOMEM;
-
-	buf = (char *) urb->transfer_buffer;
-
-	/*
-	* This first section has to do with setting the base address on the
-	* controller * associated with the display. There are 2 base
-	* pointers, currently, we only * use the 16 bpp segment.
-	*/
-	wrptr = dlfb_vidreg_lock(buf);
-	wrptr = dlfb_set_color_depth(wrptr, 0x00);
-	/* set base for 16bpp segment to 0 */
-	wrptr = dlfb_set_base16bpp(wrptr, 0);
-	/* set base for 8bpp segment to end of fb */
-	wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
-
-	wrptr = dlfb_set_vid_cmds(wrptr, var);
-	wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK);
-	wrptr = dlfb_vidreg_unlock(wrptr);
-
-	writesize = wrptr - buf;
-
-	retval = dlfb_submit_urb(dev, urb, writesize);
-
-	dev->blank_mode = FB_BLANK_UNBLANK;
-
-	return retval;
-}
-
-static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	unsigned long start = vma->vm_start;
-	unsigned long size = vma->vm_end - vma->vm_start;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	unsigned long page, pos;
-
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-	if (size > info->fix.smem_len)
-		return -EINVAL;
-	if (offset > info->fix.smem_len - size)
-		return -EINVAL;
-
-	pos = (unsigned long)info->fix.smem_start + offset;
-
-	pr_notice("mmap() framebuffer addr:%lu size:%lu\n",
-		  pos, size);
-
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-}
-
-/*
- * Trims identical data from front and back of line
- * Sets new front buffer address and width
- * And returns byte count of identical pixels
- * Assumes CPU natural alignment (unsigned long)
- * for back and front buffer ptrs and width
- */
-static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
-{
-	int j, k;
-	const unsigned long *back = (const unsigned long *) bback;
-	const unsigned long *front = (const unsigned long *) *bfront;
-	const int width = *width_bytes / sizeof(unsigned long);
-	int identical = width;
-	int start = width;
-	int end = width;
-
-	prefetch((void *) front);
-	prefetch((void *) back);
-
-	for (j = 0; j < width; j++) {
-		if (back[j] != front[j]) {
-			start = j;
-			break;
-		}
-	}
-
-	for (k = width - 1; k > j; k--) {
-		if (back[k] != front[k]) {
-			end = k+1;
-			break;
-		}
-	}
-
-	identical = start + (width - end);
-	*bfront = (u8 *) &front[start];
-	*width_bytes = (end - start) * sizeof(unsigned long);
-
-	return identical * sizeof(unsigned long);
-}
-
-/*
- * Render a command stream for an encoded horizontal line segment of pixels.
- *
- * A command buffer holds several commands.
- * It always begins with a fresh command header
- * (the protocol doesn't require this, but we enforce it to allow
- * multiple buffers to be potentially encoded and sent in parallel).
- * A single command encodes one contiguous horizontal line of pixels
- *
- * The function relies on the client to do all allocation, so that
- * rendering can be done directly to output buffers (e.g. USB URBs).
- * The function fills the supplied command buffer, providing information
- * on where it left off, so the client may call in again with additional
- * buffers if the line will take several buffers to complete.
- *
- * A single command can transmit a maximum of 256 pixels,
- * regardless of the compression ratio (protocol design limit).
- * To the hardware, 0 for a size byte means 256
- *
- * Rather than 256 pixel commands which are either rl or raw encoded,
- * the rlx command simply assumes alternating raw and rl spans within one cmd.
- * This has a slightly larger header overhead, but produces more even results.
- * It also processes all data (read and write) in a single pass.
- * Performance benchmarks of common cases show it having just slightly better
- * compression than 256 pixel raw or rle commands, with similar CPU consumpion.
- * But for very rl friendly data, will compress not quite as well.
- */
-static void dlfb_compress_hline(
-	const uint16_t **pixel_start_ptr,
-	const uint16_t *const pixel_end,
-	uint32_t *device_address_ptr,
-	uint8_t **command_buffer_ptr,
-	const uint8_t *const cmd_buffer_end)
-{
-	const uint16_t *pixel = *pixel_start_ptr;
-	uint32_t dev_addr  = *device_address_ptr;
-	uint8_t *cmd = *command_buffer_ptr;
-	const int bpp = 2;
-
-	while ((pixel_end > pixel) &&
-	       (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) {
-		uint8_t *raw_pixels_count_byte = NULL;
-		uint8_t *cmd_pixels_count_byte = NULL;
-		const uint16_t *raw_pixel_start = NULL;
-		const uint16_t *cmd_pixel_start, *cmd_pixel_end = NULL;
-
-		prefetchw((void *) cmd); /* pull in one cache line at least */
-
-		*cmd++ = 0xAF;
-		*cmd++ = 0x6B;
-		*cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
-		*cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
-		*cmd++ = (uint8_t) ((dev_addr) & 0xFF);
-
-		cmd_pixels_count_byte = cmd++; /*  we'll know this later */
-		cmd_pixel_start = pixel;
-
-		raw_pixels_count_byte = cmd++; /*  we'll know this later */
-		raw_pixel_start = pixel;
-
-		cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
-			min((int)(pixel_end - pixel),
-			    (int)(cmd_buffer_end - cmd) / bpp));
-
-		prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
-
-		while (pixel < cmd_pixel_end) {
-			const uint16_t * const repeating_pixel = pixel;
-
-			*(uint16_t *)cmd = cpu_to_be16p(pixel);
-			cmd += 2;
-			pixel++;
-
-			if (unlikely((pixel < cmd_pixel_end) &&
-				     (*pixel == *repeating_pixel))) {
-				/* go back and fill in raw pixel count */
-				*raw_pixels_count_byte = ((repeating_pixel -
-						raw_pixel_start) + 1) & 0xFF;
-
-				while ((pixel < cmd_pixel_end)
-				       && (*pixel == *repeating_pixel)) {
-					pixel++;
-				}
-
-				/* immediately after raw data is repeat byte */
-				*cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
-
-				/* Then start another raw pixel span */
-				raw_pixel_start = pixel;
-				raw_pixels_count_byte = cmd++;
-			}
-		}
-
-		if (pixel > raw_pixel_start) {
-			/* finalize last RAW span */
-			*raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
-		}
-
-		*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
-		dev_addr += (pixel - cmd_pixel_start) * bpp;
-	}
-
-	if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
-		/* Fill leftover bytes with no-ops */
-		if (cmd_buffer_end > cmd)
-			memset(cmd, 0xAF, cmd_buffer_end - cmd);
-		cmd = (uint8_t *) cmd_buffer_end;
-	}
-
-	*command_buffer_ptr = cmd;
-	*pixel_start_ptr = pixel;
-	*device_address_ptr = dev_addr;
-
-	return;
-}
-
-/*
- * There are 3 copies of every pixel: The front buffer that the fbdev
- * client renders to, the actual framebuffer across the USB bus in hardware
- * (that we can only write to, slowly, and can never read), and (optionally)
- * our shadow copy that tracks what's been sent to that hardware buffer.
- */
-static int dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
-			      const char *front, char **urb_buf_ptr,
-			      u32 byte_offset, u32 byte_width,
-			      int *ident_ptr, int *sent_ptr)
-{
-	const u8 *line_start, *line_end, *next_pixel;
-	u32 dev_addr = dev->base16 + byte_offset;
-	struct urb *urb = *urb_ptr;
-	u8 *cmd = *urb_buf_ptr;
-	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
-
-	line_start = (u8 *) (front + byte_offset);
-	next_pixel = line_start;
-	line_end = next_pixel + byte_width;
-
-	if (dev->backing_buffer) {
-		int offset;
-		const u8 *back_start = (u8 *) (dev->backing_buffer
-						+ byte_offset);
-
-		*ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
-			&byte_width);
-
-		offset = next_pixel - line_start;
-		line_end = next_pixel + byte_width;
-		dev_addr += offset;
-		back_start += offset;
-		line_start += offset;
-
-		memcpy((char *)back_start, (char *) line_start,
-		       byte_width);
-	}
-
-	while (next_pixel < line_end) {
-
-		dlfb_compress_hline((const uint16_t **) &next_pixel,
-			     (const uint16_t *) line_end, &dev_addr,
-			(u8 **) &cmd, (u8 *) cmd_end);
-
-		if (cmd >= cmd_end) {
-			int len = cmd - (u8 *) urb->transfer_buffer;
-			if (dlfb_submit_urb(dev, urb, len))
-				return 1; /* lost pixels is set */
-			*sent_ptr += len;
-			urb = dlfb_get_urb(dev);
-			if (!urb)
-				return 1; /* lost_pixels is set */
-			*urb_ptr = urb;
-			cmd = urb->transfer_buffer;
-			cmd_end = &cmd[urb->transfer_buffer_length];
-		}
-	}
-
-	*urb_buf_ptr = cmd;
-
-	return 0;
-}
-
-static int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
-	       int width, int height, char *data)
-{
-	int i, ret;
-	char *cmd;
-	cycles_t start_cycles, end_cycles;
-	int bytes_sent = 0;
-	int bytes_identical = 0;
-	struct urb *urb;
-	int aligned_x;
-
-	start_cycles = get_cycles();
-
-	aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
-	width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
-	x = aligned_x;
-
-	if ((width <= 0) ||
-	    (x + width > dev->info->var.xres) ||
-	    (y + height > dev->info->var.yres))
-		return -EINVAL;
-
-	if (!atomic_read(&dev->usb_active))
-		return 0;
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return 0;
-	cmd = urb->transfer_buffer;
-
-	for (i = y; i < y + height ; i++) {
-		const int line_offset = dev->info->fix.line_length * i;
-		const int byte_offset = line_offset + (x * BPP);
-
-		if (dlfb_render_hline(dev, &urb,
-				      (char *) dev->info->fix.smem_start,
-				      &cmd, byte_offset, width * BPP,
-				      &bytes_identical, &bytes_sent))
-			goto error;
-	}
-
-	if (cmd > (char *) urb->transfer_buffer) {
-		/* Send partial buffer remaining before exiting */
-		int len = cmd - (char *) urb->transfer_buffer;
-		ret = dlfb_submit_urb(dev, urb, len);
-		bytes_sent += len;
-	} else
-		dlfb_urb_completion(urb);
-
-error:
-	atomic_add(bytes_sent, &dev->bytes_sent);
-	atomic_add(bytes_identical, &dev->bytes_identical);
-	atomic_add(width*height*2, &dev->bytes_rendered);
-	end_cycles = get_cycles();
-	atomic_add(((unsigned int) ((end_cycles - start_cycles)
-		    >> 10)), /* Kcycles */
-		   &dev->cpu_kcycles_used);
-
-	return 0;
-}
-
-/*
- * Path triggered by usermode clients who write to filesystem
- * e.g. cat filename > /dev/fb1
- * Not used by X Windows or text-mode console. But useful for testing.
- * Slow because of extra copy and we must assume all pixels dirty.
- */
-static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
-			  size_t count, loff_t *ppos)
-{
-	ssize_t result;
-	struct dlfb_data *dev = info->par;
-	u32 offset = (u32) *ppos;
-
-	result = fb_sys_write(info, buf, count, ppos);
-
-	if (result > 0) {
-		int start = max((int)(offset / info->fix.line_length), 0);
-		int lines = min((u32)((result / info->fix.line_length) + 1),
-				(u32)info->var.yres);
-
-		dlfb_handle_damage(dev, 0, start, info->var.xres,
-			lines, info->screen_base);
-	}
-
-	return result;
-}
-
-/* hardware has native COPY command (see libdlo), but not worth it for fbcon */
-static void dlfb_ops_copyarea(struct fb_info *info,
-				const struct fb_copyarea *area)
-{
-
-	struct dlfb_data *dev = info->par;
-
-	sys_copyarea(info, area);
-
-	dlfb_handle_damage(dev, area->dx, area->dy,
-			area->width, area->height, info->screen_base);
-}
-
-static void dlfb_ops_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	struct dlfb_data *dev = info->par;
-
-	sys_imageblit(info, image);
-
-	dlfb_handle_damage(dev, image->dx, image->dy,
-			image->width, image->height, info->screen_base);
-}
-
-static void dlfb_ops_fillrect(struct fb_info *info,
-			  const struct fb_fillrect *rect)
-{
-	struct dlfb_data *dev = info->par;
-
-	sys_fillrect(info, rect);
-
-	dlfb_handle_damage(dev, rect->dx, rect->dy, rect->width,
-			      rect->height, info->screen_base);
-}
-
-/*
- * NOTE: fb_defio.c is holding info->fbdefio.mutex
- *   Touching ANY framebuffer memory that triggers a page fault
- *   in fb_defio will cause a deadlock, when it also tries to
- *   grab the same mutex.
- */
-static void dlfb_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct dlfb_data *dev = info->par;
-	struct urb *urb;
-	char *cmd;
-	cycles_t start_cycles, end_cycles;
-	int bytes_sent = 0;
-	int bytes_identical = 0;
-	int bytes_rendered = 0;
-
-	if (!fb_defio)
-		return;
-
-	if (!atomic_read(&dev->usb_active))
-		return;
-
-	start_cycles = get_cycles();
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return;
-
-	cmd = urb->transfer_buffer;
-
-	/* walk the written page list and render each to device */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-
-		if (dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
-				  &cmd, cur->index << PAGE_SHIFT,
-				  PAGE_SIZE, &bytes_identical, &bytes_sent))
-			goto error;
-		bytes_rendered += PAGE_SIZE;
-	}
-
-	if (cmd > (char *) urb->transfer_buffer) {
-		/* Send partial buffer remaining before exiting */
-		int len = cmd - (char *) urb->transfer_buffer;
-		dlfb_submit_urb(dev, urb, len);
-		bytes_sent += len;
-	} else
-		dlfb_urb_completion(urb);
-
-error:
-	atomic_add(bytes_sent, &dev->bytes_sent);
-	atomic_add(bytes_identical, &dev->bytes_identical);
-	atomic_add(bytes_rendered, &dev->bytes_rendered);
-	end_cycles = get_cycles();
-	atomic_add(((unsigned int) ((end_cycles - start_cycles)
-		    >> 10)), /* Kcycles */
-		   &dev->cpu_kcycles_used);
-}
-
-static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
-{
-	int i;
-	int ret;
-	char *rbuf;
-
-	rbuf = kmalloc(2, GFP_KERNEL);
-	if (!rbuf)
-		return 0;
-
-	for (i = 0; i < len; i++) {
-		ret = usb_control_msg(dev->udev,
-				    usb_rcvctrlpipe(dev->udev, 0), (0x02),
-				    (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
-				    HZ);
-		if (ret < 1) {
-			pr_err("Read EDID byte %d failed err %x\n", i, ret);
-			i--;
-			break;
-		}
-		edid[i] = rbuf[1];
-	}
-
-	kfree(rbuf);
-
-	return i;
-}
-
-static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
-				unsigned long arg)
-{
-
-	struct dlfb_data *dev = info->par;
-
-	if (!atomic_read(&dev->usb_active))
-		return 0;
-
-	/* TODO: Update X server to get this from sysfs instead */
-	if (cmd == DLFB_IOCTL_RETURN_EDID) {
-		void __user *edid = (void __user *)arg;
-		if (copy_to_user(edid, dev->edid, dev->edid_size))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
-	if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
-		struct dloarea area;
-
-		if (copy_from_user(&area, (void __user *)arg,
-				  sizeof(struct dloarea)))
-			return -EFAULT;
-
-		/*
-		 * If we have a damage-aware client, turn fb_defio "off"
-		 * To avoid perf imact of unnecessary page fault handling.
-		 * Done by resetting the delay for this fb_info to a very
-		 * long period. Pages will become writable and stay that way.
-		 * Reset to normal value when all clients have closed this fb.
-		 */
-		if (info->fbdefio)
-			info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
-
-		if (area.x < 0)
-			area.x = 0;
-
-		if (area.x > info->var.xres)
-			area.x = info->var.xres;
-
-		if (area.y < 0)
-			area.y = 0;
-
-		if (area.y > info->var.yres)
-			area.y = info->var.yres;
-
-		dlfb_handle_damage(dev, area.x, area.y, area.w, area.h,
-			   info->screen_base);
-	}
-
-	return 0;
-}
-
-/* taken from vesafb */
-static int
-dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
-	       unsigned blue, unsigned transp, struct fb_info *info)
-{
-	int err = 0;
-
-	if (regno >= info->cmap.len)
-		return 1;
-
-	if (regno < 16) {
-		if (info->var.red.offset == 10) {
-			/* 1:5:5:5 */
-			((u32 *) (info->pseudo_palette))[regno] =
-			    ((red & 0xf800) >> 1) |
-			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
-		} else {
-			/* 0:5:6:5 */
-			((u32 *) (info->pseudo_palette))[regno] =
-			    ((red & 0xf800)) |
-			    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
-		}
-	}
-
-	return err;
-}
-
-/*
- * It's common for several clients to have framebuffer open simultaneously.
- * e.g. both fbcon and X. Makes things interesting.
- * Assumes caller is holding info->lock (for open and release at least)
- */
-static int dlfb_ops_open(struct fb_info *info, int user)
-{
-	struct dlfb_data *dev = info->par;
-
-	/*
-	 * fbcon aggressively connects to first framebuffer it finds,
-	 * preventing other clients (X) from working properly. Usually
-	 * not what the user wants. Fail by default with option to enable.
-	 */
-	if ((user == 0) && (!console))
-		return -EBUSY;
-
-	/* If the USB device is gone, we don't accept new opens */
-	if (dev->virtualized)
-		return -ENODEV;
-
-	dev->fb_count++;
-
-	kref_get(&dev->kref);
-
-	if (fb_defio && (info->fbdefio == NULL)) {
-		/* enable defio at last moment if not disabled by client */
-
-		struct fb_deferred_io *fbdefio;
-
-		fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
-
-		if (fbdefio) {
-			fbdefio->delay = DL_DEFIO_WRITE_DELAY;
-			fbdefio->deferred_io = dlfb_dpy_deferred_io;
-		}
-
-		info->fbdefio = fbdefio;
-		fb_deferred_io_init(info);
-	}
-
-	pr_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
-	    info->node, user, info, dev->fb_count);
-
-	return 0;
-}
-
-/*
- * Called when all client interfaces to start transactions have been disabled,
- * and all references to our device instance (dlfb_data) are released.
- * Every transaction must have a reference, so we know are fully spun down
- */
-static void dlfb_free(struct kref *kref)
-{
-	struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
-
-	if (dev->backing_buffer)
-		vfree(dev->backing_buffer);
-
-	kfree(dev->edid);
-
-	pr_warn("freeing dlfb_data %p\n", dev);
-
-	kfree(dev);
-}
-
-static void dlfb_release_urb_work(struct work_struct *work)
-{
-	struct urb_node *unode = container_of(work, struct urb_node,
-					      release_urb_work.work);
-
-	up(&unode->dev->urbs.limit_sem);
-}
-
-static void dlfb_free_framebuffer(struct dlfb_data *dev)
-{
-	struct fb_info *info = dev->info;
-
-	if (info) {
-		int node = info->node;
-
-		unregister_framebuffer(info);
-
-		if (info->cmap.len != 0)
-			fb_dealloc_cmap(&info->cmap);
-		if (info->monspecs.modedb)
-			fb_destroy_modedb(info->monspecs.modedb);
-		if (info->screen_base)
-			vfree(info->screen_base);
-
-		fb_destroy_modelist(&info->modelist);
-
-		dev->info = NULL;
-
-		/* Assume info structure is freed after this point */
-		framebuffer_release(info);
-
-		pr_warn("fb_info for /dev/fb%d has been freed\n", node);
-	}
-
-	/* ref taken in probe() as part of registering framebfufer */
-	kref_put(&dev->kref, dlfb_free);
-}
-
-static void dlfb_free_framebuffer_work(struct work_struct *work)
-{
-	struct dlfb_data *dev = container_of(work, struct dlfb_data,
-					     free_framebuffer_work.work);
-	dlfb_free_framebuffer(dev);
-}
-/*
- * Assumes caller is holding info->lock mutex (for open and release at least)
- */
-static int dlfb_ops_release(struct fb_info *info, int user)
-{
-	struct dlfb_data *dev = info->par;
-
-	dev->fb_count--;
-
-	/* We can't free fb_info here - fbmem will touch it when we return */
-	if (dev->virtualized && (dev->fb_count == 0))
-		schedule_delayed_work(&dev->free_framebuffer_work, HZ);
-
-	if ((dev->fb_count == 0) && (info->fbdefio)) {
-		fb_deferred_io_cleanup(info);
-		kfree(info->fbdefio);
-		info->fbdefio = NULL;
-		info->fbops->fb_mmap = dlfb_ops_mmap;
-	}
-
-	pr_warn("released /dev/fb%d user=%d count=%d\n",
-		  info->node, user, dev->fb_count);
-
-	kref_put(&dev->kref, dlfb_free);
-
-	return 0;
-}
-
-/*
- * Check whether a video mode is supported by the DisplayLink chip
- * We start from monitor's modes, so don't need to filter that here
- */
-static int dlfb_is_valid_mode(struct fb_videomode *mode,
-		struct fb_info *info)
-{
-	struct dlfb_data *dev = info->par;
-
-	if (mode->xres * mode->yres > dev->sku_pixel_limit) {
-		pr_warn("%dx%d beyond chip capabilities\n",
-		       mode->xres, mode->yres);
-		return 0;
-	}
-
-	pr_info("%dx%d @ %d Hz valid mode\n", mode->xres, mode->yres,
-		mode->refresh);
-
-	return 1;
-}
-
-static void dlfb_var_color_format(struct fb_var_screeninfo *var)
-{
-	const struct fb_bitfield red = { 11, 5, 0 };
-	const struct fb_bitfield green = { 5, 6, 0 };
-	const struct fb_bitfield blue = { 0, 5, 0 };
-
-	var->bits_per_pixel = 16;
-	var->red = red;
-	var->green = green;
-	var->blue = blue;
-}
-
-static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	struct fb_videomode mode;
-
-	/* TODO: support dynamically changing framebuffer size */
-	if ((var->xres * var->yres * 2) > info->fix.smem_len)
-		return -EINVAL;
-
-	/* set device-specific elements of var unrelated to mode */
-	dlfb_var_color_format(var);
-
-	fb_var_to_videomode(&mode, var);
-
-	if (!dlfb_is_valid_mode(&mode, info))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int dlfb_ops_set_par(struct fb_info *info)
-{
-	struct dlfb_data *dev = info->par;
-	int result;
-	u16 *pix_framebuffer;
-	int i;
-
-	pr_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
-
-	result = dlfb_set_video_mode(dev, &info->var);
-
-	if ((result == 0) && (dev->fb_count == 0)) {
-
-		/* paint greenscreen */
-
-		pix_framebuffer = (u16 *) info->screen_base;
-		for (i = 0; i < info->fix.smem_len / 2; i++)
-			pix_framebuffer[i] = 0x37e6;
-
-		dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
-				   info->screen_base);
-	}
-
-	return result;
-}
-
-/* To fonzi the jukebox (e.g. make blanking changes take effect) */
-static char *dlfb_dummy_render(char *buf)
-{
-	*buf++ = 0xAF;
-	*buf++ = 0x6A; /* copy */
-	*buf++ = 0x00; /* from address*/
-	*buf++ = 0x00;
-	*buf++ = 0x00;
-	*buf++ = 0x01; /* one pixel */
-	*buf++ = 0x00; /* to address */
-	*buf++ = 0x00;
-	*buf++ = 0x00;
-	return buf;
-}
-
-/*
- * In order to come back from full DPMS off, we need to set the mode again
- */
-static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
-{
-	struct dlfb_data *dev = info->par;
-	char *bufptr;
-	struct urb *urb;
-
-	pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
-		info->node, dev->blank_mode, blank_mode);
-
-	if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
-	    (blank_mode != FB_BLANK_POWERDOWN)) {
-
-		/* returning from powerdown requires a fresh modeset */
-		dlfb_set_video_mode(dev, &info->var);
-	}
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return 0;
-
-	bufptr = (char *) urb->transfer_buffer;
-	bufptr = dlfb_vidreg_lock(bufptr);
-	bufptr = dlfb_blanking(bufptr, blank_mode);
-	bufptr = dlfb_vidreg_unlock(bufptr);
-
-	/* seems like a render op is needed to have blank change take effect */
-	bufptr = dlfb_dummy_render(bufptr);
-
-	dlfb_submit_urb(dev, urb, bufptr -
-			(char *) urb->transfer_buffer);
-
-	dev->blank_mode = blank_mode;
-
-	return 0;
-}
-
-static struct fb_ops dlfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_read = fb_sys_read,
-	.fb_write = dlfb_ops_write,
-	.fb_setcolreg = dlfb_ops_setcolreg,
-	.fb_fillrect = dlfb_ops_fillrect,
-	.fb_copyarea = dlfb_ops_copyarea,
-	.fb_imageblit = dlfb_ops_imageblit,
-	.fb_mmap = dlfb_ops_mmap,
-	.fb_ioctl = dlfb_ops_ioctl,
-	.fb_open = dlfb_ops_open,
-	.fb_release = dlfb_ops_release,
-	.fb_blank = dlfb_ops_blank,
-	.fb_check_var = dlfb_ops_check_var,
-	.fb_set_par = dlfb_ops_set_par,
-};
-
-
-/*
- * Assumes &info->lock held by caller
- * Assumes no active clients have framebuffer open
- */
-static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
-{
-	int retval = -ENOMEM;
-	int old_len = info->fix.smem_len;
-	int new_len;
-	unsigned char *old_fb = info->screen_base;
-	unsigned char *new_fb;
-	unsigned char *new_back = NULL;
-
-	pr_warn("Reallocating framebuffer. Addresses will change!\n");
-
-	new_len = info->fix.line_length * info->var.yres;
-
-	if (PAGE_ALIGN(new_len) > old_len) {
-		/*
-		 * Alloc system memory for virtual framebuffer
-		 */
-		new_fb = vmalloc(new_len);
-		if (!new_fb) {
-			pr_err("Virtual framebuffer alloc failed\n");
-			goto error;
-		}
-
-		if (info->screen_base) {
-			memcpy(new_fb, old_fb, old_len);
-			vfree(info->screen_base);
-		}
-
-		info->screen_base = new_fb;
-		info->fix.smem_len = PAGE_ALIGN(new_len);
-		info->fix.smem_start = (unsigned long) new_fb;
-		info->flags = udlfb_info_flags;
-
-		/*
-		 * Second framebuffer copy to mirror the framebuffer state
-		 * on the physical USB device. We can function without this.
-		 * But with imperfect damage info we may send pixels over USB
-		 * that were, in fact, unchanged - wasting limited USB bandwidth
-		 */
-		if (shadow)
-			new_back = vzalloc(new_len);
-		if (!new_back)
-			pr_info("No shadow/backing buffer allocated\n");
-		else {
-			if (dev->backing_buffer)
-				vfree(dev->backing_buffer);
-			dev->backing_buffer = new_back;
-		}
-	}
-
-	retval = 0;
-
-error:
-	return retval;
-}
-
-/*
- * 1) Get EDID from hw, or use sw default
- * 2) Parse into various fb_info structs
- * 3) Allocate virtual framebuffer memory to back highest res mode
- *
- * Parses EDID into three places used by various parts of fbdev:
- * fb_var_screeninfo contains the timing of the monitor's preferred mode
- * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
- * fb_info.modelist is a linked list of all monitor & VESA modes which work
- *
- * If EDID is not readable/valid, then modelist is all VESA modes,
- * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
- * Returns 0 if successful
- */
-static int dlfb_setup_modes(struct dlfb_data *dev,
-			   struct fb_info *info,
-			   char *default_edid, size_t default_edid_size)
-{
-	int i;
-	const struct fb_videomode *default_vmode = NULL;
-	int result = 0;
-	char *edid;
-	int tries = 3;
-
-	if (info->dev) /* only use mutex if info has been registered */
-		mutex_lock(&info->lock);
-
-	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-	if (!edid) {
-		result = -ENOMEM;
-		goto error;
-	}
-
-	fb_destroy_modelist(&info->modelist);
-	memset(&info->monspecs, 0, sizeof(info->monspecs));
-
-	/*
-	 * Try to (re)read EDID from hardware first
-	 * EDID data may return, but not parse as valid
-	 * Try again a few times, in case of e.g. analog cable noise
-	 */
-	while (tries--) {
-
-		i = dlfb_get_edid(dev, edid, EDID_LENGTH);
-
-		if (i >= EDID_LENGTH)
-			fb_edid_to_monspecs(edid, &info->monspecs);
-
-		if (info->monspecs.modedb_len > 0) {
-			dev->edid = edid;
-			dev->edid_size = i;
-			break;
-		}
-	}
-
-	/* If that fails, use a previously returned EDID if available */
-	if (info->monspecs.modedb_len == 0) {
-
-		pr_err("Unable to get valid EDID from device/display\n");
-
-		if (dev->edid) {
-			fb_edid_to_monspecs(dev->edid, &info->monspecs);
-			if (info->monspecs.modedb_len > 0)
-				pr_err("Using previously queried EDID\n");
-		}
-	}
-
-	/* If that fails, use the default EDID we were handed */
-	if (info->monspecs.modedb_len == 0) {
-		if (default_edid_size >= EDID_LENGTH) {
-			fb_edid_to_monspecs(default_edid, &info->monspecs);
-			if (info->monspecs.modedb_len > 0) {
-				memcpy(edid, default_edid, default_edid_size);
-				dev->edid = edid;
-				dev->edid_size = default_edid_size;
-				pr_err("Using default/backup EDID\n");
-			}
-		}
-	}
-
-	/* If we've got modes, let's pick a best default mode */
-	if (info->monspecs.modedb_len > 0) {
-
-		for (i = 0; i < info->monspecs.modedb_len; i++) {
-			if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info))
-				fb_add_videomode(&info->monspecs.modedb[i],
-					&info->modelist);
-			else {
-				if (i == 0)
-					/* if we've removed top/best mode */
-					info->monspecs.misc
-						&= ~FB_MISC_1ST_DETAIL;
-			}
-		}
-
-		default_vmode = fb_find_best_display(&info->monspecs,
-						     &info->modelist);
-	}
-
-	/* If everything else has failed, fall back to safe default mode */
-	if (default_vmode == NULL) {
-
-		struct fb_videomode fb_vmode = {0};
-
-		/*
-		 * Add the standard VESA modes to our modelist
-		 * Since we don't have EDID, there may be modes that
-		 * overspec monitor and/or are incorrect aspect ratio, etc.
-		 * But at least the user has a chance to choose
-		 */
-		for (i = 0; i < VESA_MODEDB_SIZE; i++) {
-			if (dlfb_is_valid_mode((struct fb_videomode *)
-						&vesa_modes[i], info))
-				fb_add_videomode(&vesa_modes[i],
-						 &info->modelist);
-		}
-
-		/*
-		 * default to resolution safe for projectors
-		 * (since they are most common case without EDID)
-		 */
-		fb_vmode.xres = 800;
-		fb_vmode.yres = 600;
-		fb_vmode.refresh = 60;
-		default_vmode = fb_find_nearest_mode(&fb_vmode,
-						     &info->modelist);
-	}
-
-	/* If we have good mode and no active clients*/
-	if ((default_vmode != NULL) && (dev->fb_count == 0)) {
-
-		fb_videomode_to_var(&info->var, default_vmode);
-		dlfb_var_color_format(&info->var);
-
-		/*
-		 * with mode size info, we can now alloc our framebuffer.
-		 */
-		memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
-		info->fix.line_length = info->var.xres *
-			(info->var.bits_per_pixel / 8);
-
-		result = dlfb_realloc_framebuffer(dev, info);
-
-	} else
-		result = -EINVAL;
-
-error:
-	if (edid && (dev->edid != edid))
-		kfree(edid);
-
-	if (info->dev)
-		mutex_unlock(&info->lock);
-
-	return result;
-}
-
-static ssize_t metrics_bytes_rendered_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->bytes_rendered));
-}
-
-static ssize_t metrics_bytes_identical_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->bytes_identical));
-}
-
-static ssize_t metrics_bytes_sent_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->bytes_sent));
-}
-
-static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->cpu_kcycles_used));
-}
-
-static ssize_t edid_show(
-			struct file *filp,
-			struct kobject *kobj, struct bin_attribute *a,
-			 char *buf, loff_t off, size_t count) {
-	struct device *fbdev = container_of(kobj, struct device, kobj);
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-
-	if (dev->edid == NULL)
-		return 0;
-
-	if ((off >= dev->edid_size) || (count > dev->edid_size))
-		return 0;
-
-	if (off + count > dev->edid_size)
-		count = dev->edid_size - off;
-
-	pr_info("sysfs edid copy %p to %p, %d bytes\n",
-		dev->edid, buf, (int) count);
-
-	memcpy(buf, dev->edid, count);
-
-	return count;
-}
-
-static ssize_t edid_store(
-			struct file *filp,
-			struct kobject *kobj, struct bin_attribute *a,
-			char *src, loff_t src_off, size_t src_size) {
-	struct device *fbdev = container_of(kobj, struct device, kobj);
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	int ret;
-
-	/* We only support write of entire EDID at once, no offset*/
-	if ((src_size != EDID_LENGTH) || (src_off != 0))
-		return -EINVAL;
-
-	ret = dlfb_setup_modes(dev, fb_info, src, src_size);
-	if (ret)
-		return ret;
-
-	if (!dev->edid || memcmp(src, dev->edid, src_size))
-		return -EINVAL;
-
-	pr_info("sysfs written EDID is new default\n");
-	dlfb_ops_set_par(fb_info);
-	return src_size;
-}
-
-static ssize_t metrics_reset_store(struct device *fbdev,
-			   struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-
-	atomic_set(&dev->bytes_rendered, 0);
-	atomic_set(&dev->bytes_identical, 0);
-	atomic_set(&dev->bytes_sent, 0);
-	atomic_set(&dev->cpu_kcycles_used, 0);
-
-	return count;
-}
-
-static struct bin_attribute edid_attr = {
-	.attr.name = "edid",
-	.attr.mode = 0666,
-	.size = EDID_LENGTH,
-	.read = edid_show,
-	.write = edid_store
-};
-
-static struct device_attribute fb_device_attrs[] = {
-	__ATTR_RO(metrics_bytes_rendered),
-	__ATTR_RO(metrics_bytes_identical),
-	__ATTR_RO(metrics_bytes_sent),
-	__ATTR_RO(metrics_cpu_kcycles_used),
-	__ATTR(metrics_reset, S_IWUSR, NULL, metrics_reset_store),
-};
-
-/*
- * This is necessary before we can communicate with the display controller.
- */
-static int dlfb_select_std_channel(struct dlfb_data *dev)
-{
-	int ret;
-	u8 set_def_chn[] = {	   0x57, 0xCD, 0xDC, 0xA7,
-				0x1C, 0x88, 0x5E, 0x15,
-				0x60, 0xFE, 0xC6, 0x97,
-				0x16, 0x3D, 0x47, 0xF2  };
-
-	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-			NR_USB_REQUEST_CHANNEL,
-			(USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
-			set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
-	return ret;
-}
-
-static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
-					struct usb_interface *interface)
-{
-	char *desc;
-	char *buf;
-	char *desc_end;
-
-	int total_len = 0;
-
-	buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
-	if (!buf)
-		return false;
-	desc = buf;
-
-	total_len = usb_get_descriptor(interface_to_usbdev(interface),
-					0x5f, /* vendor specific */
-					0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
-
-	/* if not found, look in configuration descriptor */
-	if (total_len < 0) {
-		if (0 == usb_get_extra_descriptor(interface->cur_altsetting,
-			0x5f, &desc))
-			total_len = (int) desc[0];
-	}
-
-	if (total_len > 5) {
-		pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
-			"%02x %02x %02x %02x %02x %02x %02x\n",
-			total_len, desc[0],
-			desc[1], desc[2], desc[3], desc[4], desc[5], desc[6],
-			desc[7], desc[8], desc[9], desc[10]);
-
-		if ((desc[0] != total_len) || /* descriptor length */
-		    (desc[1] != 0x5f) ||   /* vendor descriptor type */
-		    (desc[2] != 0x01) ||   /* version (2 bytes) */
-		    (desc[3] != 0x00) ||
-		    (desc[4] != total_len - 2)) /* length after type */
-			goto unrecognized;
-
-		desc_end = desc + total_len;
-		desc += 5; /* the fixed header we've already parsed */
-
-		while (desc < desc_end) {
-			u8 length;
-			u16 key;
-
-			key = le16_to_cpu(*((u16 *) desc));
-			desc += sizeof(u16);
-			length = *desc;
-			desc++;
-
-			switch (key) {
-			case 0x0200: { /* max_area */
-				u32 max_area;
-				max_area = le32_to_cpu(*((u32 *)desc));
-				pr_warn("DL chip limited to %d pixel modes\n",
-					max_area);
-				dev->sku_pixel_limit = max_area;
-				break;
-			}
-			default:
-				break;
-			}
-			desc += length;
-		}
-	} else {
-		pr_info("vendor descriptor not available (%d)\n", total_len);
-	}
-
-	goto success;
-
-unrecognized:
-	/* allow udlfb to load for now even if firmware unrecognized */
-	pr_err("Unrecognized vendor firmware descriptor\n");
-
-success:
-	kfree(buf);
-	return true;
-}
-
-static void dlfb_init_framebuffer_work(struct work_struct *work);
-
-static int dlfb_usb_probe(struct usb_interface *interface,
-			const struct usb_device_id *id)
-{
-	struct usb_device *usbdev;
-	struct dlfb_data *dev = NULL;
-	int retval = -ENOMEM;
-
-	/* usb initialization */
-
-	usbdev = interface_to_usbdev(interface);
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL) {
-		dev_err(&interface->dev, "dlfb_usb_probe: failed alloc of dev struct\n");
-		goto error;
-	}
-
-	kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
-
-	dev->udev = usbdev;
-	dev->gdev = &usbdev->dev; /* our generic struct device * */
-	usb_set_intfdata(interface, dev);
-
-	pr_info("%s %s - serial #%s\n",
-		usbdev->manufacturer, usbdev->product, usbdev->serial);
-	pr_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
-		usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-		usbdev->descriptor.bcdDevice, dev);
-	pr_info("console enable=%d\n", console);
-	pr_info("fb_defio enable=%d\n", fb_defio);
-	pr_info("shadow enable=%d\n", shadow);
-
-	dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
-
-	if (!dlfb_parse_vendor_descriptor(dev, interface)) {
-		pr_err("firmware not recognized. Assume incompatible device\n");
-		goto error;
-	}
-
-	if (pixel_limit) {
-		pr_warn("DL chip limit of %d overridden"
-			" by module param to %d\n",
-			dev->sku_pixel_limit, pixel_limit);
-		dev->sku_pixel_limit = pixel_limit;
-	}
-
-
-	if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
-		retval = -ENOMEM;
-		pr_err("dlfb_alloc_urb_list failed\n");
-		goto error;
-	}
-
-	kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
-
-	/* We don't register a new USB class. Our client interface is fbdev */
-
-	/* Workitem keep things fast & simple during USB enumeration */
-	INIT_DELAYED_WORK(&dev->init_framebuffer_work,
-			  dlfb_init_framebuffer_work);
-	schedule_delayed_work(&dev->init_framebuffer_work, 0);
-
-	return 0;
-
-error:
-	if (dev) {
-
-		kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
-		kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
-
-		/* dev has been deallocated. Do not dereference */
-	}
-
-	return retval;
-}
-
-static void dlfb_init_framebuffer_work(struct work_struct *work)
-{
-	struct dlfb_data *dev = container_of(work, struct dlfb_data,
-					     init_framebuffer_work.work);
-	struct fb_info *info;
-	int retval;
-	int i;
-
-	/* allocates framebuffer driver structure, not framebuffer memory */
-	info = framebuffer_alloc(0, dev->gdev);
-	if (!info) {
-		retval = -ENOMEM;
-		pr_err("framebuffer_alloc failed\n");
-		goto error;
-	}
-
-	dev->info = info;
-	info->par = dev;
-	info->pseudo_palette = dev->pseudo_palette;
-	info->fbops = &dlfb_ops;
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0) {
-		pr_err("fb_alloc_cmap failed %x\n", retval);
-		goto error;
-	}
-
-	INIT_DELAYED_WORK(&dev->free_framebuffer_work,
-			  dlfb_free_framebuffer_work);
-
-	INIT_LIST_HEAD(&info->modelist);
-
-	retval = dlfb_setup_modes(dev, info, NULL, 0);
-	if (retval != 0) {
-		pr_err("unable to find common mode for display and adapter\n");
-		goto error;
-	}
-
-	/* ready to begin using device */
-
-	atomic_set(&dev->usb_active, 1);
-	dlfb_select_std_channel(dev);
-
-	dlfb_ops_check_var(&info->var, info);
-	dlfb_ops_set_par(info);
-
-	retval = register_framebuffer(info);
-	if (retval < 0) {
-		pr_err("register_framebuffer failed %d\n", retval);
-		goto error;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) {
-		retval = device_create_file(info->dev, &fb_device_attrs[i]);
-		if (retval) {
-			pr_warn("device_create_file failed %d\n", retval);
-		}
-	}
-
-	retval = device_create_bin_file(info->dev, &edid_attr);
-	if (retval) {
-		pr_warn("device_create_bin_file failed %d\n", retval);
-	}
-
-	pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
-			" Using %dK framebuffer memory\n", info->node,
-			info->var.xres, info->var.yres,
-			((dev->backing_buffer) ?
-			info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
-	return;
-
-error:
-	dlfb_free_framebuffer(dev);
-}
-
-static void dlfb_usb_disconnect(struct usb_interface *interface)
-{
-	struct dlfb_data *dev;
-	struct fb_info *info;
-	int i;
-
-	dev = usb_get_intfdata(interface);
-	info = dev->info;
-
-	pr_info("USB disconnect starting\n");
-
-	/* we virtualize until all fb clients release. Then we free */
-	dev->virtualized = true;
-
-	/* When non-active we'll update virtual framebuffer, but no new urbs */
-	atomic_set(&dev->usb_active, 0);
-
-	/* this function will wait for all in-flight urbs to complete */
-	dlfb_free_urb_list(dev);
-
-	if (info) {
-		/* remove udlfb's sysfs interfaces */
-		for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
-			device_remove_file(info->dev, &fb_device_attrs[i]);
-		device_remove_bin_file(info->dev, &edid_attr);
-		unlink_framebuffer(info);
-	}
-
-	usb_set_intfdata(interface, NULL);
-	dev->udev = NULL;
-	dev->gdev = NULL;
-
-	/* if clients still have us open, will be freed on last close */
-	if (dev->fb_count == 0)
-		schedule_delayed_work(&dev->free_framebuffer_work, 0);
-
-	/* release reference taken by kref_init in probe() */
-	kref_put(&dev->kref, dlfb_free);
-
-	/* consider dlfb_data freed */
-
-	return;
-}
-
-static struct usb_driver dlfb_driver = {
-	.name = "udlfb",
-	.probe = dlfb_usb_probe,
-	.disconnect = dlfb_usb_disconnect,
-	.id_table = id_table,
-};
-
-module_usb_driver(dlfb_driver);
-
-static void dlfb_urb_completion(struct urb *urb)
-{
-	struct urb_node *unode = urb->context;
-	struct dlfb_data *dev = unode->dev;
-	unsigned long flags;
-
-	/* sync/async unlink faults aren't errors */
-	if (urb->status) {
-		if (!(urb->status == -ENOENT ||
-		    urb->status == -ECONNRESET ||
-		    urb->status == -ESHUTDOWN)) {
-			pr_err("%s - nonzero write bulk status received: %d\n",
-				__func__, urb->status);
-			atomic_set(&dev->lost_pixels, 1);
-		}
-	}
-
-	urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
-
-	spin_lock_irqsave(&dev->urbs.lock, flags);
-	list_add_tail(&unode->entry, &dev->urbs.list);
-	dev->urbs.available++;
-	spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-	/*
-	 * When using fb_defio, we deadlock if up() is called
-	 * while another is waiting. So queue to another process.
-	 */
-	if (fb_defio)
-		schedule_delayed_work(&unode->release_urb_work, 0);
-	else
-		up(&dev->urbs.limit_sem);
-}
-
-static void dlfb_free_urb_list(struct dlfb_data *dev)
-{
-	int count = dev->urbs.count;
-	struct list_head *node;
-	struct urb_node *unode;
-	struct urb *urb;
-	int ret;
-	unsigned long flags;
-
-	pr_notice("Freeing all render urbs\n");
-
-	/* keep waiting and freeing, until we've got 'em all */
-	while (count--) {
-
-		/* Getting interrupted means a leak, but ok at disconnect */
-		ret = down_interruptible(&dev->urbs.limit_sem);
-		if (ret)
-			break;
-
-		spin_lock_irqsave(&dev->urbs.lock, flags);
-
-		node = dev->urbs.list.next; /* have reserved one with sem */
-		list_del_init(node);
-
-		spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-		unode = list_entry(node, struct urb_node, entry);
-		urb = unode->urb;
-
-		/* Free each separately allocated piece */
-		usb_free_coherent(urb->dev, dev->urbs.size,
-				  urb->transfer_buffer, urb->transfer_dma);
-		usb_free_urb(urb);
-		kfree(node);
-	}
-
-	dev->urbs.count = 0;
-}
-
-static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
-{
-	int i = 0;
-	struct urb *urb;
-	struct urb_node *unode;
-	char *buf;
-
-	spin_lock_init(&dev->urbs.lock);
-
-	dev->urbs.size = size;
-	INIT_LIST_HEAD(&dev->urbs.list);
-
-	while (i < count) {
-		unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
-		if (!unode)
-			break;
-		unode->dev = dev;
-
-		INIT_DELAYED_WORK(&unode->release_urb_work,
-			  dlfb_release_urb_work);
-
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb) {
-			kfree(unode);
-			break;
-		}
-		unode->urb = urb;
-
-		buf = usb_alloc_coherent(dev->udev, MAX_TRANSFER, GFP_KERNEL,
-					 &urb->transfer_dma);
-		if (!buf) {
-			kfree(unode);
-			usb_free_urb(urb);
-			break;
-		}
-
-		/* urb->transfer_buffer_length set to actual before submit */
-		usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
-			buf, size, dlfb_urb_completion, unode);
-		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-		list_add_tail(&unode->entry, &dev->urbs.list);
-
-		i++;
-	}
-
-	sema_init(&dev->urbs.limit_sem, i);
-	dev->urbs.count = i;
-	dev->urbs.available = i;
-
-	pr_notice("allocated %d %d byte urbs\n", i, (int) size);
-
-	return i;
-}
-
-static struct urb *dlfb_get_urb(struct dlfb_data *dev)
-{
-	int ret = 0;
-	struct list_head *entry;
-	struct urb_node *unode;
-	struct urb *urb = NULL;
-	unsigned long flags;
-
-	/* Wait for an in-flight buffer to complete and get re-queued */
-	ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
-	if (ret) {
-		atomic_set(&dev->lost_pixels, 1);
-		pr_warn("wait for urb interrupted: %x available: %d\n",
-		       ret, dev->urbs.available);
-		goto error;
-	}
-
-	spin_lock_irqsave(&dev->urbs.lock, flags);
-
-	BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
-	entry = dev->urbs.list.next;
-	list_del_init(entry);
-	dev->urbs.available--;
-
-	spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-	unode = list_entry(entry, struct urb_node, entry);
-	urb = unode->urb;
-
-error:
-	return urb;
-}
-
-static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
-{
-	int ret;
-
-	BUG_ON(len > dev->urbs.size);
-
-	urb->transfer_buffer_length = len; /* set to actual payload len */
-	ret = usb_submit_urb(urb, GFP_KERNEL);
-	if (ret) {
-		dlfb_urb_completion(urb); /* because no one else will */
-		atomic_set(&dev->lost_pixels, 1);
-		pr_err("usb_submit_urb error %x\n", ret);
-	}
-	return ret;
-}
-
-module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(console, "Allow fbcon to open framebuffer");
-
-module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
-
-module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
-
-module_param(pixel_limit, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(pixel_limit, "Force limit on max mode (in x*y pixels)");
-
-MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
-	      "Jaya Kumar <jayakumar.lkml@gmail.com>, "
-	      "Bernie Thompson <bernie@plugable.com>");
-MODULE_DESCRIPTION("DisplayLink kernel framebuffer driver");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
deleted file mode 100644
index 509d452e8f91..000000000000
--- a/drivers/video/uvesafb.c
+++ /dev/null
@@ -1,2028 +0,0 @@
-/*
- * A framebuffer driver for VBE 2.0+ compliant video cards
- *
- * (c) 2007 Michal Januszewski <spock@gentoo.org>
- *     Loosely based upon the vesafb driver.
- *
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/skbuff.h>
-#include <linux/timer.h>
-#include <linux/completion.h>
-#include <linux/connector.h>
-#include <linux/random.h>
-#include <linux/platform_device.h>
-#include <linux/limits.h>
-#include <linux/fb.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <video/edid.h>
-#include <video/uvesafb.h>
-#ifdef CONFIG_X86
-#include <video/vga.h>
-#endif
-#include "edid.h"
-
-static struct cb_id uvesafb_cn_id = {
-	.idx = CN_IDX_V86D,
-	.val = CN_VAL_V86D_UVESAFB
-};
-static char v86d_path[PATH_MAX] = "/sbin/v86d";
-static char v86d_started;	/* has v86d been started by uvesafb? */
-
-static struct fb_fix_screeninfo uvesafb_fix = {
-	.id	= "VESA VGA",
-	.type	= FB_TYPE_PACKED_PIXELS,
-	.accel	= FB_ACCEL_NONE,
-	.visual = FB_VISUAL_TRUECOLOR,
-};
-
-static int mtrr		= 3;	/* enable mtrr by default */
-static bool blank	= 1;	/* enable blanking by default */
-static int ypan		= 1;	/* 0: scroll, 1: ypan, 2: ywrap */
-static bool pmi_setpal	= true; /* use PMI for palette changes */
-static bool nocrtc;		/* ignore CRTC settings */
-static bool noedid;		/* don't try DDC transfers */
-static int vram_remap;		/* set amt. of memory to be used */
-static int vram_total;		/* set total amount of memory */
-static u16 maxclk;		/* maximum pixel clock */
-static u16 maxvf;		/* maximum vertical frequency */
-static u16 maxhf;		/* maximum horizontal frequency */
-static u16 vbemode;		/* force use of a specific VBE mode */
-static char *mode_option;
-static u8  dac_width	= 6;
-
-static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
-static DEFINE_MUTEX(uvfb_lock);
-
-/*
- * A handler for replies from userspace.
- *
- * Make sure each message passes consistency checks and if it does,
- * find the kernel part of the task struct, copy the registers and
- * the buffer contents and then complete the task.
- */
-static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
-	struct uvesafb_task *utask;
-	struct uvesafb_ktask *task;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return;
-
-	if (msg->seq >= UVESAFB_TASKS_MAX)
-		return;
-
-	mutex_lock(&uvfb_lock);
-	task = uvfb_tasks[msg->seq];
-
-	if (!task || msg->ack != task->ack) {
-		mutex_unlock(&uvfb_lock);
-		return;
-	}
-
-	utask = (struct uvesafb_task *)msg->data;
-
-	/* Sanity checks for the buffer length. */
-	if (task->t.buf_len < utask->buf_len ||
-	    utask->buf_len > msg->len - sizeof(*utask)) {
-		mutex_unlock(&uvfb_lock);
-		return;
-	}
-
-	uvfb_tasks[msg->seq] = NULL;
-	mutex_unlock(&uvfb_lock);
-
-	memcpy(&task->t, utask, sizeof(*utask));
-
-	if (task->t.buf_len && task->buf)
-		memcpy(task->buf, utask + 1, task->t.buf_len);
-
-	complete(task->done);
-	return;
-}
-
-static int uvesafb_helper_start(void)
-{
-	char *envp[] = {
-		"HOME=/",
-		"PATH=/sbin:/bin",
-		NULL,
-	};
-
-	char *argv[] = {
-		v86d_path,
-		NULL,
-	};
-
-	return call_usermodehelper(v86d_path, argv, envp, UMH_WAIT_PROC);
-}
-
-/*
- * Execute a uvesafb task.
- *
- * Returns 0 if the task is executed successfully.
- *
- * A message sent to the userspace consists of the uvesafb_task
- * struct and (optionally) a buffer. The uvesafb_task struct is
- * a simplified version of uvesafb_ktask (its kernel counterpart)
- * containing only the register values, flags and the length of
- * the buffer.
- *
- * Each message is assigned a sequence number (increased linearly)
- * and a random ack number. The sequence number is used as a key
- * for the uvfb_tasks array which holds pointers to uvesafb_ktask
- * structs for all requests.
- */
-static int uvesafb_exec(struct uvesafb_ktask *task)
-{
-	static int seq;
-	struct cn_msg *m;
-	int err;
-	int len = sizeof(task->t) + task->t.buf_len;
-
-	/*
-	 * Check whether the message isn't longer than the maximum
-	 * allowed by connector.
-	 */
-	if (sizeof(*m) + len > CONNECTOR_MAX_MSG_SIZE) {
-		printk(KERN_WARNING "uvesafb: message too long (%d), "
-			"can't execute task\n", (int)(sizeof(*m) + len));
-		return -E2BIG;
-	}
-
-	m = kzalloc(sizeof(*m) + len, GFP_KERNEL);
-	if (!m)
-		return -ENOMEM;
-
-	init_completion(task->done);
-
-	memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id));
-	m->seq = seq;
-	m->len = len;
-	m->ack = prandom_u32();
-
-	/* uvesafb_task structure */
-	memcpy(m + 1, &task->t, sizeof(task->t));
-
-	/* Buffer */
-	memcpy((u8 *)(m + 1) + sizeof(task->t), task->buf, task->t.buf_len);
-
-	/*
-	 * Save the message ack number so that we can find the kernel
-	 * part of this task when a reply is received from userspace.
-	 */
-	task->ack = m->ack;
-
-	mutex_lock(&uvfb_lock);
-
-	/* If all slots are taken -- bail out. */
-	if (uvfb_tasks[seq]) {
-		mutex_unlock(&uvfb_lock);
-		err = -EBUSY;
-		goto out;
-	}
-
-	/* Save a pointer to the kernel part of the task struct. */
-	uvfb_tasks[seq] = task;
-	mutex_unlock(&uvfb_lock);
-
-	err = cn_netlink_send(m, 0, 0, GFP_KERNEL);
-	if (err == -ESRCH) {
-		/*
-		 * Try to start the userspace helper if sending
-		 * the request failed the first time.
-		 */
-		err = uvesafb_helper_start();
-		if (err) {
-			printk(KERN_ERR "uvesafb: failed to execute %s\n",
-					v86d_path);
-			printk(KERN_ERR "uvesafb: make sure that the v86d "
-					"helper is installed and executable\n");
-		} else {
-			v86d_started = 1;
-			err = cn_netlink_send(m, 0, 0, gfp_any());
-			if (err == -ENOBUFS)
-				err = 0;
-		}
-	} else if (err == -ENOBUFS)
-		err = 0;
-
-	if (!err && !(task->t.flags & TF_EXIT))
-		err = !wait_for_completion_timeout(task->done,
-				msecs_to_jiffies(UVESAFB_TIMEOUT));
-
-	mutex_lock(&uvfb_lock);
-	uvfb_tasks[seq] = NULL;
-	mutex_unlock(&uvfb_lock);
-
-	seq++;
-	if (seq >= UVESAFB_TASKS_MAX)
-		seq = 0;
-out:
-	kfree(m);
-	return err;
-}
-
-/*
- * Free a uvesafb_ktask struct.
- */
-static void uvesafb_free(struct uvesafb_ktask *task)
-{
-	if (task) {
-		kfree(task->done);
-		kfree(task);
-	}
-}
-
-/*
- * Prepare a uvesafb_ktask struct to be used again.
- */
-static void uvesafb_reset(struct uvesafb_ktask *task)
-{
-	struct completion *cpl = task->done;
-
-	memset(task, 0, sizeof(*task));
-	task->done = cpl;
-}
-
-/*
- * Allocate and prepare a uvesafb_ktask struct.
- */
-static struct uvesafb_ktask *uvesafb_prep(void)
-{
-	struct uvesafb_ktask *task;
-
-	task = kzalloc(sizeof(*task), GFP_KERNEL);
-	if (task) {
-		task->done = kzalloc(sizeof(*task->done), GFP_KERNEL);
-		if (!task->done) {
-			kfree(task);
-			task = NULL;
-		}
-	}
-	return task;
-}
-
-static void uvesafb_setup_var(struct fb_var_screeninfo *var,
-		struct fb_info *info, struct vbe_mode_ib *mode)
-{
-	struct uvesafb_par *par = info->par;
-
-	var->vmode = FB_VMODE_NONINTERLACED;
-	var->sync = FB_SYNC_VERT_HIGH_ACT;
-
-	var->xres = mode->x_res;
-	var->yres = mode->y_res;
-	var->xres_virtual = mode->x_res;
-	var->yres_virtual = (par->ypan) ?
-			info->fix.smem_len / mode->bytes_per_scan_line :
-			mode->y_res;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->bits_per_pixel = mode->bits_per_pixel;
-
-	if (var->bits_per_pixel == 15)
-		var->bits_per_pixel = 16;
-
-	if (var->bits_per_pixel > 8) {
-		var->red.offset    = mode->red_off;
-		var->red.length    = mode->red_len;
-		var->green.offset  = mode->green_off;
-		var->green.length  = mode->green_len;
-		var->blue.offset   = mode->blue_off;
-		var->blue.length   = mode->blue_len;
-		var->transp.offset = mode->rsvd_off;
-		var->transp.length = mode->rsvd_len;
-	} else {
-		var->red.offset    = 0;
-		var->green.offset  = 0;
-		var->blue.offset   = 0;
-		var->transp.offset = 0;
-
-		var->red.length    = 8;
-		var->green.length  = 8;
-		var->blue.length   = 8;
-		var->transp.length = 0;
-	}
-}
-
-static int uvesafb_vbe_find_mode(struct uvesafb_par *par,
-		int xres, int yres, int depth, unsigned char flags)
-{
-	int i, match = -1, h = 0, d = 0x7fffffff;
-
-	for (i = 0; i < par->vbe_modes_cnt; i++) {
-		h = abs(par->vbe_modes[i].x_res - xres) +
-		    abs(par->vbe_modes[i].y_res - yres) +
-		    abs(depth - par->vbe_modes[i].depth);
-
-		/*
-		 * We have an exact match in terms of resolution
-		 * and depth.
-		 */
-		if (h == 0)
-			return i;
-
-		if (h < d || (h == d && par->vbe_modes[i].depth > depth)) {
-			d = h;
-			match = i;
-		}
-	}
-	i = 1;
-
-	if (flags & UVESAFB_EXACT_DEPTH &&
-			par->vbe_modes[match].depth != depth)
-		i = 0;
-
-	if (flags & UVESAFB_EXACT_RES && d > 24)
-		i = 0;
-
-	if (i != 0)
-		return match;
-	else
-		return -1;
-}
-
-static u8 *uvesafb_vbe_state_save(struct uvesafb_par *par)
-{
-	struct uvesafb_ktask *task;
-	u8 *state;
-	int err;
-
-	if (!par->vbe_state_size)
-		return NULL;
-
-	state = kmalloc(par->vbe_state_size, GFP_KERNEL);
-	if (!state)
-		return ERR_PTR(-ENOMEM);
-
-	task = uvesafb_prep();
-	if (!task) {
-		kfree(state);
-		return NULL;
-	}
-
-	task->t.regs.eax = 0x4f04;
-	task->t.regs.ecx = 0x000f;
-	task->t.regs.edx = 0x0001;
-	task->t.flags = TF_BUF_RET | TF_BUF_ESBX;
-	task->t.buf_len = par->vbe_state_size;
-	task->buf = state;
-	err = uvesafb_exec(task);
-
-	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
-		printk(KERN_WARNING "uvesafb: VBE get state call "
-				"failed (eax=0x%x, err=%d)\n",
-				task->t.regs.eax, err);
-		kfree(state);
-		state = NULL;
-	}
-
-	uvesafb_free(task);
-	return state;
-}
-
-static void uvesafb_vbe_state_restore(struct uvesafb_par *par, u8 *state_buf)
-{
-	struct uvesafb_ktask *task;
-	int err;
-
-	if (!state_buf)
-		return;
-
-	task = uvesafb_prep();
-	if (!task)
-		return;
-
-	task->t.regs.eax = 0x4f04;
-	task->t.regs.ecx = 0x000f;
-	task->t.regs.edx = 0x0002;
-	task->t.buf_len = par->vbe_state_size;
-	task->t.flags = TF_BUF_ESBX;
-	task->buf = state_buf;
-
-	err = uvesafb_exec(task);
-	if (err || (task->t.regs.eax & 0xffff) != 0x004f)
-		printk(KERN_WARNING "uvesafb: VBE state restore call "
-				"failed (eax=0x%x, err=%d)\n",
-				task->t.regs.eax, err);
-
-	uvesafb_free(task);
-}
-
-static int uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
-			       struct uvesafb_par *par)
-{
-	int err;
-
-	task->t.regs.eax = 0x4f00;
-	task->t.flags = TF_VBEIB;
-	task->t.buf_len = sizeof(struct vbe_ib);
-	task->buf = &par->vbe_ib;
-	strncpy(par->vbe_ib.vbe_signature, "VBE2", 4);
-
-	err = uvesafb_exec(task);
-	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
-		printk(KERN_ERR "uvesafb: Getting VBE info block failed "
-				"(eax=0x%x, err=%d)\n", (u32)task->t.regs.eax,
-				err);
-		return -EINVAL;
-	}
-
-	if (par->vbe_ib.vbe_version < 0x0200) {
-		printk(KERN_ERR "uvesafb: Sorry, pre-VBE 2.0 cards are "
-				"not supported.\n");
-		return -EINVAL;
-	}
-
-	if (!par->vbe_ib.mode_list_ptr) {
-		printk(KERN_ERR "uvesafb: Missing mode list!\n");
-		return -EINVAL;
-	}
-
-	printk(KERN_INFO "uvesafb: ");
-
-	/*
-	 * Convert string pointers and the mode list pointer into
-	 * usable addresses. Print informational messages about the
-	 * video adapter and its vendor.
-	 */
-	if (par->vbe_ib.oem_vendor_name_ptr)
-		printk("%s, ",
-			((char *)task->buf) + par->vbe_ib.oem_vendor_name_ptr);
-
-	if (par->vbe_ib.oem_product_name_ptr)
-		printk("%s, ",
-			((char *)task->buf) + par->vbe_ib.oem_product_name_ptr);
-
-	if (par->vbe_ib.oem_product_rev_ptr)
-		printk("%s, ",
-			((char *)task->buf) + par->vbe_ib.oem_product_rev_ptr);
-
-	if (par->vbe_ib.oem_string_ptr)
-		printk("OEM: %s, ",
-			((char *)task->buf) + par->vbe_ib.oem_string_ptr);
-
-	printk("VBE v%d.%d\n", ((par->vbe_ib.vbe_version & 0xff00) >> 8),
-			par->vbe_ib.vbe_version & 0xff);
-
-	return 0;
-}
-
-static int uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
-				struct uvesafb_par *par)
-{
-	int off = 0, err;
-	u16 *mode;
-
-	par->vbe_modes_cnt = 0;
-
-	/* Count available modes. */
-	mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
-	while (*mode != 0xffff) {
-		par->vbe_modes_cnt++;
-		mode++;
-	}
-
-	par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) *
-				par->vbe_modes_cnt, GFP_KERNEL);
-	if (!par->vbe_modes)
-		return -ENOMEM;
-
-	/* Get info about all available modes. */
-	mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
-	while (*mode != 0xffff) {
-		struct vbe_mode_ib *mib;
-
-		uvesafb_reset(task);
-		task->t.regs.eax = 0x4f01;
-		task->t.regs.ecx = (u32) *mode;
-		task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
-		task->t.buf_len = sizeof(struct vbe_mode_ib);
-		task->buf = par->vbe_modes + off;
-
-		err = uvesafb_exec(task);
-		if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
-			printk(KERN_WARNING "uvesafb: Getting mode info block "
-				"for mode 0x%x failed (eax=0x%x, err=%d)\n",
-				*mode, (u32)task->t.regs.eax, err);
-			mode++;
-			par->vbe_modes_cnt--;
-			continue;
-		}
-
-		mib = task->buf;
-		mib->mode_id = *mode;
-
-		/*
-		 * We only want modes that are supported with the current
-		 * hardware configuration, color, graphics and that have
-		 * support for the LFB.
-		 */
-		if ((mib->mode_attr & VBE_MODE_MASK) == VBE_MODE_MASK &&
-				 mib->bits_per_pixel >= 8)
-			off++;
-		else
-			par->vbe_modes_cnt--;
-
-		mode++;
-		mib->depth = mib->red_len + mib->green_len + mib->blue_len;
-
-		/*
-		 * Handle 8bpp modes and modes with broken color component
-		 * lengths.
-		 */
-		if (mib->depth == 0 || (mib->depth == 24 &&
-					mib->bits_per_pixel == 32))
-			mib->depth = mib->bits_per_pixel;
-	}
-
-	if (par->vbe_modes_cnt > 0)
-		return 0;
-	else
-		return -EINVAL;
-}
-
-/*
- * The Protected Mode Interface is 32-bit x86 code, so we only run it on
- * x86 and not x86_64.
- */
-#ifdef CONFIG_X86_32
-static int uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
-			      struct uvesafb_par *par)
-{
-	int i, err;
-
-	uvesafb_reset(task);
-	task->t.regs.eax = 0x4f0a;
-	task->t.regs.ebx = 0x0;
-	err = uvesafb_exec(task);
-
-	if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) {
-		par->pmi_setpal = par->ypan = 0;
-	} else {
-		par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4)
-						+ task->t.regs.edi);
-		par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1];
-		par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2];
-		printk(KERN_INFO "uvesafb: protected mode interface info at "
-				 "%04x:%04x\n",
-				 (u16)task->t.regs.es, (u16)task->t.regs.edi);
-		printk(KERN_INFO "uvesafb: pmi: set display start = %p, "
-				 "set palette = %p\n", par->pmi_start,
-				 par->pmi_pal);
-
-		if (par->pmi_base[3]) {
-			printk(KERN_INFO "uvesafb: pmi: ports = ");
-			for (i = par->pmi_base[3]/2;
-					par->pmi_base[i] != 0xffff; i++)
-				printk("%x ", par->pmi_base[i]);
-			printk("\n");
-
-			if (par->pmi_base[i] != 0xffff) {
-				printk(KERN_INFO "uvesafb: can't handle memory"
-						 " requests, pmi disabled\n");
-				par->ypan = par->pmi_setpal = 0;
-			}
-		}
-	}
-	return 0;
-}
-#endif /* CONFIG_X86_32 */
-
-/*
- * Check whether a video mode is supported by the Video BIOS and is
- * compatible with the monitor limits.
- */
-static int uvesafb_is_valid_mode(struct fb_videomode *mode,
-				 struct fb_info *info)
-{
-	if (info->monspecs.gtf) {
-		fb_videomode_to_var(&info->var, mode);
-		if (fb_validate_mode(&info->var, info))
-			return 0;
-	}
-
-	if (uvesafb_vbe_find_mode(info->par, mode->xres, mode->yres, 8,
-				UVESAFB_EXACT_RES) == -1)
-		return 0;
-
-	return 1;
-}
-
-static int uvesafb_vbe_getedid(struct uvesafb_ktask *task, struct fb_info *info)
-{
-	struct uvesafb_par *par = info->par;
-	int err = 0;
-
-	if (noedid || par->vbe_ib.vbe_version < 0x0300)
-		return -EINVAL;
-
-	task->t.regs.eax = 0x4f15;
-	task->t.regs.ebx = 0;
-	task->t.regs.ecx = 0;
-	task->t.buf_len = 0;
-	task->t.flags = 0;
-
-	err = uvesafb_exec(task);
-
-	if ((task->t.regs.eax & 0xffff) != 0x004f || err)
-		return -EINVAL;
-
-	if ((task->t.regs.ebx & 0x3) == 3) {
-		printk(KERN_INFO "uvesafb: VBIOS/hardware supports both "
-				 "DDC1 and DDC2 transfers\n");
-	} else if ((task->t.regs.ebx & 0x3) == 2) {
-		printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC2 "
-				 "transfers\n");
-	} else if ((task->t.regs.ebx & 0x3) == 1) {
-		printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC1 "
-				 "transfers\n");
-	} else {
-		printk(KERN_INFO "uvesafb: VBIOS/hardware doesn't support "
-				 "DDC transfers\n");
-		return -EINVAL;
-	}
-
-	task->t.regs.eax = 0x4f15;
-	task->t.regs.ebx = 1;
-	task->t.regs.ecx = task->t.regs.edx = 0;
-	task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
-	task->t.buf_len = EDID_LENGTH;
-	task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
-	if (!task->buf)
-		return -ENOMEM;
-
-	err = uvesafb_exec(task);
-
-	if ((task->t.regs.eax & 0xffff) == 0x004f && !err) {
-		fb_edid_to_monspecs(task->buf, &info->monspecs);
-
-		if (info->monspecs.vfmax && info->monspecs.hfmax) {
-			/*
-			 * If the maximum pixel clock wasn't specified in
-			 * the EDID block, set it to 300 MHz.
-			 */
-			if (info->monspecs.dclkmax == 0)
-				info->monspecs.dclkmax = 300 * 1000000;
-			info->monspecs.gtf = 1;
-		}
-	} else {
-		err = -EINVAL;
-	}
-
-	kfree(task->buf);
-	return err;
-}
-
-static void uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
-				    struct fb_info *info)
-{
-	struct uvesafb_par *par = info->par;
-	int i;
-
-	memset(&info->monspecs, 0, sizeof(info->monspecs));
-
-	/*
-	 * If we don't get all necessary data from the EDID block,
-	 * mark it as incompatible with the GTF and set nocrtc so
-	 * that we always use the default BIOS refresh rate.
-	 */
-	if (uvesafb_vbe_getedid(task, info)) {
-		info->monspecs.gtf = 0;
-		par->nocrtc = 1;
-	}
-
-	/* Kernel command line overrides. */
-	if (maxclk)
-		info->monspecs.dclkmax = maxclk * 1000000;
-	if (maxvf)
-		info->monspecs.vfmax = maxvf;
-	if (maxhf)
-		info->monspecs.hfmax = maxhf * 1000;
-
-	/*
-	 * In case DDC transfers are not supported, the user can provide
-	 * monitor limits manually. Lower limits are set to "safe" values.
-	 */
-	if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) {
-		info->monspecs.dclkmin = 0;
-		info->monspecs.vfmin = 60;
-		info->monspecs.hfmin = 29000;
-		info->monspecs.gtf = 1;
-		par->nocrtc = 0;
-	}
-
-	if (info->monspecs.gtf)
-		printk(KERN_INFO
-			"uvesafb: monitor limits: vf = %d Hz, hf = %d kHz, "
-			"clk = %d MHz\n", info->monspecs.vfmax,
-			(int)(info->monspecs.hfmax / 1000),
-			(int)(info->monspecs.dclkmax / 1000000));
-	else
-		printk(KERN_INFO "uvesafb: no monitor limits have been set, "
-				 "default refresh rate will be used\n");
-
-	/* Add VBE modes to the modelist. */
-	for (i = 0; i < par->vbe_modes_cnt; i++) {
-		struct fb_var_screeninfo var;
-		struct vbe_mode_ib *mode;
-		struct fb_videomode vmode;
-
-		mode = &par->vbe_modes[i];
-		memset(&var, 0, sizeof(var));
-
-		var.xres = mode->x_res;
-		var.yres = mode->y_res;
-
-		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &var, info);
-		fb_var_to_videomode(&vmode, &var);
-		fb_add_videomode(&vmode, &info->modelist);
-	}
-
-	/* Add valid VESA modes to our modelist. */
-	for (i = 0; i < VESA_MODEDB_SIZE; i++) {
-		if (uvesafb_is_valid_mode((struct fb_videomode *)
-						&vesa_modes[i], info))
-			fb_add_videomode(&vesa_modes[i], &info->modelist);
-	}
-
-	for (i = 0; i < info->monspecs.modedb_len; i++) {
-		if (uvesafb_is_valid_mode(&info->monspecs.modedb[i], info))
-			fb_add_videomode(&info->monspecs.modedb[i],
-					&info->modelist);
-	}
-
-	return;
-}
-
-static void uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
-				     struct uvesafb_par *par)
-{
-	int err;
-
-	uvesafb_reset(task);
-
-	/*
-	 * Get the VBE state buffer size. We want all available
-	 * hardware state data (CL = 0x0f).
-	 */
-	task->t.regs.eax = 0x4f04;
-	task->t.regs.ecx = 0x000f;
-	task->t.regs.edx = 0x0000;
-	task->t.flags = 0;
-
-	err = uvesafb_exec(task);
-
-	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
-		printk(KERN_WARNING "uvesafb: VBE state buffer size "
-			"cannot be determined (eax=0x%x, err=%d)\n",
-			task->t.regs.eax, err);
-		par->vbe_state_size = 0;
-		return;
-	}
-
-	par->vbe_state_size = 64 * (task->t.regs.ebx & 0xffff);
-}
-
-static int uvesafb_vbe_init(struct fb_info *info)
-{
-	struct uvesafb_ktask *task = NULL;
-	struct uvesafb_par *par = info->par;
-	int err;
-
-	task = uvesafb_prep();
-	if (!task)
-		return -ENOMEM;
-
-	err = uvesafb_vbe_getinfo(task, par);
-	if (err)
-		goto out;
-
-	err = uvesafb_vbe_getmodes(task, par);
-	if (err)
-		goto out;
-
-	par->nocrtc = nocrtc;
-#ifdef CONFIG_X86_32
-	par->pmi_setpal = pmi_setpal;
-	par->ypan = ypan;
-
-	if (par->pmi_setpal || par->ypan) {
-		if (__supported_pte_mask & _PAGE_NX) {
-			par->pmi_setpal = par->ypan = 0;
-			printk(KERN_WARNING "uvesafb: NX protection is active, "
-					    "better not use the PMI.\n");
-		} else {
-			uvesafb_vbe_getpmi(task, par);
-		}
-	}
-#else
-	/* The protected mode interface is not available on non-x86. */
-	par->pmi_setpal = par->ypan = 0;
-#endif
-
-	INIT_LIST_HEAD(&info->modelist);
-	uvesafb_vbe_getmonspecs(task, info);
-	uvesafb_vbe_getstatesize(task, par);
-
-out:	uvesafb_free(task);
-	return err;
-}
-
-static int uvesafb_vbe_init_mode(struct fb_info *info)
-{
-	struct list_head *pos;
-	struct fb_modelist *modelist;
-	struct fb_videomode *mode;
-	struct uvesafb_par *par = info->par;
-	int i, modeid;
-
-	/* Has the user requested a specific VESA mode? */
-	if (vbemode) {
-		for (i = 0; i < par->vbe_modes_cnt; i++) {
-			if (par->vbe_modes[i].mode_id == vbemode) {
-				modeid = i;
-				uvesafb_setup_var(&info->var, info,
-						&par->vbe_modes[modeid]);
-				fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
-						&info->var, info);
-				/*
-				 * With pixclock set to 0, the default BIOS
-				 * timings will be used in set_par().
-				 */
-				info->var.pixclock = 0;
-				goto gotmode;
-			}
-		}
-		printk(KERN_INFO "uvesafb: requested VBE mode 0x%x is "
-				 "unavailable\n", vbemode);
-		vbemode = 0;
-	}
-
-	/* Count the modes in the modelist */
-	i = 0;
-	list_for_each(pos, &info->modelist)
-		i++;
-
-	/*
-	 * Convert the modelist into a modedb so that we can use it with
-	 * fb_find_mode().
-	 */
-	mode = kzalloc(i * sizeof(*mode), GFP_KERNEL);
-	if (mode) {
-		i = 0;
-		list_for_each(pos, &info->modelist) {
-			modelist = list_entry(pos, struct fb_modelist, list);
-			mode[i] = modelist->mode;
-			i++;
-		}
-
-		if (!mode_option)
-			mode_option = UVESAFB_DEFAULT_MODE;
-
-		i = fb_find_mode(&info->var, info, mode_option, mode, i,
-			NULL, 8);
-
-		kfree(mode);
-	}
-
-	/* fb_find_mode() failed */
-	if (i == 0) {
-		info->var.xres = 640;
-		info->var.yres = 480;
-		mode = (struct fb_videomode *)
-				fb_find_best_mode(&info->var, &info->modelist);
-
-		if (mode) {
-			fb_videomode_to_var(&info->var, mode);
-		} else {
-			modeid = par->vbe_modes[0].mode_id;
-			uvesafb_setup_var(&info->var, info,
-					&par->vbe_modes[modeid]);
-			fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
-					&info->var, info);
-
-			goto gotmode;
-		}
-	}
-
-	/* Look for a matching VBE mode. */
-	modeid = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres,
-			info->var.bits_per_pixel, UVESAFB_EXACT_RES);
-
-	if (modeid == -1)
-		return -EINVAL;
-
-	uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]);
-
-gotmode:
-	/*
-	 * If we are not VBE3.0+ compliant, we're done -- the BIOS will
-	 * ignore our timings anyway.
-	 */
-	if (par->vbe_ib.vbe_version < 0x0300 || par->nocrtc)
-		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
-					&info->var, info);
-
-	return modeid;
-}
-
-static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count,
-		int start, struct fb_info *info)
-{
-	struct uvesafb_ktask *task;
-#ifdef CONFIG_X86
-	struct uvesafb_par *par = info->par;
-	int i = par->mode_idx;
-#endif
-	int err = 0;
-
-	/*
-	 * We support palette modifications for 8 bpp modes only, so
-	 * there can never be more than 256 entries.
-	 */
-	if (start + count > 256)
-		return -EINVAL;
-
-#ifdef CONFIG_X86
-	/* Use VGA registers if mode is VGA-compatible. */
-	if (i >= 0 && i < par->vbe_modes_cnt &&
-	    par->vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) {
-		for (i = 0; i < count; i++) {
-			outb_p(start + i,        dac_reg);
-			outb_p(entries[i].red,   dac_val);
-			outb_p(entries[i].green, dac_val);
-			outb_p(entries[i].blue,  dac_val);
-		}
-	}
-#ifdef CONFIG_X86_32
-	else if (par->pmi_setpal) {
-		__asm__ __volatile__(
-		"call *(%%esi)"
-		: /* no return value */
-		: "a" (0x4f09),         /* EAX */
-		  "b" (0),              /* EBX */
-		  "c" (count),          /* ECX */
-		  "d" (start),          /* EDX */
-		  "D" (entries),        /* EDI */
-		  "S" (&par->pmi_pal)); /* ESI */
-	}
-#endif /* CONFIG_X86_32 */
-	else
-#endif /* CONFIG_X86 */
-	{
-		task = uvesafb_prep();
-		if (!task)
-			return -ENOMEM;
-
-		task->t.regs.eax = 0x4f09;
-		task->t.regs.ebx = 0x0;
-		task->t.regs.ecx = count;
-		task->t.regs.edx = start;
-		task->t.flags = TF_BUF_ESDI;
-		task->t.buf_len = sizeof(struct uvesafb_pal_entry) * count;
-		task->buf = entries;
-
-		err = uvesafb_exec(task);
-		if ((task->t.regs.eax & 0xffff) != 0x004f)
-			err = 1;
-
-		uvesafb_free(task);
-	}
-	return err;
-}
-
-static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
-		unsigned blue, unsigned transp,
-		struct fb_info *info)
-{
-	struct uvesafb_pal_entry entry;
-	int shift = 16 - dac_width;
-	int err = 0;
-
-	if (regno >= info->cmap.len)
-		return -EINVAL;
-
-	if (info->var.bits_per_pixel == 8) {
-		entry.red   = red   >> shift;
-		entry.green = green >> shift;
-		entry.blue  = blue  >> shift;
-		entry.pad   = 0;
-
-		err = uvesafb_setpalette(&entry, 1, regno, info);
-	} else if (regno < 16) {
-		switch (info->var.bits_per_pixel) {
-		case 16:
-			if (info->var.red.offset == 10) {
-				/* 1:5:5:5 */
-				((u32 *) (info->pseudo_palette))[regno] =
-						((red   & 0xf800) >>  1) |
-						((green & 0xf800) >>  6) |
-						((blue  & 0xf800) >> 11);
-			} else {
-				/* 0:5:6:5 */
-				((u32 *) (info->pseudo_palette))[regno] =
-						((red   & 0xf800)      ) |
-						((green & 0xfc00) >>  5) |
-						((blue  & 0xf800) >> 11);
-			}
-			break;
-
-		case 24:
-		case 32:
-			red   >>= 8;
-			green >>= 8;
-			blue  >>= 8;
-			((u32 *)(info->pseudo_palette))[regno] =
-				(red   << info->var.red.offset)   |
-				(green << info->var.green.offset) |
-				(blue  << info->var.blue.offset);
-			break;
-		}
-	}
-	return err;
-}
-
-static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
-	struct uvesafb_pal_entry *entries;
-	int shift = 16 - dac_width;
-	int i, err = 0;
-
-	if (info->var.bits_per_pixel == 8) {
-		if (cmap->start + cmap->len > info->cmap.start +
-		    info->cmap.len || cmap->start < info->cmap.start)
-			return -EINVAL;
-
-		entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL);
-		if (!entries)
-			return -ENOMEM;
-
-		for (i = 0; i < cmap->len; i++) {
-			entries[i].red   = cmap->red[i]   >> shift;
-			entries[i].green = cmap->green[i] >> shift;
-			entries[i].blue  = cmap->blue[i]  >> shift;
-			entries[i].pad   = 0;
-		}
-		err = uvesafb_setpalette(entries, cmap->len, cmap->start, info);
-		kfree(entries);
-	} else {
-		/*
-		 * For modes with bpp > 8, we only set the pseudo palette in
-		 * the fb_info struct. We rely on uvesafb_setcolreg to do all
-		 * sanity checking.
-		 */
-		for (i = 0; i < cmap->len; i++) {
-			err |= uvesafb_setcolreg(cmap->start + i, cmap->red[i],
-						cmap->green[i], cmap->blue[i],
-						0, info);
-		}
-	}
-	return err;
-}
-
-static int uvesafb_pan_display(struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-#ifdef CONFIG_X86_32
-	int offset;
-	struct uvesafb_par *par = info->par;
-
-	offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
-
-	/*
-	 * It turns out it's not the best idea to do panning via vm86,
-	 * so we only allow it if we have a PMI.
-	 */
-	if (par->pmi_start) {
-		__asm__ __volatile__(
-			"call *(%%edi)"
-			: /* no return value */
-			: "a" (0x4f07),         /* EAX */
-			  "b" (0),              /* EBX */
-			  "c" (offset),         /* ECX */
-			  "d" (offset >> 16),   /* EDX */
-			  "D" (&par->pmi_start));    /* EDI */
-	}
-#endif
-	return 0;
-}
-
-static int uvesafb_blank(int blank, struct fb_info *info)
-{
-	struct uvesafb_ktask *task;
-	int err = 1;
-#ifdef CONFIG_X86
-	struct uvesafb_par *par = info->par;
-
-	if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
-		int loop = 10000;
-		u8 seq = 0, crtc17 = 0;
-
-		if (blank == FB_BLANK_POWERDOWN) {
-			seq = 0x20;
-			crtc17 = 0x00;
-			err = 0;
-		} else {
-			seq = 0x00;
-			crtc17 = 0x80;
-			err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
-		}
-
-		vga_wseq(NULL, 0x00, 0x01);
-		seq |= vga_rseq(NULL, 0x01) & ~0x20;
-		vga_wseq(NULL, 0x00, seq);
-
-		crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
-		while (loop--);
-		vga_wcrt(NULL, 0x17, crtc17);
-		vga_wseq(NULL, 0x00, 0x03);
-	} else
-#endif /* CONFIG_X86 */
-	{
-		task = uvesafb_prep();
-		if (!task)
-			return -ENOMEM;
-
-		task->t.regs.eax = 0x4f10;
-		switch (blank) {
-		case FB_BLANK_UNBLANK:
-			task->t.regs.ebx = 0x0001;
-			break;
-		case FB_BLANK_NORMAL:
-			task->t.regs.ebx = 0x0101;	/* standby */
-			break;
-		case FB_BLANK_POWERDOWN:
-			task->t.regs.ebx = 0x0401;	/* powerdown */
-			break;
-		default:
-			goto out;
-		}
-
-		err = uvesafb_exec(task);
-		if (err || (task->t.regs.eax & 0xffff) != 0x004f)
-			err = 1;
-out:		uvesafb_free(task);
-	}
-	return err;
-}
-
-static int uvesafb_open(struct fb_info *info, int user)
-{
-	struct uvesafb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
-	u8 *buf = NULL;
-
-	if (!cnt && par->vbe_state_size) {
-		buf =  uvesafb_vbe_state_save(par);
-		if (IS_ERR(buf)) {
-			printk(KERN_WARNING "uvesafb: save hardware state"
-				"failed, error code is %ld!\n", PTR_ERR(buf));
-		} else {
-			par->vbe_state_orig = buf;
-		}
-	}
-
-	atomic_inc(&par->ref_count);
-	return 0;
-}
-
-static int uvesafb_release(struct fb_info *info, int user)
-{
-	struct uvesafb_ktask *task = NULL;
-	struct uvesafb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
-
-	if (!cnt)
-		return -EINVAL;
-
-	if (cnt != 1)
-		goto out;
-
-	task = uvesafb_prep();
-	if (!task)
-		goto out;
-
-	/* First, try to set the standard 80x25 text mode. */
-	task->t.regs.eax = 0x0003;
-	uvesafb_exec(task);
-
-	/*
-	 * Now try to restore whatever hardware state we might have
-	 * saved when the fb device was first opened.
-	 */
-	uvesafb_vbe_state_restore(par, par->vbe_state_orig);
-out:
-	atomic_dec(&par->ref_count);
-	if (task)
-		uvesafb_free(task);
-	return 0;
-}
-
-static int uvesafb_set_par(struct fb_info *info)
-{
-	struct uvesafb_par *par = info->par;
-	struct uvesafb_ktask *task = NULL;
-	struct vbe_crtc_ib *crtc = NULL;
-	struct vbe_mode_ib *mode = NULL;
-	int i, err = 0, depth = info->var.bits_per_pixel;
-
-	if (depth > 8 && depth != 32)
-		depth = info->var.red.length + info->var.green.length +
-			info->var.blue.length;
-
-	i = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres, depth,
-				 UVESAFB_EXACT_RES | UVESAFB_EXACT_DEPTH);
-	if (i >= 0)
-		mode = &par->vbe_modes[i];
-	else
-		return -EINVAL;
-
-	task = uvesafb_prep();
-	if (!task)
-		return -ENOMEM;
-setmode:
-	task->t.regs.eax = 0x4f02;
-	task->t.regs.ebx = mode->mode_id | 0x4000;	/* use LFB */
-
-	if (par->vbe_ib.vbe_version >= 0x0300 && !par->nocrtc &&
-	    info->var.pixclock != 0) {
-		task->t.regs.ebx |= 0x0800;		/* use CRTC data */
-		task->t.flags = TF_BUF_ESDI;
-		crtc = kzalloc(sizeof(struct vbe_crtc_ib), GFP_KERNEL);
-		if (!crtc) {
-			err = -ENOMEM;
-			goto out;
-		}
-		crtc->horiz_start = info->var.xres + info->var.right_margin;
-		crtc->horiz_end	  = crtc->horiz_start + info->var.hsync_len;
-		crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
-
-		crtc->vert_start  = info->var.yres + info->var.lower_margin;
-		crtc->vert_end    = crtc->vert_start + info->var.vsync_len;
-		crtc->vert_total  = crtc->vert_end + info->var.upper_margin;
-
-		crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
-		crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock /
-				(crtc->vert_total * crtc->horiz_total)));
-
-		if (info->var.vmode & FB_VMODE_DOUBLE)
-			crtc->flags |= 0x1;
-		if (info->var.vmode & FB_VMODE_INTERLACED)
-			crtc->flags |= 0x2;
-		if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
-			crtc->flags |= 0x4;
-		if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
-			crtc->flags |= 0x8;
-		memcpy(&par->crtc, crtc, sizeof(*crtc));
-	} else {
-		memset(&par->crtc, 0, sizeof(*crtc));
-	}
-
-	task->t.buf_len = sizeof(struct vbe_crtc_ib);
-	task->buf = &par->crtc;
-
-	err = uvesafb_exec(task);
-	if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
-		/*
-		 * The mode switch might have failed because we tried to
-		 * use our own timings.  Try again with the default timings.
-		 */
-		if (crtc != NULL) {
-			printk(KERN_WARNING "uvesafb: mode switch failed "
-				"(eax=0x%x, err=%d). Trying again with "
-				"default timings.\n", task->t.regs.eax, err);
-			uvesafb_reset(task);
-			kfree(crtc);
-			crtc = NULL;
-			info->var.pixclock = 0;
-			goto setmode;
-		} else {
-			printk(KERN_ERR "uvesafb: mode switch failed (eax="
-				"0x%x, err=%d)\n", task->t.regs.eax, err);
-			err = -EINVAL;
-			goto out;
-		}
-	}
-	par->mode_idx = i;
-
-	/* For 8bpp modes, always try to set the DAC to 8 bits. */
-	if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC &&
-	    mode->bits_per_pixel <= 8) {
-		uvesafb_reset(task);
-		task->t.regs.eax = 0x4f08;
-		task->t.regs.ebx = 0x0800;
-
-		err = uvesafb_exec(task);
-		if (err || (task->t.regs.eax & 0xffff) != 0x004f ||
-		    ((task->t.regs.ebx & 0xff00) >> 8) != 8) {
-			dac_width = 6;
-		} else {
-			dac_width = 8;
-		}
-	}
-
-	info->fix.visual = (info->var.bits_per_pixel == 8) ?
-				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = mode->bytes_per_scan_line;
-
-out:
-	kfree(crtc);
-	uvesafb_free(task);
-
-	return err;
-}
-
-static void uvesafb_check_limits(struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-	const struct fb_videomode *mode;
-	struct uvesafb_par *par = info->par;
-
-	/*
-	 * If pixclock is set to 0, then we're using default BIOS timings
-	 * and thus don't have to perform any checks here.
-	 */
-	if (!var->pixclock)
-		return;
-
-	if (par->vbe_ib.vbe_version < 0x0300) {
-		fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info);
-		return;
-	}
-
-	if (!fb_validate_mode(var, info))
-		return;
-
-	mode = fb_find_best_mode(var, &info->modelist);
-	if (mode) {
-		if (mode->xres == var->xres && mode->yres == var->yres &&
-		    !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) {
-			fb_videomode_to_var(var, mode);
-			return;
-		}
-	}
-
-	if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
-		return;
-	/* Use default refresh rate */
-	var->pixclock = 0;
-}
-
-static int uvesafb_check_var(struct fb_var_screeninfo *var,
-		struct fb_info *info)
-{
-	struct uvesafb_par *par = info->par;
-	struct vbe_mode_ib *mode = NULL;
-	int match = -1;
-	int depth = var->red.length + var->green.length + var->blue.length;
-
-	/*
-	 * Various apps will use bits_per_pixel to set the color depth,
-	 * which is theoretically incorrect, but which we'll try to handle
-	 * here.
-	 */
-	if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8)
-		depth = var->bits_per_pixel;
-
-	match = uvesafb_vbe_find_mode(par, var->xres, var->yres, depth,
-						UVESAFB_EXACT_RES);
-	if (match == -1)
-		return -EINVAL;
-
-	mode = &par->vbe_modes[match];
-	uvesafb_setup_var(var, info, mode);
-
-	/*
-	 * Check whether we have remapped enough memory for this mode.
-	 * We might be called at an early stage, when we haven't remapped
-	 * any memory yet, in which case we simply skip the check.
-	 */
-	if (var->yres * mode->bytes_per_scan_line > info->fix.smem_len
-						&& info->fix.smem_len)
-		return -EINVAL;
-
-	if ((var->vmode & FB_VMODE_DOUBLE) &&
-				!(par->vbe_modes[match].mode_attr & 0x100))
-		var->vmode &= ~FB_VMODE_DOUBLE;
-
-	if ((var->vmode & FB_VMODE_INTERLACED) &&
-				!(par->vbe_modes[match].mode_attr & 0x200))
-		var->vmode &= ~FB_VMODE_INTERLACED;
-
-	uvesafb_check_limits(var, info);
-
-	var->xres_virtual = var->xres;
-	var->yres_virtual = (par->ypan) ?
-				info->fix.smem_len / mode->bytes_per_scan_line :
-				var->yres;
-	return 0;
-}
-
-static struct fb_ops uvesafb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= uvesafb_open,
-	.fb_release	= uvesafb_release,
-	.fb_setcolreg	= uvesafb_setcolreg,
-	.fb_setcmap	= uvesafb_setcmap,
-	.fb_pan_display	= uvesafb_pan_display,
-	.fb_blank	= uvesafb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-	.fb_check_var	= uvesafb_check_var,
-	.fb_set_par	= uvesafb_set_par,
-};
-
-static void uvesafb_init_info(struct fb_info *info, struct vbe_mode_ib *mode)
-{
-	unsigned int size_vmode;
-	unsigned int size_remap;
-	unsigned int size_total;
-	struct uvesafb_par *par = info->par;
-	int i, h;
-
-	info->pseudo_palette = ((u8 *)info->par + sizeof(struct uvesafb_par));
-	info->fix = uvesafb_fix;
-	info->fix.ypanstep = par->ypan ? 1 : 0;
-	info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0;
-
-	/* Disable blanking if the user requested so. */
-	if (!blank)
-		info->fbops->fb_blank = NULL;
-
-	/*
-	 * Find out how much IO memory is required for the mode with
-	 * the highest resolution.
-	 */
-	size_remap = 0;
-	for (i = 0; i < par->vbe_modes_cnt; i++) {
-		h = par->vbe_modes[i].bytes_per_scan_line *
-					par->vbe_modes[i].y_res;
-		if (h > size_remap)
-			size_remap = h;
-	}
-	size_remap *= 2;
-
-	/*
-	 *   size_vmode -- that is the amount of memory needed for the
-	 *                 used video mode, i.e. the minimum amount of
-	 *                 memory we need.
-	 */
-	size_vmode = info->var.yres * mode->bytes_per_scan_line;
-
-	/*
-	 *   size_total -- all video memory we have. Used for mtrr
-	 *                 entries, resource allocation and bounds
-	 *                 checking.
-	 */
-	size_total = par->vbe_ib.total_memory * 65536;
-	if (vram_total)
-		size_total = vram_total * 1024 * 1024;
-	if (size_total < size_vmode)
-		size_total = size_vmode;
-
-	/*
-	 *   size_remap -- the amount of video memory we are going to
-	 *                 use for vesafb.  With modern cards it is no
-	 *                 option to simply use size_total as th
-	 *                 wastes plenty of kernel address space.
-	 */
-	if (vram_remap)
-		size_remap = vram_remap * 1024 * 1024;
-	if (size_remap < size_vmode)
-		size_remap = size_vmode;
-	if (size_remap > size_total)
-		size_remap = size_total;
-
-	info->fix.smem_len = size_remap;
-	info->fix.smem_start = mode->phys_base_ptr;
-
-	/*
-	 * We have to set yres_virtual here because when setup_var() was
-	 * called, smem_len wasn't defined yet.
-	 */
-	info->var.yres_virtual = info->fix.smem_len /
-				 mode->bytes_per_scan_line;
-
-	if (par->ypan && info->var.yres_virtual > info->var.yres) {
-		printk(KERN_INFO "uvesafb: scrolling: %s "
-			"using protected mode interface, "
-			"yres_virtual=%d\n",
-			(par->ypan > 1) ? "ywrap" : "ypan",
-			info->var.yres_virtual);
-	} else {
-		printk(KERN_INFO "uvesafb: scrolling: redraw\n");
-		info->var.yres_virtual = info->var.yres;
-		par->ypan = 0;
-	}
-
-	info->flags = FBINFO_FLAG_DEFAULT |
-			(par->ypan ? FBINFO_HWACCEL_YPAN : 0);
-
-	if (!par->ypan)
-		info->fbops->fb_pan_display = NULL;
-}
-
-static void uvesafb_init_mtrr(struct fb_info *info)
-{
-	struct uvesafb_par *par = info->par;
-
-	if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
-		int temp_size = info->fix.smem_len;
-
-		int rc;
-
-		/* Find the largest power-of-two */
-		temp_size = roundup_pow_of_two(temp_size);
-
-		/* Try and find a power of two to add */
-		do {
-			rc = arch_phys_wc_add(info->fix.smem_start, temp_size);
-			temp_size >>= 1;
-		} while (temp_size >= PAGE_SIZE && rc == -EINVAL);
-
-		if (rc >= 0)
-			par->mtrr_handle = rc;
-	}
-}
-
-static void uvesafb_ioremap(struct fb_info *info)
-{
-	info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len);
-}
-
-static ssize_t uvesafb_show_vbe_ver(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-
-	return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version);
-}
-
-static DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL);
-
-static ssize_t uvesafb_show_vbe_modes(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-	int ret = 0, i;
-
-	for (i = 0; i < par->vbe_modes_cnt && ret < PAGE_SIZE; i++) {
-		ret += snprintf(buf + ret, PAGE_SIZE - ret,
-			"%dx%d-%d, 0x%.4x\n",
-			par->vbe_modes[i].x_res, par->vbe_modes[i].y_res,
-			par->vbe_modes[i].depth, par->vbe_modes[i].mode_id);
-	}
-
-	return ret;
-}
-
-static DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL);
-
-static ssize_t uvesafb_show_vendor(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-
-	if (par->vbe_ib.oem_vendor_name_ptr)
-		return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
-			(&par->vbe_ib) + par->vbe_ib.oem_vendor_name_ptr);
-	else
-		return 0;
-}
-
-static DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL);
-
-static ssize_t uvesafb_show_product_name(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-
-	if (par->vbe_ib.oem_product_name_ptr)
-		return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
-			(&par->vbe_ib) + par->vbe_ib.oem_product_name_ptr);
-	else
-		return 0;
-}
-
-static DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL);
-
-static ssize_t uvesafb_show_product_rev(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-
-	if (par->vbe_ib.oem_product_rev_ptr)
-		return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
-			(&par->vbe_ib) + par->vbe_ib.oem_product_rev_ptr);
-	else
-		return 0;
-}
-
-static DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL);
-
-static ssize_t uvesafb_show_oem_string(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-
-	if (par->vbe_ib.oem_string_ptr)
-		return snprintf(buf, PAGE_SIZE, "%s\n",
-			(char *)(&par->vbe_ib) + par->vbe_ib.oem_string_ptr);
-	else
-		return 0;
-}
-
-static DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL);
-
-static ssize_t uvesafb_show_nocrtc(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc);
-}
-
-static ssize_t uvesafb_store_nocrtc(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
-	struct uvesafb_par *par = info->par;
-
-	if (count > 0) {
-		if (buf[0] == '0')
-			par->nocrtc = 0;
-		else
-			par->nocrtc = 1;
-	}
-	return count;
-}
-
-static DEVICE_ATTR(nocrtc, S_IRUGO | S_IWUSR, uvesafb_show_nocrtc,
-			uvesafb_store_nocrtc);
-
-static struct attribute *uvesafb_dev_attrs[] = {
-	&dev_attr_vbe_version.attr,
-	&dev_attr_vbe_modes.attr,
-	&dev_attr_oem_vendor.attr,
-	&dev_attr_oem_product_name.attr,
-	&dev_attr_oem_product_rev.attr,
-	&dev_attr_oem_string.attr,
-	&dev_attr_nocrtc.attr,
-	NULL,
-};
-
-static struct attribute_group uvesafb_dev_attgrp = {
-	.name = NULL,
-	.attrs = uvesafb_dev_attrs,
-};
-
-static int uvesafb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	struct vbe_mode_ib *mode = NULL;
-	struct uvesafb_par *par;
-	int err = 0, i;
-
-	info = framebuffer_alloc(sizeof(*par) +	sizeof(u32) * 256, &dev->dev);
-	if (!info)
-		return -ENOMEM;
-
-	par = info->par;
-
-	err = uvesafb_vbe_init(info);
-	if (err) {
-		printk(KERN_ERR "uvesafb: vbe_init() failed with %d\n", err);
-		goto out;
-	}
-
-	info->fbops = &uvesafb_ops;
-
-	i = uvesafb_vbe_init_mode(info);
-	if (i < 0) {
-		err = -EINVAL;
-		goto out;
-	} else {
-		mode = &par->vbe_modes[i];
-	}
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		err = -ENXIO;
-		goto out;
-	}
-
-	uvesafb_init_info(info, mode);
-
-	if (!request_region(0x3c0, 32, "uvesafb")) {
-		printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n");
-		err = -EIO;
-		goto out_mode;
-	}
-
-	if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
-				"uvesafb")) {
-		printk(KERN_ERR "uvesafb: cannot reserve video memory at "
-				"0x%lx\n", info->fix.smem_start);
-		err = -EIO;
-		goto out_reg;
-	}
-
-	uvesafb_init_mtrr(info);
-	uvesafb_ioremap(info);
-
-	if (!info->screen_base) {
-		printk(KERN_ERR
-			"uvesafb: abort, cannot ioremap 0x%x bytes of video "
-			"memory at 0x%lx\n",
-			info->fix.smem_len, info->fix.smem_start);
-		err = -EIO;
-		goto out_mem;
-	}
-
-	platform_set_drvdata(dev, info);
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR
-			"uvesafb: failed to register framebuffer device\n");
-		err = -EINVAL;
-		goto out_unmap;
-	}
-
-	printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, "
-			"using %dk, total %dk\n", info->fix.smem_start,
-			info->screen_base, info->fix.smem_len/1024,
-			par->vbe_ib.total_memory * 64);
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-
-	err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
-	if (err != 0)
-		fb_warn(info, "failed to register attributes\n");
-
-	return 0;
-
-out_unmap:
-	iounmap(info->screen_base);
-out_mem:
-	release_mem_region(info->fix.smem_start, info->fix.smem_len);
-out_reg:
-	release_region(0x3c0, 32);
-out_mode:
-	if (!list_empty(&info->modelist))
-		fb_destroy_modelist(&info->modelist);
-	fb_destroy_modedb(info->monspecs.modedb);
-	fb_dealloc_cmap(&info->cmap);
-out:
-	kfree(par->vbe_modes);
-
-	framebuffer_release(info);
-	return err;
-}
-
-static int uvesafb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		struct uvesafb_par *par = info->par;
-
-		sysfs_remove_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
-		unregister_framebuffer(info);
-		release_region(0x3c0, 32);
-		iounmap(info->screen_base);
-		arch_phys_wc_del(par->mtrr_handle);
-		release_mem_region(info->fix.smem_start, info->fix.smem_len);
-		fb_destroy_modedb(info->monspecs.modedb);
-		fb_dealloc_cmap(&info->cmap);
-
-		kfree(par->vbe_modes);
-		kfree(par->vbe_state_orig);
-		kfree(par->vbe_state_saved);
-
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-static struct platform_driver uvesafb_driver = {
-	.probe  = uvesafb_probe,
-	.remove = uvesafb_remove,
-	.driver = {
-		.name = "uvesafb",
-	},
-};
-
-static struct platform_device *uvesafb_device;
-
-#ifndef MODULE
-static int uvesafb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt) continue;
-
-		if (!strcmp(this_opt, "redraw"))
-			ypan = 0;
-		else if (!strcmp(this_opt, "ypan"))
-			ypan = 1;
-		else if (!strcmp(this_opt, "ywrap"))
-			ypan = 2;
-		else if (!strcmp(this_opt, "vgapal"))
-			pmi_setpal = 0;
-		else if (!strcmp(this_opt, "pmipal"))
-			pmi_setpal = 1;
-		else if (!strncmp(this_opt, "mtrr:", 5))
-			mtrr = simple_strtoul(this_opt+5, NULL, 0);
-		else if (!strcmp(this_opt, "nomtrr"))
-			mtrr = 0;
-		else if (!strcmp(this_opt, "nocrtc"))
-			nocrtc = 1;
-		else if (!strcmp(this_opt, "noedid"))
-			noedid = 1;
-		else if (!strcmp(this_opt, "noblank"))
-			blank = 0;
-		else if (!strncmp(this_opt, "vtotal:", 7))
-			vram_total = simple_strtoul(this_opt + 7, NULL, 0);
-		else if (!strncmp(this_opt, "vremap:", 7))
-			vram_remap = simple_strtoul(this_opt + 7, NULL, 0);
-		else if (!strncmp(this_opt, "maxhf:", 6))
-			maxhf = simple_strtoul(this_opt + 6, NULL, 0);
-		else if (!strncmp(this_opt, "maxvf:", 6))
-			maxvf = simple_strtoul(this_opt + 6, NULL, 0);
-		else if (!strncmp(this_opt, "maxclk:", 7))
-			maxclk = simple_strtoul(this_opt + 7, NULL, 0);
-		else if (!strncmp(this_opt, "vbemode:", 8))
-			vbemode = simple_strtoul(this_opt + 8, NULL, 0);
-		else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
-			mode_option = this_opt;
-		} else {
-			printk(KERN_WARNING
-				"uvesafb: unrecognized option %s\n", this_opt);
-		}
-	}
-
-	if (mtrr != 3 && mtrr != 0)
-		pr_warn("uvesafb: mtrr should be set to 0 or 3; %d is unsupported", mtrr);
-
-	return 0;
-}
-#endif /* !MODULE */
-
-static ssize_t show_v86d(struct device_driver *dev, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path);
-}
-
-static ssize_t store_v86d(struct device_driver *dev, const char *buf,
-		size_t count)
-{
-	strncpy(v86d_path, buf, PATH_MAX);
-	return count;
-}
-
-static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d);
-
-static int uvesafb_init(void)
-{
-	int err;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("uvesafb", &option))
-		return -ENODEV;
-	uvesafb_setup(option);
-#endif
-	err = cn_add_callback(&uvesafb_cn_id, "uvesafb", uvesafb_cn_callback);
-	if (err)
-		return err;
-
-	err = platform_driver_register(&uvesafb_driver);
-
-	if (!err) {
-		uvesafb_device = platform_device_alloc("uvesafb", 0);
-		if (uvesafb_device)
-			err = platform_device_add(uvesafb_device);
-		else
-			err = -ENOMEM;
-
-		if (err) {
-			if (uvesafb_device)
-				platform_device_put(uvesafb_device);
-			platform_driver_unregister(&uvesafb_driver);
-			cn_del_callback(&uvesafb_cn_id);
-			return err;
-		}
-
-		err = driver_create_file(&uvesafb_driver.driver,
-				&driver_attr_v86d);
-		if (err) {
-			printk(KERN_WARNING "uvesafb: failed to register "
-					"attributes\n");
-			err = 0;
-		}
-	}
-	return err;
-}
-
-module_init(uvesafb_init);
-
-static void uvesafb_exit(void)
-{
-	struct uvesafb_ktask *task;
-
-	if (v86d_started) {
-		task = uvesafb_prep();
-		if (task) {
-			task->t.flags = TF_EXIT;
-			uvesafb_exec(task);
-			uvesafb_free(task);
-		}
-	}
-
-	cn_del_callback(&uvesafb_cn_id);
-	driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d);
-	platform_device_unregister(uvesafb_device);
-	platform_driver_unregister(&uvesafb_driver);
-}
-
-module_exit(uvesafb_exit);
-
-static int param_set_scroll(const char *val, const struct kernel_param *kp)
-{
-	ypan = 0;
-
-	if (!strcmp(val, "redraw"))
-		ypan = 0;
-	else if (!strcmp(val, "ypan"))
-		ypan = 1;
-	else if (!strcmp(val, "ywrap"))
-		ypan = 2;
-	else
-		return -EINVAL;
-
-	return 0;
-}
-static struct kernel_param_ops param_ops_scroll = {
-	.set = param_set_scroll,
-};
-#define param_check_scroll(name, p) __param_check(name, p, void)
-
-module_param_named(scroll, ypan, scroll, 0);
-MODULE_PARM_DESC(scroll,
-	"Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'");
-module_param_named(vgapal, pmi_setpal, invbool, 0);
-MODULE_PARM_DESC(vgapal, "Set palette using VGA registers");
-module_param_named(pmipal, pmi_setpal, bool, 0);
-MODULE_PARM_DESC(pmipal, "Set palette using PMI calls");
-module_param(mtrr, uint, 0);
-MODULE_PARM_DESC(mtrr,
-	"Memory Type Range Registers setting. Use 0 to disable.");
-module_param(blank, bool, 0);
-MODULE_PARM_DESC(blank, "Enable hardware blanking");
-module_param(nocrtc, bool, 0);
-MODULE_PARM_DESC(nocrtc, "Ignore CRTC timings when setting modes");
-module_param(noedid, bool, 0);
-MODULE_PARM_DESC(noedid,
-	"Ignore EDID-provided monitor limits when setting modes");
-module_param(vram_remap, uint, 0);
-MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]");
-module_param(vram_total, uint, 0);
-MODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]");
-module_param(maxclk, ushort, 0);
-MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data");
-module_param(maxhf, ushort, 0);
-MODULE_PARM_DESC(maxhf,
-	"Maximum horizontal frequency [kHz], overrides EDID data");
-module_param(maxvf, ushort, 0);
-MODULE_PARM_DESC(maxvf,
-	"Maximum vertical frequency [Hz], overrides EDID data");
-module_param(mode_option, charp, 0);
-MODULE_PARM_DESC(mode_option,
-	"Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
-module_param(vbemode, ushort, 0);
-MODULE_PARM_DESC(vbemode,
-	"VBE mode number to set, overrides the 'mode' option");
-module_param_string(v86d, v86d_path, PATH_MAX, 0660);
-MODULE_PARM_DESC(v86d, "Path to the v86d userspace helper.");
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>");
-MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
-
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
deleted file mode 100644
index 97cb9bd1d1dd..000000000000
--- a/drivers/video/valkyriefb.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- *  valkyriefb.c -- frame buffer device for the PowerMac 'valkyrie' display
- *
- *  Created 8 August 1998 by 
- *  Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel
- *
- *  Vmode-switching changes and vmode 15/17 modifications created 29 August
- *  1998 by Barry K. Nathan <barryn@pobox.com>.
- *
- *  Ported to m68k Macintosh by David Huggins-Daines <dhd@debian.org>
- *
- *  Derived directly from:
- *
- *   controlfb.c -- frame buffer device for the PowerMac 'control' display
- *   Copyright (C) 1998 Dan Jacobowitz <dan@debian.org>
- *
- *   pmc-valkyrie.c -- Console support for PowerMac "valkyrie" display adaptor.
- *   Copyright (C) 1997 Paul Mackerras.
- *
- *  and indirectly:
- *
- *  Frame buffer structure from:
- *    drivers/video/chipsfb.c -- frame buffer device for
- *    Chips & Technologies 65550 chip.
- *
- *    Copyright (C) 1998 Paul Mackerras
- *
- *    This file is derived from the Powermac "chips" driver:
- *    Copyright (C) 1997 Fabio Riccardi.
- *    And from the frame buffer device for Open Firmware-initialized devices:
- *    Copyright (C) 1997 Geert Uytterhoeven.
- *
- *  Hardware information from:
- *    control.c: Console support for PowerMac "control" display adaptor.
- *    Copyright (C) 1996 Paul Mackerras
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/selection.h>
-#include <linux/init.h>
-#include <linux/nvram.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <asm/io.h>
-#ifdef CONFIG_MAC
-#include <asm/macintosh.h>
-#else
-#include <asm/prom.h>
-#endif
-#include <asm/pgtable.h>
-
-#include "macmodes.h"
-#include "valkyriefb.h"
-
-#ifdef CONFIG_MAC
-/* We don't yet have functions to read the PRAM... perhaps we can
-   adapt them from the PPC code? */
-static int default_vmode = VMODE_CHOOSE;
-static int default_cmode = CMODE_8;
-#else
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
-#endif
-
-struct fb_par_valkyrie {
-	int	vmode, cmode;
-	int	xres, yres;
-	int	vxres, vyres;
-	struct valkyrie_regvals *init;
-};
-
-struct fb_info_valkyrie {
-	struct fb_info		info;
-	struct fb_par_valkyrie	par;
-	struct cmap_regs	__iomem *cmap_regs;
-	unsigned long		cmap_regs_phys;
-	
-	struct valkyrie_regs	__iomem *valkyrie_regs;
-	unsigned long		valkyrie_regs_phys;
-	
-	__u8			__iomem *frame_buffer;
-	unsigned long		frame_buffer_phys;
-	
-	int			sense;
-	unsigned long		total_vram;
-
-	u32			pseudo_palette[16];
-};
-
-/*
- * Exported functions
- */
-int valkyriefb_init(void);
-int valkyriefb_setup(char*);
-
-static int valkyriefb_check_var(struct fb_var_screeninfo *var,
-				struct fb_info *info);
-static int valkyriefb_set_par(struct fb_info *info);
-static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info);
-static int valkyriefb_blank(int blank_mode, struct fb_info *info);
-
-static int read_valkyrie_sense(struct fb_info_valkyrie *p);
-static void set_valkyrie_clock(unsigned char *params);
-static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
-	struct fb_par_valkyrie *par, const struct fb_info *fb_info);
-
-static int valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p);
-static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix);
-static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
-
-static struct fb_ops valkyriefb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_check_var =	valkyriefb_check_var,
-	.fb_set_par =	valkyriefb_set_par,
-	.fb_setcolreg =	valkyriefb_setcolreg,
-	.fb_blank =	valkyriefb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-/* Sets the video mode according to info->var */
-static int valkyriefb_set_par(struct fb_info *info)
-{
-	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
-	volatile struct valkyrie_regs __iomem *valkyrie_regs = p->valkyrie_regs;
-	struct fb_par_valkyrie *par = info->par;
-	struct valkyrie_regvals	*init;
-	int err;
-
-	if ((err = valkyrie_var_to_par(&info->var, par, info)))
-		return err;
-
-	valkyrie_par_to_fix(par, &info->fix);
-
-	/* Reset the valkyrie */
-	out_8(&valkyrie_regs->status.r, 0);
-	udelay(100);
-
-	/* Initialize display timing registers */
-	init = par->init;
-	out_8(&valkyrie_regs->mode.r, init->mode | 0x80);
-	out_8(&valkyrie_regs->depth.r, par->cmode + 3);
-	set_valkyrie_clock(init->clock_params);
-	udelay(100);
-
-	/* Turn on display */
-	out_8(&valkyrie_regs->mode.r, init->mode);
-
-	return 0;
-}
-
-static inline int valkyrie_par_to_var(struct fb_par_valkyrie *par,
-				      struct fb_var_screeninfo *var)
-{
-	return mac_vmode_to_var(par->vmode, par->cmode, var);
-}
-
-static int
-valkyriefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int err;
-	struct fb_par_valkyrie par;
-
-	if ((err = valkyrie_var_to_par(var, &par, info)))
-		return err;
-	valkyrie_par_to_var(&par, var);
-	return 0;
-}
-
-/*
- *  Blank the screen if blank_mode != 0, else unblank. If blank_mode == NULL
- *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
- *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
- *  to e.g. a video mode which doesn't support it. Implements VESA suspend
- *  and powerdown modes on hardware that supports disabling hsync/vsync:
- *    blank_mode == 2: suspend vsync
- *    blank_mode == 3: suspend hsync
- *    blank_mode == 4: powerdown
- */
-static int valkyriefb_blank(int blank_mode, struct fb_info *info)
-{
-	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
-	struct fb_par_valkyrie *par = info->par;
-	struct valkyrie_regvals	*init = par->init;
-
-	if (init == NULL)
-		return 1;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:			/* unblank */
-		out_8(&p->valkyrie_regs->mode.r, init->mode);
-		break;
-	case FB_BLANK_NORMAL:
-		return 1;	/* get caller to set CLUT to all black */
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-		/*
-		 * [kps] Value extracted from MacOS. I don't know
-		 * whether this bit disables hsync or vsync, or
-		 * whether the hardware can do the other as well.
-		 */
-		out_8(&p->valkyrie_regs->mode.r, init->mode | 0x40);
-		break;
-	case FB_BLANK_POWERDOWN:
-		out_8(&p->valkyrie_regs->mode.r, 0x66);
-		break;
-	}
-	return 0;
-}
-
-static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info)
-{
-	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
-	volatile struct cmap_regs __iomem *cmap_regs = p->cmap_regs;
-	struct fb_par_valkyrie *par = info->par;
-
-	if (regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-
-	/* tell clut which address to fill */
-	out_8(&p->cmap_regs->addr, regno);
-	udelay(1);
-	/* send one color channel at a time */
-	out_8(&cmap_regs->lut, red);
-	out_8(&cmap_regs->lut, green);
-	out_8(&cmap_regs->lut, blue);
-
-	if (regno < 16 && par->cmode == CMODE_16)
-		((u32 *)info->pseudo_palette)[regno] =
-			(regno << 10) | (regno << 5) | regno;
-
-	return 0;
-}
-
-static inline int valkyrie_vram_reqd(int video_mode, int color_mode)
-{
-	int pitch;
-	struct valkyrie_regvals *init = valkyrie_reg_init[video_mode-1];
-	
-	if ((pitch = init->pitch[color_mode]) == 0)
-		pitch = 2 * init->pitch[0];
-	return init->vres * pitch;
-}
-
-static void set_valkyrie_clock(unsigned char *params)
-{
-	struct adb_request req;
-	int i;
-
-#ifdef CONFIG_ADB_CUDA
-	for (i = 0; i < 3; ++i) {
-		cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
-			     0x50, i + 1, params[i]);
-		while (!req.complete)
-			cuda_poll();
-	}
-#endif
-}
-
-static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p)
-{
-	p->sense = read_valkyrie_sense(p);
-	printk(KERN_INFO "Monitor sense value = 0x%x\n", p->sense);
-
-	/* Try to pick a video mode out of NVRAM if we have one. */
-#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
-	if (default_vmode == VMODE_NVRAM) {
-		default_vmode = nvram_read_byte(NV_VMODE);
-		if (default_vmode <= 0
-		 || default_vmode > VMODE_MAX
-		 || !valkyrie_reg_init[default_vmode - 1])
-			default_vmode = VMODE_CHOOSE;
-	}
-#endif
-	if (default_vmode == VMODE_CHOOSE)
-		default_vmode = mac_map_monitor_sense(p->sense);
-	if (!valkyrie_reg_init[default_vmode - 1])
-		default_vmode = VMODE_640_480_67;
-#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM)
-	if (default_cmode == CMODE_NVRAM)
-		default_cmode = nvram_read_byte(NV_CMODE);
-#endif
-
-	/*
-	 * Reduce the pixel size if we don't have enough VRAM or bandwidth.
-	 */
-	if (default_cmode < CMODE_8 || default_cmode > CMODE_16
-	    || valkyrie_reg_init[default_vmode-1]->pitch[default_cmode] == 0
-	    || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram)
-		default_cmode = CMODE_8;
-
-	printk(KERN_INFO "using video mode %d and color mode %d.\n",
-	       default_vmode, default_cmode);
-}
-
-int __init valkyriefb_init(void)
-{
-	struct fb_info_valkyrie	*p;
-	unsigned long frame_buffer_phys, cmap_regs_phys, flags;
-	int err;
-	char *option = NULL;
-
-	if (fb_get_options("valkyriefb", &option))
-		return -ENODEV;
-	valkyriefb_setup(option);
-
-#ifdef CONFIG_MAC
-	if (!MACH_IS_MAC)
-		return -ENODEV;
-	if (!(mac_bi_data.id == MAC_MODEL_Q630
-	      /* I'm not sure about this one */
-	    || mac_bi_data.id == MAC_MODEL_P588))
-		return -ENODEV;
-
-	/* Hardcoded addresses... welcome to 68k Macintosh country :-) */
-	frame_buffer_phys = 0xf9000000;
-	cmap_regs_phys = 0x50f24000;
-	flags = IOMAP_NOCACHE_SER; /* IOMAP_WRITETHROUGH?? */
-#else /* ppc (!CONFIG_MAC) */
-	{
-		struct device_node *dp;
-		struct resource r;
-
-		dp = of_find_node_by_name(NULL, "valkyrie");
-		if (dp == 0)
-			return 0;
-
-		if (of_address_to_resource(dp, 0, &r)) {
-			printk(KERN_ERR "can't find address for valkyrie\n");
-			return 0;
-		}
-
-		frame_buffer_phys = r.start;
-		cmap_regs_phys = r.start + 0x304000;
-		flags = _PAGE_WRITETHRU;
-	}
-#endif /* ppc (!CONFIG_MAC) */
-
-	p = kzalloc(sizeof(*p), GFP_ATOMIC);
-	if (p == 0)
-		return -ENOMEM;
-
-	/* Map in frame buffer and registers */
-	if (!request_mem_region(frame_buffer_phys, 0x100000, "valkyriefb")) {
-		kfree(p);
-		return 0;
-	}
-	p->total_vram = 0x100000;
-	p->frame_buffer_phys = frame_buffer_phys;
-	p->frame_buffer = __ioremap(frame_buffer_phys, p->total_vram, flags);
-	p->cmap_regs_phys = cmap_regs_phys;
-	p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
-	p->valkyrie_regs_phys = cmap_regs_phys+0x6000;
-	p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, 0x1000);
-	err = -ENOMEM;
-	if (p->frame_buffer == NULL || p->cmap_regs == NULL
-	    || p->valkyrie_regs == NULL) {
-		printk(KERN_ERR "valkyriefb: couldn't map resources\n");
-		goto out_free;
-	}
-
-	valkyrie_choose_mode(p);
-	mac_vmode_to_var(default_vmode, default_cmode, &p->info.var);
-	err = valkyrie_init_info(&p->info, p);
-	if (err < 0)
-		goto out_free;
-	valkyrie_init_fix(&p->info.fix, p);
-	if (valkyriefb_set_par(&p->info))
-		/* "can't happen" */
-		printk(KERN_ERR "valkyriefb: can't set default video mode\n");
-
-	if ((err = register_framebuffer(&p->info)) != 0)
-		goto out_cmap_free;
-
-	fb_info(&p->info, "valkyrie frame buffer device\n");
-	return 0;
-
- out_cmap_free:
-	fb_dealloc_cmap(&p->info.cmap);
- out_free:
-	if (p->frame_buffer)
-		iounmap(p->frame_buffer);
-	if (p->cmap_regs)
-		iounmap(p->cmap_regs);
-	if (p->valkyrie_regs)
-		iounmap(p->valkyrie_regs);
-	kfree(p);
-	return err;
-}
-
-/*
- * Get the monitor sense value.
- */
-static int read_valkyrie_sense(struct fb_info_valkyrie *p)
-{
-	int sense, in;
-
-	out_8(&p->valkyrie_regs->msense.r, 0);   /* release all lines */
-	__delay(20000);
-	sense = ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x70) << 4;
-	/* drive each sense line low in turn and collect the other 2 */
-	out_8(&p->valkyrie_regs->msense.r, 4);   /* drive A low */
-	__delay(20000);
-	sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x30);
-	out_8(&p->valkyrie_regs->msense.r, 2);   /* drive B low */
-	__delay(20000);
-	sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x40) >> 3;
-	sense |= (in & 0x10) >> 2;
-	out_8(&p->valkyrie_regs->msense.r, 1);   /* drive C low */
-	__delay(20000);
-	sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x60) >> 5;
-
-	out_8(&p->valkyrie_regs->msense.r, 7);
-
-	return sense;
-}
-
-/*
- * This routine takes a user-supplied var,
- * and picks the best vmode/cmode from it.
- */
-
-/* [bkn] I did a major overhaul of this function.
- *
- * Much of the old code was "swiped by jonh from atyfb.c". Because
- * macmodes has mac_var_to_vmode, I felt that it would be better to
- * rework this function to use that, instead of reinventing the wheel to
- * add support for vmode 17. This was reinforced by the fact that
- * the previously swiped atyfb.c code is no longer there.
- *
- * So, I swiped and adapted platinum_var_to_par (from platinumfb.c), replacing
- * most, but not all, of the old code in the process. One side benefit of
- * swiping the platinumfb code is that we now have more comprehensible error
- * messages when a vmode/cmode switch fails. (Most of the error messages are
- * platinumfb.c, but I added two of my own, and I also changed some commas
- * into colons to make the messages more consistent with other Linux error
- * messages.) In addition, I think the new code *might* fix some vmode-
- * switching oddities, but I'm not sure.
- *
- * There may be some more opportunities for cleanup in here, but this is a
- * good start...
- */
-
-static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
-	struct fb_par_valkyrie *par, const struct fb_info *fb_info)
-{
-	int vmode, cmode;
-	struct valkyrie_regvals *init;
-	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) fb_info;
-
-	if (mac_var_to_vmode(var, &vmode, &cmode) != 0) {
-		printk(KERN_ERR "valkyriefb: can't do %dx%dx%d.\n",
-		       var->xres, var->yres, var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	/* Check if we know about the wanted video mode */
-	if (vmode < 1 || vmode > VMODE_MAX || !valkyrie_reg_init[vmode-1]) {
-		printk(KERN_ERR "valkyriefb: vmode %d not valid.\n", vmode);
-		return -EINVAL;
-	}
-	
-	if (cmode != CMODE_8 && cmode != CMODE_16) {
-		printk(KERN_ERR "valkyriefb: cmode %d not valid.\n", cmode);
-		return -EINVAL;
-	}
-
-	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres
-	    || var->xoffset != 0 || var->yoffset != 0) {
-		return -EINVAL;
-	}
-
-	init = valkyrie_reg_init[vmode-1];
-	if (init->pitch[cmode] == 0) {
-		printk(KERN_ERR "valkyriefb: vmode %d does not support "
-		       "cmode %d.\n", vmode, cmode);
-		return -EINVAL;
-	}
-
-	if (valkyrie_vram_reqd(vmode, cmode) > p->total_vram) {
-		printk(KERN_ERR "valkyriefb: not enough ram for vmode %d, "
-		       "cmode %d.\n", vmode, cmode);
-		return -EINVAL;
-	}
-
-	par->vmode = vmode;
-	par->cmode = cmode;
-	par->init = init;
-	par->xres = var->xres;
-	par->yres = var->yres;
-	par->vxres = par->xres;
-	par->vyres = par->yres;
-
-	return 0;
-}
-
-static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
-{
-	memset(fix, 0, sizeof(*fix));
-	strcpy(fix->id, "valkyrie");
-	fix->mmio_start = p->valkyrie_regs_phys;
-	fix->mmio_len = sizeof(struct valkyrie_regs);
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->smem_start = p->frame_buffer_phys + 0x1000;
-	fix->smem_len = p->total_vram;
-
-	fix->type_aux = 0;
-	fix->ywrapstep = 0;
-	fix->ypanstep = 0;
-	fix->xpanstep = 0;
-	
-}
-
-/* Fix must already be inited above */
-static void valkyrie_par_to_fix(struct fb_par_valkyrie *par,
-	struct fb_fix_screeninfo *fix)
-{
-	fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode);
-	fix->visual = (par->cmode == CMODE_8) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-	fix->line_length = par->vxres << par->cmode;
-		/* ywrapstep, xpanstep, ypanstep */
-}
-
-static int __init valkyrie_init_info(struct fb_info *info,
-		struct fb_info_valkyrie *p)
-{
-	info->fbops = &valkyriefb_ops;
-	info->screen_base = p->frame_buffer + 0x1000;
-	info->flags = FBINFO_DEFAULT;
-	info->pseudo_palette = p->pseudo_palette;
-	info->par = &p->par;
-	return fb_alloc_cmap(&info->cmap, 256, 0);
-}
-
-
-/*
- * Parse user specified options (`video=valkyriefb:')
- */
-int __init valkyriefb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "vmode:", 6)) {
-	    		int vmode = simple_strtoul(this_opt+6, NULL, 0);
-			if (vmode > 0 && vmode <= VMODE_MAX)
-				default_vmode = vmode;
-		}
-		else if (!strncmp(this_opt, "cmode:", 6)) {
-			int depth = simple_strtoul(this_opt+6, NULL, 0);
-			switch (depth) {
-			case 8:
-				default_cmode = CMODE_8;
-				break;
-			case 15:
-			case 16:
-				default_cmode = CMODE_16;
-				break;
-			}
-		}
-	}
-	return 0;
-}
-
-module_init(valkyriefb_init);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/valkyriefb.h b/drivers/video/valkyriefb.h
deleted file mode 100644
index d787441e5a42..000000000000
--- a/drivers/video/valkyriefb.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * valkyriefb.h: Constants of all sorts for valkyriefb
- *
- *  Created 8 August 1998 by 
- *  Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel
- *
- * Vmode-switching changes and vmode 15/17 modifications created 29 August
- * 1998 by Barry K. Nathan <barryn@pobox.com>.
- * 
- * vmode 10 changed by Steven Borley <sjb@salix.demon.co.uk>, 14 mai 2000
- *
- * Ported to 68k Macintosh by David Huggins-Daines <dhd@debian.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Based directly on:
- *
- *  controlfb.h: Constants of all sorts for controlfb
- *  Copyright (C) 1998 Daniel Jacobowitz <dan@debian.org>
- *
- *  pmc-valkyrie.h: Console support for PowerMac "control" display adaptor.
- *  Copyright (C) 1997 Paul Mackerras.
- *
- *  pmc-valkyrie.c: Console support for PowerMac "control" display adaptor.
- *  Copyright (C) 1997 Paul Mackerras.
- *
- * and indirectly from:
- *
- *  pmc-control.h: Console support for PowerMac "control" display adaptor.
- *  Copyright (C) 1997 Paul Mackerras.
- *
- *  pmc-control.c: Console support for PowerMac "control" display adaptor.
- *  Copyright (C) 1996 Paul Mackerras.
- *
- *  platinumfb.c: Console support for PowerMac "platinum" display adaptor.
- *  Copyright (C) 1998 Jon Howell
- */
-
-#ifdef CONFIG_MAC
-/* Valkyrie registers are word-aligned on m68k */
-#define VALKYRIE_REG_PADSIZE	3
-#else
-#define VALKYRIE_REG_PADSIZE	7
-#endif
-
-/*
- * Structure of the registers for the Valkyrie colormap registers.
- */
-struct cmap_regs {
-	unsigned char addr;
-	char pad1[VALKYRIE_REG_PADSIZE];
-	unsigned char lut;
-};
-
-/*
- * Structure of the registers for the "valkyrie" display adaptor.
- */
-
-struct vpreg {			/* padded register */
-	unsigned char r;
-	char pad[VALKYRIE_REG_PADSIZE];
-};
-
-
-struct valkyrie_regs {
-	struct vpreg mode;
-	struct vpreg depth;
-	struct vpreg status;
-	struct vpreg reg3;
-	struct vpreg intr;
-	struct vpreg reg5;
-	struct vpreg intr_enb;
-	struct vpreg msense;
-};
-
-/*
- * Register initialization tables for the valkyrie display.
- *
- * Dot clock rate is
- * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0].
- */
-struct valkyrie_regvals {
-	unsigned char mode;
-	unsigned char clock_params[3];
-	int	pitch[2];		/* bytes/line, indexed by color_mode */
-	int	hres;
-	int	vres;
-};
-
-#ifndef CONFIG_MAC
-/* Register values for 1024x768, 75Hz mode (17) */
-/* I'm not sure which mode this is (16 or 17), so I'm defining it as 17,
- * since the equivalent mode in controlfb (which I adapted this from) is
- * also 17. Just because MacOS can't do this on Valkyrie doesn't mean we
- * can't! :)
- *
- * I was going to use 12, 31, 3, which I found by myself, but instead I'm
- * using 11, 28, 3 like controlfb, for consistency's sake.
- */
-
-static struct valkyrie_regvals valkyrie_reg_init_17 = {
-    15, 
-    { 11, 28, 3 },  /* pixel clock = 79.55MHz for V=74.50Hz */
-    { 1024, 0 },
-	1024, 768
-};
-
-/* Register values for 1024x768, 72Hz mode (15) */
-/* This used to be 12, 30, 3 for pixel clock = 78.12MHz for V=72.12Hz, but
- * that didn't match MacOS in the same video mode on this chip, and it also
- * caused the 15" Apple Studio Display to not work in this mode. While this
- * mode still doesn't match MacOS exactly (as far as I can tell), it's a lot
- * closer now, and it works with the Apple Studio Display.
- *
- * Yes, even though MacOS calls it "72Hz", in reality it's about 70Hz.
- */
-static struct valkyrie_regvals valkyrie_reg_init_15 = {
-    15,
-    { 12, 29, 3 },  /* pixel clock = 75.52MHz for V=69.71Hz? */
-		    /* I interpolated the V=69.71 from the vmode 14 and old 15
-		     * numbers. Is this result correct?
-		     */
-    { 1024, 0 },
-	1024, 768
-};
-
-/* Register values for 1024x768, 60Hz mode (14) */
-static struct valkyrie_regvals valkyrie_reg_init_14 = {
-    14,
-    { 15, 31, 3 },  /* pixel clock = 64.58MHz for V=59.62Hz */
-    { 1024, 0 },
-	1024, 768
-};
-#endif /* !defined CONFIG_MAC */
-
-/* Register values for 832x624, 75Hz mode (13) */
-static struct valkyrie_regvals valkyrie_reg_init_13 = {
-    9,
-    { 23, 42, 3 },  /* pixel clock = 57.07MHz for V=74.27Hz */
-    { 832, 0 },
-	832, 624
-};
-
-/* Register values for 800x600, 72Hz mode (11) */
-static struct valkyrie_regvals valkyrie_reg_init_11 = {
-    13,
-    { 17, 27, 3 },  /* pixel clock = 49.63MHz for V=71.66Hz */
-    { 800, 0 },
-	800, 600
-};
-
-/* Register values for 800x600, 60Hz mode (10) */
-static struct valkyrie_regvals valkyrie_reg_init_10 = {
-    12,
-    { 25, 32, 3 },  /* pixel clock = 40.0015MHz,
-                     used to be 20,53,2, pixel clock 41.41MHz for V=59.78Hz */
-    { 800, 1600 },
-	800, 600
-};
-
-/* Register values for 640x480, 67Hz mode (6) */
-static struct valkyrie_regvals valkyrie_reg_init_6 = {
-    6,
-    { 14, 27, 2 },  /* pixel clock = 30.13MHz for V=66.43Hz */
-    { 640, 1280 },
-	640, 480
-};
-
-/* Register values for 640x480, 60Hz mode (5) */
-static struct valkyrie_regvals valkyrie_reg_init_5 = {
-    11,
-    { 23, 37, 2 },  /* pixel clock = 25.14MHz for V=59.85Hz */
-    { 640, 1280 },
-	640, 480
-};
-
-static struct valkyrie_regvals *valkyrie_reg_init[VMODE_MAX] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	&valkyrie_reg_init_5,
-	&valkyrie_reg_init_6,
-	NULL,
-	NULL,
-	NULL,
-	&valkyrie_reg_init_10,
-	&valkyrie_reg_init_11,
-	NULL,
-	&valkyrie_reg_init_13,
-#ifndef CONFIG_MAC
-	&valkyrie_reg_init_14,
-	&valkyrie_reg_init_15,
-	NULL,
-	&valkyrie_reg_init_17,
-#endif
-};
diff --git a/drivers/video/vermilion/Makefile b/drivers/video/vermilion/Makefile
deleted file mode 100644
index cc21a656153d..000000000000
--- a/drivers/video/vermilion/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_FB_LE80578) += vmlfb.o
-obj-$(CONFIG_FB_CARILLO_RANCH) += crvml.o
-
-vmlfb-objs := vermilion.o
-crvml-objs := cr_pll.o
diff --git a/drivers/video/vermilion/cr_pll.c b/drivers/video/vermilion/cr_pll.c
deleted file mode 100644
index ebc6e6e0dd0f..000000000000
--- a/drivers/video/vermilion/cr_pll.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) Intel Corp. 2007.
- * All Rights Reserved.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- * This file is part of the Carillo Ranch video subsystem driver.
- * The Carillo Ranch video subsystem driver is free software;
- * you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The Carillo Ranch video subsystem driver is distributed
- * in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Authors:
- *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
- *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include "vermilion.h"
-
-/* The PLL Clock register sits on Host bridge */
-#define CRVML_DEVICE_MCH   0x5001
-#define CRVML_REG_MCHBAR   0x44
-#define CRVML_REG_MCHEN    0x54
-#define CRVML_MCHEN_BIT    (1 << 28)
-#define CRVML_MCHMAP_SIZE  4096
-#define CRVML_REG_CLOCK    0xc3c
-#define CRVML_CLOCK_SHIFT  8
-#define CRVML_CLOCK_MASK   0x00000f00
-
-static struct pci_dev *mch_dev;
-static u32 mch_bar;
-static void __iomem *mch_regs_base;
-static u32 saved_clock;
-
-static const unsigned crvml_clocks[] = {
-	6750,
-	13500,
-	27000,
-	29700,
-	37125,
-	54000,
-	59400,
-	74250,
-	120000
-	    /*
-	     * There are more clocks, but they are disabled on the CR board.
-	     */
-};
-
-static const u32 crvml_clock_bits[] = {
-	0x0a,
-	0x09,
-	0x08,
-	0x07,
-	0x06,
-	0x05,
-	0x04,
-	0x03,
-	0x0b
-};
-
-static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);
-
-static int crvml_sys_restore(struct vml_sys *sys)
-{
-	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
-
-	iowrite32(saved_clock, clock_reg);
-	ioread32(clock_reg);
-
-	return 0;
-}
-
-static int crvml_sys_save(struct vml_sys *sys)
-{
-	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
-
-	saved_clock = ioread32(clock_reg);
-
-	return 0;
-}
-
-static int crvml_nearest_index(const struct vml_sys *sys, int clock)
-{
-	int i;
-	int cur_index = 0;
-	int cur_diff;
-	int diff;
-
-	cur_diff = clock - crvml_clocks[0];
-	cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
-	for (i = 1; i < crvml_num_clocks; ++i) {
-		diff = clock - crvml_clocks[i];
-		diff = (diff < 0) ? -diff : diff;
-		if (diff < cur_diff) {
-			cur_index = i;
-			cur_diff = diff;
-		}
-	}
-	return cur_index;
-}
-
-static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
-{
-	return crvml_clocks[crvml_nearest_index(sys, clock)];
-}
-
-static int crvml_set_clock(struct vml_sys *sys, int clock)
-{
-	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
-	int index;
-	u32 clock_val;
-
-	index = crvml_nearest_index(sys, clock);
-
-	if (crvml_clocks[index] != clock)
-		return -EINVAL;
-
-	clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
-	clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
-	iowrite32(clock_val, clock_reg);
-	ioread32(clock_reg);
-
-	return 0;
-}
-
-static struct vml_sys cr_pll_ops = {
-	.name = "Carillo Ranch",
-	.save = crvml_sys_save,
-	.restore = crvml_sys_restore,
-	.set_clock = crvml_set_clock,
-	.nearest_clock = crvml_nearest_clock,
-};
-
-static int __init cr_pll_init(void)
-{
-	int err;
-	u32 dev_en;
-
-	mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
-					CRVML_DEVICE_MCH, NULL);
-	if (!mch_dev) {
-		printk(KERN_ERR
-		       "Could not find Carillo Ranch MCH device.\n");
-		return -ENODEV;
-	}
-
-	pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
-	if (!(dev_en & CRVML_MCHEN_BIT)) {
-		printk(KERN_ERR
-		       "Carillo Ranch MCH device was not enabled.\n");
-		pci_dev_put(mch_dev);
-		return -ENODEV;
-	}
-
-	pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
-			      &mch_bar);
-	mch_regs_base =
-	    ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE);
-	if (!mch_regs_base) {
-		printk(KERN_ERR
-		       "Carillo Ranch MCH device was not enabled.\n");
-		pci_dev_put(mch_dev);
-		return -ENODEV;
-	}
-
-	err = vmlfb_register_subsys(&cr_pll_ops);
-	if (err) {
-		printk(KERN_ERR
-		       "Carillo Ranch failed to initialize vml_sys.\n");
-		pci_dev_put(mch_dev);
-		return err;
-	}
-
-	return 0;
-}
-
-static void __exit cr_pll_exit(void)
-{
-	vmlfb_unregister_subsys(&cr_pll_ops);
-
-	iounmap(mch_regs_base);
-	pci_dev_put(mch_dev);
-}
-
-module_init(cr_pll_init);
-module_exit(cr_pll_exit);
-
-MODULE_AUTHOR("Tungsten Graphics Inc.");
-MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
deleted file mode 100644
index 048a66640b03..000000000000
--- a/drivers/video/vermilion/vermilion.c
+++ /dev/null
@@ -1,1175 +0,0 @@
-/*
- * Copyright (c) Intel Corp. 2007.
- * All Rights Reserved.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- * This file is part of the Vermilion Range fb driver.
- * The Vermilion Range fb driver is free software;
- * you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The Vermilion Range fb driver is distributed
- * in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Authors:
- *   Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- *   Michel Dänzer <michel-at-tungstengraphics-dot-com>
- *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/pci.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <linux/mmzone.h>
-
-/* #define VERMILION_DEBUG */
-
-#include "vermilion.h"
-
-#define MODULE_NAME "vmlfb"
-
-#define VML_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
-
-static struct mutex vml_mutex;
-static struct list_head global_no_mode;
-static struct list_head global_has_mode;
-static struct fb_ops vmlfb_ops;
-static struct vml_sys *subsys = NULL;
-static char *vml_default_mode = "1024x768@60";
-static struct fb_videomode defaultmode = {
-	NULL, 60, 1024, 768, 12896, 144, 24, 29, 3, 136, 6,
-	0, FB_VMODE_NONINTERLACED
-};
-
-static u32 vml_mem_requested = (10 * 1024 * 1024);
-static u32 vml_mem_contig = (4 * 1024 * 1024);
-static u32 vml_mem_min = (4 * 1024 * 1024);
-
-static u32 vml_clocks[] = {
-	6750,
-	13500,
-	27000,
-	29700,
-	37125,
-	54000,
-	59400,
-	74250,
-	120000,
-	148500
-};
-
-static u32 vml_num_clocks = ARRAY_SIZE(vml_clocks);
-
-/*
- * Allocate a contiguous vram area and make its linear kernel map
- * uncached.
- */
-
-static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order,
-				 unsigned min_order)
-{
-	gfp_t flags;
-	unsigned long i;
-
-	max_order++;
-	do {
-		/*
-		 * Really try hard to get the needed memory.
-		 * We need memory below the first 32MB, so we
-		 * add the __GFP_DMA flag that guarantees that we are
-		 * below the first 16MB.
-		 */
-
-		flags = __GFP_DMA | __GFP_HIGH;
-		va->logical =
-			 __get_free_pages(flags, --max_order);
-	} while (va->logical == 0 && max_order > min_order);
-
-	if (!va->logical)
-		return -ENOMEM;
-
-	va->phys = virt_to_phys((void *)va->logical);
-	va->size = PAGE_SIZE << max_order;
-	va->order = max_order;
-
-	/*
-	 * It seems like __get_free_pages only ups the usage count
-	 * of the first page. This doesn't work with fault mapping, so
-	 * up the usage count once more (XXX: should use split_page or
-	 * compound page).
-	 */
-
-	memset((void *)va->logical, 0x00, va->size);
-	for (i = va->logical; i < va->logical + va->size; i += PAGE_SIZE) {
-		get_page(virt_to_page(i));
-	}
-
-	/*
-	 * Change caching policy of the linear kernel map to avoid
-	 * mapping type conflicts with user-space mappings.
-	 */
-	set_pages_uc(virt_to_page(va->logical), va->size >> PAGE_SHIFT);
-
-	printk(KERN_DEBUG MODULE_NAME
-	       ": Allocated %ld bytes vram area at 0x%08lx\n",
-	       va->size, va->phys);
-
-	return 0;
-}
-
-/*
- * Free a contiguous vram area and reset its linear kernel map
- * mapping type.
- */
-
-static void vmlfb_free_vram_area(struct vram_area *va)
-{
-	unsigned long j;
-
-	if (va->logical) {
-
-		/*
-		 * Reset the linear kernel map caching policy.
-		 */
-
-		set_pages_wb(virt_to_page(va->logical),
-				 va->size >> PAGE_SHIFT);
-
-		/*
-		 * Decrease the usage count on the pages we've used
-		 * to compensate for upping when allocating.
-		 */
-
-		for (j = va->logical; j < va->logical + va->size;
-		     j += PAGE_SIZE) {
-			(void)put_page_testzero(virt_to_page(j));
-		}
-
-		printk(KERN_DEBUG MODULE_NAME
-		       ": Freeing %ld bytes vram area at 0x%08lx\n",
-		       va->size, va->phys);
-		free_pages(va->logical, va->order);
-
-		va->logical = 0;
-	}
-}
-
-/*
- * Free allocated vram.
- */
-
-static void vmlfb_free_vram(struct vml_info *vinfo)
-{
-	int i;
-
-	for (i = 0; i < vinfo->num_areas; ++i) {
-		vmlfb_free_vram_area(&vinfo->vram[i]);
-	}
-	vinfo->num_areas = 0;
-}
-
-/*
- * Allocate vram. Currently we try to allocate contiguous areas from the
- * __GFP_DMA zone and puzzle them together. A better approach would be to
- * allocate one contiguous area for scanout and use one-page allocations for
- * offscreen areas. This requires user-space and GPU virtual mappings.
- */
-
-static int vmlfb_alloc_vram(struct vml_info *vinfo,
-			    size_t requested,
-			    size_t min_total, size_t min_contig)
-{
-	int i, j;
-	int order;
-	int contiguous;
-	int err;
-	struct vram_area *va;
-	struct vram_area *va2;
-
-	vinfo->num_areas = 0;
-	for (i = 0; i < VML_VRAM_AREAS; ++i) {
-		va = &vinfo->vram[i];
-		order = 0;
-
-		while (requested > (PAGE_SIZE << order) && order < MAX_ORDER)
-			order++;
-
-		err = vmlfb_alloc_vram_area(va, order, 0);
-
-		if (err)
-			break;
-
-		if (i == 0) {
-			vinfo->vram_start = va->phys;
-			vinfo->vram_logical = (void __iomem *) va->logical;
-			vinfo->vram_contig_size = va->size;
-			vinfo->num_areas = 1;
-		} else {
-			contiguous = 0;
-
-			for (j = 0; j < i; ++j) {
-				va2 = &vinfo->vram[j];
-				if (va->phys + va->size == va2->phys ||
-				    va2->phys + va2->size == va->phys) {
-					contiguous = 1;
-					break;
-				}
-			}
-
-			if (contiguous) {
-				vinfo->num_areas++;
-				if (va->phys < vinfo->vram_start) {
-					vinfo->vram_start = va->phys;
-					vinfo->vram_logical =
-						(void __iomem *)va->logical;
-				}
-				vinfo->vram_contig_size += va->size;
-			} else {
-				vmlfb_free_vram_area(va);
-				break;
-			}
-		}
-
-		if (requested < va->size)
-			break;
-		else
-			requested -= va->size;
-	}
-
-	if (vinfo->vram_contig_size > min_total &&
-	    vinfo->vram_contig_size > min_contig) {
-
-		printk(KERN_DEBUG MODULE_NAME
-		       ": Contiguous vram: %ld bytes at physical 0x%08lx.\n",
-		       (unsigned long)vinfo->vram_contig_size,
-		       (unsigned long)vinfo->vram_start);
-
-		return 0;
-	}
-
-	printk(KERN_ERR MODULE_NAME
-	       ": Could not allocate requested minimal amount of vram.\n");
-
-	vmlfb_free_vram(vinfo);
-
-	return -ENOMEM;
-}
-
-/*
- * Find the GPU to use with our display controller.
- */
-
-static int vmlfb_get_gpu(struct vml_par *par)
-{
-	mutex_lock(&vml_mutex);
-
-	par->gpu = pci_get_device(PCI_VENDOR_ID_INTEL, VML_DEVICE_GPU, NULL);
-
-	if (!par->gpu) {
-		mutex_unlock(&vml_mutex);
-		return -ENODEV;
-	}
-
-	mutex_unlock(&vml_mutex);
-
-	if (pci_enable_device(par->gpu) < 0)
-		return -ENODEV;
-
-	return 0;
-}
-
-/*
- * Find a contiguous vram area that contains a given offset from vram start.
- */
-static int vmlfb_vram_offset(struct vml_info *vinfo, unsigned long offset)
-{
-	unsigned long aoffset;
-	unsigned i;
-
-	for (i = 0; i < vinfo->num_areas; ++i) {
-		aoffset = offset - (vinfo->vram[i].phys - vinfo->vram_start);
-
-		if (aoffset < vinfo->vram[i].size) {
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-/*
- * Remap the MMIO register spaces of the VDC and the GPU.
- */
-
-static int vmlfb_enable_mmio(struct vml_par *par)
-{
-	int err;
-
-	par->vdc_mem_base = pci_resource_start(par->vdc, 0);
-	par->vdc_mem_size = pci_resource_len(par->vdc, 0);
-	if (!request_mem_region(par->vdc_mem_base, par->vdc_mem_size, "vmlfb")) {
-		printk(KERN_ERR MODULE_NAME
-		       ": Could not claim display controller MMIO.\n");
-		return -EBUSY;
-	}
-	par->vdc_mem = ioremap_nocache(par->vdc_mem_base, par->vdc_mem_size);
-	if (par->vdc_mem == NULL) {
-		printk(KERN_ERR MODULE_NAME
-		       ": Could not map display controller MMIO.\n");
-		err = -ENOMEM;
-		goto out_err_0;
-	}
-
-	par->gpu_mem_base = pci_resource_start(par->gpu, 0);
-	par->gpu_mem_size = pci_resource_len(par->gpu, 0);
-	if (!request_mem_region(par->gpu_mem_base, par->gpu_mem_size, "vmlfb")) {
-		printk(KERN_ERR MODULE_NAME ": Could not claim GPU MMIO.\n");
-		err = -EBUSY;
-		goto out_err_1;
-	}
-	par->gpu_mem = ioremap_nocache(par->gpu_mem_base, par->gpu_mem_size);
-	if (par->gpu_mem == NULL) {
-		printk(KERN_ERR MODULE_NAME ": Could not map GPU MMIO.\n");
-		err = -ENOMEM;
-		goto out_err_2;
-	}
-
-	return 0;
-
-out_err_2:
-	release_mem_region(par->gpu_mem_base, par->gpu_mem_size);
-out_err_1:
-	iounmap(par->vdc_mem);
-out_err_0:
-	release_mem_region(par->vdc_mem_base, par->vdc_mem_size);
-	return err;
-}
-
-/*
- * Unmap the VDC and GPU register spaces.
- */
-
-static void vmlfb_disable_mmio(struct vml_par *par)
-{
-	iounmap(par->gpu_mem);
-	release_mem_region(par->gpu_mem_base, par->gpu_mem_size);
-	iounmap(par->vdc_mem);
-	release_mem_region(par->vdc_mem_base, par->vdc_mem_size);
-}
-
-/*
- * Release and uninit the VDC and GPU.
- */
-
-static void vmlfb_release_devices(struct vml_par *par)
-{
-	if (atomic_dec_and_test(&par->refcount)) {
-		pci_disable_device(par->gpu);
-		pci_disable_device(par->vdc);
-	}
-}
-
-/*
- * Free up allocated resources for a device.
- */
-
-static void vml_pci_remove(struct pci_dev *dev)
-{
-	struct fb_info *info;
-	struct vml_info *vinfo;
-	struct vml_par *par;
-
-	info = pci_get_drvdata(dev);
-	if (info) {
-		vinfo = container_of(info, struct vml_info, info);
-		par = vinfo->par;
-		mutex_lock(&vml_mutex);
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-		vmlfb_free_vram(vinfo);
-		vmlfb_disable_mmio(par);
-		vmlfb_release_devices(par);
-		kfree(vinfo);
-		kfree(par);
-		mutex_unlock(&vml_mutex);
-	}
-}
-
-static void vmlfb_set_pref_pixel_format(struct fb_var_screeninfo *var)
-{
-	switch (var->bits_per_pixel) {
-	case 16:
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->transp.offset = 15;
-		var->transp.length = 1;
-		break;
-	case 32:
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 0;
-		break;
-	default:
-		break;
-	}
-
-	var->blue.msb_right = var->green.msb_right =
-	    var->red.msb_right = var->transp.msb_right = 0;
-}
-
-/*
- * Device initialization.
- * We initialize one vml_par struct per device and one vml_info
- * struct per pipe. Currently we have only one pipe.
- */
-
-static int vml_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct vml_info *vinfo;
-	struct fb_info *info;
-	struct vml_par *par;
-	int err = 0;
-
-	par = kzalloc(sizeof(*par), GFP_KERNEL);
-	if (par == NULL)
-		return -ENOMEM;
-
-	vinfo = kzalloc(sizeof(*vinfo), GFP_KERNEL);
-	if (vinfo == NULL) {
-		err = -ENOMEM;
-		goto out_err_0;
-	}
-
-	vinfo->par = par;
-	par->vdc = dev;
-	atomic_set(&par->refcount, 1);
-
-	switch (id->device) {
-	case VML_DEVICE_VDC:
-		if ((err = vmlfb_get_gpu(par)))
-			goto out_err_1;
-		pci_set_drvdata(dev, &vinfo->info);
-		break;
-	default:
-		err = -ENODEV;
-		goto out_err_1;
-		break;
-	}
-
-	info = &vinfo->info;
-	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK;
-
-	err = vmlfb_enable_mmio(par);
-	if (err)
-		goto out_err_2;
-
-	err = vmlfb_alloc_vram(vinfo, vml_mem_requested,
-			       vml_mem_contig, vml_mem_min);
-	if (err)
-		goto out_err_3;
-
-	strcpy(info->fix.id, "Vermilion Range");
-	info->fix.mmio_start = 0;
-	info->fix.mmio_len = 0;
-	info->fix.smem_start = vinfo->vram_start;
-	info->fix.smem_len = vinfo->vram_contig_size;
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-	info->fix.ypanstep = 1;
-	info->fix.xpanstep = 1;
-	info->fix.ywrapstep = 0;
-	info->fix.accel = FB_ACCEL_NONE;
-	info->screen_base = vinfo->vram_logical;
-	info->pseudo_palette = vinfo->pseudo_palette;
-	info->par = par;
-	info->fbops = &vmlfb_ops;
-	info->device = &dev->dev;
-
-	INIT_LIST_HEAD(&vinfo->head);
-	vinfo->pipe_disabled = 1;
-	vinfo->cur_blank_mode = FB_BLANK_UNBLANK;
-
-	info->var.grayscale = 0;
-	info->var.bits_per_pixel = 16;
-	vmlfb_set_pref_pixel_format(&info->var);
-
-	if (!fb_find_mode
-	    (&info->var, info, vml_default_mode, NULL, 0, &defaultmode, 16)) {
-		printk(KERN_ERR MODULE_NAME ": Could not find initial mode\n");
-	}
-
-	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
-		err = -ENOMEM;
-		goto out_err_4;
-	}
-
-	err = register_framebuffer(info);
-	if (err) {
-		printk(KERN_ERR MODULE_NAME ": Register framebuffer error.\n");
-		goto out_err_5;
-	}
-
-	printk("Initialized vmlfb\n");
-
-	return 0;
-
-out_err_5:
-	fb_dealloc_cmap(&info->cmap);
-out_err_4:
-	vmlfb_free_vram(vinfo);
-out_err_3:
-	vmlfb_disable_mmio(par);
-out_err_2:
-	vmlfb_release_devices(par);
-out_err_1:
-	kfree(vinfo);
-out_err_0:
-	kfree(par);
-	return err;
-}
-
-static int vmlfb_open(struct fb_info *info, int user)
-{
-	/*
-	 * Save registers here?
-	 */
-	return 0;
-}
-
-static int vmlfb_release(struct fb_info *info, int user)
-{
-	/*
-	 * Restore registers here.
-	 */
-
-	return 0;
-}
-
-static int vml_nearest_clock(int clock)
-{
-
-	int i;
-	int cur_index;
-	int cur_diff;
-	int diff;
-
-	cur_index = 0;
-	cur_diff = clock - vml_clocks[0];
-	cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
-	for (i = 1; i < vml_num_clocks; ++i) {
-		diff = clock - vml_clocks[i];
-		diff = (diff < 0) ? -diff : diff;
-		if (diff < cur_diff) {
-			cur_index = i;
-			cur_diff = diff;
-		}
-	}
-	return vml_clocks[cur_index];
-}
-
-static int vmlfb_check_var_locked(struct fb_var_screeninfo *var,
-				  struct vml_info *vinfo)
-{
-	u32 pitch;
-	u64 mem;
-	int nearest_clock;
-	int clock;
-	int clock_diff;
-	struct fb_var_screeninfo v;
-
-	v = *var;
-	clock = PICOS2KHZ(var->pixclock);
-
-	if (subsys && subsys->nearest_clock) {
-		nearest_clock = subsys->nearest_clock(subsys, clock);
-	} else {
-		nearest_clock = vml_nearest_clock(clock);
-	}
-
-	/*
-	 * Accept a 20% diff.
-	 */
-
-	clock_diff = nearest_clock - clock;
-	clock_diff = (clock_diff < 0) ? -clock_diff : clock_diff;
-	if (clock_diff > clock / 5) {
-#if 0
-		printk(KERN_DEBUG MODULE_NAME ": Diff failure. %d %d\n",clock_diff,clock);
-#endif
-		return -EINVAL;
-	}
-
-	v.pixclock = KHZ2PICOS(nearest_clock);
-
-	if (var->xres > VML_MAX_XRES || var->yres > VML_MAX_YRES) {
-		printk(KERN_DEBUG MODULE_NAME ": Resolution failure.\n");
-		return -EINVAL;
-	}
-	if (var->xres_virtual > VML_MAX_XRES_VIRTUAL) {
-		printk(KERN_DEBUG MODULE_NAME
-		       ": Virtual resolution failure.\n");
-		return -EINVAL;
-	}
-	switch (v.bits_per_pixel) {
-	case 0 ... 16:
-		v.bits_per_pixel = 16;
-		break;
-	case 17 ... 32:
-		v.bits_per_pixel = 32;
-		break;
-	default:
-		printk(KERN_DEBUG MODULE_NAME ": Invalid bpp: %d.\n",
-		       var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	pitch = ALIGN((var->xres * var->bits_per_pixel) >> 3, 0x40);
-	mem = pitch * var->yres_virtual;
-	if (mem > vinfo->vram_contig_size) {
-		return -ENOMEM;
-	}
-
-	switch (v.bits_per_pixel) {
-	case 16:
-		if (var->blue.offset != 0 ||
-		    var->blue.length != 5 ||
-		    var->green.offset != 5 ||
-		    var->green.length != 5 ||
-		    var->red.offset != 10 ||
-		    var->red.length != 5 ||
-		    var->transp.offset != 15 || var->transp.length != 1) {
-			vmlfb_set_pref_pixel_format(&v);
-		}
-		break;
-	case 32:
-		if (var->blue.offset != 0 ||
-		    var->blue.length != 8 ||
-		    var->green.offset != 8 ||
-		    var->green.length != 8 ||
-		    var->red.offset != 16 ||
-		    var->red.length != 8 ||
-		    (var->transp.length != 0 && var->transp.length != 8) ||
-		    (var->transp.length == 8 && var->transp.offset != 24)) {
-			vmlfb_set_pref_pixel_format(&v);
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	*var = v;
-
-	return 0;
-}
-
-static int vmlfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct vml_info *vinfo = container_of(info, struct vml_info, info);
-	int ret;
-
-	mutex_lock(&vml_mutex);
-	ret = vmlfb_check_var_locked(var, vinfo);
-	mutex_unlock(&vml_mutex);
-
-	return ret;
-}
-
-static void vml_wait_vblank(struct vml_info *vinfo)
-{
-	/* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
-	mdelay(20);
-}
-
-static void vmlfb_disable_pipe(struct vml_info *vinfo)
-{
-	struct vml_par *par = vinfo->par;
-
-	/* Disable the MDVO pad */
-	VML_WRITE32(par, VML_RCOMPSTAT, 0);
-	while (!(VML_READ32(par, VML_RCOMPSTAT) & VML_MDVO_VDC_I_RCOMP)) ;
-
-	/* Disable display planes */
-	VML_WRITE32(par, VML_DSPCCNTR,
-		    VML_READ32(par, VML_DSPCCNTR) & ~VML_GFX_ENABLE);
-	(void)VML_READ32(par, VML_DSPCCNTR);
-	/* Wait for vblank for the disable to take effect */
-	vml_wait_vblank(vinfo);
-
-	/* Next, disable display pipes */
-	VML_WRITE32(par, VML_PIPEACONF, 0);
-	(void)VML_READ32(par, VML_PIPEACONF);
-
-	vinfo->pipe_disabled = 1;
-}
-
-#ifdef VERMILION_DEBUG
-static void vml_dump_regs(struct vml_info *vinfo)
-{
-	struct vml_par *par = vinfo->par;
-
-	printk(KERN_DEBUG MODULE_NAME ": Modesetting register dump:\n");
-	printk(KERN_DEBUG MODULE_NAME ": \tHTOTAL_A         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_HTOTAL_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tHBLANK_A         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_HBLANK_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tHSYNC_A          : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_HSYNC_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tVTOTAL_A         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_VTOTAL_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tVBLANK_A         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_VBLANK_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tVSYNC_A          : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_VSYNC_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tDSPCSTRIDE       : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_DSPCSTRIDE));
-	printk(KERN_DEBUG MODULE_NAME ": \tDSPCSIZE         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_DSPCSIZE));
-	printk(KERN_DEBUG MODULE_NAME ": \tDSPCPOS          : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_DSPCPOS));
-	printk(KERN_DEBUG MODULE_NAME ": \tDSPARB           : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_DSPARB));
-	printk(KERN_DEBUG MODULE_NAME ": \tDSPCADDR         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_DSPCADDR));
-	printk(KERN_DEBUG MODULE_NAME ": \tBCLRPAT_A        : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_BCLRPAT_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tCANVSCLR_A       : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_CANVSCLR_A));
-	printk(KERN_DEBUG MODULE_NAME ": \tPIPEASRC         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_PIPEASRC));
-	printk(KERN_DEBUG MODULE_NAME ": \tPIPEACONF        : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_PIPEACONF));
-	printk(KERN_DEBUG MODULE_NAME ": \tDSPCCNTR         : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_DSPCCNTR));
-	printk(KERN_DEBUG MODULE_NAME ": \tRCOMPSTAT        : 0x%08x\n",
-	       (unsigned)VML_READ32(par, VML_RCOMPSTAT));
-	printk(KERN_DEBUG MODULE_NAME ": End of modesetting register dump.\n");
-}
-#endif
-
-static int vmlfb_set_par_locked(struct vml_info *vinfo)
-{
-	struct vml_par *par = vinfo->par;
-	struct fb_info *info = &vinfo->info;
-	struct fb_var_screeninfo *var = &info->var;
-	u32 htotal, hactive, hblank_start, hblank_end, hsync_start, hsync_end;
-	u32 vtotal, vactive, vblank_start, vblank_end, vsync_start, vsync_end;
-	u32 dspcntr;
-	int clock;
-
-	vinfo->bytes_per_pixel = var->bits_per_pixel >> 3;
-	vinfo->stride = ALIGN(var->xres_virtual * vinfo->bytes_per_pixel, 0x40);
-	info->fix.line_length = vinfo->stride;
-
-	if (!subsys)
-		return 0;
-
-	htotal =
-	    var->xres + var->right_margin + var->hsync_len + var->left_margin;
-	hactive = var->xres;
-	hblank_start = var->xres;
-	hblank_end = htotal;
-	hsync_start = hactive + var->right_margin;
-	hsync_end = hsync_start + var->hsync_len;
-
-	vtotal =
-	    var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
-	vactive = var->yres;
-	vblank_start = var->yres;
-	vblank_end = vtotal;
-	vsync_start = vactive + var->lower_margin;
-	vsync_end = vsync_start + var->vsync_len;
-
-	dspcntr = VML_GFX_ENABLE | VML_GFX_GAMMABYPASS;
-	clock = PICOS2KHZ(var->pixclock);
-
-	if (subsys->nearest_clock) {
-		clock = subsys->nearest_clock(subsys, clock);
-	} else {
-		clock = vml_nearest_clock(clock);
-	}
-	printk(KERN_DEBUG MODULE_NAME
-	       ": Set mode Hfreq : %d kHz, Vfreq : %d Hz.\n", clock / htotal,
-	       ((clock / htotal) * 1000) / vtotal);
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		dspcntr |= VML_GFX_ARGB1555;
-		break;
-	case 32:
-		if (var->transp.length == 8)
-			dspcntr |= VML_GFX_ARGB8888 | VML_GFX_ALPHAMULT;
-		else
-			dspcntr |= VML_GFX_RGB0888;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	vmlfb_disable_pipe(vinfo);
-	mb();
-
-	if (subsys->set_clock)
-		subsys->set_clock(subsys, clock);
-	else
-		return -EINVAL;
-
-	VML_WRITE32(par, VML_HTOTAL_A, ((htotal - 1) << 16) | (hactive - 1));
-	VML_WRITE32(par, VML_HBLANK_A,
-		    ((hblank_end - 1) << 16) | (hblank_start - 1));
-	VML_WRITE32(par, VML_HSYNC_A,
-		    ((hsync_end - 1) << 16) | (hsync_start - 1));
-	VML_WRITE32(par, VML_VTOTAL_A, ((vtotal - 1) << 16) | (vactive - 1));
-	VML_WRITE32(par, VML_VBLANK_A,
-		    ((vblank_end - 1) << 16) | (vblank_start - 1));
-	VML_WRITE32(par, VML_VSYNC_A,
-		    ((vsync_end - 1) << 16) | (vsync_start - 1));
-	VML_WRITE32(par, VML_DSPCSTRIDE, vinfo->stride);
-	VML_WRITE32(par, VML_DSPCSIZE,
-		    ((var->yres - 1) << 16) | (var->xres - 1));
-	VML_WRITE32(par, VML_DSPCPOS, 0x00000000);
-	VML_WRITE32(par, VML_DSPARB, VML_FIFO_DEFAULT);
-	VML_WRITE32(par, VML_BCLRPAT_A, 0x00000000);
-	VML_WRITE32(par, VML_CANVSCLR_A, 0x00000000);
-	VML_WRITE32(par, VML_PIPEASRC,
-		    ((var->xres - 1) << 16) | (var->yres - 1));
-
-	wmb();
-	VML_WRITE32(par, VML_PIPEACONF, VML_PIPE_ENABLE);
-	wmb();
-	VML_WRITE32(par, VML_DSPCCNTR, dspcntr);
-	wmb();
-	VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start +
-		    var->yoffset * vinfo->stride +
-		    var->xoffset * vinfo->bytes_per_pixel);
-
-	VML_WRITE32(par, VML_RCOMPSTAT, VML_MDVO_PAD_ENABLE);
-
-	while (!(VML_READ32(par, VML_RCOMPSTAT) &
-		 (VML_MDVO_VDC_I_RCOMP | VML_MDVO_PAD_ENABLE))) ;
-
-	vinfo->pipe_disabled = 0;
-#ifdef VERMILION_DEBUG
-	vml_dump_regs(vinfo);
-#endif
-
-	return 0;
-}
-
-static int vmlfb_set_par(struct fb_info *info)
-{
-	struct vml_info *vinfo = container_of(info, struct vml_info, info);
-	int ret;
-
-	mutex_lock(&vml_mutex);
-	list_move(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode);
-	ret = vmlfb_set_par_locked(vinfo);
-
-	mutex_unlock(&vml_mutex);
-	return ret;
-}
-
-static int vmlfb_blank_locked(struct vml_info *vinfo)
-{
-	struct vml_par *par = vinfo->par;
-	u32 cur = VML_READ32(par, VML_PIPEACONF);
-
-	switch (vinfo->cur_blank_mode) {
-	case FB_BLANK_UNBLANK:
-		if (vinfo->pipe_disabled) {
-			vmlfb_set_par_locked(vinfo);
-		}
-		VML_WRITE32(par, VML_PIPEACONF, cur & ~VML_PIPE_FORCE_BORDER);
-		(void)VML_READ32(par, VML_PIPEACONF);
-		break;
-	case FB_BLANK_NORMAL:
-		if (vinfo->pipe_disabled) {
-			vmlfb_set_par_locked(vinfo);
-		}
-		VML_WRITE32(par, VML_PIPEACONF, cur | VML_PIPE_FORCE_BORDER);
-		(void)VML_READ32(par, VML_PIPEACONF);
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-		if (!vinfo->pipe_disabled) {
-			vmlfb_disable_pipe(vinfo);
-		}
-		break;
-	case FB_BLANK_POWERDOWN:
-		if (!vinfo->pipe_disabled) {
-			vmlfb_disable_pipe(vinfo);
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int vmlfb_blank(int blank_mode, struct fb_info *info)
-{
-	struct vml_info *vinfo = container_of(info, struct vml_info, info);
-	int ret;
-
-	mutex_lock(&vml_mutex);
-	vinfo->cur_blank_mode = blank_mode;
-	ret = vmlfb_blank_locked(vinfo);
-	mutex_unlock(&vml_mutex);
-	return ret;
-}
-
-static int vmlfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct vml_info *vinfo = container_of(info, struct vml_info, info);
-	struct vml_par *par = vinfo->par;
-
-	mutex_lock(&vml_mutex);
-	VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start +
-		    var->yoffset * vinfo->stride +
-		    var->xoffset * vinfo->bytes_per_pixel);
-	(void)VML_READ32(par, VML_DSPCADDR);
-	mutex_unlock(&vml_mutex);
-
-	return 0;
-}
-
-static int vmlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	u32 v;
-
-	if (regno >= 16)
-		return -EINVAL;
-
-	if (info->var.grayscale) {
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	if (info->fix.visual != FB_VISUAL_TRUECOLOR)
-		return -EINVAL;
-
-	red = VML_TOHW(red, info->var.red.length);
-	blue = VML_TOHW(blue, info->var.blue.length);
-	green = VML_TOHW(green, info->var.green.length);
-	transp = VML_TOHW(transp, info->var.transp.length);
-
-	v = (red << info->var.red.offset) |
-	    (green << info->var.green.offset) |
-	    (blue << info->var.blue.offset) |
-	    (transp << info->var.transp.offset);
-
-	switch (info->var.bits_per_pixel) {
-	case 16:
-		((u32 *) info->pseudo_palette)[regno] = v;
-		break;
-	case 24:
-	case 32:
-		((u32 *) info->pseudo_palette)[regno] = v;
-		break;
-	}
-	return 0;
-}
-
-static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct vml_info *vinfo = container_of(info, struct vml_info, info);
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	int ret;
-
-	ret = vmlfb_vram_offset(vinfo, offset);
-	if (ret)
-		return -EINVAL;
-
-	pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-	pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
-
-	return vm_iomap_memory(vma, vinfo->vram_start,
-			vinfo->vram_contig_size);
-}
-
-static int vmlfb_sync(struct fb_info *info)
-{
-	return 0;
-}
-
-static int vmlfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	return -EINVAL;	/* just to force soft_cursor() call */
-}
-
-static struct fb_ops vmlfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = vmlfb_open,
-	.fb_release = vmlfb_release,
-	.fb_check_var = vmlfb_check_var,
-	.fb_set_par = vmlfb_set_par,
-	.fb_blank = vmlfb_blank,
-	.fb_pan_display = vmlfb_pan_display,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor = vmlfb_cursor,
-	.fb_sync = vmlfb_sync,
-	.fb_mmap = vmlfb_mmap,
-	.fb_setcolreg = vmlfb_setcolreg
-};
-
-static struct pci_device_id vml_ids[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, VML_DEVICE_VDC)},
-	{0}
-};
-
-static struct pci_driver vmlfb_pci_driver = {
-	.name = "vmlfb",
-	.id_table = vml_ids,
-	.probe = vml_pci_probe,
-	.remove = vml_pci_remove,
-};
-
-static void __exit vmlfb_cleanup(void)
-{
-	pci_unregister_driver(&vmlfb_pci_driver);
-}
-
-static int __init vmlfb_init(void)
-{
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options(MODULE_NAME, &option))
-		return -ENODEV;
-#endif
-
-	printk(KERN_DEBUG MODULE_NAME ": initializing\n");
-	mutex_init(&vml_mutex);
-	INIT_LIST_HEAD(&global_no_mode);
-	INIT_LIST_HEAD(&global_has_mode);
-
-	return pci_register_driver(&vmlfb_pci_driver);
-}
-
-int vmlfb_register_subsys(struct vml_sys *sys)
-{
-	struct vml_info *entry;
-	struct list_head *list;
-	u32 save_activate;
-
-	mutex_lock(&vml_mutex);
-	if (subsys != NULL) {
-		subsys->restore(subsys);
-	}
-	subsys = sys;
-	subsys->save(subsys);
-
-	/*
-	 * We need to restart list traversal for each item, since we
-	 * release the list mutex in the loop.
-	 */
-
-	list = global_no_mode.next;
-	while (list != &global_no_mode) {
-		list_del_init(list);
-		entry = list_entry(list, struct vml_info, head);
-
-		/*
-		 * First, try the current mode which might not be
-		 * completely validated with respect to the pixel clock.
-		 */
-
-		if (!vmlfb_check_var_locked(&entry->info.var, entry)) {
-			vmlfb_set_par_locked(entry);
-			list_add_tail(list, &global_has_mode);
-		} else {
-
-			/*
-			 * Didn't work. Try to find another mode,
-			 * that matches this subsys.
-			 */
-
-			mutex_unlock(&vml_mutex);
-			save_activate = entry->info.var.activate;
-			entry->info.var.bits_per_pixel = 16;
-			vmlfb_set_pref_pixel_format(&entry->info.var);
-			if (fb_find_mode(&entry->info.var,
-					 &entry->info,
-					 vml_default_mode, NULL, 0, NULL, 16)) {
-				entry->info.var.activate |=
-				    FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
-				fb_set_var(&entry->info, &entry->info.var);
-			} else {
-				printk(KERN_ERR MODULE_NAME
-				       ": Sorry. no mode found for this subsys.\n");
-			}
-			entry->info.var.activate = save_activate;
-			mutex_lock(&vml_mutex);
-		}
-		vmlfb_blank_locked(entry);
-		list = global_no_mode.next;
-	}
-	mutex_unlock(&vml_mutex);
-
-	printk(KERN_DEBUG MODULE_NAME ": Registered %s subsystem.\n",
-				subsys->name ? subsys->name : "unknown");
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(vmlfb_register_subsys);
-
-void vmlfb_unregister_subsys(struct vml_sys *sys)
-{
-	struct vml_info *entry, *next;
-
-	mutex_lock(&vml_mutex);
-	if (subsys != sys) {
-		mutex_unlock(&vml_mutex);
-		return;
-	}
-	subsys->restore(subsys);
-	subsys = NULL;
-	list_for_each_entry_safe(entry, next, &global_has_mode, head) {
-		printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n");
-		vmlfb_disable_pipe(entry);
-		list_move_tail(&entry->head, &global_no_mode);
-	}
-	mutex_unlock(&vml_mutex);
-}
-
-EXPORT_SYMBOL_GPL(vmlfb_unregister_subsys);
-
-module_init(vmlfb_init);
-module_exit(vmlfb_cleanup);
-
-MODULE_AUTHOR("Tungsten Graphics");
-MODULE_DESCRIPTION("Initialization of the Vermilion display devices");
-MODULE_VERSION("1.0.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
deleted file mode 100644
index 43d11ec197fc..000000000000
--- a/drivers/video/vermilion/vermilion.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (c) Intel Corp. 2007.
- * All Rights Reserved.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- * This file is part of the Vermilion Range fb driver.
- * The Vermilion Range fb driver is free software;
- * you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The Vermilion Range fb driver is distributed
- * in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this driver; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Authors:
- *   Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#ifndef _VERMILION_H_
-#define _VERMILION_H_
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/atomic.h>
-#include <linux/mutex.h>
-
-#define VML_DEVICE_GPU 0x5002
-#define VML_DEVICE_VDC 0x5009
-
-#define VML_VRAM_AREAS 3
-#define VML_MAX_XRES 1024
-#define VML_MAX_YRES 768
-#define VML_MAX_XRES_VIRTUAL 1040
-
-/*
- * Display controller registers:
- */
-
-/* Display controller 10-bit color representation */
-
-#define VML_R_MASK                   0x3FF00000
-#define VML_R_SHIFT                  20
-#define VML_G_MASK                   0x000FFC00
-#define VML_G_SHIFT                  10
-#define VML_B_MASK                   0x000003FF
-#define VML_B_SHIFT                  0
-
-/* Graphics plane control */
-#define VML_DSPCCNTR                 0x00072180
-#define VML_GFX_ENABLE               0x80000000
-#define VML_GFX_GAMMABYPASS          0x40000000
-#define VML_GFX_ARGB1555             0x0C000000
-#define VML_GFX_RGB0888              0x18000000
-#define VML_GFX_ARGB8888             0x1C000000
-#define VML_GFX_ALPHACONST           0x02000000
-#define VML_GFX_ALPHAMULT            0x01000000
-#define VML_GFX_CONST_ALPHA          0x000000FF
-
-/* Graphics plane start address. Pixel aligned. */
-#define VML_DSPCADDR                 0x00072184
-
-/* Graphics plane stride register. */
-#define VML_DSPCSTRIDE               0x00072188
-
-/* Graphics plane position register. */
-#define VML_DSPCPOS                  0x0007218C
-#define VML_POS_YMASK                0x0FFF0000
-#define VML_POS_YSHIFT               16
-#define VML_POS_XMASK                0x00000FFF
-#define VML_POS_XSHIFT               0
-
-/* Graphics plane height and width */
-#define VML_DSPCSIZE                 0x00072190
-#define VML_SIZE_HMASK               0x0FFF0000
-#define VML_SIZE_HSHIFT              16
-#define VML_SISE_WMASK               0x00000FFF
-#define VML_SIZE_WSHIFT              0
-
-/* Graphics plane gamma correction lookup table registers (129 * 32 bits) */
-#define VML_DSPCGAMLUT               0x00072200
-
-/* Pixel video output configuration register */
-#define VML_PVOCONFIG                0x00061140
-#define VML_CONFIG_BASE              0x80000000
-#define VML_CONFIG_PIXEL_SWAP        0x04000000
-#define VML_CONFIG_DE_INV            0x01000000
-#define VML_CONFIG_HREF_INV          0x00400000
-#define VML_CONFIG_VREF_INV          0x00100000
-#define VML_CONFIG_CLK_INV           0x00040000
-#define VML_CONFIG_CLK_DIV2          0x00010000
-#define VML_CONFIG_ESTRB_INV         0x00008000
-
-/* Pipe A Horizontal total register */
-#define VML_HTOTAL_A                 0x00060000
-#define VML_HTOTAL_MASK              0x1FFF0000
-#define VML_HTOTAL_SHIFT             16
-#define VML_HTOTAL_VAL               8192
-#define VML_HACTIVE_MASK             0x000007FF
-#define VML_HACTIVE_SHIFT            0
-#define VML_HACTIVE_VAL              4096
-
-/* Pipe A Horizontal Blank register */
-#define VML_HBLANK_A                 0x00060004
-#define VML_HBLANK_END_MASK          0x1FFF0000
-#define VML_HBLANK_END_SHIFT         16
-#define VML_HBLANK_END_VAL           8192
-#define VML_HBLANK_START_MASK        0x00001FFF
-#define VML_HBLANK_START_SHIFT       0
-#define VML_HBLANK_START_VAL         8192
-
-/* Pipe A Horizontal Sync register */
-#define VML_HSYNC_A                  0x00060008
-#define VML_HSYNC_END_MASK           0x1FFF0000
-#define VML_HSYNC_END_SHIFT          16
-#define VML_HSYNC_END_VAL            8192
-#define VML_HSYNC_START_MASK         0x00001FFF
-#define VML_HSYNC_START_SHIFT        0
-#define VML_HSYNC_START_VAL          8192
-
-/* Pipe A Vertical total register */
-#define VML_VTOTAL_A                 0x0006000C
-#define VML_VTOTAL_MASK              0x1FFF0000
-#define VML_VTOTAL_SHIFT             16
-#define VML_VTOTAL_VAL               8192
-#define VML_VACTIVE_MASK             0x000007FF
-#define VML_VACTIVE_SHIFT            0
-#define VML_VACTIVE_VAL              4096
-
-/* Pipe A Vertical Blank register */
-#define VML_VBLANK_A                 0x00060010
-#define VML_VBLANK_END_MASK          0x1FFF0000
-#define VML_VBLANK_END_SHIFT         16
-#define VML_VBLANK_END_VAL           8192
-#define VML_VBLANK_START_MASK        0x00001FFF
-#define VML_VBLANK_START_SHIFT       0
-#define VML_VBLANK_START_VAL         8192
-
-/* Pipe A Vertical Sync register */
-#define VML_VSYNC_A                  0x00060014
-#define VML_VSYNC_END_MASK           0x1FFF0000
-#define VML_VSYNC_END_SHIFT          16
-#define VML_VSYNC_END_VAL            8192
-#define VML_VSYNC_START_MASK         0x00001FFF
-#define VML_VSYNC_START_SHIFT        0
-#define VML_VSYNC_START_VAL          8192
-
-/* Pipe A Source Image size (minus one - equal to active size)
- * Programmable while pipe is enabled.
- */
-#define VML_PIPEASRC                 0x0006001C
-#define VML_PIPEASRC_HMASK           0x0FFF0000
-#define VML_PIPEASRC_HSHIFT          16
-#define VML_PIPEASRC_VMASK           0x00000FFF
-#define VML_PIPEASRC_VSHIFT          0
-
-/* Pipe A Border Color Pattern register (10 bit color) */
-#define VML_BCLRPAT_A                0x00060020
-
-/* Pipe A Canvas Color register  (10 bit color) */
-#define VML_CANVSCLR_A               0x00060024
-
-/* Pipe A Configuration register */
-#define VML_PIPEACONF                0x00070008
-#define VML_PIPE_BASE                0x00000000
-#define VML_PIPE_ENABLE              0x80000000
-#define VML_PIPE_FORCE_BORDER        0x02000000
-#define VML_PIPE_PLANES_OFF          0x00080000
-#define VML_PIPE_ARGB_OUTPUT_MODE    0x00040000
-
-/* Pipe A FIFO setting */
-#define VML_DSPARB                   0x00070030
-#define VML_FIFO_DEFAULT             0x00001D9C
-
-/* MDVO rcomp status & pads control register */
-#define VML_RCOMPSTAT                0x00070048
-#define VML_MDVO_VDC_I_RCOMP         0x80000000
-#define VML_MDVO_POWERSAVE_OFF       0x00000008
-#define VML_MDVO_PAD_ENABLE          0x00000004
-#define VML_MDVO_PULLDOWN_ENABLE     0x00000001
-
-struct vml_par {
-	struct pci_dev *vdc;
-	u64 vdc_mem_base;
-	u64 vdc_mem_size;
-	char __iomem *vdc_mem;
-
-	struct pci_dev *gpu;
-	u64 gpu_mem_base;
-	u64 gpu_mem_size;
-	char __iomem *gpu_mem;
-
-	atomic_t refcount;
-};
-
-struct vram_area {
-	unsigned long logical;
-	unsigned long phys;
-	unsigned long size;
-	unsigned order;
-};
-
-struct vml_info {
-	struct fb_info info;
-	struct vml_par *par;
-	struct list_head head;
-	struct vram_area vram[VML_VRAM_AREAS];
-	u64 vram_start;
-	u64 vram_contig_size;
-	u32 num_areas;
-	void __iomem *vram_logical;
-	u32 pseudo_palette[16];
-	u32 stride;
-	u32 bytes_per_pixel;
-	atomic_t vmas;
-	int cur_blank_mode;
-	int pipe_disabled;
-};
-
-/*
- * Subsystem
- */
-
-struct vml_sys {
-	char *name;
-
-	/*
-	 * Save / Restore;
-	 */
-
-	int (*save) (struct vml_sys * sys);
-	int (*restore) (struct vml_sys * sys);
-
-	/*
-	 * PLL programming;
-	 */
-
-	int (*set_clock) (struct vml_sys * sys, int clock);
-	int (*nearest_clock) (const struct vml_sys * sys, int clock);
-};
-
-extern int vmlfb_register_subsys(struct vml_sys *sys);
-extern void vmlfb_unregister_subsys(struct vml_sys *sys);
-
-#define VML_READ32(_par, _offset) \
-	(ioread32((_par)->vdc_mem + (_offset)))
-#define VML_WRITE32(_par, _offset, _value)				\
-	iowrite32(_value, (_par)->vdc_mem + (_offset))
-
-#endif
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
deleted file mode 100644
index 6170e7f58640..000000000000
--- a/drivers/video/vesafb.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * framebuffer driver for VBE 2.0 compliant graphic boards
- *
- * switching to graphics mode happens at boot time (while
- * running in real mode, see arch/i386/boot/video.S).
- *
- * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/screen_info.h>
-
-#include <video/vga.h>
-#include <asm/io.h>
-#include <asm/mtrr.h>
-
-#define dac_reg	(0x3c8)
-#define dac_val	(0x3c9)
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo vesafb_defined = {
-	.activate	= FB_ACTIVATE_NOW,
-	.height		= -1,
-	.width		= -1,
-	.right_margin	= 32,
-	.upper_margin	= 16,
-	.lower_margin	= 4,
-	.vsync_len	= 4,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo vesafb_fix = {
-	.id	= "VESA VGA",
-	.type	= FB_TYPE_PACKED_PIXELS,
-	.accel	= FB_ACCEL_NONE,
-};
-
-static int   inverse    __read_mostly;
-static int   mtrr       __read_mostly;		/* disable mtrr */
-static int   vram_remap;			/* Set amount of memory to be used */
-static int   vram_total;			/* Set total amount of memory */
-static int   pmi_setpal __read_mostly = 1;	/* pmi for palette changes ??? */
-static int   ypan       __read_mostly;		/* 0..nothing, 1..ypan, 2..ywrap */
-static void  (*pmi_start)(void) __read_mostly;
-static void  (*pmi_pal)  (void) __read_mostly;
-static int   depth      __read_mostly;
-static int   vga_compat __read_mostly;
-/* --------------------------------------------------------------------- */
-
-static int vesafb_pan_display(struct fb_var_screeninfo *var,
-                              struct fb_info *info)
-{
-#ifdef __i386__
-	int offset;
-
-	offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
-
-        __asm__ __volatile__(
-                "call *(%%edi)"
-                : /* no return value */
-                : "a" (0x4f07),         /* EAX */
-                  "b" (0),              /* EBX */
-                  "c" (offset),         /* ECX */
-                  "d" (offset >> 16),   /* EDX */
-                  "D" (&pmi_start));    /* EDI */
-#endif
-	return 0;
-}
-
-static int vesa_setpalette(int regno, unsigned red, unsigned green,
-			    unsigned blue)
-{
-	int shift = 16 - depth;
-	int err = -EINVAL;
-
-/*
- * Try VGA registers first...
- */
-	if (vga_compat) {
-		outb_p(regno,       dac_reg);
-		outb_p(red   >> shift, dac_val);
-		outb_p(green >> shift, dac_val);
-		outb_p(blue  >> shift, dac_val);
-		err = 0;
-	}
-
-#ifdef __i386__
-/*
- * Fallback to the PMI....
- */
-	if (err && pmi_setpal) {
-		struct { u_char blue, green, red, pad; } entry;
-
-		entry.red   = red   >> shift;
-		entry.green = green >> shift;
-		entry.blue  = blue  >> shift;
-		entry.pad   = 0;
-	        __asm__ __volatile__(
-                "call *(%%esi)"
-                : /* no return value */
-                : "a" (0x4f09),         /* EAX */
-                  "b" (0),              /* EBX */
-                  "c" (1),              /* ECX */
-                  "d" (regno),          /* EDX */
-                  "D" (&entry),         /* EDI */
-                  "S" (&pmi_pal));      /* ESI */
-		err = 0;
-	}
-#endif
-
-	return err;
-}
-
-static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			    unsigned blue, unsigned transp,
-			    struct fb_info *info)
-{
-	int err = 0;
-
-	/*
-	 *  Set a single color register. The values supplied are
-	 *  already rounded down to the hardware's capabilities
-	 *  (according to the entries in the `var' structure). Return
-	 *  != 0 for invalid regno.
-	 */
-	
-	if (regno >= info->cmap.len)
-		return 1;
-
-	if (info->var.bits_per_pixel == 8)
-		err = vesa_setpalette(regno,red,green,blue);
-	else if (regno < 16) {
-		switch (info->var.bits_per_pixel) {
-		case 16:
-			if (info->var.red.offset == 10) {
-				/* 1:5:5:5 */
-				((u32*) (info->pseudo_palette))[regno] =
-					((red   & 0xf800) >>  1) |
-					((green & 0xf800) >>  6) |
-					((blue  & 0xf800) >> 11);
-			} else {
-				/* 0:5:6:5 */
-				((u32*) (info->pseudo_palette))[regno] =
-					((red   & 0xf800)      ) |
-					((green & 0xfc00) >>  5) |
-					((blue  & 0xf800) >> 11);
-			}
-			break;
-		case 24:
-		case 32:
-			red   >>= 8;
-			green >>= 8;
-			blue  >>= 8;
-			((u32 *)(info->pseudo_palette))[regno] =
-				(red   << info->var.red.offset)   |
-				(green << info->var.green.offset) |
-				(blue  << info->var.blue.offset);
-			break;
-		}
-	}
-
-	return err;
-}
-
-static void vesafb_destroy(struct fb_info *info)
-{
-	fb_dealloc_cmap(&info->cmap);
-	if (info->screen_base)
-		iounmap(info->screen_base);
-	release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
-}
-
-static struct fb_ops vesafb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_destroy     = vesafb_destroy,
-	.fb_setcolreg	= vesafb_setcolreg,
-	.fb_pan_display	= vesafb_pan_display,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
-
-static int vesafb_setup(char *options)
-{
-	char *this_opt;
-	
-	if (!options || !*options)
-		return 0;
-	
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt) continue;
-		
-		if (! strcmp(this_opt, "inverse"))
-			inverse=1;
-		else if (! strcmp(this_opt, "redraw"))
-			ypan=0;
-		else if (! strcmp(this_opt, "ypan"))
-			ypan=1;
-		else if (! strcmp(this_opt, "ywrap"))
-			ypan=2;
-		else if (! strcmp(this_opt, "vgapal"))
-			pmi_setpal=0;
-		else if (! strcmp(this_opt, "pmipal"))
-			pmi_setpal=1;
-		else if (! strncmp(this_opt, "mtrr:", 5))
-			mtrr = simple_strtoul(this_opt+5, NULL, 0);
-		else if (! strcmp(this_opt, "nomtrr"))
-			mtrr=0;
-		else if (! strncmp(this_opt, "vtotal:", 7))
-			vram_total = simple_strtoul(this_opt+7, NULL, 0);
-		else if (! strncmp(this_opt, "vremap:", 7))
-			vram_remap = simple_strtoul(this_opt+7, NULL, 0);
-	}
-	return 0;
-}
-
-static int vesafb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	int i, err;
-	unsigned int size_vmode;
-	unsigned int size_remap;
-	unsigned int size_total;
-	char *option = NULL;
-
-	/* ignore error return of fb_get_options */
-	fb_get_options("vesafb", &option);
-	vesafb_setup(option);
-
-	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
-		return -ENODEV;
-
-	vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
-	vesafb_fix.smem_start = screen_info.lfb_base;
-	vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
-	if (15 == vesafb_defined.bits_per_pixel)
-		vesafb_defined.bits_per_pixel = 16;
-	vesafb_defined.xres = screen_info.lfb_width;
-	vesafb_defined.yres = screen_info.lfb_height;
-	vesafb_fix.line_length = screen_info.lfb_linelength;
-	vesafb_fix.visual   = (vesafb_defined.bits_per_pixel == 8) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-
-	/*   size_vmode -- that is the amount of memory needed for the
-	 *                 used video mode, i.e. the minimum amount of
-	 *                 memory we need. */
-	size_vmode = vesafb_defined.yres * vesafb_fix.line_length;
-
-	/*   size_total -- all video memory we have. Used for mtrr
-	 *                 entries, resource allocation and bounds
-	 *                 checking. */
-	size_total = screen_info.lfb_size * 65536;
-	if (vram_total)
-		size_total = vram_total * 1024 * 1024;
-	if (size_total < size_vmode)
-		size_total = size_vmode;
-
-	/*   size_remap -- the amount of video memory we are going to
-	 *                 use for vesafb.  With modern cards it is no
-	 *                 option to simply use size_total as that
-	 *                 wastes plenty of kernel address space. */
-	size_remap  = size_vmode * 2;
-	if (vram_remap)
-		size_remap = vram_remap * 1024 * 1024;
-	if (size_remap < size_vmode)
-		size_remap = size_vmode;
-	if (size_remap > size_total)
-		size_remap = size_total;
-	vesafb_fix.smem_len = size_remap;
-
-#ifndef __i386__
-	screen_info.vesapm_seg = 0;
-#endif
-
-	if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
-		printk(KERN_WARNING
-		       "vesafb: cannot reserve video memory at 0x%lx\n",
-			vesafb_fix.smem_start);
-		/* We cannot make this fatal. Sometimes this comes from magic
-		   spaces our resource handlers simply don't know about */
-	}
-
-	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
-	if (!info) {
-		release_mem_region(vesafb_fix.smem_start, size_total);
-		return -ENOMEM;
-	}
-	platform_set_drvdata(dev, info);
-	info->pseudo_palette = info->par;
-	info->par = NULL;
-
-	/* set vesafb aperture size for generic probing */
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures) {
-		err = -ENOMEM;
-		goto err;
-	}
-	info->apertures->ranges[0].base = screen_info.lfb_base;
-	info->apertures->ranges[0].size = size_total;
-
-	printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
-	       vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
-
-	if (screen_info.vesapm_seg) {
-		printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
-		       screen_info.vesapm_seg,screen_info.vesapm_off);
-	}
-
-	if (screen_info.vesapm_seg < 0xc000)
-		ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
-
-	if (ypan || pmi_setpal) {
-		unsigned short *pmi_base;
-		pmi_base  = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
-		pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
-		pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
-		printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
-		if (pmi_base[3]) {
-			printk(KERN_INFO "vesafb: pmi: ports = ");
-				for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
-					printk("%x ",pmi_base[i]);
-			printk("\n");
-			if (pmi_base[i] != 0xffff) {
-				/*
-				 * memory areas not supported (yet?)
-				 *
-				 * Rules are: we have to set up a descriptor for the requested
-				 * memory area and pass it in the ES register to the BIOS function.
-				 */
-				printk(KERN_INFO "vesafb: can't handle memory requests, pmi disabled\n");
-				ypan = pmi_setpal = 0;
-			}
-		}
-	}
-
-	if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) {
-		printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n"
-		                    "        colors may be incorrect\n");
-		vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-	}
-
-	vesafb_defined.xres_virtual = vesafb_defined.xres;
-	vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
-	if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
-		printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
-		       (ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
-	} else {
-		printk(KERN_INFO "vesafb: scrolling: redraw\n");
-		vesafb_defined.yres_virtual = vesafb_defined.yres;
-		ypan = 0;
-	}
-
-	/* some dummy values for timing to make fbset happy */
-	vesafb_defined.pixclock     = 10000000 / vesafb_defined.xres * 1000 / vesafb_defined.yres;
-	vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
-	vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
-	
-	vesafb_defined.red.offset    = screen_info.red_pos;
-	vesafb_defined.red.length    = screen_info.red_size;
-	vesafb_defined.green.offset  = screen_info.green_pos;
-	vesafb_defined.green.length  = screen_info.green_size;
-	vesafb_defined.blue.offset   = screen_info.blue_pos;
-	vesafb_defined.blue.length   = screen_info.blue_size;
-	vesafb_defined.transp.offset = screen_info.rsvd_pos;
-	vesafb_defined.transp.length = screen_info.rsvd_size;
-
-	if (vesafb_defined.bits_per_pixel <= 8) {
-		depth = vesafb_defined.green.length;
-		vesafb_defined.red.length =
-		vesafb_defined.green.length =
-		vesafb_defined.blue.length =
-		vesafb_defined.bits_per_pixel;
-	}
-
-	printk(KERN_INFO "vesafb: %s: "
-	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
-	       (vesafb_defined.bits_per_pixel > 8) ?
-	       "Truecolor" : (vga_compat || pmi_setpal) ?
-	       "Pseudocolor" : "Static Pseudocolor",
-	       screen_info.rsvd_size,
-	       screen_info.red_size,
-	       screen_info.green_size,
-	       screen_info.blue_size,
-	       screen_info.rsvd_pos,
-	       screen_info.red_pos,
-	       screen_info.green_pos,
-	       screen_info.blue_pos);
-
-	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
-	vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
-
-	/* request failure does not faze us, as vgacon probably has this
-	 * region already (FIXME) */
-	request_region(0x3c0, 32, "vesafb");
-
-#ifdef CONFIG_MTRR
-	if (mtrr) {
-		unsigned int temp_size = size_total;
-		unsigned int type = 0;
-
-		switch (mtrr) {
-		case 1:
-			type = MTRR_TYPE_UNCACHABLE;
-			break;
-		case 2:
-			type = MTRR_TYPE_WRBACK;
-			break;
-		case 3:
-			type = MTRR_TYPE_WRCOMB;
-			break;
-		case 4:
-			type = MTRR_TYPE_WRTHROUGH;
-			break;
-		default:
-			type = 0;
-			break;
-		}
-
-		if (type) {
-			int rc;
-
-			/* Find the largest power-of-two */
-			temp_size = roundup_pow_of_two(temp_size);
-
-			/* Try and find a power of two to add */
-			do {
-				rc = mtrr_add(vesafb_fix.smem_start, temp_size,
-					      type, 1);
-				temp_size >>= 1;
-			} while (temp_size >= PAGE_SIZE && rc == -EINVAL);
-		}
-	}
-#endif
-	
-	switch (mtrr) {
-	case 1: /* uncachable */
-		info->screen_base = ioremap_nocache(vesafb_fix.smem_start, vesafb_fix.smem_len);
-		break;
-	case 2: /* write-back */
-		info->screen_base = ioremap_cache(vesafb_fix.smem_start, vesafb_fix.smem_len);
-		break;
-	case 3: /* write-combining */
-		info->screen_base = ioremap_wc(vesafb_fix.smem_start, vesafb_fix.smem_len);
-		break;
-	case 4: /* write-through */
-	default:
-		info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
-		break;
-	}
-	if (!info->screen_base) {
-		printk(KERN_ERR
-		       "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
-			vesafb_fix.smem_len, vesafb_fix.smem_start);
-		err = -EIO;
-		goto err;
-	}
-
-	printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, "
-	       "using %dk, total %dk\n",
-	       vesafb_fix.smem_start, info->screen_base,
-	       size_remap/1024, size_total/1024);
-
-	info->fbops = &vesafb_ops;
-	info->var = vesafb_defined;
-	info->fix = vesafb_fix;
-	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE |
-		(ypan ? FBINFO_HWACCEL_YPAN : 0);
-
-	if (!ypan)
-		info->fbops->fb_pan_display = NULL;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		err = -ENOMEM;
-		goto err;
-	}
-	if (register_framebuffer(info)<0) {
-		err = -EINVAL;
-		fb_dealloc_cmap(&info->cmap);
-		goto err;
-	}
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	return 0;
-err:
-	if (info->screen_base)
-		iounmap(info->screen_base);
-	framebuffer_release(info);
-	release_mem_region(vesafb_fix.smem_start, size_total);
-	return err;
-}
-
-static int vesafb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-
-	unregister_framebuffer(info);
-	framebuffer_release(info);
-
-	return 0;
-}
-
-static struct platform_driver vesafb_driver = {
-	.driver = {
-		.name = "vesa-framebuffer",
-		.owner = THIS_MODULE,
-	},
-	.probe = vesafb_probe,
-	.remove = vesafb_remove,
-};
-
-module_platform_driver(vesafb_driver);
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
deleted file mode 100644
index 70a897b1e458..000000000000
--- a/drivers/video/vfb.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- *  linux/drivers/video/vfb.c -- Virtual frame buffer device
- *
- *      Copyright (C) 2002 James Simmons
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <linux/fb.h>
-#include <linux/init.h>
-
-    /*
-     *  RAM we reserve for the frame buffer. This defines the maximum screen
-     *  size
-     *
-     *  The default can be overridden if the driver is compiled as a module
-     */
-
-#define VIDEOMEMSIZE	(1*1024*1024)	/* 1 MB */
-
-static void *videomemory;
-static u_long videomemorysize = VIDEOMEMSIZE;
-module_param(videomemorysize, ulong, 0);
-
-/**********************************************************************
- *
- * Memory management
- *
- **********************************************************************/
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-static struct fb_var_screeninfo vfb_default = {
-	.xres =		640,
-	.yres =		480,
-	.xres_virtual =	640,
-	.yres_virtual =	480,
-	.bits_per_pixel = 8,
-	.red =		{ 0, 8, 0 },
-      	.green =	{ 0, 8, 0 },
-      	.blue =		{ 0, 8, 0 },
-      	.activate =	FB_ACTIVATE_TEST,
-      	.height =	-1,
-      	.width =	-1,
-      	.pixclock =	20000,
-      	.left_margin =	64,
-      	.right_margin =	64,
-      	.upper_margin =	32,
-      	.lower_margin =	32,
-      	.hsync_len =	64,
-      	.vsync_len =	2,
-      	.vmode =	FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo vfb_fix = {
-	.id =		"Virtual FB",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep =	1,
-	.ypanstep =	1,
-	.ywrapstep =	1,
-	.accel =	FB_ACCEL_NONE,
-};
-
-static bool vfb_enable __initdata = 0;	/* disabled by default */
-module_param(vfb_enable, bool, 0);
-
-static int vfb_check_var(struct fb_var_screeninfo *var,
-			 struct fb_info *info);
-static int vfb_set_par(struct fb_info *info);
-static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			 u_int transp, struct fb_info *info);
-static int vfb_pan_display(struct fb_var_screeninfo *var,
-			   struct fb_info *info);
-static int vfb_mmap(struct fb_info *info,
-		    struct vm_area_struct *vma);
-
-static struct fb_ops vfb_ops = {
-	.fb_read        = fb_sys_read,
-	.fb_write       = fb_sys_write,
-	.fb_check_var	= vfb_check_var,
-	.fb_set_par	= vfb_set_par,
-	.fb_setcolreg	= vfb_setcolreg,
-	.fb_pan_display	= vfb_pan_display,
-	.fb_fillrect	= sys_fillrect,
-	.fb_copyarea	= sys_copyarea,
-	.fb_imageblit	= sys_imageblit,
-	.fb_mmap	= vfb_mmap,
-};
-
-    /*
-     *  Internal routines
-     */
-
-static u_long get_line_length(int xres_virtual, int bpp)
-{
-	u_long length;
-
-	length = xres_virtual * bpp;
-	length = (length + 31) & ~31;
-	length >>= 3;
-	return (length);
-}
-
-    /*
-     *  Setting the video mode has been split into two parts.
-     *  First part, xxxfb_check_var, must not write anything
-     *  to hardware, it should only verify and adjust var.
-     *  This means it doesn't alter par but it does use hardware
-     *  data from it to check this var. 
-     */
-
-static int vfb_check_var(struct fb_var_screeninfo *var,
-			 struct fb_info *info)
-{
-	u_long line_length;
-
-	/*
-	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
-	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
-	 */
-
-	if (var->vmode & FB_VMODE_CONUPDATE) {
-		var->vmode |= FB_VMODE_YWRAP;
-		var->xoffset = info->var.xoffset;
-		var->yoffset = info->var.yoffset;
-	}
-
-	/*
-	 *  Some very basic checks
-	 */
-	if (!var->xres)
-		var->xres = 1;
-	if (!var->yres)
-		var->yres = 1;
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-	if (var->bits_per_pixel <= 1)
-		var->bits_per_pixel = 1;
-	else if (var->bits_per_pixel <= 8)
-		var->bits_per_pixel = 8;
-	else if (var->bits_per_pixel <= 16)
-		var->bits_per_pixel = 16;
-	else if (var->bits_per_pixel <= 24)
-		var->bits_per_pixel = 24;
-	else if (var->bits_per_pixel <= 32)
-		var->bits_per_pixel = 32;
-	else
-		return -EINVAL;
-
-	if (var->xres_virtual < var->xoffset + var->xres)
-		var->xres_virtual = var->xoffset + var->xres;
-	if (var->yres_virtual < var->yoffset + var->yres)
-		var->yres_virtual = var->yoffset + var->yres;
-
-	/*
-	 *  Memory limit
-	 */
-	line_length =
-	    get_line_length(var->xres_virtual, var->bits_per_pixel);
-	if (line_length * var->yres_virtual > videomemorysize)
-		return -ENOMEM;
-
-	/*
-	 * Now that we checked it we alter var. The reason being is that the video
-	 * mode passed in might not work but slight changes to it might make it 
-	 * work. This way we let the user know what is acceptable.
-	 */
-	switch (var->bits_per_pixel) {
-	case 1:
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:		/* RGBA 5551 */
-		if (var->transp.length) {
-			var->red.offset = 0;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 5;
-			var->blue.offset = 10;
-			var->blue.length = 5;
-			var->transp.offset = 15;
-			var->transp.length = 1;
-		} else {	/* RGB 565 */
-			var->red.offset = 0;
-			var->red.length = 5;
-			var->green.offset = 5;
-			var->green.length = 6;
-			var->blue.offset = 11;
-			var->blue.length = 5;
-			var->transp.offset = 0;
-			var->transp.length = 0;
-		}
-		break;
-	case 24:		/* RGB 888 */
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 16;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 32:		/* RGBA 8888 */
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 16;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	}
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-
-	return 0;
-}
-
-/* This routine actually sets the video mode. It's in here where we
- * the hardware state info->par and fix which can be affected by the 
- * change in par. For this driver it doesn't do much. 
- */
-static int vfb_set_par(struct fb_info *info)
-{
-	info->fix.line_length = get_line_length(info->var.xres_virtual,
-						info->var.bits_per_pixel);
-	return 0;
-}
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			 u_int transp, struct fb_info *info)
-{
-	if (regno >= 256)	/* no. of hw registers */
-		return 1;
-	/*
-	 * Program hardware... do anything you want with transp
-	 */
-
-	/* grayscale works only partially under directcolor */
-	if (info->var.grayscale) {
-		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue =
-		    (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	/* Directcolor:
-	 *   var->{color}.offset contains start of bitfield
-	 *   var->{color}.length contains length of bitfield
-	 *   {hardwarespecific} contains width of RAMDAC
-	 *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
-	 *   RAMDAC[X] is programmed to (red, green, blue)
-	 *
-	 * Pseudocolor:
-	 *    var->{color}.offset is 0 unless the palette index takes less than
-	 *                        bits_per_pixel bits and is stored in the upper
-	 *                        bits of the pixel value
-	 *    var->{color}.length is set so that 1 << length is the number of available
-	 *                        palette entries
-	 *    cmap is not used
-	 *    RAMDAC[X] is programmed to (red, green, blue)
-	 *
-	 * Truecolor:
-	 *    does not use DAC. Usually 3 are present.
-	 *    var->{color}.offset contains start of bitfield
-	 *    var->{color}.length contains length of bitfield
-	 *    cmap is programmed to (red << red.offset) | (green << green.offset) |
-	 *                      (blue << blue.offset) | (transp << transp.offset)
-	 *    RAMDAC does not exist
-	 */
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		red = CNVT_TOHW(red, info->var.red.length);
-		green = CNVT_TOHW(green, info->var.green.length);
-		blue = CNVT_TOHW(blue, info->var.blue.length);
-		transp = CNVT_TOHW(transp, info->var.transp.length);
-		break;
-	case FB_VISUAL_DIRECTCOLOR:
-		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
-		green = CNVT_TOHW(green, 8);
-		blue = CNVT_TOHW(blue, 8);
-		/* hey, there is bug in transp handling... */
-		transp = CNVT_TOHW(transp, 8);
-		break;
-	}
-#undef CNVT_TOHW
-	/* Truecolor has hardware independent palette */
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-		u32 v;
-
-		if (regno >= 16)
-			return 1;
-
-		v = (red << info->var.red.offset) |
-		    (green << info->var.green.offset) |
-		    (blue << info->var.blue.offset) |
-		    (transp << info->var.transp.offset);
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			break;
-		case 16:
-			((u32 *) (info->pseudo_palette))[regno] = v;
-			break;
-		case 24:
-		case 32:
-			((u32 *) (info->pseudo_palette))[regno] = v;
-			break;
-		}
-		return 0;
-	}
-	return 0;
-}
-
-    /*
-     *  Pan or Wrap the Display
-     *
-     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-     */
-
-static int vfb_pan_display(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
-{
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset >= info->var.yres_virtual ||
-		    var->xoffset)
-			return -EINVAL;
-	} else {
-		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
-		    var->yoffset + info->var.yres > info->var.yres_virtual)
-			return -EINVAL;
-	}
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-	return 0;
-}
-
-    /*
-     *  Most drivers don't need their own mmap function 
-     */
-
-static int vfb_mmap(struct fb_info *info,
-		    struct vm_area_struct *vma)
-{
-	unsigned long start = vma->vm_start;
-	unsigned long size = vma->vm_end - vma->vm_start;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	unsigned long page, pos;
-
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-	if (size > info->fix.smem_len)
-		return -EINVAL;
-	if (offset > info->fix.smem_len - size)
-		return -EINVAL;
-
-	pos = (unsigned long)info->fix.smem_start + offset;
-
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-
-}
-
-#ifndef MODULE
-/*
- * The virtual framebuffer driver is only enabled if explicitly
- * requested by passing 'video=vfb:' (or any actual options).
- */
-static int __init vfb_setup(char *options)
-{
-	char *this_opt;
-
-	vfb_enable = 0;
-
-	if (!options)
-		return 1;
-
-	vfb_enable = 1;
-
-	if (!*options)
-		return 1;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		/* Test disable for backwards compatibility */
-		if (!strcmp(this_opt, "disable"))
-			vfb_enable = 0;
-	}
-	return 1;
-}
-#endif  /*  MODULE  */
-
-    /*
-     *  Initialisation
-     */
-
-static int vfb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	int retval = -ENOMEM;
-
-	/*
-	 * For real video cards we use ioremap.
-	 */
-	if (!(videomemory = rvmalloc(videomemorysize)))
-		return retval;
-
-	/*
-	 * VFB must clear memory to prevent kernel info
-	 * leakage into userspace
-	 * VGA-based drivers MUST NOT clear memory if
-	 * they want to be able to take over vgacon
-	 */
-	memset(videomemory, 0, videomemorysize);
-
-	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
-	if (!info)
-		goto err;
-
-	info->screen_base = (char __iomem *)videomemory;
-	info->fbops = &vfb_ops;
-
-	retval = fb_find_mode(&info->var, info, NULL,
-			      NULL, 0, NULL, 8);
-
-	if (!retval || (retval == 4))
-		info->var = vfb_default;
-	vfb_fix.smem_start = (unsigned long) videomemory;
-	vfb_fix.smem_len = videomemorysize;
-	info->fix = vfb_fix;
-	info->pseudo_palette = info->par;
-	info->par = NULL;
-	info->flags = FBINFO_FLAG_DEFAULT;
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0)
-		goto err1;
-
-	retval = register_framebuffer(info);
-	if (retval < 0)
-		goto err2;
-	platform_set_drvdata(dev, info);
-
-	fb_info(info, "Virtual frame buffer device, using %ldK of video memory\n",
-		videomemorysize >> 10);
-	return 0;
-err2:
-	fb_dealloc_cmap(&info->cmap);
-err1:
-	framebuffer_release(info);
-err:
-	rvfree(videomemory, videomemorysize);
-	return retval;
-}
-
-static int vfb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info) {
-		unregister_framebuffer(info);
-		rvfree(videomemory, videomemorysize);
-		fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	return 0;
-}
-
-static struct platform_driver vfb_driver = {
-	.probe	= vfb_probe,
-	.remove = vfb_remove,
-	.driver = {
-		.name	= "vfb",
-	},
-};
-
-static struct platform_device *vfb_device;
-
-static int __init vfb_init(void)
-{
-	int ret = 0;
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("vfb", &option))
-		return -ENODEV;
-	vfb_setup(option);
-#endif
-
-	if (!vfb_enable)
-		return -ENXIO;
-
-	ret = platform_driver_register(&vfb_driver);
-
-	if (!ret) {
-		vfb_device = platform_device_alloc("vfb", 0);
-
-		if (vfb_device)
-			ret = platform_device_add(vfb_device);
-		else
-			ret = -ENOMEM;
-
-		if (ret) {
-			platform_device_put(vfb_device);
-			platform_driver_unregister(&vfb_driver);
-		}
-	}
-
-	return ret;
-}
-
-module_init(vfb_init);
-
-#ifdef MODULE
-static void __exit vfb_exit(void)
-{
-	platform_device_unregister(vfb_device);
-	platform_driver_unregister(&vfb_driver);
-}
-
-module_exit(vfb_exit);
-
-MODULE_LICENSE("GPL");
-#endif				/* MODULE */
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
deleted file mode 100644
index 283d335a759f..000000000000
--- a/drivers/video/vga16fb.c
+++ /dev/null
@@ -1,1464 +0,0 @@
-/*
- * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver
- * 
- * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
- * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
- * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.  
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/screen_info.h>
-
-#include <asm/io.h>
-#include <video/vga.h>
-
-#define VGA_FB_PHYS 0xA0000
-#define VGA_FB_PHYS_LEN 65536
-
-#define MODE_SKIP4	1
-#define MODE_8BPP	2
-#define MODE_CFB	4
-#define MODE_TEXT	8
-
-/* --------------------------------------------------------------------- */
-
-/*
- * card parameters
- */
-
-struct vga16fb_par {
-	/* structure holding original VGA register settings when the
-           screen is blanked */
-	struct {
-		unsigned char	SeqCtrlIndex;	  /* Sequencer Index reg.   */
-		unsigned char	CrtCtrlIndex;	  /* CRT-Contr. Index reg.  */
-		unsigned char	CrtMiscIO;	  /* Miscellaneous register */
-		unsigned char	HorizontalTotal;  /* CRT-Controller:00h */
-		unsigned char	HorizDisplayEnd;  /* CRT-Controller:01h */
-		unsigned char	StartHorizRetrace;/* CRT-Controller:04h */
-		unsigned char	EndHorizRetrace;  /* CRT-Controller:05h */
-		unsigned char	Overflow;	  /* CRT-Controller:07h */
-		unsigned char	StartVertRetrace; /* CRT-Controller:10h */
-		unsigned char	EndVertRetrace;	  /* CRT-Controller:11h */
-		unsigned char	ModeControl;	  /* CRT-Controller:17h */
-		unsigned char	ClockingMode;	  /* Seq-Controller:01h */
-	} vga_state;
-	struct vgastate state;
-	unsigned int ref_count;
-	int palette_blanked, vesa_blanked, mode, isVGA;
-	u8 misc, pel_msk, vss, clkdiv;
-	u8 crtc[VGA_CRT_C];
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo vga16fb_defined = {
-	.xres		= 640,
-	.yres		= 480,
-	.xres_virtual	= 640,
-	.yres_virtual	= 480,
-	.bits_per_pixel	= 4,	
-	.activate	= FB_ACTIVATE_TEST,
-	.height		= -1,
-	.width		= -1,
-	.pixclock	= 39721,
-	.left_margin	= 48,
-	.right_margin	= 16,
-	.upper_margin	= 33,
-	.lower_margin	= 10,
-	.hsync_len 	= 96,
-	.vsync_len	= 2,
-	.vmode		= FB_VMODE_NONINTERLACED,
-};
-
-/* name should not depend on EGA/VGA */
-static struct fb_fix_screeninfo vga16fb_fix = {
-	.id		= "VGA16 VGA",
-	.smem_start	= VGA_FB_PHYS,
-	.smem_len	= VGA_FB_PHYS_LEN,
-	.type		= FB_TYPE_VGA_PLANES,
-	.type_aux	= FB_AUX_VGA_PLANES_VGA4,
-	.visual		= FB_VISUAL_PSEUDOCOLOR,
-	.xpanstep	= 8,
-	.ypanstep	= 1,
-	.line_length	= 640 / 8,
-	.accel		= FB_ACCEL_NONE
-};
-
-/* The VGA's weird architecture often requires that we read a byte and
-   write a byte to the same location.  It doesn't matter *what* byte
-   we write, however.  This is because all the action goes on behind
-   the scenes in the VGA's 32-bit latch register, and reading and writing
-   video memory just invokes latch behavior.
-
-   To avoid race conditions (is this necessary?), reading and writing
-   the memory byte should be done with a single instruction.  One
-   suitable instruction is the x86 bitwise OR.  The following
-   read-modify-write routine should optimize to one such bitwise
-   OR. */
-static inline void rmw(volatile char __iomem *p)
-{
-	readb(p);
-	writeb(1, p);
-}
-
-/* Set the Graphics Mode Register, and return its previous value.
-   Bits 0-1 are write mode, bit 3 is read mode. */
-static inline int setmode(int mode)
-{
-	int oldmode;
-	
-	oldmode = vga_io_rgfx(VGA_GFX_MODE);
-	vga_io_w(VGA_GFX_D, mode);
-	return oldmode;
-}
-
-/* Select the Bit Mask Register and return its value. */
-static inline int selectmask(void)
-{
-	return vga_io_rgfx(VGA_GFX_BIT_MASK);
-}
-
-/* Set the value of the Bit Mask Register.  It must already have been
-   selected with selectmask(). */
-static inline void setmask(int mask)
-{
-	vga_io_w(VGA_GFX_D, mask);
-}
-
-/* Set the Data Rotate Register and return its old value. 
-   Bits 0-2 are rotate count, bits 3-4 are logical operation
-   (0=NOP, 1=AND, 2=OR, 3=XOR). */
-static inline int setop(int op)
-{
-	int oldop;
-	
-	oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
-	vga_io_w(VGA_GFX_D, op);
-	return oldop;
-}
-
-/* Set the Enable Set/Reset Register and return its old value.  
-   The code here always uses value 0xf for this register. */
-static inline int setsr(int sr)
-{
-	int oldsr;
-
-	oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
-	vga_io_w(VGA_GFX_D, sr);
-	return oldsr;
-}
-
-/* Set the Set/Reset Register and return its old value. */
-static inline int setcolor(int color)
-{
-	int oldcolor;
-
-	oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
-	vga_io_w(VGA_GFX_D, color);
-	return oldcolor;
-}
-
-/* Return the value in the Graphics Address Register. */
-static inline int getindex(void)
-{
-	return vga_io_r(VGA_GFX_I);
-}
-
-/* Set the value in the Graphics Address Register. */
-static inline void setindex(int index)
-{
-	vga_io_w(VGA_GFX_I, index);
-}
-
-static void vga16fb_pan_var(struct fb_info *info, 
-			    struct fb_var_screeninfo *var)
-{
-	struct vga16fb_par *par = info->par;
-	u32 xoffset, pos;
-
-	xoffset = var->xoffset;
-	if (info->var.bits_per_pixel == 8) {
-		pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2;
-	} else if (par->mode & MODE_TEXT) {
-		int fh = 16; // FIXME !!! font height. Fugde for now.
-		pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3;
-	} else {
-		if (info->var.nonstd)
-			xoffset--;
-		pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3;
-	}
-	vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8);
-	vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF);
-	/* if we support CFB4, then we must! support xoffset with pixel
-	 * granularity if someone supports xoffset in bit resolution */
-	vga_io_r(VGA_IS1_RC);		/* reset flip-flop */
-	vga_io_w(VGA_ATT_IW, VGA_ATC_PEL);
-	if (info->var.bits_per_pixel == 8)
-		vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1);
-	else
-		vga_io_w(VGA_ATT_IW, xoffset & 7);
-	vga_io_r(VGA_IS1_RC);
-	vga_io_w(VGA_ATT_IW, 0x20);
-}
-
-static void vga16fb_update_fix(struct fb_info *info)
-{
-	if (info->var.bits_per_pixel == 4) {
-		if (info->var.nonstd) {
-			info->fix.type = FB_TYPE_PACKED_PIXELS;
-			info->fix.line_length = info->var.xres_virtual / 2;
-		} else {
-			info->fix.type = FB_TYPE_VGA_PLANES;
-			info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4;
-			info->fix.line_length = info->var.xres_virtual / 8;
-		}
-	} else if (info->var.bits_per_pixel == 0) {
-		info->fix.type = FB_TYPE_TEXT;
-		info->fix.type_aux = FB_AUX_TEXT_CGA;
-		info->fix.line_length = info->var.xres_virtual / 4;
-	} else {	/* 8bpp */
-		if (info->var.nonstd) {
-			info->fix.type = FB_TYPE_VGA_PLANES;
-			info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8;
-			info->fix.line_length = info->var.xres_virtual / 4;
-		} else {
-			info->fix.type = FB_TYPE_PACKED_PIXELS;
-			info->fix.line_length = info->var.xres_virtual;
-		}
-	}
-}
-
-static void vga16fb_clock_chip(struct vga16fb_par *par,
-			       unsigned int pixclock,
-			       const struct fb_info *info,
-			       int mul, int div)
-{
-	static const struct {
-		u32 pixclock;
-		u8  misc;
-		u8  seq_clock_mode;
-	} *ptr, *best, vgaclocks[] = {
-		{ 79442 /* 12.587 */, 0x00, 0x08},
-		{ 70616 /* 14.161 */, 0x04, 0x08},
-		{ 39721 /* 25.175 */, 0x00, 0x00},
-		{ 35308 /* 28.322 */, 0x04, 0x00},
-		{     0 /* bad */,    0x00, 0x00}};
-	int err;
-
-	pixclock = (pixclock * mul) / div;
-	best = vgaclocks;
-	err = pixclock - best->pixclock;
-	if (err < 0) err = -err;
-	for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) {
-		int tmp;
-
-		tmp = pixclock - ptr->pixclock;
-		if (tmp < 0) tmp = -tmp;
-		if (tmp < err) {
-			err = tmp;
-			best = ptr;
-		}
-	}
-	par->misc |= best->misc;
-	par->clkdiv = best->seq_clock_mode;
-	pixclock = (best->pixclock * div) / mul;		
-}
-			       
-#define FAIL(X) return -EINVAL
-
-static int vga16fb_open(struct fb_info *info, int user)
-{
-	struct vga16fb_par *par = info->par;
-
-	if (!par->ref_count) {
-		memset(&par->state, 0, sizeof(struct vgastate));
-		par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
-			VGA_SAVE_CMAP;
-		save_vga(&par->state);
-	}
-	par->ref_count++;
-
-	return 0;
-}
-
-static int vga16fb_release(struct fb_info *info, int user)
-{
-	struct vga16fb_par *par = info->par;
-
-	if (!par->ref_count)
-		return -EINVAL;
-
-	if (par->ref_count == 1)
-		restore_vga(&par->state);
-	par->ref_count--;
-
-	return 0;
-}
-
-static int vga16fb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
-{
-	struct vga16fb_par *par = info->par;
-	u32 xres, right, hslen, left, xtotal;
-	u32 yres, lower, vslen, upper, ytotal;
-	u32 vxres, xoffset, vyres, yoffset;
-	u32 pos;
-	u8 r7, rMode;
-	int shift;
-	int mode;
-	u32 maxmem;
-
-	par->pel_msk = 0xFF;
-
-	if (var->bits_per_pixel == 4) {
-		if (var->nonstd) {
-			if (!par->isVGA)
-				return -EINVAL;
-			shift = 3;
-			mode = MODE_SKIP4 | MODE_CFB;
-			maxmem = 16384;
-			par->pel_msk = 0x0F;
-		} else {
-			shift = 3;
-			mode = 0;
-			maxmem = 65536;
-		}
-	} else if (var->bits_per_pixel == 8) {
-		if (!par->isVGA)
-			return -EINVAL;	/* no support on EGA */
-		shift = 2;
-		if (var->nonstd) {
-			mode = MODE_8BPP | MODE_CFB;
-			maxmem = 65536;
-		} else {
-			mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB;
-			maxmem = 16384;
-		}
-	} else
-		return -EINVAL;
-
-	xres = (var->xres + 7) & ~7;
-	vxres = (var->xres_virtual + 0xF) & ~0xF;
-	xoffset = (var->xoffset + 7) & ~7;
-	left = (var->left_margin + 7) & ~7;
-	right = (var->right_margin + 7) & ~7;
-	hslen = (var->hsync_len + 7) & ~7;
-
-	if (vxres < xres)
-		vxres = xres;
-	if (xres + xoffset > vxres)
-		xoffset = vxres - xres;
-
-	var->xres = xres;
-	var->right_margin = right;
-	var->hsync_len = hslen;
-	var->left_margin = left;
-	var->xres_virtual = vxres;
-	var->xoffset = xoffset;
-
-	xres >>= shift;
-	right >>= shift;
-	hslen >>= shift;
-	left >>= shift;
-	vxres >>= shift;
-	xtotal = xres + right + hslen + left;
-	if (xtotal >= 256)
-		FAIL("xtotal too big");
-	if (hslen > 32)
-		FAIL("hslen too big");
-	if (right + hslen + left > 64)
-		FAIL("hblank too big");
-	par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5;
-	par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1;
-	par->crtc[VGA_CRTC_H_DISP] = xres - 1;
-	pos = xres + right;
-	par->crtc[VGA_CRTC_H_SYNC_START] = pos;
-	pos += hslen;
-	par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F;
-	pos += left - 2; /* blank_end + 2 <= total + 5 */
-	par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
-	if (pos & 0x20)
-		par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80;
-
-	yres = var->yres;
-	lower = var->lower_margin;
-	vslen = var->vsync_len;
-	upper = var->upper_margin;
-	vyres = var->yres_virtual;
-	yoffset = var->yoffset;
-
-	if (yres > vyres)
-		vyres = yres;
-	if (vxres * vyres > maxmem) {
-		vyres = maxmem / vxres;
-		if (vyres < yres)
-			return -ENOMEM;
-	}
-	if (yoffset + yres > vyres)
-		yoffset = vyres - yres;
-	var->yres = yres;
-	var->lower_margin = lower;
-	var->vsync_len = vslen;
-	var->upper_margin = upper;
-	var->yres_virtual = vyres;
-	var->yoffset = yoffset;
-
-	if (var->vmode & FB_VMODE_DOUBLE) {
-		yres <<= 1;
-		lower <<= 1;
-		vslen <<= 1;
-		upper <<= 1;
-	}
-	ytotal = yres + lower + vslen + upper;
-	if (ytotal > 1024) {
-		ytotal >>= 1;
-		yres >>= 1;
-		lower >>= 1;
-		vslen >>= 1;
-		upper >>= 1;
-		rMode = 0x04;
-	} else
-		rMode = 0x00;
-	if (ytotal > 1024)
-		FAIL("ytotal too big");
-	if (vslen > 16)
-		FAIL("vslen too big");
-	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
-	r7 = 0x10;	/* disable linecompare */
-	if (ytotal & 0x100) r7 |= 0x01;
-	if (ytotal & 0x200) r7 |= 0x20;
-	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
-	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
-	if (var->vmode & FB_VMODE_DOUBLE)
-		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
-	par->crtc[VGA_CRTC_CURSOR_START] = 0x20;
-	par->crtc[VGA_CRTC_CURSOR_END]   = 0x00;
-	if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB)
-		xoffset--;
-	pos = yoffset * vxres + (xoffset >> shift);
-	par->crtc[VGA_CRTC_START_HI]     = pos >> 8;
-	par->crtc[VGA_CRTC_START_LO]     = pos & 0xFF;
-	par->crtc[VGA_CRTC_CURSOR_HI]    = 0x00;
-	par->crtc[VGA_CRTC_CURSOR_LO]    = 0x00;
-	pos = yres - 1;
-	par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF;
-	par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF;
-	if (pos & 0x100)
-		r7 |= 0x0A;	/* 0x02 -> DISP_END, 0x08 -> BLANK_START */
-	if (pos & 0x200) {
-		r7 |= 0x40;	/* 0x40 -> DISP_END */
-		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
-	}
-	pos += lower;
-	par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF;
-	if (pos & 0x100)
-		r7 |= 0x04;
-	if (pos & 0x200)
-		r7 |= 0x80;
-	pos += vslen;
-	par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */
-	pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
-	par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
-                     but some SVGA chips requires all 8 bits to set */
-	if (vxres >= 512)
-		FAIL("vxres too long");
-	par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
-	if (mode & MODE_SKIP4)
-		par->crtc[VGA_CRTC_UNDERLINE] = 0x5F;	/* 256, cfb8 */
-	else
-		par->crtc[VGA_CRTC_UNDERLINE] = 0x1F;	/* 16, vgap */
-	par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3);
-	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
-	par->crtc[VGA_CRTC_OVERFLOW] = r7;
-
-	par->vss = 0x00;	/* 3DA */
-
-	par->misc = 0xE3;	/* enable CPU, ports 0x3Dx, positive sync */
-	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-		par->misc &= ~0x40;
-	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-		par->misc &= ~0x80;
-	
-	par->mode = mode;
-
-	if (mode & MODE_8BPP)
-		/* pixel clock == vga clock / 2 */
-		vga16fb_clock_chip(par, var->pixclock, info, 1, 2);
-	else
-		/* pixel clock == vga clock */
-		vga16fb_clock_chip(par, var->pixclock, info, 1, 1);
-	
-	var->red.offset = var->green.offset = var->blue.offset = 
-	var->transp.offset = 0;
-	var->red.length = var->green.length = var->blue.length =
-		(par->isVGA) ? 6 : 2;
-	var->transp.length = 0;
-	var->activate = FB_ACTIVATE_NOW;
-	var->height = -1;
-	var->width = -1;
-	var->accel_flags = 0;
-	return 0;
-}
-#undef FAIL
-
-static int vga16fb_set_par(struct fb_info *info)
-{
-	struct vga16fb_par *par = info->par;
-	u8 gdc[VGA_GFX_C];
-	u8 seq[VGA_SEQ_C];
-	u8 atc[VGA_ATT_C];
-	int fh, i;
-
-	seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv;
-	if (par->mode & MODE_TEXT)
-		seq[VGA_SEQ_PLANE_WRITE] = 0x03;
-	else
-		seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
-	seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
-	if (par->mode & MODE_TEXT)
-		seq[VGA_SEQ_MEMORY_MODE] = 0x03;
-	else if (par->mode & MODE_SKIP4)
-		seq[VGA_SEQ_MEMORY_MODE] = 0x0E;
-	else
-		seq[VGA_SEQ_MEMORY_MODE] = 0x06;
-
-	gdc[VGA_GFX_SR_VALUE] = 0x00;
-	gdc[VGA_GFX_SR_ENABLE] = 0x00;
-	gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
-	gdc[VGA_GFX_DATA_ROTATE] = 0x00;
-	gdc[VGA_GFX_PLANE_READ] = 0;
-	if (par->mode & MODE_TEXT) {
-		gdc[VGA_GFX_MODE] = 0x10;
-		gdc[VGA_GFX_MISC] = 0x06;
-	} else {
-		if (par->mode & MODE_CFB)
-			gdc[VGA_GFX_MODE] = 0x40;
-		else
-			gdc[VGA_GFX_MODE] = 0x00;
-		gdc[VGA_GFX_MISC] = 0x05;
-	}
-	gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
-	gdc[VGA_GFX_BIT_MASK] = 0xFF;
-
-	for (i = 0x00; i < 0x10; i++)
-		atc[i] = i;
-	if (par->mode & MODE_TEXT)
-		atc[VGA_ATC_MODE] = 0x04;
-	else if (par->mode & MODE_8BPP)
-		atc[VGA_ATC_MODE] = 0x41;
-	else
-		atc[VGA_ATC_MODE] = 0x81;
-	atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
-	atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
-	if (par->mode & MODE_8BPP)
-		atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1;
-	else
-		atc[VGA_ATC_PEL] = info->var.xoffset & 7;
-	atc[VGA_ATC_COLOR_PAGE] = 0x00;
-	
-	if (par->mode & MODE_TEXT) {
-		fh = 16; // FIXME !!! Fudge font height. 
-		par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] 
-					       & ~0x1F) | (fh - 1);
-	}
-
-	vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01);
-
-	/* Enable graphics register modification */
-	if (!par->isVGA) {
-		vga_io_w(EGA_GFX_E0, 0x00);
-		vga_io_w(EGA_GFX_E1, 0x01);
-	}
-	
-	/* update misc output register */
-	vga_io_w(VGA_MIS_W, par->misc);
-	
-	/* synchronous reset on */
-	vga_io_wseq(0x00, 0x01);
-
-	if (par->isVGA)
-		vga_io_w(VGA_PEL_MSK, par->pel_msk);
-
-	/* write sequencer registers */
-	vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20);
-	for (i = 2; i < VGA_SEQ_C; i++) {
-		vga_io_wseq(i, seq[i]);
-	}
-	
-	/* synchronous reset off */
-	vga_io_wseq(0x00, 0x03);
-
-	/* deprotect CRT registers 0-7 */
-	vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
-
-	/* write CRT registers */
-	for (i = 0; i < VGA_CRTC_REGS; i++) {
-		vga_io_wcrt(i, par->crtc[i]);
-	}
-	
-	/* write graphics controller registers */
-	for (i = 0; i < VGA_GFX_C; i++) {
-		vga_io_wgfx(i, gdc[i]);
-	}
-	
-	/* write attribute controller registers */
-	for (i = 0; i < VGA_ATT_C; i++) {
-		vga_io_r(VGA_IS1_RC);		/* reset flip-flop */
-		vga_io_wattr(i, atc[i]);
-	}
-
-	/* Wait for screen to stabilize. */
-	mdelay(50);
-
-	vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]);
-
-	vga_io_r(VGA_IS1_RC);
-	vga_io_w(VGA_ATT_IW, 0x20);
-
-	vga16fb_update_fix(info);
-	return 0;
-}
-
-static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
-{
-	static const unsigned char map[] = { 000, 001, 010, 011 };
-	int val;
-	
-	if (regno >= 16)
-		return;
-	val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
-	vga_io_r(VGA_IS1_RC);   /* ! 0x3BA */
-	vga_io_wattr(regno, val);
-	vga_io_r(VGA_IS1_RC);   /* some clones need it */
-	vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */
-}
-
-static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
-{
-	outb(regno,       VGA_PEL_IW);
-	outb(red   >> 10, VGA_PEL_D);
-	outb(green >> 10, VGA_PEL_D);
-	outb(blue  >> 10, VGA_PEL_D);
-}
-
-static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info *info)
-{
-	struct vga16fb_par *par = info->par;
-	int gray;
-
-	/*
-	 *  Set a single color register. The values supplied are
-	 *  already rounded down to the hardware's capabilities
-	 *  (according to the entries in the `var' structure). Return
-	 *  != 0 for invalid regno.
-	 */
-	
-	if (regno >= 256)
-		return 1;
-
-	gray = info->var.grayscale;
-	
-	if (gray) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-	if (par->isVGA) 
-		vga16_setpalette(regno,red,green,blue);
-	else
-		ega16_setpalette(regno,red,green,blue);
-	return 0;
-}
-
-static int vga16fb_pan_display(struct fb_var_screeninfo *var,
-			       struct fb_info *info) 
-{
-	vga16fb_pan_var(info, var);
-	return 0;
-}
-
-/* The following VESA blanking code is taken from vgacon.c.  The VGA
-   blanking code was originally by Huang shi chao, and modified by
-   Christoph Rimek (chrimek@toppoint.de) and todd j. derr
-   (tjd@barefoot.org) for Linux. */
-
-static void vga_vesa_blank(struct vga16fb_par *par, int mode)
-{
-	unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
-	unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
-	
-	/* save original values of VGA controller registers */
-	if(!par->vesa_blanked) {
-		par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
-		//sti();
-
-		par->vga_state.HorizontalTotal = vga_io_rcrt(0x00);	/* HorizontalTotal */
-		par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01);	/* HorizDisplayEnd */
-		par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04);	/* StartHorizRetrace */
-		par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05);	/* EndHorizRetrace */
-		par->vga_state.Overflow = vga_io_rcrt(0x07);		/* Overflow */
-		par->vga_state.StartVertRetrace = vga_io_rcrt(0x10);	/* StartVertRetrace */
-		par->vga_state.EndVertRetrace = vga_io_rcrt(0x11);	/* EndVertRetrace */
-		par->vga_state.ModeControl = vga_io_rcrt(0x17);	/* ModeControl */
-		par->vga_state.ClockingMode = vga_io_rseq(0x01);	/* ClockingMode */
-	}
-
-	/* assure that video is enabled */
-	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
-	vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
-
-	/* test for vertical retrace in process.... */
-	if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
-		vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
-
-	/*
-	 * Set <End of vertical retrace> to minimum (0) and
-	 * <Start of vertical Retrace> to maximum (incl. overflow)
-	 * Result: turn off vertical sync (VSync) pulse.
-	 */
-	if (mode & FB_BLANK_VSYNC_SUSPEND) {
-		vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
-		vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
-		/* bits 9,10 of vert. retrace */
-		vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
-	}
-
-	if (mode & FB_BLANK_HSYNC_SUSPEND) {
-		/*
-		 * Set <End of horizontal retrace> to minimum (0) and
-		 *  <Start of horizontal Retrace> to maximum
-		 * Result: turn off horizontal sync (HSync) pulse.
-		 */
-		vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
-		vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
-	}
-
-	/* restore both index registers */
-	outb_p(SeqCtrlIndex, VGA_SEQ_I);
-	outb_p(CrtCtrlIndex, VGA_CRT_IC);
-}
-
-static void vga_vesa_unblank(struct vga16fb_par *par)
-{
-	unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
-	unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
-	
-	/* restore original values of VGA controller registers */
-	vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
-
-	/* HorizontalTotal */
-	vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
-	/* HorizDisplayEnd */
-	vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd);
-	/* StartHorizRetrace */
-	vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace);
-	/* EndHorizRetrace */
-	vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace);
-	/* Overflow */
-	vga_io_wcrt(0x07, par->vga_state.Overflow);
-	/* StartVertRetrace */
-	vga_io_wcrt(0x10, par->vga_state.StartVertRetrace);
-	/* EndVertRetrace */
-	vga_io_wcrt(0x11, par->vga_state.EndVertRetrace);
-	/* ModeControl */
-	vga_io_wcrt(0x17, par->vga_state.ModeControl);
-	/* ClockingMode */
-	vga_io_wseq(0x01, par->vga_state.ClockingMode);
-
-	/* restore index/control registers */
-	vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
-	vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
-}
-
-static void vga_pal_blank(void)
-{
-	int i;
-
-	for (i=0; i<16; i++) {
-		outb_p(i, VGA_PEL_IW);
-		outb_p(0, VGA_PEL_D);
-		outb_p(0, VGA_PEL_D);
-		outb_p(0, VGA_PEL_D);
-	}
-}
-
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-static int vga16fb_blank(int blank, struct fb_info *info)
-{
-	struct vga16fb_par *par = info->par;
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK:				/* Unblank */
-		if (par->vesa_blanked) {
-			vga_vesa_unblank(par);
-			par->vesa_blanked = 0;
-		}
-		if (par->palette_blanked) {
-			par->palette_blanked = 0;
-		}
-		break;
-	case FB_BLANK_NORMAL:				/* blank */
-		vga_pal_blank();
-		par->palette_blanked = 1;
-		break;
-	default:			/* VESA blanking */
-		vga_vesa_blank(par, blank);
-		par->vesa_blanked = 1;
-		break;
-	}
-	return 0;
-}
-
-static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	u32 dx = rect->dx, width = rect->width;
-        char oldindex = getindex();
-        char oldmode = setmode(0x40);
-        char oldmask = selectmask();
-        int line_ofs, height;
-        char oldop, oldsr;
-        char __iomem *where;
-
-        dx /= 4;
-        where = info->screen_base + dx + rect->dy * info->fix.line_length;
-
-        if (rect->rop == ROP_COPY) {
-                oldop = setop(0);
-                oldsr = setsr(0);
-
-                width /= 4;
-                line_ofs = info->fix.line_length - width;
-                setmask(0xff);
-
-                height = rect->height;
-
-                while (height--) {
-                        int x;
-
-                        /* we can do memset... */
-                        for (x = width; x > 0; --x) {
-                                writeb(rect->color, where);
-                                where++;
-                        }
-                        where += line_ofs;
-                }
-        } else {
-                char oldcolor = setcolor(0xf);
-                int y;
-
-                oldop = setop(0x18);
-                oldsr = setsr(0xf);
-                setmask(0x0F);
-                for (y = 0; y < rect->height; y++) {
-                        rmw(where);
-                        rmw(where+1);
-                        where += info->fix.line_length;
-                }
-                setcolor(oldcolor);
-        }
-        setmask(oldmask);
-        setsr(oldsr);
-        setop(oldop);
-        setmode(oldmode);
-        setindex(oldindex);
-}
-
-static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	int x, x2, y2, vxres, vyres, width, height, line_ofs;
-	char __iomem *dst;
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres)
-		return;
-
-	/* We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly. */
-
-	x2 = rect->dx + rect->width;
-	y2 = rect->dy + rect->height;
-	x2 = x2 < vxres ? x2 : vxres;
-	y2 = y2 < vyres ? y2 : vyres;
-	width = x2 - rect->dx;
-
-	switch (info->fix.type) {
-	case FB_TYPE_VGA_PLANES:
-		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
-
-			height = y2 - rect->dy;
-			width = rect->width/8;
-
-			line_ofs = info->fix.line_length - width;
-			dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length;
-
-			switch (rect->rop) {
-			case ROP_COPY:
-				setmode(0);
-				setop(0);
-				setsr(0xf);
-				setcolor(rect->color);
-				selectmask();
-
-				setmask(0xff);
-
-				while (height--) {
-					for (x = 0; x < width; x++) {
-						writeb(0, dst);
-						dst++;
-					}
-					dst += line_ofs;
-				}
-				break;
-			case ROP_XOR:
-				setmode(0);
-				setop(0x18);
-				setsr(0xf);
-				setcolor(0xf);
-				selectmask();
-
-				setmask(0xff);
-				while (height--) {
-					for (x = 0; x < width; x++) {
-						rmw(dst);
-						dst++;
-					}
-					dst += line_ofs;
-				}
-				break;
-			}
-		} else 
-			vga_8planes_fillrect(info, rect);
-		break;
-	case FB_TYPE_PACKED_PIXELS:
-	default:
-		cfb_fillrect(info, rect);
-		break;
-	}
-}
-
-static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-        char oldindex = getindex();
-        char oldmode = setmode(0x41);
-        char oldop = setop(0);
-        char oldsr = setsr(0xf);
-        int height, line_ofs, x;
-	u32 sx, dx, width;
-	char __iomem *dest;
-	char __iomem *src;
-
-        height = area->height;
-
-        sx = area->sx / 4;
-        dx = area->dx / 4;
-        width = area->width / 4;
-
-        if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) {
-                line_ofs = info->fix.line_length - width;
-                dest = info->screen_base + dx + area->dy * info->fix.line_length;
-                src = info->screen_base + sx + area->sy * info->fix.line_length;
-                while (height--) {
-                        for (x = 0; x < width; x++) {
-                                readb(src);
-                                writeb(0, dest);
-                                src++;
-                                dest++;
-                        }
-                        src += line_ofs;
-                        dest += line_ofs;
-                }
-        } else {
-                line_ofs = info->fix.line_length - width;
-                dest = info->screen_base + dx + width +
-			(area->dy + height - 1) * info->fix.line_length;
-                src = info->screen_base + sx + width +
-			(area->sy + height - 1) * info->fix.line_length;
-                while (height--) {
-                        for (x = 0; x < width; x++) {
-                                --src;
-                                --dest;
-                                readb(src);
-                                writeb(0, dest);
-                        }
-                        src -= line_ofs;
-                        dest -= line_ofs;
-                }
-        }
-
-        setsr(oldsr);
-        setop(oldop);
-        setmode(oldmode);
-        setindex(oldindex);
-}
-
-static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 
-	int x, x2, y2, old_dx, old_dy, vxres, vyres;
-	int height, width, line_ofs;
-	char __iomem *dst = NULL;
-	char __iomem *src = NULL;
-
-	vxres = info->var.xres_virtual;
-	vyres = info->var.yres_virtual;
-
-	if (area->dx > vxres || area->sx > vxres || area->dy > vyres ||
-	    area->sy > vyres)
-		return;
-
-	/* clip the destination */
-	old_dx = area->dx;
-	old_dy = area->dy;
-
-	/*
-	 * We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly.
-	 */
-	x2 = area->dx + area->width;
-	y2 = area->dy + area->height;
-	dx = area->dx > 0 ? area->dx : 0;
-	dy = area->dy > 0 ? area->dy : 0;
-	x2 = x2 < vxres ? x2 : vxres;
-	y2 = y2 < vyres ? y2 : vyres;
-	width = x2 - dx;
-	height = y2 - dy;
-
-	if (sx + dx < old_dx || sy + dy < old_dy)
-		return;
-
-	/* update sx1,sy1 */
-	sx += (dx - old_dx);
-	sy += (dy - old_dy);
-
-	/* the source must be completely inside the virtual screen */
-	if (sx + width > vxres || sy + height > vyres)
-		return;
-
-	switch (info->fix.type) {
-	case FB_TYPE_VGA_PLANES:
-		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
-			width = width/8;
-			height = height;
-			line_ofs = info->fix.line_length - width;
-
-			setmode(1);
-			setop(0);
-			setsr(0xf);
-
-			if (dy < sy || (dy == sy && dx < sx)) {
-				dst = info->screen_base + (dx/8) + dy * info->fix.line_length;
-				src = info->screen_base + (sx/8) + sy * info->fix.line_length;
-				while (height--) {
-					for (x = 0; x < width; x++) {
-						readb(src);
-						writeb(0, dst);
-						dst++;
-						src++;
-					}
-					src += line_ofs;
-					dst += line_ofs;
-				}
-			} else {
-				dst = info->screen_base + (dx/8) + width + 
-					(dy + height - 1) * info->fix.line_length;
-				src = info->screen_base + (sx/8) + width + 
-					(sy + height  - 1) * info->fix.line_length;
-				while (height--) {
-					for (x = 0; x < width; x++) {
-						dst--;
-						src--;
-						readb(src);
-						writeb(0, dst);
-					}
-					src -= line_ofs;
-					dst -= line_ofs;
-				}
-			}
-		} else 
-			vga_8planes_copyarea(info, area);
-		break;
-	case FB_TYPE_PACKED_PIXELS:
-	default:
-		cfb_copyarea(info, area);
-		break;
-	}
-}
-
-#define TRANS_MASK_LOW  {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
-#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
-			 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
-
-#if defined(__LITTLE_ENDIAN)
-static const u16 transl_l[] = TRANS_MASK_LOW;
-static const u16 transl_h[] = TRANS_MASK_HIGH;
-#elif defined(__BIG_ENDIAN)
-static const u16 transl_l[] = TRANS_MASK_HIGH;
-static const u16 transl_h[] = TRANS_MASK_LOW;
-#else
-#error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
-#endif
-
-static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-        char oldindex = getindex();
-        char oldmode = setmode(0x40);
-        char oldop = setop(0);
-        char oldsr = setsr(0);
-        char oldmask = selectmask();
-        const char *cdat = image->data;
-	u32 dx = image->dx;
-        char __iomem *where;
-        int y;
-
-        dx /= 4;
-        where = info->screen_base + dx + image->dy * info->fix.line_length;
-
-        setmask(0xff);
-        writeb(image->bg_color, where);
-        readb(where);
-        selectmask();
-        setmask(image->fg_color ^ image->bg_color);
-        setmode(0x42);
-        setop(0x18);
-        for (y = 0; y < image->height; y++, where += info->fix.line_length)
-                writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where);
-        setmask(oldmask);
-        setsr(oldsr);
-        setop(oldop);
-        setmode(oldmode);
-        setindex(oldindex);
-}
-
-static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
-{
-	char __iomem *where = info->screen_base + (image->dx/8) +
-		image->dy * info->fix.line_length;
-	struct vga16fb_par *par = info->par;
-	char *cdat = (char *) image->data;
-	char __iomem *dst;
-	int x, y;
-
-	switch (info->fix.type) {
-	case FB_TYPE_VGA_PLANES:
-		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
-			if (par->isVGA) {
-				setmode(2);
-				setop(0);
-				setsr(0xf);
-				setcolor(image->fg_color);
-				selectmask();
-				
-				setmask(0xff);
-				writeb(image->bg_color, where);
-				rmb();
-				readb(where); /* fill latches */
-				setmode(3);
-				wmb();
-				for (y = 0; y < image->height; y++) {
-					dst = where;
-					for (x = image->width/8; x--;) 
-						writeb(*cdat++, dst++);
-					where += info->fix.line_length;
-				}
-				wmb();
-			} else {
-				setmode(0);
-				setop(0);
-				setsr(0xf);
-				setcolor(image->bg_color);
-				selectmask();
-				
-				setmask(0xff);
-				for (y = 0; y < image->height; y++) {
-					dst = where;
-					for (x=image->width/8; x--;){
-						rmw(dst);
-						setcolor(image->fg_color);
-						selectmask();
-						if (*cdat) {
-							setmask(*cdat++);
-							rmw(dst++);
-						}
-					}
-					where += info->fix.line_length;
-				}
-			}
-		} else 
-			vga_8planes_imageblit(info, image);
-		break;
-	case FB_TYPE_PACKED_PIXELS:
-	default:
-		cfb_imageblit(info, image);
-		break;
-	}
-}
-
-static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
-{
-	/*
-	 * Draw logo 
-	 */
-	struct vga16fb_par *par = info->par;
-	char __iomem *where =
-		info->screen_base + image->dy * info->fix.line_length +
-		image->dx/8;
-	const char *cdat = image->data;
-	char __iomem *dst;
-	int x, y;
-
-	switch (info->fix.type) {
-	case FB_TYPE_VGA_PLANES:
-		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&
-		    par->isVGA) {
-			setsr(0xf);
-			setop(0);
-			setmode(0);
-			
-			for (y = 0; y < image->height; y++) {
-				for (x = 0; x < image->width; x++) {
-					dst = where + x/8;
-
-					setcolor(*cdat);
-					selectmask();
-					setmask(1 << (7 - (x % 8)));
-					fb_readb(dst);
-					fb_writeb(0, dst);
-
-					cdat++;
-				}
-				where += info->fix.line_length;
-			}
-		}
-		break;
-	case FB_TYPE_PACKED_PIXELS:
-		cfb_imageblit(info, image);
-		break;
-	default:
-		break;
-	}
-}
-				
-static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	if (image->depth == 1)
-		vga_imageblit_expand(info, image);
-	else
-		vga_imageblit_color(info, image);
-}
-
-static void vga16fb_destroy(struct fb_info *info)
-{
-	iounmap(info->screen_base);
-	fb_dealloc_cmap(&info->cmap);
-	/* XXX unshare VGA regions */
-	framebuffer_release(info);
-}
-
-static struct fb_ops vga16fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open        = vga16fb_open,
-	.fb_release     = vga16fb_release,
-	.fb_destroy	= vga16fb_destroy,
-	.fb_check_var	= vga16fb_check_var,
-	.fb_set_par	= vga16fb_set_par,
-	.fb_setcolreg 	= vga16fb_setcolreg,
-	.fb_pan_display = vga16fb_pan_display,
-	.fb_blank 	= vga16fb_blank,
-	.fb_fillrect	= vga16fb_fillrect,
-	.fb_copyarea	= vga16fb_copyarea,
-	.fb_imageblit	= vga16fb_imageblit,
-};
-
-#ifndef MODULE
-static int __init vga16fb_setup(char *options)
-{
-	char *this_opt;
-	
-	if (!options || !*options)
-		return 0;
-	
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt) continue;
-	}
-	return 0;
-}
-#endif
-
-static int vga16fb_probe(struct platform_device *dev)
-{
-	struct fb_info *info;
-	struct vga16fb_par *par;
-	int i;
-	int ret = 0;
-
-	printk(KERN_DEBUG "vga16fb: initializing\n");
-	info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
-
-	if (!info) {
-		ret = -ENOMEM;
-		goto err_fb_alloc;
-	}
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures) {
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
-	info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
-
-	if (!info->screen_base) {
-		printk(KERN_ERR "vga16fb: unable to map device\n");
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
-	par = info->par;
-
-	par->isVGA = screen_info.orig_video_isVGA;
-	par->palette_blanked = 0;
-	par->vesa_blanked = 0;
-
-	i = par->isVGA? 6 : 2;
-	
-	vga16fb_defined.red.length   = i;
-	vga16fb_defined.green.length = i;
-	vga16fb_defined.blue.length  = i;	
-
-	/* name should not depend on EGA/VGA */
-	info->fbops = &vga16fb_ops;
-	info->var = vga16fb_defined;
-	info->fix = vga16fb_fix;
-	/* supports rectangles with widths of multiples of 8 */
-	info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
-	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE |
-		FBINFO_HWACCEL_YPAN;
-
-	i = (info->var.bits_per_pixel == 8) ? 256 : 16;
-	ret = fb_alloc_cmap(&info->cmap, i, 0);
-	if (ret) {
-		printk(KERN_ERR "vga16fb: unable to allocate colormap\n");
-		ret = -ENOMEM;
-		goto err_alloc_cmap;
-	}
-
-	if (vga16fb_check_var(&info->var, info)) {
-		printk(KERN_ERR "vga16fb: unable to validate variable\n");
-		ret = -EINVAL;
-		goto err_check_var;
-	}
-
-	vga16fb_update_fix(info);
-
-	info->apertures->ranges[0].base = VGA_FB_PHYS;
-	info->apertures->ranges[0].size = VGA_FB_PHYS_LEN;
-
-	if (register_framebuffer(info) < 0) {
-		printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
-		ret = -EINVAL;
-		goto err_check_var;
-	}
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	platform_set_drvdata(dev, info);
-
-	return 0;
-
- err_check_var:
-	fb_dealloc_cmap(&info->cmap);
- err_alloc_cmap:
-	iounmap(info->screen_base);
- err_ioremap:
-	framebuffer_release(info);
- err_fb_alloc:
-	return ret;
-}
-
-static int vga16fb_remove(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-
-	if (info)
-		unregister_framebuffer(info);
-
-	return 0;
-}
-
-static struct platform_driver vga16fb_driver = {
-	.probe = vga16fb_probe,
-	.remove = vga16fb_remove,
-	.driver = {
-		.name = "vga16fb",
-	},
-};
-
-static struct platform_device *vga16fb_device;
-
-static int __init vga16fb_init(void)
-{
-	int ret;
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("vga16fb", &option))
-		return -ENODEV;
-
-	vga16fb_setup(option);
-#endif
-	ret = platform_driver_register(&vga16fb_driver);
-
-	if (!ret) {
-		vga16fb_device = platform_device_alloc("vga16fb", 0);
-
-		if (vga16fb_device)
-			ret = platform_device_add(vga16fb_device);
-		else
-			ret = -ENOMEM;
-
-		if (ret) {
-			platform_device_put(vga16fb_device);
-			platform_driver_unregister(&vga16fb_driver);
-		}
-	}
-
-	return ret;
-}
-
-static void __exit vga16fb_exit(void)
-{
-	platform_device_unregister(vga16fb_device);
-	platform_driver_unregister(&vga16fb_driver);
-}
-
-MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
-MODULE_LICENSE("GPL");
-module_init(vga16fb_init);
-module_exit(vga16fb_exit);
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
deleted file mode 100644
index 159f26e6adb5..000000000000
--- a/drivers/video/via/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for the VIA framebuffer driver (for Linux Kernel 2.6)
-#
-
-obj-$(CONFIG_FB_VIA) += viafb.o
-
-viafb-y	:=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
-	via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \
-	via-core.o via-gpio.o via_modesetting.o via_clock.o \
-	via_aux.o via_aux_edid.o via_aux_vt1636.o via_aux_vt1632.o \
-	via_aux_vt1631.o via_aux_vt1625.o via_aux_vt1622.o via_aux_vt1621.o \
-	via_aux_sii164.o via_aux_ch7301.o
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
deleted file mode 100644
index 4b67b8e6030a..000000000000
--- a/drivers/video/via/accel.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <linux/via-core.h>
-#include "global.h"
-
-/*
- * Figure out an appropriate bytes-per-pixel setting.
- */
-static int viafb_set_bpp(void __iomem *engine, u8 bpp)
-{
-	u32 gemode;
-
-	/* Preserve the reserved bits */
-	/* Lowest 2 bits to zero gives us no rotation */
-	gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc;
-	switch (bpp) {
-	case 8:
-		gemode |= VIA_GEM_8bpp;
-		break;
-	case 16:
-		gemode |= VIA_GEM_16bpp;
-		break;
-	case 32:
-		gemode |= VIA_GEM_32bpp;
-		break;
-	default:
-		printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp);
-		return -EINVAL;
-	}
-	writel(gemode, engine + VIA_REG_GEMODE);
-	return 0;
-}
-
-
-static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
-	u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
-	u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
-	u32 fg_color, u32 bg_color, u8 fill_rop)
-{
-	u32 ge_cmd = 0, tmp, i;
-	int ret;
-
-	if (!op || op > 3) {
-		printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
-		return -EINVAL;
-	}
-
-	if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
-		if (src_x < dst_x) {
-			ge_cmd |= 0x00008000;
-			src_x += width - 1;
-			dst_x += width - 1;
-		}
-		if (src_y < dst_y) {
-			ge_cmd |= 0x00004000;
-			src_y += height - 1;
-			dst_y += height - 1;
-		}
-	}
-
-	if (op == VIA_BITBLT_FILL) {
-		switch (fill_rop) {
-		case 0x00: /* blackness */
-		case 0x5A: /* pattern inversion */
-		case 0xF0: /* pattern copy */
-		case 0xFF: /* whiteness */
-			break;
-		default:
-			printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
-				"%u\n", fill_rop);
-			return -EINVAL;
-		}
-	}
-
-	ret = viafb_set_bpp(engine, dst_bpp);
-	if (ret)
-		return ret;
-
-	if (op != VIA_BITBLT_FILL) {
-		if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
-			|| src_y & 0xFFFFF000) {
-			printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
-				"x/y %d %d\n", src_x, src_y);
-			return -EINVAL;
-		}
-		tmp = src_x | (src_y << 16);
-		writel(tmp, engine + 0x08);
-	}
-
-	if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
-		printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y "
-			"%d %d\n", dst_x, dst_y);
-		return -EINVAL;
-	}
-	tmp = dst_x | (dst_y << 16);
-	writel(tmp, engine + 0x0C);
-
-	if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
-		printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height "
-			"%d %d\n", width, height);
-		return -EINVAL;
-	}
-	tmp = (width - 1) | ((height - 1) << 16);
-	writel(tmp, engine + 0x10);
-
-	if (op != VIA_BITBLT_COLOR)
-		writel(fg_color, engine + 0x18);
-
-	if (op == VIA_BITBLT_MONO)
-		writel(bg_color, engine + 0x1C);
-
-	if (op != VIA_BITBLT_FILL) {
-		tmp = src_mem ? 0 : src_addr;
-		if (dst_addr & 0xE0000007) {
-			printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
-				"address %X\n", tmp);
-			return -EINVAL;
-		}
-		tmp >>= 3;
-		writel(tmp, engine + 0x30);
-	}
-
-	if (dst_addr & 0xE0000007) {
-		printk(KERN_WARNING "hw_bitblt_1: Unsupported destination "
-			"address %X\n", dst_addr);
-		return -EINVAL;
-	}
-	tmp = dst_addr >> 3;
-	writel(tmp, engine + 0x34);
-
-	if (op == VIA_BITBLT_FILL)
-		tmp = 0;
-	else
-		tmp = src_pitch;
-	if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
-		printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n",
-			tmp, dst_pitch);
-		return -EINVAL;
-	}
-	tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3));
-	writel(tmp, engine + 0x38);
-
-	if (op == VIA_BITBLT_FILL)
-		ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
-	else {
-		ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
-		if (src_mem)
-			ge_cmd |= 0x00000040;
-		if (op == VIA_BITBLT_MONO)
-			ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
-		else
-			ge_cmd |= 0x00000001;
-	}
-	writel(ge_cmd, engine);
-
-	if (op == VIA_BITBLT_FILL || !src_mem)
-		return 0;
-
-	tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
-		3) >> 2;
-
-	for (i = 0; i < tmp; i++)
-		writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
-
-	return 0;
-}
-
-static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
-	u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
-	u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
-	u32 fg_color, u32 bg_color, u8 fill_rop)
-{
-	u32 ge_cmd = 0, tmp, i;
-	int ret;
-
-	if (!op || op > 3) {
-		printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
-		return -EINVAL;
-	}
-
-	if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
-		if (src_x < dst_x) {
-			ge_cmd |= 0x00008000;
-			src_x += width - 1;
-			dst_x += width - 1;
-		}
-		if (src_y < dst_y) {
-			ge_cmd |= 0x00004000;
-			src_y += height - 1;
-			dst_y += height - 1;
-		}
-	}
-
-	if (op == VIA_BITBLT_FILL) {
-		switch (fill_rop) {
-		case 0x00: /* blackness */
-		case 0x5A: /* pattern inversion */
-		case 0xF0: /* pattern copy */
-		case 0xFF: /* whiteness */
-			break;
-		default:
-			printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
-				"%u\n", fill_rop);
-			return -EINVAL;
-		}
-	}
-
-	ret = viafb_set_bpp(engine, dst_bpp);
-	if (ret)
-		return ret;
-
-	if (op == VIA_BITBLT_FILL)
-		tmp = 0;
-	else
-		tmp = src_pitch;
-	if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
-		printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n",
-			tmp, dst_pitch);
-		return -EINVAL;
-	}
-	tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
-	writel(tmp, engine + 0x08);
-
-	if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
-		printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height "
-			"%d %d\n", width, height);
-		return -EINVAL;
-	}
-	tmp = (width - 1) | ((height - 1) << 16);
-	writel(tmp, engine + 0x0C);
-
-	if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
-		printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y "
-			"%d %d\n", dst_x, dst_y);
-		return -EINVAL;
-	}
-	tmp = dst_x | (dst_y << 16);
-	writel(tmp, engine + 0x10);
-
-	if (dst_addr & 0xE0000007) {
-		printk(KERN_WARNING "hw_bitblt_2: Unsupported destination "
-			"address %X\n", dst_addr);
-		return -EINVAL;
-	}
-	tmp = dst_addr >> 3;
-	writel(tmp, engine + 0x14);
-
-	if (op != VIA_BITBLT_FILL) {
-		if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
-			|| src_y & 0xFFFFF000) {
-			printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
-				"x/y %d %d\n", src_x, src_y);
-			return -EINVAL;
-		}
-		tmp = src_x | (src_y << 16);
-		writel(tmp, engine + 0x18);
-
-		tmp = src_mem ? 0 : src_addr;
-		if (dst_addr & 0xE0000007) {
-			printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
-				"address %X\n", tmp);
-			return -EINVAL;
-		}
-		tmp >>= 3;
-		writel(tmp, engine + 0x1C);
-	}
-
-	if (op == VIA_BITBLT_FILL) {
-		writel(fg_color, engine + 0x58);
-	} else if (op == VIA_BITBLT_MONO) {
-		writel(fg_color, engine + 0x4C);
-		writel(bg_color, engine + 0x50);
-	}
-
-	if (op == VIA_BITBLT_FILL)
-		ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
-	else {
-		ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
-		if (src_mem)
-			ge_cmd |= 0x00000040;
-		if (op == VIA_BITBLT_MONO)
-			ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
-		else
-			ge_cmd |= 0x00000001;
-	}
-	writel(ge_cmd, engine);
-
-	if (op == VIA_BITBLT_FILL || !src_mem)
-		return 0;
-
-	tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
-		3) >> 2;
-
-	for (i = 0; i < tmp; i++)
-		writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
-
-	return 0;
-}
-
-int viafb_setup_engine(struct fb_info *info)
-{
-	struct viafb_par *viapar = info->par;
-	void __iomem *engine;
-	u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
-
-	engine = viapar->shared->vdev->engine_mmio;
-	if (!engine) {
-		printk(KERN_WARNING "viafb_init_accel: ioremap failed, "
-			"hardware acceleration disabled\n");
-		return -ENOMEM;
-	}
-
-	switch (chip_name) {
-	case UNICHROME_CLE266:
-	case UNICHROME_K400:
-	case UNICHROME_K800:
-	case UNICHROME_PM800:
-	case UNICHROME_CN700:
-	case UNICHROME_CX700:
-	case UNICHROME_CN750:
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M890:
-	case UNICHROME_P4M900:
-		viapar->shared->hw_bitblt = hw_bitblt_1;
-		break;
-	case UNICHROME_VX800:
-	case UNICHROME_VX855:
-	case UNICHROME_VX900:
-		viapar->shared->hw_bitblt = hw_bitblt_2;
-		break;
-	default:
-		viapar->shared->hw_bitblt = NULL;
-	}
-
-	viapar->fbmem_free -= CURSOR_SIZE;
-	viapar->shared->cursor_vram_addr = viapar->fbmem_free;
-	viapar->fbmem_used += CURSOR_SIZE;
-
-	viapar->fbmem_free -= VQ_SIZE;
-	viapar->shared->vq_vram_addr = viapar->fbmem_free;
-	viapar->fbmem_used += VQ_SIZE;
-
-#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
-	/*
-	 * Set aside a chunk of framebuffer memory for the camera
-	 * driver.  Someday this driver probably needs a proper allocator
-	 * for fbmem; for now, we just have to do this before the
-	 * framebuffer initializes itself.
-	 *
-	 * As for the size: the engine can handle three frames,
-	 * 16 bits deep, up to VGA resolution.
-	 */
-	viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2;
-	viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size;
-	viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size;
-	viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
-#endif
-
-	viafb_reset_engine(viapar);
-	return 0;
-}
-
-void viafb_reset_engine(struct viafb_par *viapar)
-{
-	void __iomem *engine = viapar->shared->vdev->engine_mmio;
-	int highest_reg, i;
-	u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
-		vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
-
-	/* Initialize registers to reset the 2D engine */
-	switch (viapar->shared->chip_info.twod_engine) {
-	case VIA_2D_ENG_M1:
-		highest_reg = 0x5c;
-		break;
-	default:
-		highest_reg = 0x40;
-		break;
-	}
-	for (i = 0; i <= highest_reg; i += 4)
-		writel(0x0, engine + i);
-
-	/* Init AGP and VQ regs */
-	switch (chip_name) {
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M900:
-	case UNICHROME_VX800:
-	case UNICHROME_VX855:
-	case UNICHROME_VX900:
-		writel(0x00100000, engine + VIA_REG_CR_TRANSET);
-		writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
-		writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
-		break;
-
-	default:
-		writel(0x00100000, engine + VIA_REG_TRANSET);
-		writel(0x00000000, engine + VIA_REG_TRANSPACE);
-		writel(0x00333004, engine + VIA_REG_TRANSPACE);
-		writel(0x60000000, engine + VIA_REG_TRANSPACE);
-		writel(0x61000000, engine + VIA_REG_TRANSPACE);
-		writel(0x62000000, engine + VIA_REG_TRANSPACE);
-		writel(0x63000000, engine + VIA_REG_TRANSPACE);
-		writel(0x64000000, engine + VIA_REG_TRANSPACE);
-		writel(0x7D000000, engine + VIA_REG_TRANSPACE);
-
-		writel(0xFE020000, engine + VIA_REG_TRANSET);
-		writel(0x00000000, engine + VIA_REG_TRANSPACE);
-		break;
-	}
-
-	/* Enable VQ */
-	vq_start_addr = viapar->shared->vq_vram_addr;
-	vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1;
-
-	vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF);
-	vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF);
-	vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) |
-		((vq_end_addr & 0xFF000000) >> 16);
-	vq_len = 0x53000000 | (VQ_SIZE >> 3);
-
-	switch (chip_name) {
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M900:
-	case UNICHROME_VX800:
-	case UNICHROME_VX855:
-	case UNICHROME_VX900:
-		vq_start_low |= 0x20000000;
-		vq_end_low |= 0x20000000;
-		vq_high |= 0x20000000;
-		vq_len |= 0x20000000;
-
-		writel(0x00100000, engine + VIA_REG_CR_TRANSET);
-		writel(vq_high, engine + VIA_REG_CR_TRANSPACE);
-		writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE);
-		writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE);
-		writel(vq_len, engine + VIA_REG_CR_TRANSPACE);
-		writel(0x74301001, engine + VIA_REG_CR_TRANSPACE);
-		writel(0x00000000, engine + VIA_REG_CR_TRANSPACE);
-		break;
-	default:
-		writel(0x00FE0000, engine + VIA_REG_TRANSET);
-		writel(0x080003FE, engine + VIA_REG_TRANSPACE);
-		writel(0x0A00027C, engine + VIA_REG_TRANSPACE);
-		writel(0x0B000260, engine + VIA_REG_TRANSPACE);
-		writel(0x0C000274, engine + VIA_REG_TRANSPACE);
-		writel(0x0D000264, engine + VIA_REG_TRANSPACE);
-		writel(0x0E000000, engine + VIA_REG_TRANSPACE);
-		writel(0x0F000020, engine + VIA_REG_TRANSPACE);
-		writel(0x1000027E, engine + VIA_REG_TRANSPACE);
-		writel(0x110002FE, engine + VIA_REG_TRANSPACE);
-		writel(0x200F0060, engine + VIA_REG_TRANSPACE);
-
-		writel(0x00000006, engine + VIA_REG_TRANSPACE);
-		writel(0x40008C0F, engine + VIA_REG_TRANSPACE);
-		writel(0x44000000, engine + VIA_REG_TRANSPACE);
-		writel(0x45080C04, engine + VIA_REG_TRANSPACE);
-		writel(0x46800408, engine + VIA_REG_TRANSPACE);
-
-		writel(vq_high, engine + VIA_REG_TRANSPACE);
-		writel(vq_start_low, engine + VIA_REG_TRANSPACE);
-		writel(vq_end_low, engine + VIA_REG_TRANSPACE);
-		writel(vq_len, engine + VIA_REG_TRANSPACE);
-		break;
-	}
-
-	/* Set Cursor Image Base Address */
-	writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE);
-	writel(0x0, engine + VIA_REG_CURSOR_POS);
-	writel(0x0, engine + VIA_REG_CURSOR_ORG);
-	writel(0x0, engine + VIA_REG_CURSOR_BG);
-	writel(0x0, engine + VIA_REG_CURSOR_FG);
-	return;
-}
-
-void viafb_show_hw_cursor(struct fb_info *info, int Status)
-{
-	struct viafb_par *viapar = info->par;
-	u32 temp, iga_path = viapar->iga_path;
-
-	temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
-	switch (Status) {
-	case HW_Cursor_ON:
-		temp |= 0x1;
-		break;
-	case HW_Cursor_OFF:
-		temp &= 0xFFFFFFFE;
-		break;
-	}
-	switch (iga_path) {
-	case IGA2:
-		temp |= 0x80000000;
-		break;
-	case IGA1:
-	default:
-		temp &= 0x7FFFFFFF;
-	}
-	writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
-}
-
-void viafb_wait_engine_idle(struct fb_info *info)
-{
-	struct viafb_par *viapar = info->par;
-	int loop = 0;
-	u32 mask;
-	void __iomem *engine = viapar->shared->vdev->engine_mmio;
-
-	switch (viapar->shared->chip_info.twod_engine) {
-	case VIA_2D_ENG_H5:
-	case VIA_2D_ENG_M1:
-		mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 |
-			      VIA_3D_ENG_BUSY_M1;
-		break;
-	default:
-		while (!(readl(engine + VIA_REG_STATUS) &
-				VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
-			loop++;
-			cpu_relax();
-		}
-		mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY;
-		break;
-	}
-
-	while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) {
-		loop++;
-		cpu_relax();
-	}
-
-	if (loop >= MAXLOOP)
-		printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n");
-}
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h
deleted file mode 100644
index 79d5e10cc835..000000000000
--- a/drivers/video/via/accel.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __ACCEL_H__
-#define __ACCEL_H__
-
-#define FB_ACCEL_VIA_UNICHROME  50
-
-/* MMIO Base Address Definition */
-#define MMIO_VGABASE                0x8000
-#define MMIO_CR_READ                (MMIO_VGABASE + 0x3D4)
-#define MMIO_CR_WRITE               (MMIO_VGABASE + 0x3D5)
-#define MMIO_SR_READ                (MMIO_VGABASE + 0x3C4)
-#define MMIO_SR_WRITE               (MMIO_VGABASE + 0x3C5)
-
-/* HW Cursor Status Define */
-#define HW_Cursor_ON    0
-#define HW_Cursor_OFF   1
-
-#define CURSOR_SIZE     (8 * 1024)
-#define VQ_SIZE         (256 * 1024)
-
-#define VIA_MMIO_BLTBASE        0x200000
-#define VIA_MMIO_BLTSIZE        0x200000
-
-/* Defines for 2D registers */
-#define VIA_REG_GECMD           0x000
-#define VIA_REG_GEMODE          0x004
-#define VIA_REG_SRCPOS          0x008
-#define VIA_REG_DSTPOS          0x00C
-/* width and height */
-#define VIA_REG_DIMENSION       0x010
-#define VIA_REG_PATADDR         0x014
-#define VIA_REG_FGCOLOR         0x018
-#define VIA_REG_BGCOLOR         0x01C
-/* top and left of clipping */
-#define VIA_REG_CLIPTL          0x020
-/* bottom and right of clipping */
-#define VIA_REG_CLIPBR          0x024
-#define VIA_REG_OFFSET          0x028
-/* color key control */
-#define VIA_REG_KEYCONTROL      0x02C
-#define VIA_REG_SRCBASE         0x030
-#define VIA_REG_DSTBASE         0x034
-/* pitch of src and dst */
-#define VIA_REG_PITCH           0x038
-#define VIA_REG_MONOPAT0        0x03C
-#define VIA_REG_MONOPAT1        0x040
-/* from 0x100 to 0x1ff */
-#define VIA_REG_COLORPAT        0x100
-
-/* defines for VIA 2D registers for vt3353/3409 (M1 engine)*/
-#define VIA_REG_GECMD_M1        0x000
-#define VIA_REG_GEMODE_M1       0x004
-#define VIA_REG_GESTATUS_M1     0x004       /* as same as VIA_REG_GEMODE */
-#define VIA_REG_PITCH_M1        0x008       /* pitch of src and dst */
-#define VIA_REG_DIMENSION_M1    0x00C       /* width and height */
-#define VIA_REG_DSTPOS_M1       0x010
-#define VIA_REG_LINE_XY_M1      0x010
-#define VIA_REG_DSTBASE_M1      0x014
-#define VIA_REG_SRCPOS_M1       0x018
-#define VIA_REG_LINE_K1K2_M1    0x018
-#define VIA_REG_SRCBASE_M1      0x01C
-#define VIA_REG_PATADDR_M1      0x020
-#define VIA_REG_MONOPAT0_M1     0x024
-#define VIA_REG_MONOPAT1_M1     0x028
-#define VIA_REG_OFFSET_M1       0x02C
-#define VIA_REG_LINE_ERROR_M1   0x02C
-#define VIA_REG_CLIPTL_M1       0x040       /* top and left of clipping */
-#define VIA_REG_CLIPBR_M1       0x044       /* bottom and right of clipping */
-#define VIA_REG_KEYCONTROL_M1   0x048       /* color key control */
-#define VIA_REG_FGCOLOR_M1      0x04C
-#define VIA_REG_DSTCOLORKEY_M1  0x04C       /* as same as VIA_REG_FG */
-#define VIA_REG_BGCOLOR_M1      0x050
-#define VIA_REG_SRCCOLORKEY_M1  0x050       /* as same as VIA_REG_BG */
-#define VIA_REG_MONOPATFGC_M1   0x058       /* Add BG color of Pattern. */
-#define VIA_REG_MONOPATBGC_M1   0x05C       /* Add FG color of Pattern. */
-#define VIA_REG_COLORPAT_M1     0x100       /* from 0x100 to 0x1ff */
-
-/* VIA_REG_PITCH(0x38): Pitch Setting */
-#define VIA_PITCH_ENABLE        0x80000000
-
-/* defines for VIA HW cursor registers */
-#define VIA_REG_CURSOR_MODE     0x2D0
-#define VIA_REG_CURSOR_POS      0x2D4
-#define VIA_REG_CURSOR_ORG      0x2D8
-#define VIA_REG_CURSOR_BG       0x2DC
-#define VIA_REG_CURSOR_FG       0x2E0
-
-/* VIA_REG_GEMODE(0x04): GE mode */
-#define VIA_GEM_8bpp            0x00000000
-#define VIA_GEM_16bpp           0x00000100
-#define VIA_GEM_32bpp           0x00000300
-
-/* VIA_REG_GECMD(0x00): 2D Engine Command  */
-#define VIA_GEC_NOOP            0x00000000
-#define VIA_GEC_BLT             0x00000001
-#define VIA_GEC_LINE            0x00000005
-
-/* Rotate Command */
-#define VIA_GEC_ROT             0x00000008
-
-#define VIA_GEC_SRC_XY          0x00000000
-#define VIA_GEC_SRC_LINEAR      0x00000010
-#define VIA_GEC_DST_XY          0x00000000
-#define VIA_GEC_DST_LINRAT      0x00000020
-
-#define VIA_GEC_SRC_FB          0x00000000
-#define VIA_GEC_SRC_SYS         0x00000040
-#define VIA_GEC_DST_FB          0x00000000
-#define VIA_GEC_DST_SYS         0x00000080
-
-/* source is mono */
-#define VIA_GEC_SRC_MONO        0x00000100
-/* pattern is mono */
-#define VIA_GEC_PAT_MONO        0x00000200
-/* mono src is opaque */
-#define VIA_GEC_MSRC_OPAQUE     0x00000000
-/* mono src is transparent */
-#define VIA_GEC_MSRC_TRANS      0x00000400
-/* pattern is in frame buffer */
-#define VIA_GEC_PAT_FB          0x00000000
-/* pattern is from reg setting */
-#define VIA_GEC_PAT_REG         0x00000800
-
-#define VIA_GEC_CLIP_DISABLE    0x00000000
-#define VIA_GEC_CLIP_ENABLE     0x00001000
-
-#define VIA_GEC_FIXCOLOR_PAT    0x00002000
-
-#define VIA_GEC_INCX            0x00000000
-#define VIA_GEC_DECY            0x00004000
-#define VIA_GEC_INCY            0x00000000
-#define VIA_GEC_DECX            0x00008000
-/* mono pattern is opaque */
-#define VIA_GEC_MPAT_OPAQUE     0x00000000
-/* mono pattern is transparent */
-#define VIA_GEC_MPAT_TRANS      0x00010000
-
-#define VIA_GEC_MONO_UNPACK     0x00000000
-#define VIA_GEC_MONO_PACK       0x00020000
-#define VIA_GEC_MONO_DWORD      0x00000000
-#define VIA_GEC_MONO_WORD       0x00040000
-#define VIA_GEC_MONO_BYTE       0x00080000
-
-#define VIA_GEC_LASTPIXEL_ON    0x00000000
-#define VIA_GEC_LASTPIXEL_OFF   0x00100000
-#define VIA_GEC_X_MAJOR         0x00000000
-#define VIA_GEC_Y_MAJOR         0x00200000
-#define VIA_GEC_QUICK_START     0x00800000
-
-/* defines for VIA 3D registers */
-#define VIA_REG_STATUS          0x400
-#define VIA_REG_CR_TRANSET      0x41C
-#define VIA_REG_CR_TRANSPACE	0x420
-#define VIA_REG_TRANSET         0x43C
-#define VIA_REG_TRANSPACE       0x440
-
-/* VIA_REG_STATUS(0x400): Engine Status */
-
-/* Command Regulator is busy */
-#define VIA_CMD_RGTR_BUSY       0x00000080
-/* 2D Engine is busy */
-#define VIA_2D_ENG_BUSY         0x00000002
-/* 3D Engine is busy */
-#define VIA_3D_ENG_BUSY         0x00000001
-/* Virtual Queue is busy */
-#define VIA_VR_QUEUE_BUSY       0x00020000
-
-/* VIA_REG_STATUS(0x400): Engine Status for H5 */
-#define VIA_CMD_RGTR_BUSY_H5   0x00000010  /* Command Regulator is busy */
-#define VIA_2D_ENG_BUSY_H5     0x00000002  /* 2D Engine is busy */
-#define VIA_3D_ENG_BUSY_H5     0x00001FE1  /* 3D Engine is busy */
-#define VIA_VR_QUEUE_BUSY_H5   0x00000004  /* Virtual Queue is busy */
-
-/* VIA_REG_STATUS(0x400): Engine Status for VT3353/3409 */
-#define VIA_CMD_RGTR_BUSY_M1   0x00000010  /* Command Regulator is busy */
-#define VIA_2D_ENG_BUSY_M1     0x00000002  /* 2D Engine is busy */
-#define VIA_3D_ENG_BUSY_M1     0x00001FE1  /* 3D Engine is busy */
-#define VIA_VR_QUEUE_BUSY_M1   0x00000004  /* Virtual Queue is busy */
-
-#define MAXLOOP                 0xFFFFFF
-
-#define VIA_BITBLT_COLOR	1
-#define VIA_BITBLT_MONO		2
-#define VIA_BITBLT_FILL		3
-
-int viafb_setup_engine(struct fb_info *info);
-void viafb_reset_engine(struct viafb_par *viapar);
-void viafb_show_hw_cursor(struct fb_info *info, int Status);
-void viafb_wait_engine_idle(struct fb_info *info);
-
-#endif /* __ACCEL_H__ */
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
deleted file mode 100644
index d32a5076c20f..000000000000
--- a/drivers/video/via/chip.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#ifndef __CHIP_H__
-#define __CHIP_H__
-
-#include "global.h"
-
-/***************************************/
-/* Definition Graphic Chip Information */
-/***************************************/
-
-#define     PCI_VIA_VENDOR_ID       0x1106
-
-/* Define VIA Graphic Chip Name */
-#define     UNICHROME_CLE266        1
-#define     UNICHROME_CLE266_DID    0x3122
-#define     CLE266_REVISION_AX      0x0A
-#define     CLE266_REVISION_CX      0x0C
-
-#define     UNICHROME_K400          2
-#define     UNICHROME_K400_DID      0x7205
-
-#define     UNICHROME_K800          3
-#define     UNICHROME_K800_DID      0x3108
-
-#define     UNICHROME_PM800         4
-#define     UNICHROME_PM800_DID     0x3118
-
-#define     UNICHROME_CN700         5
-#define     UNICHROME_CN700_DID     0x3344
-
-#define     UNICHROME_CX700         6
-#define     UNICHROME_CX700_DID     0x3157
-#define     CX700_REVISION_700      0x0
-#define     CX700_REVISION_700M     0x1
-#define     CX700_REVISION_700M2    0x2
-
-#define     UNICHROME_CN750         7
-#define     UNICHROME_CN750_DID     0x3225
-
-#define     UNICHROME_K8M890        8
-#define     UNICHROME_K8M890_DID    0x3230
-
-#define     UNICHROME_P4M890        9
-#define     UNICHROME_P4M890_DID    0x3343
-
-#define     UNICHROME_P4M900        10
-#define     UNICHROME_P4M900_DID    0x3371
-
-#define     UNICHROME_VX800         11
-#define     UNICHROME_VX800_DID     0x1122
-
-#define     UNICHROME_VX855         12
-#define     UNICHROME_VX855_DID     0x5122
-
-#define     UNICHROME_VX900         13
-#define     UNICHROME_VX900_DID     0x7122
-
-/**************************************************/
-/* Definition TMDS Trasmitter Information         */
-/**************************************************/
-
-/* Definition TMDS Trasmitter Index */
-#define     NON_TMDS_TRANSMITTER    0x00
-#define     VT1632_TMDS             0x01
-#define     INTEGRATED_TMDS         0x42
-
-/* Definition TMDS Trasmitter I2C Slave Address */
-#define     VT1632_TMDS_I2C_ADDR    0x10
-
-/**************************************************/
-/* Definition LVDS Trasmitter Information         */
-/**************************************************/
-
-/* Definition LVDS Trasmitter Index */
-#define     NON_LVDS_TRANSMITTER    0x00
-#define     VT1631_LVDS             0x01
-#define     VT1636_LVDS             0x0E
-#define     INTEGRATED_LVDS         0x41
-
-/* Definition Digital Transmitter Mode */
-#define     TX_DATA_12_BITS         0x01
-#define     TX_DATA_24_BITS         0x02
-#define     TX_DATA_DDR_MODE        0x04
-#define     TX_DATA_SDR_MODE        0x08
-
-/* Definition LVDS Trasmitter I2C Slave Address */
-#define     VT1631_LVDS_I2C_ADDR    0x70
-#define     VT3271_LVDS_I2C_ADDR    0x80
-#define     VT1636_LVDS_I2C_ADDR    0x80
-
-struct tmds_chip_information {
-	int tmds_chip_name;
-	int tmds_chip_slave_addr;
-	int output_interface;
-	int i2c_port;
-};
-
-struct lvds_chip_information {
-	int lvds_chip_name;
-	int lvds_chip_slave_addr;
-	int output_interface;
-	int i2c_port;
-};
-
-/* The type of 2D engine */
-enum via_2d_engine {
-	VIA_2D_ENG_H2,
-	VIA_2D_ENG_H5,
-	VIA_2D_ENG_M1,
-};
-
-struct chip_information {
-	int gfx_chip_name;
-	int gfx_chip_revision;
-	enum via_2d_engine twod_engine;
-	struct tmds_chip_information tmds_chip_info;
-	struct lvds_chip_information lvds_chip_info;
-	struct lvds_chip_information lvds_chip_info2;
-};
-
-struct tmds_setting_information {
-	int iga_path;
-	int h_active;
-	int v_active;
-	int max_pixel_clock;
-};
-
-struct lvds_setting_information {
-	int iga_path;
-	int lcd_panel_hres;
-	int lcd_panel_vres;
-	int display_method;
-	int device_lcd_dualedge;
-	int LCDDithering;
-	int lcd_mode;
-	u32 vclk;		/*panel mode clock value */
-};
-
-struct GFX_DPA_SETTING {
-	int ClkRangeIndex;
-	u8 DVP0;		/* CR96[3:0] */
-	u8 DVP0DataDri_S1;	/* SR2A[5]   */
-	u8 DVP0DataDri_S;	/* SR1B[1]   */
-	u8 DVP0ClockDri_S1;	/* SR2A[4]   */
-	u8 DVP0ClockDri_S;	/* SR1E[2]   */
-	u8 DVP1;		/* CR9B[3:0] */
-	u8 DVP1Driving;		/* SR65[3:0], Data and Clock driving */
-	u8 DFPHigh;		/* CR97[3:0] */
-	u8 DFPLow;		/* CR99[3:0] */
-
-};
-
-struct VT1636_DPA_SETTING {
-	u8 CLK_SEL_ST1;
-	u8 CLK_SEL_ST2;
-};
-#endif /* __CHIP_H__ */
diff --git a/drivers/video/via/debug.h b/drivers/video/via/debug.h
deleted file mode 100644
index 86eacc2017f3..000000000000
--- a/drivers/video/via/debug.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#ifndef __DEBUG_H__
-#define __DEBUG_H__
-
-#ifndef VIAFB_DEBUG
-#define VIAFB_DEBUG 0
-#endif
-
-#if VIAFB_DEBUG
-#define DEBUG_MSG(f, a...)   printk(f, ## a)
-#else
-#define DEBUG_MSG(f, a...)
-#endif
-
-#define VIAFB_WARN 0
-#if VIAFB_WARN
-#define WARN_MSG(f, a...)   printk(f, ## a)
-#else
-#define WARN_MSG(f, a...)
-#endif
-
-#endif /* __DEBUG_H__ */
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
deleted file mode 100644
index 7789553952d3..000000000000
--- a/drivers/video/via/dvi.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <linux/via-core.h>
-#include <linux/via_i2c.h>
-#include "global.h"
-
-static void tmds_register_write(int index, u8 data);
-static int tmds_register_read(int index);
-static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
-static void dvi_get_panel_size_from_DDCv1(
-	struct tmds_chip_information *tmds_chip,
-	struct tmds_setting_information *tmds_setting);
-static int viafb_dvi_query_EDID(void);
-
-static inline bool check_tmds_chip(int device_id_subaddr, int device_id)
-{
-	return tmds_register_read(device_id_subaddr) == device_id;
-}
-
-void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
-			 struct tmds_setting_information *tmds_setting)
-{
-	DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
-
-	viafb_dvi_sense();
-	if (viafb_dvi_query_EDID() == 1)
-		dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
-
-	return;
-}
-
-bool viafb_tmds_trasmitter_identify(void)
-{
-	unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
-
-	/* Turn on ouputting pad */
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_K8M890:
-	    /*=* DFP Low Pad on *=*/
-		sr2a = viafb_read_reg(VIASR, SR2A);
-		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
-		break;
-
-	case UNICHROME_P4M900:
-	case UNICHROME_P4M890:
-		/* DFP Low Pad on */
-		sr2a = viafb_read_reg(VIASR, SR2A);
-		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
-		/* DVP0 Pad on */
-		sr1e = viafb_read_reg(VIASR, SR1E);
-		viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
-		break;
-
-	default:
-	    /* DVP0/DVP1 Pad on */
-		sr1e = viafb_read_reg(VIASR, SR1E);
-		viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
-			BIT5 + BIT6 + BIT7);
-	    /* SR3E[1]Multi-function selection:
-	    0 = Emulate I2C and DDC bus by GPIO2/3/4. */
-		sr3e = viafb_read_reg(VIASR, SR3E);
-		viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
-		break;
-	}
-
-	/* Check for VT1632: */
-	viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
-	viaparinfo->chip_info->
-		tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
-	viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;
-	if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
-		/*
-		 * Currently only support 12bits,dual edge,add 24bits mode later
-		 */
-		tmds_register_write(0x08, 0x3b);
-
-		DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
-		DEBUG_MSG(KERN_INFO "\n %2d",
-			  viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
-		DEBUG_MSG(KERN_INFO "\n %2d",
-			  viaparinfo->chip_info->tmds_chip_info.i2c_port);
-		return true;
-	} else {
-		viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;
-		if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
-			tmds_register_write(0x08, 0x3b);
-			DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
-			DEBUG_MSG(KERN_INFO "\n %2d",
-				  viaparinfo->chip_info->
-				  tmds_chip_info.tmds_chip_name);
-			DEBUG_MSG(KERN_INFO "\n %2d",
-				  viaparinfo->chip_info->
-				  tmds_chip_info.i2c_port);
-			return true;
-		}
-	}
-
-	viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
-
-	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
-	    ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
-	     (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
-		DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
-		return true;
-	}
-
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_K8M890:
-		viafb_write_reg(SR2A, VIASR, sr2a);
-		break;
-
-	case UNICHROME_P4M900:
-	case UNICHROME_P4M890:
-		viafb_write_reg(SR2A, VIASR, sr2a);
-		viafb_write_reg(SR1E, VIASR, sr1e);
-		break;
-
-	default:
-		viafb_write_reg(SR1E, VIASR, sr1e);
-		viafb_write_reg(SR3E, VIASR, sr3e);
-		break;
-	}
-
-	viaparinfo->chip_info->
-		tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
-	viaparinfo->chip_info->tmds_chip_info.
-		tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
-	return false;
-}
-
-static void tmds_register_write(int index, u8 data)
-{
-	viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
-			    viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
-			    index, data);
-}
-
-static int tmds_register_read(int index)
-{
-	u8 data;
-
-	viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
-			   (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
-			   (u8) index, &data);
-	return data;
-}
-
-static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
-{
-	viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port,
-			    (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
-			    (u8) index, buff, buff_len);
-	return 0;
-}
-
-/* DVI Set Mode */
-void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
-	u16 cxres, u16 cyres, int iga)
-{
-	struct fb_var_screeninfo dvi_var = *var;
-	const struct fb_videomode *rb_mode;
-	int maxPixelClock;
-
-	maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
-	if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
-		rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
-		if (rb_mode)
-			viafb_fill_var_timing_info(&dvi_var, rb_mode);
-	}
-
-	viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga);
-}
-
-/* Sense DVI Connector */
-int viafb_dvi_sense(void)
-{
-	u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
-		RegCR93 = 0, RegCR9B = 0, data;
-	int ret = false;
-
-	DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
-
-	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
-		/* DI1 Pad on */
-		RegSR1E = viafb_read_reg(VIASR, SR1E);
-		viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
-
-		/* CR6B[0]VCK Input Selection: 1 = External clock. */
-		RegCR6B = viafb_read_reg(VIACR, CR6B);
-		viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
-
-		/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
-		   [0] Software Control Power Sequence */
-		RegCR91 = viafb_read_reg(VIACR, CR91);
-		viafb_write_reg(CR91, VIACR, 0x1D);
-
-		/* CR93[7] DI1 Data Source Selection: 1 = DSP2.
-		   CR93[5] DI1 Clock Source: 1 = internal.
-		   CR93[4] DI1 Clock Polarity.
-		   CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
-		RegCR93 = viafb_read_reg(VIACR, CR93);
-		viafb_write_reg(CR93, VIACR, 0x01);
-	} else {
-		/* DVP0/DVP1 Pad on */
-		RegSR1E = viafb_read_reg(VIASR, SR1E);
-		viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
-
-		/* SR3E[1]Multi-function selection:
-		   0 = Emulate I2C and DDC bus by GPIO2/3/4. */
-		RegSR3E = viafb_read_reg(VIASR, SR3E);
-		viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
-
-		/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
-		   [0] Software Control Power Sequence */
-		RegCR91 = viafb_read_reg(VIACR, CR91);
-		viafb_write_reg(CR91, VIACR, 0x1D);
-
-		/*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
-		display.CR9B[2:0] DVP1 Clock Adjust */
-		RegCR9B = viafb_read_reg(VIACR, CR9B);
-		viafb_write_reg(CR9B, VIACR, 0x01);
-	}
-
-	data = (u8) tmds_register_read(0x09);
-	if (data & 0x04)
-		ret = true;
-
-	if (ret == false) {
-		if (viafb_dvi_query_EDID())
-			ret = true;
-	}
-
-	/* Restore status */
-	viafb_write_reg(SR1E, VIASR, RegSR1E);
-	viafb_write_reg(CR91, VIACR, RegCR91);
-	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
-		viafb_write_reg(CR6B, VIACR, RegCR6B);
-		viafb_write_reg(CR93, VIACR, RegCR93);
-	} else {
-		viafb_write_reg(SR3E, VIASR, RegSR3E);
-		viafb_write_reg(CR9B, VIACR, RegCR9B);
-	}
-
-	return ret;
-}
-
-/* Query Flat Panel's EDID Table Version Through DVI Connector */
-static int viafb_dvi_query_EDID(void)
-{
-	u8 data0, data1;
-	int restore;
-
-	DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
-
-	restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
-	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
-
-	data0 = (u8) tmds_register_read(0x00);
-	data1 = (u8) tmds_register_read(0x01);
-	if ((data0 == 0) && (data1 == 0xFF)) {
-		viaparinfo->chip_info->
-			tmds_chip_info.tmds_chip_slave_addr = restore;
-		return EDID_VERSION_1;	/* Found EDID1 Table */
-	}
-
-	return false;
-}
-
-/* Get Panel Size Using EDID1 Table */
-static void dvi_get_panel_size_from_DDCv1(
-	struct tmds_chip_information *tmds_chip,
-	struct tmds_setting_information *tmds_setting)
-{
-	int i, restore;
-	unsigned char EDID_DATA[18];
-
-	DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
-
-	restore = tmds_chip->tmds_chip_slave_addr;
-	tmds_chip->tmds_chip_slave_addr = 0xA0;
-	for (i = 0x25; i < 0x6D; i++) {
-		switch (i) {
-		case 0x36:
-		case 0x48:
-		case 0x5A:
-		case 0x6C:
-			tmds_register_read_bytes(i, EDID_DATA, 10);
-			if (!(EDID_DATA[0] || EDID_DATA[1])) {
-				/* The first two byte must be zero. */
-				if (EDID_DATA[3] == 0xFD) {
-					/* To get max pixel clock. */
-					tmds_setting->max_pixel_clock =
-						EDID_DATA[9] * 10;
-				}
-			}
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
-		tmds_setting->max_pixel_clock);
-	tmds_chip->tmds_chip_slave_addr = restore;
-}
-
-/* If Disable DVI, turn off pad */
-void viafb_dvi_disable(void)
-{
-	if (viaparinfo->chip_info->
-		tmds_chip_info.output_interface == INTERFACE_TMDS)
-		/* Turn off TMDS power. */
-		viafb_write_reg(CRD2, VIACR,
-		viafb_read_reg(VIACR, CRD2) | 0x08);
-}
-
-static void dvi_patch_skew_dvp0(void)
-{
-	/* Reset data driving first: */
-	viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
-	viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
-
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_P4M890:
-		{
-			if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
-				(viaparinfo->tmds_setting_info->v_active ==
-				1200))
-				viafb_write_reg_mask(CR96, VIACR, 0x03,
-					       BIT0 + BIT1 + BIT2);
-			else
-				viafb_write_reg_mask(CR96, VIACR, 0x07,
-					       BIT0 + BIT1 + BIT2);
-			break;
-		}
-
-	case UNICHROME_P4M900:
-		{
-			viafb_write_reg_mask(CR96, VIACR, 0x07,
-				       BIT0 + BIT1 + BIT2 + BIT3);
-			viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
-			viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
-			break;
-		}
-
-	default:
-		{
-			break;
-		}
-	}
-}
-
-static void dvi_patch_skew_dvp_low(void)
-{
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_K8M890:
-		{
-			viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
-			break;
-		}
-
-	case UNICHROME_P4M900:
-		{
-			viafb_write_reg_mask(CR99, VIACR, 0x08,
-				       BIT0 + BIT1 + BIT2 + BIT3);
-			break;
-		}
-
-	case UNICHROME_P4M890:
-		{
-			viafb_write_reg_mask(CR99, VIACR, 0x0F,
-				       BIT0 + BIT1 + BIT2 + BIT3);
-			break;
-		}
-
-	default:
-		{
-			break;
-		}
-	}
-}
-
-/* If Enable DVI, turn off pad */
-void viafb_dvi_enable(void)
-{
-	u8 data;
-
-	switch (viaparinfo->chip_info->tmds_chip_info.output_interface) {
-	case INTERFACE_DVP0:
-		viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
-		viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
-		dvi_patch_skew_dvp0();
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			tmds_register_write(0x88, 0x3b);
-		else
-			/*clear CR91[5] to direct on display period
-			   in the secondary diplay path */
-			via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
-		break;
-
-	case INTERFACE_DVP1:
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
-
-		/*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			tmds_register_write(0x88, 0x3b);
-		else
-			/*clear CR91[5] to direct on display period
-			  in the secondary diplay path */
-			via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
-
-		/*fix DVI cannot enable on EPIA-M board */
-		if (viafb_platform_epia_dvi == 1) {
-			viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
-			viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
-			if (viafb_bus_width == 24) {
-				if (viafb_device_lcd_dualedge == 1)
-					data = 0x3F;
-				else
-					data = 0x37;
-				viafb_i2c_writebyte(viaparinfo->chip_info->
-					tmds_chip_info.i2c_port,
-					viaparinfo->chip_info->
-					tmds_chip_info.tmds_chip_slave_addr,
-					0x08, data);
-			}
-		}
-		break;
-
-	case INTERFACE_DFP_HIGH:
-		if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
-			via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
-
-		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
-		break;
-
-	case INTERFACE_DFP_LOW:
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			break;
-
-		dvi_patch_skew_dvp_low();
-		via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
-		break;
-
-	case INTERFACE_TMDS:
-		/* Turn on Display period in the panel path. */
-		viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
-
-		/* Turn on TMDS power. */
-		viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
-		break;
-	}
-
-	if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
-		/* Disable LCD Scaling */
-		viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
-	}
-}
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
deleted file mode 100644
index 4c6bfba57d11..000000000000
--- a/drivers/video/via/dvi.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __DVI_H__
-#define __DVI_H__
-
-/*Definition TMDS Device ID register*/
-#define     VT1632_DEVICE_ID_REG        0x02
-#define     VT1632_DEVICE_ID            0x92
-
-#define     GET_DVI_SIZE_BY_SYSTEM_BIOS     0x01
-#define     GET_DVI_SIZE_BY_VGA_BIOS        0x02
-#define     GET_DVI_SZIE_BY_HW_STRAPPING    0x03
-
-/* Definition DVI Panel ID*/
-/* Resolution: 640x480,   Channel: single, Dithering: Enable */
-#define     DVI_PANEL_ID0_640X480       0x00
-/* Resolution: 800x600,   Channel: single, Dithering: Enable */
-#define     DVI_PANEL_ID1_800x600       0x01
-/* Resolution: 1024x768,  Channel: single, Dithering: Enable */
-#define     DVI_PANEL_ID1_1024x768      0x02
-/* Resolution: 1280x768,  Channel: single, Dithering: Enable */
-#define     DVI_PANEL_ID1_1280x768      0x03
-/* Resolution: 1280x1024, Channel: dual,   Dithering: Enable */
-#define     DVI_PANEL_ID1_1280x1024     0x04
-/* Resolution: 1400x1050, Channel: dual,   Dithering: Enable */
-#define     DVI_PANEL_ID1_1400x1050     0x05
-/* Resolution: 1600x1200, Channel: dual,   Dithering: Enable */
-#define     DVI_PANEL_ID1_1600x1200     0x06
-
-/* Define the version of EDID*/
-#define     EDID_VERSION_1      1
-#define     EDID_VERSION_2      2
-
-#define     DEV_CONNECT_DVI     0x01
-#define     DEV_CONNECT_HDMI    0x02
-
-int viafb_dvi_sense(void);
-void viafb_dvi_disable(void);
-void viafb_dvi_enable(void);
-bool viafb_tmds_trasmitter_identify(void);
-void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
-	struct tmds_setting_information *tmds_setting);
-void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
-	u16 cxres, u16 cyres, int iga);
-
-#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
deleted file mode 100644
index 3102171c1674..000000000000
--- a/drivers/video/via/global.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#include "global.h"
-int viafb_platform_epia_dvi = STATE_OFF;
-int viafb_device_lcd_dualedge = STATE_OFF;
-int viafb_bus_width = 12;
-int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
-int viafb_DeviceStatus = CRT_Device;
-int viafb_hotplug;
-int viafb_refresh = 60;
-int viafb_refresh1 = 60;
-int viafb_lcd_dsp_method = LCD_EXPANDSION;
-int viafb_lcd_mode = LCD_OPENLDI;
-int viafb_CRT_ON = 1;
-int viafb_DVI_ON;
-int viafb_LCD_ON ;
-int viafb_LCD2_ON;
-int viafb_SAMM_ON;
-int viafb_dual_fb;
-unsigned int viafb_second_xres = 640;
-unsigned int viafb_second_yres = 480;
-int viafb_hotplug_Xres = 640;
-int viafb_hotplug_Yres = 480;
-int viafb_hotplug_bpp = 32;
-int viafb_hotplug_refresh = 60;
-int viafb_primary_dev = None_Device;
-int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
-struct fb_info *viafbinfo;
-struct fb_info *viafbinfo1;
-struct viafb_par *viaparinfo;
-struct viafb_par *viaparinfo1;
-
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
deleted file mode 100644
index 275dbbbd6b81..000000000000
--- a/drivers/video/via/global.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GLOBAL_H__
-#define __GLOBAL_H__
-
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/console.h>
-#include <linux/timer.h>
-
-#include "debug.h"
-
-#include "viafbdev.h"
-#include "chip.h"
-#include "accel.h"
-#include "share.h"
-#include "dvi.h"
-#include "viamode.h"
-#include "hw.h"
-
-#include "lcd.h"
-#include "ioctl.h"
-#include "via_utility.h"
-#include "vt1636.h"
-#include "tblDPASetting.h"
-
-/* External struct*/
-
-extern int viafb_platform_epia_dvi;
-extern int viafb_device_lcd_dualedge;
-extern int viafb_bus_width;
-extern int viafb_display_hardware_layout;
-extern struct offset offset_reg;
-extern struct viafb_par *viaparinfo;
-extern struct viafb_par *viaparinfo1;
-extern struct fb_info *viafbinfo;
-extern struct fb_info *viafbinfo1;
-extern int viafb_DeviceStatus;
-extern int viafb_refresh;
-extern int viafb_refresh1;
-extern int viafb_lcd_dsp_method;
-extern int viafb_lcd_mode;
-
-extern int viafb_CRT_ON;
-extern unsigned int viafb_second_xres;
-extern unsigned int viafb_second_yres;
-extern int viafb_hotplug_Xres;
-extern int viafb_hotplug_Yres;
-extern int viafb_hotplug_bpp;
-extern int viafb_hotplug_refresh;
-extern int viafb_primary_dev;
-
-extern int viafb_lcd_panel_id;
-
-#endif /* __GLOBAL_H__ */
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
deleted file mode 100644
index 22450908306c..000000000000
--- a/drivers/video/via/hw.c
+++ /dev/null
@@ -1,2134 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/via-core.h>
-#include <asm/olpc.h>
-#include "global.h"
-#include "via_clock.h"
-
-static struct pll_limit cle266_pll_limits[] = {
-	{19, 19, 4, 0},
-	{26, 102, 5, 0},
-	{53, 112, 6, 0},
-	{41, 100, 7, 0},
-	{83, 108, 8, 0},
-	{87, 118, 9, 0},
-	{95, 115, 12, 0},
-	{108, 108, 13, 0},
-	{83, 83, 17, 0},
-	{67, 98, 20, 0},
-	{121, 121, 24, 0},
-	{99, 99, 29, 0},
-	{33, 33, 3, 1},
-	{15, 23, 4, 1},
-	{37, 121, 5, 1},
-	{82, 82, 6, 1},
-	{31, 84, 7, 1},
-	{83, 83, 8, 1},
-	{76, 127, 9, 1},
-	{33, 121, 4, 2},
-	{91, 118, 5, 2},
-	{83, 109, 6, 2},
-	{90, 90, 7, 2},
-	{93, 93, 2, 3},
-	{53, 53, 3, 3},
-	{73, 117, 4, 3},
-	{101, 127, 5, 3},
-	{99, 99, 7, 3}
-};
-
-static struct pll_limit k800_pll_limits[] = {
-	{22, 22, 2, 0},
-	{28, 28, 3, 0},
-	{81, 112, 3, 1},
-	{86, 166, 4, 1},
-	{109, 153, 5, 1},
-	{66, 116, 3, 2},
-	{93, 137, 4, 2},
-	{117, 208, 5, 2},
-	{30, 30, 2, 3},
-	{69, 125, 3, 3},
-	{89, 161, 4, 3},
-	{121, 208, 5, 3},
-	{66, 66, 2, 4},
-	{85, 85, 3, 4},
-	{141, 161, 4, 4},
-	{177, 177, 5, 4}
-};
-
-static struct pll_limit cx700_pll_limits[] = {
-	{98, 98, 3, 1},
-	{86, 86, 4, 1},
-	{109, 208, 5, 1},
-	{68, 68, 2, 2},
-	{95, 116, 3, 2},
-	{93, 166, 4, 2},
-	{110, 206, 5, 2},
-	{174, 174, 7, 2},
-	{82, 109, 3, 3},
-	{117, 161, 4, 3},
-	{112, 208, 5, 3},
-	{141, 202, 5, 4}
-};
-
-static struct pll_limit vx855_pll_limits[] = {
-	{86, 86, 4, 1},
-	{108, 208, 5, 1},
-	{110, 208, 5, 2},
-	{83, 112, 3, 3},
-	{103, 161, 4, 3},
-	{112, 209, 5, 3},
-	{142, 161, 4, 4},
-	{141, 176, 5, 4}
-};
-
-/* according to VIA Technologies these values are based on experiment */
-static struct io_reg scaling_parameters[] = {
-	{VIACR, CR7A, 0xFF, 0x01},	/* LCD Scaling Parameter 1 */
-	{VIACR, CR7B, 0xFF, 0x02},	/* LCD Scaling Parameter 2 */
-	{VIACR, CR7C, 0xFF, 0x03},	/* LCD Scaling Parameter 3 */
-	{VIACR, CR7D, 0xFF, 0x04},	/* LCD Scaling Parameter 4 */
-	{VIACR, CR7E, 0xFF, 0x07},	/* LCD Scaling Parameter 5 */
-	{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Scaling Parameter 6 */
-	{VIACR, CR80, 0xFF, 0x0D},	/* LCD Scaling Parameter 7 */
-	{VIACR, CR81, 0xFF, 0x13},	/* LCD Scaling Parameter 8 */
-	{VIACR, CR82, 0xFF, 0x16},	/* LCD Scaling Parameter 9 */
-	{VIACR, CR83, 0xFF, 0x19},	/* LCD Scaling Parameter 10 */
-	{VIACR, CR84, 0xFF, 0x1C},	/* LCD Scaling Parameter 11 */
-	{VIACR, CR85, 0xFF, 0x1D},	/* LCD Scaling Parameter 12 */
-	{VIACR, CR86, 0xFF, 0x1E},	/* LCD Scaling Parameter 13 */
-	{VIACR, CR87, 0xFF, 0x1F},	/* LCD Scaling Parameter 14 */
-};
-
-static struct io_reg common_vga[] = {
-	{VIACR, CR07, 0x10, 0x10}, /* [0] vertical total (bit 8)
-					[1] vertical display end (bit 8)
-					[2] vertical retrace start (bit 8)
-					[3] start vertical blanking (bit 8)
-					[4] line compare (bit 8)
-					[5] vertical total (bit 9)
-					[6] vertical display end (bit 9)
-					[7] vertical retrace start (bit 9) */
-	{VIACR, CR08, 0xFF, 0x00}, /* [0-4] preset row scan
-					[5-6] byte panning */
-	{VIACR, CR09, 0xDF, 0x40}, /* [0-4] max scan line
-					[5] start vertical blanking (bit 9)
-					[6] line compare (bit 9)
-					[7] scan doubling */
-	{VIACR, CR0A, 0xFF, 0x1E}, /* [0-4] cursor start
-					[5] cursor disable */
-	{VIACR, CR0B, 0xFF, 0x00}, /* [0-4] cursor end
-					[5-6] cursor skew */
-	{VIACR, CR0E, 0xFF, 0x00}, /* [0-7] cursor location (high) */
-	{VIACR, CR0F, 0xFF, 0x00}, /* [0-7] cursor location (low) */
-	{VIACR, CR11, 0xF0, 0x80}, /* [0-3] vertical retrace end
-					[6] memory refresh bandwidth
-					[7] CRTC register protect enable */
-	{VIACR, CR14, 0xFF, 0x00}, /* [0-4] underline location
-					[5] divide memory address clock by 4
-					[6] double word addressing */
-	{VIACR, CR17, 0xFF, 0x63}, /* [0-1] mapping of display address 13-14
-					[2] divide scan line clock by 2
-					[3] divide memory address clock by 2
-					[5] address wrap
-					[6] byte mode select
-					[7] sync enable */
-	{VIACR, CR18, 0xFF, 0xFF}, /* [0-7] line compare */
-};
-
-static struct fifo_depth_select display_fifo_depth_reg = {
-	/* IGA1 FIFO Depth_Select */
-	{IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
-	/* IGA2 FIFO Depth_Select */
-	{IGA2_FIFO_DEPTH_SELECT_REG_NUM,
-	 {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
-};
-
-static struct fifo_threshold_select fifo_threshold_select_reg = {
-	/* IGA1 FIFO Threshold Select */
-	{IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
-	/* IGA2 FIFO Threshold Select */
-	{IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
-};
-
-static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
-	/* IGA1 FIFO High Threshold Select */
-	{IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
-	/* IGA2 FIFO High Threshold Select */
-	{IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
-};
-
-static struct display_queue_expire_num display_queue_expire_num_reg = {
-	/* IGA1 Display Queue Expire Num */
-	{IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
-	/* IGA2 Display Queue Expire Num */
-	{IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
-};
-
-/* Definition Fetch Count Registers*/
-static struct fetch_count fetch_count_reg = {
-	/* IGA1 Fetch Count Register */
-	{IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
-	/* IGA2 Fetch Count Register */
-	{IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
-};
-
-static struct rgbLUT palLUT_table[] = {
-	/* {R,G,B} */
-	/* Index 0x00~0x03 */
-	{0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
-								     0x2A,
-								     0x2A},
-	/* Index 0x04~0x07 */
-	{0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
-								     0x2A,
-								     0x2A},
-	/* Index 0x08~0x0B */
-	{0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
-								     0x3F,
-								     0x3F},
-	/* Index 0x0C~0x0F */
-	{0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
-								     0x3F,
-								     0x3F},
-	/* Index 0x10~0x13 */
-	{0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
-								     0x0B,
-								     0x0B},
-	/* Index 0x14~0x17 */
-	{0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
-								     0x18,
-								     0x18},
-	/* Index 0x18~0x1B */
-	{0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
-								     0x28,
-								     0x28},
-	/* Index 0x1C~0x1F */
-	{0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
-								     0x3F,
-								     0x3F},
-	/* Index 0x20~0x23 */
-	{0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
-								     0x00,
-								     0x3F},
-	/* Index 0x24~0x27 */
-	{0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
-								     0x00,
-								     0x10},
-	/* Index 0x28~0x2B */
-	{0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
-								     0x2F,
-								     0x00},
-	/* Index 0x2C~0x2F */
-	{0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
-								     0x3F,
-								     0x00},
-	/* Index 0x30~0x33 */
-	{0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
-								     0x3F,
-								     0x2F},
-	/* Index 0x34~0x37 */
-	{0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
-								     0x10,
-								     0x3F},
-	/* Index 0x38~0x3B */
-	{0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
-								     0x1F,
-								     0x3F},
-	/* Index 0x3C~0x3F */
-	{0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
-								     0x1F,
-								     0x27},
-	/* Index 0x40~0x43 */
-	{0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
-								     0x3F,
-								     0x1F},
-	/* Index 0x44~0x47 */
-	{0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
-								     0x3F,
-								     0x1F},
-	/* Index 0x48~0x4B */
-	{0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
-								     0x3F,
-								     0x37},
-	/* Index 0x4C~0x4F */
-	{0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
-								     0x27,
-								     0x3F},
-	/* Index 0x50~0x53 */
-	{0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
-								     0x2D,
-								     0x3F},
-	/* Index 0x54~0x57 */
-	{0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
-								     0x2D,
-								     0x31},
-	/* Index 0x58~0x5B */
-	{0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
-								     0x3A,
-								     0x2D},
-	/* Index 0x5C~0x5F */
-	{0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
-								     0x3F,
-								     0x2D},
-	/* Index 0x60~0x63 */
-	{0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
-								     0x3F,
-								     0x3A},
-	/* Index 0x64~0x67 */
-	{0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
-								     0x31,
-								     0x3F},
-	/* Index 0x68~0x6B */
-	{0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
-								     0x00,
-								     0x1C},
-	/* Index 0x6C~0x6F */
-	{0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
-								     0x00,
-								     0x07},
-	/* Index 0x70~0x73 */
-	{0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
-								     0x15,
-								     0x00},
-	/* Index 0x74~0x77 */
-	{0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
-								     0x1C,
-								     0x00},
-	/* Index 0x78~0x7B */
-	{0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
-								     0x1C,
-								     0x15},
-	/* Index 0x7C~0x7F */
-	{0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
-								     0x07,
-								     0x1C},
-	/* Index 0x80~0x83 */
-	{0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
-								     0x0E,
-								     0x1C},
-	/* Index 0x84~0x87 */
-	{0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
-								     0x0E,
-								     0x11},
-	/* Index 0x88~0x8B */
-	{0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
-								     0x18,
-								     0x0E},
-	/* Index 0x8C~0x8F */
-	{0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
-								     0x1C,
-								     0x0E},
-	/* Index 0x90~0x93 */
-	{0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
-								     0x1C,
-								     0x18},
-	/* Index 0x94~0x97 */
-	{0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
-								     0x11,
-								     0x1C},
-	/* Index 0x98~0x9B */
-	{0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
-								     0x14,
-								     0x1C},
-	/* Index 0x9C~0x9F */
-	{0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
-								     0x14,
-								     0x16},
-	/* Index 0xA0~0xA3 */
-	{0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
-								     0x1A,
-								     0x14},
-	/* Index 0xA4~0xA7 */
-	{0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
-								     0x1C,
-								     0x14},
-	/* Index 0xA8~0xAB */
-	{0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
-								     0x1C,
-								     0x1A},
-	/* Index 0xAC~0xAF */
-	{0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
-								     0x16,
-								     0x1C},
-	/* Index 0xB0~0xB3 */
-	{0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
-								     0x00,
-								     0x10},
-	/* Index 0xB4~0xB7 */
-	{0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
-								     0x00,
-								     0x04},
-	/* Index 0xB8~0xBB */
-	{0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
-								     0x0C,
-								     0x00},
-	/* Index 0xBC~0xBF */
-	{0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
-								     0x10,
-								     0x00},
-	/* Index 0xC0~0xC3 */
-	{0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
-								     0x10,
-								     0x0C},
-	/* Index 0xC4~0xC7 */
-	{0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
-								     0x04,
-								     0x10},
-	/* Index 0xC8~0xCB */
-	{0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
-								     0x08,
-								     0x10},
-	/* Index 0xCC~0xCF */
-	{0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
-								     0x08,
-								     0x0A},
-	/* Index 0xD0~0xD3 */
-	{0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
-								     0x0E,
-								     0x08},
-	/* Index 0xD4~0xD7 */
-	{0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
-								     0x10,
-								     0x08},
-	/* Index 0xD8~0xDB */
-	{0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
-								     0x10,
-								     0x0E},
-	/* Index 0xDC~0xDF */
-	{0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
-								     0x0A,
-								     0x10},
-	/* Index 0xE0~0xE3 */
-	{0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
-								     0x0B,
-								     0x10},
-	/* Index 0xE4~0xE7 */
-	{0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
-								     0x0B,
-								     0x0C},
-	/* Index 0xE8~0xEB */
-	{0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
-								     0x0F,
-								     0x0B},
-	/* Index 0xEC~0xEF */
-	{0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
-								     0x10,
-								     0x0B},
-	/* Index 0xF0~0xF3 */
-	{0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
-								     0x10,
-								     0x0F},
-	/* Index 0xF4~0xF7 */
-	{0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
-								     0x0C,
-								     0x10},
-	/* Index 0xF8~0xFB */
-	{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
-								     0x00,
-								     0x00},
-	/* Index 0xFC~0xFF */
-	{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
-								     0x00,
-								     0x00}
-};
-
-static struct via_device_mapping device_mapping[] = {
-	{VIA_LDVP0, "LDVP0"},
-	{VIA_LDVP1, "LDVP1"},
-	{VIA_DVP0, "DVP0"},
-	{VIA_CRT, "CRT"},
-	{VIA_DVP1, "DVP1"},
-	{VIA_LVDS1, "LVDS1"},
-	{VIA_LVDS2, "LVDS2"}
-};
-
-/* structure with function pointers to support clock control */
-static struct via_clock clock;
-
-static void load_fix_bit_crtc_reg(void);
-static void init_gfx_chip_info(int chip_type);
-static void init_tmds_chip_info(void);
-static void init_lvds_chip_info(void);
-static void device_screen_off(void);
-static void device_screen_on(void);
-static void set_display_channel(void);
-static void device_off(void);
-static void device_on(void);
-static void enable_second_display_channel(void);
-static void disable_second_display_channel(void);
-
-void viafb_lock_crt(void)
-{
-	viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
-}
-
-void viafb_unlock_crt(void)
-{
-	viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
-	viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
-}
-
-static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
-{
-	outb(index, LUT_INDEX_WRITE);
-	outb(r, LUT_DATA);
-	outb(g, LUT_DATA);
-	outb(b, LUT_DATA);
-}
-
-static u32 get_dvi_devices(int output_interface)
-{
-	switch (output_interface) {
-	case INTERFACE_DVP0:
-		return VIA_DVP0 | VIA_LDVP0;
-
-	case INTERFACE_DVP1:
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			return VIA_LDVP1;
-		else
-			return VIA_DVP1;
-
-	case INTERFACE_DFP_HIGH:
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			return 0;
-		else
-			return VIA_LVDS2 | VIA_DVP0;
-
-	case INTERFACE_DFP_LOW:
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-			return 0;
-		else
-			return VIA_DVP1 | VIA_LVDS1;
-
-	case INTERFACE_TMDS:
-		return VIA_LVDS1;
-	}
-
-	return 0;
-}
-
-static u32 get_lcd_devices(int output_interface)
-{
-	switch (output_interface) {
-	case INTERFACE_DVP0:
-		return VIA_DVP0;
-
-	case INTERFACE_DVP1:
-		return VIA_DVP1;
-
-	case INTERFACE_DFP_HIGH:
-		return VIA_LVDS2 | VIA_DVP0;
-
-	case INTERFACE_DFP_LOW:
-		return VIA_LVDS1 | VIA_DVP1;
-
-	case INTERFACE_DFP:
-		return VIA_LVDS1 | VIA_LVDS2;
-
-	case INTERFACE_LVDS0:
-	case INTERFACE_LVDS0LVDS1:
-		return VIA_LVDS1;
-
-	case INTERFACE_LVDS1:
-		return VIA_LVDS2;
-	}
-
-	return 0;
-}
-
-/*Set IGA path for each device*/
-void viafb_set_iga_path(void)
-{
-	int crt_iga_path = 0;
-
-	if (viafb_SAMM_ON == 1) {
-		if (viafb_CRT_ON) {
-			if (viafb_primary_dev == CRT_Device)
-				crt_iga_path = IGA1;
-			else
-				crt_iga_path = IGA2;
-		}
-
-		if (viafb_DVI_ON) {
-			if (viafb_primary_dev == DVI_Device)
-				viaparinfo->tmds_setting_info->iga_path = IGA1;
-			else
-				viaparinfo->tmds_setting_info->iga_path = IGA2;
-		}
-
-		if (viafb_LCD_ON) {
-			if (viafb_primary_dev == LCD_Device) {
-				if (viafb_dual_fb &&
-					(viaparinfo->chip_info->gfx_chip_name ==
-					UNICHROME_CLE266)) {
-					viaparinfo->
-					lvds_setting_info->iga_path = IGA2;
-					crt_iga_path = IGA1;
-					viaparinfo->
-					tmds_setting_info->iga_path = IGA1;
-				} else
-					viaparinfo->
-					lvds_setting_info->iga_path = IGA1;
-			} else {
-				viaparinfo->lvds_setting_info->iga_path = IGA2;
-			}
-		}
-		if (viafb_LCD2_ON) {
-			if (LCD2_Device == viafb_primary_dev)
-				viaparinfo->lvds_setting_info2->iga_path = IGA1;
-			else
-				viaparinfo->lvds_setting_info2->iga_path = IGA2;
-		}
-	} else {
-		viafb_SAMM_ON = 0;
-
-		if (viafb_CRT_ON && viafb_LCD_ON) {
-			crt_iga_path = IGA1;
-			viaparinfo->lvds_setting_info->iga_path = IGA2;
-		} else if (viafb_CRT_ON && viafb_DVI_ON) {
-			crt_iga_path = IGA1;
-			viaparinfo->tmds_setting_info->iga_path = IGA2;
-		} else if (viafb_LCD_ON && viafb_DVI_ON) {
-			viaparinfo->tmds_setting_info->iga_path = IGA1;
-			viaparinfo->lvds_setting_info->iga_path = IGA2;
-		} else if (viafb_LCD_ON && viafb_LCD2_ON) {
-			viaparinfo->lvds_setting_info->iga_path = IGA2;
-			viaparinfo->lvds_setting_info2->iga_path = IGA2;
-		} else if (viafb_CRT_ON) {
-			crt_iga_path = IGA1;
-		} else if (viafb_LCD_ON) {
-			viaparinfo->lvds_setting_info->iga_path = IGA2;
-		} else if (viafb_DVI_ON) {
-			viaparinfo->tmds_setting_info->iga_path = IGA1;
-		}
-	}
-
-	viaparinfo->shared->iga1_devices = 0;
-	viaparinfo->shared->iga2_devices = 0;
-	if (viafb_CRT_ON) {
-		if (crt_iga_path == IGA1)
-			viaparinfo->shared->iga1_devices |= VIA_CRT;
-		else
-			viaparinfo->shared->iga2_devices |= VIA_CRT;
-	}
-
-	if (viafb_DVI_ON) {
-		if (viaparinfo->tmds_setting_info->iga_path == IGA1)
-			viaparinfo->shared->iga1_devices |= get_dvi_devices(
-				viaparinfo->chip_info->
-				tmds_chip_info.output_interface);
-		else
-			viaparinfo->shared->iga2_devices |= get_dvi_devices(
-				viaparinfo->chip_info->
-				tmds_chip_info.output_interface);
-	}
-
-	if (viafb_LCD_ON) {
-		if (viaparinfo->lvds_setting_info->iga_path == IGA1)
-			viaparinfo->shared->iga1_devices |= get_lcd_devices(
-				viaparinfo->chip_info->
-				lvds_chip_info.output_interface);
-		else
-			viaparinfo->shared->iga2_devices |= get_lcd_devices(
-				viaparinfo->chip_info->
-				lvds_chip_info.output_interface);
-	}
-
-	if (viafb_LCD2_ON) {
-		if (viaparinfo->lvds_setting_info2->iga_path == IGA1)
-			viaparinfo->shared->iga1_devices |= get_lcd_devices(
-				viaparinfo->chip_info->
-				lvds_chip_info2.output_interface);
-		else
-			viaparinfo->shared->iga2_devices |= get_lcd_devices(
-				viaparinfo->chip_info->
-				lvds_chip_info2.output_interface);
-	}
-
-	/* looks like the OLPC has its display wired to DVP1 and LVDS2 */
-	if (machine_is_olpc())
-		viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2;
-}
-
-static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
-{
-	outb(0xFF, 0x3C6); /* bit mask of palette */
-	outb(index, 0x3C8);
-	outb(red, 0x3C9);
-	outb(green, 0x3C9);
-	outb(blue, 0x3C9);
-}
-
-void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
-{
-	viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
-	set_color_register(index, red, green, blue);
-}
-
-void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
-{
-	viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
-	set_color_register(index, red, green, blue);
-}
-
-static void set_source_common(u8 index, u8 offset, u8 iga)
-{
-	u8 value, mask = 1 << offset;
-
-	switch (iga) {
-	case IGA1:
-		value = 0x00;
-		break;
-	case IGA2:
-		value = mask;
-		break;
-	default:
-		printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
-		return;
-	}
-
-	via_write_reg_mask(VIACR, index, value, mask);
-}
-
-static void set_crt_source(u8 iga)
-{
-	u8 value;
-
-	switch (iga) {
-	case IGA1:
-		value = 0x00;
-		break;
-	case IGA2:
-		value = 0x40;
-		break;
-	default:
-		printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x16, value, 0x40);
-}
-
-static inline void set_ldvp0_source(u8 iga)
-{
-	set_source_common(0x6C, 7, iga);
-}
-
-static inline void set_ldvp1_source(u8 iga)
-{
-	set_source_common(0x93, 7, iga);
-}
-
-static inline void set_dvp0_source(u8 iga)
-{
-	set_source_common(0x96, 4, iga);
-}
-
-static inline void set_dvp1_source(u8 iga)
-{
-	set_source_common(0x9B, 4, iga);
-}
-
-static inline void set_lvds1_source(u8 iga)
-{
-	set_source_common(0x99, 4, iga);
-}
-
-static inline void set_lvds2_source(u8 iga)
-{
-	set_source_common(0x97, 4, iga);
-}
-
-void via_set_source(u32 devices, u8 iga)
-{
-	if (devices & VIA_LDVP0)
-		set_ldvp0_source(iga);
-	if (devices & VIA_LDVP1)
-		set_ldvp1_source(iga);
-	if (devices & VIA_DVP0)
-		set_dvp0_source(iga);
-	if (devices & VIA_CRT)
-		set_crt_source(iga);
-	if (devices & VIA_DVP1)
-		set_dvp1_source(iga);
-	if (devices & VIA_LVDS1)
-		set_lvds1_source(iga);
-	if (devices & VIA_LVDS2)
-		set_lvds2_source(iga);
-}
-
-static void set_crt_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x00;
-		break;
-	case VIA_STATE_STANDBY:
-		value = 0x10;
-		break;
-	case VIA_STATE_SUSPEND:
-		value = 0x20;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x30;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIACR, 0x36, value, 0x30);
-}
-
-static void set_dvp0_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0xC0;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
-}
-
-static void set_dvp1_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x30;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x1E, value, 0x30);
-}
-
-static void set_lvds1_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x03;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x2A, value, 0x03);
-}
-
-static void set_lvds2_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x0C;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
-}
-
-void via_set_state(u32 devices, u8 state)
-{
-	/*
-	TODO: Can we enable/disable these devices? How?
-	if (devices & VIA_LDVP0)
-	if (devices & VIA_LDVP1)
-	*/
-	if (devices & VIA_DVP0)
-		set_dvp0_state(state);
-	if (devices & VIA_CRT)
-		set_crt_state(state);
-	if (devices & VIA_DVP1)
-		set_dvp1_state(state);
-	if (devices & VIA_LVDS1)
-		set_lvds1_state(state);
-	if (devices & VIA_LVDS2)
-		set_lvds2_state(state);
-}
-
-void via_set_sync_polarity(u32 devices, u8 polarity)
-{
-	if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
-		printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
-			polarity);
-		return;
-	}
-
-	if (devices & VIA_CRT)
-		via_write_misc_reg_mask(polarity << 6, 0xC0);
-	if (devices & VIA_DVP1)
-		via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
-	if (devices & VIA_LVDS1)
-		via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
-	if (devices & VIA_LVDS2)
-		via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
-}
-
-u32 via_parse_odev(char *input, char **end)
-{
-	char *ptr = input;
-	u32 odev = 0;
-	bool next = true;
-	int i, len;
-
-	while (next) {
-		next = false;
-		for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
-			len = strlen(device_mapping[i].name);
-			if (!strncmp(ptr, device_mapping[i].name, len)) {
-				odev |= device_mapping[i].device;
-				ptr += len;
-				if (*ptr == ',') {
-					ptr++;
-					next = true;
-				}
-			}
-		}
-	}
-
-	*end = ptr;
-	return odev;
-}
-
-void via_odev_to_seq(struct seq_file *m, u32 odev)
-{
-	int i, count = 0;
-
-	for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
-		if (odev & device_mapping[i].device) {
-			if (count > 0)
-				seq_putc(m, ',');
-
-			seq_puts(m, device_mapping[i].name);
-			count++;
-		}
-	}
-
-	seq_putc(m, '\n');
-}
-
-static void load_fix_bit_crtc_reg(void)
-{
-	viafb_unlock_crt();
-
-	/* always set to 1 */
-	viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
-	/* line compare should set all bits = 1 (extend modes) */
-	viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
-	/* line compare should set all bits = 1 (extend modes) */
-	viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
-	/*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
-
-	viafb_lock_crt();
-
-	/* If K8M800, enable Prefetch Mode. */
-	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
-		|| (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
-		viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
-	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-	    && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
-		viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
-
-}
-
-void viafb_load_reg(int timing_value, int viafb_load_reg_num,
-	struct io_register *reg,
-	      int io_type)
-{
-	int reg_mask;
-	int bit_num = 0;
-	int data;
-	int i, j;
-	int shift_next_reg;
-	int start_index, end_index, cr_index;
-	u16 get_bit;
-
-	for (i = 0; i < viafb_load_reg_num; i++) {
-		reg_mask = 0;
-		data = 0;
-		start_index = reg[i].start_bit;
-		end_index = reg[i].end_bit;
-		cr_index = reg[i].io_addr;
-
-		shift_next_reg = bit_num;
-		for (j = start_index; j <= end_index; j++) {
-			/*if (bit_num==8) timing_value = timing_value >>8; */
-			reg_mask = reg_mask | (BIT0 << j);
-			get_bit = (timing_value & (BIT0 << bit_num));
-			data =
-			    data | ((get_bit >> shift_next_reg) << start_index);
-			bit_num++;
-		}
-		if (io_type == VIACR)
-			viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
-		else
-			viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
-	}
-
-}
-
-/* Write Registers */
-void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
-{
-	int i;
-
-	/*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
-
-	for (i = 0; i < ItemNum; i++)
-		via_write_reg_mask(RegTable[i].port, RegTable[i].index,
-			RegTable[i].value, RegTable[i].mask);
-}
-
-void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
-{
-	int reg_value;
-	int viafb_load_reg_num;
-	struct io_register *reg = NULL;
-
-	switch (set_iga) {
-	case IGA1:
-		reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
-		viafb_load_reg_num = fetch_count_reg.
-			iga1_fetch_count_reg.reg_num;
-		reg = fetch_count_reg.iga1_fetch_count_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
-		break;
-	case IGA2:
-		reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
-		viafb_load_reg_num = fetch_count_reg.
-			iga2_fetch_count_reg.reg_num;
-		reg = fetch_count_reg.iga2_fetch_count_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
-		break;
-	}
-
-}
-
-void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
-{
-	int reg_value;
-	int viafb_load_reg_num;
-	struct io_register *reg = NULL;
-	int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
-	    0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
-	int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
-	    0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
-
-	if (set_iga == IGA1) {
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
-			iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    K800_IGA1_FIFO_HIGH_THRESHOLD;
-			/* If resolution > 1280x1024, expire length = 64, else
-			   expire length = 128 */
-			if ((hor_active > 1280) && (ver_active > 1024))
-				iga1_display_queue_expire_num = 16;
-			else
-				iga1_display_queue_expire_num =
-				    K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
-			iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    P880_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-
-			/* If resolution > 1280x1024, expire length = 64, else
-			   expire length = 128 */
-			if ((hor_active > 1280) && (ver_active > 1024))
-				iga1_display_queue_expire_num = 16;
-			else
-				iga1_display_queue_expire_num =
-				    P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
-			iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    CN700_IGA1_FIFO_HIGH_THRESHOLD;
-
-			/* If resolution > 1280x1024, expire length = 64,
-			   else expire length = 128 */
-			if ((hor_active > 1280) && (ver_active > 1024))
-				iga1_display_queue_expire_num = 16;
-			else
-				iga1_display_queue_expire_num =
-				    CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
-			iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    CX700_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
-			iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    K8M890_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
-			iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    P4M890_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
-			iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    P4M900_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
-			iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    VX800_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
-			iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    VX855_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
-			iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH;
-			iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD;
-			iga1_fifo_high_threshold =
-			    VX900_IGA1_FIFO_HIGH_THRESHOLD;
-			iga1_display_queue_expire_num =
-			    VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		/* Set Display FIFO Depath Select */
-		reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
-		viafb_load_reg_num =
-		    display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
-		reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
-
-		/* Set Display FIFO Threshold Select */
-		reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
-		viafb_load_reg_num =
-		    fifo_threshold_select_reg.
-		    iga1_fifo_threshold_select_reg.reg_num;
-		reg =
-		    fifo_threshold_select_reg.
-		    iga1_fifo_threshold_select_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
-
-		/* Set FIFO High Threshold Select */
-		reg_value =
-		    IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
-		viafb_load_reg_num =
-		    fifo_high_threshold_select_reg.
-		    iga1_fifo_high_threshold_select_reg.reg_num;
-		reg =
-		    fifo_high_threshold_select_reg.
-		    iga1_fifo_high_threshold_select_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
-
-		/* Set Display Queue Expire Num */
-		reg_value =
-		    IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
-		    (iga1_display_queue_expire_num);
-		viafb_load_reg_num =
-		    display_queue_expire_num_reg.
-		    iga1_display_queue_expire_num_reg.reg_num;
-		reg =
-		    display_queue_expire_num_reg.
-		    iga1_display_queue_expire_num_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
-
-	} else {
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
-			iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    K800_IGA2_FIFO_HIGH_THRESHOLD;
-
-			/* If resolution > 1280x1024, expire length = 64,
-			   else  expire length = 128 */
-			if ((hor_active > 1280) && (ver_active > 1024))
-				iga2_display_queue_expire_num = 16;
-			else
-				iga2_display_queue_expire_num =
-				    K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
-			iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    P880_IGA2_FIFO_HIGH_THRESHOLD;
-
-			/* If resolution > 1280x1024, expire length = 64,
-			   else  expire length = 128 */
-			if ((hor_active > 1280) && (ver_active > 1024))
-				iga2_display_queue_expire_num = 16;
-			else
-				iga2_display_queue_expire_num =
-				    P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
-			iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    CN700_IGA2_FIFO_HIGH_THRESHOLD;
-
-			/* If resolution > 1280x1024, expire length = 64,
-			   else expire length = 128 */
-			if ((hor_active > 1280) && (ver_active > 1024))
-				iga2_display_queue_expire_num = 16;
-			else
-				iga2_display_queue_expire_num =
-				    CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
-			iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    CX700_IGA2_FIFO_HIGH_THRESHOLD;
-			iga2_display_queue_expire_num =
-			    CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
-			iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    K8M890_IGA2_FIFO_HIGH_THRESHOLD;
-			iga2_display_queue_expire_num =
-			    K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
-			iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    P4M890_IGA2_FIFO_HIGH_THRESHOLD;
-			iga2_display_queue_expire_num =
-			    P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
-			iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    P4M900_IGA2_FIFO_HIGH_THRESHOLD;
-			iga2_display_queue_expire_num =
-			    P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
-			iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    VX800_IGA2_FIFO_HIGH_THRESHOLD;
-			iga2_display_queue_expire_num =
-			    VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
-			iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    VX855_IGA2_FIFO_HIGH_THRESHOLD;
-			iga2_display_queue_expire_num =
-			    VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
-			iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH;
-			iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD;
-			iga2_fifo_high_threshold =
-			    VX900_IGA2_FIFO_HIGH_THRESHOLD;
-			iga2_display_queue_expire_num =
-			    VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
-		}
-
-		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
-			/* Set Display FIFO Depath Select */
-			reg_value =
-			    IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
-			    - 1;
-			/* Patch LCD in IGA2 case */
-			viafb_load_reg_num =
-			    display_fifo_depth_reg.
-			    iga2_fifo_depth_select_reg.reg_num;
-			reg =
-			    display_fifo_depth_reg.
-			    iga2_fifo_depth_select_reg.reg;
-			viafb_load_reg(reg_value,
-				viafb_load_reg_num, reg, VIACR);
-		} else {
-
-			/* Set Display FIFO Depath Select */
-			reg_value =
-			    IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
-			viafb_load_reg_num =
-			    display_fifo_depth_reg.
-			    iga2_fifo_depth_select_reg.reg_num;
-			reg =
-			    display_fifo_depth_reg.
-			    iga2_fifo_depth_select_reg.reg;
-			viafb_load_reg(reg_value,
-				viafb_load_reg_num, reg, VIACR);
-		}
-
-		/* Set Display FIFO Threshold Select */
-		reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
-		viafb_load_reg_num =
-		    fifo_threshold_select_reg.
-		    iga2_fifo_threshold_select_reg.reg_num;
-		reg =
-		    fifo_threshold_select_reg.
-		    iga2_fifo_threshold_select_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
-
-		/* Set FIFO High Threshold Select */
-		reg_value =
-		    IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
-		viafb_load_reg_num =
-		    fifo_high_threshold_select_reg.
-		    iga2_fifo_high_threshold_select_reg.reg_num;
-		reg =
-		    fifo_high_threshold_select_reg.
-		    iga2_fifo_high_threshold_select_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
-
-		/* Set Display Queue Expire Num */
-		reg_value =
-		    IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
-		    (iga2_display_queue_expire_num);
-		viafb_load_reg_num =
-		    display_queue_expire_num_reg.
-		    iga2_display_queue_expire_num_reg.reg_num;
-		reg =
-		    display_queue_expire_num_reg.
-		    iga2_display_queue_expire_num_reg.reg;
-		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
-
-	}
-
-}
-
-static struct via_pll_config get_pll_config(struct pll_limit *limits, int size,
-	int clk)
-{
-	struct via_pll_config cur, up, down, best = {0, 1, 0};
-	const u32 f0 = 14318180; /* X1 frequency */
-	int i, f;
-
-	for (i = 0; i < size; i++) {
-		cur.rshift = limits[i].rshift;
-		cur.divisor = limits[i].divisor;
-		cur.multiplier = clk / ((f0 / cur.divisor)>>cur.rshift);
-		f = abs(get_pll_output_frequency(f0, cur) - clk);
-		up = down = cur;
-		up.multiplier++;
-		down.multiplier--;
-		if (abs(get_pll_output_frequency(f0, up) - clk) < f)
-			cur = up;
-		else if (abs(get_pll_output_frequency(f0, down) - clk) < f)
-			cur = down;
-
-		if (cur.multiplier < limits[i].multiplier_min)
-			cur.multiplier = limits[i].multiplier_min;
-		else if (cur.multiplier > limits[i].multiplier_max)
-			cur.multiplier = limits[i].multiplier_max;
-
-		f = abs(get_pll_output_frequency(f0, cur) - clk);
-		if (f < abs(get_pll_output_frequency(f0, best) - clk))
-			best = cur;
-	}
-
-	return best;
-}
-
-static struct via_pll_config get_best_pll_config(int clk)
-{
-	struct via_pll_config config;
-
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_CLE266:
-	case UNICHROME_K400:
-		config = get_pll_config(cle266_pll_limits,
-			ARRAY_SIZE(cle266_pll_limits), clk);
-		break;
-	case UNICHROME_K800:
-	case UNICHROME_PM800:
-	case UNICHROME_CN700:
-		config = get_pll_config(k800_pll_limits,
-			ARRAY_SIZE(k800_pll_limits), clk);
-		break;
-	case UNICHROME_CX700:
-	case UNICHROME_CN750:
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M890:
-	case UNICHROME_P4M900:
-	case UNICHROME_VX800:
-		config = get_pll_config(cx700_pll_limits,
-			ARRAY_SIZE(cx700_pll_limits), clk);
-		break;
-	case UNICHROME_VX855:
-	case UNICHROME_VX900:
-		config = get_pll_config(vx855_pll_limits,
-			ARRAY_SIZE(vx855_pll_limits), clk);
-		break;
-	}
-
-	return config;
-}
-
-/* Set VCLK*/
-void viafb_set_vclock(u32 clk, int set_iga)
-{
-	struct via_pll_config config = get_best_pll_config(clk);
-
-	if (set_iga == IGA1)
-		clock.set_primary_pll(config);
-	if (set_iga == IGA2)
-		clock.set_secondary_pll(config);
-
-	/* Fire! */
-	via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
-}
-
-struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
-	u16 cxres, u16 cyres)
-{
-	struct via_display_timing timing;
-	u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
-
-	timing.hor_addr = cxres;
-	timing.hor_sync_start = timing.hor_addr + var->right_margin + dx;
-	timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
-	timing.hor_total = timing.hor_sync_end + var->left_margin + dx;
-	timing.hor_blank_start = timing.hor_addr + dx;
-	timing.hor_blank_end = timing.hor_total - dx;
-	timing.ver_addr = cyres;
-	timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy;
-	timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
-	timing.ver_total = timing.ver_sync_end + var->upper_margin + dy;
-	timing.ver_blank_start = timing.ver_addr + dy;
-	timing.ver_blank_end = timing.ver_total - dy;
-	return timing;
-}
-
-void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
-	u16 cxres, u16 cyres, int iga)
-{
-	struct via_display_timing crt_reg = var_to_timing(var,
-		cxres ? cxres : var->xres, cyres ? cyres : var->yres);
-
-	if (iga == IGA1)
-		via_set_primary_timing(&crt_reg);
-	else if (iga == IGA2)
-		via_set_secondary_timing(&crt_reg);
-
-	viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
-	if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
-		&& viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
-		viafb_load_FIFO_reg(iga, var->xres, var->yres);
-
-	viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
-}
-
-void viafb_init_chip_info(int chip_type)
-{
-	via_clock_init(&clock, chip_type);
-	init_gfx_chip_info(chip_type);
-	init_tmds_chip_info();
-	init_lvds_chip_info();
-
-	/*Set IGA path for each device */
-	viafb_set_iga_path();
-
-	viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
-	viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
-	viaparinfo->lvds_setting_info2->display_method =
-		viaparinfo->lvds_setting_info->display_method;
-	viaparinfo->lvds_setting_info2->lcd_mode =
-		viaparinfo->lvds_setting_info->lcd_mode;
-}
-
-void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
-{
-	if (flag == 0) {
-		viaparinfo->tmds_setting_info->h_active = hres;
-		viaparinfo->tmds_setting_info->v_active = vres;
-	} else {
-
-		if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
-			viaparinfo->tmds_setting_info->h_active = hres;
-			viaparinfo->tmds_setting_info->v_active = vres;
-		}
-
-	}
-}
-
-static void init_gfx_chip_info(int chip_type)
-{
-	u8 tmp;
-
-	viaparinfo->chip_info->gfx_chip_name = chip_type;
-
-	/* Check revision of CLE266 Chip */
-	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
-		/* CR4F only define in CLE266.CX chip */
-		tmp = viafb_read_reg(VIACR, CR4F);
-		viafb_write_reg(CR4F, VIACR, 0x55);
-		if (viafb_read_reg(VIACR, CR4F) != 0x55)
-			viaparinfo->chip_info->gfx_chip_revision =
-			CLE266_REVISION_AX;
-		else
-			viaparinfo->chip_info->gfx_chip_revision =
-			CLE266_REVISION_CX;
-		/* restore orignal CR4F value */
-		viafb_write_reg(CR4F, VIACR, tmp);
-	}
-
-	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
-		tmp = viafb_read_reg(VIASR, SR43);
-		DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
-		if (tmp & 0x02) {
-			viaparinfo->chip_info->gfx_chip_revision =
-				CX700_REVISION_700M2;
-		} else if (tmp & 0x40) {
-			viaparinfo->chip_info->gfx_chip_revision =
-				CX700_REVISION_700M;
-		} else {
-			viaparinfo->chip_info->gfx_chip_revision =
-				CX700_REVISION_700;
-		}
-	}
-
-	/* Determine which 2D engine we have */
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_VX800:
-	case UNICHROME_VX855:
-	case UNICHROME_VX900:
-		viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
-		break;
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M900:
-		viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5;
-		break;
-	default:
-		viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2;
-		break;
-	}
-}
-
-static void init_tmds_chip_info(void)
-{
-	viafb_tmds_trasmitter_identify();
-
-	if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
-		output_interface) {
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_CX700:
-			{
-				/* we should check support by hardware layout.*/
-				if ((viafb_display_hardware_layout ==
-				     HW_LAYOUT_DVI_ONLY)
-				    || (viafb_display_hardware_layout ==
-					HW_LAYOUT_LCD_DVI)) {
-					viaparinfo->chip_info->tmds_chip_info.
-					    output_interface = INTERFACE_TMDS;
-				} else {
-					viaparinfo->chip_info->tmds_chip_info.
-						output_interface =
-						INTERFACE_NONE;
-				}
-				break;
-			}
-		case UNICHROME_K8M890:
-		case UNICHROME_P4M900:
-		case UNICHROME_P4M890:
-			/* TMDS on PCIE, we set DFPLOW as default. */
-			viaparinfo->chip_info->tmds_chip_info.output_interface =
-			    INTERFACE_DFP_LOW;
-			break;
-		default:
-			{
-				/* set DVP1 default for DVI */
-				viaparinfo->chip_info->tmds_chip_info
-				.output_interface = INTERFACE_DVP1;
-			}
-		}
-	}
-
-	DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
-		  viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
-	viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
-		&viaparinfo->shared->tmds_setting_info);
-}
-
-static void init_lvds_chip_info(void)
-{
-	viafb_lvds_trasmitter_identify();
-	viafb_init_lcd_size();
-	viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
-				   viaparinfo->lvds_setting_info);
-	if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
-		viafb_init_lvds_output_interface(&viaparinfo->chip_info->
-			lvds_chip_info2, viaparinfo->lvds_setting_info2);
-	}
-	/*If CX700,two singel LCD, we need to reassign
-	   LCD interface to different LVDS port */
-	if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
-	    && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
-		if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
-			lvds_chip_name) && (INTEGRATED_LVDS ==
-			viaparinfo->chip_info->
-			lvds_chip_info2.lvds_chip_name)) {
-			viaparinfo->chip_info->lvds_chip_info.output_interface =
-				INTERFACE_LVDS0;
-			viaparinfo->chip_info->lvds_chip_info2.
-				output_interface =
-			    INTERFACE_LVDS1;
-		}
-	}
-
-	DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
-		  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
-	DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
-		  viaparinfo->chip_info->lvds_chip_info.output_interface);
-	DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
-		  viaparinfo->chip_info->lvds_chip_info.output_interface);
-}
-
-void viafb_init_dac(int set_iga)
-{
-	int i;
-	u8 tmp;
-
-	if (set_iga == IGA1) {
-		/* access Primary Display's LUT */
-		viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
-		/* turn off LCK */
-		viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
-		for (i = 0; i < 256; i++) {
-			write_dac_reg(i, palLUT_table[i].red,
-				      palLUT_table[i].green,
-				      palLUT_table[i].blue);
-		}
-		/* turn on LCK */
-		viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
-	} else {
-		tmp = viafb_read_reg(VIACR, CR6A);
-		/* access Secondary Display's LUT */
-		viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
-		viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
-		for (i = 0; i < 256; i++) {
-			write_dac_reg(i, palLUT_table[i].red,
-				      palLUT_table[i].green,
-				      palLUT_table[i].blue);
-		}
-		/* set IGA1 DAC for default */
-		viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
-		viafb_write_reg(CR6A, VIACR, tmp);
-	}
-}
-
-static void device_screen_off(void)
-{
-	/* turn off CRT screen (IGA1) */
-	viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
-}
-
-static void device_screen_on(void)
-{
-	/* turn on CRT screen (IGA1) */
-	viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
-}
-
-static void set_display_channel(void)
-{
-	/*If viafb_LCD2_ON, on cx700, internal lvds's information
-	is keeped on lvds_setting_info2 */
-	if (viafb_LCD2_ON &&
-		viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
-		/* For dual channel LCD: */
-		/* Set to Dual LVDS channel. */
-		viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
-	} else if (viafb_LCD_ON && viafb_DVI_ON) {
-		/* For LCD+DFP: */
-		/* Set to LVDS1 + TMDS channel. */
-		viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
-	} else if (viafb_DVI_ON) {
-		/* Set to single TMDS channel. */
-		viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
-	} else if (viafb_LCD_ON) {
-		if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
-			/* For dual channel LCD: */
-			/* Set to Dual LVDS channel. */
-			viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
-		} else {
-			/* Set to LVDS0 + LVDS1 channel. */
-			viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
-		}
-	}
-}
-
-static u8 get_sync(struct fb_var_screeninfo *var)
-{
-	u8 polarity = 0;
-
-	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
-		polarity |= VIA_HSYNC_NEGATIVE;
-	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
-		polarity |= VIA_VSYNC_NEGATIVE;
-	return polarity;
-}
-
-static void hw_init(void)
-{
-	int i;
-
-	inb(VIAStatus);
-	outb(0x00, VIAAR);
-
-	/* Write Common Setting for Video Mode */
-	viafb_write_regx(common_vga, ARRAY_SIZE(common_vga));
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_CLE266:
-		viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
-		break;
-
-	case UNICHROME_K400:
-		viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
-		break;
-
-	case UNICHROME_K800:
-	case UNICHROME_PM800:
-		viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
-		break;
-
-	case UNICHROME_CN700:
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M890:
-	case UNICHROME_P4M900:
-		viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
-		break;
-
-	case UNICHROME_CX700:
-	case UNICHROME_VX800:
-		viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
-		break;
-
-	case UNICHROME_VX855:
-	case UNICHROME_VX900:
-		viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
-		break;
-	}
-
-	/* magic required on VX900 for correct modesetting on IGA1 */
-	via_write_reg_mask(VIACR, 0x45, 0x00, 0x01);
-
-	/* probably this should go to the scaling code one day */
-	via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */
-	viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
-
-	/* Fill VPIT Parameters */
-	/* Write Misc Register */
-	outb(VPIT.Misc, VIA_MISC_REG_WRITE);
-
-	/* Write Sequencer */
-	for (i = 1; i <= StdSR; i++)
-		via_write_reg(VIASR, i, VPIT.SR[i - 1]);
-
-	viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
-
-	/* Write Graphic Controller */
-	for (i = 0; i < StdGR; i++)
-		via_write_reg(VIAGR, i, VPIT.GR[i]);
-
-	/* Write Attribute Controller */
-	for (i = 0; i < StdAR; i++) {
-		inb(VIAStatus);
-		outb(i, VIAAR);
-		outb(VPIT.AR[i], VIAAR);
-	}
-
-	inb(VIAStatus);
-	outb(0x20, VIAAR);
-
-	load_fix_bit_crtc_reg();
-}
-
-int viafb_setmode(void)
-{
-	int j, cxres = 0, cyres = 0;
-	int port;
-	u32 devices = viaparinfo->shared->iga1_devices
-		| viaparinfo->shared->iga2_devices;
-	u8 value, index, mask;
-	struct fb_var_screeninfo var2;
-
-	device_screen_off();
-	device_off();
-	via_set_state(devices, VIA_STATE_OFF);
-
-	hw_init();
-
-	/* Update Patch Register */
-
-	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
-		|| viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
-		&& viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
-		for (j = 0; j < res_patch_table[0].table_length; j++) {
-			index = res_patch_table[0].io_reg_table[j].index;
-			port = res_patch_table[0].io_reg_table[j].port;
-			value = res_patch_table[0].io_reg_table[j].value;
-			mask = res_patch_table[0].io_reg_table[j].mask;
-			viafb_write_reg_mask(index, port, value, mask);
-		}
-	}
-
-	via_set_primary_pitch(viafbinfo->fix.line_length);
-	via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
-		: viafbinfo->fix.line_length);
-	via_set_primary_color_depth(viaparinfo->depth);
-	via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
-		: viaparinfo->depth);
-	via_set_source(viaparinfo->shared->iga1_devices, IGA1);
-	via_set_source(viaparinfo->shared->iga2_devices, IGA2);
-	if (viaparinfo->shared->iga2_devices)
-		enable_second_display_channel();
-	else
-		disable_second_display_channel();
-
-	/* Update Refresh Rate Setting */
-
-	/* Clear On Screen */
-
-	if (viafb_dual_fb) {
-		var2 = viafbinfo1->var;
-	} else if (viafb_SAMM_ON) {
-		viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
-			viafb_second_xres, viafb_second_yres, viafb_refresh1));
-		cxres = viafbinfo->var.xres;
-		cyres = viafbinfo->var.yres;
-		var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
-	}
-
-	/* CRT set mode */
-	if (viafb_CRT_ON) {
-		if (viaparinfo->shared->iga2_devices & VIA_CRT
-			&& viafb_SAMM_ON)
-			viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2);
-		else
-			viafb_fill_crtc_timing(&viafbinfo->var, 0, 0,
-				(viaparinfo->shared->iga1_devices & VIA_CRT)
-				? IGA1 : IGA2);
-
-		/* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
-		to 8 alignment (1368),there is several pixels (2 pixels)
-		on right side of screen. */
-		if (viafbinfo->var.xres % 8) {
-			viafb_unlock_crt();
-			viafb_write_reg(CR02, VIACR,
-				viafb_read_reg(VIACR, CR02) - 1);
-			viafb_lock_crt();
-		}
-	}
-
-	if (viafb_DVI_ON) {
-		if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
-			&& viafb_SAMM_ON)
-			viafb_dvi_set_mode(&var2, cxres, cyres, IGA2);
-		else
-			viafb_dvi_set_mode(&viafbinfo->var, 0, 0,
-				viaparinfo->tmds_setting_info->iga_path);
-	}
-
-	if (viafb_LCD_ON) {
-		if (viafb_SAMM_ON &&
-			(viaparinfo->lvds_setting_info->iga_path == IGA2)) {
-			viafb_lcd_set_mode(&var2, cxres, cyres,
-				viaparinfo->lvds_setting_info,
-				&viaparinfo->chip_info->lvds_chip_info);
-		} else {
-			/* IGA1 doesn't have LCD scaling, so set it center. */
-			if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
-				viaparinfo->lvds_setting_info->display_method =
-				    LCD_CENTERING;
-			}
-			viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
-				viaparinfo->lvds_setting_info,
-				&viaparinfo->chip_info->lvds_chip_info);
-		}
-	}
-	if (viafb_LCD2_ON) {
-		if (viafb_SAMM_ON &&
-			(viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
-			viafb_lcd_set_mode(&var2, cxres, cyres,
-				viaparinfo->lvds_setting_info2,
-				&viaparinfo->chip_info->lvds_chip_info2);
-		} else {
-			/* IGA1 doesn't have LCD scaling, so set it center. */
-			if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
-				viaparinfo->lvds_setting_info2->display_method =
-				    LCD_CENTERING;
-			}
-			viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
-				viaparinfo->lvds_setting_info2,
-				&viaparinfo->chip_info->lvds_chip_info2);
-		}
-	}
-
-	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
-	    && (viafb_LCD_ON || viafb_DVI_ON))
-		set_display_channel();
-
-	/* If set mode normally, save resolution information for hot-plug . */
-	if (!viafb_hotplug) {
-		viafb_hotplug_Xres = viafbinfo->var.xres;
-		viafb_hotplug_Yres = viafbinfo->var.yres;
-		viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel;
-		viafb_hotplug_refresh = viafb_refresh;
-
-		if (viafb_DVI_ON)
-			viafb_DeviceStatus = DVI_Device;
-		else
-			viafb_DeviceStatus = CRT_Device;
-	}
-	device_on();
-	if (!viafb_SAMM_ON)
-		via_set_sync_polarity(devices, get_sync(&viafbinfo->var));
-	else {
-		via_set_sync_polarity(viaparinfo->shared->iga1_devices,
-			get_sync(&viafbinfo->var));
-		via_set_sync_polarity(viaparinfo->shared->iga2_devices,
-			get_sync(&var2));
-	}
-
-	clock.set_engine_pll_state(VIA_STATE_ON);
-	clock.set_primary_clock_source(VIA_CLKSRC_X1, true);
-	clock.set_secondary_clock_source(VIA_CLKSRC_X1, true);
-
-#ifdef CONFIG_FB_VIA_X_COMPATIBILITY
-	clock.set_primary_pll_state(VIA_STATE_ON);
-	clock.set_primary_clock_state(VIA_STATE_ON);
-	clock.set_secondary_pll_state(VIA_STATE_ON);
-	clock.set_secondary_clock_state(VIA_STATE_ON);
-#else
-	if (viaparinfo->shared->iga1_devices) {
-		clock.set_primary_pll_state(VIA_STATE_ON);
-		clock.set_primary_clock_state(VIA_STATE_ON);
-	} else {
-		clock.set_primary_pll_state(VIA_STATE_OFF);
-		clock.set_primary_clock_state(VIA_STATE_OFF);
-	}
-
-	if (viaparinfo->shared->iga2_devices) {
-		clock.set_secondary_pll_state(VIA_STATE_ON);
-		clock.set_secondary_clock_state(VIA_STATE_ON);
-	} else {
-		clock.set_secondary_pll_state(VIA_STATE_OFF);
-		clock.set_secondary_clock_state(VIA_STATE_OFF);
-	}
-#endif /*CONFIG_FB_VIA_X_COMPATIBILITY*/
-
-	via_set_state(devices, VIA_STATE_ON);
-	device_screen_on();
-	return 1;
-}
-
-int viafb_get_refresh(int hres, int vres, u32 long_refresh)
-{
-	const struct fb_videomode *best;
-
-	best = viafb_get_best_mode(hres, vres, long_refresh);
-	if (!best)
-		return 60;
-
-	if (abs(best->refresh - long_refresh) > 3) {
-		if (hres == 1200 && vres == 900)
-			return 49; /* OLPC DCON only supports 50 Hz */
-		else
-			return 60;
-	}
-
-	return best->refresh;
-}
-
-static void device_off(void)
-{
-	viafb_dvi_disable();
-	viafb_lcd_disable();
-}
-
-static void device_on(void)
-{
-	if (viafb_DVI_ON == 1)
-		viafb_dvi_enable();
-	if (viafb_LCD_ON == 1)
-		viafb_lcd_enable();
-}
-
-static void enable_second_display_channel(void)
-{
-	/* to enable second display channel. */
-	viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
-	viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
-	viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
-}
-
-static void disable_second_display_channel(void)
-{
-	/* to disable second display channel. */
-	viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
-	viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
-	viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
-}
-
-void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
-					*p_gfx_dpa_setting)
-{
-	switch (output_interface) {
-	case INTERFACE_DVP0:
-		{
-			/* DVP0 Clock Polarity and Adjust: */
-			viafb_write_reg_mask(CR96, VIACR,
-				       p_gfx_dpa_setting->DVP0, 0x0F);
-
-			/* DVP0 Clock and Data Pads Driving: */
-			viafb_write_reg_mask(SR1E, VIASR,
-				       p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
-			viafb_write_reg_mask(SR2A, VIASR,
-				       p_gfx_dpa_setting->DVP0ClockDri_S1,
-				       BIT4);
-			viafb_write_reg_mask(SR1B, VIASR,
-				       p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
-			viafb_write_reg_mask(SR2A, VIASR,
-				       p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
-			break;
-		}
-
-	case INTERFACE_DVP1:
-		{
-			/* DVP1 Clock Polarity and Adjust: */
-			viafb_write_reg_mask(CR9B, VIACR,
-				       p_gfx_dpa_setting->DVP1, 0x0F);
-
-			/* DVP1 Clock and Data Pads Driving: */
-			viafb_write_reg_mask(SR65, VIASR,
-				       p_gfx_dpa_setting->DVP1Driving, 0x0F);
-			break;
-		}
-
-	case INTERFACE_DFP_HIGH:
-		{
-			viafb_write_reg_mask(CR97, VIACR,
-				       p_gfx_dpa_setting->DFPHigh, 0x0F);
-			break;
-		}
-
-	case INTERFACE_DFP_LOW:
-		{
-			viafb_write_reg_mask(CR99, VIACR,
-				       p_gfx_dpa_setting->DFPLow, 0x0F);
-			break;
-		}
-
-	case INTERFACE_DFP:
-		{
-			viafb_write_reg_mask(CR97, VIACR,
-				       p_gfx_dpa_setting->DFPHigh, 0x0F);
-			viafb_write_reg_mask(CR99, VIACR,
-				       p_gfx_dpa_setting->DFPLow, 0x0F);
-			break;
-		}
-	}
-}
-
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
-	const struct fb_videomode *mode)
-{
-	var->pixclock = mode->pixclock;
-	var->xres = mode->xres;
-	var->yres = mode->yres;
-	var->left_margin = mode->left_margin;
-	var->right_margin = mode->right_margin;
-	var->hsync_len = mode->hsync_len;
-	var->upper_margin = mode->upper_margin;
-	var->lower_margin = mode->lower_margin;
-	var->vsync_len = mode->vsync_len;
-	var->sync = mode->sync;
-}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
deleted file mode 100644
index 3be073c58b03..000000000000
--- a/drivers/video/via/hw.h
+++ /dev/null
@@ -1,676 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __HW_H__
-#define __HW_H__
-
-#include <linux/seq_file.h>
-
-#include "viamode.h"
-#include "global.h"
-#include "via_modesetting.h"
-
-#define viafb_read_reg(p, i)			via_read_reg(p, i)
-#define viafb_write_reg(i, p, d)		via_write_reg(p, i, d)
-#define viafb_write_reg_mask(i, p, d, m)	via_write_reg_mask(p, i, d, m)
-
-/* VIA output devices */
-#define VIA_LDVP0	0x00000001
-#define VIA_LDVP1	0x00000002
-#define VIA_DVP0	0x00000004
-#define VIA_CRT		0x00000010
-#define VIA_DVP1	0x00000020
-#define VIA_LVDS1	0x00000040
-#define VIA_LVDS2	0x00000080
-
-/* VIA output device power states */
-#define VIA_STATE_ON		0
-#define VIA_STATE_STANDBY	1
-#define VIA_STATE_SUSPEND	2
-#define VIA_STATE_OFF		3
-
-/* VIA output device sync polarity */
-#define VIA_HSYNC_NEGATIVE	0x01
-#define VIA_VSYNC_NEGATIVE	0x02
-
-/**********************************************************/
-/* Definition IGA2 Design Method of CRTC Shadow Registers */
-/**********************************************************/
-#define IGA2_HOR_TOTAL_SHADOW_FORMULA(x)           ((x/8)-5)
-#define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y)     (((x+y)/8)-1)
-#define IGA2_VER_TOTAL_SHADOW_FORMULA(x)           ((x)-2)
-#define IGA2_VER_ADDR_SHADOW_FORMULA(x)            ((x)-1)
-#define IGA2_VER_BLANK_START_SHADOW_FORMULA(x)     ((x)-1)
-#define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y)     ((x+y)-1)
-#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x)      (x)
-#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y)      (x+y)
-
-/* Define Register Number for IGA2 Shadow CRTC Timing */
-
-/* location: {CR6D,0,7},{CR71,3,3} */
-#define IGA2_SHADOW_HOR_TOTAL_REG_NUM       2
-/* location: {CR6E,0,7} */
-#define IGA2_SHADOW_HOR_BLANK_END_REG_NUM   1
-/* location: {CR6F,0,7},{CR71,0,2} */
-#define IGA2_SHADOW_VER_TOTAL_REG_NUM       2
-/* location: {CR70,0,7},{CR71,4,6} */
-#define IGA2_SHADOW_VER_ADDR_REG_NUM        2
-/* location: {CR72,0,7},{CR74,4,6} */
-#define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2
-/* location: {CR73,0,7},{CR74,0,2} */
-#define IGA2_SHADOW_VER_BLANK_END_REG_NUM   2
-/* location: {CR75,0,7},{CR76,4,6} */
-#define IGA2_SHADOW_VER_SYNC_START_REG_NUM  2
-/* location: {CR76,0,3} */
-#define IGA2_SHADOW_VER_SYNC_END_REG_NUM    1
-
-/* Define Fetch Count Register*/
-
-/* location: {SR1C,0,7},{SR1D,0,1} */
-#define IGA1_FETCH_COUNT_REG_NUM        2
-/* 16 bytes alignment. */
-#define IGA1_FETCH_COUNT_ALIGN_BYTE     16
-/* x: H resolution, y: color depth */
-#define IGA1_FETCH_COUNT_PATCH_VALUE    4
-#define IGA1_FETCH_COUNT_FORMULA(x, y)   \
-	(((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
-
-/* location: {CR65,0,7},{CR67,2,3} */
-#define IGA2_FETCH_COUNT_REG_NUM        2
-#define IGA2_FETCH_COUNT_ALIGN_BYTE     16
-#define IGA2_FETCH_COUNT_PATCH_VALUE    0
-#define IGA2_FETCH_COUNT_FORMULA(x, y)   \
-	(((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE)
-
-/* Staring Address*/
-
-/* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */
-#define IGA1_STARTING_ADDR_REG_NUM      4
-/* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */
-#define IGA2_STARTING_ADDR_REG_NUM      3
-
-/* Define Display OFFSET*/
-/* These value are by HW suggested value*/
-/* location: {SR17,0,7} */
-#define K800_IGA1_FIFO_MAX_DEPTH                384
-/* location: {SR16,0,5},{SR16,7,7} */
-#define K800_IGA1_FIFO_THRESHOLD                328
-/* location: {SR18,0,5},{SR18,7,7} */
-#define K800_IGA1_FIFO_HIGH_THRESHOLD           296
-/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
-				/* because HW only 5 bits */
-#define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      0
-
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define K800_IGA2_FIFO_MAX_DEPTH                384
-/* location: {CR68,0,3},{CR95,4,6} */
-#define K800_IGA2_FIFO_THRESHOLD                328
-/* location: {CR92,0,3},{CR95,0,2} */
-#define K800_IGA2_FIFO_HIGH_THRESHOLD           296
-/* location: {CR94,0,6} */
-#define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM      128
-
-/* location: {SR17,0,7} */
-#define P880_IGA1_FIFO_MAX_DEPTH                192
-/* location: {SR16,0,5},{SR16,7,7} */
-#define P880_IGA1_FIFO_THRESHOLD                128
-/* location: {SR18,0,5},{SR18,7,7} */
-#define P880_IGA1_FIFO_HIGH_THRESHOLD           64
-/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
-				/* because HW only 5 bits */
-#define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      0
-
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define P880_IGA2_FIFO_MAX_DEPTH                96
-/* location: {CR68,0,3},{CR95,4,6} */
-#define P880_IGA2_FIFO_THRESHOLD                64
-/* location: {CR92,0,3},{CR95,0,2} */
-#define P880_IGA2_FIFO_HIGH_THRESHOLD           32
-/* location: {CR94,0,6} */
-#define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM      128
-
-/* VT3314 chipset*/
-
-/* location: {SR17,0,7} */
-#define CN700_IGA1_FIFO_MAX_DEPTH               96
-/* location: {SR16,0,5},{SR16,7,7} */
-#define CN700_IGA1_FIFO_THRESHOLD               80
-/* location: {SR18,0,5},{SR18,7,7} */
-#define CN700_IGA1_FIFO_HIGH_THRESHOLD          64
-/* location: {SR22,0,4}. (128/4) =64, P800 must be set zero,
-				because HW only 5 bits */
-#define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     0
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define CN700_IGA2_FIFO_MAX_DEPTH               96
-/* location: {CR68,0,3},{CR95,4,6} */
-#define CN700_IGA2_FIFO_THRESHOLD               80
-/* location: {CR92,0,3},{CR95,0,2} */
-#define CN700_IGA2_FIFO_HIGH_THRESHOLD          32
-/* location: {CR94,0,6} */
-#define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
-
-/* For VT3324, these values are suggested by HW */
-/* location: {SR17,0,7} */
-#define CX700_IGA1_FIFO_MAX_DEPTH               192
-/* location: {SR16,0,5},{SR16,7,7} */
-#define CX700_IGA1_FIFO_THRESHOLD               128
-/* location: {SR18,0,5},{SR18,7,7} */
-#define CX700_IGA1_FIFO_HIGH_THRESHOLD          128
-/* location: {SR22,0,4} */
-#define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     124
-
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define CX700_IGA2_FIFO_MAX_DEPTH               96
-/* location: {CR68,0,3},{CR95,4,6} */
-#define CX700_IGA2_FIFO_THRESHOLD               64
-/* location: {CR92,0,3},{CR95,0,2} */
-#define CX700_IGA2_FIFO_HIGH_THRESHOLD          32
-/* location: {CR94,0,6} */
-#define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
-
-/* VT3336 chipset*/
-/* location: {SR17,0,7} */
-#define K8M890_IGA1_FIFO_MAX_DEPTH               360
-/* location: {SR16,0,5},{SR16,7,7} */
-#define K8M890_IGA1_FIFO_THRESHOLD               328
-/* location: {SR18,0,5},{SR18,7,7} */
-#define K8M890_IGA1_FIFO_HIGH_THRESHOLD          296
-/* location: {SR22,0,4}. */
-#define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     124
-
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define K8M890_IGA2_FIFO_MAX_DEPTH               360
-/* location: {CR68,0,3},{CR95,4,6} */
-#define K8M890_IGA2_FIFO_THRESHOLD               328
-/* location: {CR92,0,3},{CR95,0,2} */
-#define K8M890_IGA2_FIFO_HIGH_THRESHOLD          296
-/* location: {CR94,0,6} */
-#define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     124
-
-/* VT3327 chipset*/
-/* location: {SR17,0,7} */
-#define P4M890_IGA1_FIFO_MAX_DEPTH               96
-/* location: {SR16,0,5},{SR16,7,7} */
-#define P4M890_IGA1_FIFO_THRESHOLD               76
-/* location: {SR18,0,5},{SR18,7,7} */
-#define P4M890_IGA1_FIFO_HIGH_THRESHOLD          64
-/* location: {SR22,0,4}. (32/4) =8 */
-#define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     32
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define P4M890_IGA2_FIFO_MAX_DEPTH               96
-/* location: {CR68,0,3},{CR95,4,6} */
-#define P4M890_IGA2_FIFO_THRESHOLD               76
-/* location: {CR92,0,3},{CR95,0,2} */
-#define P4M890_IGA2_FIFO_HIGH_THRESHOLD          64
-/* location: {CR94,0,6} */
-#define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     32
-
-/* VT3364 chipset*/
-/* location: {SR17,0,7} */
-#define P4M900_IGA1_FIFO_MAX_DEPTH               96
-/* location: {SR16,0,5},{SR16,7,7} */
-#define P4M900_IGA1_FIFO_THRESHOLD               76
-/* location: {SR18,0,5},{SR18,7,7} */
-#define P4M900_IGA1_FIFO_HIGH_THRESHOLD          76
-/* location: {SR22,0,4}. */
-#define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     32
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define P4M900_IGA2_FIFO_MAX_DEPTH               96
-/* location: {CR68,0,3},{CR95,4,6} */
-#define P4M900_IGA2_FIFO_THRESHOLD               76
-/* location: {CR92,0,3},{CR95,0,2} */
-#define P4M900_IGA2_FIFO_HIGH_THRESHOLD          76
-/* location: {CR94,0,6} */
-#define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     32
-
-/* For VT3353, these values are suggested by HW */
-/* location: {SR17,0,7} */
-#define VX800_IGA1_FIFO_MAX_DEPTH               192
-/* location: {SR16,0,5},{SR16,7,7} */
-#define VX800_IGA1_FIFO_THRESHOLD               152
-/* location: {SR18,0,5},{SR18,7,7} */
-#define VX800_IGA1_FIFO_HIGH_THRESHOLD          152
-/* location: {SR22,0,4} */
-#define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      64
-/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
-#define VX800_IGA2_FIFO_MAX_DEPTH               96
-/* location: {CR68,0,3},{CR95,4,6} */
-#define VX800_IGA2_FIFO_THRESHOLD               64
-/* location: {CR92,0,3},{CR95,0,2} */
-#define VX800_IGA2_FIFO_HIGH_THRESHOLD          32
-/* location: {CR94,0,6} */
-#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
-
-/* For VT3409 */
-#define VX855_IGA1_FIFO_MAX_DEPTH               400
-#define VX855_IGA1_FIFO_THRESHOLD               320
-#define VX855_IGA1_FIFO_HIGH_THRESHOLD          320
-#define VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     160
-
-#define VX855_IGA2_FIFO_MAX_DEPTH               200
-#define VX855_IGA2_FIFO_THRESHOLD               160
-#define VX855_IGA2_FIFO_HIGH_THRESHOLD          160
-#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     320
-
-/* For VT3410 */
-#define VX900_IGA1_FIFO_MAX_DEPTH               400
-#define VX900_IGA1_FIFO_THRESHOLD               320
-#define VX900_IGA1_FIFO_HIGH_THRESHOLD          320
-#define VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     160
-
-#define VX900_IGA2_FIFO_MAX_DEPTH               192
-#define VX900_IGA2_FIFO_THRESHOLD               160
-#define VX900_IGA2_FIFO_HIGH_THRESHOLD          160
-#define VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     320
-
-#define IGA1_FIFO_DEPTH_SELECT_REG_NUM          1
-#define IGA1_FIFO_THRESHOLD_REG_NUM             2
-#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM        2
-#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM   1
-
-#define IGA2_FIFO_DEPTH_SELECT_REG_NUM          3
-#define IGA2_FIFO_THRESHOLD_REG_NUM             2
-#define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM        2
-#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM   1
-
-#define IGA1_FIFO_DEPTH_SELECT_FORMULA(x)                   ((x/2)-1)
-#define IGA1_FIFO_THRESHOLD_FORMULA(x)                      (x/4)
-#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x)            (x/4)
-#define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x)                 (x/4)
-#define IGA2_FIFO_DEPTH_SELECT_FORMULA(x)                   (((x/2)/4)-1)
-#define IGA2_FIFO_THRESHOLD_FORMULA(x)                      (x/4)
-#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x)            (x/4)
-#define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x)                 (x/4)
-
-/************************************************************************/
-/*  LCD Timing                                                          */
-/************************************************************************/
-
-/* 500 ms = 500000 us */
-#define LCD_POWER_SEQ_TD0               500000
-/* 50 ms = 50000 us */
-#define LCD_POWER_SEQ_TD1               50000
-/* 0 us */
-#define LCD_POWER_SEQ_TD2               0
-/* 210 ms = 210000 us */
-#define LCD_POWER_SEQ_TD3               210000
-/* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */
-#define CLE266_POWER_SEQ_UNIT           71
-/* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */
-#define K800_POWER_SEQ_UNIT             142
-/* 2^13 * (1/14.31818M) = 572.1 us */
-#define P880_POWER_SEQ_UNIT             572
-
-#define CLE266_POWER_SEQ_FORMULA(x)     ((x)/CLE266_POWER_SEQ_UNIT)
-#define K800_POWER_SEQ_FORMULA(x)       ((x)/K800_POWER_SEQ_UNIT)
-#define P880_POWER_SEQ_FORMULA(x)       ((x)/P880_POWER_SEQ_UNIT)
-
-/* location: {CR8B,0,7},{CR8F,0,3} */
-#define LCD_POWER_SEQ_TD0_REG_NUM       2
-/* location: {CR8C,0,7},{CR8F,4,7} */
-#define LCD_POWER_SEQ_TD1_REG_NUM       2
-/* location: {CR8D,0,7},{CR90,0,3} */
-#define LCD_POWER_SEQ_TD2_REG_NUM       2
-/* location: {CR8E,0,7},{CR90,4,7} */
-#define LCD_POWER_SEQ_TD3_REG_NUM       2
-
-/* LCD Scaling factor*/
-/* x: indicate setting horizontal size*/
-/* y: indicate panel horizontal size*/
-
-/* Horizontal scaling factor 10 bits (2^10) */
-#define CLE266_LCD_HOR_SCF_FORMULA(x, y)   (((x-1)*1024)/(y-1))
-/* Vertical scaling factor 10 bits (2^10) */
-#define CLE266_LCD_VER_SCF_FORMULA(x, y)   (((x-1)*1024)/(y-1))
-/* Horizontal scaling factor 10 bits (2^12) */
-#define K800_LCD_HOR_SCF_FORMULA(x, y)     (((x-1)*4096)/(y-1))
-/* Vertical scaling factor 10 bits (2^11) */
-#define K800_LCD_VER_SCF_FORMULA(x, y)     (((x-1)*2048)/(y-1))
-
-/* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */
-#define LCD_HOR_SCALING_FACTOR_REG_NUM  3
-/* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */
-#define LCD_VER_SCALING_FACTOR_REG_NUM  3
-/* location: {CR77,0,7},{CR79,4,5} */
-#define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE  2
-/* location: {CR78,0,7},{CR79,6,7} */
-#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE  2
-
-struct io_register {
-	u8 io_addr;
-	u8 start_bit;
-	u8 end_bit;
-};
-
-/*****************************************************
-**      Define IGA2 Shadow Display Timing         ****
-*****************************************************/
-
-/* IGA2 Shadow Horizontal Total */
-struct iga2_shadow_hor_total {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM];
-};
-
-/* IGA2 Shadow Horizontal Blank End */
-struct iga2_shadow_hor_blank_end {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Shadow Vertical Total */
-struct iga2_shadow_ver_total {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM];
-};
-
-/* IGA2 Shadow Vertical Addressable Video */
-struct iga2_shadow_ver_addr {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM];
-};
-
-/* IGA2 Shadow Vertical Blank Start */
-struct iga2_shadow_ver_blank_start {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM];
-};
-
-/* IGA2 Shadow Vertical Blank End */
-struct iga2_shadow_ver_blank_end {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Shadow Vertical Sync Start */
-struct iga2_shadow_ver_sync_start {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM];
-};
-
-/* IGA2 Shadow Vertical Sync End */
-struct iga2_shadow_ver_sync_end {
-	int reg_num;
-	struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
-};
-
-/* IGA1 Fetch Count Register */
-struct iga1_fetch_count {
-	int reg_num;
-	struct io_register reg[IGA1_FETCH_COUNT_REG_NUM];
-};
-
-/* IGA2 Fetch Count Register */
-struct iga2_fetch_count {
-	int reg_num;
-	struct io_register reg[IGA2_FETCH_COUNT_REG_NUM];
-};
-
-struct fetch_count {
-	struct iga1_fetch_count iga1_fetch_count_reg;
-	struct iga2_fetch_count iga2_fetch_count_reg;
-};
-
-/* Starting Address Register */
-struct iga1_starting_addr {
-	int reg_num;
-	struct io_register reg[IGA1_STARTING_ADDR_REG_NUM];
-};
-
-struct iga2_starting_addr {
-	int reg_num;
-	struct io_register reg[IGA2_STARTING_ADDR_REG_NUM];
-};
-
-struct starting_addr {
-	struct iga1_starting_addr iga1_starting_addr_reg;
-	struct iga2_starting_addr iga2_starting_addr_reg;
-};
-
-/* LCD Power Sequence Timer */
-struct lcd_pwd_seq_td0 {
-	int reg_num;
-	struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM];
-};
-
-struct lcd_pwd_seq_td1 {
-	int reg_num;
-	struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM];
-};
-
-struct lcd_pwd_seq_td2 {
-	int reg_num;
-	struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM];
-};
-
-struct lcd_pwd_seq_td3 {
-	int reg_num;
-	struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM];
-};
-
-struct _lcd_pwd_seq_timer {
-	struct lcd_pwd_seq_td0 td0;
-	struct lcd_pwd_seq_td1 td1;
-	struct lcd_pwd_seq_td2 td2;
-	struct lcd_pwd_seq_td3 td3;
-};
-
-/* LCD Scaling Factor */
-struct _lcd_hor_scaling_factor {
-	int reg_num;
-	struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM];
-};
-
-struct _lcd_ver_scaling_factor {
-	int reg_num;
-	struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM];
-};
-
-struct _lcd_scaling_factor {
-	struct _lcd_hor_scaling_factor lcd_hor_scaling_factor;
-	struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
-};
-
-struct pll_limit {
-	u16 multiplier_min;
-	u16 multiplier_max;
-	u8 divisor;
-	u8 rshift;
-};
-
-struct rgbLUT {
-	u8 red;
-	u8 green;
-	u8 blue;
-};
-
-struct lcd_pwd_seq_timer {
-	u16 td0;
-	u16 td1;
-	u16 td2;
-	u16 td3;
-};
-
-/* Display FIFO Relation Registers*/
-struct iga1_fifo_depth_select {
-	int reg_num;
-	struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM];
-};
-
-struct iga1_fifo_threshold_select {
-	int reg_num;
-	struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM];
-};
-
-struct iga1_fifo_high_threshold_select {
-	int reg_num;
-	struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM];
-};
-
-struct iga1_display_queue_expire_num {
-	int reg_num;
-	struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
-};
-
-struct iga2_fifo_depth_select {
-	int reg_num;
-	struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM];
-};
-
-struct iga2_fifo_threshold_select {
-	int reg_num;
-	struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM];
-};
-
-struct iga2_fifo_high_threshold_select {
-	int reg_num;
-	struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM];
-};
-
-struct iga2_display_queue_expire_num {
-	int reg_num;
-	struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
-};
-
-struct fifo_depth_select {
-	struct iga1_fifo_depth_select iga1_fifo_depth_select_reg;
-	struct iga2_fifo_depth_select iga2_fifo_depth_select_reg;
-};
-
-struct fifo_threshold_select {
-	struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg;
-	struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg;
-};
-
-struct fifo_high_threshold_select {
-	struct iga1_fifo_high_threshold_select
-	 iga1_fifo_high_threshold_select_reg;
-	struct iga2_fifo_high_threshold_select
-	 iga2_fifo_high_threshold_select_reg;
-};
-
-struct display_queue_expire_num {
-	struct iga1_display_queue_expire_num
-	 iga1_display_queue_expire_num_reg;
-	struct iga2_display_queue_expire_num
-	 iga2_display_queue_expire_num_reg;
-};
-
-struct iga2_shadow_crtc_timing {
-	struct iga2_shadow_hor_total hor_total_shadow;
-	struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
-	struct iga2_shadow_ver_total ver_total_shadow;
-	struct iga2_shadow_ver_addr ver_addr_shadow;
-	struct iga2_shadow_ver_blank_start ver_blank_start_shadow;
-	struct iga2_shadow_ver_blank_end ver_blank_end_shadow;
-	struct iga2_shadow_ver_sync_start ver_sync_start_shadow;
-	struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
-};
-
-/* device ID */
-#define CLE266_FUNCTION3    0x3123
-#define KM400_FUNCTION3     0x3205
-#define CN400_FUNCTION2     0x2259
-#define CN400_FUNCTION3     0x3259
-/* support VT3314 chipset */
-#define CN700_FUNCTION2     0x2314
-#define CN700_FUNCTION3     0x3208
-/* VT3324 chipset */
-#define CX700_FUNCTION2     0x2324
-#define CX700_FUNCTION3     0x3324
-/* VT3204 chipset*/
-#define KM800_FUNCTION3      0x3204
-/* VT3336 chipset*/
-#define KM890_FUNCTION3      0x3336
-/* VT3327 chipset*/
-#define P4M890_FUNCTION3     0x3327
-/* VT3293 chipset*/
-#define CN750_FUNCTION3     0x3208
-/* VT3364 chipset*/
-#define P4M900_FUNCTION3    0x3364
-/* VT3353 chipset*/
-#define VX800_FUNCTION3     0x3353
-/* VT3409 chipset*/
-#define VX855_FUNCTION3     0x3409
-/* VT3410 chipset*/
-#define VX900_FUNCTION3     0x3410
-
-struct IODATA {
-	u8 Index;
-	u8 Mask;
-	u8 Data;
-};
-
-struct pci_device_id_info {
-	u32 vendor;
-	u32 device;
-	u32 chip_index;
-};
-
-struct via_device_mapping {
-	u32 device;
-	const char *name;
-};
-
-extern int viafb_SAMM_ON;
-extern int viafb_dual_fb;
-extern int viafb_LCD2_ON;
-extern int viafb_LCD_ON;
-extern int viafb_DVI_ON;
-extern int viafb_hotplug;
-
-struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
-	u16 cxres, u16 cyres);
-void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
-	u16 cxres, u16 cyres, int iga);
-void viafb_set_vclock(u32 CLK, int set_iga);
-void viafb_load_reg(int timing_value, int viafb_load_reg_num,
-	struct io_register *reg,
-	      int io_type);
-void via_set_source(u32 devices, u8 iga);
-void via_set_state(u32 devices, u8 state);
-void via_set_sync_polarity(u32 devices, u8 polarity);
-u32 via_parse_odev(char *input, char **end);
-void via_odev_to_seq(struct seq_file *m, u32 odev);
-void init_ad9389(void);
-/* Access I/O Function */
-void viafb_lock_crt(void);
-void viafb_unlock_crt(void);
-void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
-void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
-void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
-void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
-					*p_gfx_dpa_setting);
-
-int viafb_setmode(void);
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
-	const struct fb_videomode *mode);
-void viafb_init_chip_info(int chip_type);
-void viafb_init_dac(int set_iga);
-int viafb_get_refresh(int hres, int vres, u32 float_refresh);
-void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
-
-void viafb_set_iga_path(void);
-void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
-void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
-void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
-
-#endif /* __HW_H__ */
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c
deleted file mode 100644
index ea1c51428823..000000000000
--- a/drivers/video/via/ioctl.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "global.h"
-
-int viafb_ioctl_get_viafb_info(u_long arg)
-{
-	struct viafb_ioctl_info viainfo;
-
-	memset(&viainfo, 0, sizeof(struct viafb_ioctl_info));
-
-	viainfo.viafb_id = VIAID;
-	viainfo.vendor_id = PCI_VIA_VENDOR_ID;
-
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_CLE266:
-		viainfo.device_id = UNICHROME_CLE266_DID;
-		break;
-
-	case UNICHROME_K400:
-		viainfo.device_id = UNICHROME_K400_DID;
-		break;
-
-	case UNICHROME_K800:
-		viainfo.device_id = UNICHROME_K800_DID;
-		break;
-
-	case UNICHROME_PM800:
-		viainfo.device_id = UNICHROME_PM800_DID;
-		break;
-
-	case UNICHROME_CN700:
-		viainfo.device_id = UNICHROME_CN700_DID;
-		break;
-
-	case UNICHROME_CX700:
-		viainfo.device_id = UNICHROME_CX700_DID;
-		break;
-
-	case UNICHROME_K8M890:
-		viainfo.device_id = UNICHROME_K8M890_DID;
-		break;
-
-	case UNICHROME_P4M890:
-		viainfo.device_id = UNICHROME_P4M890_DID;
-		break;
-
-	case UNICHROME_P4M900:
-		viainfo.device_id = UNICHROME_P4M900_DID;
-		break;
-	}
-
-	viainfo.version = VERSION_MAJOR;
-	viainfo.revision = VERSION_MINOR;
-
-	if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo)))
-		return -EFAULT;
-
-	return 0;
-}
-
-/* Hot-Plug Priority: DVI > CRT*/
-int viafb_ioctl_hotplug(int hres, int vres, int bpp)
-{
-	int DVIsense, status = 0;
-	DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n");
-
-	if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name !=
-		NON_TMDS_TRANSMITTER) {
-		DVIsense = viafb_dvi_sense();
-
-		if (DVIsense) {
-			DEBUG_MSG(KERN_INFO "DVI Attached...\n");
-			if (viafb_DeviceStatus != DVI_Device) {
-				viafb_DVI_ON = 1;
-				viafb_CRT_ON = 0;
-				viafb_LCD_ON = 0;
-				viafb_DeviceStatus = DVI_Device;
-				viafb_set_iga_path();
-				return viafb_DeviceStatus;
-			}
-			status = 1;
-		} else
-			DEBUG_MSG(KERN_INFO "DVI De-attached...\n");
-	}
-
-	if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) {
-		viafb_CRT_ON = 1;
-		viafb_DVI_ON = 0;
-		viafb_LCD_ON = 0;
-
-		viafb_DeviceStatus = CRT_Device;
-		viafb_set_iga_path();
-		return viafb_DeviceStatus;
-	}
-
-	return 0;
-}
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h
deleted file mode 100644
index 6010d10b59e8..000000000000
--- a/drivers/video/via/ioctl.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __IOCTL_H__
-#define __IOCTL_H__
-
-#ifndef __user
-#define __user
-#endif
-
-/* VIAFB IOCTL definition */
-#define VIAFB_GET_INFO_SIZE		0x56494101	/* 'VIA\01' */
-#define VIAFB_GET_INFO			0x56494102	/* 'VIA\02' */
-#define VIAFB_HOTPLUG			0x56494103	/* 'VIA\03' */
-#define VIAFB_SET_HOTPLUG_FLAG		0x56494104	/* 'VIA\04' */
-#define VIAFB_GET_RESOLUTION		0x56494105	/* 'VIA\05' */
-#define VIAFB_GET_SAMM_INFO		0x56494107	/* 'VIA\07' */
-#define VIAFB_TURN_ON_OUTPUT_DEVICE     0x56494108	/* 'VIA\08' */
-#define VIAFB_TURN_OFF_OUTPUT_DEVICE    0x56494109	/* 'VIA\09' */
-#define VIAFB_GET_DEVICE		0x5649410B
-#define VIAFB_GET_DRIVER_VERSION	0x56494112	/* 'VIA\12' */
-#define VIAFB_GET_CHIP_INFO		0x56494113	/* 'VIA\13' */
-#define VIAFB_GET_DEVICE_INFO           0x56494115
-
-#define VIAFB_GET_DEVICE_SUPPORT	0x56494118
-#define VIAFB_GET_DEVICE_CONNECT	0x56494119
-#define VIAFB_GET_PANEL_SUPPORT_EXPAND	0x5649411A
-#define VIAFB_GET_DRIVER_NAME		0x56494122
-#define VIAFB_GET_DEVICE_SUPPORT_STATE	0x56494123
-#define VIAFB_GET_GAMMA_LUT		0x56494124
-#define VIAFB_SET_GAMMA_LUT		0x56494125
-#define VIAFB_GET_GAMMA_SUPPORT_STATE	0x56494126
-#define VIAFB_SYNC_SURFACE		0x56494130
-#define VIAFB_GET_DRIVER_CAPS		0x56494131
-#define VIAFB_GET_IGA_SCALING_INFO	0x56494132
-#define VIAFB_GET_PANEL_MAX_SIZE	0x56494133
-#define VIAFB_GET_PANEL_MAX_POSITION	0x56494134
-#define VIAFB_SET_PANEL_SIZE		0x56494135
-#define VIAFB_SET_PANEL_POSITION        0x56494136
-#define VIAFB_GET_PANEL_POSITION        0x56494137
-#define VIAFB_GET_PANEL_SIZE		0x56494138
-
-#define None_Device 0x00
-#define CRT_Device  0x01
-#define LCD_Device  0x02
-#define DVI_Device  0x08
-#define CRT2_Device 0x10
-#define LCD2_Device 0x40
-
-#define OP_LCD_CENTERING   0x01
-#define OP_LCD_PANEL_ID    0x02
-#define OP_LCD_MODE        0x03
-
-/*SAMM operation flag*/
-#define OP_SAMM            0x80
-
-#define LCD_PANEL_ID_MAXIMUM	23
-
-#define STATE_ON            0x1
-#define STATE_OFF           0x0
-#define STATE_DEFAULT       0xFFFF
-
-#define MAX_ACTIVE_DEV_NUM  2
-
-struct device_t {
-	unsigned short crt:1;
-	unsigned short dvi:1;
-	unsigned short lcd:1;
-	unsigned short samm:1;
-	unsigned short lcd_dsp_cent:1;
-	unsigned char lcd_mode:1;
-	unsigned short epia_dvi:1;
-	unsigned short lcd_dual_edge:1;
-	unsigned short lcd2:1;
-
-	unsigned short primary_dev;
-	unsigned char lcd_panel_id;
-	unsigned short xres, yres;
-	unsigned short xres1, yres1;
-	unsigned short refresh;
-	unsigned short bpp;
-	unsigned short refresh1;
-	unsigned short bpp1;
-	unsigned short sequence;
-	unsigned short bus_width;
-};
-
-struct viafb_ioctl_info {
-	u32 viafb_id;		/* for identifying viafb */
-#define VIAID       0x56494146	/* Identify myself with 'VIAF' */
-	u16 vendor_id;
-	u16 device_id;
-	u8 version;
-	u8 revision;
-	u8 reserved[246];	/* for future use */
-};
-
-struct viafb_ioctl_mode {
-	u32 xres;
-	u32 yres;
-	u32 refresh;
-	u32 bpp;
-	u32 xres_sec;
-	u32 yres_sec;
-	u32 virtual_xres_sec;
-	u32 virtual_yres_sec;
-	u32 refresh_sec;
-	u32 bpp_sec;
-};
-struct viafb_ioctl_samm {
-	u32 samm_status;
-	u32 size_prim;
-	u32 size_sec;
-	u32 mem_base;
-	u32 offset_sec;
-};
-
-struct viafb_driver_version {
-	int iMajorNum;
-	int iKernelNum;
-	int iOSNum;
-	int iMinorNum;
-};
-
-struct viafb_ioctl_lcd_attribute {
-	unsigned int panel_id;
-	unsigned int display_center;
-	unsigned int lcd_mode;
-};
-
-struct viafb_ioctl_setting {
-	/* Enable or disable active devices */
-	unsigned short device_flag;
-	/* Indicate which device should be turn on or turn off. */
-	unsigned short device_status;
-	unsigned int reserved;
-	/* Indicate which LCD's attribute can be changed. */
-	unsigned short lcd_operation_flag;
-	/* 1: SAMM ON  0: SAMM OFF */
-	unsigned short samm_status;
-	/* horizontal resolution of first device */
-	unsigned short first_dev_hor_res;
-	/* vertical resolution of first device */
-	unsigned short first_dev_ver_res;
-	/* horizontal resolution of second device */
-	unsigned short second_dev_hor_res;
-	/* vertical resolution of second device */
-	unsigned short second_dev_ver_res;
-	/* refresh rate of first device */
-	unsigned short first_dev_refresh;
-	/* bpp of first device */
-	unsigned short first_dev_bpp;
-	/* refresh rate of second device */
-	unsigned short second_dev_refresh;
-	/* bpp of second device */
-	unsigned short second_dev_bpp;
-	/* Indicate which device are primary display device. */
-	unsigned int primary_device;
-	unsigned int struct_reserved[35];
-	struct viafb_ioctl_lcd_attribute lcd_attributes;
-};
-
-struct _UTFunctionCaps {
-	unsigned int dw3DScalingState;
-	unsigned int reserved[31];
-};
-
-struct _POSITIONVALUE {
-	unsigned int dwX;
-	unsigned int dwY;
-};
-
-struct _panel_size_pos_info {
-	unsigned int device_type;
-	int x;
-	int y;
-};
-
-extern int viafb_LCD_ON;
-extern int viafb_DVI_ON;
-
-int viafb_ioctl_get_viafb_info(u_long arg);
-int viafb_ioctl_hotplug(int hres, int vres, int bpp);
-
-#endif /* __IOCTL_H__ */
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
deleted file mode 100644
index 5d21ff436ec8..000000000000
--- a/drivers/video/via/lcd.c
+++ /dev/null
@@ -1,1005 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <linux/via-core.h>
-#include <linux/via_i2c.h>
-#include "global.h"
-
-#define viafb_compact_res(x, y) (((x)<<16)|(y))
-
-/* CLE266 Software Power Sequence */
-/* {Mask}, {Data}, {Delay} */
-static const int PowerSequenceOn[3][3] = {
-	{0x10, 0x08, 0x06}, {0x10, 0x08, 0x06},	{0x19, 0x1FE, 0x01}
-};
-static const int PowerSequenceOff[3][3] = {
-	{0x06, 0x08, 0x10}, {0x00, 0x00, 0x00},	{0xD2, 0x19, 0x01}
-};
-
-static struct _lcd_scaling_factor lcd_scaling_factor = {
-	/* LCD Horizontal Scaling Factor Register */
-	{LCD_HOR_SCALING_FACTOR_REG_NUM,
-	 {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
-	/* LCD Vertical Scaling Factor Register */
-	{LCD_VER_SCALING_FACTOR_REG_NUM,
-	 {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
-};
-static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
-	/* LCD Horizontal Scaling Factor Register */
-	{LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
-	/* LCD Vertical Scaling Factor Register */
-	{LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
-};
-
-static bool lvds_identify_integratedlvds(void);
-static void fp_id_to_vindex(int panel_id);
-static int lvds_register_read(int index);
-static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
-		      int panel_vres);
-static void lcd_patch_skew_dvp0(struct lvds_setting_information
-			 *plvds_setting_info,
-			 struct lvds_chip_information *plvds_chip_info);
-static void lcd_patch_skew_dvp1(struct lvds_setting_information
-			 *plvds_setting_info,
-			 struct lvds_chip_information *plvds_chip_info);
-static void lcd_patch_skew(struct lvds_setting_information
-	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
-
-static void integrated_lvds_disable(struct lvds_setting_information
-			     *plvds_setting_info,
-			     struct lvds_chip_information *plvds_chip_info);
-static void integrated_lvds_enable(struct lvds_setting_information
-			    *plvds_setting_info,
-			    struct lvds_chip_information *plvds_chip_info);
-static void lcd_powersequence_off(void);
-static void lcd_powersequence_on(void);
-static void fill_lcd_format(void);
-static void check_diport_of_integrated_lvds(
-	struct lvds_chip_information *plvds_chip_info,
-				     struct lvds_setting_information
-				     *plvds_setting_info);
-
-static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
-{
-	return lvds_register_read(device_id_subaddr) == device_id;
-}
-
-void viafb_init_lcd_size(void)
-{
-	DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
-
-	fp_id_to_vindex(viafb_lcd_panel_id);
-	viaparinfo->lvds_setting_info2->lcd_panel_hres =
-		viaparinfo->lvds_setting_info->lcd_panel_hres;
-	viaparinfo->lvds_setting_info2->lcd_panel_vres =
-		viaparinfo->lvds_setting_info->lcd_panel_vres;
-	viaparinfo->lvds_setting_info2->device_lcd_dualedge =
-	    viaparinfo->lvds_setting_info->device_lcd_dualedge;
-	viaparinfo->lvds_setting_info2->LCDDithering =
-		viaparinfo->lvds_setting_info->LCDDithering;
-}
-
-static bool lvds_identify_integratedlvds(void)
-{
-	if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
-		/* Two dual channel LCD (Internal LVDS + External LVDS): */
-		/* If we have an external LVDS, such as VT1636, we should
-		   have its chip ID already. */
-		if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
-			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
-			    INTEGRATED_LVDS;
-			DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
-				  "(Internal LVDS + External LVDS)\n");
-		} else {
-			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
-			    INTEGRATED_LVDS;
-			DEBUG_MSG(KERN_INFO "Not found external LVDS, "
-				  "so can't support two dual channel LVDS!\n");
-		}
-	} else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
-		/* Two single channel LCD (Internal LVDS + Internal LVDS): */
-		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
-		INTEGRATED_LVDS;
-		viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
-			INTEGRATED_LVDS;
-		DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
-			  "(Internal LVDS + Internal LVDS)\n");
-	} else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
-		/* If we have found external LVDS, just use it,
-		   otherwise, we will use internal LVDS as default. */
-		if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
-			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
-			    INTEGRATED_LVDS;
-			DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
-		}
-	} else {
-		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
-			NON_LVDS_TRANSMITTER;
-		DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
-		return false;
-	}
-
-	return true;
-}
-
-bool viafb_lvds_trasmitter_identify(void)
-{
-	if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
-		viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
-		DEBUG_MSG(KERN_INFO
-			  "Found VIA VT1636 LVDS on port i2c 0x31\n");
-	} else {
-		if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {
-			viaparinfo->chip_info->lvds_chip_info.i2c_port =
-				VIA_PORT_2C;
-			DEBUG_MSG(KERN_INFO
-				  "Found VIA VT1636 LVDS on port gpio 0x2c\n");
-		}
-	}
-
-	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
-		lvds_identify_integratedlvds();
-
-	if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
-		return true;
-	/* Check for VT1631: */
-	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
-	viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
-		VT1631_LVDS_I2C_ADDR;
-
-	if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) {
-		DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
-		DEBUG_MSG(KERN_INFO "\n %2d",
-			  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
-		DEBUG_MSG(KERN_INFO "\n %2d",
-			  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
-		return true;
-	}
-
-	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
-		NON_LVDS_TRANSMITTER;
-	viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
-		VT1631_LVDS_I2C_ADDR;
-	return false;
-}
-
-static void fp_id_to_vindex(int panel_id)
-{
-	DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
-
-	if (panel_id > LCD_PANEL_ID_MAXIMUM)
-		viafb_lcd_panel_id = panel_id =
-		viafb_read_reg(VIACR, CR3F) & 0x0F;
-
-	switch (panel_id) {
-	case 0x0:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x1:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x2:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x3:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x4:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x5:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x6:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x8:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x9:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0xA:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0xB:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0xC:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0xD:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0xE:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0xF:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0x10:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0x11:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x12:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x13:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x14:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0x15:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	case 0x16:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		break;
-	case 0x17:
-		/* OLPC XO-1.5 panel */
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		break;
-	default:
-		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
-		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
-		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
-		viaparinfo->lvds_setting_info->LCDDithering = 1;
-	}
-}
-
-static int lvds_register_read(int index)
-{
-	u8 data;
-
-	viafb_i2c_readbyte(VIA_PORT_2C,
-			(u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
-			(u8) index, &data);
-	return data;
-}
-
-static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
-		      int panel_vres)
-{
-	int reg_value = 0;
-	int viafb_load_reg_num;
-	struct io_register *reg = NULL;
-
-	DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
-
-	/* LCD Scaling Enable */
-	viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
-
-	/* Check if expansion for horizontal */
-	if (set_hres < panel_hres) {
-		/* Load Horizontal Scaling Factor */
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_CLE266:
-		case UNICHROME_K400:
-			reg_value =
-			    CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
-			viafb_load_reg_num =
-			    lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
-			    reg_num;
-			reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
-			viafb_load_reg(reg_value,
-				viafb_load_reg_num, reg, VIACR);
-			break;
-		case UNICHROME_K800:
-		case UNICHROME_PM800:
-		case UNICHROME_CN700:
-		case UNICHROME_CX700:
-		case UNICHROME_K8M890:
-		case UNICHROME_P4M890:
-		case UNICHROME_P4M900:
-		case UNICHROME_CN750:
-		case UNICHROME_VX800:
-		case UNICHROME_VX855:
-		case UNICHROME_VX900:
-			reg_value =
-			    K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
-			/* Horizontal scaling enabled */
-			viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
-			viafb_load_reg_num =
-			    lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
-			reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
-			viafb_load_reg(reg_value,
-				viafb_load_reg_num, reg, VIACR);
-			break;
-		}
-
-		DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
-	} else {
-		/* Horizontal scaling disabled */
-		viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
-	}
-
-	/* Check if expansion for vertical */
-	if (set_vres < panel_vres) {
-		/* Load Vertical Scaling Factor */
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_CLE266:
-		case UNICHROME_K400:
-			reg_value =
-			    CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
-			viafb_load_reg_num =
-			    lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
-			    reg_num;
-			reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
-			viafb_load_reg(reg_value,
-				viafb_load_reg_num, reg, VIACR);
-			break;
-		case UNICHROME_K800:
-		case UNICHROME_PM800:
-		case UNICHROME_CN700:
-		case UNICHROME_CX700:
-		case UNICHROME_K8M890:
-		case UNICHROME_P4M890:
-		case UNICHROME_P4M900:
-		case UNICHROME_CN750:
-		case UNICHROME_VX800:
-		case UNICHROME_VX855:
-		case UNICHROME_VX900:
-			reg_value =
-			    K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
-			/* Vertical scaling enabled */
-			viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
-			viafb_load_reg_num =
-			    lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
-			reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
-			viafb_load_reg(reg_value,
-				viafb_load_reg_num, reg, VIACR);
-			break;
-		}
-
-		DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
-	} else {
-		/* Vertical scaling disabled */
-		viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
-	}
-}
-
-static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp)
-{
-	unsigned char cr13, cr35, cr65, cr66, cr67;
-	unsigned long dwScreenPitch = 0;
-	unsigned long dwPitch;
-
-	dwPitch = hres * (bpp >> 3);
-	if (dwPitch & 0x1F) {
-		dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
-		if (iga_path == IGA2) {
-			if (bpp > 8) {
-				cr66 = (unsigned char)(dwScreenPitch & 0xFF);
-				viafb_write_reg(CR66, VIACR, cr66);
-				cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
-				cr67 |=
-				    (unsigned
-				     char)((dwScreenPitch & 0x300) >> 8);
-				viafb_write_reg(CR67, VIACR, cr67);
-			}
-
-			/* Fetch Count */
-			cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
-			cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
-			viafb_write_reg(CR67, VIACR, cr67);
-			cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
-			cr65 += 2;
-			viafb_write_reg(CR65, VIACR, cr65);
-		} else {
-			if (bpp > 8) {
-				cr13 = (unsigned char)(dwScreenPitch & 0xFF);
-				viafb_write_reg(CR13, VIACR, cr13);
-				cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
-				cr35 |=
-				    (unsigned
-				     char)((dwScreenPitch & 0x700) >> 3);
-				viafb_write_reg(CR35, VIACR, cr35);
-			}
-		}
-	}
-}
-static void lcd_patch_skew_dvp0(struct lvds_setting_information
-			 *plvds_setting_info,
-			 struct lvds_chip_information *plvds_chip_info)
-{
-	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_P4M900:
-			viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
-						    plvds_chip_info);
-			break;
-		case UNICHROME_P4M890:
-			viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
-						    plvds_chip_info);
-			break;
-		}
-	}
-}
-static void lcd_patch_skew_dvp1(struct lvds_setting_information
-			 *plvds_setting_info,
-			 struct lvds_chip_information *plvds_chip_info)
-{
-	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_CX700:
-			viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
-						    plvds_chip_info);
-			break;
-		}
-	}
-}
-static void lcd_patch_skew(struct lvds_setting_information
-	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
-{
-	DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_DVP0:
-		lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
-		break;
-	case INTERFACE_DVP1:
-		lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
-		break;
-	case INTERFACE_DFP_LOW:
-		if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
-			viafb_write_reg_mask(CR99, VIACR, 0x08,
-				       BIT0 + BIT1 + BIT2 + BIT3);
-		}
-		break;
-	}
-}
-
-/* LCD Set Mode */
-void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
-	u16 cyres, struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info)
-{
-	int set_iga = plvds_setting_info->iga_path;
-	int mode_bpp = var->bits_per_pixel;
-	int set_hres = cxres ? cxres : var->xres;
-	int set_vres = cyres ? cyres : var->yres;
-	int panel_hres = plvds_setting_info->lcd_panel_hres;
-	int panel_vres = plvds_setting_info->lcd_panel_vres;
-	u32 clock;
-	struct via_display_timing timing;
-	struct fb_var_screeninfo panel_var;
-	const struct fb_videomode *mode_crt_table, *panel_crt_table;
-
-	DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
-	/* Get mode table */
-	mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
-	/* Get panel table Pointer */
-	panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
-	viafb_fill_var_timing_info(&panel_var, panel_crt_table);
-	DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
-	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
-		viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
-	clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000;
-	plvds_setting_info->vclk = clock;
-
-	if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
-		&& plvds_setting_info->display_method == LCD_EXPANDSION) {
-		timing = var_to_timing(&panel_var, panel_hres, panel_vres);
-		load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
-	} else {
-		timing = var_to_timing(&panel_var, set_hres, set_vres);
-		if (set_iga == IGA2)
-			/* disable scaling */
-			via_write_reg_mask(VIACR, 0x79, 0x00,
-				BIT0 + BIT1 + BIT2);
-	}
-
-	if (set_iga == IGA1)
-		via_set_primary_timing(&timing);
-	else if (set_iga == IGA2)
-		via_set_secondary_timing(&timing);
-
-	/* Fetch count for IGA2 only */
-	viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
-
-	if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
-		&& (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
-		viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
-
-	fill_lcd_format();
-	viafb_set_vclock(clock, set_iga);
-	lcd_patch_skew(plvds_setting_info, plvds_chip_info);
-
-	/* If K8M800, enable LCD Prefetch Mode. */
-	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
-	    || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
-		viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
-
-	/* Patch for non 32bit alignment mode */
-	via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres,
-		var->bits_per_pixel);
-}
-
-static void integrated_lvds_disable(struct lvds_setting_information
-			     *plvds_setting_info,
-			     struct lvds_chip_information *plvds_chip_info)
-{
-	bool turn_off_first_powersequence = false;
-	bool turn_off_second_powersequence = false;
-	if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
-		turn_off_first_powersequence = true;
-	if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
-		turn_off_first_powersequence = true;
-	if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
-		turn_off_second_powersequence = true;
-	if (turn_off_second_powersequence) {
-		/* Use second power sequence control: */
-
-		/* Turn off power sequence. */
-		viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
-
-		/* Turn off back light. */
-		viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
-	}
-	if (turn_off_first_powersequence) {
-		/* Use first power sequence control: */
-
-		/* Turn off power sequence. */
-		viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
-
-		/* Turn off back light. */
-		viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
-	}
-
-	/* Power off LVDS channel. */
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_LVDS0:
-		{
-			viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
-			break;
-		}
-
-	case INTERFACE_LVDS1:
-		{
-			viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
-			break;
-		}
-
-	case INTERFACE_LVDS0LVDS1:
-		{
-			viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
-			break;
-		}
-	}
-}
-
-static void integrated_lvds_enable(struct lvds_setting_information
-			    *plvds_setting_info,
-			    struct lvds_chip_information *plvds_chip_info)
-{
-	DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
-		  plvds_chip_info->output_interface);
-	if (plvds_setting_info->lcd_mode == LCD_SPWG)
-		viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
-	else
-		viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
-
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_LVDS0LVDS1:
-	case INTERFACE_LVDS0:
-		/* Use first power sequence control: */
-		/* Use hardware control power sequence. */
-		viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
-		/* Turn on back light. */
-		viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
-		/* Turn on hardware power sequence. */
-		viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
-		break;
-	case INTERFACE_LVDS1:
-		/* Use second power sequence control: */
-		/* Use hardware control power sequence. */
-		viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
-		/* Turn on back light. */
-		viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
-		/* Turn on hardware power sequence. */
-		viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
-		break;
-	}
-
-	/* Power on LVDS channel. */
-	switch (plvds_chip_info->output_interface) {
-	case INTERFACE_LVDS0:
-		{
-			viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
-			break;
-		}
-
-	case INTERFACE_LVDS1:
-		{
-			viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
-			break;
-		}
-
-	case INTERFACE_LVDS0LVDS1:
-		{
-			viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
-			break;
-		}
-	}
-}
-
-void viafb_lcd_disable(void)
-{
-
-	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
-		lcd_powersequence_off();
-		/* DI1 pad off */
-		viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
-	} else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
-		if (viafb_LCD2_ON
-		    && (INTEGRATED_LVDS ==
-			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
-			integrated_lvds_disable(viaparinfo->lvds_setting_info,
-				&viaparinfo->chip_info->lvds_chip_info2);
-		if (INTEGRATED_LVDS ==
-			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
-			integrated_lvds_disable(viaparinfo->lvds_setting_info,
-				&viaparinfo->chip_info->lvds_chip_info);
-		if (VT1636_LVDS == viaparinfo->chip_info->
-			lvds_chip_info.lvds_chip_name)
-			viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
-				&viaparinfo->chip_info->lvds_chip_info);
-	} else if (VT1636_LVDS ==
-	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
-		viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
-				    &viaparinfo->chip_info->lvds_chip_info);
-	} else {
-		/* Backlight off           */
-		viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
-		/* 24 bit DI data paht off */
-		viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
-	}
-
-	/* Disable expansion bit   */
-	viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
-	/* Simultaneout disabled   */
-	viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
-}
-
-static void set_lcd_output_path(int set_iga, int output_interface)
-{
-	switch (output_interface) {
-	case INTERFACE_DFP:
-		if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
-		    || (UNICHROME_P4M890 ==
-		    viaparinfo->chip_info->gfx_chip_name))
-			viafb_write_reg_mask(CR97, VIACR, 0x84,
-				       BIT7 + BIT2 + BIT1 + BIT0);
-	case INTERFACE_DVP0:
-	case INTERFACE_DVP1:
-	case INTERFACE_DFP_HIGH:
-	case INTERFACE_DFP_LOW:
-		if (set_iga == IGA2)
-			viafb_write_reg(CR91, VIACR, 0x00);
-		break;
-	}
-}
-
-void viafb_lcd_enable(void)
-{
-	viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
-	viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
-	set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path,
-		viaparinfo->chip_info->lvds_chip_info.output_interface);
-	if (viafb_LCD2_ON)
-		set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path,
-			viaparinfo->chip_info->
-			lvds_chip_info2.output_interface);
-
-	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
-		/* DI1 pad on */
-		viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
-		lcd_powersequence_on();
-	} else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
-		if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
-			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
-			integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
-				&viaparinfo->chip_info->lvds_chip_info2);
-		if (INTEGRATED_LVDS ==
-			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
-			integrated_lvds_enable(viaparinfo->lvds_setting_info,
-				&viaparinfo->chip_info->lvds_chip_info);
-		if (VT1636_LVDS == viaparinfo->chip_info->
-			lvds_chip_info.lvds_chip_name)
-			viafb_enable_lvds_vt1636(viaparinfo->
-			lvds_setting_info, &viaparinfo->chip_info->
-			lvds_chip_info);
-	} else if (VT1636_LVDS ==
-	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
-		viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
-				   &viaparinfo->chip_info->lvds_chip_info);
-	} else {
-		/* Backlight on            */
-		viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
-		/* 24 bit DI data paht on  */
-		viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
-		/* LCD enabled             */
-		viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
-	}
-}
-
-static void lcd_powersequence_off(void)
-{
-	int i, mask, data;
-
-	/* Software control power sequence */
-	viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
-
-	for (i = 0; i < 3; i++) {
-		mask = PowerSequenceOff[0][i];
-		data = PowerSequenceOff[1][i] & mask;
-		viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
-		udelay(PowerSequenceOff[2][i]);
-	}
-
-	/* Disable LCD */
-	viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
-}
-
-static void lcd_powersequence_on(void)
-{
-	int i, mask, data;
-
-	/* Software control power sequence */
-	viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
-
-	/* Enable LCD */
-	viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
-
-	for (i = 0; i < 3; i++) {
-		mask = PowerSequenceOn[0][i];
-		data = PowerSequenceOn[1][i] & mask;
-		viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
-		udelay(PowerSequenceOn[2][i]);
-	}
-
-	udelay(1);
-}
-
-static void fill_lcd_format(void)
-{
-	u8 bdithering = 0, bdual = 0;
-
-	if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
-		bdual = BIT4;
-	if (viaparinfo->lvds_setting_info->LCDDithering)
-		bdithering = BIT0;
-	/* Dual & Dithering */
-	viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
-}
-
-static void check_diport_of_integrated_lvds(
-	struct lvds_chip_information *plvds_chip_info,
-				     struct lvds_setting_information
-				     *plvds_setting_info)
-{
-	/* Determine LCD DI Port by hardware layout. */
-	switch (viafb_display_hardware_layout) {
-	case HW_LAYOUT_LCD_ONLY:
-		{
-			if (plvds_setting_info->device_lcd_dualedge) {
-				plvds_chip_info->output_interface =
-				    INTERFACE_LVDS0LVDS1;
-			} else {
-				plvds_chip_info->output_interface =
-				    INTERFACE_LVDS0;
-			}
-
-			break;
-		}
-
-	case HW_LAYOUT_DVI_ONLY:
-		{
-			plvds_chip_info->output_interface = INTERFACE_NONE;
-			break;
-		}
-
-	case HW_LAYOUT_LCD1_LCD2:
-	case HW_LAYOUT_LCD_EXTERNAL_LCD2:
-		{
-			plvds_chip_info->output_interface =
-			    INTERFACE_LVDS0LVDS1;
-			break;
-		}
-
-	case HW_LAYOUT_LCD_DVI:
-		{
-			plvds_chip_info->output_interface = INTERFACE_LVDS1;
-			break;
-		}
-
-	default:
-		{
-			plvds_chip_info->output_interface = INTERFACE_LVDS1;
-			break;
-		}
-	}
-
-	DEBUG_MSG(KERN_INFO
-		  "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
-		  viafb_display_hardware_layout,
-		  plvds_chip_info->output_interface);
-}
-
-void viafb_init_lvds_output_interface(struct lvds_chip_information
-				*plvds_chip_info,
-				struct lvds_setting_information
-				*plvds_setting_info)
-{
-	if (INTERFACE_NONE != plvds_chip_info->output_interface) {
-		/*Do nothing, lcd port is specified by module parameter */
-		return;
-	}
-
-	switch (plvds_chip_info->lvds_chip_name) {
-
-	case VT1636_LVDS:
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_CX700:
-			plvds_chip_info->output_interface = INTERFACE_DVP1;
-			break;
-		case UNICHROME_CN700:
-			plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
-			break;
-		default:
-			plvds_chip_info->output_interface = INTERFACE_DVP0;
-			break;
-		}
-		break;
-
-	case INTEGRATED_LVDS:
-		check_diport_of_integrated_lvds(plvds_chip_info,
-						plvds_setting_info);
-		break;
-
-	default:
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_K8M890:
-		case UNICHROME_P4M900:
-		case UNICHROME_P4M890:
-			plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
-			break;
-		default:
-			plvds_chip_info->output_interface = INTERFACE_DFP;
-			break;
-		}
-		break;
-	}
-}
-
-bool viafb_lcd_get_mobile_state(bool *mobile)
-{
-	unsigned char __iomem *romptr, *tableptr, *biosptr;
-	u8 core_base;
-	/* Rom address */
-	const u32 romaddr = 0x000C0000;
-	u16 start_pattern;
-
-	biosptr = ioremap(romaddr, 0x10000);
-	start_pattern = readw(biosptr);
-
-	/* Compare pattern */
-	if (start_pattern == 0xAA55) {
-		/* Get the start of Table */
-		/* 0x1B means BIOS offset position */
-		romptr = biosptr + 0x1B;
-		tableptr = biosptr + readw(romptr);
-
-		/* Get the start of biosver structure */
-		/* 18 means BIOS version position. */
-		romptr = tableptr + 18;
-		romptr = biosptr + readw(romptr);
-
-		/* The offset should be 44, but the
-		   actual image is less three char. */
-		/* pRom += 44; */
-		romptr += 41;
-
-		core_base = readb(romptr);
-
-		if (core_base & 0x8)
-			*mobile = false;
-		else
-			*mobile = true;
-		/* release memory */
-		iounmap(biosptr);
-
-		return true;
-	} else {
-		iounmap(biosptr);
-		return false;
-	}
-}
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
deleted file mode 100644
index 5c988a063ad5..000000000000
--- a/drivers/video/via/lcd.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#ifndef __LCD_H__
-#define __LCD_H__
-
-/*Definition TMDS Device ID register*/
-#define     VT1631_DEVICE_ID_REG        0x02
-#define     VT1631_DEVICE_ID            0x92
-
-#define     VT3271_DEVICE_ID_REG        0x02
-#define     VT3271_DEVICE_ID            0x71
-
-/* Definition DVI Panel ID*/
-/* Resolution: 640x480,   Channel: single, Dithering: Enable */
-#define     LCD_PANEL_ID0_640X480       0x00
-/* Resolution: 800x600,   Channel: single, Dithering: Enable */
-#define     LCD_PANEL_ID1_800X600       0x01
-/* Resolution: 1024x768,  Channel: single, Dithering: Enable */
-#define     LCD_PANEL_ID2_1024X768      0x02
-/* Resolution: 1280x768,  Channel: single, Dithering: Enable */
-#define     LCD_PANEL_ID3_1280X768      0x03
-/* Resolution: 1280x1024, Channel: dual,   Dithering: Enable */
-#define     LCD_PANEL_ID4_1280X1024     0x04
-/* Resolution: 1400x1050, Channel: dual,   Dithering: Enable */
-#define     LCD_PANEL_ID5_1400X1050     0x05
-/* Resolution: 1600x1200, Channel: dual,   Dithering: Enable */
-#define     LCD_PANEL_ID6_1600X1200     0x06
-/* Resolution: 1366x768,  Channel: single, Dithering: Disable */
-#define     LCD_PANEL_ID7_1366X768      0x07
-/* Resolution: 1024x600,  Channel: single, Dithering: Enable*/
-#define     LCD_PANEL_ID8_1024X600      0x08
-/* Resolution: 1280x800,  Channel: single, Dithering: Enable*/
-#define     LCD_PANEL_ID9_1280X800      0x09
-/* Resolution: 800x480,   Channel: single, Dithering: Enable*/
-#define     LCD_PANEL_IDA_800X480       0x0A
-/* Resolution: 1360x768,   Channel: single, Dithering: Disable*/
-#define     LCD_PANEL_IDB_1360X768     0x0B
-/* Resolution: 480x640,  Channel: single, Dithering: Enable */
-#define     LCD_PANEL_IDC_480X640      0x0C
-/* Resolution: 1200x900,  Channel: single, Dithering: Disable */
-#define     LCD_PANEL_IDD_1200X900      0x0D
-
-
-extern int viafb_LCD2_ON;
-extern int viafb_LCD_ON;
-extern int viafb_DVI_ON;
-
-void viafb_disable_lvds_vt1636(struct lvds_setting_information
-			 *plvds_setting_info,
-			 struct lvds_chip_information *plvds_chip_info);
-void viafb_enable_lvds_vt1636(struct lvds_setting_information
-			*plvds_setting_info,
-			struct lvds_chip_information *plvds_chip_info);
-void viafb_lcd_disable(void);
-void viafb_lcd_enable(void);
-void viafb_init_lcd_size(void);
-void viafb_init_lvds_output_interface(struct lvds_chip_information
-				*plvds_chip_info,
-				struct lvds_setting_information
-				*plvds_setting_info);
-void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
-	u16 cyres, struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info);
-bool viafb_lvds_trasmitter_identify(void);
-void viafb_init_lvds_output_interface(struct lvds_chip_information
-				*plvds_chip_info,
-				struct lvds_setting_information
-				*plvds_setting_info);
-bool viafb_lcd_get_mobile_state(bool *mobile);
-
-#endif /* __LCD_H__ */
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
deleted file mode 100644
index 65c65c611e0a..000000000000
--- a/drivers/video/via/share.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __SHARE_H__
-#define __SHARE_H__
-
-#include "via_modesetting.h"
-
-/* Define Bit Field */
-#define BIT0    0x01
-#define BIT1    0x02
-#define BIT2    0x04
-#define BIT3    0x08
-#define BIT4    0x10
-#define BIT5    0x20
-#define BIT6    0x40
-#define BIT7    0x80
-
-/* Video Memory Size */
-#define VIDEO_MEMORY_SIZE_16M    0x1000000
-
-/*
- * Lengths of the VPIT structure arrays.
- */
-#define StdCR       0x19
-#define StdSR       0x04
-#define StdGR       0x09
-#define StdAR       0x14
-
-#define PatchCR     11
-
-/* Display path */
-#define IGA1        1
-#define IGA2        2
-
-/* Define Color Depth  */
-#define MODE_8BPP       1
-#define MODE_16BPP      2
-#define MODE_32BPP      4
-
-#define GR20    0x20
-#define GR21    0x21
-#define GR22    0x22
-
-/* Sequencer Registers */
-#define SR01    0x01
-#define SR10    0x10
-#define SR12    0x12
-#define SR15    0x15
-#define SR16    0x16
-#define SR17    0x17
-#define SR18    0x18
-#define SR1B    0x1B
-#define SR1A    0x1A
-#define SR1C    0x1C
-#define SR1D    0x1D
-#define SR1E    0x1E
-#define SR1F    0x1F
-#define SR20    0x20
-#define SR21    0x21
-#define SR22    0x22
-#define SR2A    0x2A
-#define SR2D    0x2D
-#define SR2E    0x2E
-
-#define SR30    0x30
-#define SR39    0x39
-#define SR3D    0x3D
-#define SR3E    0x3E
-#define SR3F    0x3F
-#define SR40    0x40
-#define SR43    0x43
-#define SR44    0x44
-#define SR45    0x45
-#define SR46    0x46
-#define SR47    0x47
-#define SR48    0x48
-#define SR49    0x49
-#define SR4A    0x4A
-#define SR4B    0x4B
-#define SR4C    0x4C
-#define SR52    0x52
-#define SR57	0x57
-#define SR58	0x58
-#define SR59	0x59
-#define SR5D    0x5D
-#define SR5E    0x5E
-#define SR65    0x65
-
-/* CRT Controller Registers */
-#define CR00    0x00
-#define CR01    0x01
-#define CR02    0x02
-#define CR03    0x03
-#define CR04    0x04
-#define CR05    0x05
-#define CR06    0x06
-#define CR07    0x07
-#define CR08    0x08
-#define CR09    0x09
-#define CR0A    0x0A
-#define CR0B    0x0B
-#define CR0C    0x0C
-#define CR0D    0x0D
-#define CR0E    0x0E
-#define CR0F    0x0F
-#define CR10    0x10
-#define CR11    0x11
-#define CR12    0x12
-#define CR13    0x13
-#define CR14    0x14
-#define CR15    0x15
-#define CR16    0x16
-#define CR17    0x17
-#define CR18    0x18
-
-/* Extend CRT Controller Registers */
-#define CR30    0x30
-#define CR31    0x31
-#define CR32    0x32
-#define CR33    0x33
-#define CR34    0x34
-#define CR35    0x35
-#define CR36    0x36
-#define CR37    0x37
-#define CR38    0x38
-#define CR39    0x39
-#define CR3A    0x3A
-#define CR3B    0x3B
-#define CR3C    0x3C
-#define CR3D    0x3D
-#define CR3E    0x3E
-#define CR3F    0x3F
-#define CR40    0x40
-#define CR41    0x41
-#define CR42    0x42
-#define CR43    0x43
-#define CR44    0x44
-#define CR45    0x45
-#define CR46    0x46
-#define CR47    0x47
-#define CR48    0x48
-#define CR49    0x49
-#define CR4A    0x4A
-#define CR4B    0x4B
-#define CR4C    0x4C
-#define CR4D    0x4D
-#define CR4E    0x4E
-#define CR4F    0x4F
-#define CR50    0x50
-#define CR51    0x51
-#define CR52    0x52
-#define CR53    0x53
-#define CR54    0x54
-#define CR55    0x55
-#define CR56    0x56
-#define CR57    0x57
-#define CR58    0x58
-#define CR59    0x59
-#define CR5A    0x5A
-#define CR5B    0x5B
-#define CR5C    0x5C
-#define CR5D    0x5D
-#define CR5E    0x5E
-#define CR5F    0x5F
-#define CR60    0x60
-#define CR61    0x61
-#define CR62    0x62
-#define CR63    0x63
-#define CR64    0x64
-#define CR65    0x65
-#define CR66    0x66
-#define CR67    0x67
-#define CR68    0x68
-#define CR69    0x69
-#define CR6A    0x6A
-#define CR6B    0x6B
-#define CR6C    0x6C
-#define CR6D    0x6D
-#define CR6E    0x6E
-#define CR6F    0x6F
-#define CR70    0x70
-#define CR71    0x71
-#define CR72    0x72
-#define CR73    0x73
-#define CR74    0x74
-#define CR75    0x75
-#define CR76    0x76
-#define CR77    0x77
-#define CR78    0x78
-#define CR79    0x79
-#define CR7A    0x7A
-#define CR7B    0x7B
-#define CR7C    0x7C
-#define CR7D    0x7D
-#define CR7E    0x7E
-#define CR7F    0x7F
-#define CR80    0x80
-#define CR81    0x81
-#define CR82    0x82
-#define CR83    0x83
-#define CR84    0x84
-#define CR85    0x85
-#define CR86    0x86
-#define CR87    0x87
-#define CR88    0x88
-#define CR89    0x89
-#define CR8A    0x8A
-#define CR8B    0x8B
-#define CR8C    0x8C
-#define CR8D    0x8D
-#define CR8E    0x8E
-#define CR8F    0x8F
-#define CR90    0x90
-#define CR91    0x91
-#define CR92    0x92
-#define CR93    0x93
-#define CR94    0x94
-#define CR95    0x95
-#define CR96    0x96
-#define CR97    0x97
-#define CR98    0x98
-#define CR99    0x99
-#define CR9A    0x9A
-#define CR9B    0x9B
-#define CR9C    0x9C
-#define CR9D    0x9D
-#define CR9E    0x9E
-#define CR9F    0x9F
-#define CRA0    0xA0
-#define CRA1    0xA1
-#define CRA2    0xA2
-#define CRA3    0xA3
-#define CRD2    0xD2
-#define CRD3    0xD3
-#define CRD4    0xD4
-
-/* LUT Table*/
-#define LUT_DATA             0x3C9	/* DACDATA */
-#define LUT_INDEX_READ       0x3C7	/* DACRX */
-#define LUT_INDEX_WRITE      0x3C8	/* DACWX */
-#define DACMASK              0x3C6
-
-/* Definition Device */
-#define DEVICE_CRT  0x01
-#define DEVICE_DVI  0x03
-#define DEVICE_LCD  0x04
-
-/* Device output interface */
-#define INTERFACE_NONE          0x00
-#define INTERFACE_ANALOG_RGB    0x01
-#define INTERFACE_DVP0          0x02
-#define INTERFACE_DVP1          0x03
-#define INTERFACE_DFP_HIGH      0x04
-#define INTERFACE_DFP_LOW       0x05
-#define INTERFACE_DFP           0x06
-#define INTERFACE_LVDS0         0x07
-#define INTERFACE_LVDS1         0x08
-#define INTERFACE_LVDS0LVDS1    0x09
-#define INTERFACE_TMDS          0x0A
-
-#define HW_LAYOUT_LCD_ONLY      0x01
-#define HW_LAYOUT_DVI_ONLY      0x02
-#define HW_LAYOUT_LCD_DVI       0x03
-#define HW_LAYOUT_LCD1_LCD2     0x04
-#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
-
-/* Definition CRTC Timing Index */
-#define H_TOTAL_INDEX               0
-#define H_ADDR_INDEX                1
-#define H_BLANK_START_INDEX         2
-#define H_BLANK_END_INDEX           3
-#define H_SYNC_START_INDEX          4
-#define H_SYNC_END_INDEX            5
-#define V_TOTAL_INDEX               6
-#define V_ADDR_INDEX                7
-#define V_BLANK_START_INDEX         8
-#define V_BLANK_END_INDEX           9
-#define V_SYNC_START_INDEX          10
-#define V_SYNC_END_INDEX            11
-#define H_TOTAL_SHADOW_INDEX        12
-#define H_BLANK_END_SHADOW_INDEX    13
-#define V_TOTAL_SHADOW_INDEX        14
-#define V_ADDR_SHADOW_INDEX         15
-#define V_BLANK_SATRT_SHADOW_INDEX  16
-#define V_BLANK_END_SHADOW_INDEX    17
-#define V_SYNC_SATRT_SHADOW_INDEX   18
-#define V_SYNC_END_SHADOW_INDEX     19
-
-/* LCD display method
-*/
-#define     LCD_EXPANDSION              0x00
-#define     LCD_CENTERING               0x01
-
-/* LCD mode
-*/
-#define     LCD_OPENLDI               0x00
-#define     LCD_SPWG                  0x01
-
-struct crt_mode_table {
-	int refresh_rate;
-	int h_sync_polarity;
-	int v_sync_polarity;
-	struct via_display_timing crtc;
-};
-
-struct io_reg {
-	int port;
-	u8 index;
-	u8 mask;
-	u8 value;
-};
-
-#endif /* __SHARE_H__ */
diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/via/tblDPASetting.c
deleted file mode 100644
index 73bb554e7c1e..000000000000
--- a/drivers/video/via/tblDPASetting.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "global.h"
-
-struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
-/*  ClkRange, DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
-					DVP1Driving, DFPHigh, DFPLow */
-/*  CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
-					SR65,        CR97,    CR99   */
-	/* LCK/VCK < 30000000 will use this value */
-	{DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
-	 0x00},
-	/* 30000000 < LCK/VCK < 50000000 will use this value */
-	{DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
-	 0x00},
-	/* 50000000 < LCK/VCK < 70000000 will use this value */
-	{DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-	 0x00},
-	/* 70000000 < LCK/VCK < 100000000 will use this value */
-	{DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-	 0x00},
-	/* 100000000 < LCK/VCK < 15000000 will use this value */
-	{DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-	 0x00},
-	/* 15000000 < LCK/VCK will use this value */
-	{DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00,
-	 0x00},
-};
-
-struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
-/*  ClkRange,DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
-					DVP1Driving, DFPHigh,   DFPLow */
-/*   CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
-					SR65,        CR97,      CR99   */
-/* LCK/VCK < 30000000 will use this value */
-{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
-/* 30000000 < LCK/VCK < 50000000 will use this value */
-{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
-/* 50000000 < LCK/VCK < 70000000 will use this value */
-{DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
-/* 70000000 < LCK/VCK < 100000000 will use this value */
-{DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03},
-/* 100000000 < LCK/VCK < 15000000 will use this value */
-{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02},
-/* 15000000 < LCK/VCK will use this value */
-{DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03},
-};
-
-/* For VT3364: */
-struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = {
-/*  ClkRange,DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
-					DVP1Driving, DFPHigh,   DFPLow */
-/*   CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
-					SR65,        CR97,      CR99   */
-/* LCK/VCK < 30000000 will use this value */
-{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
-/* 30000000 < LCK/VCK < 50000000 will use this value */
-{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
-/* 50000000 < LCK/VCK < 70000000 will use this value */
-{DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
-/* 70000000 < LCK/VCK < 100000000 will use this value */
-{DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
-/* 100000000 < LCK/VCK < 15000000 will use this value */
-{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
-/* 15000000 < LCK/VCK will use this value */
-{DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08},
-};
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/via/tblDPASetting.h
deleted file mode 100644
index 6db61519cb5d..000000000000
--- a/drivers/video/via/tblDPASetting.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _TBLDPASETTING_H_
-#define _TBLDPASETTING_H_
-#include "global.h"
-
-#define DPA_CLK_30M       30000000
-#define DPA_CLK_50M       50000000
-#define DPA_CLK_70M       70000000
-#define DPA_CLK_100M      100000000
-#define DPA_CLK_150M      150000000
-
-enum DPA_RANGE {
-	DPA_CLK_RANGE_30M,
-	DPA_CLK_RANGE_30_50M,
-	DPA_CLK_RANGE_50_70M,
-	DPA_CLK_RANGE_70_100M,
-	DPA_CLK_RANGE_100_150M,
-	DPA_CLK_RANGE_150M
-};
-
-extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
-extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
-extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
-
-#endif
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
deleted file mode 100644
index 6e274825fb31..000000000000
--- a/drivers/video/via/via-core.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
- * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
- */
-
-/*
- * Core code for the Via multifunction framebuffer device.
- */
-#include <linux/via-core.h>
-#include <linux/via_i2c.h>
-#include <linux/via-gpio.h>
-#include "global.h"
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/pm.h>
-#include <asm/olpc.h>
-
-/*
- * The default port config.
- */
-static struct via_port_cfg adap_configs[] = {
-	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
-	[VIA_PORT_31]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
-	[VIA_PORT_25]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
-	[VIA_PORT_2C]	= { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
-	[VIA_PORT_3D]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
-	{ 0, 0, 0, 0 }
-};
-
-/*
- * The OLPC XO-1.5 puts the camera power and reset lines onto
- * GPIO 2C.
- */
-static struct via_port_cfg olpc_adap_configs[] = {
-	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
-	[VIA_PORT_31]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
-	[VIA_PORT_25]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
-	[VIA_PORT_2C]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
-	[VIA_PORT_3D]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
-	{ 0, 0, 0, 0 }
-};
-
-/*
- * We currently only support one viafb device (will there ever be
- * more than one?), so just declare it globally here.
- */
-static struct viafb_dev global_dev;
-
-
-/*
- * Basic register access; spinlock required.
- */
-static inline void viafb_mmio_write(int reg, u32 v)
-{
-	iowrite32(v, global_dev.engine_mmio + reg);
-}
-
-static inline int viafb_mmio_read(int reg)
-{
-	return ioread32(global_dev.engine_mmio + reg);
-}
-
-/* ---------------------------------------------------------------------- */
-/*
- * Interrupt management.  We have a single IRQ line for a lot of
- * different functions, so we need to share it.  The design here
- * is that we don't want to reimplement the shared IRQ code here;
- * we also want to avoid having contention for a single handler thread.
- * So each subdev driver which needs interrupts just requests
- * them directly from the kernel.  We just have what's needed for
- * overall access to the interrupt control register.
- */
-
-/*
- * Which interrupts are enabled now?
- */
-static u32 viafb_enabled_ints;
-
-static void viafb_int_init(void)
-{
-	viafb_enabled_ints = 0;
-
-	viafb_mmio_write(VDE_INTERRUPT, 0);
-}
-
-/*
- * Allow subdevs to ask for specific interrupts to be enabled.  These
- * functions must be called with reg_lock held
- */
-void viafb_irq_enable(u32 mask)
-{
-	viafb_enabled_ints |= mask;
-	viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE);
-}
-EXPORT_SYMBOL_GPL(viafb_irq_enable);
-
-void viafb_irq_disable(u32 mask)
-{
-	viafb_enabled_ints &= ~mask;
-	if (viafb_enabled_ints == 0)
-		viafb_mmio_write(VDE_INTERRUPT, 0);  /* Disable entirely */
-	else
-		viafb_mmio_write(VDE_INTERRUPT,
-				viafb_enabled_ints | VDE_I_ENABLE);
-}
-EXPORT_SYMBOL_GPL(viafb_irq_disable);
-
-/* ---------------------------------------------------------------------- */
-/*
- * Currently, the camera driver is the only user of the DMA code, so we
- * only compile it in if the camera driver is being built.  Chances are,
- * most viafb systems will not need to have this extra code for a while.
- * As soon as another user comes long, the ifdef can be removed.
- */
-#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
-/*
- * Access to the DMA engine.  This currently provides what the camera
- * driver needs (i.e. outgoing only) but is easily expandable if need
- * be.
- */
-
-/*
- * There are four DMA channels in the vx855.  For now, we only
- * use one of them, though.  Most of the time, the DMA channel
- * will be idle, so we keep the IRQ handler unregistered except
- * when some subsystem has indicated an interest.
- */
-static int viafb_dma_users;
-static DECLARE_COMPLETION(viafb_dma_completion);
-/*
- * This mutex protects viafb_dma_users and our global interrupt
- * registration state; it also serializes access to the DMA
- * engine.
- */
-static DEFINE_MUTEX(viafb_dma_lock);
-
-/*
- * The VX855 DMA descriptor (used for s/g transfers) looks
- * like this.
- */
-struct viafb_vx855_dma_descr {
-	u32	addr_low;	/* Low part of phys addr */
-	u32	addr_high;	/* High 12 bits of addr */
-	u32	fb_offset;	/* Offset into FB memory */
-	u32	seg_size;	/* Size, 16-byte units */
-	u32	tile_mode;	/* "tile mode" setting */
-	u32	next_desc_low;	/* Next descriptor addr */
-	u32	next_desc_high;
-	u32	pad;		/* Fill out to 64 bytes */
-};
-
-/*
- * Flags added to the "next descriptor low" pointers
- */
-#define VIAFB_DMA_MAGIC		0x01  /* ??? Just has to be there */
-#define VIAFB_DMA_FINAL_SEGMENT 0x02  /* Final segment */
-
-/*
- * The completion IRQ handler.
- */
-static irqreturn_t viafb_dma_irq(int irq, void *data)
-{
-	int csr;
-	irqreturn_t ret = IRQ_NONE;
-
-	spin_lock(&global_dev.reg_lock);
-	csr = viafb_mmio_read(VDMA_CSR0);
-	if (csr & VDMA_C_DONE) {
-		viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
-		complete(&viafb_dma_completion);
-		ret = IRQ_HANDLED;
-	}
-	spin_unlock(&global_dev.reg_lock);
-	return ret;
-}
-
-/*
- * Indicate a need for DMA functionality.
- */
-int viafb_request_dma(void)
-{
-	int ret = 0;
-
-	/*
-	 * Only VX855 is supported currently.
-	 */
-	if (global_dev.chip_type != UNICHROME_VX855)
-		return -ENODEV;
-	/*
-	 * Note the new user and set up our interrupt handler
-	 * if need be.
-	 */
-	mutex_lock(&viafb_dma_lock);
-	viafb_dma_users++;
-	if (viafb_dma_users == 1) {
-		ret = request_irq(global_dev.pdev->irq, viafb_dma_irq,
-				IRQF_SHARED, "via-dma", &viafb_dma_users);
-		if (ret)
-			viafb_dma_users--;
-		else
-			viafb_irq_enable(VDE_I_DMA0TDEN);
-	}
-	mutex_unlock(&viafb_dma_lock);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(viafb_request_dma);
-
-void viafb_release_dma(void)
-{
-	mutex_lock(&viafb_dma_lock);
-	viafb_dma_users--;
-	if (viafb_dma_users == 0) {
-		viafb_irq_disable(VDE_I_DMA0TDEN);
-		free_irq(global_dev.pdev->irq, &viafb_dma_users);
-	}
-	mutex_unlock(&viafb_dma_lock);
-}
-EXPORT_SYMBOL_GPL(viafb_release_dma);
-
-
-#if 0
-/*
- * Copy a single buffer from FB memory, synchronously.  This code works
- * but is not currently used.
- */
-void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len)
-{
-	unsigned long flags;
-	int csr;
-
-	mutex_lock(&viafb_dma_lock);
-	init_completion(&viafb_dma_completion);
-	/*
-	 * Program the controller.
-	 */
-	spin_lock_irqsave(&global_dev.reg_lock, flags);
-	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
-	/* Enable ints; must happen after CSR0 write! */
-	viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE);
-	viafb_mmio_write(VDMA_MARL0, (int) (paddr & 0xfffffff0));
-	viafb_mmio_write(VDMA_MARH0, (int) ((paddr >> 28) & 0xfff));
-	/* Data sheet suggests DAR0 should be <<4, but it lies */
-	viafb_mmio_write(VDMA_DAR0, offset);
-	viafb_mmio_write(VDMA_DQWCR0, len >> 4);
-	viafb_mmio_write(VDMA_TMR0, 0);
-	viafb_mmio_write(VDMA_DPRL0, 0);
-	viafb_mmio_write(VDMA_DPRH0, 0);
-	viafb_mmio_write(VDMA_PMR0, 0);
-	csr = viafb_mmio_read(VDMA_CSR0);
-	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
-	spin_unlock_irqrestore(&global_dev.reg_lock, flags);
-	/*
-	 * Now we just wait until the interrupt handler says
-	 * we're done.
-	 */
-	wait_for_completion_interruptible(&viafb_dma_completion);
-	viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
-	mutex_unlock(&viafb_dma_lock);
-}
-EXPORT_SYMBOL_GPL(viafb_dma_copy_out);
-#endif
-
-/*
- * Do a scatter/gather DMA copy from FB memory.  You must have done
- * a successful call to viafb_request_dma() first.
- */
-int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
-{
-	struct viafb_vx855_dma_descr *descr;
-	void *descrpages;
-	dma_addr_t descr_handle;
-	unsigned long flags;
-	int i;
-	struct scatterlist *sgentry;
-	dma_addr_t nextdesc;
-
-	/*
-	 * Get a place to put the descriptors.
-	 */
-	descrpages = dma_alloc_coherent(&global_dev.pdev->dev,
-			nsg*sizeof(struct viafb_vx855_dma_descr),
-			&descr_handle, GFP_KERNEL);
-	if (descrpages == NULL) {
-		dev_err(&global_dev.pdev->dev, "Unable to get descr page.\n");
-		return -ENOMEM;
-	}
-	mutex_lock(&viafb_dma_lock);
-	/*
-	 * Fill them in.
-	 */
-	descr = descrpages;
-	nextdesc = descr_handle + sizeof(struct viafb_vx855_dma_descr);
-	for_each_sg(sg, sgentry, nsg, i) {
-		dma_addr_t paddr = sg_dma_address(sgentry);
-		descr->addr_low = paddr & 0xfffffff0;
-		descr->addr_high = ((u64) paddr >> 32) & 0x0fff;
-		descr->fb_offset = offset;
-		descr->seg_size = sg_dma_len(sgentry) >> 4;
-		descr->tile_mode = 0;
-		descr->next_desc_low = (nextdesc&0xfffffff0) | VIAFB_DMA_MAGIC;
-		descr->next_desc_high = ((u64) nextdesc >> 32) & 0x0fff;
-		descr->pad = 0xffffffff;  /* VIA driver does this */
-		offset += sg_dma_len(sgentry);
-		nextdesc += sizeof(struct viafb_vx855_dma_descr);
-		descr++;
-	}
-	descr[-1].next_desc_low = VIAFB_DMA_FINAL_SEGMENT|VIAFB_DMA_MAGIC;
-	/*
-	 * Program the engine.
-	 */
-	spin_lock_irqsave(&global_dev.reg_lock, flags);
-	init_completion(&viafb_dma_completion);
-	viafb_mmio_write(VDMA_DQWCR0, 0);
-	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
-	viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE | VDMA_MR_CHAIN);
-	viafb_mmio_write(VDMA_DPRL0, descr_handle | VIAFB_DMA_MAGIC);
-	viafb_mmio_write(VDMA_DPRH0,
-			(((u64)descr_handle >> 32) & 0x0fff) | 0xf0000);
-	(void) viafb_mmio_read(VDMA_CSR0);
-	viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
-	spin_unlock_irqrestore(&global_dev.reg_lock, flags);
-	/*
-	 * Now we just wait until the interrupt handler says
-	 * we're done.  Except that, actually, we need to wait a little
-	 * longer: the interrupts seem to jump the gun a little and we
-	 * get corrupted frames sometimes.
-	 */
-	wait_for_completion_timeout(&viafb_dma_completion, 1);
-	msleep(1);
-	if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0)
-		printk(KERN_ERR "VIA DMA timeout!\n");
-	/*
-	 * Clean up and we're done.
-	 */
-	viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
-	viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
-	mutex_unlock(&viafb_dma_lock);
-	dma_free_coherent(&global_dev.pdev->dev,
-			nsg*sizeof(struct viafb_vx855_dma_descr), descrpages,
-			descr_handle);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
-#endif /* CONFIG_VIDEO_VIA_CAMERA */
-
-/* ---------------------------------------------------------------------- */
-/*
- * Figure out how big our framebuffer memory is.  Kind of ugly,
- * but evidently we can't trust the information found in the
- * fbdev configuration area.
- */
-static u16 via_function3[] = {
-	CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
-	CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
-	P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3,
-};
-
-/* Get the BIOS-configured framebuffer size from PCI configuration space
- * of function 3 in the respective chipset */
-static int viafb_get_fb_size_from_pci(int chip_type)
-{
-	int i;
-	u8 offset = 0;
-	u32 FBSize;
-	u32 VideoMemSize;
-
-	/* search for the "FUNCTION3" device in this chipset */
-	for (i = 0; i < ARRAY_SIZE(via_function3); i++) {
-		struct pci_dev *pdev;
-
-		pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
-				      NULL);
-		if (!pdev)
-			continue;
-
-		DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
-
-		switch (pdev->device) {
-		case CLE266_FUNCTION3:
-		case KM400_FUNCTION3:
-			offset = 0xE0;
-			break;
-		case CN400_FUNCTION3:
-		case CN700_FUNCTION3:
-		case CX700_FUNCTION3:
-		case KM800_FUNCTION3:
-		case KM890_FUNCTION3:
-		case P4M890_FUNCTION3:
-		case P4M900_FUNCTION3:
-		case VX800_FUNCTION3:
-		case VX855_FUNCTION3:
-		case VX900_FUNCTION3:
-		/*case CN750_FUNCTION3: */
-			offset = 0xA0;
-			break;
-		}
-
-		if (!offset)
-			break;
-
-		pci_read_config_dword(pdev, offset, &FBSize);
-		pci_dev_put(pdev);
-	}
-
-	if (!offset) {
-		printk(KERN_ERR "cannot determine framebuffer size\n");
-		return -EIO;
-	}
-
-	FBSize = FBSize & 0x00007000;
-	DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
-
-	if (chip_type < UNICHROME_CX700) {
-		switch (FBSize) {
-		case 0x00004000:
-			VideoMemSize = (16 << 20);	/*16M */
-			break;
-
-		case 0x00005000:
-			VideoMemSize = (32 << 20);	/*32M */
-			break;
-
-		case 0x00006000:
-			VideoMemSize = (64 << 20);	/*64M */
-			break;
-
-		default:
-			VideoMemSize = (32 << 20);	/*32M */
-			break;
-		}
-	} else {
-		switch (FBSize) {
-		case 0x00001000:
-			VideoMemSize = (8 << 20);	/*8M */
-			break;
-
-		case 0x00002000:
-			VideoMemSize = (16 << 20);	/*16M */
-			break;
-
-		case 0x00003000:
-			VideoMemSize = (32 << 20);	/*32M */
-			break;
-
-		case 0x00004000:
-			VideoMemSize = (64 << 20);	/*64M */
-			break;
-
-		case 0x00005000:
-			VideoMemSize = (128 << 20);	/*128M */
-			break;
-
-		case 0x00006000:
-			VideoMemSize = (256 << 20);	/*256M */
-			break;
-
-		case 0x00007000:	/* Only on VX855/875 */
-			VideoMemSize = (512 << 20);	/*512M */
-			break;
-
-		default:
-			VideoMemSize = (32 << 20);	/*32M */
-			break;
-		}
-	}
-
-	return VideoMemSize;
-}
-
-
-/*
- * Figure out and map our MMIO regions.
- */
-static int via_pci_setup_mmio(struct viafb_dev *vdev)
-{
-	int ret;
-	/*
-	 * Hook up to the device registers.  Note that we soldier
-	 * on if it fails; the framebuffer can operate (without
-	 * acceleration) without this region.
-	 */
-	vdev->engine_start = pci_resource_start(vdev->pdev, 1);
-	vdev->engine_len = pci_resource_len(vdev->pdev, 1);
-	vdev->engine_mmio = ioremap_nocache(vdev->engine_start,
-			vdev->engine_len);
-	if (vdev->engine_mmio == NULL)
-		dev_err(&vdev->pdev->dev,
-				"Unable to map engine MMIO; operation will be "
-				"slow and crippled.\n");
-	/*
-	 * Map in framebuffer memory.  For now, failure here is
-	 * fatal.  Unfortunately, in the absence of significant
-	 * vmalloc space, failure here is also entirely plausible.
-	 * Eventually we want to move away from mapping this
-	 * entire region.
-	 */
-	if (vdev->chip_type == UNICHROME_VX900)
-		vdev->fbmem_start = pci_resource_start(vdev->pdev, 2);
-	else
-		vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
-	ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
-	if (ret < 0)
-		goto out_unmap;
-
-	/* try to map less memory on failure, 8 MB should be still enough */
-	for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
-		vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
-		if (vdev->fbmem)
-			break;
-	}
-
-	if (vdev->fbmem == NULL) {
-		ret = -ENOMEM;
-		goto out_unmap;
-	}
-	return 0;
-out_unmap:
-	iounmap(vdev->engine_mmio);
-	return ret;
-}
-
-static void via_pci_teardown_mmio(struct viafb_dev *vdev)
-{
-	iounmap(vdev->fbmem);
-	iounmap(vdev->engine_mmio);
-}
-
-/*
- * Create our subsidiary devices.
- */
-static struct viafb_subdev_info {
-	char *name;
-	struct platform_device *platdev;
-} viafb_subdevs[] = {
-	{
-		.name = "viafb-gpio",
-	},
-	{
-		.name = "viafb-i2c",
-	},
-#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
-	{
-		.name = "viafb-camera",
-	},
-#endif
-};
-#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
-
-static int via_create_subdev(struct viafb_dev *vdev,
-			     struct viafb_subdev_info *info)
-{
-	int ret;
-
-	info->platdev = platform_device_alloc(info->name, -1);
-	if (!info->platdev) {
-		dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
-			info->name);
-		return -ENOMEM;
-	}
-	info->platdev->dev.parent = &vdev->pdev->dev;
-	info->platdev->dev.platform_data = vdev;
-	ret = platform_device_add(info->platdev);
-	if (ret) {
-		dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
-				info->name);
-		platform_device_put(info->platdev);
-		info->platdev = NULL;
-	}
-	return ret;
-}
-
-static int via_setup_subdevs(struct viafb_dev *vdev)
-{
-	int i;
-
-	/*
-	 * Ignore return values.  Even if some of the devices
-	 * fail to be created, we'll still be able to use some
-	 * of the rest.
-	 */
-	for (i = 0; i < N_SUBDEVS; i++)
-		via_create_subdev(vdev, viafb_subdevs + i);
-	return 0;
-}
-
-static void via_teardown_subdevs(void)
-{
-	int i;
-
-	for (i = 0; i < N_SUBDEVS; i++)
-		if (viafb_subdevs[i].platdev) {
-			viafb_subdevs[i].platdev->dev.platform_data = NULL;
-			platform_device_unregister(viafb_subdevs[i].platdev);
-		}
-}
-
-/*
- * Power management functions
- */
-#ifdef CONFIG_PM
-static LIST_HEAD(viafb_pm_hooks);
-static DEFINE_MUTEX(viafb_pm_hooks_lock);
-
-void viafb_pm_register(struct viafb_pm_hooks *hooks)
-{
-	INIT_LIST_HEAD(&hooks->list);
-
-	mutex_lock(&viafb_pm_hooks_lock);
-	list_add_tail(&hooks->list, &viafb_pm_hooks);
-	mutex_unlock(&viafb_pm_hooks_lock);
-}
-EXPORT_SYMBOL_GPL(viafb_pm_register);
-
-void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
-{
-	mutex_lock(&viafb_pm_hooks_lock);
-	list_del(&hooks->list);
-	mutex_unlock(&viafb_pm_hooks_lock);
-}
-EXPORT_SYMBOL_GPL(viafb_pm_unregister);
-
-static int via_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct viafb_pm_hooks *hooks;
-
-	if (state.event != PM_EVENT_SUSPEND)
-		return 0;
-	/*
-	 * "I've occasionally hit a few drivers that caused suspend
-	 * failures, and each and every time it was a driver bug, and
-	 * the right thing to do was to just ignore the error and suspend
-	 * anyway - returning an error code and trying to undo the suspend
-	 * is not what anybody ever really wants, even if our model
-	 *_allows_ for it."
-	 * -- Linus Torvalds, Dec. 7, 2009
-	 */
-	mutex_lock(&viafb_pm_hooks_lock);
-	list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
-		hooks->suspend(hooks->private);
-	mutex_unlock(&viafb_pm_hooks_lock);
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	return 0;
-}
-
-static int via_resume(struct pci_dev *pdev)
-{
-	struct viafb_pm_hooks *hooks;
-
-	/* Get the bus side powered up */
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	if (pci_enable_device(pdev))
-		return 0;
-
-	pci_set_master(pdev);
-
-	/* Now bring back any subdevs */
-	mutex_lock(&viafb_pm_hooks_lock);
-	list_for_each_entry(hooks, &viafb_pm_hooks, list)
-		hooks->resume(hooks->private);
-	mutex_unlock(&viafb_pm_hooks_lock);
-
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int ret;
-
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-
-	/*
-	 * Global device initialization.
-	 */
-	memset(&global_dev, 0, sizeof(global_dev));
-	global_dev.pdev = pdev;
-	global_dev.chip_type = ent->driver_data;
-	global_dev.port_cfg = adap_configs;
-	if (machine_is_olpc())
-		global_dev.port_cfg = olpc_adap_configs;
-
-	spin_lock_init(&global_dev.reg_lock);
-	ret = via_pci_setup_mmio(&global_dev);
-	if (ret)
-		goto out_disable;
-	/*
-	 * Set up interrupts and create our subdevices.  Continue even if
-	 * some things fail.
-	 */
-	viafb_int_init();
-	via_setup_subdevs(&global_dev);
-	/*
-	 * Set up the framebuffer device
-	 */
-	ret = via_fb_pci_probe(&global_dev);
-	if (ret)
-		goto out_subdevs;
-	return 0;
-
-out_subdevs:
-	via_teardown_subdevs();
-	via_pci_teardown_mmio(&global_dev);
-out_disable:
-	pci_disable_device(pdev);
-	return ret;
-}
-
-static void via_pci_remove(struct pci_dev *pdev)
-{
-	via_teardown_subdevs();
-	via_fb_pci_remove(pdev);
-	via_pci_teardown_mmio(&global_dev);
-	pci_disable_device(pdev);
-}
-
-
-static struct pci_device_id via_pci_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
-	  .driver_data = UNICHROME_CLE266 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
-	  .driver_data = UNICHROME_K400 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
-	  .driver_data = UNICHROME_K800 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
-	  .driver_data = UNICHROME_PM800 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN700_DID),
-	  .driver_data = UNICHROME_CN700 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
-	  .driver_data = UNICHROME_CX700 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
-	  .driver_data = UNICHROME_CN750 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
-	  .driver_data = UNICHROME_K8M890 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
-	  .driver_data = UNICHROME_P4M890 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
-	  .driver_data = UNICHROME_P4M900 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
-	  .driver_data = UNICHROME_VX800 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
-	  .driver_data = UNICHROME_VX855 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID),
-	  .driver_data = UNICHROME_VX900 },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, via_pci_table);
-
-static struct pci_driver via_driver = {
-	.name		= "viafb",
-	.id_table	= via_pci_table,
-	.probe		= via_pci_probe,
-	.remove		= via_pci_remove,
-#ifdef CONFIG_PM
-	.suspend	= via_suspend,
-	.resume		= via_resume,
-#endif
-};
-
-static int __init via_core_init(void)
-{
-	int ret;
-
-	ret = viafb_init();
-	if (ret)
-		return ret;
-	viafb_i2c_init();
-	viafb_gpio_init();
-	return pci_register_driver(&via_driver);
-}
-
-static void __exit via_core_exit(void)
-{
-	pci_unregister_driver(&via_driver);
-	viafb_gpio_exit();
-	viafb_i2c_exit();
-	viafb_exit();
-}
-
-module_init(via_core_init);
-module_exit(via_core_exit);
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c
deleted file mode 100644
index e408679081ab..000000000000
--- a/drivers/video/via/via-gpio.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Support for viafb GPIO ports.
- *
- * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
- * Distributable under version 2 of the GNU General Public License.
- */
-
-#include <linux/spinlock.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/via-core.h>
-#include <linux/via-gpio.h>
-#include <linux/export.h>
-
-/*
- * The ports we know about.  Note that the port-25 gpios are not
- * mentioned in the datasheet.
- */
-
-struct viafb_gpio {
-	char *vg_name;	/* Data sheet name */
-	u16 vg_io_port;
-	u8  vg_port_index;
-	int  vg_mask_shift;
-};
-
-static struct viafb_gpio viafb_all_gpios[] = {
-	{
-		.vg_name = "VGPIO0",  /* Guess - not in datasheet */
-		.vg_io_port = VIASR,
-		.vg_port_index = 0x25,
-		.vg_mask_shift = 1
-	},
-	{
-		.vg_name = "VGPIO1",
-		.vg_io_port = VIASR,
-		.vg_port_index = 0x25,
-		.vg_mask_shift = 0
-	},
-	{
-		.vg_name = "VGPIO2",  /* aka DISPCLKI0 */
-		.vg_io_port = VIASR,
-		.vg_port_index = 0x2c,
-		.vg_mask_shift = 1
-	},
-	{
-		.vg_name = "VGPIO3",  /* aka DISPCLKO0 */
-		.vg_io_port = VIASR,
-		.vg_port_index = 0x2c,
-		.vg_mask_shift = 0
-	},
-	{
-		.vg_name = "VGPIO4",  /* DISPCLKI1 */
-		.vg_io_port = VIASR,
-		.vg_port_index = 0x3d,
-		.vg_mask_shift = 1
-	},
-	{
-		.vg_name = "VGPIO5",  /* DISPCLKO1 */
-		.vg_io_port = VIASR,
-		.vg_port_index = 0x3d,
-		.vg_mask_shift = 0
-	},
-};
-
-#define VIAFB_NUM_GPIOS ARRAY_SIZE(viafb_all_gpios)
-
-/*
- * This structure controls the active GPIOs, which may be a subset
- * of those which are known.
- */
-
-struct viafb_gpio_cfg {
-	struct gpio_chip gpio_chip;
-	struct viafb_dev *vdev;
-	struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS];
-	const char *gpio_names[VIAFB_NUM_GPIOS];
-};
-
-/*
- * GPIO access functions
- */
-static void via_gpio_set(struct gpio_chip *chip, unsigned int nr,
-			 int value)
-{
-	struct viafb_gpio_cfg *cfg = container_of(chip,
-						  struct viafb_gpio_cfg,
-						  gpio_chip);
-	u8 reg;
-	struct viafb_gpio *gpio;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
-	gpio = cfg->active_gpios[nr];
-	reg = via_read_reg(VIASR, gpio->vg_port_index);
-	reg |= 0x40 << gpio->vg_mask_shift;  /* output enable */
-	if (value)
-		reg |= 0x10 << gpio->vg_mask_shift;
-	else
-		reg &= ~(0x10 << gpio->vg_mask_shift);
-	via_write_reg(VIASR, gpio->vg_port_index, reg);
-	spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
-}
-
-static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr,
-			    int value)
-{
-	via_gpio_set(chip, nr, value);
-	return 0;
-}
-
-/*
- * Set the input direction.  I'm not sure this is right; we should
- * be able to do input without disabling output.
- */
-static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr)
-{
-	struct viafb_gpio_cfg *cfg = container_of(chip,
-						  struct viafb_gpio_cfg,
-						  gpio_chip);
-	struct viafb_gpio *gpio;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
-	gpio = cfg->active_gpios[nr];
-	via_write_reg_mask(VIASR, gpio->vg_port_index, 0,
-			0x40 << gpio->vg_mask_shift);
-	spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
-	return 0;
-}
-
-static int via_gpio_get(struct gpio_chip *chip, unsigned int nr)
-{
-	struct viafb_gpio_cfg *cfg = container_of(chip,
-						  struct viafb_gpio_cfg,
-						  gpio_chip);
-	u8 reg;
-	struct viafb_gpio *gpio;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
-	gpio = cfg->active_gpios[nr];
-	reg = via_read_reg(VIASR, gpio->vg_port_index);
-	spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
-	return reg & (0x04 << gpio->vg_mask_shift);
-}
-
-
-static struct viafb_gpio_cfg viafb_gpio_config = {
-	.gpio_chip = {
-		.label = "VIAFB onboard GPIO",
-		.owner = THIS_MODULE,
-		.direction_output = via_gpio_dir_out,
-		.set = via_gpio_set,
-		.direction_input = via_gpio_dir_input,
-		.get = via_gpio_get,
-		.base = -1,
-		.ngpio = 0,
-		.can_sleep = 0
-	}
-};
-
-/*
- * Manage the software enable bit.
- */
-static void viafb_gpio_enable(struct viafb_gpio *gpio)
-{
-	via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02);
-}
-
-static void viafb_gpio_disable(struct viafb_gpio *gpio)
-{
-	via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
-}
-
-#ifdef CONFIG_PM
-
-static int viafb_gpio_suspend(void *private)
-{
-	return 0;
-}
-
-static int viafb_gpio_resume(void *private)
-{
-	int i;
-
-	for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
-		viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
-	return 0;
-}
-
-static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
-	.suspend = viafb_gpio_suspend,
-	.resume = viafb_gpio_resume
-};
-#endif /* CONFIG_PM */
-
-/*
- * Look up a specific gpio and return the number it was assigned.
- */
-int viafb_gpio_lookup(const char *name)
-{
-	int i;
-
-	for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++)
-		if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name))
-			return viafb_gpio_config.gpio_chip.base + i;
-	return -1;
-}
-EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
-
-/*
- * Platform device stuff.
- */
-static int viafb_gpio_probe(struct platform_device *platdev)
-{
-	struct viafb_dev *vdev = platdev->dev.platform_data;
-	struct via_port_cfg *port_cfg = vdev->port_cfg;
-	int i, ngpio = 0, ret;
-	struct viafb_gpio *gpio;
-	unsigned long flags;
-
-	/*
-	 * Set up entries for all GPIOs which have been configured to
-	 * operate as such (as opposed to as i2c ports).
-	 */
-	for (i = 0; i < VIAFB_NUM_PORTS; i++) {
-		if (port_cfg[i].mode != VIA_MODE_GPIO)
-			continue;
-		for (gpio = viafb_all_gpios;
-		     gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++)
-			if (gpio->vg_port_index == port_cfg[i].ioport_index) {
-				viafb_gpio_config.active_gpios[ngpio] = gpio;
-				viafb_gpio_config.gpio_names[ngpio] =
-					gpio->vg_name;
-				ngpio++;
-			}
-	}
-	viafb_gpio_config.gpio_chip.ngpio = ngpio;
-	viafb_gpio_config.gpio_chip.names = viafb_gpio_config.gpio_names;
-	viafb_gpio_config.vdev = vdev;
-	if (ngpio == 0) {
-		printk(KERN_INFO "viafb: no GPIOs configured\n");
-		return 0;
-	}
-	/*
-	 * Enable the ports.  They come in pairs, with a single
-	 * enable bit for both.
-	 */
-	spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
-	for (i = 0; i < ngpio; i += 2)
-		viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
-	spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
-	/*
-	 * Get registered.
-	 */
-	viafb_gpio_config.gpio_chip.base = -1;  /* Dynamic */
-	ret = gpiochip_add(&viafb_gpio_config.gpio_chip);
-	if (ret) {
-		printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
-		viafb_gpio_config.gpio_chip.ngpio = 0;
-	}
-#ifdef CONFIG_PM
-	viafb_pm_register(&viafb_gpio_pm_hooks);
-#endif
-	return ret;
-}
-
-
-static int viafb_gpio_remove(struct platform_device *platdev)
-{
-	unsigned long flags;
-	int ret = 0, i;
-
-#ifdef CONFIG_PM
-	viafb_pm_unregister(&viafb_gpio_pm_hooks);
-#endif
-
-	/*
-	 * Get unregistered.
-	 */
-	if (viafb_gpio_config.gpio_chip.ngpio > 0) {
-		ret = gpiochip_remove(&viafb_gpio_config.gpio_chip);
-		if (ret) { /* Somebody still using it? */
-			printk(KERN_ERR "Viafb: GPIO remove failed\n");
-			return ret;
-		}
-	}
-	/*
-	 * Disable the ports.
-	 */
-	spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
-	for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
-		viafb_gpio_disable(viafb_gpio_config.active_gpios[i]);
-	viafb_gpio_config.gpio_chip.ngpio = 0;
-	spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
-	return ret;
-}
-
-static struct platform_driver via_gpio_driver = {
-	.driver = {
-		.name = "viafb-gpio",
-	},
-	.probe = viafb_gpio_probe,
-	.remove = viafb_gpio_remove,
-};
-
-int viafb_gpio_init(void)
-{
-	return platform_driver_register(&via_gpio_driver);
-}
-
-void viafb_gpio_exit(void)
-{
-	platform_driver_unregister(&via_gpio_driver);
-}
diff --git a/drivers/video/via/via_aux.c b/drivers/video/via/via_aux.c
deleted file mode 100644
index 4a0a55cdac3d..000000000000
--- a/drivers/video/via/via_aux.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * infrastructure for devices connected via I2C
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap)
-{
-	struct via_aux_bus *bus;
-
-	if (!adap)
-		return NULL;
-
-	bus = kmalloc(sizeof(*bus), GFP_KERNEL);
-	if (!bus)
-		return NULL;
-
-	bus->adap = adap;
-	INIT_LIST_HEAD(&bus->drivers);
-
-	via_aux_edid_probe(bus);
-	via_aux_vt1636_probe(bus);
-	via_aux_vt1632_probe(bus);
-	via_aux_vt1631_probe(bus);
-	via_aux_vt1625_probe(bus);
-	via_aux_vt1622_probe(bus);
-	via_aux_vt1621_probe(bus);
-	via_aux_sii164_probe(bus);
-	via_aux_ch7301_probe(bus);
-
-	return bus;
-}
-
-void via_aux_free(struct via_aux_bus *bus)
-{
-	struct via_aux_drv *pos, *n;
-
-	if (!bus)
-		return;
-
-	list_for_each_entry_safe(pos, n, &bus->drivers, chain) {
-		if (pos->cleanup)
-			pos->cleanup(pos);
-
-		list_del(&pos->chain);
-		kfree(pos->data);
-		kfree(pos);
-	}
-
-	kfree(bus);
-}
-
-const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus)
-{
-	struct via_aux_drv *pos;
-	const struct fb_videomode *mode = NULL;
-
-	if (!bus)
-		return NULL;
-
-	list_for_each_entry(pos, &bus->drivers, chain) {
-		if (pos->get_preferred_mode)
-			mode = pos->get_preferred_mode(pos);
-	}
-
-	return mode;
-}
diff --git a/drivers/video/via/via_aux.h b/drivers/video/via/via_aux.h
deleted file mode 100644
index a8de3f038cea..000000000000
--- a/drivers/video/via/via_aux.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * infrastructure for devices connected via I2C
- */
-
-#ifndef __VIA_AUX_H__
-#define __VIA_AUX_H__
-
-
-#include <linux/list.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-
-
-struct via_aux_bus {
-	struct i2c_adapter *adap;	/* the I2C device to access the bus */
-	struct list_head drivers;	/* drivers for devices on this bus */
-};
-
-struct via_aux_drv {
-	struct list_head chain;		/* chain to support multiple drivers */
-
-	struct via_aux_bus *bus;	/* the I2C bus used */
-	u8 addr;			/* the I2C slave address */
-
-	const char *name;	/* human readable name of the driver */
-	void *data;		/* private data of this driver */
-
-	void (*cleanup)(struct via_aux_drv *drv);
-	const struct fb_videomode* (*get_preferred_mode)
-		(struct via_aux_drv *drv);
-};
-
-
-struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap);
-void via_aux_free(struct via_aux_bus *bus);
-const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus);
-
-
-static inline bool via_aux_add(struct via_aux_drv *drv)
-{
-	struct via_aux_drv *data = kmalloc(sizeof(*data), GFP_KERNEL);
-
-	if (!data)
-		return false;
-
-	*data = *drv;
-	list_add_tail(&data->chain, &data->bus->drivers);
-	return true;
-}
-
-static inline bool via_aux_read(struct via_aux_drv *drv, u8 start, u8 *buf,
-	u8 len)
-{
-	struct i2c_msg msg[2] = {
-		{.addr = drv->addr, .flags = 0, .len = 1, .buf = &start},
-		{.addr = drv->addr, .flags = I2C_M_RD, .len = len, .buf = buf} };
-
-	return i2c_transfer(drv->bus->adap, msg, 2) == 2;
-}
-
-
-/* probe functions of existing drivers - should only be called in via_aux.c */
-void via_aux_ch7301_probe(struct via_aux_bus *bus);
-void via_aux_edid_probe(struct via_aux_bus *bus);
-void via_aux_sii164_probe(struct via_aux_bus *bus);
-void via_aux_vt1636_probe(struct via_aux_bus *bus);
-void via_aux_vt1632_probe(struct via_aux_bus *bus);
-void via_aux_vt1631_probe(struct via_aux_bus *bus);
-void via_aux_vt1625_probe(struct via_aux_bus *bus);
-void via_aux_vt1622_probe(struct via_aux_bus *bus);
-void via_aux_vt1621_probe(struct via_aux_bus *bus);
-
-
-#endif /* __VIA_AUX_H__ */
diff --git a/drivers/video/via/via_aux_ch7301.c b/drivers/video/via/via_aux_ch7301.c
deleted file mode 100644
index 1cbe5037a6b0..000000000000
--- a/drivers/video/via/via_aux_ch7301.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for Chrontel CH7301 DVI Transmitter
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "CH7301 DVI Transmitter";
-
-
-static void probe(struct via_aux_bus *bus, u8 addr)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	addr,
-		.name	=	name};
-	u8 tmp;
-
-	if (!via_aux_read(&drv, 0x4B, &tmp, 1) || tmp != 0x17)
-		return;
-
-	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
-	via_aux_add(&drv);
-}
-
-void via_aux_ch7301_probe(struct via_aux_bus *bus)
-{
-	probe(bus, 0x75);
-	probe(bus, 0x76);
-}
diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c
deleted file mode 100644
index 754d4509033f..000000000000
--- a/drivers/video/via/via_aux_edid.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * generic EDID driver
- */
-
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include "via_aux.h"
-#include "../edid.h"
-
-
-static const char *name = "EDID";
-
-
-static void query_edid(struct via_aux_drv *drv)
-{
-	struct fb_monspecs *spec = drv->data;
-	unsigned char edid[EDID_LENGTH];
-	bool valid = false;
-
-	if (spec) {
-		fb_destroy_modedb(spec->modedb);
-	} else {
-		spec = kmalloc(sizeof(*spec), GFP_KERNEL);
-		if (!spec)
-			return;
-	}
-
-	spec->version = spec->revision = 0;
-	if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
-		fb_edid_to_monspecs(edid, spec);
-		valid = spec->version || spec->revision;
-	}
-
-	if (!valid) {
-		kfree(spec);
-		spec = NULL;
-	} else
-		printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor);
-
-	drv->data = spec;
-}
-
-static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv)
-{
-	struct fb_monspecs *spec = drv->data;
-	int i;
-
-	if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))
-		return NULL;
-
-	for (i = 0; i < spec->modedb_len; i++) {
-		if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&
-			spec->modedb[i].flag & FB_MODE_IS_DETAILED)
-			return &spec->modedb[i];
-	}
-
-	return NULL;
-}
-
-static void cleanup(struct via_aux_drv *drv)
-{
-	struct fb_monspecs *spec = drv->data;
-
-	if (spec)
-		fb_destroy_modedb(spec->modedb);
-}
-
-void via_aux_edid_probe(struct via_aux_bus *bus)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	0x50,
-		.name	=	name,
-		.cleanup	=	cleanup,
-		.get_preferred_mode	=	get_preferred_mode};
-
-	query_edid(&drv);
-
-	/* as EDID devices can be connected/disconnected just add the driver */
-	via_aux_add(&drv);
-}
diff --git a/drivers/video/via/via_aux_sii164.c b/drivers/video/via/via_aux_sii164.c
deleted file mode 100644
index ca1b35f033b1..000000000000
--- a/drivers/video/via/via_aux_sii164.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for Silicon Image SiI 164 PanelLink Transmitter
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "SiI 164 PanelLink Transmitter";
-
-
-static void probe(struct via_aux_bus *bus, u8 addr)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	addr,
-		.name	=	name};
-	/* check vendor id and device id */
-	const u8 id[] = {0x01, 0x00, 0x06, 0x00}, len = ARRAY_SIZE(id);
-	u8 tmp[len];
-
-	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
-		return;
-
-	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
-	via_aux_add(&drv);
-}
-
-void via_aux_sii164_probe(struct via_aux_bus *bus)
-{
-	u8 i;
-
-	for (i = 0x38; i <= 0x3F; i++)
-		probe(bus, i);
-}
diff --git a/drivers/video/via/via_aux_vt1621.c b/drivers/video/via/via_aux_vt1621.c
deleted file mode 100644
index 38eca8479898..000000000000
--- a/drivers/video/via/via_aux_vt1621.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for VIA VT1621(M) TV Encoder
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "VT1621(M) TV Encoder";
-
-
-void via_aux_vt1621_probe(struct via_aux_bus *bus)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	0x20,
-		.name	=	name};
-	u8 tmp;
-
-	if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x02)
-		return;
-
-	printk(KERN_INFO "viafb: Found %s\n", name);
-	via_aux_add(&drv);
-}
diff --git a/drivers/video/via/via_aux_vt1622.c b/drivers/video/via/via_aux_vt1622.c
deleted file mode 100644
index 8c79c68ba683..000000000000
--- a/drivers/video/via/via_aux_vt1622.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for VIA VT1622(M) Digital TV Encoder
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "VT1622(M) Digital TV Encoder";
-
-
-static void probe(struct via_aux_bus *bus, u8 addr)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	addr,
-		.name	=	name};
-	u8 tmp;
-
-	if (!via_aux_read(&drv, 0x1B, &tmp, 1) ||  tmp != 0x03)
-		return;
-
-	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
-	via_aux_add(&drv);
-}
-
-void via_aux_vt1622_probe(struct via_aux_bus *bus)
-{
-	probe(bus, 0x20);
-	probe(bus, 0x21);
-}
diff --git a/drivers/video/via/via_aux_vt1625.c b/drivers/video/via/via_aux_vt1625.c
deleted file mode 100644
index 03eb30165d36..000000000000
--- a/drivers/video/via/via_aux_vt1625.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for VIA VT1625(M) HDTV Encoder
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "VT1625(M) HDTV Encoder";
-
-
-static void probe(struct via_aux_bus *bus, u8 addr)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	addr,
-		.name	=	name};
-	u8 tmp;
-
-	if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x50)
-		return;
-
-	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
-	via_aux_add(&drv);
-}
-
-void via_aux_vt1625_probe(struct via_aux_bus *bus)
-{
-	probe(bus, 0x20);
-	probe(bus, 0x21);
-}
diff --git a/drivers/video/via/via_aux_vt1631.c b/drivers/video/via/via_aux_vt1631.c
deleted file mode 100644
index 06e742f1f723..000000000000
--- a/drivers/video/via/via_aux_vt1631.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for VIA VT1631 LVDS Transmitter
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "VT1631 LVDS Transmitter";
-
-
-void via_aux_vt1631_probe(struct via_aux_bus *bus)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	0x38,
-		.name	=	name};
-	/* check vendor id and device id */
-	const u8 id[] = {0x06, 0x11, 0x91, 0x31}, len = ARRAY_SIZE(id);
-	u8 tmp[len];
-
-	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
-		return;
-
-	printk(KERN_INFO "viafb: Found %s\n", name);
-	via_aux_add(&drv);
-}
diff --git a/drivers/video/via/via_aux_vt1632.c b/drivers/video/via/via_aux_vt1632.c
deleted file mode 100644
index d24f4cd97401..000000000000
--- a/drivers/video/via/via_aux_vt1632.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for VIA VT1632 DVI Transmitter
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "VT1632 DVI Transmitter";
-
-
-static void probe(struct via_aux_bus *bus, u8 addr)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	addr,
-		.name	=	name};
-	/* check vendor id and device id */
-	const u8 id[] = {0x06, 0x11, 0x92, 0x31}, len = ARRAY_SIZE(id);
-	u8 tmp[len];
-
-	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
-		return;
-
-	printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
-	via_aux_add(&drv);
-}
-
-void via_aux_vt1632_probe(struct via_aux_bus *bus)
-{
-	u8 i;
-
-	for (i = 0x08; i <= 0x0F; i++)
-		probe(bus, i);
-}
diff --git a/drivers/video/via/via_aux_vt1636.c b/drivers/video/via/via_aux_vt1636.c
deleted file mode 100644
index 9e015c101d4d..000000000000
--- a/drivers/video/via/via_aux_vt1636.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * driver for VIA VT1636 LVDS Transmitter
- */
-
-#include <linux/slab.h>
-#include "via_aux.h"
-
-
-static const char *name = "VT1636 LVDS Transmitter";
-
-
-void via_aux_vt1636_probe(struct via_aux_bus *bus)
-{
-	struct via_aux_drv drv = {
-		.bus	=	bus,
-		.addr	=	0x40,
-		.name	=	name};
-	/* check vendor id and device id */
-	const u8 id[] = {0x06, 0x11, 0x45, 0x33}, len = ARRAY_SIZE(id);
-	u8 tmp[len];
-
-	if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
-		return;
-
-	printk(KERN_INFO "viafb: Found %s\n", name);
-	via_aux_add(&drv);
-}
diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c
deleted file mode 100644
index db1e39277e32..000000000000
--- a/drivers/video/via/via_clock.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * clock and PLL management functions
- */
-
-#include <linux/kernel.h>
-#include <linux/via-core.h>
-#include <asm/olpc.h>
-#include "via_clock.h"
-#include "global.h"
-#include "debug.h"
-
-const char *via_slap = "Please slap VIA Technologies to motivate them "
-	"releasing full documentation for your platform!\n";
-
-static inline u32 cle266_encode_pll(struct via_pll_config pll)
-{
-	return (pll.multiplier << 8)
-		| (pll.rshift << 6)
-		| pll.divisor;
-}
-
-static inline u32 k800_encode_pll(struct via_pll_config pll)
-{
-	return ((pll.divisor - 2) << 16)
-		| (pll.rshift << 10)
-		| (pll.multiplier - 2);
-}
-
-static inline u32 vx855_encode_pll(struct via_pll_config pll)
-{
-	return (pll.divisor << 16)
-		| (pll.rshift << 10)
-		| pll.multiplier;
-}
-
-static inline void cle266_set_primary_pll_encoded(u32 data)
-{
-	via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
-	via_write_reg(VIASR, 0x46, data & 0xFF);
-	via_write_reg(VIASR, 0x47, (data >> 8) & 0xFF);
-	via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
-}
-
-static inline void k800_set_primary_pll_encoded(u32 data)
-{
-	via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
-	via_write_reg(VIASR, 0x44, data & 0xFF);
-	via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
-	via_write_reg(VIASR, 0x46, (data >> 16) & 0xFF);
-	via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
-}
-
-static inline void cle266_set_secondary_pll_encoded(u32 data)
-{
-	via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
-	via_write_reg(VIASR, 0x44, data & 0xFF);
-	via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
-	via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
-}
-
-static inline void k800_set_secondary_pll_encoded(u32 data)
-{
-	via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
-	via_write_reg(VIASR, 0x4A, data & 0xFF);
-	via_write_reg(VIASR, 0x4B, (data >> 8) & 0xFF);
-	via_write_reg(VIASR, 0x4C, (data >> 16) & 0xFF);
-	via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
-}
-
-static inline void set_engine_pll_encoded(u32 data)
-{
-	via_write_reg_mask(VIASR, 0x40, 0x01, 0x01); /* enable reset */
-	via_write_reg(VIASR, 0x47, data & 0xFF);
-	via_write_reg(VIASR, 0x48, (data >> 8) & 0xFF);
-	via_write_reg(VIASR, 0x49, (data >> 16) & 0xFF);
-	via_write_reg_mask(VIASR, 0x40, 0x00, 0x01); /* disable reset */
-}
-
-static void cle266_set_primary_pll(struct via_pll_config config)
-{
-	cle266_set_primary_pll_encoded(cle266_encode_pll(config));
-}
-
-static void k800_set_primary_pll(struct via_pll_config config)
-{
-	k800_set_primary_pll_encoded(k800_encode_pll(config));
-}
-
-static void vx855_set_primary_pll(struct via_pll_config config)
-{
-	k800_set_primary_pll_encoded(vx855_encode_pll(config));
-}
-
-static void cle266_set_secondary_pll(struct via_pll_config config)
-{
-	cle266_set_secondary_pll_encoded(cle266_encode_pll(config));
-}
-
-static void k800_set_secondary_pll(struct via_pll_config config)
-{
-	k800_set_secondary_pll_encoded(k800_encode_pll(config));
-}
-
-static void vx855_set_secondary_pll(struct via_pll_config config)
-{
-	k800_set_secondary_pll_encoded(vx855_encode_pll(config));
-}
-
-static void k800_set_engine_pll(struct via_pll_config config)
-{
-	set_engine_pll_encoded(k800_encode_pll(config));
-}
-
-static void vx855_set_engine_pll(struct via_pll_config config)
-{
-	set_engine_pll_encoded(vx855_encode_pll(config));
-}
-
-static void set_primary_pll_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x20;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x2D, value, 0x30);
-}
-
-static void set_secondary_pll_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x08;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x2D, value, 0x0C);
-}
-
-static void set_engine_pll_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x02;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x2D, value, 0x03);
-}
-
-static void set_primary_clock_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x20;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x1B, value, 0x30);
-}
-
-static void set_secondary_clock_state(u8 state)
-{
-	u8 value;
-
-	switch (state) {
-	case VIA_STATE_ON:
-		value = 0x80;
-		break;
-	case VIA_STATE_OFF:
-		value = 0x00;
-		break;
-	default:
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x1B, value, 0xC0);
-}
-
-static inline u8 set_clock_source_common(enum via_clksrc source, bool use_pll)
-{
-	u8 data = 0;
-
-	switch (source) {
-	case VIA_CLKSRC_X1:
-		data = 0x00;
-		break;
-	case VIA_CLKSRC_TVX1:
-		data = 0x02;
-		break;
-	case VIA_CLKSRC_TVPLL:
-		data = 0x04; /* 0x06 should be the same */
-		break;
-	case VIA_CLKSRC_DVP1TVCLKR:
-		data = 0x0A;
-		break;
-	case VIA_CLKSRC_CAP0:
-		data = 0xC;
-		break;
-	case VIA_CLKSRC_CAP1:
-		data = 0x0E;
-		break;
-	}
-
-	if (!use_pll)
-		data |= 1;
-
-	return data;
-}
-
-static void set_primary_clock_source(enum via_clksrc source, bool use_pll)
-{
-	u8 data = set_clock_source_common(source, use_pll) << 4;
-	via_write_reg_mask(VIACR, 0x6C, data, 0xF0);
-}
-
-static void set_secondary_clock_source(enum via_clksrc source, bool use_pll)
-{
-	u8 data = set_clock_source_common(source, use_pll);
-	via_write_reg_mask(VIACR, 0x6C, data, 0x0F);
-}
-
-static void dummy_set_clock_state(u8 state)
-{
-	printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap);
-}
-
-static void dummy_set_clock_source(enum via_clksrc source, bool use_pll)
-{
-	printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap);
-}
-
-static void dummy_set_pll_state(u8 state)
-{
-	printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap);
-}
-
-static void dummy_set_pll(struct via_pll_config config)
-{
-	printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
-}
-
-static void noop_set_clock_state(u8 state)
-{
-}
-
-void via_clock_init(struct via_clock *clock, int gfx_chip)
-{
-	switch (gfx_chip) {
-	case UNICHROME_CLE266:
-	case UNICHROME_K400:
-		clock->set_primary_clock_state = dummy_set_clock_state;
-		clock->set_primary_clock_source = dummy_set_clock_source;
-		clock->set_primary_pll_state = dummy_set_pll_state;
-		clock->set_primary_pll = cle266_set_primary_pll;
-
-		clock->set_secondary_clock_state = dummy_set_clock_state;
-		clock->set_secondary_clock_source = dummy_set_clock_source;
-		clock->set_secondary_pll_state = dummy_set_pll_state;
-		clock->set_secondary_pll = cle266_set_secondary_pll;
-
-		clock->set_engine_pll_state = dummy_set_pll_state;
-		clock->set_engine_pll = dummy_set_pll;
-		break;
-	case UNICHROME_K800:
-	case UNICHROME_PM800:
-	case UNICHROME_CN700:
-	case UNICHROME_CX700:
-	case UNICHROME_CN750:
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M890:
-	case UNICHROME_P4M900:
-	case UNICHROME_VX800:
-		clock->set_primary_clock_state = set_primary_clock_state;
-		clock->set_primary_clock_source = set_primary_clock_source;
-		clock->set_primary_pll_state = set_primary_pll_state;
-		clock->set_primary_pll = k800_set_primary_pll;
-
-		clock->set_secondary_clock_state = set_secondary_clock_state;
-		clock->set_secondary_clock_source = set_secondary_clock_source;
-		clock->set_secondary_pll_state = set_secondary_pll_state;
-		clock->set_secondary_pll = k800_set_secondary_pll;
-
-		clock->set_engine_pll_state = set_engine_pll_state;
-		clock->set_engine_pll = k800_set_engine_pll;
-		break;
-	case UNICHROME_VX855:
-	case UNICHROME_VX900:
-		clock->set_primary_clock_state = set_primary_clock_state;
-		clock->set_primary_clock_source = set_primary_clock_source;
-		clock->set_primary_pll_state = set_primary_pll_state;
-		clock->set_primary_pll = vx855_set_primary_pll;
-
-		clock->set_secondary_clock_state = set_secondary_clock_state;
-		clock->set_secondary_clock_source = set_secondary_clock_source;
-		clock->set_secondary_pll_state = set_secondary_pll_state;
-		clock->set_secondary_pll = vx855_set_secondary_pll;
-
-		clock->set_engine_pll_state = set_engine_pll_state;
-		clock->set_engine_pll = vx855_set_engine_pll;
-		break;
-
-	}
-
-	if (machine_is_olpc()) {
-		/* The OLPC XO-1.5 cannot suspend/resume reliably if the
-		 * IGA1/IGA2 clocks are set as on or off (memory rot
-		 * occasionally happens during suspend under such
-		 * configurations).
-		 *
-		 * The only known stable scenario is to leave this bits as-is,
-		 * which in their default states are documented to enable the
-		 * clock only when it is needed.
-		 */
-		clock->set_primary_clock_state = noop_set_clock_state;
-		clock->set_secondary_clock_state = noop_set_clock_state;
-	}
-}
diff --git a/drivers/video/via/via_clock.h b/drivers/video/via/via_clock.h
deleted file mode 100644
index 88714ae0d157..000000000000
--- a/drivers/video/via/via_clock.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
- * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * clock and PLL management functions
- */
-
-#ifndef __VIA_CLOCK_H__
-#define __VIA_CLOCK_H__
-
-#include <linux/types.h>
-
-enum via_clksrc {
-	VIA_CLKSRC_X1 = 0,
-	VIA_CLKSRC_TVX1,
-	VIA_CLKSRC_TVPLL,
-	VIA_CLKSRC_DVP1TVCLKR,
-	VIA_CLKSRC_CAP0,
-	VIA_CLKSRC_CAP1,
-};
-
-struct via_pll_config {
-	u16 multiplier;
-	u8 divisor;
-	u8 rshift;
-};
-
-struct via_clock {
-	void (*set_primary_clock_state)(u8 state);
-	void (*set_primary_clock_source)(enum via_clksrc src, bool use_pll);
-	void (*set_primary_pll_state)(u8 state);
-	void (*set_primary_pll)(struct via_pll_config config);
-
-	void (*set_secondary_clock_state)(u8 state);
-	void (*set_secondary_clock_source)(enum via_clksrc src, bool use_pll);
-	void (*set_secondary_pll_state)(u8 state);
-	void (*set_secondary_pll)(struct via_pll_config config);
-
-	void (*set_engine_pll_state)(u8 state);
-	void (*set_engine_pll)(struct via_pll_config config);
-};
-
-
-static inline u32 get_pll_internal_frequency(u32 ref_freq,
-	struct via_pll_config pll)
-{
-	return ref_freq / pll.divisor * pll.multiplier;
-}
-
-static inline u32 get_pll_output_frequency(u32 ref_freq,
-	struct via_pll_config pll)
-{
-	return get_pll_internal_frequency(ref_freq, pll) >> pll.rshift;
-}
-
-void via_clock_init(struct via_clock *clock, int gfx_chip);
-
-#endif /* __VIA_CLOCK_H__ */
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
deleted file mode 100644
index dd53058bbbb7..000000000000
--- a/drivers/video/via/via_i2c.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/via-core.h>
-#include <linux/via_i2c.h>
-
-/*
- * There can only be one set of these, so there's no point in having
- * them be dynamically allocated...
- */
-#define VIAFB_NUM_I2C		5
-static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
-static struct viafb_dev *i2c_vdev;  /* Passed in from core */
-
-static void via_i2c_setscl(void *data, int state)
-{
-	u8 val;
-	struct via_port_cfg *adap_data = data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
-	val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
-	if (state)
-		val |= 0x20;
-	else
-		val &= ~0x20;
-	switch (adap_data->type) {
-	case VIA_PORT_I2C:
-		val |= 0x01;
-		break;
-	case VIA_PORT_GPIO:
-		val |= 0x82;
-		break;
-	default:
-		printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
-	}
-	via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
-	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
-}
-
-static int via_i2c_getscl(void *data)
-{
-	struct via_port_cfg *adap_data = data;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
-	if (adap_data->type == VIA_PORT_GPIO)
-		via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
-			0, 0x80);
-	if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08)
-		ret = 1;
-	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
-	return ret;
-}
-
-static int via_i2c_getsda(void *data)
-{
-	struct via_port_cfg *adap_data = data;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
-	if (adap_data->type == VIA_PORT_GPIO)
-		via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
-			0, 0x40);
-	if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04)
-		ret = 1;
-	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
-	return ret;
-}
-
-static void via_i2c_setsda(void *data, int state)
-{
-	u8 val;
-	struct via_port_cfg *adap_data = data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
-	val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
-	if (state)
-		val |= 0x10;
-	else
-		val &= ~0x10;
-	switch (adap_data->type) {
-	case VIA_PORT_I2C:
-		val |= 0x01;
-		break;
-	case VIA_PORT_GPIO:
-		val |= 0x42;
-		break;
-	default:
-		printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
-	}
-	via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
-	spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
-}
-
-int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
-{
-	int ret;
-	u8 mm1[] = {0x00};
-	struct i2c_msg msgs[2];
-
-	if (!via_i2c_par[adap].is_active)
-		return -ENODEV;
-	*pdata = 0;
-	msgs[0].flags = 0;
-	msgs[1].flags = I2C_M_RD;
-	msgs[0].addr = msgs[1].addr = slave_addr / 2;
-	mm1[0] = index;
-	msgs[0].len = 1; msgs[1].len = 1;
-	msgs[0].buf = mm1; msgs[1].buf = pdata;
-	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
-	if (ret == 2)
-		ret = 0;
-	else if (ret >= 0)
-		ret = -EIO;
-
-	return ret;
-}
-
-int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
-{
-	int ret;
-	u8 msg[2] = { index, data };
-	struct i2c_msg msgs;
-
-	if (!via_i2c_par[adap].is_active)
-		return -ENODEV;
-	msgs.flags = 0;
-	msgs.addr = slave_addr / 2;
-	msgs.len = 2;
-	msgs.buf = msg;
-	ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
-	if (ret == 1)
-		ret = 0;
-	else if (ret >= 0)
-		ret = -EIO;
-
-	return ret;
-}
-
-int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
-{
-	int ret;
-	u8 mm1[] = {0x00};
-	struct i2c_msg msgs[2];
-
-	if (!via_i2c_par[adap].is_active)
-		return -ENODEV;
-	msgs[0].flags = 0;
-	msgs[1].flags = I2C_M_RD;
-	msgs[0].addr = msgs[1].addr = slave_addr / 2;
-	mm1[0] = index;
-	msgs[0].len = 1; msgs[1].len = buff_len;
-	msgs[0].buf = mm1; msgs[1].buf = buff;
-	ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
-	if (ret == 2)
-		ret = 0;
-	else if (ret >= 0)
-		ret = -EIO;
-
-	return ret;
-}
-
-/*
- * Allow other viafb subdevices to look up a specific adapter
- * by port name.
- */
-struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which)
-{
-	struct via_i2c_stuff *stuff = &via_i2c_par[which];
-
-	return &stuff->adapter;
-}
-EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter);
-
-
-static int create_i2c_bus(struct i2c_adapter *adapter,
-			  struct i2c_algo_bit_data *algo,
-			  struct via_port_cfg *adap_cfg,
-			  struct pci_dev *pdev)
-{
-	algo->setsda = via_i2c_setsda;
-	algo->setscl = via_i2c_setscl;
-	algo->getsda = via_i2c_getsda;
-	algo->getscl = via_i2c_getscl;
-	algo->udelay = 10;
-	algo->timeout = 2;
-	algo->data = adap_cfg;
-
-	sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
-		adap_cfg->ioport_index);
-	adapter->owner = THIS_MODULE;
-	adapter->class = I2C_CLASS_DDC;
-	adapter->algo_data = algo;
-	if (pdev)
-		adapter->dev.parent = &pdev->dev;
-	else
-		adapter->dev.parent = NULL;
-	/* i2c_set_adapdata(adapter, adap_cfg); */
-
-	/* Raise SCL and SDA */
-	via_i2c_setsda(adap_cfg, 1);
-	via_i2c_setscl(adap_cfg, 1);
-	udelay(20);
-
-	return i2c_bit_add_bus(adapter);
-}
-
-static int viafb_i2c_probe(struct platform_device *platdev)
-{
-	int i, ret;
-	struct via_port_cfg *configs;
-
-	i2c_vdev = platdev->dev.platform_data;
-	configs = i2c_vdev->port_cfg;
-
-	for (i = 0; i < VIAFB_NUM_PORTS; i++) {
-		struct via_port_cfg *adap_cfg = configs++;
-		struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
-
-		i2c_stuff->is_active = 0;
-		if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C)
-			continue;
-		ret = create_i2c_bus(&i2c_stuff->adapter,
-				     &i2c_stuff->algo, adap_cfg,
-				NULL); /* FIXME: PCIDEV */
-		if (ret < 0) {
-			printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n",
-				i, ret);
-			continue;  /* Still try to make the rest */
-		}
-		i2c_stuff->is_active = 1;
-	}
-
-	return 0;
-}
-
-static int viafb_i2c_remove(struct platform_device *platdev)
-{
-	int i;
-
-	for (i = 0; i < VIAFB_NUM_PORTS; i++) {
-		struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
-		/*
-		 * Only remove those entries in the array that we've
-		 * actually used (and thus initialized algo_data)
-		 */
-		if (i2c_stuff->is_active)
-			i2c_del_adapter(&i2c_stuff->adapter);
-	}
-	return 0;
-}
-
-static struct platform_driver via_i2c_driver = {
-	.driver = {
-		.name = "viafb-i2c",
-	},
-	.probe = viafb_i2c_probe,
-	.remove = viafb_i2c_remove,
-};
-
-int viafb_i2c_init(void)
-{
-	return platform_driver_register(&via_i2c_driver);
-}
-
-void viafb_i2c_exit(void)
-{
-	platform_driver_unregister(&via_i2c_driver);
-}
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
deleted file mode 100644
index 0b414b09b9b4..000000000000
--- a/drivers/video/via/via_modesetting.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
- * Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * basic modesetting functions
- */
-
-#include <linux/kernel.h>
-#include <linux/via-core.h>
-#include "via_modesetting.h"
-#include "share.h"
-#include "debug.h"
-
-
-void via_set_primary_timing(const struct via_display_timing *timing)
-{
-	struct via_display_timing raw;
-
-	raw.hor_total = timing->hor_total / 8 - 5;
-	raw.hor_addr = timing->hor_addr / 8 - 1;
-	raw.hor_blank_start = timing->hor_blank_start / 8 - 1;
-	raw.hor_blank_end = timing->hor_blank_end / 8 - 1;
-	raw.hor_sync_start = timing->hor_sync_start / 8;
-	raw.hor_sync_end = timing->hor_sync_end / 8;
-	raw.ver_total = timing->ver_total - 2;
-	raw.ver_addr = timing->ver_addr - 1;
-	raw.ver_blank_start = timing->ver_blank_start - 1;
-	raw.ver_blank_end = timing->ver_blank_end - 1;
-	raw.ver_sync_start = timing->ver_sync_start - 1;
-	raw.ver_sync_end = timing->ver_sync_end - 1;
-
-	/* unlock timing registers */
-	via_write_reg_mask(VIACR, 0x11, 0x00, 0x80);
-
-	via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF);
-	via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF);
-	via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF);
-	via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F);
-	via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF);
-	via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F)
-		| (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F);
-	via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF);
-	via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01)
-		| (raw.ver_addr >> (8 - 1) & 0x02)
-		| (raw.ver_sync_start >> (8 - 2) & 0x04)
-		| (raw.ver_blank_start >> (8 - 3) & 0x08)
-		| (raw.ver_total >> (9 - 5) & 0x20)
-		| (raw.ver_addr >> (9 - 6) & 0x40)
-		| (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF);
-	via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20,
-		0x20);
-	via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF);
-	via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F);
-	via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF);
-	via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF);
-	via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF);
-	via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10)
-		| (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30);
-	via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01)
-		| (raw.ver_sync_start >> (10 - 1) & 0x02)
-		| (raw.ver_addr >> (10 - 2) & 0x04)
-		| (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F);
-	via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08);
-
-	/* lock timing registers */
-	via_write_reg_mask(VIACR, 0x11, 0x80, 0x80);
-
-	/* reset timing control */
-	via_write_reg_mask(VIACR, 0x17, 0x00, 0x80);
-	via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
-}
-
-void via_set_secondary_timing(const struct via_display_timing *timing)
-{
-	struct via_display_timing raw;
-
-	raw.hor_total = timing->hor_total - 1;
-	raw.hor_addr = timing->hor_addr - 1;
-	raw.hor_blank_start = timing->hor_blank_start - 1;
-	raw.hor_blank_end = timing->hor_blank_end - 1;
-	raw.hor_sync_start = timing->hor_sync_start - 1;
-	raw.hor_sync_end = timing->hor_sync_end - 1;
-	raw.ver_total = timing->ver_total - 1;
-	raw.ver_addr = timing->ver_addr - 1;
-	raw.ver_blank_start = timing->ver_blank_start - 1;
-	raw.ver_blank_end = timing->ver_blank_end - 1;
-	raw.ver_sync_start = timing->ver_sync_start - 1;
-	raw.ver_sync_end = timing->ver_sync_end - 1;
-
-	via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF);
-	via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF);
-	via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF);
-	via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF);
-	via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07)
-		| (raw.hor_blank_end >> (8 - 3) & 0x38)
-		| (raw.hor_sync_start >> (8 - 6) & 0xC0));
-	via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F)
-		| (raw.hor_addr >> (8 - 4) & 0x70), 0x7F);
-	via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF);
-	via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF);
-	via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF);
-	via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF);
-	via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF);
-	via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF);
-	via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07)
-		| (raw.ver_blank_end >> (8 - 3) & 0x38)
-		| (raw.hor_sync_end >> (8 - 6) & 0x40)
-		| (raw.hor_sync_start >> (10 - 7) & 0x80));
-	via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07)
-		| (raw.ver_addr >> (8 - 3) & 0x38)
-		| (raw.hor_blank_end >> (11 - 6) & 0x40)
-		| (raw.hor_sync_start >> (11 - 7) & 0x80));
-	via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF);
-	via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F)
-		| (raw.ver_sync_start >> (8 - 5) & 0xE0));
-}
-
-void via_set_primary_address(u32 addr)
-{
-	DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
-	via_write_reg(VIACR, 0x0D, addr & 0xFF);
-	via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF);
-	via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF);
-	via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F);
-}
-
-void via_set_secondary_address(u32 addr)
-{
-	DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr);
-	/* secondary display supports only quadword aligned memory */
-	via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE);
-	via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF);
-	via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF);
-	via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07);
-}
-
-void via_set_primary_pitch(u32 pitch)
-{
-	DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch);
-	/* spec does not say that first adapter skips 3 bits but old
-	 * code did it and seems to be reasonable in analogy to 2nd adapter
-	 */
-	pitch = pitch >> 3;
-	via_write_reg(VIACR, 0x13, pitch & 0xFF);
-	via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0);
-}
-
-void via_set_secondary_pitch(u32 pitch)
-{
-	DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch);
-	pitch = pitch >> 3;
-	via_write_reg(VIACR, 0x66, pitch & 0xFF);
-	via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03);
-	via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80);
-}
-
-void via_set_primary_color_depth(u8 depth)
-{
-	u8 value;
-
-	DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth);
-	switch (depth) {
-	case 8:
-		value = 0x00;
-		break;
-	case 15:
-		value = 0x04;
-		break;
-	case 16:
-		value = 0x14;
-		break;
-	case 24:
-		value = 0x0C;
-		break;
-	case 30:
-		value = 0x08;
-		break;
-	default:
-		printk(KERN_WARNING "via_set_primary_color_depth: "
-			"Unsupported depth: %d\n", depth);
-		return;
-	}
-
-	via_write_reg_mask(VIASR, 0x15, value, 0x1C);
-}
-
-void via_set_secondary_color_depth(u8 depth)
-{
-	u8 value;
-
-	DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth);
-	switch (depth) {
-	case 8:
-		value = 0x00;
-		break;
-	case 16:
-		value = 0x40;
-		break;
-	case 24:
-		value = 0xC0;
-		break;
-	case 30:
-		value = 0x80;
-		break;
-	default:
-		printk(KERN_WARNING "via_set_secondary_color_depth: "
-			"Unsupported depth: %d\n", depth);
-		return;
-	}
-
-	via_write_reg_mask(VIACR, 0x67, value, 0xC0);
-}
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
deleted file mode 100644
index f6a6503da3b3..000000000000
--- a/drivers/video/via/via_modesetting.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
- * Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * basic modesetting functions
- */
-
-#ifndef __VIA_MODESETTING_H__
-#define __VIA_MODESETTING_H__
-
-#include <linux/types.h>
-
-
-#define VIA_PITCH_SIZE	(1<<3)
-#define VIA_PITCH_MAX	0x3FF8
-
-
-struct via_display_timing {
-	u16 hor_total;
-	u16 hor_addr;
-	u16 hor_blank_start;
-	u16 hor_blank_end;
-	u16 hor_sync_start;
-	u16 hor_sync_end;
-	u16 ver_total;
-	u16 ver_addr;
-	u16 ver_blank_start;
-	u16 ver_blank_end;
-	u16 ver_sync_start;
-	u16 ver_sync_end;
-};
-
-
-void via_set_primary_timing(const struct via_display_timing *timing);
-void via_set_secondary_timing(const struct via_display_timing *timing);
-void via_set_primary_address(u32 addr);
-void via_set_secondary_address(u32 addr);
-void via_set_primary_pitch(u32 pitch);
-void via_set_secondary_pitch(u32 pitch);
-void via_set_primary_color_depth(u8 depth);
-void via_set_secondary_color_depth(u8 depth);
-
-#endif /* __VIA_MODESETTING_H__ */
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c
deleted file mode 100644
index 35458a5eadc8..000000000000
--- a/drivers/video/via/via_utility.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/via-core.h>
-#include "global.h"
-
-void viafb_get_device_support_state(u32 *support_state)
-{
-	*support_state = CRT_Device;
-
-	if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS)
-		*support_state |= DVI_Device;
-
-	if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS)
-		*support_state |= LCD_Device;
-}
-
-void viafb_get_device_connect_state(u32 *connect_state)
-{
-	bool mobile = false;
-
-	*connect_state = CRT_Device;
-
-	if (viafb_dvi_sense())
-		*connect_state |= DVI_Device;
-
-	viafb_lcd_get_mobile_state(&mobile);
-	if (mobile)
-		*connect_state |= LCD_Device;
-}
-
-bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres)
-{
-	unsigned int support_state = 0;
-
-	switch (viafb_lcd_panel_id) {
-	case LCD_PANEL_ID0_640X480:
-		if ((xres < 640) && (yres < 480))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID1_800X600:
-		if ((xres < 800) && (yres < 600))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID2_1024X768:
-		if ((xres < 1024) && (yres < 768))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID3_1280X768:
-		if ((xres < 1280) && (yres < 768))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID4_1280X1024:
-		if ((xres < 1280) && (yres < 1024))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID5_1400X1050:
-		if ((xres < 1400) && (yres < 1050))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID6_1600X1200:
-		if ((xres < 1600) && (yres < 1200))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID7_1366X768:
-		if ((xres < 1366) && (yres < 768))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID8_1024X600:
-		if ((xres < 1024) && (yres < 600))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_ID9_1280X800:
-		if ((xres < 1280) && (yres < 800))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_IDA_800X480:
-		if ((xres < 800) && (yres < 480))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_IDB_1360X768:
-		if ((xres < 1360) && (yres < 768))
-			support_state = true;
-		break;
-
-	case LCD_PANEL_IDC_480X640:
-		if ((xres < 480) && (yres < 640))
-			support_state = true;
-		break;
-
-	default:
-		support_state = false;
-		break;
-	}
-
-	return support_state;
-}
-
-/*====================================================================*/
-/*                      Gamma Function Implementation*/
-/*====================================================================*/
-
-void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
-{
-	int i, sr1a;
-	int active_device_amount = 0;
-	int device_status = viafb_DeviceStatus;
-
-	for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) {
-		if (device_status & 1)
-			active_device_amount++;
-		device_status >>= 1;
-	}
-
-	/* 8 bpp mode can't adjust gamma */
-	if (bpp == 8)
-		return ;
-
-	/* Enable Gamma */
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_CLE266:
-	case UNICHROME_K400:
-		viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
-		break;
-
-	case UNICHROME_K800:
-	case UNICHROME_PM800:
-	case UNICHROME_CN700:
-	case UNICHROME_CX700:
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M890:
-	case UNICHROME_P4M900:
-		viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
-		break;
-	}
-	sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A);
-	viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
-
-	/* Fill IGA1 Gamma Table */
-	outb(0, LUT_INDEX_WRITE);
-	for (i = 0; i < 256; i++) {
-		outb(gamma_table[i] >> 16, LUT_DATA);
-		outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
-		outb(gamma_table[i] & 0xFF, LUT_DATA);
-	}
-
-	/* If adjust Gamma value in SAMM, fill IGA1,
-	   IGA2 Gamma table simultaneous. */
-	/* Switch to IGA2 Gamma Table */
-	if ((active_device_amount > 1) &&
-		!((viaparinfo->chip_info->gfx_chip_name ==
-		UNICHROME_CLE266) &&
-		(viaparinfo->chip_info->gfx_chip_revision < 15))) {
-		viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
-		viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1);
-
-		/* Fill IGA2 Gamma Table */
-		outb(0, LUT_INDEX_WRITE);
-		for (i = 0; i < 256; i++) {
-			outb(gamma_table[i] >> 16, LUT_DATA);
-			outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
-			outb(gamma_table[i] & 0xFF, LUT_DATA);
-		}
-	}
-	viafb_write_reg(SR1A, VIASR, sr1a);
-}
-
-void viafb_get_gamma_table(unsigned int *gamma_table)
-{
-	unsigned char color_r, color_g, color_b;
-	unsigned char sr1a = 0;
-	int i;
-
-	/* Enable Gamma */
-	switch (viaparinfo->chip_info->gfx_chip_name) {
-	case UNICHROME_CLE266:
-	case UNICHROME_K400:
-		viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
-		break;
-
-	case UNICHROME_K800:
-	case UNICHROME_PM800:
-	case UNICHROME_CN700:
-	case UNICHROME_CX700:
-	case UNICHROME_K8M890:
-	case UNICHROME_P4M890:
-	case UNICHROME_P4M900:
-		viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
-		break;
-	}
-	sr1a = viafb_read_reg(VIASR, SR1A);
-	viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
-
-	/* Reading gamma table to get color value */
-	outb(0, LUT_INDEX_READ);
-	for (i = 0; i < 256; i++) {
-		color_r = inb(LUT_DATA);
-		color_g = inb(LUT_DATA);
-		color_b = inb(LUT_DATA);
-		gamma_table[i] =
-		    ((((u32) color_r) << 16) |
-		     (((u16) color_g) << 8)) | color_b;
-	}
-	viafb_write_reg(SR1A, VIASR, sr1a);
-}
-
-void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
-{
-	if (bpp == 8)
-		*support_state = None_Device;
-	else
-		*support_state = CRT_Device | DVI_Device | LCD_Device;
-}
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h
deleted file mode 100644
index f23be1708c14..000000000000
--- a/drivers/video/via/via_utility.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#ifndef __VIAUTILITY_H__
-#define __VIAUTILITY_H__
-
-/* These functions are used to get information about device's state */
-void viafb_get_device_support_state(u32 *support_state);
-void viafb_get_device_connect_state(u32 *connect_state);
-bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
-
-/* These function are used to access gamma table */
-void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
-void viafb_get_gamma_table(unsigned int *gamma_table);
-void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
-
-#endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
deleted file mode 100644
index 325c43c6ff97..000000000000
--- a/drivers/video/via/viafbdev.c
+++ /dev/null
@@ -1,2176 +0,0 @@
-/*
- * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/via-core.h>
-#include <linux/via_i2c.h>
-#include <asm/olpc.h>
-
-#define _MASTER_FILE
-#include "global.h"
-
-static char *viafb_name = "Via";
-static u32 pseudo_pal[17];
-
-/* video mode */
-static char *viafb_mode;
-static char *viafb_mode1;
-static int viafb_bpp = 32;
-static int viafb_bpp1 = 32;
-
-static unsigned int viafb_second_offset;
-static int viafb_second_size;
-
-static int viafb_accel = 1;
-
-/* Added for specifying active devices.*/
-static char *viafb_active_dev;
-
-/*Added for specify lcd output port*/
-static char *viafb_lcd_port = "";
-static char *viafb_dvi_port = "";
-
-static void retrieve_device_setting(struct viafb_ioctl_setting
-	*setting_info);
-static int viafb_pan_display(struct fb_var_screeninfo *var,
-	struct fb_info *info);
-
-static struct fb_ops viafb_ops;
-
-/* supported output devices on each IGP
- * only CX700, VX800, VX855, VX900 were documented
- * VIA_CRT should be everywhere
- * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
- * source selection on CX700 and later
- * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
- */
-static const u32 supported_odev_map[] = {
-	[UNICHROME_CLE266]	= VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
-	[UNICHROME_K400]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
-				| VIA_LVDS2,
-	[UNICHROME_K800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
-				| VIA_LVDS2,
-	[UNICHROME_PM800]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
-				| VIA_LVDS2,
-	[UNICHROME_CN700]	= VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
-				| VIA_LVDS2,
-	[UNICHROME_CX700]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-	[UNICHROME_CN750]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-	[UNICHROME_K8M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-	[UNICHROME_P4M890]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-	[UNICHROME_P4M900]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-	[UNICHROME_VX800]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-	[UNICHROME_VX855]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-	[UNICHROME_VX900]	= VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
-};
-
-static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
-{
-	var->grayscale = 0;
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	var->transp.msb_right = 0;
-	var->nonstd = 0;
-	switch (depth) {
-	case 8:
-		var->bits_per_pixel = 8;
-		var->red.offset = 0;
-		var->green.offset = 0;
-		var->blue.offset = 0;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	case 15:
-		var->bits_per_pixel = 16;
-		var->red.offset = 10;
-		var->green.offset = 5;
-		var->blue.offset = 0;
-		var->red.length = 5;
-		var->green.length = 5;
-		var->blue.length = 5;
-		break;
-	case 16:
-		var->bits_per_pixel = 16;
-		var->red.offset = 11;
-		var->green.offset = 5;
-		var->blue.offset = 0;
-		var->red.length = 5;
-		var->green.length = 6;
-		var->blue.length = 5;
-		break;
-	case 24:
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	case 30:
-		var->bits_per_pixel = 32;
-		var->red.offset = 20;
-		var->green.offset = 10;
-		var->blue.offset = 0;
-		var->red.length = 10;
-		var->green.length = 10;
-		var->blue.length = 10;
-		break;
-	}
-}
-
-static void viafb_update_fix(struct fb_info *info)
-{
-	u32 bpp = info->var.bits_per_pixel;
-
-	info->fix.visual =
-		bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
-		VIA_PITCH_SIZE);
-}
-
-static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
-	struct viafb_par *viaparinfo)
-{
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, viafb_name);
-
-	fix->smem_start = viaparinfo->fbmem;
-	fix->smem_len = viaparinfo->fbmem_free;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	fix->visual = FB_VISUAL_TRUECOLOR;
-
-	fix->xpanstep = fix->ywrapstep = 0;
-	fix->ypanstep = 1;
-
-	/* Just tell the accel name */
-	viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
-}
-static int viafb_open(struct fb_info *info, int user)
-{
-	DEBUG_MSG(KERN_INFO "viafb_open!\n");
-	return 0;
-}
-
-static int viafb_release(struct fb_info *info, int user)
-{
-	DEBUG_MSG(KERN_INFO "viafb_release!\n");
-	return 0;
-}
-
-static inline int get_var_refresh(struct fb_var_screeninfo *var)
-{
-	u32 htotal, vtotal;
-
-	htotal = var->left_margin + var->xres + var->right_margin
-		+ var->hsync_len;
-	vtotal = var->upper_margin + var->yres + var->lower_margin
-		+ var->vsync_len;
-	return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
-}
-
-static int viafb_check_var(struct fb_var_screeninfo *var,
-	struct fb_info *info)
-{
-	int depth, refresh;
-	struct viafb_par *ppar = info->par;
-	u32 line;
-
-	DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
-	/* Sanity check */
-	/* HW neither support interlacte nor double-scaned mode */
-	if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
-		return -EINVAL;
-
-	/* the refresh rate is not important here, as we only want to know
-	 * whether the resolution exists
-	 */
-	if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
-		DEBUG_MSG(KERN_INFO
-			  "viafb: Mode %dx%dx%d not supported!!\n",
-			  var->xres, var->yres, var->bits_per_pixel);
-		return -EINVAL;
-	}
-
-	depth = fb_get_color_depth(var, &info->fix);
-	if (!depth)
-		depth = var->bits_per_pixel;
-
-	if (depth < 0 || depth > 32)
-		return -EINVAL;
-	else if (!depth)
-		depth = 24;
-	else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
-		depth = 15;
-	else if (depth == 30)
-		depth = 30;
-	else if (depth <= 8)
-		depth = 8;
-	else if (depth <= 16)
-		depth = 16;
-	else
-		depth = 24;
-
-	viafb_fill_var_color_info(var, depth);
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
-		VIA_PITCH_SIZE);
-	if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
-		return -EINVAL;
-
-	/* Based on var passed in to calculate the refresh,
-	 * because our driver use some modes special.
-	 */
-	refresh = viafb_get_refresh(var->xres, var->yres,
-		get_var_refresh(var));
-
-	/* Adjust var according to our driver's own table */
-	viafb_fill_var_timing_info(var,
-		viafb_get_best_mode(var->xres, var->yres, refresh));
-	if (var->accel_flags & FB_ACCELF_TEXT &&
-		!ppar->shared->vdev->engine_mmio)
-		var->accel_flags = 0;
-
-	return 0;
-}
-
-static int viafb_set_par(struct fb_info *info)
-{
-	struct viafb_par *viapar = info->par;
-	int refresh;
-	DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
-
-	viafb_update_fix(info);
-	viapar->depth = fb_get_color_depth(&info->var, &info->fix);
-	viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
-		viafbinfo->var.bits_per_pixel, 0);
-
-	if (viafb_dual_fb) {
-		viafb_update_device_setting(viafbinfo1->var.xres,
-			viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
-			1);
-	} else if (viafb_SAMM_ON == 1) {
-		DEBUG_MSG(KERN_INFO
-		"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
-			  viafb_second_xres, viafb_second_yres, viafb_bpp1);
-
-		viafb_update_device_setting(viafb_second_xres,
-			viafb_second_yres, viafb_bpp1, 1);
-	}
-
-	refresh = get_var_refresh(&info->var);
-	if (viafb_dual_fb && viapar->iga_path == IGA2) {
-		viafb_bpp1 = info->var.bits_per_pixel;
-		viafb_refresh1 = refresh;
-	} else {
-		viafb_bpp = info->var.bits_per_pixel;
-		viafb_refresh = refresh;
-	}
-
-	if (info->var.accel_flags & FB_ACCELF_TEXT)
-		info->flags &= ~FBINFO_HWACCEL_DISABLED;
-	else
-		info->flags |= FBINFO_HWACCEL_DISABLED;
-	viafb_setmode();
-	viafb_pan_display(&info->var, info);
-
-	return 0;
-}
-
-/* Set one color register */
-static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
-unsigned blue, unsigned transp, struct fb_info *info)
-{
-	struct viafb_par *viapar = info->par;
-	u32 r, g, b;
-
-	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
-		if (regno > 255)
-			return -EINVAL;
-
-		if (!viafb_dual_fb || viapar->iga_path == IGA1)
-			viafb_set_primary_color_register(regno, red >> 8,
-				green >> 8, blue >> 8);
-
-		if (!viafb_dual_fb || viapar->iga_path == IGA2)
-			viafb_set_secondary_color_register(regno, red >> 8,
-				green >> 8, blue >> 8);
-	} else {
-		if (regno > 15)
-			return -EINVAL;
-
-		r = (red >> (16 - info->var.red.length))
-			<< info->var.red.offset;
-		b = (blue >> (16 - info->var.blue.length))
-			<< info->var.blue.offset;
-		g = (green >> (16 - info->var.green.length))
-			<< info->var.green.offset;
-		((u32 *) info->pseudo_palette)[regno] = r | g | b;
-	}
-
-	return 0;
-}
-
-static int viafb_pan_display(struct fb_var_screeninfo *var,
-	struct fb_info *info)
-{
-	struct viafb_par *viapar = info->par;
-	u32 vram_addr = viapar->vram_addr
-		+ var->yoffset * info->fix.line_length
-		+ var->xoffset * info->var.bits_per_pixel / 8;
-
-	DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
-	if (!viafb_dual_fb) {
-		via_set_primary_address(vram_addr);
-		via_set_secondary_address(vram_addr);
-	} else if (viapar->iga_path == IGA1)
-		via_set_primary_address(vram_addr);
-	else
-		via_set_secondary_address(vram_addr);
-
-	return 0;
-}
-
-static int viafb_blank(int blank_mode, struct fb_info *info)
-{
-	DEBUG_MSG(KERN_INFO "viafb_blank!\n");
-	/* clear DPMS setting */
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		/* Screen: On, HSync: On, VSync: On */
-		/* control CRT monitor power management */
-		via_set_state(VIA_CRT, VIA_STATE_ON);
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		/* Screen: Off, HSync: Off, VSync: On */
-		/* control CRT monitor power management */
-		via_set_state(VIA_CRT, VIA_STATE_STANDBY);
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		/* Screen: Off, HSync: On, VSync: Off */
-		/* control CRT monitor power management */
-		via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
-		break;
-	case FB_BLANK_POWERDOWN:
-		/* Screen: Off, HSync: Off, VSync: Off */
-		/* control CRT monitor power management */
-		via_set_state(VIA_CRT, VIA_STATE_OFF);
-		break;
-	}
-
-	return 0;
-}
-
-static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
-{
-	union {
-		struct viafb_ioctl_mode viamode;
-		struct viafb_ioctl_samm viasamm;
-		struct viafb_driver_version driver_version;
-		struct fb_var_screeninfo sec_var;
-		struct _panel_size_pos_info panel_pos_size_para;
-		struct viafb_ioctl_setting viafb_setting;
-		struct device_t active_dev;
-	} u;
-	u32 state_info = 0;
-	u32 *viafb_gamma_table;
-	char driver_name[] = "viafb";
-
-	u32 __user *argp = (u32 __user *) arg;
-	u32 gpu32;
-
-	DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
-	printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
-	memset(&u, 0, sizeof(u));
-
-	switch (cmd) {
-	case VIAFB_GET_CHIP_INFO:
-		if (copy_to_user(argp, viaparinfo->chip_info,
-				sizeof(struct chip_information)))
-			return -EFAULT;
-		break;
-	case VIAFB_GET_INFO_SIZE:
-		return put_user((u32)sizeof(struct viafb_ioctl_info), argp);
-	case VIAFB_GET_INFO:
-		return viafb_ioctl_get_viafb_info(arg);
-	case VIAFB_HOTPLUG:
-		return put_user(viafb_ioctl_hotplug(info->var.xres,
-					      info->var.yres,
-					      info->var.bits_per_pixel), argp);
-	case VIAFB_SET_HOTPLUG_FLAG:
-		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
-			return -EFAULT;
-		viafb_hotplug = (gpu32) ? 1 : 0;
-		break;
-	case VIAFB_GET_RESOLUTION:
-		u.viamode.xres = (u32) viafb_hotplug_Xres;
-		u.viamode.yres = (u32) viafb_hotplug_Yres;
-		u.viamode.refresh = (u32) viafb_hotplug_refresh;
-		u.viamode.bpp = (u32) viafb_hotplug_bpp;
-		if (viafb_SAMM_ON == 1) {
-			u.viamode.xres_sec = viafb_second_xres;
-			u.viamode.yres_sec = viafb_second_yres;
-			u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual;
-			u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual;
-			u.viamode.refresh_sec = viafb_refresh1;
-			u.viamode.bpp_sec = viafb_bpp1;
-		} else {
-			u.viamode.xres_sec = 0;
-			u.viamode.yres_sec = 0;
-			u.viamode.virtual_xres_sec = 0;
-			u.viamode.virtual_yres_sec = 0;
-			u.viamode.refresh_sec = 0;
-			u.viamode.bpp_sec = 0;
-		}
-		if (copy_to_user(argp, &u.viamode, sizeof(u.viamode)))
-			return -EFAULT;
-		break;
-	case VIAFB_GET_SAMM_INFO:
-		u.viasamm.samm_status = viafb_SAMM_ON;
-
-		if (viafb_SAMM_ON == 1) {
-			if (viafb_dual_fb) {
-				u.viasamm.size_prim = viaparinfo->fbmem_free;
-				u.viasamm.size_sec = viaparinfo1->fbmem_free;
-			} else {
-				if (viafb_second_size) {
-					u.viasamm.size_prim =
-					    viaparinfo->fbmem_free -
-					    viafb_second_size * 1024 * 1024;
-					u.viasamm.size_sec =
-					    viafb_second_size * 1024 * 1024;
-				} else {
-					u.viasamm.size_prim =
-					    viaparinfo->fbmem_free >> 1;
-					u.viasamm.size_sec =
-					    (viaparinfo->fbmem_free >> 1);
-				}
-			}
-			u.viasamm.mem_base = viaparinfo->fbmem;
-			u.viasamm.offset_sec = viafb_second_offset;
-		} else {
-			u.viasamm.size_prim =
-			    viaparinfo->memsize - viaparinfo->fbmem_used;
-			u.viasamm.size_sec = 0;
-			u.viasamm.mem_base = viaparinfo->fbmem;
-			u.viasamm.offset_sec = 0;
-		}
-
-		if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm)))
-			return -EFAULT;
-
-		break;
-	case VIAFB_TURN_ON_OUTPUT_DEVICE:
-		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
-			return -EFAULT;
-		if (gpu32 & CRT_Device)
-			via_set_state(VIA_CRT, VIA_STATE_ON);
-		if (gpu32 & DVI_Device)
-			viafb_dvi_enable();
-		if (gpu32 & LCD_Device)
-			viafb_lcd_enable();
-		break;
-	case VIAFB_TURN_OFF_OUTPUT_DEVICE:
-		if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
-			return -EFAULT;
-		if (gpu32 & CRT_Device)
-			via_set_state(VIA_CRT, VIA_STATE_OFF);
-		if (gpu32 & DVI_Device)
-			viafb_dvi_disable();
-		if (gpu32 & LCD_Device)
-			viafb_lcd_disable();
-		break;
-	case VIAFB_GET_DEVICE:
-		u.active_dev.crt = viafb_CRT_ON;
-		u.active_dev.dvi = viafb_DVI_ON;
-		u.active_dev.lcd = viafb_LCD_ON;
-		u.active_dev.samm = viafb_SAMM_ON;
-		u.active_dev.primary_dev = viafb_primary_dev;
-
-		u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
-		u.active_dev.lcd_panel_id = viafb_lcd_panel_id;
-		u.active_dev.lcd_mode = viafb_lcd_mode;
-
-		u.active_dev.xres = viafb_hotplug_Xres;
-		u.active_dev.yres = viafb_hotplug_Yres;
-
-		u.active_dev.xres1 = viafb_second_xres;
-		u.active_dev.yres1 = viafb_second_yres;
-
-		u.active_dev.bpp = viafb_bpp;
-		u.active_dev.bpp1 = viafb_bpp1;
-		u.active_dev.refresh = viafb_refresh;
-		u.active_dev.refresh1 = viafb_refresh1;
-
-		u.active_dev.epia_dvi = viafb_platform_epia_dvi;
-		u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
-		u.active_dev.bus_width = viafb_bus_width;
-
-		if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev)))
-			return -EFAULT;
-		break;
-
-	case VIAFB_GET_DRIVER_VERSION:
-		u.driver_version.iMajorNum = VERSION_MAJOR;
-		u.driver_version.iKernelNum = VERSION_KERNEL;
-		u.driver_version.iOSNum = VERSION_OS;
-		u.driver_version.iMinorNum = VERSION_MINOR;
-
-		if (copy_to_user(argp, &u.driver_version,
-			sizeof(u.driver_version)))
-			return -EFAULT;
-
-		break;
-
-	case VIAFB_GET_DEVICE_INFO:
-
-		retrieve_device_setting(&u.viafb_setting);
-
-		if (copy_to_user(argp, &u.viafb_setting,
-				 sizeof(u.viafb_setting)))
-			return -EFAULT;
-
-		break;
-
-	case VIAFB_GET_DEVICE_SUPPORT:
-		viafb_get_device_support_state(&state_info);
-		if (put_user(state_info, argp))
-			return -EFAULT;
-		break;
-
-	case VIAFB_GET_DEVICE_CONNECT:
-		viafb_get_device_connect_state(&state_info);
-		if (put_user(state_info, argp))
-			return -EFAULT;
-		break;
-
-	case VIAFB_GET_PANEL_SUPPORT_EXPAND:
-		state_info =
-		    viafb_lcd_get_support_expand_state(info->var.xres,
-						 info->var.yres);
-		if (put_user(state_info, argp))
-			return -EFAULT;
-		break;
-
-	case VIAFB_GET_DRIVER_NAME:
-		if (copy_to_user(argp, driver_name, sizeof(driver_name)))
-			return -EFAULT;
-		break;
-
-	case VIAFB_SET_GAMMA_LUT:
-		viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32));
-		if (IS_ERR(viafb_gamma_table))
-			return PTR_ERR(viafb_gamma_table);
-		viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
-		kfree(viafb_gamma_table);
-		break;
-
-	case VIAFB_GET_GAMMA_LUT:
-		viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
-		if (!viafb_gamma_table)
-			return -ENOMEM;
-		viafb_get_gamma_table(viafb_gamma_table);
-		if (copy_to_user(argp, viafb_gamma_table,
-			256 * sizeof(u32))) {
-			kfree(viafb_gamma_table);
-			return -EFAULT;
-		}
-		kfree(viafb_gamma_table);
-		break;
-
-	case VIAFB_GET_GAMMA_SUPPORT_STATE:
-		viafb_get_gamma_support_state(viafb_bpp, &state_info);
-		if (put_user(state_info, argp))
-			return -EFAULT;
-		break;
-	case VIAFB_SYNC_SURFACE:
-		DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
-		break;
-	case VIAFB_GET_DRIVER_CAPS:
-		break;
-
-	case VIAFB_GET_PANEL_MAX_SIZE:
-		if (copy_from_user(&u.panel_pos_size_para, argp,
-				   sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
-		if (copy_to_user(argp, &u.panel_pos_size_para,
-		     sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		break;
-	case VIAFB_GET_PANEL_MAX_POSITION:
-		if (copy_from_user(&u.panel_pos_size_para, argp,
-				   sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
-		if (copy_to_user(argp, &u.panel_pos_size_para,
-				 sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		break;
-
-	case VIAFB_GET_PANEL_POSITION:
-		if (copy_from_user(&u.panel_pos_size_para, argp,
-				   sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
-		if (copy_to_user(argp, &u.panel_pos_size_para,
-				 sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		break;
-	case VIAFB_GET_PANEL_SIZE:
-		if (copy_from_user(&u.panel_pos_size_para, argp,
-				   sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
-		if (copy_to_user(argp, &u.panel_pos_size_para,
-				 sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		break;
-
-	case VIAFB_SET_PANEL_POSITION:
-		if (copy_from_user(&u.panel_pos_size_para, argp,
-				   sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		break;
-	case VIAFB_SET_PANEL_SIZE:
-		if (copy_from_user(&u.panel_pos_size_para, argp,
-				   sizeof(u.panel_pos_size_para)))
-			return -EFAULT;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void viafb_fillrect(struct fb_info *info,
-	const struct fb_fillrect *rect)
-{
-	struct viafb_par *viapar = info->par;
-	struct viafb_shared *shared = viapar->shared;
-	u32 fg_color;
-	u8 rop;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	if (!rect->width || !rect->height)
-		return;
-
-	if (info->fix.visual == FB_VISUAL_TRUECOLOR)
-		fg_color = ((u32 *)info->pseudo_palette)[rect->color];
-	else
-		fg_color = rect->color;
-
-	if (rect->rop == ROP_XOR)
-		rop = 0x5A;
-	else
-		rop = 0xF0;
-
-	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
-	if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL,
-		rect->width, rect->height, info->var.bits_per_pixel,
-		viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
-		NULL, 0, 0, 0, 0, fg_color, 0, rop))
-		cfb_fillrect(info, rect);
-}
-
-static void viafb_copyarea(struct fb_info *info,
-	const struct fb_copyarea *area)
-{
-	struct viafb_par *viapar = info->par;
-	struct viafb_shared *shared = viapar->shared;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	if (!area->width || !area->height)
-		return;
-
-	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
-	if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR,
-		area->width, area->height, info->var.bits_per_pixel,
-		viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
-		NULL, viapar->vram_addr, info->fix.line_length,
-		area->sx, area->sy, 0, 0, 0))
-		cfb_copyarea(info, area);
-}
-
-static void viafb_imageblit(struct fb_info *info,
-	const struct fb_image *image)
-{
-	struct viafb_par *viapar = info->par;
-	struct viafb_shared *shared = viapar->shared;
-	u32 fg_color = 0, bg_color = 0;
-	u8 op;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt ||
-		(image->depth != 1 && image->depth != viapar->depth)) {
-		cfb_imageblit(info, image);
-		return;
-	}
-
-	if (image->depth == 1) {
-		op = VIA_BITBLT_MONO;
-		if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
-			fg_color =
-				((u32 *)info->pseudo_palette)[image->fg_color];
-			bg_color =
-				((u32 *)info->pseudo_palette)[image->bg_color];
-		} else {
-			fg_color = image->fg_color;
-			bg_color = image->bg_color;
-		}
-	} else
-		op = VIA_BITBLT_COLOR;
-
-	DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
-	if (shared->hw_bitblt(shared->vdev->engine_mmio, op,
-		image->width, image->height, info->var.bits_per_pixel,
-		viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
-		(u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
-		cfb_imageblit(info, image);
-}
-
-static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct viafb_par *viapar = info->par;
-	void __iomem *engine = viapar->shared->vdev->engine_mmio;
-	u32 temp, xx, yy, bg_color = 0, fg_color = 0,
-		chip_name = viapar->shared->chip_info.gfx_chip_name;
-	int i, j = 0, cur_size = 64;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
-		return -ENODEV;
-
-	/* LCD ouput does not support hw cursors (at least on VN896) */
-	if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) ||
-		viafb_LCD_ON)
-		return -ENODEV;
-
-	viafb_show_hw_cursor(info, HW_Cursor_OFF);
-
-	if (cursor->set & FB_CUR_SETHOT) {
-		temp = (cursor->hot.x << 16) + cursor->hot.y;
-		writel(temp, engine + VIA_REG_CURSOR_ORG);
-	}
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		yy = cursor->image.dy - info->var.yoffset;
-		xx = cursor->image.dx - info->var.xoffset;
-		temp = yy & 0xFFFF;
-		temp |= (xx << 16);
-		writel(temp, engine + VIA_REG_CURSOR_POS);
-	}
-
-	if (cursor->image.width <= 32 && cursor->image.height <= 32)
-		cur_size = 32;
-	else if (cursor->image.width <= 64 && cursor->image.height <= 64)
-		cur_size = 64;
-	else {
-		printk(KERN_WARNING "viafb_cursor: The cursor is too large "
-			"%dx%d", cursor->image.width, cursor->image.height);
-		return -ENXIO;
-	}
-
-	if (cursor->set & FB_CUR_SETSIZE) {
-		temp = readl(engine + VIA_REG_CURSOR_MODE);
-		if (cur_size == 32)
-			temp |= 0x2;
-		else
-			temp &= ~0x2;
-
-		writel(temp, engine + VIA_REG_CURSOR_MODE);
-	}
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		fg_color = cursor->image.fg_color;
-		bg_color = cursor->image.bg_color;
-		if (chip_name == UNICHROME_CX700 ||
-			chip_name == UNICHROME_VX800 ||
-			chip_name == UNICHROME_VX855 ||
-			chip_name == UNICHROME_VX900) {
-			fg_color =
-				((info->cmap.red[fg_color] & 0xFFC0) << 14) |
-				((info->cmap.green[fg_color] & 0xFFC0) << 4) |
-				((info->cmap.blue[fg_color] & 0xFFC0) >> 6);
-			bg_color =
-				((info->cmap.red[bg_color] & 0xFFC0) << 14) |
-				((info->cmap.green[bg_color] & 0xFFC0) << 4) |
-				((info->cmap.blue[bg_color] & 0xFFC0) >> 6);
-		} else {
-			fg_color =
-				((info->cmap.red[fg_color] & 0xFF00) << 8) |
-				(info->cmap.green[fg_color] & 0xFF00) |
-				((info->cmap.blue[fg_color] & 0xFF00) >> 8);
-			bg_color =
-				((info->cmap.red[bg_color] & 0xFF00) << 8) |
-				(info->cmap.green[bg_color] & 0xFF00) |
-				((info->cmap.blue[bg_color] & 0xFF00) >> 8);
-		}
-
-		writel(bg_color, engine + VIA_REG_CURSOR_BG);
-		writel(fg_color, engine + VIA_REG_CURSOR_FG);
-	}
-
-	if (cursor->set & FB_CUR_SETSHAPE) {
-		struct {
-			u8 data[CURSOR_SIZE];
-			u32 bak[CURSOR_SIZE / 4];
-		} *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
-		int size = ((cursor->image.width + 7) >> 3) *
-			cursor->image.height;
-
-		if (!cr_data)
-			return -ENOMEM;
-
-		if (cur_size == 32) {
-			for (i = 0; i < (CURSOR_SIZE / 4); i++) {
-				cr_data->bak[i] = 0x0;
-				cr_data->bak[i + 1] = 0xFFFFFFFF;
-				i += 1;
-			}
-		} else {
-			for (i = 0; i < (CURSOR_SIZE / 4); i++) {
-				cr_data->bak[i] = 0x0;
-				cr_data->bak[i + 1] = 0x0;
-				cr_data->bak[i + 2] = 0xFFFFFFFF;
-				cr_data->bak[i + 3] = 0xFFFFFFFF;
-				i += 3;
-			}
-		}
-
-		switch (cursor->rop) {
-		case ROP_XOR:
-			for (i = 0; i < size; i++)
-				cr_data->data[i] = cursor->mask[i];
-			break;
-		case ROP_COPY:
-
-			for (i = 0; i < size; i++)
-				cr_data->data[i] = cursor->mask[i];
-			break;
-		default:
-			break;
-		}
-
-		if (cur_size == 32) {
-			for (i = 0; i < size; i++) {
-				cr_data->bak[j] = (u32) cr_data->data[i];
-				cr_data->bak[j + 1] = ~cr_data->bak[j];
-				j += 2;
-			}
-		} else {
-			for (i = 0; i < size; i++) {
-				cr_data->bak[j] = (u32) cr_data->data[i];
-				cr_data->bak[j + 1] = 0x0;
-				cr_data->bak[j + 2] = ~cr_data->bak[j];
-				cr_data->bak[j + 3] = ~cr_data->bak[j + 1];
-				j += 4;
-			}
-		}
-
-		memcpy_toio(viafbinfo->screen_base + viapar->shared->
-			cursor_vram_addr, cr_data->bak, CURSOR_SIZE);
-		kfree(cr_data);
-	}
-
-	if (cursor->enable)
-		viafb_show_hw_cursor(info, HW_Cursor_ON);
-
-	return 0;
-}
-
-static int viafb_sync(struct fb_info *info)
-{
-	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
-		viafb_wait_engine_idle(info);
-	return 0;
-}
-
-static int get_primary_device(void)
-{
-	int primary_device = 0;
-	/* Rule: device on iga1 path are the primary device. */
-	if (viafb_SAMM_ON) {
-		if (viafb_CRT_ON) {
-			if (viaparinfo->shared->iga1_devices & VIA_CRT) {
-				DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1);
-				primary_device = CRT_Device;
-			}
-		}
-		if (viafb_DVI_ON) {
-			if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
-				DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
-					viaparinfo->
-					tmds_setting_info->iga_path);
-				primary_device = DVI_Device;
-			}
-		}
-		if (viafb_LCD_ON) {
-			if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
-				DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
-					viaparinfo->
-					lvds_setting_info->iga_path);
-				primary_device = LCD_Device;
-			}
-		}
-		if (viafb_LCD2_ON) {
-			if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
-				DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
-					viaparinfo->
-					lvds_setting_info2->iga_path);
-				primary_device = LCD2_Device;
-			}
-		}
-	}
-	return primary_device;
-}
-
-static void retrieve_device_setting(struct viafb_ioctl_setting
-	*setting_info)
-{
-
-	/* get device status */
-	if (viafb_CRT_ON == 1)
-		setting_info->device_status = CRT_Device;
-	if (viafb_DVI_ON == 1)
-		setting_info->device_status |= DVI_Device;
-	if (viafb_LCD_ON == 1)
-		setting_info->device_status |= LCD_Device;
-	if (viafb_LCD2_ON == 1)
-		setting_info->device_status |= LCD2_Device;
-
-	setting_info->samm_status = viafb_SAMM_ON;
-	setting_info->primary_device = get_primary_device();
-
-	setting_info->first_dev_bpp = viafb_bpp;
-	setting_info->second_dev_bpp = viafb_bpp1;
-
-	setting_info->first_dev_refresh = viafb_refresh;
-	setting_info->second_dev_refresh = viafb_refresh1;
-
-	setting_info->first_dev_hor_res = viafb_hotplug_Xres;
-	setting_info->first_dev_ver_res = viafb_hotplug_Yres;
-	setting_info->second_dev_hor_res = viafb_second_xres;
-	setting_info->second_dev_ver_res = viafb_second_yres;
-
-	/* Get lcd attributes */
-	setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
-	setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
-	setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
-}
-
-static int __init parse_active_dev(void)
-{
-	viafb_CRT_ON = STATE_OFF;
-	viafb_DVI_ON = STATE_OFF;
-	viafb_LCD_ON = STATE_OFF;
-	viafb_LCD2_ON = STATE_OFF;
-	/* 1. Modify the active status of devices. */
-	/* 2. Keep the order of devices, so we can set corresponding
-	   IGA path to devices in SAMM case. */
-	/*    Note: The previous of active_dev is primary device,
-	   and the following is secondary device. */
-	if (!viafb_active_dev) {
-		if (machine_is_olpc()) { /* LCD only */
-			viafb_LCD_ON = STATE_ON;
-			viafb_SAMM_ON = STATE_OFF;
-		} else {
-			viafb_CRT_ON = STATE_ON;
-			viafb_SAMM_ON = STATE_OFF;
-		}
-	} else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
-		/* CRT+DVI */
-		viafb_CRT_ON = STATE_ON;
-		viafb_DVI_ON = STATE_ON;
-		viafb_primary_dev = CRT_Device;
-	} else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
-		/* DVI+CRT */
-		viafb_CRT_ON = STATE_ON;
-		viafb_DVI_ON = STATE_ON;
-		viafb_primary_dev = DVI_Device;
-	} else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
-		/* CRT+LCD */
-		viafb_CRT_ON = STATE_ON;
-		viafb_LCD_ON = STATE_ON;
-		viafb_primary_dev = CRT_Device;
-	} else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
-		/* LCD+CRT */
-		viafb_CRT_ON = STATE_ON;
-		viafb_LCD_ON = STATE_ON;
-		viafb_primary_dev = LCD_Device;
-	} else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
-		/* DVI+LCD */
-		viafb_DVI_ON = STATE_ON;
-		viafb_LCD_ON = STATE_ON;
-		viafb_primary_dev = DVI_Device;
-	} else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
-		/* LCD+DVI */
-		viafb_DVI_ON = STATE_ON;
-		viafb_LCD_ON = STATE_ON;
-		viafb_primary_dev = LCD_Device;
-	} else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
-		viafb_LCD_ON = STATE_ON;
-		viafb_LCD2_ON = STATE_ON;
-		viafb_primary_dev = LCD_Device;
-	} else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
-		viafb_LCD_ON = STATE_ON;
-		viafb_LCD2_ON = STATE_ON;
-		viafb_primary_dev = LCD2_Device;
-	} else if (!strcmp(viafb_active_dev, "CRT")) {
-		/* CRT only */
-		viafb_CRT_ON = STATE_ON;
-		viafb_SAMM_ON = STATE_OFF;
-	} else if (!strcmp(viafb_active_dev, "DVI")) {
-		/* DVI only */
-		viafb_DVI_ON = STATE_ON;
-		viafb_SAMM_ON = STATE_OFF;
-	} else if (!strcmp(viafb_active_dev, "LCD")) {
-		/* LCD only */
-		viafb_LCD_ON = STATE_ON;
-		viafb_SAMM_ON = STATE_OFF;
-	} else
-		return -EINVAL;
-
-	return 0;
-}
-
-static int parse_port(char *opt_str, int *output_interface)
-{
-	if (!strncmp(opt_str, "DVP0", 4))
-		*output_interface = INTERFACE_DVP0;
-	else if (!strncmp(opt_str, "DVP1", 4))
-		*output_interface = INTERFACE_DVP1;
-	else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
-		*output_interface = INTERFACE_DFP;
-	else if (!strncmp(opt_str, "DFP_HIGH", 8))
-		*output_interface = INTERFACE_DFP_HIGH;
-	else if (!strncmp(opt_str, "DFP_LOW", 7))
-		*output_interface = INTERFACE_DFP_LOW;
-	else
-		*output_interface = INTERFACE_NONE;
-	return 0;
-}
-
-static void parse_lcd_port(void)
-{
-	parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
-		output_interface);
-	/*Initialize to avoid unexpected behavior */
-	viaparinfo->chip_info->lvds_chip_info2.output_interface =
-	INTERFACE_NONE;
-
-	DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
-		  viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
-		  output_interface);
-}
-
-static void parse_dvi_port(void)
-{
-	parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
-		output_interface);
-
-	DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
-		  viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
-		  output_interface);
-}
-
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-
-/*
- * The proc filesystem read/write function, a simple proc implement to
- * get/set the value of DPA  DVP0,   DVP0DataDriving,  DVP0ClockDriving, DVP1,
- * DVP1Driving, DFPHigh, DFPLow CR96,   SR2A[5], SR1B[1], SR2A[4], SR1E[2],
- * CR9B,    SR65,    CR97,    CR99
- */
-static int viafb_dvp0_proc_show(struct seq_file *m, void *v)
-{
-	u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
-	dvp0_data_dri =
-	    (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
-	    (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
-	dvp0_clk_dri =
-	    (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
-	    (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
-	dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
-	seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
-	return 0;
-}
-
-static int viafb_dvp0_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_dvp0_proc_show, NULL);
-}
-
-static ssize_t viafb_dvp0_proc_write(struct file *file,
-	const char __user *buffer, size_t count, loff_t *pos)
-{
-	char buf[20], *value, *pbuf;
-	u8 reg_val = 0;
-	unsigned long length, i;
-	if (count < 1)
-		return -EINVAL;
-	length = count > 20 ? 20 : count;
-	if (copy_from_user(&buf[0], buffer, length))
-		return -EFAULT;
-	buf[length - 1] = '\0';	/*Ensure end string */
-	pbuf = &buf[0];
-	for (i = 0; i < 3; i++) {
-		value = strsep(&pbuf, " ");
-		if (value != NULL) {
-			if (kstrtou8(value, 0, &reg_val) < 0)
-				return -EINVAL;
-			DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
-				  reg_val);
-			switch (i) {
-			case 0:
-				viafb_write_reg_mask(CR96, VIACR,
-					reg_val, 0x0f);
-				break;
-			case 1:
-				viafb_write_reg_mask(SR2A, VIASR,
-					reg_val << 4, BIT5);
-				viafb_write_reg_mask(SR1B, VIASR,
-					reg_val << 1, BIT1);
-				break;
-			case 2:
-				viafb_write_reg_mask(SR2A, VIASR,
-					reg_val << 3, BIT4);
-				viafb_write_reg_mask(SR1E, VIASR,
-					reg_val << 2, BIT2);
-				break;
-			default:
-				break;
-			}
-		} else {
-			break;
-		}
-	}
-	return count;
-}
-
-static const struct file_operations viafb_dvp0_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_dvp0_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= viafb_dvp0_proc_write,
-};
-
-static int viafb_dvp1_proc_show(struct seq_file *m, void *v)
-{
-	u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
-	dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
-	dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
-	dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
-	seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
-	return 0;
-}
-
-static int viafb_dvp1_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_dvp1_proc_show, NULL);
-}
-
-static ssize_t viafb_dvp1_proc_write(struct file *file,
-	const char __user *buffer, size_t count, loff_t *pos)
-{
-	char buf[20], *value, *pbuf;
-	u8 reg_val = 0;
-	unsigned long length, i;
-	if (count < 1)
-		return -EINVAL;
-	length = count > 20 ? 20 : count;
-	if (copy_from_user(&buf[0], buffer, length))
-		return -EFAULT;
-	buf[length - 1] = '\0';	/*Ensure end string */
-	pbuf = &buf[0];
-	for (i = 0; i < 3; i++) {
-		value = strsep(&pbuf, " ");
-		if (value != NULL) {
-			if (kstrtou8(value, 0, &reg_val) < 0)
-				return -EINVAL;
-			switch (i) {
-			case 0:
-				viafb_write_reg_mask(CR9B, VIACR,
-					reg_val, 0x0f);
-				break;
-			case 1:
-				viafb_write_reg_mask(SR65, VIASR,
-					reg_val << 2, 0x0c);
-				break;
-			case 2:
-				viafb_write_reg_mask(SR65, VIASR,
-					reg_val, 0x03);
-				break;
-			default:
-				break;
-			}
-		} else {
-			break;
-		}
-	}
-	return count;
-}
-
-static const struct file_operations viafb_dvp1_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_dvp1_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= viafb_dvp1_proc_write,
-};
-
-static int viafb_dfph_proc_show(struct seq_file *m, void *v)
-{
-	u8 dfp_high = 0;
-	dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
-	seq_printf(m, "%x\n", dfp_high);
-	return 0;
-}
-
-static int viafb_dfph_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_dfph_proc_show, NULL);
-}
-
-static ssize_t viafb_dfph_proc_write(struct file *file,
-	const char __user *buffer, size_t count, loff_t *pos)
-{
-	int err;
-	u8 reg_val;
-	err = kstrtou8_from_user(buffer, count, 0, &reg_val);
-	if (err)
-		return err;
-
-	viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
-	return count;
-}
-
-static const struct file_operations viafb_dfph_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_dfph_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= viafb_dfph_proc_write,
-};
-
-static int viafb_dfpl_proc_show(struct seq_file *m, void *v)
-{
-	u8 dfp_low = 0;
-	dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
-	seq_printf(m, "%x\n", dfp_low);
-	return 0;
-}
-
-static int viafb_dfpl_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_dfpl_proc_show, NULL);
-}
-
-static ssize_t viafb_dfpl_proc_write(struct file *file,
-	const char __user *buffer, size_t count, loff_t *pos)
-{
-	int err;
-	u8 reg_val;
-	err = kstrtou8_from_user(buffer, count, 0, &reg_val);
-	if (err)
-		return err;
-
-	viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
-	return count;
-}
-
-static const struct file_operations viafb_dfpl_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_dfpl_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= viafb_dfpl_proc_write,
-};
-
-static int viafb_vt1636_proc_show(struct seq_file *m, void *v)
-{
-	u8 vt1636_08 = 0, vt1636_09 = 0;
-	switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
-	case VT1636_LVDS:
-		vt1636_08 =
-		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
-		    &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
-		vt1636_09 =
-		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
-		    &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
-		seq_printf(m, "%x %x\n", vt1636_08, vt1636_09);
-		break;
-	default:
-		break;
-	}
-	switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
-	case VT1636_LVDS:
-		vt1636_08 =
-		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
-			&viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
-		vt1636_09 =
-		    viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
-			&viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
-		seq_printf(m, " %x %x\n", vt1636_08, vt1636_09);
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int viafb_vt1636_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_vt1636_proc_show, NULL);
-}
-
-static ssize_t viafb_vt1636_proc_write(struct file *file,
-	const char __user *buffer, size_t count, loff_t *pos)
-{
-	char buf[30], *value, *pbuf;
-	struct IODATA reg_val;
-	unsigned long length, i;
-	if (count < 1)
-		return -EINVAL;
-	length = count > 30 ? 30 : count;
-	if (copy_from_user(&buf[0], buffer, length))
-		return -EFAULT;
-	buf[length - 1] = '\0';	/*Ensure end string */
-	pbuf = &buf[0];
-	switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
-	case VT1636_LVDS:
-		for (i = 0; i < 2; i++) {
-			value = strsep(&pbuf, " ");
-			if (value != NULL) {
-				if (kstrtou8(value, 0, &reg_val.Data) < 0)
-					return -EINVAL;
-				switch (i) {
-				case 0:
-					reg_val.Index = 0x08;
-					reg_val.Mask = 0x0f;
-					viafb_gpio_i2c_write_mask_lvds
-					    (viaparinfo->lvds_setting_info,
-					    &viaparinfo->
-					    chip_info->lvds_chip_info,
-					     reg_val);
-					break;
-				case 1:
-					reg_val.Index = 0x09;
-					reg_val.Mask = 0x1f;
-					viafb_gpio_i2c_write_mask_lvds
-					    (viaparinfo->lvds_setting_info,
-					    &viaparinfo->
-					    chip_info->lvds_chip_info,
-					     reg_val);
-					break;
-				default:
-					break;
-				}
-			} else {
-				break;
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
-	case VT1636_LVDS:
-		for (i = 0; i < 2; i++) {
-			value = strsep(&pbuf, " ");
-			if (value != NULL) {
-				if (kstrtou8(value, 0, &reg_val.Data) < 0)
-					return -EINVAL;
-				switch (i) {
-				case 0:
-					reg_val.Index = 0x08;
-					reg_val.Mask = 0x0f;
-					viafb_gpio_i2c_write_mask_lvds
-					    (viaparinfo->lvds_setting_info2,
-					    &viaparinfo->
-					    chip_info->lvds_chip_info2,
-					     reg_val);
-					break;
-				case 1:
-					reg_val.Index = 0x09;
-					reg_val.Mask = 0x1f;
-					viafb_gpio_i2c_write_mask_lvds
-					    (viaparinfo->lvds_setting_info2,
-					    &viaparinfo->
-					    chip_info->lvds_chip_info2,
-					     reg_val);
-					break;
-				default:
-					break;
-				}
-			} else {
-				break;
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	return count;
-}
-
-static const struct file_operations viafb_vt1636_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_vt1636_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= viafb_vt1636_proc_write,
-};
-
-#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
-
-static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
-{
-	via_odev_to_seq(m, supported_odev_map[
-		viaparinfo->shared->chip_info.gfx_chip_name]);
-	return 0;
-}
-
-static int viafb_sup_odev_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_sup_odev_proc_show, NULL);
-}
-
-static const struct file_operations viafb_sup_odev_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_sup_odev_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
-{
-	char buf[64], *ptr = buf;
-	u32 devices;
-	bool add, sub;
-
-	if (count < 1 || count > 63)
-		return -EINVAL;
-	if (copy_from_user(&buf[0], buffer, count))
-		return -EFAULT;
-	buf[count] = '\0';
-	add = buf[0] == '+';
-	sub = buf[0] == '-';
-	if (add || sub)
-		ptr++;
-	devices = via_parse_odev(ptr, &ptr);
-	if (*ptr == '\n')
-		ptr++;
-	if (*ptr != 0)
-		return -EINVAL;
-	if (add)
-		*odev |= devices;
-	else if (sub)
-		*odev &= ~devices;
-	else
-		*odev = devices;
-	return count;
-}
-
-static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
-{
-	via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
-	return 0;
-}
-
-static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_iga1_odev_proc_show, NULL);
-}
-
-static ssize_t viafb_iga1_odev_proc_write(struct file *file,
-	const char __user *buffer, size_t count, loff_t *pos)
-{
-	u32 dev_on, dev_off, dev_old, dev_new;
-	ssize_t res;
-
-	dev_old = dev_new = viaparinfo->shared->iga1_devices;
-	res = odev_update(buffer, count, &dev_new);
-	if (res != count)
-		return res;
-	dev_off = dev_old & ~dev_new;
-	dev_on = dev_new & ~dev_old;
-	viaparinfo->shared->iga1_devices = dev_new;
-	viaparinfo->shared->iga2_devices &= ~dev_new;
-	via_set_state(dev_off, VIA_STATE_OFF);
-	via_set_source(dev_new, IGA1);
-	via_set_state(dev_on, VIA_STATE_ON);
-	return res;
-}
-
-static const struct file_operations viafb_iga1_odev_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_iga1_odev_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= viafb_iga1_odev_proc_write,
-};
-
-static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
-{
-	via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
-	return 0;
-}
-
-static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, viafb_iga2_odev_proc_show, NULL);
-}
-
-static ssize_t viafb_iga2_odev_proc_write(struct file *file,
-	const char __user *buffer, size_t count, loff_t *pos)
-{
-	u32 dev_on, dev_off, dev_old, dev_new;
-	ssize_t res;
-
-	dev_old = dev_new = viaparinfo->shared->iga2_devices;
-	res = odev_update(buffer, count, &dev_new);
-	if (res != count)
-		return res;
-	dev_off = dev_old & ~dev_new;
-	dev_on = dev_new & ~dev_old;
-	viaparinfo->shared->iga2_devices = dev_new;
-	viaparinfo->shared->iga1_devices &= ~dev_new;
-	via_set_state(dev_off, VIA_STATE_OFF);
-	via_set_source(dev_new, IGA2);
-	via_set_state(dev_on, VIA_STATE_ON);
-	return res;
-}
-
-static const struct file_operations viafb_iga2_odev_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= viafb_iga2_odev_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= viafb_iga2_odev_proc_write,
-};
-
-#define IS_VT1636(lvds_chip)	((lvds_chip).lvds_chip_name == VT1636_LVDS)
-static void viafb_init_proc(struct viafb_shared *shared)
-{
-	struct proc_dir_entry *iga1_entry, *iga2_entry,
-		*viafb_entry = proc_mkdir("viafb", NULL);
-
-	shared->proc_entry = viafb_entry;
-	if (viafb_entry) {
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-		proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
-		proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
-		proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
-		proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
-		if (IS_VT1636(shared->chip_info.lvds_chip_info)
-			|| IS_VT1636(shared->chip_info.lvds_chip_info2))
-			proc_create("vt1636", 0, viafb_entry,
-				&viafb_vt1636_proc_fops);
-#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
-
-		proc_create("supported_output_devices", 0, viafb_entry,
-			&viafb_sup_odev_proc_fops);
-		iga1_entry = proc_mkdir("iga1", viafb_entry);
-		shared->iga1_proc_entry = iga1_entry;
-		proc_create("output_devices", 0, iga1_entry,
-			&viafb_iga1_odev_proc_fops);
-		iga2_entry = proc_mkdir("iga2", viafb_entry);
-		shared->iga2_proc_entry = iga2_entry;
-		proc_create("output_devices", 0, iga2_entry,
-			&viafb_iga2_odev_proc_fops);
-	}
-}
-static void viafb_remove_proc(struct viafb_shared *shared)
-{
-	struct proc_dir_entry *viafb_entry = shared->proc_entry,
-		*iga1_entry = shared->iga1_proc_entry,
-		*iga2_entry = shared->iga2_proc_entry;
-
-	if (!viafb_entry)
-		return;
-
-	remove_proc_entry("output_devices", iga2_entry);
-	remove_proc_entry("iga2", viafb_entry);
-	remove_proc_entry("output_devices", iga1_entry);
-	remove_proc_entry("iga1", viafb_entry);
-	remove_proc_entry("supported_output_devices", viafb_entry);
-
-#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-	remove_proc_entry("dvp0", viafb_entry);/* parent dir */
-	remove_proc_entry("dvp1", viafb_entry);
-	remove_proc_entry("dfph", viafb_entry);
-	remove_proc_entry("dfpl", viafb_entry);
-	if (IS_VT1636(shared->chip_info.lvds_chip_info)
-		|| IS_VT1636(shared->chip_info.lvds_chip_info2))
-		remove_proc_entry("vt1636", viafb_entry);
-#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
-
-	remove_proc_entry("viafb", NULL);
-}
-#undef IS_VT1636
-
-static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres)
-{
-	const struct fb_videomode *mode = NULL;
-	char *ptr;
-
-	if (!str) {
-		if (devices == VIA_CRT)
-			mode = via_aux_get_preferred_mode(
-				viaparinfo->shared->i2c_26);
-		else if (devices == VIA_DVP1)
-			mode = via_aux_get_preferred_mode(
-				viaparinfo->shared->i2c_31);
-
-		if (mode) {
-			*xres = mode->xres;
-			*yres = mode->yres;
-		} else if (machine_is_olpc()) {
-			*xres = 1200;
-			*yres = 900;
-		} else {
-			*xres = 640;
-			*yres = 480;
-		}
-		return 0;
-	}
-
-	*xres = simple_strtoul(str, &ptr, 10);
-	if (ptr[0] != 'x')
-		return -EINVAL;
-
-	*yres = simple_strtoul(&ptr[1], &ptr, 10);
-	if (ptr[0])
-		return -EINVAL;
-
-	return 0;
-}
-
-
-#ifdef CONFIG_PM
-static int viafb_suspend(void *unused)
-{
-	console_lock();
-	fb_set_suspend(viafbinfo, 1);
-	viafb_sync(viafbinfo);
-	console_unlock();
-
-	return 0;
-}
-
-static int viafb_resume(void *unused)
-{
-	console_lock();
-	if (viaparinfo->shared->vdev->engine_mmio)
-		viafb_reset_engine(viaparinfo);
-	viafb_set_par(viafbinfo);
-	if (viafb_dual_fb)
-		viafb_set_par(viafbinfo1);
-	fb_set_suspend(viafbinfo, 0);
-
-	console_unlock();
-	return 0;
-}
-
-static struct viafb_pm_hooks viafb_fb_pm_hooks = {
-	.suspend = viafb_suspend,
-	.resume = viafb_resume
-};
-
-#endif
-
-static void i2c_bus_probe(struct viafb_shared *shared)
-{
-	/* should be always CRT */
-	printk(KERN_INFO "viafb: Probing I2C bus 0x26\n");
-	shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26));
-
-	/* seems to be usually DVP1 */
-	printk(KERN_INFO "viafb: Probing I2C bus 0x31\n");
-	shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31));
-
-	/* FIXME: what is this? */
-	if (!machine_is_olpc()) {
-		printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n");
-		shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C));
-	}
-
-	printk(KERN_INFO "viafb: Finished I2C bus probing");
-}
-
-static void i2c_bus_free(struct viafb_shared *shared)
-{
-	via_aux_free(shared->i2c_26);
-	via_aux_free(shared->i2c_31);
-	via_aux_free(shared->i2c_2C);
-}
-
-int via_fb_pci_probe(struct viafb_dev *vdev)
-{
-	u32 default_xres, default_yres;
-	struct fb_var_screeninfo default_var;
-	int rc;
-	u32 viafb_par_length;
-
-	DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
-	memset(&default_var, 0, sizeof(default_var));
-	viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
-
-	/* Allocate fb_info and ***_par here, also including some other needed
-	 * variables
-	*/
-	viafbinfo = framebuffer_alloc(viafb_par_length +
-		ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8),
-		&vdev->pdev->dev);
-	if (!viafbinfo) {
-		printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
-		return -ENOMEM;
-	}
-
-	viaparinfo = (struct viafb_par *)viafbinfo->par;
-	viaparinfo->shared = viafbinfo->par + viafb_par_length;
-	viaparinfo->shared->vdev = vdev;
-	viaparinfo->vram_addr = 0;
-	viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
-	viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
-	viaparinfo->lvds_setting_info2 =
-		&viaparinfo->shared->lvds_setting_info2;
-	viaparinfo->chip_info = &viaparinfo->shared->chip_info;
-
-	i2c_bus_probe(viaparinfo->shared);
-	if (viafb_dual_fb)
-		viafb_SAMM_ON = 1;
-	parse_lcd_port();
-	parse_dvi_port();
-
-	viafb_init_chip_info(vdev->chip_type);
-	/*
-	 * The framebuffer will have been successfully mapped by
-	 * the core (or we'd not be here), but we still need to
-	 * set up our own accounting.
-	 */
-	viaparinfo->fbmem = vdev->fbmem_start;
-	viaparinfo->memsize = vdev->fbmem_len;
-	viaparinfo->fbmem_free = viaparinfo->memsize;
-	viaparinfo->fbmem_used = 0;
-	viafbinfo->screen_base = vdev->fbmem;
-
-	viafbinfo->fix.mmio_start = vdev->engine_start;
-	viafbinfo->fix.mmio_len = vdev->engine_len;
-	viafbinfo->node = 0;
-	viafbinfo->fbops = &viafb_ops;
-	viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-
-	viafbinfo->pseudo_palette = pseudo_pal;
-	if (viafb_accel && !viafb_setup_engine(viafbinfo)) {
-		viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
-			FBINFO_HWACCEL_FILLRECT |  FBINFO_HWACCEL_IMAGEBLIT;
-		default_var.accel_flags = FB_ACCELF_TEXT;
-	} else {
-		viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
-		default_var.accel_flags = 0;
-	}
-
-	if (viafb_second_size && (viafb_second_size < 8)) {
-		viafb_second_offset = viaparinfo->fbmem_free -
-			viafb_second_size * 1024 * 1024;
-	} else {
-		viafb_second_size = 8;
-		viafb_second_offset = viaparinfo->fbmem_free -
-			viafb_second_size * 1024 * 1024;
-	}
-
-	parse_mode(viafb_mode, viaparinfo->shared->iga1_devices,
-		&default_xres, &default_yres);
-	if (viafb_SAMM_ON == 1)
-		parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices,
-			&viafb_second_xres, &viafb_second_yres);
-
-	default_var.xres = default_xres;
-	default_var.yres = default_yres;
-	default_var.xres_virtual = default_xres;
-	default_var.yres_virtual = default_yres;
-	default_var.bits_per_pixel = viafb_bpp;
-	viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
-		default_var.xres, default_var.yres, viafb_refresh));
-	viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
-	viafbinfo->var = default_var;
-
-	if (viafb_dual_fb) {
-		viafbinfo1 = framebuffer_alloc(viafb_par_length,
-				&vdev->pdev->dev);
-		if (!viafbinfo1) {
-			printk(KERN_ERR
-			"allocate the second framebuffer struct error\n");
-			rc = -ENOMEM;
-			goto out_fb_release;
-		}
-		viaparinfo1 = viafbinfo1->par;
-		memcpy(viaparinfo1, viaparinfo, viafb_par_length);
-		viaparinfo1->vram_addr = viafb_second_offset;
-		viaparinfo1->memsize = viaparinfo->memsize -
-			viafb_second_offset;
-		viaparinfo->memsize = viafb_second_offset;
-		viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
-
-		viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
-		viaparinfo1->fbmem_free = viaparinfo1->memsize -
-			viaparinfo1->fbmem_used;
-		viaparinfo->fbmem_free = viaparinfo->memsize;
-		viaparinfo->fbmem_used = 0;
-
-		viaparinfo->iga_path = IGA1;
-		viaparinfo1->iga_path = IGA2;
-		memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
-		viafbinfo1->par = viaparinfo1;
-		viafbinfo1->screen_base = viafbinfo->screen_base +
-			viafb_second_offset;
-
-		default_var.xres = viafb_second_xres;
-		default_var.yres = viafb_second_yres;
-		default_var.xres_virtual = viafb_second_xres;
-		default_var.yres_virtual = viafb_second_yres;
-		default_var.bits_per_pixel = viafb_bpp1;
-		viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
-			default_var.xres, default_var.yres, viafb_refresh1));
-
-		viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
-		viafb_check_var(&default_var, viafbinfo1);
-		viafbinfo1->var = default_var;
-		viafb_update_fix(viafbinfo1);
-		viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var,
-			&viafbinfo1->fix);
-	}
-
-	viafb_check_var(&viafbinfo->var, viafbinfo);
-	viafb_update_fix(viafbinfo);
-	viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
-		&viafbinfo->fix);
-	default_var.activate = FB_ACTIVATE_NOW;
-	rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
-	if (rc)
-		goto out_fb1_release;
-
-	if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
-	    && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
-		rc = register_framebuffer(viafbinfo1);
-		if (rc)
-			goto out_dealloc_cmap;
-	}
-	rc = register_framebuffer(viafbinfo);
-	if (rc)
-		goto out_fb1_unreg_lcd_cle266;
-
-	if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
-			|| (viaparinfo->chip_info->gfx_chip_name !=
-			UNICHROME_CLE266))) {
-		rc = register_framebuffer(viafbinfo1);
-		if (rc)
-			goto out_fb_unreg;
-	}
-	DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
-		  viafbinfo->node, viafbinfo->fix.id, default_var.xres,
-		  default_var.yres, default_var.bits_per_pixel);
-
-	viafb_init_proc(viaparinfo->shared);
-	viafb_init_dac(IGA2);
-
-#ifdef CONFIG_PM
-	viafb_pm_register(&viafb_fb_pm_hooks);
-#endif
-	return 0;
-
-out_fb_unreg:
-	unregister_framebuffer(viafbinfo);
-out_fb1_unreg_lcd_cle266:
-	if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
-	    && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
-		unregister_framebuffer(viafbinfo1);
-out_dealloc_cmap:
-	fb_dealloc_cmap(&viafbinfo->cmap);
-out_fb1_release:
-	if (viafbinfo1)
-		framebuffer_release(viafbinfo1);
-out_fb_release:
-	i2c_bus_free(viaparinfo->shared);
-	framebuffer_release(viafbinfo);
-	return rc;
-}
-
-void via_fb_pci_remove(struct pci_dev *pdev)
-{
-	DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
-	fb_dealloc_cmap(&viafbinfo->cmap);
-	unregister_framebuffer(viafbinfo);
-	if (viafb_dual_fb)
-		unregister_framebuffer(viafbinfo1);
-	viafb_remove_proc(viaparinfo->shared);
-	i2c_bus_free(viaparinfo->shared);
-	framebuffer_release(viafbinfo);
-	if (viafb_dual_fb)
-		framebuffer_release(viafbinfo1);
-}
-
-#ifndef MODULE
-static int __init viafb_setup(void)
-{
-	char *this_opt;
-	char *options;
-
-	DEBUG_MSG(KERN_INFO "viafb_setup!\n");
-
-	if (fb_get_options("viafb", &options))
-		return -ENODEV;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-
-		if (!strncmp(this_opt, "viafb_mode1=", 12)) {
-			viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
-		} else if (!strncmp(this_opt, "viafb_mode=", 11)) {
-			viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
-		} else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
-			if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
-			if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
-			if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
-			if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
-			if (kstrtoint(this_opt + 21, 0,
-				      &viafb_lcd_dsp_method) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
-			if (kstrtoint(this_opt + 19, 0,
-				      &viafb_lcd_panel_id) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_accel=", 12)) {
-			if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
-			if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
-			viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
-		} else if (!strncmp(this_opt,
-			"viafb_display_hardware_layout=", 30)) {
-			if (kstrtoint(this_opt + 30, 0,
-				      &viafb_display_hardware_layout) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
-			if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt,
-			"viafb_platform_epia_dvi=", 24)) {
-			if (kstrtoint(this_opt + 24, 0,
-				      &viafb_platform_epia_dvi) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt,
-			"viafb_device_lcd_dualedge=", 26)) {
-			if (kstrtoint(this_opt + 26, 0,
-				      &viafb_device_lcd_dualedge) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
-			if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
-			if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
-				return -EINVAL;
-		} else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
-			viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
-		} else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
-			viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
-		}
-	}
-	return 0;
-}
-#endif
-
-/*
- * These are called out of via-core for now.
- */
-int __init viafb_init(void)
-{
-	u32 dummy_x, dummy_y;
-	int r = 0;
-
-	if (machine_is_olpc())
-		/* Apply XO-1.5-specific configuration. */
-		viafb_lcd_panel_id = 23;
-
-#ifndef MODULE
-	r = viafb_setup();
-	if (r < 0)
-		return r;
-#endif
-	if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y)
-		|| !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
-		|| parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y)
-		|| !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
-		|| viafb_bpp < 0 || viafb_bpp > 32
-		|| viafb_bpp1 < 0 || viafb_bpp1 > 32
-		|| parse_active_dev())
-		return -EINVAL;
-
-	printk(KERN_INFO
-       "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
-	       VERSION_MAJOR, VERSION_MINOR);
-	return r;
-}
-
-void __exit viafb_exit(void)
-{
-	DEBUG_MSG(KERN_INFO "viafb_exit!\n");
-}
-
-static struct fb_ops viafb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = viafb_open,
-	.fb_release = viafb_release,
-	.fb_check_var = viafb_check_var,
-	.fb_set_par = viafb_set_par,
-	.fb_setcolreg = viafb_setcolreg,
-	.fb_pan_display = viafb_pan_display,
-	.fb_blank = viafb_blank,
-	.fb_fillrect = viafb_fillrect,
-	.fb_copyarea = viafb_copyarea,
-	.fb_imageblit = viafb_imageblit,
-	.fb_cursor = viafb_cursor,
-	.fb_ioctl = viafb_ioctl,
-	.fb_sync = viafb_sync,
-};
-
-
-#ifdef MODULE
-module_param(viafb_mode, charp, S_IRUSR);
-MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
-
-module_param(viafb_mode1, charp, S_IRUSR);
-MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
-
-module_param(viafb_bpp, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
-
-module_param(viafb_bpp1, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
-
-module_param(viafb_refresh, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_refresh,
-	"Set CRT viafb_refresh rate (default = 60)");
-
-module_param(viafb_refresh1, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_refresh1,
-	"Set CRT refresh rate (default = 60)");
-
-module_param(viafb_lcd_panel_id, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_lcd_panel_id,
-	"Set Flat Panel type(Default=1024x768)");
-
-module_param(viafb_lcd_dsp_method, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_lcd_dsp_method,
-	"Set Flat Panel display scaling method.(Default=Expandsion)");
-
-module_param(viafb_SAMM_ON, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_SAMM_ON,
-	"Turn on/off flag of SAMM(Default=OFF)");
-
-module_param(viafb_accel, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_accel,
-	"Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)");
-
-module_param(viafb_active_dev, charp, S_IRUSR);
-MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
-
-module_param(viafb_display_hardware_layout, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_display_hardware_layout,
-	"Display Hardware Layout (LCD Only, DVI Only...,etc)");
-
-module_param(viafb_second_size, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_second_size,
-	"Set secondary device memory size");
-
-module_param(viafb_dual_fb, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_dual_fb,
-	"Turn on/off flag of dual framebuffer devices.(Default = OFF)");
-
-module_param(viafb_platform_epia_dvi, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_platform_epia_dvi,
-	"Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
-
-module_param(viafb_device_lcd_dualedge, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_device_lcd_dualedge,
-	"Turn on/off flag of dual edge panel.(Default = OFF)");
-
-module_param(viafb_bus_width, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_bus_width,
-	"Set bus width of panel.(Default = 12)");
-
-module_param(viafb_lcd_mode, int, S_IRUSR);
-MODULE_PARM_DESC(viafb_lcd_mode,
-	"Set Flat Panel mode(Default=OPENLDI)");
-
-module_param(viafb_lcd_port, charp, S_IRUSR);
-MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
-
-module_param(viafb_dvi_port, charp, S_IRUSR);
-MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
-
-MODULE_LICENSE("GPL");
-#endif
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
deleted file mode 100644
index f6b2ddf56e94..000000000000
--- a/drivers/video/via/viafbdev.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __VIAFBDEV_H__
-#define __VIAFBDEV_H__
-
-#include <linux/proc_fs.h>
-#include <linux/fb.h>
-#include <linux/spinlock.h>
-
-#include "via_aux.h"
-#include "ioctl.h"
-#include "share.h"
-#include "chip.h"
-#include "hw.h"
-
-#define VERSION_MAJOR       2
-#define VERSION_KERNEL      6	/* For kernel 2.6 */
-
-#define VERSION_OS          0	/* 0: for 32 bits OS, 1: for 64 bits OS */
-#define VERSION_MINOR       4
-
-#define VIAFB_NUM_I2C		5
-
-struct viafb_shared {
-	u32 iga1_devices;
-	u32 iga2_devices;
-
-	struct proc_dir_entry *proc_entry;	/*viafb proc entry */
-	struct proc_dir_entry *iga1_proc_entry;
-	struct proc_dir_entry *iga2_proc_entry;
-	struct viafb_dev *vdev;			/* Global dev info */
-
-	/* I2C busses that may have auxiliary devices */
-	struct via_aux_bus *i2c_26;
-	struct via_aux_bus *i2c_31;
-	struct via_aux_bus *i2c_2C;
-
-	/* All the information will be needed to set engine */
-	struct tmds_setting_information tmds_setting_info;
-	struct lvds_setting_information lvds_setting_info;
-	struct lvds_setting_information lvds_setting_info2;
-	struct chip_information chip_info;
-
-	/* hardware acceleration stuff */
-	u32 cursor_vram_addr;
-	u32 vq_vram_addr;	/* virtual queue address in video ram */
-	int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height,
-		u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
-		u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
-		u32 fg_color, u32 bg_color, u8 fill_rop);
-};
-
-struct viafb_par {
-	u8 depth;
-	u32 vram_addr;
-
-	unsigned int fbmem;	/*framebuffer physical memory address */
-	unsigned int memsize;	/*size of fbmem */
-	u32 fbmem_free;		/* Free FB memory */
-	u32 fbmem_used;		/* Use FB memory size */
-	u32 iga_path;
-
-	struct viafb_shared *shared;
-
-	/* All the information will be needed to set engine */
-	/* depreciated, use the ones in shared directly */
-	struct tmds_setting_information *tmds_setting_info;
-	struct lvds_setting_information *lvds_setting_info;
-	struct lvds_setting_information *lvds_setting_info2;
-	struct chip_information *chip_info;
-};
-
-extern int viafb_SAMM_ON;
-extern int viafb_dual_fb;
-extern int viafb_LCD2_ON;
-extern int viafb_LCD_ON;
-extern int viafb_DVI_ON;
-extern int viafb_hotplug;
-
-u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
-	*plvds_setting_info, struct lvds_chip_information
-	*plvds_chip_info, u8 index);
-void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
-			      *plvds_setting_info, struct lvds_chip_information
-			      *plvds_chip_info, struct IODATA io_data);
-int via_fb_pci_probe(struct viafb_dev *vdev);
-void via_fb_pci_remove(struct pci_dev *pdev);
-/* Temporary */
-int viafb_init(void);
-void viafb_exit(void);
-#endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
deleted file mode 100644
index 0666ab01cf4a..000000000000
--- a/drivers/video/via/viamode.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/via-core.h>
-#include "global.h"
-
-struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
-{VIASR, SR15, 0x02, 0x02},
-{VIASR, SR16, 0xBF, 0x08},
-{VIASR, SR17, 0xFF, 0x1F},
-{VIASR, SR18, 0xFF, 0x4E},
-{VIASR, SR1A, 0xFB, 0x08},
-{VIASR, SR1E, 0x0F, 0x01},
-{VIASR, SR2A, 0xFF, 0x00},
-{VIACR, CR32, 0xFF, 0x00},
-{VIACR, CR33, 0xFF, 0x00},
-{VIACR, CR35, 0xFF, 0x00},
-{VIACR, CR36, 0x08, 0x00},
-{VIACR, CR69, 0xFF, 0x00},
-{VIACR, CR6A, 0xFF, 0x40},
-{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                      */
-{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0                */
-{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1                */
-{VIACR, CR8B, 0xFF, 0x69},	/* LCD Power Sequence Control 0        */
-{VIACR, CR8C, 0xFF, 0x57},	/* LCD Power Sequence Control 1        */
-{VIACR, CR8D, 0xFF, 0x00},	/* LCD Power Sequence Control 2        */
-{VIACR, CR8E, 0xFF, 0x7B},	/* LCD Power Sequence Control 3        */
-{VIACR, CR8F, 0xFF, 0x03},	/* LCD Power Sequence Control 4        */
-{VIACR, CR90, 0xFF, 0x30},	/* LCD Power Sequence Control 5        */
-{VIACR, CR91, 0xFF, 0xA0},	/* 24/12 bit LVDS Data off             */
-{VIACR, CR96, 0xFF, 0x00},
-{VIACR, CR97, 0xFF, 0x00},
-{VIACR, CR99, 0xFF, 0x00},
-{VIACR, CR9B, 0xFF, 0x00}
-};
-
-/* Video Mode Table for VT3314 chipset*/
-/* Common Setting for Video Mode */
-struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
-{VIASR, SR15, 0x02, 0x02},
-{VIASR, SR16, 0xBF, 0x08},
-{VIASR, SR17, 0xFF, 0x1F},
-{VIASR, SR18, 0xFF, 0x4E},
-{VIASR, SR1A, 0xFB, 0x82},
-{VIASR, SR1B, 0xFF, 0xF0},
-{VIASR, SR1F, 0xFF, 0x00},
-{VIASR, SR1E, 0xFF, 0x01},
-{VIASR, SR22, 0xFF, 0x1F},
-{VIASR, SR2A, 0x0F, 0x00},
-{VIASR, SR2E, 0xFF, 0xFF},
-{VIASR, SR3F, 0xFF, 0xFF},
-{VIASR, SR40, 0xF7, 0x00},
-{VIASR, CR30, 0xFF, 0x04},
-{VIACR, CR32, 0xFF, 0x00},
-{VIACR, CR33, 0x7F, 0x00},
-{VIACR, CR35, 0xFF, 0x00},
-{VIACR, CR36, 0xFF, 0x31},
-{VIACR, CR41, 0xFF, 0x80},
-{VIACR, CR42, 0xFF, 0x00},
-{VIACR, CR55, 0x80, 0x00},
-{VIACR, CR5D, 0x80, 0x00},	/*Horizontal Retrace Start bit[11] should be 0*/
-{VIACR, CR68, 0xFF, 0x67},	/* Default FIFO For IGA2 */
-{VIACR, CR69, 0xFF, 0x00},
-{VIACR, CR6A, 0xFD, 0x40},
-{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR77, 0xFF, 0x00},	/* LCD scaling Factor */
-{VIACR, CR78, 0xFF, 0x00},	/* LCD scaling Factor */
-{VIACR, CR79, 0xFF, 0x00},	/* LCD scaling Factor */
-{VIACR, CR9F, 0x03, 0x00},	/* LCD scaling Factor */
-{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type */
-{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0 */
-{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1 */
-{VIACR, CR8B, 0xFF, 0x5D},	/* LCD Power Sequence Control 0 */
-{VIACR, CR8C, 0xFF, 0x2B},	/* LCD Power Sequence Control 1 */
-{VIACR, CR8D, 0xFF, 0x6F},	/* LCD Power Sequence Control 2 */
-{VIACR, CR8E, 0xFF, 0x2B},	/* LCD Power Sequence Control 3 */
-{VIACR, CR8F, 0xFF, 0x01},	/* LCD Power Sequence Control 4 */
-{VIACR, CR90, 0xFF, 0x01},	/* LCD Power Sequence Control 5 */
-{VIACR, CR91, 0xFF, 0xA0},	/* 24/12 bit LVDS Data off */
-{VIACR, CR96, 0xFF, 0x00},
-{VIACR, CR97, 0xFF, 0x00},
-{VIACR, CR99, 0xFF, 0x00},
-{VIACR, CR9B, 0xFF, 0x00},
-{VIACR, CR9D, 0xFF, 0x80},
-{VIACR, CR9E, 0xFF, 0x80}
-};
-
-struct io_reg KM400_ModeXregs[] = {
-	{VIASR, SR10, 0xFF, 0x01},	/* Unlock Register                 */
-	{VIASR, SR16, 0xFF, 0x08},	/* Display FIFO threshold Control  */
-	{VIASR, SR17, 0xFF, 0x1F},	/* Display FIFO Control            */
-	{VIASR, SR18, 0xFF, 0x4E},	/* GFX PREQ threshold              */
-	{VIASR, SR1A, 0xFF, 0x0a},	/* GFX PREQ threshold              */
-	{VIASR, SR1F, 0xFF, 0x00},	/* Memory Control 0                */
-	{VIASR, SR1B, 0xFF, 0xF0},	/* Power Management Control 0      */
-	{VIASR, SR1E, 0xFF, 0x01},	/* Power Management Control        */
-	{VIASR, SR20, 0xFF, 0x00},	/* Sequencer Arbiter Control 0     */
-	{VIASR, SR21, 0xFF, 0x00},	/* Sequencer Arbiter Control 1     */
-	{VIASR, SR22, 0xFF, 0x1F},	/* Display Arbiter Control 1       */
-	{VIASR, SR2A, 0xFF, 0x00},	/* Power Management Control 5      */
-	{VIASR, SR2D, 0xFF, 0xFF},	/* Power Management Control 1      */
-	{VIASR, SR2E, 0xFF, 0xFF},	/* Power Management Control 2      */
-	{VIACR, CR33, 0xFF, 0x00},
-	{VIACR, CR55, 0x80, 0x00},
-	{VIACR, CR5D, 0x80, 0x00},
-	{VIACR, CR36, 0xFF, 0x01},	/* Power Mangement 3                  */
-	{VIACR, CR68, 0xFF, 0x67},	/* Default FIFO For IGA2              */
-	{VIACR, CR6A, 0x20, 0x20},	/* Extended FIFO On                   */
-	{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                     */
-	{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0               */
-	{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1               */
-	{VIACR, CR8B, 0xFF, 0x2D},	/* LCD Power Sequence Control 0       */
-	{VIACR, CR8C, 0xFF, 0x2D},	/* LCD Power Sequence Control 1       */
-	{VIACR, CR8D, 0xFF, 0xC8},	/* LCD Power Sequence Control 2       */
-	{VIACR, CR8E, 0xFF, 0x36},	/* LCD Power Sequence Control 3       */
-	{VIACR, CR8F, 0xFF, 0x00},	/* LCD Power Sequence Control 4       */
-	{VIACR, CR90, 0xFF, 0x10},	/* LCD Power Sequence Control 5       */
-	{VIACR, CR91, 0xFF, 0xA0},	/* 24/12 bit LVDS Data off            */
-	{VIACR, CR96, 0xFF, 0x03},	/* DVP0        ; DVP0 Clock Skew */
-	{VIACR, CR97, 0xFF, 0x03},	/* DFP high    ; DFPH Clock Skew */
-	{VIACR, CR99, 0xFF, 0x03},	/* DFP low           ; DFPL Clock Skew*/
-	{VIACR, CR9B, 0xFF, 0x07}	/* DVI on DVP1       ; DVP1 Clock Skew*/
-};
-
-/* For VT3324: Common Setting for Video Mode */
-struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
-{VIASR, SR15, 0x02, 0x02},
-{VIASR, SR16, 0xBF, 0x08},
-{VIASR, SR17, 0xFF, 0x1F},
-{VIASR, SR18, 0xFF, 0x4E},
-{VIASR, SR1A, 0xFB, 0x08},
-{VIASR, SR1B, 0xFF, 0xF0},
-{VIASR, SR1E, 0xFF, 0x01},
-{VIASR, SR2A, 0xFF, 0x00},
-{VIASR, SR2D, 0xC0, 0xC0},	/* delayed E3_ECK */
-{VIACR, CR32, 0xFF, 0x00},
-{VIACR, CR33, 0xFF, 0x00},
-{VIACR, CR35, 0xFF, 0x00},
-{VIACR, CR36, 0x08, 0x00},
-{VIACR, CR47, 0xC8, 0x00},	/* Clear VCK Plus. */
-{VIACR, CR69, 0xFF, 0x00},
-{VIACR, CR6A, 0xFF, 0x40},
-{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                      */
-{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0                */
-{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1                */
-{VIACR, CRD4, 0xFF, 0x81},	/* Second power sequence control       */
-{VIACR, CR8B, 0xFF, 0x5D},	/* LCD Power Sequence Control 0        */
-{VIACR, CR8C, 0xFF, 0x2B},	/* LCD Power Sequence Control 1        */
-{VIACR, CR8D, 0xFF, 0x6F},	/* LCD Power Sequence Control 2        */
-{VIACR, CR8E, 0xFF, 0x2B},	/* LCD Power Sequence Control 3        */
-{VIACR, CR8F, 0xFF, 0x01},	/* LCD Power Sequence Control 4        */
-{VIACR, CR90, 0xFF, 0x01},	/* LCD Power Sequence Control 5        */
-{VIACR, CR91, 0xFF, 0x80},	/* 24/12 bit LVDS Data off             */
-{VIACR, CR96, 0xFF, 0x00},
-{VIACR, CR97, 0xFF, 0x00},
-{VIACR, CR99, 0xFF, 0x00},
-{VIACR, CR9B, 0xFF, 0x00}
-};
-
-struct io_reg VX855_ModeXregs[] = {
-{VIASR, SR10, 0xFF, 0x01},
-{VIASR, SR15, 0x02, 0x02},
-{VIASR, SR16, 0xBF, 0x08},
-{VIASR, SR17, 0xFF, 0x1F},
-{VIASR, SR18, 0xFF, 0x4E},
-{VIASR, SR1A, 0xFB, 0x08},
-{VIASR, SR1B, 0xFF, 0xF0},
-{VIASR, SR1E, 0x07, 0x01},
-{VIASR, SR2A, 0xF0, 0x00},
-{VIASR, SR58, 0xFF, 0x00},
-{VIASR, SR59, 0xFF, 0x00},
-{VIASR, SR2D, 0xC0, 0xC0},	/* delayed E3_ECK */
-{VIACR, CR32, 0xFF, 0x00},
-{VIACR, CR33, 0x7F, 0x00},
-{VIACR, CR35, 0xFF, 0x00},
-{VIACR, CR36, 0x08, 0x00},
-{VIACR, CR69, 0xFF, 0x00},
-{VIACR, CR6A, 0xFD, 0x60},
-{VIACR, CR6B, 0xFF, 0x00},
-{VIACR, CR88, 0xFF, 0x40},          /* LCD Panel Type                      */
-{VIACR, CR89, 0xFF, 0x00},          /* LCD Timing Control 0                */
-{VIACR, CR8A, 0xFF, 0x88},          /* LCD Timing Control 1                */
-{VIACR, CRD4, 0xFF, 0x81},          /* Second power sequence control       */
-{VIACR, CR91, 0xFF, 0x80},          /* 24/12 bit LVDS Data off             */
-{VIACR, CR96, 0xFF, 0x00},
-{VIACR, CR97, 0xFF, 0x00},
-{VIACR, CR99, 0xFF, 0x00},
-{VIACR, CR9B, 0xFF, 0x00},
-{VIACR, CRD2, 0xFF, 0xFF}           /* TMDS/LVDS control register.         */
-};
-
-/* Video Mode Table */
-/* Common Setting for Video Mode */
-struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
-{VIASR, SR2A, 0x0F, 0x00},
-{VIASR, SR15, 0x02, 0x02},
-{VIASR, SR16, 0xBF, 0x08},
-{VIASR, SR17, 0xFF, 0x1F},
-{VIASR, SR18, 0xFF, 0x4E},
-{VIASR, SR1A, 0xFB, 0x08},
-
-{VIACR, CR32, 0xFF, 0x00},
-{VIACR, CR35, 0xFF, 0x00},
-{VIACR, CR36, 0x08, 0x00},
-{VIACR, CR6A, 0xFF, 0x80},
-{VIACR, CR6A, 0xFF, 0xC0},
-
-{VIACR, CR55, 0x80, 0x00},
-{VIACR, CR5D, 0x80, 0x00},
-
-{VIAGR, GR20, 0xFF, 0x00},
-{VIAGR, GR21, 0xFF, 0x00},
-{VIAGR, GR22, 0xFF, 0x00},
-
-};
-
-/* Mode:1024X768 */
-struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C},
-{VIASR, 0x18, 0xFF, 0x4C}
-};
-
-struct patch_table res_patch_table[] = {
-	{ARRAY_SIZE(PM1024x768), PM1024x768}
-};
-
-/* struct VPITTable {
-	unsigned char  Misc;
-	unsigned char  SR[StdSR];
-	unsigned char  CR[StdCR];
-	unsigned char  GR[StdGR];
-	unsigned char  AR[StdAR];
- };*/
-
-struct VPITTable VPIT = {
-	/* Msic */
-	0xC7,
-	/* Sequencer */
-	{0x01, 0x0F, 0x00, 0x0E},
-	/* Graphic Controller */
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
-	/* Attribute Controller */
-	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-	 0x01, 0x00, 0x0F, 0x00}
-};
-
-/********************/
-/* Mode Table       */
-/********************/
-
-static const struct fb_videomode viafb_modes[] = {
-	{NULL, 60, 480, 640, 40285, 72, 24, 19, 1, 48, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, 0, 0},
-	{NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0, 0},
-	{NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3, 0, 0, 0},
-	{NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 120, 640, 480, 19081, 104, 40, 31, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 720, 480, 37426, 88, 16, 13, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 720, 576, 30611, 96, 24, 17, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 100, 800, 600, 14667, 136, 48, 32, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 120, 800, 600, 11911, 144, 56, 39, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 800, 480, 33602, 96, 24, 10, 3, 72, 7, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 848, 480, 31565, 104, 24, 12, 3, 80, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 856, 480, 31517, 104, 16, 13, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1024, 512, 24218, 136, 32, 15, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1024, 600, 20423, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, 0, 0, 0},
-	{NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1280, 768, 12478, 200, 64, 23, 1, 136, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 50, 1280, 768, 15342, 184, 56, 19, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 960, 600, 21964, 128, 32, 15, 3, 96, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1000, 600, 20803, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1024, 576, 21278, 144, 40, 17, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1088, 612, 18825, 152, 48, 16, 3, 104, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1152, 720, 14974, 168, 56, 19, 3, 112, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1200, 720, 14248, 184, 56, 22, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 49, 1200, 900, 17703, 21, 11, 1, 1, 32, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1280, 600, 16259, 184, 56, 18, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1280, 800, 11938, 200, 72, 22, 3, 128, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1360, 768, 11759, 208, 72, 22, 3, 136, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 50, 1368, 768, 14301, 200, 56, 19, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1440, 900, 9372, 232, 80, 25, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 75, 1440, 900, 7311, 248, 96, 33, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1440, 1040, 7993, 248, 96, 33, 1, 152, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1600, 900, 8449, 256, 88, 26, 3, 168, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1600, 1024, 7333, 272, 104, 32, 1, 168, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1680, 1050, 6832, 280, 104, 30, 3, 176, 6, 0, 0, 0},
-	{NULL, 75, 1680, 1050, 5339, 296, 120, 40, 3, 176, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1792, 1344, 4883, 328, 128, 46, 1, 200, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1856, 1392, 4581, 352, 96, 43, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 2048, 1536, 3738, 376, 152, 49, 3, 224, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1280, 720, 13484, 216, 112, 20, 5, 40, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 50, 1280, 720, 16538, 176, 48, 17, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1920, 1080, 5776, 328, 128, 32, 3, 200, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1920, 1200, 5164, 336, 136, 36, 3, 200, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 60, 1400, 1050, 8210, 232, 88, 32, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
-	{NULL, 75, 1400, 1050, 6398, 248, 104, 42, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0} };
-
-static const struct fb_videomode viafb_rb_modes[] = {
-	{NULL, 60, 1360, 768, 13879, 80, 48, 14, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
-	{NULL, 60, 1440, 900, 11249, 80, 48, 17, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
-	{NULL, 60, 1400, 1050, 9892, 80, 48, 23, 3, 32, 4, FB_SYNC_HOR_HIGH_ACT, 0, 0},
-	{NULL, 60, 1600, 900, 10226, 80, 48, 18, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
-	{NULL, 60, 1680, 1050, 8387, 80, 48, 21, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
-	{NULL, 60, 1920, 1080, 7212, 80, 48, 23, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
-	{NULL, 60, 1920, 1200, 6488, 80, 48, 26, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0} };
-
-int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
-int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
-int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs);
-int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs);
-int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs);
-int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
-int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
-
-
-static const struct fb_videomode *get_best_mode(
-	const struct fb_videomode *modes, int n,
-	int hres, int vres, int refresh)
-{
-	const struct fb_videomode *best = NULL;
-	int i;
-
-	for (i = 0; i < n; i++) {
-		if (modes[i].xres != hres || modes[i].yres != vres)
-			continue;
-
-		if (!best || abs(modes[i].refresh - refresh) <
-			abs(best->refresh - refresh))
-			best = &modes[i];
-	}
-
-	return best;
-}
-
-const struct fb_videomode *viafb_get_best_mode(int hres, int vres, int refresh)
-{
-	return get_best_mode(viafb_modes, ARRAY_SIZE(viafb_modes),
-		hres, vres, refresh);
-}
-
-const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
-	int refresh)
-{
-	return get_best_mode(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes),
-		hres, vres, refresh);
-}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
deleted file mode 100644
index dd19106698e7..000000000000
--- a/drivers/video/via/viamode.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __VIAMODE_H__
-#define __VIAMODE_H__
-
-#include "global.h"
-
-struct VPITTable {
-	unsigned char Misc;
-	unsigned char SR[StdSR];
-	unsigned char GR[StdGR];
-	unsigned char AR[StdAR];
-};
-
-struct patch_table {
-	int table_length;
-	struct io_reg *io_reg_table;
-};
-
-extern int NUM_TOTAL_CN400_ModeXregs;
-extern int NUM_TOTAL_CN700_ModeXregs;
-extern int NUM_TOTAL_KM400_ModeXregs;
-extern int NUM_TOTAL_CX700_ModeXregs;
-extern int NUM_TOTAL_VX855_ModeXregs;
-extern int NUM_TOTAL_CLE266_ModeXregs;
-extern int NUM_TOTAL_PATCH_MODE;
-
-extern struct io_reg CN400_ModeXregs[];
-extern struct io_reg CN700_ModeXregs[];
-extern struct io_reg KM400_ModeXregs[];
-extern struct io_reg CX700_ModeXregs[];
-extern struct io_reg VX800_ModeXregs[];
-extern struct io_reg VX855_ModeXregs[];
-extern struct io_reg CLE266_ModeXregs[];
-extern struct io_reg PM1024x768[];
-extern struct patch_table res_patch_table[];
-extern struct VPITTable VPIT;
-
-const struct fb_videomode *viafb_get_best_mode(int hres, int vres,
-	int refresh);
-const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
-	int refresh);
-
-#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
deleted file mode 100644
index ee2903b472cf..000000000000
--- a/drivers/video/via/vt1636.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/via-core.h>
-#include <linux/via_i2c.h>
-#include "global.h"
-
-static const struct IODATA common_init_data[] = {
-/*  Index, Mask, Value */
-	/* Set panel power sequence timing */
-	{0x10, 0xC0, 0x00},
-	/* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
-	{0x0B, 0xFF, 0x40},
-	/* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
-	{0x0C, 0xFF, 0x31},
-	/* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
-	{0x0D, 0xFF, 0x31},
-	/* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
-	{0x0E, 0xFF, 0x68},
-	/* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
-	{0x0F, 0xFF, 0x68},
-	/* LVDS output power up */
-	{0x09, 0xA0, 0xA0},
-	/* turn on back light */
-	{0x10, 0x33, 0x13}
-};
-
-/* Index, Mask, Value */
-static const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
-static const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
-static const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
-static const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
-static const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
-static const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
-
-u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
-	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
-	u8 index)
-{
-	u8 data;
-
-	viafb_i2c_readbyte(plvds_chip_info->i2c_port,
-			   plvds_chip_info->lvds_chip_slave_addr, index, &data);
-	return data;
-}
-
-void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
-			      *plvds_setting_info, struct lvds_chip_information
-			      *plvds_chip_info, struct IODATA io_data)
-{
-	int index, data;
-
-	index = io_data.Index;
-	data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
-		index);
-	data = (data & (~io_data.Mask)) | io_data.Data;
-
-	viafb_i2c_writebyte(plvds_chip_info->i2c_port,
-			    plvds_chip_info->lvds_chip_slave_addr, index, data);
-}
-
-void viafb_init_lvds_vt1636(struct lvds_setting_information
-	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
-{
-	int reg_num, i;
-
-	/* Common settings: */
-	reg_num = ARRAY_SIZE(common_init_data);
-	for (i = 0; i < reg_num; i++)
-		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-			plvds_chip_info, common_init_data[i]);
-
-	/* Input Data Mode Select */
-	if (plvds_setting_info->device_lcd_dualedge)
-		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-			plvds_chip_info, dual_channel_enable_data);
-	else
-		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-			plvds_chip_info, single_channel_enable_data);
-
-	if (plvds_setting_info->LCDDithering)
-		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-			plvds_chip_info, dithering_enable_data);
-	else
-		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-			plvds_chip_info, dithering_disable_data);
-}
-
-void viafb_enable_lvds_vt1636(struct lvds_setting_information
-			*plvds_setting_info,
-			struct lvds_chip_information *plvds_chip_info)
-{
-	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
-		vdd_on_data);
-}
-
-void viafb_disable_lvds_vt1636(struct lvds_setting_information
-			 *plvds_setting_info,
-			 struct lvds_chip_information *plvds_chip_info)
-{
-	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
-		vdd_off_data);
-}
-
-bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
-{
-	u8 Buffer[2];
-
-	DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
-
-	/* Sense VT1636 LVDS Transmiter */
-	viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
-		VT1636_LVDS_I2C_ADDR;
-
-	/* Check vendor ID first: */
-	if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR,
-					0x00, &Buffer[0]))
-		return false;
-	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]);
-
-	if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
-		return false;
-
-	/* Check Chip ID: */
-	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]);
-	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]);
-	if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
-		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
-			VT1636_LVDS;
-		return true;
-	}
-
-	return false;
-}
-
-static int get_clk_range_index(u32 Clk)
-{
-	if (Clk < DPA_CLK_30M)
-		return DPA_CLK_RANGE_30M;
-	else if (Clk < DPA_CLK_50M)
-		return DPA_CLK_RANGE_30_50M;
-	else if (Clk < DPA_CLK_70M)
-		return DPA_CLK_RANGE_50_70M;
-	else if (Clk < DPA_CLK_100M)
-		return DPA_CLK_RANGE_70_100M;
-	else if (Clk < DPA_CLK_150M)
-		return DPA_CLK_RANGE_100_150M;
-	else
-		return DPA_CLK_RANGE_150M;
-}
-
-static void set_dpa_vt1636(struct lvds_setting_information
-	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
-		    struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
-{
-	struct IODATA io_data;
-
-	io_data.Index = 0x09;
-	io_data.Mask = 0x1F;
-	io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
-	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
-		plvds_chip_info, io_data);
-
-	io_data.Index = 0x08;
-	io_data.Mask = 0x0F;
-	io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
-	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
-		io_data);
-}
-
-void viafb_vt1636_patch_skew_on_vt3324(
-	struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info)
-{
-	struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
-		*pdpa;
-	int index;
-
-	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
-
-	/* Graphics DPA settings: */
-	index = get_clk_range_index(plvds_setting_info->vclk);
-	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
-		    &GFX_DPA_SETTING_TBL_VT3324[index]);
-
-	/* LVDS Transmitter DPA settings: */
-	if (plvds_setting_info->lcd_panel_hres == 1600 &&
-		plvds_setting_info->lcd_panel_vres == 1200)
-		pdpa = &dpa_16x12;
-	else
-		pdpa = &dpa;
-
-	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
-}
-
-void viafb_vt1636_patch_skew_on_vt3327(
-	struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info)
-{
-	struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
-	int index;
-
-	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
-
-	/* Graphics DPA settings: */
-	index = get_clk_range_index(plvds_setting_info->vclk);
-	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
-		    &GFX_DPA_SETTING_TBL_VT3327[index]);
-
-	/* LVDS Transmitter DPA settings: */
-	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
-}
-
-void viafb_vt1636_patch_skew_on_vt3364(
-	struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info)
-{
-	int index;
-
-	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
-
-	/* Graphics DPA settings: */
-	index = get_clk_range_index(plvds_setting_info->vclk);
-	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
-		    &GFX_DPA_SETTING_TBL_VT3364[index]);
-}
diff --git a/drivers/video/via/vt1636.h b/drivers/video/via/vt1636.h
deleted file mode 100644
index 4c1314e57468..000000000000
--- a/drivers/video/via/vt1636.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _VT1636_H_
-#define _VT1636_H_
-#include "chip.h"
-bool viafb_lvds_identify_vt1636(u8 i2c_adapter);
-void viafb_init_lvds_vt1636(struct lvds_setting_information
-	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
-void viafb_enable_lvds_vt1636(struct lvds_setting_information
-			*plvds_setting_info,
-			struct lvds_chip_information *plvds_chip_info);
-void viafb_disable_lvds_vt1636(struct lvds_setting_information
-			 *plvds_setting_info,
-			 struct lvds_chip_information *plvds_chip_info);
-void viafb_vt1636_patch_skew_on_vt3324(
-	struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info);
-void viafb_vt1636_patch_skew_on_vt3327(
-	struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info);
-void viafb_vt1636_patch_skew_on_vt3364(
-	struct lvds_setting_information *plvds_setting_info,
-	struct lvds_chip_information *plvds_chip_info);
-
-#endif
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
deleted file mode 100644
index a8f2b280f796..000000000000
--- a/drivers/video/vt8500lcdfb.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- *  linux/drivers/video/vt8500lcdfb.c
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * Based on skeletonfb.c and pxafb.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <video/of_display_timing.h>
-
-#include "vt8500lcdfb.h"
-#include "wmt_ge_rops.h"
-
-#ifdef CONFIG_OF
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/memblock.h>
-#endif
-
-
-#define to_vt8500lcd_info(__info) container_of(__info, \
-						struct vt8500lcd_info, fb)
-
-static int vt8500lcd_set_par(struct fb_info *info)
-{
-	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
-	int reg_bpp = 5; /* 16bpp */
-	int i;
-	unsigned long control0;
-
-	if (!fbi)
-		return -EINVAL;
-
-	if (info->var.bits_per_pixel <= 8) {
-		/* palettized */
-		info->var.red.offset    = 0;
-		info->var.red.length    = info->var.bits_per_pixel;
-		info->var.red.msb_right = 0;
-
-		info->var.green.offset  = 0;
-		info->var.green.length  = info->var.bits_per_pixel;
-		info->var.green.msb_right = 0;
-
-		info->var.blue.offset   = 0;
-		info->var.blue.length   = info->var.bits_per_pixel;
-		info->var.blue.msb_right = 0;
-
-		info->var.transp.offset = 0;
-		info->var.transp.length = 0;
-		info->var.transp.msb_right = 0;
-
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		info->fix.line_length = info->var.xres_virtual /
-						(8/info->var.bits_per_pixel);
-	} else {
-		/* non-palettized */
-		info->var.transp.offset = 0;
-		info->var.transp.length = 0;
-		info->var.transp.msb_right = 0;
-
-		if (info->var.bits_per_pixel == 16) {
-			/* RGB565 */
-			info->var.red.offset = 11;
-			info->var.red.length = 5;
-			info->var.red.msb_right = 0;
-			info->var.green.offset = 5;
-			info->var.green.length = 6;
-			info->var.green.msb_right = 0;
-			info->var.blue.offset = 0;
-			info->var.blue.length = 5;
-			info->var.blue.msb_right = 0;
-		} else {
-			/* Equal depths per channel */
-			info->var.red.offset = info->var.bits_per_pixel
-							* 2 / 3;
-			info->var.red.length = info->var.bits_per_pixel / 3;
-			info->var.red.msb_right = 0;
-			info->var.green.offset = info->var.bits_per_pixel / 3;
-			info->var.green.length = info->var.bits_per_pixel / 3;
-			info->var.green.msb_right = 0;
-			info->var.blue.offset = 0;
-			info->var.blue.length = info->var.bits_per_pixel / 3;
-			info->var.blue.msb_right = 0;
-		}
-
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		info->fix.line_length = info->var.bits_per_pixel > 16 ?
-					info->var.xres_virtual << 2 :
-					info->var.xres_virtual << 1;
-	}
-
-	for (i = 0; i < 8; i++) {
-		if (bpp_values[i] == info->var.bits_per_pixel) {
-			reg_bpp = i;
-			continue;
-		}
-	}
-
-	control0 = readl(fbi->regbase) & ~0xf;
-	writel(0, fbi->regbase);
-	while (readl(fbi->regbase + 0x38) & 0x10)
-		/* wait */;
-	writel((((info->var.hsync_len - 1) & 0x3f) << 26)
-		| ((info->var.left_margin & 0xff) << 18)
-		| (((info->var.xres - 1) & 0x3ff) << 8)
-		| (info->var.right_margin & 0xff), fbi->regbase + 0x4);
-	writel((((info->var.vsync_len - 1) & 0x3f) << 26)
-		| ((info->var.upper_margin & 0xff) << 18)
-		| (((info->var.yres - 1) & 0x3ff) << 8)
-		| (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
-	writel((((info->var.yres - 1) & 0x400) << 2)
-		| ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
-	writel(0x80000000, fbi->regbase + 0x20);
-	writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
-
-	return 0;
-}
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info) {
-	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
-	int ret = 1;
-	unsigned int val;
-	if (regno >= 256)
-		return -EINVAL;
-
-	if (info->var.grayscale)
-		red = green = blue =
-			(19595 * red + 38470 * green + 7471 * blue) >> 16;
-
-	switch (fbi->fb.fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		if (regno < 16) {
-			u32 *pal = fbi->fb.pseudo_palette;
-
-			val  = chan_to_field(red, &fbi->fb.var.red);
-			val |= chan_to_field(green, &fbi->fb.var.green);
-			val |= chan_to_field(blue, &fbi->fb.var.blue);
-
-			pal[regno] = val;
-			ret = 0;
-		}
-		break;
-
-	case FB_VISUAL_STATIC_PSEUDOCOLOR:
-	case FB_VISUAL_PSEUDOCOLOR:
-		writew((red & 0xf800)
-		      | ((green >> 5) & 0x7e0)
-		      | ((blue >> 11) & 0x1f),
-		       fbi->palette_cpu + sizeof(u16) * regno);
-		break;
-	}
-
-	return ret;
-}
-
-static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
-			 unsigned long arg)
-{
-	int ret = 0;
-	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
-
-	if (cmd == FBIO_WAITFORVSYNC) {
-		/* Unmask End of Frame interrupt */
-		writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
-		ret = wait_event_interruptible_timeout(fbi->wait,
-			readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
-		/* Mask back to reduce unwanted interrupt traffic */
-		writel(0xffffffff, fbi->regbase + 0x3c);
-		if (ret < 0)
-			return ret;
-		if (ret == 0)
-			return -ETIMEDOUT;
-	}
-
-	return ret;
-}
-
-static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
-	unsigned off = pixlen * var->xoffset
-		      + info->fix.line_length * var->yoffset;
-	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
-
-	writel((1 << 31)
-	     | (((info->var.xres_virtual - info->var.xres) * pixlen / 4) << 20)
-	     | (off >> 2), fbi->regbase + 0x20);
-	return 0;
-}
-
-/*
- * vt8500lcd_blank():
- *	Blank the display by setting all palette values to zero.  Note,
- * 	True Color modes do not really use the palette, so this will not
- *      blank the display in all modes.
- */
-static int vt8500lcd_blank(int blank, struct fb_info *info)
-{
-	int i;
-
-	switch (blank) {
-	case FB_BLANK_POWERDOWN:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-		if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
-		    info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-			for (i = 0; i < 256; i++)
-				vt8500lcd_setcolreg(i, 0, 0, 0, 0, info);
-	case FB_BLANK_UNBLANK:
-		if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
-		    info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-			fb_set_cmap(&info->cmap, info);
-	}
-	return 0;
-}
-
-static struct fb_ops vt8500lcd_ops = {
-	.owner		= THIS_MODULE,
-	.fb_set_par	= vt8500lcd_set_par,
-	.fb_setcolreg	= vt8500lcd_setcolreg,
-	.fb_fillrect	= wmt_ge_fillrect,
-	.fb_copyarea	= wmt_ge_copyarea,
-	.fb_imageblit	= sys_imageblit,
-	.fb_sync	= wmt_ge_sync,
-	.fb_ioctl	= vt8500lcd_ioctl,
-	.fb_pan_display	= vt8500lcd_pan_display,
-	.fb_blank	= vt8500lcd_blank,
-};
-
-static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
-{
-	struct vt8500lcd_info *fbi = dev_id;
-
-	if (readl(fbi->regbase + 0x38) & (1 << 3))
-		wake_up_interruptible(&fbi->wait);
-
-	writel(0xffffffff, fbi->regbase + 0x38);
-	return IRQ_HANDLED;
-}
-
-static int vt8500lcd_probe(struct platform_device *pdev)
-{
-	struct vt8500lcd_info *fbi;
-	struct resource *res;
-	struct display_timings *disp_timing;
-	void *addr;
-	int irq, ret;
-
-	struct fb_videomode	of_mode;
-	u32			bpp;
-	dma_addr_t fb_mem_phys;
-	unsigned long fb_mem_len;
-	void *fb_mem_virt;
-
-	ret = -ENOMEM;
-	fbi = NULL;
-
-	fbi = devm_kzalloc(&pdev->dev, sizeof(struct vt8500lcd_info)
-			+ sizeof(u32) * 16, GFP_KERNEL);
-	if (!fbi) {
-		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-		return -ENOMEM;
-	}
-
-	strcpy(fbi->fb.fix.id, "VT8500 LCD");
-
-	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
-	fbi->fb.fix.xpanstep	= 0;
-	fbi->fb.fix.ypanstep	= 1;
-	fbi->fb.fix.ywrapstep	= 0;
-	fbi->fb.fix.accel	= FB_ACCEL_NONE;
-
-	fbi->fb.var.nonstd	= 0;
-	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
-	fbi->fb.var.height	= -1;
-	fbi->fb.var.width	= -1;
-	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
-
-	fbi->fb.fbops		= &vt8500lcd_ops;
-	fbi->fb.flags		= FBINFO_DEFAULT
-				| FBINFO_HWACCEL_COPYAREA
-				| FBINFO_HWACCEL_FILLRECT
-				| FBINFO_HWACCEL_YPAN
-				| FBINFO_VIRTFB
-				| FBINFO_PARTIAL_PAN_OK;
-	fbi->fb.node		= -1;
-
-	addr = fbi;
-	addr = addr + sizeof(struct vt8500lcd_info);
-	fbi->fb.pseudo_palette	= addr;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no I/O memory resource defined\n");
-		return -ENODEV;
-	}
-
-	res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
-	if (res == NULL) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		return -EBUSY;
-	}
-
-	fbi->regbase = ioremap(res->start, resource_size(res));
-	if (fbi->regbase == NULL) {
-		dev_err(&pdev->dev, "failed to map I/O memory\n");
-		ret = -EBUSY;
-		goto failed_free_res;
-	}
-
-	disp_timing = of_get_display_timings(pdev->dev.of_node);
-	if (!disp_timing) {
-		ret = -EINVAL;
-		goto failed_free_io;
-	}
-
-	ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
-							OF_USE_NATIVE_MODE);
-	if (ret)
-		goto failed_free_io;
-
-	ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
-	if (ret)
-		goto failed_free_io;
-
-	/* try allocating the framebuffer */
-	fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
-	fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
-				GFP_KERNEL);
-	if (!fb_mem_virt) {
-		pr_err("%s: Failed to allocate framebuffer\n", __func__);
-		ret = -ENOMEM;
-		goto failed_free_io;
-	}
-
-	fbi->fb.fix.smem_start	= fb_mem_phys;
-	fbi->fb.fix.smem_len	= fb_mem_len;
-	fbi->fb.screen_base	= fb_mem_virt;
-
-	fbi->palette_size	= PAGE_ALIGN(512);
-	fbi->palette_cpu	= dma_alloc_coherent(&pdev->dev,
-						     fbi->palette_size,
-						     &fbi->palette_phys,
-						     GFP_KERNEL);
-	if (fbi->palette_cpu == NULL) {
-		dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
-		ret = -ENOMEM;
-		goto failed_free_io;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no IRQ defined\n");
-		ret = -ENODEV;
-		goto failed_free_palette;
-	}
-
-	ret = request_irq(irq, vt8500lcd_handle_irq, 0, "LCD", fbi);
-	if (ret) {
-		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
-		ret = -EBUSY;
-		goto failed_free_palette;
-	}
-
-	init_waitqueue_head(&fbi->wait);
-
-	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
-		dev_err(&pdev->dev, "Failed to allocate color map\n");
-		ret = -ENOMEM;
-		goto failed_free_irq;
-	}
-
-	fb_videomode_to_var(&fbi->fb.var, &of_mode);
-
-	fbi->fb.var.xres_virtual	= of_mode.xres;
-	fbi->fb.var.yres_virtual	= of_mode.yres * 2;
-	fbi->fb.var.bits_per_pixel	= bpp;
-
-	ret = vt8500lcd_set_par(&fbi->fb);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to set parameters\n");
-		goto failed_free_cmap;
-	}
-
-	writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
-	writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
-
-	platform_set_drvdata(pdev, fbi);
-
-	ret = register_framebuffer(&fbi->fb);
-	if (ret < 0) {
-		dev_err(&pdev->dev,
-			"Failed to register framebuffer device: %d\n", ret);
-		goto failed_free_cmap;
-	}
-
-	/*
-	 * Ok, now enable the LCD controller
-	 */
-	writel(readl(fbi->regbase) | 1, fbi->regbase);
-
-	return 0;
-
-failed_free_cmap:
-	if (fbi->fb.cmap.len)
-		fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_irq:
-	free_irq(irq, fbi);
-failed_free_palette:
-	dma_free_coherent(&pdev->dev, fbi->palette_size,
-			  fbi->palette_cpu, fbi->palette_phys);
-failed_free_io:
-	iounmap(fbi->regbase);
-failed_free_res:
-	release_mem_region(res->start, resource_size(res));
-	return ret;
-}
-
-static int vt8500lcd_remove(struct platform_device *pdev)
-{
-	struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
-	struct resource *res;
-	int irq;
-
-	unregister_framebuffer(&fbi->fb);
-
-	writel(0, fbi->regbase);
-
-	if (fbi->fb.cmap.len)
-		fb_dealloc_cmap(&fbi->fb.cmap);
-
-	irq = platform_get_irq(pdev, 0);
-	free_irq(irq, fbi);
-
-	dma_free_coherent(&pdev->dev, fbi->palette_size,
-			  fbi->palette_cpu, fbi->palette_phys);
-
-	iounmap(fbi->regbase);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	kfree(fbi);
-
-	return 0;
-}
-
-static const struct of_device_id via_dt_ids[] = {
-	{ .compatible = "via,vt8500-fb", },
-	{}
-};
-
-static struct platform_driver vt8500lcd_driver = {
-	.probe		= vt8500lcd_probe,
-	.remove		= vt8500lcd_remove,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "vt8500-lcd",
-		.of_match_table = of_match_ptr(via_dt_ids),
-	},
-};
-
-module_platform_driver(vt8500lcd_driver);
-
-MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
-MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, via_dt_ids);
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/vt8500lcdfb.h
deleted file mode 100644
index 36ca3ca09d83..000000000000
--- a/drivers/video/vt8500lcdfb.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  linux/drivers/video/vt8500lcdfb.h
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-struct vt8500lcd_info {
-	struct fb_info		fb;
-	void __iomem		*regbase;
-	void __iomem		*palette_cpu;
-	dma_addr_t		palette_phys;
-	size_t			palette_size;
-	wait_queue_head_t	wait;
-};
-
-static int bpp_values[] = {
-	1,
-	2,
-	4,
-	8,
-	12,
-	16,
-	18,
-	24,
-};
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
deleted file mode 100644
index 5c7cbc6c6236..000000000000
--- a/drivers/video/vt8623fb.c
+++ /dev/null
@@ -1,958 +0,0 @@
-/*
- * linux/drivers/video/vt8623fb.c - fbdev driver for
- * integrated graphic core in VIA VT8623 [CLE266] chipset
- *
- * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Code is based on s3fb, some parts are from David Boucher's viafb
- * (http://davesdomain.org.uk/viafb/)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/svga.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
-#include <video/vga.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-struct vt8623fb_info {
-	char __iomem *mmio_base;
-	int mtrr_reg;
-	struct vgastate state;
-	struct mutex open_lock;
-	unsigned int ref_count;
-	u32 pseudo_palette[16];
-};
-
-
-
-/* ------------------------------------------------------------------------- */
-
-static const struct svga_fb_format vt8623fb_formats[] = {
-	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP8,	FB_VISUAL_PSEUDOCOLOR, 16, 16},
-	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 16, 16},
-	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
-		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 16, 16},
-	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 8},
-/*	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},	*/
-	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 4, 4},
-	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 2},
-	SVGA_FORMAT_END
-};
-
-static const struct svga_pll vt8623_pll = {2, 127, 2, 7, 0, 3,
-	60000, 300000, 14318};
-
-/* CRT timing register sets */
-
-static struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
-static struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
-static struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
-static struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
-static struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
-static struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
-
-static struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
-static struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
-static struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
-static struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
-static struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
-static struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
-
-static struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
-static struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
-static struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
-static struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
-
-static struct svga_timing_regs vt8623_timing_regs     = {
-	vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
-	vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
-	vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
-	vt8623_v_blank_end_regs, vt8623_v_sync_start_regs, vt8623_v_sync_end_regs,
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* Module parameters */
-
-static char *mode_option = "640x480-8@60";
-
-#ifdef CONFIG_MTRR
-static int mtrr = 1;
-#endif
-
-MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <santiago@crfreenet.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("fbdev driver for integrated graphics core in VIA VT8623 [CLE266]");
-
-module_param(mode_option, charp, 0644);
-MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
-module_param_named(mode, mode_option, charp, 0);
-MODULE_PARM_DESC(mode, "Default video mode e.g. '648x480-8@60' (deprecated)");
-
-#ifdef CONFIG_MTRR
-module_param(mtrr, int, 0444);
-MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
-#endif
-
-
-/* ------------------------------------------------------------------------- */
-
-static void vt8623fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
-{
-	struct vt8623fb_info *par = info->par;
-
-	svga_tilecursor(par->state.vgabase, info, cursor);
-}
-
-static struct fb_tile_ops vt8623fb_tile_ops = {
-	.fb_settile	= svga_settile,
-	.fb_tilecopy	= svga_tilecopy,
-	.fb_tilefill    = svga_tilefill,
-	.fb_tileblit    = svga_tileblit,
-	.fb_tilecursor  = vt8623fb_tilecursor,
-	.fb_get_tilemax = svga_get_tilemax,
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* image data is MSB-first, fb structure is MSB-first too */
-static inline u32 expand_color(u32 c)
-{
-	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
-}
-
-/* vt8623fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
-static void vt8623fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	u32 fg = expand_color(image->fg_color);
-	u32 bg = expand_color(image->bg_color);
-	const u8 *src1, *src;
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	u32 val;
-	int x, y;
-
-	src1 = image->data;
-	dst1 = info->screen_base + (image->dy * info->fix.line_length)
-		 + ((image->dx / 8) * 4);
-
-	for (y = 0; y < image->height; y++) {
-		src = src1;
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < image->width; x += 8) {
-			val = *(src++) * 0x01010101;
-			val = (val & fg) | (~val & bg);
-			fb_writel(val, dst++);
-		}
-		src1 += image->width / 8;
-		dst1 += info->fix.line_length;
-	}
-}
-
-/* vt8623fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
-static void vt8623fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	u32 fg = expand_color(rect->color);
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	int x, y;
-
-	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
-		 + ((rect->dx / 8) * 4);
-
-	for (y = 0; y < rect->height; y++) {
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < rect->width; x += 8) {
-			fb_writel(fg, dst++);
-		}
-		dst1 += info->fix.line_length;
-	}
-}
-
-
-/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
-static inline u32 expand_pixel(u32 c)
-{
-	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
-		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
-}
-
-/* vt8623fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
-static void vt8623fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	u32 fg = image->fg_color * 0x11111111;
-	u32 bg = image->bg_color * 0x11111111;
-	const u8 *src1, *src;
-	u8 __iomem *dst1;
-	u32 __iomem *dst;
-	u32 val;
-	int x, y;
-
-	src1 = image->data;
-	dst1 = info->screen_base + (image->dy * info->fix.line_length)
-		 + ((image->dx / 8) * 4);
-
-	for (y = 0; y < image->height; y++) {
-		src = src1;
-		dst = (u32 __iomem *) dst1;
-		for (x = 0; x < image->width; x += 8) {
-			val = expand_pixel(*(src++));
-			val = (val & fg) | (~val & bg);
-			fb_writel(val, dst++);
-		}
-		src1 += image->width / 8;
-		dst1 += info->fix.line_length;
-	}
-}
-
-static void vt8623fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
-	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
-		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
-			vt8623fb_iplan_imageblit(info, image);
-		else
-			vt8623fb_cfb4_imageblit(info, image);
-	} else
-		cfb_imageblit(info, image);
-}
-
-static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	if ((info->var.bits_per_pixel == 4)
-	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
-	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
-		vt8623fb_iplan_fillrect(info, rect);
-	 else
-		cfb_fillrect(info, rect);
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock)
-{
-	struct vt8623fb_info *par = info->par;
-	u16 m, n, r;
-	u8 regval;
-	int rv;
-
-	rv = svga_compute_pll(&vt8623_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
-	if (rv < 0) {
-		fb_err(info, "cannot set requested pixclock, keeping old value\n");
-		return;
-	}
-
-	/* Set VGA misc register  */
-	regval = vga_r(par->state.vgabase, VGA_MIS_R);
-	vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
-
-	/* Set clock registers */
-	vga_wseq(par->state.vgabase, 0x46, (n  | (r << 6)));
-	vga_wseq(par->state.vgabase, 0x47, m);
-
-	udelay(1000);
-
-	/* PLL reset */
-	svga_wseq_mask(par->state.vgabase, 0x40, 0x02, 0x02);
-	svga_wseq_mask(par->state.vgabase, 0x40, 0x00, 0x02);
-}
-
-
-static int vt8623fb_open(struct fb_info *info, int user)
-{
-	struct vt8623fb_info *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	if (par->ref_count == 0) {
-		void __iomem *vgabase = par->state.vgabase;
-
-		memset(&(par->state), 0, sizeof(struct vgastate));
-		par->state.vgabase = vgabase;
-		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
-		par->state.num_crtc = 0xA2;
-		par->state.num_seq = 0x50;
-		save_vga(&(par->state));
-	}
-
-	par->ref_count++;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-static int vt8623fb_release(struct fb_info *info, int user)
-{
-	struct vt8623fb_info *par = info->par;
-
-	mutex_lock(&(par->open_lock));
-	if (par->ref_count == 0) {
-		mutex_unlock(&(par->open_lock));
-		return -EINVAL;
-	}
-
-	if (par->ref_count == 1)
-		restore_vga(&(par->state));
-
-	par->ref_count--;
-	mutex_unlock(&(par->open_lock));
-
-	return 0;
-}
-
-static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	int rv, mem, step;
-
-	/* Find appropriate format */
-	rv = svga_match_format (vt8623fb_formats, var, NULL);
-	if (rv < 0)
-	{
-		fb_err(info, "unsupported mode requested\n");
-		return rv;
-	}
-
-	/* Do not allow to have real resoulution larger than virtual */
-	if (var->xres > var->xres_virtual)
-		var->xres_virtual = var->xres;
-
-	if (var->yres > var->yres_virtual)
-		var->yres_virtual = var->yres;
-
-	/* Round up xres_virtual to have proper alignment of lines */
-	step = vt8623fb_formats[rv].xresstep - 1;
-	var->xres_virtual = (var->xres_virtual+step) & ~step;
-
-	/* Check whether have enough memory */
-	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
-	if (mem > info->screen_size)
-	{
-		fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n",
-		       mem >> 10, (unsigned int) (info->screen_size >> 10));
-		return -EINVAL;
-	}
-
-	/* Text mode is limited to 256 kB of memory */
-	if ((var->bits_per_pixel == 0) && (mem > (256*1024)))
-	{
-		fb_err(info, "text framebuffer size too large (%d kB requested, 256 kB possible)\n",
-		       mem >> 10);
-		return -EINVAL;
-	}
-
-	rv = svga_check_timings (&vt8623_timing_regs, var, info->node);
-	if (rv < 0)
-	{
-		fb_err(info, "invalid timings requested\n");
-		return rv;
-	}
-
-	/* Interlaced mode not supported */
-	if (var->vmode & FB_VMODE_INTERLACED)
-		return -EINVAL;
-
-	return 0;
-}
-
-
-static int vt8623fb_set_par(struct fb_info *info)
-{
-	u32 mode, offset_value, fetch_value, screen_size;
-	struct vt8623fb_info *par = info->par;
-	u32 bpp = info->var.bits_per_pixel;
-
-	if (bpp != 0) {
-		info->fix.ypanstep = 1;
-		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
-
-		info->flags &= ~FBINFO_MISC_TILEBLITTING;
-		info->tileops = NULL;
-
-		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */
-		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
-		info->pixmap.blit_y = ~(u32)0;
-
-		offset_value = (info->var.xres_virtual * bpp) / 64;
-		fetch_value  = ((info->var.xres * bpp) / 128) + 4;
-
-		if (bpp == 4)
-			fetch_value  = (info->var.xres / 8) + 8; /* + 0 is OK */
-
-		screen_size  = info->var.yres_virtual * info->fix.line_length;
-	} else {
-		info->fix.ypanstep = 16;
-		info->fix.line_length = 0;
-
-		info->flags |= FBINFO_MISC_TILEBLITTING;
-		info->tileops = &vt8623fb_tile_ops;
-
-		/* supports 8x16 tiles only */
-		info->pixmap.blit_x = 1 << (8 - 1);
-		info->pixmap.blit_y = 1 << (16 - 1);
-
-		offset_value = info->var.xres_virtual / 16;
-		fetch_value  = (info->var.xres / 8) + 8;
-		screen_size  = (info->var.xres_virtual * info->var.yres_virtual) / 64;
-	}
-
-	info->var.xoffset = 0;
-	info->var.yoffset = 0;
-	info->var.activate = FB_ACTIVATE_NOW;
-
-	/* Unlock registers */
-	svga_wseq_mask(par->state.vgabase, 0x10, 0x01, 0x01);
-	svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
-	svga_wcrt_mask(par->state.vgabase, 0x47, 0x00, 0x01);
-
-	/* Device, screen and sync off */
-	svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-	svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
-	svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
-
-	/* Set default values */
-	svga_set_default_gfx_regs(par->state.vgabase);
-	svga_set_default_atc_regs(par->state.vgabase);
-	svga_set_default_seq_regs(par->state.vgabase);
-	svga_set_default_crt_regs(par->state.vgabase);
-	svga_wcrt_multi(par->state.vgabase, vt8623_line_compare_regs, 0xFFFFFFFF);
-	svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, 0);
-
-	svga_wcrt_multi(par->state.vgabase, vt8623_offset_regs, offset_value);
-	svga_wseq_multi(par->state.vgabase, vt8623_fetch_count_regs, fetch_value);
-
-	/* Clear H/V Skew */
-	svga_wcrt_mask(par->state.vgabase, 0x03, 0x00, 0x60);
-	svga_wcrt_mask(par->state.vgabase, 0x05, 0x00, 0x60);
-
-	if (info->var.vmode & FB_VMODE_DOUBLE)
-		svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
-	else
-		svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
-
-	svga_wseq_mask(par->state.vgabase, 0x1E, 0xF0, 0xF0); // DI/DVP bus
-	svga_wseq_mask(par->state.vgabase, 0x2A, 0x0F, 0x0F); // DI/DVP bus
-	svga_wseq_mask(par->state.vgabase, 0x16, 0x08, 0xBF); // FIFO read threshold
-	vga_wseq(par->state.vgabase, 0x17, 0x1F);       // FIFO depth
-	vga_wseq(par->state.vgabase, 0x18, 0x4E);
-	svga_wseq_mask(par->state.vgabase, 0x1A, 0x08, 0x08); // enable MMIO ?
-
-	vga_wcrt(par->state.vgabase, 0x32, 0x00);
-	vga_wcrt(par->state.vgabase, 0x34, 0x00);
-	vga_wcrt(par->state.vgabase, 0x6A, 0x80);
-	vga_wcrt(par->state.vgabase, 0x6A, 0xC0);
-
-	vga_wgfx(par->state.vgabase, 0x20, 0x00);
-	vga_wgfx(par->state.vgabase, 0x21, 0x00);
-	vga_wgfx(par->state.vgabase, 0x22, 0x00);
-
-	/* Set SR15 according to number of bits per pixel */
-	mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix));
-	switch (mode) {
-	case 0:
-		fb_dbg(info, "text mode\n");
-		svga_set_textmode_vga_regs(par->state.vgabase);
-		svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
-		svga_wcrt_mask(par->state.vgabase, 0x11, 0x60, 0x70);
-		break;
-	case 1:
-		fb_dbg(info, "4 bit pseudocolor\n");
-		vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
-		svga_wseq_mask(par->state.vgabase, 0x15, 0x20, 0xFE);
-		svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
-		break;
-	case 2:
-		fb_dbg(info, "4 bit pseudocolor, planar\n");
-		svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
-		svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
-		break;
-	case 3:
-		fb_dbg(info, "8 bit pseudocolor\n");
-		svga_wseq_mask(par->state.vgabase, 0x15, 0x22, 0xFE);
-		break;
-	case 4:
-		fb_dbg(info, "5/6/5 truecolor\n");
-		svga_wseq_mask(par->state.vgabase, 0x15, 0xB6, 0xFE);
-		break;
-	case 5:
-		fb_dbg(info, "8/8/8 truecolor\n");
-		svga_wseq_mask(par->state.vgabase, 0x15, 0xAE, 0xFE);
-		break;
-	default:
-		printk(KERN_ERR "vt8623fb: unsupported mode - bug\n");
-		return (-EINVAL);
-	}
-
-	vt8623_set_pixclock(info, info->var.pixclock);
-	svga_set_timings(par->state.vgabase, &vt8623_timing_regs, &(info->var), 1, 1,
-			 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1,
-			 1, info->node);
-
-	memset_io(info->screen_base, 0x00, screen_size);
-
-	/* Device and screen back on */
-	svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
-	svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
-	svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
-
-	return 0;
-}
-
-
-static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-				u_int transp, struct fb_info *fb)
-{
-	switch (fb->var.bits_per_pixel) {
-	case 0:
-	case 4:
-		if (regno >= 16)
-			return -EINVAL;
-
-		outb(0x0F, VGA_PEL_MSK);
-		outb(regno, VGA_PEL_IW);
-		outb(red >> 10, VGA_PEL_D);
-		outb(green >> 10, VGA_PEL_D);
-		outb(blue >> 10, VGA_PEL_D);
-		break;
-	case 8:
-		if (regno >= 256)
-			return -EINVAL;
-
-		outb(0xFF, VGA_PEL_MSK);
-		outb(regno, VGA_PEL_IW);
-		outb(red >> 10, VGA_PEL_D);
-		outb(green >> 10, VGA_PEL_D);
-		outb(blue >> 10, VGA_PEL_D);
-		break;
-	case 16:
-		if (regno >= 16)
-			return 0;
-
-		if (fb->var.green.length == 5)
-			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
-				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
-		else if (fb->var.green.length == 6)
-			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
-				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-		else
-			return -EINVAL;
-		break;
-	case 24:
-	case 32:
-		if (regno >= 16)
-			return 0;
-
-		/* ((transp & 0xFF00) << 16) */
-		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
-			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
-static int vt8623fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct vt8623fb_info *par = info->par;
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		fb_dbg(info, "unblank\n");
-		svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
-		break;
-	case FB_BLANK_NORMAL:
-		fb_dbg(info, "blank\n");
-		svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	case FB_BLANK_HSYNC_SUSPEND:
-		fb_dbg(info, "DPMS standby (hsync off)\n");
-		svga_wcrt_mask(par->state.vgabase, 0x36, 0x10, 0x30);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	case FB_BLANK_VSYNC_SUSPEND:
-		fb_dbg(info, "DPMS suspend (vsync off)\n");
-		svga_wcrt_mask(par->state.vgabase, 0x36, 0x20, 0x30);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	case FB_BLANK_POWERDOWN:
-		fb_dbg(info, "DPMS off (no sync)\n");
-		svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
-		svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
-		break;
-	}
-
-	return 0;
-}
-
-
-static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct vt8623fb_info *par = info->par;
-	unsigned int offset;
-
-	/* Calculate the offset */
-	if (info->var.bits_per_pixel == 0) {
-		offset = (var->yoffset / 16) * info->var.xres_virtual
-		       + var->xoffset;
-		offset = offset >> 3;
-	} else {
-		offset = (var->yoffset * info->fix.line_length) +
-			 (var->xoffset * info->var.bits_per_pixel / 8);
-		offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1);
-	}
-
-	/* Set the offset */
-	svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, offset);
-
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-
-/* Frame buffer operations */
-
-static struct fb_ops vt8623fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_open	= vt8623fb_open,
-	.fb_release	= vt8623fb_release,
-	.fb_check_var	= vt8623fb_check_var,
-	.fb_set_par	= vt8623fb_set_par,
-	.fb_setcolreg	= vt8623fb_setcolreg,
-	.fb_blank	= vt8623fb_blank,
-	.fb_pan_display	= vt8623fb_pan_display,
-	.fb_fillrect	= vt8623fb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= vt8623fb_imageblit,
-	.fb_get_caps    = svga_get_caps,
-};
-
-
-/* PCI probe */
-
-static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct pci_bus_region bus_reg;
-	struct resource vga_res;
-	struct fb_info *info;
-	struct vt8623fb_info *par;
-	unsigned int memsize1, memsize2;
-	int rc;
-
-	/* Ignore secondary VGA device because there is no VGA arbitration */
-	if (! svga_primary_device(dev)) {
-		dev_info(&(dev->dev), "ignoring secondary device\n");
-		return -ENODEV;
-	}
-
-	/* Allocate and fill driver data structure */
-	info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev));
-	if (! info) {
-		dev_err(&(dev->dev), "cannot allocate memory\n");
-		return -ENOMEM;
-	}
-
-	par = info->par;
-	mutex_init(&par->open_lock);
-
-	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
-	info->fbops = &vt8623fb_ops;
-
-	/* Prepare PCI device */
-
-	rc = pci_enable_device(dev);
-	if (rc < 0) {
-		dev_err(info->device, "cannot enable PCI device\n");
-		goto err_enable_device;
-	}
-
-	rc = pci_request_regions(dev, "vt8623fb");
-	if (rc < 0) {
-		dev_err(info->device, "cannot reserve framebuffer region\n");
-		goto err_request_regions;
-	}
-
-	info->fix.smem_start = pci_resource_start(dev, 0);
-	info->fix.smem_len = pci_resource_len(dev, 0);
-	info->fix.mmio_start = pci_resource_start(dev, 1);
-	info->fix.mmio_len = pci_resource_len(dev, 1);
-
-	/* Map physical IO memory address into kernel space */
-	info->screen_base = pci_iomap(dev, 0, 0);
-	if (! info->screen_base) {
-		rc = -ENOMEM;
-		dev_err(info->device, "iomap for framebuffer failed\n");
-		goto err_iomap_1;
-	}
-
-	par->mmio_base = pci_iomap(dev, 1, 0);
-	if (! par->mmio_base) {
-		rc = -ENOMEM;
-		dev_err(info->device, "iomap for MMIO failed\n");
-		goto err_iomap_2;
-	}
-
-	bus_reg.start = 0;
-	bus_reg.end = 64 * 1024;
-
-	vga_res.flags = IORESOURCE_IO;
-
-	pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
-
-	par->state.vgabase = (void __iomem *) vga_res.start;
-
-	/* Find how many physical memory there is on card */
-	memsize1 = (vga_rseq(par->state.vgabase, 0x34) + 1) >> 1;
-	memsize2 = vga_rseq(par->state.vgabase, 0x39) << 2;
-
-	if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
-		info->screen_size = memsize1 << 20;
-	else {
-		dev_err(info->device, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
-		info->screen_size = 16 << 20;
-	}
-
-	info->fix.smem_len = info->screen_size;
-	strcpy(info->fix.id, "VIA VT8623");
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-	info->fix.ypanstep = 0;
-	info->fix.accel = FB_ACCEL_NONE;
-	info->pseudo_palette = (void*)par->pseudo_palette;
-
-	/* Prepare startup mode */
-
-	kparam_block_sysfs_write(mode_option);
-	rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
-	kparam_unblock_sysfs_write(mode_option);
-	if (! ((rc == 1) || (rc == 2))) {
-		rc = -EINVAL;
-		dev_err(info->device, "mode %s not found\n", mode_option);
-		goto err_find_mode;
-	}
-
-	rc = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (rc < 0) {
-		dev_err(info->device, "cannot allocate colormap\n");
-		goto err_alloc_cmap;
-	}
-
-	rc = register_framebuffer(info);
-	if (rc < 0) {
-		dev_err(info->device, "cannot register framebuffer\n");
-		goto err_reg_fb;
-	}
-
-	fb_info(info, "%s on %s, %d MB RAM\n",
-		info->fix.id, pci_name(dev), info->fix.smem_len >> 20);
-
-	/* Record a reference to the driver data */
-	pci_set_drvdata(dev, info);
-
-#ifdef CONFIG_MTRR
-	if (mtrr) {
-		par->mtrr_reg = -1;
-		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
-	}
-#endif
-
-	return 0;
-
-	/* Error handling */
-err_reg_fb:
-	fb_dealloc_cmap(&info->cmap);
-err_alloc_cmap:
-err_find_mode:
-	pci_iounmap(dev, par->mmio_base);
-err_iomap_2:
-	pci_iounmap(dev, info->screen_base);
-err_iomap_1:
-	pci_release_regions(dev);
-err_request_regions:
-/*	pci_disable_device(dev); */
-err_enable_device:
-	framebuffer_release(info);
-	return rc;
-}
-
-/* PCI remove */
-
-static void vt8623_pci_remove(struct pci_dev *dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-
-	if (info) {
-		struct vt8623fb_info *par = info->par;
-
-#ifdef CONFIG_MTRR
-		if (par->mtrr_reg >= 0) {
-			mtrr_del(par->mtrr_reg, 0, 0);
-			par->mtrr_reg = -1;
-		}
-#endif
-
-		unregister_framebuffer(info);
-		fb_dealloc_cmap(&info->cmap);
-
-		pci_iounmap(dev, info->screen_base);
-		pci_iounmap(dev, par->mmio_base);
-		pci_release_regions(dev);
-/*		pci_disable_device(dev); */
-
-		framebuffer_release(info);
-	}
-}
-
-
-#ifdef CONFIG_PM
-/* PCI suspend */
-
-static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct vt8623fb_info *par = info->par;
-
-	dev_info(info->device, "suspend\n");
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
-		mutex_unlock(&(par->open_lock));
-		console_unlock();
-		return 0;
-	}
-
-	fb_set_suspend(info, 1);
-
-	pci_save_state(dev);
-	pci_disable_device(dev);
-	pci_set_power_state(dev, pci_choose_state(dev, state));
-
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-
-	return 0;
-}
-
-
-/* PCI resume */
-
-static int vt8623_pci_resume(struct pci_dev* dev)
-{
-	struct fb_info *info = pci_get_drvdata(dev);
-	struct vt8623fb_info *par = info->par;
-
-	dev_info(info->device, "resume\n");
-
-	console_lock();
-	mutex_lock(&(par->open_lock));
-
-	if (par->ref_count == 0)
-		goto fail;
-
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
-
-	if (pci_enable_device(dev))
-		goto fail;
-
-	pci_set_master(dev);
-
-	vt8623fb_set_par(info);
-	fb_set_suspend(info, 0);
-
-fail:
-	mutex_unlock(&(par->open_lock));
-	console_unlock();
-
-	return 0;
-}
-#else
-#define vt8623_pci_suspend NULL
-#define vt8623_pci_resume NULL
-#endif /* CONFIG_PM */
-
-/* List of boards that we are trying to support */
-
-static struct pci_device_id vt8623_devices[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)},
-	{0, 0, 0, 0, 0, 0, 0}
-};
-
-MODULE_DEVICE_TABLE(pci, vt8623_devices);
-
-static struct pci_driver vt8623fb_pci_driver = {
-	.name		= "vt8623fb",
-	.id_table	= vt8623_devices,
-	.probe		= vt8623_pci_probe,
-	.remove		= vt8623_pci_remove,
-	.suspend	= vt8623_pci_suspend,
-	.resume		= vt8623_pci_resume,
-};
-
-/* Cleanup */
-
-static void __exit vt8623fb_cleanup(void)
-{
-	pr_debug("vt8623fb: cleaning up\n");
-	pci_unregister_driver(&vt8623fb_pci_driver);
-}
-
-/* Driver Initialisation */
-
-static int __init vt8623fb_init(void)
-{
-
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("vt8623fb", &option))
-		return -ENODEV;
-
-	if (option && *option)
-		mode_option = option;
-#endif
-
-	pr_debug("vt8623fb: initializing\n");
-	return pci_register_driver(&vt8623fb_pci_driver);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* Modularization */
-
-module_init(vt8623fb_init);
-module_exit(vt8623fb_cleanup);
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
deleted file mode 100644
index 10951c82f6ed..000000000000
--- a/drivers/video/w100fb.c
+++ /dev/null
@@ -1,1637 +0,0 @@
-/*
- * linux/drivers/video/w100fb.c
- *
- * Frame Buffer Device for ATI Imageon w100 (Wallaby)
- *
- * Copyright (C) 2002, ATI Corp.
- * Copyright (C) 2004-2006 Richard Purdie
- * Copyright (c) 2005 Ian Molton
- * Copyright (c) 2006 Alberto Mardegan
- *
- * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
- *
- * Generic platform support by Ian Molton <spyro@f2s.com>
- * and Richard Purdie <rpurdie@rpsys.net>
- *
- * w32xx support by Ian Molton
- *
- * Hardware acceleration support by Alberto Mardegan
- * <mardy@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <video/w100fb.h>
-#include "w100fb.h"
-
-/*
- * Prototypes
- */
-static void w100_suspend(u32 mode);
-static void w100_vsync(void);
-static void w100_hw_init(struct w100fb_par*);
-static void w100_pwm_setup(struct w100fb_par*);
-static void w100_init_clocks(struct w100fb_par*);
-static void w100_setup_memory(struct w100fb_par*);
-static void w100_init_lcd(struct w100fb_par*);
-static void w100_set_dispregs(struct w100fb_par*);
-static void w100_update_enable(void);
-static void w100_update_disable(void);
-static void calc_hsync(struct w100fb_par *par);
-static void w100_init_graphic_engine(struct w100fb_par *par);
-struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
-
-/* Pseudo palette size */
-#define MAX_PALETTES      16
-
-#define W100_SUSPEND_EXTMEM 0
-#define W100_SUSPEND_ALL    1
-
-#define BITS_PER_PIXEL    16
-
-/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
-static void *remapped_base;
-static void *remapped_regs;
-static void *remapped_fbuf;
-
-#define REMAPPED_FB_LEN   0x15ffff
-
-/* This is the offset in the w100's address space we map the current
-   framebuffer memory to. We use the position of external memory as
-   we can remap internal memory to there if external isn't present. */
-#define W100_FB_BASE MEM_EXT_BASE_VALUE
-
-
-/*
- * Sysfs functions
- */
-static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct w100fb_par *par=info->par;
-
-	return sprintf(buf, "%d\n",par->flip);
-}
-
-static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	unsigned int flip;
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct w100fb_par *par=info->par;
-
-	flip = simple_strtoul(buf, NULL, 10);
-
-	if (flip > 0)
-		par->flip = 1;
-	else
-		par->flip = 0;
-
-	w100_update_disable();
-	w100_set_dispregs(par);
-	w100_update_enable();
-
-	calc_hsync(par);
-
-	return count;
-}
-
-static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
-
-static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	unsigned long regs, param;
-	regs = simple_strtoul(buf, NULL, 16);
-	param = readl(remapped_regs + regs);
-	printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
-	return count;
-}
-
-static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
-
-static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	unsigned long regs, param;
-	sscanf(buf, "%lx %lx", &regs, &param);
-
-	if (regs <= 0x2000) {
-		printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
-		writel(param, remapped_regs + regs);
-	}
-
-	return count;
-}
-
-static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
-
-
-static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct w100fb_par *par=info->par;
-
-	return sprintf(buf, "%d\n",par->fastpll_mode);
-}
-
-static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct w100fb_par *par=info->par;
-
-	if (simple_strtoul(buf, NULL, 10) > 0) {
-		par->fastpll_mode=1;
-		printk("w100fb: Using fast system clock (if possible)\n");
-	} else {
-		par->fastpll_mode=0;
-		printk("w100fb: Using normal system clock\n");
-	}
-
-	w100_init_clocks(par);
-	calc_hsync(par);
-
-	return count;
-}
-
-static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
-
-/*
- * Some touchscreens need hsync information from the video driver to
- * function correctly. We export it here.
- */
-unsigned long w100fb_get_hsynclen(struct device *dev)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct w100fb_par *par=info->par;
-
-	/* If display is blanked/suspended, hsync isn't active */
-	if (par->blanked)
-		return 0;
-	else
-		return par->hsync_len;
-}
-EXPORT_SYMBOL(w100fb_get_hsynclen);
-
-static void w100fb_clear_screen(struct w100fb_par *par)
-{
-	memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
-}
-
-
-/*
- * Set a palette value from rgb components
- */
-static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int trans, struct fb_info *info)
-{
-	unsigned int val;
-	int ret = 1;
-
-	/*
-	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no matter what visual we are using.
-	 */
-	if (info->var.grayscale)
-		red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
-
-	/*
-	 * 16-bit True Colour.  We encode the RGB value
-	 * according to the RGB bitfield information.
-	 */
-	if (regno < MAX_PALETTES) {
-		u32 *pal = info->pseudo_palette;
-
-		val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
-		pal[regno] = val;
-		ret = 0;
-	}
-	return ret;
-}
-
-
-/*
- * Blank the display based on value in blank_mode
- */
-static int w100fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct w100fb_par *par = info->par;
-	struct w100_tg_info *tg = par->mach->tg;
-
-	switch(blank_mode) {
-
- 	case FB_BLANK_NORMAL:         /* Normal blanking */
-	case FB_BLANK_VSYNC_SUSPEND:  /* VESA blank (vsync off) */
-	case FB_BLANK_HSYNC_SUSPEND:  /* VESA blank (hsync off) */
- 	case FB_BLANK_POWERDOWN:      /* Poweroff */
-  		if (par->blanked == 0) {
-			if(tg && tg->suspend)
-				tg->suspend(par);
-			par->blanked = 1;
-  		}
-  		break;
-
- 	case FB_BLANK_UNBLANK: /* Unblanking */
-  		if (par->blanked != 0) {
-			if(tg && tg->resume)
-				tg->resume(par);
-			par->blanked = 0;
-  		}
-  		break;
- 	}
-	return 0;
-}
-
-
-static void w100_fifo_wait(int entries)
-{
-	union rbbm_status_u status;
-	int i;
-
-	for (i = 0; i < 2000000; i++) {
-		status.val = readl(remapped_regs + mmRBBM_STATUS);
-		if (status.f.cmdfifo_avail >= entries)
-			return;
-		udelay(1);
-	}
-	printk(KERN_ERR "w100fb: FIFO Timeout!\n");
-}
-
-
-static int w100fb_sync(struct fb_info *info)
-{
-	union rbbm_status_u status;
-	int i;
-
-	for (i = 0; i < 2000000; i++) {
-		status.val = readl(remapped_regs + mmRBBM_STATUS);
-		if (!status.f.gui_active)
-			return 0;
-		udelay(1);
-	}
-	printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
-	return -EBUSY;
-}
-
-
-static void w100_init_graphic_engine(struct w100fb_par *par)
-{
-	union dp_gui_master_cntl_u gmc;
-	union dp_mix_u dp_mix;
-	union dp_datatype_u dp_datatype;
-	union dp_cntl_u dp_cntl;
-
-	w100_fifo_wait(4);
-	writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
-	writel(par->xres, remapped_regs + mmDST_PITCH);
-	writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
-	writel(par->xres, remapped_regs + mmSRC_PITCH);
-
-	w100_fifo_wait(3);
-	writel(0, remapped_regs + mmSC_TOP_LEFT);
-	writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
-	writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
-
-	w100_fifo_wait(4);
-	dp_cntl.val = 0;
-	dp_cntl.f.dst_x_dir = 1;
-	dp_cntl.f.dst_y_dir = 1;
-	dp_cntl.f.src_x_dir = 1;
-	dp_cntl.f.src_y_dir = 1;
-	dp_cntl.f.dst_major_x = 1;
-	dp_cntl.f.src_major_x = 1;
-	writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
-
-	gmc.val = 0;
-	gmc.f.gmc_src_pitch_offset_cntl = 1;
-	gmc.f.gmc_dst_pitch_offset_cntl = 1;
-	gmc.f.gmc_src_clipping = 1;
-	gmc.f.gmc_dst_clipping = 1;
-	gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
-	gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
-	gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
-	gmc.f.gmc_byte_pix_order = 1;
-	gmc.f.gmc_default_sel = 0;
-	gmc.f.gmc_rop3 = ROP3_SRCCOPY;
-	gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
-	gmc.f.gmc_clr_cmp_fcn_dis = 1;
-	gmc.f.gmc_wr_msk_dis = 1;
-	gmc.f.gmc_dp_op = DP_OP_ROP;
-	writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
-
-	dp_datatype.val = dp_mix.val = 0;
-	dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
-	dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
-	dp_datatype.f.dp_src2_type = 0;
-	dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
-	dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
-	dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
-	writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
-
-	dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
-	dp_mix.f.dp_src2_source = 1;
-	dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
-	dp_mix.f.dp_op = gmc.f.gmc_dp_op;
-	writel(dp_mix.val, remapped_regs + mmDP_MIX);
-}
-
-
-static void w100fb_fillrect(struct fb_info *info,
-                            const struct fb_fillrect *rect)
-{
-	union dp_gui_master_cntl_u gmc;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_fillrect(info, rect);
-		return;
-	}
-
-	gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
-	gmc.f.gmc_rop3 = ROP3_PATCOPY;
-	gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
-	w100_fifo_wait(2);
-	writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
-	writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
-
-	w100_fifo_wait(2);
-	writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
-	writel((rect->width << 16) | (rect->height & 0xffff),
-	       remapped_regs + mmDST_WIDTH_HEIGHT);
-}
-
-
-static void w100fb_copyarea(struct fb_info *info,
-                            const struct fb_copyarea *area)
-{
-	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
-	u32 h = area->height, w = area->width;
-	union dp_gui_master_cntl_u gmc;
-
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-	if (info->flags & FBINFO_HWACCEL_DISABLED) {
-		cfb_copyarea(info, area);
-		return;
-	}
-
-	gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
-	gmc.f.gmc_rop3 = ROP3_SRCCOPY;
-	gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
-	w100_fifo_wait(1);
-	writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
-
-	w100_fifo_wait(3);
-	writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
-	writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
-	writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
-}
-
-
-/*
- *  Change the resolution by calling the appropriate hardware functions
- */
-static void w100fb_activate_var(struct w100fb_par *par)
-{
-	struct w100_tg_info *tg = par->mach->tg;
-
-	w100_pwm_setup(par);
-	w100_setup_memory(par);
-	w100_init_clocks(par);
-	w100fb_clear_screen(par);
-	w100_vsync();
-
-	w100_update_disable();
-	w100_init_lcd(par);
-	w100_set_dispregs(par);
-	w100_update_enable();
-	w100_init_graphic_engine(par);
-
-	calc_hsync(par);
-
-	if (!par->blanked && tg && tg->change)
-		tg->change(par);
-}
-
-
-/* Select the smallest mode that allows the desired resolution to be
- * displayed. If desired, the x and y parameters can be rounded up to
- * match the selected mode.
- */
-static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
-{
-	struct w100_mode *mode = NULL;
-	struct w100_mode *modelist = par->mach->modelist;
-	unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
-	unsigned int i;
-
-	for (i = 0 ; i < par->mach->num_modes ; i++) {
-		if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
-				modelist[i].xres < best_x && modelist[i].yres < best_y) {
-			best_x = modelist[i].xres;
-			best_y = modelist[i].yres;
-			mode = &modelist[i];
-		} else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
-		        modelist[i].xres < best_y && modelist[i].yres < best_x) {
-			best_x = modelist[i].yres;
-			best_y = modelist[i].xres;
-			mode = &modelist[i];
-		}
-	}
-
-	if (mode && saveval) {
-		*x = best_x;
-		*y = best_y;
-	}
-
-	return mode;
-}
-
-
-/*
- *  w100fb_check_var():
- *  Get the video params out of 'var'. If a value doesn't fit, round it up,
- *  if it's too big, return -EINVAL.
- */
-static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct w100fb_par *par=info->par;
-
-	if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
-		return -EINVAL;
-
-	if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
-		return -EINVAL;
-
-	if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
-		return -EINVAL;
-
-	var->xres_virtual = max(var->xres_virtual, var->xres);
-	var->yres_virtual = max(var->yres_virtual, var->yres);
-
-	if (var->bits_per_pixel > BITS_PER_PIXEL)
-		return -EINVAL;
-	else
-		var->bits_per_pixel = BITS_PER_PIXEL;
-
-	var->red.offset = 11;
-	var->red.length = 5;
-	var->green.offset = 5;
-	var->green.length = 6;
-	var->blue.offset = 0;
-	var->blue.length = 5;
-	var->transp.offset = var->transp.length = 0;
-
-	var->nonstd = 0;
-	var->height = -1;
-	var->width = -1;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	var->sync = 0;
-	var->pixclock = 0x04;  /* 171521; */
-
-	return 0;
-}
-
-
-/*
- * w100fb_set_par():
- *	Set the user defined part of the display for the specified console
- *  by looking at the values in info.var
- */
-static int w100fb_set_par(struct fb_info *info)
-{
-	struct w100fb_par *par=info->par;
-
-	if (par->xres != info->var.xres || par->yres != info->var.yres)	{
-		par->xres = info->var.xres;
-		par->yres = info->var.yres;
-		par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
-
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		info->fix.ypanstep = 0;
-		info->fix.ywrapstep = 0;
-		info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
-
-		mutex_lock(&info->mm_lock);
-		if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
-			par->extmem_active = 1;
-			info->fix.smem_len = par->mach->mem->size+1;
-		} else {
-			par->extmem_active = 0;
-			info->fix.smem_len = MEM_INT_SIZE+1;
-		}
-		mutex_unlock(&info->mm_lock);
-
-		w100fb_activate_var(par);
-	}
-	return 0;
-}
-
-
-/*
- *  Frame buffer operations
- */
-static struct fb_ops w100fb_ops = {
-	.owner        = THIS_MODULE,
-	.fb_check_var = w100fb_check_var,
-	.fb_set_par   = w100fb_set_par,
-	.fb_setcolreg = w100fb_setcolreg,
-	.fb_blank     = w100fb_blank,
-	.fb_fillrect  = w100fb_fillrect,
-	.fb_copyarea  = w100fb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_sync      = w100fb_sync,
-};
-
-#ifdef CONFIG_PM
-static void w100fb_save_vidmem(struct w100fb_par *par)
-{
-	int memsize;
-
-	if (par->extmem_active) {
-		memsize=par->mach->mem->size;
-		par->saved_extmem = vmalloc(memsize);
-		if (par->saved_extmem)
-			memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
-	}
-	memsize=MEM_INT_SIZE;
-	par->saved_intmem = vmalloc(memsize);
-	if (par->saved_intmem && par->extmem_active)
-		memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
-	else if (par->saved_intmem)
-		memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
-}
-
-static void w100fb_restore_vidmem(struct w100fb_par *par)
-{
-	int memsize;
-
-	if (par->extmem_active && par->saved_extmem) {
-		memsize=par->mach->mem->size;
-		memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
-		vfree(par->saved_extmem);
-	}
-	if (par->saved_intmem) {
-		memsize=MEM_INT_SIZE;
-		if (par->extmem_active)
-			memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
-		else
-			memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
-		vfree(par->saved_intmem);
-	}
-}
-
-static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct w100fb_par *par=info->par;
-	struct w100_tg_info *tg = par->mach->tg;
-
-	w100fb_save_vidmem(par);
-	if(tg && tg->suspend)
-		tg->suspend(par);
-	w100_suspend(W100_SUSPEND_ALL);
-	par->blanked = 1;
-
-	return 0;
-}
-
-static int w100fb_resume(struct platform_device *dev)
-{
-	struct fb_info *info = platform_get_drvdata(dev);
-	struct w100fb_par *par=info->par;
-	struct w100_tg_info *tg = par->mach->tg;
-
-	w100_hw_init(par);
-	w100fb_activate_var(par);
-	w100fb_restore_vidmem(par);
-	if(tg && tg->resume)
-		tg->resume(par);
-	par->blanked = 0;
-
-	return 0;
-}
-#else
-#define w100fb_suspend  NULL
-#define w100fb_resume   NULL
-#endif
-
-
-int w100fb_probe(struct platform_device *pdev)
-{
-	int err = -EIO;
-	struct w100fb_mach_info *inf;
-	struct fb_info *info = NULL;
-	struct w100fb_par *par;
-	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	unsigned int chip_id;
-
-	if (!mem)
-		return -EINVAL;
-
-	/* Remap the chip base address */
-	remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
-	if (remapped_base == NULL)
-		goto out;
-
-	/* Map the register space */
-	remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
-	if (remapped_regs == NULL)
-		goto out;
-
-	/* Identify the chip */
-	printk("Found ");
-	chip_id = readl(remapped_regs + mmCHIP_ID);
-	switch(chip_id) {
-		case CHIP_ID_W100:  printk("w100");  break;
-		case CHIP_ID_W3200: printk("w3200"); break;
-		case CHIP_ID_W3220: printk("w3220"); break;
-		default:
-			printk("Unknown imageon chip ID\n");
-			err = -ENODEV;
-			goto out;
-	}
-	printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
-
-	/* Remap the framebuffer */
-	remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
-	if (remapped_fbuf == NULL)
-		goto out;
-
-	info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
-	if (!info) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	par = info->par;
-	platform_set_drvdata(pdev, info);
-
-	inf = dev_get_platdata(&pdev->dev);
-	par->chip_id = chip_id;
-	par->mach = inf;
-	par->fastpll_mode = 0;
-	par->blanked = 0;
-
-	par->pll_table=w100_get_xtal_table(inf->xtal_freq);
-	if (!par->pll_table) {
-		printk(KERN_ERR "No matching Xtal definition found\n");
-		err = -EINVAL;
-		goto out;
-	}
-
-	info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
-	if (!info->pseudo_palette) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	info->fbops = &w100fb_ops;
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
-		FBINFO_HWACCEL_FILLRECT;
-	info->node = -1;
-	info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
-	info->screen_size = REMAPPED_FB_LEN;
-
-	strcpy(info->fix.id, "w100fb");
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux = 0;
-	info->fix.accel = FB_ACCEL_NONE;
-	info->fix.smem_start = mem->start+W100_FB_BASE;
-	info->fix.mmio_start = mem->start+W100_REG_BASE;
-	info->fix.mmio_len = W100_REG_LEN;
-
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	par->mode = &inf->modelist[0];
-	if(inf->init_mode & INIT_MODE_ROTATED) {
-		info->var.xres = par->mode->yres;
-		info->var.yres = par->mode->xres;
-	}
-	else {
-		info->var.xres = par->mode->xres;
-		info->var.yres = par->mode->yres;
-	}
-
-	if(inf->init_mode &= INIT_MODE_FLIPPED)
-		par->flip = 1;
-	else
-		par->flip = 0;
-
-	info->var.xres_virtual = info->var.xres;
-	info->var.yres_virtual = info->var.yres;
-	info->var.pixclock = 0x04;  /* 171521; */
-	info->var.sync = 0;
-	info->var.grayscale = 0;
-	info->var.xoffset = info->var.yoffset = 0;
-	info->var.accel_flags = 0;
-	info->var.activate = FB_ACTIVATE_NOW;
-
-	w100_hw_init(par);
-
-	if (w100fb_check_var(&info->var, info) < 0) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	if (register_framebuffer(info) < 0) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
-	err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
-	err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
-	err |= device_create_file(&pdev->dev, &dev_attr_flip);
-
-	if (err != 0)
-		fb_warn(info, "failed to register attributes (%d)\n", err);
-
-	fb_info(info, "%s frame buffer device\n", info->fix.id);
-	return 0;
-out:
-	if (info) {
-		fb_dealloc_cmap(&info->cmap);
-		kfree(info->pseudo_palette);
-	}
-	if (remapped_fbuf != NULL)
-		iounmap(remapped_fbuf);
-	if (remapped_regs != NULL)
-		iounmap(remapped_regs);
-	if (remapped_base != NULL)
-		iounmap(remapped_base);
-	if (info)
-		framebuffer_release(info);
-	return err;
-}
-
-
-static int w100fb_remove(struct platform_device *pdev)
-{
-	struct fb_info *info = platform_get_drvdata(pdev);
-	struct w100fb_par *par=info->par;
-
-	device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
-	device_remove_file(&pdev->dev, &dev_attr_reg_read);
-	device_remove_file(&pdev->dev, &dev_attr_reg_write);
-	device_remove_file(&pdev->dev, &dev_attr_flip);
-
-	unregister_framebuffer(info);
-
-	vfree(par->saved_intmem);
-	vfree(par->saved_extmem);
-	kfree(info->pseudo_palette);
-	fb_dealloc_cmap(&info->cmap);
-
-	iounmap(remapped_base);
-	iounmap(remapped_regs);
-	iounmap(remapped_fbuf);
-
-	framebuffer_release(info);
-
-	return 0;
-}
-
-
-/* ------------------- chipset specific functions -------------------------- */
-
-
-static void w100_soft_reset(void)
-{
-	u16 val = readw((u16 *) remapped_base + cfgSTATUS);
-	writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
-	udelay(100);
-	writew(0x00, (u16 *) remapped_base + cfgSTATUS);
-	udelay(100);
-}
-
-static void w100_update_disable(void)
-{
-	union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
-
-	/* Prevent display updates */
-	disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
-	disp_db_buf_wr_cntl.f.update_db_buf = 0;
-	disp_db_buf_wr_cntl.f.en_db_buf = 0;
-	writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
-}
-
-static void w100_update_enable(void)
-{
-	union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
-
-	/* Enable display updates */
-	disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
-	disp_db_buf_wr_cntl.f.update_db_buf = 1;
-	disp_db_buf_wr_cntl.f.en_db_buf = 1;
-	writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
-}
-
-unsigned long w100fb_gpio_read(int port)
-{
-	unsigned long value;
-
-	if (port==W100_GPIO_PORT_A)
-		value = readl(remapped_regs + mmGPIO_DATA);
-	else
-		value = readl(remapped_regs + mmGPIO_DATA2);
-
-	return value;
-}
-
-void w100fb_gpio_write(int port, unsigned long value)
-{
-	if (port==W100_GPIO_PORT_A)
-		writel(value, remapped_regs + mmGPIO_DATA);
-	else
-		writel(value, remapped_regs + mmGPIO_DATA2);
-}
-EXPORT_SYMBOL(w100fb_gpio_read);
-EXPORT_SYMBOL(w100fb_gpio_write);
-
-/*
- * Initialization of critical w100 hardware
- */
-static void w100_hw_init(struct w100fb_par *par)
-{
-	u32 temp32;
-	union cif_cntl_u cif_cntl;
-	union intf_cntl_u intf_cntl;
-	union cfgreg_base_u cfgreg_base;
-	union wrap_top_dir_u wrap_top_dir;
-	union cif_read_dbg_u cif_read_dbg;
-	union cpu_defaults_u cpu_default;
-	union cif_write_dbg_u cif_write_dbg;
-	union wrap_start_dir_u wrap_start_dir;
-	union cif_io_u cif_io;
-	struct w100_gpio_regs *gpio = par->mach->gpio;
-
-	w100_soft_reset();
-
-	/* This is what the fpga_init code does on reset. May be wrong
-	   but there is little info available */
-	writel(0x31, remapped_regs + mmSCRATCH_UMSK);
-	for (temp32 = 0; temp32 < 10000; temp32++)
-		readl(remapped_regs + mmSCRATCH_UMSK);
-	writel(0x30, remapped_regs + mmSCRATCH_UMSK);
-
-	/* Set up CIF */
-	cif_io.val = defCIF_IO;
-	writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
-
-	cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
-	cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
-	cif_write_dbg.f.en_dword_split_to_rbbm = 1;
-	cif_write_dbg.f.dis_timeout_during_rbbm = 1;
-	writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
-
-	cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
-	cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
-	writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
-
-	cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
-	cif_cntl.f.dis_system_bits = 1;
-	cif_cntl.f.dis_mr = 1;
-	cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
-	cif_cntl.f.intb_oe = 1;
-	cif_cntl.f.interrupt_active_high = 1;
-	writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
-
-	/* Setup cfgINTF_CNTL and cfgCPU defaults */
-	intf_cntl.val = defINTF_CNTL;
-	intf_cntl.f.ad_inc_a = 1;
-	intf_cntl.f.ad_inc_b = 1;
-	intf_cntl.f.rd_data_rdy_a = 0;
-	intf_cntl.f.rd_data_rdy_b = 0;
-	writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
-
-	cpu_default.val = defCPU_DEFAULTS;
-	cpu_default.f.access_ind_addr_a = 1;
-	cpu_default.f.access_ind_addr_b = 1;
-	cpu_default.f.access_scratch_reg = 1;
-	cpu_default.f.transition_size = 0;
-	writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
-
-	/* set up the apertures */
-	writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
-
-	cfgreg_base.val = defCFGREG_BASE;
-	cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
-	writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
-
-	wrap_start_dir.val = defWRAP_START_DIR;
-	wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
-	writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
-
-	wrap_top_dir.val = defWRAP_TOP_DIR;
-	wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
-	writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
-
-	writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
-
-	/* Set the hardware to 565 colour */
-	temp32 = readl(remapped_regs + mmDISP_DEBUG2);
-	temp32 &= 0xff7fffff;
-	temp32 |= 0x00800000;
-	writel(temp32, remapped_regs + mmDISP_DEBUG2);
-
-	/* Initialise the GPIO lines */
-	if (gpio) {
-		writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
-		writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
-		writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
-		writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
-		writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
-		writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
-	}
-}
-
-
-struct power_state {
-	union clk_pin_cntl_u clk_pin_cntl;
-	union pll_ref_fb_div_u pll_ref_fb_div;
-	union pll_cntl_u pll_cntl;
-	union sclk_cntl_u sclk_cntl;
-	union pclk_cntl_u pclk_cntl;
-	union pwrmgt_cntl_u pwrmgt_cntl;
-	int auto_mode;  /* system clock auto changing? */
-};
-
-
-static struct power_state w100_pwr_state;
-
-/* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
-
-/* 12.5MHz Crystal PLL Table */
-static struct w100_pll_info xtal_12500000[] = {
-	/*freq     M   N_int    N_fac  tfgoal  lock_time */
-	{ 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
-	{ 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
-	{100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
-	{125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
-	{150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
-	{  0,      0,   0,       0,        0,         0},  /* Terminator */
-};
-
-/* 14.318MHz Crystal PLL Table */
-static struct w100_pll_info xtal_14318000[] = {
-	/*freq     M   N_int    N_fac  tfgoal  lock_time */
-	{ 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
-	{ 50,      1,   6,       0,     0xe0,	     64}, /*  50.05 MHz */
-	{ 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
-	{ 75,      0,   4,       3,     0xe0,	     43}, /*  75.08 MHz */
-	{100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
-	{  0,      0,   0,       0,        0,         0},
-};
-
-/* 16MHz Crystal PLL Table */
-static struct w100_pll_info xtal_16000000[] = {
-	/*freq     M   N_int    N_fac  tfgoal  lock_time */
-	{ 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
-	{ 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
-	{ 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
-	{ 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
-	{  0,      0,   0,       0,        0,         0},
-};
-
-static struct pll_entries {
-	int xtal_freq;
-	struct w100_pll_info *pll_table;
-} w100_pll_tables[] = {
-	{ 12500000, &xtal_12500000[0] },
-	{ 14318000, &xtal_14318000[0] },
-	{ 16000000, &xtal_16000000[0] },
-	{ 0 },
-};
-
-struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
-{
-	struct pll_entries *pll_entry = w100_pll_tables;
-
-	do {
-		if (freq == pll_entry->xtal_freq)
-			return pll_entry->pll_table;
-		pll_entry++;
-	} while (pll_entry->xtal_freq);
-	return 0;
-}
-
-
-static unsigned int w100_get_testcount(unsigned int testclk_sel)
-{
-	union clk_test_cntl_u clk_test_cntl;
-
-	udelay(5);
-
-	/* Select the test clock source and reset */
-	clk_test_cntl.f.start_check_freq = 0x0;
-	clk_test_cntl.f.testclk_sel = testclk_sel;
-	clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
-	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-
-	clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
-	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-
-	/* Run clock test */
-	clk_test_cntl.f.start_check_freq = 0x1;
-	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-
-	/* Give the test time to complete */
-	udelay(20);
-
-	/* Return the result */
-	clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
-	clk_test_cntl.f.start_check_freq = 0x0;
-	writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
-
-	return clk_test_cntl.f.test_count;
-}
-
-
-static int w100_pll_adjust(struct w100_pll_info *pll)
-{
-	unsigned int tf80;
-	unsigned int tf20;
-
-	/* Initial Settings */
-	w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
-	w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
-	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
-	w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
-	w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
-	w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
-	w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
-
-	/* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
-	 * therefore, commented out the following lines
-	 * tf80 meant tf100
-	 */
-	do {
-		/* set VCO input = 0.8 * VDD */
-		w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
-		writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-
-		tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
-		if (tf80 >= (pll->tfgoal)) {
-			/* set VCO input = 0.2 * VDD */
-			w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
-			writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-
-			tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
-			if (tf20 <= (pll->tfgoal))
-				return 1;  /* Success */
-
-			if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
-				((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
-				(w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
-				/* slow VCO config */
-				w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
-				w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
-				w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
-				continue;
-			}
-		}
-		if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
-			w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
-		} else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
-			w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
-			w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
-		} else {
-			return 0;  /* Error */
-		}
-	} while(1);
-}
-
-
-/*
- * w100_pll_calibration
- */
-static int w100_pll_calibration(struct w100_pll_info *pll)
-{
-	int status;
-
-	status = w100_pll_adjust(pll);
-
-	/* PLL Reset And Lock */
-	/* set VCO input = 0.5 * VDD */
-	w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
-	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-
-	udelay(1);  /* reset time */
-
-	/* enable charge pump */
-	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
-	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-
-	/* set VCO input = Hi-Z, disable DAC */
-	w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
-	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-
-	udelay(400);  /* lock time */
-
-	/* PLL locked */
-
-	return status;
-}
-
-
-static int w100_pll_set_clk(struct w100_pll_info *pll)
-{
-	int status;
-
-	if (w100_pwr_state.auto_mode == 1)  /* auto mode */
-	{
-		w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
-		w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
-		writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
-	}
-
-	/* Set system clock source to XTAL whilst adjusting the PLL! */
-	w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
-	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
-	w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
-	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
-	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
-	w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
-	writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
-
-	w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
-	writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
-
-	status = w100_pll_calibration(pll);
-
-	if (w100_pwr_state.auto_mode == 1)  /* auto mode */
-	{
-		w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
-		w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
-		writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
-	}
-	return status;
-}
-
-/* freq = target frequency of the PLL */
-static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
-{
-	struct w100_pll_info *pll = par->pll_table;
-
-	do {
-		if (freq == pll->freq) {
-			return w100_pll_set_clk(pll);
-		}
-		pll++;
-	} while(pll->freq);
-	return 0;
-}
-
-/* Set up an initial state.  Some values/fields set
-   here will be overwritten. */
-static void w100_pwm_setup(struct w100fb_par *par)
-{
-	w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
-	w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
-	w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
-	w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
-	w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
-	w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
-	writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
-
-	w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
-	w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
-	w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
-	w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
-	w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
-	w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
-	w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
-	w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
-	w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
-	w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
-	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-
-	w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
-	w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
-	w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
-	writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
-
-	w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
-	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
-	w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
-	w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
-	w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
-	writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
-
-	w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
-	w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
-	w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
-	w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
-	w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
-	w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
-	w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
-	w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
-	w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
-	w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
-	writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
-
-	w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
-	w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
-	w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
-	w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
-	w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
-	w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
-	w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
-	w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
-	w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
-	writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
-
-	w100_pwr_state.auto_mode = 0;  /* manual mode */
-}
-
-
-/*
- * Setup the w100 clocks for the specified mode
- */
-static void w100_init_clocks(struct w100fb_par *par)
-{
-	struct w100_mode *mode = par->mode;
-
-	if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
-		w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
-
-	w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
-	w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
-	w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
-	writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
-}
-
-static void w100_init_lcd(struct w100fb_par *par)
-{
-	u32 temp32;
-	struct w100_mode *mode = par->mode;
-	struct w100_gen_regs *regs = par->mach->regs;
-	union active_h_disp_u active_h_disp;
-	union active_v_disp_u active_v_disp;
-	union graphic_h_disp_u graphic_h_disp;
-	union graphic_v_disp_u graphic_v_disp;
-	union crtc_total_u crtc_total;
-
-	/* w3200 doesn't like undefined bits being set so zero register values first */
-
-	active_h_disp.val = 0;
-	active_h_disp.f.active_h_start=mode->left_margin;
-	active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
-	writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
-
-	active_v_disp.val = 0;
-	active_v_disp.f.active_v_start=mode->upper_margin;
-	active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
-	writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
-
-	graphic_h_disp.val = 0;
-	graphic_h_disp.f.graphic_h_start=mode->left_margin;
-	graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
-	writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
-
-	graphic_v_disp.val = 0;
-	graphic_v_disp.f.graphic_v_start=mode->upper_margin;
-	graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
-	writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
-
-	crtc_total.val = 0;
-	crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
-	crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
-	writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
-
-	writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
-	writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
-	writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
-	writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
-	writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
-	writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
-	writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
-	writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
-	writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
-
-	writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
-	writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
-	writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
-	writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
-	writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
-	writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
-
-	writel(0x00000000, remapped_regs + mmCRTC_FRAME);
-	writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
-	writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
-	writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
-
-	/* Hack for overlay in ext memory */
-	temp32 = readl(remapped_regs + mmDISP_DEBUG2);
-	temp32 |= 0xc0000000;
-	writel(temp32, remapped_regs + mmDISP_DEBUG2);
-}
-
-
-static void w100_setup_memory(struct w100fb_par *par)
-{
-	union mc_ext_mem_location_u extmem_location;
-	union mc_fb_location_u intmem_location;
-	struct w100_mem_info *mem = par->mach->mem;
-	struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
-
-	if (!par->extmem_active) {
-		w100_suspend(W100_SUSPEND_EXTMEM);
-
-		/* Map Internal Memory at FB Base */
-		intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
-		intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
-		writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
-
-		/* Unmap External Memory - value is *probably* irrelevant but may have meaning
-		   to acceleration libraries */
-		extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
-		extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
-		writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
-	} else {
-		/* Map Internal Memory to its default location */
-		intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
-		intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
-		writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
-
-		/* Map External Memory at FB Base */
-		extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
-		extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
-		writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
-
-		writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
-		writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
-		writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
-		udelay(100);
-		writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
-		udelay(100);
-		writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
-		udelay(100);
-		writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
-		writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
-		if (bm_mem) {
-			writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
-			writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
-			writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
-			writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
-			writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
-			writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
-			writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
-		}
-	}
-}
-
-static void w100_set_dispregs(struct w100fb_par *par)
-{
-	unsigned long rot=0, divider, offset=0;
-	union graphic_ctrl_u graphic_ctrl;
-
-	/* See if the mode has been rotated */
-	if (par->xres == par->mode->xres) {
-		if (par->flip) {
-			rot=3; /* 180 degree */
-			offset=(par->xres * par->yres) - 1;
-		} /* else 0 degree */
-		divider = par->mode->pixclk_divider;
-	} else {
-		if (par->flip) {
-			rot=2; /* 270 degree */
-			offset=par->xres - 1;
-		} else {
-			rot=1; /* 90 degree */
-			offset=par->xres * (par->yres - 1);
-		}
-		divider = par->mode->pixclk_divider_rotated;
-	}
-
-	graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
-	switch (par->chip_id) {
-		case CHIP_ID_W100:
-			graphic_ctrl.f_w100.color_depth=6;
-			graphic_ctrl.f_w100.en_crtc=1;
-			graphic_ctrl.f_w100.en_graphic_req=1;
-			graphic_ctrl.f_w100.en_graphic_crtc=1;
-			graphic_ctrl.f_w100.lcd_pclk_on=1;
-			graphic_ctrl.f_w100.lcd_sclk_on=1;
-			graphic_ctrl.f_w100.low_power_on=0;
-			graphic_ctrl.f_w100.req_freq=0;
-			graphic_ctrl.f_w100.portrait_mode=rot;
-
-			/* Zaurus needs this */
-			switch(par->xres) {
-				case 240:
-				case 320:
-				default:
-					graphic_ctrl.f_w100.total_req_graphic=0xa0;
-					break;
-				case 480:
-				case 640:
-					switch(rot) {
-						case 0:  /* 0 */
-						case 3:  /* 180 */
-							graphic_ctrl.f_w100.low_power_on=1;
-							graphic_ctrl.f_w100.req_freq=5;
-						break;
-						case 1:  /* 90 */
-						case 2:  /* 270 */
-							graphic_ctrl.f_w100.req_freq=4;
-							break;
-						default:
-							break;
-					}
-					graphic_ctrl.f_w100.total_req_graphic=0xf0;
-					break;
-			}
-			break;
-		case CHIP_ID_W3200:
-		case CHIP_ID_W3220:
-			graphic_ctrl.f_w32xx.color_depth=6;
-			graphic_ctrl.f_w32xx.en_crtc=1;
-			graphic_ctrl.f_w32xx.en_graphic_req=1;
-			graphic_ctrl.f_w32xx.en_graphic_crtc=1;
-			graphic_ctrl.f_w32xx.lcd_pclk_on=1;
-			graphic_ctrl.f_w32xx.lcd_sclk_on=1;
-			graphic_ctrl.f_w32xx.low_power_on=0;
-			graphic_ctrl.f_w32xx.req_freq=0;
-			graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
-			graphic_ctrl.f_w32xx.portrait_mode=rot;
-			break;
-	}
-
-	/* Set the pixel clock source and divider */
-	w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
-	w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
-	writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
-
-	writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
-	writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
-	writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
-}
-
-
-/*
- * Work out how long the sync pulse lasts
- * Value is 1/(time in seconds)
- */
-static void calc_hsync(struct w100fb_par *par)
-{
-	unsigned long hsync;
-	struct w100_mode *mode = par->mode;
-	union crtc_ss_u crtc_ss;
-
-	if (mode->pixclk_src == CLK_SRC_XTAL)
-		hsync=par->mach->xtal_freq;
-	else
-		hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
-
-	hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
-
-	crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
-	if (crtc_ss.val)
-		par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
-	else
-		par->hsync_len = 0;
-}
-
-static void w100_suspend(u32 mode)
-{
-	u32 val;
-
-	writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
-	writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
-
-	val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
-	val &= ~(0x00100000);  /* bit20=0 */
-	val |= 0xFF000000;     /* bit31:24=0xff */
-	writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
-
-	val = readl(remapped_regs + mmMEM_EXT_CNTL);
-	val &= ~(0x00040000);  /* bit18=0 */
-	val |= 0x00080000;     /* bit19=1 */
-	writel(val, remapped_regs + mmMEM_EXT_CNTL);
-
-	udelay(1);  /* wait 1us */
-
-	if (mode == W100_SUSPEND_EXTMEM) {
-		/* CKE: Tri-State */
-		val = readl(remapped_regs + mmMEM_EXT_CNTL);
-		val |= 0x40000000;  /* bit30=1 */
-		writel(val, remapped_regs + mmMEM_EXT_CNTL);
-
-		/* CLK: Stop */
-		val = readl(remapped_regs + mmMEM_EXT_CNTL);
-		val &= ~(0x00000001);  /* bit0=0 */
-		writel(val, remapped_regs + mmMEM_EXT_CNTL);
-	} else {
-		writel(0x00000000, remapped_regs + mmSCLK_CNTL);
-		writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
-		writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
-
-		udelay(5);
-
-		val = readl(remapped_regs + mmPLL_CNTL);
-		val |= 0x00000004;  /* bit2=1 */
-		writel(val, remapped_regs + mmPLL_CNTL);
-
-		writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
-		writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
-		writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
-		writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
-		writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
-
-		val = readl(remapped_regs + mmMEM_EXT_CNTL);
-		val |= 0xF0000000;
-		val &= ~(0x00000001);
-		writel(val, remapped_regs + mmMEM_EXT_CNTL);
-
-		writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
-	}
-}
-
-static void w100_vsync(void)
-{
-	u32 tmp;
-	int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
-
-	tmp = readl(remapped_regs + mmACTIVE_V_DISP);
-
-	/* set vline pos  */
-	writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
-
-	/* disable vline irq */
-	tmp = readl(remapped_regs + mmGEN_INT_CNTL);
-
-	tmp &= ~0x00000002;
-	writel(tmp, remapped_regs + mmGEN_INT_CNTL);
-
-	/* clear vline irq status */
-	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
-
-	/* enable vline irq */
-	writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
-
-	/* clear vline irq status */
-	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
-
-	while(timeout > 0) {
-		if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
-			break;
-		udelay(1);
-		timeout--;
-	}
-
-	/* disable vline irq */
-	writel(tmp, remapped_regs + mmGEN_INT_CNTL);
-
-	/* clear vline irq status */
-	writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
-}
-
-static struct platform_driver w100fb_driver = {
-	.probe		= w100fb_probe,
-	.remove		= w100fb_remove,
-	.suspend	= w100fb_suspend,
-	.resume		= w100fb_resume,
-	.driver		= {
-		.name	= "w100fb",
-	},
-};
-
-module_platform_driver(w100fb_driver);
-
-MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/w100fb.h b/drivers/video/w100fb.h
deleted file mode 100644
index fffae7b4f6e9..000000000000
--- a/drivers/video/w100fb.h
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * linux/drivers/video/w100fb.h
- *
- * Frame Buffer Device for ATI w100 (Wallaby)
- *
- * Copyright (C) 2002, ATI Corp.
- * Copyright (C) 2004-2005 Richard Purdie
- * Copyright (c) 2005 Ian Molton <spyro@f2s.com>
- *
- * Modified to work with 2.6 by Richard Purdie <rpurdie@rpsys.net>
- *
- * w32xx support by Ian Molton
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#if !defined (_W100FB_H)
-#define _W100FB_H
-
-/* Block CIF Start: */
-#define mmCHIP_ID           0x0000
-#define mmREVISION_ID       0x0004
-#define mmWRAP_BUF_A        0x0008
-#define mmWRAP_BUF_B        0x000C
-#define mmWRAP_TOP_DIR      0x0010
-#define mmWRAP_START_DIR    0x0014
-#define mmCIF_CNTL          0x0018
-#define mmCFGREG_BASE       0x001C
-#define mmCIF_IO            0x0020
-#define mmCIF_READ_DBG      0x0024
-#define mmCIF_WRITE_DBG     0x0028
-#define cfgIND_ADDR_A_0     0x0000
-#define cfgIND_ADDR_A_1     0x0001
-#define cfgIND_ADDR_A_2     0x0002
-#define cfgIND_DATA_A       0x0003
-#define cfgREG_BASE         0x0004
-#define cfgINTF_CNTL        0x0005
-#define cfgSTATUS           0x0006
-#define cfgCPU_DEFAULTS     0x0007
-#define cfgIND_ADDR_B_0     0x0008
-#define cfgIND_ADDR_B_1     0x0009
-#define cfgIND_ADDR_B_2     0x000A
-#define cfgIND_DATA_B       0x000B
-#define cfgPM4_RPTR         0x000C
-#define cfgSCRATCH          0x000D
-#define cfgPM4_WRPTR_0      0x000E
-#define cfgPM4_WRPTR_1      0x000F
-/* Block CIF End: */
-
-/* Block CP Start: */
-#define mmSCRATCH_UMSK      0x0280
-#define mmSCRATCH_ADDR      0x0284
-#define mmGEN_INT_CNTL      0x0200
-#define mmGEN_INT_STATUS    0x0204
-/* Block CP End: */
-
-/* Block DISPLAY Start: */
-#define mmLCD_FORMAT        0x0410
-#define mmGRAPHIC_CTRL      0x0414
-#define mmGRAPHIC_OFFSET    0x0418
-#define mmGRAPHIC_PITCH     0x041C
-#define mmCRTC_TOTAL        0x0420
-#define mmACTIVE_H_DISP     0x0424
-#define mmACTIVE_V_DISP     0x0428
-#define mmGRAPHIC_H_DISP    0x042C
-#define mmGRAPHIC_V_DISP    0x0430
-#define mmVIDEO_CTRL        0x0434
-#define mmGRAPHIC_KEY       0x0438
-#define mmBRIGHTNESS_CNTL   0x045C
-#define mmDISP_INT_CNTL     0x0488
-#define mmCRTC_SS           0x048C
-#define mmCRTC_LS           0x0490
-#define mmCRTC_REV          0x0494
-#define mmCRTC_DCLK         0x049C
-#define mmCRTC_GS           0x04A0
-#define mmCRTC_VPOS_GS      0x04A4
-#define mmCRTC_GCLK         0x04A8
-#define mmCRTC_GOE          0x04AC
-#define mmCRTC_FRAME        0x04B0
-#define mmCRTC_FRAME_VPOS   0x04B4
-#define mmGPIO_DATA         0x04B8
-#define mmGPIO_CNTL1        0x04BC
-#define mmGPIO_CNTL2        0x04C0
-#define mmLCDD_CNTL1        0x04C4
-#define mmLCDD_CNTL2        0x04C8
-#define mmGENLCD_CNTL1      0x04CC
-#define mmGENLCD_CNTL2      0x04D0
-#define mmDISP_DEBUG        0x04D4
-#define mmDISP_DB_BUF_CNTL  0x04D8
-#define mmDISP_CRC_SIG      0x04DC
-#define mmCRTC_DEFAULT_COUNT    0x04E0
-#define mmLCD_BACKGROUND_COLOR  0x04E4
-#define mmCRTC_PS2          0x04E8
-#define mmCRTC_PS2_VPOS     0x04EC
-#define mmCRTC_PS1_ACTIVE   0x04F0
-#define mmCRTC_PS1_NACTIVE  0x04F4
-#define mmCRTC_GCLK_EXT     0x04F8
-#define mmCRTC_ALW          0x04FC
-#define mmCRTC_ALW_VPOS     0x0500
-#define mmCRTC_PSK          0x0504
-#define mmCRTC_PSK_HPOS     0x0508
-#define mmCRTC_CV4_START    0x050C
-#define mmCRTC_CV4_END      0x0510
-#define mmCRTC_CV4_HPOS     0x0514
-#define mmCRTC_ECK          0x051C
-#define mmREFRESH_CNTL      0x0520
-#define mmGENLCD_CNTL3      0x0524
-#define mmGPIO_DATA2        0x0528
-#define mmGPIO_CNTL3        0x052C
-#define mmGPIO_CNTL4        0x0530
-#define mmCHIP_STRAP        0x0534
-#define mmDISP_DEBUG2       0x0538
-#define mmDEBUG_BUS_CNTL    0x053C
-#define mmGAMMA_VALUE1      0x0540
-#define mmGAMMA_VALUE2      0x0544
-#define mmGAMMA_SLOPE       0x0548
-#define mmGEN_STATUS        0x054C
-#define mmHW_INT            0x0550
-/* Block DISPLAY End: */
-
-/* Block GFX Start: */
-#define mmDST_OFFSET          0x1004
-#define mmDST_PITCH           0x1008
-#define mmDST_Y_X             0x1038
-#define mmDST_WIDTH_HEIGHT    0x1198
-#define mmDP_GUI_MASTER_CNTL  0x106C
-#define mmBRUSH_OFFSET        0x108C
-#define mmBRUSH_Y_X           0x1074
-#define mmDP_BRUSH_FRGD_CLR   0x107C
-#define mmSRC_OFFSET          0x11AC
-#define mmSRC_PITCH           0x11B0
-#define mmSRC_Y_X             0x1034
-#define mmDEFAULT_PITCH_OFFSET      0x10A0
-#define mmDEFAULT_SC_BOTTOM_RIGHT   0x10A8
-#define mmDEFAULT2_SC_BOTTOM_RIGHT  0x10AC
-#define mmSC_TOP_LEFT         0x11BC
-#define mmSC_BOTTOM_RIGHT     0x11C0
-#define mmSRC_SC_BOTTOM_RIGHT 0x11C4
-#define mmGLOBAL_ALPHA        0x1210
-#define mmFILTER_COEF         0x1214
-#define mmMVC_CNTL_START      0x11E0
-#define mmE2_ARITHMETIC_CNTL  0x1220
-#define mmDP_CNTL             0x11C8
-#define mmDP_CNTL_DST_DIR     0x11CC
-#define mmDP_DATATYPE         0x12C4
-#define mmDP_MIX              0x12C8
-#define mmDP_WRITE_MSK        0x12CC
-#define mmENG_CNTL            0x13E8
-#define mmENG_PERF_CNT        0x13F0
-/* Block GFX End: */
-
-/* Block IDCT Start: */
-#define mmIDCT_RUNS         0x0C00
-#define mmIDCT_LEVELS       0x0C04
-#define mmIDCT_CONTROL      0x0C3C
-#define mmIDCT_AUTH_CONTROL 0x0C08
-#define mmIDCT_AUTH         0x0C0C
-/* Block IDCT End: */
-
-/* Block MC Start: */
-#define mmMEM_CNTL             0x0180
-#define mmMEM_ARB              0x0184
-#define mmMC_FB_LOCATION       0x0188
-#define mmMEM_EXT_CNTL         0x018C
-#define mmMC_EXT_MEM_LOCATION  0x0190
-#define mmMEM_EXT_TIMING_CNTL  0x0194
-#define mmMEM_SDRAM_MODE_REG   0x0198
-#define mmMEM_IO_CNTL          0x019C
-#define mmMC_DEBUG             0x01A0
-#define mmMC_BIST_CTRL         0x01A4
-#define mmMC_BIST_COLLAR_READ  0x01A8
-#define mmTC_MISMATCH          0x01AC
-#define mmMC_PERF_MON_CNTL     0x01B0
-#define mmMC_PERF_COUNTERS     0x01B4
-/* Block MC End: */
-
-/* Block BM Start: */
-#define mmBM_EXT_MEM_BANDWIDTH    0x0A00
-#define mmBM_OFFSET               0x0A04
-#define mmBM_MEM_EXT_TIMING_CNTL  0x0A08
-#define mmBM_MEM_EXT_CNTL         0x0A0C
-#define mmBM_MEM_MODE_REG         0x0A10
-#define mmBM_MEM_IO_CNTL          0x0A18
-#define mmBM_CONFIG               0x0A1C
-#define mmBM_STATUS               0x0A20
-#define mmBM_DEBUG                0x0A24
-#define mmBM_PERF_MON_CNTL        0x0A28
-#define mmBM_PERF_COUNTERS        0x0A2C
-#define mmBM_PERF2_MON_CNTL       0x0A30
-#define mmBM_PERF2_COUNTERS       0x0A34
-/* Block BM End: */
-
-/* Block RBBM Start: */
-#define mmWAIT_UNTIL        0x1400
-#define mmISYNC_CNTL        0x1404
-#define mmRBBM_STATUS       0x0140
-#define mmRBBM_CNTL         0x0144
-#define mmNQWAIT_UNTIL      0x0150
-/* Block RBBM End: */
-
-/* Block CG Start: */
-#define mmCLK_PIN_CNTL      0x0080
-#define mmPLL_REF_FB_DIV    0x0084
-#define mmPLL_CNTL          0x0088
-#define mmSCLK_CNTL         0x008C
-#define mmPCLK_CNTL         0x0090
-#define mmCLK_TEST_CNTL     0x0094
-#define mmPWRMGT_CNTL       0x0098
-#define mmPWRMGT_STATUS     0x009C
-/* Block CG End: */
-
-/* default value definitions */
-#define defWRAP_TOP_DIR        0x00000000
-#define defWRAP_START_DIR      0x00000000
-#define defCFGREG_BASE         0x00000000
-#define defCIF_IO              0x000C0902
-#define defINTF_CNTL           0x00000011
-#define defCPU_DEFAULTS        0x00000006
-#define defHW_INT              0x00000000
-#define defMC_EXT_MEM_LOCATION 0x07ff0000
-#define defTC_MISMATCH         0x00000000
-
-#define W100_CFG_BASE          0x0
-#define W100_CFG_LEN           0x10
-#define W100_REG_BASE          0x10000
-#define W100_REG_LEN           0x2000
-#define MEM_INT_BASE_VALUE     0x100000
-#define MEM_EXT_BASE_VALUE     0x800000
-#define MEM_INT_SIZE           0x05ffff
-#define MEM_WINDOW_BASE        0x100000
-#define MEM_WINDOW_SIZE        0xf00000
-
-#define WRAP_BUF_BASE_VALUE    0x80000
-#define WRAP_BUF_TOP_VALUE     0xbffff
-
-#define CHIP_ID_W100           0x57411002
-#define CHIP_ID_W3200          0x56441002
-#define CHIP_ID_W3220          0x57441002
-
-/* Register structure definitions */
-
-struct wrap_top_dir_t {
-	u32 top_addr  : 23;
-	u32           : 9;
-} __attribute__((packed));
-
-union wrap_top_dir_u {
-	u32 val : 32;
-	struct wrap_top_dir_t f;
-} __attribute__((packed));
-
-struct wrap_start_dir_t {
-	u32 start_addr : 23;
-	u32            : 9;
-} __attribute__((packed));
-
-union wrap_start_dir_u {
-	u32 val : 32;
-	struct wrap_start_dir_t f;
-} __attribute__((packed));
-
-struct cif_cntl_t {
-	u32 swap_reg                 : 2;
-	u32 swap_fbuf_1              : 2;
-	u32 swap_fbuf_2              : 2;
-	u32 swap_fbuf_3              : 2;
-	u32 pmi_int_disable          : 1;
-	u32 pmi_schmen_disable       : 1;
-	u32 intb_oe                  : 1;
-	u32 en_wait_to_compensate_dq_prop_dly  : 1;
-	u32 compensate_wait_rd_size  : 2;
-	u32 wait_asserted_timeout_val  : 2;
-	u32 wait_masked_val          : 2;
-	u32 en_wait_timeout          : 1;
-	u32 en_one_clk_setup_before_wait  : 1;
-	u32 interrupt_active_high    : 1;
-	u32 en_overwrite_straps      : 1;
-	u32 strap_wait_active_hi     : 1;
-	u32 lat_busy_count           : 2;
-	u32 lat_rd_pm4_sclk_busy     : 1;
-	u32 dis_system_bits          : 1;
-	u32 dis_mr                   : 1;
-	u32 cif_spare_1              : 4;
-} __attribute__((packed));
-
-union cif_cntl_u {
-	u32 val : 32;
-	struct cif_cntl_t f;
-} __attribute__((packed));
-
-struct cfgreg_base_t {
-	u32 cfgreg_base  : 24;
-	u32              : 8;
-} __attribute__((packed));
-
-union cfgreg_base_u {
-	u32 val : 32;
-	struct cfgreg_base_t f;
-} __attribute__((packed));
-
-struct cif_io_t {
-	u32 dq_srp     : 1;
-	u32 dq_srn     : 1;
-	u32 dq_sp      : 4;
-	u32 dq_sn      : 4;
-	u32 waitb_srp  : 1;
-	u32 waitb_srn  : 1;
-	u32 waitb_sp   : 4;
-	u32 waitb_sn   : 4;
-	u32 intb_srp   : 1;
-	u32 intb_srn   : 1;
-	u32 intb_sp    : 4;
-	u32 intb_sn    : 4;
-	u32            : 2;
-} __attribute__((packed));
-
-union cif_io_u {
-	u32 val : 32;
-	struct cif_io_t f;
-} __attribute__((packed));
-
-struct cif_read_dbg_t {
-	u32 unpacker_pre_fetch_trig_gen  : 2;
-	u32 dly_second_rd_fetch_trig     : 1;
-	u32 rst_rd_burst_id              : 1;
-	u32 dis_rd_burst_id              : 1;
-	u32 en_block_rd_when_packer_is_not_emp : 1;
-	u32 dis_pre_fetch_cntl_sm        : 1;
-	u32 rbbm_chrncy_dis              : 1;
-	u32 rbbm_rd_after_wr_lat         : 2;
-	u32 dis_be_during_rd             : 1;
-	u32 one_clk_invalidate_pulse     : 1;
-	u32 dis_chnl_priority            : 1;
-	u32 rst_read_path_a_pls          : 1;
-	u32 rst_read_path_b_pls          : 1;
-	u32 dis_reg_rd_fetch_trig        : 1;
-	u32 dis_rd_fetch_trig_from_ind_addr : 1;
-	u32 dis_rd_same_byte_to_trig_fetch : 1;
-	u32 dis_dir_wrap                 : 1;
-	u32 dis_ring_buf_to_force_dec    : 1;
-	u32 dis_addr_comp_in_16bit       : 1;
-	u32 clr_w                        : 1;
-	u32 err_rd_tag_is_3              : 1;
-	u32 err_load_when_ful_a          : 1;
-	u32 err_load_when_ful_b          : 1;
-	u32                              : 7;
-} __attribute__((packed));
-
-union cif_read_dbg_u {
-	u32 val : 32;
-	struct cif_read_dbg_t f;
-} __attribute__((packed));
-
-struct cif_write_dbg_t {
-	u32 packer_timeout_count          : 2;
-	u32 en_upper_load_cond            : 1;
-	u32 en_chnl_change_cond           : 1;
-	u32 dis_addr_comp_cond            : 1;
-	u32 dis_load_same_byte_addr_cond  : 1;
-	u32 dis_timeout_cond              : 1;
-	u32 dis_timeout_during_rbbm       : 1;
-	u32 dis_packer_ful_during_rbbm_timeout : 1;
-	u32 en_dword_split_to_rbbm        : 1;
-	u32 en_dummy_val                  : 1;
-	u32 dummy_val_sel                 : 1;
-	u32 mask_pm4_wrptr_dec            : 1;
-	u32 dis_mc_clean_cond             : 1;
-	u32 err_two_reqi_during_ful       : 1;
-	u32 err_reqi_during_idle_clk      : 1;
-	u32 err_global                    : 1;
-	u32 en_wr_buf_dbg_load            : 1;
-	u32 en_wr_buf_dbg_path            : 1;
-	u32 sel_wr_buf_byte               : 3;
-	u32 dis_rd_flush_wr               : 1;
-	u32 dis_packer_ful_cond           : 1;
-	u32 dis_invalidate_by_ops_chnl    : 1;
-	u32 en_halt_when_reqi_err         : 1;
-	u32 cif_spare_2                   : 5;
-	u32                               : 1;
-} __attribute__((packed));
-
-union cif_write_dbg_u {
-	u32 val : 32;
-	struct cif_write_dbg_t f;
-} __attribute__((packed));
-
-
-struct intf_cntl_t {
-	unsigned char ad_inc_a            : 1;
-	unsigned char ring_buf_a          : 1;
-	unsigned char rd_fetch_trigger_a  : 1;
-	unsigned char rd_data_rdy_a       : 1;
-	unsigned char ad_inc_b            : 1;
-	unsigned char ring_buf_b          : 1;
-	unsigned char rd_fetch_trigger_b  : 1;
-	unsigned char rd_data_rdy_b       : 1;
-} __attribute__((packed));
-
-union intf_cntl_u {
-	unsigned char val : 8;
-	struct intf_cntl_t f;
-} __attribute__((packed));
-
-struct cpu_defaults_t {
-	unsigned char unpack_rd_data     : 1;
-	unsigned char access_ind_addr_a  : 1;
-	unsigned char access_ind_addr_b  : 1;
-	unsigned char access_scratch_reg : 1;
-	unsigned char pack_wr_data       : 1;
-	unsigned char transition_size    : 1;
-	unsigned char en_read_buf_mode   : 1;
-	unsigned char rd_fetch_scratch   : 1;
-} __attribute__((packed));
-
-union cpu_defaults_u {
-	unsigned char val : 8;
-	struct cpu_defaults_t f;
-} __attribute__((packed));
-
-struct crtc_total_t {
-	u32 crtc_h_total : 10;
-	u32              : 6;
-	u32 crtc_v_total : 10;
-	u32              : 6;
-} __attribute__((packed));
-
-union crtc_total_u {
-	u32 val : 32;
-	struct crtc_total_t f;
-} __attribute__((packed));
-
-struct crtc_ss_t {
-	u32 ss_start    : 10;
-	u32             : 6;
-	u32 ss_end      : 10;
-	u32             : 2;
-	u32 ss_align    : 1;
-	u32 ss_pol      : 1;
-	u32 ss_run_mode : 1;
-	u32 ss_en       : 1;
-} __attribute__((packed));
-
-union crtc_ss_u {
-	u32 val : 32;
-	struct crtc_ss_t f;
-} __attribute__((packed));
-
-struct active_h_disp_t {
-	u32 active_h_start  : 10;
-	u32                 : 6;
-	u32 active_h_end    : 10;
-	u32                 : 6;
-} __attribute__((packed));
-
-union active_h_disp_u {
-	u32 val : 32;
-	struct active_h_disp_t f;
-} __attribute__((packed));
-
-struct active_v_disp_t {
-	u32 active_v_start  : 10;
-	u32                 : 6;
-	u32 active_v_end    : 10;
-	u32                 : 6;
-} __attribute__((packed));
-
-union active_v_disp_u {
-	u32 val : 32;
-	struct active_v_disp_t f;
-} __attribute__((packed));
-
-struct graphic_h_disp_t {
-	u32 graphic_h_start : 10;
-	u32                 : 6;
-	u32 graphic_h_end   : 10;
-	u32                 : 6;
-} __attribute__((packed));
-
-union graphic_h_disp_u {
-	u32 val : 32;
-	struct graphic_h_disp_t f;
-} __attribute__((packed));
-
-struct graphic_v_disp_t {
-	u32 graphic_v_start : 10;
-	u32                 : 6;
-	u32 graphic_v_end   : 10;
-	u32                 : 6;
-} __attribute__((packed));
-
-union graphic_v_disp_u{
-	u32 val : 32;
-	struct graphic_v_disp_t f;
-} __attribute__((packed));
-
-struct graphic_ctrl_t_w100 {
-	u32 color_depth       : 3;
-	u32 portrait_mode     : 2;
-	u32 low_power_on      : 1;
-	u32 req_freq          : 4;
-	u32 en_crtc           : 1;
-	u32 en_graphic_req    : 1;
-	u32 en_graphic_crtc   : 1;
-	u32 total_req_graphic : 9;
-	u32 lcd_pclk_on       : 1;
-	u32 lcd_sclk_on       : 1;
-	u32 pclk_running      : 1;
-	u32 sclk_running      : 1;
-	u32                   : 6;
-} __attribute__((packed));
-
-struct graphic_ctrl_t_w32xx {
-	u32 color_depth       : 3;
-	u32 portrait_mode     : 2;
-	u32 low_power_on      : 1;
-	u32 req_freq          : 4;
-	u32 en_crtc           : 1;
-	u32 en_graphic_req    : 1;
-	u32 en_graphic_crtc   : 1;
-	u32 total_req_graphic : 10;
-	u32 lcd_pclk_on       : 1;
-	u32 lcd_sclk_on       : 1;
-	u32 pclk_running      : 1;
-	u32 sclk_running      : 1;
-	u32                   : 5;
-} __attribute__((packed));
-
-union graphic_ctrl_u {
-	u32 val : 32;
-	struct graphic_ctrl_t_w100 f_w100;
-	struct graphic_ctrl_t_w32xx f_w32xx;
-} __attribute__((packed));
-
-struct video_ctrl_t {
-	u32 video_mode       : 1;
-	u32 keyer_en         : 1;
-	u32 en_video_req     : 1;
-	u32 en_graphic_req_video  : 1;
-	u32 en_video_crtc    : 1;
-	u32 video_hor_exp    : 2;
-	u32 video_ver_exp    : 2;
-	u32 uv_combine       : 1;
-	u32 total_req_video  : 9;
-	u32 video_ch_sel     : 1;
-	u32 video_portrait   : 2;
-	u32 yuv2rgb_en       : 1;
-	u32 yuv2rgb_option   : 1;
-	u32 video_inv_hor    : 1;
-	u32 video_inv_ver    : 1;
-	u32 gamma_sel        : 2;
-	u32 dis_limit        : 1;
-	u32 en_uv_hblend     : 1;
-	u32 rgb_gamma_sel    : 2;
-} __attribute__((packed));
-
-union video_ctrl_u {
-	u32 val : 32;
-	struct video_ctrl_t f;
-} __attribute__((packed));
-
-struct disp_db_buf_cntl_rd_t {
-	u32 en_db_buf           : 1;
-	u32 update_db_buf_done  : 1;
-	u32 db_buf_cntl         : 6;
-	u32                     : 24;
-} __attribute__((packed));
-
-union disp_db_buf_cntl_rd_u {
-	u32 val : 32;
-	struct disp_db_buf_cntl_rd_t f;
-} __attribute__((packed));
-
-struct disp_db_buf_cntl_wr_t {
-	u32 en_db_buf      : 1;
-	u32 update_db_buf  : 1;
-	u32 db_buf_cntl    : 6;
-	u32                : 24;
-} __attribute__((packed));
-
-union disp_db_buf_cntl_wr_u {
-	u32 val : 32;
-	struct disp_db_buf_cntl_wr_t f;
-} __attribute__((packed));
-
-struct gamma_value1_t {
-	u32 gamma1   : 8;
-	u32 gamma2   : 8;
-	u32 gamma3   : 8;
-	u32 gamma4   : 8;
-} __attribute__((packed));
-
-union gamma_value1_u {
-	u32 val : 32;
-	struct gamma_value1_t f;
-} __attribute__((packed));
-
-struct gamma_value2_t {
-	u32 gamma5   : 8;
-	u32 gamma6   : 8;
-	u32 gamma7   : 8;
-	u32 gamma8   : 8;
-} __attribute__((packed));
-
-union gamma_value2_u {
-	u32 val : 32;
-	struct gamma_value2_t f;
-} __attribute__((packed));
-
-struct gamma_slope_t {
-	u32 slope1   : 3;
-	u32 slope2   : 3;
-	u32 slope3   : 3;
-	u32 slope4   : 3;
-	u32 slope5   : 3;
-	u32 slope6   : 3;
-	u32 slope7   : 3;
-	u32 slope8   : 3;
-	u32          : 8;
-} __attribute__((packed));
-
-union gamma_slope_u {
-	u32 val : 32;
-	struct gamma_slope_t f;
-} __attribute__((packed));
-
-struct mc_ext_mem_location_t {
-	u32 mc_ext_mem_start : 16;
-	u32 mc_ext_mem_top   : 16;
-} __attribute__((packed));
-
-union mc_ext_mem_location_u {
-	u32 val : 32;
-	struct mc_ext_mem_location_t f;
-} __attribute__((packed));
-
-struct mc_fb_location_t {
-	u32 mc_fb_start      : 16;
-	u32 mc_fb_top        : 16;
-} __attribute__((packed));
-
-union mc_fb_location_u {
-	u32 val : 32;
-	struct mc_fb_location_t f;
-} __attribute__((packed));
-
-struct clk_pin_cntl_t {
-	u32 osc_en           : 1;
-	u32 osc_gain         : 5;
-	u32 dont_use_xtalin  : 1;
-	u32 xtalin_pm_en     : 1;
-	u32 xtalin_dbl_en    : 1;
-	u32                  : 7;
-	u32 cg_debug         : 16;
-} __attribute__((packed));
-
-union clk_pin_cntl_u {
-	u32 val : 32;
-	struct clk_pin_cntl_t f;
-} __attribute__((packed));
-
-struct pll_ref_fb_div_t {
-	u32 pll_ref_div      : 4;
-	u32                  : 4;
-	u32 pll_fb_div_int   : 6;
-	u32                  : 2;
-	u32 pll_fb_div_frac  : 3;
-	u32                  : 1;
-	u32 pll_reset_time   : 4;
-	u32 pll_lock_time    : 8;
-} __attribute__((packed));
-
-union pll_ref_fb_div_u {
-	u32 val : 32;
-	struct pll_ref_fb_div_t f;
-} __attribute__((packed));
-
-struct pll_cntl_t {
-	u32 pll_pwdn        : 1;
-	u32 pll_reset       : 1;
-	u32 pll_pm_en       : 1;
-	u32 pll_mode        : 1;
-	u32 pll_refclk_sel  : 1;
-	u32 pll_fbclk_sel   : 1;
-	u32 pll_tcpoff      : 1;
-	u32 pll_pcp         : 3;
-	u32 pll_pvg         : 3;
-	u32 pll_vcofr       : 1;
-	u32 pll_ioffset     : 2;
-	u32 pll_pecc_mode   : 2;
-	u32 pll_pecc_scon   : 2;
-	u32 pll_dactal      : 4;
-	u32 pll_cp_clip     : 2;
-	u32 pll_conf        : 3;
-	u32 pll_mbctrl      : 2;
-	u32 pll_ring_off    : 1;
-} __attribute__((packed));
-
-union pll_cntl_u {
-	u32 val : 32;
-	struct pll_cntl_t f;
-} __attribute__((packed));
-
-struct sclk_cntl_t {
-	u32 sclk_src_sel         : 2;
-	u32                      : 2;
-	u32 sclk_post_div_fast   : 4;
-	u32 sclk_clkon_hys       : 3;
-	u32 sclk_post_div_slow   : 4;
-	u32 disp_cg_ok2switch_en : 1;
-	u32 sclk_force_reg       : 1;
-	u32 sclk_force_disp      : 1;
-	u32 sclk_force_mc        : 1;
-	u32 sclk_force_extmc     : 1;
-	u32 sclk_force_cp        : 1;
-	u32 sclk_force_e2        : 1;
-	u32 sclk_force_e3        : 1;
-	u32 sclk_force_idct      : 1;
-	u32 sclk_force_bist      : 1;
-	u32 busy_extend_cp       : 1;
-	u32 busy_extend_e2       : 1;
-	u32 busy_extend_e3       : 1;
-	u32 busy_extend_idct     : 1;
-	u32                      : 3;
-} __attribute__((packed));
-
-union sclk_cntl_u {
-	u32 val : 32;
-	struct sclk_cntl_t f;
-} __attribute__((packed));
-
-struct pclk_cntl_t {
-	u32 pclk_src_sel     : 2;
-	u32                  : 2;
-	u32 pclk_post_div    : 4;
-	u32                  : 8;
-	u32 pclk_force_disp  : 1;
-	u32                  : 15;
-} __attribute__((packed));
-
-union pclk_cntl_u {
-	u32 val : 32;
-	struct pclk_cntl_t f;
-} __attribute__((packed));
-
-
-#define TESTCLK_SRC_PLL   0x01
-#define TESTCLK_SRC_SCLK  0x02
-#define TESTCLK_SRC_PCLK  0x03
-/* 4 and 5 seem to by XTAL/M */
-#define TESTCLK_SRC_XTAL  0x06
-
-struct clk_test_cntl_t {
-	u32 testclk_sel      : 4;
-	u32                  : 3;
-	u32 start_check_freq : 1;
-	u32 tstcount_rst     : 1;
-	u32                  : 15;
-	u32 test_count       : 8;
-} __attribute__((packed));
-
-union clk_test_cntl_u {
-	u32 val : 32;
-	struct clk_test_cntl_t f;
-} __attribute__((packed));
-
-struct pwrmgt_cntl_t {
-	u32 pwm_enable           : 1;
-	u32                      : 1;
-	u32 pwm_mode_req         : 2;
-	u32 pwm_wakeup_cond      : 2;
-	u32 pwm_fast_noml_hw_en  : 1;
-	u32 pwm_noml_fast_hw_en  : 1;
-	u32 pwm_fast_noml_cond   : 4;
-	u32 pwm_noml_fast_cond   : 4;
-	u32 pwm_idle_timer       : 8;
-	u32 pwm_busy_timer       : 8;
-} __attribute__((packed));
-
-union pwrmgt_cntl_u {
-	u32 val : 32;
-	struct pwrmgt_cntl_t f;
-} __attribute__((packed));
-
-#define SRC_DATATYPE_EQU_DST	3
-
-#define ROP3_SRCCOPY	0xcc
-#define ROP3_PATCOPY	0xf0
-
-#define GMC_BRUSH_SOLID_COLOR	13
-#define GMC_BRUSH_NONE			15
-
-#define DP_SRC_MEM_RECTANGULAR	2
-
-#define DP_OP_ROP	0
-
-struct dp_gui_master_cntl_t {
-	u32 gmc_src_pitch_offset_cntl : 1;
-	u32 gmc_dst_pitch_offset_cntl : 1;
-	u32 gmc_src_clipping          : 1;
-	u32 gmc_dst_clipping          : 1;
-	u32 gmc_brush_datatype        : 4;
-	u32 gmc_dst_datatype          : 4;
-	u32 gmc_src_datatype          : 3;
-	u32 gmc_byte_pix_order        : 1;
-	u32 gmc_default_sel           : 1;
-	u32 gmc_rop3                  : 8;
-	u32 gmc_dp_src_source         : 3;
-	u32 gmc_clr_cmp_fcn_dis       : 1;
-	u32                           : 1;
-	u32 gmc_wr_msk_dis            : 1;
-	u32 gmc_dp_op                 : 1;
-} __attribute__((packed));
-
-union dp_gui_master_cntl_u {
-	u32 val : 32;
-	struct dp_gui_master_cntl_t f;
-} __attribute__((packed));
-
-struct rbbm_status_t {
-	u32 cmdfifo_avail   : 7;
-	u32                 : 1;
-	u32 hirq_on_rbb     : 1;
-	u32 cprq_on_rbb     : 1;
-	u32 cfrq_on_rbb     : 1;
-	u32 hirq_in_rtbuf   : 1;
-	u32 cprq_in_rtbuf   : 1;
-	u32 cfrq_in_rtbuf   : 1;
-	u32 cf_pipe_busy    : 1;
-	u32 eng_ev_busy     : 1;
-	u32 cp_cmdstrm_busy : 1;
-	u32 e2_busy         : 1;
-	u32 rb2d_busy       : 1;
-	u32 rb3d_busy       : 1;
-	u32 se_busy         : 1;
-	u32 re_busy         : 1;
-	u32 tam_busy        : 1;
-	u32 tdm_busy        : 1;
-	u32 pb_busy         : 1;
-	u32                 : 6;
-	u32 gui_active      : 1;
-} __attribute__((packed));
-
-union rbbm_status_u {
-	u32 val : 32;
-	struct rbbm_status_t f;
-} __attribute__((packed));
-
-struct dp_datatype_t {
-	u32 dp_dst_datatype   : 4;
-	u32                   : 4;
-	u32 dp_brush_datatype : 4;
-	u32 dp_src2_type      : 1;
-	u32 dp_src2_datatype  : 3;
-	u32 dp_src_datatype   : 3;
-	u32                   : 11;
-	u32 dp_byte_pix_order : 1;
-	u32                   : 1;
-} __attribute__((packed));
-
-union dp_datatype_u {
-	u32 val : 32;
-	struct dp_datatype_t f;
-} __attribute__((packed));
-
-struct dp_mix_t {
-	u32                : 8;
-	u32 dp_src_source  : 3;
-	u32 dp_src2_source : 3;
-	u32                : 2;
-	u32 dp_rop3        : 8;
-	u32 dp_op          : 1;
-	u32                : 7;
-} __attribute__((packed));
-
-union dp_mix_u {
-	u32 val : 32;
-	struct dp_mix_t f;
-} __attribute__((packed));
-
-struct eng_cntl_t {
-	u32 erc_reg_rd_ws            : 1;
-	u32 erc_reg_wr_ws            : 1;
-	u32 erc_idle_reg_wr          : 1;
-	u32 dis_engine_triggers      : 1;
-	u32 dis_rop_src_uses_dst_w_h : 1;
-	u32 dis_src_uses_dst_dirmaj  : 1;
-	u32                          : 6;
-	u32 force_3dclk_when_2dclk   : 1;
-	u32                          : 19;
-} __attribute__((packed));
-
-union eng_cntl_u {
-	u32 val : 32;
-	struct eng_cntl_t f;
-} __attribute__((packed));
-
-struct dp_cntl_t {
-	u32 dst_x_dir   : 1;
-	u32 dst_y_dir   : 1;
-	u32 src_x_dir   : 1;
-	u32 src_y_dir   : 1;
-	u32 dst_major_x : 1;
-	u32 src_major_x : 1;
-	u32             : 26;
-} __attribute__((packed));
-
-union dp_cntl_u {
-	u32 val : 32;
-	struct dp_cntl_t f;
-} __attribute__((packed));
-
-struct dp_cntl_dst_dir_t {
-	u32           : 15;
-	u32 dst_y_dir : 1;
-	u32           : 15;
-	u32 dst_x_dir : 1;
-} __attribute__((packed));
-
-union dp_cntl_dst_dir_u {
-	u32 val : 32;
-	struct dp_cntl_dst_dir_t f;
-} __attribute__((packed));
-
-#endif
-
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
deleted file mode 100644
index 537d199612af..000000000000
--- a/drivers/video/wm8505fb.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- *  WonderMedia WM8505 Frame Buffer device driver
- *
- *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
- *    Based on vt8500lcdfb.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/fb.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/memblock.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <video/of_display_timing.h>
-
-#include "wm8505fb_regs.h"
-#include "wmt_ge_rops.h"
-
-#define DRIVER_NAME "wm8505-fb"
-
-#define to_wm8505fb_info(__info) container_of(__info, \
-						struct wm8505fb_info, fb)
-struct wm8505fb_info {
-	struct fb_info		fb;
-	void __iomem		*regbase;
-	unsigned int		contrast;
-};
-
-
-static int wm8505fb_init_hw(struct fb_info *info)
-{
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-
-	int i;
-
-	/* I know the purpose only of few registers, so clear unknown */
-	for (i = 0; i < 0x200; i += 4)
-		writel(0, fbi->regbase + i);
-
-	/* Set frame buffer address */
-	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
-	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
-
-	/*
-	 * Set in-memory picture format to RGB
-	 * 0x31C sets the correct color mode (RGB565) for WM8650
-	 * Bit 8+9 (0x300) are ignored on WM8505 as reserved
-	 */
-	writel(0x31c,		       fbi->regbase + WMT_GOVR_COLORSPACE);
-	writel(1,		       fbi->regbase + WMT_GOVR_COLORSPACE1);
-
-	/* Virtual buffer size */
-	writel(info->var.xres,	       fbi->regbase + WMT_GOVR_XRES);
-	writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
-
-	/* black magic ;) */
-	writel(0xf,		       fbi->regbase + WMT_GOVR_FHI);
-	writel(4,		       fbi->regbase + WMT_GOVR_DVO_SET);
-	writel(1,		       fbi->regbase + WMT_GOVR_MIF_ENABLE);
-	writel(1,		       fbi->regbase + WMT_GOVR_REG_UPDATE);
-
-	return 0;
-}
-
-static int wm8505fb_set_timing(struct fb_info *info)
-{
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-
-	int h_start = info->var.left_margin;
-	int h_end = h_start + info->var.xres;
-	int h_all = h_end + info->var.right_margin;
-	int h_sync = info->var.hsync_len;
-
-	int v_start = info->var.upper_margin;
-	int v_end = v_start + info->var.yres;
-	int v_all = v_end + info->var.lower_margin;
-	int v_sync = info->var.vsync_len;
-
-	writel(0, fbi->regbase + WMT_GOVR_TG);
-
-	writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
-	writel(h_end,   fbi->regbase + WMT_GOVR_TIMING_H_END);
-	writel(h_all,   fbi->regbase + WMT_GOVR_TIMING_H_ALL);
-	writel(h_sync,  fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
-
-	writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
-	writel(v_end,   fbi->regbase + WMT_GOVR_TIMING_V_END);
-	writel(v_all,   fbi->regbase + WMT_GOVR_TIMING_V_ALL);
-	writel(v_sync,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
-
-	writel(1, fbi->regbase + WMT_GOVR_TG);
-
-	return 0;
-}
-
-
-static int wm8505fb_set_par(struct fb_info *info)
-{
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-
-	if (!fbi)
-		return -EINVAL;
-
-	if (info->var.bits_per_pixel == 32) {
-		info->var.red.offset = 16;
-		info->var.red.length = 8;
-		info->var.red.msb_right = 0;
-		info->var.green.offset = 8;
-		info->var.green.length = 8;
-		info->var.green.msb_right = 0;
-		info->var.blue.offset = 0;
-		info->var.blue.length = 8;
-		info->var.blue.msb_right = 0;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		info->fix.line_length = info->var.xres_virtual << 2;
-	} else if (info->var.bits_per_pixel == 16) {
-		info->var.red.offset = 11;
-		info->var.red.length = 5;
-		info->var.red.msb_right = 0;
-		info->var.green.offset = 5;
-		info->var.green.length = 6;
-		info->var.green.msb_right = 0;
-		info->var.blue.offset = 0;
-		info->var.blue.length = 5;
-		info->var.blue.msb_right = 0;
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-		info->fix.line_length = info->var.xres_virtual << 1;
-	}
-
-	wm8505fb_set_timing(info);
-
-	writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
-		fbi->regbase + WMT_GOVR_CONTRAST);
-
-	return 0;
-}
-
-static ssize_t contrast_show(struct device *dev,
-			     struct device_attribute *attr, char *buf)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-
-	return sprintf(buf, "%d\n", fbi->contrast);
-}
-
-static ssize_t contrast_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct fb_info *info = dev_get_drvdata(dev);
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-	unsigned long tmp;
-
-	if (kstrtoul(buf, 10, &tmp) || (tmp > 0xff))
-		return -EINVAL;
-	fbi->contrast = tmp;
-
-	wm8505fb_set_par(info);
-
-	return count;
-}
-
-static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
-
-static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
-{
-	chan &= 0xffff;
-	chan >>= 16 - bf->length;
-	return chan << bf->offset;
-}
-
-static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info) {
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-	int ret = 1;
-	unsigned int val;
-	if (regno >= 256)
-		return -EINVAL;
-
-	if (info->var.grayscale)
-		red = green = blue =
-			(19595 * red + 38470 * green + 7471 * blue) >> 16;
-
-	switch (fbi->fb.fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		if (regno < 16) {
-			u32 *pal = info->pseudo_palette;
-
-			val  = chan_to_field(red, &fbi->fb.var.red);
-			val |= chan_to_field(green, &fbi->fb.var.green);
-			val |= chan_to_field(blue, &fbi->fb.var.blue);
-
-			pal[regno] = val;
-			ret = 0;
-		}
-		break;
-	}
-
-	return ret;
-}
-
-static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-
-	writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
-	writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
-	return 0;
-}
-
-static int wm8505fb_blank(int blank, struct fb_info *info)
-{
-	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
-
-	switch (blank) {
-	case FB_BLANK_UNBLANK:
-		wm8505fb_set_timing(info);
-		break;
-	default:
-		writel(0,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
-		break;
-	}
-
-	return 0;
-}
-
-static struct fb_ops wm8505fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_set_par	= wm8505fb_set_par,
-	.fb_setcolreg	= wm8505fb_setcolreg,
-	.fb_fillrect	= wmt_ge_fillrect,
-	.fb_copyarea	= wmt_ge_copyarea,
-	.fb_imageblit	= sys_imageblit,
-	.fb_sync	= wmt_ge_sync,
-	.fb_pan_display	= wm8505fb_pan_display,
-	.fb_blank	= wm8505fb_blank,
-};
-
-static int wm8505fb_probe(struct platform_device *pdev)
-{
-	struct wm8505fb_info	*fbi;
-	struct resource	*res;
-	struct display_timings *disp_timing;
-	void			*addr;
-	int ret;
-
-	struct fb_videomode	mode;
-	u32			bpp;
-	dma_addr_t fb_mem_phys;
-	unsigned long fb_mem_len;
-	void *fb_mem_virt;
-
-	fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
-			sizeof(u32) * 16, GFP_KERNEL);
-	if (!fbi) {
-		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-		return -ENOMEM;
-	}
-
-	strcpy(fbi->fb.fix.id, DRIVER_NAME);
-
-	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
-	fbi->fb.fix.xpanstep	= 1;
-	fbi->fb.fix.ypanstep	= 1;
-	fbi->fb.fix.ywrapstep	= 0;
-	fbi->fb.fix.accel	= FB_ACCEL_NONE;
-
-	fbi->fb.fbops		= &wm8505fb_ops;
-	fbi->fb.flags		= FBINFO_DEFAULT
-				| FBINFO_HWACCEL_COPYAREA
-				| FBINFO_HWACCEL_FILLRECT
-				| FBINFO_HWACCEL_XPAN
-				| FBINFO_HWACCEL_YPAN
-				| FBINFO_VIRTFB
-				| FBINFO_PARTIAL_PAN_OK;
-	fbi->fb.node		= -1;
-
-	addr = fbi;
-	addr = addr + sizeof(struct wm8505fb_info);
-	fbi->fb.pseudo_palette	= addr;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(fbi->regbase))
-		return PTR_ERR(fbi->regbase);
-
-	disp_timing = of_get_display_timings(pdev->dev.of_node);
-	if (!disp_timing)
-		return -EINVAL;
-
-	ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE);
-	if (ret)
-		return ret;
-
-	ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
-	if (ret)
-		return ret;
-
-	fb_videomode_to_var(&fbi->fb.var, &mode);
-
-	fbi->fb.var.nonstd		= 0;
-	fbi->fb.var.activate		= FB_ACTIVATE_NOW;
-
-	fbi->fb.var.height		= -1;
-	fbi->fb.var.width		= -1;
-
-	/* try allocating the framebuffer */
-	fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8);
-	fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
-				GFP_KERNEL);
-	if (!fb_mem_virt) {
-		pr_err("%s: Failed to allocate framebuffer\n", __func__);
-		return -ENOMEM;
-	}
-
-	fbi->fb.var.xres_virtual	= mode.xres;
-	fbi->fb.var.yres_virtual	= mode.yres * 2;
-	fbi->fb.var.bits_per_pixel	= bpp;
-
-	fbi->fb.fix.smem_start		= fb_mem_phys;
-	fbi->fb.fix.smem_len		= fb_mem_len;
-	fbi->fb.screen_base		= fb_mem_virt;
-	fbi->fb.screen_size		= fb_mem_len;
-
-	fbi->contrast = 0x10;
-	ret = wm8505fb_set_par(&fbi->fb);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to set parameters\n");
-		return ret;
-	}
-
-	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
-		dev_err(&pdev->dev, "Failed to allocate color map\n");
-		return -ENOMEM;
-	}
-
-	wm8505fb_init_hw(&fbi->fb);
-
-	platform_set_drvdata(pdev, fbi);
-
-	ret = register_framebuffer(&fbi->fb);
-	if (ret < 0) {
-		dev_err(&pdev->dev,
-			"Failed to register framebuffer device: %d\n", ret);
-		if (fbi->fb.cmap.len)
-			fb_dealloc_cmap(&fbi->fb.cmap);
-		return ret;
-	}
-
-	ret = device_create_file(&pdev->dev, &dev_attr_contrast);
-	if (ret < 0)
-		fb_warn(&fbi->fb, "failed to register attributes (%d)\n", ret);
-
-	fb_info(&fbi->fb, "%s frame buffer at 0x%lx-0x%lx\n",
-		fbi->fb.fix.id, fbi->fb.fix.smem_start,
-		fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
-
-	return 0;
-}
-
-static int wm8505fb_remove(struct platform_device *pdev)
-{
-	struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
-
-	device_remove_file(&pdev->dev, &dev_attr_contrast);
-
-	unregister_framebuffer(&fbi->fb);
-
-	writel(0, fbi->regbase);
-
-	if (fbi->fb.cmap.len)
-		fb_dealloc_cmap(&fbi->fb.cmap);
-
-	return 0;
-}
-
-static const struct of_device_id wmt_dt_ids[] = {
-	{ .compatible = "wm,wm8505-fb", },
-	{}
-};
-
-static struct platform_driver wm8505fb_driver = {
-	.probe		= wm8505fb_probe,
-	.remove		= wm8505fb_remove,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= DRIVER_NAME,
-		.of_match_table = wmt_dt_ids,
-	},
-};
-
-module_platform_driver(wm8505fb_driver);
-
-MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
-MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, wmt_dt_ids);
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/wm8505fb_regs.h
deleted file mode 100644
index 4dd41668c6d1..000000000000
--- a/drivers/video/wm8505fb_regs.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *  GOVR registers list for WM8505 chips
- *
- *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
- *   Based on VIA/WonderMedia wm8510-govrh-reg.h
- *   http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
- *         drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _WM8505FB_REGS_H
-#define _WM8505FB_REGS_H
-
-/*
- * Color space select register, default value 0x1c
- *   BIT0 GOVRH_DVO_YUV2RGB_ENABLE
- *   BIT1 GOVRH_VGA_YUV2RGB_ENABLE
- *   BIT2 GOVRH_RGB_MODE
- *   BIT3 GOVRH_DAC_CLKINV
- *   BIT4 GOVRH_BLANK_ZERO
- */
-#define WMT_GOVR_COLORSPACE	0x1e4
-/*
- * Another colorspace select register, default value 1
- *   BIT0 GOVRH_DVO_RGB
- *   BIT1 GOVRH_DVO_YUV422
- */
-#define WMT_GOVR_COLORSPACE1	 0x30
-
-#define WMT_GOVR_CONTRAST	0x1b8
-#define WMT_GOVR_BRGHTNESS	0x1bc /* incompatible with RGB? */
-
-/* Framubeffer address */
-#define WMT_GOVR_FBADDR		 0x90
-#define WMT_GOVR_FBADDR1	 0x94 /* UV offset in YUV mode */
-
-/* Offset of visible window */
-#define WMT_GOVR_XPAN		 0xa4
-#define WMT_GOVR_YPAN		 0xa0
-
-#define WMT_GOVR_XRES		 0x98
-#define WMT_GOVR_XRES_VIRTUAL	 0x9c
-
-#define WMT_GOVR_MIF_ENABLE	 0x80
-#define WMT_GOVR_FHI		 0xa8
-#define WMT_GOVR_REG_UPDATE	 0xe4
-
-/*
- *   BIT0 GOVRH_DVO_OUTWIDTH
- *   BIT1 GOVRH_DVO_SYNC_POLAR
- *   BIT2 GOVRH_DVO_ENABLE
- */
-#define WMT_GOVR_DVO_SET	0x148
-
-/* Timing generator? */
-#define WMT_GOVR_TG		0x100
-
-/* Timings */
-#define WMT_GOVR_TIMING_H_ALL	0x108
-#define WMT_GOVR_TIMING_V_ALL	0x10c
-#define WMT_GOVR_TIMING_V_START	0x110
-#define WMT_GOVR_TIMING_V_END	0x114
-#define WMT_GOVR_TIMING_H_START	0x118
-#define WMT_GOVR_TIMING_H_END	0x11c
-#define WMT_GOVR_TIMING_V_SYNC	0x128
-#define WMT_GOVR_TIMING_H_SYNC	0x12c
-
-#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
deleted file mode 100644
index b0a9f34b2e01..000000000000
--- a/drivers/video/wmt_ge_rops.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- *  linux/drivers/video/wmt_ge_rops.c
- *
- *  Accelerators for raster operations using WonderMedia Graphics Engine
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/fb.h>
-#include <linux/platform_device.h>
-#include "fb_draw.h"
-
-#define GE_COMMAND_OFF		0x00
-#define GE_DEPTH_OFF		0x04
-#define GE_HIGHCOLOR_OFF	0x08
-#define GE_ROPCODE_OFF		0x14
-#define GE_FIRE_OFF		0x18
-#define GE_SRCBASE_OFF		0x20
-#define GE_SRCDISPW_OFF		0x24
-#define GE_SRCDISPH_OFF		0x28
-#define GE_SRCAREAX_OFF		0x2c
-#define GE_SRCAREAY_OFF		0x30
-#define GE_SRCAREAW_OFF		0x34
-#define GE_SRCAREAH_OFF		0x38
-#define GE_DESTBASE_OFF		0x3c
-#define GE_DESTDISPW_OFF	0x40
-#define GE_DESTDISPH_OFF	0x44
-#define GE_DESTAREAX_OFF	0x48
-#define GE_DESTAREAY_OFF	0x4c
-#define GE_DESTAREAW_OFF	0x50
-#define GE_DESTAREAH_OFF	0x54
-#define GE_PAT0C_OFF		0x88	/* Pattern 0 color */
-#define GE_ENABLE_OFF		0xec
-#define GE_INTEN_OFF		0xf0
-#define GE_STATUS_OFF		0xf8
-
-static void __iomem *regbase;
-
-void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
-{
-	unsigned long fg, pat;
-
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
-	    p->fix.visual == FB_VISUAL_DIRECTCOLOR)
-		fg = ((u32 *) (p->pseudo_palette))[rect->color];
-	else
-		fg = rect->color;
-
-	pat = pixel_to_pat(p->var.bits_per_pixel, fg);
-
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-
-	writel(p->var.bits_per_pixel == 32 ? 3 :
-	      (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
-	writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
-	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
-	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
-	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
-	writel(rect->dx, regbase + GE_DESTAREAX_OFF);
-	writel(rect->dy, regbase + GE_DESTAREAY_OFF);
-	writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
-	writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
-
-	writel(pat, regbase + GE_PAT0C_OFF);
-	writel(1, regbase + GE_COMMAND_OFF);
-	writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
-	writel(1, regbase + GE_FIRE_OFF);
-}
-EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
-
-void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
-{
-	if (p->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (p->fbops->fb_sync)
-		p->fbops->fb_sync(p);
-
-	writel(p->var.bits_per_pixel > 16 ? 3 :
-	      (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
-
-	writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
-	writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
-	writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
-	writel(area->sx, regbase + GE_SRCAREAX_OFF);
-	writel(area->sy, regbase + GE_SRCAREAY_OFF);
-	writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
-	writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
-
-	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
-	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
-	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
-	writel(area->dx, regbase + GE_DESTAREAX_OFF);
-	writel(area->dy, regbase + GE_DESTAREAY_OFF);
-	writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
-	writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
-
-	writel(0xcc, regbase + GE_ROPCODE_OFF);
-	writel(1, regbase + GE_COMMAND_OFF);
-	writel(1, regbase + GE_FIRE_OFF);
-}
-EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
-
-int wmt_ge_sync(struct fb_info *p)
-{
-	int loops = 5000000;
-	while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
-		cpu_relax();
-	return loops > 0 ? 0 : -EBUSY;
-}
-EXPORT_SYMBOL_GPL(wmt_ge_sync);
-
-static int wmt_ge_rops_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no I/O memory resource defined\n");
-		return -ENODEV;
-	}
-
-	/* Only one ROP engine is presently supported. */
-	if (unlikely(regbase)) {
-		WARN_ON(1);
-		return -EBUSY;
-	}
-
-	regbase = ioremap(res->start, resource_size(res));
-	if (regbase == NULL) {
-		dev_err(&pdev->dev, "failed to map I/O memory\n");
-		return -EBUSY;
-	}
-
-	writel(1, regbase + GE_ENABLE_OFF);
-	printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
-
-	return 0;
-}
-
-static int wmt_ge_rops_remove(struct platform_device *pdev)
-{
-	iounmap(regbase);
-	return 0;
-}
-
-static const struct of_device_id wmt_dt_ids[] = {
-	{ .compatible = "wm,prizm-ge-rops", },
-	{ /* sentinel */ }
-};
-
-static struct platform_driver wmt_ge_rops_driver = {
-	.probe		= wmt_ge_rops_probe,
-	.remove		= wmt_ge_rops_remove,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "wmt_ge_rops",
-		.of_match_table = wmt_dt_ids,
-	},
-};
-
-module_platform_driver(wmt_ge_rops_driver);
-
-MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
-MODULE_DESCRIPTION("Accelerators for raster operations using "
-		   "WonderMedia Graphics Engine");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, wmt_dt_ids);
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
deleted file mode 100644
index f73ec6377a46..000000000000
--- a/drivers/video/wmt_ge_rops.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifdef CONFIG_FB_WMT_GE_ROPS
-
-extern void wmt_ge_fillrect(struct fb_info *info,
-			    const struct fb_fillrect *rect);
-extern void wmt_ge_copyarea(struct fb_info *info,
-			    const struct fb_copyarea *area);
-extern int wmt_ge_sync(struct fb_info *info);
-
-#else
-
-static inline int wmt_ge_sync(struct fb_info *p)
-{
-	return 0;
-}
-
-static inline void wmt_ge_fillrect(struct fb_info *p,
-				    const struct fb_fillrect *rect)
-{
-	sys_fillrect(p, rect);
-}
-
-static inline void wmt_ge_copyarea(struct fb_info *p,
-				     const struct fb_copyarea *area)
-{
-	sys_copyarea(p, area);
-}
-
-#endif
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
deleted file mode 100644
index 901014bbc821..000000000000
--- a/drivers/video/xen-fbfront.c
+++ /dev/null
@@ -1,719 +0,0 @@
-/*
- * Xen para-virtual frame buffer device
- *
- * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
- * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
- *
- *  Based on linux/drivers/video/q40fb.c
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-/*
- * TODO:
- *
- * Switch to grant tables when they become capable of dealing with the
- * frame buffer.
- */
-
-#include <linux/console.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-
-#include <asm/xen/hypervisor.h>
-
-#include <xen/xen.h>
-#include <xen/events.h>
-#include <xen/page.h>
-#include <xen/interface/io/fbif.h>
-#include <xen/interface/io/protocols.h>
-#include <xen/xenbus.h>
-#include <xen/platform_pci.h>
-
-struct xenfb_info {
-	unsigned char		*fb;
-	struct fb_info		*fb_info;
-	int			x1, y1, x2, y2;	/* dirty rectangle,
-						   protected by dirty_lock */
-	spinlock_t		dirty_lock;
-	int			nr_pages;
-	int			irq;
-	struct xenfb_page	*page;
-	unsigned long 		*mfns;
-	int			update_wanted; /* XENFB_TYPE_UPDATE wanted */
-	int			feature_resize; /* XENFB_TYPE_RESIZE ok */
-	struct xenfb_resize	resize;		/* protected by resize_lock */
-	int			resize_dpy;	/* ditto */
-	spinlock_t		resize_lock;
-
-	struct xenbus_device	*xbdev;
-};
-
-#define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
-
-enum { KPARAM_MEM, KPARAM_WIDTH, KPARAM_HEIGHT, KPARAM_CNT };
-static int video[KPARAM_CNT] = { 2, XENFB_WIDTH, XENFB_HEIGHT };
-module_param_array(video, int, NULL, 0);
-MODULE_PARM_DESC(video,
-	"Video memory size in MB, width, height in pixels (default 2,800,600)");
-
-static void xenfb_make_preferred_console(void);
-static int xenfb_remove(struct xenbus_device *);
-static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *);
-static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
-static void xenfb_disconnect_backend(struct xenfb_info *);
-
-static void xenfb_send_event(struct xenfb_info *info,
-			     union xenfb_out_event *event)
-{
-	u32 prod;
-
-	prod = info->page->out_prod;
-	/* caller ensures !xenfb_queue_full() */
-	mb();			/* ensure ring space available */
-	XENFB_OUT_RING_REF(info->page, prod) = *event;
-	wmb();			/* ensure ring contents visible */
-	info->page->out_prod = prod + 1;
-
-	notify_remote_via_irq(info->irq);
-}
-
-static void xenfb_do_update(struct xenfb_info *info,
-			    int x, int y, int w, int h)
-{
-	union xenfb_out_event event;
-
-	memset(&event, 0, sizeof(event));
-	event.type = XENFB_TYPE_UPDATE;
-	event.update.x = x;
-	event.update.y = y;
-	event.update.width = w;
-	event.update.height = h;
-
-	/* caller ensures !xenfb_queue_full() */
-	xenfb_send_event(info, &event);
-}
-
-static void xenfb_do_resize(struct xenfb_info *info)
-{
-	union xenfb_out_event event;
-
-	memset(&event, 0, sizeof(event));
-	event.resize = info->resize;
-
-	/* caller ensures !xenfb_queue_full() */
-	xenfb_send_event(info, &event);
-}
-
-static int xenfb_queue_full(struct xenfb_info *info)
-{
-	u32 cons, prod;
-
-	prod = info->page->out_prod;
-	cons = info->page->out_cons;
-	return prod - cons == XENFB_OUT_RING_LEN;
-}
-
-static void xenfb_handle_resize_dpy(struct xenfb_info *info)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->resize_lock, flags);
-	if (info->resize_dpy) {
-		if (!xenfb_queue_full(info)) {
-			info->resize_dpy = 0;
-			xenfb_do_resize(info);
-		}
-	}
-	spin_unlock_irqrestore(&info->resize_lock, flags);
-}
-
-static void xenfb_refresh(struct xenfb_info *info,
-			  int x1, int y1, int w, int h)
-{
-	unsigned long flags;
-	int x2 = x1 + w - 1;
-	int y2 = y1 + h - 1;
-
-	xenfb_handle_resize_dpy(info);
-
-	if (!info->update_wanted)
-		return;
-
-	spin_lock_irqsave(&info->dirty_lock, flags);
-
-	/* Combine with dirty rectangle: */
-	if (info->y1 < y1)
-		y1 = info->y1;
-	if (info->y2 > y2)
-		y2 = info->y2;
-	if (info->x1 < x1)
-		x1 = info->x1;
-	if (info->x2 > x2)
-		x2 = info->x2;
-
-	if (xenfb_queue_full(info)) {
-		/* Can't send right now, stash it in the dirty rectangle */
-		info->x1 = x1;
-		info->x2 = x2;
-		info->y1 = y1;
-		info->y2 = y2;
-		spin_unlock_irqrestore(&info->dirty_lock, flags);
-		return;
-	}
-
-	/* Clear dirty rectangle: */
-	info->x1 = info->y1 = INT_MAX;
-	info->x2 = info->y2 = 0;
-
-	spin_unlock_irqrestore(&info->dirty_lock, flags);
-
-	if (x1 <= x2 && y1 <= y2)
-		xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
-}
-
-static void xenfb_deferred_io(struct fb_info *fb_info,
-			      struct list_head *pagelist)
-{
-	struct xenfb_info *info = fb_info->par;
-	struct page *page;
-	unsigned long beg, end;
-	int y1, y2, miny, maxy;
-
-	miny = INT_MAX;
-	maxy = 0;
-	list_for_each_entry(page, pagelist, lru) {
-		beg = page->index << PAGE_SHIFT;
-		end = beg + PAGE_SIZE - 1;
-		y1 = beg / fb_info->fix.line_length;
-		y2 = end / fb_info->fix.line_length;
-		if (y2 >= fb_info->var.yres)
-			y2 = fb_info->var.yres - 1;
-		if (miny > y1)
-			miny = y1;
-		if (maxy < y2)
-			maxy = y2;
-	}
-	xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
-}
-
-static struct fb_deferred_io xenfb_defio = {
-	.delay		= HZ / 20,
-	.deferred_io	= xenfb_deferred_io,
-};
-
-static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	u32 v;
-
-	if (regno > info->cmap.len)
-		return 1;
-
-#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
-	red = CNVT_TOHW(red, info->var.red.length);
-	green = CNVT_TOHW(green, info->var.green.length);
-	blue = CNVT_TOHW(blue, info->var.blue.length);
-	transp = CNVT_TOHW(transp, info->var.transp.length);
-#undef CNVT_TOHW
-
-	v = (red << info->var.red.offset) |
-	    (green << info->var.green.offset) |
-	    (blue << info->var.blue.offset);
-
-	switch (info->var.bits_per_pixel) {
-	case 16:
-	case 24:
-	case 32:
-		((u32 *)info->pseudo_palette)[regno] = v;
-		break;
-	}
-
-	return 0;
-}
-
-static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
-{
-	struct xenfb_info *info = p->par;
-
-	sys_fillrect(p, rect);
-	xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
-}
-
-static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
-{
-	struct xenfb_info *info = p->par;
-
-	sys_imageblit(p, image);
-	xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
-}
-
-static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
-{
-	struct xenfb_info *info = p->par;
-
-	sys_copyarea(p, area);
-	xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
-}
-
-static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
-			size_t count, loff_t *ppos)
-{
-	struct xenfb_info *info = p->par;
-	ssize_t res;
-
-	res = fb_sys_write(p, buf, count, ppos);
-	xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
-	return res;
-}
-
-static int
-xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct xenfb_info *xenfb_info;
-	int required_mem_len;
-
-	xenfb_info = info->par;
-
-	if (!xenfb_info->feature_resize) {
-		if (var->xres == video[KPARAM_WIDTH] &&
-		    var->yres == video[KPARAM_HEIGHT] &&
-		    var->bits_per_pixel == xenfb_info->page->depth) {
-			return 0;
-		}
-		return -EINVAL;
-	}
-
-	/* Can't resize past initial width and height */
-	if (var->xres > video[KPARAM_WIDTH] || var->yres > video[KPARAM_HEIGHT])
-		return -EINVAL;
-
-	required_mem_len = var->xres * var->yres * xenfb_info->page->depth / 8;
-	if (var->bits_per_pixel == xenfb_info->page->depth &&
-	    var->xres <= info->fix.line_length / (XENFB_DEPTH / 8) &&
-	    required_mem_len <= info->fix.smem_len) {
-		var->xres_virtual = var->xres;
-		var->yres_virtual = var->yres;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int xenfb_set_par(struct fb_info *info)
-{
-	struct xenfb_info *xenfb_info;
-	unsigned long flags;
-
-	xenfb_info = info->par;
-
-	spin_lock_irqsave(&xenfb_info->resize_lock, flags);
-	xenfb_info->resize.type = XENFB_TYPE_RESIZE;
-	xenfb_info->resize.width = info->var.xres;
-	xenfb_info->resize.height = info->var.yres;
-	xenfb_info->resize.stride = info->fix.line_length;
-	xenfb_info->resize.depth = info->var.bits_per_pixel;
-	xenfb_info->resize.offset = 0;
-	xenfb_info->resize_dpy = 1;
-	spin_unlock_irqrestore(&xenfb_info->resize_lock, flags);
-	return 0;
-}
-
-static struct fb_ops xenfb_fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_read	= fb_sys_read,
-	.fb_write	= xenfb_write,
-	.fb_setcolreg	= xenfb_setcolreg,
-	.fb_fillrect	= xenfb_fillrect,
-	.fb_copyarea	= xenfb_copyarea,
-	.fb_imageblit	= xenfb_imageblit,
-	.fb_check_var	= xenfb_check_var,
-	.fb_set_par     = xenfb_set_par,
-};
-
-static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
-{
-	/*
-	 * No in events recognized, simply ignore them all.
-	 * If you need to recognize some, see xen-kbdfront's
-	 * input_handler() for how to do that.
-	 */
-	struct xenfb_info *info = dev_id;
-	struct xenfb_page *page = info->page;
-
-	if (page->in_cons != page->in_prod) {
-		info->page->in_cons = info->page->in_prod;
-		notify_remote_via_irq(info->irq);
-	}
-
-	/* Flush dirty rectangle: */
-	xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
-
-	return IRQ_HANDLED;
-}
-
-static int xenfb_probe(struct xenbus_device *dev,
-		       const struct xenbus_device_id *id)
-{
-	struct xenfb_info *info;
-	struct fb_info *fb_info;
-	int fb_size;
-	int val;
-	int ret = 0;
-
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (info == NULL) {
-		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
-		return -ENOMEM;
-	}
-
-	/* Limit kernel param videoram amount to what is in xenstore */
-	if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {
-		if (val < video[KPARAM_MEM])
-			video[KPARAM_MEM] = val;
-	}
-
-	/* If requested res does not fit in available memory, use default */
-	fb_size = video[KPARAM_MEM] * 1024 * 1024;
-	if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8
-	    > fb_size) {
-		video[KPARAM_WIDTH] = XENFB_WIDTH;
-		video[KPARAM_HEIGHT] = XENFB_HEIGHT;
-		fb_size = XENFB_DEFAULT_FB_LEN;
-	}
-
-	dev_set_drvdata(&dev->dev, info);
-	info->xbdev = dev;
-	info->irq = -1;
-	info->x1 = info->y1 = INT_MAX;
-	spin_lock_init(&info->dirty_lock);
-	spin_lock_init(&info->resize_lock);
-
-	info->fb = vzalloc(fb_size);
-	if (info->fb == NULL)
-		goto error_nomem;
-
-	info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
-	info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
-	if (!info->mfns)
-		goto error_nomem;
-
-	/* set up shared page */
-	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-	if (!info->page)
-		goto error_nomem;
-
-	/* abusing framebuffer_alloc() to allocate pseudo_palette */
-	fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
-	if (fb_info == NULL)
-		goto error_nomem;
-
-	/* complete the abuse: */
-	fb_info->pseudo_palette = fb_info->par;
-	fb_info->par = info;
-
-	fb_info->screen_base = info->fb;
-
-	fb_info->fbops = &xenfb_fb_ops;
-	fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];
-	fb_info->var.yres_virtual = fb_info->var.yres = video[KPARAM_HEIGHT];
-	fb_info->var.bits_per_pixel = XENFB_DEPTH;
-
-	fb_info->var.red = (struct fb_bitfield){16, 8, 0};
-	fb_info->var.green = (struct fb_bitfield){8, 8, 0};
-	fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
-
-	fb_info->var.activate = FB_ACTIVATE_NOW;
-	fb_info->var.height = -1;
-	fb_info->var.width = -1;
-	fb_info->var.vmode = FB_VMODE_NONINTERLACED;
-
-	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
-	fb_info->fix.line_length = fb_info->var.xres * XENFB_DEPTH / 8;
-	fb_info->fix.smem_start = 0;
-	fb_info->fix.smem_len = fb_size;
-	strcpy(fb_info->fix.id, "xen");
-	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
-	fb_info->fix.accel = FB_ACCEL_NONE;
-
-	fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
-
-	ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
-	if (ret < 0) {
-		framebuffer_release(fb_info);
-		xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
-		goto error;
-	}
-
-	fb_info->fbdefio = &xenfb_defio;
-	fb_deferred_io_init(fb_info);
-
-	xenfb_init_shared_page(info, fb_info);
-
-	ret = xenfb_connect_backend(dev, info);
-	if (ret < 0) {
-		xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
-		goto error_fb;
-	}
-
-	ret = register_framebuffer(fb_info);
-	if (ret) {
-		xenbus_dev_fatal(dev, ret, "register_framebuffer");
-		goto error_fb;
-	}
-	info->fb_info = fb_info;
-
-	xenfb_make_preferred_console();
-	return 0;
-
-error_fb:
-	fb_deferred_io_cleanup(fb_info);
-	fb_dealloc_cmap(&fb_info->cmap);
-	framebuffer_release(fb_info);
-error_nomem:
-	if (!ret) {
-		ret = -ENOMEM;
-		xenbus_dev_fatal(dev, ret, "allocating device memory");
-	}
-error:
-	xenfb_remove(dev);
-	return ret;
-}
-
-static void xenfb_make_preferred_console(void)
-{
-	struct console *c;
-
-	if (console_set_on_cmdline)
-		return;
-
-	console_lock();
-	for_each_console(c) {
-		if (!strcmp(c->name, "tty") && c->index == 0)
-			break;
-	}
-	console_unlock();
-	if (c) {
-		unregister_console(c);
-		c->flags |= CON_CONSDEV;
-		c->flags &= ~CON_PRINTBUFFER; /* don't print again */
-		register_console(c);
-	}
-}
-
-static int xenfb_resume(struct xenbus_device *dev)
-{
-	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
-
-	xenfb_disconnect_backend(info);
-	xenfb_init_shared_page(info, info->fb_info);
-	return xenfb_connect_backend(dev, info);
-}
-
-static int xenfb_remove(struct xenbus_device *dev)
-{
-	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
-
-	xenfb_disconnect_backend(info);
-	if (info->fb_info) {
-		fb_deferred_io_cleanup(info->fb_info);
-		unregister_framebuffer(info->fb_info);
-		fb_dealloc_cmap(&info->fb_info->cmap);
-		framebuffer_release(info->fb_info);
-	}
-	free_page((unsigned long)info->page);
-	vfree(info->mfns);
-	vfree(info->fb);
-	kfree(info);
-
-	return 0;
-}
-
-static unsigned long vmalloc_to_mfn(void *address)
-{
-	return pfn_to_mfn(vmalloc_to_pfn(address));
-}
-
-static void xenfb_init_shared_page(struct xenfb_info *info,
-				   struct fb_info *fb_info)
-{
-	int i;
-	int epd = PAGE_SIZE / sizeof(info->mfns[0]);
-
-	for (i = 0; i < info->nr_pages; i++)
-		info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
-
-	for (i = 0; i * epd < info->nr_pages; i++)
-		info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * epd]);
-
-	info->page->width = fb_info->var.xres;
-	info->page->height = fb_info->var.yres;
-	info->page->depth = fb_info->var.bits_per_pixel;
-	info->page->line_length = fb_info->fix.line_length;
-	info->page->mem_length = fb_info->fix.smem_len;
-	info->page->in_cons = info->page->in_prod = 0;
-	info->page->out_cons = info->page->out_prod = 0;
-}
-
-static int xenfb_connect_backend(struct xenbus_device *dev,
-				 struct xenfb_info *info)
-{
-	int ret, evtchn, irq;
-	struct xenbus_transaction xbt;
-
-	ret = xenbus_alloc_evtchn(dev, &evtchn);
-	if (ret)
-		return ret;
-	irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
-					0, dev->devicetype, info);
-	if (irq < 0) {
-		xenbus_free_evtchn(dev, evtchn);
-		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
-		return irq;
-	}
- again:
-	ret = xenbus_transaction_start(&xbt);
-	if (ret) {
-		xenbus_dev_fatal(dev, ret, "starting transaction");
-		goto unbind_irq;
-	}
-	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
-			    virt_to_mfn(info->page));
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
-			    evtchn);
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
-			    XEN_IO_PROTO_ABI_NATIVE);
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_transaction_end(xbt, 0);
-	if (ret) {
-		if (ret == -EAGAIN)
-			goto again;
-		xenbus_dev_fatal(dev, ret, "completing transaction");
-		goto unbind_irq;
-	}
-
-	xenbus_switch_state(dev, XenbusStateInitialised);
-	info->irq = irq;
-	return 0;
-
- error_xenbus:
-	xenbus_transaction_end(xbt, 1);
-	xenbus_dev_fatal(dev, ret, "writing xenstore");
- unbind_irq:
-	unbind_from_irqhandler(irq, info);
-	return ret;
-}
-
-static void xenfb_disconnect_backend(struct xenfb_info *info)
-{
-	/* Prevent xenfb refresh */
-	info->update_wanted = 0;
-	if (info->irq >= 0)
-		unbind_from_irqhandler(info->irq, info);
-	info->irq = -1;
-}
-
-static void xenfb_backend_changed(struct xenbus_device *dev,
-				  enum xenbus_state backend_state)
-{
-	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
-	int val;
-
-	switch (backend_state) {
-	case XenbusStateInitialising:
-	case XenbusStateInitialised:
-	case XenbusStateReconfiguring:
-	case XenbusStateReconfigured:
-	case XenbusStateUnknown:
-		break;
-
-	case XenbusStateInitWait:
-InitWait:
-		xenbus_switch_state(dev, XenbusStateConnected);
-		break;
-
-	case XenbusStateConnected:
-		/*
-		 * Work around xenbus race condition: If backend goes
-		 * through InitWait to Connected fast enough, we can
-		 * get Connected twice here.
-		 */
-		if (dev->state != XenbusStateConnected)
-			goto InitWait; /* no InitWait seen yet, fudge it */
-
-		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				 "request-update", "%d", &val) < 0)
-			val = 0;
-		if (val)
-			info->update_wanted = 1;
-
-		if (xenbus_scanf(XBT_NIL, dev->otherend,
-				 "feature-resize", "%d", &val) < 0)
-			val = 0;
-		info->feature_resize = val;
-		break;
-
-	case XenbusStateClosed:
-		if (dev->state == XenbusStateClosed)
-			break;
-		/* Missed the backend's CLOSING state -- fallthrough */
-	case XenbusStateClosing:
-		xenbus_frontend_closed(dev);
-		break;
-	}
-}
-
-static const struct xenbus_device_id xenfb_ids[] = {
-	{ "vfb" },
-	{ "" }
-};
-
-static DEFINE_XENBUS_DRIVER(xenfb, ,
-	.probe = xenfb_probe,
-	.remove = xenfb_remove,
-	.resume = xenfb_resume,
-	.otherend_changed = xenfb_backend_changed,
-);
-
-static int __init xenfb_init(void)
-{
-	if (!xen_domain())
-		return -ENODEV;
-
-	/* Nothing to do if running in dom0. */
-	if (xen_initial_domain())
-		return -ENODEV;
-
-	if (!xen_has_pv_devices())
-		return -ENODEV;
-
-	return xenbus_register_frontend(&xenfb_driver);
-}
-
-static void __exit xenfb_cleanup(void)
-{
-	xenbus_unregister_driver(&xenfb_driver);
-}
-
-module_init(xenfb_init);
-module_exit(xenfb_cleanup);
-
-MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("xen:vfb");
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
deleted file mode 100644
index 553cff2f3f4c..000000000000
--- a/drivers/video/xilinxfb.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Xilinx TFT frame buffer driver
- *
- * Author: MontaVista Software, Inc.
- *         source@mvista.com
- *
- * 2002-2007 (c) MontaVista Software, Inc.
- * 2007 (c) Secret Lab Technologies, Ltd.
- * 2009 (c) Xilinx Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/*
- * This driver was based on au1100fb.c by MontaVista rewritten for 2.6
- * by Embedded Alley Solutions <source@embeddedalley.com>, which in turn
- * was based on skeletonfb.c, Skeleton for a frame buffer device by
- * Geert Uytterhoeven.
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PPC_DCR
-#include <asm/dcr.h>
-#endif
-
-#define DRIVER_NAME		"xilinxfb"
-
-
-/*
- * Xilinx calls it "TFT LCD Controller" though it can also be used for
- * the VGA port on the Xilinx ML40x board. This is a hardware display
- * controller for a 640x480 resolution TFT or VGA screen.
- *
- * The interface to the framebuffer is nice and simple.  There are two
- * control registers.  The first tells the LCD interface where in memory
- * the frame buffer is (only the 11 most significant bits are used, so
- * don't start thinking about scrolling).  The second allows the LCD to
- * be turned on or off as well as rotated 180 degrees.
- *
- * In case of direct BUS access the second control register will be at
- * an offset of 4 as compared to the DCR access where the offset is 1
- * i.e. REG_CTRL. So this is taken care in the function
- * xilinx_fb_out32 where it left shifts the offset 2 times in case of
- * direct BUS access.
- */
-#define NUM_REGS	2
-#define REG_FB_ADDR	0
-#define REG_CTRL	1
-#define REG_CTRL_ENABLE	 0x0001
-#define REG_CTRL_ROTATE	 0x0002
-
-/*
- * The hardware only handles a single mode: 640x480 24 bit true
- * color. Each pixel gets a word (32 bits) of memory.  Within each word,
- * the 8 most significant bits are ignored, the next 8 bits are the red
- * level, the next 8 bits are the green level and the 8 least
- * significant bits are the blue level.  Each row of the LCD uses 1024
- * words, but only the first 640 pixels are displayed with the other 384
- * words being ignored.  There are 480 rows.
- */
-#define BYTES_PER_PIXEL	4
-#define BITS_PER_PIXEL	(BYTES_PER_PIXEL * 8)
-
-#define RED_SHIFT	16
-#define GREEN_SHIFT	8
-#define BLUE_SHIFT	0
-
-#define PALETTE_ENTRIES_NO	16	/* passed to fb_alloc_cmap() */
-
-/* ML300/403 reference design framebuffer driver platform data struct */
-struct xilinxfb_platform_data {
-	u32 rotate_screen;      /* Flag to rotate display 180 degrees */
-	u32 screen_height_mm;   /* Physical dimensions of screen in mm */
-	u32 screen_width_mm;
-	u32 xres, yres;         /* resolution of screen in pixels */
-	u32 xvirt, yvirt;       /* resolution of memory buffer */
-
-	/* Physical address of framebuffer memory; If non-zero, driver
-	* will use provided memory address instead of allocating one from
-	* the consistent pool. */
-	u32 fb_phys;
-};
-
-/*
- * Default xilinxfb configuration
- */
-static struct xilinxfb_platform_data xilinx_fb_default_pdata = {
-	.xres = 640,
-	.yres = 480,
-	.xvirt = 1024,
-	.yvirt = 480,
-};
-
-/*
- * Here are the default fb_fix_screeninfo and fb_var_screeninfo structures
- */
-static struct fb_fix_screeninfo xilinx_fb_fix = {
-	.id =		"Xilinx",
-	.type =		FB_TYPE_PACKED_PIXELS,
-	.visual =	FB_VISUAL_TRUECOLOR,
-	.accel =	FB_ACCEL_NONE
-};
-
-static struct fb_var_screeninfo xilinx_fb_var = {
-	.bits_per_pixel =	BITS_PER_PIXEL,
-
-	.red =		{ RED_SHIFT, 8, 0 },
-	.green =	{ GREEN_SHIFT, 8, 0 },
-	.blue =		{ BLUE_SHIFT, 8, 0 },
-	.transp =	{ 0, 0, 0 },
-
-	.activate =	FB_ACTIVATE_NOW
-};
-
-
-#define BUS_ACCESS_FLAG		0x1 /* 1 = BUS, 0 = DCR */
-#define LITTLE_ENDIAN_ACCESS	0x2 /* LITTLE ENDIAN IO functions */
-
-struct xilinxfb_drvdata {
-
-	struct fb_info	info;		/* FB driver info record */
-
-	phys_addr_t	regs_phys;	/* phys. address of the control
-						registers */
-	void __iomem	*regs;		/* virt. address of the control
-						registers */
-#ifdef CONFIG_PPC_DCR
-	dcr_host_t      dcr_host;
-	unsigned int    dcr_len;
-#endif
-	void		*fb_virt;	/* virt. address of the frame buffer */
-	dma_addr_t	fb_phys;	/* phys. address of the frame buffer */
-	int		fb_alloced;	/* Flag, was the fb memory alloced? */
-
-	u8 		flags;		/* features of the driver */
-
-	u32		reg_ctrl_default;
-
-	u32		pseudo_palette[PALETTE_ENTRIES_NO];
-					/* Fake palette of 16 colors */
-};
-
-#define to_xilinxfb_drvdata(_info) \
-	container_of(_info, struct xilinxfb_drvdata, info)
-
-/*
- * The XPS TFT Controller can be accessed through BUS or DCR interface.
- * To perform the read/write on the registers we need to check on
- * which bus its connected and call the appropriate write API.
- */
-static void xilinx_fb_out32(struct xilinxfb_drvdata *drvdata, u32 offset,
-				u32 val)
-{
-	if (drvdata->flags & BUS_ACCESS_FLAG) {
-		if (drvdata->flags & LITTLE_ENDIAN_ACCESS)
-			iowrite32(val, drvdata->regs + (offset << 2));
-		else
-			iowrite32be(val, drvdata->regs + (offset << 2));
-	}
-#ifdef CONFIG_PPC_DCR
-	else
-		dcr_write(drvdata->dcr_host, offset, val);
-#endif
-}
-
-static u32 xilinx_fb_in32(struct xilinxfb_drvdata *drvdata, u32 offset)
-{
-	if (drvdata->flags & BUS_ACCESS_FLAG) {
-		if (drvdata->flags & LITTLE_ENDIAN_ACCESS)
-			return ioread32(drvdata->regs + (offset << 2));
-		else
-			return ioread32be(drvdata->regs + (offset << 2));
-	}
-#ifdef CONFIG_PPC_DCR
-	else
-		return dcr_read(drvdata->dcr_host, offset);
-#endif
-	return 0;
-}
-
-static int
-xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-	unsigned transp, struct fb_info *fbi)
-{
-	u32 *palette = fbi->pseudo_palette;
-
-	if (regno >= PALETTE_ENTRIES_NO)
-		return -EINVAL;
-
-	if (fbi->var.grayscale) {
-		/* Convert color to grayscale.
-		 * grayscale = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue =
-			(red * 77 + green * 151 + blue * 28 + 127) >> 8;
-	}
-
-	/* fbi->fix.visual is always FB_VISUAL_TRUECOLOR */
-
-	/* We only handle 8 bits of each color. */
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	palette[regno] = (red << RED_SHIFT) | (green << GREEN_SHIFT) |
-			 (blue << BLUE_SHIFT);
-
-	return 0;
-}
-
-static int
-xilinx_fb_blank(int blank_mode, struct fb_info *fbi)
-{
-	struct xilinxfb_drvdata *drvdata = to_xilinxfb_drvdata(fbi);
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		/* turn on panel */
-		xilinx_fb_out32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
-		break;
-
-	case FB_BLANK_NORMAL:
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_POWERDOWN:
-		/* turn off panel */
-		xilinx_fb_out32(drvdata, REG_CTRL, 0);
-	default:
-		break;
-
-	}
-	return 0; /* success */
-}
-
-static struct fb_ops xilinxfb_ops =
-{
-	.owner			= THIS_MODULE,
-	.fb_setcolreg		= xilinx_fb_setcolreg,
-	.fb_blank		= xilinx_fb_blank,
-	.fb_fillrect		= cfb_fillrect,
-	.fb_copyarea		= cfb_copyarea,
-	.fb_imageblit		= cfb_imageblit,
-};
-
-/* ---------------------------------------------------------------------
- * Bus independent setup/teardown
- */
-
-static int xilinxfb_assign(struct platform_device *pdev,
-			   struct xilinxfb_drvdata *drvdata,
-			   struct xilinxfb_platform_data *pdata)
-{
-	int rc;
-	struct device *dev = &pdev->dev;
-	int fbsize = pdata->xvirt * pdata->yvirt * BYTES_PER_PIXEL;
-
-	if (drvdata->flags & BUS_ACCESS_FLAG) {
-		struct resource *res;
-
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		drvdata->regs = devm_ioremap_resource(&pdev->dev, res);
-		if (IS_ERR(drvdata->regs))
-			return PTR_ERR(drvdata->regs);
-
-		drvdata->regs_phys = res->start;
-	}
-
-	/* Allocate the framebuffer memory */
-	if (pdata->fb_phys) {
-		drvdata->fb_phys = pdata->fb_phys;
-		drvdata->fb_virt = ioremap(pdata->fb_phys, fbsize);
-	} else {
-		drvdata->fb_alloced = 1;
-		drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(fbsize),
-					&drvdata->fb_phys, GFP_KERNEL);
-	}
-
-	if (!drvdata->fb_virt) {
-		dev_err(dev, "Could not allocate frame buffer memory\n");
-		return -ENOMEM;
-	}
-
-	/* Clear (turn to black) the framebuffer */
-	memset_io((void __iomem *)drvdata->fb_virt, 0, fbsize);
-
-	/* Tell the hardware where the frame buffer is */
-	xilinx_fb_out32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
-	rc = xilinx_fb_in32(drvdata, REG_FB_ADDR);
-	/* Endianess detection */
-	if (rc != drvdata->fb_phys) {
-		drvdata->flags |= LITTLE_ENDIAN_ACCESS;
-		xilinx_fb_out32(drvdata, REG_FB_ADDR, drvdata->fb_phys);
-	}
-
-	/* Turn on the display */
-	drvdata->reg_ctrl_default = REG_CTRL_ENABLE;
-	if (pdata->rotate_screen)
-		drvdata->reg_ctrl_default |= REG_CTRL_ROTATE;
-	xilinx_fb_out32(drvdata, REG_CTRL,
-					drvdata->reg_ctrl_default);
-
-	/* Fill struct fb_info */
-	drvdata->info.device = dev;
-	drvdata->info.screen_base = (void __iomem *)drvdata->fb_virt;
-	drvdata->info.fbops = &xilinxfb_ops;
-	drvdata->info.fix = xilinx_fb_fix;
-	drvdata->info.fix.smem_start = drvdata->fb_phys;
-	drvdata->info.fix.smem_len = fbsize;
-	drvdata->info.fix.line_length = pdata->xvirt * BYTES_PER_PIXEL;
-
-	drvdata->info.pseudo_palette = drvdata->pseudo_palette;
-	drvdata->info.flags = FBINFO_DEFAULT;
-	drvdata->info.var = xilinx_fb_var;
-	drvdata->info.var.height = pdata->screen_height_mm;
-	drvdata->info.var.width = pdata->screen_width_mm;
-	drvdata->info.var.xres = pdata->xres;
-	drvdata->info.var.yres = pdata->yres;
-	drvdata->info.var.xres_virtual = pdata->xvirt;
-	drvdata->info.var.yres_virtual = pdata->yvirt;
-
-	/* Allocate a colour map */
-	rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0);
-	if (rc) {
-		dev_err(dev, "Fail to allocate colormap (%d entries)\n",
-			PALETTE_ENTRIES_NO);
-		goto err_cmap;
-	}
-
-	/* Register new frame buffer */
-	rc = register_framebuffer(&drvdata->info);
-	if (rc) {
-		dev_err(dev, "Could not register frame buffer\n");
-		goto err_regfb;
-	}
-
-	if (drvdata->flags & BUS_ACCESS_FLAG) {
-		/* Put a banner in the log (for DEBUG) */
-		dev_dbg(dev, "regs: phys=%pa, virt=%p\n",
-			&drvdata->regs_phys, drvdata->regs);
-	}
-	/* Put a banner in the log (for DEBUG) */
-	dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n",
-		(unsigned long long)drvdata->fb_phys, drvdata->fb_virt, fbsize);
-
-	return 0;	/* success */
-
-err_regfb:
-	fb_dealloc_cmap(&drvdata->info.cmap);
-
-err_cmap:
-	if (drvdata->fb_alloced)
-		dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
-			drvdata->fb_phys);
-	else
-		iounmap(drvdata->fb_virt);
-
-	/* Turn off the display */
-	xilinx_fb_out32(drvdata, REG_CTRL, 0);
-
-	return rc;
-}
-
-static int xilinxfb_release(struct device *dev)
-{
-	struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev);
-
-#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
-	xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info);
-#endif
-
-	unregister_framebuffer(&drvdata->info);
-
-	fb_dealloc_cmap(&drvdata->info.cmap);
-
-	if (drvdata->fb_alloced)
-		dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
-				  drvdata->fb_virt, drvdata->fb_phys);
-	else
-		iounmap(drvdata->fb_virt);
-
-	/* Turn off the display */
-	xilinx_fb_out32(drvdata, REG_CTRL, 0);
-
-#ifdef CONFIG_PPC_DCR
-	/* Release the resources, as allocated based on interface */
-	if (!(drvdata->flags & BUS_ACCESS_FLAG))
-		dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
-#endif
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------
- * OF bus binding
- */
-
-static int xilinxfb_of_probe(struct platform_device *pdev)
-{
-	const u32 *prop;
-	u32 tft_access = 0;
-	struct xilinxfb_platform_data pdata;
-	int size;
-	struct xilinxfb_drvdata *drvdata;
-
-	/* Copy with the default pdata (not a ptr reference!) */
-	pdata = xilinx_fb_default_pdata;
-
-	/* Allocate the driver data region */
-	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata)
-		return -ENOMEM;
-
-	/*
-	 * To check whether the core is connected directly to DCR or BUS
-	 * interface and initialize the tft_access accordingly.
-	 */
-	of_property_read_u32(pdev->dev.of_node, "xlnx,dcr-splb-slave-if",
-			     &tft_access);
-
-	/*
-	 * Fill the resource structure if its direct BUS interface
-	 * otherwise fill the dcr_host structure.
-	 */
-	if (tft_access) {
-		drvdata->flags |= BUS_ACCESS_FLAG;
-	}
-#ifdef CONFIG_PPC_DCR
-	else {
-		int start;
-		start = dcr_resource_start(pdev->dev.of_node, 0);
-		drvdata->dcr_len = dcr_resource_len(pdev->dev.of_node, 0);
-		drvdata->dcr_host = dcr_map(pdev->dev.of_node, start, drvdata->dcr_len);
-		if (!DCR_MAP_OK(drvdata->dcr_host)) {
-			dev_err(&pdev->dev, "invalid DCR address\n");
-			return -ENODEV;
-		}
-	}
-#endif
-
-	prop = of_get_property(pdev->dev.of_node, "phys-size", &size);
-	if ((prop) && (size >= sizeof(u32)*2)) {
-		pdata.screen_width_mm = prop[0];
-		pdata.screen_height_mm = prop[1];
-	}
-
-	prop = of_get_property(pdev->dev.of_node, "resolution", &size);
-	if ((prop) && (size >= sizeof(u32)*2)) {
-		pdata.xres = prop[0];
-		pdata.yres = prop[1];
-	}
-
-	prop = of_get_property(pdev->dev.of_node, "virtual-resolution", &size);
-	if ((prop) && (size >= sizeof(u32)*2)) {
-		pdata.xvirt = prop[0];
-		pdata.yvirt = prop[1];
-	}
-
-	if (of_find_property(pdev->dev.of_node, "rotate-display", NULL))
-		pdata.rotate_screen = 1;
-
-	dev_set_drvdata(&pdev->dev, drvdata);
-	return xilinxfb_assign(pdev, drvdata, &pdata);
-}
-
-static int xilinxfb_of_remove(struct platform_device *op)
-{
-	return xilinxfb_release(&op->dev);
-}
-
-/* Match table for of_platform binding */
-static struct of_device_id xilinxfb_of_match[] = {
-	{ .compatible = "xlnx,xps-tft-1.00.a", },
-	{ .compatible = "xlnx,xps-tft-2.00.a", },
-	{ .compatible = "xlnx,xps-tft-2.01.a", },
-	{ .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", },
-	{ .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
-
-static struct platform_driver xilinxfb_of_driver = {
-	.probe = xilinxfb_of_probe,
-	.remove = xilinxfb_of_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
-		.of_match_table = xilinxfb_of_match,
-	},
-};
-
-module_platform_driver(xilinxfb_of_driver);
-
-MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
-MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index 06990c6a1a69..61e706c0e00c 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -320,7 +320,7 @@ static int tsi148_irq_init(struct vme_bridge *tsi148_bridge)
 	struct pci_dev *pdev;
 	struct tsi148_driver *bridge;
 
-	pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
+	pdev = to_pci_dev(tsi148_bridge->parent);
 
 	bridge = tsi148_bridge->driver_priv;
 
@@ -433,9 +433,7 @@ static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level,
 		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
 
 		if (sync != 0) {
-			pdev = container_of(tsi148_bridge->parent,
-				struct pci_dev, dev);
-
+			pdev = to_pci_dev(tsi148_bridge->parent);
 			synchronize_irq(pdev->irq);
 		}
 	} else {
@@ -741,7 +739,7 @@ static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
 	reg_join(vme_bound_high, vme_bound_low, &vme_bound);
 	reg_join(pci_offset_high, pci_offset_low, &pci_offset);
 
-	*pci_base = (dma_addr_t)vme_base + pci_offset;
+	*pci_base = (dma_addr_t)(*vme_base + pci_offset);
 
 	*enabled = 0;
 	*aspace = 0;
@@ -814,7 +812,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
 
 	tsi148_bridge = image->parent;
 
-	pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
+	pdev = to_pci_dev(tsi148_bridge->parent);
 
 	existing_size = (unsigned long long)(image->bus_resource.end -
 		image->bus_resource.start);
@@ -910,11 +908,15 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled,
 	unsigned long long pci_bound, vme_offset, pci_base;
 	struct vme_bridge *tsi148_bridge;
 	struct tsi148_driver *bridge;
+	struct pci_bus_region region;
+	struct pci_dev *pdev;
 
 	tsi148_bridge = image->parent;
 
 	bridge = tsi148_bridge->driver_priv;
 
+	pdev = to_pci_dev(tsi148_bridge->parent);
+
 	/* Verify input data */
 	if (vme_base & 0xFFFF) {
 		dev_err(tsi148_bridge->parent, "Invalid VME Window "
@@ -949,7 +951,9 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled,
 		pci_bound = 0;
 		vme_offset = 0;
 	} else {
-		pci_base = (unsigned long long)image->bus_resource.start;
+		pcibios_resource_to_bus(pdev->bus, &region,
+					&image->bus_resource);
+		pci_base = region.start;
 
 		/*
 		 * Bound address is a valid address for the window, adjust
@@ -2232,7 +2236,7 @@ static void *tsi148_alloc_consistent(struct device *parent, size_t size,
 	struct pci_dev *pdev;
 
 	/* Find pci_dev container of dev */
-	pdev = container_of(parent, struct pci_dev, dev);
+	pdev = to_pci_dev(parent);
 
 	return pci_alloc_consistent(pdev, size, dma);
 }
@@ -2243,7 +2247,7 @@ static void tsi148_free_consistent(struct device *parent, size_t size,
 	struct pci_dev *pdev;
 
 	/* Find pci_dev container of dev */
-	pdev = container_of(parent, struct pci_dev, dev);
+	pdev = to_pci_dev(parent);
 
 	pci_free_consistent(pdev, size, vaddr, dma);
 }
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index b96f61b15dc6..ff52618cafbe 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -614,27 +614,11 @@ end:
 	return err;
 }
 
-/*
- * Handle sysfs file creation and removal here, before userspace is told that
- * the device is added / removed from the system
- */
-static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
-			 void *data)
+static int w1_family_notify(unsigned long action, struct w1_slave *sl)
 {
-	struct device *dev = data;
-	struct w1_slave *sl;
 	struct w1_family_ops *fops;
 	int err;
 
-	/*
-	 * Only care about slave devices at the moment.  Yes, we should use a
-	 * separate "type" for this, but for now, look at the release function
-	 * to know which type it is...
-	 */
-	if (dev->release != w1_slave_release)
-		return 0;
-
-	sl = dev_to_w1_slave(dev);
 	fops = sl->family->fops;
 
 	if (!fops)
@@ -673,10 +657,6 @@ static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
 	return 0;
 }
 
-static struct notifier_block w1_bus_nb = {
-	.notifier_call = w1_bus_notify,
-};
-
 static int __w1_attach_slave_device(struct w1_slave *sl)
 {
 	int err;
@@ -698,6 +678,9 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
 	dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__,
 		dev_name(&sl->dev), sl);
 
+	/* suppress for w1_family_notify before sending KOBJ_ADD */
+	dev_set_uevent_suppress(&sl->dev, true);
+
 	err = device_register(&sl->dev);
 	if (err < 0) {
 		dev_err(&sl->dev,
@@ -705,7 +688,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
 			dev_name(&sl->dev), err);
 		return err;
 	}
-
+	w1_family_notify(BUS_NOTIFY_ADD_DEVICE, sl);
 
 	dev_set_uevent_suppress(&sl->dev, false);
 	kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
@@ -799,6 +782,7 @@ int w1_unref_slave(struct w1_slave *sl)
 		msg.type = W1_SLAVE_REMOVE;
 		w1_netlink_send(sl->master, &msg);
 
+		w1_family_notify(BUS_NOTIFY_DEL_DEVICE, sl);
 		device_unregister(&sl->dev);
 		#ifdef DEBUG
 		memset(sl, 0, sizeof(*sl));
@@ -1186,10 +1170,6 @@ static int __init w1_init(void)
 		goto err_out_exit_init;
 	}
 
-	retval = bus_register_notifier(&w1_bus_type, &w1_bus_nb);
-	if (retval)
-		goto err_out_bus_unregister;
-
 	retval = driver_register(&w1_master_driver);
 	if (retval) {
 		printk(KERN_ERR
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 9b084db739c7..3aaa15f6b7e9 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -92,9 +92,8 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
 	err = device_register(&dev->dev);
 	if (err) {
 		printk(KERN_ERR "Failed to register master device. err=%d\n", err);
-		memset(dev, 0, sizeof(struct w1_master));
-		kfree(dev);
-		dev = NULL;
+		put_device(&dev->dev);
+		return NULL;
 	}
 
 	return dev;
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 5234964fe001..a02704a59321 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -300,12 +300,6 @@ static int w1_process_command_root(struct cn_msg *msg,
 	struct w1_netlink_msg *w;
 	u32 *id;
 
-	if (mcmd->type != W1_LIST_MASTERS) {
-		printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n",
-			__func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len);
-		return -EPROTO;
-	}
-
 	cn = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!cn)
 		return -ENOMEM;
@@ -441,6 +435,9 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
 		w1_netlink_send_error(&node->block->msg, node->m, cmd,
 			node->block->portid, err);
 
+	/* ref taken in w1_search_slave or w1_search_master_id when building
+	 * the block
+	 */
 	if (sl)
 		w1_unref_slave(sl);
 	else
@@ -503,30 +500,42 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 
 	msg_len = msg->len;
 	while (msg_len && !err) {
-		struct w1_reg_num id;
-		u16 mlen = m->len;
 
 		dev = NULL;
 		sl = NULL;
 
-		memcpy(&id, m->id.id, sizeof(id));
-#if 0
-		printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n",
-				__func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len);
-#endif
 		if (m->len + sizeof(struct w1_netlink_msg) > msg_len) {
 			err = -E2BIG;
 			break;
 		}
 
+		/* execute on this thread, no need to process later */
+		if (m->type == W1_LIST_MASTERS) {
+			err = w1_process_command_root(msg, m, nsp->portid);
+			goto out_cont;
+		}
+
+		/* All following message types require additional data,
+		 * check here before references are taken.
+		 */
+		if (!m->len) {
+			err = -EPROTO;
+			goto out_cont;
+		}
+
+		/* both search calls take reference counts */
 		if (m->type == W1_MASTER_CMD) {
 			dev = w1_search_master_id(m->id.mst.id);
 		} else if (m->type == W1_SLAVE_CMD) {
-			sl = w1_search_slave(&id);
+			sl = w1_search_slave((struct w1_reg_num *)m->id.id);
 			if (sl)
 				dev = sl->master;
 		} else {
-			err = w1_process_command_root(msg, m, nsp->portid);
+			printk(KERN_NOTICE
+				"%s: msg: %x.%x, wrong type: %u, len: %u.\n",
+				__func__, msg->id.idx, msg->id.val,
+				m->type, m->len);
+			err = -EPROTO;
 			goto out_cont;
 		}
 
@@ -536,8 +545,6 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 		}
 
 		err = 0;
-		if (!mlen)
-			goto out_cont;
 
 		atomic_inc(&block->refcnt);
 		node->async.cb = w1_process_cb;
@@ -557,7 +564,8 @@ out_cont:
 		if (err)
 			w1_netlink_send_error(msg, m, NULL, nsp->portid, err);
 		msg_len -= sizeof(struct w1_netlink_msg) + m->len;
-		m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len);
+		m = (struct w1_netlink_msg *)(((u8 *)m) +
+			sizeof(struct w1_netlink_msg) + m->len);
 
 		/*
 		 * Let's allow requests for nonexisting devices.
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 82358d14ecf1..59fc190f1e92 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -127,7 +127,7 @@ static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
 			pr_debug("     C%d: %s %d uS\n",
 				 cx->type, cx->desc, (u32)cx->latency);
 		}
-	} else if (ret != -EINVAL)
+	} else if ((ret != -EINVAL) && (ret != -ENOSYS))
 		/* EINVAL means the ACPI ID is incorrect - meaning the ACPI
 		 * table is referencing a non-existing CPU - which can happen
 		 * with broken ACPI tables. */
@@ -259,7 +259,7 @@ static int push_pxx_to_hypervisor(struct acpi_processor *_pr)
 			(u32) perf->states[i].power,
 			(u32) perf->states[i].transition_latency);
 		}
-	} else if (ret != -EINVAL)
+	} else if ((ret != -EINVAL) && (ret != -ENOSYS))
 		/* EINVAL means the ACPI ID is incorrect - meaning the ACPI
 		 * table is referencing a non-existing CPU - which can happen
 		 * with broken ACPI tables. */
diff --git a/firmware/WHENCE b/firmware/WHENCE
index 8388f02de2bd..0c4d96dee9b6 100644
--- a/firmware/WHENCE
+++ b/firmware/WHENCE
@@ -273,16 +273,6 @@ Converted from Intel HEX files, used in our binary representation of ihex.
 
 --------------------------------------------------------------------------
 
-Driver: ip2 -- Computone IntelliPort Plus serial device
-
-File: intelliport2.bin
-
-Licence: Unknown
-
-Found in hex form in kernel source.
-
---------------------------------------------------------------------------
-
 Driver: CPiA2 -- cameras based on Vision's CPiA2
 
 File: cpia2/stv0672_vp4.bin
diff --git a/fs/aio.c b/fs/aio.c
index 12a3de0ee6da..2adbb0398ab9 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -112,6 +112,11 @@ struct kioctx {
 
 	struct work_struct	free_work;
 
+	/*
+	 * signals when all in-flight requests are done
+	 */
+	struct completion *requests_done;
+
 	struct {
 		/*
 		 * This counts the number of available slots in the ringbuffer,
@@ -508,6 +513,10 @@ static void free_ioctx_reqs(struct percpu_ref *ref)
 {
 	struct kioctx *ctx = container_of(ref, struct kioctx, reqs);
 
+	/* At this point we know that there are no any in-flight requests */
+	if (ctx->requests_done)
+		complete(ctx->requests_done);
+
 	INIT_WORK(&ctx->free_work, free_ioctx);
 	schedule_work(&ctx->free_work);
 }
@@ -718,7 +727,8 @@ err:
  *	when the processes owning a context have all exited to encourage
  *	the rapid destruction of the kioctx.
  */
-static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
+static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
+		struct completion *requests_done)
 {
 	if (!atomic_xchg(&ctx->dead, 1)) {
 		struct kioctx_table *table;
@@ -747,7 +757,11 @@ static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
 		if (ctx->mmap_size)
 			vm_munmap(ctx->mmap_base, ctx->mmap_size);
 
+		ctx->requests_done = requests_done;
 		percpu_ref_kill(&ctx->users);
+	} else {
+		if (requests_done)
+			complete(requests_done);
 	}
 }
 
@@ -809,7 +823,7 @@ void exit_aio(struct mm_struct *mm)
 		 */
 		ctx->mmap_size = 0;
 
-		kill_ioctx(mm, ctx);
+		kill_ioctx(mm, ctx, NULL);
 	}
 }
 
@@ -1185,7 +1199,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
 	if (!IS_ERR(ioctx)) {
 		ret = put_user(ioctx->user_id, ctxp);
 		if (ret)
-			kill_ioctx(current->mm, ioctx);
+			kill_ioctx(current->mm, ioctx, NULL);
 		percpu_ref_put(&ioctx->users);
 	}
 
@@ -1203,8 +1217,22 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
 {
 	struct kioctx *ioctx = lookup_ioctx(ctx);
 	if (likely(NULL != ioctx)) {
-		kill_ioctx(current->mm, ioctx);
+		struct completion requests_done =
+			COMPLETION_INITIALIZER_ONSTACK(requests_done);
+
+		/* Pass requests_done to kill_ioctx() where it can be set
+		 * in a thread-safe way. If we try to set it here then we have
+		 * a race condition if two io_destroy() called simultaneously.
+		 */
+		kill_ioctx(current->mm, ioctx, &requests_done);
 		percpu_ref_put(&ioctx->users);
+
+		/* Wait until all IO for the context are done. Otherwise kernel
+		 * keep using user-space buffers even if user thinks the context
+		 * is destroyed.
+		 */
+		wait_for_completion(&requests_done);
+
 		return 0;
 	}
 	pr_debug("EINVAL: io_destroy: invalid context id\n");
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index d626756ff721..1e27cd33f7f2 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -396,9 +396,8 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
 	if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){
 		inode->i_size = 0;
 		inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE;
-		strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
-			BEFS_SYMLINK_LEN - 1);
-		befs_ino->i_data.symlink[BEFS_SYMLINK_LEN - 1] = '\0';
+		strlcpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
+			BEFS_SYMLINK_LEN);
 	} else {
 		int num_blks;
 
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index aa3cb626671e..c2e5d4647345 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -145,6 +145,25 @@ static int padzero(unsigned long elf_bss)
 #define ELF_BASE_PLATFORM NULL
 #endif
 
+/*
+ * Use get_random_int() to implement AT_RANDOM while avoiding depletion
+ * of the entropy pool.
+ */
+static void get_atrandom_bytes(unsigned char *buf, size_t nbytes)
+{
+	unsigned char *p = buf;
+
+	while (nbytes) {
+		unsigned int random_variable;
+		size_t chunk = min(nbytes, sizeof(random_variable));
+
+		random_variable = get_random_int();
+		memcpy(p, &random_variable, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+}
+
 static int
 create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 		unsigned long load_addr, unsigned long interp_load_addr)
@@ -206,7 +225,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	/*
 	 * Generate 16 random bytes for userspace PRNG seeding.
 	 */
-	get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
+	get_atrandom_bytes(k_rand_bytes, sizeof(k_rand_bytes));
 	u_rand_bytes = (elf_addr_t __user *)
 		       STACK_ALLOC(p, sizeof(k_rand_bytes));
 	if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
diff --git a/fs/bio.c b/fs/bio.c
index 6f0362b77806..9e4fa9498cd4 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -112,7 +112,8 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
 	bslab = &bio_slabs[entry];
 
 	snprintf(bslab->name, sizeof(bslab->name), "bio-%d", entry);
-	slab = kmem_cache_create(bslab->name, sz, 0, SLAB_HWCACHE_ALIGN, NULL);
+	slab = kmem_cache_create(bslab->name, sz, ARCH_KMALLOC_MINALIGN,
+				 SLAB_HWCACHE_ALIGN, NULL);
 	if (!slab)
 		goto out_unlock;
 
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 39da1c2efa50..88a6df4cbe6d 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1221,9 +1221,6 @@ static long ceph_fallocate(struct file *file, int mode,
 	if (!S_ISREG(inode->i_mode))
 		return -EOPNOTSUPP;
 
-	if (IS_SWAPFILE(inode))
-		return -ETXTBSY;
-
 	mutex_lock(&inode->i_mutex);
 
 	if (ceph_snap(inode) != CEPH_NOSNAP) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index df9c9141c099..5be1f997ecde 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -253,6 +253,11 @@ cifs_alloc_inode(struct super_block *sb)
 	cifs_set_oplock_level(cifs_inode, 0);
 	cifs_inode->delete_pending = false;
 	cifs_inode->invalid_mapping = false;
+	clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cifs_inode->flags);
+	clear_bit(CIFS_INODE_PENDING_WRITERS, &cifs_inode->flags);
+	clear_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cifs_inode->flags);
+	spin_lock_init(&cifs_inode->writers_lock);
+	cifs_inode->writers = 0;
 	cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
 	cifs_inode->server_eof = 0;
 	cifs_inode->uniqueid = 0;
@@ -732,19 +737,26 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 				   unsigned long nr_segs, loff_t pos)
 {
 	struct inode *inode = file_inode(iocb->ki_filp);
+	struct cifsInodeInfo *cinode = CIFS_I(inode);
 	ssize_t written;
 	int rc;
 
+	written = cifs_get_writer(cinode);
+	if (written)
+		return written;
+
 	written = generic_file_aio_write(iocb, iov, nr_segs, pos);
 
 	if (CIFS_CACHE_WRITE(CIFS_I(inode)))
-		return written;
+		goto out;
 
 	rc = filemap_fdatawrite(inode->i_mapping);
 	if (rc)
 		cifs_dbg(FYI, "cifs_file_aio_write: %d rc on %p inode\n",
 			 rc, inode);
 
+out:
+	cifs_put_writer(cinode);
 	return written;
 }
 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index c0f3718b77a8..30f6e9251a4a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -228,6 +228,8 @@ struct smb_version_operations {
 	/* verify the message */
 	int (*check_message)(char *, unsigned int);
 	bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
+	void (*downgrade_oplock)(struct TCP_Server_Info *,
+					struct cifsInodeInfo *, bool);
 	/* process transaction2 response */
 	bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *,
 			     char *, int);
@@ -1113,6 +1115,12 @@ struct cifsInodeInfo {
 	unsigned int epoch;		/* used to track lease state changes */
 	bool delete_pending;		/* DELETE_ON_CLOSE is set */
 	bool invalid_mapping;		/* pagecache is invalid */
+	unsigned long flags;
+#define CIFS_INODE_PENDING_OPLOCK_BREAK   (0) /* oplock break in progress */
+#define CIFS_INODE_PENDING_WRITERS	  (1) /* Writes in progress */
+#define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */
+	spinlock_t writers_lock;
+	unsigned int writers;		/* Number of writers on this inode */
 	unsigned long time;		/* jiffies of last update of inode */
 	u64  server_eof;		/* current file size on server -- protected by i_lock */
 	u64  uniqueid;			/* server inode number */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index acc4ee8ed075..ca7980a1e303 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -127,6 +127,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
 extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
 				      int offset);
 extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
+extern int cifs_get_writer(struct cifsInodeInfo *cinode);
+extern void cifs_put_writer(struct cifsInodeInfo *cinode);
+extern void cifs_done_oplock_break(struct cifsInodeInfo *cinode);
 extern int cifs_unlock_range(struct cifsFileInfo *cfile,
 			     struct file_lock *flock, const unsigned int xid);
 extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f3264bd7a83d..6ce4e0954b98 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -6197,6 +6197,9 @@ QAllEAsRetry:
 	cifs_dbg(FYI, "ea length %d\n", list_len);
 	if (list_len <= 8) {
 		cifs_dbg(FYI, "empty EA list returned from server\n");
+		/* didn't find the named attribute */
+		if (ea_name)
+			rc = -ENODATA;
 		goto QAllEAsOut;
 	}
 
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8add25538a3b..d8ee76241b64 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2621,12 +2621,20 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
 	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
 	ssize_t written;
 
+	written = cifs_get_writer(cinode);
+	if (written)
+		return written;
+
 	if (CIFS_CACHE_WRITE(cinode)) {
 		if (cap_unix(tcon->ses) &&
 		(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
-		    && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
-			return generic_file_aio_write(iocb, iov, nr_segs, pos);
-		return cifs_writev(iocb, iov, nr_segs, pos);
+		  && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
+			written = generic_file_aio_write(
+					iocb, iov, nr_segs, pos);
+			goto out;
+		}
+		written = cifs_writev(iocb, iov, nr_segs, pos);
+		goto out;
 	}
 	/*
 	 * For non-oplocked files in strict cache mode we need to write the data
@@ -2646,6 +2654,8 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
 			 inode);
 		cinode->oplock = 0;
 	}
+out:
+	cifs_put_writer(cinode);
 	return written;
 }
 
@@ -3621,6 +3631,13 @@ static int cifs_launder_page(struct page *page)
 	return rc;
 }
 
+static int
+cifs_pending_writers_wait(void *unused)
+{
+	schedule();
+	return 0;
+}
+
 void cifs_oplock_break(struct work_struct *work)
 {
 	struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
@@ -3628,8 +3645,15 @@ void cifs_oplock_break(struct work_struct *work)
 	struct inode *inode = cfile->dentry->d_inode;
 	struct cifsInodeInfo *cinode = CIFS_I(inode);
 	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+	struct TCP_Server_Info *server = tcon->ses->server;
 	int rc = 0;
 
+	wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
+			cifs_pending_writers_wait, TASK_UNINTERRUPTIBLE);
+
+	server->ops->downgrade_oplock(server, cinode,
+		test_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cinode->flags));
+
 	if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
 						cifs_has_mand_locks(cinode)) {
 		cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
@@ -3666,6 +3690,7 @@ void cifs_oplock_break(struct work_struct *work)
 							     cinode);
 		cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
 	}
+	cifs_done_oplock_break(cinode);
 }
 
 /*
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 2f9f3790679d..3b0c62e622da 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -466,8 +466,22 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 				cifs_dbg(FYI, "file id match, oplock break\n");
 				pCifsInode = CIFS_I(netfile->dentry->d_inode);
 
-				cifs_set_oplock_level(pCifsInode,
-					pSMB->OplockLevel ? OPLOCK_READ : 0);
+				set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
+					&pCifsInode->flags);
+
+				/*
+				 * Set flag if the server downgrades the oplock
+				 * to L2 else clear.
+				 */
+				if (pSMB->OplockLevel)
+					set_bit(
+					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+					   &pCifsInode->flags);
+				else
+					clear_bit(
+					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+					   &pCifsInode->flags);
+
 				queue_work(cifsiod_wq,
 					   &netfile->oplock_break);
 				netfile->oplock_break_cancelled = false;
@@ -551,6 +565,62 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
 		cinode->oplock = 0;
 }
 
+static int
+cifs_oplock_break_wait(void *unused)
+{
+	schedule();
+	return signal_pending(current) ? -ERESTARTSYS : 0;
+}
+
+/*
+ * We wait for oplock breaks to be processed before we attempt to perform
+ * writes.
+ */
+int cifs_get_writer(struct cifsInodeInfo *cinode)
+{
+	int rc;
+
+start:
+	rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
+				   cifs_oplock_break_wait, TASK_KILLABLE);
+	if (rc)
+		return rc;
+
+	spin_lock(&cinode->writers_lock);
+	if (!cinode->writers)
+		set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+	cinode->writers++;
+	/* Check to see if we have started servicing an oplock break */
+	if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) {
+		cinode->writers--;
+		if (cinode->writers == 0) {
+			clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+			wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
+		}
+		spin_unlock(&cinode->writers_lock);
+		goto start;
+	}
+	spin_unlock(&cinode->writers_lock);
+	return 0;
+}
+
+void cifs_put_writer(struct cifsInodeInfo *cinode)
+{
+	spin_lock(&cinode->writers_lock);
+	cinode->writers--;
+	if (cinode->writers == 0) {
+		clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+		wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
+	}
+	spin_unlock(&cinode->writers_lock);
+}
+
+void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
+{
+	clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
+	wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK);
+}
+
 bool
 backup_cred(struct cifs_sb_info *cifs_sb)
 {
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 526fb89f9230..d1fdfa848703 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -372,6 +372,16 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
 	return 0;
 }
 
+static void
+cifs_downgrade_oplock(struct TCP_Server_Info *server,
+			struct cifsInodeInfo *cinode, bool set_level2)
+{
+	if (set_level2)
+		cifs_set_oplock_level(cinode, OPLOCK_READ);
+	else
+		cifs_set_oplock_level(cinode, 0);
+}
+
 static bool
 cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 		  char *buf, int malformed)
@@ -1019,6 +1029,7 @@ struct smb_version_operations smb1_operations = {
 	.clear_stats = cifs_clear_stats,
 	.print_stats = cifs_print_stats,
 	.is_oplock_break = is_valid_oplock_break,
+	.downgrade_oplock = cifs_downgrade_oplock,
 	.check_trans2 = cifs_check_trans2,
 	.need_neg = cifs_need_neg,
 	.negotiate = cifs_negotiate,
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index fb3966265b6e..b8021fde987d 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -575,9 +575,21 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 				else
 					cfile->oplock_break_cancelled = false;
 
-				server->ops->set_oplock_level(cinode,
-				  rsp->OplockLevel ? SMB2_OPLOCK_LEVEL_II : 0,
-				  0, NULL);
+				set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
+					&cinode->flags);
+
+				/*
+				 * Set flag if the server downgrades the oplock
+				 * to L2 else clear.
+				 */
+				if (rsp->OplockLevel)
+					set_bit(
+					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+					   &cinode->flags);
+				else
+					clear_bit(
+					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+					   &cinode->flags);
 
 				queue_work(cifsiod_wq, &cfile->oplock_break);
 
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 192f51a12cf1..35ddc3ed119d 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -905,6 +905,17 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 }
 
 static void
+smb2_downgrade_oplock(struct TCP_Server_Info *server,
+			struct cifsInodeInfo *cinode, bool set_level2)
+{
+	if (set_level2)
+		server->ops->set_oplock_level(cinode, SMB2_OPLOCK_LEVEL_II,
+						0, NULL);
+	else
+		server->ops->set_oplock_level(cinode, 0, 0, NULL);
+}
+
+static void
 smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
 		      unsigned int epoch, bool *purge_cache)
 {
@@ -1110,6 +1121,7 @@ struct smb_version_operations smb20_operations = {
 	.clear_stats = smb2_clear_stats,
 	.print_stats = smb2_print_stats,
 	.is_oplock_break = smb2_is_valid_oplock_break,
+	.downgrade_oplock = smb2_downgrade_oplock,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
 	.negotiate_wsize = smb2_negotiate_wsize,
@@ -1184,6 +1196,7 @@ struct smb_version_operations smb21_operations = {
 	.clear_stats = smb2_clear_stats,
 	.print_stats = smb2_print_stats,
 	.is_oplock_break = smb2_is_valid_oplock_break,
+	.downgrade_oplock = smb2_downgrade_oplock,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
 	.negotiate_wsize = smb2_negotiate_wsize,
@@ -1259,6 +1272,7 @@ struct smb_version_operations smb30_operations = {
 	.print_stats = smb2_print_stats,
 	.dump_share_caps = smb2_dump_share_caps,
 	.is_oplock_break = smb2_is_valid_oplock_break,
+	.downgrade_oplock = smb2_downgrade_oplock,
 	.need_neg = smb2_need_neg,
 	.negotiate = smb2_negotiate,
 	.negotiate_wsize = smb2_negotiate_wsize,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 860344701067..3802f8c94acc 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1352,7 +1352,6 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
 		     u64 persistent_fid, u64 volatile_fid)
 {
 	int rc;
-	char *res_key = NULL;
 	struct  compress_ioctl fsctl_input;
 	char *ret_data = NULL;
 
@@ -1365,7 +1364,6 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
 			2 /* in data len */, &ret_data /* out data */, NULL);
 
 	cifs_dbg(FYI, "set compression rc %d\n", rc);
-	kfree(res_key);
 
 	return rc;
 }
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index b1eaa7a1f82c..c705360e2b16 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -230,8 +230,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to initialize "
 			"the lower file for the dentry with name "
-			"[%s]; rc = [%d]\n", __func__,
-			ecryptfs_dentry->d_name.name, rc);
+			"[%pd]; rc = [%d]\n", __func__,
+			ecryptfs_dentry, rc);
 		goto out_free;
 	}
 	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE)
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index d4a9431ec73c..4d6c7e48828d 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -250,8 +250,8 @@ int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to initialize "
 			"the lower file for the dentry with name "
-			"[%s]; rc = [%d]\n", __func__,
-			ecryptfs_dentry->d_name.name, rc);
+			"[%pd]; rc = [%d]\n", __func__,
+			ecryptfs_dentry, rc);
 		goto out;
 	}
 	rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode);
@@ -313,8 +313,8 @@ static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode)
 	if (rc) {
 		printk(KERN_ERR "%s: Error attempting to initialize "
 			"the lower file for the dentry with name "
-			"[%s]; rc = [%d]\n", __func__,
-			dentry->d_name.name, rc);
+			"[%pd]; rc = [%d]\n", __func__,
+			dentry, rc);
 		return rc;
 	}
 
@@ -418,8 +418,8 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
 	if (IS_ERR(lower_dentry)) {
 		rc = PTR_ERR(lower_dentry);
 		ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
-				"[%d] on lower_dentry = [%s]\n", __func__, rc,
-				ecryptfs_dentry->d_name.name);
+				"[%d] on lower_dentry = [%pd]\n", __func__, rc,
+				ecryptfs_dentry);
 		goto out;
 	}
 	if (lower_dentry->d_inode)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 6ea7b1436bbc..5c56785007e0 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -667,7 +667,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
 			continue;
 
 		x = ext4_count_free(bitmap_bh->b_data,
-				    EXT4_BLOCKS_PER_GROUP(sb) / 8);
+				    EXT4_CLUSTERS_PER_GROUP(sb) / 8);
 		printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
 			i, ext4_free_group_clusters(sb, gdp), x);
 		bitmap_count += x;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f1c65dc7cc0a..1d08a1b51bdd 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -158,7 +158,6 @@ struct ext4_allocation_request {
 #define EXT4_MAP_MAPPED		(1 << BH_Mapped)
 #define EXT4_MAP_UNWRITTEN	(1 << BH_Unwritten)
 #define EXT4_MAP_BOUNDARY	(1 << BH_Boundary)
-#define EXT4_MAP_UNINIT		(1 << BH_Uninit)
 /* Sometimes (in the bigalloc case, from ext4_da_get_block_prep) the caller of
  * ext4_map_blocks wants to know whether or not the underlying cluster has
  * already been accounted for. EXT4_MAP_FROM_CLUSTER conveys to the caller that
@@ -169,7 +168,7 @@ struct ext4_allocation_request {
 #define EXT4_MAP_FROM_CLUSTER	(1 << BH_AllocFromCluster)
 #define EXT4_MAP_FLAGS		(EXT4_MAP_NEW | EXT4_MAP_MAPPED |\
 				 EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY |\
-				 EXT4_MAP_UNINIT | EXT4_MAP_FROM_CLUSTER)
+				 EXT4_MAP_FROM_CLUSTER)
 
 struct ext4_map_blocks {
 	ext4_fsblk_t m_pblk;
@@ -184,7 +183,7 @@ struct ext4_map_blocks {
 #define	EXT4_IO_END_UNWRITTEN	0x0001
 
 /*
- * For converting uninitialized extents on a work queue. 'handle' is used for
+ * For converting unwritten extents on a work queue. 'handle' is used for
  * buffered writeback.
  */
 typedef struct ext4_io_end {
@@ -537,26 +536,26 @@ enum {
 /*
  * Flags used by ext4_map_blocks()
  */
-	/* Allocate any needed blocks and/or convert an unitialized
+	/* Allocate any needed blocks and/or convert an unwritten
 	   extent to be an initialized ext4 */
 #define EXT4_GET_BLOCKS_CREATE			0x0001
-	/* Request the creation of an unitialized extent */
-#define EXT4_GET_BLOCKS_UNINIT_EXT		0x0002
-#define EXT4_GET_BLOCKS_CREATE_UNINIT_EXT	(EXT4_GET_BLOCKS_UNINIT_EXT|\
+	/* Request the creation of an unwritten extent */
+#define EXT4_GET_BLOCKS_UNWRIT_EXT		0x0002
+#define EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT	(EXT4_GET_BLOCKS_UNWRIT_EXT|\
 						 EXT4_GET_BLOCKS_CREATE)
 	/* Caller is from the delayed allocation writeout path
 	 * finally doing the actual allocation of delayed blocks */
 #define EXT4_GET_BLOCKS_DELALLOC_RESERVE	0x0004
 	/* caller is from the direct IO path, request to creation of an
-	unitialized extents if not allocated, split the uninitialized
+	unwritten extents if not allocated, split the unwritten
 	extent if blocks has been preallocated already*/
 #define EXT4_GET_BLOCKS_PRE_IO			0x0008
 #define EXT4_GET_BLOCKS_CONVERT			0x0010
 #define EXT4_GET_BLOCKS_IO_CREATE_EXT		(EXT4_GET_BLOCKS_PRE_IO|\
-					 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
+					 EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT)
 	/* Convert extent to initialized after IO complete */
 #define EXT4_GET_BLOCKS_IO_CONVERT_EXT		(EXT4_GET_BLOCKS_CONVERT|\
-					 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
+					 EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT)
 	/* Eventual metadata allocation (due to growing extent tree)
 	 * should not fail, so try to use reserved blocks for that.*/
 #define EXT4_GET_BLOCKS_METADATA_NOFAIL		0x0020
@@ -876,6 +875,8 @@ struct ext4_inode_info {
 	struct inode vfs_inode;
 	struct jbd2_inode *jinode;
 
+	spinlock_t i_raw_lock;	/* protects updates to the raw inode */
+
 	/*
 	 * File creation time. Its function is same as that of
 	 * struct timespec i_{a,c,m}time in the generic inode.
@@ -2466,23 +2467,6 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
 	up_write(&EXT4_I(inode)->i_data_sem);
 }
 
-/*
- * Update i_disksize after writeback has been started. Races with truncate
- * are avoided by checking i_size under i_data_sem.
- */
-static inline void ext4_wb_update_i_disksize(struct inode *inode, loff_t newsize)
-{
-	loff_t i_size;
-
-	down_write(&EXT4_I(inode)->i_data_sem);
-	i_size = i_size_read(inode);
-	if (newsize > i_size)
-		newsize = i_size;
-	if (newsize > EXT4_I(inode)->i_disksize)
-		EXT4_I(inode)->i_disksize = newsize;
-	up_write(&EXT4_I(inode)->i_data_sem);
-}
-
 struct ext4_group_info {
 	unsigned long   bb_state;
 	struct rb_root  bb_free_root;
@@ -2801,10 +2785,9 @@ extern int ext4_mmp_csum_verify(struct super_block *sb,
  * See EXT4_MAP_... to see where this is used.
  */
 enum ext4_state_bits {
-	BH_Uninit	/* blocks are allocated but uninitialized on disk */
-	 = BH_JBDPrivateStart,
-	BH_AllocFromCluster,	/* allocated blocks were part of already
+	BH_AllocFromCluster	/* allocated blocks were part of already
 				 * allocated cluster. */
+	= BH_JBDPrivateStart
 };
 
 /*
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index 5074fe23f19e..a867f5ca9991 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -137,21 +137,21 @@ struct ext4_ext_path {
  * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
  * initialized extent. This is 2^15 and not (2^16 - 1), since we use the
  * MSB of ee_len field in the extent datastructure to signify if this
- * particular extent is an initialized extent or an uninitialized (i.e.
+ * particular extent is an initialized extent or an unwritten (i.e.
  * preallocated).
- * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
- * uninitialized extent.
+ * EXT_UNWRITTEN_MAX_LEN is the maximum number of blocks we can have in an
+ * unwritten extent.
  * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
- * uninitialized one. In other words, if MSB of ee_len is set, it is an
- * uninitialized extent with only one special scenario when ee_len = 0x8000.
- * In this case we can not have an uninitialized extent of zero length and
+ * unwritten one. In other words, if MSB of ee_len is set, it is an
+ * unwritten extent with only one special scenario when ee_len = 0x8000.
+ * In this case we can not have an unwritten extent of zero length and
  * thus we make it as a special case of initialized extent with 0x8000 length.
  * This way we get better extent-to-group alignment for initialized extents.
  * Hence, the maximum number of blocks we can have in an *initialized*
- * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
+ * extent is 2^15 (32768) and in an *unwritten* extent is 2^15-1 (32767).
  */
 #define EXT_INIT_MAX_LEN	(1UL << 15)
-#define EXT_UNINIT_MAX_LEN	(EXT_INIT_MAX_LEN - 1)
+#define EXT_UNWRITTEN_MAX_LEN	(EXT_INIT_MAX_LEN - 1)
 
 
 #define EXT_FIRST_EXTENT(__hdr__) \
@@ -187,14 +187,14 @@ static inline unsigned short ext_depth(struct inode *inode)
 	return le16_to_cpu(ext_inode_hdr(inode)->eh_depth);
 }
 
-static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
+static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext)
 {
-	/* We can not have an uninitialized extent of zero length! */
+	/* We can not have an unwritten extent of zero length! */
 	BUG_ON((le16_to_cpu(ext->ee_len) & ~EXT_INIT_MAX_LEN) == 0);
 	ext->ee_len |= cpu_to_le16(EXT_INIT_MAX_LEN);
 }
 
-static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext)
+static inline int ext4_ext_is_unwritten(struct ext4_extent *ext)
 {
 	/* Extent with ee_len of 0x8000 is treated as an initialized extent */
 	return (le16_to_cpu(ext->ee_len) > EXT_INIT_MAX_LEN);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 82df3ce9874a..9315843eb6f7 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -29,6 +29,7 @@
  *   - smart tree reduction
  */
 
+#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/jbd2.h>
@@ -50,8 +51,8 @@
  */
 #define EXT4_EXT_MAY_ZEROOUT	0x1  /* safe to zeroout if split fails \
 					due to ENOSPC */
-#define EXT4_EXT_MARK_UNINIT1	0x2  /* mark first half uninitialized */
-#define EXT4_EXT_MARK_UNINIT2	0x4  /* mark second half uninitialized */
+#define EXT4_EXT_MARK_UNWRIT1	0x2  /* mark first half unwritten */
+#define EXT4_EXT_MARK_UNWRIT2	0x4  /* mark second half unwritten */
 
 #define EXT4_EXT_DATA_VALID1	0x8  /* first half contains valid data */
 #define EXT4_EXT_DATA_VALID2	0x10 /* second half contains valid data */
@@ -524,7 +525,7 @@ __read_extent_tree_block(const char *function, unsigned int line,
 						     lblk - prev, ~0,
 						     EXTENT_STATUS_HOLE);
 
-			if (ext4_ext_is_uninitialized(ex))
+			if (ext4_ext_is_unwritten(ex))
 				status = EXTENT_STATUS_UNWRITTEN;
 			ext4_es_cache_extent(inode, lblk, len,
 					     ext4_ext_pblock(ex), status);
@@ -620,7 +621,7 @@ static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
 		} else if (path->p_ext) {
 			ext_debug("  %d:[%d]%d:%llu ",
 				  le32_to_cpu(path->p_ext->ee_block),
-				  ext4_ext_is_uninitialized(path->p_ext),
+				  ext4_ext_is_unwritten(path->p_ext),
 				  ext4_ext_get_actual_len(path->p_ext),
 				  ext4_ext_pblock(path->p_ext));
 		} else
@@ -646,7 +647,7 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path)
 
 	for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ex++) {
 		ext_debug("%d:[%d]%d:%llu ", le32_to_cpu(ex->ee_block),
-			  ext4_ext_is_uninitialized(ex),
+			  ext4_ext_is_unwritten(ex),
 			  ext4_ext_get_actual_len(ex), ext4_ext_pblock(ex));
 	}
 	ext_debug("\n");
@@ -677,7 +678,7 @@ static void ext4_ext_show_move(struct inode *inode, struct ext4_ext_path *path,
 		ext_debug("move %d:%llu:[%d]%d in new leaf %llu\n",
 				le32_to_cpu(ex->ee_block),
 				ext4_ext_pblock(ex),
-				ext4_ext_is_uninitialized(ex),
+				ext4_ext_is_unwritten(ex),
 				ext4_ext_get_actual_len(ex),
 				newblock);
 		ex++;
@@ -802,7 +803,7 @@ ext4_ext_binsearch(struct inode *inode,
 	ext_debug("  -> %d:%llu:[%d]%d ",
 			le32_to_cpu(path->p_ext->ee_block),
 			ext4_ext_pblock(path->p_ext),
-			ext4_ext_is_uninitialized(path->p_ext),
+			ext4_ext_is_unwritten(path->p_ext),
 			ext4_ext_get_actual_len(path->p_ext));
 
 #ifdef CHECK_BINSEARCH
@@ -1686,11 +1687,11 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
 
 	/*
 	 * Make sure that both extents are initialized. We don't merge
-	 * uninitialized extents so that we can be sure that end_io code has
+	 * unwritten extents so that we can be sure that end_io code has
 	 * the extent that was written properly split out and conversion to
 	 * initialized is trivial.
 	 */
-	if (ext4_ext_is_uninitialized(ex1) != ext4_ext_is_uninitialized(ex2))
+	if (ext4_ext_is_unwritten(ex1) != ext4_ext_is_unwritten(ex2))
 		return 0;
 
 	ext1_ee_len = ext4_ext_get_actual_len(ex1);
@@ -1707,10 +1708,10 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
 	 */
 	if (ext1_ee_len + ext2_ee_len > EXT_INIT_MAX_LEN)
 		return 0;
-	if (ext4_ext_is_uninitialized(ex1) &&
+	if (ext4_ext_is_unwritten(ex1) &&
 	    (ext4_test_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN) ||
 	     atomic_read(&EXT4_I(inode)->i_unwritten) ||
-	     (ext1_ee_len + ext2_ee_len > EXT_UNINIT_MAX_LEN)))
+	     (ext1_ee_len + ext2_ee_len > EXT_UNWRITTEN_MAX_LEN)))
 		return 0;
 #ifdef AGGRESSIVE_TEST
 	if (ext1_ee_len >= 4)
@@ -1735,7 +1736,7 @@ static int ext4_ext_try_to_merge_right(struct inode *inode,
 {
 	struct ext4_extent_header *eh;
 	unsigned int depth, len;
-	int merge_done = 0, uninit;
+	int merge_done = 0, unwritten;
 
 	depth = ext_depth(inode);
 	BUG_ON(path[depth].p_hdr == NULL);
@@ -1745,11 +1746,11 @@ static int ext4_ext_try_to_merge_right(struct inode *inode,
 		if (!ext4_can_extents_be_merged(inode, ex, ex + 1))
 			break;
 		/* merge with next extent! */
-		uninit = ext4_ext_is_uninitialized(ex);
+		unwritten = ext4_ext_is_unwritten(ex);
 		ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
 				+ ext4_ext_get_actual_len(ex + 1));
-		if (uninit)
-			ext4_ext_mark_uninitialized(ex);
+		if (unwritten)
+			ext4_ext_mark_unwritten(ex);
 
 		if (ex + 1 < EXT_LAST_EXTENT(eh)) {
 			len = (EXT_LAST_EXTENT(eh) - ex - 1)
@@ -1903,7 +1904,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	struct ext4_ext_path *npath = NULL;
 	int depth, len, err;
 	ext4_lblk_t next;
-	int mb_flags = 0, uninit;
+	int mb_flags = 0, unwritten;
 
 	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
 		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
@@ -1943,21 +1944,21 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 		if (ext4_can_extents_be_merged(inode, ex, newext)) {
 			ext_debug("append [%d]%d block to %u:[%d]%d"
 				  "(from %llu)\n",
-				  ext4_ext_is_uninitialized(newext),
+				  ext4_ext_is_unwritten(newext),
 				  ext4_ext_get_actual_len(newext),
 				  le32_to_cpu(ex->ee_block),
-				  ext4_ext_is_uninitialized(ex),
+				  ext4_ext_is_unwritten(ex),
 				  ext4_ext_get_actual_len(ex),
 				  ext4_ext_pblock(ex));
 			err = ext4_ext_get_access(handle, inode,
 						  path + depth);
 			if (err)
 				return err;
-			uninit = ext4_ext_is_uninitialized(ex);
+			unwritten = ext4_ext_is_unwritten(ex);
 			ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
 					+ ext4_ext_get_actual_len(newext));
-			if (uninit)
-				ext4_ext_mark_uninitialized(ex);
+			if (unwritten)
+				ext4_ext_mark_unwritten(ex);
 			eh = path[depth].p_hdr;
 			nearex = ex;
 			goto merge;
@@ -1969,10 +1970,10 @@ prepend:
 			ext_debug("prepend %u[%d]%d block to %u:[%d]%d"
 				  "(from %llu)\n",
 				  le32_to_cpu(newext->ee_block),
-				  ext4_ext_is_uninitialized(newext),
+				  ext4_ext_is_unwritten(newext),
 				  ext4_ext_get_actual_len(newext),
 				  le32_to_cpu(ex->ee_block),
-				  ext4_ext_is_uninitialized(ex),
+				  ext4_ext_is_unwritten(ex),
 				  ext4_ext_get_actual_len(ex),
 				  ext4_ext_pblock(ex));
 			err = ext4_ext_get_access(handle, inode,
@@ -1980,13 +1981,13 @@ prepend:
 			if (err)
 				return err;
 
-			uninit = ext4_ext_is_uninitialized(ex);
+			unwritten = ext4_ext_is_unwritten(ex);
 			ex->ee_block = newext->ee_block;
 			ext4_ext_store_pblock(ex, ext4_ext_pblock(newext));
 			ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
 					+ ext4_ext_get_actual_len(newext));
-			if (uninit)
-				ext4_ext_mark_uninitialized(ex);
+			if (unwritten)
+				ext4_ext_mark_unwritten(ex);
 			eh = path[depth].p_hdr;
 			nearex = ex;
 			goto merge;
@@ -2046,7 +2047,7 @@ has_space:
 		ext_debug("first extent in the leaf: %u:%llu:[%d]%d\n",
 				le32_to_cpu(newext->ee_block),
 				ext4_ext_pblock(newext),
-				ext4_ext_is_uninitialized(newext),
+				ext4_ext_is_unwritten(newext),
 				ext4_ext_get_actual_len(newext));
 		nearex = EXT_FIRST_EXTENT(eh);
 	} else {
@@ -2057,7 +2058,7 @@ has_space:
 					"nearest %p\n",
 					le32_to_cpu(newext->ee_block),
 					ext4_ext_pblock(newext),
-					ext4_ext_is_uninitialized(newext),
+					ext4_ext_is_unwritten(newext),
 					ext4_ext_get_actual_len(newext),
 					nearex);
 			nearex++;
@@ -2068,7 +2069,7 @@ has_space:
 					"nearest %p\n",
 					le32_to_cpu(newext->ee_block),
 					ext4_ext_pblock(newext),
-					ext4_ext_is_uninitialized(newext),
+					ext4_ext_is_unwritten(newext),
 					ext4_ext_get_actual_len(newext),
 					nearex);
 		}
@@ -2078,7 +2079,7 @@ has_space:
 					"move %d extents from 0x%p to 0x%p\n",
 					le32_to_cpu(newext->ee_block),
 					ext4_ext_pblock(newext),
-					ext4_ext_is_uninitialized(newext),
+					ext4_ext_is_unwritten(newext),
 					ext4_ext_get_actual_len(newext),
 					len, nearex, nearex + 1);
 			memmove(nearex + 1, nearex,
@@ -2200,7 +2201,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
 			es.es_lblk = le32_to_cpu(ex->ee_block);
 			es.es_len = ext4_ext_get_actual_len(ex);
 			es.es_pblk = ext4_ext_pblock(ex);
-			if (ext4_ext_is_uninitialized(ex))
+			if (ext4_ext_is_unwritten(ex))
 				flags |= FIEMAP_EXTENT_UNWRITTEN;
 		}
 
@@ -2576,7 +2577,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 	unsigned num;
 	ext4_lblk_t ex_ee_block;
 	unsigned short ex_ee_len;
-	unsigned uninitialized = 0;
+	unsigned unwritten = 0;
 	struct ext4_extent *ex;
 	ext4_fsblk_t pblk;
 
@@ -2623,13 +2624,13 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 	while (ex >= EXT_FIRST_EXTENT(eh) &&
 			ex_ee_block + ex_ee_len > start) {
 
-		if (ext4_ext_is_uninitialized(ex))
-			uninitialized = 1;
+		if (ext4_ext_is_unwritten(ex))
+			unwritten = 1;
 		else
-			uninitialized = 0;
+			unwritten = 0;
 
 		ext_debug("remove ext %u:[%d]%d\n", ex_ee_block,
-			 uninitialized, ex_ee_len);
+			  unwritten, ex_ee_len);
 		path[depth].p_ext = ex;
 
 		a = ex_ee_block > start ? ex_ee_block : start;
@@ -2701,11 +2702,11 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 
 		ex->ee_len = cpu_to_le16(num);
 		/*
-		 * Do not mark uninitialized if all the blocks in the
+		 * Do not mark unwritten if all the blocks in the
 		 * extent have been removed.
 		 */
-		if (uninitialized && num)
-			ext4_ext_mark_uninitialized(ex);
+		if (unwritten && num)
+			ext4_ext_mark_unwritten(ex);
 		/*
 		 * If the extent was completely released,
 		 * we need to remove it from the leaf
@@ -2854,9 +2855,9 @@ again:
 		    end < ee_block + ext4_ext_get_actual_len(ex) - 1) {
 			int split_flag = 0;
 
-			if (ext4_ext_is_uninitialized(ex))
-				split_flag = EXT4_EXT_MARK_UNINIT1 |
-					     EXT4_EXT_MARK_UNINIT2;
+			if (ext4_ext_is_unwritten(ex))
+				split_flag = EXT4_EXT_MARK_UNWRIT1 |
+					     EXT4_EXT_MARK_UNWRIT2;
 
 			/*
 			 * Split the extent in two so that 'end' is the last
@@ -3113,7 +3114,7 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
  * @path: the path to the extent
  * @split: the logical block where the extent is splitted.
  * @split_flags: indicates if the extent could be zeroout if split fails, and
- *		 the states(init or uninit) of new extents.
+ *		 the states(init or unwritten) of new extents.
  * @flags: flags used to insert new extent to extent tree.
  *
  *
@@ -3155,10 +3156,10 @@ static int ext4_split_extent_at(handle_t *handle,
 	newblock = split - ee_block + ext4_ext_pblock(ex);
 
 	BUG_ON(split < ee_block || split >= (ee_block + ee_len));
-	BUG_ON(!ext4_ext_is_uninitialized(ex) &&
+	BUG_ON(!ext4_ext_is_unwritten(ex) &&
 	       split_flag & (EXT4_EXT_MAY_ZEROOUT |
-			     EXT4_EXT_MARK_UNINIT1 |
-			     EXT4_EXT_MARK_UNINIT2));
+			     EXT4_EXT_MARK_UNWRIT1 |
+			     EXT4_EXT_MARK_UNWRIT2));
 
 	err = ext4_ext_get_access(handle, inode, path + depth);
 	if (err)
@@ -3170,8 +3171,8 @@ static int ext4_split_extent_at(handle_t *handle,
 		 * then we just change the state of the extent, and splitting
 		 * is not needed.
 		 */
-		if (split_flag & EXT4_EXT_MARK_UNINIT2)
-			ext4_ext_mark_uninitialized(ex);
+		if (split_flag & EXT4_EXT_MARK_UNWRIT2)
+			ext4_ext_mark_unwritten(ex);
 		else
 			ext4_ext_mark_initialized(ex);
 
@@ -3185,8 +3186,8 @@ static int ext4_split_extent_at(handle_t *handle,
 	/* case a */
 	memcpy(&orig_ex, ex, sizeof(orig_ex));
 	ex->ee_len = cpu_to_le16(split - ee_block);
-	if (split_flag & EXT4_EXT_MARK_UNINIT1)
-		ext4_ext_mark_uninitialized(ex);
+	if (split_flag & EXT4_EXT_MARK_UNWRIT1)
+		ext4_ext_mark_unwritten(ex);
 
 	/*
 	 * path may lead to new leaf, not to original leaf any more
@@ -3200,8 +3201,8 @@ static int ext4_split_extent_at(handle_t *handle,
 	ex2->ee_block = cpu_to_le32(split);
 	ex2->ee_len   = cpu_to_le16(ee_len - (split - ee_block));
 	ext4_ext_store_pblock(ex2, newblock);
-	if (split_flag & EXT4_EXT_MARK_UNINIT2)
-		ext4_ext_mark_uninitialized(ex2);
+	if (split_flag & EXT4_EXT_MARK_UNWRIT2)
+		ext4_ext_mark_unwritten(ex2);
 
 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
 	if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
@@ -3278,7 +3279,7 @@ static int ext4_split_extent(handle_t *handle,
 	struct ext4_extent *ex;
 	unsigned int ee_len, depth;
 	int err = 0;
-	int uninitialized;
+	int unwritten;
 	int split_flag1, flags1;
 	int allocated = map->m_len;
 
@@ -3286,14 +3287,14 @@ static int ext4_split_extent(handle_t *handle,
 	ex = path[depth].p_ext;
 	ee_block = le32_to_cpu(ex->ee_block);
 	ee_len = ext4_ext_get_actual_len(ex);
-	uninitialized = ext4_ext_is_uninitialized(ex);
+	unwritten = ext4_ext_is_unwritten(ex);
 
 	if (map->m_lblk + map->m_len < ee_block + ee_len) {
 		split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT;
 		flags1 = flags | EXT4_GET_BLOCKS_PRE_IO;
-		if (uninitialized)
-			split_flag1 |= EXT4_EXT_MARK_UNINIT1 |
-				       EXT4_EXT_MARK_UNINIT2;
+		if (unwritten)
+			split_flag1 |= EXT4_EXT_MARK_UNWRIT1 |
+				       EXT4_EXT_MARK_UNWRIT2;
 		if (split_flag & EXT4_EXT_DATA_VALID2)
 			split_flag1 |= EXT4_EXT_DATA_VALID1;
 		err = ext4_split_extent_at(handle, inode, path,
@@ -3313,15 +3314,20 @@ static int ext4_split_extent(handle_t *handle,
 		return PTR_ERR(path);
 	depth = ext_depth(inode);
 	ex = path[depth].p_ext;
-	uninitialized = ext4_ext_is_uninitialized(ex);
+	if (!ex) {
+		EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+				 (unsigned long) map->m_lblk);
+		return -EIO;
+	}
+	unwritten = ext4_ext_is_unwritten(ex);
 	split_flag1 = 0;
 
 	if (map->m_lblk >= ee_block) {
 		split_flag1 = split_flag & EXT4_EXT_DATA_VALID2;
-		if (uninitialized) {
-			split_flag1 |= EXT4_EXT_MARK_UNINIT1;
+		if (unwritten) {
+			split_flag1 |= EXT4_EXT_MARK_UNWRIT1;
 			split_flag1 |= split_flag & (EXT4_EXT_MAY_ZEROOUT |
-						     EXT4_EXT_MARK_UNINIT2);
+						     EXT4_EXT_MARK_UNWRIT2);
 		}
 		err = ext4_split_extent_at(handle, inode, path,
 				map->m_lblk, split_flag1, flags);
@@ -3336,16 +3342,16 @@ out:
 
 /*
  * This function is called by ext4_ext_map_blocks() if someone tries to write
- * to an uninitialized extent. It may result in splitting the uninitialized
+ * to an unwritten extent. It may result in splitting the unwritten
  * extent into multiple extents (up to three - one initialized and two
- * uninitialized).
+ * unwritten).
  * There are three possibilities:
  *   a> There is no split required: Entire extent should be initialized
  *   b> Splits in two extents: Write is happening at either end of the extent
  *   c> Splits in three extents: Somone is writing in middle of the extent
  *
  * Pre-conditions:
- *  - The extent pointed to by 'path' is uninitialized.
+ *  - The extent pointed to by 'path' is unwritten.
  *  - The extent pointed to by 'path' contains a superset
  *    of the logical span [map->m_lblk, map->m_lblk + map->m_len).
  *
@@ -3391,12 +3397,12 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 	trace_ext4_ext_convert_to_initialized_enter(inode, map, ex);
 
 	/* Pre-conditions */
-	BUG_ON(!ext4_ext_is_uninitialized(ex));
+	BUG_ON(!ext4_ext_is_unwritten(ex));
 	BUG_ON(!in_range(map->m_lblk, ee_block, ee_len));
 
 	/*
 	 * Attempt to transfer newly initialized blocks from the currently
-	 * uninitialized extent to its neighbor. This is much cheaper
+	 * unwritten extent to its neighbor. This is much cheaper
 	 * than an insertion followed by a merge as those involve costly
 	 * memmove() calls. Transferring to the left is the common case in
 	 * steady state for workloads doing fallocate(FALLOC_FL_KEEP_SIZE)
@@ -3432,7 +3438,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 		 * - C4: abut_ex can receive the additional blocks without
 		 *   overflowing the (initialized) length limit.
 		 */
-		if ((!ext4_ext_is_uninitialized(abut_ex)) &&		/*C1*/
+		if ((!ext4_ext_is_unwritten(abut_ex)) &&		/*C1*/
 			((prev_lblk + prev_len) == ee_block) &&		/*C2*/
 			((prev_pblk + prev_len) == ee_pblk) &&		/*C3*/
 			(prev_len < (EXT_INIT_MAX_LEN - map_len))) {	/*C4*/
@@ -3447,7 +3453,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 			ex->ee_block = cpu_to_le32(ee_block + map_len);
 			ext4_ext_store_pblock(ex, ee_pblk + map_len);
 			ex->ee_len = cpu_to_le16(ee_len - map_len);
-			ext4_ext_mark_uninitialized(ex); /* Restore the flag */
+			ext4_ext_mark_unwritten(ex); /* Restore the flag */
 
 			/* Extend abut_ex by 'map_len' blocks */
 			abut_ex->ee_len = cpu_to_le16(prev_len + map_len);
@@ -3478,7 +3484,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 		 * - C4: abut_ex can receive the additional blocks without
 		 *   overflowing the (initialized) length limit.
 		 */
-		if ((!ext4_ext_is_uninitialized(abut_ex)) &&		/*C1*/
+		if ((!ext4_ext_is_unwritten(abut_ex)) &&		/*C1*/
 		    ((map->m_lblk + map_len) == next_lblk) &&		/*C2*/
 		    ((ee_pblk + ee_len) == next_pblk) &&		/*C3*/
 		    (next_len < (EXT_INIT_MAX_LEN - map_len))) {	/*C4*/
@@ -3493,7 +3499,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 			abut_ex->ee_block = cpu_to_le32(next_lblk - map_len);
 			ext4_ext_store_pblock(abut_ex, next_pblk - map_len);
 			ex->ee_len = cpu_to_le16(ee_len - map_len);
-			ext4_ext_mark_uninitialized(ex); /* Restore the flag */
+			ext4_ext_mark_unwritten(ex); /* Restore the flag */
 
 			/* Extend abut_ex by 'map_len' blocks */
 			abut_ex->ee_len = cpu_to_le16(next_len + map_len);
@@ -3598,26 +3604,26 @@ out:
 /*
  * This function is called by ext4_ext_map_blocks() from
  * ext4_get_blocks_dio_write() when DIO to write
- * to an uninitialized extent.
+ * to an unwritten extent.
  *
- * Writing to an uninitialized extent may result in splitting the uninitialized
- * extent into multiple initialized/uninitialized extents (up to three)
+ * Writing to an unwritten extent may result in splitting the unwritten
+ * extent into multiple initialized/unwritten extents (up to three)
  * There are three possibilities:
- *   a> There is no split required: Entire extent should be uninitialized
+ *   a> There is no split required: Entire extent should be unwritten
  *   b> Splits in two extents: Write is happening at either end of the extent
  *   c> Splits in three extents: Somone is writing in middle of the extent
  *
  * This works the same way in the case of initialized -> unwritten conversion.
  *
  * One of more index blocks maybe needed if the extent tree grow after
- * the uninitialized extent split. To prevent ENOSPC occur at the IO
- * complete, we need to split the uninitialized extent before DIO submit
- * the IO. The uninitialized extent called at this time will be split
- * into three uninitialized extent(at most). After IO complete, the part
+ * the unwritten extent split. To prevent ENOSPC occur at the IO
+ * complete, we need to split the unwritten extent before DIO submit
+ * the IO. The unwritten extent called at this time will be split
+ * into three unwritten extent(at most). After IO complete, the part
  * being filled will be convert to initialized by the end_io callback function
  * via ext4_convert_unwritten_extents().
  *
- * Returns the size of uninitialized extent to be written on success.
+ * Returns the size of unwritten extent to be written on success.
  */
 static int ext4_split_convert_extents(handle_t *handle,
 					struct inode *inode,
@@ -3655,7 +3661,7 @@ static int ext4_split_convert_extents(handle_t *handle,
 	} else if (flags & EXT4_GET_BLOCKS_CONVERT) {
 		split_flag |= ee_block + ee_len <= eof_block ?
 			      EXT4_EXT_MAY_ZEROOUT : 0;
-		split_flag |= (EXT4_EXT_MARK_UNINIT2 | EXT4_EXT_DATA_VALID2);
+		split_flag |= (EXT4_EXT_MARK_UNWRIT2 | EXT4_EXT_DATA_VALID2);
 	}
 	flags |= EXT4_GET_BLOCKS_PRE_IO;
 	return ext4_split_extent(handle, inode, path, map, split_flag, flags);
@@ -3694,13 +3700,19 @@ static int ext4_convert_initialized_extents(handle_t *handle,
 		}
 		depth = ext_depth(inode);
 		ex = path[depth].p_ext;
+		if (!ex) {
+			EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+					 (unsigned long) map->m_lblk);
+			err = -EIO;
+			goto out;
+		}
 	}
 
 	err = ext4_ext_get_access(handle, inode, path + depth);
 	if (err)
 		goto out;
-	/* first mark the extent as uninitialized */
-	ext4_ext_mark_uninitialized(ex);
+	/* first mark the extent as unwritten */
+	ext4_ext_mark_unwritten(ex);
 
 	/* note: ext4_ext_correct_indexes() isn't needed here because
 	 * borders are not changed
@@ -3960,10 +3972,10 @@ ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
 
 	/*
 	 * Make sure that the extent is no bigger than we support with
-	 * uninitialized extent
+	 * unwritten extent
 	 */
-	if (map->m_len > EXT_UNINIT_MAX_LEN)
-		map->m_len = EXT_UNINIT_MAX_LEN / 2;
+	if (map->m_len > EXT_UNWRITTEN_MAX_LEN)
+		map->m_len = EXT_UNWRITTEN_MAX_LEN / 2;
 
 	ret = ext4_convert_initialized_extents(handle, inode, map,
 						path);
@@ -3982,7 +3994,7 @@ ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
 }
 
 static int
-ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
 			struct ext4_map_blocks *map,
 			struct ext4_ext_path *path, int flags,
 			unsigned int allocated, ext4_fsblk_t newblock)
@@ -3991,19 +4003,19 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 	int err = 0;
 	ext4_io_end_t *io = ext4_inode_aio(inode);
 
-	ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical "
+	ext_debug("ext4_ext_handle_unwritten_extents: inode %lu, logical "
 		  "block %llu, max_blocks %u, flags %x, allocated %u\n",
 		  inode->i_ino, (unsigned long long)map->m_lblk, map->m_len,
 		  flags, allocated);
 	ext4_ext_show_leaf(inode, path);
 
 	/*
-	 * When writing into uninitialized space, we should not fail to
+	 * When writing into unwritten space, we should not fail to
 	 * allocate metadata blocks for the new extent block if needed.
 	 */
 	flags |= EXT4_GET_BLOCKS_METADATA_NOFAIL;
 
-	trace_ext4_ext_handle_uninitialized_extents(inode, map, flags,
+	trace_ext4_ext_handle_unwritten_extents(inode, map, flags,
 						    allocated, newblock);
 
 	/* get_block() before submit the IO, split the extent */
@@ -4022,8 +4034,6 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 		else
 			ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
 		map->m_flags |= EXT4_MAP_UNWRITTEN;
-		if (ext4_should_dioread_nolock(inode))
-			map->m_flags |= EXT4_MAP_UNINIT;
 		goto out;
 	}
 	/* IO end_io complete, convert the filled extent to written */
@@ -4048,7 +4058,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 	 * repeat fallocate creation request
 	 * we already have an unwritten extent
 	 */
-	if (flags & EXT4_GET_BLOCKS_UNINIT_EXT) {
+	if (flags & EXT4_GET_BLOCKS_UNWRIT_EXT) {
 		map->m_flags |= EXT4_MAP_UNWRITTEN;
 		goto map_out;
 	}
@@ -4299,7 +4309,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 
 
 		/*
-		 * Uninitialized extents are treated as holes, except that
+		 * unwritten extents are treated as holes, except that
 		 * we split out initialized portions during a write.
 		 */
 		ee_len = ext4_ext_get_actual_len(ex);
@@ -4318,16 +4328,16 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			 * If the extent is initialized check whether the
 			 * caller wants to convert it to unwritten.
 			 */
-			if ((!ext4_ext_is_uninitialized(ex)) &&
+			if ((!ext4_ext_is_unwritten(ex)) &&
 			    (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) {
 				allocated = ext4_ext_convert_initialized_extent(
 						handle, inode, map, path, flags,
 						allocated, newblock);
 				goto out2;
-			} else if (!ext4_ext_is_uninitialized(ex))
+			} else if (!ext4_ext_is_unwritten(ex))
 				goto out;
 
-			ret = ext4_ext_handle_uninitialized_extents(
+			ret = ext4_ext_handle_unwritten_extents(
 				handle, inode, map, path, flags,
 				allocated, newblock);
 			if (ret < 0)
@@ -4399,15 +4409,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	/*
 	 * See if request is beyond maximum number of blocks we can have in
 	 * a single extent. For an initialized extent this limit is
-	 * EXT_INIT_MAX_LEN and for an uninitialized extent this limit is
-	 * EXT_UNINIT_MAX_LEN.
+	 * EXT_INIT_MAX_LEN and for an unwritten extent this limit is
+	 * EXT_UNWRITTEN_MAX_LEN.
 	 */
 	if (map->m_len > EXT_INIT_MAX_LEN &&
-	    !(flags & EXT4_GET_BLOCKS_UNINIT_EXT))
+	    !(flags & EXT4_GET_BLOCKS_UNWRIT_EXT))
 		map->m_len = EXT_INIT_MAX_LEN;
-	else if (map->m_len > EXT_UNINIT_MAX_LEN &&
-		 (flags & EXT4_GET_BLOCKS_UNINIT_EXT))
-		map->m_len = EXT_UNINIT_MAX_LEN;
+	else if (map->m_len > EXT_UNWRITTEN_MAX_LEN &&
+		 (flags & EXT4_GET_BLOCKS_UNWRIT_EXT))
+		map->m_len = EXT_UNWRITTEN_MAX_LEN;
 
 	/* Check if we can really insert (m_lblk)::(m_lblk + m_len) extent */
 	newex.ee_len = cpu_to_le16(map->m_len);
@@ -4455,21 +4465,19 @@ got_allocated_blocks:
 	/* try to insert new extent into found leaf and return */
 	ext4_ext_store_pblock(&newex, newblock + offset);
 	newex.ee_len = cpu_to_le16(ar.len);
-	/* Mark uninitialized */
-	if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
-		ext4_ext_mark_uninitialized(&newex);
+	/* Mark unwritten */
+	if (flags & EXT4_GET_BLOCKS_UNWRIT_EXT){
+		ext4_ext_mark_unwritten(&newex);
 		map->m_flags |= EXT4_MAP_UNWRITTEN;
 		/*
 		 * io_end structure was created for every IO write to an
-		 * uninitialized extent. To avoid unnecessary conversion,
+		 * unwritten extent. To avoid unnecessary conversion,
 		 * here we flag the IO that really needs the conversion.
 		 * For non asycn direct IO case, flag the inode state
 		 * that we need to perform conversion when IO is done.
 		 */
 		if ((flags & EXT4_GET_BLOCKS_PRE_IO))
 			set_unwritten = 1;
-		if (ext4_should_dioread_nolock(inode))
-			map->m_flags |= EXT4_MAP_UNINIT;
 	}
 
 	err = 0;
@@ -4596,9 +4604,9 @@ got_allocated_blocks:
 
 	/*
 	 * Cache the extent and update transaction to commit on fdatasync only
-	 * when it is _not_ an uninitialized extent.
+	 * when it is _not_ an unwritten extent.
 	 */
-	if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0)
+	if ((flags & EXT4_GET_BLOCKS_UNWRIT_EXT) == 0)
 		ext4_update_inode_fsync_trans(handle, inode, 1);
 	else
 		ext4_update_inode_fsync_trans(handle, inode, 0);
@@ -4672,7 +4680,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
 	 * that it doesn't get unnecessarily split into multiple
 	 * extents.
 	 */
-	if (len <= EXT_UNINIT_MAX_LEN)
+	if (len <= EXT_UNWRITTEN_MAX_LEN)
 		flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
 
 	/*
@@ -4761,7 +4769,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 	else
 		max_blocks -= lblk;
 
-	flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT |
+	flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT |
 		EXT4_GET_BLOCKS_CONVERT_UNWRITTEN;
 	if (mode & FALLOC_FL_KEEP_SIZE)
 		flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
@@ -4851,6 +4859,14 @@ out_mutex:
 	return ret;
 }
 
+#ifdef CONFIG_EXT4_DEBUG
+int ext4_fallocate_mode_block __read_mostly;
+
+module_param_named(fallocate_mode_block, ext4_fallocate_mode_block, int, 0644);
+MODULE_PARM_DESC(fallocate_mode_block,
+		 "Fallocate modes which are blocked for debugging purposes");
+#endif
+
 /*
  * preallocate space for a file. This implements ext4's fallocate file
  * operation, which gets called from sys_fallocate system call.
@@ -4870,6 +4886,15 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	struct timespec tv;
 	unsigned int blkbits = inode->i_blkbits;
 
+#ifdef CONFIG_EXT4_DEBUG
+	/*
+	 * For debugging purposes, allow certain fallocate operations
+	 * to be disabled
+	 */
+	if (unlikely(mode & ext4_fallocate_mode_block))
+		return -EOPNOTSUPP;
+#endif
+
 	/* Return error if mode is not supported */
 	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
 		     FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE))
@@ -4878,9 +4903,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	if (mode & FALLOC_FL_PUNCH_HOLE)
 		return ext4_punch_hole(inode, offset, len);
 
-	if (mode & FALLOC_FL_COLLAPSE_RANGE)
-		return ext4_collapse_range(inode, offset, len);
-
 	ret = ext4_convert_inline_data(inode);
 	if (ret)
 		return ret;
@@ -4892,6 +4914,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 		return -EOPNOTSUPP;
 
+	if (mode & FALLOC_FL_COLLAPSE_RANGE)
+		return ext4_collapse_range(inode, offset, len);
+
 	if (mode & FALLOC_FL_ZERO_RANGE)
 		return ext4_zero_range(file, offset, len, mode);
 
@@ -4904,7 +4929,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
 		- lblk;
 
-	flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT;
+	flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT;
 	if (mode & FALLOC_FL_KEEP_SIZE)
 		flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
 
@@ -5229,11 +5254,11 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
 			if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr))
 				update = 1;
 
-			*start = ex_last->ee_block +
+			*start = le32_to_cpu(ex_last->ee_block) +
 				ext4_ext_get_actual_len(ex_last);
 
 			while (ex_start <= ex_last) {
-				ex_start->ee_block -= shift;
+				le32_add_cpu(&ex_start->ee_block, -shift);
 				if (ex_start >
 					EXT_FIRST_EXTENT(path[depth].p_hdr)) {
 					if (ext4_ext_try_to_merge_right(inode,
@@ -5255,7 +5280,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
 		if (err)
 			goto out;
 
-		path[depth].p_idx->ei_block -= shift;
+		le32_add_cpu(&path[depth].p_idx->ei_block, -shift);
 		err = ext4_ext_dirty(handle, inode, path + depth);
 		if (err)
 			goto out;
@@ -5300,7 +5325,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
 		return ret;
 	}
 
-	stop_block = extent->ee_block + ext4_ext_get_actual_len(extent);
+	stop_block = le32_to_cpu(extent->ee_block) +
+			ext4_ext_get_actual_len(extent);
 	ext4_ext_drop_refs(path);
 	kfree(path);
 
@@ -5313,10 +5339,18 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
 	 * enough to accomodate the shift.
 	 */
 	path = ext4_ext_find_extent(inode, start - 1, NULL, 0);
+	if (IS_ERR(path))
+		return PTR_ERR(path);
 	depth = path->p_depth;
 	extent =  path[depth].p_ext;
-	ex_start = extent->ee_block;
-	ex_end = extent->ee_block + ext4_ext_get_actual_len(extent);
+	if (extent) {
+		ex_start = le32_to_cpu(extent->ee_block);
+		ex_end = le32_to_cpu(extent->ee_block) +
+			ext4_ext_get_actual_len(extent);
+	} else {
+		ex_start = 0;
+		ex_end = 0;
+	}
 	ext4_ext_drop_refs(path);
 	kfree(path);
 
@@ -5331,7 +5365,13 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
 			return PTR_ERR(path);
 		depth = path->p_depth;
 		extent = path[depth].p_ext;
-		current_block = extent->ee_block;
+		if (!extent) {
+			EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+					 (unsigned long) start);
+			return -EIO;
+		}
+
+		current_block = le32_to_cpu(extent->ee_block);
 		if (start > current_block) {
 			/* Hole, move to the next extent */
 			ret = mext_next_extent(inode, path, &extent);
@@ -5368,8 +5408,6 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 	loff_t new_size;
 	int ret;
 
-	BUG_ON(offset + len > i_size_read(inode));
-
 	/* Collapse range works only on fs block size aligned offsets. */
 	if (offset & (EXT4_BLOCK_SIZE(sb) - 1) ||
 	    len & (EXT4_BLOCK_SIZE(sb) - 1))
@@ -5383,6 +5421,13 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 	punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb);
 	punch_stop = (offset + len) >> EXT4_BLOCK_SIZE_BITS(sb);
 
+	/* Call ext4_force_commit to flush all data in case of data=journal. */
+	if (ext4_should_journal_data(inode)) {
+		ret = ext4_force_commit(inode->i_sb);
+		if (ret)
+			return ret;
+	}
+
 	/* Write out all dirty pages */
 	ret = filemap_write_and_wait_range(inode->i_mapping, offset, -1);
 	if (ret)
@@ -5391,14 +5436,12 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 	/* Take mutex lock */
 	mutex_lock(&inode->i_mutex);
 
-	/* It's not possible punch hole on append only file */
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
-		ret = -EPERM;
-		goto out_mutex;
-	}
-
-	if (IS_SWAPFILE(inode)) {
-		ret = -ETXTBSY;
+	/*
+	 * There is no need to overlap collapse range with EOF, in which case
+	 * it is effectively a truncate operation
+	 */
+	if (offset + len >= i_size_read(inode)) {
+		ret = -EINVAL;
 		goto out_mutex;
 	}
 
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 0a014a7194b2..98c90f5834ee 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -433,7 +433,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
 		ee_start = ext4_ext_pblock(ex);
 		ee_len = ext4_ext_get_actual_len(ex);
 
-		ee_status = ext4_ext_is_uninitialized(ex) ? 1 : 0;
+		ee_status = ext4_ext_is_unwritten(ex) ? 1 : 0;
 		es_status = ext4_es_is_unwritten(es) ? 1 : 0;
 
 		/*
@@ -810,7 +810,7 @@ retry:
 
 			newes.es_lblk = end + 1;
 			newes.es_len = len2;
-			block = 0x7FDEADBEEF;
+			block = 0x7FDEADBEEFULL;
 			if (ext4_es_is_written(&orig_es) ||
 			    ext4_es_is_unwritten(&orig_es))
 				block = ext4_es_pblock(&orig_es) +
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index ca7502d89fde..7d55a591deba 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -82,7 +82,7 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
 	size_t count = iov_length(iov, nr_segs);
 	loff_t final_size = pos + count;
 
-	if (pos >= inode->i_size)
+	if (pos >= i_size_read(inode))
 		return 0;
 
 	if ((pos & blockmask) || (final_size & blockmask))
@@ -92,58 +92,91 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
 }
 
 static ssize_t
-ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
-		    unsigned long nr_segs, loff_t pos)
+ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
+		unsigned long nr_segs, loff_t pos)
 {
 	struct file *file = iocb->ki_filp;
-	struct inode *inode = file->f_mapping->host;
+	struct inode *inode = file_inode(iocb->ki_filp);
+	struct mutex *aio_mutex = NULL;
 	struct blk_plug plug;
-	int unaligned_aio = 0;
-	ssize_t ret;
+	int o_direct = file->f_flags & O_DIRECT;
 	int overwrite = 0;
 	size_t length = iov_length(iov, nr_segs);
+	ssize_t ret;
 
-	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
-	    !is_sync_kiocb(iocb))
-		unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos);
+	BUG_ON(iocb->ki_pos != pos);
 
-	/* Unaligned direct AIO must be serialized; see comment above */
-	if (unaligned_aio) {
-		mutex_lock(ext4_aio_mutex(inode));
+	/*
+	 * Unaligned direct AIO must be serialized; see comment above
+	 * In the case of O_APPEND, assume that we must always serialize
+	 */
+	if (o_direct &&
+	    ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
+	    !is_sync_kiocb(iocb) &&
+	    (file->f_flags & O_APPEND ||
+	     ext4_unaligned_aio(inode, iov, nr_segs, pos))) {
+		aio_mutex = ext4_aio_mutex(inode);
+		mutex_lock(aio_mutex);
 		ext4_unwritten_wait(inode);
 	}
 
-	BUG_ON(iocb->ki_pos != pos);
-
 	mutex_lock(&inode->i_mutex);
-	blk_start_plug(&plug);
+	if (file->f_flags & O_APPEND)
+		iocb->ki_pos = pos = i_size_read(inode);
+
+	/*
+	 * If we have encountered a bitmap-format file, the size limit
+	 * is smaller than s_maxbytes, which is for extent-mapped files.
+	 */
+	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
+		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 
-	iocb->private = &overwrite;
+		if ((pos > sbi->s_bitmap_maxbytes) ||
+		    (pos == sbi->s_bitmap_maxbytes && length > 0)) {
+			mutex_unlock(&inode->i_mutex);
+			ret = -EFBIG;
+			goto errout;
+		}
 
-	/* check whether we do a DIO overwrite or not */
-	if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
-	    !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
-		struct ext4_map_blocks map;
-		unsigned int blkbits = inode->i_blkbits;
-		int err, len;
+		if (pos + length > sbi->s_bitmap_maxbytes) {
+			nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
+					      sbi->s_bitmap_maxbytes - pos);
+		}
+	}
 
-		map.m_lblk = pos >> blkbits;
-		map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits)
-			- map.m_lblk;
-		len = map.m_len;
+	if (o_direct) {
+		blk_start_plug(&plug);
 
-		err = ext4_map_blocks(NULL, inode, &map, 0);
-		/*
-		 * 'err==len' means that all of blocks has been preallocated no
-		 * matter they are initialized or not.  For excluding
-		 * uninitialized extents, we need to check m_flags.  There are
-		 * two conditions that indicate for initialized extents.
-		 * 1) If we hit extent cache, EXT4_MAP_MAPPED flag is returned;
-		 * 2) If we do a real lookup, non-flags are returned.
-		 * So we should check these two conditions.
-		 */
-		if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
-			overwrite = 1;
+		iocb->private = &overwrite;
+
+		/* check whether we do a DIO overwrite or not */
+		if (ext4_should_dioread_nolock(inode) && !aio_mutex &&
+		    !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
+			struct ext4_map_blocks map;
+			unsigned int blkbits = inode->i_blkbits;
+			int err, len;
+
+			map.m_lblk = pos >> blkbits;
+			map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits)
+				- map.m_lblk;
+			len = map.m_len;
+
+			err = ext4_map_blocks(NULL, inode, &map, 0);
+			/*
+			 * 'err==len' means that all of blocks has
+			 * been preallocated no matter they are
+			 * initialized or not.  For excluding
+			 * unwritten extents, we need to check
+			 * m_flags.  There are two conditions that
+			 * indicate for initialized extents.  1) If we
+			 * hit extent cache, EXT4_MAP_MAPPED flag is
+			 * returned; 2) If we do a real lookup,
+			 * non-flags are returned.  So we should check
+			 * these two conditions.
+			 */
+			if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
+				overwrite = 1;
+		}
 	}
 
 	ret = __generic_file_aio_write(iocb, iov, nr_segs);
@@ -156,45 +189,12 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
 		if (err < 0)
 			ret = err;
 	}
-	blk_finish_plug(&plug);
-
-	if (unaligned_aio)
-		mutex_unlock(ext4_aio_mutex(inode));
-
-	return ret;
-}
-
-static ssize_t
-ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
-		unsigned long nr_segs, loff_t pos)
-{
-	struct inode *inode = file_inode(iocb->ki_filp);
-	ssize_t ret;
-
-	/*
-	 * If we have encountered a bitmap-format file, the size limit
-	 * is smaller than s_maxbytes, which is for extent-mapped files.
-	 */
-
-	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
-		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-		size_t length = iov_length(iov, nr_segs);
-
-		if ((pos > sbi->s_bitmap_maxbytes ||
-		    (pos == sbi->s_bitmap_maxbytes && length > 0)))
-			return -EFBIG;
-
-		if (pos + length > sbi->s_bitmap_maxbytes) {
-			nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
-					      sbi->s_bitmap_maxbytes - pos);
-		}
-	}
-
-	if (unlikely(iocb->ki_filp->f_flags & O_DIRECT))
-		ret = ext4_file_dio_write(iocb, iov, nr_segs, pos);
-	else
-		ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+	if (o_direct)
+		blk_finish_plug(&plug);
 
+errout:
+	if (aio_mutex)
+		mutex_unlock(aio_mutex);
 	return ret;
 }
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5b0d2c7d5408..7ae10f002ce9 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -489,8 +489,8 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
  * Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping
  * based files
  *
- * On success, it returns the number of blocks being mapped or allocate.
- * if create==0 and the blocks are pre-allocated and uninitialized block,
+ * On success, it returns the number of blocks being mapped or allocated.
+ * if create==0 and the blocks are pre-allocated and unwritten block,
  * the result buffer head is unmapped. If the create ==1, it will make sure
  * the buffer head is mapped.
  *
@@ -522,6 +522,10 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	if (unlikely(map->m_len > INT_MAX))
 		map->m_len = INT_MAX;
 
+	/* We can handle the block number less than EXT_MAX_BLOCKS */
+	if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS))
+		return -EIO;
+
 	/* Lookup extent status tree firstly */
 	if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
 		ext4_es_lru_add(inode);
@@ -618,7 +622,7 @@ found:
 	map->m_flags &= ~EXT4_MAP_FLAGS;
 
 	/*
-	 * New blocks allocate and/or writing to uninitialized extent
+	 * New blocks allocate and/or writing to unwritten extent
 	 * will possibly result in updating i_data, so we take
 	 * the write lock of i_data_sem, and call get_blocks()
 	 * with create == 1 flag.
@@ -2028,7 +2032,7 @@ static int mpage_process_page_bufs(struct mpage_da_data *mpd,
  * Scan buffers corresponding to changed extent (we expect corresponding pages
  * to be already locked) and update buffer state according to new extent state.
  * We map delalloc buffers to their physical location, clear unwritten bits,
- * and mark buffers as uninit when we perform writes to uninitialized extents
+ * and mark buffers as uninit when we perform writes to unwritten extents
  * and do extent conversion after IO is finished. If the last page is not fully
  * mapped, we update @map to the next extent in the last page that needs
  * mapping. Otherwise we submit the page for IO.
@@ -2122,12 +2126,12 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
 	struct inode *inode = mpd->inode;
 	struct ext4_map_blocks *map = &mpd->map;
 	int get_blocks_flags;
-	int err;
+	int err, dioread_nolock;
 
 	trace_ext4_da_write_pages_extent(inode, map);
 	/*
 	 * Call ext4_map_blocks() to allocate any delayed allocation blocks, or
-	 * to convert an uninitialized extent to be initialized (in the case
+	 * to convert an unwritten extent to be initialized (in the case
 	 * where we have written into one or more preallocated blocks).  It is
 	 * possible that we're going to need more metadata blocks than
 	 * previously reserved. However we must not fail because we're in
@@ -2144,7 +2148,8 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
 	 */
 	get_blocks_flags = EXT4_GET_BLOCKS_CREATE |
 			   EXT4_GET_BLOCKS_METADATA_NOFAIL;
-	if (ext4_should_dioread_nolock(inode))
+	dioread_nolock = ext4_should_dioread_nolock(inode);
+	if (dioread_nolock)
 		get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT;
 	if (map->m_flags & (1 << BH_Delay))
 		get_blocks_flags |= EXT4_GET_BLOCKS_DELALLOC_RESERVE;
@@ -2152,7 +2157,7 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
 	err = ext4_map_blocks(handle, inode, map, get_blocks_flags);
 	if (err < 0)
 		return err;
-	if (map->m_flags & EXT4_MAP_UNINIT) {
+	if (dioread_nolock && (map->m_flags & EXT4_MAP_UNWRITTEN)) {
 		if (!mpd->io_submit.io_end->handle &&
 		    ext4_handle_valid(handle)) {
 			mpd->io_submit.io_end->handle = handle->h_rsv_handle;
@@ -2243,13 +2248,23 @@ static int mpage_map_and_submit_extent(handle_t *handle,
 			return err;
 	} while (map->m_len);
 
-	/* Update on-disk size after IO is submitted */
+	/*
+	 * Update on-disk size after IO is submitted.  Races with
+	 * truncate are avoided by checking i_size under i_data_sem.
+	 */
 	disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT;
 	if (disksize > EXT4_I(inode)->i_disksize) {
 		int err2;
-
-		ext4_wb_update_i_disksize(inode, disksize);
+		loff_t i_size;
+
+		down_write(&EXT4_I(inode)->i_data_sem);
+		i_size = i_size_read(inode);
+		if (disksize > i_size)
+			disksize = i_size;
+		if (disksize > EXT4_I(inode)->i_disksize)
+			EXT4_I(inode)->i_disksize = disksize;
 		err2 = ext4_mark_inode_dirty(handle, inode);
+		up_write(&EXT4_I(inode)->i_data_sem);
 		if (err2)
 			ext4_error(inode->i_sb,
 				   "Failed to mark inode %lu dirty",
@@ -3056,9 +3071,9 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
  * preallocated extents, and those write extend the file, no need to
  * fall back to buffered IO.
  *
- * For holes, we fallocate those blocks, mark them as uninitialized
+ * For holes, we fallocate those blocks, mark them as unwritten
  * If those blocks were preallocated, we mark sure they are split, but
- * still keep the range to write as uninitialized.
+ * still keep the range to write as unwritten.
  *
  * The unwritten extents will be converted to written when DIO is completed.
  * For async direct IO, since the IO may still pending when return, we
@@ -3110,12 +3125,12 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
 	 * We could direct write to holes and fallocate.
 	 *
 	 * Allocated blocks to fill the hole are marked as
-	 * uninitialized to prevent parallel buffered read to expose
+	 * unwritten to prevent parallel buffered read to expose
 	 * the stale data before DIO complete the data IO.
 	 *
 	 * As to previously fallocated extents, ext4 get_block will
 	 * just simply mark the buffer mapped but still keep the
-	 * extents uninitialized.
+	 * extents unwritten.
 	 *
 	 * For non AIO case, we will convert those unwritten extents
 	 * to written after return back from blockdev_direct_IO.
@@ -3527,15 +3542,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 	}
 
 	mutex_lock(&inode->i_mutex);
-	/* It's not possible punch hole on append only file */
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
-		ret = -EPERM;
-		goto out_mutex;
-	}
-	if (IS_SWAPFILE(inode)) {
-		ret = -ETXTBSY;
-		goto out_mutex;
-	}
 
 	/* No need to punch hole beyond i_size */
 	if (offset >= inode->i_size)
@@ -4300,12 +4306,15 @@ static int ext4_do_update_inode(handle_t *handle,
 	struct ext4_inode *raw_inode = ext4_raw_inode(iloc);
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	struct buffer_head *bh = iloc->bh;
+	struct super_block *sb = inode->i_sb;
 	int err = 0, rc, block;
-	int need_datasync = 0;
+	int need_datasync = 0, set_large_file = 0;
 	uid_t i_uid;
 	gid_t i_gid;
 
-	/* For fields not not tracking in the in-memory inode,
+	spin_lock(&ei->i_raw_lock);
+
+	/* For fields not tracked in the in-memory inode,
 	 * initialise them to zero for new inodes. */
 	if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
@@ -4343,8 +4352,10 @@ static int ext4_do_update_inode(handle_t *handle,
 	EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
 	EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
 
-	if (ext4_inode_blocks_set(handle, raw_inode, ei))
+	if (ext4_inode_blocks_set(handle, raw_inode, ei)) {
+		spin_unlock(&ei->i_raw_lock);
 		goto out_brelse;
+	}
 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
 	raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF);
 	if (likely(!test_opt2(inode->i_sb, HURD_COMPAT)))
@@ -4356,24 +4367,11 @@ static int ext4_do_update_inode(handle_t *handle,
 		need_datasync = 1;
 	}
 	if (ei->i_disksize > 0x7fffffffULL) {
-		struct super_block *sb = inode->i_sb;
 		if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
 				EXT4_FEATURE_RO_COMPAT_LARGE_FILE) ||
 				EXT4_SB(sb)->s_es->s_rev_level ==
-				cpu_to_le32(EXT4_GOOD_OLD_REV)) {
-			/* If this is the first large file
-			 * created, add a flag to the superblock.
-			 */
-			err = ext4_journal_get_write_access(handle,
-					EXT4_SB(sb)->s_sbh);
-			if (err)
-				goto out_brelse;
-			ext4_update_dynamic_rev(sb);
-			EXT4_SET_RO_COMPAT_FEATURE(sb,
-					EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
-			ext4_handle_sync(handle);
-			err = ext4_handle_dirty_super(handle, sb);
-		}
+		    cpu_to_le32(EXT4_GOOD_OLD_REV))
+			set_large_file = 1;
 	}
 	raw_inode->i_generation = cpu_to_le32(inode->i_generation);
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
@@ -4405,12 +4403,23 @@ static int ext4_do_update_inode(handle_t *handle,
 
 	ext4_inode_csum_set(inode, raw_inode, ei);
 
+	spin_unlock(&ei->i_raw_lock);
+
 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
 	rc = ext4_handle_dirty_metadata(handle, NULL, bh);
 	if (!err)
 		err = rc;
 	ext4_clear_inode_state(inode, EXT4_STATE_NEW);
-
+	if (set_large_file) {
+		err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+		if (err)
+			goto out_brelse;
+		ext4_update_dynamic_rev(sb);
+		EXT4_SET_RO_COMPAT_FEATURE(sb,
+					   EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
+		ext4_handle_sync(handle);
+		err = ext4_handle_dirty_super(handle, sb);
+	}
 	ext4_update_inode_fsync_trans(handle, inode, need_datasync);
 out_brelse:
 	brelse(bh);
@@ -4423,21 +4432,20 @@ out_brelse:
  *
  * We are called from a few places:
  *
- * - Within generic_file_write() for O_SYNC files.
+ * - Within generic_file_aio_write() -> generic_write_sync() for O_SYNC files.
  *   Here, there will be no transaction running. We wait for any running
  *   transaction to commit.
  *
- * - Within sys_sync(), kupdate and such.
- *   We wait on commit, if tol to.
+ * - Within flush work (sys_sync(), kupdate and such).
+ *   We wait on commit, if told to.
  *
- * - Within prune_icache() (PF_MEMALLOC == true)
- *   Here we simply return.  We can't afford to block kswapd on the
- *   journal commit.
+ * - Within iput_final() -> write_inode_now()
+ *   We wait on commit, if told to.
  *
  * In all cases it is actually safe for us to return without doing anything,
  * because the inode has been copied into a raw inode buffer in
- * ext4_mark_inode_dirty().  This is a correctness thing for O_SYNC and for
- * knfsd.
+ * ext4_mark_inode_dirty().  This is a correctness thing for WB_SYNC_ALL
+ * writeback.
  *
  * Note that we are absolutely dependent upon all inode dirtiers doing the
  * right thing: they *must* call mark_inode_dirty() after dirtying info in
@@ -4449,15 +4457,15 @@ out_brelse:
  *	stuff();
  *	inode->i_size = expr;
  *
- * is in error because a kswapd-driven write_inode() could occur while
- * `stuff()' is running, and the new i_size will be lost.  Plus the inode
- * will no longer be on the superblock's dirty inode list.
+ * is in error because write_inode() could occur while `stuff()' is running,
+ * and the new i_size will be lost.  Plus the inode will no longer be on the
+ * superblock's dirty inode list.
  */
 int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	int err;
 
-	if (current->flags & PF_MEMALLOC)
+	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
 		return 0;
 
 	if (EXT4_SB(inode->i_sb)->s_journal) {
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index a888cac76e9c..c8238a26818c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -989,7 +989,7 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
 	poff = block % blocks_per_page;
 	page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
 	if (!page)
-		return -EIO;
+		return -ENOMEM;
 	BUG_ON(page->mapping != inode->i_mapping);
 	e4b->bd_bitmap_page = page;
 	e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
@@ -1003,7 +1003,7 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
 	pnum = block / blocks_per_page;
 	page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
 	if (!page)
-		return -EIO;
+		return -ENOMEM;
 	BUG_ON(page->mapping != inode->i_mapping);
 	e4b->bd_buddy_page = page;
 	return 0;
@@ -1168,7 +1168,11 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
 			unlock_page(page);
 		}
 	}
-	if (page == NULL || !PageUptodate(page)) {
+	if (page == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	if (!PageUptodate(page)) {
 		ret = -EIO;
 		goto err;
 	}
@@ -1197,7 +1201,11 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
 			unlock_page(page);
 		}
 	}
-	if (page == NULL || !PageUptodate(page)) {
+	if (page == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	if (!PageUptodate(page)) {
 		ret = -EIO;
 		goto err;
 	}
@@ -5008,6 +5016,8 @@ error_return:
  */
 static int ext4_trim_extent(struct super_block *sb, int start, int count,
 			     ext4_group_t group, struct ext4_buddy *e4b)
+__releases(bitlock)
+__acquires(bitlock)
 {
 	struct ext4_free_extent ex;
 	int ret = 0;
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 58ee7dc87669..1b809fe51da1 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -57,8 +57,8 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
 static void
 copy_extent_status(struct ext4_extent *src, struct ext4_extent *dest)
 {
-	if (ext4_ext_is_uninitialized(src))
-		ext4_ext_mark_uninitialized(dest);
+	if (ext4_ext_is_unwritten(src))
+		ext4_ext_mark_unwritten(dest);
 	else
 		dest->ee_len = cpu_to_le16(ext4_ext_get_actual_len(dest));
 }
@@ -593,14 +593,14 @@ mext_calc_swap_extents(struct ext4_extent *tmp_dext,
  * @inode:		inode in question
  * @from:		block offset of inode
  * @count:		block count to be checked
- * @uninit:		extents expected to be uninitialized
+ * @unwritten:		extents expected to be unwritten
  * @err:		pointer to save error value
  *
  * Return 1 if all extents in range has expected type, and zero otherwise.
  */
 static int
 mext_check_coverage(struct inode *inode, ext4_lblk_t from, ext4_lblk_t count,
-			  int uninit, int *err)
+		    int unwritten, int *err)
 {
 	struct ext4_ext_path *path = NULL;
 	struct ext4_extent *ext;
@@ -611,7 +611,7 @@ mext_check_coverage(struct inode *inode, ext4_lblk_t from, ext4_lblk_t count,
 		if (*err)
 			goto out;
 		ext = path[ext_depth(inode)].p_ext;
-		if (uninit != ext4_ext_is_uninitialized(ext))
+		if (unwritten != ext4_ext_is_unwritten(ext))
 			goto out;
 		from += ext4_ext_get_actual_len(ext);
 		ext4_ext_drop_refs(path);
@@ -894,7 +894,7 @@ out:
  * @orig_page_offset:		page index on original file
  * @data_offset_in_page:	block index where data swapping starts
  * @block_len_in_page:		the number of blocks to be swapped
- * @uninit:			orig extent is uninitialized or not
+ * @unwritten:			orig extent is unwritten or not
  * @err:			pointer to save return value
  *
  * Save the data in original inode blocks and replace original inode extents
@@ -905,7 +905,7 @@ out:
 static int
 move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
 		  pgoff_t orig_page_offset, int data_offset_in_page,
-		  int block_len_in_page, int uninit, int *err)
+		  int block_len_in_page, int unwritten, int *err)
 {
 	struct inode *orig_inode = file_inode(o_filp);
 	struct page *pagep[2] = {NULL, NULL};
@@ -962,27 +962,27 @@ again:
 	if (unlikely(*err < 0))
 		goto stop_journal;
 	/*
-	 * If orig extent was uninitialized it can become initialized
+	 * If orig extent was unwritten it can become initialized
 	 * at any time after i_data_sem was dropped, in order to
 	 * serialize with delalloc we have recheck extent while we
 	 * hold page's lock, if it is still the case data copy is not
 	 * necessary, just swap data blocks between orig and donor.
 	 */
-	if (uninit) {
+	if (unwritten) {
 		ext4_double_down_write_data_sem(orig_inode, donor_inode);
 		/* If any of extents in range became initialized we have to
 		 * fallback to data copying */
-		uninit = mext_check_coverage(orig_inode, orig_blk_offset,
-					     block_len_in_page, 1, err);
+		unwritten = mext_check_coverage(orig_inode, orig_blk_offset,
+						block_len_in_page, 1, err);
 		if (*err)
 			goto drop_data_sem;
 
-		uninit &= mext_check_coverage(donor_inode, orig_blk_offset,
-					      block_len_in_page, 1, err);
+		unwritten &= mext_check_coverage(donor_inode, orig_blk_offset,
+						 block_len_in_page, 1, err);
 		if (*err)
 			goto drop_data_sem;
 
-		if (!uninit) {
+		if (!unwritten) {
 			ext4_double_up_write_data_sem(orig_inode, donor_inode);
 			goto data_copy;
 		}
@@ -1259,7 +1259,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
 	int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
 	int data_offset_in_page;
 	int block_len_in_page;
-	int uninit;
+	int unwritten;
 
 	if (orig_inode->i_sb != donor_inode->i_sb) {
 		ext4_debug("ext4 move extent: The argument files "
@@ -1391,8 +1391,8 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
 		    !last_extent)
 			continue;
 
-		/* Is original extent is uninitialized */
-		uninit = ext4_ext_is_uninitialized(ext_prev);
+		/* Is original extent is unwritten */
+		unwritten = ext4_ext_is_unwritten(ext_prev);
 
 		data_offset_in_page = seq_start % blocks_per_page;
 
@@ -1432,8 +1432,8 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
 						o_filp, donor_inode,
 						orig_page_offset,
 						data_offset_in_page,
-						block_len_in_page, uninit,
-						&ret);
+						block_len_in_page,
+						unwritten, &ret);
 
 			/* Count how many blocks we have exchanged */
 			*moved_len += block_len_in_page;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 1cb84f78909e..a683f958f128 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2510,8 +2510,7 @@ static int empty_dir(struct inode *inode)
 		 ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize);
 	de = ext4_next_entry(de1, sb->s_blocksize);
 	while (offset < inode->i_size) {
-		if (!bh ||
-		    (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+		if ((void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
 			unsigned int lblock;
 			err = 0;
 			brelse(bh);
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index ab95508e3d40..c18d95b50540 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -308,13 +308,14 @@ static void ext4_end_bio(struct bio *bio, int error)
 	if (error) {
 		struct inode *inode = io_end->inode;
 
-		ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
+		ext4_warning(inode->i_sb, "I/O error %d writing to inode %lu "
 			     "(offset %llu size %ld starting block %llu)",
-			     inode->i_ino,
+			     error, inode->i_ino,
 			     (unsigned long long) io_end->offset,
 			     (long) io_end->size,
 			     (unsigned long long)
 			     bi_sector >> (inode->i_blkbits - 9));
+		mapping_set_error(inode->i_mapping, error);
 	}
 
 	if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f3c667091618..1f8cb1812723 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -879,6 +879,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 		return NULL;
 
 	ei->vfs_inode.i_version = 1;
+	spin_lock_init(&ei->i_raw_lock);
 	INIT_LIST_HEAD(&ei->i_prealloc_list);
 	spin_lock_init(&ei->i_prealloc_lock);
 	ext4_es_init_tree(&ei->i_es_tree);
@@ -3337,7 +3338,7 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
 	 * By default we reserve 2% or 4096 clusters, whichever is smaller.
 	 * This should cover the situations where we can not afford to run
 	 * out of space like for example punch hole, or converting
-	 * uninitialized extents in delalloc path. In most cases such
+	 * unwritten extents in delalloc path. In most cases such
 	 * allocation would require 1, or 2 blocks, higher numbers are
 	 * very rare.
 	 */
@@ -3869,19 +3870,38 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 			goto failed_mount2;
 		}
 	}
+
+	/*
+	 * set up enough so that it can read an inode,
+	 * and create new inode for buddy allocator
+	 */
+	sbi->s_gdb_count = db_count;
+	if (!test_opt(sb, NOLOAD) &&
+	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
+		sb->s_op = &ext4_sops;
+	else
+		sb->s_op = &ext4_nojournal_sops;
+
+	ext4_ext_init(sb);
+	err = ext4_mb_init(sb);
+	if (err) {
+		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
+			 err);
+		goto failed_mount2;
+	}
+
 	if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
 		ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
-		goto failed_mount2;
+		goto failed_mount2a;
 	}
 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
 		if (!ext4_fill_flex_info(sb)) {
 			ext4_msg(sb, KERN_ERR,
 			       "unable to initialize "
 			       "flex_bg meta info!");
-			goto failed_mount2;
+			goto failed_mount2a;
 		}
 
-	sbi->s_gdb_count = db_count;
 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
 	spin_lock_init(&sbi->s_next_gen_lock);
 
@@ -3916,14 +3936,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_stripe = ext4_get_stripe_size(sbi);
 	sbi->s_extent_max_zeroout_kb = 32;
 
-	/*
-	 * set up enough so that it can read an inode
-	 */
-	if (!test_opt(sb, NOLOAD) &&
-	    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
-		sb->s_op = &ext4_sops;
-	else
-		sb->s_op = &ext4_nojournal_sops;
 	sb->s_export_op = &ext4_export_ops;
 	sb->s_xattr = ext4_xattr_handlers;
 #ifdef CONFIG_QUOTA
@@ -4113,21 +4125,13 @@ no_journal:
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
 			 "reserved pool", ext4_calculate_resv_clusters(sb));
-		goto failed_mount4a;
+		goto failed_mount5;
 	}
 
 	err = ext4_setup_system_zone(sb);
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "failed to initialize system "
 			 "zone (%d)", err);
-		goto failed_mount4a;
-	}
-
-	ext4_ext_init(sb);
-	err = ext4_mb_init(sb);
-	if (err) {
-		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
-			 err);
 		goto failed_mount5;
 	}
 
@@ -4204,11 +4208,8 @@ failed_mount8:
 failed_mount7:
 	ext4_unregister_li_request(sb);
 failed_mount6:
-	ext4_mb_release(sb);
-failed_mount5:
-	ext4_ext_release(sb);
 	ext4_release_system_zone(sb);
-failed_mount4a:
+failed_mount5:
 	dput(sb->s_root);
 	sb->s_root = NULL;
 failed_mount4:
@@ -4232,11 +4233,14 @@ failed_mount3:
 	percpu_counter_destroy(&sbi->s_extent_cache_cnt);
 	if (sbi->s_mmp_tsk)
 		kthread_stop(sbi->s_mmp_tsk);
+failed_mount2a:
+	ext4_mb_release(sb);
 failed_mount2:
 	for (i = 0; i < db_count; i++)
 		brelse(sbi->s_group_desc[i]);
 	ext4_kvfree(sbi->s_group_desc);
 failed_mount:
+	ext4_ext_release(sb);
 	if (sbi->s_chksum_driver)
 		crypto_free_shash(sbi->s_chksum_driver);
 	if (sbi->s_proc) {
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 1f5cf5880718..4eec399ec807 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -520,8 +520,8 @@ static void ext4_xattr_update_super_block(handle_t *handle,
 }
 
 /*
- * Release the xattr block BH: If the reference count is > 1, decrement
- * it; otherwise free the block.
+ * Release the xattr block BH: If the reference count is > 1, decrement it;
+ * otherwise free the block.
  */
 static void
 ext4_xattr_release_block(handle_t *handle, struct inode *inode,
@@ -542,16 +542,31 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
 		if (ce)
 			mb_cache_entry_free(ce);
 		get_bh(bh);
+		unlock_buffer(bh);
 		ext4_free_blocks(handle, inode, bh, 0, 1,
 				 EXT4_FREE_BLOCKS_METADATA |
 				 EXT4_FREE_BLOCKS_FORGET);
-		unlock_buffer(bh);
 	} else {
 		le32_add_cpu(&BHDR(bh)->h_refcount, -1);
 		if (ce)
 			mb_cache_entry_release(ce);
+		/*
+		 * Beware of this ugliness: Releasing of xattr block references
+		 * from different inodes can race and so we have to protect
+		 * from a race where someone else frees the block (and releases
+		 * its journal_head) before we are done dirtying the buffer. In
+		 * nojournal mode this race is harmless and we actually cannot
+		 * call ext4_handle_dirty_xattr_block() with locked buffer as
+		 * that function can call sync_dirty_buffer() so for that case
+		 * we handle the dirtying after unlocking the buffer.
+		 */
+		if (ext4_handle_valid(handle))
+			error = ext4_handle_dirty_xattr_block(handle, inode,
+							      bh);
 		unlock_buffer(bh);
-		error = ext4_handle_dirty_xattr_block(handle, inode, bh);
+		if (!ext4_handle_valid(handle))
+			error = ext4_handle_dirty_xattr_block(handle, inode,
+							      bh);
 		if (IS_SYNC(inode))
 			ext4_handle_sync(handle);
 		dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1));
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 4aa521aa9bc3..744c68be2e15 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -174,10 +174,7 @@ no_write:
 	return 0;
 
 redirty_out:
-	dec_page_count(sbi, F2FS_DIRTY_META);
-	wbc->pages_skipped++;
-	account_page_redirty(page);
-	set_page_dirty(page);
+	redirty_page_for_writepage(wbc, page);
 	return AOP_WRITEPAGE_ACTIVATE;
 }
 
@@ -555,14 +552,13 @@ fail_no_cp:
 static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	struct list_head *head = &sbi->dir_inode_list;
-	struct dir_inode_entry *entry;
 
-	list_for_each_entry(entry, head, list)
-		if (unlikely(entry->inode == inode))
-			return -EEXIST;
+	if (is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR))
+		return -EEXIST;
 
-	list_add_tail(&new->list, head);
+	set_inode_flag(F2FS_I(inode), FI_DIRTY_DIR);
+	F2FS_I(inode)->dirty_dir = new;
+	list_add_tail(&new->list, &sbi->dir_inode_list);
 	stat_inc_dirty_dir(sbi);
 	return 0;
 }
@@ -611,31 +607,26 @@ void add_dirty_dir_inode(struct inode *inode)
 void remove_dirty_dir_inode(struct inode *inode)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	struct list_head *head;
 	struct dir_inode_entry *entry;
 
 	if (!S_ISDIR(inode->i_mode))
 		return;
 
 	spin_lock(&sbi->dir_inode_lock);
-	if (get_dirty_dents(inode)) {
+	if (get_dirty_dents(inode) ||
+			!is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) {
 		spin_unlock(&sbi->dir_inode_lock);
 		return;
 	}
 
-	head = &sbi->dir_inode_list;
-	list_for_each_entry(entry, head, list) {
-		if (entry->inode == inode) {
-			list_del(&entry->list);
-			stat_dec_dirty_dir(sbi);
-			spin_unlock(&sbi->dir_inode_lock);
-			kmem_cache_free(inode_entry_slab, entry);
-			goto done;
-		}
-	}
+	entry = F2FS_I(inode)->dirty_dir;
+	list_del(&entry->list);
+	F2FS_I(inode)->dirty_dir = NULL;
+	clear_inode_flag(F2FS_I(inode), FI_DIRTY_DIR);
+	stat_dec_dirty_dir(sbi);
 	spin_unlock(&sbi->dir_inode_lock);
+	kmem_cache_free(inode_entry_slab, entry);
 
-done:
 	/* Only from the recovery routine */
 	if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) {
 		clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT);
@@ -643,26 +634,6 @@ done:
 	}
 }
 
-struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino)
-{
-
-	struct list_head *head;
-	struct inode *inode = NULL;
-	struct dir_inode_entry *entry;
-
-	spin_lock(&sbi->dir_inode_lock);
-
-	head = &sbi->dir_inode_list;
-	list_for_each_entry(entry, head, list) {
-		if (entry->inode->i_ino == ino) {
-			inode = entry->inode;
-			break;
-		}
-	}
-	spin_unlock(&sbi->dir_inode_lock);
-	return inode;
-}
-
 void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
 {
 	struct list_head *head;
@@ -762,6 +733,12 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 	void *kaddr;
 	int i;
 
+	/*
+	 * This avoids to conduct wrong roll-forward operations and uses
+	 * metapages, so should be called prior to sync_meta_pages below.
+	 */
+	discard_next_dnode(sbi);
+
 	/* Flush all the NAT/SIT pages */
 	while (get_pages(sbi, F2FS_DIRTY_META))
 		sync_meta_pages(sbi, META, LONG_MAX);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 45abd60e2bff..b5cd6d1c9320 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -798,10 +798,8 @@ static int f2fs_write_data_page(struct page *page,
 	 * this page does not have to be written to disk.
 	 */
 	offset = i_size & (PAGE_CACHE_SIZE - 1);
-	if ((page->index >= end_index + 1) || !offset) {
-		inode_dec_dirty_dents(inode);
+	if ((page->index >= end_index + 1) || !offset)
 		goto out;
-	}
 
 	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
 write:
@@ -810,7 +808,6 @@ write:
 
 	/* Dentry blocks are controlled by checkpoint */
 	if (S_ISDIR(inode->i_mode)) {
-		inode_dec_dirty_dents(inode);
 		err = do_write_data_page(page, &fio);
 		goto done;
 	}
@@ -832,15 +829,14 @@ done:
 
 	clear_cold_data(page);
 out:
+	inode_dec_dirty_dents(inode);
 	unlock_page(page);
 	if (need_balance_fs)
 		f2fs_balance_fs(sbi);
 	return 0;
 
 redirty_out:
-	wbc->pages_skipped++;
-	account_page_redirty(page);
-	set_page_dirty(page);
+	redirty_page_for_writepage(wbc, page);
 	return AOP_WRITEPAGE_ACTIVATE;
 }
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 2ecac8312359..d3180f8c0f97 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -218,6 +218,7 @@ struct f2fs_inode_info {
 	nid_t i_xattr_nid;		/* node id that contains xattrs */
 	unsigned long long xattr_ver;	/* cp version of xattr modification */
 	struct extent_info ext;		/* in-memory extent cache entry */
+	struct dir_inode_entry *dirty_dir;	/* the pointer of dirty dir */
 };
 
 static inline void get_extent_info(struct extent_info *ext,
@@ -958,6 +959,7 @@ static inline int f2fs_clear_bit(unsigned int nr, char *addr)
 enum {
 	FI_NEW_INODE,		/* indicate newly allocated inode */
 	FI_DIRTY_INODE,		/* indicate inode is dirty or not */
+	FI_DIRTY_DIR,		/* indicate directory has dirty pages */
 	FI_INC_LINK,		/* need to increment i_nlink */
 	FI_ACL_MODE,		/* indicate acl mode */
 	FI_NO_ALLOC,		/* should not allocate any blocks */
@@ -1179,6 +1181,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *);
 void invalidate_blocks(struct f2fs_sb_info *, block_t);
 void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t);
 void clear_prefree_segments(struct f2fs_sb_info *);
+void discard_next_dnode(struct f2fs_sb_info *);
 int npages_for_summary_flush(struct f2fs_sb_info *);
 void allocate_new_segments(struct f2fs_sb_info *);
 struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
@@ -1221,7 +1224,6 @@ int get_valid_checkpoint(struct f2fs_sb_info *);
 void set_dirty_dir_page(struct inode *, struct page *);
 void add_dirty_dir_inode(struct inode *);
 void remove_dirty_dir_inode(struct inode *);
-struct inode *check_dirty_dir_inode(struct f2fs_sb_info *, nid_t);
 void sync_dirty_dir_inodes(struct f2fs_sb_info *);
 void write_checkpoint(struct f2fs_sb_info *, bool);
 void init_orphan_info(struct f2fs_sb_info *);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 383db1fabcf4..3258c7cf00d5 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -81,8 +81,10 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
 
 	f2fs_lock_op(sbi);
 	ipage = get_node_page(sbi, inode->i_ino);
-	if (IS_ERR(ipage))
-		return PTR_ERR(ipage);
+	if (IS_ERR(ipage)) {
+		err = PTR_ERR(ipage);
+		goto out;
+	}
 
 	/*
 	 * i_addr[0] is not used for inline data,
@@ -90,10 +92,8 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
 	 */
 	set_new_dnode(&dn, inode, ipage, NULL, 0);
 	err = f2fs_reserve_block(&dn, 0);
-	if (err) {
-		f2fs_unlock_op(sbi);
-		return err;
-	}
+	if (err)
+		goto out;
 
 	zero_user_segment(page, MAX_INLINE_DATA, PAGE_CACHE_SIZE);
 
@@ -118,6 +118,7 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
 
 	sync_inode_page(&dn);
 	f2fs_put_dnode(&dn);
+out:
 	f2fs_unlock_op(sbi);
 	return err;
 }
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index a161e955c4c8..f760793c1a64 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1227,10 +1227,7 @@ static int f2fs_write_node_page(struct page *page,
 	return 0;
 
 redirty_out:
-	dec_page_count(sbi, F2FS_DIRTY_NODES);
-	wbc->pages_skipped++;
-	account_page_redirty(page);
-	set_page_dirty(page);
+	redirty_page_for_writepage(wbc, page);
 	return AOP_WRITEPAGE_ACTIVATE;
 }
 
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index b1ae89f0f44e..9eb6487f383d 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -46,15 +46,17 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
 	struct inode *dir, *einode;
 	int err = 0;
 
-	dir = check_dirty_dir_inode(F2FS_SB(inode->i_sb), pino);
-	if (!dir) {
-		dir = f2fs_iget(inode->i_sb, pino);
-		if (IS_ERR(dir)) {
-			err = PTR_ERR(dir);
-			goto out;
-		}
-		set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT);
+	dir = f2fs_iget(inode->i_sb, pino);
+	if (IS_ERR(dir)) {
+		err = PTR_ERR(dir);
+		goto out;
+	}
+
+	if (is_inode_flag_set(F2FS_I(dir), FI_DIRTY_DIR)) {
+		iput(dir);
+	} else {
 		add_dirty_dir_inode(dir);
+		set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT);
 	}
 
 	name.len = le32_to_cpu(raw_inode->i_namelen);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 085f548be7a3..9993f94848fc 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -226,6 +226,7 @@ repeat:
 			next = cmd->next;
 			complete(&cmd->wait);
 		}
+		bio_put(bio);
 		sm_i->dispatch_list = NULL;
 	}
 
@@ -242,9 +243,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi)
 	if (!test_opt(sbi, FLUSH_MERGE))
 		return blkdev_issue_flush(sbi->sb->s_bdev, GFP_KERNEL, NULL);
 
-	cmd = f2fs_kmem_cache_alloc(flush_cmd_slab, GFP_ATOMIC);
-	cmd->next = NULL;
-	cmd->ret = 0;
+	cmd = f2fs_kmem_cache_alloc(flush_cmd_slab, GFP_ATOMIC | __GFP_ZERO);
 	init_completion(&cmd->wait);
 
 	spin_lock(&sm_i->issue_lock);
@@ -336,13 +335,26 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
 	mutex_unlock(&dirty_i->seglist_lock);
 }
 
-static void f2fs_issue_discard(struct f2fs_sb_info *sbi,
+static int f2fs_issue_discard(struct f2fs_sb_info *sbi,
 				block_t blkstart, block_t blklen)
 {
 	sector_t start = SECTOR_FROM_BLOCK(sbi, blkstart);
 	sector_t len = SECTOR_FROM_BLOCK(sbi, blklen);
-	blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0);
 	trace_f2fs_issue_discard(sbi->sb, blkstart, blklen);
+	return blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0);
+}
+
+void discard_next_dnode(struct f2fs_sb_info *sbi)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
+	block_t blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
+
+	if (f2fs_issue_discard(sbi, blkaddr, 1)) {
+		struct page *page = grab_meta_page(sbi, blkaddr);
+		/* zero-filled page */
+		set_page_dirty(page);
+		f2fs_put_page(page, 1);
+	}
 }
 
 static void add_discard_addrs(struct f2fs_sb_info *sbi,
@@ -1860,10 +1872,9 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
 	sm_info->nr_discards = 0;
 	sm_info->max_discards = 0;
 
-	if (test_opt(sbi, FLUSH_MERGE)) {
+	if (test_opt(sbi, FLUSH_MERGE) && !f2fs_readonly(sbi->sb)) {
 		spin_lock_init(&sm_info->issue_lock);
 		init_waitqueue_head(&sm_info->flush_wait_queue);
-
 		sm_info->f2fs_issue_flush = kthread_run(issue_flush_thread, sbi,
 				"f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev));
 		if (IS_ERR(sm_info->f2fs_issue_flush))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index c756923a7302..5e20d2a36eac 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -514,7 +514,7 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb);
 
-	if (!(root->d_sb->s_flags & MS_RDONLY) && test_opt(sbi, BG_GC))
+	if (!f2fs_readonly(sbi->sb) && test_opt(sbi, BG_GC))
 		seq_printf(seq, ",background_gc=%s", "on");
 	else
 		seq_printf(seq, ",background_gc=%s", "off");
@@ -542,7 +542,7 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 		seq_puts(seq, ",disable_ext_identify");
 	if (test_opt(sbi, INLINE_DATA))
 		seq_puts(seq, ",inline_data");
-	if (test_opt(sbi, FLUSH_MERGE))
+	if (!f2fs_readonly(sbi->sb) && test_opt(sbi, FLUSH_MERGE))
 		seq_puts(seq, ",flush_merge");
 	seq_printf(seq, ",active_logs=%u", sbi->active_logs);
 
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 91ad9e1c9441..e26bc9a22ac9 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -303,6 +303,31 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
 	return dclus;
 }
 
+static int fat_get_mapped_cluster(struct inode *inode, sector_t sector,
+				  sector_t last_block,
+				  unsigned long *mapped_blocks, sector_t *bmap)
+{
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	int cluster, offset;
+
+	cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
+	offset  = sector & (sbi->sec_per_clus - 1);
+	cluster = fat_bmap_cluster(inode, cluster);
+
+	if (cluster < 0)
+		return cluster;
+
+	else if (cluster) {
+		*bmap = fat_clus_to_blknr(sbi, cluster) + offset;
+		*mapped_blocks = sbi->sec_per_clus - offset;
+		if (*mapped_blocks > last_block - sector)
+			*mapped_blocks = last_block - sector;
+	}
+
+	return 0;
+}
+
 int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
 	     unsigned long *mapped_blocks, int create)
 {
@@ -311,7 +336,6 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
 	const unsigned long blocksize = sb->s_blocksize;
 	const unsigned char blocksize_bits = sb->s_blocksize_bits;
 	sector_t last_block;
-	int cluster, offset;
 
 	*phys = 0;
 	*mapped_blocks = 0;
@@ -329,25 +353,39 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
 			return 0;
 
 		/*
-		 * ->mmu_private can access on only allocation path.
-		 * (caller must hold ->i_mutex)
+		 * Both ->mmu_private and ->i_disksize can access
+		 * on only allocation path. (caller must hold ->i_mutex)
 		 */
-		last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1))
+		last_block = (MSDOS_I(inode)->i_disksize + (blocksize - 1))
 			>> blocksize_bits;
 		if (sector >= last_block)
 			return 0;
 	}
 
-	cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
-	offset  = sector & (sbi->sec_per_clus - 1);
-	cluster = fat_bmap_cluster(inode, cluster);
-	if (cluster < 0)
-		return cluster;
-	else if (cluster) {
-		*phys = fat_clus_to_blknr(sbi, cluster) + offset;
-		*mapped_blocks = sbi->sec_per_clus - offset;
-		if (*mapped_blocks > last_block - sector)
-			*mapped_blocks = last_block - sector;
-	}
-	return 0;
+	return fat_get_mapped_cluster(inode, sector, last_block, mapped_blocks,
+				      phys);
+}
+
+int fat_bmap2(struct inode *inode, sector_t sector,
+	      unsigned long *mapped_blocks, struct buffer_head *bh_result,
+	      int create, sector_t *bmap)
+{
+	struct super_block *sb = inode->i_sb;
+	sector_t last_block;
+	const unsigned long blocksize = sb->s_blocksize;
+	const unsigned char blocksize_bits = sb->s_blocksize_bits;
+
+	BUG_ON(create != 0);
+
+	*bmap = 0;
+	*mapped_blocks = 0;
+
+	last_block = (MSDOS_I(inode)->i_disksize + (blocksize - 1))
+		>> blocksize_bits;
+
+	if (sector >= last_block)
+		return 0;
+
+	return fat_get_mapped_cluster(inode, sector, last_block, mapped_blocks,
+				      bmap);
 }
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 7c31f4bc74a9..7270bdbca9c3 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -118,7 +118,8 @@ struct msdos_inode_info {
 	unsigned int cache_valid_id;
 
 	/* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */
-	loff_t mmu_private;	/* physically allocated size */
+	loff_t mmu_private;	/* physically allocated size (initialized) */
+	loff_t i_disksize;	/* physically allocated size (uninitialized) */
 
 	int i_start;		/* first cluster or 0 */
 	int i_logstart;		/* logical first cluster */
@@ -289,6 +290,9 @@ extern int fat_get_cluster(struct inode *inode, int cluster,
 			   int *fclus, int *dclus);
 extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
 		    unsigned long *mapped_blocks, int create);
+extern int fat_bmap2(struct inode *inode, sector_t sector,
+		     unsigned long *mapped_blocks,
+		     struct buffer_head *bh_result, int create, sector_t *bmap);
 
 /* fat/dir.c */
 extern const struct file_operations fat_dir_operations;
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 9b104f543056..e33c8a2cb99c 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -17,8 +17,12 @@
 #include <linux/blkdev.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
+#include <linux/falloc.h>
 #include "fat.h"
 
+static long fat_fallocate(struct file *file, int mode,
+			  loff_t offset, loff_t len);
+
 static int fat_ioctl_get_attributes(struct inode *inode, u32 __user *user_attr)
 {
 	u32 attr;
@@ -182,6 +186,7 @@ const struct file_operations fat_file_operations = {
 #endif
 	.fsync		= fat_file_fsync,
 	.splice_read	= generic_file_splice_read,
+	.fallocate	= fat_fallocate,
 };
 
 static int fat_cont_expand(struct inode *inode, loff_t size)
@@ -220,6 +225,75 @@ out:
 	return err;
 }
 
+/*
+ * Preallocate space for a file. This implements fat's fallocate file
+ * operation, which gets called from sys_fallocate system call. User
+ * space requests len bytes at offset. If FALLOC_FL_KEEP_SIZE is set
+ * we just allocate clusters without zeroing them out. Otherwise we
+ * allocate and zero out clusters via an expanding truncate.
+ */
+static long fat_fallocate(struct file *file, int mode,
+			  loff_t offset, loff_t len)
+{
+	int cluster;
+	int nr_cluster; /* Number of clusters to be allocated */
+	loff_t mm_bytes; /* Number of bytes to be allocated for file */
+	struct inode *inode = file->f_mapping->host;
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	int err = 0;
+
+	/* No support for hole punch or other fallocate flags. */
+	if (mode & ~FALLOC_FL_KEEP_SIZE)
+		return -EOPNOTSUPP;
+
+	/* No support for dir */
+	if (!S_ISREG(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&inode->i_mutex);
+	if ((offset + len) <= MSDOS_I(inode)->i_disksize)
+		goto error;
+
+	err = inode_newsize_ok(inode, (len + offset));
+	if (err)
+		goto error;
+
+	if (mode & FALLOC_FL_KEEP_SIZE) {
+		/* First compute the number of clusters to be allocated */
+		mm_bytes = offset + len - round_up(MSDOS_I(inode)->i_disksize,
+			sbi->cluster_size);
+		nr_cluster = (mm_bytes + (sbi->cluster_size - 1)) >>
+			sbi->cluster_bits;
+
+		/* Start the allocation.We are not zeroing out the clusters */
+		while (nr_cluster-- > 0) {
+			err = fat_alloc_clusters(inode, &cluster, 1);
+			if (err) {
+				fat_msg(sb, KERN_ERR,
+					"fat_fallocate(): fat_alloc_clusters() error");
+				goto error;
+			}
+			err = fat_chain_add(inode, cluster, 1);
+			if (err) {
+				fat_free_clusters(inode, cluster);
+				goto error;
+			}
+			MSDOS_I(inode)->i_disksize += sbi->cluster_size;
+		}
+	} else {
+		/* This is just an expanding truncate */
+		err = fat_cont_expand(inode, (offset + len));
+		if (err)
+			fat_msg(sb, KERN_ERR,
+				"fat_fallocate(): fat_cont_expand() error");
+	}
+
+error:
+	mutex_unlock(&inode->i_mutex);
+	return err;
+}
+
 /* Free all clusters after the skip'th cluster. */
 static int fat_free(struct inode *inode, int skip)
 {
@@ -300,8 +374,10 @@ void fat_truncate_blocks(struct inode *inode, loff_t offset)
 	 * This protects against truncating a file bigger than it was then
 	 * trying to write into the hole.
 	 */
-	if (MSDOS_I(inode)->mmu_private > offset)
+	if (MSDOS_I(inode)->i_disksize > offset) {
 		MSDOS_I(inode)->mmu_private = offset;
+		MSDOS_I(inode)->i_disksize = offset;
+	}
 
 	nr_clusters = (offset + (cluster_size - 1)) >> sbi->cluster_bits;
 
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index b3361fe2bcb5..992e8cb1132c 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -54,6 +54,25 @@ static int fat_add_cluster(struct inode *inode)
 	return err;
 }
 
+static void check_fallocated_region(struct inode *inode, sector_t iblock,
+		unsigned long *max_blocks, struct buffer_head *bh_result)
+{
+	struct super_block *sb = inode->i_sb;
+	sector_t last_block, disk_block;
+	const unsigned long blocksize = sb->s_blocksize;
+	const unsigned char blocksize_bits = sb->s_blocksize_bits;
+
+	last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1))
+		>> blocksize_bits;
+	disk_block = (MSDOS_I(inode)->i_disksize + (blocksize - 1))
+		>> blocksize_bits;
+	if (iblock >= last_block && iblock <= disk_block) {
+		MSDOS_I(inode)->mmu_private += *max_blocks << blocksize_bits;
+		set_buffer_new(bh_result);
+	}
+
+}
+
 static inline int __fat_get_block(struct inode *inode, sector_t iblock,
 				  unsigned long *max_blocks,
 				  struct buffer_head *bh_result, int create)
@@ -68,8 +87,11 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
 	if (err)
 		return err;
 	if (phys) {
-		map_bh(bh_result, sb, phys);
 		*max_blocks = min(mapped_blocks, *max_blocks);
+		if (create)
+			check_fallocated_region(inode, iblock, max_blocks,
+				bh_result);
+		map_bh(bh_result, sb, phys);
 		return 0;
 	}
 	if (!create)
@@ -93,6 +115,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
 
 	*max_blocks = min(mapped_blocks, *max_blocks);
 	MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits;
+	MSDOS_I(inode)->i_disksize = MSDOS_I(inode)->mmu_private;
 
 	err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create);
 	if (err)
@@ -206,6 +229,13 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
 		loff_t size = offset + iov_length(iov, nr_segs);
 		if (MSDOS_I(inode)->mmu_private < size)
 			return 0;
+
+		/*
+		 * In case of writing in fallocated region, return 0 and
+		 * fallback to buffered write.
+		 */
+		if (MSDOS_I(inode)->i_disksize > MSDOS_I(inode)->mmu_private)
+			return 0;
 	}
 
 	/*
@@ -220,13 +250,36 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
 	return ret;
 }
 
+static int fat_get_block_bmap(struct inode *inode, sector_t iblock,
+		struct buffer_head *bh_result, int create)
+{
+	struct super_block *sb = inode->i_sb;
+	unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
+	int err;
+	sector_t bmap;
+	unsigned long mapped_blocks;
+
+	err = fat_bmap2(inode, iblock, &mapped_blocks, bh_result, create,
+			&bmap);
+	if (err)
+		return err;
+
+	if (bmap) {
+		map_bh(bh_result, sb, bmap);
+		max_blocks = min(mapped_blocks, max_blocks);
+	}
+
+	bh_result->b_size = max_blocks << sb->s_blocksize_bits;
+	return 0;
+}
+
 static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
 {
 	sector_t blocknr;
 
 	/* fat_get_cluster() assumes the requested blocknr isn't truncated. */
 	down_read(&MSDOS_I(mapping->host)->truncate_lock);
-	blocknr = generic_block_bmap(mapping, block, fat_get_block);
+	blocknr = generic_block_bmap(mapping, block, fat_get_block_bmap);
 	up_read(&MSDOS_I(mapping->host)->truncate_lock);
 
 	return blocknr;
@@ -407,7 +460,6 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 		error = fat_calc_dir_size(inode);
 		if (error < 0)
 			return error;
-		MSDOS_I(inode)->mmu_private = inode->i_size;
 
 		set_nlink(inode, fat_subdirs(inode));
 	} else { /* not a directory */
@@ -422,8 +474,12 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 		inode->i_op = &fat_file_inode_operations;
 		inode->i_fop = &fat_file_operations;
 		inode->i_mapping->a_ops = &fat_aops;
-		MSDOS_I(inode)->mmu_private = inode->i_size;
 	}
+
+	MSDOS_I(inode)->mmu_private = inode->i_size;
+	MSDOS_I(inode)->i_disksize = round_up(inode->i_size,
+		inode->i_sb->s_blocksize);
+
 	if (de->attr & ATTR_SYS) {
 		if (sbi->options.sys_immutable)
 			inode->i_flags |= S_IMMUTABLE;
@@ -488,12 +544,34 @@ out:
 
 EXPORT_SYMBOL_GPL(fat_build_inode);
 
+static int __fat_write_inode(struct inode *inode, int wait);
 static void fat_evict_inode(struct inode *inode)
 {
 	truncate_inode_pages_final(&inode->i_data);
 	if (!inode->i_nlink) {
 		inode->i_size = 0;
 		fat_truncate_blocks(inode, 0);
+	} else {
+		/* Release unwritten fallocated blocks on inode eviction. */
+		if (MSDOS_I(inode)->i_disksize >
+		    round_up(MSDOS_I(inode)->mmu_private,
+				inode->i_sb->s_blocksize)) {
+			int err;
+			fat_truncate_blocks(inode, MSDOS_I(inode)->mmu_private);
+			/* Fallocate results in updating the i_start/iogstart
+			 * for the zero byte file. So, make it return to
+			 * original state during evict and commit it to avoid
+			 * any corruption on the next access to the cluster
+			 * chain for the file.
+			 */
+			err = __fat_write_inode(inode, inode_needs_sync(inode));
+			if (err) {
+				fat_msg(inode->i_sb, KERN_WARNING, "Failed to "
+				"update on disk inode for unused fallocated "
+				"blocks, inode could be corrupted. Please run "
+				"fsck");
+			}
+		}
 	}
 	invalidate_inode_buffers(inode);
 	clear_inode(inode);
@@ -1225,6 +1303,7 @@ static int fat_read_root(struct inode *inode)
 			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;
 	MSDOS_I(inode)->i_logstart = 0;
 	MSDOS_I(inode)->mmu_private = inode->i_size;
+	MSDOS_I(inode)->i_disksize = inode->i_size;
 
 	fat_save_attrs(inode, ATTR_DIR);
 	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 32602c667b4a..7892e6fddb66 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -38,21 +38,30 @@ int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
 	return hfsplus_strcmp(&k1->cat.name, &k2->cat.name);
 }
 
-void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
-			   u32 parent, struct qstr *str)
+/* Generates key for catalog file/folders record. */
+int hfsplus_cat_build_key(struct super_block *sb,
+		hfsplus_btree_key *key, u32 parent, struct qstr *str)
 {
-	int len;
+	int len, err;
 
 	key->cat.parent = cpu_to_be32(parent);
-	if (str) {
-		hfsplus_asc2uni(sb, &key->cat.name, HFSPLUS_MAX_STRLEN,
-					str->name, str->len);
-		len = be16_to_cpu(key->cat.name.length);
-	} else {
-		key->cat.name.length = 0;
-		len = 0;
-	}
+	err = hfsplus_asc2uni(sb, &key->cat.name, HFSPLUS_MAX_STRLEN,
+			str->name, str->len);
+	if (unlikely(err < 0))
+		return err;
+
+	len = be16_to_cpu(key->cat.name.length);
 	key->key_len = cpu_to_be16(6 + 2 * len);
+	return 0;
+}
+
+/* Generates key for catalog thread record. */
+void hfsplus_cat_build_key_with_cnid(struct super_block *sb,
+			hfsplus_btree_key *key, u32 parent)
+{
+	key->cat.parent = cpu_to_be32(parent);
+	key->cat.name.length = 0;
+	key->key_len = cpu_to_be16(6);
 }
 
 static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent,
@@ -167,11 +176,16 @@ static int hfsplus_fill_cat_thread(struct super_block *sb,
 				   hfsplus_cat_entry *entry, int type,
 				   u32 parentid, struct qstr *str)
 {
+	int err;
+
 	entry->type = cpu_to_be16(type);
 	entry->thread.reserved = 0;
 	entry->thread.parentID = cpu_to_be32(parentid);
-	hfsplus_asc2uni(sb, &entry->thread.nodeName, HFSPLUS_MAX_STRLEN,
+	err = hfsplus_asc2uni(sb, &entry->thread.nodeName, HFSPLUS_MAX_STRLEN,
 				str->name, str->len);
+	if (unlikely(err < 0))
+		return err;
+
 	return 10 + be16_to_cpu(entry->thread.nodeName.length) * 2;
 }
 
@@ -183,7 +197,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 	int err;
 	u16 type;
 
-	hfsplus_cat_build_key(sb, fd->search_key, cnid, NULL);
+	hfsplus_cat_build_key_with_cnid(sb, fd->search_key, cnid);
 	err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
 	if (err)
 		return err;
@@ -250,11 +264,16 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 	if (err)
 		return err;
 
-	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
+	hfsplus_cat_build_key_with_cnid(sb, fd.search_key, cnid);
 	entry_size = hfsplus_fill_cat_thread(sb, &entry,
 		S_ISDIR(inode->i_mode) ?
 			HFSPLUS_FOLDER_THREAD : HFSPLUS_FILE_THREAD,
 		dir->i_ino, str);
+	if (unlikely(entry_size < 0)) {
+		err = entry_size;
+		goto err2;
+	}
+
 	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
 		if (!err)
@@ -265,7 +284,10 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 	if (err)
 		goto err2;
 
-	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
+	err = hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
+	if (unlikely(err))
+		goto err1;
+
 	entry_size = hfsplus_cat_build_record(&entry, cnid, inode);
 	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
@@ -288,7 +310,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 	return 0;
 
 err1:
-	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
+	hfsplus_cat_build_key_with_cnid(sb, fd.search_key, cnid);
 	if (!hfs_brec_find(&fd, hfs_find_rec_by_key))
 		hfs_brec_remove(&fd);
 err2:
@@ -313,7 +335,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 	if (!str) {
 		int len;
 
-		hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
+		hfsplus_cat_build_key_with_cnid(sb, fd.search_key, cnid);
 		err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 		if (err)
 			goto out;
@@ -329,7 +351,9 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 			off + 2, len);
 		fd.search_key->key_len = cpu_to_be16(6 + len);
 	} else
-		hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
+		err = hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
+		if (unlikely(err))
+			goto out;
 
 	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err)
@@ -360,7 +384,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 	if (err)
 		goto out;
 
-	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
+	hfsplus_cat_build_key_with_cnid(sb, fd.search_key, cnid);
 	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
@@ -405,7 +429,11 @@ int hfsplus_rename_cat(u32 cnid,
 	dst_fd = src_fd;
 
 	/* find the old dir entry and read the data */
-	hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
+	err = hfsplus_cat_build_key(sb, src_fd.search_key,
+			src_dir->i_ino, src_name);
+	if (unlikely(err))
+		goto out;
+
 	err = hfs_brec_find(&src_fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
@@ -419,7 +447,11 @@ int hfsplus_rename_cat(u32 cnid,
 	type = be16_to_cpu(entry.type);
 
 	/* create new dir entry with the data from the old entry */
-	hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
+	err = hfsplus_cat_build_key(sb, dst_fd.search_key,
+			dst_dir->i_ino, dst_name);
+	if (unlikely(err))
+		goto out;
+
 	err = hfs_brec_find(&dst_fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
 		if (!err)
@@ -436,7 +468,11 @@ int hfsplus_rename_cat(u32 cnid,
 	dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC;
 
 	/* finally remove the old entry */
-	hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
+	err = hfsplus_cat_build_key(sb, src_fd.search_key,
+			src_dir->i_ino, src_name);
+	if (unlikely(err))
+		goto out;
+
 	err = hfs_brec_find(&src_fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
@@ -449,7 +485,7 @@ int hfsplus_rename_cat(u32 cnid,
 	src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC;
 
 	/* remove old thread entry */
-	hfsplus_cat_build_key(sb, src_fd.search_key, cnid, NULL);
+	hfsplus_cat_build_key_with_cnid(sb, src_fd.search_key, cnid);
 	err = hfs_brec_find(&src_fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
@@ -459,9 +495,14 @@ int hfsplus_rename_cat(u32 cnid,
 		goto out;
 
 	/* create new thread entry */
-	hfsplus_cat_build_key(sb, dst_fd.search_key, cnid, NULL);
+	hfsplus_cat_build_key_with_cnid(sb, dst_fd.search_key, cnid);
 	entry_size = hfsplus_fill_cat_thread(sb, &entry, type,
 		dst_dir->i_ino, dst_name);
+	if (unlikely(entry_size < 0)) {
+		err = entry_size;
+		goto out;
+	}
+
 	err = hfs_brec_find(&dst_fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
 		if (!err)
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index bdec66522de3..b306b66ccaba 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -43,7 +43,10 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
 	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 	if (err)
 		return ERR_PTR(err);
-	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
+	err = hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino,
+			&dentry->d_name);
+	if (unlikely(err < 0))
+		goto fail;
 again:
 	err = hfs_brec_read(&fd, &entry, sizeof(entry));
 	if (err) {
@@ -96,9 +99,11 @@ again:
 					be32_to_cpu(entry.file.permissions.dev);
 				str.len = sprintf(name, "iNode%d", linkid);
 				str.name = name;
-				hfsplus_cat_build_key(sb, fd.search_key,
+				err = hfsplus_cat_build_key(sb, fd.search_key,
 					HFSPLUS_SB(sb)->hidden_dir->i_ino,
 					&str);
+				if (unlikely(err < 0))
+					goto fail;
 				goto again;
 			}
 		} else if (!dentry->d_fsdata)
@@ -139,7 +144,7 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
 	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 	if (err)
 		return err;
-	hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
+	hfsplus_cat_build_key_with_cnid(sb, fd.search_key, inode->i_ino);
 	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 83dc29286b10..7f36453a788d 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -444,8 +444,10 @@ int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *,
 		const hfsplus_btree_key *);
 int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *,
 		const hfsplus_btree_key *);
-void hfsplus_cat_build_key(struct super_block *sb,
+int hfsplus_cat_build_key(struct super_block *sb,
 		hfsplus_btree_key *, u32, struct qstr *);
+void hfsplus_cat_build_key_with_cnid(struct super_block *sb,
+		hfsplus_btree_key *, u32);
 int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
 int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
 int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index a513d2d36be9..dcb474129d5c 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -514,7 +514,9 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 	err = hfs_find_init(sbi->cat_tree, &fd);
 	if (err)
 		goto out_put_root;
-	hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
+	err = hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
+	if (unlikely(err < 0))
+		goto out_put_root;
 	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
 		hfs_find_exit(&fd);
 		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 2b60ce1996aa..bb9cebc9ca8a 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -75,10 +75,13 @@ void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
 static int jffs2_garbage_collect_thread(void *_c)
 {
 	struct jffs2_sb_info *c = _c;
+	sigset_t hupmask;
 
+	siginitset(&hupmask, sigmask(SIGHUP));
 	allow_signal(SIGKILL);
 	allow_signal(SIGSTOP);
 	allow_signal(SIGCONT);
+	allow_signal(SIGHUP);
 
 	c->gc_task = current;
 	complete(&c->gc_thread_start);
@@ -87,7 +90,7 @@ static int jffs2_garbage_collect_thread(void *_c)
 
 	set_freezable();
 	for (;;) {
-		allow_signal(SIGHUP);
+		sigprocmask(SIG_UNBLOCK, &hupmask, NULL);
 	again:
 		spin_lock(&c->erase_completion_lock);
 		if (!jffs2_thread_should_wake(c)) {
@@ -95,10 +98,9 @@ static int jffs2_garbage_collect_thread(void *_c)
 			spin_unlock(&c->erase_completion_lock);
 			jffs2_dbg(1, "%s(): sleeping...\n", __func__);
 			schedule();
-		} else
+		} else {
 			spin_unlock(&c->erase_completion_lock);
-			
-
+		}
 		/* Problem - immediately after bootup, the GCD spends a lot
 		 * of time in places like jffs2_kill_fragtree(); so much so
 		 * that userspace processes (like gdm and X) are starved
@@ -150,7 +152,7 @@ static int jffs2_garbage_collect_thread(void *_c)
 			}
 		}
 		/* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */
-		disallow_signal(SIGHUP);
+		sigprocmask(SIG_BLOCK, &hupmask, NULL);
 
 		jffs2_dbg(1, "%s(): pass\n", __func__);
 		if (jffs2_garbage_collect_pass(c) == -ENOSPC) {
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 7f464c513ba0..6b0f816201a2 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -29,20 +29,20 @@
 void jfs_set_inode_flags(struct inode *inode)
 {
 	unsigned int flags = JFS_IP(inode)->mode2;
-
-	inode->i_flags &= ~(S_IMMUTABLE | S_APPEND |
-		S_NOATIME | S_DIRSYNC | S_SYNC);
+	unsigned int new_fl = 0;
 
 	if (flags & JFS_IMMUTABLE_FL)
-		inode->i_flags |= S_IMMUTABLE;
+		new_fl |= S_IMMUTABLE;
 	if (flags & JFS_APPEND_FL)
-		inode->i_flags |= S_APPEND;
+		new_fl |= S_APPEND;
 	if (flags & JFS_NOATIME_FL)
-		inode->i_flags |= S_NOATIME;
+		new_fl |= S_NOATIME;
 	if (flags & JFS_DIRSYNC_FL)
-		inode->i_flags |= S_DIRSYNC;
+		new_fl |= S_DIRSYNC;
 	if (flags & JFS_SYNC_FL)
-		inode->i_flags |= S_SYNC;
+		new_fl |= S_SYNC;
+	inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND | S_NOATIME |
+			S_DIRSYNC | S_SYNC);
 }
 
 void jfs_get_inode_flags(struct jfs_inode_info *jfs_ip)
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index abb0f1f53d93..985217626e66 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -48,14 +48,18 @@ void __init kernfs_inode_init(void)
 
 static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
 {
+	static DEFINE_MUTEX(iattr_mutex);
+	struct kernfs_iattrs *ret;
 	struct iattr *iattrs;
 
+	mutex_lock(&iattr_mutex);
+
 	if (kn->iattr)
-		return kn->iattr;
+		goto out_unlock;
 
 	kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL);
 	if (!kn->iattr)
-		return NULL;
+		goto out_unlock;
 	iattrs = &kn->iattr->ia_iattr;
 
 	/* assign default attributes */
@@ -65,8 +69,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
 	iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
 
 	simple_xattrs_init(&kn->iattr->xattrs);
-
-	return kn->iattr;
+out_unlock:
+	ret = kn->iattr;
+	mutex_unlock(&iattr_mutex);
+	return ret;
 }
 
 static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
diff --git a/fs/locks.c b/fs/locks.c
index 13fc7a6d380a..b380f5543614 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1391,11 +1391,10 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
 
 restart:
 	break_time = flock->fl_break_time;
-	if (break_time != 0) {
+	if (break_time != 0)
 		break_time -= jiffies;
-		if (break_time == 0)
-			break_time++;
-	}
+	if (break_time == 0)
+		break_time++;
 	locks_insert_block(flock, new_fl);
 	spin_unlock(&inode->i_lock);
 	error = wait_event_interruptible_timeout(new_fl->fl_wait,
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index 9c501449450d..427bb73e298f 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -245,8 +245,8 @@ static int logfs_mtd_can_write_buf(struct super_block *sb, u64 ofs)
 		goto out;
 	if (memchr_inv(buf, 0xff, super->s_writesize))
 		err = -EIO;
-	kfree(buf);
 out:
+	kfree(buf);
 	return err;
 }
 
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 54360293bcb5..b256c0690e5b 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -287,14 +287,14 @@ static int logfs_make_writeable(struct super_block *sb)
 	if (err)
 		return err;
 
+	/* Do one GC pass before any data gets dirtied */
+	logfs_gc_pass(sb);
+
 	/* Check areas for trailing unaccounted data */
 	err = logfs_check_areas(sb);
 	if (err)
 		return err;
 
-	/* Do one GC pass before any data gets dirtied */
-	logfs_gc_pass(sb);
-
 	/* after all initializations are done, replay the journal
 	 * for rw-mounts, if necessary */
 	err = logfs_replay_journal(sb);
diff --git a/fs/mpage.c b/fs/mpage.c
index 4979ffa60aaa..4e0af5ae34fa 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -462,6 +462,7 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
 	struct buffer_head map_bh;
 	loff_t i_size = i_size_read(inode);
 	int ret = 0;
+	int wr = (wbc->sync_mode == WB_SYNC_ALL ?  WRITE_SYNC : WRITE);
 
 	if (page_has_buffers(page)) {
 		struct buffer_head *head = page_buffers(page);
@@ -570,7 +571,7 @@ page_is_mapped:
 	 * This page will go to BIO.  Do we need to send this BIO off first?
 	 */
 	if (bio && mpd->last_block_in_bio != blocks[0] - 1)
-		bio = mpage_bio_submit(WRITE, bio);
+		bio = mpage_bio_submit(wr, bio);
 
 alloc_new:
 	if (bio == NULL) {
@@ -587,7 +588,7 @@ alloc_new:
 	 */
 	length = first_unmapped << blkbits;
 	if (bio_add_page(bio, page, length, 0) < length) {
-		bio = mpage_bio_submit(WRITE, bio);
+		bio = mpage_bio_submit(wr, bio);
 		goto alloc_new;
 	}
 
@@ -620,7 +621,7 @@ alloc_new:
 	set_page_writeback(page);
 	unlock_page(page);
 	if (boundary || (first_unmapped != blocks_per_page)) {
-		bio = mpage_bio_submit(WRITE, bio);
+		bio = mpage_bio_submit(wr, bio);
 		if (boundary_block) {
 			write_boundary_block(boundary_bdev,
 					boundary_block, 1 << blkbits);
@@ -632,7 +633,7 @@ alloc_new:
 
 confused:
 	if (bio)
-		bio = mpage_bio_submit(WRITE, bio);
+		bio = mpage_bio_submit(wr, bio);
 
 	if (mpd->use_writepage) {
 		ret = mapping->a_ops->writepage(page, wbc);
@@ -688,8 +689,11 @@ mpage_writepages(struct address_space *mapping,
 		};
 
 		ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd);
-		if (mpd.bio)
-			mpage_bio_submit(WRITE, mpd.bio);
+		if (mpd.bio) {
+			int wr = (wbc->sync_mode == WB_SYNC_ALL ?
+				  WRITE_SYNC : WRITE);
+			mpage_bio_submit(wr, mpd.bio);
+		}
 	}
 	blk_finish_plug(&plug);
 	return ret;
@@ -706,8 +710,11 @@ int mpage_writepage(struct page *page, get_block_t get_block,
 		.use_writepage = 0,
 	};
 	int ret = __mpage_writepage(page, wbc, &mpd);
-	if (mpd.bio)
-		mpage_bio_submit(WRITE, mpd.bio);
+	if (mpd.bio) {
+		int wr = (wbc->sync_mode == WB_SYNC_ALL ?
+			  WRITE_SYNC : WRITE);
+		mpage_bio_submit(wr, mpd.bio);
+	}
 	return ret;
 }
 EXPORT_SYMBOL(mpage_writepage);
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 66984a9aafaa..b94f80420a58 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -120,7 +120,8 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
 
 	security_d_instantiate(ret, inode);
 	spin_lock(&ret->d_lock);
-	if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
+	if (IS_ROOT(ret) && !ret->d_fsdata &&
+	    !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
 		ret->d_fsdata = name;
 		name = NULL;
 	}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 0c438973f3c8..c79f3e767c8c 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1575,18 +1575,20 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 			inode->i_version = fattr->change_attr;
 		}
 	} else if (server->caps & NFS_CAP_CHANGE_ATTR)
-		invalid |= save_cache_validity;
+		nfsi->cache_validity |= save_cache_validity;
 
 	if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
 		memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
 	} else if (server->caps & NFS_CAP_MTIME)
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATTR
 				| NFS_INO_REVAL_FORCED);
 
 	if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
 		memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
 	} else if (server->caps & NFS_CAP_CTIME)
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATTR
 				| NFS_INO_REVAL_FORCED);
 
 	/* Check if our cached file size is stale */
@@ -1608,7 +1610,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 					(long long)new_isize);
 		}
 	} else
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATTR
 				| NFS_INO_REVAL_PAGECACHE
 				| NFS_INO_REVAL_FORCED);
 
@@ -1616,7 +1619,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 	if (fattr->valid & NFS_ATTR_FATTR_ATIME)
 		memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
 	else if (server->caps & NFS_CAP_ATIME)
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATIME
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATIME
 				| NFS_INO_REVAL_FORCED);
 
 	if (fattr->valid & NFS_ATTR_FATTR_MODE) {
@@ -1627,7 +1631,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 		}
 	} else if (server->caps & NFS_CAP_MODE)
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_ACCESS
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
@@ -1638,7 +1643,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 			inode->i_uid = fattr->uid;
 		}
 	} else if (server->caps & NFS_CAP_OWNER)
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_ACCESS
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
@@ -1649,7 +1655,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 			inode->i_gid = fattr->gid;
 		}
 	} else if (server->caps & NFS_CAP_OWNER_GROUP)
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATTR
 				| NFS_INO_INVALID_ACCESS
 				| NFS_INO_INVALID_ACL
 				| NFS_INO_REVAL_FORCED);
@@ -1662,7 +1669,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 			set_nlink(inode, fattr->nlink);
 		}
 	} else if (server->caps & NFS_CAP_NLINK)
-		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+		nfsi->cache_validity |= save_cache_validity &
+				(NFS_INO_INVALID_ATTR
 				| NFS_INO_REVAL_FORCED);
 
 	if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9a3b6a4cd6b9..cd7c651f9b84 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1353,6 +1353,30 @@ static const struct rpc_call_ops nfs_write_common_ops = {
 	.rpc_release = nfs_writeback_release_common,
 };
 
+/*
+ * Special version of should_remove_suid() that ignores capabilities.
+ */
+static int nfs_should_remove_suid(const struct inode *inode)
+{
+	umode_t mode = inode->i_mode;
+	int kill = 0;
+
+	/* suid always must be killed */
+	if (unlikely(mode & S_ISUID))
+		kill = ATTR_KILL_SUID;
+
+	/*
+	 * sgid without any exec bits is just a mandatory locking mark; leave
+	 * it alone.  If some exec bits are set, it's a real sgid; kill it.
+	 */
+	if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
+		kill |= ATTR_KILL_SGID;
+
+	if (unlikely(kill && S_ISREG(mode)))
+		return kill;
+
+	return 0;
+}
 
 /*
  * This function is called when the WRITE call is complete.
@@ -1401,9 +1425,16 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 		}
 	}
 #endif
-	if (task->tk_status < 0)
+	if (task->tk_status < 0) {
 		nfs_set_pgio_error(data->header, task->tk_status, argp->offset);
-	else if (resp->count < argp->count) {
+		return;
+	}
+
+	/* Deal with the suid/sgid bit corner case */
+	if (nfs_should_remove_suid(inode))
+		nfs_mark_for_revalidate(inode);
+
+	if (resp->count < argp->count) {
 		static unsigned long    complain;
 
 		/* This a short write! */
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
index ee4144ce5d7c..f82498c35e78 100644
--- a/fs/ntfs/compress.c
+++ b/fs/ntfs/compress.c
@@ -58,7 +58,7 @@ typedef enum {
 /**
  * ntfs_compression_buffer - one buffer for the decompression engine
  */
-static u8 *ntfs_compression_buffer = NULL;
+static u8 *ntfs_compression_buffer;
 
 /**
  * ntfs_cb_lock - spinlock which protects ntfs_compression_buffer
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 9de2491f2926..6c3296e546c3 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -50,8 +50,8 @@
 static unsigned long ntfs_nr_compression_users;
 
 /* A global default upcase table and a corresponding reference count. */
-static ntfschar *default_upcase = NULL;
-static unsigned long ntfs_nr_upcase_users = 0;
+static ntfschar *default_upcase;
+static unsigned long ntfs_nr_upcase_users;
 
 /* Error constants/strings used in inode.c::ntfs_show_options(). */
 typedef enum {
diff --git a/fs/ntfs/sysctl.c b/fs/ntfs/sysctl.c
index 79a89184cb5e..1927170a35ce 100644
--- a/fs/ntfs/sysctl.c
+++ b/fs/ntfs/sysctl.c
@@ -56,7 +56,7 @@ static ctl_table sysctls_root[] = {
 };
 
 /* Storage for the sysctls header. */
-static struct ctl_table_header *sysctls_root_table = NULL;
+static struct ctl_table_header *sysctls_root_table;
 
 /**
  * ntfs_sysctl - add or remove the debug sysctl
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index c6b90e670389..681691bc233a 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -108,7 +108,7 @@ static struct rb_root o2net_handler_tree = RB_ROOT;
 static struct o2net_node o2net_nodes[O2NM_MAX_NODES];
 
 /* XXX someday we'll need better accounting */
-static struct socket *o2net_listen_sock = NULL;
+static struct socket *o2net_listen_sock;
 
 /*
  * listen work is only queued by the listening socket callbacks on the
@@ -1799,7 +1799,7 @@ int o2net_register_hb_callbacks(void)
 
 /* ------------------------------------------------------------ */
 
-static int o2net_accept_one(struct socket *sock)
+static int o2net_accept_one(struct socket *sock, int *more)
 {
 	int ret, slen;
 	struct sockaddr_in sin;
@@ -1810,6 +1810,7 @@ static int o2net_accept_one(struct socket *sock)
 	struct o2net_node *nn;
 
 	BUG_ON(sock == NULL);
+	*more = 0;
 	ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type,
 			       sock->sk->sk_protocol, &new_sock);
 	if (ret)
@@ -1821,6 +1822,7 @@ static int o2net_accept_one(struct socket *sock)
 	if (ret < 0)
 		goto out;
 
+	*more = 1;
 	new_sock->sk->sk_allocation = GFP_ATOMIC;
 
 	ret = o2net_set_nodelay(new_sock);
@@ -1919,11 +1921,36 @@ out:
 	return ret;
 }
 
+/*
+ * This function is invoked in response to one or more
+ * pending accepts at softIRQ level. We must drain the
+ * entire que before returning.
+ */
+
 static void o2net_accept_many(struct work_struct *work)
 {
 	struct socket *sock = o2net_listen_sock;
-	while (o2net_accept_one(sock) == 0)
+	int	more;
+	int	err;
+
+	/*
+	 * It is critical to note that due to interrupt moderation
+	 * at the network driver level, we can't assume to get a
+	 * softIRQ for every single conn since tcp SYN packets
+	 * can arrive back-to-back, and therefore many pending
+	 * accepts may result in just 1 softIRQ. If we terminate
+	 * the o2net_accept_one() loop upon seeing an err, what happens
+	 * to the rest of the conns in the queue? If no new SYN
+	 * arrives for hours, no softIRQ  will be delivered,
+	 * and the connections will just sit in the queue.
+	 */
+
+	for (;;) {
+		err = o2net_accept_one(sock, &more);
+		if (!more)
+			break;
 		cond_resched();
+	}
 }
 
 static void o2net_listen_data_ready(struct sock *sk)
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index e33cd7a3c582..18f13c2e4a10 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -338,7 +338,7 @@ void dlm_print_one_mle(struct dlm_master_list_entry *mle)
 
 #ifdef CONFIG_DEBUG_FS
 
-static struct dentry *dlm_debugfs_root = NULL;
+static struct dentry *dlm_debugfs_root;
 
 #define DLM_DEBUGFS_DIR				"o2dlm"
 #define DLM_DEBUGFS_DLM_STATE			"dlm_state"
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 5d32f7511f74..66c2a491f68d 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -52,7 +52,7 @@
 #define MLOG_MASK_PREFIX ML_DLM
 #include "cluster/masklog.h"
 
-static struct kmem_cache *dlm_lock_cache = NULL;
+static struct kmem_cache *dlm_lock_cache;
 
 static DEFINE_SPINLOCK(dlm_cookie_lock);
 static u64 dlm_next_cookie = 1;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index af3f7aa73e13..1256dc49f83f 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -82,9 +82,9 @@ static inline int dlm_mle_equal(struct dlm_ctxt *dlm,
 	return 1;
 }
 
-static struct kmem_cache *dlm_lockres_cache = NULL;
-static struct kmem_cache *dlm_lockname_cache = NULL;
-static struct kmem_cache *dlm_mle_cache = NULL;
+static struct kmem_cache *dlm_lockres_cache;
+static struct kmem_cache *dlm_lockname_cache;
+static struct kmem_cache *dlm_mle_cache;
 
 static void dlm_mle_release(struct kref *kref);
 static void dlm_init_mle(struct dlm_master_list_entry *mle,
@@ -3084,11 +3084,15 @@ static int dlm_add_migration_mle(struct dlm_ctxt *dlm,
 			/* remove it so that only one mle will be found */
 			__dlm_unlink_mle(dlm, tmp);
 			__dlm_mle_detach_hb_events(dlm, tmp);
-			ret = DLM_MIGRATE_RESPONSE_MASTERY_REF;
-			mlog(0, "%s:%.*s: master=%u, newmaster=%u, "
-			    "telling master to get ref for cleared out mle "
-			    "during migration\n", dlm->name, namelen, name,
-			    master, new_master);
+			if (tmp->type == DLM_MLE_MASTER) {
+				ret = DLM_MIGRATE_RESPONSE_MASTERY_REF;
+				mlog(0, "%s:%.*s: master=%u, newmaster=%u, "
+						"telling master to get ref "
+						"for cleared out mle during "
+						"migration\n", dlm->name,
+						namelen, name, master,
+						new_master);
+			}
 		}
 		spin_unlock(&tmp->spinlock);
 	}
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 2060fc398445..7629da1b6897 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -231,6 +231,7 @@ static int ocfs2_mknod(struct inode *dir,
 	sigset_t oldset;
 	int did_block_signals = 0;
 	struct posix_acl *default_acl = NULL, *acl = NULL;
+	struct ocfs2_dentry_lock *dl = NULL;
 
 	trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name,
 			  (unsigned long long)OCFS2_I(dir)->ip_blkno,
@@ -423,6 +424,8 @@ static int ocfs2_mknod(struct inode *dir,
 		goto leave;
 	}
 
+	dl = dentry->d_fsdata;
+
 	status = ocfs2_add_entry(handle, dentry, inode,
 				 OCFS2_I(inode)->ip_blkno, parent_fe_bh,
 				 &lookup);
@@ -469,6 +472,16 @@ leave:
 	 * ocfs2_delete_inode will mutex_lock again.
 	 */
 	if ((status < 0) && inode) {
+		if (dl) {
+			ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
+			ocfs2_lock_res_free(&dl->dl_lockres);
+			BUG_ON(dl->dl_count != 1);
+			spin_lock(&dentry_attach_lock);
+			dentry->d_fsdata = NULL;
+			spin_unlock(&dentry_attach_lock);
+			kfree(dl);
+			iput(inode);
+		}
 		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
 		clear_nlink(inode);
 		iput(inode);
@@ -991,6 +1004,65 @@ leave:
 	return status;
 }
 
+static int ocfs2_check_if_ancestor(struct ocfs2_super *osb,
+		u64 src_inode_no, u64 dest_inode_no)
+{
+	int ret = 0, i = 0;
+	u64 parent_inode_no = 0;
+	u64 child_inode_no = src_inode_no;
+	struct inode *child_inode;
+
+#define MAX_LOOKUP_TIMES 32
+	while (1) {
+		child_inode = ocfs2_iget(osb, child_inode_no, 0, 0);
+		if (IS_ERR(child_inode)) {
+			ret = PTR_ERR(child_inode);
+			break;
+		}
+
+		ret = ocfs2_inode_lock(child_inode, NULL, 0);
+		if (ret < 0) {
+			iput(child_inode);
+			if (ret != -ENOENT)
+				mlog_errno(ret);
+			break;
+		}
+
+		ret = ocfs2_lookup_ino_from_name(child_inode, "..", 2,
+				&parent_inode_no);
+		ocfs2_inode_unlock(child_inode, 0);
+		iput(child_inode);
+		if (ret < 0) {
+			ret = -ENOENT;
+			break;
+		}
+
+		if (parent_inode_no == dest_inode_no) {
+			ret = 1;
+			break;
+		}
+
+		if (parent_inode_no == osb->root_inode->i_ino) {
+			ret = 0;
+			break;
+		}
+
+		child_inode_no = parent_inode_no;
+
+		if (++i >= MAX_LOOKUP_TIMES) {
+			mlog(ML_NOTICE, "max lookup times reached, filesystem "
+					"may have nested directories, "
+					"src inode: %llu, dest inode: %llu.\n",
+					(unsigned long long)src_inode_no,
+					(unsigned long long)dest_inode_no);
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
 /*
  * The only place this should be used is rename!
  * if they have the same id, then the 1st one is the only one locked.
@@ -1002,6 +1074,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
 			     struct inode *inode2)
 {
 	int status;
+	int inode1_is_ancestor, inode2_is_ancestor;
 	struct ocfs2_inode_info *oi1 = OCFS2_I(inode1);
 	struct ocfs2_inode_info *oi2 = OCFS2_I(inode2);
 	struct buffer_head **tmpbh;
@@ -1015,9 +1088,26 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
 	if (*bh2)
 		*bh2 = NULL;
 
-	/* we always want to lock the one with the lower lockid first. */
+	/* we always want to lock the one with the lower lockid first.
+	 * and if they are nested, we lock ancestor first */
 	if (oi1->ip_blkno != oi2->ip_blkno) {
-		if (oi1->ip_blkno < oi2->ip_blkno) {
+		inode1_is_ancestor = ocfs2_check_if_ancestor(osb, oi2->ip_blkno,
+				oi1->ip_blkno);
+		if (inode1_is_ancestor < 0) {
+			status = inode1_is_ancestor;
+			goto bail;
+		}
+
+		inode2_is_ancestor = ocfs2_check_if_ancestor(osb, oi1->ip_blkno,
+				oi2->ip_blkno);
+		if (inode2_is_ancestor < 0) {
+			status = inode2_is_ancestor;
+			goto bail;
+		}
+
+		if ((inode1_is_ancestor == 1) ||
+				(oi1->ip_blkno < oi2->ip_blkno &&
+				inode2_is_ancestor == 0)) {
 			/* switch id1 and id2 around */
 			tmpbh = bh2;
 			bh2 = bh1;
@@ -1134,6 +1224,22 @@ static int ocfs2_rename(struct inode *old_dir,
 			goto bail;
 		}
 		rename_lock = 1;
+
+		/* here we cannot guarantee the inodes haven't just been
+		 * changed, so check if they are nested again */
+		status = ocfs2_check_if_ancestor(osb, new_dir->i_ino,
+				old_inode->i_ino);
+		if (status < 0) {
+			mlog_errno(status);
+			goto bail;
+		} else if (status == 1) {
+			status = -EPERM;
+			mlog(ML_ERROR, "src inode %llu should not be ancestor "
+				"of new dir inode %llu\n",
+				(unsigned long long)old_inode->i_ino,
+				(unsigned long long)new_dir->i_ino);
+			goto bail;
+		}
 	}
 
 	/* if old and new are the same, this'll just do one lock. */
@@ -1642,6 +1748,7 @@ static int ocfs2_symlink(struct inode *dir,
 	struct ocfs2_dir_lookup_result lookup = { NULL, };
 	sigset_t oldset;
 	int did_block_signals = 0;
+	struct ocfs2_dentry_lock *dl = NULL;
 
 	trace_ocfs2_symlink_begin(dir, dentry, symname,
 				  dentry->d_name.len, dentry->d_name.name);
@@ -1830,6 +1937,8 @@ static int ocfs2_symlink(struct inode *dir,
 		goto bail;
 	}
 
+	dl = dentry->d_fsdata;
+
 	status = ocfs2_add_entry(handle, dentry, inode,
 				 le64_to_cpu(fe->i_blkno), parent_fe_bh,
 				 &lookup);
@@ -1864,6 +1973,16 @@ bail:
 	if (xattr_ac)
 		ocfs2_free_alloc_context(xattr_ac);
 	if ((status < 0) && inode) {
+		if (dl) {
+			ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
+			ocfs2_lock_res_free(&dl->dl_lockres);
+			BUG_ON(dl->dl_count != 1);
+			spin_lock(&dentry_attach_lock);
+			dentry->d_fsdata = NULL;
+			spin_unlock(&dentry_attach_lock);
+			kfree(dl);
+			iput(inode);
+		}
 		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
 		clear_nlink(inode);
 		iput(inode);
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 83f1a665ae97..5d965e83bd43 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -709,7 +709,7 @@ static struct ctl_table ocfs2_root_table[] = {
 	{ }
 };
 
-static struct ctl_table_header *ocfs2_table_header = NULL;
+static struct ctl_table_header *ocfs2_table_header;
 
 
 /*
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index a7cdd56f4c79..c7a89cea5c5d 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -75,7 +75,7 @@
 
 #include "buffer_head_io.h"
 
-static struct kmem_cache *ocfs2_inode_cachep = NULL;
+static struct kmem_cache *ocfs2_inode_cachep;
 struct kmem_cache *ocfs2_dquot_cachep;
 struct kmem_cache *ocfs2_qf_chunk_cachep;
 
@@ -85,7 +85,7 @@ struct kmem_cache *ocfs2_qf_chunk_cachep;
  * workqueue and schedule on our own. */
 struct workqueue_struct *ocfs2_wq = NULL;
 
-static struct dentry *ocfs2_debugfs_root = NULL;
+static struct dentry *ocfs2_debugfs_root;
 
 MODULE_AUTHOR("Oracle");
 MODULE_LICENSE("GPL");
@@ -2292,8 +2292,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
 		goto bail;
 	}
 
-	strncpy(osb->vol_label, di->id2.i_super.s_label, 63);
-	osb->vol_label[63] = '\0';
+	strlcpy(osb->vol_label, di->id2.i_super.s_label,
+		OCFS2_MAX_VOL_LABEL_LEN);
 	osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno);
 	osb->system_dir_blkno = le64_to_cpu(di->id2.i_super.s_system_dir_blkno);
 	osb->first_cluster_group_blkno =
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c
index 52eaf33d346f..82e17b076ce7 100644
--- a/fs/ocfs2/uptodate.c
+++ b/fs/ocfs2/uptodate.c
@@ -67,7 +67,7 @@ struct ocfs2_meta_cache_item {
 	sector_t	c_block;
 };
 
-static struct kmem_cache *ocfs2_uptodate_cachep = NULL;
+static struct kmem_cache *ocfs2_uptodate_cachep;
 
 u64 ocfs2_metadata_cache_owner(struct ocfs2_caching_info *ci)
 {
diff --git a/fs/open.c b/fs/open.c
index 3d30eb1fc95e..9d64679cec73 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -254,17 +254,22 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 		return -EBADF;
 
 	/*
-	 * It's not possible to punch hole or perform collapse range
-	 * on append only file
+	 * We can only allow pure fallocate on append only files
 	 */
-	if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE)
-	    && IS_APPEND(inode))
+	if ((mode & ~FALLOC_FL_KEEP_SIZE) && IS_APPEND(inode))
 		return -EPERM;
 
 	if (IS_IMMUTABLE(inode))
 		return -EPERM;
 
 	/*
+	 * We can not allow to do any fallocate operation on an active
+	 * swapfile
+	 */
+	if (IS_SWAPFILE(inode))
+		ret = -ETXTBSY;
+
+	/*
 	 * Revalidate the write permissions, in case security policy has
 	 * changed since the files were opened.
 	 */
@@ -286,14 +291,6 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
 		return -EFBIG;
 
-	/*
-	 * There is no need to overlap collapse range with EOF, in which case
-	 * it is effectively a truncate operation
-	 */
-	if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
-	    (offset + len >= i_size_read(inode)))
-		return -EINVAL;
-
 	if (!file->f_op->fallocate)
 		return -EOPNOTSUPP;
 
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 442177b1119a..fa6d6a4e85b3 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -424,7 +424,6 @@ const struct file_operations proc_tid_maps_operations = {
 
 #ifdef CONFIG_PROC_PAGE_MONITOR
 struct mem_size_stats {
-	struct vm_area_struct *vma;
 	unsigned long resident;
 	unsigned long shared_clean;
 	unsigned long shared_dirty;
@@ -438,15 +437,16 @@ struct mem_size_stats {
 	u64 pss;
 };
 
-
-static void smaps_pte_entry(pte_t ptent, unsigned long addr,
-		unsigned long ptent_size, struct mm_walk *walk)
+static int smaps_pte(pte_t *pte, unsigned long addr, unsigned long end,
+			struct mm_walk *walk)
 {
 	struct mem_size_stats *mss = walk->private;
-	struct vm_area_struct *vma = mss->vma;
+	struct vm_area_struct *vma = walk->vma;
 	pgoff_t pgoff = linear_page_index(vma, addr);
 	struct page *page = NULL;
 	int mapcount;
+	pte_t ptent = *pte;
+	unsigned long ptent_size = end - addr;
 
 	if (pte_present(ptent)) {
 		page = vm_normal_page(vma, addr, ptent);
@@ -463,7 +463,7 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr,
 	}
 
 	if (!page)
-		return;
+		return 0;
 
 	if (PageAnon(page))
 		mss->anonymous += ptent_size;
@@ -489,35 +489,22 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr,
 			mss->private_clean += ptent_size;
 		mss->pss += (ptent_size << PSS_SHIFT);
 	}
+	return 0;
 }
 
-static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-			   struct mm_walk *walk)
+static int smaps_pmd(pmd_t *pmd, unsigned long addr, unsigned long end,
+			struct mm_walk *walk)
 {
 	struct mem_size_stats *mss = walk->private;
-	struct vm_area_struct *vma = mss->vma;
-	pte_t *pte;
 	spinlock_t *ptl;
 
-	if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
-		smaps_pte_entry(*(pte_t *)pmd, addr, HPAGE_PMD_SIZE, walk);
+	if (pmd_trans_huge_lock(pmd, walk->vma, &ptl) == 1) {
+		smaps_pte((pte_t *)pmd, addr, addr + HPAGE_PMD_SIZE, walk);
 		spin_unlock(ptl);
 		mss->anonymous_thp += HPAGE_PMD_SIZE;
-		return 0;
+		/* don't call smaps_pte() */
+		walk->skip = 1;
 	}
-
-	if (pmd_trans_unstable(pmd))
-		return 0;
-	/*
-	 * The mmap_sem held all the way back in m_start() is what
-	 * keeps khugepaged out of here and from collapsing things
-	 * in here.
-	 */
-	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	for (; addr != end; pte++, addr += PAGE_SIZE)
-		smaps_pte_entry(*pte, addr, PAGE_SIZE, walk);
-	pte_unmap_unlock(pte - 1, ptl);
-	cond_resched();
 	return 0;
 }
 
@@ -582,16 +569,16 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 	struct vm_area_struct *vma = v;
 	struct mem_size_stats mss;
 	struct mm_walk smaps_walk = {
-		.pmd_entry = smaps_pte_range,
+		.pmd_entry = smaps_pmd,
+		.pte_entry = smaps_pte,
 		.mm = vma->vm_mm,
+		.vma = vma,
 		.private = &mss,
 	};
 
 	memset(&mss, 0, sizeof mss);
-	mss.vma = vma;
 	/* mmap_sem is held in m_start */
-	if (vma->vm_mm && !is_vm_hugetlb_page(vma))
-		walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
+	walk_page_vma(vma, &smaps_walk);
 
 	show_map_vma(m, vma, is_pid);
 
@@ -712,7 +699,6 @@ enum clear_refs_types {
 };
 
 struct clear_refs_private {
-	struct vm_area_struct *vma;
 	enum clear_refs_types type;
 };
 
@@ -737,48 +723,52 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,
 		ptent = pte_file_clear_soft_dirty(ptent);
 	}
 
-	if (vma->vm_flags & VM_SOFTDIRTY)
-		vma->vm_flags &= ~VM_SOFTDIRTY;
-
 	set_pte_at(vma->vm_mm, addr, pte, ptent);
 #endif
 }
 
-static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
+static int clear_refs_pte(pte_t *pte, unsigned long addr,
 				unsigned long end, struct mm_walk *walk)
 {
 	struct clear_refs_private *cp = walk->private;
-	struct vm_area_struct *vma = cp->vma;
-	pte_t *pte, ptent;
-	spinlock_t *ptl;
+	struct vm_area_struct *vma = walk->vma;
 	struct page *page;
 
-	split_huge_page_pmd(vma, addr, pmd);
-	if (pmd_trans_unstable(pmd))
+	if (cp->type == CLEAR_REFS_SOFT_DIRTY) {
+		clear_soft_dirty(vma, addr, pte);
 		return 0;
+	}
+	if (!pte_present(*pte))
+		return 0;
+	page = vm_normal_page(vma, addr, *pte);
+	if (!page)
+		return 0;
+	/* Clear accessed and referenced bits. */
+	ptep_test_and_clear_young(vma, addr, pte);
+	ClearPageReferenced(page);
+	return 0;
+}
 
-	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	for (; addr != end; pte++, addr += PAGE_SIZE) {
-		ptent = *pte;
-
-		if (cp->type == CLEAR_REFS_SOFT_DIRTY) {
-			clear_soft_dirty(vma, addr, pte);
-			continue;
-		}
-
-		if (!pte_present(ptent))
-			continue;
-
-		page = vm_normal_page(vma, addr, ptent);
-		if (!page)
-			continue;
+static int clear_refs_test_walk(unsigned long start, unsigned long end,
+				struct mm_walk *walk)
+{
+	struct clear_refs_private *cp = walk->private;
+	struct vm_area_struct *vma = walk->vma;
 
-		/* Clear accessed and referenced bits. */
-		ptep_test_and_clear_young(vma, addr, pte);
-		ClearPageReferenced(page);
+	/*
+	 * Writing 1 to /proc/pid/clear_refs affects all pages.
+	 * Writing 2 to /proc/pid/clear_refs only affects anonymous pages.
+	 * Writing 3 to /proc/pid/clear_refs only affects file mapped pages.
+	 * Writing 4 to /proc/pid/clear_refs affects all pages.
+	 */
+	if (cp->type == CLEAR_REFS_ANON && vma->vm_file)
+		walk->skip = 1;
+	if (cp->type == CLEAR_REFS_MAPPED && !vma->vm_file)
+		walk->skip = 1;
+	if (cp->type == CLEAR_REFS_SOFT_DIRTY) {
+		if (vma->vm_flags & VM_SOFTDIRTY)
+			vma->vm_flags &= ~VM_SOFTDIRTY;
 	}
-	pte_unmap_unlock(pte - 1, ptl);
-	cond_resched();
 	return 0;
 }
 
@@ -807,8 +797,9 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 
 	if (type == CLEAR_REFS_SOFT_DIRTY) {
 		soft_dirty_cleared = true;
-		pr_warn_once("The pagemap bits 55-60 has changed their meaning! "
-				"See the linux/Documentation/vm/pagemap.txt for details.\n");
+		pr_warn_once("The pagemap bits 55-60 has changed their meaning!"
+			     " See the linux/Documentation/vm/pagemap.txt for "
+			     "details.\n");
 	}
 
 	task = get_proc_task(file_inode(file));
@@ -820,33 +811,16 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 			.type = type,
 		};
 		struct mm_walk clear_refs_walk = {
-			.pmd_entry = clear_refs_pte_range,
+			.pte_entry = clear_refs_pte,
+			.test_walk = clear_refs_test_walk,
 			.mm = mm,
 			.private = &cp,
 		};
 		down_read(&mm->mmap_sem);
 		if (type == CLEAR_REFS_SOFT_DIRTY)
 			mmu_notifier_invalidate_range_start(mm, 0, -1);
-		for (vma = mm->mmap; vma; vma = vma->vm_next) {
-			cp.vma = vma;
-			if (is_vm_hugetlb_page(vma))
-				continue;
-			/*
-			 * Writing 1 to /proc/pid/clear_refs affects all pages.
-			 *
-			 * Writing 2 to /proc/pid/clear_refs only affects
-			 * Anonymous pages.
-			 *
-			 * Writing 3 to /proc/pid/clear_refs only affects file
-			 * mapped pages.
-			 */
-			if (type == CLEAR_REFS_ANON && vma->vm_file)
-				continue;
-			if (type == CLEAR_REFS_MAPPED && !vma->vm_file)
-				continue;
-			walk_page_range(vma->vm_start, vma->vm_end,
-					&clear_refs_walk);
-		}
+		for (vma = mm->mmap; vma; vma = vma->vm_next)
+			walk_page_vma(vma, &clear_refs_walk);
 		if (type == CLEAR_REFS_SOFT_DIRTY)
 			mmu_notifier_invalidate_range_end(mm, 0, -1);
 		flush_tlb_mm(mm);
@@ -987,19 +961,33 @@ static inline void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, struct pagemap
 }
 #endif
 
-static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+static int pagemap_pte(pte_t *pte, unsigned long addr, unsigned long end,
 			     struct mm_walk *walk)
 {
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma = walk->vma;
 	struct pagemapread *pm = walk->private;
-	spinlock_t *ptl;
-	pte_t *pte;
+	pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
+
+	if (vma && vma->vm_start <= addr && end <= vma->vm_end) {
+		pte_to_pagemap_entry(&pme, pm, vma, addr, *pte);
+		/* unmap before userspace copy */
+		pte_unmap(pte);
+	}
+	return add_to_pagemap(addr, &pme, pm);
+}
+
+static int pagemap_pmd(pmd_t *pmd, unsigned long addr, unsigned long end,
+			     struct mm_walk *walk)
+{
 	int err = 0;
+	struct vm_area_struct *vma = walk->vma;
+	struct pagemapread *pm = walk->private;
 	pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
+	spinlock_t *ptl;
 
-	/* find the first VMA at or above 'addr' */
-	vma = find_vma(walk->mm, addr);
-	if (vma && pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
+	if (!vma)
+		return err;
+	if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
 		int pmd_flags2;
 
 		if ((vma->vm_flags & VM_SOFTDIRTY) || pmd_soft_dirty(*pmd))
@@ -1018,41 +1006,9 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 				break;
 		}
 		spin_unlock(ptl);
-		return err;
+		/* don't call pagemap_pte() */
+		walk->skip = 1;
 	}
-
-	if (pmd_trans_unstable(pmd))
-		return 0;
-	for (; addr != end; addr += PAGE_SIZE) {
-		int flags2;
-
-		/* check to see if we've left 'vma' behind
-		 * and need a new, higher one */
-		if (vma && (addr >= vma->vm_end)) {
-			vma = find_vma(walk->mm, addr);
-			if (vma && (vma->vm_flags & VM_SOFTDIRTY))
-				flags2 = __PM_SOFT_DIRTY;
-			else
-				flags2 = 0;
-			pme = make_pme(PM_NOT_PRESENT(pm->v2) | PM_STATUS2(pm->v2, flags2));
-		}
-
-		/* check that 'vma' actually covers this address,
-		 * and that it isn't a huge page vma */
-		if (vma && (vma->vm_start <= addr) &&
-		    !is_vm_hugetlb_page(vma)) {
-			pte = pte_offset_map(pmd, addr);
-			pte_to_pagemap_entry(&pme, pm, vma, addr, *pte);
-			/* unmap before userspace copy */
-			pte_unmap(pte);
-		}
-		err = add_to_pagemap(addr, &pme, pm);
-		if (err)
-			return err;
-	}
-
-	cond_resched();
-
 	return err;
 }
 
@@ -1070,24 +1026,22 @@ static void huge_pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *
 }
 
 /* This function walks within one hugetlb entry in the single call */
-static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
-				 unsigned long addr, unsigned long end,
-				 struct mm_walk *walk)
+static int pagemap_hugetlb(pte_t *pte, unsigned long addr, unsigned long end,
+			   struct mm_walk *walk)
 {
 	struct pagemapread *pm = walk->private;
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma = walk->vma;
 	int err = 0;
 	int flags2;
 	pagemap_entry_t pme;
+	unsigned long hmask;
 
-	vma = find_vma(walk->mm, addr);
-	WARN_ON_ONCE(!vma);
-
-	if (vma && (vma->vm_flags & VM_SOFTDIRTY))
+	if (vma->vm_flags & VM_SOFTDIRTY)
 		flags2 = __PM_SOFT_DIRTY;
 	else
 		flags2 = 0;
 
+	hmask = huge_page_mask(hstate_vma(vma));
 	for (; addr != end; addr += PAGE_SIZE) {
 		int offset = (addr & ~hmask) >> PAGE_SHIFT;
 		huge_pte_to_pagemap_entry(&pme, pm, *pte, offset, flags2);
@@ -1095,9 +1049,6 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
 		if (err)
 			return err;
 	}
-
-	cond_resched();
-
 	return err;
 }
 #endif /* HUGETLB_PAGE */
@@ -1164,10 +1115,11 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
 	if (!mm || IS_ERR(mm))
 		goto out_free;
 
-	pagemap_walk.pmd_entry = pagemap_pte_range;
+	pagemap_walk.pte_entry = pagemap_pte;
+	pagemap_walk.pmd_entry = pagemap_pmd;
 	pagemap_walk.pte_hole = pagemap_pte_hole;
 #ifdef CONFIG_HUGETLB_PAGE
-	pagemap_walk.hugetlb_entry = pagemap_hugetlb_range;
+	pagemap_walk.hugetlb_entry = pagemap_hugetlb;
 #endif
 	pagemap_walk.mm = mm;
 	pagemap_walk.private = &pm;
@@ -1243,7 +1195,6 @@ const struct file_operations proc_pagemap_operations = {
 #ifdef CONFIG_NUMA
 
 struct numa_maps {
-	struct vm_area_struct *vma;
 	unsigned long pages;
 	unsigned long anon;
 	unsigned long active;
@@ -1309,44 +1260,42 @@ static struct page *can_gather_numa_stats(pte_t pte, struct vm_area_struct *vma,
 	return page;
 }
 
-static int gather_pte_stats(pmd_t *pmd, unsigned long addr,
+static int gather_pte_stats(pte_t *pte, unsigned long addr,
 		unsigned long end, struct mm_walk *walk)
 {
-	struct numa_maps *md;
-	spinlock_t *ptl;
-	pte_t *orig_pte;
-	pte_t *pte;
+	struct numa_maps *md = walk->private;
 
-	md = walk->private;
+	struct page *page = can_gather_numa_stats(*pte, walk->vma, addr);
+	if (!page)
+		return 0;
+	gather_stats(page, md, pte_dirty(*pte), 1);
+	return 0;
+}
 
-	if (pmd_trans_huge_lock(pmd, md->vma, &ptl) == 1) {
+static int gather_pmd_stats(pmd_t *pmd, unsigned long addr,
+		unsigned long end, struct mm_walk *walk)
+{
+	struct numa_maps *md = walk->private;
+	struct vm_area_struct *vma = walk->vma;
+	spinlock_t *ptl;
+
+	if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
 		pte_t huge_pte = *(pte_t *)pmd;
 		struct page *page;
 
-		page = can_gather_numa_stats(huge_pte, md->vma, addr);
+		page = can_gather_numa_stats(huge_pte, vma, addr);
 		if (page)
 			gather_stats(page, md, pte_dirty(huge_pte),
 				     HPAGE_PMD_SIZE/PAGE_SIZE);
 		spin_unlock(ptl);
-		return 0;
+		/* don't call gather_pte_stats() */
+		walk->skip = 1;
 	}
-
-	if (pmd_trans_unstable(pmd))
-		return 0;
-	orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
-	do {
-		struct page *page = can_gather_numa_stats(*pte, md->vma, addr);
-		if (!page)
-			continue;
-		gather_stats(page, md, pte_dirty(*pte), 1);
-
-	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap_unlock(orig_pte, ptl);
 	return 0;
 }
 #ifdef CONFIG_HUGETLB_PAGE
-static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
-		unsigned long addr, unsigned long end, struct mm_walk *walk)
+static int gather_hugetlb_stats(pte_t *pte, unsigned long addr,
+				unsigned long end, struct mm_walk *walk)
 {
 	struct numa_maps *md;
 	struct page *page;
@@ -1354,6 +1303,9 @@ static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
 	if (pte_none(*pte))
 		return 0;
 
+	if (!pte_present(*pte))
+		return 0;
+
 	page = pte_page(*pte);
 	if (!page)
 		return 0;
@@ -1364,8 +1316,8 @@ static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
 }
 
 #else
-static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
-		unsigned long addr, unsigned long end, struct mm_walk *walk)
+static int gather_hugetlb_stats(pte_t *pte, unsigned long addr,
+				unsigned long end, struct mm_walk *walk)
 {
 	return 0;
 }
@@ -1394,12 +1346,12 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
 	/* Ensure we start with an empty set of numa_maps statistics. */
 	memset(md, 0, sizeof(*md));
 
-	md->vma = vma;
-
-	walk.hugetlb_entry = gather_hugetbl_stats;
-	walk.pmd_entry = gather_pte_stats;
+	walk.hugetlb_entry = gather_hugetlb_stats;
+	walk.pmd_entry = gather_pmd_stats;
+	walk.pte_entry = gather_pte_stats;
 	walk.private = md;
 	walk.mm = mm;
+	walk.vma = vma;
 
 	pol = get_vma_policy(task, vma, vma->vm_start);
 	mpol_to_str(buffer, sizeof(buffer), pol);
@@ -1430,6 +1382,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
 	if (is_vm_hugetlb_page(vma))
 		seq_printf(m, " huge");
 
+	/* mmap_sem is held by m_start */
 	walk_page_range(vma->vm_start, vma->vm_end, &walk);
 
 	if (!md->pages)
diff --git a/fs/super.c b/fs/super.c
index e9dc3c3fe159..48377f7463c0 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -800,7 +800,10 @@ void emergency_remount(void)
 
 static DEFINE_IDA(unnamed_dev_ida);
 static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
-static int unnamed_dev_start = 0; /* don't bother trying below it */
+/* Many userspace utilities consider an FSID of 0 invalid.
+ * Always return at least 1 from get_anon_bdev.
+ */
+static int unnamed_dev_start = 1;
 
 int get_anon_bdev(dev_t *p)
 {
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 1b8b91b67fdb..28cc1acd5439 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -453,95 +453,3 @@ void sysfs_remove_bin_file(struct kobject *kobj,
 	kernfs_remove_by_name(kobj->sd, attr->attr.name);
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
-
-struct sysfs_schedule_callback_struct {
-	struct list_head	workq_list;
-	struct kobject		*kobj;
-	void			(*func)(void *);
-	void			*data;
-	struct module		*owner;
-	struct work_struct	work;
-};
-
-static struct workqueue_struct *sysfs_workqueue;
-static DEFINE_MUTEX(sysfs_workq_mutex);
-static LIST_HEAD(sysfs_workq);
-static void sysfs_schedule_callback_work(struct work_struct *work)
-{
-	struct sysfs_schedule_callback_struct *ss = container_of(work,
-			struct sysfs_schedule_callback_struct, work);
-
-	(ss->func)(ss->data);
-	kobject_put(ss->kobj);
-	module_put(ss->owner);
-	mutex_lock(&sysfs_workq_mutex);
-	list_del(&ss->workq_list);
-	mutex_unlock(&sysfs_workq_mutex);
-	kfree(ss);
-}
-
-/**
- * sysfs_schedule_callback - helper to schedule a callback for a kobject
- * @kobj: object we're acting for.
- * @func: callback function to invoke later.
- * @data: argument to pass to @func.
- * @owner: module owning the callback code
- *
- * sysfs attribute methods must not unregister themselves or their parent
- * kobject (which would amount to the same thing).  Attempts to do so will
- * deadlock, since unregistration is mutually exclusive with driver
- * callbacks.
- *
- * Instead methods can call this routine, which will attempt to allocate
- * and schedule a workqueue request to call back @func with @data as its
- * argument in the workqueue's process context.  @kobj will be pinned
- * until @func returns.
- *
- * Returns 0 if the request was submitted, -ENOMEM if storage could not
- * be allocated, -ENODEV if a reference to @owner isn't available,
- * -EAGAIN if a callback has already been scheduled for @kobj.
- */
-int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
-		void *data, struct module *owner)
-{
-	struct sysfs_schedule_callback_struct *ss, *tmp;
-
-	if (!try_module_get(owner))
-		return -ENODEV;
-
-	mutex_lock(&sysfs_workq_mutex);
-	list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list)
-		if (ss->kobj == kobj) {
-			module_put(owner);
-			mutex_unlock(&sysfs_workq_mutex);
-			return -EAGAIN;
-		}
-	mutex_unlock(&sysfs_workq_mutex);
-
-	if (sysfs_workqueue == NULL) {
-		sysfs_workqueue = create_singlethread_workqueue("sysfsd");
-		if (sysfs_workqueue == NULL) {
-			module_put(owner);
-			return -ENOMEM;
-		}
-	}
-
-	ss = kmalloc(sizeof(*ss), GFP_KERNEL);
-	if (!ss) {
-		module_put(owner);
-		return -ENOMEM;
-	}
-	kobject_get(kobj);
-	ss->kobj = kobj;
-	ss->func = func;
-	ss->data = data;
-	ss->owner = owner;
-	INIT_WORK(&ss->work, sysfs_schedule_callback_work);
-	INIT_LIST_HEAD(&ss->workq_list);
-	mutex_lock(&sysfs_workq_mutex);
-	list_add_tail(&ss->workq_list, &sysfs_workq);
-	mutex_unlock(&sysfs_workq_mutex);
-	queue_work(sysfs_workqueue, &ss->work);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 0ab1de4b39a5..dd5d176c9c2f 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -52,7 +52,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
 	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
 		ufs_error (sb, "ufs_free_fragments", "internal error");
 	
-	mutex_lock(&UFS_SB(sb)->s_lock);
+	lock_ufs(sb);
 	
 	cgno = ufs_dtog(uspi, fragment);
 	bit = ufs_dtogd(uspi, fragment);
@@ -116,12 +116,12 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
 		ubh_sync_block(UCPI_UBH(ucpi));
 	ufs_mark_sb_dirty(sb);
 	
-	mutex_unlock(&UFS_SB(sb)->s_lock);
+	unlock_ufs(sb);
 	UFSD("EXIT\n");
 	return;
 
 failed:
-	mutex_unlock(&UFS_SB(sb)->s_lock);
+	unlock_ufs(sb);
 	UFSD("EXIT (FAILED)\n");
 	return;
 }
@@ -151,7 +151,7 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
 		goto failed;
 	}
 
-	mutex_lock(&UFS_SB(sb)->s_lock);
+	lock_ufs(sb);
 	
 do_more:
 	overflow = 0;
@@ -211,12 +211,12 @@ do_more:
 	}
 
 	ufs_mark_sb_dirty(sb);
-	mutex_unlock(&UFS_SB(sb)->s_lock);
+	unlock_ufs(sb);
 	UFSD("EXIT\n");
 	return;
 
 failed_unlock:
-	mutex_unlock(&UFS_SB(sb)->s_lock);
+	unlock_ufs(sb);
 failed:
 	UFSD("EXIT (FAILED)\n");
 	return;
@@ -357,7 +357,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
 	usb1 = ubh_get_usb_first(uspi);
 	*err = -ENOSPC;
 
-	mutex_lock(&UFS_SB(sb)->s_lock);
+	lock_ufs(sb);
 	tmp = ufs_data_ptr_to_cpu(sb, p);
 
 	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
@@ -378,19 +378,19 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
 				  "fragment %llu, tmp %llu\n",
 				  (unsigned long long)fragment,
 				  (unsigned long long)tmp);
-			mutex_unlock(&UFS_SB(sb)->s_lock);
+			unlock_ufs(sb);
 			return INVBLOCK;
 		}
 		if (fragment < UFS_I(inode)->i_lastfrag) {
 			UFSD("EXIT (ALREADY ALLOCATED)\n");
-			mutex_unlock(&UFS_SB(sb)->s_lock);
+			unlock_ufs(sb);
 			return 0;
 		}
 	}
 	else {
 		if (tmp) {
 			UFSD("EXIT (ALREADY ALLOCATED)\n");
-			mutex_unlock(&UFS_SB(sb)->s_lock);
+			unlock_ufs(sb);
 			return 0;
 		}
 	}
@@ -399,7 +399,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
 	 * There is not enough space for user on the device
 	 */
 	if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
-		mutex_unlock(&UFS_SB(sb)->s_lock);
+		unlock_ufs(sb);
 		UFSD("EXIT (FAILED)\n");
 		return 0;
 	}
@@ -424,7 +424,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
 			ufs_clear_frags(inode, result + oldcount,
 					newcount - oldcount, locked_page != NULL);
 		}
-		mutex_unlock(&UFS_SB(sb)->s_lock);
+		unlock_ufs(sb);
 		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
@@ -439,7 +439,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
 						fragment + count);
 		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
 				locked_page != NULL);
-		mutex_unlock(&UFS_SB(sb)->s_lock);
+		unlock_ufs(sb);
 		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
@@ -477,7 +477,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
 		*err = 0;
 		UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
 						fragment + count);
-		mutex_unlock(&UFS_SB(sb)->s_lock);
+		unlock_ufs(sb);
 		if (newcount < request)
 			ufs_free_fragments (inode, result + newcount, request - newcount);
 		ufs_free_fragments (inode, tmp, oldcount);
@@ -485,7 +485,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
 		return result;
 	}
 
-	mutex_unlock(&UFS_SB(sb)->s_lock);
+	unlock_ufs(sb);
 	UFSD("EXIT (FAILED)\n");
 	return 0;
 }		
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 98f7211599ff..a9cc75ffa925 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -69,11 +69,11 @@ void ufs_free_inode (struct inode * inode)
 	
 	ino = inode->i_ino;
 
-	mutex_lock(&UFS_SB(sb)->s_lock);
+	lock_ufs(sb);
 
 	if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) {
 		ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino);
-		mutex_unlock(&UFS_SB(sb)->s_lock);
+		unlock_ufs(sb);
 		return;
 	}
 	
@@ -81,7 +81,7 @@ void ufs_free_inode (struct inode * inode)
 	bit = ufs_inotocgoff (ino);
 	ucpi = ufs_load_cylinder (sb, cg);
 	if (!ucpi) {
-		mutex_unlock(&UFS_SB(sb)->s_lock);
+		unlock_ufs(sb);
 		return;
 	}
 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
@@ -115,7 +115,7 @@ void ufs_free_inode (struct inode * inode)
 		ubh_sync_block(UCPI_UBH(ucpi));
 	
 	ufs_mark_sb_dirty(sb);
-	mutex_unlock(&UFS_SB(sb)->s_lock);
+	unlock_ufs(sb);
 	UFSD("EXIT\n");
 }
 
@@ -193,7 +193,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
 	sbi = UFS_SB(sb);
 	uspi = sbi->s_uspi;
 
-	mutex_lock(&sbi->s_lock);
+	lock_ufs(sb);
 
 	/*
 	 * Try to place the inode in its parent directory
@@ -328,21 +328,20 @@ cg_found:
 			sync_dirty_buffer(bh);
 		brelse(bh);
 	}
-
-	mutex_unlock(&sbi->s_lock);
+	unlock_ufs(sb);
 
 	UFSD("allocating inode %lu\n", inode->i_ino);
 	UFSD("EXIT\n");
 	return inode;
 
 fail_remove_inode:
-	mutex_unlock(&sbi->s_lock);
+	unlock_ufs(sb);
 	clear_nlink(inode);
 	iput(inode);
 	UFSD("EXIT (FAILED): err %d\n", err);
 	return ERR_PTR(err);
 failed:
-	mutex_unlock(&sbi->s_lock);
+	unlock_ufs(sb);
 	make_bad_inode(inode);
 	iput (inode);
 	UFSD("EXIT (FAILED): err %d\n", err);
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index c1183f9f69dc..b879f1ba3439 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -697,7 +697,6 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
 	unsigned flags;
 
 	lock_ufs(sb);
-	mutex_lock(&UFS_SB(sb)->s_lock);
 
 	UFSD("ENTER\n");
 
@@ -715,7 +714,6 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
 	ufs_put_cstotal(sb);
 
 	UFSD("EXIT\n");
-	mutex_unlock(&UFS_SB(sb)->s_lock);
 	unlock_ufs(sb);
 
 	return 0;
@@ -760,6 +758,7 @@ static void ufs_put_super(struct super_block *sb)
 
 	ubh_brelse_uspi (sbi->s_uspi);
 	kfree (sbi->s_uspi);
+	mutex_destroy(&sbi->mutex);
 	kfree (sbi);
 	sb->s_fs_info = NULL;
 	UFSD("EXIT\n");
@@ -786,6 +785,14 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 	flags = 0;
 	
 	UFSD("ENTER\n");
+
+#ifndef CONFIG_UFS_FS_WRITE
+	if (!(sb->s_flags & MS_RDONLY)) {
+		printk("ufs was compiled with read-only support, "
+		       "can't be mounted as read-write\n");
+		return -EROFS;
+	}
+#endif
 		
 	sbi = kzalloc(sizeof(struct ufs_sb_info), GFP_KERNEL);
 	if (!sbi)
@@ -795,15 +802,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 
 	UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY));
 	
-#ifndef CONFIG_UFS_FS_WRITE
-	if (!(sb->s_flags & MS_RDONLY)) {
-		printk("ufs was compiled with read-only support, "
-		"can't be mounted as read-write\n");
-		goto failed;
-	}
-#endif
 	mutex_init(&sbi->mutex);
-	mutex_init(&sbi->s_lock);
 	spin_lock_init(&sbi->work_lock);
 	INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
 	/*
@@ -1257,6 +1256,7 @@ magic_found:
 	return 0;
 
 failed:
+	mutex_destroy(&sbi->mutex);
 	if (ubh)
 		ubh_brelse_uspi (uspi);
 	kfree (uspi);
@@ -1280,7 +1280,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 
 	sync_filesystem(sb);
 	lock_ufs(sb);
-	mutex_lock(&UFS_SB(sb)->s_lock);
 	uspi = UFS_SB(sb)->s_uspi;
 	flags = UFS_SB(sb)->s_flags;
 	usb1 = ubh_get_usb_first(uspi);
@@ -1294,7 +1293,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 	new_mount_opt = 0;
 	ufs_set_opt (new_mount_opt, ONERROR_LOCK);
 	if (!ufs_parse_options (data, &new_mount_opt)) {
-		mutex_unlock(&UFS_SB(sb)->s_lock);
 		unlock_ufs(sb);
 		return -EINVAL;
 	}
@@ -1302,14 +1300,12 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 		new_mount_opt |= ufstype;
 	} else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
 		printk("ufstype can't be changed during remount\n");
-		mutex_unlock(&UFS_SB(sb)->s_lock);
 		unlock_ufs(sb);
 		return -EINVAL;
 	}
 
 	if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
 		UFS_SB(sb)->s_mount_opt = new_mount_opt;
-		mutex_unlock(&UFS_SB(sb)->s_lock);
 		unlock_ufs(sb);
 		return 0;
 	}
@@ -1334,7 +1330,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 #ifndef CONFIG_UFS_FS_WRITE
 		printk("ufs was compiled with read-only support, "
 		"can't be mounted as read-write\n");
-		mutex_unlock(&UFS_SB(sb)->s_lock);
 		unlock_ufs(sb);
 		return -EINVAL;
 #else
@@ -1344,13 +1339,11 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
 		    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
 			printk("this ufstype is read-only supported\n");
-			mutex_unlock(&UFS_SB(sb)->s_lock);
 			unlock_ufs(sb);
 			return -EINVAL;
 		}
 		if (!ufs_read_cylinder_structures(sb)) {
 			printk("failed during remounting\n");
-			mutex_unlock(&UFS_SB(sb)->s_lock);
 			unlock_ufs(sb);
 			return -EPERM;
 		}
@@ -1358,7 +1351,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 #endif
 	}
 	UFS_SB(sb)->s_mount_opt = new_mount_opt;
-	mutex_unlock(&UFS_SB(sb)->s_lock);
 	unlock_ufs(sb);
 	return 0;
 }
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
index ff2c15ab81aa..343e6fc571e5 100644
--- a/fs/ufs/ufs.h
+++ b/fs/ufs/ufs.h
@@ -24,7 +24,6 @@ struct ufs_sb_info {
 	int work_queued; /* non-zero if the delayed work is queued */
 	struct delayed_work sync_work; /* FS sync delayed work */
 	spinlock_t work_lock; /* protects sync_work and work_queued */
-	struct mutex s_lock;
 };
 
 struct ufs_inode_info {
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 75df77d09f75..0479c32c5eb1 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1344,6 +1344,14 @@ __xfs_get_blocks(
 	/*
 	 * If this is O_DIRECT or the mpage code calling tell them how large
 	 * the mapping is, so that we can avoid repeated get_blocks calls.
+	 *
+	 * If the mapping spans EOF, then we have to break the mapping up as the
+	 * mapping for blocks beyond EOF must be marked new so that sub block
+	 * regions can be correctly zeroed. We can't do this for mappings within
+	 * EOF unless the mapping was just allocated or is unwritten, otherwise
+	 * the callers would overwrite existing data with zeros. Hence we have
+	 * to split the mapping into a range up to and including EOF, and a
+	 * second mapping for beyond EOF.
 	 */
 	if (direct || size > (1 << inode->i_blkbits)) {
 		xfs_off_t		mapping_size;
@@ -1354,6 +1362,12 @@ __xfs_get_blocks(
 		ASSERT(mapping_size > 0);
 		if (mapping_size > size)
 			mapping_size = size;
+		if (offset < i_size_read(inode) &&
+		    offset + mapping_size >= i_size_read(inode)) {
+			/* limit mapping to block that spans EOF */
+			mapping_size = roundup_64(i_size_read(inode) - offset,
+						  1 << inode->i_blkbits);
+		}
 		if (mapping_size > LONG_MAX)
 			mapping_size = LONG_MAX;
 
@@ -1566,6 +1580,16 @@ xfs_vm_write_failed(
 
 		xfs_vm_kill_delalloc_range(inode, block_offset,
 					   block_offset + bh->b_size);
+
+		/*
+		 * This buffer does not contain data anymore. make sure anyone
+		 * who finds it knows that for certain.
+		 */
+		clear_buffer_delay(bh);
+		clear_buffer_uptodate(bh);
+		clear_buffer_mapped(bh);
+		clear_buffer_new(bh);
+		clear_buffer_dirty(bh);
 	}
 
 }
@@ -1599,12 +1623,21 @@ xfs_vm_write_begin(
 	status = __block_write_begin(page, pos, len, xfs_get_blocks);
 	if (unlikely(status)) {
 		struct inode	*inode = mapping->host;
+		size_t		isize = i_size_read(inode);
 
 		xfs_vm_write_failed(inode, page, pos, len);
 		unlock_page(page);
 
-		if (pos + len > i_size_read(inode))
-			truncate_pagecache(inode, i_size_read(inode));
+		/*
+		 * If the write is beyond EOF, we only want to kill blocks
+		 * allocated in this write, not blocks that were previously
+		 * written successfully.
+		 */
+		if (pos + len > isize) {
+			ssize_t start = max_t(ssize_t, pos, isize);
+
+			truncate_pagecache_range(inode, start, pos + len);
+		}
 
 		page_cache_release(page);
 		page = NULL;
@@ -1615,9 +1648,12 @@ xfs_vm_write_begin(
 }
 
 /*
- * On failure, we only need to kill delalloc blocks beyond EOF because they
- * will never be written. For blocks within EOF, generic_write_end() zeros them
- * so they are safe to leave alone and be written with all the other valid data.
+ * On failure, we only need to kill delalloc blocks beyond EOF in the range of
+ * this specific write because they will never be written. Previous writes
+ * beyond EOF where block allocation succeeded do not need to be trashed, so
+ * only new blocks from this write should be trashed. For blocks within
+ * EOF, generic_write_end() zeros them so they are safe to leave alone and be
+ * written with all the other valid data.
  */
 STATIC int
 xfs_vm_write_end(
@@ -1640,8 +1676,11 @@ xfs_vm_write_end(
 		loff_t		to = pos + len;
 
 		if (to > isize) {
-			truncate_pagecache(inode, isize);
+			/* only kill blocks in this write beyond EOF */
+			if (pos > isize)
+				isize = pos;
 			xfs_vm_kill_delalloc_range(inode, isize, to);
+			truncate_pagecache_range(inode, isize, to);
 		}
 	}
 	return ret;
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 5b6092ef51ef..f0efc7e970ef 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -5413,6 +5413,7 @@ xfs_bmap_shift_extents(
 	int				whichfork = XFS_DATA_FORK;
 	int				logflags;
 	xfs_filblks_t			blockcount = 0;
+	int				total_extents;
 
 	if (unlikely(XFS_TEST_ERROR(
 	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -5429,7 +5430,6 @@ xfs_bmap_shift_extents(
 	ASSERT(current_ext != NULL);
 
 	ifp = XFS_IFORK_PTR(ip, whichfork);
-
 	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
 		/* Read in all the extents */
 		error = xfs_iread_extents(tp, ip, whichfork);
@@ -5456,7 +5456,6 @@ xfs_bmap_shift_extents(
 
 	/* We are going to change core inode */
 	logflags = XFS_ILOG_CORE;
-
 	if (ifp->if_flags & XFS_IFBROOT) {
 		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
 		cur->bc_private.b.firstblock = *firstblock;
@@ -5467,8 +5466,14 @@ xfs_bmap_shift_extents(
 		logflags |= XFS_ILOG_DEXT;
 	}
 
-	while (nexts++ < num_exts &&
-	       *current_ext <  XFS_IFORK_NEXTENTS(ip, whichfork)) {
+	/*
+	 * There may be delalloc extents in the data fork before the range we
+	 * are collapsing out, so we cannot
+	 * use the count of real extents here. Instead we have to calculate it
+	 * from the incore fork.
+	 */
+	total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+	while (nexts++ < num_exts && *current_ext < total_extents) {
 
 		gotp = xfs_iext_get_ext(ifp, *current_ext);
 		xfs_bmbt_get_all(gotp, &got);
@@ -5556,10 +5561,11 @@ xfs_bmap_shift_extents(
 		}
 
 		(*current_ext)++;
+		total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
 	}
 
 	/* Check if we are done */
-	if (*current_ext ==  XFS_IFORK_NEXTENTS(ip, whichfork))
+	if (*current_ext == total_extents)
 		*done = 1;
 
 del_cursor:
@@ -5568,6 +5574,5 @@ del_cursor:
 			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
 
 	xfs_trans_log_inode(tp, ip, logflags);
-
 	return error;
 }
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 01f6a646caa1..296160b8e78c 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1418,6 +1418,8 @@ xfs_zero_file_space(
 	xfs_off_t		end_boundary;
 	int			error;
 
+	trace_xfs_zero_file_space(ip);
+
 	granularity = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
 
 	/*
@@ -1432,9 +1434,18 @@ xfs_zero_file_space(
 	ASSERT(end_boundary <= offset + len);
 
 	if (start_boundary < end_boundary - 1) {
-		/* punch out the page cache over the conversion range */
+		/*
+		 * punch out delayed allocation blocks and the page cache over
+		 * the conversion range
+		 */
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		error = xfs_bmap_punch_delalloc_range(ip,
+				XFS_B_TO_FSBT(mp, start_boundary),
+				XFS_B_TO_FSB(mp, end_boundary - start_boundary));
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		truncate_pagecache_range(VFS_I(ip), start_boundary,
 					 end_boundary - 1);
+
 		/* convert the blocks */
 		error = xfs_alloc_file_space(ip, start_boundary,
 					end_boundary - start_boundary - 1,
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 107f2fdfe41f..cb10a0aaab3a 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1372,21 +1372,29 @@ xfs_buf_iorequest(
 		xfs_buf_wait_unpin(bp);
 	xfs_buf_hold(bp);
 
-	/* Set the count to 1 initially, this will stop an I/O
+	/*
+	 * Set the count to 1 initially, this will stop an I/O
 	 * completion callout which happens before we have started
 	 * all the I/O from calling xfs_buf_ioend too early.
 	 */
 	atomic_set(&bp->b_io_remaining, 1);
 	_xfs_buf_ioapply(bp);
-	_xfs_buf_ioend(bp, 1);
+	/*
+	 * If _xfs_buf_ioapply failed, we'll get back here with
+	 * only the reference we took above.  _xfs_buf_ioend will
+	 * drop it to zero, so we'd better not queue it for later,
+	 * or we'll free it before it's done.
+	 */
+	_xfs_buf_ioend(bp, bp->b_error ? 0 : 1);
 
 	xfs_buf_rele(bp);
 }
 
 /*
  * Waits for I/O to complete on the buffer supplied.  It returns immediately if
- * no I/O is pending or there is already a pending error on the buffer.  It
- * returns the I/O error code, if any, or 0 if there was no error.
+ * no I/O is pending or there is already a pending error on the buffer, in which
+ * case nothing will ever complete.  It returns the I/O error code, if any, or
+ * 0 if there was no error.
  */
 int
 xfs_buf_iowait(
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 79e96ce98733..951a2321ee01 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -679,7 +679,7 @@ xfs_file_dio_aio_write(
 		goto out;
 
 	if (mapping->nrpages) {
-		ret = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+		ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
 						    pos, -1);
 		if (ret)
 			goto out;
@@ -841,7 +841,15 @@ xfs_file_fallocate(
 			goto out_unlock;
 		}
 
-		ASSERT(offset + len < i_size_read(inode));
+		/*
+		 * There is no need to overlap collapse range with EOF,
+		 * in which case it is effectively a truncate operation
+		 */
+		if (offset + len >= i_size_read(inode)) {
+			error = -EINVAL;
+			goto out_unlock;
+		}
+
 		new_size = i_size_read(inode) - len;
 
 		error = xfs_collapse_file_space(ip, offset, len);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 5e7a38fa6ee6..768087bedbac 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1334,7 +1334,8 @@ int
 xfs_create_tmpfile(
 	struct xfs_inode	*dp,
 	struct dentry		*dentry,
-	umode_t			mode)
+	umode_t			mode,
+	struct xfs_inode	**ipp)
 {
 	struct xfs_mount	*mp = dp->i_mount;
 	struct xfs_inode	*ip = NULL;
@@ -1402,7 +1403,6 @@ xfs_create_tmpfile(
 	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
 
 	ip->i_d.di_nlink--;
-	d_tmpfile(dentry, VFS_I(ip));
 	error = xfs_iunlink(tp, ip);
 	if (error)
 		goto out_trans_abort;
@@ -1415,6 +1415,7 @@ xfs_create_tmpfile(
 	xfs_qm_dqrele(gdqp);
 	xfs_qm_dqrele(pdqp);
 
+	*ipp = ip;
 	return 0;
 
  out_trans_abort:
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 396cc1fafd0d..f2fcde52b66d 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -334,7 +334,7 @@ int		xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
 int		xfs_create(struct xfs_inode *dp, struct xfs_name *name,
 			   umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp);
 int		xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry,
-			   umode_t mode);
+			   umode_t mode, struct xfs_inode **ipp);
 int		xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
 			   struct xfs_inode *ip);
 int		xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 89b07e43ca28..ef1ca010f417 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1053,11 +1053,25 @@ xfs_vn_tmpfile(
 	struct dentry	*dentry,
 	umode_t		mode)
 {
-	int		error;
+	int			error;
+	struct xfs_inode	*ip;
+	struct inode		*inode;
 
-	error = xfs_create_tmpfile(XFS_I(dir), dentry, mode);
+	error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip);
+	if (unlikely(error))
+		return -error;
 
-	return -error;
+	inode = VFS_I(ip);
+
+	error = xfs_init_security(inode, dir, &dentry->d_name);
+	if (unlikely(error)) {
+		iput(inode);
+		return -error;
+	}
+
+	d_tmpfile(dentry, inode);
+
+	return 0;
 }
 
 static const struct inode_operations xfs_inode_operations = {
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 8497a00e399d..08624dc67317 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1181,11 +1181,14 @@ xlog_iodone(xfs_buf_t *bp)
 	/* log I/O is always issued ASYNC */
 	ASSERT(XFS_BUF_ISASYNC(bp));
 	xlog_state_done_syncing(iclog, aborted);
+
 	/*
-	 * do not reference the buffer (bp) here as we could race
-	 * with it being freed after writing the unmount record to the
-	 * log.
+	 * drop the buffer lock now that we are done. Nothing references
+	 * the buffer after this, so an unmount waiting on this lock can now
+	 * tear it down safely. As such, it is unsafe to reference the buffer
+	 * (bp) after the unlock as we could race with it being freed.
 	 */
+	xfs_buf_unlock(bp);
 }
 
 /*
@@ -1368,8 +1371,16 @@ xlog_alloc_log(
 	bp = xfs_buf_alloc(mp->m_logdev_targp, 0, BTOBB(log->l_iclog_size), 0);
 	if (!bp)
 		goto out_free_log;
-	bp->b_iodone = xlog_iodone;
+
+	/*
+	 * The iclogbuf buffer locks are held over IO but we are not going to do
+	 * IO yet.  Hence unlock the buffer so that the log IO path can grab it
+	 * when appropriately.
+	 */
 	ASSERT(xfs_buf_islocked(bp));
+	xfs_buf_unlock(bp);
+
+	bp->b_iodone = xlog_iodone;
 	log->l_xbuf = bp;
 
 	spin_lock_init(&log->l_icloglock);
@@ -1398,6 +1409,9 @@ xlog_alloc_log(
 		if (!bp)
 			goto out_free_iclog;
 
+		ASSERT(xfs_buf_islocked(bp));
+		xfs_buf_unlock(bp);
+
 		bp->b_iodone = xlog_iodone;
 		iclog->ic_bp = bp;
 		iclog->ic_data = bp->b_addr;
@@ -1422,7 +1436,6 @@ xlog_alloc_log(
 		iclog->ic_callback_tail = &(iclog->ic_callback);
 		iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
 
-		ASSERT(xfs_buf_islocked(iclog->ic_bp));
 		init_waitqueue_head(&iclog->ic_force_wait);
 		init_waitqueue_head(&iclog->ic_write_wait);
 
@@ -1631,6 +1644,12 @@ xlog_cksum(
  * we transition the iclogs to IOERROR state *after* flushing all existing
  * iclogs to disk. This is because we don't want anymore new transactions to be
  * started or completed afterwards.
+ *
+ * We lock the iclogbufs here so that we can serialise against IO completion
+ * during unmount. We might be processing a shutdown triggered during unmount,
+ * and that can occur asynchronously to the unmount thread, and hence we need to
+ * ensure that completes before tearing down the iclogbufs. Hence we need to
+ * hold the buffer lock across the log IO to acheive that.
  */
 STATIC int
 xlog_bdstrat(
@@ -1638,6 +1657,7 @@ xlog_bdstrat(
 {
 	struct xlog_in_core	*iclog = bp->b_fspriv;
 
+	xfs_buf_lock(bp);
 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
 		xfs_buf_ioerror(bp, EIO);
 		xfs_buf_stale(bp);
@@ -1645,7 +1665,8 @@ xlog_bdstrat(
 		/*
 		 * It would seem logical to return EIO here, but we rely on
 		 * the log state machine to propagate I/O errors instead of
-		 * doing it here.
+		 * doing it here. Similarly, IO completion will unlock the
+		 * buffer, so we don't do it here.
 		 */
 		return 0;
 	}
@@ -1847,14 +1868,28 @@ xlog_dealloc_log(
 	xlog_cil_destroy(log);
 
 	/*
-	 * always need to ensure that the extra buffer does not point to memory
-	 * owned by another log buffer before we free it.
+	 * Cycle all the iclogbuf locks to make sure all log IO completion
+	 * is done before we tear down these buffers.
 	 */
+	iclog = log->l_iclog;
+	for (i = 0; i < log->l_iclog_bufs; i++) {
+		xfs_buf_lock(iclog->ic_bp);
+		xfs_buf_unlock(iclog->ic_bp);
+		iclog = iclog->ic_next;
+	}
+
+	/*
+	 * Always need to ensure that the extra buffer does not point to memory
+	 * owned by another log buffer before we free it. Also, cycle the lock
+	 * first to ensure we've completed IO on it.
+	 */
+	xfs_buf_lock(log->l_xbuf);
+	xfs_buf_unlock(log->l_xbuf);
 	xfs_buf_set_empty(log->l_xbuf, BTOBB(log->l_iclog_size));
 	xfs_buf_free(log->l_xbuf);
 
 	iclog = log->l_iclog;
-	for (i=0; i<log->l_iclog_bufs; i++) {
+	for (i = 0; i < log->l_iclog_bufs; i++) {
 		xfs_buf_free(iclog->ic_bp);
 		next_iclog = iclog->ic_next;
 		kmem_free(iclog);
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index a4ae41c179a8..65d8c793a25c 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -603,6 +603,7 @@ DEFINE_INODE_EVENT(xfs_readlink);
 DEFINE_INODE_EVENT(xfs_inactive_symlink);
 DEFINE_INODE_EVENT(xfs_alloc_file_space);
 DEFINE_INODE_EVENT(xfs_free_file_space);
+DEFINE_INODE_EVENT(xfs_zero_file_space);
 DEFINE_INODE_EVENT(xfs_collapse_file_space);
 DEFINE_INODE_EVENT(xfs_readdir);
 #ifdef CONFIG_XFS_POSIX_ACL
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 1ec08c198b66..a8015a7a55bb 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -693,24 +693,35 @@ static inline int pmd_numa(pmd_t pmd)
 #ifndef pte_mknonnuma
 static inline pte_t pte_mknonnuma(pte_t pte)
 {
-	pte = pte_clear_flags(pte, _PAGE_NUMA);
-	return pte_set_flags(pte, _PAGE_PRESENT|_PAGE_ACCESSED);
+	pteval_t val = pte_val(pte);
+
+	val &= ~_PAGE_NUMA;
+	val |= (_PAGE_PRESENT|_PAGE_ACCESSED);
+	return __pte(val);
 }
 #endif
 
 #ifndef pmd_mknonnuma
 static inline pmd_t pmd_mknonnuma(pmd_t pmd)
 {
-	pmd = pmd_clear_flags(pmd, _PAGE_NUMA);
-	return pmd_set_flags(pmd, _PAGE_PRESENT|_PAGE_ACCESSED);
+	pmdval_t val = pmd_val(pmd);
+
+	val &= ~_PAGE_NUMA;
+	val |= (_PAGE_PRESENT|_PAGE_ACCESSED);
+
+	return __pmd(val);
 }
 #endif
 
 #ifndef pte_mknuma
 static inline pte_t pte_mknuma(pte_t pte)
 {
-	pte = pte_set_flags(pte, _PAGE_NUMA);
-	return pte_clear_flags(pte, _PAGE_PRESENT);
+	pteval_t val = pte_val(pte);
+
+	val &= ~_PAGE_PRESENT;
+	val |= _PAGE_NUMA;
+
+	return __pte(val);
 }
 #endif
 
@@ -729,8 +740,12 @@ static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
 #ifndef pmd_mknuma
 static inline pmd_t pmd_mknuma(pmd_t pmd)
 {
-	pmd = pmd_set_flags(pmd, _PAGE_NUMA);
-	return pmd_clear_flags(pmd, _PAGE_PRESENT);
+	pmdval_t val = pmd_val(pmd);
+
+	val &= ~_PAGE_PRESENT;
+	val |= _PAGE_NUMA;
+
+	return __pmd(val);
 }
 #endif
 
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
index d401e5463fb0..0c938a4354f6 100644
--- a/include/asm-generic/syscall.h
+++ b/include/asm-generic/syscall.h
@@ -147,7 +147,7 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
  *
  * Returns the AUDIT_ARCH_* based on the system call convention in use.
  *
- * It's only valid to call this when @task is stopped on entry to a system
+ * It's only valid to call this when current is stopped on entry to a system
  * call, due to %TIF_SYSCALL_TRACE, %TIF_SYSCALL_AUDIT, or %TIF_SECCOMP.
  *
  * Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index a7c2a862b4f4..f3c9a63e3707 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1310,7 +1310,7 @@ extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
 /* Cache management (drm_cache.c) */
 void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
 void drm_clflush_sg(struct sg_table *st);
-void drm_clflush_virt_range(char *addr, unsigned long length);
+void drm_clflush_virt_range(void *addr, unsigned long length);
 
 				/* Locking IOCTL support (drm_lock.h) */
 extern int drm_lock(struct drm_device *dev, void *data,
diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h
index 6548a5fbcf4a..1118f7a4bca6 100644
--- a/include/dt-bindings/clock/r8a7790-clock.h
+++ b/include/dt-bindings/clock/r8a7790-clock.h
@@ -33,8 +33,8 @@
 #define R8A7790_CLK_TMU0		25
 #define R8A7790_CLK_VSP1_DU1		27
 #define R8A7790_CLK_VSP1_DU0		28
-#define R8A7790_CLK_VSP1_RT		30
-#define R8A7790_CLK_VSP1_SY		31
+#define R8A7790_CLK_VSP1_R		30
+#define R8A7790_CLK_VSP1_S		31
 
 /* MSTP2 */
 #define R8A7790_CLK_SCIFA2		2
@@ -50,6 +50,7 @@
 #define R8A7790_CLK_SYS_DMAC0		19
 
 /* MSTP3 */
+#define R8A7790_CLK_IIC2		0
 #define R8A7790_CLK_TPU0		4
 #define R8A7790_CLK_MMCIF1		5
 #define R8A7790_CLK_SDHI3		11
@@ -57,6 +58,8 @@
 #define R8A7790_CLK_SDHI1		13
 #define R8A7790_CLK_SDHI0		14
 #define R8A7790_CLK_MMCIF0		15
+#define R8A7790_CLK_IIC0		18
+#define R8A7790_CLK_IIC1		23
 #define R8A7790_CLK_SSUSB		28
 #define R8A7790_CLK_CMT1		29
 #define R8A7790_CLK_USBDMAC0		30
diff --git a/include/dt-bindings/clock/r8a7791-clock.h b/include/dt-bindings/clock/r8a7791-clock.h
index 30f82f286e29..29b0f3355ffb 100644
--- a/include/dt-bindings/clock/r8a7791-clock.h
+++ b/include/dt-bindings/clock/r8a7791-clock.h
@@ -32,7 +32,7 @@
 #define R8A7791_CLK_TMU0		25
 #define R8A7791_CLK_VSP1_DU1		27
 #define R8A7791_CLK_VSP1_DU0		28
-#define R8A7791_CLK_VSP1_SY		31
+#define R8A7791_CLK_VSP1_S		31
 
 /* MSTP2 */
 #define R8A7791_CLK_SCIFA2		2
@@ -51,6 +51,8 @@
 #define R8A7791_CLK_SDHI1		12
 #define R8A7791_CLK_SDHI0		14
 #define R8A7791_CLK_MMCIF0		15
+#define R8A7791_CLK_IIC0		18
+#define R8A7791_CLK_IIC1		23
 #define R8A7791_CLK_SSUSB		28
 #define R8A7791_CLK_CMT1		29
 #define R8A7791_CLK_USBDMAC0		30
@@ -61,6 +63,7 @@
 #define R8A7791_CLK_PWM			23
 
 /* MSTP7 */
+#define R8A7791_CLK_EHCI		3
 #define R8A7791_CLK_HSUSB		4
 #define R8A7791_CLK_HSCIF2		13
 #define R8A7791_CLK_SCIF5		14
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 0120451545d8..ab469d525894 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -18,7 +18,9 @@ struct blk_mq_hw_ctx {
 	} ____cacheline_aligned_in_smp;
 
 	unsigned long		state;		/* BLK_MQ_S_* flags */
-	struct delayed_work	delayed_work;
+	struct delayed_work	run_work;
+	struct delayed_work	delay_work;
+	cpumask_var_t		cpumask;
 
 	unsigned long		flags;		/* BLK_MQ_F_* flags */
 
@@ -32,8 +34,6 @@ struct blk_mq_hw_ctx {
 	unsigned int 		nr_ctx_map;
 	unsigned long		*ctx_map;
 
-	struct request		**rqs;
-	struct list_head	page_list;
 	struct blk_mq_tags	*tags;
 
 	unsigned long		queued;
@@ -41,7 +41,6 @@ struct blk_mq_hw_ctx {
 #define BLK_MQ_MAX_DISPATCH_ORDER	10
 	unsigned long		dispatched[BLK_MQ_MAX_DISPATCH_ORDER];
 
-	unsigned int		queue_depth;
 	unsigned int		numa_node;
 	unsigned int		cmd_size;	/* per-request extra data */
 
@@ -49,7 +48,7 @@ struct blk_mq_hw_ctx {
 	struct kobject		kobj;
 };
 
-struct blk_mq_reg {
+struct blk_mq_tag_set {
 	struct blk_mq_ops	*ops;
 	unsigned int		nr_hw_queues;
 	unsigned int		queue_depth;
@@ -58,14 +57,22 @@ struct blk_mq_reg {
 	int			numa_node;
 	unsigned int		timeout;
 	unsigned int		flags;		/* BLK_MQ_F_* */
+	void			*driver_data;
+
+	struct blk_mq_tags	**tags;
 };
 
 typedef int (queue_rq_fn)(struct blk_mq_hw_ctx *, struct request *);
 typedef struct blk_mq_hw_ctx *(map_queue_fn)(struct request_queue *, const int);
-typedef struct blk_mq_hw_ctx *(alloc_hctx_fn)(struct blk_mq_reg *,unsigned int);
+typedef struct blk_mq_hw_ctx *(alloc_hctx_fn)(struct blk_mq_tag_set *,
+		unsigned int);
 typedef void (free_hctx_fn)(struct blk_mq_hw_ctx *, unsigned int);
 typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int);
 typedef void (exit_hctx_fn)(struct blk_mq_hw_ctx *, unsigned int);
+typedef int (init_request_fn)(void *, struct request *, unsigned int,
+		unsigned int, unsigned int);
+typedef void (exit_request_fn)(void *, struct request *, unsigned int,
+		unsigned int);
 
 struct blk_mq_ops {
 	/*
@@ -98,6 +105,14 @@ struct blk_mq_ops {
 	 */
 	init_hctx_fn		*init_hctx;
 	exit_hctx_fn		*exit_hctx;
+
+	/*
+	 * Called for every command allocated by the block layer to allow
+	 * the driver to set up driver specific data.
+	 * Ditto for exit/teardown.
+	 */
+	init_request_fn		*init_request;
+	exit_request_fn		*exit_request;
 };
 
 enum {
@@ -114,11 +129,12 @@ enum {
 	BLK_MQ_MAX_DEPTH	= 2048,
 };
 
-struct request_queue *blk_mq_init_queue(struct blk_mq_reg *, void *);
+struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *);
 int blk_mq_register_disk(struct gendisk *);
 void blk_mq_unregister_disk(struct gendisk *);
-int blk_mq_init_commands(struct request_queue *, int (*init)(void *data, struct blk_mq_hw_ctx *, struct request *, unsigned int), void *data);
-void blk_mq_free_commands(struct request_queue *, void (*free)(void *data, struct blk_mq_hw_ctx *, struct request *, unsigned int), void *data);
+
+int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set);
+void blk_mq_free_tag_set(struct blk_mq_tag_set *set);
 
 void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule);
 
@@ -128,26 +144,25 @@ void blk_mq_free_request(struct request *rq);
 bool blk_mq_can_queue(struct blk_mq_hw_ctx *);
 struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp);
 struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw, gfp_t gfp);
-struct request *blk_mq_rq_from_tag(struct request_queue *q, unsigned int tag);
+struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag);
 
 struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index);
-struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_reg *, unsigned int);
+struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *, unsigned int);
 void blk_mq_free_single_hw_queue(struct blk_mq_hw_ctx *, unsigned int);
 
-bool blk_mq_end_io_partial(struct request *rq, int error,
-		unsigned int nr_bytes);
-static inline void blk_mq_end_io(struct request *rq, int error)
-{
-	bool done = !blk_mq_end_io_partial(rq, error, blk_rq_bytes(rq));
-	BUG_ON(!done);
-}
+void blk_mq_end_io(struct request *rq, int error);
+void __blk_mq_end_io(struct request *rq, int error);
+
+void blk_mq_requeue_request(struct request *rq);
 
 void blk_mq_complete_request(struct request *rq);
 
 void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx);
 void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx);
 void blk_mq_stop_hw_queues(struct request_queue *q);
-void blk_mq_start_stopped_hw_queues(struct request_queue *q);
+void blk_mq_start_hw_queues(struct request_queue *q);
+void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async);
+void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs);
 
 /*
  * Driver command data is immediately after the request. So subtract request
@@ -162,12 +177,6 @@ static inline void *blk_mq_rq_to_pdu(struct request *rq)
 	return (void *) rq + sizeof(*rq);
 }
 
-static inline struct request *blk_mq_tag_to_rq(struct blk_mq_hw_ctx *hctx,
-					       unsigned int tag)
-{
-	return hctx->rqs[tag];
-}
-
 #define queue_for_each_hw_ctx(q, hctx, i)				\
 	for ((i) = 0; (i) < (q)->nr_hw_queues &&			\
 	     ({ hctx = (q)->queue_hw_ctx[i]; 1; }); (i)++)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 0d84981ee03f..74ee55fefcf0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -98,7 +98,7 @@ struct request {
 	struct list_head queuelist;
 	union {
 		struct call_single_data csd;
-		struct work_struct mq_flush_work;
+		struct work_struct requeue_work;
 		unsigned long fifo_time;
 	};
 
@@ -178,7 +178,6 @@ struct request {
 	unsigned short ioprio;
 
 	void *special;		/* opaque pointer available for LLD use */
-	char *buffer;		/* kaddr of the current segment if available */
 
 	int tag;
 	int errors;
@@ -613,6 +612,15 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
 
 #define rq_data_dir(rq)		(((rq)->cmd_flags & 1) != 0)
 
+/*
+ * Driver can handle struct request, if it either has an old style
+ * request_fn defined, or is blk-mq based.
+ */
+static inline bool queue_is_rq_based(struct request_queue *q)
+{
+	return q->request_fn || q->mq_ops;
+}
+
 static inline unsigned int blk_queue_cluster(struct request_queue *q)
 {
 	return q->limits.cluster;
@@ -937,6 +945,7 @@ extern struct request *blk_fetch_request(struct request_queue *q);
  */
 extern bool blk_update_request(struct request *rq, int error,
 			       unsigned int nr_bytes);
+extern void blk_finish_request(struct request *rq, int error);
 extern bool blk_end_request(struct request *rq, int error,
 			    unsigned int nr_bytes);
 extern void blk_end_request_all(struct request *rq, int error);
@@ -1102,7 +1111,8 @@ static inline bool blk_needs_flush_plug(struct task_struct *tsk)
 /*
  * tag stuff
  */
-#define blk_rq_tagged(rq)		((rq)->cmd_flags & REQ_QUEUED)
+#define blk_rq_tagged(rq) \
+	((rq)->mq_ctx || ((rq)->cmd_flags & REQ_QUEUED))
 extern int blk_queue_start_tag(struct request_queue *, struct request *);
 extern struct request *blk_queue_find_tag(struct request_queue *, int);
 extern void blk_queue_end_tag(struct request_queue *, struct request *);
@@ -1370,8 +1380,9 @@ static inline void put_dev_sector(Sector p)
 }
 
 struct work_struct;
-int kblockd_schedule_work(struct request_queue *q, struct work_struct *work);
-int kblockd_schedule_delayed_work(struct request_queue *q, struct delayed_work *dwork, unsigned long delay);
+int kblockd_schedule_work(struct work_struct *work);
+int kblockd_schedule_delayed_work(struct delayed_work *dwork, unsigned long delay);
+int kblockd_schedule_delayed_work_on(int cpu, struct delayed_work *dwork, unsigned long delay);
 
 #ifdef CONFIG_BLK_CGROUP
 /*
diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
index 5529c5239421..ba147a1727e6 100644
--- a/include/linux/compiler-intel.h
+++ b/include/linux/compiler-intel.h
@@ -13,12 +13,9 @@
 /* Intel ECC compiler doesn't support gcc specific asm stmts.
  * It uses intrinsics to do the equivalent things.
  */
-#undef barrier
 #undef RELOC_HIDE
 #undef OPTIMIZER_HIDE_VAR
 
-#define barrier() __memory_barrier()
-
 #define RELOC_HIDE(ptr, off)					\
   ({ unsigned long __ptr;					\
      __ptr = (unsigned long) (ptr);				\
diff --git a/include/linux/crc64_ecma.h b/include/linux/crc64_ecma.h
new file mode 100644
index 000000000000..bba7a4d692b3
--- /dev/null
+++ b/include/linux/crc64_ecma.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CRC64_ECMA_H_
+#define __CRC64_ECMA_H_
+
+#include <linux/types.h>
+
+
+#define CRC64_DEFAULT_INITVAL           0xFFFFFFFFFFFFFFFFULL
+
+
+/*
+ * crc64_ecma_seed - Initializes the CRC64 ECMA seed.
+ */
+u64 crc64_ecma_seed(void);
+
+/*
+ * crc64_ecma - Computes the 64 bit ECMA CRC.
+ *
+ * @pdata:	pointer to the data to compute checksum for.
+ * @nbytes:	number of bytes in data buffer.
+ * @seed:	CRC seed.
+ */
+u64 crc64_ecma(u8 const *pdata, u32 nbytes, u64 seed);
+
+#endif /* __CRC64_ECMA_H_ */
diff --git a/include/linux/dell-led.h b/include/linux/dell-led.h
new file mode 100644
index 000000000000..7009b8bec77b
--- /dev/null
+++ b/include/linux/dell-led.h
@@ -0,0 +1,10 @@
+#ifndef __DELL_LED_H__
+#define __DELL_LED_H__
+
+enum {
+	DELL_LED_MICMUTE,
+};
+
+int dell_app_wmi_led_set(int whichled, int on);
+
+#endif
diff --git a/include/linux/device.h b/include/linux/device.h
index 233bbbeb768d..d1d1c055b48e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -566,12 +566,6 @@ extern int __must_check device_create_bin_file(struct device *dev,
 					const struct bin_attribute *attr);
 extern void device_remove_bin_file(struct device *dev,
 				   const struct bin_attribute *attr);
-extern int device_schedule_callback_owner(struct device *dev,
-		void (*func)(struct device *dev), struct module *owner);
-
-/* This is a macro to avoid include problems with THIS_MODULE */
-#define device_schedule_callback(dev, func)			\
-	device_schedule_callback_owner(dev, func, THIS_MODULE)
 
 /* device resource management */
 typedef void (*dr_release_t)(struct device *dev, void *res);
@@ -932,10 +926,7 @@ extern int device_online(struct device *dev);
 extern struct device *__root_device_register(const char *name,
 					     struct module *owner);
 
-/*
- * This is a macro to avoid include problems with THIS_MODULE,
- * just as per what is done for device_schedule_callback() above.
- */
+/* This is a macro to avoid include problems with THIS_MODULE */
 #define root_device_register(name) \
 	__root_device_register(name, THIS_MODULE)
 
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 8300fb87b84a..72cb0ddb9678 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -429,6 +429,7 @@ typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
 typedef void (*dma_async_tx_callback)(void *dma_async_param);
 
 struct dmaengine_unmap_data {
+	u8 map_cnt;
 	u8 to_cnt;
 	u8 from_cnt;
 	u8 bidi_cnt;
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 262dcbb75ffe..024fd03e5d18 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -220,7 +220,6 @@ enum {
 	BPF_S_ANC_RXHASH,
 	BPF_S_ANC_CPU,
 	BPF_S_ANC_ALU_XOR_X,
-	BPF_S_ANC_SECCOMP_LD_W,
 	BPF_S_ANC_VLAN_TAG,
 	BPF_S_ANC_VLAN_TAG_PRESENT,
 	BPF_S_ANC_PAY_OFFSET,
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 39b81dc7d01a..d382db71e300 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -31,7 +31,6 @@ struct vm_area_struct;
 #define ___GFP_HARDWALL		0x20000u
 #define ___GFP_THISNODE		0x40000u
 #define ___GFP_RECLAIMABLE	0x80000u
-#define ___GFP_KMEMCG		0x100000u
 #define ___GFP_NOTRACK		0x200000u
 #define ___GFP_NO_KSWAPD	0x400000u
 #define ___GFP_OTHER_NODE	0x800000u
@@ -91,7 +90,6 @@ struct vm_area_struct;
 
 #define __GFP_NO_KSWAPD	((__force gfp_t)___GFP_NO_KSWAPD)
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
-#define __GFP_KMEMCG	((__force gfp_t)___GFP_KMEMCG) /* Allocation comes from a memcg-accounted resource */
 #define __GFP_WRITE	((__force gfp_t)___GFP_WRITE)	/* Allocator intends to dirty page */
 
 /*
@@ -353,6 +351,10 @@ extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
 #define alloc_page_vma_node(gfp_mask, vma, addr, node)		\
 	alloc_pages_vma(gfp_mask, 0, vma, addr, node)
 
+extern struct page *alloc_kmem_pages(gfp_t gfp_mask, unsigned int order);
+extern struct page *alloc_kmem_pages_node(int nid, gfp_t gfp_mask,
+					  unsigned int order);
+
 extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
 extern unsigned long get_zeroed_page(gfp_t gfp_mask);
 
@@ -372,8 +374,8 @@ extern void free_pages(unsigned long addr, unsigned int order);
 extern void free_hot_cold_page(struct page *page, int cold);
 extern void free_hot_cold_page_list(struct list_head *list, int cold);
 
-extern void __free_memcg_kmem_pages(struct page *page, unsigned int order);
-extern void free_memcg_kmem_pages(unsigned long addr, unsigned int order);
+extern void __free_kmem_pages(struct page *page, unsigned int order);
+extern void free_kmem_pages(unsigned long addr, unsigned int order);
 
 #define __free_page(page) __free_pages((page), 0)
 #define free_page(addr) free_pages((addr), 0)
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 1827b43966d9..573e4f3243d0 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -51,7 +51,10 @@ struct seq_file;
  *      format specifier for an unsigned int.  It is substituted by the actual
  *      number of the gpio.
  * @can_sleep: flag must be set iff get()/set() methods sleep, as they
- *	must while accessing GPIO expander chips over I2C or SPI
+ *	must while accessing GPIO expander chips over I2C or SPI. This
+ *	implies that if the chip supports IRQs, these IRQs need to be threaded
+ *	as the chip access may sleep when e.g. reading out the IRQ status
+ *	registers.
  * @exported: flags if the gpiochip is exported for use from sysfs. Private.
  *
  * A gpio_chip can help platforms abstract various sources of GPIOs so
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 720e3a10608c..54f855b2c902 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -570,6 +570,8 @@ struct hid_descriptor {
 	.bus = BUS_USB, .vendor = (ven), .product = (prod)
 #define HID_BLUETOOTH_DEVICE(ven, prod)					\
 	.bus = BUS_BLUETOOTH, .vendor = (ven), .product = (prod)
+#define HID_I2C_DEVICE(ven, prod)				\
+	.bus = BUS_I2C, .vendor = (ven), .product = (prod)
 
 #define HID_REPORT_ID(rep) \
 	.report_type = (rep)
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 5b337cf8fb86..1ae16673c672 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -41,8 +41,6 @@ extern int hugetlb_max_hstate __read_mostly;
 struct hugepage_subpool *hugepage_new_subpool(long nr_blocks);
 void hugepage_put_subpool(struct hugepage_subpool *spool);
 
-int PageHuge(struct page *page);
-
 void reset_vma_resv_huge_pages(struct vm_area_struct *vma);
 int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *);
 int hugetlb_overcommit_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *);
@@ -109,11 +107,6 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
 
 #else /* !CONFIG_HUGETLB_PAGE */
 
-static inline int PageHuge(struct page *page)
-{
-	return 0;
-}
-
 static inline void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
 {
 }
diff --git a/include/linux/hugetlb_inline.h b/include/linux/hugetlb_inline.h
index 2bb681fbeb35..4d60c82e9fda 100644
--- a/include/linux/hugetlb_inline.h
+++ b/include/linux/hugetlb_inline.h
@@ -10,6 +10,8 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
 	return !!(vma->vm_flags & VM_HUGETLB);
 }
 
+int PageHuge(struct page *page);
+
 #else
 
 static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
@@ -17,6 +19,11 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
 	return 0;
 }
 
+static inline int PageHuge(struct page *page)
+{
+	return 0;
+}
+
 #endif
 
 #endif
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index ab7359fde987..2d7b4f139c32 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -147,15 +147,17 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
  * 0 . 13 (Windows Server 2008)
  * 1 . 1  (Windows 7)
  * 2 . 4  (Windows 8)
+ * 3 . 0  (Windows 8 R2)
  */
 
 #define VERSION_WS2008  ((0 << 16) | (13))
 #define VERSION_WIN7    ((1 << 16) | (1))
 #define VERSION_WIN8    ((2 << 16) | (4))
+#define VERSION_WIN8_1    ((3 << 16) | (0))
 
 #define VERSION_INVAL -1
 
-#define VERSION_CURRENT VERSION_WIN8
+#define VERSION_CURRENT VERSION_WIN8_1
 
 /* Make maximum size of pipe payload of 16K */
 #define MAX_PIPE_DATA_PAYLOAD		(sizeof(u8) * 16384)
diff --git a/include/linux/input.h b/include/linux/input.h
index 82ce323b9986..6453b22372ac 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -79,6 +79,7 @@ struct input_value {
  * @led: reflects current state of device's LEDs
  * @snd: reflects current state of sound effects
  * @sw: reflects current state of device's switches
+ * @leds: leds objects for the device's LEDs
  * @open: this method is called when the very first user calls
  *	input_open_device(). The driver must prepare the device
  *	to start generating events (start polling thread,
@@ -164,6 +165,8 @@ struct input_dev {
 	unsigned long snd[BITS_TO_LONGS(SND_CNT)];
 	unsigned long sw[BITS_TO_LONGS(SW_CNT)];
 
+	struct led_classdev *leds;
+
 	int (*open)(struct input_dev *dev);
 	void (*close)(struct input_dev *dev);
 	int (*flush)(struct input_dev *dev, struct file *file);
@@ -531,4 +534,22 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
 int input_ff_create_memless(struct input_dev *dev, void *data,
 		int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
 
+#ifdef CONFIG_INPUT_LEDS
+
+int input_led_connect(struct input_dev *dev);
+void input_led_disconnect(struct input_dev *dev);
+
+#else
+
+static inline int input_led_connect(struct input_dev *dev)
+{
+	return 0;
+}
+
+static inline void input_led_disconnect(struct input_dev *dev)
+{
+}
+
+#endif
+
 #endif
diff --git a/include/linux/key.h b/include/linux/key.h
index 80d677483e31..cd0abb8c9c33 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -309,6 +309,17 @@ static inline key_serial_t key_serial(const struct key *key)
 
 extern void key_set_timeout(struct key *, unsigned);
 
+/*
+ * The permissions required on a key that we're looking up.
+ */
+#define	KEY_NEED_VIEW	0x01	/* Require permission to view attributes */
+#define	KEY_NEED_READ	0x02	/* Require permission to read content */
+#define	KEY_NEED_WRITE	0x04	/* Require permission to update / modify */
+#define	KEY_NEED_SEARCH	0x08	/* Require permission to search (keyring) or find (key) */
+#define	KEY_NEED_LINK	0x10	/* Require permission to link */
+#define	KEY_NEED_SETATTR 0x20	/* Require permission to change attributes */
+#define	KEY_NEED_ALL	0x3f	/* All the above permissions */
+
 /**
  * key_is_instantiated - Determine if a key has been positively instantiated
  * @key: The key to check.
diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h
index 7c9fe3c2be73..66c30a763b10 100644
--- a/include/linux/mdio-gpio.h
+++ b/include/linux/mdio-gpio.h
@@ -17,6 +17,11 @@ struct mdio_gpio_platform_data {
 	/* GPIO numbers for bus pins */
 	unsigned int mdc;
 	unsigned int mdio;
+	unsigned int mdo;
+
+	bool mdc_active_low;
+	bool mdio_active_low;
+	bool mdo_active_low;
 
 	unsigned int phy_mask;
 	int irqs[PHY_MAX_ADDR];
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 8a20a51ed42d..73dc382e72d8 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 
 #define INIT_MEMBLOCK_REGIONS	128
+#define INIT_PHYSMEM_REGIONS	4
 
 /* Definition of memblock flags. */
 #define MEMBLOCK_HOTPLUG	0x1	/* hotpluggable region */
@@ -43,6 +44,9 @@ struct memblock {
 	phys_addr_t current_limit;
 	struct memblock_type memory;
 	struct memblock_type reserved;
+#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
+	struct memblock_type physmem;
+#endif
 };
 
 extern struct memblock memblock;
@@ -71,6 +75,63 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size);
 void memblock_trim_memory(phys_addr_t align);
 int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
+
+/* Low level functions */
+int memblock_add_range(struct memblock_type *type,
+		       phys_addr_t base, phys_addr_t size,
+		       int nid, unsigned long flags);
+
+int memblock_remove_range(struct memblock_type *type,
+			  phys_addr_t base,
+			  phys_addr_t size);
+
+void __next_mem_range(u64 *idx, int nid, struct memblock_type *type_a,
+		      struct memblock_type *type_b, phys_addr_t *out_start,
+		      phys_addr_t *out_end, int *out_nid);
+
+void __next_mem_range_rev(u64 *idx, int nid, struct memblock_type *type_a,
+			  struct memblock_type *type_b, phys_addr_t *out_start,
+			  phys_addr_t *out_end, int *out_nid);
+
+/**
+ * for_each_mem_range - iterate through memblock areas from type_a and not
+ * included in type_b. Or just type_a if type_b is NULL.
+ * @i: u64 used as loop variable
+ * @type_a: ptr to memblock_type to iterate
+ * @type_b: ptr to memblock_type which excludes from the iteration
+ * @nid: node selector, %NUMA_NO_NODE for all nodes
+ * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
+ * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
+ * @p_nid: ptr to int for nid of the range, can be %NULL
+ */
+#define for_each_mem_range(i, type_a, type_b, nid,			\
+			   p_start, p_end, p_nid)			\
+	for (i = 0, __next_mem_range(&i, nid, type_a, type_b,		\
+				     p_start, p_end, p_nid);		\
+	     i != (u64)ULLONG_MAX;					\
+	     __next_mem_range(&i, nid, type_a, type_b,			\
+			      p_start, p_end, p_nid))
+
+/**
+ * for_each_mem_range_rev - reverse iterate through memblock areas from
+ * type_a and not included in type_b. Or just type_a if type_b is NULL.
+ * @i: u64 used as loop variable
+ * @type_a: ptr to memblock_type to iterate
+ * @type_b: ptr to memblock_type which excludes from the iteration
+ * @nid: node selector, %NUMA_NO_NODE for all nodes
+ * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
+ * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
+ * @p_nid: ptr to int for nid of the range, can be %NULL
+ */
+#define for_each_mem_range_rev(i, type_a, type_b, nid,			\
+			       p_start, p_end, p_nid)			\
+	for (i = (u64)ULLONG_MAX,					\
+		     __next_mem_range_rev(&i, nid, type_a, type_b,	\
+					 p_start, p_end, p_nid);	\
+	     i != (u64)ULLONG_MAX;					\
+	     __next_mem_range_rev(&i, nid, type_a, type_b,		\
+				  p_start, p_end, p_nid))
+
 #ifdef CONFIG_MOVABLE_NODE
 static inline bool memblock_is_hotpluggable(struct memblock_region *m)
 {
@@ -113,9 +174,6 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
 	     i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))
 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
 
-void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start,
-			   phys_addr_t *out_end, int *out_nid);
-
 /**
  * for_each_free_mem_range - iterate through free memblock areas
  * @i: u64 used as loop variable
@@ -128,13 +186,8 @@ void __next_free_mem_range(u64 *idx, int nid, phys_addr_t *out_start,
  * soon as memblock is initialized.
  */
 #define for_each_free_mem_range(i, nid, p_start, p_end, p_nid)		\
-	for (i = 0,							\
-	     __next_free_mem_range(&i, nid, p_start, p_end, p_nid);	\
-	     i != (u64)ULLONG_MAX;					\
-	     __next_free_mem_range(&i, nid, p_start, p_end, p_nid))
-
-void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start,
-			       phys_addr_t *out_end, int *out_nid);
+	for_each_mem_range(i, &memblock.memory, &memblock.reserved,	\
+			   nid, p_start, p_end, p_nid)
 
 /**
  * for_each_free_mem_range_reverse - rev-iterate through free memblock areas
@@ -148,10 +201,8 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start,
  * order.  Available as soon as memblock is initialized.
  */
 #define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid)	\
-	for (i = (u64)ULLONG_MAX,					\
-	     __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid);	\
-	     i != (u64)ULLONG_MAX;					\
-	     __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid))
+	for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved,	\
+			       nid, p_start, p_end, p_nid)
 
 static inline void memblock_set_region_flags(struct memblock_region *r,
 					     unsigned long flags)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index b569b8be5c5a..5155d09e749d 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -506,6 +506,9 @@ void memcg_update_array_size(int num_groups);
 struct kmem_cache *
 __memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp);
 
+int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size);
+void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size);
+
 void mem_cgroup_destroy_cache(struct kmem_cache *cachep);
 int __kmem_cache_destroy_memcg_children(struct kmem_cache *s);
 
@@ -534,7 +537,7 @@ memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **memcg, int order)
 	 * res_counter_charge_nofail, but we hope those allocations are rare,
 	 * and won't be worth the trouble.
 	 */
-	if (!(gfp & __GFP_KMEMCG) || (gfp & __GFP_NOFAIL))
+	if (gfp & __GFP_NOFAIL)
 		return true;
 	if (in_interrupt() || (!current->mm) || (current->flags & PF_KTHREAD))
 		return true;
@@ -583,17 +586,7 @@ memcg_kmem_commit_charge(struct page *page, struct mem_cgroup *memcg, int order)
  * @cachep: the original global kmem cache
  * @gfp: allocation flags.
  *
- * This function assumes that the task allocating, which determines the memcg
- * in the page allocator, belongs to the same cgroup throughout the whole
- * process.  Misacounting can happen if the task calls memcg_kmem_get_cache()
- * while belonging to a cgroup, and later on changes. This is considered
- * acceptable, and should only happen upon task migration.
- *
- * Before the cache is created by the memcg core, there is also a possible
- * imbalance: the task belongs to a memcg, but the cache being allocated from
- * is the global cache, since the child cache is not yet guaranteed to be
- * ready. This case is also fine, since in this case the GFP_KMEMCG will not be
- * passed and the page allocator will not attempt any cgroup accounting.
+ * All memory allocated from a per-memcg cache is charged to the owner memcg.
  */
 static __always_inline struct kmem_cache *
 memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp)
diff --git a/include/linux/mfd/samsung/s2mps14.h b/include/linux/mfd/samsung/s2mps14.h
index 4b449b8ac548..900cd7a04314 100644
--- a/include/linux/mfd/samsung/s2mps14.h
+++ b/include/linux/mfd/samsung/s2mps14.h
@@ -148,6 +148,8 @@ enum s2mps14_regulators {
 #define S2MPS14_ENABLE_SHIFT		6
 /* On/Off controlled by PWREN */
 #define S2MPS14_ENABLE_SUSPEND		(0x01 << S2MPS14_ENABLE_SHIFT)
+/* On/Off controlled by LDO10EN or EMMCEN */
+#define S2MPS14_ENABLE_EXT_CONTROL	(0x00 << S2MPS14_ENABLE_SHIFT)
 #define S2MPS14_LDO_N_VOLTAGES		(S2MPS14_LDO_VSEL_MASK + 1)
 #define S2MPS14_BUCK_N_VOLTAGES		(S2MPS14_BUCK_VSEL_MASK + 1)
 
diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h
index 6b8e1ff4672b..e6088c2e2092 100644
--- a/include/linux/mfd/tc3589x.h
+++ b/include/linux/mfd/tc3589x.h
@@ -111,7 +111,6 @@ enum tx3589x_block {
 #define TC3589x_INT_PORIRQ	7
 
 #define TC3589x_NR_INTERNAL_IRQS	8
-#define TC3589x_INT_GPIO(x)	(TC3589x_NR_INTERNAL_IRQS + (x))
 
 struct tc3589x {
 	struct mutex lock;
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 407bdb67fd4f..3406cfb1267a 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -179,6 +179,7 @@ enum {
 	MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR	= 1LL <<  9,
 	MLX5_DEV_CAP_FLAG_APM		= 1LL << 17,
 	MLX5_DEV_CAP_FLAG_ATOMIC	= 1LL << 18,
+	MLX5_DEV_CAP_FLAG_BLOCK_MCAST	= 1LL << 23,
 	MLX5_DEV_CAP_FLAG_ON_DMND_PG	= 1LL << 24,
 	MLX5_DEV_CAP_FLAG_CQ_MODER	= 1LL << 29,
 	MLX5_DEV_CAP_FLAG_RESIZE_CQ	= 1LL << 30,
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h
index f829ad80ff28..9709b30e2d69 100644
--- a/include/linux/mlx5/qp.h
+++ b/include/linux/mlx5/qp.h
@@ -146,6 +146,7 @@ enum {
 
 enum {
 	MLX5_QP_LAT_SENSITIVE	= 1 << 28,
+	MLX5_QP_BLOCK_MCAST	= 1 << 30,
 	MLX5_QP_ENABLE_SIG	= 1 << 31,
 };
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bf9811e1321a..9a3744d98b00 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1096,10 +1096,18 @@ void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
  * @pte_entry: if set, called for each non-empty PTE (4th-level) entry
  * @pte_hole: if set, called for each hole at all levels
  * @hugetlb_entry: if set, called for each hugetlb entry
- *		   *Caution*: The caller must hold mmap_sem() if @hugetlb_entry
- * 			      is used.
+ * @test_walk: caller specific callback function to determine whether
+ *             we walk over the current vma or not. A positive returned
+ *             value means "do page table walk over the current vma,"
+ *             and a negative one means "abort current page table walk
+ *             right now." 0 means "skip the current vma."
+ * @mm:        mm_struct representing the target process of page table walk
+ * @vma:       vma currently walked
+ * @skip:      internal control flag which is set when we skip the lower
+ *             level entries.
+ * @private:   private data for callbacks' use
  *
- * (see walk_page_range for more details)
+ * (see the comment on walk_page_range() for more details)
  */
 struct mm_walk {
 	int (*pgd_entry)(pgd_t *pgd, unsigned long addr,
@@ -1112,15 +1120,19 @@ struct mm_walk {
 			 unsigned long next, struct mm_walk *walk);
 	int (*pte_hole)(unsigned long addr, unsigned long next,
 			struct mm_walk *walk);
-	int (*hugetlb_entry)(pte_t *pte, unsigned long hmask,
-			     unsigned long addr, unsigned long next,
-			     struct mm_walk *walk);
+	int (*hugetlb_entry)(pte_t *pte, unsigned long addr,
+			unsigned long next, struct mm_walk *walk);
+	int (*test_walk)(unsigned long addr, unsigned long next,
+			struct mm_walk *walk);
 	struct mm_struct *mm;
+	struct vm_area_struct *vma;
+	int skip;
 	void *private;
 };
 
 int walk_page_range(unsigned long addr, unsigned long end,
 		struct mm_walk *walk);
+int walk_page_vma(struct vm_area_struct *vma, struct mm_walk *walk);
 void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 		unsigned long end, unsigned long floor, unsigned long ceiling);
 int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h
index ec2ffaf418c8..df78dc2b5524 100644
--- a/include/linux/netfilter/nf_conntrack_proto_gre.h
+++ b/include/linux/netfilter/nf_conntrack_proto_gre.h
@@ -87,7 +87,6 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
 /* delete keymap entries */
 void nf_ct_gre_keymap_destroy(struct nf_conn *ct);
 
-void nf_ct_gre_keymap_flush(struct net *net);
 void nf_nat_need_gre(void);
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/of.h b/include/linux/of.h
index 919bf211877d..3bad8d106e0e 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -374,6 +374,11 @@ static inline struct device_node *of_find_matching_node_and_match(
 	return NULL;
 }
 
+static inline struct device_node *of_find_node_by_path(const char *path)
+{
+	return NULL;
+}
+
 static inline struct device_node *of_get_parent(const struct device_node *node)
 {
 	return NULL;
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 45598f1e9aa3..d4acafc51949 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -316,6 +316,34 @@ static inline loff_t page_file_offset(struct page *page)
 	return ((loff_t)page_file_index(page)) << PAGE_CACHE_SHIFT;
 }
 
+/*
+ * Get the order of a given page in the context of the pagecache which it
+ * belongs to.
+ *
+ * Pagecache unit size is not a fixed value (hugetlbfs is an example), but the
+ * vma_interval_tree and anon_vma_interval_tree APIs assume that indices are in
+ * PAGE_SIZE units.  So this function helps us to get normalized indices.
+ *
+ * page_size_order() should be called only for pagecache pages/hugepages and
+ * anonymous pages/hugepages, because pagecache unit size is irrelevant except
+ * for those pages.
+ */
+static inline unsigned int page_size_order(struct page *page)
+{
+	return unlikely(PageHuge(page)) ?
+		compound_order(compound_head(page)) :
+		(PAGE_CACHE_SHIFT - PAGE_SHIFT);
+}
+
+/*
+ * page->index stores pagecache index whose unit is not always PAGE_SIZE.
+ * This function converts it into PAGE_SIZE offset.
+ */
+static inline pgoff_t page_pgoff(struct page *page)
+{
+	return page->index << page_size_order(page);
+}
+
 extern pgoff_t linear_hugepage_index(struct vm_area_struct *vma,
 				     unsigned long address);
 
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index e7a0b95ed527..539b3caa5748 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -29,7 +29,7 @@
  */
 #define get_cpu_var(var) (*({				\
 	preempt_disable();				\
-	&__get_cpu_var(var); }))
+	this_cpu_ptr(&var); }))
 
 /*
  * The weird & is necessary because sparse considers (void)(var) to be
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 24126c4b27b5..4d0221fd0688 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -75,6 +75,7 @@ typedef enum {
 	PHY_INTERFACE_MODE_SMII,
 	PHY_INTERFACE_MODE_XGMII,
 	PHY_INTERFACE_MODE_MOCA,
+	PHY_INTERFACE_MODE_QSGMII,
 	PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
@@ -116,6 +117,8 @@ static inline const char *phy_modes(phy_interface_t interface)
 		return "xgmii";
 	case PHY_INTERFACE_MODE_MOCA:
 		return "moca";
+	case PHY_INTERFACE_MODE_QSGMII:
+		return "qsgmii";
 	default:
 		return "unknown";
 	}
diff --git a/include/linux/platform_data/leds-pca9685.h b/include/linux/platform_data/leds-pca9685.h
deleted file mode 100644
index 778e9e4249cc..000000000000
--- a/include/linux/platform_data/leds-pca9685.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2013 Maximilian Güntner <maximilian.guentner@gmail.com>
- *
- * This file is subject to the terms and conditions of version 2 of
- * the GNU General Public License.  See the file COPYING in the main
- * directory of this archive for more details.
- *
- * Based on leds-pca963x.h by Peter Meerwald <p.meerwald@bct-electronic.com>
- *
- * LED driver for the NXP PCA9685 PWM chip
- *
- */
-
-#ifndef __LINUX_PCA9685_H
-#define __LINUX_PCA9685_H
-
-#include <linux/leds.h>
-
-enum pca9685_outdrv {
-	PCA9685_OPEN_DRAIN,
-	PCA9685_TOTEM_POLE,
-};
-
-enum pca9685_inverted {
-	PCA9685_NOT_INVERTED,
-	PCA9685_INVERTED,
-};
-
-struct pca9685_platform_data {
-	struct led_platform_data leds;
-	enum pca9685_outdrv outdrv;
-	enum pca9685_inverted inverted;
-};
-
-#endif /* __LINUX_PCA9685_H */
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 9e7db9e73cc1..48bf152761c7 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -20,13 +20,13 @@ enum reboot_mode {
 extern enum reboot_mode reboot_mode;
 
 enum reboot_type {
-	BOOT_TRIPLE = 't',
-	BOOT_KBD = 'k',
-	BOOT_BIOS = 'b',
-	BOOT_ACPI = 'a',
-	BOOT_EFI = 'e',
-	BOOT_CF9 = 'p',
-	BOOT_CF9_COND = 'q',
+	BOOT_TRIPLE	= 't',
+	BOOT_KBD	= 'k',
+	BOOT_BIOS	= 'b',
+	BOOT_ACPI	= 'a',
+	BOOT_EFI	= 'e',
+	BOOT_CF9_FORCE	= 'p',
+	BOOT_CF9_SAFE	= 'q',
 };
 extern enum reboot_type reboot_type;
 
diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h
index f9217965aaa3..a5abd8334003 100644
--- a/include/linux/regulator/of_regulator.h
+++ b/include/linux/regulator/of_regulator.h
@@ -20,6 +20,8 @@ extern struct regulator_init_data
 extern int of_regulator_match(struct device *dev, struct device_node *node,
 			      struct of_regulator_match *matches,
 			      unsigned int num_matches);
+extern int of_regulator_put_match(struct of_regulator_match *matches,
+				  unsigned int num_matches);
 #else
 static inline struct regulator_init_data
 	*of_get_regulator_init_data(struct device *dev,
@@ -35,6 +37,11 @@ static inline int of_regulator_match(struct device *dev,
 {
 	return 0;
 }
+static inline int of_regulator_put_match(struct of_regulator_match *matches,
+					 unsigned int num_matches)
+{
+	return 0;
+}
 #endif /* CONFIG_OF */
 
 #endif /* __LINUX_OF_REG_H */
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index a964f7285600..4b152c81c5fa 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -136,7 +136,7 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
 static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
 			    struct scatterlist *sgl)
 {
-#ifndef ARCH_HAS_SG_CHAIN
+#ifndef CONFIG_ARCH_HAS_SG_CHAIN
 	BUG();
 #endif
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 25f54c79f757..148481cbc89f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2366,9 +2366,6 @@ extern void flush_itimer_signals(void);
 
 extern void do_group_exit(int);
 
-extern int allow_signal(int);
-extern int disallow_signal(int);
-
 extern int do_execve(struct filename *,
 		     const char __user * const __user *,
 		     const char __user * const __user *);
diff --git a/include/linux/security.h b/include/linux/security.h
index 6478ce3252c7..9c6b9722ff48 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1708,7 +1708,7 @@ struct security_operations {
 	void (*key_free) (struct key *key);
 	int (*key_permission) (key_ref_t key_ref,
 			       const struct cred *cred,
-			       key_perm_t perm);
+			       unsigned perm);
 	int (*key_getsecurity)(struct key *key, char **_buffer);
 #endif	/* CONFIG_KEYS */
 
@@ -3034,7 +3034,7 @@ static inline int security_path_chroot(struct path *path)
 int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags);
 void security_key_free(struct key *key);
 int security_key_permission(key_ref_t key_ref,
-			    const struct cred *cred, key_perm_t perm);
+			    const struct cred *cred, unsigned perm);
 int security_key_getsecurity(struct key *key, char **_buffer);
 
 #else
@@ -3052,7 +3052,7 @@ static inline void security_key_free(struct key *key)
 
 static inline int security_key_permission(key_ref_t key_ref,
 					  const struct cred *cred,
-					  key_perm_t perm)
+					  unsigned perm)
 {
 	return 0;
 }
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 2ac423bdb676..c9e65360c49a 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -63,11 +63,6 @@ static inline int sigismember(sigset_t *set, int _sig)
 		return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
 }
 
-static inline int sigfindinword(unsigned long word)
-{
-	return ffz(~word);
-}
-
 #endif /* __HAVE_ARCH_SIG_BITOPS */
 
 static inline int sigisemptyset(sigset_t *set)
@@ -289,6 +284,22 @@ extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
 extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
 extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping);
 extern void exit_signals(struct task_struct *tsk);
+extern void kernel_sigaction(int, __sighandler_t);
+
+static inline void allow_signal(int sig)
+{
+	/*
+	 * Kernel threads handle their own signals. Let the signal code
+	 * know it'll be handled, so that they don't get converted to
+	 * SIGKILL or just silently dropped.
+	 */
+	kernel_sigaction(sig, (__force __sighandler_t)2);
+}
+
+static inline void disallow_signal(int sig)
+{
+	kernel_sigaction(sig, SIG_IGN);
+}
 
 /*
  * Eventually that'll replace get_signal_to_deliver(); macro for now,
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 307bfbe62387..a6aab2c0dfc5 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -369,16 +369,7 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 #include <linux/slub_def.h>
 #endif
 
-static __always_inline void *
-kmalloc_order(size_t size, gfp_t flags, unsigned int order)
-{
-	void *ret;
-
-	flags |= (__GFP_COMP | __GFP_KMEMCG);
-	ret = (void *) __get_free_pages(flags, order);
-	kmemleak_alloc(ret, size, 1, flags);
-	return ret;
-}
+extern void *kmalloc_order(size_t size, gfp_t flags, unsigned int order);
 
 #ifdef CONFIG_TRACING
 extern void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order);
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 633f5edd7470..0de1effbdd76 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -29,6 +29,17 @@ extern unsigned int total_cpus;
 int smp_call_function_single(int cpuid, smp_call_func_t func, void *info,
 			     int wait);
 
+struct queue_single_data;
+typedef void (*smp_queue_func_t)(struct queue_single_data *qsd);
+
+struct queue_single_data {
+	struct call_single_data data;
+	smp_queue_func_t func;
+	int pending;
+};
+
+int smp_queue_function_single(int cpu, struct queue_single_data *qsd);
+
 /*
  * Call a function on all processors
  */
diff --git a/include/linux/spi/adi_spi3.h b/include/linux/spi/adi_spi3.h
new file mode 100644
index 000000000000..c84123aa1d06
--- /dev/null
+++ b/include/linux/spi/adi_spi3.h
@@ -0,0 +1,254 @@
+/*
+ * Analog Devices SPI3 controller driver
+ *
+ * Copyright (c) 2014 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ADI_SPI3_H_
+#define _ADI_SPI3_H_
+
+#include <linux/types.h>
+
+/* SPI_CONTROL */
+#define SPI_CTL_EN                  0x00000001    /* Enable */
+#define SPI_CTL_MSTR                0x00000002    /* Master/Slave */
+#define SPI_CTL_PSSE                0x00000004    /* controls modf error in master mode */
+#define SPI_CTL_ODM                 0x00000008    /* Open Drain Mode */
+#define SPI_CTL_CPHA                0x00000010    /* Clock Phase */
+#define SPI_CTL_CPOL                0x00000020    /* Clock Polarity */
+#define SPI_CTL_ASSEL               0x00000040    /* Slave Select Pin Control */
+#define SPI_CTL_SELST               0x00000080    /* Slave Select Polarity in-between transfers */
+#define SPI_CTL_EMISO               0x00000100    /* Enable MISO */
+#define SPI_CTL_SIZE                0x00000600    /* Word Transfer Size */
+#define SPI_CTL_SIZE08              0x00000000    /* SIZE: 8 bits */
+#define SPI_CTL_SIZE16              0x00000200    /* SIZE: 16 bits */
+#define SPI_CTL_SIZE32              0x00000400    /* SIZE: 32 bits */
+#define SPI_CTL_LSBF                0x00001000    /* LSB First */
+#define SPI_CTL_FCEN                0x00002000    /* Flow-Control Enable */
+#define SPI_CTL_FCCH                0x00004000    /* Flow-Control Channel Selection */
+#define SPI_CTL_FCPL                0x00008000    /* Flow-Control Polarity */
+#define SPI_CTL_FCWM                0x00030000    /* Flow-Control Water-Mark */
+#define SPI_CTL_FIFO0               0x00000000    /* FCWM: TFIFO empty or RFIFO Full */
+#define SPI_CTL_FIFO1               0x00010000    /* FCWM: TFIFO 75% or more empty or RFIFO 75% or more full */
+#define SPI_CTL_FIFO2               0x00020000    /* FCWM: TFIFO 50% or more empty or RFIFO 50% or more full */
+#define SPI_CTL_FMODE               0x00040000    /* Fast-mode Enable */
+#define SPI_CTL_MIOM                0x00300000    /* Multiple I/O Mode */
+#define SPI_CTL_MIO_DIS             0x00000000    /* MIOM: Disable */
+#define SPI_CTL_MIO_DUAL            0x00100000    /* MIOM: Enable DIOM (Dual I/O Mode) */
+#define SPI_CTL_MIO_QUAD            0x00200000    /* MIOM: Enable QUAD (Quad SPI Mode) */
+#define SPI_CTL_SOSI                0x00400000    /* Start on MOSI */
+/* SPI_RX_CONTROL */
+#define SPI_RXCTL_REN               0x00000001    /* Receive Channel Enable */
+#define SPI_RXCTL_RTI               0x00000004    /* Receive Transfer Initiate */
+#define SPI_RXCTL_RWCEN             0x00000008    /* Receive Word Counter Enable */
+#define SPI_RXCTL_RDR               0x00000070    /* Receive Data Request */
+#define SPI_RXCTL_RDR_DIS           0x00000000    /* RDR: Disabled */
+#define SPI_RXCTL_RDR_NE            0x00000010    /* RDR: RFIFO not empty */
+#define SPI_RXCTL_RDR_25            0x00000020    /* RDR: RFIFO 25% full */
+#define SPI_RXCTL_RDR_50            0x00000030    /* RDR: RFIFO 50% full */
+#define SPI_RXCTL_RDR_75            0x00000040    /* RDR: RFIFO 75% full */
+#define SPI_RXCTL_RDR_FULL          0x00000050    /* RDR: RFIFO full */
+#define SPI_RXCTL_RDO               0x00000100    /* Receive Data Over-Run */
+#define SPI_RXCTL_RRWM              0x00003000    /* FIFO Regular Water-Mark */
+#define SPI_RXCTL_RWM_0             0x00000000    /* RRWM: RFIFO Empty */
+#define SPI_RXCTL_RWM_25            0x00001000    /* RRWM: RFIFO 25% full */
+#define SPI_RXCTL_RWM_50            0x00002000    /* RRWM: RFIFO 50% full */
+#define SPI_RXCTL_RWM_75            0x00003000    /* RRWM: RFIFO 75% full */
+#define SPI_RXCTL_RUWM              0x00070000    /* FIFO Urgent Water-Mark */
+#define SPI_RXCTL_UWM_DIS           0x00000000    /* RUWM: Disabled */
+#define SPI_RXCTL_UWM_25            0x00010000    /* RUWM: RFIFO 25% full */
+#define SPI_RXCTL_UWM_50            0x00020000    /* RUWM: RFIFO 50% full */
+#define SPI_RXCTL_UWM_75            0x00030000    /* RUWM: RFIFO 75% full */
+#define SPI_RXCTL_UWM_FULL          0x00040000    /* RUWM: RFIFO full */
+/* SPI_TX_CONTROL */
+#define SPI_TXCTL_TEN               0x00000001    /* Transmit Channel Enable */
+#define SPI_TXCTL_TTI               0x00000004    /* Transmit Transfer Initiate */
+#define SPI_TXCTL_TWCEN             0x00000008    /* Transmit Word Counter Enable */
+#define SPI_TXCTL_TDR               0x00000070    /* Transmit Data Request */
+#define SPI_TXCTL_TDR_DIS           0x00000000    /* TDR: Disabled */
+#define SPI_TXCTL_TDR_NF            0x00000010    /* TDR: TFIFO not full */
+#define SPI_TXCTL_TDR_25            0x00000020    /* TDR: TFIFO 25% empty */
+#define SPI_TXCTL_TDR_50            0x00000030    /* TDR: TFIFO 50% empty */
+#define SPI_TXCTL_TDR_75            0x00000040    /* TDR: TFIFO 75% empty */
+#define SPI_TXCTL_TDR_EMPTY         0x00000050    /* TDR: TFIFO empty */
+#define SPI_TXCTL_TDU               0x00000100    /* Transmit Data Under-Run */
+#define SPI_TXCTL_TRWM              0x00003000    /* FIFO Regular Water-Mark */
+#define SPI_TXCTL_RWM_FULL          0x00000000    /* TRWM: TFIFO full */
+#define SPI_TXCTL_RWM_25            0x00001000    /* TRWM: TFIFO 25% empty */
+#define SPI_TXCTL_RWM_50            0x00002000    /* TRWM: TFIFO 50% empty */
+#define SPI_TXCTL_RWM_75            0x00003000    /* TRWM: TFIFO 75% empty */
+#define SPI_TXCTL_TUWM              0x00070000    /* FIFO Urgent Water-Mark */
+#define SPI_TXCTL_UWM_DIS           0x00000000    /* TUWM: Disabled */
+#define SPI_TXCTL_UWM_25            0x00010000    /* TUWM: TFIFO 25% empty */
+#define SPI_TXCTL_UWM_50            0x00020000    /* TUWM: TFIFO 50% empty */
+#define SPI_TXCTL_UWM_75            0x00030000    /* TUWM: TFIFO 75% empty */
+#define SPI_TXCTL_UWM_EMPTY         0x00040000    /* TUWM: TFIFO empty */
+/* SPI_CLOCK */
+#define SPI_CLK_BAUD                0x0000FFFF    /* Baud Rate */
+/* SPI_DELAY */
+#define SPI_DLY_STOP                0x000000FF    /* Transfer delay time in multiples of SCK period */
+#define SPI_DLY_LEADX               0x00000100    /* Extended (1 SCK) LEAD Control */
+#define SPI_DLY_LAGX                0x00000200    /* Extended (1 SCK) LAG control */
+/* SPI_SSEL */
+#define SPI_SLVSEL_SSE1             0x00000002    /* SPISSEL1 Enable */
+#define SPI_SLVSEL_SSE2             0x00000004    /* SPISSEL2 Enable */
+#define SPI_SLVSEL_SSE3             0x00000008    /* SPISSEL3 Enable */
+#define SPI_SLVSEL_SSE4             0x00000010    /* SPISSEL4 Enable */
+#define SPI_SLVSEL_SSE5             0x00000020    /* SPISSEL5 Enable */
+#define SPI_SLVSEL_SSE6             0x00000040    /* SPISSEL6 Enable */
+#define SPI_SLVSEL_SSE7             0x00000080    /* SPISSEL7 Enable */
+#define SPI_SLVSEL_SSEL1            0x00000200    /* SPISSEL1 Value */
+#define SPI_SLVSEL_SSEL2            0x00000400    /* SPISSEL2 Value */
+#define SPI_SLVSEL_SSEL3            0x00000800    /* SPISSEL3 Value */
+#define SPI_SLVSEL_SSEL4            0x00001000    /* SPISSEL4 Value */
+#define SPI_SLVSEL_SSEL5            0x00002000    /* SPISSEL5 Value */
+#define SPI_SLVSEL_SSEL6            0x00004000    /* SPISSEL6 Value */
+#define SPI_SLVSEL_SSEL7            0x00008000    /* SPISSEL7 Value */
+/* SPI_RWC */
+#define SPI_RWC_VALUE               0x0000FFFF    /* Received Word-Count */
+/* SPI_RWCR */
+#define SPI_RWCR_VALUE              0x0000FFFF    /* Received Word-Count Reload */
+/* SPI_TWC */
+#define SPI_TWC_VALUE               0x0000FFFF    /* Transmitted Word-Count */
+/* SPI_TWCR */
+#define SPI_TWCR_VALUE              0x0000FFFF    /* Transmitted Word-Count Reload */
+/* SPI_IMASK */
+#define SPI_IMSK_RUWM               0x00000002    /* Receive Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_TUWM               0x00000004    /* Transmit Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_ROM                0x00000010    /* Receive Over-Run Error Interrupt Mask */
+#define SPI_IMSK_TUM                0x00000020    /* Transmit Under-Run Error Interrupt Mask */
+#define SPI_IMSK_TCM                0x00000040    /* Transmit Collision Error Interrupt Mask */
+#define SPI_IMSK_MFM                0x00000080    /* Mode Fault Error Interrupt Mask */
+#define SPI_IMSK_RSM                0x00000100    /* Receive Start Interrupt Mask */
+#define SPI_IMSK_TSM                0x00000200    /* Transmit Start Interrupt Mask */
+#define SPI_IMSK_RFM                0x00000400    /* Receive Finish Interrupt Mask */
+#define SPI_IMSK_TFM                0x00000800    /* Transmit Finish Interrupt Mask */
+/* SPI_IMASKCL */
+#define SPI_IMSK_CLR_RUW            0x00000002    /* Receive Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_CLR_TUWM           0x00000004    /* Transmit Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_CLR_ROM            0x00000010    /* Receive Over-Run Error Interrupt Mask */
+#define SPI_IMSK_CLR_TUM            0x00000020    /* Transmit Under-Run Error Interrupt Mask */
+#define SPI_IMSK_CLR_TCM            0x00000040    /* Transmit Collision Error Interrupt Mask */
+#define SPI_IMSK_CLR_MFM            0x00000080    /* Mode Fault Error Interrupt Mask */
+#define SPI_IMSK_CLR_RSM            0x00000100    /* Receive Start Interrupt Mask */
+#define SPI_IMSK_CLR_TSM            0x00000200    /* Transmit Start Interrupt Mask */
+#define SPI_IMSK_CLR_RFM            0x00000400    /* Receive Finish Interrupt Mask */
+#define SPI_IMSK_CLR_TFM            0x00000800    /* Transmit Finish Interrupt Mask */
+/* SPI_IMASKST */
+#define SPI_IMSK_SET_RUWM           0x00000002    /* Receive Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_SET_TUWM           0x00000004    /* Transmit Urgent Water-Mark Interrupt Mask */
+#define SPI_IMSK_SET_ROM            0x00000010    /* Receive Over-Run Error Interrupt Mask */
+#define SPI_IMSK_SET_TUM            0x00000020    /* Transmit Under-Run Error Interrupt Mask */
+#define SPI_IMSK_SET_TCM            0x00000040    /* Transmit Collision Error Interrupt Mask */
+#define SPI_IMSK_SET_MFM            0x00000080    /* Mode Fault Error Interrupt Mask */
+#define SPI_IMSK_SET_RSM            0x00000100    /* Receive Start Interrupt Mask */
+#define SPI_IMSK_SET_TSM            0x00000200    /* Transmit Start Interrupt Mask */
+#define SPI_IMSK_SET_RFM            0x00000400    /* Receive Finish Interrupt Mask */
+#define SPI_IMSK_SET_TFM            0x00000800    /* Transmit Finish Interrupt Mask */
+/* SPI_STATUS */
+#define SPI_STAT_SPIF               0x00000001    /* SPI Finished */
+#define SPI_STAT_RUWM               0x00000002    /* Receive Urgent Water-Mark Breached */
+#define SPI_STAT_TUWM               0x00000004    /* Transmit Urgent Water-Mark Breached */
+#define SPI_STAT_ROE                0x00000010    /* Receive Over-Run Error Indication */
+#define SPI_STAT_TUE                0x00000020    /* Transmit Under-Run Error Indication */
+#define SPI_STAT_TCE                0x00000040    /* Transmit Collision Error Indication */
+#define SPI_STAT_MODF               0x00000080    /* Mode Fault Error Indication */
+#define SPI_STAT_RS                 0x00000100    /* Receive Start Indication */
+#define SPI_STAT_TS                 0x00000200    /* Transmit Start Indication */
+#define SPI_STAT_RF                 0x00000400    /* Receive Finish Indication */
+#define SPI_STAT_TF                 0x00000800    /* Transmit Finish Indication */
+#define SPI_STAT_RFS                0x00007000    /* SPI_RFIFO status */
+#define SPI_STAT_RFIFO_EMPTY        0x00000000    /* RFS: RFIFO Empty */
+#define SPI_STAT_RFIFO_25           0x00001000    /* RFS: RFIFO 25% Full */
+#define SPI_STAT_RFIFO_50           0x00002000    /* RFS: RFIFO 50% Full */
+#define SPI_STAT_RFIFO_75           0x00003000    /* RFS: RFIFO 75% Full */
+#define SPI_STAT_RFIFO_FULL         0x00004000    /* RFS: RFIFO Full */
+#define SPI_STAT_TFS                0x00070000    /* SPI_TFIFO status */
+#define SPI_STAT_TFIFO_FULL         0x00000000    /* TFS: TFIFO full */
+#define SPI_STAT_TFIFO_25           0x00010000    /* TFS: TFIFO 25% empty */
+#define SPI_STAT_TFIFO_50           0x00020000    /* TFS: TFIFO 50% empty */
+#define SPI_STAT_TFIFO_75           0x00030000    /* TFS: TFIFO 75% empty */
+#define SPI_STAT_TFIFO_EMPTY        0x00040000    /* TFS: TFIFO empty */
+#define SPI_STAT_FCS                0x00100000    /* Flow-Control Stall Indication */
+#define SPI_STAT_RFE                0x00400000    /* SPI_RFIFO Empty */
+#define SPI_STAT_TFF                0x00800000    /* SPI_TFIFO Full */
+/* SPI_ILAT */
+#define SPI_ILAT_RUWMI              0x00000002    /* Receive Urgent Water Mark Interrupt */
+#define SPI_ILAT_TUWMI              0x00000004    /* Transmit Urgent Water Mark Interrupt */
+#define SPI_ILAT_ROI                0x00000010    /* Receive Over-Run Error Indication */
+#define SPI_ILAT_TUI                0x00000020    /* Transmit Under-Run Error Indication */
+#define SPI_ILAT_TCI                0x00000040    /* Transmit Collision Error Indication */
+#define SPI_ILAT_MFI                0x00000080    /* Mode Fault Error Indication */
+#define SPI_ILAT_RSI                0x00000100    /* Receive Start Indication */
+#define SPI_ILAT_TSI                0x00000200    /* Transmit Start Indication */
+#define SPI_ILAT_RFI                0x00000400    /* Receive Finish Indication */
+#define SPI_ILAT_TFI                0x00000800    /* Transmit Finish Indication */
+/* SPI_ILATCL */
+#define SPI_ILAT_CLR_RUWMI          0x00000002    /* Receive Urgent Water Mark Interrupt */
+#define SPI_ILAT_CLR_TUWMI          0x00000004    /* Transmit Urgent Water Mark Interrupt */
+#define SPI_ILAT_CLR_ROI            0x00000010    /* Receive Over-Run Error Indication */
+#define SPI_ILAT_CLR_TUI            0x00000020    /* Transmit Under-Run Error Indication */
+#define SPI_ILAT_CLR_TCI            0x00000040    /* Transmit Collision Error Indication */
+#define SPI_ILAT_CLR_MFI            0x00000080    /* Mode Fault Error Indication */
+#define SPI_ILAT_CLR_RSI            0x00000100    /* Receive Start Indication */
+#define SPI_ILAT_CLR_TSI            0x00000200    /* Transmit Start Indication */
+#define SPI_ILAT_CLR_RFI            0x00000400    /* Receive Finish Indication */
+#define SPI_ILAT_CLR_TFI            0x00000800    /* Transmit Finish Indication */
+
+/*
+ * adi spi3 registers layout
+ */
+struct adi_spi_regs {
+	u32 revid;
+	u32 control;
+	u32 rx_control;
+	u32 tx_control;
+	u32 clock;
+	u32 delay;
+	u32 ssel;
+	u32 rwc;
+	u32 rwcr;
+	u32 twc;
+	u32 twcr;
+	u32 reserved0;
+	u32 emask;
+	u32 emaskcl;
+	u32 emaskst;
+	u32 reserved1;
+	u32 status;
+	u32 elat;
+	u32 elatcl;
+	u32 reserved2;
+	u32 rfifo;
+	u32 reserved3;
+	u32 tfifo;
+};
+
+#define MAX_CTRL_CS          8  /* cs in spi controller */
+
+/* device.platform_data for SSP controller devices */
+struct adi_spi3_master {
+	u16 num_chipselect;
+	u16 pin_req[7];
+};
+
+/* spi_board_info.controller_data for SPI slave devices,
+ * copied to spi_device.platform_data ... mostly for dma tuning
+ */
+struct adi_spi3_chip {
+	u32 control;
+	u16 cs_chg_udelay; /* Some devices require 16-bit delays */
+	u32 tx_dummy_val; /* tx value for rx only transfer */
+	bool enable_dma;
+};
+
+#endif /* _ADI_SPI3_H_ */
diff --git a/include/linux/string.h b/include/linux/string.h
index ac889c5ea11b..f29f9a0b7265 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -114,6 +114,7 @@ void *memchr_inv(const void *s, int c, size_t n);
 
 extern char *kstrdup(const char *s, gfp_t gfp);
 extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
+extern char *kstrimdup(const char *s, gfp_t gfp);
 extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
 
 extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 084354b0e814..5ffaa3443712 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -179,9 +179,6 @@ struct sysfs_ops {
 
 #ifdef CONFIG_SYSFS
 
-int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
-			    void *data, struct module *owner);
-
 int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns);
 void sysfs_remove_dir(struct kobject *kobj);
 int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
@@ -255,12 +252,6 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn)
 
 #else /* CONFIG_SYSFS */
 
-static inline int sysfs_schedule_callback(struct kobject *kobj,
-		void (*func)(void *), void *data, struct module *owner)
-{
-	return -ENOSYS;
-}
-
 static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
 {
 	return 0;
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index fddbe2023a5d..1807bb194816 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -61,8 +61,6 @@ extern long do_no_restart_syscall(struct restart_block *parm);
 # define THREADINFO_GFP		(GFP_KERNEL | __GFP_NOTRACK)
 #endif
 
-#define THREADINFO_GFP_ACCOUNTED (THREADINFO_GFP | __GFP_KMEMCG)
-
 /*
  * flag set/clear/test wrappers
  * - pass TIF_xxxx constants to these functions
diff --git a/include/linux/tick.h b/include/linux/tick.h
index b84773cb9f4c..9d3fcc2b9e63 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -182,6 +182,7 @@ static inline bool tick_nohz_full_cpu(int cpu)
 extern void tick_nohz_init(void);
 extern void __tick_nohz_full_check(void);
 extern void tick_nohz_full_kick(void);
+extern void tick_nohz_full_kick_cpu(int cpu);
 extern void tick_nohz_full_kick_all(void);
 extern void __tick_nohz_task_switch(struct task_struct *tsk);
 #else
@@ -190,6 +191,7 @@ static inline bool tick_nohz_full_enabled(void) { return false; }
 static inline bool tick_nohz_full_cpu(int cpu) { return false; }
 static inline void __tick_nohz_full_check(void) { }
 static inline void tick_nohz_full_kick(void) { }
+static inline void tick_nohz_full_kick_cpu(int cpu) { }
 static inline void tick_nohz_full_kick_all(void) { }
 static inline void __tick_nohz_task_switch(struct task_struct *tsk) { }
 #endif
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index 486c3972c0be..ced92345c963 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -80,6 +80,10 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		NR_TLB_LOCAL_FLUSH_ALL,
 		NR_TLB_LOCAL_FLUSH_ONE,
 #endif /* CONFIG_DEBUG_TLBFLUSH */
+#ifdef CONFIG_DEBUG_VM_VMACACHE
+		VMACACHE_FIND_CALLS,
+		VMACACHE_FIND_HITS,
+#endif
 		NR_VM_EVENT_ITEMS
 };
 
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 45c9cd1daf7a..82e7db7f7100 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -95,6 +95,12 @@ static inline void vm_events_fold_cpu(int cpu)
 #define count_vm_tlb_events(x, y) do { (void)(y); } while (0)
 #endif
 
+#ifdef CONFIG_DEBUG_VM_VMACACHE
+#define count_vm_vmacache_event(x) count_vm_event(x)
+#else
+#define count_vm_vmacache_event(x) do {} while (0)
+#endif
+
 #define __count_zone_vm_events(item, zone, delta) \
 		__count_vm_events(item##_NORMAL - ZONE_NORMAL + \
 		zone_idx(zone), delta)
diff --git a/include/linux/wait.h b/include/linux/wait.h
index e7d9d9ed14f5..bd68819f0815 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -191,11 +191,23 @@ wait_queue_head_t *bit_waitqueue(void *, int);
 	(!__builtin_constant_p(state) ||				\
 		state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE)	\
 
+/*
+ * The below macro ___wait_event() has an explicit shadow of the __ret
+ * variable when used from the wait_event_*() macros.
+ *
+ * This is so that both can use the ___wait_cond_timeout() construct
+ * to wrap the condition.
+ *
+ * The type inconsistency of the wait_event_*() __ret variable is also
+ * on purpose; we use long where we can return timeout values and int
+ * otherwise.
+ */
+
 #define ___wait_event(wq, condition, state, exclusive, ret, cmd)	\
 ({									\
 	__label__ __out;						\
 	wait_queue_t __wait;						\
-	long __ret = ret;						\
+	long __ret = ret;	/* explicit shadow */			\
 									\
 	INIT_LIST_HEAD(&__wait.task_list);				\
 	if (exclusive)							\
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index be150cf8cd43..4261a67682c0 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -367,6 +367,7 @@ enum {
 #define HCI_ERROR_REMOTE_POWER_OFF	0x15
 #define HCI_ERROR_LOCAL_HOST_TERM	0x16
 #define HCI_ERROR_PAIRING_NOT_ALLOWED	0x18
+#define HCI_ERROR_ADVERTISING_TIMEOUT	0x3c
 
 /* Flow control modes */
 #define HCI_FLOW_CTL_MODE_PACKET_BASED	0x00
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5f8bc05694ac..d73f41855ada 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -68,6 +68,11 @@ struct discovery_state {
 	struct list_head	unknown;	/* Name state not known */
 	struct list_head	resolve;	/* Name needs to be resolved */
 	__u32			timestamp;
+	bdaddr_t		last_adv_addr;
+	u8			last_adv_addr_type;
+	s8			last_adv_rssi;
+	u8			last_adv_data[HCI_MAX_AD_LENGTH];
+	u8			last_adv_data_len;
 };
 
 struct hci_conn_hash {
@@ -194,6 +199,7 @@ struct hci_dev {
 	__u16		le_scan_window;
 	__u16		le_conn_min_interval;
 	__u16		le_conn_max_interval;
+	__u16		discov_interleaved_timeout;
 	__u8		ssp_debug_mode;
 
 	__u16		devid_source;
@@ -1204,8 +1210,8 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
  */
 #define DISCOV_LE_SCAN_WIN		0x12
 #define DISCOV_LE_SCAN_INT		0x12
-#define DISCOV_LE_TIMEOUT		msecs_to_jiffies(10240)
-#define DISCOV_INTERLEAVED_TIMEOUT	msecs_to_jiffies(5120)
+#define DISCOV_LE_TIMEOUT		10240	/* msec */
+#define DISCOV_INTERLEAVED_TIMEOUT	5120	/* msec */
 #define DISCOV_INTERLEAVED_INQUIRY_LEN	0x04
 #define DISCOV_BREDR_INQUIRY_LEN	0x08
 
@@ -1265,7 +1271,8 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
 				       u8 *randomizer256, u8 status);
 void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		       u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
-		       u8 ssp, u8 *eir, u16 eir_len);
+		       u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
+		       u8 scan_rsp_len);
 void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		      u8 addr_type, s8 rssi, u8 *name, u8 name_len);
 void mgmt_discovering(struct hci_dev *hdev, u8 discovering);
diff --git a/include/net/dst.h b/include/net/dst.h
index 46ed958e0c6e..71c60f42be48 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -45,7 +45,7 @@ struct dst_entry {
 	void			*__pad1;
 #endif
 	int			(*input)(struct sk_buff *);
-	int			(*output)(struct sk_buff *);
+	int			(*output)(struct sock *sk, struct sk_buff *skb);
 
 	unsigned short		flags;
 #define DST_HOST		0x0001
@@ -367,7 +367,11 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 	return child;
 }
 
-int dst_discard(struct sk_buff *skb);
+int dst_discard_sk(struct sock *sk, struct sk_buff *skb);
+static inline int dst_discard(struct sk_buff *skb)
+{
+	return dst_discard_sk(skb->sk, skb);
+}
 void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref,
 		int initial_obsolete, unsigned short flags);
 void __dst_free(struct dst_entry *dst);
@@ -449,9 +453,13 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
 }
 
 /* Output packet to network from transport.  */
+static inline int dst_output_sk(struct sock *sk, struct sk_buff *skb)
+{
+	return skb_dst(skb)->output(sk, skb);
+}
 static inline int dst_output(struct sk_buff *skb)
 {
-	return skb_dst(skb)->output(skb);
+	return dst_output_sk(skb->sk, skb);
 }
 
 /* Input packet from network to transport.  */
diff --git a/include/net/flow.h b/include/net/flow.h
index 64fd24836650..8109a159d1b3 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -11,6 +11,14 @@
 #include <linux/in6.h>
 #include <linux/atomic.h>
 
+/*
+ * ifindex generation is per-net namespace, and loopback is
+ * always the 1st device in ns (see net_dev_init), thus any
+ * loopback device should get ifindex 1
+ */
+
+#define LOOPBACK_IFINDEX	1
+
 struct flowi_common {
 	int	flowic_oif;
 	int	flowic_iif;
@@ -80,7 +88,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
 				      __be16 dport, __be16 sport)
 {
 	fl4->flowi4_oif = oif;
-	fl4->flowi4_iif = 0;
+	fl4->flowi4_iif = LOOPBACK_IFINDEX;
 	fl4->flowi4_mark = mark;
 	fl4->flowi4_tos = tos;
 	fl4->flowi4_scope = scope;
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index f981ba7adeed..74af137304be 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -40,7 +40,7 @@ void inet6_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
 
 void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
 
-int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl);
+int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
 
 struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu);
 #endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index c55aeed41ace..7a4313887568 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -36,7 +36,7 @@ struct tcp_congestion_ops;
  * (i.e. things that depend on the address family)
  */
 struct inet_connection_sock_af_ops {
-	int	    (*queue_xmit)(struct sk_buff *skb, struct flowi *fl);
+	int	    (*queue_xmit)(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
 	void	    (*send_check)(struct sock *sk, struct sk_buff *skb);
 	int	    (*rebuild_header)(struct sock *sk);
 	void	    (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
diff --git a/include/net/ip.h b/include/net/ip.h
index 25064c28e059..3ec2b0fb9d83 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -104,14 +104,19 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 	   struct net_device *orig_dev);
 int ip_local_deliver(struct sk_buff *skb);
 int ip_mr_input(struct sk_buff *skb);
-int ip_output(struct sk_buff *skb);
-int ip_mc_output(struct sk_buff *skb);
+int ip_output(struct sock *sk, struct sk_buff *skb);
+int ip_mc_output(struct sock *sk, struct sk_buff *skb);
 int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 int ip_do_nat(struct sk_buff *skb);
 void ip_send_check(struct iphdr *ip);
 int __ip_local_out(struct sk_buff *skb);
-int ip_local_out(struct sk_buff *skb);
-int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl);
+int ip_local_out_sk(struct sock *sk, struct sk_buff *skb);
+static inline int ip_local_out(struct sk_buff *skb)
+{
+	return ip_local_out_sk(skb->sk, skb);
+}
+
+int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
 void ip_init(void);
 int ip_append_data(struct sock *sk, struct flowi4 *fl4,
 		   int getfrag(void *from, char *to, int offset, int len,
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 3c3bb184eb8f..6c4f5eac98e7 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -32,6 +32,11 @@ struct route_info {
 #define RT6_LOOKUP_F_SRCPREF_PUBLIC	0x00000010
 #define RT6_LOOKUP_F_SRCPREF_COA	0x00000020
 
+/* We do not (yet ?) support IPv6 jumbograms (RFC 2675)
+ * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header
+ */
+#define IP6_MAX_MTU (0xFFFF + sizeof(struct ipv6hdr))
+
 /*
  * rt6_srcprefs2flags() and rt6_flags2srcprefs() translate
  * between IPV6_ADDR_PREFERENCES socket option values
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index e77c10405d51..a4daf9eb8562 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -153,7 +153,7 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
 }
 
 int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
-int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
+int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 		  __be32 src, __be32 dst, __u8 proto,
 		  __u8 tos, __u8 ttl, __be16 df, bool xnet);
 
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 4f541f11ce63..d640925bc454 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -731,7 +731,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net,
  *	skb processing functions
  */
 
-int ip6_output(struct sk_buff *skb);
+int ip6_output(struct sock *sk, struct sk_buff *skb);
 int ip6_forward(struct sk_buff *skb);
 int ip6_input(struct sk_buff *skb);
 int ip6_mc_input(struct sk_buff *skb);
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 79387f73f875..5f9eb260990f 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -9,6 +9,7 @@
 #include <linux/list.h>
 #include <linux/sysctl.h>
 
+#include <net/flow.h>
 #include <net/netns/core.h>
 #include <net/netns/mib.h>
 #include <net/netns/unix.h>
@@ -131,14 +132,6 @@ struct net {
 	atomic_t		fnhe_genid;
 };
 
-/*
- * ifindex generation is per-net namespace, and loopback is
- * always the 1st device in ns (see net_dev_init), thus any
- * loopback device should get ifindex 1
- */
-
-#define LOOPBACK_IFINDEX	1
-
 #include <linux/seq_file_net.h>
 
 /* Init's network namespace */
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index cf2b7ae2b9d8..a75fc8e27cd6 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -13,6 +13,16 @@ struct nft_cmp_fast_expr {
 	u8			len;
 };
 
+/* Calculate the mask for the nft_cmp_fast expression. On big endian the
+ * mask needs to include the *upper* bytes when interpreting that data as
+ * something smaller than the full u32, therefore a cpu_to_le32 is done.
+ */
+static inline u32 nft_cmp_fast_mask(unsigned int len)
+{
+	return cpu_to_le32(~0U >> (FIELD_SIZEOF(struct nft_cmp_fast_expr,
+						data) * BITS_PER_BYTE - len));
+}
+
 extern const struct nft_expr_ops nft_cmp_fast_ops;
 
 int nft_cmp_module_init(void);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 6ee76c804893..d992ca3145fe 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1653,6 +1653,17 @@ struct sctp_association {
 	/* This is the last advertised value of rwnd over a SACK chunk. */
 	__u32 a_rwnd;
 
+	/* Number of bytes by which the rwnd has slopped.  The rwnd is allowed
+	 * to slop over a maximum of the association's frag_point.
+	 */
+	__u32 rwnd_over;
+
+	/* Keeps treack of rwnd pressure.  This happens when we have
+	 * a window, but not recevie buffer (i.e small packets).  This one
+	 * is releases slowly (1 PMTU at a time ).
+	 */
+	__u32 rwnd_press;
+
 	/* This is the sndbuf size in use for the association.
 	 * This corresponds to the sndbuf size for the association,
 	 * as specified in the sk->sndbuf.
@@ -1881,7 +1892,8 @@ void sctp_assoc_update(struct sctp_association *old,
 __u32 sctp_association_get_next_tsn(struct sctp_association *);
 
 void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *);
-void sctp_assoc_rwnd_update(struct sctp_association *, bool);
+void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int);
+void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int);
 void sctp_assoc_set_primary(struct sctp_association *,
 			    struct sctp_transport *);
 void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 32682ae47b3f..116e9c7e19cb 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -333,7 +333,7 @@ struct xfrm_state_afinfo {
 						const xfrm_address_t *saddr);
 	int			(*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
 	int			(*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
-	int			(*output)(struct sk_buff *skb);
+	int			(*output)(struct sock *sk, struct sk_buff *skb);
 	int			(*output_finish)(struct sk_buff *skb);
 	int			(*extract_input)(struct xfrm_state *x,
 						 struct sk_buff *skb);
@@ -1540,7 +1540,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 
 int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
-int xfrm4_output(struct sk_buff *skb);
+int xfrm4_output(struct sock *sk, struct sk_buff *skb);
 int xfrm4_output_finish(struct sk_buff *skb);
 int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
 int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol);
@@ -1565,7 +1565,7 @@ __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
 __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
 int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
-int xfrm6_output(struct sk_buff *skb);
+int xfrm6_output(struct sock *sk, struct sk_buff *skb);
 int xfrm6_output_finish(struct sk_buff *skb);
 int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
 			  u8 **prevhdr);
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 0a4edfe8af51..d34cf2df093b 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -31,7 +31,7 @@ enum scsi_timeouts {
  * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit
  * is totally arbitrary, a setting of 2048 will get you at least 8mb ios.
  */
-#ifdef ARCH_HAS_SG_CHAIN
+#ifdef CONFIG_ARCH_HAS_SG_CHAIN
 #define SCSI_MAX_SG_CHAIN_SEGMENTS	2048
 #else
 #define SCSI_MAX_SG_CHAIN_SEGMENTS	SCSI_MAX_SG_SEGMENTS
diff --git a/include/sound/atmel-ac97c.h b/include/sound/atmel-ac97c.h
index e6aabdb45865..00e6c289a936 100644
--- a/include/sound/atmel-ac97c.h
+++ b/include/sound/atmel-ac97c.h
@@ -23,7 +23,6 @@
  * @reset_pin: GPIO pin wired to the reset input on the external AC97 codec,
  *             optional to use, set to -ENODEV if not in use. AC97 layer will
  *             try to do a software reset of the external codec anyway.
- * @flags: Flags for which directions should be enabled.
  *
  * If the user do not want to use a DMA channel for playback or capture, i.e.
  * only one feature is required on the board. The slave for playback or capture
@@ -33,7 +32,6 @@
 struct ac97c_platform_data {
 	struct dw_dma_slave	rx_dws;
 	struct dw_dma_slave	tx_dws;
-	unsigned int 		flags;
 	int			reset_pin;
 };
 
diff --git a/include/sound/rt5640.h b/include/sound/rt5640.h
index 27cc75ed67f8..59d26dd81e45 100644
--- a/include/sound/rt5640.h
+++ b/include/sound/rt5640.h
@@ -16,6 +16,10 @@ struct rt5640_platform_data {
 	bool in1_diff;
 	bool in2_diff;
 
+	bool dmic_en;
+	bool dmic1_data_pin; /* 0 = IN1P; 1 = GPIO3 */
+	bool dmic2_data_pin; /* 0 = IN1N; 1 = GPIO4 */
+
 	int ldo1_en; /* GPIO for LDO1_EN */
 };
 
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index ef78f562f4a8..5ec03b5e2054 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -107,10 +107,6 @@ struct device;
 {	.id = snd_soc_dapm_mux, .name = wname, \
 	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
 	.kcontrol_news = wcontrols, .num_kcontrols = 1}
-#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
-	SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
-#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
-	SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
 
 /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
 #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
@@ -166,10 +162,6 @@ struct device;
 	SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
 	.kcontrol_news = wcontrols, .num_kcontrols = 1, \
 	.event = wevent, .event_flags = wflags}
-#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
-	wevent, wflags) \
-	SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, wevent, \
-		wflags)
 
 /* additional sequencing control within an event type */
 #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
@@ -305,16 +297,12 @@ struct device;
  	.get = snd_soc_dapm_get_enum_double, \
  	.put = snd_soc_dapm_put_enum_double, \
   	.private_value = (unsigned long)&xenum }
-#define SOC_DAPM_ENUM_VIRT(xname, xenum) \
-	SOC_DAPM_ENUM(xname, xenum)
 #define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_enum_double, \
 	.get = xget, \
 	.put = xput, \
 	.private_value = (unsigned long)&xenum }
-#define SOC_DAPM_VALUE_ENUM(xname, xenum) \
-	SOC_DAPM_ENUM(xname, xenum)
 #define SOC_DAPM_PIN_SWITCH(xname) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \
 	.info = snd_soc_dapm_info_pin_switch, \
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 0b83168d8ff4..488e749ed41d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -196,8 +196,6 @@
 	.info = snd_soc_info_enum_double, \
 	.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
 	.private_value = (unsigned long)&xenum }
-#define SOC_VALUE_ENUM(xname, xenum) \
-	SOC_ENUM(xname, xenum)
 #define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
 	 xhandler_get, xhandler_put) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -393,12 +391,6 @@ int devm_snd_soc_register_component(struct device *dev,
 			 const struct snd_soc_component_driver *cmpnt_drv,
 			 struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_component(struct device *dev);
-int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
-				    unsigned int reg);
-int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
-				    unsigned int reg);
-int snd_soc_codec_writable_register(struct snd_soc_codec *codec,
-				    unsigned int reg);
 int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 			       struct regmap *regmap);
 int snd_soc_cache_sync(struct snd_soc_codec *codec);
@@ -469,12 +461,12 @@ static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
 #endif
 
 /* codec register bit access */
-int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
+int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
 				unsigned int mask, unsigned int value);
 int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
-			       unsigned short reg, unsigned int mask,
+			       unsigned int reg, unsigned int mask,
 			       unsigned int value);
-int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
+int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
 				unsigned int mask, unsigned int value);
 
 int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
@@ -668,6 +660,7 @@ struct snd_soc_component {
 	unsigned int active;
 
 	unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
+	unsigned int registered_as_component:1;
 
 	struct list_head list;
 
@@ -692,9 +685,6 @@ struct snd_soc_codec {
 	struct list_head list;
 	struct list_head card_list;
 	int num_dai;
-	int (*volatile_register)(struct snd_soc_codec *, unsigned int);
-	int (*readable_register)(struct snd_soc_codec *, unsigned int);
-	int (*writable_register)(struct snd_soc_codec *, unsigned int);
 
 	/* runtime */
 	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
@@ -754,13 +744,9 @@ struct snd_soc_codec_driver {
 		unsigned int freq_in, unsigned int freq_out);
 
 	/* codec IO */
+	struct regmap *(*get_regmap)(struct device *);
 	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
 	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
-	int (*display_register)(struct snd_soc_codec *, char *,
-				size_t, unsigned int);
-	int (*volatile_register)(struct snd_soc_codec *, unsigned int);
-	int (*readable_register)(struct snd_soc_codec *, unsigned int);
-	int (*writable_register)(struct snd_soc_codec *, unsigned int);
 	unsigned int reg_cache_size;
 	short reg_cache_step;
 	short reg_word_size;
@@ -791,6 +777,7 @@ struct snd_soc_platform_driver {
 	int (*remove)(struct snd_soc_platform *);
 	int (*suspend)(struct snd_soc_dai *dai);
 	int (*resume)(struct snd_soc_dai *dai);
+	struct snd_soc_component_driver component_driver;
 
 	/* pcm creation and destruction */
 	int (*pcm_new)(struct snd_soc_pcm_runtime *);
@@ -844,6 +831,8 @@ struct snd_soc_platform {
 	struct list_head list;
 	struct list_head card_list;
 
+	struct snd_soc_component component;
+
 	struct snd_soc_dapm_context dapm;
 
 #ifdef CONFIG_DEBUG_FS
@@ -1120,6 +1109,19 @@ static inline struct snd_soc_codec *snd_soc_component_to_codec(
 	return container_of(component, struct snd_soc_codec, component);
 }
 
+/**
+ * snd_soc_component_to_platform() - Casts a component to the platform it is embedded in
+ * @component: The component to cast to a platform
+ *
+ * This function must only be used on components that are known to be platforms.
+ * Otherwise the behavior is undefined.
+ */
+static inline struct snd_soc_platform *snd_soc_component_to_platform(
+	struct snd_soc_component *component)
+{
+	return container_of(component, struct snd_soc_platform, component);
+}
+
 /* codec IO */
 unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
 unsigned int snd_soc_write(struct snd_soc_codec *codec,
@@ -1228,6 +1230,34 @@ static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec)
 	return snd_soc_component_is_active(&codec->component);
 }
 
+/**
+ * snd_soc_kcontrol_codec() - Returns the CODEC that registered the control
+ * @kcontrol: The control for which to get the CODEC
+ *
+ * Note: This function will only work correctly if the control has been
+ * registered with snd_soc_add_codec_controls() or via table based setup of
+ * snd_soc_codec_driver. Otherwise the behavior is undefined.
+ */
+static inline struct snd_soc_codec *snd_soc_kcontrol_codec(
+	struct snd_kcontrol *kcontrol)
+{
+	return snd_kcontrol_chip(kcontrol);
+}
+
+/**
+ * snd_soc_kcontrol_platform() - Returns the platform that registerd the control
+ * @kcontrol: The control for which to get the platform
+ *
+ * Note: This function will only work correctly if the control has been
+ * registered with snd_soc_add_platform_controls() or via table based setup of
+ * a snd_soc_platform_driver. Otherwise the behavior is undefined.
+ */
+static inline struct snd_soc_platform *snd_soc_kcontrol_platform(
+	struct snd_kcontrol *kcontrol)
+{
+	return snd_kcontrol_chip(kcontrol);
+}
+
 int snd_soc_util_init(void);
 void snd_soc_util_exit(void);
 
diff --git a/include/sound/sta350.h b/include/sound/sta350.h
new file mode 100644
index 000000000000..3a3298106b22
--- /dev/null
+++ b/include/sound/sta350.h
@@ -0,0 +1,52 @@
+/*
+ * Platform data for ST STA350 ASoC codec driver.
+ *
+ * Copyright: 2014 Raumfeld GmbH
+ * Author: Sven Brandau <info@brandau.biz>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef __LINUX_SND__STA350_H
+#define __LINUX_SND__STA350_H
+
+#define STA350_OCFG_2CH		0
+#define STA350_OCFG_2_1CH	1
+#define STA350_OCFG_1CH		3
+
+#define STA350_OM_CH1		0
+#define STA350_OM_CH2		1
+#define STA350_OM_CH3		2
+
+#define STA350_THERMAL_ADJUSTMENT_ENABLE	1
+#define STA350_THERMAL_RECOVERY_ENABLE		2
+#define STA350_FAULT_DETECT_RECOVERY_BYPASS	1
+
+#define STA350_FFX_PM_DROP_COMP			0
+#define STA350_FFX_PM_TAPERED_COMP		1
+#define STA350_FFX_PM_FULL_POWER		2
+#define STA350_FFX_PM_VARIABLE_DROP_COMP	3
+
+
+struct sta350_platform_data {
+	u8 output_conf;
+	u8 ch1_output_mapping;
+	u8 ch2_output_mapping;
+	u8 ch3_output_mapping;
+	u8 ffx_power_output_mode;
+	u8 drop_compensation_ns;
+	unsigned int thermal_warning_recovery:1;
+	unsigned int thermal_warning_adjustment:1;
+	unsigned int fault_detect_recovery:1;
+	unsigned int oc_warning_adjustment:1;
+	unsigned int max_power_use_mpcc:1;
+	unsigned int max_power_correction:1;
+	unsigned int am_reduction_mode:1;
+	unsigned int odd_pwm_speed_mode:1;
+	unsigned int distortion_compensation:1;
+	unsigned int invalid_input_detect_mute:1;
+};
+
+#endif /* __LINUX_SND__STA350_H */
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 010ea89eeb0e..d4f70a7fe876 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -16,15 +16,6 @@ struct mpage_da_data;
 struct ext4_map_blocks;
 struct extent_status;
 
-/* shim until we merge in the xfs_collapse_range branch */
-#ifndef FALLOC_FL_COLLAPSE_RANGE
-#define FALLOC_FL_COLLAPSE_RANGE	0x08
-#endif
-
-#ifndef FALLOC_FL_ZERO_RANGE
-#define FALLOC_FL_ZERO_RANGE           0x10
-#endif
-
 #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
 
 #define show_mballoc_flags(flags) __print_flags(flags, "|",	\
@@ -45,7 +36,7 @@ struct extent_status;
 
 #define show_map_flags(flags) __print_flags(flags, "|",			\
 	{ EXT4_GET_BLOCKS_CREATE,		"CREATE" },		\
-	{ EXT4_GET_BLOCKS_UNINIT_EXT,		"UNINIT" },		\
+	{ EXT4_GET_BLOCKS_UNWRIT_EXT,		"UNWRIT" },		\
 	{ EXT4_GET_BLOCKS_DELALLOC_RESERVE,	"DELALLOC" },		\
 	{ EXT4_GET_BLOCKS_PRE_IO,		"PRE_IO" },		\
 	{ EXT4_GET_BLOCKS_CONVERT,		"CONVERT" },		\
@@ -60,7 +51,6 @@ struct extent_status;
 	{ EXT4_MAP_MAPPED,	"M" },			\
 	{ EXT4_MAP_UNWRITTEN,	"U" },			\
 	{ EXT4_MAP_BOUNDARY,	"B" },			\
-	{ EXT4_MAP_UNINIT,	"u" },			\
 	{ EXT4_MAP_FROM_CLUSTER, "C" })
 
 #define show_free_flags(flags) __print_flags(flags, "|",	\
@@ -1506,7 +1496,7 @@ DEFINE_EVENT(ext4__truncate, ext4_truncate_exit,
 	TP_ARGS(inode)
 );
 
-/* 'ux' is the uninitialized extent. */
+/* 'ux' is the unwritten extent. */
 TRACE_EVENT(ext4_ext_convert_to_initialized_enter,
 	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map,
 		 struct ext4_extent *ux),
@@ -1542,7 +1532,7 @@ TRACE_EVENT(ext4_ext_convert_to_initialized_enter,
 );
 
 /*
- * 'ux' is the uninitialized extent.
+ * 'ux' is the unwritten extent.
  * 'ix' is the initialized extent to which blocks are transferred.
  */
 TRACE_EVENT(ext4_ext_convert_to_initialized_fastpath,
@@ -1820,7 +1810,7 @@ DEFINE_EVENT(ext4__trim, ext4_trim_all_free,
 	TP_ARGS(sb, group, start, len)
 );
 
-TRACE_EVENT(ext4_ext_handle_uninitialized_extents,
+TRACE_EVENT(ext4_ext_handle_unwritten_extents,
 	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int flags,
 		 unsigned int allocated, ext4_fsblk_t newblock),
 
diff --git a/include/trace/events/gfpflags.h b/include/trace/events/gfpflags.h
index 1eddbf1557f2..d6fd8e5b14b7 100644
--- a/include/trace/events/gfpflags.h
+++ b/include/trace/events/gfpflags.h
@@ -34,7 +34,6 @@
 	{(unsigned long)__GFP_HARDWALL,		"GFP_HARDWALL"},	\
 	{(unsigned long)__GFP_THISNODE,		"GFP_THISNODE"},	\
 	{(unsigned long)__GFP_RECLAIMABLE,	"GFP_RECLAIMABLE"},	\
-	{(unsigned long)__GFP_KMEMCG,		"GFP_KMEMCG"},		\
 	{(unsigned long)__GFP_MOVABLE,		"GFP_MOVABLE"},		\
 	{(unsigned long)__GFP_NOTRACK,		"GFP_NOTRACK"},		\
 	{(unsigned long)__GFP_NO_KSWAPD,	"GFP_NO_KSWAPD"},	\
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 126bfaa8bb6b..8a3e4ef00c3d 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -337,6 +337,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_EXEC_NO_RELOC	 25
 #define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
 #define I915_PARAM_HAS_WT     	 	 27
+#define I915_PARAM_CMD_PARSER_VERSION	 28
 
 typedef struct drm_i915_getparam {
 	int param;
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 11917f747cb4..573dc363ac07 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -424,17 +424,4 @@ struct audit_rule_data {
 	char		buf[0];	/* string fields buffer */
 };
 
-/* audit_rule is supported to maintain backward compatibility with
- * userspace.  It supports integer fields only and corresponds to
- * AUDIT_ADD, AUDIT_DEL and AUDIT_LIST requests.
- */
-struct audit_rule {		/* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
-	__u32		flags;	/* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
-	__u32		action;	/* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
-	__u32		field_count;
-	__u32		mask[AUDIT_BITMASK_SIZE];
-	__u32		fields[AUDIT_MAX_FIELDS];
-	__u32		values[AUDIT_MAX_FIELDS];
-};
-
 #endif /* _UAPI_LINUX_AUDIT_H_ */
diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h
index 9beb7c991638..78e4a86030dd 100644
--- a/include/uapi/linux/hyperv.h
+++ b/include/uapi/linux/hyperv.h
@@ -305,6 +305,7 @@ enum hv_kvp_exchg_pool {
 #define HV_ERROR_DEVICE_NOT_CONNECTED	0x8007048F
 #define HV_INVALIDARG			0x80070057
 #define HV_GUID_NOTFOUND		0x80041002
+#define HV_ERROR_ALREADY_EXISTS		0x80070050
 
 #define ADDR_FAMILY_NONE	0x00
 #define ADDR_FAMILY_IPV4	0x01
diff --git a/init/Kconfig b/init/Kconfig
index 765018c24cf9..0f0f351029eb 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1255,6 +1255,77 @@ config CC_OPTIMIZE_FOR_SIZE
 
 	  If unsure, say N.
 
+config LTO_MENU
+	bool "Enable gcc link time optimization (LTO)"
+	# Only tested on X86 for now. For other architectures you likely
+	# have to fix some things first, like adding asmlinkages etc.
+	depends on X86
+	# lto does not support excluding flags for specific files
+	# right now. Can be removed if that is fixed.
+	depends on !FUNCTION_TRACER
+	help
+	  With this option gcc will do whole program optimizations for
+	  the whole kernel and module. This increases compile time, but can
+	  lead to better code. It allows gcc to inline functions between
+	  different files and do other optimization.  It might also trigger
+	  bugs due to more aggressive optimization. It allows gcc to drop unused
+	  code. On smaller monolithic kernel configurations
+	  it usually leads to smaller kernels, especially when modules
+	  are disabled.
+
+	  With this option gcc will also do some global checking over
+	  different source files. It also disables a number of kernel
+	  features.
+
+	  This option is recommended for release builds. With LTO
+	  the kernel always has to be re-optimized (but not re-parsed)
+	  on each build.
+
+	  This requires a gcc 4.8 or later compiler and
+	  Linux binutils 2.21.51.0.3 or later.  gcc 4.9 builds significantly
+	  faster than 4.8 It does not currently work with a FSF release of
+	  binutils or with the gold linker.
+
+	  On larger configurations this may need more than 4GB of RAM.
+	  It will likely not work on those with a 32bit compiler.
+
+	  When the toolchain support is not available this will (hopefully)
+	  be automatically disabled.
+
+	  For more information see Documentation/lto-build
+
+config LTO_DISABLE
+         bool "Disable LTO again"
+         depends on LTO_MENU
+         default n
+         help
+           This option is merely here so that allyesconfig or allmodconfig do
+           not enable LTO. If you want to actually use LTO do not enable.
+
+config LTO
+	bool
+	default y
+	depends on LTO_MENU && !LTO_DISABLE
+
+config LTO_DEBUG
+	bool "Enable LTO compile time debugging"
+	depends on LTO
+	help
+	  Enable LTO debugging in the compiler. The compiler dumps
+	  some log files that make it easier to figure out LTO
+	  behavior. The log files also allow to reconstruct
+	  the global inlining and a global callgraph.
+	  They however add some (single threaded) cost to the
+	  compilation.  When in doubt do not enable.
+
+config LTO_CP_CLONE
+	bool "Allow aggressive cloning for function specialization"
+	depends on LTO
+	help
+	  Allow the compiler to clone and specialize functions for specific
+	  arguments when it determines these arguments are very commonly
+	  called.  Experimential. Will increase text size.
+
 config SYSCTL
 	bool
 
@@ -1646,6 +1717,18 @@ config MMAP_ALLOW_UNINITIALIZED
 
 	  See Documentation/nommu-mmap.txt for more information.
 
+config SYSTEM_TRUSTED_KEYRING
+	bool "Provide system-wide ring of trusted keys"
+	depends on KEYS
+	help
+	  Provide a system keyring to which trusted keys can be added.  Keys in
+	  the keyring are considered to be trusted.  Keys may be added at will
+	  by the kernel from compiled-in data and from hardware key stores, but
+	  userspace may only add extra keys if those keys can be verified by
+	  keys already in the keyring.
+
+	  Keys in this keyring are used by module signature checking.
+
 config PROFILING
 	bool "Profiling support"
 	help
@@ -1681,18 +1764,6 @@ config BASE_SMALL
 	default 0 if BASE_FULL
 	default 1 if !BASE_FULL
 
-config SYSTEM_TRUSTED_KEYRING
-	bool "Provide system-wide ring of trusted keys"
-	depends on KEYS
-	help
-	  Provide a system keyring to which trusted keys can be added.  Keys in
-	  the keyring are considered to be trusted.  Keys may be added at will
-	  by the kernel from compiled-in data and from hardware key stores, but
-	  userspace may only add extra keys if those keys can be verified by
-	  keys already in the keyring.
-
-	  Keys in this keyring are used by module signature checking.
-
 menuconfig MODULES
 	bool "Enable loadable module support"
 	option modules
@@ -1744,6 +1815,8 @@ config MODULE_FORCE_UNLOAD
 
 config MODVERSIONS
 	bool "Module versioning support"
+	# LTO should work with gcc 4.9
+	depends on !LTO
 	help
 	  Usually, you have to use modules compiled with your kernel.
 	  Saying Y here makes it sometimes possible to use modules
diff --git a/init/main.c b/init/main.c
index 9c7fd4c9249f..ba8798058748 100644
--- a/init/main.c
+++ b/init/main.c
@@ -77,6 +77,7 @@
 #include <linux/sched_clock.h>
 #include <linux/context_tracking.h>
 #include <linux/random.h>
+#include <linux/list.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -666,19 +667,83 @@ static void __init do_ctors(void)
 bool initcall_debug;
 core_param(initcall_debug, initcall_debug, bool, 0644);
 
+#ifdef CONFIG_KALLSYMS
+struct blacklist_entry {
+	struct list_head next;
+	char *buf;
+};
+
+static __initdata_or_module LIST_HEAD(blacklisted_initcalls);
+
+static int __init initcall_blacklist(char *str)
+{
+	char *str_entry;
+	struct blacklist_entry *entry;
+
+	/* str argument is a comma-separated list of functions */
+	do {
+		str_entry = strsep(&str, ",");
+		if (str_entry) {
+			pr_debug("blacklisting initcall %s\n", str_entry);
+			entry = alloc_bootmem(sizeof(*entry));
+			entry->buf = alloc_bootmem(strlen(str_entry) + 1);
+			strcpy(entry->buf, str_entry);
+			list_add(&entry->next, &blacklisted_initcalls);
+		}
+	} while (str_entry);
+
+	return 0;
+}
+
+static bool __init_or_module initcall_blacklisted(initcall_t fn)
+{
+	struct list_head *tmp;
+	struct blacklist_entry *entry;
+	char *fn_name;
+
+	fn_name = kasprintf(GFP_KERNEL, "%pf", fn);
+	if (!fn_name)
+		return false;
+
+	list_for_each(tmp, &blacklisted_initcalls) {
+		entry = list_entry(tmp, struct blacklist_entry, next);
+		if (!strcmp(fn_name, entry->buf)) {
+			pr_debug("initcall %s blacklisted\n", fn_name);
+			kfree(fn_name);
+			return true;
+		}
+	}
+
+	kfree(fn_name);
+	return false;
+}
+#else
+static int __init initcall_blacklist(char *str)
+{
+	pr_warn("initcall_blacklist requires CONFIG_KALLSYMS\n");
+	return 0;
+}
+
+static bool __init_or_module initcall_blacklisted(initcall_t fn)
+{
+	return false;
+}
+#endif
+__setup("initcall_blacklist=", initcall_blacklist);
+
 static int __init_or_module do_one_initcall_debug(initcall_t fn)
 {
 	ktime_t calltime, delta, rettime;
 	unsigned long long duration;
 	int ret;
 
-	pr_debug("calling  %pF @ %i\n", fn, task_pid_nr(current));
+	printk(KERN_DEBUG "calling  %pF @ %i\n", fn, task_pid_nr(current));
 	calltime = ktime_get();
 	ret = fn();
 	rettime = ktime_get();
 	delta = ktime_sub(rettime, calltime);
 	duration = (unsigned long long) ktime_to_ns(delta) >> 10;
-	pr_debug("initcall %pF returned %d after %lld usecs\n",
+	printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n",
 		 fn, ret, duration);
 
 	return ret;
@@ -690,6 +755,9 @@ int __init_or_module do_one_initcall(initcall_t fn)
 	int ret;
 	char msgbuf[64];
 
+	if (initcall_blacklisted(fn))
+		return -EPERM;
+
 	if (initcall_debug)
 		ret = do_one_initcall_debug(fn);
 	else
diff --git a/ipc/msg.c b/ipc/msg.c
index 649853105a5d..35e4018de53c 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -306,15 +306,14 @@ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
 SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg)
 {
 	struct ipc_namespace *ns;
-	struct ipc_ops msg_ops;
+	static const struct ipc_ops msg_ops = {
+		.getnew = newque,
+		.associate = msg_security,
+	};
 	struct ipc_params msg_params;
 
 	ns = current->nsproxy->ipc_ns;
 
-	msg_ops.getnew = newque;
-	msg_ops.associate = msg_security;
-	msg_ops.more_checks = NULL;
-
 	msg_params.key = key;
 	msg_params.flg = msgflg;
 
diff --git a/ipc/sem.c b/ipc/sem.c
index bee555417312..3fcbc96abee9 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -564,7 +564,11 @@ static inline int sem_more_checks(struct kern_ipc_perm *ipcp,
 SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
 {
 	struct ipc_namespace *ns;
-	struct ipc_ops sem_ops;
+	static const struct ipc_ops sem_ops = {
+		.getnew = newary,
+		.associate = sem_security,
+		.more_checks = sem_more_checks,
+	};
 	struct ipc_params sem_params;
 
 	ns = current->nsproxy->ipc_ns;
@@ -572,10 +576,6 @@ SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
 	if (nsems < 0 || nsems > ns->sc_semmsl)
 		return -EINVAL;
 
-	sem_ops.getnew = newary;
-	sem_ops.associate = sem_security;
-	sem_ops.more_checks = sem_more_checks;
-
 	sem_params.key = key;
 	sem_params.flg = semflg;
 	sem_params.u.nsems = nsems;
diff --git a/ipc/shm.c b/ipc/shm.c
index 76459616a7fa..b54c93f6d117 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -609,15 +609,15 @@ static inline int shm_more_checks(struct kern_ipc_perm *ipcp,
 SYSCALL_DEFINE3(shmget, key_t, key, size_t, size, int, shmflg)
 {
 	struct ipc_namespace *ns;
-	struct ipc_ops shm_ops;
+	static const struct ipc_ops shm_ops = {
+		.getnew = newseg,
+		.associate = shm_security,
+		.more_checks = shm_more_checks,
+	};
 	struct ipc_params shm_params;
 
 	ns = current->nsproxy->ipc_ns;
 
-	shm_ops.getnew = newseg;
-	shm_ops.associate = shm_security;
-	shm_ops.more_checks = shm_more_checks;
-
 	shm_params.key = key;
 	shm_params.flg = shmflg;
 	shm_params.u.size = size;
diff --git a/ipc/util.c b/ipc/util.c
index 2eb0d1eaa312..9b3fa38afe2c 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -317,7 +317,7 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
  * when the key is IPC_PRIVATE.
  */
 static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
-		struct ipc_ops *ops, struct ipc_params *params)
+		const struct ipc_ops *ops, struct ipc_params *params)
 {
 	int err;
 
@@ -344,7 +344,7 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
  */
 static int ipc_check_perms(struct ipc_namespace *ns,
 			   struct kern_ipc_perm *ipcp,
-			   struct ipc_ops *ops,
+			   const struct ipc_ops *ops,
 			   struct ipc_params *params)
 {
 	int err;
@@ -375,7 +375,7 @@ static int ipc_check_perms(struct ipc_namespace *ns,
  * On success, the ipc id is returned.
  */
 static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
-		struct ipc_ops *ops, struct ipc_params *params)
+		const struct ipc_ops *ops, struct ipc_params *params)
 {
 	struct kern_ipc_perm *ipcp;
 	int flg = params->flg;
@@ -678,7 +678,7 @@ out:
  * Common routine called by sys_msgget(), sys_semget() and sys_shmget().
  */
 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
-			struct ipc_ops *ops, struct ipc_params *params)
+			const struct ipc_ops *ops, struct ipc_params *params)
 {
 	if (params->key == IPC_PRIVATE)
 		return ipcget_new(ns, ids, ops, params);
diff --git a/ipc/util.h b/ipc/util.h
index 9c47d6f6c7b4..e1153ad574b7 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -201,7 +201,7 @@ static inline bool ipc_valid_object(struct kern_ipc_perm *perm)
 
 struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id);
 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
-			struct ipc_ops *ops, struct ipc_params *params);
+			const struct ipc_ops *ops, struct ipc_params *params);
 void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
 		void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
 #endif
diff --git a/kernel/exit.c b/kernel/exit.c
index 6ed6a1d552b5..ad7183a8dbbd 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -313,45 +313,6 @@ kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent)
 	}
 }
 
-/*
- * Let kernel threads use this to say that they allow a certain signal.
- * Must not be used if kthread was cloned with CLONE_SIGHAND.
- */
-int allow_signal(int sig)
-{
-	if (!valid_signal(sig) || sig < 1)
-		return -EINVAL;
-
-	spin_lock_irq(&current->sighand->siglock);
-	/* This is only needed for daemonize()'ed kthreads */
-	sigdelset(&current->blocked, sig);
-	/*
-	 * Kernel threads handle their own signals. Let the signal code
-	 * know it'll be handled, so that they don't get converted to
-	 * SIGKILL or just silently dropped.
-	 */
-	current->sighand->action[(sig)-1].sa.sa_handler = (void __user *)2;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	return 0;
-}
-
-EXPORT_SYMBOL(allow_signal);
-
-int disallow_signal(int sig)
-{
-	if (!valid_signal(sig) || sig < 1)
-		return -EINVAL;
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->sighand->action[(sig)-1].sa.sa_handler = SIG_IGN;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	return 0;
-}
-
-EXPORT_SYMBOL(disallow_signal);
-
 #ifdef CONFIG_MM_OWNER
 /*
  * A task is exiting.   If it owned this mm, find a new owner for the mm.
diff --git a/kernel/fork.c b/kernel/fork.c
index 54a8d26f612f..59e3dcc5b8f2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -150,15 +150,15 @@ void __weak arch_release_thread_info(struct thread_info *ti)
 static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
 						  int node)
 {
-	struct page *page = alloc_pages_node(node, THREADINFO_GFP_ACCOUNTED,
-					     THREAD_SIZE_ORDER);
+	struct page *page = alloc_kmem_pages_node(node, THREADINFO_GFP,
+						  THREAD_SIZE_ORDER);
 
 	return page ? page_address(page) : NULL;
 }
 
 static inline void free_thread_info(struct thread_info *ti)
 {
-	free_memcg_kmem_pages((unsigned long)ti, THREAD_SIZE_ORDER);
+	free_kmem_pages((unsigned long)ti, THREAD_SIZE_ORDER);
 }
 # else
 static struct kmem_cache *thread_info_cache;
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index d04ce8ac4399..32f65b7aed46 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -2,7 +2,7 @@ menu "GCOV-based kernel profiling"
 
 config GCOV_KERNEL
 	bool "Enable gcov-based kernel profiling"
-	depends on DEBUG_FS
+	depends on DEBUG_FS && !LTO
 	select CONSTRUCTORS if !UML
 	default n
 	---help---
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 6b375af4958d..c18c891766b5 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -285,10 +285,7 @@ static int wait_for_helper(void *data)
 	pid_t pid;
 
 	/* If SIGCLD is ignored sys_wait4 won't populate the status. */
-	spin_lock_irq(&current->sighand->siglock);
-	current->sighand->action[SIGCHLD-1].sa.sa_handler = SIG_DFL;
-	spin_unlock_irq(&current->sighand->siglock);
-
+	kernel_sigaction(SIGCHLD, SIG_DFL);
 	pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);
 	if (pid < 0) {
 		sub_info->retval = pid;
diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c
index e1191c996c59..5cf6731b98e9 100644
--- a/kernel/locking/mutex-debug.c
+++ b/kernel/locking/mutex-debug.c
@@ -71,18 +71,17 @@ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
 
 void debug_mutex_unlock(struct mutex *lock)
 {
-	if (unlikely(!debug_locks))
-		return;
+	if (likely(debug_locks)) {
+		DEBUG_LOCKS_WARN_ON(lock->magic != lock);
 
-	DEBUG_LOCKS_WARN_ON(lock->magic != lock);
+		if (!lock->owner)
+			DEBUG_LOCKS_WARN_ON(!lock->owner);
+		else
+			DEBUG_LOCKS_WARN_ON(lock->owner != current);
 
-	if (!lock->owner)
-		DEBUG_LOCKS_WARN_ON(!lock->owner);
-	else
-		DEBUG_LOCKS_WARN_ON(lock->owner != current);
-
-	DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
-	mutex_clear_owner(lock);
+		DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
+		mutex_clear_owner(lock);
+	}
 
 	/*
 	 * __mutex_slowpath_needs_to_unlock() is explicitly 0 for debug
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 268a45ea238c..00ac2481795b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1500,9 +1500,7 @@ void scheduler_ipi(void)
 	 */
 	preempt_fold_need_resched();
 
-	if (llist_empty(&this_rq()->wake_list)
-			&& !tick_nohz_full_cpu(smp_processor_id())
-			&& !got_nohz_idle_kick())
+	if (llist_empty(&this_rq()->wake_list) && !got_nohz_idle_kick())
 		return;
 
 	/*
@@ -1519,7 +1517,6 @@ void scheduler_ipi(void)
 	 * somewhat pessimize the simple resched case.
 	 */
 	irq_enter();
-	tick_nohz_full_check();
 	sched_ttwu_pending();
 
 	/*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7e9bd0b1fa9e..4f14a656a720 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1497,7 +1497,7 @@ static void task_numa_placement(struct task_struct *p)
 	/* If the task is part of a group prevent parallel updates to group stats */
 	if (p->numa_group) {
 		group_lock = &p->numa_group->lock;
-		spin_lock(group_lock);
+		spin_lock_irq(group_lock);
 	}
 
 	/* Find the node with the highest number of faults */
@@ -1572,7 +1572,7 @@ static void task_numa_placement(struct task_struct *p)
 			}
 		}
 
-		spin_unlock(group_lock);
+		spin_unlock_irq(group_lock);
 	}
 
 	/* Preferred node as the node with the most faults */
@@ -1677,7 +1677,8 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
 	if (!join)
 		return;
 
-	double_lock(&my_grp->lock, &grp->lock);
+	BUG_ON(irqs_disabled());
+	double_lock_irq(&my_grp->lock, &grp->lock);
 
 	for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++) {
 		my_grp->faults[i] -= p->numa_faults_memory[i];
@@ -1691,7 +1692,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
 	grp->nr_tasks++;
 
 	spin_unlock(&my_grp->lock);
-	spin_unlock(&grp->lock);
+	spin_unlock_irq(&grp->lock);
 
 	rcu_assign_pointer(p->numa_group, grp);
 
@@ -1710,14 +1711,14 @@ void task_numa_free(struct task_struct *p)
 	void *numa_faults = p->numa_faults_memory;
 
 	if (grp) {
-		spin_lock(&grp->lock);
+		spin_lock_irq(&grp->lock);
 		for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
 			grp->faults[i] -= p->numa_faults_memory[i];
 		grp->total_faults -= p->total_numa_faults;
 
 		list_del(&p->numa_entry);
 		grp->nr_tasks--;
-		spin_unlock(&grp->lock);
+		spin_unlock_irq(&grp->lock);
 		rcu_assign_pointer(p->numa_group, NULL);
 		put_numa_group(grp);
 	}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index c9007f28d3a2..6089e007a6eb 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1225,7 +1225,7 @@ static inline void inc_nr_running(struct rq *rq)
 		if (tick_nohz_full_cpu(rq->cpu)) {
 			/* Order rq->nr_running write against the IPI */
 			smp_wmb();
-			smp_send_reschedule(rq->cpu);
+			tick_nohz_full_kick_cpu(rq->cpu);
 		}
        }
 #endif
@@ -1385,6 +1385,15 @@ static inline void double_lock(spinlock_t *l1, spinlock_t *l2)
 	spin_lock_nested(l2, SINGLE_DEPTH_NESTING);
 }
 
+static inline void double_lock_irq(spinlock_t *l1, spinlock_t *l2)
+{
+	if (l1 > l2)
+		swap(l1, l2);
+
+	spin_lock_irq(l1);
+	spin_lock_nested(l2, SINGLE_DEPTH_NESTING);
+}
+
 static inline void double_raw_lock(raw_spinlock_t *l1, raw_spinlock_t *l2)
 {
 	if (l1 > l2)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index d8d046c0726a..b35c21503a36 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -69,18 +69,17 @@ static void populate_seccomp_data(struct seccomp_data *sd)
 {
 	struct task_struct *task = current;
 	struct pt_regs *regs = task_pt_regs(task);
+	unsigned long args[6];
 
 	sd->nr = syscall_get_nr(task, regs);
 	sd->arch = syscall_get_arch();
-
-	/* Unroll syscall_get_args to help gcc on arm. */
-	syscall_get_arguments(task, regs, 0, 1, (unsigned long *) &sd->args[0]);
-	syscall_get_arguments(task, regs, 1, 1, (unsigned long *) &sd->args[1]);
-	syscall_get_arguments(task, regs, 2, 1, (unsigned long *) &sd->args[2]);
-	syscall_get_arguments(task, regs, 3, 1, (unsigned long *) &sd->args[3]);
-	syscall_get_arguments(task, regs, 4, 1, (unsigned long *) &sd->args[4]);
-	syscall_get_arguments(task, regs, 5, 1, (unsigned long *) &sd->args[5]);
-
+	syscall_get_arguments(task, regs, 0, 6, args);
+	sd->args[0] = args[0];
+	sd->args[1] = args[1];
+	sd->args[2] = args[2];
+	sd->args[3] = args[3];
+	sd->args[4] = args[4];
+	sd->args[5] = args[5];
 	sd->instruction_pointer = KSTK_EIP(task);
 }
 
@@ -256,6 +255,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
 		goto free_prog;
 
 	/* Allocate a new seccomp_filter */
+	ret = -ENOMEM;
 	filter = kzalloc(sizeof(struct seccomp_filter) +
 			 sizeof(struct sock_filter_int) * new_len,
 			 GFP_KERNEL|__GFP_NOWARN);
@@ -265,6 +265,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
 	ret = sk_convert_filter(fp, fprog->len, filter->insnsi, &new_len);
 	if (ret)
 		goto free_filter;
+	kfree(fp);
 
 	atomic_set(&filter->usage, 1);
 	filter->len = new_len;
diff --git a/kernel/signal.c b/kernel/signal.c
index 6ea13c09ae56..45dba6165ace 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -705,11 +705,8 @@ void signal_wake_up_state(struct task_struct *t, unsigned int state)
  * Returns 1 if any signals were found.
  *
  * All callers must be holding the siglock.
- *
- * This version takes a sigset mask and looks at all signals,
- * not just those in the first mask word.
  */
-static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)
+static int flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
 {
 	struct sigqueue *q, *n;
 	sigset_t m;
@@ -727,29 +724,6 @@ static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)
 	}
 	return 1;
 }
-/*
- * Remove signals in mask from the pending set and queue.
- * Returns 1 if any signals were found.
- *
- * All callers must be holding the siglock.
- */
-static int rm_from_queue(unsigned long mask, struct sigpending *s)
-{
-	struct sigqueue *q, *n;
-
-	if (!sigtestsetmask(&s->signal, mask))
-		return 0;
-
-	sigdelsetmask(&s->signal, mask);
-	list_for_each_entry_safe(q, n, &s->list, list) {
-		if (q->info.si_signo < SIGRTMIN &&
-		    (mask & sigmask(q->info.si_signo))) {
-			list_del_init(&q->list);
-			__sigqueue_free(q);
-		}
-	}
-	return 1;
-}
 
 static inline int is_si_special(const struct siginfo *info)
 {
@@ -861,6 +835,7 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
 {
 	struct signal_struct *signal = p->signal;
 	struct task_struct *t;
+	sigset_t flush;
 
 	if (signal->flags & (SIGNAL_GROUP_EXIT | SIGNAL_GROUP_COREDUMP)) {
 		if (signal->flags & SIGNAL_GROUP_COREDUMP)
@@ -872,26 +847,25 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
 		/*
 		 * This is a stop signal.  Remove SIGCONT from all queues.
 		 */
-		rm_from_queue(sigmask(SIGCONT), &signal->shared_pending);
-		t = p;
-		do {
-			rm_from_queue(sigmask(SIGCONT), &t->pending);
-		} while_each_thread(p, t);
+		siginitset(&flush, sigmask(SIGCONT));
+		flush_sigqueue_mask(&flush, &signal->shared_pending);
+		for_each_thread(p, t)
+			flush_sigqueue_mask(&flush, &t->pending);
 	} else if (sig == SIGCONT) {
 		unsigned int why;
 		/*
 		 * Remove all stop signals from all queues, wake all threads.
 		 */
-		rm_from_queue(SIG_KERNEL_STOP_MASK, &signal->shared_pending);
-		t = p;
-		do {
+		siginitset(&flush, SIG_KERNEL_STOP_MASK);
+		flush_sigqueue_mask(&flush, &signal->shared_pending);
+		for_each_thread(p, t) {
+			flush_sigqueue_mask(&flush, &t->pending);
 			task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING);
-			rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
 			if (likely(!(t->ptrace & PT_SEIZED)))
 				wake_up_state(t, __TASK_STOPPED);
 			else
 				ptrace_trap_notify(t);
-		} while_each_thread(p, t);
+		}
 
 		/*
 		 * Notify the parent with CLD_CONTINUED if we were stopped.
@@ -2854,7 +2828,7 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
 
 		spin_lock_irq(&tsk->sighand->siglock);
 		__set_task_blocked(tsk, &tsk->real_blocked);
-		siginitset(&tsk->real_blocked, 0);
+		sigemptyset(&tsk->real_blocked);
 		sig = dequeue_signal(tsk, &mask, info);
 	}
 	spin_unlock_irq(&tsk->sighand->siglock);
@@ -3091,18 +3065,39 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
 }
 #endif
 
+/*
+ * For kthreads only, must not be used if cloned with CLONE_SIGHAND
+ */
+void kernel_sigaction(int sig, __sighandler_t action)
+{
+	spin_lock_irq(&current->sighand->siglock);
+	current->sighand->action[sig - 1].sa.sa_handler = action;
+	if (action == SIG_IGN) {
+		sigset_t mask;
+
+		sigemptyset(&mask);
+		sigaddset(&mask, sig);
+
+		flush_sigqueue_mask(&mask, &current->signal->shared_pending);
+		flush_sigqueue_mask(&mask, &current->pending);
+		recalc_sigpending();
+	}
+	spin_unlock_irq(&current->sighand->siglock);
+}
+EXPORT_SYMBOL(kernel_sigaction);
+
 int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 {
-	struct task_struct *t = current;
+	struct task_struct *p = current, *t;
 	struct k_sigaction *k;
 	sigset_t mask;
 
 	if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
 		return -EINVAL;
 
-	k = &t->sighand->action[sig-1];
+	k = &p->sighand->action[sig-1];
 
-	spin_lock_irq(&current->sighand->siglock);
+	spin_lock_irq(&p->sighand->siglock);
 	if (oact)
 		*oact = *k;
 
@@ -3121,21 +3116,20 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 		 *   (for example, SIGCHLD), shall cause the pending signal to
 		 *   be discarded, whether or not it is blocked"
 		 */
-		if (sig_handler_ignored(sig_handler(t, sig), sig)) {
+		if (sig_handler_ignored(sig_handler(p, sig), sig)) {
 			sigemptyset(&mask);
 			sigaddset(&mask, sig);
-			rm_from_queue_full(&mask, &t->signal->shared_pending);
-			do {
-				rm_from_queue_full(&mask, &t->pending);
-			} while_each_thread(current, t);
+			flush_sigqueue_mask(&mask, &p->signal->shared_pending);
+			for_each_thread(p, t)
+				flush_sigqueue_mask(&mask, &t->pending);
 		}
 	}
 
-	spin_unlock_irq(&current->sighand->siglock);
+	spin_unlock_irq(&p->sighand->siglock);
 	return 0;
 }
 
-static int 
+static int
 do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp)
 {
 	stack_t oss;
diff --git a/kernel/smp.c b/kernel/smp.c
index 06d574e42c72..7589be5b6a1d 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -265,6 +265,48 @@ int smp_call_function_single_async(int cpu, struct call_single_data *csd)
 }
 EXPORT_SYMBOL_GPL(smp_call_function_single_async);
 
+void generic_smp_queue_function_single_interrupt(void *info)
+{
+	struct queue_single_data *qsd = info;
+
+	WARN_ON_ONCE(xchg(&qsd->pending, 0) != 1);
+	qsd->func(qsd);
+}
+
+/**
+ * smp_queue_function_single - Queue an asynchronous function to run on a
+ * 				specific CPU unless it's already pending.
+ * @cpu: The CPU to run on.
+ * @qsd: Pre-allocated and setup data structure
+ *
+ * Like smp_call_function_single_async() but the call to the function is
+ * serialized and won't be queued if it is already pending. In the latter case,
+ * ordering is still guaranteed such that the pending call will see the new
+ * data we expect it to.
+ *
+ * This must not be called on offline CPUs.
+ *
+ * Returns 0 when function is successfully queued or already pending, else a
+ * negative status code.
+ */
+int smp_queue_function_single(int cpu, struct queue_single_data *qsd)
+{
+	int err;
+
+	if (cmpxchg(&qsd->pending, 0, 1))
+		return 0;
+
+	preempt_disable();
+	err = generic_exec_single(cpu, &qsd->data, generic_smp_queue_function_single_interrupt, qsd, 0);
+	preempt_enable();
+
+	/* Reset in case of error. This must not be called on offline CPUs */
+	if (err)
+		qsd->pending = 0;
+
+	return err;
+}
+
 /*
  * smp_call_function_any - Run a function on any of the given cpus
  * @mask: The mask of cpus it can run on.
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 4d23dc4d8139..5038b4d3b76d 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -154,6 +154,10 @@ void __init sched_clock_register(u64 (*read)(void), int bits,
 	raw_write_seqcount_end(&cd.seq);
 
 	r = rate;
+	/*
+	 * Use 4MHz instead of 1MHz so that things like 1.832Mhz show as
+	 * 1832Khz
+	 */
 	if (r >= 4000000) {
 		r /= 1000000;
 		r_unit = 'M';
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 015661279b68..0a0608edeb26 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -276,7 +276,7 @@ static bool tick_check_preferred(struct clock_event_device *curdev,
 bool tick_check_replacement(struct clock_event_device *curdev,
 			    struct clock_event_device *newdev)
 {
-	if (tick_check_percpu(curdev, newdev, smp_processor_id()))
+	if (!tick_check_percpu(curdev, newdev, smp_processor_id()))
 		return false;
 
 	return tick_check_preferred(curdev, newdev);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 9f8af69c67ec..c12c00641358 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -84,6 +84,9 @@ static void tick_do_update_jiffies64(ktime_t now)
 
 		/* Keep the tick_next_period variable up to date */
 		tick_next_period = ktime_add(last_jiffies_update, tick_period);
+	} else {
+		write_sequnlock(&jiffies_lock);
+		return;
 	}
 	write_sequnlock(&jiffies_lock);
 	update_wall_time();
@@ -230,6 +233,27 @@ void tick_nohz_full_kick(void)
 		irq_work_queue(&__get_cpu_var(nohz_full_kick_work));
 }
 
+static void nohz_full_kick_queue(struct queue_single_data *qsd)
+{
+	__tick_nohz_full_check();
+}
+
+static DEFINE_PER_CPU(struct queue_single_data, nohz_full_kick_qsd) = {
+	.func = nohz_full_kick_queue,
+};
+
+void tick_nohz_full_kick_cpu(int cpu)
+{
+	if (!tick_nohz_full_cpu(cpu))
+		return;
+
+	if (cpu == smp_processor_id()) {
+		irq_work_queue(&__get_cpu_var(nohz_full_kick_work));
+	} else {
+		smp_queue_function_single(cpu, &per_cpu(nohz_full_kick_qsd, cpu));
+	}
+}
+
 static void nohz_full_kick_ipi(void *info)
 {
 	__tick_nohz_full_check();
@@ -967,7 +991,7 @@ static void tick_nohz_switch_to_nohz(void)
 	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
 	ktime_t next;
 
-	if (!tick_nohz_active)
+	if (!tick_nohz_enabled)
 		return;
 
 	local_irq_disable();
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 0d8f6023fd8d..bf71b4b2d632 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -152,7 +152,7 @@ static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
 
 	/* Find the matching extent */
 	extents = map->nr_extents;
-	smp_read_barrier_depends();
+	smp_rmb();
 	for (idx = 0; idx < extents; idx++) {
 		first = map->extent[idx].first;
 		last = first + map->extent[idx].count - 1;
@@ -176,7 +176,7 @@ static u32 map_id_down(struct uid_gid_map *map, u32 id)
 
 	/* Find the matching extent */
 	extents = map->nr_extents;
-	smp_read_barrier_depends();
+	smp_rmb();
 	for (idx = 0; idx < extents; idx++) {
 		first = map->extent[idx].first;
 		last = first + map->extent[idx].count - 1;
@@ -199,7 +199,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id)
 
 	/* Find the matching extent */
 	extents = map->nr_extents;
-	smp_read_barrier_depends();
+	smp_rmb();
 	for (idx = 0; idx < extents; idx++) {
 		first = map->extent[idx].lower_first;
 		last = first + map->extent[idx].count - 1;
@@ -615,9 +615,8 @@ static ssize_t map_write(struct file *file, const char __user *buf,
 	 * were written before the count of the extents.
 	 *
 	 * To achieve this smp_wmb() is used on guarantee the write
-	 * order and smp_read_barrier_depends() is guaranteed that we
-	 * don't have crazy architectures returning stale data.
-	 *
+	 * order and smp_rmb() is guaranteed that we don't have crazy
+	 * architectures returning stale data.
 	 */
 	mutex_lock(&id_map_mutex);
 
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index e90089fd78e0..18bc5c2a26df 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -239,10 +239,12 @@ static void watchdog_overflow_callback(struct perf_event *event,
 		if (__this_cpu_read(hard_watchdog_warn) == true)
 			return;
 
-		if (hardlockup_panic)
+		if (hardlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
-		else
+		} else {
 			WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
+		}
 
 		__this_cpu_write(hard_watchdog_warn, true);
 		return;
@@ -323,8 +325,10 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 		else
 			dump_stack();
 
-		if (softlockup_panic)
+		if (softlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("softlockup: hung tasks");
+		}
 		__this_cpu_write(soft_watchdog_warn, true);
 	} else
 		__this_cpu_write(soft_watchdog_warn, false);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0ee63af30bd1..3150b217c936 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -4100,7 +4100,8 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
 	if (!pwq) {
 		pr_warning("workqueue: allocation failed while updating NUMA affinity of \"%s\"\n",
 			   wq->name);
-		goto out_unlock;
+		mutex_lock(&wq->mutex);
+		goto use_dfl_pwq;
 	}
 
 	/*
diff --git a/lib/Kconfig b/lib/Kconfig
index 4771fb3f4da4..e5ae36dcbf01 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -177,6 +177,13 @@ config CRC8
 	  when they need to do cyclic redundancy check according CRC8
 	  algorithm. Module will be called crc8.
 
+config CRC64_ECMA
+	tristate "CRC64 ECMA function"
+	help
+	  This option provides CRC64 ECMA function. Drivers may select this
+	  when they need to do cyclic redundancy check according to the CRC64
+	  ECMA algorithm.
+
 config AUDIT_GENERIC
 	bool
 	depends on AUDIT && !AUDIT_ARCH
@@ -460,4 +467,11 @@ config UCS2_STRING
 
 source "lib/fonts/Kconfig"
 
+#
+# sg chaining option
+#
+
+config ARCH_HAS_SG_CHAIN
+	def_bool n
+
 endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 140b66a874c1..cd5c82988d68 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -180,7 +180,7 @@ config STRIP_ASM_SYMS
 
 config READABLE_ASM
         bool "Generate readable assembler code"
-        depends on DEBUG_KERNEL
+        depends on DEBUG_KERNEL && !LTO
         help
           Disable some compiler optimizations that tend to generate human unreadable
           assembler output. This may make the kernel slightly slower, but it helps
@@ -501,12 +501,21 @@ config DEBUG_VM
 
 	  If unsure, say N.
 
+config DEBUG_VM_VMACACHE
+	bool "Debug VMA caching"
+	depends on DEBUG_VM
+	help
+	  Enable this to turn on VMA caching debug information. Doing so
+	  can cause significant overhead, so only enable it in non-production
+	  environments.
+
+	  If unsure, say N.
+
 config DEBUG_VM_RB
 	bool "Debug VM red-black trees"
 	depends on DEBUG_VM
 	help
-	  Enable this to turn on more extended checks in the virtual-memory
-	  system that may impact performance.
+	  Enable VM red-black tree debugging information and extra validations.
 
 	  If unsure, say N.
 
diff --git a/lib/Makefile b/lib/Makefile
index 0cd7b68e1382..02da5b614a80 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_CRC7)	+= crc7.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
 obj-$(CONFIG_CRC8)	+= crc8.o
+obj-$(CONFIG_CRC64_ECMA)	+= crc64_ecma.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
diff --git a/lib/crc64_ecma.c b/lib/crc64_ecma.c
new file mode 100644
index 000000000000..41629ea5a60c
--- /dev/null
+++ b/lib/crc64_ecma.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/crc64_ecma.h>
+
+
+#define CRC64_BYTE_MASK			0xFF
+#define CRC64_TABLE_SIZE		256
+
+
+struct crc64_table {
+	u64 seed;
+	u64 table[CRC64_TABLE_SIZE];
+};
+
+
+static struct crc64_table CRC64_ECMA_182 = {
+	CRC64_DEFAULT_INITVAL,
+	{
+		0x0000000000000000ULL,
+		0xb32e4cbe03a75f6fULL,
+		0xf4843657a840a05bULL,
+		0x47aa7ae9abe7ff34ULL,
+		0x7bd0c384ff8f5e33ULL,
+		0xc8fe8f3afc28015cULL,
+		0x8f54f5d357cffe68ULL,
+		0x3c7ab96d5468a107ULL,
+		0xf7a18709ff1ebc66ULL,
+		0x448fcbb7fcb9e309ULL,
+		0x0325b15e575e1c3dULL,
+		0xb00bfde054f94352ULL,
+		0x8c71448d0091e255ULL,
+		0x3f5f08330336bd3aULL,
+		0x78f572daa8d1420eULL,
+		0xcbdb3e64ab761d61ULL,
+		0x7d9ba13851336649ULL,
+		0xceb5ed8652943926ULL,
+		0x891f976ff973c612ULL,
+		0x3a31dbd1fad4997dULL,
+		0x064b62bcaebc387aULL,
+		0xb5652e02ad1b6715ULL,
+		0xf2cf54eb06fc9821ULL,
+		0x41e11855055bc74eULL,
+		0x8a3a2631ae2dda2fULL,
+		0x39146a8fad8a8540ULL,
+		0x7ebe1066066d7a74ULL,
+		0xcd905cd805ca251bULL,
+		0xf1eae5b551a2841cULL,
+		0x42c4a90b5205db73ULL,
+		0x056ed3e2f9e22447ULL,
+		0xb6409f5cfa457b28ULL,
+		0xfb374270a266cc92ULL,
+		0x48190ecea1c193fdULL,
+		0x0fb374270a266cc9ULL,
+		0xbc9d3899098133a6ULL,
+		0x80e781f45de992a1ULL,
+		0x33c9cd4a5e4ecdceULL,
+		0x7463b7a3f5a932faULL,
+		0xc74dfb1df60e6d95ULL,
+		0x0c96c5795d7870f4ULL,
+		0xbfb889c75edf2f9bULL,
+		0xf812f32ef538d0afULL,
+		0x4b3cbf90f69f8fc0ULL,
+		0x774606fda2f72ec7ULL,
+		0xc4684a43a15071a8ULL,
+		0x83c230aa0ab78e9cULL,
+		0x30ec7c140910d1f3ULL,
+		0x86ace348f355aadbULL,
+		0x3582aff6f0f2f5b4ULL,
+		0x7228d51f5b150a80ULL,
+		0xc10699a158b255efULL,
+		0xfd7c20cc0cdaf4e8ULL,
+		0x4e526c720f7dab87ULL,
+		0x09f8169ba49a54b3ULL,
+		0xbad65a25a73d0bdcULL,
+		0x710d64410c4b16bdULL,
+		0xc22328ff0fec49d2ULL,
+		0x85895216a40bb6e6ULL,
+		0x36a71ea8a7ace989ULL,
+		0x0adda7c5f3c4488eULL,
+		0xb9f3eb7bf06317e1ULL,
+		0xfe5991925b84e8d5ULL,
+		0x4d77dd2c5823b7baULL,
+		0x64b62bcaebc387a1ULL,
+		0xd7986774e864d8ceULL,
+		0x90321d9d438327faULL,
+		0x231c512340247895ULL,
+		0x1f66e84e144cd992ULL,
+		0xac48a4f017eb86fdULL,
+		0xebe2de19bc0c79c9ULL,
+		0x58cc92a7bfab26a6ULL,
+		0x9317acc314dd3bc7ULL,
+		0x2039e07d177a64a8ULL,
+		0x67939a94bc9d9b9cULL,
+		0xd4bdd62abf3ac4f3ULL,
+		0xe8c76f47eb5265f4ULL,
+		0x5be923f9e8f53a9bULL,
+		0x1c4359104312c5afULL,
+		0xaf6d15ae40b59ac0ULL,
+		0x192d8af2baf0e1e8ULL,
+		0xaa03c64cb957be87ULL,
+		0xeda9bca512b041b3ULL,
+		0x5e87f01b11171edcULL,
+		0x62fd4976457fbfdbULL,
+		0xd1d305c846d8e0b4ULL,
+		0x96797f21ed3f1f80ULL,
+		0x2557339fee9840efULL,
+		0xee8c0dfb45ee5d8eULL,
+		0x5da24145464902e1ULL,
+		0x1a083bacedaefdd5ULL,
+		0xa9267712ee09a2baULL,
+		0x955cce7fba6103bdULL,
+		0x267282c1b9c65cd2ULL,
+		0x61d8f8281221a3e6ULL,
+		0xd2f6b4961186fc89ULL,
+		0x9f8169ba49a54b33ULL,
+		0x2caf25044a02145cULL,
+		0x6b055fede1e5eb68ULL,
+		0xd82b1353e242b407ULL,
+		0xe451aa3eb62a1500ULL,
+		0x577fe680b58d4a6fULL,
+		0x10d59c691e6ab55bULL,
+		0xa3fbd0d71dcdea34ULL,
+		0x6820eeb3b6bbf755ULL,
+		0xdb0ea20db51ca83aULL,
+		0x9ca4d8e41efb570eULL,
+		0x2f8a945a1d5c0861ULL,
+		0x13f02d374934a966ULL,
+		0xa0de61894a93f609ULL,
+		0xe7741b60e174093dULL,
+		0x545a57dee2d35652ULL,
+		0xe21ac88218962d7aULL,
+		0x5134843c1b317215ULL,
+		0x169efed5b0d68d21ULL,
+		0xa5b0b26bb371d24eULL,
+		0x99ca0b06e7197349ULL,
+		0x2ae447b8e4be2c26ULL,
+		0x6d4e3d514f59d312ULL,
+		0xde6071ef4cfe8c7dULL,
+		0x15bb4f8be788911cULL,
+		0xa6950335e42fce73ULL,
+		0xe13f79dc4fc83147ULL,
+		0x521135624c6f6e28ULL,
+		0x6e6b8c0f1807cf2fULL,
+		0xdd45c0b11ba09040ULL,
+		0x9aefba58b0476f74ULL,
+		0x29c1f6e6b3e0301bULL,
+		0xc96c5795d7870f42ULL,
+		0x7a421b2bd420502dULL,
+		0x3de861c27fc7af19ULL,
+		0x8ec62d7c7c60f076ULL,
+		0xb2bc941128085171ULL,
+		0x0192d8af2baf0e1eULL,
+		0x4638a2468048f12aULL,
+		0xf516eef883efae45ULL,
+		0x3ecdd09c2899b324ULL,
+		0x8de39c222b3eec4bULL,
+		0xca49e6cb80d9137fULL,
+		0x7967aa75837e4c10ULL,
+		0x451d1318d716ed17ULL,
+		0xf6335fa6d4b1b278ULL,
+		0xb199254f7f564d4cULL,
+		0x02b769f17cf11223ULL,
+		0xb4f7f6ad86b4690bULL,
+		0x07d9ba1385133664ULL,
+		0x4073c0fa2ef4c950ULL,
+		0xf35d8c442d53963fULL,
+		0xcf273529793b3738ULL,
+		0x7c0979977a9c6857ULL,
+		0x3ba3037ed17b9763ULL,
+		0x888d4fc0d2dcc80cULL,
+		0x435671a479aad56dULL,
+		0xf0783d1a7a0d8a02ULL,
+		0xb7d247f3d1ea7536ULL,
+		0x04fc0b4dd24d2a59ULL,
+		0x3886b22086258b5eULL,
+		0x8ba8fe9e8582d431ULL,
+		0xcc0284772e652b05ULL,
+		0x7f2cc8c92dc2746aULL,
+		0x325b15e575e1c3d0ULL,
+		0x8175595b76469cbfULL,
+		0xc6df23b2dda1638bULL,
+		0x75f16f0cde063ce4ULL,
+		0x498bd6618a6e9de3ULL,
+		0xfaa59adf89c9c28cULL,
+		0xbd0fe036222e3db8ULL,
+		0x0e21ac88218962d7ULL,
+		0xc5fa92ec8aff7fb6ULL,
+		0x76d4de52895820d9ULL,
+		0x317ea4bb22bfdfedULL,
+		0x8250e80521188082ULL,
+		0xbe2a516875702185ULL,
+		0x0d041dd676d77eeaULL,
+		0x4aae673fdd3081deULL,
+		0xf9802b81de97deb1ULL,
+		0x4fc0b4dd24d2a599ULL,
+		0xfceef8632775faf6ULL,
+		0xbb44828a8c9205c2ULL,
+		0x086ace348f355aadULL,
+		0x34107759db5dfbaaULL,
+		0x873e3be7d8faa4c5ULL,
+		0xc094410e731d5bf1ULL,
+		0x73ba0db070ba049eULL,
+		0xb86133d4dbcc19ffULL,
+		0x0b4f7f6ad86b4690ULL,
+		0x4ce50583738cb9a4ULL,
+		0xffcb493d702be6cbULL,
+		0xc3b1f050244347ccULL,
+		0x709fbcee27e418a3ULL,
+		0x3735c6078c03e797ULL,
+		0x841b8ab98fa4b8f8ULL,
+		0xadda7c5f3c4488e3ULL,
+		0x1ef430e13fe3d78cULL,
+		0x595e4a08940428b8ULL,
+		0xea7006b697a377d7ULL,
+		0xd60abfdbc3cbd6d0ULL,
+		0x6524f365c06c89bfULL,
+		0x228e898c6b8b768bULL,
+		0x91a0c532682c29e4ULL,
+		0x5a7bfb56c35a3485ULL,
+		0xe955b7e8c0fd6beaULL,
+		0xaeffcd016b1a94deULL,
+		0x1dd181bf68bdcbb1ULL,
+		0x21ab38d23cd56ab6ULL,
+		0x9285746c3f7235d9ULL,
+		0xd52f0e859495caedULL,
+		0x6601423b97329582ULL,
+		0xd041dd676d77eeaaULL,
+		0x636f91d96ed0b1c5ULL,
+		0x24c5eb30c5374ef1ULL,
+		0x97eba78ec690119eULL,
+		0xab911ee392f8b099ULL,
+		0x18bf525d915feff6ULL,
+		0x5f1528b43ab810c2ULL,
+		0xec3b640a391f4fadULL,
+		0x27e05a6e926952ccULL,
+		0x94ce16d091ce0da3ULL,
+		0xd3646c393a29f297ULL,
+		0x604a2087398eadf8ULL,
+		0x5c3099ea6de60cffULL,
+		0xef1ed5546e415390ULL,
+		0xa8b4afbdc5a6aca4ULL,
+		0x1b9ae303c601f3cbULL,
+		0x56ed3e2f9e224471ULL,
+		0xe5c372919d851b1eULL,
+		0xa26908783662e42aULL,
+		0x114744c635c5bb45ULL,
+		0x2d3dfdab61ad1a42ULL,
+		0x9e13b115620a452dULL,
+		0xd9b9cbfcc9edba19ULL,
+		0x6a978742ca4ae576ULL,
+		0xa14cb926613cf817ULL,
+		0x1262f598629ba778ULL,
+		0x55c88f71c97c584cULL,
+		0xe6e6c3cfcadb0723ULL,
+		0xda9c7aa29eb3a624ULL,
+		0x69b2361c9d14f94bULL,
+		0x2e184cf536f3067fULL,
+		0x9d36004b35545910ULL,
+		0x2b769f17cf112238ULL,
+		0x9858d3a9ccb67d57ULL,
+		0xdff2a94067518263ULL,
+		0x6cdce5fe64f6dd0cULL,
+		0x50a65c93309e7c0bULL,
+		0xe388102d33392364ULL,
+		0xa4226ac498dedc50ULL,
+		0x170c267a9b79833fULL,
+		0xdcd7181e300f9e5eULL,
+		0x6ff954a033a8c131ULL,
+		0x28532e49984f3e05ULL,
+		0x9b7d62f79be8616aULL,
+		0xa707db9acf80c06dULL,
+		0x14299724cc279f02ULL,
+		0x5383edcd67c06036ULL,
+		0xe0ada17364673f59ULL
+	}
+};
+
+
+/*
+ * crc64_ecma_seed - Initializes the CRC64 ECMA seed.
+ */
+u64 crc64_ecma_seed(void)
+{
+	return CRC64_ECMA_182.seed;
+}
+EXPORT_SYMBOL(crc64_ecma_seed);
+
+/*
+ * crc64_ecma - Computes the 64 bit ECMA CRC.
+ *
+ * pdata: pointer to the data to compute checksum for.
+ * nbytes: number of bytes in data buffer.
+ * seed: CRC seed.
+ */
+u64 crc64_ecma(u8 const *pdata, u32 nbytes, u64 seed)
+{
+	unsigned int i;
+	u64 crc = seed;
+
+	for (i = 0; i < nbytes; i++)
+		crc = CRC64_ECMA_182.table[(crc ^ pdata[i]) & CRC64_BYTE_MASK] ^
+			(crc >> 8);
+
+	return crc;
+}
+EXPORT_SYMBOL(crc64_ecma);
+
+MODULE_DESCRIPTION("CRC64 ECMA function");
+MODULE_AUTHOR("Freescale Semiconductor Inc.");
+MODULE_LICENSE("GPL");
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
index 569985d522d5..e3edc5f3f5ee 100644
--- a/lib/lzo/lzo1x_decompress_safe.c
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -72,9 +72,11 @@ copy_literal_run:
 						COPY8(op, ip);
 						op += 8;
 						ip += 8;
+#  if !defined(__arm__)
 						COPY8(op, ip);
 						op += 8;
 						ip += 8;
+#  endif
 					} while (ip < ie);
 					ip = ie;
 					op = oe;
@@ -159,9 +161,11 @@ copy_literal_run:
 					COPY8(op, m_pos);
 					op += 8;
 					m_pos += 8;
+#  if !defined(__arm__)
 					COPY8(op, m_pos);
 					op += 8;
 					m_pos += 8;
+#  endif
 				} while (op < oe);
 				op = oe;
 				if (HAVE_IP(6)) {
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
index 6710b83ce72e..db756ccb2756 100644
--- a/lib/lzo/lzodefs.h
+++ b/lib/lzo/lzodefs.h
@@ -12,8 +12,14 @@
  */
 
 
+#if 1 && defined(__arm__) && ((__LINUX_ARM_ARCH__ >= 6) || defined(__ARM_FEATURE_UNALIGNED))
+#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
+#define COPY4(dst, src)	\
+		* (u32 *) (void *) (dst) = * (const u32 *) (const void *) (src)
+#else
 #define COPY4(dst, src)	\
 		put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#endif
 #if defined(__x86_64__)
 #define COPY8(dst, src)	\
 		put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 3a8e8e8fb2a5..4251cbd5becb 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(sg_nents);
  **/
 struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
 {
-#ifndef ARCH_HAS_SG_CHAIN
+#ifndef CONFIG_ARCH_HAS_SG_CHAIN
 	struct scatterlist *ret = &sgl[nents - 1];
 #else
 	struct scatterlist *sg, *ret = NULL;
@@ -251,7 +251,7 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
 
 	if (nents == 0)
 		return -EINVAL;
-#ifndef ARCH_HAS_SG_CHAIN
+#ifndef CONFIG_ARCH_HAS_SG_CHAIN
 	if (WARN_ON_ONCE(nents > max_ents))
 		return -EINVAL;
 #endif
diff --git a/lib/string.c b/lib/string.c
index 9b1f9062a202..89ad0f035f48 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -107,7 +107,7 @@ EXPORT_SYMBOL(strcpy);
 
 #ifndef __HAVE_ARCH_STRNCPY
 /**
- * strncpy - Copy a length-limited, %NUL-terminated string
+ * strncpy - Copy a length-limited, C-string
  * @dest: Where to copy the string to
  * @src: Where to copy the string from
  * @count: The maximum number of bytes to copy
@@ -136,7 +136,7 @@ EXPORT_SYMBOL(strncpy);
 
 #ifndef __HAVE_ARCH_STRLCPY
 /**
- * strlcpy - Copy a %NUL terminated string into a sized buffer
+ * strlcpy - Copy a C-string into a sized buffer
  * @dest: Where to copy the string to
  * @src: Where to copy the string from
  * @size: size of destination buffer
@@ -182,7 +182,7 @@ EXPORT_SYMBOL(strcat);
 
 #ifndef __HAVE_ARCH_STRNCAT
 /**
- * strncat - Append a length-limited, %NUL-terminated string to another
+ * strncat - Append a length-limited, C-string to another
  * @dest: The string to be appended to
  * @src: The string to append to it
  * @count: The maximum numbers of bytes to copy
@@ -211,7 +211,7 @@ EXPORT_SYMBOL(strncat);
 
 #ifndef __HAVE_ARCH_STRLCAT
 /**
- * strlcat - Append a length-limited, %NUL-terminated string to another
+ * strlcat - Append a length-limited, C-string to another
  * @dest: The string to be appended to
  * @src: The string to append to it
  * @count: The size of the destination buffer.
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 0648291cdafe..e30d885d9631 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1183,6 +1183,21 @@ char *address_val(char *buf, char *end, const void *addr,
 	return number(buf, end, num, spec);
 }
 
+static noinline_for_stack
+char *comm_name(char *buf, char *end, struct task_struct *tsk,
+		struct printf_spec spec, const char *fmt)
+{
+	char name[TASK_COMM_LEN];
+
+	/* Caller can pass NULL instead of current. */
+	if (!tsk)
+		tsk = current;
+	/* Not using get_task_comm() in case I'm in IRQ context. */
+	memcpy(name, tsk->comm, TASK_COMM_LEN);
+	name[sizeof(name) - 1] = '\0';
+	return string(buf, end, name, spec);
+}
+
 int kptr_restrict __read_mostly;
 
 /*
@@ -1250,6 +1265,7 @@ int kptr_restrict __read_mostly;
  *           (default assumed to be phys_addr_t, passed by reference)
  * - 'd[234]' For a dentry name (optionally 2-4 last components)
  * - 'D[234]' Same as 'd' but for a struct file
+ * - 'T' task_struct->comm
  *
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
@@ -1261,7 +1277,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 {
 	int default_width = 2 * sizeof(void *) + (spec.flags & SPECIAL ? 2 : 0);
 
-	if (!ptr && *fmt != 'K') {
+	if (!ptr && *fmt != 'K' && *fmt != 'T') {
 		/*
 		 * Print (null) with the same width as a pointer so it makes
 		 * tabular output look nice.
@@ -1389,6 +1405,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		return dentry_name(buf, end,
 				   ((const struct file *)ptr)->f_path.dentry,
 				   spec, fmt);
+	case 'T':
+		return comm_name(buf, end, ptr, spec, fmt);
 	}
 	spec.flags |= SMALL;
 	if (spec.field_width == -1) {
diff --git a/lib/xz/Kconfig b/lib/xz/Kconfig
index 08837db52d94..12d2d777f36b 100644
--- a/lib/xz/Kconfig
+++ b/lib/xz/Kconfig
@@ -9,33 +9,33 @@ config XZ_DEC
 if XZ_DEC
 
 config XZ_DEC_X86
-	bool "x86 BCJ filter decoder"
-	default y if X86
+	bool "x86 BCJ filter decoder" if EXPERT
+	default y
 	select XZ_DEC_BCJ
 
 config XZ_DEC_POWERPC
-	bool "PowerPC BCJ filter decoder"
-	default y if PPC
+	bool "PowerPC BCJ filter decoder" if EXPERT
+	default y
 	select XZ_DEC_BCJ
 
 config XZ_DEC_IA64
-	bool "IA-64 BCJ filter decoder"
-	default y if IA64
+	bool "IA-64 BCJ filter decoder" if EXPERT
+	default y
 	select XZ_DEC_BCJ
 
 config XZ_DEC_ARM
-	bool "ARM BCJ filter decoder"
-	default y if ARM
+	bool "ARM BCJ filter decoder" if EXPERT
+	default y
 	select XZ_DEC_BCJ
 
 config XZ_DEC_ARMTHUMB
-	bool "ARM-Thumb BCJ filter decoder"
-	default y if (ARM && ARM_THUMB)
+	bool "ARM-Thumb BCJ filter decoder" if EXPERT
+	default y
 	select XZ_DEC_BCJ
 
 config XZ_DEC_SPARC
-	bool "SPARC BCJ filter decoder"
-	default y if SPARC
+	bool "SPARC BCJ filter decoder" if EXPERT
+	default y
 	select XZ_DEC_BCJ
 
 endif
diff --git a/localversion-next b/localversion-next
new file mode 100644
index 000000000000..b5f1ae67c438
--- /dev/null
+++ b/localversion-next
@@ -0,0 +1 @@
+-next-20140417
diff --git a/mm/Kconfig b/mm/Kconfig
index ebe5880c29d6..30cb6cb008f5 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -134,6 +134,9 @@ config HAVE_MEMBLOCK
 config HAVE_MEMBLOCK_NODE_MAP
 	boolean
 
+config HAVE_MEMBLOCK_PHYS_MAP
+	boolean
+
 config ARCH_DISCARD_MEMBLOCK
 	boolean
 
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 09d9591b7708..5ab9a49ce037 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -234,11 +234,46 @@ static ssize_t stable_pages_required_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(stable_pages_required);
 
+static ssize_t strictlimit_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct backing_dev_info *bdi = dev_get_drvdata(dev);
+	unsigned int val;
+	ssize_t ret;
+
+	ret = kstrtouint(buf, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	switch (val) {
+	case 0:
+		bdi->capabilities &= ~BDI_CAP_STRICTLIMIT;
+		break;
+	case 1:
+		bdi->capabilities |= BDI_CAP_STRICTLIMIT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return count;
+}
+static ssize_t strictlimit_show(struct device *dev,
+		struct device_attribute *attr, char *page)
+{
+	struct backing_dev_info *bdi = dev_get_drvdata(dev);
+
+	return snprintf(page, PAGE_SIZE-1, "%d\n",
+			!!(bdi->capabilities & BDI_CAP_STRICTLIMIT));
+}
+static DEVICE_ATTR_RW(strictlimit);
+
 static struct attribute *bdi_dev_attrs[] = {
 	&dev_attr_read_ahead_kb.attr,
 	&dev_attr_min_ratio.attr,
 	&dev_attr_max_ratio.attr,
 	&dev_attr_stable_pages_required.attr,
+	&dev_attr_strictlimit.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(bdi_dev);
diff --git a/mm/compaction.c b/mm/compaction.c
index 37f976287068..9635083cd8ec 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -293,14 +293,14 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 
 		/* Found a free page, break it into order-0 pages */
 		isolated = split_free_page(page);
-		total_isolated += isolated;
-		for (i = 0; i < isolated; i++) {
-			list_add(&page->lru, freelist);
-			page++;
-		}
-
-		/* If a page was split, advance to the end of it */
 		if (isolated) {
+			total_isolated += isolated;
+			for (i = 0; i < isolated; i++) {
+				list_add(&page->lru, freelist);
+				page++;
+			}
+
+			/* If a page was split, advance to the end of it */
 			blockpfn += isolated - 1;
 			cursor += isolated - 1;
 			continue;
@@ -309,9 +309,6 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 isolate_fail:
 		if (strict)
 			break;
-		else
-			continue;
-
 	}
 
 	trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated);
diff --git a/mm/fremap.c b/mm/fremap.c
index 34feba60a17e..2c5646f11f41 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -82,13 +82,10 @@ static int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
 
 	ptfile = pgoff_to_pte(pgoff);
 
-	if (!pte_none(*pte)) {
-		if (pte_present(*pte) && pte_soft_dirty(*pte))
-			pte_file_mksoft_dirty(ptfile);
+	if (!pte_none(*pte))
 		zap_pte(mm, vma, addr, pte);
-	}
 
-	set_pte_at(mm, addr, pte, ptfile);
+	set_pte_at(mm, addr, pte, pte_file_mksoft_dirty(ptfile));
 	/*
 	 * We don't need to run update_mmu_cache() here because the "file pte"
 	 * being installed by install_file_pte() is not a real pte - it's a
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 64635f5278ff..7577c40f2ad7 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1800,7 +1800,7 @@ static void __split_huge_page(struct page *page,
 			      struct list_head *list)
 {
 	int mapcount, mapcount2;
-	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+	pgoff_t pgoff = page_pgoff(page);
 	struct anon_vma_chain *avc;
 
 	BUG_ON(!PageHead(page));
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index dd30f22b35e0..86c7c5bbc2f7 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -31,6 +31,7 @@
 
 #include <linux/io.h>
 #include <linux/hugetlb.h>
+#include <linux/hugetlb_inline.h>
 #include <linux/hugetlb_cgroup.h>
 #include <linux/node.h>
 #include "internal.h"
@@ -1172,6 +1173,7 @@ static void return_unused_surplus_pages(struct hstate *h,
 	while (nr_pages--) {
 		if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
 			break;
+		cond_resched_lock(&hugetlb_lock);
 	}
 }
 
diff --git a/mm/memblock.c b/mm/memblock.c
index e9d6ca9a01a9..a810ba923cdd 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -27,6 +27,9 @@
 
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
 static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
+#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
+static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
+#endif
 
 struct memblock memblock __initdata_memblock = {
 	.memory.regions		= memblock_memory_init_regions,
@@ -37,6 +40,12 @@ struct memblock memblock __initdata_memblock = {
 	.reserved.cnt		= 1,	/* empty dummy entry */
 	.reserved.max		= INIT_MEMBLOCK_REGIONS,
 
+#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
+	.physmem.regions	= memblock_physmem_init_regions,
+	.physmem.cnt		= 1,	/* empty dummy entry */
+	.physmem.max		= INIT_PHYSMEM_REGIONS,
+#endif
+
 	.bottom_up		= false,
 	.current_limit		= MEMBLOCK_ALLOC_ANYWHERE,
 };
@@ -472,7 +481,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,
 }
 
 /**
- * memblock_add_region - add new memblock region
+ * memblock_add_range - add new memblock region
  * @type: memblock type to add new region into
  * @base: base address of the new region
  * @size: size of the new region
@@ -487,7 +496,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,
  * RETURNS:
  * 0 on success, -errno on failure.
  */
-static int __init_memblock memblock_add_region(struct memblock_type *type,
+int __init_memblock memblock_add_range(struct memblock_type *type,
 				phys_addr_t base, phys_addr_t size,
 				int nid, unsigned long flags)
 {
@@ -569,12 +578,12 @@ repeat:
 int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,
 				       int nid)
 {
-	return memblock_add_region(&memblock.memory, base, size, nid, 0);
+	return memblock_add_range(&memblock.memory, base, size, nid, 0);
 }
 
 int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
 {
-	return memblock_add_region(&memblock.memory, base, size,
+	return memblock_add_range(&memblock.memory, base, size,
 				   MAX_NUMNODES, 0);
 }
 
@@ -654,8 +663,8 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,
 	return 0;
 }
 
-static int __init_memblock __memblock_remove(struct memblock_type *type,
-					     phys_addr_t base, phys_addr_t size)
+int __init_memblock memblock_remove_range(struct memblock_type *type,
+					  phys_addr_t base, phys_addr_t size)
 {
 	int start_rgn, end_rgn;
 	int i, ret;
@@ -671,9 +680,10 @@ static int __init_memblock __memblock_remove(struct memblock_type *type,
 
 int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
 {
-	return __memblock_remove(&memblock.memory, base, size);
+	return memblock_remove_range(&memblock.memory, base, size);
 }
 
+
 int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
 {
 	memblock_dbg("   memblock_free: [%#016llx-%#016llx] %pF\n",
@@ -681,7 +691,7 @@ int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
 		     (unsigned long long)base + size - 1,
 		     (void *)_RET_IP_);
 
-	return __memblock_remove(&memblock.reserved, base, size);
+	return memblock_remove_range(&memblock.reserved, base, size);
 }
 
 static int __init_memblock memblock_reserve_region(phys_addr_t base,
@@ -696,7 +706,7 @@ static int __init_memblock memblock_reserve_region(phys_addr_t base,
 		     (unsigned long long)base + size - 1,
 		     flags, (void *)_RET_IP_);
 
-	return memblock_add_region(_rgn, base, size, nid, flags);
+	return memblock_add_range(_rgn, base, size, nid, flags);
 }
 
 int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
@@ -758,17 +768,19 @@ int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
 }
 
 /**
- * __next_free_mem_range - next function for for_each_free_mem_range()
+ * __next__mem_range - next function for for_each_free_mem_range() etc.
  * @idx: pointer to u64 loop variable
  * @nid: node selector, %NUMA_NO_NODE for all nodes
+ * @type_a: pointer to memblock_type from where the range is taken
+ * @type_b: pointer to memblock_type which excludes memory from being taken
  * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
  * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
  * @out_nid: ptr to int for nid of the range, can be %NULL
  *
- * Find the first free area from *@idx which matches @nid, fill the out
+ * Find the first area from *@idx which matches @nid, fill the out
  * parameters, and update *@idx for the next iteration.  The lower 32bit of
- * *@idx contains index into memory region and the upper 32bit indexes the
- * areas before each reserved region.  For example, if reserved regions
+ * *@idx contains index into type_a and the upper 32bit indexes the
+ * areas before each region in type_b.	For example, if type_b regions
  * look like the following,
  *
  *	0:[0-16), 1:[32-48), 2:[128-130)
@@ -780,53 +792,77 @@ int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
  * As both region arrays are sorted, the function advances the two indices
  * in lockstep and returns each intersection.
  */
-void __init_memblock __next_free_mem_range(u64 *idx, int nid,
-					   phys_addr_t *out_start,
-					   phys_addr_t *out_end, int *out_nid)
+void __init_memblock __next_mem_range(u64 *idx, int nid,
+				      struct memblock_type *type_a,
+				      struct memblock_type *type_b,
+				      phys_addr_t *out_start,
+				      phys_addr_t *out_end, int *out_nid)
 {
-	struct memblock_type *mem = &memblock.memory;
-	struct memblock_type *rsv = &memblock.reserved;
-	int mi = *idx & 0xffffffff;
-	int ri = *idx >> 32;
+	int idx_a = *idx & 0xffffffff;
+	int idx_b = *idx >> 32;
 
-	if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
+	if (WARN_ONCE(nid == MAX_NUMNODES,
+	"Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
 		nid = NUMA_NO_NODE;
 
-	for ( ; mi < mem->cnt; mi++) {
-		struct memblock_region *m = &mem->regions[mi];
+	for (; idx_a < type_a->cnt; idx_a++) {
+		struct memblock_region *m = &type_a->regions[idx_a];
+
 		phys_addr_t m_start = m->base;
 		phys_addr_t m_end = m->base + m->size;
+		int	    m_nid = memblock_get_region_node(m);
 
 		/* only memory regions are associated with nodes, check it */
-		if (nid != NUMA_NO_NODE && nid != memblock_get_region_node(m))
+		if (nid != NUMA_NO_NODE && nid != m_nid)
 			continue;
 
-		/* scan areas before each reservation for intersection */
-		for ( ; ri < rsv->cnt + 1; ri++) {
-			struct memblock_region *r = &rsv->regions[ri];
-			phys_addr_t r_start = ri ? r[-1].base + r[-1].size : 0;
-			phys_addr_t r_end = ri < rsv->cnt ? r->base : ULLONG_MAX;
+		if (!type_b) {
+			if (out_start)
+				*out_start = m_start;
+			if (out_end)
+				*out_end = m_end;
+			if (out_nid)
+				*out_nid = m_nid;
+			idx_a++;
+			*idx = (u32)idx_a | (u64)idx_b << 32;
+			return;
+		}
 
-			/* if ri advanced past mi, break out to advance mi */
+		/* scan areas before each reservation */
+		for (; idx_b < type_b->cnt + 1; idx_b++) {
+			struct memblock_region *r;
+			phys_addr_t r_start;
+			phys_addr_t r_end;
+
+			r = &type_b->regions[idx_b];
+			r_start = idx_b ? r[-1].base + r[-1].size : 0;
+			r_end = idx_b < type_b->cnt ?
+				r->base : ULLONG_MAX;
+
+			/*
+			 * if idx_b advanced past idx_a,
+			 * break out to advance idx_a
+			 */
 			if (r_start >= m_end)
 				break;
 			/* if the two regions intersect, we're done */
 			if (m_start < r_end) {
 				if (out_start)
-					*out_start = max(m_start, r_start);
+					*out_start =
+						max(m_start, r_start);
 				if (out_end)
 					*out_end = min(m_end, r_end);
 				if (out_nid)
-					*out_nid = memblock_get_region_node(m);
+					*out_nid = m_nid;
 				/*
-				 * The region which ends first is advanced
-				 * for the next iteration.
+				 * The region which ends first is
+				 * advanced for the next iteration.
 				 */
 				if (m_end <= r_end)
-					mi++;
+					idx_a++;
 				else
-					ri++;
-				*idx = (u32)mi | (u64)ri << 32;
+					idx_b++;
+				*idx = (u32)idx_a | (u64)idx_b << 32;
 				return;
 			}
 		}
@@ -837,57 +873,80 @@ void __init_memblock __next_free_mem_range(u64 *idx, int nid,
 }
 
 /**
- * __next_free_mem_range_rev - next function for for_each_free_mem_range_reverse()
+ * __next_mem_range_rev - generic next function for for_each_*_range_rev()
+ *
+ * Finds the next range from type_a which is not marked as unsuitable
+ * in type_b.
+ *
  * @idx: pointer to u64 loop variable
  * @nid: nid: node selector, %NUMA_NO_NODE for all nodes
+ * @type_a: pointer to memblock_type from where the range is taken
+ * @type_b: pointer to memblock_type which excludes memory from being taken
  * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
  * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
  * @out_nid: ptr to int for nid of the range, can be %NULL
  *
- * Reverse of __next_free_mem_range().
- *
- * Linux kernel cannot migrate pages used by itself. Memory hotplug users won't
- * be able to hot-remove hotpluggable memory used by the kernel. So this
- * function skip hotpluggable regions if needed when allocating memory for the
- * kernel.
+ * Reverse of __next_mem_range().
  */
-void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid,
-					   phys_addr_t *out_start,
-					   phys_addr_t *out_end, int *out_nid)
+void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
+					  struct memblock_type *type_a,
+					  struct memblock_type *type_b,
+					  phys_addr_t *out_start,
+					  phys_addr_t *out_end, int *out_nid)
 {
-	struct memblock_type *mem = &memblock.memory;
-	struct memblock_type *rsv = &memblock.reserved;
-	int mi = *idx & 0xffffffff;
-	int ri = *idx >> 32;
+	int idx_a = *idx & 0xffffffff;
+	int idx_b = *idx >> 32;
 
 	if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
 		nid = NUMA_NO_NODE;
 
 	if (*idx == (u64)ULLONG_MAX) {
-		mi = mem->cnt - 1;
-		ri = rsv->cnt;
+		idx_a = type_a->cnt - 1;
+		idx_b = type_b->cnt;
 	}
 
-	for ( ; mi >= 0; mi--) {
-		struct memblock_region *m = &mem->regions[mi];
+	for (; idx_a >= 0; idx_a--) {
+		struct memblock_region *m = &type_a->regions[idx_a];
+
 		phys_addr_t m_start = m->base;
 		phys_addr_t m_end = m->base + m->size;
+		int m_nid = memblock_get_region_node(m);
 
 		/* only memory regions are associated with nodes, check it */
-		if (nid != NUMA_NO_NODE && nid != memblock_get_region_node(m))
+		if (nid != NUMA_NO_NODE && nid != m_nid)
 			continue;
 
 		/* skip hotpluggable memory regions if needed */
 		if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
 			continue;
 
-		/* scan areas before each reservation for intersection */
-		for ( ; ri >= 0; ri--) {
-			struct memblock_region *r = &rsv->regions[ri];
-			phys_addr_t r_start = ri ? r[-1].base + r[-1].size : 0;
-			phys_addr_t r_end = ri < rsv->cnt ? r->base : ULLONG_MAX;
+		if (!type_b) {
+			if (out_start)
+				*out_start = m_start;
+			if (out_end)
+				*out_end = m_end;
+			if (out_nid)
+				*out_nid = m_nid;
+			idx_a++;
+			*idx = (u32)idx_a | (u64)idx_b << 32;
+			return;
+		}
+
+		/* scan areas before each reservation */
+		for (; idx_b >= 0; idx_b--) {
+			struct memblock_region *r;
+			phys_addr_t r_start;
+			phys_addr_t r_end;
+
+			r = &type_b->regions[idx_b];
+			r_start = idx_b ? r[-1].base + r[-1].size : 0;
+			r_end = idx_b < type_b->cnt ?
+				r->base : ULLONG_MAX;
+			/*
+			 * if idx_b advanced past idx_a,
+			 * break out to advance idx_a
+			 */
 
-			/* if ri advanced past mi, break out to advance mi */
 			if (r_end <= m_start)
 				break;
 			/* if the two regions intersect, we're done */
@@ -897,18 +956,17 @@ void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid,
 				if (out_end)
 					*out_end = min(m_end, r_end);
 				if (out_nid)
-					*out_nid = memblock_get_region_node(m);
-
+					*out_nid = m_nid;
 				if (m_start >= r_start)
-					mi--;
+					idx_a--;
 				else
-					ri--;
-				*idx = (u32)mi | (u64)ri << 32;
+					idx_b--;
+				*idx = (u32)idx_a | (u64)idx_b << 32;
 				return;
 			}
 		}
 	}
-
+	/* signal end of iteration */
 	*idx = ULLONG_MAX;
 }
 
@@ -1201,7 +1259,7 @@ void __init __memblock_free_early(phys_addr_t base, phys_addr_t size)
 		     __func__, (u64)base, (u64)base + size - 1,
 		     (void *)_RET_IP_);
 	kmemleak_free_part(__va(base), size);
-	__memblock_remove(&memblock.reserved, base, size);
+	memblock_remove_range(&memblock.reserved, base, size);
 }
 
 /*
@@ -1287,8 +1345,10 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 	}
 
 	/* truncate both memory and reserved regions */
-	__memblock_remove(&memblock.memory, max_addr, (phys_addr_t)ULLONG_MAX);
-	__memblock_remove(&memblock.reserved, max_addr, (phys_addr_t)ULLONG_MAX);
+	memblock_remove_range(&memblock.memory, max_addr,
+			      (phys_addr_t)ULLONG_MAX);
+	memblock_remove_range(&memblock.reserved, max_addr,
+			      (phys_addr_t)ULLONG_MAX);
 }
 
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
@@ -1502,6 +1562,9 @@ static int __init memblock_init_debugfs(void)
 		return -ENXIO;
 	debugfs_create_file("memory", S_IRUGO, root, &memblock.memory, &memblock_debug_fops);
 	debugfs_create_file("reserved", S_IRUGO, root, &memblock.reserved, &memblock_debug_fops);
+#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
+	debugfs_create_file("physmem", S_IRUGO, root, &memblock.physmem, &memblock_debug_fops);
+#endif
 
 	return 0;
 }
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 29501f040568..e59f5729e5e6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2944,7 +2944,7 @@ static int mem_cgroup_slabinfo_read(struct seq_file *m, void *v)
 }
 #endif
 
-static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size)
+int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size)
 {
 	struct res_counter *fail_res;
 	int ret = 0;
@@ -2982,7 +2982,7 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size)
 	return ret;
 }
 
-static void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size)
+void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size)
 {
 	res_counter_uncharge(&memcg->res, size);
 	if (do_swap_account)
@@ -3531,11 +3531,12 @@ __memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **_memcg, int order)
 	/*
 	 * Disabling accounting is only relevant for some specific memcg
 	 * internal allocations. Therefore we would initially not have such
-	 * check here, since direct calls to the page allocator that are marked
-	 * with GFP_KMEMCG only happen outside memcg core. We are mostly
-	 * concerned with cache allocations, and by having this test at
-	 * memcg_kmem_get_cache, we are already able to relay the allocation to
-	 * the root cache and bypass the memcg cache altogether.
+	 * check here, since direct calls to the page allocator that are
+	 * accounted to kmemcg (alloc_kmem_pages and friends) only happen
+	 * outside memcg core. We are mostly concerned with cache allocations,
+	 * and by having this test at memcg_kmem_get_cache, we are already able
+	 * to relay the allocation to the root cache and bypass the memcg cache
+	 * altogether.
 	 *
 	 * There is one exception, though: the SLUB allocator does not create
 	 * large order caches, but rather service large kmallocs directly from
@@ -6777,30 +6778,29 @@ static inline enum mc_target_type get_mctgt_type_thp(struct vm_area_struct *vma,
 }
 #endif
 
-static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd,
+static int mem_cgroup_count_precharge_pte(pte_t *pte,
 					unsigned long addr, unsigned long end,
 					struct mm_walk *walk)
 {
-	struct vm_area_struct *vma = walk->private;
-	pte_t *pte;
+	if (get_mctgt_type(walk->vma, addr, *pte, NULL))
+		mc.precharge++;	/* increment precharge temporarily */
+	return 0;
+}
+
+static int mem_cgroup_count_precharge_pmd(pmd_t *pmd,
+					unsigned long addr, unsigned long end,
+					struct mm_walk *walk)
+{
+	struct vm_area_struct *vma = walk->vma;
 	spinlock_t *ptl;
 
 	if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) {
 		if (get_mctgt_type_thp(vma, addr, *pmd, NULL) == MC_TARGET_PAGE)
 			mc.precharge += HPAGE_PMD_NR;
 		spin_unlock(ptl);
-		return 0;
+		/* don't call mem_cgroup_count_precharge_pte() */
+		walk->skip = 1;
 	}
-
-	if (pmd_trans_unstable(pmd))
-		return 0;
-	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	for (; addr != end; pte++, addr += PAGE_SIZE)
-		if (get_mctgt_type(vma, addr, *pte, NULL))
-			mc.precharge++;	/* increment precharge temporarily */
-	pte_unmap_unlock(pte - 1, ptl);
-	cond_resched();
-
 	return 0;
 }
 
@@ -6809,18 +6809,14 @@ static unsigned long mem_cgroup_count_precharge(struct mm_struct *mm)
 	unsigned long precharge;
 	struct vm_area_struct *vma;
 
+	struct mm_walk mem_cgroup_count_precharge_walk = {
+		.pmd_entry = mem_cgroup_count_precharge_pmd,
+		.pte_entry = mem_cgroup_count_precharge_pte,
+		.mm = mm,
+	};
 	down_read(&mm->mmap_sem);
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		struct mm_walk mem_cgroup_count_precharge_walk = {
-			.pmd_entry = mem_cgroup_count_precharge_pte_range,
-			.mm = mm,
-			.private = vma,
-		};
-		if (is_vm_hugetlb_page(vma))
-			continue;
-		walk_page_range(vma->vm_start, vma->vm_end,
-					&mem_cgroup_count_precharge_walk);
-	}
+	for (vma = mm->mmap; vma; vma = vma->vm_next)
+		walk_page_vma(vma, &mem_cgroup_count_precharge_walk);
 	up_read(&mm->mmap_sem);
 
 	precharge = mc.precharge;
@@ -6959,7 +6955,7 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
 				struct mm_walk *walk)
 {
 	int ret = 0;
-	struct vm_area_struct *vma = walk->private;
+	struct vm_area_struct *vma = walk->vma;
 	pte_t *pte;
 	spinlock_t *ptl;
 	enum mc_target_type target_type;
@@ -7060,6 +7056,10 @@ put:			/* get_mctgt_type() gets the page */
 static void mem_cgroup_move_charge(struct mm_struct *mm)
 {
 	struct vm_area_struct *vma;
+	struct mm_walk mem_cgroup_move_charge_walk = {
+		.pmd_entry = mem_cgroup_move_charge_pte_range,
+		.mm = mm,
+	};
 
 	lru_add_drain_all();
 retry:
@@ -7075,24 +7075,8 @@ retry:
 		cond_resched();
 		goto retry;
 	}
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		int ret;
-		struct mm_walk mem_cgroup_move_charge_walk = {
-			.pmd_entry = mem_cgroup_move_charge_pte_range,
-			.mm = mm,
-			.private = vma,
-		};
-		if (is_vm_hugetlb_page(vma))
-			continue;
-		ret = walk_page_range(vma->vm_start, vma->vm_end,
-						&mem_cgroup_move_charge_walk);
-		if (ret)
-			/*
-			 * means we have consumed all precharges and failed in
-			 * doing additional charge. Just abandon here.
-			 */
-			break;
-	}
+	for (vma = mm->mmap; vma; vma = vma->vm_next)
+		walk_page_vma(vma, &mem_cgroup_move_charge_walk);
 	up_read(&mm->mmap_sem);
 }
 
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 35ef28acf137..12ac5df4d49a 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -202,7 +202,7 @@ static int kill_proc(struct task_struct *t, unsigned long addr, int trapno,
 #ifdef __ARCH_SI_TRAPNO
 	si.si_trapno = trapno;
 #endif
-	si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
+	si.si_addr_lsb = page_size_order(page) + PAGE_SHIFT;
 
 	if ((flags & MF_ACTION_REQUIRED) && t == current) {
 		si.si_code = BUS_MCEERR_AR;
@@ -404,7 +404,7 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill,
 	if (av == NULL)	/* Not actually mapped anymore */
 		return;
 
-	pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+	pgoff = page_pgoff(page);
 	read_lock(&tasklist_lock);
 	for_each_process (tsk) {
 		struct anon_vma_chain *vmac;
@@ -437,7 +437,7 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill,
 	mutex_lock(&mapping->i_mmap_mutex);
 	read_lock(&tasklist_lock);
 	for_each_process(tsk) {
-		pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+		pgoff_t pgoff = page_pgoff(page);
 
 		if (!task_early_kill(tsk))
 			continue;
diff --git a/mm/memory.c b/mm/memory.c
index d0f0bef3be48..9f562946f5e7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3578,6 +3578,8 @@ static int do_shared_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	int dirtied = 0;
 	int ret, tmp;
 
+	WARN_ON_ONCE(!rwsem_is_locked(&mm->mmap_sem));
+
 	ret = __do_fault(vma, address, pgoff, flags, &fault_page);
 	if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY)))
 		return ret;
@@ -3608,6 +3610,12 @@ static int do_shared_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
 	if (set_page_dirty(fault_page))
 		dirtied = 1;
+	/*
+	 * Take a local copy of the address_space - page.mapping may be zeroed
+	 * by truncate after unlock_page().   The address_space itself remains
+	 * pinned by vma->vm_file's reference.  We rely on unlock_page()'s
+	 * release semantics to prevent the compiler from undoing this copying.
+	 */
 	mapping = fault_page->mapping;
 	unlock_page(fault_page);
 	if ((dirtied || vma->vm_ops->page_mkwrite) && mapping) {
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 78e1472933ea..9d2ef4111a4c 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -476,140 +476,70 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
 static void migrate_page_add(struct page *page, struct list_head *pagelist,
 				unsigned long flags);
 
+struct queue_pages {
+	struct list_head *pagelist;
+	unsigned long flags;
+	nodemask_t *nmask;
+	struct vm_area_struct *prev;
+};
+
 /*
  * Scan through pages checking if pages follow certain conditions,
  * and move them to the pagelist if they do.
  */
-static int queue_pages_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
-		unsigned long addr, unsigned long end,
-		const nodemask_t *nodes, unsigned long flags,
-		void *private)
+static int queue_pages_pte(pte_t *pte, unsigned long addr,
+			unsigned long next, struct mm_walk *walk)
 {
-	pte_t *orig_pte;
-	pte_t *pte;
-	spinlock_t *ptl;
-
-	orig_pte = pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	do {
-		struct page *page;
-		int nid;
+	struct vm_area_struct *vma = walk->vma;
+	struct page *page;
+	struct queue_pages *qp = walk->private;
+	unsigned long flags = qp->flags;
+	int nid;
 
-		if (!pte_present(*pte))
-			continue;
-		page = vm_normal_page(vma, addr, *pte);
-		if (!page)
-			continue;
-		/*
-		 * vm_normal_page() filters out zero pages, but there might
-		 * still be PageReserved pages to skip, perhaps in a VDSO.
-		 */
-		if (PageReserved(page))
-			continue;
-		nid = page_to_nid(page);
-		if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT))
-			continue;
+	if (!pte_present(*pte))
+		return 0;
+	page = vm_normal_page(vma, addr, *pte);
+	if (!page)
+		return 0;
+	/*
+	 * vm_normal_page() filters out zero pages, but there might
+	 * still be PageReserved pages to skip, perhaps in a VDSO.
+	 */
+	if (PageReserved(page))
+		return 0;
+	nid = page_to_nid(page);
+	if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT))
+		return 0;
 
-		if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
-			migrate_page_add(page, private, flags);
-		else
-			break;
-	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap_unlock(orig_pte, ptl);
-	return addr != end;
+	if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+		migrate_page_add(page, qp->pagelist, flags);
+	return 0;
 }
 
-static void queue_pages_hugetlb_pmd_range(struct vm_area_struct *vma,
-		pmd_t *pmd, const nodemask_t *nodes, unsigned long flags,
-				    void *private)
+static int queue_pages_hugetlb(pte_t *pte, unsigned long addr,
+				unsigned long next, struct mm_walk *walk)
 {
 #ifdef CONFIG_HUGETLB_PAGE
+	struct queue_pages *qp = walk->private;
+	unsigned long flags = qp->flags;
 	int nid;
 	struct page *page;
-	spinlock_t *ptl;
+	pte_t entry;
 
-	ptl = huge_pte_lock(hstate_vma(vma), vma->vm_mm, (pte_t *)pmd);
-	page = pte_page(huge_ptep_get((pte_t *)pmd));
+	entry = huge_ptep_get(pte);
+	if (!pte_present(entry))
+		return 0;
+	page = pte_page(entry);
 	nid = page_to_nid(page);
-	if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT))
-		goto unlock;
+	if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT))
+		return 0;
 	/* With MPOL_MF_MOVE, we migrate only unshared hugepage. */
 	if (flags & (MPOL_MF_MOVE_ALL) ||
 	    (flags & MPOL_MF_MOVE && page_mapcount(page) == 1))
-		isolate_huge_page(page, private);
-unlock:
-	spin_unlock(ptl);
+		isolate_huge_page(page, qp->pagelist);
 #else
 	BUG();
 #endif
-}
-
-static inline int queue_pages_pmd_range(struct vm_area_struct *vma, pud_t *pud,
-		unsigned long addr, unsigned long end,
-		const nodemask_t *nodes, unsigned long flags,
-		void *private)
-{
-	pmd_t *pmd;
-	unsigned long next;
-
-	pmd = pmd_offset(pud, addr);
-	do {
-		next = pmd_addr_end(addr, end);
-		if (!pmd_present(*pmd))
-			continue;
-		if (pmd_huge(*pmd) && is_vm_hugetlb_page(vma)) {
-			queue_pages_hugetlb_pmd_range(vma, pmd, nodes,
-						flags, private);
-			continue;
-		}
-		split_huge_page_pmd(vma, addr, pmd);
-		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
-			continue;
-		if (queue_pages_pte_range(vma, pmd, addr, next, nodes,
-				    flags, private))
-			return -EIO;
-	} while (pmd++, addr = next, addr != end);
-	return 0;
-}
-
-static inline int queue_pages_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
-		unsigned long addr, unsigned long end,
-		const nodemask_t *nodes, unsigned long flags,
-		void *private)
-{
-	pud_t *pud;
-	unsigned long next;
-
-	pud = pud_offset(pgd, addr);
-	do {
-		next = pud_addr_end(addr, end);
-		if (pud_huge(*pud) && is_vm_hugetlb_page(vma))
-			continue;
-		if (pud_none_or_clear_bad(pud))
-			continue;
-		if (queue_pages_pmd_range(vma, pud, addr, next, nodes,
-				    flags, private))
-			return -EIO;
-	} while (pud++, addr = next, addr != end);
-	return 0;
-}
-
-static inline int queue_pages_pgd_range(struct vm_area_struct *vma,
-		unsigned long addr, unsigned long end,
-		const nodemask_t *nodes, unsigned long flags,
-		void *private)
-{
-	pgd_t *pgd;
-	unsigned long next;
-
-	pgd = pgd_offset(vma->vm_mm, addr);
-	do {
-		next = pgd_addr_end(addr, end);
-		if (pgd_none_or_clear_bad(pgd))
-			continue;
-		if (queue_pages_pud_range(vma, pgd, addr, next, nodes,
-				    flags, private))
-			return -EIO;
-	} while (pgd++, addr = next, addr != end);
 	return 0;
 }
 
@@ -642,6 +572,45 @@ static unsigned long change_prot_numa(struct vm_area_struct *vma,
 }
 #endif /* CONFIG_NUMA_BALANCING */
 
+static int queue_pages_test_walk(unsigned long start, unsigned long end,
+				struct mm_walk *walk)
+{
+	struct vm_area_struct *vma = walk->vma;
+	struct queue_pages *qp = walk->private;
+	unsigned long endvma = vma->vm_end;
+	unsigned long flags = qp->flags;
+
+	if (endvma > end)
+		endvma = end;
+	if (vma->vm_start > start)
+		start = vma->vm_start;
+
+	if (!(flags & MPOL_MF_DISCONTIG_OK)) {
+		if (!vma->vm_next && vma->vm_end < end)
+			return -EFAULT;
+		if (qp->prev && qp->prev->vm_end < vma->vm_start)
+			return -EFAULT;
+	}
+
+	qp->prev = vma;
+	walk->skip = 1;
+
+	if (vma->vm_flags & VM_PFNMAP)
+		return 0;
+
+	if (flags & MPOL_MF_LAZY) {
+		change_prot_numa(vma, start, endvma);
+		return 0;
+	}
+
+	if ((flags & MPOL_MF_STRICT) ||
+	    ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
+	     vma_migratable(vma)))
+		/* queue pages from current vma */
+		walk->skip = 0;
+	return 0;
+}
+
 /*
  * Walk through page tables and collect pages to be migrated.
  *
@@ -651,51 +620,29 @@ static unsigned long change_prot_numa(struct vm_area_struct *vma,
  */
 static struct vm_area_struct *
 queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
-		const nodemask_t *nodes, unsigned long flags, void *private)
+		nodemask_t *nodes, unsigned long flags,
+		struct list_head *pagelist)
 {
 	int err;
-	struct vm_area_struct *first, *vma, *prev;
-
-
-	first = find_vma(mm, start);
-	if (!first)
-		return ERR_PTR(-EFAULT);
-	prev = NULL;
-	for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) {
-		unsigned long endvma = vma->vm_end;
-
-		if (endvma > end)
-			endvma = end;
-		if (vma->vm_start > start)
-			start = vma->vm_start;
-
-		if (!(flags & MPOL_MF_DISCONTIG_OK)) {
-			if (!vma->vm_next && vma->vm_end < end)
-				return ERR_PTR(-EFAULT);
-			if (prev && prev->vm_end < vma->vm_start)
-				return ERR_PTR(-EFAULT);
-		}
-
-		if (flags & MPOL_MF_LAZY) {
-			change_prot_numa(vma, start, endvma);
-			goto next;
-		}
-
-		if ((flags & MPOL_MF_STRICT) ||
-		     ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
-		      vma_migratable(vma))) {
-
-			err = queue_pages_pgd_range(vma, start, endvma, nodes,
-						flags, private);
-			if (err) {
-				first = ERR_PTR(err);
-				break;
-			}
-		}
-next:
-		prev = vma;
-	}
-	return first;
+	struct queue_pages qp = {
+		.pagelist = pagelist,
+		.flags = flags,
+		.nmask = nodes,
+		.prev = NULL,
+	};
+	struct mm_walk queue_pages_walk = {
+		.hugetlb_entry = queue_pages_hugetlb,
+		.pte_entry = queue_pages_pte,
+		.test_walk = queue_pages_test_walk,
+		.mm = mm,
+		.private = &qp,
+	};
+
+	err = walk_page_range(start, end, &queue_pages_walk);
+	if (err < 0)
+		return ERR_PTR(err);
+	else
+		return find_vma(mm, start);
 }
 
 /*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 5dba2933c9c0..7cfdcd808f52 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2697,7 +2697,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
 	int migratetype = allocflags_to_migratetype(gfp_mask);
 	unsigned int cpuset_mems_cookie;
 	int alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET|ALLOC_FAIR;
-	struct mem_cgroup *memcg = NULL;
 
 	gfp_mask &= gfp_allowed_mask;
 
@@ -2716,13 +2715,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
 	if (unlikely(!zonelist->_zonerefs->zone))
 		return NULL;
 
-	/*
-	 * Will only have any effect when __GFP_KMEMCG is set.  This is
-	 * verified in the (always inline) callee
-	 */
-	if (!memcg_kmem_newpage_charge(gfp_mask, &memcg, order))
-		return NULL;
-
 retry_cpuset:
 	cpuset_mems_cookie = read_mems_allowed_begin();
 
@@ -2782,8 +2774,6 @@ out:
 	if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
 		goto retry_cpuset;
 
-	memcg_kmem_commit_charge(page, memcg, order);
-
 	return page;
 }
 EXPORT_SYMBOL(__alloc_pages_nodemask);
@@ -2837,27 +2827,51 @@ void free_pages(unsigned long addr, unsigned int order)
 EXPORT_SYMBOL(free_pages);
 
 /*
- * __free_memcg_kmem_pages and free_memcg_kmem_pages will free
- * pages allocated with __GFP_KMEMCG.
+ * alloc_kmem_pages charges newly allocated pages to the kmem resource counter
+ * of the current memory cgroup.
  *
- * Those pages are accounted to a particular memcg, embedded in the
- * corresponding page_cgroup. To avoid adding a hit in the allocator to search
- * for that information only to find out that it is NULL for users who have no
- * interest in that whatsoever, we provide these functions.
- *
- * The caller knows better which flags it relies on.
+ * It should be used when the caller would like to use kmalloc, but since the
+ * allocation is large, it has to fall back to the page allocator.
+ */
+struct page *alloc_kmem_pages(gfp_t gfp_mask, unsigned int order)
+{
+	struct page *page;
+	struct mem_cgroup *memcg = NULL;
+
+	if (!memcg_kmem_newpage_charge(gfp_mask, &memcg, order))
+		return NULL;
+	page = alloc_pages(gfp_mask, order);
+	memcg_kmem_commit_charge(page, memcg, order);
+	return page;
+}
+
+struct page *alloc_kmem_pages_node(int nid, gfp_t gfp_mask, unsigned int order)
+{
+	struct page *page;
+	struct mem_cgroup *memcg = NULL;
+
+	if (!memcg_kmem_newpage_charge(gfp_mask, &memcg, order))
+		return NULL;
+	page = alloc_pages_node(nid, gfp_mask, order);
+	memcg_kmem_commit_charge(page, memcg, order);
+	return page;
+}
+
+/*
+ * __free_kmem_pages and free_kmem_pages will free pages allocated with
+ * alloc_kmem_pages.
  */
-void __free_memcg_kmem_pages(struct page *page, unsigned int order)
+void __free_kmem_pages(struct page *page, unsigned int order)
 {
 	memcg_kmem_uncharge_pages(page, order);
 	__free_pages(page, order);
 }
 
-void free_memcg_kmem_pages(unsigned long addr, unsigned int order)
+void free_kmem_pages(unsigned long addr, unsigned int order)
 {
 	if (addr != 0) {
 		VM_BUG_ON(!virt_addr_valid((void *)addr));
-		__free_memcg_kmem_pages(virt_to_page((void *)addr), order);
+		__free_kmem_pages(virt_to_page((void *)addr), order);
 	}
 }
 
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index 2beeabf502c5..b2a075ffb96e 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -3,29 +3,58 @@
 #include <linux/sched.h>
 #include <linux/hugetlb.h>
 
-static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-			  struct mm_walk *walk)
+/*
+ * Check the current skip status of page table walker.
+ *
+ * Here what I mean by skip is to skip lower level walking, and that was
+ * determined for each entry independently. For example, when walk_pmd_range
+ * handles a pmd_trans_huge we don't have to walk over ptes under that pmd,
+ * and the skipping does not affect the walking over ptes under other pmds.
+ * That's why we reset @walk->skip after tested.
+ */
+static bool skip_lower_level_walking(struct mm_walk *walk)
 {
+	if (walk->skip) {
+		walk->skip = 0;
+		return true;
+	}
+	return false;
+}
+
+static int walk_pte_range(pmd_t *pmd, unsigned long addr,
+				unsigned long end, struct mm_walk *walk)
+{
+	struct mm_struct *mm = walk->mm;
 	pte_t *pte;
+	pte_t *orig_pte;
+	spinlock_t *ptl;
 	int err = 0;
 
-	pte = pte_offset_map(pmd, addr);
-	for (;;) {
+	orig_pte = pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+	do {
+		if (pte_none(*pte)) {
+			if (walk->pte_hole)
+				err = walk->pte_hole(addr, addr + PAGE_SIZE,
+							walk);
+			if (err)
+				break;
+			continue;
+		}
+		/*
+		 * Callers should have their own way to handle swap entries
+		 * in walk->pte_entry().
+		 */
 		err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, walk);
 		if (err)
 		       break;
-		addr += PAGE_SIZE;
-		if (addr == end)
-			break;
-		pte++;
-	}
-
-	pte_unmap(pte);
-	return err;
+	} while (pte++, addr += PAGE_SIZE, addr < end);
+	pte_unmap_unlock(orig_pte, ptl);
+	cond_resched();
+	return addr == end ? 0 : err;
 }
 
-static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
-			  struct mm_walk *walk)
+static int walk_pmd_range(pud_t *pud, unsigned long addr,
+				unsigned long end, struct mm_walk *walk)
 {
 	pmd_t *pmd;
 	unsigned long next;
@@ -35,6 +64,7 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
 	do {
 again:
 		next = pmd_addr_end(addr, end);
+
 		if (pmd_none(*pmd)) {
 			if (walk->pte_hole)
 				err = walk->pte_hole(addr, next, walk);
@@ -42,35 +72,32 @@ again:
 				break;
 			continue;
 		}
-		/*
-		 * This implies that each ->pmd_entry() handler
-		 * needs to know about pmd_trans_huge() pmds
-		 */
-		if (walk->pmd_entry)
-			err = walk->pmd_entry(pmd, addr, next, walk);
-		if (err)
-			break;
 
-		/*
-		 * Check this here so we only break down trans_huge
-		 * pages when we _need_ to
-		 */
-		if (!walk->pte_entry)
-			continue;
+		if (walk->pmd_entry) {
+			err = walk->pmd_entry(pmd, addr, next, walk);
+			if (skip_lower_level_walking(walk))
+				continue;
+			if (err)
+				break;
+		}
 
-		split_huge_page_pmd_mm(walk->mm, addr, pmd);
-		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
-			goto again;
-		err = walk_pte_range(pmd, addr, next, walk);
-		if (err)
-			break;
-	} while (pmd++, addr = next, addr != end);
+		if (walk->pte_entry) {
+			if (walk->vma) {
+				split_huge_page_pmd(walk->vma, addr, pmd);
+				if (pmd_trans_unstable(pmd))
+					goto again;
+			}
+			err = walk_pte_range(pmd, addr, next, walk);
+			if (err)
+				break;
+		}
+	} while (pmd++, addr = next, addr < end);
 
 	return err;
 }
 
-static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
-			  struct mm_walk *walk)
+static int walk_pud_range(pgd_t *pgd, unsigned long addr,
+				unsigned long end, struct mm_walk *walk)
 {
 	pud_t *pud;
 	unsigned long next;
@@ -79,6 +106,7 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
 	pud = pud_offset(pgd, addr);
 	do {
 		next = pud_addr_end(addr, end);
+
 		if (pud_none_or_clear_bad(pud)) {
 			if (walk->pte_hole)
 				err = walk->pte_hole(addr, next, walk);
@@ -86,13 +114,58 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
 				break;
 			continue;
 		}
-		if (walk->pud_entry)
+
+		if (walk->pud_entry) {
 			err = walk->pud_entry(pud, addr, next, walk);
-		if (!err && (walk->pmd_entry || walk->pte_entry))
+			if (skip_lower_level_walking(walk))
+				continue;
+			if (err)
+				break;
+		}
+
+		if (walk->pmd_entry || walk->pte_entry) {
 			err = walk_pmd_range(pud, addr, next, walk);
-		if (err)
-			break;
-	} while (pud++, addr = next, addr != end);
+			if (err)
+				break;
+		}
+	} while (pud++, addr = next, addr < end);
+
+	return err;
+}
+
+static int walk_pgd_range(unsigned long addr, unsigned long end,
+			struct mm_walk *walk)
+{
+	pgd_t *pgd;
+	unsigned long next;
+	int err = 0;
+
+	pgd = pgd_offset(walk->mm, addr);
+	do {
+		next = pgd_addr_end(addr, end);
+
+		if (pgd_none_or_clear_bad(pgd)) {
+			if (walk->pte_hole)
+				err = walk->pte_hole(addr, next, walk);
+			if (err)
+				break;
+			continue;
+		}
+
+		if (walk->pgd_entry) {
+			err = walk->pgd_entry(pgd, addr, next, walk);
+			if (skip_lower_level_walking(walk))
+				continue;
+			if (err)
+				break;
+		}
+
+		if (walk->pud_entry || walk->pmd_entry || walk->pte_entry) {
+			err = walk_pud_range(pgd, addr, next, walk);
+			if (err)
+				break;
+		}
+	} while (pgd++, addr = next, addr < end);
 
 	return err;
 }
@@ -105,144 +178,180 @@ static unsigned long hugetlb_entry_end(struct hstate *h, unsigned long addr,
 	return boundary < end ? boundary : end;
 }
 
-static int walk_hugetlb_range(struct vm_area_struct *vma,
-			      unsigned long addr, unsigned long end,
-			      struct mm_walk *walk)
+static int walk_hugetlb_range(unsigned long addr, unsigned long end,
+				struct mm_walk *walk)
 {
+	struct mm_struct *mm = walk->mm;
+	struct vm_area_struct *vma = walk->vma;
 	struct hstate *h = hstate_vma(vma);
 	unsigned long next;
 	unsigned long hmask = huge_page_mask(h);
 	pte_t *pte;
 	int err = 0;
+	spinlock_t *ptl;
 
 	do {
 		next = hugetlb_entry_end(h, addr, end);
 		pte = huge_pte_offset(walk->mm, addr & hmask);
-		if (pte && walk->hugetlb_entry)
-			err = walk->hugetlb_entry(pte, hmask, addr, next, walk);
+		if (!pte)
+			continue;
+		ptl = huge_pte_lock(h, mm, pte);
+		/*
+		 * Callers should have their own way to handle swap entries
+		 * in walk->hugetlb_entry().
+		 */
+		if (walk->hugetlb_entry)
+			err = walk->hugetlb_entry(pte, addr, next, walk);
+		spin_unlock(ptl);
 		if (err)
-			return err;
+			break;
 	} while (addr = next, addr != end);
-
-	return 0;
+	cond_resched();
+	return err;
 }
 
 #else /* CONFIG_HUGETLB_PAGE */
-static int walk_hugetlb_range(struct vm_area_struct *vma,
-			      unsigned long addr, unsigned long end,
-			      struct mm_walk *walk)
+static inline int walk_hugetlb_range(unsigned long addr, unsigned long end,
+				struct mm_walk *walk)
 {
 	return 0;
 }
 
 #endif /* CONFIG_HUGETLB_PAGE */
 
+/*
+ * Decide whether we really walk over the current vma on [@start, @end)
+ * or skip it. When we skip it, we set @walk->skip to 1.
+ * The return value is used to control the page table walking to
+ * continue (for zero) or not (for non-zero).
+ *
+ * Default check (only VM_PFNMAP check for now) is used when the caller
+ * doesn't define test_walk() callback.
+ */
+static int walk_page_test(unsigned long start, unsigned long end,
+			struct mm_walk *walk)
+{
+	struct vm_area_struct *vma = walk->vma;
+
+	if (walk->test_walk)
+		return walk->test_walk(start, end, walk);
 
+	/*
+	 * Do not walk over vma(VM_PFNMAP), because we have no valid struct
+	 * page backing a VM_PFNMAP range. See also commit a9ff785e4437.
+	 */
+	if (vma->vm_flags & VM_PFNMAP)
+		walk->skip = 1;
+	return 0;
+}
+
+static int __walk_page_range(unsigned long start, unsigned long end,
+			struct mm_walk *walk)
+{
+	int err = 0;
+	struct vm_area_struct *vma = walk->vma;
+
+	if (vma && is_vm_hugetlb_page(vma)) {
+		if (walk->hugetlb_entry)
+			err = walk_hugetlb_range(start, end, walk);
+	} else
+		err = walk_pgd_range(start, end, walk);
+
+	return err;
+}
 
 /**
- * walk_page_range - walk a memory map's page tables with a callback
- * @addr: starting address
- * @end: ending address
- * @walk: set of callbacks to invoke for each level of the tree
+ * walk_page_range - walk page table with caller specific callbacks
+ *
+ * Recursively walk the page table tree of the process represented by
+ * @walk->mm within the virtual address range [@start, @end). In walking,
+ * we can call caller-specific callback functions against each entry.
  *
- * Recursively walk the page table for the memory area in a VMA,
- * calling supplied callbacks. Callbacks are called in-order (first
- * PGD, first PUD, first PMD, first PTE, second PTE... second PMD,
- * etc.). If lower-level callbacks are omitted, walking depth is reduced.
+ * Before starting to walk page table, some callers want to check whether
+ * they really want to walk over the vma (for example by checking vm_flags.)
+ * walk_page_test() and @walk->test_walk() do that check.
  *
- * Each callback receives an entry pointer and the start and end of the
- * associated range, and a copy of the original mm_walk for access to
- * the ->private or ->mm fields.
+ * If any callback returns a non-zero value, the page table walk is aborted
+ * immediately and the return value is propagated back to the caller.
+ * Note that the meaning of the positive returned value can be defined
+ * by the caller for its own purpose.
  *
- * Usually no locks are taken, but splitting transparent huge page may
- * take page table lock. And the bottom level iterator will map PTE
- * directories from highmem if necessary.
+ * If the caller defines multiple callbacks in different levels, the
+ * callbacks are called in depth-first manner. It could happen that
+ * multiple callbacks are called on a address. For example if some caller
+ * defines test_walk(), pmd_entry(), and pte_entry(), then callbacks are
+ * called in the order of test_walk(), pmd_entry(), and pte_entry().
+ * If you don't want to go down to lower level at some point and move to
+ * the next entry in the same level, you set @walk->skip to 1.
+ * For example if you succeed to handle some pmd entry as trans_huge entry,
+ * you need not call walk_pte_range() any more, so set it to avoid that.
+ * We can't determine whether to go down to lower level with the return
+ * value of the callback, because the whole range of return values (0, >0,
+ * and <0) are used up for other meanings.
  *
- * If any callback returns a non-zero value, the walk is aborted and
- * the return value is propagated back to the caller. Otherwise 0 is returned.
+ * Each callback can access to the vma over which it is doing page table
+ * walk right now via @walk->vma. @walk->vma is set to NULL in walking
+ * outside a vma. If you want to access to some caller-specific data from
+ * callbacks, @walk->private should be helpful.
  *
- * walk->mm->mmap_sem must be held for at least read if walk->hugetlb_entry
- * is !NULL.
+ * The callers should hold @walk->mm->mmap_sem. Note that the lower level
+ * iterators can take page table lock in lowest level iteration and/or
+ * in split_huge_page_pmd().
  */
-int walk_page_range(unsigned long addr, unsigned long end,
+int walk_page_range(unsigned long start, unsigned long end,
 		    struct mm_walk *walk)
 {
-	pgd_t *pgd;
-	unsigned long next;
 	int err = 0;
+	struct vm_area_struct *vma;
+	unsigned long next;
 
-	if (addr >= end)
-		return err;
+	if (start >= end)
+		return -EINVAL;
 
 	if (!walk->mm)
 		return -EINVAL;
 
 	VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem));
 
-	pgd = pgd_offset(walk->mm, addr);
 	do {
-		struct vm_area_struct *vma = NULL;
+		vma = find_vma(walk->mm, start);
+		if (!vma) { /* after the last vma */
+			walk->vma = NULL;
+			next = end;
+		} else if (start < vma->vm_start) { /* outside the found vma */
+			walk->vma = NULL;
+			next = vma->vm_start;
+		} else { /* inside the found vma */
+			walk->vma = vma;
+			next = min(end, vma->vm_end);
 
-		next = pgd_addr_end(addr, end);
-
-		/*
-		 * This function was not intended to be vma based.
-		 * But there are vma special cases to be handled:
-		 * - hugetlb vma's
-		 * - VM_PFNMAP vma's
-		 */
-		vma = find_vma(walk->mm, addr);
-		if (vma) {
-			/*
-			 * There are no page structures backing a VM_PFNMAP
-			 * range, so do not allow split_huge_page_pmd().
-			 */
-			if ((vma->vm_start <= addr) &&
-			    (vma->vm_flags & VM_PFNMAP)) {
-				next = vma->vm_end;
-				pgd = pgd_offset(walk->mm, next);
-				continue;
-			}
-			/*
-			 * Handle hugetlb vma individually because pagetable
-			 * walk for the hugetlb page is dependent on the
-			 * architecture and we can't handled it in the same
-			 * manner as non-huge pages.
-			 */
-			if (walk->hugetlb_entry && (vma->vm_start <= addr) &&
-			    is_vm_hugetlb_page(vma)) {
-				if (vma->vm_end < next)
-					next = vma->vm_end;
-				/*
-				 * Hugepage is very tightly coupled with vma,
-				 * so walk through hugetlb entries within a
-				 * given vma.
-				 */
-				err = walk_hugetlb_range(vma, addr, next, walk);
-				if (err)
-					break;
-				pgd = pgd_offset(walk->mm, next);
+			err = walk_page_test(start, next, walk);
+			if (skip_lower_level_walking(walk))
 				continue;
-			}
-		}
-
-		if (pgd_none_or_clear_bad(pgd)) {
-			if (walk->pte_hole)
-				err = walk->pte_hole(addr, next, walk);
 			if (err)
 				break;
-			pgd++;
-			continue;
 		}
-		if (walk->pgd_entry)
-			err = walk->pgd_entry(pgd, addr, next, walk);
-		if (!err &&
-		    (walk->pud_entry || walk->pmd_entry || walk->pte_entry))
-			err = walk_pud_range(pgd, addr, next, walk);
+		err = __walk_page_range(start, next, walk);
 		if (err)
 			break;
-		pgd++;
-	} while (addr = next, addr < end);
-
+	} while (start = next, start < end);
 	return err;
 }
+
+int walk_page_vma(struct vm_area_struct *vma, struct mm_walk *walk)
+{
+	int err;
+
+	if (!walk->mm)
+		return -EINVAL;
+
+	VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem));
+	VM_BUG_ON(!vma);
+	walk->vma = vma;
+	err = walk_page_test(vma->vm_start, vma->vm_end, walk);
+	if (skip_lower_level_walking(walk))
+		return 0;
+	if (err)
+		return err;
+	return __walk_page_range(vma->vm_start, vma->vm_end, walk);
+}
diff --git a/mm/percpu.c b/mm/percpu.c
index 63e24fb4387b..2ddf9a990dbd 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -610,7 +610,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void)
 	chunk->map = pcpu_mem_zalloc(PCPU_DFL_MAP_ALLOC *
 						sizeof(chunk->map[0]));
 	if (!chunk->map) {
-		kfree(chunk);
+		pcpu_mem_free(chunk, pcpu_chunk_struct_size);
 		return NULL;
 	}
 
diff --git a/mm/rmap.c b/mm/rmap.c
index 9c3e77396d1a..e065ba798fde 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -515,11 +515,7 @@ void page_unlock_anon_vma_read(struct anon_vma *anon_vma)
 static inline unsigned long
 __vma_address(struct page *page, struct vm_area_struct *vma)
 {
-	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-
-	if (unlikely(is_vm_hugetlb_page(vma)))
-		pgoff = page->index << huge_page_order(page_hstate(page));
-
+	pgoff_t pgoff = page_pgoff(page);
 	return vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
 }
 
@@ -1024,7 +1020,7 @@ void page_add_new_anon_rmap(struct page *page,
 	__mod_zone_page_state(page_zone(page), NR_ANON_PAGES,
 			hpage_nr_pages(page));
 	__page_set_anon_rmap(page, vma, address, 1);
-	if (!mlocked_vma_newpage(vma, page)) {
+	if (!mlocked_vma_newpage(vma, page) && !PageUnevictable(page)) {
 		SetPageActive(page);
 		lru_cache_add(page);
 	} else
@@ -1359,7 +1355,7 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
 		if (page->index != linear_page_index(vma, address)) {
 			pte_t ptfile = pgoff_to_pte(page->index);
 			if (pte_soft_dirty(pteval))
-				pte_file_mksoft_dirty(ptfile);
+				ptfile = pte_file_mksoft_dirty(ptfile);
 			set_pte_at(mm, address, pte, ptfile);
 		}
 
@@ -1609,7 +1605,7 @@ static struct anon_vma *rmap_walk_anon_lock(struct page *page,
 static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc)
 {
 	struct anon_vma *anon_vma;
-	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+	pgoff_t pgoff = page_pgoff(page);
 	struct anon_vma_chain *avc;
 	int ret = SWAP_AGAIN;
 
@@ -1650,7 +1646,7 @@ static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc)
 static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc)
 {
 	struct address_space *mapping = page->mapping;
-	pgoff_t pgoff = page->index << compound_order(page);
+	pgoff_t pgoff = page_pgoff(page);
 	struct vm_area_struct *vma;
 	int ret = SWAP_AGAIN;
 
diff --git a/mm/slab.c b/mm/slab.c
index 388cb1ae6fbc..cbcd2fa7af2f 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1681,8 +1681,12 @@ static struct page *kmem_getpages(struct kmem_cache *cachep, gfp_t flags,
 	if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
 		flags |= __GFP_RECLAIMABLE;
 
+	if (memcg_charge_slab(cachep, flags, cachep->gfporder))
+		return NULL;
+
 	page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder);
 	if (!page) {
+		memcg_uncharge_slab(cachep, cachep->gfporder);
 		if (!(flags & __GFP_NOWARN) && printk_ratelimit())
 			slab_out_of_memory(cachep, flags, nodeid);
 		return NULL;
@@ -1741,7 +1745,8 @@ static void kmem_freepages(struct kmem_cache *cachep, struct page *page)
 	memcg_release_pages(cachep, cachep->gfporder);
 	if (current->reclaim_state)
 		current->reclaim_state->reclaimed_slab += nr_freed;
-	__free_memcg_kmem_pages(page, cachep->gfporder);
+	__free_pages(page, cachep->gfporder);
+	memcg_uncharge_slab(cachep, cachep->gfporder);
 }
 
 static void kmem_rcu_free(struct rcu_head *head)
diff --git a/mm/slab.h b/mm/slab.h
index 3045316b7c9d..3db3c52f80a2 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -191,6 +191,26 @@ static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
 		return s;
 	return s->memcg_params->root_cache;
 }
+
+static __always_inline int memcg_charge_slab(struct kmem_cache *s,
+					     gfp_t gfp, int order)
+{
+	if (!memcg_kmem_enabled())
+		return 0;
+	if (is_root_cache(s))
+		return 0;
+	return memcg_charge_kmem(s->memcg_params->memcg, gfp,
+				 PAGE_SIZE << order);
+}
+
+static __always_inline void memcg_uncharge_slab(struct kmem_cache *s, int order)
+{
+	if (!memcg_kmem_enabled())
+		return;
+	if (is_root_cache(s))
+		return;
+	memcg_uncharge_kmem(s->memcg_params->memcg, PAGE_SIZE << order);
+}
 #else
 static inline bool is_root_cache(struct kmem_cache *s)
 {
@@ -226,6 +246,15 @@ static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
 {
 	return s;
 }
+
+static inline int memcg_charge_slab(struct kmem_cache *s, gfp_t gfp, int order)
+{
+	return 0;
+}
+
+static inline void memcg_uncharge_slab(struct kmem_cache *s, int order)
+{
+}
 #endif
 
 static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
diff --git a/mm/slab_common.c b/mm/slab_common.c
index f3cfccf76dda..963f0376e4c1 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -290,12 +290,8 @@ void kmem_cache_create_memcg(struct mem_cgroup *memcg, struct kmem_cache *root_c
 				 root_cache->size, root_cache->align,
 				 root_cache->flags, root_cache->ctor,
 				 memcg, root_cache);
-	if (IS_ERR(s)) {
+	if (IS_ERR(s))
 		kfree(cache_name);
-		goto out_unlock;
-	}
-
-	s->allocflags |= __GFP_KMEMCG;
 
 out_unlock:
 	mutex_unlock(&slab_mutex);
@@ -577,6 +573,19 @@ void __init create_kmalloc_caches(unsigned long flags)
 }
 #endif /* !CONFIG_SLOB */
 
+void *kmalloc_order(size_t size, gfp_t flags, unsigned int order)
+{
+	void *ret;
+	struct page *page;
+
+	flags |= __GFP_COMP;
+	page = alloc_kmem_pages(flags, order);
+	ret = page ? page_address(page) : NULL;
+	kmemleak_alloc(ret, size, 1, flags);
+	return ret;
+}
+EXPORT_SYMBOL(kmalloc_order);
+
 #ifdef CONFIG_TRACING
 void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
 {
diff --git a/mm/slub.c b/mm/slub.c
index 5e234f1f8853..fa7a1817835e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1317,17 +1317,26 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x)
 /*
  * Slab allocation and freeing
  */
-static inline struct page *alloc_slab_page(gfp_t flags, int node,
-					struct kmem_cache_order_objects oo)
+static inline struct page *alloc_slab_page(struct kmem_cache *s,
+		gfp_t flags, int node, struct kmem_cache_order_objects oo)
 {
+	struct page *page;
 	int order = oo_order(oo);
 
 	flags |= __GFP_NOTRACK;
 
+	if (memcg_charge_slab(s, flags, order))
+		return NULL;
+
 	if (node == NUMA_NO_NODE)
-		return alloc_pages(flags, order);
+		page = alloc_pages(flags, order);
 	else
-		return alloc_pages_exact_node(node, flags, order);
+		page = alloc_pages_exact_node(node, flags, order);
+
+	if (!page)
+		memcg_uncharge_slab(s, order);
+
+	return page;
 }
 
 static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
@@ -1349,7 +1358,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
 	 */
 	alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;
 
-	page = alloc_slab_page(alloc_gfp, node, oo);
+	page = alloc_slab_page(s, alloc_gfp, node, oo);
 	if (unlikely(!page)) {
 		oo = s->min;
 		alloc_gfp = flags;
@@ -1357,7 +1366,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
 		 * Allocation may have failed due to fragmentation.
 		 * Try a lower order alloc if possible
 		 */
-		page = alloc_slab_page(alloc_gfp, node, oo);
+		page = alloc_slab_page(s, alloc_gfp, node, oo);
 
 		if (page)
 			stat(s, ORDER_FALLBACK);
@@ -1473,7 +1482,8 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
 	page_mapcount_reset(page);
 	if (current->reclaim_state)
 		current->reclaim_state->reclaimed_slab += pages;
-	__free_memcg_kmem_pages(page, order);
+	__free_pages(page, order);
+	memcg_uncharge_slab(s, order);
 }
 
 #define need_reserve_slab_rcu						\
@@ -3325,8 +3335,8 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node)
 	struct page *page;
 	void *ptr = NULL;
 
-	flags |= __GFP_COMP | __GFP_NOTRACK | __GFP_KMEMCG;
-	page = alloc_pages_node(node, flags, get_order(size));
+	flags |= __GFP_COMP | __GFP_NOTRACK;
+	page = alloc_kmem_pages_node(node, flags, get_order(size));
 	if (page)
 		ptr = page_address(page);
 
@@ -3395,7 +3405,7 @@ void kfree(const void *x)
 	if (unlikely(!PageSlab(page))) {
 		BUG_ON(!PageCompound(page));
 		kfree_hook(x);
-		__free_memcg_kmem_pages(page, compound_order(page));
+		__free_kmem_pages(page, compound_order(page));
 		return;
 	}
 	slab_free(page->slab_cache, page, object, _RET_IP_);
diff --git a/mm/util.c b/mm/util.c
index f380af7ea779..efadeaaef81e 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -3,6 +3,7 @@
 #include <linux/string.h>
 #include <linux/compiler.h>
 #include <linux/export.h>
+#include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/sched.h>
 #include <linux/security.h>
@@ -64,6 +65,35 @@ char *kstrndup(const char *s, size_t max, gfp_t gfp)
 EXPORT_SYMBOL(kstrndup);
 
 /**
+ * kstrimdup - Trim and copy a %NUL terminated string.
+ * @s: the string to trim and duplicate
+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
+ *
+ * Returns an address, which the caller must kfree, containing
+ * a duplicate of the passed string with leading and/or trailing
+ * whitespace (as defined by isspace) removed.
+ */
+char *kstrimdup(const char *s, gfp_t gfp)
+{
+	char *buf;
+	char *begin = skip_spaces(s);
+	size_t len = strlen(begin);
+
+	while (len && isspace(begin[len - 1]))
+		len--;
+
+	buf = kmalloc_track_caller(len + 1, gfp);
+	if (!buf)
+		return NULL;
+
+	memcpy(buf, begin, len);
+	buf[len] = '\0';
+
+	return buf;
+}
+EXPORT_SYMBOL(kstrimdup);
+
+/**
  * kmemdup - duplicate region of memory
  *
  * @src: memory region to duplicate
diff --git a/mm/vmacache.c b/mm/vmacache.c
index d4224b397c0e..61c38ae9f54b 100644
--- a/mm/vmacache.c
+++ b/mm/vmacache.c
@@ -17,6 +17,16 @@ void vmacache_flush_all(struct mm_struct *mm)
 {
 	struct task_struct *g, *p;
 
+	/*
+	 * Single threaded tasks need not iterate the entire
+	 * list of process. We can avoid the flushing as well
+	 * since the mm's seqnum was increased and don't have
+	 * to worry about other threads' seqnum. Current's
+	 * flush will occur upon the next lookup.
+	 */
+	if (atomic_read(&mm->mm_users) == 1)
+		return;
+
 	rcu_read_lock();
 	for_each_process_thread(g, p) {
 		/*
@@ -78,11 +88,14 @@ struct vm_area_struct *vmacache_find(struct mm_struct *mm, unsigned long addr)
 	if (!vmacache_valid(mm))
 		return NULL;
 
+	count_vm_vmacache_event(VMACACHE_FIND_CALLS);
+
 	for (i = 0; i < VMACACHE_SIZE; i++) {
 		struct vm_area_struct *vma = current->vmacache[i];
 
 		if (vma && vma->vm_start <= addr && vma->vm_end > addr) {
 			BUG_ON(vma->vm_mm != mm);
+			count_vm_vmacache_event(VMACACHE_FIND_HITS);
 			return vma;
 		}
 	}
@@ -100,11 +113,15 @@ struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm,
 	if (!vmacache_valid(mm))
 		return NULL;
 
+	count_vm_vmacache_event(VMACACHE_FIND_CALLS);
+
 	for (i = 0; i < VMACACHE_SIZE; i++) {
 		struct vm_area_struct *vma = current->vmacache[i];
 
-		if (vma && vma->vm_start == start && vma->vm_end == end)
+		if (vma && vma->vm_start == start && vma->vm_end == end) {
+			count_vm_vmacache_event(VMACACHE_FIND_HITS);
 			return vma;
+		}
 	}
 
 	return NULL;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9b6497eda806..6cdda104f629 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1158,7 +1158,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
 			TTU_UNMAP|TTU_IGNORE_ACCESS,
 			&dummy1, &dummy2, &dummy3, &dummy4, &dummy5, true);
 	list_splice(&clean_pages, page_list);
-	__mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret);
+	mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret);
 	return ret;
 }
 
@@ -1866,6 +1866,8 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
 	bool force_scan = false;
 	unsigned long ap, fp;
 	enum lru_list lru;
+	bool some_scanned;
+	int pass;
 
 	/*
 	 * If the zone or memcg is small, nr[l] can be 0.  This
@@ -1971,39 +1973,49 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
 	fraction[1] = fp;
 	denominator = ap + fp + 1;
 out:
-	for_each_evictable_lru(lru) {
-		int file = is_file_lru(lru);
-		unsigned long size;
-		unsigned long scan;
+	some_scanned = false;
+	/* Only use force_scan on second pass. */
+	for (pass = 0; !some_scanned && pass < 2; pass++) {
+		for_each_evictable_lru(lru) {
+			int file = is_file_lru(lru);
+			unsigned long size;
+			unsigned long scan;
 
-		size = get_lru_size(lruvec, lru);
-		scan = size >> sc->priority;
+			size = get_lru_size(lruvec, lru);
+			scan = size >> sc->priority;
 
-		if (!scan && force_scan)
-			scan = min(size, SWAP_CLUSTER_MAX);
+			if (!scan && pass && force_scan)
+				scan = min(size, SWAP_CLUSTER_MAX);
 
-		switch (scan_balance) {
-		case SCAN_EQUAL:
-			/* Scan lists relative to size */
-			break;
-		case SCAN_FRACT:
+			switch (scan_balance) {
+			case SCAN_EQUAL:
+				/* Scan lists relative to size */
+				break;
+			case SCAN_FRACT:
+				/*
+				 * Scan types proportional to swappiness and
+				 * their relative recent reclaim efficiency.
+				 */
+				scan = div64_u64(scan * fraction[file],
+							denominator);
+				break;
+			case SCAN_FILE:
+			case SCAN_ANON:
+				/* Scan one type exclusively */
+				if ((scan_balance == SCAN_FILE) != file)
+					scan = 0;
+				break;
+			default:
+				/* Look ma, no brain */
+				BUG();
+			}
+			nr[lru] = scan;
 			/*
-			 * Scan types proportional to swappiness and
-			 * their relative recent reclaim efficiency.
+			 * Skip the second pass and don't force_scan,
+			 * if we found something to scan.
 			 */
-			scan = div64_u64(scan * fraction[file], denominator);
-			break;
-		case SCAN_FILE:
-		case SCAN_ANON:
-			/* Scan one type exclusively */
-			if ((scan_balance == SCAN_FILE) != file)
-				scan = 0;
-			break;
-		default:
-			/* Look ma, no brain */
-			BUG();
+			some_scanned |= !!scan;
 		}
-		nr[lru] = scan;
 	}
 }
 
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 302dd076b8bf..82ce17ce58c4 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -866,6 +866,10 @@ const char * const vmstat_text[] = {
 	"nr_tlb_local_flush_one",
 #endif /* CONFIG_DEBUG_TLBFLUSH */
 
+#ifdef CONFIG_DEBUG_VM_VMACACHE
+	"vmacache_find_calls",
+	"vmacache_find_hits",
+#endif
 #endif /* CONFIG_VM_EVENTS_COUNTERS */
 };
 #endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d958e2dca52f..095943c02d6e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -367,9 +367,23 @@ static void le_conn_timeout(struct work_struct *work)
 {
 	struct hci_conn *conn = container_of(work, struct hci_conn,
 					     le_conn_timeout.work);
+	struct hci_dev *hdev = conn->hdev;
 
 	BT_DBG("");
 
+	/* We could end up here due to having done directed advertising,
+	 * so clean up the state if necessary. This should however only
+	 * happen with broken hardware or if low duty cycle was used
+	 * (which doesn't have a timeout of its own).
+	 */
+	if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
+		u8 enable = 0x00;
+		hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
+			     &enable);
+		hci_le_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
+		return;
+	}
+
 	hci_le_create_connection_cancel(conn);
 }
 
@@ -401,6 +415,10 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 	case ACL_LINK:
 		conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
 		break;
+	case LE_LINK:
+		/* conn->src should reflect the local identity address */
+		hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
+		break;
 	case SCO_LINK:
 		if (lmp_esco_capable(hdev))
 			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
@@ -545,6 +563,11 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 	 * favor of connection establishment, we should restart it.
 	 */
 	hci_update_background_scan(hdev);
+
+	/* Re-enable advertising in case this was a failed connection
+	 * attempt as a peripheral.
+	 */
+	mgmt_reenable_advertising(hdev);
 }
 
 static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
@@ -605,6 +628,45 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
 	conn->state = BT_CONNECT;
 }
 
+static void hci_req_directed_advertising(struct hci_request *req,
+					 struct hci_conn *conn)
+{
+	struct hci_dev *hdev = req->hdev;
+	struct hci_cp_le_set_adv_param cp;
+	u8 own_addr_type;
+	u8 enable;
+
+	enable = 0x00;
+	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+
+	/* Clear the HCI_ADVERTISING bit temporarily so that the
+	 * hci_update_random_address knows that it's safe to go ahead
+	 * and write a new random address. The flag will be set back on
+	 * as soon as the SET_ADV_ENABLE HCI command completes.
+	 */
+	clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
+
+	/* Set require_privacy to false so that the remote device has a
+	 * chance of identifying us.
+	 */
+	if (hci_update_random_address(req, false, &own_addr_type) < 0)
+		return;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.type = LE_ADV_DIRECT_IND;
+	cp.own_address_type = own_addr_type;
+	cp.direct_addr_type = conn->dst_type;
+	bacpy(&cp.direct_addr, &conn->dst);
+	cp.channel_map = hdev->le_adv_channel_map;
+
+	hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
+
+	enable = 0x01;
+	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+
+	conn->state = BT_CONNECT;
+}
+
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 				u8 dst_type, u8 sec_level, u8 auth_type)
 {
@@ -614,9 +676,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 	struct hci_request req;
 	int err;
 
-	if (test_bit(HCI_ADVERTISING, &hdev->flags))
-		return ERR_PTR(-ENOTSUPP);
-
 	/* Some devices send ATT messages as soon as the physical link is
 	 * established. To be able to handle these ATT messages, the user-
 	 * space first establishes the connection and then starts the pairing
@@ -664,13 +723,20 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 		return ERR_PTR(-ENOMEM);
 
 	conn->dst_type = dst_type;
-
-	conn->out = true;
-	conn->link_mode |= HCI_LM_MASTER;
 	conn->sec_level = BT_SECURITY_LOW;
 	conn->pending_sec_level = sec_level;
 	conn->auth_type = auth_type;
 
+	hci_req_init(&req, hdev);
+
+	if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
+		hci_req_directed_advertising(&req, conn);
+		goto create_conn;
+	}
+
+	conn->out = true;
+	conn->link_mode |= HCI_LM_MASTER;
+
 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
 	if (params) {
 		conn->le_conn_min_interval = params->conn_min_interval;
@@ -680,8 +746,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
 	}
 
-	hci_req_init(&req, hdev);
-
 	/* If controller is scanning, we stop it since some controllers are
 	 * not able to scan and connect at the same time. Also set the
 	 * HCI_LE_SCAN_INTERRUPTED flag so that the command complete
@@ -695,6 +759,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 
 	hci_req_add_le_create_conn(&req, conn);
 
+create_conn:
 	err = hci_req_run(&req, create_le_conn_complete);
 	if (err) {
 		hci_conn_del(conn);
@@ -819,14 +884,17 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
 		struct hci_cp_auth_requested cp;
 
-		/* encrypt must be pending if auth is also pending */
-		set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
-
 		cp.handle = cpu_to_le16(conn->handle);
 		hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
 			     sizeof(cp), &cp);
+
+		/* If we're already encrypted set the REAUTH_PEND flag,
+		 * otherwise set the ENCRYPT_PEND.
+		 */
 		if (conn->key_type != 0xff)
 			set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
+		else
+			set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
 	}
 
 	return 0;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 1c6ffaa8902f..d31f144860d1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -955,14 +955,9 @@ static ssize_t le_auto_conn_write(struct file *file, const char __user *data,
 	if (count < 3)
 		return -EINVAL;
 
-	buf = kzalloc(count, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	if (copy_from_user(buf, data, count)) {
-		err = -EFAULT;
-		goto done;
-	}
+	buf = memdup_user(data, count);
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
 	if (memcmp(buf, "add", 3) == 0) {
 		n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu",
@@ -1828,6 +1823,9 @@ static int __hci_init(struct hci_dev *hdev)
 				    &lowpan_debugfs_fops);
 		debugfs_create_file("le_auto_conn", 0644, hdev->debugfs, hdev,
 				    &le_auto_conn_fops);
+		debugfs_create_u16("discov_interleaved_timeout", 0644,
+				   hdev->debugfs,
+				   &hdev->discov_interleaved_timeout);
 	}
 
 	return 0;
@@ -2033,12 +2031,11 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
 
 	hci_remove_remote_oob_data(hdev, &data->bdaddr);
 
-	if (ssp)
-		*ssp = data->ssp_mode;
+	*ssp = data->ssp_mode;
 
 	ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
 	if (ie) {
-		if (ie->data.ssp_mode && ssp)
+		if (ie->data.ssp_mode)
 			*ssp = true;
 
 		if (ie->name_state == NAME_NEEDED &&
@@ -3791,6 +3788,7 @@ struct hci_dev *hci_alloc_dev(void)
 	hdev->le_conn_max_interval = 0x0038;
 
 	hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
+	hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT;
 
 	mutex_init(&hdev->lock);
 	mutex_init(&hdev->req_lock);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 49774912cb01..ca19fd4bbb8f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -991,10 +991,25 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 	if (!sent)
 		return;
 
+	if (status)
+		return;
+
 	hci_dev_lock(hdev);
 
-	if (!status)
-		mgmt_advertising(hdev, *sent);
+	/* If we're doing connection initation as peripheral. Set a
+	 * timeout in case something goes wrong.
+	 */
+	if (*sent) {
+		struct hci_conn *conn;
+
+		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+		if (conn)
+			queue_delayed_work(hdev->workqueue,
+					   &conn->le_conn_timeout,
+					   HCI_LE_CONN_TIMEOUT);
+	}
+
+	mgmt_advertising(hdev, *sent);
 
 	hci_dev_unlock(hdev);
 }
@@ -1018,6 +1033,33 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
+static bool has_pending_adv_report(struct hci_dev *hdev)
+{
+	struct discovery_state *d = &hdev->discovery;
+
+	return bacmp(&d->last_adv_addr, BDADDR_ANY);
+}
+
+static void clear_pending_adv_report(struct hci_dev *hdev)
+{
+	struct discovery_state *d = &hdev->discovery;
+
+	bacpy(&d->last_adv_addr, BDADDR_ANY);
+	d->last_adv_data_len = 0;
+}
+
+static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				     u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
+{
+	struct discovery_state *d = &hdev->discovery;
+
+	bacpy(&d->last_adv_addr, bdaddr);
+	d->last_adv_addr_type = bdaddr_type;
+	d->last_adv_rssi = rssi;
+	memcpy(d->last_adv_data, data, len);
+	d->last_adv_data_len = len;
+}
+
 static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 				      struct sk_buff *skb)
 {
@@ -1036,9 +1078,25 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 	switch (cp->enable) {
 	case LE_SCAN_ENABLE:
 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
+		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
+			clear_pending_adv_report(hdev);
 		break;
 
 	case LE_SCAN_DISABLE:
+		/* We do this here instead of when setting DISCOVERY_STOPPED
+		 * since the latter would potentially require waiting for
+		 * inquiry to stop too.
+		 */
+		if (has_pending_adv_report(hdev)) {
+			struct discovery_state *d = &hdev->discovery;
+
+			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
+					  d->last_adv_addr_type, NULL,
+					  d->last_adv_rssi, 0, 1,
+					  d->last_adv_data,
+					  d->last_adv_data_len, NULL, 0);
+		}
+
 		/* Cancel this timer so that we don't try to disable scanning
 		 * when it's already disabled.
 		 */
@@ -1827,7 +1885,7 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 				  info->dev_class, 0, !name_known, ssp, NULL,
-				  0);
+				  0, NULL, 0);
 	}
 
 	hci_dev_unlock(hdev);
@@ -3102,7 +3160,7 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 							      false, &ssp);
 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 					  info->dev_class, info->rssi,
-					  !name_known, ssp, NULL, 0);
+					  !name_known, ssp, NULL, 0, NULL, 0);
 		}
 	} else {
 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
@@ -3120,7 +3178,7 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 							      false, &ssp);
 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 					  info->dev_class, info->rssi,
-					  !name_known, ssp, NULL, 0);
+					  !name_known, ssp, NULL, 0, NULL, 0);
 		}
 	}
 
@@ -3309,7 +3367,7 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 		eir_len = eir_get_length(info->data, sizeof(info->data));
 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 				  info->dev_class, info->rssi, !name_known,
-				  ssp, info->data, eir_len);
+				  ssp, info->data, eir_len, NULL, 0);
 	}
 
 	hci_dev_unlock(hdev);
@@ -3330,6 +3388,12 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
 	if (!conn)
 		goto unlock;
 
+	/* For BR/EDR the necessary steps are taken through the
+	 * auth_complete event.
+	 */
+	if (conn->type != LE_LINK)
+		goto unlock;
+
 	if (!ev->status)
 		conn->sec_level = conn->pending_sec_level;
 
@@ -3361,24 +3425,20 @@ unlock:
 
 static u8 hci_get_auth_req(struct hci_conn *conn)
 {
-	/* If remote requests dedicated bonding follow that lead */
-	if (conn->remote_auth == HCI_AT_DEDICATED_BONDING ||
-	    conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) {
-		/* If both remote and local IO capabilities allow MITM
-		 * protection then require it, otherwise don't */
-		if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT ||
-		    conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)
-			return HCI_AT_DEDICATED_BONDING;
-		else
-			return HCI_AT_DEDICATED_BONDING_MITM;
-	}
-
 	/* If remote requests no-bonding follow that lead */
 	if (conn->remote_auth == HCI_AT_NO_BONDING ||
 	    conn->remote_auth == HCI_AT_NO_BONDING_MITM)
 		return conn->remote_auth | (conn->auth_type & 0x01);
 
-	return conn->auth_type;
+	/* If both remote and local have enough IO capabilities, require
+	 * MITM protection
+	 */
+	if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
+	    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
+		return conn->remote_auth | 0x01;
+
+	/* No MITM protection possible so ignore remote requirement */
+	return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
 }
 
 static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -3408,8 +3468,21 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		 * to DisplayYesNo as it is not supported by BT spec. */
 		cp.capability = (conn->io_capability == 0x04) ?
 				HCI_IO_DISPLAY_YESNO : conn->io_capability;
-		conn->auth_type = hci_get_auth_req(conn);
-		cp.authentication = conn->auth_type;
+
+		/* If we are initiators, there is no remote information yet */
+		if (conn->remote_auth == 0xff) {
+			cp.authentication = conn->auth_type;
+
+			/* Request MITM protection if our IO caps allow it
+			 * except for the no-bonding case
+			 */
+			if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
+			    cp.authentication != HCI_AT_NO_BONDING)
+				cp.authentication |= 0x01;
+		} else {
+			conn->auth_type = hci_get_auth_req(conn);
+			cp.authentication = conn->auth_type;
+		}
 
 		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
@@ -3477,12 +3550,9 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 	rem_mitm = (conn->remote_auth & 0x01);
 
 	/* If we require MITM but the remote device can't provide that
-	 * (it has NoInputNoOutput) then reject the confirmation
-	 * request. The only exception is when we're dedicated bonding
-	 * initiators (connect_cfm_cb set) since then we always have the MITM
-	 * bit set. */
-	if (!conn->connect_cfm_cb && loc_mitm &&
-	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
+	 * (it has NoInputNoOutput) then reject the confirmation request
+	 */
+	if (loc_mitm && conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
 		BT_DBG("Rejecting request: remote device can't provide MITM");
 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
 			     sizeof(ev->bdaddr), &ev->bdaddr);
@@ -3840,17 +3910,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 		conn->dst_type = ev->bdaddr_type;
 
-		/* The advertising parameters for own address type
-		 * define which source address and source address
-		 * type this connections has.
-		 */
-		if (bacmp(&conn->src, BDADDR_ANY)) {
-			conn->src_type = ADDR_LE_DEV_PUBLIC;
-		} else {
-			bacpy(&conn->src, &hdev->static_addr);
-			conn->src_type = ADDR_LE_DEV_RANDOM;
-		}
-
 		if (ev->role == LE_CONN_ROLE_MASTER) {
 			conn->out = true;
 			conn->link_mode |= HCI_LM_MASTER;
@@ -3875,27 +3934,24 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 							  &conn->init_addr,
 							  &conn->init_addr_type);
 			}
-		} else {
-			/* Set the responder (our side) address type based on
-			 * the advertising address type.
-			 */
-			conn->resp_addr_type = hdev->adv_addr_type;
-			if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
-				bacpy(&conn->resp_addr, &hdev->random_addr);
-			else
-				bacpy(&conn->resp_addr, &hdev->bdaddr);
-
-			conn->init_addr_type = ev->bdaddr_type;
-			bacpy(&conn->init_addr, &ev->bdaddr);
 		}
 	} else {
 		cancel_delayed_work(&conn->le_conn_timeout);
 	}
 
-	/* Ensure that the hci_conn contains the identity address type
-	 * regardless of which address the connection was made with.
-	 */
-	hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
+	if (!conn->out) {
+		/* Set the responder (our side) address type based on
+		 * the advertising address type.
+		 */
+		conn->resp_addr_type = hdev->adv_addr_type;
+		if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM)
+			bacpy(&conn->resp_addr, &hdev->random_addr);
+		else
+			bacpy(&conn->resp_addr, &hdev->bdaddr);
+
+		conn->init_addr_type = ev->bdaddr_type;
+		bacpy(&conn->init_addr, &ev->bdaddr);
+	}
 
 	/* Lookup the identity address from the stored connection
 	 * address and address type.
@@ -3975,25 +4031,97 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
 	}
 }
 
+static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
+			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
+{
+	struct discovery_state *d = &hdev->discovery;
+	bool match;
+
+	/* Passive scanning shouldn't trigger any device found events */
+	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
+		if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND)
+			check_pending_le_conn(hdev, bdaddr, bdaddr_type);
+		return;
+	}
+
+	/* If there's nothing pending either store the data from this
+	 * event or send an immediate device found event if the data
+	 * should not be stored for later.
+	 */
+	if (!has_pending_adv_report(hdev)) {
+		/* If the report will trigger a SCAN_REQ store it for
+		 * later merging.
+		 */
+		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
+			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
+						 rssi, data, len);
+			return;
+		}
+
+		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
+				  rssi, 0, 1, data, len, NULL, 0);
+		return;
+	}
+
+	/* Check if the pending report is for the same device as the new one */
+	match = (!bacmp(bdaddr, &d->last_adv_addr) &&
+		 bdaddr_type == d->last_adv_addr_type);
+
+	/* If the pending data doesn't match this report or this isn't a
+	 * scan response (e.g. we got a duplicate ADV_IND) then force
+	 * sending of the pending data.
+	 */
+	if (type != LE_ADV_SCAN_RSP || !match) {
+		/* Send out whatever is in the cache, but skip duplicates */
+		if (!match)
+			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
+					  d->last_adv_addr_type, NULL,
+					  d->last_adv_rssi, 0, 1,
+					  d->last_adv_data,
+					  d->last_adv_data_len, NULL, 0);
+
+		/* If the new report will trigger a SCAN_REQ store it for
+		 * later merging.
+		 */
+		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
+			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
+						 rssi, data, len);
+			return;
+		}
+
+		/* The advertising reports cannot be merged, so clear
+		 * the pending report and send out a device found event.
+		 */
+		clear_pending_adv_report(hdev);
+		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
+				  rssi, 0, 1, data, len, NULL, 0);
+		return;
+	}
+
+	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
+	 * the new event is a SCAN_RSP. We can therefore proceed with
+	 * sending a merged device found event.
+	 */
+	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
+			  d->last_adv_addr_type, NULL, rssi, 0, 1, data, len,
+			  d->last_adv_data, d->last_adv_data_len);
+	clear_pending_adv_report(hdev);
+}
+
 static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	u8 num_reports = skb->data[0];
 	void *ptr = &skb->data[1];
-	s8 rssi;
 
 	hci_dev_lock(hdev);
 
 	while (num_reports--) {
 		struct hci_ev_le_advertising_info *ev = ptr;
-
-		if (ev->evt_type == LE_ADV_IND ||
-		    ev->evt_type == LE_ADV_DIRECT_IND)
-			check_pending_le_conn(hdev, &ev->bdaddr,
-					      ev->bdaddr_type);
+		s8 rssi;
 
 		rssi = ev->data[ev->length];
-		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
-				  NULL, rssi, 0, 1, ev->data, ev->length);
+		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
+				   ev->bdaddr_type, rssi, ev->data, ev->length);
 
 		ptr += sizeof(*ev) + ev->length + 1;
 	}
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c
index b3fbc73516c4..941ad7530eda 100644
--- a/net/bluetooth/lib.c
+++ b/net/bluetooth/lib.c
@@ -58,6 +58,7 @@ int bt_to_errno(__u16 code)
 		return EIO;
 
 	case 0x04:
+	case 0x3c:
 		return EHOSTDOWN;
 
 	case 0x05:
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d2d4e0d5aed0..54abbce3a39e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2850,10 +2850,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
 	}
 
 	sec_level = BT_SECURITY_MEDIUM;
-	if (cp->io_cap == 0x03)
-		auth_type = HCI_AT_DEDICATED_BONDING;
-	else
-		auth_type = HCI_AT_DEDICATED_BONDING_MITM;
+	auth_type = HCI_AT_DEDICATED_BONDING;
 
 	if (cp->addr.type == BDADDR_BREDR) {
 		conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
@@ -3351,6 +3348,8 @@ static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
 
 static void start_discovery_complete(struct hci_dev *hdev, u8 status)
 {
+	unsigned long timeout = 0;
+
 	BT_DBG("status %d", status);
 
 	if (status) {
@@ -3366,13 +3365,11 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status)
 
 	switch (hdev->discovery.type) {
 	case DISCOV_TYPE_LE:
-		queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
-				   DISCOV_LE_TIMEOUT);
+		timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
 		break;
 
 	case DISCOV_TYPE_INTERLEAVED:
-		queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
-				   DISCOV_INTERLEAVED_TIMEOUT);
+		timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
 		break;
 
 	case DISCOV_TYPE_BREDR:
@@ -3381,6 +3378,11 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status)
 	default:
 		BT_ERR("Invalid discovery type %d", hdev->discovery.type);
 	}
+
+	if (!timeout)
+		return;
+
+	queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
 }
 
 static int start_discovery(struct sock *sk, struct hci_dev *hdev,
@@ -5668,8 +5670,9 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
 }
 
 void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
-		       u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
-		       ssp, u8 *eir, u16 eir_len)
+		       u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
+		       u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
+		       u8 scan_rsp_len)
 {
 	char buf[512];
 	struct mgmt_ev_device_found *ev = (void *) buf;
@@ -5679,8 +5682,10 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 	if (!hci_discovery_active(hdev))
 		return;
 
-	/* Leave 5 bytes for a potential CoD field */
-	if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
+	/* Make sure that the buffer is big enough. The 5 extra bytes
+	 * are for the potential CoD field.
+	 */
+	if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
 		return;
 
 	memset(buf, 0, sizeof(buf));
@@ -5707,8 +5712,11 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
 					  dev_class, 3);
 
-	ev->eir_len = cpu_to_le16(eir_len);
-	ev_size = sizeof(*ev) + eir_len;
+	if (scan_rsp_len > 0)
+		memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
+
+	ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
+	ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
 
 	mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index 14dac0654f28..5b3042e69f85 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2284,7 +2284,7 @@ EXPORT_SYMBOL(skb_checksum_help);
 __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
 {
 	__be16 type = skb->protocol;
-	int vlan_depth = ETH_HLEN;
+	int vlan_depth = skb->mac_len;
 
 	/* Tunnel gso handlers can set protocol to ethernet. */
 	if (type == htons(ETH_P_TEB)) {
diff --git a/net/core/dst.c b/net/core/dst.c
index ca4231ec7347..80d6286c8b62 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -142,12 +142,12 @@ loop:
 	mutex_unlock(&dst_gc_mutex);
 }
 
-int dst_discard(struct sk_buff *skb)
+int dst_discard_sk(struct sock *sk, struct sk_buff *skb)
 {
 	kfree_skb(skb);
 	return 0;
 }
-EXPORT_SYMBOL(dst_discard);
+EXPORT_SYMBOL(dst_discard_sk);
 
 const u32 dst_default_metrics[RTAX_MAX + 1] = {
 	/* This initializer is needed to force linker to place this variable
@@ -184,7 +184,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
 	dst->xfrm = NULL;
 #endif
 	dst->input = dst_discard;
-	dst->output = dst_discard;
+	dst->output = dst_discard_sk;
 	dst->error = 0;
 	dst->obsolete = initial_obsolete;
 	dst->header_len = 0;
@@ -209,8 +209,10 @@ static void ___dst_free(struct dst_entry *dst)
 	/* The first case (dev==NULL) is required, when
 	   protocol module is unloaded.
 	 */
-	if (dst->dev == NULL || !(dst->dev->flags&IFF_UP))
-		dst->input = dst->output = dst_discard;
+	if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
+		dst->input = dst_discard;
+		dst->output = dst_discard_sk;
+	}
 	dst->obsolete = DST_OBSOLETE_DEAD;
 }
 
@@ -361,7 +363,8 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 		return;
 
 	if (!unregister) {
-		dst->input = dst->output = dst_discard;
+		dst->input = dst_discard;
+		dst->output = dst_discard_sk;
 	} else {
 		dst->dev = dev_net(dst->dev)->loopback_dev;
 		dev_hold(dst->dev);
diff --git a/net/core/filter.c b/net/core/filter.c
index e08b3822c72a..cd58614660cf 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -600,6 +600,9 @@ static u64 __skb_get_nlattr(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
 	if (skb_is_nonlinear(skb))
 		return 0;
 
+	if (skb->len < sizeof(struct nlattr))
+		return 0;
+
 	if (A > skb->len - sizeof(struct nlattr))
 		return 0;
 
@@ -618,11 +621,14 @@ static u64 __skb_get_nlattr_nest(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
 	if (skb_is_nonlinear(skb))
 		return 0;
 
+	if (skb->len < sizeof(struct nlattr))
+		return 0;
+
 	if (A > skb->len - sizeof(struct nlattr))
 		return 0;
 
 	nla = (struct nlattr *) &skb->data[A];
-	if (nla->nla_len > A - skb->len)
+	if (nla->nla_len > skb->len - A)
 		return 0;
 
 	nla = nla_find_nested(nla, X);
@@ -1737,7 +1743,6 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
 		[BPF_S_ANC_RXHASH]	= BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_ANC_CPU]		= BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_ANC_ALU_XOR_X]	= BPF_LD|BPF_B|BPF_ABS,
-		[BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_ANC_VLAN_TAG]	= BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
 		[BPF_S_ANC_PAY_OFFSET]	= BPF_LD|BPF_B|BPF_ABS,
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 8876078859da..0248e8a3460c 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -138,7 +138,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
 
 		DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
 
-		err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl);
+		err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl);
 		return net_xmit_eval(err);
 	}
 	return -ENOBUFS;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index ce0cbbfe0f43..daccc4a36d80 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -752,7 +752,7 @@ static int dn_to_neigh_output(struct sk_buff *skb)
 	return n->output(n, skb);
 }
 
-static int dn_output(struct sk_buff *skb)
+static int dn_output(struct sock *sk, struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb_dst(skb);
 	struct dn_route *rt = (struct dn_route *)dst;
@@ -838,6 +838,18 @@ drop:
  * Used to catch bugs. This should never normally get
  * called.
  */
+static int dn_rt_bug_sk(struct sock *sk, struct sk_buff *skb)
+{
+	struct dn_skb_cb *cb = DN_SKB_CB(skb);
+
+	net_dbg_ratelimited("dn_rt_bug: skb from:%04x to:%04x\n",
+			    le16_to_cpu(cb->src), le16_to_cpu(cb->dst));
+
+	kfree_skb(skb);
+
+	return NET_RX_DROP;
+}
+
 static int dn_rt_bug(struct sk_buff *skb)
 {
 	struct dn_skb_cb *cb = DN_SKB_CB(skb);
@@ -1463,7 +1475,7 @@ make_route:
 
 	rt->n = neigh;
 	rt->dst.lastuse = jiffies;
-	rt->dst.output = dn_rt_bug;
+	rt->dst.output = dn_rt_bug_sk;
 	switch (res.type) {
 	case RTN_UNICAST:
 		rt->dst.input = dn_forward;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 1a629f870274..255aa9946fe7 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -250,7 +250,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 	bool dev_match;
 
 	fl4.flowi4_oif = 0;
-	fl4.flowi4_iif = oif;
+	fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX;
 	fl4.daddr = src;
 	fl4.saddr = dst;
 	fl4.flowi4_tos = tos;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index b53f0bf84dca..8a043f03c88e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -631,6 +631,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
 				.daddr = nh->nh_gw,
 				.flowi4_scope = cfg->fc_scope + 1,
 				.flowi4_oif = nh->nh_oif,
+				.flowi4_iif = LOOPBACK_IFINDEX,
 			};
 
 			/* It is not necessary, but requires a bit of thinking */
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 1a0755fea491..1cbeba5edff9 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -101,17 +101,17 @@ int __ip_local_out(struct sk_buff *skb)
 		       skb_dst(skb)->dev, dst_output);
 }
 
-int ip_local_out(struct sk_buff *skb)
+int ip_local_out_sk(struct sock *sk, struct sk_buff *skb)
 {
 	int err;
 
 	err = __ip_local_out(skb);
 	if (likely(err == 1))
-		err = dst_output(skb);
+		err = dst_output_sk(sk, skb);
 
 	return err;
 }
-EXPORT_SYMBOL_GPL(ip_local_out);
+EXPORT_SYMBOL_GPL(ip_local_out_sk);
 
 static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)
 {
@@ -226,9 +226,8 @@ static int ip_finish_output(struct sk_buff *skb)
 		return ip_finish_output2(skb);
 }
 
-int ip_mc_output(struct sk_buff *skb)
+int ip_mc_output(struct sock *sk, struct sk_buff *skb)
 {
-	struct sock *sk = skb->sk;
 	struct rtable *rt = skb_rtable(skb);
 	struct net_device *dev = rt->dst.dev;
 
@@ -287,7 +286,7 @@ int ip_mc_output(struct sk_buff *skb)
 			    !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
 
-int ip_output(struct sk_buff *skb)
+int ip_output(struct sock *sk, struct sk_buff *skb)
 {
 	struct net_device *dev = skb_dst(skb)->dev;
 
@@ -315,9 +314,9 @@ static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4)
 	       sizeof(fl4->saddr) + sizeof(fl4->daddr));
 }
 
-int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
+/* Note: skb->sk can be different from sk, in case of tunnels */
+int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl)
 {
-	struct sock *sk = skb->sk;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ip_options_rcu *inet_opt;
 	struct flowi4 *fl4;
@@ -389,6 +388,7 @@ packet_routed:
 	ip_select_ident_more(skb, &rt->dst, sk,
 			     (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
+	/* TODO : should we use skb->sk here instead of sk ? */
 	skb->priority = sk->sk_priority;
 	skb->mark = sk->sk_mark;
 
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index e77381d1df9a..fa5b7519765f 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -670,7 +670,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 		return;
 	}
 
-	err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol,
+	err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, protocol,
 			    tos, ttl, df, !net_eq(tunnel->net, dev_net(dev)));
 	iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
 
@@ -722,19 +722,18 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
 int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
 {
 	int err = 0;
-	struct ip_tunnel *t;
-	struct net *net = dev_net(dev);
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
+	struct ip_tunnel *t = netdev_priv(dev);
+	struct net *net = t->net;
+	struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id);
 
 	BUG_ON(!itn->fb_tunnel_dev);
 	switch (cmd) {
 	case SIOCGETTUNNEL:
-		t = NULL;
-		if (dev == itn->fb_tunnel_dev)
+		if (dev == itn->fb_tunnel_dev) {
 			t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
-		if (t == NULL)
-			t = netdev_priv(dev);
+			if (t == NULL)
+				t = netdev_priv(dev);
+		}
 		memcpy(p, &t->parms, sizeof(*p));
 		break;
 
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index e0c2b1d2ea4e..bcf206c79005 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -46,7 +46,7 @@
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
 
-int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
+int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 		  __be32 src, __be32 dst, __u8 proto,
 		  __u8 tos, __u8 ttl, __be16 df, bool xnet)
 {
@@ -76,7 +76,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
 	iph->ttl	=	ttl;
 	__ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
-	err = ip_local_out(skb);
+	err = ip_local_out_sk(sk, skb);
 	if (unlikely(net_xmit_eval(err)))
 		pkt_len = 0;
 	return pkt_len;
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index afcee51b90ed..dbaa3d390177 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -349,7 +349,6 @@ static int vti_tunnel_init(struct net_device *dev)
 	memcpy(dev->dev_addr, &iph->saddr, 4);
 	memcpy(dev->broadcast, &iph->daddr, 4);
 
-	dev->hard_header_len	= LL_MAX_HEADER + sizeof(struct iphdr);
 	dev->mtu		= ETH_DATA_LEN;
 	dev->flags		= IFF_NOARP;
 	dev->iflink		= 0;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 28863570dd60..d84dc8d4c916 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -455,7 +455,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct mr_table *mrt;
 	struct flowi4 fl4 = {
 		.flowi4_oif	= dev->ifindex,
-		.flowi4_iif	= skb->skb_iif,
+		.flowi4_iif	= skb->skb_iif ? : LOOPBACK_IFINDEX,
 		.flowi4_mark	= skb->mark,
 	};
 	int err;
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
index c49dcd0284a0..4bfaedf9b34e 100644
--- a/net/ipv4/netfilter/ipt_rpfilter.c
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -89,11 +89,8 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	if (ipv4_is_multicast(iph->daddr)) {
 		if (ipv4_is_zeronet(iph->saddr))
 			return ipv4_is_local_multicast(iph->daddr) ^ invert;
-		flow.flowi4_iif = 0;
-	} else {
-		flow.flowi4_iif = LOOPBACK_IFINDEX;
 	}
-
+	flow.flowi4_iif = LOOPBACK_IFINDEX;
 	flow.daddr = iph->saddr;
 	flow.saddr = rpfilter_get_saddr(iph->daddr);
 	flow.flowi4_oif = 0;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index f4b19e5dde54..8210964a9f19 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -252,26 +252,33 @@ int ping_init_sock(struct sock *sk)
 {
 	struct net *net = sock_net(sk);
 	kgid_t group = current_egid();
-	struct group_info *group_info = get_current_groups();
-	int i, j, count = group_info->ngroups;
+	struct group_info *group_info;
+	int i, j, count;
 	kgid_t low, high;
+	int ret = 0;
 
 	inet_get_ping_group_range_net(net, &low, &high);
 	if (gid_lte(low, group) && gid_lte(group, high))
 		return 0;
 
+	group_info = get_current_groups();
+	count = group_info->ngroups;
 	for (i = 0; i < group_info->nblocks; i++) {
 		int cp_count = min_t(int, NGROUPS_PER_BLOCK, count);
 		for (j = 0; j < cp_count; j++) {
 			kgid_t gid = group_info->blocks[i][j];
 			if (gid_lte(low, gid) && gid_lte(gid, high))
-				return 0;
+				goto out_release_group;
 		}
 
 		count -= cp_count;
 	}
 
-	return -EACCES;
+	ret = -EACCES;
+
+out_release_group:
+	put_group_info(group_info);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(ping_init_sock);
 
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 34d094cadb11..db1e0da871f4 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1129,7 +1129,7 @@ static void ipv4_link_failure(struct sk_buff *skb)
 		dst_set_expires(&rt->dst, 0);
 }
 
-static int ip_rt_bug(struct sk_buff *skb)
+static int ip_rt_bug(struct sock *sk, struct sk_buff *skb)
 {
 	pr_debug("%s: %pI4 -> %pI4, %s\n",
 		 __func__, &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr,
@@ -1700,8 +1700,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
 	if (res.type == RTN_LOCAL) {
 		err = fib_validate_source(skb, saddr, daddr, tos,
-					  LOOPBACK_IFINDEX,
-					  dev, in_dev, &itag);
+					  0, dev, in_dev, &itag);
 		if (err < 0)
 			goto martian_source_keep_err;
 		goto local_input;
@@ -2218,7 +2217,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
 
 		new->__use = 1;
 		new->input = dst_discard;
-		new->output = dst_discard;
+		new->output = dst_discard_sk;
 
 		new->dev = ort->dst.dev;
 		if (new->dev)
@@ -2357,7 +2356,7 @@ static int rt_fill_info(struct net *net,  __be32 dst, __be32 src,
 			}
 		} else
 #endif
-			if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
+			if (nla_put_u32(skb, RTA_IIF, skb->dev->ifindex))
 				goto nla_put_failure;
 	}
 
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 699fb102e971..025e25093984 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -981,7 +981,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
 		TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS,
 			      tcp_skb_pcount(skb));
 
-	err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl);
+	err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl);
 	if (likely(err <= 0))
 		return err;
 
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index baa0f63731fd..186a8ecf92fa 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -62,10 +62,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 	if (err)
 		return err;
 
-	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
-	IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED;
-
-	skb->protocol = htons(ETH_P_IP);
+	IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
 
 	return x->outer_mode->output2(x, skb);
 }
@@ -73,27 +70,34 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
 
 int xfrm4_output_finish(struct sk_buff *skb)
 {
-#ifdef CONFIG_NETFILTER
-	if (!skb_dst(skb)->xfrm) {
-		IPCB(skb)->flags |= IPSKB_REROUTED;
-		return dst_output(skb);
-	}
+	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+	skb->protocol = htons(ETH_P_IP);
 
+#ifdef CONFIG_NETFILTER
 	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 #endif
 
-	skb->protocol = htons(ETH_P_IP);
 	return xfrm_output(skb);
 }
 
-int xfrm4_output(struct sk_buff *skb)
+static int __xfrm4_output(struct sk_buff *skb)
 {
-	struct dst_entry *dst = skb_dst(skb);
-	struct xfrm_state *x = dst->xfrm;
+	struct xfrm_state *x = skb_dst(skb)->xfrm;
+
+#ifdef CONFIG_NETFILTER
+	if (!x) {
+		IPCB(skb)->flags |= IPSKB_REROUTED;
+		return dst_output(skb);
+	}
+#endif
 
+	return x->outer_mode->afinfo->output_finish(skb);
+}
+
+int xfrm4_output(struct sock *sk, struct sk_buff *skb)
+{
 	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb,
-			    NULL, dst->dev,
-			    x->outer_mode->afinfo->output_finish,
+			    NULL, skb_dst(skb)->dev, __xfrm4_output,
 			    !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
 
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index c9138189415a..d4ade34ab375 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -224,9 +224,8 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
 	return dst;
 }
 
-int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused)
+int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused)
 {
-	struct sock *sk = skb->sk;
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct flowi6 fl6;
 	struct dst_entry *dst;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index c98338b81d30..9d921462b57f 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1559,6 +1559,15 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
 	return 0;
 }
 
+static void ip6gre_dellink(struct net_device *dev, struct list_head *head)
+{
+	struct net *net = dev_net(dev);
+	struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
+
+	if (dev != ign->fb_tunnel_dev)
+		unregister_netdevice_queue(dev, head);
+}
+
 static size_t ip6gre_get_size(const struct net_device *dev)
 {
 	return
@@ -1636,6 +1645,7 @@ static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
 	.validate	= ip6gre_tunnel_validate,
 	.newlink	= ip6gre_newlink,
 	.changelink	= ip6gre_changelink,
+	.dellink	= ip6gre_dellink,
 	.get_size	= ip6gre_get_size,
 	.fill_info	= ip6gre_fill_info,
 };
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3284d61577c0..40e7581374f7 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -132,7 +132,7 @@ static int ip6_finish_output(struct sk_buff *skb)
 		return ip6_finish_output2(skb);
 }
 
-int ip6_output(struct sk_buff *skb)
+int ip6_output(struct sock *sk, struct sk_buff *skb)
 {
 	struct net_device *dev = skb_dst(skb)->dev;
 	struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e1df691d78be..b05b609f69d1 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1340,8 +1340,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	int err = 0;
 	struct ip6_tnl_parm p;
 	struct __ip6_tnl_parm p1;
-	struct ip6_tnl *t = NULL;
-	struct net *net = dev_net(dev);
+	struct ip6_tnl *t = netdev_priv(dev);
+	struct net *net = t->net;
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
 	switch (cmd) {
@@ -1353,11 +1353,11 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 			}
 			ip6_tnl_parm_from_user(&p1, &p);
 			t = ip6_tnl_locate(net, &p1, 0);
+			if (t == NULL)
+				t = netdev_priv(dev);
 		} else {
 			memset(&p, 0, sizeof(p));
 		}
-		if (t == NULL)
-			t = netdev_priv(dev);
 		ip6_tnl_parm_to_user(&p, &t->parms);
 		if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) {
 			err = -EFAULT;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 8737400af0a0..8659067da28e 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -700,7 +700,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
 	struct mr6_table *mrt;
 	struct flowi6 fl6 = {
 		.flowi6_oif	= dev->ifindex,
-		.flowi6_iif	= skb->skb_iif,
+		.flowi6_iif	= skb->skb_iif ? : LOOPBACK_IFINDEX,
 		.flowi6_mark	= skb->mark,
 	};
 	int err;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5015c50a5ba7..4011617cca68 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -84,9 +84,9 @@ static void		ip6_dst_ifdown(struct dst_entry *,
 static int		 ip6_dst_gc(struct dst_ops *ops);
 
 static int		ip6_pkt_discard(struct sk_buff *skb);
-static int		ip6_pkt_discard_out(struct sk_buff *skb);
+static int		ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb);
 static int		ip6_pkt_prohibit(struct sk_buff *skb);
-static int		ip6_pkt_prohibit_out(struct sk_buff *skb);
+static int		ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb);
 static void		ip6_link_failure(struct sk_buff *skb);
 static void		ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 					   struct sk_buff *skb, u32 mtu);
@@ -290,7 +290,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
 		.obsolete	= DST_OBSOLETE_FORCE_CHK,
 		.error		= -EINVAL,
 		.input		= dst_discard,
-		.output		= dst_discard,
+		.output		= dst_discard_sk,
 	},
 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
 	.rt6i_protocol  = RTPROT_KERNEL,
@@ -1058,7 +1058,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
 
 		new->__use = 1;
 		new->input = dst_discard;
-		new->output = dst_discard;
+		new->output = dst_discard_sk;
 
 		if (dst_metrics_read_only(&ort->dst))
 			new->_metrics = ort->dst._metrics;
@@ -1338,7 +1338,7 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
 	unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
 
 	if (mtu)
-		return mtu;
+		goto out;
 
 	mtu = IPV6_MIN_MTU;
 
@@ -1348,7 +1348,8 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
 		mtu = idev->cnf.mtu6;
 	rcu_read_unlock();
 
-	return mtu;
+out:
+	return min_t(unsigned int, mtu, IP6_MAX_MTU);
 }
 
 static struct dst_entry *icmp6_dst_gc_list;
@@ -1576,7 +1577,7 @@ int ip6_route_add(struct fib6_config *cfg)
 		switch (cfg->fc_type) {
 		case RTN_BLACKHOLE:
 			rt->dst.error = -EINVAL;
-			rt->dst.output = dst_discard;
+			rt->dst.output = dst_discard_sk;
 			rt->dst.input = dst_discard;
 			break;
 		case RTN_PROHIBIT:
@@ -2128,7 +2129,7 @@ static int ip6_pkt_discard(struct sk_buff *skb)
 	return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES);
 }
 
-static int ip6_pkt_discard_out(struct sk_buff *skb)
+static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb)
 {
 	skb->dev = skb_dst(skb)->dev;
 	return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
@@ -2139,7 +2140,7 @@ static int ip6_pkt_prohibit(struct sk_buff *skb)
 	return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);
 }
 
-static int ip6_pkt_prohibit_out(struct sk_buff *skb)
+static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb)
 {
 	skb->dev = skb_dst(skb)->dev;
 	return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1693c8d885f0..e5a453ca302e 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -974,8 +974,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 		goto out;
 	}
 
-	err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
-			    ttl, df, !net_eq(tunnel->net, dev_net(dev)));
+	err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr,
+			    IPPROTO_IPV6, tos, ttl, df,
+			    !net_eq(tunnel->net, dev_net(dev)));
 	iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
 	return NETDEV_TX_OK;
 
@@ -1126,8 +1127,8 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 	int err = 0;
 	struct ip_tunnel_parm p;
 	struct ip_tunnel_prl prl;
-	struct ip_tunnel *t;
-	struct net *net = dev_net(dev);
+	struct ip_tunnel *t = netdev_priv(dev);
+	struct net *net = t->net;
 	struct sit_net *sitn = net_generic(net, sit_net_id);
 #ifdef CONFIG_IPV6_SIT_6RD
 	struct ip_tunnel_6rd ip6rd;
@@ -1138,16 +1139,15 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 #ifdef CONFIG_IPV6_SIT_6RD
 	case SIOCGET6RD:
 #endif
-		t = NULL;
 		if (dev == sitn->fb_tunnel_dev) {
 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
 				err = -EFAULT;
 				break;
 			}
 			t = ipip6_tunnel_locate(net, &p, 0);
+			if (t == NULL)
+				t = netdev_priv(dev);
 		}
-		if (t == NULL)
-			t = netdev_priv(dev);
 
 		err = -EFAULT;
 		if (cmd == SIOCGETTUNNEL) {
@@ -1243,9 +1243,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 		err = -EINVAL;
 		if (dev == sitn->fb_tunnel_dev)
 			goto done;
-		err = -ENOENT;
-		if (!(t = netdev_priv(dev)))
-			goto done;
 		err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data);
 		break;
 
@@ -1261,9 +1258,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 		err = -EFAULT;
 		if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
 			goto done;
-		err = -ENOENT;
-		if (!(t = netdev_priv(dev)))
-			goto done;
 
 		switch (cmd) {
 		case SIOCDELPRL:
@@ -1291,8 +1285,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 				   sizeof(ip6rd)))
 			goto done;
 
-		t = netdev_priv(dev);
-
 		if (cmd != SIOCDEL6RD) {
 			err = ipip6_tunnel_update_6rd(t, &ip6rd);
 			if (err < 0)
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 6cd625e37706..b930d080c66f 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -114,12 +114,6 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 	if (err)
 		return err;
 
-	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
-#ifdef CONFIG_NETFILTER
-	IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
-#endif
-
-	skb->protocol = htons(ETH_P_IPV6);
 	skb->local_df = 1;
 
 	return x->outer_mode->output2(x, skb);
@@ -128,11 +122,13 @@ EXPORT_SYMBOL(xfrm6_prepare_output);
 
 int xfrm6_output_finish(struct sk_buff *skb)
 {
+	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+	skb->protocol = htons(ETH_P_IPV6);
+
 #ifdef CONFIG_NETFILTER
 	IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
 #endif
 
-	skb->protocol = htons(ETH_P_IPV6);
 	return xfrm_output(skb);
 }
 
@@ -142,6 +138,13 @@ static int __xfrm6_output(struct sk_buff *skb)
 	struct xfrm_state *x = dst->xfrm;
 	int mtu;
 
+#ifdef CONFIG_NETFILTER
+	if (!x) {
+		IP6CB(skb)->flags |= IP6SKB_REROUTED;
+		return dst_output(skb);
+	}
+#endif
+
 	if (skb->protocol == htons(ETH_P_IPV6))
 		mtu = ip6_skb_dst_mtu(skb);
 	else
@@ -163,8 +166,9 @@ static int __xfrm6_output(struct sk_buff *skb)
 	return x->outer_mode->afinfo->output_finish(skb);
 }
 
-int xfrm6_output(struct sk_buff *skb)
+int xfrm6_output(struct sock *sk, struct sk_buff *skb)
 {
-	return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL,
-		       skb_dst(skb)->dev, __xfrm6_output);
+	return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb,
+			    NULL, skb_dst(skb)->dev, __xfrm6_output,
+			    !(IP6CB(skb)->flags & IP6SKB_REROUTED));
 }
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 47f7a5490555..a4e37d7158dc 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1131,10 +1131,10 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
 	skb->local_df = 1;
 #if IS_ENABLED(CONFIG_IPV6)
 	if (tunnel->sock->sk_family == PF_INET6 && !tunnel->v4mapped)
-		error = inet6_csk_xmit(skb, NULL);
+		error = inet6_csk_xmit(tunnel->sock, skb, NULL);
 	else
 #endif
-		error = ip_queue_xmit(skb, fl);
+		error = ip_queue_xmit(tunnel->sock, skb, fl);
 
 	/* Update stats */
 	if (error >= 0) {
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 0b44d855269c..3397fe6897c0 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -487,7 +487,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
 
 xmit:
 	/* Queue the packet to IP for output */
-	rc = ip_queue_xmit(skb, &inet->cork.fl);
+	rc = ip_queue_xmit(sk, skb, &inet->cork.fl);
 	rcu_read_unlock();
 
 error:
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index bd1fd8ea5105..75b5dd2c9267 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -249,7 +249,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
 
 	if (!local->use_chanctx) {
 		local->_oper_chandef = *chandef;
-		ieee80211_hw_config(local, 0);
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 	} else {
 		err = drv_add_chanctx(local, ctx);
 		if (err) {
@@ -286,7 +286,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
 			check_single_channel = true;
 		local->hw.conf.radar_enabled = false;
 
-		ieee80211_hw_config(local, 0);
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 	} else {
 		drv_remove_chanctx(local, ctx);
 	}
@@ -492,6 +492,13 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
 		rx_chains_static = max(rx_chains_static, needed_static);
 		rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
 	}
+
+	/* Disable SMPS for the monitor interface */
+	sdata = rcu_dereference(local->monitor_sdata);
+	if (sdata &&
+	    rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf)
+		rx_chains_dynamic = rx_chains_static = local->rx_chains;
+
 	rcu_read_unlock();
 
 	if (!local->use_chanctx) {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b055f6a55c68..4c1bf61bc778 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -148,6 +148,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 		if (!rcu_access_pointer(sdata->vif.chanctx_conf))
 			continue;
+		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+			continue;
 		power = min(power, sdata->vif.bss_conf.txpower);
 	}
 	rcu_read_unlock();
@@ -199,7 +201,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_local *local = sdata->local;
 
-	if (!changed)
+	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		return;
 
 	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 0c2a29484c07..6fb38558a5e6 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -355,6 +355,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
 		struct ieee80211_roc_work *dep;
 
 		/* start this ROC */
+		ieee80211_offchannel_stop_vifs(local);
 
 		/* switch channel etc */
 		ieee80211_recalc_idle(local);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index e6e574a307c8..00ba90b02ab2 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -618,6 +618,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 					sta, true, acked);
 
 		if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) &&
+		    (ieee80211_is_data(hdr->frame_control)) &&
 		    (rates_idx != -1))
 			sta->last_tx_rate = info->status.rates[rates_idx];
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 6dba48efe01e..75421f2ba8be 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1795,6 +1795,7 @@ int nf_conntrack_init_net(struct net *net)
 	int cpu;
 
 	atomic_set(&net->ct.count, 0);
+	seqcount_init(&net->ct.generation);
 
 	net->ct.pcpu_lists = alloc_percpu(struct ct_pcpu);
 	if (!net->ct.pcpu_lists)
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 7bd03decd36c..825c3e3f8305 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -605,32 +605,14 @@ static struct nf_conntrack_helper pptp __read_mostly = {
 	.expect_policy		= &pptp_exp_policy,
 };
 
-static void nf_conntrack_pptp_net_exit(struct net *net)
-{
-	nf_ct_gre_keymap_flush(net);
-}
-
-static struct pernet_operations nf_conntrack_pptp_net_ops = {
-	.exit = nf_conntrack_pptp_net_exit,
-};
-
 static int __init nf_conntrack_pptp_init(void)
 {
-	int rv;
-
-	rv = nf_conntrack_helper_register(&pptp);
-	if (rv < 0)
-		return rv;
-	rv = register_pernet_subsys(&nf_conntrack_pptp_net_ops);
-	if (rv < 0)
-		nf_conntrack_helper_unregister(&pptp);
-	return rv;
+	return nf_conntrack_helper_register(&pptp);
 }
 
 static void __exit nf_conntrack_pptp_fini(void)
 {
 	nf_conntrack_helper_unregister(&pptp);
-	unregister_pernet_subsys(&nf_conntrack_pptp_net_ops);
 }
 
 module_init(nf_conntrack_pptp_init);
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 9d9c0dade602..d5665739e3b1 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -66,7 +66,7 @@ static inline struct netns_proto_gre *gre_pernet(struct net *net)
 	return net_generic(net, proto_gre_net_id);
 }
 
-void nf_ct_gre_keymap_flush(struct net *net)
+static void nf_ct_gre_keymap_flush(struct net *net)
 {
 	struct netns_proto_gre *net_gre = gre_pernet(net);
 	struct nf_ct_gre_keymap *km, *tmp;
@@ -78,7 +78,6 @@ void nf_ct_gre_keymap_flush(struct net *net)
 	}
 	write_unlock_bh(&net_gre->keymap_lock);
 }
-EXPORT_SYMBOL(nf_ct_gre_keymap_flush);
 
 static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
 				const struct nf_conntrack_tuple *t)
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 90998a6ff8b9..804105391b9a 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -25,9 +25,8 @@ static void nft_cmp_fast_eval(const struct nft_expr *expr,
 			      struct nft_data data[NFT_REG_MAX + 1])
 {
 	const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
-	u32 mask;
+	u32 mask = nft_cmp_fast_mask(priv->len);
 
-	mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - priv->len);
 	if ((data[priv->sreg].data[0] & mask) == priv->data)
 		return;
 	data[NFT_REG_VERDICT].verdict = NFT_BREAK;
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 954925db414d..e2b3f51c81f1 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -128,7 +128,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
 	BUG_ON(err < 0);
 	desc.len *= BITS_PER_BYTE;
 
-	mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - desc.len);
+	mask = nft_cmp_fast_mask(desc.len);
 	priv->data = data.data[0] & mask;
 	priv->len  = desc.len;
 	return 0;
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index a3d6951602db..ebb6e2442554 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -174,7 +174,7 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
 
 	skb->local_df = 1;
 
-	return iptunnel_xmit(rt, skb, fl.saddr,
+	return iptunnel_xmit(skb->sk, rt, skb, fl.saddr,
 			     OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE,
 			     OVS_CB(skb)->tun_key->ipv4_tos,
 			     OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 4f6d6f9d1274..39579c3e0d14 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1395,35 +1395,44 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc)
 	return false;
 }
 
-/* Update asoc's rwnd for the approximated state in the buffer,
- * and check whether SACK needs to be sent.
- */
-void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
+/* Increase asoc's rwnd by len and send any window update SACK if needed. */
+void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
 {
-	int rx_count;
 	struct sctp_chunk *sack;
 	struct timer_list *timer;
 
-	if (asoc->ep->rcvbuf_policy)
-		rx_count = atomic_read(&asoc->rmem_alloc);
-	else
-		rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
+	if (asoc->rwnd_over) {
+		if (asoc->rwnd_over >= len) {
+			asoc->rwnd_over -= len;
+		} else {
+			asoc->rwnd += (len - asoc->rwnd_over);
+			asoc->rwnd_over = 0;
+		}
+	} else {
+		asoc->rwnd += len;
+	}
 
-	if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0)
-		asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1;
-	else
-		asoc->rwnd = 0;
+	/* If we had window pressure, start recovering it
+	 * once our rwnd had reached the accumulated pressure
+	 * threshold.  The idea is to recover slowly, but up
+	 * to the initial advertised window.
+	 */
+	if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) {
+		int change = min(asoc->pathmtu, asoc->rwnd_press);
+		asoc->rwnd += change;
+		asoc->rwnd_press -= change;
+	}
 
-	pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n",
-		 __func__, asoc, asoc->rwnd, rx_count,
-		 asoc->base.sk->sk_rcvbuf);
+	pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n",
+		 __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
+		 asoc->a_rwnd);
 
 	/* Send a window update SACK if the rwnd has increased by at least the
 	 * minimum of the association's PMTU and half of the receive buffer.
 	 * The algorithm used is similar to the one described in
 	 * Section 4.2.3.3 of RFC 1122.
 	 */
-	if (update_peer && sctp_peer_needs_update(asoc)) {
+	if (sctp_peer_needs_update(asoc)) {
 		asoc->a_rwnd = asoc->rwnd;
 
 		pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u "
@@ -1445,6 +1454,45 @@ void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
 	}
 }
 
+/* Decrease asoc's rwnd by len. */
+void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
+{
+	int rx_count;
+	int over = 0;
+
+	if (unlikely(!asoc->rwnd || asoc->rwnd_over))
+		pr_debug("%s: association:%p has asoc->rwnd:%u, "
+			 "asoc->rwnd_over:%u!\n", __func__, asoc,
+			 asoc->rwnd, asoc->rwnd_over);
+
+	if (asoc->ep->rcvbuf_policy)
+		rx_count = atomic_read(&asoc->rmem_alloc);
+	else
+		rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
+
+	/* If we've reached or overflowed our receive buffer, announce
+	 * a 0 rwnd if rwnd would still be positive.  Store the
+	 * the potential pressure overflow so that the window can be restored
+	 * back to original value.
+	 */
+	if (rx_count >= asoc->base.sk->sk_rcvbuf)
+		over = 1;
+
+	if (asoc->rwnd >= len) {
+		asoc->rwnd -= len;
+		if (over) {
+			asoc->rwnd_press += asoc->rwnd;
+			asoc->rwnd = 0;
+		}
+	} else {
+		asoc->rwnd_over = len - asoc->rwnd;
+		asoc->rwnd = 0;
+	}
+
+	pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n",
+		 __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
+		 asoc->rwnd_press);
+}
 
 /* Build the bind address list for the association based on info from the
  * local endpoint and the remote peer.
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 4e1d0fcb028e..c09757fbf803 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -957,7 +957,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
 
 	SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
 
-	return ip_queue_xmit(skb, &transport->fl);
+	return ip_queue_xmit(&inet->sk, skb, &transport->fl);
 }
 
 static struct sctp_af sctp_af_inet;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 01e002430c85..ae9fbeba40b0 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -6178,7 +6178,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 	 * PMTU.  In cases, such as loopback, this might be a rather
 	 * large spill over.
 	 */
-	if ((!chunk->data_accepted) && (!asoc->rwnd ||
+	if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over ||
 	    (datalen > asoc->rwnd + asoc->frag_point))) {
 
 		/* If this is the next TSN, consider reneging to make
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e13519e9df80..ff20e2dbbbc7 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2115,6 +2115,12 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
 		sctp_skb_pull(skb, copied);
 		skb_queue_head(&sk->sk_receive_queue, skb);
 
+		/* When only partial message is copied to the user, increase
+		 * rwnd by that amount. If all the data in the skb is read,
+		 * rwnd is updated when the event is freed.
+		 */
+		if (!sctp_ulpevent_is_notification(event))
+			sctp_assoc_rwnd_increase(event->asoc, copied);
 		goto out;
 	} else if ((event->msg_flags & MSG_NOTIFICATION) ||
 		   (event->msg_flags & MSG_EOR))
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 8d198ae03606..85c64658bd0b 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
 	skb = sctp_event2skb(event);
 	/* Set the owner and charge rwnd for bytes received.  */
 	sctp_ulpevent_set_owner(event, asoc);
-	sctp_assoc_rwnd_update(asoc, false);
+	sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));
 
 	if (!skb->data_len)
 		return;
@@ -1011,7 +1011,6 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 {
 	struct sk_buff *skb, *frag;
 	unsigned int	len;
-	struct sctp_association *asoc;
 
 	/* Current stack structures assume that the rcv buffer is
 	 * per socket.   For UDP style sockets this is not true as
@@ -1036,11 +1035,8 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 	}
 
 done:
-	asoc = event->asoc;
-	sctp_association_hold(asoc);
+	sctp_assoc_rwnd_increase(event->asoc, len);
 	sctp_ulpevent_release_owner(event);
-	sctp_assoc_rwnd_update(asoc, true);
-	sctp_association_put(asoc);
 }
 
 static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
diff --git a/net/socket.c b/net/socket.c
index 1b1e7e6a960f..abf56b2a14f9 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1880,8 +1880,8 @@ out:
  *	Receive a datagram from a socket.
  */
 
-asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
-			 unsigned int flags)
+SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
+		unsigned int, flags)
 {
 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
 }
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f02f511b7107..c08fbd11ceff 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1842,7 +1842,7 @@ purge_queue:
 	xfrm_pol_put(pol);
 }
 
-static int xdst_queue_output(struct sk_buff *skb)
+static int xdst_queue_output(struct sock *sk, struct sk_buff *skb)
 {
 	unsigned long sched_next;
 	struct dst_entry *dst = skb_dst(skb);
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 003bc263105a..b5e02b669469 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -50,67 +50,6 @@ ifeq ($(KBUILD_NOPEDANTIC),)
         endif
 endif
 
-#
-# make W=... settings
-#
-# W=1 - warnings that may be relevant and does not occur too often
-# W=2 - warnings that occur quite often but may still be relevant
-# W=3 - the more obscure warnings, can most likely be ignored
-#
-# $(call cc-option, -W...) handles gcc -W.. options which
-# are not supported by all versions of the compiler
-ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
-warning-  := $(empty)
-
-warning-1 := -Wextra -Wunused -Wno-unused-parameter
-warning-1 += -Wmissing-declarations
-warning-1 += -Wmissing-format-attribute
-warning-1 += $(call cc-option, -Wmissing-prototypes)
-warning-1 += -Wold-style-definition
-warning-1 += $(call cc-option, -Wmissing-include-dirs)
-warning-1 += $(call cc-option, -Wunused-but-set-variable)
-warning-1 += $(call cc-disable-warning, missing-field-initializers)
-
-# Clang
-warning-1 += $(call cc-disable-warning, initializer-overrides)
-warning-1 += $(call cc-disable-warning, unused-value)
-warning-1 += $(call cc-disable-warning, format)
-warning-1 += $(call cc-disable-warning, unknown-warning-option)
-warning-1 += $(call cc-disable-warning, sign-compare)
-warning-1 += $(call cc-disable-warning, format-zero-length)
-warning-1 += $(call cc-disable-warning, uninitialized)
-warning-1 += $(call cc-option, -fcatch-undefined-behavior)
-
-warning-2 := -Waggregate-return
-warning-2 += -Wcast-align
-warning-2 += -Wdisabled-optimization
-warning-2 += -Wnested-externs
-warning-2 += -Wshadow
-warning-2 += $(call cc-option, -Wlogical-op)
-warning-2 += $(call cc-option, -Wmissing-field-initializers)
-
-warning-3 := -Wbad-function-cast
-warning-3 += -Wcast-qual
-warning-3 += -Wconversion
-warning-3 += -Wpacked
-warning-3 += -Wpadded
-warning-3 += -Wpointer-arith
-warning-3 += -Wredundant-decls
-warning-3 += -Wswitch-default
-warning-3 += $(call cc-option, -Wpacked-bitfield-compat)
-warning-3 += $(call cc-option, -Wvla)
-
-warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
-
-ifeq ("$(strip $(warning))","")
-        $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown)
-endif
-
-KBUILD_CFLAGS += $(warning)
-endif
-
 include scripts/Makefile.lib
 
 ifdef host-progs
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
new file mode 100644
index 000000000000..65643506c71c
--- /dev/null
+++ b/scripts/Makefile.extrawarn
@@ -0,0 +1,67 @@
+# ==========================================================================
+#
+# make W=... settings
+#
+# W=1 - warnings that may be relevant and does not occur too often
+# W=2 - warnings that occur quite often but may still be relevant
+# W=3 - the more obscure warnings, can most likely be ignored
+#
+# $(call cc-option, -W...) handles gcc -W.. options which
+# are not supported by all versions of the compiler
+# ==========================================================================
+
+ifeq ("$(origin W)", "command line")
+  export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W)
+endif
+
+ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
+warning-  := $(empty)
+
+warning-1 := -Wextra -Wunused -Wno-unused-parameter
+warning-1 += -Wmissing-declarations
+warning-1 += -Wmissing-format-attribute
+warning-1 += $(call cc-option, -Wmissing-prototypes)
+warning-1 += -Wold-style-definition
+warning-1 += $(call cc-option, -Wmissing-include-dirs)
+warning-1 += $(call cc-option, -Wunused-but-set-variable)
+warning-1 += $(call cc-disable-warning, missing-field-initializers)
+
+# Clang
+warning-1 += $(call cc-disable-warning, initializer-overrides)
+warning-1 += $(call cc-disable-warning, unused-value)
+warning-1 += $(call cc-disable-warning, format)
+warning-1 += $(call cc-disable-warning, unknown-warning-option)
+warning-1 += $(call cc-disable-warning, sign-compare)
+warning-1 += $(call cc-disable-warning, format-zero-length)
+warning-1 += $(call cc-disable-warning, uninitialized)
+warning-1 += $(call cc-option, -fcatch-undefined-behavior)
+
+warning-2 := -Waggregate-return
+warning-2 += -Wcast-align
+warning-2 += -Wdisabled-optimization
+warning-2 += -Wnested-externs
+warning-2 += -Wshadow
+warning-2 += $(call cc-option, -Wlogical-op)
+warning-2 += $(call cc-option, -Wmissing-field-initializers)
+
+warning-3 := -Wbad-function-cast
+warning-3 += -Wcast-qual
+warning-3 += -Wconversion
+warning-3 += -Wpacked
+warning-3 += -Wpadded
+warning-3 += -Wpointer-arith
+warning-3 += -Wredundant-decls
+warning-3 += -Wswitch-default
+warning-3 += $(call cc-option, -Wpacked-bitfield-compat)
+warning-3 += $(call cc-option, -Wvla)
+
+warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
+warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
+warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS)))
+
+ifeq ("$(strip $(warning))","")
+        $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown)
+endif
+
+KBUILD_CFLAGS += $(warning)
+endif
diff --git a/scripts/Makefile.lto b/scripts/Makefile.lto
new file mode 100644
index 000000000000..b8e9e4836f4b
--- /dev/null
+++ b/scripts/Makefile.lto
@@ -0,0 +1,84 @@
+#
+# Support for gcc link time optimization
+#
+
+DISABLE_LTO :=
+LTO_CFLAGS :=
+
+export DISABLE_LTO
+export LTO_CFLAGS
+
+ifdef CONFIG_LTO
+# 4.7 works mostly, but it sometimes loses symbols on large builds
+# This can be worked around by marking those symbols visible,
+# but that is fairly ugly and the problem is gone with 4.8
+# So only allow it with 4.8 for now.
+ifeq ($(call cc-ifversion, -ge, 0408,y),y)
+ifneq ($(call cc-option,${LTO_CFLAGS},n),n)
+# We need HJ Lu's Linux binutils because mainline binutils does not
+# support mixing assembler and LTO code in the same ld -r object.
+# XXX check if the gcc plugin ld is the expected one too
+# XXX some Fedora binutils should also support it. How to check for that?
+ifeq ($(call ld-ifversion,-ge,22710001,y),y)
+        LTO_CFLAGS := -flto -fno-toplevel-reorder
+	LTO_FINAL_CFLAGS := -fuse-linker-plugin
+
+# the -fno-toplevel-reorder is to preserve the order of initcalls
+# everything else should tolerate reordering
+        LTO_FINAL_CFLAGS +=-fno-toplevel-reorder
+
+# enable LTO and set the jobs used by the LTO phase
+# this should be -flto=jobserver to coordinate with the
+# parent make, but work around
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50639
+# use as many jobs as processors are online for now
+# this actually seems to be a kernel bug with the pipe code
+	LTO_FINAL_CFLAGS := -flto=$(shell getconf _NPROCESSORS_ONLN)
+	#LTO_FINAL_CFLAGS := -flto=jobserver
+
+	# requires plugin ar passed and very recent HJ binutils
+        LTO_CFLAGS += -fno-fat-lto-objects
+
+# Used to disable LTO for specific files (e.g. vdso)
+	DISABLE_LTO := -fno-lto
+
+	LTO_FINAL_CFLAGS += ${LTO_CFLAGS} -fwhole-program
+
+ifdef CONFIG_LTO_DEBUG
+	LTO_FINAL_CFLAGS += -dH -fdump-ipa-cgraph -fdump-ipa-inline-details
+	# -Wl,-plugin-save-temps -save-temps
+	LTO_CFLAGS +=
+endif
+ifdef CONFIG_LTO_CP_CLONE
+	LTO_FINAL_CFLAGS += -fipa-cp-clone
+	LTO_CFLAGS += -fipa-cp-clone
+endif
+
+	# In principle gcc should pass through options in the object files,
+	# but it doesn't always work. So do it here manually
+	# Note that special options for individual files does not
+	# work currently (except for some special cases that only
+	# affect the compiler frontend)
+	# The main offenders are FTRACE and GCOV -- we exclude
+	# those in the config.
+	LTO_FINAL_CFLAGS += $(filter -g%,${KBUILD_CFLAGS})
+	LTO_FINAL_CFLAGS += $(filter -O%,${KBUILD_CFLAGS})
+	LTO_FINAL_CFLAGS += $(filter -f%,${KBUILD_CFLAGS})
+	LTO_FINAL_CFLAGS += $(filter -m%,${KBUILD_CFLAGS})
+	LTO_FINAL_CFLAGS += $(filter -W%,${KBUILD_CFLAGS})
+
+	KBUILD_CFLAGS += ${LTO_CFLAGS}
+
+	LDFINAL := ${CONFIG_SHELL} ${srctree}/scripts/gcc-ld \
+                  ${LTO_FINAL_CFLAGS}
+
+else
+        $(warning "WARNING: Too old linker version $(call ld-version) for kernel LTO. You need Linux binutils. CONFIG_LTO disabled.")
+endif
+else
+        $(warning "WARNING: Compiler/Linker does not support LTO/WHOPR with linker plugin. CONFIG_LTO disabled.")
+endif
+else
+        $(warning "WARNING: GCC $(call cc-version) too old for LTO/WHOPR. CONFIG_LTO disabled")
+endif
+endif
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 69f0a1417e9a..9c40daea846c 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -77,7 +77,8 @@ modpost = scripts/mod/modpost                    \
  $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
  $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
  $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S)      \
- $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
+ $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
+ $(if $(CONFIG_LTO),-w)
 
 MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
 
@@ -115,8 +116,8 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
 targets += $(modules:.ko=.mod.o)
 
 # Step 6), final link of the modules
-quiet_cmd_ld_ko_o = LD [M]  $@
-      cmd_ld_ko_o = $(LD) -r $(LDFLAGS)                                 \
+quiet_cmd_ld_ko_o = LDFINAL [M]  $@
+      cmd_ld_ko_o = $(LDFINAL) -r $(LDFLAGS)                            \
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                              -o $@ $(filter-out FORCE,$^)
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 34eb2160489d..cf02ff038df5 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -397,6 +397,11 @@ foreach my $entry (@mode_permission_funcs) {
 	$mode_perms_search .= $entry->[0];
 }
 
+our $declaration_macros = qr{(?x:
+	(?:$Storage\s+)?(?:DECLARE|DEFINE)_[A-Z]+\s*\(|
+	(?:$Storage\s+)?LIST_HEAD\s*\(
+)};
+
 our $allowed_asm_includes = qr{(?x:
 	irq|
 	memory
@@ -2266,18 +2271,35 @@ sub process {
 		}
 
 # check for missing blank lines after declarations
-		if ($realfile =~ m@^(drivers/net/|net/)@ &&
-		    $prevline =~ /^\+\s+$Declare\s+$Ident/ &&
-		    !($prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
-		      $prevline =~ /(?:\{\s*|\\)$/) &&		#extended lines
-		    $sline =~ /^\+\s+/ &&			#Not at char 1
-		    !($sline =~ /^\+\s+$Declare/ ||
-		      $sline =~ /^\+\s+$Ident\s+$Ident/ ||	#eg: typedef foo
+		if ($sline =~ /^\+\s+\S/ &&			#Not at char 1
+			# actual declarations
+		    ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;\[]/ ||
+			# foo bar; where foo is some local typedef or #define
+		     $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
+			# known declaration macros
+		     $prevline =~ /^\+\s+$declaration_macros/) &&
+			# for "else if" which can look like "$Ident $Ident"
+		    !($prevline =~ /^\+\s+$c90_Keywords\b/ ||
+			# other possible extensions of declaration lines
+		      $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
+			# not starting a section or a macro "\" extended line
+		      $prevline =~ /(?:\{\s*|\\)$/) &&
+			# looks like a declaration
+		    !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;\[]/ ||
+			# foo bar; where foo is some local typedef or #define
+		      $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
+			# known declaration macros
+		      $sline =~ /^\+\s+$declaration_macros/ ||
+			# start of struct or union or enum
 		      $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ ||
-		      $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(])/ ||
+			# start or end of block or continuation of declaration
+		      $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
+			# bitfield continuation
+		      $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ ||
+			# other possible extensions of declaration lines
 		      $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) {
 			WARN("SPACING",
-			     "networking uses a blank line after declarations\n" . $hereprev);
+			     "Missing a blank line after declarations\n" . $hereprev);
 		}
 
 # check for spaces at the beginning of a line.
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 86a4fe75f453..ec9a8ae33f8f 100644
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -53,7 +53,7 @@ vmlinux_link()
 	local lds="${objtree}/${KBUILD_LDS}"
 
 	if [ "${SRCARCH}" != "um" ]; then
-		${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2}                  \
+		${LDFINAL} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2}                  \
 			-T ${lds} ${KBUILD_VMLINUX_INIT}                     \
 			--start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}
 	else
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index cc49062acdee..1052d4834a44 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -35,6 +35,10 @@
 #define EM_ARCOMPACT	93
 #endif
 
+#ifndef EM_XTENSA
+#define EM_XTENSA	94
+#endif
+
 #ifndef EM_AARCH64
 #define EM_AARCH64	183
 #endif
@@ -281,6 +285,7 @@ do_file(char const *const fname)
 	case EM_AARCH64:
 	case EM_MICROBLAZE:
 	case EM_MIPS:
+	case EM_XTENSA:
 		break;
 	}  /* end switch */
 
diff --git a/scripts/tags.sh b/scripts/tags.sh
index f2c5b006a3d7..c1f64893efe9 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -201,7 +201,8 @@ exuberant()
 	--regex-c='/DECLARE_(TASKLET|WORK|DELAYED_WORK)\((\w*)/\2/v/'	\
 	--regex-c='/DEFINE_PCI_DEVICE_TABLE\((\w*)/\1/v/'		\
 	--regex-c='/(^\s)OFFSET\((\w*)/\2/v/'				\
-	--regex-c='/(^\s)DEFINE\((\w*)/\2/v/'
+	--regex-c='/(^\s)DEFINE\((\w*)/\2/v/'				\
+	--regex-c='/DEFINE_HASHTABLE\((\w*)/\1/v/'
 
 	all_kconfigs | xargs $1 -a                              \
 	--langdef=kconfig --language-force=kconfig              \
@@ -246,7 +247,8 @@ emacs()
 	--regex='/__TESTCLEARFLAG_FALSE(\([^,)]*\).*/__TestClearPage\1/' \
 	--regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'		\
 	--regex='/PCI_OP_READ(\([a-z]*[a-z]\).*[1-4])/pci_bus_read_config_\1/' \
-	--regex='/PCI_OP_WRITE(\([a-z]*[a-z]\).*[1-4])/pci_bus_write_config_\1/'
+	--regex='/PCI_OP_WRITE(\([a-z]*[a-z]\).*[1-4])/pci_bus_write_config_\1/'\
+	--regex='/DEFINE_HASHTABLE\((\w*)/\1/v/'
 
 	all_kconfigs | xargs $1 -a                              \
 	--regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
diff --git a/security/capability.c b/security/capability.c
index ad0d4de69944..e76373de3129 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -879,7 +879,7 @@ static void cap_key_free(struct key *key)
 }
 
 static int cap_key_permission(key_ref_t key_ref, const struct cred *cred,
-			      key_perm_t perm)
+			      unsigned perm)
 {
 	return 0;
 }
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 80b2aac4f50c..5f20da01fd8d 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -176,20 +176,11 @@ extern int key_task_permission(const key_ref_t key_ref,
 /*
  * Check to see whether permission is granted to use a key in the desired way.
  */
-static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
+static inline int key_permission(const key_ref_t key_ref, unsigned perm)
 {
 	return key_task_permission(key_ref, current_cred(), perm);
 }
 
-/* required permissions */
-#define	KEY_VIEW	0x01	/* require permission to view attributes */
-#define	KEY_READ	0x02	/* require permission to read content */
-#define	KEY_WRITE	0x04	/* require permission to update / modify */
-#define	KEY_SEARCH	0x08	/* require permission to search (keyring) or find (key) */
-#define	KEY_LINK	0x10	/* require permission to link */
-#define	KEY_SETATTR	0x20	/* require permission to change attributes */
-#define	KEY_ALL		0x3f	/* all the above permissions */
-
 /*
  * Authorisation record for request_key().
  */
diff --git a/security/keys/key.c b/security/keys/key.c
index 6e21c11e48bc..2048a110e7f1 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -714,7 +714,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
 	int ret;
 
 	/* need write permission on the key to update it */
-	ret = key_permission(key_ref, KEY_WRITE);
+	ret = key_permission(key_ref, KEY_NEED_WRITE);
 	if (ret < 0)
 		goto error;
 
@@ -838,7 +838,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 
 	/* if we're going to allocate a new key, we're going to have
 	 * to modify the keyring */
-	ret = key_permission(keyring_ref, KEY_WRITE);
+	ret = key_permission(keyring_ref, KEY_NEED_WRITE);
 	if (ret < 0) {
 		key_ref = ERR_PTR(ret);
 		goto error_link_end;
@@ -928,7 +928,7 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
 	key_check(key);
 
 	/* the key must be writable */
-	ret = key_permission(key_ref, KEY_WRITE);
+	ret = key_permission(key_ref, KEY_NEED_WRITE);
 	if (ret < 0)
 		goto error;
 
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index cee72ce64222..cd5bd0cef25d 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -111,7 +111,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
 	}
 
 	/* find the target keyring (which must be writable) */
-	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
 	if (IS_ERR(keyring_ref)) {
 		ret = PTR_ERR(keyring_ref);
 		goto error3;
@@ -195,7 +195,7 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
 	dest_ref = NULL;
 	if (destringid) {
 		dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
-					   KEY_WRITE);
+					   KEY_NEED_WRITE);
 		if (IS_ERR(dest_ref)) {
 			ret = PTR_ERR(dest_ref);
 			goto error3;
@@ -253,7 +253,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create)
 	long ret;
 
 	lflags = create ? KEY_LOOKUP_CREATE : 0;
-	key_ref = lookup_user_key(id, lflags, KEY_SEARCH);
+	key_ref = lookup_user_key(id, lflags, KEY_NEED_SEARCH);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error;
@@ -334,7 +334,7 @@ long keyctl_update_key(key_serial_t id,
 	}
 
 	/* find the target key (which must be writable) */
-	key_ref = lookup_user_key(id, 0, KEY_WRITE);
+	key_ref = lookup_user_key(id, 0, KEY_NEED_WRITE);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error2;
@@ -365,12 +365,12 @@ long keyctl_revoke_key(key_serial_t id)
 	key_ref_t key_ref;
 	long ret;
 
-	key_ref = lookup_user_key(id, 0, KEY_WRITE);
+	key_ref = lookup_user_key(id, 0, KEY_NEED_WRITE);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		if (ret != -EACCES)
 			goto error;
-		key_ref = lookup_user_key(id, 0, KEY_SETATTR);
+		key_ref = lookup_user_key(id, 0, KEY_NEED_SETATTR);
 		if (IS_ERR(key_ref)) {
 			ret = PTR_ERR(key_ref);
 			goto error;
@@ -401,7 +401,7 @@ long keyctl_invalidate_key(key_serial_t id)
 
 	kenter("%d", id);
 
-	key_ref = lookup_user_key(id, 0, KEY_SEARCH);
+	key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error;
@@ -428,7 +428,7 @@ long keyctl_keyring_clear(key_serial_t ringid)
 	key_ref_t keyring_ref;
 	long ret;
 
-	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
 	if (IS_ERR(keyring_ref)) {
 		ret = PTR_ERR(keyring_ref);
 
@@ -470,13 +470,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
 	key_ref_t keyring_ref, key_ref;
 	long ret;
 
-	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
 	if (IS_ERR(keyring_ref)) {
 		ret = PTR_ERR(keyring_ref);
 		goto error;
 	}
 
-	key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_LINK);
+	key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_NEED_LINK);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error2;
@@ -505,7 +505,7 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
 	key_ref_t keyring_ref, key_ref;
 	long ret;
 
-	keyring_ref = lookup_user_key(ringid, 0, KEY_WRITE);
+	keyring_ref = lookup_user_key(ringid, 0, KEY_NEED_WRITE);
 	if (IS_ERR(keyring_ref)) {
 		ret = PTR_ERR(keyring_ref);
 		goto error;
@@ -548,7 +548,7 @@ long keyctl_describe_key(key_serial_t keyid,
 	char *tmpbuf;
 	long ret;
 
-	key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
+	key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW);
 	if (IS_ERR(key_ref)) {
 		/* viewing a key under construction is permitted if we have the
 		 * authorisation token handy */
@@ -639,7 +639,7 @@ long keyctl_keyring_search(key_serial_t ringid,
 	}
 
 	/* get the keyring at which to begin the search */
-	keyring_ref = lookup_user_key(ringid, 0, KEY_SEARCH);
+	keyring_ref = lookup_user_key(ringid, 0, KEY_NEED_SEARCH);
 	if (IS_ERR(keyring_ref)) {
 		ret = PTR_ERR(keyring_ref);
 		goto error2;
@@ -649,7 +649,7 @@ long keyctl_keyring_search(key_serial_t ringid,
 	dest_ref = NULL;
 	if (destringid) {
 		dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
-					   KEY_WRITE);
+					   KEY_NEED_WRITE);
 		if (IS_ERR(dest_ref)) {
 			ret = PTR_ERR(dest_ref);
 			goto error3;
@@ -676,7 +676,7 @@ long keyctl_keyring_search(key_serial_t ringid,
 
 	/* link the resulting key to the destination keyring if we can */
 	if (dest_ref) {
-		ret = key_permission(key_ref, KEY_LINK);
+		ret = key_permission(key_ref, KEY_NEED_LINK);
 		if (ret < 0)
 			goto error6;
 
@@ -727,7 +727,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
 	key = key_ref_to_ptr(key_ref);
 
 	/* see if we can read it directly */
-	ret = key_permission(key_ref, KEY_READ);
+	ret = key_permission(key_ref, KEY_NEED_READ);
 	if (ret == 0)
 		goto can_read_key;
 	if (ret != -EACCES)
@@ -799,7 +799,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
 		goto error;
 
 	key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
-				  KEY_SETATTR);
+				  KEY_NEED_SETATTR);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error;
@@ -905,7 +905,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
 		goto error;
 
 	key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
-				  KEY_SETATTR);
+				  KEY_NEED_SETATTR);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error;
@@ -947,7 +947,7 @@ static long get_instantiation_keyring(key_serial_t ringid,
 
 	/* if a specific keyring is nominated by ID, then use that */
 	if (ringid > 0) {
-		dkref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+		dkref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
 		if (IS_ERR(dkref))
 			return PTR_ERR(dkref);
 		*_dest_keyring = key_ref_to_ptr(dkref);
@@ -1315,7 +1315,7 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout)
 	long ret;
 
 	key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
-				  KEY_SETATTR);
+				  KEY_NEED_SETATTR);
 	if (IS_ERR(key_ref)) {
 		/* setting the timeout on a key under construction is permitted
 		 * if we have the authorisation token handy */
@@ -1418,7 +1418,7 @@ long keyctl_get_security(key_serial_t keyid,
 	char *context;
 	long ret;
 
-	key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
+	key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW);
 	if (IS_ERR(key_ref)) {
 		if (PTR_ERR(key_ref) != -EACCES)
 			return PTR_ERR(key_ref);
@@ -1482,7 +1482,7 @@ long keyctl_session_to_parent(void)
 	struct cred *cred;
 	int ret;
 
-	keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK);
+	keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_NEED_LINK);
 	if (IS_ERR(keyring_r))
 		return PTR_ERR(keyring_r);
 
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 2fb2576dc644..9cf2575f0d97 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -541,7 +541,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
 	/* key must have search permissions */
 	if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) &&
 	    key_task_permission(make_key_ref(key, ctx->possessed),
-				ctx->cred, KEY_SEARCH) < 0) {
+				ctx->cred, KEY_NEED_SEARCH) < 0) {
 		ctx->result = ERR_PTR(-EACCES);
 		kleave(" = %d [!perm]", ctx->skipped_ret);
 		goto skipped;
@@ -721,7 +721,7 @@ ascend_to_node:
 		/* Search a nested keyring */
 		if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) &&
 		    key_task_permission(make_key_ref(key, ctx->possessed),
-					ctx->cred, KEY_SEARCH) < 0)
+					ctx->cred, KEY_NEED_SEARCH) < 0)
 			continue;
 
 		/* stack the current position */
@@ -843,7 +843,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 		return ERR_PTR(-ENOTDIR);
 
 	if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM)) {
-		err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH);
+		err = key_task_permission(keyring_ref, ctx->cred, KEY_NEED_SEARCH);
 		if (err < 0)
 			return ERR_PTR(err);
 	}
@@ -973,7 +973,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
 
 			if (!skip_perm_check &&
 			    key_permission(make_key_ref(keyring, 0),
-					   KEY_SEARCH) < 0)
+					   KEY_NEED_SEARCH) < 0)
 				continue;
 
 			/* we've got a match but we might end up racing with
diff --git a/security/keys/permission.c b/security/keys/permission.c
index efcc0c855a0d..732cc0beffdf 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -28,7 +28,7 @@
  * permissions bits or the LSM check.
  */
 int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
-			key_perm_t perm)
+			unsigned perm)
 {
 	struct key *key;
 	key_perm_t kperm;
@@ -68,7 +68,7 @@ use_these_perms:
 	if (is_key_possessed(key_ref))
 		kperm |= key->perm >> 24;
 
-	kperm = kperm & perm & KEY_ALL;
+	kperm = kperm & perm & KEY_NEED_ALL;
 
 	if (kperm != perm)
 		return -EACCES;
diff --git a/security/keys/persistent.c b/security/keys/persistent.c
index 0ad3ee283781..c9fae5ea89fe 100644
--- a/security/keys/persistent.c
+++ b/security/keys/persistent.c
@@ -108,7 +108,7 @@ static long key_get_persistent(struct user_namespace *ns, kuid_t uid,
 	return PTR_ERR(persistent_ref);
 
 found:
-	ret = key_task_permission(persistent_ref, current_cred(), KEY_LINK);
+	ret = key_task_permission(persistent_ref, current_cred(), KEY_NEED_LINK);
 	if (ret == 0) {
 		persistent = key_ref_to_ptr(persistent_ref);
 		ret = key_link(key_ref_to_ptr(dest_ref), persistent);
@@ -151,7 +151,7 @@ long keyctl_get_persistent(uid_t _uid, key_serial_t destid)
 	}
 
 	/* There must be a destination keyring */
-	dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_WRITE);
+	dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
 	if (IS_ERR(dest_ref))
 		return PTR_ERR(dest_ref);
 	if (key_ref_to_ptr(dest_ref)->type != &key_type_keyring) {
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 88e9a466940f..d3f6f2fd21db 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -218,7 +218,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
 	 * - the caller holds a spinlock, and thus the RCU read lock, making our
 	 *   access to __current_cred() safe
 	 */
-	rc = key_task_permission(key_ref, ctx.cred, KEY_VIEW);
+	rc = key_task_permission(key_ref, ctx.cred, KEY_NEED_VIEW);
 	if (rc < 0)
 		return 0;
 
diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c
index 8c0af08760c8..b68faa1a5cfd 100644
--- a/security/keys/sysctl.c
+++ b/security/keys/sysctl.c
@@ -15,7 +15,7 @@
 
 static const int zero, one = 1, max = INT_MAX;
 
-ctl_table key_sysctls[] = {
+struct ctl_table key_sysctls[] = {
 	{
 		.procname = "maxkeys",
 		.data = &key_quota_maxkeys,
diff --git a/security/security.c b/security/security.c
index 8b774f362a3d..31614e9e96e5 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1425,7 +1425,7 @@ void security_key_free(struct key *key)
 }
 
 int security_key_permission(key_ref_t key_ref,
-			    const struct cred *cred, key_perm_t perm)
+			    const struct cred *cred, unsigned perm)
 {
 	return security_ops->key_permission(key_ref, cred, perm);
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b4beb77967b1..6befc9203e65 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5722,7 +5722,7 @@ static void selinux_key_free(struct key *k)
 
 static int selinux_key_permission(key_ref_t key_ref,
 				  const struct cred *cred,
-				  key_perm_t perm)
+				  unsigned perm)
 {
 	struct key *key;
 	struct key_security_struct *ksec;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 14f52be78c75..8177e7df8c2d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3506,11 +3506,12 @@ static void smack_key_free(struct key *key)
  * an error code otherwise
  */
 static int smack_key_permission(key_ref_t key_ref,
-				const struct cred *cred, key_perm_t perm)
+				const struct cred *cred, unsigned perm)
 {
 	struct key *keyp;
 	struct smk_audit_info ad;
 	struct smack_known *tkp = smk_of_task(cred->security);
+	int request = 0;
 
 	keyp = key_ref_to_ptr(key_ref);
 	if (keyp == NULL)
@@ -3531,7 +3532,11 @@ static int smack_key_permission(key_ref_t key_ref,
 	ad.a.u.key_struct.key = keyp->serial;
 	ad.a.u.key_struct.key_desc = keyp->description;
 #endif
-	return smk_access(tkp, keyp->security, MAY_READWRITE, &ad);
+	if (perm & KEY_NEED_READ)
+		request = MAY_READ;
+	if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR))
+		request = MAY_WRITE;
+	return smk_access(tkp, keyp->security, request, &ad);
 }
 #endif /* CONFIG_KEYS */
 
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 05ec049c9faf..a04d23174dc2 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -1198,6 +1198,7 @@ static int atmel_ac97c_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver atmel_ac97c_driver = {
+	.probe		= atmel_ac97c_probe,
 	.remove		= atmel_ac97c_remove,
 	.driver		= {
 		.name	= "atmel_ac97c",
@@ -1205,19 +1206,7 @@ static struct platform_driver atmel_ac97c_driver = {
 		.pm	= ATMEL_AC97C_PM_OPS,
 	},
 };
-
-static int __init atmel_ac97c_init(void)
-{
-	return platform_driver_probe(&atmel_ac97c_driver,
-			atmel_ac97c_probe);
-}
-module_init(atmel_ac97c_init);
-
-static void __exit atmel_ac97c_exit(void)
-{
-	platform_driver_unregister(&atmel_ac97c_driver);
-}
-module_exit(atmel_ac97c_exit);
+module_platform_driver(atmel_ac97c_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Driver for Atmel AC97 controller");
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index ce83def9f43b..9acc77eae487 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -345,7 +345,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
 			snd_pcm_debug_name(substream, name, sizeof(name));
 			xrun_log_show(substream);
 			pcm_err(substream->pcm,
-				"BUG: %s, pos = %ld, buffer size = %ld, period size = %ld\n",
+				"XRUN: %s, pos = %ld, buffer size = %ld, period size = %ld\n",
 				name, pos, runtime->buffer_size,
 				runtime->period_size);
 		}
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 1c16830af3d8..6faaac60161a 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -520,7 +520,7 @@ static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip,
 			snd_es18xx_mixer_write(chip, 0x78, 0x93);
 #ifdef AVOID_POPS
 		/* Avoid pops */
-                udelay(100000);
+		mdelay(100);
 		if (chip->caps & ES18XX_PCM2)
 			/* Restore Audio 2 volume */
 			snd_es18xx_mixer_write(chip, 0x7C, chip->audio2_vol);
@@ -537,7 +537,7 @@ static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip,
                 /* Stop DMA */
                 snd_es18xx_mixer_write(chip, 0x78, 0x00);
 #ifdef AVOID_POPS
-                udelay(25000);
+		mdelay(25);
 		if (chip->caps & ES18XX_PCM2)
 			/* Set Audio 2 volume to 0 */
 			snd_es18xx_mixer_write(chip, 0x7C, 0);
@@ -596,7 +596,7 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
 	snd_es18xx_write(chip, 0xA5, count >> 8);
 
 #ifdef AVOID_POPS
-	udelay(100000);
+	mdelay(100);
 #endif
 
         /* Set format */
@@ -691,7 +691,7 @@ static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip,
                 snd_es18xx_write(chip, 0xB8, 0x05);
 #ifdef AVOID_POPS
 		/* Avoid pops */
-                udelay(100000);
+		mdelay(100);
                 /* Enable Audio 1 */
                 snd_es18xx_dsp_command(chip, 0xD1);
 #endif
@@ -705,7 +705,7 @@ static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip,
                 snd_es18xx_write(chip, 0xB8, 0x00);
 #ifdef AVOID_POPS
 		/* Avoid pops */
-                udelay(25000);
+		mdelay(25);
                 /* Disable Audio 1 */
                 snd_es18xx_dsp_command(chip, 0xD3);
 #endif
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 14ae979a92ea..c643dfc0a826 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4621,6 +4621,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1028, 0x0667, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -4912,6 +4913,7 @@ static int patch_alc269(struct hda_codec *codec)
 		spec->codec_variant = ALC269_TYPE_ALC285;
 		break;
 	case 0x10ec0286:
+	case 0x10ec0288:
 		spec->codec_variant = ALC269_TYPE_ALC286;
 		break;
 	case 0x10ec0255:
@@ -5539,6 +5541,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE),
 	SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE),
+	SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
 	SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
 	SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
@@ -5781,6 +5785,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
 	{ .id = 0x10ec0285, .name = "ALC285", .patch = patch_alc269 },
 	{ .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 },
+	{ .id = 0x10ec0288, .name = "ALC288", .patch = patch_alc269 },
 	{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
 	{ .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
 	{ .id = 0x10ec0293, .name = "ALC293", .patch = patch_alc269 },
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index b07e17160f94..3c4b10ff48c1 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -276,7 +276,7 @@ static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int reg2 = mc->rreg;
 	int val[2], val2[2], i;
@@ -300,7 +300,7 @@ static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int reg2 = mc->rreg;
 	int err;
@@ -333,7 +333,7 @@ static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int reg2 = mc->rreg;
 	unsigned int shift = mc->shift;
@@ -353,7 +353,7 @@ static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int reg2 = mc->rreg;
 	unsigned int shift = mc->shift;
@@ -1327,10 +1327,6 @@ static int pm860x_probe(struct snd_soc_codec *codec)
 
 	pm860x->codec = codec;
 
-	ret = snd_soc_codec_set_cache_io(codec, pm860x->regmap);
-	if (ret)
-		return ret;
-
 	for (i = 0; i < 4; i++) {
 		ret = request_threaded_irq(pm860x->irq[i], NULL,
 					   pm860x_codec_handler, IRQF_ONESHOT,
@@ -1362,10 +1358,18 @@ static int pm860x_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static struct regmap *pm860x_get_regmap(struct device *dev)
+{
+	struct pm860x_priv *pm860x = dev_get_drvdata(dev);
+
+	return pm860x->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
 	.probe		= pm860x_probe,
 	.remove		= pm860x_remove,
 	.set_bias_level	= pm860x_set_bias_level,
+	.get_regmap	= pm860x_get_regmap,
 
 	.controls = pm860x_snd_controls,
 	.num_controls = ARRAY_SIZE(pm860x_snd_controls),
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f0e840137887..3afa868b3ebf 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -39,7 +39,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_ALC5623 if I2C
 	select SND_SOC_ALC5632 if I2C
 	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
-	select SND_SOC_CS42L51 if I2C
+	select SND_SOC_CS42L51_I2C if I2C
 	select SND_SOC_CS42L52 if I2C
 	select SND_SOC_CS42L73 if I2C
 	select SND_SOC_CS4270 if I2C
@@ -80,6 +80,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_SSM2602_SPI if SPI_MASTER
 	select SND_SOC_SSM2602_I2C if I2C
 	select SND_SOC_STA32X if I2C
+	select SND_SOC_STA350 if I2C
 	select SND_SOC_STA529 if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
 	select SND_SOC_TAS5086 if I2C
@@ -280,6 +281,10 @@ config SND_SOC_CQ0093VC
 config SND_SOC_CS42L51
 	tristate
 
+config SND_SOC_CS42L51_I2C
+	tristate
+	select SND_SOC_CS42L51
+
 config SND_SOC_CS42L52
 	tristate "Cirrus Logic CS42L52 CODEC"
 	depends on I2C
@@ -435,6 +440,10 @@ config SND_SOC_SSM2602_I2C
 config SND_SOC_STA32X
 	tristate
 
+config SND_SOC_STA350
+	tristate "STA350 speaker amplifier"
+	depends on I2C
+
 config SND_SOC_STA529
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 3c4d275d064b..43a5d974122d 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -26,6 +26,7 @@ snd-soc-ak5386-objs := ak5386.o
 snd-soc-arizona-objs := arizona.o
 snd-soc-cq93vc-objs := cq93vc.o
 snd-soc-cs42l51-objs := cs42l51.o
+snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-cs42l73-objs := cs42l73.o
 snd-soc-cs4270-objs := cs4270.o
@@ -74,6 +75,7 @@ snd-soc-ssm2602-objs := ssm2602.o
 snd-soc-ssm2602-spi-objs := ssm2602-spi.o
 snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o
 snd-soc-sta32x-objs := sta32x.o
+snd-soc-sta350-objs := sta350.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
@@ -177,6 +179,7 @@ obj-$(CONFIG_SND_SOC_ALC5632)	+= snd-soc-alc5632.o
 obj-$(CONFIG_SND_SOC_ARIZONA)	+= snd-soc-arizona.o
 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
 obj-$(CONFIG_SND_SOC_CS42L51)	+= snd-soc-cs42l51.o
+obj-$(CONFIG_SND_SOC_CS42L51_I2C)	+= snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_CS42L73)	+= snd-soc-cs42l73.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
@@ -221,6 +224,7 @@ obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
 obj-$(CONFIG_SND_SOC_SSM2602_SPI)	+= snd-soc-ssm2602-spi.o
 obj-$(CONFIG_SND_SOC_SSM2602_I2C)	+= snd-soc-ssm2602-i2c.o
 obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
+obj-$(CONFIG_SND_SOC_STA350)   += snd-soc-sta350.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 1ad92cbf0b24..1fb4402bf72d 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -1139,7 +1139,7 @@ static void anc_configure(struct snd_soc_codec *codec,
 static int sid_status_control_get(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 
 	mutex_lock(&codec->mutex);
@@ -1153,7 +1153,7 @@ static int sid_status_control_get(struct snd_kcontrol *kcontrol,
 static int sid_status_control_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 	unsigned int param, sidconf, val;
 	int status = 1;
@@ -1208,7 +1208,7 @@ out:
 static int anc_status_control_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 
 	mutex_lock(&codec->mutex);
@@ -1221,7 +1221,7 @@ static int anc_status_control_get(struct snd_kcontrol *kcontrol,
 static int anc_status_control_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 	struct device *dev = codec->dev;
 	bool apply_fir, apply_iir;
@@ -1306,7 +1306,7 @@ static int filter_control_info(struct snd_kcontrol *kcontrol,
 static int filter_control_get(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct filter_control *fc =
 			(struct filter_control *)kcontrol->private_value;
 	unsigned int i;
@@ -1322,7 +1322,7 @@ static int filter_control_get(struct snd_kcontrol *kcontrol,
 static int filter_control_put(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct filter_control *fc =
 			(struct filter_control *)kcontrol->private_value;
 	unsigned int i;
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 877f5737bb6b..1ff7d4d027e9 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -519,8 +519,7 @@ static const struct snd_kcontrol_new adau1373_controls[] = {
 	SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum),
 
 	SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum),
-	SOC_VALUE_ENUM("Bass Clip Level Threshold",
-	    adau1373_bass_clip_level_enum),
+	SOC_ENUM("Bass Clip Level Threshold", adau1373_bass_clip_level_enum),
 	SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum),
 	SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0),
 	SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0,
@@ -580,7 +579,7 @@ static SOC_ENUM_SINGLE_VIRT_DECL(adau1373_decimator_enum,
 	adau1373_decimator_text);
 
 static const struct snd_kcontrol_new adau1373_decimator_mux =
-	SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum);
+	SOC_DAPM_ENUM("Decimator Mux", adau1373_decimator_enum);
 
 static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = {
 	SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0),
@@ -694,7 +693,7 @@ static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = {
 	SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0),
 	SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0),
 
-	SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0,
 		&adau1373_decimator_mux),
 
 	SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0),
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index 5062e34ee8dc..c43b93fdf0df 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -172,14 +172,14 @@ static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3);
 static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3);
 
 static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl =
-	SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum);
+	SOC_DAPM_ENUM("Route", adav80x_aux_capture_enum);
 static const struct snd_kcontrol_new adav80x_capture_mux_ctrl =
-	SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum);
+	SOC_DAPM_ENUM("Route", adav80x_capture_enum);
 static const struct snd_kcontrol_new adav80x_dac_mux_ctrl =
-	SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum);
+	SOC_DAPM_ENUM("Route", adav80x_dac_enum);
 
 #define ADAV80X_MUX(name, ctrl) \
-	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+	SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
 static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = {
 	SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1),
@@ -315,7 +315,7 @@ static int adav80x_set_deemph(struct snd_soc_codec *codec)
 static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 	unsigned int deemph = ucontrol->value.enumerated.item[0];
 
@@ -330,7 +330,7 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
 static int adav80x_get_deemph(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = adav80x->deemph;
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 868c0e2da1ec..7afe8f482088 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -74,7 +74,7 @@ static int ak4641_set_deemph(struct snd_soc_codec *codec)
 static int ak4641_put_deemph(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
 	int deemph = ucontrol->value.enumerated.item[0];
 
@@ -89,7 +89,7 @@ static int ak4641_put_deemph(struct snd_kcontrol *kcontrol,
 static int ak4641_get_deemph(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = ak4641->deemph;
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c
index 72e953b2cb41..8107a1cac876 100644
--- a/sound/soc/codecs/ak5386.c
+++ b/sound/soc/codecs/ak5386.c
@@ -14,12 +14,18 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
 #include <sound/soc.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
 
+static const char * const supply_names[] = {
+	"va", "vd"
+};
+
 struct ak5386_priv {
 	int reset_gpio;
+	struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
 };
 
 static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
@@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
 	{ "Capture", NULL, "AINR" },
 };
 
+static int ak5386_soc_probe(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+}
+
+static int ak5386_soc_remove(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ak5386_soc_suspend(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	return 0;
+}
+
+static int ak5386_soc_resume(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+}
+#else
+#define ak5386_soc_suspend	NULL
+#define ak5386_soc_resume	NULL
+#endif /* CONFIG_PM */
+
 static struct snd_soc_codec_driver soc_codec_ak5386 = {
+	.probe = ak5386_soc_probe,
+	.remove = ak5386_soc_remove,
+	.suspend = ak5386_soc_suspend,
+	.resume = ak5386_soc_resume,
 	.dapm_widgets = ak5386_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
 	.dapm_routes = ak5386_dapm_routes,
@@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ak5386_priv *priv;
+	int ret, i;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev)
 	priv->reset_gpio = -EINVAL;
 	dev_set_drvdata(dev, priv);
 
+	for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+		priv->supplies[i].supply = supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
+				      priv->supplies);
+	if (ret < 0)
+		return ret;
+
 	if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
 		priv->reset_gpio = of_get_named_gpio(dev->of_node,
 						      "reset-gpio", 0);
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index f500905e9373..2acf82f4a08a 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -1018,13 +1018,13 @@ static int alc5623_i2c_probe(struct i2c_client *client,
 		dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
 		return ret;
 	}
-	vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
 
 	ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
 	if (ret < 0) {
 		dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
 		return ret;
 	}
+	vid2 >>= 8;
 
 	if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
 		dev_err(&client->dev, "unknown or wrong codec\n");
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 16df0f913353..05ae17f5bca3 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -107,7 +107,7 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
 
 #define ARIZONA_MUX_CTL_DECL(name) \
 	const struct snd_kcontrol_new name##_mux =	\
-		SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+		SOC_DAPM_ENUM("Route", name##_enum)
 
 #define ARIZONA_MUX_ENUMS(name, base_reg) \
 	static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg);      \
@@ -128,7 +128,7 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
 	ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
 
 #define ARIZONA_MUX(name, ctrl) \
-	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+	SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
 #define ARIZONA_MUX_WIDGETS(name, name_str) \
 	ARIZONA_MUX(name_str " Input", &name##_mux)
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 1e25c7af853b..5ee48c8e4849 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -139,8 +139,6 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
 
 	davinci_vc->cq93vc.codec = codec;
 
-	snd_soc_codec_set_cache_io(codec, davinci_vc->regmap);
-
 	/* Off, with power on */
 	cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -154,11 +152,19 @@ static int cq93vc_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static struct regmap *cq93vc_get_regmap(struct device *dev)
+{
+	struct davinci_vc *davinci_vc = codec->dev->platform_data;
+
+	return davinci_vc->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
 	.set_bias_level = cq93vc_set_bias_level,
 	.probe = cq93vc_probe,
 	.remove = cq93vc_remove,
 	.resume = cq93vc_resume,
+	.get_regmap = cq93vc_get_regmap,
 	.controls = cq93vc_snd_controls,
 	.num_controls = ARRAY_SIZE(cq93vc_snd_controls),
 };
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 3920e6264948..9947a9583679 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -438,7 +438,7 @@ static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute)
 static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
 	int left = !ucontrol->value.integer.value[0];
 	int right = !ucontrol->value.integer.value[1];
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index aef4965750c7..93cec52f4733 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -284,7 +284,7 @@ static int cs4271_set_deemph(struct snd_soc_codec *codec)
 static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = cs4271->deemph;
@@ -294,7 +294,7 @@ static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
 static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 
 	cs4271->deemph = ucontrol->value.enumerated.item[0];
diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c
new file mode 100644
index 000000000000..cee51ae177c1
--- /dev/null
+++ b/sound/soc/codecs/cs42l51-i2c.c
@@ -0,0 +1,59 @@
+/*
+ * cs42l56.c -- CS42L51 ALSA SoC I2C audio driver
+ *
+ * Copyright 2014 CirrusLogic, Inc.
+ *
+ * Author: Brian Austin <brian.austin@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <sound/soc.h>
+
+#include "cs42l51.h"
+
+static struct i2c_device_id cs42l51_i2c_id[] = {
+	{"cs42l51", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id);
+
+static int cs42l51_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
+{
+	struct regmap_config config;
+
+	config = cs42l51_regmap;
+	config.val_bits = 8;
+	config.reg_bits = 8;
+
+	return cs42l51_probe(&i2c->dev, devm_regmap_init_i2c(i2c, &config));
+}
+
+static int cs42l51_i2c_remove(struct i2c_client *i2c)
+{
+	snd_soc_unregister_codec(&i2c->dev);
+
+	return 0;
+}
+
+static struct i2c_driver cs42l51_i2c_driver = {
+	.driver = {
+		.name = "cs42l51",
+		.owner = THIS_MODULE,
+	},
+	.probe = cs42l51_i2c_probe,
+	.remove = cs42l51_i2c_remove,
+	.id_table = cs42l51_i2c_id,
+};
+
+module_i2c_driver(cs42l51_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L51 I2C Driver");
+MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 6c0da2baa154..dadc20d4396c 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -29,7 +29,6 @@
 #include <sound/initval.h>
 #include <sound/pcm_params.h>
 #include <sound/pcm.h>
-#include <linux/i2c.h>
 #include <linux/regmap.h>
 
 #include "cs42l51.h"
@@ -55,7 +54,7 @@ struct cs42l51_private {
 static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3;
 
 	switch (value) {
@@ -83,7 +82,7 @@ static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
 static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned char val;
 
 	switch (ucontrol->value.integer.value[0]) {
@@ -483,7 +482,7 @@ static struct snd_soc_dai_driver cs42l51_dai = {
 	.ops = &cs42l51_dai_ops,
 };
 
-static int cs42l51_probe(struct snd_soc_codec *codec)
+static int cs42l51_codec_probe(struct snd_soc_codec *codec)
 {
 	int ret, reg;
 
@@ -504,7 +503,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
 }
 
 static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
-	.probe = cs42l51_probe,
+	.probe = cs42l51_codec_probe,
 
 	.controls = cs42l51_snd_controls,
 	.num_controls = ARRAY_SIZE(cs42l51_snd_controls),
@@ -514,91 +513,55 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
 	.num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
 };
 
-static const struct regmap_config cs42l51_regmap = {
-	.reg_bits = 8,
-	.val_bits = 8,
-
+const struct regmap_config cs42l51_regmap = {
 	.max_register = CS42L51_CHARGE_FREQ,
 	.cache_type = REGCACHE_RBTREE,
 };
+EXPORT_SYMBOL_GPL(cs42l51_regmap);
 
-static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
-	const struct i2c_device_id *id)
+int cs42l51_probe(struct device *dev, struct regmap *regmap)
 {
 	struct cs42l51_private *cs42l51;
-	struct regmap *regmap;
 	unsigned int val;
 	int ret;
 
-	regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap);
-	if (IS_ERR(regmap)) {
-		ret = PTR_ERR(regmap);
-		dev_err(&i2c_client->dev, "Failed to create regmap: %d\n",
-			ret);
-		return ret;
-	}
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	cs42l51 = devm_kzalloc(dev, sizeof(struct cs42l51_private),
+			       GFP_KERNEL);
+	if (!cs42l51)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, cs42l51);
 
 	/* Verify that we have a CS42L51 */
 	ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
 	if (ret < 0) {
-		dev_err(&i2c_client->dev, "failed to read I2C\n");
+		dev_err(dev, "failed to read I2C\n");
 		goto error;
 	}
 
 	if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
 	    (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
-		dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val);
+		dev_err(dev, "Invalid chip id: %x\n", val);
 		ret = -ENODEV;
 		goto error;
 	}
+	dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n", val & 0xFF);
 
-	dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
-		 val & 7);
-
-	cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private),
-			       GFP_KERNEL);
-	if (!cs42l51)
-		return -ENOMEM;
-
-	i2c_set_clientdata(i2c_client, cs42l51);
-
-	ret =  snd_soc_register_codec(&i2c_client->dev,
+	ret =  snd_soc_register_codec(dev,
 			&soc_codec_device_cs42l51, &cs42l51_dai, 1);
 error:
 	return ret;
 }
-
-static int cs42l51_i2c_remove(struct i2c_client *client)
-{
-	snd_soc_unregister_codec(&client->dev);
-	return 0;
-}
-
-static const struct i2c_device_id cs42l51_id[] = {
-	{"cs42l51", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, cs42l51_id);
+EXPORT_SYMBOL_GPL(cs42l51_probe);
 
 static const struct of_device_id cs42l51_of_match[] = {
 	{ .compatible = "cirrus,cs42l51", },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, cs42l51_of_match);
-
-static struct i2c_driver cs42l51_i2c_driver = {
-	.driver = {
-		.name = "cs42l51-codec",
-		.owner = THIS_MODULE,
-		.of_match_table = cs42l51_of_match,
-	},
-	.id_table = cs42l51_id,
-	.probe = cs42l51_i2c_probe,
-	.remove = cs42l51_i2c_remove,
-};
-
-module_i2c_driver(cs42l51_i2c_driver);
-
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h
index 2beeb171db4b..641ef18435b3 100644
--- a/sound/soc/codecs/cs42l51.h
+++ b/sound/soc/codecs/cs42l51.h
@@ -18,6 +18,11 @@
 #ifndef _CS42L51_H
 #define _CS42L51_H
 
+struct device;
+
+extern const struct regmap_config cs42l51_regmap;
+int cs42l51_probe(struct device *dev, struct regmap *regmap);
+
 #define CS42L51_CHIP_ID			0x1B
 #define CS42L51_CHIP_REV_A		0x00
 #define CS42L51_CHIP_REV_B		0x01
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 137e8ebc092c..21810e5f3321 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -335,7 +335,7 @@ static SOC_ENUM_SINGLE_DECL(da7210_hp_mode_sel,
 static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 
 	if (ucontrol->value.integer.value[0]) {
 		/* Check if noise suppression is enabled */
@@ -358,7 +358,7 @@ static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
 static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	u8 val;
 
 	if (ucontrol->value.integer.value[0]) {
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index 738fa18a50d2..9ec577f0edb4 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -345,7 +345,7 @@ static void da7213_alc_calib(struct snd_soc_codec *codec)
 static int da7213_put_mixin_gain(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
@@ -361,7 +361,7 @@ static int da7213_put_mixin_gain(struct snd_kcontrol *kcontrol,
 static int da7213_put_alc_sw(struct snd_kcontrol *kcontrol,
 			    struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec);
 
 	/* Force ALC offset calibration if enabling ALC */
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index 48f3fef68484..2fae31cb0067 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -332,7 +332,7 @@ static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum,
 static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
 	unsigned int reg = enum_ctrl->reg;
 	unsigned int sel = ucontrol->value.integer.value[0];
@@ -360,7 +360,7 @@ static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
 static int da732x_hpf_get(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
 	unsigned int reg = enum_ctrl->reg;
 	int val;
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index 4ff06b50fbba..ad19cc56702b 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -484,7 +484,7 @@ static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val)
 static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	u8 reg_val, adc_left, adc_right, mic_left, mic_right;
 	int avg_left_data, avg_right_data, offset_l, offset_r;
 
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c
index 9cb1c7d3e1dc..1087fd5f9917 100644
--- a/sound/soc/codecs/hdmi.c
+++ b/sound/soc/codecs/hdmi.c
@@ -20,6 +20,7 @@
  */
 #include <linux/module.h>
 #include <sound/soc.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 
 #define DRV_NAME "hdmi-audio-codec"
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 4f048db9f55f..a924bb9d7886 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -49,7 +49,7 @@ static const struct reg_default lm4857_default_regs[] = {
 static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = lm4857->mode;
@@ -60,7 +60,7 @@ static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
 static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
 	uint8_t value = ucontrol->value.integer.value[0];
 
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index ec481fc428c7..e1c196a41930 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -43,7 +43,7 @@ static struct reg_default max9768_default_regs[] = {
 static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
 	int val = gpio_get_value_cansleep(max9768->mute_gpio);
 
@@ -55,7 +55,7 @@ static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
 static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
 
 	gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index ef7cf89f5623..9134982807b5 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -635,7 +635,7 @@ static SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum,
 static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
        unsigned int sel = ucontrol->value.integer.value[0];
 
@@ -649,7 +649,7 @@ static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol,
 static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
 
        ucontrol->value.integer.value[0] = max98088->mic1pre;
@@ -659,7 +659,7 @@ static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol,
 static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
        unsigned int sel = ucontrol->value.integer.value[0];
 
@@ -673,7 +673,7 @@ static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol,
 static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
 
        ucontrol->value.integer.value[0] = max98088->mic2pre;
@@ -1750,7 +1750,7 @@ static void max98088_setup_eq2(struct snd_soc_codec *codec)
 static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
        struct max98088_pdata *pdata = max98088->pdata;
        int channel = max98088_get_channel(codec, kcontrol->id.name);
@@ -1782,7 +1782,7 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
 static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
        int channel = max98088_get_channel(codec, kcontrol->id.name);
        struct max98088_cdata *cdata;
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index f7b0b37aa858..f3dd9791e736 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -11,6 +11,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
@@ -426,7 +427,7 @@ static const unsigned int max98090_rcv_lout_tlv[] = {
 static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
@@ -466,7 +467,7 @@ static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol,
 static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
@@ -875,7 +876,7 @@ static const char *dmic_mux_text[] = { "ADC", "DMIC" };
 static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text);
 
 static const struct snd_kcontrol_new max98090_dmic_mux =
-	SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum);
+	SOC_DAPM_ENUM("DMIC Mux", dmic_mux_enum);
 
 static const char *max98090_micpre_text[] = { "Off", "On" };
 
@@ -1175,8 +1176,7 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
 	SND_SOC_DAPM_MUX("MIC2 Mux", SND_SOC_NOPM,
 		0, 0, &max98090_mic2_mux),
 
-	SND_SOC_DAPM_VIRT_MUX("DMIC Mux", SND_SOC_NOPM,
-		0, 0, &max98090_dmic_mux),
+	SND_SOC_DAPM_MUX("DMIC Mux", SND_SOC_NOPM, 0, 0, &max98090_dmic_mux),
 
 	SND_SOC_DAPM_PGA_E("MIC1 Input", M98090_REG_MIC1_INPUT_LEVEL,
 		M98090_MIC_PA1EN_SHIFT, 0, NULL, 0, max98090_micinput_event,
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 03f0536e6f61..5d4c621dbf99 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -612,7 +612,7 @@ static SOC_ENUM_SINGLE_DECL(max98095_dai3_dac_filter_enum,
 static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	unsigned int sel = ucontrol->value.integer.value[0];
 
@@ -626,7 +626,7 @@ static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol,
 static int max98095_mic1pre_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = max98095->mic1pre;
@@ -636,7 +636,7 @@ static int max98095_mic1pre_get(struct snd_kcontrol *kcontrol,
 static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	unsigned int sel = ucontrol->value.integer.value[0];
 
@@ -650,7 +650,7 @@ static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol,
 static int max98095_mic2pre_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = max98095->mic2pre;
@@ -1737,7 +1737,7 @@ static int max98095_get_eq_channel(const char *name)
 static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	struct max98095_pdata *pdata = max98095->pdata;
 	int channel = max98095_get_eq_channel(kcontrol->id.name);
@@ -1801,7 +1801,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
 static int max98095_get_eq_enum(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	int channel = max98095_get_eq_channel(kcontrol->id.name);
 	struct max98095_cdata *cdata;
@@ -1891,7 +1891,7 @@ static int max98095_get_bq_channel(struct snd_soc_codec *codec,
 static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	struct max98095_pdata *pdata = max98095->pdata;
 	int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
@@ -1952,7 +1952,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
 static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
 	struct max98095_cdata *cdata;
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 2c59b1fb69dc..0b0a4ca22da0 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -409,7 +409,7 @@ static const char * const adcl_enum_text[] = {
 static SOC_ENUM_SINGLE_VIRT_DECL(adcl_enum, adcl_enum_text);
 
 static const struct snd_kcontrol_new left_input_mux =
-	SOC_DAPM_ENUM_VIRT("Route", adcl_enum);
+	SOC_DAPM_ENUM("Route", adcl_enum);
 
 static const char * const adcr_enum_text[] = {
 	"MC1R", "MC2", "RXINR", "TXIN",
@@ -418,7 +418,7 @@ static const char * const adcr_enum_text[] = {
 static SOC_ENUM_SINGLE_VIRT_DECL(adcr_enum, adcr_enum_text);
 
 static const struct snd_kcontrol_new right_input_mux =
-	SOC_DAPM_ENUM_VIRT("Route", adcr_enum);
+	SOC_DAPM_ENUM("Route", adcr_enum);
 
 static const struct snd_kcontrol_new samp_ctl =
 	SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0);
@@ -478,9 +478,9 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = {
 	SND_SOC_DAPM_SWITCH("MC2 Amp", MC13783_AUDIO_TX, 9, 0, &mc2_amp_ctl),
 	SND_SOC_DAPM_SWITCH("TXIN Amp", MC13783_AUDIO_TX, 11, 0, &atx_amp_ctl),
 
-	SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0,
 			      &left_input_mux),
-	SND_SOC_DAPM_VIRT_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
 			      &right_input_mux),
 
 	SND_SOC_DAPM_MUX("Speaker Amp Source MUX", SND_SOC_NOPM, 0, 0,
@@ -608,14 +608,6 @@ static struct snd_kcontrol_new mc13783_control_list[] = {
 static int mc13783_probe(struct snd_soc_codec *codec)
 {
 	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
-	int ret;
-
-	ret = snd_soc_codec_set_cache_io(codec,
-			dev_get_regmap(codec->dev->parent, NULL));
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-		return ret;
-	}
 
 	/* these are the reset values */
 	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
@@ -735,9 +727,15 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
 	}
 };
 
+static struct regmap *mc13783_get_regmap(struct device *dev)
+{
+	return dev_get_regmap(dev->parent, NULL);
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
 	.probe		= mc13783_probe,
 	.remove		= mc13783_remove,
+	.get_regmap	= mc13783_get_regmap,
 	.controls	= mc13783_control_list,
 	.num_controls	= ARRAY_SIZE(mc13783_control_list),
 	.dapm_widgets	= mc13783_dapm_widgets,
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
index e427544183d7..a722a023c262 100644
--- a/sound/soc/codecs/pcm1681.c
+++ b/sound/soc/codecs/pcm1681.c
@@ -115,7 +115,7 @@ static int pcm1681_set_deemph(struct snd_soc_codec *codec)
 static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = priv->deemph;
@@ -126,7 +126,7 @@ static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
 static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
 
 	priv->deemph = ucontrol->value.enumerated.item[0];
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 4b4c0c7bb918..163ec3855fd4 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -269,7 +269,7 @@ SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
 	   PCM512x_RQMR_SHIFT, 1, 1),
 
 SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
-SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program),
+SOC_ENUM("DSP Program", pcm512x_dsp_program),
 
 SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
 SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
@@ -517,6 +517,7 @@ void pcm512x_remove(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(pcm512x_remove);
 
+#ifdef CONFIG_PM_RUNTIME
 static int pcm512x_suspend(struct device *dev)
 {
 	struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
@@ -578,6 +579,7 @@ static int pcm512x_resume(struct device *dev)
 
 	return 0;
 }
+#endif
 
 const struct dev_pm_ops pcm512x_pm_ops = {
 	SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index d4c229f0233f..30e234708579 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -188,7 +188,7 @@ static unsigned int mic_bst_tlv[] = {
 static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = rt5631->dmic_used_flag;
@@ -199,7 +199,7 @@ static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
 static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
 
 	rt5631->dmic_used_flag = ucontrol->value.integer.value[0];
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 68b4dd622b87..b947c820697d 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1,5 +1,5 @@
 /*
- * rt5640.c  --  RT5640 ALSA SoC audio codec driver
+ * rt5640.c  --  RT5640/RT5639 ALSA SoC audio codec driver
  *
  * Copyright 2011 Realtek Semiconductor Corp.
  * Author: Johnny Hsu <johnnyhsu@realtek.com>
@@ -18,6 +18,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
@@ -59,7 +60,7 @@ static struct reg_default init_list[] = {
 };
 #define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list)
 
-static const struct reg_default rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
+static const struct reg_default rt5640_reg[] = {
 	{ 0x00, 0x000e },
 	{ 0x01, 0xc8c8 },
 	{ 0x02, 0xc8c8 },
@@ -398,18 +399,13 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
 		RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
 	SOC_DOUBLE_TLV("OUT Playback Volume", RT5640_OUTPUT,
 		RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
-	/* MONO Output Control */
-	SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT,
-				RT5640_L_MUTE_SFT, 1, 1),
+
 	/* DAC Digital Volume */
 	SOC_DOUBLE("DAC2 Playback Switch", RT5640_DAC2_CTRL,
 		RT5640_M_DAC_L2_VOL_SFT, RT5640_M_DAC_R2_VOL_SFT, 1, 1),
 	SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5640_DAC1_DIG_VOL,
 			RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
 			175, 0, dac_vol_tlv),
-	SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL,
-			RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
-			175, 0, dac_vol_tlv),
 	/* IN1/IN2 Control */
 	SOC_SINGLE_TLV("IN1 Boost", RT5640_IN1_IN2,
 		RT5640_BST_SFT1, 8, 0, bst_tlv),
@@ -441,6 +437,15 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
 	SOC_ENUM("DAC IF2 Data Switch", rt5640_if2_dac_enum),
 };
 
+static const struct snd_kcontrol_new rt5640_specific_snd_controls[] = {
+	/* MONO Output Control */
+	SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT, RT5640_L_MUTE_SFT,
+		1, 1),
+
+	SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL,
+		RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 175, 0, dac_vol_tlv),
+};
+
 /**
  * set_dmic_clk - Set parameter of dmic.
  *
@@ -480,14 +485,14 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
 	return idx;
 }
 
-static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
 			 struct snd_soc_dapm_widget *sink)
 {
 	unsigned int val;
 
 	val = snd_soc_read(source->codec, RT5640_GLB_CLK);
 	val &= RT5640_SCLK_SRC_MASK;
-	if (val == RT5640_SCLK_SRC_PLL1 || val == RT5640_SCLK_SRC_PLL1T)
+	if (val == RT5640_SCLK_SRC_PLL1)
 		return 1;
 	else
 		return 0;
@@ -554,6 +559,20 @@ static const struct snd_kcontrol_new rt5640_sto_dac_r_mix[] = {
 			RT5640_M_ANC_DAC_R_SFT, 1, 1),
 };
 
+static const struct snd_kcontrol_new rt5639_sto_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_STO_DAC_MIXER,
+			RT5640_M_DAC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_STO_DAC_MIXER,
+			RT5640_M_DAC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5639_sto_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_STO_DAC_MIXER,
+			RT5640_M_DAC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_STO_DAC_MIXER,
+			RT5640_M_DAC_R2_SFT, 1, 1),
+};
+
 static const struct snd_kcontrol_new rt5640_mono_dac_l_mix[] = {
 	SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_MONO_DAC_MIXER,
 			RT5640_M_DAC_L1_MONO_L_SFT, 1, 1),
@@ -676,6 +695,30 @@ static const struct snd_kcontrol_new rt5640_out_r_mix[] = {
 			RT5640_M_DAC_R1_OM_R_SFT, 1, 1),
 };
 
+static const struct snd_kcontrol_new rt5639_out_l_mix[] = {
+	SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_L3_MIXER,
+			RT5640_M_BST1_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL Switch", RT5640_OUT_L3_MIXER,
+			RT5640_M_IN_L_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_OUT_L3_MIXER,
+			RT5640_M_RM_L_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_OUT_L3_MIXER,
+			RT5640_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5639_out_r_mix[] = {
+	SOC_DAPM_SINGLE("BST2 Switch", RT5640_OUT_R3_MIXER,
+			RT5640_M_BST4_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_R3_MIXER,
+			RT5640_M_BST1_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR Switch", RT5640_OUT_R3_MIXER,
+			RT5640_M_IN_R_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_OUT_R3_MIXER,
+			RT5640_M_RM_R_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_OUT_R3_MIXER,
+			RT5640_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
 static const struct snd_kcontrol_new rt5640_spo_l_mix[] = {
 	SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_L_MIXER,
 			RT5640_M_DAC_R1_SPM_L_SFT, 1, 1),
@@ -707,6 +750,13 @@ static const struct snd_kcontrol_new rt5640_hpo_mix[] = {
 			RT5640_M_HPVOL_HM_SFT, 1, 1),
 };
 
+static const struct snd_kcontrol_new rt5639_hpo_mix[] = {
+	SOC_DAPM_SINGLE("HPO MIX DAC1 Switch", RT5640_HPO_MIXER,
+			RT5640_M_DAC1_HM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("HPO MIX HPVOL Switch", RT5640_HPO_MIXER,
+			RT5640_M_HPVOL_HM_SFT, 1, 1),
+};
+
 static const struct snd_kcontrol_new rt5640_lout_mix[] = {
 	SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_LOUT_MIXER,
 			RT5640_M_DAC_L1_LM_SFT, 1, 1),
@@ -824,7 +874,7 @@ static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_l2_enum,
 				  0x3, rt5640_dac_l2_src, rt5640_dac_l2_values);
 
 static const struct snd_kcontrol_new rt5640_dac_l2_mux =
-	SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum);
+	SOC_DAPM_ENUM("DAC2 left channel source", rt5640_dac_l2_enum);
 
 static const char * const rt5640_dac_r2_src[] = {
 	"IF2",
@@ -859,7 +909,7 @@ static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dai_iis_map_enum,
 				  rt5640_dai_iis_map_values);
 
 static const struct snd_kcontrol_new rt5640_dai_mux =
-	SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum);
+	SOC_DAPM_ENUM("DAI select", rt5640_dai_iis_map_enum);
 
 /* SDI select */
 static const char * const rt5640_sdi_sel[] = {
@@ -872,54 +922,6 @@ static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP,
 static const struct snd_kcontrol_new rt5640_sdi_mux =
 	SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
 
-static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
-			RT5640_GP2_PIN_MASK | RT5640_GP3_PIN_MASK,
-			RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP3_PIN_DMIC1_SDA);
-		snd_soc_update_bits(codec, RT5640_DMIC,
-			RT5640_DMIC_1L_LH_MASK | RT5640_DMIC_1R_LH_MASK |
-			RT5640_DMIC_1_DP_MASK,
-			RT5640_DMIC_1L_LH_FALLING | RT5640_DMIC_1R_LH_RISING |
-			RT5640_DMIC_1_DP_IN1P);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
-			RT5640_GP2_PIN_MASK | RT5640_GP4_PIN_MASK,
-			RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP4_PIN_DMIC2_SDA);
-		snd_soc_update_bits(codec, RT5640_DMIC,
-			RT5640_DMIC_2L_LH_MASK | RT5640_DMIC_2R_LH_MASK |
-			RT5640_DMIC_2_DP_MASK,
-			RT5640_DMIC_2L_LH_FALLING | RT5640_DMIC_2R_LH_RISING |
-			RT5640_DMIC_2_DP_IN1N);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
 static void hp_amp_power_on(struct snd_soc_codec *codec)
 {
 	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
@@ -1054,12 +1056,10 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 
 	SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
 		set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC,
-		RT5640_DMIC_1_EN_SFT, 0, rt5640_set_dmic1_event,
-		SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC,
-		RT5640_DMIC_2_EN_SFT, 0, rt5640_set_dmic2_event,
-		SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC, RT5640_DMIC_1_EN_SFT, 0,
+		NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC, RT5640_DMIC_2_EN_SFT, 0,
+		NULL, 0),
 	/* Boost */
 	SND_SOC_DAPM_PGA("BST1", RT5640_PWR_ANLG2,
 		RT5640_PWR_BST1_BIT, 0, NULL, 0),
@@ -1146,26 +1146,15 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
-	/* Audio DSP */
-	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
-	/* ANC */
-	SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
 	/* Output Side */
 	/* DAC mixer before sound effect  */
 	SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
 		rt5640_dac_l_mix, ARRAY_SIZE(rt5640_dac_l_mix)),
 	SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
 		rt5640_dac_r_mix, ARRAY_SIZE(rt5640_dac_r_mix)),
-	/* DAC2 channel Mux */
-	SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0,
-				&rt5640_dac_l2_mux),
-	SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0,
-				&rt5640_dac_r2_mux),
+
 	/* DAC Mixer */
-	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
-		rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)),
-	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
-		rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)),
 	SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
 		rt5640_mono_dac_l_mix, ARRAY_SIZE(rt5640_mono_dac_l_mix)),
 	SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
@@ -1177,21 +1166,14 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	/* DACs */
 	SND_SOC_DAPM_DAC("DAC L1", NULL, RT5640_PWR_DIG1,
 			RT5640_PWR_DAC_L1_BIT, 0),
-	SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1,
-			RT5640_PWR_DAC_L2_BIT, 0),
 	SND_SOC_DAPM_DAC("DAC R1", NULL, RT5640_PWR_DIG1,
 			RT5640_PWR_DAC_R1_BIT, 0),
-	SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1,
-			RT5640_PWR_DAC_R2_BIT, 0),
+
 	/* SPK/OUT Mixer */
 	SND_SOC_DAPM_MIXER("SPK MIXL", RT5640_PWR_MIXER, RT5640_PWR_SM_L_BIT,
 		0, rt5640_spk_l_mix, ARRAY_SIZE(rt5640_spk_l_mix)),
 	SND_SOC_DAPM_MIXER("SPK MIXR", RT5640_PWR_MIXER, RT5640_PWR_SM_R_BIT,
 		0, rt5640_spk_r_mix, ARRAY_SIZE(rt5640_spk_r_mix)),
-	SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
-		0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)),
-	SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
-		0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)),
 	/* Ouput Volume */
 	SND_SOC_DAPM_PGA("SPKVOL L", RT5640_PWR_VOL,
 		RT5640_PWR_SV_L_BIT, 0, NULL, 0),
@@ -1210,16 +1192,8 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 		0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)),
 	SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0,
 		0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)),
-	SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
-		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
-	SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
-		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
 	SND_SOC_DAPM_MIXER("LOUT MIX", RT5640_PWR_ANLG1, RT5640_PWR_LM_BIT, 0,
 		rt5640_lout_mix, ARRAY_SIZE(rt5640_lout_mix)),
-	SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
-		rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
-	SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
-		RT5640_PWR_MA_BIT, 0, NULL, 0),
 	SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM,
 		0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0,
@@ -1251,10 +1225,69 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("HPOR"),
 	SND_SOC_DAPM_OUTPUT("LOUTL"),
 	SND_SOC_DAPM_OUTPUT("LOUTR"),
+};
+
+static const struct snd_soc_dapm_widget rt5640_specific_dapm_widgets[] = {
+	/* Audio DSP */
+	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+	/* ANC */
+	SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* DAC2 channel Mux */
+	SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dac_l2_mux),
+	SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dac_r2_mux),
+
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)),
+
+	SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1, RT5640_PWR_DAC_R2_BIT,
+		0),
+	SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1, RT5640_PWR_DAC_L2_BIT,
+		0),
+
+	SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
+		0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
+		0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)),
+
+	SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
+		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
+	SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
+		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
+
+	SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
+		rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
+	SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
+		RT5640_PWR_MA_BIT, 0, NULL, 0),
+
 	SND_SOC_DAPM_OUTPUT("MONOP"),
 	SND_SOC_DAPM_OUTPUT("MONON"),
 };
 
+static const struct snd_soc_dapm_widget rt5639_specific_dapm_widgets[] = {
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5639_sto_dac_l_mix, ARRAY_SIZE(rt5639_sto_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5639_sto_dac_r_mix, ARRAY_SIZE(rt5639_sto_dac_r_mix)),
+
+	SND_SOC_DAPM_SUPPLY("DAC L2 Filter", RT5640_PWR_DIG1,
+		RT5640_PWR_DAC_L2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC R2 Filter", RT5640_PWR_DIG1,
+		RT5640_PWR_DAC_R2_BIT, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
+		0, rt5639_out_l_mix, ARRAY_SIZE(rt5639_out_l_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
+		0, rt5639_out_r_mix, ARRAY_SIZE(rt5639_out_r_mix)),
+
+	SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
+		rt5639_hpo_mix, ARRAY_SIZE(rt5639_hpo_mix)),
+	SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
+		rt5639_hpo_mix, ARRAY_SIZE(rt5639_hpo_mix)),
+};
+
 static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"IN1P", NULL, "LDO2"},
 	{"IN2P", NULL, "LDO2"},
@@ -1323,22 +1356,22 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"Stereo ADC MIXL", "ADC1 Switch", "Stereo ADC L1 Mux"},
 	{"Stereo ADC MIXL", "ADC2 Switch", "Stereo ADC L2 Mux"},
 	{"Stereo ADC MIXL", NULL, "Stereo Filter"},
-	{"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"Stereo ADC MIXR", "ADC1 Switch", "Stereo ADC R1 Mux"},
 	{"Stereo ADC MIXR", "ADC2 Switch", "Stereo ADC R2 Mux"},
 	{"Stereo ADC MIXR", NULL, "Stereo Filter"},
-	{"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux"},
 	{"Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux"},
 	{"Mono ADC MIXL", NULL, "Mono Left Filter"},
-	{"Mono Left Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux"},
 	{"Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux"},
 	{"Mono ADC MIXR", NULL, "Mono Right Filter"},
-	{"Mono Right Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"IF2 ADC L", NULL, "Mono ADC MIXL"},
 	{"IF2 ADC R", NULL, "Mono ADC MIXR"},
@@ -1396,71 +1429,38 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"DAC MIXR", "Stereo ADC Switch", "Stereo ADC MIXR"},
 	{"DAC MIXR", "INF1 Switch", "IF1 DAC R"},
 
-	{"ANC", NULL, "Stereo ADC MIXL"},
-	{"ANC", NULL, "Stereo ADC MIXR"},
-
-	{"Audio DSP", NULL, "DAC MIXL"},
-	{"Audio DSP", NULL, "DAC MIXR"},
-
-	{"DAC L2 Mux", "IF2", "IF2 DAC L"},
-	{"DAC L2 Mux", "Base L/R", "Audio DSP"},
-
-	{"DAC R2 Mux", "IF2", "IF2 DAC R"},
-
 	{"Stereo DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
-	{"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
-	{"Stereo DAC MIXL", "ANC Switch", "ANC"},
 	{"Stereo DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
-	{"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
-	{"Stereo DAC MIXR", "ANC Switch", "ANC"},
 
 	{"Mono DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
-	{"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
-	{"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
 	{"Mono DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
-	{"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
-	{"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
 
 	{"DIG MIXL", "DAC L1 Switch", "DAC MIXL"},
-	{"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
 	{"DIG MIXR", "DAC R1 Switch", "DAC MIXR"},
-	{"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
 
 	{"DAC L1", NULL, "Stereo DAC MIXL"},
-	{"DAC L1", NULL, "PLL1", check_sysclk1_source},
+	{"DAC L1", NULL, "PLL1", is_sys_clk_from_pll},
 	{"DAC R1", NULL, "Stereo DAC MIXR"},
-	{"DAC R1", NULL, "PLL1", check_sysclk1_source},
-	{"DAC L2", NULL, "Mono DAC MIXL"},
-	{"DAC L2", NULL, "PLL1", check_sysclk1_source},
-	{"DAC R2", NULL, "Mono DAC MIXR"},
-	{"DAC R2", NULL, "PLL1", check_sysclk1_source},
+	{"DAC R1", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"SPK MIXL", "REC MIXL Switch", "RECMIXL"},
 	{"SPK MIXL", "INL Switch", "INL VOL"},
 	{"SPK MIXL", "DAC L1 Switch", "DAC L1"},
-	{"SPK MIXL", "DAC L2 Switch", "DAC L2"},
 	{"SPK MIXL", "OUT MIXL Switch", "OUT MIXL"},
 	{"SPK MIXR", "REC MIXR Switch", "RECMIXR"},
 	{"SPK MIXR", "INR Switch", "INR VOL"},
 	{"SPK MIXR", "DAC R1 Switch", "DAC R1"},
-	{"SPK MIXR", "DAC R2 Switch", "DAC R2"},
 	{"SPK MIXR", "OUT MIXR Switch", "OUT MIXR"},
 
-	{"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"},
 	{"OUT MIXL", "BST1 Switch", "BST1"},
 	{"OUT MIXL", "INL Switch", "INL VOL"},
 	{"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
-	{"OUT MIXL", "DAC R2 Switch", "DAC R2"},
-	{"OUT MIXL", "DAC L2 Switch", "DAC L2"},
 	{"OUT MIXL", "DAC L1 Switch", "DAC L1"},
 
-	{"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"},
 	{"OUT MIXR", "BST2 Switch", "BST2"},
 	{"OUT MIXR", "BST1 Switch", "BST1"},
 	{"OUT MIXR", "INR Switch", "INR VOL"},
 	{"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
-	{"OUT MIXR", "DAC L2 Switch", "DAC L2"},
-	{"OUT MIXR", "DAC R2 Switch", "DAC R2"},
 	{"OUT MIXR", "DAC R1 Switch", "DAC R1"},
 
 	{"SPKVOL L", NULL, "SPK MIXL"},
@@ -1479,11 +1479,9 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"SPOR MIX", "SPKVOL R Switch", "SPKVOL R"},
 	{"SPOR MIX", "BST1 Switch", "BST1"},
 
-	{"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
 	{"HPO MIX L", "HPO MIX DAC1 Switch", "DAC L1"},
 	{"HPO MIX L", "HPO MIX HPVOL Switch", "HPOVOL L"},
 	{"HPO MIX L", NULL, "HP L Amp"},
-	{"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
 	{"HPO MIX R", "HPO MIX DAC1 Switch", "DAC R1"},
 	{"HPO MIX R", "HPO MIX HPVOL Switch", "HPOVOL R"},
 	{"HPO MIX R", NULL, "HP R Amp"},
@@ -1493,12 +1491,6 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
 	{"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
 
-	{"Mono MIX", "DAC R2 Switch", "DAC R2"},
-	{"Mono MIX", "DAC L2 Switch", "DAC L2"},
-	{"Mono MIX", "OUTVOL R Switch", "OUTVOL R"},
-	{"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
-	{"Mono MIX", "BST1 Switch", "BST1"},
-
 	{"HP Amp", NULL, "HPO MIX L"},
 	{"HP Amp", NULL, "HPO MIX R"},
 
@@ -1523,11 +1515,82 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"HPOR", NULL, "HP R Playback"},
 	{"LOUTL", NULL, "LOUT MIX"},
 	{"LOUTR", NULL, "LOUT MIX"},
+};
+
+static const struct snd_soc_dapm_route rt5640_specific_dapm_routes[] = {
+	{"ANC", NULL, "Stereo ADC MIXL"},
+	{"ANC", NULL, "Stereo ADC MIXR"},
+
+	{"Audio DSP", NULL, "DAC MIXL"},
+	{"Audio DSP", NULL, "DAC MIXR"},
+
+	{"DAC L2 Mux", "IF2", "IF2 DAC L"},
+	{"DAC L2 Mux", "Base L/R", "Audio DSP"},
+
+	{"DAC R2 Mux", "IF2", "IF2 DAC R"},
+
+	{"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+	{"Stereo DAC MIXL", "ANC Switch", "ANC"},
+	{"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+	{"Stereo DAC MIXR", "ANC Switch", "ANC"},
+
+	{"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+	{"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
+
+	{"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+	{"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
+
+	{"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+	{"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+
+	{"DAC L2", NULL, "Mono DAC MIXL"},
+	{"DAC L2", NULL, "PLL1", is_sys_clk_from_pll},
+	{"DAC R2", NULL, "Mono DAC MIXR"},
+	{"DAC R2", NULL, "PLL1", is_sys_clk_from_pll},
+
+	{"SPK MIXL", "DAC L2 Switch", "DAC L2"},
+	{"SPK MIXR", "DAC R2 Switch", "DAC R2"},
+
+	{"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"},
+	{"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"},
+
+	{"OUT MIXL", "DAC R2 Switch", "DAC R2"},
+	{"OUT MIXL", "DAC L2 Switch", "DAC L2"},
+
+	{"OUT MIXR", "DAC L2 Switch", "DAC L2"},
+	{"OUT MIXR", "DAC R2 Switch", "DAC R2"},
+
+	{"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
+	{"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
+
+	{"Mono MIX", "DAC R2 Switch", "DAC R2"},
+	{"Mono MIX", "DAC L2 Switch", "DAC L2"},
+	{"Mono MIX", "OUTVOL R Switch", "OUTVOL R"},
+	{"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
+	{"Mono MIX", "BST1 Switch", "BST1"},
+
 	{"MONOP", NULL, "Mono MIX"},
 	{"MONON", NULL, "Mono MIX"},
 	{"MONOP", NULL, "Improve MONO Amp Drv"},
 };
 
+static const struct snd_soc_dapm_route rt5639_specific_dapm_routes[] = {
+	{"Stereo DAC MIXL", "DAC L2 Switch", "IF2 DAC L"},
+	{"Stereo DAC MIXR", "DAC R2 Switch", "IF2 DAC R"},
+
+	{"Mono DAC MIXL", "DAC L2 Switch", "IF2 DAC L"},
+	{"Mono DAC MIXL", "DAC R2 Switch", "IF2 DAC R"},
+
+	{"Mono DAC MIXR", "DAC R2 Switch", "IF2 DAC R"},
+	{"Mono DAC MIXR", "DAC L2 Switch", "IF2 DAC L"},
+
+	{"DIG MIXL", "DAC L2 Switch", "IF2 DAC L"},
+	{"DIG MIXR", "DAC R2 Switch", "IF2 DAC R"},
+
+	{"IF2 DAC L", NULL, "DAC L2 Filter"},
+	{"IF2 DAC R", NULL, "DAC R2 Filter"},
+};
+
 static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
 {
 	int ret = 0, val;
@@ -1622,16 +1685,16 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
 	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
 				bclk_ms, pre_div, dai->id);
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		val_len |= RT5640_I2S_DL_20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		val_len |= RT5640_I2S_DL_24;
 		break;
-	case SNDRV_PCM_FORMAT_S8:
+	case 8:
 		val_len |= RT5640_I2S_DL_8;
 		break;
 	default:
@@ -1744,12 +1807,6 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
 	case RT5640_SCLK_S_PLL1:
 		reg_val |= RT5640_SCLK_SRC_PLL1;
 		break;
-	case RT5640_SCLK_S_PLL1_TK:
-		reg_val |= RT5640_SCLK_SRC_PLL1T;
-		break;
-	case RT5640_SCLK_S_RCCLK:
-		reg_val |= RT5640_SCLK_SRC_RCCLK;
-		break;
 	default:
 		dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
 		return -EINVAL;
@@ -1890,11 +1947,9 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5640_set_bias_level(struct snd_soc_codec *codec,
 			enum snd_soc_bias_level level)
 {
-	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
 	switch (level) {
 	case SND_SOC_BIAS_STANDBY:
 		if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
-			regcache_cache_only(rt5640->regmap, false);
 			snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
 				RT5640_PWR_VREF1 | RT5640_PWR_MB |
 				RT5640_PWR_BG | RT5640_PWR_VREF2,
@@ -1904,7 +1959,6 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
 			snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2);
-			regcache_sync(rt5640->regmap);
 			snd_soc_update_bits(codec, RT5640_DUMMY1,
 						0x0301, 0x0301);
 			snd_soc_update_bits(codec, RT5640_MICBIAS,
@@ -1938,13 +1992,34 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 
 	rt5640->codec = codec;
 
-	codec->dapm.idle_bias_off = 1;
 	rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
 	snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
 	snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
 
+	switch (snd_soc_read(codec, RT5640_RESET)) {
+	case RT5640_RESET_ID:
+		snd_soc_add_codec_controls(codec,
+			rt5640_specific_snd_controls,
+			ARRAY_SIZE(rt5640_specific_snd_controls));
+		snd_soc_dapm_new_controls(&codec->dapm,
+			rt5640_specific_dapm_widgets,
+			ARRAY_SIZE(rt5640_specific_dapm_widgets));
+		snd_soc_dapm_add_routes(&codec->dapm,
+			rt5640_specific_dapm_routes,
+			ARRAY_SIZE(rt5640_specific_dapm_routes));
+		break;
+	case RT5639_RESET_ID:
+		snd_soc_dapm_new_controls(&codec->dapm,
+			rt5639_specific_dapm_widgets,
+			ARRAY_SIZE(rt5639_specific_dapm_widgets));
+		snd_soc_dapm_add_routes(&codec->dapm,
+			rt5639_specific_dapm_routes,
+			ARRAY_SIZE(rt5639_specific_dapm_routes));
+		break;
+	}
+
 	return 0;
 }
 
@@ -1979,6 +2054,9 @@ static int rt5640_resume(struct snd_soc_codec *codec)
 		msleep(400);
 	}
 
+	regcache_cache_only(rt5640->regmap, false);
+	regcache_sync(rt5640->regmap);
+
 	return 0;
 }
 #else
@@ -2044,6 +2122,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
 	.suspend = rt5640_suspend,
 	.resume = rt5640_resume,
 	.set_bias_level = rt5640_set_bias_level,
+	.idle_bias_off = true,
 	.controls = rt5640_snd_controls,
 	.num_controls = ARRAY_SIZE(rt5640_snd_controls),
 	.dapm_widgets = rt5640_dapm_widgets,
@@ -2070,6 +2149,7 @@ static const struct regmap_config rt5640_regmap = {
 
 static const struct i2c_device_id rt5640_i2c_id[] = {
 	{ "rt5640", 0 },
+	{ "rt5639", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
@@ -2166,7 +2246,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
 	}
 
 	regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val);
-	if ((val != RT5640_DEVICE_ID)) {
+	if (val != RT5640_DEVICE_ID) {
 		dev_err(&i2c->dev,
 			"Device with ID register %x is not rt5640/39\n", val);
 		return -ENODEV;
@@ -2187,6 +2267,25 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
 		regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4,
 					RT5640_IN_DF2, RT5640_IN_DF2);
 
+	if (rt5640->pdata.dmic_en) {
+		regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+			RT5640_GP2_PIN_MASK, RT5640_GP2_PIN_DMIC1_SCL);
+
+		if (rt5640->pdata.dmic1_data_pin) {
+			regmap_update_bits(rt5640->regmap, RT5640_DMIC,
+				RT5640_DMIC_1_DP_MASK, RT5640_DMIC_1_DP_GPIO3);
+			regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+				RT5640_GP3_PIN_MASK, RT5640_GP3_PIN_DMIC1_SDA);
+		}
+
+		if (rt5640->pdata.dmic2_data_pin) {
+			regmap_update_bits(rt5640->regmap, RT5640_DMIC,
+				RT5640_DMIC_2_DP_MASK, RT5640_DMIC_2_DP_GPIO4);
+			regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+				RT5640_GP4_PIN_MASK, RT5640_GP4_PIN_DMIC2_SDA);
+		}
+	}
+
 	rt5640->hp_mute = 1;
 
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
@@ -2219,6 +2318,6 @@ static struct i2c_driver rt5640_i2c_driver = {
 };
 module_i2c_driver(rt5640_i2c_driver);
 
-MODULE_DESCRIPTION("ASoC RT5640 driver");
+MODULE_DESCRIPTION("ASoC RT5640/RT5639 driver");
 MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>");
 MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 5e8df25a13f3..3b50459a83b4 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -14,6 +14,9 @@
 
 #include <sound/rt5640.h>
 
+#define RT5639_RESET_ID				0x0008
+#define RT5640_RESET_ID				0x000c
+
 /* Info */
 #define RT5640_RESET				0x00
 #define RT5640_VENDOR_ID			0xfd
@@ -976,8 +979,6 @@
 #define RT5640_SCLK_SRC_SFT			14
 #define RT5640_SCLK_SRC_MCLK			(0x0 << 14)
 #define RT5640_SCLK_SRC_PLL1			(0x1 << 14)
-#define RT5640_SCLK_SRC_PLL1T			(0x2 << 14)
-#define RT5640_SCLK_SRC_RCCLK			(0x3 << 14) /* 15MHz */
 #define RT5640_PLL1_SRC_MASK			(0x3 << 12)
 #define RT5640_PLL1_SRC_SFT			12
 #define RT5640_PLL1_SRC_MCLK			(0x0 << 12)
@@ -2097,7 +2098,6 @@ struct rt5640_priv {
 	int pll_in;
 	int pll_out;
 
-	int dmic_en;
 	bool hp_mute;
 };
 
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index d3ed1be5a186..b56caefcf664 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -296,7 +296,7 @@ static int dac_info_volsw(struct snd_kcontrol *kcontrol,
 static int dac_get_volsw(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	int reg;
 	int l;
 	int r;
@@ -349,7 +349,7 @@ static int dac_get_volsw(struct snd_kcontrol *kcontrol,
 static int dac_put_volsw(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	int reg;
 	int l;
 	int r;
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 244c097cd905..f26befb0c297 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -208,13 +208,6 @@ out:
 	return err;
 }
 
-static int si476x_codec_probe(struct snd_soc_codec *codec)
-{
-	struct regmap *regmap = dev_get_regmap(codec->dev->parent, NULL);
-
-	return snd_soc_codec_set_cache_io(codec, regmap);
-}
-
 static struct snd_soc_dai_ops si476x_dai_ops = {
 	.hw_params	= si476x_codec_hw_params,
 	.set_fmt	= si476x_codec_set_dai_fmt,
@@ -238,8 +231,13 @@ static struct snd_soc_dai_driver si476x_dai = {
 	.ops		= &si476x_dai_ops,
 };
 
+static struct regmap *si476x_get_regmap(struct device *dev)
+{
+	return dev_get_regmap(dev->parent, NULL);
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_si476x = {
-	.probe  = si476x_codec_probe,
+	.get_regmap = si476x_get_regmap,
 	.dapm_widgets = si476x_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets),
 	.dapm_routes = si476x_dapm_routes,
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c
index 58e7c1f23771..c5177bc5df82 100644
--- a/sound/soc/codecs/sirf-audio-codec.c
+++ b/sound/soc/codecs/sirf-audio-codec.c
@@ -279,13 +279,63 @@ static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
 	{"Mic input mode mux", "Differential", "MICIN1"},
 };
 
+static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
+{
+	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
+		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
+	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
+		AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
+	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
+	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
+	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
+		AUDIO_FIFO_START, AUDIO_FIFO_START);
+	regmap_update_bits(sirf_audio_codec->regmap,
+		AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
+}
+
+static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
+{
+	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
+	regmap_update_bits(sirf_audio_codec->regmap,
+		AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
+}
+
+static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
+	int channels)
+{
+	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
+		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
+	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
+		AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
+	regmap_write(sirf_audio_codec->regmap,
+		AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
+	regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
+	regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
+		AUDIO_FIFO_START, AUDIO_FIFO_START);
+	if (channels == 1)
+		regmap_update_bits(sirf_audio_codec->regmap,
+			AUDIO_PORT_IC_CODEC_RX_CTRL,
+			IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
+	else
+		regmap_update_bits(sirf_audio_codec->regmap,
+			AUDIO_PORT_IC_CODEC_RX_CTRL,
+			IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
+}
+
+static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
+{
+	regmap_update_bits(sirf_audio_codec->regmap,
+			AUDIO_PORT_IC_CODEC_RX_CTRL,
+			IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
+}
+
 static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
 		int cmd,
 		struct snd_soc_dai *dai)
 {
-	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	struct snd_soc_codec *codec = dai->codec;
-	u32 val = 0;
+	struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec);
+	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
 	/*
 	 * This is a workaround, When stop playback,
@@ -295,20 +345,28 @@ static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (playback) {
+			snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
+				IC_HSLEN | IC_HSREN, 0);
+			sirf_audio_codec_tx_disable(sirf_audio_codec);
+		} else
+			sirf_audio_codec_rx_disable(sirf_audio_codec);
 		break;
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (playback)
-			val = IC_HSLEN | IC_HSREN;
+		if (playback) {
+			sirf_audio_codec_tx_enable(sirf_audio_codec);
+			snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
+				IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
+		} else
+			sirf_audio_codec_rx_enable(sirf_audio_codec,
+				substream->runtime->channels);
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	if (playback)
-		snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0,
-			IC_HSLEN | IC_HSREN, val);
 	return 0;
 }
 
@@ -392,7 +450,7 @@ static const struct regmap_config sirf_audio_codec_regmap_config = {
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
-	.max_register = AUDIO_IC_CODEC_CTRL3,
+	.max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
 	.cache_type = REGCACHE_NONE,
 };
 
diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h
index d4c187b8e54a..ba1adc03839f 100644
--- a/sound/soc/codecs/sirf-audio-codec.h
+++ b/sound/soc/codecs/sirf-audio-codec.h
@@ -72,4 +72,54 @@
 #define IC_RXPGAR		0x7B
 #define IC_RXPGAL		0x7B
 
+#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK     0x3F
+#define AUDIO_PORT_TX_FIFO_SC_OFFSET    0
+#define AUDIO_PORT_TX_FIFO_LC_OFFSET    10
+#define AUDIO_PORT_TX_FIFO_HC_OFFSET    20
+
+#define TX_FIFO_SC(x)           (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
+				<< AUDIO_PORT_TX_FIFO_SC_OFFSET)
+#define TX_FIFO_LC(x)           (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
+				<< AUDIO_PORT_TX_FIFO_LC_OFFSET)
+#define TX_FIFO_HC(x)           (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
+				<< AUDIO_PORT_TX_FIFO_HC_OFFSET)
+
+#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK     0x0F
+#define AUDIO_PORT_RX_FIFO_SC_OFFSET    0
+#define AUDIO_PORT_RX_FIFO_LC_OFFSET    10
+#define AUDIO_PORT_RX_FIFO_HC_OFFSET    20
+
+#define RX_FIFO_SC(x)           (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
+				<< AUDIO_PORT_RX_FIFO_SC_OFFSET)
+#define RX_FIFO_LC(x)           (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
+				<< AUDIO_PORT_RX_FIFO_LC_OFFSET)
+#define RX_FIFO_HC(x)           (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
+				<< AUDIO_PORT_RX_FIFO_HC_OFFSET)
+#define AUDIO_PORT_IC_CODEC_TX_CTRL		(0x00F4)
+#define AUDIO_PORT_IC_CODEC_RX_CTRL		(0x00F8)
+
+#define AUDIO_PORT_IC_TXFIFO_OP			(0x00FC)
+#define AUDIO_PORT_IC_TXFIFO_LEV_CHK		(0x0100)
+#define AUDIO_PORT_IC_TXFIFO_STS		(0x0104)
+#define AUDIO_PORT_IC_TXFIFO_INT		(0x0108)
+#define AUDIO_PORT_IC_TXFIFO_INT_MSK		(0x010C)
+
+#define AUDIO_PORT_IC_RXFIFO_OP			(0x0110)
+#define AUDIO_PORT_IC_RXFIFO_LEV_CHK		(0x0114)
+#define AUDIO_PORT_IC_RXFIFO_STS		(0x0118)
+#define AUDIO_PORT_IC_RXFIFO_INT		(0x011C)
+#define AUDIO_PORT_IC_RXFIFO_INT_MSK		(0x0120)
+
+#define AUDIO_FIFO_START		(1 << 0)
+#define AUDIO_FIFO_RESET		(1 << 1)
+
+#define AUDIO_FIFO_FULL			(1 << 0)
+#define AUDIO_FIFO_EMPTY		(1 << 1)
+#define AUDIO_FIFO_OFLOW		(1 << 2)
+#define AUDIO_FIFO_UFLOW		(1 << 3)
+
+#define IC_TX_ENABLE		(0x03)
+#define IC_RX_ENABLE_MONO	(0x01)
+#define IC_RX_ENABLE_STEREO	(0x03)
+
 #endif /*__SIRF_AUDIO_CODEC_H*/
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 12577749b17b..0579d187135b 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -243,7 +243,7 @@ static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol,
 static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	int numcoef = kcontrol->private_value >> 16;
 	int index = kcontrol->private_value & 0xffff;
 	unsigned int cfud;
@@ -272,7 +272,7 @@ static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
 static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
 	int numcoef = kcontrol->private_value >> 16;
 	int index = kcontrol->private_value & 0xffff;
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c
new file mode 100644
index 000000000000..552e92a6b770
--- /dev/null
+++ b/sound/soc/codecs/sta350.c
@@ -0,0 +1,1266 @@
+/*
+ * Codec driver for ST STA350 2.1-channel high-efficiency digital audio system
+ *
+ * Copyright: 2014 Raumfeld GmbH
+ * Author: Sven Brandau <info@brandau.biz>
+ *
+ * based on code from:
+ *	Raumfeld GmbH
+ *	  Johannes Stezenbach <js@sig21.net>
+ *	Wolfson Microelectronics PLC.
+ *	  Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *	Freescale Semiconductor, Inc.
+ *	  Timur Tabi <timur@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <sound/sta350.h>
+#include "sta350.h"
+
+#define STA350_RATES (SNDRV_PCM_RATE_32000 | \
+		      SNDRV_PCM_RATE_44100 | \
+		      SNDRV_PCM_RATE_48000 | \
+		      SNDRV_PCM_RATE_88200 | \
+		      SNDRV_PCM_RATE_96000 | \
+		      SNDRV_PCM_RATE_176400 | \
+		      SNDRV_PCM_RATE_192000)
+
+#define STA350_FORMATS \
+	(SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S16_BE  | \
+	 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
+	 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
+	 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
+	 SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE  | \
+	 SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_S32_BE)
+
+/* Power-up register defaults */
+static const struct reg_default sta350_regs[] = {
+	{  0x0, 0x63 },
+	{  0x1, 0x80 },
+	{  0x2, 0xdf },
+	{  0x3, 0x40 },
+	{  0x4, 0xc2 },
+	{  0x5, 0x5c },
+	{  0x6, 0x00 },
+	{  0x7, 0xff },
+	{  0x8, 0x60 },
+	{  0x9, 0x60 },
+	{  0xa, 0x60 },
+	{  0xb, 0x00 },
+	{  0xc, 0x00 },
+	{  0xd, 0x00 },
+	{  0xe, 0x00 },
+	{  0xf, 0x40 },
+	{ 0x10, 0x80 },
+	{ 0x11, 0x77 },
+	{ 0x12, 0x6a },
+	{ 0x13, 0x69 },
+	{ 0x14, 0x6a },
+	{ 0x15, 0x69 },
+	{ 0x16, 0x00 },
+	{ 0x17, 0x00 },
+	{ 0x18, 0x00 },
+	{ 0x19, 0x00 },
+	{ 0x1a, 0x00 },
+	{ 0x1b, 0x00 },
+	{ 0x1c, 0x00 },
+	{ 0x1d, 0x00 },
+	{ 0x1e, 0x00 },
+	{ 0x1f, 0x00 },
+	{ 0x20, 0x00 },
+	{ 0x21, 0x00 },
+	{ 0x22, 0x00 },
+	{ 0x23, 0x00 },
+	{ 0x24, 0x00 },
+	{ 0x25, 0x00 },
+	{ 0x26, 0x00 },
+	{ 0x27, 0x2a },
+	{ 0x28, 0xc0 },
+	{ 0x29, 0xf3 },
+	{ 0x2a, 0x33 },
+	{ 0x2b, 0x00 },
+	{ 0x2c, 0x0c },
+	{ 0x31, 0x00 },
+	{ 0x36, 0x00 },
+	{ 0x37, 0x00 },
+	{ 0x38, 0x00 },
+	{ 0x39, 0x01 },
+	{ 0x3a, 0xee },
+	{ 0x3b, 0xff },
+	{ 0x3c, 0x7e },
+	{ 0x3d, 0xc0 },
+	{ 0x3e, 0x26 },
+	{ 0x3f, 0x00 },
+	{ 0x48, 0x00 },
+	{ 0x49, 0x00 },
+	{ 0x4a, 0x00 },
+	{ 0x4b, 0x04 },
+	{ 0x4c, 0x00 },
+};
+
+static const struct regmap_range sta350_write_regs_range[] = {
+	regmap_reg_range(STA350_CONFA,  STA350_AUTO2),
+	regmap_reg_range(STA350_C1CFG,  STA350_FDRC2),
+	regmap_reg_range(STA350_EQCFG,  STA350_EVOLRES),
+	regmap_reg_range(STA350_NSHAPE, STA350_MISC2),
+};
+
+static const struct regmap_range sta350_read_regs_range[] = {
+	regmap_reg_range(STA350_CONFA,  STA350_AUTO2),
+	regmap_reg_range(STA350_C1CFG,  STA350_STATUS),
+	regmap_reg_range(STA350_EQCFG,  STA350_EVOLRES),
+	regmap_reg_range(STA350_NSHAPE, STA350_MISC2),
+};
+
+static const struct regmap_range sta350_volatile_regs_range[] = {
+	regmap_reg_range(STA350_CFADDR2, STA350_CFUD),
+	regmap_reg_range(STA350_STATUS,  STA350_STATUS),
+};
+
+static const struct regmap_access_table sta350_write_regs = {
+	.yes_ranges =	sta350_write_regs_range,
+	.n_yes_ranges =	ARRAY_SIZE(sta350_write_regs_range),
+};
+
+static const struct regmap_access_table sta350_read_regs = {
+	.yes_ranges =	sta350_read_regs_range,
+	.n_yes_ranges =	ARRAY_SIZE(sta350_read_regs_range),
+};
+
+static const struct regmap_access_table sta350_volatile_regs = {
+	.yes_ranges =	sta350_volatile_regs_range,
+	.n_yes_ranges =	ARRAY_SIZE(sta350_volatile_regs_range),
+};
+
+/* regulator power supply names */
+static const char * const sta350_supply_names[] = {
+	"vdd-dig",	/* digital supply, 3.3V */
+	"vdd-pll",	/* pll supply, 3.3V */
+	"vcc"		/* power amp supply, 5V - 26V */
+};
+
+/* codec private data */
+struct sta350_priv {
+	struct regmap *regmap;
+	struct regulator_bulk_data supplies[ARRAY_SIZE(sta350_supply_names)];
+	struct sta350_platform_data *pdata;
+
+	unsigned int mclk;
+	unsigned int format;
+
+	u32 coef_shadow[STA350_COEF_COUNT];
+	int shutdown;
+
+	struct gpio_desc *gpiod_nreset;
+	struct gpio_desc *gpiod_power_down;
+
+	struct mutex coeff_lock;
+};
+
+static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
+static const DECLARE_TLV_DB_SCALE(tone_tlv, -1200, 200, 0);
+
+static const char * const sta350_drc_ac[] = {
+	"Anti-Clipping", "Dynamic Range Compression"
+};
+static const char * const sta350_auto_gc_mode[] = {
+	"User", "AC no clipping", "AC limited clipping (10%)",
+	"DRC nighttime listening mode"
+};
+static const char * const sta350_auto_xo_mode[] = {
+	"User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz",
+	"200Hz", "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz",
+	"340Hz", "360Hz"
+};
+static const char * const sta350_binary_output[] = {
+	"FFX 3-state output - normal operation", "Binary output"
+};
+static const char * const sta350_limiter_select[] = {
+	"Limiter Disabled", "Limiter #1", "Limiter #2"
+};
+static const char * const sta350_limiter_attack_rate[] = {
+	"3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024",
+	"0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752",
+	"0.0645", "0.0564", "0.0501", "0.0451"
+};
+static const char * const sta350_limiter_release_rate[] = {
+	"0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",
+	"0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",
+	"0.0134", "0.0117", "0.0110", "0.0104"
+};
+static const char * const sta350_noise_shaper_type[] = {
+	"Third order", "Fourth order"
+};
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_ac_attack_tlv,
+	0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
+	8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
+);
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_ac_release_tlv,
+	0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
+	1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
+	2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
+	3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
+	8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
+);
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_drc_attack_tlv,
+	0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
+	8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
+	14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
+);
+
+static DECLARE_TLV_DB_RANGE(sta350_limiter_drc_release_tlv,
+	0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
+	1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
+	3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
+	5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
+	13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
+);
+
+static SOC_ENUM_SINGLE_DECL(sta350_drc_ac_enum,
+			    STA350_CONFD, STA350_CONFD_DRC_SHIFT,
+			    sta350_drc_ac);
+static SOC_ENUM_SINGLE_DECL(sta350_noise_shaper_enum,
+			    STA350_CONFE, STA350_CONFE_NSBW_SHIFT,
+			    sta350_noise_shaper_type);
+static SOC_ENUM_SINGLE_DECL(sta350_auto_gc_enum,
+			    STA350_AUTO1, STA350_AUTO1_AMGC_SHIFT,
+			    sta350_auto_gc_mode);
+static SOC_ENUM_SINGLE_DECL(sta350_auto_xo_enum,
+			    STA350_AUTO2, STA350_AUTO2_XO_SHIFT,
+			    sta350_auto_xo_mode);
+static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch1_enum,
+			    STA350_C1CFG, STA350_CxCFG_BO_SHIFT,
+			    sta350_binary_output);
+static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch2_enum,
+			    STA350_C2CFG, STA350_CxCFG_BO_SHIFT,
+			    sta350_binary_output);
+static SOC_ENUM_SINGLE_DECL(sta350_binary_output_ch3_enum,
+			    STA350_C3CFG, STA350_CxCFG_BO_SHIFT,
+			    sta350_binary_output);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch1_enum,
+			    STA350_C1CFG, STA350_CxCFG_LS_SHIFT,
+			    sta350_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch2_enum,
+			    STA350_C2CFG, STA350_CxCFG_LS_SHIFT,
+			    sta350_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter_ch3_enum,
+			    STA350_C3CFG, STA350_CxCFG_LS_SHIFT,
+			    sta350_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter1_attack_rate_enum,
+			    STA350_L1AR, STA350_LxA_SHIFT,
+			    sta350_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter2_attack_rate_enum,
+			    STA350_L2AR, STA350_LxA_SHIFT,
+			    sta350_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter1_release_rate_enum,
+			    STA350_L1AR, STA350_LxR_SHIFT,
+			    sta350_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta350_limiter2_release_rate_enum,
+			    STA350_L2AR, STA350_LxR_SHIFT,
+			    sta350_limiter_release_rate);
+
+/*
+ * byte array controls for setting biquad, mixer, scaling coefficients;
+ * for biquads all five coefficients need to be set in one go,
+ * mixer and pre/postscale coefs can be set individually;
+ * each coef is 24bit, the bytes are ordered in the same way
+ * as given in the STA350 data sheet (big endian; b1, b2, a1, a2, b0)
+ */
+
+static int sta350_coefficient_info(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *uinfo)
+{
+	int numcoef = kcontrol->private_value >> 16;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+	uinfo->count = 3 * numcoef;
+	return 0;
+}
+
+static int sta350_coefficient_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	int numcoef = kcontrol->private_value >> 16;
+	int index = kcontrol->private_value & 0xffff;
+	unsigned int cfud, val;
+	int i, ret = 0;
+
+	mutex_lock(&sta350->coeff_lock);
+
+	/* preserve reserved bits in STA350_CFUD */
+	regmap_read(sta350->regmap, STA350_CFUD, &cfud);
+	cfud &= 0xf0;
+	/*
+	 * chip documentation does not say if the bits are self clearing,
+	 * so do it explicitly
+	 */
+	regmap_write(sta350->regmap, STA350_CFUD, cfud);
+
+	regmap_write(sta350->regmap, STA350_CFADDR2, index);
+	if (numcoef == 1) {
+		regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x04);
+	} else if (numcoef == 5) {
+		regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x08);
+	} else {
+		ret = -EINVAL;
+		goto exit_unlock;
+	}
+
+	for (i = 0; i < 3 * numcoef; i++) {
+		regmap_read(sta350->regmap, STA350_B1CF1 + i, &val);
+		ucontrol->value.bytes.data[i] = val;
+	}
+
+exit_unlock:
+	mutex_unlock(&sta350->coeff_lock);
+
+	return ret;
+}
+
+static int sta350_coefficient_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	int numcoef = kcontrol->private_value >> 16;
+	int index = kcontrol->private_value & 0xffff;
+	unsigned int cfud;
+	int i;
+
+	/* preserve reserved bits in STA350_CFUD */
+	regmap_read(sta350->regmap, STA350_CFUD, &cfud);
+	cfud &= 0xf0;
+	/*
+	 * chip documentation does not say if the bits are self clearing,
+	 * so do it explicitly
+	 */
+	regmap_write(sta350->regmap, STA350_CFUD, cfud);
+
+	regmap_write(sta350->regmap, STA350_CFADDR2, index);
+	for (i = 0; i < numcoef && (index + i < STA350_COEF_COUNT); i++)
+		sta350->coef_shadow[index + i] =
+			  (ucontrol->value.bytes.data[3 * i] << 16)
+			| (ucontrol->value.bytes.data[3 * i + 1] << 8)
+			| (ucontrol->value.bytes.data[3 * i + 2]);
+	for (i = 0; i < 3 * numcoef; i++)
+		regmap_write(sta350->regmap, STA350_B1CF1 + i,
+			     ucontrol->value.bytes.data[i]);
+	if (numcoef == 1)
+		regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01);
+	else if (numcoef == 5)
+		regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x02);
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sta350_sync_coef_shadow(struct snd_soc_codec *codec)
+{
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	unsigned int cfud;
+	int i;
+
+	/* preserve reserved bits in STA350_CFUD */
+	regmap_read(sta350->regmap, STA350_CFUD, &cfud);
+	cfud &= 0xf0;
+
+	for (i = 0; i < STA350_COEF_COUNT; i++) {
+		regmap_write(sta350->regmap, STA350_CFADDR2, i);
+		regmap_write(sta350->regmap, STA350_B1CF1,
+			     (sta350->coef_shadow[i] >> 16) & 0xff);
+		regmap_write(sta350->regmap, STA350_B1CF2,
+			     (sta350->coef_shadow[i] >> 8) & 0xff);
+		regmap_write(sta350->regmap, STA350_B1CF3,
+			     (sta350->coef_shadow[i]) & 0xff);
+		/*
+		 * chip documentation does not say if the bits are
+		 * self-clearing, so do it explicitly
+		 */
+		regmap_write(sta350->regmap, STA350_CFUD, cfud);
+		regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01);
+	}
+	return 0;
+}
+
+static int sta350_cache_sync(struct snd_soc_codec *codec)
+{
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	unsigned int mute;
+	int rc;
+
+	/* mute during register sync */
+	regmap_read(sta350->regmap, STA350_CFUD, &mute);
+	regmap_write(sta350->regmap, STA350_MMUTE, mute | STA350_MMUTE_MMUTE);
+	sta350_sync_coef_shadow(codec);
+	rc = regcache_sync(sta350->regmap);
+	regmap_write(sta350->regmap, STA350_MMUTE, mute);
+	return rc;
+}
+
+#define SINGLE_COEF(xname, index) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = sta350_coefficient_info, \
+	.get = sta350_coefficient_get,\
+	.put = sta350_coefficient_put, \
+	.private_value = index | (1 << 16) }
+
+#define BIQUAD_COEFS(xname, index) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = sta350_coefficient_info, \
+	.get = sta350_coefficient_get,\
+	.put = sta350_coefficient_put, \
+	.private_value = index | (5 << 16) }
+
+static const struct snd_kcontrol_new sta350_snd_controls[] = {
+SOC_SINGLE_TLV("Master Volume", STA350_MVOL, 0, 0xff, 1, mvol_tlv),
+/* VOL */
+SOC_SINGLE_TLV("Ch1 Volume", STA350_C1VOL, 0, 0xff, 1, chvol_tlv),
+SOC_SINGLE_TLV("Ch2 Volume", STA350_C2VOL, 0, 0xff, 1, chvol_tlv),
+SOC_SINGLE_TLV("Ch3 Volume", STA350_C3VOL, 0, 0xff, 1, chvol_tlv),
+/* CONFD */
+SOC_SINGLE("High Pass Filter Bypass Switch",
+	   STA350_CONFD, STA350_CONFD_HPB_SHIFT, 1, 1),
+SOC_SINGLE("De-emphasis Filter Switch",
+	   STA350_CONFD, STA350_CONFD_DEMP_SHIFT, 1, 0),
+SOC_SINGLE("DSP Bypass Switch",
+	   STA350_CONFD, STA350_CONFD_DSPB_SHIFT, 1, 0),
+SOC_SINGLE("Post-scale Link Switch",
+	   STA350_CONFD, STA350_CONFD_PSL_SHIFT, 1, 0),
+SOC_SINGLE("Biquad Coefficient Link Switch",
+	   STA350_CONFD, STA350_CONFD_BQL_SHIFT, 1, 0),
+SOC_ENUM("Compressor/Limiter Switch", sta350_drc_ac_enum),
+SOC_ENUM("Noise Shaper Bandwidth", sta350_noise_shaper_enum),
+SOC_SINGLE("Zero-detect Mute Enable Switch",
+	   STA350_CONFD, STA350_CONFD_ZDE_SHIFT, 1, 0),
+SOC_SINGLE("Submix Mode Switch",
+	   STA350_CONFD, STA350_CONFD_SME_SHIFT, 1, 0),
+/* CONFE */
+SOC_SINGLE("Zero Cross Switch", STA350_CONFE, STA350_CONFE_ZCE_SHIFT, 1, 0),
+SOC_SINGLE("Soft Ramp Switch", STA350_CONFE, STA350_CONFE_SVE_SHIFT, 1, 0),
+/* MUTE */
+SOC_SINGLE("Master Switch", STA350_MMUTE, STA350_MMUTE_MMUTE_SHIFT, 1, 1),
+SOC_SINGLE("Ch1 Switch", STA350_MMUTE, STA350_MMUTE_C1M_SHIFT, 1, 1),
+SOC_SINGLE("Ch2 Switch", STA350_MMUTE, STA350_MMUTE_C2M_SHIFT, 1, 1),
+SOC_SINGLE("Ch3 Switch", STA350_MMUTE, STA350_MMUTE_C3M_SHIFT, 1, 1),
+/* AUTOx */
+SOC_ENUM("Automode GC", sta350_auto_gc_enum),
+SOC_ENUM("Automode XO", sta350_auto_xo_enum),
+/* CxCFG */
+SOC_SINGLE("Ch1 Tone Control Bypass Switch",
+	   STA350_C1CFG, STA350_CxCFG_TCB_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 Tone Control Bypass Switch",
+	   STA350_C2CFG, STA350_CxCFG_TCB_SHIFT, 1, 0),
+SOC_SINGLE("Ch1 EQ Bypass Switch",
+	   STA350_C1CFG, STA350_CxCFG_EQBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 EQ Bypass Switch",
+	   STA350_C2CFG, STA350_CxCFG_EQBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch1 Master Volume Bypass Switch",
+	   STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 Master Volume Bypass Switch",
+	   STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch3 Master Volume Bypass Switch",
+	   STA350_C1CFG, STA350_CxCFG_VBP_SHIFT, 1, 0),
+SOC_ENUM("Ch1 Binary Output Select", sta350_binary_output_ch1_enum),
+SOC_ENUM("Ch2 Binary Output Select", sta350_binary_output_ch2_enum),
+SOC_ENUM("Ch3 Binary Output Select", sta350_binary_output_ch3_enum),
+SOC_ENUM("Ch1 Limiter Select", sta350_limiter_ch1_enum),
+SOC_ENUM("Ch2 Limiter Select", sta350_limiter_ch2_enum),
+SOC_ENUM("Ch3 Limiter Select", sta350_limiter_ch3_enum),
+/* TONE */
+SOC_SINGLE_RANGE_TLV("Bass Tone Control Volume",
+		     STA350_TONE, STA350_TONE_BTC_SHIFT, 1, 13, 0, tone_tlv),
+SOC_SINGLE_RANGE_TLV("Treble Tone Control Volume",
+		     STA350_TONE, STA350_TONE_TTC_SHIFT, 1, 13, 0, tone_tlv),
+SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta350_limiter1_attack_rate_enum),
+SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta350_limiter2_attack_rate_enum),
+SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta350_limiter1_release_rate_enum),
+SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta350_limiter2_release_rate_enum),
+
+/*
+ * depending on mode, the attack/release thresholds have
+ * two different enum definitions; provide both
+ */
+SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)",
+	       STA350_L1ATRT, STA350_LxA_SHIFT,
+	       16, 0, sta350_limiter_ac_attack_tlv),
+SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)",
+	       STA350_L2ATRT, STA350_LxA_SHIFT,
+	       16, 0, sta350_limiter_ac_attack_tlv),
+SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)",
+	       STA350_L1ATRT, STA350_LxR_SHIFT,
+	       16, 0, sta350_limiter_ac_release_tlv),
+SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)",
+	       STA350_L2ATRT, STA350_LxR_SHIFT,
+	       16, 0, sta350_limiter_ac_release_tlv),
+SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)",
+	       STA350_L1ATRT, STA350_LxA_SHIFT,
+	       16, 0, sta350_limiter_drc_attack_tlv),
+SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)",
+	       STA350_L2ATRT, STA350_LxA_SHIFT,
+	       16, 0, sta350_limiter_drc_attack_tlv),
+SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)",
+	       STA350_L1ATRT, STA350_LxR_SHIFT,
+	       16, 0, sta350_limiter_drc_release_tlv),
+SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)",
+	       STA350_L2ATRT, STA350_LxR_SHIFT,
+	       16, 0, sta350_limiter_drc_release_tlv),
+
+BIQUAD_COEFS("Ch1 - Biquad 1", 0),
+BIQUAD_COEFS("Ch1 - Biquad 2", 5),
+BIQUAD_COEFS("Ch1 - Biquad 3", 10),
+BIQUAD_COEFS("Ch1 - Biquad 4", 15),
+BIQUAD_COEFS("Ch2 - Biquad 1", 20),
+BIQUAD_COEFS("Ch2 - Biquad 2", 25),
+BIQUAD_COEFS("Ch2 - Biquad 3", 30),
+BIQUAD_COEFS("Ch2 - Biquad 4", 35),
+BIQUAD_COEFS("High-pass", 40),
+BIQUAD_COEFS("Low-pass", 45),
+SINGLE_COEF("Ch1 - Prescale", 50),
+SINGLE_COEF("Ch2 - Prescale", 51),
+SINGLE_COEF("Ch1 - Postscale", 52),
+SINGLE_COEF("Ch2 - Postscale", 53),
+SINGLE_COEF("Ch3 - Postscale", 54),
+SINGLE_COEF("Thermal warning - Postscale", 55),
+SINGLE_COEF("Ch1 - Mix 1", 56),
+SINGLE_COEF("Ch1 - Mix 2", 57),
+SINGLE_COEF("Ch2 - Mix 1", 58),
+SINGLE_COEF("Ch2 - Mix 2", 59),
+SINGLE_COEF("Ch3 - Mix 1", 60),
+SINGLE_COEF("Ch3 - Mix 2", 61),
+};
+
+static const struct snd_soc_dapm_widget sta350_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_OUTPUT("LEFT"),
+SND_SOC_DAPM_OUTPUT("RIGHT"),
+SND_SOC_DAPM_OUTPUT("SUB"),
+};
+
+static const struct snd_soc_dapm_route sta350_dapm_routes[] = {
+	{ "LEFT", NULL, "DAC" },
+	{ "RIGHT", NULL, "DAC" },
+	{ "SUB", NULL, "DAC" },
+	{ "DAC", NULL, "Playback" },
+};
+
+/* MCLK interpolation ratio per fs */
+static struct {
+	int fs;
+	int ir;
+} interpolation_ratios[] = {
+	{ 32000, 0 },
+	{ 44100, 0 },
+	{ 48000, 0 },
+	{ 88200, 1 },
+	{ 96000, 1 },
+	{ 176400, 2 },
+	{ 192000, 2 },
+};
+
+/* MCLK to fs clock ratios */
+static int mcs_ratio_table[3][6] = {
+	{ 768, 512, 384, 256, 128, 576 },
+	{ 384, 256, 192, 128,  64,   0 },
+	{ 192, 128,  96,  64,  32,   0 },
+};
+
+/**
+ * sta350_set_dai_sysclk - configure MCLK
+ * @codec_dai: the codec DAI
+ * @clk_id: the clock ID (ignored)
+ * @freq: the MCLK input frequency
+ * @dir: the clock direction (ignored)
+ *
+ * The value of MCLK is used to determine which sample rates are supported
+ * by the STA350, based on the mcs_ratio_table.
+ *
+ * This function must be called by the machine driver's 'startup' function,
+ * otherwise the list of supported sample rates will not be available in
+ * time for ALSA.
+ */
+static int sta350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+				 int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "mclk=%u\n", freq);
+	sta350->mclk = freq;
+
+	return 0;
+}
+
+/**
+ * sta350_set_dai_fmt - configure the codec for the selected audio format
+ * @codec_dai: the codec DAI
+ * @fmt: a SND_SOC_DAIFMT_x value indicating the data format
+ *
+ * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
+ * codec accordingly.
+ */
+static int sta350_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	unsigned int confb = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_RIGHT_J:
+	case SND_SOC_DAIFMT_LEFT_J:
+		sta350->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		confb |= STA350_CONFB_C2IM;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		confb |= STA350_CONFB_C1IM;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(sta350->regmap, STA350_CONFB,
+				  STA350_CONFB_C1IM | STA350_CONFB_C2IM, confb);
+}
+
+/**
+ * sta350_hw_params - program the STA350 with the given hardware parameters.
+ * @substream: the audio stream
+ * @params: the hardware parameters to set
+ * @dai: the SOC DAI (ignored)
+ *
+ * This function programs the hardware with the values provided.
+ * Specifically, the sample rate and the data format.
+ */
+static int sta350_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	int i, mcs = -EINVAL, ir = -EINVAL;
+	unsigned int confa, confb;
+	unsigned int rate, ratio;
+	int ret;
+
+	if (!sta350->mclk) {
+		dev_err(codec->dev,
+			"sta350->mclk is unset. Unable to determine ratio\n");
+		return -EIO;
+	}
+
+	rate = params_rate(params);
+	ratio = sta350->mclk / rate;
+	dev_dbg(codec->dev, "rate: %u, ratio: %u\n", rate, ratio);
+
+	for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
+		if (interpolation_ratios[i].fs == rate) {
+			ir = interpolation_ratios[i].ir;
+			break;
+		}
+	}
+
+	if (ir < 0) {
+		dev_err(codec->dev, "Unsupported samplerate: %u\n", rate);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 6; i++) {
+		if (mcs_ratio_table[ir][i] == ratio) {
+			mcs = i;
+			break;
+		}
+	}
+
+	if (mcs < 0) {
+		dev_err(codec->dev, "Unresolvable ratio: %u\n", ratio);
+		return -EINVAL;
+	}
+
+	confa = (ir << STA350_CONFA_IR_SHIFT) |
+		(mcs << STA350_CONFA_MCS_SHIFT);
+	confb = 0;
+
+	switch (params_width(params)) {
+	case 24:
+		dev_dbg(codec->dev, "24bit\n");
+		/* fall through */
+	case 32:
+		dev_dbg(codec->dev, "24bit or 32bit\n");
+		switch (sta350->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x0;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0x1;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0x2;
+			break;
+		}
+
+		break;
+	case 20:
+		dev_dbg(codec->dev, "20bit\n");
+		switch (sta350->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x4;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0x5;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0x6;
+			break;
+		}
+
+		break;
+	case 18:
+		dev_dbg(codec->dev, "18bit\n");
+		switch (sta350->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x8;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0x9;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0xa;
+			break;
+		}
+
+		break;
+	case 16:
+		dev_dbg(codec->dev, "16bit\n");
+		switch (sta350->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x0;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0xd;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0xe;
+			break;
+		}
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_update_bits(sta350->regmap, STA350_CONFA,
+				 STA350_CONFA_MCS_MASK | STA350_CONFA_IR_MASK,
+				 confa);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_update_bits(sta350->regmap, STA350_CONFB,
+				 STA350_CONFB_SAI_MASK | STA350_CONFB_SAIFB,
+				 confb);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int sta350_startup_sequence(struct sta350_priv *sta350)
+{
+	if (sta350->gpiod_power_down)
+		gpiod_set_value(sta350->gpiod_power_down, 1);
+
+	if (sta350->gpiod_nreset) {
+		gpiod_set_value(sta350->gpiod_nreset, 0);
+		mdelay(1);
+		gpiod_set_value(sta350->gpiod_nreset, 1);
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+/**
+ * sta350_set_bias_level - DAPM callback
+ * @codec: the codec device
+ * @level: DAPM power level
+ *
+ * This is called by ALSA to put the codec into low power mode
+ * or to wake it up.  If the codec is powered off completely
+ * all registers must be restored after power on.
+ */
+static int sta350_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	dev_dbg(codec->dev, "level = %d\n", level);
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		/* Full power on */
+		regmap_update_bits(sta350->regmap, STA350_CONFF,
+				   STA350_CONFF_PWDN | STA350_CONFF_EAPD,
+				   STA350_CONFF_PWDN | STA350_CONFF_EAPD);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = regulator_bulk_enable(
+				ARRAY_SIZE(sta350->supplies),
+				sta350->supplies);
+			if (ret < 0) {
+				dev_err(codec->dev,
+					"Failed to enable supplies: %d\n",
+					ret);
+				return ret;
+			}
+			sta350_startup_sequence(sta350);
+			sta350_cache_sync(codec);
+		}
+
+		/* Power down */
+		regmap_update_bits(sta350->regmap, STA350_CONFF,
+				   STA350_CONFF_PWDN | STA350_CONFF_EAPD,
+				   0);
+
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		/* The chip runs through the power down sequence for us */
+		regmap_update_bits(sta350->regmap, STA350_CONFF,
+				   STA350_CONFF_PWDN | STA350_CONFF_EAPD, 0);
+
+		/* power down: low */
+		if (sta350->gpiod_power_down)
+			gpiod_set_value(sta350->gpiod_power_down, 0);
+
+		if (sta350->gpiod_nreset)
+			gpiod_set_value(sta350->gpiod_nreset, 0);
+
+		regulator_bulk_disable(ARRAY_SIZE(sta350->supplies),
+				       sta350->supplies);
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+static const struct snd_soc_dai_ops sta350_dai_ops = {
+	.hw_params	= sta350_hw_params,
+	.set_sysclk	= sta350_set_dai_sysclk,
+	.set_fmt	= sta350_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver sta350_dai = {
+	.name = "sta350-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = STA350_RATES,
+		.formats = STA350_FORMATS,
+	},
+	.ops = &sta350_dai_ops,
+};
+
+#ifdef CONFIG_PM
+static int sta350_suspend(struct snd_soc_codec *codec)
+{
+	sta350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int sta350_resume(struct snd_soc_codec *codec)
+{
+	sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+#else
+#define sta350_suspend NULL
+#define sta350_resume NULL
+#endif
+
+static int sta350_probe(struct snd_soc_codec *codec)
+{
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+	struct sta350_platform_data *pdata = sta350->pdata;
+	int i, ret = 0, thermal = 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(sta350->supplies),
+				    sta350->supplies);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+		return ret;
+	}
+
+	ret = sta350_startup_sequence(sta350);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to startup device\n");
+		return ret;
+	}
+
+	/* CONFA */
+	if (!pdata->thermal_warning_recovery)
+		thermal |= STA350_CONFA_TWAB;
+	if (!pdata->thermal_warning_adjustment)
+		thermal |= STA350_CONFA_TWRB;
+	if (!pdata->fault_detect_recovery)
+		thermal |= STA350_CONFA_FDRB;
+	regmap_update_bits(sta350->regmap, STA350_CONFA,
+			   STA350_CONFA_TWAB | STA350_CONFA_TWRB |
+			   STA350_CONFA_FDRB,
+			   thermal);
+
+	/* CONFC */
+	regmap_update_bits(sta350->regmap, STA350_CONFC,
+			   STA350_CONFC_OM_MASK,
+			   pdata->ffx_power_output_mode
+				<< STA350_CONFC_OM_SHIFT);
+	regmap_update_bits(sta350->regmap, STA350_CONFC,
+			   STA350_CONFC_CSZ_MASK,
+			   pdata->drop_compensation_ns
+				<< STA350_CONFC_CSZ_SHIFT);
+	regmap_update_bits(sta350->regmap,
+			   STA350_CONFC,
+			   STA350_CONFC_OCRB,
+			   pdata->oc_warning_adjustment ?
+				STA350_CONFC_OCRB : 0);
+
+	/* CONFE */
+	regmap_update_bits(sta350->regmap, STA350_CONFE,
+			   STA350_CONFE_MPCV,
+			   pdata->max_power_use_mpcc ?
+				STA350_CONFE_MPCV : 0);
+	regmap_update_bits(sta350->regmap, STA350_CONFE,
+			   STA350_CONFE_MPC,
+			   pdata->max_power_correction ?
+				STA350_CONFE_MPC : 0);
+	regmap_update_bits(sta350->regmap, STA350_CONFE,
+			   STA350_CONFE_AME,
+			   pdata->am_reduction_mode ?
+				STA350_CONFE_AME : 0);
+	regmap_update_bits(sta350->regmap, STA350_CONFE,
+			   STA350_CONFE_PWMS,
+			   pdata->odd_pwm_speed_mode ?
+				STA350_CONFE_PWMS : 0);
+	regmap_update_bits(sta350->regmap, STA350_CONFE,
+			   STA350_CONFE_DCCV,
+			   pdata->distortion_compensation ?
+				STA350_CONFE_DCCV : 0);
+	/*  CONFF */
+	regmap_update_bits(sta350->regmap, STA350_CONFF,
+			   STA350_CONFF_IDE,
+			   pdata->invalid_input_detect_mute ?
+				STA350_CONFF_IDE : 0);
+	regmap_update_bits(sta350->regmap, STA350_CONFF,
+			   STA350_CONFF_OCFG_MASK,
+			   pdata->output_conf
+				<< STA350_CONFF_OCFG_SHIFT);
+
+	/* channel to output mapping */
+	regmap_update_bits(sta350->regmap, STA350_C1CFG,
+			   STA350_CxCFG_OM_MASK,
+			   pdata->ch1_output_mapping
+				<< STA350_CxCFG_OM_SHIFT);
+	regmap_update_bits(sta350->regmap, STA350_C2CFG,
+			   STA350_CxCFG_OM_MASK,
+			   pdata->ch2_output_mapping
+				<< STA350_CxCFG_OM_SHIFT);
+	regmap_update_bits(sta350->regmap, STA350_C3CFG,
+			   STA350_CxCFG_OM_MASK,
+			   pdata->ch3_output_mapping
+				<< STA350_CxCFG_OM_SHIFT);
+
+	/* initialize coefficient shadow RAM with reset values */
+	for (i = 4; i <= 49; i += 5)
+		sta350->coef_shadow[i] = 0x400000;
+	for (i = 50; i <= 54; i++)
+		sta350->coef_shadow[i] = 0x7fffff;
+	sta350->coef_shadow[55] = 0x5a9df7;
+	sta350->coef_shadow[56] = 0x7fffff;
+	sta350->coef_shadow[59] = 0x7fffff;
+	sta350->coef_shadow[60] = 0x400000;
+	sta350->coef_shadow[61] = 0x400000;
+
+	sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	/* Bias level configuration will have done an extra enable */
+	regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);
+
+	return 0;
+}
+
+static int sta350_remove(struct snd_soc_codec *codec)
+{
+	struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
+
+	sta350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);
+
+	return 0;
+}
+
+static const struct snd_soc_codec_driver sta350_codec = {
+	.probe =		sta350_probe,
+	.remove =		sta350_remove,
+	.suspend =		sta350_suspend,
+	.resume =		sta350_resume,
+	.set_bias_level =	sta350_set_bias_level,
+	.controls =		sta350_snd_controls,
+	.num_controls =		ARRAY_SIZE(sta350_snd_controls),
+	.dapm_widgets =		sta350_dapm_widgets,
+	.num_dapm_widgets =	ARRAY_SIZE(sta350_dapm_widgets),
+	.dapm_routes =		sta350_dapm_routes,
+	.num_dapm_routes =	ARRAY_SIZE(sta350_dapm_routes),
+};
+
+static const struct regmap_config sta350_regmap = {
+	.reg_bits =		8,
+	.val_bits =		8,
+	.max_register =		STA350_MISC2,
+	.reg_defaults =		sta350_regs,
+	.num_reg_defaults =	ARRAY_SIZE(sta350_regs),
+	.cache_type =		REGCACHE_RBTREE,
+	.wr_table =		&sta350_write_regs,
+	.rd_table =		&sta350_read_regs,
+	.volatile_table =	&sta350_volatile_regs,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id st350_dt_ids[] = {
+	{ .compatible = "st,sta350", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, st350_dt_ids);
+
+static const char * const sta350_ffx_modes[] = {
+	[STA350_FFX_PM_DROP_COMP]		= "drop-compensation",
+	[STA350_FFX_PM_TAPERED_COMP]		= "tapered-compensation",
+	[STA350_FFX_PM_FULL_POWER]		= "full-power-mode",
+	[STA350_FFX_PM_VARIABLE_DROP_COMP]	= "variable-drop-compensation",
+};
+
+static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350)
+{
+	struct device_node *np = dev->of_node;
+	struct sta350_platform_data *pdata;
+	const char *ffx_power_mode;
+	u16 tmp;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	of_property_read_u8(np, "st,output-conf",
+			    &pdata->output_conf);
+	of_property_read_u8(np, "st,ch1-output-mapping",
+			    &pdata->ch1_output_mapping);
+	of_property_read_u8(np, "st,ch2-output-mapping",
+			    &pdata->ch2_output_mapping);
+	of_property_read_u8(np, "st,ch3-output-mapping",
+			    &pdata->ch3_output_mapping);
+
+	if (of_get_property(np, "st,thermal-warning-recovery", NULL))
+		pdata->thermal_warning_recovery = 1;
+	if (of_get_property(np, "st,thermal-warning-adjustment", NULL))
+		pdata->thermal_warning_adjustment = 1;
+	if (of_get_property(np, "st,fault-detect-recovery", NULL))
+		pdata->fault_detect_recovery = 1;
+
+	pdata->ffx_power_output_mode = STA350_FFX_PM_VARIABLE_DROP_COMP;
+	if (!of_property_read_string(np, "st,ffx-power-output-mode",
+				     &ffx_power_mode)) {
+		int i, mode = -EINVAL;
+
+		for (i = 0; i < ARRAY_SIZE(sta350_ffx_modes); i++)
+			if (!strcasecmp(ffx_power_mode, sta350_ffx_modes[i]))
+				mode = i;
+
+		if (mode < 0)
+			dev_warn(dev, "Unsupported ffx output mode: %s\n",
+				 ffx_power_mode);
+		else
+			pdata->ffx_power_output_mode = mode;
+	}
+
+	tmp = 140;
+	of_property_read_u16(np, "st,drop-compensation-ns", &tmp);
+	pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20;
+
+	if (of_get_property(np, "st,overcurrent-warning-adjustment", NULL))
+		pdata->oc_warning_adjustment = 1;
+
+	/* CONFE */
+	if (of_get_property(np, "st,max-power-use-mpcc", NULL))
+		pdata->max_power_use_mpcc = 1;
+
+	if (of_get_property(np, "st,max-power-correction", NULL))
+		pdata->max_power_correction = 1;
+
+	if (of_get_property(np, "st,am-reduction-mode", NULL))
+		pdata->am_reduction_mode = 1;
+
+	if (of_get_property(np, "st,odd-pwm-speed-mode", NULL))
+		pdata->odd_pwm_speed_mode = 1;
+
+	if (of_get_property(np, "st,distortion-compensation", NULL))
+		pdata->distortion_compensation = 1;
+
+	/* CONFF */
+	if (of_get_property(np, "st,invalid-input-detect-mute", NULL))
+		pdata->invalid_input_detect_mute = 1;
+
+	sta350->pdata = pdata;
+
+	return 0;
+}
+#endif
+
+static int sta350_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct device *dev = &i2c->dev;
+	struct sta350_priv *sta350;
+	int ret, i;
+
+	sta350 = devm_kzalloc(dev, sizeof(struct sta350_priv), GFP_KERNEL);
+	if (!sta350)
+		return -ENOMEM;
+
+	mutex_init(&sta350->coeff_lock);
+	sta350->pdata = dev_get_platdata(dev);
+
+#ifdef CONFIG_OF
+	if (dev->of_node) {
+		ret = sta350_probe_dt(dev, sta350);
+		if (ret < 0)
+			return ret;
+	}
+#endif
+
+	/* GPIOs */
+	sta350->gpiod_nreset = devm_gpiod_get(dev, "reset");
+	if (IS_ERR(sta350->gpiod_nreset)) {
+		ret = PTR_ERR(sta350->gpiod_nreset);
+		if (ret != -ENOENT && ret != -ENOSYS)
+			return ret;
+
+		sta350->gpiod_nreset = NULL;
+	} else {
+		gpiod_direction_output(sta350->gpiod_nreset, 0);
+	}
+
+	sta350->gpiod_power_down = devm_gpiod_get(dev, "power-down");
+	if (IS_ERR(sta350->gpiod_power_down)) {
+		ret = PTR_ERR(sta350->gpiod_power_down);
+		if (ret != -ENOENT && ret != -ENOSYS)
+			return ret;
+
+		sta350->gpiod_power_down = NULL;
+	} else {
+		gpiod_direction_output(sta350->gpiod_power_down, 0);
+	}
+
+	/* regulators */
+	for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++)
+		sta350->supplies[i].supply = sta350_supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sta350->supplies),
+				      sta350->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to request supplies: %d\n", ret);
+		return ret;
+	}
+
+	sta350->regmap = devm_regmap_init_i2c(i2c, &sta350_regmap);
+	if (IS_ERR(sta350->regmap)) {
+		ret = PTR_ERR(sta350->regmap);
+		dev_err(dev, "Failed to init regmap: %d\n", ret);
+		return ret;
+	}
+
+	i2c_set_clientdata(i2c, sta350);
+
+	ret = snd_soc_register_codec(dev, &sta350_codec, &sta350_dai, 1);
+	if (ret < 0)
+		dev_err(dev, "Failed to register codec (%d)\n", ret);
+
+	return ret;
+}
+
+static int sta350_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static const struct i2c_device_id sta350_i2c_id[] = {
+	{ "sta350", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sta350_i2c_id);
+
+static struct i2c_driver sta350_i2c_driver = {
+	.driver = {
+		.name = "sta350",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(st350_dt_ids),
+	},
+	.probe =    sta350_i2c_probe,
+	.remove =   sta350_i2c_remove,
+	.id_table = sta350_i2c_id,
+};
+
+module_i2c_driver(sta350_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC STA350 driver");
+MODULE_AUTHOR("Sven Brandau <info@brandau.biz>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sta350.h b/sound/soc/codecs/sta350.h
new file mode 100644
index 000000000000..c3248f0fad2c
--- /dev/null
+++ b/sound/soc/codecs/sta350.h
@@ -0,0 +1,228 @@
+/*
+ * Codec driver for ST STA350 2.1-channel high-efficiency digital audio system
+ *
+ * Copyright: 2011 Raumfeld GmbH
+ * Author: Sven Brandau <info@brandau.biz>
+ *
+ * based on code from:
+ *      Raumfeld GmbH
+ *        Johannes Stezenbach <js@sig21.net>
+ *	Wolfson Microelectronics PLC.
+ *	  Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASOC_STA_350_H
+#define _ASOC_STA_350_H
+
+/* STA50 register addresses */
+
+#define STA350_REGISTER_COUNT	0x4D
+#define STA350_COEF_COUNT 62
+
+#define STA350_CONFA	0x00
+#define STA350_CONFB    0x01
+#define STA350_CONFC    0x02
+#define STA350_CONFD    0x03
+#define STA350_CONFE    0x04
+#define STA350_CONFF    0x05
+#define STA350_MMUTE    0x06
+#define STA350_MVOL     0x07
+#define STA350_C1VOL    0x08
+#define STA350_C2VOL    0x09
+#define STA350_C3VOL    0x0a
+#define STA350_AUTO1    0x0b
+#define STA350_AUTO2    0x0c
+#define STA350_AUTO3    0x0d
+#define STA350_C1CFG    0x0e
+#define STA350_C2CFG    0x0f
+#define STA350_C3CFG    0x10
+#define STA350_TONE     0x11
+#define STA350_L1AR     0x12
+#define STA350_L1ATRT   0x13
+#define STA350_L2AR     0x14
+#define STA350_L2ATRT   0x15
+#define STA350_CFADDR2  0x16
+#define STA350_B1CF1    0x17
+#define STA350_B1CF2    0x18
+#define STA350_B1CF3    0x19
+#define STA350_B2CF1    0x1a
+#define STA350_B2CF2    0x1b
+#define STA350_B2CF3    0x1c
+#define STA350_A1CF1    0x1d
+#define STA350_A1CF2    0x1e
+#define STA350_A1CF3    0x1f
+#define STA350_A2CF1    0x20
+#define STA350_A2CF2    0x21
+#define STA350_A2CF3    0x22
+#define STA350_B0CF1    0x23
+#define STA350_B0CF2    0x24
+#define STA350_B0CF3    0x25
+#define STA350_CFUD     0x26
+#define STA350_MPCC1    0x27
+#define STA350_MPCC2    0x28
+#define STA350_DCC1     0x29
+#define STA350_DCC2     0x2a
+#define STA350_FDRC1    0x2b
+#define STA350_FDRC2    0x2c
+#define STA350_STATUS   0x2d
+/* reserved: 0x2d - 0x30 */
+#define STA350_EQCFG    0x31
+#define STA350_EATH1    0x32
+#define STA350_ERTH1    0x33
+#define STA350_EATH2    0x34
+#define STA350_ERTH2    0x35
+#define STA350_CONFX    0x36
+#define STA350_SVCA     0x37
+#define STA350_SVCB     0x38
+#define STA350_RMS0A    0x39
+#define STA350_RMS0B    0x3a
+#define STA350_RMS0C    0x3b
+#define STA350_RMS1A    0x3c
+#define STA350_RMS1B    0x3d
+#define STA350_RMS1C    0x3e
+#define STA350_EVOLRES  0x3f
+/* reserved: 0x40 - 0x47 */
+#define STA350_NSHAPE   0x48
+#define STA350_CTXB4B1  0x49
+#define STA350_CTXB7B5  0x4a
+#define STA350_MISC1    0x4b
+#define STA350_MISC2    0x4c
+
+/* 0x00 CONFA */
+#define STA350_CONFA_MCS_MASK	0x03
+#define STA350_CONFA_MCS_SHIFT	0
+#define STA350_CONFA_IR_MASK	0x18
+#define STA350_CONFA_IR_SHIFT	3
+#define STA350_CONFA_TWRB	BIT(5)
+#define STA350_CONFA_TWAB	BIT(6)
+#define STA350_CONFA_FDRB	BIT(7)
+
+/* 0x01 CONFB */
+#define STA350_CONFB_SAI_MASK	0x0f
+#define STA350_CONFB_SAI_SHIFT	0
+#define STA350_CONFB_SAIFB	BIT(4)
+#define STA350_CONFB_DSCKE	BIT(5)
+#define STA350_CONFB_C1IM	BIT(6)
+#define STA350_CONFB_C2IM	BIT(7)
+
+/* 0x02 CONFC */
+#define STA350_CONFC_OM_MASK	0x03
+#define STA350_CONFC_OM_SHIFT	0
+#define STA350_CONFC_CSZ_MASK	0x3c
+#define STA350_CONFC_CSZ_SHIFT	2
+#define STA350_CONFC_OCRB	BIT(7)
+
+/* 0x03 CONFD */
+#define STA350_CONFD_HPB_SHIFT	0
+#define STA350_CONFD_DEMP_SHIFT	1
+#define STA350_CONFD_DSPB_SHIFT	2
+#define STA350_CONFD_PSL_SHIFT	3
+#define STA350_CONFD_BQL_SHIFT	4
+#define STA350_CONFD_DRC_SHIFT	5
+#define STA350_CONFD_ZDE_SHIFT	6
+#define STA350_CONFD_SME_SHIFT	7
+
+/* 0x04 CONFE */
+#define STA350_CONFE_MPCV	BIT(0)
+#define STA350_CONFE_MPCV_SHIFT	0
+#define STA350_CONFE_MPC	BIT(1)
+#define STA350_CONFE_MPC_SHIFT	1
+#define STA350_CONFE_NSBW	BIT(2)
+#define STA350_CONFE_NSBW_SHIFT	2
+#define STA350_CONFE_AME	BIT(3)
+#define STA350_CONFE_AME_SHIFT	3
+#define STA350_CONFE_PWMS	BIT(4)
+#define STA350_CONFE_PWMS_SHIFT	4
+#define STA350_CONFE_DCCV	BIT(5)
+#define STA350_CONFE_DCCV_SHIFT	5
+#define STA350_CONFE_ZCE	BIT(6)
+#define STA350_CONFE_ZCE_SHIFT	6
+#define STA350_CONFE_SVE	BIT(7)
+#define STA350_CONFE_SVE_SHIFT	7
+
+/* 0x05 CONFF */
+#define STA350_CONFF_OCFG_MASK	0x03
+#define STA350_CONFF_OCFG_SHIFT	0
+#define STA350_CONFF_IDE	BIT(2)
+#define STA350_CONFF_BCLE	BIT(3)
+#define STA350_CONFF_LDTE	BIT(4)
+#define STA350_CONFF_ECLE	BIT(5)
+#define STA350_CONFF_PWDN	BIT(6)
+#define STA350_CONFF_EAPD	BIT(7)
+
+/* 0x06 MMUTE */
+#define STA350_MMUTE_MMUTE		0x01
+#define STA350_MMUTE_MMUTE_SHIFT	0
+#define STA350_MMUTE_C1M		0x02
+#define STA350_MMUTE_C1M_SHIFT		1
+#define STA350_MMUTE_C2M		0x04
+#define STA350_MMUTE_C2M_SHIFT		2
+#define STA350_MMUTE_C3M		0x08
+#define STA350_MMUTE_C3M_SHIFT		3
+#define STA350_MMUTE_LOC_MASK		0xC0
+#define STA350_MMUTE_LOC_SHIFT		6
+
+/* 0x0b AUTO1 */
+#define STA350_AUTO1_AMGC_MASK	0x30
+#define STA350_AUTO1_AMGC_SHIFT	4
+
+/* 0x0c AUTO2 */
+#define STA350_AUTO2_AMAME	0x01
+#define STA350_AUTO2_AMAM_MASK	0x0e
+#define STA350_AUTO2_AMAM_SHIFT	1
+#define STA350_AUTO2_XO_MASK	0xf0
+#define STA350_AUTO2_XO_SHIFT	4
+
+/* 0x0d AUTO3 */
+#define STA350_AUTO3_PEQ_MASK	0x1f
+#define STA350_AUTO3_PEQ_SHIFT	0
+
+/* 0x0e 0x0f 0x10 CxCFG */
+#define STA350_CxCFG_TCB_SHIFT	0
+#define STA350_CxCFG_EQBP_SHIFT	1
+#define STA350_CxCFG_VBP_SHIFT	2
+#define STA350_CxCFG_BO_SHIFT	3
+#define STA350_CxCFG_LS_SHIFT	4
+#define STA350_CxCFG_OM_MASK	0xc0
+#define STA350_CxCFG_OM_SHIFT	6
+
+/* 0x11 TONE */
+#define STA350_TONE_BTC_SHIFT	0
+#define STA350_TONE_TTC_SHIFT	4
+
+/* 0x12 0x13 0x14 0x15 limiter attack/release */
+#define STA350_LxA_SHIFT	0
+#define STA350_LxR_SHIFT	4
+
+/* 0x26 CFUD */
+#define STA350_CFUD_W1		0x01
+#define STA350_CFUD_WA		0x02
+#define STA350_CFUD_R1		0x04
+#define STA350_CFUD_RA		0x08
+
+
+/* biquad filter coefficient table offsets */
+#define STA350_C1_BQ_BASE	0
+#define STA350_C2_BQ_BASE	20
+#define STA350_CH_BQ_NUM	4
+#define STA350_BQ_NUM_COEF	5
+#define STA350_XO_HP_BQ_BASE	40
+#define STA350_XO_LP_BQ_BASE	45
+#define STA350_C1_PRESCALE	50
+#define STA350_C2_PRESCALE	51
+#define STA350_C1_POSTSCALE	52
+#define STA350_C2_POSTSCALE	53
+#define STA350_C3_POSTSCALE	54
+#define STA350_TW_POSTSCALE	55
+#define STA350_C1_MIX1		56
+#define STA350_C1_MIX2		57
+#define STA350_C2_MIX1		58
+#define STA350_C2_MIX2		59
+#define STA350_C3_MIX1		60
+#define STA350_C3_MIX2		61
+
+#endif /* _ASOC_STA_350_H */
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index a895a5e4bdf2..d48491a4a19d 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -272,7 +272,7 @@ static int tas5086_set_deemph(struct snd_soc_codec *codec)
 static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = priv->deemph;
@@ -283,7 +283,7 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
 static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 
 	priv->deemph = ucontrol->value.enumerated.item[0];
diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c
index b73c94ebcc2a..f13701995482 100644
--- a/sound/soc/codecs/tlv320aic23-i2c.c
+++ b/sound/soc/codecs/tlv320aic23-i2c.c
@@ -13,6 +13,7 @@
 
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/regmap.h>
 #include <sound/soc.h>
 
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 20864ee8793b..686b8b85b956 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -82,7 +82,7 @@ static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
 static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	u16 val, reg;
 
 	val = (ucontrol->value.integer.value[0] & 0x07);
@@ -105,7 +105,7 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
 static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	u16 val;
 
 	val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0);
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index fa158cfe9b32..b93d500e960b 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -28,6 +28,7 @@
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <sound/core.h>
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index b1835103e9b4..d7349bc89ad3 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1399,7 +1399,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 	}
 
 	aic3x_add_widgets(codec);
-	list_add(&aic3x->list, &reset_list);
 
 	return 0;
 
@@ -1569,7 +1568,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_aic3x, &aic3x_dai, 1);
-	return ret;
+
+	if (ret != 0)
+		goto err_gpio;
+
+	list_add(&aic3x->list, &reset_list);
+
+	return 0;
 
 err_gpio:
 	if (gpio_is_valid(aic3x->gpio_reset) &&
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 6bfc8a17331b..517055ab65ef 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -442,7 +442,7 @@ static int dac33_playback_event(struct snd_soc_dapm_widget *w,
 static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = dac33->fifo_mode;
@@ -453,7 +453,7 @@ static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
 static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 	int ret = 0;
 
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index b27c396037d4..8fc5a647453b 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -30,6 +30,7 @@
 #include <sound/tpa6130a2-plat.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 
 #include "tpa6130a2.h"
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 975e0f760ac1..69e12a311ba2 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -830,7 +830,7 @@ static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int shift = mc->shift;
 	unsigned int rshift = mc->rshift;
@@ -859,7 +859,7 @@ static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int shift = mc->shift;
 	unsigned int rshift = mc->rshift;
@@ -888,7 +888,7 @@ static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int reg2 = mc->rreg;
 	unsigned int shift = mc->shift;
@@ -915,7 +915,7 @@ static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg = mc->reg;
 	unsigned int reg2 = mc->rreg;
 	unsigned int shift = mc->shift;
@@ -956,7 +956,7 @@ static SOC_ENUM_SINGLE_DECL(twl4030_op_modes_enum,
 static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 
 	if (twl4030->configured) {
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index bd3a20647fdf..0f6067f04e29 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -484,7 +484,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum,
 static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = priv->hs_power_mode;
@@ -495,7 +495,7 @@ static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
 static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 	int high_perf = ucontrol->value.enumerated.item[0];
 	int ret = 0;
@@ -512,7 +512,7 @@ static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
 static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = priv->pll_power_mode;
@@ -523,7 +523,7 @@ static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
 static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 
 	priv->pll_power_mode = ucontrol->value.enumerated.item[0];
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 6be5f80b65f1..4ead0dc02b87 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -172,7 +172,7 @@ out:
 static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = wl1273->mode;
@@ -190,7 +190,7 @@ static const char * const wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" };
 static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
 	if (wl1273->mode == ucontrol->value.integer.value[0])
@@ -214,7 +214,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route);
 static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
 	dev_dbg(codec->dev, "%s: enter.\n", __func__);
@@ -227,7 +227,7 @@ static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
 static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 	int val, r = 0;
 
@@ -251,7 +251,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings);
 static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
 				    struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
 	dev_dbg(codec->dev, "%s: enter.\n", __func__);
@@ -264,7 +264,7 @@ static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
 static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol,
 				    struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 	int r;
 
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 83a2c872925c..a4c352cc3464 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -607,7 +607,7 @@ static int wm2000_anc_set_mode(struct wm2000_priv *wm2000)
 static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
 	ucontrol->value.enumerated.item[0] = wm2000->anc_active;
@@ -618,7 +618,7 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
 static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 	int anc_active = ucontrol->value.enumerated.item[0];
 	int ret;
@@ -640,7 +640,7 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
 static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
 	ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
@@ -651,7 +651,7 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
 static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 	int val = ucontrol->value.enumerated.item[0];
 	int ret;
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index 2e721e06671b..cdea9d9c1631 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -1083,7 +1083,7 @@ static int wm2200_mixer_values[] = {
 
 #define WM2200_MUX_CTL_DECL(name) \
 	const struct snd_kcontrol_new name##_mux =	\
-		SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+		SOC_DAPM_ENUM("Route", name##_enum)
 
 #define WM2200_MIXER_ENUMS(name, base_reg) \
 	static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg);	     \
@@ -1207,7 +1207,7 @@ WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
 
 #define WM2200_MUX(name, ctrl) \
-	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+	SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
 #define WM2200_MIXER_WIDGETS(name, name_str)	\
 	WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index eca983fad891..91a9ea2a2056 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -390,7 +390,7 @@ static int wm5100_mixer_values[] = {
 
 #define WM5100_MUX_CTL_DECL(name) \
 	const struct snd_kcontrol_new name##_mux =	\
-		SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+		SOC_DAPM_ENUM("Route", name##_enum)
 
 #define WM5100_MIXER_ENUMS(name, base_reg) \
 	static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg);	     \
@@ -448,7 +448,7 @@ WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE);
 WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE);
 
 #define WM5100_MUX(name, ctrl) \
-	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+	SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
 #define WM5100_MIXER_WIDGETS(name, name_str)	\
 	WM5100_MUX(name_str " Input 1", &name##_in1_mux), \
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index dcf1d12cfef8..289b64d89abd 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -764,8 +764,8 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
 SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
 
-SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
-SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
 
 ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
@@ -814,9 +814,9 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
 		 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
 		 0xbf, 0, digital_tlv),
 
-SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
-SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
-SOC_VALUE_ENUM("EPOUT OSR", wm5102_hpout_osr[2]),
+SOC_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
+SOC_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
+SOC_ENUM("EPOUT OSR", wm5102_hpout_osr[2]),
 
 SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE,
 	   ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0),
@@ -970,7 +970,7 @@ static const struct soc_enum wm5102_aec_loopback =
 			      wm5102_aec_loopback_values);
 
 static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
-	SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5102_aec_loopback);
+	SOC_DAPM_ENUM("AEC Loopback", wm5102_aec_loopback);
 
 static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
@@ -1204,7 +1204,7 @@ SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
 
 ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
 
-SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
+SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
 		       ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
 		       &wm5102_aec_loopback_mux),
 
@@ -1760,10 +1760,6 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
 	struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
-	ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap);
-	if (ret != 0)
-		return ret;
-
 	ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2);
 	if (ret != 0)
 		return ret;
@@ -1802,9 +1798,17 @@ static unsigned int wm5102_digital_vu[] = {
 	ARIZONA_DAC_DIGITAL_VOLUME_5R,
 };
 
+static struct regmap *wm5102_get_regmap(struct device *dev)
+{
+	struct wm5102_priv *priv = dev_get_drvdata(dev);
+
+	return priv->core.arizona->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
 	.probe = wm5102_codec_probe,
 	.remove = wm5102_codec_remove,
+	.get_regmap = wm5102_get_regmap,
 
 	.idle_bias_off = true,
 
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index df5a38dd8328..2e5fcb559e90 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -324,13 +324,13 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
 SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
 
-SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
-SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
-SOC_VALUE_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]),
-SOC_VALUE_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]),
-SOC_VALUE_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),
-SOC_VALUE_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]),
-SOC_VALUE_ENUM("ASRC RATE 1", arizona_asrc_rate1),
+SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]),
+SOC_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]),
+SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),
+SOC_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]),
+SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1),
 
 ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
@@ -367,6 +367,11 @@ SOC_SINGLE("HPOUT2 SC Protect Switch", ARIZONA_HP2_SHORT_CIRCUIT_CTRL,
 SOC_SINGLE("HPOUT3 SC Protect Switch", ARIZONA_HP3_SHORT_CIRCUIT_CTRL,
 	   ARIZONA_HP3_SC_ENA_SHIFT, 1, 0),
 
+SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
+	   ARIZONA_OUT5_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
+	   ARIZONA_OUT6_OSR_SHIFT, 1, 0),
+
 SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
 	     ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -592,7 +597,7 @@ static const struct soc_enum wm5110_aec_loopback =
 			      wm5110_aec_loopback_values);
 
 static const struct snd_kcontrol_new wm5110_aec_loopback_mux =
-	SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5110_aec_loopback);
+	SOC_DAPM_ENUM("AEC Loopback", wm5110_aec_loopback);
 
 static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
@@ -774,7 +779,7 @@ SND_SOC_DAPM_PGA("ISRC3DEC3", ARIZONA_ISRC_3_CTRL_3,
 SND_SOC_DAPM_PGA("ISRC3DEC4", ARIZONA_ISRC_3_CTRL_3,
 		 ARIZONA_ISRC3_DEC3_ENA_SHIFT, 0, NULL, 0),
 
-SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
+SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
 		       ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
 		       &wm5110_aec_loopback_mux),
 
@@ -1589,10 +1594,6 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
 
 	priv->core.arizona->dapm = &codec->dapm;
 
-	ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap);
-	if (ret != 0)
-		return ret;
-
 	arizona_init_spk(codec);
 	arizona_init_gpio(codec);
 
@@ -1633,9 +1634,17 @@ static unsigned int wm5110_digital_vu[] = {
 	ARIZONA_DAC_DIGITAL_VOLUME_6R,
 };
 
+static struct regmap *wm5110_get_regmap(struct device *dev)
+{
+	struct wm5110_priv *priv = dev_get_drvdata(dev);
+
+	return priv->core.arizona->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
 	.probe = wm5110_codec_probe,
 	.remove = wm5110_codec_remove,
+	.get_regmap = wm5110_get_regmap,
 
 	.idle_bias_off = true,
 
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 757256bf7672..392285edb595 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -302,7 +302,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8350_data *wm8350_priv = snd_soc_codec_get_drvdata(codec);
 	struct wm8350_output *out = NULL;
 	struct soc_mixer_control *mc =
@@ -345,7 +345,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
 static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8350_data *wm8350_priv = snd_soc_codec_get_drvdata(codec);
 	struct wm8350_output *out1 = &wm8350_priv->out1;
 	struct wm8350_output *out2 = &wm8350_priv->out2;
@@ -1505,8 +1505,6 @@ static  int wm8350_codec_probe(struct snd_soc_codec *codec)
 	if (ret != 0)
 		return ret;
 
-	snd_soc_codec_set_cache_io(codec, wm8350->regmap);
-
 	/* Put the codec into reset if it wasn't already */
 	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
 
@@ -1608,11 +1606,19 @@ static int  wm8350_codec_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static struct regmap *wm8350_get_regmap(struct device *dev)
+{
+	struct wm8350 *wm8350 = dev_get_platdata(dev);
+
+	return wm8350->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
 	.probe =	wm8350_codec_probe,
 	.remove =	wm8350_codec_remove,
 	.suspend = 	wm8350_suspend,
 	.resume =	wm8350_resume,
+	.get_regmap =	wm8350_get_regmap,
 	.set_bias_level = wm8350_set_bias_level,
 
 	.controls = wm8350_snd_controls,
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 146564feaea0..06e913d3fea1 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -93,7 +93,7 @@ static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
 static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
         struct snd_ctl_elem_value *ucontrol)
 {
-        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	int reg = mc->reg;
@@ -1318,8 +1318,6 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
 	priv->wm8400 = wm8400;
 	priv->codec = codec;
 
-	snd_soc_codec_set_cache_io(codec, wm8400->regmap);
-
 	ret = devm_regulator_bulk_get(wm8400->dev,
 				 ARRAY_SIZE(power), &power[0]);
 	if (ret != 0) {
@@ -1361,11 +1359,19 @@ static int  wm8400_codec_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static struct regmap *wm8400_get_regmap(struct device *dev)
+{
+	struct wm8400 *wm8400 = dev_get_platdata(dev);
+
+	return wm8400->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
 	.probe =	wm8400_codec_probe,
 	.remove =	wm8400_codec_remove,
 	.suspend =	wm8400_suspend,
 	.resume =	wm8400_resume,
+	.get_regmap =	wm8400_get_regmap,
 	.set_bias_level = wm8400_set_bias_level,
 
 	.controls = wm8400_snd_controls,
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index af7ed8b5d4e1..7665ff6aea6d 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -252,7 +252,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
 	unsigned int reg = mc->reg;
 	unsigned int reg2 = mc->rreg;
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index d74f43975b90..763b265d9528 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -119,7 +119,7 @@ static int wm8731_set_deemph(struct snd_soc_codec *codec)
 static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8731->deemph;
@@ -130,7 +130,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
 static int wm8731_put_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 	int deemph = ucontrol->value.enumerated.item[0];
 	int ret = 0;
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index cbb8d55052a4..53e57b4049a8 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -234,7 +234,7 @@ SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
 static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = wm8753->dai_func;
@@ -244,7 +244,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
 static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 	u16 ioctl;
 
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index ee76f0fb4299..589455c3bfcd 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -106,7 +106,7 @@ static int txsrc_get(struct snd_kcontrol *kcontrol,
 	struct snd_soc_codec *codec;
 	unsigned int src;
 
-	codec = snd_kcontrol_chip(kcontrol);
+	codec = snd_soc_kcontrol_codec(kcontrol);
 	src = snd_soc_read(codec, WM8804_SPDTX4);
 	if (src & 0x40)
 		ucontrol->value.integer.value[0] = 1;
@@ -122,7 +122,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
 	struct snd_soc_codec *codec;
 	unsigned int src, txpwr;
 
-	codec = snd_kcontrol_chip(kcontrol);
+	codec = snd_soc_kcontrol_codec(kcontrol);
 
 	if (ucontrol->value.integer.value[0] != 0
 			&& ucontrol->value.integer.value[0] != 1)
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index b0084a127d18..b84940c359a1 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -439,7 +439,7 @@ static int wm8903_set_deemph(struct snd_soc_codec *codec)
 static int wm8903_get_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8903->deemph;
@@ -450,7 +450,7 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol,
 static int wm8903_put_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 	int deemph = ucontrol->value.enumerated.item[0];
 	int ret = 0;
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 49c35c36935e..f7c549949c54 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -391,7 +391,7 @@ static void wm8904_set_drc(struct snd_soc_codec *codec)
 static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 	struct wm8904_pdata *pdata = wm8904->pdata;
 	int value = ucontrol->value.integer.value[0];
@@ -409,7 +409,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
 static int wm8904_get_drc_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8904->drc_cfg;
@@ -462,7 +462,7 @@ static void wm8904_set_retune_mobile(struct snd_soc_codec *codec)
 static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 	struct wm8904_pdata *pdata = wm8904->pdata;
 	int value = ucontrol->value.integer.value[0];
@@ -480,7 +480,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 static int wm8904_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8904->retune_mobile_cfg;
@@ -520,7 +520,7 @@ static int wm8904_set_deemph(struct snd_soc_codec *codec)
 static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8904->deemph;
@@ -530,7 +530,7 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
 static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 	int deemph = ucontrol->value.enumerated.item[0];
 
@@ -570,7 +570,7 @@ static SOC_ENUM_SINGLE_DECL(hpf_mode, WM8904_ADC_DIGITAL_0, 5,
 static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int val;
 	int ret;
 
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index fecd4e4f4c57..7e443c4f6f85 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -390,7 +390,7 @@ static int wm8955_set_deemph(struct snd_soc_codec *codec)
 static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8955->deemph;
@@ -400,7 +400,7 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
 static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 	int deemph = ucontrol->value.enumerated.item[0];
 
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 7ac2e511403c..b2ebb104d879 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -456,7 +456,7 @@ static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif)
 static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
 	int value = ucontrol->value.integer.value[0];
@@ -478,7 +478,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
 static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
@@ -500,7 +500,7 @@ static int wm8958_mbc_get(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int mbc = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc];
@@ -512,7 +512,7 @@ static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int mbc = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0])
@@ -546,7 +546,7 @@ static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
 static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
 	int value = ucontrol->value.integer.value[0];
@@ -568,7 +568,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
 static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8994->vss_cfg;
@@ -579,7 +579,7 @@ static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol,
 static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
 	int value = ucontrol->value.integer.value[0];
@@ -601,7 +601,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
 static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg;
@@ -623,7 +623,7 @@ static int wm8958_vss_get(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int vss = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = wm8994->vss_ena[vss];
@@ -635,7 +635,7 @@ static int wm8958_vss_put(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int vss = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0])
@@ -684,7 +684,7 @@ static int wm8958_hpf_get(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int hpf = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	if (hpf < 3)
@@ -699,7 +699,7 @@ static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int hpf = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	if (hpf < 3) {
@@ -746,7 +746,7 @@ static int wm8958_hpf_put(struct snd_kcontrol *kcontrol,
 static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
 	int value = ucontrol->value.integer.value[0];
@@ -768,7 +768,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
 static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg;
@@ -790,7 +790,7 @@ static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int eq = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq];
@@ -802,7 +802,7 @@ static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
 	int eq = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
 	if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0])
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index d04e9cad445c..a145d0431b63 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -178,7 +178,7 @@ static int wm8960_set_deemph(struct snd_soc_codec *codec)
 static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.enumerated.item[0] = wm8960->deemph;
@@ -188,7 +188,7 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
 static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 	int deemph = ucontrol->value.enumerated.item[0];
 
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 5522d2566c67..37986c84cbff 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1552,7 +1552,7 @@ static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
 	int shift = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
 
 	ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift);
@@ -1564,7 +1564,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
 	int shift = kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
 	int old = wm8962->dsp2_ena;
 	int ret = 0;
@@ -1602,7 +1602,7 @@ out:
 static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
 			    struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	int ret;
 
 	/* Apply the update (if any) */
@@ -1632,7 +1632,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
 static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
 			    struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	int ret;
 
 	/* Apply the update (if any) */
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index 2b9bfa53efbf..19d5baa38f5c 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -552,7 +552,7 @@ static const struct snd_soc_dapm_route wm8983_audio_map[] = {
 static int eqmode_get(struct snd_kcontrol *kcontrol,
 		      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg;
 
 	reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
@@ -567,7 +567,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
 static int eqmode_put(struct snd_kcontrol *kcontrol,
 		      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int regpwr2, regpwr3;
 	unsigned int reg_eq;
 
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index 5473dc969585..ad23ffb8346c 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -526,7 +526,7 @@ static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
 static int eqmode_get(struct snd_kcontrol *kcontrol,
 		      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg;
 
 	reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
@@ -541,7 +541,7 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
 static int eqmode_put(struct snd_kcontrol *kcontrol,
 		      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int regpwr2, regpwr3;
 	unsigned int reg_eq;
 
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 3a1ae4f5164d..d3fea46d58e8 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -268,7 +268,7 @@ static const struct soc_enum wm8988_lline_enum =
 			      wm8988_line_texts,
 			      wm8988_line_values);
 static const struct snd_kcontrol_new wm8988_left_line_controls =
-	SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
+	SOC_DAPM_ENUM("Route", wm8988_lline_enum);
 
 static const struct soc_enum wm8988_rline_enum =
 	SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7,
@@ -276,7 +276,7 @@ static const struct soc_enum wm8988_rline_enum =
 			      wm8988_line_texts,
 			      wm8988_line_values);
 static const struct snd_kcontrol_new wm8988_right_line_controls =
-	SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
+	SOC_DAPM_ENUM("Route", wm8988_lline_enum);
 
 /* Left Mixer */
 static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {
@@ -304,7 +304,7 @@ static const struct soc_enum wm8988_lpga_enum =
 			      wm8988_pga_sel,
 			      wm8988_pga_val);
 static const struct snd_kcontrol_new wm8988_left_pga_controls =
-	SOC_DAPM_VALUE_ENUM("Route", wm8988_lpga_enum);
+	SOC_DAPM_ENUM("Route", wm8988_lpga_enum);
 
 /* Right PGA Mux */
 static const struct soc_enum wm8988_rpga_enum =
@@ -313,7 +313,7 @@ static const struct soc_enum wm8988_rpga_enum =
 			      wm8988_pga_sel,
 			      wm8988_pga_val);
 static const struct snd_kcontrol_new wm8988_right_pga_controls =
-	SOC_DAPM_VALUE_ENUM("Route", wm8988_rpga_enum);
+	SOC_DAPM_ENUM("Route", wm8988_rpga_enum);
 
 /* Differential Mux */
 static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"};
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index c413c1991453..b5c1f0f07058 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -132,7 +132,7 @@ static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
 static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	int reg = mc->reg;
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 844cc4a60d66..b8fd284fc0c0 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -154,7 +154,7 @@ static const unsigned int out_sidetone_tlv[] = {
 static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	int reg = kcontrol->private_value & 0xff;
 	int ret;
 	u16 val;
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 6303537f54c6..247b39013fba 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -298,7 +298,7 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
 {
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	int mask, ret;
 
 	/* Can't enable both ADC and DAC paths simultaneously */
@@ -355,7 +355,7 @@ static int wm8994_get_drc(const char *name)
 static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
 	struct wm8994_pdata *pdata = &control->pdata;
@@ -378,7 +378,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
 static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	int drc = wm8994_get_drc(kcontrol->id.name);
 
@@ -462,7 +462,7 @@ static int wm8994_get_retune_mobile_block(const char *name)
 static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
 	struct wm8994_pdata *pdata = &control->pdata;
@@ -485,7 +485,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
 
@@ -1347,10 +1347,10 @@ static const char *adc_mux_text[] = {
 static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text);
 
 static const struct snd_kcontrol_new adcl_mux =
-	SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
+	SOC_DAPM_ENUM("ADCL Mux", adc_enum);
 
 static const struct snd_kcontrol_new adcr_mux =
-	SOC_DAPM_ENUM_VIRT("ADCR Mux", adc_enum);
+	SOC_DAPM_ENUM("ADCR Mux", adc_enum);
 
 static const struct snd_kcontrol_new left_speaker_mixer[] = {
 SOC_DAPM_SINGLE("DAC2 Switch", WM8994_SPEAKER_MIXER, 9, 1, 0),
@@ -1651,15 +1651,15 @@ SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
 };
 
 static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = {
-SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
+SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
 			adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
-SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
+SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
 			adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
 };
 
 static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = {
-SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
-SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
+SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
+SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
 };
 
 static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
@@ -3999,8 +3999,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
 	wm8994->hubs.codec = codec;
 
-	snd_soc_codec_set_cache_io(codec, control->regmap);
-
 	mutex_init(&wm8994->accdet_lock);
 	INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
 			  wm1811_jackdet_bootstrap);
@@ -4434,11 +4432,19 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static struct regmap *wm8994_get_regmap(struct device *dev)
+{
+	struct wm8994 *control = dev_get_drvdata(dev->parent);
+
+	return control->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
 	.probe =	wm8994_codec_probe,
 	.remove =	wm8994_codec_remove,
 	.suspend =	wm8994_codec_suspend,
 	.resume =	wm8994_codec_resume,
+	.get_regmap =   wm8994_get_regmap,
 	.set_bias_level = wm8994_set_bias_level,
 };
 
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index d3152cf5bd56..863a2c38bcb5 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -885,10 +885,10 @@ static const char *adc_mux_text[] = {
 static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text);
 
 static const struct snd_kcontrol_new adcl_mux =
-	SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
+	SOC_DAPM_ENUM("ADCL Mux", adc_enum);
 
 static const struct snd_kcontrol_new adcr_mux =
-	SOC_DAPM_ENUM_VIRT("ADCR Mux", adc_enum);
+	SOC_DAPM_ENUM("ADCR Mux", adc_enum);
 
 static const char *spk_src_text[] = {
 	"DAC1L", "DAC1R", "DAC2L", "DAC2R"
@@ -948,10 +948,8 @@ static const struct snd_soc_dapm_widget wm8995_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT("AIF1ADC2R", "AIF1 Capture",
 		0, WM8995_POWER_MANAGEMENT_3, 10, 0),
 
-	SND_SOC_DAPM_VIRT_MUX("ADCL Mux", SND_SOC_NOPM, 1, 0,
-		&adcl_mux),
-	SND_SOC_DAPM_VIRT_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
-		&adcr_mux),
+	SND_SOC_DAPM_MUX("ADCL Mux", SND_SOC_NOPM, 1, 0, &adcl_mux),
+	SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
 
 	SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8995_POWER_MANAGEMENT_3, 5, 0),
 	SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8995_POWER_MANAGEMENT_3, 4, 0),
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index c6cbb3b8ace9..69266332760e 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -412,7 +412,7 @@ static int wm8996_get_retune_mobile_block(const char *name)
 static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	struct wm8996_pdata *pdata = &wm8996->pdata;
 	int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
@@ -434,7 +434,7 @@ static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 static int wm8996_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
 
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index 004186b6bd48..bb9b47b956aa 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -245,8 +245,8 @@ SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
 SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
 SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
 
-SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
-SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
 
 ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
@@ -286,8 +286,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
 		 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
 		 0xbf, 0, digital_tlv),
 
-SOC_VALUE_ENUM("HPOUT1 OSR", wm8997_hpout_osr[0]),
-SOC_VALUE_ENUM("EPOUT OSR", wm8997_hpout_osr[1]),
+SOC_ENUM("HPOUT1 OSR", wm8997_hpout_osr[0]),
+SOC_ENUM("EPOUT OSR", wm8997_hpout_osr[1]),
 
 SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
 SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
@@ -405,7 +405,7 @@ static const struct soc_enum wm8997_aec_loopback =
 			      wm8997_aec_loopback_values);
 
 static const struct snd_kcontrol_new wm8997_aec_loopback_mux =
-	SOC_DAPM_VALUE_ENUM("AEC Loopback", wm8997_aec_loopback);
+	SOC_DAPM_ENUM("AEC Loopback", wm8997_aec_loopback);
 
 static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
@@ -604,7 +604,7 @@ SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
 		    ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
 		    ARIZONA_SLIMRX8_ENA_SHIFT, 0),
 
-SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
+SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
 		       ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
 		       &wm8997_aec_loopback_mux),
 
@@ -1051,11 +1051,6 @@ static struct snd_soc_dai_driver wm8997_dai[] = {
 static int wm8997_codec_probe(struct snd_soc_codec *codec)
 {
 	struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec);
-	int ret;
-
-	ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap);
-	if (ret != 0)
-		return ret;
 
 	arizona_init_spk(codec);
 
@@ -1086,9 +1081,17 @@ static unsigned int wm8997_digital_vu[] = {
 	ARIZONA_DAC_DIGITAL_VOLUME_5R,
 };
 
+static struct regmap *wm8997_get_regmap(struct device *dev)
+{
+	struct wm8997_priv *priv = dev_get_drvdata(dev);
+
+	return priv->core.arizona->regmap;
+}
+
 static struct snd_soc_codec_driver soc_codec_dev_wm8997 = {
 	.probe = wm8997_codec_probe,
 	.remove = wm8997_codec_remove,
+	.get_regmap =   wm8997_get_regmap,
 
 	.idle_bias_off = true,
 
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index d18eff31fbbc..185eb97769e7 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -340,7 +340,7 @@ static SOC_ENUM_SINGLE_DECL(speaker_mode, WM9081_ANALOGUE_SPEAKER_2, 6,
 static int speaker_mode_get(struct snd_kcontrol *kcontrol,
 			    struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg;
 
 	reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
@@ -361,7 +361,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol,
 static int speaker_mode_put(struct snd_kcontrol *kcontrol,
 			    struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	unsigned int reg_pwr = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
 	unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
 
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index bb5f7b4e3ebb..d9686dcd024c 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -242,7 +242,7 @@ struct wm_coeff_ctl {
 static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
 
@@ -254,7 +254,7 @@ static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
 static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
 
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index b6209662ab13..916817fe6632 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -337,7 +337,7 @@ static void enable_dc_servo(struct snd_soc_codec *codec)
 static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 4f75cac462d1..af92d3e8671d 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -37,6 +37,8 @@
 #include "davinci-pcm.h"
 #include "davinci-mcasp.h"
 
+#define MCASP_MAX_AFIFO_DEPTH	64
+
 struct davinci_mcasp_context {
 	u32	txfmtctl;
 	u32	rxfmtctl;
@@ -269,25 +271,51 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 {
 	struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
 	int ret = 0;
+	u32 data_delay;
+	bool fs_pol_rising;
+	bool inv_fs = false;
 
 	pm_runtime_get_sync(mcasp->dev);
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+		mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+		/* 1st data bit occur one ACLK cycle after the frame sync */
+		data_delay = 1;
+		break;
 	case SND_SOC_DAIFMT_DSP_B:
 	case SND_SOC_DAIFMT_AC97:
 		mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
 		mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+		/* No delay after FS */
+		data_delay = 0;
 		break;
-	default:
+	case SND_SOC_DAIFMT_I2S:
 		/* configure a full-word SYNC pulse (LRCLK) */
 		mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
 		mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
-
-		/* make 1st data bit occur one ACLK cycle after the frame sync */
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
+		/* 1st data bit occur one ACLK cycle after the frame sync */
+		data_delay = 1;
+		/* FS need to be inverted */
+		inv_fs = true;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		/* configure a full-word SYNC pulse (LRCLK) */
+		mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+		mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+		/* No delay after FS */
+		data_delay = 0;
 		break;
+	default:
+		ret = -EINVAL;
+		goto out;
 	}
 
+	mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(data_delay),
+		       FSXDLY(3));
+	mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(data_delay),
+		       FSRDLY(3));
+
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
 		/* codec is clock and frame slave */
@@ -325,7 +353,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 			       ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
 		mcasp->bclk_master = 0;
 		break;
-
 	default:
 		ret = -EINVAL;
 		goto out;
@@ -334,39 +361,38 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 	case SND_SOC_DAIFMT_IB_NF:
 		mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
-
 		mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		fs_pol_rising = true;
 		break;
-
 	case SND_SOC_DAIFMT_NB_IF:
 		mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
-
 		mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		fs_pol_rising = false;
 		break;
-
 	case SND_SOC_DAIFMT_IB_IF:
 		mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
-
 		mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		fs_pol_rising = false;
 		break;
-
 	case SND_SOC_DAIFMT_NB_NF:
 		mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
-
 		mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		fs_pol_rising = true;
 		break;
-
 	default:
 		ret = -EINVAL;
-		break;
+		goto out;
+	}
+
+	if (inv_fs)
+		fs_pol_rising = !fs_pol_rising;
+
+	if (fs_pol_rising) {
+		mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+		mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+	} else {
+		mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+		mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
 	}
 out:
 	pm_runtime_put_sync(mcasp->dev);
@@ -464,17 +490,19 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
 }
 
 static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
-				    int channels)
+				 int period_words, int channels)
 {
+	struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[stream];
+	struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream];
 	int i;
 	u8 tx_ser = 0;
 	u8 rx_ser = 0;
-	u8 ser;
 	u8 slots = mcasp->tdm_slots;
 	u8 max_active_serializers = (channels + slots - 1) / slots;
+	int active_serializers, numevt, n;
 	u32 reg;
 	/* Default configuration */
-	if (mcasp->version != MCASP_VERSION_4)
+	if (mcasp->version < MCASP_VERSION_3)
 		mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
 
 	/* All PINS as McASP */
@@ -505,37 +533,71 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
 		}
 	}
 
-	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-		ser = tx_ser;
-	else
-		ser = rx_ser;
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		active_serializers = tx_ser;
+		numevt = mcasp->txnumevt;
+		reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+	} else {
+		active_serializers = rx_ser;
+		numevt = mcasp->rxnumevt;
+		reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+	}
 
-	if (ser < max_active_serializers) {
+	if (active_serializers < max_active_serializers) {
 		dev_warn(mcasp->dev, "stream has more channels (%d) than are "
-			"enabled in mcasp (%d)\n", channels, ser * slots);
+			 "enabled in mcasp (%d)\n", channels,
+			 active_serializers * slots);
 		return -EINVAL;
 	}
 
-	if (mcasp->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (mcasp->txnumevt * tx_ser > 64)
-			mcasp->txnumevt = 1;
-
-		reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
-		mcasp_mod_bits(mcasp, reg, tx_ser, NUMDMA_MASK);
-		mcasp_mod_bits(mcasp, reg, ((mcasp->txnumevt * tx_ser) << 8),
-			       NUMEVT_MASK);
+	/* AFIFO is not in use */
+	if (!numevt) {
+		/* Configure the burst size for platform drivers */
+		if (active_serializers > 1) {
+			/*
+			 * If more than one serializers are in use we have one
+			 * DMA request to provide data for all serializers.
+			 * For example if three serializers are enabled the DMA
+			 * need to transfer three words per DMA request.
+			 */
+			dma_params->fifo_level = active_serializers;
+			dma_data->maxburst = active_serializers;
+		} else {
+			dma_params->fifo_level = 0;
+			dma_data->maxburst = 0;
+		}
+		return 0;
 	}
 
-	if (mcasp->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
-		if (mcasp->rxnumevt * rx_ser > 64)
-			mcasp->rxnumevt = 1;
-
-		reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
-		mcasp_mod_bits(mcasp, reg, rx_ser, NUMDMA_MASK);
-		mcasp_mod_bits(mcasp, reg, ((mcasp->rxnumevt * rx_ser) << 8),
-			       NUMEVT_MASK);
+	if (period_words % active_serializers) {
+		dev_err(mcasp->dev, "Invalid combination of period words and "
+			"active serializers: %d, %d\n", period_words,
+			active_serializers);
+		return -EINVAL;
 	}
 
+	/*
+	 * Calculate the optimal AFIFO depth for platform side:
+	 * The number of words for numevt need to be in steps of active
+	 * serializers.
+	 */
+	n = numevt % active_serializers;
+	if (n)
+		numevt += (active_serializers - n);
+	while (period_words % numevt && numevt > 0)
+		numevt -= active_serializers;
+	if (numevt <= 0)
+		numevt = active_serializers;
+
+	mcasp_mod_bits(mcasp, reg, active_serializers, NUMDMA_MASK);
+	mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK);
+
+	/* Configure the burst size for platform drivers */
+	if (numevt == 1)
+		numevt = 0;
+	dma_params->fifo_level = numevt;
+	dma_data->maxburst = numevt;
+
 	return 0;
 }
 
@@ -607,27 +669,24 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 	struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
 	struct davinci_pcm_dma_params *dma_params =
 					&mcasp->dma_params[substream->stream];
-	struct snd_dmaengine_dai_dma_data *dma_data =
-					&mcasp->dma_data[substream->stream];
 	int word_length;
-	u8 fifo_level;
-	u8 slots = mcasp->tdm_slots;
-	u8 active_serializers;
 	int channels = params_channels(params);
+	int period_size = params_period_size(params);
 	int ret;
 
 	/* If mcasp is BCLK master we need to set BCLK divider */
 	if (mcasp->bclk_master) {
 		unsigned int bclk_freq = snd_soc_params_to_bclk(params);
 		if (mcasp->sysclk_freq % bclk_freq != 0) {
-			dev_err(mcasp->dev, "Can't produce requred BCLK\n");
+			dev_err(mcasp->dev, "Can't produce required BCLK\n");
 			return -EINVAL;
 		}
 		davinci_mcasp_set_clkdiv(
 			cpu_dai, 1, mcasp->sysclk_freq / bclk_freq);
 	}
 
-	ret = mcasp_common_hw_param(mcasp, substream->stream, channels);
+	ret = mcasp_common_hw_param(mcasp, substream->stream,
+				    period_size * channels, channels);
 	if (ret)
 		return ret;
 
@@ -671,21 +730,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	/* Calculate FIFO level */
-	active_serializers = (channels + slots - 1) / slots;
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		fifo_level = mcasp->txnumevt * active_serializers;
-	else
-		fifo_level = mcasp->rxnumevt * active_serializers;
-
-	if (mcasp->version == MCASP_VERSION_2 && !fifo_level)
+	if (mcasp->version == MCASP_VERSION_2 && !dma_params->fifo_level)
 		dma_params->acnt = 4;
 	else
 		dma_params->acnt = dma_params->data_type;
 
-	dma_params->fifo_level = fifo_level;
-	dma_data->maxburst = fifo_level;
-
 	davinci_config_channel_size(mcasp, word_length);
 
 	return 0;
@@ -716,22 +765,7 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
 	return ret;
 }
 
-static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
-				 struct snd_soc_dai *dai)
-{
-	struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
-
-	if (mcasp->version == MCASP_VERSION_4)
-		snd_soc_dai_set_dma_data(dai, substream,
-					&mcasp->dma_data[substream->stream]);
-	else
-		snd_soc_dai_set_dma_data(dai, substream, mcasp->dma_params);
-
-	return 0;
-}
-
 static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
-	.startup	= davinci_mcasp_startup,
 	.trigger	= davinci_mcasp_trigger,
 	.hw_params	= davinci_mcasp_hw_params,
 	.set_fmt	= davinci_mcasp_set_dai_fmt,
@@ -739,6 +773,25 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
 	.set_sysclk	= davinci_mcasp_set_sysclk,
 };
 
+static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
+{
+	struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
+
+	if (mcasp->version == MCASP_VERSION_4) {
+		/* Using dmaengine PCM */
+		dai->playback_dma_data =
+				&mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
+		dai->capture_dma_data =
+				&mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
+	} else {
+		/* Using davinci-pcm */
+		dai->playback_dma_data = mcasp->dma_params;
+		dai->capture_dma_data = mcasp->dma_params;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
 {
@@ -792,6 +845,7 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai)
 static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
 	{
 		.name		= "davinci-mcasp.0",
+		.probe		= davinci_mcasp_dai_probe,
 		.suspend	= davinci_mcasp_suspend,
 		.resume		= davinci_mcasp_resume,
 		.playback	= {
@@ -811,6 +865,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
 	},
 	{
 		.name		= "davinci-mcasp.1",
+		.probe		= davinci_mcasp_dai_probe,
 		.playback 	= {
 			.channels_min	= 1,
 			.channels_max	= 384,
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 8fed757d6087..98fbc451892a 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -283,6 +283,7 @@
  */
 #define FIFO_ENABLE	BIT(16)
 #define NUMEVT_MASK	(0xFF << 8)
+#define NUMEVT(x)	(((x) & 0xFF) << 8)
 #define NUMDMA_MASK	(0xFF)
 
 #endif	/* DAVINCI_MCASP_H */
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index fbb710c76c08..5fd4737ab398 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -29,7 +29,17 @@ struct davinci_pcm_dma_params {
 	unsigned int fifo_level;
 };
 
+#if IS_ENABLED(CONFIG_SND_DAVINCI_SOC)
 int davinci_soc_platform_register(struct device *dev);
 void davinci_soc_platform_unregister(struct device *dev);
+#else
+static inline int davinci_soc_platform_register(struct device *dev)
+{
+	return 0;
+}
+static inline void davinci_soc_platform_unregister(struct device *dev)
+{
+}
+#endif /* CONFIG_SND_DAVINCI_SOC */
 
 #endif
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 338a91642471..7a7eaf32158f 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,14 +1,28 @@
+menu "SoC Audio for Freescale CPUs"
+
+comment "Common SoC Audio options for Freescale CPUs:"
+
 config SND_SOC_FSL_SAI
 	tristate
 	select REGMAP_MMIO
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 
 config SND_SOC_FSL_SSI
-	tristate
+	tristate "Synchronous Serial Interface module support"
+	help
+	  Say Y if you want to add Synchronous Serial Interface (SSI)
+	  support for the Freescale CPUs.
+	  This option is only useful for out-of-tree drivers since
+	  in-tree drivers select it automatically.
 
 config SND_SOC_FSL_SPDIF
-	tristate
+	tristate "Sony/Philips Digital Interface module support"
 	select REGMAP_MMIO
+	help
+	  Say Y if you want to add Sony/Philips Digital Interface (SPDIF)
+	  support for the Freescale CPUs.
+	  This option is only useful for out-of-tree drivers since
+	  in-tree drivers select it automatically.
 
 config SND_SOC_FSL_ESAI
 	tristate
@@ -18,13 +32,32 @@ config SND_SOC_FSL_ESAI
 config SND_SOC_FSL_UTILS
 	tristate
 
-menuconfig SND_POWERPC_SOC
+config SND_SOC_IMX_PCM_DMA
+	tristate
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+
+config SND_SOC_IMX_AUDMUX
+	tristate "Digital Audio Mux module support"
+	help
+	  Say Y if you want to add Digital Audio Mux (AUDMUX) support
+	  for the ARM i.MX CPUs.
+	  This option is only useful for out-of-tree drivers since
+	  in-tree drivers select it automatically.
+
+config SND_POWERPC_SOC
 	tristate "SoC Audio for Freescale PowerPC CPUs"
 	depends on FSL_SOC || PPC_MPC52xx
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the PowerPC CPUs.
 
+config SND_IMX_SOC
+	tristate "SoC Audio for Freescale i.MX CPUs"
+	depends on ARCH_MXC || COMPILE_TEST
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the i.MX CPUs.
+
 if SND_POWERPC_SOC
 
 config SND_MPC52xx_DMA
@@ -33,6 +66,8 @@ config SND_MPC52xx_DMA
 config SND_SOC_POWERPC_DMA
 	tristate
 
+comment "SoC Audio support for Freescale PPC boards:"
+
 config SND_SOC_MPC8610_HPCD
 	tristate "ALSA SoC support for the Freescale MPC8610 HPCD board"
 	# I2C is necessary for the CS4270 driver
@@ -110,13 +145,6 @@ config SND_MPC52xx_SOC_EFIKA
 
 endif # SND_POWERPC_SOC
 
-menuconfig SND_IMX_SOC
-	tristate "SoC Audio for Freescale i.MX CPUs"
-	depends on ARCH_MXC || COMPILE_TEST
-	help
-	  Say Y or M if you want to add support for codecs attached to
-	  the i.MX CPUs.
-
 if SND_IMX_SOC
 
 config SND_SOC_IMX_SSI
@@ -127,12 +155,7 @@ config SND_SOC_IMX_PCM_FIQ
 	tristate
 	select FIQ
 
-config SND_SOC_IMX_PCM_DMA
-	tristate
-	select SND_SOC_GENERIC_DMAENGINE_PCM
-
-config SND_SOC_IMX_AUDMUX
-	tristate
+comment "SoC Audio support for Freescale i.MX boards:"
 
 config SND_MXC_SOC_WM1133_EV1
 	tristate "Audio on the i.MX31ADS with WM1133-EV1 fitted"
@@ -225,3 +248,5 @@ config SND_SOC_IMX_MC13783
 	select SND_SOC_IMX_PCM_DMA
 
 endif # SND_IMX_SOC
+
+endmenu
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index c8e5db1414d7..b49b78df2f5b 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -209,8 +209,9 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
 	struct clk *clksrc = esai_priv->extalclk;
 	bool tx = clk_id <= ESAI_HCKT_EXTAL;
 	bool in = dir == SND_SOC_CLOCK_IN;
-	u32 ret, ratio, ecr = 0;
+	u32 ratio, ecr = 0;
 	unsigned long clk_rate;
+	int ret;
 
 	/* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
 	esai_priv->sck_div[tx] = true;
@@ -432,8 +433,8 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static int fsl_esai_startup(struct snd_pcm_substream *substream,
 			    struct snd_soc_dai *dai)
 {
-	int ret;
 	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+	int ret;
 
 	/*
 	 * Some platforms might use the same bit to gate all three or two of
@@ -491,7 +492,8 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	u32 width = snd_pcm_format_width(params_format(params));
 	u32 channels = params_channels(params);
-	u32 bclk, mask, val, ret;
+	u32 bclk, mask, val;
+	int ret;
 
 	bclk = params_rate(params) * esai_priv->slot_width * 2;
 
@@ -816,6 +818,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
 
 static const struct of_device_id fsl_esai_dt_ids[] = {
 	{ .compatible = "fsl,imx35-esai", },
+	{ .compatible = "fsl,vf610-esai", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 56da8c8c5960..c5a0e8af8226 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -22,6 +22,7 @@
 #include <sound/pcm_params.h>
 
 #include "fsl_sai.h"
+#include "imx-pcm.h"
 
 #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
 		       FSL_SAI_CSR_FEIE)
@@ -30,78 +31,96 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
 {
 	struct fsl_sai *sai = (struct fsl_sai *)devid;
 	struct device *dev = &sai->pdev->dev;
-	u32 xcsr, mask;
+	u32 flags, xcsr, mask;
+	bool irq_none = true;
 
-	/* Only handle those what we enabled */
+	/*
+	 * Both IRQ status bits and IRQ mask bits are in the xCSR but
+	 * different shifts. And we here create a mask only for those
+	 * IRQs that we activated.
+	 */
 	mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
 
 	/* Tx IRQ */
 	regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
-	xcsr &= mask;
+	flags = xcsr & mask;
+
+	if (flags)
+		irq_none = false;
+	else
+		goto irq_rx;
 
-	if (xcsr & FSL_SAI_CSR_WSF)
+	if (flags & FSL_SAI_CSR_WSF)
 		dev_dbg(dev, "isr: Start of Tx word detected\n");
 
-	if (xcsr & FSL_SAI_CSR_SEF)
+	if (flags & FSL_SAI_CSR_SEF)
 		dev_warn(dev, "isr: Tx Frame sync error detected\n");
 
-	if (xcsr & FSL_SAI_CSR_FEF) {
+	if (flags & FSL_SAI_CSR_FEF) {
 		dev_warn(dev, "isr: Transmit underrun detected\n");
 		/* FIFO reset for safety */
 		xcsr |= FSL_SAI_CSR_FR;
 	}
 
-	if (xcsr & FSL_SAI_CSR_FWF)
+	if (flags & FSL_SAI_CSR_FWF)
 		dev_dbg(dev, "isr: Enabled transmit FIFO is empty\n");
 
-	if (xcsr & FSL_SAI_CSR_FRF)
+	if (flags & FSL_SAI_CSR_FRF)
 		dev_dbg(dev, "isr: Transmit FIFO watermark has been reached\n");
 
-	regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
-			   FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
+	flags &= FSL_SAI_CSR_xF_W_MASK;
+	xcsr &= ~FSL_SAI_CSR_xF_MASK;
+
+	if (flags)
+		regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
 
+irq_rx:
 	/* Rx IRQ */
 	regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
-	xcsr &= mask;
+	flags = xcsr & mask;
 
-	if (xcsr & FSL_SAI_CSR_WSF)
+	if (flags)
+		irq_none = false;
+	else
+		goto out;
+
+	if (flags & FSL_SAI_CSR_WSF)
 		dev_dbg(dev, "isr: Start of Rx word detected\n");
 
-	if (xcsr & FSL_SAI_CSR_SEF)
+	if (flags & FSL_SAI_CSR_SEF)
 		dev_warn(dev, "isr: Rx Frame sync error detected\n");
 
-	if (xcsr & FSL_SAI_CSR_FEF) {
+	if (flags & FSL_SAI_CSR_FEF) {
 		dev_warn(dev, "isr: Receive overflow detected\n");
 		/* FIFO reset for safety */
 		xcsr |= FSL_SAI_CSR_FR;
 	}
 
-	if (xcsr & FSL_SAI_CSR_FWF)
+	if (flags & FSL_SAI_CSR_FWF)
 		dev_dbg(dev, "isr: Enabled receive FIFO is full\n");
 
-	if (xcsr & FSL_SAI_CSR_FRF)
+	if (flags & FSL_SAI_CSR_FRF)
 		dev_dbg(dev, "isr: Receive FIFO watermark has been reached\n");
 
-	regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
-			   FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
+	flags &= FSL_SAI_CSR_xF_W_MASK;
+	xcsr &= ~FSL_SAI_CSR_xF_MASK;
+
+	if (flags)
+		regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
 
-	return IRQ_HANDLED;
+out:
+	if (irq_none)
+		return IRQ_NONE;
+	else
+		return IRQ_HANDLED;
 }
 
 static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
 		int clk_id, unsigned int freq, int fsl_dir)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 val_cr2, reg_cr2;
-
-	if (fsl_dir == FSL_FMT_TRANSMITTER)
-		reg_cr2 = FSL_SAI_TCR2;
-	else
-		reg_cr2 = FSL_SAI_RCR2;
-
-	regmap_read(sai->regmap, reg_cr2, &val_cr2);
-
-	val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
+	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
+	u32 val_cr2 = 0;
 
 	switch (clk_id) {
 	case FSL_SAI_CLK_BUS:
@@ -120,7 +139,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
 		return -EINVAL;
 	}
 
-	regmap_write(sai->regmap, reg_cr2, val_cr2);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+			   FSL_SAI_CR2_MSEL_MASK, val_cr2);
 
 	return 0;
 }
@@ -152,22 +172,10 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 				unsigned int fmt, int fsl_dir)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 val_cr2, val_cr4, reg_cr2, reg_cr4;
-
-	if (fsl_dir == FSL_FMT_TRANSMITTER) {
-		reg_cr2 = FSL_SAI_TCR2;
-		reg_cr4 = FSL_SAI_TCR4;
-	} else {
-		reg_cr2 = FSL_SAI_RCR2;
-		reg_cr4 = FSL_SAI_RCR4;
-	}
+	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
+	u32 val_cr2 = 0, val_cr4 = 0;
 
-	regmap_read(sai->regmap, reg_cr2, &val_cr2);
-	regmap_read(sai->regmap, reg_cr4, &val_cr4);
-
-	if (sai->big_endian_data)
-		val_cr4 &= ~FSL_SAI_CR4_MF;
-	else
+	if (!sai->big_endian_data)
 		val_cr4 |= FSL_SAI_CR4_MF;
 
 	/* DAI mode */
@@ -188,7 +196,6 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		 * frame sync asserts with the first bit of the frame.
 		 */
 		val_cr2 |= FSL_SAI_CR2_BCP;
-		val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
 		/*
@@ -198,7 +205,6 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		 * data word.
 		 */
 		val_cr2 |= FSL_SAI_CR2_BCP;
-		val_cr4 &= ~FSL_SAI_CR4_FSP;
 		val_cr4 |= FSL_SAI_CR4_FSE;
 		sai->is_dsp_mode = true;
 		break;
@@ -208,7 +214,6 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		 * frame sync asserts with the first bit of the frame.
 		 */
 		val_cr2 |= FSL_SAI_CR2_BCP;
-		val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
 		sai->is_dsp_mode = true;
 		break;
 	case SND_SOC_DAIFMT_RIGHT_J:
@@ -246,23 +251,22 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
 		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
-		val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
-		val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
 		break;
 	case SND_SOC_DAIFMT_CBS_CFM:
 		val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
-		val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
 		break;
 	case SND_SOC_DAIFMT_CBM_CFS:
-		val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
 		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	regmap_write(sai->regmap, reg_cr2, val_cr2);
-	regmap_write(sai->regmap, reg_cr4, val_cr4);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+			   FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+			   FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
+			   FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
 
 	return 0;
 }
@@ -289,29 +293,10 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	unsigned int channels = params_channels(params);
 	u32 word_width = snd_pcm_format_width(params_format(params));
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		reg_cr4 = FSL_SAI_TCR4;
-		reg_cr5 = FSL_SAI_TCR5;
-		reg_mr = FSL_SAI_TMR;
-	} else {
-		reg_cr4 = FSL_SAI_RCR4;
-		reg_cr5 = FSL_SAI_RCR5;
-		reg_mr = FSL_SAI_RMR;
-	}
-
-	regmap_read(sai->regmap, reg_cr4, &val_cr4);
-	regmap_read(sai->regmap, reg_cr4, &val_cr5);
-
-	val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK;
-	val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK;
-
-	val_cr5 &= ~FSL_SAI_CR5_WNW_MASK;
-	val_cr5 &= ~FSL_SAI_CR5_W0W_MASK;
-	val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
+	u32 val_cr4 = 0, val_cr5 = 0;
 
 	if (!sai->is_dsp_mode)
 		val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
@@ -319,18 +304,20 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 	val_cr5 |= FSL_SAI_CR5_WNW(word_width);
 	val_cr5 |= FSL_SAI_CR5_W0W(word_width);
 
-	val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
 	if (sai->big_endian_data)
 		val_cr5 |= FSL_SAI_CR5_FBT(0);
 	else
 		val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
 
 	val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
-	val_mr = ~0UL - ((1 << channels) - 1);
 
-	regmap_write(sai->regmap, reg_cr4, val_cr4);
-	regmap_write(sai->regmap, reg_cr5, val_cr5);
-	regmap_write(sai->regmap, reg_mr, val_mr);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+			   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
+			   val_cr4);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx),
+			   FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
+			   FSL_SAI_CR5_FBT_MASK, val_cr5);
+	regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
 
 	return 0;
 }
@@ -339,6 +326,7 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	u32 tcsr, rcsr;
 
 	/*
@@ -353,14 +341,6 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 	regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr);
 	regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		tcsr |= FSL_SAI_CSR_FRDE;
-		rcsr &= ~FSL_SAI_CSR_FRDE;
-	} else {
-		rcsr |= FSL_SAI_CSR_FRDE;
-		tcsr &= ~FSL_SAI_CSR_FRDE;
-	}
-
 	/*
 	 * It is recommended that the transmitter is the last enabled
 	 * and the first disabled.
@@ -369,22 +349,33 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		tcsr |= FSL_SAI_CSR_TERE;
-		rcsr |= FSL_SAI_CSR_TERE;
+		if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) {
+			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+					   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
+			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+					   FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
+		}
 
-		regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
-		regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+				   FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+				   FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (!(cpu_dai->playback_active || cpu_dai->capture_active)) {
-			tcsr &= ~FSL_SAI_CSR_TERE;
-			rcsr &= ~FSL_SAI_CSR_TERE;
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+				   FSL_SAI_CSR_FRDE, 0);
+		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+				   FSL_SAI_CSR_xIE_MASK, 0);
+
+		/* Check if the opposite FRDE is also disabled */
+		if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) {
+			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+					   FSL_SAI_CSR_TERE, 0);
+			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+					   FSL_SAI_CSR_TERE, 0);
 		}
-
-		regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
-		regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
 		break;
 	default:
 		return -EINVAL;
@@ -397,14 +388,17 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 reg;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+	struct device *dev = &sai->pdev->dev;
+	int ret;
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		reg = FSL_SAI_TCR3;
-	else
-		reg = FSL_SAI_RCR3;
+	ret = clk_prepare_enable(sai->bus_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable bus clock: %d\n", ret);
+		return ret;
+	}
 
-	regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE,
 			   FSL_SAI_CR3_TRCE);
 
 	return 0;
@@ -414,15 +408,11 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 reg;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		reg = FSL_SAI_TCR3;
-	else
-		reg = FSL_SAI_RCR3;
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0);
 
-	regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
-			   ~FSL_SAI_CR3_TRCE);
+	clk_disable_unprepare(sai->bus_clk);
 }
 
 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
@@ -438,8 +428,8 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
 
-	regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, FSL_SAI_FLAGS);
-	regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, FSL_SAI_FLAGS);
+	regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0);
+	regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0);
 	regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
 			   FSL_SAI_MAXBURST_TX * 2);
 	regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
@@ -555,7 +545,8 @@ static int fsl_sai_probe(struct platform_device *pdev)
 	struct fsl_sai *sai;
 	struct resource *res;
 	void __iomem *base;
-	int irq, ret;
+	char tmp[8];
+	int irq, ret, i;
 
 	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
 	if (!sai)
@@ -563,6 +554,9 @@ static int fsl_sai_probe(struct platform_device *pdev)
 
 	sai->pdev = pdev;
 
+	if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx6sx-sai"))
+		sai->sai_on_imx = true;
+
 	sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
 	if (sai->big_endian_regs)
 		fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
@@ -575,12 +569,35 @@ static int fsl_sai_probe(struct platform_device *pdev)
 		return PTR_ERR(base);
 
 	sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
-			"sai", base, &fsl_sai_regmap_config);
+			"bus", base, &fsl_sai_regmap_config);
+
+	/* Compatible with old DTB cases */
+	if (IS_ERR(sai->regmap))
+		sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+				"sai", base, &fsl_sai_regmap_config);
 	if (IS_ERR(sai->regmap)) {
 		dev_err(&pdev->dev, "regmap init failed\n");
 		return PTR_ERR(sai->regmap);
 	}
 
+	/* No error out for old DTB cases but only mark the clock NULL */
+	sai->bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(sai->bus_clk)) {
+		dev_err(&pdev->dev, "failed to get bus clock: %ld\n",
+				PTR_ERR(sai->bus_clk));
+		sai->bus_clk = NULL;
+	}
+
+	for (i = 0; i < FSL_SAI_MCLK_MAX; i++) {
+		sprintf(tmp, "mclk%d", i + 1);
+		sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp);
+		if (IS_ERR(sai->mclk_clk[i])) {
+			dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n",
+					i + 1, PTR_ERR(sai->mclk_clk[i]));
+			sai->mclk_clk[i] = NULL;
+		}
+	}
+
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
@@ -605,12 +622,16 @@ static int fsl_sai_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
-			SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
+	if (sai->sai_on_imx)
+		return imx_pcm_dma_init(pdev);
+	else
+		return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
+				SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
 }
 
 static const struct of_device_id fsl_sai_ids[] = {
 	{ .compatible = "fsl,vf610-sai", },
+	{ .compatible = "fsl,imx6sx-sai", },
 	{ /* sentinel */ }
 };
 
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index a264185c7138..0e6c9f595d75 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -35,6 +35,16 @@
 #define FSL_SAI_RFR	0xc0 /* SAI Receive FIFO */
 #define FSL_SAI_RMR	0xe0 /* SAI Receive Mask */
 
+#define FSL_SAI_xCSR(tx)	(tx ? FSL_SAI_TCSR : FSL_SAI_RCSR)
+#define FSL_SAI_xCR1(tx)	(tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1)
+#define FSL_SAI_xCR2(tx)	(tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2)
+#define FSL_SAI_xCR3(tx)	(tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3)
+#define FSL_SAI_xCR4(tx)	(tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4)
+#define FSL_SAI_xCR5(tx)	(tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5)
+#define FSL_SAI_xDR(tx)		(tx ? FSL_SAI_TDR : FSL_SAI_RDR)
+#define FSL_SAI_xFR(tx)		(tx ? FSL_SAI_TFR : FSL_SAI_RFR)
+#define FSL_SAI_xMR(tx)		(tx ? FSL_SAI_TMR : FSL_SAI_RMR)
+
 /* SAI Transmit/Recieve Control Register */
 #define FSL_SAI_CSR_TERE	BIT(31)
 #define FSL_SAI_CSR_FR		BIT(25)
@@ -48,6 +58,7 @@
 #define FSL_SAI_CSR_FWF		BIT(17)
 #define FSL_SAI_CSR_FRF		BIT(16)
 #define FSL_SAI_CSR_xIE_SHIFT	8
+#define FSL_SAI_CSR_xIE_MASK	(0x1f << FSL_SAI_CSR_xIE_SHIFT)
 #define FSL_SAI_CSR_WSIE	BIT(12)
 #define FSL_SAI_CSR_SEIE	BIT(11)
 #define FSL_SAI_CSR_FEIE	BIT(10)
@@ -108,6 +119,8 @@
 #define FSL_SAI_CLK_MAST2	2
 #define FSL_SAI_CLK_MAST3	3
 
+#define FSL_SAI_MCLK_MAX	3
+
 /* SAI data transfer numbers per DMA request */
 #define FSL_SAI_MAXBURST_TX 6
 #define FSL_SAI_MAXBURST_RX 6
@@ -115,10 +128,13 @@
 struct fsl_sai {
 	struct platform_device *pdev;
 	struct regmap *regmap;
+	struct clk *bus_clk;
+	struct clk *mclk_clk[FSL_SAI_MCLK_MAX];
 
 	bool big_endian_regs;
 	bool big_endian_data;
 	bool is_dsp_mode;
+	bool sai_on_imx;
 
 	struct snd_dmaengine_dai_dma_data dma_params_rx;
 	struct snd_dmaengine_dai_dma_data dma_params_tx;
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 6452ca83d889..daa6198ae41f 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -13,18 +13,18 @@
  * kind, whether express or implied.
  */
 
-#include <linux/module.h>
+#include <linux/bitrev.h>
 #include <linux/clk.h>
 #include <linux/clk-private.h>
-#include <linux/bitrev.h>
-#include <linux/regmap.h>
+#include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/regmap.h>
 
 #include <sound/asoundef.h>
-#include <sound/soc.h>
 #include <sound/dmaengine_pcm.h>
+#include <sound/soc.h>
 
 #include "fsl_spdif.h"
 #include "imx-pcm.h"
@@ -1186,6 +1186,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
 
 static const struct of_device_id fsl_spdif_dt_ids[] = {
 	{ .compatible = "fsl,imx35-spdif", },
+	{ .compatible = "fsl,vf610-spdif", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids);
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 5428a1fda260..25865d8f2efd 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -40,6 +40,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
@@ -642,96 +643,6 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
 	write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
 }
 
-static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
-{
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-	u8 wm;
-	int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
-
-	fsl_ssi_setup_reg_vals(ssi_private);
-
-	if (ssi_private->imx_ac97)
-		ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
-	else
-		ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
-
-	/*
-	 * Section 16.5 of the MPC8610 reference manual says that the SSI needs
-	 * to be disabled before updating the registers we set here.
-	 */
-	write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
-
-	/*
-	 * Program the SSI into I2S Slave Non-Network Synchronous mode. Also
-	 * enable the transmit and receive FIFO.
-	 *
-	 * FIXME: Little-endian samples require a different shift dir
-	 */
-	write_ssi_mask(&ssi->scr,
-		CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
-		CCSR_SSI_SCR_TFR_CLK_DIS |
-		ssi_private->i2s_mode |
-		(synchronous ? CCSR_SSI_SCR_SYN : 0));
-
-	write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFSI |
-			CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr);
-
-	write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFSI |
-			CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
-
-	/*
-	 * The DC and PM bits are only used if the SSI is the clock master.
-	 */
-
-	/*
-	 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
-	 * use FIFO 1. We program the transmit water to signal a DMA transfer
-	 * if there are only two (or fewer) elements left in the FIFO. Two
-	 * elements equals one frame (left channel, right channel). This value,
-	 * however, depends on the depth of the transmit buffer.
-	 *
-	 * We set the watermark on the same level as the DMA burstsize.  For
-	 * fiq it is probably better to use the biggest possible watermark
-	 * size.
-	 */
-	if (ssi_private->use_dma)
-		wm = ssi_private->fifo_depth - 2;
-	else
-		wm = ssi_private->fifo_depth;
-
-	write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
-		CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm),
-		&ssi->sfcsr);
-
-	/*
-	 * For ac97 interrupts are enabled with the startup of the substream
-	 * because it is also running without an active substream. Normally SSI
-	 * is only enabled when there is a substream.
-	 */
-	if (ssi_private->imx_ac97)
-		fsl_ssi_setup_ac97(ssi_private);
-
-	/*
-	 * Set a default slot number so that there is no need for those common
-	 * cases like I2S mode to call the extra set_tdm_slot() any more.
-	 */
-	if (!ssi_private->imx_ac97) {
-		write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
-				CCSR_SSI_SxCCR_DC(2));
-		write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
-				CCSR_SSI_SxCCR_DC(2));
-	}
-
-	if (ssi_private->use_dual_fifo) {
-		write_ssi_mask(&ssi->srcr, 0, CCSR_SSI_SRCR_RFEN1);
-		write_ssi_mask(&ssi->stcr, 0, CCSR_SSI_STCR_TFEN1);
-		write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_TCH_EN);
-	}
-
-	return 0;
-}
-
-
 /**
  * fsl_ssi_startup: create a new substream
  *
@@ -748,12 +659,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
 		snd_soc_dai_get_drvdata(rtd->cpu_dai);
 	unsigned long flags;
 
-	/* First, we only do fsl_ssi_setup() when SSI is going to be active.
-	 * Second, fsl_ssi_setup was already called by ac97_init earlier if
-	 * the driver is in ac97 mode.
-	 */
 	if (!dai->active && !ssi_private->imx_ac97) {
-		fsl_ssi_setup(ssi_private);
 		spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
 		ssi_private->baudclk_locked = false;
 		spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
@@ -835,9 +741,11 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
 	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
 	u32 strcr = 0, stcr, srcr, scr, mask;
+	u8 wm;
+
+	fsl_ssi_setup_reg_vals(ssi_private);
 
 	scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
-	scr |= CCSR_SSI_SCR_NET;
 
 	mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
 		CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
@@ -845,19 +753,19 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 	stcr = read_ssi(&ssi->stcr) & ~mask;
 	srcr = read_ssi(&ssi->srcr) & ~mask;
 
+	ssi_private->i2s_mode = CCSR_SSI_SCR_NET;
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
 		switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 		case SND_SOC_DAIFMT_CBS_CFS:
-			ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_MASTER;
+			ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_MASTER;
 			break;
 		case SND_SOC_DAIFMT_CBM_CFM:
-			ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
+			ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_SLAVE;
 			break;
 		default:
 			return -EINVAL;
 		}
-		scr |= ssi_private->i2s_mode;
 
 		/* Data on rising edge of bclk, frame low, 1clk before data */
 		strcr |= CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TSCKP |
@@ -877,9 +785,13 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 		strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
 			CCSR_SSI_STCR_TXBIT0;
 		break;
+	case SND_SOC_DAIFMT_AC97:
+		ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_NORMAL;
+		break;
 	default:
 		return -EINVAL;
 	}
+	scr |= ssi_private->i2s_mode;
 
 	/* DAI clock inversion */
 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -929,6 +841,38 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 	write_ssi(srcr, &ssi->srcr);
 	write_ssi(scr, &ssi->scr);
 
+	/*
+	 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
+	 * use FIFO 1. We program the transmit water to signal a DMA transfer
+	 * if there are only two (or fewer) elements left in the FIFO. Two
+	 * elements equals one frame (left channel, right channel). This value,
+	 * however, depends on the depth of the transmit buffer.
+	 *
+	 * We set the watermark on the same level as the DMA burstsize.  For
+	 * fiq it is probably better to use the biggest possible watermark
+	 * size.
+	 */
+	if (ssi_private->use_dma)
+		wm = ssi_private->fifo_depth - 2;
+	else
+		wm = ssi_private->fifo_depth;
+
+	write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
+			CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm),
+			&ssi->sfcsr);
+
+	if (ssi_private->use_dual_fifo) {
+		write_ssi_mask(&ssi->srcr, CCSR_SSI_SRCR_RFEN1,
+				CCSR_SSI_SRCR_RFEN1);
+		write_ssi_mask(&ssi->stcr, CCSR_SSI_STCR_TFEN1,
+				CCSR_SSI_STCR_TFEN1);
+		write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TCH_EN,
+				CCSR_SSI_SCR_TCH_EN);
+	}
+
+	if (fmt & SND_SOC_DAIFMT_AC97)
+		fsl_ssi_setup_ac97(ssi_private);
+
 	return 0;
 }
 
@@ -1184,11 +1128,6 @@ static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
 
 static struct fsl_ssi_private *fsl_ac97_data;
 
-static void fsl_ssi_ac97_init(void)
-{
-	fsl_ssi_setup(fsl_ac97_data);
-}
-
 static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 		unsigned short val)
 {
@@ -1547,9 +1486,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 	}
 
 done:
-	if (ssi_private->imx_ac97)
-		fsl_ssi_ac97_init();
-
 	return 0;
 
 error_dai:
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c
index f7687107cf7f..f24619adc3d1 100644
--- a/sound/soc/intel/sst-firmware.c
+++ b/sound/soc/intel/sst-firmware.c
@@ -505,9 +505,7 @@ struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp)
 
 	/* calculate required scratch size */
 	list_for_each_entry(sst_module, &dsp->module_list, list) {
-		if (scratch->s.size > sst_module->s.size)
-			scratch->s.size = scratch->s.size;
-		else
+		if (scratch->s.size < sst_module->s.size)
 			scratch->s.size = sst_module->s.size;
 	}
 
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index f46bb4ddde6f..455a1857c441 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -991,7 +991,8 @@ int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream
 		return -EINVAL;
 
 	sst_dsp_read(hsw->dsp, volume,
-		stream->reply.volume_register_address[channel], sizeof(volume));
+		stream->reply.volume_register_address[channel],
+		sizeof(*volume));
 
 	return 0;
 }
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index 0a32dd13a23d..67a5eb3c6196 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -136,7 +136,7 @@ static inline unsigned int hsw_ipc_to_mixer(u32 value)
 static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct hsw_priv_data *pdata =
@@ -174,7 +174,7 @@ static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol,
 static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct hsw_priv_data *pdata =
@@ -206,7 +206,7 @@ static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol,
 static int hsw_volume_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
 	struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
 	struct sst_hsw *hsw = pdata->hsw;
 	u32 volume;
@@ -231,7 +231,7 @@ static int hsw_volume_put(struct snd_kcontrol *kcontrol,
 static int hsw_volume_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
 	struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
 	struct sst_hsw *hsw = pdata->hsw;
 	unsigned int volume = 0;
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 56a5219c0a00..2ac0a0c3b570 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -38,7 +38,6 @@
 #include "omap-mcbsp.h"
 #include "../codecs/cx20442.h"
 
-
 /* Board specific DAPM widgets */
 static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
 	/* Handset */
@@ -90,17 +89,23 @@ static const unsigned short ams_delta_audio_mode_pins[] = {
 
 static unsigned short ams_delta_audio_agc;
 
+/*
+ * Used for passing a codec structure pointer
+ * from the board initialization code to the tty line discipline.
+ */
+static struct snd_soc_codec *cx20442_codec;
+
 static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_context *dapm = &card->dapm;
 	struct soc_enum *control = (struct soc_enum *)kcontrol->private_value;
 	unsigned short pins;
 	int pin, changed = 0;
 
 	/* Refuse any mode changes if we are not able to control the codec. */
-	if (!codec->hw_write)
+	if (!cx20442_codec->hw_write)
 		return -EUNATCH;
 
 	if (ucontrol->value.enumerated.item[0] >= control->items)
@@ -166,8 +171,8 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
 static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_context *dapm = &card->dapm;
 	unsigned short pins, mode;
 
 	pins = ((snd_soc_dapm_get_pin_status(dapm, "Mouthpiece") <<
@@ -270,12 +275,6 @@ static void cx81801_timeout(unsigned long data)
 		ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
 }
 
-/*
- * Used for passing a codec structure pointer
- * from the board initialization code to the tty line discipline.
- */
-static struct snd_soc_codec *cx20442_codec;
-
 /* Line discipline .open() */
 static int cx81801_open(struct tty_struct *tty)
 {
@@ -302,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty)
 static void cx81801_close(struct tty_struct *tty)
 {
 	struct snd_soc_codec *codec = tty->disc_data;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dapm_context *dapm = &codec->card->dapm;
 
 	del_timer_sync(&cx81801_timer);
 
@@ -475,15 +474,14 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream)
 
 static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_card *card = rtd->card;
+	struct snd_soc_dapm_context *dapm = &card->dapm;
 	int ret;
 	/* Codec is ready, now add/activate board specific controls */
 
 	/* Store a pointer to the codec structure for tty ldisc use */
-	cx20442_codec = codec;
+	cx20442_codec = rtd->codec;
 
 	/* Set up digital mute if not provided by the codec */
 	if (!codec_dai->driver->ops) {
@@ -520,25 +518,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
 		return 0;
 	}
 
-	/* Add board specific DAPM widgets and routes */
-	ret = snd_soc_dapm_new_controls(dapm, ams_delta_dapm_widgets,
-					ARRAY_SIZE(ams_delta_dapm_widgets));
-	if (ret) {
-		dev_warn(card->dev,
-				"Failed to register DAPM controls, "
-				"will continue without any.\n");
-		return 0;
-	}
-
-	ret = snd_soc_dapm_add_routes(dapm, ams_delta_audio_map,
-					ARRAY_SIZE(ams_delta_audio_map));
-	if (ret) {
-		dev_warn(card->dev,
-				"Failed to set up DAPM routes, "
-				"will continue with codec default map.\n");
-		return 0;
-	}
-
 	/* Set up initial pin constellation */
 	snd_soc_dapm_disable_pin(dapm, "Mouthpiece");
 	snd_soc_dapm_enable_pin(dapm, "Earpiece");
@@ -547,14 +526,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_disable_pin(dapm, "AGCIN");
 	snd_soc_dapm_disable_pin(dapm, "AGCOUT");
 
-	/* Add virtual switch */
-	ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls,
-					ARRAY_SIZE(ams_delta_audio_controls));
-	if (ret)
-		dev_warn(card->dev,
-				"Failed to register audio mode control, "
-				"will continue without it.\n");
-
 	return 0;
 }
 
@@ -576,6 +547,13 @@ static struct snd_soc_card ams_delta_audio_card = {
 	.owner = THIS_MODULE,
 	.dai_link = &ams_delta_dai_link,
 	.num_links = 1,
+
+	.controls = ams_delta_audio_controls,
+	.num_controls = ARRAY_SIZE(ams_delta_audio_controls),
+	.dapm_widgets = ams_delta_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(ams_delta_dapm_widgets),
+	.dapm_routes = ams_delta_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(ams_delta_audio_map),
 };
 
 /* Module init/exit */
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index cf604a2faa18..02181bb70400 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -121,7 +121,7 @@ static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
  *  |A| <~~clk~~+
  *  |P| <--- TWL4030 <--------- Line In and MICs
  */
-static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget omap3pandora_dapm_widgets[] = {
 	SND_SOC_DAPM_DAC_E("PCM DAC", "HiFi Playback", SND_SOC_NOPM,
 			   0, 0, omap3pandora_dac_event,
 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -130,22 +130,18 @@ static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
 	SND_SOC_DAPM_LINE("Line Out", NULL),
-};
 
-static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Mic (internal)", NULL),
 	SND_SOC_DAPM_MIC("Mic (external)", NULL),
 	SND_SOC_DAPM_LINE("Line In", NULL),
 };
 
-static const struct snd_soc_dapm_route omap3pandora_out_map[] = {
+static const struct snd_soc_dapm_route omap3pandora_map[] = {
 	{"PCM DAC", NULL, "APLL Enable"},
 	{"Headphone Amplifier", NULL, "PCM DAC"},
 	{"Line Out", NULL, "PCM DAC"},
 	{"Headphone Jack", NULL, "Headphone Amplifier"},
-};
 
-static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
 	{"AUXL", NULL, "Line In"},
 	{"AUXR", NULL, "Line In"},
 
@@ -160,7 +156,6 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int ret;
 
 	/* All TWL4030 output pins are floating */
 	snd_soc_dapm_nc_pin(dapm, "EARPIECE");
@@ -174,20 +169,13 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "HFR");
 	snd_soc_dapm_nc_pin(dapm, "VIBRA");
 
-	ret = snd_soc_dapm_new_controls(dapm, omap3pandora_out_dapm_widgets,
-				ARRAY_SIZE(omap3pandora_out_dapm_widgets));
-	if (ret < 0)
-		return ret;
-
-	return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
-		ARRAY_SIZE(omap3pandora_out_map));
+	return 0;
 }
 
 static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int ret;
 
 	/* Not comnnected */
 	snd_soc_dapm_nc_pin(dapm, "HSMIC");
@@ -195,13 +183,7 @@ static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "DIGIMIC0");
 	snd_soc_dapm_nc_pin(dapm, "DIGIMIC1");
 
-	ret = snd_soc_dapm_new_controls(dapm, omap3pandora_in_dapm_widgets,
-				ARRAY_SIZE(omap3pandora_in_dapm_widgets));
-	if (ret < 0)
-		return ret;
-
-	return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
-		ARRAY_SIZE(omap3pandora_in_map));
+	return 0;
 }
 
 static struct snd_soc_ops omap3pandora_ops = {
@@ -241,6 +223,11 @@ static struct snd_soc_card snd_soc_card_omap3pandora = {
 	.owner = THIS_MODULE,
 	.dai_link = omap3pandora_dai,
 	.num_links = ARRAY_SIZE(omap3pandora_dai),
+
+	.dapm_widgets = omap3pandora_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(omap3pandora_dapm_widgets),
+	.dapm_routes = omap3pandora_map,
+	.num_dapm_routes = ARRAY_SIZE(omap3pandora_map),
 };
 
 static struct platform_device *omap3pandora_snd_device;
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 7fb3d4b10370..2b4641123142 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -237,9 +237,6 @@ static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
 	SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event),
 	SND_SOC_DAPM_MIC("HS Mic", NULL),
 	SND_SOC_DAPM_LINE("FM Transmitter", NULL),
-};
-
-static const struct snd_soc_dapm_widget aic34_dapm_widgetsb[] = {
 	SND_SOC_DAPM_SPK("Earphone", NULL),
 };
 
@@ -253,9 +250,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
 
 	{"DMic Rate 64", NULL, "Mic Bias"},
 	{"Mic Bias", NULL, "DMic"},
-};
 
-static const struct snd_soc_dapm_route audio_mapb[] = {
 	{"b LINE2R", NULL, "MONO_LOUT"},
 	{"Earphone", NULL, "b HPLOUT"},
 
@@ -281,9 +276,6 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
 	SOC_ENUM_EXT("Jack Function", rx51_enum[2],
 		     rx51_get_jack, rx51_set_jack),
 	SOC_DAPM_PIN_SWITCH("FM Transmitter"),
-};
-
-static const struct snd_kcontrol_new aic34_rx51_controlsb[] = {
 	SOC_DAPM_PIN_SWITCH("Earphone"),
 };
 
@@ -298,19 +290,6 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "MIC3R");
 	snd_soc_dapm_nc_pin(dapm, "LINE1R");
 
-	/* Add RX-51 specific controls */
-	err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls,
-				   ARRAY_SIZE(aic34_rx51_controls));
-	if (err < 0)
-		return err;
-
-	/* Add RX-51 specific widgets */
-	snd_soc_dapm_new_controls(dapm, aic34_dapm_widgets,
-				  ARRAY_SIZE(aic34_dapm_widgets));
-
-	/* Set up RX-51 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
 	err = tpa6130a2_add_controls(codec);
 	if (err < 0)
 		return err;
@@ -333,24 +312,6 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	return err;
 }
 
-static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
-{
-	int err;
-
-	err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb,
-				   ARRAY_SIZE(aic34_rx51_controlsb));
-	if (err < 0)
-		return err;
-
-	err = snd_soc_dapm_new_controls(dapm, aic34_dapm_widgetsb,
-					ARRAY_SIZE(aic34_dapm_widgetsb));
-	if (err < 0)
-		return 0;
-
-	return snd_soc_dapm_add_routes(dapm, audio_mapb,
-				       ARRAY_SIZE(audio_mapb));
-}
-
 /* Digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link rx51_dai[] = {
 	{
@@ -371,7 +332,6 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = {
 	{
 		.name = "TLV320AIC34b",
 		.codec_name = "tlv320aic3x-codec.2-0019",
-		.init = rx51_aic34b_init,
 	},
 };
 
@@ -392,6 +352,13 @@ static struct snd_soc_card rx51_sound_card = {
 	.num_aux_devs = ARRAY_SIZE(rx51_aux_dev),
 	.codec_conf = rx51_codec_conf,
 	.num_configs = ARRAY_SIZE(rx51_codec_conf),
+
+	.controls = aic34_rx51_controls,
+	.num_controls = ARRAY_SIZE(aic34_rx51_controls),
+	.dapm_widgets = aic34_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(aic34_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *rx51_snd_device;
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 6232b7d307aa..4d0720ed5a90 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -258,7 +258,7 @@ static int rsnd_src_init(struct rsnd_mod *mod,
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
-	clk_enable(src->clk);
+	clk_prepare_enable(src->clk);
 
 	return 0;
 }
@@ -269,7 +269,7 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
-	clk_disable(src->clk);
+	clk_disable_unprepare(src->clk);
 
 	return 0;
 }
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 4b7e20603dd7..1d8387c25bd8 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -171,7 +171,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
 	u32 cr;
 
 	if (0 == ssi->usrcnt) {
-		clk_enable(ssi->clk);
+		clk_prepare_enable(ssi->clk);
 
 		if (rsnd_dai_is_clk_master(rdai)) {
 			if (rsnd_ssi_clk_from_parent(ssi))
@@ -230,7 +230,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
 				rsnd_ssi_master_clk_stop(ssi);
 		}
 
-		clk_disable(ssi->clk);
+		clk_disable_unprepare(ssi->clk);
 	}
 
 	dev_dbg(dev, "ssi%d hw stopped\n", rsnd_mod_id(&ssi->mod));
diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c
index b04a53f2b4f6..b4afa31b2bc1 100644
--- a/sound/soc/sirf/sirf-audio-port.c
+++ b/sound/soc/sirf/sirf-audio-port.c
@@ -6,60 +6,15 @@
  * Licensed under GPLv2 or later.
  */
 #include <linux/module.h>
-#include <linux/io.h>
-#include <linux/regmap.h>
 #include <sound/soc.h>
 #include <sound/dmaengine_pcm.h>
 
-#include "sirf-audio-port.h"
-
 struct sirf_audio_port {
 	struct regmap *regmap;
 	struct snd_dmaengine_dai_dma_data playback_dma_data;
 	struct snd_dmaengine_dai_dma_data capture_dma_data;
 };
 
-static void sirf_audio_port_tx_enable(struct sirf_audio_port *port)
-{
-	regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP,
-		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
-	regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
-	regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
-	regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP,
-		AUDIO_FIFO_START, AUDIO_FIFO_START);
-	regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL,
-		IC_TX_ENABLE, IC_TX_ENABLE);
-}
-
-static void sirf_audio_port_tx_disable(struct sirf_audio_port *port)
-{
-	regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
-	regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL,
-		IC_TX_ENABLE, ~IC_TX_ENABLE);
-}
-
-static void sirf_audio_port_rx_enable(struct sirf_audio_port *port,
-	int channels)
-{
-	regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP,
-		AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
-	regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
-	regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
-	regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP,
-		AUDIO_FIFO_START, AUDIO_FIFO_START);
-	if (channels == 1)
-		regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL,
-			IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
-	else
-		regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL,
-			IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
-}
-
-static void sirf_audio_port_rx_disable(struct sirf_audio_port *port)
-{
-	regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL,
-			IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
-}
 
 static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai)
 {
@@ -69,41 +24,6 @@ static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai)
 	return 0;
 }
 
-static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd,
-	struct snd_soc_dai *dai)
-{
-	struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai);
-	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (playback)
-			sirf_audio_port_tx_disable(port);
-		else
-			sirf_audio_port_rx_disable(port);
-		break;
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (playback)
-			sirf_audio_port_tx_enable(port);
-		else
-			sirf_audio_port_rx_enable(port,
-				substream->runtime->channels);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = {
-	.trigger = sirf_audio_port_trigger,
-};
-
 static struct snd_soc_dai_driver sirf_audio_port_dai = {
 	.probe = sirf_audio_port_dai_probe,
 	.name = "sirf-audio-port",
@@ -120,49 +40,22 @@ static struct snd_soc_dai_driver sirf_audio_port_dai = {
 		.rates = SNDRV_PCM_RATE_48000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
-	.ops = &sirf_audio_port_dai_ops,
 };
 
 static const struct snd_soc_component_driver sirf_audio_port_component = {
 	.name       = "sirf-audio-port",
 };
 
-static const struct regmap_config sirf_audio_port_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
-	.cache_type = REGCACHE_NONE,
-};
-
 static int sirf_audio_port_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct sirf_audio_port *port;
-	void __iomem *base;
-	struct resource *mem_res;
 
 	port = devm_kzalloc(&pdev->dev,
 			sizeof(struct sirf_audio_port), GFP_KERNEL);
 	if (!port)
 		return -ENOMEM;
 
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem_res) {
-		dev_err(&pdev->dev, "no mem resource?\n");
-		return -ENODEV;
-	}
-
-	base = devm_ioremap(&pdev->dev, mem_res->start,
-			resource_size(mem_res));
-	if (base == NULL)
-		return -ENOMEM;
-
-	port->regmap = devm_regmap_init_mmio(&pdev->dev, base,
-					    &sirf_audio_port_regmap_config);
-	if (IS_ERR(port->regmap))
-		return PTR_ERR(port->regmap);
-
 	ret = devm_snd_soc_register_component(&pdev->dev,
 			&sirf_audio_port_component, &sirf_audio_port_dai, 1);
 	if (ret)
diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h
deleted file mode 100644
index f32dc54f4499..000000000000
--- a/sound/soc/sirf/sirf-audio-port.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SiRF Audio port controllers define
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef _SIRF_AUDIO_PORT_H
-#define _SIRF_AUDIO_PORT_H
-
-#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK     0x3F
-#define AUDIO_PORT_TX_FIFO_SC_OFFSET    0
-#define AUDIO_PORT_TX_FIFO_LC_OFFSET    10
-#define AUDIO_PORT_TX_FIFO_HC_OFFSET    20
-
-#define TX_FIFO_SC(x)           (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
-				<< AUDIO_PORT_TX_FIFO_SC_OFFSET)
-#define TX_FIFO_LC(x)           (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
-				<< AUDIO_PORT_TX_FIFO_LC_OFFSET)
-#define TX_FIFO_HC(x)           (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \
-				<< AUDIO_PORT_TX_FIFO_HC_OFFSET)
-
-#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK     0x0F
-#define AUDIO_PORT_RX_FIFO_SC_OFFSET    0
-#define AUDIO_PORT_RX_FIFO_LC_OFFSET    10
-#define AUDIO_PORT_RX_FIFO_HC_OFFSET    20
-
-#define RX_FIFO_SC(x)           (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
-				<< AUDIO_PORT_RX_FIFO_SC_OFFSET)
-#define RX_FIFO_LC(x)           (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
-				<< AUDIO_PORT_RX_FIFO_LC_OFFSET)
-#define RX_FIFO_HC(x)           (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \
-				<< AUDIO_PORT_RX_FIFO_HC_OFFSET)
-#define AUDIO_PORT_IC_CODEC_TX_CTRL		(0x00F4)
-#define AUDIO_PORT_IC_CODEC_RX_CTRL		(0x00F8)
-
-#define AUDIO_PORT_IC_TXFIFO_OP			(0x00FC)
-#define AUDIO_PORT_IC_TXFIFO_LEV_CHK		(0x0100)
-#define AUDIO_PORT_IC_TXFIFO_STS		(0x0104)
-#define AUDIO_PORT_IC_TXFIFO_INT		(0x0108)
-#define AUDIO_PORT_IC_TXFIFO_INT_MSK		(0x010C)
-
-#define AUDIO_PORT_IC_RXFIFO_OP			(0x0110)
-#define AUDIO_PORT_IC_RXFIFO_LEV_CHK		(0x0114)
-#define AUDIO_PORT_IC_RXFIFO_STS		(0x0118)
-#define AUDIO_PORT_IC_RXFIFO_INT		(0x011C)
-#define AUDIO_PORT_IC_RXFIFO_INT_MSK		(0x0120)
-
-#define AUDIO_FIFO_START		(1 << 0)
-#define AUDIO_FIFO_RESET		(1 << 1)
-
-#define AUDIO_FIFO_FULL			(1 << 0)
-#define AUDIO_FIFO_EMPTY		(1 << 1)
-#define AUDIO_FIFO_OFLOW		(1 << 2)
-#define AUDIO_FIFO_UFLOW		(1 << 3)
-
-#define IC_TX_ENABLE		(0x03)
-#define IC_RX_ENABLE_MONO	(0x01)
-#define IC_RX_ENABLE_STEREO	(0x03)
-
-#endif /*__SIRF_AUDIO_PORT_H*/
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index bfed3e4c45ff..3fa77d5f9b75 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -162,8 +162,6 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
 						  i, codec_drv->reg_word_size) == val)
 				continue;
 
-		WARN_ON(!snd_soc_codec_writable_register(codec, i));
-
 		ret = snd_soc_write(codec, i, val);
 		if (ret)
 			return ret;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 051c006281f5..b0ed28caf662 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -154,22 +154,15 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
 		step = codec->driver->reg_cache_step;
 
 	for (i = 0; i < codec->driver->reg_cache_size; i += step) {
-		if (!snd_soc_codec_readable_register(codec, i))
-			continue;
-		if (codec->driver->display_register) {
-			count += codec->driver->display_register(codec, buf + count,
-							 PAGE_SIZE - count, i);
-		} else {
-			/* only support larger than PAGE_SIZE bytes debugfs
-			 * entries for the default case */
-			if (p >= pos) {
-				if (total + len >= count - 1)
-					break;
-				format_register_str(codec, i, buf + total, len);
-				total += len;
-			}
-			p += len;
+		/* only support larger than PAGE_SIZE bytes debugfs
+		 * entries for the default case */
+		if (p >= pos) {
+			if (total + len >= count - 1)
+				break;
+			format_register_str(codec, i, buf + total, len);
+			total += len;
 		}
+		p += len;
 	}
 
 	total = min(total, count - 1);
@@ -854,14 +847,47 @@ EXPORT_SYMBOL_GPL(snd_soc_resume);
 static const struct snd_soc_dai_ops null_dai_ops = {
 };
 
+static struct snd_soc_codec *soc_find_codec(const struct device_node *codec_of_node,
+					    const char *codec_name)
+{
+	struct snd_soc_codec *codec;
+
+	list_for_each_entry(codec, &codec_list, list) {
+		if (codec_of_node) {
+			if (codec->dev->of_node != codec_of_node)
+				continue;
+		} else {
+			if (strcmp(codec->name, codec_name))
+				continue;
+		}
+
+		return codec;
+	}
+
+	return NULL;
+}
+
+static struct snd_soc_dai *soc_find_codec_dai(struct snd_soc_codec *codec,
+					      const char *codec_dai_name)
+{
+	struct snd_soc_dai *codec_dai;
+
+	list_for_each_entry(codec_dai, &codec->component.dai_list, list) {
+		if (!strcmp(codec_dai->name, codec_dai_name)) {
+			return codec_dai;
+		}
+	}
+
+	return NULL;
+}
+
 static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 {
 	struct snd_soc_dai_link *dai_link = &card->dai_link[num];
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
 	struct snd_soc_component *component;
-	struct snd_soc_codec *codec;
 	struct snd_soc_platform *platform;
-	struct snd_soc_dai *codec_dai, *cpu_dai;
+	struct snd_soc_dai *cpu_dai;
 	const char *platform_name;
 
 	dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num);
@@ -889,42 +915,24 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 		return -EPROBE_DEFER;
 	}
 
-	/* Find CODEC from registered CODECs */
-	list_for_each_entry(codec, &codec_list, list) {
-		if (dai_link->codec_of_node) {
-			if (codec->dev->of_node != dai_link->codec_of_node)
-				continue;
-		} else {
-			if (strcmp(codec->name, dai_link->codec_name))
-				continue;
-		}
-
-		rtd->codec = codec;
-
-		/*
-		 * CODEC found, so find CODEC DAI from registered DAIs from
-		 * this CODEC
-		 */
-		list_for_each_entry(codec_dai, &codec->component.dai_list, list) {
-			if (!strcmp(codec_dai->name, dai_link->codec_dai_name)) {
-				rtd->codec_dai = codec_dai;
-				break;
-			}
-		}
-
-		if (!rtd->codec_dai) {
-			dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
-				dai_link->codec_dai_name);
-			return -EPROBE_DEFER;
-		}
-	}
-
+	/* Find CODEC from registered list */
+	rtd->codec = soc_find_codec(dai_link->codec_of_node,
+				    dai_link->codec_name);
 	if (!rtd->codec) {
 		dev_err(card->dev, "ASoC: CODEC %s not registered\n",
 			dai_link->codec_name);
 		return -EPROBE_DEFER;
 	}
 
+	/* Find CODEC DAI from registered list */
+	rtd->codec_dai = soc_find_codec_dai(rtd->codec,
+					    dai_link->codec_dai_name);
+	if (!rtd->codec_dai) {
+		dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
+			dai_link->codec_dai_name);
+		return -EPROBE_DEFER;
+	}
+
 	/* if there's no platform we match on the empty platform */
 	platform_name = dai_link->platform_name;
 	if (!platform_name && !dai_link->platform_of_node)
@@ -995,21 +1003,10 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
 	module_put(codec->dev->driver->owner);
 }
 
-static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
+static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order)
 {
-	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
-	struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
 	int err;
 
-	/* unregister the rtd device */
-	if (rtd->dev_registered) {
-		device_remove_file(rtd->dev, &dev_attr_pmdown_time);
-		device_remove_file(rtd->dev, &dev_attr_codec_reg);
-		device_unregister(rtd->dev);
-		rtd->dev_registered = 0;
-	}
-
-	/* remove the CODEC DAI */
 	if (codec_dai && codec_dai->probed &&
 			codec_dai->driver->remove_order == order) {
 		if (codec_dai->driver->remove) {
@@ -1022,6 +1019,24 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
 		codec_dai->probed = 0;
 		list_del(&codec_dai->card_list);
 	}
+}
+
+static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
+{
+	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
+	struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
+	int err;
+
+	/* unregister the rtd device */
+	if (rtd->dev_registered) {
+		device_remove_file(rtd->dev, &dev_attr_pmdown_time);
+		device_remove_file(rtd->dev, &dev_attr_codec_reg);
+		device_unregister(rtd->dev);
+		rtd->dev_registered = 0;
+	}
+
+	/* remove the CODEC DAI */
+	soc_remove_codec_dai(codec_dai, order);
 
 	/* remove the cpu_dai */
 	if (cpu_dai && cpu_dai->probed &&
@@ -1127,26 +1142,31 @@ static int soc_probe_codec(struct snd_soc_card *card,
 
 	soc_init_codec_debugfs(codec);
 
-	if (driver->dapm_widgets)
-		snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
-					  driver->num_dapm_widgets);
+	if (driver->dapm_widgets) {
+		ret = snd_soc_dapm_new_controls(&codec->dapm,
+						driver->dapm_widgets,
+					 	driver->num_dapm_widgets);
 
-	/* Create DAPM widgets for each DAI stream */
-	list_for_each_entry(dai, &codec->component.dai_list, list)
-		snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
+		if (ret != 0) {
+			dev_err(codec->dev,
+				"Failed to create new controls %d\n", ret);
+			goto err_probe;
+		}
+	}
 
-	codec->dapm.idle_bias_off = driver->idle_bias_off;
+	/* Create DAPM widgets for each DAI stream */
+	list_for_each_entry(dai, &codec->component.dai_list, list) {
+		ret = snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
 
-	if (!codec->write && dev_get_regmap(codec->dev, NULL)) {
-		/* Set the default I/O up try regmap */
-		ret = snd_soc_codec_set_cache_io(codec, NULL);
-		if (ret < 0) {
+		if (ret != 0) {
 			dev_err(codec->dev,
-				"Failed to set cache I/O: %d\n", ret);
+				"Failed to create DAI widgets %d\n", ret);
 			goto err_probe;
 		}
 	}
 
+	codec->dapm.idle_bias_off = driver->idle_bias_off;
+
 	if (driver->probe) {
 		ret = driver->probe(codec);
 		if (ret < 0) {
@@ -1366,6 +1386,67 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num,
 	return 0;
 }
 
+static int soc_probe_codec_dai(struct snd_soc_card *card,
+			       struct snd_soc_dai *codec_dai,
+			       int order)
+{
+	int ret;
+
+	if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
+		if (codec_dai->driver->probe) {
+			ret = codec_dai->driver->probe(codec_dai);
+			if (ret < 0) {
+				dev_err(codec_dai->dev,
+					"ASoC: failed to probe CODEC DAI %s: %d\n",
+					codec_dai->name, ret);
+				return ret;
+			}
+		}
+
+		/* mark codec_dai as probed and add to card dai list */
+		codec_dai->probed = 1;
+		list_add(&codec_dai->card_list, &card->dai_dev_list);
+	}
+
+	return 0;
+}
+
+static int soc_link_dai_widgets(struct snd_soc_card *card,
+				struct snd_soc_dai_link *dai_link,
+				struct snd_soc_dai *cpu_dai,
+				struct snd_soc_dai *codec_dai)
+{
+	struct snd_soc_dapm_widget *play_w, *capture_w;
+	int ret;
+
+	/* link the DAI widgets */
+	play_w = codec_dai->playback_widget;
+	capture_w = cpu_dai->capture_widget;
+	if (play_w && capture_w) {
+		ret = snd_soc_dapm_new_pcm(card, dai_link->params,
+					   capture_w, play_w);
+		if (ret != 0) {
+			dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
+				play_w->name, capture_w->name, ret);
+			return ret;
+		}
+	}
+
+	play_w = cpu_dai->playback_widget;
+	capture_w = codec_dai->capture_widget;
+	if (play_w && capture_w) {
+		ret = snd_soc_dapm_new_pcm(card, dai_link->params,
+					   capture_w, play_w);
+		if (ret != 0) {
+			dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
+				play_w->name, capture_w->name, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 {
 	struct snd_soc_dai_link *dai_link = &card->dai_link[num];
@@ -1374,7 +1455,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dapm_widget *play_w, *capture_w;
 	int ret;
 
 	dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
@@ -1415,21 +1495,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 	}
 
 	/* probe the CODEC DAI */
-	if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
-		if (codec_dai->driver->probe) {
-			ret = codec_dai->driver->probe(codec_dai);
-			if (ret < 0) {
-				dev_err(codec_dai->dev,
-					"ASoC: failed to probe CODEC DAI %s: %d\n",
-					codec_dai->name, ret);
-				return ret;
-			}
-		}
-
-		/* mark codec_dai as probed and add to card dai list */
-		codec_dai->probed = 1;
-		list_add(&codec_dai->card_list, &card->dai_dev_list);
-	}
+	ret = soc_probe_codec_dai(card, codec_dai, order);
+	if (ret)
+		return ret;
 
 	/* complete DAI probe during last probe */
 	if (order != SND_SOC_COMP_ORDER_LAST)
@@ -1467,29 +1535,10 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 						codec2codec_close_delayed_work);
 
 			/* link the DAI widgets */
-			play_w = codec_dai->playback_widget;
-			capture_w = cpu_dai->capture_widget;
-			if (play_w && capture_w) {
-				ret = snd_soc_dapm_new_pcm(card, dai_link->params,
-						   capture_w, play_w);
-				if (ret != 0) {
-					dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
-						play_w->name, capture_w->name, ret);
-					return ret;
-				}
-			}
-
-			play_w = cpu_dai->playback_widget;
-			capture_w = codec_dai->capture_widget;
-			if (play_w && capture_w) {
-				ret = snd_soc_dapm_new_pcm(card, dai_link->params,
-						   capture_w, play_w);
-				if (ret != 0) {
-					dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
-						play_w->name, capture_w->name, ret);
-					return ret;
-				}
-			}
+			ret = soc_link_dai_widgets(card, dai_link,
+					cpu_dai, codec_dai);
+			if (ret)
+				return ret;
 		}
 	}
 
@@ -1501,14 +1550,15 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
 }
 
 #ifdef CONFIG_SND_SOC_AC97_BUS
-static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
+static int soc_register_ac97_codec(struct snd_soc_codec *codec,
+				   struct snd_soc_dai *codec_dai)
 {
 	int ret;
 
 	/* Only instantiate AC97 if not already done by the adaptor
 	 * for the generic AC97 subsystem.
 	 */
-	if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) {
+	if (codec_dai->driver->ac97_control && !codec->ac97_registered) {
 		/*
 		 * It is possible that the AC97 device is already registered to
 		 * the device subsystem. This happens when the device is created
@@ -1517,28 +1567,38 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
 		 *
 		 * In those cases we don't try to register the device again.
 		 */
-		if (!rtd->codec->ac97_created)
+		if (!codec->ac97_created)
 			return 0;
 
-		ret = soc_ac97_dev_register(rtd->codec);
+		ret = soc_ac97_dev_register(codec);
 		if (ret < 0) {
-			dev_err(rtd->codec->dev,
+			dev_err(codec->dev,
 				"ASoC: AC97 device register failed: %d\n", ret);
 			return ret;
 		}
 
-		rtd->codec->ac97_registered = 1;
+		codec->ac97_registered = 1;
 	}
 	return 0;
 }
 
-static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
+static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
+{
+	return soc_register_ac97_codec(rtd->codec, rtd->codec_dai);
+}
+
+static void soc_unregister_ac97_codec(struct snd_soc_codec *codec)
 {
 	if (codec->ac97_registered) {
 		soc_ac97_dev_unregister(codec);
 		codec->ac97_registered = 0;
 	}
 }
+
+static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
+{
+	soc_unregister_ac97_codec(rtd->codec);
+}
 #endif
 
 static int soc_check_aux_dev(struct snd_soc_card *card, int num)
@@ -1837,7 +1897,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 			dev_err(card->dev,
 				"ASoC: failed to register AC97: %d\n", ret);
 			while (--i >= 0)
-				soc_unregister_ac97_dai_link(card->rtd[i].codec);
+				soc_unregister_ac97_dai_link(&card->rtd[i]);
 			goto probe_aux_dev_err;
 		}
 	}
@@ -1980,92 +2040,6 @@ static struct platform_driver soc_driver = {
 };
 
 /**
- * snd_soc_codec_volatile_register: Report if a register is volatile.
- *
- * @codec: CODEC to query.
- * @reg: Register to query.
- *
- * Boolean function indiciating if a CODEC register is volatile.
- */
-int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
-				    unsigned int reg)
-{
-	if (codec->volatile_register)
-		return codec->volatile_register(codec, reg);
-	else
-		return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
-
-/**
- * snd_soc_codec_readable_register: Report if a register is readable.
- *
- * @codec: CODEC to query.
- * @reg: Register to query.
- *
- * Boolean function indicating if a CODEC register is readable.
- */
-int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
-				    unsigned int reg)
-{
-	if (codec->readable_register)
-		return codec->readable_register(codec, reg);
-	else
-		return 1;
-}
-EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register);
-
-/**
- * snd_soc_codec_writable_register: Report if a register is writable.
- *
- * @codec: CODEC to query.
- * @reg: Register to query.
- *
- * Boolean function indicating if a CODEC register is writable.
- */
-int snd_soc_codec_writable_register(struct snd_soc_codec *codec,
-				    unsigned int reg)
-{
-	if (codec->writable_register)
-		return codec->writable_register(codec, reg);
-	else
-		return 1;
-}
-EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register);
-
-int snd_soc_platform_read(struct snd_soc_platform *platform,
-					unsigned int reg)
-{
-	unsigned int ret;
-
-	if (!platform->driver->read) {
-		dev_err(platform->dev, "ASoC: platform has no read back\n");
-		return -1;
-	}
-
-	ret = platform->driver->read(platform, reg);
-	dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
-	trace_snd_soc_preg_read(platform, reg, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(snd_soc_platform_read);
-
-int snd_soc_platform_write(struct snd_soc_platform *platform,
-					 unsigned int reg, unsigned int val)
-{
-	if (!platform->driver->write) {
-		dev_err(platform->dev, "ASoC: platform has no write back\n");
-		return -1;
-	}
-
-	dev_dbg(platform->dev, "write %x = %x\n", reg, val);
-	trace_snd_soc_preg_write(platform, reg, val);
-	return platform->driver->write(platform, reg, val);
-}
-EXPORT_SYMBOL_GPL(snd_soc_platform_write);
-
-/**
  * snd_soc_new_ac97_codec - initailise AC97 device
  * @codec: audio codec
  * @ops: AC97 bus operations
@@ -2273,7 +2247,7 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
 {
 	mutex_lock(&codec->mutex);
 #ifdef CONFIG_SND_SOC_AC97_BUS
-	soc_unregister_ac97_dai_link(codec);
+	soc_unregister_ac97_codec(codec);
 #endif
 	kfree(codec->ac97->bus);
 	kfree(codec->ac97);
@@ -2283,118 +2257,6 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
 
-unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
-{
-	unsigned int ret;
-
-	ret = codec->read(codec, reg);
-	dev_dbg(codec->dev, "read %x => %x\n", reg, ret);
-	trace_snd_soc_reg_read(codec, reg, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(snd_soc_read);
-
-unsigned int snd_soc_write(struct snd_soc_codec *codec,
-			   unsigned int reg, unsigned int val)
-{
-	dev_dbg(codec->dev, "write %x = %x\n", reg, val);
-	trace_snd_soc_reg_write(codec, reg, val);
-	return codec->write(codec, reg, val);
-}
-EXPORT_SYMBOL_GPL(snd_soc_write);
-
-/**
- * snd_soc_update_bits - update codec register bits
- * @codec: audio codec
- * @reg: codec register
- * @mask: register mask
- * @value: new value
- *
- * Writes new register value.
- *
- * Returns 1 for change, 0 for no change, or negative error code.
- */
-int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
-				unsigned int mask, unsigned int value)
-{
-	bool change;
-	unsigned int old, new;
-	int ret;
-
-	if (codec->using_regmap) {
-		ret = regmap_update_bits_check(codec->control_data, reg,
-					       mask, value, &change);
-	} else {
-		ret = snd_soc_read(codec, reg);
-		if (ret < 0)
-			return ret;
-
-		old = ret;
-		new = (old & ~mask) | (value & mask);
-		change = old != new;
-		if (change)
-			ret = snd_soc_write(codec, reg, new);
-	}
-
-	if (ret < 0)
-		return ret;
-
-	return change;
-}
-EXPORT_SYMBOL_GPL(snd_soc_update_bits);
-
-/**
- * snd_soc_update_bits_locked - update codec register bits
- * @codec: audio codec
- * @reg: codec register
- * @mask: register mask
- * @value: new value
- *
- * Writes new register value, and takes the codec mutex.
- *
- * Returns 1 for change else 0.
- */
-int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
-			       unsigned short reg, unsigned int mask,
-			       unsigned int value)
-{
-	int change;
-
-	mutex_lock(&codec->mutex);
-	change = snd_soc_update_bits(codec, reg, mask, value);
-	mutex_unlock(&codec->mutex);
-
-	return change;
-}
-EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked);
-
-/**
- * snd_soc_test_bits - test register for change
- * @codec: audio codec
- * @reg: codec register
- * @mask: register mask
- * @value: new value
- *
- * Tests a register with a new value and checks if the new value is
- * different from the old value.
- *
- * Returns 1 for change else 0.
- */
-int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
-				unsigned int mask, unsigned int value)
-{
-	int change;
-	unsigned int old, new;
-
-	old = snd_soc_read(codec, reg);
-	new = (old & ~mask) | value;
-	change = old != new;
-
-	return change;
-}
-EXPORT_SYMBOL_GPL(snd_soc_test_bits);
-
 /**
  * snd_soc_cnew - create new control
  * @_template: control template
@@ -2896,7 +2758,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
 	int min = mc->min;
 	int mask = (1 << (fls(min + max) - 1)) - 1;
 	int err = 0;
-	unsigned short val, val_mask, val2 = 0;
+	unsigned int val, val_mask, val2 = 0;
 
 	val_mask = mask << shift;
 	val = (ucontrol->value.integer.value[0] + min) & mask;
@@ -3343,7 +3205,7 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned int regbase = mc->regbase;
 	unsigned int regcount = mc->regcount;
-	unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
+	unsigned int regwshift = codec->val_bytes * BITS_PER_BYTE;
 	unsigned int regwmask = (1<<regwshift)-1;
 	unsigned int invert = mc->invert;
 	unsigned long mask = (1UL<<mc->nbits)-1;
@@ -3389,7 +3251,7 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned int regbase = mc->regbase;
 	unsigned int regcount = mc->regcount;
-	unsigned int regwshift = codec->driver->reg_word_size * BITS_PER_BYTE;
+	unsigned int regwshift = codec->val_bytes * BITS_PER_BYTE;
 	unsigned int regwmask = (1<<regwshift)-1;
 	unsigned int invert = mc->invert;
 	unsigned long mask = (1UL<<mc->nbits)-1;
@@ -4084,6 +3946,7 @@ int snd_soc_register_component(struct device *dev,
 	}
 
 	cmpnt->ignore_pmdown_time = true;
+	cmpnt->registered_as_component = true;
 
 	return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL,
 					    dai_drv, num_dai, true);
@@ -4099,7 +3962,7 @@ void snd_soc_unregister_component(struct device *dev)
 	struct snd_soc_component *cmpnt;
 
 	list_for_each_entry(cmpnt, &component_list, list) {
-		if (dev == cmpnt->dev)
+		if (dev == cmpnt->dev && cmpnt->registered_as_component)
 			goto found;
 	}
 	return;
@@ -4125,6 +3988,8 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
 int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
 		const struct snd_soc_platform_driver *platform_drv)
 {
+	int ret;
+
 	/* create platform component name */
 	platform->name = fmt_single_name(dev, &platform->id);
 	if (platform->name == NULL)
@@ -4137,6 +4002,16 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
 	platform->dapm.stream_event = platform_drv->stream_event;
 	mutex_init(&platform->mutex);
 
+	/* register component */
+	ret = __snd_soc_register_component(dev, &platform->component,
+					   &platform_drv->component_driver,
+					   NULL, NULL, 0, false);
+	if (ret < 0) {
+		dev_err(platform->component.dev,
+			"ASoC: Failed to register component: %d\n", ret);
+		return ret;
+	}
+
 	mutex_lock(&client_mutex);
 	list_add(&platform->list, &platform_list);
 	mutex_unlock(&client_mutex);
@@ -4178,6 +4053,8 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
  */
 void snd_soc_remove_platform(struct snd_soc_platform *platform)
 {
+	snd_soc_unregister_component(platform->dev);
+
 	mutex_lock(&client_mutex);
 	list_del(&platform->list);
 	mutex_unlock(&client_mutex);
@@ -4263,6 +4140,7 @@ int snd_soc_register_codec(struct device *dev,
 			   int num_dai)
 {
 	struct snd_soc_codec *codec;
+	struct regmap *regmap;
 	int ret, i;
 
 	dev_dbg(dev, "codec register %s\n", dev_name(dev));
@@ -4280,9 +4158,6 @@ int snd_soc_register_codec(struct device *dev,
 
 	codec->write = codec_drv->write;
 	codec->read = codec_drv->read;
-	codec->volatile_register = codec_drv->volatile_register;
-	codec->readable_register = codec_drv->readable_register;
-	codec->writable_register = codec_drv->writable_register;
 	codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
 	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
 	codec->dapm.dev = dev;
@@ -4292,8 +4167,26 @@ int snd_soc_register_codec(struct device *dev,
 	codec->dev = dev;
 	codec->driver = codec_drv;
 	codec->num_dai = num_dai;
+	codec->val_bytes = codec_drv->reg_word_size;
 	mutex_init(&codec->mutex);
 
+	if (!codec->write) {
+		if (codec_drv->get_regmap)
+			regmap = codec_drv->get_regmap(dev);
+		else
+			regmap = dev_get_regmap(dev, NULL);
+
+		if (regmap) {
+			ret = snd_soc_codec_set_cache_io(codec, regmap);
+			if (ret && ret != -ENOTSUPP) {
+				dev_err(codec->dev,
+						"Failed to set cache I/O:%d\n",
+						ret);
+				return ret;
+			}
+		}
+	}
+
 	for (i = 0; i < num_dai; i++) {
 		fixup_codec_formats(&dai_drv[i].playback);
 		fixup_codec_formats(&dai_drv[i].capture);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 260efc8466fc..14bdf79bf7cc 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -19,6 +19,150 @@
 
 #include <trace/events/asoc.h>
 
+unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	unsigned int ret;
+
+	ret = codec->read(codec, reg);
+	dev_dbg(codec->dev, "read %x => %x\n", reg, ret);
+	trace_snd_soc_reg_read(codec, reg, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_read);
+
+unsigned int snd_soc_write(struct snd_soc_codec *codec,
+			   unsigned int reg, unsigned int val)
+{
+	dev_dbg(codec->dev, "write %x = %x\n", reg, val);
+	trace_snd_soc_reg_write(codec, reg, val);
+	return codec->write(codec, reg, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_write);
+
+/**
+ * snd_soc_update_bits - update codec register bits
+ * @codec: audio codec
+ * @reg: codec register
+ * @mask: register mask
+ * @value: new value
+ *
+ * Writes new register value.
+ *
+ * Returns 1 for change, 0 for no change, or negative error code.
+ */
+int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
+				unsigned int mask, unsigned int value)
+{
+	bool change;
+	unsigned int old, new;
+	int ret;
+
+	if (codec->using_regmap) {
+		ret = regmap_update_bits_check(codec->control_data, reg,
+					       mask, value, &change);
+	} else {
+		ret = snd_soc_read(codec, reg);
+		if (ret < 0)
+			return ret;
+
+		old = ret;
+		new = (old & ~mask) | (value & mask);
+		change = old != new;
+		if (change)
+			ret = snd_soc_write(codec, reg, new);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return change;
+}
+EXPORT_SYMBOL_GPL(snd_soc_update_bits);
+
+/**
+ * snd_soc_update_bits_locked - update codec register bits
+ * @codec: audio codec
+ * @reg: codec register
+ * @mask: register mask
+ * @value: new value
+ *
+ * Writes new register value, and takes the codec mutex.
+ *
+ * Returns 1 for change else 0.
+ */
+int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
+			       unsigned int reg, unsigned int mask,
+			       unsigned int value)
+{
+	int change;
+
+	mutex_lock(&codec->mutex);
+	change = snd_soc_update_bits(codec, reg, mask, value);
+	mutex_unlock(&codec->mutex);
+
+	return change;
+}
+EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked);
+
+/**
+ * snd_soc_test_bits - test register for change
+ * @codec: audio codec
+ * @reg: codec register
+ * @mask: register mask
+ * @value: new value
+ *
+ * Tests a register with a new value and checks if the new value is
+ * different from the old value.
+ *
+ * Returns 1 for change else 0.
+ */
+int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
+				unsigned int mask, unsigned int value)
+{
+	int change;
+	unsigned int old, new;
+
+	old = snd_soc_read(codec, reg);
+	new = (old & ~mask) | value;
+	change = old != new;
+
+	return change;
+}
+EXPORT_SYMBOL_GPL(snd_soc_test_bits);
+
+int snd_soc_platform_read(struct snd_soc_platform *platform,
+					unsigned int reg)
+{
+	unsigned int ret;
+
+	if (!platform->driver->read) {
+		dev_err(platform->dev, "ASoC: platform has no read back\n");
+		return -1;
+	}
+
+	ret = platform->driver->read(platform, reg);
+	dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
+	trace_snd_soc_preg_read(platform, reg, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_platform_read);
+
+int snd_soc_platform_write(struct snd_soc_platform *platform,
+					 unsigned int reg, unsigned int val)
+{
+	if (!platform->driver->write) {
+		dev_err(platform->dev, "ASoC: platform has no write back\n");
+		return -1;
+	}
+
+	dev_dbg(platform->dev, "write %x = %x\n", reg, val);
+	trace_snd_soc_preg_write(platform, reg, val);
+	return platform->driver->write(platform, reg, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_platform_write);
+
 #ifdef CONFIG_REGMAP
 static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
 		    unsigned int value)
@@ -60,14 +204,11 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 {
 	int ret;
 
-	/* Device has made its own regmap arrangements */
 	if (!regmap)
-		codec->control_data = dev_get_regmap(codec->dev, NULL);
-	else
-		codec->control_data = regmap;
+		return -EINVAL;
 
-	if (IS_ERR(codec->control_data))
-		return PTR_ERR(codec->control_data);
+	/* Device has made its own regmap arrangements */
+	codec->control_data = regmap;
 
 	codec->write = hw_write;
 	codec->read = hw_read;
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index e05a86b7c0da..d393153c474f 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -147,5 +147,18 @@ config SND_USB_HIFACE
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-usb-hiface.
 
+config SND_BCD2000
+	tristate "Behringer BCD2000 MIDI driver"
+	select SND_RAWMIDI
+	help
+	  Say Y here to include MIDI support for the Behringer BCD2000 DJ
+	  controller.
+
+	  Audio support is still work-in-progress at
+	  https://github.com/anyc/snd-usb-bcd2000
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-bcd2000.
+
 endif	# SND_USB
 
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index abe668f660d1..2b92f0dcbc4c 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
 
-obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/
+obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/
diff --git a/sound/usb/bcd2000/Makefile b/sound/usb/bcd2000/Makefile
new file mode 100644
index 000000000000..f09ccc0af6ff
--- /dev/null
+++ b/sound/usb/bcd2000/Makefile
@@ -0,0 +1,3 @@
+snd-bcd2000-y := bcd2000.o
+
+obj-$(CONFIG_SND_BCD2000) += snd-bcd2000.o
\ No newline at end of file
diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
new file mode 100644
index 000000000000..820d6ca8c458
--- /dev/null
+++ b/sound/usb/bcd2000/bcd2000.c
@@ -0,0 +1,461 @@
+/*
+ * Behringer BCD2000 driver
+ *
+ *   Copyright (C) 2014 Mario Kicherer (dev@kicherer.org)
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/bitmap.h>
+#include <linux/usb.h>
+#include <linux/usb/audio.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+
+#define PREFIX "snd-bcd2000: "
+#define BUFSIZE 64
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE(0x1397, 0x00bd) },
+	{ },
+};
+
+static unsigned char device_cmd_prefix[] = {0x03, 0x00};
+
+static unsigned char bcd2000_init_sequence[] = {
+	0x07, 0x00, 0x00, 0x00, 0x78, 0x48, 0x1c, 0x81,
+	0xc4, 0x00, 0x00, 0x00, 0x5e, 0x53, 0x4a, 0xf7,
+	0x18, 0xfa, 0x11, 0xff, 0x6c, 0xf3, 0x90, 0xff,
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x18, 0xfa, 0x11, 0xff, 0x14, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xf2, 0x34, 0x4a, 0xf7,
+	0x18, 0xfa, 0x11, 0xff
+};
+
+struct bcd2000 {
+	struct usb_device *dev;
+	struct snd_card *card;
+	struct usb_interface *intf;
+	int card_index;
+
+	int midi_out_active;
+	struct snd_rawmidi *rmidi;
+	struct snd_rawmidi_substream *midi_receive_substream;
+	struct snd_rawmidi_substream *midi_out_substream;
+
+	unsigned char midi_in_buf[BUFSIZE];
+	unsigned char midi_out_buf[BUFSIZE];
+
+	struct urb *midi_out_urb;
+	struct urb *midi_in_urb;
+
+	struct usb_anchor anchor;
+};
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+
+static DEFINE_MUTEX(devices_mutex);
+DECLARE_BITMAP(devices_used, SNDRV_CARDS);
+static struct usb_driver bcd2000_driver;
+
+#ifdef CONFIG_SND_DEBUG
+static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len)
+{
+	print_hex_dump(KERN_DEBUG, prefix,
+			DUMP_PREFIX_NONE, 16, 1,
+			buf, len, false);
+}
+#else
+static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len) {}
+#endif
+
+static int bcd2000_midi_input_open(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static int bcd2000_midi_input_close(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+/* (de)register midi substream from client */
+static void bcd2000_midi_input_trigger(struct snd_rawmidi_substream *substream,
+						int up)
+{
+	struct bcd2000 *bcd2k = substream->rmidi->private_data;
+	bcd2k->midi_receive_substream = up ? substream : NULL;
+}
+
+static void bcd2000_midi_handle_input(struct bcd2000 *bcd2k,
+				const unsigned char *buf, unsigned int buf_len)
+{
+	unsigned int payload_length, tocopy;
+	struct snd_rawmidi_substream *midi_receive_substream;
+
+	midi_receive_substream = ACCESS_ONCE(bcd2k->midi_receive_substream);
+	if (!midi_receive_substream)
+		return;
+
+	bcd2000_dump_buffer(PREFIX "received from device: ", buf, buf_len);
+
+	if (buf_len < 2)
+		return;
+
+	payload_length = buf[0];
+
+	/* ignore packets without payload */
+	if (payload_length == 0)
+		return;
+
+	tocopy = min(payload_length, buf_len-1);
+
+	bcd2000_dump_buffer(PREFIX "sending to userspace: ",
+					&buf[1], tocopy);
+
+	snd_rawmidi_receive(midi_receive_substream,
+					&buf[1], tocopy);
+}
+
+static void bcd2000_midi_send(struct bcd2000 *bcd2k)
+{
+	int len, ret;
+	struct snd_rawmidi_substream *midi_out_substream;
+
+	BUILD_BUG_ON(sizeof(device_cmd_prefix) >= BUFSIZE);
+
+	midi_out_substream = ACCESS_ONCE(bcd2k->midi_out_substream);
+	if (!midi_out_substream)
+		return;
+
+	/* copy command prefix bytes */
+	memcpy(bcd2k->midi_out_buf, device_cmd_prefix,
+		sizeof(device_cmd_prefix));
+
+	/*
+	 * get MIDI packet and leave space for command prefix
+	 * and payload length
+	 */
+	len = snd_rawmidi_transmit(midi_out_substream,
+				bcd2k->midi_out_buf + 3, BUFSIZE - 3);
+
+	if (len < 0)
+		dev_err(&bcd2k->dev->dev, "%s: snd_rawmidi_transmit error %d\n",
+				__func__, len);
+
+	if (len <= 0)
+		return;
+
+	/* set payload length */
+	bcd2k->midi_out_buf[2] = len;
+	bcd2k->midi_out_urb->transfer_buffer_length = BUFSIZE;
+
+	bcd2000_dump_buffer(PREFIX "sending to device: ",
+			bcd2k->midi_out_buf, len+3);
+
+	/* send packet to the BCD2000 */
+	ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_ATOMIC);
+	if (ret < 0)
+		dev_err(&bcd2k->dev->dev, PREFIX
+			"%s (%p): usb_submit_urb() failed, ret=%d, len=%d\n",
+			__func__, midi_out_substream, ret, len);
+	else
+		bcd2k->midi_out_active = 1;
+}
+
+static int bcd2000_midi_output_open(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static int bcd2000_midi_output_close(struct snd_rawmidi_substream *substream)
+{
+	struct bcd2000 *bcd2k = substream->rmidi->private_data;
+
+	if (bcd2k->midi_out_active) {
+		usb_kill_urb(bcd2k->midi_out_urb);
+		bcd2k->midi_out_active = 0;
+	}
+
+	return 0;
+}
+
+/* (de)register midi substream from client */
+static void bcd2000_midi_output_trigger(struct snd_rawmidi_substream *substream,
+						int up)
+{
+	struct bcd2000 *bcd2k = substream->rmidi->private_data;
+
+	if (up) {
+		bcd2k->midi_out_substream = substream;
+		/* check if there is data userspace wants to send */
+		if (!bcd2k->midi_out_active)
+			bcd2000_midi_send(bcd2k);
+	} else {
+		bcd2k->midi_out_substream = NULL;
+	}
+}
+
+static void bcd2000_output_complete(struct urb *urb)
+{
+	struct bcd2000 *bcd2k = urb->context;
+
+	bcd2k->midi_out_active = 0;
+
+	if (urb->status)
+		dev_warn(&urb->dev->dev,
+			PREFIX "output urb->status: %d\n", urb->status);
+
+	if (urb->status == -ESHUTDOWN)
+		return;
+
+	/* check if there is more data userspace wants to send */
+	bcd2000_midi_send(bcd2k);
+}
+
+static void bcd2000_input_complete(struct urb *urb)
+{
+	int ret;
+	struct bcd2000 *bcd2k = urb->context;
+
+	if (urb->status)
+		dev_warn(&urb->dev->dev,
+			PREFIX "input urb->status: %i\n", urb->status);
+
+	if (!bcd2k || urb->status == -ESHUTDOWN)
+		return;
+
+	if (urb->actual_length > 0)
+		bcd2000_midi_handle_input(bcd2k, urb->transfer_buffer,
+					urb->actual_length);
+
+	/* return URB to device */
+	ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_ATOMIC);
+	if (ret < 0)
+		dev_err(&bcd2k->dev->dev, PREFIX
+			"%s: usb_submit_urb() failed, ret=%d\n",
+			__func__, ret);
+}
+
+static struct snd_rawmidi_ops bcd2000_midi_output = {
+	.open =    bcd2000_midi_output_open,
+	.close =   bcd2000_midi_output_close,
+	.trigger = bcd2000_midi_output_trigger,
+};
+
+static struct snd_rawmidi_ops bcd2000_midi_input = {
+	.open =    bcd2000_midi_input_open,
+	.close =   bcd2000_midi_input_close,
+	.trigger = bcd2000_midi_input_trigger,
+};
+
+static void bcd2000_init_device(struct bcd2000 *bcd2k)
+{
+	int ret;
+
+	init_usb_anchor(&bcd2k->anchor);
+	usb_anchor_urb(bcd2k->midi_out_urb, &bcd2k->anchor);
+	usb_anchor_urb(bcd2k->midi_in_urb, &bcd2k->anchor);
+
+	/* copy init sequence into buffer */
+	memcpy(bcd2k->midi_out_buf, bcd2000_init_sequence, 52);
+	bcd2k->midi_out_urb->transfer_buffer_length = 52;
+
+	/* submit sequence */
+	ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_KERNEL);
+	if (ret < 0)
+		dev_err(&bcd2k->dev->dev, PREFIX
+			"%s: usb_submit_urb() out failed, ret=%d: ",
+			__func__, ret);
+	else
+		bcd2k->midi_out_active = 1;
+
+	/* pass URB to device to enable button and controller events */
+	ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_KERNEL);
+	if (ret < 0)
+		dev_err(&bcd2k->dev->dev, PREFIX
+			"%s: usb_submit_urb() in failed, ret=%d: ",
+			__func__, ret);
+
+	/* ensure initialization is finished */
+	usb_wait_anchor_empty_timeout(&bcd2k->anchor, 1000);
+}
+
+static int bcd2000_init_midi(struct bcd2000 *bcd2k)
+{
+	int ret;
+	struct snd_rawmidi *rmidi;
+
+	ret = snd_rawmidi_new(bcd2k->card, bcd2k->card->shortname, 0,
+					1, /* output */
+					1, /* input */
+					&rmidi);
+
+	if (ret < 0)
+		return ret;
+
+	strlcpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
+
+	rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
+	rmidi->private_data = bcd2k;
+
+	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+					&bcd2000_midi_output);
+
+	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+					&bcd2000_midi_input);
+
+	bcd2k->rmidi = rmidi;
+
+	bcd2k->midi_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	bcd2k->midi_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+	if (!bcd2k->midi_in_urb || !bcd2k->midi_out_urb) {
+		dev_err(&bcd2k->dev->dev, PREFIX "usb_alloc_urb failed\n");
+		return -ENOMEM;
+	}
+
+	usb_fill_int_urb(bcd2k->midi_in_urb, bcd2k->dev,
+				usb_rcvintpipe(bcd2k->dev, 0x81),
+				bcd2k->midi_in_buf, BUFSIZE,
+				bcd2000_input_complete, bcd2k, 1);
+
+	usb_fill_int_urb(bcd2k->midi_out_urb, bcd2k->dev,
+				usb_sndintpipe(bcd2k->dev, 0x1),
+				bcd2k->midi_out_buf, BUFSIZE,
+				bcd2000_output_complete, bcd2k, 1);
+
+	bcd2000_init_device(bcd2k);
+
+	return 0;
+}
+
+static void bcd2000_free_usb_related_resources(struct bcd2000 *bcd2k,
+						struct usb_interface *interface)
+{
+	/* usb_kill_urb not necessary, urb is aborted automatically */
+
+	usb_free_urb(bcd2k->midi_out_urb);
+	usb_free_urb(bcd2k->midi_in_urb);
+
+	if (bcd2k->intf) {
+		usb_set_intfdata(bcd2k->intf, NULL);
+		bcd2k->intf = NULL;
+	}
+}
+
+static int bcd2000_probe(struct usb_interface *interface,
+				const struct usb_device_id *usb_id)
+{
+	struct snd_card *card;
+	struct bcd2000 *bcd2k;
+	unsigned int card_index;
+	char usb_path[32];
+	int err;
+
+	mutex_lock(&devices_mutex);
+
+	for (card_index = 0; card_index < SNDRV_CARDS; ++card_index)
+		if (!test_bit(card_index, devices_used))
+			break;
+
+	if (card_index >= SNDRV_CARDS) {
+		mutex_unlock(&devices_mutex);
+		return -ENOENT;
+	}
+
+	err = snd_card_new(&interface->dev, index[card_index], id[card_index],
+			THIS_MODULE, sizeof(*bcd2k), &card);
+	if (err < 0) {
+		mutex_unlock(&devices_mutex);
+		return err;
+	}
+
+	bcd2k = card->private_data;
+	bcd2k->dev = interface_to_usbdev(interface);
+	bcd2k->card = card;
+	bcd2k->card_index = card_index;
+	bcd2k->intf = interface;
+
+	snd_card_set_dev(card, &interface->dev);
+
+	strncpy(card->driver, "snd-bcd2000", sizeof(card->driver));
+	strncpy(card->shortname, "BCD2000", sizeof(card->shortname));
+	usb_make_path(bcd2k->dev, usb_path, sizeof(usb_path));
+	snprintf(bcd2k->card->longname, sizeof(bcd2k->card->longname),
+		    "Behringer BCD2000 at %s",
+			usb_path);
+
+	err = bcd2000_init_midi(bcd2k);
+	if (err < 0)
+		goto probe_error;
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto probe_error;
+
+	usb_set_intfdata(interface, bcd2k);
+	set_bit(card_index, devices_used);
+
+	mutex_unlock(&devices_mutex);
+	return 0;
+
+probe_error:
+	dev_info(&bcd2k->dev->dev, PREFIX "error during probing");
+	bcd2000_free_usb_related_resources(bcd2k, interface);
+	snd_card_free(card);
+	mutex_unlock(&devices_mutex);
+	return err;
+}
+
+static void bcd2000_disconnect(struct usb_interface *interface)
+{
+	struct bcd2000 *bcd2k = usb_get_intfdata(interface);
+
+	if (!bcd2k)
+		return;
+
+	mutex_lock(&devices_mutex);
+
+	/* make sure that userspace cannot create new requests */
+	snd_card_disconnect(bcd2k->card);
+
+	bcd2000_free_usb_related_resources(bcd2k, interface);
+
+	clear_bit(bcd2k->card_index, devices_used);
+
+	snd_card_free_when_closed(bcd2k->card);
+
+	mutex_unlock(&devices_mutex);
+}
+
+static struct usb_driver bcd2000_driver = {
+	.name =		"snd-bcd2000",
+	.probe =	bcd2000_probe,
+	.disconnect =	bcd2000_disconnect,
+	.id_table =	id_table,
+};
+
+module_usb_driver(bcd2000_driver);
+
+MODULE_DEVICE_TABLE(usb, id_table);
+MODULE_AUTHOR("Mario Kicherer, dev@kicherer.org");
+MODULE_DESCRIPTION("Behringer BCD2000 driver");
+MODULE_LICENSE("GPL");
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 4ecc4fd0bc1b..fba1c75aa484 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -82,8 +82,10 @@ static int hv_start_fcopy(struct hv_start_fcopy *smsg)
 
 	if (!access(target_fname, F_OK)) {
 		syslog(LOG_INFO, "File: %s exists", target_fname);
-		if (!smsg->copy_flags & OVER_WRITE)
+		if (!(smsg->copy_flags & OVER_WRITE)) {
+			error = HV_ERROR_ALREADY_EXISTS;
 			goto done;
+		}
 	}
 
 	target_fd = open(target_fname, O_RDWR | O_CREAT | O_CLOEXEC, 0744);
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 07b0b7542511..cb09d3ff8f58 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -1,13 +1,8 @@
-# liblockdep version
-LL_VERSION = 0
-LL_PATCHLEVEL = 0
-LL_EXTRAVERSION = 1
-
 # file format version
 FILE_VERSION = 1
 
 MAKEFLAGS += --no-print-directory
-
+LIBLOCKDEP_VERSION=$(shell make -sC ../../.. kernelversion)
 
 # Makefiles suck: This macro sets a default value of $(2) for the
 # variable named by $(1), unless the variable has been set by
@@ -98,7 +93,7 @@ export prefix libdir bindir src obj
 libdir_SQ = $(subst ','\'',$(libdir))
 bindir_SQ = $(subst ','\'',$(bindir))
 
-LIB_FILE = liblockdep.a liblockdep.so
+LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION)
 BIN_FILE = lockdep
 
 CONFIG_INCLUDES =
@@ -110,8 +105,6 @@ N		=
 
 export Q VERBOSE
 
-LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
-
 INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include $(CONFIG_INCLUDES)
 
 # Set compile option CFLAGS if not set elsewhere
@@ -146,7 +139,7 @@ do_app_build =						\
 
 do_compile_shared_library =			\
 	($(print_shared_lib_compile)		\
-	$(CC) --shared $^ -o $@ -lpthread -ldl)
+	$(CC) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='"$@"';$(shell ln -s $@ liblockdep.so))
 
 do_build_static_lib =				\
 	($(print_static_lib_build)		\
@@ -177,7 +170,7 @@ all: all_cmd
 
 all_cmd: $(CMD_TARGETS)
 
-liblockdep.so: $(PEVENT_LIB_OBJS)
+liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS)
 	$(Q)$(do_compile_shared_library)
 
 liblockdep.a: $(PEVENT_LIB_OBJS)
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h
index d0f5d6e50214..c1552c28507e 100644
--- a/tools/lib/lockdep/uinclude/linux/lockdep.h
+++ b/tools/lib/lockdep/uinclude/linux/lockdep.h
@@ -10,6 +10,9 @@
 
 #define MAX_LOCK_DEPTH 2000UL
 
+#define asmlinkage
+#define __visible
+
 #include "../../../include/linux/lockdep.h"
 
 struct task_struct {
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 1587ea392ad6..baec7d887da4 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -50,6 +50,18 @@ static int show_warning = 1;
 			warning(fmt, ##__VA_ARGS__);	\
 	} while (0)
 
+#define do_warning_event(event, fmt, ...)			\
+	do {							\
+		if (!show_warning)				\
+			continue;				\
+								\
+		if (event)					\
+			warning("[%s:%s] " fmt, event->system,	\
+				event->name, ##__VA_ARGS__);	\
+		else						\
+			warning(fmt, ##__VA_ARGS__);		\
+	} while (0)
+
 static void init_input_buf(const char *buf, unsigned long long size)
 {
 	input_buf = buf;
@@ -1355,7 +1367,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
 		}
 
 		if (!field->type) {
-			do_warning("%s: no type found", __func__);
+			do_warning_event(event, "%s: no type found", __func__);
 			goto fail;
 		}
 		field->name = last_token;
@@ -1402,7 +1414,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
 				free_token(token);
 				type = read_token(&token);
 				if (type == EVENT_NONE) {
-					do_warning("failed to find token");
+					do_warning_event(event, "failed to find token");
 					goto fail;
 				}
 			}
@@ -1636,7 +1648,7 @@ process_cond(struct event_format *event, struct print_arg *top, char **tok)
 	right = alloc_arg();
 
 	if (!arg || !left || !right) {
-		do_warning("%s: not enough memory!", __func__);
+		do_warning_event(event, "%s: not enough memory!", __func__);
 		/* arg will be freed at out_free */
 		free_arg(left);
 		free_arg(right);
@@ -1686,7 +1698,7 @@ process_array(struct event_format *event, struct print_arg *top, char **tok)
 
 	arg = alloc_arg();
 	if (!arg) {
-		do_warning("%s: not enough memory!", __func__);
+		do_warning_event(event, "%s: not enough memory!", __func__);
 		/* '*tok' is set to top->op.op.  No need to free. */
 		*tok = NULL;
 		return EVENT_ERROR;
@@ -1792,7 +1804,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 	if (arg->type == PRINT_OP && !arg->op.left) {
 		/* handle single op */
 		if (token[1]) {
-			do_warning("bad op token %s", token);
+			do_warning_event(event, "bad op token %s", token);
 			goto out_free;
 		}
 		switch (token[0]) {
@@ -1802,7 +1814,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 		case '-':
 			break;
 		default:
-			do_warning("bad op token %s", token);
+			do_warning_event(event, "bad op token %s", token);
 			goto out_free;
 
 		}
@@ -1888,7 +1900,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 			char *new_atom;
 
 			if (left->type != PRINT_ATOM) {
-				do_warning("bad pointer type");
+				do_warning_event(event, "bad pointer type");
 				goto out_free;
 			}
 			new_atom = realloc(left->atom.atom,
@@ -1930,7 +1942,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 		type = process_array(event, arg, tok);
 
 	} else {
-		do_warning("unknown op '%s'", token);
+		do_warning_event(event, "unknown op '%s'", token);
 		event->flags |= EVENT_FL_FAILED;
 		/* the arg is now the left side */
 		goto out_free;
@@ -1951,7 +1963,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 	return type;
 
 out_warn_free:
-	do_warning("%s: not enough memory!", __func__);
+	do_warning_event(event, "%s: not enough memory!", __func__);
 out_free:
 	free_token(token);
 	*tok = NULL;
@@ -2385,7 +2397,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok)
 
 	field = alloc_arg();
 	if (!field) {
-		do_warning("%s: not enough memory!", __func__);
+		do_warning_event(event, "%s: not enough memory!", __func__);
 		goto out_free;
 	}
 
@@ -2438,7 +2450,7 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
 
 	field = alloc_arg();
 	if (!field) {
-		do_warning("%s: not enough memory!", __func__);
+		do_warning_event(event, "%s: not enough memory!", __func__);
 		goto out_free;
 	}
 
@@ -2477,7 +2489,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok)
 
 	field = alloc_arg();
 	if (!field) {
-		do_warning("%s: not enough memory!", __func__);
+		do_warning_event(event, "%s: not enough memory!", __func__);
 		goto out_free;
 	}
 
@@ -2492,7 +2504,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok)
 
 	field = alloc_arg();
 	if (!field) {
-		do_warning("%s: not enough memory!", __func__);
+		do_warning_event(event, "%s: not enough memory!", __func__);
 		*tok = NULL;
 		return EVENT_ERROR;
 	}
@@ -2555,7 +2567,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char **
 	free_token(token);
 	arg = alloc_arg();
 	if (!arg) {
-		do_warning("%s: not enough memory!", __func__);
+		do_warning_event(event, "%s: not enough memory!", __func__);
 		*tok = NULL;
 		return EVENT_ERROR;
 	}
@@ -2614,13 +2626,14 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok)
 
 		/* prevous must be an atom */
 		if (arg->type != PRINT_ATOM) {
-			do_warning("previous needed to be PRINT_ATOM");
+			do_warning_event(event, "previous needed to be PRINT_ATOM");
 			goto out_free;
 		}
 
 		item_arg = alloc_arg();
 		if (!item_arg) {
-			do_warning("%s: not enough memory!", __func__);
+			do_warning_event(event, "%s: not enough memory!",
+					 __func__);
 			goto out_free;
 		}
 
@@ -2721,21 +2734,24 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
 	for (i = 0; i < func->nr_args; i++) {
 		farg = alloc_arg();
 		if (!farg) {
-			do_warning("%s: not enough memory!", __func__);
+			do_warning_event(event, "%s: not enough memory!",
+					 __func__);
 			return EVENT_ERROR;
 		}
 
 		type = process_arg(event, farg, &token);
 		if (i < (func->nr_args - 1)) {
 			if (type != EVENT_DELIM || strcmp(token, ",") != 0) {
-				warning("Error: function '%s()' expects %d arguments but event %s only uses %d",
+				do_warning_event(event,
+					"Error: function '%s()' expects %d arguments but event %s only uses %d",
 					func->name, func->nr_args,
 					event->name, i + 1);
 				goto err;
 			}
 		} else {
 			if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
-				warning("Error: function '%s()' only expects %d arguments but event %s has more",
+				do_warning_event(event,
+					"Error: function '%s()' only expects %d arguments but event %s has more",
 					func->name, func->nr_args, event->name);
 				goto err;
 			}
@@ -2792,7 +2808,7 @@ process_function(struct event_format *event, struct print_arg *arg,
 		return process_func_handler(event, func, arg, tok);
 	}
 
-	do_warning("function %s not defined", token);
+	do_warning_event(event, "function %s not defined", token);
 	free_token(token);
 	return EVENT_ERROR;
 }
@@ -2878,7 +2894,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
 
 	case EVENT_ERROR ... EVENT_NEWLINE:
 	default:
-		do_warning("unexpected type %d", type);
+		do_warning_event(event, "unexpected type %d", type);
 		return EVENT_ERROR;
 	}
 	*tok = token;
@@ -2901,7 +2917,8 @@ static int event_read_print_args(struct event_format *event, struct print_arg **
 
 		arg = alloc_arg();
 		if (!arg) {
-			do_warning("%s: not enough memory!", __func__);
+			do_warning_event(event, "%s: not enough memory!",
+					 __func__);
 			return -1;
 		}
 
@@ -3481,11 +3498,12 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
 	return val;
 
 out_warning_op:
-	do_warning("%s: unknown op '%s'", __func__, arg->op.op);
+	do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
 	return 0;
 
 out_warning_field:
-	do_warning("%s: field %s not found", __func__, arg->field.name);
+	do_warning_event(event, "%s: field %s not found",
+			 __func__, arg->field.name);
 	return 0;
 }
 
@@ -3591,7 +3609,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
 		}
 		str = malloc(len + 1);
 		if (!str) {
-			do_warning("%s: not enough memory!", __func__);
+			do_warning_event(event, "%s: not enough memory!",
+					 __func__);
 			return;
 		}
 		memcpy(str, data + field->offset, len);
@@ -3697,7 +3716,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
 	return;
 
 out_warning_field:
-	do_warning("%s: field %s not found", __func__, arg->field.name);
+	do_warning_event(event, "%s: field %s not found",
+			 __func__, arg->field.name);
 }
 
 static unsigned long long
@@ -3742,14 +3762,16 @@ process_defined_func(struct trace_seq *s, void *data, int size,
 			trace_seq_terminate(&str);
 			string = malloc(sizeof(*string));
 			if (!string) {
-				do_warning("%s(%d): malloc str", __func__, __LINE__);
+				do_warning_event(event, "%s(%d): malloc str",
+						 __func__, __LINE__);
 				goto out_free;
 			}
 			string->next = strings;
 			string->str = strdup(str.buffer);
 			if (!string->str) {
 				free(string);
-				do_warning("%s(%d): malloc str", __func__, __LINE__);
+				do_warning_event(event, "%s(%d): malloc str",
+						 __func__, __LINE__);
 				goto out_free;
 			}
 			args[i] = (uintptr_t)string->str;
@@ -3761,7 +3783,7 @@ process_defined_func(struct trace_seq *s, void *data, int size,
 			 * Something went totally wrong, this is not
 			 * an input error, something in this code broke.
 			 */
-			do_warning("Unexpected end of arguments\n");
+			do_warning_event(event, "Unexpected end of arguments\n");
 			goto out_free;
 		}
 		farg = farg->next;
@@ -3811,12 +3833,12 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
 	if (!field) {
 		field = pevent_find_field(event, "buf");
 		if (!field) {
-			do_warning("can't find buffer field for binary printk");
+			do_warning_event(event, "can't find buffer field for binary printk");
 			return NULL;
 		}
 		ip_field = pevent_find_field(event, "ip");
 		if (!ip_field) {
-			do_warning("can't find ip field for binary printk");
+			do_warning_event(event, "can't find ip field for binary printk");
 			return NULL;
 		}
 		pevent->bprint_buf_field = field;
@@ -3830,7 +3852,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
 	 */
 	args = alloc_arg();
 	if (!args) {
-		do_warning("%s(%d): not enough memory!", __func__, __LINE__);
+		do_warning_event(event, "%s(%d): not enough memory!",
+				 __func__, __LINE__);
 		return NULL;
 	}
 	arg = args;
@@ -3896,7 +3919,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
 				bptr += vsize;
 				arg = alloc_arg();
 				if (!arg) {
-					do_warning("%s(%d): not enough memory!",
+					do_warning_event(event, "%s(%d): not enough memory!",
 						   __func__, __LINE__);
 					goto out_free;
 				}
@@ -3919,7 +3942,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
 			case 's':
 				arg = alloc_arg();
 				if (!arg) {
-					do_warning("%s(%d): not enough memory!",
+					do_warning_event(event, "%s(%d): not enough memory!",
 						   __func__, __LINE__);
 					goto out_free;
 				}
@@ -3959,7 +3982,7 @@ get_bprint_format(void *data, int size __maybe_unused,
 	if (!field) {
 		field = pevent_find_field(event, "fmt");
 		if (!field) {
-			do_warning("can't find format field for binary printk");
+			do_warning_event(event, "can't find format field for binary printk");
 			return NULL;
 		}
 		pevent->bprint_fmt_field = field;
@@ -4003,8 +4026,8 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
 		arg->field.field =
 			pevent_find_any_field(event, arg->field.name);
 		if (!arg->field.field) {
-			do_warning("%s: field %s not found",
-				   __func__, arg->field.name);
+			do_warning_event(event, "%s: field %s not found",
+					 __func__, arg->field.name);
 			return;
 		}
 	}
@@ -4176,7 +4199,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
 			case '*':
 				/* The argument is the length. */
 				if (!arg) {
-					do_warning("no argument match");
+					do_warning_event(event, "no argument match");
 					event->flags |= EVENT_FL_FAILED;
 					goto out_failed;
 				}
@@ -4213,7 +4236,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
 			case 'X':
 			case 'u':
 				if (!arg) {
-					do_warning("no argument match");
+					do_warning_event(event, "no argument match");
 					event->flags |= EVENT_FL_FAILED;
 					goto out_failed;
 				}
@@ -4223,7 +4246,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
 
 				/* should never happen */
 				if (len > 31) {
-					do_warning("bad format!");
+					do_warning_event(event, "bad format!");
 					event->flags |= EVENT_FL_FAILED;
 					len = 31;
 				}
@@ -4290,13 +4313,13 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
 						trace_seq_printf(s, format, (long long)val);
 					break;
 				default:
-					do_warning("bad count (%d)", ls);
+					do_warning_event(event, "bad count (%d)", ls);
 					event->flags |= EVENT_FL_FAILED;
 				}
 				break;
 			case 's':
 				if (!arg) {
-					do_warning("no matching argument");
+					do_warning_event(event, "no matching argument");
 					event->flags |= EVENT_FL_FAILED;
 					goto out_failed;
 				}
@@ -4306,7 +4329,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
 
 				/* should never happen */
 				if (len > 31) {
-					do_warning("bad format!");
+					do_warning_event(event, "bad format!");
 					event->flags |= EVENT_FL_FAILED;
 					len = 31;
 				}
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
index 7065cd6fbdfc..4464ad770d51 100644
--- a/tools/perf/Documentation/perf-bench.txt
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -48,6 +48,12 @@ SUBSYSTEM
 'mem'::
 	Memory access performance.
 
+'numa'::
+	NUMA scheduling and MM benchmarks.
+
+'futex'::
+	Futex stressing benchmarks.
+
 'all'::
 	All benchmark subsystems.
 
@@ -187,6 +193,22 @@ Show only the result with page faults before memset.
 --no-prefault::
 Show only the result without page faults before memset.
 
+SUITES FOR 'numa'
+~~~~~~~~~~~~~~~~~
+*mem*::
+Suite for evaluating NUMA workloads.
+
+SUITES FOR 'futex'
+~~~~~~~~~~~~~~~~~~
+*hash*::
+Suite for evaluating hash tables.
+
+*wake*::
+Suite for evaluating wake calls.
+
+*requeue*::
+Suite for evaluating requeue calls.
+
 SEE ALSO
 --------
 linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index cdd8d4946dba..976b00c6cdb1 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -87,7 +87,6 @@ Default is to monitor all CPUS.
 --realtime=<priority>::
 	Collect data with this RT SCHED_FIFO priority.
 
--s <symbol>::
 --sym-annotate=<symbol>::
         Annotate this symbol.
 
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 50d875d970c4..e96923310d57 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -192,13 +192,13 @@ endif
 export PERL_PATH
 
 $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
-	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
+	$(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
 
 $(OUTPUT)util/parse-events-bison.c: util/parse-events.y
 	$(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
 
 $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
-	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
+	$(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
 
 $(OUTPUT)util/pmu-bison.c: util/pmu.y
 	$(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 97d86d828190..ebfa163b80b5 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -1593,6 +1593,10 @@ static void init_params(struct params *p, const char *name, int argc, const char
 	p->data_rand_walk		= true;
 	p->nr_loops			= -1;
 	p->init_random			= true;
+	p->mb_global_str		= "1";
+	p->nr_proc			= 1;
+	p->nr_threads			= 1;
+	p->nr_secs			= 5;
 	p->run_all			= argc == 1;
 }
 
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8b0e1c9234d9..65a151e36067 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -174,13 +174,20 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
 
 static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
 {
-	memset(evsel->priv, 0, sizeof(struct perf_stat));
+	int i;
+	struct perf_stat *ps = evsel->priv;
+
+	for (i = 0; i < 3; i++)
+		init_stats(&ps->res_stats[i]);
 }
 
 static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
 {
 	evsel->priv = zalloc(sizeof(struct perf_stat));
-	return evsel->priv == NULL ? -ENOMEM : 0;
+	if (evsel == NULL)
+		return -ENOMEM;
+	perf_evsel__reset_stat_priv(evsel);
+	return 0;
 }
 
 static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index c23418225c2c..ee21fa95ebcf 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -65,10 +65,9 @@ ifndef NO_LIBELF
   ifdef LIBDW_DIR
     LIBDW_CFLAGS  := -I$(LIBDW_DIR)/include
     LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
-
-    FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
-    FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
   endif
+  FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
+  FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
 endif
 
 # include ARCH specific config
@@ -278,6 +277,8 @@ else
       NO_LIBELF := 1
       NO_DWARF := 1
       NO_DEMANGLE := 1
+      NO_LIBUNWIND := 1
+      NO_LIBDW_DWARF_UNWIND := 1
     else
       msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
     endif
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 653a8fe2db95..bfb186900ac0 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -504,6 +504,7 @@ static int do_test_code_reading(bool try_kcore)
 		if (ret < 0) {
 			if (!excl_kernel) {
 				excl_kernel = true;
+				perf_evlist__set_maps(evlist, NULL, NULL);
 				perf_evlist__delete(evlist);
 				evlist = NULL;
 				continue;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index df0238654698..562762117639 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -985,7 +985,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
 
 #if _ELFUTILS_PREREQ(0, 142)
 	/* Get the call frame information from this dwarf */
-	pf->cfi = dwarf_getcfi(dbg->dbg);
+	pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg));
 #endif
 
 	off = 0;
@@ -1441,13 +1441,15 @@ static int line_range_walk_cb(const char *fname, int lineno,
 			      void *data)
 {
 	struct line_finder *lf = data;
+	int err;
 
 	if ((strtailcmp(fname, lf->fname) != 0) ||
 	    (lf->lno_s > lineno || lf->lno_e < lineno))
 		return 0;
 
-	if (line_range_add_line(fname, lineno, lf->lr) < 0)
-		return -EINVAL;
+	err = line_range_add_line(fname, lineno, lf->lr);
+	if (err < 0 && err != -EEXIST)
+		return err;
 
 	return 0;
 }
@@ -1473,14 +1475,15 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
 
 static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
 {
-	find_line_range_by_line(in_die, data);
+	int ret = find_line_range_by_line(in_die, data);
 
 	/*
 	 * We have to check all instances of inlined function, because
 	 * some execution paths can be optimized out depends on the
-	 * function argument of instances
+	 * function argument of instances. However, if an error occurs,
+	 * it should be handled by the caller.
 	 */
-	return 0;
+	return ret < 0 ? ret : 0;
 }
 
 /* Search function definition from function name */
diff --git a/usr/Kconfig b/usr/Kconfig
index 642f503d3e9f..2d4c77eecf2e 100644
--- a/usr/Kconfig
+++ b/usr/Kconfig
@@ -98,80 +98,3 @@ config RD_LZ4
 	help
 	  Support loading of a LZ4 encoded initial ramdisk or cpio buffer
 	  If unsure, say N.
-
-choice
-	prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!=""
-	help
-	  This option decides by which algorithm the builtin initramfs
-	  will be compressed.  Several compression algorithms are
-	  available, which differ in efficiency, compression and
-	  decompression speed.  Compression speed is only relevant
-	  when building a kernel.  Decompression speed is relevant at
-	  each boot.
-
-	  If you have any problems with bzip2 or LZMA compressed
-	  initramfs, mail me (Alain Knaff) <alain@knaff.lu>.
-
-	  High compression options are mostly useful for users who are
-	  low on RAM, since it reduces the memory consumption during
-	  boot.
-
-	  If in doubt, select 'gzip'
-
-config INITRAMFS_COMPRESSION_NONE
-	bool "None"
-	help
-	  Do not compress the built-in initramfs at all. This may
-	  sound wasteful in space, but, you should be aware that the
-	  built-in initramfs will be compressed at a later stage
-	  anyways along with the rest of the kernel, on those
-	  architectures that support this.
-	  However, not compressing the initramfs may lead to slightly
-	  higher memory consumption during a short time at boot, while
-	  both the cpio image and the unpacked filesystem image will
-	  be present in memory simultaneously
-
-config INITRAMFS_COMPRESSION_GZIP
-	bool "Gzip"
-	depends on RD_GZIP
-	help
-	  The old and tried gzip compression. It provides a good balance
-	  between compression ratio and decompression speed.
-
-config INITRAMFS_COMPRESSION_BZIP2
-	bool "Bzip2"
-	depends on RD_BZIP2
-	help
-	  Its compression ratio and speed is intermediate.
-	  Decompression speed is slowest among the choices.  The initramfs
-	  size is about 10% smaller with bzip2, in comparison to gzip.
-	  Bzip2 uses a large amount of memory. For modern kernels you
-	  will need at least 8MB RAM or more for booting.
-
-config INITRAMFS_COMPRESSION_LZMA
-	bool "LZMA"
-	depends on RD_LZMA
-	help
-	  This algorithm's compression ratio is best.
-	  Decompression speed is between the other choices.
-	  Compression is slowest. The initramfs size is about 33%
-	  smaller with LZMA in comparison to gzip.
-
-config INITRAMFS_COMPRESSION_XZ
-	bool "XZ"
-	depends on RD_XZ
-	help
-	  XZ uses the LZMA2 algorithm. The initramfs size is about 30%
-	  smaller with XZ in comparison to gzip. Decompression speed
-	  is better than that of bzip2 but worse than gzip and LZO.
-	  Compression is slow.
-
-config INITRAMFS_COMPRESSION_LZO
-	bool "LZO"
-	depends on RD_LZO
-	help
-	  Its compression ratio is the poorest among the choices. The kernel
-	  size is about 10% bigger than gzip; however its speed
-	  (both compression and decompression) is the fastest.
-
-endchoice
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index d4b601547f1f..2458a1dc2ba9 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -97,6 +97,14 @@ static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic)
 	bitmap_zero(ioapic->rtc_status.dest_map, KVM_MAX_VCPUS);
 }
 
+static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
+
+static void rtc_status_pending_eoi_check_valid(struct kvm_ioapic *ioapic)
+{
+	if (WARN_ON(ioapic->rtc_status.pending_eoi < 0))
+		kvm_rtc_eoi_tracking_restore_all(ioapic);
+}
+
 static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
 {
 	bool new_val, old_val;
@@ -120,9 +128,8 @@ static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
 	} else {
 		__clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map);
 		ioapic->rtc_status.pending_eoi--;
+		rtc_status_pending_eoi_check_valid(ioapic);
 	}
-
-	WARN_ON(ioapic->rtc_status.pending_eoi < 0);
 }
 
 void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
@@ -149,10 +156,10 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic)
 
 static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu)
 {
-	if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map))
+	if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map)) {
 		--ioapic->rtc_status.pending_eoi;
-
-	WARN_ON(ioapic->rtc_status.pending_eoi < 0);
+		rtc_status_pending_eoi_check_valid(ioapic);
+	}
 }
 
 static bool rtc_irq_check_coalesced(struct kvm_ioapic *ioapic)
@@ -353,10 +360,16 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
 		ioapic->irr &= ~(1 << irq);
 
 	if (irq == RTC_GSI && line_status) {
+		/*
+		 * pending_eoi cannot ever become negative (see
+		 * rtc_status_pending_eoi_check_valid) and the caller
+		 * ensures that it is only called if it is >= zero, namely
+		 * if rtc_irq_check_coalesced returns false).
+		 */
 		BUG_ON(ioapic->rtc_status.pending_eoi != 0);
 		ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
 				ioapic->rtc_status.dest_map);
-		ioapic->rtc_status.pending_eoi = ret;
+		ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret);
 	} else
 		ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL);
 
